tcl8.6.5/0000755000175000017500000000000012665173607011572 5ustar sergeisergeitcl8.6.5/ChangeLog.20040000644000175000017500000054201611555560472013735 0ustar sergeisergei2004-12-29 Jeff Hobbs * win/tcl.m4, win/configure: update MSVC CFLAGS_OPT to -O2, remove -Gs (included in -O2) and -GD (outdated). Use "link -lib" instead of "lib" binary and remove -YX for MSVC7 portability. Add -fomit-frame-pointer for gcc OPT compiles. [Bug 1092952, 1091967] Align LIBS_GUI with Tk head needs. 2004-12-29 Kevin B. Kenny * generic/tclDate.c: Regen * generic/tclGetDate.y (TclDatelex): Fixed a problem where a four-digit group with >=2 leading zeroes appeared to be a two-digit group, leading to misinterpreting the time 0012 as 1200. [Bug 1090413] * library/clock.tcl: Added code to interpret correctly months outside the range 01-12 as reduced modulo 12 with a corresponding adjustment to the year. [Bug 1092789] * tests/clock.test: Added regression test cases for the above two bugs * unix/Makefile.in: Added --no-lines to the 'bison' command line to * win/Makefile.in: help constrain the number of diffs in a cvs checkin 2004-12-24 Miguel Sofer * generic/tclCompile.c: * generic/tclCompile.h: * generic/tclExecute.c: * generic/tclInt.h: * generic/tclLiteral.c: * generic/tclProc.c: Avoid sharing cmdName literals accross namespaces, and generalise usage of the TclRegisterNewLiteral macro. [Patch 1090905] 2004-12-20 Miguel Sofer * generic/tclCompile.c: moved TclInitCompiledLocals to tclProc.c * generic/tclProc.c: new static InitCompiledLocals to allow for a single pass over the proc's arguments at proc load time (instead of two as previously). TclObjInterpProc() now allocates the compiledLocals on the tcl execution stack, using the new TclStackAlloc/Free functions. 2004-12-16 Donal K. Fellows * generic/tclInterp.c (Tcl_LimitSetTime, TimeLimitCallback): (TclLimitRemoveAllHandlers, TclInitLimitSupport): Set a timer event to trigger when the time limit runs out. All the time limit actually does is check to see if the time limit has been exceeded, but this is enough to fix [Bug 1085023]. * generic/tclInt.h (struct Interp): Added a field to hold the token for the timer event handler associated with the current time limit. * generic/tclEvent.c (Tcl_UpdateObjCmd, Tcl_VwaitObjCmd): Add error message when limit exceeded. * tests/interp.test (interp-34.[89]): Check that time limits handle the two cases reported in [Bug 1085023] * generic/tclTimer.c (TclCreateAbsoluteTimerHandler): New internal function that allows setting a timer handler that will be triggered at (or after) a specific time instead of at some number of milliseconds in the future. This is a candidate for future exposure via a TIP. 2004-12-15 Miguel Sofer * generic/tclBasic.c: * generic/tclExecute.c: * generic/tclInt.decls: * generic/tclIntDecls.h: * generic/tclNamesp.c: * generic/tclProc.c: * generic/tclStubInit.c: * generic/tclTest.c: Added two new functions to allocate memory from the execution stack (TclStackAlloc, TclStackFree). Added functions TclPushStackFrame and TclPopStackFrame that do the work of Tcl_PushCallFrame and Tcl_PopCallFrame, but using frames allocated in the execution stack - i.e., heap instead of C-stack. The core uses these two new functions exclusively; the old ones remain for backwards compat, as at least two popular extensions (itcl, xotcl) are known to use them. 2004-12-14 Miguel Sofer * generic/tclCmdIL.c: * generic/tclInt.h: * generic/tclProc.c: * generic/tclVar.c: changing the isProcCallFrame field of the CallFrame struct from a 0/1 field to flags. Should be perfectly backwards compatible. 2004-12-14 Don Porter * unix/configure.in: Added special processing to remove "$U" from libraries in the LIBOBJS value. This is an auto-make-ism we need to avoid. [Bug 1081541] * unix/configure: autoconf-2.57 2004-12-13 Don Porter * generic/tcl.h: Restored extern "C" guards so that C++ code sees function pointer typedef linkage consistent with earlier Tcl releases. [Bug 1082349] * generic/tclEncoding.c: Plugged some memory leaks. Thanks to Rolf Ade * generic/tclUtil.c: for reports and testing [Bug 1083082] 2004-12-13 Kevin B. Kenny * doc/clock.n: Clarify that the [clock scan] command does not accept the full range of ISO8601 point-in-time formats. [Bug 1075433] 2004-12-12 Miguel Sofer * generic/tclVar.c (TclArrayObjCmd - ARRAY_NAMES): leaking an object [Bug 1084111] - thanks to Rolf Ade. 2004-12-12 Miguel Sofer * generic/tclObj.c (TclSetCmdNameObj): special handling for fully qualified command names (as in fix [Patch 456668]). 2004-12-11 Miguel Sofer * generic/tclInt.h: * generic/tclNamesp.c: converting the static function GetNamespaceFromObj() to MODULE_SCOPE TclGetNamespaceFromObj(). 2004-12-10 Donal K. Fellows * tools/tcl.wse.in, unix/tcl.spec, win/README.binary, README: * win/configure.in, unix/configure.in, generic/tcl.h: Bumped version number to 8.5a3 to distinguish HEAD of CVS development from the recent 8.5a2 release. 2004-12-10 Miguel Sofer * generic/tclCompile.c (TclInitCompiledLocals): * generic/tclCompile.h: * generic/tclInt.h: * generic/tclProc.c (TclObjInterpProc, TclCreateProc): optimised loops that initialise a proc's arguments and compiled local variables, removing tests from inner loops. 2004-12-10 Donal K. Fellows * generic/tclInt.h: Move ensemble API decls here from tclNamesp.c 2004-12-09 Donal K. Fellows * generic/tclNamesp.c (TclMakeEnsembleCmd, TclSetEnsemble*) (TclSetEnsemble*, TclFindEnsemble): Build an internal API for creating and manipulating ensembles; they can be deleted using the normal command-deletion API. * doc/Async.3: Reword for better grammar, better nroff and get the flag name right. (Reported by David Welton.) 2004-12-07 Don Porter * tests/unixInit.test (2.1-4): Added constraints so that when a value of TCL_LIBRARY is required for process initialization, we skip the tests that mess with that value. 2004-12-07 Donal K. Fellows *** 8.5a2 TAGGED FOR RELEASE *** * unix/Makefile.in: add library/{tzdata,msgs} to dist target (kbk) * doc/foreach.n: Adjust tabs to be friendlier to some HTML converters. [Bug 1078760] 2004-12-06 Jeff Hobbs * unix/tclUnixNotfy.c (NotifierThreadProc): init numFdBits [Bug 1079286] * doc/error.n, doc/SaveResult.3, doc/Thread.3: minor nroff typos 2004-12-06 Don Porter * tests/safe.test: Trim auto_path to improve performance [1080039] * tests/msgcat.test: makeFile/removeFile cleanup [1079117] 2004-12-04 Don Porter * generic/tclEncoding.c: Different fix for [Bug 1077005]. * generic/tclEvent.c: Broke apart TclpSetInitialEncodings() on * generic/tclInt.h: Windows into TclpSetInterfaces(), that is * unix/tclUnixInit.c: fundamentally essential, and the initialization * win/tclWinInit.c: of the system encoding, which is not. Made the TclpSetInterfaces call part of TclInitSubsystems so it cannot be overlooked. 2004-12-03 Jeff Hobbs * changes: updated for 8.5a2 release 2004-12-02 Don Porter * generic/tclUtil.c (TclSetProcessGlobalValue): Handle the case where a ProcessGlobalValue might be assigned to itself. * generic/tclEncoding.c (MakeFileMap): Correct refcounting errors managing values returned by TclPathPart (with refCount of 1!) that led to a memory leak. [Bug 1077474]. 2004-12-02 Vince Darley * generic/tclPathObj.c: fix and new tests for [Bug 1074671] to ensure * tests/fileSystem.test: tilde paths are not returned specially by 'glob'. 2004-12-02 Kevin B. Kenny * win/Makefile.in: Added a 'sed' in the setting of ROOT_DIR_NATIVE to compensate for a bug in cygpath (at least version 1.36) that leaves a trailing backslash on the end of the converted path. 2004-12-02 Donal K. Fellows * generic/tclInterp.c (Alias,Target,Master): Rewrote these so that the aliases that refer to an interpreter are stored in a list and not a hashtable (which was only ever a convenience, and forced the use of a global mutex to generate keys!) [FRQ 1077210] * generic/tclNamesp.c (numNsCreated): Moved into thread-local storage to remove a global mutex. [FRQ 1077210] 2004-12-01 Don Porter * generic/tclUtil.c (TclGetProcessGlobalValue): Narrowed the scope of mutex locks. * generic/tclUtil.c: Updated Tcl_GetNameOfExecutable() to * generic/tclEncoding.c: make use of a ProcessGlobalValue for * generic/tclEvent.c: storing the executable name. Added internal routines Tcl(Get|Set)ObjNameOfExecutable() to access that storage in Tcl_Obj, rather than string format. * unix/tclUnixFile.c: Rewrote TclpFindExecutable() to use * win/tclWinFile.c: TclSetObjNameOfExecutable to store the executable name it computes. * generic/tclInt.h: Added internal stub entries for * generic/tclInt.decls: TclpFindExecutable and Tcl(Get|Set)ObjNameOfExecutable. * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclCmdIL.c: Retrieve executable name in Tcl_Obj form * win/tclWinPipe.c: instead of string form. * unix/tclUnixTest.c: Update [testfindexecutable] command to use new internal interfaces. * generic/tclEncoding.c: Moved TclpSetInitialEncodings() call from Tcl_FindExecutable() into TclInitEncodingSubsystem(). This is important on Windows where it establishes whether the "ascii" or "unicode" set of system routines will be used, and that needs to be done earlier to support filesystem operations. [Bug 1077005] 2004-12-01 Donal K. Fellows * tests/winDde.test: Rewritten to use tcltest2 features more thoroughly (reducing the [catch] count!) and fix the problem with winDde-6.1 being out of synch with the implementation. 2004-11-30 Don Porter * library/init.tcl ([unknown]): Restored the save/restore of the variables ::errorCode and ::errorInfo. This is needed when the [::bgerror] command is auto-loaded (as it is by Tk). Patch 976520 reworks several of the details involved with startup/initialization of the Tcl library, focused on the activities of Tcl_FindExecutable(). * generic/tclIO.c: Removed bogus claim in comment that encoding "iso8859-1" is "built-in" to Tcl. * generic/tclInt.h: Created a new struct ProcessGlobalValue, * generic/tclUtil.c: routines Tcl(Get|Set)ProcessGlobalValue, and function type TclInitProcessGlobalValueProc. Together, these take care of the housekeeping for "values" (things that can be held in a Tcl_Obj) that are global across a whole process. That is, they are shared among multiple threads, and epoch and mutex protection must govern the validity of cached copies maintained in each thread. * generic/tclNotify.c: Modified TclInitNotifier() to tolerate being called multiple times in the same thread. * generic/tclEvent.c: Dropped the unused argv0 argument to TclInitSubsystems(). Removed machinery to unsure only one TclInitNotifier() call per thread, now that that is safe. Converted Tcl(Get|Set)LibraryPath to use a ProcessGlobalValue, and moved them to tclEncoding.c. * generic/tclBasic.c: Updated caller. * generic/tclInt.h: TclpFindExecutable now returns void. * unix/tclUnixFile.c: * win/tclWinFile.c: * win/tclWinPipe.c: * generic/tclEncoding.c: Built new encoding search initialization on a foundation of ProcessGlobalValues, exposing new routines Tcl(Get|Set)EncodingSearchPath. A cache of a map from encoding name to directory pathname keeps track of where encodings are available for loading. Tcl_FindExecutable greatly simplified into just three function calls. The "library path" is now misnamed, as its only remaining purpose is as a foundation for the default encoding search path. * generic/tclInterp.c: Inlined the initScript that is evaluated by Tcl_Init(). Added verification after initScript evaluation that Tcl can find its installed *.enc files, and that it has initialized [encoding system] in agreement with what the environment expects. [tclInit] no longer driven by the value of $::tcl_libPath; it largely constructs its own search path now, rather than attempt to share one with the encoding system. * unix/tclUnixInit.c: TclpSetInitialEncodings factored so that a new * win/tclWinInit.c: routine TclpGetEncodingNameFromEnvironment can reveal that Tcl thinks the [encoding system] should be, even when an incomplete encoding search path, or a missing *.enc file won't allow that initialization to succeed. TclpInitLibraryPath reworked as an initializer of a ProcessGlobalValue. * unix/tclUnixTest.c: Update implementations of [testfindexecutable], [testgetdefenc], and [testsetdefenc]. * tests/unixInit.test: Corrected tests to operate properly even when a value of TCL_LIBRARY is required to find encodings. * generic/tclInt.decls: New internal stubs: TclGetEncodingSearchPath, TclSetEncodingSearchPath, TclpGetEncodingNameFromEnvironment. These are candidates for public exposure by future TIPs. * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclTest.c: Updated [testencoding] to use * tests/encoding.test: Tcl(Get|Set)EncodingSearchPath. Updated tests. 2004-11-30 Kevin B. Kenny * library/clock.tcl: Corrected the regular expressions that match a time zone to allow for time zones specified as +HH or -HH. * tests/clock.test: Added regression test case for the above issue. Thanks to Rolf Ade for reporting this issue [http://wiki.tcl.tk/13094] * win/tclWinDde.c (Tcl_DdeObjCmd): Corrected a typo that caused a compilation failure on VC++. 2004-11-29 Andreas Kupries * win/Makefile.in (install-libraries): Brought entry '2004-10-26 Don Porter (Tcl Modules)' into the windows world, actually the win/configure buildsystem. The other windows buildsystems (.vc, .bc) still have to be updated as well. 2004-11-26 Andreas Kupries * win/tclWinDde.c (ExecuteRemoteObject): Removed bogus semicolon found at the end of the header for the function definition, terminating it early and preventing a compile. This is likely a fix for '2004-11-25 Donal'. I have to conclude that it is also unknown if the other changes to this file actually pass the testsuite. Running testsuite ... They don't. winDde-6.1 fails. This is only a message discrepance, i.e. not too bad. Leaving resolution of that to Pat and Donal. 2004-11-26 Don Porter * library/auto.tcl (tcl_findLibrary): Made sure the uniquifying operations on the search path does not also normalize. [Bug 1072136] 2004-11-26 Donal K. Fellows * unix/configure.in: Simplify the code to check for correctness of strstr, strtoul and strtod. * unix/tcl.m4 (SC_TCL_CHECK_BROKEN_FUNC): Split a complex stanza out of configure.in into its own function. Also force it to do the right thing with cacheing of results of AC_TRY_RUN to deal with issue raised in [Patch 1073524] * doc/foreach.n: Added simple example. [FRQ 1073334] 2004-11-25 Donal K. Fellows * generic/tclProc.c (TclObjInterpProc): Make it so that only * generic/tclIndexObj.c (Tcl_WrongNumArgs): [proc] instances do * tests/indexObj.test (indexObj-5.7): quoting of their first arguments, so keeping [Bug 942757] fixed and making [Bug 1066837] be fixed as well. Done with a load of #ifdef-ery because this hack is so ugly nobody should keep it around once Itcl's fixed. 2004-11-25 Reinhard Max * tests/tcltest.test: The order in which [glob] returns the file names is undefined, so tests should not depend on it. 2004-11-25 Zoran Vasiljevic * doc/Thread.3: * doc/Notifier.3: Added changes from the core-8-4-branch 2004-11-25 Donal K. Fellows * doc/dde.n: Synchronized the documentation of the commands with the header of the docs and what the package actually does. Thanks to Andreas Kupries for spotting this. * win/tclWinDde.c (Tcl_DdeObjCmd): Much cleanup of argument parsing code. 2004-11-24 David Gravereaux * generic/tclPort.h: Relative include of tclWinPort.h returned as it was requiring me set -I$(tcl_root)/win for my extensions that need to include tclInt.h and doesn't appear to serve any purpose for windows builds. 2004-11-24 Kevin B. Kenny * unix/tcl.m4 (SC_ENABLE_THREADS): Corrected bad check for 3-argument readdir_r [Bug 1001325]. * unix/configure: Regenerated. * unix/tclUnixNotfy.c: Corrected all uses of 'select' to manage their masks using the FD_CLR, FD_ISSET, FD_SET, and FD_ZERO macros rather than bit-whacking that failed under Solaris-Sparc-64. [Bug 1071807] * win/tclWinInit.c (TclpInitLibraryPath): Removed unused vars 'pathc' and 'pathv' that caused compilation problems on VC++ with --enable-symbols. 2004-11-24 Don Porter * unix/tcl.m4 (SC_ENABLE_THREADS): Corrected failure to determine the number of arguments for readdir_r on SunOS systems. [Bug 1071701] * unix/configure: autoconf-2.57 * generic/tclCmdIL.c (InfoVarsCmd): Corrected segfault in new * tests/info.test (info-19.6): trivial matching branch [Bug 1072654] 2004-11-24 Donal K. Fellows * tools/man2html.tcl, tools/man2html1.tcl: Update to use Tcl 8.4. * tools/man2html2.tcl: Fix broken .SS handling. 2004-11-23 Donal K. Fellows * unix/Makefile.in: Add (commented-out) code to integrate tclConfig.h into the dependency tree and 'make distclean'. [Bug 1068171] * generic/tclResult.c (Tcl_AppendResultVA): Remove call to Tcl_GetStringResult to speed up repeated calls to Tcl_AppendResult with the side effect that code that wants to access interp->result should always call Tcl_GetStringResult first. See [Patch 1041072] discussion for more details. 2004-11-22 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_TCL_64BIT_FLAGS): Define HAVE_TYPE_OFF64_T only when off64_t, open64(), and lseek64() are defined. IRIX 5.3 is known to not include an open64 function. [Bug 1030465] 2004-11-22 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_ENABLE_THREADS): Check for a 2 argument version of readdir_r that is known to exists under IRIX 5.3. * unix/tclUnixThrd.c (TclpReaddir): Use either 2 arg or 3 arg version of readdir_r. [Bug 1001325] 2004-11-22 Don Porter * unix/tclUnixInit.c (TclpInitLibraryPath): Purged dead code that used * win/tclWinInit.c (TclpInitLibraryPath): to extend the "library path". Search path construction for init.tcl is now done within the [tclInit] proc. * generic/tclInterp.c: Restored several directories to the search * tests/unixInit.test: path used to locate init.tcl within [tclInit]. This change does not restore any directories to the encoding search path, so should still avoid the price of an unreasonably large number of filesystem accesses during encoding initialization at startup [Bug 976438] 2004-11-22 Vince Darley * generic/tclPathObj.c: fix and new test for [Bug 1043129] in the * tests/fileSystem.test: treatment of backslashes in file join on Windows. 2004-11-21 Don Porter * doc/AddErrInfo.3: Typo corrections (Thanks Daniel South). * doc/interp.n: 2004-11-19 Don Porter * doc/AddErrInfo.3: Docs for Tcl_(Get|Set)ReturnOptions. [TIP 227] * doc/AddErrInfo.3: * doc/Async.3: Documentation updates to replace references * doc/BackgdErr.3: to global variable ::errorInfo and ::errorCode * doc/SaveResult.3: and to the ::bgerror command with references * doc/after.n: to their preferred replacements, the * doc/bgerror.n: -errorinfo and -errorcode return options, * doc/error.n: the Tcl_*InterpState routines, and the * doc/exec.n: [interp bgerror] command. * doc/exit.n: * doc/fileevent.n: * doc/interp.n: * doc/return.n: * doc/tclvars.n: * doc/update.n: * tests/unixInit.test: Removed "knownBug" constraints to prompt bug fixing before 8.5a2 release. 2004-11-19 Daniel Steffen * macosx/Makefile: * unix/configure.in: * unix/tclUnixInit.c (MacOSXGetLibraryPath): changed detection of tcl framework build when determining tclLibPath from overloaded TCL_LIBRARY to configuration define TCL_FRAMEWORK. [Bug 1068088] * unix/configure: autoconf-2.57 * unix/tclConfig.h.in: autoheader-2.57 2004-11-18 Don Porter * doc/SaveResult.3: Documentation for Tcl_*InterpState (TIP 226). * generic/tclEvent.c (HandleBgErrors): Simplified program flow. * tests/basic.test: Updated functional (not testing) uses of * tests/io.test: [bgerror] to make use of [interp bgerror]. * tests/socket.test: * tests/timer.test: * tests/interp.test (interp-36.*): [interp bgerror] tests. * generic/tclInterp.c: Corrected [interp bgerror] error messages. 2004-11-18 Reinhard Max * unix/tcl.m4 (SC_CONFIG_MANPAGES): Applied an improved version of * unix/configure.in: [Patch 996085], that introduces * unix/Makefile.in: --enable-man-suffix. * unix/installManPage: added * unix/mkLinks.tcl: removed * unix/mkLinks: removed * unix/configure: generated * unix/Makefile.in: Don't install tclConfig.h . 2004-11-17 Don Porter * unix/configure.in: The change below reveals that the public data type Tcl_StatBuf relies on config information. For now, disabled the use of the tclConfig.h file until its full impact on Tcl's interface can be assessed. * unix/configure: autoconf-2.57 * generic/tcl.h: Moved the #include "tclConfig.h" out of * generic/tclInt.h: tcl.h. The config settings are not part of * generic/tclPort.: the public interface, and having it there breaks compiled against uninstalled Tcl and extensions using autoconf-2.5*. 2004-11-16 Jeff Hobbs * unix/tclUnixChan.c (TtySetOptionProc): fixed crash configuring -ttycontrol on a channel. [Bug 1067708] 2004-11-16 Don Porter * generic/tclIOUtil.c (TclFSEpochOk): There were two code paths via which the thread copy of filesystemEpoch could be synched with the master copy, but only one kept the filesystem list cache up to date. Fix routes everything through a single code path. [Bug 1035775]. 2004-11-16 Donal K. Fellows * unix/tcl.m4 (SC_CONFIG_CFLAGS): Stop architecture flags to 'ld' from getting lost when [load] is disabled. [Bug 1016796] 2004-11-16 Daniel Steffen * generic/tcl.h: * unix/configure.in: changed HAVE_CONFIG_H to HAVE_TCL_CONFIG_H. * unix/configure: autoconf-2.57 2004-11-15 Don Porter * generic/tclInt.h: Added comment warning that the old ERR_IN_PROGRESS and ERROR_CODE_SET flag values should not be re-used for the sake of those extensions that have accessed them. * generic/tclCmdMZ.c (Tcl_TraceObjCmd): Fixed Bug 1065378 which failed * tests/trace.test (trace-33.1): to permit a variable trace created with [trace variable] to be destroyed with [trace remove]. Thanks to Keith Vetter for the report. 2004-11-15 Donal K. Fellows * doc/tclvars.n: Added section to documentation on global variables that are specific to tclsh and wish. [Patch 1065732] 2004-11-12 Jeff Hobbs * generic/tclEncoding.c (TableFromUtfProc): correct crash condition when TCL_UTF_MAX == 6. [Bug 1004065] 2004-11-12 Donal K. Fellows * doc/interp.n: Basic documentation of the TIP#221 API. 2004-11-12 Don Porter TIP #221 IMPLEMENTATION * generic/tclBasic.c: Define [::tcl::Bgerror] in new interps. * generic/tclEvent.c: Update Tcl_BackgroundError to make use of the registered [interp bgerror] command. * generic/tclInterp.c: New [interp bgerror] subcommand. * tests/interp.test: syntax tests updated. TIP #226 IMPLEMENTATION * generic/tcl.decls: Stubs for Tcl_(Save|Restore|Discard)InterpState * generic/tcl.h: New public opaque type, Tcl_InterpState. * generic/tclInt.h: Drop old private declarations. Add Tcl(Get|Set)BgErrorHandler * generic/tclResult.c: Tcl_*InterpState implementations. * generic/tclDictObj.c: Update callers. * generic/tclIOGT.c: * generic/tclTrace.c: TIP #227 IMPLEMENTATION * generic/tcl.decls: Stubs for Tcl_(Get|Set)ReturnOptions. * generic/tclInt.h: Drop old private declarations. * generic/tclResult.c: Tcl_*ReturnOptions implementations. * generic/tclCmdAH.c: Update callers. * generic/tclMain.c: * generic/tclDecls.h: make genstubs * generic/tclStubInit.c: * unix/tclAppInit.c: Removed tclConfig.h #include, now that tcl.h takes care of it for us. * generic/tclInt.h: Moved verification of ptrdiff_t typedef from * generic/tclExecute.c: multiple .c files into one common header where * generic/tclVar.c: it is verifiably after tclConfig.h inclusion. 2004-11-12 Daniel Steffen * generic/tcl.h: * generic/tclInt.h: * unix/Makefile.in: include tclConfig.h from tcl.h and install it as a public header. Normalized compiler include path order to -I${BUILD_DIR} -I${UNIX_DIR} -I${GENERIC_DIR}. * unix/dltest/Makefile.in: add ${BUILD_DIR}/.. to include path to pick up tclConfig.h. * unix/tclUnixInit.c: moved check for HAVE_CFBUNDLE define after #include "tclInt.h" to ensure tclConfig.h has been included. 2004-11-12 Reinhard Max * unix/config.h.in: * unix/tclConfig.h.in: renamed * unix/Makefile.in: Completed support for config header, * unix/configure.in: fixed building outside of the unix dir, * unix/tclAppinit.c: and reflected the name change of config.h. * generic/tclInt.h: * unix/configure: generated 2004-11-12 Donal K. Fellows * unix/config.h.in: Allow configure to put all the C #defs into * unix/configure.in: a file (called config.h) so that Unix builds * unix/tcl.m4: now take far fewer lines of scrollback to * unix/Makefile.in: proceed (making it less likely that any errors * generic/tclInt.h: or warnings will get missed). * unix/tclAppInit.c: Part of the TIP#34 upgrades. * unix/tcl.m4, unix/tclUnixPort.h: Check for pthread_attr_get_np in before forcing the use of to make things work on NetBSD 2.0. [Bug 1064882] * doc/binary.n, doc/upvar.n: More minor fixes. 2004-11-12 Daniel Steffen * doc/CrtChannel.3: * doc/Interp.3: * doc/Limit.3: * doc/binary.n: * doc/dict.n: * doc/tm.n: * doc/upvar.n: fixed *roff errors uncovered by running 'make html'. * tools/tcltk-man2html.tcl: added faked support for bullet point lists, i.e. *nroff ".IP \(bu" syntax. 2004-11-11 Daniel Steffen * tests/fCmd.test: * unix/tclUnixFCmd.c (TraverseUnixTree): added option to rewind() the readdir() loop whenever the source hierarchy has been modified by traverseProc (e.g. by deleting files); this is required to ensure complete traversal of the source hierarchy on certain filesystems like HFS+. Added test for failing recursive delete on Mac OS X that was due to this. [Bug 1034337] * generic/tclListObj.c (Tcl_ListObjReplace): use memmove() instead of manual copy loop to shift list elements. Decreases time spent in Tcl_ListObjReplace() from 5.2% to 1.7% of overall runtime of tclbench on a ppc 7455 (i.e. 200% speed increase). [Patch 1064243] * generic/tclHash.c: hoisted some constant pointer dereferences out of loops to eliminate redundant loads that the gcc optimizer didn't deal with. Decreases time spend in Tcl_FindHashEntry() by 10% over a full run of the tcl testuite on a ppc 7455. [Patch 1064243] * tests/fileName.test: * tests/fileSystem.test: * tests/io.test: * tests/msgcat.test: * tests/tcltest.test: * tests/unixInit.test: fixed bugs causing failures when running tests with -tmpdir arg not set to working dir. * macosx/Makefile: corrected path to html help inside framework. Prevent parallel make from building several targets at the same time. * macosx/tclMacOSXFCmd.c (struct fileinfobuf): force struct to be packed to prevent failures when builing with -malign=natural. 2004-11-10 Andreas Kupries * unix/tclUnixChan.c: [Bug 727786]. Exterminated the code marked DEPRECATED. This code has not been used in over a year now, and we have no complaints. 2004-11-08 David Gravereaux * win/tclWinPipe.c: The pipe channel driver now respects the -blocking option when closing is the same way the UNIX side works. This is to avoid a hung shell when exiting due to open pipes that refuse to close in a graceful manner. * doc/open.n: Added a note about -blocking 0 and lack of exit status as it had never been documented. [Bug 947693] ***POTENTIAL INCOMPATIBILITY*** Scripts that use async pipes on windows, must (like the UNIX side) set -blocking to 1 before calling [close] to receive the exit status. 2004-11-07 David Gravereaux * tests/winFile.test: added contraint to winFile-4.0 to prevent it being run on NT4 [Bug 981829] 2004-11-05 Donal K. Fellows * tests/reg.test: Major reorganization so that this file is much easier for a normal Tcl maintainer to comprehend. The test flags are still very cryptic, but they appear to have to be that way. The number of skipped tests has increased, but now the skipped tests have much more meaningful content. * tests/tm.test (genpaths): Add a [file normalize] so we pick up Windows drive letters, etc. [Bug 1053568] 2004-11-04 Don Porter * changes: Updates toward an 8.5a2 release. 2004-11-03 Kevin B. Kenny * library/clock.tcl (FreeScan): Fixed a bug where scanning "Monday" with a base time other than midnight incorrectly carried the base time forward. * test/clock.test (clock-33.{5,5a}): Made the test failure more informative. * tests/clock.test (clock-34.{28,44,45,46}): Removed 'knownBug' constraints from tests that no longer fail. Thanks to Don Porter for reporting these. 2004-11-03 David Gravereaux * generic/tcl.h: Moved the preprocessor logic * generic/tclDecls.h: from tclInt.h of setting the * generic/tclInt.h: TCL_STORAGE_CLASS macro to the * generic/tclIntDecls.h: tcl*Decls.h files now that no * generic/tclIntPlatDecls.h: use of EXTERN is left in tclInt.h. * generic/tclPlatDecls.h: Proto for Tcl_Main moved in tcl.h * win/tclWinPort.h: to prior the inclusion of the Stubs headers as they are now resetting TCL_STORAGE_CLASS. Removed extraineous reset from tclWinPort.h. [Patch 1055668] * generic/tclCompile.h: Removed extrainious reset of TCL_STORAGE_CLASS missed in my last edit. 2004-11-03 Don Porter * library/init.tcl ([unknown]): Corrections to the 2004-10-25 mods to Aunt ??? in [unknown]. Flaws revealed by Itcl test suite, which still apparently relies on this brokenness. Also added comment suggesting the error message that any code using this hack *ought* to receive in reply. * generic/tclTrace.c (TclCallVarTraces): Improved ability to debug * tests/incr-old.test (incr-old-2.6): errors during variable * tests/incr.test (incr-{1,2}.28): traces by preserving the * tests/set.test (set-{2,4}.4): -errorinfo data. * tests/trace.test (trace-33.1): [Bug 527164] 2004-11-02 David Gravereaux * generic/tclInt.h: added a check for #ifdef __cplusplus around the #define of MODULE_SCOPE. About the only time it would be problem is when someone is statically linking to Tcl and accessing internals from a C++ file and has name mangling issues from the lack of "C" after 'extern' [Patch 1055668]. * generic/tclCompile.h: Exchanged use of the EXTERN macro to the new MODULE_SCOPE macro. Lowered exported internals count by 35. [Patch 1055668] * win/tclWinInt.h: * win/tclWinPort.h: exported internals dropped by a count of 14. * generic/tclFileSystem.h: Added use of MODULE_SCOPE on protos. * generic/tclRegexp.h: manipulating TCL_STORAGE_CLASS unnecessary. 2004-11-02 Don Porter * library/tcltest/tcltest.tcl: Corrected some misleading * tests/tcltest.test (tcltest-26.1,2): displays of ::errorInfo and ::errorCode information when the -setup, -body, and/or -cleanup scripts return an unexpected return code. Thanks to Robert Seeger for the fix. [RFE 1017151]. 2004-11-02 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Improved version of the NaN fix from Miguel Sofer. [Bug 761471] 2004-11-02 Kevin Kenny * library/tzdata/America/Cuiaba: Change to DST rules for * library/tzdata/America/Havana: autumn of 2004. [ftp://elsie.nci.nih.gov/pub/tzdata2004g.tar.gz] * tools/tclZIC.tcl: Updated to be compatible with recent changes in library/clock.tcl. 2004-11-02 Vince Darley * win/tclWinFile.c: Simplify TclpUtime to use Tcl_FSGetNativePath, and add comments. 2004-11-02 Donal K. Fellows * generic/tclInt.h: Change uses of EXTERN to MODULE_SCOPE (defined in this file too to be 'extern' if not overridden) as nothing declared in tclInt.h is supposed to be visible outside the Tcl core. If there *is* anything that extensions are actually using, we can open this up later on. [Patch 1055668] * doc/CrtChannel.3 (Tcl_GetChannelMode): Add synopsis. [Bug 1058446] 2004-11-01 Kevin B. Kenny * win/tclWinFile.c (FromCTime, TclpUtime): Replaced a call to the Posix 'utime' function with calls to Windows-API equivalents, to avoid a bug where the VC++ versions misconvert times across a Daylight Saving Time boundary. [Bug 926106] * win/tclWinInt.h (TclWinProcs): * win/tclWin32Dll.c (asciiProcs, unicodeProcs): Removed now-unused reference to 'utime'. * tests/cmdAH.test (cmdAH-24.12): Added test case for the above bug. 2004-11-01 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Make INST_EQ and friends handle NaN correctly in all cases. [Bug 761471] * generic/tclNamesp.c (NamespaceInscopeCmd): Make the error message generation the same as in NamespaceEvalCmd(). (Tcl_Import): Rationalized to use Tcl_EvalObjv(). 2004-10-31 Donal K. Fellows * tests/io.test (io-40.3): Convert umask2 test constraint into a form that most people will be able to satisfy. * tests/cmdAH.test (cmdAH-8.45): Removed broken test constraint. It didn't do what it was intended to do, and it implied the other correct constraint. [Bug 1053908] * generic/tclCmdIL.c (InfoGlobalsCmd): * tests/info.test (info-8.4): Strip leading global-namespace specifiers from the pattern argument. [Bug 1057461] 2004-10-30 Kevin Kenny * generic/clock.c: Replaced WIN32 macro with __WIN32__. [Bug 1054357]. Thanks to David Gravereaux for the patch. * win/tclWinFile.c: Removed a long-standing bug that causes incorrect conversion between file time and UTC time if the file time is recorded in a different Daylight Saving Time status than the current one. [Bug 926106] 2004-10-29 Don Porter * library/tcltest/tcltest.tcl: Correct reaction to errors in the obsolete processCmdLineArgsHook. [Bug 1055673] * library/tcltest/pkgIndex.tcl: Bump to tcltest 2.2.7 * unix/Makefile.in: * tests/all.tcl: Update to use [tcltest::configure]. 2004-10-29 Donal K. Fellows * library/tm.tcl (::tcl::tm::*): Use the core proc engine to generate the wrong-num-args error messages for the path ensemble. Ensembles can now (sometimes) rewrite the error messages of their subcommands so they appear more like the arguments that the user passed to the ensemble. Below is a description of changes involved in doing this. * tests/namespace.test (namespace-50.*): Tests of ensemble subcommand error message rewriting. * generic/tclProc.c (TclObjInterpProc): Make procedures implement their wrong-num-args message using Tcl_WrongNumArgs instead of something baked-at-home. * generic/tclNamesp.c (TclIsEnsemble, NsEnsembleImplementationCmd): Added test of ensemble-hood (available to rest of core) and made ensembles set up the rewriting for Tcl_WrongNumArgs to take advantage of. * generic/tclInt.h (Interp.ensembleRewrite): Extra fields. * generic/tclIndexObj.c (Tcl_WrongNumArgs): Add knowledge of what is going on in ensembles' command rewriting so this command can generate the right error message itself. * generic/tclBasic.c (Tcl_CreateInterp, TclEvalObjvInternal): Added code to initialize (as empty) the rewriting fields and reset them when we leak outside an ensemble implementation. 2004-10-28 Miguel Sofer * generic/tclExecute.c (INST_START_CMD): * tests/execute.test (execute-8.3): fix for execution stack corruption [Bug 1055676]. Credit dgp for detective work and fix. 2004-10-27 Don Porter * tests/socket.test (socket-13.1): Balanced [makeFile] and [removeFile] commands. * tests/clock.test: Correct duplicate test names. * tests/namespace.test: * tests/string.test: * tests/io.test (io-50.4): Use namespace variables. 2004-10-27 David Gravereaux * generic/tclInt.decls: The following 9 functions were moved from * generic/tclInt.h: tclInt.h to the private/int Stubs table for * generic/tclIntDecls.h: use by the test suite. As tclTest.obj is * generic/tclStubInit.c: linked to the shell, these functions need "blessed" status so as to always be exported from the library. Being placed in the Stubs table guarantees this [Bug 1054748]: TclpObjRemoveDirectory, TclpObjCopyDirectory, TclpObjCreateDirectory, TclpObjDeleteFile, TclpObjCopyFile, TclpObjRenameFile, TclpObjStat, TclpObjAccess, TclpOpenFileChannel * tests/registry.test: Fixed test files to load the correct * tests/winDde.test: registry and dde packages by using the info * win/Makefile.in: from makefiles to tell tcltest where to load * win/makefile.vc: them from. This avoids grabbing the wrong package from $auto_path which might be the install point rather than the dev location. Kudos to Jennifer Hom for adding -load and -loadfile to the tcltest package. [Bug 926088] * win/tclWinThrd.c (TclFinalizeLock): release the critical section before deleting it. [Bug 731778] * generic/tcl.h: Removed the file level 'extern "C" {' and the coresponding closing block as it serves no purpose given that all the function prototypes have the proper extern usage already. * unix/tclAppInit.c: When built as tcltest, TclThread_Init was * win/tclAppInit.c: getting called twice. First by Tcltest_Init, then again in Tcl_AppInit. The call from Tcl_AppInit is now removed. 2004-10-27 Andreas Kupries * tests/tm.test: Expanded on the testsuite entered by Donal. * library/tm.tcl: Even found bugs, these have been corrected. 2004-10-26 Kevin Kenny * tests/format.test (format-19.1): Additional regression test for [Bug 868489]. 2004-10-27 Donal K. Fellows * doc/*.n: Many small general documentation fixes. 2004-10-26 David Gravereaux * generic/tclPipe.c (TclCleanupChildren): bad cast of resolvedPid caused PIDs on win95 to go negative. winpipe-4.2 brought this to the surface. Fixed with sprintf in place of TclFormatInt. Thanks to hgiese [Patch 767676] 2004-10-26 Andreas Kupries * library/tm.tcl (::tcl::tm::Defaults): Added a second [file dirname] around the location of the executable. This fixes [Bug 1038705]. Instable of a bogus "foo/bin/lib" we now have the correct "foo/lib" as a base path for modules. 2004-10-26 Don Porter * generic/tclParse.c (Tcl_SubstObj): Fix for failed subst-12.3 test * tests/subst.test (subst-12.3-5): More tests for Bug 1036649. * unix/Makefile.in (install-libraries): Updated the installation of the http, msgcat, and tcltest packages to install as Tcl Modules on Unix systems. Other platform Makefiles still need updating. [Patch 1054370] * tests/basic.test: Added missing constraints. * tests/compile.test: * tests/fileSystem.test: * tests/init.test (init-2.8): Updated to not rely on http package. 2004-10-26 Miguel Sofer * generic/tclInt.h: * generic/tclVar.c: removed more direct references to the VAR flags, replaced with access macros. 2004-10-26 Donal K. Fellows * doc/expr.n: Clarified that non-num/non-bool literals require quoting. [Bug 1027849]. Also listed booleans as acceptable values. 2004-10-26 Kevin B. Kenny * library/clock.tcl (FreeScan): Fixed a bug that caused relative days of the week in free-form [clock scan] to be evaluated in the wrong time zone. * tests/clock.test (clock-31.[456]): Made sure that there isn't an env(TZ) or env(TCL_TZ) lying around that will override the time zone that we're trying to establish with the simulated registry. Both problems reported as [Bug 1054101]. 2004-10-25 Donal K. Fellows * doc/string.n (map): Rewrote to clarify that we don't just map single characters. [Bug 1048005] * doc/info.n (procs): Clarified that the pattern argument may have namespace separators in it. [Bug 1047928] * tests/cmdAH.test (cmdAH-8.45): Simplify in the hope that the reasons for [Bug 1053908] will become clearer. 2004-10-25 Don Porter * generic/tclExecute.c (IllegalExprOperandType,TclExecuteByteCode): Removed several DECACHE_INFO/CACHE_INFO pairs that are no longer needed for protection because routines like Tcl_SetErrorCode() and Tcl_AddErrorInfo() can no longer re-enter bytecode execution. * generic/tclResult.c (TclProcessReturn): Bug fix. Be sure that a missing -errorinfo option when code == TCL_ERROR causes the errorInfo field to get reset. * tests/thread.test (thread-4.4): Test depended on a ::errorInfo value initialized to "". Added code to test to setup that requirement. * library/auto.tcl: Purged Tcl's script library of all * library/clock.tcl: remaining references to global vars * library/init.tcl: ::errorInfo and ::errorCode. * generic/tclMain.c (Tcl_Main): Updated to make use of TclGetReturnOptions instead of ::errorInfo variable. * generic/tclInterp.c (tclInit): Bug fix. Access dict variables with [dict get], not array syntax. 2004-10-25 Donal K. Fellows * tests/tm.test: Rewrote the tests to actually perform syntax checks on the public API. Added a new test (currently failing) to indicate that the test suite is not complete yet. * library/tm.tcl (path): Rewrote to turn this command into an ensemble to make it faster and simpler. 2004-10-24 Miguel Sofer * generic/tclCmdIL.c: * generic/tclExecute.c: * generic/tclInt.h: * generic/tclTrace.c: defined new macros to get/set the flags of variables. The only files that still access the flag values directly are tclCompCmds.c, tclCompile.c, tclProc.c and tclVar.c 2004-10-24 Don Porter * generic/tclBasic.c (Tcl_LogCommandInfo,Tcl_AddObjErrorInfo): Shift the initialization of errorCode to NONE to more central location. * generic/tclEvent.c (BgError,Tcl_BackgroundError,HandleBgErrors): Rewrite to build on the new TclGet/SetReturnOptions routines. * generic/tclResult.c (TclGetReturnOptions): Add call to Tcl_AddObjErrorInfo to be sure error fields are initialized. * generic/tclResult.c (TclTransferResult): Rewrite to build on the new TclGet/SetReturnOptions routines. 2004-10-22 Donal K. Fellows * doc/tm.n: Tightened up the documentation. * tests/tm.test: Created (with partially dummy content) so TIP#189 can be marked Final. * generic/tclNamesp.c (NsEnsembleImplementationCmd): Make ensembles cut their implementations out of error traces. This is the right thing to do more often than not. 2004-10-22 Kevin B. Kenny * library/clock.tcl: Fixed a typo where the fallback time zone became ::localtime instead of :localtime. Fixed a bug where time zone names containing hyphens could not be loaded. * tests/clock.test: Added regression test cases that covers both bugs. Thanks to Todd M. Helfter for finding these bugs. 2004-10-22 Donal K. Fellows * generic/tclExecute.c (TclCompEvalObj, Tcl_ExprObj): * generic/tclProc.c (TclProcCompileProc): Always call object freeIntRepProc's in the same way. 2004-10-22 Miguel Sofer * generic/tclVar.c: fixed bug in commit of 2004-07-23, which was causing a leak of Proc structures and failure of compile-12.1. Two lines were 'zombies' from the previous way localVarNames worked. Credit dgp for finding this. 2004-10-21 Don Porter * generic/tclInt.h (Interp): * generic/tclBasic.c (Tcl_CreateInterp,Tcl_DeleteInterp): * generic/tclResult.c (GetKeys,ReleaseKeys,etc.): Moved the key values of the return options dictionary out of private fields of the Interp struct and into thread-static values managed in tclResult.c. * generic/tclCmdAH.c (Tcl_CatchObjCmd, Tcl_ErrorObjCmd): Updated to call the new TclGet/SetReturnOptions routines to do much of their work. * generic/tclInt.h (TclGetReturnOptions,TclSetReturnOptions): * generic/tclResult.c (TclGetReturnOptions,TclSetReturnOptions): New utility routines to get/set the return options of an interp. Intent is that these routines will be converted to public routines after TIP approval. * generic/tclCmdMZ.c (TclProcessReturn,TclMergeReturnOptions): * generic/tclResult.c (TclProcessReturn,TclMergeReturnOptions): Move internal utility routines from tclCmdMZ.c to tclResult.c. * generic/tclBasic.c (Tcl_CreateInterp, Tcl_DeleteInterp): * generic/tclResult.c (TclTransferResult): Rework so that iPtr->returnOpts can be NULL when there are no special options. * generic/tclResult.c (TclRestoreInterpState): Plug potential memory leak. 2004-10-21 Kevin B. Kenny * generic/tclBasic.c: Various changes to [clock format] that, * generic/tclClock.c: together, make it roughly twice as fast * generic/tclInt.h: while all tests in the test suite * library/clock.tcl: continue to pass. 2004-10-20 Andreas Kupries * win/Makefile.in (install-msgs): Fixed a problem with the * win/Makefile.in (install-tzdata): installation of timezone data and message catalogs. They used the installed tcl library directory, not the source library. Before it was installed. Switched to source lib dir. Thanks to Kevin for the help in figuring this out. 2004-10-20 Don Porter * generic/tclThreadTest.c (ThreadEventProc): Corrected subtle bug where the returned (char *) from Tcl_GetStringResult(interp) continued to be used without copying or refcounting, while activity on the interp continued. That's not safe, and recent changes demonstrated the lack of safety with failing tests thread-4.3 and thread-4.5. 2004-10-19 Donal K. Fellows * generic/tclDictObj.c (DictWithCmd): Make sure all paths (that are not themselves error paths) do not lose the result code. 2004-10-19 Don Porter * generic/tclInt.h (Tcl*InterpState): New internal routines * generic/tclResult.c (Tcl*InterpState): TclSaveInterpState, TclRestoreInterpState, and TclDiscardInterpState are superior replacements for Tcl_(Save|Restore|Discard)Result. Intent is that these routines will be converted to public routines after TIP approval. Interfaces for these routines were shamelessly stolen from Itcl. * generic/tclBasic.c (TclEvalObjvInternal): * generic/tclDictObj.c (DictUpdateCmd, DictWithCmd): * generic/tclIOGT.c (ExecuteCallback): * generic/tclTrace.c (Trace*Proc,TclCheck*Traces,TclCallVarTraces): Callers of Tcl_*Result updated to call the new routines. The calls were relocated in several cases to perform save/restore operations only when needed. * generic/tclEvent.c (HandleBgErrors): * generic/tclFCmd.c (CopyRenameOneFile): Calls to Tcl_*Result that were eliminated because they appeared to serve no useful purpose, typically saving/restoring an error message, only to throw it away. 2004-10-18 Don Porter * generic/tclBasic.c (Tcl_CreateInterp,Tcl_DeleteInterp): * generic/tclCmdAH.c (Tcl_CatchObjCmd): * generic/tclCmdMZ.c (TclMergeReturnOptions,TclProcessReturn): * generic/tclCompCmds.c (TclCompileReturnCmd): * generic/tclExecute.c (TclCompEvalObj): * generic/tclInt.h (Interp): * generic/tclProc.c (TclUpdateReturnInfo): Place primary storage of the -level and -code information in private fields of the Interp struct, rather than in a DictObj. This should significantly improve performance of TclUpdateReturnInfo. 2004-10-17 Miguel Sofer * generic/tclResult.c: removed unused variable [Bug 1048588]. Thanks to Daniel South. 2004-10-15 Don Porter * generic/tclCmdMZ.c (TclProcessReturn): Now that primary * generic/tclProc.c (TclUpdateReturnInfo): storage for the errorInfo and errorCode values are internal fields, we can set them at the time of the [return] command, and not have to wait until the specified number of "-level"s have popped. * generic/tclBasic.c (Tcl_CreateInterp, Tcl_DeleteInterp) (TclEvalObjvInternal, Tcl_LogCommandInfo, TclAddObjErrorInfo): * generic/tclCmdAH.c (Tcl_CatchObjCmd): * generic/tclEvent.c (BgError, ErrAssocData, Tcl_BackgroundError) (HandleBgErrors, BgErrorDeleteProc): * generic/tclExecute.c (TclCreateExecEnv, TclDeleteExecEnv): * generic/tclIOUtil.c (comments only): * generic/tclInt.h (ExecEnv,Interp, ERR_IN_PROGRESS): * generic/tclInterp.c ([tclInit]): * generic/tclMain.c (comments only): * generic/tclNamesp.c (Tcl_CreateNamespace, Tcl_DeleteNamespace) (TclTeardownNamespace): * generic/tclProc.c (TclUpdateReturnInfo): * generic/tclResult.c (Tcl_ResetResult, TclTransferResult): * generic/tclTrace.c (CallVarTraces): Reworked management of the "errorInfo" data of an interp. That information is now primarily stored in a new private (Tcl_Obj *) field of the Interp struct, rather than using a global variable ::errorInfo as the primary storage. The ERR_IN_PROGRESS flag bit value is no longer required to manage the value in its new location, and is removed. Variable traces are established to support compatibility for any code expecting the ::errorInfo variable to hold the information. ***POTENTIAL INCOMPATIBILITY*** Code that sets traces on the ::errorInfo variable may notice a difference in timing of the firing of those traces. Code that uses the value ERR_IN_PROGRESS. 2004-10-14 Donal K. Fellows TIP#217 IMPLEMENTATION * generic/tclCmdIL.c (Tcl_LsortObjCmd): Add -indices option from James Salsman. [Patch 1017532] * generic/tclUtil.c (TclMatchIsTrivial): Detect degenerate cases of glob matching that let us avoid scanning through hash tables. * generic/tclCmdIL.c (InfoCommandsCmd, InfoGlobalsCmd, InfoProcsCmd): (InfoVarsCmd): Use this to speed up some [info] subcommands. 2004-10-12 Kevin B. Kenny * library/tzdata/America/Campo_Grande: * library/tzdata/America/Cuiaba: * library/tzdata/America/Sao_Paulo * library/tzdata/America/Argentina/Mendoza: * library/tzdata/America/Argentina/San_Juan: Synchronized to Olson's 'tzdata2004e'. 2004-10-08 Donal K. Fellows TIP#201 AND TIP#212 IMPLEMENTATIONS * doc/dict.n, doc/expr.n: Documentation for new functionality. * tests/expr.test: Basic tests of 'in' and 'ni' behaviour. * tests/dict.test (dict-21.*,dict-22.*): Tests for [dict update] and [dict with]. * generic/tclExecute.c (TclExecuteByteCode): Implementation of the INST_LIST_IN and INST_LIST_NOT_IN bytecodes. * generic/tclParseExpr.c (GetLexeme): Parse the 'in' and 'ni' operators for TIP#201. * generic/tclDictObj.c (DictUpdateCmd,DictWithCmd): Core of implementation of TIP#212; docs and tests still to do... 2004-10-07 Don Porter * generic/tclTest.c (TestsetobjerrorcodeCmd): Simplified. 2004-10-07 Vince Darley * generic/tclFileName.c: * generic/tclFileSystem.h: * generic/tclIOUtil.c: * generic/tclPathObj.c: * unix/tclUnixFile.c: * win/tclWinFile.c: * tests/fileName.test: * tests/winFCmd.test: code reorganization for better generic/platform code splitting [Bug 925620] removing the need for several #ifdef's, and tests and fix for an unreported Windows glob problem ('glob -dir C: -tails *'). 2004-10-07 Donal K. Fellows * *.3: Convert CONST to const and VOID to void so we document how people should actually use the Tcl API and not the compatability hacks that it has to have. * doc/man.macros, *.3: Update .AS macro so it can know how wide to make the third column of the argument list. Update documentation for C API (only users) to take advantage of this. * doc/FileSystem.3: Formatting fixes for greater documentation clarity. 2004-10-06 Donal K. Fellows * generic/tclFileName.c (DoGlob, TclGlob): Stop messy sharing of interpreter result and instead use a private object for collecting the result of the glob. This simplifies TclGlob quite a lot. * generic/tclIOUtil.c (Tcl_FSMatchInDirectory): Simplify by removing some nesting. Also standardize variable names. (FsAddMountsToGlobResult): Force updates to the list to be done in-place, putting a side-condition of non-shared-ness on the resultPtr argument to Tcl_FSMatchInDirectory, but everything would have broken before if that was shared *anyway*. * generic/tclEncoding.c (LoadTableEncoding): Removed reference to Tcl interpreter; it wasn't needed as direct object use is more efficient. * generic/tclPathObj.c: Made this file follow the style rules in the Engineering Manual more closely, and also take advantage of the internal object manipulation macros more. * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Reorganized to have fewer magic flag variables and to separate the code that scans for a match from the code that processes a match body. 2004-10-06 Don Porter * generic/tclBasic.c: * generic/tclBinary.c: * generic/tclCmdAH.c: * generic/tclCmdIL.c: * generic/tclCmdMZ.c: * generic/tclCompExpr.c: * generic/tclDictObj.c: * generic/tclEncoding.c: * generic/tclExecute.c: * generic/tclFCmd.c: * generic/tclHistory.c: * generic/tclIndexObj.c: * generic/tclInterp.c: * generic/tclIO.c: * generic/tclIOCmd.c: * generic/tclNamesp.c: * generic/tclObj.c: * generic/tclPkg.c: * generic/tclResult.c: * generic/tclScan.c: * generic/tclTimer.c: * generic/tclTrace.c: * generic/tclUtil.c: * generic/tclVar.c: * unix/tclUnixFCmd.c: * unix/tclUnixPipe.c: * win/tclWinDde.c: * win/tclWinFCmd.c: * win/tclWinPipe.c: * win/tclWinReg.c: It is a poor practice to directly set or append to the value of the objResult of an interp, because that value might be shared, and in that circumstance a Tcl_Panic() will be the result. Searched for example of this practice and replaced with safer alternatives, often using the Tcl_AppendResult() routine that dkf just rehabilitated. * library/dde/pkgIndex.tcl: Bump to dde 1.3.1 * library/reg/pkgIndex.tcl: Bump to registry 1.1.5 2004-10-06 Donal K. Fellows * doc/SetResult.3: Made Tcl_AppendResult non-deprecated; better that people use it than most of the common alternatives! * generic/tclResult.c (Tcl_AppendResultVA): Make this work better with Tcl_Objs. [Patch 1041072] (Tcl_SetResult, Tcl_AppendElement): Change string to stringPtr to avoid C++ keywords. 2004-10-05 Don Porter * generic/tclBasic.c (TclObjInvoke): More simplification of the TclObjInvoke routine toward unification with the rest of the evaluation stack. * generic/tclBasic.c (Tcl_CreateInterp, Tcl_DeleteInterp) (TclEvalObjvInternal, Tcl_LogCommandInfo): * generic/tclCmdAH.c (Tcl_CatchObjCmd): * generic/tclEvent.c (BgError, Tcl_BackgroundError, HandleBgErrors): * generic/tclInt.h (Interp, ERROR_CODE_SET): * generic/tclNamesp.c (Tcl_CreateNamespace, Tcl_DeleteNamespace) (TclTeardownNamespace): * generic/tclResult.c (Tcl_ResetResult, Tcl_SetObjErrorCode) (TclTransferResult): * generic/tclTrace.c (CallVarTraces): Reworked management of the "errorCode" data of an interp. That information is now primarily stored in a new private (Tcl_Obj *) field of the Interp struct, rather than using a global variable ::errorCode as the primary storage. The ERROR_CODE_SET flag bit value is no longer required to manage the value in its new location, and is removed. Variable traces are established to support compatibility for any code expecting the ::errorCode variable to hold the information. ***POTENTIAL INCOMPATIBILITY*** Code that sets traces on the ::errorCode variable may notice a difference in timing of the firing of those traces. * generic/tclNamesp.c (Tcl_PopCallFrame): Removed Bug 1038021 workaround. That bug is now fixed. 2004-10-04 Kevin B. Kenny * tests/clock.test (clock-34.*): Removed an antibug that forced comparison of [clock scan] results with the :localtime time zone. Now that [clock scan] uses the current time zone instead, the antibug caused several tests to fail. [Bug 1038554] 2004-10-04 Donal K. Fellows * generic/tclParseExpr.c (GetLexeme): Ensure that the 'eq' and 'ne' operators are followed by non-alphabetic characters so lexemes can't run together. [Bug 884830] * doc/DictObj.3, doc/dict.n: Clarified that a dictionary is not order-preserving. [Bug 1032243] Also added another example to show off more ways of using a dictionary and a few other formatting improvements. 2004-10-02 Donal K. Fellows * generic/tclDictObj.c (TraceDictPath, Tcl_DictObjPutKeyList): Add support for automatic creation of dictionary paths since that is what everyone seems to actually expect of the API! [Bug 1037235] (Tcl_DictObjNext): Make calling this after Tcl_DictObjDone non-fatal as that simplifies a number of internal APIs. This doesn't break any existing working code as it is a case which previously caused a panic. 2004-10-02 Don Porter * tests/namespace.test (namespace-8.7): Another test for save/restore of ::errorInfo and ::errorCode during global namespace teardown. 2004-10-01 Donal K. Fellows * generic/tclProc.c (TclObjGetFrame, Tcl_UplevelObjCmd): * generic/tclVar.c (Tcl_UpvarObjCmd): Cache stackframe level references in the level object for speed. 2004-09-30 Don Porter * generic/tclBasic.c (Tcl_CreateInterp): * generic/tclInt.h (Interp): Removed the flag bit value EXPR_INITIALIZED. It was set during interp creation and never tested. Whatever purpose it had is in the past. * generic/tclBasic.c (Tcl_EvalObjEx): Removed the flag bit value * generic/tclInt.h (Interp): USE_EVAL_DIRECT. It was used * generic/tcLTest.c (TestevalexObjCmd): only in the testing command * tests/parser.test (parse-9.2): [testevalex] and nothing in the test suite made use of the capability it enabled. * generic/tclBasic.c (Tcl_AddObjErrorInfo): More re-organization * generic/tclCmdAH.c (Tcl_ErrorObjCmd): of the management of * generic/tclCmdMZ.c (TclProcessReturn): the errorCode value. * tests/error.test (error-6.4-9): * generic/tclNamespace.c (TclTeardownNamespace): Tcl_Obj-ified * tests/namespace.test (namespace-8.5,6): the save/restore of ::errorInfo and ::errorCode during global namespace teardown. Revised the comment to clarify why this is done, and added tests that will fail if this is not done. * generic/tclResult.c (TclTransferResult): Added safety checks so that unexpected undefined ::errorInfo or ::errorCode will not lead to a segfault. * generic/tclTrace.c (TclCallVarTraces): Save/restore the flag values * tests/var.test (var-16.1): that define part of the interpreter state during variable traces. [Bug 1038021]. 2004-09-30 Miguel Sofer * tests/subst.test (12.1-2): added tests for [Bug 1036649] 2004-09-29 Don Porter * tests/basic.test (49.*): New tests for TCL_EVAL_GLOBAL. 2004-09-29 Donal K. Fellows * generic/tclVar.c (TclObjLookupVar, TclObjLookupVar): (TclObjUnsetVar2, SetArraySearchObj): * generic/tclUtil.c (SetEndOffsetFromAny): * generic/tclStringObj.c (Tcl_SetStringObj): (Tcl_SetUnicodeObj, SetStringFromAny): * generic/tclResult.c (ResetObjResult): * generic/tclRegexp.c (Tcl_GetRegExpFromObj): * generic/tclPathObj.c (TclFSMakePathRelative, SetFsPathFromAny): (TclFSMakePathFromNormalized, Tcl_FSNewNativePath): * generic/tclObj.c (TclFreeObj, Tcl_SetBooleanObj, SetBooleanFromAny): (Tcl_SetDoubleObj, SetDoubleFromAny, Tcl_SetIntObj): (SetIntOrWideFromAny, Tcl_SetLongObj, SetWideIntFromAny): (Tcl_SetWideIntObj, TclSetCmdNameObj, SetCmdNameFromAny): * generic/tclNamesp.c (SetNsNameFromAny, MakeCachedEnsembleCommand): * generic/tclListObj.c (Tcl_SetListObj, SetListFromAny): * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): * generic/tclDictObj.c (SetDictFromAny): * generic/tclCompile.c (TclInitByteCodeObj): * generic/tclBinary.c (Tcl_SetByteArrayObj, SetByteArrayFromAny): * generic/tclInt.h (TclFreeIntRep): Factorize out deletion of object internal representation to a shared macro, so simplifying much code. 2004-09-27 Miguel Sofer * generic/tclBasic.c (TclObjInvoke): fix for bogus gcc warning about uninitialised variable. 2004-09-27 Don Porter * generic/tclBasic.c: Removed internal routines TclInvoke, * generic/tclInt.decls: TclGlobalInvoke, TclObjInvokeGlobal and the * tests/basic.test: portion of TclObjInvoke that handles calls without TCL_INVOKE_HIDDEN enabled. None of this code is called any longer within the core, and the superior public interface, Tcl_EvalObjv, is available for any external callers. * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclEvent.c (HandleBgErrors): Updated [bgerror] invocations to make use of Tcl_Obj based routines, dropping the calls to TclGlobalInvoke() 2004-09-27 Vince Darley * generic/tclFileName.c: * generic/tclFileSystem.h: * generic/tclIOUtil.c: * generic/tclPathObj.c: * tests/cmdAH.test: * tests/fileSystem.test: * tests/winFCmd.test: fix to bad error message with 'cd' on windows, when permissions are inadequate [Bug 1035462] and to treatment of a volume-relative pwd on Windows [Bug 1018980]. * doc/FileSystem.3: added missing Tcl_GlobTypeData documentation [Bug 935853] 2004-09-27 Kevin Kenny * compat/strftime.c (Removed): * generic/tclClock.c (removed TclClockOldscanObjCmd): * generic/tclDate.c (Regenerated): * generic/tclGetDate.y: * generic/tclInt.decls (removed TclGetDate and TclpStrftime): * generic/tclInt.h (removed TclGetDateInfo): * generic/tclIntDecls.h (Regenerated): * generic/tclStubInit.c (Regenerated): * library/clock.tcl: * unix/tclUnixTime.c (removed TclpStrftime): * win/Makefile.in: * win/makefile.bc: * win/makefile.bc: * win/tcl.dsp: Continued refactoring of [clock] for TIP 173 changes. Broke the free-form parser apart so that the Bison parser is responsible for only parsing, while clock.tcl handles relative times like "next Thursday", "next January". This change is needed to make timezones other than :localtime and :Etc/UTC work with free-form scanning. This change closes out the issue identified as being "for another day" in my log message of 2004-09-08. The refactored code also eliminates the last known references to TclpStrftime and TclGetDate, so those routines (including compat/strftime.c) have been removed. The refactoring also has the benefit that all storage in the Bison parser is now on the C stack, eliminating any need for mutex protection around [clock scan]. Also, changed the Makefiles so that 'make gendate' is available on Windows as well as Unix. * generic/tclCmdAH.c (Tcl_FormatObjCmd): Removed some grubby * generic/tclObj.c (SetBooleanFromAny): work-around code that was needed only because of Bug 868489. * generic/tclBasic.c (TclObjInvoke): Removed three unused variables to silence a compiler warning in VC++. 2004-09-27 Vince Darley * doc/FileSystem.3: fix to small typo. 2004-09-26 Miguel Sofer * generic/tclCompCmds.c: * generic/tclCompExpr.c: * generic/tclCompile.c: * generic/tclCompile.h: * generic/tclInt.h: * generic/tclProc.c: * tests/compExpr-old.test: * tests/compExpr.test: * tests/expr.test: * tests/for.test: * tests/if.test: * tests/incr.test: * tests/while.test: Report compilation errors at runtime, [Patch 1033689] by dgp. 2004-09-23 Mo DeJong * unix/dltest/Makefile.in (clean): Fixup make clean rule so that it does not delete all files when SHLIB_SUFFIX is set to the empty string in a static build. [Bug 1016726] 2004-09-23 Don Porter * generic/tclBasic.c: Corrections to the 2004-09-21 commit * generic/tclExecute.c: regarding ERR_ALREADY_LOGGED. That commit * generic/tclNamesp.c: caused Tk test send-10.7 to fail. Added * tests/namespace.test (25.7,8): tests in the Tcl test suite * tests/pkg.test (2.25,26): to catch this error without the aid of Tk in the future. * generic/tclCmdAH.c (Tcl_ExprObjCmd): Simplified the TclObjCmdProc of [expr] with a call to Tcl_ConcatObj. 2004-09-22 Don Porter * generic/tclCmdMZ.c (TclProcessReturn): Support the -errorline * generic/tclCompile.c (TclCompileScript): option to [return]. * tests/compile.test (16.23.*): Use that capability to defer reporting * tests/misc.test (1.2): of parse errors until runtime. Updated tests to reflect change. [Bug 1032805] 2004-09-22 Miguel Sofer * generic/tclExecute.c (INST_START_CMD): * tests/proc.test (7.2-3): fix for [Bug 729692] was incorrect whenever a loop exception was returned. 2004-09-22 Kevin B. Kenny * library/tzdata/America/Montevideo: Updated to reflect ftp://elsie.nci.nih.gov/pub/tzdata2004d.tar.gz. (Changes to Asia/Jerusalem were in the comments only.) [Routine maintenance - no bug] Spanish-language description of the change at http://www.presidencia.gub.uy/decretos/2004091502.htm 2004-09-21 Don Porter * generic/tclCompCmds.c: Tolerate [append] syntax errors * tests/appendComp.test (8.1): at compile time, and allow runtime to raise the error (or succeed if a redefined [append] allows). * generic/tclBasic.c: Reworked management of the interp flag * generic/tclCompile.c: ERR_ALREADY_LOGGED, to reduce its exposure. * generic/tclExecute.c: Still left several referebces that are just * generic/tclNamesp.c: too nice on performace to do away with. These changes also resolve an inconsistency in the ::errorInfo values produced by [namespace eval x error foo bar] and [namespace eval x {error foo bar}]. * generic/tclExecute.c (TclCompEvalObj): Simplified the TclCompEvalObj routine. Much housekeeping now reliably happens elsewhere. [Patch 1031949] 2004-09-21 Donal K. Fellows * doc/interp.n: Tighten up wording on how [interp eval] and [interp invokehidden] operate w.r.t. stack frames. [Bug 926590] 2004-09-20 Don Porter * tests/error.test (error-6.2,3): Added more tests to verify ::errorCode setting by/after a [catch]. 2004-09-19 Miguel Sofer * generic/tclCmdAH.c: removed outdated comment [Bug 1029518]. 2004-09-18 David Gravereaux * win/tclAppInit.c: Dde package can load into a safe interp. Claim this fact for the Tcl_StaticPackage() call when the shell is built with the TCL_USE_STATIC_PACKAGES option. 2004-09-18 Donal K. Fellows * generic/tclExecute.c (TEBC-INST_LSHIFT,INST_RSHIFT): Ensure that large shifts end up shifting correctly. [Bug 868467] * doc/FileSystem.3, doc/OpenFileChnl.3: More documentation fixes from Mikhail Kolesnitchenko. [Patch 1022527] * doc/*: Standardize highlighting of symbols defined in tcl.h 2004-09-17 Don Porter * generic/tclBasic.c (Tcl_AddObjErrorInfo, Tcl_LogCommandInfo): * generic/tclCmdAH.c ([catch], [error]): * generic/tclCmdMZ.c ([return]): * generic/tclProc.c (TclUpdateReturnInfo): * generic/tclResult.c (Tcl_SetErrorCodeVA, Tcl_SetObjErrorCode) (TclTransferResult): Refactored so that all errorCode setting flows through Tcl_SetObjErrorCode(). This greatly reduces the number of different places in the code that need to know details about an internal bitflag field of the Interp struct. Also places errorCode setting in one place for easier future mods. 2004-09-17 Kevin B.Kenny * generic/tclDate.c: Revised tclGetDate.y to use bison instead of * generic/tclGetDate.y: yacc to build the parser, eliminating all the * generic/tclInt.h: complicated hackery involving 'sed' * unix/Makefile.in: postprocessing. Rebuilt the parser. 2004-09-14 Kevin B. Kenny * generic/tclClock.c (ClockOldscanObjCmd): Silenced a compiler warning (long passed as a param where unsigend long was expected). 'Unsigned long' is wrong, but the fix is really to change the signature of TclGetDate to return a structure of its 'yy' variables and then do the remaining work inside clock.tcl. But, as I said on 2004-09-08, that's a job for another day. [Bug 1027993] 2004-09-10 Miguel Sofer * doc/interp.n: * generic/tclInterp.c (TclPreventAliasLoop, AliasCreate): * tests/interp.test (17.4-6, 19.3-4): fixing problems with renaming of aliases [Bugs 707104 1026493]. Fix designed by dgp. 2004-09-13 Donal K. Fellows * generic/tclNamesp.c (NsEnsembleImplementationCmd): Add token field to internal rep of EnsembleCmdRep structure so that we can check it to see if the subcommand object is really being used with the same ensemble. [Bug 1026903] 2004-09-11 Kevin B. Kenny * generic/tclClock.c (TclMktimeObjCmd): Corrected a bad check for error return from 'mktime'. * generic/tclObj.c (Tcl_GetIntFromObj): Corrected a problem where demoting a wide to an int failed on a big-endian machine. [Bug 1026125]. * tests/clock.test (clock-43.1): Added regression test for error return from 'mktime'. 2004-09-11 Miguel Sofer * generic/tclExecute.c (INST_CONCAT1): fix for [Bug 1025834]; avoid unnecessary string copies. 2004-09-10 David Gravereaux * tests/tcltest.test: tcltest-12.3-4 needed to have ::tcltest::loadScript set to empty in their -setup 2004-09-10 Donal K. Fellows * generic/tclObj.c (SetIntOrWideFromAny): Rewritten integral value parsing code so that values do not flip so easily between numeric representations. Thanks to KBK for this! [Bug 868489] * generic/tclIO.c (Tcl_Seek): Make sure wide seeks do not fail to set ::errorCode on error. [Bug 1025359] 2004-09-10 Andreas Kupries * generic/tcl.h: Micro formatting fixes. * generic/tclIOGT.c: Channel version fixed, must be 3, to have wideseekProc. Thanks to David Graveraux . 2004-09-11 Don Porter * generic/tclNamespace.c (TclGetNamespaceForQualName): Resolved longstanding inconsistency in the treatment of the TCL_NAMESPACE_ONLY flag revealed by testing the 2004-09-09 commits against Itcl. TCL_NAMESPACE_ONLY now acts as specified in the pre-function comment, forcing resolution in the passed in context namespace. It has been incorrectly forcing resolution in the interp's current namespace. 2004-09-10 Kevin Kenny * library/clock.tcl: Fixed a bug where %z always put a plus sign on the time zone in :localtime. * tests/clock.test: Added test case for the above bug. 2004-09-10 Miguel Sofer * generic/tclExecute.c (INST_CONCAT1): added a peephole optimisation for concatting an empty string. This enables replacing the idiom 'K $x [set x {}]' by '$x[set x {}]' for fastest execution. 2004-09-09 David Gravereaux * win/tclWinConsole.c: Calls to WriteFile and WriteConsoleA changed to WriteConsole for simplicity. 2004-09-09 Don Porter * generic/tclNamesp.c (Tcl_ForgetImport): Corrected faulty * tests/namespace.test: logic that relied exclusively on string matching and failed in the presence of [rename]s. [Bug 560297] Also corrected faulty prevention of [namespace import] cycles. [Bug 1017299] 2004-09-08 Don Porter * generic/tclBasic.c (Tcl_CreateInterp): Removed obsolete field for storing the string-based command procedure of built-in commands. We no longer have any string-based built-in commands! 2004-09-08 Kevin B. Kenny * compat/strftime.c (_conv): Corrected a problem where hour 0 would format as a blank format group with %k. * doc/clock.n: Corrected a buglet in the header information. [Bug 1024058] * generic/tclClock.c (TclClockMktimeObjCmd): Fixed a bug where the month was scanned incorrectly in -timezone :localtime. * tests/clock.test (clock-34.*,clock-40.1, clock-41.1): Adjusted the clock-34.* test cases so that the consistency check is performed in :localtime rather than the current time zone. This change allows dealing with issues where the C library has a different idea of DST conversion than Tcl. (Real fix would be to break TclGetDate into separate parser and time converter, and do the time conversion in clock.tcl. That's for another day.) Added regression test case for the bug where month was scanned incorrectly in -timezone :localtime. [Bug 1023779] Added regression test case for %k at the zero hour. 2004-09-07 David Gravereaux * win/makefile.vc: some quoting needed to be removed as it was breaking with VC7. [Bug 1023150] 2004-09-07 Kevin B. Kenny * doc/clock.n: Documented the default -format, and changed references to a (nonexistent) msgcat command to refer to the msgcat package. [Bug 1023870] * generic/tclTimer.c: Removed a premature optimisation that attempted to store the assoc data in the client data; the optimisation caused a bug that [after] would overwrite its imports. [Bug 1016167] * library/clock.tcl (InitTZData, ClearCaches): Changed so that the in-memory time zone :UTC (and its aliases) always gets reinitialised, in case tzdata is absent. [Bug 1019537, 1023779] * library/tzdata/*: Regenerated. * tests/clock.test (clock-31.*, clock-39.1): Corrected a problem where the 'system' locale tests fail on a non-English Windows machine. [Bug 1023761]. Added a test to make sure that alias time zones load correctly. [Bug 1023779]. * tests/timer.test (timer-1.1, timer-2.1): Changed to (one hopes!) be more resilient on an overloaded system, if [after 200] sleeps for 300 ms or longer. * tools/tclZIC.tcl (writeLinks): Corrected a problem where alias time zone names were written incorrectly, causing them to fail to load at run time. [Bug 1023779]. * win/tclWinTime.c (Tcl_GetTime): Eliminated CPUID tests on Win64 - assuming that HAL vendors now do a better job of keeping the performance counters synchronized among CPU's. [Bug 1020445] 2004-09-06 Donal K. Fellows * doc/tclvars.n, doc/tcltest.n, doc/tclsh.1, doc/safe.n, doc/expr.n * doc/WrongNumArgs.3, doc/Utf.3, doc/TraceVar.3, doc/Thread.3 * doc/TCL_MEM_DEBUG.3, doc/SubstObj.3, doc/StdChannels.3 * doc/SetResult.3, doc/RegExp.3, doc/RegConfig.3, doc/RecEvalObj.3 * doc/PrintDbl.3, doc/ParseCmd.3, doc/Panic.3, doc/ObjectType.3 * doc/Object.3, doc/Namespace.3, doc/Interp.3, doc/IntObj.3 * doc/Hash.3, doc/GetOpnFl.3, doc/GetIndex.3, doc/Eval.3 * doc/Encoding.3, doc/DoubleObj.3, doc/DictObj.3, doc/CrtTimerHdlr.3 * doc/CrtObjCmd.3, doc/CrtMathFnc.3, doc/CrtCommand.3, doc/CrtChannel.3 * doc/ChnlStack.3, doc/ByteArrObj.3, doc/AssocData.3, doc/Alloc.3: More documentation fixes from Mikhail Kolesnitchenko. [Patch 1022527] 2004-09-03 Donal K. Fellows * unix/tclUnixFCmd.c: Stop NULL interp arguments from triggering a crash when an error happens. [Bug 1020538] 2004-09-02 Donal K. Fellows * doc/lsearch.n: Clarified meaning of -dictionary. [Bug 759545] 2004-09-02 Vince Darley * win/makefile.vc: clock.tcl needs to be installed. 2004-09-01 Jeff Hobbs * win/tclWinReg.c (BroadcastValue): WIN64 cast corrections * win/tclWinDde.c (DdeClientWindowProc): (DdeServicesOnAck, DdeEnumWindowsCallback): WIN64 corrections * win/tclWin32Dll.c (TclWinCPUID): need _asm for WIN64 (Itanium), until we have it, just return unknown. [Bug 1020445] 2004-09-01 Donal K. Fellows * doc/regsub.n, doc/RegConfig.3, doc/Environment.3: * doc/CrtChannel.3, doc/safe.n: Use correct abbreviations. 2004-08-31 Donal K. Fellows * doc/trace.n, doc/socket.n, doc/registry.n, doc/pid.n: * doc/namespace.n, doc/msgcat.n, doc/lsort.n, doc/lsearch.n: * doc/linsert.n, doc/info.n, doc/http.n, doc/history.n: * doc/format.n, doc/file.n, doc/exec.n, doc/dde.n, doc/clock.n: * doc/catch.n, doc/binary.n: More spelling and grammar fixes from Mikhail Kolesnitchenko. [Patch 1018486] 2004-08-31 Vince Darley * doc/FileSystem.3: * generic/tclIOUtil.c: Clarified documentation regarding ability of a filesystem to say that it doesn't support a given operation using the EXDEV posix error code (copyFileProc, renameFileProc, etc), and updated one piece of code to ensure correct behaviour when an operation is not supported [Bug 1017072] * tests/fCmd.test: fix to test suite problem [Bug 1002884] 2004-08-31 Daniel Steffen * unix/Makefile.in (install-libraries): portable sh fix. 2004-08-30 Donal K. Fellows * generic/tclCmdMZ.c (Tcl_StringObjCmd): Stop [string map] from crashing when its map and input string are the same object. 2004-08-27 Donal K. Fellows * generic/tclNamesp.c (FindEnsemble): Factor out the code to convert a command name into an ensemble configuration and add support for ignoring [namespace import] link chains. [Bug 1017022] (NamespaceWhichCmd): Rework to use newer option parsing API. 2004-08-27 Daniel Steffen * unix/Makefile.in: added customization of default module path roots via TCL_MODULE_PATH makefile variable. * macosx/Makefile: add platform standard locations to default module path roots. [Patch 942881] * tests/env.test: macosx fixes. 2004-08-25 Don Porter * tests/timer.test (timer-10.1): Test for Bug 1016167. * generic/tclTimer.c: Workaround for situation when a [namespace import] causes the objv[0] value to be something other than what Tcl_AfterObjCmd expects. [Bug 1016167]. 2004-08-25 Donal K. Fellows * generic/tclNamesp.c (NsEnsembleImplementationCmd): Use the ensemble command token to get the name of the ensemble for passing to the -unknown handler instead of relying on objv[0], which may contain useless info in the presence of [namespace import]. Problem found by Don Porter when investigating [Bug 1016167]. 2004-08-24 Don Porter * generic/tclProc.c: The routine TclProcInterpProc was a * generic/tclTestProcBodyObj.c: specific instance of the general service already provided by TclObjInvokeProc. Removed TclProcInterpProc and TclGetInterpProc from the code... * generic/tclInt.decls: ...and from the internal stubs table. * generic/tclIntDecls.h * generic/tclStubInit.c 2004-08-24 Donal K. Fellows * doc/string.n: Added clarifying note. 2004-08-23 Don Porter * library/auto.tcl: Updated [tcl_findLibrary] search path to include any [::pkgconfig get scriptdir,runtime] directory, as well as the $::auto_path. [RFE 695441] 2004-08-21 Kevin B. Kenny * tests/clock.test (clock-38.1): Changed TZ setting to specify CET in excruciating detail to deal with systems that lack the Posix defaults for DST changes (and to be formally correct with the change dates for CET). 2004-08-19 Donal K. Fellows * generic/tclScan.c (Tcl_ScanObjCmd, ValidateFormat): Ensure that the %ld conversion works correctly on 64-bit platforms. [Bug 1011860] 2004-08-19 Kevin Kenny * library/clock.tcl (format): Changed default timezone format from alphabetic to numeric to produce scannable times in more locales. * tests/clock.test (clock-37.1): Removed now-unused 'needPST' constraint and the comments that refer to it. 2004-08-18 Andreas Kupries * library/init.tcl: Integrated TIP #189. We source a separate file (see below), instead of inlining the contents of that file. This should beeasier to maintain, and easier to backport/install in 8.4 installations. Note: Usage of Tcl Modules is restricted to non-safe interps. It cannot be loaded into a safe interp. * library/tm.tcl: New file, the v2 reference implementation for TIP #189, Tcl Modules. * doc/tm.n: New file, documentation for Tcl Modules, based on the TIP. * unix/mkLinks: Regenerated. * win/makefile.vc: Added tm.tcl to list of files to install. 2004-08-18 Kevin Kenny * tests/httpd (httpdRespond): Corrected an abuse of the [clock] command that caused test failures for some values of [clock clicks]. * doc/clock.n * generic/tclBasic.c (Tcl_CreateInterp, Tcl_HideUnsafeCommands): * generic/tclClock.c (all): * generic/tclInt.h: * generic/tclInterp.c (CreateSlave): * library/clock.tcl: (new file) * library/init.tcl (clock): * library/msgs/*.msg:(new files) * library/tzdata/*: * library/tzdata/*/*: * library/tzdata/*/*/*: (new files) * tools/installData.tcl: (new file) * tools/loadICU.tcl: (new file) * tools/makeTestCases.tcl: (new file) * tools/tclZIC.tcl: (new file) * unix/Makefile.in: * unix/configure: (regenerated) * unix/tcl.m4: * tests/clock.test (all): * win/Makefile.in: * win/Makefile.vc: Implementation of TIPs #173 and #209. The [clock] command is now a Tcl ensemble, with most of its functionality written in Tcl and callouts to C code only to access low-level functions such as localtime, mktime and tzset. In addition to the functionality changes called out in the two TIPs, it is worth noting that the [clock] command in a safe slave interpreter is now an alias to the [clock] command in the master, and that [clock] is otherwise not expected to function entirely correctly in safe interps. C code that simply does Tcl_MakeSafe needs to be aware that [clock] may need special handling. (It appears unlikely that such code actually exists.) One incompatibility of note is that if the time zone cannot be determined from the TZ, TCL_TZ environment variables, or from the Windows control panel, so that the C library must be used for date and time conversions, then times outside the range of time_t will fail; they used to return bad data silently. Many thanks to all the many people who assisted with testing, debugging, criticism of the specification, and localisation. Deserving of particular mention are Joe English, Clif Flynt, Donal K. Fellows, Jeff Hobbs, Cameron Laird, Arjen Markus, Reinhard Max, Christopher Nelson, Steve Offutt, Donald G. Porter, Pascal Scheffers, Peter da Silva and Richard Suchenwirth-Bauersachs. *** POTENTIAL INCOMPATIBILITY *** 2004-08-16 Miguel Sofer * doc/SetVar.3: * generic/tclTest.c (TestseterrorcodeCmd): * generic/tclVar.c (TclPtrSetVar): * tests/result.test (result-4.*, result-5.*): [Bug 1008314] detected and fixed by dgp. 2004-08-13 Don Porter * library/msgcat/msgcat.tcl: Added checks to prevent [mclocale] * tests/msgcat.test: from registering filesystem paths to possibly malicious code to be evaluated by a later [mcload]. 2004-08-10 Zoran Vasiljevic * unix/tclUnixThrd.c (TclpThreadCreate): changed handling of the returned thread ID since broken on 64-bit systems (Cray). Thanks to Rob Ratcliff for reporting the bug. 2004-08-03 Donal K. Fellows * generic/tclNamesp.c (MakeCachedEnsembleCommand): Initialize the epoch field cached in the subcommand. [Bug 989298] (NsEnsembleImplementationCmd): Plug a leak (thanks to Miguel Sofer for spotting it with valgrind) and reduce the number of goto labels to make the code clearer. 2004-08-02 Don Porter * library/package.tcl (pkg_mkIndex): Updated [pkg_mkIndex] to make use of [glob -directory $dir -tails] and return options. TIP#207 IMPLEMENTATION * doc/interp.n: Added support for a -namespace option to the * generic/tclBasic.c: [interp invokehidden] command. Also added an * generic/tclInt.h: internal routine TclObjInvokeNamespace() and * generic/tclInterp.c: corrected the flag names TCL_FIND_ONLY_NS and * generic/tclNamesp.c: TCL_CREATE_NS_IF_UNKNOWN that are passed to the * generic/tclTrace.c: internal routine TclGetNamespaceForQualName(). * tests/interp.test: [Patch 981841] * generic/tclLiteral.c (TclCleanupLiteralTable): Corrected * tests/compile.test (compile-12.4): flawed deletion of literal internal reps that could lead to accessing of freed memory. Thanks to Kevin Kenny for test case and fix [Bug 1001997]. 2004-07-30 Don Porter * tests/safe.test (safe-2.1): Disabled senseless test. [Bug 999612] * library/auto.tcl (auto_reset): Removed "protected" list of commands from [auto_reset]. All entries in the auto_index can be re-loaded. * library/package.tcl: Updated comment to reflect 2004-07-28 commit. * generic/tclEvent.c (Tcl_Finalize): Re-organized Tcl_Finalize so that Tcl_ExitProc's that call Tcl_Finalize recursively do not cause deadlock. [Patch 999084 fixes Tk Bug 714956] 2004-07-30 Daniel Steffen * unix/configure: * unix/tcl.m4 (SC_CONFIG_CFLAGS): Darwin: instead of setting PLAT_OBJS to explict object files in tcl.m4, refer to MAC_OSX_OBJS makefile var. * unix/Makefile.in: added MAC_OSX_OBJS variable. 2004-07-29 Don Porter * library/package.tcl: [::pkg::create] is now an alias. Test safe-2.1 will now fail until Bug 999612 is corrected. 2004-07-28 Don Porter * library/package.tcl: Moved private command * library/tclIndex: [pkg_compareExtension] into ::tcl::Pkg. * tests/pkg_mkIndex.test: Also moved implementation of [::pkg::create] to [::tcl::Pkg::Create]. 2004-07-25 Pat Thoyts * tests/io.test: Make io-61.1 create file as binary to pass on Win32 2004-07-23 Miguel Sofer * generic/tclVar.c: simplify tclLocalVarNameType, removing the reference to the corresponding proc. The reference is now seen as unnecessary, and it may cause leaking circular references under some circumstances (see for example [Bug 994838]). 2004-07-22 Don Porter * tests/eofchar.data (removed): Test io-61.1 now generates its own * tests/io.test: file of test data as needed. 2004-07-20 Jeff Hobbs * generic/tclEvent.c: Correct threaded obj allocator to * generic/tclInt.h: fully cleanup on exit and allow for * generic/tclThreadAlloc.c: reinitialization. [Bug 736426] * unix/tclUnixThrd.c: (mistachkin, kenny) * win/tclWinThrd.c: 2004-07-21 Kevin Kenny * generic/tclBasic.c (DeleteInterpProc): * generic/tclLiteral.c (TclCleanupLiteralTable): * generic/tclInt.h: added a TclCleanupLiteralTable function, called from DeleteInterpProc, that frees internal representations of shared literals early when an interpreter is being deleted. This change corrects a number of memory mismanagement issues in the cases where the internal representation of one literal contains a reference to another, and avoids conditions such as resolved variable names referring to procedure and namespace contexts that no longer exist. [Bug 994838] 2004-07-20 Daniel Steffen * unix/Makefile.in: * win/Makefile.in: added 'install-private-headers' makefile target to allow optionally installing private tcl headers. [FR 922727] * macosx/Makefile: use new 'install-private-headers' target to install private headers into framework. [FR 922727] * unix/tclUnixFile.c (NativeMatchType): added support for readonly matching of user immutable files (where available). * macosx/tclMacOSXBundle.c: dynamically acquire address for CFBundleOpenBundleResourceMap symbol, since it is only present in full CoreFoundation on Mac OS X and not in CFLite on pure Darwin. 2004-07-19 Zoran Vasiljevic * win/tclwinThrd.c: redefined MASTER_LOCK to call TclpMasterLock. Fixes [Bug 987967] 2004-07-17 Vince Darley * generic/tclIOUtil.c: fix to rare 'cd' infinite loop in normalization with vfs [Bug 991420]. * tests/fileSystem.test: added test for above bug. * doc/FileSystem.3: clarified documentation of posix error codes in 'remove directory' FS proc - 'EEXIST' is used to signify a non-empty directory error (bug reported against tclvfs). 2004-07-16 Jeff Hobbs * unix/Makefile.in, unix/tcl.m4: move (C|LD)FLAGS after their * unix/configure.in, unix/configure: _DEFAULT to allow for env setting to override m4 switches. Move SC_MISSING_POSIX_HEADERS up and consolidate calls to limit redundancy in configure. (CFLAGS_WARNING): Remove -Wconversion (SC_ENABLE_THREADS): Set m4 to force threaded build when built against a threaded Tcl core. 2004-07-16 Andreas Kupries * generic/tclIOCmd.c (Tcl_FcopyObjCmd): Corrected a typo in the generation of error messages and simplified by reusing data in a variable instead of retrieving the string again. Fixes [Bug 835289]. * doc/OpenFileChnl.3: Added description of the behaviour of Tcl_ReadChars when its 'charsToRead' argument is set to -1. Fixes [Bug 934511]. * doc/CrtCommand.3: Added note that the arguments given to the command proc of a Tcl_CreateCommand are in utf8 since Tcl 8.1. Closing [Patch 414778]. * doc/ChnlStack.3: Removed the declaration that the interp argument to Tcl_(un)StackChannel can be NULL. This fixes [Bug 881220], reported by Marco Maggi . * tests/socket.test: Accepted two new testcases by Stuart Casoff checking that -server and -async don't go together [Bug 796534]. * unix/tclUnixNotfy.c (NotifierThreadProc): Accepted Joe Mistachkin's patch for [Bug 990500], properly closing the notifier thread when its exits. 2004-07-15 Andreas Kupries * unix/tclUnixThrd.c (TclpFinalizeMutex): Accepted Joe Mistachkin's patch for [Bug 990453], closing leakage of mutexes. They were not destroyed properly upon finalization. 2004-07-15 Andreas Kupries * generic/tclIO.h (CHANNEL_INCLOSE): New flag. Set in * generic/tclIO.c (Tcl_UnregisterChannel): 'Tcl_Close' while the * generic/tclIO.c (Tcl_Close): close callbacks are run. Checked in 'Tcl_Close' and 'Tcl_Unregister' to prevent recursive call of 'close' in the close-callbacks. This is a possible error made by implementors of virtual filesystems based on 'tclvfs', thinking that they have to close the channel in the close handler for the filesystem. 2004-07-14 Andreas Kupries * generic/tclIO.c: * generic/tclIO.h: * Not reverting, but #ifdef'ing the changes from May 19, 2004 out of the core. This removes the ***POTENTIAL INCOMPATIBILITY*** for channel drivers it introduced. This has become possible due to Expect gaining a BlockModeProc and now handling blockingg and non-blocking modes correctly. Thus [SF Tcl Bug 943274] is still fixed if a recent enough version of Expect is used. * doc/CrtChannel.3: Added warning about usage of a channel without a BlockModeProc. 2004-07-15 Andreas Kupries * generic/tclIOCmd.c (Tcl_PutsObjCmd): Added length check to the old depreceated newline syntax, to ensure that only "nonewline" is accepted. [Tcl SF Bug 985869], reported by Joe Mistachkin . 2004-07-15 Zoran Vasiljevic * generic/tclEvent.c (Tcl_Finalize): stuffed memory leak incurred by re-initializing of TSD slots after the last call to TclFinalizeThreadData (done from within Tcl_FinalizeThread()). We basically just repeat the TclFinalizeThreadData() once more before tearing down TSD keys in TclFinalizeSynchronization(). There should be more elaborate mechanism in place for handling such issues, based on thread cleanup handlers registered on the OS level. Such change requires much more work and would also require TIP because some visible parts of Tcl API would have to be modified. In the meantime, this will do. * generic/tclNotify.c (TclFinalizeNotifier): Added conditional notifier finalization based on the fact that an TclInitNotifier has been called for the current thread. This fixes the [Bug 770053] again. Hopefully this time w/o unwanted side-effects. 2004-07-15 Kevin Kenny * generic/tclLiteral.c (TclReleaseLiteral): Removed unused variable 'codePtr' to silence a message from VC++. 2004-07-15 Miguel Sofer * generic/tclCompile.c (TclCompileScript): * generic/tclLiteral.c (TclReleaseLiteral): fix for [Bug 467523], which resurfaced with the latest changes. The previous strategy was to have special code in TclReleaseLiteral to handle the self-references generated by empty scripts. The new approach avoids the self-reference altogether, by having empty scripts return an unshared literal. 2004-07-15 Zoran Vasiljevic * generic/tclEvent.c (NewThreadProc): Backout of changes to fix the [Bug 770053]. See SF bugreport for more info. 2004-07-11 Miguel Sofer * generic/tclBasic.c (Tcl_EvalEx): leak fix by dgp, release objv[objectsUsed] on error. 2004-07-11 Miguel Sofer * generic/tclParse.c (Tcl_SubstObj): leak fix by dgp, release result on error. 2004-07-11 Donal K. Fellows * generic/tclNamesp.c (BuildEnsembleConfig): Don't forget to clean out references when deleting the hash table. * generic/tclDictObj.c (Tcl_DictObjRemoveKeyList): Oops, forgot to delete value object when removing the hash entry. [Bug 989093 in part] 2004-07-11 Miguel Sofer * generic/tclExecute.c (TEBC): fixed leak of expandNestList objs when there is an error while an expansion is in progress (code added at checkForCatch). 2004-07-11 Vince Darley * generic/tclIOUtil.c: fix to 'cd' bug when vfs is active [tclvfs Bug 986944] - this bug recently introduced by some threading fixes. Need to work out how to add tests for this. 2004-07-10 Kevin Kenny * tests/clock.test (clock-2.11): Changed the test so that it isn't an infinite loop when run under valgrind on a slow virtual machine. Thanks to Miguel Sofer for the bug report. Also put in code to restore env(LC_TIME) after tests complete, silencing a warning from 'make TESTFLAGS="-debug 1" test'. 2004-07-08 Miguel Sofer * generic/tclBasic.c (DeleteInterpProc): reverted the modification of 3 days ago, as the leak of [Bug 983660] is now handled by the change in TclCleanupByteCode. * generic/tclCompile.c (TclCleanupByteCode): let each bytecode remove its references to literals at interp deletion, without updating the dying literal table. * generic/tclLiteral.c (TclDeleteLiteralTable): with the above change to TclCleanupByteCode, this function now removes a single reference to the literal object and cleans up its own structures. 2004-07-08 Kevin Kenny * win/tclWinInit.c (AppendEnvironment): Silenced a compilation warning about a type mismatch. 2004-07-07 Miguel Sofer * generic/tclCompile.c (TclCompileScript): fix for [Bug 458361]. Single-word scripts are compiled with an unshared cmdName to avoid shimmering between bytecode and cmdName reps. 2004-07-07 Don Porter * generic/tclCmdMZ.c (TclMergeReturnOptions): Simplified logic and removed potential memory leak. [Bug 986257]. 2004-07-07 Donal K. Fellows * tools/man2help2.tcl (setTabs, IPmacro): Added support for the more advanced *roff macros used in Tk's doc/bind.n * generic/tclObj.c (TclInitObjSubsystem): Declare all current object types. 2004-07-06 Don Porter * tests/cmdMZ.test (cmdMZ-return-2.17): Added a test that a word containing backslash-quoted value is treated correctly. * generic/tclCompile.c (TclWordKnownAtCompileTime): [Bug 986196] Corrected flaw above and the flaw that caused TCL_TOKEN_SIMPLE_WORDs to have their original word value copied ( "{a b}" ) rather than the actual value ( "a b" ). Thanks to Kevin Kenny for report and tests. 2004-07-06 Kevin B. Kenny * tests/cmdMZ.test (cmdMZ-return-2.15,cmdMZ-return-2.16): Added a test that a return code containing spaces is correctly returned. 2004-07-06 Donal K. Fellows * tools/man2html2.tcl (IPmacro, setTabs): Added support for the more advanced *roff macros used in Tk's doc/bind.n 2004-07-05 Miguel Sofer * generic/tclBasic.c (DeleteInterpProc): fix for [Bug 983660], found by pspjuth. Tear down the global namespace before freeing the interp handle, to allow the bytecodes to free their non-shared literals. * generic/tclLiteral.c (TclReleaseLiteral): moved special code for self-ref so that it is also used for non-shared literals. Possible bug found by inspection. 2004-07-03 Miguel Sofer * generic/tclExecute.c (ExprRoundFunc): * tests/expr-old.test (39.1): added support for wide integers to round(); [Bug 908375], reported by Hemang Lavana. 2004-07-03 Miguel Sofer * generic/tclCompile.h: * generic/tclInt.decls: * generic/tclIntDecls.h: * generic/tclStubInit.c: Moved declaration of TclCompEvalObj() from tclCompile.h to the internal stubs table, for compiler experimentation. 2004-07-02 Jeff Hobbs * generic/regcomp.c (stid): correct minor pointer size error * generic/tclPipe.c (TclCreatePipeline): applied TIP #202 patch that * doc/exec.n, tests/exec.test: adds 2>@1 as a special case redirection of stderr to the result output. 2004-07-02 Kevin B. Kenny * tests/io.test: Changed several tests to run the event loop rather than just calling [update] periodically, avoiding intermittent failures (usually in io-29.32) that stemmed from unreaped processes on Windows. * tests/winPipe.test (winpipe-1.11): Fixed a bug that caused test to fail if the path name of the working directory contained whitespace [Bug 678430] 2004-07-01 Vince Darley * tests/fileSystem.test: Added test for [Bug 970529] 2004-07-01 Donal K. Fellows * win/README.binary, win/README: Updated references to Tcl and Tk 8.4 to point to 8.5 instead. Thanks to Theo Verelst for spotting this. * generic/tcl.h: Added note to help prevent those changes from getting missed in the future. * doc/Namespace.3, doc/load.n, doc/Limit.3: Typo fixes and remove duplicate documentation. [Bug 983146] 2004-06-30 Don Porter * tests/fileSystem.test: Minor correction to new fileSystem-9.X tests so that they clean up temporary directories correctly. 2004-06-30 Vince Darley * doc/filename.n: clarified behaviour concerning trailing slashes in filenames [Bug 971976] * win/tclWinFile.c: * tests/fileSystem.test: fix and tests for [Bug 979879] 2004-06-30 Donal K. Fellows TIP#188 IMPLEMENTATION * doc/string.n, tests/string.test: Add 'wideinteger' to things * generic/tclCmdMZ.c (Tcl_StringObjCmd): that can be tested for with the [string is] subcommand. [Patch 940915, by Kevin Kenny] 2004-06-29 Don Porter * win/tclWinInit.c: Corrected reference counting flaw in recent changes. Thanks to Pat Thoyts. [Bug 981893]. 2004-06-29 Vince Darley * win/tclWin32Dll.c: fix to compilation with VC++ 5.2 2004-06-29 Donal K. Fellows * library/safe.tcl: Make sure that the temporary variable is local to the namespace and not inadvertently global. [Bug 981733] 2004-06-24 Donal K. Fellows * tests/unixNotfy.test: Modified constraints so that testing with a threaded tclsh (not tcltest) will not hang. 2004-06-23 Don Porter * generic/tclThreadStorage.c: Corrected type casting errors that led to calculation of a negative index value, thus accesses outside the threadStorageCache array, thus memory corruption. Crash observed on Mac OS X platform. 2004-06-23 Joe Mistachkin * generic/tclThread.c: Implements platform independent thread storage * generic/tclThreadStorage.c: mechanism and fixes associated bugs on platforms where there is limited thread local storage space (Win98/WinNT4). [Patch 976496] * generic/tclInt.decls: * generic/tclIntDecls.h: Added thread storage functions to the * generic/tclStubInit.c: internal stubs table. * unix/Makefile.in: * unix/configure: * unix/tcl.m4: * win/makefile.vc: * win/rules.vc: * win/Makefile.in: Modified the unix, VC++, and Cygwin build systems * win/configure: to include the new "tclThreadStorage.c" and the new * win/tcl.m4: USE_THREAD_STORAGE define. 2004-06-23 Pat Thoyts * tests/io.test: Added -force to 18.1 and 18.2. This was failing on WinXP. * tests/winFCmd.test: Added a cleanup to winFCmd-16.11 to avoid a failure in 16.12. * tests/eofchar.data: Added -kb option to ensure a binary checkout to win32 systems. This fixes a failure in io-61.1 * win/makefile.vc: fix for [Bug 977369] about launching tclsh to generate a tclConfig.sh with the nmake build system 2004-06-23 Kevin B. Kenny * tests/winDde.test (createChildProcess): Added a 200-ms delay (with the event loop live) when shutting down the test DDE server process. With the delay in place, nuisance failures of tests winDde-4.2, -6.5, and -6.6 appear to be much less frequent. [Bug 957449] 2004-06-23 Donal K. Fellows * tests/*.test: Standardize use of platform constraints. * unix/tclUnixInit.c (GetStackSize, TclpCheckStackSpace): * unix/tclUnixThrd.c (TclpThreadGetStackSize): Added code to check whether the C stack is about to be exceeded, from [Patch 746378] by Joe Mistachkin but with substantial revisions. 2004-06-22 Kevin Kenny * generic/tclEvent.c (NewThreadProc): Fixed broken build on Windows caused by missing TCL_THREAD_CREATE_RETURN. * tests/stack.test (stack-3.1): Corrected nuisance error in threaded builds. 2004-06-22 Zoran Vasiljevic * generic/tclEvent.c: * generic/tclInt.h: * unix/tclUnixNotfy.c: * unix/tclUnixThrd.c: * win/tclWinThrd.c: [Bug 770053]. See bug report for more information about what it does. * tests/unixNotfy.test: rewritten to use tcltest::threadReap to gracefully wait for the test thread to exit. Otherwise we got a race condition with main thread exiting before the test thread. This exposed the long-standing Tcl lib issue with resource garbage-collection on application exit. 2004-06-21 Mo DeJong * win/tclWin32Dll.c (DllMain, _except_dllmain_detach_handler) (TclpCheckStackSpace, _except_checkstackspace_handler) (TclWinCPUID, _except_TclWinCPUID_detach_handler): * win/tclWinChan.c (Tcl_MakeFileChannel) (_except_makefilechannel_handler): * win/tclWinFCmd.c (DoRenameFile, _except_dorenamefile_handler) (DoCopyFile, _except_docopyfile_handler): Rework pushing of exception handler function pointer so that compiling with gcc -O3 works. Remove empty function call to avoid compiler warning. Mark the DllMain function as noinline to avoid compiler error from duplicated asm labels in generated code. 2004-06-21 Donal K. Fellows * generic/tclThreadAlloc.c (Ptr2Block): Rewrote so as to maximize the chance of detecting and reporting a memory inconsistency without relying on things being consistent. [Bug 975895] 2004-06-18 Don Porter * tests/load.test: Relaxed strictness of error message matching for test load-2.3 so that it will pass on Mac OSX. * generic/tclEncoding.c: Static TclFindEncodings -> FindEncodings. * generic/tclInt.h: Updated TclpFindExecutable() so that failed * generic/tclUtil.c: attempts to find the executable are saved * unix/tclUnixFile.c: just as successful finds are. [Patch 966053] * unix/tclUnixTest.c: 2004-06-18 Kevin B. Kenny * tests/winFCmd.test (winFCmd-16.12): Changed test to compute the target directory, so as not to fail if the user's HOME isn't the root. 2004-06-19 Daniel Steffen * unix/tcl.m4: autoconf 2.5 fixes in Darwin section. * unix/configure: autoconf-2.57 2004-06-18 Donal K. Fellows * unix/tclUnixInit.c (localeTable): Added some more locale to encoding mapping info from Jim Huang * generic/tclInt.h (PendingObjData,TclFreeObjMacro,etc): * generic/tclObj.c (TclFreeObj): Added scheme for making TclFreeObj() avoid blowing up the C stack when freeing up very large object trees. [Bug 886231] * win/tclWinInit.c (SetDefaultLibraryDir): Fix logic, simplify and add comments. 2004-06-17 Don Porter * generic/tclObj.c: Added missing space in panic message. * win/tclWinInit.c: Inform [tclInit] about the default library directory via the ::tclDefaultLibrary variable. This should correct a problem with my 2004-06-11 commit. Better solutions still in the works. Thanks to Joe Mistachkin for pointing out the breakage. 2004-06-16 Don Porter * doc/library.n: Moved variables ::auto_oldpath and * library/auto.tcl: ::unknown_pending into ::tcl namespace. * library/init.tcl: [Bugs 808319, 948794] 2004-06-15 Donal K. Fellows * doc/binary.n: Added some notes to the documentation of the 'a' format to address the point raised in [RFE 768852]. 2004-06-15 Jeff Hobbs * unix/tclConfig.sh.in (TCL_EXTRA_CFLAGS): set to @CFLAGS@, which is the configure-time CFLAGS. Addendum to m4 change on 2004-05-26. 2004-06-14 Kevin Kenny * win/Makefile.in: Corrected compilation flags for tclPkgConfig.c so that it doesn't require Stubs. * generic/tclBasic.c (Tcl_CreateInterp): Removed comment stating that TclInitEmbeddedConfigurationInformation needs Stubs; with the change above, the comment is now erroneous. 2004-06-11 Don Porter * doc/Encoding.3: Removed bogus claims about tcl_libPath. * generic/tclInterp.c (Tcl_Init): Stopped setting the tcl_libPath variable. [tclInit] can get all its directories without it. * tests/unixInit.test: Modified test code that made use of tcl_libPath variable. * unix/tclUnixInit.c: Stopped setting the tclDefaultLibrary variable, execept on the Mac OS X platform with HAVE_CFBUNDLE. In that configuration we should seek some way to make use of the TIP 59 facilities and get rid of that usage of tclDefaultLibrary as well. * generic/tclInterp.c: Updated [tclInit] to make $env(TCL_LIBRARY) an absolute path, and to include the scriptdir,runtime configuration value on the search path for init.tcl. * unix/tclUnixInit.c: The routines Tcl_Init() and TclSourceRCFile() * win/tclWinInit.c: had identical implementations for both win and * generic/tclInterp.c: unix. Moved to a single generic implementation. * generic/tclMain.c: * library/init.tcl: * generic/tclInitScript.h (removed): * unix/Makefile.in: * win/tcl.dsp: * unix/configure.in: Updated TCL_PACKAGE_PATH value to handle * win/configure.in: --libdir configuration. * unix/configure.in: autoconf-2.57 * win/configure.in: * generic/tclBasic.c (Tcl_CreateInterp): Moved call to TclInitEmbeddedConfigurationInformation() earlier in Tcl_CreateInterp() so that other parts of interp creation and initialization may access and use the config values. 2004-06-11 Kevin Kenny * win/tclAppInit.c: Restored the 'setargv' procedure when compiling with mingw. Apparently, the command line parsing in mingw doesn't work as well as that in vc++, and the result was (1) that winPipe-8.19 failed, and (2) that 'make test' would work at all only with TESTFLAGS='-singleproc 1'. [Bug 967195] 2004-06-10 Zoran Vasiljevic * generic/tclIOUtil.c: removed forceful setting of the private cached current working directory rep from within the Tcl_FSChdir(). We delegate this task to the Tcl_FSGetCwd() which does this task anyway. The relevant code is still present but disabled temporarily until the change proves correct. The Tcl test suite passes all test with the given change so I suppose it is good enough. 2004-06-10 Don Porter * unix/tclUnixInit.c (TclpInitLibraryPath): Disabled addition of * win/tclWinInit.c (TclpInitLibraryPath): relative-to-executable directories to the library search path. A first step in reform of Tcl's startup process. ***POTENTIAL INCOMPATIBILITY*** Attempts to directly run ./tclsh or ./tcltest out of a build directory will either fail, or will make use of an installed script library in preference to the one in the source tree. Use `make shell` or `make runtest` instead. * tests/unixInit.test: Modified tests to suit above changes. * generic/tclPathObj.c: Corrected [file tail] results when operating on a path produced by TclNewFSPathObj(). [Bug 970529] 2004-06-09 Zoran Vasiljevic * generic/tclIOUtil.c: partially corrected [Bug 932314]. Also corrected return values of Tcl_FSChdir() to reflect those of the underlying platform-specific call. Originally, return codes were mixed with those of Tcl. 2004-06-08 Miguel Sofer * generic/tclCompile.c: * generic/tclExecute.c: handle warning [Bug 969066] 2004-06-08 Donal K. Fellows * generic/tclHash.c (RebuildTable): Move declaration of variable so it is only declared when it is used. [Bug 969068] 2004-06-07 Donal K. Fellows * doc/lsearch.n: Added correct option to example. [Bug 968219] 2004-06-05 Kevin B. Kenny * generic/tcl.h: Corrected Tcl_WideInt declarations so that the mingw build works again. * generic/tclDecls.h: Changes to the tests for clock * generic/tclInt.decls: frequency in Tcl_WinTime so * generic/tclIntDecls.h: that any clock frequency is * generic/tclIntPlatDecls.h: accepted provided that all * generic/tclPlatDecls.h: CPU's in the system share a * generic/tclStubInit.c: common chip, and hence, * tests/platform.test (platform-1.3): presumably, a common clock. * win/tclWin32Dll.c (TclWinCPUID): This change necessitated a * win/tclWinTest.c (TestwincpuidCmd) small burst of assembly code * win/tclWinTime.c (Tcl_GetTime): to read CPU ID information, which was added as TclWinCPUID in the internal Stubs. To test this code in the common case of a single-processor machine, a 'testwincpuid' command was added to tclWinTest.c, and a test case in platform.test. Thanks to Jeff Godfrey and Richard Suchenwirth for reporting this bug. [Bug 976722] 2004-06-04 Don Porter * generic/tcl.h: Restored #include to tcl.h, rejecting the "fix" for "Bug" 945570. Tcl_FSSeek() needs the values of SEEK_SET, etc. and too many extensions rely on tcl.h providing stdio.h for them. 2004-06-02 Jeff Hobbs * win/tclWinFile.c (TclpFindExecutable): when using GetModuleFileNameA (Win9x), convert from CP_ACP to WCHAR then convert back to utf8. Adjunct to 2004-04-07 fix. 2004-06-02 David Gravereaux * tests/winPipe.test (winpipe-6.1): blocking set to 1 before closing to ensure we get an exitcode. The windows pipe channel driver doesn't differentiate between a blocking and non-blocking close just yet, but will soon. Part of [Bug 947693] 2004-06-02 Vince Darley * doc/file.n: fix to documentation of 'file volumes' (Bug 962435) 2004-06-01 David Gravereaux * win/makefile.vc: check for either MSDEVDIR or MSVCDIR being in the environment, for VC7. [Bug 942214] * generic/tclIO.c (Tcl_SetChannelOption): -buffersize wasn't understanding hexidecimal notation nor was reporting number conversion errors. The behavior to silently ignore settings outside the acceptable range of Tcl_SetChannelBufferSize (<10 or >1M) is unchanged. This silent ignoring behavior might be up for review soon. 2004-05-30 David Gravereaux * win/tclWinPipe.c: * win/tclWinPort.h: Reworked the win implementation of Tcl_WaitPid to support exitcodes in the 'signed short' range. Even though this range is non-portable, it is valid on windows. Detection of exception codes are now more accurate. Previously, an application that exited with ExitProcess((DWORD)-1); was improperly reported as exiting with SIGABRT. 2004-05-30 Donal K. Fellows * generic/tclInterp.c: Added comments describing the purposes of each function in the limit implementation and rewrote the names of some non-public functions for greater clarity of purpose. * doc/interp.n: Added note about what happens when a limited interpreter creates a slave interpreter. * doc/Limit.3: Added manual page for the resource limit subsystem's C API. [Bug 953903] 2004-05-29 Joe English * doc/global.n, doc/interp.n, doc/lrange.n: Fix minor markup errors. 2004-05-28 Donal K. Fellows * doc/*.n: Added examples to many (too many to list) more man pages. 2004-05-25 Miguel Sofer * generic/tclExecute.c: * generic/tclVar.c: using (ptrdiff_t) instead of (int) casting to correct compiler warnings [Bug 961657], reported by Bob Techentin. 2004-05-27 Kevin B. Kenny * tests/clock.test: Added a single test for the presence of %G in [clock format], and conditioned out the clock-10.x series if they're all going to fail because of a broken strftime() call. [Bug 961714] 2004-05-27 Donal K. Fellows * generic/tclHash.c (CompareStringKeys): Added #ifdef to allow people to instruct this function to use strcmp(). [FRQ 951168] * generic/tclVar.c: Moved declarations into #if guards so they only happen when required. * unix/tclUnixPort.h: Guard declaration of strtod() so it is only enabled when we don't have a declaration in stdlib.h * unix/tclUnixThrd.c (Tcl_CreateThread): Added declarations * unix/tclUnixTest.c (AlarmHandler): and casts so that * unix/tclUnixChan.c (TtyModemStatusStr): all functions are * generic/tclScan.c (Tcl_ScanObjCmd): defined before use * generic/tclDictObj.c (InvalidateDictChain): and no cross-type * generic/tclCmdMZ.c (Tcl_StringObjCmd): uses are performed. The overall effect is to make building with gcc with the additional flags -Wstrict-prototypes -Wmissing-prototypes produce no increase in the total number of warnings (except for main(), which is undeclared for traditional reasons.) 2004-05-26 Jeff Hobbs * unix/Makefile.in: Rework configure ordering to TCL_LINK_LIBS, * unix/tcl.m4: ENABLE_SHARED, CONFIG_CFLAGS, & ENABLE_SYMBOLS * unix/configure: before TCL_EARLY_FLAGS and TCL_64BIT_FLAGS * unix/configure.in: (about 400 lines earlier) in configure.in. This forces CFLAGS configuration to be done before many tests, which is needed for 64-bit builds and may affect other builds. Also make CONFIG_CFLAGS append to CFLAGS directly instead of using EXTRA_CFLAGS, and have LDFLAGS append to any existing value. [Bug 874058] * unix/dltest/Makefile.in: change EXTRA_CFLAGS to DEFS 2004-05-26 Don Porter * library/tcltest/tcltest.tcl: Correction to debug prints and testing * library/tcltest/pkgIndex.tcl: if TCLTEST_OPTIONS value. Corrected * tests/tcltest.test: double increment of numTestFiles in -singleproc 1 configurations. Updated tcltest-19.1 to tcltest 2.1 behavior. Corrected tcltest-25.3 to not falsely report a failure in tcltest.test. Bumped to tcltest 2.2.6. [Bugs 960560, 960926] 2004-05-25 Jeff Hobbs * doc/http.n (http::config): add -urlencoding option (default utf-8) * library/http/http.tcl: that specifies encoding conversion of * library/http/pkgIndex.tcl: args for http::formatQuery. Previously * tests/http.test: undefined, RFC 2718 says it should be utf-8. 'http::config -urlencoding {}' returns previous behavior, which will throw errors processing non-latin-1 chars. Bumped http package to 2.5.0. 2004-05-25 Donal K. Fellows * generic/tclInterp.c (DeleteScriptLimitCallback): Move all deletion of script callback hash table entries to happen here so the entries are correctly removed at the right time. [Bug 960410] 2004-05-25 Miguel Sofer * docs/global.n: added details for qualified variable names [Bug 959831] 2004-05-25 Miguel Sofer * generic/tclNamesp.c (Tcl_FindNamespaceVar): * tests/namespace.test (namespace-17.10-12): reverted commit of 2004-05-23 and removed the tests, as it interferes with the varname resolver and there are apps that break (AlphaTk). A fix will have to wait for Tcl9. * generic/tclVar.c: Caching of namespace variables disabled: no simple way was found to avoid interfering with the resolver's idea of variable existence. A cached varName may keep a variable's name in the namespace's hash table, which is the resolver's criterion for existence. * tests/namespace.c (namespace-17.10): testing for interference between varname caching and name resolver. 2004-05-25 Kevin Kenny * tests/winFCmd.test: Correct test for the presence of a CD-ROM so that it doesn't misdetect some other sort of filesystem with a write-protected root as being a CD-ROM drive. [Bug 918267] 2004-05-25 Don Porter * tests/winPipe.test: Protect against path being set * tests/unixInit.test: Unset path when done. * tests/unload.test (unload-3.1): Verify [pkgb_sub] does not exist. Delete interps when done. * tests/stringComp.test: stop re-use of string.test test names * tests/regexpComp.test: stop re-use of regexp.test test names * tests/namespace.test (namespace-46.3): Verify [p] does not exist. * tests/http.test: Clear away the custom [bgerror] when done. * tests/io.test: Take care to use namespace variables. * tests/autoMkindex.test (autoMkindex-5.2): Use variable "result" that gets cleaned up. * tests/exec.test: Clean up the "path" array. * tests/interp.test (interp-9.3): Initialize res, so prior values cannot make the test fail. * tests/execute.test (execute-8.1): Updated to remove the trace set on ::errorInfo. When left in place, that trace can cause later tests to fail. 2004-05-25 Donal K. Fellows * generic/tclBasic.c: Removed references to Tcl_RenameCommand from * generic/tcl.h: comments. [Bug 848440, second part] * tests/fCmd.test: Rewrote tests that failed consistently on NFS so they either succeed (through slightly more liberal matching of the results) or are constrained to not run. [Bug 931312] * doc/bgerror.n: Use idiomatic open flags for working with log files. [Bug 959602] 2004-05-24 Jeff Hobbs * generic/tclExecute.c (VerifyExprObjType): use GET_WIDE_OR_INT to properly have tclIntType used for smaller values. This corrects [TclX Bug 896727] and any other 3rd party extension that created math functions but was not yet WIDE_INT aware in them. 2004-05-24 Donal K. Fellows * generic/tclInterp.c (TclInitLimitSupport): Made limits work on platforms where sizeof(void*)!=sizeof(int). [Bug 959193] 2004-05-24 Miguel Sofer * doc/set.n: accurate description of name resolution process, referring to namespace.n for details [Bug 959180] 2004-05-23 Miguel Sofer * generic/tclNamesp.c (Tcl_FindNamespaceVar): [Bug 959052] fixed, insuring that no "zombie" variables are found. * generic/tclVar.c (TclLookupSimpleVar): comments re [Bug 736729] (predecessor of [Bug 959052]) removed. * tests/namespace.test: added tests 17.10-12 The patch modifies non-documented behaviour, and passes every test in the testsuite. However, scripts relying on the old behaviour may break. Note that the only behaviour change concerns the creative writing of unset variables. More precisely, which variable will be created when neither a namespace variable nor a global variable by that name exists, as defined by [info vars]. The new behaviour is that the namespace resolution process deems a variable to exist exactly when [info vars] finds it - ie, either it has value, or else it was "fixed" by a call to [variable]. Note: this patch was removed on 2002-05-25. 2004-05-22 Miguel Sofer * generic/tclVar.c (TclObjLookupVar, TclObjUnsetVar2): fix for new (in tcl8.4) exteriorisations of [Bug 736729] due to the use of tclNsVarNameType obj types. Reenabling the use of this objType ("VAR ref absolute" benchmark down to 66 ms, from 230). Added comments in TclLookupSimpleVar explaining my current understanding of [Bug 736729]. 2004-05-22 Miguel Sofer * generic/tclVar.c: fix for [Bug 735335]. The use of tclNsVarNameType objs is still disabled, pending resolution of [Bug 736729]. 2004-05-21 Miguel Sofer * tests/namespace.test (namespace-41.3): removed the {knownBug} constraint: [Bug 231259] is closed since nov 2001, and the fix of [Bug 729692] (INST_START_CMD) makes the test succeed. 2004-05-21 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Move a few declarations a short distance so pre-C99 compilers can cope. Also fix so TCL_COMPILE_DEBUG path compiles... 2004-05-21 Miguel Sofer * generic/tclExecute.c (TclExecuteByteCode): reorganised TEBC automatic variables, defining them in tight blocks instead of at the function level. This has three purposes: - it simplifies the analysis of individual instructions - it is preliminary work to the non-recursive engine - it allows a better register allocation by the optimiser; under gcc3.3, this results in up to 10% runtime in some tests 2004-05-20 Donal K. Fellows * generic/tclInterp.c (TclLimitRemoveAllHandlers): * generic/tclBasic.c (DeleteInterpProc): * tests/interp.test (interp-34.7): Ensure that all limit callbacks are deleted when their interpreters are deleted. [Bug 956083] 2004-05-19 Kevin B. Kenny * win/tclWinFile.c (TclpMatchInDirectory): fix for an issue where there was a sneak path from Tcl_DStringFree to SetErrorCode(0). The result was that the error code could be reset between a call to FindFirstFileEx and the check of its status return, leading to a bizarre error return of {POSIX unknown {No error}}. (Found in unplanned test - no incident logged at SourceForge.) 2004-05-19 Donal K. Fellows * tests/interp.test (interp-34.3): Rewrite this test to see if a time limit can catch a tight bytecode loop, a maximally aggressive denial-of-service attack. * generic/tclInterp.c (Tcl_LimitCheck): Fix the sense of checks to see whether a time limit has been extended. * tests/*.test: Many minor fixes, including ensuring that every test is run (so constraints control whether the test is doing anything) and making sure that constraints are always set using the API instead of poking around inside tcltest's internal datastructures. Also got rid of all trailing whitespace lines from the test suite! 2004-05-19 Andreas Kupries * generic/tclIO.c: Fixed [SF Tcl Bug 943274]. This is the same problem * generic/tclIO.h: as [SF Tcl Bug 462317], see ChangeLog entry 2001-09-26. The fix done at that time is incomplete. It is possible to get around it if the actual read operation is defered and not executed in the event handler itself. Instead of tracking if we are in an read caused by a synthesized fileevent we now track if the OS has delivered a true event = actual data and bypass the driver if a read finds that there is no actual data waiting. The flag is cleared by a short or full read. ***POTENTIAL INCOMPATIBILITY*** for channel drivers. 2004-05-17 Vince Darley * generic/tclPathObj.c: fix to (Bug 956063) in 'file dirname'. * tests/cmdAH.test: added test for this bug. * doc/FileSystem.3: better documentation of refCount requirements of some FS functions (Bug 956126) 2004-05-19 Donal K. Fellows * generic/tclTest.c (TestgetintCmd): Made the tests in get.test check * tests/get.test: Tcl_GetInt() since the core now avoids that function. 2004-05-18 Kevin B. Kenny * compat/strftime.c (_fmt, ISO8601Week): * doc/clock.n: * tests/clock.test: Major rework to the handling of ISO8601 week numbers. Now passes all the %G and %V test cases on Windows, Linux and Solaris [Bugs 500285, 500389, and 852944] 2004-05-18 Donal K. Fellows * doc/append.n, doc/upvar.n: Added example. 2004-05-18 David Gravereaux * win/makefile.vc: now generates a tclConfig.sh from Pat Thoyts [Patch 909911] 2004-05-18 Donal K. Fellows * doc/lsearch.n: Improve clarity (based on [Patch 955361] by Peter Spjuth) * tools/man2help2.tcl (macro,SHmacro): Added support for subsection (.SS) header macros. * doc/interp.n: Added user documentation for the TIP#143 resource limits and some examples. * generic/tclInterp.c (Tcl_LimitCheck, Tcl_LimitTypeReset): Reset the limit-exceeded flag when removing a limit. 2004-05-18 Miguel Sofer * generic/tclExecute.c (TclExecuteByteCode): added comments to classify the variables according to their use in TEBC. 2004-05-17 Donal K. Fellows * doc/global.n, doc/uplevel.n: Added an example. * tests/info.test (info-3.1): Corrected test result back to what it used to be in Tcl 7.* now that command counts are being correctly kept * generic/tclExecute.c (TEBC:INST_START_CMD): Make sure that the command-count is always advanced. Allows TIP#143 limits to tell that work is being done. * doc/list.n: Updated example to fit with the unified format. * doc/seek.n: Added some examples. 2004-05-17 Vince Darley * win/tclWinFile.c: * tests/cmdAH.test: fix to (Bug 954263) where 'file executable' was case-sensitive. 2004-05-17 Donal K. Fellows * doc/OpenFileChnl.3: Documented type of 'offset' argument to Tcl_Seek was wrong. [Bug 953374] 2004-05-16 Miguel Sofer * generic/tclExecute.c (TclExecuteByteCode): remove one level of indirection for compiledLocals addressing. 2004-05-16 Miguel Sofer * generic/tclExecute.c (INST_CALL_FUNC1): bugfix; restored (DE)CACHE_STACK_INFO pair around the call - the user defined math function could cause a recursive call to TEBC. 2004-05-16 Miguel Sofer * generic/tclBasic.c (Tcl_DeleteInterp): * generic/tclExecute.c (INST_START_CMD): interp deletion now modifies the compileEpoch, eliminating the need for the check for interp deletion in INST_START_CMD. 2004-05-16 Miguel Sofer * generic/tclCompile.h: * generic/tclCompile.c: * generic/tclExecute.c: changed implementation of {expand}, last chance while in alpha as ... ***POTENTIAL INCOMPATIBILITY*** Scripts precompiled with ProComp under previous tcl8.5a versions may malfunction due to changed instruction numbers for INST_LIST_INDEX_IMM, INST_LIST_RANGE_IMM and INST_START_CMD. 2004-05-14 Kevin B. Kenny * generic/tclInt.decls: Promoted TclpLocaltime and TclpGmtime * generic/tclIntDecls.h: from Unix-specific stubs to the generic * generic/tclIntPlatDecls.h: internal Stubs table. Reran 'genstubs' * generic/tclStubInit.c: * unix/tclUnixPort.h: * generic/tclClock.c: Changed a buggy 'GMT' timezone specification to the correct 'GMT0'. [Bug 922848] * unix/tclUnixThrd.c: Moved TclpGmtime and TclpLocaltime to unix/tclUnixTime.c where they belong. * unix/tclUnixTime.c (TclpGmtime, TclpLocaltime, TclpGetTimeZone, ThreadSafeGMTime [removed], ThreadSafeLocalTime [removed], SetTZIfNecessary, CleanupMemory): Restructured to make sure that the same mutex protects all calls to localtime, gmtime, and tzset. Added a check in front of those calls to make sure that the TZ env var hasn't changed since the last call to tzset, and repeat tzset if necessary. [Bug 942078] Removed a buggy test of the Daylight Saving Time information in 'gettimeofday' in favor of applying 'localtime' to a known value. [Bug 922848] * tests/clock.test (clock-3.14): Added test to make sure that changes to $env(TZ) take effect immediately. * win/tclWinTime.c (TclpLocaltime, TclpGmtime): Added porting layer for 'localtime' and 'gmtime' calls. 2004-05-14 Miguel Sofer * generic/tclExecute.c: * generic/tclCompile.h: the math functions receive a pointer to top of the stack (tosPtr) instead of the execution environment (eePtr). First step towards a change in the execution stack management - it is now only used within TEBC. 2004-05-13 Donal K. Fellows TIP#143 IMPLEMENTATION * generic/tclExecute.c (TclCompEvalObj, TclExecuteByteCode): * generic/tclBasic.c (TclEvalObjvInternal): Enable limit checking. * generic/tclInterp.c (Tcl_Limit*): Public limit API. * generic/tcl.decls: * tests/interp.test: Basic tests of command limits. * doc/binary.n: TIP#129 IMPLEMENTATION [Patch 858211] * generic/tclBinary.c: Note that the test suite probably has many more * tests/binary.test: failures now due to alterations in constraints. 2004-05-12 Miguel Sofer Optimisations for INST_START_CMD [Bug 926164]. * generic/tclCompile.c (TclCompileScript): avoid emitting INST_START_CMD as the first instruction in a bytecoded Tcl_Obj. It is not needed, as the checks are done before calling TEBC. * generic/tclExecute.c (TclExecuteByteCode): runtime peephole optimisation: check at INST_POP if the next instruction is INST_START_CMD, in which case we fall through. 2004-05-11 Donal K. Fellows * doc/split.n, doc/join.n: Updated examples and added more. 2004-05-11 Vince Darley * doc/glob.n: documented behaviour of symbolic links with 'glob -types d' (Bug 951489) 2004-05-11 Donal K. Fellows * doc/scan.n: Updated the examples to be clearer about their relevance to the scan command. 2004-05-10 Donal K. Fellows * doc/scan.n: Added examples. 2004-05-10 David Gravereaux * win/tclWinPipe.c (BuildCommandLine): Moved non-obvious appending logic to outside the loop and added commentary for its purpose. Also use the existence of contents in the linePtr rather than the scratch DString post the append, as this more clear. (TclpCreateProcess): When under NT, with no console, and executing a DOS application, the path priming does not need an ending space as BuildCommandLine() will do this for us. 2004-05-08 Vince Darley * generic/tclFileName.c: * generic/tclIOUtil.c: remove some compiler warnings on MacOS X. 2004-05-07 Chengye Mao * win/tclWinPipe.c: refixed bug 789040 re-entered in rev 1.41. Let's be careful and don't re-enter previously fixed bugs. 2004-05-08 Donal K. Fellows * doc/format.n: Added examples. 2004-05-07 Miguel Sofer * doc/unset.n: added upvar.n to the "see also" list 2004-05-07 Reinhard Max * generic/tclEncoding.c: * tests/encoding.test: added support and tests for translating embedded null characters between real nullbytes and the internal representation on input/output [Bug 949905]. 2004-05-07 Vince Darley * generic/tclFileName.c: * generic/tclIOUtil.c: * generic/tclFileSystem.h: * tests/fileSystem.test: fix for [Bug 943995], in which vfs-registered root volumes were not handled correctly as glob patterns in all circumstances. 2004-05-06 Miguel Sofer * generic/tclInt.h: * generic/tclObj.c (TclFreeObj): made TclFreeObj use the new macro TclFreeObjMacro(), so that the allocation and freeing of Tcl_Obj is defined in a single spot (the macros in tclInt.h), with the exception of the TCL_MEM_DEBUG case. The #ifdef logic for the corresponding macros has been reformulated to make it clearer. 2004-05-05 Donal K. Fellows * doc/break.n, doc/continue.n, doc/for.n, doc/while.n: More examples. 2004-05-05 Don Porter * tests/unixInit.test (unixInit-2.10): Test correction for Mac OSX. Be sure to consistently compare normalized path names. Thanks to Steven Abner (tauvan). [Bug 948177] 2004-05-05 Donal K. Fellows * doc/CrtObjCmd.3: Remove reference to Tcl_RenameCommand; there is no such API. [Bug 848440] 2004-05-05 David Gravereaux * win/tclWinSock.c (SocketEventProc) : connect errors should fire both the readable and writable handlers because this is how it works on UNIX [Bug 794839] * generic/tclEncoding.c (TclFinalizeEncodingSubsystem): FreeEncoding(systemEncoding); moved to before the hash table iteration as it was causing a double free attempt under some conditions. * win/coffbase.txt: Added the tls extension to the list of preferred load addresses. 2004-05-04 Jeff Hobbs * tests/fileSystem.test (filesystem-1.39): replace 'file volumes' * tests/fileName.test (filename-12.9,10): lindex with direct C:/ hard-coded because A:/ was being used and that is empty for most. * tests/winFCmd.test (winFCmd-16.12): test volumerelative $HOME 2004-05-04 Don Porter * generic/tclAlloc.c: Make sure Tclp*Alloc* routines get * generic/tclInt.h: declared in the TCL_MEM_DEBUG and * generic/tclThreadAlloc.c: TCL_THREADS configuration. [Bug 947564] * tests/tcltest.test: Test corrections for Mac OSX. Thanks to Steven Abner (tauvan). [Bug 947440] 2004-05-04 Donal K. Fellows * generic/tclEvent.c (TclSetLibraryPath): Suppress a warning. 2004-05-03 Andreas Kupries * Applied [Patch 868853], fixing a mem leak in TtySetOptionProc. Report and Patch provided by Stuart Cassoff . 2004-05-03 Miguel Sofer * generic/tclProc.c (TclCreateProc): comments corrected. 2004-05-03 Miguel Sofer * generic/tclCompile.c (TclCompileScript): setting the compilation namespace outside of the loop. 2004-05-03 Miguel Sofer * generic/tclCompile.c: * generic/tclInt.h: reverted fix for [Bug 926445] of 2004-04-02, restoring TCL_ALIGN to the header file. Todd Helfter reported that the macro is required by tbcload. 2004-05-03 Kevin Kenny * win/tclWin32Dll.c (TclpCheckStackSpace): * tests/stack.test (stack-3.1): Fix for undetected stack overflow in TclReExec on Windows. [Bug 947070] 2004-05-03 Don Porter * library/init.tcl: Corrected unique prefix matching of interactive command completion in [unknown]. [Bug 946952] 2004-05-02 Miguel Sofer * generic/tclProc.c (TclObjInvokeProc): * tests/proc.test (proc-3.6): fix for bad quoting of multi-word proc names in error messages [Bug 942757] 2004-04-30 Donal K. Fellows * doc/glob.n, doc/incr.n, doc/set.n: More examples. * doc/if.n, doc/rename.n, doc/time.n: 2004-04-30 Don Porter * generic/tclInt.h: Replaced Kevin Kenny's temporary * generic/tclThreadAlloc.c: fix for Bug 945447 with a cleaner, more permanent replacement. 2004-04-30 Kevin B. Kenny * generic/tclThreadAlloc.c: Added a temporary (or so I hope!) inclusion of "tclWinInt.h" to avoid problems when compiling on Win32-VC++ with --enable-threads. [Bug 945447] 2004-04-30 Donal K. Fellows * doc/puts.n: Added a few examples. 2004-04-29 Don Porter * tests/execute.test (execute-8.2): Avoid crashes when there is limited system stack space (threads-enabled). 2004-04-28 Miguel Sofer * doc/global.n: * doc/upvar.n: * generic/tclVar.c (ObjMakeUpvar): * tests/upvar.test (upvar-8.11): * tests/var.test (var-3.11): Avoid creation of unusable variables: [Bug 600812] [TIP 184]. 2004-04-28 Donal K. Fellows * doc/lsearch.n: Fixed fault in documentation of -index option [943448] 2004-04-26 Don Porter * unix/tclUnixFCmd.c (TclpObjNormalizePath): Corrected improper positioning of returned checkpoint. [Bug 941108] 2004-04-26 Donal K. Fellows * doc/open.n, doc/close.n: Updated (thanks to David Welton) to be clearer about pipeline errors and added example to open(n) that shows simple pipeline use. [Patches 941377,941380] * doc/DictObj.3: Added warning about the use of Tcl_DictObjDone and an example of use of iteration. [Bug 940843] * doc/Thread.3: Reworked to remove references to testing interfaces and instead promote the use of the Thread package. [Patch 932527] Also reworked and reordered the page for better readability. 2004-04-25 Don Porter * generic/tcl.h: Removed obsolete declarations and #include's. * generic/tclInt.h: [Bugs 926459, 926486] 2004-04-24 David Gravereaux * win/tclWin32Dll.c (DllMain): Added DisableThreadLibraryCalls() for the DLL_PROCESS_ATTACH case. We're not interested in knowing about DLL_THREAD_ATTACH, so disable the notices. 2004-04-24 Daniel Steffen * generic/tclPort.h: * macosx/Makefile: * unix/Makefile.in: followup on tcl header reform [FR 922727]: removed use of relative #include paths in tclPort.h to allow installation of private headers outside of tcl source tree; added 'unix' dir to compiler header search path; add newly required tcl private headers to Tcl.framework on Mac OSX. 2004-04-23 Andreas Kupries * generic/tclIO.c (Tcl_SetChannelOption): Fixed [SF Tcl Bug 930851]. When changing the eofchar we have to zap the related flags to prevent them from prematurely aborting the next read. 2004-04-25 Vince Darley * generic/tclPathObj.c: fix to [Bug 940281]. Tcl_FSJoinPath will now always return a valid Tcl_Obj when the input is valid. * generic/tclIOUtil.c: fix to [Bug 931823] for a more consistent Tcl_FSPathSeparator() implementation which allows filesystems not to implement their Tcl_FSFilesystemSeparatorProc if they wish to use the default '/'. Also fixed associated memory leak seen with, e.g., tclvfs package. * doc/FileSystem.3: documented Tcl_FSJoinPath return values more clearly, and Tcl_FSFilesystemSeparatorProc requirements. 2004-04-23 David Gravereaux * win/tclWin32Dll.c: Removed my mistake from 4/19 of adding an exit handler to TclWinInit. TclWinEncodingsCleanup called from TclFinalizeFilesystem does the Tcl_FreeEncoding for us. * win/tclWinChan.c (Tcl_MakeFileChannel): Case for CloseHandle returning zero and not throwing a RaiseException(EXCEPTION_INVALID_HANDLE) now being done. 2004-04-22 David Gravereaux * generic/tclEvent.c: TclSetLibraryPath's use of caching the stringrep of the pathPtr object to TclGetLibraryPath called from another thread was ineffective if the original's stringrep had been invalidated as what happens when it gets muted to a list. * win/tclWinTime.c: If the Tcl_ExitProc (StopCalibration) is called from the stack frame of DllMain's PROCESS_DETACH, the wait operation should timeout and continue. * generic/tclInt.h: * generic/tclThread.c: * generic/tclEvent.c: * unix/tclUnixThrd.c: * win/tclWinThrd.c: Provisions made so masterLock, initLock, allocLock and joinLock mutexes can be recovered during Tcl_Finalize. 2004-04-22 Donal K. Fellows * doc/switch.n: Reworked the examples to be more systematically named and to cover some TIP#75 capabilities. * doc/cd.n: Documentation clarification from David Welton. * doc/exec.n: Added some examples, Windows ones from Arjen Markus and Unix ones by myself. 2004-04-21 Donal K. Fellows * doc/Hash.3: Added note to Tcl_{First,Next}HashEntry docs that deleting the element they return is supported (and is in fact the only safe update you can do to the structure of a hashtable while an iteration is going over it.) * doc/bgerror.n: Added example from David Welton. [Patch 939473] * doc/after.n: Added examples from David Welton. [Patch 938820] 2004-04-19 David Gravereaux * win/tclWin32Dll.c: Added an exit handler in TclWinInit() so tclWinTCharEncoding could be freed during Tcl_Finalize(). * generic/tclEncoding.c: Added FreeEncoding(systemEncoding) in TclFinalizeEncodingSubsystem because its ref count was incremented in TclInitEncodingSubsystem. 2004-04-19 Donal K. Fellows * doc/read.n: Added example from David Welton. [Patch 938056] 2004-04-19 Kevin B. Kenny * generic/tclObj.c (Tcl_GetDoubleFromObj) Corrected "short circuit" conversion of int to double. Reported by Jeff Hobbs on the Tcl'ers Chat. 2004-04-16 Donal K. Fellows * doc/lreplace.n, doc/lrange.n, doc/llength.n: More examples for * doc/linsert.n, doc/lappend.n: the documentation. 2004-04-16 Vince Darley * doc/FileSystem.3: Corrected documentation of Tcl_FSUtime, and the corresponding filesystem driver Tcl_FSUtimeProc. [Bug 935838] 2004-04-16 Donal K. Fellows * doc/socket.n: Added example from [Patch 936245]. * doc/gets.n: Added example based on [Patch 935911]. 2004-04-15 Donal K. Fellows * generic/tclClock.c (Tcl_ClockObjCmd): Minor fault in a [clock clicks] error message. 2004-04-07 Jeff Hobbs * win/tclWinInit.c (TclpSetInitialEncodings): note that WIN32_CE is also a unicode platform. * generic/tclEncoding.c (TclFindEncodings, Tcl_FindExecutable): * generic/tclInt.h: Correct handling of UTF * unix/tclUnixInit.c (TclpInitLibraryPath): data that is actually * win/tclWinFile.c (TclpFindExecutable): "clean", allowing the * win/tclWinInit.c (TclpInitLibraryPath): loading of Tcl from paths that contain multi-byte chars on Windows [Bug 920667] * win/configure: define TCL_LIB_FLAG, TCL_BUILD_LIB_SPEC, * win/configure.in: TCL_LIB_SPEC, TCL_PACKAGE_PATH in tclConfig.sh. 2004-04-06 Don Porter Patch 922727 committed. Implements three changes: * generic/tclInt.h: Reworked the Tcl header files into a clean * unix/tclUnixPort.h: hierarchy where tcl.h < tclPort.h < tclInt.h * win/tclWinInt.h: and every C source file should #include * win/tclWinPort.h: at most one of those files to satisfy its declaration needs. tclWinInt.h and tclWinPort.h also better organized so that tclWinPort.h includes the Windows implementation of cross-platform declarations, while tclWinInt.h makes declarations that are available on Windows only. * generic/tclBinary.c (TCL_NO_MATH): Deleted the generic/tclMath.h * generic/tclMath.h (removed): header file. The internal Tcl * macosx/Makefile (PRIVATE_HEADERS): header, tclInt.h, has a * win/tcl.dsp: #include directly, and file external to Tcl needing libm should do the same. * win/Makefile.in (WIN_OBJS): Deleted the win/tclWinMtherr.c file. * win/makefile.bc (TCLOBJS): It's a vestige from matherr() days * win/makefile.vc (TCLOBJS): gone by. * win/tcl.dsp: * win/tclWinMtherr.c (removed): End Patch 922727. * tests/unixInit.test (unixInit-3.1): Default encoding on Darwin systems is utf-8. Thanks to Steven Abner (tauvan). [Bug 928808] 2004-04-06 Donal K. Fellows * tests/cmdAH.test (cmdAH-18.2): Added constraint because access(...,X_OK) is defined to be permitted to be meaningless when running as root, and OSX exhibits this. [Bug 929892] 2004-04-02 Miguel Sofer * generic/tclCompile.c: * generic/tclInt.h: removed the macro TCL_ALIGN() from tclInt.h, replaced by the static macro ALIGN() in tclCompile.c [Bug 926445] 2004-04-02 Miguel Sofer * generic/tclCompile.h: removed redundant #ifdef _TCLINT [Bug 928415], reported by tauvan. 2004-04-02 Don Porter * tests/tcltest.test: Corrected constraint typos: "nonRoot" -> "notRoot". Thanks to Steven Abner (tauvan). [Bug 928353] 2004-04-01 Don Porter * generic/tclInt.h: Removed obsolete tclBlockTime* declarations. [Bug 926454] 2004-04-01 Vince Darley * generic/tclIOUtil.c: Fix to privately reported vfs bug with 'glob -type d -dir . *' across a vfs boundary. No tests for this are currently possible without effectively moving tclvfs into Tcl's test suite. 2004-03-31 Don Porter * doc/msgcat.n: Clarified message catalog file encodings. [Bug 811457] * library/msgcat/msgcat.tcl: Updated internals to make use of [dict]s to store message catalog data and to use [source -encoding utf-8] to access catalog files. Thanks to Michael Sclenker. [Patch 875055, RFE 811459] Corrected [mcset] to be able to successfully set a translation to the empty string. [mcset $loc $src {}] was incorrectly set the $loc translation of $src back to $src. Also changed [ConvertLocale] to minimally require a non-empty "language" part in the locale value. If not, an error raised prompts [Init] to keep looking for a valid locale value, or ultimately fall back on the "C" locale. [Bug 811461]. * library/msgcat/pkgIndex.tcl: Bump to msgcat 1.4.1. 2004-03-30 Donal K. Fellows * generic/tclHash.c (HashStringKey): Cleaned up. This function is not faster, but it is a little bit clearer. * generic/tclLiteral.c (HashString): Applied logic from HashObjKey. * generic/tclObj.c (HashObjKey): Rewrote to fix fault which hashed every single-character object to the same hash bucket. The new code is shorter, simpler, clearer, and (happily) faster. 2004-03-30 Miguel Sofer * generic/tclExecute.c (TEBC): reverting to the previous method for async tests in TEBC, as the new method turned out to be too costly. Async tests now run every 64 instructions. 2004-03-30 Miguel Sofer * generic/tclCompile.c: New instruction code INST_START_CMD that * generic/tclCompile.h: allows checking the bytecode's validity * generic/tclExecute.c: [Bug 729692] and the interp's readyness * tests/interp.test (18.9): [Bug 495830] before running the command. * tests/proc.test (7.1): It also changes the mechanics of the async * tests/rename.test (6.1): tests in TEBC, doing it now at command start instead of every 16 instructions. 2004-03-30 Vince Darley * generic/tclFileName.c: Fix to Windows glob where the pattern is a * generic/tclIOUtil.c: volume relative path or a network share [Bug * tests/fileName.test: 898238]. On windows 'glob' will now return * tests/fileSystem.test: the results of 'glob /foo/bar' and 'glob \\foo\\bar' as 'C:/foo/bar', i.e. a correct absolute path (rather than a volume relative path). Note that the test suite does not test commands like 'glob //Machine/Shared/*' (on a network share). 2004-03-30 Vince Darley * generic/tclPathObj.c: Fix to filename bugs recently * tests/fileName.test: introduced [Bug 918320]. 2004-03-29 Don Porter * generic/tclMain.c (Tcl_Main, StdinProc): Append newline only * tests/basic.test (basic-46.1): to incomplete scripts as part of multi-line script construction. Do not add an extra trailing newline to the complete script. [Bug 833150] 2004-03-28 Miguel Sofer * generic/tclCompile.c (TclCompileScript): corrected possible segfault when a compilation returns TCL_OUTLINE_COMPILE after having grown the compile environment [Bug 925121]. 2004-03-27 Miguel Sofer * doc/array.n: added documentation for trace-realted behaviour of 'array get' [Bug 449893] 2004-03-26 Don Porter * README: Bumped version number to 8.5a2 to distinguish * tools/tcl.wse.in: HEAD of CVS development from the recent 8.5a1 * unix/configure.in: release. * unix/tcl.spec: * win/README.binary: * win/configure.in: * unix/configure: autoconf-2.57 * win/configure: 2004-03-26 Vince Darley * generic/tclPathObj.c: Fix to Windows-only volume relative path * tests/fileSystem.test: normalization. [Bug 923568]. Also fixed another volume relative bug found while testing. 2004-03-24 Donal K. Fellows * generic/tclNamesp.c (NsEnsembleImplementationCmd): Fix messed up handling of strncmp result which just happened to work in some libc implementations. [Bug 922752] 2004-03-23 Donal K. Fellows * doc/StringObj.3: Inverted the sense of the documentation of how the bytes parameter is documented to match behaviour. [Bug 921464] 2004-03-19 Kevin B. Kenny * compat/strtoll.c: * compat/strtoull.c: * generic/tclIntDecls.h: * generic/tclMain.c: * generic/tclObj.c: * win/tclWinDde.c: * win/tclWinReg.c: * win/tclWinTime.c: Made HEAD build on Windows VC++ again. 2004-03-19 Donal K. Fellows * generic/tclIntDecls.h: Made HEAD build on Solaris again by applying fix recommended by Don Porter. 2004-03-18 Reinhard Max * generic/tclIntDecls.h: Removed TclpTime_t. It wasn't really needed, * generic/tclInt.h: but caused warnings related to * generic/tclInt.decls: strict aliasing with GCC 3.3. * generic/tclClock.c: * generic/tclDate.c: * generic/tclGetDate.y: * win/tclWinTime.c: * unix/tclUnixTime.c: * generic/tclNamesp.c: Added temporary pointer variables to work * generic/tclStubLib.c: around warnings related to * unix/tclUnixChan.c: strict aliasing with GCC 3.3. * unix/tcl.m4: Removed -Wno-strict-aliasing. 2004-03-18 Daniel Steffen Removed support for Mac OS Classic platform [Patch 918142] * README: * compat/string.h: * doc/Encoding.3: * doc/FileSystem.3: * doc/Init.3: * doc/Macintosh.3 (removed): * doc/OpenFileChnl.3: * doc/OpenTcp.3: * doc/SourceRCFile.3: * doc/Thread.3: * doc/clock.n: * doc/exec.n: * doc/fconfigure.n: * doc/file.n: * doc/filename.n: * doc/glob.n: * doc/open.n: * doc/puts.n: * doc/resource.n (removed): * doc/safe.n: * doc/source.n: * doc/tclvars.n: * doc/unload.n: * generic/README: * generic/tcl.decls: * generic/tcl.h: * generic/tclAlloc.c: * generic/tclBasic.c: * generic/tclCmdAH.c: * generic/tclDate.c: * generic/tclDecls.h: * generic/tclFCmd.c: * generic/tclFileName.c: * generic/tclGetDate.y: * generic/tclIOCmd.c: * generic/tclIOUtil.c: * generic/tclInitScript.h: * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclIntPlatDecls.h: * generic/tclMain.c: * generic/tclMath.h: * generic/tclNotify.c: * generic/tclPathObj.c: * generic/tclPlatDecls.h: * generic/tclPort.h: * generic/tclStubInit.c: * generic/tclTest.c: * generic/tclThreadJoin.c: * library/auto.tcl: * library/init.tcl: * library/package.tcl: * library/safe.tcl: * library/tclIndex: * mac/AppleScript.html (removed): * mac/Background.doc (removed): * mac/MW_TclAppleScriptHeader.h (removed): * mac/MW_TclAppleScriptHeader.pch (removed): * mac/MW_TclBuildLibHeader.h (removed): * mac/MW_TclBuildLibHeader.pch (removed): * mac/MW_TclHeader.h (removed): * mac/MW_TclHeader.pch (removed): * mac/MW_TclHeaderCommon.h (removed): * mac/MW_TclStaticHeader.h (removed): * mac/MW_TclStaticHeader.pch (removed): * mac/MW_TclTestHeader.h (removed): * mac/MW_TclTestHeader.pch (removed): * mac/README (removed): * mac/bugs.doc (removed): * mac/libmoto.doc (removed): * mac/morefiles.doc (removed): * mac/porting.notes (removed): * mac/tclMac.h (removed): * mac/tclMacAETE.r (removed): * mac/tclMacAlloc.c (removed): * mac/tclMacAppInit.c (removed): * mac/tclMacApplication.r (removed): * mac/tclMacBOAAppInit.c (removed): * mac/tclMacBOAMain.c (removed): * mac/tclMacChan.c (removed): * mac/tclMacCommonPch.h (removed): * mac/tclMacDNR.c (removed): * mac/tclMacEnv.c (removed): * mac/tclMacExit.c (removed): * mac/tclMacFCmd.c (removed): * mac/tclMacFile.c (removed): * mac/tclMacInit.c (removed): * mac/tclMacInt.h (removed): * mac/tclMacInterupt.c (removed): * mac/tclMacLibrary.c (removed): * mac/tclMacLibrary.r (removed): * mac/tclMacLoad.c (removed): * mac/tclMacMath.h (removed): * mac/tclMacNotify.c (removed): * mac/tclMacOSA.c (removed): * mac/tclMacOSA.r (removed): * mac/tclMacPanic.c (removed): * mac/tclMacPkgConfig.c (removed): * mac/tclMacPort.h (removed): * mac/tclMacProjects.sea.hqx (removed): * mac/tclMacResource.c (removed): * mac/tclMacResource.r (removed): * mac/tclMacSock.c (removed): * mac/tclMacTclCode.r (removed): * mac/tclMacTest.c (removed): * mac/tclMacThrd.c (removed): * mac/tclMacThrd.h (removed): * mac/tclMacTime.c (removed): * mac/tclMacUnix.c (removed): * mac/tclMacUtil.c (removed): * mac/tcltkMacBuildSupport.sea.hqx (removed): * tests/all.tcl: * tests/binary.test: * tests/cmdAH.test: * tests/cmdMZ.test: * tests/fCmd.test: * tests/fileName.test: * tests/fileSystem.test: * tests/interp.test: * tests/io.test: * tests/ioCmd.test: * tests/load.test: * tests/macFCmd.test (removed): * tests/osa.test (removed): * tests/resource.test (removed): * tests/socket.test: * tests/source.test: * tests/unload.test: * tools/cvtEOL.tcl (removed): * tools/genStubs.tcl: * unix/Makefile.in: * unix/README: * unix/mkLinks: * unix/tcl.spec: * win/README.binary: * win/tcl.dsp: 2004-03-17 Donal K. Fellows * doc/lsearch.n: Improved examples on the advanced capabilities of lsearch (with the right options, set element removal can be done) following discussion on tkchat. 2004-03-16 Don Porter * doc/catch.n: Compiled [catch] no longer fails to catch syntax errors. Removed the claims in the documentation that it does. * doc/return.n: Updated example to use [dict merge]. 2004-03-16 Jeff Hobbs * unix/configure, unix/tcl.m4: add -Wno-strict-aliasing for GCC to suppress useless type puning warnings. 2004-03-16 Donal K. Fellows * doc/file.n: *roff formatting fix. [Bug 917171] 2004-03-15 David Gravereaux * win/tclWinNotify.c: Fixed a mistake where the return value of MsgWaitForMultipleObjectsEx for "a message is in the queue" wasn't accurate. I removed the check on the case result==(WAIT_OBJECT_0 + 1) This was having the error of falling into GetMessage and waiting there by accident, which wasn't alertable through Tcl_AlertNotifier. I'll do some more study on this and try to find-out why. 2004-03-12 Donal K. Fellows IMPLEMENTATION OF TIP#163 * generic/tclDictObj.c (DictMergeCmd): This is based on work by Joe * tests/dict.test (dict-20.*): English in Tcl [FRQ 745851] * doc/dict.n: but not exactly. 2004-03-10 Kevin B. Kenny * generic/tclGetDate.y (TclGetDate): Fix so that [clock scan -gmt true] uses the GMT base date instead of the local one. [Bug 913513] * tests/clock.test: Added test cases for wrong ISO8601 week number [Bug 500285] and wrong GMT base date [Bug 913513]. Several tests still fail on Windows, and these are actual faults in [clock scan]. Fix is still pending. * generic/tclDate.c: Regenerated. 2004-03-08 Vince Darley * generic/tclFileName.c: Fix to 'glob -path' near the root * tests/fileName.test: of the filesystem. [Bug 910525] 2004-03-08 Don Porter * generic/tclParse.c (TclParseInit): Modified TclParseInit so * generic/tclTest.c ([testexprparser]): that Tcl_Parse initialization conforms to documented promised about what fields will not be modified by what Tcl_Parse* routines. [Bug 910595] 2004-03-05 Mo DeJong * win/configure: Regen. * win/configure.in: Check for define of MWMO_ALERTABLE in winuser.h. * win/tclWinPort.h: If MWMO_ALERTABLE is not defined in winuser.h then define it. This is needed for Mingw. 2004-03-05 Kevin B. Kenny * generic/tclTest.c: Modified TesteventObjCmd to use a Tcl_QueuePosition in place of an 'int' for the enumerated queue position, to avoid a compiler warning on SGI. [Bug 771960] 2004-03-05 Kevin B. Kenny * tests/registry.test: Applied fix from [Patch 910174] to make the test for an English-language system include any country code, rather than just English-United States.1252. Thanks to Pat Thoyts for the changes. 2004-03-04 Pat Thoyts * tests/registry.test: Applied fixed from [Bug 766159] to skip two tests on Win98 that depend on a Unicode registry (NT specific). 2004-03-04 Don Porter * generic/tclInt.h (TclParseInit): Factored the common code * generic/tclParse.c (TclParseInit): for initializing a Tcl_Parse * generic/tclParseExpr.c: struct into one routine. 2004-03-04 Pat Thoyts * library/reg/pkgIndex.tcl: Added TIP #100 support to the * win/tclWinReg.c: registry package [patch 903831] This provides a Windows test of the TIP #100 mechanism and a sample to show how unloading an extension can be done. 2004-03-04 Donal K. Fellows * unix/dltest/pkgua.c: Fix minor syntax problems. [Bug 909288] 2004-03-03 Jeff Hobbs *** 8.5a1 TAGGED FOR RELEASE *** * changes: updated for 8.5a1 2004-03-03 David Gravereaux * win/makefile.vc: default environment variable for VC++ is %MSDevDir% not %MSVCDir%, although vcvars32.bat sets both. * win/tclWinNotify.c (Tcl_WaitForEvent) : Allows an idling notifier to service "Asynchronous Procedure Calls" from its wait state. Only useful for extension authors who decide they might want to try "completion routines" with WriteFileEx(), as an example. From experience, I recommend that "completion ports" should be used instead as the execution of the callbacks are more managable. 2004-03-01 Jeff Hobbs * README: update patchlevel to 8.5a1 * generic/tcl.h: * tools/tcl.wse.in, tools/tclSplash.bmp: * unix/configure, unix/configure.in, unix/tcl.spec: * win/README.binary, win/configure, win/configure.in: * unix/tcl.m4: update HP-11 build libs setup 2004-03-01 Don Porter * unix/tcl.m4 (SC_CONFIG_CFLAGS): Allow 64-bit enabling on IRIX64-6.5* systems. [Bug 218561] * unix/configure: autoconf-2.57 * generic/tclTrace.c (TclCheckInterpTraces): The TIP 62 * generic/tclTest.c (TestcmdtraceCmd): implementation introduced a * tests/trace.test (trace-29.10): bug by testing the CallFrame level instead of the iPtr->numLevels level when deciding what traces created by Tcl_Create(Obj)Trace to call. Added test to expose the error, and made fix. [FRQ 462580] 2004-02-28 Vince Darley * tests/fileSystem.test: fix to Tcl Bug 905163. * tests/fileName.test: fix to Tcl Bug 904705. * doc/{various}.n: removed 'the the' typos. 2004-02-26 Daniel Steffen * macosx/Makefile: fixed copyright year in Tcl.framework Info.plist 2004-02-25 Don Porter * tests/basic.test: Made several tests more robust to the * tests/cmdMZ.test: list-quoting of path names that might contain * tests/exec.test: Tcl-special chars like { or [. Should help us * tests/io.test: sort out [Bug 554068] * tests/pid.test: * tests/socket.test: * tests/source.test: * tests/unixInit.test: 2004-02-25 Donal K. Fellows * generic/tclLoad.c (Tcl_LoadObjCmd): Missing dereference caused segfault with non-loadable extension. [Bug 904307] * unix/tclUnixChan.c (TcpGetOptionProc): Stop memory leak with very long hostnames. [Bug 888777] 2004-02-25 Pat Thoyts * win/tclWinDde.c: Removed some gcc warnings - except for the -Wconversion warning for GetGlobalAtomName. gcc is just wrong about this. 2004-02-24 Donal K. Fellows IMPLEMENTATION OF TIP#100 FROM GEORGIOS PETASIS * generic/tclLoad.c (Tcl_UnloadObjCmd): Implementation. * tests/unload.test: Test suite. * unix/dltest/pkgua.c: Helper for test suite. * doc/unload.n: Documentation. Also assorted changes (mostly small) to several other files. 2004-02-23 Donal K. Fellows * generic/regc_locale.c (cclass): Buffer was having its size reset instead of being released => memleak. [Bug 902562] 2004-02-21 Donal K. Fellows * generic/tclLoad.c (Tcl_LoadObjCmd): Fixed memory leak due to an improper error exit route. 2004-02-20 David Gravereaux * win/tclWinSock.c (SocketThreadExitHandler): Don't call TerminateThread when WaitForSingleObject returns a timeout. Tcl_Finalize called from DllMain will pause all threads. Trust that the thread will get the close notice at a later time if it does ever wake up before being cleaned up by the system anyway. 2004-02-17 Don Porter * doc/tcltest.n: * library/tcltest/tcltest.tcl: Changed -verbose default value to {body error} so that detailed information on unexpected errors in tests is provided by default, even after the fix for [Bug 725253] 2004-02-17 Jeff Hobbs * tests/unixInit.test (unixInit-7.1): * unix/tclUnixInit.c (TclpInitPlatform): ensure the std fds exist to prevent crash condition [Bug 772288] 2004-02-17 Donal K. Fellows * generic/tclCompCmds.c (TclCompileSwitchCmd): Bozo mistake in memory releasing order when in an error case. [Bug 898910] 2004-02-16 Jeff Hobbs * generic/tclTrace.c (TclTraceExecutionObjCmd) (TclTraceCommandObjCmd): fix possible mem leak in trace info. 2004-02-12 Mo DeJong * win/tclWinInit.c (AppendEnvironment): Use the tail component of the passed in lib path instead of just blindly using lib+4. That worked when lib was "lib/..." but fails for other values. Thanks go to Patrick Samson for pointing this out. 2004-02-10 David Gravereaux * win/nmakehlp.c: better macro grepping logic. 2004-02-07 David Gravereaux * win/makefile.vc: * win/rules.vc: * win/tcl.rc: * win/tclsh.rc: Added an 'unchecked' option to the OPTS macro so a core built with symbols can be linked to the non-debug enabled C run-time. As per discussion with Kevin Kenny. Called like this: nmake -af makefile.vc OPTS=unchecked,symbols This clarifies the meaning of the 'g' naming suffix to mean only that the binary requires the debug enabled C run-time. Whether the binary contains symbols or not is a different condition. 2004-02-06 Don Porter * doc/clock.n: Removed reference to non-existent [file ctime]. 2004-02-05 David Gravereaux * docs/tclvars.n: Added clarification of the tcl_platform(debug) var that it only refers to the flavor of the C run-time, and not whether the core contains symbols. 2004-02-05 Don Porter * generic/tclFileName.c (SkipToChar): Corrected CONST and type-casting issues that caused compiler warnings. 2004-02-04 Don Porter * generic/tclCmdAH.c (StoreStatData): Removed improper refcount decrement of the varName parameter. This error was causing segfaults following test cmdAH-28.7. * library/tcltest/tcltest.tcl: Corrected references to non-existent $name variable in [cleanupTests]. [Bug 833637] 2004-02-03 Don Porter * library/tcltest/tcltest.tcl: Corrected parsing of single command line argument (option with missing value) [Bug 833910] * library/tcltest/pkgIndex.tcl: Bump to version 2.2.5. 2004-02-02 David Gravereaux * generic/tclIO.c (Tcl_Ungets): Fixes improper filling of the channel buffer. This is the buffer before the splice. [Bug 405995] 2004-02-01 David Gravereaux * tests/winPipe.test: more pass-thru commandline verifications. * win/tclWinPipe.c (BuildCommandLine): Special case quoting for '{' not required by the c-runtimes's parse_cmdline(). * win/tclAppInit.c: Removed our custom setargv() in favor of the work provided by the c-runtime. [Bug 672938] * win/nmakehlp.c: defensive techniques to avoid static buffer overflows and a couple envars upsetting invokations of cl.exe and link.exe. [Bug 885537] * tests/winPipe.test: Added proof that BuildCommandLine() is not doing the "N backslashes followed a quote -> insert N * 2 + 1 backslashes then a quote" rule needed for the crt's parse_cmdline(). * win/tclWinPipe.c: Fixed BuildCommandLine() to pass the new cases. 2004-01-30 David Gravereaux * win/makefile.vc: Use the -GZ compiler switch when building for symbols. This is supposed to emulate the release build better to avoid hiding problems that only show themselves in a release build. 2004-01-29 Vince Darley * generic/tclPathObj.c: fix to [Bug 883143] in file normalization 2004-01-29 Vince Darley * doc/file.n: * generic/tclFCmd.c * generic/tclTest.c * library/init.tcl * mac/tclMacFile.c * tests/fileSystem.test: fix to [Bug 886352] where 'file copy -force' had inconsistent behaviour wrt target files with insufficient permissions, particular from vfs->native fs. Behaviour of '-force' is now always consistent (and now consistent with behaviour of 'file delete -force'). Added new tests and documentation and cleaned up the 'simplefs' test filesystem. * generic/tclIOUtil.c * unix/tclUnixFCmd.c * unix/tclUnixFile.c * win/tclWinFile.c: made native filesystems more robust to C code which asks for mount lists. * generic/tclPathObj.c: fix to [Bug 886607] removing warning/error with some compilers. 2004-01-28 Donal K. Fellows * generic/tclObj.c (SetBooleanFromAny): Rewrite to do more efficient string->bool conversion. Many other minor whitespace/style fixes to this file too. 2004-01-27 David Gravereaux * win/nmakehlp.c: Use '.\nul' as the sourcefile name instead of 'nul' so VC 5.2 doesn't try searching the path for it and failing with a possible dialogbox popping up about having to add a CD to an empty drive. Also added a SetErrorMode() call to disable any dialogs that cl.exe or link.exe might create. [Bug 885537] 2004-01-22 Vince Darley * doc/file.n: clarified documentation of 'file system' [Bug 883825] * tests/fCmd.test: improved test result in failure case. 2004-01-22 Vince Darley * tests/fileSystem.test: 3 new tests * generic/tclPathObj.c: fix to [Bug 879555] in file normalization. * doc/filename.n: small clarification to Windows behaviour with filenames like '.....', 'a.....', '.....a'. * generic/tclIOUtil.c: slight improvement to native cwd caching on Windows. 2004-01-21 David Gravereaux * doc/Panic.3: Mentions of 'panic' and 'panicVA' removed from the documentation. 2004-01-21 Vince Darley * doc/FileSystem.3: * generic/tcl.decls: * generic/tclCmdAH.c * generic/tclDecls.h * generic/tclFCmd.c * generic/tclFileName.c * generic/tclFileSystem.h * generic/tclIOUtil.c * generic/tclInt.decls * generic/tclInt.h * generic/tclIntDecls.h * generic/tclPathObj.c * generic/tclStubInit.c * generic/tclTest.c * mac/tclMacFile.c * tests/fileName.test * tests/fileSystem.test * tests/winFCmd.test * unix/tclUnixFile.c * win/tclWin32Dll.c * win/tclWinFCmd.c * win/tclWinFile.c * win/tclWinInt.h Three main issues accomplished: (1) cleaned up variable names in the filesystem code so that 'pathPtr' is used throughout. (2) applied a round of filesystem optimisation with better handling and caching of relative and absolute paths, requiring fewer conversions. (3) clarifications to the documentation, particularly regarding the acceptable refCounts of objects. Some new tests added. Tcl benchmarks show a significant improvement over 8.4.5, and on Windows typically a small improvement over 8.3.5 (Unix still appears to require optimisation). TCL_FILESYSTEM_VERSION_2 introduced, but for internal use only. There should be no public incompatibilities from these changes. Thanks to dgp for extensive testing. 2004-01-19 David Gravereaux * win/tclWinPipe.c (Tcl_WaitPid): Fixed a thread-safety problem with the process list. The delayed cut operation after the wait was going stale by being outside the list lock. It now cuts within the lock and does a locked splice for when it needs to instead. [Bug 859820] 2004-01-18 Donal K. Fellows * generic/tclCompile.c, generic/tclCompile.h: Two new opcodes, INST_LIST_INDEX_IMM and INST_LIST_RANGE_IMM, that have operand(s) of new type OPERAND_IDX4 which represents indexes into things like lists (and perhaps other things eventually.) * generic/tclExecute.c (TclExecuteByteCode): Implementation of the new opcodes. INST_LIST_INDEX_IMM does a simple [lindex] with either front- or end-based simple indexing. INST_LIST_RANGE_IMM does an [lrange] with front- or end-based simple indexing for both the reference to the first and last items in the range. * generic/tclCompCmds.c (TclCompileLassignCmd): Generate bytecode for the [lassign] command. 2004-01-17 David Gravereaux * win/tclWinInit.c: added #pragma comment(lib, "advapi32.lib") when compiling under VC++ so we don't need to specify it when linking. 2004-01-17 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LassignObjCmd): Add more shimmering protection for when the list is also one of the variables. BASIC IMPLEMENTATION OF TIP#57 * generic/tclCmdIL.c (Tcl_LassignObjCmd): Implementation of the [lassign] command that takes full advantage of Tcl's object API. * doc/lassign.n: New file documenting the command. * tests/cmdIL.test (cmdIL-6.*): Test suite for the command. 2004-01-15 David Gravereaux * win/tclWinReg.c: Placed the requirement for advapi.lib into the object file itself with #pragma comment (lib, ...) when built with VC++. This will simplify linking for users of the static library. * win/rules.vc: Added new 'fullwarn' to the CHECKS commandline macro; sets $(FULLWARNINGS). * win/makefile.vc: Removed 'advapi.lib' from $(baselibs). Added new logic to crank-up the warning levels for both compile and link when $(FULLWARNINGS) is set. Some clean-up with how the resource files are built and how -DTCL_USE_STATIC_PACKAGES is sent when compiling the shells. * win/tclAppInit.c: Small change in how TCL_USE_STATIC_PACKAGES is used. * win/tcl.rc: * win/tclsh.rc: Some clean-up with how the resource files are built. Fixed 'OriginalFilename' problem that still thought a debug suffix was still 'd', now is 'g'. 2004-01-14 Donal K. Fellows * generic/tclDictObj.c (TraceDictPath, DictExistsCmd): Adjusted behaviour of [dict exists] so a failure to look up a dictionary along the path of dicts doesn't trigger an error. This is how it was documented to behave previously... [Bug 871387] * generic/tclDictObj.c: Assorted dict fixes from Peter Spjuth relating to [Bug 876170]. (SetDictFromAny): Make sure that lists retain their ordering even when converted to dictionaries and back. (TraceDictPath): Correct object reference count handling! (DictReplaceCmd, DictRemoveCmd): Stop object leak. (DictIncrCmd,DictLappendCmd,DictAppendCmd,DictSetCmd,DictUnsetCmd): Simpler handling of reference counts when assigning to variables. * tests/dict.test (dict-19.2): Memory leak stress test 2004-01-13 Don Porter * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Silence compiler warnings. Patch 876451: restores performance of [return]. Also allows forms such as [return -code error $msg] to be bytecompiled. * generic/tclInt.h: Factored Tcl_ReturnObjCmd() into two pieces: * generic/tclCmdMZ.c: TclMergeReturnOptions(), which can parse the options to [return], check their validity, and create the corresponding return options dictionary, and TclProcessReturn(), which takes that return options dictionary and performs the [return] operation. * generic/tclCompCmds.c: Rewrote TclCompileReturnCmd() to call TclMergeReturnOptions() at compile time so the return options dictionary is computed at compile time (when it is fully known). The dictionary is pushed on the stack along with the result, and the code and level values are included in the bytecode as operands. Also supports optimized compilation of un-[catch]ed [return]s from procs with default options into the INST_DONE instruction. * generic/tclExecute.c: Rewrote INST_RETURN instruction to retrieve the code and level operands, pop the return options from the stack, and call TclProcessReturn() to perform the [return] operation. * generic/tclCompile.h: New utilities include TclEmitInt4 macro * generic/tclCompile.c: and TclWordKnownAtCompileTime(). End Patch 876451. * generic/tclFileName.c (Tcl_GlobObjCmd): Latest changes to management of the interp result by Tcl_GetIndexFromObj() exposed improper interp result management in the [glob] command procedure. Corrected by adopting the Tcl_SetObjResult(Tcl_NewStringObj) pattern. This stopped a segfault in test filename-11.36. [Bug 877677] 2004-01-13 Donal K. Fellows * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct, Tcl_WrongNumArgs): Create fresh objects instead of using the one currently in the interpreter, which isn't guaranteed to be fresh and unshared. The cost for the core will be minimal because of the object cache, and this fixes [Bug 875395]. 2004-01-12 Miguel Sofer * generic/tclCompExpr.c (CompileLandOrLorExpr): cosmetic changes. 2004-01-12 Miguel Sofer * generic/tclCompExpr.c (CompileLandOrLorExpr): new logic, fewer instructions. As a side effect, the instructions INST_LOR and INST_LAND are now never used. * generic/tclExecute.c (INST_JUMP*): small optimisation; fix a bug in debug code. 2004-01-11 David Gravereaux * win/tclWinThrd.c (Tcl_ConditionNotify): condPtr must be dereferenced to see if there are waiters else uninitialized datum is manipulated. [Bug 849007 789338 745068] 2004-01-09 David Gravereaux * generic/tcl.h: Renamed and deprecated #defines moved to within the #ifndef TCL_NO_DEPRECATED block. This allows us to build Tcl to check for deprecated functions in use, such as panic() and Tcl_Ckalloc(). By request from DKF. Extensions that build with -DTCL_NO_DEPRECATED now have these macros as restricted. ***POTENTIAL INCOMPATIBILITY*** * win/makefile.vc: * win/rules.vc: Added -DTCL_NO_DEPRECATED usage to makefile.vc. Called like this: nmake -af makefile.vc CHECKS=nodep 2004-01-09 Vince Darley * generic/tclIOUtil.c: fix to infinite loop in TclFinalizeFilesystem [Bug 873311] ****************************************************************** *** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003" *** *** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002" *** *** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" *** *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" *** *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" *** ****************************************************************** tcl8.6.5/ChangeLog.20010000644000175000017500000041562212663660064013733 0ustar sergeisergei2001-12-28 Jeff Hobbs * library/init.tcl: make sure env(COMSPEC) on Windows is executed with the right case, as it may otherwise fail inexplicably. 2001-12-28 Don Porter * generic/tclCkalloc.c (MemoryCmd, TclFinalizeMemorySubsystem): Added the [memory onexit] command, intended to replace [checkmem]. * doc/DumpActiveMemory.3: * doc/memory.n: Updated documentation for [memory] and related matters. [Bug 487677] * mac/tclMacBOAMain.c (Tcl_Main, CheckmemCmd): Removed all the machinery for the [checkmem] command that is completely duplicated by code in generic/tclCkalloc.c. * generic/tclBinary.c: * generic/tclListObj.c: * generic/tclObj.c: * generic/tclStringObj.c: Removed references to [checkmem] in comments, referencing [memory active] instead, since it is documented. 2001-12-28 Daniel Steffen * mac/tclMacInit.c: * mac/tclMacTclCode.r: synced up tclInit features to unix/win: implemented TclSetPreInitScript support, use of existing tclInit proc if defined, check of default encoding dir if set. Changed script library resource names to lowercase (i.e. same as corresponding files). Used Tcl_JoinPath instead of string append. Check that system encoding could be loaded before utf translating the LibraryPath. * mac/tclMacApplication.r: * mac/tclMacLibrary.r: * mac/tclMacOSA.r: * mac/tclMacResource.r: minor version resources cleanup 2001-12-21 Mo DeJong * unix/tcl.m4 (SC_PATH_TCLCONFIG, SC_PATH_TKCONFIG): Search for config file using exec_prefix instead of prefix when no --with-tcl or --with-tk argument is used. [Bug 492418] 2001-12-21 Daniel Steffen * unix/tcl.m4: fixed incorrect SHLIB_LD_LIBS setting for MacOSX / Darwin. * unix/configure: Regen. * unix/mkLinks.tcl: improved case-insensitive filesystem support. * unix/mkLinks: Regen. 2001-12-19 Don Porter * unix/Makefile.in (dist): corrected use of eolFix.tcl on working files. It should operate on distributed files. [Bug 495120] 2001-12-19 David Gravereaux * tools/tcl.wse.in: Fix for [Bug 495120]. tcl.wse.in was stored in cvs with improper . This resulted in corrupted when checked-out on translating CVS clients such as windows (CRCRLF) and mac (CRCR). 2001-12-19 Mo DeJong * unix/configure: * unix/tcl.m4 (SC_CONFIG_CFLAGS): Update SunOS 5.[0-6] target so that correct linker options are passed to gcc or ld. [Tk Bug 220863] 2001-12-19 Mo DeJong * unix/README: Update to account for changes in the unix/dltest directory, the way autoconf is run, and the new "make shell" target. 2001-12-19 Mo DeJong * unix/Makefile.in: Rename dltest to dlpkgs to fix problem where lib files were not getting built because dltest/ directory already existed. 2001-12-19 Jeff Hobbs * win/tclWinSerial.c (SerialCheckProc): corrected time calculations to be unsigned. (schroedter) 2001-12-18 Mo DeJong * unix/Makefile.in: Define new dltest target that simply does a cd to dltest/ before running make. There is no need for the separate configure script that was previously being used. * unix/configure: Regen. * unix/configure.in: Subst into dltest/Makefile. * unix/dltest/Makefile.in: Define LIBS using DL_LIBS, LIBS, and MATH_LIBS variables instead of TCL_LIBS variable from tclConfig.sh. * unix/dltest/README: Update readme to account for new configure free implementation. * unix/dltest/configure: Removed. * unix/dltest/configure.in: Removed. 2001-12-18 Donal K. Fellows * generic/tcl.h (TCL_STUB_MAGIC): Added cast to force type to be an int and get rid of a persistent and pointless warning with SunPro compiler. * generic/tclCkalloc.c (Tcl_AttemptDbCkalloc,Tcl_AttemptDbCkrealloc): * generic/tcl.decls (Tcl_AttemptDbCkalloc,Tcl_AttemptDbCkrealloc): Made the file parameters to these functions into CONST char *, like they always should have been to match the other Tcl*Db* API functions. 2001-12-17 Andreas Kupries * Applied [Bug 219311] on behalf of Rolf Schroedter to prevent fcopy on serial ports from flooding the event queue. 2001-12-11 Miguel Sofer * doc/CrtInterp.3: * generic/tclBasic.c: docs and comments corrections. [Bug 493412] Bug & patch by Don Porter. 2001-12-14 Donal K. Fellows * win/tclWinNotify.c (Tcl_FinalizeNotifier): Stop Tcl on Windows from crashing when shutdown from a non-Tcl thread. Fixes [Bug 217982] [orig. 5804] reported by Hugh Vu and Gene Leache. I'm not convinced that the shutdown process is right even with this, but it was definitely wrong without... 2001-12-13 Andreas Kupries * win/tclWinSock.c (TcpGetOptionProc): Fix for [Bug 478565] reported by an unknown person. Bypasses all calls to "gethostbyaddr" for address "0.0.0.0" to prevent delays on Win/NT. 2001-12-12 Jeff Hobbs * doc/Preserve.3: doc'd TCL_DYNAMIC use. [Patch 483989] (porter) 2001-12-12 Andreas Kupries * generic/tclIO.c (Tcl_GetsObj): Applied patch for [Bug 491341] as provided by Don Porter . Fixes the assumption of having an empty Tcl_Obj to work with. 2001-12-11 Miguel Sofer * generic/tclCompCmds.c: * generic/tclCompile.c: * generic/tclExecute.c: consistency patch, to make all instructions that pop a variable number of Tcl_Obj's off the execution stack take the number of popped objects as first operand. Modified *only* the new instructions INST_LIST_INDEX_MULTI and INST_LSET_FLAT, so this has no effect on bytecodes generated up to tcl8.4a3 inclusive. * generic/tclExecute.c: fix debug messages in INST_LSET_LIST. * generic/tclCompCmds.c (TclCompileLindexCmd): * generic/tclCompExpr.c (CompileMathFuncCall): removed the last two overestimates of the necessary stack depth for bytecodes in the fix of [Bug 483611] 2001-12-10 Andreas Kupries * unix/tclUnixPipe.c (TclpCreateProcess): Applied Don Porter's patch fixing [Bug 437489]. 2001-12-10 Miguel Sofer * generic/tclEvent.c: * tests/event.test: fix background error reporting in the absence of a bgerror proc [Bug 219142]. 2001-12-10 Don Porter * doc/Access.3: * doc/CrtChannel.3: * doc/DString.3: * doc/ExprLong.3: * doc/FileSystem.3: * doc/GetStdChan.3: * doc/OpenFileChnl.3: * doc/StdChannels.3: * doc/TCL_MEM_DEBUG.3: * doc/Tcl_Main.3: * doc/Utf.3: * doc/file.n: * doc/tclsh.1: Several typo and formatting corrections discovered during conversion to TMML. Thanks to Joe English. [Patch 490514] * unix/mkLinks: 'make mklinks' 2001-12-10 Miguel Sofer * generic/tclCompCmds.c: * generic/tclCompExpr.c: * generic/tclCompile.c: * generic/tclCompile.h: * generic/tclExecute.c: * generic/tclProc.c: fixed the calculation of the maximal stack depth required by bytecodes. [Bug 483611] 2001-12-07 Miguel Sofer * generic/tclVar.c: * tests/trace.test: restored consistency in refCount accounting by array traces [Bug 4484339], submitted by Don Porter. 2001-12-06 Donal K. Fellows * tests/parseExpr.test, tests/for.test, tests/expr.test: * tests/expr-old.test, tests/compile.test, tests/compExpr.test * tests/compExpr-old.test: Kept up to date with syntax errors. * generic/tclParseExpr.c (ParsePrimaryExpr): Rewrote to give even better syntax errors in the fairly common case of an identifier without decorations by guessing based on the currently available functions. Also made messages consistent between memdebug and ordinary builds. 2001-12-05 Miguel Sofer * generic/tclVar.c: * tests/trace.test: new algorithm for [array get], safe when there are traces that modify the array. [Bug 449893] 2001-12-04 Donal K. Fellows * tests/compExpr-old.test, tests/compExpr.test, tests/compile.test: * tests/expr-old.test, tests/expr.test, tests/for.test: * tests/while.test, tests/if.test: Rewrite to handle more specific syntax errors. * tests/parseExpr.test: Rewrite to get rid of dup test numbers and handle more specific syntax errors. * generic/tclParseExpr.c (LogSyntaxError): Added a detail message argument to help explain what the syntax error is. (Tcl_ParseExpr, ParseCondExpr, ParsePrimaryExpr): Added detail messages. (UNKNOWN_CHAR): New lexeme for characters that are always illegal in expressions outside strings. 2001-12-03 Donal K. Fellows * doc/expr.n: Various documentation improvements in relation to the function calls. Includes fix for [Bug 487704] submitted by Devin Eyre. 2001-12-03 David Gravereaux * win/makefile.vc: Some install target bugs repaired along with $(TCLSTUBLIB) added to the dependencies rather than implicit through the dde and reg extensions which don't happen to always require it for some build types. 2001-11-30 Miguel Sofer * generic/tclVar.c: Tcl_Preserve'ing VarTrace structures to avoid memory corruption. Patch for [Bug 484334] provided by Don Porter 2001-11-29 Miguel Sofer * tests/namespace.test: modified namespace-41.2, added 41.3 {knownbug} after discussion with Don Porter and Kevin Kenny. 2001-11-29 Miguel Sofer * tests/namespace.test: added namespace-41.2, a simpler test for [Bug 231259] 2001-11-29 Donal K. Fellows * generic/tclBinary.c (BINARY_SCAN_MAX_CACHE, Tcl_BinaryObjCmd, (ScanNumber): Added caching scheme to reduce number of object allocations when doing scans of large repetitive binary strings. See comments in file for reasoning behind implementation. Suggested by Miguel Sofer in [Patch 429916], but independently implemented. 2001-11-28 Donal K. Fellows * doc/regsub.n, doc/regexp.n: Converted dangling references to METASYNTAX section into references to the re_syntax manual page. 2001-11-27 D. Richard Hipp * win/tclWinFCmd.c: Fix a coredump in the filename normalizer code for Win95/98. 2001-11-27 David Gravereaux * win/makefile.vc: Removed the Tk reference for the 'winhelp' target. Converge at install will need to be the solution for Tk and all other extensions. 2001-11-27 Donal K. Fellows * tests/cmdAH.test (cmdAH-24.2): Made test less sensitive to OS preemption, but perfection isn't practical. [Bug 463189, reported by Don Porter] * tests/switch.test (switch-9.*): Added tests to exercise more of the argument checking. (switch-7.2,switch-7.3): Test changed behaviour slightly. * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Reworked argument parsing to be stricter about what it accepts. This should make uses of the [switch] command be more maintainable. [Bug 475397, reported by Don Porter] 2001-11-26 Don Porter * generic/tclIntPlatDecls.h: 'make genstubs' after changes in 2001-11-23 commit from Daniel Steffen. 2001-11-24 Mo DeJong * unix/Makefile.in: Add comments to better describe TCL_EXE and when it should be available. * win/Makefile.in: Add TCL_EXE variable to be used by rules like `make genstubs`. Don't set TCL_LIBRARY before running `make genstubs` since we will be running with a tclsh from the PATH not the one we build. 2001-11-24 Mo DeJong * win/configure: Regen. * win/tcl.m4 (SC_CONFIG_CFLAGS): Add comctl32.lib to wish link libs. This change was originally added to Tk on 2001-11-09 but was not committed to Tcl. 2001-11-23 Daniel Steffen * unix/Makefile.in: * unix/configure.in: * unix/install-sh: * unix/mkLinks: * unix/mkLinks.tcl: * unix/tclLoadDyld.c: * unix/tclMtherr.c: Mac OSX support: build system, dynamic code loading and support for case-insensitive filesystems in mkLinks. [Patch 435258] 2001-11-23 Daniel Steffen Up-port to 8.4 of mac code changes for 8.3.3 & various new changes for 8.4, some already backported to 8.3.4. [Patch 435658] * generic/tclObj.c: added #include to fix missing prototype errors * generic/tcl.h: MAC_TCL: addition of ConditionalMacros.h and use of DLLIMPORT and DLLEXPORT like on other platforms. ( => no longer need the .exp files and can remove use of #pragma export that never worked well) removed line continuation in #if clause as this breaks the mac resource compiler (note that *.r files include tcl.h) * mac/tclMacFile.c: fixed bug in permission checking code * mac/tclMacLoad.c: corrected utf8 handling, comparison of package names to code fragment names changed to only match on the length of package name, this allows for fragment names with version numbers appended. * mac/tclMacInt.h: * generic/tclInt.h: * mac/tclMacTime.c: * generic/tclIOUtil.c: moved declaration of TclpGetGMTOffset() * mac/tclMacShLib.exp: * mac/tclMacOSA.exp: * mac/tclMacMSLPrefix.h: removed files * unix/Makefile.in: removed reference to .exp files * mac/MW_TclBuildLibHeader.h: * mac/MW_TclBuildLibHeader.pch: * mac/MW_TclHeaderCommon.h: * mac/MW_TclStaticHeader.h: * mac/MW_TclStaticHeader.pch: new precompiled header files * mac/MW_TclAppleScriptHeader.pch: * mac/MW_TclHeader.pch: * mac/MW_TclTestHeader.pch: * mac/tclMacCommonPch.h: revised precompiled header handling: now include a common header file 'MW_TclHeaderCommon.h' from all .pch files, the .pch files themselves now only setup #defines (e.g. BUILD_tcl, STATIC_BUILD, TCL_DEBUG, TCL_THREADS) like in makefiles on other platforms. * mac/tclMac.h: * mac/tclMacPort.h: * mac/tclMacInt.h: use of BUILD_tcl and TCL_STORAGE_CLASS like on other platforms, standardize #include'd files to what's done on other platforms, removed use of #pragma export. * mac/tcltkMacBuildSupport.sea.hqx: new archive of mac build support files & suggested build environment directory hierarchy: 'Building MacTclTk' & 'CW Pro6 changes' readme's. projects for MoreFiles 1.5.2 static & shared libraries. project & sources for 'pseudoCarbonSupport', see below. included XML versions of the projects for CW Pro5 or Pro7 users. * mac/tclMacProjects.sea.hqx: updated mac build project files: build support for CodeWarrior Pro6, UnivIntf 3.4 & shared runtime libraries: the MSL libraries and MoreFiles are no longer compiled into Tcl.shlb, all non-static binaries now use the Pro6 shared runtime libraries and MoreFiles.shlb. These shlbs are merged into the standard Wish and TclShell, but 3rd party applications linking with Tcl.shlb or Tk.shlb need to setup access to them. (see the "(sh-ppc)" targets for how to do this.) included XML versions of the projects for CW Pro5 or Pro7 users. use compat/strtod.c instead of MSL's strtod() use WASTE versions of MSL for tcl test target to avoid text buffer cutoff at 32k. Merging the full MSL.shlb and the other shlbs into Wish & TclShell makes them a bit larger than before, use unmerged binaries to avoid copying the shared code with every application, e.g. when deploying numerous Wish based droplets. Note that using CW Pro5 to compile extensions is in principle still possible, but need to link with Pro6 runtime libraries. Tclapplescript now loads and runs on CFM68k. Highly experimental "pseudoCarbon" support for Tcl only on OS 8/9: binaries in "Build:(Carbon):" link against CarbonLib instead of InterfaceLib, however the actual code has not been carbonized! i.e. it will not run on OSX and may not even run properly with CarbonLib. This should in principle allow you to build & test OS9 CFM Carbon binaries that need to link with Tcl.shlb. On OSX you can use the native Tcl.framework, but you have to build a MachO binary as there is no CFM glue lib for Tcl.framework. the library pseudoCarbonSupport.shlb manually loads the symbols from InterfaceLib that are not in CarbonLib but are needed by the uncarbonized code in Tcl.shlb and TclShell. * generic/tclMain.c: MAC_TCL: workaround for broken/non-standard isatty on MW Pro6, #include instead of defining isatty * mac/tclMacPort.h: MW Pro6 changes for MSL fcntl.h, stat.h & isatty * mac/tclMacAppInit.c: add EXTERN to InstallConsole to enable DLL export via the TCL_STORAGE_CLASS mechanism. * mac/tclMacFCmd.c: fix for FSpDirectoryCopy API change * mac/tclMacLibrary.c: emit compile time error when TCL_REGISTER_LIBRARY and USE_TCL_STUBS are both defined at the same time in an extension, this use is not currently supported and will result in a crash when dynamically loading the extension. * mac/tclMacApplication.r: * mac/tclMacLibrary.r: * mac/tclMacOSA.r: * mac/tclMacResource.r: fixed obsolete copyrights/dates in version strings; updated version strings to standard usage; added support for '(Support Libraries)' subfolder for shared runtime libraries in unmerged binaries; commented out demo setting of "Tcl Environment Variables"; reorganized resources among these files to avoid multiple copies in applications and shared libraries, the script libraries are now no longer duplicated in Tclsh but are only included in the resources of Tcl.shlb. * mac/tclMacChan.c: * mac/tclMacSock.c: cast for *BlockMode * mac/tclMacUtil.c: * mac/tclMacMath.h: removed obsolete hypot() definition * generic/tclIntPlatDecls.h: * generic/tclInt.decls: * generic/tclStubInit.c: * mac/tclMacNotify.c: * mac/tclMacOSA.c: * mac/tclMacUtil.c: * generic/tclThreadTest.c: renamed routines conflicting with standard Apple or MoreFiles headers (at compile or link time): GetGlobalMouse -> GetGlobalMouseTcl FSpGetDirectoryID -> FSpGetDirectoryIDTcl FSpOpenResFileCompat -> FSpOpenResFileCompatTcl FSpCreateResFileCompat -> FSpCreateResFileCompatTcl NewThread -> NewTestThread the renamed MoreFiles *Tcl routines are just wrappers calling into the MoreFiles DLL. * mac/tclMacCommonPch.h: * mac/tclMacThrd.c: * mac/tclMacPanic.c: removed OLDROUTINENAMES define, renamed obsolete apple API names to modern equivalents; UH3.4 support: added #include , updated New*Proc() calls to New*UPP(). * mac/tclMacUnix.c: added missing (Tcl_Obj ***) cast to Tcl_ListObjGetElements call * mac/tclMacAlloc.c: modernized TclpSysAlloc() to use temporary memory instead of system heap memory when available (MacOS >= 7.5 and possibly earlier, use of system heap has been discouraged for a long time and has many disadvantages, e.g. memory isn't paged out, and errors can very easily bring the system down); fixed crashing bug in TclpSysRealloc() and CleanUpExitProc() where memory was being accessed after having been deallocated; fixed memory leak in (de)allocation code (for every block ever allocated with TclpSysAlloc, a Ptr was leaked), if temporary memory is available, don't track allocated memory, instead use RecoverHandle() to get Handle from Ptr, otherwise use doubly linked list to correctly track memory and free all allocated memory; added new option for ConfigureMemory: MEMORY_DONT_USE_TEMPMEM, disables use of temporary memory even when it would be available, only necessary when writing e.g. a driver (using tcl??); increased fraction of application heap reserved for OS routines to 512K * compat/strftime.c: * mac/tclMacTime.c: * mac/tclMacPort.h: * generic/tclInt.decls: * generic/tclIntPlatDecls.h: * generic/tclStubInit.c: timezone support for mac via TclpGetTZName() like on windows, using an inverse timezone table adapted from tclDate.c to map gmtoffset in seconds gotten from the MacOS APIs to a timezone string, as there is no good way to get this info from MacOS. I had to make up some unusual timezones and arbitrarily decide on the most standard of the multiple choices available for every timezone. * generic/tclExecute.c: workaround for a MSL bug/misfeature: for very small floats, MSL can return errno ERANGE but a non-zero value (< LDBL_MIN however) * mac/tclMacAppInit.c: support for WASTE text library using temporary memory, setting has no effect if WASTE is not used. * mac/tclMacPanic.c: removed duplicate code from generic/tclPanic.c and added that file to projects instead. * tests/all.tcl: set tcltest::singleProcess 1 as multiple processes are not available on the mac. * tests/cmdAH.test: access time not available on the mac, skip the atime touch test * tests/appendComp.test: * tests/cmdMZ.test: * tests/compile.test: * tests/exec.test: * tests/fileName.test: * tests/lset.test: * tests/namespace.test: * tests/tcltest.test: added missing cleanups/tests/catches that caused tests to fail on the mac. * doc/tclvars.n: doc bug, env(PWD) should be env(HOME) [Bug 463834] 2001-11-21 Don Porter * tests/trace.test (trace-8.8): Corrected test for Bug 219393. * generic/tclBasic.c (Tcl_DeleteCommandFromToken,CallCommandTraces): * generic/tclCmdMZ>c (Tcl_UntraceCommand): Added Tcl_Preserve and Tcl_Release calls to prevent deletion of CommandTrace structures until all callers are done using them, preventing memory corruption. [Bug 453805] 2001-11-20 Kevin B. Kenny * doc/GetTime.3 (Tcl_GetTime): * generic/tcl.decls (Tcl_GetTime): * generic/tclClock.c (Tcl_ClockObjCmd): * generic/tclCompile.c (TclCleanupByteCode, TclInitByteCodeObj): * generic/tclCmdMZ.c (Tcl_TimeObjCmd): * generic/tclUtil.c (TclpGetTime): * generic/tclTest.c (GetTimesCmd): * generic/tclTimer.c (Tcl_CreateTimerHandler, TimerSetupProc, (TimerCheckProc, TimerHandlerEventProc): * mac/tclMacNotify.c (Tcl_SetTimer): * mac/tclMacShLib.exp (Tcl_GetTime): * mac/tclMacTime.c (Tcl_GetTime): * unix/tclUnixChan.c (TclUnixWaitForFile): * unix/tclUnixEvent.c (Tcl_Sleep): * unix/tclUnixThrd.c (Tcl_ConditionWait): * unix/tclUnixTime.c (Tcl_GetTime): * win/tclWinNotify.c (Tcl_Sleep): * win/tclWinTest.c (TestwinclockCmd): * win/tclWinTime.c (TclpGetSeconds, TclpGetClicks, Tcl_GetTime): Changed all uses of TclpGetTime to Tcl_GetTime. Added Tcl_GetTime to the Stubs table and the library documentation. Added a TclpGetTime in tclUtil.c for backward compatibility of extensions. [Patch 483500, TIP#73] * generic/tclCmdMZ.c (Tcl_TimeObjCmd): Corrected an error in the [time] command that caused incorrect results to be returned if the total duration of all iterations exceeded 2**31 microseconds. [Bug 478847] * generic/tclInt.decls: * generic/tclInt.h: * generic/tclStubInit.h: Reran 'make genstubs' 2001-11-20 Miguel Sofer * generic/tclBasic.c * generic/tclCompile.h: * generic/tclExecute.c: moving all code relative to bytecodes from tclBasic.c to tclExecute.c - the functions RecordTracebackInfo and Tcl_ExprObj went to tclExecute.c, and new interface function was defined (TclCompEvalObj). The final objective of this sequence of moves is to provide a clean, clear-cut interface between Tcl's core and the compiler/engine subsystem. 2001-11-20 Miguel Sofer * generic/tclBasic.c * generic/tclCompile.h: * generic/tclExecute.c: factoring out of common code in tclBasic.c (new function TclInterpReady defined: it resets the interp's result, then checks that it hasn't been deleted and that the nesting level is acceptable). Passed the responsibility of calling it to the *callers* of TclEvalObjvInternal. 2001-11-20 Miguel Sofer * generic/tclBasic.c * generic/tclExecute.c: a better variant of the previous-to-last commit (restoring numLevels computations). The managing of the levels now has to be done by the *callers* of TclEvalObjvInternal 2001-11-20 Miguel Sofer * generic/tclExecute.c: missing variable declaration under TCL_COMPILE_DEBUG. 2001-11-20 Miguel Sofer * generic/tclExecute.c: * generic/tclProc.c: restoring the computations of iPtr->numLevels to the original logic (previous to buggy modifs on 2001-11-16). 2001-11-20 Jeff Hobbs * tools/eolFix.tcl (new-file): * unix/Makefile.in: added EOL correction for Windows bat files to dist target. [Bug 219409] (davygrvy) * unix/tclUnixInit.c (TclpSetInitialEncodings): update of patch from 2001-11-16 that uses the old Tcl encoding check mechanism as a fallback to the original. Also added a TCL_DEFAULT_ENCODING #define (defaults to iso8859-1). Tcl will first try setlocale and nl_langinfo, and if that fails, guess based on certain LANG|LC_* env vars. [Patch 418645] 2001-11-19 David Gravereaux * win/buildall.vc.bat: Added useful comments. 2001-11-19 Miguel Sofer * tests/compile.test: added a test for bug [Bug 483309] 2001-11-19 Vince Darley * win/tclWinFile.c: * win/tclWinFCmd.c: * win/tclWin32Dll.c: * doc/file.n: * tests/winFCmd.test: improved speed of file normalization for Win95/98, and clarified docs on differences in file normalization between NT/2000 and the older operating systems. Added test to ensure normalization is correct. 2001-11-19 Miguel Sofer * generic/tclBasic.c: * generic/tclParse.c: Code reorganisation. Moved all evaluation functions from tclParse.c to tclBasic.c, so that now tclParse.c deals exclusively with parsing and all evaluations are done by code in tclBasic.c. The functions moved are: TclEvalObjvInternal, Tcl_EvalObjv, Tcl_LogCommandInfo, Tcl_EvalTokensStandard, Tcl_EvalTokens, Tcl_EvalEx, Tcl_Eval, Tcl_EvalObj and Tcl_GlobalEvalObj. 2001-11-19 Donal K. Fellows * tests/trace.test (trace-8.8): Added adapted version of [Bug 219393] as new test; the test won't reliably show up the old problem unless it is being run under something like Purify, but something is better than nothing... * generic/tclVar.c (Tcl_TraceVar2, Tcl_UntraceVar2): Added missing mask bits for trace result type and a check for a nonsense flag combination. * generic/tclCmdMZ.c (TraceVarProc): Added missing test for NULL when deleting a trace that doesn't cause an error. * doc/TraceVar.3: Added documentation for change due to TIP#68. * generic/tclCmdMZ.c (TraceVarInfo): Removed problematic errMsg field from structure. (TraceVarProc): Removed references to errMsg field and changed handling of errors so that they returned a Tcl_Obj* containing the error string. This minimizes the number of calls to the memory management subsystem. (TclTraceCommandObjCmd, TraceCommandProc): Removed references to errMsg field which was never used in command traces in any case. (Tcl_TraceObjCmd, TclTraceVariableObjCmd): Removed references to errMsg field and made variable traces register with TCL_TRACE_RESULT_OBJECT bit set. * generic/tcl.h (TCL_TRACE_RESULT_DYNAMIC,TCL_TRACE_RESULT_OBJECT): New constants to define how to handle the strings returned from trace callbacks [TIP#68] * generic/tclVar.c (CallTraces, Tcl_GetVar2Ex, TclGetIndexedScalar, (TclGetElementOfIndexedArray, Tcl_SetVar2Ex, TclSetIndexedScalar, (TclSetElementOfIndexedArray, Tcl_UnsetVar2, Tcl_ArrayObjCmd, (TclDeleteVars, TclDeleteCompiledLocalVars, DeleteArray, (TclVarTraceExists): Support for those new trace flags. 2001-11-19 Miguel Sofer * generic/tclCompCmds.c: patch for [Bug 483309] (petasis). 2001-11-16 Kevin B. Kenny * generic/tclListObj.c: removed a C++-style comment that was inadvertently left in the source code. 2001-11-16 Jeff Hobbs * tests/interp.test: * generic/tclInterp.c (SlaveObjCmd): Corrected argument checking for '$interp alias|aliases|issafe'. [Patch 479560] (thoyts, hobbs) * unix/tclUnixInit.c: added HAVE_LANGINFO code block. * unix/configure: regened * unix/configure.in: added SC_ENABLE_LANGINFO call * unix/tcl.m4: made SHLIB_LD_LIBS='${LIBS}' for FreeBSD* (meyer) Added modified version of Wagner patch to make use of nl_langinfo where possible to determine Unix platform encoding, instead of the inflexible built-in system. This is used by default when possible, and can be disabled with --enable-langinfo=no. [Patch 418645] (hobbs, wagner) 2001-11-16 Miguel Sofer * generic/tclCompile.h: * generic/tclExecute.c: * generic/tclObj.c: moved Tcl_GetCommandFromObj and all defining code for tclCmdNameType objects to tclObj.c (from tclExecute.c). This code has nothing to do with bytecodes. 2001-11-16 Miguel Sofer * generic/tclBasic.c: * generic/tclCompile.h: * generic/tclExecute.c: * generic/tclParse.c: * generic/tclProc.c: * tests/stack.test: consolidation of duplicated code (in TclExecuteByteCode and EvalObjv); renaming of EvalObjv to TclEvalObjv as it is not static anymore; restored consistency of level counts between compiled and directly evaled code. [Bug 480896] 2001-11-12 David Gravereaux * win/makefile.vc: * win/rules.vc: Small bug fixes. * win/README: added some docs pointing to the docs in makefile.vc for it's use. 2001-10-17 Kevin B. Kenny * doc/lappend.n: * doc/lindex.n: * doc/linsert.n: * doc/list.n: * doc/llength.n: * doc/lrange.n: * doc/lsearch.n: * doc/lset.n (new-file): * doc/lsort.n: * generic/tclBasic.c (builtInCmds, Tcl_EvalObjEx): * generic/tclCmdIL.c (Tcl_LindexObjCmd, Tcl_LindexList): (Tcl_LindexFlat, Tcl_LsetObjCmd): * generic/tclCompCmds.c (Tcl_CompileLindexCmd, Tcl_CompileLsetCmd): * generic/tclCompile.c: * generic/tclCompile.h: * generic/tclExecute.c (TclExecuteByteCode): * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclListObj.c (TclLsetList, TclLsetFlat, TclSetListElement): * generic/tclObj.c (TclInitObjSubsystem): * generic/tclStubInit.c: * generic/tclTestObj.c (TestobjCmd): * generic/tclUtil.c (TclGetIntForIndex, SetEndOffsetFromAny): * generic/tclVar.c (Tcl_LappendObjCmd): * tests/lindex.test: * tests/lset.test (new-file): * tests/lsetComp.test (new-file): * tests/obj.test: * tests/string.test: * tests/stringComp.test: Reference implementation of TIP's #22, #33 and #45. Adds the ability of the [lindex] command to have multiple index arguments, and adds the [lset] command. Both commands are byte-code compiled. [Patch 471874] (work by Kenny, commited by Hobbs) 2001-11-12 David Gravereaux * win/buildall.vc.bat(new): * win/makefile.vc: Small fix with deriving the "OriginalFilename" string in the .rc scripts. Added a quick batchfile for building the entire thing. 2001-11-12 Jeff Hobbs * doc/FileSystem.3: * doc/file.n: * doc/tcltest.n: converted use of \' to more reasonable format. 2001-11-10 Mo DeJong * unix/Makefile.in: * win/Makefile.in: Add "make gdb" target. This target can run tclsh inside either gdb or insight. 2001-11-10 David Gravereaux * win/makefile.vc: Added a check to make sure one runs the makefile from the /win directory only. * win/mkd.bat: * win/rmd.bat: Changes from Llyod Lim for better stability. [Patch 456759] 2001-11-09 David Gravereaux * win/makefile.vc: * win/tcl.dsp: winhelp target fixes for non-NT systems. It seems NMAKE under these remembers changed directories during commands. A new tcltest feature from Peter Spjuth to specify a pattern file from the commandline and redirecting output to a file when not under NT with it's scrollback console. Then it replays it, piped through more. Added 2 new static "configurations" to tcl.dsp. I could keep adding more, but I think we should leave it up to the user for customizing it. Sticky-points left: 'profile' option. 2001-11-09 Jeff Hobbs * doc/FileSystem.3: * doc/StdChannels.3: * doc/file.n: * doc/tcltest.n: * tools/man2help.tcl: * tools/man2help2.tcl: fixed winhelp generation problems [Patch 480268] * unix/configure: * unix/tcl.m4: added -lc to AIX libs, fixed path to ldAix 2001-11-09 Don Porter * tests/var.test: * generic/tclVar.c: Corrected bug in [global] when dealing with variable names matching :*. [Bug 480176] 2001-11-08 Mo DeJong Fixup stack size under OSF1. [Patch 474790] * unix/configure: Regen. * unix/tcl.m4: Add HAVE_PTHREAD_ATTR_SETSTACKSIZE define to EXTRA_CFLAGS to adjust initial stack size. 2001-11-08 Mo DeJong Enable thread support under FreeBSD. [Bug 473708] * unix/configure: Regen. * unix/tcl.m4 (SC_ENABLE_THREADS): Check for pthread functions in libc_r and enable thread support if found. * unix/dltest/Makefile.in: Set SHLIB_LD_LIBS and use it in the Makefile to properly link a shared library. 2001-11-08 Mo DeJong * unix/Makefile.in: * unix/dltest/Makefile.in: Avoid adding libc to the LIBS variable since it is not needed when linking with CC. If required when linking with LD it should be done on a case by case basis in tcl.m4. 2001-11-08 David Gravereaux * win/rules.vc: * win/makefile.vc: Fixed install target to adjust for the different build types. Added a 'linkexten' option to link the win extensions inside the shell when built static. Placed win/tclAppInit.c patch in SF patch DB for approval. 'profile' option not hooked in yet. Everything else know is done. * win/tcl.dsp(new): * win/tcl.dsw(new): Simple MsDev stub project files that calls makefile.vc. Will help run Tcl in the debugger easier without confusing MsDev for where the .pdb files are. 2001-11-07 Mo DeJong * unix/Makefile.in: * win/Makefile.in: Print a message indicating that the user should run "make genstubs" when the generated tclStubInit.c file is out of date. We can't regenerate automatically since there may be no tclsh on the system and that would cause bootstrap problems. [Bug 465874] 2001-11-07 Mo DeJong Define TCL_INCLUDE_SPEC in tclConfig.sh. It should be included by extensions that need to find Tcl include headers in the install location. The user can override the include install dir with --includedir so we need to record this information for extensions. [Bug 421835] * unix/configure: Regen. * unix/configure.in: Define TCL_INCLUDE_SPEC. * unix/tclConfig.sh.in: Define TCL_INCLUDE_SPEC. * win/configure: Regen. * win/configure.in: Define TCL_INCLUDE_SPEC. * win/tclConfig.sh.in: Define TCL_INCLUDE_SPEC. 2001-11-07 David Gravereaux * win/rules.vc: * win/makefile.vc: Dropped the NOMSVCRT macro and put it on the option list instead. It makes more sense to me this way as NOMSVCRT=0 would only be the valid setting. Fixed the dde and reg extension for building static. Improved, but not perfected, the winhelp target. 2001-11-07 Mo DeJong * win/README: Change minimum VC++ version to 5.X since 4.X is known not to work. Indicate that Mingw is required and building with Cygwin gcc is not supported. Include instructions that indicate how to install Mingw and what URLs folks should use to download the supported version of Mingw. * win/configure: Regen. * win/configure.in: Error out if user tries to compile the Windows version of Tcl with Cygwin gcc. Users should compile with Mingw gcc instead. 2001-11-06 Andreas Kupries * generic/tclIO.c (ReadChars): Fixed [Bug 478856] reported by Stuart Cassoff . The bug caused loss of fileevents when [read]ing less data from the channel than buffered. Due to an empty input buffer the flag CHANNEL_NEED_MORE_DATA was set but never reset, causing the I/O system to wait for more data instead of using a timer to synthesize fileevents and to flush the pending data out of the buffers. 2001-11-06 David Gravereaux * win/rules.vc (new): * win/makefile.vc: Complete over/under rewrite to support numerous build options all from the commandline itself without needing to edit the makefile. Now requires vcvars32.bat to be run prior to running nmake for bootstraping the environment. Fully doc'd usage for it is in makefile.vc. Commentary welcome. Sticky points left are: 1) winhelp target shows errors in the converting script. 2) .rc scripts aren't getting the right #defines to build the correct "OriginalFilename" strings. (have patch, won't commit yet) 3) Naming convention with suffixes describing the buildtype are 'tsdx' which will need public acceptance. ie. tclsh84tsx.exe is a (t) threaded shell (s) statically linked to the core and (x) uses msvcrt instead of libcmt. 2001-11-04 Vince Darley * library/init.tcl: made filesystem fallback proc ::tcl::CopyDirectory more robust to vagaries of non-native filesystems. 2001-11-02 Vince Darley * doc/file.n: * generic/tclIOUtil.c: updated documentation and comments to clarify behaviour of 'file copy' wrt soft links. 2001-10-29 Vince Darley * win/tclWinFile.c: fix to '-types {f r}' bug in TclpMatchInDirectory (which could cause a UMR, as well as returning wrong results). Also improved API for 'stat' to resolve [Bug 219258]. * win/tclWin32Dll.c * win/tclWinInt.h: addition of improved stat API to internal lookup table. * tests/fileName.test: two new tests for the above bug. * generic/tclIOUtil.c: some cleanup of comments and #ifdefs 2001-10-29 Donal K. Fellows * unix/tclUnixFile.c (TclpMatchInDirectory): Argument to access() was entryPtr->d_name instead of nativeEntry which failed when trying to check access for files in other than the current directory. [Bug 475941, reported by Georgios Petasis] 2001-10-25 Donal K. Fellows * unix/tclUnixChan.c: Added stateUpdated member to struct TtyState. (TtyCloseProc,TtySetOptionProc,TtyInit): Use stateUpdated member of TtyState to decide whether it is necessary to reset a serial port when Tcl closes it. Blindly resetting can cause Tcl to be sent an unexpected SIGTSTP when it is executing in the background [Bug 471374, reported by Chris Nelson] 2001-10-22 Andreas Kupries * doc/ObjectType.3: Minor documentation fix, reported by David N. Welton directly to me. 2001-10-22 Vince Darley * win/tclWinFCmd.c: fix to stop test suite from hanging process under some versions of WinNT. [Bug 466102] (Kevin Kenny) 2001-10-18 Jeff Hobbs * tests/clock.test (clock-8.1): * generic/tclDate.c (RelativeMonth): * generic/tclGetDate.y (RelativeMonth): corrected off-by-one-day error in clock scan with relative months and years during swing hours. [Bug 413397, Patch 414024] (lavana) 2001-10-18 Vince Darley * generic/tclIOUtil.c: fix to bug in Tcl_FSChdir shown up by recent tclkit builds. 2001-10-17 Jeff Hobbs * unix/tclUnixPipe.c (PipeInputProc, PipeOutputProc): do immediate retry when error is returned with errno == EINTR. [Bug 415131] (leger) 2001-10-16 Jeff Hobbs * unix/tclLoadAout.c (TclGuessPackageName): removed unused vars and fixed warnings. [Bug 446622] (lim) 2001-10-15 Miguel Sofer * generic/tclProc.c: changing a memcmp to strncmp to avoid a memory error detected by purify (thanks Jeff); modify style to agrre with the style guide. 2001-10-15 Andreas Kupries * generic/tclInt.decls (TclExpandCodeArray,TclGetInstructionTable): Added to internal stubs table. Tclcompiler (Tclpro project) needs them if used as loadable package under Windows. Changed signatures. We don't want to describe compiler internal structures in "tclInt.h". * generic/tclCompile.h: S.a. Removed function declarations. * generic/tclCompile.c: S.a. Adapted to changed signatures. 2001-10-15 Jeff Hobbs * unix/configure: * unix/configure.in: * win/configure: * win/configure.in: * win/tcl.m4: reworked to be a little cleaner in comparison to each other, and to AC_SUBST even empty vars for win/tclConfig.sh * generic/tclFileName.c: minor code cleanup * generic/tcl.h: moved #define of WIN32 to tcl.h where __WIN32__ is defined and added #ifndef check. * doc/open.n: moved all fconfigure option docs to fconfigure.n * doc/fconfigure.n: added serial config options * win/tclWinChan.c: * win/tclWinPort.h: * win/tclWinSerial.c: added TIP #35 Windows enhancements for serial configuration. [Patch 438509] (schroedter) 2001-10-15 Vince Darley * generic/tclFCmd.c: fix to memory leak in TclFileDeleteCmd on certain error conditions. * doc/FileSystem.3: fix to typo. 2001-10-12 Jeff Hobbs * library/encoding/ebcdic.enc: * tools/encoding/ebcdic.txt: EBCDIC charset mapping. [Patch 219323] (nijtmans) * library/encoding/tis-620.enc: * tools/encoding/tis-620.txt: TIS-620 charset mapping. [Patch 467423] (poonlap) * tests/http.test: added removeFile for outdata * tests/ioCmd.test: added catch around file removal, as Windows file locking throws errors. * tests/socket.test (socket-7.2): corrected to work on Win2K. 2001-10-12 Miguel Sofer * tests/compile.test: new tests for [Bug 467523]; they are only effective if TCL_MEM_DEBUG was set during compilation. 2001-10-11 Miguel Sofer * generic/tclLiteral.c (TclReleaseLiteral): insured that self-referential bytecodes are properly cleaned up on interpreter deletion [Bug 467523] (Ronnie Brunner) 2001-10-10 David Gravereaux * win/tclWinPort.h: #include needed to get moved to after #include or wierd misunderstandings took place when -D_WIN32_WINNT=0x0400 is set for outside code that requires knowledge of Tcl innards. General header macro magic applied liberally... 2001-10-10 Don Porter * tests/unixInit.test: Corrected restore of ::env(LANG). 2001-10-09 Jeff Hobbs * generic/tclFileName.c (Tcl_SplitPath): corrected mem leak intro'd with VFS code where the result obj from Tcl_FSSplitPath was not getting freed. 2001-10-09 Miguel Sofer * generic/tclLiteral.c: (TclReleaseLiteral) reverted previous patch for [Bug 467523] - cure is worse than the illness. 2001-10-05 Miguel Sofer * generic/tclLiteral.c: (TclReleaseLiteral) insured that self-referential bytecodes are properly cleaned up on interpreter deletion. [Bug 467523] (Ronnie Brunner) 2001-10-04 Jeff Hobbs * tools/configure: * tools/configure.in: noted 8.4 as default Tcl version * library/encoding/cp936.enc: * library/encoding/cp949.enc: * library/encoding/cp950.enc: * library/encoding/iso8859-16.enc: * library/encoding/macCroatian.enc: * library/encoding/macCyrillic.enc: * library/encoding/macGreek.enc: * library/encoding/macIceland.enc: * library/encoding/macRoman.enc: * library/encoding/macTurkish.enc: * tools/encoding/cp1250.txt: * tools/encoding/cp1251.txt: * tools/encoding/cp1252.txt: * tools/encoding/cp1253.txt: * tools/encoding/cp1254.txt: * tools/encoding/cp1255.txt: * tools/encoding/cp1256.txt: * tools/encoding/cp1257.txt: * tools/encoding/cp1258.txt: * tools/encoding/cp874.txt: * tools/encoding/cp932.txt: * tools/encoding/cp936.txt: * tools/encoding/cp949.txt: * tools/encoding/cp950.txt: * tools/encoding/iso8859-1.txt: * tools/encoding/iso8859-10.txt: * tools/encoding/iso8859-13.txt: * tools/encoding/iso8859-14.txt: * tools/encoding/iso8859-15.txt: * tools/encoding/iso8859-16.txt: * tools/encoding/iso8859-2.txt: * tools/encoding/iso8859-3.txt: * tools/encoding/iso8859-4.txt: * tools/encoding/iso8859-5.txt: * tools/encoding/iso8859-6.txt: * tools/encoding/iso8859-7.txt: * tools/encoding/iso8859-8.txt: * tools/encoding/iso8859-9.txt: * tools/encoding/koi8-r.txt: * tools/encoding/macCentEuro.txt: * tools/encoding/macCroatian.txt: * tools/encoding/macCyrillic.txt: * tools/encoding/macGreek.txt: * tools/encoding/macIceland.txt: * tools/encoding/macRoman.txt: * tools/encoding/macTurkish.txt: Updated encodings with latest mappings from www.unicode.org. This did not include some Mac encodings that have special multi-unichar translations now (like symbols, dingbats and japanese). Also does not include big5, gb or euc* as those have different formats in the latest Unicode version that need new conversion tools. Not all related .enc files changed as some had been updates separately. 2001-10-03 Jeff Hobbs * generic/tclEvent.c (Tcl_FinalizeThread): moved freeing of tclLibraryPath to before the thread exit handlers are called. Slight modification to change on 2001-09-24. 2001-10-01 Jeff Hobbs * win/configure: regen'ed * win/tcl.m4: * win/makefile.vc: added Win64 SDK RC1 compilation support * win/Makefile.in: added $(LDFLAGS_CONSOLE) to TCLSH, TCLTEST and PIPE_DLL_FILE targets to get the link flags * win/tclWinInit.c: minor 64bit casts 2001-10-01 Miguel Sofer * generic/tclCmdIL.c: * generic/tclCmdMZ.c: * generic/tclParseExpr.c: removed unnecessary inclusion of tclCompile.h and made a small modification in (InfoBodyCmd) to improve the isolation of the compiler/engine subsystem. 2001-09-29 Vince Darley * generic/tclIOUtil.c: * doc/FileSystem.3: corrected and clarified documentation for 'Tcl_FSListVolumes(Proc)'. No code changes. 2001-09-28 Miguel Sofer * doc/FindExec.3: added a comment not to change the working directory before calling Tcl_GetNameOfExecutable. [Bug 219215] 2001-09-28 Kevin Kenny * generic/tclIO.c: added two more '(ClientData)' casts on calls to Tcl_Preserve and Tcl_Release -- ones that Vince apparently missed. 2001-09-28 Donal K. Fellows * doc/lsort.n: Improved doc... * generic/tclCmdIL.c (Tcl_LsortObjCmd, SortCompare): Made offset-from-end indexing work, and factored out some "magic numbers" for easier understanding. [Bug 465674] * tests/cmdIL.test (cmdIL-1.26): Added test for offset-from-end indexing for lsort. 2001-09-28 Vince Darley * win/tclWinFCmd.c: * unix/tclUnixFCmd.c: fix to performance issue reported by jcw in which 'access("")' is called unnecessarily when normalizing any absolute path. * generic/tclIO.c: added '(ClientData)' cast to calls to Tcl_(Preserve|Release) newly introduced, fixing compile error on Windows. 2001-09-27 Don Porter * doc/FileSystem.3 (Tcl_FSLoadFile): * generic/tcl.decls (Tcl_FSLoadFile): * generic/tcl.h (Tcl_FSLoadFileProc): * generic/tclInt.h (TclpLoadFile): * generic/tclIOUtil.c (Tcl_FSLoadFile): * generic/tclLoadNone.c (TclpLoadFile): * generic/tclTest.c (TestReportLoadFile): * library/ldAout.tcl: * mac/tclMacLoad.c (TclpLoadFile): * unix/tclLoadAix.c (TclpLoadFile): * unix/tclLoadAout.c (TclpLoadFile): * unix/tclLoadDl.c (TclpLoadFile): * unix/tclLoadDld.c (TclpLoadFile): * unix/tclLoadDyld.c (TclpLoadFile): * unix/tclLoadNext.c (TclpLoadFile): * unix/tclLoadOSF.c (TclpLoadFile): * unix/tclLoadShl.c (TclpLoadFile): * win/tclWinLoad.c (TclpLoadFile): * win/tclWinFCmd.c (DoRemoveJustDirectory): More CONST poisoning fixes from the 2001-09-24 TIP 27 changes. CONST-ified Tcl_FSLoadFile and TclpLoadFile. Report and patch from Kevin Kenny. [Bug 465833] * generic/tclIO.c (ChannelTimerProc): Added Tcl_Preserve() and Tcl_Release() to fix segfault introduced by the 2001-09-26 changes. [Bug 465494] * doc/TCL_MEM_DEBUG.3: Updated out-of-date reference to #define GUARD_SIZE. * doc/UpVar.3 (Tcl_UpVar,Tcl_UpVar2): * generic/tcl.decls (Tcl_UpVar,Tcl_UpVar2): * generic/tclInt.decls (TclFindProc,TclGetFrame): * generic/tclInt.h (TclFindProc,TclGetFrame,TclLookupVar, (TclPrecTraceProc,TclProcInterpProc}): * generic/tclProc.c (TclGetFrame,TclFindProc): * generic/tclVar.c (Tcl_UpVar,Tcl_UpVar2,MakeUpvar): Updated APIs in generic/tclProc.c and generic/tclVar.c according to the guidelines of TIP 27. [Patch 465442] * generic/tclDecls.h: * generic/tclIntDecls.h: make genstubs 2001-09-26 Andreas Kupries * doc/fileevent.n: Accepted [Patch 465279] adding an example to the fileevent manpage. Minor modifications to get a better formatting. Report and patch by David N. Welton . * The changes below fix [Bug 462317] where Expect tried to read more than was in the buffers and then blocked in the OS call as its pty channel driver provides no blockmodeproc through which the OS could be notified of blocking-behaviour. Because of this the general I/O core has to take more care than usual to preserve the semantics of non-blocking channels. The problem was reported by "Kevin O'Gorman" . * generic/tclIO.c (Tcl_ReadRaw): Do not read from the driver if the channel is non-blocking and the fileevent causing the read was generated by a timer. We do not know if there is data available from the OS. Instead of going to the OS for more and potentially blocking we simply signal EWOULDBLOCK to the higher levels to cause the system to wait for true fileevents. (GetInput): Same as before. (ChannelTimerProc): Added set and clear of CHANNEL_TIMER_FEV. * generic/tclIO.h (CHANNEL_TIMER_FEV): New flag for channels. Is set if a fileevent was generated by a timer, the channel is not blocking and the driver did not provide a blockmodeproc. In that case the I/O core has to be especially careful about going to the driver for more data. 2001-09-26 Don Porter * doc/SplitPath.3 (Tcl_GetPathType): * generic/tcl.decls (Tcl_GetPathType): * generic/tclFileName.c (Tcl_GetPathType): * win/tclWinFile.c (TclpMatchInDirectory, NativeStat): Vince Darley reports the 2001-09-24 TIP 27 changes left the win directory CONST poisoned. These changes should fix that. * generic/tclDecls.h: make genstubs 2001-09-25 Don Porter * doc/GetInt.3: * generic/tclInt.h (TclGetLong deleted): * generic/tcl.decls: * generic/tclInt.decls: * generic/tclGet.c: Updated APIs in generic/tclGet.c according to the guidelines of TIP 27. [Patch 464674] * generic/tclDecls.h: * generic/tclIntDecls.h: make genstubs 2001-09-25 Miguel Sofer * generic/tclVar.c: removed comments referring to unused flag TCL_PARSE_PART1. 2001-09-24 Don Porter * doc/Concat.3: * doc/DString.3: * doc/SplitList.3: * generic/tclInt.h (TclCheckBadOctal): * generic/tcl.decls: * generic/tclInt.decls: * generic/tclEncoding.c (OpenEncodingFile): * generic/tclMain.c (Tcl_Main): * generic/tclUtil.c: * unix/tclLoadDl.c (TclpLoadFile): Updated APIs in generic/tclUtil.c according to the guidelines of TIP 27. [Patch 464553] * generic/tclDecls.h: * generic/tclIntDecls.h: make genstubs 2001-09-24 Andreas Kupries The change below fixes [Bug 464380]. The bug was reported by Ronnie Brunner . He also provided the patch. * generic/tclEvent.c (Tcl_Finalize): Moved release of 'tclLibraryPath' to Tcl_FinalizeThread. (Tcl_FinalizeThread): See above, new place for release of 'tclLibraryPath'. 2001-09-24 Donal K. Fellows * tools/encoding/cp1252.txt: File was missing part of the encoding [euro, ZCaron and zcaron]. * doc/OpenFileChnl.3: Add docs for Tcl_OutputBuffered; remove some old changebars. 2001-09-21 Jeff Hobbs * generic/tclExecute.c (TclExecuteByteCode): corrected INST_STR_CMP else case for strings to pass true utf char length to Tcl_UtfNCmp. 2001-09-20 Jeff Hobbs * win/tclWinInit.c: added extra processor definitions. (mstacy) * win/tclWinSock.c (SocketThread): corrected pointer cast for _WIN64. * win/tclWinNotify.c: removed unnecessary winsock include (it is already in from tclWinPort.h). * win/tclWinPort.h: changed winsock.h include to winsock2.h. Reverses change from 2000-11-16, but is necessary for WIN64. Extensions should comply with defined OS words, or use #ifndef. 2001-09-20 Donal K. Fellows * tests/socket.test: removed dependence on being run from same dir as remote.tcl, which only now needs to be in the same dir as this file. [Bug 219326] 2001-09-19 Jeff Hobbs * generic/tclTest.c (TestcmdtokenCmd): corrected pointer storage/retrieval for 64bit machines. * generic/tclCmdAH.c (Tcl_FormatObjCmd): * generic/tclScan.c (Tcl_ScanObjCmd): corrected handling of format and scan on 64-bit machines. [Bug 412696] (rmax) * unix/configure: regen'ed * unix/tcl.m4: added --enable-64bit support for HP-11 with the 64-bit kernel. * tests/basic.test: * tests/cmdInfo.test: improved skip reporting of missing commands * tests/winFCmd.test: simplified error check for winFCmd-7.9 * tests/winPipe.test: removed obsolete cat16 tests * generic/tclExecute.c (TclExecuteByteCode): fixed invalid usage of valuePtr in TRACE_WITH_OBJ in INST_EVAL_STK case. [Bug 462594] Changed INST_STR_CMP instruction to promote to Unicode strings only when one of the strings is already of Unicode type. * generic/tclExecute.c (TclExecuteByteCode): * generic/tclCompile.c (instructionTable): * generic/tclCompCmds.c (TclCompileStringCmd): INST_STR_MATCH - Updated to Int1 instruction type and added special case to use INST_STR_EQ instead when no glob chars are specified in a static string. * tests/{for.test,foreach.test,if.test,while.test}: * generic/tclCompCmds.c (TclCompileForCmd, TclCompileForeachCmd, TclCompileIfCmd, TclCompileWhileCmd): Corrected the overaggressive compiling of loop bodies enclosed in ""s. [Bug 219166] (msofer) 2001-09-19 Miguel Sofer * generic/tclExecute.c: insured that execution stack errors are also detected at abnormal returns. 2001-09-19 Donal K. Fellows * doc/socket.n: Added documentation to mention what happens when a server socket is created with port=0. Removed an old change bar, and no new change bar because Tcl has always behaved this way as it is really a poorly-documented standards-defined OS feature. * tests/util.test (util-8.1): Test derived from code to detect the problem, but the test always works in the C locale, so beware if you are maintaining the code. * generic/tclUtil.c (TclNeedSpace): Rewrote to be UTF-8 aware. [Bug 411825, but not that patch which would have added extra spaces if there was a real non-ASCII space involved.] 2001-09-18 Andreas Kupries * generic/tclIOCmd.c (Tcl_PutsObjCmd): Rewritten to have saner and faster argument handling. [Bug 123552], [Patch 402564] (fellows) 2001-09-18 Don Porter * unix/configure: Regen. * unix/tcl.m4 (SC_CONFIG_CFLAGS): On Linux, disable inlining when one of the compat/*.c routines is to be linked in. [Patch 440891] 2001-09-17 Jeff Hobbs * generic/tcl.h: removed forced #define USE_TCLALLOC 1 for Windows. This means the native system allocator will be used by default. This should be binary and source compatible with extensions, as Tcl_Alloc is a properly stubbed function. 2001-09-17 Miguel Sofer * generic/tclExecute.c: corrected small bug in [Patch 456668] - the varFramePtr was not restored in one possible exit. 2001-09-17 Miguel Sofer * doc/tclvars.n: * generic/tclCompile.c: * generic/tclCompile.h: * generic/tclExecute.c: * generic/tclProc.c: disabled all compile and execution tracing functionality in standard builds; TCL_COMPILE_DEBUG is now necessary to enable it. [Bug 451858] 2001-09-14 Andreas Kupries * doc/gets.n: * doc/read.n: * doc/puts.n: * doc/flush.n: * doc/fconfigure.n: * doc/flush.n: * doc/eof.n: * doc/seek.n: * doc/tell.n: * doc/close.n: * doc/fileevent.n: Added references to the Tcl standard channels. Item [219250], reported by David LeBlanc . Thanks to Christopher Nelson for doing editorial work. 2001-09-13 Andreas Kupries * win/Makefile.in: * win/configure.in: * win/makefile.bc: * win/makefile.vc: * library/dde/pkgIndex.tcl: Fixed version numbers from bogus tcl versions to independent versions for dde and registry packages. 2001-09-13 Jeff Hobbs * tests/regexp.test (regexp-20.1): * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): had to adjust fix from 2001-08-06 to actually duplicate the objects in certain cases. This is really a place where feather would have been essential. [Bug 461322] * generic/tclUtf.c (Tcl_UtfPrev): corrected to return the proper location when the middle of a UTF-8 byte was passed in [Tk Bug 450504] * ChangeLog.1999: * ChangeLog: broke changes from 199x into ChangeLog.1999 to reduce size of the main ChangeLog. 2001-09-13 Andreas Kupries * tests/ioCmd.test: Changed the computation of the result for iocmd-8.1[123] so that the tests work for single- and multi-process execution of the testsuite. Depending on the choice of the user stdout is a tty or not and thus reports different channel options. Fixes [460993] reported by Don Porter. 2001-09-13 Miguel Sofer * doc/ParseCmd.3: * generic/tcl.decls: * generic/tclCmdMZ.c (Tcl_SubstObjCmd): * generic/tclDecls.h: * generic/tclParse.c: * generic/tclStubInit.c: * tests/parse.test: Deprecate the use of Tcl_EvalTokens, replaced by the new Tcl_EvalTokensStandard. The new function performs the same duties but adheres to the standard return convention for Tcl evaluations; the deprecated function could only return TCL_OK or TCL_ERROR, which caused [Bug 219384] and [Bug 455151]. This patch implements [TIP 56]. 2001-09-12 Mo DeJong * unix/configure: Regen. * unix/tcl.m4: Invert the logic that checks for $GCC. Instead of checking for "$GCC" = "no" we check for "$GCC" != "yes" or simply swap the true and false blocks of code in an if statement. That way if GCC is set to "" everything will still work. [Bug 460991] 2001-09-12 Don Porter * tests/appendComp.test: * tests/lsearch.test: * tests/namespace.test: * tests/rename.test: * tests/split.test: Corrected tests to better isolate tests in one file from influencing tests in other files. [Bug 460591] 2001-09-12 Miguel Sofer * generic/tcl.decls: reserved stub #481 for the implementation of [TIP 56] 2001-09-11 Andreas Kupries * doc/OpenFileChnl.3: Added documentation for Tcl_WriteRaw and Tcl_ReadRaw [Bug 414929]. * doc/CrtChannel.3: Added documentation for Tcl_ChannelBuffered and Tcl_GetTopChannel [Bug 414929]. * The changes below are a fix for [Bug 219253]. * tests/socket.test: Removed _most_ instances of hardwired port numbers for listening sockets. Remaining are the ports in all tests with constraint 'doTestsWithRemoteServer'. These seem to be designed for a more controlled environment and are usually skipped when running the testsuite. * tests/io.test: Removed all instances of hardwired port numbers for listening sockets. 2001-09-10 Jeff Hobbs * generic/tclEvent.c (TclInExit): Corrected handling of tsd in late stages of finalization. [Bug 419449] (darley) * tests/stack.test: * generic/tclInterp.c (AliasObjCmd): Check the numLevels to ensure that we aren't hitting some alias loop condition. [Bug 443184] 2001-09-10 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_CONFIG_CFLAGS): Don't include . characters in the Tcl library name when building on FreeBSD 3.X and later systems. [Patch 450725] 2001-09-10 Andreas Kupries * doc/tclsh.1: * doc/Tcl_Main.3: * doc/CrtChannel.3: * doc/OpenFileChnl.3: * doc/GetStdChan.3: Enhanced the manpages with cross-references to the new manpage and more explanations how these functions deal with the standard channels in various situations. * doc/StdChannels.3: New manpage describing handling of the standard channels by the Tcl library. [Bug 402725] 2001-09-10 Don Porter * unix/mkLinks (Tcl_FSLink): Updated to reflect 2001-08-23 file system changes. * unix/tclLoadShl.c: Added #include of tclInt.h; access to Tcl internals, notably TclpUnloadFile(), is required. Thanks to Bob Techentin for report and patch. [Bug 459305] * generic/tclInitScript.h (initScript): * win/tclWinInit.c (TCL_REGISTRY_KEY, TclpSetVariables): Removed vestiges of Tcl's old initialization from registry variables. [Bug 455645] 2001-09-10 Andreas Kupries * generic/tclInt.decls: Also added 'TclWinFlushDirtyChannels' to the internal platform specific stub table. * win/tclWinFile.c (TclpObjStat): Now added the call to 'TclWinFlushDirtyChannels' to this function. I don't know where my head was last thursday (2001-09-06), but the call was actually added to 'TclpObjChdir', i.e. the implementation of [cd]. Corrected this now. Thanks to Vince Darley for spotting this. 2001-09-10 Miguel Sofer * generic/tclProc.c: * tests/proc.test: made [proc] bytecompile a no-op for procs defined with _args_ as single argument and an empty body. [FRQ 451441] 2001-09-09 Mo DeJong * unix/Makefile.in: * win/Makefile.in: Use () around variable name instead of {}. Use TCLTEST variable directly instead of depending on the tcltest alias. 2001-09-09 David Gravereaux * generic/tcl.h: * generic/tclPlatDecls.h: Reminder from David Cuthbert that I hadn't finished the Borland compatibility stuff. [Patch 436116] 2001-09-09 Mo DeJong * tests/cmdAH.test: Modify cmdAH-20.5 and cmdAH-24.8 to display the file atime or mtime results if the test fails. 2001-09-08 David Gravereaux * win/mkd.bat: * win/rmd.bat: made these text files, text files again. [Patch 451333] 2001-09-08 Mo DeJong * win/mkd.bat: * win/rmd.bat: Apply binary property (cvs admin -kb) to files and convert to CRLF linefeed format to fix the VC++ build. [Bug 219409] 2001-09-08 Vince Darley * generic/tclInt.h: * generic/tclFCmd.c: * doc/FileSystem.3: * generic/tclIOUtil.c: removed Tcl_FSCopyFile fallback to channel copying, since the channels will not have access to interpreters and the channel copying currently requires an interp. Code which required cross-platform copies always has interpreters, so that solves the problem. Fixes bug in TclKit. 2001-09-07 David Gravereaux * win/tcl.m4: Added -link50compat option so a VC6 linker makes a VC5 (pre sp3) compatible import library. [Bug 219257] 2001-09-07 Mo DeJong * win/tclWinThrd.c (TclpThreadExit): Cast status argument to _endthreadex to unsigned instead of DWORD to match the Win32 function prototype. 2001-09-06 Andreas Kupries * All the changes below serve to fix bug [219148] which reports a 80x performance hit for file I/O on Win* systems. On my system it was closer to a 120x hit. Problem report by Uwe Traum . The fix goes like this: The obstacle is 'FlushFileBuffers', executed whenever Tcl writes data to the OS, as Tcl has to wait for the disk to complete I/O, and disks are slow. We remove that obstacle. This opens another problem, [file size] reports back wrong numbers. So for [file size] we add the call back in. As optimization we keep track of the channels which were written to and flush only these. * win/tclWinFile.c (TclpObjStat): Added a call to 'TclWinFlushDirtyChannels'. This ensures that [file size] and related commands report the correct size of a file even if Tcl has recently written to it. Unixoid OS's always report the correct size even for files with pending data, but Win* syssystem don't. They only report what is actually on disk. * win/tclWinInt.h: Added declaration of 'TclWinFlushDirtyChannels', making it available to other parts of the tcl core. * win/tclWinChan.c (TclWinFlushDirtyChannels): New, internal, procedure. Goes through the list of open file channels and forces the OS to flush its file buffers for all which were written to since the last call of this function. This is an expensive operation as Tcl has to wait for the OS to complete actual writes to the disk. (FileInfo): Added dirty flag required by the procedure above. (FileOutputProc): Removed flushing of file buffers, setting the dirty flag instead. This means that the previously incurred delays do not happen anymore. (TclWinOpenFileChannel): Added initialization of 'dirty' flag. 2001-09-06 Jeff Hobbs * doc/http.n: noted -binary, charset and coding state keys. * tests/http.test: * library/http/pkgIndex.tcl: * library/http/http.tcl (geturl): correctly get charset parameter and convert text according to specified encoding (if known). RFC iso8859-1 is used by default. Also recognize Content-encoding to see if we should do binary translation. Added a CYA -binary switch for the cases that were missed. [Bugs 219211, 219399] * tests/ioUtil.test: changed to make better use of constraints and remove knownBug constraints that weren't valid. 2001-09-06 Don Porter * tests/unixInit.test (unixInit-3.2): Updated test to support newer HP-UX releases that properly report euc-jp as the system encoding for Japanese. Bug report and patch verification by Bob Techentin. [Bug 453883] * doc/http.n: * library/http/*.tcl: * tools/tcl.wse.in: * tools/tclmin.wse: * unix/Makefile.in: * win/{Mm}akefile.*: Updated http package to version 2.4, reflecting the new features just added. 2001-09-06 Vince Darley * generic/tclTest.c: tests of old-fs hooks no longer cause problems in threaded builds. Also removed unused unload proc. * generic/tcl.decls: * generic/tclIOUtilc: added Tcl_FSMountsChanged so that a vfs can inform the filesystem that the filesystem epoch must be changed (since cached filesystems may now be incorrect). Fixes problem running tclvfs extension. * library/tcltest/tcltest.tcl: if tests aren't in a native filesystem, then don't use pipes to run them. [Bug 458741] 2001-09-06 Donal K. Fellows * generic/tcl.decls (479 generic): * generic/tclIO.c (Tcl_Seek,Tcl_Tell,Tcl_OutputBuffered): Added public function to return the size of the output buffer and reworked other channel functions to use this shared functionality and that of Tcl_InputBuffered() too. [TIP#49, Rolf Schroedter] 2001-09-05 David Gravereaux * generic/tclPlatDecls.h: Another small trim finalizing Borland support. * win/tclWinPipe.c: * win/tclWinPort.h: More Borland compatibility fixes. Changed EDQUOT #define from 49 to 69. Borland had a clash as it was already using this number. Upon advice from Helmut Giese, EDQUOT has been found in other header files #defined as 69. [Patch 436116] * win/.cvsignore: A few more glob patterns added. * win/makefile.bc (new): Borland lives once more! rejoice.. * generic/tclAlloc.c: Small Borland compatibility fix. * win/tclWinTime.c: More Borland compatibility fixes. [Patch 436116] 2001-09-05 Vince Darley * tests/winFCmd.test: made notWin2000 constraint false if not running on Windows at all. 2001-09-04 David Gravereaux * win/tclWinThrd.c: Revisited _beginthreadex() stuff. Instead of assuming a c-runtime implimentation of _beginthreadex normal, I reversed the logic to not assume, and use when is by explicitly needing to add runtimes that support it such as Borland. * generic/tcl.h: * generic/tclPlatDecls.h: Borland compatibility change so ClientData was properly typed as a void* and TCHAR would not be defined twice. * generic/tcl.h: Removed a small mistake from before. Changes to the EXTERN macro for proper Borland compatibility will have to see a TIP. What's this with the MS compiler: __declspec(dllexport) int func (int a, int b); will have to be this with Borland: int __cdecl __export func (int a, int b); The order of the attribute needs to be after the return type. 2001-09-04 Don Porter * compat/strtod.c (strtod): Fixed failure to handle expressions like 3eq2 and failure to set errno on overflow. [Bug 440894] 2001-09-04 Miguel Sofer * generic/tclProc.c: * tests/proc.test: made [proc] check that formal args have simple names. [Bug 458548] 2001-09-04 Vince Darley Minor bug fixes in filesystem, plus small vfs changes as a result of enabling the test filesystem to work properly. * tests/fileName.test: ensure new test cleans up after itself * doc/filename.n: * generic/tclFileName.c: improved Mac path handling and document why [Bug 421842] on Windows handling of UNC paths is not valid. Documentation and code now much clearer on what is and is not a UNC path. * doc/FileSystem.3: * unix/tclUnixPipe.c: * generic/tclFCmd.c: * generic/tclIOUtil.c: fixed error message, fixed [Bug 453512] about dangerous use of tmpnam, replaced with mkstemp. Documented all the changes. * generic/tclTest.c: made test vfs fully functional as a 'reporting filesystem'. * generic/tcl.stubs: * generic/tcl.h: * generic/tclInt.h: * generic/tclIOUtil.c: * doc/file.n: * various platform-specific 'TclpLoadFile': fixed comments about unload behaviour, and completed objectification of loading. Required change to Tcl_Filesystem lookup table, so incompatible with 8.4a3, but not older versions of Tcl. The change also allows 'link' and 'reporting' filesystems to function correctly when loading files. Implementation of 'file delete -force' copes with case where cwd is inside the directory. Moved overlooked Tcl_FSGetPathType from internal to external API. Made sure filesystems which are registered and then unregistered are only freed when all references to them are gone. Documented changes. * unix/tclUnixFCmd.c: when deleting directories recursively, make sure permissions are ok. Together with the above, this fixes [Bug 219139] * tests/winFCmd.test: differentiated test results for win2k versus not. This fixes [Bug: 219239] * tests/fCmd.test: added tests for 'file delete -force' where the cwd is inside, and when permissions are inadequate. 2001-09-04 Miguel Sofer * generic/tclCompile.c: fixed incorrect operands for INST_LIST [Bug 458241] (David Cuthbert, dacut@users.sourceforge.net) 2001-09-03 Jeff Hobbs * generic/tclExecute.c (TclExecuteByteCode): fixed missing comma in debug macro. 2001-09-03 Donal K. Fellows * doc/ExprLongObj.3: Fixed error in documentation of argument type to Tcl_ExprObj [Bug 457435] 2001-09-02 David Gravereaux * win/tclWinThrd.c: Portability fix for Cygwin who's c-runtime, not surprisingly, doesn't have the MSVCRT specific _beginthreadex / _endthreadex pair. This might have to be revisited for proper Borland, lcc32, Watcom and other support as well. [Patch 444255] * win/tclWinThrd.c: Moved FinalizeConditionEvent() proto to within the main #ifdef TCL_THREADS block to avoid mingw warning about it being there but unused. * win/makefile.vc: Added -Zl (zee el) to tclStubLib.c compile line to make sure the tclstub84.lib static library is built without requiring a specific C-runtime library at link-time for the end-use developer. It has been noted on c.l.t that this trips many first time users trying to make extensions. [Patch 403533] 2001-08-31 Jeff Hobbs * generic/tclInt.h: added TclCompileListCmd header * generic/tclBasic.c: added TclCompileListCmd compile proc * generic/tclCompCmds.c (TclCompileListCmd): function to compile the 'list' command at parse time. * generic/tclExecute.c (TclExecuteByteCode): definition of INST_LIST bytecode. * doc/StringObj.3: added words of warning to use Tcl_ResetResult with the Tcl_Append* functions. * tests/compile.test: added compile-11.* interp result checks * generic/tclUtil.c (TclGetIntForIndex): added Tcl_ResetResult before Tcl_AppendStringsToObj to prevent shared object crash when called from bcc instruction. The Tcl_Append* calls that append to the result object that are invoked by bcc insts must remember to call Tcl_ResetResult because the bcc doesn't do this for us. [Bug 456892] 2001-08-30 Jeff Hobbs * generic/tclIndexObj.c: fixed some casting problems that upset Crays. [Bug 419528] (andreasen) 2001-08-30 Don Porter * generic/tcl.h: Silence warning from Sun compiler. [Bug 454374] 2001-08-30 Miguel Sofer * generic/tclExecute.c: allow cached fully-qualified command names to be usable from different namespaces within the same interpreter without forcing a new lookup. This speeds up scripts that pass command names in variables ("this" in some OO packages). [Patch 456668] 2001-08-30 Vince Darley Further fs updates. After examining the most common Tcl extensions (TclX, BLT, Tk, TclPro, Mktclapp), it has been determined that only TclpGetCwd and the Access/Stat/Open insert/delete hooks of the internal fs functions are ever used. The remaining functions from Tcl's internal interfaces have therefore been removed, since Tcl now exports a more suitable public API (Tcl_FS...) * generic/tclInt.stubs: * generic/tclInt.h: updated for removed internal functions. Some new internal functions have been put in tclInt.h (and not exported in the stub table because good public equivalents exist). * generic/tclTest.c: some test functions used the internal private APIs. These tests have been retained, but modified to use public APIs. Also objectified the internal filesystem tests. * win/tclWinFile.c: removed TclpStat, TclpAccess and refactored code to use NativeAccess, NativeStat. This should speed up stat, access and glob commands. * win/tclWinFCmd.c: removed all TclpCopy/Rename/Delete File/Directory string-based procedures which aren't used any more. Improved efficiency of some other procedures. Ensure that filename conversions with a NULL interp do not crash Tcl. * mac/tclMacFCmd.c: wrapped long lines and cleaned up TclpObjNormalizePath, removed all TclpCopy/Rename/Delete File/Directory string-based procedures which aren't used any more. * mac/tclMacFile.c: removed obsolete TclpStat, TclpAccess, TclpChdir, etc. * unix/tclUnixFCmd.c: removed use of TclpAccess, removed all TclpCopy/Rename/Delete File/Directory string-based procedures which aren't used any more. * unix/tclUnixFile.c: removed obsolete TclpStat, TclpAccess, TclpChdir, etc. * tcl(Unix|Mac|Win)Chan.c: objectified TclpOpenFileChannel. * various 'load' implementations all objectified. * generic/tclFileName.c: removed redundant code. * generic/tclIOUtil.c: removed TclStat, TclAccess, TclpListVolumes. Fix to MatchInDirectory at the root of a volume. Also improved some documentation, and improved default path joining behaviour for virtual filesystems, especially regarding '~'. * tests/fileName.test: added tests to check for bugs fixed above. * doc/FileName.3: improved documentation 2001-08-30 David Gravereaux * generic/tclAsync.c: * generic/tclEvent.c: * generic/tclInt.h: Improper cleanup of asyncMutex in tclAsync.c repaired. TclFinalizeSynchronization() was trying to remove a registered mutex that was dumped earlier when the TSD it was stored in was cleared. This was only surfacing on *nix. Windows was being masked by mutexes not actually being returned to the system! That was repaired in a previous patch. Needed to add a private TclFinalizeAsync() to tclAsync.c and called from Tcl_FinalizeThread(). Pheww.. Is this done yet? [Bug 414419] requested by Rob Ratcliff 2001-08-28 Jeff Hobbs * generic/tclCompCmds.c (TclPushVarName): noted 'static' defn. [Bug 453872] 2001-08-26 Don Porter * library/auto.tcl (tcl_findLibrary): * tests/unixInit.test (unixInit-2.{1,9}): * unix/tclUnixInit.c (TclpInitLibraryPath): * win/tclWinInit.c (TclpInitLibraryPath): Corrected inconsistency between the search path for script libraries and the directory name $DISTNAME into which distributions built by 'make test' unpack. [Bug 455642] 2001-08-24 Jeff Hobbs * tests/stringComp.test: added string-1.3 * generic/tclCompCmds.c (TclCompileStringCmd): changed to return TCL_OUT_LINE_COMPILE instead of TCL_ERROR when compiling and an unknown string method is called. This is necessary as the string command may be never called, or not until 'string' is redefined. 2001-08-24 Vince Darley * doc/glob.n: documented windows-style path issue with glob. [Bug 219392] * doc/filename.n: documented windows path/file length limitation. [Bug 454597] 2001-08-24 Don Porter * tests/unixInit.test (unixInit-2.9): Corrected expected result to match Tcl's quirky construction of its init library path. 2001-08-23 Andreas Kupries * win/tclWinPipe.c (BuildCommandLine): Fixed [Bug 432499]. Part of the code used the non-absolute path to the executable to determine quoting. This failed if the absolute path contained spaces, but the application name itself not. This bug caused no trouble on Win NT 5, but does for other variants in the Win* family. Report and fix due to Ken Poole . 2001-08-23 Jeff Hobbs * unix/configure: * unix/tcl.m4: added QNX-6 build support. [Bug 219410] (loverso) * unix/tclUnixFCmd.c: * generic/tclIOUtil.c: * generic/tclFileName.c: corrected minor compiler warnings. 2001-08-23 Vince Darley Variety of small filesystem and vfs issues fixed or improved. The new fs code allows many new opportunities for efficiency improvements through the objectified API. The main changes integrated here are such efficiency improvements. Some limitations of the original implementation have also now been lifted. Meanwhile a variety of fs bugs (some old, some new) have also been fixed. * generic/tclFileName.c: Made Tcl_FSSplitPath more efficient, and removed some static string-based procedures which are no longer used. Much more objectification. Tcl_FSJoinPath is now very efficient and more aware of virtual filesystems. Clarified where the Mac-specific code attempts to interpret Unix-style paths. Modified TclDoGlob to use lstat not access to fix [Bug 434876] (L. Virden) * tcl(Win|Unix|Mac)FCmd.c: * tcl(Win|Unix|Mac)File.c: replaced TclpListVolumes with TclpObjListVolumes with different signature, updated code due to more efficient signature of Tcl_FSGetTranslatedPath. Used cached native paths where possible to improve efficiency -- this was completed on MacOS, but on Unix and Win the traversal functions make the task much more complex, so there are still some improvements possible there. Removed unused TclpNormalizePath which had been left in tclWinFCmd.c. Objectified all 'file attributes' functions. Fixed the new [Bug 451571, Bruce Stephens] which is most obvious on Unix, but could occur on MacOS or Windows. This bug actually existed in Tcl 8.3.x but was only made obvious by the recent filesystem overhaul when the code was exercised more heavily. * tests/fileName.test: Three new tests to exercise the above bug, and make sure it is fixed correctly. * unix/tclUnixFile.c: avoid panic in glob when a link doesn't point anywhere. It would probably be good to define exactly what Tcl should do in circumstances like these, and make sure mac/win/unix all behave accordingly. [Bug 417111] (Hemang Lavana). Also fixed misleading/obsolete comment in the code. * generic/tcl.stubs: changed signature of Tcl_FSGetTranslatedPath and added Tcl_FSGetTranslatedStringPath. These changes allow further optimisations in the FS code. * generic/tcl.h: changed signature of Tcl_FSListVolumes so that it doesn't require a Tcl interpreter plus result. Renamed Tcl_FSReadLink to Tcl_FSLink with additional argument so we can support making links in the future. [Patch: 450340] * generic/tclInt.h: added declaration for TclpObjListVolumes. Objectified internal call signatures for 'file attributes' functions, and added an internal objectified get path type function. * generic/tclIOUtil.c: added the moved function TclpListVolumes which calls platform specific code (needed for backwards compatibility), and improved efficiency of parts of the FS (particularly file normalization). Much less copying and memory allocation is required now. added new GetPathType so that changes in 'file volumes' can actually affect files' types, and objectified more code. Made current code work with test suite artificially changing current platform. Added 'static' keywords where required. * generic/tclIO.c: * generic/tclTest.c: Added 'static' keywords, fixing [Bug 453872] (Bob Techentin) * generic/tclCmdAH.c: file command implementation updated for API changes, removed unnecessary special-case SplitPath static function, since it no longer helps prevent code duplication. Moved setting of interpreter result to each individual location that actually required it, to avoid very large code separation between reading and setting the result. * doc/FileSystem.3: updated documentation for the new or changed APIs, and clarified some issues. * doc/SplitPath.3: added pointer to newer APIs in FileSystem.3 * doc/filename.n: clarified current implementation of tilde support on Mac/Win. [Bug 453514] (Sergey Kuzmin) * doc/glob.n: improved documentation for '-directory' and '-path' options. There are now many private, obsolete, platform-specific 'Tclp' string-based filesystem APIs which could be removed. We should check whether any of these are used by extensions and, at least in Tcl 9, remove them. The above changes signify a ***POTENTIAL INCOMPATIBILITY*** with 8.4a3, since signatures of two functions in the new API have changed, but not with older versions of Tcl. 2001-08-23 Donal K. Fellows * generic/tclBinary.c (FormatNumber): Extract a long from the object and not an int, to stop [binary format] from being unable to format some input numbers on architectures where sizeof(int) is less than sizeof(long) (particularly Alpha). [tiprender Bug 441861] * tests/format.test: Converted conditional execution of tests into a test constraint. 2001-08-22 Jeff Hobbs * win/Makefile.in: * win/makefile.vc: updated install target for dde1.2 * doc/dde.n: fixed dde man page (which was totally incorrect). * tests/winDde.test: * win/tclWinDde.c (Tcl_DdeObjCmd): added -binary option to dde request command to allow for returning binary data. [Bug 227482] Updated dde to 1.2 * tests/tcltest.test: added unixExecs constraint to files that used 'grep' in the test. [Bug 453143] * library/tcltest/tcltest.tcl: fixed stdio constraint test. [Patch 454050] (stanton) Simplified unixExecs constraint test. 2001-08-22 Don Porter * tests/ioUtil.test (ioUtil-3.*): Corrected errors in tests revealed by fix of overagressive compiler. [Bug 451200] 2001-08-21 Miguel Sofer * generic/tclCompCmds.c: * tests/compile.test: Fixed overagressive compilation of [catch]: it was catching errors at substitution time. [Bug 219184] 2001-08-21 Jeff Hobbs * tests/tcltest.test (tcltest-12.2): fixed test that would break when env vars weren't Tcl list friendly [Patch 454046] (stanton) 2001-08-20 Jeff Hobbs * library/http/http.tcl (geturl): added port number to Host: header to comply with HTTP/1.1 spec (RFC 2068). [Bug 452217] 2001-08-16 David Gravereaux * tools/tcl.wse.in: * tools/tcl.hpj.in: * win/tcl.hpj.in: Removed -kb storage in CVS to ensure these text files are checked-out in the translation mode CVS is in. Setting these as binary as part of an effort to make sure they are always in CRLF, no matter what the CVS translation, is bypassing how CVS works and is confusing. * tools/genStubs.tcl: Removed LF-only output. Having to reconvert back to CRLF before committing to CVS was giving me a headache. [Bug 451333] * win/makefile.vc: replaced $(WINDIR) with $(include32) for the .rc.res inference rule. winver.h wasn't getting included. [Bug 445630] 2001-08-14 Miguel Sofer * generic/tclBasic.c: make the intial maxNestingDepth of an interpreter be MAX_NESTING_DEPTH instead of a hardwired value. [Bug 232564] 2001-08-13 Miguel Sofer * tests/trace.test: Corrected test numbers. [Bug 449794] 2001-08-12 Mo DeJong * unix/configure: Regen. * unix/configure.in: * unix/tcl.m4: Use GCC variable set by AC_PROG_CC instead of defining our own using_gcc variable. 2001-08-11 Vince Darley Variety of small issues introduced by the vfs code fixed: * generic/tclIOUtil.c: uninitialised read. * generic/tclFCmd.c: possible memory leak in file delete with error condition. 2001-08-10 Miguel Sofer * generic/tclVar.c: * tests/trace.test: Insure that [array] traces work correctly for undefined variables. [Bug 449094] 2001-08-09 Mo DeJong * unix/Makefile.in: Delete the unused getcwd.o target. [Bug 440942] 2001-08-08 Don Porter * library/dde/pkgIndex.tcl: * library/http/http.tcl: * library/http/pkgIndex.tcl: * library/msgcat/msgcat.tcl: * library/msgcat/pkgIndex.tcl: * library/opt/optparse.tcl: * library/opt/pkgIndex.tcl: * library/reg/pkgIndex.tcl: * library/tcltest/tcltest.tcl: * library/tcltest/pkgIndex.tcl: Added checks for package dependencies. Bumped patchlevels of changed packages: http 2.3.2, msgcat 1.2.2, opt 0.4.3, tcltest 2.0.1. [Patch 448931] * README: * generic/tcl.h: * tools/tcl.wse.in: * unix/configure: * unix/configure.in: * unix/tcl.spec: * win/README.binary: * win/configure: * win/configure.in: Bumped up patchlevel to 8.4a4 to distinguish CVS snapshots from the 8.4a3 release. This does not necessarily mean there will be an 8.4a4 release. [Bug 448938] 2001-08-06 Jeff Hobbs 8.4a3 RELEASE * changes: * README: * mac/README: * unix/README: * win/README.binary: updated for 8.4a3 release * generic/tclFileName.c (Tcl_FSSplitPath): update to Tcl style guide. * generic/tclFCmd.c (FileCopyRename): fixed mem leak in introduction of vfs code where a new Tcl_Obj wasn't freed. * generic/tclCmdMZ.c (Tcl_RegexpObjCmd, Tcl_RegsubObjCmd): reordered the retrieval of arguments to avoid shimmering bug when the pattern and string referenced the same object. * unix/configure: regenerated * unixE/tcl.m4: added GNU (HURD) configuration target. [Patch 442974] (brinkmann) * win/README: made note of URL for Windows compilation notes * win/tclWinThrd.c (TclpFinalizeMutex, TclpFinalizeCondition): added DeleteCriticalSection calls for cleanup [Patch 419683] * unix/tclUnixPipe.c (TclpCreateTempFile): fixed use of tmpnam, which is dangerous. [Patch 442636] (lim) The use of tmpnam in TclpTempFileName must still be changed. * tests/http.test (http-4.14): fixed variable error return. [Bug 424252] 2001-08-03 Jeff Hobbs * win/configure: regenerated * win/tcl.m4: fixed DLLSUFFIX definition to always be ${DBGX}.dll. This is necessary for TEA compliant builds that build shared against a static-built Tcl. * win/Makefile.in ($(TCLSH)): added $(TCL_STUB_LIB_FILE) to build target, otherwise it wouldn't get generated in a static build. 2001-08-06 Andreas Kupries * generic/tclIOCmd.c (Tcl_GetsObjCmd): Applied patch from [Bug 442665] to fix the bug reported by it. The function can corrupt a freed object if it is called with objc == 3. This is because it retrieves resultPtr and does not increment its reference count, but then calls Tcl_ObjSetVar2, which causes the retrieved resultPtr object to be released. 2001-08-06 Don Porter * doc/tclsh.1: Added note that the tclsh program is frequently installed with the Tcl version numer as part of the name. [Patch 402725] * generic/tclPkg.c: * tests/pkg.test: [package forget] now forgets all of the package arguments it receives, not stopping when a package is not found. [Bug 415273] 2001-08-02 Jeff Hobbs * generic/tclIOUtil.c (Tcl_FSMatchInDirectory): corrected uninitialized value. 2001-08-02 Mo DeJong * generic/tclPlatDecls.h: * win/tclWinPort.h: Revert related changes made to improve Cygwin support on 2001-07-18. This change ended up breaking the VC++ build because of conflicts between Windows APIs and internal Tk APIs. 2001-08-01 Jeff Hobbs * unix/tclUnixFCmd.c: minor casts to eliminate warnings. (lim) [Patch 440218] * tests/parseOld.test: changed some tests that required testwordend to exist to skip in a proper tcltest manner. [Bug 442663] * library/http/http.tcl (http::mapReply): the regsub'ing of \n and \t to escape them was unnecessary. 2001-07-31 Vince Darley Changes from TIP#17 "Redo Tcl's filesystem" The following files were impacted: * doc/Access.3: * doc/FileSystem.3: * doc/OpenFileChnl.3: * doc/file.n: * doc/glob.n: * generic/tcl.decls: * generic/tcl.h: * generic/tclCmdAH.c: * generic/tclCmdIL.c: * generic/tclCmdMZ.c: * generic/tclDate.c: * generic/tclDecls.h: * generic/tclEncoding.c: * generic/tclFCmd.c: * generic/tclFileName.c: * generic/tclGetDate.y: * generic/tclIO.c: * generic/tclIOCmd.c: * generic/tclIOUtil.c: * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclLoad.c: * generic/tclStubInit.c: * generic/tclTest.c: * generic/tclUtil.c: * library/init.tcl: * mac/tclMacFCmd.c: * mac/tclMacFile.c: * mac/tclMacInit.c: * mac/tclMacPort.h: * mac/tclMacResource.c: * mac/tclMacTime.c: * tests/cmdAH.test: * tests/event.test: * tests/fCmd.test: * tests/fileName.test: * tests/io.test: * tests/ioCmd.test: * tests/proc-old.test: * tests/registry.test: * tests/unixFCmd.test: * tests/winDde.test: * tests/winFCmd.test: * unix/mkLinks: * unix/tclUnixFCmd.c: * unix/tclUnixFile.c: * unix/tclUnixInit.c: * unix/tclUnixPipe.c: * win/tclWinFCmd.c: * win/tclWinFile.c: * win/tclWinInit.c: * win/tclWinPipe.c: 2001-07-24 Mo DeJong * win/tclWinThrd.c (Tcl_CreateThread): Close Windows HANDLE returned by _beginthreadex. The MS documentation states that this handle is not closed by a later call to _endthreadex. 2001-07-21 Don Porter * doc/pkgMkindex.n: * library/package.tcl: Corrected documentation and usage message of [pkg_mkIndex]. 2001-07-18 Mo DeJong * generic/tclPlatDecls.h: Define TCHAR by including windows.h instead of tchar.h since Cygwin does not support the tchar.h header. Include CHECK_UNICODE_CALLS logic from tclWinPort.h. * win/tclWinPort.h: Remove CHECK_UNICODE_CALLS logic. Remove include of windows.h since this now done it tclPlatDecls.h. * win/tclWinReg.c: Remove duplicate include of windows.h. 2001-07-18 Andreas Kupries * generic/tclIO.c: Aftermath to [Bug 427196]. Squash empty buffers if they are smaller than the requested buffersize, to prevent reusage of old buffers and to honor changes in the requested buffersize made by the user. 2001-07-17 Mo DeJong * win/tclWinFile.c (TclpReadlink): Add Cygwin specific definition for the TclpReadlink function. This method implements reading of symbolic links when build with Cygwin. 2001-07-17 Mo DeJong * win/tclWinPort.h: Add Cygwin specific defines for environ and timezone variables. 2001-07-17 Andreas Kupries * generic/tclIO.c (GetInput): Fixed [Bug 427196]. Memory was overwritten because a buffer was used after a change of the requested buffersize together with that requested buffersize and not its actual size, which was smaller. Note that the continous reuse of the smaller buffer negatively impacts performance. The system never allocates a buffer with the newly requested bigger buffersize. 2001-07-16 Mo DeJong * generic/tcl.h: Define __WIN32__ when __CYGWIN__ or __MINGW32__ is defined. * generic/tclAlloc.c: Define caddr_t when compiling with VC++ or mingw. This type is already defined when compiling with Cygwin. 2001-07-16 Mo DeJong * win/tclWinConsole.c: * win/tclWinPipe.c: * win/tclWinPort.h: * win/tclWinSerial.c: * win/tclWinThrd.c: Remove unnecessary #includes of dos.h, direct.h, and tchar.h. This will help the Cygwin porting effort since these headers do not exist under Cygwin. 2001-07-16 Jeff Hobbs * win/tclWinPipe.c (PipeClose2Proc): constrained the mutex lock to just the TerminateThread call and waiting for termination. (jsmith) * generic/tclCmdMZ.c: Removed extra copy of the SCAN_* macros #defined in generic/tclScan.c. [Bug 441230] (porter) 2001-07-12 Donal K. Fellows * tests/unixInit.test (unixInit-2.8): Added extra constraint, notInstalledInTmp, to stop this test from damaging installations in /tmp; not much fun to have to reinstall the Tcl library every time you run the test suite! * tests/subst.test (subst-10.*): Updated tests to check new behaviour for 'break' in command substitutions. (subst-1.2,subst-7.1): Error messages changed. * doc/SubstObj.3: New file, to document Tcl_SubstObj. * doc/subst.n: Improved and updated documentation for 'subst' to help support the changed behaviour. * generic/tcl.decls (generic-437): Declaration for Tcl_SubstObj * generic/tcl.h (TCL_SUBST_*): Added flags for Tcl_SubstObj. * generic/tclCmdMZ.c (Tcl_SubstObj,Tcl_SubstObjCmd): Divided into two parts to allow people to access the innards of 'subst' and changed the behaviour when command substitutions do a 'break' to be different from 'continue'. Also now works with objects, which allows for some nifty optimisations with variable substitutions and a slight improvement with command substitutions. [TIP#36] 2001-07-10 Mo DeJong * unix/Makefile.in: Add AR variable for use in STLIB_LD. * unix/configure: Regen. * unix/configure.in: Use STLIB_LD when defining MAKE_LIB and MAKE_STUB_LIB. Subst RANLIB and AR. * unix/tcl.m4 (SC_CONFIG_CFLAGS): Add doc comment about STLIB_LD command. Check ${AR} env var when setting STLIB_LD and delay evaluation until make time. * win/configure: Regen. * win/tcl.m4 (SC_CONFIG_CFLAGS): Delay evaluation of ${AR} in STLIB_LD and add flags to better match the Unix implementation. Don't bother defining AR when using VC++ since it is not used. 2001-07-06 Mo DeJong * win/configure: Regen. * win/tcl.m4 (SC_CONFIG_CFLAGS): Pass -e _WinMain@16 in addition to the -mwindows flag to work around a problem with ld when it incorrectly use main() as the executable entry point when both WinMain() and main() are available. 2001-07-06 Donal K. Fellows * tests/cmdAH.test: Added leading zero to file modes to work around fault in HPUX strtol() which ignores the base parameter. [Bug 438808] 2001-07-05 Mo DeJong * win/Makefile.in: Subst DEPARG directly instead of relying on a variable. This will make Cygwin builds faster since an extra exec will be avoided. * win/configure: Regen. * win/configure.in: Subst DEPARG. * win/tcl.m4 (SC_CONFIG_CFLAGS): Move AC_MSG_CHECKING after the AC_CHECK_PROG so that status messages do not get mixed together. Set DEPARG based on the results of the cygpath check so that we avoid using an extra exec when it is not needed. Use ac_cv_cygwin status flag instead of looking at the output of gcc -v, which works in the case where -mno-cygwin is set in the CFLAGS. 2001-07-04 Jeff Hobbs * README: * mac/README: * unix/README: * win/README: * win/README.binary: updated READMEs with purls 2001-07-03 Mo DeJong * win/Makefile.in: Remove PATHTYPE variable. * win/configure: Regen. * win/configure.in: Don't subst PATHTYPE. * win/tcl.m4 (SC_CONFIG_CFLAGS): Remove PATHTYPE variable. Set CYGPATH to "cygpath -w" if the cygpath executable is found on the path. This approach works for native Cygwin builds and cross compiles. 2001-07-03 Jeff Hobbs * tests/var.test: * generic/tclVar.c (Tcl_VariableObjCmd): added patch to check for number of args. [Patch 426038] * generic/tclVar.c (Tcl_GetVar2Ex): added ability to recognize TCL_TRACE_READS flags to cause creation of part1 in TclLookupVar to make sure newly created array will get read traces triggered appropriately. This is called by Tcl_ObjGetVar2, Tcl_GetVar, and Tcl_GetVar2. (TclSetIndexedScalar, TclSetElementOfIndexedArray): added read trace triggering for lappend case. (Tcl_LappendObjCmd): pass TCL_TRACE_READS to Tcl_ObjGetVar2 to trigger possible read traces for new arrays. * generic/tclExecute.c (TclExecuteByteCode): added TCL_TRACE_READS flag to INST_LAPPEND(_ARRAY)_STK case to trigger read traces for newly created arrays. Removed unnecessary #ifdef for TCL_COMPILE_DEBUG in INST_LOAD_SCALAR1 case. * tests/append.test: * tests/appendComp.test: added tests for read trace triggering for append and lappend. 2001-07-03 Mo DeJong * tests/clock.test (clock-2.5): Adjust test so that it passes when the time slice is 60 msecs, now passes under Windows 98. 2001-07-03 Mo DeJong * win/tcl.m4 (SC_CONFIG_CFLAGS): Don't pass the v flag to ${AR} when using gcc, verbose output is not needed. 2001-07-03 Don Porter * tests/unixInit.test (unixInit-2.8): Changed test back to using installation layout, adding comments explaining why the test writes to the directories it does, and checks to avoid destroying other files in /tmp. 2001-07-03 Donal K. Fellows * tests/unixInit.test (unixInit-1.2): Fixed faults reported in [Bug 438070] - well, at least enough to work on Solaris - and added comments that should make what is going on in the test clearer. 2001-07-02 Jeff Hobbs * tests/util.test: added util-4.6 * generic/tclUtil.c (Tcl_ConcatObj): Corrected walking backwards over utf-8 chars. [Bug 227512] 2001-07-02 Don Porter * tests/unixInit.test (unixInit-2.8): Corrected test for all absolute pathnames in library path when executable is installed near root directory to use correct development directory layout. [Bug 438014] * tests/unixInit.test (unixInit-2.9): * unix/tclUnixInit.c (TclpInitLibraryPath): * win/tclWinInit.c (TclpInitLibraryPath): Corrected buggy construction of search path entries relative to executable. Added test for bad construction. [Bug 438014] 2001-06-28 Miguel Sofer * generic/tclNamesp.c: Correction to faulty patch from [Bug 231259] 2001-06-28 Donal K. Fellows * tests/unixInit.test (unixInit-1.2): Modified so as not to require a local echo service, which fails on many systems which have that turned off for security reasons... 2001-06-27 Jeff Hobbs * generic/tclInt.h: * generic/tclObj.c: * unix/Makefile.in: added a -DPURIFY mode that makes Tcl_Obj's allocated and free singularly (instead of in alloc in blocks and never free) to allow checkers like Purify to operate better. * library/encoding/koi8-u.enc: added koi8-u (Ukranian variant) encoding. * tests/subst.test: * generic/tclUtf.c (Tcl_UtfBackslash): Corrected backslash handling of multibyte utf-8 chars. [Bug 217987] * generic/tclCmdIL.c (InfoProcsCmd): fixed potential mem leak in info procs that created objects without using them. * generic/tclCompCmds.c (TclCompileStringCmd): fixed mem leak when string command failed to parse the subcommand. * doc/interp.n: * doc/unknown.n: updated notes about what is in a safe interp. [Bug 218605] 2001-06-27 Donal K. Fellows * tests/event.test (event-11.5): Removed hard-coded port number which could fail on some systems. [Bug 436727] 2001-06-26 Mo DeJong * unix/Makefile.in: * win/Makefile.in: Add `make shell` target. This target will set the proper env vars before invoking tclsh from the build directory. 2001-06-26 Mo DeJong * win/Makefile.in: Use : to separate VPATH entries. This works for both Cygwin builds and cross builds, the VPSEP variable is simply unneeded complexity. * win/configure: Regen. * win/configure.in: Don't subst VPSEP. * win/tcl.m4 (SC_CONFIG_CFLAGS): Remove VPSEP variable. 2001-06-26 Mo DeJong * unix/configure: Regen. * unix/configure.in: Fix last checkin by removing export since that only works in bash. * win/configure: Regen. * win/configure.in: Ditto. 2001-06-26 Mo DeJong * unix/configure: Regen. * unix/configure.in: Set CFLAGS to "" if the user did not set CFLAGS in the env. This keeps AC_PROG_CC from adding "-g -O2" to the CFLAGS by default. * win/configure: Regen. * win/configure.in: Ditto. 2001-06-25 Mo DeJong * win/configure: Regen. * win/configure.in: Use RC_DEFINE flag from tcl.m4. * win/tcl.m4 (SC_CONFIG_CFLAGS): Set RC_DEFINE flag based on the compiler in use. 2001-06-25 Mo DeJong * win/tcl.m4 (SC_CONFIG_CFLAGS): Link to the imm32 library when building with mingw gcc. 2001-06-25 Mo DeJong * win/configure: Regen. * win/tcl.m4 (SC_CONFIG_CFLAGS): When building with gcc, don't attempt to link with LD or support dllwrap. Simply require a recent version of Cygwin gcc or Mingw gcc that supports -shared. When linking, use gcc instead of ld since gcc automatically includes libs like -lmsvcrt. 2001-06-22 Mo DeJong * win/configure: Regen. * win/configure.in: Add resource compiler fix from 8.3.3 to fix compiling with mingw. 2001-06-22 Mo DeJong * win/configure: Regen. * win/tcl.m4: Fix silly typo in last checkin. 2001-06-22 Mo DeJong * unix/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@. Set LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@. Add LDFLAGS_DEBUG and LDFLAGS_OPTIMIZE to match the way CFLAGS_DEFAULT works. This will support user set CFLAGS or LDFLAGS at configure time. * unix/configure: Regen. * unix/configure.in: Don't set CFLAGS to CFLAGS_DEFAULT, instead subst CFLAGS_DEFAULT into the Makefile. Add AC_SUBST for CFLAGS_DEFAULT, LDFLAGS_DEFAULT, LDFLAGS_DEBUG, and LDFLAGS_OPTIMIZE. * unix/tcl.m4 (SC_ENABLE_SYMBOLS): Modify LDFLAGS_DEFAULT so that it uses a Makefile variable just like CFLAGS_DEFAULT. * win/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@. Set LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@. This will support user set CFLAGS or LDFLAGS at configure time. * win/configure: Regen. * win/configure.in: Don't set CFLAGS or LDFLAGS, instead subst CFLAGS_DEFAULT and LDFLAGS_DEFAULT into the Makefile. * win/tcl.m4 (SC_ENABLE_SYMBOLS): Modify LDFLAGS_DEFAULT so that it uses a Makefile variable just like CFLAGS_DEFAULT. 2001-06-22 Mo DeJong * win/configure: * win/tcl.m4 (SC_CONFIG_CFLAGS): Don't set LDFLAGS_DEBUG to -g or LDFLAGS_OPTIMIZE to -O when compiling with gcc. These flags are not needed and can cause problems with the Cygwin version of ld. 2001-06-18 Donal K. Fellows * tests/unixInit.test (unixInit-1.2,unixInit-2.8): Added test for code described below, and fixed a couple of errors that caused problems during testing; the code to determine the installedTcl constraint was wrong, and test unixInit-2.8 assumed that /tmp/lib was free for use and could be deleted, which clashed nastily with my installation and made other tests fail unnecessarily! * unix/tclUnixChan.c (TtyInit,TclpOpenFileChannel, (Tcl_MakeFileChannel,TclpGetDefaultStdChannel): Alterations so that the standard channels - stdin, stdout and stderr - have the correct type and fconfigure options. This required making the initialisation of serial lines a little more sophisticated to make the console behave correctly in interactive mode... [Bug 219137 and duplicates] 2001-06-16 Don Porter * generic/tclInt.decls: * generic/tclInt.h: * generic/tclPanic.c (Tcl_PanicVA): * mac/tclMacAppInit.c (main): * mac/tclMacPanic.c (TclpPanic): * unix/tclUnixPort.h: * win/tclWinPort.h: Replaced TclMacSetPanic with TclpPanic for setting a platform-specific panic handler. TclpPanic is NULL on Unix and Windows. Fixes broken wish on Mac due to earlier patches. [Patch 415648] * generic/tclIntPlatDecls.h: * generic/tclStubInit.c: `make gentubs` after above changes. 2001-06-13 Don Porter * mac/tclMacAppInit.c (main, Macintosh_Init): * mac/tclMacBOAAppInit.c (main): * mac/tclMacPanic.c: Applied patches from Dan Steffen correcting problems on the Macintosh in the 2001-06-08 changes. 2001-06-12 Donal K. Fellows * tests/regexp.test (regexp-18.12): * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): Fixed so that submatches that do not match always have index pair {-1 -1} [Bug 219232] 2001-06-08 Don Porter * generic/tcl.h: * generic/tcl.decls: * generic/tclPanic.c: Added CONST to Tcl_*Panic* public interfaces. [Patch 415648, TIP 27] * generic/tclInt.decls: * mac/tclMacAppInit.c (main): * mac/tclMacBOAAppInit.c (main): * mac/tclMacPanic.c: Modified special Mac implementations of Tcl_*Panic* to be exact copies of the generic implementations. Added TclMacSetPanic. The generic implementations should be used directly, rather than copies, but that requires further changes by someone familiar with the Mac build systems. [Patch 415648] * generic/tclDecls.h: * generic/tclIntPlatDecls.h: * generic/tclStubInit.c: `make gentubs` after above changes. * doc/Panic.3: * unix/mkLinks: New file documenting Tcl_*Panic* public interfaces, followed by `make mklinks`. [Patch 415648, Bug 219170, Bug 414936] 2001-06-03 Jeff Hobbs * generic/tclUtil.c (Tcl_DStringAppendElement): patch to save an extra strlen call. [Bug 428572] 2001-05-30 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Added two casts to INST_STR_CMP implementation to get rid of a couple warnings from the SUNWspro C compiler. * generic/tclBasic.c (Tcl_GetMathFuncInfo,Tcl_ListMathFuncs): * generic/tclCmdIL.c (Tcl_InfoObjCmd,InfoFunctionsCmd): * generic/tcl.decls (generic table, positions 435+436): * tests/info.test: * doc/CrtMathFnc.3: * doc/info.n: Changes due to TIP #15 "Functions to List and Detail Math Functions" 2001-05-28 Jeff Hobbs * library/init.tcl (unknown): removed errant " in error message 2001-05-27 Jeff Hobbs * generic/regc_locale.c: updated character class range data for Unicode v3.1.0 compliance. * generic/tclUniData.c: regenerated from Unicode v3.1.0 data file (new as of 2001-05-16). This brings Tcl to current unicode compliance. * tests/utf.test: added tests to check unicode 3 compliance * unix/Makefile.in (tclUtf.o): added tclUniData.c dependency. * tools/uniClass.tcl: added comments to output format and the script for clarification. * tools/uniParse.tcl: corrected filename output and GetDelta macro to use 'info' as param (was 'infO') 2001-05-26 Donal K. Fellows * generic/tclVar.c (tclArraySearchType,SetArraySearchObj, (ParseSearchId): Added code to speed up array searching by reducing the amount of parsing needed for searchIds. * generic/tclObj.c (TclInitObjSubsystem): * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): * generic/tclNamesp.c (TclInitNamespaceSubsystem): * generic/tclInt.h: Moved some Tcl_ObjType initialisation to TclInitObjSubsystem to be with the bulk of the rest. [Patch 424851] Committed by Miguel Sofer 2001-05-23 Jeff Hobbs * tests/io.test: changed io-52.[9-11] to not be platform sensitive with EOL translation. * library/encoding/cp1250.enc: * library/encoding/cp1251.enc: * library/encoding/cp1252.enc: * library/encoding/cp1253.enc: * library/encoding/cp1254.enc: * library/encoding/cp1255.enc: * library/encoding/cp1256.enc: * library/encoding/cp1257.enc: * library/encoding/cp1258.enc: * library/encoding/cp874.enc: * library/encoding/iso8859-6.enc: * library/encoding/iso8859-7.enc: * library/encoding/iso8859-8.enc: * library/encoding/iso8859-10.enc (new): * library/encoding/iso8859-13.enc (new): * library/encoding/iso8859-14.enc (new): updated encoding tables based on http://www.unicode.org/Public/MAPPINGS/. (kuhn) 2001-05-23 Mo DeJong * unix/tcl.m4 (SC_PATH_TCLCONFIG): Fix comments, and typo in cached variable name. 2001-05-23 Mo DeJong * unix/tcl.m4 (SC_LOAD_TKCONFIG): Remove use of undefined TCLCONFIG variable and call AC_MSG_RESULT to print the checking result. * win/tcl.m4: Ditto. 2001-05-22 Jeff Hobbs * generic/tclObj.c (TclAllocateFreeObjects): simplified objSizePlusPadding to use sizeof(Tcl_Obj) (max) Corrected use of tclObjsAlloced/Freed/Shared in TCL_MEM_DEBUG compile. 2001-05-22 Miguel Sofer * generic/tclExecute.c: removed Tcl_DuplicateObj in INST_DUP 2001-05-21 Jeff Hobbs * tests/tcltest.test (tcltest-19.1): fixed failing test that was getting affected by Windows env handling of empty valued elements. * unix/tcl.m4: added more common install directories in which to search for *Config.sh. [Bug 419812] * tests/cmdMZ.test (cmdMZ-1.4): added notLinux constraint to test to prevent failure message on Linux due to OS caching bug. * tests/httpd (httpdRespond): added response to timeout value in query string. * tests/http.test: removed unused notLinux constraint setting * generic/tclRegexp.c (Tcl_RegExpExecObj): added use of Tcl_GetUnicodeFromObj. 2001-05-19 Andreas Kupries * Note that "tclbench" (see project "tcllib") was extended with performance benchmarks for [fcopy] too. * doc/fcopy.n: Updated to reflect the extended behaviour of 'fcopy'. * tests/io.test: Added tests 'io-52.9', 'io-52.10' and 'io-52.11' to test the handling of encodings by 'fcopy' / 'TclCopychannel'. [Bug 209210] * generic/tclIO.c: Split of both 'Tcl_ReadChars' and 'Tcl_WriteChars' into a public error checking and an internal working part. The public functions now use the new internal ones. The new functions are 'DoReadChars' and 'DoWriteChars'. Extended 'CopyData' to use the new functions 'DoXChars' when required by the encodings on the input and output channels. [Bug 209210] 2001-05-16 Jeff Hobbs * library/history.tcl (tcl::HistAdd): prevent empty calls from being added to the history (arndt) * tests/error.test: updated error-1.3 message to account for string index being compiled at toplevel. * tests/appendComp.test: * tests/stringComp.test: new files for extended bytecode testing * generic/tclBasic.c: added new CompileProc invocations to basic command initialization. * generic/tclCompCmds.c: added new compile commands for append, lappend, lindex and llength. Refactored set and incr compile commands to use new TclPushVarName function for handling the varname component during compilation (also used by append and lappend). Changed string compile command to compile toplevel code as well (when possible). * generic/tclCompile.c: added new instruction enums * generic/tclCompile.h: added debug info for new instructions * generic/tclExecute.c (TclExecuteByteCode): moved elemPtr to toplevel var (oft-used). Added definitions for new bytecode instructions INST_LIST_INDEX, INST_LIST_LENGTH, INST_APPEND_SCALAR1, INST_APPEND_SCALAR4, INST_APPEND_ARRAY1, INST_APPEND_ARRAY4, INST_APPEND_ARRAY_STK, INST_APPEND_STK, INST_LAPPEND_SCALAR1, INST_LAPPEND_SCALAR4, INST_LAPPEND_ARRAY1, INST_LAPPEND_ARRAY4, INST_LAPPEND_ARRAY_STK, INST_LAPPEND_STK. Refactored repititious code for reuse with INST_LOAD_STK (same as INST_LOAD_SCALAR_STK), INST_STORE_STK (same as INST_STORE_SCALAR_STK). Updated INST_STR_CMP with style of fix of 2001-04-06 Fellows [Bug 219201] as that fix only affected the runtime eval'ed "string" (string compare is normally byte-compiled now). We may want to back these out for speed in the future, noting the problems with \x00 comparisons in the docs. * generic/tclInt.h: declarations for new compile commands. * generic/tclVar.c: change TclGetIndexedScalar, TclGetElementOfIndexedArray, TclSetElementOfIndexedArray and TclSetIndexedScalar to use flags. The Set functions now support TCL_APPEND_ELEMENT and TCL_LIST_ELEMENT as well. * generic/tclInt.decls: * generic/tclIntDecls.h: minor signature changes for above. * generic/tclCmdMZ.c: made use of new Tcl_GetUnicodeFromObj. 2001-05-16 Donal K. Fellows * doc/console.n: Deleted. Put it in the wrong source tree! D'oh! 2001-05-15 Jeff Hobbs * generic/tcl.decls: * generic/tclDecls.h: * generic/tclStubInit.c: * generic/tclStringObj.c (Tcl_GetUnicodeFromObj): new function to parallel Tcl_GetStringFromObj (fix of an API oversight). * unix/tclUnixPipe.c: updated pipeChannelType to TCL_CHANNEL_VERSION_2 type specification. * tests/fileName.test: corrected tests not to fail on win when a C:/test dir exists. * generic/tclFileName.c (ExtractWinRoot): corrected ABR error 2001-05-15 Miguel Sofer * tests/lindex.test: added test for nested braces [Patch 423617] 2001-05-15 Miguel Sofer * generic/tclInt.h: * generic/tclNamesp.c: invalidate all bytecodes in a namespace if a new command shadows a bytecoded command. * tests/namespace.test: Patched from [Bug 231259] 2001-05-15 Donal K. Fellows * doc/console.n: Created. It seems very odd to me that the console implementation is part of the Tcl distribution and not part of Tk, but given the location of the source, the documentation must obviously match up... 2001-05-14 Donal K. Fellows * generic/tclCmdMZ.c (Tcl_StringObjCmd): * tests/string.test (string-4.14): Negative string indices should not be added as offsets to the result of [string first] but instead be treated as referring to the start of the string. [Bug 423581] 2001-05-11 Mo DeJong * unix/Makefile.in: Add a LDFLAGS variable to the Makefile instead of directly substing @LDFLAGS@. * unix/configure: Regen. * unix/tcl.m4: Fix CFLAGS_DEFAULT so that the name of a Makefile variable is passed as @CFLAGS@. * win/Makefile.in: Move the setting of CFLAGS higher up in the Makefile. * win/configure: Regen. * win/configure.in: Use dnl to comment out macros so that they are not accidently expanded. * win/tcl.m4: Fix CFLAGS_DEFAULT so that the name of a Makefile variable is passed as @CFLAGS@. 2001-05-07 Miguel Sofer * generic/tclExecute.c: insure different rand() seeds in different threads. [Bug 416643] 2001-05-03 Jeff Hobbs * tests/tcltest.test: removed extraneous 'c' (doh!) [Bug: 414031] * tools/tcltk-man2html.tcl: removed use of 'exec' for portability and fixed up code. 2001-05-03 Don Porter * doc/library.n: * library/init.tcl: * tests/autoMkindex.t*: Modified [auto_import] to apply pattern matching in the [namespace import] style. [Bug 420186] ***POTENTIAL INCOMPATIBILITY*** for any callers of [auto_import] from outside Tcl that expect the pattern matching to be like that of [string match]. 2001-05-03 Miguel Sofer * generic/tclParse.c: * tests/namespace.test: Insure consistent behaviour of the [unknown] command: when a command is unknown, it is always processed by [::unknown], ignoring any namespace proc which happens to be called "unknown" [Patch 421166, Bug 420507] 2001-05-02 Don Porter * tools/genStubs.tcl: Add a package require of Tcl 8 at the beginning of the script so that the script will print a descriptive error message when run in an old Tcl 7 shell. 2001-04-27 Kevin Kenny * generic/tclInt.decls: * generic/tclInt.h: * generic/tclCmdIL.c: * generic/tclProc.c: * generic/tclVar.c: Added another collection of missing CONSTs related to TclGetNamespaceForQualName. * generic/tclIntDecls.h: Regenerated. 2001-04-25 Mo DeJong * unix/configure: Regen. * unix/tcl.m4: Subst TCL_THREADS into tclConfig.sh. * unix/tclConfig.sh.in: Add TCL_THREADS variable. * win/configure: Regen. * win/tcl.m4: Subst TCL_THREADS into tclConfig.sh. * win/tclConfig.sh.in: Add TCL_THREADS variable. 2001-04-25 Mo DeJong * unix/configure: Regen. * unix/configure.in: Use $@ in MAKE_LIB and MAKE_STUB_LIB commands instead of using a delayed subst variable. Replace instances of STUB_LIB_FILE with TCL_STUB_LIB_FILE. 2001-04-25 Mo DeJong * unix/Makefile.in: Use TCL_STUB_LIB_FILE instead of STUB_LIB_FILE. * unix/configure: Regen. * unix/configure.in: Don't subst STUB_LIB_FILE, use TCL_STUB_LIB_FILE instead. 2001-04-25 Donal K. Fellows * tools/encoding/iso8859-15.txt: * library/encoding/iso8859-15.enc: Oops! Got the full encoding wrong. Should be fixed now... * tools/encoding/iso8859-15.txt: * library/encoding/iso8859-15.enc: * tools/tcl.wse.in: Added ISO 8859-15 (a.k.a. Latin-1 + Euro currency symbol) support. * generic/tclNamesp.c: * generic/tclBasic.c (TclRenameCommand): Missing CONST from several declarations relating to use of TclGetNamespaceForQualName 2001-04-24 Kevin B. Kenny * doc/AssocData.3: * doc/CrtCommand.3: * doc/CrtMathFnc.3: * doc/CrtObjCmd.3: * doc/ExprLong.3: * generic/tclBasic.c: * generic/tclCmdMZ.c: * doc/CrtSlave.3: * generic/tclNamesp.c: * generic/tcl.decls: * generic/tcl.h: * generic/tclInt.decls: * generic/tclInt.h: (TIP #27) Another round of CONST changes, this time adding CONST to the API's exported from tclBasic.c. [Patch 415179] ***POTENTIAL INCOMPATIBILITY*** from 8.4a2, in which Vince Darley's changes to command tracing were added. A const has been added to the type signature of one of the parameters to Tcl_CommandTraceProc. 2001-04-10 Kevin B. Kenny * unix/tclUnixTime.c: Altered code to use memcpy instead of structure assigments in an effort to achieve better K&R compatibility. 2001-04-10 Kevin B. Kenny * unix/tclUnixTime.c: Fixed silly typo in calls to 'gmtime' and 'localtime' that broke the Linux build. 2001-04-09 Kevin B. Kenny * unix/tclLoadShl.c: Added DYNAMIC_PATH to the load flags so that the SHLIB_PATH will be searched for other libraries. [Bug 219140] 2001-04-09 Kevin B. Kenny * unix/tcl.m4: Added _REENTRANT to Solaris build so that thread safe library routines are included. * unix/configure: Re-ran 'autoconf' with changed tcl.m4 * tclUnixTime.c: Modified for thread safety of 'gmtime' and 'localtime' system calls. [Bugs 219136 and 232558] 2001-04-09 Donal K. Fellows * tests/expr.test (expr-21.*): Tests to check below fix. * generic/tclParseExpr.c (GetLexeme): Now recognises the non-numeric boolean literals for what they are. It no longer makes sense for anyone to create functions with the same name as one of them, but this was true in 7.* as well [Bug 217777; finally!] 2001-04-07 Miguel Sofer * generic/tclExecute.c: Avoid panic when there are extra items in the tcl stack. [Bug 406709, Patch 414470] * tests/foreach.test: test to exercise the patch 2001-04-07 Miguel Sofer * doc/namespace.n: document correct functionality * generic/tclNamesp.c: corrected behaviour of [namespace code] [Bug 219385, Patch 403530] * library/init.tcl: * tests/namespace-old.test: test correct functionality * tests/namespace.test: test correct functionality 2001-04-07 Andreas Kupries * unix/Makefile.in (checkdoc): New target, checking the definitions as found in the compiled library against the manpages to find undocumented public functionality. * unix/mkLinks: Updated to include the new manpage. * doc/UniCharIsAlpha.3: New manpage documenting the Unicode character classification APIs. [Bug 218720] 2001-04-07 Andreas Kupries * unix/mkLinks: Updated to incorporate the changes below. * doc/StringObj.3: Added 'Tcl_AttemptSetObjLength' to the NAME section. [Bug 414435] * doc/Alloc.3: Added both 'Tcl_AttemptAlloc' and 'Tcl_AttemptRealloc' to the NAME section. [Bug 414435] * doc/Utf.3: Added both 'Tcl_UniCharCaseMatch' and 'Tcl_UniCharNcasecmp' to the NAME section. [Bug 414435] 2001-04-06 Don Porter * library/init.tcl: * tests/init.test: Modified processing of $::errorInfo by [unknown] when the auto-loaded command throws an error to better cover the tracks of auto-loading. [Bug 219280, Patch 403551] 2001-04-06 Donal K. Fellows * doc/read.n: Added section on "USE WITH SERIAL PORTS" to resolve [Bug 219402] * tests/string.test (string-2.30): Test for this case * generic/tclCmdMZ.c (Tcl_StringObjCmd, STR_COMPARE branch): Fixed problem caused by Utf-rep of \x00 being more than Utf-rep of \x01 fooling memcmp by forcing everything through Utf-based comparisons. Added optimizations for case where objects have a string/unicode-rep or a bytearray-rep (i.e. where we can perform comparisons on fixed-size units). [Bug 219201] * generic/tclUtf.c (Tcl_UtfNcmp): Corrected seriously erroneous comment. 2001-04-05 Andreas Kupries * doc/Macintosh.3: Removed duplicates from .SH line. [Bug 413983] 2001-04-05 Donal K. Fellows * generic/tclCmdMZ.c (Tcl_StringObjCmd): Fixed so will compile with K&R compilers. [Patch 413844, Bug 413847] 2001-04-04 Don Porter * generic/tclMain.c: Patch from Kevin Kenny to restore support of pre-ANSI compilers. [Bug 413846, Patch 413842] 2001-04-04 Andreas Kupries * unix/mkLinks: Updated to contain the new manpage. * doc/Environment.3: New manpage, describes Tcl_PutEnv. [Bug 219171] * doc/Macintosh.3: New manpage describing the macintosh specific parts of the public API. [Bug 219169] 2001-04-04 Jeff Hobbs * unix/configure: * unix/tcl.m4: extended test of termios vs. termio vs. sgtty to better detect result on Linux and when certain configure redirections are being used. [Patch 402923; Bug 227412, 219194] (max) 2001-04-04 Andreas Kupries * generic/tclTest.c: * tests/io.tests: TIP #10 followup correcting a problem with the original patch because of the lack of 'testthread id' for a non-threaded compilation. 2001-04-04 Kevin Kenny * doc/ByteArrObj.3: * doc/DumpActiveMemory.3: * doc/InitStubs.3: * doc/PkgRequire.3: * doc/StringObj.3: * generic/tcl.decls: * generic/tcl.h: * generic/tclBinary.c: * generic/tclCkalloc.c: * generic/tclDecls.h: * generic/tclListObj.c: * generic/tclObj.c: * generic/tclPkg.c: * generic/tclStringObj.c: * generic/tclStubLib.c: (TIP#27) Changed a number of Tcl API's to accept "CONST char*" in place of simple "char*". (kennykb) [Patch 404026] 2001-04-04 Jeff Hobbs * generic/tclListObj.c (Tcl_SetListObj): set objPtr->length = 0 in empty object case to maintain sanctity of Tcl_Obj bytes/length pairing. [Patch 405998] (porter) 2001-04-03 Andreas Kupries * unix/mkLinks: Added 'Signal.3', 'Tcl_WaitPid'. * doc/DetachPids.3: Added description of 'Tcl_WaitPid' [Bug 219173]. * doc/Signal.3: New man page describing the public API procedures 'Tcl_SignalId' and 'Tcl_SignalMsg'. [Bug 219172] 2001-04-02 Jeff Hobbs * README: * win/README: * win/README.binary: further notes corrections. * win/configure: * win/tcl.m4 (SHLIB_LD): added -incremental:no. [Bug 219381] 2001-04-01 Jeff Hobbs * README: * mac/README: * win/README: * win/README.binary: * unix/README: updated patchlevel information to 8.4a3 and updated links and notes. * generic/tcl.h: * tools/tcl.wse.in: * win/configure.in (VER): * win/configure: * unix/configure: * unix/configure.in (VER): * unix/tcl.spec: updated patchlevel information to 8.4a3 2001-03-30 Jeff Hobbs * generic/tclCkalloc.c (TclFinalizeMemorySubsystem): set curTagPtr to NULL to allow for reuse. * generic/tclEvent.c (Tcl_Finalize): moved the tsdPtr initialization inside the subsystemsInitialized check to prevent it potentially getting called twice during finalization. [Patch 403532, Bug 219391] (wu) * generic/tclThreadTest.c (Tcl_ThreadObjCmd): cast fixes * generic/tclTest.c (TestChannelCmd): added cast to mollify Windows debug build. * win/tclWinSock.c (SocketEventProc): Fixed race condition in readability of socket on Windows. [Patch 410674, Bug 219205, 219333] * win/tcl.m4: added imm32.lib to LIBS_GUI for Tk IME support. * win/Makefile.in (install-libraries): removed extra \s that broke the target. (install-doc): improved install-* targets to use their base build dependency. 2001-03-30 Andreas Kupries * All of the changes below belong to TIP #10 [Tcl I/O Enhancement: Thread-Aware Channels]. See also [Patch 403358] at SF. * generic/tclIO.h (struct ChannelState, line 236f): Extended the structure with a new field of type 'Tcl_ThreadId' to hold the id of the thread currently managing all channels with this state. Note: This structure is shared by all channels in a stack of transformations. * generic/tclIO.c (Tcl_CreateChannel, lines 1058-1065): Modified to store the Id of the current thread in the 'ChannelState' of the new channel. * generic/tclIO.c (Tcl_SpliceChannel, lines 2265-2270): Modified in the same manner as 'Tcl_CreateChannel' as the channel will be managed by the current thread afterward. * generic/tclIO.c (Tcl_GetChannelThread, lines 1478-1503): * generic/tcl.decls (Tcl_GetChannelThread, lines 1504-1506): New API function to retrieve the Id of the managing thread from a channel. Implementation and declaration. * generic/tclTest.c (TestChannelCmd, lines 4520-4532): Added subcommand 'mthread' to query a channel about its managing thread. 2001-03-29 Mo DeJong * tests/interp.test: Print out warning when testinterpdelete command is not defined. Add tests that checks to make sure a child interp inherits the parent's cwd. 2001-03-29 Jeff Hobbs * doc/tcltest.n: corrected incorrect macro usage. * doc/lsort.n: corrected unbalanced nroff macros. * unix/tclUnixPipe.c (TclpCreateTempFile): prevent potential race condition and security leak in tmp filename creation. [Patch 402924] (max) * unix/configure: * unix/tcl.m4: corrected IRIX-5.x config to not use -n32. [Patch 403626] (english) * unix/tclUnixThrd.c (Tcl_ConditionWait): fixed handling of timeout for threads (corrects excessive CPU usage issue for Tk on Unix in threaded Tcl environment). [Bug 411603] (ruppert) 2001-03-29 Donal K. Fellows * doc/lsort.n: Added some notes that clarify the behaviour of [lsort] as well as a whole bunch of examples. [Bug 219202] 2001-03-27 Jeff Hobbs * doc/Alloc.3: corrected docs to note that Tcl_Attempt* return char *'s, not ints. [Bug 411388] * tests/regexp.test (regexp-19.1): * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): fixed handling of nulls in subspec value. 2001-03-26 Don Porter * generic/tclDecls.h (Tcl_InitCustomHashTable): Correction to patch from 2001-01-18; tclDecls.h was not generated using 'make genstubs'. 2001-03-26 Donal K. Fellows * win/tclWinInt.h (tclWinTCharEncoding): Removed as now a static variable in win/tclWin32Dll.c instead. 2001-03-23 Jeff Hobbs * generic/tclVar.c (Tcl_ArrayObjCmd): Corrected retrieval of resultPtr to prevent possible corruption. * generic/tclNamesp.c (Tcl_Import): Correctly freed a DString. [Patch 403755] (lavana) 2001-03-15 Donal K. Fellows * tests/set-old.test (set-old-7.2): Changed error behaviour of [unset] to agree with documentation, so must change test as well. 2001-03-14 Don Porter * library/package.tcl (pkg_mkIndex): Added patch from Vince Darley to make [pkg_mkIndex -verbose] even more verbose. [Bug 219349, Patch 403529] 2001-03-13 Donal K. Fellows * doc/info.n: Improved documentation for [info hostname]. [Bug 403840] * generic/tclVar.c (Tcl_UnsetObjCmd): Made command behave as documented [issue remaining from Bug 405769] * generic/tclCmdMZ.c (Tcl_StringObjCmd): A missing {return TCL_OK;} was causing memory corruption. [Bug 408002] * generic/tclExecute.c (TclDeleteExecEnv, GrowEvaluationStack, (TclExecuteByteCode): Added some casts to ClientData that are apparently needed on some architectures. 2001-03-12 Donal K. Fellows * tests/string.test: Fixed some test numberings and added a test. [Patch 403229] 2001-03-06 Donal K. Fellows * generic/tclVar.c (Tcl_UnsetObjCmd): Rewrote argument parser to avoid a read off the end of the argument array that could occur when executing something like [unset -nocomplain] was executed. Improved the error message given when too few arguments are given (-nocomplain should obviously be *before* --, not after it) and also modified the test suite to take account of that and the documentation to use the same improvement. [Bug 405769] 2001-03-02 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Fixed bug that could pass pointers to freed memory to command implementations, which most obviously caused some weird behaviour with [info level], but could have caused problems with user code and command traces too. [Bug 404865, Patch 405436] 2001-02-23 msofer * no changes; fixing up the missing comment in the previous one. Sorry. 2001-02-23 msofer * /cvsroot/tcl/tcl/tests/execute.test: added test for evaluation of an expression in a variable; evals once by compiling, second time using the previous compilation 2001-02-18 Kevin B. Kenny * doc/clock.n: Updated documentation to reflect the addition of compat/strftime.c, including the correct formatting of ISO-8601:1988 fiscal week number (%V). 2001-02-15 Donal K. Fellows * generic/tclCmdMZ.c (Tcl_SplitObjCmd): Improved efficiency of splitting strings into individual characters by adding hash so that only one Tcl_Obj per character is created. Improves performance of splitting of short strings and makes a huge difference to splitting of long strings, such as is done in the mime package in tcllib. [Bug 131523] 2001-01-31 Don Porter * win/makefile.vc (install-libraries): Corrected misdirected install directory for the msgcat 1.2 package. 2001-01-30 Don Porter * generic/tclIO.c (CopyData): Moved code that updates the count of how many bytes are left to copy. Corrects bug that when writing occurs in the background, the copy loop could be escaped without updating the count, causing CopyData() to try to copy more bytes than the toRead value originally passed to TclCopyChannel(), leading to hangs and misreporting of number of bytes copied. [Bug 118203, Patch 103432] 2001-01-18 Andreas Kupries Everything below belongs together, it fixes [Bug 123153] * generic/tcl.h (line 342): A bit more explanation about the default value for TCL_PRESERVE_BINARY_COMPATABILITY. * generic/tcl.h (line 1208): Define the macro 'Tcl_InitHashTable' only when TCL_PRESERVE_BINARY_COMPATIBILITY is not set as it kills binary compatibility to 8.3 and earlier versions. This is the main part of the patch/change. * generic/tcl.decls (line 1469): * generic/tclHash.c (Tcl_InitHashTable): * generic/tclHash.c (Tcl_InitHashTableEx): * generic/tclObj.c (Tcl_InitObjHashTable): Changed 'Tcl_InitHashTableEx' to 'Tcl_InitCustomHashTable'. This change is more of an estethical nature, replacing the ubiquitous 'Ex' suffix with a more meaningful name. The introduced binary incompatibility is deemed acceptable as it is between alpha versions. Updated callers. * doc/Hash.3: * unix/mkLinks: Changed 'Tcl_InitHashTableEx' to 'Tcl_InitCustomHashTable'. 2001-01-10 Donal K. Fellows * tests/winPipe.test (winpipe-1.20): * tests/winDde.test (createChildProcess): * tests/pkgMkIndex.test (pkgtest::createIndex): Removed assumption that paths contain no spaces which causes problems with both [eval] and [open |...] due to the well-known differences between lists and strings. Fixes [Bug 119406] 2001-01-04 Don Porter * tests/unixInit.test: * unix/tclUnixInit.c (TclpInitLibraryPath): * win/tclWinInit.c (TclpInitLibraryPath): Several entries in the library path ($tcl_libPath) are determined relative to the absolute path of the executable. When the executable is installed in or near the root directory of the file system, relative pathnames were being incorrectly generated, and in the worst case, memory access violations were crashing the program. [Bug 119416, Patch 102972] ****************************************************************** *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" *** *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" *** ****************************************************************** tcl8.6.5/ChangeLog0000644000175000017500000122227512663660064013353 0ustar sergeisergeiA NOTE ON THE CHANGELOG: Starting in early 2011, Tcl source code has been under the management of fossil, hosted at http://core.tcl.tk/tcl/ . Fossil presents a "Timeline" view of changes made that is superior in every way to a hand edited log file. Because of this, many Tcl developers are now out of the habit of maintaining this log file. You may still find useful things in it, but the Timeline is a better first place to look now. ============================================================================ 2013-09-19 Don Porter *** 8.6.1 TAGGED FOR RELEASE *** * generic/tcl.h: Bump version number to 8.6.1. * library/init.tcl: * unix/configure.in: * win/configure.in: * unix/tcl.spec: * README: * unix/configure: autoconf-2.59 * win/configure: 2013-09-19 Donal Fellows * doc/next.n (METHOD SEARCH ORDER): Bug [3606943]: Corrected description of method search order. 2013-09-18 Donal Fellows Bump TclOO version to 1.0.1 for release. 2013-09-17 Donal Fellows * generic/tclBinary.c (BinaryEncodeUu, BinaryDecodeUu): [Bug 2152292]: Corrected implementation of the core of uuencode handling so that the line length processing is correctly applied. ***POTENTIAL INCOMPATIBILITY*** Existing code that was using the old versions and working around the limitations will now need to do far less. The -maxlen option now has strict limits on the range of supported lengths; this is a limitation of the format itself. 2013-09-09 Donal Fellows * generic/tclOOMethod.c (CloneProcedureMethod): [Bug 3609693]: Strip the internal representation of method bodies during cloning in order to ensure that any bound references to instance variables are removed. 2013-09-01 Donal Fellows * generic/tclBinary.c (BinaryDecodeHex): [Bug b98fa55285]: Ensure that whitespace at the end of a string don't cause the decoder to drop the last decoded byte. 2013-08-03 Donal Fellows * library/auto.tcl: [Patch 3611643]: Allow TclOO classes to be found by the autoloading mechanism. 2013-08-02 Donal Fellows * generic/tclOODefineCmds.c (ClassSuperSet): Bug [9d61624b3d]: Stop crashes when emptying the superclass slot, even when doing elaborate things with metaclasses. 2013-08-01 Harald Oehlmann * tclUnixNotify.c (Tcl_InitNotifier): Bug [a0bc856dcd]: Start notifier thread again if we were forked, to solve Rivet bug 55153. 2013-07-05 Kevin B. Kenny * library/tzdata/Africa/Casablanca: * library/tzdata/America/Asuncion: * library/tzdata/Antarctica/Macquarie: * library/tzdata/Asia/Gaza: * library/tzdata/Asia/Hebron: * library/tzdata/Asia/Jerusalem: http://www.iana.org/time-zones/repository/releases/tzdata2013d.tar.gz 2013-07-03 Jan Nijtmans * unix/tclXtNotify.c: Bug [817249]: bring tclXtNotify.c up to date with Tcl_SetNotifier() change. 2013-07-02 Jan Nijtmans * unix/tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4 * unix/configure: (thanks to Brian Griffin) 2013-06-27 Jan Nijtmans * generic/tclConfig.c: Bug [9b2e636361]: Tcl_CreateInterp() needs * generic/tclMain.c: initialized encodings. 2013-06-18 Jan Nijtmans * generic/tclEvent.c: Bug [3611974]: InitSubsystems multiple thread issue. 2013-06-17 Jan Nijtmans * generic/regc_locale.c: Bug [a876646efe]: re_expr character class [:cntrl:] should contain \u0000 - \u001f 2013-06-09 Donal K. Fellows * generic/tclCompCmdsSZ.c (TclCompileTryCmd): [Bug 779d38b996]: Rewrote the [try] compiler to generate better code in some cases and to behave correctly in others; when an error happens during the processing of an exception-trap clause or a finally clause, the *original* return options are now captured in a -during option, even when fully compiled. 2013-06-05 Donal K. Fellows * generic/tclExecute.c (INST_EXPAND_DROP): [Bugs 2835313, 3614226]: New opcode to allow resetting the stack to get rid of an expansion, restoring the stack to a known state in the process. * generic/tclCompile.c, generic/tclCompCmds.c: Adjusted the compilers for [break] and [continue] to get stack cleanup right in the majority of cases. * tests/for.test (for-7.*): Set of tests for these evil cases. 2013-06-04 Jan Nijtmans * unix/tcl.m4: Eliminate NO_VIZ macro as current zlib uses HAVE_HIDDEN instead. One more last-moment fix for FreeBSD by Pietro Cerutti 2013-06-03 Miguel Sofer * generic/tclExecute.c: fix for perf bug detected by Kieran (https://groups.google.com/forum/?fromgroups#!topic/comp.lang.tcl/vfpI3bc-DkQ), diagnosed by dgp to be a close relative of [Bug 781585], which was fixed by commit [f46fb50cb3]. This bug was introduced by myself in commit [cbfe055d8c]. 2013-06-03 Donal K. Fellows * generic/tclCompCmds.c (TclCompileBreakCmd, TclCompileContinueCmd): Added code to allow [break] and [continue] to be issued as a jump (in the most common cases) rather than using the more expensive exception processing path in the bytecode engine. [Bug 3614226]: Partial fix for the issues relating to cleaning up the stack when dealing with [break] and [continue]. 2013-05-27 Harald Oehlmann * library/msgcat/msgcat.tcl: [Bug 3036566]: Also get locale from registry key HCU\Control Panel\Desktop : PreferredUILanguages to honor installed language packs on Vista+. Bumped msgcat version to 1.5.2 2013-05-22 Andreas Kupries * tclCompile.c: Removed duplicate const qualifier causing the HP native cc to error out. 2013-05-22 Donal K. Fellows * generic/tclUtf.c (TclUtfCasecmp): [Bug 3613609]: Replace problematic uses of strcasecmp with a proper UTF-8-aware version. Affects both [lsearch -nocase] and [lsort -nocase]. 2013-05-22 Donal K. Fellows * doc/file.n: [Bug 3613671]: Added note to portability section on the fact that [file owned] does not produce useful results on Windows. 2013-05-20 Donal K. Fellows * unix/tclUnixFCmd.c (DefaultTempDir): [Bug 3613567]: Corrected logic for checking return code of access() system call, which was inverted. 2013-05-19 Jan Nijtmans * unix/tcl.m4: Fix for FreeBSD, and remove support for older * unix/configure: FreeBSD versions. Patch by Pietro Cerutti. 2013-05-18 Donal K. Fellows * generic/tclCompCmdsGR.c: Split tclCompCmds.c again to keep size of code down. 2013-05-16 Jan Nijtmans * generic/tclBasic.c: Add panic in order to detect incompatible mingw32 sys/stat.h and sys/time.h headers. 2013-05-13 Jan Nijtmans * compat/zlib/*: Upgrade to zlib 1.2.8 2013-05-10 Donal K. Fellows Optimizations and general bytecode generation improvements. * generic/tclCompCmds.c (TclCompileAppendCmd, TclCompileLappendCmd): (TclCompileReturnCmd): Make these generate bytecode in more cases. (TclCompileListCmd): Make this able to push a literal when it can. * generic/tclCompile.c (TclSetByteCodeFromAny, PeepholeOptimize): Added checks to see if we can apply some simple cross-command-boundary optimizations, and defined a small number of such optimizations. (TclCompileScript): Added the special ability to compile the list command with expansion ([list {*}blah]) into bytecode that does not call an external command. 2013-05-06 Jan Nijtmans * generic/tclStubInit.c: Add support for Cygwin64, which has a 64-bit * generic/tclDecls.h: "long" type. Binary compatibility with win64 requires that all stub entries use 32-bit long's, therefore the need for various wrapper functions/macros. For Tcl 9 a better solution is needed, but that cannot be done without introducing binary incompatibility. 2013-04-30 Andreas Kupries * library/platform/platform.tcl (::platform::LibcVersion): * library/platform/pkgIndex.tcl: Followup to the 2013-01-30 change. The RE become too restrictive again. SuSe added a timestamp after the version. Loosened up a bit. Bumped package to version 1.0.12. 2013-04-29 Donal K. Fellows * generic/tclCompCmds.c (TclCompileArraySetCmd): Generate better code when the list of things to set is a literal. 2013-04-25 Jan Nijtmans * generic/tclDecls.h: Implement Tcl_NewBooleanObj, Tcl_DbNewBooleanObj and Tcl_SetBooleanObj as macros using Tcl_NewIntObj, Tcl_DbNewLongObj and Tcl_SetIntObj. Starting with Tcl 8.5, this is exactly the same, it only eliminates code duplication. * generic/tclInt.h: Eliminate use of NO_WIDE_TYPE everywhere: It's exactly the same as TCL_WIDE_INT_IS_LONG 2013-04-19 Jan Nijtmans * generic/tclDecls.h: Implement many Tcl_*Var* functions and Tcl_GetIndexFromObj as (faster/stack-saving) macros around resp their Tcl_*Var*2 equivalent and Tcl_GetIndexFromObjStruct. 2013-04-12 Jan Nijtmans * generic/tclDecls.h: Implement Tcl_Pkg* functions as (faster/stack-saving) macros around Tcl_Pkg*Ex functions. 2013-04-08 Don Porter * generic/regc_color.c: [Bug 3610026]: Stop crash when the number of * generic/regerrs.h: "colors" in a regular expression overflows a * generic/regex.h: short int. Thanks to Heikki Linnakangas for * generic/regguts.h: the report and the patch. * tests/regexp.test: 2013-04-04 Reinhard Max * library/http/http.tcl (http::geturl): Allow URLs that don't have a path, but a query query, e.g. http://example.com?foo=bar * Bump the http package to 2.8.7. 2013-03-22 Venkat Iyer * library/tzdata/Africa/Cairo: Update to tzdata2013b. * library/tzdata/Africa/Casablanca: * library/tzdata/Africa/Gaborone: * library/tzdata/Africa/Tripoli: * library/tzdata/America/Asuncion: * library/tzdata/America/Barbados: * library/tzdata/America/Bogota: * library/tzdata/America/Costa_Rica: * library/tzdata/America/Curacao: * library/tzdata/America/Nassau: * library/tzdata/America/Port-au-Prince: * library/tzdata/America/Santiago: * library/tzdata/Antarctica/Palmer: * library/tzdata/Asia/Aden: * library/tzdata/Asia/Hong_Kong: * library/tzdata/Asia/Muscat: * library/tzdata/Asia/Rangoon: * library/tzdata/Asia/Shanghai: * library/tzdata/Atlantic/Bermuda: * library/tzdata/Europe/Vienna: * library/tzdata/Pacific/Easter: * library/tzdata/Pacific/Fiji: * library/tzdata/Asia/Khandyga: (new) * library/tzdata/Asia/Ust-Nera: (new) * library/tzdata/Europe/Busingen: (new) 2013-03-21 Don Porter * library/auto.tcl: [Bug 2102614]: Add ensemble indexing support to * tests/autoMkindex.test: [auto_mkindex]. Thanks Brian Griffin. 2013-03-19 Don Porter * generic/tclFCmd.c: [Bug 3597000]: Consistent [file copy] result. * tests/fileSystem.test: 2013-03-19 Jan Nijtmans * win/tclWinFile.c: [Bug 3608360]: Incompatible behaviour of "file exists". 2013-03-18 Donal K. Fellows * tests/cmdAH.test (cmdAH-19.12): [Bug 3608360]: Added test to ensure that we never ever allow [file exists] to do globbing. 2013-03-12 Jan Nijtmans * unix/tcl.m4: Patch by Andrew Shadura, providing better support for three architectures they have in Debian. 2013-03-11 Don Porter * generic/tclCompile.c: [Bugs 3607246,3607372]: Unbalanced refcounts * generic/tclLiteral.c: of literals in the global literal table. 2013-03-06 Don Porter * generic/regc_nfa.c: [Bugs 3604074,3606683]: Rewrite of the * generic/regcomp.c: fixempties() routine (and supporting routines) to completely eliminate the infinite loop hazard. Thanks to Tom Lane for the much improved solution. 2013-02-28 Don Porter * generic/tclLiteral.c: Revise TclReleaseLiteral() to tolerate a NULL interp argument. * generic/tclCompile.c: Update callers and revise mistaken comments. * generic/tclProc.c: 2013-02-27 Jan Nijtmans * generic/regcomp.c: [Bug 3606139]: missing error check allows * tests/regexp.test: regexp to crash Tcl. Thanks to Tom Lane for providing the test-case and the patch. 2013-02-26 Donal K. Fellows * tests/chanio.test (chan-io-28.7): [Bug 3605120]: Stop test from hanging when run standalone. 2013-02-26 Jan Nijtmans * generic/tclObj.c: Don't panic if Tcl_ConvertToType is called for a type that doesn't have a setFromAnyProc, create a proper error message. 2013-02-25 Donal K. Fellows * tests/binary.test (binary-41.*): [Bug 3605721]: Test independence fixes. Thanks to Rolf Ade for pointing out the problem. 2013-02-25 Don Porter * tests/assocd.test: [Bugs 3605719,3605720]: Test independence. * tests/basic.test: Thanks Rolf Ade for patches. 2013-02-23 Jan Nijtmans * compat/fake-rfc2553.c: [Bug 3599194]: compat/fake-rfc2553.c is broken. 2013-02-22 Don Porter * generic/tclAssembly.c: Shift more burden of smart cleanup * generic/tclCompile.c: onto the TclFreeCompileEnv() routine. Stop crashes when the hookProc raises an error. 2013-02-20 Don Porter * generic/tclNamesp.c: [Bug 3605447]: Make sure the -clear option * tests/namespace.test: to [namespace export] always clears, whether or not new export patterns are specified. 2013-02-20 Jan Nijtmans * win/tclWinDde.c: [Bug 3605401]: Compiler error with latest mingw-w64 headers. 2013-02-19 Jan Nijtmans * generic/tclTrace.c: [Bug 2438181]: Incorrect error reporting in * tests/trace.test: traces. Test-case and fix provided by Poor Yorick. 2013-02-15 Don Porter * generic/regc_nfa.c: [Bug 3604074]: Fix regexp optimization to * tests/regexp.test: stop hanging on the expression ((((((((a)*)*)*)*)*)*)*)* . Thanks to Bjørn Grathwohl for discovery. 2013-02-14 Harald Oehlmann * library/msgcat/msgcat.tcl: [Bug 3604576]: Catch missing registry entry "HCU\Control Panel\International". Bumped msgcat version to 1.5.1 2013-02-11 Donal K. Fellows * generic/tclZlib.c (ZlibTransformOutput): [Bug 3603553]: Ensure that data gets written to the underlying stream by compressing transforms when the amount of data to be written is one buffer's-worth; problem was particularly likely to occur when compressing large quantities of not-very-compressible data. Many thanks to Piera Poggio (vampiera) for reporting. 2013-02-09 Donal K. Fellows * generic/tclOOBasic.c (TclOO_Object_VarName): [Bug 3603695]: Change the way that the 'varname' method is implemented so that there are no longer problems with interactions due to the resolver. Thanks to Taylor Venable for identifying the problem. 2013-02-08 Donal K. Fellows * generic/regc_nfa.c (duptraverse): [Bug 3603557]: Increase the maximum depth of recursion used when duplicating an automaton in response to encountering a "wild" RE that hit the previous limit. Allow the limit (DUPTRAVERSE_MAX_DEPTH) to be set by defining its value in the Makefile. Problem reported by Jonathan Mills. 2013-02-05 Don Porter * win/tclWinFile.c: [Bug 3603434]: Make sure TclpObjNormalizePath() properly declares "a:/" to be normalized, even when no "A:" drive is present on the system. 2013-02-05 Donal K. Fellows * generic/tclLoadNone.c (TclpLoadMemory): [Bug 3433012]: Added dummy version of this function to use in the event that a platform thinks it can load from memory but cannot actually do so due to it being disabled at configuration time. 2013-02-04 Donal K. Fellows * generic/tclCompCmds.c (TclCompileArraySetCmd): [Bug 3603163]: Stop crash in weird case where [eval] is used to make [array set] get confused about whether there is a local variable table or not. Thanks to Poor Yorick for identifying a reproducible crashing case. 2013-01-30 Andreas Kupries * library/platform/platform.tcl (::platform::LibcVersion): See * library/platform/pkgIndex.tcl: [Bug 3599098]: Fixed the RE * unix/Makefile.in: extracting the version to avoid issues with * win/Makefile.in: recent changes to the glibc banner. Now targeting a less variable part of the string. Bumped package to version 1.0.11. 2013-01-28 Donal K. Fellows * generic/tclCompCmds.c (TclCompileArraySetCmd) (TclCompileArrayUnsetCmd, TclCompileDictAppendCmd) (TclCompileDictCreateCmd, CompileDictEachCmd, TclCompileDictIncrCmd) (TclCompileDictLappendCmd, TclCompileDictMergeCmd) (TclCompileDictUnsetCmd, TclCompileDictUpdateCmd) (TclCompileDictWithCmd, TclCompileInfoCommandsCmd): * generic/tclCompCmdsSZ.c (TclCompileStringMatchCmd) (TclCompileStringMapCmd): Improve the code generation in cases where full compilation is impossible but a full ensemble invoke is provably not necessary. 2013-01-26 Jan Nijtmans * unix/tclUnixCompat.c: [Bug 3601804]: platformCPUID segmentation fault on Darwin. 2013-01-23 Donal K. Fellows * library/http/http.tcl (http::geturl): [Bug 2911139]: Do not do vwait for connect to avoid reentrancy problems (except when operating without a -command option). Internally, this means that all sockets created by the http package will always be operated in asynchronous mode. 2013-01-21 Jan Nijtmans * generic/tclInt.decls: Put back Tcl[GS]etStartupScript(Path|FileName) in private stub table, so extensions using this (like Tk 8.4) will continue to work in all Tcl 8.x versions. Extensions using this still cannot be compiled against Tcl 8.6 headers. 2013-01-18 Jan Nijtmans * generic/tclPort.h: [Bug 3598300]: unix: tcl.h does not include sys/stat.h 2013-01-17 Donal K. Fellows * generic/tclCompCmds.c (PushVarName): [Bug 3600328]: Added mechanism for suppressing compilation of variables when we couldn't cope with the results. Useful for some [array] subcommands. * generic/tclEnsemble.c (CompileToCompiledCommand): Must restore the compilation environment when a command compiler fails. 2013-01-16 Donal K. Fellows * generic/tclZlib.c (TclZlibInit): [Bug 3601086]: Register the config info in the iso8859-1 encoding as that is guaranteed to be present. 2013-01-16 Jan Nijtmans * Makefile.in: Allow win32 build with -DTCL_NO_DEPRECATED, just as * generic/tcl.h: in the UNIX build. Define Tcl_EvalObj and * generic/tclDecls.h: Tcl_GlobalEvalObj as macros, even when * generic/tclBasic.c: TCL_NO_DEPRECATED is defined, so Tk can benefit from it too. 2013-01-14 Jan Nijtmans * win/tcl.m4: More flexible search for win32 tclConfig.sh, backported from TEA (not actually used in Tcl, only for Tk) 2013-01-14 Jan Nijtmans * generic/tclInt.decls: Put back Tcl_[GS]etStartupScript in internal stub table, so extensions using this, compiled against 8.5 headers still run in Tcl 8.6. 2013-01-13 Alexandre Ferrieux * doc/fileevent.n: [Bug 3436609]: Clarify readable fileevent "false positives" in the case of multibyte encodings/transforms. 2013-01-13 Jan Nijtmans * generic/tclIntDecls.h: If TCL_NO_DEPRECATED is defined, make sure that TIP #139 functions all are taken from the public stub table, even if the inclusion is through tclInt.h. 2013-01-12 Jan Nijtmans * generic/tclInt.decls: Put back TclBackgroundException in internal stub table, so extensions using this, compiled against 8.5 headers still run in Tcl 8.6. 2013-01-09 Jan Nijtmans * library/http/http.tcl: [Bug 3599395]: http assumes status line is a proper Tcl list. 2013-01-08 Jan Nijtmans * win/tclWinFile.c: [Bug 3092089]: [file normalize] can remove path components. [Bug 3587096]: win vista/7: "can't find init.tcl" when called via junction without folder list access. 2013-01-07 Jan Nijtmans * generic/tclOOStubLib.c: Restrict the stub library to only use * generic/tclTomMathStubLib.c: Tcl_PkgRequireEx, Tcl_ResetResult and Tcl_AppendResult, not any other function. This puts least restrictions on eventual Tcl 9 stubs re-organization, and it works on the widest range of Tcl versions. 2013-01-06 Jan Nijtmans * library/http/http.tcl: Don't depend on Spencer-specific regexp * tests/env.test: syntax (/u and /U) any more in unrelated places. * tests/exec.test: Bump http package to 2.8.6. 2013-01-04 Donal K. Fellows * generic/tclEnsemble.c (CompileBasicNArgCommand): Added very simple compiler (which just compiles to a normal invoke of the implementation command) for many ensemble subcommands where we can prove that there is no way for scripts to detect the difference even through error handling or [info level]/[info frame]. This improves the code produced from some ensembles (e.g., [info], [string]) to the point where the ensemble is now not normally seen at the bytecode level at all. 2013-01-04 Miguel Sofer * generic/tclInt.h: Insure that PURIFY builds cannot exploit the * generic/tclExecute.c: Tcl stack to hide mem defects. 2013-01-03 Donal K. Fellows * doc/fconfigure.n, doc/CrtChannel.3: Updated to reflect the fact that the minimum buffer size is one byte, not ten. Identified by Schelte Bron on the Tcler's Chat. * generic/tclExecute.c (TEBCresume:INST_INVOKE_REPLACE): * generic/tclEnsemble.c (TclCompileEnsemble): Added new mechanism to allow for more efficient dispatch of non-bytecode-compiled subcommands of bytecode-compiled ensembles. This can provide substantial speed benefits in some cases. 2013-01-02 Miguel Sofer * generic/tclEnsemble.c: Remove stray calls to Tcl_Alloc and friends: * generic/tclExecute.c: the core should only use ckalloc to allow * generic/tclIORTrans.c: MEM_DEBUG to work properly. * generic/tclTomMathInterface.c: 2012-12-31 Donal K. Fellows * doc/string.n: Noted the obsolescence of the 'bytelength', 'wordstart' and 'wordend' subcommands, and moved them to later in the file. 2012-12-27 Jan Nijtmans * generic/tclListObj.c: [Bug 3598580]: Tcl_ListObjReplace may release deleted elements too early. 2012-12-22 Alexandre Ferrieux * generic/tclUtil.c: [Bug 3598150]: Stop leaking allocated space when objifying a zero-length DString. Spotted by afredd. 2012-12-21 Jan Nijtmans * unix/dltest/pkgb.c: Inline compat Tcl_GetDefaultEncodingDir. * generic/tclStubLib.c: Eliminate unnecessary static HasStubSupport() and isDigit() functions, just do the same inline. 2012-12-18 Donal K. Fellows * generic/tclCompCmdsSZ.c (TclSubstCompile): Improved the sequence of instructions issued for [subst] when dealing with simple variable references. 2012-12-14 Don Porter *** 8.6.0 TAGGED FOR RELEASE *** * changes: updates for 8.6.0 2012-12-13 Don Porter * generic/tclZlib.c: Repair same issue with misusing the * tests/zlib.test: 'fire and forget' nature of Tcl_ObjSetVar2 in the new TIP 400 implementation. 2012-12-13 Miguel Sofer * generic/tclCmdAH.c: (CatchObjCmdCallback): do not decrRefCount * tests/cmdAH.test: the newValuePtr sent to Tcl_ObjSetVar2: TOSV2 is 'fire and forget', it decrs on its own. Fix for [Bug 3595576], found by andrewsh. 2012-12-13 Jan Nijtmans * generic/tcl.h: Fix Tcl_DecrRefCount macro such that it doesn't access its objPtr parameter twice any more. 2012-12-11 Don Porter * generic/tcl.h: Bump version number to 8.6.0. * library/init.tcl: * unix/configure.in: * win/configure.in: * unix/tcl.spec: * README: * unix/configure: autoconf-2.59 * win/configure: 2012-12-10 Donal K. Fellows * tools/tcltk-man2html.tcl (plus-pkgs): Increased robustness of version number detection code to deal with packages whose names are prefixes of other packages. * unix/Makefile.in (dist): Added pkgs/package.list.txt to distribution builds to ensure that 'make html' will work better. 2012-12-09 Alexandre Ferrieux * tests/chan.test: Clean up unwanted eofchar side-effect of chan-4.6 leading to a spurious "'" at end of chan.test under certain conditions (see [Bug 3389289] and [Bug 3389251]). * doc/expr.n: [Bug 3594188]: Clarifications about commas. 2012-12-08 Alexandre Ferrieux * generic/tclIO.c: Fix busyloop at exit under TCL_FINALIZE_ON_EXIT when there are unflushed nonblocking channels. Thanks Miguel for spotting. 2012-12-07 Jan Nijtmans * unix/dltest/pkgb.c: Turn pkgb.so into a Tcl9 interoperability test library: Whatever Tcl9 looks like, loading pkgb.so in Tcl 9 should either result in an error-message, either succeed, but never crash. 2012-11-28 Donal K. Fellows * generic/tclZlib.c (ZlibStreamSubcmd): [Bug 3590483]: Use a mechanism for complex option resolution that has fewer problems with more finicky compilers. 2012-11-26 Reinhard Max * unix/tclUnixSock.c: Factor out creation of the -sockname and -peername lists from TcpGetOptionProc() to TcpHostPortList(). Make it robust against implementations of getnameinfo() that error out if reverse mapping fails instead of falling back to the numeric representation. 2012-11-20 Donal K. Fellows * generic/tclBinary.c (BinaryDecode64): [Bug 3033307]: Corrected handling of trailing whitespace when decoding base64. Thanks to Anton Kovalenko for reporting, and Andy Goth for the fix and tests. 2012-11-19 Donal K. Fellows * generic/tclExecute.c (INST_STR_RANGE_IMM): [Bug 3588366]: Corrected implementation of bounds restriction for end-indexed compiled [string range]. Thanks to Emiliano Gavilan for diagnosis and fix. 2012-11-15 Jan Nijtmans IMPLEMENTATION OF TIP#416 New Options for 'load': -global and -lazy * generic/tcl.h: * generic/tclLoad.c * unix/tclLoadDl.c * unix/tclLoadDyld.c * tests/load.test * doc/Load.3 * doc/load.n 2012-11-14 Donal K. Fellows * unix/tclUnixFCmd.c (TclUnixOpenTemporaryFile): [Bug 2933003]: Factor out all the code to do temporary file creation so that it is possible to make it correct in one place. Allow overriding of the back-stop default temporary file location at compile time by setting the TCL_TEMPORARY_FILE_DIRECTORY #def to a string containing the directory name (defaults to "/tmp" as that is the most common default). 2012-11-13 Joe Mistachkin * win/tclWinInit.c: also search for the library directory (init.tcl, encodings, etc) relative to the build directory associated with the source checkout. 2012-11-10 Miguel Sofer * generic/tclBasic.c: re-enable bcc-tailcall, after fixing an * generic/tclExecute.c: infinite loop in the TCL_COMPILE_DEBUG mode 2012-11-07 Kevin B. Kenny * library/tzdata/Africa/Casablanca: * library/tzdata/America/Araguaina: * library/tzdata/America/Bahia: * library/tzdata/America/Havana: * library/tzdata/Asia/Amman: * library/tzdata/Asia/Gaza: * library/tzdata/Asia/Hebron: * library/tzdata/Asia/Jerusalem: * library/tzdata/Pacific/Apia: * library/tzdata/Pacific/Fakaofo: * library/tzdata/Pacific/Fiji: Import tzdata2012i. 2012-11-06 Donal K. Fellows * library/http/http.tcl (http::Finish): [Bug 3581754]: Ensure that callbacks are done at most once to prevent problems with timeouts on a keep-alive connection (combined with reentrant http package use) causing excessive stack growth. Not a fix for the underlying problem, but ensures that pain will be mostly kept away from users. Bump http package to 2.8.5. 2012-11-05 Donal K. Fellows Added bytecode compilation of many Tcl commands. Some of these are total compilations and some are only partial (i.e., only compile in some cases). The (sub-)commands affected are: * array: exists, set, unset * dict: create, exists, merge * format: (simple cases only) * info: commands, coroutine, level, object * info object: class, isa object, namespace * namespace: current, code, qualifiers, tail, which * regsub: (only cases convertable to simple [string map]) * self: (only no-argument and [self object] cases) * string: first, last, map, range * tailcall: * yield: [This was work originally done on the 'dkf-compile-misc-info' branch.] 2012-11-05 Jan Nijtmans IMPLEMENTATION OF TIP#413 Align the [string trim] and [string is space] commands, such that [string trim] by default trims all characters for which [string is space] returns 1, augmented with the NUL character. * generic/tclUtf.c: Add NEL, BOM and two more characters to [string is space] * generic/tclCmdMZ.c: Modify [string trim] for Unicode modifications. * generic/regc_locale.c: Regexp engine must match [string is space] * doc/string.n * tests/string.test ***POTENTIAL INCOMPATIBILITY*** Code that relied on characters not previously trimmed being not removed will notice a difference; it is believed that this is rare, but a workaround to get the behavior in Tcl 8.5 is to use " \t\n\r" as an explicit trim set. 2012-10-31 Jan Nijtmans * win/Makefile.in: Dde version number to 1.4.0, ready for Tcl 8.6.0rc1 * win/makefile.vc * win/tclWinDde.c * library/dde/pkgIndex.tcl * tests/winDde.test 2012-10-24 Donal K. Fellows * generic/tclCompCmds.c (TclCompileDictUnsetCmd): Added compilation of the [dict unset] command (for scalar var in LVT only). 2012-10-23 Jan Nijtmans * generic/tclInt.h: Add "flags" parameter from Tcl_LoadFile to * generic/tclIOUtil.c: to various internal functions, so these * generic/tclLoadNone.c: flags are available through the whole * unix/tclLoad*.c: filesystem for (future) internal use. * win/tclWinLoad.c: 2012-10-17 Miguel Sofer * generic/tclBasic.c (TclNRCoroutineObjCmd): insure that numlevels are properly set, fix bug discovered by dkf and reported at http://code.activestate.com/lists/tcl-core/12213/ 2012-10-16 Donal K. Fellows IMPLEMENTATION OF TIP#405 New commands for applying a transformation to the elements of a list to produce another list (the [lmap] command) and to the mappings of a dictionary to produce another dictionary (the [dict map] command). In both cases, a [continue] will cause the skipping of an element/pair, and a [break] will terminate the construction early and successfully. * generic/tclCmdAH.c (Tcl_LmapObjCmd, TclNRLmapCmd): Implementation of the new [lmap] command, based on (and sharing much of) [foreach]. * generic/tclDictObj.c (DictMapNRCmd): Implementation of the new [dict map] subcommand, based on (and sharing much of) [dict for]. * generic/tclCompCmds.c (TclCompileLmapCmd, TclCompileDictMapCmd): Compilation engines for [lmap] and [dict map]. IMPLEMENTATION OF TIP#400 * generic/tclZlib.c: Allow the specification of a compression dictionary (a binary blob used to seed the compression engine) in both streams and channel transformations. Also some reorganization to allow for getting gzip header dictionaries and controlling buffering levels in channel transformations (allowing a trade-off between formal correctness and speed). (Tcl_ZlibStreamSetCompressionDictionary): New C API to allow setting the compression dictionary without using a Tcl script. 2012-10-14 Jan Nijtmans * generic/tclDictObj.c: [Bug 3576509]: ::tcl::Bgerror crashes with * generic/tclEvent.c: invalid arguments. Better fix, which helps for all Tcl_DictObjGet() calls in Tcl's source code. 2012-10-13 Jan Nijtmans * generic/tclEvent.c: [Bug 3576509]: tcl::Bgerror crashes with invalid arguments 2012-10-06 Jan Nijtmans * win/Makefile.in: [Bug 2459774]: tcl/win/Makefile.in not compatible with msys 0.8. 2012-10-03 Don Porter * generic/tclIO.c: When checking for std channels being closed, compare the channel state, not the channel itself so that stacked channels do not cause trouble. 2012-09-26 Reinhard Max * generic/tclIOSock.c (TclCreateSocketAddress): Work around a bug in getaddrinfo() on OSX that caused name resolution to fail for [socket -server foo -myaddr localhost 0]. 2012-09-20 Jan Nijtmans * win/configure.in: New import libraries for zlib 1.2.7, usable for * win/configure: all win32/win64 compilers * compat/zlib/win32/zdll.lib: * compat/zlib/win64/zdll.lib: * win/tclWinDde.c: [FRQ 3527238]: Full unicode support for dde. Dde version is now 1.4.0b2. ***POTENTIAL INCOMPATIBILITY*** 2012-09-19 Jan Nijtmans * generic/tcl.h: Make Tcl_Interp a fully opaque structure if TCL_NO_DEPRECATED is set (TIP 330 and 336). * win/nmakehlp.c: Let "nmakehlp -V" start searching digits after the found match (suggested by Harald Oehlmann). 2012-09-19 Harald Oehlmann IMPLEMENTATION OF TIP#412. * library/msgcat/msgcat.tcl: dynamic locale change with mc file * library/clock.tcl: load on locale change. clock uses new msgcat features. 2012-09-07 Harald Oehlmann *** 8.6b3 TAGGED FOR RELEASE *** IMPLEMENTATION OF TIP#404. * library/msgcat/msgcat.tcl: [FRQ 3544988]: New commands [mcflset] * library/msgcat/pkgIndex.tcl: and [mcflmset] to set mc entries with * unix/Makefile.in: implicit message file locale. * win/Makefile.in: Bump to 1.5.0. 2012-08-25 Donal K. Fellows * library/msgs/uk.msg: [Bug 3561330]: Use the correct full name of March in Ukrainian. Thanks to Mikhail Teterin for reporting. 2012-08-23 Jan Nijtmans * generic/tclBinary.c: [Bug 3496014]: Unecessary memset() in Tcl_SetByteArrayObj(). 2012-08-20 Don Porter * generic/tclPathObj.c: [Bug 3559678]: Fix bad filename normalization when the last component is the empty string. 2012-08-20 Jan Nijtmans * win/tclWinPort.h: Remove wrapper macro for ntohs(): unnecessary, because it doesn't require an initialized winsock_2 library. See: * win/tclWinSock.c: * generic/tclStubInit.c: 2012-08-17 Jan Nijtmans * win/nmakehlp.c: Add "-V" option, in order to be able to detect partial version numbers. 2012-08-15 Jan Nijtmans * win/buildall.vc.bat: Only build the threaded builds by default * win/rules.vc: Some code cleanup 2010-08-13 Stuart Cassoff * unix/tclUnixCompat.c: [Bug 3555454]: Rearrange a bit to quash 'declared but never defined' compiler warnings. 2012-08-13 Jan Nijtmans * compat/zlib/win64/zlib1.dll: Add 64-bit build of zlib1.dll, and use * compat/zlib/win64/zdll.lib: it for the dynamic mingw-w64 build. * win/Makefile.in: * win/configure.in: * win/configure: 2012-08-09 Reinhard Max * tests/http.test: Fix http-3.29 for machines without IPv6 support. 2010-08-08 Stuart Cassoff * unix/tclUnixCompat.c: Change one '#ifdef' to '#if defined()' for improved consistency within the file. 2012-08-08 Jan Nijtmans * generic/tclfileName.c: [Bug #1536227]: Cygwin network pathname * tests/fileName.test: support 2012-08-07 Don Porter * generic/tclIOUtil.c: [Bug 3554250]: Overlooked one field of cleanup in the thread exit handler for the filesystem subsystem. 2012-07-31 Donal K. Fellows * generic/tclInterp.c (Tcl_GetInterpPath): * unix/tclUnixPipe.c (TclGetAndDetachPids, Tcl_PidObjCmd): * win/tclWinPipe.c (TclGetAndDetachPids, Tcl_PidObjCmd): Purge use of Tcl_AppendElement, and corrected conversion of PIDs to integer objects. 2012-07-31 Jan Nijtmans * win/nmakehlp.c: Add -Q option from sampleextension. * win/Makefile.in: [FRQ 3544967]: Missing objectfiles in static lib * win/makefile.vc: (Thanks to Jos Decoster). 2012-07-29 Jan Nijtmans * win/Makefile.in: No longer build tcltest.exe to run the tests, but use tclsh86.exe in combination with tcltest86.dll to do that. * tests/*.test: load tcltest86.dll if necessary. 2012-07-28 Jan Nijtmans * tests/clock.test: [Bug 3549770]: Multiple test failures running * tests/registry.test: tcltest outside build tree * tests/winDde.test: 2012-07-27 Jan Nijtmans * generic/tclUniData.c: Support Unicode 6.2 (Add Turkish lira sign) * generic/regc_locale.c: 2012-07-25 Alexandre Ferrieux * win/tclWinPipe.c: [Bug 3547994]: Abandon the synchronous Windows pipe driver to its fate when needed to honour TIP#398. 2012-07-24 Trevor Davel * win/tclWinSock.c: [Bug: 3545363]: Loop over multiple underlying file descriptors for a socket where required (TcpCloseProc, SocketProc). Refactor socket/descriptor setup to manage linked list operations in one place. Fix memory leak in socket close (TcpCloseProc) and related dangling pointers in SocketEventProc. 2012-07-19 Reinhard Max * win/tclWinSock.c (TcpAccept): [Bug: 3545363]: Use a large enough buffer for accept()ing IPv6 connections. Fix conversion of host and port for passing to the accept proc to be independent of the IP version. 2012-07-23 Alexandre Ferrieux * generic/tclIO.c: [Bug 3545365]: Never try a bg-flush on a dead channel, just like before 2011-08-17. 2012-07-19 Joe Mistachkin * generic/tclTest.c: Fix several more missing mutex-locks in TestasyncCmd. 2012-07-19 Alexandre Ferrieux * generic/tclTest.c: [Bug 3544685]: Missing mutex-lock in TestasyncCmd since 2011-08-19. Unbounded gratitude to Stuart Cassoff for spotting it. 2012-07-17 Jan Nijtmans * win/makefile.vc: [Bug 3544932]: Visual studio compiler check fails 2012-07-16 Donal K. Fellows * generic/tclUtil.c (UpdateStringOfEndOffset): [Bug 3544658]: Stop 1-byte overrun in memcpy, that object placement rules made harmless but which still caused compiler complaints. 2012-07-16 Jan Nijtmans * library/reg/pkgIndex.tcl: Make registry 1.3 package dynamically loadable when ::tcl::pkgconfig is available. 2012-07-11 Jan Nijtmans * win/tclWinReg.c: [Bug 3362446]: registry keys command fails with 8.5/8.6. Follow Microsofts example better in order to prevent problems when using HKEY_PERFORMANCE_DATA. 2012-07-10 Jan Nijtmans * unix/tclUnixNotfy.c: [Bug 3541646]: Don't panic on triggerPipe overrun. 2012-07-10 Donal K. Fellows * win/tclWinSock.c (InitializeHostName): Corrected logic that extracted the name of the computer from the gethostname call so that it would use the name on success, not failure. Also ensured that the buffer size is exactly that recommended by Microsoft. 2012-07-08 Reinhard Max * library/http/http.tcl: [Bug 3531209]: Add fix and test for URLs that * tests/http.test: contain literal IPv6 addresses. 2012-07-05 Don Porter * unix/tclUnixPipe.c: [Bug 1189293]: Make "<<" binary safe. * win/tclWinPipe.c: 2012-07-03 Donal K. Fellows * generic/tclUtil.c (TclDStringAppendObj, TclDStringAppendDString): * generic/tclInt.h (TclDStringAppendLiteral, TclDStringClear): * generic/tclCompile.h (TclDStringAppendToken): Added wrappers to make common cases of appending to Tcl_DStrings simpler to write. Prompted by looking at [FRQ 1357401] (these are an _internal_ implementation of that FRQ). 2012-06-29 Jan Nijtmans * library/msgcat/msgcat.tcl: Add tn, ro_MO and ru_MO to msgcat. 2012-06-29 Harald Oehlmann * library/msgcat/msgcat.tcl: [Bug 3536888]: Locale guessing of * library/msgcat/pkgIndex.tcl: msgcat fails on (some) Windows 7. Bump * unix/Makefile.in: to 1.4.5 * win/Makefile.in: 2012-06-29 Donal K. Fellows * doc/GetIndex.3: Reinforced the description of the requirement for the tables of names to index over to be static, following posting to tcl-core by Brian Griffin about a bug caused by Tktreectrl not obeying this rule correctly. This does not represent a functionality change, merely a clearer documentation of a long-standing constraint. 2012-06-26 Jan Nijtmans * unix/tcl.m4: Let Cygwin shared build link with * unix/configure.in: zlib1.dll, not cygz.dll (two less * unix/configure: dependencies on cygwin-specific dll's) * unix/Makefile.in: 2012-06-26 Reinhard Max * generic/tclIOSock.c: Use EAI_SYSTEM only if it exists. * unix/tclUnixSock.c: 2012-06-25 Don Porter * generic/tclFileSystem.h: [Bug 3024359]: Make sure that the * generic/tclIOUtil.c: per-thread cache of the list of file systems * generic/tclPathObj.c: currently registered is only updated at times when no active loops are traversing it. Also reduce the amount of epoch storing and checking to where it can make a difference. 2012-06-25 Donal K. Fellows * generic/tclCmdAH.c (EncodingDirsObjCmd): [Bug 3537605]: Do the right thing when reporting errors with the number of arguments. 2012-06-25 Jan Nijtmans * generic/tclfileName.c: [Patch 1536227]: Cygwin network pathname * tests/fileName.test: support. 2012-06-23 Jan Nijtmans * unix/tclUnixNotfy.c: [Bug 3508771]: Cygwin notifier for handling win32 events. 2012-06-22 Reinhard Max * generic/tclIOSock.c: Rework the error message generation of [socket], * unix/tclUnixSock.c: so that the error code of getaddrinfo is used * win/tclWinSock.c: instead of errno unless it is EAI_SYSTEM. 2012-06-21 Jan Nijtmans * win/tclWinReg.c: [Bug 3362446]: registry keys command fails * tests/registry.test: with 8.5/8.6 2012-06-11 Don Porter * generic/tclBasic.c: [Bug 3532959]: Make sure the lifetime * generic/tclProc.c: management of entries in the linePBodyPtr * tests/proc.test: hash table can tolerate either order of teardown, interp first, or Proc first. 2012-06-08 Don Porter * unix/configure.in: Update autogoo for gettimeofday(). * unix/tclUnixPort.h: Thanks Joe English. * unix/configure: autoconf 2.13 * unix/tclUnixPort.h: [Bug 3530533]: Centralize #include * unix/tclUnixThrd.c: in the tclUnixPort.h header so that old unix systems that need inclusion in all compilation units are supported. 2012-06-08 Jan Nijtmans * win/tclWinDde.c: Revise the "null data" check: null strings are possible, but empty binary arrays are not. * tests/winDde.test: Add test-case (winDde-9.4) for transferring null-strings with dde. Convert tests to tcltest-2 syntax. 2012-06-06 Donal K. Fellows * generic/tclZlib.c (TclZlibInit): Declare that Tcl is publishing the zlib package (version 2.0) as part of its bootstrap process. This will have an impact on tclkit (which includes zlib 1.1) but otherwise be very low impact. 2012-06-06 Jan Nijtmans * unix/tclUnixInit.c: On Cygwin, use win32 API in stead of uname() to determine the tcl_platform variables. 2012-05-31 Jan Nijtmans * generic/tclZlib.c: [Bug 3530536]: zlib-7.4 fails on IRIX64 * tests/zlib.test: * doc/zlib.n: Document that [stream checksum] doesn't do what's expected for "inflate" and "deflate" formats 2012-05-31 Donal K. Fellows * library/safe.tcl (safe::AliasFileSubcommand): Don't assume that slaves have corresponding commands, as that is not true for sub-subinterpreters (used in Tk's test suite). * doc/safe.n: [Bug 1997845]: Corrected formatting so that generated HTML can link properly. * tests/socket.test (socket*-13.1): Prevented intermittent test failure due to race condition. 2012-05-29 Donal K. Fellows * doc/expr.n, doc/mathop.n: [Bug 2931407]: Clarified semantics of division and remainder operators. 2012-05-29 Jan Nijtmans * win/tclWinDde.c: [Bug 3525762]: Encoding handling in dde. * win/Makefile.in: Fix "make genstubs" when cross-compiling on UNIX 2012-05-28 Donal K. Fellows * library/safe.tcl (safe::AliasFileSubcommand): [Bug 3529949]: Made a more sophisticated method for preventing information leakage; it changes references to "~user" into "./~user", which is safe. 2012-05-25 Donal K. Fellows * doc/namespace.n, doc/Ensemble.3: [Bug 3528418]: Document what is going on with respect to qualification of command prefixes in ensemble subcommand maps. * generic/tclIO.h (SYNTHETIC_EVENT_TIME): Factored out the definition of the amount of time that should be waited before firing a synthetic event on a channel. 2012-05-25 Jan Nijtmans * win/tclWinDde.c: [Bug 473946]: Special characters were not correctly sent, now for XTYP_EXECUTE as well as XTYP_REQUEST. * win/Makefile.in: Fix "make genstubs" when cross-compiling on UNIX 2012-05-24 Jan Nijtmans * tools/genStubs.tcl: Take cygwin handling of X11 into account. * generic/tcl*Decls.h: re-generated * generic/tclStubInit.c: Implement TclpIsAtty, Cygwin only. * doc/dde.n: Doc fix: "dde execute iexplore" doesn't work without -async, because iexplore doesn't return a value 2012-05-24 Jan Nijtmans * tools/genStubs.tcl: Let cygwin share stub table with win32 * win/tclWinSock.c: implement TclpInetNtoa for win32 * generic/tclInt.decls: Revert most of [3caedf05df], since when we let cygwin share the win32 stub table this is no longer necessary * generic/tcl*Decls.h: re-generated * doc/dde.n: 1.3 -> 1.4 2012-05-23 Donal K. Fellows * generic/tclZlib.c (ZlibTransformInput): [Bug 3525907]: Ensure that decompressed input is flushed through the transform correctly when the input stream gets to the end. Thanks to Alexandre Ferrieux and Andreas Kupries for their work on this. 2012-05-21 Don Porter * generic/tclFileName.c: When using Tcl_SetObjLength() calls to * generic/tclPathObj.c: grow and shrink the objPtr->bytes buffer, care must be taken that the value cannot possibly become pure Unicode. Calling Tcl_AppendToObj() has the possibility of making such a conversion. Bug found while valgrinding the trunk. 2012-05-21 Jan Nijtmans IMPLEMENTATION OF TIP#106 * win/tclWinDde.c: Added encoding-related abilities to * library/dde/pkgIndex.tcl: the [dde] command. The dde package's * tests/winDde.test: version is now 1.4.0. * doc/dde.n: 2012-05-20 Donal K. Fellows * generic/tclOOBasic.c (TclOO_Class_Constructor): [Bug 2023112]: Cut the amount of hackiness in class constructors, and refactor some of the error message handling from [oo::define] to be saner in the face of odd happenings. 2012-05-17 Donal K. Fellows * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): [Bug 3106532]: Corrected resulting indexes from -indexvar option to be usable with [string range]; this was always the intention (and is consistent with [regexp -indices] too). ***POTENTIAL INCOMPATIBILITY*** Uses of [switch -regexp -indexvar] that previously compensated for the wrong offsets (by subtracting 1 from the end indices) now do not need to do so as the value is correct. * library/safe.tcl (safe::InterpInit): Ensure that the module path is constructed in the correct order. (safe::AliasGlob): [Bug 2964715]: More extensive handling of what globbing is required to support package loading. * doc/expr.n: [Bug 3525462]: Corrected statement about what happens when comparing "0y" and "0x12"; the previously documented behavior was actually a subtle bug (now long-corrected). 2012-05-16 Donal K. Fellows * generic/tclCmdAH.c (TclMakeFileCommandSafe): [Bug 3445787]: Improve the compatibility of safe interpreters' version of 'file' with that of unsafe interpreters. * library/safe.tcl (::safe::InterpInit): Teach the safe-interp scripts about how to expose 'file' properly. 2012-05-13 Jan Nijtmans * win/tclWinDde.c: Protect against receiving strings without ending \0, as external applications (or Tcl with TIP #106) could generate that. 2012-05-10 Jan Nijtmans * win/tclWinDde.c: [Bug 473946]: Special characters not correctly sent * library/dde/pkgIndex.tcl: Increase version to 1.3.3 2012-05-10 Alexandre Ferrieux * {win,unix}/configure{,.in}: [Bug 2812981]: Clean up bundled packages' build directory from within Tcl's ./configure, to avoid stale configuration. 2012-05-09 Andreas Kupries * generic/tclIORChan.c: [Bug 3522560]: Fixed the crash, enabled the test case. Modified [chan postevent] to properly inject the event(s) into the owner thread's event queue for execution in the correct context. Renamed the ForwardOpTo...Thread() function to match with our terminology. * tests/ioCmd.test: [Bug 3522560]: Added a test which crashes the core if it were not disabled as knownBug. For a reflected channel transfered to a different thread the [chan postevent] run in the handler thread tries to execute the owner threads's fileevent scripts by itself, wrongly reaching across thread boundaries. 2012-04-28 Alexandre Ferrieux * generic/tclIO.c: Properly close nonblocking channels even when not flushing them. 2012-05-03 Jan Nijtmans * compat/zlib/*: Upgrade to zlib 1.2.7 (pre-built dll is still 1.2.5, will be upgraded as soon as the official build is available) 2012-05-03 Don Porter * tests/socket.test: [Bug 3428754]: Test socket-14.2 tolerate [socket -async] connection that connects synchronously. * unix/tclUnixSock.c: [Bug 3428753]: Fix [socket -async] connections that manage to connect synchronously. 2012-05-02 Jan Nijtmans * generic/configure.in: Better detection and implementation for * generic/configure: cpuid instruction on Intel-derived * generic/tclUnixCompat.c: processors, both 32-bit and 64-bit. * generic/tclTest.c: Move cpuid testcase from win-specific to * win/tclWinTest.c: generic tests, as it should work on all * tests/platform.test: Intel-related platforms now. 2012-04-30 Alexandre Ferrieux * tests/ioCmd.test: [Bug 3522560]: Tame deadlocks in broken refchan tests. 2012-04-28 Alexandre Ferrieux IMPLEMENTATION OF TIP#398 * generic/tclIO.c: Quickly Exit with Non-Blocking Blocked Channels * tests/io.test : *** POTENTIAL INCOMPATIBILITY *** * doc/close.n : (compat flag available) 2012-04-27 Jan Nijtmans * generic/tclPort.h: Move CYGWIN-specific stuff from tclPort.h to * generic/tclEnv.c: tclUnixPort.h, where it belongs. * unix/tclUnixPort.h: * unix/tclUnixFile.c: 2012-04-27 Donal K. Fellows * library/init.tcl (auto_execok): Allow shell builtins to be detected even if they are upper-cased. 2012-04-26 Jan Nijtmans * generic/tclStubInit.c: Get rid of _ANSI_ARGS_ and CONST * generic/tclIO.c: * generic/tclIOCmd.c: * generic/tclTest.c: * unix/tclUnixChan.c: 2012-04-25 Donal K. Fellows * generic/tclUtil.c (TclDStringToObj): Added internal function to make the fairly-common operation of converting a DString into an Obj a more efficient one; for long strings, it can just transfer the ownership of the buffer directly. Replaces this: obj=Tcl_NewStringObj(Tcl_DStringValue(&ds),Tcl_DStringLength(&ds)); Tcl_DStringFree(&ds); with this: obj=TclDStringToObj(&ds); 2012-04-24 Jan Nijtmans * generic/tclInt.decls: [Bug 3508771]: load tclreg.dll in cygwin tclsh * generic/tclIntPlatDecls.h: Implement TclWinGetSockOpt, * generic/tclStubInit.c: TclWinGetServByName and TclWinCPUID for * generic/tclUnixCompat.c: Cygwin. * unix/configure.in: * unix/configure: * unix/tclUnixCompat.c: 2012-04-18 Kevin B. Kenny * library/tzdata/Africa/Casablanca: * library/tzdata/America/Port-au-Prince: * library/tzdata/Asia/Damascus: * library/tzdata/Asia/Gaza: * library/tzdata/Asia/Hebron: tzdata2012c 2012-04-16 Donal K. Fellows * doc/FileSystem.3 (Tcl_FSOpenFileChannelProc): [Bug 3518244]: Fixed documentation of this filesystem callback function; it must not register its created channel - that's the responsibility of the caller of Tcl_FSOpenFileChannel - as that leads to reference leaks. 2012-04-15 Donal K. Fellows * generic/tclEnsemble.c (NsEnsembleImplementationCmdNR): * generic/tclIOUtil.c (Tcl_FSEvalFileEx): Cut out levels of the C stack by going direct to the relevant internal evaluation function. * generic/tclZlib.c (ZlibTransformSetOption): [Bug 3517696]: Make flushing work correctly in a pushed compressing channel transform. 2012-04-12 Jan Nijtmans * generic/tclInt.decls: [Bug 3514475]: Remove TclpGetTimeZone and * generic/tclIntDecls.h: TclpGetTZName * generic/tclIntPlatDecls.h: * generic/tclStubInit.c: * unix/tclUnixTime.c: * unix/tclWinTilemc: 2012-04-11 Jan Nijtmans * win/tclWinInit.c: [Bug 3448512]: clock scan "1958-01-01" fails * win/tcl.m4: only in debug compilation. * win/configure: * unix/tcl.m4: Use NDEBUG consistantly meaning: no debugging. * unix/configure: * generic/tclBasic.c: * library/dde/pkgIndex.tcl: Use [::tcl::pkgconfig get debug] instead * library/reg/pkgIndex.tcl: of [info exists ::tcl_platform(debug)] 2012-04-10 Donal K. Fellows * generic/tcl.h (TCL_DEPRECATED_API): [Bug 2458976]: Added macro that can be used to mark parts of Tcl's API as deprecated. Currently only used for fields of Tcl_Interp, which TIPs 330 and 336 have deprecated with a migration strategy; we want to encourage people to move away from those fields. 2012-04-09 Donal K. Fellows * generic/tclOODefineCmds.c (ClassVarsSet, ObjVarsSet): [Bug 3396896]: Ensure that the lists of variable names used to drive variable resolution will never have the same name twice. * generic/tclVar.c (AppendLocals): [Bug 2712377]: Fix problem with reporting of declared variables in methods. It's really a problem with how [info vars] interacts with variable resolvers; this is just a bit of a hack so it is no longer a big problem. 2012-04-04 Donal K. Fellows * generic/tclOO.c (Tcl_NewObjectInstance, TclNRNewObjectInstance): [Bug 3514761]: Fixed bogosity with automated argument description handling when constructing an instance of a class that is itself a member of an ensemble. Thanks to Andreas Kupries for identifying that this was a problem case at all! (Tcl_CopyObjectInstance): Fix potential bleed-over of ensemble information into [oo::copy]. 2012-04-04 Jan Nijtmans * win/tclWinSock.c: [Bug 510001]: TclSockMinimumBuffers needs * generic/tclIOSock.c: platform implementation. * generic/tclInt.decls: * generic/tclIntDecls.h: * generic/tclStubInit.c: 2012-04-03 Jan Nijtmans * generic/tclStubInit.c: Remove the TclpGetTZName implementation for * generic/tclIntDecls.h: Cygwin (from 2012-04-02 commit), re-generated * generic/tclIntPlatDecls.h: 2012-04-02 Donal K. Fellows IMPLEMENTATION OF TIP#396. * generic/tclBasic.c (builtInCmds, TclNRYieldToObjCmd): Convert the formerly-unsupported yieldm and yieldTo commands into [yieldto]. 2012-04-02 Jan Nijtmans * generic/tclInt.decls: [Bug 3508771]: load tclreg.dll in cygwin tclsh * generic/tclIntPlatDecls.h: Implement TclWinGetTclInstance, * generic/tclStubInit.c: TclpGetTZName, and various more win32-specific internal functions for Cygwin, so win32 extensions using those can be loaded in the cygwin version of tclsh. 2012-03-30 Jan Nijtmans * unix/tcl.m4: [Bug 3511806]: Compiler checks too early * unix/configure.in: This change allows to build the cygwin and * unix/tclUnixPort.h: mingw32 ports of Tcl/Tk to build out-of-the-box * win/tcl.m4: using a native or cross-compiler. * win/configure.in: * win/tclWinPort.h: * win/README Document how to build win32 or win64 executables with Linux, Cygwin or Darwin. 2012-03-29 Jan Nijtmans * generic/tclCmdMZ.c (StringIsCmd): Faster mem-leak free implementation of [string is entier]. 2012-03-27 Donal K. Fellows IMPLEMENTATION OF TIP#395. * generic/tclCmdMZ.c (StringIsCmd): Implementation of the [string is entier] check. Code by Jos Decoster. 2012-03-27 Jan Nijtmans * generic/tcl.h: [Bug 3508771]: Wrong Tcl_StatBuf used on MinGW. * generic/tclFCmd.c: [Bug 2015723]: Duplicate inodes from file stat * generic/tclCmdAH.c: on windows (but now for cygwin as well). * generic/tclOODefineCmds.c: minor gcc warning * win/tclWinPort.h: Use lower numbers, preventing integer overflow. Remove the workaround for mingw-w64 [Bug 3407992]. It's long fixed. 2012-03-27 Donal K. Fellows IMPLEMENTATION OF TIP#397. * generic/tclOO.c (Tcl_CopyObjectInstance): [Bug 3474460]: Make the target object name optional when copying classes. [RFE 3485060]: Add callback method ("") so that scripted control over copying is easier. ***POTENTIAL INCOMPATIBILITY*** If you'd previously been using the "" method name, this now has a standard semantics and call interface. Only a problem if you are also using [oo::copy]. 2012-03-26 Donal K. Fellows IMPLEMENTATION OF TIP#380. * doc/define.n, doc/object.n, generic/tclOO.c, generic/tclOOBasic.c: * generic/tclOOCall.c, generic/tclOODefineCmds.c, generic/tclOOInt.h: * tests/oo.test: Switch definitions of lists of things in objects and classes to a slot-based approach, which gives a lot more flexibility and programmability at the script-level. Introduce new [::oo::Slot] class which is the implementation of these things. ***POTENTIAL INCOMPATIBILITY*** The unknown method handler now may be asked to deal with the case where no method name is provided at all. The default implementation generates a compatible error message, and any override that forces the presence of a first argument (i.e., a method name) will continue to function as at present as well, so this is a pretty small change. * generic/tclOOBasic.c (TclOO_Object_Destroy): Made it easier to do a tailcall inside a normally-invoked destructor; prevented leakage out to calling command. 2012-03-25 Jan Nijtmans * generic/tclInt.decls: [Bug 3508771]: load tclreg.dll in cygwin * generic/tclIntPlatDecls.h: tclsh. Implement TclWinConvertError, * generic/tclStubInit.c: TclWinConvertWSAError, and various more * unix/Makefile.in: win32-specific internal functions for * unix/tcl.m4: Cygwin, so win32 extensions using those * unix/configure: can be loaded in the cygwin version of * win/tclWinError.c: tclsh. 2012-03-23 Jan Nijtmans * generic/tclInt.decls: Revert some cygwin-related signature * generic/tclIntPlatDecls.h: changes from [835f8e1e9d] (2010-01-22). * win/tclWinError.c: They were an attempt to make the cygwin port compile again, but since cygwin is based on unix this serves no purpose any more. * win/tclWinSerial.c: Use EAGAIN in stead of EWOULDBLOCK, * win/tclWinSock.c: because in VS10+ the value of EWOULDBLOCK is no longer the same as EAGAIN. * unix/Makefile.in: Add tclWinError.c to the CYGWIN build. * unix/tcl.m4: * unix/configure: 2012-03-20 Jan Nijtmans * generic/tcl.decls: [Bug 3508771]: load tclreg.dll in cygwin * generic/tclInt.decls: tclsh. Implement TclWinGetPlatformId, * generic/tclIntPlatDecls.h: Tcl_WinUtfToTChar, Tcl_WinTCharToUtf (and * generic/tclPlatDecls.h: a dummy TclWinCPUID) for Cygwin, so win32 * generic/tclStubInit.c: extensions using those can be loaded in * unix/tclUnixCompat.c: the cygwin version of tclsh. 2012-03-19 Venkat Iyer * library/tzdata/America/Atikokan: Update to tzdata2012b. * library/tzdata/America/Blanc-Sablon: * library/tzdata/America/Dawson_Creek: * library/tzdata/America/Edmonton: * library/tzdata/America/Glace_Bay: * library/tzdata/America/Goose_Bay: * library/tzdata/America/Halifax: * library/tzdata/America/Havana: * library/tzdata/America/Moncton: * library/tzdata/America/Montreal: * library/tzdata/America/Nipigon: * library/tzdata/America/Rainy_River: * library/tzdata/America/Regina: * library/tzdata/America/Santiago: * library/tzdata/America/St_Johns: * library/tzdata/America/Swift_Current: * library/tzdata/America/Toronto: * library/tzdata/America/Vancouver: * library/tzdata/America/Winnipeg: * library/tzdata/Antarctica/Casey: * library/tzdata/Antarctica/Davis: * library/tzdata/Antarctica/Palmer: * library/tzdata/Asia/Yerevan: * library/tzdata/Atlantic/Stanley: * library/tzdata/Pacific/Easter: * library/tzdata/Pacific/Fakaofo: * library/tzdata/America/Creston: (new) 2012-03-19 Reinhard Max * unix/tclUnixSock.c (Tcl_OpenTcpServer): Use the values returned by getaddrinfo() for all three arguments to socket() instead of only using ai_family. Try to keep the most meaningful error while iterating over the result list, because using the last error can be misleading. 2012-03-15 Jan Nijtmans * generic/tcl.h: [Bug 3288345]: Wrong Tcl_StatBuf used on Cygwin * unix/tclUnixFile.c: * unix/tclUnixPort.h: * win/cat.c: Remove cygwin stuff no longer needed * win/tclWinFile.c: * win/tclWinPort.h: 2012-03-12 Jan Nijtmans * win/tclWinFile.c: [Bug 3388350]: mingw64 compiler warnings 2012-03-11 Donal K. Fellows * doc/*.n, doc/*.3: A number of small spelling and wording fixes. 2012-03-08 Donal K. Fellows * doc/info.n: Various minor fixes (prompted by Andreas Kupries * doc/socket.n: detecting a spelling mistake). 2012-03-07 Andreas Kupries * library/http/http.tcl: [Bug 3498327]: Generate upper-case * library/http/pkgIndex.tcl: hexadecimal output for compliance * tests/http.test: with RFC 3986. Bumped version to 2.8.4. * unix/Makefile.in: * win/Makefile.in: 2012-03-06 Jan Nijtmans * win/tclWinPort.h: Compatibility with older Visual Studio versions. 2012-03-04 Jan Nijtmans * generic/tclLoad.c: Patch from the cygwin folks * unix/tcl.m4: * unix/configure: (re-generated) 2012-03-02 Donal K. Fellows * generic/tclBinary.c (Tcl_SetByteArrayObj): [Bug 3496014]: Only zero out the memory block if it is not being immediately overwritten. (Our caller might still overwrite, but we should at least avoid known-useless work.) 2012-02-29 Jan Nijtmans * generic/tclIOUtil.c: [Bug 3466099]: BOM in Unicode * generic/tclEncoding.c: * tests/source.test: 2012-02-23 Donal K. Fellows * tests/reg.test (14.21-23): Add tests relating to Bug 1115587. Actual bug is characterised by test marked with 'knownBug'. 2012-02-17 Jan Nijtmans * generic/tclIOUtil.c: [Bug 2233954]: AIX: compile error * unix/tclUnixPort.h: 2012-02-16 Donal K. Fellows * generic/tclExecute.c (INST_LIST_RANGE_IMM): Enhance implementation so that shortening a (not multiply-referenced) list by lopping the end off with [lrange] or [lreplace] is efficient. 2012-02-15 Donal K. Fellows * generic/tclCompCmds.c (TclCompileLreplaceCmd): Added a compilation strategy for [lreplace] that tackles the cases which are equivalent to a static [lrange]. (TclCompileLrangeCmd): Add compiler for [lrange] with constant indices so we can take advantage of existing TCL_LIST_RANGE_IMM opcode. (TclCompileLindexCmd): Improve coverage of constant-index-style compliation using technique developed for [lrange] above. (TclCompileDictForCmd): [Bug 3487626]: Fix crash in compilation of [dict for] when its implementation command is used directly rather than through the ensemble. 2012-02-09 Don Porter * generic/tclStringObj.c: Converted the memcpy() calls in append operations to memmove() calls. This adds safety in the case of overlapping copies, and improves performance on some benchmarks. 2012-02-06 Don Porter * generic/tclEnsemble.c: [Bug 3485022]: TclCompileEnsemble() avoid * tests/trace.test: compile when exec traces set. 2012-02-06 Miguel Sofer * generic/tclTrace.c: [Bug 3484621]: Ensure that execution traces on * tests/trace.test: bytecoded commands bump the interp's compile epoch. 2012-02-02 Jan Nijtmans * generic/tclUniData.c: [FRQ 3464401]: Support Unicode 6.1 * generic/regc_locale.c: 2012-02-02 Don Porter * win/tclWinFile.c: [Bugs 2974459,2879351,1951574,1852572, 1661378,1613456]: Revisions to the NativeAccess() routine that queries file permissions on Windows native filesystems. Meant to fix numerous bugs where [file writable|readable|executable] "lies" about what operations are possible, especially when the file resides on a Samba share. 2012-02-01 Donal K. Fellows * doc/AddErrInfo.3: [Bug 3482614]: Documentation nit. 2012-01-30 Donal K. Fellows * generic/tclCompCmds.c (TclCompileCatchCmd): Added a more efficient bytecode generator for the case where 'catch' is used without any variable arguments; don't capture the result just to discard it. 2012-01-26 Don Porter * generic/tclCmdAH.c: [Bug 3479689]: New internal routine * generic/tclFCmd.c: TclJoinPath(). Refactor all the * generic/tclFileName.c: *Join*Path* routines to give them more * generic/tclInt.h: useful interfaces that are easier to * generic/tclPathObj.c: manage getting the refcounts right. 2012-01-26 Don Porter * generic/tclPathObj.c: [Bug 3475569]: Add checks for unshared values before calls demanding them. [Bug 3479689]: Stop memory corruption when shimmering 0-refCount value to "path" type. 2012-01-25 Donal K. Fellows * generic/tclOO.c (Tcl_CopyObjectInstance): [Bug 3474460]: When copying an object, make sure that the configuration of the variable resolver is also duplicated. 2012-01-22 Jan Nijtmans * tools/uniClass.tcl: [FRQ 3473670]: Various Unicode-related * tools/uniParse.tcl: speedups/robustness. Enhanced tools to be * generic/tclUniData.c: able to handle characters > 0xffff. Done in * generic/tclUtf.c: all branches in order to simplify merges for * generic/regc_locale.c: new Unicode versions (such as 6.1) 2012-01-22 Donal K. Fellows * generic/tclDictObj.c (DictExistsCmd): [Bug 3475264]: Ensure that errors only ever happen when insufficient arguments are supplied, and not when a path doesn't exist or a dictionary is poorly formatted (the two cases can't be easily distinguished). 2012-01-21 Jan Nijtmans * generic/tcl.h: [Bug 3474726]: Eliminate detection of struct * generic/tclWinPort.h: _stat32i64, just use _stati64 in combination * generic/tclFCmd.c: with _USE_32BIT_TIME_T, which is the same * generic/tclTest.c: then. Only keep _stat32i64 usage for cygwin, * win/configure.in: so it will not conflict with cygwin's own * win/configure: struct stat. 2012-01-21 Don Porter * generic/tclCmdMZ.c: [Bug 3475667]: Prevent buffer read overflow. Thanks to "sebres" for the report and fix. 2012-01-17 Donal K. Fellows * doc/dict.n (dict with): [Bug 3474512]: Explain better what is going on when a dictionary key and the dictionary variable collide. 2012-01-13 Donal K. Fellows * library/http/http.tcl (http::Connect): [Bug 3472316]: Ensure that we only try to read the socket error exactly once. 2012-01-12 Donal K. Fellows * doc/tclvars.n: [Bug 3466506]: Document more environment variables. 2012-01-09 Jan Nijtmans * generic/tclUtf.c: [Bug 3464428]: [string is graph \u0120] was * generic/regc_locale.c: wrong. Add table for Unicode [:cntrl:] class. * tools/uniClass.tcl: Generate Unicode [:cntrl:] class table. * tests/utf.test: 2012-01-08 Kevin B. Kenny * library/clock.tcl (ReadZoneinfoFile): [Bug 3470928]: Corrected a bug * tests/clock.test (clock-56.4): where loading zoneinfo would fail if one timezone abbreviation was a proper tail of another, and zic used the same bytes of the file to represent both of them. Added a test case for the bug, using the same data that caused the observed failure "in the wild." 2011-12-30 Venkat Iyer * library/tzdata/America/Bahia: Update to Olson's tzdata2011n * library/tzdata/America/Havana: * library/tzdata/Europe/Kiev: * library/tzdata/Europe/Simferopol: * library/tzdata/Europe/Uzhgorod: * library/tzdata/Europe/Zaporozhye: * library/tzdata/Pacific/Fiji: 2011-12-23 Jan Nijtmans * generic/tclUtf.c: [Bug 3464428]: [string is graph \u0120] is wrong. * generic/tclUniData.c: * generic/regc_locale.c: * tests/utf.test: * tools/uniParse.tcl: Clean up some unused stuff, and be more robust against changes in UnicodeData.txt syntax 2011-12-13 Andreas Kupries * generic/tclCompile.c (TclInitAuxDataTypeTable): Extended to register the DictUpdateInfo structure as an AuxData type. For use by tbcload, tclcompiler. 2011-12-11 Jan Nijtmans * generic/regc_locale.c: [Bug 3457031]: Some Unicode 6.0 chars not * tests/utf.test: in [:print:] class 2011-12-07 Jan Nijtmans * tools/uniParse.tcl: [Bug 3444754]: string tolower \u01c5 is wrong * generic/tclUniData.c: * tests/utf.test: 2011-11-30 Jan Nijtmans * library/tcltest/tcltest.tcl: [Bug 967195]: Make tcltest work when tclsh is compiled without using the setargv() function on mingw. 2011-11-29 Jan Nijtmans * win/Makefile.in: don't install tommath_(super)?class.h * unix/Makefile.in: don't install directories like 8.2 and 8.3 * generic/tclTomMath.h: [Bug 2991415]: move include tclInt.h from * generic/tclTomMathInt.h: tclTomMath.h to tclTomMathInt.h 2011-11-25 Donal K. Fellows * library/history.tcl (history): Simplify the dance of variable management used when chaining to the implementation command. 2011-11-22 Donal K. Fellows * generic/tclExecute.c (TclCompileObj): Simplify and de-indent the logic so that it is easier to comprehend. 2011-11-22 Jan Nijtmans * win/tclWinPort.h: [Bug 3354324]: Windows: [file mtime] sets wrong * win/tclWinFile.c: time (VS2005+ only). * generic/tclTest.c: 2011-11-20 Joe Mistachkin * tests/thread.test: Remove unnecessary [after] calls from the thread tests. Make error message matching more robust for tests that may have built-in race conditions. Test thread-7.26 must first unset all thread testing related variables. Revise results of the thread-7.28 through thread-7.31 tests to account for the fact they are canceled via a script sent to the thread asynchronously, which then impacts the error message handling. Attempt to manually drain the event queue for the main thread after joining the test thread to make sure no stray events are processed at the wrong time on the main thread. Revise all the synchronization and comparison semantics related to the thread id and error message. 2011-11-18 Joe Mistachkin * tests/thread.test: Remove all use of thread::release from the thread 7.x tests, replacing it with a script that can easily cause "stuck" threads to self-destruct for those test cases that require it. Also, make the error message handling far more robust by keeping track of every asynchronous error. 2011-11-17 Joe Mistachkin * tests/thread.test: Refactor all the remaining thread-7.x tests that were using [testthread]. Note that this test file now requires the very latest version of the Thread package to pass all tests. In addition, the thread-7.18 and thread-7.19 tests have been flagged as knownBug because they cannot pass without modifications to the [expr] command, persuant to TIP #392. 2011-11-17 Joe Mistachkin * generic/tclThreadTest.c: For [testthread cancel], avoid creating a new Tcl_Obj when the default script cancellation result is desired. 2011-11-11 Donal K. Fellows * win/tclWinConsole.c: Refactor common thread handling patterns. 2011-11-11 Alexandre Ferrieux * tests/zlib.test: [Bug 3428756]: Use nonblocking writes in single-threaded IO tests to avoid deadlocks when going beyond OS buffers. Tidy up [chan configure] flags across zlib.test. 2011-11-03 Donal K. Fellows * unix/tclUnixCompat.c (TclpGetPwNam, TclpGetPwUid, TclpGetGrNam) (TclpGetGrGid): Use the elaborate memory management scheme outlined on http://www.opengroup.org/austin/docs/austin_328.txt to handle Tcl's use of standard reentrant versions of the passwd/group access functions so that everything can work on all BSDs. Problem identified by Stuart Cassoff. 2011-10-20 Don Porter * library/http/http.tcl: Bump to version 2.8.3 * library/http/pkgIndex.tcl: * unix/Makefile.in: * win/Makefile.in: * changes: Updates toward 8.6b3 release. 2011-10-20 Donal K. Fellows * generic/tclLiteral.c (TclInvalidateCmdLiteral): [Bug 3418547]: Additional code for handling the invalidation of literals. * generic/tclBasic.c (Tcl_CreateObjCommand, Tcl_CreateCommand) (TclRenameCommand, Tcl_ExposeCommand): The four additional places that need extra care when dealing with literals. * generic/tclTest.c (TestInterpResolverCmd): Additional test machinery for interpreter resolvers. 2011-10-18 Reinhard Max * library/clock.tcl (::tcl::clock::GetSystemTimeZone): Cache the time zone only if it was detected by one of the expensive methods. Otherwise after unsetting TCL_TZ or TZ the previous value will still be used. 2011-10-15 Venkat Iyer * library/tzdata/America/Sitka: Update to Olson's tzdata2011l * library/tzdata/Pacific/Fiji: * library/tzdata/Asia/Hebron: (New) 2011-10-11 Jan Nijtmans * win/tclWinFile.c: [Bug 2935503]: Incorrect mode field returned by [file stat] command. 2011-10-09 Donal K. Fellows * generic/tclCompCmds.c (TclCompileDictWithCmd): Corrected handling of qualified names, and added spacial cases for empty bodies (used when [dict with] is just used for extracting variables). 2011-10-07 Jan Nijtmans * generic/tcl.h: Fix gcc warnings (discovered with latest * generic/tclIORChan.c: mingw, based on gcc 4.6.1) * tests/env.test: Fix env.test, when running under wine 1.3. 2011-10-06 Donal K. Fellows * generic/tclDictObj.c (TclDictWithInit, TclDictWithFinish): * generic/tclCompCmds.c (TclCompileDictWithCmd): Experimental compilation for the [dict with] subcommand, using parts factored out from the interpreted version of the command. 2011-10-05 Jan Nijtmans * win/tclWinInt.h: Remove tclWinProcs, as it is no longer * win/tclWin32Dll.c: being used. 2011-10-03 Venkat Iyer * library/tzdata/Africa/Dar_es_Salaam: Update to Olson's tzdata2011k * library/tzdata/Africa/Kampala: * library/tzdata/Africa/Nairobi: * library/tzdata/Asia/Gaza: * library/tzdata/Europe/Kaliningrad: * library/tzdata/Europe/Kiev: * library/tzdata/Europe/Minsk: * library/tzdata/Europe/Simferopol: * library/tzdata/Europe/Uzhgorod: * library/tzdata/Europe/Zaporozhye: * library/tzdata/Pacific/Apia: 2011-09-29 Donal K. Fellows * tools/tcltk-man2html.tcl, tools/tcltk-man2html-utils.tcl: More refactoring so that more of the utility code is decently out of the way. Adjusted the header-material generator so that version numbers are only included in locations where there is room. 2011-09-28 Jan Nijtmans * generic/tclOO.h: [RFE 3010352]: make all TclOO API functions * generic/tclOODecls.h: MODULE_SCOPE * generic/tclOOIntDecls.h: 2011-09-27 Donal K. Fellows * generic/tclIndexObj.c (Tcl_ParseArgsObjv): [Bug 3413857]: Corrected the memory management for the code parsing arguments when returning "large" numbers of arguments. Also unbroke the TCL_ARGV_AUTO_REST macro in passing. 2011-09-26 Donal K. Fellows * generic/tclCmdAH.c (TclMakeFileCommandSafe): [Bug 3211758]: Also make the main [file] command hidden by default in safe interpreters, because that's what existing code expects. This will reduce the amount which the code breaks, but not necessarily eliminate it... 2011-09-23 Don Porter * generic/tclIORTrans.c: More revisions to get finalization of ReflectedTransforms correct, including adopting a "dead" field as was done in tclIORChan.c. * tests/thread.test: Stop using the deprecated thread management commands of the tcltest package. The test suite ought to provide these tools for itself. They do not belong in a testing harness. 2011-09-22 Don Porter * generic/tclCmdIL.c: Revise [info frame] so that it stops creating cycles in the iPtr->cmdFramePtr stack. 2011-09-22 Donal K. Fellows * doc/re_syntax.n: [Bug 2903743]: Add more magic so that we can do at least something sane on Solaris. * tools/tcltk-man2html-utils.tcl (process-text): Teach the HTML generator how to handle this magic. 2011-09-21 Don Porter * generic/tclThreadTest.c: Revise the thread exit handling of the [testthread] command so that it properly maintains the per-process data structures even when the thread exits for reasons other than the [testthread exit] command. 2011-09-21 Alexandre Ferrieux * unix/tclIO.c: [Bug 3412487]: Now short reads are allowed in synchronous fcopy, avoid mistaking them as nonblocking ones. 2011-09-21 Andreas Kupries * generic/tclIORTrans.c (ForwardOpToOwnerThread): Fixed the missing initialization of the 'dsti' field. Reported by Don Porter, on chat. 2011-09-20 Don Porter * generic/tclIORChan.c: Re-using the "interp" field to signal a dead channel (via NULL value) interfered with conditional cleanup tasks testing for "the right interp". Added a new field "dead" to perform the dead channel signalling task so the corrupted logic is avoided. * generic/tclIORTrans.c: Revised ReflectClose() and FreeReflectedTransform() so that we stop leaking ReflectedTransforms, yet free all Tcl_Obj values in the same thread that alloced them. 2011-09-19 Don Porter * tests/ioTrans.test: Conversion from [testthread] to Thread package stops most memory leaks. * tests/thread.test: Plug most memory leaks in thread.test. Constrain the rest to be skipped during `make valgrind'. Tests using the [testthread cancel] testing command are leaky. Corrections wait for either addition of [thread::cancel] to the Thread package, or improvements to the [testthread] testing command to make leak-free versions of these tests possible. * generic/tclIORChan.c: Plug all memory leaks in ioCmd.test exposed * tests/ioCmd.test: by `make valgrind'. * unix/Makefile.in: 2011-09-16 Jan Nijtmans IMPLEMENTATION OF TIP #388 * doc/Tcl.n: * doc/re_syntax.n: * generic/regc_lex.c: * generic/regcomp.c: * generic/regcustom.h: * generic/tcl.h: * generic/tclParse.c: * tests/reg.test: * tests/utf.test: 2011-09-16 Donal K. Fellows * generic/tclProc.c (ProcWrongNumArgs): [Bugs 3400658,3408830]: Corrected the handling of procedure error messages (found by TclOO). 2011-09-16 Jan Nijtmans * generic/tcl.h: Don't change Tcl_UniChar type when * generic/regcustom.h: TCL_UTF_MAX == 4 (not supported anyway) 2011-09-16 Donal K. Fellows * generic/tclProc.c (ProcWrongNumArgs): [Bugs 3400658,3408830]: Ensemble-like rewriting of error messages is complex, and TclOO (in combination with iTcl) hits the most tricky cases. * library/http/http.tcl (http::geturl): [Bug 3391977]: Ensure that the -headers option overrides the -type option (important because -type has a default that is not always appropriate, and the header must not be duplicated). 2011-09-15 Don Porter * generic/tclCompExpr.c: [Bug 3408408]: Partial improvement by sharing as literals the computed values of constant subexpressions when we can do so without incurring the cost of string rep generation. 2011-09-13 Don Porter * generic/tclUtil.c: [Bug 3390638]: Workaround broken Solaris Studio cc optimizer. Thanks to Wolfgang S. Kechel. * generic/tclDTrace.d: [Bug 3405652]: Portability workaround for broken system DTrace support. Thanks to Dagobert Michelson. 2011-09-12 Jan Nijtmans * win/tclWinPort.h: [Bug 3407070]: tclPosixStr.c won't build with EOVERFLOW==E2BIG 2011-09-11 Don Porter * tests/thread.test: Convert [testthread] use to Thread package use in thread-6.1. Eliminates a memory leak in `make valgrind`. * tests/socket.test: [Bug 3390699]: Convert [testthread] use to Thread package use in socket_*-13.1. Eliminates a memory leak in `make valgrind`. 2011-09-09 Don Porter * tests/chanio.test: [Bug 3389733]: Convert [testthread] use to * tests/io.test: Thread package use in *io-70.1. Eliminates a memory leak in `make valgrind`. 2011-09-07 Don Porter * generic/tclCompExpr.c: [Bug 3401704]: Allow function names like * tests/parseExpr.test: influence(), nanobot(), and 99bottles() that have been parsed as missing operator syntax errors before with the form NUMBER + FUNCTION. ***POTENTIAL INCOMPATIBILITY*** 2011-09-06 Venkat Iyer * library/tzdata/America/Goose_Bay: Update to Olson's tzdata2011i * library/tzdata/America/Metlakatla: * library/tzdata/America/Resolute: * library/tzdata/America/St_Johns: * library/tzdata/Europe/Kaliningrad: * library/tzdata/Pacific/Apia: * library/tzdata/Pacific/Honolulu: * library/tzdata/Africa/Juba: (new) 2011-09-06 Jan Nijtmans * generic/tcl.h: [RFE 1711975]: Tcl_MainEx() (like Tk_MainEx()) * generic/tclDecls.h: * generic/tclMain.c: 2011-09-02 Don Porter * tests/http.test: Convert [testthread] use to Thread package use. Eliminates memory leak seen in `make valgrind`. 2011-09-01 Alexandre Ferrieux * unix/tclUnixSock.c: [Bug 3401422]: Cache script-level changes to the nonblocking flag of an async client socket in progress, and commit them on completion. 2011-09-01 Don Porter * generic/tclStrToD.c: [Bug 3402540]: Corrections to TclParseNumber() * tests/binary.test: to make it reject invalid Nan(Hex) strings. * tests/scan.test: [scan Inf %g] is portable; remove constraint. 2011-08-30 Donal K. Fellows * generic/tclInterp.c (SlaveCommandLimitCmd, SlaveTimeLimitCmd): [Bug 3398794]: Ensure that low-level conditions in the limit API are enforced at the script level through errors, not a Tcl_Panic. This means that interpreters cannot read their own limits (writing already did not work). 2011-08-30 Reinhard Max * unix/tclUnixSock.c (TcpWatchProc): [Bug 3394732]: Put back the check for server sockets. 2011-08-29 Don Porter * generic/tclIORTrans.c: Leak of ReflectedTransformMap. 2011-08-27 Don Porter * generic/tclStringObj.c: [RFE 3396731]: Revise the [string reverse] * tests/string.test: implementation to operate on the representation that comes in, avoid conversion to other reps. 2011-08-23 Don Porter * generic/tclIORChan.c: [Bug 3396948]: Leak of ReflectedChannelMap. 2011-08-19 Don Porter * generic/tclIORTrans.c: [Bugs 3393279, 3393280]: ReflectClose(.) is missing Tcl_EventuallyFree() calls at some of its exits. * generic/tclIO.c: [Bugs 3394654, 3393276]: Revise FlushChannel() to account for the possibility that the ChanWrite() call might recycle the buffer out from under us. * generic/tclIO.c: Preserve the chanPtr during FlushChannel so that channel drivers don't yank it away before we're done with it. 2011-08-19 Alexandre Ferrieux * generic/tclTest.c: [Bug 2981154]: async-4.3 segfault. * tests/async.test: [Bug 1774689]: async-4.3 sometimes fails. 2011-08-18 Alexandre Ferrieux * generic/tclIO.c: [Bug 3096275]: Sync fcopy buffers input. 2011-08-18 Jan Nijtmans * generic/tclUniData.c: [Bug 3393714]: Overflow in toupper delta * tools/uniParse.tcl: * tests/utf.test: 2011-08-17 Alexandre Ferrieux * generic/tclIO.c: [Bug 2946474]: Consistently resume backgrounded * tests/ioCmd.test: flushes+closes when exiting. 2011-08-17 Alexandre Ferrieux * doc/interp.n: Document TIP 378's one-way-ness. 2011-08-17 Don Porter * generic/tclGet.c: [Bug 3393150]: Overlooked free of intreps. (It matters for bignums!) 2011-08-16 Don Porter * generic/tclCompile.c: [Bug 3392070]: More complete prevention of Tcl_Obj reference cycles when producing an intrep of ByteCode. 2011-08-16 Donal K. Fellows * generic/tclListObj.c (TclLindexList, TclLsetFlat): Silence warnings about (unreachable) cases of uninitialized variables. * generic/tclCmdIL.c (SelectObjFromSublist): Improve the generation of * generic/tclIndexObj.c (Tcl_ParseArgsObjv): messages through the use * generic/tclVar.c (ArrayStartSearchCmd): of Tcl_ObjPrintf. 2011-08-15 Don Porter * generic/tclBasic.c: [Bug 3390272]: Leak of [info script] value. 2011-08-15 Jan Nijtmans * generic/tclPosixStr.c: [Bug 3388350]: mingw64 compiler warnings * win/tclWinPort.h: * win/configure.in: * win/configure: 2011-08-14 Jan Nijtmans * doc/FindExec.3: [Patch 3124554]: Move WishPanic from Tk to Tcl * doc/Panic.3 Added Documentation 2011-08-12 Don Porter * generic/tclPathObj.c: [Bug 3389764]: Eliminate possibility that dup of a "path" value can create reference cycle. 2011-08-12 Donal K. Fellows * generic/tclZlib.c (ZlibTransformOutput): [Bug 3390073]: Return the correct length of written data for a compressing transform. 2011-08-10 Alexandre Ferrieux * generic/tclTestObj.c: [Bug 3386721]: Allow multiple [load]ing of the Tcltest package. 2011-08-09 Alexandre Ferrieux * generic/tclBasic.c: [Bug 2919042]: Restore "valgrindability" of Tcl * generic/tclEvent.c: that was lost by the streamlining of [exit], by * generic/tclExecute.c: conditionally forcing a full Finalize: * generic/tclInt.h: use -DPURIFY or ::env(TCL_FINALIZE_ON_EXIT) 2011-08-09 Alexandre Ferrieux * generic/tclCompCmds.c: [Bug 3386417]: Avoid a reference loop between * generic/tclInt.h: the bytecode and its companion errostack * generic/tclResult.c: when compiling a syntax error. 2011-08-09 Jan Nijtmans * win/tclWinConsole.c: [Bug 3388350]: mingw64 compiler warnings * win/tclWinDde.c: * win/tclWinPipe.c: * win/tclWinSerial.c: 2011-08-09 Jan Nijtmans * generic/tclInt.h: Change the signature of TclParseHex(), such that * generic/tclParse.c: it can now parse up to 8 hex characters. 2011-08-08 Donal K. Fellows * generic/tclZlib.c (ZlibStreamCmd): Make the -buffersize option to '$zstream add' function correctly instead of having its value just be discarded unceremoniously. Also generate error codes from more of the code, not just the low-level code but also the Tcl infrastructure. 2011-08-07 Donal K. Fellows * generic/tclOOInfo.c (InfoClassCallCmd): [Bug 3387082]: Plug memory leak in call chain introspection. 2011-08-06 Kevin B, Kenny * generic/tclAssemnbly.c: [Bug 3384840]: Plug another memory leak. * generic/tclStrToD.c: [Bug 3386975]: Plug another memory leak. 2011-08-05 Kevin B. Kenny * generic/tclStrToD.c: [Bug 3386975]: Plugged a memory leak in double->string conversion. 2011-08-05 Don Porter *** 8.6b2 TAGGED FOR RELEASE *** * changes: Updates for 8.6b2 release. 2011-08-05 Donal K. Fellows * generic/tclAssembly.c (AssembleOneLine): Ensure that memory isn't leaked when an unknown instruction is encountered. Also simplify code through use of Tcl_ObjPrintf in error message generation. * generic/tclZlib.c (ZlibTransformClose): [Bug 3386197]: Plug a memory leak found by Miguel with valgrind, and ensure that the correct direction's buffers are released. 2011-08-04 Miguel Sofer * generic/tclVar.c (TclPtrSetVar): Fix valgrind-detected error when newValuePtr is the interp's result obj. 2011-08-04 Donal K. Fellows * generic/tclAssembly.c (FreeAssemblyEnv): [Bug 3384840]: Plug another possible memory leak due to over-complex code for freeing the table of labels. 2011-08-04 Reinhard Max * generic/tclIOSock.c (TclCreateSocketAddress): Don't bother using AI_ADDRCONFIG for now, as it was causing problems in various situations. 2011-08-04 Donal K. Fellows * generic/tclAssembly.c (AssembleOneLine, GetBooleanOperand) (GetIntegerOperand, GetListIndexOperand, FindLocalVar): [Bug 3384840]: A Tcl_Obj is allocated by GetNextOperand, so callers of it must not hold a reference to one in the 'out' parameter when calling it. This was causing a great many memory leaks. * tests/assemble.test (assemble-51.*): Added group of memory leak tests. 2011-08-02 Don Porter * changes: Updates for 8.6b2 release. * tools/tcltk-man2html.tcl: Variable substitution botch. 2011-08-02 Donal K. Fellows * generic/tclObj.c (Tcl_DbIncrRefCount, Tcl_DbDecrRefCount) (Tcl_DbIsShared): [Bug 3384007]: Fix the panic messages so they share what should be shared and have the right number of spaces. 2011-08-01 Miguel Sofer * generic/tclProc.c (TclProcCompileProc): [Bug 3383616]: Fix for leak of resolveInfo when recompiling procs. Thanks go to Gustaf Neumann for detecting the bug and providing the fix. 2011-08-01 Donal K. Fellows * doc/tclvars.n (EXAMPLES): Added some examples of how some of the standard global variables can be used, following prompting by a request by Robert Hicks. * tools/tcltk-man2html.tcl (plus-pkgs): [Bug 3382474]: Added code to determine the version number of contributed packages from their directory names so that HTML documentation builds are less confusing. 2011-07-29 Donal K. Fellows * tools/tcltk-man2html.tcl (ensemble_commands, remap_link_target): Small enhancements to improve cross-linking with contributed packages. * tools/tcltk-man2html-utils.tcl (insert-cross-references): Enhance to cope with contributed packages' C API. 2011-07-28 Reinhard Max * unix/tcl.m4 (SC_TCL_IPV6): Fix AC_DEFINE invocation for NEED_FAKE_RFC2553. * unix/configure: autoconf-2.59 2011-07-28 Don Porter * changes: Updates for 8.6b2 release. * library/tzdata/Asia/Anadyr: Update to Olson's tzdata2011h * library/tzdata/Asia/Irkutsk: * library/tzdata/Asia/Kamchatka: * library/tzdata/Asia/Krasnoyarsk: * library/tzdata/Asia/Magadan: * library/tzdata/Asia/Novokuznetsk: * library/tzdata/Asia/Novosibirsk: * library/tzdata/Asia/Omsk: * library/tzdata/Asia/Sakhalin: * library/tzdata/Asia/Vladivostok: * library/tzdata/Asia/Yakutsk: * library/tzdata/Asia/Yekaterinburg: * library/tzdata/Europe/Kaliningrad: * library/tzdata/Europe/Moscow: * library/tzdata/Europe/Samara: * library/tzdata/Europe/Volgograd: * library/tzdata/America/Kralendijk: (new) * library/tzdata/America/Lower_Princes: (new) 2011-07-26 Donal K. Fellows * generic/tclOO.c (initScript): Ensure that TclOO is properly found by all the various package mechanisms (by adding a dummy ifneeded script) and not just some of them. 2011-07-21 Jan Nijtmans * win/tclWinPort.h: [Bug 3372130]: Fix hypot math function with MSVC10 2011-07-19 Don Porter * generic/tclUtil.c: [Bug 3371644]: Repair failure to properly handle * tests/util.test: (length == -1) scanning in TclConvertElement(). Thanks to Thomas Sader and Alexandre Ferrieux. 2011-07-19 Donal K. Fellows * doc/*.3, doc/*.n: Many small fixes to documentation as part of project to improve quality of generated HTML docs. * tools/tcltk-man2html.tcl (remap_link_target): More complete set of definitions of link targets, especially for major C API types. * tools/tcltk-man2html-utils.tcl (output-IP-list, cross-reference): Update to generation to produce proper HTML bulleted and enumerated lists. 2011-07-19 Alexandre Ferrieux * doc/upvar.n: Undocument long gone limitation of [upvar]. 2011-07-18 Don Porter * generic/tcl.h: Bump version number to 8.6b2. * library/init.tcl: * unix/configure.in: * win/configure.in: * unix/tcl.spec: * tools/tcl.wse.in: * README: * unix/configure: autoconf-2.59 * win/configure: 2011-07-15 Don Porter * generic/tclCompile.c: Avoid segfaults when RecordByteCodeStats() is called in a deleted interp. * generic/tclCompile.c: [Bug 467523, 3357771]: Prevent circular references in values with ByteCode intreps. They can lead to memory leaks. 2011-07-14 Donal K. Fellows * generic/tclOOCall.c (TclOORenderCallChain): [Bug 3365156]: Remove stray refcount bump that caused a memory leak. 2011-07-12 Don Porter * generic/tclUnixSock.c: [Bug 3364777]: Stop segfault caused by reading from struct after it had been freed. 2011-07-11 Joe Mistachkin * generic/tclExecute.c: [Bug 3339502]: Correct cast for CURR_DEPTH to silence compiler warning. 2011-07-08 Donal K. Fellows * doc/http.n: [FRQ 3358415]: State what RFC defines HTTP/1.1. 2011-07-07 Miguel Sofer * generic/tclBasic.c: Add missing INT2PTR 2011-07-03 Donal K. Fellows * doc/FileSystem.3: Corrected statements about ctime field of 'struct stat'; that was always the time of the last metadata change, not the time of creation. 2011-07-02 Kevin B. Kenny * generic/tclStrToD.c: * generic/tclTomMath.decls: * generic/tclTomMathDecls.h: * macosx/Tcl.xcode/project.pbxproj: * macosx/Tcl.xcodeproj/project.pbxproj: * tests/util.test: * unix/Makefile.in: * win/Makefile.in: * win/Makefile.vc: [Bug 3349507]: Fix a bug where bignum->double conversion is "round up" and not "round to nearest" (causing expr double(1[string repeat 0 23]) not to be 1e+23). 2011-06-28 Reinhard Max * unix/tclUnixSock.c (CreateClientSocket): [Bug 3325339]: Fix and simplify posting of the writable fileevent at the end of an asynchronous connection attempt. Improve comments for some of the trickery around [socket -async]. * tests/socket.test: Adjust tests to the async code changes. Add more tests for corner cases of async sockets. 2011-06-22 Andreas Kupries * library/platform/pkgIndex.tcl: Updated to platform 1.0.10. Added * library/platform/platform.tcl: handling of the DEB_HOST_MULTIARCH * unix/Makefile.in: location change for libc. * win/Makefile.in: * generic/tclInt.h: Fixed the inadvertently committed disabling of stack checks, see my 2010-11-15 commit. 2011-06-22 Reinhard Max Merge from rmax-ipv6-branch: * unix/tclUnixSock.c: Fix [socket -async], so that all addresses returned by getaddrinfo() are tried, not just the first one. This requires the event loop to be running while the async connection is in progress. ***POTENTIAL INCOMPATIBILITY*** * tests/socket.test: Add a test for the above. * doc/socket: Document the fact that -async needs the event loop * generic/tclIOSock.c: AI_ADDRCONFIG is broken on HP-UX 2011-06-21 Don Porter * generic/tclLink.c: [Bug 3317466]: Prevent multiple links to a single Tcl variable when calling Tcl_LinkVar(). 2011-06-13 Don Porter * generic/tclStrToD.c: [Bug 3315098]: Mem leak fix from Gustaf Neumann. 2011-06-08 Andreas Kupries * generic/tclExecute.c: Reverted the fix for [Bug 3274728] committed on 2011-04-06 and replaced with one which is 64bit-safe. The existing fix crashed tclsh on Windows 64bit. 2011-06-08 Donal K. Fellows * tests/fileSystem.test: Reduce the amount of use of duplication of complex code to perform common tests, and convert others to do the test result check directly using Tcltest's own primitives. 2011-06-06 Jan Nijtmans * tests/socket.test: Add test constraint, so 6.2 and 6.3 don't fail when the machine does not have support for ip6. Follow-up to checkin from 2011-05-11 by rmax. 2011-06-02 Don Porter * generic/tclBasic.c: Removed TclCleanupLiteralTable(), and old * generic/tclInt.h: band-aid routine put in place while a fix for * generic/tclLiteral.c: [Bug 994838] took shape. No longer needed. 2011-06-02 Donal K. Fellows * generic/tclInt.h (TclInvalidateNsCmdLookup): [Bug 3185407]: Extend the set of epochs that are potentially bumped when a command is created, for a slight performance drop (in some circumstances) and improved semantics. 2011-06-01 Miguel Sofer * generic/tclBasic.c: Using the two free data elements in NRCommand to store objc and objv - useful for debugging. 2011-06-01 Jan Nijtmans * generic/tclUtil.c: Fix for [Bug 3309871]: Valgrind finds: invalid read in TclMaxListLength(). 2011-05-31 Don Porter * generic/tclInt.h: Use a complete growth algorithm for lists so * generic/tclListObj.c: that length limits do not overconstrain by a * generic/tclStringObj.c: factor of 2. [Bug 3293874]: Fix includes * generic/tclUtil.c: rooting all growth routines by default on a common tunable parameter TCL_MIN_GROWTH. 2011-05-25 Don Porter * library/msgcat/msgcat.tcl: Bump to msgcat 1.4.4. * library/msgcat/pkgIndex.tcl: * unix/Makefile.in: * win/Makefile.in: 2011-05-25 Donal K. Fellows * generic/tclOO.h (TCLOO_VERSION): Bump version. IMPLEMENTATION OF TIP#381. * doc/next.n, doc/ooInfo.n, doc/self.n, generic/tclOO.c, * generic/tclOOBasic.c, generic/tclOOCall.c, generic/tclOOInfo.c, * generic/tclOOInt.h, tests/oo.test, tests/ooNext2.test: Added introspection of call chains ([self call], [info object call], [info class call]) and ability to skip ahead in chain ([nextto]). 2011-05-24 Venkat Iyer * library/tzdata/Africa/Cairo: Update to Olson tzdata2011g 2011-05-24 Donal K. Fellows * library/msgcat/msgcat.tcl (msgcat::mcset, msgcat::mcmset): Remove some useless code; [dict set] builds dictionary levels for us. 2011-05-17 Andreas Kupries * generic/tclCompile.c (TclFixupForwardJump): Tracked down and fixed * generic/tclBasic.c (TclArgumentBCEnter): the cause of a violation of my assertion that 'ePtr->nline == objc' in TclArgumentBCEnter. When a bytecode was grown during jump fixup the pc -> command line mapping was not updated. When things aligned just wrong the mapping would direct command A to the data for command B, with a different number of arguments. 2011-05-11 Reinhard Max * unix/tclUnixSock.c (TcpWatchProc): No need to check for server sockets here, as the generic server code already takes care of that. * tests/socket.test (accept): Add tests to make sure that this remains so. 2011-05-10 Don Porter * generic/tclInt.h: New internal routines TclScanElement() and * generic/tclUtil.c: TclConvertElement() are rewritten guts of machinery to produce string rep of lists. The new routines avoid and correct [Bug 3173086]. See comments for much more detail. * generic/tclDictObj.c: Update all callers. * generic/tclIndexObj.c: * generic/tclListObj.c: * generic/tclUtil.c: * tests/list.test: 2011-05-09 Donal K. Fellows * generic/tclNamesp.c (NamespacePathCmd): Convert to use Tcl_Obj API * generic/tclPkg.c (Tcl_PackageObjCmd): for result generation in * generic/tclTimer.c (Tcl_AfterObjCmd): [after info], [namespace path] and [package versions]. 2011-05-09 Don Porter * generic/tclListObj.c: Revise empty string tests so that we avoid potentially expensive string rep generations, especially for dicts. 2011-05-07 Donal K. Fellows * generic/tclLoad.c (TclGetLoadedPackages): Convert to use Tcl_Obj API for result generation. 2011-05-07 Miguel Sofer * generic/tclInt.h: Fix USE_TCLALLOC so that it can be enabled without * unix/Makefile.in: editing the Makefile. 2011-05-05 Don Porter * generic/tclListObj.c: Stop generating string rep of dict when converting to list. Tolerate NULL interps more completely. 2011-05-03 Don Porter * generic/tclUtil.c: Tighten Tcl_SplitList(). * generic/tclListObj.c: Tighten SetListFromAny(). * generic/tclDictObj.c: Tighten SetDictFromAny(). * tests/join.test: * tests/mathop.test: 2011-05-02 Don Porter * generic/tclCmdMZ.c: Revised TclFindElement() interface. The final * generic/tclDictObj.c: argument had been bracePtr, the address of a * generic/tclListObj.c: boolean var, where the caller can be told * generic/tclParse.c: whether or not the parsed list element was * generic/tclUtil.c: enclosed in braces. In practice, no callers really care about that. What the callers really want to know is whether the list element value exists as a literal substring of the string being parsed, or whether a call to TclCopyAndCollpase() is needed to produce the list element value. Now the final argument is changed to do what callers actually need. This is a better fit for the calls in tclParse.c, where now a good deal of post-processing checking for "naked backslashes" is no longer necessary. ***POTENTIAL INCOMPATIBILITY*** For any callers calling in via the internal stubs table who really do use the final argument explicitly to check for the enclosing brace scenario. Simply looking for the braces where they must be is the revision available to those callers, and it will backport cleanly. * tests/parse.test: Tests for expanded literals quoting detection. * generic/tclCompCmdsSZ.c: New TclFindElement() is also a better fit for the [switch] compiler. * generic/tclInt.h: Replace TclCountSpaceRuns() with * generic/tclListObj.c: TclMaxListLength() which is the function we * generic/tclUtil.c: actually want. * generic/tclCompCmdsSZ.c: * generic/tclCompCmdsSZ.c: Rewrite of parts of the switch compiler to better use the powers of TclFindElement() and do less parsing on its own. 2011-04-28 Don Porter * generic/tclInt.h: New utility routines: * generic/tclParse.c: TclIsSpaceProc() and TclCountSpaceRuns() * generic/tclUtil.c: * generic/tclCmdMZ.c: Use new routines to replace calls to isspace() * generic/tclListObj.c: and their /* INTL */ risk. * generic/tclStrToD.c: * generic/tclUtf.c: * unix/tclUnixFile.c: * generic/tclStringObj.c: Improved reaction to out of memory. 2011-04-27 Don Porter * generic/tclCmdMZ.c: TclFreeIntRep() correction & cleanup. * generic/tclExecute.c: * generic/tclIndexObj.c: * generic/tclInt.h: * generic/tclListObj.c: * generic/tclNamesp.c: * generic/tclResult.c: * generic/tclStringObj.c: * generic/tclVar.c: * generic/tclListObj.c: FreeListInternalRep() cleanup. 2011-04-21 Don Porter * generic/tclInt.h: Use macro to set List intreps. * generic/tclListObj.c: * generic/tclCmdIL.c: Limits on list length were too strict. * generic/tclInt.h: Revised panics to errors where possible. * generic/tclListObj.c: * tests/lrepeat.test: * generic/tclCompile.c: Make sure SetFooFromAny routines react * generic/tclIO.c: reasonably when passed a NULL interp. * generic/tclIndexObj.c: * generic/tclListObj.c: * generic/tclNamesp.c: * generic/tclObj.c: * generic/tclProc.c: * macosx/tclMacOSXFCmd.c: 2011-04-21 Jan Nijtmans * generic/tcl.h: fix for [Bug 3288345]: Wrong Tcl_StatBuf * generic/tclInt.h: used on MinGW. Make sure that all _WIN32 * win/tclWinFile.c: compilers use exactly the same layout * win/configure.in: for Tcl_StatBuf - the one used by MSVC6 - * win/configure: in all situations. 2011-04-19 Don Porter * generic/tclConfig.c: Reduce internals access in the implementation of [::pkgconfig list]. 2011-04-18 Don Porter * generic/tclCmdIL.c: Use ListRepPtr(.) and other cleanup. * generic/tclConfig.c: * generic/tclListObj.c: * generic/tclInt.h: Define and use macros that test whether a Tcl * generic/tclBasic.c: list value is canonical. * generic/tclUtil.c: 2011-04-18 Donal K. Fellows * doc/dict.n: [Bug 3288696]: Command summary was confusingly wrong when it came to [dict filter] with a 'value' filter. 2011-04-16 Donal K. Fellows * generic/tclFCmd.c (TclFileAttrsCmd): Add comments to make this code easier to understand. Added a panic to handle the case where the VFS layer does something odd. 2011-04-13 Don Porter * generic/tclUtil.c: [Bug 3285375]: Rewrite of Tcl_Concat*() routines to prevent segfaults on buffer overflow. Build them out of existing primitives already coded to handle overflow properly. Uses the new TclTrim*() routines. * generic/tclCmdMZ.c: New internal utility routines TclTrimLeft() * generic/tclInt.h: and TclTrimRight(). Refactor the * generic/tclUtil.c: [string trim*] implementations to use them. 2011-04-13 Miguel Sofer * generic/tclVar.c: [Bug 2662380]: Fix crash caused by appending to a variable with a write trace that unsets it. 2011-04-13 Donal K. Fellows * generic/tclUtil.c (Tcl_ConcatObj): [Bug 3285375]: Make the crash less mysterious through the judicious use of a panic. Not yet properly fixed, but at least now clearer what the failure mode is. 2011-04-12 Don Porter * tests/string.test: Test for [Bug 3285472]. Not buggy in trunk. 2011-04-12 Venkat Iyer * library/tzdata/Atlantic/Stanley: Update to Olson tzdata2011f 2011-04-12 Miguel Sofer * generic/tclBasic.c: Fix for [Bug 2440625], kbk's patch 2011-04-11 Miguel Sofer * generic/tclBasic.c: * tests/coroutine.test: [Bug 3282869]: Ensure that 'coroutine eval' runs the initial command in the proper context. 2011-04-11 Jan Nijtmans * generic/tcl.h: Fix for [Bug 3281728]: Tcl sources from 2011-04-06 * unix/tcl.m4: do not build on GCC9 (RH9) * unix/configure: 2011-04-08 Jan Nijtmans * win/tclWinPort.h: Fix for [Bug 3280043]: win2k: unresolved DLL * win/configure.in: imports. * win/configure 2011-04-06 Miguel Sofer * generic/tclExecute.c (TclCompileObj): Earlier return if Tip280 gymnastics not needed. * generic/tclExecute.c: Fix for [Bug 3274728]: making *catchTop an unsigned long. 2011-04-06 Jan Nijtmans * unix/tclAppInit.c: Make symbols "main" and "Tcl_AppInit" MODULE_SCOPE: there is absolutely no reason for exporting them. * unix/tcl.m4: Don't use -fvisibility=hidden with static * unix/configure libraries (--disable-shared) 2011-04-06 Donal K. Fellows * generic/tclFCmd.c, macosx/tclMacOSXFCmd.c, unix/tclUnixChan.c, * unix/tclUnixFCmd.c, win/tclWinChan.c, win/tclWinDde.c, * win/tclWinFCmd.c, win/tclWinLoad.c, win/tclWinPipe.c, * win/tclWinReg.c, win/tclWinSerial.c, win/tclWinSock.c: More generation of error codes (most platform-specific parts not already using Tcl_PosixError). 2011-04-05 Venkat Iyer * library/tzdata/Africa/Casablanca: Update to Olson's tzdata2011e * library/tzdata/America/Santiago: * library/tzdata/Pacific/Easter: * library/tzdata/America/Metlakatla: (new) * library/tzdata/America/North_Dakota/Beulah: (new) * library/tzdata/America/Sitka: (new) 2011-04-04 Donal K. Fellows * generic/tclOO.c, generic/tclOOBasic.c, generic/tclOODefineCmds.c * generic/tclOOInfo.c, generic/tclOOMethod.c: More generation of error codes (TclOO miscellany). * generic/tclCmdAH.c, generic/tclCmdIL.c: More generation of error codes (miscellaneous commands mostly already handled). 2011-04-04 Don Porter * README: [Bug 3202030]: Updated README files, repairing broken * macosx/README:URLs and removing other bits that were clearly wrong. * unix/README: Still could use more eyeballs on the detailed build * win/README: advice on various plaforms. 2011-04-04 Donal K. Fellows * library/init.tcl (tcl::mathfunc::rmmadwiw): Disable by default to make test suite work. * generic/tclBasic.c, generic/tclStringObj.c, generic/tclTimer.c, * generic/tclTrace.c, generic/tclUtil.c: More generation of error codes ([format], [after], [trace], RE optimizer). 2011-04-04 Jan Nijtmans * generic/tclCmdAH.c: Better error-message in case of errors * generic/tclCmdIL.c: related to setting a variable. This fixes * generic/tclDictObj.c: a warning: "Why make your own error * generic/tclScan.c: message? Why?" * generic/tclTest.c: * test/error.test: * test/info.test: * test/scan.test: * unix/tclUnixThrd.h: Remove this unused header file. 2011-04-03 Donal K. Fellows * generic/tclNamesp.c, generic/tclObj.c, generic/tclPathObj.c: * generic/tclPipe.c, generic/tclPkg.c, generic/tclProc.c: * generic/tclScan.c: More generation of error codes (namespace creation, path normalization, pipeline creation, package handling, procedures, [scan] formats) 2011-04-02 Kevin B. Kenny * generic/tclStrToD.c (QuickConversion): Replaced another couple of 'double' declarations with 'volatile double' to work around misrounding issues in mingw-gcc 3.4.5. 2011-04-02 Donal K. Fellows * generic/tclInterp.c, generic/tclListObj.c, generic/tclLoad.c: More generation of errorCodes ([interp], [lset], [load], [unload]). * generic/tclEvent.c, generic/tclFileName.c: More generation of errorCode information (default [bgerror] and [glob]). 2011-04-01 Reinhard Max * library/init.tcl: TIP#131 implementation. 2011-03-31 Donal K. Fellows * generic/tclGetDate.y, generic/tclDate.c (TclClockOldscanObjCmd): More generation of errorCode information. 2011-03-28 Donal K. Fellows * generic/tclCmdMZ.c, generic/tclConfig.c, generic/tclUtil.c: More generation of errorCode information, notably when lists are mis-parsed * generic/tclCmdMZ.c (Tcl_RegexpObjCmd, Tcl_RegsubObjCmd): Use the error messages generated by the variable management code rather than creating our own. 2011-03-27 Miguel Sofer * generic/tclBasic.c (TclNREvalObjEx): fix performance issue, notably apparent in tclbench's "LIST lset foreach". Many thanks to Twylite for patiently researching the issue and explaining it to me: a missing Tcl_ResetObjResult that causes unwanted sharing of the current result Tcl_Obj. 2011-03-26 Donal K. Fellows * generic/tclNamesp.c (Tcl_Export, Tcl_Import, DoImport): More generation of errorCode information. * generic/tclCompExpr.c, generic/tclCompile.c, generic/tclExecute.c: * generic/tclListObj.c, generic/tclNamesp.c, generic/tclObj.c: * generic/tclStringObj.c, generic/tclUtil.c: Reduce the number of casts used to manage Tcl_Obj internal representations. 2011-03-24 Don Porter * generic/tcl.h (ckfree,etc.): Restored C++ usability to the memory allocation and free macros. 2011-03-24 Donal K. Fellows * generic/tclFCmd.c (TclFileAttrsCmd): Ensure that any reference to temporary index tables is squelched immediately rather than hanging around to trip us up in the future. 2011-03-23 Miguel Sofer * generic/tclObj.c: Exploit HAVE_FAST_TSD for the deletion context in TclFreeObj() 2011-03-22 Miguel Sofer * generic/tclThreadAlloc.c: Simpler initialization of Cache under HAVE_FAST_TSD, from mig-alloc-reform. 2011-03-21 Jan Nijtmans * unix/tclLoadDl.c: [Bug 3216070]: Loading extension libraries * unix/tclLoadDyld.c: from embedded Tcl applications. ***POTENTIAL INCOMPATIBILITY*** For extensions which rely on symbols from other extensions being present in the global symbol table. For an example and some discussion of workarounds, see http://stackoverflow.com/q/8330614/301832 2011-03-21 Miguel Sofer * generic/tclCkAlloc.c: * generic/tclInt.h: Remove one level of allocator indirection in non-memdebug builds, imported from mig-alloc-reform. 2011-03-20 Miguel Sofer * generic/tclThreadAlloc.c: Imported HAVE_FAST_TSD support from mig-alloc-reform. The feature has to be enabled by hand: no autoconf support has been added. It is not clear how universal a build using this will be: it also requires some loader support. 2011-03-17 Donal K. Fellows * generic/tclCompExpr.c (ParseExpr): Generate errorCode information on failure to parse expressions. 2011-03-17 Jan Nijtmans * generic/tclMain.c: [Patch 3124683]: Reorganize the platform-specific stuff in (tcl|tk)Main.c. 2011-03-16 Jan Nijtmans * generic/tclCkalloc.c: [Bug 3197864]: Pointer truncation on Win64 TCL_MEM_DEBUG builds. 2011-03-16 Don Porter * generic/tclBasic.c: Some rewrites to eliminate calls to isspace() * generic/tclParse.c: and their /* INTL */ risk. * generic/tclProc.c: 2011-03-16 Jan Nijtmans * unix/tcl.m4: Make SHLIB_LD_LIBS='${LIBS}' the default and * unix/configure: set to "" on per-platform necessary basis. Backported from TEA, but kept all original platform code which was removed from TEA. 2011-03-14 Kevin B. Kenny * tools/tclZIC.tcl (onDayOfMonth): Allow for leading zeroes in month and day so that tzdata2011d parses correctly. * library/tzdata/America/Havana: * library/tzdata/America/Juneau: * library/tzdata/America/Santiago: * library/tzdata/Europe/Istanbul: * library/tzdata/Pacific/Apia: * library/tzdata/Pacific/Easter: * library/tzdata/Pacific/Honolulu: tzdata2011d * generic/tclAssembly.c (BBEmitInstInt1): Changed parameter data types in an effort to silence a MSVC warning reported by Ashok P. Nadkarni. Unable to test, since both forms work on my machine in VC2005, 2008, 2010, in both release and debug builds. * tests/tclTest.c (TestdstringCmd): Restored MSVC buildability broken by [5574bdd262], which changed the effective return type of 'ckalloc' from 'char*' to 'void*'. 2011-03-13 Miguel Sofer * generic/tclExecute.c: remove TEBCreturn() 2011-03-12 Donal K. Fellows * generic/tcl.h (ckalloc,ckfree,ckrealloc): Moved casts into these macro so that they work with VOID* (which is a void* on all platforms which Tcl actually builds on) and unsigned int for the length parameters, removing the need for MANY casts across the rest of Tcl. Note that this is a strict source-level-only change, so size_t cannot be used (would break binary compatibility on 64-bit platforms). 2011-03-12 Jan Nijtmans * win/tclWinFile.c: [Bug 3185609]: File normalization corner case of ... broken with -DUNICODE 2011-03-11 Donal K. Fellows * tests/unixInit.test: Make better use of tcltest2. 2011-03-10 Donal K. Fellows * generic/tclBasic.c, generic/tclCompCmds.c, generic/tclEnsemble.c: * generic/tclInt.h, generic/tclNamesp.c, library/auto.tcl: * tests/interp.test, tests/namespace.test, tests/nre.test: Converted the [namespace] command into an ensemble. This has the consequence of making it vital for Tcl code that wishes to work with namespaces to _not_ delete the ::tcl namespace. ***POTENTIAL INCOMPATIBILITY*** * library/tcltest/tcltest.tcl (loadIntoSlaveInterpreter): Added this command to handle connecting tcltest to a slave interpreter. This adds in the hook (inside the tcltest namespace) that allows the tests run in the child interpreter to be reported as part of the main sequence of test results. Bumped version of tcltest to 2.3.3. * tests/init.test, tests/package.test: Adapted these test files to use the new feature. * generic/tclAlloc.c, generic/tclCmdMZ.c, generic/tclCompExpr.c: * generic/tclCompile.c, generic/tclEnv.c, generic/tclEvent.c: * generic/tclIO.c, generic/tclIOCmd.c, generic/tclIORChan.c: * generic/tclIORTrans.c, generic/tclLiteral.c, generic/tclNotify.c: * generic/tclParse.c, generic/tclStringObj.c, generic/tclUtil.c: * generic/tclZlib.c, unix/tclUnixFCmd.c, unix/tclUnixNotfy.c: * unix/tclUnixPort.h, unix/tclXtNotify.c: Formatting fixes, mainly to comments, so code better fits the style in the Engineering Manual. 2011-03-09 Donal K. Fellows * tests/incr.test: Update more of the test suite to use Tcltest 2. 2011-03-09 Don Porter * generic/tclNamesp.c: [Bug 3202171]: Tighten the detector of nested * tests/namespace.test: [namespace code] quoting that the quoted scripts function properly even in a namespace that contains a custom "namespace" command. * doc/tclvars.n: Formatting fix. Thanks to Pat Thotys. 2011-03-09 Donal K. Fellows * tests/dstring.test, tests/init.test, tests/link.test: Update more of the test suite to use Tcltest 2. 2011-03-08 Jan Nijtmans * generic/tclBasic.c: Fix gcc warnings: variable set but not used * generic/tclProc.c: * generic/tclIORChan.c: * generic/tclIORTrans.c: * generic/tclAssembly.c: Fix gcc warning: comparison between signed and unsigned integer expressions 2011-03-08 Don Porter * generic/tclInt.h: Remove TclMarkList() routine, an experimental * generic/tclUtil.c: dead-end from the 8.5 alpha days. * generic/tclResult.c (ResetObjResult): [Bug 3202905]: Correct failure to clear invalid intrep. Thanks to Colin McDonald. 2011-03-08 Donal K. Fellows * generic/tclAssembly.c, tests/assemble.test: Migrate to use a style more consistent with the rest of Tcl. 2011-03-06 Don Porter * generic/tclBasic.c: More replacements of Tcl_UtfBackslash() calls * generic/tclCompile.c: with TclParseBackslash() where possible. * generic/tclCompCmdsSZ.c: * generic/tclParse.c: * generic/tclUtil.c: * generic/tclUtil.c (TclFindElement): [Bug 3192636]: Guard escape sequence scans to not overrun the string end. 2011-03-05 Don Porter * generic/tclParse.c (TclParseBackslash): [Bug 3200987]: Correct * tests/parse.test: trunction checks in \x and \u substitutions. 2011-03-05 Miguel Sofer * generic/tclExecute.c (TclStackFree): insure that the execStack satisfies "at most one free stack after the current one" when consecutive reallocs caused the creation of intervening stacks. 2011-03-05 Kevin B. Kenny * generic/tclAssembly.c (new file): * generic/tclBasic.c (Tcl_CreateInterp): * generic/tclInt.h: * tests/assemble.test (new file): * unix/Makefile.in: * win/Makefile.in: * win/makefile.vc: Merged dogeen-assembler-branch into HEAD. Since all functional changes are in the tcl::unsupported namespace, there's no reason to sequester this code on a separate branch. 2011-03-05 Miguel Sofer * generic/tclExecute.c: Cleaner mem management for TEBCdata * generic/tclExecute.c: * tests/nre.test: Renamed BottomData to TEBCdata, so that the name refers to what it is rather than to its storage location. * generic/tclBasic.c: Renamed struct TEOV_callback to the more * generic/tclCompExpr.c: descriptive NRE_callback. * generic/tclCompile.c: * generic/tclExecute.c: * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclTest.c: 2011-03-04 Donal K. Fellows * generic/tclOOMethod.c (ProcedureMethodCompiledVarConnect) (ProcedureMethodCompiledVarDelete): [Bug 3185009]: Keep references to resolved object variables so that an unset doesn't leave any dangling pointers for code to trip over. 2011-03-01 Miguel Sofer * generic/tclBasic.c (TclNREvalObjv): Missing a variable declaration in commented out non-optimised code, left for ref in checkin [b97b771b6d] 2011-03-03 Don Porter * generic/tclResult.c (Tcl_AppendResultVA): Use the directive USE_INTERP_RESULT [TIP 330] to force compat with interp->result access, instead of the improvised hack USE_DIRECT_INTERP_RESULT_ACCESS from releases past. 2011-03-01 Miguel Sofer * generic/tclCompCmdsSZ.c (TclCompileThrowCmd, TclCompileUnsetCmd): fix leaks * generic/tclBasic.c: This is [Patch 3168398], * generic/tclCompCmdsSZ.c: Joe Mistachkin's optimisation * generic/tclExecute.c: of Tip #285 * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclInterp.c: * generic/tclOODecls.h: * generic/tclStubInit.c: * win/makefile.vc: * generic/tclExecute.c (ExprObjCallback): Fix object leak * generic/tclExecute.c (TEBCresume): Store local var array and constants in automatic vars to reduce indirection, slight perf increase * generic/tclOOCall.c (TclOODeleteContext): Added missing '*' so that trunk compiles. * generic/tclBasic.c (TclNRRunCallbacks): [Patch 3168229]: Don't do the trampoline dance for commands that do not have an nreProc. 2011-03-01 Donal K. Fellows * generic/tclOO.c (Tcl_NewObjectInstance, TclNRNewObjectInstance) (TclOOObjectCmdCore, FinalizeObjectCall): * generic/tclOOBasic.c (TclOO_Object_Destroy, AfterNRDestructor): * generic/tclOOCall.c (TclOODeleteContext, TclOOGetCallContext): Reorganization of call context reference count management so that code is (mostly) simpler. 2011-01-26 Donal K. Fellows * doc/RegExp.3: [Bug 3165108]: Corrected documentation of description of subexpression info in Tcl_RegExpInfo structure. 2011-01-25 Jan Nijtmans * generic/tclPreserve.c: Don't miss 64-bit address bits in panic message. * win/tclWinChan.c: Fix various gcc-4.5.2 64-bit warning * win/tclWinConsole.c: messages, e.g. by using full 64-bits for * win/tclWinDde.c: socket fd's * win/tclWinPipe.c: * win/tclWinReg.c: * win/tclWinSerial.c: * win/tclWinSock.c: * win/tclWinThrd.c: 2011-01-19 Jan Nijtmans * tools/genStubs.tcl: [FRQ 3159920]: Tcl_ObjPrintf() crashes with * generic/tcl.decls bad format specifier. * generic/tcl.h: * generic/tclDecls.h: 2011-01-18 Donal K. Fellows * generic/tclOOMethod.c (PushMethodCallFrame): [Bug 3001438]: Make sure that the cmdPtr field of the procPtr is correct and relevant at all times so that [info frame] can report sensible information about a frame after a return to it from a recursive call, instead of probably crashing (depending on what else has overwritten the Tcl stack!) 2011-01-18 Jan Nijtmans * generic/tclBasic.c: Various mismatches between Tcl_Panic * generic/tclCompCmds.c: format string and its arguments, * generic/tclCompCmdsSZ.c: discovered thanks to [Bug 3159920] * generic/tclCompExpr.c: * generic/tclEnsemble.c: * generic/tclPreserve.c: * generic/tclTest.c: 2011-01-17 Jan Nijtmans * generic/tclIOCmd.c: [Bug 3148192]: Commands "read/puts" incorrectly * tests/chanio.test: interpret parameters. Improved error-message * tests/io.test regarding legacy form. * tests/ioCmd.test 2011-01-15 Kevin B. Kenny * doc/tclvars.n: * generic/tclStrToD.c: * generic/tclUtil.c (Tcl_PrintDouble): * tests/util.test (util-16.*): [Bug 3157475]: Restored full Tcl 8.4 compatibility for the formatting of floating point numbers when $::tcl_precision is not zero. Added compatibility tests to make sure that excess trailing zeroes are suppressed for all eight major code paths. 2011-01-12 Jan Nijtmans * win/tclWinFile.c: Use _vsnprintf in stead of vsnprintf, because MSVC 6 doesn't have it. Reported by andreask. * win/tcl.m4: handle --enable-64bit=ia64 for gcc * win/configure.in: more accurate test for correct * win/configure: (autoconf-2.59) * win/tclWin32Dll.c: VS 2005 64-bit does not have intrin.h, and * generic/tclPanic.c: does not need it. 2011-01-07 Kevin B. Kenny * tests/util.test (util-15.*): Added test cases for floating point conversion of the largest denormal and the smallest normal number, to avoid any possibility of the failure suffered by PHP in the last couple of days. (They didn't fail, so no actual functional change.) 2011-01-05 Donal K. Fellows * tests/package.test, tests/pkg.test: Coalesce these tests into one file that is concerned with the package system. Convert to use tcltest2 properly. * tests/autoMkindex.test, tests/pkgMkIndex.test: Convert to use tcltest2 properly. 2011-01-01 Donal K. Fellows * tests/cmdAH.test, tests/cmdMZ.test, tests/compExpr.test, * tests/compile.test, tests/concat.test, tests/eval.test, * tests/fileName.test, tests/fileSystem.test, tests/interp.test, * tests/lsearch.test, tests/namespace-old.test, tests/namespace.test, * tests/oo.test, tests/proc.test, tests/security.test, * tests/switch.test, tests/unixInit.test, tests/var.test, * tests/winDde.test, tests/winPipe.test: Clean up of tests and conversion to tcltest 2. Target has been to get init and cleanup code out of the test body and into the -setup/-cleanup stanzas. * tests/execute.test (execute-11.1): [Bug 3142026]: Added test that fails (with a crash) in an unfixed memdebug build on 64-bit systems. 2010-12-31 Donal K. Fellows * generic/tclCmdIL.c (SortElement): Use unions properly in the definition of this structure so that there is no need to use nasty int/pointer type punning. Made it clearer what the purposes of the various parts of the structure are. 2010-12-31 Jan Nijtmans * unix/dltest/*.c: [Bug 3148192]: Fix broken [load] tests by ensuring that the affected files are never compiled with -DSTATIC_BUILD. 2010-12-30 Miguel Sofer * generic/tclExecute.c (GrowEvaluationStack): Off-by-one error in sizing the new allocation - was ok in comment but wrong in the code. Triggered by [Bug 3142026] which happened to require exactly one more than what was in existence. 2010-12-26 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LsortObjCmd): Fix crash when multiple -index options are used. Simplified memory handling logic. 2010-12-20 Jan Nijtmans * win/tclWin32Dll.c: [Patch 3059922]: fixes for mingw64 - gcc4.5.1 tdm64-1: completed for all environments. 2010-12-20 Jan Nijtmans * win/configure.in: Explicitely test for intrinsics support in compiler, before assuming only MSVC has it. * win/configure: (autoconf-2.59) * generic/tclPanic.c: 2010-12-19 Jan Nijtmans * win/tclWin32Dll.c: [Patch 3059922]: fixes for mingw64 - gcc4.5.1 tdm64-1: Fixed for gcc, not yet for MSVC 64-bit. 2010-12-17 Stuart Cassoff * unix/Makefile.in: Remove unwanted/obsolete 'ddd' target. 2010-12-17 Stuart Cassoff * unix/Makefile.in: Clean up '.PHONY:' targets: Arrange those common to Tcl and Tk as in Tk's Makefile.in, add any missing ones and remove duplicates. 2010-12-17 Stuart Cassoff * unix/Makefile.in: [Bug 2446711]: Remove 'allpatch' target. 2010-12-17 Stuart Cassoff * unix/Makefile.in: [Bug 2537626]: Use 'rpmbuild', not 'rpm'. 2010-12-16 Jan Nijtmans * generic/tclPanic.c: [Patch 3124554]: Move WishPanic from Tk to Tcl * win/tclWinFile.c: Better communication with debugger, if present. 2010-12-15 Kevin B. Kenny [dogeen-assembler-branch] * tclAssembly.c: * assemble.test: Reworked beginCatch/endCatch handling to enforce the more severe (but more correct) restrictions on catch handling that appeared in the discussion of [Bug 3098302] and in tcl-core traffic beginning about 2010-10-29. 2010-12-15 Jan Nijtmans * generic/tclPanic.c: Restore abort() as it was before. * win/tclWinFile.c: [Patch 3124554]: Use ExitProcess() here, like in wish. 2010-12-14 Jan Nijtmans * generic/tcl.h: [Bug 3137454]: Tcl CVS HEAD does not build on GCC 3. 2010-12-14 Reinhard Max * win/tclWinSock.c (CreateSocket): Swap the loops over * unix/tclUnixSock.c (CreateClientSocket): local and remote addresses, so that the system's address preference for the remote side decides which family gets tried first. Cleanup and clarify some of the comments. 2010-12-13 Jan Nijtmans * generic/tcl.h: [Bug 3135271]: Link error due to hidden * unix/tcl.m4: symbols (CentOS 4.2) * unix/configure: (autoconf-2.59) * win/tclWinFile.c: Undocumented feature, only meant to be used by Tk_Main. See [Patch 3124554]: Move WishPanic from Tk to Tcl 2010-12-12 Stuart Cassoff * unix/tcl.m4: Better building on OpenBSD. * unix/configure: (autoconf-2.59) 2010-12-10 Jan Nijtmans * generic/tcl.h: [Bug 3129448]: Possible over-allocation on * generic/tclCkalloc.c: 64-bit platforms, part 2 * generic/tclCompile.c: * generic/tclHash.c: * generic/tclInt.h: * generic/tclIO.h: * generic/tclProc.c: 2010-12-10 Alexandre Ferrieux * generic/tclIO.c: Make sure [fcopy -size ... -command ...] always * tests/io.test: calls the callback asynchronously, even for size zero. 2010-12-10 Jan Nijtmans * generic/tclBinary.c: Fix gcc -Wextra warning: missing initializer * generic/tclCmdAH.c: * generic/tclCmdIL.c: * generic/tclCmdMZ.c: * generic/tclDictObj.c: * generic/tclIndexObj.c: * generic/tclIOCmd.c: * generic/tclVar.c: * win/tcl.m4: Fix manifest-generation for 64-bit gcc (mingw-w64) * win/configure.in: Check for availability of intptr_t and uintptr_t * win/configure: (autoconf-2.59) * generic/tclInt.decls: Change 1st param of TclSockMinimumBuffers * generic/tclIntDecls.h: to ClientData, and TclWin(Get|Set)SockOpt * generic/tclIntPlatDecls.h:to SOCKET, because on Win64 those are * generic/tclIOSock.c: 64-bit, which does not fit. * win/tclWinSock.c: * unix/tclUnixSock.c: 2010-12-09 Donal K. Fellows * tests/fCmd.test: Improve sanity of constraints now that we don't support anything before Windows 2000. * generic/tclCmdAH.c (TclInitFileCmd, TclMakeFileCommandSafe, ...): Break up [file] into an ensemble. Note that the ensemble is safe in itself, but the majority of its subcommands are not. * generic/tclFCmd.c (FileCopyRename,TclFileDeleteCmd,TclFileAttrsCmd) (TclFileMakeDirsCmd): Adjust these subcommand implementations to work inside an ensemble. (TclFileLinkCmd, TclFileReadLinkCmd, TclFileTemporaryCmd): Move these subcommand implementations from tclCmdAH.c, where they didn't really belong. * generic/tclIOCmd.c (TclChannelNamesCmd): Move to more appropriate source file. * generic/tclEnsemble.c (TclMakeEnsemble): Start of code to make partially-safe ensembles. Currently does not function as expected due to various shortcomings in how safe interpreters are constructed. * tests/cmdAH.test, tests/fCmd.test, tests/interp.test: Test updates to take into account systematization of error messages. * tests/append.test, tests/appendComp.test: Clean up tests so that they don't leave things in the global environment (detected when doing -singleproc testing). 2010-12-07 Donal K. Fellows * tests/fCmd.test, tests/safe.test, tests/uplevel.test, * tests/upvar.test, tests/var.test: Convert more tests to tcltest2 and factor them to be easier to understand. * generic/tclStrToD.c: Tidy up code so that more #ifdef-fery is quarantined at the front of the file and function headers follow the modern Tcl style. 2010-12-06 Jan Nijtmans * generic/tclBinary.c: [Bug 3129448]: Possible over-allocation on * generic/tclCkalloc.c: 64-bit platforms. * generic/tclTrace.c: 2010-12-05 Jan Nijtmans * unix/tcl.m4: [Patch 3116490]: Cross-compile support for unix * unix/configure: (autoconf-2.59) 2010-12-03 Jeff Hobbs * generic/tclUtil.c (TclReToGlob): Add extra check for multiple inner *s that leads to poor recursive glob matching, defer to original RE instead. tclbench RE var backtrack. 2010-12-03 Jan Nijtmans * generic/tclUtil.c: Silence gcc warning when using -Wwrite-strings * generic/tclStrToD.c: Silence gcc warning for non-IEEE platforms * win/Makefile.in: [Patch 3116490]: Cross-compile Tcl mingw32 on unix * win/tcl.m4: This makes it possible to cross-compile Tcl/Tk for * win/configure.in: Windows (either 32-bit or 64-bit) out-of-the-box * win/configure: on UNIX, using mingw-w64 build tools (If Itcl, tdbc and Thread take over the latest tcl.m4, they can do that too). 2010-12-01 Kevin B. Kenny * generic/tclStrToD.c (SetPrecisionLimits, TclDoubleDigits): [Bug 3124675]: Added meaningless initialization of 'i', 'ilim' and 'ilim1' to silence warnings from the C compiler about possible use of uninitialized variables, Added a panic to the 'switch' that assigns them, to assert that the 'default' case is impossible. 2010-12-01 Jan Nijtmans * generic/tclBasic.c: Fix gcc 64-bit warnings: cast from pointer to * generic/tclHash.c: integer of different size. * generic/tclTest.c: * generic/tclThreadTest.c: * generic/tclStrToD.c: Fix gcc(-4.5.2) warning: 'static' is not at beginning of declaration. * generic/tclPanic.c: Allow Tcl_Panic() to enter the debugger on win32 * generic/tclCkalloc.c: Use Tcl_Panic() in stead of duplicating the code. 2010-11-30 Jeff Hobbs * generic/tclInt.decls, generic/tclInt.h, generic/tclIntDecls.h: * generic/tclStubInit.c: TclFormatInt restored at slot 24 * generic/tclUtil.c (TclFormatInt): restore TclFormatInt func from 2005-07-05 macro-ization. Benchmarks indicate it is faster, as a key int->string routine (e.g. int-indexed arrays). 2010-11-29 Alexandre Ferrieux * generic/tclBasic.c: Patch by Miguel, providing a [::tcl::unsupported::inject coroname command args], which prepends ("injects") arbitrary code to a suspended coro's future resumption. Neat for debugging complex coros without heavy instrumentation. 2010-11-29 Kevin B. Kenny * generic/tclInt.decls: * generic/tclInt.h: * generic/tclStrToD.c: * generic/tclTest.c: * generic/tclTomMath.decls: * generic/tclUtil.c: * tests/util.test: * unix/Makefile.in: * win/Makefile.in: * win/makefile.vc: Rewrite of Tcl_PrintDouble and TclDoubleDigits that (a) fixes a severe performance problem with floating point shimmering reported by Karl Lehenbauer, (b) allows TclDoubleDigits to generate the digit strings for 'e' and 'f' format, so that it can be used for tcl_precision != 0 (and possibly later for [format]), (c) fixes [Bug 3120139] by making TclPrintDouble inherently locale-independent, (d) adds test cases to util.test for correct rounding in difficult cases of TclDoubleDigits where fixed- precision results are requested. (e) adds test cases to util.test for the controversial aspects of [Bug 3105247]. As a side effect, two more modules from libtommath (bn_mp_set_int.c and bn_mp_init_set_int.c) are brought into the build, since the new code uses them. * generic/tclIntDecls.h: * generic/tclStubInit.c: * generic/tclTomMathDecls.h: Regenerated. 2010-11-24 Donal K. Fellows * tests/chanio.test, tests/iogt.test, tests/ioTrans.test: Convert more tests to tcltest2 and factor them to be easier to understand. 2010-11-20 Donal K. Fellows * tests/chanio.test: Converted many tests to tcltest2 by marking the setup and cleanup parts as such. 2010-11-19 Jan Nijtmans * win/tclWin32Dll.c: Fix gcc warnings: unused variable 'registration' * win/tclWinChan.c: * win/tclWinFCmd.c: 2010-11-18 Jan Nijtmans * win/tclAppInit.c: [FRQ 491789]: "setargv() doesn't support a unicode cmdline" now implemented for cygwin and mingw32 too. * tests/main.test: No longer disable tests Tcl_Main-1.4 and 1.6 on Windows, because those now work on all supported platforms. * win/configure.in: Set NO_VIZ=1 when zlib is compiled in libtcl, this resolves compiler warnings in 64-bit and static builds. * win/configure (regenerated) 2010-11-18 Donal K. Fellows * doc/file.n: [Bug 3111298]: Typofix. * tests/oo.test: [Bug 3111059]: Added testing that neatly trapped this issue. 2010-11-18 Miguel Sofer * generic/tclNamesp.c: [Bug 3111059]: Fix leak due to bad looping construct. 2010-11-17 Jan Nijtmans * win/tcl.m4: [FRQ 491789]: "setargv() doesn't support a unicode cmdline" now implemented for mingw-w64 * win/configure (re-generated) 2010-11-16 Jan Nijtmans * win/tclAppInit.c:Bring compilation under mingw-w64 a bit closer * win/cat.c: to reality. See for what's missing: * win/tcl.m4: * win/configure: (re-generated) * win/tclWinPort.h: [Bug 3110161]: Extensions using TCHAR don't compile on VS2005 SP1 2010-11-15 Andreas Kupries * doc/interp.n: [Bug 3081184]: TIP #378. * doc/tclvars.n: Performance fix for TIP #280. * generic/tclBasic.c: * generic/tclExecute.c: * generic/tclInt.h: * generic/tclInterp.c: * tests/info.test: * tests/interp.test: 2010-11-10 Andreas Kupries * changes: Updates for 8.6b2 release. 2010-11-09 Donal K. Fellows * generic/tclOOMethod.c (ProcedureMethodVarResolver): [Bug 3105999]: * tests/oo.test: Make sure that resolver structures that are only temporarily needed get squelched. 2010-11-05 Jan Nijtmans * generic/tclMain.c: Thanks, Kevin, for the fix, but this how it was supposed to be (TCL_ASCII_MAIN is only supposed to be defined on WIN32). 2010-11-05 Kevin B. Kenny * generic/tclMain.c: Added missing conditional on _WIN32 around code that messes around with the definition of _UNICODE, to correct a badly broken Unix build from Jan's last commit. 2010-11-04 Jan Nijtmans * generic/tclDecls.h: [FRQ 491789]: "setargv() doesn't support a * generic/tclMain.c: unicode cmdline" implemented for Tcl on MSVC++ * doc/Tcl_Main.3: * win/tclAppInit.c: * win/makefile.vc: * win/Makefile.in: * win/tclWin32Dll.c: Eliminate minor MSVC warning TCHAR -> char conversion 2010-11-04 Reinhard Max * tests/socket.test: Run the socket tests three times with the address family set to any, inet, and inet6 respectively. Use constraints to skip the tests if a family is found to be unsupported or not configured on the local machine. Adjust the tests to dynamically adapt to the address family that is being tested. Rework some of the tests to speed them up by avoiding (supposedly) unneeded [after]s. 2010-11-04 Stuart Cassoff * unix/Makefile.in: [Patch 3101127]: Installer Improvements. * unix/install-sh: 2010-11-04 Donal K. Fellows * tests/error.test (error-19.13): Another variation on testing for issues in [try] compilation. * doc/Tcl.n (Variable substitution): [Bug 3099086]: Increase clarity of explanation of what characters are actually permitted in variable substitutions. Note that this does not constitute a change of behavior; it is just an improvement of explanation. 2010-11-04 Don Porter * changes: Updates for 8.6b2 release. (Thanks Andreas Kupries) 2010-11-03 Jan Nijtmans * win/tclWinFcmd.c: [FRQ 2965056]: Windows build with -DUNICODE * win/tclWinFile.c: (more clean-ups for pre-win2000 stuff) * win/tclWinReg.c: 2010-11-03 Donal K. Fellows * generic/tclCmdMZ.c (TryPostBody): Ensure that errors when setting * tests/error.test (error-19.1[12]): message/opt capture variables get reflected properly to the caller. 2010-11-03 Kevin B. Kenny * generic/tclCompCmds.c (TclCompileCatchCmd): [Bug 3098302]: * tests/compile.test (compile-3.6): Reworked the compilation of the [catch] command so as to avoid placing any code that might throw an exception (specifically, any initial substitutions or any stores to result or options variables) between the BEGIN_CATCH and END_CATCH but outside the exception range. Added a test case that panics on a stack smash if the change is not made. 2010-11-01 Stuart Cassoff * library/safe.tcl: Improved handling of non-standard module path * tests/safe.test: lists, empty path lists in particular. 2010-11-01 Kevin B. Kenny * library/tzdata/Asia/Hong_Kong: * library/tzdata/Pacific/Apia: * library/tzdata/Pacific/Fiji: Olson's tzdata2010o. 2010-10-29 Alexandre Ferrieux * generic/tclTimer.c: [Bug 2905784]: Stop small [after]s from wasting CPU while keeping accuracy. 2010-10-28 Kevin B. Kenny [dogeen-assembler-branch] * generic/tclAssembly.c: * tests/assembly.test (assemble-31.*): Added jump tables. 2010-10-28 Don Porter * tests/http.test: [Bug 3097490]: Make http-4.15 pass in isolation. * unix/tclUnixSock.c: [Bug 3093120]: Prevent calls of freeaddrinfo(NULL) which can crash some systems. Thanks Larry Virden. 2010-10-26 Reinhard Max * Changelog.2008: Split off from Changelog. * generic/tclIOSock.c (TclCreateSocketAddress): The interp != NULL check is needed for ::tcl::unsupported::socketAF as well. 2010-10-26 Donal K. Fellows * unix/tclUnixSock.c (TcpGetOptionProc): Prevent crash if interp is * win/tclWinSock.c (TcpGetOptionProc): NULL (a legal situation). 2010-10-26 Reinhard Max * unix/tclUnixSock.c (TcpGetOptionProc): Added support for ::tcl::unsupported::noReverseDNS, which if set to any value, prevents [fconfigure -sockname] and [fconfigure -peername] from doing reverse DNS queries. 2010-10-24 Kevin B. Kenny [dogeen-assembler-branch] * generic/tclAssembly.c: * tests/assembly.test (assemble-17.15): Reworked branch handling so that forward branches can use jump1 (jumpTrue1, jumpFalse1). Added test cases that the forward branches will expand to jump4, jumpTrue4, jumpFalse4 when needed. 2010-10-23 Kevin B. Kenny [dogeen-assembler-branch] * generic/tclAssembly.h (removed): Removed file that was included in only one source file. * generictclAssembly.c: Inlined tclAssembly.h. 2010-10-17 Alexandre Ferrieux * doc/info.n: [Patch 2995655]: * generic/tclBasic.c: Report inner contexts in [info errorstack] * generic/tclCompCmds.c: * generic/tclCompile.c: * generic/tclCompile.h: * generic/tclExecute.c: * generic/tclInt.h: * generic/tclNamesp.c: * tests/error.test: * tests/result.test: 2010-10-20 Donal K. Fellows * generic/tclCompCmds.c (TclCompileDictForCmd): Update the compilation * generic/tclCompile.c (tclInstructionTable): of [dict for] so that * generic/tclExecute.c (TEBCresume): it no longer makes any use of INST_DICT_DONE now that's not needed, and make it clearer in the implementation of the instruction that it's just a deprecated form of unset operation. Followup to my commit of 2010-10-16. 2010-10-19 Donal K. Fellows * generic/tclZlib.c (Tcl_ZlibStreamGet): [Bug 3081008]: Ensure that when a bytearray gets its internals entangled with zlib for more than a passing moment, that bytearray will never be shimmered away. This increases the amount of copying but is simple to get right, which is a reasonable trade-off. * generic/tclStringObj.c (Tcl_AppendObjToObj): Added some special cases so that most of the time when you build up a bytearray by appending, it actually ends up being a bytearray rather than shimmering back and forth to string. * tests/http11.test (check_crc): Use a simpler way to express the functionality of this procedure. * generic/tclZlib.c: Purge code that wrote to the object returned by Tcl_GetObjResult, as we don't want to do that anti-pattern no more. 2010-10-18 Jan Nijtmans * tools/uniParse.tcl: [Bug 3085863]: tclUniData was 9 years old; Ignore non-BMP characters and fix comment about UnicodeData.txt file. * generic/regcomp.c: Fix comment * tests/utf.test: Add some Unicode 6 testcases 2010-10-17 Alexandre Ferrieux * doc/info.n: Document [info errorstack] faithfully. 2010-10-16 Donal K. Fellows * generic/tclExecute.c (ReleaseDictIterator): Factored out the release of the bytecode-level dictionary iterator information so that the side-conditions on instruction issuing are simpler. 2010-10-15 Jan Nijtmans * generic/reg_locale.c: [Bug 3085863]: tclUniData 9 years old: Updated * generic/tclUniData.c: Unicode tables to latest UnicodeData.txt, * tools/uniParse.tcl: corresponding with Unicode 6.0 (except for out-of-range chars > 0xFFFF) 2010-10-13 Don Porter * generic/tclCompile.c: Alternative fix for [Bugs 467523,983660] where * generic/tclExecute.c: sharing of empty scripts is allowed again. 2010-10-13 Jan Nijtmans * win/tclWinThrd.h: (removed) because it is just empty en used nowhere * win/tcl.dsp 2010-10-12 Jan Nijtmans * tools/uniClass.tcl: Spacing and comments: let uniClass.tcl * generic/regc_locale.c: generation match better the current (hand-modified) regc_locale.c * tools/uniParse.tcl: Generate proper const qualifiers for * generic/tclUniData.c: tclUniData.c 2010-10-12 Reinhard Max * unix/tclUnixSock.c (CreateClientSocket): [Bug 3084338]: Fix a memleak and refactor the calls to freeaddrinfo(). 2010-10-11 Jan Nijtmans * win/tclWinDde.c: [FRQ 2965056]: Windows build with -DUNICODE * win/tclWinReg.c: * win/tclWinTest.c: More cleanups * win/tclWinFile.c: Add netapi32 to the link line, so we no longer * win/tcl.m4: have to use LoadLibrary to access those functions. * win/makefile.vc: * win/configure: (Re-generate with autoconf-2.59) * win/rules.vc Update for VS10 2010-10-09 Miguel Sofer * generic/tclExecute.c: Fix overallocation of exec stack in TEBC (due to mixing numwords and numbytes) 2010-10-08 Jan Nijtmans * generic/tclIOSock.c: On Windows, use gai_strerrorA 2010-10-06 Don Porter * tests/winPipe.test: Test hygiene with makeFile and removeFile. * generic/tclCompile.c: [Bug 3081065]: Prevent writing to the intrep * tests/subst.test: fields of a freed Tcl_Obj. 2010-10-06 Kevin B. Kenny [dogeen-assembler-branch] * generic/tclAssembly.c: * generic/tclAssembly.h: * tests/assemble.test: Added catches. Still needs a lot of testing. 2010-10-02 Kevin B. Kenny [dogeen-assembler-branch] * generic/tclAssembly.c: * generic/tclAssembly.h: * tests/assemble.test: Added dictAppend, dictIncrImm, dictLappend, dictSet, dictUnset, nop, regexp, nsupvar, upvar, and variable. 2010-10-02 Donal K. Fellows * generic/tclExecute.c (TEBCresume): [Bug 3079830]: Added invalidation of string representations of dictionaries in some cases. 2010-10-01 Jeff Hobbs * generic/tclExecute.c (EvalStatsCmd): change 'evalstats' to return data to interp by default, or if given an arg, use that as filename to output to (accepts 'stdout' and 'stderr'). Fix output to print used inst count data. * generic/tclCkalloc.c: Change TclDumpMemoryInfo sig to allow objPtr * generic/tclInt.decls: as well as FILE* as output. * generic/tclIntDecls.h: 2010-10-01 Donal K. Fellows * generic/tclBasic.c, generic/tclClock.c, generic/tclEncoding.c, * generic/tclEnv.c, generic/tclLoad.c, generic/tclNamesp.c, * generic/tclObj.c, generic/tclRegexp.c, generic/tclResolve.c, * generic/tclResult.c, generic/tclUtil.c, macosx/tclMacOSXFCmd.c: More purging of strcpy() from locations where we already know the length of the data being copied. 2010-10-01 Kevin B. Kenny [dogeen-assembler-branch] * tests/assemble.test: * generic/tclAssemble.h: * generic/tclAssemble.c: Added listIn, listNotIn, and dictGet. 2010-09-30 Kevin B. Kenny [dogeen-assembler-branch] * tests/assemble.test: Added tryCvtToNumeric and several more list * generic/tclAssemble.c: operations. * generic/tclAssemble.h: 2010-09-29 Kevin B. Kenny [dogeen-assembler-branch] * tests/assemble.test: Completed conversion of tests to a * generic/tclAssemble.c: "white box" structure that follows the C code. Added missing safety checks on the operands of 'over' and 'reverse' so that negative operand counts don't smash the stack. 2010-09-29 Jan Nijtmans * unix/configure: Re-generate with autoconf-2.59 * win/configure: * generic/tclMain.c: Make compilable with -DUNICODE as well 2010-09-28 Reinhard Max TIP #162 IMPLEMENTATION * doc/socket.n: Document the changes to the [socket] and [fconfigure] commands. * generic/tclInt.h: Introduce TclCreateSocketAddress() as a * generic/tclIOSock.c: replacement for the platform-dependent * unix/tclUnixSock.c: TclpCreateSocketAddress() functions. Extend * unix/tclUnixChan.c: the [socket] and [fconfigure] commands to * unix/tclUnixPort.h: behave as proposed in TIP #162. This is the * win/tclWinSock.c: core of what is required to support the use of * win/tclWinPort.h: IPv6 sockets in Tcl. * compat/fake-rfc2553.c: A compat implementation of the APIs defined * compat/fake-rfc2553.h: in RFC-2553 (getaddrinfo() and friends) on top of the existing gethostbyname() etc. * unix/configure.in: Test whether the fake-implementation is * unix/tcl.m4: needed. * unix/Makefile.in: Add a compile target for fake-rfc2553. * win/configure.in: Allow cross-compilation by default. * tests/socket.test: Improve the test suite to make more use of * tests/remote.tcl: randomized ports to reduce interference with tests running in parallel or other services on the machine. 2010-09-28 Kevin B. Kenny [dogeen-assembler-branch] * tests/assemble.test: Added more "white box" tests. * generic/tclAssembly.c: Added the error checking and reporting for undefined labels. Revised code so that no pointers into the bytecode sequence are held (because the sequence can move!), that no Tcl_HashEntry pointers are held (because the hash table doesn't guarantee their stability!) and to eliminate the BBHash table, which is merely additional information indexed by jump labels and can just as easily be held in the 'label' structure. Renamed shared structures to CamelCase, and renamed 'label' to JumpLabel because other types of labels may eventually be possible. 2010-09-27 Kevin B. Kenny [dogeen-assembler-branch] * tests/assemble.test: Added more "white box" tests. * generic/tclAssembly.c: Fixed bugs exposed by the new tests. (a) [eval] and [expr] had incorrect stack balance computed if the arg was not a simple word. (b) [concat] accepted a negative operand count. (c) [invoke] accepted a zero or negative operand count. (d) more misspelt error messages. Also replaced a funky NRCallTEBC with the new call TclNRExecuteByteCode, necessitated by a merge with changes on the HEAD. 2010-09-26 Miguel Sofer * generic/tclBasic.c: [Patch 3072080] (minus the itcl * generic/tclCmdIL.c: update): a saner NRE. * generic/tclCompExpr.c: * generic/tclCompile.c: This makes TclNRExecuteByteCode (ex TEBC) * generic/tclCompile.h: to be a normal NRE citizen: it loses its * generic/tclExecute.c: special status. * generic/tclInt.decls: The logic flow within the BC engine is * generic/tclInt.h: simplified considerably. * generic/tclIntDecls.h: * generic/tclObj.c: * generic/tclProc.c: * generic/tclTest.c: * generic/tclVar.c: Use the macro HasLocalVars everywhere 2010-09-26 Miguel Sofer * generic/tclOOMethod.c (ProcedureMethodVarResolver): avoid code duplication, let the runtime var resolver call the compiled var resolver. 2010-09-26 Kevin B. Kenny [dogeen-assembler-branch] * tests/assemble.test: Added many new tests moving toward a more comprehensive test suite for the assembler. * generic/tclAssembly.c: Fixed bugs exposed by the new tests: (a) [bitnot] and [not] had incorrect operand counts. (b) INST_CONCAT cannot concatenate zero objects. (c) misspelt error messages. (d) the "assembly code" internal representation lacked a duplicator, which caused double-frees of the Bytecode object if assembly code ever was duplicated. 2010-09-25 Kevin B. Kenny [dogeen-assembler-branch] * generic/tclAssembly.c: Massive refactoring of the assembler * generic/tclAssembly.h: to use a Tcl-like syntax (and use * tests/assemble.test: Tcl_ParseCommand to parse it). The * tests/assemble1.bench: refactoring also ensures that Tcl_Tokens in the assembler have string ranges inside the source code, which allows for [eval] and [expr] assembler directives that simply call TclCompileScript and TclCompileExpr recursively. 2010-09-24 Jeff Hobbs * tests/stringComp.test: improved string eq/cmp test coverage * generic/tclExecute.c (TclExecuteByteCode): merge INST_STR_CMP and INST_STR_EQ/INST_STR_NEQ paths. Speeds up eq/ne/[string eq] with obj-aware comparisons and eq/==/ne/!= with length equality check. 2010-09-24 Andreas Kupries * tclWinsock.c: [Bug 3056775]: Fixed race condition between thread and internal co-thread access of a socket's structure because of the thread not using the socketListLock in TcpAccept(). Added documentation on how the module works to the top. 2010-09-23 Jan Nijtmans * generic/tclDecls.h: Make Tcl_SetPanicProc and Tcl_GetStringResult * unix/tclAppInit.c: callable without stubs, just as Tcl_SetVar. * win/tclAppInit.c: 2010-09-23 Don Porter * generic/tclCmdAH.c: Fix cases where value returned by * generic/tclEvent.c: Tcl_GetReturnOptions() was leaked. * generic/tclMain.c: Thanks to Jeff Hobbs for discovery of the anti-pattern to seek and destroy. 2010-09-23 Jan Nijtmans * unix/tclAppInit.c: Make compilable with -DUNICODE (not activated * win/tclAppInit.c: yet), many clean-ups in comments. 2010-09-22 Miguel Sofer * generic/tclExecute: [Bug 3072640]: One more DECACHE_STACK_INFO() was missing. * tests/execute.test: Added execute-10.3 for [Bug 3072640]. The test causes a mem failure. * generic/tclExecute: Protect all possible writes to ::errorInfo or ::errorCode with DECACHE_STACK_INFO(), as they could run traces. The new calls to be protected are Tcl_ResetResult(), Tcl_SetErrorCode(), IllegalExprOperandType(), TclExprFloatError(). The error was triggered by [Patch 3072080]. 2010-09-22 Jan Nijtmans * win/tcl.m4: Add kernel32 to LIBS, so the link line for * win/configure: mingw is exactly the same as for MSVC++. 2010-09-21 Jeff Hobbs * generic/tclExecute.c (TclExecuteByteCode): * generic/tclOOMethod.c (ProcedureMethodCompiledVarConnect): * generic/tclVar.c (TclLookupSimpleVar, CompareVarKeys): * generic/tclPathObj.c (Tcl_FSGetNormalizedPath, Tcl_FSEqualPaths): * generic/tclIOUtil.c (TclFSCwdPointerEquals): peephole opt * generic/tclResult.c (TclMergeReturnOptions): Use memcmp where applicable as possible speedup on some libc variants. 2010-09-21 Kevin B. Kenny [BRANCH: dogeen-assembler-branch] * generic/tclAssembly.c (new file): * generic/tclAssembly.h: * generic/tclBasic.c (builtInCmds, Tcl_CreateInterp): * generic/tclInt.h: * tests/assemble.test (new file): * tests/assemble1.bench (new file): * unix/Makefile.in: * win/Makefile.in: * win/Makefile.vc: Initial commit of Ozgur Dogan Ugurlu's (SF user: dogeen) assembler for the Tcl bytecode language. 2010-09-21 Jan Nijtmans * win/tclWinFile.c: Fix declaration after statement. * win/tcl.m4: Add -Wdeclaration-after-statement, so this * win/configure: mistake cannot happen again. * win/tclWinFCmd.c: [Bug 3069278]: Breakage on head Windows * win/tclWinPipe.c: triggered by install-tzdata, final fix 2010-09-20 Jan Nijtmans * win/tclWinFCmd.c: Eliminate tclWinProcs->useWide everywhere, since * win/tclWinFile.c: the value is always "1" on platforms >win95 * win/tclWinPipe.c: 2010-09-19 Donal K. Fellows * doc/file.n (file readlink): [Bug 3070580]: Typofix. 2010-09-18 Jan Nijtmans * win/tclWinFCmd.c [Bug 3069278]: Breakage on head Windows triggered by install-tzdata. Temporary don't compile this with -DUNICODE, while investigating this bug. 2010-09-16 Jeff Hobbs * win/tclWinFile.c: Remove define of FINDEX_INFO_LEVELS as all supported versions of compilers should now have it. * unix/Makefile.in: Do not pass current build env vars when using NATIVE_TCLSH in targets. 2010-09-16 Jan Nijtmans * generic/tclDecls.h: Make Tcl_FindExecutable() work in UNICODE * generic/tclEncoding.c: compiles (windows-only) as well as ASCII. * generic/tclStubInit.c: Needed for [FRQ 491789]: setargv() doesn't support a unicode cmdline. 2010-09-15 Donal K. Fellows * generic/tclBinary.c (TclAppendBytesToByteArray): [Bug 3067036]: Make sure we never try to double zero repeatedly to get a buffer size. Also added a check for sanity on the size of buffer being appended. 2010-09-15 Don Porter * unix/Makefile.in: Revise `make dist` target to tolerate the case of zero bundled packages. 2010-09-15 Jan Nijtmans * tools/genStubs.tcl: [Patch 3034251]: Backport ttkGenStubs.tcl * generic/tcl.decls: features to genStubs.tcl. Make the "generic" * generic/tclInt.decls: argument in the *.decls files optional * generic/tclOO.decls: (no change to any tcl*Decls.h files) * generic/tclTomMath.decls: This allows genStubs.tcl to generate the ttk stub files as well, while keeping full compatibility with existing *.decls files. 2010-09-14 Jan Nijtmans * win/tclWinPort.h: Allow all Win2000+ API entries in Tcl * win/tclWin32Dll.c: Eliminate dynamical loading of advapi23 and kernel32 symbols. 2010-09-13 Jan Nijtmans * win/tclWinChan.c: Various clean-ups, converting from * win/tclWinConsole.c: tclWinProc->xxxProc directly to Xxx * win/tclWinInit.c: (no change in functionality) * win/tclWinLoad.c: * win/tclWinSerial.c: * win/tclWinSock.c: * tools/genStubs.tcl: Add scspec feature from ttkGenStubs.tcl (no change in output for *Decls.h files) 2010-09-10 Jan Nijtmans * win/tclWin32Dll.c: Partly revert yesterday's change, to make it work on VC++ 6.0 again. 2010-09-10 Donal K. Fellows * doc/regsub.n: [Bug 3063568]: Fix for gotcha in example due to Tcl's special handling of backslash-newline. Makes example slightly less pure, but more useful. 2010-09-09 Jan Nijtmans * win/makefile.vc: Mingw should always link with -ladvapi32. * win/tcl.m4: * win/configure: (regenerated) * win/tclWinInt.h: Remove ascii variant of tkWinPocs table, it is * win/tclWin32Dll.c: no longer necessary. Fix CreateProcess signature * win/tclWinPipe.c: and remove unused GetModuleFileName and lstrcpy. * win/tclWinPort.h: Mingw/cygwin fixes: should always be included, and fix conflict in various macro values: Always force the same values as in VC++. 2010-09-08 Don Porter * win/tclWinChan.c: [Bug 3059922]: #ifdef protections to permit * win/tclWinFCmd.c: builds with mingw on amd64 systems. Thanks to "mescalinum" for reporting and testing. 2010-09-08 Andreas Kupries * doc/tm.n: Added underscore to the set of characters accepted in module names. This is true for quite some time in the code, this change catches up the documentation. 2010-09-03 Donal K. Fellows * tools/tcltk-man2html.tcl (plus-pkgs): Improve the package documentation search pattern to support the doctoos-generated directory structure. * tools/tcltk-man2html-utils.tcl (output-name): Made this more resilient against misformatted NAME sections, induced by import of Thread package documentation into Tcl doc tree. 2010-09-02 Andreas Kupries * doc/glob.n: Fixed documentation ambiguity regarding the handling of -join. * library/safe.tcl (safe::AliasGlob): Fixed another problem, the option -join does not stop option processing in the core builtin, so the emulation must not do that either. 2010-09-01 Andreas Kupries * library/safe.tcl (safe::AliasGlob): Moved the command extending the actual glob command with a -directory flag to when we actually have a proper untranslated path, 2010-09-01 Andreas Kupries * generic/tclExecute.c: [Bug 3057639]: Applied patch by Jeff to make * generic/tclVar.c: the behaviour of lappend in bytecompiled mode * tests/append.test: consistent with direct-eval and 'append' * tests/appendComp.test: generally. Added tests (append*-9.*) showing the difference. 2010-08-31 Jan Nijtmans * win/rules.vc: Typo (thanks to Twylite discovering this) * generic/tclStubLib.c: Revert to previous version: MSVC++ 6.0 * generic/tclTomMathStubLib.c:cannot handle the new construct. * generic/tcl.decls [Patch 2997642]: Many type casts needed * generic/tclDecls.h: when using Tcl_Pkg* API. Remaining part. * generic/tclPkg.c: * generic/tclBasic.c: * generic/tclTomMathInterface.c: * doc/PkgRequire.3 2010-08-31 Andreas Kupries * win/tcl.m4: Applied patch by Jeff fixing issues with the manifest handling on Win64. * win/configure: Regenerated. 2010-08-30 Miguel Sofer * generic/tclBasic.c: [Bugs 3046594,3047235,3048771]: New * generic/tclCmdAH.c: implementation for [tailcall] command: it now * generic/tclCmdMZ.c: schedules the command and returns TCL_RETURN. * generic/tclExecute.c: This fixes all issues with [catch] and [try]. * generic/tclInt.h: Thanks dgp for exploring the dark corners. * generic/tclNamesp.c: More thorough testing is required. * tests/tailcall.test: 2010-08-30 Jan Nijtmans * win/Makefile.in: [FRQ 2965056]: Windows build with -DUNICODE * win/rules.vc: * win/tclWinFCmd.c: Make sure that allocated TCHAR arrays are * win/tclWinFile.c: always properly aligned as wchar_t, and * win/tclWinPipe.c: not bigger than necessary. * win/tclWinSock.c: * win/tclWinDde.c: Those 3 files are not converted yet to be * win/tclWinReg.c: built with -DUNICODE, so add a TODO. * win/tclWinTest.c: * generic/tcl.decls: [Patch 2997642]: Many type casts needed when * generic/tclDecls.h: using Tcl_Pkg* API. Partly. * generic/tclPkg.c: * generic/tclStubLib.c: Demonstration how this change can benefit code. * generic/tclTomMathStubLib.c: * doc/PkgRequire.3: 2010-08-29 Donal K. Fellows * doc/dict.n: [Bug 3046999]: Corrected cross reference to array manpage to refer to (correct) existing subcommand. 2010-08-26 Jeff Hobbs * unix/configure, unix/tcl.m4: SHLIB_LD_LIBS='${LIBS}' for OSF1-V*. Add /usr/lib64 to set of auto-search dirs. [Bug 1230554] (SC_PATH_X): Correct syntax error when xincludes not found. * win/Makefile.in (VC_MANIFEST_EMBED_DLL VC_MANIFEST_EMBED_EXE): * win/configure, win/configure.in, win/tcl.m4: SC_EMBED_MANIFEST macro and --enable-embedded-manifest configure arg added to support manifest embedding where we know the magic. Help prevents DLL hell with MSVC8+. 2010-08-24 Jan Nijtmans * generic/tcl.decls: [Bug 3007895]: Tcl_(Find|Create)HashEntry * generic/tclHash.c: stub entries can never be called. * generic/tclDecls.h: * generic/tclStubInit.c: [Patch 2994165]: Change signature of Tcl_FSGetNativePath and TclpDeleteFile follow-up: move stub entry back to original location. 2010-08-23 Kevin B. Kenny * library/tzdata/Africa/Cairo: * library/tzdata/Asia/Gaza: Olson's tzdata2010l. 2010-08-22 Jan Nijtmans * generic/tclBasic.c: [Patch 3009403]: Signature of Tcl_GetHashKey, * generic/tclBinary.c: Tcl_(Create|Find)HashEntry follow-up: * generic/tclCmdIL.c: Remove many type casts which are no longer * generic/tclCompile.c:necessary as a result of this signature change. * generic/tclDictObj.c: * generic/tclEncoding.c: * generic/tclExecute.c: * generic/tclInterp.c: * generic/tclIOCmd.c: * generic/tclObj.c: * generic/tclProc.c: * generic/tclTest.c: * generic/tclTrace.c: * generic/tclUtil.c: * generic/tclVar.c: 2010-08-21 Donal K. Fellows * doc/linsert.n: [Bug 3045123]: Make description of what is actually happening more accurate. 2010-08-21 Jan Nijtmans * tools/genStubs.tcl: [Patch 3034251]: Backport ttkGenStubs.tcl features to genStubs.tcl, partly: Use void (*reserved$i)(void) = 0 instead of void *reserved$i = NULL for unused stub entries, in case pointer-to-function and pointer-to-object are different sizes. * generic/tcl*Decls.h: (regenerated) * generic/tcl*StubInit.c:(regenerated) 2010-08-20 Jan Nijtmans * doc/Method.3: Fix definition of Tcl_MethodType. 2010-08-19 Donal K. Fellows * generic/tclTrace.c (TraceExecutionObjCmd, TraceCommandObjCmd) (TraceVariableObjCmd): [Patch 3048354]: Use memcpy() instead of strcpy() to avoid buffer overflow; we have the correct length of data to copy anyway since we've just allocated the target buffer. 2010-08-18 Jan Nijtmans * tools/genStubs.tcl: [Patch 3034251]: Backport ttkGenStubs.tcl features to genStubs.tcl, partly: remove unneeded ifdeffery and put C++ guard around stubs pointer definition. * generic/*Decls.h: (regenerated) 2010-08-18 Miguel Sofer * generic/tclBasic.c: New redesign of [tailcall]: find * generic/tclExecute.c: errors early on, so that errorInfo * generic/tclInt.h: contains the proper info [Bug 3047235] * generic/tclNamesp.c: * generic/tclCmdAH.c (TclNRTryObjCmd): [Bug 3046594]: Block tailcalling out of the body of a non-bc'ed [try]. * generic/tclBasic.c: Redesign of [tailcall] to * generic/tclCmdAH.c: (a) fix [Bug 3047235] * generic/tclCompile.h: (b) enable fix for [Bug 3046594] * generic/tclExecute.c: (c) enable recursive tailcalls * generic/tclInt.h: * generic/tclNamesp.c: * tests/tailcall.test: 2010-08-18 Donal K. Fellows * library/safe.tcl (AliasGlob): [Bug 3004191]: Restore safe [glob] to working condition. 2010-08-15 Donal K. Fellows * generic/tclProc.c (ProcWrongNumArgs): [Bug 3045010]: Make the handling of passing the wrong number of arguments to [apply] somewhat less verbose when a lambda term is present. 2010-08-14 Jan Nijtmans * compat/unicows: Remove completely, see [FRQ 2819611]. * doc/FileSystem.3: [Patch 2994165]: Change signature of * generic/tcl.decls Tcl_FSGetNativePath and TclpDeleteFile * generic/tclDecls.h: * generic/tclIOUtil.c: * generic/tclStubInit.c: * generic/tclInt.h: * unix/tclUnixFCmd.c: * win/tclWinFCmd.c: * doc/Hash.3: [Patch 3009403]: Signature of Tcl_GetHashKey, * generic/tcl.h: Tcl_(Create|Find)HashEntry 2010-08-11 Jeff Hobbs * unix/ldAix: Remove ancient (pre-4.2) AIX support * unix/configure: Regen with ac-2.59 * unix/configure.in, unix/tclConfig.sh.in, unix/Makefile.in: * unix/tcl.m4 (AIX): Remove the need for ldAIX, replace with -bexpall/-brtl. Remove TCL_EXP_FILE (export file) and other baggage that went with it. Remove pre-4 AIX build support. 2010-08-11 Miguel Sofer * generic/tclBasic.c (TclNRYieldToObjCmd): * tests/coroutine.test: Fixed bad copypasta snafu. Thanks to Andy Goth for finding the bug. 2010-08-10 Jeff Hobbs * generic/tclUtil.c (TclByteArrayMatch): Patterns may not be null-terminated, so account for that. 2010-08-09 Don Porter * changes: Updates for 8.6b2 release. 2010-08-04 Jeff Hobbs * win/Makefile.in, win/makefile.bc, win/makefile.vc, win/tcl.dsp: * win/tclWinPipe.c (TclpCreateProcess): * win/stub16.c (removed): Removed Win9x tclpip8x.dll build and 16-bit application loader stub support. Win9x is no longer supported. * win/tclWin32Dll.c (TclWinInit): Hard-enforce Windows 9x as an unsupported platform with a panic. Code to support it still exists in other files (to go away in time), but new APIs are being used that don't exist on Win9x. * unix/tclUnixFCmd.c: Adjust license header as per ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change * license.terms: Fix DFARs note for number-adjusted rights clause * win/tclWin32Dll.c (asciiProcs, unicodeProcs): * win/tclWinLoad.c (TclpDlopen): 'load' use LoadLibraryEx with * win/tclWinInt.h (TclWinProcs): LOAD_WITH_ALTERED_SEARCH_PATH to prefer dependent DLLs in same dir as loaded DLL. * win/Makefile.in (%.${OBJEXT}): better implicit rules support 2010-08-04 Andreas Kupries * generic/tclIORChan.c: [Bug 3034840]: Fixed reference counting in * generic/tclIORTrans.c: InvokeTclMethod and callers. * tests/ioTrans.test: 2010-08-03 Andreas Kupries * tests/var.test (var-19.1): [Bug 3037525]: Added test demonstrating the local hashtable deletion crash and fix. * tests/info.test (info-39.1): Added forward copy of test in 8.5 branch about [Bug 2933089]. Should not fail, and doesn't, after updating the line numbers to the changed position. 2010-08-02 Kevin B. Kenny * library/tzdata/America/Bahia_Banderas: * library/tzdata/Pacific/Chuuk: * library/tzdata/Pacific/Pohnpei: * library/tzdata/Africa/Cairo: * library/tzdata/Europe/Helsinki: * library/tzdata/Pacific/Ponape: * library/tzdata/Pacific/Truk: * library/tzdata/Pacific/Yap: Olson's tzdata2010k. 2010-08-02 Miguel Sofer * generic/tclVar.c: Correcting bad port of [Bug 3037525] fix 2010-07-28 Miguel Sofer * generic/tclVar.c: [Bug 3037525]: Lose fickle optimisation in TclDeleteVars (used for runtime-created locals) that caused crash. 2010-07-29 Jan Nijtmans * compat/zlib/win32/README.txt: Official build of zlib1.dll 1.2.5 is * compat/zlib/win32/USAGE.txt: finally available, so put it in. * compat/zlib/win32/zlib1.dll: 2010-07-25 Donal K. Fellows * doc/http.n: Corrected description of location of one of the entries in the state array. 2010-07-24 Jan Nijtmans * generic/tclDecls.h: [Bug 3029891]: Functions that don't belong in * generic/tclTest.c: the stub table. * generic/tclBasic.c: From [Bug 3030870] make itcl 3.x built with pre-8.6 work in 8.6: Relax the relation between Tcl_CallFrame and CallFrame. 2010-07-16 Donal K. Fellows * generic/tclBasic.c: Added more errorCode setting. 2010-07-15 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Ensure that [dict get] * generic/tclDictObj.c (DictGetCmd): always generates an errorCode on a failure to look up an entry. 2010-07-11 Pat Thoyts * unix/configure: (regenerated) * unix/configure.in: For the NATIVE_TCLSH variable use the autoconf * unix/Makefile.in: SC_PROG_TCLSH to try and find a locally installed native binary. This avoids manually fixing up when cross compiling. If there is not one, revert to using the build product. 2010-07-02 Don Porter * generic/tclInt.decs: Reverted to the original TIP 337 implementation on what to do with the obsolete internal stub for TclBackgroundException() (eliminate it!) * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: 2010-07-02 Jan Nijtmans * generic/tclInt.decls: [Bug 803489]: Tcl_FindNamespace problem in * generic/tclIntDecls.h: the Stubs table * generic/tclStubInit.c: 2010-07-02 Donal K. Fellows * generic/tclExecute.c (IllegalExprOperandType): [Bug 3024379]: Made sure that errors caused by an argument to an operator being outside the domain of the operator all result in ::errorCode being ARITH DOMAIN and not NONE. 2010-07-01 Jan Nijtmans * win/rules.vc: [Bug 3020677]: wish can't link reg1.2 * tools/checkLibraryDoc.tcl: formatting, spacing, cleanup unused * tools/eolFix.tcl: variables; no change in generated output * tools/fix_tommath_h.tcl: * tools/genStubs.tcl: * tools/index.tcl: * tools/man2help2.tcl: * tools/regexpTestLib.tcl: * tools/tsdPerf.tcl: * tools/uniClass.tcl: * tools/uniParse.tcl: 2010-07-01 Donal K. Fellows * doc/mathop.n: [Bug 3023165]: Fix typo that was preventing proper rendering of the exclusive-or operator. 2010-06-28 Jan Nijtmans * generic/tclPosixStr.c: [Bug 3019634]: errno.h and tclWinPort.h have conflicting definitions. Added messages for ENOTRECOVERABLE, EOTHER, ECANCELED and EOWNERDEAD, and fixed various typing mistakes in other messages. 2010-06-25 Reinhard Max * tests/socket.test: Prevent a race condition during shutdown of the remote test server that can cause a hang when the server is being run in verbose mode. 2010-06-24 Jan Nijtmans * win/tclWinPort.h: [Bug 3019634]: errno.h and tclWinPort.h have conflicting definitions. ***POTENTIAL INCOMPATIBILITY*** On win32, the correspondence between errno and the related error message, as handled by Tcl_ErrnoMsg() changes. The error message is kept the same, but the corresponding errno value might change. 2010-06-22 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LsetObjCmd): [Bug 3019351]: Corrected wrong args message. 2010-06-21 Jan Nijtmans * unix/tclLoadDl.c: Eliminate various unnecessary type casts, use * unix/tclLoadNext.c: function typedefs whenever possible * unix/tclUnixChan.c: * unix/tclUnixFile.c: * unix/tclUnixNotfy.c: * unix/tclUnixSock.c: * unix/tclUnixTest.c: * unix/tclXtTest.c: * generic/tclZlib.c: Remove hack needed for zlib 1.2.3 on win32 2010-06-18 Donal K. Fellows * library/init.tcl (auto_execok): [Bug 3017997]: Add .cmd to the default list of extensions that we can execute interactively. 2010-06-16 Jan Nijtmans * tools/loadICU.tcl: [Bug 3016135]: Traceback using clock format * library/msgs/he.msg: with locale of he_IL. * generic/tcl.h: Simplify Tcl_AppInit and *_Init definitions, * generic/tclInt.h: spacing. Change TclpThreadCreate and * generic/tcl.decls: Tcl_CreateThread signature, making clear that * generic/tclDecls.h: "proc" is a function pointer, as in all other * generic/tclEvent.c: "proc" function parameters. * generic/tclTestProcBodyObj.c: * win/tclWinThrd.c: * unix/tclUnixThrd.c: * doc/Thread.3: * doc/Class.3: Fix Tcl_ObjectMetadataType definition. 2010-06-14 Jan Nijtmans * unix/Makefile.in: Fix compilation of xttest with 8.6 changes * unix/tclXtNotify.c: * unix/tclXtTest.c: * generic/tclPipe.c: Fix gcc warning (with -fstrict-aliasing=2) * library/auto.tcl: Spacing and style fixes. * library/history.tcl: * library/init.tcl: * library/package.tcl: * library/safe.tcl: * library/tm.tcl: 2010-06-13 Donal K. Fellows * tools/tcltk-man2html.tcl (make-man-pages): [Bug 3015327]: Make the title of a manual page be stored relative to its resulting directory name as well as its source filename. This was caused by both Tcl and a contributed package ([incr Tcl]) defining an Object.3. Also corrected the joining of strings in titles to avoid extra braces. 2010-06-09 Andreas Kupries * library/platform/platform.tcl: Added OSX Intel 64bit * library/platform/pkgIndex.tcl: Package updated to version 1.0.9. * unix/Makefile.in: * win/Makefile.in: 2010-06-09 Jan Nijtmans * tools/tsdPerf.c: Fix export of symbol Tsdperf_Init, when using -fvisibility=hidden. Make two functions static, eliminate some unnecessary type casts. * tools/configure.in: Update to Tcl 8.6 * tools/configure: (regenerated) * tools/.cvsignore new file 2010-06-07 Alexandre Ferrieux * generic/tclExecute.c: Ensure proper reset of [info errorstack] even * generic/tclNamesp.c: when compiling constant expr's with errors. 2010-06-05 Miguel Sofer * generic/tclBasic.c: [Bug 3008307]: make callerPtr chains be * generic/tclExecute.c: traversable accross coro boundaries. Add the special coroutine CallFrame (partially reverting commit of 2009-12-10), as it is needed for coroutines that do not push a CF, eg, those with [eval] as command. Thanks to Colin McCormack (coldstore) and Alexandre Ferrieux for the hard work on this. 2010-06-03 Alexandre Ferrieux * generic/tclNamesp.c: Safer (and faster) computation of [uplevel] * tests/error.test: offsets in TIP 348. Toplevel offsets no longer * tests/result.test: overestimated. 2010-06-02 Jan Nijtmans * generic/tclOO.h: BUILD_tcloo is never defined (leftover) * win/makefile.bc: Don't set BUILD_tcloo (leftover) See also entry below: 2008-06-01 Joe Mistachkin 2010-06-01 Alexandre Ferrieux * generic/tclNamesp.c: Fix computation of [uplevel] offsets in TIP 348 * tests/error.test: Only depend on callerPtr chaining now. * tests/result.test: Needed for upcoming coro patch. 2010-05-31 Jan Nijtmans * generic/tclVar.c: Eliminate some casts to (Tcl_HashTable *) * generic/tclExecute.c: * tests/fileSystem.test: Fix filesystem-5.1 test failure on CYGWIN 2010-05-28 Jan Nijtmans * generic/tclInt.h: [Patch 3008541]: Order of TIP #348 fields in Interp structure 2010-05-28 Donal K. Fellows * generic/tclCompCmdsSZ.c (IssueTryFinallyInstructions): [3007374]: Corrected error in handling of catch contexts to prevent crash with chained handlers. * generic/tclExecute.c (TclExecuteByteCode): Restore correct operation of instruction-level execution tracing (had been broken by NRE). 2010-05-27 Jan Nijtmans * library/opt/optParse.tcl: Don't generate spaces at the end of a * library/opt/pkgIndex.tcl: line, eliminate ';' at line end, bump to * tools/uniParse.tcl: v0.4.6 * generic/tclUniData.c: * tests/opt.test: * tests/safe.test: 2010-05-21 Jan Nijtmans * tools/installData.tcl: Make sure that copyDir only receives normalized paths, otherwise it might result in a crash on CYGWIN. Restyle according to the Tcl style guide. * generic/tclStrToD.c: [Bug 3005233]: Fix for build on OpenBSD vax 2010-05-19 Alexandre Ferrieux * tests/dict.test: Add missing tests for [Bug 3004007], fixed under the radar on 2010-02-24 (dkf): EIAS violation in list-dict conversions 2010-05-19 Jan Nijtmans * generic/regcomp.c: Don't use arrays of length 1, just use a * generic/tclFileName.c: single element then, it makes code more * generic/tclLoad.c: readable. (Here it even prevents a type cast) 2010-05-17 Jan Nijtmans * generic/tclStrToD.c: [Bug 2996549]: Failure in expr.test on Win32 2010-05-17 Donal K. Fellows * generic/tclCmdIL.c (TclInfoFrame): Change this code to use Tcl_GetCommandFullName rather than rolling its own. Discovered during the hunting of [Bug 3001438] but unlikely to be a fix. 2010-05-11 Jan Nijtmans * win/tclWinConsole.c: [Patch 2997087]: Unnecessary type casts. * win/tclWinDde.c: * win/tclWinLoad.c: * win/tclWinNotify.c: * win/tclWinSerial.c: * win/tclWinSock.c: * win/tclWinTime.c: * win/tclWinPort.h: Don't duplicate CYGWIN timezone #define from tclPort.h 2010-05-07 Andreas Kupries * library/platform/platform.tcl: Fix cpu name for Solaris/Intel 64bit. * library/platform/pkgIndex.tcl: Package updated to version 1.0.8. * unix/Makefile.in: * win/Makefile.in: 2010-05-06 Jan Nijtmans * generic/tclPkg.c: Unnecessary type casts, see [Patch 2997087] 2010-05-04 Jan Nijtmans * win/tclWinNotify.c: TCHAR-related fixes, making those two files * win/tclWinSock.c: compile fine when TCHAR != char. Please see comments in [FRQ 2965056] (2965056-1.patch). 2010-05-03 Jan Nijtmans * generic/tclIORChan.c: Use "tclIO.h" and "tclTomMathDecls.h" * generic/tclIORTrans.c: everywhere * generic/tclTomMath.h: * tools/fix_tommath_h.tcl: * libtommath/tommath.h: Formatting (# should always be first char on line) * win/tclAppInit.c: For MINGW/CYGWIN, use GetCommandLineA explicitly. * unix/.cvsignore: Add pkg, *.dll * libtommath/tommath.h: CONSTify various useful internal * libtommath/bn_mp_cmp_d.c: functions (TclBignumToDouble, TclCeil, * libtommath/bn_mp_cmp_mag.c: TclFloor), and related tommath functions * libtommath/bn_mp_cmp.c: * libtommath/bn_mp_copy.c: * libtommath/bn_mp_count_bits.c: * libtommath/bn_mp_div_2d.c: * libtommath/bn_mp_mod_2d.c: * libtommath/bn_mp_mul_2d.c: * libtommath/bn_mp_neg.c: * generic/tclBasic.c: Handle TODO: const correctness ? * generic/tclInt.h: * generic/tclStrToD.c: * generic/tclTomMath.decls: * generic/tclTomMath.h: * generic/tclTomMathDecls.h: 2010-04-30 Don Porter * generic/tcl.h: Bump patchlevel to 8.6b1.2 to distinguish * library/init.tcl: CVS snapshots from earlier snapshots as well * unix/configure.in: as the 8.6b1 and 8.6b2 releases. * win/configure.in: * unix/configure: autoconf-2.59 * win/configure: * generic/tclBinary.c (TclAppendBytesToByteArray): Add comments * generic/tclInt.h (TclAppendBytesToByteArray): placing overflow protection responsibility on caller. Convert "len" argument to signed int which any value already vetted for overflow issues will fit into. * generic/tclStringObj.c: Update caller; standardize panic msg. * generic/tclBinary.c (UpdateStringOfByteArray): [Bug 2994924]: Add panic when the generated string representation would grow beyond Tcl's size limits. 2010-04-30 Donal K. Fellows * generic/tclBinary.c (TclAppendBytesToByteArray): Add extra armour against buffer overflows. * generic/tclBasic.c (NRInterpCoroutine): Corrected handling of * tests/coroutine.test (coroutine-6.4): arguments to deal with trickier cases. 2010-04-30 Miguel Sofer * tests/coroutine.test: testing coroutine arguments after [yield]: check that only 0/1 allowed 2010-04-30 Donal K. Fellows * generic/tclBasic.c (NRInterpCoroutine): Corrected handling of arguments to deal with trickier cases. * generic/tclCompCmds.c (TclCompileVariableCmd): Slightly tighter issuing of instructions. * generic/tclExecute.c (TclExecuteByteCode): Add peephole optimization of the fact that INST_DICT_FIRST and INST_DICT_NEXT always have a conditional jump afterwards. * generic/tclBasic.c (TclNRYieldObjCmd, TclNRYieldmObjCmd) (NRInterpCoroutine): Replace magic values for formal argument counts for coroutine command implementations with #defines, for an increase in readability. 2010-04-30 Jan Nijtmans * generic/tclMain.c: Unnecessary TCL_STORAGE_CLASS re-definition. It was used for an ancient dummy reference to Tcl_LinkVar(), but that's already gone since 2002-05-29. 2010-04-29 Miguel Sofer * generic/tclCompExpr.c: Slight change in the literal sharing * generic/tclCompile.c: mechanism to avoid shimmering of * generic/tclCompile.h: command names. * generic/tclLiteral.c: 2010-04-29 Andreas Kupries * library/platform/platform.tcl: Another stab at getting the /lib, * library/platform/pkgIndex.tcl: /lib64 difference right for linux. * unix/Makefile.in: Package updated to version 1.0.7. * win/Makefile.in: 2010-04-29 Kevin B. Kenny * library/tzdata/Antarctica/Macquarie: * library/tzdata/Africa/Casablanca: * library/tzdata/Africa/Tunis: * library/tzdata/America/Santiago: * library/tzdata/America/Argentina/San_Luis: * library/tzdata/Antarctica/Casey: * library/tzdata/Antarctica/Davis: * library/tzdata/Asia/Anadyr: * library/tzdata/Asia/Damascus: * library/tzdata/Asia/Dhaka: * library/tzdata/Asia/Gaza: * library/tzdata/Asia/Kamchatka: * library/tzdata/Asia/Karachi: * library/tzdata/Asia/Taipei: * library/tzdata/Europe/Samara: * library/tzdata/Pacific/Apia: * library/tzdata/Pacific/Easter: * library/tzdata/Pacific/Fiji: Olson's tzdata2010i. 2010-04-29 Donal K. Fellows * generic/tclBinary.c (TclAppendBytesToByteArray): [Bug 2992970]: Make * generic/tclStringObj.c (Tcl_AppendObjToObj): an append of a byte array to another into an efficent operation. The problem was the (lack of) a proper growth management strategy for the byte array. 2010-04-29 Jan Nijtmans * compat/dirent2.h: Include "tcl.h", not , like everywhere * compat/dlfcn.h: else, to ensure that the version in the Tcl * compat/stdlib.h: distribution is used, not some version from * compat/string.h: somewhere else. * compat/unistd.h: 2010-04-28 Jan Nijtmans * win/Makefile.in: Remove unused @MAN2TCLFLAGS@ * win/tclWinPort.h: Move include from tclInt.h to * generic/tclInt.h: tclWinPort.h, and eliminate unneeded * generic/tclEnv.c: , and , which are already in tclInt.h * generic/regcustom.h: Move "tclInt.h" from regcustom.h up to * generic/regex.h: regex.h. * generic/tclAlloc.c: Unneeded include. * generic/tclExecute.c: Fix gcc warning: comparison between signed and unsigned. 2010-04-28 Donal K. Fellows * generic/tclInt.h (TclIsVarDirectUnsettable): Corrected flags so that deletion of traces is not optimized out... * generic/tclExecute.c (ExecuteExtendedBinaryMathOp) (TclCompareTwoNumbers,ExecuteExtendedUnaryMathOp,TclExecuteByteCode): [Patch 2981677]: Move the less common arithmetic operations (i.e., exponentiation and operations on non-longs) out of TEBC for a big drop in the overall size of the stack frame for most code. Net effect on speed is minimal (slightly faster overall in tclbench). Also extended the number of places where TRESULT handling is replaced with a jump to dedicated code. 2010-04-27 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Rearrange location of an assignment to shorten the object code. 2010-04-27 Jan Nijtmans * generic/tclIOUtil.c (Tcl_FSGetNativePath): [Bug 2992292]: tclIOUtil.c assignment type mismatch compiler warning * generic/regguts.h: If tclInt.h or tclPort.h is already * generic/tclBasic.c: included, don't include * generic/tclExecute.c: again. Follow-up to [Bug 2991415]: * generic/tclIORChan.c: tclport.h #included before limits.h * generic/tclIORTrans.c: See comments in [Bug 2991415] * generic/tclObj.c: * generic/tclOOInt.h: * generic/tclStrToD.c: * generic/tclTomMath.h: * generic/tclTomMathInterface.c: * generic/tclUtil.c: * compat/strtod.c: * compat/strtol.c: 2010-04-27 Kevin B. Kenny * unix/tclLoadDl.c (FindSymbol): [Bug 2992295]: Simplified the logic so that the casts added in Donal Fellows's change for the same bug are no longer necessary. 2010-04-26 Donal K. Fellows * unix/tclLoadDl.c (FindSymbol): [Bug 2992295]: Added an explicit cast because auto-casting between function and non-function types is never naturally warning-free. * generic/tclStubInit.c: Add a small amount of gcc-isms (with #ifdef * generic/tclOOStubInit.c: guards) to ensure that warnings are issued when these files are older than the various *.decls files. 2010-04-25 Miguel Sofer * generic/tclBasic.c: Add unsupported [yieldm] command. Credit * generic/tclInt.h: Lars Hellstrom for the basic idea. 2010-04-24 Miguel Sofer * generic/tclBasic.c: Modify api of TclSpliceTailcall() to fix * generic/tclExecute.c: [yieldTo], which had not survived the latest * generic/tclInt.h: mods to tailcall. Thanks kbk for detecting the problem. 2010-04-23 Jan Nijtmans * unix/tclUnixPort.h: [Bug 2991415]: tclport.h #included before limits.h 2010-04-22 Jan Nijtmans * generic/tclPlatDecls.h: Move TCHAR fallback typedef from tcl.h to * generic/tcl.h: tclPlatDecls.h (as suggested by dgp) * generic/tclInt.h: fix typo * generic/tclIOUtil.c: Eliminate various unnecessary * unix/tclUnixFile.c: type casts. * unix/tclUnixPipe.c: * win/tclWinChan.c: * win/tclWinFCmd.c: * win/tclWinFile.c: * win/tclWinLoad.c: * win/tclWinPipe.c: 2010-04-20 Jan Nijtmans * generic/tclTest.c: Use function prototypes from the FS API. * compat/zlib/*: Upgrade to zlib 1.2.5 2010-04-19 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Improve commenting and reduce indentation for the Invocation Block. 2010-04-18 Donal K. Fellows * doc/unset.n: [Bug 2988940]: Fix typo. 2010-04-15 Jan Nijtmans * win/tclWinPort.h: Move inclusion of from * generic/tcl.h: tclPlatDecls.h to tclWinPort.h, where it * generic/tclPlatDecls.h: belongs. Add fallback in tcl.h, so TCHAR is available in win32 always. 2010-04-15 Donal K. Fellows * doc/try.n: [Bug 2987551]: Fix typo. 2010-04-14 Andreas Kupries * library/platform/platform.tcl: Linux platform identification: * library/platform/pkgIndex.tcl: Check /lib64 for existence of files * unix/Makefile.in: matching libc* before accepting it as base * win/Makefile.in: directory. This can happen on weirdly installed 32bit systems which have an empty or partially filled /lib64 without an actual libc. Bumped to version 1.0.6. 2010-04-13 Jan Nijtmans * win/tclWinPort.h: Fix [Patch 2986105]: conditionally defining * win/tclWinFile.c: strcasecmp/strncasecmp * win/tclWinLoad.c: Fix gcc warning: comparison of unsigned expression >= 0 is always true 2010-04-08 Donal K. Fellows * generic/tclCompCmdsSZ.c (TclSubstCompile): If the first token does not result in a *guaranteed* push of a Tcl_Obj on the stack, we must push an empty object. Otherwise it is possible to get to a 'concat1' or 'done' without enough values on the stack, resulting in a crash. Thanks to Joe Mistachkin for identifying a script that could trigger this case. 2010-04-07 Donal K. Fellows * doc/catch.n, doc/info.n, doc/return.n: Formatting. 2010-04-06 Donal K. Fellows * doc/Load.3: Minor corrections of formatting and cross links. 2010-04-06 Jan Nijtmans * win/configure: (regenerate with autoconf-2.59) * unix/configure: * unix/installManPage: [Bug 2982540]: configure and install* script * unix/install-sh: files should always have LF line ending. * doc/Load.3: Fix signature of Tcl_LoadFile in documentation. 2010-04-05 Alexandre Ferrieux TIP #348 IMPLEMENTATION * generic/tclBasic.c: [Patch 2868499]: Substituted error stack * generic/tclCmdIL.c: * generic/tclInt.h: * generic/tclNamesp.c: * generic/tclResult.c: * doc/catch.n: * doc/info.n: * doc/return.n: * tests/cmdMZ.test: * tests/error.test: * tests/execute.test: * tests/info.test: * tests/init.test: * tests/result.test: 2010-04-05 Donal K. Fellows * unix/tcl.m4 (SC_ENABLE_THREADS): Flip the default for whether to * win/tcl.m4 (SC_ENABLE_THREADS): build in threaded mode. Part of * win/rules.vc: TIP #364. * unix/tclLoadDyld.c (FindSymbol): Better human-readable error message generation to match code in tclLoadDl.c. 2010-04-04 Donal K. Fellows * generic/tclIOUtil.c, unix/tclLoadDl.c: Minor changes to enforce Engineering Manual style rules. * doc/FileSystem.3, doc/Load.3: Documentation for TIP#357. * macosx/tclMacOSXBundle.c (OpenResourceMap): [Bug 2981528]: Only define this function when HAVE_COREFOUNDATION is defined. 2010-04-02 Jan Nijtmans * generic/tcl.decls (Tcl_LoadFile): Add missing "const" in signature, * generic/tclIOUtil.c (Tcl_LoadFile): and some formatting fixes * generic/tclDecls.h: (regenerated) 2010-04-02 Donal K. Fellows * generic/tclIOUtil.c (Tcl_LoadFile): Corrections to previous commit * unix/tclLoadDyld.c (TclpDlopen): to make it build on OSX. 2010-04-02 Kevin B. Kenny TIP #357 IMPLEMENTATION TIP #362 IMPLEMENTATION * generic/tclStrToD.c: [Bug 2952904]: Defer creation of the smallest floating point number until it is actually used. (This change avoids a bogus syslog message regarding a 'floating point software assist fault' on SGI systems.) * library/reg/pkgIndex.tcl: [TIP #362]: Fixed first round of bugs * tests/registry.test: resulting from the recent commits of * win/tclWinReg.c: changes in support of the referenced TIP. * generic/tcl.decls: [TIP #357]: First round of changes * generic/tclDecls.h: to export Tcl_LoadFile, * generic/tclIOUtil.c: Tcl_FindSymbol, and Tcl_FSUnloadFile * generic/tclInt.h: to the public API. * generic/tclLoad.c: * generic/tclLoadNone.c: * generic/tclStubInit.c: * tests/fileSystem.test: * tests/load.test: * tests/unload.test: * unix/tclLoadDl.c: * unix/tclLoadDyld.c: * unix/tclLoadNext.c: * unix/tclLoadOSF.c: * unix/tclLoadShl.c: * unix/tclUnixPipe.c: * win/Makefile.in: * win/tclWinLoad.c: 2010-03-31 Donal K. Fellows * doc/registry.n: Added missing documentation of TIP#362 flags. * doc/package.n: [Bug 2980210]: Document the arguments taken by the [package present] command correctly. * doc/Thread.3: Added some better documentation of how to create and use a thread using the C-level thread API, based on realization that no such tutorial appeared to exist. 2010-03-31 Jan Nijtmans * test/cmdMZ.test: [FRQ 2974744]: share exception codes (ObjType?): * test/error.test: Revised test cases, making sure that abbreviated * test/proc-old.test: codes are checked resulting in an error, and checking for the exact error message. 2010-03-30 Andreas Kupries * generic/tclIORChan.c (ReflectClose, ReflectInput, ReflectOutput, (ReflectSeekWide, ReflectWatch, ReflectBlock, ReflectSetOption, (ReflectGetOption, ForwardProc): [Bug 2978773]: Preserve ReflectedChannel* structures across handler invokations, to avoid crashes when the handler implementation induces nested callbacks and destruction of the channel deep inside such a nesting. 2010-03-30 Don Porter * generic/tclObj.c (Tcl_GetCommandFromObj): [Bug 2979402]: Reorder the validity tests on internal rep of a "cmdName" value to avoid invalid reads reported by valgrind. 2010-03-30 Jan Nijtmans * generic/tclIndexObj: [FRQ 2974744]: share exception codes * generic/tclResult.c: further optimization, making use of indexType. * generic/tclZlib.c: [Bug 2979399]: uninitialized value troubles 2010-03-30 Donal K. Fellows TIP #362 IMPLEMENTATION * win/tclWinReg.c: [Patch 2960976]: Apply patch from Damon Courtney to * tests/registry.test: allow the registry command to be told to work * win/Makefile.in: with both 32-bit and 64-bit registries. Bump * win/configure.in: version of registry package to 1.3. * win/makefile.bc: * win/makefile.vc: * win/configure: autoconf-2.59 2010-03-29 Jan Nijtmans * unix/tcl.m4: Only test for -visibility=hidden with gcc (Second remark in [Bug 2976508]) * unix/configure: regen 2010-03-29 Don Porter * generic/tclStringObj.c: Fix array overrun in test format-1.12 caught by valgrind testing. 2010-03-27 Jan Nijtmans * generic/tclInt.h: [FRQ 2974744]: share exception codes * generic/tclResult.c: (ObjType?) * generic/tclCmdMZ.c: * generic/tclCompCmdsSZ.c: 2010-03-26 Jan Nijtmans * generic/tclExecute.c: [Bug 2976508]: Tcl HEAD fails on HP-UX 2010-03-25 Donal K. Fellows * unix/tclUnixFCmd.c (TclUnixCopyFile): [Bug 2976504]: Corrected number of arguments to fstatfs() call. * macosx/tclMacOSXBundle.c, macosx/tclMacOSXFCmd.c: * macosx/tclMacOSXNotify.c: Reduce the level of ifdeffery in the functions of these files to improve readability. They need to be audited for whether complexity can be removed based on the minimum supported version of OSX, but that requires a real expert. 2010-03-24 Don Porter * generic/tclResult.c: [Bug 2383005]: Revise [return -errorcode] so * tests/result.test: that it rejects illegal non-list values. 2010-03-24 Donal K. Fellows * generic/tclOOInfo.c (InfoObjectMethodTypeCmd) (InfoClassMethodTypeCmd): Added introspection of method types so that it is possible to find this info out without using errors. * generic/tclOOMethod.c (procMethodType): Now that introspection can reveal the name of method types, regularize the name of normal methods to be the name of the definition type used to create them. * tests/async.test (async-4.*): Reduce obscurity of these tests by putting the bulk of the code for them inside the test body with the help of [apply]. * generic/tclCmdMZ.c (TryPostBody, TryPostHandler): Make sure that the [try] command does not trap unwinding due to limits. 2010-03-23 Don Porter * generic/tclCmdMZ.c: [Bug 2973361]: Revised fix for computing indices of script arguments to [try]. 2010-03-23 Jan Nijtmans * generic/tclCmdMZ.c: Make error message in "try" implementation * generic/tclCompCmdsSZ.c: exactly the same as the one in "return" * tests/error.test: * libtommath/mtests/mpi.c: Single "const" addition 2010-03-22 Don Porter * generic/tclCmdMZ.c: [Bug 2973361]: Compute the correct integer values to identify the argument indices of the various script arguments to [try]. Passing in -1 led to invalid memory reads. 2010-03-20 Donal K. Fellows * doc/exec.n: Make it a bit clearer that there is an option to run a pipeline in the background. * generic/tclIOCmd.c (Tcl_FcopyObjCmd): Lift the restriction * generic/tclIO.c (TclCopyChannel, CopyData): on the [fcopy] command * generic/tclIO.h (CopyState): that forced it to only copy up to 2GB per script-level callback. Now it is anything that can fit in a (signed) 64-bit integer. Problem identified by Frederic Bonnet on comp.lang.tcl. Note that individual low-level reads and writes are still smaller as the optimal buffer size is smaller. 2010-03-20 Jan Nijtmans * win/stub16.c: Don't hide that we use the ASCII API here. (does someone still use that?) * win/tclWinPipe.c: 2 unnecessary type casts. 2010-03-19 Donal K. Fellows * generic/tclCompCmdsSZ.c (TclCompileThrowCmd): Added compilation for the [throw] command. 2010-03-18 Don Porter * generic/tclListObj.c: [Bug 2971669]: Prevent in overflow trouble in * generic/tclTestObj.c: ListObjReplace operations. Thanks to kbk for * tests/listObj.test: fix and test. 2010-03-18 Donal K. Fellows * generic/tclCompCmdsSZ.c (IssueTryFinallyInstructions): [Bug 2971921]: Corrected jump so that it doesn't skip into the middle of an instruction! Tightened the instruction issuing. Moved endCatch calls closer to their point that they guard, ensuring correct ordering of result values. 2010-03-17 Andreas Kupries * generic/tclIORTrans.c (ReflectInput, ReflectOutput) (ReflectSeekWide): [Bug 2921116]: Added missing TclEventuallyFree calls for preserved ReflectedTransform* structures. Reworked ReflectInput to preserve the structure for its whole life, not only in InvokeTclMethod. * generic/tclIO.c (Tcl_GetsObj): [Bug 2921116]: Regenerate topChan, may have been changed by a self-modifying transformation. * tests/ioTrans/test (iortrans-4.8, iortrans-4.9, iortrans-5.11) (iortrans-7.4, iortrans-8.3): New test cases. 2010-03-16 Jan Nijtmans * compat/zlib/*: Upgrade zlib to version 1.2.4. * win/makefile.vc: * unix/Makefile.in: * win/tclWinChan.c: Don't cast away "const" without reason. 2010-03-12 Jan Nijtmans * win/makefile.vc: [Bug 2967340]: Static build was failing. * win/.cvsignore: 2010-03-10 Jan Nijtmans * generic/tclTest.c: Remove unnecessary '&' decoration for * generic/tclIOUtil.c: function pointers * win/tclWin32Dll.c: Double declaration of TclNativeDupInternalRep * unix/tclIOUtil.c: * unix/dltest/.cvsignore: Ignore *.so here 2010-03-09 Andreas Kupries * generic/tclIORChan.c: [Bug 2936225]: Thanks to Alexandre Ferrieux * doc/refchan.n: for debugging and * tests/ioCmd.test: fixing the problem. It is the write-side equivalent to the bug fixed 2009-08-06. 2010-03-09 Don Porter * library/tzdata/America/Matamoros: New locale * library/tzdata/America/Ojinaga: New locale * library/tzdata/America/Santa_Isabel: New locale * library/tzdata/America/Asuncion: * library/tzdata/America/Tijuana: * library/tzdata/Antarctica/Casey: * library/tzdata/Antarctica/Davis: * library/tzdata/Antarctica/Mawson: * library/tzdata/Asia/Dhaka: * library/tzdata/Pacific/Fiji: Olson tzdata2010c. 2010-03-07 Jan Nijtmans * generic/tclTest.c: Test that tclOO stubs are present in stub library * generic/tclOOMethod.c: Applied missing part of [Patch 2961556] * win/tclWinInt.h: Change all tclWinProcs signatures to use * win/tclWin32Dll.c: TCHAR* in stead of WCHAR*. This is meant * win/tclWinDde.c: as preparation to make [Enh 2965056] * win/tclWinFCmd.c: possible at all. * win/tclWinFile.c: * win/tclWinPipe.c: * win/tclWinSock.c: 2010-03-06 Jan Nijtmans * generic/tclStubLib.c: Remove presence of tclTomMathStubsPtr here. * generic/tclTest.c: Test that tommath stubs are present in stub library. 2010-03-05 Donal K. Fellows * generic/tclIORTrans.c (ForwardProc): [Bug 2964425]: When cleaning the stables, it is sometimes necessary to do more than the minimum. In this case, rationalizing the variables for a forwarded limit? method required removing an extra Tcl_DecrRefCount too. * generic/tclOO.h, generic/tclOOInt.h: [Patch 2961556]: Change TclOO to use the same style of function typedefs as Tcl, as this is about the last chance to get this right. ***POTENTIAL INCOMPATIBILITY*** Source code that uses function typedefs from TclOO will need to update variables and argument definitions so that pointers to the function values are used instead. Binary compatibility is not affected. * generic/*.c, generic/tclInt.h, unix/*.c, macosx/*.c: Applied results of doing a Code Audit. Principal changes: * Use do { ... } while (0) in macros * Avoid shadowing one local variable with another * Use clearer 'foo.bar++;' instead of '++foo.bar;' where result not required (i.e., semantically equivalent); clarity is increased because it is bar that is incremented, not foo. * Follow Engineering Manual rules on spacing and declarations 2010-03-04 Donal K. Fellows * generic/tclOO.c (ObjectRenamedTrace): [Bug 2962664]: Add special handling so that when the class of classes is deleted, so is the class of objects. Immediately. * generic/tclOOInt.h (ROOT_CLASS): Add new flag for specially marking the root class. Simpler and more robust than the previous technique. 2010-03-04 Jan Nijtmans * generic/tclGetDate.y: 3 unnecessary MODULE_SCOPE * generic/tclDate.c: symbols * generic/tclStubLib.c: Split tommath stub lib * generic/tclTomMathStubLib.c: in separate file. * win/makefile.bc: * win/Makefile.in: * win/makefile.vc: * win/tcl.dsp: * unix/Makefile.in: * unix/tcl.m4: Cygwin only gives warning * unix/configure: using -fvisibility=hidden * compat/strncasecmp.c: A few more const's * compat/strtod.c: * compat/strtoul.c: 2010-03-03 Andreas Kupries * doc/refchan.n: Followup to ChangeLog entry 2009-10-07 (generic/tclIORChan.c). Fixed the documentation to explain that errno numbers are operating system dependent, and reworked the associated example. 2010-03-02 Jan Nijtmans * unix/tcl.m4: [FRQ 2959069]: Support for -fvisibility=hidden * unix/configure (regenerated with autoconf-2.59) 2010-03-01 Alexandre Ferrieux * unix/tclUnixSock.c: Refrain from a possibly lengthy reverse-DNS lookup on 0.0.0.0 when calling [fconfigure -sockname] on an universally-bound (default) server socket. * generic/tclIndexObj.c: fix [AT 86258]: special-casing of empty tables when generating error messages for [::tcl::prefix match]. 2010-02-28 Donal K. Fellows * generic/tclCmdIL.c: More additions of {TCL LOOKUP} error-code generation to various subcommands of [info] as part of long-term project to classify all Tcl's generated errors. 2010-02-28 Jan Nijtmans * generic/tclStubInit.c: [Bug 2959713]: Link error with gcc 4.1 2010-02-27 Donal K. Fellows * generic/tclCmdMZ.c (StringFirstCmd, StringLastCmd): [Bug 2960021]: Only search for the needle in the haystack when the needle isn't larger than the haystack. Prevents an odd crash from sometimes happening when things get mixed up (a common programming error). * generic/tclMain.c (Tcl_Main): [Bug 801429]: Factor out the holding of the client-installed main loop function into thread-specific data. ***POTENTIAL INCOMPATIBILITY*** Code that previously tried to set the main loop from another thread will now fail. On the other hand, there is a fairly high probability that such programs would have been failing before due to the lack of any kind of inter-thread memory barriers guarding accesses to this part of Tcl's state. 2010-02-26 Donal K. Fellows * generic/tclCompCmds.c: Split this file into two pieces to make it * generic/tclCompCmdsSZ.c: easier to work with. It's still two very long files even after the split. 2010-02-26 Reinhard Max * doc/safe.n: Name the installed file after the command it documents. Use "Safe Tcl" instead of the "Safe Base", "Safe Tcl" mixture. 2010-02-26 Donal K. Fellows * unix/Makefile.in (NATIVE_TCLSH): Added this variable to allow for better control of what tclsh to use for various scripts when doing cross compiling. An imperfect solution, but works. * unix/installManPage: Remap non-alphanumeric sequences in filenames to single underscores (especially colons). 2010-02-26 Pat Thoyts * tests/zlib.test: Add tests for [Bug 2818131] which was crashing with mismatched zlib algorithms used in combination with gets. This issue has been fixed by Andreas's last commit. 2010-02-25 Jan Nijtmans * generic/tclHash.c: [FRQ 2958832]: Further speed-up of the * generic/tclLiteral.c: ouster-hash function. * generic/tclObj.c: * generic/tclCkalloc.c: Eliminate various unnecessary (ClientData) * generic/tclTest.c: type casts. * generic/tclTestObj.c: * generic/tclTestProcBodyObj.c: * unix/tclUnixTest.c: * unix/tclUnixTime.c: * unix/tclXtTest.c: 2010-02-24 Donal K. Fellows * generic/tclDictObj.c (SetDictFromAny): Prevent the list<->dict * generic/tclListObj.c (SetListFromAny): conversion code from taking too many liberties. Stops loss of duplicate keys in some scenarios. Many thanks to Jean-Claude Wippler for finding this. * generic/tclExecute.c (TclExecuteByteCode): Reduce ifdef-fery and size of activation record. More variables shared across instructions than before. * doc/socket.n: [Bug 2957688]: Clarified that [socket -server] works with a command prefix. Extended example to show this in action. 2010-02-22 Andreas Kupries * generic/tclZlib.c (ZlibTransformInput): [Bug 2762041]: Added a hack to work around the general problem, early EOF recognition based on the base-channel, instead of the data we have ready for reading in the transform. Long-term we need a proper general fix (likely tracking EOF on each level of the channel stack), with attendant complexity. Furthermore, Z_BUF_ERROR can be ignored, and must be when feeding the zlib code with single characters. 2010-02-22 Jan Nijtmans * unix/tclUnixPort.h: Remove unnecessary EXTERN's, which already are in the global stub table. * unix/configure.in: Use @EXEEXT@ in stead of @EXT_SUFFIX@ * unix/tcl.m4: * unix/Makefile.in: Use -DBUILD_tcl for CYGWIN * unix/configure: (regenerated) * unix/dltest/pkg*.c: Use EXTERN to control CYGWIN exported symbols * generic/tclCmdMZ.c: Remove some unnecessary type casts. * generic/tclCompCmds.c: * generic/tclTest.c: * generic/tclUtil.c: 2010-02-21 Mo DeJong * tests/regexp.test: Add test cases back ported from Jacl regexp work. 2010-02-21 Jan Nijtmans * generic/tclDate.c: Some more const tables. * generic/tclGetDate.y: * generic/regc_lex.c: * generic/regerror.c: * generic/tclStubLib.c: * generic/tclBasic.c: Fix [Bug 2954959] expr abs(0.0) is -0.0 * tests/expr.test: 2010-02-20 Donal K. Fellows * generic/tclCompCmds.c (TclCompileStringLenCmd): Make [string length] of a constant string be handled better (i.e., handle backslashes too). 2010-02-19 Stuart Cassoff * tcl.m4: Correct compiler/linker flags for threaded builds on OpenBSD. * configure: (regenerated). 2010-02-19 Donal K. Fellows * unix/installManPage: [Bug 2954638]: Correct behaviour of manual page installer. Also added armouring to check that assumptions about the initial state are actually valid (e.g., look for existing input file). 2010-02-17 Donal K. Fellows * generic/tclHash.c (HashStringKey): Restore these hash functions * generic/tclLiteral.c (HashString): to use the classic algorithm. * generic/tclObj.c (TclHashObjKey): Community felt normal case speed to be more important than resistance to malicious cases. For now, hashes that need to deal with the malicious case can use a custom hash table and install their own hash function, though that is not functionality exposed to the script level. * generic/tclCompCmds.c (TclCompileDictUpdateCmd): Stack depth must be correctly described when compiling a body to prevent crashes in some debugging modes. 2010-02-16 Jan Nijtmans * generic/tclInt.h: Change order of various struct members, fixing potential binary incompatibility with Tcl 8.5 2010-02-16 Donal K. Fellows * unix/configure.in, generic/tclIOUtil.c (Tcl_Stat): Updated so that we do not assume that all unix systems have the POSIX blkcnt_t type, since OpenBSD apparently does not. * generic/tclLiteral.c (HashString): Missed updating to FNV in one place; the literal table (a copy of the hash table code...) 2010-02-15 Jan Nijtmans * tools/genStubs.tcl: Reverted earlier rename from tcl*Stubs to * generic/tclBasic.c: tcl*ConstStubs, it's not necessary at all. * generic/tclOO.c: * generic/tclTomMathInterface.c: * generic/tclStubInit.c: (regenerated) * generic/tclOOStubInit.c: (regenerated) * generic/tclEnsemble.c:Fix signed-unsigned mismatch * win/tclWinInt.h: make tclWinProcs "const" * win/tclWin32Dll.c: * win/tclWinFCmd.c: Eliminate all internal Tcl_WinUtfToTChar * win/tclWinFile.c: and Tcl_WinTCharToUtf calls, needed * win/tclWinInit.c: for mslu support. * win/tclWinLoad.c: * win/tclWinPipe.c: * win/tclWinSerial.c: * win/.cvsignore: * compat/unicows/readme.txt: [FRQ 2819611]: Add first part of MSLU * compat/unicows/license.txt: support. * compat/unicows/unicows.lib: 2010-02-15 Donal K. Fellows * generic/tclOO.c (AllocObject, SquelchedNsFirst, ObjectRenamedTrace): * generic/tclNamesp.c (Tcl_DeleteNamespace): [Bug 2950259]: Revised the namespace deletion code to provide an additional internal callback that gets triggered early enough in namespace deletion to allow TclOO destructors to run sanely. Adjusted TclOO to take advantage of this, so making tearing down an object by killing its namespace appear to work seamlessly, which is needed for Itcl. (Note that this is not a feature that will ever be backported to 8.5, and it remains not a recommended way of deleting an object.) 2010-02-13 Donal K. Fellows * generic/tclCompCmds.c (TclCompileSwitchCmd): Divided the [switch] compiler into three pieces (after the model of [try]): a parser, an instruction-issuer for chained tests, and an instruction-issuer for jump tables. * generic/tclEnsemble.c: Split the ensemble engine out into its own file rather than keeping it mashed together with the namespace code. 2010-02-12 Jan Nijtmans * win/tcl.m4: Use -pipe for gcc on win32 * win/configure: (mingw/cygwin) (regenerated) * win/.cvsignore: Add .lib, .exp and .res here 2010-02-11 Mo DeJong * tests/list.test: Add tests for explicit \0 in a string argument to the list command. 2010-02-11 Donal K. Fellows * generic/tclIOCmd.c (Tcl_OpenObjCmd): [Bug 2949740]: Make sure that we do not try to put a NULL pipeline channel into binary mode. 2010-02-11 Mo DeJong [Bug 2826551, Patch 2948425]: Assorted regexp bugs related to -all, -line and -start options and newlines. * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): If -offset is given, treat it as the start of the line if the previous character was a newline. Fix nasty edge case where a zero length match would not advance the index. * tests/regexp.test: Add regression tests back ported from Jacl. Checks for a number of issues related to -line and newline handling. A few of tests were broken before the patch and continue to be broken, marked as knownBug. 2010-02-11 Donal K. Fellows * generic/tclOO.c (ObjectRenamedTrace): [Bug 2949397]: Prevent destructors from running on the two core class objects when the whole interpreter is being destroyed. 2010-02-09 Donal K. Fellows * generic/tclCompCmds.c (TclCompileTryCmd, IssueTryInstructions) (IssueTryFinallyInstructions): Added compiler for the [try] command. It is split into three pieces that handle the parsing of the tokens, the issuing of instructions for finally-free [try], and the issuing of instructions for [try] with finally; there are enough differences between the all cases that it was easier to split the code rather than have a single function do the whole thing. 2010-02-09 Alexandre Ferrieux * tools/genStubs.tcl: Remove dependency on 8.5+ idiom "in" in expressions. 2010-02-08 Donal K. Fellows * generic/tclZlib.c (Tcl_ZlibDeflate, Tcl_ZlibInflate): [Bug 2947783]: Make sure that the result is an unshared object before appending to it so that nothing crashes if it is shared (use in Tcl code was not affected by this, but use from C was an issue). 2010-02-06 Donal K. Fellows * generic/tclHash.c (HashStringKey): Replace Tcl's crusty old hash * generic/tclObj.c (TclHashObjKey): function with the algorithm due to Fowler, Noll and Vo. This is slightly faster (assuming the presence of hardware multiply) and has somewhat better distribution properties of the resulting hash values. Note that we only ever used the 32-bit version of the FNV algorithm; Tcl's core hash engine assumes that hash values are simple unsigned ints. ***POTENTIAL INCOMPATIBILITY*** Code that depends on hash iteration order (especially tests) may well be disrupted by this. Where a definite order is required, the fix is usually to just sort the results after extracting them from the hash. Where this is insufficient, the code that has ceased working was always wrong and was only working by chance. 2010-02-05 Donal K. Fellows * generic/tclCompCmds.c (TclCompileErrorCmd): Added compilation of the [error] command. No new bytecodes. 2010-02-05 Jan Nijtmans * tools/genStubs.tcl: Follow-up to earlier commit today: Eliminate the need for an extra Stubs Pointer for adressing a static stub table: Just change the exported table from static to MODULE_SCOPE. * generic/tclBasic.c * generic/tclOO.c * generic/tclTomMathInterface.c * generic/tcl*Decls.h (regenerated) * generic/tclStubInit.c (regenerated) * generic/tclOOStubInit.c (regenerated) * generic/tclTest.c (minor formatting) 2010-02-05 Donal K. Fellows * generic/tclVar.c: More consistency in errorcode generation. * generic/tclOOBasic.c (TclOO_Object_Destroy): Rewrote to be NRE-aware when calling destructors. Note that there is no guarantee that destructors will always be called in an NRE context; that's a feature of the 'destroy' method only. * generic/tclEncoding.c: Add 'const' to many function-internal vars that are never pointing to things that are written to. 2010-02-05 Jan Nijtmans * tools/genStubs.tcl: Follow-up to [2010-01-29] commit: prevent space within stub table function parameters if the parameter type is a pointer. * win/tclWinInt.h: Minor Formatting * generic/tcl.h: VOID -> void and other formatting * generic/tclInt.h: Minor formatting * generic/tclInt.decls: Change signature of TclNRInterpProcCore, * generic/tclOO.decls: and TclOONewProc(Instance|)MethodEx, * generic/tclProc.c: indicating that errorProc is a function, * generic/tclOOMethod.c:pointer, and other formatting * generic/tcl*Decls.h: (regenerated) * generic/tclVar.c: gcc warning(line 3703): 'pattern' may be used uninitialized in this function gcc warning(line 3788): 'matched' may be used uninitialized in this function 2010-02-04 Donal K. Fellows * generic/tclVar.c: Added more use of error-codes and reduced the stack overhead of older interfaces. (ArrayGetCmd): Stop silly crash when using a trivial pattern due to error in conversion to ensemble. (ArrayNamesCmd): Use the object RE interface for faster matching. 2010-02-03 Donal K. Fellows * generic/tclVar.c (ArrayUnsetCmd): More corrections. 2010-02-02 Donal K. Fellows * generic/tclVar.c: Turned the [array] command into a true ensemble. * generic/tclOO.c (AllocObject, MyDeleted): A slightly faster way to handle the deletion of [my] is with a standard delete callback. This is because it doesn't require an additional memory allocation during object creation. Also reduced the amount of string manipulation performed during object creation to further streamline memory handling; this is not backported to the 8.5 package as it breaks a number of abstractions. * generic/tclOOBasic.c (TclOO_Object_Destroy): [Bug 2944404]: Do not crash when a destructor deletes the object that is executing that destructor. 2010-02-01 Donal K. Fellows * generic/tclVar.c (Tcl_ArrayObjCmd): [Bug 2939073]: Stop the [array unset] command from having dangling pointer problems when an unset trace deletes the element that is going to be processed next. Many thanks to Alexandre Ferrieux for the bulk of this fix. * generic/regexec.c (ccondissect, crevdissect): [Bug 2942697]: Rework these functions so that certain pathological patterns are matched much more rapidly. Many thanks to Tom Lane for dianosing this issue and providing an initial patch. 2010-01-30 Donal K. Fellows * generic/tclCompile.c (tclInstructionTable): Bytecode instructions * generic/tclCompCmds.c (TclCompileUnsetCmd): to allow the [unset] * generic/tclExecute.c (TclExecuteByteCode): command to be compiled with the compiler being a complete compilation for all compile-time decidable uses. * generic/tclVar.c (TclPtrUnsetVar): Var reference version of the code to unset a variable. Required for INST_UNSET bytecodes. 2010-01-29 Jan Nijtmans * generic/tcl.h: [Bug 2942081]: Reverted Tcl_ThreadDataKey type change Changed some Tcl_CallFrame fields from "char *" to "void *". This saves unnecessary space on Cray's (and it's simply more correct). * tools/genStubs.tcl: No longer generate a space after "*" and immediately after a function name, so the format of function definitions in tcl*Decls.h match all other tcl*.h header files. * doc/ParseArgs.3: Change Tcl_ArgvFuncProc, Tcl_ArgvGenFuncProc * generic/tcl.h: and GetFrameInfoValueProc to be function * generic/tclInt.h: definitions, not pointers, for consistency * generic/tclOOInt.h: with all other Tcl function definitions. * generic/tclIndexObj.c: * generic/regguts.h: CONST -> const * generic/tcl.decls: Formatting * generic/tclTomMath.decls: Formatting * generic/tclDecls.h: (regenerated) * generic/tclIntDecls.h: * generic/tclIntPlatDecls.h: * generic/tclOODecls.h: * generic/tclOOIntDecls.h: * generic/tclPlatDecls.h: * generic/tclTomMathDecls.h: 2010-01-28 Donal K. Fellows * generic/tclOOBasic.c (TclOO_Object_Destroy): Move the execution of destructors to a point where they can produce an error. This will not work for all destructors, but it does mean that more failing calls of them will be caught. * generic/tclOO.c (AllocObject, MyDeletedTrace, ObjectRenamedTrace): (ObjectNamespaceDeleted): Stop various ways of getting at commands with dangling pointers to the object. Also increases the reliability of calling of destructors (though most destructors won't benefit; when an object is deleted namespace-first, its destructors are not run in a nice state as the namespace is partially gone). 2010-01-25 Jan Nijtmans * generic/tclOOStubInit.c: Remove double includes (which causes a * generic/tclOOStubLib.c: warning in CYGWIN compiles) * unix/.cvsignore: add confdefs.h 2010-01-22 Donal K. Fellows * doc/proc.n: [Bug 1970629]: Define a bit better what the current namespace of a procedure is. 2010-01-22 Jan Nijtmans * generic/tclInt.decls: Don't use DWORD and HANDLE here. * generic/tclIntPlatDecls.h: * generic/tcl.h: Revert [2009-12-21] change, instead * generic/tclPort.h: resolve the CYGWIN inclusion problems by * win/tclWinPort.h: re-arranging the inclusions at other places. * win/tclWinError.c * win/tclWinPipe.c * win/tcl.m4: Make cygwin configuration error into * win/configure.in: a warning: CYGWIN compilation works * win/configure: although there still are test failures. 2010-01-22 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Improve error code generation from some of the tailcall-related bits of TEBC. 2010-01-21 Miguel Sofer * generic/tclCompile.h: [Bug 2910748]: NRE-enable direct eval on BC * generic/tclExecute.c: spoilage. * tests/nre.test: 2010-01-19 Donal K. Fellows * doc/dict.n: [Bug 2929546]: Clarify just what [dict with] and [dict update] are doing with variables. 2010-01-18 Andreas Kupries * generic/tclIO.c (CreateScriptRecord): [Bug 2918110]: Initialize the EventScriptRecord (esPtr) fully before handing it to Tcl_CreateChannelHandler for registration. Otherwise a reflected channel calling 'chan postevent' (== Tcl_NotifyChannel) in its 'watchProc' will cause the function 'TclChannelEventScriptInvoker' to be run on an uninitialized structure. 2010-01-18 Donal K. Fellows * generic/tclStringObj.c (Tcl_AppendFormatToObj): [Bug 2932421]: Stop the [format] command from causing argument objects to change their internal representation when not needed. Thanks to Alexandre Ferrieux for this fix. 2010-01-13 Donal K. Fellows * tools/tcltk-man2html.tcl: More factoring out of special cases * tools/tcltk-man2html-utils.tcl: so that they are described outside the engine file. Now there is only one real set of special cases in there, to handle the .SO/.OP/.SE directives. 2010-01-13 Jan Nijtmans * generic/tcl.h: Fix TCL_LL_MODIFIER for Cygwin * generic/tclEnv.c: Fix CYGWIN compilation problems, * generic/tclInt.h: and remove some unnecessary * generic/tclPort.h: double includes. * generic/tclPlatDecls.h: * win/cat.c: * win/tclWinConsole.c: * win/tclWinFCmd.c: * win/tclWinFile.c: * win/tclWinPipe.c: * win/tclWinSerial.c: * win/tclWinThrd.c: * win/tclWinPort.h: Put win32 includes first * unix/tclUnixChan.c: Forgot one CONST change 2010-01-12 Donal K. Fellows * tools/tcltk-man2html.tcl: Make the generation of the list of things to process the docs from simpler and more flexible. Also factored out the lists of special cases. 2010-01-10 Jan Nijtmans * win/tclWinDde.c: VC++ 6.0 doesn't have * win/tclWinReg.c: PDWORD_PTR * win/tclWinThrd.c: Fix various minor gcc warnings. * win/tclWinTime.c: * win/tclWinConsole.c: Put channel type definitions * win/tclWinChan.c: in static const memory * win/tclWinPipe.c: * win/tclWinSerial.c: * win/tclWinSock.c: * generic/tclIOGT.c: * generic/tclIORChan.c: * generic/tclIORTrans.c: * unix/tclUnixChan.c: * unix/tclUnixPipe.c: * unix/tclUnixSock.c: * unix/configure: (regenerated with autoconf 2.59) * tests/info.test: Make test independant from tcltest implementation. 2010-01-10 Donal K. Fellows * tests/namespace.test (namespace-51.17): [Bug 2898722]: Demonstrate that there are still bugs in the handling of resolution epochs. This bug is not yet fixed. * tools/tcltk-man2html.tcl: Split the man->html converter into * tools/tcltk-man2html-utils.tcl: two pieces for easier maintenance. Also made it much less verbose in its printed messages by default. 2010-01-09 Donal K. Fellows * tools/tcltk-man2html.tcl: Added basic support for building the docs for contributed packages into the HTML versions. Prompted by question on Tcler's Chat by Tom Krehbiel. Note that there remain problems in the documentation generated due to errors in the contributed docs. 2010-01-05 Don Porter * generic/tclPathObj.c (TclPathPart): [Bug 2918610]: Correct * tests/fileName.test (filename-14.31): inconsistency between the string rep and the intrep of a path value created by [file rootname]. Thanks to Vitaly Magerya for reporting. 2010-01-03 Donal K. Fellows * unix/tcl.m4 (SC_CONFIG_CFLAGS): [Bug 1636685]: Use the configuration for modern FreeBSD suggested by the FreeBSD porter. 2010-01-03 Miguel Sofer * generic/tclBasic.c: [Bug 2724403]: Fix leak of coroutines on * generic/tclCompile.h: namespace deletion. Added a test for this * generic/tclNamesp.c: leak, and also a test for leaks on namespace * tests/coroutine.test: deletion. * tests/namespace.test: 2009-12-30 Donal K. Fellows * library/safe.tcl (AliasSource): [Bug 2923613]: Make the safer * tests/safe.test (safe-8.9): [source] handle a [return] at the end of the file correctly. 2009-12-30 Miguel Sofer * library/init.tcl (unknown): [Bug 2824981]: Fix infinite recursion of ::unknown when [set] is undefined. 2009-12-29 Donal K. Fellows * generic/tclHistory.c (Tcl_RecordAndEvalObj): Reduce the amount of allocation and deallocation of memory by caching objects in the interpreter assocData table. * generic/tclObj.c (Tcl_GetCommandFromObj): Rewrite the logic so that it does not require making assignments part way through an 'if' condition, which was deeply unclear. * generic/tclInterp.c (Tcl_MakeSafe): [Bug 2895741]: Make sure that the min() and max() functions are supported in safe interpreters. 2009-12-29 Pat Thoyts * generic/tclBinary.c: [Bug 2922555]: Handle completely invalid input * tests/binary.test: to the decode methods. 2009-12-28 Donal K. Fellows * unix/Makefile.in (trace-shell, trace-test): [FRQ 1083288]: Added targets to allow easier tracing of shell and test invokations. * unix/configure.in: [Bug 942170]: Detect the st_blocks field of * generic/tclCmdAH.c (StoreStatData): 'struct stat' correctly. * generic/tclFileName.c (Tcl_GetBlocksFromStat): * generic/tclIOUtil.c (Tcl_Stat): * generic/tclInterp.c (TimeLimitCallback): [Bug 2891362]: Ensure that * tests/interp.test (interp-34.13): the granularity ticker is reset when we check limits because of the time limit event firing. 2009-12-27 Donal K. Fellows * doc/namespace.n (SCOPED SCRIPTS): [Bug 2921538]: Updated example to not be quite so ancient. 2009-12-25 Jan Nijtmans * generic/tclCmdMZ.c: CONST -> const * generic/tclParse.c 2009-12-23 Donal K. Fellows * library/safe.tcl (AliasSource, AliasExeName): [Bug 2913625]: Stop information about paths from leaking through [info script] and [info nameofexecutable]. 2009-12-23 Jan Nijtmans * unix/tcl.m4: Install libtcl8.6.dll in bin directory * unix/Makefile.in: * unix/configure: (regenerated) 2009-12-22 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LsortObjCmd): [Bug 2918962]: Stop crash when -index and -stride are used together. 2009-12-21 Jan Nijtmans * generic/tclThreadStorage.c: Fix gcc warning, using gcc-4.3.4 on cygwin: missing initializer * generic/tclOOInt.h: Prevent conflict with DUPLICATE definition in WINAPI's nb30.h * generic/rege_dfa.c: Fix macro conflict on CYGWIN: don't use "small". * generic/tcl.h: Include before on CYGWIN * generic/tclPathObj.c * generic/tclPort.h * tests/env.test: Don't unset WINDIR and TERM, it has a special meaning on CYGWIN (both in UNIX and WIN32 mode!) * generic/tclPlatDecls.h: Include through tclPlatDecls.h * win/tclWinPort.h: stricmp -> strcasecmp * win/tclWinDde.c: _wcsicmp -> wcscasecmp * win/tclWinFile.c * win/tclWinPipe.c * win/tclWinSock.c * unix/tcl.m4: Add dynamic loading support to CYGWIN * unix/configure (regenerated) * unix/Makefile.in 2009-12-19 Miguel Sofer * generic/tclBasic.c: [Bug 2917627]: Fix for bad cmd resolution by * tests/coroutine.test: coroutines. Thanks to schelte for finding it. 2009-12-16 Donal K. Fellows * library/safe.tcl (::safe::AliasGlob): Upgrade to correctly support a larger fraction of [glob] functionality, while being stricter about directory management. 2009-12-11 Jan Nijtmans * generic/tclTest.c: Fix gcc warning: ignoring return value of * unix/tclUnixNotify.c: "write", declared with attribute * unix/tclUnixPipe.c: warn_unused_result. * generic/tclInt.decls: CONSTify functions TclpGetUserHome and * generic/tclIntDecls.h:TclSetPreInitScript (TIP #27) * generic/tclInterp.c: * win/tclWinFile.c: * unix/tclUnixFile.c: 2009-12-16 Donal K. Fellows * doc/tm.n: [Bug 1911342]: Formatting rewrite to avoid bogus crosslink to the list manpage when generating HTML. * library/msgcat/msgcat.tcl (Init): [Bug 2913616]: Do not use platform tests that are not needed and which don't work in safe interpreters. 2009-12-14 Donal K. Fellows * doc/file.n (file tempfile): [Bug 2388866]: Note that this only ever creates files on the native filesystem. This is a design feature. 2009-12-13 Miguel Sofer * generic/tclBasic.c: Release TclPopCallFrame() from its * generic/tclExecute.c: tailcall-management duties * generic/tclNamesp.c: * generic/tclBasic.c: Moving TclBCArgumentRelease call from * generic/tclExecute.c: TclNRTailcallObjCmd to TEBC, so that the pairing of the Enter and Release calls is clearer. 2009-12-12 Donal K. Fellows * generic/tclTest.c (TestconcatobjCmd): [Bug 2895367]: Stop memory leak when testing. We don't need extra noise of this sort when tracking down real problems! 2009-12-11 Jan Nijtmans * generic/tclBinary.c: Fix gcc warning, using gcc-4.3.4 on cygwin * generic/tclCompExpr.c:warning: array subscript has type 'char' * generic/tclPkg.c: * libtommath/bn_mp_read_radix.c: * win/makefile.vc: [Bug 2912773]: Revert to version 1.203 * unix/tclUnixCompat.c: Fix gcc warning: signed and unsigned type in conditional expression. 2009-12-11 Donal K. Fellows * tools/tcltk-man2html.tcl (long-toc, cross-reference): [FRQ 2897296]: Added cross links to sections within manual pages. 2009-12-11 Miguel Sofer * generic/tclBasic.c: [Bug 2806407]: Full nre-enabling of coroutines * generic/tclExecute.c: * generic/tclBasic.c: Small cleanup * generic/tclExecute.c: Fix panic in http11.test caused by buggy earlier commits in coroutine management. 2009-12-10 Andreas Kupries * generic/tclObj.c (TclContinuationsEnter): [Bug 2895323]: Updated comments to describe when the function can be entered for the same Tcl_Obj* multiple times. This is a continuation of the 2009-11-10 entry where a memory leak was plugged, but where not sure if that was just a band-aid to paper over some other error. It isn't, this is a legal situation. 2009-12-10 Miguel Sofer * generic/tclBasic.c: Reducing the # of moving parts for coroutines * generic/tclExecute.c: by delegating more to tebc; eliminate the special coroutine CallFrame. 2009-12-09 Andreas Kupries * generic/tclIO.c: [Bug 2901998]: Applied Alexandre Ferrieux's patch fixing the inconsistent buffered I/O. Tcl's I/O now flushes buffered output before reading, discards buffered input before writing, etc. 2009-12-09 Miguel Sofer * generic/tclBasic.c: Ensure right lifetime of varFrame's (objc,objv) for coroutines. * generic/tclExecute.c: Code regrouping 2009-12-09 Donal K. Fellows * generic/tclBasic.c: Added some of the missing setting of errorcode values. 2009-12-08 Miguel Sofer * generic/tclExecute.c (TclStackFree): Improved panic msg. 2009-12-08 Miguel Sofer * generic/tclBasic.c: Partial nre-enabling of coroutines. The * generic/tclExecute.c: initial call still requires its own * generic/tclInt.h: instance of tebc, but on resume coros can execute in the caller's tebc. * generic/tclExecute.c (TEBC): Silence warning about pcAdjustment. 2009-12-08 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Make the dict opcodes more sparing in their use of C variables, to reduce size of TEBC activiation record a little bit. 2009-12-07 Miguel Sofer * generic/tclExecute.c (TEBC): Grouping "slow" variables into structs, to reduce register pressure and help the compiler with variable allocation. 2009-12-07 Miguel Sofer * generic/tclExecute.c: Start cleaning the TEBC stables * generic/tclInt.h: * generic/tclCmdIL.c: [Bug 2910094]: Fix by aku * tests/coroutine.test: * generic/tclBasic.c: Arrange for [tailcall] to be created with the other builtins: was being created in a separate call, leftover from pre-tip days. 2009-12-07 Don Porter * generic/tclStrToD.c: [Bug 2902010]: Correct conditional compile directives to better detect the toolchain that needs extra work for proper underflow treatment instead of merely detecting the MIPS platform. 2009-12-07 Miguel Sofer * generic/tclBasic.c: [Patch 2910056]: Add ::tcl::unsupported::yieldTo * generic/tclInt.h: 2009-12-07 Donal K. Fellows * generic/tclCmdMZ.c (TryPostBody): [Bug 2910044]: Close off memory leak in [try] when a variable-free handler clause is present. 2009-12-05 Miguel Sofer * generic/tclBasic.c: Small changes for clarity in tailcall * generic/tclExecute.c: and coroutine code. * tests/coroutine.test: * tests/tailcall.test: Remove some old unused crud; improved the stack depth tests. * generic/tclBasic.c: Fixed things so that you can tailcall * generic/tclNamesp.c: properly out of a coroutine. * tests/tailcall.test: * generic/tclInterp.c: Fixed tailcalls for same-interp aliases (no test) 2009-12-03 Donal K. Fellows * library/safe.tcl (::safe::AliasEncoding): Make the safe encoding command behave more closely like the unsafe one (for safe ops). (::safe::AliasGlob): [Bug 2906841]: Clamp down on evil use of [glob] in safe interpreters. * tests/safe.test: Rewrite to use tcltest2 better. 2009-12-02 Jan Nijtmans * tools/genStubs.tcl: Add support for win32 CALLBACK functions and remove obsolete "emitStubs" and "genStubs" functions. * win/Makefile.in: Use tcltest86.dll for all tests, and add .PHONY rules to preemptively stop trouble that plagued Tk from hitting Tcl too. 2009-11-30 Jan Nijtmans * generic/tcl.h: Don't use EXPORT for Tcl_InitStubs * win/Makefile.in: Better dependancies in case of static build. 2009-11-30 Donal K. Fellows * doc/Tcl.n: [Bug 2901433]: Improved description of expansion to mention that it is using list syntax. 2009-11-27 Kevin B. Kenny * win/tclAppInit.c (Tcl_AppInit): [Bug 2902965]: Reverted Jan's change that added a call to Tcl_InitStubs. The 'tclsh' and 'tcltest' programs are providers, not consumers of the Stubs table, and should not link with the Stubs library, but only with the main Tcl library. (In any case, the presence of Tcl_InitStubs broke the build.) 2009-11-27 Donal K. Fellows * doc/BoolObj.3, doc/Class.3, doc/CrtChannel.3, doc/DictObj.3: * doc/DoubleObj.3, doc/Ensemble.3, doc/Environment.3: * doc/FileSystem.3, doc/Hash.3, doc/IntObj.3, doc/Limit.3: * doc/Method.3, doc/NRE.3, doc/ObjectType.3, doc/PkgRequire.3: * doc/SetChanErr.3, doc/SetResult.3: [Patch 2903921]: Many small spelling fixes from Larry Virden. BUMP VERSION OF TCLOO TO 0.6.2. Too many people need accumulated small versions and bugfixes, so the version-bump removes confusion. * generic/tclOOBasic.c (TclOO_Object_LinkVar): [Bug 2903811]: Remove unneeded restrictions on who can usefully call this method. 2009-11-26 Donal K. Fellows * unix/Makefile.in: Add .PHONY rules and documentation to preemptively stop trouble that plagued Tk from hitting Tcl too, and to make the overall makefile easier to understand. Some reorganization too to move related rules closer together. 2009-11-26 Jan Nijtmans * win/Makefile.in: [Bug 2902965]: Fix stub related changes that * win/makefile.vc: caused tclkit build to break. * win/tclAppInit.c * unix/tcl.m4 * unix/Makefile.in * unix/tclAppInit.c * unix/configure: (regenerated) 2009-11-25 Kevin B. Kenny * win/Makefile.in: Added a 'test-tcl' rule that is identical to 'test' except that it does not go spelunking in 'pkgs/'. (This rule has existed in unix/Makefile.in for some time.) 2009-11-25 Stuart Cassoff * unix/configure.in: [Patch 2892871]: Remove unneeded * unix/tcl.m4: AC_STRUCT_TIMEZONE and use * unix/tclConfig.h.in: AC_CHECK_MEMBERS([struct stat.st_blksize]) * unix/tclUnixFCmd.c: instead of AC_STRUCT_ST_BLKSIZE. * unix/configure: Regenerated with autoconf-2.59. 2009-11-24 Andreas Kupries * library/tclIndex: Manually redone the part of tclIndex dealing with safe.tcl and tm.tcl. This part passes the testsuite. Note that automatic regeneration of this part is not possible because it wrongly puts 'safe::Setup' on the list, and wrongly leaves out 'safe::Log' which is more dynamically created than the generator expects. Further note that the file "clock.tcl" is explicitly loaded by "init.tcl", the first time the clock command is invoked. The relevant code can be found at line 172ff, roughly, the definition of the procedure 'clock'. This means none of the procedures of this file belong in the tclIndex. Another indicator that automatic regeneration of tclIndex is ill-advised. 2009-11-24 Donal K. Fellows * generic/tclOO.c (FinalizeAlloc, Tcl_NewObjectInstance): [Bug 2903011]: Make it an error to destroy an object in a constructor, and also make sure that an object is not deleted twice in the error case. 2009-11-24 Pat Thoyts * tests/fCmd.test: [Bug 2893771]: Teach [file stat] to handle locked * win/tclWinFile.c: files so that [file exists] no longer lies. 2009-11-23 Kevin Kenny * tests/fCmd.test (fCmd-30.1): Changed registry location of the 'My Documents' folder to the one that's correct for Windows 2000, XP, Server 2003, Vista, Server 2008, and Windows 7. (See http://support.microsoft.com/kb/310746) 2009-11-23 Jan Nijtmans * win/tclWinDde.c: #undef STATIC_BUILD, in order to make sure * win/tclWinReg.c: that Xxxxx_Init is always exported even when * generic/tclTest.c: Tcl is built static (otherwise we cannot create a DLL). * generic/tclThreadTest.c: Make all functions static, except TclThread_Init. * tests/fCmd.test: Enable fCmd-30.1 when registry is available. * win/tcl.m4: Fix ${SHLIB_LD_LIBS} definition, fix conflicts * win/Makefile.in: Simplifications related to tcl.m4 changes. * win/configure.in: Between static libraries and import library on windows. * win/configure: (regenerated) * win/makefile.vc: Add stub library to necessary link lines. 2009-11-23 Kevin B. Kenny * generic/tclThreadTest.c (NewTestThread): [Bug 2901803]: Further machinations to get NewTestThread actually to launch the thread, not just compile. 2009-11-22 Donal K. Fellows * generic/tclThreadTest.c (NewTestThread): [Bug 2901803]: Fix small error in function naming which blocked a threaded test build. 2009-11-19 Jan Nijtmans * win/Makefile.in: Create tcltest86.dll as dynamic Tcltest package. * generic/tclTest.c: Remove extraneous prototypes, follow-up to * generic/tclTestObj.c: [Bug 2883850] * tests/chanio.test: Test-cases for fixed [Bug 2849797] * tests/io.test: * tests/safe.test: Fix safe-10.1 and safe-10.4 test cases, making the wrong assumption that Tcltest is a static package. * generic/tclEncoding.c:[Bug 2857044]: Updated freeIntRepProc routines * generic/tclVar.c: so that they set the typePtr field to NULL so that the Tcl_Obj is not left in an inconsistent state. * unix/tcl.m4: [Patch 2883533]: tcl.m4 support for Haiku OS * unix/configure: autoconf-2.59 2009-11-19 Don Porter * unix/tclAppInit.c: [Bug 2883850, 2900542]: Repair broken build of * win/tclAppInit.c: the tcltest executable. 2009-11-19 Donal K. Fellows * library/auto.tcl (tcl_findLibrary): * library/clock.tcl (MakeUniquePrefixRegexp, MakeParseCodeFromFields) (SetupTimeZone, ProcessPosixTimeZone): Restored the use of a literal * library/history.tcl (HistAdd): 'then' when following a multi- * library/safe.tcl (interpConfigure): line test expresssion. It's an * library/tm.tcl (UnknownHandler): aid to readability then. 2009-11-19 Jan Nijtmans * generic/tclInt.h: Make all internal initialization * generic/tclTest.c: routines MODULE_SCOPE * generic/tclTestObj.c: * generic/tclTestProcBodyObj.c: * generic/tclThreadTest.c: * unix/Makefile.in: Fix [Bug 2883850]: pkgIndex.tcl doesn't * unix/tclAppInit.c: get created with static Tcl build * unix/tclXtTest.c: * unix/tclXtNotify.c: * unix/tclUnixTest.c: * win/Makefile.in: * win/tcl.m4: * win/configure: (regenerated) * win/tclAppInit.c: * win/tclWinDde.c: Always compile with Stubs. * win/tclWinReg.c: * win/tclWinTest.c: 2009-11-18 Jan Nijtmans * doc/CrtChannel.3: [Bug 2849797]: Fix channel name inconsistences * generic/tclIORChan.c: as suggested by DKF. * generic/tclIO.c: Minor *** POTENTIAL INCOMPATIBILITY *** because Tcl_CreateChannel() and derivatives now sometimes ignore their "chanName" argument. * generic/tclAsync.c: Eliminate various gcc warnings (with -Wextra) * generic/tclBasic.c * generic/tclBinary.c * generic/tclCmdAH.c * generic/tclCmdIL.c * generic/tclCmdMZ.c * generic/tclCompile.c * generic/tclDate.c * generic/tclExecute.c * generic/tclDictObj.c * generic/tclIndexObj.c * generic/tclIOCmd.c * generic/tclIOUtil.c * generic/tclIORTrans.c * generic/tclOO.c * generic/tclZlib.c * generic/tclGetDate.y * win/tclWinInit.c * win/tclWinChan.c * win/tclWinConsole.c * win/tclWinNotify.c * win/tclWinReg.c * library/auto.tcl: Eliminate "then" keyword * library/clock.tcl * library/history.tcl * library/safe.tcl * library/tm.tcl * library/http/http.tcl: Eliminate unnecessary spaces * library/http1.0/http.tcl * library/msgcat/msgcat.tcl * library/opt/optparse.tcl * library/platform/platform.tcl * tools/tcltk-man2html.tcl * tools/tclZIC.tcl * tools/tsdPerf.c 2009-11-17 Andreas Kupries * unix/tclUnixChan.c (TtyParseMode): Partial undo of Donal's tidy-up from a few days ago (2009-11-9, not in ChangeLog). It seems that strchr is apparently a macro on AIX and reacts badly to pre-processor directives in its arguments. 2009-11-16 Alexandre Ferrieux * generic/tclEncoding.c: [Bug 2891556]: Fix and improve test to * generic/tclTest.c: detect similar manifestations in the future. * tests/encoding.test: Add tcltest support for finalization. 2009-11-15 Mo DeJong * win/tclWinDde.c: Avoid gcc compiler warning by explicitly casting DdeCreateStringHandle argument. 2009-11-12 Andreas Kupries * generic/tclIO.c (CopyData): [Bug 2895565]: Dropped bogosity which * tests/io.test: used the number of _written_ bytes or character to update the counters for the read bytes/characters. New test io-53.11. This is a forward port from the 8.5 branch. 2009-11-11 Don Porter * generic/tclClock.c (TclClockInit): Do not create [clock] support commands in safe interps. 2009-11-11 Jan Nijtmans * library/http/http.tcl (http::geturl): [Bug 2891171]: URL checking too strict when using multiple question marks. * tests/http.test * library/http/pkgIndex.tcl: Bump to http 2.8.2 * unix/Makefile.in: * win/Makefile.in: 2009-11-11 Alexandre Ferrieux * generic/tclIO.c: Fix [Bug 2888099] (close discards ENOSPC error) by saving the errno from the first of two FlushChannel()s. Uneasy to test; might need specific channel drivers. Four-hands with aku. 2009-11-10 Pat Thoyts * tests/winFCmd.test: Cleanup directories that have been set chmod 000. On Windows7 and Vista we really have no access and these were getting left behind. A few tests were changed to reflect the intent of the test where setting a directory chmod 000 should prevent any modification. This restriction was ignored on XP but is honoured on Vista 2009-11-10 Andreas Kupries * generic/tclBasic.c: Plug another leak in TCL_EVAL_DIRECT evaluation. Forward port from Tcl 8.5 branch, change by Don Porter. * generic/tclObj.c: [Bug 2895323]: Plug memory leak in TclContinuationsEnter(). Forward port from Tcl 8.5 branch, change by Don Porter. 2009-11-09 Stuart Cassoff * win/README: [bug 2459744]: Removed outdated Msys + Mingw info. 2009-11-09 Andreas Kupries * generic/tclBasic.c (TclEvalObjEx): Moved the #280 decrement of refCount for the file path out of the branch after the whole conditional, closing a memory leak. Added clause on structure type to prevent seg.faulting. Forward port from valgrinding the Tcl 8.5 branch. * tests/info.test: Resolve ambiguous resolution of variable "res". Forward port from 8.5 2009-11-08 Donal K. Fellows * doc/string.n (bytelength): Noted that this command is not a good thing to use, and suggested a better alternatve. Also factored out the description of the indices into its own section. 2009-11-07 Pat Thoyts * tests/fCmd.test: [Bug 2891026]: Exclude tests using chmod 555 directories on vista and win7. The current user has access denied and so cannot rename the directory without admin privileges. 2009-11-06 Andreas Kupries * library/safe.tcl (::safe::Setup): Added documentation of the contents of the state array. Also killed the 'InterpState' procedure with its upleveled variable/upvar combination, and replaced all uses with 'namespace upvar'. 2009-11-05 Andreas Kupries * library/safe.tcl: A series of patches which bring the SafeBase up to date with code guidelines, Tcl's features, also eliminating a number of inefficiencies along the way. (1) Changed all procedure names to be fully qualified. (2) Moved the procedures out of the namespace eval. Kept their locations. IOW, broke the namespace eval apart into small sections not covering the procedure definitions. (3) Reindented the code. Just lots of whitespace changes. Functionality unchanged. (4) Moved the multiple namespace eval's around. Command export at the top, everything else (var decls, argument parsing setup) at the bottom. (5) Moved the argument parsing setup into a procedure called when the code is loaded. Easier management of temporary data. (6) Replaced several uses of 'Set' with calls to the new procedure 'InterpState' and direct access to the per-slave state array. (7) Replaced the remaining uses of 'Set' and others outside of the path/token handling, and deleted a number of procedures related to state array access which are not used any longer. (8) Converted the path token system to cache normalized paths and path <-> token conversions. Removed more procedures not used any longer. Removed the test cases 4.3 and 4.4 from safe.test. They were testing the now deleted command "InterpStateName". (9) Changed the log command setup so that logging is compiled out completely when disabled (default). (10) Misc. cleanup. Inlined IsInterp into CheckInterp, its only user. Consistent 'return -code error' for error reporting. Updated to use modern features (lassign, in/ni, dicts). The latter are used to keep a reverse path -> token map and quicker check of existence. (11) Fixed [Bug 2854929]: Recurse into all subdirs under all TM root dirs and put them on the access path. 2009-11-02 Kevin B. Kenny * library/tzdata/Asia/Novokuznetsk: New tzdata locale for Kemerovo oblast', which now keeps Novosibirsk time and not Kranoyarsk time. * library/tzdata/Asia/Damascus: Syrian DST changes. * library/tzdata/Asia/Hong_Kong: Hong Kong historic DST corrections. Olson tzdata2009q. 2009-11-02 Donal K. Fellows * doc/object.n (DESCRIPTION): Substantive revision to make it clearer what the fundamental semantics of an object actually are. 2009-11-01 Joe Mistachkin * doc/Cancel.3: Minor cosmetic fixes. * win/makefile.vc: Make htmlhelp target work again. An extra set of double quotes around the definition of the HTML help compiler tool appears to be required. Previously, there was one set of double quotes around the definition of the tool and one around the actual invocation. This led to confusion because it was the only such tool path to include double quotes around its invocation. Also, it was somewhat inflexible in the event that somebody needed to override the tool command to include arguments. Therefore, even though it may look "wrong", there are now two double quotes on either side of the tool path definition. This fixes the problem that currently prevents the htmlhelp target from building and maintains flexibility in case somebody needs to override it via the command line or an environment variable. 2009-11-01 Joe English * doc/Eval.3, doc/Cancel.3: Move TIP#285 routines out of Eval.3 into their own manpage. 2009-10-31 Donal K. Fellows * generic/tclBasic.c (ExprRoundFunc): [Bug 2889593]: Correctly report the expected number of arguments when generating an error for round(). 2009-10-30 Pat Thoyts * tests/tcltest.test: When creating the notwritabledir we deny the current user access to delete the file. We must grant this right when we cleanup. Required on Windows 7 when the user does not automatically have administrator rights. 2009-10-29 Don Porter * generic/tcl.h: Changed the typedef for the mp_digit type from: typedef unsigned long mp_digit; to: typedef unsigned int mp_digit; For 32-bit builds where "long" and "int" are two names for the same thing, this is no change at all. For 64-bit builds, though, this causes the dp[] array of an mp_int to be made up of 32-bit elements instead of 64-bit elements. This is a huge improvement because details elsewhere in the mp_int implementation cause only 28 bits of each element to be actually used storing number data. Without this change bignums are over 50% wasted space on 64-bit systems. [Bug 2800740]. ***POTENTIAL INCOMPATIBILITY*** For 64-bit builds, callers of routines with (mp_digit) or (mp_digit *) arguments *will*, and callers of routines with (mp_int *) arguments *may* suffer both binary and stubs incompatibilities with Tcl releases 8.5.0 - 8.5.7. Such possibilities should be checked, and if such incompatibilities are present, suitable [package require] requirements on the Tcl release should be put in place to keep such built code [load]-ing only in Tcl interps that are compatible. 2009-10-29 Donal K. Fellows * tests/dict.test: Make variable-clean and simplify tests by utilizing the fact that dictionaries have defined orders. * generic/tclZlib.c (TclZlibCmd): Remove accidental C99-ism which reportedly makes the AIX native compiler choke. 2009-10-29 Kevin B. Kenny * library/clock.tcl (LocalizeFormat): * tests/clock.test (clock-67.1): [Bug 2819334]: Corrected a problem where '%%' followed by a letter in a format group could expand recursively: %%R would turn into %%H:%M:%S 2009-10-28 Don Porter * generic/tclLiteral.c: [Bug 2888044]: Fixed 2 bugs. * tests/info.test: First, as noted in the comments of the TclCleanupLiteralTable routine, since the teardown of the intrep of one Tcl_Obj can cause the teardown of others in the same table, the full table cleanup must be done with care, but the code did not contain the same care demanded in the comment. Second, recent additions to the info.test file had poor hygiene, leaving an array variable ::a lying around, which breaks later interp.test tests during a -singleproc 1 run of the test suite. 2009-10-28 Kevin B. Kenny * tests/fileName.test (fileName-20.[78]): Corrected poor test hygiene (failure to save and restore the working directory) that caused these two tests to fail on Windows (and [Bug 2806250] to be reopened). 2009-10-27 Don Porter * generic/tclPathObj.c: [Bug 2884203]: Missing refcount on cached normalized path caused crashes. 2009-10-27 Kevin B. Kenny * library/clock.tcl (ParseClockScanFormat): [Bug 2886852]: Corrected a problem where [clock scan] didn't load the timezone soon enough when processing a time format that lacked a complete date. * tests/clock.test (clock-66.1): Added a test case for the above bug. * library/tzdata/America/Argentina/Buenos_Aires: * library/tzdata/America/Argentina/Cordoba: * library/tzdata/America/Argentina/San_Luis: * library/tzdata/America/Argentina/Tucuman: New DST rules for Argentina. (Olson's tzdata2009p.) 2009-10-26 Don Porter * unix/Makefile.in: Remove $(PACKAGE).* and prototype from the `make distclean` target. Completes 2009-10-20 commit. 2009-10-24 Kevin B. Kenny * library/clock.tcl (ProcessPosixTimeZone): Corrected a regression in the fix to [Bug 2207436] that caused [clock] to apply EU daylight saving time rules in the US. Thanks to Karl Lehenbauer for reporting this regression. * tests/clock.test (clock-52.4): Added a regression test for the above bug. * library/tzdata/Asia/Dhaka: * library/tzdata/Asia/Karachi: New DST rules for Bangladesh and Pakistan. (Olson's tzdata2009o.) 2009-10-23 Andreas Kupries * generic/tclIO.c (FlushChannel): Skip OutputProc for low-level 0-length writes. When closing pipes which have already been closed not skipping leads to spurious SIG_PIPE signals. Reported by Mikhail Teterin . 2009-10-22 Donal K. Fellows * generic/tclOOBasic.c (TclOO_Object_VarName): [Bug 2883857]: Allow the passing of array element names through this method. 2009-10-21 Donal K. Fellows * generic/tclPosixStr.c: [Bug 2882561]: Work around oddity on Haiku OS where SIGSEGV and SIGBUS are the same value. * generic/tclTrace.c (StringTraceProc): [Bug 2881259]: Added back cast to work around silly bug in MSVC's handling of auto-casting. 2009-10-20 Don Porter * unix/Makefile.in: Removed the long outdated and broken targets package-* that were for building Solaris packages. Appears that the pieces needed for these targets to function have never been present in the current era of Tcl development and belong completely to Tcl pre-history. 2009-10-19 Don Porter * generic/tclIO.c: [Patch 2107634]: Revised ReadChars and FilterInputBytes routines to permit reads to continue up to the string limits of Tcl values. Before revisions, large read attempts could panic when as little as half the limiting value length was reached. Thanks to Sean Morrison and Bob Parker for their roles in the fix. 2009-10-18 Joe Mistachkin * generic/tclObj.c (TclDbDumpActiveObjects, TclDbInitNewObj) (Tcl_DbIncrRefCount, Tcl_DbDecrRefCount, Tcl_DbIsShared): [Bug 2871908]: Enforce separation of concerns between the lineCLPtr and objThreadMap thread specific data members. 2009-10-18 Joe Mistachkin * tests/thread.test (thread-4.[345]): [Bug 1565466]: Correct tests to save their error state before the final call to threadReap just in case it triggers an "invalid thread id" error. This error can occur if one or more of the target threads has exited prior to the attempt to send it an asynchronous exit command. 2009-10-17 Donal K. Fellows * generic/tclVar.c (UnsetVarStruct, TclDeleteNamespaceVars) (TclDeleteCompiledLocalVars, DeleteArray): * generic/tclTrace.c (Tcl_UntraceVar2): [Bug 2629338]: Stop traces that are deleted part way through (a feature used by tdom) from causing freed memory to be accessed. 2009-10-08 Donal K. Fellows * generic/tclDictObj.c (DictIncrCmd): [Bug 2874678]: Don't leak any bignums when doing [dict incr] with a value. * tests/dict.test (dict-19.3): Memory leak detection code. 2009-10-07 Andreas Kupries * generic/tclObj.c: [Bug 2871908]: Plug memory leaks of objThreadMap and lineCLPtr hashtables. Also make the names of the continuation line information initialization and finalization functions more consistent. Patch supplied by Joe Mistachkin . * generic/tclIORChan.c (ErrnoReturn): Replace hardwired constant 11 with proper errno #define, EAGAIN. What was I thinking? The BSD's have a different errno assignment and break with the hardwired number. Reported by emiliano on the chat. 2009-10-06 Don Porter * generic/tclInterp.c (SlaveEval): Agressive stomping of internal reps was added as part of the NRE patch of 2008-07-13. This doesn't appear to actually be needed, and it hurts quite a bit when large lists lose their intreps and require reparsing. Thanks to Ashok Nadkarni for reporting the problem. * generic/tclTomMathInt.h (new): Public header tclTomMath.h had * generic/tclTomMath.h: dependence on private headers, breaking use * generic/tommath.h: by extensions [Bug 1941434]. 2009-10-05 Andreas Kupries * library/safe.tcl (AliasGlob): Fixed conversion of catch to try/finally, it had an 'on ok msg' branch missing, causing a silent error immediately, and bogus glob results, breaking search for Tcl modules. 2009-10-04 Daniel Steffen * macosx/tclMacOSXBundle.c: [Bug 2569449]: Workaround CF memory * unix/tclUnixInit.c: managment bug in Mac OS X 10.4 & earlier. 2009-10-02 Kevin B. Kenny * library/tzdata/Africa/Cairo: * library/tzdata/Asia/Gaza: * library/tzdata/Asia/Karachi: * library/tzdata/Pacific/Apia: Olson's tzdata2009n. 2009-09-29 Don Porter * generic/tclDictObj.c: [Bug 2857044]: Updated freeIntRepProc * generic/tclExecute.c: routines so that they set the typePtr * generic/tclIO.c: field to NULL so that the Tcl_Obj is * generic/tclIndexObj.c: not left in an inconsistent state. * generic/tclInt.h: * generic/tclListObj.c: * generic/tclNamesp.c: * generic/tclOOCall.c: * generic/tclObj.c: * generic/tclPathObj.c: * generic/tclProc.c: * generic/tclRegexp.c: * generic/tclStringObj.c: * generic/tclAlloc.c: Cleaned up various routines in the * generic/tclCkalloc.c: call stacks for memory allocation to * generic/tclInt.h: guarantee that any size values computed * generic/tclThreadAlloc.c: are within the domains of the routines they get passed to. [Bugs 2557696 and 2557796]. 2009-09-28 Don Porter * generic/tclCmdMZ.c: Replaced TclProcessReturn() calls with * tests/error.test: Tcl_SetReturnOptions() calls as a simple fix for [Bug 2855247]. Thanks to Anton Kovalenko for the report and fix. Additional fixes for other failures demonstrated by new tests. 2009-09-27 Don Porter * tests/error.test (error-15.8.*): Coverage tests illustrating flaws in the propagation of return options by [try]. 2009-09-26 Donal K. Fellows * unix/tclooConfig.sh, win/tclooConfig.sh: [Bug 2026844]: Added dummy versions of tclooConfig.sh that make it easier to build extensions against both Tcl8.5+TclOO-standalone and Tcl8.6. 2009-09-24 Don Porter TIP #356 IMPLEMENTATION * generic/tcl.decls: Promote internal routine TclNRSubstObj() * generic/tclCmdMZ.c: to public Tcl_NRSubstObj(). Still needs docs. * generic/tclCompile.c: * generic/tclInt.h: * generic/tclDecls.h: make genstubs * generic/tclStubInit.c: 2009-09-23 Miguel Sofer * doc/namespace.n: the description of [namespace unknown] failed to mention [namespace path]: fixed. Thx emiliano. 2009-09-21 Mo DeJong * tests/regexp.test: Added check for error message from unbalanced [] in regexp. Added additional simple test cases of basic regsub command. 2009-09-21 Don Porter * generic/tclCompile.c: Correct botch in the conversion of Tcl_SubstObj(). Thanks to Kevin Kenny for detection and report. 2009-09-17 Don Porter * generic/tclCompile.c: Re-implement Tcl_SubstObj() as a simple * generic/tclParse.c: wrapper around TclNRSubstObj(). This has * tests/basic.test: the effect of caching compiled bytecode in * tests/parse.test: the value to be substituted. Note that Tcl_SubstObj() now exists only for extensions. Tcl itself no longer makes any use of it. Note also that TclSubstTokens() is now reachable only by Tcl_EvalEx() and Tcl_ParseVar() so tests aiming to test its functioning needed adjustment to still have the intended effect. 2009-09-16 Alexandre Ferrieux * generic/tclObj.c: Extended ::tcl::unsupported::representation. 2009-09-11 Don Porter * generic/tclBasic.c: Completed the NR-enabling of [subst]. * generic/tclCmdMZ.c: [Bug 2314561]. * generic/tclCompCmds.c: * generic/tclCompile.c: * generic/tclInt.h: * tests/coroutine.test: * tests/parse.test: 2009-09-11 Donal K. Fellows * tests/http.test: Added in cleaning up of http tokens for each test to reduce amount of global-variable pollution. 2009-09-10 Donal K. Fellows * library/http/http.tcl (http::Event): [Bug 2849860]: Handle charset names in double quotes; some servers like generating them like that. 2009-09-07 Don Porter * generic/tclParse.c: [Bug 2850901]: Corrected line counting error * tests/into.test: in multi-command script substitutions. 2009-09-07 Daniel Steffen * generic/tclExecute.c: Fix potential uninitialized variable use and * generic/tclFCmd.c: null dereference flagged by clang static * generic/tclProc.c: analyzer. * generic/tclTimer.c: * generic/tclUtf.c: * generic/tclExecute.c: Silence false positives from clang static * generic/tclIO.c: analyzer about potential null dereference. * generic/tclScan.c: * generic/tclCompExpr.c: 2009-09-04 Don Porter * generic/tclCompCmds.c (TclCompileSubstCmd): [Bug 2314561]: * generic/tclBasic.c: Added a bytecode compiler routine for the * generic/tclCmdMZ.c: [subst] command. This is a partial solution to * generic/tclCompile.c: the need to NR-enable [subst] since bytecode * generic/tclCompile.h: execution is already NR-enabled. Two new * generic/tclExecute.c: bytecode instructions, INST_NOP and * generic/tclInt.h: INST_RETURN_CODE_BRANCH were added to support * generic/tclParse.c: the new routine. INST_RETURN_CODE_BRANCH is * tests/basic.test: likely to be useful in any future effort to * tests/info.test: add a bytecode compiler routine for [try]. * tests/parse.test: 2009-09-03 Donal K. Fellows * doc/LinkVar.3: [Bug 2844962]: Added documentation of issues relating to use of this API in a multi-threaded environment. 2009-09-01 Andreas Kupries * generic/tclIORTrans.c (ReflectInput): Remove error response to 0-result from method 'limit?' of transformations. Return the number of copied bytes instead, which is possibly nothing. The latter then triggers EOF handling in the higher layers, making the 0-result of limit? the way to inject artificial EOF's into the data stream. 2009-09-01 Don Porter * library/tcltest/tcltest.tcl: Bump to tcltest 2.3.2 after revision * library/tcltest/pkgIndex.tcl: to verbose error message. * unix/Makefile.in: * win/Makefile.in: 2009-08-27 Don Porter * generic/tclStringObj.c: [Bug 2845535]: A few more string overflow cases in [format]. 2009-08-25 Andreas Kupries * generic/tclBasic.c (Tcl_CreateInterp, Tcl_EvalTokensStandard) (Tcl_EvalEx, TclEvalEx, TclAdvanceContinuations, TclNREvalObjEx): * generic/tclCmdMZ.c (Tcl_SwitchObjCmd, TclListLines): * generic/tclCompCmds.c (*): * generic/tclCompile.c (TclSetByteCodeFromAny, TclInitCompileEnv) (TclFreeCompileEnv, TclCompileScript, TclCompileTokens): * generic/tclCompile.h (CompileEnv): * generic/tclInt.h (ContLineLoc, Interp): * generic/tclObj.c (ThreadSpecificData, ContLineLocFree) (TclThreadFinalizeObjects, TclInitObjSubsystem, TclContinuationsEnter, (TclContinuationsEnterDerived, TclContinuationsCopy, TclFreeObj) (TclContinuationsGet): * generic/tclParse.c (TclSubstTokens, Tcl_SubstObj): * generic/tclProc.c (TclCreateProc): * generic/tclVar.c (TclPtrSetVar): * tests/info.test (info-30.0-24): Extended the parser, compiler, and execution engine with code and attendant data structures tracking the position of continuation lines which are not visible in the resulting script Tcl_Obj*'s, to properly account for them while counting lines for #280. 2009-08-24 Daniel Steffen * generic/tclInt.h: Annotate Tcl_Panic as noreturn for clang static analyzer in PURIFY builds, replacing preprocessor/assert technique. * macosx/tclMacOSXNotify.c: Fix multiple issues with nested event loops when CoreFoundation notifier is running in embedded mode. (Fixes problems in TkAqua Cocoa reported by Youness Alaoui on tcl-mac) 2009-08-21 Don Porter * generic/tclFileName.c: Correct regression in [Bug 2837800] fix. * tests/fileName.test: 2009-08-20 Don Porter * generic/tclFileName.c: [Bug 2837800]: Correct the result produced by [glob */test] when * matches something like ~foo. * generic/tclPathObj.c: [Bug 2806250]: Prevent the storage of strings starting with ~ in the "tail" part (normPathPtr field) of the path intrep when PATHFLAGS != 0. This establishes the assumptions relied on elsewhere that the name stored there is a relative path. Also refactored to make an AppendPath() routine instead of the cut/paste stanzas that were littered throughout. 2009-08-20 Donal K. Fellows * generic/tclCmdIL.c (TclNRIfObjCmd): [Bug 2823276]: Make [if] NRE-safe on all arguments when interpreted. (Tcl_LsortObjCmd): Close off memory leak. 2009-08-19 Donal K. Fellows * generic/tclCmdAH.c (TclNRForObjCmd, etc.): [Bug 2823276]: Make [for] and [while] into NRE-safe commands, even when interpreted. 2009-08-18 Don Porter * generic/tclPathObj.c: [Bug 2837800]: Added NULL check to prevent * tests/fileName.test: crashes during [glob]. 2009-08-16 Jan Nijtmans * unix/dltest/pkge.c: const addition * unix/tclUnixThrd.c: Use in stead of "pthread.h" * win/tclWinDde.c: Eliminate some more gcc warnings * win/tclWinReg.c: * generic/tclInt.h: Change ForIterData, make it const-safe. * generic/tclCmdAH.c: 2009-08-12 Don Porter TIP #353 IMPLEMENTATION * doc/NRE.3: New public routine Tcl_NRExprObj() permits * generic/tcl.decls: extension commands to evaluate Tcl expressions * generic/tclBasic.c: in NR-enabled command procedures. * generic/tclCmdAH.c: * generic/tclExecute.c: * generic/tclInt.h: * generic/tclObj.c: * tests/expr.test: * generic/tclDecls.h: make genstubs * generic/tclStubInit.c: 2009-08-06 Andreas Kupries * doc/refchan.n [Bug 2827000]: Extended the implementation of * generic/tclIORChan.c: reflective channels (TIP 219, method * tests/ioCmd.test: 'read'), enabling handlers to signal EAGAIN to indicate 'no data, but not at EOF either', and other system errors. Updated documentation, extended testsuite (New test cases iocmd*-23.{9,10}). 2009-08-02 Miguel Sofer * tests/coroutine.test: fix testfile cleanup 2009-08-02 Donal K. Fellows * generic/tclObj.c (Tcl_RepresentationCmd): Added an unsupported command for reporting the representation of an object. Result string is deliberately a bit obstructive so that people are not encouraged to make code that depends on it; it's a debugging tool only! * unix/tclUnixFCmd.c (GetOwnerAttribute, SetOwnerAttribute) (GetGroupAttribute, SetGroupAttribute): [Bug 1942222]: Stop calling * unix/tclUnixFile.c (TclpGetUserHome): endpwent() and endgrent(); they've been unnecessary for ages. 2009-08-02 Jan Nijtmans * win/tclWin32Dll.c: Eliminate TclWinResetInterfaceEncodings, since it * win/tclWinInit.c: does exactly the same as TclWinEncodingsCleanup, * win/tclWinInt.h: make sure that tclWinProcs and tclWinTCharEncoding are always set and reset concurrently. * win/tclWinFCmd.c: Correct check for win95 2009-07-31 Don Porter * generic/tclStringObj.c: [Bug 2830354]: Corrected failure to * tests/format.test: grow buffer when format spec request large width floating point values. Thanks to Clemens Misch. 2009-07-26 Donal K. Fellows * library/auto.tcl (tcl_findLibrary, auto_mkindex): * library/package.tcl (pkg_mkIndex, tclPkgUnknown, MacOSXPkgUnknown): * library/safe.tcl (interpAddToAccessPath, interpDelete, AliasGlob): (AliasSource, AliasLoad, AliasEncoding): * library/tm.tcl (UnknownHandler): Simplify by swapping some [catch] gymnastics for use of [try]. 2009-07-26 Alexandre Ferrieux * tools/genStubs.tcl: Forced LF translation when generating .h's to avoid spurious diffs when regenerating on a Windows box. 2009-07-26 Jan Nijtmans * win/Makefile.in: [Bug 2827066]: msys build --enable-symbols broken * win/tcl.m4: And modified the same for unicows.dll, as a * win/configure: preparation for [Enh 2819611]. 2009-07-25 Donal K. Fellows * library/history.tcl (history): Reworked the history mechanism in terms of ensembles, rather than the ad hoc ensemble-lite mechanism used previously. 2009-07-24 Donal K. Fellows * doc/self.n (self class): [Bug 2704302]: Add some text to make it clearer how to get the name of the current object's class. 2009-07-23 Andreas Kupries * generic/tclIO.c (Tcl_GetChannelHandle): [Bug 2826248]: Do not crash * generic/tclPipe.c (FileForRedirect): for getHandleProc == NULL, this is allowed. Provide a nice error message in the bypass area. Updated caller to check the bypass for a mesage. Bug reported by Andy Sonnenburg 2009-07-23 Joe Mistachkin * generic/tclNotify.c: [Bug 2820349]: Ensure that queued events are freed once processed. 2009-07-22 Jan Nijtmans * macosx/tclMacOSXFCmd.c: CONST -> const * generic/tclGetDate.y: * generic/tclDate.c: * generic/tclLiteral.c: (char *) cast in ckfree call * generic/tclPanic.c: [Feature Request 2814786]: remove TclpPanic * generic/tclInt.h * unix/tclUnixPort.h * win/tclWinPort.h 2009-07-22 Alexandre Ferrieux * generic/tclEvent.c: [Bug 2001201 again]: Refined the 20090617 patch on [exit] streamlining, so that it now correctly calls thread exit handlers for the calling thread, including bindings in Tk. 2009-07-21 Kevin B. Kenny * library/tzdata/Asia/Dhaka: * library/tzdata/Indian/Mauritius: Olson's tzdata2009k. 2009-07-20 Donal K. Fellows * generic/tclCmdMZ.c (StringIsCmd): Reorganize so that [string is] is more efficient when parsing things that are correct, at a cost of making the empty string test slightly more costly. With this, the cost of doing [string is integer -strict $x] matches [catch {expr {$x+0}}] in the successful case, and greatly outstrips it in the failing case. 2009-07-19 Donal K. Fellows * generic/tclOO.decls, generic/tclOO.c (Tcl_GetObjectName): Expose a function for efficiently returning the current name of an object. 2009-07-18 Daniel Steffen * unix/Makefile.in: Define NDEBUG in optimized (non-symbols) build to disable NRE assert()s and threaded allocator range checks. 2009-07-16 Don Porter * generic/tclBinary.c: Removed unused variables. * generic/tclCmdIL.c: * generic/tclCompile.c: * generic/tclExecute.c: * generic/tclHash.c: * generic/tclIOUtil.c: * generic/tclVar.c: * generic/tclBasic.c: Silence compiler warnings about ClientData. * generic/tclProc.c: * generic/tclScan.c: Typo in ACCEPT_NAN configuration. * generic/tclStrToD.c: [Bug 2819200]: Set floating point control register on MIPS systems so that the gradual underflow expected by Tcl is in effect. 2009-07-15 Donal K. Fellows * generic/tclInt.h (Namespace): Added machinery to allow * generic/tclNamesp.c (many functions): reduction of memory used * generic/tclResolve.c (BumpCmdRefEpochs): by namespaces. Currently #ifdef'ed out because of compatibility concerns. * generic/tclInt.decls: Added four functions for better integration with itcl-ng. 2009-07-14 Kevin B. Kenny * generic/tclInt.h (TclNRSwitchObjCmd): * generic/tclBasic.c (builtInCmds): * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): * tests/switch.test (switch-15.1): [Bug 2821401]: Make non-bytecoded [switch] command aware of NRE. 2009-07-13 Andreas Kupries * generic/tclCompile.c (TclInitCompileEnv, EnterCmdWordIndex) (TclCleanupByteCode, TclCompileScript): * generic/tclExecute.c (TclCompileObj, TclExecuteByteCode): * tclCompile.h (ExtCmdLoc): * tclInt.h (ExtIndex, CFWordBC, CmdFrame): * tclBasic.c (DeleteInterpProc, TclArgumentBCEnter) (TclArgumentBCRelease, TclArgumentGet, SAVE_CONTEXT) (RESTORE_CONTEXT, NRCoroutineExitCallback, TclNRCoroutineObjCmd): * generic/tclCmdAH.c (TclNRForObjCmd, TclNRForIterCallback, (ForNextCallback): * generic/tclCmdMZ.c (TclNRWhileObjCmd): Extended the bytecode compiler initialization to recognize the compilation of whole files (NRE enabled 'source' command) and switch to the counting of absolute lines in that case. Further extended the bytecode compiler to track the start line in the generated information, and modified the bytecode execution to recompile an object if the location as per the calling context doesn't match the location saved in the bytecode. This part could be optimized more by using more memory to keep all possibilities which occur around, or by just adjusting the location information instead of a total recompile. Reworked the handling of literal command arguments in bytecode to be saved (compiler) and used (execution) per command (See the TCL_INVOKE_STK* instructions), and not per the whole bytecode. This, and the previous change remove the problems with location data caused by literal sharing (across whole files, but also proc bodies). Simplified the associated datastructures (ExtIndex is gone, as is the function EnterCmdWordIndex). The last change causes the hashtable 'lineLABCPtr' to be state which has to be kept per coroutine, like the CmdFrame stack. Reworked the coroutine support code to create, delete and switch the information as needed. Further reworked the tailcall command as well, it has to pop its own arguments when run in a bytecode context to keep a proper stack in 'lineLABCPtr'. Fixed the mishandling of line information in the NRE-enabled 'for' and 'while' commands introduced when both were made to share their iteration callbacks without taking into account that the loop body is found in different words of the command. Introduced a separate data structure to hold all the callback information, as we went over the limit of 4 direct client-data values for NRE callbacks. The above fixes [Bug 1605269]. 2009-07-12 Donal K. Fellows * generic/tclCmdMZ.c (StringIndexCmd, StringEqualCmd, StringCmpCmd): * generic/tclExecute.c (TclExecuteByteCode): [Bug 2637173]: Factor out * generic/tclInt.h (TclIsPureByteArray): the code to determine if * generic/tclUtil.c (TclStringMatchObj): it is safe to work with byte arrays directly, so that we get the check correct _once_. * generic/tclOOCall.c (TclOOGetCallContext): [Bug 1895546]: Changed * generic/tclOO.c (TclOOObjectCmdCore): the way that the cache is managed so that when itcl does cunning things, those cunning things can be cached properly. 2009-07-11 Donal K. Fellows * doc/vwait.n: Substantially increased the discussion of issues and work-arounds relating to nested vwaits, following discussion on the tcl-core mailing list on the topic. 2009-07-10 Pat Thoyts * tests/zlib.test: ZlibTransformClose may be called with a NULL * generic/tclZlib.c: interpreter during finalization and Tcl_SetChannelError requires a list. Added some tests to ensure error propagation from the zlib library to the interp. 2009-07-09 Pat Thoyts * tests/zlib.test: [Bug 2818131]: Added tests and fixed a typo that broke [zlib push] for deflate format. 2009-07-09 Donal K. Fellows * compat/mkstemp.c (mkstemp): [Bug 2819227]: Use rand() for random numbers as it is more portable. 2009-07-05 Donal K. Fellows * generic/tclZlib.c (ZlibTransformWatch): Correct the handling of events so that channel transforms work with things like an asynch [chan copy]. Problem reported by Pat Thoyts. 2009-07-01 Pat Thoyts * win/tclWinInt.h: [Bug 2806622]: Handle the GetUserName API call * win/tclWin32Dll.c: via the tclWinProcs indirection structure. This * win/tclWinInit.c: fixes a problem obtaining the username when the USERNAME environment variable is unset. 2009-06-30 Daniel Steffen * generic/tclInt.h: Add assert macros for clang static * generic/tclPanic.c: analyzer and redefine Tcl_Panic to * generic/tclStubInit.c: assert after panic in clang PURIFY builds. * generic/tclCmdIL.c: Add clang assert for false positive from static analyzer. 2009-06-26 Daniel Steffen * macosx/Tcl-Common.xcconfig: Update projects for Xcode 3.1 and * macosx/Tcl.xcode/*: 3.2, standardize on gcc 4.2, remove * macosx/Tcl.xcodeproj/*: obsolete configurations and pre-Xcode * macosx/Tcl.pbproj/* (removed): project. * macosx/README: Update project docs, cleanup. * unix/Makefile.in: Update dist target for project changes. 2009-06-24 Donal K. Fellows * tests/oo.test (oo-19.1): [Bug 2811598]: Make more resilient. 2009-06-24 Pat Thoyts * tests/http11.test: [Bug 2811492]: Clean up procs after testing. 2009-06-18 Donal K. Fellows * generic/tclCkalloc.c (MemoryCmd): [Bug 988703]: * generic/tclObj.c (ObjData, TclFinalizeThreadObjects): Add mechanism for discovering what Tcl_Objs are allocated when built for memory debugging. Developed by Joe Mistachkin. 2009-06-17 Alexandre Ferrieux * generic/tclEvent.c: Applied a patch by George Peter Staplin drastically reducing the ambition of [exit] wrt finalization, and thus solving many multi-thread teardown issues. [Bugs 2001201, 486399, and possibly 597575, 990457, 1437595, 2750491] 2009-06-15 Don Porter * generic/tclStringObj.c: sprintf() -> Tcl_ObjPrintf() conversion. 2009-06-15 Reinhard Max * unix/tclUnixPort.h: Move all socket-related code from tclUnixChan.c * unix/tclUnixChan.c: to tclUnixSock.c. * unix/tclUnixSock.c: 2009-06-15 Donal K. Fellows * tools/tcltk-man2html.tcl (make-man-pages): [Patch 557486]: Apply last remaining meaningful part of this patch, a clean up of some closing tags. 2009-06-13 Don Porter * generic/tclCompile.c: [Bug 2802881]: The value stashed in * generic/tclProc.c: iPtr->compiledProcPtr when compiling a proc * tests/execute.test: survives too long. We only need it there long enough for the right TclInitCompileEnv() call to re-stash it into envPtr->procPtr. Once that is done, the CompileEnv controls. If we let the value of iPtr->compiledProcPtr linger, though, then any other bytecode compile operation that takes place will also have its CompileEnv initialized with it, and that's not correct. The value is meant to control the compile of the proc body only, not other compile tasks that happen along. Thanks to Carlos Tasada for discovering and reporting the problem. 2009-06-10 Don Porter * generic/tclStringObj.c: [Bug 2801413]: Revised [format] to not overflow the integer calculations computing the length of the %ll formats of really big integers. Also added protections so that [format]s that would produce results overflowing the maximum string length of Tcl values throw a normal Tcl error instead of a panic. * generic/tclStringObj.c: [Bug 2803109]: Corrected failures to deal with the "pure unicode" representation of an empty string. Thanks to Julian Noble for reporting the problem. 2006-06-09 Kevin B. Kenny * generic/tclGetDate.y: Fixed a thread safety bug in the generated * library/clock.tcl: Bison parser (needed a %pure-parser * tests/clock.test: declaration to avoid static variables). Discovered that the %pure-parser declaration allowed for returning the Bison error message to the Tcl caller in the event of a syntax error, so did so. * generic/tclDate.c: bison 2.3 2006-06-08 Kevin B. Kenny * library/tzdata/Asia/Dhaka: New DST rule for Bangladesh. (Olson's tzdata2009i.) 2009-06-08 Donal K. Fellows * doc/copy.n: Fix error in example spotted by Venkat Iyer. 2009-06-02 Don Porter * generic/tclExecute.c: Replace dynamically-initialized table with a table of static constants in the lookup table for exponent operator computations that fit in a 64 bit integer result. * generic/tclExecute.c: [Bug 2798543]: Corrected implementations and selection logic of the INST_EXPON instruction. 2009-06-01 Don Porter * tests/expr.test: [Bug 2798543]: Added many tests demonstrating the broken cases. 009-05-30 Kevin B. Kenny * library/tzdata/Africa/Cairo: * library/tzdata/Asia/Amman: Olson's tzdata2009h. 2009-05-29 Andreas Kupries * library/platform/platform.tcl: Fixed handling of cpu ia64, * library/platform/pkgIndex.tcl: taking ia64_32 into account * unix/Makefile.in: now. Bumped version to 1.0.5. Updated the * win/Makefile.in: installation commands. 2009-05-26 Alexandre Ferrieux * doc/expr.n: Fixed documentation of the right-associativity of the ** operator. (spotted by kbk) 2009-05-14 Donal K. Fellows * generic/tclOOInfo.c (InfoObjectNsCmd): Added introspection mechanism for finding out what an object's namespace is. Experience suggests that it is just too useful to be able to do without it. 2009-05-12 Donal K. Fellows * doc/vwait.n: Added more words to make it clear just how bad it is to nest [vwait]s. * compat/mkstemp.c: Add more headers to make this file build on IRIX 6.5. Thanks to Larry McVoy for this. 2009-05-08 Donal K. Fellows * generic/tclOO.c (TclNRNewObjectInstance): [Bug 2414858]: Add a * generic/tclBasic.c (TclPushTailcallPoint): marker to the stack of NRE callbacks at the right point so that tailcall works correctly in a constructor. * tests/exec.test (cat): [Bug 2788468]: Adjust the scripted version of cat so that it does not perform transformations on the data it is working with, making it more like the standard Unix 'cat' program. 2009-05-07 Miguel Sofer * generic/tclObj.c (Tcl_GetCommandFromObj): [Bug 2785893]: Ensure that a command in a deleted namespace can't be found through a cached name. * generic/tclBasic.c: Let coroutines start with a much smaller * generic/tclCompile.h: stack: 200 words (previously was 2000, the * generic/tclExecute.c: same as interps). 2009-05-07 Donal K. Fellows * tests/env.test (printenvScript, env-4.3, env-4.5): [Bug 1513659]: * tests/exec.test (exec-2.6): These tests had subtle dependencies on being on platforms that were either ISO 8859-1 or UTF-8. Stabilized the results by forcing the encoding. 2009-05-06 Don Porter * generic/tclCmdMZ.c: [Bug 2582327]: Improve overflow error message from [string repeat]. * tests/interp.test: interp-20.50 test for Bug 2486550. 2009-05-04 Donal K. Fellows * generic/tclOO.c (InitFoundation, AllocObject, AllocClass): * generic/tclOODefineCmds.c (InitDefineContext): Make sure that when support namespaces are deleted, nothing bad can subsequently happen. Issue spotted by Don Porter. 2009-05-03 Donal K. Fellows * doc/Tcl.n: [Bug 2538432]: Clarified exact treatment of ${arr(idx)} form of variable substitution. This is not a change of behavior, just an improved description of the current situation. 2009-04-30 Miguel Sofer * generic/tclBasic.c (TclObjInvoke): [Bug 2486550]: Make sure that a null objProc is not used, use Tcl_NRCallObjProc instead. 2009-05-01 Jan Nijtmans * win/configure.in Fix 64-bit detection for zlib on Win64 * win/configure (regenerated) 2009-04-28 Jeff Hobbs * unix/tcl.m4, unix/configure (SC_CONFIG_CFLAGS): harden the check to add _r to CC on AIX with threads. 2009-04-27 Donal K. Fellows * doc/concat.n (EXAMPLES): [Bug 2780680]: Rewrote so that the spacing of result messages is correct. (The exact way they were wrong was different when rendered through groff or as HTML, but it was still wrong both ways.) 2009-04-27 Jan Nijtmans * generic/tclIndexObj.c: Reset internal INTERP_ALTERNATE_WRONG_ARGS * generic/tclIOCmd.c: flag inside the Tcl_WrongNumArgs function, so the caller no longer has to do the reset. 2009-04-24 Stuart Cassoff * unix/Makefile.in: [Patch 2769530]: Don't chmod/exec installManPage. 2009-04-19 Pat Thoyts * library/http/http.tcl: [Bug 2715421]: Removed spurious newline added * tests/http11.test: after POST and added tests to detect excess * tests/httpd11.tcl: bytes being POSTed. * library/http/pkgIndex.tcl: * makefiles: package version now 2.8.1 2009-04-15 Donal K. Fellows * doc/chan.n, doc/close.n: Tidy up documentation of TIP #332. 2009-04-14 Kevin B. Kenny * library/tzdata/Asia/Karachi: Updated rules for Pakistan Summer Time (Olson's tzdata2009f) 2009-04-11 Donal K. Fellows * generic/tclOOMethod.c (InvokeForwardMethod): Clarify the resolution behaviour of the name of the command that is forwarded to: it's now resolved using the object's namespace as context, which is much more useful than the previous (somewhat random) behaviour of using the caller's current namespace. 2009-04-10 Pat Thoyts * library/http/http.tcl: Improved HTTP/1.1 support and added * library/http/pkgIndex.tcl: specific HTTP/1.1 testing to ensure * tests/http11.test: we handle chunked+gzip for the various * tests/httpd11.test: modes (normal, -channel and -handler) * makefiles: package version set to 2.8.0 2009-04-10 Daniel Steffen * unix/tclUnixChan.c: TclUnixWaitForFile(): use FD_* macros * macosx/tclMacOSXNotify.c: to manipulate select masks (Cassoff). [FRQ 1960647] [Bug 3486554] * unix/tclLoadDyld.c: Use RTLD_GLOBAL instead of RTLD_LOCAL. [Bug 1961211] * macosx/tclMacOSXNotify.c: revise CoreFoundation notifier to allow embedding into applications that already have a CFRunLoop running and want to run the tcl event loop via Tcl_ServiceModeHook(TCL_SERVICE_ALL). * macosx/tclMacOSXNotify.c: add CFRunLoop based Tcl_Sleep() and * unix/tclUnixChan.c: TclUnixWaitForFile() implementations * unix/tclUnixEvent.c: and disable select() based ones in CoreFoundation builds. * unix/tclUnixNotify.c: simplify, sync with tclMacOSXNotify.c. * generic/tclInt.decls: add TclMacOSXNotifierAddRunLoopMode() * generic/tclIntPlatDecls.h: internal API, regen. * generic/tclStubInit.c: * unix/configure.in (Darwin): use Darwin SUSv3 extensions if available; remove /Network locations from default tcl package search path (NFS mounted locations and thus slow). * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 * macosx/tclMacOSXBundle.c: on Mac OS X 10.4 and later, replace deprecated NSModule API by dlfcn API. 2009-04-10 Donal K. Fellows * doc/StringObj.3: [Bug 2089279]: Corrected example so that it works on 64-bit machines as well. 2009-04-10 Pat Thoyts * tests/http.test: [Bug 26245326]: Added specific check for problem * tests/httpd: (return incomplete HTTP response header). 2009-04-08 Kevin B. Kenny * tools/tclZIC.tcl: Always emit files with Unix line termination. * library/tzdata: Olson's tzdata2009e 2009-04-09 Don Porter * library/http/http.tcl: [Bug 26245326]: Handle incomplete lines in the "connecting" state. Thanks to Sergei Golovan. 2009-04-08 Andreas Kupries * library/platform/platform.tcl: Extended the darwin sections to add * library/platform/pkgIndex.tcl: a kernel version number to the * unix/Makefile.in: identifier for anything from Leopard (10.5) on up. * win/Makefile.in: Extended patterns for same. Extended cpu * doc/platform.n: recognition for 64bit Tcl running on a 32bit kernel on a 64bit processor (By Daniel Steffen). Bumped version to 1.0.4. Updated Makefiles. 2009-04-08 Don Porter * library/tcltest/tcltest.tcl: [Bug 2570363]: Converted [eval]s (some * library/tcltest/pkgIndex.tcl: unsafe!) to {*} in tcltest package. * unix/Makefile.in: => tcltest 2.3.1 * win/Makefile.in: 2009-04-07 Don Porter * generic/tclStringObj.c: Correction so that value of TCL_GROWTH_MIN_ALLOC is everywhere expressed in bytes as comment claims. 2009-04-04 Donal K. Fellows * doc/vwait.n: [Bug 1910136]: Extend description and examples to make it clearer just how this command interprets variable names. 2009-03-30 Don Porter * doc/Alloc.3: [Bug 2556263]: Size argument is "unsigned int". 2009-03-27 Don Porter * generic/tclPathObj.c (TclPathPart): [Bug 2710920]: TclPathPart() * tests/fileName.test: was computing the wrong results for both [file dirname] and [file tail] on "path" arguments with the PATHFLAGS != 0 intrep and with an empty string for the "joined-on" part. 2009-03-25 Jan Nijtmans * doc/tclsh.1: Bring doc and tools in line with * tools/installData.tcl: http://wiki.tcl.tk/812 * tools/str2c * tools/tcltk-man2html.tcl 2009-03-25 Donal K. Fellows * doc/coroutine.n: [Bug 2152285]: Added basic documentation for the coroutine and yield commands. 2009-03-24 Donal K. Fellows * generic/tclOOBasic.c (TclOOSelfObjCmd): [Bug 2704302]: Make 'self class' better defined in the context of objects that change class. * generic/tclVar.c (Tcl_UpvarObjCmd): [Bug 2673163] (ferrieux) * generic/tclProc.c (TclObjGetFrame): Make the upvar command more able to handle its officially documented syntax. 2009-03-22 Miguel Sofer * generic/tclBasic.c: [Bug 2502037]: NR-enable the handling of unknown commands. 2009-03-21 Miguel Sofer * generic/tclBasic.c: Fixed "leaks" in aliases, imports and * generic/tclInt.h: ensembles. Only remaining known leak is in * generic/tclInterp.c: ensemble unknown dispatch (as it not * generic/tclNamesp.c: NR-enabled) * tests/tailcall.test: * tclInt.h: comments * tests/tailcall.test: Added tests to show that [tailcall] does not currently always execute in constant space: interp-alias, ns-imports and ensembles "leak" as of this commit. * tests/nre.test: [foreach] has been NR-enabled for a while, the test was marked 'knownBug': unmark it. * generic/tclBasic.c: Fix for (among others) [Bug 2699087] * generic/tclCmdAH.c: Tailcalls now perform properly even from * generic/tclExecute.c: within [eval]ed scripts. * generic/tclInt.h: More tests missing, as well as proper exploration and testing of the interaction with "redirectors" like interp-alias (suspect that it does not happen in constant space) and pure-eval commands. * generic/tclExecute.c: Proper fix for [Bug 2415422]. Reenabled * tests/nre.test: the failing assertion that was disabled on 2008-12-18: the assertion is correct, the fault was in the management of expansions. * generic/tclExecute.c: Fix both test and code for tailcall * tests/tailcall.test: from within a compiled [eval] body. * tests/tailcall.test: Slightly improved tests 2009-03-20 Don Porter * tests/stringObj.test: [Bug 2597185]: Test stringObj-6.9 checks that Tcl_AppendStringsToObj() no longer crashes when operating on a pure unicode value. * generic/tclExecute.c (INST_CONCAT1): [Bug 2669109]: Panic when appends overflow the max length of a Tcl value. 2009-03-19 Miguel Sofer * generic/tcl.h: * generic/tclInt.h: * generic/tclBasic.c: * generic/tclExecute.c: * generic/tclNamesp.c (Tcl_PopCallFrame): Rewritten tailcall implementation, ::unsupported::atProcExit is (temporarily?) gone. The new approach is much simpler, and also closer to being correct. This commit fixes [Bug 2649975] and [Bug 2695587]. * tests/coroutine.test: Moved the tests to their own files, * tests/tailcall.test: removed the unsupported.test. Added * tests/unsupported.test: tests for the fixed bugs. 2009-03-19 Donal K. Fellows * doc/tailcall.n: Added documentation for tailcall command. 2009-03-18 Don Porter * win/tclWinFile.c (TclpObjNormalizePath): [Bug 2688184]: Corrected Tcl_Obj leak. Thanks to Joe Mistachkin for detection and patch. * generic/tclVar.c (TclLookupSimpleVar): [Bug 2689307]: Shift all calls to Tcl_SetErrorCode() out of TclLookupSimpleVar and onto its callers, where control with TCL_LEAVE_ERR_MSG flag is more easily handled. 2009-03-16 Donal K. Fellows * generic/tclCmdMZ.c (TryPostBody): [Bug 2688063]: Extract information from list before getting rid of last reference to it. 2009-03-15 Joe Mistachkin * generic/tclThread.c: [Bug 2687952]: Modify fix for TSD leak to match * generic/tclThreadStorage.c: Tcl 8.5 (and prior) allocation semantics 2009-03-15 Donal K. Fellows * generic/tclThreadStorage.c (TSDTableDelete): [Bug 2687952]: Ensure * generic/tclThread.c (Tcl_GetThreadData): that structures in Tcl's TSD system are all freed. Use the correct matching allocator. * generic/tclPosixStr.c (Tcl_SignalId,Tcl_SignalMsg): [Patch 1513655]: Added support for SIGINFO, which is present on BSD platforms. 2009-03-14 Donal K. Fellows * unix/tcl.pc.in (new file): [Patch 2243948] (hat0) * unix/configure.in, unix/Makefile.in: Added support for reporting Tcl's public build configuration via the pkg-config system. TEA is still the official mechanism though, in part because pkg-config is not universally supported across all Tcl's supported platforms. 2009-03-11 Miguel Sofer * generic/tclBasic.c (TclNRCoroutineObjCmd): fix Tcl_Obj leak. Diagnosis and fix thanks to GPS. 2009-03-09 Donal K. Fellows * generic/tclCmdMZ.c (Tcl_TryObjCmd, TclNRTryObjCmd): Moved the implementation of [try] from Tcl code into C. Still lacks a bytecode version, but should be better than what was before. 2009-03-04 Donal K. Fellows * generic/tclZlib.c (TclZlibCmd): Checksums are defined to be unsigned 32-bit integers, use Tcl_WideInt to pass to scripts. [Bug 2662434] (ZlibStreamCmd, ChanGetOption): A few other related corrections. 2009-02-27 Jan Nijtmans * generic/tcl.decls: [Bug 218977]: Tcl_DbCkfree needs return value * generic/tclCkalloc.c * generic/tclDecls.h: (regenerated) * generic/tclInt.decls: don't use CONST84/CONST86 here * generic/tclCompile.h: don't use CONST86 here, comment fixing. * generic/tclIO.h: don't use CONST86 here, comment fixing. * generic/tclIntDecls.h (regenerated) 2009-02-25 Don Porter * generic/tclUtil.c (TclStringMatchObj): [Bug 2637173]: Revised the branching on the strObj->typePtr so that untyped values get converted to the "string" type and pass through the Unicode matcher. [Bug 2613766]: Also added checks to only perform "bytearray" optimization on pure bytearray values. * generic/tclCmdMZ.c: Since Tcl_GetCharLength() has its own * generic/tclExecute.c: optimizations for the tclByteArrayType, stop having the callers do them. 2009-02-24 Donal K. Fellows * doc/clock.n, doc/fblocked.n, doc/format.n, doc/lsort.n, * doc/pkgMkIndex.n, doc/regsub.n, doc/scan.n, doc/tclvars.n: General minor documentation improvements. * library/http/http.tcl (geturl, Eof): Added support for 8.6's built in zlib routines. 2009-02-22 Alexandre Ferrieux * tests/lrange.test: Revert commits of 2008-07-23. Those were speed * tests/binary.test: tests, that are inherently brittle. 2009-02-21 Don Porter * generic/tclStringObj.c: Several revisions to the shimmering patterns between Unicode and UTF string reps. Most notably the call: objPtr = Tcl_NewUnicodeObj(...,0); followed by a loop of calls: Tcl_AppendUnicodeToObj(objPtr, u, n); will now grow and append to the Unicode representation. Before this commit, the sequence would convert each append to UTF and perform the append to the UTF rep. This is puzzling and likely a bug. The performance of [string map] is significantly improved by this change (according to the MAP collection of benchmarks in tclbench). Just in case there was some wisdom in the old ways that I missed, I left in the ability to restore the old patterns with a #define COMPAT 1 at the top of the file. 2009-02-20 Don Porter * generic/tclPathObj.c: [Bug 2571597]: Fixed mistaken logic in * tests/fileName.test: TclFSGetPathType() that assumed (not "absolute") => "relative". This is a false assumption on Windows, where "volumerelative" is another possibility. 2009-02-18 Don Porter * generic/tclStringObj.c: Simplify the logic of the Tcl_*SetObjLength() routines. * generic/tclStringObj.c: Rewrite GrowStringBuffer() so that it has parallel structure with GrowUnicodeBuffer(). The revision permits allocation attempts to continue all the way up to failure, with no gap. It also directly manipulates the String and Tcl_Obj internals instead of inefficiently operating via Tcl_*SetObjLength() with all of its extra protections and underdocumented special cases. * generic/tclStringObj.c: Another round of simplification on the allocation macros. 2009-02-17 Jeff Hobbs * win/tcl.m4, win/configure: Check if cl groks _WIN64 already to avoid CC manipulation that can screw up later configure checks. Use 'd'ebug runtime in 64-bit builds. 2009-02-17 Don Porter * generic/tclStringObj.c: Pare back the length of the unicode array in a non-extended String struct to one Tcl_UniChar, meant to hold the terminating NUL character. Non-empty unicode strings are then stored by extending the String struct by stringPtr->maxChars additional slots in that array with sizeof(Tcl_UniChar) bytes per slot. This revision makes the allocation macros much simpler. * generic/tclStringObj.c: Factor out common GrowUnicodeBuffer() and solve overflow and growth algorithm fallbacks in it. * generic/tclStringObj.c: Factor out common GrowStringBuffer(). * generic/tclStringObj.c: Convert Tcl_AppendStringsToObj into * tests/stringObj.test: a radically simpler implementation where we just loop over calls to Tcl_AppendToObj. This fixes [Bug 2597185]. It also creates a *** POTENTIAL INCOMPATIBILITY *** in that T_ASTO can now allocate more space than is strictly required, like all the other Tcl_Append* routines. The incompatibility was detected by test stringObj-6.5, which I've updated to reflect the new behavior. * generic/tclStringObj.c: Revise buffer growth implementation in ExtendStringRepWithUnicode. Use cheap checks to determine that no reallocation is necessary without cost of computing the precise number of bytes needed. Also make use of the string growth algortihm in the case of repeated appends. 2009-02-16 Jan Nijtmans * generic/tclZlib.c: Hack needed for official zlib1.dll build. * win/configure.in: fix [Feature Request 2605263] use official * win/Makefile.in: zlib build. * win/configure: (regenerated) * compat/zlib/zdll.lib: new files * compat/zlib/zlib1.dll: * win/Makefile.in: [Bug 2605232]: tdbc doesn't build when Tcl is compiled with --disable-shared. 2009-02-15 Don Porter * generic/tclStringObj.c: [Bug 2603158]: Added protections from * generic/tclTestObj.c: invalid memory accesses when we append * tests/stringObj.test: (some part of) a Tcl_Obj to itself. Added the appendself and appendself2 subcommands to the [teststringobj] testing command and added tests to the test suite. * generic/tclStringObj.c: Factor out duplicate code from Tcl_AppendObjToObj. * generic/tclStringObj.c: Replace the 'size_t uallocated' field of the String struct, storing the number of bytes allocated to store the Tcl_UniChar array, with an 'int maxChars' field, storing the number of Tcl_UniChars that may be stored in the allocated space. This reduces memory requirement a small bit, and makes some range checks simpler to code. * generic/tclTestObj.c: Replace the [teststringobj ualloc] testing * tests/stringObj.test: command with [teststringobj maxchars] and update the tests. * generic/tclStringObj.c: Removed limitation in Tcl_AppendObjToObj where the char length of the result was only computed if the appended string was all single byte characters. This limitation was in place to dodge a bug in Tcl_GetUniChar. With that bug gone, we can take advantage of always recording the length of append results when we know it. 2009-02-14 Don Porter * generic/tclStringObj.c: Revisions so that we avoid creating the strange representation of an empty string with objPtr->bytes == NULL and stringPtr->hasUnicode == 0. Instead in the situations where that was being created, create a traditional two-legged stork representation (objPtr->bytes = tclEmptyStringRep and stringPtr->hasUnicode = 1). In the situations where the strange rep was treated differently, continue to do so by testing stringPtr->numChars == 0 to detect it. These changes make the code more conventional so easier for new maintainers to pick up. Also sets up further simplifications. * generic/tclTestObj.c: Revise updates to [teststringobj] so we don't get blocked by MODULE_SCOPE limits. 2009-02-12 Don Porter * generic/tclStringObj.c: Rewrites of the routines Tcl_GetCharLength, Tcl_GetUniChar, Tcl_GetUnicodeFromObj, Tcl_GetRange, and TclStringObjReverse to use the new macro, and to more simply and clearly split the cases depending on whether a valid unicode rep is present or needs to be created. New utility routine UnicodeLength(), to compute the length of unicode buffer arguments when no length is passed in, with built-in overflow protection included. Update three callers to use it. * generic/tclInt.h: New macro TclNumUtfChars meant to be a faster replacement for a full Tcl_NumUtfChars() call when the string has all single-byte characters. * generic/tclStringObj.c: Simplified Tcl_GetCharLength by * generic/tclTestObj.c: removing code that did nothing. Added early returns from Tcl_*SetObjLength when the desired length is already present; adapted test command to the change. * generic/tclStringObj.c: Re-implemented AppendUtfToUnicodeRep so that we no longer pass through Tcl_DStrings which have their own sets of problems when lengths overflow the int range. Now AUTUR and FillUnicodeRep share a common core routine. 2009-02-12 Donal K. Fellows * generic/tclOODefineCmds.c (TclOOGetDefineCmdContext): Use the correct field in the Interp structure for retrieving the frame to get the context object so that people can extend [oo::define] without deep shenanigans. Bug found by Federico Ferri. 2009-02-11 Don Porter * generic/tclStringObj.c: Re-implemented AppendUnicodeToUtfRep so that we no longer pass through Tcl_DStrings which have their own sets of problems when lengths overflow the int range. Now AUTUR and UpdateStringOfString share a common core routine. * generic/tclStringObj.c: Changed type of the 'allocated' field * generic/tclTestObj.c: of the String struct (and the TestString counterpart) from size_t to int since only int values are ever stored in it. 2009-02-10 Jan Nijtmans * generic/tclEncoding.c: Eliminate some unnessary type casts * generic/tclEvent.c: some internal const decorations * generic/tclExecute.c: spacing * generic/tclIndexObj.c: * generic/tclInterp.c: * generic/tclIO.c: * generic/tclIOCmd.c: * generic/tclIORChan.c: * generic/tclIOUtil.c: * generic/tclListObj.c: * generic/tclLiteral.c: * generic/tclNamesp.c: * generic/tclObj.c: * generic/tclOOBasic.c: * generic/tclPathObj.c: * generic/tclPkg.c: * generic/tclProc.c: * generic/tclRegexp.c: * generic/tclScan.c: * generic/tclStringObj.c: * generic/tclTest.c: * generic/tclTestProcBodyObj.c: * generic/tclThread.c: * generic/tclThreadTest.c: * generic/tclTimer.c: * generic/tclTrace.c: * generic/tclUtil.c: * generic/tclVar.c: * generic/tclStubInit.c: (regenerated) 2009-02-10 Jan Nijtmans * unix/tcl.m4: [Bug 2502365]: Building of head on HPUX is broken when using the native CC. * unix/configure: (autoconf-2.59) 2009-02-10 Don Porter * generic/tclObj.c (Tcl_GetString): Added comments and validity checks following the call to an UpdateStringProc. * generic/tclStringObj.c: Reduce code duplication in Tcl_GetUnicode*. Restrict AppendUtfToUtfRep to non-negative length appends. Convert all Tcl_InvalidateStringRep() calls into macros. Simplify Tcl_AttemptSetObjLength by removing unreachable code. Simplify SetStringFromAny() by removing unreachable and duplicate code. Simplify Tcl_SetObjLength by removing unreachable code. Removed handling of (objPtr->bytes != NULL) from UpdateStringOfString, which is only called when objPtr->bytes is NULL. 2009-02-09 Jan Nijtmans * generic/tclCompile.c: [Bug 2555129]: const compiler warning (as error) in tclCompile.c 2009-02-07 Donal K. Fellows * generic/tclZlib.c (TclZlibCmd): [Bug 2573172]: Ensure that when invalid subcommand name is given, the list of valid subcommands is produced. This gives a better experience when using the command interactively. 2009-02-05 Joe Mistachkin * generic/tclInterp.c: [Bug 2544618]: Fix argument checking for [interp cancel]. * unix/Makefile.in: Fix build issue with zlib on FreeBSD (and possibly other platforms). 2009-02-05 Donal K. Fellows * generic/tclCmdMZ.c (StringIndexCmd, StringRangeCmd, StringLenCmd): Simplify the implementation of some commands now that the underlying string API knows more about bytearrays. * generic/tclExecute.c (TclExecuteByteCode): [Bug 2568434]: Make sure that INST_CONCAT1 will not lose string reps wrongly. * generic/tclStringObj.c (Tcl_AppendObjToObj): Special-case the appending of one bytearray to another, which can be extremely rapid. Part of scheme to address [Bug 1665628] by making the basic string operations more efficient on byte arrays. (Tcl_GetCharLength, Tcl_GetUniChar, Tcl_GetRange): More special casing work for bytearrays. 2009-02-04 Don Porter * generic/tclStringObj.c: [Bug 2561794]: Added overflow protections to the AppendUtfToUtfRep routine to either avoid invalid arguments and crashes, or to replace them with controlled panics. * generic/tclCmdMZ.c: [Bug 2561746]: Prevent crashes due to int overflow of the length of the result of [string repeat]. 2009-02-03 Jan Nijtmans * macosx/tclMacOSXFCmd.c: Eliminate some unnessary type casts * unix/tclLoadDyld.c: some internal const decorations * unix/tclUnixCompat.c: spacing * unix/tclUnixFCmd.c * unix/tclUnixFile.c * win/tclWinDde.c * win/tclWinFCmd.c * win/tclWinInit.c * win/tclWinLoad.c * win/tclWinPipe.c * win/tclWinReg.c * win/tclWinTest.c * generic/tclBasic.c * generic/tclBinary.c * generic/tclCmdAH.c * generic/tclCmdIL.c * generic/tclCmdMZ.c * generic/tclCompCmds.c * generic/tclDictObj.c 2009-02-03 Donal K. Fellows * generic/tclObj.c (tclCmdNameType): [Bug 2558422]: Corrected the type of this structure so that extensions that write it (yuk!) will still be able to function correctly. 2009-02-03 Don Porter * generic/tclStringObj.c (SetUnicodeObj): [Bug 2561488]: Corrected failure of Tcl_SetUnicodeObj() to panic on a shared object. Also factored out common code to reduce duplication. * generic/tclObj.c (Tcl_GetStringFromObj): Reduce code duplication. 2009-02-02 Don Porter * generic/tclInterp.c: Reverted the conversion of [interp] into an * tests/interp.test: ensemble. Such conversion is not necessary * tests/nre.test: (or even all that helpful) in the NRE-enabling of [interp invokehidden], and it has other implications -- including significant forkage of the 8.5 and 8.6 implementations -- that are better off avoided if there's no gain. * generic/tclStringObj.c (STRING_NOMEM): [Bug 2494093]: Add missing cast of NULL to (char *) that upsets some compilers. * generic/tclStringObj.c (Tcl_(Attempt)SetObjLength): [Bug 2553906]: Added protections against callers asking for negative lengths. It is likely when this happens that an integer overflow is to blame. 2009-02-01 David Gravereaux * win/makefile.vc: Allow nmake flags such as -a (rebuild all) to pass down to the pkgs targets, too. 2009-01-30 Donal K. Fellows * doc/chan.n: [Bug 1216074]: Added another extended example. * doc/refchan.n: Added an example of how to build a scripted channel. 2009-01-29 Donal K. Fellows * tests/stringObj.test: [Bug 2006888]: Remove non-ASCII chars from non-comment locations in the file, making it work more reliably in locales with a non-Latin-1 default encoding. * generic/tclNamesp.c (Tcl_FindCommand): [Bug 2519474]: Ensure that the path is not searched when the TCL_NAMESPACE_ONLY flag is given. * generic/tclOODecls.h (Tcl_OOInitStubs): [Bug 2537839]: Make the declaration of this macro work correctly in the non-stub case. 2009-01-29 Don Porter * generic/tclInterp.c: Convert the [interp] command into a * tests/interp.test: [namespace ensemble]. Work in progress * tests/nre.test: to NRE-enable the [interp invokehidden] subcommand. 2009-01-29 Donal K. Fellows * generic/tclNamesp.c (TclMakeEnsemble): [Bug 2529117]: Make this function behave more sensibly when presented with a fully-qualified name, rather than doing strange stuff. 2009-01-28 Donal K. Fellows * generic/tclBasic.c (TclInvokeObjectCommand): Made this understand what to do if it ends up being used on a command with no objProc; that shouldn't happen, but... * generic/tclNamesp.c (TclMakeEnsemble): [Bug 2529157]: Made this understand NRE command implementations better. * generic/tclDictObj.c (DictForCmd): Eliminate unnecessary command implementation. 2009-01-27 Donal K. Fellows * generic/tclOODefineCmds.c (Tcl_ClassSetConstructor): [Bug 2531577]: Ensure that caches of constructor chains are cleared when the constructor is changed. 2009-01-26 Alexandre Ferrieux * generic/tclInt.h: [Bug 1028264]: WSACleanup() too early. * generic/tclEvent.c: The fix introduces "late exit handlers" for * win/tclWinSock.c: similar late process-wide cleanups. 2009-01-26 Alexandre Ferrieux * win/tclWinSock.c: [Bug 2446662]: Resync Win behavior on RST with that of unix (EOF). 2009-01-26 Donal K. Fellows * generic/tclZlib.c (ChanClose): [Bug 2536400]: Only generate error messages in the interpreter when the thread is not being closed down. 2009-01-23 Donal K. Fellows * doc/zlib.n: Added a note that 'zlib push' is reversed by 'chan pop'. 2009-01-22 Jan Nijtmans * generic/tclCompile.h: CONSTify TclPrintInstruction (TIP #27) * generic/tclCompile.c * generic/tclInt.h: CONSTify TclpNativeJoinPath (TIP #27) * generic/tclFileName.c * generic/tcl.decls: {unix win} is equivalent to {generic} * generic/tclInt.decls * generic/tclDecls.h: (regenerated) * generic/tclIntDecls.h * generic/tclGetDate.y: Single internal const decoration. * generic/tclDate.c: 2009-01-22 Kevin B. Kenny * unix/tcl.m4: Corrected a typo ($(SHLIB_VERSION) should be ${SHLIB_VERSION}). * unix/configure: Autoconf 2.59 2009-01-21 Andreas Kupries * generic/tclIORChan.c (ReflectClose): [Bug 2458202]: * generic/tclIORTrans.c (ReflectClose): Closing a channel may supply NULL for the 'interp'. Test for finalization needs to be different, and one place has to pull the interp out of the channel instead. 2009-01-21 Don Porter * generic/tclStringObj.c: New fix for [Bug 2494093] replaces the flawed attempt committed 2009-01-09. 2009-01-19 Kevin B. Kenny * unix/Makefile.in: [Patch 907924]:Added a CONFIG_INSTALL_DIR * unix/tcl.m4: parameter so that distributors can control where tclConfig.sh goes. Made the installation of 'ldAix' conditional upon actually being on an AIX system. Allowed for downstream packagers to customize SHLIB_VERSION on BSD-derived systems. Thanks to Stuart Cassoff for his help. * unix/configure: Autoconf 2.59 2009-01-19 David Gravereaux * win/build.vc.bat: Improved tools detection and error message * win/makefile.vc: Reorganized the $(TCLOBJ) file list into seperate parts for easier maintenance. Matched all sources built using -GL to both $(lib) and $(link) to use -LTCG and avoid a warning message. Addressed the over-building nature of the htmlhelp target by moving from a pseudo target to a real target dependent on the entire docs/ directory contents. * win/nmakehlp.c: Removed -g option and GrepForDefine() func as it isn't being used anymore. The -V option method is much better. 2009-01-16 Don Porter * generic/tcl.h: Bump patchlevel to 8.6b1.1 to distinguish * library/init.tcl: CVS snapshots from the 8.6b1 and 8.6b2 releases * unix/configure.in: and to deal with the fact that the 8.6b1 * win/configure.in: version of init.tcl will not [source] in the HEAD version of Tcl. * unix/configure: autoconf-2.59 * win/configure: 2009-01-14 Don Porter * generic/tclBasic.c (Tcl_DeleteCommandFromToken): Reverted most of the substance of my 2009-01-12 commit. NULLing the objProc field of a Command when deleting it is important so that tests for certain classes of commands don't return false positives when applied to deleted command tokens. Overall change is now just replacement of a false comment with a true one. 2009-01-13 Jan Nijtmans * unix/tcl.m4: [Bug 2502365]: Building of head on HPUX is broken when using the native CC. * unix/configure (autoconf-2.59) 2009-01-13 Donal K. Fellows * generic/tclCmdMZ.c (Tcl_ThrowObjCmd): Move implementation of [throw] * library/init.tcl (throw): to C from Tcl. 2009-01-12 Don Porter * generic/tclBasic.c (Tcl_DeleteCommandFromToken): One consequence of the NRE rewrite is that there are now situations where a NULL objProc field in a Command struct is perfectly normal. Removed an outdated comment in Tcl_DeleteCommandFromToken that claimed we use cmdPtr->objPtr==NULL as a test of command validity. In fact we use cmdPtr->flags&CMD_IS_DELETED to perform that test. Also removed the setting to NULL, since any extension following the advice of the old comment is going to be broken by NRE anyway, and needs to shift to flag-based testing (or stop intruding into such internal matters). Part of [Bug 2486550]. 2009-01-09 Don Porter * generic/tclStringObj.c (STRING_SIZE): [Bug 2494093]: Corrected failure to limit memory allocation requests to the sizes that can be supported by Tcl's memory allocation routines. 2009-01-09 Donal K. Fellows * generic/tclNamesp.c (NamespaceEnsembleCmd): [Bug 1558654]: Error out when someone gives wrong # of args to [namespace ensemble create]. 2009-01-08 Don Porter * generic/tclStringObj.c (STRING_UALLOC): [Bug 2494093]: Added missing parens required to get correct results out of things like STRING_UALLOC(num + append). 2009-01-08 Donal K. Fellows * generic/tclDictObj.c, generic/tclIndexObj.c, generic/tclListObj.c, * generic/tclObj.c, generic/tclStrToD.c, generic/tclUtil.c, * generic/tclVar.c: Generate errorcodes for the error cases which approximate to "I can't interpret that string as one of those" and "You gave me the wrong number of arguments". 2009-01-07 Donal K. Fellows * doc/dict.n: [Tk Bug 2491235]: Added more examples. * tests/oo.test (oo-22.1): Adjusted test to be less dependent on the specifics of how [info frame] reports general frame information, and instead to focus on what methods add to it; that's really what the test is about anyway. 2009-01-06 Don Porter * tests/stringObj.test: Revise tests that demand a NULL Tcl_ObjType in certain values to construct those values with [testdstring] so there's no lack of robustness depending on the shimmer history of shared literals. 2009-01-06 Donal K. Fellows * generic/tclDictObj.c (DictIncrCmd): Corrected twiddling in internals of dictionaries so that literals can't get destroyed. * tests/expr.test: [Bug 2006879]: Eliminate non-ASCII char. * generic/tclOOInfo.c (InfoObjectMethodsCmd,InfoClassMethodsCmd): [Bug 2489836]: Only delete pointers that were actually allocated! * generic/tclOO.c (TclNRNewObjectInstance, Tcl_NewObjectInstance): [Bug 2481109]: Perform search for existing commands in right context. 2009-01-05 Donal K. Fellows * generic/tclCmdMZ.c (TclNRSourceObjCmd): [Bug 2412068]: Make * generic/tclIOUtil.c (TclNREvalFile): implementation of the [source] command be NRE enabled so that [yield] inside a script sourced in a coroutine can work. 2009-01-04 Donal K. Fellows * generic/tclCmdAH.c: Tidy up spacing and code style. 2009-01-03 Kevin B. Kenny * library/clock.tcl (tcl::clock::add): Fixed error message formatting in the case where [clock add] is presented with a bad switch. * tests/clock.test (clock-65.1) Added a test case for the above problem [Bug 2481670]. 2009-01-02 Donal K. Fellows * unix/tcl.m4 (SC_CONFIG_CFLAGS): [Bug 878333]: Force the use of the compatibility version of mkstemp() on IRIX. * unix/configure.in, unix/Makefile.in (mkstemp.o): * compat/mkstemp.c (new file): [Bug 741967]: Added a compatibility implementation of the mkstemp() function, which is apparently needed on some platforms. ****************************************************************** *** CHANGELOG ENTRIES FOR 2008 IN "ChangeLog.2008" *** *** CHANGELOG ENTRIES FOR 2006-2007 IN "ChangeLog.2007" *** *** CHANGELOG ENTRIES FOR 2005 IN "ChangeLog.2005" *** *** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2004" *** *** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003" *** *** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002" *** *** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" *** *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" *** *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" *** ****************************************************************** tcl8.6.5/tools/0000755000175000017500000000000012665173607012732 5ustar sergeisergeitcl8.6.5/tools/tsdPerf.tcl0000644000175000017500000000077012663653210015040 0ustar sergeisergei package require Thread set ::tids [list] for {set i 0} {$i < 4} {incr i} { lappend ::tids [thread::create [string map [list IVALUE $i] { set curdir [file dirname [info script]] load [file join $curdir tsdPerf[info sharedlibextension]] while 1 { tsdPerfSet IVALUE } }]] } puts TIDS:$::tids set curdir [file dirname [info script]] load [file join $curdir tsdPerf[info sharedlibextension]] tsdPerfSet 1234 while 1 { puts "TIME:[time {set value [tsdPerfGet]} 1000] VALUE:$value" } tcl8.6.5/tools/index.tcl0000644000175000017500000001027612663653210014542 0ustar sergeisergei# index.tcl -- # # This file defines procedures that are used during the first pass of # the man page conversion. It is used to extract information used to # generate a table of contents and a keyword list. # # Copyright (c) 1996 by Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # Global variables used by these scripts: # # state - state variable that controls action of text proc. # # topics - array indexed by (package,section,topic) with value # of topic ID. # # keywords - array indexed by keyword string with value of topic ID. # # curID - current topic ID, starts at 0 and is incremented for # each new topic file. # # curPkg - current package name (e.g. Tcl). # # curSect - current section title (e.g. "Tcl Built-In Commands"). # # getPackages -- # # Generate a sorted list of package names from the topics array. # # Arguments: # none. proc getPackages {} { global topics foreach i [array names topics] { regsub {^(.*),.*,.*$} $i {\1} i set temp($i) {} } lsort [array names temp] } # getSections -- # # Generate a sorted list of section titles in the specified package # from the topics array. # # Arguments: # pkg - Name of package to search. proc getSections {pkg} { global topics regsub -all {[][*?\\]} $pkg {\\&} pkg foreach i [array names topics "${pkg},*"] { regsub {^.*,(.*),.*$} $i {\1} i set temp($i) {} } lsort [array names temp] } # getTopics -- # # Generate a sorted list of topics in the specified section of the # specified package from the topics array. # # Arguments: # pkg - Name of package to search. # sect - Name of section to search. proc getTopics {pkg sect} { global topics regsub -all {[][*?\\]} $pkg {\\&} pkg regsub -all {[][*?\\]} $sect {\\&} sect foreach i [array names topics "${pkg},${sect},*"] { regsub {^.*,.*,(.*)$} $i {\1} i set temp($i) {} } lsort [array names temp] } # text -- # # This procedure adds entries to the hypertext arrays topics and keywords. # # Arguments: # string - Text to index. proc text string { global state curID curPkg curSect topics keywords switch $state { NAME { foreach i [split $string ","] { set topic [string trim $i] set index "$curPkg,$curSect,$topic" if {[info exists topics($index)] && [string compare $topics($index) $curID] != 0} { puts stderr "duplicate topic $topic in $curPkg" } set topics($index) $curID lappend keywords($topic) $curID } } KEY { foreach i [split $string ","] { lappend keywords([string trim $i]) $curID } } DT - OFF - DASH {} default { puts stderr "text: unknown state: $state" } } } # macro -- # # This procedure is invoked to process macro invocations that start # with "." (instead of '). # # Arguments: # name - The name of the macro (without the "."). # args - Any additional arguments to the macro. proc macro {name args} { switch $name { SH - SS { global state switch $args { NAME { if {$state eq "INIT" } { set state NAME } } DESCRIPTION {set state DT} INTRODUCTION {set state DT} KEYWORDS {set state KEY} default {set state OFF} } } TH { global state curID curPkg curSect topics keywords set state INIT if {[llength $args] != 5} { set args [join $args " "] puts stderr "Bad .TH macro: .$name $args" } incr curID set topic [lindex $args 0] ;# Tcl_UpVar set curPkg [lindex $args 3] ;# Tcl set curSect [lindex $args 4] ;# {Tcl Library Procedures} regsub -all {\\ } $curSect { } curSect set index "$curPkg,$curSect,$topic" set topics($index) $curID lappend keywords($topic) $curID } } } # dash -- # # This procedure is invoked to handle dash characters ("\-" in # troff). It only function in pass1 is to terminate the NAME state. # # Arguments: # None. proc dash {} { global state if {$state eq "NAME"} { set state DASH } } # initGlobals, tab, font, char, macro2 -- # # These procedures do nothing during the first pass. # # Arguments: # None. proc initGlobals {} {} proc newline {} {} proc tab {} {} proc font type {} proc char name {} proc macro2 {name args} {} tcl8.6.5/tools/tcltk-man2html.tcl0000755000175000017500000005035112663660066016304 0ustar sergeisergei#!/usr/bin/env tclsh if {[catch {package require Tcl 8.6} msg]} { puts stderr "ERROR: $msg" puts stderr "If running this script from 'make html', set the\ NATIVE_TCLSH environment\nvariable to point to an installed\ tclsh8.6 (or the equivalent tclsh86.exe\non Windows)." exit 1 } # Convert Ousterhout format man pages into highly crosslinked hypertext. # # Along the way detect many unmatched font changes and other odd things. # # Note well, this program is a hack rather than a piece of software # engineering. In that sense it's probably a good example of things # that a scripting language, like Tcl, can do well. It is offered as # an example of how someone might convert a specific set of man pages # into hypertext, not as a general solution to the problem. If you # try to use this, you'll be very much on your own. # # Copyright (c) 1995-1997 Roger E. Critchlow Jr # Copyright (c) 2004-2010 Donal K. Fellows set ::Version "50/8.6" set ::CSSFILE "docs.css" ## ## Source the utility functions that provide most of the ## implementation of the transformation from nroff to html. ## source [file join [file dirname [info script]] tcltk-man2html-utils.tcl] proc parse_command_line {} { global argv Version # These variables determine where the man pages come from and where # the converted pages go to. global tcltkdir tkdir tcldir webdir build_tcl build_tk verbose # Set defaults based on original code. set tcltkdir ../.. set tkdir {} set tcldir {} set webdir ../html set build_tcl 0 set build_tk 0 set verbose 0 # Default search version is a glob pattern set useversion {{,[8-9].[0-9]{,[.ab][0-9]{,[0-9]}}}} # Handle arguments a la GNU: # --version # --useversion= # --help # --srcdir=/path # --htmldir=/path foreach option $argv { switch -glob -- $option { --version { puts "tcltk-man-html $Version" exit 0 } --help { puts "usage: tcltk-man-html \[OPTION\] ...\n" puts " --help print this help, then exit" puts " --version print version number, then exit" puts " --srcdir=DIR find tcl and tk source below DIR" puts " --htmldir=DIR put generated HTML in DIR" puts " --tcl build tcl help" puts " --tk build tk help" puts " --useversion version of tcl/tk to search for" puts " --verbose whether to print longer messages" exit 0 } --srcdir=* { # length of "--srcdir=" is 9. set tcltkdir [string range $option 9 end] } --htmldir=* { # length of "--htmldir=" is 10 set webdir [string range $option 10 end] } --useversion=* { # length of "--useversion=" is 13 set useversion [string range $option 13 end] } --tcl { set build_tcl 1 } --tk { set build_tk 1 } --verbose=* { set verbose [string range $option \ [string length --verbose=] end] } default { puts stderr "tcltk-man-html: unrecognized option -- `$option'" exit 1 } } } if {!$build_tcl && !$build_tk} { set build_tcl 1; set build_tk 1 } if {$build_tcl} { # Find Tcl. set tcldir [lindex [lsort [glob -nocomplain -tails -type d \ -directory $tcltkdir tcl$useversion]] end] if {$tcldir eq ""} { puts stderr "tcltk-man-html: couldn't find Tcl below $tcltkdir" exit 1 } puts "using Tcl source directory $tcldir" } if {$build_tk} { # Find Tk. set tkdir [lindex [lsort [glob -nocomplain -tails -type d \ -directory $tcltkdir tk$useversion]] end] if {$tkdir eq ""} { puts stderr "tcltk-man-html: couldn't find Tk below $tcltkdir" exit 1 } puts "using Tk source directory $tkdir" } puts "verbose messages are [expr {$verbose ? {on} : {off}}]" # the title for the man pages overall global overall_title set overall_title "" if {$build_tcl} { append overall_title "[capitalize $tcldir]" } if {$build_tcl && $build_tk} { append overall_title "/" } if {$build_tk} { append overall_title "[capitalize $tkdir]" } append overall_title " Documentation" } proc capitalize {string} { return [string toupper $string 0] } ## ## Returns the style sheet. ## proc css-style args { upvar 1 style style set body [uplevel 1 [list subst [lindex $args end]]] set tokens [join [lrange $args 0 end-1] ", "] append style $tokens " \{" $body "\}\n" } proc css-stylesheet {} { set hBd "1px dotted #11577b" css-style body div p th td li dd ul ol dl dt blockquote { font-family: Verdana, sans-serif; } css-style pre code { font-family: 'Courier New', Courier, monospace; } css-style pre { background-color: #f6fcec; border-top: 1px solid #6A6A6A; border-bottom: 1px solid #6A6A6A; padding: 1em; overflow: auto; } css-style body { background-color: #FFFFFF; font-size: 12px; line-height: 1.25; letter-spacing: .2px; padding-left: .5em; } css-style h1 h2 h3 h4 { font-family: Georgia, serif; padding-left: 1em; margin-top: 1em; } css-style h1 { font-size: 18px; color: #11577b; border-bottom: $hBd; margin-top: 0px; } css-style h2 { font-size: 14px; color: #11577b; background-color: #c5dce8; padding-left: 1em; border: 1px solid #6A6A6A; } css-style h3 h4 { color: #1674A4; background-color: #e8f2f6; border-bottom: $hBd; border-top: $hBd; } css-style h3 { font-size: 12px; } css-style h4 { font-size: 11px; } css-style ".keylist dt" ".arguments dt" { width: 20em; float: left; padding: 2px; border-top: 1px solid #999; } css-style ".keylist dt" { font-weight: bold; } css-style ".keylist dd" ".arguments dd" { margin-left: 20em; padding: 2px; border-top: 1px solid #999; } css-style .copy { background-color: #f6fcfc; white-space: pre; font-size: 80%; border-top: 1px solid #6A6A6A; margin-top: 2em; } css-style .tablecell { font-size: 12px; padding-left: .5em; padding-right: .5em; } } ## ## foreach of the man directories specified by args ## convert manpages into hypertext in the directory ## specified by html. ## proc make-man-pages {html args} { global manual overall_title tcltkdesc verbose global excluded_pages forced_index_pages process_first_patterns makedirhier $html set cssfd [open $html/$::CSSFILE w] puts $cssfd [css-stylesheet] close $cssfd set manual(short-toc-n) 1 set manual(short-toc-fp) [open $html/[indexfile] w] puts $manual(short-toc-fp) [htmlhead $overall_title $overall_title] puts $manual(short-toc-fp) "
" set manual(merge-copyrights) {} foreach arg $args { # preprocess to set up subheader for the rest of the files if {![llength $arg]} { continue } lassign $arg -> name file if {[regexp {(.*)(?: Package)? Commands(?:, version .*)?} $name -> pkg]} { set name "$pkg Commands" } elseif {[regexp {(.*)(?: Package)? C API(?:, version .*)?} $name -> pkg]} { set name "$pkg C API" } lappend manual(subheader) $name $file } ## ## parse the manpages in a section of the docs (split by ## package) and construct formatted manpages ## foreach arg $args { if {[llength $arg]} { make-manpage-section $html $arg } } ## ## build the keyword index. ## if {!$verbose} { puts stderr "Assembling index" } file delete -force -- $html/Keywords makedirhier $html/Keywords set keyfp [open $html/Keywords/[indexfile] w] 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} # Create header first set keyheader {} foreach a $letters { set keys [array names manual "keyword-\[[string totitle $a$a]\]*"] if {[llength $keys]} { lappend keyheader "$a" } else { # No keywords for this letter lappend keyheader $a } } set keyheader

[join $keyheader " |\n"]

puts $keyfp $keyheader foreach a $letters { set keys [array names manual "keyword-\[[string totitle $a$a]\]*"] if {![llength $keys]} { continue } # Per-keyword page set afp [open $html/Keywords/$a.htm w] puts $afp [htmlhead "$tcltkdesc Keywords - $a" \ "$tcltkdesc Keywords - $a" \ $overall_title "../[indexfile]"] puts $afp $keyheader puts $afp "
" foreach k [lsort -dictionary $keys] { set k [string range $k 8 end] puts $afp "
$k
" puts $afp "
" set refs {} foreach man $manual(keyword-$k) { set name [lindex $man 0] set file [lindex $man 1] if {[info exists manual(tooltip-$file)]} { set tooltip $manual(tooltip-$file) if {[string match {*[<>""]*} $tooltip]} { manerror "bad tooltip for $file: \"$tooltip\"" } lappend refs "$name" } else { lappend refs "$name" } } puts $afp "[join $refs {, }]
" } puts $afp "
" # insert merged copyrights puts $afp [copyout $manual(merge-copyrights)] puts $afp "" close $afp } # insert merged copyrights puts $keyfp [copyout $manual(merge-copyrights)] puts $keyfp "" close $keyfp ## ## finish off short table of contents ## puts $manual(short-toc-fp) "
Keywords
The keywords from the $tcltkdesc man pages." puts $manual(short-toc-fp) "
" # insert merged copyrights puts $manual(short-toc-fp) [copyout $manual(merge-copyrights)] puts $manual(short-toc-fp) "" close $manual(short-toc-fp) ## ## output man pages ## unset manual(section) if {!$verbose} { puts stderr "Rescanning [llength $manual(all-pages)] pages to build cross links and write out" } foreach path $manual(all-pages) wing_name $manual(all-page-domains) { set manual(wing-file) [file dirname $path] set manual(tail) [file tail $path] set manual(name) [file root $manual(tail)] try { set text $manual(output-$manual(wing-file)-$manual(name)) set ntext 0 foreach item $text { incr ntext [llength [split $item \n]] incr ntext } set toc $manual(toc-$manual(wing-file)-$manual(name)) set ntoc 0 foreach item $toc { incr ntoc [llength [split $item \n]] incr ntoc } if {$verbose} { puts stderr "rescanning page $manual(name) $ntoc/$ntext" } else { puts -nonewline stderr . } set outfd [open $html/$manual(wing-file)/$manual(name).htm w] puts $outfd [htmlhead "$manual($manual(wing-file)-$manual(name)-title)" \ $manual(name) $wing_name "[indexfile]" \ $overall_title "../[indexfile]"] if {($ntext > 60) && ($ntoc > 32)} { foreach item $toc { puts $outfd $item } } elseif {$manual(name) in $forced_index_pages} { if {!$verbose} {puts stderr ""} manerror "forcing index generation" foreach item $toc { puts $outfd $item } } foreach item $text { puts $outfd [insert-cross-references $item] } puts $outfd "" } on error msg { if {$verbose} { puts stderr $msg } else { puts stderr "\nError when processing $manual(name): $msg" } } finally { catch {close $outfd} } } if {!$verbose} { puts stderr "\nDone" } return {} } ## ## Helper for assembling the descriptions of base packages (i.e., Tcl and Tk). ## proc plus-base {var root glob name dir desc} { global tcltkdir if {$var} { if {[file exists $tcltkdir/$root/README]} { set f [open $tcltkdir/$root/README] set d [read $f] close $f if {[regexp {This is the \w+ (\S+) source distribution} $d -> version]} { append name ", version $version" } } set glob $root/$glob return [list $tcltkdir/$glob $name $dir $desc] } } ## ## Helper for assembling the descriptions of contributed packages. ## proc plus-pkgs {type args} { global build_tcl tcltkdir tcldir if {$type ni {n 3}} { error "unknown type \"$type\": must be 3 or n" } if {!$build_tcl} return set result {} set pkgsdir $tcltkdir/$tcldir/pkgs foreach {dir name version} $args { set globpat $pkgsdir/$dir/doc/*.$type if {![llength [glob -type f -nocomplain $globpat]]} { # Fallback for manpages generated using doctools set globpat $pkgsdir/$dir/doc/man/*.$type if {![llength [glob -type f -nocomplain $globpat]]} { continue } } set dir [string trimright $dir "0123456789-."] switch $type { n { set title "$name Package Commands" if {$version ne ""} { append title ", version $version" } set dir [string totitle $dir]Cmd set desc \ "The additional commands provided by the $name package." } 3 { set title "$name Package C API" if {$version ne ""} { append title ", version $version" } set dir [string totitle $dir]Lib set desc \ "The additional C functions provided by the $name package." } } lappend result [list $globpat $title $dir $desc] } return $result } ## ## Set up some special cases. It would be nice if we didn't have them, ## but we do... ## set excluded_pages {case menubar pack-old} set forced_index_pages {GetDash} set process_first_patterns {*/ttk_widget.n */options.n} set ensemble_commands { after array binary chan clock dde dict encoding file history info interp memory namespace package registry self string trace update zlib clipboard console font grab grid image option pack place selection tk tkwait ttk::style winfo wm itcl::delete itcl::find itcl::is } array set remap_link_target { stdin Tcl_GetStdChannel stdout Tcl_GetStdChannel stderr Tcl_GetStdChannel style ttk::style {style map} ttk::style {tk busy} busy library auto_execok safe-tcl safe tclvars env tcl_break catch tcl_continue catch tcl_error catch tcl_ok catch tcl_return catch int() mathfunc wide() mathfunc packagens pkg::create pkgMkIndex pkg_mkIndex pkg_mkIndex pkg_mkIndex Tcl_Obj Tcl_NewObj Tcl_ObjType Tcl_RegisterObjType Tcl_OpenFileChannelProc Tcl_FSOpenFileChannel errorinfo env errorcode env tcl_pkgpath env Tcl_Command Tcl_CreateObjCommand Tcl_CmdProc Tcl_CreateObjCommand Tcl_CmdDeleteProc Tcl_CreateObjCommand Tcl_ObjCmdProc Tcl_CreateObjCommand Tcl_Channel Tcl_OpenFileChannel Tcl_WideInt Tcl_NewIntObj Tcl_ChannelType Tcl_CreateChannel Tcl_DString Tcl_DStringInit Tcl_Namespace Tcl_AppendExportList Tcl_Object Tcl_NewObjectInstance Tcl_Class Tcl_GetObjectAsClass Tcl_Event Tcl_QueueEvent Tcl_Time Tcl_GetTime Tcl_ThreadId Tcl_CreateThread Tk_Window Tk_WindowId Tk_3DBorder Tk_Get3DBorder Tk_Anchor Tk_GetAnchor Tk_Cursor Tk_GetCursor Tk_Dash Tk_GetDash Tk_Font Tk_GetFont Tk_Image Tk_GetImage Tk_ImageMaster Tk_GetImage Tk_ItemType Tk_CreateItemType Tk_Justify Tk_GetJustify Ttk_Theme Ttk_GetTheme } array set exclude_refs_map { bind.n {button destroy option} clock.n {next} history.n {exec} next.n {unknown} zlib.n {binary close filename text} canvas.n {bitmap text} console.n {eval} checkbutton.n {image} clipboard.n {string} entry.n {string} event.n {return} font.n {menu} getOpenFile.n {file open text} grab.n {global} interp.n {time} menu.n {checkbutton radiobutton} messageBox.n {error info} options.n {bitmap image set} radiobutton.n {image} safe.n {join split} scale.n {label variable} scrollbar.n {set} selection.n {string} tcltest.n {error} tkvars.n {tk} tkwait.n {variable} tm.n {exec} ttk_checkbutton.n {variable} ttk_combobox.n {selection} ttk_entry.n {focus variable} ttk_intro.n {focus text} ttk_label.n {font text} ttk_labelframe.n {text} ttk_menubutton.n {flush} ttk_notebook.n {image text} ttk_progressbar.n {variable} ttk_radiobutton.n {variable} ttk_scale.n {variable} ttk_scrollbar.n {set} ttk_spinbox.n {format} ttk_treeview.n {text open} ttk_widget.n {image text variable} TclZlib.3 {binary flush filename text} } array set exclude_when_followed_by_map { canvas.n { bind widget focus widget image are lower widget raise widget } selection.n { clipboard selection clipboard ; } ttk_image.n { image imageSpec } fontchooser.n { tk fontchooser } } try { # Parse what the user told us to do parse_command_line # Some strings depend on what options are specified set tcltkdesc ""; set cmdesc ""; set appdir "" if {$build_tcl} { append tcltkdesc "Tcl" append cmdesc "Tcl" append appdir "$tcldir" } if {$build_tcl && $build_tk} { append tcltkdesc "/" append cmdesc " and " append appdir "," } if {$build_tk} { append tcltkdesc "Tk" append cmdesc "Tk" append appdir "$tkdir" } apply {{} { global packageBuildList tcltkdir tcldir build_tcl # When building docs for Tcl, try to build docs for bundled packages too set packageBuildList {} if {$build_tcl} { set pkgsDir [file join $tcltkdir $tcldir pkgs] set subdirs [glob -nocomplain -types d -tails -directory $pkgsDir *] foreach dir [lsort $subdirs] { # Parse the subdir name into (name, version) as fallback... set description [split $dir -] if {2 != [llength $description]} { regexp {([^0-9]*)(.*)} $dir -> n v set description [list $n $v] } # ... but try to extract (name, version) from subdir contents try { try { set f [open [file join $pkgsDir $dir configure.in]] } trap {POSIX ENOENT} {} { set f [open [file join $pkgsDir $dir configure.ac]] } foreach line [split [read $f] \n] { if {2 == [scan $line \ { AC_INIT ( [%[^]]] , [%[^]]] ) } n v]} { set description [list $n $v] break } } } finally { catch {close $f; unset f} } if {[file exists [file join $pkgsDir $dir configure]]} { # Looks like a package, record our best extraction attempt lappend packageBuildList $dir {*}$description } } } # Get the list of packages to try, and what their human-readable names # are. Note that the package directory list should be version-less. try { set packageDirNameMap {} if {$build_tcl} { set f [open $tcltkdir/$tcldir/pkgs/package.list.txt] try { foreach line [split [read $f] \n] { if {[string trim $line] eq ""} continue if {[string match #* $line]} continue lassign $line dir name lappend packageDirNameMap $dir $name } } finally { close $f } } } trap {POSIX ENOENT} {} { set packageDirNameMap { itcl {[incr Tcl]} tdbc {TDBC} thread Thread } } # Convert to human readable names, if applicable for {set idx 0} {$idx < [llength $packageBuildList]} {incr idx 3} { lassign [lrange $packageBuildList $idx $idx+2] d n v if {[dict exists $packageDirNameMap $n]} { lset packageBuildList $idx+1 [dict get $packageDirNameMap $n] } } }} # # Invoke the scraper/converter engine. # make-man-pages $webdir \ [list $tcltkdir/{$appdir}/doc/*.1 "$tcltkdesc Applications" UserCmd \ "The interpreters which implement $cmdesc."] \ [plus-base $build_tcl $tcldir doc/*.n {Tcl Commands} TclCmd \ "The commands which the tclsh interpreter implements."] \ [plus-base $build_tk $tkdir doc/*.n {Tk Commands} TkCmd \ "The additional commands which the wish interpreter implements."] \ {*}[plus-pkgs n {*}$packageBuildList] \ [plus-base $build_tcl $tcldir doc/*.3 {Tcl C API} TclLib \ "The C functions which a Tcl extended C program may use."] \ [plus-base $build_tk $tkdir doc/*.3 {Tk C API} TkLib \ "The additional C functions which a Tk extended C program may use."] \ {*}[plus-pkgs 3 {*}$packageBuildList] } on error {msg opts} { # On failure make sure we show what went wrong. We're not supposed # to get here though; it represents a bug in the script. puts $msg\n[dict get $opts -errorinfo] exit 1 } # Local-Variables: # mode: tcl # End: tcl8.6.5/tools/tclZIC.tcl0000755000175000017500000010570712663653210014572 0ustar sergeisergei#---------------------------------------------------------------------- # # tclZIC.tcl -- # # Take the time zone data source files from Arthur Olson's # repository at elsie.nci.nih.gov, and prepare time zone # information files for Tcl. # # Usage: # tclsh tclZIC.tcl inputDir outputDir # # Parameters: # inputDir - Directory (e.g., tzdata2003e) where Olson's source # files are to be found. # outputDir - Directory (e.g., ../library/tzdata) where # the time zone information files are to be placed. # # Results: # May produce error messages on the standard error. An exit # code of zero denotes success; any other exit code is failure. # # This program parses the timezone data in a means analogous to the # 'zic' command, and produces Tcl time zone information files suitable # for loading into the 'clock' namespace. # #---------------------------------------------------------------------- # # Copyright (c) 2004 by Kevin B. Kenny. All rights reserved. # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. #---------------------------------------------------------------------- package require Tcl 8.5 # Define the names of the Olson files that we need to load. # We avoid the solar time files and the leap seconds. set olsonFiles { africa antarctica asia australasia backward etcetera europe northamerica pacificnew southamerica systemv } # Define the year at which the DST information will stop. set maxyear 2100 # Determine how big a wide integer is. set MAXWIDE [expr {wide(1)}] while 1 { set next [expr {wide($MAXWIDE + $MAXWIDE + 1)}] if {$next < 0} { break } set MAXWIDE $next } set MINWIDE [expr {-$MAXWIDE-1}] #---------------------------------------------------------------------- # # loadFiles -- # # Loads the time zone files for each continent into memory # # Parameters: # dir - Directory where the time zone source files are found # # Results: # None. # # Side effects: # Calls 'loadZIC' for each continent's data file in turn. # Reports progress on stdout. # #---------------------------------------------------------------------- proc loadFiles {dir} { variable olsonFiles foreach file $olsonFiles { puts "loading: [file join $dir $file]" loadZIC [file join $dir $file] } return } #---------------------------------------------------------------------- # # checkForwardRuleRefs -- # # Checks to make sure that all references to Daylight Saving # Time rules designate defined rules. # # Parameters: # None. # # Results: # None. # # Side effects: # Produces an error message and increases the error count if # any undefined rules are present. # #---------------------------------------------------------------------- proc checkForwardRuleRefs {} { variable forwardRuleRefs variable rules foreach {rule where} [array get forwardRuleRefs] { if {![info exists rules($rule)]} { foreach {fileName lno} $where { puts stderr "$fileName:$lno:can't locate rule \"$rule\"" incr errorCount } } } } #---------------------------------------------------------------------- # # loadZIC -- # # Load one continent's data into memory. # # Parameters: # fileName -- Name of the time zone source file. # # Results: # None. # # Side effects: # The global variable, 'errorCount' counts the number of errors. # The global array, 'links', contains a distillation of the # 'Link' directives in the file. The keys are 'links to' and # the values are 'links from'. The 'parseRule' and 'parseZone' # procedures are called to handle 'Rule' and 'Zone' directives. # #---------------------------------------------------------------------- proc loadZIC {fileName} { variable errorCount variable links # Suck the text into memory. set f [open $fileName r] set data [read $f] close $f # Break the input into lines, and count line numbers. set lno 0 foreach line [split $data \n] { incr lno # Break a line of input into words. regsub {\s*(\#.*)?$} $line {} line if {$line eq ""} { continue } set words {} if {[regexp {^\s} $line]} { # Detect continuations of a zone and flag the list appropriately lappend words "" } lappend words {*}[regexp -all -inline {\S+} $line] # Switch on the directive switch -exact -- [lindex $words 0] { Rule { parseRule $fileName $lno $words } Link { set links([lindex $words 2]) [lindex $words 1] } Zone { set lastZone [lindex $words 1] set until [parseZone $fileName $lno \ $lastZone [lrange $words 2 end] "minimum"] } {} { set i 0 foreach word $words { if {[lindex $words $i] ne ""} { break } incr i } set words [lrange $words $i end] set until [parseZone $fileName $lno $lastZone $words $until] } default { incr errorCount puts stderr "$fileName:$lno:unknown line type \"[lindex $words 0]\"" } } } return } #---------------------------------------------------------------------- # # parseRule -- # # Parses a Rule directive in an Olson file. # # Parameters: # fileName -- Name of the file being parsed. # lno - Line number within the file # words - The line itself, broken into words. # # Results: # None. # # Side effects: # The rule is analyzed and added to the 'rules' array. # Errors are reported and counted. # #---------------------------------------------------------------------- proc parseRule {fileName lno words} { variable rules variable errorCount # Break out the columns lassign $words Rule name from to type in on at save letter # Handle the 'only' keyword if {$to eq "only"} { set to $from } # Process the start year if {![string is integer $from]} { if {![string equal -length [string length $from] $from "minimum"]} { puts stderr "$fileName:$lno:FROM field \"$from\" not an integer." incr errorCount return } else { set from "minimum" } } # Process the end year if {![string is integer $to]} { if {![string equal -length [string length $to] $to "maximum"]} { puts stderr "$fileName:$lno:TO field \"$to\" not an integer." incr errorCount return } else { set to "maximum" } } # Process the type of year in which the rule applies if {$type ne "-"} { puts stderr "$fileName:$lno:year types are not yet supported." incr errorCount return } # Process the month in which the rule starts if {[catch {lookupMonth $in} in]} { puts stderr "$fileName:$lno:$in" incr errorCount return } # Process the day of the month on which the rule starts if {[catch {parseON $on} on]} { puts stderr "$fileName:$lno:$on" incr errorCount return } # Process the time of day on which the rule starts if {[catch {parseTOD $at} at]} { puts stderr "$fileName:$lno:$at" incr errorCount return } # Process the DST adder if {[catch {parseOffsetTime $save} save]} { puts stderr "$fileName:$lno:$save" incr errorCount return } # Process the letter to use for summer time if {$letter eq "-"} { set letter "" } # Accumulate all the data. lappend rules($name) $from $to $type $in $on $at $save $letter return } #---------------------------------------------------------------------- # # parseON -- # # Parse a specification for a day of the month # # Parameters: # on - the ON field from a line in an Olson file. # # Results: # Returns a partial Tcl command. When the year and number of the # month are appended, the command will return the Julian Day Number # of the desired date. # # Side effects: # None. # # The specification can be: # - a simple number, which designates a constant date. # - The name of a weekday, followed by >= or <=, followed by a number. # This designates the nearest occurrence of the given weekday on # or before (on or after) the given day of the month. # - The word 'last' followed by a weekday name with no intervening # space. This designates the last occurrence of the given weekday # in the month. # #---------------------------------------------------------------------- proc parseON {on} { if {![regexp -expanded { ^(?: # first possibility - simple number - field 1 ([[:digit:]]+) | # second possibility - weekday >= (or <=) number # field 2 - weekday ([[:alpha:]]+) # field 3 - direction ([<>]=) # field 4 - number ([[:digit:]]+) | # third possibility - lastWeekday - field 5 last([[:alpha:]]+) )$ } $on -> dom1 wday2 dir2 num2 wday3]} { error "can't parse ON field \"$on\"" } if {$dom1 ne ""} { return [list onDayOfMonth $dom1] } elseif {$wday2 ne ""} { set wday2 [lookupDayOfWeek $wday2] return [list onWeekdayInMonth $wday2 $dir2 $num2] } elseif {$wday3 ne ""} { set wday3 [lookupDayOfWeek $wday3] return [list onLastWeekdayInMonth $wday3] } else { error "in parseOn \"$on\": can't happen" } } #---------------------------------------------------------------------- # # onDayOfMonth -- # # Find a given day of a given month # # Parameters: # day - Day of the month # year - Gregorian year # month - Number of the month (1-12) # # Results: # Returns the Julian Day Number of the desired day. # # Side effects: # None. # #---------------------------------------------------------------------- proc onDayOfMonth {day year month} { scan $day %d day scan $year %d year scan $month %d month set date [::tcl::clock::GetJulianDayFromEraYearMonthDay \ [dict create era CE year $year month $month dayOfMonth $day] \ 2361222] return [dict get $date julianDay] } #---------------------------------------------------------------------- # # onWeekdayInMonth -- # # Find the weekday falling on or after (on or before) a # given day of the month # # Parameters: # dayOfWeek - Day of the week (Monday=1, Sunday=7) # relation - <= for the weekday on or before a given date, >= for # the weekday on or after the given date. # dayOfMonth - Day of the month # year - Gregorian year # month - Number of the month (1-12) # # Results: # Returns the Juloan Day Number of the desired day. # # Side effects: # None. # # onWeekdayInMonth is used to compute Daylight Saving Time rules # like 'Sun>=1' (for the nearest Sunday on or after the first of the month) # or "Mon<=4' (for the Monday on or before the fourth of the month). # #---------------------------------------------------------------------- proc onWeekdayInMonth {dayOfWeek relation dayOfMonth year month} { set date [::tcl::clock::GetJulianDayFromEraYearMonthDay [dict create \ era CE year $year month $month dayOfMonth $dayOfMonth] 2361222] switch -exact -- $relation { <= { return [::tcl::clock::WeekdayOnOrBefore $dayOfWeek \ [dict get $date julianDay]] } >= { return [::tcl::clock::WeekdayOnOrBefore $dayOfWeek \ [expr {[dict get $date julianDay] + 6}]] } } } #---------------------------------------------------------------------- # # onLastWeekdayInMonth -- # # Find the last instance of a given weekday in a month. # # Parameters: # dayOfWeek - Weekday to find (Monday=1, Sunday=7) # year - Gregorian year # month - Month (1-12) # # Results: # Returns the Julian Day number of the last instance of # the given weekday in the given month # # Side effects: # None. # #---------------------------------------------------------------------- proc onLastWeekdayInMonth {dayOfWeek year month} { incr month # Find day 0 of the following month, which is the last day of # the current month. Yes, it works to ask for day 0 of month 13! set date [::tcl::clock::GetJulianDayFromEraYearMonthDay [dict create \ era CE year $year month $month dayOfMonth 0] 2361222] return [::tcl::clock::WeekdayOnOrBefore $dayOfWeek \ [dict get $date julianDay]] } #---------------------------------------------------------------------- # # parseTOD -- # # Parses the specification of a time of day in an Olson file. # # Parameters: # tod - Time of day, which may be followed by 'w', 's', 'u', 'g' # or 'z'. 'w' (or no letter) designates a wall clock time, # 's' designates Standard Time in the given zone, and # 'u', 'g', and 'z' all designate UTC. # # Results: # Returns a two element list containing a count of seconds from # midnight and the letter that followed the time. # # Side effects: # Reports and counts an error if the time cannot be parsed. # #---------------------------------------------------------------------- proc parseTOD {tod} { if {![regexp -expanded { ^ ([[:digit:]]{1,2}) # field 1 - hour (?: :([[:digit:]]{2}) # field 2 - minute (?: :([[:digit:]]{2}) # field 3 - second )? )? (?: ([wsugz]) # field 4 - type indicator )? } $tod -> hour minute second ind]} { puts stderr "$fileName:$lno:can't parse time field \"$tod\"" incr errorCount } scan $hour %d hour if {$minute ne ""} { scan $minute %d minute } else { set minute 0 } if {$second ne ""} { scan $second %d second } else { set second 0 } if {$ind eq ""} { set ind w } return [list [expr {($hour * 60 + $minute) * 60 + $second}] $ind] } #---------------------------------------------------------------------- # # parseOffsetTime -- # # Parses the specification of an offset time in an Olson file. # # Parameters: # offset - Offset time as [+-]hh:mm:ss # # Results: # Returns the offset time as a count of seconds. # # Side effects: # Reports and counts an error if the time cannot be parsed. # #---------------------------------------------------------------------- proc parseOffsetTime {offset} { if {![regexp -expanded { ^ ([-+])? # field 1 - signum ([[:digit:]]{1,2}) # field 2 - hour (?: :([[:digit:]]{2}) # field 3 - minute (?: :([[:digit:]]{2}) # field 4 - second )? )? } $offset -> signum hour minute second]} { puts stderr "$fileName:$lno:can't parse offset time \"$offset\"" incr errorCount } append signum 1 scan $hour %d hour if {$minute ne ""} { scan $minute %d minute } else { set minute 0 } if {$second ne ""} { scan $second %d second } else { set second 0 } return [expr {(($hour * 60 + $minute) * 60 + $second) * $signum}] } #---------------------------------------------------------------------- # # lookupMonth - # Looks up a month by name # # Parameters: # month - Name of a month. # # Results: # Returns the number of the month. # # Side effects: # None. # #---------------------------------------------------------------------- proc lookupMonth {month} { set indx [lsearch -regexp { {} January February March April May June July August September October November December } ${month}.*] if {$indx < 1} { error "unknown month name \"$month\"" } return $indx } #---------------------------------------------------------------------- # # lookupDayOfWeek -- # # Looks up the name of a weekday. # # Parameters: # wday - Weekday name (or a unique prefix). # # Results: # Returns the weekday number (Monday=1, Sunday=7) # # Side effects: # None. # #---------------------------------------------------------------------- proc lookupDayOfWeek {wday} { set indx [lsearch -regexp { {} Monday Tuesday Wednesday Thursday Friday Saturday Sunday } ${wday}.*] if {$indx < 1} { error "unknown weekday name \"$wday\"" } return $indx } #---------------------------------------------------------------------- # # parseZone -- # # Parses a Zone directive in an Olson file # # Parameters: # fileName -- Name of the file being parsed. # lno -- Line number within the file. # zone -- Name of the time zone # words -- Remaining words on the line. # start -- 'Until' time from the previous line if this is a # continuation line, or 'minimum' if this is the first line. # # Results: # Returns the 'until' field of the current line # # Side effects: # Stores a row in the 'zones' array describing the current zone. # The row consists of a start time (year month day tod), a Standard # Time offset from Greenwich, a Daylight Saving Time offset from # Standard Time, and a format for printing the time zone. # # The start time is the result of an earlier call to 'parseUntil' # or else the keyword 'minimum'. The GMT offset is the # result of a call to 'parseOffsetTime'. The Daylight Saving # Time offset is represented as a partial Tcl command. To the # command will be appended a start time (seconds from epoch) # the current offset of Standard Time from Greenwich, the current # offset of Daylight Saving Time from Greenwich, the default # offset from this line, the name pattern from this line, # the 'until' field from this line, and a variable name where points # are to be stored. This command is implemented by the 'applyNoRule', # 'applyDSTOffset' and 'applyRules' procedures. # #---------------------------------------------------------------------- proc parseZone {fileName lno zone words start} { variable zones variable rules variable errorCount variable forwardRuleRefs lassign $words gmtoff save format if {[catch {parseOffsetTime $gmtoff} gmtoff]} { puts stderr "$fileName:$lno:$gmtoff" incr errorCount return } if {[info exists rules($save)]} { set save [list applyRules $save] } elseif {$save eq "-"} { set save [list applyNoRule] } elseif {[catch {parseOffsetTime $save} save2]} { lappend forwardRuleRefs($save) $fileName $lno set save [list applyRules $save] } else { set save [list applyDSTOffset $save2] } lappend zones($zone) $start $gmtoff $save $format if {[llength $words] >= 4} { return [parseUntil [lrange $words 3 end]] } else { return {} } } #---------------------------------------------------------------------- # # parseUntil -- # # Parses the 'UNTIL' part of a 'Zone' directive. # # Parameters: # words - The 'UNTIL' part of the directie. # # Results: # Returns a list comprising the year, the month, the day, and # the time of day. Time of day is represented as the result of # 'parseTOD'. # #---------------------------------------------------------------------- proc parseUntil {words} { variable firstYear if {[llength $words] >= 1} { set year [lindex $words 0] if {![string is integer $year]} { error "can't parse UNTIL field \"$words\"" } if {![info exists firstYear] || $year < $firstYear} { set firstYear $year } } else { set year "maximum" } if {[llength $words] >= 2} { set month [lookupMonth [lindex $words 1]] } else { set month 1 } if {[llength $words] >= 3} { set day [parseON [lindex $words 2]] } else { set day {onDayOfMonth 1} } if {[llength $words] >= 4} { set tod [parseTOD [lindex $words 3]] } else { set tod {0 w} } return [list $year $month $day $tod] } #---------------------------------------------------------------------- # # applyNoRule -- # # Generates time zone data for a zone without Daylight Saving # Time. # # Parameters: # year - Year in which the rule applies # startSecs - Time at which the rule starts. # stdGMTOffset - Offset from Greenwich prior to the start of the # rule # DSTOffset - Offset of Daylight from Standard prior to the # start of the rule. # nextGMTOffset - Offset from Greenwich when the rule is in effect. # namePattern - Name of the timezone. # until - Time at which the rule expires. # pointsVar - Name of a variable in callers scope that receives # transition times # # Results: # Returns a two element list comprising 'nextGMTOffset' and # 0 - the zero indicates that Daylight Saving Time is not # in effect. # # Side effects: # Appends a row to the 'points' variable comprising the start time, # the offset from GMT, a zero (indicating that DST is not in effect), # and the name of the time zone. # #---------------------------------------------------------------------- proc applyNoRule {year startSecs stdGMTOffset DSTOffset nextGMTOffset namePattern until pointsVar} { upvar 1 $pointsVar points lappend points $startSecs $nextGMTOffset 0 \ [convertNamePattern $namePattern -] return [list $nextGMTOffset 0] } #---------------------------------------------------------------------- # # applyDSTOffset -- # # Generates time zone data for a zone with permanent Daylight # Saving Time. # # Parameters: # nextDSTOffset - Offset of Daylight from Standard while the # rule is in effect. # year - Year in which the rule applies # startSecs - Time at which the rule starts. # stdGMTOffset - Offset from Greenwich prior to the start of the # rule # DSTOffset - Offset of Daylight from Standard prior to the # start of the rule. # nextGMTOffset - Offset from Greenwich when the rule is in effect. # namePattern - Name of the timezone. # until - Time at which the rule expires. # pointsVar - Name of a variable in callers scope that receives # transition times # # Results: # Returns a two element list comprising 'nextGMTOffset' and # 'nextDSTOffset'. # # Side effects: # Appends a row to the 'points' variable comprising the start time, # the offset from GMT, a one (indicating that DST is in effect), # and the name of the time zone. # #---------------------------------------------------------------------- proc applyDSTOffset {nextDSTOffset year startSecs stdGMTOffset DSTOffset nextGMTOffset namePattern until pointsVar} { upvar 1 $pointsVar points lappend points \ $startSecs \ [expr {$nextGMTOffset + $nextDSTOffset}] \ 1 \ [convertNamePattern $namePattern S] return [list $nextGMTOffset $nextDSTOffset] } #---------------------------------------------------------------------- # # applyRules -- # # Applies a rule set to a time zone for a given range of time # # Parameters: # ruleSet - Name of the rule set to apply # year - Starting year for the rules # startSecs - Time at which the rules begin to apply # stdGMTOffset - Offset from Greenwich prior to the start of the # rules. # DSTOffset - Offset of Daylight from Standard prior to the # start of the rules. # nextGMTOffset - Offset from Greenwich when the rules are in effect. # namePattern - Name pattern for the time zone. # until - Time at which the rule set expires. # pointsVar - Name of a variable in callers scope that receives # transition times # # Results: # Returns a two element list comprising the offset from GMT # to Standard and the offset from Standard to Daylight (if DST # is in effect) at the end of the period in which the rules apply # # Side effects: # Appends one or more rows to the 'points' variable, each of which # comprises a transition time, the offset from GMT that is # in effect after the transition, a flag for whether DST is in # effect, and the name of the time zone. # #---------------------------------------------------------------------- proc applyRules {ruleSet year startSecs stdGMTOffset DSTOffset nextGMTOffset namePattern until pointsVar} { variable done variable rules variable maxyear upvar 1 $pointsVar points # Extract the rules that apply to the current year, and the number # of rules (now or in future) that will end at a specific year. # Ignore rules entirely in the past. lassign [divideRules $ruleSet $year] currentRules nSunsetRules # If the first transition is later than $startSecs, and $stdGMTOffset is # different from $nextGMTOffset, we will need an initial record like: # lappend points $startSecs $stdGMTOffset 0 \ # [convertNamePattern $namePattern -] set didTransitionIn false # Determine the letter to use in Standard Time set prevLetter "" foreach { fromYear toYear yearType monthIn daySpecOn timeAt save letter } $rules($ruleSet) { if {$save == 0} { set prevLetter $letter break } } # Walk through each year in turn. This loop will break when # (a) the 'until' time is passed # or (b) the 'until' time is empty and all remaining rules extend to # the end of time set stdGMTOffset $nextGMTOffset # convert "until" to seconds from epoch in current time zone if {$until ne ""} { lassign $until untilYear untilMonth untilDaySpec untilTimeOfDay lappend untilDaySpec $untilYear $untilMonth set untilJCD [eval $untilDaySpec] set untilBaseSecs [expr { wide(86400) * wide($untilJCD) - 210866803200 }] set untilSecs [convertTimeOfDay $untilBaseSecs $stdGMTOffset \ $DSTOffset {*}$untilTimeOfDay] } set origStartSecs $startSecs while {($until ne "" && $startSecs < $untilSecs) || ($until eq "" && ($nSunsetRules > 0 || $year < $maxyear))} { set remainingRules $currentRules while {[llength $remainingRules] > 0} { # Find the rule with the earliest start time from among the # active rules that haven't yet been processed. lassign [findEarliestRule $remainingRules $year \ $stdGMTOffset $DSTOffset] earliestSecs earliestIndex set endi [expr {$earliestIndex + 7}] set rule [lrange $remainingRules $earliestIndex $endi] lassign $rule fromYear toYear \ yearType monthIn daySpecOn timeAt save letter # Test if the rule is in effect. if { $earliestSecs > $startSecs && ($until eq "" || $earliestSecs < $untilSecs) } { # Test if the initial transition has been done. # If not, do it now. if {!$didTransitionIn && $earliestSecs > $origStartSecs} { set nm [convertNamePattern $namePattern $prevLetter] lappend points \ $origStartSecs \ [expr {$stdGMTOffset + $DSTOffset}] \ 0 \ $nm set didTransitionIn true } # Add a row to 'points' for the rule set nm [convertNamePattern $namePattern $letter] lappend points \ $earliestSecs \ [expr {$stdGMTOffset + $save}] \ [expr {$save != 0}] \ $nm } # Remove the rule just applied from the queue set remainingRules [lreplace \ $remainingRules[set remainingRules {}] \ $earliestIndex $endi] # Update current DST offset and time zone letter set DSTOffset $save set prevLetter $letter # Reconvert the 'until' time in the current zone. if {$until ne ""} { set untilSecs [convertTimeOfDay $untilBaseSecs \ $stdGMTOffset $DSTOffset {*}$untilTimeOfDay] } } # Advance to the next year incr year set date [::tcl::clock::GetJulianDayFromEraYearMonthDay \ [dict create era CE year $year month 1 dayOfMonth 1] 2361222] set startSecs [expr { [dict get $date julianDay] * wide(86400) - 210866803200 - $stdGMTOffset - $DSTOffset }] # Get rules in effect in the new year. lassign [divideRules $ruleSet $year] currentRules nSunsetRules } return [list $stdGMTOffset $DSTOffset] } #---------------------------------------------------------------------- # # divideRules -- # Determine what Daylight Saving Time rules may be in effect in # a given year. # # Parameters: # ruleSet - Set of rules from 'parseRule' # year - Year to test # # Results: # Returns a two element list comprising the subset of 'ruleSet' # that is in effect in the given year, and the count of rules # that expire in the future (as opposed to those that expire in # the past or not at all). If this count is zero, the rules do # not change in future years. # # Side effects: # None. # #---------------------------------------------------------------------- proc divideRules {ruleSet year} { variable rules set currentRules {} set nSunsetRules 0 foreach { fromYear toYear yearType monthIn daySpecOn timeAt save letter } $rules($ruleSet) { if {$toYear ne "maximum" && $year > $toYear} { # ignore - rule is in the past } else { if {$fromYear eq "minimum" || $fromYear <= $year} { lappend currentRules $fromYear $toYear $yearType $monthIn \ $daySpecOn $timeAt $save $letter } if {$toYear ne "maximum"} { incr nSunsetRules } } } return [list $currentRules $nSunsetRules] } #---------------------------------------------------------------------- # # findEarliestRule -- # # Find the rule in a rule set that has the earliest start time. # # Parameters: # remainingRules -- Rules to search # year - Year being processed. # stdGMTOffset - Current offset of standard time from GMT # DSTOffset - Current offset of daylight time from standard, # if daylight time is in effect. # # Results: # Returns the index in remainingRules of the next rule to # go into effect. # # Side effects: # None. # #---------------------------------------------------------------------- proc findEarliestRule {remainingRules year stdGMTOffset DSTOffset} { set earliest $::MAXWIDE set i 0 foreach { fromYear toYear yearType monthIn daySpecOn timeAt save letter } $remainingRules { lappend daySpecOn $year $monthIn set dayIn [eval $daySpecOn] set secs [expr {wide(86400) * wide($dayIn) - 210866803200}] set secs [convertTimeOfDay $secs \ $stdGMTOffset $DSTOffset {*}$timeAt] if {$secs < $earliest} { set earliest $secs set earliestIdx $i } incr i 8 } return [list $earliest $earliestIdx] } #---------------------------------------------------------------------- # # convertNamePattern -- # # Converts a name pattern to the name of the time zone. # # Parameters: # pattern - Patthern to convert # flag - Daylight Time flag. An empty string denotes Standard # Time, anything else is Daylight Time. # # Results; # Returns the name of the time zone. # # Side effects: # None. # #---------------------------------------------------------------------- proc convertNamePattern {pattern flag} { if {[regexp {(.*)/(.*)} $pattern -> standard daylight]} { if {$flag ne ""} { set pattern $daylight } else { set pattern $standard } } return [string map [list %s $flag] $pattern] } #---------------------------------------------------------------------- # # convertTimeOfDay -- # # Takes a time of day specifier from 'parseAt' and converts # to seconds from the Epoch, # # Parameters: # seconds -- Time at which the GMT day starts, in seconds # from the Posix epoch # stdGMTOffset - Offset of Standard Time from Greenwich # DSTOffset - Offset of Daylight Time from standard. # timeOfDay - Time of day to convert, in seconds from midnight # flag - Flag indicating whether the time is Greenwich, Standard # or wall-clock. (g, s, or w) # # Results: # Returns the time of day in seconds from the Posix epoch. # # Side effects: # None. # #---------------------------------------------------------------------- proc convertTimeOfDay {seconds stdGMTOffset DSTOffset timeOfDay flag} { incr seconds $timeOfDay switch -exact $flag { g - u - z { } w { incr seconds [expr {-$stdGMTOffset}] incr seconds [expr {-$DSTOffset}] } s { incr seconds [expr {-$stdGMTOffset}] } } return $seconds } #---------------------------------------------------------------------- # # processTimeZone -- # # Generate the information about all time transitions in a # time zone. # # Parameters: # zoneName - Name of the time zone # zoneData - List containing the rows describing the time zone, # obtained from 'parseZone. # # Results: # Returns a list of rows. Each row consists of a time in # seconds from the Posix epoch, an offset from GMT to local # that begins at that time, a flag indicating whether DST # is in effect after that time, and the printable name of the # timezone that goes into effect at that time. # # Side effects: # None. # #---------------------------------------------------------------------- proc processTimeZone {zoneName zoneData} { set points {} set i 0 foreach {startTime nextGMTOffset dstRule namePattern} $zoneData { incr i 4 set until [lindex $zoneData $i] if {![info exists stdGMTOffset]} { set stdGMTOffset $nextGMTOffset } if {![info exists DSTOffset]} { set DSTOffset 0 } if {$startTime eq "minimum"} { set secs $::MINWIDE set year 0 } else { lassign $startTime year month dayRule timeOfDay lappend dayRule $year $month set startDay [eval $dayRule] set secs [expr {wide(86400) * wide($startDay) -210866803200}] set secs [convertTimeOfDay $secs \ $stdGMTOffset $DSTOffset {*}$timeOfDay] } lappend dstRule \ $year $secs $stdGMTOffset $DSTOffset $nextGMTOffset \ $namePattern $until points lassign [eval $dstRule] stdGMTOffset DSTOffset } return $points } #---------------------------------------------------------------------- # # writeZones -- # # Writes all the time zone information files. # # Parameters: # outDir - Directory in which to store the files. # # Results: # None. # # Side effects: # Writes the time zone information files; traces what's happening # on the standard output. # #---------------------------------------------------------------------- proc writeZones {outDir} { variable zones # Walk the zones foreach zoneName [lsort -dictionary [array names zones]] { puts "calculating: $zoneName" set fileName [eval [list file join $outDir] [file split $zoneName]] # Create directories as needed set dirName [file dirname $fileName] if {![file exists $dirName]} { puts "creating directory: $dirName" file mkdir $dirName } # Generate data for a zone set data "" foreach { time offset dst name } [processTimeZone $zoneName $zones($zoneName)] { append data "\n " [list [list $time $offset $dst $name]] } append data \n # Write the data to the information file set f [open $fileName w] fconfigure $f -translation lf puts $f "\# created by $::argv0 - do not edit" puts $f "" puts $f [list set TZData(:$zoneName) $data] close $f } return } #---------------------------------------------------------------------- # # writeLinks -- # # Write files describing time zone synonyms (the Link directives # from the Olson files) # # Parameters: # outDir - Name of the directory where the output files go. # # Results: # None. # # Side effects: # Creates a file for each link. proc writeLinks {outDir} { variable links # Walk the links foreach zoneName [lsort -dictionary [array names links]] { puts "creating link: $zoneName" set fileName [eval [list file join $outDir] [file split $zoneName]] # Create directories as needed set dirName [file dirname $fileName] if {![file exists $dirName]} { puts "creating directory: $dirName" file mkdir $dirName } # Create code for the synonym set linkTo $links($zoneName) set sourceCmd "\n [list LoadTimeZoneFile $linkTo]\n" set ifCmd [list if "!\[info exists TZData($linkTo)\]" $sourceCmd] set setCmd "set TZData(:$zoneName) \$TZData(:$linkTo)" # Write the file set f [open $fileName w] fconfigure $f -translation lf puts $f "\# created by $::argv0 - do not edit" puts $f $ifCmd puts $f $setCmd close $f } return } #---------------------------------------------------------------------- # # MAIN PROGRAM # #---------------------------------------------------------------------- puts "Compiling time zones -- [clock format [clock seconds] \ -format {%x %X} -locale system]" # Determine directories lassign $argv inDir outDir puts "Olson files in $inDir" puts "Tcl files to be placed in $outDir" # Initialize count of errors set errorCount 0 # Parse the Olson files loadFiles $inDir if {$errorCount > 0} { exit 1 } # Check that all riles appearing in Zone and Link lines actually exist checkForwardRuleRefs if {$errorCount > 0} { exit 1 } # Write the time zone information files writeZones $outDir writeLinks $outDir if {$errorCount > 0} { exit 1 } # All done! exit tcl8.6.5/tools/makeTestCases.tcl0000755000175000017500000007765012663660066016212 0ustar sergeisergei# TODO - When integrating this with the Core, path names will need to be # swizzled here. package require msgcat set d [file dirname [file dirname [info script]]] puts "getting transition data from [file join $d library tzdata America Detroit]" source [file join $d library/tzdata/America/Detroit] namespace eval ::tcl::clock { ::msgcat::mcmset en_US_roman { LOCALE_ERAS { {-62164627200 {} 0} {-59008867200 c 100} {-55853107200 cc 200} {-52697347200 ccc 300} {-49541587200 cd 400} {-46385827200 d 500} {-43230067200 dc 600} {-40074307200 dcc 700} {-36918547200 dccc 800} {-33762787200 cm 900} {-30607027200 m 1000} {-27451267200 mc 1100} {-24295507200 mcc 1200} {-21139747200 mccc 1300} {-17983987200 mcd 1400} {-14828227200 md 1500} {-11672467200 mdc 1600} {-8516707200 mdcc 1700} {-5364662400 mdccc 1800} {-2208988800 mcm 1900} {946684800 mm 2000} } LOCALE_NUMERALS { ? i ii iii iv v vi vii viii ix x xi xii xiii xiv xv xvi xvii xviii xix xx xxi xxii xxiii xxiv xxv xxvi xxvii xxviii xxix xxx xxxi xxxii xxxiii xxxiv xxxv xxxvi xxxvii xxxviii xxxix xl xli xlii xliii xliv xlv xlvi xlvii xlviii xlix l li lii liii liv lv lvi lvii lviii lix lx lxi lxii lxiii lxiv lxv lxvi lxvii lxviii lxix lxx lxxi lxxii lxxiii lxxiv lxxv lxxvi lxxvii lxxviii lxxix lxxx lxxxi lxxxii lxxxiii lxxxiv lxxxv lxxxvi lxxxvii lxxxviii lxxxix xc xci xcii xciii xciv xcv xcvi xcvii xcviii xcix c } DATE_FORMAT {%m/%d/%Y} TIME_FORMAT {%H:%M:%S} DATE_TIME_FORMAT {%x %X} LOCALE_DATE_FORMAT {die %Od mensis %Om annoque %EY} LOCALE_TIME_FORMAT {%OH h %OM m %OS s} LOCALE_DATE_TIME_FORMAT {%Ex %EX} } } #---------------------------------------------------------------------- # # listYears -- # # List the years to test in the common clock test cases. # # Parameters: # startOfYearArray - Name of an array in caller's scope that will # be initialized as # Results: # None # # Side effects: # Determines the year numbers of one common year, one leap year, one year # following a common year, and one year following a leap year -- starting # on each day of the week -- in the XIXth, XXth and XXIth centuries. # Initializes the given array to have keys equal to the year numbers and # values equal to [clock seconds] at the start of the corresponding # years. # #---------------------------------------------------------------------- proc listYears { startOfYearArray } { upvar 1 $startOfYearArray startOfYear # List years after 1970 set y 1970 set s 0 set dw 4 ;# Thursday while { $y < 2100 } { if { $y % 4 == 0 && $y % 100 != 0 || $y % 400 == 0 } { set l 1 incr dw 366 set s2 [expr { $s + wide( 366 * 86400 ) }] } else { set l 0 incr dw 365 set s2 [expr { $s + wide( 365 * 86400 ) }] } set x [expr { $y >= 2037 }] set dw [expr {$dw % 7}] set c [expr { $y / 100 }] if { ![info exists do($x$c$dw$l)] } { set do($x$c$dw$l) $y set startOfYear($y) $s set startOfYear([expr {$y + 1}]) $s2 } set s $s2 incr y } # List years before 1970 set y 1970 set s 0 set dw 4; # Thursday while { $y >= 1801 } { set s0 $s incr dw 371 incr y -1 if { $y % 4 == 0 && $y % 100 != 0 || $y % 400 == 0 } { set l 1 incr dw -366 set s [expr { $s - wide(366 * 86400) }] } else { set l 0 incr dw -365 set s [expr { $s - wide(365 * 86400) }] } set dw [expr {$dw % 7}] set c [expr { $y / 100 }] if { ![info exists do($c$dw$l)] } { set do($c$dw$l) $y set startOfYear($y) $s set startOfYear([expr {$y + 1}]) $s0 } } } #---------------------------------------------------------------------- # # processFile - # # Processes the 'clock.test' file, updating the test cases in it. # # Parameters: # None. # # Side effects: # Replaces the file with a new copy, constructing needed test cases. # #---------------------------------------------------------------------- proc processFile {d} { # Open two files set f1 [open [file join $d tests/clock.test] r] set f2 [open [file join $d tests/clock.new] w] # Copy leading portion of the test file set state {} while { [gets $f1 line] >= 0 } { switch -exact -- $state { {} { puts $f2 $line if { [regexp "^\# BEGIN (.*)" $line -> cases] && [string compare {} [info commands $cases]] } { set state inCaseSet $cases $f2 } } inCaseSet { if { [regexp "^\#\ END $cases\$" $line] } { puts $f2 $line set state {} } } } } # Rotate the files close $f1 close $f2 file delete -force [file join $d tests/clock.bak] file rename -force [file join $d tests/clock.test] \ [file join $d tests/clock.bak] file rename [file join $d tests/clock.new] [file join $d tests/clock.test] } #---------------------------------------------------------------------- # # testcases2 -- # # Outputs the 'clock-2.x' test cases. # # Parameters: # f2 -- Channel handle to the output file # # Results: # None. # # Side effects: # Test cases for formatting in Gregorian calendar are written to the # output file. # #---------------------------------------------------------------------- proc testcases2 { f2 } { listYears startOfYear # Define the roman numerals set roman { ? i ii iii iv v vi vii viii ix x xi xii xiii xiv xv xvi xvii xviii xix xx xxi xxii xxiii xxiv xxv xxvi xxvii xxviii xxix xxx xxxi xxxii xxxiii xxxiv xxxv xxxvi xxxvii xxxviii xxxix xl xli xlii xliii xliv xlv xlvi xlvii xlviii xlix l li lii liii liv lv lvi lvii lviii lix lx lxi lxii lxiii lxiv lxv lxvi lxvii lxviii lxix lxx lxxi lxxii lxxiii lxxiv lxxv lxxvi lxxvii lxxviii lxxix lxxx lxxxi lxxxii lxxxiii lxxxiv lxxxv lxxxvi lxxxvii lxxxviii lxxxix xc xci xcii xciii xciv xcv xcvi xcvii xcviii xcix c } set romanc { ? c cc ccc cd d dc dcc dccc cm m mc mcc mccc mcd md mdc mdcc mdccc mcm mm mmc mmcc mmccc mmcd mmd mmdc mmdcc mmdccc mmcm mmm mmmc mmmcc mmmccc mmmcd mmmd mmmdc mmmdcc mmmdccc mmmcm } # Names of the months set short {{} Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec} set long { {} January February March April May June July August September October November December } # Put out a header describing the tests puts $f2 "" puts $f2 "\# Test formatting of Gregorian year, month, day, all formats" puts $f2 "\# Formats tested: %b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y %EY" puts $f2 "" # Generate the test cases for the first and last day of every month # from 1896 to 2045 set n 0 foreach { y } [lsort -integer [array names startOfYear]] { set s [expr { $startOfYear($y) + wide(12*3600 + 34*60 + 56) }] set m 0 set yd 1 foreach hath { 31 28 31 30 31 30 31 31 30 31 30 31 } { incr m if { $m == 2 && ( $y%4 == 0 && $y%100 != 0 || $y%400 == 0 ) } { incr hath } set b [lindex $short $m] set B [lindex $long $m] set C [format %02d [expr { $y / 100 }]] set h $b set j [format %03d $yd] set mm [format %02d $m] set N [format %2d $m] set yy [format %02d [expr { $y % 100 }]] set J [expr { ( $s / 86400 ) + 2440588 }] set dt $y-$mm-01 set result "" append result $b " " $B " " \ $mm /01/ $y " 12:34:56 " \ "die i mensis " [lindex $roman $m] " annoque " \ [lindex $romanc [expr { $y / 100 }]] \ [lindex $roman [expr { $y % 100 }]] " " \ [lindex $roman 12] " h " [lindex $roman 34] " m " \ [lindex $roman 56] " s " \ $C " " [lindex $romanc [expr { $y / 100 }]] \ " 01 i 1 i " \ $h " " $j " " $J " " $mm " " [lindex $roman $m] " " $N \ " " $mm "/01/" $y \ " die i mensis " [lindex $roman $m] " annoque " \ [lindex $romanc [expr { $y / 100 }]] \ [lindex $roman [expr { $y % 100 }]] \ " " $yy " " [lindex $roman [expr { $y % 100 }]] " " $y puts $f2 "test clock-2.[incr n] {conversion of $dt} {" puts $f2 " clock format $s \\" puts $f2 "\t-format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \\" puts $f2 "\t-gmt true -locale en_US_roman" puts $f2 "} {$result}" set hm1 [expr { $hath - 1 }] incr s [expr { 86400 * ( $hath - 1 ) }] incr yd $hm1 set dd [format %02d $hath] set ee [format %2d $hath] set j [format %03d $yd] set J [expr { ( $s / 86400 ) + 2440588 }] set dt $y-$mm-$dd set result "" append result $b " " $B " " \ $mm / $dd / $y " 12:34:56 " \ "die " [lindex $roman $hath] " mensis " [lindex $roman $m] \ " annoque " \ [lindex $romanc [expr { $y / 100 }]] \ [lindex $roman [expr { $y % 100 }]] " " \ [lindex $roman 12] " h " [lindex $roman 34] " m " \ [lindex $roman 56] " s " \ $C " " [lindex $romanc [expr { $y / 100 }]] \ " " $dd " " [lindex $roman $hath] " " \ $ee " " [lindex $roman $hath] " "\ $h " " $j " " $J " " $mm " " [lindex $roman $m] " " $N \ " " $mm "/" $dd "/" $y \ " die " [lindex $roman $hath] " mensis " [lindex $roman $m] \ " annoque " \ [lindex $romanc [expr { $y / 100 }]] \ [lindex $roman [expr { $y % 100 }]] \ " " $yy " " [lindex $roman [expr { $y % 100 }]] " " $y puts $f2 "test clock-2.[incr n] {conversion of $dt} {" puts $f2 " clock format $s \\" puts $f2 "\t-format {%b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y} \\" puts $f2 "\t-gmt true -locale en_US_roman" puts $f2 "} {$result}" incr s 86400 incr yd } } puts "testcases2: $n test cases" } #---------------------------------------------------------------------- # # testcases3 -- # # Generate test cases for ISO8601 calendar. # # Parameters: # f2 - Channel handle to the output file # # Results: # None # # Side effects: # Makes a test case for the first and last day of weeks 51, 52, and 1 # plus the first and last day of a year. Does so for each possible # weekday on which a Common Year or Leap Year can begin. # #---------------------------------------------------------------------- proc testcases3 { f2 } { listYears startOfYear set case 0 foreach { y } [lsort -integer [array names startOfYear]] { set secs $startOfYear($y) set ym1 [expr { $y - 1 }] set dow [expr { ( $secs / 86400 + 4 ) % 7}] switch -exact $dow { 0 { # Year starts on a Sunday. # Prior year started on a Friday or Saturday, and was # a 52-week year. # 1 January is ISO week 52 of the prior year. 2 January # begins ISO week 1 of the current year. # 1 January is week 1 according to %U. According to %W, # week 1 begins on 2 January testISO $f2 $ym1 52 1 [expr { $secs - 6*86400 }] testISO $f2 $ym1 52 6 [expr { $secs - 86400 }] testISO $f2 $ym1 52 7 $secs testISO $f2 $y 1 1 [expr { $secs + 86400 }] testISO $f2 $y 1 6 [expr { $secs + 6*86400}] testISO $f2 $y 1 7 [expr { $secs + 7*86400 }] testISO $f2 $y 2 1 [expr { $secs + 8*86400 }] } 1 { # Year starts on a Monday. # Previous year started on a Saturday or Sunday, and was # a 52-week year. # 1 January is ISO week 1 of the current year # According to %U, it's week 0 until 7 January # 1 January is week 1 according to %W testISO $f2 $ym1 52 1 [expr { $secs - 7*86400 }] testISO $f2 $ym1 52 6 [expr {$secs - 2*86400}] testISO $f2 $ym1 52 7 [expr { $secs - 86400 }] testISO $f2 $y 1 1 $secs testISO $f2 $y 1 6 [expr {$secs + 5*86400}] testISO $f2 $y 1 7 [expr { $secs + 6*86400 }] testISO $f2 $y 2 1 [expr { $secs + 7*86400 }] } 2 { # Year starts on a Tuesday. testISO $f2 $ym1 52 1 [expr { $secs - 8*86400 }] testISO $f2 $ym1 52 6 [expr {$secs - 3*86400}] testISO $f2 $ym1 52 7 [expr { $secs - 2*86400 }] testISO $f2 $y 1 1 [expr { $secs - 86400 }] testISO $f2 $y 1 2 $secs testISO $f2 $y 1 6 [expr {$secs + 4*86400}] testISO $f2 $y 1 7 [expr { $secs + 5*86400 }] testISO $f2 $y 2 1 [expr { $secs + 6*86400 }] } 3 { testISO $f2 $ym1 52 1 [expr { $secs - 9*86400 }] testISO $f2 $ym1 52 6 [expr {$secs - 4*86400}] testISO $f2 $ym1 52 7 [expr { $secs - 3*86400 }] testISO $f2 $y 1 1 [expr { $secs - 2*86400 }] testISO $f2 $y 1 3 $secs testISO $f2 $y 1 6 [expr {$secs + 3*86400}] testISO $f2 $y 1 7 [expr { $secs + 4*86400 }] testISO $f2 $y 2 1 [expr { $secs + 5*86400 }] } 4 { testISO $f2 $ym1 52 1 [expr { $secs - 10*86400 }] testISO $f2 $ym1 52 6 [expr {$secs - 5*86400}] testISO $f2 $ym1 52 7 [expr { $secs - 4*86400 }] testISO $f2 $y 1 1 [expr { $secs - 3*86400 }] testISO $f2 $y 1 4 $secs testISO $f2 $y 1 6 [expr {$secs + 2*86400}] testISO $f2 $y 1 7 [expr { $secs + 3*86400 }] testISO $f2 $y 2 1 [expr { $secs + 4*86400 }] } 5 { testISO $f2 $ym1 53 1 [expr { $secs - 4*86400 }] testISO $f2 $ym1 53 5 $secs testISO $f2 $ym1 53 6 [expr {$secs + 86400}] testISO $f2 $ym1 53 7 [expr { $secs + 2*86400 }] testISO $f2 $y 1 1 [expr { $secs + 3*86400 }] testISO $f2 $y 1 6 [expr {$secs + 8*86400}] testISO $f2 $y 1 7 [expr { $secs + 9*86400 }] testISO $f2 $y 2 1 [expr { $secs + 10*86400 }] } 6 { # messy case because previous year may have had 52 or 53 weeks if { $y%4 == 1 } { testISO $f2 $ym1 53 1 [expr { $secs - 5*86400 }] testISO $f2 $ym1 53 6 $secs testISO $f2 $ym1 53 7 [expr { $secs + 86400 }] } else { testISO $f2 $ym1 52 1 [expr { $secs - 5*86400 }] testISO $f2 $ym1 52 6 $secs testISO $f2 $ym1 52 7 [expr { $secs + 86400 }] } testISO $f2 $y 1 1 [expr { $secs + 2*86400 }] testISO $f2 $y 1 6 [expr { $secs + 7*86400 }] testISO $f2 $y 1 7 [expr { $secs + 8*86400 }] testISO $f2 $y 2 1 [expr { $secs + 9*86400 }] } } } puts "testcases3: $case test cases." } proc testISO { f2 G V u secs } { upvar 1 case case set longdays {Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday} set shortdays {Sun Mon Tue Wed Thu Fri Sat Sun} puts $f2 "test clock-3.[incr case] {ISO week-based calendar [format %04d-W%02d-%d $G $V $u]} {" puts $f2 " clock format $secs -format {%a %A %g %G %u %U %V %w %W} -gmt true; \# $G-W[format %02d $V]-$u" puts $f2 "} {[lindex $shortdays $u] [lindex $longdays $u]\ [format %02d [expr { $G % 100 }]] $G\ $u\ [clock format $secs -format %U -gmt true]\ [format %02d $V] [expr { $u % 7 }]\ [clock format $secs -format %W -gmt true]}" } #---------------------------------------------------------------------- # # testcases4 -- # # Makes the test cases that test formatting of time of day. # # Parameters: # f2 - Channel handle to the output file # # Results: # None. # # Side effects: # Writes test cases to the output. # #---------------------------------------------------------------------- proc testcases4 { f2 } { puts $f2 {} puts $f2 "\# Test formatting of time of day" puts $f2 "\# Format groups tested: %H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+" puts $f2 {} set i 0 set fmt "%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+" foreach { h romanH I romanI am } { 0 ? 12 xii AM 1 i 1 i AM 11 xi 11 xi AM 12 xii 12 xii PM 13 xiii 1 i PM 23 xxiii 11 xi PM } { set hh [format %02d $h] set II [format %02d $I] set hs [format %2d $h] set Is [format %2d $I] foreach { m romanM } { 0 ? 1 i 58 lviii 59 lix } { set mm [format %02d $m] foreach { s romanS } { 0 ? 1 i 58 lviii 59 lix } { set ss [format %02d $s] set x [expr { ( $h * 60 + $m ) * 60 + $s }] set result "" append result $hh " " $romanH " " $II " " $romanI " " \ $hs " " $romanH " " $Is " " $romanI " " $mm " " $romanM " " \ $am " " [string tolower $am] " " \ $II ":" $mm ":" $ss " " [string tolower $am] " " \ $hh ":" $mm " " \ $ss " " $romanS " " \ $hh ":" $mm ":" $ss " " \ $hh ":" $mm ":" $ss " " \ $romanH " h " $romanM " m " $romanS " s " \ "Thu Jan 1 " $hh : $mm : $ss " GMT 1970" puts $f2 "test clock-4.[incr i] { format time of day $hh:$mm:$ss } {" puts $f2 " clock format $x \\" puts $f2 " -format [list $fmt] \\" puts $f2 " -locale en_US_roman \\" puts $f2 " -gmt true" puts $f2 "} {$result}" } } } puts "testcases4: $i test cases." } #---------------------------------------------------------------------- # # testcases5 -- # # Generates the test cases for Daylight Saving Time # # Parameters: # f2 - Channel handle for the input file # # Results: # None. # # Side effects: # Makes test cases for each known or anticipated time change # in Detroit. # #---------------------------------------------------------------------- proc testcases5 { f2 } { variable TZData puts $f2 {} puts $f2 "\# Test formatting of Daylight Saving Time" puts $f2 {} set fmt {%H:%M:%S %z %Z} set i 0 puts $f2 "test clock-5.[incr i] {does Detroit exist} {" puts $f2 " clock format 0 -format {} -timezone :America/Detroit" puts $f2 " concat" puts $f2 "} {}" puts $f2 "test clock-5.[incr i] {does Detroit have a Y2038 problem} detroit {" puts $f2 " if { \[clock format 2158894800 -format %z -timezone :America/Detroit\] ne {-0400} } {" puts $f2 " concat {y2038 problem}" puts $f2 " } else {" puts $f2 " concat {ok}" puts $f2 " }" puts $f2 "} ok" foreach row $TZData(:America/Detroit) { foreach { t offset isdst tzname } $row break if { $t > -4000000000000 } { set conds [list detroit] if { $t > wide(0x7fffffff) } { set conds [list detroit y2038] } incr t -1 set x [clock format $t -format {%Y-%m-%d %H:%M:%S} \ -timezone :America/Detroit] set r [clock format $t -format $fmt \ -timezone :America/Detroit] puts $f2 "test clock-5.[incr i] {time zone boundary case $x} [list $conds] {" puts $f2 " clock format $t -format [list $fmt] \\" puts $f2 " -timezone :America/Detroit" puts $f2 "} [list $r]" incr t set x [clock format $t -format {%Y-%m-%d %H:%M:%S} \ -timezone :America/Detroit] set r [clock format $t -format $fmt \ -timezone :America/Detroit] puts $f2 "test clock-5.[incr i] {time zone boundary case $x} [list $conds] {" puts $f2 " clock format $t -format [list $fmt] \\" puts $f2 " -timezone :America/Detroit" puts $f2 "} [list $r]" incr t set x [clock format $t -format {%Y-%m-%d %H:%M:%S} \ -timezone :America/Detroit] set r [clock format $t -format $fmt \ -timezone :America/Detroit] puts $f2 "test clock-5.[incr i] {time zone boundary case $x} [list $conds] {" puts $f2 " clock format $t -format [list $fmt] \\" puts $f2 " -timezone :America/Detroit" puts $f2 "} [list $r]" } } puts "testcases5: $i test cases" } #---------------------------------------------------------------------- # # testcases8 -- # # Outputs the 'clock-8.x' test cases. # # Parameters: # f2 -- Channel handle to the output file # # Results: # None. # # Side effects: # Test cases for parsing dates in ccyymmdd format are written to the # output file. # #---------------------------------------------------------------------- proc testcases8 { f2 } { # Put out a header describing the tests puts $f2 "" puts $f2 "\# Test parsing of ccyymmdd" puts $f2 "" set n 0 foreach year {1970 1971 2000 2001} { foreach month {01 12} { foreach day {02 31} { set scanned [clock scan $year$month$day -gmt true] foreach ccyy {%C%y %Y} { foreach mm {%b %B %h %m %Om %N} { foreach dd {%d %Od %e %Oe} { set string [clock format $scanned \ -format "$ccyy $mm $dd" \ -locale en_US_roman \ -gmt true] puts $f2 "test clock-8.[incr n] {parse ccyymmdd} {" puts $f2 " [list clock scan $string -format [list $ccyy $mm $dd] -locale en_US_roman -gmt 1]" puts $f2 "} $scanned" } } } foreach fmt {%x %D} { set string [clock format $scanned \ -format $fmt \ -locale en_US_roman \ -gmt true] puts $f2 "test clock-8.[incr n] {parse ccyymmdd} {" puts $f2 " [list clock scan $string -format $fmt -locale en_US_roman -gmt 1]" puts $f2 "} $scanned" } } } } puts "testcases8: $n test cases" } #---------------------------------------------------------------------- # # testcases11 -- # # Outputs the 'clock-11.x' test cases. # # Parameters: # f2 -- Channel handle to the output file # # Results: # None. # # Side effects: # Test cases for precedence among YYYYMMDD and YYYYDDD are written # to f2. # #---------------------------------------------------------------------- proc testcases11 { f2 } { # Put out a header describing the tests puts $f2 "" puts $f2 "\# Test precedence among yyyymmdd and yyyyddd" puts $f2 "" array set v { Y 1970 m 01 d 01 j 002 } set n 0 foreach {a b c d} { Y m d j m Y d j d Y m j j Y m d Y m j d m Y j d d Y j m j Y d m Y d m j m d Y j d m Y j j m Y d Y d j m m d j Y d m j Y j m d Y Y j m d m j Y d d j Y m j d Y m Y j d m m j d Y d j m Y j d m Y } { foreach x [list $a $b $c $d] { switch -exact -- $x { m - d { set value 0 } j { set value 86400 } } } set format "%$a%$b%$c%$d" set string "$v($a)$v($b)$v($c)$v($d)" puts $f2 "test clock-11.[incr n] {precedence of ccyyddd and ccyymmdd} {" puts $f2 " [list clock scan $string -format $format -gmt 1]" puts $f2 "} $value" } puts "testcases11: $n test cases" } #---------------------------------------------------------------------- # # testcases12 -- # # Outputs the 'clock-12.x' test cases, parsing CCyyWwwd # # Parameters: # f2 -- Channel handle to the output file # # Results: # None. # # Side effects: # Test cases for parsing dates in Gregorian calendar are written to the # output file. # #---------------------------------------------------------------------- proc testcases12 { f2 } { # Put out a header describing the tests puts $f2 "" puts $f2 "\# Test parsing of ccyyWwwd" puts $f2 "" set n 0 foreach year {1970 1971 2000 2001} { foreach month {01 12} { foreach day {02 31} { set scanned [clock scan $year$month$day -gmt true] foreach d {%a %A %u %w %Ou %Ow} { set string [clock format $scanned \ -format "%G W%V $d" \ -locale en_US_roman \ -gmt true] puts $f2 "test clock-12.[incr n] {parse ccyyWwwd} {" puts $f2 " [list clock scan $string -format [list %G W%V $d] -locale en_US_roman -gmt 1]" puts $f2 "} $scanned" } } } } puts "testcases12: $n test cases" } #---------------------------------------------------------------------- # # testcases14 -- # # Outputs the 'clock-14.x' test cases. # # Parameters: # f2 -- Channel handle to the output file # # Results: # None. # # Side effects: # Test cases for parsing yymmdd dates are output. # #---------------------------------------------------------------------- proc testcases14 { f2 } { # Put out a header describing the tests puts $f2 "" puts $f2 "\# Test parsing of yymmdd" puts $f2 "" set n 0 foreach year {1938 1970 2000 2037} { foreach month {01 12} { foreach day {02 31} { set scanned [clock scan $year$month$day -gmt true] foreach yy {%y %Oy} { foreach mm {%b %B %h %m %Om %N} { foreach dd {%d %Od %e %Oe} { set string [clock format $scanned \ -format "$yy $mm $dd" \ -locale en_US_roman \ -gmt true] puts $f2 "test clock-14.[incr n] {parse yymmdd} {" puts $f2 " [list clock scan $string -format [list $yy $mm $dd] -locale en_US_roman -gmt 1]" puts $f2 "} $scanned" } } } } } } puts "testcases14: $n test cases" } #---------------------------------------------------------------------- # # testcases17 -- # # Outputs the 'clock-17.x' test cases, parsing yyWwwd # # Parameters: # f2 -- Channel handle to the output file # # Results: # None. # # Side effects: # Test cases for parsing dates in Gregorian calendar are written to the # output file. # #---------------------------------------------------------------------- proc testcases17 { f2 } { # Put out a header describing the tests puts $f2 "" puts $f2 "\# Test parsing of yyWwwd" puts $f2 "" set n 0 foreach year {1970 1971 2000 2001} { foreach month {01 12} { foreach day {02 31} { set scanned [clock scan $year$month$day -gmt true] foreach d {%a %A %u %w %Ou %Ow} { set string [clock format $scanned \ -format "%g W%V $d" \ -locale en_US_roman \ -gmt true] puts $f2 "test clock-17.[incr n] {parse yyWwwd} {" puts $f2 " [list clock scan $string -format [list %g W%V $d] -locale en_US_roman -gmt 1]" puts $f2 "} $scanned" } } } } puts "testcases17: $n test cases" } #---------------------------------------------------------------------- # # testcases19 -- # # Outputs the 'clock-19.x' test cases. # # Parameters: # f2 -- Channel handle to the output file # # Results: # None. # # Side effects: # Test cases for parsing mmdd dates are output. # #---------------------------------------------------------------------- proc testcases19 { f2 } { # Put out a header describing the tests puts $f2 "" puts $f2 "\# Test parsing of mmdd" puts $f2 "" set n 0 foreach year {1938 1970 2000 2037} { set base [clock scan ${year}0101 -gmt true] foreach month {01 12} { foreach day {02 31} { set scanned [clock scan $year$month$day -gmt true] foreach mm {%b %B %h %m %Om %N} { foreach dd {%d %Od %e %Oe} { set string [clock format $scanned \ -format "$mm $dd" \ -locale en_US_roman \ -gmt true] puts $f2 "test clock-19.[incr n] {parse mmdd} {" puts $f2 " [list clock scan $string -format [list $mm $dd] -locale en_US_roman -base $base -gmt 1]" puts $f2 "} $scanned" } } } } } puts "testcases19: $n test cases" } #---------------------------------------------------------------------- # # testcases21 -- # # Outputs the 'clock-21.x' test cases, parsing Wwwd # # Parameters: # f2 -- Channel handle to the output file # # Results: # None. # # Side effects: # Test cases for parsing dates in Gregorian calendar are written to the # output file. # #---------------------------------------------------------------------- proc testcases22 { f2 } { # Put out a header describing the tests puts $f2 "" puts $f2 "\# Test parsing of Wwwd" puts $f2 "" set n 0 foreach year {1970 1971 2000 2001} { set base [clock scan ${year}0104 -gmt true] foreach month {03 10} { foreach day {01 31} { set scanned [clock scan $year$month$day -gmt true] foreach d {%a %A %u %w %Ou %Ow} { set string [clock format $scanned \ -format "W%V $d" \ -locale en_US_roman \ -gmt true] puts $f2 "test clock-22.[incr n] {parse Wwwd} {" puts $f2 " [list clock scan $string -format [list W%V $d] -locale en_US_roman -gmt 1] -base $base" puts $f2 "} $scanned" } } } } puts "testcases22: $n test cases" } #---------------------------------------------------------------------- # # testcases24 -- # # Outputs the 'clock-24.x' test cases. # # Parameters: # f2 -- Channel handle to the output file # # Results: # None. # # Side effects: # Test cases for parsing naked day of the month are output. # #---------------------------------------------------------------------- proc testcases24 { f2 } { # Put out a header describing the tests puts $f2 "" puts $f2 "\# Test parsing of naked day-of-month" puts $f2 "" set n 0 foreach year {1970 2000} { foreach month {01 12} { set base [clock scan ${year}${month}01 -gmt true] foreach day {02 28} { set scanned [clock scan $year$month$day -gmt true] foreach dd {%d %Od %e %Oe} { set string [clock format $scanned \ -format "$dd" \ -locale en_US_roman \ -gmt true] puts $f2 "test clock-24.[incr n] {parse naked day of month} {" puts $f2 " [list clock scan $string -format $dd -locale en_US_roman -base $base -gmt 1]" puts $f2 "} $scanned" } } } } puts "testcases24: $n test cases" } #---------------------------------------------------------------------- # # testcases26 -- # # Outputs the 'clock-26.x' test cases, parsing naked day of week # # Parameters: # f2 -- Channel handle to the output file # # Results: # None. # # Side effects: # Test cases for parsing dates in Gregorian calendar are written to the # output file. # #---------------------------------------------------------------------- proc testcases26 { f2 } { # Put out a header describing the tests puts $f2 "" puts $f2 "\# Test parsing of naked day of week" puts $f2 "" set n 0 foreach year {1970 2001} { foreach week {01 52} { set base [clock scan ${year}W${week}4 \ -format %GW%V%u -gmt true] foreach day {1 7} { set scanned [clock scan ${year}W${week}${day} \ -format %GW%V%u -gmt true] foreach d {%a %A %u %w %Ou %Ow} { set string [clock format $scanned \ -format "$d" \ -locale en_US_roman \ -gmt true] puts $f2 "test clock-26.[incr n] {parse naked day of week} {" puts $f2 " [list clock scan $string -format $d -locale en_US_roman -gmt 1] -base $base" puts $f2 "} $scanned" } } } } puts "testcases26: $n test cases" } #---------------------------------------------------------------------- # # testcases29 -- # # Makes test cases for parsing of time of day. # # Parameters: # f2 -- Channel where tests are to be written # # Results: # None. # # Side effects: # Writes the tests. # #---------------------------------------------------------------------- proc testcases29 { f2 } { # Put out a header describing the tests puts $f2 "" puts $f2 "\# Test parsing of time of day" puts $f2 "" set n 0 foreach hour {0 1 11 12 13 23} \ hampm {12 1 11 12 1 11} \ lhour {? i xi xii xiii xxiii} \ lhampm {xii i xi xii i xi} \ ampmind {am am am pm pm pm} { set sphr [format %2d $hour] set 2dhr [format %02d $hour] set sphampm [format %2d $hampm] set 2dhampm [format %02d $hampm] set AMPMind [string toupper $ampmind] foreach minute {00 01 59} lminute {? i lix} { foreach second {00 01 59} lsecond {? i lix} { set time [expr { ( 60 * $hour + $minute ) * 60 + $second }] foreach {hfmt afmt} [list \ %H {} %k {} %OH {} %Ok {} \ %I %p %l %p \ %OI %p %Ol %p \ %I %P %l %P \ %OI %P %Ol %P] \ {hfld afld} [list \ $2dhr {} $sphr {} $lhour {} $lhour {} \ $2dhampm $AMPMind $sphampm $AMPMind \ $lhampm $AMPMind $lhampm $AMPMind \ $2dhampm $ampmind $sphampm $ampmind \ $lhampm $ampmind $lhampm $ampmind] \ { if { $second eq "00" } { if { $minute eq "00" } { puts $f2 "test clock-29.[incr n] {time parsing} {" puts $f2 " clock scan {2440588 $hfld $afld} \\" puts $f2 " -gmt true -locale en_US_roman \\" puts $f2 " -format {%J $hfmt $afmt}" puts $f2 "} $time" } puts $f2 "test clock-29.[incr n] {time parsing} {" puts $f2 " clock scan {2440588 $hfld:$minute $afld} \\" puts $f2 " -gmt true -locale en_US_roman \\" puts $f2 " -format {%J $hfmt:%M $afmt}" puts $f2 "} $time" puts $f2 "test clock-29.[incr n] {time parsing} {" puts $f2 " clock scan {2440588 $hfld:$lminute $afld} \\" puts $f2 " -gmt true -locale en_US_roman \\" puts $f2 " -format {%J $hfmt:%OM $afmt}" puts $f2 "} $time" } puts $f2 "test clock-29.[incr n] {time parsing} {" puts $f2 " clock scan {2440588 $hfld:$minute:$second $afld} \\" puts $f2 " -gmt true -locale en_US_roman \\" puts $f2 " -format {%J $hfmt:%M:%S $afmt}" puts $f2 "} $time" puts $f2 "test clock-29.[incr n] {time parsing} {" puts $f2 " clock scan {2440588 $hfld:$lminute:$lsecond $afld} \\" puts $f2 " -gmt true -locale en_US_roman \\" puts $f2 " -format {%J $hfmt:%OM:%OS $afmt}" puts $f2 "} $time" } } } } puts "testcases29: $n test cases" } processFile $d tcl8.6.5/tools/fix_tommath_h.tcl0000755000175000017500000000441712663653210016264 0ustar sergeisergei# fixtommath.tcl -- # # Changes to 'tommath.h' to make it conform with Tcl's linking # conventions. # # Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. #---------------------------------------------------------------------- set f [open [lindex $argv 0] r] set data [read $f] close $f set eat_endif 0 set eat_semi 0 set def_count 0 foreach line [split $data \n] { if {!$eat_semi && !$eat_endif} { switch -regexp -- $line { {#define BN_H_} { puts $line puts {} puts "\#include \"tclInt.h\"" puts "\#include \"tclTomMathDecls.h\"" puts "\#ifndef MODULE_SCOPE" puts "\#define MODULE_SCOPE extern" puts "\#endif" } {typedef\s+unsigned long\s+mp_digit;} { # change the second 'typedef unsigned long mp incr def_count puts "\#ifndef MP_DIGIT_DECLARED" if {$def_count == 2} { puts [string map {long int} $line] } else { puts $line } puts "\#define MP_DIGIT_DECLARED" puts "\#endif" } {typedef.*mp_digit;} { puts "\#ifndef MP_DIGIT_DECLARED" puts $line puts "\#define MP_DIGIT_DECLARED" puts "\#endif" } {typedef struct} { puts "\#ifndef MP_INT_DECLARED" puts "\#define MP_INT_DECLARED" puts "typedef struct mp_int mp_int;" puts "\#endif" puts "struct mp_int \{" } \}\ mp_int\; { puts "\};" } {^(char|int|void)} { puts "/*" puts $line set eat_semi 1 set after_semi "*/" } {^extern (int|const)} { puts "\#if defined(BUILD_tcl) || !defined(_WIN32)" puts [regsub {^extern} $line "MODULE_SCOPE"] set eat_semi 1 set after_semi "\#endif" } {define heap macros} { puts $line puts "\#if 0 /* these are macros in tclTomMathDecls.h */" set eat_endif 1 } {__x86_64__} { puts "[string map {__x86_64__ NEVER} $line]\ /* 128-bit ints fail in too many places */" } {#include} { # remove all includes } default { puts $line } } } else { puts $line } if {$eat_semi} { if {[regexp {; *$} $line]} { puts $after_semi set eat_semi 0 } } if {$eat_endif} { if {[regexp {^\#endif} $line]} { puts "\#endif" set eat_endif 0 } } } tcl8.6.5/tools/checkLibraryDoc.tcl0000755000175000017500000001625212663653210016466 0ustar sergeisergei# checkLibraryDoc.tcl -- # # This script attempts to determine what APIs exist in the source base that # have not been documented. By grepping through all of the doc/*.3 man # pages, looking for "Pkg_*" (e.g., Tcl_ or Tk_), and comparing this list # against the list of Pkg_ APIs found in the source (e.g., tcl8.2/*/*.[ch]) # we create six lists: # 1) APIs in Source not in Docs. # 2) APIs in Docs not in Source. # 3) Internal APIs and structs. # 4) Misc APIs and structs that we are not documenting. # 5) Command APIs (e.g., Tcl_ArrayObjCmd.) # 6) Proc pointers (e.g., Tcl_CloseProc.) # # Note: Each list is "a best guess" approximation. If developers write # non-standard code, this script will produce erroneous results. Each # list should be carefully checked for accuracy. # # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. lappend auto_path "c:/program\ files/tclpro1.2/win32-ix86/bin" #lappend auto_path "/home/surles/cvs/tclx8.0/tcl/unix" if {[catch {package require Tclx}]} { puts "error: could not load TclX. Please set TCL_LIBRARY." exit 1 } # A list of structs that are known to be undocumented. set StructList { Tcl_AsyncHandler \ Tcl_CallFrame \ Tcl_Condition \ Tcl_Encoding \ Tcl_EncodingState \ Tcl_EncodingType \ Tcl_HashEntry \ Tcl_HashSearch \ Tcl_HashTable \ Tcl_Mutex \ Tcl_Pid \ Tcl_QueuePosition \ Tcl_ResolvedVarInfo \ Tcl_SavedResult \ Tcl_ThreadDataKey \ Tcl_ThreadId \ Tcl_Time \ Tcl_TimerToken \ Tcl_Token \ Tcl_Trace \ Tcl_Value \ Tcl_ValueType \ Tcl_Var \ Tk_3DBorder \ Tk_ArgvInfo \ Tk_BindingTable \ Tk_Canvas \ Tk_CanvasTextInfo \ Tk_ConfigSpec \ Tk_ConfigTypes \ Tk_Cursor \ Tk_CustomOption \ Tk_ErrorHandler \ Tk_FakeWin \ Tk_Font \ Tk_FontMetrics \ Tk_GeomMgr \ Tk_Image \ Tk_ImageMaster \ Tk_ImageType \ Tk_Item \ Tk_ItemType \ Tk_OptionSpec\ Tk_OptionTable \ Tk_OptionType \ Tk_PhotoHandle \ Tk_PhotoImageBlock \ Tk_PhotoImageFormat \ Tk_PostscriptInfo \ Tk_SavedOption \ Tk_SavedOptions \ Tk_SegType \ Tk_TextLayout \ Tk_Window \ } # Misc junk that appears in the comments of the source. This just # allows us to filter comments that "fool" the script. set CommentList { Tcl_Create\[Obj\]Command \ Tcl_DecrRefCount\\n \ Tcl_NewObj\\n \ Tk_GetXXX \ } # Main entry point to this script. proc main {} { global argv0 global argv set len [llength $argv] if {($len != 2) && ($len != 3)} { puts "usage: $argv0 pkgName pkgDir \[outFile\]" puts " pkgName == Tcl,Tk" puts " pkgDir == /home/surles/cvs/tcl8.2" exit 1 } set pkg [lindex $argv 0] set dir [lindex $argv 1] if {[llength $argv] == 3} { set file [open [lindex $argv 2] w] } else { set file stdout } foreach {c d} [compare [grepCode $dir $pkg] [grepDocs $dir $pkg]] {} filter $c $d $dir $pkg $file if {$file ne "stdout"} { close $file } return } # Intersect the two list and write out the sets of APIs in one # list that is not in the other. proc compare {list1 list2} { set inter [intersect3 $list1 $list2] return [list [lindex $inter 0] [lindex $inter 2]] } # Filter the lists into the six lists we report on. Then write # the results to the file. proc filter {code docs dir pkg {outFile stdout}} { set apis {} # A list of Tcl command APIs. These are not documented. # This list should just be verified for accuracy. set cmds {} # A list of proc pointer structs. These are not documented. # This list should just be verified for accuracy. set procs {} # A list of internal declarations. These are not documented. # This list should just be verified for accuracy. set decls [grepDecl $dir $pkg] # A list of misc. procedure declarations that are not documented. # This list should just be verified for accuracy. set misc [grepMisc $dir $pkg] set pat1 ".*(${pkg}_\[A-z0-9]+).*$" # A list of APIs in the source, not in the docs. # This list should just be verified for accuracy. foreach x $code { if {[string match *Cmd $x]} { if {[string match ${pkg}* $x]} { lappend cmds $x } } elseif {[string match *Proc $x]} { if {[string match ${pkg}* $x]} { lappend procs $x } } elseif {[lsearch -exact $decls $x] >= 0} { # No Op. } elseif {[lsearch -exact $misc $x] >= 0} { # No Op. } else { lappend apis $x } } dump $apis "APIs in Source not in Docs." $outFile dump $docs "APIs in Docs not in Source." $outFile dump $decls "Internal APIs and structs." $outFile dump $misc "Misc APIs and structs that we are not documenting." $outFile dump $cmds "Command APIs." $outFile dump $procs "Proc pointers." $outFile return } # Print the list of APIs if the list is not null. proc dump {list title file} { if {$list ne ""} { puts $file "" puts $file $title puts $file "---------------------------------------------------------" foreach x $list { puts $file $x } } } # Grep into "dir/*/*.[ch]" looking for APIs that match $pkg_*. # (e.g., Tcl_Exit). Return a list of APIs. proc grepCode {dir pkg} { set apis [myGrep "${pkg}_\.\*" "${dir}/\*/\*\.\[ch\]"] set pat1 ".*(${pkg}_\[A-z0-9]+).*$" foreach a $apis { if {[regexp -- $pat1 $a main n1]} { set result([string trim $n1]) 1 } } return [lsort [array names result]] } # Grep into "dir/doc/*.3" looking for APIs that match $pkg_*. # (e.g., Tcl_Exit). Return a list of APIs. proc grepDocs {dir pkg} { set apis [myGrep "\\fB${pkg}_\.\*\\fR" "${dir}/doc/\*\.3"] set pat1 ".*(${pkg}_\[A-z0-9]+)\\\\fR.*$" foreach a $apis { if {[regexp -- $pat1 $a main n1]} { set result([string trim $n1]) 1 } } return [lsort [array names result]] } # Grep into "generic/pkgIntDecls.h" looking for APIs that match $pkg_*. # (e.g., Tcl_Export). Return a list of APIs. proc grepDecl {dir pkg} { set file [file join $dir generic "[string tolower $pkg]IntDecls.h"] set apis [myGrep "^EXTERN.*\[ \t\]${pkg}_.*" $file] set pat1 ".*(${pkg}_\[A-z0-9]+).*$" foreach a $apis { if {[regexp -- $pat1 $a main n1]} { set result([string trim $n1]) 1 } } return [lsort [array names result]] } # Grep into "*/*.[ch]" looking for APIs that match $pkg_Db*. # (e.g., Tcl_DbCkalloc). Return a list of APIs. proc grepMisc {dir pkg} { global CommentList global StructList set apis [myGrep "^EXTERN.*\[ \t\]${pkg}_Db.*" "${dir}/\*/\*\.\[ch\]"] set pat1 ".*(${pkg}_\[A-z0-9]+).*$" foreach a $apis { if {[regexp -- $pat1 $a main n1]} { set dbg([string trim $n1]) 1 } } set result {} eval {lappend result} $StructList eval {lappend result} [lsort [array names dbg]] eval {lappend result} $CommentList return $result } proc myGrep {searchPat globPat} { set result {} foreach file [glob -nocomplain $globPat] { set file [open $file r] set data [read $file] close $file foreach line [split $data "\n"] { if {[regexp "^.*${searchPat}.*\$" $line]} { lappend result $line } } } return $result } main tcl8.6.5/tools/white.bmp0000644000175000017500000005005211555560474014553 0ustar sergeisergeiBM*P>(ÕUìOttÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøtcl8.6.5/tools/man2tcl.c0000644000175000017500000002102312663653210014423 0ustar sergeisergei/* * man2tcl.c -- * * This file contains a program that turns a man page of the form used * for Tcl and Tk into a Tcl script that invokes a Tcl command for each * construct in the man page. The script can then be eval'ed to translate * the manual entry into some other format such as MIF or HTML. * * Usage: * * man2tcl ?fileName? * * Copyright (c) 1995 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ static char sccsid[] = "@(#) man2tcl.c 1.3 95/08/12 17:34:08"; #include #include #include #include #include /* * Imported things that aren't defined in header files: */ /* * Some define errno to be something complex and thread-aware; in * that case we definitely do not want to declare errno ourselves! */ #ifndef errno extern int errno; #endif /* * Current line number, used for error messages. */ static int lineNumber; /* * The variable below is set to 1 if an error occurs anywhere while reading in * the file. */ static int status; /* * The variable below is set to 1 if output should be generated. If it's 0, it * means we're doing a pre-pass to make sure that the file can be properly * parsed. */ static int writeOutput; #define PRINT(args) if (writeOutput) { printf args; } #define PRINTC(chr) if (writeOutput) { putc((chr), stdout); } /* * Prototypes for functions defined in this file: */ static void DoMacro(char *line); static void DoText(char *line); static void QuoteText(char *string, int count); /* *---------------------------------------------------------------------- * * main -- * * This function is the main program, which does all of the work of the * program. * * Results: * None: exits with a 0 return status to indicate success, or 1 to * indicate that there were problems in the translation. * * Side effects: * A Tcl script is output to standard output. Error messages may be * output on standard error. * *---------------------------------------------------------------------- */ int main( int argc, /* Number of command-line arguments. */ char **argv) /* Values of command-line arguments. */ { FILE *f; #define MAX_LINE_SIZE 4000 char line[MAX_LINE_SIZE]; char *p; /* * Find the file to read, and open it if it isn't stdin. */ if (argc == 1) { f = stdin; } else if (argc == 2) { f = fopen(argv[1], "r"); if (f == NULL) { fprintf(stderr, "Couldn't read \"%s\": %s\n", argv[1], strerror(errno)); exit(1); } } else { fprintf(stderr, "Usage: %s ?fileName?\n", argv[0]); } /* * Make two passes over the file. In the first pass, just check to make * sure we can handle everything. If there are problems, generate output * and stop. If everything is OK, make a second pass to actually generate * output. */ for (writeOutput = 0; writeOutput < 2; writeOutput++) { lineNumber = 0; status = 0; while (fgets(line, MAX_LINE_SIZE, f) != NULL) { for (p = line; *p != 0; p++) { if (*p == '\n') { *p = 0; break; } } lineNumber++; if (((line[0] == '.') || (line[0] == '\'')) && (line[1] == '\\') && (line[2] == '\"')) { /* * This line is a comment. Ignore it. */ continue; } if (strlen(line) >= MAX_LINE_SIZE -1) { fprintf(stderr, "Too long line. Max is %d chars.\n", MAX_LINE_SIZE - 1); exit(1); } if ((line[0] == '.') || (line[0] == '\'')) { /* * This line is a macro invocation. */ DoMacro(line); } else { /* * This line is text, possibly with formatting characters * embedded in it. */ DoText(line); } } if (status != 0) { break; } fseek(f, 0, SEEK_SET); } exit(status); } /* *---------------------------------------------------------------------- * * DoMacro -- * * This function is called to handle a macro invocation. It parses the * arguments to the macro and generates a Tcl command to handle the * invocation. * * Results: * None. * * Side effects: * A Tcl command is written to stdout. * *---------------------------------------------------------------------- */ static void DoMacro( char *line) /* The line of text that contains the macro * invocation. */ { char *p, *end; int quote; /* * If there is no macro name, then just skip the whole line. */ if ((line[1] == 0) || (isspace(line[1]))) { return; } PRINT(("macro")); if (*line != '.') { PRINT(("2")); } /* * Parse the arguments to the macro (including the name), in order. */ p = line+1; while (1) { PRINTC(' '); if (*p == '"') { /* * The argument is delimited by quotes. */ for (end = p+1; *end != '"'; end++) { if (*end == 0) { fprintf(stderr, "Unclosed quote in macro call on line %d.\n", lineNumber); status = 1; break; } } QuoteText(p+1, (end-(p+1))); } else { quote = 0; for (end = p+1; (*end != 0) && (quote || !isspace(*end)); end++) { if (*end == '\'') { quote = !quote; } } QuoteText(p, end-p); } if (*end == 0) { break; } p = end+1; while (isspace(*p)) { /* * Skip empty space before next argument. */ p++; } if (*p == 0) { break; } } PRINTC('\n'); } /* *---------------------------------------------------------------------- * * DoText -- * * This function is called to handle a line of troff text. It parses the * text, generating Tcl commands for text and for formatting stuff such * as font changes. * * Results: * None. * * Side effects: * Tcl commands are written to stdout. * *---------------------------------------------------------------------- */ static void DoText( char *line) /* The line of text. */ { char *p, *end; /* * Divide the line up into pieces consisting of backslash sequences, tabs, * and other text. */ p = line; while (*p != 0) { if (*p == '\t') { PRINT(("tab\n")); p++; } else if (*p != '\\') { /* * Ordinary text. */ for (end = p+1; (*end != '\\') && (*end != 0); end++) { /* Empty loop body. */ } PRINT(("text ")); QuoteText(p, end-p); PRINTC('\n'); p = end; } else { /* * A backslash sequence. There are particular ones that we * understand; output an error message for anything else and just * ignore the backslash. */ p++; if (*p == 'f') { /* * Font change. */ PRINT(("font %c\n", p[1])); p += 2; } else if (*p == '-') { PRINT(("dash\n")); p++; } else if (*p == 'e') { PRINT(("text \\\\\n")); p++; } else if (*p == '.') { PRINT(("text .\n")); p++; } else if (*p == '&') { p++; } else if (*p == '0') { PRINT(("text { }\n")); p++; } else if (*p == '(') { if ((p[1] == 0) || (p[2] == 0)) { fprintf(stderr, "Bad \\( sequence on line %d.\n", lineNumber); status = 1; } else { PRINT(("char {\\(%c%c}\n", p[1], p[2])); p += 3; } } else if (*p == 'N' && *(p+1) == '\'') { int ch; p += 2; sscanf(p,"%d",&ch); PRINT(("text \\u%04x\n", ch)); while(*p&&*p!='\'') p++; p++; } else if (*p != 0) { PRINT(("char {\\%c}\n", *p)); p++; } } } PRINT(("newline\n")); } /* *---------------------------------------------------------------------- * * QuoteText -- * * Copy the "string" argument to stdout, adding quote characters around * any special Tcl characters so that they'll just be treated as ordinary * text. * * Results: * None. * * Side effects: * Text is written to stdout. * *---------------------------------------------------------------------- */ static void QuoteText( char *string, /* The line of text. */ int count) /* Number of characters to write from * string. */ { if (count == 0) { PRINT(("{}")); return; } for ( ; count > 0; string++, count--) { switch (*string) { case '\\': if (*(string+1) == 'N' && *(string+2) == '\'') { int ch; string += 3; count -= 3; sscanf(string,"%d",&ch); PRINT(("\\u%04x", ch)); while(count>0&&*string!='\'') {string++;count--;} continue; } else if (*(string+1) == '0') { PRINT(("\\ ")); string++; count--; continue; } case '$': case '[': case '{': case ' ': case ';': case '"': case '\t': PRINTC('\\'); default: PRINTC(*string); } } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/tools/mkdepend.tcl0000644000175000017500000002243312663660066015227 0ustar sergeisergei#============================================================================== # # mkdepend : generate dependency information from C/C++ files # # Copyright (c) 1998, Nat Pryce # # Permission is hereby granted, without written agreement and without # license or royalty fees, to use, copy, modify, and distribute this # software and its documentation for any purpose, provided that the # above copyright notice and the following two paragraphs appear in # all copies of this software. # # IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, # SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF # THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR HAS BEEN ADVISED # OF THE POSSIBILITY OF SUCH DAMAGE. # # THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A # PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" # BASIS, AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, # UPDATES, ENHANCEMENTS, OR MODIFICATIONS. #============================================================================== # # Modified heavily by David Gravereaux about 9/17/2006. # Original can be found @ # http://web.archive.org/web/20070616205924/http://www.doc.ic.ac.uk/~np2/software/mkdepend.html #============================================================================== array set mode_data {} set mode_data(vc32) {cl -nologo -E} set source_extensions [list .c .cpp .cxx .cc] set excludes [list] if [info exists env(INCLUDE)] { set rawExcludes [split [string trim $env(INCLUDE) ";"] ";"] foreach exclude $rawExcludes { lappend excludes [file normalize $exclude] } } # openOutput -- # # Opens the output file. # # Arguments: # file The file to open # # Results: # None. proc openOutput {file} { global output set output [open $file w] puts $output "# Automatically generated at [clock format [clock seconds] -format "%Y-%m-%dT%H:%M:%S"] by [info script]\n" } # closeOutput -- # # Closes output file. # # Arguments: # none # # Results: # None. proc closeOutput {} { global output if {[string match stdout $output] != 0} { close $output } } # readDepends -- # # Read off CCP pipe for #line references. # # Arguments: # chan The pipe channel we are reading in. # # Results: # Raw dependency list pairs. proc readDepends {chan} { set line "" array set depends {} while {[gets $chan line] != -1} { if {[regexp {^#line [0-9]+ \"(.*)\"$} $line dummy fname] != 0} { set fname [file normalize $fname] if {![info exists target]} { # this is ourself set target $fname puts stderr "processing [file tail $fname]" } else { # don't include ourselves as a dependency of ourself. if {![string compare $fname $target]} {continue} # store in an array so multiple occurances are not counted. set depends($target|$fname) "" } } } set result {} foreach n [array names depends] { set pair [split $n "|"] lappend result [list [lindex $pair 0] [lindex $pair 1]] } return $result } # writeDepends -- # # Write the processed list out to the file. # # Arguments: # out The channel to write to. # depends The list of dependency pairs # # Results: # None. proc writeDepends {out depends} { foreach pair $depends { puts $out "[lindex $pair 0] : \\\n\t[join [lindex $pair 1] " \\\n\t"]" } } # stringStartsWith -- # # Compares second string to the beginning of the first. # # Arguments: # str The string to test the beginning of. # prefix The string to test against # # Results: # the result of the comparison. proc stringStartsWith {str prefix} { set front [string range $str 0 [expr {[string length $prefix] - 1}]] return [expr {[string compare [string tolower $prefix] \ [string tolower $front]] == 0}] } # filterExcludes -- # # Remove non-project header files. # # Arguments: # depends List of dependency pairs. # excludes List of directories that should be removed # # Results: # the processed dependency list. proc filterExcludes {depends excludes} { set filtered {} foreach pair $depends { set excluded 0 set file [lindex $pair 1] foreach dir $excludes { if [stringStartsWith $file $dir] { set excluded 1 break; } } if {!$excluded} { lappend filtered $pair } } return $filtered } # replacePrefix -- # # Take the normalized search path and put back the # macro name for it. # # Arguments: # file filename. # # Results: # filename properly replaced with macro for it. proc replacePrefix {file} { global srcPathList srcPathReplaceList foreach was $srcPathList is $srcPathReplaceList { regsub $was $file $is file } return $file } # rebaseFiles -- # # Replaces normalized paths with original macro names. # # Arguments: # depends Dependency pair list. # # Results: # The processed dependency pair list. proc rebaseFiles {depends} { set rebased {} foreach pair $depends { lappend rebased [list \ [replacePrefix [lindex $pair 0]] \ [replacePrefix [lindex $pair 1]]] } return $rebased } # compressDeps -- # # Compresses same named tragets into one pair with # multiple deps. # # Arguments: # depends Dependency pair list. # # Results: # The processed list. proc compressDeps {depends} { array set compressed [list] foreach pair $depends { lappend compressed([lindex $pair 0]) [lindex $pair 1] } set result [list] foreach n [array names compressed] { lappend result [list $n [lsort $compressed($n)]] } return $result } # addSearchPath -- # # Adds a new set of path and replacement string to the global list. # # Arguments: # newPathInfo comma seperated path and replacement string # # Results: # None. proc addSearchPath {newPathInfo} { global srcPathList srcPathReplaceList set infoList [split $newPathInfo ,] lappend srcPathList [file normalize [lindex $infoList 0]] lappend srcPathReplaceList [lindex $infoList 1] } # displayUsage -- # # Displays usage to stderr # # Arguments: # none. # # Results: # None. proc displayUsage {} { puts stderr "mkdepend.tcl \[options\] genericDir,macroName compatDir,macroName platformDir,macroName" } # readInputListFile -- # # Open and read the object file list. # # Arguments: # objectListFile - name of the file to open. # # Results: # None. proc readInputListFile {objectListFile} { global srcFileList srcPathList source_extensions set f [open $objectListFile r] set fl [read $f] close $f # fix native path seperator so it isn't treated as an escape. regsub -all {\\} $fl {/} fl # Treat the string as a list so filenames between double quotes are # treated as list elements. foreach fname $fl { # Compiled .res resource files should be ignored. if {[file extension $fname] ne ".obj"} {continue} # Just filename without path or extension because the path is # the build directory, not where the source files are located. set baseName [file rootname [file tail $fname]] set found 0 foreach path $srcPathList { foreach ext $source_extensions { set test [file join $path ${baseName}${ext}] if {[file exist $test]} { lappend srcFileList $test set found 1 break } } if {$found} break } } } # main -- # # The main procedure of this script. # # Arguments: # none. # # Results: # None. proc main {} { global argc argv mode mode_data srcFileList srcPathList excludes global remove_prefix target_prefix output env set srcPathList [list] set srcFileList [list] if {$argc == 1} {displayUsage} # Parse mkdepend input for {set i 0} {$i < [llength $argv]} {incr i} { switch -glob -- [set arg [lindex $argv $i]] { -vc32 { set mode vc32 } -bc32 { set mode bc32 } -wc32 { set mode wc32 } -lc32 { set mode lc32 } -mgw32 { set mode mgw32 } -passthru:* { set passthru [string range $arg 10 end] regsub -all {"} $passthru {\"} passthru regsub -all {\\} $passthru {/} passthru } -out:* { openOutput [string range $arg 5 end] } @* { set objfile [string range $arg 1 end] regsub -all {\\} $objfile {/} objfile readInputListFile $objfile } -? - -help - --help { displayUsage exit 1 } default { if {![info exist mode]} { puts stderr "mode not set" displayUsage } addSearchPath $arg } } } # Execute the CPP command and parse output foreach srcFile $srcFileList { if {[catch { set command "$mode_data($mode) $passthru \"$srcFile\"" set input [open |$command r] set depends [readDepends $input] set status [catch {close $input} result] if {$status == 1 && [lindex $::errorCode 0] eq "CHILDSTATUS"} { foreach { - pid code } $::errorCode break if {$code == 2} { # preprocessor died a cruel death. error $result } } } err]} { puts stderr "error ocurred: $err\n" continue } set depends [filterExcludes $depends $excludes] set depends [rebaseFiles $depends] set depends [compressDeps $depends] writeDepends $output $depends } closeOutput } # kick it up. main tcl8.6.5/tools/man2help2.tcl0000644000175000017500000005135012663660066015230 0ustar sergeisergei# man2help2.tcl -- # # This file defines procedures that are used during the second pass of # the man page conversion. It converts the man format input to rtf # form suitable for use by the Windows help compiler. # # Copyright (c) 1996 by Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # Global variables used by these scripts: # # state - state variable that controls action of text proc. # # topics - array indexed by (package,section,topic) with value # of topic ID. # # keywords - array indexed by keyword string with value of topic ID. # # curID - current topic ID, starts at 0 and is incremented for # each new topic file. # # curPkg - current package name (e.g. Tcl). # # curSect - current section title (e.g. "Tcl Built-In Commands"). # # initGlobals -- # # This procedure is invoked to set the initial values of all of the # global variables, before processing a man page. # # Arguments: # None. proc initGlobals {} { uplevel \#0 unset state global state chars set state(paragraphPending) 0 set state(breakPending) 0 set state(firstIndent) 0 set state(leftIndent) 0 set state(inTP) 0 set state(paragraph) 0 set state(textState) 0 set state(curFont) "" set state(startCode) "{\\b " set state(startEmphasis) "{\\i " set state(endCode) "}" set state(endEmphasis) "}" set state(noFill) 0 set state(charCnt) 0 set state(offset) [getTwips 0.5i] set state(leftMargin) [getTwips 0.5i] set state(nestingLevel) 0 set state(intl) 0 set state(sb) 0 setTabs 0.5i # set up international character table array set chars { o^ F4 } } # beginFont -- # # Arranges for future text to use a special font, rather than # the default paragraph font. # # Arguments: # font - Name of new font to use. proc beginFont {font} { global file state textSetup if {[string equal $state(curFont) $font]} { return } endFont puts -nonewline $file $state(start$font) set state(curFont) $font } # endFont -- # # Reverts to the default font for the paragraph type. # # Arguments: # None. proc endFont {} { global state file if {[string compare $state(curFont) ""]} { puts -nonewline $file $state(end$state(curFont)) set state(curFont) "" } } # textSetup -- # # This procedure is called the first time that text is output for a # paragraph. It outputs the header information for the paragraph. # # Arguments: # None. proc textSetup {} { global file state if $state(breakPending) { puts $file "\\line" } if $state(paragraphPending) { puts $file [format "\\par\n\\pard\\fi%.0f\\li%.0f" \ $state(firstIndent) $state(leftIndent)] foreach tab $state(tabs) { puts $file [format "\\tx%.0f" $tab] } set state(tabs) {} if {$state(sb)} { puts $file "\\sb$state(sb)" set state(sb) 0 } } set state(breakPending) 0 set state(paragraphPending) 0 } # text -- # # This procedure adds text to the current state(paragraph). If this is # the first text in the state(paragraph) then header information for the # state(paragraph) is output before the text. # # Arguments: # string - Text to output in the state(paragraph). proc text {string} { global file state chars textSetup set string [string map [list \ "\\" "\\\\" \ "\{" "\\\{" \ "\}" "\\\}" \ "\t" {\tab } \ '' "\\rdblquote " \ `` "\\ldblquote " \ "\u00b7" "\\bullet " \ ] $string] # Check if this is the beginning of an international character string. # If so, look up the sequence in the chars table and substitute the # appropriate hex value. if {$state(intl)} { if {[regexp {^'([^']*)'} $string dummy ch]} { if {[info exists chars($ch)]} { regsub {^'[^']*'} $string "\\\\'$chars($ch)" string } else { puts stderr "Unknown international character '$ch'" } } set state(intl) 0 } switch $state(textState) { REF { if {$state(inTP) == 0} { set string [insertRef $string] } } SEE { global topics curPkg curSect foreach i [split $string] { if {![regexp -nocase {^[a-z_0-9]+} [string trim $i] i ]} { continue } if {![catch {set ref $topics($curPkg,$curSect,$i)} ]} { regsub $i $string [link $i $ref] string } } } KEY { return } } puts -nonewline $file "$string" } # insertRef -- # # This procedure looks for a string in the cross reference table and # generates a hot-link to the appropriate topic. Tries to find the # nearest reference in the manual. # # Arguments: # string - Text to output in the state(paragraph). proc insertRef {string} { global NAME_file curPkg curSect topics curID set path {} set string [string trim $string] set ref {} if {[info exists topics($curPkg,$curSect,$string)]} { set ref $topics($curPkg,$curSect,$string) } else { set sites [array names topics "$curPkg,*,$string"] set count [llength $sites] if {$count > 0} { set ref $topics([lindex $sites 0]) } else { set sites [array names topics "*,*,$string"] set count [llength $sites] if {$count > 0} { set ref $topics([lindex $sites 0]) } } } if {($ref != "") && ($ref != $curID)} { set string [link $string $ref] } return $string } # macro -- # # This procedure is invoked to process macro invocations that start # with "." (instead of '). # # Arguments: # name - The name of the macro (without the "."). # args - Any additional arguments to the macro. proc macro {name args} { global state file switch $name { AP { if {[llength $args] != 3 && [llength $args] != 2} { puts stderr "Bad .AP macro: .$name [join $args " "]" } newPara 3.75i -3.75i setTabs {1.25i 2.5i 3.75i} font B text [lindex $args 0] tab font I text [lindex $args 1] tab font R if {[llength $args] == 3} { text "([lindex $args 2])" } tab } AS { # next page and previous page } br { lineBreak } BS {} BE {} CE { puts -nonewline $::file "\\f0\\fs20 " set state(noFill) 0 set state(breakPending) 0 newPara "" set state(leftIndent) [expr {$state(leftIndent) - $state(offset)}] set state(sb) 80 } CS { # code section set state(noFill) 1 newPara "" set state(leftIndent) [expr {$state(leftIndent) + $state(offset)}] set state(sb) 80 puts -nonewline $::file "\\f1\\fs18 " } DE { set state(noFill) 0 decrNestingLevel newPara 0i } DS { set state(noFill) 1 incrNestingLevel newPara 0i } fi { set state(noFill) 0 } IP { IPmacro $args } LP { newPara 0i set state(sb) 80 } ne { } nf { set state(noFill) 1 } OP { if {[llength $args] != 3} { puts stderr "Bad .OP macro: .$name [join $args " "]" } set state(nestingLevel) 0 newPara 0i set state(sb) 120 setTabs 4c text "Command-Line Name:" tab font B set x [lindex $args 0] regsub -all {\\-} $x - x text $x lineBreak font R text "Database Name:" tab font B text [lindex $args 1] lineBreak font R text "Database Class:" tab font B text [lindex $args 2] font R set state(inTP) 0 newPara 0.5i set state(sb) 80 } PP { newPara 0i set state(sb) 120 } RE { decrNestingLevel } RS { incrNestingLevel } SE { font R set state(noFill) 0 set state(nestingLevel) 0 newPara 0i text "See the " font B set temp $state(textState) set state(textState) REF text options set state(textState) $temp font R text " manual entry for detailed descriptions of the above options." } SH { SHmacro $args } SS { SHmacro $args subsection } SO { SHmacro "STANDARD OPTIONS" set state(nestingLevel) 0 newPara 0i setTabs {4c 8c 12c} font B set state(noFill) 1 } so { if {$args ne "man.macros"} { puts stderr "Unknown macro: .$name [join $args " "]" } } sp { ;# needs work if {$args eq ""} { set count 1 } else { set count [lindex $args 0] } while {$count > 0} { lineBreak incr count -1 } } ta { setTabs $args } TH { THmacro $args } TP { TPmacro $args } UL { ;# underline puts -nonewline $file "{\\ul " text [lindex $args 0] puts -nonewline $file "}" if {[llength $args] == 2} { text [lindex $args 1] } } VE {} VS {} QW { formattedText "``[lindex $args 0]''[lindex $args 1] " } MT { text "``'' " } PQ { formattedText \ "(``[lindex $args 0]''[lindex $args 1])[lindex $args 2] " } QR { formattedText "``[lindex $args 0]" dash formattedText "[lindex $args 1]''[lindex $args 2] " } default { puts stderr "Unknown macro: .$name [join $args " "]" } } } # link -- # # This procedure returns the string for a hot link to a different # context location. # # Arguments: # label - String to display in hot-spot. # id - Context string to jump to. proc link {label id} { return "{\\uldb $label}{\\v $id}" } # font -- # # This procedure is invoked to handle font changes in the text # being output. # # Arguments: # type - Type of font: R, I, B, or S. proc font {type} { global state switch $type { P - R { endFont if {$state(textState) eq "REF"} { set state(textState) INSERT } } C - B { beginFont Code if {$state(textState) eq "INSERT"} { set state(textState) REF } } I { beginFont Emphasis } S { } default { puts stderr "Unknown font: $type" } } } # formattedText -- # # Insert a text string that may also have \fB-style font changes # and a few other backslash sequences in it. # # Arguments: # text - Text to insert. proc formattedText {text} { global chars while {$text ne ""} { set index [string first \\ $text] if {$index < 0} { text $text return } text [string range $text 0 [expr {$index-1}]] set c [string index $text [expr {$index+1}]] switch -- $c { f { font [string index $text [expr {$index+2}]] set text [string range $text [expr {$index+3}] end] } e { text "\\" set text [string range $text [expr {$index+2}] end] } - { dash set text [string range $text [expr {$index+2}] end] } & - | { set text [string range $text [expr {$index+2}] end] } ( { char [string range $text $index [expr {$index+3}]] set text [string range $text [expr {$index+4}] end] } default { puts stderr "Unknown sequence: \\$c" set text [string range $text [expr {$index+2}] end] } } } } # dash -- # # This procedure is invoked to handle dash characters ("\-" in # troff). It outputs a special dash character. # # Arguments: # None. proc dash {} { global state if {[string equal $state(textState) "NAME"]} { set state(textState) 0 } text "-" } # tab -- # # This procedure is invoked to handle tabs in the troff input. # Right now it does nothing. # # Arguments: # None. proc tab {} { global file textSetup puts -nonewline $file "\\tab " } # setTabs -- # # This procedure handles the ".ta" macro, which sets tab stops. # # Arguments: # tabList - List of tab stops in *roff format proc setTabs {tabList} { global file state set state(tabs) {} foreach arg $tabList { if {[string match +* $arg]} { set relativeTo [lindex $state(tabs) end] set arg [string range $arg 1 end] } else { # Local left margin set relativeTo [expr {$state(leftMargin) \ + ($state(offset) * $state(nestingLevel))}] } if {[regexp {^\\w'([^']*)'u$} $arg -> submatch]} { # Magic factor! set distance [expr {[string length $submatch] * 86.4}] } else { set distance [getTwips $arg] } lappend state(tabs) [expr {round($distance + $relativeTo)}] } } # lineBreak -- # # Generates a line break in the HTML output. # # Arguments: # None. proc lineBreak {} { global state textSetup set state(breakPending) 1 } # newline -- # # This procedure is invoked to handle newlines in the troff input. # It outputs either a space character or a newline character, depending # on fill mode. # # Arguments: # None. proc newline {} { global state if {$state(inTP)} { set state(inTP) 0 lineBreak } elseif {$state(noFill)} { lineBreak } else { text " " } } # pageBreak -- # # This procedure is invoked to generate a page break. # # Arguments: # None. proc pageBreak {} { global file curVer if {[string equal $curVer ""]} { puts $file {\page} } else { puts $file {\par} puts $file {\pard\sb400\qc} puts $file "Last change: $curVer\\page" } } # char -- # # This procedure is called to handle a special character. # # Arguments: # name - Special character named in troff \x or \(xx construct. proc char {name} { global file state switch -exact $name { {\o} { set state(intl) 1 } {\ } { textSetup puts -nonewline $file " " } {\0} { textSetup puts -nonewline $file " \\emspace " } {\\} - {\e} { textSetup puts -nonewline $file "\\\\" } {\(+-} { textSetup puts -nonewline $file "\\'b1 " } {\%} - {\|} { } {\(->} { textSetup puts -nonewline $file "->" } {\(bu} { textSetup puts -nonewline $file "\\bullet " } {\(co} { textSetup puts -nonewline $file "\\'a9 " } {\(mi} { textSetup puts -nonewline $file "-" } {\(mu} { textSetup puts -nonewline $file "\\'d7 " } {\(em} - {\(en} { textSetup puts -nonewline $file "-" } {\(fm} { textSetup puts -nonewline $file "\\'27 " } default { puts stderr "Unknown character: $name" } } } # macro2 -- # # This procedure handles macros that are invoked with a leading "'" # character instead of space. Right now it just generates an # error diagnostic. # # Arguments: # name - The name of the macro (without the "."). # args - Any additional arguments to the macro. proc macro2 {name args} { puts stderr "Unknown macro: '$name [join $args " "]" } # SHmacro -- # # Subsection head; handles the .SH and .SS macros. # # Arguments: # name - Section name. proc SHmacro {argList {style section}} { global file state set args [join $argList " "] if {[llength $argList] < 1} { puts stderr "Bad .SH macro: .SH $args" } # control what the text proc does with text switch $args { NAME {set state(textState) NAME} DESCRIPTION {set state(textState) INSERT} INTRODUCTION {set state(textState) INSERT} "WIDGET-SPECIFIC OPTIONS" {set state(textState) INSERT} "SEE ALSO" {set state(textState) SEE} KEYWORDS {set state(textState) KEY; return} } if {$state(breakPending) != -1} { set state(breakPending) 1 } else { set state(breakPending) 0 } set state(noFill) 0 if {[string compare "subsection" $style] == 0} { nextPara .25i } else { nextPara 0i } font B text $args font R nextPara .5i } # IPmacro -- # # This procedure is invoked to handle ".IP" macros, which may take any # of the following forms: # # .IP [1] Translate to a "1Step" state(paragraph). # .IP [x] (x > 1) Translate to a "Step" state(paragraph). # .IP Translate to a "Bullet" state(paragraph). # .IP text count Translate to a FirstBody state(paragraph) with special # indent and tab stop based on "count", and tab after # "text". # # Arguments: # argList - List of arguments to the .IP macro. # # HTML limitations: 'count' in '.IP text count' is ignored. proc IPmacro {argList} { global file state set length [llength $argList] foreach {text indent} $argList break if {$length > 2} { puts stderr "Bad .IP macro: .IP [join $argList " "]" } if {$length == 0} { set text {\(bu} set indent 5 } elseif {$length == 1} { set indent 5 } if {$text == {\(bu}} { set text "\u00b7" } set tab [expr $indent * 0.1]i newPara $tab -$tab set state(sb) 80 setTabs $tab formattedText $text tab } # TPmacro -- # # This procedure is invoked to handle ".TP" macros, which may take any # of the following forms: # # .TP x Translate to an state(indent)ed state(paragraph) with the # specified state(indent) (in 100 twip units). # .TP Translate to an state(indent)ed state(paragraph) with # default state(indent). # # Arguments: # argList - List of arguments to the .IP macro. # # HTML limitations: 'x' in '.TP x' is ignored. proc TPmacro {argList} { global state set length [llength $argList] if {$length == 0} { set val 0.5i } else { set val [expr {([lindex $argList 0] * 100.0)/1440}]i } newPara $val -$val setTabs $val set state(inTP) 1 set state(sb) 120 } # THmacro -- # # This procedure handles the .TH macro. It generates the non-scrolling # header section for a given man page, and enters information into the # table of contents. The .TH macro has the following form: # # .TH name section date footer header # # Arguments: # argList - List of arguments to the .TH macro. proc THmacro {argList} { global file curPkg curSect curID id_keywords state curVer bitmap if {[llength $argList] != 5} { set args [join $argList " "] puts stderr "Bad .TH macro: .TH $args" } incr curID set name [lindex $argList 0] ;# Tcl_UpVar set page [lindex $argList 1] ;# 3 set curVer [lindex $argList 2] ;# 7.4 set curPkg [lindex $argList 3] ;# Tcl set curSect [lindex $argList 4] ;# {Tcl Library Procedures} regsub -all {\\ } $curSect { } curSect ;# Clean up for [incr\ Tcl] puts $file "#{\\footnote $curID}" ;# Context string puts $file "\${\\footnote $name}" ;# Topic title set browse "${curSect}${name}" regsub -all {[ _-]} $browse {} browse puts $file "+{\\footnote $browse}" ;# Browse sequence # Suppress duplicates foreach i $id_keywords($curID) { set keys($i) 1 } foreach i [array names keys] { set i [string trim $i] if {[string length $i] > 0} { puts $file "K{\\footnote $i}" ;# Keyword strings } } unset keys puts $file "\\pard\\tx3000\\sb100\\sa100\\fs24\\keepn" font B text $name tab text $curSect font R if {[info exists bitmap]} { # a right justified bitmap puts $file "\\\{bmrt $bitmap\\\}" } puts $file "\\fs20" set state(breakPending) -1 } # nextPara -- # # Set the indents for a new paragraph, and start a paragraph break # # Arguments: # leftIndent - The new left margin for body lines. # firstIndent - The offset from the left margin for the first line. proc nextPara {leftIndent {firstIndent 0i}} { global state set state(leftIndent) [getTwips $leftIndent] set state(firstIndent) [getTwips $firstIndent] set state(paragraphPending) 1 } # newPara -- # # This procedure sets the left and hanging state(indent)s for a line. # State(Indent)s are specified in units of inches or centimeters, and are # relative to the current nesting level and left margin. # # Arguments: # leftState(Indent) - The new left margin for lines after the first. # firstState(Indent) - The new left margin for the first line of a state(paragraph). proc newPara {leftIndent {firstIndent 0i}} { global state file if $state(paragraph) { puts -nonewline $file "\\line\n" } if {$leftIndent ne ""} { set state(leftIndent) [expr {$state(leftMargin) \ + ($state(offset) * $state(nestingLevel)) \ + [getTwips $leftIndent]}] } set state(firstIndent) [getTwips $firstIndent] set state(paragraphPending) 1 } # getTwips -- # # This procedure converts a distance in inches or centimeters into # twips (1/1440 of an inch). # # Arguments: # arg - A number followed by "i" or "c" proc getTwips {arg} { if {[scan $arg "%f%s" distance units] != 2} { puts stderr "bad distance \"$arg\"" return 0 } if {[string length $units] > 1} { puts stderr "additional characters after unit \"$arg\"" set units [string index $units 0] } switch -- $units { c { set distance [expr {$distance * 567}] } i { set distance [expr {$distance * 1440}] } default { puts stderr "bad units in distance \"$arg\"" return 0 } } return $distance } # incrNestingLevel -- # # This procedure does the work of the .RS macro, which increments # the number of state(indent)ations that affect things like .PP. # # Arguments: # None. proc incrNestingLevel {} { global state incr state(nestingLevel) set oldp $state(paragraph) set state(paragraph) 0 newPara 0i set state(paragraph) $oldp } # decrNestingLevel -- # # This procedure does the work of the .RE macro, which decrements # the number of indentations that affect things like .PP. # # Arguments: # None. proc decrNestingLevel {} { global state if {$state(nestingLevel) == 0} { puts stderr "Nesting level decremented below 0" } else { incr state(nestingLevel) -1 } } tcl8.6.5/tools/findBadExternals.tcl0000755000175000017500000000233512663660066016657 0ustar sergeisergei# findBadExternals.tcl -- # # This script scans the Tcl load library for exported symbols # that do not begin with 'Tcl' or 'tcl'. It reports them on the # standard output. It is used to make sure that the library does # not inadvertently export externals that may be in conflict with # other code. # # Usage: # # tclsh findBadExternals.tcl /path/to/tclXX.so-or-.dll # # Copyright (c) 2005 George Peter Staplin and Kevin Kenny # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. #---------------------------------------------------------------------- proc main {argc argv} { if {$argc != 1} { puts stderr "syntax is: [info script] libtcl" return 1 } switch -exact -- $::tcl_platform(platform) { unix - macosx { set status [catch { exec nm --extern-only --defined-only [lindex $argv 0] } result] } windows { set status [catch { exec dumpbin /exports [lindex $argv 0] } result] } } if {$status != 0 && $::errorCode ne "NONE"} { puts $result return 1 } foreach line [split $result \n] { if {! [string match {* [Tt]cl*} $line]} { puts $line } } return 0 } exit [main $::argc $::argv] tcl8.6.5/tools/tcltk-man2html-utils.tcl0000644000175000017500000012246712663660066017447 0ustar sergeisergei## ## Utility functions for Man->HTML converter. Note that these ## functions are specifically intended to work with the format as used ## by Tcl and Tk; they do not cope with arbitrary nroff markup. ## ## Copyright (c) 1995-1997 Roger E. Critchlow Jr ## Copyright (c) 2004-2011 Donal K. Fellows set ::manual(report-level) 1 proc manerror {msg} { global manual set name {} set subj {} set procname [lindex [info level -1] 0] if {[info exists manual(name)]} { set name $manual(name) } if {[info exists manual(section)] && [string length $manual(section)]} { puts stderr "$name: $manual(section): $procname: $msg" } else { puts stderr "$name: $procname: $msg" } } proc manreport {level msg} { global manual if {$level < $manual(report-level)} { uplevel 1 [list manerror $msg] } } proc fatal {msg} { global manual uplevel 1 [list manerror $msg] exit 1 } ## ## templating ## proc indexfile {} { if {[info exists ::TARGET] && $::TARGET eq "devsite"} { return "index.tml" } else { return "contents.htm" } } proc copyright {copyright {level {}}} { # We don't actually generate a separate copyright page anymore #set page "${level}copyright.htm" #return "Copyright © [htmlize-text [lrange $copyright 2 end]]" # obfuscate any email addresses that may appear in name set who [string map {@ (at)} [lrange $copyright 2 end]] return "Copyright © [htmlize-text $who]" } proc copyout {copyrights {level {}}} { set out "
" foreach c $copyrights { append out "[copyright $c $level]\n" } append out "
" return $out } proc CSS {{level ""}} { return "\n" } proc DOCTYPE {} { return "" } proc htmlhead {title header args} { set level "" if {[lindex $args end] eq "../[indexfile]"} { # XXX hack - assume same level for CSS file set level "../" } set out "[DOCTYPE]\n\n$title\n[CSS $level]\n" foreach {uptitle url} $args { set header "$uptitle > $header" } append out "

$header

" global manual if {[info exists manual(subheader)]} { set subs {} foreach {name subdir} $manual(subheader) { if {$name eq $title} { lappend subs $name } else { lappend subs "$name" } } append out "\n

[join $subs { | }]

" } return $out } ## ## parsing ## proc unquote arg { return [string map [list \" {}] $arg] } proc parse-directive {line codename restname} { upvar 1 $codename code $restname rest return [regexp {^(\.[.a-zA-Z0-9]*) *(.*)} $line all code rest] } proc htmlize-text {text {charmap {}}} { # contains some extras for use in nroff->html processing # build on the list passed in, if any lappend charmap \ "–" "–" \ {&} {&} \ {\\} "\" \ {\e} "\" \ {\ } { } \ {\|} { } \ {\0} { } \ \" {"} \ {<} {<} \ {>} {>} \ \u201c "“" \ \u201d "”" return [string map $charmap $text] } proc process-text {text} { global manual # preprocess text; note that this is an incomplete map, and will probably # need to have things added to it as the manuals expand to use them. set charmap [list \ {\&} "\t" \ {\%} {} \ "\\\n" "\n" \ {\(+-} "±" \ {\(co} "©" \ {\(em} "—" \ {\(en} "–" \ {\(fm} "′" \ {\(mu} "×" \ {\(mi} "−" \ {\(->} "" \ {\fP} {\fR} \ {\.} . \ {\(bu} "•" \ {\*(qo} "ô" \ ] lappend charmap {\-\|\-} -- ; # two hyphens lappend charmap {\-} - ; # a hyphen set text [htmlize-text $text $charmap] # General quoted entity regsub -all {\\N'(\d+)'} $text "\\&#\\1;" text while {[string first "\\" $text] >= 0} { # C R if {[regsub {^([^\\]*)\\fC([^\\]*)\\fR(.*)$} $text \ {\1\2\3} text]} continue # B R if {[regsub {^([^\\]*)\\fB([^\\]*)\\fR(.*)$} $text \ {\1\2\3} text]} continue # B I if {[regsub {^([^\\]*)\\fB([^\\]*)\\fI(.*)$} $text \ {\1\2\\fI\3} text]} continue # I R if {[regsub {^([^\\]*)\\fI([^\\]*)\\fR(.*)$} $text \ {\1\2\3} text]} continue # I B if {[regsub {^([^\\]*)\\fI([^\\]*)\\fB(.*)$} $text \ {\1\2\\fB\3} text]} continue # B B, I I, R R if { [regsub {^([^\\]*)\\fB([^\\]*)\\fB(.*)$} $text \ {\1\\fB\2\3} ntext] || [regsub {^([^\\]*)\\fI([^\\]*)\\fI(.*)$} $text \ {\1\\fI\2\3} ntext] || [regsub {^([^\\]*)\\fR([^\\]*)\\fR(.*)$} $text \ {\1\\fR\2\3} ntext] } { manerror "impotent font change: $text" set text $ntext continue } # unrecognized manerror "uncaught backslash: $text" set text [string map [list "\\" "\"] $text] } return $text } ## ## pass 2 text input and matching ## proc open-text {} { global manual set manual(text-length) [llength $manual(text)] set manual(text-pointer) 0 } proc more-text {} { global manual return [expr {$manual(text-pointer) < $manual(text-length)}] } proc next-text {} { global manual if {[more-text]} { set text [lindex $manual(text) $manual(text-pointer)] incr manual(text-pointer) return $text } manerror "read past end of text" error "fatal" } proc is-a-directive {line} { return [string match .* $line] } proc split-directive {line opname restname} { upvar 1 $opname op $restname rest set op [string range $line 0 2] set rest [string trim [string range $line 3 end]] } proc next-op-is {op restname} { global manual upvar 1 $restname rest if {[more-text]} { set text [lindex $manual(text) $manual(text-pointer)] if {[string equal -length 3 $text $op]} { set rest [string range $text 4 end] incr manual(text-pointer) return 1 } } return 0 } proc backup-text {n} { global manual if {$manual(text-pointer)-$n >= 0} { incr manual(text-pointer) -$n } } proc match-text args { global manual set nargs [llength $args] if {$manual(text-pointer) + $nargs > $manual(text-length)} { return 0 } set nback 0 foreach arg $args { if {![more-text]} { backup-text $nback return 0 } set arg [string trim $arg] set targ [string trim [lindex $manual(text) $manual(text-pointer)]] if {$arg eq $targ} { incr nback incr manual(text-pointer) continue } if {[regexp {^@(\w+)$} $arg all name]} { upvar 1 $name var set var $targ incr nback incr manual(text-pointer) continue } if {[regexp -nocase {^(\.[A-Z][A-Z])@(\w+)$} $arg all op name]\ && [string equal $op [lindex $targ 0]]} { upvar 1 $name var set var [lrange $targ 1 end] incr nback incr manual(text-pointer) continue } backup-text $nback return 0 } return 1 } proc expand-next-text {n} { global manual return [join [lrange $manual(text) $manual(text-pointer) \ [expr {$manual(text-pointer)+$n-1}]] \n\n] } ## ## pass 2 output ## proc man-puts {text} { global manual lappend manual(output-$manual(wing-file)-$manual(name)) $text } ## ## build hypertext links to tables of contents ## proc long-toc {text} { global manual set here M[incr manual(section-toc-n)] set manual($manual(name)-id-$text) $here set there L[incr manual(long-toc-n)] lappend manual(section-toc) \ "
$text" return "$text" } proc option-toc {name class switch} { global manual # Special case handling, oh we hate it but must do it if {[string match "*OPTIONS" $manual(section)]} { if {$manual(name) ne "ttk_widget" && ($manual(name) ne "ttk_entry" || ![string match validate* $name])} { # link the defined option into the long table of contents set link [long-toc "$switch, $name, $class"] regsub -- "$switch, $name, $class" $link "$switch" link return $link } } elseif {"$manual(name):$manual(section)" ne "options:DESCRIPTION"} { error "option-toc in $manual(name) section $manual(section)" } # link the defined standard option to the long table of contents and make # a target for the standard option references from other man pages. set first [lindex $switch 0] set here M$first set there L[incr manual(long-toc-n)] set manual(standard-option-$manual(name)-$first) \ "$switch, $name, $class" lappend manual(section-toc) \ "
$switch, $name, $class" return "$switch" } proc std-option-toc {name page} { global manual if {[info exists manual(standard-option-$page-$name)]} { lappend manual(section-toc)
$manual(standard-option-$page-$name) return $manual(standard-option-$page-$name) } manerror "missing reference to \"$name\" in $page.n" set here M[incr manual(section-toc-n)] set there L[incr manual(long-toc-n)] set other M$name lappend manual(section-toc) "
$name" return "$name" } ## ## process the widget option section ## in widget and options man pages ## proc output-widget-options {rest} { global manual man-puts
lappend manual(section-toc)
backup-text 1 set para {} while {[next-op-is .OP rest]} { switch -exact -- [llength $rest] { 3 { lassign $rest switch name class } 5 { set switch [lrange $rest 0 2] set name [lindex $rest 3] set class [lindex $rest 4] } default { fatal "bad .OP $rest" } } if {![regexp {^(<.>)([-\w ]+)()$} $switch \ all oswitch switch cswitch]} { if {![regexp {^(<.>)([-\w ]+) or ([-\w ]+)()$} $switch \ all oswitch switch1 switch2 cswitch]} { error "not Switch: $switch" } set switch "$switch1$cswitch or $oswitch$switch2" } if {![regexp {^(<.>)([\w]*)()$} $name all oname name cname]} { error "not Name: $name" } if {![regexp {^(<.>)([\w]*)()$} $class all oclass class cclass]} { error "not Class: $class" } man-puts "$para
Command-Line Name: $oswitch[option-toc $name $class $switch]$cswitch" man-puts "
Database Name: $oname$name$cname" man-puts "
Database Class: $oclass$class$cclass" man-puts
[next-text] set para

if {[next-op-is .RS rest]} { while {[more-text]} { set line [next-text] if {[is-a-directive $line]} { split-directive $line code rest switch -exact -- $code { .RE { break } .SH - .SS { manerror "unbalanced .RS at section end" backup-text 1 break } default { output-directive $line } } } else { man-puts $line } } } } man-puts

lappend manual(section-toc)
} ## ## process .RS lists ## proc output-RS-list {} { global manual if {[next-op-is .IP rest]} { output-IP-list .RS .IP $rest if {[match-text .RE .sp .RS @rest .IP @rest2]} { man-puts

$rest output-IP-list .RS .IP $rest2 } if {[match-text .RE .sp .RS @rest .RE]} { man-puts

$rest return } if {[next-op-is .RE rest]} { return } } man-puts

while {[more-text]} { set line [next-text] if {[is-a-directive $line]} { split-directive $line code rest switch -exact -- $code { .RE { break } .SH - .SS { manerror "unbalanced .RS at section end" backup-text 1 break } default { output-directive $line } } } else { man-puts $line } } man-puts
} ## ## process .IP lists which may be plain indents, ## numeric lists, or definition lists ## proc output-IP-list {context code rest} { global manual if {![string length $rest]} { # blank label, plain indent, no contents entry man-puts
while {[more-text]} { set line [next-text] if {[is-a-directive $line]} { split-directive $line code rest if {$code eq ".IP" && $rest eq {}} { man-puts "

" continue } if {$code in {.br .DS .RS}} { output-directive $line } else { backup-text 1 break } } else { man-puts $line } } man-puts

} else { # labelled list, make contents if {$context ne ".SH" && $context ne ".SS"} { man-puts

} set dl "

" set enddl "
" if {$code eq ".IP"} { if {[regexp {^\[[\da-f]+\]|\(?[\da-f]+\)$} $rest]} { set dl "
    " set enddl "
" } elseif {"•" eq $rest} { set dl "
    " set enddl "
" } } man-puts $dl lappend manual(section-toc) $dl backup-text 1 set accept_RE 0 set para {} while {[more-text]} { set line [next-text] if {[is-a-directive $line]} { split-directive $line code rest switch -exact -- $code { .IP { if {$accept_RE} { output-IP-list .IP $code $rest continue } if {$manual(section) eq "ARGUMENTS"} { man-puts "$para
$rest
" } elseif {[regexp {^\[([\da-f]+)\]$} $rest -> value]} { man-puts "$para
  • " } elseif {[regexp {^\(?([\da-f]+)\)$} $rest -> value]} { man-puts "$para
  • " } elseif {"•" eq $rest} { man-puts "$para
  • " } else { man-puts "$para
    [long-toc $rest]
    " } } .sp - .br - .DS - .CS { output-directive $line } .RS { if {[match-text .RS]} { output-directive $line incr accept_RE 1 } elseif {[match-text .CS]} { output-directive .CS incr accept_RE 1 } elseif {[match-text .PP]} { output-directive .PP incr accept_RE 1 } elseif {[match-text .DS]} { output-directive .DS incr accept_RE 1 } else { output-directive $line } } .PP { if {[match-text @rest1 .br @rest2 .RS]} { # yet another nroff kludge as above man-puts "$para
    [long-toc $rest1]" man-puts "
    [long-toc $rest2]
    " incr accept_RE 1 } elseif {[match-text @rest .RE]} { # gad, this is getting ridiculous if {!$accept_RE} { man-puts "$enddl

    $rest$dl" backup-text 1 set para {} break } man-puts "

    $rest" incr accept_RE -1 } elseif {$accept_RE} { output-directive $line } else { backup-text 1 break } } .RE { if {!$accept_RE} { backup-text 1 break } incr accept_RE -1 } default { backup-text 1 break } } } else { man-puts $line } set para

    } man-puts "$para$enddl" lappend manual(section-toc) $enddl if {$accept_RE} { manerror "missing .RE in output-IP-list" } } } ## ## handle the NAME section lines ## there's only one line in the NAME section, ## consisting of a comma separated list of names, ## followed by a hyphen and a short description. ## proc output-name {line} { global manual # split name line into pieces regexp {^([^-]+) - (.*)$} [regsub -all {[ \n\r\t]+} $line " "] -> head tail # output line to manual page untouched man-puts "$head — $tail" # output line to long table of contents lappend manual(section-toc) "

    $head — $tail
    " # separate out the names for future reference foreach name [split $head ,] { set name [string trim $name] if {[llength $name] > 1} { manerror "name has a space: {$name}\nfrom: $line" } lappend manual(wing-toc) $name lappend manual(name-$name) $manual(wing-file)/$manual(name) } set manual(tooltip-$manual(wing-file)/$manual(name).htm) $line } ## ## build a cross-reference link if appropriate ## proc cross-reference {ref} { global manual remap_link_target global ensemble_commands exclude_refs_map exclude_when_followed_by_map set manname $manual(name) set mantail $manual(tail) if {[string match "Tcl_*" $ref] || [string match "Tk_*" $ref] || [string match "Ttk_*" $ref] || [string match "Itcl_*" $ref] || [string match "Tdbc_*" $ref]} { regexp {^\w+} $ref lref ## ## apply a link remapping if available ## if {[info exists remap_link_target($lref)]} { set lref $remap_link_target($lref) } } elseif {$ref eq "Tcl"} { set lref $ref } elseif { [regexp {^[A-Z0-9 ?!]+$} $ref] && [info exists manual($manname-id-$ref)] } { return "$ref" } else { set lref [string tolower $ref] ## ## apply a link remapping if available ## if {[info exists remap_link_target($lref)]} { set lref $remap_link_target($lref) } } ## ## nothing to reference ## if {![info exists manual(name-$lref)]} { foreach name $ensemble_commands { if { [regexp "^$name \[a-z0-9]*\$" $lref] && [info exists manual(name-$name)] && $mantail ne "$name.n" && (![info exists exclude_refs_map($mantail)] || $manual(name-$name) ni $exclude_refs_map($mantail)) } { return "$ref" } } if {$lref in {end}} { # no good place to send this tcl token? } return $ref } set manref $manual(name-$lref) ## ## would be a self reference ## foreach name $manref { if {"$manual(wing-file)/$manname" in $name} { return $ref } } ## ## multiple choices for reference ## if {[llength $manref] > 1} { set tcl_i [lsearch -glob $manref *TclCmd*] if {$tcl_i >= 0 && $manual(wing-file) eq "TclCmd" || $manual(wing-file) eq "TclLib"} { set tcl_ref [lindex $manref $tcl_i] return "$ref" } set tk_i [lsearch -glob $manref *TkCmd*] if {$tk_i >= 0 && $manual(wing-file) eq "TkCmd" || $manual(wing-file) eq "TkLib"} { set tk_ref [lindex $manref $tk_i] return "$ref" } if {$lref eq "exit" && $mantail eq "tclsh.1" && $tcl_i >= 0} { set tcl_ref [lindex $manref $tcl_i] return "$ref" } puts stderr "multiple cross reference to $ref in $manref from $manual(wing-file)/$mantail" return $ref } ## ## exceptions, sigh, to the rule ## if {[info exists exclude_when_followed_by_map($mantail)]} { upvar 1 text tail set following_word [lindex [regexp -inline {\S+} $tail] 0] foreach {this that} $exclude_when_followed_by_map($mantail) { # only a ref if $this is not followed by $that if {$lref eq $this && [string match $that* $following_word]} { return $ref } } } if { [info exists exclude_refs_map($mantail)] && $lref in $exclude_refs_map($mantail) } { return $ref } ## ## return the cross reference ## return "$ref" } ## ## reference generation errors ## proc reference-error {msg text} { global manual puts stderr "$manual(tail): $msg: {$text}" return $text } ## ## insert as many cross references into this text string as are appropriate ## proc insert-cross-references {text} { global manual set result "" while 1 { ## ## we identify cross references by: ## ``quotation'' ## emboldening ## Tcl_ prefix ## Tk_ prefix ## [a-zA-Z0-9]+ manual entry ## and we avoid messing with already anchored text ## ## ## find where each item lives - EXPENSIVE - and accumulate a list ## unset -nocomplain offsets foreach {name pattern} { anchor {} quote {``} end-quote {''} bold {} end-bold {} c.tcl {Tcl_} c.tk {Tk_} c.ttk {Ttk_} c.tdbc {Tdbc_} c.itcl {Itcl_} Tcl1 {Tcl manual entry} Tcl2 {Tcl overview manual entry} url {http://} } { set o [string first $pattern $text] if {[set offset($name) $o] >= 0} { set invert($o) $name lappend offsets $o } } ## ## if nothing, then we're done. ## if {![info exists offsets]} { return [append result $text] } ## ## sort the offsets ## set offsets [lsort -integer $offsets] ## ## see which we want to use ## switch -exact -- $invert([lindex $offsets 0]) { anchor { if {$offset(end-anchor) < 0} { return [reference-error {Missing end anchor} $text] } append result [string range $text 0 $offset(end-anchor)] set text [string range $text[set text ""] \ [expr {$offset(end-anchor)+1}] end] continue } quote { if {$offset(end-quote) < 0} { return [reference-error "Missing end quote" $text] } if {$invert([lindex $offsets 1]) in {tcl tk ttk}} { set offsets [lreplace $offsets 1 1] } switch -exact -- $invert([lindex $offsets 1]) { end-quote { append result [string range $text 0 [expr {$offset(quote)-1}]] set body [string range $text [expr {$offset(quote)+2}] \ [expr {$offset(end-quote)-1}]] set text [string range $text[set text ""] \ [expr {$offset(end-quote)+2}] end] append result `` [cross-reference $body] '' continue } bold - anchor { append result [string range $text \ 0 [expr {$offset(end-quote)+1}]] set text [string range $text[set text ""] \ [expr {$offset(end-quote)+2}] end] continue } } return [reference-error "Uncaught quote case" $text] } bold { if {$offset(end-bold) < 0} { return [append result $text] } if {[string match "c.*" $invert([lindex $offsets 1])]} { set offsets [lreplace $offsets 1 1] } switch -exact -- $invert([lindex $offsets 1]) { url - end-bold { append result \ [string range $text 0 [expr {$offset(bold)-1}]] set body [string range $text [expr {$offset(bold)+3}] \ [expr {$offset(end-bold)-1}]] set text [string range $text[set text ""] \ [expr {$offset(end-bold)+4}] end] regsub {http://[\w/.]+} $body {&} body append result [cross-reference $body] continue } anchor { append result \ [string range $text 0 [expr {$offset(end-bold)+3}]] set text [string range $text[set text ""] \ [expr {$offset(end-bold)+4}] end] continue } default { return [reference-error "Uncaught bold case" $text] } } } c.tk - c.ttk - c.tcl - c.tdbc - c.itcl { append result [string range $text 0 \ [expr {[lindex $offsets 0]-1}]] regexp -indices -start [lindex $offsets 0] {\w+} $text range set body [string range $text {*}$range] set text [string range $text[set text ""] \ [expr {[lindex $range 1]+1}] end] append result [cross-reference $body] continue } Tcl1 - Tcl2 { set off [lindex $offsets 0] append result [string range $text 0 [expr {$off-1}]] set text [string range $text[set text ""] [expr {$off+3}] end] append result [cross-reference Tcl] continue } url { set off [lindex $offsets 0] append result [string range $text 0 [expr {$off-1}]] regexp -indices -start $off {http://[\w/.]+} $text range set url [string range $text {*}$range] append result "$url" set text [string range $text[set text ""] \ [expr {[lindex $range 1]+1}] end] continue } end-anchor - end-bold - end-quote { return [reference-error "Out of place $invert([lindex $offsets 0])" $text] } } } } ## ## process formatting directives ## proc output-directive {line} { global manual # process format directive split-directive $line code rest switch -exact -- $code { .BS - .BE { # man-puts
    } .SH - .SS { # drain any open lists # announce the subject set manual(section) $rest # start our own stack of stuff set manual($manual(name)-$manual(section)) {} lappend manual(has-$manual(section)) $manual(name) if {$code ne ".SS"} { man-puts "

    [long-toc $manual(section)]

    " } else { man-puts "

    [long-toc $manual(section)]

    " } # some sections can simply free wheel their way through the text # some sections can be processed in their own loops switch -exact -- [string index $code end]:$manual(section) { H:NAME { set names {} while {1} { set line [next-text] if {[is-a-directive $line]} { backup-text 1 if {[llength $names]} { output-name [join $names { }] } return } lappend names [string trim $line] } } H:SYNOPSIS { lappend manual(section-toc)
    while {1} { if { [next-op-is .nf rest] || [next-op-is .br rest] || [next-op-is .fi rest] } { continue } if { [next-op-is .SH rest] || [next-op-is .SS rest] || [next-op-is .BE rest] || [next-op-is .SO rest] } { backup-text 1 break } if {[next-op-is .sp rest]} { #man-puts

    continue } set more [next-text] if {[is-a-directive $more]} { manerror "in SYNOPSIS found $more" backup-text 1 break } foreach more [split $more \n] { regexp {^(\s*)(.*)} $more -> spaces more set spaces [string map {" " " "} $spaces] if {[string length $spaces]} { set spaces $spaces } man-puts $spaces$more
    if {$manual(wing-file) in {TclLib TkLib}} { lappend manual(section-toc)

    $more } } } lappend manual(section-toc)
    return } {H:SEE ALSO} { while {[more-text]} { if {[next-op-is .SH rest] || [next-op-is .SS rest]} { backup-text 1 return } set more [next-text] if {[is-a-directive $more]} { manerror "$more" backup-text 1 return } set nmore {} foreach cr [split $more ,] { set cr [string trim $cr] if {![regexp {^.*$} $cr]} { set cr $cr } if {[regexp {^(.*)\([13n]\)$} $cr all name]} { set cr $name } lappend nmore $cr } man-puts [join $nmore {, }] } return } H:KEYWORDS { while {[more-text]} { if {[next-op-is .SH rest] || [next-op-is .SS rest]} { backup-text 1 return } set more [next-text] if {[is-a-directive $more]} { manerror "$more" backup-text 1 return } set keys {} foreach key [split $more ,] { set key [string trim $key] lappend manual(keyword-$key) [list $manual(name) \ $manual(wing-file)/$manual(name).htm] set initial [string toupper [string index $key 0]] lappend keys "$key" } man-puts [join $keys {, }] } return } } if {[next-op-is .IP rest]} { output-IP-list $code .IP $rest return } if {[next-op-is .PP rest]} { return } return } .SO { # When there's a sequence of multiple .SO chunks, process into one set optslist {} while 1 { if {[match-text @stuff .SE]} { foreach opt [split $stuff \n\t] { lappend optslist [list $opt $rest] } } else { manerror "unexpected .SO format:\n[expand-next-text 2]" } if {![next-op-is .SO rest]} { break } } output-directive {.SH STANDARD OPTIONS} man-puts
    lappend manual(section-toc)
    foreach optionpair [lsort -dictionary -index 0 $optslist] { lassign $optionpair option targetPage man-puts "
    [std-option-toc $option $targetPage]" } man-puts
    lappend manual(section-toc)
    } .OP { output-widget-options $rest return } .IP { output-IP-list .IP .IP $rest return } .PP - .sp { man-puts

    } .RS { output-RS-list return } .br { man-puts
    return } .DS { if {[next-op-is .ta rest]} { # skip the leading .ta directive if it is there } if {[match-text @stuff .DE]} { set td "

    " set bodyText [string map [list \n $td \t $td] \n$stuff] man-puts "

    $bodyText
    " #man-puts
    $stuff
    } elseif {[match-text .fi @ul1 @ul2 .nf @stuff .DE]} { man-puts "
    [lindex $ul1 1][lindex $ul2 1]\n$stuff
    " } else { manerror "unexpected .DS format:\n[expand-next-text 2]" } return } .CS { if {[next-op-is .ta rest]} { # ??? } if {[match-text @stuff .CE]} { man-puts
    $stuff
    } else { manerror "unexpected .CS format:\n[expand-next-text 2]" } return } .nf { if {[match-text @more .fi]} { foreach more [split $more \n] { man-puts $more
    } } elseif {[match-text .RS @more .RE .fi]} { man-puts
    foreach more [split $more \n] { man-puts $more
    } man-puts
    } elseif {[match-text .RS @more .RS @more2 .RE .RE .fi]} { man-puts
    foreach more [split $more \n] { man-puts $more
    } man-puts
    foreach more2 [split $more2 \n] { man-puts $more2
    } man-puts
    } elseif {[match-text .RS @more .RS @more2 .RE @more3 .RE .fi]} { man-puts
    foreach more [split $more \n] { man-puts $more
    } man-puts
    foreach more2 [split $more2 \n] { man-puts $more2
    } man-puts
    foreach more3 [split $more3 \n] { man-puts $more3
    } man-puts
    } elseif {[match-text .sp .RS @more .RS @more2 .sp .RE .RE .fi]} { man-puts

    foreach more [split $more \n] { man-puts $more
    } man-puts
    foreach more2 [split $more2 \n] { man-puts $more2
    } man-puts

    } elseif {[match-text .RS .sp @more .sp .RE .fi]} { man-puts

    foreach more [split $more \n] { man-puts $more
    } man-puts

    } else { manerror "ignoring $line" } } .RE - .DE - .CE { manerror "unexpected $code" return } .ta - .fi - .na - .ad - .UL - .ie - .el - .ne { manerror "ignoring $line" } default { manerror "unrecognized format directive: $line" } } } ## ## merge copyright listings ## proc merge-copyrights {l1 l2} { set merge {} set re1 {^Copyright +(?:\(c\)|\\\(co|©) +(\w.*?)(?:all rights reserved)?(?:\. )*$} set re2 {^(\d+) +(?:by +)?(\w.*)$} ;# date who set re3 {^(\d+)-(\d+) +(?:by +)?(\w.*)$} ;# from to who set re4 {^(\d+), *(\d+) +(?:by +)?(\w.*)$} ;# date1 date2 who foreach copyright [concat $l1 $l2] { if {[regexp -nocase -- $re1 $copyright -> info]} { set info [string trimright $info ". "] ; # remove extra period if {[regexp -- $re2 $info -> date who]} { lappend dates($who) $date continue } elseif {[regexp -- $re3 $info -> from to who]} { for {set date $from} {$date <= $to} {incr date} { lappend dates($who) $date } continue } elseif {[regexp -- $re3 $info -> date1 date2 who]} { lappend dates($who) $date1 $date2 continue } } puts "oops: $copyright" } foreach who [array names dates] { set list [lsort -dictionary $dates($who)] if {[llength $list] == 1 || [lindex $list 0] eq [lrange $list end end]} { lappend merge "Copyright © [lindex $list 0] $who" } else { lappend merge "Copyright © [lindex $list 0]-[lrange $list end end] $who" } } return [lsort -dictionary $merge] } ## ## foreach of the man pages in the section specified by ## sectionDescriptor, convert manpages into hypertext in ## the directory specified by outputDir. ## proc make-manpage-section {outputDir sectionDescriptor} { global manual overall_title tcltkdesc verbose global excluded_pages forced_index_pages process_first_patterns set LQ \u201c set RQ \u201d lassign $sectionDescriptor \ manual(wing-glob) \ manual(wing-name) \ manual(wing-file) \ manual(wing-description) set manual(wing-copyrights) {} makedirhier $outputDir/$manual(wing-file) set manual(wing-toc-fp) [open $outputDir/$manual(wing-file)/[indexfile] w] # whistle puts stderr "scanning section $manual(wing-name)" # put the entry for this section into the short table of contents if {[regexp {^(.+), version (.+)$} $manual(wing-name) -> name version]} { puts $manual(short-toc-fp) "

    $name
    $manual(wing-description)
    " } else { puts $manual(short-toc-fp) "
    $manual(wing-name)
    $manual(wing-description)
    " } # initialize the wing table of contents puts $manual(wing-toc-fp) [htmlhead $manual(wing-name) \ $manual(wing-name) $overall_title "../[indexfile]"] # initialize the short table of contents for this section set manual(wing-toc) {} # initialize the man directory for this section makedirhier $outputDir/$manual(wing-file) # initialize the long table of contents for this section set manual(long-toc-n) 1 # get the manual pages for this section set manual(pages) [lsort -dictionary [glob -nocomplain $manual(wing-glob)]] # Some pages have to go first so that their links override others foreach pat $process_first_patterns { set n [lsearch -glob $manual(pages) $pat] if {$n >= 0} { set f [lindex $manual(pages) $n] puts stderr "shuffling [file tail $f] to front of processing queue" set manual(pages) \ [linsert [lreplace $manual(pages) $n $n] 0 $f] } } # set manual(pages) [lrange $manual(pages) 0 5] foreach manual_page $manual(pages) { set manual(page) [file normalize $manual_page] # whistle if {$verbose} { puts stderr "scanning page $manual(page)" } else { puts -nonewline stderr . } set manual(tail) [file tail $manual(page)] set manual(name) [file root $manual(tail)] set manual(section) {} if {$manual(name) in $excluded_pages} { # obsolete if {!$verbose} { puts stderr "" } manerror "discarding $manual(name)" continue } set manual(infp) [open $manual(page)] set manual(text) {} set manual(partial-text) {} foreach p {.RS .DS .CS .SO} { set manual($p) 0 } set manual(stack) {} set manual(section) {} set manual(section-toc) {} set manual(section-toc-n) 1 set manual(copyrights) {} lappend manual(all-pages) $manual(wing-file)/$manual(tail) lappend manual(all-page-domains) $manual(wing-name) manreport 100 $manual(name) while {[gets $manual(infp) line] >= 0} { manreport 100 $line if {[regexp {^[`'][/\\]} $line]} { if {[regexp {Copyright (?:\(c\)|\\\(co).*$} $line copyright]} { lappend manual(copyrights) $copyright } # comment continue } if {"$line" eq {'}} { # comment continue } if {![parse-directive $line code rest]} { addbuffer $line continue } switch -exact -- $code { .if - .nr - .ti - .in - .ie - .el - .ad - .na - .so - .ne - .AS - .HS - .VE - .VS - . { # ignore continue } } switch -exact -- $code { .SH - .SS { flushbuffer if {[llength $rest] == 0} { gets $manual(infp) rest } lappend manual(text) "$code [unquote $rest]" } .TH { flushbuffer lappend manual(text) "$code [unquote $rest]" } .QW { lassign [regexp -all -inline {\"(?:[^""]+)\"|\S+} $rest] \ inQuote afterwards addbuffer $LQ [unquote $inQuote] $RQ [unquote $afterwards] } .PQ { lassign [regexp -all -inline {\"(?:[^""]+)\"|\S+} $rest] \ inQuote punctuation afterwards addbuffer ( $LQ [unquote $inQuote] $RQ \ [unquote $punctuation] ) [unquote $afterwards] } .QR { lassign [regexp -all -inline {\"(?:[^""]+)\"|\S+} $rest] \ rangeFrom rangeTo afterwards addbuffer $LQ [unquote $rangeFrom] "–" \ [unquote $rangeTo] $RQ [unquote $afterwards] } .MT { addbuffer $LQ$RQ } .HS - .UL - .ta { flushbuffer lappend manual(text) "$code [unquote $rest]" } .BS - .BE - .br - .fi - .sp - .nf { flushbuffer if {$rest ne ""} { if {!$verbose} { puts stderr "" } manerror "unexpected argument: $line" } lappend manual(text) $code } .AP { flushbuffer lappend manual(text) [concat .IP [process-text \ "[lindex $rest 0] \\fB[lindex $rest 1]\\fR ([lindex $rest 2])"]] } .IP { flushbuffer regexp {^(.*) +\d+$} $rest all rest lappend manual(text) ".IP [process-text \ [unquote [string trim $rest]]]" } .TP { flushbuffer while {[is-a-directive [set next [gets $manual(infp)]]]} { if {!$verbose} { puts stderr "" } manerror "ignoring $next after .TP" } if {"$next" ne {'}} { lappend manual(text) ".IP [process-text $next]" } } .OP { flushbuffer lassign $rest cmdName dbName dbClass lappend manual(text) [concat .OP [process-text \ "\\fB$cmdName\\fR \\fB$dbName\\fR \\fB$dbClass\\fR"]] } .PP - .LP { flushbuffer lappend manual(text) {.PP} } .RS { flushbuffer incr manual(.RS) lappend manual(text) $code } .RE { flushbuffer incr manual(.RS) -1 lappend manual(text) $code } .SO { flushbuffer incr manual(.SO) if {[llength $rest] == 0} { lappend manual(text) "$code options" } else { lappend manual(text) "$code [unquote $rest]" } } .SE { flushbuffer incr manual(.SO) -1 lappend manual(text) $code } .DS { flushbuffer incr manual(.DS) lappend manual(text) $code } .DE { flushbuffer incr manual(.DS) -1 lappend manual(text) $code } .CS { flushbuffer incr manual(.CS) lappend manual(text) $code } .CE { flushbuffer incr manual(.CS) -1 lappend manual(text) $code } .de { while {[gets $manual(infp) line] >= 0} { if {[string match "..*" $line]} { break } } } .. { if {!$verbose} { puts stderr "" } error "found .. outside of .de" } default { if {!$verbose} { puts stderr "" } flushbuffer manerror "unrecognized format directive: $line" } } } flushbuffer close $manual(infp) # fixups if {$manual(.RS) != 0} { if {!$verbose} { puts stderr "" } puts "unbalanced .RS .RE" } if {$manual(.DS) != 0} { if {!$verbose} { puts stderr "" } puts "unbalanced .DS .DE" } if {$manual(.CS) != 0} { if {!$verbose} { puts stderr "" } puts "unbalanced .CS .CE" } if {$manual(.SO) != 0} { if {!$verbose} { puts stderr "" } puts "unbalanced .SO .SE" } # output conversion open-text set haserror 0 if {[next-op-is .HS rest]} { set manual($manual(wing-file)-$manual(name)-title) \ "[join [lrange $rest 1 end] { }] [lindex $rest 0] manual page" } elseif {[next-op-is .TH rest]} { set manual($manual(wing-file)-$manual(name)-title) \ "[lindex $rest 0] manual page - [join [lrange $rest 4 end] { }]" } else { set haserror 1 if {!$verbose} { puts stderr "" } manerror "no .HS or .TH record found" } if {!$haserror} { while {[more-text]} { set line [next-text] if {[is-a-directive $line]} { output-directive $line } else { man-puts $line } } man-puts [copyout $manual(copyrights) "../"] set manual(wing-copyrights) [merge-copyrights \ $manual(wing-copyrights) $manual(copyrights)] } # # make the long table of contents for this page # set manual(toc-$manual(wing-file)-$manual(name)) \ [concat
    $manual(section-toc)
    ] } if {!$verbose} { puts stderr "" } # # make the wing table of contents for the section # set width 0 foreach name $manual(wing-toc) { if {[string length $name] > $width} { set width [string length $name] } } set perline [expr {118 / $width}] set nrows [expr {([llength $manual(wing-toc)]+$perline)/$perline}] set n 0 catch {unset rows} foreach name [lsort -dictionary $manual(wing-toc)] { set tail $manual(name-$name) if {[llength $tail] > 1} { manerror "$name is defined in more than one file: $tail" set tail [lindex $tail [expr {[llength $tail]-1}]] } set tail [file tail $tail] if {[info exists manual(tooltip-$manual(wing-file)/$tail.htm)]} { set tooltip $manual(tooltip-$manual(wing-file)/$tail.htm) set tooltip [string map {[ {\[} ] {\]} $ {\$} \\ \\\\} $tooltip] regsub {^[^-]+-\s*(.)} $tooltip {[string totitle \1]} tooltip append rows([expr {$n%$nrows}]) \ " $name " } else { append rows([expr {$n%$nrows}]) \ " $name " } incr n } puts $manual(wing-toc-fp) foreach row [lsort -integer [array names rows]] { puts $manual(wing-toc-fp) $rows($row) } puts $manual(wing-toc-fp)
    # # insert wing copyrights # puts $manual(wing-toc-fp) [copyout $manual(wing-copyrights) "../"] puts $manual(wing-toc-fp) "" close $manual(wing-toc-fp) set manual(merge-copyrights) \ [merge-copyrights $manual(merge-copyrights) $manual(wing-copyrights)] } proc makedirhier {dir} { try { if {![file isdirectory $dir]} { file mkdir $dir } } on error msg { return -code error "cannot create directory $dir: $msg" } } proc addbuffer {args} { global manual if {$manual(partial-text) ne ""} { append manual(partial-text) \n } append manual(partial-text) [join $args ""] } proc flushbuffer {} { global manual if {$manual(partial-text) ne ""} { lappend manual(text) [process-text $manual(partial-text)] set manual(partial-text) "" } } return tcl8.6.5/tools/configure.in0000644000175000017500000000242712663653210015237 0ustar sergeisergeidnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run to configure the dnl Makefile in this directory. AC_INIT(man2tcl.c) AC_PREREQ(2.59) # Recover information that Tcl computed with its configure script. #-------------------------------------------------------------------- # See if there was a command-line option for where Tcl is; if # not, assume that its top-level directory is a sibling of ours. #-------------------------------------------------------------------- DEF_VER=8.6 AC_ARG_WITH(tcl, [ --with-tcl=DIR use Tcl $DEF_VER binaries from DIR], TCL_BIN_DIR=$withval, TCL_BIN_DIR=`cd ../../tcl$DEF_VER$TCL_PATCH_LEVEL/unix; pwd`) if test ! -d $TCL_BIN_DIR; then AC_MSG_ERROR(Tcl directory $TCL_BIN_DIR doesn't exist) fi if test ! -f $TCL_BIN_DIR/tclConfig.sh; then AC_MSG_ERROR(There's no tclConfig.sh in $TCL_BIN_DIR; perhaps you didn't specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?) fi . $TCL_BIN_DIR/tclConfig.sh TCL_WIN_VERSION=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION AC_SUBST(TCL_WIN_VERSION) CC=$TCL_CC AC_SUBST(CC) AC_SUBST(TCL_VERSION) AC_SUBST(TCL_PATCH_LEVEL) AC_SUBST(TCL_SRC_DIR) AC_SUBST(TCL_BIN_DIR) AC_OUTPUT(Makefile tcl.hpj) tcl8.6.5/tools/man2help.tcl0000644000175000017500000000631012663660066015142 0ustar sergeisergei# man2help.tcl -- # # This file defines procedures that work in conjunction with the # man2tcl program to generate a Windows help file from Tcl manual # entries. # # Copyright (c) 1996 by Sun Microsystems, Inc. # # PASS 1 # set man2tclprog [file join [file dirname [info script]] \ man2tcl[file extension [info nameofexecutable]]] proc generateContents {basename version files} { global curID topics set curID 0 foreach f $files { puts "Pass 1 -- $f" flush stdout doFile $f } set fd [open [file join [file dirname [info script]] $basename$version.cnt] w] fconfigure $fd -translation crlf puts $fd ":Base $basename$version.hlp" foreach package [getPackages] { foreach section [getSections $package] { if {![info exists lastSection]} { set lastSection {} } if {[string compare $lastSection $section]} { puts $fd "1 $section" } set lastSection $section set lastTopic {} foreach topic [getTopics $package $section] { if {[string compare $lastTopic $topic]} { set id $topics($package,$section,$topic) puts $fd "2 $topic=$id" set lastTopic $topic } } } } close $fd } # # PASS 2 # proc generateHelp {basename files} { global curID topics keywords file id_keywords set curID 0 foreach key [array names keywords] { foreach id $keywords($key) { lappend id_keywords($id) $key } } set file [open [file join [file dirname [info script]] $basename.rtf] w] fconfigure $file -translation crlf puts $file "\{\\rtf1\\ansi \\deff0\\deflang1033\{\\fonttbl\{\\f0\\froman\\fcharset0\\fprq2 Times New Roman\;\}\{\\f1\\fmodern\\fcharset0\\fprq1 Courier New\;\}\}" foreach f $files { puts "Pass 2 -- $f" flush stdout initGlobals doFile $f pageBreak } puts $file "\}" close $file } # doFile -- # # Given a file as argument, translate the file to a tcl script and # evaluate it. # # Arguments: # file - Name of file to translate. proc doFile {file} { global man2tclprog if {[catch {eval [exec $man2tclprog [glob $file]]} msg]} { global errorInfo puts stderr $msg puts "in" puts $errorInfo exit 1 } } # doDir -- # # Given a directory as argument, translate all the man pages in # that directory. # # Arguments: # dir - Name of the directory. proc doDir dir { puts "Generating man pages for $dir..." foreach f [lsort [glob -directory $dir "*.\[13n\]"]] { doFile $f } } # process command line arguments if {$argc < 3} { puts stderr "usage: $argv0 \[options\] projectName version manFiles..." exit 1 } set arg 0 if {![string compare [lindex $argv $arg] "-bitmap"]} { set bitmap [lindex $argv [incr arg]] incr arg } set baseName [lindex $argv $arg] set version [lindex $argv [incr arg]] set files {} foreach i [lrange $argv [incr arg] end] { set i [file join $i] if {[file isdir $i]} { foreach f [lsort [glob -directory $i "*.\[13n\]"]] { lappend files $f } } elseif {[file exists $i]} { lappend files $i } } source [file join [file dirname [info script]] index.tcl] generateContents $baseName $version $files source [file join [file dirname [info script]] man2help2.tcl] generateHelp $baseName $files tcl8.6.5/tools/man2html2.tcl0000644000175000017500000005132412663653210015236 0ustar sergeisergei############################################################################## # man2html2.tcl -- # # This file defines procedures that are used during the second pass of the man # page to html conversion process. It is sourced by man2html.tcl. # # Copyright (c) 1996 by Sun Microsystems, Inc. package require Tcl 8.4 # Global variables used by these scripts: # # NAME_file - array indexed by NAME and containing file names used for # hyperlinks. # # textState - state variable defining action of 'text' proc. # # nestStk - stack oriented list containing currently active HTML tags (UL, # OL, DL). Local to 'nest' proc. # # inDT - set by 'TPmacro', cleared by 'newline'. Used to insert the # tag while in a dictionary list
    . # # curFont - Name of special font that is currently in use. Null means the # default paragraph font is being used. # # file - Where to output the generated HTML. # # fontStart - Array to map font names to starting sequences. # # fontEnd - Array to map font names to ending sequences. # # noFillCount - Non-zero means don't fill the next $noFillCount lines: force a # line break at each newline. Zero means filling is enabled, so # don't output line breaks for each newline. # # footer - info inserted at bottom of each page. Normally read from the # xref.tcl file ############################################################################## # initGlobals -- # # This procedure is invoked to set the initial values of all of the global # variables, before processing a man page. # # Arguments: # None. proc initGlobals {} { global file noFillCount textState global fontStart fontEnd curFont inPRE charCnt inTable nest init set inPRE 0 set inTable 0 set textState 0 set curFont "" set fontStart(Code) "" set fontStart(Emphasis) "" set fontEnd(Code) "" set fontEnd(Emphasis) "" set noFillCount 0 set charCnt 0 setTabs 0.5i } ############################################################################## # beginFont -- # # Arranges for future text to use a special font, rather than the default # paragraph font. # # Arguments: # font - Name of new font to use. proc beginFont font { global curFont file fontStart if {$curFont eq $font} { return } endFont puts -nonewline $file $fontStart($font) set curFont $font } ############################################################################## # endFont -- # # Reverts to the default font for the paragraph type. # # Arguments: # None. proc endFont {} { global curFont file fontEnd if {$curFont ne ""} { puts -nonewline $file $fontEnd($curFont) set curFont "" } } ############################################################################## # text -- # # This procedure adds text to the current paragraph. If this is the first text # in the paragraph then header information for the paragraph is output before # the text. # # Arguments: # string - Text to output in the paragraph. proc text string { global file textState inDT charCnt inTable set pos [string first "\t" $string] if {$pos >= 0} { text [string range $string 0 [expr $pos-1]] tab text [string range $string [expr $pos+1] end] return } if {$inTable} { if {$inTable == 1} { puts -nonewline $file set inTable 2 } puts -nonewline $file } incr charCnt [string length $string] regsub -all {&} $string {\&} string regsub -all {<} $string {\<} string regsub -all {>} $string {\>} string regsub -all \" $string {\"} string switch -exact -- $textState { REF { if {$inDT eq ""} { set string [insertRef $string] } } SEE { global NAME_file foreach i [split $string] { if {![regexp -nocase {^[a-z_]+} [string trim $i] i]} { # puts "Warning: $i in SEE ALSO not found" continue } if {![catch { set ref $NAME_file($i) }]} { regsub $i $string "$i" string } } } } puts -nonewline $file "$string" if {$inTable} { puts -nonewline $file } } ############################################################################## # insertRef -- # # Arguments: # string - Text to output in the paragraph. proc insertRef string { global NAME_file self set path {} if {![catch { set ref $NAME_file([string trim $string]) }]} { if {"$ref.html" ne $self} { set string "$string" # puts "insertRef: $self $ref.html ---$string--" } } return $string } ############################################################################## # macro -- # # This procedure is invoked to process macro invocations that start with "." # (instead of '). # # Arguments: # name - The name of the macro (without the "."). # args - Any additional arguments to the macro. proc macro {name args} { switch $name { AP { if {[llength $args] != 3} { puts stderr "Bad .AP macro: .$name [join $args " "]" } setTabs {1.25i 2.5i 3.75i} TPmacro {} font B text "[lindex $args 0] " font I text "[lindex $args 1]" font R text " ([lindex $args 2])" newline } AS {} ;# next page and previous page br { lineBreak } BS {} BE {} CE { global file noFillCount inPRE puts $file set inPRE 0 } CS { ;# code section global file noFillCount inPRE puts -nonewline $file
    	    set inPRE 1
    	}
    	DE {
    	    global file noFillCount inTable
    	    puts $file 
    set inTable 0 set noFillCount 0 } DS { global file noFillCount inTable puts -nonewline $file {
    } set noFillCount 10000000 set inTable 1 } fi { global noFillCount set noFillCount 0 } IP { IPmacro $args } LP { nest decr nest incr newPara } ne { } nf { global noFillCount set noFillCount 1000000 } OP { global inDT file inPRE if {[llength $args] != 3} { puts stderr "Bad .OP macro: .$name [join $args " "]" } nest para DL DT set inPRE 1 puts -nonewline $file
    	    setTabs 4c
    	    text "Command-Line Name:"
    	    tab
    	    font B
    	    set x [lindex $args 0]
    	    regsub -all {\\-} $x - x
    	    text $x
    	    newline
    	    font R
    	    text "Database Name:"
    	    tab
    	    font B
    	    text [lindex $args 1]
    	    newline
    	    font R
    	    text "Database Class:"
    	    tab
    	    font B
    	    text [lindex $args 2]
    	    font R
    	    puts -nonewline $file 
    set inDT "\n
    " ;# next newline writes inDT set inPRE 0 newline } PP { nest decr nest incr newPara } RE { nest decr } RS { nest incr } SE { global noFillCount textState inPRE file font R puts -nonewline $file set inPRE 0 set noFillCount 0 nest reset newPara text "See the " font B set temp $textState set textState REF if {[llength $args] > 0} { text [lindex $args 0] } else { text options } set textState $temp font R text " manual entry for detailed descriptions of the above options." } SH { SHmacro $args } SS { SHmacro $args subsection } SO { global noFillCount inPRE file SHmacro "STANDARD OPTIONS" setTabs {4c 8c 12c} set noFillCount 1000000 puts -nonewline $file
    	    set inPRE 1
    	    font B
    	}
    	so {
    	    if {$args ne "man.macros"} {
    		puts stderr "Unknown macro: .$name [join $args " "]"
    	    }
    	}
    	sp {					;# needs work
    	    if {$args eq ""} {
    		set count 1
    	    } else {
    		set count [lindex $args 0]
    	    }
    	    while {$count > 0} {
    		lineBreak
    		incr count -1
    	    }
    	}
    	ta {
    	    setTabs $args
    	}
    	TH {
    	    THmacro $args
    	}
    	TP {
    	    TPmacro $args
    	}
    	UL {					;# underline
    	    global file
    	    puts -nonewline $file ""
    	    text [lindex $args 0]
    	    puts -nonewline $file ""
    	    if {[llength $args] == 2} {
    		text [lindex $args 1]
    	    }
    	}
    	VE {
    #	    global file
    #	    puts -nonewline $file ""
    	}
    	VS {
    #	    global file
    #	    if {[llength $args] > 0} {
    #		puts -nonewline $file "
    " # } # puts -nonewline $file "" } QW { puts -nonewline $file "&\#147;" text [lindex $args 0] puts -nonewline $file "&\#148;" if {[llength $args] > 1} { text [lindex $args 1] } } PQ { puts -nonewline $file "(&\#147;" if {[lindex $args 0] eq {\N'34'}} { puts -nonewline $file \" } else { text [lindex $args 0] } puts -nonewline $file "&\#148;" if {[llength $args] > 1} { text [lindex $args 1] } puts -nonewline $file ")" if {[llength $args] > 2} { text [lindex $args 2] } } QR { puts -nonewline $file "&\#147;" text [lindex $args 0] puts -nonewline $file "&\#148;&\#150;&\#147;" text [lindex $args 1] puts -nonewline $file "&\#148;" if {[llength $args] > 2} { text [lindex $args 2] } } MT { puts -nonewline $file "&\#147;&\#148;" } default { puts stderr "Unknown macro: .$name [join $args " "]" } } # global nestStk; puts "$name [format "%-20s" $args] $nestStk" # flush stdout; flush stderr } ############################################################################## # font -- # # This procedure is invoked to handle font changes in the text being output. # # Arguments: # type - Type of font: R, I, B, or S. proc font type { global textState switch $type { P - R { endFont if {$textState eq "REF"} { set textState INSERT } } B { beginFont Code if {$textState eq "INSERT"} { set textState REF } } I { beginFont Emphasis } S { } default { puts stderr "Unknown font: $type" } } } ############################################################################## # formattedText -- # # Insert a text string that may also have \fB-style font changes and a few # other backslash sequences in it. # # Arguments: # text - Text to insert. proc formattedText text { # puts "formattedText: $text" while {$text ne ""} { set index [string first \\ $text] if {$index < 0} { text $text return } text [string range $text 0 [expr $index-1]] set c [string index $text [expr $index+1]] switch -- $c { f { font [string index $text [expr $index+2]] set text [string range $text [expr $index+3] end] } e { text \\ set text [string range $text [expr $index+2] end] } - { dash set text [string range $text [expr $index+2] end] } | { set text [string range $text [expr $index+2] end] } default { puts stderr "Unknown sequence: \\$c" set text [string range $text [expr $index+2] end] } } } } ############################################################################## # dash -- # # This procedure is invoked to handle dash characters ("\-" in troff). It # outputs a special dash character. # # Arguments: # None. proc dash {} { global textState charCnt if {$textState eq "NAME"} { set textState 0 } incr charCnt text "-" } ############################################################################## # tab -- # # This procedure is invoked to handle tabs in the troff input. # # Arguments: # None. proc tab {} { global inPRE charCnt tabString file # ? charCnt if {$inPRE == 1} { set pos [expr $charCnt % [string length $tabString] ] set spaces [string first "1" [string range $tabString $pos end] ] text [format "%*s" [incr spaces] " "] } else { # puts "tab: found tab outside of
     block"
        }
    }
    
    ##############################################################################
    # setTabs --
    #
    # This procedure handles the ".ta" macro, which sets tab stops.
    #
    # Arguments:
    # tabList -	List of tab stops, each consisting of a number
    #			followed by "i" (inch) or "c" (cm).
    
    proc setTabs {tabList} {
        global file breakPending tabString
    
        # puts "setTabs: --$tabList--"
        set last 0
        set tabString {}
        set charsPerInch 14.
        set numTabs [llength $tabList]
        foreach arg $tabList {
    	if {[string match +* $arg]} {
    	    set relative 1
    	    set arg [string range $arg 1 end]
    	} else {
    	    set relative 0
    	}
    	# Always operate in relative mode for "measurement" mode
    	if {[regexp {^\\w'(.*)'u$} $arg content]} {
    	    set distance [string length $content]
    	} else {
    	    if {[scan $arg "%f%s" distance units] != 2} {
    		puts stderr "bad distance \"$arg\""
    		return 0
    	    }
    	    switch -- $units {
    		c {
    		    set distance [expr {$distance * $charsPerInch / 2.54}]
    		}
    		i {
    		    set distance [expr {$distance * $charsPerInch}]
    		}
    		default {
    		    puts stderr "bad units in distance \"$arg\""
    		    continue
    		}
    	    }
    	}
    	# ? distance
    	if {$relative} {
    	    append tabString [format "%*s1" [expr {round($distance-1)}] " "]
    	    set last [expr {$last + $distance}]
    	} else {
    	    append tabString [format "%*s1" [expr {round($distance-$last-1)}] " "]
    	    set last $distance
    	}
        }
        # puts "setTabs: --$tabString--"
    }
    
    ##############################################################################
    # lineBreak --
    #
    # Generates a line break in the HTML output.
    #
    # Arguments:
    # None.
    
    proc lineBreak {} {
        global file inPRE
        puts $file "
    " } ############################################################################## # newline -- # # This procedure is invoked to handle newlines in the troff input. It outputs # either a space character or a newline character, depending on fill mode. # # Arguments: # None. proc newline {} { global noFillCount file inDT inPRE charCnt inTable if {$inDT ne ""} { puts $file "\n$inDT" set inDT {} } elseif {$inTable} { if {$inTable > 1} { puts $file set inTable 1 } } elseif {$noFillCount == 0 || $inPRE == 1} { puts $file {} } else { lineBreak incr noFillCount -1 } set charCnt 0 } ############################################################################## # char -- # # This procedure is called to handle a special character. # # Arguments: # name - Special character named in troff \x or \(xx construct. proc char name { global file charCnt incr charCnt # puts "char: $name" switch -exact $name { \\0 { ;# \0 puts -nonewline $file " " } \\\\ { ;# \ puts -nonewline $file "\\" } \\(+- { ;# +/- puts -nonewline $file "±" } \\% {} ;# \% \\| { ;# \| } default { puts stderr "Unknown character: $name" } } } ############################################################################## # macro2 -- # # This procedure handles macros that are invoked with a leading "'" character # instead of space. Right now it just generates an error diagnostic. # # Arguments: # name - The name of the macro (without the "."). # args - Any additional arguments to the macro. proc macro2 {name args} { puts stderr "Unknown macro: '$name [join $args " "]" } ############################################################################## # SHmacro -- # # Subsection head; handles the .SH and .SS macros. # # Arguments: # name - Section name. # style - Type of section (optional) proc SHmacro {argList {style section}} { global file noFillCount textState charCnt set args [join $argList " "] if {[llength $argList] < 1} { puts stderr "Bad .SH macro: .$name $args" } set noFillCount 0 nest reset set tag H3 if {$style eq "subsection"} { set tag H4 } puts -nonewline $file "<$tag>" text $args puts $file "" # ? args textState # control what the text proc does with text switch $args { NAME {set textState NAME} DESCRIPTION {set textState INSERT} INTRODUCTION {set textState INSERT} "WIDGET-SPECIFIC OPTIONS" {set textState INSERT} "SEE ALSO" {set textState SEE} KEYWORDS {set textState 0} } set charCnt 0 } ############################################################################## # IPmacro -- # # This procedure is invoked to handle ".IP" macros, which may take any of the # following forms: # # .IP [1] Translate to a "1Step" paragraph. # .IP [x] (x > 1) Translate to a "Step" paragraph. # .IP Translate to a "Bullet" paragraph. # .IP \(bu Translate to a "Bullet" paragraph. # .IP text count Translate to a FirstBody paragraph with # special indent and tab stop based on "count", # and tab after "text". # # Arguments: # argList - List of arguments to the .IP macro. # # HTML limitations: 'count' in '.IP text count' is ignored. proc IPmacro argList { global file setTabs 0.5i set length [llength $argList] if {$length == 0} { nest para UL LI return } # Special case for alternative mechanism for declaring bullets if {[lindex $argList 0] eq "\\(bu"} { nest para UL LI return } if {[regexp {^\[\d+\]$} [lindex $argList 0]]} { nest para OL LI return } nest para DL DT formattedText [lindex $argList 0] puts $file "\n
    " return } ############################################################################## # TPmacro -- # # This procedure is invoked to handle ".TP" macros, which may take any of the # following forms: # # .TP x Translate to an indented paragraph with the specified indent # (in 100 twip units). # .TP Translate to an indented paragraph with default indent. # # Arguments: # argList - List of arguments to the .IP macro. # # HTML limitations: 'x' in '.TP x' is ignored. proc TPmacro {argList} { global inDT nest para DL DT set inDT "\n
    " ;# next newline writes inDT setTabs 0.5i } ############################################################################## # THmacro -- # # This procedure handles the .TH macro. It generates the non-scrolling header # section for a given man page, and enters information into the table of # contents. The .TH macro has the following form: # # .TH name section date footer header # # Arguments: # argList - List of arguments to the .TH macro. proc THmacro {argList} { global file if {[llength $argList] != 5} { set args [join $argList " "] puts stderr "Bad .TH macro: .$name $args" } set name [lindex $argList 0] ;# Tcl_UpVar set page [lindex $argList 1] ;# 3 set vers [lindex $argList 2] ;# 7.4 set lib [lindex $argList 3] ;# Tcl set pname [lindex $argList 4] ;# {Tcl Library Procedures} puts -nonewline $file "" text "$lib - $name ($page)" puts $file "\n" puts -nonewline $file "

    " text $pname puts $file "

    \n" } ############################################################################## # newPara -- # # This procedure sets the left and hanging indents for a line. Indents are # specified in units of inches or centimeters, and are relative to the current # nesting level and left margin. # # Arguments: # None proc newPara {} { global file nestStk if {[lindex $nestStk end] ne "NEW"} { nest decr } puts -nonewline $file "

    " } ############################################################################## # nest -- # # This procedure takes care of inserting the tags associated with the IP, TP, # RS, RE, LP and PP macros. Only 'nest para' takes arguments. # # Arguments: # op - operation: para, incr, decr, reset, init # listStart - begin list tag: OL, UL, DL. # listItem - item tag: LI, LI, DT. proc nest {op {listStart "NEW"} {listItem ""} } { global file nestStk inDT charCnt # puts "nest: $op $listStart $listItem" switch $op { para { set top [lindex $nestStk end] if {$top eq "NEW"} { set nestStk [lreplace $nestStk end end $listStart] puts $file "<$listStart>" } elseif {$top ne $listStart} { puts stderr "nest para: bad stack" exit 1 } puts $file "\n<$listItem>" set charCnt 0 } incr { lappend nestStk NEW } decr { if {[llength $nestStk] == 0} { puts stderr "nest error: nest length is zero" set nestStk NEW } set tag [lindex $nestStk end] if {$tag ne "NEW"} { puts $file "" } set nestStk [lreplace $nestStk end end] } reset { while {[llength $nestStk] > 0} { nest decr } set nestStk NEW } init { set nestStk NEW set inDT {} } } set charCnt 0 } ############################################################################## # do -- # # This is the toplevel procedure that translates a man page to HTML. It runs # the man2tcl program to turn the man page into a script, then it evals that # script. # # Arguments: # fileName - Name of the file to translate. proc do fileName { global file self html_dir package footer set self "[file tail $fileName].html" set file [open "$html_dir/$package/$self" w] puts " Pass 2 -- $fileName" flush stdout initGlobals if {[catch { eval [exec man2tcl [glob $fileName]] } msg]} { global errorInfo puts stderr $msg puts "in" puts stderr $errorInfo exit 1 } nest reset puts $file $footer puts $file "" close $file } tcl8.6.5/tools/genStubs.tcl0000644000175000017500000007066712663660066015246 0ustar sergeisergei# genStubs.tcl -- # # This script generates a set of stub files for a given # interface. # # # Copyright (c) 1998-1999 by Scriptics Corporation. # Copyright (c) 2007 Daniel A. Steffen # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. package require Tcl 8.4 namespace eval genStubs { # libraryName -- # # The name of the entire library. This value is used to compute # the USE_*_STUBS macro and the name of the init file. variable libraryName "UNKNOWN" # interfaces -- # # An array indexed by interface name that is used to maintain # the set of valid interfaces. The value is empty. array set interfaces {} # curName -- # # The name of the interface currently being defined. variable curName "UNKNOWN" # scspec -- # # Storage class specifier for external function declarations. # Normally "EXTERN", may be set to something like XYZAPI # variable scspec "EXTERN" # epoch, revision -- # # The epoch and revision numbers of the interface currently being defined. # (@@@TODO: should be an array mapping interface names -> numbers) # variable epoch {} variable revision 0 # hooks -- # # An array indexed by interface name that contains the set of # subinterfaces that should be defined for a given interface. array set hooks {} # stubs -- # # This three dimensional array is indexed first by interface name, # second by platform name, and third by a numeric offset or the # constant "lastNum". The lastNum entry contains the largest # numeric offset used for a given interface/platform combo. Each # numeric offset contains the C function specification that # should be used for the given entry in the stub table. The spec # consists of a list in the form returned by parseDecl. array set stubs {} # outDir -- # # The directory where the generated files should be placed. variable outDir . } # genStubs::library -- # # This function is used in the declarations file to set the name # of the library that the interfaces are associated with (e.g. "tcl"). # This value will be used to define the inline conditional macro. # # Arguments: # name The library name. # # Results: # None. proc genStubs::library {name} { variable libraryName $name } # genStubs::interface -- # # This function is used in the declarations file to set the name # of the interface currently being defined. # # Arguments: # name The name of the interface. # # Results: # None. proc genStubs::interface {name} { variable curName $name variable interfaces set interfaces($name) {} return } # genStubs::scspec -- # # Define the storage class macro used for external function declarations. # Typically, this will be a macro like XYZAPI or EXTERN that # expands to either DLLIMPORT or DLLEXPORT, depending on whether # -DBUILD_XYZ has been set. # proc genStubs::scspec {value} { variable scspec $value } # genStubs::epoch -- # # Define the epoch number for this library. The epoch # should be incrememented when a release is made that # contains incompatible changes to the public API. # proc genStubs::epoch {value} { variable epoch $value } # genStubs::hooks -- # # This function defines the subinterface hooks for the current # interface. # # Arguments: # names The ordered list of interfaces that are reachable through the # hook vector. # # Results: # None. proc genStubs::hooks {names} { variable curName variable hooks set hooks($curName) $names return } # genStubs::declare -- # # This function is used in the declarations file to declare a new # interface entry. # # Arguments: # index The index number of the interface. # platform The platform the interface belongs to. Should be one # of generic, win, unix, or macosx or aqua or x11. # decl The C function declaration, or {} for an undefined # entry. # # Results: # None. proc genStubs::declare {args} { variable stubs variable curName variable revision incr revision if {[llength $args] == 2} { lassign $args index decl set platformList generic } elseif {[llength $args] == 3} { lassign $args index platformList decl } else { puts stderr "wrong # args: declare $args" return } # Check for duplicate declarations, then add the declaration and # bump the lastNum counter if necessary. foreach platform $platformList { if {[info exists stubs($curName,$platform,$index)]} { puts stderr "Duplicate entry: declare $args" } } regsub -all "\[ \t\n\]+" [string trim $decl] " " decl set decl [parseDecl $decl] foreach platform $platformList { if {$decl ne ""} { set stubs($curName,$platform,$index) $decl if {![info exists stubs($curName,$platform,lastNum)] \ || ($index > $stubs($curName,$platform,lastNum))} { set stubs($curName,$platform,lastNum) $index } } } return } # genStubs::export -- # # This function is used in the declarations file to declare a symbol # that is exported from the library but is not in the stubs table. # # Arguments: # decl The C function declaration, or {} for an undefined # entry. # # Results: # None. proc genStubs::export {args} { if {[llength $args] != 1} { puts stderr "wrong # args: export $args" } return } # genStubs::rewriteFile -- # # This function replaces the machine generated portion of the # specified file with new contents. It looks for the !BEGIN! and # !END! comments to determine where to place the new text. # # Arguments: # file The name of the file to modify. # text The new text to place in the file. # # Results: # None. proc genStubs::rewriteFile {file text} { if {![file exists $file]} { puts stderr "Cannot find file: $file" return } set in [open ${file} r] set out [open ${file}.new w] fconfigure $out -translation lf while {![eof $in]} { set line [gets $in] if {[string match "*!BEGIN!*" $line]} { break } puts $out $line } puts $out "/* !BEGIN!: Do not edit below this line. */" puts $out $text while {![eof $in]} { set line [gets $in] if {[string match "*!END!*" $line]} { break } } puts $out "/* !END!: Do not edit above this line. */" puts -nonewline $out [read $in] close $in close $out file rename -force ${file}.new ${file} return } # genStubs::addPlatformGuard -- # # Wrap a string inside a platform #ifdef. # # Arguments: # plat Platform to test. # # Results: # Returns the original text inside an appropriate #ifdef. proc genStubs::addPlatformGuard {plat iftxt {eltxt {}} {withCygwin 0}} { set text "" switch $plat { win { append text "#if defined(_WIN32)" if {$withCygwin} { append text " || defined(__CYGWIN__)" } append text " /* WIN */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* WIN */\n${eltxt}" } append text "#endif /* WIN */\n" } unix { append text "#if !defined(_WIN32)" if {$withCygwin} { append text " && !defined(__CYGWIN__)" } append text " && !defined(MAC_OSX_TCL)\ /* UNIX */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* UNIX */\n${eltxt}" } append text "#endif /* UNIX */\n" } macosx { append text "#ifdef MAC_OSX_TCL /* MACOSX */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* MACOSX */\n${eltxt}" } append text "#endif /* MACOSX */\n" } aqua { append text "#ifdef MAC_OSX_TK /* AQUA */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* AQUA */\n${eltxt}" } append text "#endif /* AQUA */\n" } x11 { append text "#if !(defined(_WIN32)" if {$withCygwin} { append text " || defined(__CYGWIN__)" } append text " || defined(MAC_OSX_TK))\ /* X11 */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* X11 */\n${eltxt}" } append text "#endif /* X11 */\n" } default { append text "${iftxt}${eltxt}" } } return $text } # genStubs::emitSlots -- # # Generate the stub table slots for the given interface. If there # are no generic slots, then one table is generated for each # platform, otherwise one table is generated for all platforms. # # Arguments: # name The name of the interface being emitted. # textVar The variable to use for output. # # Results: # None. proc genStubs::emitSlots {name textVar} { upvar $textVar text forAllStubs $name makeSlot 1 text {" void (*reserved$i)(void);\n"} return } # genStubs::parseDecl -- # # Parse a C function declaration into its component parts. # # Arguments: # decl The function declaration. # # Results: # Returns a list of the form {returnType name args}. The args # element consists of a list of type/name pairs, or a single # element "void". If the function declaration is malformed # then an error is displayed and the return value is {}. proc genStubs::parseDecl {decl} { if {![regexp {^(.*)\((.*)\)$} $decl all prefix args]} { set prefix $decl set args {} } set prefix [string trim $prefix] if {![regexp {^(.+[ ][*]*)([^ *]+)$} $prefix all rtype fname]} { puts stderr "Bad return type: $decl" return } set rtype [string trim $rtype] if {$args eq ""} { return [list $rtype $fname {}] } foreach arg [split $args ,] { lappend argList [string trim $arg] } if {![string compare [lindex $argList end] "..."]} { set args TCL_VARARGS foreach arg [lrange $argList 0 end-1] { set argInfo [parseArg $arg] if {[llength $argInfo] == 2 || [llength $argInfo] == 3} { lappend args $argInfo } else { puts stderr "Bad argument: '$arg' in '$decl'" return } } } else { set args {} foreach arg $argList { set argInfo [parseArg $arg] if {![string compare $argInfo "void"]} { lappend args "void" break } elseif {[llength $argInfo] == 2 || [llength $argInfo] == 3} { lappend args $argInfo } else { puts stderr "Bad argument: '$arg' in '$decl'" return } } } return [list $rtype $fname $args] } # genStubs::parseArg -- # # This function parses a function argument into a type and name. # # Arguments: # arg The argument to parse. # # Results: # Returns a list of type and name with an optional third array # indicator. If the argument is malformed, returns "". proc genStubs::parseArg {arg} { if {![regexp {^(.+[ ][*]*)([^][ *]+)(\[\])?$} $arg all type name array]} { if {$arg eq "void"} { return $arg } else { return } } set result [list [string trim $type] $name] if {$array ne ""} { lappend result $array } return $result } # genStubs::makeDecl -- # # Generate the prototype for a function. # # Arguments: # name The interface name. # decl The function declaration. # index The slot index for this function. # # Results: # Returns the formatted declaration string. proc genStubs::makeDecl {name decl index} { variable scspec lassign $decl rtype fname args append text "/* $index */\n" set line "$scspec $rtype" set count [expr {2 - ([string length $line] / 8)}] append line [string range "\t\t\t" 0 $count] set pad [expr {24 - [string length $line]}] if {$pad <= 0} { append line " " set pad 0 } if {$args eq ""} { append line $fname append text $line append text ";\n" return $text } append line $fname set arg1 [lindex $args 0] switch -exact $arg1 { void { append line "(void)" } TCL_VARARGS { set sep "(" foreach arg [lrange $args 1 end] { append line $sep set next {} append next [lindex $arg 0] if {[string index $next end] ne "*"} { append next " " } append next [lindex $arg 1] [lindex $arg 2] if {[string length $line] + [string length $next] \ + $pad > 76} { append text [string trimright $line] \n set line "\t\t\t\t" set pad 28 } append line $next set sep ", " } append line ", ...)" if {[lindex $args end] eq "{const char *} format"} { append line " TCL_FORMAT_PRINTF(" [expr [llength $args] - 1] ", " [llength $args] ")" } } default { set sep "(" foreach arg $args { append line $sep set next {} append next [lindex $arg 0] if {[string index $next end] ne "*"} { append next " " } append next [lindex $arg 1] [lindex $arg 2] if {[string length $line] + [string length $next] \ + $pad > 76} { append text [string trimright $line] \n set line "\t\t\t\t" set pad 28 } append line $next set sep ", " } append line ")" } } return "$text$line;\n" } # genStubs::makeMacro -- # # Generate the inline macro for a function. # # Arguments: # name The interface name. # decl The function declaration. # index The slot index for this function. # # Results: # Returns the formatted macro definition. proc genStubs::makeMacro {name decl index} { lassign $decl rtype fname args set lfname [string tolower [string index $fname 0]] append lfname [string range $fname 1 end] set text "#define $fname \\\n\t(" if {$args eq ""} { append text "*" } append text "${name}StubsPtr->$lfname)" append text " /* $index */\n" return $text } # genStubs::makeSlot -- # # Generate the stub table entry for a function. # # Arguments: # name The interface name. # decl The function declaration. # index The slot index for this function. # # Results: # Returns the formatted table entry. proc genStubs::makeSlot {name decl index} { lassign $decl rtype fname args set lfname [string tolower [string index $fname 0]] append lfname [string range $fname 1 end] set text " " if {$args eq ""} { append text $rtype " *" $lfname "; /* $index */\n" return $text } if {[string range $rtype end-8 end] eq "__stdcall"} { append text [string trim [string range $rtype 0 end-9]] " (__stdcall *" $lfname ") " } elseif {[string range $rtype 0 11] eq "TCL_NORETURN"} { append text "TCL_NORETURN1 " [string trim [string range $rtype 12 end]] " (*" $lfname ") " } else { append text $rtype " (*" $lfname ") " } set arg1 [lindex $args 0] switch -exact $arg1 { void { append text "(void)" } TCL_VARARGS { set sep "(" foreach arg [lrange $args 1 end] { append text $sep [lindex $arg 0] if {[string index $text end] ne "*"} { append text " " } append text [lindex $arg 1] [lindex $arg 2] set sep ", " } append text ", ...)" if {[lindex $args end] eq "{const char *} format"} { append text " TCL_FORMAT_PRINTF(" [expr [llength $args] - 1] ", " [llength $args] ")" } } default { set sep "(" foreach arg $args { append text $sep [lindex $arg 0] if {[string index $text end] ne "*"} { append text " " } append text [lindex $arg 1] [lindex $arg 2] set sep ", " } append text ")" } } append text "; /* $index */\n" return $text } # genStubs::makeInit -- # # Generate the prototype for a function. # # Arguments: # name The interface name. # decl The function declaration. # index The slot index for this function. # # Results: # Returns the formatted declaration string. proc genStubs::makeInit {name decl index} { if {[lindex $decl 2] eq ""} { append text " &" [lindex $decl 1] ", /* " $index " */\n" } else { append text " " [lindex $decl 1] ", /* " $index " */\n" } return $text } # genStubs::forAllStubs -- # # This function iterates over all of the platforms and invokes # a callback for each slot. The result of the callback is then # placed inside appropriate platform guards. # # Arguments: # name The interface name. # slotProc The proc to invoke to handle the slot. It will # have the interface name, the declaration, and # the index appended. # onAll If 1, emit the skip string even if there are # definitions for one or more platforms. # textVar The variable to use for output. # skipString The string to emit if a slot is skipped. This # string will be subst'ed in the loop so "$i" can # be used to substitute the index value. # # Results: # None. proc genStubs::forAllStubs {name slotProc onAll textVar {skipString {"/* Slot $i is reserved */\n"}}} { variable stubs upvar $textVar text set plats [array names stubs $name,*,lastNum] if {[info exists stubs($name,generic,lastNum)]} { # Emit integrated stubs block set lastNum -1 foreach plat [array names stubs $name,*,lastNum] { if {$stubs($plat) > $lastNum} { set lastNum $stubs($plat) } } for {set i 0} {$i <= $lastNum} {incr i} { set slots [array names stubs $name,*,$i] set emit 0 if {[info exists stubs($name,generic,$i)]} { if {[llength $slots] > 1} { puts stderr "conflicting generic and platform entries:\ $name $i" } append text [$slotProc $name $stubs($name,generic,$i) $i] set emit 1 } elseif {[llength $slots] > 0} { array set slot {unix 0 x11 0 win 0 macosx 0 aqua 0} foreach s $slots { set slot([lindex [split $s ,] 1]) 1 } # "aqua", "macosx" and "x11" are special cases: # "macosx" implies "unix", "aqua" implies "macosx" and "x11" # implies "unix", so we need to be careful not to emit # duplicate stubs entries: if {($slot(unix) && $slot(macosx)) || ( ($slot(unix) || $slot(macosx)) && ($slot(x11) || $slot(aqua)))} { puts stderr "conflicting platform entries: $name $i" } ## unix ## set temp {} set plat unix if {!$slot(aqua) && !$slot(x11)} { if {$slot($plat)} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } elseif {$onAll} { eval {append temp} $skipString } } if {$temp ne ""} { append text [addPlatformGuard $plat $temp] set emit 1 } ## x11 ## set temp {} set plat x11 if {!$slot(unix) && !$slot(macosx)} { if {$slot($plat)} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } elseif {$onAll} { eval {append temp} $skipString } } if {$temp ne ""} { append text [addPlatformGuard $plat $temp] set emit 1 } ## win ## set temp {} set plat win if {$slot($plat)} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } elseif {$onAll} { eval {append temp} $skipString } if {$temp ne ""} { append text [addPlatformGuard $plat $temp] set emit 1 } ## macosx ## set temp {} set plat macosx if {!$slot(aqua) && !$slot(x11)} { if {$slot($plat)} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } elseif {$slot(unix)} { append temp [$slotProc $name $stubs($name,unix,$i) $i] } elseif {$onAll} { eval {append temp} $skipString } } if {$temp ne ""} { append text [addPlatformGuard $plat $temp] set emit 1 } ## aqua ## set temp {} set plat aqua if {!$slot(unix) && !$slot(macosx)} { if {[string range $skipString 1 2] ne "/*"} { # genStubs.tcl previously had a bug here causing it to # erroneously generate both a unix entry and an aqua # entry for a given stubs table slot. To preserve # backwards compatibility, generate a dummy stubs entry # before every aqua entry (note that this breaks the # correspondence between emitted entry number and # actual position of the entry in the stubs table, e.g. # TkIntStubs entry 113 for aqua is in fact at position # 114 in the table, entry 114 at position 116 etc). eval {append temp} $skipString set temp "[string range $temp 0 end-1] /*\ Dummy entry for stubs table backwards\ compatibility */\n" } if {$slot($plat)} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } elseif {$onAll} { eval {append temp} $skipString } } if {$temp ne ""} { append text [addPlatformGuard $plat $temp] set emit 1 } } if {!$emit} { eval {append text} $skipString } } } else { # Emit separate stubs blocks per platform array set block {unix 0 x11 0 win 0 macosx 0 aqua 0} foreach s [array names stubs $name,*,lastNum] { set block([lindex [split $s ,] 1]) 1 } ## unix ## if {$block(unix) && !$block(x11)} { set temp {} set plat unix set lastNum $stubs($name,$plat,lastNum) for {set i 0} {$i <= $lastNum} {incr i} { if {[info exists stubs($name,$plat,$i)]} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } else { eval {append temp} $skipString } } append text [addPlatformGuard $plat $temp {} true] } ## win ## if {$block(win)} { set temp {} set plat win set lastNum $stubs($name,$plat,lastNum) for {set i 0} {$i <= $lastNum} {incr i} { if {[info exists stubs($name,$plat,$i)]} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } else { eval {append temp} $skipString } } append text [addPlatformGuard $plat $temp {} true] } ## macosx ## if {($block(unix) || $block(macosx)) && !$block(aqua) && !$block(x11)} { set temp {} set lastNum -1 foreach plat {unix macosx} { if {$block($plat)} { set lastNum [expr {$lastNum > $stubs($name,$plat,lastNum) ? $lastNum : $stubs($name,$plat,lastNum)}] } } for {set i 0} {$i <= $lastNum} {incr i} { set emit 0 foreach plat {unix macosx} { if {[info exists stubs($name,$plat,$i)]} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] set emit 1 break } } if {!$emit} { eval {append temp} $skipString } } append text [addPlatformGuard macosx $temp] } ## aqua ## if {$block(aqua)} { set temp {} set lastNum -1 foreach plat {unix macosx aqua} { if {$block($plat)} { set lastNum [expr {$lastNum > $stubs($name,$plat,lastNum) ? $lastNum : $stubs($name,$plat,lastNum)}] } } for {set i 0} {$i <= $lastNum} {incr i} { set emit 0 foreach plat {unix macosx aqua} { if {[info exists stubs($name,$plat,$i)]} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] set emit 1 break } } if {!$emit} { eval {append temp} $skipString } } append text [addPlatformGuard aqua $temp] } ## x11 ## if {$block(x11)} { set temp {} set lastNum -1 foreach plat {unix macosx x11} { if {$block($plat)} { set lastNum [expr {$lastNum > $stubs($name,$plat,lastNum) ? $lastNum : $stubs($name,$plat,lastNum)}] } } for {set i 0} {$i <= $lastNum} {incr i} { set emit 0 foreach plat {unix macosx x11} { if {[info exists stubs($name,$plat,$i)]} { if {$plat ne "macosx"} { append temp [$slotProc $name \ $stubs($name,$plat,$i) $i] } else { eval {set etxt} $skipString append temp [addPlatformGuard $plat [$slotProc \ $name $stubs($name,$plat,$i) $i] $etxt true] } set emit 1 break } } if {!$emit} { eval {append temp} $skipString } } append text [addPlatformGuard x11 $temp {} true] } } } # genStubs::emitDeclarations -- # # This function emits the function declarations for this interface. # # Arguments: # name The interface name. # textVar The variable to use for output. # # Results: # None. proc genStubs::emitDeclarations {name textVar} { upvar $textVar text append text "\n/*\n * Exported function declarations:\n */\n\n" forAllStubs $name makeDecl 0 text return } # genStubs::emitMacros -- # # This function emits the inline macros for an interface. # # Arguments: # name The name of the interface being emitted. # textVar The variable to use for output. # # Results: # None. proc genStubs::emitMacros {name textVar} { variable libraryName upvar $textVar text set upName [string toupper $libraryName] append text "\n#if defined(USE_${upName}_STUBS)\n" append text "\n/*\n * Inline function declarations:\n */\n\n" forAllStubs $name makeMacro 0 text append text "\n#endif /* defined(USE_${upName}_STUBS) */\n" return } # genStubs::emitHeader -- # # This function emits the body of the Decls.h file for # the specified interface. # # Arguments: # name The name of the interface being emitted. # # Results: # None. proc genStubs::emitHeader {name} { variable outDir variable hooks variable epoch variable revision set capName [string toupper [string index $name 0]] append capName [string range $name 1 end] if {$epoch ne ""} { set CAPName [string toupper $name] append text "\n" append text "#define ${CAPName}_STUBS_EPOCH $epoch\n" append text "#define ${CAPName}_STUBS_REVISION $revision\n" } append text "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n" emitDeclarations $name text if {[info exists hooks($name)]} { append text "\ntypedef struct {\n" foreach hook $hooks($name) { set capHook [string toupper [string index $hook 0]] append capHook [string range $hook 1 end] append text " const struct ${capHook}Stubs *${hook}Stubs;\n" } append text "} ${capName}StubHooks;\n" } append text "\ntypedef struct ${capName}Stubs {\n" append text " int magic;\n" if {$epoch ne ""} { append text " int epoch;\n" append text " int revision;\n" } if {[info exists hooks($name)]} { append text " const ${capName}StubHooks *hooks;\n\n" } else { append text " void *hooks;\n\n" } emitSlots $name text append text "} ${capName}Stubs;\n\n" append text "extern const ${capName}Stubs *${name}StubsPtr;\n\n" append text "#ifdef __cplusplus\n}\n#endif\n" emitMacros $name text rewriteFile [file join $outDir ${name}Decls.h] $text return } # genStubs::emitInit -- # # Generate the table initializers for an interface. # # Arguments: # name The name of the interface to initialize. # textVar The variable to use for output. # # Results: # Returns the formatted output. proc genStubs::emitInit {name textVar} { variable hooks variable interfaces variable epoch upvar $textVar text set root 1 set capName [string toupper [string index $name 0]] append capName [string range $name 1 end] if {[info exists hooks($name)]} { append text "\nstatic const ${capName}StubHooks ${name}StubHooks = \{\n" set sep " " foreach sub $hooks($name) { append text $sep "&${sub}Stubs" set sep ",\n " } append text "\n\};\n" } foreach intf [array names interfaces] { if {[info exists hooks($intf)]} { if {[lsearch -exact $hooks($intf) $name] >= 0} { set root 0 break } } } append text "\n" if {!$root} { append text "static " } append text "const ${capName}Stubs ${name}Stubs = \{\n TCL_STUB_MAGIC,\n" if {$epoch ne ""} { set CAPName [string toupper $name] append text " ${CAPName}_STUBS_EPOCH,\n" append text " ${CAPName}_STUBS_REVISION,\n" } if {[info exists hooks($name)]} { append text " &${name}StubHooks,\n" } else { append text " 0,\n" } forAllStubs $name makeInit 1 text {" 0, /* $i */\n"} append text "\};\n" return } # genStubs::emitInits -- # # This function emits the body of the StubInit.c file for # the specified interface. # # Arguments: # name The name of the interface being emitted. # # Results: # None. proc genStubs::emitInits {} { variable hooks variable outDir variable libraryName variable interfaces # Assuming that dependencies only go one level deep, we need to emit # all of the leaves first to avoid needing forward declarations. set leaves {} set roots {} foreach name [lsort [array names interfaces]] { if {[info exists hooks($name)]} { lappend roots $name } else { lappend leaves $name } } foreach name $leaves { emitInit $name text } foreach name $roots { emitInit $name text } rewriteFile [file join $outDir ${libraryName}StubInit.c] $text } # genStubs::init -- # # This is the main entry point. # # Arguments: # None. # # Results: # None. proc genStubs::init {} { global argv argv0 variable outDir variable interfaces if {[llength $argv] < 2} { puts stderr "usage: $argv0 outDir declFile ?declFile...?" exit 1 } set outDir [lindex $argv 0] foreach file [lrange $argv 1 end] { source $file } foreach name [lsort [array names interfaces]] { puts "Emitting $name" emitHeader $name } emitInits } # lassign -- # # This function emulates the TclX lassign command. # # Arguments: # valueList A list containing the values to be assigned. # args The list of variables to be assigned. # # Results: # Returns any values that were not assigned to variables. if {[string length [namespace which lassign]] == 0} { proc lassign {valueList args} { if {[llength $args] == 0} { error "wrong # args: should be \"lassign list varName ?varName ...?\"" } uplevel [list foreach $args $valueList {break}] return [lrange $valueList [llength $args] end] } } genStubs::init tcl8.6.5/tools/configure0000755000175000017500000020227712663653210014642 0ustar sergeisergei#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59. # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="man2tcl.c" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS TCL_WIN_VERSION CC TCL_VERSION TCL_PATCH_LEVEL TCL_SRC_DIR TCL_BIN_DIR LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-tcl=DIR use Tcl $DEF_VER binaries from DIR _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Recover information that Tcl computed with its configure script. #-------------------------------------------------------------------- # See if there was a command-line option for where Tcl is; if # not, assume that its top-level directory is a sibling of ours. #-------------------------------------------------------------------- DEF_VER=8.6 # Check whether --with-tcl or --without-tcl was given. if test "${with_tcl+set}" = set; then withval="$with_tcl" TCL_BIN_DIR=$withval else TCL_BIN_DIR=`cd ../../tcl$DEF_VER$TCL_PATCH_LEVEL/unix; pwd` fi; if test ! -d $TCL_BIN_DIR; then { { echo "$as_me:$LINENO: error: Tcl directory $TCL_BIN_DIR doesn't exist" >&5 echo "$as_me: error: Tcl directory $TCL_BIN_DIR doesn't exist" >&2;} { (exit 1); exit 1; }; } fi if test ! -f $TCL_BIN_DIR/tclConfig.sh; then { { echo "$as_me:$LINENO: error: There's no tclConfig.sh in $TCL_BIN_DIR; perhaps you didn't specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?" >&5 echo "$as_me: error: There's no tclConfig.sh in $TCL_BIN_DIR; perhaps you didn't specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?" >&2;} { (exit 1); exit 1; }; } fi . $TCL_BIN_DIR/tclConfig.sh TCL_WIN_VERSION=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION CC=$TCL_CC ac_config_files="$ac_config_files Makefile tcl.hpj" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then we branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. cat >confdef2opt.sed <<\_ACEOF t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g t quote s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g t quote d : quote s,[ `~#$^&*(){}\\|;'"<>?],\\&,g s,\[,\\&,g s,\],\\&,g s,\$,$$,g p _ACEOF # We use echo to avoid assuming a particular line-breaking character. # The extra dot is to prevent the shell from consuming trailing # line-breaks from the sub-command output. A line-break within # single-quotes doesn't work because, if this script is created in a # platform that uses two characters for line-breaks (e.g., DOS), tr # would break. ac_LF_and_DOT=`echo; echo .` DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` rm -f confdef2opt.sed ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by $as_me, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "tcl.hpj" ) CONFIG_FILES="$CONFIG_FILES tcl.hpj" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@TCL_WIN_VERSION@,$TCL_WIN_VERSION,;t t s,@CC@,$CC,;t t s,@TCL_VERSION@,$TCL_VERSION,;t t s,@TCL_PATCH_LEVEL@,$TCL_PATCH_LEVEL,;t t s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi tcl8.6.5/tools/man2html1.tcl0000644000175000017500000001240512663660066015241 0ustar sergeisergei# man2html1.tcl -- # # This file defines procedures that are used during the first pass of the # man page to html conversion process. It is sourced by h.tcl. # # Copyright (c) 1996 by Sun Microsystems, Inc. package require Tcl 8.4 # Global variables used by these scripts: # # state - state variable that controls action of text proc. # # curFile - tail of current man page. # # file - file pointer; for both xref.tcl and contents.html # # NAME_file - array indexed by NAME and containing file names used # for hyperlinks. # # KEY_file - array indexed by KEYWORD and containing file names used # for hyperlinks. # # lib - contains package name. Used to label section in contents.html # # inDT - in dictionary term. # text -- # # This procedure adds entries to the hypertext arrays NAME_file # and KEY_file. # # DT: might do this: if first word of $dt matches $name and [llength $name==1] # and [llength $dt > 1], then add to NAME_file. # # Arguments: # string - Text to index. proc text string { global state curFile NAME_file KEY_file inDT switch $state { NAME { foreach i [split $string ","] { lappend NAME_file([string trim $i]) $curFile } } KEY { foreach i [split $string ","] { lappend KEY_file([string trim $i]) $curFile } } DT - OFF - DASH {} default { puts stderr "text: unknown state: $state" } } } # macro -- # # This procedure is invoked to process macro invocations that start # with "." (instead of '). # # Arguments: # name - The name of the macro (without the "."). # args - Any additional arguments to the macro. proc macro {name args} { switch $name { SH - SS { global state switch $args { NAME { if {$state eq "INIT"} { set state NAME } } DESCRIPTION {set state DT} INTRODUCTION {set state DT} KEYWORDS {set state KEY} default {set state OFF} } } TP { global inDT set inDT 1 } TH { global lib state inDT set inDT 0 set state INIT if {[llength $args] != 5} { set args [join $args " "] puts stderr "Bad .TH macro: .$name $args" } set lib [lindex $args 3] ;# Tcl or Tk } } } # dash -- # # This procedure is invoked to handle dash characters ("\-" in # troff). It only function in pass1 is to terminate the NAME state. # # Arguments: # None. proc dash {} { global state if {$state eq "NAME"} { set state DASH } } # newline -- # # This procedure is invoked to handle newlines in the troff input. # It's only purpose is to terminate a DT (dictionary term). # # Arguments: # None. proc newline {} { global inDT set inDT 0 } # initGlobals, tab, font, char, macro2 -- # # These procedures do nothing during the first pass. # # Arguments: # None. proc initGlobals {} {} proc tab {} {} proc font type {} proc char name {} proc macro2 {name args} {} # doListing -- # # Writes an ls like list to a file. Searches NAME_file for entries # that match the input pattern. # # Arguments: # file - Output file pointer. # pattern - glob style match pattern proc doListing {file pattern} { global NAME_file set max_len 0 foreach name [lsort [array names NAME_file]] { set ref $NAME_file($name) if [string match $pattern $ref] { lappend type $name if {[string length $name] > $max_len} { set max_len [string length $name] } } } if [catch {llength $type} ] { puts stderr " doListing: no names matched pattern ($pattern)" return } incr max_len set ncols [expr {90/$max_len}] set nrows [expr {int(ceil([llength $type] / double($ncols)))} ] # ? max_len ncols nrows set index 0 foreach f $type { lappend row([expr {$index % $nrows}]) $f incr index } puts -nonewline $file "

    "
        for {set i 0} {$i<$nrows} {incr i} {
    	foreach name $row($i) {
    	    set str [format "%-*s" $max_len $name]
    	    regsub $name $str "$name" str
    	    puts -nonewline $file $str
    	}
    	puts $file {}
        }
        puts $file "
    " } # doContents -- # # Generates a HTML contents file using the NAME_file array # as its input database. # # Arguments: # file - name of the contents file. # packageName - string used in the title and sub-heads of the HTML # page. Normally name of the package without version # numbers. proc doContents {file packageName} { global footer set file [open $file w] puts $file "$packageName Manual" puts $file "

    $packageName

    " doListing $file "*.1" puts $file "

    $packageName Commands

    " doListing $file "*.n" puts $file "

    $packageName Library

    " doListing $file "*.3" puts $file $footer puts $file "" close $file } # do -- # # This is the toplevel procedure that searches a man page # for hypertext links. It builds a data base consisting of # two arrays: NAME_file and KEY file. It runs the man2tcl # program to turn the man page into a script, then it evals # that script. # # Arguments: # fileName - Name of the file to scan. proc do fileName { global curFile set curFile [file tail $fileName] set file stdout puts " Pass 1 -- $fileName" flush stdout if [catch {eval [exec man2tcl [glob $fileName]]} msg] { global errorInfo puts stderr $msg puts "in" puts $errorInfo exit 1 } } tcl8.6.5/tools/man2html.tcl0000644000175000017500000001051112663660066015154 0ustar sergeisergei#!/bin/sh # \ exec tclsh "$0" ${1+"$@"} package require Tcl 8.4 # man2html.tcl -- # # This file contains procedures that work in conjunction with the # man2tcl program to generate a HTML files from Tcl manual entries. # # Copyright (c) 1996 by Sun Microsystems, Inc. # sarray - # # Save an array to a file so that it can be sourced. # # Arguments: # file - Name of the output file # args - Name of the arrays to save # proc sarray {file args} { set file [open $file w] foreach a $args { upvar $a array if {![array exists array]} { puts "sarray: \"$a\" isn't an array" break } foreach name [lsort [array names array]] { regsub -all " " $name "\\ " name1 puts $file "set ${a}($name1) \{$array($name)\}" } } close $file } # footer -- # # Builds footer info for HTML pages # # Arguments: # packages - List of packages to link to. proc footer {packages} { lappend f "
    " set h {[} foreach package $packages { lappend h "$package" lappend h "|" } lappend f [join [lreplace $h end end {]} ] " "] lappend f "
    " lappend f "
    Copyright © 1989-1994 The Regents of the University of California."
        lappend f "Copyright © 1994-1996 Sun Microsystems, Inc."
        lappend f "
    " return [join $f "\n"] } # doDir -- # # Given a directory as argument, translate all the man pages in # that directory. # # Arguments: # dir - Name of the directory. proc doDir dir { foreach f [lsort [glob -directory $dir "*.\[13n\]"]] { do $f ;# defined in man2html1.tcl & man2html2.tcl } } # main -- # # Main code for converting Tcl manual pages to HTML. # # Arguments: # argv - List of arguments to this script. proc main {argv} { global html_dir # Global vars used in man2html1.tcl and man2html2.tcl global NAME_file KEY_file lib state curFile file inDT textState nestStk global curFont fontStart fontEnd noFillCount footer if {[llength $argv] < 2} { puts stderr "usage: $::argv0 html_dir tcl_dir packages..." puts stderr "usage: $::argv0 -clean html_dir" exit 1 } if {[lindex $argv 0] eq "-clean"} { set html_dir [lindex $argv 1] puts -nonewline "recursively remove: $html_dir? " flush stdout if {[gets stdin] eq "y"} { puts "removing: $html_dir" file delete -force $html_dir } exit 0 } set html_dir [lindex $argv 0] set tcl_dir [lindex $argv 1] set packages [lrange $argv 2 end] set homeDir [file dirname [info script]] #### need to add glob capability to packages #### # make sure there are doc directories for each package foreach i $packages { if {![file exists $tcl_dir/$i/doc]} { puts stderr "Error: doc directory for package $i is missing" exit 1 } if {![file isdirectory $tcl_dir/$i/doc]} { puts stderr "Error: $tcl_dir/$i/doc is not a directory" exit 1 } } # we want to start with a clean sheet if {[file exists $html_dir]} { puts stderr "Error: HTML directory already exists" exit 1 } else { file mkdir $html_dir } set footer [footer $packages] # make the hyperlink arrays and contents.html for all packages foreach package $packages { file mkdir $html_dir/$package # build hyperlink database arrays: NAME_file and KEY_file # puts "\nScanning man pages in $tcl_dir/$package/doc..." uplevel \#0 [list source $homeDir/man2html1.tcl] doDir $tcl_dir/$package/doc # clean up the NAME_file and KEY_file database arrays # catch {unset KEY_file()} foreach name [lsort [array names NAME_file]] { set file_name $NAME_file($name) if {[llength $file_name] > 1} { set file_name [lsort $file_name] puts "Warning: '$name' multiply defined in: $file_name;\ using last" set NAME_file($name) [lindex $file_name end] } } # sarray $html_dir/$package/xref.tcl NAME_file KEY_file # build the contents file from NAME_file # puts "\nGenerating contents.html for $package" doContents $html_dir/$package/contents.html $lib ;# defined in man2html1.tcl # now translate the man pages to HTML pages # uplevel \#0 [list source $homeDir/man2html2.tcl] puts "\nBuilding html pages from man pages in $tcl_dir/$package/doc..." doDir $tcl_dir/$package/doc unset NAME_file } } if [catch { main $argv } result] { global errorInfo puts stderr $result puts stderr "in" puts stderr $errorInfo } tcl8.6.5/tools/feather.bmp0000644000175000017500000000406611555560474015055 0ustar sergeisergeiBM66( ÄÄ€€€€€€€€€ÀÀÀÀÜÀðʦ @ ` €   À à@@ @@@`@€@ @À@à`` `@```€` `À`à€€ €@€`€€€ €À€à    @ ` €   À àÀÀ À@À`À€À ÀÀÀààà à@à`à€à àÀàà@@ @@@`@€@ @À@à@ @ @ @@ `@ €@  @ À@ à@@@@ @@@@@`@@€@@ @@À@@à@`@` @`@@``@`€@` @`À@`à@€@€ @€@@€`@€€@€ @€À@€à@ @  @ @@ `@ €@  @ À@ à@À@À @À@@À`@À€@À @ÀÀ@Àà@à@à @à@@à`@à€@à @àÀ@àà€€ €@€`€€€ €À€à€ € € @€ `€ €€  € À€ à€@€@ €@@€@`€@€€@ €@À€@à€`€` €`@€``€`€€` €`À€`à€€€€ €€@€€`€€€€€ €€À€€à€ €  € @€ `€ €€  € À€ à€À€À €À@€À`€À€€À €ÀÀ€Àà€à€à €à@€à`€à€€à €àÀ€ààÀÀ À@À`À€À ÀÀÀàÀ À À @À `À €À  À ÀÀ àÀ@À@ À@@À@`À@€À@ À@ÀÀ@àÀ`À` À`@À``À`€À` À`ÀÀ`àÀ€À€ À€@À€`À€€À€ À€ÀÀ€àÀ À  À @À `À €À  À ÀÀ àÀÀÀÀ ÀÀ@ÀÀ`ÀÀ€ÀÀ ðûÿ¤  €€€ÿÿÿÿÿÿÿÿÿÿÿÿûû¤ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû¤ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû¤ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû¤ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû¤ûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû¤¤ûûûûûûûûûûûûû¤û¤ÐÀÀÀûûûûûûûûû¤¤ûûûûûûûûûûûû¤û¤ÀÀÀÀÀÀûûûûûûûûûû¤ûûûûûûûûûûûü¤ûÐÀÀÀÀÀÀûûûûûûûûû¤ûûûûûûûûûûÀü÷ÐÀÀÀÀÀÀÀûûûû¤¤ûûûûûûûûûûûûûÀüü÷ÀÀÀÀÀÀÀÀûûûûû¤ûûûûûûûûûûûûûÀüü¤ÀÀÀÀÀÀÀÀûûûûû¤ûûûûûûûûûûûûÀüüüÐÀÀÀÀÀÀÀÀûûûûû¤ûûûûûûûûûûûÀüüüüÐÀÀÀÀÀÀÀÀûûûûûûûûûûûûûûûûûÀüüüüÐÀÀÀÀÀÀÀûûûûûûûûûûûûûûûûûÀüüüüüÐÀÀÀÀÀÀûûûûûûûûûûûûûûûûûûÀüüüüü÷ÀÀÀÀÀÀûûûûûûûûûûûûûûûûûÀüüüüü÷ÀÀÀÀÀÀÀûûûûûûûûûûûûûûûûÀüüüüÐü÷ÀÀÀÀÀÀÀûûûûûûûûûûûûûûûûÀüÐüüüü¤ÀÀÀÀÀÀÀûûûûûûûûûûûûûûûûÀüüüüÐüФÀÀÀÀÀÀûûûûûûûûûûûûûûûûÀüüÐüÐüЛÀÀÀÀÀÀûûûûûûûûûûûûûûûûÀüüÐüÐÐÐüÀÀÀÀÀÀûûûûûûûû¤ûûûûûûûûÀÐüÐüÐÐÐüÀÀÀÀÀûûûûûûû¤ûûû¤ûûûûûÀÐüÐÐÐÐÐüÀÀÀÀÀûûûûûûûû¤ûûû¤ûûûûûÀüÐÐÐÐÐÐüÀÀÀÀûûûûûûû¤ûûûû¤ûûûûûÀÀüÐÐÐÐÐüÀÀÀÀûûûûûûûû¤ûûûû¤ûûûûûûÀüÐÐÐÐÐüÀÀÀûûûûûûûû¤ûûûû¤¤ûûûûûÀÀüÐÐÐÐüÀÀÀûûûûûûûûû¤ûûûûû¤¤ûûûûûÀÀüÐÐÐüÀÀûûûûûûûûûûûûûûûûûûûûûûûûÀÀÀüÐüÀûûûûûûûûûûûûûûûûûûûûûûûûûûûÀÀÀÀûûtcl8.6.5/tools/uniClass.tcl0000644000175000017500000000645712663660066015231 0ustar sergeisergei#!/bin/sh # The next line is executed by /bin/sh, but not tcl \ exec tclsh "$0" ${1+"$@"} # # uniClass.tcl -- # # Generates the character ranges and singletons that are used in # generic/regc_locale.c for translation of character classes. # This file must be generated using a tclsh that contains the # correct corresponding tclUniData.c file (generated by uniParse.tcl) # in order for the class ranges to match. # proc emitRange {first last} { global ranges numranges chars numchars extchars extranges if {$first < ($last-1)} { if {!$extranges && ($first) > 0xffff} { set extranges 1 set numranges 0 set ranges [string trimright $ranges " \n\r\t,"] append ranges "\n#if TCL_UTF_MAX > 4\n ," } append ranges [format "{0x%x, 0x%x}, " \ $first $last] if {[incr numranges] % 4 == 0} { set ranges [string trimright $ranges] append ranges "\n " } } else { if {!$extchars && ($first) > 0xffff} { set extchars 1 set numchars 0 set chars [string trimright $chars " \n\r\t,"] append chars "\n#if TCL_UTF_MAX > 4\n ," } append chars [format "0x%x, " $first] incr numchars if {$numchars % 9 == 0} { set chars [string trimright $chars] append chars "\n " } if {$first != $last} { append chars [format "0x%x, " $last] incr numchars if {$numchars % 9 == 0} { append chars "\n " } } } } proc genTable {type} { global first last ranges numranges chars numchars extchars extranges set first -2 set last -2 set ranges " " set numranges 0 set chars " " set numchars 0 set extchars 0 set extranges 0 for {set i 0} {$i <= 0x10ffff} {incr i} { if {$i == 0xd800} { # Skip surrogates set i 0xdc00 } if {[string is $type [format %c $i]]} { if {$i == ($last + 1)} { set last $i } else { if {$first >= 0} { emitRange $first $last } set first $i set last $i } } } emitRange $first $last set ranges [string trimright $ranges "\t\n ,"] if {$extranges} { append ranges "\n#endif" } set chars [string trimright $chars "\t\n ,"] if {$extchars} { append chars "\n#endif" } if {$ranges ne ""} { puts "static const crange ${type}RangeTable\[\] = {\n$ranges\n};\n" puts "#define NUM_[string toupper $type]_RANGE (sizeof(${type}RangeTable)/sizeof(crange))\n" } else { puts "/* no contiguous ranges of $type characters */\n" } if {$chars ne ""} { puts "static const chr ${type}CharTable\[\] = {\n$chars\n};\n" puts "#define NUM_[string toupper $type]_CHAR (sizeof(${type}CharTable)/sizeof(chr))\n" } else { puts "/*\n * no singletons of $type characters.\n */\n" } } puts "/* * Declarations of Unicode character ranges. This code * is automatically generated by the tools/uniClass.tcl script * and used in generic/regc_locale.c. Do not modify by hand. */ " foreach {type desc} { alpha "alphabetic characters" control "control characters" digit "decimal digit characters" punct "punctuation characters" space "white space characters" lower "lowercase characters" upper "uppercase characters" graph "unicode print characters excluding space" } { puts "/*\n * Unicode: $desc.\n */\n" genTable $type } puts "/* * End of auto-generated Unicode character ranges declarations. */" tcl8.6.5/tools/eolFix.tcl0000644000175000017500000000327612663653210014663 0ustar sergeisergei## Super aggressive EOL-fixer! ## ## Will even understand screwed up ones like CRCRLF. ## (found in bad CVS repositories, caused by spacey developers ## abusing CVS) ## ## davygrvy@pobox.com 3:41 PM 10/12/2001 ## package provide EOL-fix 1.1 namespace eval ::EOL { variable outMode crlf } proc EOL::fix {filename {newfilename {}}} { variable outMode if {![file exists $filename]} { return } puts "EOL Fixing: $filename" file rename ${filename} ${filename}.o set fhnd [open ${filename}.o r] if {$newfilename ne ""} { set newfhnd [open ${newfilename} w] } else { set newfhnd [open ${filename} w] } fconfigure $newfhnd -translation [list auto $outMode] seek $fhnd 0 end set theEnd [tell $fhnd] seek $fhnd 0 start fconfigure $fhnd -translation binary -buffersize $theEnd set rawFile [read $fhnd $theEnd] close $fhnd regsub -all {(\r)|(\r){1,2}(\n)} $rawFile "\n" rawFile set lineList [split $rawFile \n] foreach line $lineList { puts $newfhnd $line } close $newfhnd file delete ${filename}.o } proc EOL::fixall {args} { if {[llength $args] == 0} { puts stderr "no files to fix" exit 1 } else { set cmd [lreplace $args -1 -1 glob -nocomplain] } foreach f [eval $cmd] { if {[file isfile $f]} {fix $f} } } if {$tcl_interactive == 0 && $argc > 0} { if {[string index [lindex $argv 0] 0] eq "-"} { switch -- [lindex $argv 0] { -cr {set ::EOL::outMode cr} -crlf {set ::EOL::outMode crlf} -lf {set ::EOL::outMode lf} default {puts stderr "improper mode switch"; exit 1} } set argv [lrange $argv 1 end] } eval EOL::fixall $argv } else { return } tcl8.6.5/tools/Makefile.in0000644000175000017500000000271312663660066015000 0ustar sergeisergei# This makefile is used to convert Tcl manual pages into various # alternate formats: # # Windows help file: 1. Build the winhelp target on Unix # 2. Build the helpfile target on Windows # # HTML: 1. Build the html target on Unix TCL = tcl@TCL_VERSION@ TK = tk@TCL_VERSION@ VER = @TCL_WIN_VERSION@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_SOURCE = @TCL_SRC_DIR@ TK_SOURCE = $(TCL_SOURCE)/../$(TK) PRO_SOURCE = $(TCL_SOURCE)/../pro ITCL_SOURCE = $(TCL_SOURCE)/../itcl3.1.0 TCL_DOCS = $(TCL_SOURCE)/doc/*.[13n] TK_DOCS = $(TK_SOURCE)/doc/*.[13n] PRO_DOCS = \ $(PRO_SOURCE)/doc/man/procheck.1 \ $(PRO_SOURCE)/doc/man/prodebug.1 \ $(PRO_SOURCE)/doc/man/prodebug.n \ $(PRO_SOURCE)/doc/man/prolicense.1 ITCL_DOCS = \ $(ITCL_SOURCE)/itcl/doc/*.[13n] \ $(ITCL_SOURCE)/itk/doc/*.[13n] # $(ITCL_SOURCE)/iwidgets3.0.0/doc/*.[13n] COREDOCS = $(TCL_DOCS) $(TK_DOCS) #PRODOCS = $(COREDOCS) $(PRO_DOCS) $(ITCL_DOCS) PRODOCS = $(COREDOCS) $(PRO_DOCS) TCLSH = $(TCL_BIN_DIR)/tclsh CC = @CC@ # # Targets # all: core pro: $(MAKE) DOCS="$(PRODOCS)" VER="" rtf core: $(MAKE) DOCS="$(COREDOCS)" rtf rtf: $(TCL_SOURCE)/tools/man2help.tcl man2tcl $(DOCS) LD_LIBRARY_PATH=$(TCL_BIN_DIR) \ TCL_LIBRARY=$(TCL_SOURCE)/library \ $(TCLSH) $(TCL_SOURCE)/tools/man2help.tcl tcl "$(VER)" $(DOCS) winhelp: tcl.rtf man2tcl: $(TCL_SOURCE)/tools/man2tcl.c $(CC) $(CFLAGS) -o man2tcl $(TCL_SOURCE)/tools/man2tcl.c clean: -rm -f man2tcl *.o *.cnt *.rtf helpfile: hcw /c /e tcl.hpj tcl8.6.5/tools/regexpTestLib.tcl0000644000175000017500000001665412663653210016222 0ustar sergeisergei# regexpTestLib.tcl -- # # This file contains tcl procedures used by spencer2testregexp.tcl and # spencer2regexp.tcl, which are programs written to convert Henry # Spencer's test suite to tcl test files. # # Copyright (c) 1996 by Sun Microsystems, Inc. proc readInputFile {} { global inFileName global lineArray set fileId [open $inFileName r] set i 0 while {[gets $fileId line] >= 0} { set len [string length $line] if {($len > 0) && ([string index $line [expr $len - 1]] == "\\")} { if {[info exists lineArray(c$i)] == 0} { set lineArray(c$i) 1 } else { incr lineArray(c$i) } set line [string range $line 0 [expr $len - 2]] append lineArray($i) $line continue } if {[info exists lineArray(c$i)] == 0} { set lineArray(c$i) 1 } else { incr lineArray(c$i) } append lineArray($i) $line incr i } close $fileId return $i } # # strings with embedded @'s are truncated # unpreceeded @'s are replaced by {} # proc removeAts {ls} { set len [llength $ls] set newLs {} foreach item $ls { regsub @.* $item "" newItem lappend newLs $newItem } return $newLs } proc convertErrCode {code} { set errMsg "couldn't compile regular expression pattern:" if {[string compare $code "INVARG"] == 0} { return "$errMsg invalid argument to regex routine" } elseif {[string compare $code "BADRPT"] == 0} { return "$errMsg ?+* follows nothing" } elseif {[string compare $code "BADBR"] == 0} { return "$errMsg invalid repetition count(s)" } elseif {[string compare $code "BADOPT"] == 0} { return "$errMsg invalid embedded option" } elseif {[string compare $code "EPAREN"] == 0} { return "$errMsg unmatched ()" } elseif {[string compare $code "EBRACE"] == 0} { return "$errMsg unmatched {}" } elseif {[string compare $code "EBRACK"] == 0} { return "$errMsg unmatched \[\]" } elseif {[string compare $code "ERANGE"] == 0} { return "$errMsg invalid character range" } elseif {[string compare $code "ECTYPE"] == 0} { return "$errMsg invalid character class" } elseif {[string compare $code "ECOLLATE"] == 0} { return "$errMsg invalid collating element" } elseif {[string compare $code "EESCAPE"] == 0} { return "$errMsg invalid escape sequence" } elseif {[string compare $code "BADPAT"] == 0} { return "$errMsg invalid regular expression" } elseif {[string compare $code "ESUBREG"] == 0} { return "$errMsg invalid backreference number" } elseif {[string compare $code "IMPOSS"] == 0} { return "$errMsg can never match" } return "$errMsg $code" } proc writeOutputFile {numLines fcn} { global outFileName global lineArray # open output file and write file header info to it. set fileId [open $outFileName w] puts $fileId "# Commands covered: $fcn" puts $fileId "#" puts $fileId "# This Tcl-generated file contains tests for the $fcn tcl command." puts $fileId "# Sourcing this file into Tcl runs the tests and generates output for" puts $fileId "# errors. No output means no errors were found. Setting VERBOSE to" puts $fileId "# -1 will run tests that are known to fail." puts $fileId "#" puts $fileId "# Copyright (c) 1998 Sun Microsystems, Inc." puts $fileId "#" puts $fileId "# See the file \"license.terms\" for information on usage and redistribution" puts $fileId "# of this file, and for a DISCLAIMER OF ALL WARRANTIES." puts $fileId "#" puts $fileId "\# SCCS: \%Z\% \%M\% \%I\% \%E\% \%U\%" puts $fileId "\nproc print \{arg\} \{puts \$arg\}\n" puts $fileId "if \{\[string compare test \[info procs test\]\] == 1\} \{" puts $fileId " source defs ; set VERBOSE -1\n\}\n" puts $fileId "if \{\$VERBOSE != -1\} \{" puts $fileId " proc print \{arg\} \{\}\n\}\n" puts $fileId "#" puts $fileId "# The remainder of this file is Tcl tests that have been" puts $fileId "# converted from Henry Spencer's regexp test suite." puts $fileId "#\n" set lineNum 0 set srcLineNum 1 while {$lineNum < $numLines} { set currentLine $lineArray($lineNum) # copy comment string to output file and continue if {[string index $currentLine 0] == "#"} { puts $fileId $currentLine incr srcLineNum $lineArray(c$lineNum) incr lineNum continue } set len [llength $currentLine] # copy empty string to output file and continue if {$len == 0} { puts $fileId "\n" incr srcLineNum $lineArray(c$lineNum) incr lineNum continue } if {($len < 3)} { puts "warning: test is too short --\n\t$currentLine" incr srcLineNum $lineArray(c$lineNum) incr lineNum continue } puts $fileId [convertTestLine $currentLine $len $lineNum $srcLineNum] incr srcLineNum $lineArray(c$lineNum) incr lineNum } close $fileId } proc convertTestLine {currentLine len lineNum srcLineNum} { regsub -all {(?b)\\} $currentLine {\\\\} currentLine set re [lindex $currentLine 0] set flags [lindex $currentLine 1] set str [lindex $currentLine 2] # based on flags, decide whether to skip the test if {[findSkipFlag $flags]} { regsub -all {\[|\]|\(|\)|\{|\}|\#} $currentLine {\&} line set msg "\# skipping char mapping test from line $srcLineNum\n" append msg "print \{... skip test from line $srcLineNum: $line\}" return $msg } # perform mapping if '=' flag exists set noBraces 0 if {[regexp {=|>} $flags] == 1} { regsub -all {_} $currentLine {\\ } currentLine regsub -all {A} $currentLine {\\007} currentLine regsub -all {B} $currentLine {\\b} currentLine regsub -all {E} $currentLine {\\033} currentLine regsub -all {F} $currentLine {\\f} currentLine regsub -all {N} $currentLine {\\n} currentLine # if and \r substitutions are made, do not wrap re, flags, # str, and result in braces set noBraces [regsub -all {R} $currentLine {\\\u000D} currentLine] regsub -all {T} $currentLine {\\t} currentLine regsub -all {V} $currentLine {\\v} currentLine if {[regexp {=} $flags] == 1} { set re [lindex $currentLine 0] } set str [lindex $currentLine 2] } set flags [removeFlags $flags] # find the test result set numVars [expr $len - 3] set vars {} set vals {} set result 0 set v 0 if {[regsub {\*} "$flags" "" newFlags] == 1} { # an error is expected if {[string compare $str "EMPTY"] == 0} { # empty regexp is not an error # skip this test return "\# skipping the empty-re test from line $srcLineNum\n" } set flags $newFlags set result "\{1 \{[convertErrCode $str]\}\}" } elseif {$numVars > 0} { # at least 1 match is made if {[regexp {s} $flags] == 1} { set result "\{0 1\}" } else { while {$v < $numVars} { append vars " var($v)" append vals " \$var($v)" incr v } set tmp [removeAts [lrange $currentLine 3 $len]] set result "\{0 \{1 $tmp\}\}" if {$noBraces} { set result "\[subst $result\]" } } } else { # no match is made set result "\{0 0\}" } # set up the test and write it to the output file set cmd [prepareCmd $flags $re $str $vars $noBraces] if {$cmd == -1} { return "\# skipping test with metasyntax from line $srcLineNum\n" } set test "test regexp-1.$srcLineNum \{converted from line $srcLineNum\} \{\n" append test "\tcatch {unset var}\n" append test "\tlist \[catch \{\n" append test "\t\tset match \[$cmd\]\n" append test "\t\tlist \$match $vals\n" append test "\t\} msg\] \$msg\n" append test "\} $result\n" return $test } tcl8.6.5/tools/uniParse.tcl0000644000175000017500000002506612663660066015233 0ustar sergeisergei# uniParse.tcl -- # # This program parses the UnicodeData file and generates the # corresponding tclUniData.c file with compressed character # data tables. The input to this program should be the latest # UnicodeData file from: # ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt # # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. namespace eval uni { set shift 5; # number of bits of data within a page # This value can be adjusted to find the # best split to minimize table size variable pMap; # map from page to page index, each entry is # an index into the pages table, indexed by # page number variable pages; # map from page index to page info, each # entry is a list of indices into the groups # table, the list is indexed by the offset variable groups; # list of character info values, indexed by # group number, initialized with the # unassigned character group variable categories { Cn Lu Ll Lt Lm Lo Mn Me Mc Nd Nl No Zs Zl Zp Cc Cf Co Cs Pc Pd Ps Pe Pi Pf Po Sm Sc Sk So }; # Ordered list of character categories, must # match the enumeration in the header file. } proc uni::getValue {items index} { variable categories # Extract character info set category [lindex $items 2] if {[scan [lindex $items 12] %x toupper] == 1} { set toupper [expr {$index - $toupper}] } else { set toupper 0 } if {[scan [lindex $items 13] %x tolower] == 1} { set tolower [expr {$tolower - $index}] } else { set tolower 0 } if {[scan [lindex $items 14] %x totitle] == 1} { set totitle [expr {$index - $totitle}] } elseif {$tolower} { set totitle 0 } else { set totitle $toupper } set categoryIndex [lsearch -exact $categories $category] if {$categoryIndex < 0} { error "Unexpected character category: $index($category)" } return [list $categoryIndex $toupper $tolower $totitle] } proc uni::getGroup {value} { variable groups set gIndex [lsearch -exact $groups $value] if {$gIndex == -1} { set gIndex [llength $groups] lappend groups $value } return $gIndex } proc uni::addPage {info} { variable pMap variable pages variable shift set pIndex [lsearch -exact $pages $info] if {$pIndex == -1} { set pIndex [llength $pages] lappend pages $info } lappend pMap [expr {$pIndex << $shift}] return } proc uni::buildTables {data} { variable shift variable pMap {} variable pages {} variable groups {{0 0 0 0}} variable next 0 set info {} ;# temporary page info set mask [expr {(1 << $shift) - 1}] foreach line [split $data \n] { if {$line eq ""} { if {!($next & $mask)} { # next character is already on page boundary continue } # fill remaining page set line [format %X [expr {($next-1)|$mask}]] append line ";;Cn;0;ON;;;;;N;;;;;\n" } set items [split $line \;] scan [lindex $items 0] %x index if {$index > 0x2ffff} then { # Ignore non-BMP characters, as long as Tcl doesn't support them continue } set index [format %d $index] set gIndex [getGroup [getValue $items $index]] # Since the input table omits unassigned characters, these will # show up as gaps in the index sequence. There are a few special cases # where the gaps correspond to a uniform block of assigned characters. # These are indicated as such in the character name. # Enter all unassigned characters up to the current character. if {($index > $next) \ && ![regexp "Last>$" [lindex $items 1]]} { for {} {$next < $index} {incr next} { lappend info 0 if {($next & $mask) == $mask} { addPage $info set info {} } } } # Enter all assigned characters up to the current character for {set i $next} {$i <= $index} {incr i} { # Add the group index to the info for the current page lappend info $gIndex # If this is the last entry in the page, add the page if {($i & $mask) == $mask} { addPage $info set info {} } } set next [expr {$index + 1}] } return } proc uni::main {} { global argc argv0 argv variable pMap variable pages variable groups variable shift variable next if {$argc != 2} { puts stderr "\nusage: $argv0 \n" exit 1 } set f [open [lindex $argv 0] r] set data [read $f] close $f buildTables $data puts "X = [llength $pMap] Y= [llength $pages] A= [llength $groups]" set size [expr {[llength $pMap]*2 + ([llength $pages]<<$shift)}] puts "shift = $shift, space = $size" set f [open [file join [lindex $argv 1] tclUniData.c] w] fconfigure $f -translation lf puts $f "/* * tclUniData.c -- * * Declarations of Unicode character information tables. This file is * automatically generated by the tools/uniParse.tcl script. Do not * modify this file by hand. * * Copyright (c) 1998 by Scriptics Corporation. * All rights reserved. */ /* * A 16-bit Unicode character is split into two parts in order to index * into the following tables. The lower OFFSET_BITS comprise an offset * into a page of characters. The upper bits comprise the page number. */ #define OFFSET_BITS $shift /* * The pageMap is indexed by page number and returns an alternate page number * that identifies a unique page of characters. Many Unicode characters map * to the same alternate page number. */ static const unsigned short pageMap\[\] = {" set line " " set last [expr {[llength $pMap] - 1}] for {set i 0} {$i <= $last} {incr i} { if {$i == [expr {0x10000 >> $shift}]} { set line [string trimright $line " \t,"] puts $f $line set lastpage [expr {[lindex $line end] >> $shift}] puts stdout "lastpage: $lastpage" puts $f "#if TCL_UTF_MAX > 3" set line " ," } append line [lindex $pMap $i] if {$i != $last} { append line ", " } if {[string length $line] > 70} { puts $f [string trimright $line] set line " " } } puts $f $line puts $f "#endif /* TCL_UTF_MAX > 3 */" puts $f "}; /* * The groupMap is indexed by combining the alternate page number with * the page offset and returns a group number that identifies a unique * set of character attributes. */ static const unsigned char groupMap\[\] = {" set line " " set lasti [expr {[llength $pages] - 1}] for {set i 0} {$i <= $lasti} {incr i} { set page [lindex $pages $i] set lastj [expr {[llength $page] - 1}] if {$i == ($lastpage + 1)} { puts $f [string trimright $line " \t,"] puts $f "#if TCL_UTF_MAX > 3" set line " ," } for {set j 0} {$j <= $lastj} {incr j} { append line [lindex $page $j] if {$j != $lastj || $i != $lasti} { append line ", " } if {[string length $line] > 70} { puts $f [string trimright $line] set line " " } } } puts $f $line puts $f "#endif /* TCL_UTF_MAX > 3 */" puts $f "}; /* * Each group represents a unique set of character attributes. The attributes * are encoded into a 32-bit value as follows: * * Bits 0-4 Character category: see the constants listed below. * * Bits 5-7 Case delta type: 000 = identity * 010 = add delta for lower * 011 = add delta for lower, add 1 for title * 100 = subtract delta for title/upper * 101 = sub delta for upper, sub 1 for title * 110 = sub delta for upper, add delta for lower * * Bits 8-31 Case delta: delta for case conversions. This should be the * highest field so we can easily sign extend. */ static const int groups\[\] = {" set line " " set last [expr {[llength $groups] - 1}] for {set i 0} {$i <= $last} {incr i} { foreach {type toupper tolower totitle} [lindex $groups $i] {} # Compute the case conversion type and delta if {$totitle} { if {$totitle == $toupper} { # subtract delta for title or upper set case 4 set delta $toupper if {$tolower} { error "New case conversion type needed: $toupper $tolower $totitle" } } elseif {$toupper} { # subtract delta for upper, subtract 1 for title set case 5 set delta $toupper if {($totitle != 1) || $tolower} { error "New case conversion type needed: $toupper $tolower $totitle" } } else { # add delta for lower, add 1 for title set case 3 set delta $tolower if {$totitle != -1} { error "New case conversion type needed: $toupper $tolower $totitle" } } } elseif {$toupper} { # subtract delta for upper, add delta for lower set case 6 set delta $toupper if {$tolower != $toupper} { error "New case conversion type needed: $toupper $tolower $totitle" } } elseif {$tolower} { # add delta for lower set case 2 set delta $tolower } else { # noop set case 0 set delta 0 } append line [expr {($delta << 8) | ($case << 5) | $type}] if {$i != $last} { append line ", " } if {[string length $line] > 65} { puts $f [string trimright $line] set line " " } } puts $f $line puts -nonewline $f "}; #if TCL_UTF_MAX > 3 # define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1fffff) >= [format 0x%x $next]) #else # define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1f0000) != 0) #endif /* * The following constants are used to determine the category of a * Unicode character. */ enum { UNASSIGNED, UPPERCASE_LETTER, LOWERCASE_LETTER, TITLECASE_LETTER, MODIFIER_LETTER, OTHER_LETTER, NON_SPACING_MARK, ENCLOSING_MARK, COMBINING_SPACING_MARK, DECIMAL_DIGIT_NUMBER, LETTER_NUMBER, OTHER_NUMBER, SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, PRIVATE_USE, SURROGATE, CONNECTOR_PUNCTUATION, DASH_PUNCTUATION, OPEN_PUNCTUATION, CLOSE_PUNCTUATION, INITIAL_QUOTE_PUNCTUATION, FINAL_QUOTE_PUNCTUATION, OTHER_PUNCTUATION, MATH_SYMBOL, CURRENCY_SYMBOL, MODIFIER_SYMBOL, OTHER_SYMBOL }; /* * The following macros extract the fields of the character info. The * GetDelta() macro is complicated because we can't rely on the C compiler * to do sign extension on right shifts. */ #define GetCaseType(info) (((info) & 0xe0) >> 5) #define GetCategory(ch) (GetUniCharInfo(ch) & 0x1f) #define GetDelta(info) ((info) >> 8) /* * This macro extracts the information about a character from the * Unicode character tables. */ #if TCL_UTF_MAX > 3 # define GetUniCharInfo(ch) (groups\[groupMap\[pageMap\[((ch) & 0x1fffff) >> OFFSET_BITS\] | ((ch) & ((1 << OFFSET_BITS)-1))\]\]) #else # define GetUniCharInfo(ch) (groups\[groupMap\[pageMap\[((ch) & 0xffff) >> OFFSET_BITS\] | ((ch) & ((1 << OFFSET_BITS)-1))\]\]) #endif " close $f } uni::main return tcl8.6.5/tools/loadICU.tcl0000755000175000017500000004531612663660066014730 0ustar sergeisergei#---------------------------------------------------------------------- # # loadICU,tcl -- # # Extracts locale strings from a distribution of ICU # (http://oss.software.ibm.com/developerworks/opensource/icu/project/) # and makes Tcl message catalogs for the 'clock' command. # # Usage: # loadICU.tcl sourceDir destDir # # Parameters: # sourceDir -- Path name of the 'data' directory of your ICU4C # distribution. # destDir -- Directory into which the Tcl message catalogs should go. # # Results: # None. # # Side effects: # Creates the message catalogs. # #---------------------------------------------------------------------- # # Copyright (c) 2004 by Kevin B. Kenny. All rights reserved. # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. #---------------------------------------------------------------------- # Calculate the Chinese numerals from zero to ninety-nine. set zhDigits [list {} \u4e00 \u4e8c \u4e09 \u56db \ \u4e94 \u516d \u4e03 \u516b \u4e5d] set t 0 foreach zt $zhDigits { if { $t == 0 } { set zt {} } elseif { $t == 10 } { set zt \u5341 } else { append zt \u5341 } set d 0 foreach zd $zhDigits { if { $t == 0 && $d == 0 } { set zd \u3007 } elseif { $t == 20 && $d != 0 } { set zt \u5eff } elseif { $t == 30 && $d != 0 } { set zt \u5345 } lappend zhNumbers $zt$zd incr d } incr t 10 } # Set format overrides for various locales. set format(zh,LOCALE_NUMERALS) $zhNumbers set format(ja,LOCALE_ERAS) [list \ [list -9223372036854775808 \u897f\u66a6 0 ] \ [list -3061011600 \u660e\u6cbb 1867] \ [list -1812186000 \u5927\u6b63 1911] \ [list -1357635600 \u662d\u548c 1925] \ [list 600220800 \u5e73\u6210 1988]] set format(zh,LOCALE_DATE_FORMAT) "\u516c\u5143%Y\u5e74%B%Od\u65E5" set format(ja,LOCALE_DATE_FORMAT) "%EY\u5e74%m\u6708%d\u65E5" set format(ko,LOCALE_DATE_FORMAT) "%Y\ub144%B%Od\uc77c" set format(zh,LOCALE_TIME_FORMAT) "%OH\u65f6%OM\u5206%OS\u79d2" set format(ja,LOCALE_TIME_FORMAT) "%H\u6642%M\u5206%S\u79d2" set format(ko,LOCALE_TIME_FORMAT) "%H\uc2dc%M\ubd84%S\ucd08" set format(zh,LOCALE_DATE_TIME_FORMAT) "%A %Y\u5e74%B%Od\u65E5%OH\u65f6%OM\u5206%OS\u79d2 %z" set format(ja,LOCALE_DATE_TIME_FORMAT) "%EY\u5e74%m\u6708%d\u65E5 (%a) %H\u6642%M\u5206%S\u79d2 %z" set format(ko,LOCALE_DATE_TIME_FORMAT) "%A %Y\ub144%B%Od\uc77c%H\uc2dc%M\ubd84%S\ucd08 %z" set format(ja,TIME_FORMAT_12) {%P %I:%M:%S} # The next set of format overrides were obtained from the glibc # localization strings. set format(cs_CZ,DATE_FORMAT) %d.%m.%Y set format(cs_CZ,DATE_TIME_FORMAT) {%a %e. %B %Y, %H:%M:%S %z} set format(cs_CZ,TIME_FORMAT) %H:%M:%S set format(cs_CZ,TIME_FORMAT_12) %I:%M:%S set format(da_DK,DATE_FORMAT) %d-%m-%Y set format(da_DK,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(da_DK,TIME_FORMAT) %T set format(da_DK,TIME_FORMAT_12) %T set format(de_AT,DATE_FORMAT) %Y-%m-%d set format(de_AT,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(de_AT,TIME_FORMAT) %T set format(de_AT,TIME_FORMAT_12) %T set format(de_BE,DATE_FORMAT) %Y-%m-%d set format(de_BE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(de_BE,TIME_FORMAT) %T set format(de_BE,TIME_FORMAT_12) %T set format(de_CH,DATE_FORMAT) %Y-%m-%d set format(de_CH,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(de_CH,TIME_FORMAT) %T set format(de_CH,TIME_FORMAT_12) %T set format(de_DE,DATE_FORMAT) %Y-%m-%d set format(de_DE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(de_DE,TIME_FORMAT) %T set format(de_DE,TIME_FORMAT_12) %T set format(de_LU,DATE_FORMAT) %Y-%m-%d set format(de_LU,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(de_LU,TIME_FORMAT) %T set format(de_LU,TIME_FORMAT_12) %T set format(en_CA,DATE_FORMAT) %d/%m/%y set format(en_CA,DATE_TIME_FORMAT) {%a %d %b %Y %r %z} set format(en_CA,TIME_FORMAT) %r set format(en_CA,TIME_FORMAT_12) {%I:%M:%S %p} set format(en_DK,DATE_FORMAT) %Y-%m-%d set format(en_DK,DATE_TIME_FORMAT) {%Y-%m-%dT%T %z} set format(en_DK,TIME_FORMAT) %T set format(en_DK,TIME_FORMAT_12) %T set format(en_GB,DATE_FORMAT) %d/%m/%y set format(en_GB,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(en_GB,TIME_FORMAT) %T set format(en_GB,TIME_FORMAT_12) %T set format(en_IE,DATE_FORMAT) %d/%m/%y set format(en_IE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(en_IE,TIME_FORMAT) %T set format(en_IE,TIME_FORMAT_12) %T set format(en_US,DATE_FORMAT) %m/%d/%y set format(en_US,DATE_TIME_FORMAT) {%a %d %b %Y %r %z} set format(en_US,TIME_FORMAT) %r set format(en_US,TIME_FORMAT_12) {%I:%M:%S %p} set format(es_ES,DATE_FORMAT) %d/%m/%y set format(es_ES,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(es_ES,TIME_FORMAT) %T set format(es_ES,TIME_FORMAT_12) %T set format(et_EE,DATE_FORMAT) %d.%m.%Y set format(et_EE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(et_EE,TIME_FORMAT) %T set format(et_EE,TIME_FORMAT_12) %T set format(eu_ES,DATE_FORMAT) {%a, %Yeko %bren %da} set format(eu_ES,DATE_TIME_FORMAT) {%y-%m-%d %T %z} set format(eu_ES,TIME_FORMAT) %T set format(eu_ES,TIME_FORMAT_12) %T set format(fi_FI,DATE_FORMAT) %d.%m.%Y set format(fi_FI,DATE_TIME_FORMAT) {%a %e %B %Y %T} set format(fi_FI,TIME_FORMAT) %T set format(fi_FI,TIME_FORMAT_12) %T set format(fo_FO,DATE_FORMAT) %d/%m-%Y set format(fo_FO,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(fo_FO,TIME_FORMAT) %T set format(fo_FO,TIME_FORMAT_12) %T set format(fr_BE,DATE_FORMAT) %d/%m/%y set format(fr_BE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(fr_BE,TIME_FORMAT) %T set format(fr_BE,TIME_FORMAT_12) %T set format(fr_CA,DATE_FORMAT) %Y-%m-%d set format(fr_CA,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(fr_CA,TIME_FORMAT) %T set format(fr_CA,TIME_FORMAT_12) %T set format(fr_CH,DATE_FORMAT) {%d. %m. %y} set format(fr_CH,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(fr_CH,TIME_FORMAT) %T set format(fr_CH,TIME_FORMAT_12) %T set format(fr_FR,DATE_FORMAT) %d.%m.%Y set format(fr_FR,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(fr_FR,TIME_FORMAT) %T set format(fr_FR,TIME_FORMAT_12) %T set format(fr_LU,DATE_FORMAT) %d.%m.%Y set format(fr_LU,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(fr_LU,TIME_FORMAT) %T set format(fr_LU,TIME_FORMAT_12) %T set format(ga_IE,DATE_FORMAT) %d.%m.%y set format(ga_IE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(ga_IE,TIME_FORMAT) %T set format(ga_IE,TIME_FORMAT_12) %T set format(gr_GR,DATE_FORMAT) %d/%m/%Y set format(gr_GR,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(gr_GR,TIME_FORMAT) %T set format(gr_GR,TIME_FORMAT_12) %T set format(hr_HR,DATE_FORMAT) %d.%m.%y set format(hr_HR,DATE_TIME_FORMAT) {%a %d %b %Y %T} set format(hr_HR,TIME_FORMAT) %T set format(hr_HR,TIME_FORMAT_12) %T set format(hu_HU,DATE_FORMAT) %Y-%m-%d set format(hu_HU,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(hu_HU,TIME_FORMAT) %T set format(hu_HU,TIME_FORMAT_12) %T set format(is_IS,DATE_FORMAT) {%a %e.%b %Y} set format(is_IS,DATE_TIME_FORMAT) {%a %e.%b %Y, %T %z} set format(is_IS,TIME_FORMAT) %T set format(is_IS,TIME_FORMAT_12) %T set format(it_IT,DATE_FORMAT) %d/%m/%Y set format(it_IT,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(it_IT,TIME_FORMAT) %T set format(it_IT,TIME_FORMAT_12) %T set format(iw_IL,DATE_FORMAT) %d/%m/%y set format(iw_IL,DATE_TIME_FORMAT) {%z %H:%M:%S %Y %b %d %a} set format(iw_IL,TIME_FORMAT) %H:%M:%S set format(iw_IL,TIME_FORMAT_12) {%I:%M:%S %P} set format(kl_GL,DATE_FORMAT) {%d %b %Y} set format(kl_GL,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(kl_GL,TIME_FORMAT) %T set format(kl_GL,TIME_FORMAT_12) %T set format(lt_LT,DATE_FORMAT) %Y.%m.%d set format(lt_LT,DATE_TIME_FORMAT) {%Y m. %B %d d. %T} set format(lt_LT,TIME_FORMAT) %T set format(lt_LT,TIME_FORMAT_12) %T set format(lv_LV,DATE_FORMAT) %Y.%m.%d. set format(lv_LV,DATE_TIME_FORMAT) {%A, %Y. gada %e. %B, plkst. %H un %M} set format(lv_LV,TIME_FORMAT) %T set format(lv_LV,TIME_FORMAT_12) %T set format(nl_BE,DATE_FORMAT) %d-%m-%y set format(nl_BE,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(nl_BE,TIME_FORMAT) %T set format(nl_BE,TIME_FORMAT_12) %T set format(nl_NL,DATE_FORMAT) %d-%m-%y set format(nl_NL,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(nl_NL,TIME_FORMAT) %T set format(nl_NL,TIME_FORMAT_12) %T set format(no_NO,DATE_FORMAT) %d-%m-%Y set format(no_NO,DATE_TIME_FORMAT) {%a %d-%m-%Y %T %z} set format(no_NO,TIME_FORMAT) %T set format(no_NO,TIME_FORMAT_12) %T set format(pl_PL,DATE_FORMAT) %Y-%m-%d set format(pl_PL,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(pl_PL,TIME_FORMAT) %T set format(pl_PL,TIME_FORMAT_12) %T set format(pt_BR,DATE_FORMAT) %d-%m-%Y set format(pt_BR,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(pt_BR,TIME_FORMAT) %T set format(pt_BR,TIME_FORMAT_12) %T set format(pt_PT,DATE_FORMAT) %d-%m-%Y set format(pt_PT,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(pt_PT,TIME_FORMAT) %T set format(pt_PT,TIME_FORMAT_12) %T set format(ro_RO,DATE_FORMAT) %Y-%m-%d set format(ro_RO,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(ro_RO,TIME_FORMAT) %T set format(ro_RO,TIME_FORMAT_12) %T set format(ru_RU,DATE_FORMAT) %d.%m.%Y set format(ru_RU,DATE_TIME_FORMAT) {%a %d %b %Y %T} set format(ru_RU,TIME_FORMAT) %T set format(ru_RU,TIME_FORMAT_12) %T set format(sl_SI,DATE_FORMAT) %d.%m.%Y set format(sl_SI,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(sl_SI,TIME_FORMAT) %T set format(sl_SI,TIME_FORMAT_12) %T set format(sv_FI,DATE_FORMAT) %Y-%m-%d set format(sv_FI,DATE_TIME_FORMAT) {%a %e %b %Y %H.%M.%S} set format(sv_FI,TIME_FORMAT) %H.%M.%S set format(sv_FI,TIME_FORMAT_12) %H.%M.%S set format(sv_SE,DATE_FORMAT) %Y-%m-%d set format(sv_SE,DATE_TIME_FORMAT) {%a %e %b %Y %H.%M.%S} set format(sv_SE,TIME_FORMAT) %H.%M.%S set format(sv_SE,TIME_FORMAT_12) %H.%M.%S set format(tr_TR,DATE_FORMAT) %Y-%m-%d set format(tr_TR,DATE_TIME_FORMAT) {%a %d %b %Y %T %z} set format(tr_TR,TIME_FORMAT) %T set format(tr_TR,TIME_FORMAT_12) %T #---------------------------------------------------------------------- # # handleLocaleFile -- # # Extracts strings from an ICU locale definition. # # Parameters: # localeName - Name of the locale (e.g., de_AT_euro) # fileName - Name of the file containing the data # msgFileName - Name of the file containing the Tcl message catalog # # Results: # None. # # Side effects: # Writes the Tcl message catalog. # #---------------------------------------------------------------------- proc handleLocaleFile { localeName fileName msgFileName } { variable format # Get the content of the ICU file set f [open $fileName r] fconfigure $f -encoding utf-8 set data [read $f] close $f # Parse the ICU data set state {} foreach line [split $data \n] { switch -exact -- $state { {} { # Look for the beginnings of data blocks switch -regexp -- $line { {^[[:space:]]*AmPmMarkers[[:space:]]+[\{]} { set state data set key AmPmMarkers } {^[[:space:]]*DateTimePatterns[[:space:]]+[\{]} { set state data set key DateTimePatterns } {^[[:space:]]*DayAbbreviations[[:space:]]+[\{]} { set state data set key DayAbbreviations } {^[[:space:]]*DayNames[[:space:]]+[\{]} { set state data set key DayNames } {^[[:space:]]*Eras[[:space:]]+[\{]} { set state data set key Eras } {^[[:space:]]*MonthAbbreviations[[:space:]]+[\{]} { set state data set key MonthAbbreviations } {^[[:space:]]*MonthNames[[:space:]]+[\{]} { set state data set key MonthNames } } } data { # Inside a data block, collect the strings, doing backslash # expansion to pick up the Unicodes if { [regexp {"(.*)",} $line -> item] } { lappend items($key) [subst -nocommands -novariables $item] } elseif { [regexp {^[[:space:]]*[\}][[:space:]]*$} $line] } { set state {} } } } } # Skip locales that don't change time strings. if {![array exists items]} return # Write the Tcl message catalog set f [open $msgFileName w] # Write a header puts $f "\# created by $::argv0 -- do not edit" puts $f "namespace eval ::tcl::clock \{" # Do ordinary sets of strings (weekday and month names) foreach key { DayAbbreviations DayNames MonthAbbreviations MonthNames } tkey { DAYS_OF_WEEK_ABBREV DAYS_OF_WEEK_FULL MONTHS_ABBREV MONTHS_FULL } { if { [info exists items($key)] } { set itemList $items($key) set cmd1 " ::msgcat::mcset " append cmd1 $localeName " " $tkey " \[list " foreach item $itemList { append cmd1 \\\n { } \" [backslashify $item] \" } append cmd1 \] puts $f $cmd1 } } # Do the eras, B.C.E., and C.E. if { [info exists items(Eras)] } { foreach { bce ce } $items(Eras) break set cmd " ::msgcat::mcset " append cmd $localeName " " BCE " \"" [backslashify $bce] \" puts $f $cmd set cmd " ::msgcat::mcset " append cmd $localeName " " CE " \"" [backslashify $ce] \" puts $f $cmd } # Do the AM and PM markers if { [info exists items(AmPmMarkers)] } { foreach { am pm } $items(AmPmMarkers) break set cmd " ::msgcat::mcset " append cmd $localeName " " AM " \"" [backslashify $am] \" puts $f $cmd set cmd " ::msgcat::mcset " append cmd $localeName " " PM " \"" [backslashify $pm] \" puts $f $cmd } # Do the date/time patterns. First date... if { [info exists format($localeName,DATE_FORMAT)] || [info exists items(DateTimePatterns)] } { # Find the shortest date format that includes a 4-digit year. if { ![info exists format($localeName,DATE_FORMAT)] } { for { set i 7 } { $i >= 4 } { incr i -1 } { if { [regexp yyyy [lindex $items(DateTimePatterns) $i]] } { break } } set fmt \ [backslashify \ [percentify [lindex $items(DateTimePatterns) $i]]] set format($localeName,DATE_FORMAT) $fmt } # Put it to the message catalog set cmd " ::msgcat::mcset " append cmd $localeName " DATE_FORMAT \"" \ $format($localeName,DATE_FORMAT) "\"" puts $f $cmd } # Time if { [info exists format($localeName,TIME_FORMAT)] || [info exists items(DateTimePatterns)] } { # Find the shortest time pattern that includes the seconds if { ![info exists format($localeName,TIME_FORMAT)] } { for { set i 3 } { $i >= 0 } { incr i -1 } { if { [regexp H [lindex $items(DateTimePatterns) $i]] && [regexp s [lindex $items(DateTimePatterns) $i]] } { break } } if { $i >= 0 } { set fmt \ [backslashify \ [percentify [lindex $items(DateTimePatterns) $i]]] regsub { %Z} $fmt {} format($localeName,TIME_FORMAT) } } # Put it to the message catalog if { [info exists format($localeName,TIME_FORMAT)] } { set cmd " ::msgcat::mcset " append cmd $localeName " TIME_FORMAT \"" \ $format($localeName,TIME_FORMAT) "\"" puts $f $cmd } } # 12-hour time... if { [info exists format($localeName,TIME_FORMAT_12)] || [info exists items(DateTimePatterns)] } { # Shortest patterm with 12-hour time that includes seconds if { ![info exists format($localeName,TIME_FORMAT_12)] } { for { set i 3 } { $i >= 0 } { incr i -1 } { if { [regexp h [lindex $items(DateTimePatterns) $i]] && [regexp s [lindex $items(DateTimePatterns) $i]] } { break } } if { $i >= 0 } { set fmt \ [backslashify \ [percentify [lindex $items(DateTimePatterns) $i]]] regsub { %Z} $fmt {} format($localeName,TIME_FORMAT_12) } } # Put it to the catalog if { [info exists format($localeName,TIME_FORMAT_12)] } { set cmd " ::msgcat::mcset " append cmd $localeName " TIME_FORMAT_12 \"" \ $format($localeName,TIME_FORMAT_12) "\"" puts $f $cmd } } # Date and time... Prefer 24-hour format to 12-hour format. if { ![info exists format($localeName,DATE_TIME_FORMAT)] && [info exists format($localeName,DATE_FORMAT)] && [info exists format($localeName,TIME_FORMAT)]} { set format($localeName,DATE_TIME_FORMAT) \ $format($localeName,DATE_FORMAT) append format($localeName,DATE_TIME_FORMAT) \ " " $format($localeName,TIME_FORMAT) " %z" } if { ![info exists format($localeName,DATE_TIME_FORMAT)] && [info exists format($localeName,DATE_FORMAT)] && [info exists format($localeName,TIME_FORMAT_12)]} { set format($localeName,DATE_TIME_FORMAT) \ $format($localeName,DATE_FORMAT) append format($localeName,DATE_TIME_FORMAT) \ " " $format($localeName,TIME_FORMAT_12) " %z" } # Write date/time format to the file if { [info exists format($localeName,DATE_TIME_FORMAT)] } { set cmd " ::msgcat::mcset " append cmd $localeName " DATE_TIME_FORMAT \"" \ $format($localeName,DATE_TIME_FORMAT) "\"" puts $f $cmd } # Write the string sets to the file. foreach key { LOCALE_NUMERALS LOCALE_DATE_FORMAT LOCALE_TIME_FORMAT LOCALE_DATE_TIME_FORMAT LOCALE_ERAS LOCALE_YEAR_FORMAT } { if { [info exists format($localeName,$key)] } { set cmd " ::msgcat::mcset " append cmd $localeName " " $key " \"" \ [backslashify $format($localeName,$key)] "\"" puts $f $cmd } } # Footer puts $f "\}" close $f } #---------------------------------------------------------------------- # # percentify -- # # Converts a Java/ICU-style time format to a C/Tcl style one. # # Parameters: # string -- Format to convert # # Results: # Returns the converted format. # # Side effects: # None. # #---------------------------------------------------------------------- proc percentify { string } { set retval {} foreach { unquoted quoted } [split $string '] { append retval [string map { EEEE %A MMMM %B yyyy %Y MMM %b EEE %a dd %d hh %I HH %H mm %M MM %m ss %S yy %y a %P d %e h %l H %k M %m z %z } $unquoted] append retval $quoted } return $retval } #---------------------------------------------------------------------- # # backslashify -- # # Converts a UTF-8 string to a plain ASCII one with escapes. # # Parameters: # string -- String to convert # # Results: # Returns the converted string # # Side effects: # None. # #---------------------------------------------------------------------- proc backslashify { string } { set retval {} foreach char [split $string {}] { scan $char %c ccode if { $ccode >= 0x0020 && $ccode < 0x007f && $char ne "\"" && $char ne "\{" && $char ne "\}" && $char ne "\[" && $char ne "\]" && $char ne "\\" && $char ne "\$" } { append retval $char } else { append retval \\u [format %04x $ccode] } } return $retval } #---------------------------------------------------------------------- # # MAIN PROGRAM # #---------------------------------------------------------------------- # Extract directories from command line foreach { icudir msgdir } $argv break # Walk the ICU files and create corresponding Tcl message catalogs foreach fileName [glob -directory $icudir *.txt] { set n [file rootname [file tail $fileName]] if { [regexp {^[a-z]{2,3}(_[A-Z]{2,3}(_.*)?)?$} $n] } { handleLocaleFile $n $fileName [file join $msgdir [string tolower $n].msg] } } tcl8.6.5/tools/README0000644000175000017500000000150412663660066013610 0ustar sergeisergeiThis directory contains unsupported tools used to build parts of Tcl for distribution. uniParse.tcl -- Script for converting the Unicode character database into a compact table stored in generic/tclUniData.c. 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 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 tcl8.6.5/tools/tcl.hpj.in0000644000175000017500000000053412663660066014624 0ustar sergeisergei; This file is maintained by HCW. Do not modify this file directly. [OPTIONS] HCW=0 LCID=0x409 0x0 0x0 ;English (United States) REPORT=Yes TITLE=Tcl/Tk Reference Manual CNT=tcl86.cnt COPYRIGHT=Copyright © 2000 Ajuba Solutions HLP=tcl86.hlp [FILES] tcl.rtf [WINDOWS] main="Tcl/Tk Reference Manual",,0 [CONFIG] BrowseButtons() tcl8.6.5/tools/installData.tcl0000644000175000017500000000267412663653210015676 0ustar sergeisergei#!/bin/sh #\ exec tclsh "$0" ${1+"$@"} #---------------------------------------------------------------------- # # installData.tcl -- # # This file installs a hierarchy of data found in the directory # specified by its first argument into the directory specified # by its second. # #---------------------------------------------------------------------- # # Copyright (c) 2004 by Kevin B. Kenny. All rights reserved. # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. #---------------------------------------------------------------------- proc copyDir {d1 d2} { puts [format {%*sCreating %s} [expr {4 * [info level]}] {} \ [file tail $d2]] file delete -force -- $d2 file mkdir $d2 foreach ftail [glob -directory $d1 -nocomplain -tails *] { set f [file join $d1 $ftail] if {[file isdirectory $f] && [string compare CVS $ftail]} { copyDir $f [file join $d2 $ftail] } elseif {[file isfile $f]} { file copy -force $f [file join $d2 $ftail] if {$::tcl_platform(platform) eq {unix}} { file attributes [file join $d2 $ftail] -permissions 0644 } else { file attributes [file join $d2 $ftail] -readonly 1 } } } if {$::tcl_platform(platform) eq {unix}} { file attributes $d2 -permissions 0755 } else { file attributes $d2 -readonly 1 } } copyDir [file normalize [lindex $argv 0]] [file normalize [lindex $argv 1]] tcl8.6.5/doc/0000755000175000017500000000000012665173607012337 5ustar sergeisergeitcl8.6.5/doc/zlib.n0000644000175000017500000003535412663660065013465 0ustar sergeisergei'\" '\" Copyright (c) 2008-2012 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH zlib n 8.6 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME zlib \- compression and decompression operations .SH SYNOPSIS .nf \fBzlib \fIsubcommand arg ...\fR .fi .BE .SH DESCRIPTION .PP The \fBzlib\fR command provides access to the compression and check-summing facilities of the Zlib library by Jean-loup Gailly and Mark Adler. It has the following subcommands. .SS "COMPRESSION SUBCOMMANDS" .TP \fBzlib compress\fI string\fR ?\fIlevel\fR? . Returns the zlib-format compressed binary data of the binary string in \fIstring\fR. If present, \fIlevel\fR gives the compression level to use (from 0, which is uncompressed, to 9, maximally compressed). .TP \fBzlib decompress\fI string\fR ?\fIbufferSize\fR? . Returns the uncompressed version of the raw compressed binary data in \fIstring\fR. If present, \fIbufferSize\fR is a hint as to what size of buffer is to be used to receive the data. .TP \fBzlib deflate\fI string\fR ?\fIlevel\fR? . Returns the raw compressed binary data of the binary string in \fIstring\fR. If present, \fIlevel\fR gives the compression level to use (from 0, which is uncompressed, to 9, maximally compressed). .TP \fBzlib gunzip\fI string\fR ?\fB\-headerVar \fIvarName\fR? . Return the uncompressed contents of binary string \fIstring\fR, which must have been in gzip format. If \fB\-headerVar\fR is given, store a dictionary describing the contents of the gzip header in the variable called \fIvarName\fR. The keys of the dictionary that may be present are: .RS .TP \fBcomment\fR . The comment field from the header, if present. .TP \fBcrc\fR . A boolean value describing whether a CRC of the header is computed. .TP \fBfilename\fR . The filename field from the header, if present. .TP \fBos\fR . The operating system type code field from the header (if not the QW unknown value). See RFC 1952 for the meaning of these codes. .TP \fBsize\fR . The size of the uncompressed data. .TP \fBtime\fR . The time field from the header if non-zero, expected to be time that the file named by the \fBfilename\fR field was modified. Suitable for use with \fBclock format\fR. .TP \fBtype\fR . The type of the uncompressed data (\fBbinary\fR or \fBtext\fR) if known. .RE .TP \fBzlib gzip\fI string\fR ?\fB\-level \fIlevel\fR? ?\fB\-header \fIdict\fR? . Return the compressed contents of binary string \fIstring\fR in gzip format. If \fB\-level\fR is given, \fIlevel\fR gives the compression level to use (from 0, which is uncompressed, to 9, maximally compressed). If \fB\-header\fR is given, \fIdict\fR is a dictionary containing values used for the gzip header. The following keys may be defined: .RS .TP \fBcomment\fR . Add the given comment to the header of the gzip-format data. .TP \fBcrc\fR . A boolean saying whether to compute a CRC of the header. Note that if the data is to be interchanged with the \fBgzip\fR program, a header CRC should \fInot\fR be computed. .TP \fBfilename\fR . The name of the file that the data to be compressed came from. .TP \fBos\fR . The operating system type code, which should be one of the values described in RFC 1952. .TP \fBtime\fR . The time that the file named in the \fBfilename\fR key was last modified. This will be in the same as is returned by \fBclock seconds\fR or \fBfile mtime\fR. .TP \fBtype\fR . The type of the data being compressed, being \fBbinary\fR or \fBtext\fR. .RE .TP \fBzlib inflate\fI string\fR ?\fIbufferSize\fR? . Returns the uncompressed version of the raw compressed binary data in \fIstring\fR. If present, \fIbufferSize\fR is a hint as to what size of buffer is to be used to receive the data. .SS "CHANNEL SUBCOMMAND" .TP \fBzlib push\fI mode channel\fR ?\fIoptions ...\fR? . Pushes a compressing or decompressing transformation onto the channel \fIchannel\fR. The transformation can be removed again with \fBchan pop\fR. The \fImode\fR argument determines what type of transformation is pushed; the following are supported: .RS .TP \fBcompress\fR . The transformation will be a compressing transformation that produces zlib-format data on \fIchannel\fR, which must be writable. .TP \fBdecompress\fR . The transformation will be a decompressing transformation that reads zlib-format data from \fIchannel\fR, which must be readable. .TP \fBdeflate\fR . The transformation will be a compressing transformation that produces raw compressed data on \fIchannel\fR, which must be writable. .TP \fBgunzip\fR . The transformation will be a decompressing transformation that reads gzip-format data from \fIchannel\fR, which must be readable. .TP \fBgzip\fR . The transformation will be a compressing transformation that produces gzip-format data on \fIchannel\fR, which must be writable. .TP \fBinflate\fR . The transformation will be a decompressing transformation that reads raw compressed data from \fIchannel\fR, which must be readable. .PP The following options may be set when creating a transformation via the .QW "\fIoptions ...\fR" to the \fBzlib push\fR command: .TP \fB\-dictionary\fI binData\fR .VS "TIP 400" Sets the compression dictionary to use when working with compressing or decompressing the data to be \fIbinData\fR. Not valid for transformations that work with gzip-format data. .VE .TP \fB\-header\fI dictionary\fR . Passes a description of the gzip header to create, in the same format that \fBzlib gzip\fR understands. .TP \fB\-level\fI compressionLevel\fR . How hard to compress the data. Must be an integer from 0 (uncompressed) to 9 (maximally compressed). .TP \fB\-limit\fI readaheadLimit\fR . The maximum number of bytes ahead to read when decompressing. This defaults to 1, which ensures that data is always decompressed correctly, but may be increased to improve performance. This is more useful when the channel is non-blocking. .PP Both compressing and decompressing channel transformations add extra configuration options that may be accessed through \fBchan configure\fR. The options are: .TP \fB\-checksum\fI checksum\fR . This read-only option gets the current checksum for the uncompressed data that the compression engine has seen so far. It is valid for both compressing and decompressing transforms, but not for the raw inflate and deflate formats. The compression algorithm depends on what format is being produced or consumed. .TP \fB\-dictionary\fI binData\fR .VS "TIP 400" This read-write options gets or sets the compression dictionary to use when working with compressing or decompressing the data to be \fIbinData\fR. It is not valid for transformations that work with gzip-format data, and should not normally be set on compressing transformations other than at the point where the transformation is stacked. .VE .TP \fB\-flush\fI type\fR . This write-only operation flushes the current state of the compressor to the underlying channel. It is only valid for compressing transformations. The \fItype\fR must be either \fBsync\fR or \fBfull\fR for a normal flush or an expensive flush respectively. Flushing degrades the compression ratio, but makes it easier for a decompressor to recover more of the file in the case of data corruption. .TP \fB\-header\fI dictionary\fR . This read-only option, only valid for decompressing transforms that are processing gzip-format data, returns the dictionary describing the header read off the data stream. .TP \fB\-limit\fI readaheadLimit\fR . This read-write option is used by decompressing channels to control the maximum number of bytes ahead to read from the underlying data source. This defaults to 1, which ensures that data is always decompressed correctly, but may be increased to improve performance. This is more useful when the channel is non-blocking. .RE .SS "STREAMING SUBCOMMAND" .TP \fBzlib stream\fI mode\fR ?\fIoptions\fR? . Creates a streaming compression or decompression command based on the \fImode\fR, and return the name of the command. For a description of how that command works, see \fBSTREAMING INSTANCE COMMAND\fR below. The following modes and \fIoptions\fR are supported: .RS .TP \fBzlib stream compress\fR ?\fB\-dictionary \fIbindata\fR? ?\fB\-level \fIlevel\fR? . The stream will be a compressing stream that produces zlib-format output, using compression level \fIlevel\fR (if specified) which will be an integer from 0 to 9, .VS "TIP 400" and the compression dictionary \fIbindata\fR (if specified). .VE .TP \fBzlib stream decompress\fR ?\fB\-dictionary \fIbindata\fR? . The stream will be a decompressing stream that takes zlib-format input and produces uncompressed output. .VS "TIP 400" If \fIbindata\fR is supplied, it is a compression dictionary to use if required. .VE .TP \fBzlib stream deflate\fR ?\fB\-dictionary \fIbindata\fR? ?\fB\-level \fIlevel\fR? . The stream will be a compressing stream that produces raw output, using compression level \fIlevel\fR (if specified) which will be an integer from 0 to 9, .VS "TIP 400" and the compression dictionary \fIbindata\fR (if specified). Note that the raw compressed data includes no metadata about what compression dictionary was used, if any; that is a feature of the zlib-format data. .VE .TP \fBzlib stream gunzip\fR . The stream will be a decompressing stream that takes gzip-format input and produces uncompressed output. .TP \fBzlib stream gzip\fR ?\fB\-header \fIheader\fR? ?\fB\-level \fIlevel\fR? . The stream will be a compressing stream that produces gzip-format output, using compression level \fIlevel\fR (if specified) which will be an integer from 0 to 9, and the header descriptor dictionary \fIheader\fR (if specified; for keys see \fBzlib gzip\fR). .TP \fBzlib stream inflate\fR ?\fB\-dictionary \fIbindata\fR? . The stream will be a decompressing stream that takes raw compressed input and produces uncompressed output. .VS "TIP 400" If \fIbindata\fR is supplied, it is a compression dictionary to use. Note that there are no checks in place to determine whether the compression dictionary is correct. .VE .RE .SS "CHECKSUMMING SUBCOMMANDS" .TP \fBzlib adler32\fI string\fR ?\fIinitValue\fR? . Compute a checksum of binary string \fIstring\fR using the Adler-32 algorithm. If given, \fIinitValue\fR is used to initialize the checksum engine. .TP \fBzlib crc32\fI string\fR ?\fIinitValue\fR? . Compute a checksum of binary string \fIstring\fR using the CRC-32 algorithm. If given, \fIinitValue\fR is used to initialize the checksum engine. .SH "STREAMING INSTANCE COMMAND" .PP Streaming compression instance commands are produced by the \fBzlib stream\fR command. They are used by calling their \fBput\fR subcommand one or more times to load data in, and their \fBget\fR subcommand one or more times to extract the transformed data. .PP The full set of subcommands supported by a streaming instance command, \fIstream\fR, is as follows: .TP \fIstream \fBadd\fR ?\fIoption...\fR? \fIdata\fR . A short-cut for .QW "\fIstream \fBput \fR?\fIoption...\fR? \fIdata\fR" followed by .QW "\fIstream \fBget\fR" . .TP \fIstream \fBchecksum\fR . Returns the checksum of the uncompressed data seen so far by this stream. .TP \fIstream \fBclose\fR . Deletes this stream and frees up all resources associated with it. .TP \fIstream \fBeof\fR . Returns a boolean indicating whether the end of the stream (as determined by the compressed data itself) has been reached. Not all formats support detection of the end of the stream. .TP \fIstream \fBfinalize\fR . A short-cut for .QW "\fIstream \fBput \-finalize {}\fR" . .TP \fIstream \fBflush\fR . A short-cut for .QW "\fIstream \fBput \-flush {}\fR" . .TP \fIstream \fBfullflush\fR . A short-cut for .QW "\fIstream \fBput \-fullflush {}\fR" . .TP \fIstream \fBget \fR?\fIcount\fR? . Return up to \fIcount\fR bytes from \fIstream\fR's internal buffers with the transformation applied. If \fIcount\fR is omitted, the entire contents of the buffers are returned. . \fIstream \fBheader\fR . Return the gzip header description dictionary extracted from the stream. Only supported for streams created with their \fImode\fR parameter set to \fBgunzip\fR. .TP \fIstream \fBput\fR ?\fIoption...\fR? \fIdata\fR . Append the contents of the binary string \fIdata\fR to \fIstream\fR's internal buffers while applying the transformation. The following \fIoption\fRs are supported (or an unambiguous prefix of them), which are used to modify the way in which the transformation is applied: .RS .TP \fB\-dictionary\fI binData\fR .VS "TIP 400" Sets the compression dictionary to use when working with compressing or decompressing the data to be \fIbinData\fR. .VE .TP \fB\-finalize\fR . Mark the stream as finished, ensuring that all bytes have been wholly compressed or decompressed. For gzip streams, this also ensures that the footer is written to the stream. The stream will need to be reset before having more data written to it after this, though data can still be read out of the stream with the \fBget\fR subcommand. .RS .PP This option is mutually exclusive with the \fB\-flush\fR and \fB\-fullflush\fR options. .RE .TP \fB\-flush\fR . Ensure that a decompressor consuming the bytes that the current (compressing) stream is producing will be able to produce all the bytes that have been compressed so far, at some performance penalty. .RS .PP This option is mutually exclusive with the \fB\-finalize\fR and \fB\-fullflush\fR options. .RE .TP \fB\-fullflush\fR . Ensure that not only can a decompressor handle all the bytes produced so far (as with \fB\-flush\fR above) but also that it can restart from this point if it detects that the stream is partially corrupt. This incurs a substantial performance penalty. .RS .PP This option is mutually exclusive with the \fB\-finalize\fR and \fB\-flush\fR options. .RE .RE .TP \fIstream \fBreset\fR . Puts any stream, including those that have been finalized or that have reached eof, back into a state where it can process more data. Throws away all internally buffered data. .SH EXAMPLES .PP To compress a Tcl string, it should be first converted to a particular charset encoding since the \fBzlib\fR command always operates on binary strings. .PP .CS set binData [encoding convertto utf-8 $string] set compData [\fBzlib compress\fR $binData] .CE .PP When converting back, it is also important to reverse the charset encoding: .PP .CS set binData [\fBzlib decompress\fR $compData] set string [encoding convertfrom utf-8 $binData] .CE .PP The compression operation from above can also be done with streams, which is especially helpful when you want to accumulate the data by stages: .PP .CS set strm [\fBzlib stream\fR compress] $\fIstrm \fBput\fR [encoding convertto utf-8 $string] # ... $\fIstrm \fBfinalize\fR set compData [$\fIstrm \fBget\fR] $\fIstrm \fBclose\fR .CE .SH "SEE ALSO" binary(n), chan(n), encoding(n), Tcl_ZlibDeflate(3), RFC1950 \- RFC1952 .SH "KEYWORDS" compress, decompress, deflate, gzip, inflate, zlib '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/Preserve.30000644000175000017500000001072312663660065014216 0ustar sergeisergei'\" '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-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_Preserve 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_Preserve, Tcl_Release, Tcl_EventuallyFree \- avoid freeing storage while it is being used .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_Preserve\fR(\fIclientData\fR) .sp \fBTcl_Release\fR(\fIclientData\fR) .sp \fBTcl_EventuallyFree\fR(\fIclientData, freeProc\fR) .SH ARGUMENTS .AS Tcl_FreeProc clientData .AP ClientData clientData in Token describing structure to be freed or reallocated. Usually a pointer to memory for structure. .AP Tcl_FreeProc *freeProc in Procedure to invoke to free \fIclientData\fR. .BE .SH DESCRIPTION .PP These three procedures help implement a simple reference count mechanism for managing storage. They are designed to solve a problem having to do with widget deletion, but are also useful in many other situations. When a widget is deleted, its widget record (the structure holding information specific to the widget) must be returned to the storage allocator. However, it is possible that the widget record is in active use by one of the procedures on the stack at the time of the deletion. This can happen, for example, if the command associated with a button widget causes the button to be destroyed: an X event causes an event-handling C procedure in the button to be invoked, which in turn causes the button's associated Tcl command to be executed, which in turn causes the button to be deleted, which in turn causes the button's widget record to be de-allocated. Unfortunately, when the Tcl command returns, the button's event-handling procedure will need to reference the button's widget record. Because of this, the widget record must not be freed as part of the deletion, but must be retained until the event-handling procedure has finished with it. In other situations where the widget is deleted, it may be possible to free the widget record immediately. .PP \fBTcl_Preserve\fR and \fBTcl_Release\fR implement short-term reference counts for their \fIclientData\fR argument. The \fIclientData\fR argument identifies an object and usually consists of the address of a structure. The reference counts guarantee that an object will not be freed until each call to \fBTcl_Preserve\fR for the object has been matched by calls to \fBTcl_Release\fR. There may be any number of unmatched \fBTcl_Preserve\fR calls in effect at once. .PP \fBTcl_EventuallyFree\fR is invoked to free up its \fIclientData\fR argument. It checks to see if there are unmatched \fBTcl_Preserve\fR calls for the object. If not, then \fBTcl_EventuallyFree\fR calls \fIfreeProc\fR immediately. Otherwise \fBTcl_EventuallyFree\fR records the fact that \fIclientData\fR needs eventually to be freed. When all calls to \fBTcl_Preserve\fR have been matched with calls to \fBTcl_Release\fR then \fIfreeProc\fR will be called by \fBTcl_Release\fR to do the cleanup. .PP All the work of freeing the object is carried out by \fIfreeProc\fR. \fIFreeProc\fR must have arguments and result that match the type \fBTcl_FreeProc\fR: .PP .CS typedef void \fBTcl_FreeProc\fR( char *\fIblockPtr\fR); .CE .PP The \fIblockPtr\fR argument to \fIfreeProc\fR will be the same as the \fIclientData\fR argument to \fBTcl_EventuallyFree\fR. The type of \fIblockPtr\fR (\fBchar *\fR) is different than the type of the \fIclientData\fR argument to \fBTcl_EventuallyFree\fR for historical reasons, but the value is the same. .PP When the \fIclientData\fR argument to \fBTcl_EventuallyFree\fR refers to storage allocated and returned by a prior call to \fBTcl_Alloc\fR, \fBckalloc\fR, or another function of the Tcl library, then the \fIfreeProc\fR argument should be given the special value of \fBTCL_DYNAMIC\fR. .PP This mechanism can be used to solve the problem described above by placing \fBTcl_Preserve\fR and \fBTcl_Release\fR calls around actions that may cause undesired storage re-allocation. The mechanism is intended only for short-term use (i.e. while procedures are pending on the stack); it will not work efficiently as a mechanism for long-term reference counts. The implementation does not depend in any way on the internal structure of the objects being freed; it keeps the reference counts in a separate structure. .SH "SEE ALSO" Tcl_Interp, Tcl_Alloc .SH KEYWORDS free, reference count, storage tcl8.6.5/doc/AddErrInfo.30000644000175000017500000003272412663660065014405 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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_AddErrorInfo 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_GetReturnOptions, Tcl_SetReturnOptions, Tcl_AddErrorInfo, Tcl_AppendObjToErrorInfo, Tcl_AddObjErrorInfo, Tcl_SetObjErrorCode, Tcl_SetErrorCode, Tcl_SetErrorCodeVA, Tcl_SetErrorLine, Tcl_GetErrorLine, Tcl_PosixError, Tcl_LogCommandInfo \- retrieve or record information about errors and other return options .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * \fBTcl_GetReturnOptions\fR(\fIinterp, code\fR) .sp int \fBTcl_SetReturnOptions\fR(\fIinterp, options\fR) .sp \fBTcl_AddErrorInfo\fR(\fIinterp, message\fR) .sp \fBTcl_AppendObjToErrorInfo\fR(\fIinterp, objPtr\fR) .sp \fBTcl_AddObjErrorInfo\fR(\fIinterp, message, length\fR) .sp \fBTcl_SetObjErrorCode\fR(\fIinterp, errorObjPtr\fR) .sp \fBTcl_SetErrorCode\fR(\fIinterp, element, element, ... \fB(char *) NULL\fR) .sp \fBTcl_SetErrorCodeVA\fR(\fIinterp, argList\fR) .sp \fBTcl_GetErrorLine\fR(\fIinterp\fR) .sp \fBTcl_SetErrorLine\fR(\fIinterp, lineNum\fR) .sp const char * \fBTcl_PosixError\fR(\fIinterp\fR) .sp void \fBTcl_LogCommandInfo\fR(\fIinterp, script, command, commandLength\fR) .SH ARGUMENTS .AS Tcl_Interp commandLength .AP Tcl_Interp *interp in Interpreter in which to record information. .AP int code The code returned from script evaluation. .AP Tcl_Obj *options A dictionary of return options. .AP char *message in For \fBTcl_AddErrorInfo\fR, this is a conventional C string to append to the \fB\-errorinfo\fR return option. For \fBTcl_AddObjErrorInfo\fR, this points to the first byte of an array of \fIlength\fR bytes containing a string to append to the \fB\-errorinfo\fR return option. This byte array may contain embedded null bytes unless \fIlength\fR is negative. .AP Tcl_Obj *objPtr in A message to be appended to the \fB\-errorinfo\fR return option in the form of a Tcl_Obj value. .AP int length in The number of bytes to copy from \fImessage\fR when appending to the \fB\-errorinfo\fR return option. If negative, all bytes up to the first null byte are used. .AP Tcl_Obj *errorObjPtr in The \fB\-errorcode\fR return option will be set to this value. .AP char *element in String to record as one element of the \fB\-errorcode\fR return option. Last \fIelement\fR argument must be NULL. .AP va_list argList in An argument list which must have been initialized using \fBva_start\fR, and cleared using \fBva_end\fR. .AP int lineNum The line number of a script where an error occurred. .AP "const char" *script in Pointer to first character in script containing command (must be <= command) .AP "const char" *command in Pointer to first character in command that generated the error .AP int commandLength in Number of bytes in command; -1 means use all bytes up to first null byte .BE .SH DESCRIPTION .PP The \fBTcl_SetReturnOptions\fR and \fBTcl_GetReturnOptions\fR routines expose the same capabilities as the \fBreturn\fR and \fBcatch\fR commands, respectively, in the form of a C interface. .PP \fBTcl_GetReturnOptions\fR retrieves the dictionary of return options from an interpreter following a script evaluation. Routines such as \fBTcl_Eval\fR are called to evaluate a script in an interpreter. These routines return an integer completion code. These routines also leave in the interpreter both a result and a dictionary of return options generated by script evaluation. Just as \fBTcl_GetObjResult\fR retrieves the result, \fBTcl_GetReturnOptions\fR retrieves the dictionary of return options. The integer completion code should be passed as the \fIcode\fR argument to \fBTcl_GetReturnOptions\fR so that all required options will be present in the dictionary. Specifically, a \fIcode\fR value of \fBTCL_ERROR\fR will ensure that entries for the keys \fB\-errorinfo\fR, \fB\-errorcode\fR, and \fB\-errorline\fR will appear in the dictionary. Also, the entries for the keys \fB\-code\fR and \fB\-level\fR will be adjusted if necessary to agree with the value of \fIcode\fR. The \fB(Tcl_Obj *)\fR returned by \fBTcl_GetReturnOptions\fR points to an unshared \fBTcl_Obj\fR with reference count of zero. The dictionary may be written to, either adding, removing, or overwriting any entries in it, without the need to check for a shared value. As with any \fBTcl_Obj\fR with reference count of zero, it is up to the caller to arrange for its disposal with \fBTcl_DecrRefCount\fR or to a reference to it via \fBTcl_IncrRefCount\fR (or one of the many functions that call that, notably including \fBTcl_SetObjResult\fR and \fBTcl_SetVar2Ex\fR). .PP A typical usage for \fBTcl_GetReturnOptions\fR is to retrieve the stack trace when script evaluation returns \fBTCL_ERROR\fR, like so: .PP .CS int code = Tcl_Eval(interp, script); if (code == TCL_ERROR) { Tcl_Obj *options = \fBTcl_GetReturnOptions\fR(interp, code); Tcl_Obj *key = Tcl_NewStringObj("-errorinfo", -1); Tcl_Obj *stackTrace; Tcl_IncrRefCount(key); Tcl_DictObjGet(NULL, options, key, &stackTrace); Tcl_DecrRefCount(key); /* Do something with stackTrace */ Tcl_DecrRefCount(options); } .CE .PP \fBTcl_SetReturnOptions\fR sets the return options of \fIinterp\fR to be \fIoptions\fR. If \fIoptions\fR contains any invalid value for any key, TCL_ERROR will be returned, and the interp result will be set to an appropriate error message. Otherwise, a completion code in agreement with the \fB\-code\fR and \fB\-level\fR keys in \fIoptions\fR will be returned. .PP As an example, Tcl's \fBreturn\fR command itself could be implemented in terms of \fBTcl_SetReturnOptions\fR like so: .PP .CS if ((objc % 2) == 0) { /* explicit result argument */ objc--; Tcl_SetObjResult(interp, objv[objc]); } return \fBTcl_SetReturnOptions\fR(interp, Tcl_NewListObj(objc-1, objv+1)); .CE .PP (It is not really implemented that way. Internal access privileges allow for a more efficient alternative that meshes better with the bytecode compiler.) .PP Note that a newly created \fBTcl_Obj\fR may be passed in as the \fIoptions\fR argument without the need to tend to any reference counting. This is analogous to \fBTcl_SetObjResult\fR. .PP While \fBTcl_SetReturnOptions\fR provides a general interface to set any collection of return options, there are a handful of return options that are very frequently used. Most notably the \fB\-errorinfo\fR and \fB\-errorcode\fR return options should be set properly when the command procedure of a command returns \fBTCL_ERROR\fR. The \fB\-errorline\fR return option is also read by commands that evaluate scripts and wish to supply detailed error location information in the stack trace text they append to the \fB\-errorinfo\fR option. Tcl provides several simpler interfaces to more directly set these return options. .PP The \fB\-errorinfo\fR option holds a stack trace of the operations that were in progress when an error occurred, and is intended to be human-readable. The \fB\-errorcode\fR option holds a Tcl list of items that are intended to be machine-readable. The first item in the \fB\-errorcode\fR value identifies the class of error that occurred (e.g., POSIX means an error occurred in a POSIX system call) and additional elements hold additional pieces of information that depend on the class. See the manual entry on the \fBerrorCode\fR variable for details on the various formats for the \fB\-errorcode\fR option used by Tcl's built-in commands. .PP The \fB\-errorinfo\fR option value is gradually built up as an error unwinds through the nested operations. Each time an error code is returned to \fBTcl_Eval\fR, or any of the routines that performs script evaluation, the procedure \fBTcl_AddErrorInfo\fR is called to add additional text to the \fB\-errorinfo\fR value describing the command that was being executed when the error occurred. By the time the error has been passed all the way back to the application, it will contain a complete trace of the activity in progress when the error occurred. .PP It is sometimes useful to add additional information to the \fB\-errorinfo\fR value beyond what can be supplied automatically by the script evaluation routines. \fBTcl_AddErrorInfo\fR may be used for this purpose: its \fImessage\fR argument is an additional string to be appended to the \fB\-errorinfo\fR option. For example, when an error arises during the \fBsource\fR command, the procedure \fBTcl_AddErrorInfo\fR is called to record the name of the file being processed and the line number on which the error occurred. Likewise, when an error arises during evaluation of a Tcl procedures, the procedure name and line number within the procedure are recorded, and so on. The best time to call \fBTcl_AddErrorInfo\fR is just after a script evaluation routine has returned \fBTCL_ERROR\fR. The value of the \fB\-errorline\fR return option (retrieved via a call to \fBTcl_GetReturnOptions\fR) often makes up a useful part of the \fImessage\fR passed to \fBTcl_AddErrorInfo\fR. .PP \fBTcl_AppendObjToErrorInfo\fR is an alternative interface to the same functionality as \fBTcl_AddErrorInfo\fR. \fBTcl_AppendObjToErrorInfo\fR is called when the string value to be appended to the \fB\-errorinfo\fR option is available as a \fBTcl_Obj\fR instead of as a \fBchar\fR array. .PP \fBTcl_AddObjErrorInfo\fR is nearly identical to \fBTcl_AddErrorInfo\fR, except that it has an additional \fIlength\fR argument. This allows the \fImessage\fR string to contain embedded null bytes. This is essentially never a good idea. If the \fImessage\fR needs to contain the null character \fBU+0000\fR, Tcl's usual internal encoding rules should be used to avoid the need for a null byte. If the \fBTcl_AddObjErrorInfo\fR interface is used at all, it should be with a negative \fIlength\fR value. .PP The procedure \fBTcl_SetObjErrorCode\fR is used to set the \fB\-errorcode\fR return option to the list value \fIerrorObjPtr\fR built up by the caller. \fBTcl_SetObjErrorCode\fR is typically invoked just before returning an error. If an error is returned without calling \fBTcl_SetObjErrorCode\fR or \fBTcl_SetErrorCode\fR the Tcl interpreter automatically sets the \fB\-errorcode\fR return option to \fBNONE\fR. .PP The procedure \fBTcl_SetErrorCode\fR is also used to set the \fB\-errorcode\fR return option. However, it takes one or more strings to record instead of a value. Otherwise, it is similar to \fBTcl_SetObjErrorCode\fR in behavior. .PP \fBTcl_SetErrorCodeVA\fR is the same as \fBTcl_SetErrorCode\fR except that instead of taking a variable number of arguments it takes an argument list. .PP The procedure \fBTcl_GetErrorLine\fR is used to read the integer value of the \fB\-errorline\fR return option without the overhead of a full call to \fBTcl_GetReturnOptions\fR. Likewise, \fBTcl_SetErrorLine\fR sets the \fB\-errorline\fR return option value. .PP \fBTcl_PosixError\fR sets the \fB\-errorcode\fR variable after an error in a POSIX kernel call. It reads the value of the \fBerrno\fR C variable and calls \fBTcl_SetErrorCode\fR to set the \fB\-errorcode\fR return option in the \fBPOSIX\fR format. The caller must previously have called \fBTcl_SetErrno\fR to set \fBerrno\fR; this is necessary on some platforms (e.g. Windows) where Tcl is linked into an application as a shared library, or when the error occurs in a dynamically loaded extension. See the manual entry for \fBTcl_SetErrno\fR for more information. .PP \fBTcl_PosixError\fR returns a human-readable diagnostic message for the error (this is the same value that will appear as the third element in the \fB\-errorcode\fR value). It may be convenient to include this string as part of the error message returned to the application in the interpreter's result. .PP \fBTcl_LogCommandInfo\fR is invoked after an error occurs in an interpreter. It adds information about the command that was being executed when the error occurred to the \fB\-errorinfo\fR value, and the line number stored internally in the interpreter is set. .PP In older releases of Tcl, there was no \fBTcl_GetReturnOptions\fR routine. In its place, the global Tcl variables \fBerrorInfo\fR and \fBerrorCode\fR were the only place to retrieve the error information. Much existing code written for older Tcl releases still access this information via those global variables. .PP It is important to realize that while reading from those global variables remains a supported way to access these return option values, it is important not to assume that writing to those global variables will properly set the corresponding return options. It has long been emphasized in this manual page that it is important to call the procedures described here rather than setting \fBerrorInfo\fR or \fBerrorCode\fR directly with \fBTcl_ObjSetVar2\fR. .PP If the procedure \fBTcl_ResetResult\fR is called, it clears all of the state of the interpreter associated with script evaluation, including the entire return options dictionary. In particular, the \fB\-errorinfo\fR and \fB\-errorcode\fR options are reset. If an error had occurred, the \fBTcl_ResetResult\fR call will clear the error state to make it appear as if no error had occurred after all. The global variables \fBerrorInfo\fR and \fBerrorCode\fR are not modified by \fBTcl_ResetResult\fR so they continue to hold a record of information about the most recent error seen in an interpreter. .SH "SEE ALSO" Tcl_DecrRefCount(3), Tcl_IncrRefCount(3), Tcl_Interp(3), Tcl_ResetResult(3), Tcl_SetErrno(3), errorCode(n), errorInfo(n) .SH KEYWORDS error, value, value result, stack, trace, variable tcl8.6.5/doc/close.n0000644000175000017500000001041212663660065013616 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 close n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME close \- Close an open channel .SH SYNOPSIS \fBclose \fIchannelId\fR ?r(ead)|w(rite)? .BE .SH DESCRIPTION .PP Closes or half-closes the channel given by \fIchannelId\fR. .PP \fIChannelId\fR must be an identifier for an open channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. .PP The single-argument form is a simple .QW "full-close" : all buffered output is flushed to the channel's output device, any buffered input is discarded, the underlying file or device is closed, and \fIchannelId\fR becomes unavailable for use. .PP If the channel is blocking, the command does not return until all output is flushed. If the channel is nonblocking and there is unflushed output, the channel remains open and the command returns immediately; output will be flushed in the background and the channel will be closed when all the flushing is complete. .PP If \fIchannelId\fR is a blocking channel for a command pipeline then \fBclose\fR waits for the child processes to complete. .PP If the channel is shared between interpreters, then \fBclose\fR makes \fIchannelId\fR unavailable in the invoking interpreter but has no other effect until all of the sharing interpreters have closed the channel. When the last interpreter in which the channel is registered invokes \fBclose\fR, the cleanup actions described above occur. See the \fBinterp\fR command for a description of channel sharing. .PP Channels are automatically closed when an interpreter is destroyed and when the process exits. .VS 8.6 From 8.6 on (TIP#398), nonblocking channels are no longer switched to blocking mode when exiting; this guarantees a timely exit even when the peer or a communication channel is stalled. To ensure proper flushing of stalled nonblocking channels on exit, one must now either (a) actively switch them back to blocking or (b) use the environment variable TCL_FLUSH_NONBLOCKING_ON_EXIT, which when set and not equal to "0" restores the previous behavior. .VE 8.6 .PP The command returns an empty string, and may generate an error if an error occurs while flushing output. If a command in a command pipeline created with \fBopen\fR returns an error, \fBclose\fR generates an error (similar to the \fBexec\fR command.) .PP .VS 8.6 The two-argument form is a .QW "half-close" : given a bidirectional channel like a socket or command pipeline and a (possibly abbreviated) direction, it closes only the sub-stream going in that direction. This means a shutdown() on a socket, and a close() of one end of a pipe for a command pipeline. Then, the Tcl-level channel data structure is either kept or freed depending on whether the other direction is still open. .PP A single-argument close on an already half-closed bidirectional channel is defined to just .QW "finish the job" . A half-close on an already closed half, or on a wrong-sided unidirectional channel, raises an error. .PP In the case of a command pipeline, the child-reaping duty falls upon the shoulders of the last close or half-close, which is thus allowed to report an abnormal exit error. .PP Currently only sockets and command pipelines support half-close. A future extension will allow reflected and stacked channels to do so. .VE 8.6 .SH EXAMPLE .PP This illustrates how you can use Tcl to ensure that files get closed even when errors happen by combining \fBcatch\fR, \fBclose\fR and \fBreturn\fR: .PP .CS proc withOpenFile {filename channelVar script} { upvar 1 $channelVar chan set chan [open $filename] catch { uplevel 1 $script } result options \fBclose\fR $chan return -options $options $result } .CE .SH "SEE ALSO" file(n), open(n), socket(n), eof(n), Tcl_StandardChannels(3) .SH KEYWORDS blocking, channel, close, nonblocking, half-close '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/dict.n0000644000175000017500000004473212663660065013450 0ustar sergeisergei'\" '\" Copyright (c) 2003 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH dict n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME dict \- Manipulate dictionaries .SH SYNOPSIS \fBdict \fIoption arg \fR?\fIarg ...\fR? .BE .SH DESCRIPTION .PP Performs one of several operations on dictionary values or variables containing dictionary values (see the \fBDICTIONARY VALUES\fR section below for a description), depending on \fIoption\fR. The legal \fIoption\fRs (which may be abbreviated) are: .TP \fBdict append \fIdictionaryVariable key \fR?\fIstring ...\fR? . This appends the given string (or strings) to the value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to an empty string. The updated dictionary value is returned. .TP \fBdict create \fR?\fIkey value ...\fR? . Return a new dictionary that contains each of the key/value mappings listed as arguments (keys and values alternating, with each key being followed by its associated value.) .TP \fBdict exists \fIdictionaryValue key \fR?\fIkey ...\fR? . This returns a boolean value indicating whether the given key (or path of keys through a set of nested dictionaries) exists in the given dictionary value. This returns a true value exactly when \fBdict get\fR on that path will succeed. .TP \fBdict filter \fIdictionaryValue filterType arg \fR?\fIarg ...\fR? . This takes a dictionary value and returns a new dictionary that contains just those key/value pairs that match the specified filter type (which may be abbreviated.) Supported filter types are: .RS .TP \fBdict filter \fIdictionaryValue \fBkey\fR ?\fIglobPattern ...\fR? .VS 8.6 The key rule only matches those key/value pairs whose keys match any of the given patterns (in the style of \fBstring match\fR.) .VE 8.6 .TP \fBdict filter \fIdictionaryValue \fBscript {\fIkeyVariable valueVariable\fB} \fIscript\fR . The script rule tests for matching by assigning the key to the \fIkeyVariable\fR and the value to the \fIvalueVariable\fR, and then evaluating the given script which should return a boolean value (with the key/value pair only being included in the result of the \fBdict filter\fR when a true value is returned.) Note that the first argument after the rule selection word is a two-element list. If the \fIscript\fR returns with a condition of \fBTCL_BREAK\fR, no further key/value pairs are considered for inclusion in the resulting dictionary, and a condition of \fBTCL_CONTINUE\fR is equivalent to a false result. The key/value pairs are tested in the order in which the keys were inserted into the dictionary. .TP \fBdict filter \fIdictionaryValue \fBvalue \fR?\fIglobPattern ...\fR? .VS 8.6 The value rule only matches those key/value pairs whose values match any of the given patterns (in the style of \fBstring match\fR.) .VE 8.6 .RE .TP \fBdict for {\fIkeyVariable valueVariable\fB} \fIdictionaryValue body\fR . This command takes three arguments, the first a two-element list of variable names (for the key and value respectively of each mapping in the dictionary), the second the dictionary value to iterate across, and the third a script to be evaluated for each mapping with the key and value variables set appropriately (in the manner of \fBforeach\fR.) The result of the command is an empty string. If any evaluation of the body generates a \fBTCL_BREAK\fR result, no further pairs from the dictionary will be iterated over and the \fBdict for\fR command will terminate successfully immediately. If any evaluation of the body generates a \fBTCL_CONTINUE\fR result, this shall be treated exactly like a normal \fBTCL_OK\fR result. The order of iteration is the order in which the keys were inserted into the dictionary. .TP \fBdict get \fIdictionaryValue \fR?\fIkey ...\fR? . Given a dictionary value (first argument) and a key (second argument), this will retrieve the value for that key. Where several keys are supplied, the behaviour of the command shall be as if the result of \fBdict get $dictVal $key\fR was passed as the first argument to \fBdict get\fR with the remaining arguments as second (and possibly subsequent) arguments. This facilitates lookups in nested dictionaries. For example, the following two commands are equivalent: .RS .PP .CS dict get $dict foo bar spong dict get [dict get [dict get $dict foo] bar] spong .CE .PP If no keys are provided, \fBdict get\fR will return a list containing pairs of elements in a manner similar to \fBarray get\fR. That is, the first element of each pair would be the key and the second element would be the value for that key. .PP It is an error to attempt to retrieve a value for a key that is not present in the dictionary. .RE .TP \fBdict incr \fIdictionaryVariable key \fR?\fIincrement\fR? . This adds the given increment value (an integer that defaults to 1 if not specified) to the value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to 0. It is an error to increment a value for an existing key if that value is not an integer. The updated dictionary value is returned. .TP \fBdict info \fIdictionaryValue\fR . This returns information (intended for display to people) about the given dictionary though the format of this data is dependent on the implementation of the dictionary. For dictionaries that are implemented by hash tables, it is expected that this will return the string produced by \fBTcl_HashStats\fR, similar to \fBarray statistics\fR. .TP \fBdict keys \fIdictionaryValue \fR?\fIglobPattern\fR? . Return a list of all keys in the given dictionary value. If a pattern is supplied, only those keys that match it (according to the rules of \fBstring match\fR) will be returned. The returned keys will be in the order that they were inserted into the dictionary. .TP \fBdict lappend \fIdictionaryVariable key \fR?\fIvalue ...\fR? . This appends the given items to the list value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to an empty list, and it is legal for there to be no items to append to the list. It is an error for the value that the key maps to to not be representable as a list. The updated dictionary value is returned. .TP \fBdict map \fR{\fIkeyVariable valueVariable\fR} \fIdictionaryValue body\fR . This command applies a transformation to each element of a dictionary, returning a new dictionary. It takes three arguments: the first is a two-element list of variable names (for the key and value respectively of each mapping in the dictionary), the second the dictionary value to iterate across, and the third a script to be evaluated for each mapping with the key and value variables set appropriately (in the manner of \fBlmap\fR). In an iteration where the evaluated script completes normally (\fBTCL_OK\fR, as opposed to an \fBerror\fR, etc.) the result of the script is put into an accumulator dictionary using the key that is the current contents of the \fIkeyVariable\fR variable at that point. The result of the \fBdict map\fR command is the accumulator dictionary after all keys have been iterated over. .RS .PP If the evaluation of the body for any particular step generates a \fBbreak\fR, no further pairs from the dictionary will be iterated over and the \fBdict map\fR command will terminate successfully immediately. If the evaluation of the body for a particular step generates a \fBcontinue\fR result, the current iteration is aborted and the accumulator dictionary is not modified. The order of iteration is the natural order of the dictionary (typically the order in which the keys were added to the dictionary; the order is the same as that used in \fBdict for\fR). .RE .TP \fBdict merge \fR?\fIdictionaryValue ...\fR? . Return a dictionary that contains the contents of each of the \fIdictionaryValue\fR arguments. Where two (or more) dictionaries contain a mapping for the same key, the resulting dictionary maps that key to the value according to the last dictionary on the command line containing a mapping for that key. .TP \fBdict remove \fIdictionaryValue \fR?\fIkey ...\fR? . Return a new dictionary that is a copy of an old one passed in as first argument except without mappings for each of the keys listed. It is legal for there to be no keys to remove, and it also legal for any of the keys to be removed to not be present in the input dictionary in the first place. .TP \fBdict replace \fIdictionaryValue \fR?\fIkey value ...\fR? . Return a new dictionary that is a copy of an old one passed in as first argument except with some values different or some extra key/value pairs added. It is legal for this command to be called with no key/value pairs, but illegal for this command to be called with a key but no value. .TP \fBdict set \fIdictionaryVariable key \fR?\fIkey ...\fR? \fIvalue\fR . This operation takes the name of a variable containing a dictionary value and places an updated dictionary value in that variable containing a mapping from the given key to the given value. When multiple keys are present, this operation creates or updates a chain of nested dictionaries. The updated dictionary value is returned. .TP \fBdict size \fIdictionaryValue\fR . Return the number of key/value mappings in the given dictionary value. .TP \fBdict unset \fIdictionaryVariable key \fR?\fIkey ...\fR? . This operation (the companion to \fBdict set\fR) takes the name of a variable containing a dictionary value and places an updated dictionary value in that variable that does not contain a mapping for the given key. Where multiple keys are present, this describes a path through nested dictionaries to the mapping to remove. At least one key must be specified, but the last key on the key-path need not exist. All other components on the path must exist. The updated dictionary value is returned. .TP \fBdict update \fIdictionaryVariable key varName \fR?\fIkey varName ...\fR? \fIbody\fR . Execute the Tcl script in \fIbody\fR with the value for each \fIkey\fR (as found by reading the dictionary value in \fIdictionaryVariable\fR) mapped to the variable \fIvarName\fR. There may be multiple \fIkey\fR/\fIvarName\fR pairs. If a \fIkey\fR does not have a mapping, that corresponds to an unset \fIvarName\fR. When \fIbody\fR terminates, any changes made to the \fIvarName\fRs is reflected back to the dictionary within \fIdictionaryVariable\fR (unless \fIdictionaryVariable\fR itself becomes unreadable, when all updates are silently discarded), even if the result of \fIbody\fR is an error or some other kind of exceptional exit. The result of \fBdict update\fR is (unless some kind of error occurs) the result of the evaluation of \fIbody\fR. .RS .PP Each \fIvarName\fR is mapped in the scope enclosing the \fBdict update\fR; it is recommended that this command only be used in a local scope (\fBproc\fRedure, lambda term for \fBapply\fR, or method). Because of this, the variables set by \fBdict update\fR will continue to exist after the command finishes (unless explicitly \fBunset\fR). Note that the mapping of values to variables does not use traces; changes to the \fIdictionaryVariable\fR's contents only happen when \fIbody\fR terminates. .RE .TP \fBdict values \fIdictionaryValue \fR?\fIglobPattern\fR? . Return a list of all values in the given dictionary value. If a pattern is supplied, only those values that match it (according to the rules of \fBstring match\fR) will be returned. The returned values will be in the order of that the keys associated with those values were inserted into the dictionary. .TP \fBdict with \fIdictionaryVariable \fR?\fIkey ...\fR? \fIbody\fR . Execute the Tcl script in \fIbody\fR with the value for each key in \fIdictionaryVariable\fR mapped (in a manner similarly to \fBdict update\fR) to a variable with the same name. Where one or more \fIkey\fRs are available, these indicate a chain of nested dictionaries, with the innermost dictionary being the one opened out for the execution of \fIbody\fR. As with \fBdict update\fR, making \fIdictionaryVariable\fR unreadable will make the updates to the dictionary be discarded, and this also happens if the contents of \fIdictionaryVariable\fR are adjusted so that the chain of dictionaries no longer exists. The result of \fBdict with\fR is (unless some kind of error occurs) the result of the evaluation of \fIbody\fR. .RS .PP The variables are mapped in the scope enclosing the \fBdict with\fR; it is recommended that this command only be used in a local scope (\fBproc\fRedure, lambda term for \fBapply\fR, or method). Because of this, the variables set by \fBdict with\fR will continue to exist after the command finishes (unless explicitly \fBunset\fR). Note that the mapping of values to variables does not use traces; changes to the \fIdictionaryVariable\fR's contents only happen when \fIbody\fR terminates. .PP If the \fIdictionaryVariable\fR contains a value that is not a dictionary at the point when the \fIbody\fR terminates (which can easily happen if the name is the same as any of the keys in dictionary) then an error occurs at that point. This command is thus not recommended for use when the keys in the dictionary are expected to clash with the \fIdictionaryVariable\fR name itself. Where the contained key does map to a dictionary, the net effect is to combine that inner dictionary into the outer dictionary; see the \fBEXAMPLES\fR below for an illustration of this. .RE .SH "DICTIONARY VALUES" .PP Dictionaries are values that contain an efficient, order-preserving mapping from arbitrary keys to arbitrary values. Each key in the dictionary maps to a single value. They have a textual format that is exactly that of any list with an even number of elements, with each mapping in the dictionary being represented as two items in the list. When a command takes a dictionary and produces a new dictionary based on it (either returning it or writing it back into the variable that the starting dictionary was read from) the new dictionary will have the same order of keys, modulo any deleted keys and with new keys added on to the end. When a string is interpreted as a dictionary and it would otherwise have duplicate keys, only the last value for a particular key is used; the others are ignored, meaning that, .QW "apple banana" and .QW "apple carrot apple banana" are equivalent dictionaries (with different string representations). .PP Operations that derive a new dictionary from an old one (e.g., updates like \fBdict set\fR and \fBdict unset\fR) preserve the order of keys in the dictionary. The exceptions to this are for any new keys they add, which are appended to the sequence, and any keys that are removed, which are excised from the order. .SH EXAMPLES .PP Basic dictionary usage: .PP .CS # Make a dictionary to map extensions to descriptions set filetypes [\fBdict create\fR .txt "Text File" .tcl "Tcl File"] # Add/update the dictionary \fBdict set\fR filetypes .tcl "Tcl Script" \fBdict set\fR filetypes .tm "Tcl Module" \fBdict set\fR filetypes .gif "GIF Image" \fBdict set\fR filetypes .png "PNG Image" # Simple read from the dictionary set ext ".tcl" set desc [\fBdict get\fR $filetypes $ext] puts "$ext is for a $desc" # Somewhat more complex, with existence test foreach filename [glob *] { set ext [file extension $filename] if {[\fBdict exists\fR $filetypes $ext]} { puts "$filename is a [\fBdict get\fR $filetypes $ext]" } } .CE .PP Constructing and using nested dictionaries: .PP .CS # Data for one employee \fBdict set\fR employeeInfo 12345-A forenames "Joe" \fBdict set\fR employeeInfo 12345-A surname "Schmoe" \fBdict set\fR employeeInfo 12345-A street "147 Short Street" \fBdict set\fR employeeInfo 12345-A city "Springfield" \fBdict set\fR employeeInfo 12345-A phone "555-1234" # Data for another employee \fBdict set\fR employeeInfo 98372-J forenames "Anne" \fBdict set\fR employeeInfo 98372-J surname "Other" \fBdict set\fR employeeInfo 98372-J street "32995 Oakdale Way" \fBdict set\fR employeeInfo 98372-J city "Springfield" \fBdict set\fR employeeInfo 98372-J phone "555-8765" # The above data probably ought to come from a database... # Print out some employee info set i 0 puts "There are [\fBdict size\fR $employeeInfo] employees" \fBdict for\fR {id info} $employeeInfo { puts "Employee #[incr i]: $id" \fBdict with\fR info { puts " Name: $forenames $surname" puts " Address: $street, $city" puts " Telephone: $phone" } } # Another way to iterate and pick out names... foreach id [\fBdict keys\fR $employeeInfo] { puts "Hello, [\fBdict get\fR $employeeInfo $id forenames]!" } .CE .PP A localizable version of \fBstring toupper\fR: .PP .CS # Set up the basic C locale set capital [\fBdict create\fR C [\fBdict create\fR]] foreach c [split {abcdefghijklmnopqrstuvwxyz} ""] { \fBdict set\fR capital C $c [string toupper $c] } # English locales can luckily share the "C" locale \fBdict set\fR capital en [\fBdict get\fR $capital C] \fBdict set\fR capital en_US [\fBdict get\fR $capital C] \fBdict set\fR capital en_GB [\fBdict get\fR $capital C] # ... and so on for other supported languages ... # Now get the mapping for the current locale and use it. set upperCaseMap [\fBdict get\fR $capital $env(LANG)] set upperCase [string map $upperCaseMap $string] .CE .PP Showing the detail of \fBdict with\fR: .PP .CS proc sumDictionary {varName} { upvar 1 $varName vbl foreach key [\fBdict keys\fR $vbl] { # Manufacture an entry in the subdictionary \fBdict set\fR vbl $key total 0 # Add the values and remove the old \fBdict with\fR vbl $key { set total [expr {$x + $y + $z}] unset x y z } } puts "last total was $total, for key $key" } set myDict { a {x 1 y 2 z 3} b {x 6 y 5 z 4} } sumDictionary myDict # prints: \fIlast total was 15, for key b\fR puts "dictionary is now \\"$myDict\\"" # prints: \fIdictionary is now "a {total 6} b {total 15}"\fR .CE .PP When \fBdict with\fR is used with a key that clashes with the name of the dictionary variable: .PP .CS set foo {foo {a b} bar 2 baz 3} \fBdict with\fR foo {} puts $foo # prints: \fIa b foo {a b} bar 2 baz 3\fR .CE .SH "SEE ALSO" append(n), array(n), foreach(n), mapeach(n), incr(n), list(n), lappend(n), set(n) .SH KEYWORDS dictionary, create, update, lookup, iterate, filter, map '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/WrongNumArgs.30000644000175000017500000000550012663660065015011 0ustar sergeisergei'\" '\" Copyright (c) 1994-1997 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_WrongNumArgs 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_WrongNumArgs \- generate standard error message for wrong number of arguments .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_WrongNumArgs\fR(\fIinterp, objc, objv, message\fR) .SH ARGUMENTS .AS "Tcl_Obj *const" *message .AP Tcl_Interp interp in Interpreter in which error will be reported: error message gets stored in its result value. .AP int objc in Number of leading arguments from \fIobjv\fR to include in error message. .AP "Tcl_Obj *const" objv[] in Arguments to command that had the wrong number of arguments. .AP "const char" *message in Additional error information to print after leading arguments from \fIobjv\fR. This typically gives the acceptable syntax of the command. This argument may be NULL. .BE .SH DESCRIPTION .PP \fBTcl_WrongNumArgs\fR is a utility procedure that is invoked by command procedures when they discover that they have received the wrong number of arguments. \fBTcl_WrongNumArgs\fR generates a standard error message and stores it in the result value of \fIinterp\fR. The message includes the \fIobjc\fR initial elements of \fIobjv\fR plus \fImessage\fR. For example, if \fIobjv\fR consists of the values \fBfoo\fR and \fBbar\fR, \fIobjc\fR is 1, and \fImessage\fR is .QW "\fBfileName count\fR" then \fIinterp\fR's result value will be set to the following string: .PP .CS wrong # args: should be "foo fileName count" .CE .PP If \fIobjc\fR is 2, the result will be set to the following string: .PP .CS wrong # args: should be "foo bar fileName count" .CE .PP \fIObjc\fR is usually 1, but may be 2 or more for commands like \fBstring\fR and the Tk widget commands, which use the first argument as a subcommand. .PP Some of the values in the \fIobjv\fR array may be abbreviations for a subcommand. The command \fBTcl_GetIndexFromObj\fR will convert the abbreviated string value into an \fIindexObject\fR. If an error occurs in the parsing of the subcommand we would like to use the full subcommand name rather than the abbreviation. If the \fBTcl_WrongNumArgs\fR command finds any \fIindexObjects\fR in the \fIobjv\fR array it will use the full subcommand name in the error message instead of the abbreviated name that was originally passed in. Using the above example, let us assume that \fIbar\fR is actually an abbreviation for \fIbarfly\fR and the value is now an \fIindexObject\fR because it was passed to \fBTcl_GetIndexFromObj\fR. In this case the error message would be: .PP .CS wrong # args: should be "foo barfly fileName count" .CE .SH "SEE ALSO" Tcl_GetIndexFromObj(3) .SH KEYWORDS command, error message, wrong number of arguments tcl8.6.5/doc/after.n0000644000175000017500000001272412663660065013622 0ustar sergeisergei'\" '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-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 after n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME after \- Execute a command after a time delay .SH SYNOPSIS \fBafter \fIms\fR .sp \fBafter \fIms \fR?\fIscript script script ...\fR? .sp \fBafter cancel \fIid\fR .sp \fBafter cancel \fIscript script script ...\fR .sp \fBafter idle \fR?\fIscript script script ...\fR? .sp \fBafter info \fR?\fIid\fR? .BE .SH DESCRIPTION .PP This command is used to delay execution of the program or to execute a command in background sometime in the future. It has several forms, depending on the first argument to the command: .TP \fBafter \fIms\fR . \fIMs\fR must be an integer giving a time in milliseconds. The command sleeps for \fIms\fR milliseconds and then returns. While the command is sleeping the application does not respond to events. .TP \fBafter \fIms \fR?\fIscript script script ...\fR? . In this form the command returns immediately, but it arranges for a Tcl command to be executed \fIms\fR milliseconds later as an event handler. The command will be executed exactly once, at the given time. The delayed command is formed by concatenating all the \fIscript\fR arguments in the same fashion as the \fBconcat\fR command. The command will be executed at global level (outside the context of any Tcl procedure). If an error occurs while executing the delayed command then the background error will be reported by the command registered with \fBinterp bgerror\fR. The \fBafter\fR command returns an identifier that can be used to cancel the delayed command using \fBafter cancel\fR. .TP \fBafter cancel \fIid\fR . Cancels the execution of a delayed command that was previously scheduled. \fIId\fR indicates which command should be canceled; it must have been the return value from a previous \fBafter\fR command. If the command given by \fIid\fR has already been executed then the \fBafter cancel\fR command has no effect. .TP \fBafter cancel \fIscript script ...\fR . This command also cancels the execution of a delayed command. The \fIscript\fR arguments are concatenated together with space separators (just as in the \fBconcat\fR command). If there is a pending command that matches the string, it is canceled and will never be executed; if no such command is currently pending then the \fBafter cancel\fR command has no effect. .TP \fBafter idle \fIscript \fR?\fIscript script ...\fR? . Concatenates the \fIscript\fR arguments together with space separators (just as in the \fBconcat\fR command), and arranges for the resulting script to be evaluated later as an idle callback. The script will be run exactly once, the next time the event loop is entered and there are no events to process. The command returns an identifier that can be used to cancel the delayed command using \fBafter cancel\fR. If an error occurs while executing the script then the background error will be reported by the command registered with \fBinterp bgerror\fR. .TP \fBafter info \fR?\fIid\fR? . This command returns information about existing event handlers. If no \fIid\fR argument is supplied, the command returns a list of the identifiers for all existing event handlers created by the \fBafter\fR command for this interpreter. If \fIid\fR is supplied, it specifies an existing handler; \fIid\fR must have been the return value from some previous call to \fBafter\fR and it must not have triggered yet or been canceled. In this case the command returns a list with two elements. The first element of the list is the script associated with \fIid\fR, and the second element is either \fBidle\fR or \fBtimer\fR to indicate what kind of event handler it is. .LP The \fBafter \fIms\fR and \fBafter idle\fR forms of the command assume that the application is event driven: the delayed commands will not be executed unless the application enters the event loop. In applications that are not normally event-driven, such as \fBtclsh\fR, the event loop can be entered with the \fBvwait\fR and \fBupdate\fR commands. .SH "EXAMPLES" This defines a command to make Tcl do nothing at all for \fIN\fR seconds: .PP .CS proc sleep {N} { \fBafter\fR [expr {int($N * 1000)}] } .CE .PP This arranges for the command \fIwake_up\fR to be run in eight hours (providing the event loop is active at that time): .PP .CS \fBafter\fR [expr {1000 * 60 * 60 * 8}] wake_up .CE .PP The following command can be used to do long-running calculations (as represented here by \fI::my_calc::one_step\fR, which is assumed to return a boolean indicating whether another step should be performed) in a step-by-step fashion, though the calculation itself needs to be arranged so it can work step-wise. This technique is extra careful to ensure that the event loop is not starved by the rescheduling of processing steps (arranging for the next step to be done using an already-triggered timer event only when the event queue has been drained) and is useful when you want to ensure that a Tk GUI remains responsive during a slow task. .PP .CS proc doOneStep {} { if {[::my_calc::one_step]} { \fBafter idle\fR [list \fBafter\fR 0 doOneStep] } } doOneStep .CE .SH "SEE ALSO" concat(n), interp(n), update(n), vwait(n) .SH KEYWORDS cancel, delay, idle callback, sleep, time '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/DetachPids.30000644000175000017500000000601112663660065014426 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_DetachPids 3 "" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_DetachPids, Tcl_ReapDetachedProcs, Tcl_WaitPid \- manage child processes in background .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_DetachPids\fR(\fInumPids, pidPtr\fR) .sp \fBTcl_ReapDetachedProcs\fR() .sp Tcl_Pid \fBTcl_WaitPid\fR(\fIpid, statusPtr, options\fR) .SH ARGUMENTS .AS Tcl_Pid *statusPtr out .AP int numPids in Number of process ids contained in the array pointed to by \fIpidPtr\fR. .AP int *pidPtr in Address of array containing \fInumPids\fR process ids. .AP Tcl_Pid pid in The id of the process (pipe) to wait for. .AP int *statusPtr out The result of waiting on a process (pipe). Either 0 or ECHILD. .AP int options in The options controlling the wait. WNOHANG specifies not to wait when checking the process. .BE .SH DESCRIPTION .PP \fBTcl_DetachPids\fR and \fBTcl_ReapDetachedProcs\fR provide a mechanism for managing subprocesses that are running in background. These procedures are needed because the parent of a process must eventually invoke the \fBwaitpid\fR kernel call (or one of a few other similar kernel calls) to wait for the child to exit. Until the parent waits for the child, the child's state cannot be completely reclaimed by the system. If a parent continually creates children and doesn't wait on them, the system's process table will eventually overflow, even if all the children have exited. .PP \fBTcl_DetachPids\fR may be called to ask Tcl to take responsibility for one or more processes whose process ids are contained in the \fIpidPtr\fR array passed as argument. The caller presumably has started these processes running in background and does not want to have to deal with them again. .PP \fBTcl_ReapDetachedProcs\fR invokes the \fBwaitpid\fR kernel call on each of the background processes so that its state can be cleaned up if it has exited. If the process has not exited yet, \fBTcl_ReapDetachedProcs\fR does not wait for it to exit; it will check again the next time it is invoked. Tcl automatically calls \fBTcl_ReapDetachedProcs\fR each time the \fBexec\fR command is executed, so in most cases it is not necessary for any code outside of Tcl to invoke \fBTcl_ReapDetachedProcs\fR. However, if you call \fBTcl_DetachPids\fR in situations where the \fBexec\fR command may never get executed, you may wish to call \fBTcl_ReapDetachedProcs\fR from time to time so that background processes can be cleaned up. .PP \fBTcl_WaitPid\fR is a thin wrapper around the facilities provided by the operating system to wait on the end of a spawned process and to check a whether spawned process is still running. It is used by \fBTcl_ReapDetachedProcs\fR and the channel system to portably access the operating system. .SH KEYWORDS background, child, detach, process, wait tcl8.6.5/doc/while.n0000644000175000017500000000424312663660065013626 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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 while n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME while \- Execute script repeatedly as long as a condition is met .SH SYNOPSIS \fBwhile \fItest body\fR .BE .SH DESCRIPTION .PP The \fBwhile\fR command evaluates \fItest\fR as an expression (in the same way that \fBexpr\fR evaluates its argument). The value of the expression must a proper boolean value; if it is a true value then \fIbody\fR is executed by passing it to the Tcl interpreter. Once \fIbody\fR has been executed then \fItest\fR is evaluated again, and the process repeats until eventually \fItest\fR evaluates to a false boolean value. \fBContinue\fR commands may be executed inside \fIbody\fR to terminate the current iteration of the loop, and \fBbreak\fR commands may be executed inside \fIbody\fR to cause immediate termination of the \fBwhile\fR command. The \fBwhile\fR command always returns an empty string. .PP Note: \fItest\fR should almost always be enclosed in braces. If not, variable substitutions will be made before the \fBwhile\fR command starts executing, which means that variable changes made by the loop body will not be considered in the expression. This is likely to result in an infinite loop. If \fItest\fR is enclosed in braces, variable substitutions are delayed until the expression is evaluated (before each loop iteration), so changes in the variables will be visible. For an example, try the following script with and without the braces around \fB$x<10\fR: .PP .CS set x 0 \fBwhile\fR {$x<10} { puts "x is $x" incr x } .CE .SH EXAMPLE .PP Read lines from a channel until we get to the end of the stream, and print them out with a line-number prepended: .PP .CS set lineCount 0 \fBwhile\fR {[gets $chan line] >= 0} { puts "[incr lineCount]: $line" } .CE .SH "SEE ALSO" break(n), continue(n), for(n), foreach(n) .SH KEYWORDS boolean, loop, test, while tcl8.6.5/doc/Cancel.30000644000175000017500000000544112663660065013611 0ustar sergeisergei'\" '\" Copyright (c) 2006-2008 Joe Mistachkin. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_Cancel 3 8.6 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CancelEval, Tcl_Canceled \- cancel Tcl scripts .SH SYNOPSIS .nf \fB#include \fR int \fBTcl_CancelEval\fR(\fIinterp, resultObjPtr, clientData, flags\fR) .sp int \fBTcl_Canceled\fR(\fIinterp, flags\fR) .SH ARGUMENTS .AS Tcl_Interp *interp .AP Tcl_Interp *interp in Interpreter in which to cancel the script. .AP Tcl_Obj *resultObjPtr in Error message to use in the cancellation, or NULL to use a default message. If not NULL, this object will have its reference count decremented before \fBTcl_CancelEval\fR returns. .AP int flags in ORed combination of flag bits that specify additional options. For \fBTcl_CancelEval\fR, only \fBTCL_CANCEL_UNWIND\fR is currently supported. For \fBTcl_Canceled\fR, only \fBTCL_LEAVE_ERR_MSG\fR and \fBTCL_CANCEL_UNWIND\fR are currently supported. .AP ClientData clientData in Currently reserved for future use. It should be set to NULL. .BE .SH DESCRIPTION .PP \fBTcl_CancelEval\fR cancels or unwinds the script in progress soon after the next invocation of asynchronous handlers, causing \fBTCL_ERROR\fR to be the return code for that script. This function is thread-safe and may be called from any thread in the process. .PP \fBTcl_Canceled\fR checks if the script in progress has been canceled and returns \fBTCL_ERROR\fR if it has. Otherwise, \fBTCL_OK\fR is returned. Extensions can use this function to check to see if they should abort a long running command. This function is thread sensitive and may only be called from the thread the interpreter was created in. .SS "FLAG BITS" Any ORed combination of the following values may be used for the \fIflags\fR argument to procedures such as \fBTcl_CancelEval\fR: .TP 20 \fBTCL_CANCEL_UNWIND\fR . This flag is used by \fBTcl_CancelEval\fR and \fBTcl_Canceled\fR. For \fBTcl_CancelEval\fR, if this flag is set, the script in progress is canceled and the evaluation stack for the interpreter is unwound. For \fBTcl_Canceled\fR, if this flag is set, the script in progress is considered to be canceled only if the evaluation stack for the interpreter is being unwound. .TP 20 \fBTCL_LEAVE_ERR_MSG\fR . This flag is only used by \fBTcl_Canceled\fR; it is ignored by other procedures. If an error is returned and this bit is set in \fIflags\fR, then an error message will be left in the interpreter's result, where it can be retrieved with \fBTcl_GetObjResult\fR or \fBTcl_GetStringResult\fR. If this flag bit is not set then no error message is left and the interpreter's result will not be modified. .SH "SEE ALSO" interp(n), Tcl_Eval(3), TIP 285 .SH KEYWORDS cancel, unwind tcl8.6.5/doc/CrtMathFnc.30000644000175000017500000001561612663660065014422 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_CreateMathFunc 3 8.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CreateMathFunc, Tcl_GetMathFuncInfo, Tcl_ListMathFuncs \- Define, query and enumerate math functions for expressions .SH "NOTICE OF EVENTUAL DEPRECATION" .PP The \fBTcl_CreateMathFunc\fR and \fBTcl_GetMathFuncInfo\fR functions are rendered somewhat obsolete by the ability to create functions for expressions by placing commands in the \fBtcl::mathfunc\fR namespace, as described in the \fBmathfunc\fR manual page; the API described on this page is not expected to be maintained indefinitely. .SH SYNOPSIS .nf \fB#include \fR .sp void \fBTcl_CreateMathFunc\fR(\fIinterp, name, numArgs, argTypes, proc, clientData\fR) .sp int \fBTcl_GetMathFuncInfo\fR(\fIinterp, name, numArgsPtr, argTypesPtr, procPtr, clientDataPtr\fR) .sp Tcl_Obj * \fBTcl_ListMathFuncs\fR(\fIinterp, pattern\fR) .SH ARGUMENTS .AS Tcl_ValueType *clientDataPtr out .AP Tcl_Interp *interp in Interpreter in which new function will be defined. .AP "const char" *name in Name for new function. .AP int numArgs in Number of arguments to new function; also gives size of \fIargTypes\fR array. .AP Tcl_ValueType *argTypes in Points to an array giving the permissible types for each argument to function. .AP Tcl_MathProc *proc in Procedure that implements the function. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR when it is invoked. .AP int *numArgsPtr out Points to a variable that will be set to contain the number of arguments to the function. .AP Tcl_ValueType **argTypesPtr out Points to a variable that will be set to contain a pointer to an array giving the permissible types for each argument to the function which will need to be freed up using \fITcl_Free\fR. .AP Tcl_MathProc **procPtr out Points to a variable that will be set to contain a pointer to the implementation code for the function (or NULL if the function is implemented directly in bytecode). .AP ClientData *clientDataPtr out Points to a variable that will be set to contain the clientData argument passed to \fITcl_CreateMathFunc\fR when the function was created if the function is not implemented directly in bytecode. .AP "const char" *pattern in Pattern to match against function names so as to filter them (by passing to \fITcl_StringMatch\fR), or NULL to not apply any filter. .BE .SH DESCRIPTION .PP Tcl allows a number of mathematical functions to be used in expressions, such as \fBsin\fR, \fBcos\fR, and \fBhypot\fR. These functions are represented by commands in the namespace, \fBtcl::mathfunc\fR. The \fBTcl_CreateMathFunc\fR function is an obsolete way for applications to add additional functions to those already provided by Tcl or to replace existing functions. It should not be used by new applications, which should create math functions using \fBTcl_CreateObjCommand\fR to create a command in the \fBtcl::mathfunc\fR namespace. .PP In the \fBTcl_CreateMathFunc\fR interface, \fIName\fR is the name of the function as it will appear in expressions. If \fIname\fR does not already exist in the \fB::tcl::mathfunc\fR namespace, then a new command is created in that namespace. If \fIname\fR does exist, then the existing function is replaced. \fINumArgs\fR and \fIargTypes\fR describe the arguments to the function. Each entry in the \fIargTypes\fR array must be one of \fBTCL_INT\fR, \fBTCL_DOUBLE\fR, \fBTCL_WIDE_INT\fR, or \fBTCL_EITHER\fR to indicate whether the corresponding argument must be an integer, a double-precision floating value, a wide (64-bit) integer, or any, respectively. .PP Whenever the function is invoked in an expression Tcl will invoke \fIproc\fR. \fIProc\fR should have arguments and result that match the type \fBTcl_MathProc\fR: .PP .CS typedef int \fBTcl_MathProc\fR( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR, Tcl_Value *\fIargs\fR, Tcl_Value *\fIresultPtr\fR); .CE .PP When \fIproc\fR is invoked the \fIclientData\fR and \fIinterp\fR arguments will be the same as those passed to \fBTcl_CreateMathFunc\fR. \fIArgs\fR will point to an array of \fInumArgs\fR Tcl_Value structures, which describe the actual arguments to the function: .PP .CS typedef struct Tcl_Value { Tcl_ValueType \fItype\fR; long \fIintValue\fR; double \fIdoubleValue\fR; Tcl_WideInt \fIwideValue\fR; } \fBTcl_Value\fR; .CE .PP The \fItype\fR field indicates the type of the argument and is one of \fBTCL_INT\fR, \fBTCL_DOUBLE\fR or \fBTCL_WIDE_INT\fR. It will match the \fIargTypes\fR value specified for the function unless the \fIargTypes\fR value was \fBTCL_EITHER\fR. Tcl converts the argument supplied in the expression to the type requested in \fIargTypes\fR, if that is necessary. Depending on the value of the \fItype\fR field, the \fIintValue\fR, \fIdoubleValue\fR or \fIwideValue\fR field will contain the actual value of the argument. .PP \fIProc\fR should compute its result and store it either as an integer in \fIresultPtr->intValue\fR or as a floating value in \fIresultPtr->doubleValue\fR. It should set also \fIresultPtr->type\fR to one of \fBTCL_INT\fR, \fBTCL_DOUBLE\fR or \fBTCL_WIDE_INT\fR to indicate which value was set. Under normal circumstances \fIproc\fR should return \fBTCL_OK\fR. If an error occurs while executing the function, \fIproc\fR should return \fBTCL_ERROR\fR and leave an error message in the interpreter's result. .PP \fBTcl_GetMathFuncInfo\fR retrieves the values associated with function \fIname\fR that were passed to a preceding \fBTcl_CreateMathFunc\fR call. Normally, the return code is \fBTCL_OK\fR but if the named function does not exist, \fBTCL_ERROR\fR is returned and an error message is placed in the interpreter's result. .PP If an error did not occur, the array reference placed in the variable pointed to by \fIargTypesPtr\fR is newly allocated, and should be released by passing it to \fBTcl_Free\fR. Some functions (the standard set implemented in the core, and those defined by placing commands in the \fBtcl::mathfunc\fR namespace) do not have argument type information; attempting to retrieve values for them causes a NULL to be stored in the variable pointed to by \fIprocPtr\fR and the variable pointed to by \fIclientDataPtr\fR will not be modified. The variable pointed to by \fInumArgsPointer\fR will contain -1, and no argument types will be stored in the variable pointed to by \fIargTypesPointer\fR. .PP \fBTcl_ListMathFuncs\fR returns a Tcl value containing a list of all the math functions defined in the interpreter whose name matches \fIpattern\fR. The returned value has a reference count of zero. .SH "SEE ALSO" expr(n), info(n), Tcl_CreateObjCommand(3), Tcl_Free(3), Tcl_NewListObj(3) .SH KEYWORDS expression, mathematical function tcl8.6.5/doc/RecordEval.30000644000175000017500000000401112663660065014442 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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_RecordAndEval 3 7.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_RecordAndEval \- save command on history list before evaluating .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_RecordAndEval\fR(\fIinterp, cmd, flags\fR) .SH ARGUMENTS .AS Tcl_Interp *interp .AP Tcl_Interp *interp in Tcl interpreter in which to evaluate command. .AP "const char" *cmd in Command (or sequence of commands) to execute. .AP int flags in An OR'ed combination of flag bits. \fBTCL_NO_EVAL\fR means record the command but do not evaluate it. \fBTCL_EVAL_GLOBAL\fR means evaluate the command at global level instead of the current stack level. .BE .SH DESCRIPTION .PP \fBTcl_RecordAndEval\fR is invoked to record a command as an event on the history list and then execute it using \fBTcl_Eval\fR (or \fBTcl_GlobalEval\fR if the \fBTCL_EVAL_GLOBAL\fR bit is set in \fIflags\fR). It returns a completion code such as \fBTCL_OK\fR just like \fBTcl_Eval\fR and it leaves information in the interpreter's result. If you do not want the command recorded on the history list then you should invoke \fBTcl_Eval\fR instead of \fBTcl_RecordAndEval\fR. Normally \fBTcl_RecordAndEval\fR is only called with top-level commands typed by the user, since the purpose of history is to allow the user to re-issue recently-invoked commands. If the \fIflags\fR argument contains the \fBTCL_NO_EVAL\fR bit then the command is recorded without being evaluated. .PP Note that \fBTcl_RecordAndEval\fR has been largely replaced by the value-based procedure \fBTcl_RecordAndEvalObj\fR. That value-based procedure records and optionally executes a command held in a Tcl value instead of a string. .SH "SEE ALSO" Tcl_RecordAndEvalObj .SH KEYWORDS command, event, execute, history, interpreter, record tcl8.6.5/doc/tcltest.n0000644000175000017500000013215512663660065014204 0ustar sergeisergei'\" '\" Copyright (c) 1990-1994 The Regents of the University of California '\" Copyright (c) 1994-1997 Sun Microsystems, Inc. '\" Copyright (c) 1998-1999 Scriptics Corporation '\" Copyright (c) 2000 Ajuba Solutions '\" Contributions from Don Porter, NIST, 2002. (not subject to US copyright) '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH "tcltest" n 2.3 tcltest "Tcl Bundled Packages" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME tcltest \- Test harness support code and utilities .SH SYNOPSIS .nf \fBpackage require tcltest\fR ?\fB2.3\fR? \fBtcltest::test \fIname description\fR ?\fI\-option value ...\fR? \fBtcltest::test \fIname description\fR ?\fIconstraints\fR? \fIbody result\fR \fBtcltest::loadTestedCommands\fR \fBtcltest::makeDirectory \fIname\fR ?\fIdirectory\fR? \fBtcltest::removeDirectory \fIname\fR ?\fIdirectory\fR? \fBtcltest::makeFile \fIcontents name\fR ?\fIdirectory\fR? \fBtcltest::removeFile \fIname\fR ?\fIdirectory\fR? \fBtcltest::viewFile \fIname\fR ?\fIdirectory\fR? \fBtcltest::cleanupTests \fR?\fIrunningMultipleTests\fR? \fBtcltest::runAllTests\fR \fBtcltest::configure\fR \fBtcltest::configure \fI\-option\fR \fBtcltest::configure \fI\-option value\fR ?\fI\-option value ...\fR? \fBtcltest::customMatch \fImode command\fR \fBtcltest::testConstraint \fIconstraint\fR ?\fIvalue\fR? \fBtcltest::outputChannel \fR?\fIchannelID\fR? \fBtcltest::errorChannel \fR?\fIchannelID\fR? \fBtcltest::interpreter \fR?\fIinterp\fR? \fBtcltest::debug \fR?\fIlevel\fR? \fBtcltest::errorFile \fR?\fIfilename\fR? \fBtcltest::limitConstraints \fR?\fIboolean\fR? \fBtcltest::loadFile \fR?\fIfilename\fR? \fBtcltest::loadScript \fR?\fIscript\fR? \fBtcltest::match \fR?\fIpatternList\fR? \fBtcltest::matchDirectories \fR?\fIpatternList\fR? \fBtcltest::matchFiles \fR?\fIpatternList\fR? \fBtcltest::outputFile \fR?\fIfilename\fR? \fBtcltest::preserveCore \fR?\fIlevel\fR? \fBtcltest::singleProcess \fR?\fIboolean\fR? \fBtcltest::skip \fR?\fIpatternList\fR? \fBtcltest::skipDirectories \fR?\fIpatternList\fR? \fBtcltest::skipFiles \fR?\fIpatternList\fR? \fBtcltest::temporaryDirectory \fR?\fIdirectory\fR? \fBtcltest::testsDirectory \fR?\fIdirectory\fR? \fBtcltest::verbose \fR?\fIlevel\fR? \fBtcltest::test \fIname description optionList\fR \fBtcltest::bytestring \fIstring\fR \fBtcltest::normalizeMsg \fImsg\fR \fBtcltest::normalizePath \fIpathVar\fR \fBtcltest::workingDirectory \fR?\fIdir\fR? .fi .BE .SH DESCRIPTION .PP The \fBtcltest\fR package provides several utility commands useful in the construction of test suites for code instrumented to be run by evaluation of Tcl commands. Notably the built-in commands of the Tcl library itself are tested by a test suite using the tcltest package. .PP All the commands provided by the \fBtcltest\fR package are defined in and exported from the \fB::tcltest\fR namespace, as indicated in the \fBSYNOPSIS\fR above. In the following sections, all commands will be described by their simple names, in the interest of brevity. .PP The central command of \fBtcltest\fR is \fBtest\fR that defines and runs a test. Testing with \fBtest\fR involves evaluation of a Tcl script and comparing the result to an expected result, as configured and controlled by a number of options. Several other commands provided by \fBtcltest\fR govern the configuration of \fBtest\fR and the collection of many \fBtest\fR commands into test suites. .PP See \fBCREATING TEST SUITES WITH TCLTEST\fR below for an extended example of how to use the commands of \fBtcltest\fR to produce test suites for your Tcl-enabled code. .SH COMMANDS .TP \fBtest\fR \fIname description\fR ?\fI\-option value ...\fR? . Defines and possibly runs a test with the name \fIname\fR and description \fIdescription\fR. The name and description of a test are used in messages reported by \fBtest\fR during the test, as configured by the options of \fBtcltest\fR. The remaining \fIoption value\fR arguments to \fBtest\fR define the test, including the scripts to run, the conditions under which to run them, the expected result, and the means by which the expected and actual results should be compared. See \fBTESTS\fR below for a complete description of the valid options and how they define a test. The \fBtest\fR command returns an empty string. .TP \fBtest\fR \fIname description\fR ?\fIconstraints\fR? \fIbody result\fR . This form of \fBtest\fR is provided to support test suites written for version 1 of the \fBtcltest\fR package, and also a simpler interface for a common usage. It is the same as .QW "\fBtest\fR \fIname description\fB \-constraints \fIconstraints\fB \-body \fIbody\fB \-result \fIresult\fR" . All other options to \fBtest\fR take their default values. When \fIconstraints\fR is omitted, this form of \fBtest\fR can be distinguished from the first because all \fIoption\fRs begin with .QW \- . .TP \fBloadTestedCommands\fR . Evaluates in the caller's context the script specified by \fBconfigure \-load\fR or \fBconfigure \-loadfile\fR. Returns the result of that script evaluation, including any error raised by the script. Use this command and the related configuration options to provide the commands to be tested to the interpreter running the test suite. .TP \fBmakeFile\fR \fIcontents name\fR ?\fIdirectory\fR? . Creates a file named \fIname\fR relative to directory \fIdirectory\fR and write \fIcontents\fR to that file using the encoding \fBencoding system\fR. If \fIcontents\fR does not end with a newline, a newline will be appended so that the file named \fIname\fR does end with a newline. Because the system encoding is used, this command is only suitable for making text files. The file will be removed by the next evaluation of \fBcleanupTests\fR, unless it is removed by \fBremoveFile\fR first. The default value of \fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR. Returns the full path of the file created. Use this command to create any text file required by a test with contents as needed. .TP \fBremoveFile\fR \fIname\fR ?\fIdirectory\fR? . Forces the file referenced by \fIname\fR to be removed. This file name should be relative to \fIdirectory\fR. The default value of \fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR. Returns an empty string. Use this command to delete files created by \fBmakeFile\fR. .TP \fBmakeDirectory\fR \fIname\fR ?\fIdirectory\fR? . Creates a directory named \fIname\fR relative to directory \fIdirectory\fR. The directory will be removed by the next evaluation of \fBcleanupTests\fR, unless it is removed by \fBremoveDirectory\fR first. The default value of \fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR. Returns the full path of the directory created. Use this command to create any directories that are required to exist by a test. .TP \fBremoveDirectory\fR \fIname\fR ?\fIdirectory\fR? . Forces the directory referenced by \fIname\fR to be removed. This directory should be relative to \fIdirectory\fR. The default value of \fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR. Returns an empty string. Use this command to delete any directories created by \fBmakeDirectory\fR. .TP \fBviewFile\fR \fIfile\fR ?\fIdirectory\fR? . Returns the contents of \fIfile\fR, except for any final newline, just as \fBread \-nonewline\fR would return. This file name should be relative to \fIdirectory\fR. The default value of \fIdirectory\fR is the directory \fBconfigure \-tmpdir\fR. Use this command as a convenient way to turn the contents of a file generated by a test into the result of that test for matching against an expected result. The contents of the file are read using the system encoding, so its usefulness is limited to text files. .TP \fBcleanupTests\fR . Intended to clean up and summarize after several tests have been run. Typically called once per test file, at the end of the file after all tests have been completed. For best effectiveness, be sure that the \fBcleanupTests\fR is evaluated even if an error occurs earlier in the test file evaluation. .RS .PP Prints statistics about the tests run and removes files that were created by \fBmakeDirectory\fR and \fBmakeFile\fR since the last \fBcleanupTests\fR. Names of files and directories in the directory \fBconfigure \-tmpdir\fR created since the last \fBcleanupTests\fR, but not created by \fBmakeFile\fR or \fBmakeDirectory\fR are printed to \fBoutputChannel\fR. This command also restores the original shell environment, as described by the global \fBenv\fR array. Returns an empty string. .RE .TP \fBrunAllTests\fR . This is a master command meant to run an entire suite of tests, spanning multiple files and/or directories, as governed by the configurable options of \fBtcltest\fR. See \fBRUNNING ALL TESTS\fR below for a complete description of the many variations possible with \fBrunAllTests\fR. .SS "CONFIGURATION COMMANDS" .TP \fBconfigure\fR . Returns the list of configurable options supported by \fBtcltest\fR. See \fBCONFIGURABLE OPTIONS\fR below for the full list of options, their valid values, and their effect on \fBtcltest\fR operations. .TP \fBconfigure \fIoption\fR . Returns the current value of the supported configurable option \fIoption\fR. Raises an error if \fIoption\fR is not a supported configurable option. .TP \fBconfigure \fIoption value\fR ?\fI\-option value ...\fR? . Sets the value of each configurable option \fIoption\fR to the corresponding value \fIvalue\fR, in order. Raises an error if an \fIoption\fR is not a supported configurable option, or if \fIvalue\fR is not a valid value for the corresponding \fIoption\fR, or if a \fIvalue\fR is not provided. When an error is raised, the operation of \fBconfigure\fR is halted, and subsequent \fIoption value\fR arguments are not processed. .RS .PP If the environment variable \fB::env(TCLTEST_OPTIONS)\fR exists when the \fBtcltest\fR package is loaded (by \fBpackage require\fR \fBtcltest\fR) then its value is taken as a list of arguments to pass to \fBconfigure\fR. This allows the default values of the configuration options to be set by the environment. .RE .TP \fBcustomMatch \fImode script\fR . Registers \fImode\fR as a new legal value of the \fB\-match\fR option to \fBtest\fR. When the \fB\-match \fImode\fR option is passed to \fBtest\fR, the script \fIscript\fR will be evaluated to compare the actual result of evaluating the body of the test to the expected result. To perform the match, the \fIscript\fR is completed with two additional words, the expected result, and the actual result, and the completed script is evaluated in the global namespace. The completed script is expected to return a boolean value indicating whether or not the results match. The built-in matching modes of \fBtest\fR are \fBexact\fR, \fBglob\fR, and \fBregexp\fR. .TP \fBtestConstraint \fIconstraint\fR ?\fIboolean\fR? . Sets or returns the boolean value associated with the named \fIconstraint\fR. See \fBTEST CONSTRAINTS\fR below for more information. .TP \fBinterpreter\fR ?\fIexecutableName\fR? . Sets or returns the name of the executable to be \fBexec\fRed by \fBrunAllTests\fR to run each test file when \fBconfigure \-singleproc\fR is false. The default value for \fBinterpreter\fR is the name of the currently running program as returned by \fBinfo nameofexecutable\fR. .TP \fBoutputChannel\fR ?\fIchannelID\fR? . Sets or returns the output channel ID. This defaults to \fBstdout\fR. Any test that prints test related output should send that output to \fBoutputChannel\fR rather than letting that output default to \fBstdout\fR. .TP \fBerrorChannel\fR ?\fIchannelID\fR? . Sets or returns the error channel ID. This defaults to \fBstderr\fR. Any test that prints error messages should send that output to \fBerrorChannel\fR rather than printing directly to \fBstderr\fR. .SS "SHORTCUT CONFIGURATION COMMANDS" .TP \fBdebug\fR ?\fIlevel\fR? . Same as .QW "\fBconfigure \-debug\fR ?\fIlevel\fR?" . .TP \fBerrorFile\fR ?\fIfilename\fR? . Same as .QW "\fBconfigure \-errfile\fR ?\fIfilename\fR?" . .TP \fBlimitConstraints\fR ?\fIboolean\fR? . Same as .QW "\fBconfigure \-limitconstraints\fR ?\fIboolean\fR?" . .TP \fBloadFile\fR ?\fIfilename\fR? . Same as .QW "\fBconfigure \-loadfile\fR ?\fIfilename\fR?" . .TP \fBloadScript\fR ?\fIscript\fR? . Same as .QW "\fBconfigure \-load\fR ?\fIscript\fR?" . .TP \fBmatch\fR ?\fIpatternList\fR? . Same as .QW "\fBconfigure \-match\fR ?\fIpatternList\fR?" . .TP \fBmatchDirectories\fR ?\fIpatternList\fR? . Same as .QW "\fBconfigure \-relateddir\fR ?\fIpatternList\fR?" . .TP \fBmatchFiles\fR ?\fIpatternList\fR? . Same as .QW "\fBconfigure \-file\fR ?\fIpatternList\fR?" . .TP \fBoutputFile\fR ?\fIfilename\fR? . Same as .QW "\fBconfigure \-outfile\fR ?\fIfilename\fR?" . .TP \fBpreserveCore\fR ?\fIlevel\fR? . Same as .QW "\fBconfigure \-preservecore\fR ?\fIlevel\fR?" . .TP \fBsingleProcess\fR ?\fIboolean\fR? . Same as .QW "\fBconfigure \-singleproc\fR ?\fIboolean\fR?" . .TP \fBskip\fR ?\fIpatternList\fR? . Same as .QW "\fBconfigure \-skip\fR ?\fIpatternList\fR?" . .TP \fBskipDirectories\fR ?\fIpatternList\fR? . Same as .QW "\fBconfigure \-asidefromdir\fR ?\fIpatternList\fR?" . .TP \fBskipFiles\fR ?\fIpatternList\fR? . Same as .QW "\fBconfigure \-notfile\fR ?\fIpatternList\fR?" . .TP \fBtemporaryDirectory\fR ?\fIdirectory\fR? . Same as .QW "\fBconfigure \-tmpdir\fR ?\fIdirectory\fR?" . .TP \fBtestsDirectory\fR ?\fIdirectory\fR? . Same as .QW "\fBconfigure \-testdir\fR ?\fIdirectory\fR?" . .TP \fBverbose\fR ?\fIlevel\fR? . Same as .QW "\fBconfigure \-verbose\fR ?\fIlevel\fR?" . .SS "OTHER COMMANDS" .PP The remaining commands provided by \fBtcltest\fR have better alternatives provided by \fBtcltest\fR or \fBTcl\fR itself. They are retained to support existing test suites, but should be avoided in new code. .TP \fBtest\fR \fIname description optionList\fR . This form of \fBtest\fR was provided to enable passing many options spanning several lines to \fBtest\fR as a single argument quoted by braces, rather than needing to backslash quote the newlines between arguments to \fBtest\fR. The \fIoptionList\fR argument is expected to be a list with an even number of elements representing \fIoption\fR and \fIvalue\fR arguments to pass to \fBtest\fR. However, these values are not passed directly, as in the alternate forms of \fBswitch\fR. Instead, this form makes an unfortunate attempt to overthrow Tcl's substitution rules by performing substitutions on some of the list elements as an attempt to implement a .QW "do what I mean" interpretation of a brace-enclosed .QW block . The result is nearly impossible to document clearly, and for that reason this form is not recommended. See the examples in \fBCREATING TEST SUITES WITH TCLTEST\fR below to see that this form is really not necessary to avoid backslash-quoted newlines. If you insist on using this form, examine the source code of \fBtcltest\fR if you want to know the substitution details, or just enclose the third through last argument to \fBtest\fR in braces and hope for the best. .TP \fBworkingDirectory\fR ?\fIdirectoryName\fR? . Sets or returns the current working directory when the test suite is running. The default value for workingDirectory is the directory in which the test suite was launched. The Tcl commands \fBcd\fR and \fBpwd\fR are sufficient replacements. .TP \fBnormalizeMsg \fImsg\fR . Returns the result of removing the .QW extra newlines from \fImsg\fR, where .QW extra is rather imprecise. Tcl offers plenty of string processing commands to modify strings as you wish, and \fBcustomMatch\fR allows flexible matching of actual and expected results. .TP \fBnormalizePath \fIpathVar\fR . Resolves symlinks in a path, thus creating a path without internal redirection. It is assumed that \fIpathVar\fR is absolute. \fIpathVar\fR is modified in place. The Tcl command \fBfile normalize\fR is a sufficient replacement. .TP \fBbytestring \fIstring\fR . Construct a string that consists of the requested sequence of bytes, as opposed to a string of properly formed UTF-8 characters using the value supplied in \fIstring\fR. This allows the tester to create denormalized or improperly formed strings to pass to C procedures that are supposed to accept strings with embedded NULL types and confirm that a string result has a certain pattern of bytes. This is exactly equivalent to the Tcl command \fBencoding convertfrom\fR \fBidentity\fR. .SH TESTS .PP The \fBtest\fR command is the heart of the \fBtcltest\fR package. Its essential function is to evaluate a Tcl script and compare the result with an expected result. The options of \fBtest\fR define the test script, the environment in which to evaluate it, the expected result, and how the compare the actual result to the expected result. Some configuration options of \fBtcltest\fR also influence how \fBtest\fR operates. .PP The valid options for \fBtest\fR are summarized: .PP .CS \fBtest\fR \fIname\fR \fIdescription\fR ?\fB\-constraints \fIkeywordList|expression\fR? ?\fB\-setup \fIsetupScript\fR? ?\fB\-body \fItestScript\fR? ?\fB\-cleanup \fIcleanupScript\fR? ?\fB\-result \fIexpectedAnswer\fR? ?\fB\-output \fIexpectedOutput\fR? ?\fB\-errorOutput \fIexpectedError\fR? ?\fB\-returnCodes \fIcodeList\fR? ?\fB\-match \fImode\fR? .CE .PP The \fIname\fR may be any string. It is conventional to choose a \fIname\fR according to the pattern: .PP .CS \fItarget\fR-\fImajorNum\fR.\fIminorNum\fR .CE .PP For white-box (regression) tests, the target should be the name of the C function or Tcl procedure being tested. For black-box tests, the target should be the name of the feature being tested. Some conventions call for the names of black-box tests to have the suffix \fB_bb\fR. Related tests should share a major number. As a test suite evolves, it is best to have the same test name continue to correspond to the same test, so that it remains meaningful to say things like .QW "Test foo-1.3 passed in all releases up to 3.4, but began failing in release 3.5." .PP During evaluation of \fBtest\fR, the \fIname\fR will be compared to the lists of string matching patterns returned by \fBconfigure \-match\fR, and \fBconfigure \-skip\fR. The test will be run only if \fIname\fR matches any of the patterns from \fBconfigure \-match\fR and matches none of the patterns from \fBconfigure \-skip\fR. .PP The \fIdescription\fR should be a short textual description of the test. The \fIdescription\fR is included in output produced by the test, typically test failure messages. Good \fIdescription\fR values should briefly explain the purpose of the test to users of a test suite. The name of a Tcl or C function being tested should be included in the description for regression tests. If the test case exists to reproduce a bug, include the bug ID in the description. .PP Valid attributes and associated values are: .TP \fB\-constraints \fIkeywordList\fR|\fIexpression\fR . The optional \fB\-constraints\fR attribute can be list of one or more keywords or an expression. If the \fB\-constraints\fR value is a list of keywords, each of these keywords should be the name of a constraint defined by a call to \fBtestConstraint\fR. If any of the listed constraints is false or does not exist, the test is skipped. If the \fB\-constraints\fR value is an expression, that expression is evaluated. If the expression evaluates to true, then the test is run. Note that the expression form of \fB\-constraints\fR may interfere with the operation of \fBconfigure \-constraints\fR and \fBconfigure \-limitconstraints\fR, and is not recommended. Appropriate constraints should be added to any tests that should not always be run. That is, conditional evaluation of a test should be accomplished by the \fB\-constraints\fR option, not by conditional evaluation of \fBtest\fR. In that way, the same number of tests are always reported by the test suite, though the number skipped may change based on the testing environment. The default value is an empty list. See \fBTEST CONSTRAINTS\fR below for a list of built-in constraints and information on how to add your own constraints. .TP \fB\-setup \fIscript\fR . The optional \fB\-setup\fR attribute indicates a \fIscript\fR that will be run before the script indicated by the \fB\-body\fR attribute. If evaluation of \fIscript\fR raises an error, the test will fail. The default value is an empty script. .TP \fB\-body \fIscript\fR . The \fB\-body\fR attribute indicates the \fIscript\fR to run to carry out the test, which must return a result that can be checked for correctness. If evaluation of \fIscript\fR raises an error, the test will fail (unless the \fB\-returnCodes\fR option is used to state that an error is expected). The default value is an empty script. .TP \fB\-cleanup \fIscript\fR . The optional \fB\-cleanup\fR attribute indicates a \fIscript\fR that will be run after the script indicated by the \fB\-body\fR attribute. If evaluation of \fIscript\fR raises an error, the test will fail. The default value is an empty script. .TP \fB\-match \fImode\fR . The \fB\-match\fR attribute determines how expected answers supplied by \fB\-result\fR, \fB\-output\fR, and \fB\-errorOutput\fR are compared. Valid values for \fImode\fR are \fBregexp\fR, \fBglob\fR, \fBexact\fR, and any value registered by a prior call to \fBcustomMatch\fR. The default value is \fBexact\fR. .TP \fB\-result \fIexpectedValue\fR . The \fB\-result\fR attribute supplies the \fIexpectedValue\fR against which the return value from script will be compared. The default value is an empty string. .TP \fB\-output \fIexpectedValue\fR . The \fB\-output\fR attribute supplies the \fIexpectedValue\fR against which any output sent to \fBstdout\fR or \fBoutputChannel\fR during evaluation of the script(s) will be compared. Note that only output printed using the global \fBputs\fR command is used for comparison. If \fB\-output\fR is not specified, output sent to \fBstdout\fR and \fBoutputChannel\fR is not processed for comparison. .TP \fB\-errorOutput \fIexpectedValue\fR . The \fB\-errorOutput\fR attribute supplies the \fIexpectedValue\fR against which any output sent to \fBstderr\fR or \fBerrorChannel\fR during evaluation of the script(s) will be compared. Note that only output printed using the global \fBputs\fR command is used for comparison. If \fB\-errorOutput\fR is not specified, output sent to \fBstderr\fR and \fBerrorChannel\fR is not processed for comparison. .TP \fB\-returnCodes \fIexpectedCodeList\fR . The optional \fB\-returnCodes\fR attribute supplies \fIexpectedCodeList\fR, a list of return codes that may be accepted from evaluation of the \fB\-body\fR script. If evaluation of the \fB\-body\fR script returns a code not in the \fIexpectedCodeList\fR, the test fails. All return codes known to \fBreturn\fR, in both numeric and symbolic form, including extended return codes, are acceptable elements in the \fIexpectedCodeList\fR. Default value is .QW "\fBok return\fR" . .PP To pass, a test must successfully evaluate its \fB\-setup\fR, \fB\-body\fR, and \fB\-cleanup\fR scripts. The return code of the \fB\-body\fR script and its result must match expected values, and if specified, output and error data from the test must match expected \fB\-output\fR and \fB\-errorOutput\fR values. If any of these conditions are not met, then the test fails. Note that all scripts are evaluated in the context of the caller of \fBtest\fR. .PP As long as \fBtest\fR is called with valid syntax and legal values for all attributes, it will not raise an error. Test failures are instead reported as output written to \fBoutputChannel\fR. In default operation, a successful test produces no output. The output messages produced by \fBtest\fR are controlled by the \fBconfigure \-verbose\fR option as described in \fBCONFIGURABLE OPTIONS\fR below. Any output produced by the test scripts themselves should be produced using \fBputs\fR to \fBoutputChannel\fR or \fBerrorChannel\fR, so that users of the test suite may easily capture output with the \fBconfigure \-outfile\fR and \fBconfigure \-errfile\fR options, and so that the \fB\-output\fR and \fB\-errorOutput\fR attributes work properly. .SS "TEST CONSTRAINTS" .PP Constraints are used to determine whether or not a test should be skipped. Each constraint has a name, which may be any string, and a boolean value. Each \fBtest\fR has a \fB\-constraints\fR value which is a list of constraint names. There are two modes of constraint control. Most frequently, the default mode is used, indicated by a setting of \fBconfigure \-limitconstraints\fR to false. The test will run only if all constraints in the list are true-valued. Thus, the \fB\-constraints\fR option of \fBtest\fR is a convenient, symbolic way to define any conditions required for the test to be possible or meaningful. For example, a \fBtest\fR with \fB\-constraints unix\fR will only be run if the constraint \fBunix\fR is true, which indicates the test suite is being run on a Unix platform. .PP Each \fBtest\fR should include whatever \fB\-constraints\fR are required to constrain it to run only where appropriate. Several constraints are pre-defined in the \fBtcltest\fR package, listed below. The registration of user-defined constraints is performed by the \fBtestConstraint\fR command. User-defined constraints may appear within a test file, or within the script specified by the \fBconfigure \-load\fR or \fBconfigure \-loadfile\fR options. .PP The following is a list of constraints pre-defined by the \fBtcltest\fR package itself: .TP \fIsingleTestInterp\fR . This test can only be run if all test files are sourced into a single interpreter. .TP \fIunix\fR . This test can only be run on any Unix platform. .TP \fIwin\fR . This test can only be run on any Windows platform. .TP \fInt\fR . This test can only be run on any Windows NT platform. .TP \fImac\fR . This test can only be run on any Mac platform. .TP \fIunixOrWin\fR . This test can only be run on a Unix or Windows platform. .TP \fImacOrWin\fR . This test can only be run on a Mac or Windows platform. .TP \fImacOrUnix\fR . This test can only be run on a Mac or Unix platform. .TP \fItempNotWin\fR . This test can not be run on Windows. This flag is used to temporarily disable a test. .TP \fItempNotMac\fR . This test can not be run on a Mac. This flag is used to temporarily disable a test. .TP \fIunixCrash\fR . This test crashes if it is run on Unix. This flag is used to temporarily disable a test. .TP \fIwinCrash\fR . This test crashes if it is run on Windows. This flag is used to temporarily disable a test. .TP \fImacCrash\fR . This test crashes if it is run on a Mac. This flag is used to temporarily disable a test. .TP \fIemptyTest\fR . This test is empty, and so not worth running, but it remains as a place-holder for a test to be written in the future. This constraint has value false to cause tests to be skipped unless the user specifies otherwise. .TP \fIknownBug\fR . This test is known to fail and the bug is not yet fixed. This constraint has value false to cause tests to be skipped unless the user specifies otherwise. .TP \fInonPortable\fR . This test can only be run in some known development environment. Some tests are inherently non-portable because they depend on things like word length, file system configuration, window manager, etc. This constraint has value false to cause tests to be skipped unless the user specifies otherwise. .TP \fIuserInteraction\fR . This test requires interaction from the user. This constraint has value false to causes tests to be skipped unless the user specifies otherwise. .TP \fIinteractive\fR . This test can only be run in if the interpreter is in interactive mode (when the global tcl_interactive variable is set to 1). .TP \fInonBlockFiles\fR . This test can only be run if platform supports setting files into nonblocking mode. .TP \fIasyncPipeClose\fR . This test can only be run if platform supports async flush and async close on a pipe. .TP \fIunixExecs\fR . This test can only be run if this machine has Unix-style commands \fBcat\fR, \fBecho\fR, \fBsh\fR, \fBwc\fR, \fBrm\fR, \fBsleep\fR, \fBfgrep\fR, \fBps\fR, \fBchmod\fR, and \fBmkdir\fR available. .TP \fIhasIsoLocale\fR . This test can only be run if can switch to an ISO locale. .TP \fIroot\fR . This test can only run if Unix user is root. .TP \fInotRoot\fR . This test can only run if Unix user is not root. .TP \fIeformat\fR . This test can only run if app has a working version of sprintf with respect to the .QW e format of floating-point numbers. .TP \fIstdio\fR . This test can only be run if \fBinterpreter\fR can be \fBopen\fRed as a pipe. .PP The alternative mode of constraint control is enabled by setting \fBconfigure \-limitconstraints\fR to true. With that configuration setting, all existing constraints other than those in the constraint list returned by \fBconfigure \-constraints\fR are set to false. When the value of \fBconfigure \-constraints\fR is set, all those constraints are set to true. The effect is that when both options \fBconfigure \-constraints\fR and \fBconfigure \-limitconstraints\fR are in use, only those tests including only constraints from the \fBconfigure \-constraints\fR list are run; all others are skipped. For example, one might set up a configuration with .PP .CS \fBconfigure\fR -constraints knownBug \e -limitconstraints true \e -verbose pass .CE .PP to run exactly those tests that exercise known bugs, and discover whether any of them pass, indicating the bug had been fixed. .SS "RUNNING ALL TESTS" .PP The single command \fBrunAllTests\fR is evaluated to run an entire test suite, spanning many files and directories. The configuration options of \fBtcltest\fR control the precise operations. The \fBrunAllTests\fR command begins by printing a summary of its configuration to \fBoutputChannel\fR. .PP Test files to be evaluated are sought in the directory \fBconfigure \-testdir\fR. The list of files in that directory that match any of the patterns in \fBconfigure \-file\fR and match none of the patterns in \fBconfigure \-notfile\fR is generated and sorted. Then each file will be evaluated in turn. If \fBconfigure \-singleproc\fR is true, then each file will be \fBsource\fRd in the caller's context. If it is false, then a copy of \fBinterpreter\fR will be \fBexec\fR'd to evaluate each file. The multi-process operation is useful when testing can cause errors so severe that a process terminates. Although such an error may terminate a child process evaluating one file, the master process can continue with the rest of the test suite. In multi-process operation, the configuration of \fBtcltest\fR in the master process is passed to the child processes as command line arguments, with the exception of \fBconfigure \-outfile\fR. The \fBrunAllTests\fR command in the master process collects all output from the child processes and collates their results into one master report. Any reports of individual test failures, or messages requested by a \fBconfigure \-verbose\fR setting are passed directly on to \fBoutputChannel\fR by the master process. .PP After evaluating all selected test files, a summary of the results is printed to \fBoutputChannel\fR. The summary includes the total number of \fBtest\fRs evaluated, broken down into those skipped, those passed, and those failed. The summary also notes the number of files evaluated, and the names of any files with failing tests or errors. A list of the constraints that caused tests to be skipped, and the number of tests skipped for each is also printed. Also, messages are printed if it appears that evaluation of a test file has caused any temporary files to be left behind in \fBconfigure \-tmpdir\fR. .PP Having completed and summarized all selected test files, \fBrunAllTests\fR then recursively acts on subdirectories of \fBconfigure \-testdir\fR. All subdirectories that match any of the patterns in \fBconfigure \-relateddir\fR and do not match any of the patterns in \fBconfigure \-asidefromdir\fR are examined. If a file named \fBall.tcl\fR is found in such a directory, it will be \fBsource\fRd in the caller's context. Whether or not an examined directory contains an \fBall.tcl\fR file, its subdirectories are also scanned against the \fBconfigure \-relateddir\fR and \fBconfigure \-asidefromdir\fR patterns. In this way, many directories in a directory tree can have all their test files evaluated by a single \fBrunAllTests\fR command. .SH "CONFIGURABLE OPTIONS" The \fBconfigure\fR command is used to set and query the configurable options of \fBtcltest\fR. The valid options are: .TP \fB\-singleproc \fIboolean\fR . Controls whether or not \fBrunAllTests\fR spawns a child process for each test file. No spawning when \fIboolean\fR is true. Default value is false. .TP \fB\-debug \fIlevel\fR . Sets the debug level to \fIlevel\fR, an integer value indicating how much debugging information should be printed to \fBstdout\fR. Note that debug messages always go to \fBstdout\fR, independent of the value of \fBconfigure \-outfile\fR. Default value is 0. Levels are defined as: .RS .IP 0 4 Do not display any debug information. .IP 1 Display information regarding whether a test is skipped because it does not match any of the tests that were specified using by \fBconfigure \-match\fR (userSpecifiedNonMatch) or matches any of the tests specified by \fBconfigure \-skip\fR (userSpecifiedSkip). Also print warnings about possible lack of cleanup or balance in test files. Also print warnings about any re-use of test names. .IP 2 Display the flag array parsed by the command line processor, the contents of the global \fBenv\fR array, and all user-defined variables that exist in the current namespace as they are used. .IP 3 Display information regarding what individual procs in the test harness are doing. .RE .TP \fB\-verbose \fIlevel\fR . Sets the type of output verbosity desired to \fIlevel\fR, a list of zero or more of the elements \fBbody\fR, \fBpass\fR, \fBskip\fR, \fBstart\fR, \fBerror\fR and \fBline\fR. Default value is .QW "\fBbody error\fR" . Levels are defined as: .RS .IP "body (\fBb\fR)" Display the body of failed tests .IP "pass (\fBp\fR)" Print output when a test passes .IP "skip (\fBs\fR)" Print output when a test is skipped .IP "start (\fBt\fR)" Print output whenever a test starts .IP "error (\fBe\fR)" Print errorInfo and errorCode, if they exist, when a test return code does not match its expected return code .IP "line (\fBl\fR)" Print source file line information of failed tests .PP The single letter abbreviations noted above are also recognized so that .QW "\fBconfigure \-verbose pt\fR" is the same as .QW "\fBconfigure \-verbose {pass start}\fR" . .RE .TP \fB\-preservecore \fIlevel\fR . Sets the core preservation level to \fIlevel\fR. This level determines how stringent checks for core files are. Default value is 0. Levels are defined as: .RS .IP 0 No checking \(em do not check for core files at the end of each test command, but do check for them in \fBrunAllTests\fR after all test files have been evaluated. .IP 1 Also check for core files at the end of each \fBtest\fR command. .IP 2 Check for core files at all times described above, and save a copy of each core file produced in \fBconfigure \-tmpdir\fR. .RE .TP \fB\-limitconstraints \fIboolean\fR . Sets the mode by which \fBtest\fR honors constraints as described in \fBTESTS\fR above. Default value is false. .TP \fB\-constraints \fIlist\fR . Sets all the constraints in \fIlist\fR to true. Also used in combination with \fBconfigure \-limitconstraints true\fR to control an alternative constraint mode as described in \fBTESTS\fR above. Default value is an empty list. .TP \fB\-tmpdir \fIdirectory\fR . Sets the temporary directory to be used by \fBmakeFile\fR, \fBmakeDirectory\fR, \fBviewFile\fR, \fBremoveFile\fR, and \fBremoveDirectory\fR as the default directory where temporary files and directories created by test files should be created. Default value is \fBworkingDirectory\fR. .TP \fB\-testdir \fIdirectory\fR . Sets the directory searched by \fBrunAllTests\fR for test files and subdirectories. Default value is \fBworkingDirectory\fR. .TP \fB\-file \fIpatternList\fR . Sets the list of patterns used by \fBrunAllTests\fR to determine what test files to evaluate. Default value is .QW \fB*.test\fR . .TP \fB\-notfile \fIpatternList\fR . Sets the list of patterns used by \fBrunAllTests\fR to determine what test files to skip. Default value is .QW \fBl.*.test\fR , so that any SCCS lock files are skipped. .TP \fB\-relateddir \fIpatternList\fR . Sets the list of patterns used by \fBrunAllTests\fR to determine what subdirectories to search for an \fBall.tcl\fR file. Default value is .QW \fB*\fR . .TP \fB\-asidefromdir \fIpatternList\fR . Sets the list of patterns used by \fBrunAllTests\fR to determine what subdirectories to skip when searching for an \fBall.tcl\fR file. Default value is an empty list. .TP \fB\-match \fIpatternList\fR . Set the list of patterns used by \fBtest\fR to determine whether a test should be run. Default value is .QW \fB*\fR . .TP \fB\-skip \fIpatternList\fR . Set the list of patterns used by \fBtest\fR to determine whether a test should be skipped. Default value is an empty list. .TP \fB\-load \fIscript\fR . Sets a script to be evaluated by \fBloadTestedCommands\fR. Default value is an empty script. .TP \fB\-loadfile \fIfilename\fR . Sets the filename from which to read a script to be evaluated by \fBloadTestedCommands\fR. This is an alternative to \fB\-load\fR. They cannot be used together. .TP \fB\-outfile \fIfilename\fR . Sets the file to which all output produced by tcltest should be written. A file named \fIfilename\fR will be \fBopen\fRed for writing, and the resulting channel will be set as the value of \fBoutputChannel\fR. .TP \fB\-errfile \fIfilename\fR . Sets the file to which all error output produced by tcltest should be written. A file named \fIfilename\fR will be \fBopen\fRed for writing, and the resulting channel will be set as the value of \fBerrorChannel\fR. .SH "CREATING TEST SUITES WITH TCLTEST" .PP The fundamental element of a test suite is the individual \fBtest\fR command. We begin with several examples. .IP [1] Test of a script that returns normally. .RS .PP .CS \fBtest\fR example-1.0 {normal return} { format %s value } value .CE .RE .IP [2] Test of a script that requires context setup and cleanup. Note the bracing and indenting style that avoids any need for line continuation. .RS .PP .CS \fBtest\fR example-1.1 {test file existence} -setup { set file [makeFile {} test] } -body { file exists $file } -cleanup { removeFile test } -result 1 .CE .RE .IP [3] Test of a script that raises an error. .RS .PP .CS \fBtest\fR example-1.2 {error return} -body { error message } -returnCodes error -result message .CE .RE .IP [4] Test with a constraint. .RS .PP .CS \fBtest\fR example-1.3 {user owns created files} -constraints { unix } -setup { set file [makeFile {} test] } -body { file attributes $file -owner } -cleanup { removeFile test } -result $::tcl_platform(user) .CE .RE .PP At the next higher layer of organization, several \fBtest\fR commands are gathered together into a single test file. Test files should have names with the .QW \fB.test\fR extension, because that is the default pattern used by \fBrunAllTests\fR to find test files. It is a good rule of thumb to have one test file for each source code file of your project. It is good practice to edit the test file and the source code file together, keeping tests synchronized with code changes. .PP Most of the code in the test file should be the \fBtest\fR commands. Use constraints to skip tests, rather than conditional evaluation of \fBtest\fR. .IP [5] Recommended system for writing conditional tests, using constraints to guard: .RS .PP .CS \fBtestConstraint\fR X [expr $myRequirement] \fBtest\fR goodConditionalTest {} X { # body } result .CE .RE .IP [6] Discouraged system for writing conditional tests, using \fBif\fR to guard: .RS .PP .CS if $myRequirement { \fBtest\fR badConditionalTest {} { #body } result } .CE .RE .PP Use the \fB\-setup\fR and \fB\-cleanup\fR options to establish and release all context requirements of the test body. Do not make tests depend on prior tests in the file. Those prior tests might be skipped. If several consecutive tests require the same context, the appropriate setup and cleanup scripts may be stored in variable for passing to each tests \fB\-setup\fR and \fB\-cleanup\fR options. This is a better solution than performing setup outside of \fBtest\fR commands, because the setup will only be done if necessary, and any errors during setup will be reported, and not cause the test file to abort. .PP A test file should be able to be combined with other test files and not interfere with them, even when \fBconfigure \-singleproc 1\fR causes all files to be evaluated in a common interpreter. A simple way to achieve this is to have your tests define all their commands and variables in a namespace that is deleted when the test file evaluation is complete. A good namespace to use is a child namespace \fBtest\fR of the namespace of the module you are testing. .PP A test file should also be able to be evaluated directly as a script, not depending on being called by a master \fBrunAllTests\fR. This means that each test file should process command line arguments to give the tester all the configuration control that \fBtcltest\fR provides. .PP After all \fBtest\fRs in a test file, the command \fBcleanupTests\fR should be called. .IP [7] Here is a sketch of a sample test file illustrating those points: .RS .PP .CS package require tcltest 2.2 eval \fB::tcltest::configure\fR $argv package require example namespace eval ::example::test { namespace import ::tcltest::* \fBtestConstraint\fR X [expr {...}] variable SETUP {#common setup code} variable CLEANUP {#common cleanup code} \fBtest\fR example-1 {} -setup $SETUP -body { # First test } -cleanup $CLEANUP -result {...} \fBtest\fR example-2 {} -constraints X -setup $SETUP -body { # Second test; constrained } -cleanup $CLEANUP -result {...} \fBtest\fR example-3 {} { # Third test; no context required } {...} \fBcleanupTests\fR } namespace delete ::example::test .CE .RE .PP The next level of organization is a full test suite, made up of several test files. One script is used to control the entire suite. The basic function of this script is to call \fBrunAllTests\fR after doing any necessary setup. This script is usually named \fBall.tcl\fR because that is the default name used by \fBrunAllTests\fR when combining multiple test suites into one testing run. .IP [8] Here is a sketch of a sample test suite master script: .RS .PP .CS package require Tcl 8.4 package require tcltest 2.2 package require example \fB::tcltest::configure\fR -testdir \e [file dirname [file normalize [info script]]] eval \fB::tcltest::configure\fR $argv \fB::tcltest::runAllTests\fR .CE .RE .SH COMPATIBILITY .PP A number of commands and variables in the \fB::tcltest\fR namespace provided by earlier releases of \fBtcltest\fR have not been documented here. They are no longer part of the supported public interface of \fBtcltest\fR and should not be used in new test suites. However, to continue to support existing test suites written to the older interface specifications, many of those deprecated commands and variables still work as before. For example, in many circumstances, \fBconfigure\fR will be automatically called shortly after \fBpackage require\fR \fBtcltest 2.1\fR succeeds with arguments from the variable \fB::argv\fR. This is to support test suites that depend on the old behavior that \fBtcltest\fR was automatically configured from command line arguments. New test files should not depend on this, but should explicitly include .PP .CS eval \fB::tcltest::configure\fR $::argv .CE .PP or .PP .CS \fB::tcltest::configure\fR {*}$::argv .CE .PP to establish a configuration from command line arguments. .SH "KNOWN ISSUES" There are two known issues related to nested evaluations of \fBtest\fR. The first issue relates to the stack level in which test scripts are executed. Tests nested within other tests may be executed at the same stack level as the outermost test. For example, in the following code: .PP .CS \fBtest\fR level-1.1 {level 1} { -body { \fBtest\fR level-2.1 {level 2} { } } } .CE .PP any script executed in level-2.1 may be executed at the same stack level as the script defined for level-1.1. .PP In addition, while two \fBtest\fRs have been run, results will only be reported by \fBcleanupTests\fR for tests at the same level as test level-1.1. However, test results for all tests run prior to level-1.1 will be available when test level-2.1 runs. What this means is that if you try to access the test results for test level-2.1, it will may say that .QW m tests have run, .QW n tests have been skipped, .QW o tests have passed and .QW p tests have failed, where .QW m , .QW n , .QW o , and .QW p refer to tests that were run at the same test level as test level-1.1. .PP Implementation of output and error comparison in the test command depends on usage of \fBputs\fR in your application code. Output is intercepted by redefining the global \fBputs\fR command while the defined test script is being run. Errors thrown by C procedures or printed directly from C applications will not be caught by the \fBtest\fR command. Therefore, usage of the \fB\-output\fR and \fB\-errorOutput\fR options to \fBtest\fR is useful only for pure Tcl applications that use \fBputs\fR to produce output. .SH KEYWORDS test, test harness, test suite .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/fconfigure.n0000644000175000017500000003005612663660065014646 0ustar sergeisergei'\" '\" 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 fconfigure n 8.3 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fconfigure \- Set and get options on a channel .SH SYNOPSIS .nf \fBfconfigure \fIchannelId\fR \fBfconfigure \fIchannelId\fR \fIname\fR \fBfconfigure \fIchannelId\fR \fIname value \fR?\fIname value ...\fR? .fi .BE .SH DESCRIPTION .PP The \fBfconfigure\fR command sets and retrieves options for channels. .PP \fIChannelId\fR identifies the channel for which to set or query an option and must refer to an open channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. .PP If no \fIname\fR or \fIvalue\fR arguments are supplied, the command returns a list containing alternating option names and values for the channel. If \fIname\fR is supplied but no \fIvalue\fR then the command returns the current value of the given option. If one or more pairs of \fIname\fR and \fIvalue\fR are supplied, the command sets each of the named options to the corresponding \fIvalue\fR; in this case the return value is an empty string. .PP The options described below are supported for all channels. In addition, each channel type may add options that only it supports. See the manual entry for the command that creates each type of channels for the options that that specific type of channel supports. For example, see the manual entry for the \fBsocket\fR command for additional options for sockets, and the \fBopen\fR command for additional options for serial devices. .TP \fB\-blocking\fR \fIboolean\fR The \fB\-blocking\fR option determines whether I/O operations on the channel can cause the process to block indefinitely. The value of the option must be a proper boolean value. Channels are normally in blocking mode; if a channel is placed into nonblocking mode it will affect the operation of the \fBgets\fR, \fBread\fR, \fBputs\fR, \fBflush\fR, and \fBclose\fR commands by allowing them to operate asynchronously; see the documentation for those commands for details. For nonblocking mode to work correctly, the application must be using the Tcl event loop (e.g. by calling \fBTcl_DoOneEvent\fR or invoking the \fBvwait\fR command). .TP \fB\-buffering\fR \fInewValue\fR . If \fInewValue\fR is \fBfull\fR then the I/O system will buffer output until its internal buffer is full or until the \fBflush\fR command is invoked. If \fInewValue\fR is \fBline\fR, then the I/O system will automatically flush output for the channel whenever a newline character is output. If \fInewValue\fR is \fBnone\fR, the I/O system will flush automatically after every output operation. The default is for \fB\-buffering\fR to be set to \fBfull\fR except for channels that connect to terminal-like devices; for these channels the initial setting is \fBline\fR. Additionally, \fBstdin\fR and \fBstdout\fR are initially set to \fBline\fR, and \fBstderr\fR is set to \fBnone\fR. .TP \fB\-buffersize\fR \fInewSize\fR . \fINewvalue\fR must be an integer; its value is used to set the size of buffers, in bytes, subsequently allocated for this channel to store input or output. \fINewvalue\fR must be between one and one million, allowing buffers of one to one million bytes in size. .TP \fB\-encoding\fR \fIname\fR . This option is used to specify the encoding of the channel, so that the data can be converted to and from Unicode for use in Tcl. For instance, in order for Tcl to read characters from a Japanese file in \fBshiftjis\fR and properly process and display the contents, the encoding would be set to \fBshiftjis\fR. Thereafter, when reading from the channel, the bytes in the Japanese file would be converted to Unicode as they are read. Writing is also supported \- as Tcl strings are written to the channel they will automatically be converted to the specified encoding on output. .RS .PP If a file contains pure binary data (for instance, a JPEG image), the encoding for the channel should be configured to be \fBbinary\fR. Tcl will then assign no interpretation to the data in the file and simply read or write raw bytes. The Tcl \fBbinary\fR command can be used to manipulate this byte-oriented data. It is usually better to set the \fB\-translation\fR option to \fBbinary\fR when you want to transfer binary data, as this turns off the other automatic interpretations of the bytes in the stream as well. .PP The default encoding for newly opened channels is the same platform- and locale-dependent system encoding used for interfacing with the operating system, as returned by \fBencoding system\fR. .RE .TP \fB\-eofchar\fR \fIchar\fR .TP \fB\-eofchar\fR \fB{\fIinChar outChar\fB}\fR . This option supports DOS file systems that use Control-z (\ex1a) as an end of file marker. If \fIchar\fR is not an empty string, then this character signals end-of-file when it is encountered during input. For output, the end-of-file character is output when the channel is closed. If \fIchar\fR is the empty string, then there is no special end of file character marker. For read-write channels, a two-element list specifies the end of file marker for input and output, respectively. As a convenience, when setting the end-of-file character for a read-write channel you can specify a single value that will apply to both reading and writing. When querying the end-of-file character of a read-write channel, a two-element list will always be returned. The default value for \fB\-eofchar\fR is the empty string in all cases except for files under Windows. In that case the \fB\-eofchar\fR is Control-z (\ex1a) for reading and the empty string for writing. The acceptable range for \fB\-eofchar\fR values is \ex01 - \ex7f; attempting to set \fB\-eofchar\fR to a value outside of this range will generate an error. .TP \fB\-translation\fR \fImode\fR .TP \fB\-translation\fR \fB{\fIinMode outMode\fB}\fR . In Tcl scripts the end of a line is always represented using a single newline character (\en). However, in actual files and devices the end of a line may be represented differently on different platforms, or even for different devices on the same platform. For example, under UNIX newlines are used in files, whereas carriage-return-linefeed sequences are normally used in network connections. On input (i.e., with \fBgets\fR and \fBread\fR) the Tcl I/O system automatically translates the external end-of-line representation into newline characters. Upon output (i.e., with \fBputs\fR), the I/O system translates newlines to the external end-of-line representation. The default translation mode, \fBauto\fR, handles all the common cases automatically, but the \fB\-translation\fR option provides explicit control over the end of line translations. .RS .PP The value associated with \fB\-translation\fR is a single item for read-only and write-only channels. The value is a two-element list for read-write channels; the read translation mode is the first element of the list, and the write translation mode is the second element. As a convenience, when setting the translation mode for a read-write channel you can specify a single value that will apply to both reading and writing. When querying the translation mode of a read-write channel, a two-element list will always be returned. The following values are currently supported: .TP \fBauto\fR . As the input translation mode, \fBauto\fR treats any of newline (\fBlf\fR), carriage return (\fBcr\fR), or carriage return followed by a newline (\fBcrlf\fR) as the end of line representation. The end of line representation can even change from line-to-line, and all cases are translated to a newline. As the output translation mode, \fBauto\fR chooses a platform specific representation; for sockets on all platforms Tcl chooses \fBcrlf\fR, for all Unix flavors, it chooses \fBlf\fR, and for the various flavors of Windows it chooses \fBcrlf\fR. The default setting for \fB\-translation\fR is \fBauto\fR for both input and output. .TP \fBbinary\fR . No end-of-line translations are performed. This is nearly identical to \fBlf\fR mode, except that in addition \fBbinary\fR mode also sets the end-of-file character to the empty string (which disables it) and sets the encoding to \fBbinary\fR (which disables encoding filtering). See the description of \fB\-eofchar\fR and \fB\-encoding\fR for more information. .RS .PP Internally, i.e. when it comes to the actual behaviour of the translator this value \fBis\fR identical to \fBlf\fR and is therefore reported as such when queried. Even if \fBbinary\fR was used to set the translation. .RE .TP \fBcr\fR . The end of a line in the underlying file or device is represented by a single carriage return character. As the input translation mode, \fBcr\fR mode converts carriage returns to newline characters. As the output translation mode, \fBcr\fR mode translates newline characters to carriage returns. .TP \fBcrlf\fR . The end of a line in the underlying file or device is represented by a carriage return character followed by a linefeed character. As the input translation mode, \fBcrlf\fR mode converts carriage-return-linefeed sequences to newline characters. As the output translation mode, \fBcrlf\fR mode translates newline characters to carriage-return-linefeed sequences. This mode is typically used on Windows platforms and for network connections. .TP \fBlf\fR . The end of a line in the underlying file or device is represented by a single newline (linefeed) character. In this mode no translations occur during either input or output. This mode is typically used on UNIX platforms. .RE .PP .SH "STANDARD CHANNELS" .PP The Tcl standard channels (\fBstdin\fR, \fBstdout\fR, and \fBstderr\fR) can be configured through this command like every other channel opened by the Tcl library. Beyond the standard options described above they will also support any special option according to their current type. If, for example, a Tcl application is started by the \fBinet\fR super-server common on Unix system its Tcl standard channels will be sockets and thus support the socket options. .SH EXAMPLES .PP Instruct Tcl to always send output to \fBstdout\fR immediately, whether or not it is to a terminal: .PP .CS \fBfconfigure\fR stdout -buffering none .CE .PP Open a socket and read lines from it without ever blocking the processing of other events: .PP .CS set s [socket some.where.com 12345] \fBfconfigure\fR $s -blocking 0 fileevent $s readable "readMe $s" proc readMe chan { if {[gets $chan line] < 0} { if {[eof $chan]} { close $chan return } # Could not read a complete line this time; Tcl's # internal buffering will hold the partial line for us # until some more data is available over the socket. } else { puts stdout $line } } .CE .PP Read a PPM-format image from a file: .PP .CS # Open the file and put it into Unix ASCII mode set f [open teapot.ppm] \fBfconfigure\fR $f \-encoding ascii \-translation lf # Get the header if {[gets $f] ne "P6"} { error "not a raw\-bits PPM" } # Read lines until we have got non-comment lines # that supply us with three decimal values. set words {} while {[llength $words] < 3} { gets $f line if {[string match "#*" $line]} continue lappend words {*}[join [scan $line %d%d%d]] } # Those words supply the size of the image and its # overall depth per channel. Assign to variables. lassign $words xSize ySize depth # Now switch to binary mode to pull in the data, # one byte per channel (red,green,blue) per pixel. \fBfconfigure\fR $f \-translation binary set numDataBytes [expr {3 * $xSize * $ySize}] set data [read $f $numDataBytes] close $f .CE .SH "SEE ALSO" close(n), flush(n), gets(n), open(n), puts(n), read(n), socket(n), Tcl_StandardChannels(3) .SH KEYWORDS blocking, buffering, carriage return, end of line, flushing, linemode, newline, nonblocking, platform, translation, encoding, filter, byte array, binary '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/coroutine.n0000644000175000017500000001477312663660065014536 0ustar sergeisergei'\" '\" Copyright (c) 2009 Donal K. Fellows. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH coroutine n 8.6 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME coroutine, yield, yieldto \- Create and produce values from coroutines .SH SYNOPSIS .nf \fBcoroutine \fIname command\fR ?\fIarg...\fR? \fByield\fR ?\fIvalue\fR? .VS TIP396 \fByieldto\fR \fIcommand\fR ?\fIarg...\fR? \fIname\fR ?\fIvalue...\fR? .VE TIP396 .fi .BE .SH DESCRIPTION .PP The \fBcoroutine\fR command creates a new coroutine context (with associated command) named \fIname\fR and executes that context by calling \fIcommand\fR, passing in the other remaining arguments without further interpretation. Once \fIcommand\fR returns normally or with an exception (e.g., an error) the coroutine context \fIname\fR is deleted. .PP Within the context, values may be generated as results by using the \fByield\fR command; if no \fIvalue\fR is supplied, the empty string is used. When that is called, the context will suspend execution and the \fBcoroutine\fR command will return the argument to \fByield\fR. The execution of the context can then be resumed by calling the context command, optionally passing in the \fIsingle\fR value to use as the result of the \fByield\fR call that caused the context to be suspended. If the coroutine context never yields and instead returns conventionally, the result of the \fBcoroutine\fR command will be the result of the evaluation of the context. .PP .VS TIP396 The coroutine may also suspend its execution by use of the \fByieldto\fR command, which instead of returning, cedes execution to some command called \fIcommand\fR (resolved in the context of the coroutine) and to which \fIany number\fR of arguments may be passed. Since every coroutine has a context command, \fByieldto\fR can be used to transfer control directly from one coroutine to another (this is only advisable if the two coroutines are expecting this to happen) but \fIany\fR command may be the target. If a coroutine is suspended by this mechanism, the coroutine processing can be resumed by calling the context command optionally passing in an arbitrary number of arguments. The return value of the \fByieldto\fR call will be the list of arguments passed to the context command; it is up to the caller to decide what to do with those values. .PP The recommended way of writing a version of \fByield\fR that allows resumption with multiple arguments is by using \fByieldto\fR and the \fBreturn\fR command, like this: .PP .CS proc yieldm {value} { \fByieldto\fR return -level 0 $value } .CE .VE TIP396 .PP The coroutine can also be deleted by destroying the command \fIname\fR, and the name of the current coroutine can be retrieved by using \fBinfo coroutine\fR. If there are deletion traces on variables in the coroutine's implementation, they will fire at the point when the coroutine is explicitly deleted (or, naturally, if the command returns conventionally). .PP At the point when \fIcommand\fR is called, the current namespace will be the global namespace and there will be no stack frames above it (in the sense of \fBupvar\fR and \fBuplevel\fR). However, which command to call will be determined in the namespace that the \fBcoroutine\fR command was called from. .SH EXAMPLES .PP This example shows a coroutine that will produce an infinite sequence of even values, and a loop that consumes the first ten of them. .PP .CS proc allNumbers {} { \fByield\fR set i 0 while 1 { \fByield\fR $i incr i 2 } } \fBcoroutine\fR nextNumber allNumbers for {set i 0} {$i < 10} {incr i} { puts "received [\fInextNumber\fR]" } rename nextNumber {} .CE .PP In this example, the coroutine acts to add up the arguments passed to it. .PP .CS \fBcoroutine\fR accumulator apply {{} { set x 0 while 1 { incr x [\fByield\fR $x] } }} for {set i 0} {$i < 10} {incr i} { puts "$i -> [\fIaccumulator\fR $i]" } .CE .PP This example demonstrates the use of coroutines to implement the classic Sieve of Eratosthenes algorithm for finding prime numbers. Note the creation of coroutines inside a coroutine. .PP .CS proc filterByFactor {source n} { \fByield\fR [info coroutine] while 1 { set x [\fI$source\fR] if {$x % $n} { \fByield\fR $x } } } \fBcoroutine\fR allNumbers apply {{} {while 1 {\fByield\fR [incr x]}}} \fBcoroutine\fR eratosthenes apply {c { \fByield\fR while 1 { set n [\fI$c\fR] \fByield\fR $n set c [\fBcoroutine\fR prime$n filterByFactor $c $n] } }} allNumbers for {set i 1} {$i <= 20} {incr i} { puts "prime#$i = [\fIeratosthenes\fR]" } .CE .PP .VS TIP396 This example shows how a value can be passed around a group of three coroutines that yield to each other: .PP .CS proc juggler {name target {value ""}} { if {$value eq ""} { set value [\fByield\fR [info coroutine]] } while {$value ne ""} { puts "$name : $value" set value [string range $value 0 end-1] lassign [\fByieldto\fR $target $value] value } } \fBcoroutine\fR j1 juggler Larry [ \fBcoroutine\fR j2 juggler Curly [ \fBcoroutine\fR j3 juggler Moe j1]] "Nyuck!Nyuck!Nyuck!" .CE .VE TIP396 .SS "DETAILED SEMANTICS" .PP This example demonstrates that coroutines start from the global namespace, and that \fIcommand\fR resolution happens before the coroutine stack is created. .PP .CS proc report {where level} { # Where was the caller called from? set ns [uplevel 2 {namespace current}] \fByield\fR "made $where $level context=$ns name=[info coroutine]" } proc example {} { report outer [info level] } namespace eval demo { proc example {} { report inner [info level] } proc makeExample {} { puts "making from [info level]" puts [\fBcoroutine\fR coroEg example] } makeExample } .CE .PP Which produces the output below. In particular, we can see that stack manipulation has occurred (comparing the levels from the first and second line) and that the parent level in the coroutine is the global namespace. We can also see that coroutine names are local to the current namespace if not qualified, and that coroutines may yield at depth (e.g., in called procedures). .PP .CS making from 2 made inner 1 context=:: name=::demo::coroEg .CE .SH "SEE ALSO" apply(n), info(n), proc(n), return(n) .SH KEYWORDS coroutine, generator '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/RegConfig.30000644000175000017500000001037012663660065014264 0ustar sergeisergei'\" '\" Copyright (c) 2002 Andreas Kupries '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_RegisterConfig 3 8.4 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_RegisterConfig \- procedures to register embedded configuration information .SH SYNOPSIS .nf \fB#include \fR .sp void \fBTcl_RegisterConfig\fR(\fIinterp, pkgName, configuration, valEncoding\fR) .sp .SH ARGUMENTS .AS Tcl_Interp *configuration .AP Tcl_Interp *interp in Refers to the interpreter the embedded configuration information is registered for. Must not be NULL. .AP "const char" *pkgName in Contains the name of the package registering the embedded 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 is signaled by either a key identical to NULL, or a key referring to the empty string. .AP "const char" *valEncoding in Contains the name of the encoding used to store the configuration values as ASCII string. This means that this information is in UTF-8 too. Must not be NULL. .BE .SH DESCRIPTION .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 Tcl-level interface for querying this information. .PP To embed configuration information into their binary 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. .PP \fBTcl_RegisterConfig\fR takes four arguments; first, a reference to the interpreter we are registering the information with, second, the name of the package registering its configuration information, third, a pointer to an array of structures, and fourth a string declaring the encoding used by the configuration values. .PP The string \fIvalEncoding\fR contains the name of an encoding known to Tcl. All these names are use only characters in the ASCII subset of UTF-8 and are thus implicitly in the UTF-8 encoding. It is expected that keys are legible English text and therefore using the ASCII subset of UTF-8. In other words, they are expected to be in UTF-8 too. The values associated with the keys can be any string however. For these the contents of \fIvalEncoding\fR define which encoding was used to represent the characters of the strings. .PP Each element of the \fIconfiguration\fR array refers to two strings containing the key and the value associated with that key. The end of the array is signaled by either an empty key or a key identical to NULL. The function makes \fBno\fR copy of the \fIconfiguration\fR array. This means that the caller has to make sure that the memory holding this array is never released. This is the meaning behind the word \fBnon-volatile\fR used earlier. The easiest way to accomplish this is to define a global static array of Tcl_Config entries. See the file .QW generic/tclPkgConfig.c in the sources of the Tcl core for an example. .PP When called \fBTcl_RegisterConfig\fR will .IP (1) create a namespace having the provided \fIpkgName\fR, if not yet existing. .IP (2) create the command \fBpkgconfig\fR in that namespace and link it to the provided information so that the keys from \fIconfiguration\fR and their associated values can be retrieved through calls to \fBpkgconfig\fR. .PP The command \fBpkgconfig\fR will provide two subcommands, \fBlist\fR and \fBget\fR: .RS .TP ::\fIpkgName\fR::\fBpkgconfig\fR list Returns a list containing the names of all defined keys. .TP ::\fIpkgName\fR::\fBpkgconfig\fR get \fIkey\fR Returns the configuration value associated with the specified \fIkey\fR. .RE .SH TCL_CONFIG .PP The \fBTcl_Config\fR structure contains the following fields: .PP .CS typedef struct Tcl_Config { const char *\fIkey\fR; const char *\fIvalue\fR; } \fBTcl_Config\fR; .CE .\" No cross references yet. .\" .SH "SEE ALSO" .SH KEYWORDS embedding, configuration, binary library tcl8.6.5/doc/read.n0000644000175000017500000000676712663660065013446 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 read n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME read \- Read from a channel .SH SYNOPSIS \fBread \fR?\fB\-nonewline\fR? \fIchannelId\fR .sp \fBread \fIchannelId numChars\fR .BE .SH DESCRIPTION .PP In the first form, the \fBread\fR command reads all of the data from \fIchannelId\fR up to the end of the file. If the \fB\-nonewline\fR switch is specified then the last character of the file is discarded if it is a newline. In the second form, the extra argument specifies how many characters to read. Exactly that many characters will be read and returned, unless there are fewer than \fInumChars\fR left in the file; in this case all the remaining characters are returned. If the channel is configured to use a multi-byte encoding, then the number of characters read may not be the same as the number of bytes read. .PP \fIChannelId\fR must be an identifier for an open channel such as the Tcl standard input channel (\fBstdin\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. The channel must have been opened for input. .PP If \fIchannelId\fR is in nonblocking mode, the command may not read as many characters as requested: once all available input has been read, the command will return the data that is available rather than blocking for more input. If the channel is configured to use a multi-byte encoding, then there may actually be some bytes remaining in the internal buffers that do not form a complete character. These bytes will not be returned until a complete character is available or end-of-file is reached. The \fB\-nonewline\fR switch is ignored if the command returns before reaching the end of the file. .PP \fBRead\fR translates end-of-line sequences in the input into newline characters according to the \fB\-translation\fR option for the channel. See the \fBfconfigure\fR manual entry for a discussion on ways in which \fBfconfigure\fR will alter input. .SH "USE WITH SERIAL PORTS" '\" Note: this advice actually applies to many versions of Tcl .PP For most applications a channel connected to a serial port should be configured to be nonblocking: \fBfconfigure\fI channelId \fB\-blocking \fI0\fR. Then \fBread\fR behaves much like described above. Care must be taken when using \fBread\fR on blocking serial ports: .TP \fBread \fIchannelId numChars\fR . In this form \fBread\fR blocks until \fInumChars\fR have been received from the serial port. .TP \fBread \fIchannelId\fR . In this form \fBread\fR blocks until the reception of the end-of-file character, see \fBfconfigure\fR \fB\-eofchar\fR. If there no end-of-file character has been configured for the channel, then \fBread\fR will block forever. .SH "EXAMPLE" .PP This example code reads a file all at once, and splits it into a list, with each line in the file corresponding to an element in the list: .PP .CS set fl [open /proc/meminfo] set data [\fBread\fR $fl] close $fl set lines [split $data \en] .CE .SH "SEE ALSO" file(n), eof(n), fblocked(n), fconfigure(n), Tcl_StandardChannels(3) .SH KEYWORDS blocking, channel, end of line, end of file, nonblocking, read, translation, encoding '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/AllowExc.30000644000175000017500000000311412663660065014135 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_AllowExceptions 3 7.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_AllowExceptions \- allow all exceptions in next script evaluation .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_AllowExceptions\fR(\fIinterp\fR) .SH ARGUMENTS .AS Tcl_Interp *interp .AP Tcl_Interp *interp in Interpreter in which script will be evaluated. .BE .SH DESCRIPTION .PP If a script is evaluated at top-level (i.e. no other scripts are pending evaluation when the script is invoked), and if the script terminates with a completion code other than \fBTCL_OK\fR, \fBTCL_ERROR\fR or \fBTCL_RETURN\fR, then Tcl normally converts this into a \fBTCL_ERROR\fR return with an appropriate message. The particular script evaluation procedures of Tcl that act in the manner are \fBTcl_EvalObjEx\fR, \fBTcl_EvalObjv\fR, \fBTcl_Eval\fR, \fBTcl_EvalEx\fR, \fBTcl_GlobalEval\fR, \fBTcl_GlobalEvalObj\fR, \fBTcl_VarEval\fR and \fBTcl_VarEvalVA\fR. .PP However, if \fBTcl_AllowExceptions\fR is invoked immediately before calling one of those a procedures, then arbitrary completion codes are permitted from the script, and they are returned without modification. This is useful in cases where the caller can deal with exceptions such as \fBTCL_BREAK\fR or \fBTCL_CONTINUE\fR in a meaningful way. .SH KEYWORDS continue, break, exception, interpreter tcl8.6.5/doc/DString.30000644000175000017500000001367412663660065014005 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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_DString 3 7.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_DStringStartSublist, Tcl_DStringEndSublist, Tcl_DStringLength, Tcl_DStringValue, Tcl_DStringSetLength, Tcl_DStringTrunc, Tcl_DStringFree, Tcl_DStringResult, Tcl_DStringGetResult \- manipulate dynamic strings .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_DStringInit\fR(\fIdsPtr\fR) .sp char * \fBTcl_DStringAppend\fR(\fIdsPtr, bytes, length\fR) .sp char * \fBTcl_DStringAppendElement\fR(\fIdsPtr, element\fR) .sp \fBTcl_DStringStartSublist\fR(\fIdsPtr\fR) .sp \fBTcl_DStringEndSublist\fR(\fIdsPtr\fR) .sp int \fBTcl_DStringLength\fR(\fIdsPtr\fR) .sp char * \fBTcl_DStringValue\fR(\fIdsPtr\fR) .sp \fBTcl_DStringSetLength\fR(\fIdsPtr, newLength\fR) .sp \fBTcl_DStringTrunc\fR(\fIdsPtr, newLength\fR) .sp \fBTcl_DStringFree\fR(\fIdsPtr\fR) .sp \fBTcl_DStringResult\fR(\fIinterp, dsPtr\fR) .sp \fBTcl_DStringGetResult\fR(\fIinterp, dsPtr\fR) .SH ARGUMENTS .AS Tcl_DString newLength in/out .AP Tcl_DString *dsPtr in/out Pointer to structure that is used to manage a dynamic string. .AP "const char" *bytes in Pointer to characters to append to dynamic string. .AP "const char" *element in Pointer to characters to append as list element to dynamic string. .AP int length in Number of bytes from \fIbytes\fR to add to dynamic string. If -1, add all characters up to null terminating character. .AP int newLength in New length for dynamic string, not including null terminating character. .AP Tcl_Interp *interp in/out Interpreter whose result is to be set from or moved to the dynamic string. .BE .SH DESCRIPTION .PP Dynamic strings provide a mechanism for building up arbitrarily long strings by gradually appending information. If the dynamic string is short then there will be no memory allocation overhead; as the string gets larger, additional space will be allocated as needed. .PP \fBTcl_DStringInit\fR initializes a dynamic string to zero length. The Tcl_DString structure must have been allocated by the caller. No assumptions are made about the current state of the structure; anything already in it is discarded. If the structure has been used previously, \fBTcl_DStringFree\fR should be called first to free up any memory allocated for the old string. .PP \fBTcl_DStringAppend\fR adds new information to a dynamic string, allocating more memory for the string if needed. If \fIlength\fR is less than zero then everything in \fIbytes\fR is appended to the dynamic string; otherwise \fIlength\fR specifies the number of bytes to append. \fBTcl_DStringAppend\fR returns a pointer to the characters of the new string. The string can also be retrieved from the \fIstring\fR field of the Tcl_DString structure. .PP \fBTcl_DStringAppendElement\fR is similar to \fBTcl_DStringAppend\fR except that it does not take a \fIlength\fR argument (it appends all of \fIelement\fR) and it converts the string to a proper list element before appending. \fBTcl_DStringAppendElement\fR adds a separator space before the new list element unless the new list element is the first in a list or sub-list (i.e. either the current string is empty, or it contains the single character .QW { , or the last two characters of the current string are .QW " {" ). \fBTcl_DStringAppendElement\fR returns a pointer to the characters of the new string. .PP \fBTcl_DStringStartSublist\fR and \fBTcl_DStringEndSublist\fR can be used to create nested lists. To append a list element that is itself a sublist, first call \fBTcl_DStringStartSublist\fR, then call \fBTcl_DStringAppendElement\fR for each of the elements in the sublist, then call \fBTcl_DStringEndSublist\fR to end the sublist. \fBTcl_DStringStartSublist\fR appends a space character if needed, followed by an open brace; \fBTcl_DStringEndSublist\fR appends a close brace. Lists can be nested to any depth. .PP \fBTcl_DStringLength\fR is a macro that returns the current length of a dynamic string (not including the terminating null character). \fBTcl_DStringValue\fR is a macro that returns a pointer to the current contents of a dynamic string. .PP .PP \fBTcl_DStringSetLength\fR changes the length of a dynamic string. If \fInewLength\fR is less than the string's current length, then the string is truncated. If \fInewLength\fR is greater than the string's current length, then the string will become longer and new space will be allocated for the string if needed. However, \fBTcl_DStringSetLength\fR will not initialize the new space except to provide a terminating null character; it is up to the caller to fill in the new space. \fBTcl_DStringSetLength\fR does not free up the string's storage space even if the string is truncated to zero length, so \fBTcl_DStringFree\fR will still need to be called. .PP \fBTcl_DStringTrunc\fR changes the length of a dynamic string. This procedure is now deprecated. \fBTcl_DStringSetLength\fR should be used instead. .PP \fBTcl_DStringFree\fR should be called when you are finished using the string. It frees up any memory that was allocated for the string and reinitializes the string's value to an empty string. .PP \fBTcl_DStringResult\fR sets the result of \fIinterp\fR to the value of the dynamic string given by \fIdsPtr\fR. It does this by moving a pointer from \fIdsPtr\fR to the interpreter's result. This saves the cost of allocating new memory and copying the string. \fBTcl_DStringResult\fR also reinitializes the dynamic string to an empty string. .PP \fBTcl_DStringGetResult\fR does the opposite of \fBTcl_DStringResult\fR. It sets the value of \fIdsPtr\fR to the result of \fIinterp\fR and it clears \fIinterp\fR's result. If possible it does this by moving a pointer rather than by copying the string. .SH KEYWORDS append, dynamic string, free, result tcl8.6.5/doc/registry.n0000644000175000017500000001721612663660065014372 0ustar sergeisergei'\" '\" Copyright (c) 1997 Sun Microsystems, Inc. '\" Copyright (c) 2002 ActiveState Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH registry n 1.1 registry "Tcl Bundled Packages" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME registry \- Manipulate the Windows registry .SH SYNOPSIS .sp \fBpackage require registry 1.3\fR .sp \fBregistry \fR?\fI\-mode\fR? \fIoption\fR \fIkeyName\fR ?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP The \fBregistry\fR package provides a general set of operations for manipulating the Windows registry. The package implements the \fBregistry\fR Tcl command. This command is only supported on the Windows platform. Warning: this command should be used with caution as a corrupted registry can leave your system in an unusable state. .PP \fIKeyName\fR is the name of a registry key. Registry keys must be one of the following forms: .RS .PP \fB\e\e\fIhostname\fB\e\fIrootname\fB\e\fIkeypath\fR .PP \fIrootname\fB\e\fIkeypath\fR .PP \fIrootname\fR .RE .PP \fIHostname\fR specifies the name of any valid Windows host that exports its registry. The \fIrootname\fR component must be one of \fBHKEY_LOCAL_MACHINE\fR, \fBHKEY_USERS\fR, \fBHKEY_CLASSES_ROOT\fR, \fBHKEY_CURRENT_USER\fR, \fBHKEY_CURRENT_CONFIG\fR, \fBHKEY_PERFORMANCE_DATA\fR, or \fBHKEY_DYN_DATA\fR. The \fIkeypath\fR can be one or more registry key names separated by backslash (\fB\e\fR) characters. .PP .VS 8.6 The optional \fI\-mode\fR argument indicates which registry to work with; when it is \fB\-32bit\fR the 32-bit registry will be used, and when it is \fB\-64bit\fR the 64-bit registry will be used. If this argument is omitted, the system's default registry will be the subject of the requested operation. .VE 8.6 .PP \fIOption\fR indicates what to do with the registry key name. Any unique abbreviation for \fIoption\fR is acceptable. The valid options are: .TP \fBregistry broadcast \fIkeyName\fR ?\fB\-timeout \fImilliseconds\fR? . Sends a broadcast message to the system and running programs to notify them of certain updates. This is necessary to propagate changes to key registry keys like Environment. The timeout specifies the amount of time, in milliseconds, to wait for applications to respond to the broadcast message. It defaults to 3000. The following example demonstrates how to add a path to the global Environment and notify applications of the change without requiring a logoff/logon step (assumes admin privileges): .RS .PP .CS set regPath [join { HKEY_LOCAL_MACHINE SYSTEM CurrentControlSet Control {Session Manager} Environment } "\e\e"] set curPath [\fBregistry get\fR $regPath "Path"] \fBregistry set\fR $regPath "Path" "$curPath;$addPath" \fBregistry broadcast\fR "Environment" .CE .RE .TP \fBregistry delete \fIkeyName\fR ?\fIvalueName\fR? . If the optional \fIvalueName\fR argument is present, the specified value under \fIkeyName\fR will be deleted from the registry. If the optional \fIvalueName\fR is omitted, the specified key and any subkeys or values beneath it in the registry hierarchy will be deleted. If the key could not be deleted then an error is generated. If the key did not exist, the command has no effect. .TP \fBregistry get \fIkeyName valueName\fR . Returns the data associated with the value \fIvalueName\fR under the key \fIkeyName\fR. If either the key or the value does not exist, then an error is generated. For more details on the format of the returned data, see \fBSUPPORTED TYPES\fR, below. .TP \fBregistry keys \fIkeyName\fR ?\fIpattern\fR? . If \fIpattern\fR is not specified, returns a list of names of all the subkeys of \fIkeyName\fR. If \fIpattern\fR is specified, only those names matching \fIpattern\fR are returned. Matching is determined using the same rules as for \fBstring match\fR. If the specified \fIkeyName\fR does not exist, then an error is generated. .TP \fBregistry set \fIkeyName\fR ?\fIvalueName data \fR?\fItype\fR?? . If \fIvalueName\fR is not specified, creates the key \fIkeyName\fR if it does not already exist. If \fIvalueName\fR is specified, creates the key \fIkeyName\fR and value \fIvalueName\fR if necessary. The contents of \fIvalueName\fR are set to \fIdata\fR with the type indicated by \fItype\fR. If \fItype\fR is not specified, the type \fBsz\fR is assumed. For more details on the data and type arguments, see \fBSUPPORTED TYPES\fR below. .TP \fBregistry type \fIkeyName valueName\fR . Returns the type of the value \fIvalueName\fR in the key \fIkeyName\fR. For more information on the possible types, see \fBSUPPORTED TYPES\fR, below. .TP \fBregistry values \fIkeyName\fR ?\fIpattern\fR? . If \fIpattern\fR is not specified, returns a list of names of all the values of \fIkeyName\fR. If \fIpattern\fR is specified, only those names matching \fIpattern\fR are returned. Matching is determined using the same rules as for \fBstring match\fR. .SH "SUPPORTED TYPES" Each value under a key in the registry contains some data of a particular type in a type-specific representation. The \fBregistry\fR command converts between this internal representation and one that can be manipulated by Tcl scripts. In most cases, the data is simply returned as a Tcl string. The type indicates the intended use for the data, but does not actually change the representation. For some types, the \fBregistry\fR command returns the data in a different form to make it easier to manipulate. The following types are recognized by the registry command: .TP 17 \fBbinary\fR . The registry value contains arbitrary binary data. The data is represented exactly in Tcl, including any embedded nulls. .TP \fBnone\fR . The registry value contains arbitrary binary data with no defined type. The data is represented exactly in Tcl, including any embedded nulls. .TP \fBsz\fR . The registry value contains a null-terminated string. The data is represented in Tcl as a string. .TP \fBexpand_sz\fR . The registry value contains a null-terminated string that contains unexpanded references to environment variables in the normal Windows style (for example, .QW %PATH% ). The data is represented in Tcl as a string. .TP \fBdword\fR . The registry value contains a little-endian 32-bit number. The data is represented in Tcl as a decimal string. .TP \fBdword_big_endian\fR . The registry value contains a big-endian 32-bit number. The data is represented in Tcl as a decimal string. .TP \fBlink\fR . The registry value contains a symbolic link. The data is represented exactly in Tcl, including any embedded nulls. .TP \fBmulti_sz\fR . The registry value contains an array of null-terminated strings. The data is represented in Tcl as a list of strings. .TP \fBresource_list\fR . The registry value contains a device-driver resource list. The data is represented exactly in Tcl, including any embedded nulls. .PP In addition to the symbolically named types listed above, unknown types are identified using a 32-bit integer that corresponds to the type code returned by the system interfaces. In this case, the data is represented exactly in Tcl, including any embedded nulls. .SH "PORTABILITY ISSUES" The registry command is only available on Windows. .SH EXAMPLE Print out how double-clicking on a Tcl script file will invoke a Tcl interpreter: .PP .CS package require registry set ext .tcl # Read the type name set type [\fBregistry get\fR HKEY_CLASSES_ROOT\e\e$ext {}] # Work out where to look for the command set path HKEY_CLASSES_ROOT\e\e$type\e\eShell\e\eOpen\e\ecommand # Read the command! set command [\fBregistry get\fR $path {}] puts "$ext opens with $command" .CE .SH KEYWORDS registry '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/fcopy.n0000644000175000017500000001437112663660065013641 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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 fcopy n 8.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fcopy \- Copy data from one channel to another .SH SYNOPSIS \fBfcopy \fIinchan\fR \fIoutchan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR? .BE .SH DESCRIPTION .PP The \fBfcopy\fR command copies data from one I/O channel, \fIinchan\fR to another I/O channel, \fIoutchan\fR. The \fBfcopy\fR command leverages the buffering in the Tcl I/O system to avoid extra copies and to avoid buffering too much data in main memory when copying large files to slow destinations like network sockets. .PP The \fBfcopy\fR command transfers data from \fIinchan\fR until end of file or \fIsize\fR bytes have been transferred. If no \fB\-size\fR argument is given, then the copy goes until end of file. All the data read from \fIinchan\fR is copied to \fIoutchan\fR. Without the \fB\-command\fR option, \fBfcopy\fR blocks until the copy is complete and returns the number of bytes written to \fIoutchan\fR. .PP The \fB\-command\fR argument makes \fBfcopy\fR work in the background. In this case it returns immediately and the \fIcallback\fR is invoked later when the copy completes. The \fIcallback\fR is called with one or two additional arguments that indicates how many bytes were written to \fIoutchan\fR. If an error occurred during the background copy, the second argument is the error string associated with the error. With a background copy, it is not necessary to put \fIinchan\fR or \fIoutchan\fR into non-blocking mode; the \fBfcopy\fR command takes care of that automatically. However, it is necessary to enter the event loop by using the \fBvwait\fR command or by using Tk. .PP You are not allowed to do other input operations with \fIinchan\fR, or output operations with \fIoutchan\fR, during a background \fBfcopy\fR. The converse is entirely legitimate, as exhibited by the bidirectional fcopy example below. .PP If either \fIinchan\fR or \fIoutchan\fR get closed while the copy is in progress, the current copy is stopped and the command callback is \fInot\fR made. If \fIinchan\fR is closed, then all data already queued for \fIoutchan\fR is written out. .PP Note that \fIinchan\fR can become readable during a background copy. You should turn off any \fBfileevent\fR handlers during a background copy so those handlers do not interfere with the copy. Any wrong-sided I/O attempted (by a \fBfileevent\fR handler or otherwise) will get a .QW "channel busy" error. .PP \fBFcopy\fR translates end-of-line sequences in \fIinchan\fR and \fIoutchan\fR according to the \fB\-translation\fR option for these channels. See the manual entry for \fBfconfigure\fR for details on the \fB\-translation\fR option. The translations mean that the number of bytes read from \fIinchan\fR can be different than the number of bytes written to \fIoutchan\fR. Only the number of bytes written to \fIoutchan\fR is reported, either as the return value of a synchronous \fBfcopy\fR or as the argument to the callback for an asynchronous \fBfcopy\fR. .PP \fBFcopy\fR obeys the encodings and character translations configured for the channels. This means that the incoming characters are converted internally first UTF-8 and then into the encoding of the channel \fBfcopy\fR writes to. See the manual entry for \fBfconfigure\fR for details on the \fB\-encoding\fR and \fB\-translation\fR options. No conversion is done if both channels are set to encoding .QW binary and have matching translations. If only the output channel is set to encoding .QW binary the system will write the internal UTF-8 representation of the incoming characters. If only the input channel is set to encoding .QW binary the system will assume that the incoming bytes are valid UTF-8 characters and convert them according to the output encoding. The behaviour of the system for bytes which are not valid UTF-8 characters is undefined in this case. .SH EXAMPLES .PP The first example transfers the contents of one channel exactly to another. Note that when copying one file to another, it is better to use \fBfile copy\fR which also copies file metadata (e.g. the file access permissions) where possible. .PP .CS fconfigure $in -translation binary fconfigure $out -translation binary \fBfcopy\fR $in $out .CE .PP This second example shows how the callback gets passed the number of bytes transferred. It also uses vwait to put the application into the event loop. Of course, this simplified example could be done without the command callback. .PP .CS proc Cleanup {in out bytes {error {}}} { global total set total $bytes close $in close $out if {[string length $error] != 0} { # error occurred during the copy } } set in [open $file1] set out [socket $server $port] \fBfcopy\fR $in $out -command [list Cleanup $in $out] vwait total .CE .PP The third example copies in chunks and tests for end of file in the command callback. .PP .CS proc CopyMore {in out chunk bytes {error {}}} { global total done incr total $bytes if {([string length $error] != 0) || [eof $in]} { set done $total close $in close $out } else { \fBfcopy\fR $in $out -size $chunk \e -command [list CopyMore $in $out $chunk] } } set in [open $file1] set out [socket $server $port] set chunk 1024 set total 0 \fBfcopy\fR $in $out -size $chunk \e -command [list CopyMore $in $out $chunk] vwait done .CE .PP The fourth example starts an asynchronous, bidirectional fcopy between two sockets. Those could also be pipes from two [open "|hal 9000" r+] (though their conversation would remain secret to the script, since all four fileevent slots are busy). .PP .CS set flows 2 proc Done {dir args} { global flows done puts "$dir is over." incr flows -1 if {$flows<=0} {set done 1} } \fBfcopy\fR $sok1 $sok2 -command [list Done UP] \fBfcopy\fR $sok2 $sok1 -command [list Done DOWN] vwait done .CE .SH "SEE ALSO" eof(n), fblocked(n), fconfigure(n), file(n) .SH KEYWORDS blocking, channel, end of line, end of file, nonblocking, read, translation tcl8.6.5/doc/Tcl.n0000644000175000017500000002466312663660065013250 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 n "8.6" Tcl "Tcl Built-In Commands" .so man.macros .BS .SH NAME Tcl \- Tool Command Language .SH SYNOPSIS Summary of Tcl language syntax. .BE .SH DESCRIPTION .PP The following rules define the syntax and semantics of the Tcl language: .IP "[1] \fBCommands.\fR" A Tcl script is a string containing one or more commands. Semi-colons and newlines are command separators unless quoted as described below. Close brackets are command terminators during command substitution (see below) unless quoted. .IP "[2] \fBEvaluation.\fR" A command is evaluated in two steps. First, the Tcl interpreter breaks the command into \fIwords\fR and performs substitutions as described below. These substitutions are performed in the same way for all commands. Secondly, the first word is used to locate a command procedure to carry out the command, then all of the words of the command are passed to the command procedure. The command procedure is free to interpret each of its words in any way it likes, such as an integer, variable name, list, or Tcl script. Different commands interpret their words differently. .IP "[3] \fBWords.\fR" Words of a command are separated by white space (except for newlines, which are command separators). .IP "[4] \fBDouble quotes.\fR" If the first character of a word is double-quote .PQ \N'34' then the word is terminated by the next double-quote character. If semi-colons, close brackets, or white space characters (including newlines) appear between the quotes then they are treated as ordinary characters and included in the word. Command substitution, variable substitution, and backslash substitution are performed on the characters between the quotes as described below. The double-quotes are not retained as part of the word. .IP "[5] \fBArgument expansion.\fR" If a word starts with the string .QW {*} followed by a non-whitespace character, then the leading .QW {*} is removed and the rest of the word is parsed and substituted as any other word. After substitution, the word is parsed as a list (without command or variable substitutions; backslash substitutions are performed as is normal for a list and individual internal words may be surrounded by either braces or double-quote characters), and its words are added to the command being substituted. For instance, .QW "cmd a {*}{b [c]} d {*}{$e f {g h}}" is equivalent to .QW "cmd a b {[c]} d {$e} f {g h}" . .IP "[6] \fBBraces.\fR" If the first character of a word is an open brace .PQ { and rule [5] does not apply, then the word is terminated by the matching close brace .PQ } "" . Braces nest within the word: for each additional open brace there must be an additional close brace (however, if an open brace or close brace within the word is quoted with a backslash then it is not counted in locating the matching close brace). No substitutions are performed on the characters between the braces except for backslash-newline substitutions described below, nor do semi-colons, newlines, close brackets, or white space receive any special interpretation. The word will consist of exactly the characters between the outer braces, not including the braces themselves. .IP "[7] \fBCommand substitution.\fR" If a word contains an open bracket .PQ [ then Tcl performs \fIcommand substitution\fR. To do this it invokes the Tcl interpreter recursively to process the characters following the open bracket as a Tcl script. The script may contain any number of commands and must be terminated by a close bracket .PQ ] "" . The result of the script (i.e. the result of its last command) is substituted into the word in place of the brackets and all of the characters between them. There may be any number of command substitutions in a single word. Command substitution is not performed on words enclosed in braces. .IP "[8] \fBVariable substitution.\fR" If a word contains a dollar-sign .PQ $ followed by one of the forms described below, then Tcl performs \fIvariable substitution\fR: the dollar-sign and the following characters are replaced in the word by the value of a variable. Variable substitution may take any of the following forms: .RS .TP 15 \fB$\fIname\fR . \fIName\fR is the name of a scalar variable; the name is a sequence of one or more characters that are a letter, digit, underscore, or namespace separators (two or more colons). Letters and digits are \fIonly\fR the standard ASCII ones (\fB0\fR\(en\fB9\fR, \fBA\fR\(en\fBZ\fR and \fBa\fR\(en\fBz\fR). .TP 15 \fB$\fIname\fB(\fIindex\fB)\fR . \fIName\fR gives the name of an array variable and \fIindex\fR gives the name of an element within that array. \fIName\fR must contain only letters, digits, underscores, and namespace separators, and may be an empty string. Letters and digits are \fIonly\fR the standard ASCII ones (\fB0\fR\(en\fB9\fR, \fBA\fR\(en\fBZ\fR and \fBa\fR\(en\fBz\fR). Command substitutions, variable substitutions, and backslash substitutions are performed on the characters of \fIindex\fR. .TP 15 \fB${\fIname\fB}\fR . \fIName\fR is the name of a scalar variable or array element. It may contain any characters whatsoever except for close braces. It indicates an array element if \fIname\fR is in the form .QW \fIarrayName\fB(\fIindex\fB)\fR where \fIarrayName\fR does not contain any open parenthesis characters, .QW \fB(\fR , or close brace characters, .QW \fB}\fR , and \fIindex\fR can be any sequence of characters except for close brace characters. No further substitutions are performed during the parsing of \fIname\fR. .PP There may be any number of variable substitutions in a single word. Variable substitution is not performed on words enclosed in braces. .PP Note that variables may contain character sequences other than those listed above, but in that case other mechanisms must be used to access them (e.g., via the \fBset\fR command's single-argument form). .RE .IP "[9] \fBBackslash substitution.\fR" If a backslash .PQ \e appears within a word then \fIbackslash substitution\fR occurs. In all cases but those described below the backslash is dropped and the following character is treated as an ordinary character and included in the word. This allows characters such as double quotes, close brackets, and dollar signs to be included in words without triggering special processing. The following table lists the backslash sequences that are handled specially, along with the value that replaces each sequence. .RS .TP 7 \e\fBa\fR Audible alert (bell) (Unicode U+000007). .TP 7 \e\fBb\fR Backspace (Unicode U+000008). .TP 7 \e\fBf\fR Form feed (Unicode U+00000C). .TP 7 \e\fBn\fR Newline (Unicode U+00000A). .TP 7 \e\fBr\fR Carriage-return (Unicode U+00000D). .TP 7 \e\fBt\fR Tab (Unicode U+000009). .TP 7 \e\fBv\fR Vertical tab (Unicode U+00000B). .TP 7 \e\fB\fIwhiteSpace\fR . A single space character replaces the backslash, newline, and all spaces and tabs after the newline. This backslash sequence is unique in that it is replaced in a separate pre-pass before the command is actually parsed. This means that it will be replaced even when it occurs between braces, and the resulting space will be treated as a word separator if it is not in braces or quotes. .TP 7 \e\e Backslash .PQ \e "" . .TP 7 \e\fIooo\fR . The digits \fIooo\fR (one, two, or three of them) give a eight-bit octal value for the Unicode character that will be inserted, in the range \fI000\fR\(en\fI377\fR (i.e., the range U+000000\(enU+0000FF). The parser will stop just before this range overflows, or when the maximum of three digits is reached. The upper bits of the Unicode character will be 0. .TP 7 \e\fBx\fIhh\fR . The hexadecimal digits \fIhh\fR (one or two of them) give an eight-bit hexadecimal value for the Unicode character that will be inserted. The upper bits of the Unicode character will be 0 (i.e., the character will be in the range U+000000\(enU+0000FF). .TP 7 \e\fBu\fIhhhh\fR . The hexadecimal digits \fIhhhh\fR (one, two, three, or four of them) give a sixteen-bit hexadecimal value for the Unicode character that will be inserted. The upper bits of the Unicode character will be 0 (i.e., the character will be in the range U+000000\(enU+00FFFF). .TP 7 \e\fBU\fIhhhhhhhh\fR . The hexadecimal digits \fIhhhhhhhh\fR (one up to eight of them) give a twenty-one-bit hexadecimal value for the Unicode character that will be inserted, in the range U+000000\(enU+10FFFF. The parser will stop just before this range overflows, or when the maximum of eight digits is reached. The upper bits of the Unicode character will be 0. .RS .PP The range U+010000\(enU+10FFFD is reserved for the future. .RE .PP Backslash substitution is not performed on words enclosed in braces, except for backslash-newline as described above. .RE .IP "[10] \fBComments.\fR" If a hash character .PQ # appears at a point where Tcl is expecting the first character of the first word of a command, then the hash character and the characters that follow it, up through the next newline, are treated as a comment and ignored. The comment character only has significance when it appears at the beginning of a command. .IP "[11] \fBOrder of substitution.\fR" Each character is processed exactly once by the Tcl interpreter as part of creating the words of a command. For example, if variable substitution occurs then no further substitutions are performed on the value of the variable; the value is inserted into the word verbatim. If command substitution occurs then the nested command is processed entirely by the recursive call to the Tcl interpreter; no substitutions are performed before making the recursive call and no additional substitutions are performed on the result of the nested script. .RS .PP Substitutions take place from left to right, and each substitution is evaluated completely before attempting to evaluate the next. Thus, a sequence like .PP .CS set y [set x 0][incr x][incr x] .CE .PP will always set the variable \fIy\fR to the value, \fI012\fR. .RE .IP "[12] \fBSubstitution and word boundaries.\fR" Substitutions do not affect the word boundaries of a command, except for argument expansion as specified in rule [5]. For example, during variable substitution the entire value of the variable becomes part of a single word, even if the variable's value contains spaces. .SH KEYWORDS backslash, command, comment, script, substitution, variable '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/llength.n0000644000175000017500000000243312663660065014152 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2001 Kevin B. Kenny . All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH llength n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME llength \- Count the number of elements in a list .SH SYNOPSIS \fBllength \fIlist\fR .BE .SH DESCRIPTION .PP Treats \fIlist\fR as a list and returns a decimal string giving the number of elements in it. .SH EXAMPLES .PP The result is the number of elements: .PP .CS % \fBllength\fR {a b c d e} 5 % \fBllength\fR {a b c} 3 % \fBllength\fR {} 0 .CE .PP Elements are not guaranteed to be exactly words in a dictionary sense of course, especially when quoting is used: .PP .CS % \fBllength\fR {a b {c d} e} 4 % \fBllength\fR {a b { } c d e} 6 .CE .PP An empty list is not necessarily an empty string: .PP .CS % set var { }; puts "[string length $var],[\fBllength\fR $var]" 1,0 .CE .SH "SEE ALSO" list(n), lappend(n), lindex(n), linsert(n), lsearch(n), lset(n), lsort(n), lrange(n), lreplace(n) .SH KEYWORDS element, list, length tcl8.6.5/doc/lappend.n0000644000175000017500000000276012663660065014143 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2001 Kevin B. Kenny . All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lappend n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lappend \- Append list elements onto a variable .SH SYNOPSIS \fBlappend \fIvarName \fR?\fIvalue value value ...\fR? .BE .SH DESCRIPTION .PP This command treats the variable given by \fIvarName\fR as a list and appends each of the \fIvalue\fR arguments to that list as a separate element, with spaces between elements. If \fIvarName\fR does not exist, it is created as a list with elements given by the \fIvalue\fR arguments. \fBLappend\fR is similar to \fBappend\fR except that the \fIvalue\fRs are appended as list elements rather than raw text. This command provides a relatively efficient way to build up large lists. For example, .QW "\fBlappend a $b\fR" is much more efficient than .QW "\fBset a [concat $a [list $b]]\fR" when \fB$a\fR is long. .SH EXAMPLE .PP Using \fBlappend\fR to build up a list of numbers. .PP .CS % set var 1 1 % \fBlappend\fR var 2 1 2 % \fBlappend\fR var 3 4 5 1 2 3 4 5 .CE .SH "SEE ALSO" list(n), lindex(n), linsert(n), llength(n), lset(n), lsort(n), lrange(n) .SH KEYWORDS append, element, list, variable tcl8.6.5/doc/Ensemble.30000644000175000017500000002241212663660065014153 0ustar sergeisergei'\" '\" Copyright (c) 2005 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" '\" This documents the C API introduced in TIP#235 '\" .TH Tcl_Ensemble 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CreateEnsemble, Tcl_FindEnsemble, Tcl_GetEnsembleFlags, Tcl_GetEnsembleMappingDict, Tcl_GetEnsembleNamespace, Tcl_GetEnsembleParameterList, Tcl_GetEnsembleUnknownHandler, Tcl_GetEnsembleSubcommandList, Tcl_IsEnsemble, Tcl_SetEnsembleFlags, Tcl_SetEnsembleMappingDict, Tcl_SetEnsembleParameterList, Tcl_SetEnsembleSubcommandList, Tcl_SetEnsembleUnknownHandler \- manipulate ensemble commands .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Command \fBTcl_CreateEnsemble\fR(\fIinterp, name, namespacePtr, ensFlags\fR) .sp Tcl_Command \fBTcl_FindEnsemble\fR(\fIinterp, cmdNameObj, flags\fR) .sp int \fBTcl_IsEnsemble\fR(\fItoken\fR) .sp int \fBTcl_GetEnsembleFlags\fR(\fIinterp, token, ensFlagsPtr\fR) .sp int \fBTcl_SetEnsembleFlags\fR(\fIinterp, token, ensFlags\fR) .sp int \fBTcl_GetEnsembleMappingDict\fR(\fIinterp, token, dictObjPtr\fR) .sp int \fBTcl_SetEnsembleMappingDict\fR(\fIinterp, token, dictObj\fR) .sp .VS 8.6 int \fBTcl_GetEnsembleParameterList\fR(\fIinterp, token, listObjPtr\fR) .sp int \fBTcl_SetEnsembleParameterList\fR(\fIinterp, token, listObj\fR) .VE 8.6 .sp int \fBTcl_GetEnsembleSubcommandList\fR(\fIinterp, token, listObjPtr\fR) .sp int \fBTcl_SetEnsembleSubcommandList\fR(\fIinterp, token, listObj\fR) .sp int \fBTcl_GetEnsembleUnknownHandler\fR(\fIinterp, token, listObjPtr\fR) .sp int \fBTcl_SetEnsembleUnknownHandler\fR(\fIinterp, token, listObj\fR) .sp int \fBTcl_GetEnsembleNamespace\fR(\fIinterp, token, namespacePtrPtr\fR) .SH ARGUMENTS .AS Tcl_Namespace **namespacePtrPtr in/out .AP Tcl_Interp *interp in/out The interpreter in which the ensemble is to be created or found. Also where error result messages are written. The functions whose names start with \fBTcl_GetEnsemble\fR may have a NULL for the \fIinterp\fR, but all other functions must not. .AP "const char" *name in The name of the ensemble command to be created. .AP Tcl_Namespace *namespacePtr in The namespace to which the ensemble command is to be bound, or NULL for the current namespace. .AP int ensFlags in An ORed set of flag bits describing the basic configuration of the ensemble. Currently only one bit has meaning, \fBTCL_ENSEMBLE_PREFIX\fR, which is present when the ensemble command should also match unambiguous prefixes of subcommands. .AP Tcl_Obj *cmdNameObj in A value holding the name of the ensemble command to look up. .AP int flags in An ORed set of flag bits controlling the behavior of \fBTcl_FindEnsemble\fR. Currently only \fBTCL_LEAVE_ERR_MSG\fR is supported. .AP Tcl_Command token in A normal command token that refers to an ensemble command, or which you wish to use for testing as an ensemble command in \fBTcl_IsEnsemble\fR. .AP int *ensFlagsPtr out Pointer to a variable into which to write the current ensemble flag bits; currently only the bit \fBTCL_ENSEMBLE_PREFIX\fR is defined. .AP Tcl_Obj *dictObj in A dictionary value to use for the subcommand to implementation command prefix mapping dictionary in the ensemble. May be NULL if the mapping dictionary is to be removed. .AP Tcl_Obj **dictObjPtr out Pointer to a variable into which to write the current ensemble mapping dictionary. .AP Tcl_Obj *listObj in A list value to use for the list of formal pre-subcommand parameters, the defined list of subcommands in the dictionary or the unknown subcommand handler command prefix. May be NULL if the subcommand list or unknown handler are to be removed. .AP Tcl_Obj **listObjPtr out Pointer to a variable into which to write the current list of formal pre-subcommand parameters, the defined list of subcommands or the current unknown handler prefix. .AP Tcl_Namespace **namespacePtrPtr out Pointer to a variable into which to write the handle of the namespace to which the ensemble is bound. .BE .SH DESCRIPTION An ensemble is a command, bound to some namespace, which consists of a collection of subcommands implemented by other Tcl commands. The first argument to the ensemble command is always interpreted as a selector that states what subcommand to execute. .PP Ensembles are created using \fBTcl_CreateEnsemble\fR, which takes four arguments: the interpreter to work within, the name of the ensemble to create, the namespace within the interpreter to bind the ensemble to, and the default set of ensemble flags. The result of the function is the command token for the ensemble, which may be used to further configure the ensemble using the API described below in \fBENSEMBLE PROPERTIES\fR. .PP Given the name of an ensemble command, the token for that command may be retrieved using \fBTcl_FindEnsemble\fR. If the given command name (in \fIcmdNameObj\fR) does not refer to an ensemble command, the result of the function is NULL and (if the \fBTCL_LEAVE_ERR_MSG\fR bit is set in \fIflags\fR) an error message is left in the interpreter result. .PP A command token may be checked to see if it refers to an ensemble using \fBTcl_IsEnsemble\fR. This returns 1 if the token refers to an ensemble, or 0 otherwise. .SS "ENSEMBLE PROPERTIES" Every ensemble has four read-write properties and a read-only property. The properties are: .TP \fBflags\fR (read-write) . The set of flags for the ensemble, expressed as a bit-field. Currently, the only public flag is \fBTCL_ENSEMBLE_PREFIX\fR which is set when unambiguous prefixes of subcommands are permitted to be resolved to implementations as well as exact matches. The flags may be read and written using \fBTcl_GetEnsembleFlags\fR and \fBTcl_SetEnsembleFlags\fR respectively. The result of both of those functions is a Tcl result code (\fBTCL_OK\fR, or \fBTCL_ERROR\fR if the token does not refer to an ensemble). .TP \fBmapping dictionary\fR (read-write) . A dictionary containing a mapping from subcommand names to lists of words to use as a command prefix (replacing the first two words of the command which are the ensemble command itself and the subcommand name), or NULL if every subcommand is to be mapped to the command with the same unqualified name in the ensemble's bound namespace. Defaults to NULL. May be read and written using \fBTcl_GetEnsembleMappingDict\fR and \fBTcl_SetEnsembleMappingDict\fR respectively. The result of both of those functions is a Tcl result code (\fBTCL_OK\fR, or \fBTCL_ERROR\fR if the token does not refer to an ensemble) and the dictionary obtained from \fBTcl_GetEnsembleMappingDict\fR should always be treated as immutable even if it is unshared. All command names in prefixes set via \fBTcl_SetEnsembleMappingDict\fR must be fully qualified. .TP \fBformal pre-subcommand parameter list\fR (read-write) .VS 8.6 A list of formal parameter names (the names only being used when generating error messages) that come at invocation of the ensemble between the name of the ensemble and the subcommand argument. NULL (the default) is equivalent to the empty list. May be read and written using \fBTcl_GetEnsembleParameterList\fR and \fBTcl_SetEnsembleParameterList\fR respectively. The result of both of those functions is a Tcl result code (\fBTCL_OK\fR, or \fBTCL_ERROR\fR if the token does not refer to an ensemble) and the dictionary obtained from \fBTcl_GetEnsembleParameterList\fR should always be treated as immutable even if it is unshared. .VE 8.6 .TP \fBsubcommand list\fR (read-write) . A list of all the subcommand names for the ensemble, or NULL if this is to be derived from either the keys of the mapping dictionary (see above) or (if that is also NULL) from the set of commands exported by the bound namespace. May be read and written using \fBTcl_GetEnsembleSubcommandList\fR and \fBTcl_SetEnsembleSubcommandList\fR respectively. The result of both of those functions is a Tcl result code (\fBTCL_OK\fR, or \fBTCL_ERROR\fR if the token does not refer to an ensemble) and the list obtained from \fBTcl_GetEnsembleSubcommandList\fR should always be treated as immutable even if it is unshared. .TP \fBunknown subcommand handler command prefix\fR (read-write) . A list of words to prepend on the front of any subcommand when the subcommand is unknown to the ensemble (according to the current prefix handling rule); see the \fBnamespace ensemble\fR command for more details. If NULL, the default behavior \- generate a suitable error message \- will be used when an unknown subcommand is encountered. May be read and written using \fBTcl_GetEnsembleUnknownHandler\fR and \fBTcl_SetEnsembleUnknownHandler\fR respectively. The result of both functions is a Tcl result code (\fBTCL_OK\fR, or \fBTCL_ERROR\fR if the token does not refer to an ensemble) and the list obtained from \fBTcl_GetEnsembleUnknownHandler\fR should always be treated as immutable even if it is unshared. .TP \fBbound namespace\fR (read-only) . The namespace to which the ensemble is bound; when the namespace is deleted, so too will the ensemble, and this namespace is also the namespace whose list of exported commands is used if both the mapping dictionary and the subcommand list properties are NULL. May be read using \fBTcl_GetEnsembleNamespace\fR which returns a Tcl result code (\fBTCL_OK\fR, or \fBTCL_ERROR\fR if the token does not refer to an ensemble). .SH "SEE ALSO" namespace(n), Tcl_DeleteCommandFromToken(3) .SH KEYWORDS command, ensemble tcl8.6.5/doc/lrange.n0000644000175000017500000000425612663660065013772 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2001 Kevin B. Kenny . All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lrange n 7.4 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lrange \- Return one or more adjacent elements from a list .SH SYNOPSIS \fBlrange \fIlist first last\fR .BE .SH DESCRIPTION .PP \fIList\fR must be a valid Tcl list. This command will return a new list consisting of elements \fIfirst\fR through \fIlast\fR, inclusive. The index values \fIfirst\fR and \fIlast\fR are interpreted the same as index values for the command \fBstring index\fR, supporting simple index arithmetic and indices relative to the end of the list. If \fIfirst\fR is less than zero, it is treated as if it were zero. If \fIlast\fR is greater than or equal to the number of elements in the list, then it is treated as if it were \fBend\fR. If \fIfirst\fR is greater than \fIlast\fR then an empty string is returned. Note: .QW "\fBlrange \fIlist first first\fR" does not always produce the same result as .QW "\fBlindex \fIlist first\fR" (although it often does for simple fields that are not enclosed in braces); it does, however, produce exactly the same results as .QW "\fBlist [lindex \fIlist first\fB]\fR" .SH EXAMPLES .PP Selecting the first two elements: .PP .CS % \fBlrange\fR {a b c d e} 0 1 a b .CE .PP Selecting the last three elements: .PP .CS % \fBlrange\fR {a b c d e} end-2 end c d e .CE .PP Selecting everything except the first and last element: .PP .CS % \fBlrange\fR {a b c d e} 1 end-1 b c d .CE .PP Selecting a single element with \fBlrange\fR is not the same as doing so with \fBlindex\fR: .PP .CS % set var {some {elements to} select} some {elements to} select % lindex $var 1 elements to % \fBlrange\fR $var 1 1 {elements to} .CE .SH "SEE ALSO" list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n), lset(n), lreplace(n), lsort(n), string(n) .SH KEYWORDS element, list, range, sublist tcl8.6.5/doc/GetIndex.30000644000175000017500000001114612663660065014132 0ustar sergeisergei'\" '\" Copyright (c) 1997 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_GetIndexFromObj 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct \- lookup string in table of keywords .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_GetIndexFromObj\fR(\fIinterp, objPtr, tablePtr, msg, flags, indexPtr\fR) .sp int \fBTcl_GetIndexFromObjStruct\fR(\fIinterp, objPtr, structTablePtr, offset, msg, flags, indexPtr\fR) .SH ARGUMENTS .AS "const char" *structTablePtr in/out .AP Tcl_Interp *interp in Interpreter to use for error reporting; if NULL, then no message is provided on errors. .AP Tcl_Obj *objPtr in/out The string value of this value is used to search through \fItablePtr\fR. The internal representation is modified to hold the index of the matching table entry. .AP "const char *const" *tablePtr in An array of null-terminated strings. The end of the array is marked by a NULL string pointer. Note that references to the \fItablePtr\fR may be retained in the internal representation of \fIobjPtr\fR, so this should represent the address of a statically-allocated array. .AP "const void" *structTablePtr in An array of arbitrary type, typically some \fBstruct\fR type. The first member of the structure must be a null-terminated string. The size of the structure is given by \fIoffset\fR. Note that references to the \fIstructTablePtr\fR may be retained in the internal representation of \fIobjPtr\fR, so this should represent the address of a statically-allocated array of structures. .AP int offset in The offset to add to structTablePtr to get to the next entry. The end of the array is marked by a NULL string pointer. .AP "const char" *msg in Null-terminated string describing what is being looked up, such as \fBoption\fR. This string is included in error messages. .AP int flags in OR-ed combination of bits providing additional information for operation. The only bit that is currently defined is \fBTCL_EXACT\fR. .AP int *indexPtr out The index of the string in \fItablePtr\fR that matches the value of \fIobjPtr\fR is returned here. .BE .SH DESCRIPTION .PP These procedures provide an efficient way for looking up keywords, switch names, option names, and similar things where the literal value of a Tcl value must be chosen from a predefined set. \fBTcl_GetIndexFromObj\fR compares \fIobjPtr\fR against each of the strings in \fItablePtr\fR to find a match. A match occurs if \fIobjPtr\fR's string value is identical to one of the strings in \fItablePtr\fR, or if it is a non-empty unique abbreviation for exactly one of the strings in \fItablePtr\fR and the \fBTCL_EXACT\fR flag was not specified; in either case the index of the matching entry is stored at \fI*indexPtr\fR and \fBTCL_OK\fR is returned. .PP If there is no matching entry, \fBTCL_ERROR\fR is returned and an error message is left in \fIinterp\fR's result if \fIinterp\fR is not NULL. \fIMsg\fR is included in the error message to indicate what was being looked up. For example, if \fImsg\fR is \fBoption\fR the error message will have a form like .QW "\fBbad option \N'34'firt\N'34': must be first, second, or third\fR" . .PP If \fBTcl_GetIndexFromObj\fR completes successfully it modifies the internal representation of \fIobjPtr\fR to hold the address of the table and the index of the matching entry. If \fBTcl_GetIndexFromObj\fR is invoked again with the same \fIobjPtr\fR and \fItablePtr\fR arguments (e.g. during a reinvocation of a Tcl command), it returns the matching index immediately without having to redo the lookup operation. Note: \fBTcl_GetIndexFromObj\fR assumes that the entries in \fItablePtr\fR are static: they must not change between invocations. If the value of \fIobjPtr\fR is the empty string, \fBTcl_GetIndexFromObj\fR will treat it as a non-matching value and return \fBTCL_ERROR\fR. .PP \fBTcl_GetIndexFromObjStruct\fR works just like \fBTcl_GetIndexFromObj\fR, except that instead of treating \fItablePtr\fR as an array of string pointers, it treats it as a pointer to the first string in a series of strings that have \fIoffset\fR bytes between them (i.e. that there is a pointer to the first array of characters at \fItablePtr\fR, a pointer to the second array of characters at \fItablePtr\fR+\fIoffset\fR bytes, etc.) This is particularly useful when processing things like \fBTk_ConfigurationSpec\fR, whose string keys are in the same place in each of several array elements. .SH "SEE ALSO" prefix(n), Tcl_WrongNumArgs(3) .SH KEYWORDS index, option, value, table lookup tcl8.6.5/doc/class.n0000644000175000017500000001137312663660065013625 0ustar sergeisergei'\" '\" Copyright (c) 2007 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH class n 0.1 TclOO "TclOO Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME oo::class \- class of all classes .SH SYNOPSIS .nf package require TclOO \fBoo::class\fI method \fR?\fIarg ...\fR? .fi .SH "CLASS HIERARCHY" .nf \fBoo::object\fR \(-> \fBoo::class\fR .fi .BE .SH DESCRIPTION .PP Classes are objects that can manufacture other objects according to a pattern stored in the factory object (the class). An instance of the class is created by calling one of the class's factory methods, typically either \fBcreate\fR if an explicit name is being given, or \fBnew\fR if an arbitrary unique name is to be automatically selected. .PP The \fBoo::class\fR class is the class of all classes; every class is an instance of this class, which is consequently an instance of itself. This class is a subclass of \fBoo::object\fR, so every class is also an object. Additional metaclasses (i.e., classes of classes) can be defined if necessary by subclassing \fBoo::class\fR. Note that the \fBoo::class\fR object hides the \fBnew\fR method on itself, so new classes should always be made using the \fBcreate\fR method. .SS CONSTRUCTOR .PP The constructor of the \fBoo::class\fR class takes an optional argument which, if present, is sent to the \fBoo::define\fR command (along with the name of the newly-created class) to allow the class to be conveniently configured at creation time. .SS DESTRUCTOR The \fBoo::class\fR class does not define an explicit destructor. However, when a class is destroyed, all its subclasses and instances are also destroyed, along with all objects that it has been mixed into. .SS "EXPORTED METHODS" .TP \fIcls \fBcreate \fIname \fR?\fIarg ...\fR? . This creates a new instance of the class \fIcls\fR called \fIname\fR (which is resolved within the calling context's namespace if not fully qualified), passing the arguments, \fIarg ...\fR, to the constructor, and (if that returns a successful result) returning the fully qualified name of the created object (the result of the constructor is ignored). If the constructor fails (i.e. returns a non-OK result) then the object is destroyed and the error message is the result of this method call. .TP \fIcls \fBnew \fR?\fIarg ...\fR? . This creates a new instance of the class \fIcls\fR with a new unique name, passing the arguments, \fIarg ...\fR, to the constructor, and (if that returns a successful result) returning the fully qualified name of the created object (the result of the constructor is ignored). If the constructor fails (i.e., returns a non-OK result) then the object is destroyed and the error message is the result of this method call. .RS .PP Note that this method is not exported by the \fBoo::class\fR object itself, so classes should not be created using this method. .RE .SS "NON-EXPORTED METHODS" .PP The \fBoo::class\fR class supports the following non-exported methods: .TP \fIcls \fBcreateWithNamespace\fI name nsName\fR ?\fIarg ...\fR? . This creates a new instance of the class \fIcls\fR called \fIname\fR (which is resolved within the calling context's namespace if not fully qualified), passing the arguments, \fIarg ...\fR, to the constructor, and (if that returns a successful result) returning the fully qualified name of the created object (the result of the constructor is ignored). The name of the instance's internal namespace will be \fInsName\fR unless that namespace already exists (when an arbitrary name will be chosen instead). If the constructor fails (i.e., returns a non-OK result) then the object is destroyed and the error message is the result of this method call. .SH EXAMPLES .PP This example defines a simple class hierarchy and creates a new instance of it. It then invokes a method of the object before destroying the hierarchy and showing that the destruction is transitive. .PP .CS \fBoo::class create\fR fruit { method eat {} { puts "yummy!" } } \fBoo::class create\fR banana { superclass fruit constructor {} { my variable peeled set peeled 0 } method peel {} { my variable peeled set peeled 1 puts "skin now off" } method edible? {} { my variable peeled return $peeled } method eat {} { if {![my edible?]} { my peel } next } } set b [banana \fBnew\fR] $b eat \fI\(-> prints "skin now off" and "yummy!"\fR fruit destroy $b eat \fI\(-> error "unknown command"\fR .CE .SH "SEE ALSO" oo::define(n), oo::object(n) .SH KEYWORDS class, metaclass, object .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: tcl8.6.5/doc/fileevent.n0000644000175000017500000001502712663660065014501 0ustar sergeisergei'\" '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2008 Pat Thoyts '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH fileevent n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fileevent \- Execute a script when a channel becomes readable or writable .SH SYNOPSIS \fBfileevent \fIchannelId \fBreadable \fR?\fIscript\fR? .sp \fBfileevent \fIchannelId \fBwritable \fR?\fIscript\fR? .BE .SH DESCRIPTION .PP This command is used to create \fIfile event handlers\fR. A file event handler is a binding between a channel and a script, such that the script is evaluated whenever the channel becomes readable or writable. File event handlers are most commonly used to allow data to be received from another process on an event-driven basis, so that the receiver can continue to interact with the user while waiting for the data to arrive. If an application invokes \fBgets\fR or \fBread\fR on a blocking channel when there is no input data available, the process will block; until the input data arrives, it will not be able to service other events, so it will appear to the user to .QW "freeze up" . With \fBfileevent\fR, the process can tell when data is present and only invoke \fBgets\fR or \fBread\fR when they will not block. .PP The \fIchannelId\fR argument to \fBfileevent\fR refers to an open channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. .PP If the \fIscript\fR argument is specified, then \fBfileevent\fR creates a new event handler: \fIscript\fR will be evaluated whenever the channel becomes readable or writable (depending on the second argument to \fBfileevent\fR). In this case \fBfileevent\fR returns an empty string. The \fBreadable\fR and \fBwritable\fR event handlers for a file are independent, and may be created and deleted separately. However, there may be at most one \fBreadable\fR and one \fBwritable\fR handler for a file at a given time in a given interpreter. If \fBfileevent\fR is called when the specified handler already exists in the invoking interpreter, the new script replaces the old one. .PP If the \fIscript\fR argument is not specified, \fBfileevent\fR returns the current script for \fIchannelId\fR, or an empty string if there is none. If the \fIscript\fR argument is specified as an empty string then the event handler is deleted, so that no script will be invoked. A file event handler is also deleted automatically whenever its channel is closed or its interpreter is deleted. .PP A channel is considered to be readable if there is unread data available on the underlying device. A channel is also considered to be readable if there is unread data in an input buffer, except in the special case where the most recent attempt to read from the channel was a \fBgets\fR call that could not find a complete line in the input buffer. This feature allows a file to be read a line at a time in nonblocking mode using events. A channel is also considered to be readable if an end of file or error condition is present on the underlying file or device. It is important for \fIscript\fR to check for these conditions and handle them appropriately; for example, if there is no special check for end of file, an infinite loop may occur where \fIscript\fR reads no data, returns, and is immediately invoked again. .PP A channel is considered to be writable if at least one byte of data can be written to the underlying file or device without blocking, or if an error condition is present on the underlying file or device. .PP Event-driven I/O works best for channels that have been placed into nonblocking mode with the \fBfconfigure\fR command. In blocking mode, a \fBputs\fR command may block if you give it more data than the underlying file or device can accept, and a \fBgets\fR or \fBread\fR command will block if you attempt to read more data than is ready; a readable underlying file or device may not even guarantee that a blocking [read 1] will succeed (counter-examples being multi-byte encodings, compression or encryption transforms ). In all such cases, no events will be processed while the commands block. .PP In nonblocking mode \fBputs\fR, \fBread\fR, and \fBgets\fR never block. See the documentation for the individual commands for information on how they handle blocking and nonblocking channels. .PP Testing for the end of file condition should be done after any attempts read the channel data. The eof flag is set once an attempt to read the end of data has occurred and testing before this read will require an additional event to be fired. .PP The script for a file event is executed at global level (outside the context of any Tcl procedure) in the interpreter in which the \fBfileevent\fR command was invoked. If an error occurs while executing the script then the command registered with \fBinterp bgerror\fR is used to report the error. In addition, the file event handler is deleted if it ever returns an error; this is done in order to prevent infinite loops due to buggy handlers. .SH EXAMPLE .PP In this setup \fBGetData\fR will be called with the channel as an argument whenever $chan becomes readable. The \fBread\fR call will read whatever binary data is currently available without blocking. Here the channel has the fileevent removed when an end of file occurs to avoid being continually called (see above). Alternatively the channel may be closed on this condition. .PP .CS proc GetData {chan} { set data [read $chan] puts "[string length $data] $data" if {[eof $chan]} { fileevent $chan readable {} } } fconfigure $chan -blocking 0 -encoding binary \fBfileevent\fR $chan readable [list GetData $chan] .CE .PP The next example demonstrates use of \fBgets\fR to read line-oriented data. .PP .CS proc GetData {chan} { if {[gets $chan line] >= 0} { puts $line } if {[eof $chan]} { close $chan } } fconfigure $chan -blocking 0 -buffering line -translation crlf \fBfileevent\fR $chan readable [list GetData $chan] .CE .SH CREDITS .PP \fBfileevent\fR is based on the \fBaddinput\fR command created by Mark Diekhans. .SH "SEE ALSO" fconfigure(n), gets(n), interp(n), puts(n), read(n), Tcl_StandardChannels(3) .SH KEYWORDS asynchronous I/O, blocking, channel, event handler, nonblocking, readable, script, writable. tcl8.6.5/doc/socket.n0000644000175000017500000002302512663660065014005 0ustar sergeisergei'\" '\" Copyright (c) 1996 Sun Microsystems, Inc. '\" Copyright (c) 1998-1999 by Scriptics Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH socket n 8.6 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME socket \- Open a TCP network connection .SH SYNOPSIS .sp \fBsocket \fR?\fIoptions\fR? \fIhost port\fR .sp \fBsocket\fR \fB\-server \fIcommand\fR ?\fIoptions\fR? \fIport\fR .BE .SH DESCRIPTION .PP This command opens a network socket and returns a channel identifier that may be used in future invocations of commands like \fBread\fR, \fBputs\fR and \fBflush\fR. At present only the TCP network protocol is supported over IPv4 and IPv6; future releases may include support for additional protocols. The \fBsocket\fR command may be used to open either the client or server side of a connection, depending on whether the \fB\-server\fR switch is specified. .PP Note that the default encoding for \fIall\fR sockets is the system encoding, as returned by \fBencoding system\fR. Most of the time, you will need to use \fBchan configure\fR to alter this to something else, such as \fIutf\-8\fR (ideal for communicating with other Tcl processes) or \fIiso8859\-1\fR (useful for many network protocols, especially the older ones). .SH "CLIENT SOCKETS" .PP If the \fB\-server\fR option is not specified, then the client side of a connection is opened and the command returns a channel identifier that can be used for both reading and writing. \fIPort\fR and \fIhost\fR specify a port to connect to; there must be a server accepting connections on this port. \fIPort\fR is an integer port number (or service name, where supported and understood by the host operating system) and \fIhost\fR is either a domain-style name such as \fBwww.tcl.tk\fR or a numerical IPv4 or IPv6 address such as \fB127.0.0.1\fR or \fB2001:DB8::1\fR. Use \fIlocalhost\fR to refer to the host on which the command is invoked. .PP The following options may also be present before \fIhost\fR to specify additional information about the connection: .TP \fB\-myaddr\fI addr\fR . \fIAddr\fR gives the domain-style name or numerical IP address of the client-side network interface to use for the connection. This option may be useful if the client machine has multiple network interfaces. If the option is omitted then the client-side interface will be chosen by the system software. .TP \fB\-myport\fI port\fR . \fIPort\fR specifies an integer port number (or service name, where supported and understood by the host operating system) to use for the client's side of the connection. If this option is omitted, the client's port number will be chosen at random by the system software. .TP \fB\-async\fR . This option will cause the client socket to be connected asynchronously. This means that the socket will be created immediately but may not yet be connected to the server, when the call to \fBsocket\fR returns. .RS .PP When a \fBgets\fR or \fBflush\fR is done on the socket before the connection attempt succeeds or fails, if the socket is in blocking mode, the operation will wait until the connection is completed or fails. If the socket is in nonblocking mode and a \fBgets\fR or \fBflush\fR is done on the socket before the connection attempt succeeds or fails, the operation returns immediately and \fBfblocked\fR on the socket returns 1. Synchronous client sockets may be switched (after they have connected) to operating in asynchronous mode using: .PP .CS \fBchan configure \fIchan \fB\-blocking 0\fR .CE .PP See the \fBchan configure\fR command for more details. .PP The Tcl event loop should be running while an asynchronous connection is in progress, because it may have to do several connection attempts in the background. Running the event loop also allows you to set up a writable channel event on the socket to get notified when the asynchronous connection has succeeded or failed. See the \fBvwait\fR and the \fBchan\fR commands for more details on the event loop and channel events. .PP The \fBchan configure\fR option \fB-connecting\fR may be used to check if the connect is still running. To verify a successful connect, the option \fB-error\fR may be checked when \fB-connecting\fR returned 0. .PP Operation without the event queue requires at the moment calls to \fBchan configure\fR to advance the internal state machine. .RE .SH "SERVER SOCKETS" .PP If the \fB\-server\fR option is specified then the new socket will be a server that listens on the given \fIport\fR (either an integer or a service name, where supported and understood by the host operating system; if \fIport\fR is zero, the operating system will allocate a free port to the server socket which may be discovered by using \fBchan configure\fR to read the \fB\-sockname\fR option). If the host supports both, IPv4 and IPv6, the socket will listen on both address families. Tcl will automatically accept connections to the given port. For each connection Tcl will create a new channel that may be used to communicate with the client. Tcl then invokes \fIcommand\fR (properly a command prefix list, see the \fBEXAMPLES\fR below) with three additional arguments: the name of the new channel, the address, in network address notation, of the client's host, and the client's port number. .PP The following additional option may also be specified before \fIport\fR: .TP \fB\-myaddr\fI addr\fR . \fIAddr\fR gives the domain-style name or numerical IP address of the server-side network interface to use for the connection. This option may be useful if the server machine has multiple network interfaces. If the option is omitted then the server socket is bound to the wildcard address so that it can accept connections from any interface. If \fIaddr\fR is a domain name that resolves to multiple IP addresses that are available on the local machine, the socket will listen on all of them. .PP Server channels cannot be used for input or output; their sole use is to accept new client connections. The channels created for each incoming client connection are opened for input and output. Closing the server channel shuts down the server so that no new connections will be accepted; however, existing connections will be unaffected. .PP Server sockets depend on the Tcl event mechanism to find out when new connections are opened. If the application does not enter the event loop, for example by invoking the \fBvwait\fR command or calling the C procedure \fBTcl_DoOneEvent\fR, then no connections will be accepted. .PP If \fIport\fR is specified as zero, the operating system will allocate an unused port for use as a server socket. The port number actually allocated may be retrieved from the created server socket using the \fBchan configure\fR command to retrieve the \fB\-sockname\fR option as described below. .SH "CONFIGURATION OPTIONS" .PP The \fBchan configure\fR command can be used to query several readonly configuration options for socket channels: .TP \fB\-error\fR . This option gets the current error status of the given socket. This is useful when you need to determine if an asynchronous connect operation succeeded. If there was an error, the error message is returned. If there was no error, an empty string is returned. .RS .PP Note that the error status is reset by the read operation; this mimics the underlying getsockopt(SO_ERROR) call. .RE .TP \fB\-sockname\fR . For client sockets (including the channels that get created when a client connects to a server socket) this option returns a list of three elements, the address, the host name and the port number for the socket. If the host name cannot be computed, the second element is identical to the address, the first element of the list. .RS .PP For server sockets this option returns a list of a multiple of three elements each group of which have the same meaning as described above. The list contains more than one group when the server socket was created without \fB\-myaddr\fR or with the argument to \fB\-myaddr\fR being a domain name that resolves multiple IP addresses that are local to the invoking host. .RE .TP \fB\-peername\fR . This option is not supported by server sockets. For client and accepted sockets, this option returns a list of three elements; these are the address, the host name and the port to which the peer socket is connected or bound. If the host name cannot be computed, the second element of the list is identical to the address, its first element. .TP \fB\-connecting\fR . This option is not supported by server sockets. For client sockets, this option returns 1 if an asyncroneous connect is still in progress, 0 otherwise. .PP .SH "EXAMPLES" .PP Here is a very simple time server: .PP .CS proc Server {startTime channel clientaddr clientport} { puts "Connection from $clientaddr registered" set now [clock seconds] puts $channel [clock format $now] puts $channel "[expr {$now - $startTime}] since start" close $channel } \fBsocket -server\fR [list Server [clock seconds]] 9900 vwait forever .CE .PP And here is the corresponding client to talk to the server and extract some information: .PP .CS set server localhost set sockChan [\fBsocket\fR $server 9900] gets $sockChan line1 gets $sockChan line2 close $sockChan puts "The time on $server is $line1" puts "That is [lindex $line2 0]s since the server started" .CE .SH "HISTORY" Support for IPv6 was added in Tcl 8.6. .SH "SEE ALSO" chan(n), flush(n), open(n), read(n) .SH KEYWORDS asynchronous I/O, bind, channel, connection, domain name, host, network address, socket, tcp '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/interp.n0000644000175000017500000012407612663660065014026 0ustar sergeisergei'\" '\" Copyright (c) 1995-1996 Sun Microsystems, Inc. '\" Copyright (c) 2004 Donal K. Fellows '\" Copyright (c) 2006-2008 Joe Mistachkin. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH interp n 8.6 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME interp \- Create and manipulate Tcl interpreters .SH SYNOPSIS \fBinterp \fIsubcommand \fR?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP This command makes it possible to create one or more new Tcl interpreters that co-exist with the creating interpreter in the same application. The creating interpreter is called the \fImaster\fR and the new interpreter is called a \fIslave\fR. A master can create any number of slaves, and each slave can itself create additional slaves for which it is master, resulting in a hierarchy of interpreters. .PP Each interpreter is independent from the others: it has its own name space for commands, procedures, and global variables. A master interpreter may create connections between its slaves and itself using a mechanism called an \fIalias\fR. An \fIalias\fR is a command in a slave interpreter which, when invoked, causes a command to be invoked in its master interpreter or in another slave interpreter. The only other connections between interpreters are through environment variables (the \fBenv\fR variable), which are normally shared among all interpreters in the application, and by resource limit exceeded callbacks. Note that the name space for files (such as the names returned by the \fBopen\fR command) is no longer shared between interpreters. Explicit commands are provided to share files and to transfer references to open files from one interpreter to another. .PP The \fBinterp\fR command also provides support for \fIsafe\fR interpreters. A safe interpreter is a slave whose functions have been greatly restricted, so that it is safe to execute untrusted scripts without fear of them damaging other interpreters or the application's environment. For example, all IO channel creation commands and subprocess creation commands are made inaccessible to safe interpreters. See \fBSAFE INTERPRETERS\fR below for more information on what features are present in a safe interpreter. The dangerous functionality is not removed from the safe interpreter; instead, it is \fIhidden\fR, so that only trusted interpreters can obtain access to it. For a detailed explanation of hidden commands, see \fBHIDDEN COMMANDS\fR, below. The alias mechanism can be used for protected communication (analogous to a kernel call) between a slave interpreter and its master. See \fBALIAS INVOCATION\fR, below, for more details on how the alias mechanism works. .PP A qualified interpreter name is a proper Tcl lists containing a subset of its ancestors in the interpreter hierarchy, terminated by the string naming the interpreter in its immediate master. Interpreter names are relative to the interpreter in which they are used. For example, if .QW \fBa\fR is a slave of the current interpreter and it has a slave .QW \fBa1\fR , which in turn has a slave .QW \fBa11\fR , the qualified name of .QW \fBa11\fR in .QW \fBa\fR is the list .QW "\fBa1 a11\fR" . .PP The \fBinterp\fR command, described below, accepts qualified interpreter names as arguments; the interpreter in which the command is being evaluated can always be referred to as \fB{}\fR (the empty list or string). Note that it is impossible to refer to a master (ancestor) interpreter by name in a slave interpreter except through aliases. Also, there is no global name by which one can refer to the first interpreter created in an application. Both restrictions are motivated by safety concerns. .SH "THE INTERP COMMAND" .PP The \fBinterp\fR command is used to create, delete, and manipulate slave interpreters, and to share or transfer channels between interpreters. It can have any of several forms, depending on the \fIsubcommand\fR argument: .TP \fBinterp\fR \fBalias\fR \fIsrcPath\fR \fIsrcToken\fR . Returns a Tcl list whose elements are the \fItargetCmd\fR and \fIarg\fRs associated with the alias represented by \fIsrcToken\fR (this is the value returned when the alias was created; it is possible that the name of the source command in the slave is different from \fIsrcToken\fR). .TP \fBinterp\fR \fBalias\fR \fIsrcPath\fR \fIsrcToken\fR \fB{}\fR . Deletes the alias for \fIsrcToken\fR in the slave interpreter identified by \fIsrcPath\fR. \fIsrcToken\fR refers to the value returned when the alias was created; if the source command has been renamed, the renamed command will be deleted. .TP \fBinterp\fR \fBalias\fR \fIsrcPath\fR \fIsrcCmd\fR \fItargetPath\fR \fItargetCmd \fR?\fIarg arg ...\fR? . This command creates an alias between one slave and another (see the \fBalias\fR slave command below for creating aliases between a slave and its master). In this command, either of the slave interpreters may be anywhere in the hierarchy of interpreters under the interpreter invoking the command. \fISrcPath\fR and \fIsrcCmd\fR identify the source of the alias. \fISrcPath\fR is a Tcl list whose elements select a particular interpreter. For example, .QW "\fBa b\fR" identifies an interpreter .QW \fBb\fR , which is a slave of interpreter .QW \fBa\fR , which is a slave of the invoking interpreter. An empty list specifies the interpreter invoking the command. \fIsrcCmd\fR gives the name of a new command, which will be created in the source interpreter. \fITargetPath\fR and \fItargetCmd\fR specify a target interpreter and command, and the \fIarg\fR arguments, if any, specify additional arguments to \fItargetCmd\fR which are prepended to any arguments specified in the invocation of \fIsrcCmd\fR. \fITargetCmd\fR may be undefined at the time of this call, or it may already exist; it is not created by this command. The alias arranges for the given target command to be invoked in the target interpreter whenever the given source command is invoked in the source interpreter. See \fBALIAS INVOCATION\fR below for more details. The command returns a token that uniquely identifies the command created \fIsrcCmd\fR, even if the command is renamed afterwards. The token may but does not have to be equal to \fIsrcCmd\fR. .TP \fBinterp\fR \fBaliases \fR?\fIpath\fR? . This command returns a Tcl list of the tokens of all the source commands for aliases defined in the interpreter identified by \fIpath\fR. The tokens correspond to the values returned when the aliases were created (which may not be the same as the current names of the commands). .TP \fBinterp bgerror \fIpath\fR ?\fIcmdPrefix\fR? . This command either gets or sets the current background exception handler for the interpreter identified by \fIpath\fR. If \fIcmdPrefix\fR is absent, the current background exception handler is returned, and if it is present, it is a list of words (of minimum length one) that describes what to set the interpreter's background exception handler to. See the \fBBACKGROUND EXCEPTION HANDLING\fR section for more details. .TP \fBinterp\fR \fBcancel \fR?\fB\-unwind\fR? ?\fB\-\|\-\fR? ?\fIpath\fR? ?\fIresult\fR? .VS 8.6 Cancels the script being evaluated in the interpreter identified by \fIpath\fR. Without the \fB\-unwind\fR switch the evaluation stack for the interpreter is unwound until an enclosing catch command is found or there are no further invocations of the interpreter left on the call stack. With the \fB\-unwind\fR switch the evaluation stack for the interpreter is unwound without regard to any intervening catch command until there are no further invocations of the interpreter left on the call stack. The \fB\-\|\-\fR switch can be used to mark the end of switches; it may be needed if \fIpath\fR is an unusual value such as \fB\-safe\fR. If \fIresult\fR is present, it will be used as the error message string; otherwise, a default error message string will be used. .VE 8.6 .TP \fBinterp\fR \fBcreate \fR?\fB\-safe\fR? ?\fB\-\|\-\fR? ?\fIpath\fR? . Creates a slave interpreter identified by \fIpath\fR and a new command, called a \fIslave command\fR. The name of the slave command is the last component of \fIpath\fR. The new slave interpreter and the slave command are created in the interpreter identified by the path obtained by removing the last component from \fIpath\fR. For example, if \fIpath\fR is \fBa b c\fR then a new slave interpreter and slave command named \fBc\fR are created in the interpreter identified by the path \fBa b\fR. The slave command may be used to manipulate the new interpreter as described below. If \fIpath\fR is omitted, Tcl creates a unique name of the form \fBinterp\fIx\fR, where \fIx\fR is an integer, and uses it for the interpreter and the slave command. If the \fB\-safe\fR switch is specified (or if the master interpreter is a safe interpreter), the new slave interpreter will be created as a safe interpreter with limited functionality; otherwise the slave will include the full set of Tcl built-in commands and variables. The \fB\-\|\-\fR switch can be used to mark the end of switches; it may be needed if \fIpath\fR is an unusual value such as \fB\-safe\fR. The result of the command is the name of the new interpreter. The name of a slave interpreter must be unique among all the slaves for its master; an error occurs if a slave interpreter by the given name already exists in this master. The initial recursion limit of the slave interpreter is set to the current recursion limit of its parent interpreter. .TP \fBinterp\fR \fBdebug \fIpath\fR ?\fB\-frame\fR ?\fIbool\fR?? . Controls whether frame-level stack information is captured in the slave interpreter identified by \fIpath\fR. If no arguments are given, option and current setting are returned. If \fB\-frame\fR is given, the debug setting is set to the given boolean if provided and the current setting is returned. This only effects the output of \fBinfo frame\fR, in that exact frame-level information for command invocation at the bytecode level is only captured with this setting on. .RS .PP For example, with code like .PP .CS \fBproc\fR mycontrol {... script} { ... \fBuplevel\fR 1 $script ... } \fBproc\fR dosomething {...} { ... mycontrol { somecode } } .CE .PP the standard setting will provide a relative line number for the command \fBsomecode\fR and the relevant frame will be of type \fBeval\fR. With frame-debug active on the other hand the tracking extends so far that the system will be able to determine the file and absolute line number of this command, and return a frame of type \fBsource\fR. This more exact information is paid for with slower execution of all commands. .PP Note that once it is on, this flag cannot be switched back off: such attempts are silently ignored. This is needed to maintain the consistency of the underlying interpreter's state. .RE .TP \fBinterp\fR \fBdelete \fR?\fIpath ...?\fR . Deletes zero or more interpreters given by the optional \fIpath\fR arguments, and for each interpreter, it also deletes its slaves. The command also deletes the slave command for each interpreter deleted. For each \fIpath\fR argument, if no interpreter by that name exists, the command raises an error. .TP \fBinterp\fR \fBeval\fR \fIpath arg \fR?\fIarg ...\fR? . This command concatenates all of the \fIarg\fR arguments in the same fashion as the \fBconcat\fR command, then evaluates the resulting string as a Tcl script in the slave interpreter identified by \fIpath\fR. The result of this evaluation (including all \fBreturn\fR options, such as \fB\-errorinfo\fR and \fB\-errorcode\fR information, if an error occurs) is returned to the invoking interpreter. Note that the script will be executed in the current context stack frame of the \fIpath\fR interpreter; this is so that the implementations (in a master interpreter) of aliases in a slave interpreter can execute scripts in the slave that find out information about the slave's current state and stack frame. .TP \fBinterp exists \fIpath\fR . Returns \fB1\fR if a slave interpreter by the specified \fIpath\fR exists in this master, \fB0\fR otherwise. If \fIpath\fR is omitted, the invoking interpreter is used. .TP \fBinterp expose \fIpath\fR \fIhiddenName\fR ?\fIexposedCmdName\fR? . Makes the hidden command \fIhiddenName\fR exposed, eventually bringing it back under a new \fIexposedCmdName\fR name (this name is currently accepted only if it is a valid global name space name without any ::), in the interpreter denoted by \fIpath\fR. If an exposed command with the targeted name already exists, this command fails. Hidden commands are explained in more detail in \fBHIDDEN COMMANDS\fR, below. .TP \fBinterp\fR \fBhide\fR \fIpath\fR \fIexposedCmdName\fR ?\fIhiddenCmdName\fR? . Makes the exposed command \fIexposedCmdName\fR hidden, renaming it to the hidden command \fIhiddenCmdName\fR, or keeping the same name if \fIhiddenCmdName\fR is not given, in the interpreter denoted by \fIpath\fR. If a hidden command with the targeted name already exists, this command fails. Currently both \fIexposedCmdName\fR and \fIhiddenCmdName\fR can not contain namespace qualifiers, or an error is raised. Commands to be hidden by \fBinterp hide\fR are looked up in the global namespace even if the current namespace is not the global one. This prevents slaves from fooling a master interpreter into hiding the wrong command, by making the current namespace be different from the global one. Hidden commands are explained in more detail in \fBHIDDEN COMMANDS\fR, below. .TP \fBinterp\fR \fBhidden\fR \fIpath\fR . Returns a list of the names of all hidden commands in the interpreter identified by \fIpath\fR. .TP \fBinterp\fR \fBinvokehidden\fR \fIpath\fR ?\fI\-option ...\fR? \fIhiddenCmdName\fR ?\fIarg ...\fR? . Invokes the hidden command \fIhiddenCmdName\fR with the arguments supplied in the interpreter denoted by \fIpath\fR. No substitutions or evaluation are applied to the arguments. Three \fI\-option\fRs are supported, all of which start with \fB\-\fR: \fB\-namespace\fR (which takes a single argument afterwards, \fInsName\fR), \fB\-global\fR, and \fB\-\|\-\fR. If the \fB\-namespace\fR flag is present, the hidden command is invoked in the namespace called \fInsName\fR in the target interpreter. If the \fB\-global\fR flag is present, the hidden command is invoked at the global level in the target interpreter; otherwise it is invoked at the current call frame and can access local variables in that and outer call frames. The \fB\-\|\-\fR flag allows the \fIhiddenCmdName\fR argument to start with a .QW \- character, and is otherwise unnecessary. If both the \fB\-namespace\fR and \fB\-global\fR flags are present, the \fB\-namespace\fR flag is ignored. Note that the hidden command will be executed (by default) in the current context stack frame of the \fIpath\fR interpreter. Hidden commands are explained in more detail in \fBHIDDEN COMMANDS\fR, below. .TP \fBinterp issafe\fR ?\fIpath\fR? . Returns \fB1\fR if the interpreter identified by the specified \fIpath\fR is safe, \fB0\fR otherwise. .TP \fBinterp\fR \fBlimit\fR \fIpath\fR \fIlimitType\fR ?\fI\-option\fR? ?\fIvalue\fR \fI...\fR? . Sets up, manipulates and queries the configuration of the resource limit \fIlimitType\fR for the interpreter denoted by \fIpath\fR. If no \fI\-option\fR is specified, return the current configuration of the limit. If \fI\-option\fR is the sole argument, return the value of that option. Otherwise, a list of \fI\-option\fR/\fIvalue\fR argument pairs must supplied. See \fBRESOURCE LIMITS\fR below for a more detailed explanation of what limits and options are supported. .TP \fBinterp marktrusted\fR \fIpath\fR . Marks the interpreter identified by \fIpath\fR as trusted. Does not expose the hidden commands. This command can only be invoked from a trusted interpreter. The command has no effect if the interpreter identified by \fIpath\fR is already trusted. .TP \fBinterp\fR \fBrecursionlimit\fR \fIpath\fR ?\fInewlimit\fR? . Returns the maximum allowable nesting depth for the interpreter specified by \fIpath\fR. If \fInewlimit\fR is specified, the interpreter recursion limit will be set so that nesting of more than \fInewlimit\fR calls to \fBTcl_Eval\fR and related procedures in that interpreter will return an error. The \fInewlimit\fR value is also returned. The \fInewlimit\fR value must be a positive integer between 1 and the maximum value of a non-long integer on the platform. .RS .PP The command sets the maximum size of the Tcl call stack only. It cannot by itself prevent stack overflows on the C stack being used by the application. If your machine has a limit on the size of the C stack, you may get stack overflows before reaching the limit set by the command. If this happens, see if there is a mechanism in your system for increasing the maximum size of the C stack. .RE .TP \fBinterp\fR \fBshare\fR \fIsrcPath channelId destPath\fR . Causes the IO channel identified by \fIchannelId\fR to become shared between the interpreter identified by \fIsrcPath\fR and the interpreter identified by \fIdestPath\fR. Both interpreters have the same permissions on the IO channel. Both interpreters must close it to close the underlying IO channel; IO channels accessible in an interpreter are automatically closed when an interpreter is destroyed. .TP \fBinterp\fR \fBslaves\fR ?\fIpath\fR? . Returns a Tcl list of the names of all the slave interpreters associated with the interpreter identified by \fIpath\fR. If \fIpath\fR is omitted, the invoking interpreter is used. .TP \fBinterp\fR \fBtarget\fR \fIpath alias\fR . Returns a Tcl list describing the target interpreter for an alias. The alias is specified with an interpreter path and source command name, just as in \fBinterp alias\fR above. The name of the target interpreter is returned as an interpreter path, relative to the invoking interpreter. If the target interpreter for the alias is the invoking interpreter then an empty list is returned. If the target interpreter for the alias is not the invoking interpreter or one of its descendants then an error is generated. The target command does not have to be defined at the time of this invocation. .TP \fBinterp\fR \fBtransfer\fR \fIsrcPath channelId destPath\fR . Causes the IO channel identified by \fIchannelId\fR to become available in the interpreter identified by \fIdestPath\fR and unavailable in the interpreter identified by \fIsrcPath\fR. .SH "SLAVE COMMAND" .PP For each slave interpreter created with the \fBinterp\fR command, a new Tcl command is created in the master interpreter with the same name as the new interpreter. This command may be used to invoke various operations on the interpreter. It has the following general form: .PP .CS \fIslave command \fR?\fIarg arg ...\fR? .CE .PP \fISlave\fR is the name of the interpreter, and \fIcommand\fR and the \fIarg\fRs determine the exact behavior of the command. The valid forms of this command are: .TP \fIslave \fBaliases\fR . Returns a Tcl list whose elements are the tokens of all the aliases in \fIslave\fR. The tokens correspond to the values returned when the aliases were created (which may not be the same as the current names of the commands). .TP \fIslave \fBalias \fIsrcToken\fR . Returns a Tcl list whose elements are the \fItargetCmd\fR and \fIarg\fRs associated with the alias represented by \fIsrcToken\fR (this is the value returned when the alias was created; it is possible that the actual source command in the slave is different from \fIsrcToken\fR). .TP \fIslave \fBalias \fIsrcToken \fB{}\fR . Deletes the alias for \fIsrcToken\fR in the slave interpreter. \fIsrcToken\fR refers to the value returned when the alias was created; if the source command has been renamed, the renamed command will be deleted. .TP \fIslave \fBalias \fIsrcCmd targetCmd \fR?\fIarg ..\fR? . Creates an alias such that whenever \fIsrcCmd\fR is invoked in \fIslave\fR, \fItargetCmd\fR is invoked in the master. The \fIarg\fR arguments will be passed to \fItargetCmd\fR as additional arguments, prepended before any arguments passed in the invocation of \fIsrcCmd\fR. See \fBALIAS INVOCATION\fR below for details. The command returns a token that uniquely identifies the command created \fIsrcCmd\fR, even if the command is renamed afterwards. The token may but does not have to be equal to \fIsrcCmd\fR. .TP \fIslave \fBbgerror\fR ?\fIcmdPrefix\fR? . This command either gets or sets the current background exception handler for the \fIslave\fR interpreter. If \fIcmdPrefix\fR is absent, the current background exception handler is returned, and if it is present, it is a list of words (of minimum length one) that describes what to set the interpreter's background exception handler to. See the \fBBACKGROUND EXCEPTION HANDLING\fR section for more details. .TP \fIslave \fBeval \fIarg \fR?\fIarg ..\fR? . This command concatenates all of the \fIarg\fR arguments in the same fashion as the \fBconcat\fR command, then evaluates the resulting string as a Tcl script in \fIslave\fR. The result of this evaluation (including all \fBreturn\fR options, such as \fB\-errorinfo\fR and \fB\-errorcode\fR information, if an error occurs) is returned to the invoking interpreter. Note that the script will be executed in the current context stack frame of \fIslave\fR; this is so that the implementations (in a master interpreter) of aliases in a slave interpreter can execute scripts in the slave that find out information about the slave's current state and stack frame. .TP \fIslave \fBexpose \fIhiddenName \fR?\fIexposedCmdName\fR? . This command exposes the hidden command \fIhiddenName\fR, eventually bringing it back under a new \fIexposedCmdName\fR name (this name is currently accepted only if it is a valid global name space name without any ::), in \fIslave\fR. If an exposed command with the targeted name already exists, this command fails. For more details on hidden commands, see \fBHIDDEN COMMANDS\fR, below. .TP \fIslave \fBhide \fIexposedCmdName\fR ?\fIhiddenCmdName\fR? . This command hides the exposed command \fIexposedCmdName\fR, renaming it to the hidden command \fIhiddenCmdName\fR, or keeping the same name if the argument is not given, in the \fIslave\fR interpreter. If a hidden command with the targeted name already exists, this command fails. Currently both \fIexposedCmdName\fR and \fIhiddenCmdName\fR can not contain namespace qualifiers, or an error is raised. Commands to be hidden are looked up in the global namespace even if the current namespace is not the global one. This prevents slaves from fooling a master interpreter into hiding the wrong command, by making the current namespace be different from the global one. For more details on hidden commands, see \fBHIDDEN COMMANDS\fR, below. .TP \fIslave \fBhidden\fR . Returns a list of the names of all hidden commands in \fIslave\fR. .TP \fIslave \fBinvokehidden\fR ?\fI\-option ...\fR? \fIhiddenName \fR?\fIarg ..\fR? . This command invokes the hidden command \fIhiddenName\fR with the supplied arguments, in \fIslave\fR. No substitutions or evaluations are applied to the arguments. Three \fI\-option\fRs are supported, all of which start with \fB\-\fR: \fB\-namespace\fR (which takes a single argument afterwards, \fInsName\fR), \fB\-global\fR, and \fB\-\|\-\fR. If the \fB\-namespace\fR flag is given, the hidden command is invoked in the specified namespace in the slave. If the \fB\-global\fR flag is given, the command is invoked at the global level in the slave; otherwise it is invoked at the current call frame and can access local variables in that or outer call frames. The \fB\-\|\-\fR flag allows the \fIhiddenCmdName\fR argument to start with a .QW \- character, and is otherwise unnecessary. If both the \fB\-namespace\fR and \fB\-global\fR flags are given, the \fB\-namespace\fR flag is ignored. Note that the hidden command will be executed (by default) in the current context stack frame of \fIslave\fR. For more details on hidden commands, see \fBHIDDEN COMMANDS\fR, below. .TP \fIslave \fBissafe\fR . Returns \fB1\fR if the slave interpreter is safe, \fB0\fR otherwise. .TP \fIslave \fBlimit\fR \fIlimitType\fR ?\fI\-option\fR? ?\fIvalue\fR \fI...\fR? . Sets up, manipulates and queries the configuration of the resource limit \fIlimitType\fR for the slave interpreter. If no \fI\-option\fR is specified, return the current configuration of the limit. If \fI\-option\fR is the sole argument, return the value of that option. Otherwise, a list of \fI\-option\fR/\fIvalue\fR argument pairs must supplied. See \fBRESOURCE LIMITS\fR below for a more detailed explanation of what limits and options are supported. .TP \fIslave \fBmarktrusted\fR . Marks the slave interpreter as trusted. Can only be invoked by a trusted interpreter. This command does not expose any hidden commands in the slave interpreter. The command has no effect if the slave is already trusted. .TP \fIslave\fR \fBrecursionlimit\fR ?\fInewlimit\fR? . Returns the maximum allowable nesting depth for the \fIslave\fR interpreter. If \fInewlimit\fR is specified, the recursion limit in \fIslave\fR will be set so that nesting of more than \fInewlimit\fR calls to \fBTcl_Eval()\fR and related procedures in \fIslave\fR will return an error. The \fInewlimit\fR value is also returned. The \fInewlimit\fR value must be a positive integer between 1 and the maximum value of a non-long integer on the platform. .RS .PP The command sets the maximum size of the Tcl call stack only. It cannot by itself prevent stack overflows on the C stack being used by the application. If your machine has a limit on the size of the C stack, you may get stack overflows before reaching the limit set by the command. If this happens, see if there is a mechanism in your system for increasing the maximum size of the C stack. .RE .SH "SAFE INTERPRETERS" .PP A safe interpreter is one with restricted functionality, so that is safe to execute an arbitrary script from your worst enemy without fear of that script damaging the enclosing application or the rest of your computing environment. In order to make an interpreter safe, certain commands and variables are removed from the interpreter. For example, commands to create files on disk are removed, and the \fBexec\fR command is removed, since it could be used to cause damage through subprocesses. Limited access to these facilities can be provided, by creating aliases to the master interpreter which check their arguments carefully and provide restricted access to a safe subset of facilities. For example, file creation might be allowed in a particular subdirectory and subprocess invocation might be allowed for a carefully selected and fixed set of programs. .PP A safe interpreter is created by specifying the \fB\-safe\fR switch to the \fBinterp create\fR command. Furthermore, any slave created by a safe interpreter will also be safe. .PP A safe interpreter is created with exactly the following set of built-in commands: .DS .ta 1.2i 2.4i 3.6i \fBafter\fR \fBappend\fR \fBapply\fR \fBarray\fR \fBbinary\fR \fBbreak\fR \fBcatch\fR \fBchan\fR \fBclock\fR \fBclose\fR \fBconcat\fR \fBcontinue\fR \fBdict\fR \fBeof\fR \fBerror\fR \fBeval\fR \fBexpr\fR \fBfblocked\fR \fBfcopy\fR \fBfileevent\fR \fBflush\fR \fBfor\fR \fBforeach\fR \fBformat\fR \fBgets\fR \fBglobal\fR \fBif\fR \fBincr\fR \fBinfo\fR \fBinterp\fR \fBjoin\fR \fBlappend\fR \fBlassign\fR \fBlindex\fR \fBlinsert\fR \fBlist\fR \fBllength\fR \fBlrange\fR \fBlrepeat\fR \fBlreplace\fR \fBlsearch\fR \fBlset\fR \fBlsort\fR \fBnamespace\fR \fBpackage\fR \fBpid\fR \fBproc\fR \fBputs\fR \fBread\fR \fBregexp\fR \fBregsub\fR \fBrename\fR \fBreturn\fR \fBscan\fR \fBseek\fR \fBset\fR \fBsplit\fR \fBstring\fR \fBsubst\fR \fBswitch\fR \fBtell\fR \fBtime\fR \fBtrace\fR \fBunset\fR \fBupdate\fR \fBuplevel\fR \fBupvar\fR \fBvariable\fR \fBvwait\fR \fBwhile\fR .DE The following commands are hidden by \fBinterp create\fR when it creates a safe interpreter: .DS .ta 1.2i 2.4i 3.6i \fBcd\fR \fBencoding\fR \fBexec\fR \fBexit\fR \fBfconfigure\fR \fBfile\fR \fBglob\fR \fBload\fR \fBopen\fR \fBpwd\fR \fBsocket\fR \fBsource\fR \fBunload\fR .DE These commands can be recreated later as Tcl procedures or aliases, or re-exposed by \fBinterp expose\fR. .PP The following commands from Tcl's library of support procedures are not present in a safe interpreter: .DS .ta 1.6i 3.2i \fBauto_exec_ok\fR \fBauto_import\fR \fBauto_load\fR \fBauto_load_index\fR \fBauto_qualify\fR \fBunknown\fR .DE Note in particular that safe interpreters have no default \fBunknown\fR command, so Tcl's default autoloading facilities are not available. Autoload access to Tcl's commands that are normally autoloaded: .DS .ta 2.1i \fBauto_mkindex\fR \fBauto_mkindex_old\fR \fBauto_reset\fR \fBhistory\fR \fBparray\fR \fBpkg_mkIndex\fR \fB::pkg::create\fR \fB::safe::interpAddToAccessPath\fR \fB::safe::interpCreate\fR \fB::safe::interpConfigure\fR \fB::safe::interpDelete\fR \fB::safe::interpFindInAccessPath\fR \fB::safe::interpInit\fR \fB::safe::setLogCmd\fR \fBtcl_endOfWord\fR \fBtcl_findLibrary\fR \fBtcl_startOfNextWord\fR \fBtcl_startOfPreviousWord\fR \fBtcl_wordBreakAfter\fR \fBtcl_wordBreakBefore\fR .DE can only be provided by explicit definition of an \fBunknown\fR command in the safe interpreter. This will involve exposing the \fBsource\fR command. This is most easily accomplished by creating the safe interpreter with Tcl's \fBSafe\-Tcl\fR mechanism. \fBSafe\-Tcl\fR provides safe versions of \fBsource\fR, \fBload\fR, and other Tcl commands needed to support autoloading of commands and the loading of packages. .PP In addition, the \fBenv\fR variable is not present in a safe interpreter, so it cannot share environment variables with other interpreters. The \fBenv\fR variable poses a security risk, because users can store sensitive information in an environment variable. For example, the PGP manual recommends storing the PGP private key protection password in the environment variable \fIPGPPASS\fR. Making this variable available to untrusted code executing in a safe interpreter would incur a security risk. .PP If extensions are loaded into a safe interpreter, they may also restrict their own functionality to eliminate unsafe commands. For a discussion of management of extensions for safety see the manual entries for \fBSafe\-Tcl\fR and the \fBload\fR Tcl command. .PP A safe interpreter may not alter the recursion limit of any interpreter, including itself. .SH "ALIAS INVOCATION" .PP The alias mechanism has been carefully designed so that it can be used safely when an untrusted script is executing in a safe slave and the target of the alias is a trusted master. The most important thing in guaranteeing safety is to ensure that information passed from the slave to the master is never evaluated or substituted in the master; if this were to occur, it would enable an evil script in the slave to invoke arbitrary functions in the master, which would compromise security. .PP When the source for an alias is invoked in the slave interpreter, the usual Tcl substitutions are performed when parsing that command. These substitutions are carried out in the source interpreter just as they would be for any other command invoked in that interpreter. The command procedure for the source command takes its arguments and merges them with the \fItargetCmd\fR and \fIarg\fRs for the alias to create a new array of arguments. If the words of \fIsrcCmd\fR were .QW "\fIsrcCmd arg1 arg2 ... argN\fR" , the new set of words will be .QW "\fItargetCmd arg arg ... arg arg1 arg2 ... argN\fR" , where \fItargetCmd\fR and \fIarg\fRs are the values supplied when the alias was created. \fITargetCmd\fR is then used to locate a command procedure in the target interpreter, and that command procedure is invoked with the new set of arguments. An error occurs if there is no command named \fItargetCmd\fR in the target interpreter. No additional substitutions are performed on the words: the target command procedure is invoked directly, without going through the normal Tcl evaluation mechanism. Substitutions are thus performed on each word exactly once: \fItargetCmd\fR and \fIargs\fR were substituted when parsing the command that created the alias, and \fIarg1 - argN\fR are substituted when the alias's source command is parsed in the source interpreter. .PP When writing the \fItargetCmd\fRs for aliases in safe interpreters, it is very important that the arguments to that command never be evaluated or substituted, since this would provide an escape mechanism whereby the slave interpreter could execute arbitrary code in the master. This in turn would compromise the security of the system. .SH "HIDDEN COMMANDS" .PP Safe interpreters greatly restrict the functionality available to Tcl programs executing within them. Allowing the untrusted Tcl program to have direct access to this functionality is unsafe, because it can be used for a variety of attacks on the environment. However, there are times when there is a legitimate need to use the dangerous functionality in the context of the safe interpreter. For example, sometimes a program must be \fBsource\fRd into the interpreter. Another example is Tk, where windows are bound to the hierarchy of windows for a specific interpreter; some potentially dangerous functions, e.g. window management, must be performed on these windows within the interpreter context. .PP The \fBinterp\fR command provides a solution to this problem in the form of \fIhidden commands\fR. Instead of removing the dangerous commands entirely from a safe interpreter, these commands are hidden so they become unavailable to Tcl scripts executing in the interpreter. However, such hidden commands can be invoked by any trusted ancestor of the safe interpreter, in the context of the safe interpreter, using \fBinterp invoke\fR. Hidden commands and exposed commands reside in separate name spaces. It is possible to define a hidden command and an exposed command by the same name within one interpreter. .PP Hidden commands in a slave interpreter can be invoked in the body of procedures called in the master during alias invocation. For example, an alias for \fBsource\fR could be created in a slave interpreter. When it is invoked in the slave interpreter, a procedure is called in the master interpreter to check that the operation is allowable (e.g. it asks to source a file that the slave interpreter is allowed to access). The procedure then it invokes the hidden \fBsource\fR command in the slave interpreter to actually source in the contents of the file. Note that two commands named \fBsource\fR exist in the slave interpreter: the alias, and the hidden command. .PP Because a master interpreter may invoke a hidden command as part of handling an alias invocation, great care must be taken to avoid evaluating any arguments passed in through the alias invocation. Otherwise, malicious slave interpreters could cause a trusted master interpreter to execute dangerous commands on their behalf. See the section on \fBALIAS INVOCATION\fR for a more complete discussion of this topic. To help avoid this problem, no substitutions or evaluations are applied to arguments of \fBinterp invokehidden\fR. .PP Safe interpreters are not allowed to invoke hidden commands in themselves or in their descendants. This prevents safe slaves from gaining access to hidden functionality in themselves or their descendants. .PP The set of hidden commands in an interpreter can be manipulated by a trusted interpreter using \fBinterp expose\fR and \fBinterp hide\fR. The \fBinterp expose\fR command moves a hidden command to the set of exposed commands in the interpreter identified by \fIpath\fR, potentially renaming the command in the process. If an exposed command by the targeted name already exists, the operation fails. Similarly, \fBinterp hide\fR moves an exposed command to the set of hidden commands in that interpreter. Safe interpreters are not allowed to move commands between the set of hidden and exposed commands, in either themselves or their descendants. .PP Currently, the names of hidden commands cannot contain namespace qualifiers, and you must first rename a command in a namespace to the global namespace before you can hide it. Commands to be hidden by \fBinterp hide\fR are looked up in the global namespace even if the current namespace is not the global one. This prevents slaves from fooling a master interpreter into hiding the wrong command, by making the current namespace be different from the global one. .SH "RESOURCE LIMITS" .PP Every interpreter has two kinds of resource limits that may be imposed by any master interpreter upon its slaves. Command limits (of type \fBcommand\fR) restrict the total number of Tcl commands that may be executed by an interpreter (as can be inspected via the \fBinfo cmdcount\fR command), and time limits (of type \fBtime\fR) place a limit by which execution within the interpreter must complete. Note that time limits are expressed as \fIabsolute\fR times (as in \fBclock seconds\fR) and not relative times (as in \fBafter\fR) because they may be modified after creation. .PP When a limit is exceeded for an interpreter, first any handler callbacks defined by master interpreters are called. If those callbacks increase or remove the limit, execution within the (previously) limited interpreter continues. If the limit is still in force, an error is generated at that point and normal processing of errors within the interpreter (by the \fBcatch\fR command) is disabled, so the error propagates outwards (building a stack-trace as it goes) to the point where the limited interpreter was invoked (e.g. by \fBinterp eval\fR) where it becomes the responsibility of the calling code to catch and handle. .SS "LIMIT OPTIONS" .PP Every limit has a number of options associated with it, some of which are common across all kinds of limits, and others of which are particular to the kind of limit. .TP \fB\-command\fR . This option (common for all limit types) specifies (if non-empty) a Tcl script to be executed in the global namespace of the interpreter reading and writing the option when the particular limit in the limited interpreter is exceeded. The callback may modify the limit on the interpreter if it wishes the limited interpreter to continue executing. If the callback generates an exception, it is reported through the background exception mechanism (see \fBBACKGROUND EXCEPTION HANDLING\fR). Note that the callbacks defined by one interpreter are completely isolated from the callbacks defined by another, and that the order in which those callbacks are called is undefined. .TP \fB\-granularity\fR . This option (common for all limit types) specifies how frequently (out of the points when the Tcl interpreter is in a consistent state where limit checking is possible) that the limit is actually checked. This allows the tuning of how frequently a limit is checked, and hence how often the limit-checking overhead (which may be substantial in the case of time limits) is incurred. .TP \fB\-milliseconds\fR . This option specifies the number of milliseconds after the moment defined in the \fB\-seconds\fR option that the time limit will fire. It should only ever be specified in conjunction with the \fB\-seconds\fR option (whether it was set previously or is being set this invocation.) .TP \fB\-seconds\fR . This option specifies the number of seconds after the epoch (see \fBclock seconds\fR) that the time limit for the interpreter will be triggered. The limit will be triggered at the start of the second unless specified at a sub-second level using the \fB\-milliseconds\fR option. This option may be the empty string, which indicates that a time limit is not set for the interpreter. .TP \fB\-value\fR . This option specifies the number of commands that the interpreter may execute before triggering the command limit. This option may be the empty string, which indicates that a command limit is not set for the interpreter. .PP Where an interpreter with a resource limit set on it creates a slave interpreter, that slave interpreter will have resource limits imposed on it that are at least as restrictive as the limits on the creating master interpreter. If the master interpreter of the limited master wishes to relax these conditions, it should hide the \fBinterp\fR command in the child and then use aliases and the \fBinterp invokehidden\fR subcommand to provide such access as it chooses to the \fBinterp\fR command to the limited master as necessary. .SH "BACKGROUND EXCEPTION HANDLING" .PP When an exception happens in a situation where it cannot be reported directly up the stack (e.g. when processing events in an \fBupdate\fR or \fBvwait\fR call) the exception is instead reported through the background exception handling mechanism. Every interpreter has a background exception handler registered; the default exception handler arranges for the \fBbgerror\fR command in the interpreter's global namespace to be called, but other exception handlers may be installed and process background exceptions in substantially different ways. .PP A background exception handler consists of a non-empty list of words to which will be appended two further words at invocation time. The first word will be the interpreter result at time of the exception, typically an error message, and the second will be the dictionary of return options at the time of the exception. These are the same values that \fBcatch\fR can capture when it controls script evaluation in a non-background situation. The resulting list will then be executed in the interpreter's global namespace without further substitutions being performed. .SH CREDITS The safe interpreter mechanism is based on the Safe-Tcl prototype implemented by Nathaniel Borenstein and Marshall Rose. .SH EXAMPLES .PP Creating and using an alias for a command in the current interpreter: .PP .CS \fBinterp alias\fR {} getIndex {} lsearch {alpha beta gamma delta} set idx [getIndex delta] .CE .PP Executing an arbitrary command in a safe interpreter where every invocation of \fBlappend\fR is logged: .PP .CS set i [\fBinterp create\fR -safe] \fBinterp hide\fR $i lappend \fBinterp alias\fR $i lappend {} loggedLappend $i proc loggedLappend {i args} { puts "logged invocation of lappend $args" \fBinterp invokehidden\fR $i lappend {*}$args } \fBinterp eval\fR $i $someUntrustedScript .CE .PP Setting a resource limit on an interpreter so that an infinite loop terminates. .PP .CS set i [\fBinterp create\fR] \fBinterp limit\fR $i command -value 1000 \fBinterp eval\fR $i { set x 0 while {1} { puts "Counting up... [incr x]" } } .CE .SH "SEE ALSO" bgerror(n), load(n), safe(n), Tcl_CreateSlave(3), Tcl_Eval(3), Tcl_BackgroundException(3) .SH KEYWORDS alias, master interpreter, safe interpreter, slave interpreter '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/switch.n0000644000175000017500000001465412663660065014026 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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 switch n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME switch \- Evaluate one of several scripts, depending on a given value .SH SYNOPSIS \fBswitch \fR?\fIoptions\fR?\fI string pattern body \fR?\fIpattern body \fR...? .sp \fBswitch \fR?\fIoptions\fR?\fI string \fR{\fIpattern body \fR?\fIpattern body \fR...?} .BE .SH DESCRIPTION .PP The \fBswitch\fR command matches its \fIstring\fR argument against each of the \fIpattern\fR arguments in order. As soon as it finds a \fIpattern\fR that matches \fIstring\fR it evaluates the following \fIbody\fR argument by passing it recursively to the Tcl interpreter and returns the result of that evaluation. If the last \fIpattern\fR argument is \fBdefault\fR then it matches anything. If no \fIpattern\fR argument matches \fIstring\fR and no default is given, then the \fBswitch\fR command returns an empty string. .PP If the initial arguments to \fBswitch\fR start with \fB\-\fR then they are treated as options unless there are exactly two arguments to \fBswitch\fR (in which case the first must the \fIstring\fR and the second must be the \fIpattern\fR/\fIbody\fR list). The following options are currently supported: .TP 10 \fB\-exact\fR . Use exact matching when comparing \fIstring\fR to a pattern. This is the default. .TP 10 \fB\-glob\fR . When matching \fIstring\fR to the patterns, use glob-style matching (i.e. the same as implemented by the \fBstring match\fR command). .TP 10 \fB\-regexp\fR . When matching \fIstring\fR to the patterns, use regular expression matching (as described in the \fBre_syntax\fR reference page). .TP 10 \fB\-nocase\fR . Causes comparisons to be handled in a case-insensitive manner. .TP 10 \fB\-matchvar\fR \fIvarName\fR . This option (only legal when \fB\-regexp\fR is also specified) specifies the name of a variable into which the list of matches found by the regular expression engine will be written. The first element of the list written will be the overall substring of the input string (i.e. the \fIstring\fR argument to \fBswitch\fR) matched, the second element of the list will be the substring matched by the first capturing parenthesis in the regular expression that matched, and so on. When a \fBdefault\fR branch is taken, the variable will have the empty list written to it. This option may be specified at the same time as the \fB\-indexvar\fR option. .TP 10 \fB\-indexvar\fR \fIvarName\fR . This option (only legal when \fB\-regexp\fR is also specified) specifies the name of a variable into which the list of indices referring to matching substrings found by the regular expression engine will be written. The first element of the list written will be a two-element list specifying the index of the start and index of the first character after the end of the overall substring of the input string (i.e. the \fIstring\fR argument to \fBswitch\fR) matched, in a similar way to the \fB\-indices\fR option to the \fBregexp\fR can obtain. Similarly, the second element of the list refers to the first capturing parenthesis in the regular expression that matched, and so on. When a \fBdefault\fR branch is taken, the variable will have the empty list written to it. This option may be specified at the same time as the \fB\-matchvar\fR option. .TP 10 \fB\-\|\-\fR . Marks the end of options. The argument following this one will be treated as \fIstring\fR even if it starts with a \fB\-\fR. This is not required when the matching patterns and bodies are grouped together in a single argument. .PP Two syntaxes are provided for the \fIpattern\fR and \fIbody\fR arguments. The first uses a separate argument for each of the patterns and commands; this form is convenient if substitutions are desired on some of the patterns or commands. The second form places all of the patterns and commands together into a single argument; the argument must have proper list structure, with the elements of the list being the patterns and commands. The second form makes it easy to construct multi-line switch commands, since the braces around the whole list make it unnecessary to include a backslash at the end of each line. Since the \fIpattern\fR arguments are in braces in the second form, no command or variable substitutions are performed on them; this makes the behavior of the second form different than the first form in some cases. .PP If a \fIbody\fR is specified as .QW \fB\-\fR it means that the \fIbody\fR for the next pattern should also be used as the body for this pattern (if the next pattern also has a body of .QW \fB\-\fR then the body after that is used, and so on). This feature makes it possible to share a single \fIbody\fR among several patterns. .PP Beware of how you place comments in \fBswitch\fR commands. Comments should only be placed \fBinside\fR the execution body of one of the patterns, and not intermingled with the patterns. .SH "EXAMPLES" .PP The \fBswitch\fR command can match against variables and not just literals, as shown here (the result is \fI2\fR): .PP .CS set foo "abc" \fBswitch\fR abc a \- b {expr {1}} $foo {expr {2}} default {expr {3}} .CE .PP Using glob matching and the fall-through body is an alternative to writing regular expressions with alternations, as can be seen here (this returns \fI1\fR): .PP .CS \fBswitch\fR \-glob aaab { a*b \- b {expr {1}} a* {expr {2}} default {expr {3}} } .CE .PP Whenever nothing matches, the \fBdefault\fR clause (which must be last) is taken. This example has a result of \fI3\fR: .PP .CS \fBswitch\fR xyz { a \- b { # Correct Comment Placement expr {1} } c { expr {2} } default { expr {3} } } .CE .PP When matching against regular expressions, information about what exactly matched is easily obtained using the \fB\-matchvar\fR option: .PP .CS \fBswitch\fR \-regexp \-matchvar foo \-\- $bar { a(b*)c { puts "Found [string length [lindex $foo 1]] 'b's" } d(e*)f(g*)h { puts "Found [string length [lindex $foo 1]] 'e's and\e [string length [lindex $foo 2]] 'g's" } } .CE .SH "SEE ALSO" for(n), if(n), regexp(n) .SH KEYWORDS switch, match, regular expression .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/mathfunc.n0000644000175000017500000002261612663660065014327 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-2000 Sun Microsystems, Inc. '\" Copyright (c) 2005 by Kevin B. Kenny . All rights reserved '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH mathfunc n 8.5 Tcl "Tcl Mathematical Functions" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME mathfunc \- Mathematical functions for Tcl expressions .SH SYNOPSIS package require \fBTcl 8.5\fR .sp \fB::tcl::mathfunc::abs\fR \fIarg\fR .br \fB::tcl::mathfunc::acos\fR \fIarg\fR .br \fB::tcl::mathfunc::asin\fR \fIarg\fR .br \fB::tcl::mathfunc::atan\fR \fIarg\fR .br \fB::tcl::mathfunc::atan2\fR \fIy\fR \fIx\fR .br \fB::tcl::mathfunc::bool\fR \fIarg\fR .br \fB::tcl::mathfunc::ceil\fR \fIarg\fR .br \fB::tcl::mathfunc::cos\fR \fIarg\fR .br \fB::tcl::mathfunc::cosh\fR \fIarg\fR .br \fB::tcl::mathfunc::double\fR \fIarg\fR .br \fB::tcl::mathfunc::entier\fR \fIarg\fR .br \fB::tcl::mathfunc::exp\fR \fIarg\fR .br \fB::tcl::mathfunc::floor\fR \fIarg\fR .br \fB::tcl::mathfunc::fmod\fR \fIx\fR \fIy\fR .br \fB::tcl::mathfunc::hypot\fR \fIx\fR \fIy\fR .br \fB::tcl::mathfunc::int\fR \fIarg\fR .br \fB::tcl::mathfunc::isqrt\fR \fIarg\fR .br \fB::tcl::mathfunc::log\fR \fIarg\fR .br \fB::tcl::mathfunc::log10\fR \fIarg\fR .br \fB::tcl::mathfunc::max\fR \fIarg\fR ?\fIarg\fR ...? .br \fB::tcl::mathfunc::min\fR \fIarg\fR ?\fIarg\fR ...? .br \fB::tcl::mathfunc::pow\fR \fIx\fR \fIy\fR .br \fB::tcl::mathfunc::rand\fR .br \fB::tcl::mathfunc::round\fR \fIarg\fR .br \fB::tcl::mathfunc::sin\fR \fIarg\fR .br \fB::tcl::mathfunc::sinh\fR \fIarg\fR .br \fB::tcl::mathfunc::sqrt\fR \fIarg\fR .br \fB::tcl::mathfunc::srand\fR \fIarg\fR .br \fB::tcl::mathfunc::tan\fR \fIarg\fR .br \fB::tcl::mathfunc::tanh\fR \fIarg\fR .br \fB::tcl::mathfunc::wide\fR \fIarg\fR .sp .BE .SH "DESCRIPTION" .PP The \fBexpr\fR command handles mathematical functions of the form \fBsin($x)\fR or \fBatan2($y,$x)\fR by converting them to calls of the form \fB[tcl::mathfunc::sin [expr {$x}]]\fR or \fB[tcl::mathfunc::atan2 [expr {$y}] [expr {$x}]]\fR. A number of math functions are available by default within the namespace \fB::tcl::mathfunc\fR; these functions are also available for code apart from \fBexpr\fR, by invoking the given commands directly. .PP Tcl supports the following mathematical functions in expressions, all of which work solely with floating-point numbers unless otherwise noted: .DS .ta 3c 6c 9c \fBabs\fR \fBacos\fR \fBasin\fR \fBatan\fR \fBatan2\fR \fBbool\fR \fBceil\fR \fBcos\fR \fBcosh\fR \fBdouble\fR \fBentier\fR \fBexp\fR \fBfloor\fR \fBfmod\fR \fBhypot\fR \fBint\fR \fBisqrt\fR \fBlog\fR \fBlog10\fR \fBmax\fR \fBmin\fR \fBpow\fR \fBrand\fR \fBround\fR \fBsin\fR \fBsinh\fR \fBsqrt\fR \fBsrand\fR \fBtan\fR \fBtanh\fR \fBwide\fR .DE .PP In addition to these predefined functions, applications may define additional functions by using \fBproc\fR (or any other method, such as \fBinterp alias\fR or \fBTcl_CreateObjCommand\fR) to define new commands in the \fBtcl::mathfunc\fR namespace. In addition, an obsolete interface named \fBTcl_CreateMathFunc\fR() is available to extensions that are written in C. The latter interface is not recommended for new implementations. .SS "DETAILED DEFINITIONS" .TP \fBabs \fIarg\fR . Returns the absolute value of \fIarg\fR. \fIArg\fR may be either integer or floating-point, and the result is returned in the same form. .TP \fBacos \fIarg\fR . Returns the arc cosine of \fIarg\fR, in the range [\fI0\fR,\fIpi\fR] radians. \fIArg\fR should be in the range [\fI\-1\fR,\fI1\fR]. .TP \fBasin \fIarg\fR . Returns the arc sine of \fIarg\fR, in the range [\fI\-pi/2\fR,\fIpi/2\fR] radians. \fIArg\fR should be in the range [\fI\-1\fR,\fI1\fR]. .TP \fBatan \fIarg\fR . Returns the arc tangent of \fIarg\fR, in the range [\fI\-pi/2\fR,\fIpi/2\fR] radians. .TP \fBatan2 \fIy x\fR . Returns the arc tangent of \fIy\fR/\fIx\fR, in the range [\fI\-pi\fR,\fIpi\fR] radians. \fIx\fR and \fIy\fR cannot both be 0. If \fIx\fR is greater than \fI0\fR, this is equivalent to .QW "\fBatan \fR[\fBexpr\fR {\fIy\fB/\fIx\fR}]" . .TP \fBbool \fIarg\fR . Accepts any numeric value, or any string acceptable to \fBstring is boolean\fR, and returns the corresponding boolean value \fB0\fR or \fB1\fR. Non-zero numbers are true. Other numbers are false. Non-numeric strings produce boolean value in agreement with \fBstring is true\fR and \fBstring is false\fR. .TP \fBceil \fIarg\fR . Returns the smallest integral floating-point value (i.e. with a zero fractional part) not less than \fIarg\fR. The argument may be any numeric value. .TP \fBcos \fIarg\fR . Returns the cosine of \fIarg\fR, measured in radians. .TP \fBcosh \fIarg\fR . Returns the hyperbolic cosine of \fIarg\fR. If the result would cause an overflow, an error is returned. .TP \fBdouble \fIarg\fR . The argument may be any numeric value, If \fIarg\fR is a floating-point value, returns \fIarg\fR, otherwise converts \fIarg\fR to floating-point and returns the converted value. May return \fBInf\fR or \fB\-Inf\fR when the argument is a numeric value that exceeds the floating-point range. .TP \fBentier \fIarg\fR . The argument may be any numeric value. The integer part of \fIarg\fR is determined and returned. The integer range returned by this function is unlimited, unlike \fBint\fR and \fBwide\fR which truncate their range to fit in particular storage widths. .TP \fBexp \fIarg\fR . Returns the exponential of \fIarg\fR, defined as \fIe\fR**\fIarg\fR. If the result would cause an overflow, an error is returned. .TP \fBfloor \fIarg\fR . Returns the largest integral floating-point value (i.e. with a zero fractional part) not greater than \fIarg\fR. The argument may be any numeric value. .TP \fBfmod \fIx y\fR . Returns the floating-point remainder of the division of \fIx\fR by \fIy\fR. If \fIy\fR is 0, an error is returned. .TP \fBhypot \fIx y\fR . Computes the length of the hypotenuse of a right-angled triangle, approximately .QW "\fBsqrt\fR [\fBexpr\fR {\fIx\fB*\fIx\fB+\fIy\fB*\fIy\fR}]" except for being more numerically stable when the two arguments have substantially different magnitudes. .TP \fBint \fIarg\fR . The argument may be any numeric value. The integer part of \fIarg\fR is determined, and then the low order bits of that integer value up to the machine word size are returned as an integer value. For reference, the number of bytes in the machine word are stored in the \fBwordSize\fR element of the \fBtcl_platform\fR array. .TP \fBisqrt \fIarg\fR . Computes the integer part of the square root of \fIarg\fR. \fIArg\fR must be a positive value, either an integer or a floating point number. Unlike \fBsqrt\fR, which is limited to the precision of a floating point number, \fIisqrt\fR will return a result of arbitrary precision. .TP \fBlog \fIarg\fR . Returns the natural logarithm of \fIarg\fR. \fIArg\fR must be a positive value. .TP \fBlog10 \fIarg\fR . Returns the base 10 logarithm of \fIarg\fR. \fIArg\fR must be a positive value. .TP \fBmax \fIarg\fB \fI...\fR . Accepts one or more numeric arguments. Returns the one argument with the greatest value. .TP \fBmin \fIarg\fB \fI...\fR . Accepts one or more numeric arguments. Returns the one argument with the least value. .TP \fBpow \fIx y\fR . Computes the value of \fIx\fR raised to the power \fIy\fR. If \fIx\fR is negative, \fIy\fR must be an integer value. .TP \fBrand\fR . Returns a pseudo-random floating-point value in the range (\fI0\fR,\fI1\fR). The generator algorithm is a simple linear congruential generator that is not cryptographically secure. Each result from \fBrand\fR completely determines all future results from subsequent calls to \fBrand\fR, so \fBrand\fR should not be used to generate a sequence of secrets, such as one-time passwords. The seed of the generator is initialized from the internal clock of the machine or may be set with the \fBsrand\fR function. .TP \fBround \fIarg\fR . If \fIarg\fR is an integer value, returns \fIarg\fR, otherwise converts \fIarg\fR to integer by rounding and returns the converted value. .TP \fBsin \fIarg\fR . Returns the sine of \fIarg\fR, measured in radians. .TP \fBsinh \fIarg\fR . Returns the hyperbolic sine of \fIarg\fR. If the result would cause an overflow, an error is returned. .TP \fBsqrt \fIarg\fR . The argument may be any non-negative numeric value. Returns a floating-point value that is the square root of \fIarg\fR. May return \fBInf\fR when the argument is a numeric value that exceeds the square of the maximum value of the floating-point range. .TP \fBsrand \fIarg\fR . The \fIarg\fR, which must be an integer, is used to reset the seed for the random number generator of \fBrand\fR. Returns the first random number (see \fBrand\fR) from that seed. Each interpreter has its own seed. .TP \fBtan \fIarg\fR . Returns the tangent of \fIarg\fR, measured in radians. .TP \fBtanh \fIarg\fR . Returns the hyperbolic tangent of \fIarg\fR. .TP \fBwide \fIarg\fR . The argument may be any numeric value. The integer part of \fIarg\fR is determined, and then the low order 64 bits of that integer value are returned as an integer value. .SH "SEE ALSO" expr(n), mathop(n), namespace(n) .SH "COPYRIGHT" .nf Copyright (c) 1993 The Regents of the University of California. Copyright (c) 1994-2000 Sun Microsystems Incorporated. Copyright (c) 2005, 2006 by Kevin B. Kenny . .fi '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/lsearch.n0000644000175000017500000001614412663660065014142 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2001 Kevin B. Kenny . All rights reserved. '\" Copyright (c) 2003-2004 Donal K. Fellows. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lsearch n 8.6 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lsearch \- See if a list contains a particular element .SH SYNOPSIS \fBlsearch \fR?\fIoptions\fR? \fIlist pattern\fR .BE .SH DESCRIPTION .PP This command searches the elements of \fIlist\fR to see if one of them matches \fIpattern\fR. If so, the command returns the index of the first matching element (unless the options \fB\-all\fR or \fB\-inline\fR are specified.) If not, the command returns \fB\-1\fR. The \fIoption\fR arguments indicates how the elements of the list are to be matched against \fIpattern\fR and must have one of the values below: .SS "MATCHING STYLE OPTIONS" .PP If all matching style options are omitted, the default matching style is \fB\-glob\fR. If more than one matching style is specified, the last matching style given takes precedence. .TP \fB\-exact\fR . \fIPattern\fR is a literal string that is compared for exact equality against each list element. .TP \fB\-glob\fR . \fIPattern\fR is a glob-style pattern which is matched against each list element using the same rules as the \fBstring match\fR command. .TP \fB\-regexp\fR . \fIPattern\fR is treated as a regular expression and matched against each list element using the rules described in the \fBre_syntax\fR reference page. .TP \fB\-sorted\fR . The list elements are in sorted order. If this option is specified, \fBlsearch\fR will use a more efficient searching algorithm to search \fIlist\fR. If no other options are specified, \fIlist\fR is assumed to be sorted in increasing order, and to contain ASCII strings. This option is mutually exclusive with \fB\-glob\fR and \fB\-regexp\fR, and is treated exactly like \fB\-exact\fR when either \fB\-all\fR or \fB\-not\fR are specified. .SS "GENERAL MODIFIER OPTIONS" .PP These options may be given with all matching styles. .TP \fB\-all\fR . Changes the result to be the list of all matching indices (or all matching values if \fB\-inline\fR is specified as well.) If indices are returned, the indices will be in numeric order. If values are returned, the order of the values will be the order of those values within the input \fIlist\fR. .TP \fB\-inline\fR . The matching value is returned instead of its index (or an empty string if no value matches.) If \fB\-all\fR is also specified, then the result of the command is the list of all values that matched. .TP \fB\-not\fR . This negates the sense of the match, returning the index of the first non-matching value in the list. .TP \fB\-start\fR\0\fIindex\fR . The list is searched starting at position \fIindex\fR. The interpretation of the \fIindex\fR value is the same as for the command \fBstring index\fR, supporting simple index arithmetic and indices relative to the end of the list. .SS "CONTENTS DESCRIPTION OPTIONS" .PP These options describe how to interpret the items in the list being searched. They are only meaningful when used with the \fB\-exact\fR and \fB\-sorted\fR options. If more than one is specified, the last one takes precedence. The default is \fB\-ascii\fR. .TP \fB\-ascii\fR . The list elements are to be examined as Unicode strings (the name is for backward-compatibility reasons.) .TP \fB\-dictionary\fR . The list elements are to be compared using dictionary-style comparisons (see \fBlsort\fR for a fuller description). Note that this only makes a meaningful difference from the \fB\-ascii\fR option when the \fB\-sorted\fR option is given, because values are only dictionary-equal when exactly equal. .TP \fB\-integer\fR . The list elements are to be compared as integers. .TP \fB\-nocase\fR . Causes comparisons to be handled in a case-insensitive manner. Has no effect if combined with the \fB\-dictionary\fR, \fB\-integer\fR, or \fB\-real\fR options. .TP \fB\-real\fR . The list elements are to be compared as floating-point values. .SS "SORTED LIST OPTIONS" .PP These options (only meaningful with the \fB\-sorted\fR option) specify how the list is sorted. If more than one is given, the last one takes precedence. The default option is \fB\-increasing\fR. .TP \fB\-decreasing\fR . The list elements are sorted in decreasing order. This option is only meaningful when used with \fB\-sorted\fR. .TP \fB\-increasing\fR . The list elements are sorted in increasing order. This option is only meaningful when used with \fB\-sorted\fR. .TP \fB\-bisect\fR .VS 8.6 Inexact search when the list elements are in sorted order. For an increasing list the last index where the element is less than or equal to the pattern is returned. For a decreasing list the last index where the element is greater than or equal to the pattern is returned. If the pattern is before the first element or the list is empty, -1 is returned. This option implies \fB\-sorted\fR and cannot be used with either \fB\-all\fR or \fB\-not\fR. .VE 8.6 .SS "NESTED LIST OPTIONS" .PP These options are used to search lists of lists. They may be used with any other options. .TP \fB\-index\fR\0\fIindexList\fR . This option is designed for use when searching within nested lists. The \fIindexList\fR argument gives a path of indices (much as might be used with the \fBlindex\fR or \fBlset\fR commands) within each element to allow the location of the term being matched against. .TP \fB\-subindices\fR . If this option is given, the index result from this command (or every index result when \fB\-all\fR is also specified) will be a complete path (suitable for use with \fBlindex\fR or \fBlset\fR) within the overall list to the term found. This option has no effect unless the \fB\-index\fR is also specified, and is just a convenience short-cut. .SH EXAMPLES .PP Basic searching: .PP .CS \fBlsearch\fR {a b c d e} c \fI\(-> 2\fR \fBlsearch\fR -all {a b c a b c} c \fI\(-> 2 5\fR .CE .PP Using \fBlsearch\fR to filter lists: .PP .CS \fBlsearch\fR -inline {a20 b35 c47} b* \fI\(-> b35\fR \fBlsearch\fR -inline -not {a20 b35 c47} b* \fI\(-> a20\fR \fBlsearch\fR -all -inline -not {a20 b35 c47} b* \fI\(-> a20 c47\fR \fBlsearch\fR -all -not {a20 b35 c47} b* \fI\(-> 0 2\fR .CE .PP This can even do a .QW set-like removal operation: .PP .CS \fBlsearch\fR -all -inline -not -exact {a b c a d e a f g a} a \fI\(-> b c d e f g\fR .CE .PP Searching may start part-way through the list: .PP .CS \fBlsearch\fR -start 3 {a b c a b c} c \fI\(-> 5\fR .CE .PP It is also possible to search inside elements: .PP .CS \fBlsearch\fR -index 1 -all -inline {{a abc} {b bcd} {c cde}} *bc* \fI\(-> {a abc} {b bcd}\fR .CE .SH "SEE ALSO" foreach(n), list(n), lappend(n), lindex(n), linsert(n), llength(n), lset(n), lsort(n), lrange(n), lreplace(n), string(n) .SH KEYWORDS binary search, linear search, list, match, pattern, regular expression, search, string '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/platform_shell.n0000644000175000017500000000430212663660065015525 0ustar sergeisergei'\" '\" Copyright (c) 2006-2008 ActiveState Software Inc '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH "platform::shell" n 1.1.4 platform::shell "Tcl Bundled Packages" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME platform::shell \- System identification support code and utilities .SH SYNOPSIS .nf \fBpackage require platform::shell ?1.1.4?\fR .sp \fBplatform::shell::generic \fIshell\fR \fBplatform::shell::identify \fIshell\fR \fBplatform::shell::platform \fIshell\fR .fi .BE .SH DESCRIPTION .PP The \fBplatform::shell\fR package provides several utility commands useful for the identification of the architecture of a specific Tcl shell. .PP This package allows the identification of the architecture of a specific Tcl shell different from the shell running the package. The only requirement is that the other shell (identified by its path), is actually executable on the current machine. .PP While for most platform this means that the architecture of the interrogated shell is identical to the architecture of the running shell this is not generally true. A counter example are all platforms which have 32 and 64 bit variants and where a 64bit system is able to run 32bit code. For these running and interrogated shell may have different 32/64 bit settings and thus different identifiers. .PP For applications like a code repository it is important to identify the architecture of the shell which will actually run the installed packages, versus the architecture of the shell running the repository software. .SH COMMANDS .TP \fBplatform::shell::identify \fIshell\fR This command does the same identification as \fBplatform::identify\fR, for the specified Tcl shell, in contrast to the running shell. .TP \fBplatform::shell::generic \fIshell\fR This command does the same identification as \fBplatform::generic\fR, for the specified Tcl shell, in contrast to the running shell. .TP \fBplatform::shell::platform \fIshell\fR This command returns the contents of \fBtcl_platform(platform)\fR for the specified Tcl shell. .SH KEYWORDS operating system, cpu architecture, platform, architecture tcl8.6.5/doc/ChnlStack.30000644000175000017500000000746112663660065014302 0ustar sergeisergei'\" '\" Copyright (c) 1999-2000 Ajuba Solutions. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. .TH Tcl_StackChannel 3 8.3 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_StackChannel, Tcl_UnstackChannel, Tcl_GetStackedChannel, Tcl_GetTopChannel \- manipulate stacked I/O channels .SH SYNOPSIS .nf .nf \fB#include \fR .sp Tcl_Channel \fBTcl_StackChannel\fR(\fIinterp, typePtr, clientData, mask, channel\fR) .sp int \fBTcl_UnstackChannel\fR(\fIinterp, channel\fR) .sp Tcl_Channel \fBTcl_GetStackedChannel\fR(\fIchannel\fR) .sp Tcl_Channel \fBTcl_GetTopChannel\fR(\fIchannel\fR) .sp .SH ARGUMENTS .AS Tcl_ChannelType clientData .AP Tcl_Interp *interp in Interpreter for error reporting. .AP "const Tcl_ChannelType" *typePtr in The new channel I/O procedures to use for \fIchannel\fR. .AP ClientData clientData in Arbitrary one-word value to pass to channel I/O procedures. .AP int mask in Conditions under which \fIchannel\fR will be used: OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR and \fBTCL_EXCEPTION\fR. This can be a subset of the operations currently allowed on \fIchannel\fR. .AP Tcl_Channel channel in An existing Tcl channel such as returned by \fBTcl_CreateChannel\fR. .BE .SH DESCRIPTION .PP These functions are for use by extensions that add processing layers to Tcl I/O channels. Examples include compression and encryption modules. These functions transparently stack and unstack a new channel on top of an existing one. Any number of channels can be stacked together. .PP The implementation of the Tcl channel code was rewritten in 8.3.2 to correct some problems with the previous implementation with regard to stacked channels. Anyone using stacked channels or creating stacked channel drivers should update to the new \fBTCL_CHANNEL_VERSION_2\fR \fBTcl_ChannelType\fR structure. See \fBTcl_CreateChannel\fR for details. .PP \fBTcl_StackChannel\fR stacks a new \fIchannel\fR on an existing channel with the same name that was registered for \fIchannel\fR by \fBTcl_RegisterChannel\fR. .PP \fBTcl_StackChannel\fR works by creating a new channel structure and placing itself on top of the channel stack. EOL translation, encoding and buffering options are shared between all channels in the stack. The hidden channel does no buffering, newline translations, or character set encoding. Instead, the buffering, newline translations, and encoding functions all remain at the top of the channel stack. A pointer to the new top channel structure is returned. If an error occurs when stacking the channel, NULL is returned instead. .PP The \fImask\fR parameter specifies the operations that are allowed on the new channel. These can be a subset of the operations allowed on the original channel. For example, a read-write channel may become read-only after the \fBTcl_StackChannel\fR call. .PP Closing a channel closes the channels stacked below it. The close of stacked channels is executed in a way that allows buffered data to be properly flushed. .PP \fBTcl_UnstackChannel\fR reverses the process. The old channel is associated with the channel name, and the processing module added by \fBTcl_StackChannel\fR is destroyed. If there is no old channel, then \fBTcl_UnstackChannel\fR is equivalent to \fBTcl_Close\fR. If an error occurs unstacking the channel, \fBTCL_ERROR\fR is returned, otherwise \fBTCL_OK\fR is returned. .PP \fBTcl_GetTopChannel\fR returns the top channel in the stack of channels the supplied channel is part of. .PP \fBTcl_GetStackedChannel\fR returns the channel in the stack of channels which is just below the supplied channel. .SH "SEE ALSO" Notifier(3), Tcl_CreateChannel(3), Tcl_OpenFileChannel(3), vwait(n). .SH KEYWORDS channel, compression tcl8.6.5/doc/array.n0000644000175000017500000001700312663660065013632 0ustar sergeisergei'\" '\" Copyright (c) 1993-1994 The Regents of the University of California. '\" Copyright (c) 1994-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 array n 8.3 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME array \- Manipulate array variables .SH SYNOPSIS \fBarray \fIoption arrayName\fR ?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP This command performs one of several operations on the variable given by \fIarrayName\fR. Unless otherwise specified for individual commands below, \fIarrayName\fR must be the name of an existing array variable. The \fIoption\fR argument determines what action is carried out by the command. The legal \fIoptions\fR (which may be abbreviated) are: .TP \fBarray anymore \fIarrayName searchId\fR Returns 1 if there are any more elements left to be processed in an array search, 0 if all elements have already been returned. \fISearchId\fR indicates which search on \fIarrayName\fR to check, and must have been the return value from a previous invocation of \fBarray startsearch\fR. This option is particularly useful if an array has an element with an empty name, since the return value from \fBarray nextelement\fR will not indicate whether the search has been completed. .TP \fBarray donesearch \fIarrayName searchId\fR This command terminates an array search and destroys all the state associated with that search. \fISearchId\fR indicates which search on \fIarrayName\fR to destroy, and must have been the return value from a previous invocation of \fBarray startsearch\fR. Returns an empty string. .TP \fBarray exists \fIarrayName\fR Returns 1 if \fIarrayName\fR is an array variable, 0 if there is no variable by that name or if it is a scalar variable. .TP \fBarray get \fIarrayName\fR ?\fIpattern\fR? Returns a list containing pairs of elements. The first element in each pair is the name of an element in \fIarrayName\fR and the second element of each pair is the value of the array element. The order of the pairs is undefined. If \fIpattern\fR is not specified, then all of the elements of the array are included in the result. If \fIpattern\fR is specified, then only those elements whose names match \fIpattern\fR (using the matching rules of \fBstring match\fR) are included. If \fIarrayName\fR is not the name of an array variable, or if the array contains no elements, then an empty list is returned. If traces on the array modify the list of elements, the elements returned are those that exist both before and after the call to \fBarray get\fR. .TP \fBarray names \fIarrayName\fR ?\fImode\fR? ?\fIpattern\fR? Returns a list containing the names of all of the elements in the array that match \fIpattern\fR. \fIMode\fR may be one of \fB\-exact\fR, \fB\-glob\fR, or \fB\-regexp\fR. If specified, \fImode\fR designates which matching rules to use to match \fIpattern\fR against the names of the elements in the array. If not specified, \fImode\fR defaults to \fB\-glob\fR. See the documentation for \fBstring match\fR for information on glob style matching, and the documentation for \fBregexp\fR for information on regexp matching. If \fIpattern\fR is omitted then the command returns all of the element names in the array. If there are no (matching) elements in the array, or if \fIarrayName\fR is not the name of an array variable, then an empty string is returned. .TP \fBarray nextelement \fIarrayName searchId\fR Returns the name of the next element in \fIarrayName\fR, or an empty string if all elements of \fIarrayName\fR have already been returned in this search. The \fIsearchId\fR argument identifies the search, and must have been the return value of an \fBarray startsearch\fR command. Warning: if elements are added to or deleted from the array, then all searches are automatically terminated just as if \fBarray donesearch\fR had been invoked; this will cause \fBarray nextelement\fR operations to fail for those searches. .TP \fBarray set \fIarrayName list\fR Sets the values of one or more elements in \fIarrayName\fR. \fIlist\fR must have a form like that returned by \fBarray get\fR, consisting of an even number of elements. Each odd-numbered element in \fIlist\fR is treated as an element name within \fIarrayName\fR, and the following element in \fIlist\fR is used as a new value for that array element. If the variable \fIarrayName\fR does not already exist and \fIlist\fR is empty, \fIarrayName\fR is created with an empty array value. .TP \fBarray size \fIarrayName\fR Returns a decimal string giving the number of elements in the array. If \fIarrayName\fR is not the name of an array then 0 is returned. .TP \fBarray startsearch \fIarrayName\fR This command initializes an element-by-element search through the array given by \fIarrayName\fR, such that invocations of the \fBarray nextelement\fR command will return the names of the individual elements in the array. When the search has been completed, the \fBarray donesearch\fR command should be invoked. The return value is a search identifier that must be used in \fBarray nextelement\fR and \fBarray donesearch\fR commands; it allows multiple searches to be underway simultaneously for the same array. It is currently more efficient and easier to use either the \fBarray get\fR or \fBarray names\fR, together with \fBforeach\fR, to iterate over all but very large arrays. See the examples below for how to do this. .TP \fBarray statistics \fIarrayName\fR Returns statistics about the distribution of data within the hashtable that represents the array. This information includes the number of entries in the table, the number of buckets, and the utilization of the buckets. .TP \fBarray unset \fIarrayName\fR ?\fIpattern\fR? Unsets all of the elements in the array that match \fIpattern\fR (using the matching rules of \fBstring match\fR). If \fIarrayName\fR is not the name of an array variable or there are no matching elements in the array, no error will be raised. If \fIpattern\fR is omitted and \fIarrayName\fR is an array variable, then the command unsets the entire array. The command always returns an empty string. .SH EXAMPLES .CS \fBarray set\fR colorcount { red 1 green 5 blue 4 white 9 } foreach {color count} [\fBarray get\fR colorcount] { puts "Color: $color Count: $count" } \fB\(->\fR Color: blue Count: 4 Color: white Count: 9 Color: green Count: 5 Color: red Count: 1 foreach color [\fBarray names\fR colorcount] { puts "Color: $color Count: $colorcount($color)" } \fB\(->\fR Color: blue Count: 4 Color: white Count: 9 Color: green Count: 5 Color: red Count: 1 foreach color [lsort [\fBarray names\fR colorcount]] { puts "Color: $color Count: $colorcount($color)" } \fB\(->\fR Color: blue Count: 4 Color: green Count: 5 Color: red Count: 1 Color: white Count: 9 \fBarray statistics\fR colorcount \fB\(->\fR 4 entries in table, 4 buckets number of buckets with 0 entries: 1 number of buckets with 1 entries: 2 number of buckets with 2 entries: 1 number of buckets with 3 entries: 0 number of buckets with 4 entries: 0 number of buckets with 5 entries: 0 number of buckets with 6 entries: 0 number of buckets with 7 entries: 0 number of buckets with 8 entries: 0 number of buckets with 9 entries: 0 number of buckets with 10 or more entries: 0 average search distance for entry: 1.2 .CE .SH "SEE ALSO" list(n), string(n), variable(n), trace(n), foreach(n) .SH KEYWORDS array, element names, search tcl8.6.5/doc/vwait.n0000644000175000017500000001557512663660065013662 0ustar sergeisergei'\" '\" 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 vwait n 8.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME vwait \- Process events until a variable is written .SH SYNOPSIS \fBvwait\fR \fIvarName\fR .BE .SH DESCRIPTION .PP This command enters the Tcl event loop to process events, blocking the application if no events are ready. It continues processing events until some event handler sets the value of the global variable \fIvarName\fR. Once \fIvarName\fR has been set, the \fBvwait\fR command will return as soon as the event handler that modified \fIvarName\fR completes. The \fIvarName\fR argument is always interpreted as a variable name with respect to the global namespace, but can refer to any namespace's variables if the fully-qualified name is given. .PP In some cases the \fBvwait\fR command may not return immediately after \fIvarName\fR is set. This happens if the event handler that sets \fIvarName\fR does not complete immediately. For example, if an event handler sets \fIvarName\fR and then itself calls \fBvwait\fR to wait for a different variable, then it may not return for a long time. During this time the top-level \fBvwait\fR is blocked waiting for the event handler to complete, so it cannot return either. (See the \fBNESTED VWAITS BY EXAMPLE\fR below.) .PP To be clear, \fImultiple \fBvwait\fI calls will nest and will not happen in parallel\fR. The outermost call to \fBvwait\fR will not return until all the inner ones do. It is recommended that code should never nest \fBvwait\fR calls (by avoiding putting them in event callbacks) but when that is not possible, care should be taken to add interlock variables to the code to prevent all reentrant calls to \fBvwait\fR that are not \fIstrictly\fR necessary. Be aware that the synchronous modes of operation of some Tcl packages (e.g.,\ \fBhttp\fR) use \fBvwait\fR internally; if using the event loop, it is best to use the asynchronous callback-based modes of operation of those packages where available. .SH EXAMPLES .PP Run the event-loop continually until some event calls \fBexit\fR. (You can use any variable not mentioned elsewhere, but the name \fIforever\fR reminds you at a glance of the intent.) .PP .CS \fBvwait\fR forever .CE .PP Wait five seconds for a connection to a server socket, otherwise close the socket and continue running the script: .PP .CS # Initialise the state after 5000 set state timeout set server [socket -server accept 12345] proc accept {args} { global state connectionInfo set state accepted set connectionInfo $args } # Wait for something to happen \fBvwait\fR state # Clean up events that could have happened close $server after cancel set state timeout # Do something based on how the vwait finished... switch $state { timeout { puts "no connection on port 12345" } accepted { puts "connection: $connectionInfo" puts [lindex $connectionInfo 0] "Hello there!" } } .CE .PP A command that will wait for some time delay by waiting for a namespace variable to be set. Includes an interlock to prevent nested waits. .PP .CS namespace eval example { variable v done proc wait {delay} { variable v if {$v ne "waiting"} { set v waiting after $delay [namespace code {set v done}] \fBvwait\fR [namespace which -variable v] } return $v } } .CE .PP When running inside a \fBcoroutine\fR, an alternative to using \fBvwait\fR is to \fByield\fR to an outer event loop and to get recommenced when the variable is set, or at an idle moment after that. .PP .CS coroutine task apply {{} { # simulate [after 1000] after 1000 [info coroutine] yield # schedule the setting of a global variable, as normal after 2000 {set var 1} # simulate [\fBvwait\fR var] proc updatedVar {task args} { after idle $task trace remove variable ::var write "updatedVar $task" } trace add variable ::var write "updatedVar [info coroutine]" yield }} .CE .SS "NESTED VWAITS BY EXAMPLE" .PP This example demonstrates what can happen when the \fBvwait\fR command is nested. The script will never finish because the waiting for the \fIa\fR variable never finishes; that \fBvwait\fR command is still waiting for a script scheduled with \fBafter\fR to complete, which just happens to be running an inner \fBvwait\fR (for \fIb\fR) even though the event that the outer \fBvwait\fR was waiting for (the setting of \fIa\fR) has occurred. .PP .CS after 500 { puts "waiting for b" \fBvwait\fR b puts "b was set" } after 1000 { puts "setting a" set a 10 } puts "waiting for a" \fBvwait\fR a puts "a was set" puts "setting b" set b 42 .CE .PP If you run the above code, you get this output: .PP .CS waiting for a waiting for b setting a .CE .PP The script will never print .QW "a was set" until after it has printed .QW "b was set" because of the nesting of \fBvwait\fR commands, and yet \fIb\fR will not be set until after the outer \fBvwait\fR returns, so the script has deadlocked. The only ways to avoid this are to either structure the overall program in continuation-passing style or to use \fBcoroutine\fR to make the continuations implicit. The first of these options would be written as: .PP .CS after 500 { puts "waiting for b" trace add variable b write {apply {args { global a b trace remove variable ::b write \e [lrange [info level 0] 0 1] puts "b was set" set ::done ok }}} } after 1000 { puts "setting a" set a 10 } puts "waiting for a" trace add variable a write {apply {args { global a b trace remove variable a write [lrange [info level 0] 0 1] puts "a was set" puts "setting b" set b 42 }}} \fBvwait\fR done .CE .PP The second option, with \fBcoroutine\fR and some helper procedures, is done like this: .PP .CS # A coroutine-based wait-for-variable command proc waitvar globalVar { trace add variable ::$globalVar write \e [list apply {{v c args} { trace remove variable $v write \e [lrange [info level 0] 0 3] after 0 $c }} ::$globalVar [info coroutine]] yield } # A coroutine-based wait-for-some-time command proc waittime ms { after $ms [info coroutine] yield } coroutine task-1 eval { puts "waiting for a" waitvar a puts "a was set" puts "setting b" set b 42 } coroutine task-2 eval { waittime 500 puts "waiting for b" waitvar b puts "b was set" set done ok } coroutine task-3 eval { waittime 1000 puts "setting a" set a 10 } \fBvwait\fR done .CE .SH "SEE ALSO" global(n), update(n) .SH KEYWORDS asynchronous I/O, event, variable, wait '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/pid.n0000644000175000017500000000276612663660065013302 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 pid n 7.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME pid \- Retrieve process identifiers .SH SYNOPSIS \fBpid \fR?\fIfileId\fR? .BE .SH DESCRIPTION .PP If the \fIfileId\fR argument is given then it should normally refer to a process pipeline created with the \fBopen\fR command. In this case the \fBpid\fR command will return a list whose elements are the process identifiers of all the processes in the pipeline, in order. The list will be empty if \fIfileId\fR refers to an open file that is not a process pipeline. If no \fIfileId\fR argument is given then \fBpid\fR returns the process identifier of the current process. All process identifiers are returned as decimal strings. .SH EXAMPLE Print process information about the processes in a pipeline using the SysV \fBps\fR program before reading the output of that pipeline: .PP .CS set pipeline [open "| zcat somefile.gz | grep foobar | sort -u"] # Print process information exec ps -fp [\fBpid\fR $pipeline] >@stdout # Print a separator and then the output of the pipeline puts [string repeat - 70] puts [read $pipeline] close $pipeline .CE .SH "SEE ALSO" exec(n), open(n) .SH KEYWORDS file, pipeline, process identifier tcl8.6.5/doc/RegExp.30000644000175000017500000003561412663660065013623 0ustar sergeisergei'\" '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 1998-1999 Scriptics Corporation '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_RegExpMatch 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_RegExpMatch, Tcl_RegExpCompile, Tcl_RegExpExec, Tcl_RegExpRange, Tcl_GetRegExpFromObj, Tcl_RegExpMatchObj, Tcl_RegExpExecObj, Tcl_RegExpGetInfo \- Pattern matching with regular expressions .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_RegExpMatchObj\fR(\fIinterp\fR, \fItextObj\fR, \fIpatObj\fR) .sp int \fBTcl_RegExpMatch\fR(\fIinterp\fR, \fItext\fR, \fIpattern\fR) .sp Tcl_RegExp \fBTcl_RegExpCompile\fR(\fIinterp\fR, \fIpattern\fR) .sp int \fBTcl_RegExpExec\fR(\fIinterp\fR, \fIregexp\fR, \fItext\fR, \fIstart\fR) .sp void \fBTcl_RegExpRange\fR(\fIregexp\fR, \fIindex\fR, \fIstartPtr\fR, \fIendPtr\fR) .sp Tcl_RegExp \fBTcl_GetRegExpFromObj\fR(\fIinterp\fR, \fIpatObj\fR, \fIcflags\fR) .sp int \fBTcl_RegExpExecObj\fR(\fIinterp\fR, \fIregexp\fR, \fItextObj\fR, \fIoffset\fR, \fInmatches\fR, \fIeflags\fR) .sp void \fBTcl_RegExpGetInfo\fR(\fIregexp\fR, \fIinfoPtr\fR) .fi .SH ARGUMENTS .AS Tcl_RegExpInfo *interp in/out .AP Tcl_Interp *interp in Tcl interpreter to use for error reporting. The interpreter may be NULL if no error reporting is desired. .AP Tcl_Obj *textObj in/out Refers to the value from which to get the text to search. The internal representation of the value may be converted to a form that can be efficiently searched. .AP Tcl_Obj *patObj in/out Refers to the value from which to get a regular expression. The compiled regular expression is cached in the value. .AP char *text in Text to search for a match with a regular expression. .AP "const char" *pattern in String in the form of a regular expression pattern. .AP Tcl_RegExp regexp in Compiled regular expression. Must have been returned previously by \fBTcl_GetRegExpFromObj\fR or \fBTcl_RegExpCompile\fR. .AP char *start in If \fItext\fR is just a portion of some other string, this argument identifies the beginning of the larger string. If it is not the same as \fItext\fR, then no .QW \fB^\fR matches will be allowed. .AP int index in Specifies which range is desired: 0 means the range of the entire match, 1 or greater means the range that matched a parenthesized sub-expression. .AP "const char" **startPtr out The address of the first character in the range is stored here, or NULL if there is no such range. .AP "const char" **endPtr out The address of the character just after the last one in the range is stored here, or NULL if there is no such range. .AP int cflags in OR-ed combination of the compilation flags \fBTCL_REG_ADVANCED\fR, \fBTCL_REG_EXTENDED\fR, \fBTCL_REG_BASIC\fR, \fBTCL_REG_EXPANDED\fR, \fBTCL_REG_QUOTE\fR, \fBTCL_REG_NOCASE\fR, \fBTCL_REG_NEWLINE\fR, \fBTCL_REG_NLSTOP\fR, \fBTCL_REG_NLANCH\fR, \fBTCL_REG_NOSUB\fR, and \fBTCL_REG_CANMATCH\fR. See below for more information. .AP int offset in The character offset into the text where matching should begin. The value of the offset has no impact on \fB^\fR matches. This behavior is controlled by \fIeflags\fR. .AP int nmatches in The number of matching subexpressions that should be remembered for later use. If this value is 0, then no subexpression match information will be computed. If the value is \-1, then all of the matching subexpressions will be remembered. Any other value will be taken as the maximum number of subexpressions to remember. .AP int eflags in OR-ed combination of the execution flags \fBTCL_REG_NOTBOL\fR and \fBTCL_REG_NOTEOL\fR. See below for more information. .AP Tcl_RegExpInfo *infoPtr out The address of the location where information about a previous match should be stored by \fBTcl_RegExpGetInfo\fR. .BE .SH DESCRIPTION .PP \fBTcl_RegExpMatch\fR determines whether its \fIpattern\fR argument matches \fIregexp\fR, where \fIregexp\fR is interpreted as a regular expression using the rules in the \fBre_syntax\fR reference page. If there is a match then \fBTcl_RegExpMatch\fR returns 1. If there is no match then \fBTcl_RegExpMatch\fR returns 0. If an error occurs in the matching process (e.g. \fIpattern\fR is not a valid regular expression) then \fBTcl_RegExpMatch\fR returns \-1 and leaves an error message in the interpreter result. \fBTcl_RegExpMatchObj\fR is similar to \fBTcl_RegExpMatch\fR except it operates on the Tcl values \fItextObj\fR and \fIpatObj\fR instead of UTF strings. \fBTcl_RegExpMatchObj\fR is generally more efficient than \fBTcl_RegExpMatch\fR, so it is the preferred interface. .PP \fBTcl_RegExpCompile\fR, \fBTcl_RegExpExec\fR, and \fBTcl_RegExpRange\fR provide lower-level access to the regular expression pattern matcher. \fBTcl_RegExpCompile\fR compiles a regular expression string into the internal form used for efficient pattern matching. The return value is a token for this compiled form, which can be used in subsequent calls to \fBTcl_RegExpExec\fR or \fBTcl_RegExpRange\fR. If an error occurs while compiling the regular expression then \fBTcl_RegExpCompile\fR returns NULL and leaves an error message in the interpreter result. Note: the return value from \fBTcl_RegExpCompile\fR is only valid up to the next call to \fBTcl_RegExpCompile\fR; it is not safe to retain these values for long periods of time. .PP \fBTcl_RegExpExec\fR executes the regular expression pattern matcher. It returns 1 if \fItext\fR contains a range of characters that match \fIregexp\fR, 0 if no match is found, and \-1 if an error occurs. In the case of an error, \fBTcl_RegExpExec\fR leaves an error message in the interpreter result. When searching a string for multiple matches of a pattern, it is important to distinguish between the start of the original string and the start of the current search. For example, when searching for the second occurrence of a match, the \fItext\fR argument might point to the character just after the first match; however, it is important for the pattern matcher to know that this is not the start of the entire string, so that it does not allow .QW \fB^\fR atoms in the pattern to match. The \fIstart\fR argument provides this information by pointing to the start of the overall string containing \fItext\fR. \fIStart\fR will be less than or equal to \fItext\fR; if it is less than \fItext\fR then no \fB^\fR matches will be allowed. .PP \fBTcl_RegExpRange\fR may be invoked after \fBTcl_RegExpExec\fR returns; it provides detailed information about what ranges of the string matched what parts of the pattern. \fBTcl_RegExpRange\fR returns a pair of pointers in \fI*startPtr\fR and \fI*endPtr\fR that identify a range of characters in the source string for the most recent call to \fBTcl_RegExpExec\fR. \fIIndex\fR indicates which of several ranges is desired: if \fIindex\fR is 0, information is returned about the overall range of characters that matched the entire pattern; otherwise, information is returned about the range of characters that matched the \fIindex\fR'th parenthesized subexpression within the pattern. If there is no range corresponding to \fIindex\fR then NULL is stored in \fI*startPtr\fR and \fI*endPtr\fR. .PP \fBTcl_GetRegExpFromObj\fR, \fBTcl_RegExpExecObj\fR, and \fBTcl_RegExpGetInfo\fR are value interfaces that provide the most direct control of Henry Spencer's regular expression library. For users that need to modify compilation and execution options directly, it is recommended that you use these interfaces instead of calling the internal regexp functions. These interfaces handle the details of UTF to Unicode translations as well as providing improved performance through caching in the pattern and string values. .PP \fBTcl_GetRegExpFromObj\fR attempts to return a compiled regular expression from the \fIpatObj\fR. If the value does not already contain a compiled regular expression it will attempt to create one from the string in the value and assign it to the internal representation of the \fIpatObj\fR. The return value of this function is of type \fBTcl_RegExp\fR. The return value is a token for this compiled form, which can be used in subsequent calls to \fBTcl_RegExpExecObj\fR or \fBTcl_RegExpGetInfo\fR. If an error occurs while compiling the regular expression then \fBTcl_GetRegExpFromObj\fR returns NULL and leaves an error message in the interpreter result. The regular expression token can be used as long as the internal representation of \fIpatObj\fR refers to the compiled form. The \fIcflags\fR argument is a bit-wise OR of zero or more of the following flags that control the compilation of \fIpatObj\fR: .RS 2 .TP \fBTCL_REG_ADVANCED\fR Compile advanced regular expressions .PQ ARE s . This mode corresponds to the normal regular expression syntax accepted by the Tcl \fBregexp\fR and \fBregsub\fR commands. .TP \fBTCL_REG_EXTENDED\fR Compile extended regular expressions .PQ ERE s . This mode corresponds to the regular expression syntax recognized by Tcl 8.0 and earlier versions. .TP \fBTCL_REG_BASIC\fR Compile basic regular expressions .PQ BRE s . This mode corresponds to the regular expression syntax recognized by common Unix utilities like \fBsed\fR and \fBgrep\fR. This is the default if no flags are specified. .TP \fBTCL_REG_EXPANDED\fR Compile the regular expression (basic, extended, or advanced) using an expanded syntax that allows comments and whitespace. This mode causes non-backslashed non-bracket-expression white space and #-to-end-of-line comments to be ignored. .TP \fBTCL_REG_QUOTE\fR Compile a literal string, with all characters treated as ordinary characters. .TP \fBTCL_REG_NOCASE\fR Compile for matching that ignores upper/lower case distinctions. .TP \fBTCL_REG_NEWLINE\fR Compile for newline-sensitive matching. By default, newline is a completely ordinary character with no special meaning in either regular expressions or strings. With this flag, .QW [^ bracket expressions and .QW . never match newline, .QW ^ matches an empty string after any newline in addition to its normal function, and .QW $ matches an empty string before any newline in addition to its normal function. \fBREG_NEWLINE\fR is the bit-wise OR of \fBREG_NLSTOP\fR and \fBREG_NLANCH\fR. .TP \fBTCL_REG_NLSTOP\fR Compile for partial newline-sensitive matching, with the behavior of .QW [^ bracket expressions and .QW . affected, but not the behavior of .QW ^ and .QW $ . In this mode, .QW [^ bracket expressions and .QW . never match newline. .TP \fBTCL_REG_NLANCH\fR Compile for inverse partial newline-sensitive matching, with the behavior of .QW ^ and .QW $ (the .QW anchors ) affected, but not the behavior of .QW [^ bracket expressions and .QW . . In this mode .QW ^ matches an empty string after any newline in addition to its normal function, and .QW $ matches an empty string before any newline in addition to its normal function. .TP \fBTCL_REG_NOSUB\fR Compile for matching that reports only success or failure, not what was matched. This reduces compile overhead and may improve performance. Subsequent calls to \fBTcl_RegExpGetInfo\fR or \fBTcl_RegExpRange\fR will not report any match information. .TP \fBTCL_REG_CANMATCH\fR Compile for matching that reports the potential to complete a partial match given more text (see below). .RE .PP Only one of \fBTCL_REG_EXTENDED\fR, \fBTCL_REG_ADVANCED\fR, \fBTCL_REG_BASIC\fR, and \fBTCL_REG_QUOTE\fR may be specified. .PP \fBTcl_RegExpExecObj\fR executes the regular expression pattern matcher. It returns 1 if \fIobjPtr\fR contains a range of characters that match \fIregexp\fR, 0 if no match is found, and \-1 if an error occurs. In the case of an error, \fBTcl_RegExpExecObj\fR leaves an error message in the interpreter result. The \fInmatches\fR value indicates to the matcher how many subexpressions are of interest. If \fInmatches\fR is 0, then no subexpression match information is recorded, which may allow the matcher to make various optimizations. If the value is \-1, then all of the subexpressions in the pattern are remembered. If the value is a positive integer, then only that number of subexpressions will be remembered. Matching begins at the specified Unicode character index given by \fIoffset\fR. Unlike \fBTcl_RegExpExec\fR, the behavior of anchors is not affected by the offset value. Instead the behavior of the anchors is explicitly controlled by the \fIeflags\fR argument, which is a bit-wise OR of zero or more of the following flags: .RS 2 .TP \fBTCL_REG_NOTBOL\fR The starting character will not be treated as the beginning of a line or the beginning of the string, so .QW ^ will not match there. Note that this flag has no effect on how .QW \fB\eA\fR matches. .TP \fBTCL_REG_NOTEOL\fR The last character in the string will not be treated as the end of a line or the end of the string, so .QW $ will not match there. Note that this flag has no effect on how .QW \fB\eZ\fR matches. .RE .PP \fBTcl_RegExpGetInfo\fR retrieves information about the last match performed with a given regular expression \fIregexp\fR. The \fIinfoPtr\fR argument contains a pointer to a structure that is defined as follows: .PP .CS typedef struct Tcl_RegExpInfo { int \fInsubs\fR; Tcl_RegExpIndices *\fImatches\fR; long \fIextendStart\fR; } \fBTcl_RegExpInfo\fR; .CE .PP The \fInsubs\fR field contains a count of the number of parenthesized subexpressions within the regular expression. If the \fBTCL_REG_NOSUB\fR was used, then this value will be zero. The \fImatches\fR field points to an array of \fInsubs\fR+1 values that indicate the bounds of each subexpression matched. The first element in the array refers to the range matched by the entire regular expression, and subsequent elements refer to the parenthesized subexpressions in the order that they appear in the pattern. Each element is a structure that is defined as follows: .PP .CS typedef struct Tcl_RegExpIndices { long \fIstart\fR; long \fIend\fR; } \fBTcl_RegExpIndices\fR; .CE .PP The \fIstart\fR and \fIend\fR values are Unicode character indices relative to the offset location within \fIobjPtr\fR where matching began. The \fIstart\fR index identifies the first character of the matched subexpression. The \fIend\fR index identifies the first character after the matched subexpression. If the subexpression matched the empty string, then \fIstart\fR and \fIend\fR will be equal. If the subexpression did not participate in the match, then \fIstart\fR and \fIend\fR will be set to \-1. .PP The \fIextendStart\fR field in \fBTcl_RegExpInfo\fR is only set if the \fBTCL_REG_CANMATCH\fR flag was used. It indicates the first character in the string where a match could occur. If a match was found, this will be the same as the beginning of the current match. If no match was found, then it indicates the earliest point at which a match might occur if additional text is appended to the string. If it is no match is possible even with further text, this field will be set to \-1. .SH "SEE ALSO" re_syntax(n) .SH KEYWORDS match, pattern, regular expression, string, subexpression, Tcl_RegExpIndices, Tcl_RegExpInfo tcl8.6.5/doc/IntObj.30000644000175000017500000001433312663660065013611 0ustar sergeisergei'\" '\" Copyright (c) 1996-1997 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_IntObj 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_GetIntFromObj, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * \fBTcl_NewIntObj\fR(\fIintValue\fR) .sp Tcl_Obj * \fBTcl_NewLongObj\fR(\fIlongValue\fR) .sp Tcl_Obj * \fBTcl_NewWideIntObj\fR(\fIwideValue\fR) .sp \fBTcl_SetIntObj\fR(\fIobjPtr, intValue\fR) .sp \fBTcl_SetLongObj\fR(\fIobjPtr, longValue\fR) .sp \fBTcl_SetWideIntObj\fR(\fIobjPtr, wideValue\fR) .sp int \fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR) .sp int \fBTcl_GetLongFromObj\fR(\fIinterp, objPtr, longPtr\fR) .sp int \fBTcl_GetWideIntFromObj\fR(\fIinterp, objPtr, widePtr\fR) .sp .sp \fB#include \fR .sp Tcl_Obj * \fBTcl_NewBignumObj\fR(\fIbigValue\fR) .sp \fBTcl_SetBignumObj\fR(\fIobjPtr, bigValue\fR) .sp int \fBTcl_GetBignumFromObj\fR(\fIinterp, objPtr, bigValue\fR) .sp int \fBTcl_TakeBignumFromObj\fR(\fIinterp, objPtr, bigValue\fR) .sp int \fBTcl_InitBignumFromDouble\fR(\fIinterp, doubleValue, bigValue\fR) .SH ARGUMENTS .AS Tcl_WideInt doubleValue in/out .AP int intValue in Integer value used to initialize or set a Tcl value. .AP long longValue in Long integer value used to initialize or set a Tcl value. .AP Tcl_WideInt wideValue in Wide integer value used to initialize or set a Tcl value. .AP Tcl_Obj *objPtr in/out For \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR, and \fBTcl_SetBignumObj\fR, this points to the value in which to store an integral value. For \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR, \fBTcl_GetWideIntFromObj\fR, \fBTcl_GetBignumFromObj\fR, and \fBTcl_TakeBignumFromObj\fR, this refers to the value from which to retrieve an integral value. .AP Tcl_Interp *interp in/out When non-NULL, an error message is left here when integral value retrieval fails. .AP int *intPtr out Points to place to store the integer value retrieved from \fIobjPtr\fR. .AP long *longPtr out Points to place to store the long integer value retrieved from \fIobjPtr\fR. .AP Tcl_WideInt *widePtr out Points to place to store the wide integer value retrieved from \fIobjPtr\fR. .AP mp_int *bigValue in/out Points to a multi-precision integer structure declared by the LibTomMath library. .AP double doubleValue in Double value from which the integer part is determined and used to initialize a multi-precision integer value. .BE .SH DESCRIPTION .PP These procedures are used to create, modify, and read Tcl values that hold integral values. .PP The different routines exist to accommodate different integral types in C with which values might be exchanged. The C integral types for which Tcl provides value exchange routines are \fBint\fR, \fBlong int\fR, \fBTcl_WideInt\fR, and \fBmp_int\fR. The \fBint\fR and \fBlong int\fR types are provided by the C language standard. The \fBTcl_WideInt\fR type is a typedef defined to be whatever signed integral type covers at least the 64-bit integer range (-9223372036854775808 to 9223372036854775807). Depending on the platform and the C compiler, the actual type might be \fBlong int\fR, \fBlong long int\fR, \fBint64\fR, or something else. The \fBmp_int\fR type is a multiple-precision integer type defined by the LibTomMath multiple-precision integer library. .PP The \fBTcl_NewIntObj\fR, \fBTcl_NewLongObj\fR, \fBTcl_NewWideIntObj\fR, and \fBTcl_NewBignumObj\fR routines each create and return a new Tcl value initialized to the integral value of the argument. The returned Tcl value is unshared. .PP The \fBTcl_SetIntObj\fR, \fBTcl_SetLongObj\fR, \fBTcl_SetWideIntObj\fR, and \fBTcl_SetBignumObj\fR routines each set the value of an existing Tcl value pointed to by \fIobjPtr\fR to the integral value provided by the other argument. The \fIobjPtr\fR argument must point to an unshared Tcl value. Any attempt to set the value of a shared Tcl value violates Tcl's copy-on-write policy. Any existing string representation or internal representation in the unshared Tcl value will be freed as a consequence of setting the new value. .PP The \fBTcl_GetIntFromObj\fR, \fBTcl_GetLongFromObj\fR, \fBTcl_GetWideIntFromObj\fR, \fBTcl_GetBignumFromObj\fR, and \fBTcl_TakeBignumFromObj\fR routines attempt to retrieve an integral value of the appropriate type from the Tcl value \fIobjPtr\fR. If the attempt succeeds, then \fBTCL_OK\fR is returned, and the value is written to the storage provided by the caller. The attempt might fail if \fIobjPtr\fR does not hold an integral value, or if the value exceeds the range of the target type. If the attempt fails, then \fBTCL_ERROR\fR is returned, and if \fIinterp\fR is non-NULL, an error message is left in \fIinterp\fR. The \fBTcl_ObjType\fR of \fIobjPtr\fR may be changed to make subsequent calls to the same routine more efficient. Unlike the other functions, \fBTcl_TakeBignumFromObj\fR may set the content of the Tcl value \fIobjPtr\fR to an empty string in the process of retrieving the multiple-precision integer value. .PP The choice between \fBTcl_GetBignumFromObj\fR and \fBTcl_TakeBignumFromObj\fR is governed by how the caller will continue to use \fIobjPtr\fR. If after the \fBmp_int\fR value is retrieved from \fIobjPtr\fR, the caller will make no more use of \fIobjPtr\fR, then using \fBTcl_TakeBignumFromObj\fR permits Tcl to detect when an unshared \fIobjPtr\fR permits the value to be moved instead of copied, which should be more efficient. If anything later in the caller requires \fIobjPtr\fR to continue to hold the same value, then \fBTcl_GetBignumFromObj\fR must be chosen. .PP The \fBTcl_InitBignumFromDouble\fR routine is a utility procedure that extracts the integer part of \fIdoubleValue\fR and stores that integer value in the \fBmp_int\fR value \fIbigValue\fR. .SH "SEE ALSO" Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult .SH KEYWORDS integer, integer value, integer type, internal representation, value, value type, string representation tcl8.6.5/doc/StringObj.30000644000175000017500000004104312663660065014323 0ustar sergeisergei'\" '\" Copyright (c) 1994-1997 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_StringObj 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_NewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicodeFromObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendObjToObj, Tcl_AppendStringsToObj, Tcl_AppendStringsToObjVA, Tcl_AppendLimitedToObj, Tcl_Format, Tcl_AppendFormatToObj, Tcl_ObjPrintf, Tcl_AppendPrintfToObj, Tcl_SetObjLength, Tcl_AttemptSetObjLength, Tcl_ConcatObj \- manipulate Tcl values as strings .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * \fBTcl_NewStringObj\fR(\fIbytes, length\fR) .sp Tcl_Obj * \fBTcl_NewUnicodeObj\fR(\fIunicode, numChars\fR) .sp void \fBTcl_SetStringObj\fR(\fIobjPtr, bytes, length\fR) .sp void \fBTcl_SetUnicodeObj\fR(\fIobjPtr, unicode, numChars\fR) .sp char * \fBTcl_GetStringFromObj\fR(\fIobjPtr, lengthPtr\fR) .sp char * \fBTcl_GetString\fR(\fIobjPtr\fR) .sp Tcl_UniChar * \fBTcl_GetUnicodeFromObj\fR(\fIobjPtr, lengthPtr\fR) .sp Tcl_UniChar * \fBTcl_GetUnicode\fR(\fIobjPtr\fR) .sp Tcl_UniChar \fBTcl_GetUniChar\fR(\fIobjPtr, index\fR) .sp int \fBTcl_GetCharLength\fR(\fIobjPtr\fR) .sp Tcl_Obj * \fBTcl_GetRange\fR(\fIobjPtr, first, last\fR) .sp void \fBTcl_AppendToObj\fR(\fIobjPtr, bytes, length\fR) .sp void \fBTcl_AppendUnicodeToObj\fR(\fIobjPtr, unicode, numChars\fR) .sp void \fBTcl_AppendObjToObj\fR(\fIobjPtr, appendObjPtr\fR) .sp void \fBTcl_AppendStringsToObj\fR(\fIobjPtr, string, string, ... \fB(char *) NULL\fR) .sp void \fBTcl_AppendStringsToObjVA\fR(\fIobjPtr, argList\fR) .sp void \fBTcl_AppendLimitedToObj\fR(\fIobjPtr, bytes, length, limit, ellipsis\fR) .sp Tcl_Obj * \fBTcl_Format\fR(\fIinterp, format, objc, objv\fR) .sp int \fBTcl_AppendFormatToObj\fR(\fIinterp, objPtr, format, objc, objv\fR) .sp Tcl_Obj * \fBTcl_ObjPrintf\fR(\fIformat, ...\fR) .sp void \fBTcl_AppendPrintfToObj\fR(\fIobjPtr, format, ...\fR) .sp void \fBTcl_SetObjLength\fR(\fIobjPtr, newLength\fR) .sp int \fBTcl_AttemptSetObjLength\fR(\fIobjPtr, newLength\fR) .sp Tcl_Obj * \fBTcl_ConcatObj\fR(\fIobjc, objv\fR) .SH ARGUMENTS .AS "const Tcl_UniChar" *appendObjPtr in/out .AP "const char" *bytes in Points to the first byte of an array of UTF-8-encoded bytes used to set or append to a string value. This byte array may contain embedded null characters unless \fInumChars\fR is negative. (Applications needing null bytes should represent them as the two-byte sequence \fI\e700\e600\fR, use \fBTcl_ExternalToUtf\fR to convert, or \fBTcl_NewByteArrayObj\fR if the string is a collection of uninterpreted bytes.) .AP int length in The number of bytes to copy from \fIbytes\fR when initializing, setting, or appending to a string value. If negative, all bytes up to the first null are used. .AP "const Tcl_UniChar" *unicode in Points to the first byte of an array of Unicode characters used to set or append to a string value. This byte array may contain embedded null characters unless \fInumChars\fR is negative. .AP int numChars in The number of Unicode characters to copy from \fIunicode\fR when initializing, setting, or appending to a string value. If negative, all characters up to the first null character are used. .AP int index in The index of the Unicode character to return. .AP int first in The index of the first Unicode character in the Unicode range to be returned as a new value. .AP int last in The index of the last Unicode character in the Unicode range to be returned as a new value. .AP Tcl_Obj *objPtr in/out Points to a value to manipulate. .AP Tcl_Obj *appendObjPtr in The value to append to \fIobjPtr\fR in \fBTcl_AppendObjToObj\fR. .AP int *lengthPtr out If non-NULL, the location where \fBTcl_GetStringFromObj\fR will store the length of a value's string representation. .AP "const char" *string in Null-terminated string value to append to \fIobjPtr\fR. .AP va_list argList in An argument list which must have been initialized using \fBva_start\fR, and cleared using \fBva_end\fR. .AP int limit in Maximum number of bytes to be appended. .AP "const char" *ellipsis in Suffix to append when the limit leads to string truncation. If NULL is passed then the suffix .QW "..." is used. .AP "const char" *format in Format control string including % conversion specifiers. .AP int objc in The number of elements to format or concatenate. .AP Tcl_Obj *objv[] in The array of values to format or concatenate. .AP int newLength in New length for the string value of \fIobjPtr\fR, not including the final null character. .BE .SH DESCRIPTION .PP The procedures described in this manual entry allow Tcl values to be manipulated as string values. They use the internal representation of the value to store additional information to make the string manipulations more efficient. In particular, they make a series of append operations efficient by allocating extra storage space for the string so that it does not have to be copied for each append. Also, indexing and length computations are optimized because the Unicode string representation is calculated and cached as needed. When using the \fBTcl_Append*\fR family of functions where the interpreter's result is the value being appended to, it is important to call Tcl_ResetResult first to ensure you are not unintentionally appending to existing data in the result value. .PP \fBTcl_NewStringObj\fR and \fBTcl_SetStringObj\fR create a new value or modify an existing value to hold a copy of the string given by \fIbytes\fR and \fIlength\fR. \fBTcl_NewUnicodeObj\fR and \fBTcl_SetUnicodeObj\fR create a new value or modify an existing value to hold a copy of the Unicode string given by \fIunicode\fR and \fInumChars\fR. \fBTcl_NewStringObj\fR and \fBTcl_NewUnicodeObj\fR return a pointer to a newly created value with reference count zero. All four procedures set the value to hold a copy of the specified string. \fBTcl_SetStringObj\fR and \fBTcl_SetUnicodeObj\fR free any old string representation as well as any old internal representation of the value. .PP \fBTcl_GetStringFromObj\fR and \fBTcl_GetString\fR return a value's string representation. This is given by the returned byte pointer and (for \fBTcl_GetStringFromObj\fR) length, which is stored in \fIlengthPtr\fR if it is non-NULL. If the value's UTF string representation is invalid (its byte pointer is NULL), the string representation is regenerated from the value's internal representation. The storage referenced by the returned byte pointer is owned by the value manager. It is passed back as a writable pointer so that extension author creating their own \fBTcl_ObjType\fR will be able to modify the string representation within the \fBTcl_UpdateStringProc\fR of their \fBTcl_ObjType\fR. Except for that limited purpose, the pointer returned by \fBTcl_GetStringFromObj\fR or \fBTcl_GetString\fR should be treated as read-only. It is recommended that this pointer be assigned to a (const char *) variable. Even in the limited situations where writing to this pointer is acceptable, one should take care to respect the copy-on-write semantics required by \fBTcl_Obj\fR's, with appropriate calls to \fBTcl_IsShared\fR and \fBTcl_DuplicateObj\fR prior to any in-place modification of the string representation. The procedure \fBTcl_GetString\fR is used in the common case where the caller does not need the length of the string representation. .PP \fBTcl_GetUnicodeFromObj\fR and \fBTcl_GetUnicode\fR return a value's value as a Unicode string. This is given by the returned pointer and (for \fBTcl_GetUnicodeFromObj\fR) length, which is stored in \fIlengthPtr\fR if it is non-NULL. The storage referenced by the returned byte pointer is owned by the value manager and should not be modified by the caller. The procedure \fBTcl_GetUnicode\fR is used in the common case where the caller does not need the length of the unicode string representation. .PP \fBTcl_GetUniChar\fR returns the \fIindex\fR'th character in the value's Unicode representation. .PP \fBTcl_GetRange\fR returns a newly created value comprised of the characters between \fIfirst\fR and \fIlast\fR (inclusive) in the value's Unicode representation. If the value's Unicode representation is invalid, the Unicode representation is regenerated from the value's string representation. .PP \fBTcl_GetCharLength\fR returns the number of characters (as opposed to bytes) in the string value. .PP \fBTcl_AppendToObj\fR appends the data given by \fIbytes\fR and \fIlength\fR to the string representation of the value specified by \fIobjPtr\fR. If the value has an invalid string representation, then an attempt is made to convert \fIbytes\fR is to the Unicode format. If the conversion is successful, then the converted form of \fIbytes\fR is appended to the value's Unicode representation. Otherwise, the value's Unicode representation is invalidated and converted to the UTF format, and \fIbytes\fR is appended to the value's new string representation. .PP \fBTcl_AppendUnicodeToObj\fR appends the Unicode string given by \fIunicode\fR and \fInumChars\fR to the value specified by \fIobjPtr\fR. If the value has an invalid Unicode representation, then \fIunicode\fR is converted to the UTF format and appended to the value's string representation. Appends are optimized to handle repeated appends relatively efficiently (it over-allocates the string or Unicode space to avoid repeated reallocations and copies of value's string value). .PP \fBTcl_AppendObjToObj\fR is similar to \fBTcl_AppendToObj\fR, but it appends the string or Unicode value (whichever exists and is best suited to be appended to \fIobjPtr\fR) of \fIappendObjPtr\fR to \fIobjPtr\fR. .PP \fBTcl_AppendStringsToObj\fR is similar to \fBTcl_AppendToObj\fR except that it can be passed more than one value to append and each value must be a null-terminated string (i.e. none of the values may contain internal null characters). Any number of \fIstring\fR arguments may be provided, but the last argument must be a NULL pointer to indicate the end of the list. .PP \fBTcl_AppendStringsToObjVA\fR is the same as \fBTcl_AppendStringsToObj\fR except that instead of taking a variable number of arguments it takes an argument list. .PP \fBTcl_AppendLimitedToObj\fR is similar to \fBTcl_AppendToObj\fR except that it imposes a limit on how many bytes are appended. This can be handy when the string to be appended might be very large, but the value being constructed should not be allowed to grow without bound. A common usage is when constructing an error message, where the end result should be kept short enough to be read. Bytes from \fIbytes\fR are appended to \fIobjPtr\fR, but no more than \fIlimit\fR bytes total are to be appended. If the limit prevents all \fIlength\fR bytes that are available from being appended, then the appending is done so that the last bytes appended are from the string \fIellipsis\fR. This allows for an indication of the truncation to be left in the string. When \fIlength\fR is \fB-1\fR, all bytes up to the first zero byte are appended, subject to the limit. When \fIellipsis\fR is NULL, the default string \fB...\fR is used. When \fIellipsis\fR is non-NULL, it must point to a zero-byte-terminated string in Tcl's internal UTF encoding. The number of bytes appended can be less than the lesser of \fIlength\fR and \fIlimit\fR when appending fewer bytes is necessary to append only whole multi-byte characters. .PP \fBTcl_Format\fR is the C-level interface to the engine of the \fBformat\fR command. The actual command procedure for \fBformat\fR is little more than .PP .CS \fBTcl_Format\fR(interp, \fBTcl_GetString\fR(objv[1]), objc-2, objv+2); .CE .PP The \fIobjc\fR Tcl_Obj values in \fIobjv\fR are formatted into a string according to the conversion specification in \fIformat\fR argument, following the documentation for the \fBformat\fR command. The resulting formatted string is converted to a new Tcl_Obj with refcount of zero and returned. If some error happens during production of the formatted string, NULL is returned, and an error message is recorded in \fIinterp\fR, if \fIinterp\fR is non-NULL. .PP \fBTcl_AppendFormatToObj\fR is an appending alternative form of \fBTcl_Format\fR with functionality equivalent to: .PP .CS Tcl_Obj *newPtr = \fBTcl_Format\fR(interp, format, objc, objv); if (newPtr == NULL) return TCL_ERROR; \fBTcl_AppendObjToObj\fR(objPtr, newPtr); \fBTcl_DecrRefCount\fR(newPtr); return TCL_OK; .CE .PP but with greater convenience and efficiency when the appending functionality is needed. .PP \fBTcl_ObjPrintf\fR serves as a replacement for the common sequence .PP .CS char buf[SOME_SUITABLE_LENGTH]; sprintf(buf, format, ...); \fBTcl_NewStringObj\fR(buf, -1); .CE .PP but with greater convenience and no need to determine \fBSOME_SUITABLE_LENGTH\fR. The formatting is done with the same core formatting engine used by \fBTcl_Format\fR. This means the set of supported conversion specifiers is that of the \fBformat\fR command and not that of the \fBsprintf\fR routine where the two sets differ. When a conversion specifier passed to \fBTcl_ObjPrintf\fR includes a precision, the value is taken as a number of bytes, as \fBsprintf\fR does, and not as a number of characters, as \fBformat\fR does. This is done on the assumption that C code is more likely to know how many bytes it is passing around than the number of encoded characters those bytes happen to represent. The variable number of arguments passed in should be of the types that would be suitable for passing to \fBsprintf\fR. Note in this example usage, \fIx\fR is of type \fBint\fR. .PP .CS int x = 5; Tcl_Obj *objPtr = \fBTcl_ObjPrintf\fR("Value is %d", x); .CE .PP If the value of \fIformat\fR contains internal inconsistencies or invalid specifier formats, the formatted string result produced by \fBTcl_ObjPrintf\fR will be an error message describing the error. It is impossible however to provide runtime protection against mismatches between the format and any subsequent arguments. Compile-time protection may be provided by some compilers. .PP \fBTcl_AppendPrintfToObj\fR is an appending alternative form of \fBTcl_ObjPrintf\fR with functionality equivalent to .PP .CS Tcl_Obj *newPtr = \fBTcl_ObjPrintf\fR(format, ...); \fBTcl_AppendObjToObj\fR(objPtr, newPtr); \fBTcl_DecrRefCount\fR(newPtr); .CE .PP but with greater convenience and efficiency when the appending functionality is needed. .PP The \fBTcl_SetObjLength\fR procedure changes the length of the string value of its \fIobjPtr\fR argument. If the \fInewLength\fR argument is greater than the space allocated for the value's string, then the string space is reallocated and the old value is copied to the new space; the bytes between the old length of the string and the new length may have arbitrary values. If the \fInewLength\fR argument is less than the current length of the value's string, with \fIobjPtr->length\fR is reduced without reallocating the string space; the original allocated size for the string is recorded in the value, so that the string length can be enlarged in a subsequent call to \fBTcl_SetObjLength\fR without reallocating storage. In all cases \fBTcl_SetObjLength\fR leaves a null character at \fIobjPtr->bytes[newLength]\fR. .PP \fBTcl_AttemptSetObjLength\fR is identical in function to \fBTcl_SetObjLength\fR except that if sufficient memory to satisfy the request cannot be allocated, it does not cause the Tcl interpreter to \fBpanic\fR. Thus, if \fInewLength\fR is greater than the space allocated for the value's string, and there is not enough memory available to satisfy the request, \fBTcl_AttemptSetObjLength\fR will take no action and return 0 to indicate failure. If there is enough memory to satisfy the request, \fBTcl_AttemptSetObjLength\fR behaves just like \fBTcl_SetObjLength\fR and returns 1 to indicate success. .PP The \fBTcl_ConcatObj\fR function returns a new string value whose value is the space-separated concatenation of the string representations of all of the values in the \fIobjv\fR array. \fBTcl_ConcatObj\fR eliminates leading and trailing white space as it copies the string representations of the \fIobjv\fR array to the result. If an element of the \fIobjv\fR array consists of nothing but white space, then that value is ignored entirely. This white-space removal was added to make the output of the \fBconcat\fR command cleaner-looking. \fBTcl_ConcatObj\fR returns a pointer to a newly-created value whose ref count is zero. .SH "SEE ALSO" Tcl_NewObj(3), Tcl_IncrRefCount(3), Tcl_DecrRefCount(3), format(n), sprintf(3) .SH KEYWORDS append, internal representation, value, value type, string value, string type, string representation, concat, concatenate, unicode tcl8.6.5/doc/for.n0000644000175000017500000000561512663660065013310 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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 for n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME for \- 'For' loop .SH SYNOPSIS \fBfor \fIstart test next body\fR .BE .SH DESCRIPTION .PP \fBFor\fR is a looping command, similar in structure to the C \fBfor\fR statement. The \fIstart\fR, \fInext\fR, and \fIbody\fR arguments must be Tcl command strings, and \fItest\fR is an expression string. The \fBfor\fR command first invokes the Tcl interpreter to execute \fIstart\fR. Then it repeatedly evaluates \fItest\fR as an expression; if the result is non-zero it invokes the Tcl interpreter on \fIbody\fR, then invokes the Tcl interpreter on \fInext\fR, then repeats the loop. The command terminates when \fItest\fR evaluates to 0. If a \fBcontinue\fR command is invoked within \fIbody\fR then any remaining commands in the current execution of \fIbody\fR are skipped; processing continues by invoking the Tcl interpreter on \fInext\fR, then evaluating \fItest\fR, and so on. If a \fBbreak\fR command is invoked within \fIbody\fR or \fInext\fR, then the \fBfor\fR command will return immediately. The operation of \fBbreak\fR and \fBcontinue\fR are similar to the corresponding statements in C. \fBFor\fR returns an empty string. .PP Note: \fItest\fR should almost always be enclosed in braces. If not, variable substitutions will be made before the \fBfor\fR command starts executing, which means that variable changes made by the loop body will not be considered in the expression. This is likely to result in an infinite loop. If \fItest\fR is enclosed in braces, variable substitutions are delayed until the expression is evaluated (before each loop iteration), so changes in the variables will be visible. See below for an example: .SH EXAMPLES .PP Print a line for each of the integers from 0 to 9: .PP .CS \fBfor\fR {set x 0} {$x<10} {incr x} { puts "x is $x" } .CE .PP Either loop infinitely or not at all because the expression being evaluated is actually the constant, or even generate an error! The actual behaviour will depend on whether the variable \fIx\fR exists before the \fBfor\fR command is run and whether its value is a value that is less than or greater than/equal to ten, and this is because the expression will be substituted before the \fBfor\fR command is executed. .PP .CS \fBfor\fR {set x 0} $x<10 {incr x} { puts "x is $x" } .CE .PP Print out the powers of two from 1 to 1024: .PP .CS \fBfor\fR {set x 1} {$x<=1024} {set x [expr {$x * 2}]} { puts "x is $x" } .CE .SH "SEE ALSO" break(n), continue(n), foreach(n), while(n) .SH KEYWORDS boolean, for, iteration, loop '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/http.n0000644000175000017500000005253712663660065013506 0ustar sergeisergei'\" '\" Copyright (c) 1995-1997 Sun Microsystems, Inc. '\" Copyright (c) 1998-2000 by Ajuba Solutions. '\" Copyright (c) 2004 ActiveState Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH "http" n 2.7 http "Tcl Bundled Packages" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME http \- Client-side implementation of the HTTP/1.1 protocol .SH SYNOPSIS \fBpackage require http ?2.7?\fR .\" See Also -useragent option documentation in body! .sp \fB::http::config ?\fI\-option value\fR ...? .sp \fB::http::geturl \fIurl\fR ?\fI\-option value\fR ...? .sp \fB::http::formatQuery\fR \fIkey value\fR ?\fIkey value\fR ...? .sp \fB::http::reset\fR \fItoken\fR ?\fIwhy\fR? .sp \fB::http::wait \fItoken\fR .sp \fB::http::status \fItoken\fR .sp \fB::http::size \fItoken\fR .sp \fB::http::code \fItoken\fR .sp \fB::http::ncode \fItoken\fR .sp \fB::http::meta \fItoken\fR .sp \fB::http::data \fItoken\fR .sp \fB::http::error \fItoken\fR .sp \fB::http::cleanup \fItoken\fR .sp \fB::http::register \fIproto port command\fR .sp \fB::http::unregister \fIproto\fR .BE .SH DESCRIPTION .PP The \fBhttp\fR package provides the client side of the HTTP/1.1 protocol, as defined in RFC 2616. The package implements the GET, POST, and HEAD operations of HTTP/1.1. It allows configuration of a proxy host to get through firewalls. The package is compatible with the \fBSafesock\fR security policy, so it can be used by untrusted applets to do URL fetching from a restricted set of hosts. This package can be extended to support additional HTTP transport protocols, such as HTTPS, by providing a custom \fBsocket\fR command, via \fB::http::register\fR. .PP The \fB::http::geturl\fR procedure does a HTTP transaction. Its \fIoptions \fR determine whether a GET, POST, or HEAD transaction is performed. The return value of \fB::http::geturl\fR is a token for the transaction. The value is also the name of an array in the ::http namespace that contains state information about the transaction. The elements of this array are described in the \fBSTATE ARRAY\fR section. .PP If the \fB\-command\fR option is specified, then the HTTP operation is done in the background. \fB::http::geturl\fR returns immediately after generating the HTTP request and the callback is invoked when the transaction completes. For this to work, the Tcl event loop must be active. In Tk applications this is always true. For pure-Tcl applications, the caller can use \fB::http::wait\fR after calling \fB::http::geturl\fR to start the event loop. .SH COMMANDS .TP \fB::http::config\fR ?\fIoptions\fR? . The \fB::http::config\fR command is used to set and query the name of the proxy server and port, and the User-Agent name used in the HTTP requests. If no options are specified, then the current configuration is returned. If a single argument is specified, then it should be one of the flags described below. In this case the current value of that setting is returned. Otherwise, the options should be a set of flags and values that define the configuration: .RS .TP \fB\-accept\fR \fImimetypes\fR . The Accept header of the request. The default is */*, which means that all types of documents are accepted. Otherwise you can supply a comma-separated list of mime type patterns that you are willing to receive. For example, .QW "image/gif, image/jpeg, text/*" . .TP \fB\-proxyhost\fR \fIhostname\fR . The name of the proxy host, if any. If this value is the empty string, the URL host is contacted directly. .TP \fB\-proxyport\fR \fInumber\fR . The proxy port number. .TP \fB\-proxyfilter\fR \fIcommand\fR . The command is a callback that is made during \fB::http::geturl\fR to determine if a proxy is required for a given host. One argument, a host name, is added to \fIcommand\fR when it is invoked. If a proxy is required, the callback should return a two-element list containing the proxy server and proxy port. Otherwise the filter should return an empty list. The default filter returns the values of the \fB\-proxyhost\fR and \fB\-proxyport\fR settings if they are non-empty. .TP \fB\-urlencoding\fR \fIencoding\fR . The \fIencoding\fR used for creating the x-url-encoded URLs with \fB::http::formatQuery\fR. The default is \fButf-8\fR, as specified by RFC 2718. Prior to http 2.5 this was unspecified, and that behavior can be returned by specifying the empty string (\fB{}\fR), although \fIiso8859-1\fR is recommended to restore similar behavior but without the \fB::http::formatQuery\fR throwing an error processing non-latin-1 characters. .TP \fB\-useragent\fR \fIstring\fR . The value of the User-Agent header in the HTTP request. The default is .QW "\fBTcl http client package 2.7\fR" . .RE .TP \fB::http::geturl\fR \fIurl\fR ?\fIoptions\fR? . The \fB::http::geturl\fR command is the main procedure in the package. The \fB\-query\fR option causes a POST operation and the \fB\-validate\fR option causes a HEAD operation; otherwise, a GET operation is performed. The \fB::http::geturl\fR command returns a \fItoken\fR value that can be used to get information about the transaction. See the \fBSTATE ARRAY\fR and \fBERRORS\fR section for details. The \fB::http::geturl\fR command blocks until the operation completes, unless the \fB\-command\fR option specifies a callback that is invoked when the HTTP transaction completes. \fB::http::geturl\fR takes several options: .RS .TP \fB\-binary\fR \fIboolean\fR . Specifies whether to force interpreting the URL data as binary. Normally this is auto-detected (anything not beginning with a \fBtext\fR content type or whose content encoding is \fBgzip\fR or \fBcompress\fR is considered binary data). .TP \fB\-blocksize\fR \fIsize\fR . The block size used when reading the URL. At most \fIsize\fR bytes are read at once. After each block, a call to the \fB\-progress\fR callback is made (if that option is specified). .TP \fB\-channel\fR \fIname\fR . Copy the URL contents to channel \fIname\fR instead of saving it in \fBstate(body)\fR. .TP \fB\-command\fR \fIcallback\fR . Invoke \fIcallback\fR after the HTTP transaction completes. This option causes \fB::http::geturl\fR to return immediately. The \fIcallback\fR gets an additional argument that is the \fItoken\fR returned from \fB::http::geturl\fR. This token is the name of an array that is described in the \fBSTATE ARRAY\fR section. Here is a template for the callback: .RS .PP .CS proc httpCallback {token} { upvar #0 $token state # Access state as a Tcl array } .CE .RE .TP \fB\-handler\fR \fIcallback\fR . Invoke \fIcallback\fR whenever HTTP data is available; if present, nothing else will be done with the HTTP data. This procedure gets two additional arguments: the socket for the HTTP data and the \fItoken\fR returned from \fB::http::geturl\fR. The token is the name of a global array that is described in the \fBSTATE ARRAY\fR section. The procedure is expected to return the number of bytes read from the socket. Here is a template for the callback: .RS .PP .CS proc httpHandlerCallback {socket token} { upvar #0 $token state # Access socket, and state as a Tcl array # For example... ... set data [read $socket 1000] set nbytes [string length $data] ... return $nbytes } .CE .RE .TP \fB\-headers\fR \fIkeyvaluelist\fR . This option is used to add headers not already specified by \fB::http::config\fR to the HTTP request. The \fIkeyvaluelist\fR argument must be a list with an even number of elements that alternate between keys and values. The keys become header field names. Newlines are stripped from the values so the header cannot be corrupted. For example, if \fIkeyvaluelist\fR is \fBPragma no-cache\fR then the following header is included in the HTTP request: .RS .PP .CS Pragma: no-cache .CE .RE .TP \fB\-keepalive\fR \fIboolean\fR . If true, attempt to keep the connection open for servicing multiple requests. Default is 0. .TP \fB\-method\fR \fItype\fR . Force the HTTP request method to \fItype\fR. \fB::http::geturl\fR will auto-select GET, POST or HEAD based on other options, but this option enables choices like PUT and DELETE for webdav support. .TP \fB\-myaddr\fR \fIaddress\fR . Pass an specific local address to the underlying \fBsocket\fR call in case multiple interfaces are available. .TP \fB\-progress\fR \fIcallback\fR . The \fIcallback\fR is made after each transfer of data from the URL. The callback gets three additional arguments: the \fItoken\fR from \fB::http::geturl\fR, the expected total size of the contents from the \fBContent-Length\fR meta-data, and the current number of bytes transferred so far. The expected total size may be unknown, in which case zero is passed to the callback. Here is a template for the progress callback: .RS .PP .CS proc httpProgress {token total current} { upvar #0 $token state } .CE .RE .TP \fB\-protocol\fR \fIversion\fR . Select the HTTP protocol version to use. This should be 1.0 or 1.1 (the default). Should only be necessary for servers that do not understand or otherwise complain about HTTP/1.1. .TP \fB\-query\fR \fIquery\fR . This flag causes \fB::http::geturl\fR to do a POST request that passes the \fIquery\fR to the server. The \fIquery\fR must be an x-url-encoding formatted query. The \fB::http::formatQuery\fR procedure can be used to do the formatting. .TP \fB\-queryblocksize\fR \fIsize\fR . The block size used when posting query data to the URL. At most \fIsize\fR bytes are written at once. After each block, a call to the \fB\-queryprogress\fR callback is made (if that option is specified). .TP \fB\-querychannel\fR \fIchannelID\fR . This flag causes \fB::http::geturl\fR to do a POST request that passes the data contained in \fIchannelID\fR to the server. The data contained in \fIchannelID\fR must be an x-url-encoding formatted query unless the \fB\-type\fR option below is used. If a Content-Length header is not specified via the \fB\-headers\fR options, \fB::http::geturl\fR attempts to determine the size of the post data in order to create that header. If it is unable to determine the size, it returns an error. .TP \fB\-queryprogress\fR \fIcallback\fR . The \fIcallback\fR is made after each transfer of data to the URL (i.e. POST) and acts exactly like the \fB\-progress\fR option (the callback format is the same). .TP \fB\-strict\fR \fIboolean\fR . Whether to enforce RFC 3986 URL validation on the request. Default is 1. .TP \fB\-timeout\fR \fImilliseconds\fR . If \fImilliseconds\fR is non-zero, then \fB::http::geturl\fR sets up a timeout to occur after the specified number of milliseconds. A timeout results in a call to \fB::http::reset\fR and to the \fB\-command\fR callback, if specified. The return value of \fB::http::status\fR is \fBtimeout\fR after a timeout has occurred. .TP \fB\-type\fR \fImime-type\fR . Use \fImime-type\fR as the \fBContent-Type\fR value, instead of the default value (\fBapplication/x-www-form-urlencoded\fR) during a POST operation. .TP \fB\-validate\fR \fIboolean\fR . If \fIboolean\fR is non-zero, then \fB::http::geturl\fR does an HTTP HEAD request. This request returns meta information about the URL, but the contents are not returned. The meta information is available in the \fBstate(meta) \fR variable after the transaction. See the \fBSTATE ARRAY\fR section for details. .RE .TP \fB::http::formatQuery\fR \fIkey value\fR ?\fIkey value\fR ...? . This procedure does x-url-encoding of query data. It takes an even number of arguments that are the keys and values of the query. It encodes the keys and values, and generates one string that has the proper & and = separators. The result is suitable for the \fB\-query\fR value passed to \fB::http::geturl\fR. .TP \fB::http::reset\fR \fItoken\fR ?\fIwhy\fR? . This command resets the HTTP transaction identified by \fItoken\fR, if any. This sets the \fBstate(status)\fR value to \fIwhy\fR, which defaults to \fBreset\fR, and then calls the registered \fB\-command\fR callback. .TP \fB::http::wait\fR \fItoken\fR . This is a convenience procedure that blocks and waits for the transaction to complete. This only works in trusted code because it uses \fBvwait\fR. Also, it is not useful for the case where \fB::http::geturl\fR is called \fIwithout\fR the \fB\-command\fR option because in this case the \fB::http::geturl\fR call does not return until the HTTP transaction is complete, and thus there is nothing to wait for. .TP \fB::http::data\fR \fItoken\fR . This is a convenience procedure that returns the \fBbody\fR element (i.e., the URL data) of the state array. .TP \fB::http::error\fR \fItoken\fR . This is a convenience procedure that returns the \fBerror\fR element of the state array. .TP \fB::http::status\fR \fItoken\fR . This is a convenience procedure that returns the \fBstatus\fR element of the state array. .TP \fB::http::code\fR \fItoken\fR . This is a convenience procedure that returns the \fBhttp\fR element of the state array. .TP \fB::http::ncode\fR \fItoken\fR . This is a convenience procedure that returns just the numeric return code (200, 404, etc.) from the \fBhttp\fR element of the state array. .TP \fB::http::size\fR \fItoken\fR . This is a convenience procedure that returns the \fBcurrentsize\fR element of the state array, which represents the number of bytes received from the URL in the \fB::http::geturl\fR call. .TP \fB::http::meta\fR \fItoken\fR . This is a convenience procedure that returns the \fBmeta\fR element of the state array which contains the HTTP response headers. See below for an explanation of this element. .TP \fB::http::cleanup\fR \fItoken\fR . This procedure cleans up the state associated with the connection identified by \fItoken\fR. After this call, the procedures like \fB::http::data\fR cannot be used to get information about the operation. It is \fIstrongly\fR recommended that you call this function after you are done with a given HTTP request. Not doing so will result in memory not being freed, and if your app calls \fB::http::geturl\fR enough times, the memory leak could cause a performance hit...or worse. .TP \fB::http::register\fR \fIproto port command\fR . This procedure allows one to provide custom HTTP transport types such as HTTPS, by registering a prefix, the default port, and the command to execute to create the Tcl \fBchannel\fR. E.g.: .RS .PP .CS package require http package require tls ::http::register https 443 ::tls::socket set token [::http::geturl https://my.secure.site/] .CE .RE .TP \fB::http::unregister\fR \fIproto\fR . This procedure unregisters a protocol handler that was previously registered via \fB::http::register\fR. .SH ERRORS The \fB::http::geturl\fR procedure will raise errors in the following cases: invalid command line options, an invalid URL, a URL on a non-existent host, or a URL at a bad port on an existing host. These errors mean that it cannot even start the network transaction. It will also raise an error if it gets an I/O error while writing out the HTTP request header. For synchronous \fB::http::geturl\fR calls (where \fB\-command\fR is not specified), it will raise an error if it gets an I/O error while reading the HTTP reply headers or data. Because \fB::http::geturl\fR does not return a token in these cases, it does all the required cleanup and there is no issue of your app having to call \fB::http::cleanup\fR. .PP For asynchronous \fB::http::geturl\fR calls, all of the above error situations apply, except that if there is any error while reading the HTTP reply headers or data, no exception is thrown. This is because after writing the HTTP headers, \fB::http::geturl\fR returns, and the rest of the HTTP transaction occurs in the background. The command callback can check if any error occurred during the read by calling \fB::http::status\fR to check the status and if its \fIerror\fR, calling \fB::http::error\fR to get the error message. .PP Alternatively, if the main program flow reaches a point where it needs to know the result of the asynchronous HTTP request, it can call \fB::http::wait\fR and then check status and error, just as the callback does. .PP In any case, you must still call \fB::http::cleanup\fR to delete the state array when you are done. .PP There are other possible results of the HTTP transaction determined by examining the status from \fB::http::status\fR. These are described below. .TP \fBok\fR . If the HTTP transaction completes entirely, then status will be \fBok\fR. However, you should still check the \fB::http::code\fR value to get the HTTP status. The \fB::http::ncode\fR procedure provides just the numeric error (e.g., 200, 404 or 500) while the \fB::http::code\fR procedure returns a value like .QW "HTTP 404 File not found" . .TP \fBeof\fR . If the server closes the socket without replying, then no error is raised, but the status of the transaction will be \fBeof\fR. .TP \fBerror\fR . The error message will also be stored in the \fBerror\fR status array element, accessible via \fB::http::error\fR. .PP Another error possibility is that \fB::http::geturl\fR is unable to write all the post query data to the server before the server responds and closes the socket. The error message is saved in the \fBposterror\fR status array element and then \fB::http::geturl\fR attempts to complete the transaction. If it can read the server's response it will end up with an \fBok\fR status, otherwise it will have an \fBeof\fR status. .SH "STATE ARRAY" The \fB::http::geturl\fR procedure returns a \fItoken\fR that can be used to get to the state of the HTTP transaction in the form of a Tcl array. Use this construct to create an easy-to-use array variable: .PP .CS upvar #0 $token state .CE .PP Once the data associated with the URL is no longer needed, the state array should be unset to free up storage. The \fB::http::cleanup\fR procedure is provided for that purpose. The following elements of the array are supported: .RS .TP \fBbody\fR . The contents of the URL. This will be empty if the \fB\-channel\fR option has been specified. This value is returned by the \fB::http::data\fR command. .TP \fBcharset\fR . The value of the charset attribute from the \fBContent-Type\fR meta-data value. If none was specified, this defaults to the RFC standard \fBiso8859-1\fR, or the value of \fB$::http::defaultCharset\fR. Incoming text data will be automatically converted from this charset to utf-8. .TP \fBcoding\fR . A copy of the \fBContent-Encoding\fR meta-data value. .TP \fBcurrentsize\fR . The current number of bytes fetched from the URL. This value is returned by the \fB::http::size\fR command. .TP \fBerror\fR . If defined, this is the error string seen when the HTTP transaction was aborted. .TP \fBhttp\fR . The HTTP status reply from the server. This value is returned by the \fB::http::code\fR command. The format of this value is: .RS .PP .CS \fIHTTP/1.1 code string\fR .CE .PP The \fIcode\fR is a three-digit number defined in the HTTP standard. A code of 200 is OK. Codes beginning with 4 or 5 indicate errors. Codes beginning with 3 are redirection errors. In this case the \fBLocation\fR meta-data specifies a new URL that contains the requested information. .RE .TP \fBmeta\fR . The HTTP protocol returns meta-data that describes the URL contents. The \fBmeta\fR element of the state array is a list of the keys and values of the meta-data. This is in a format useful for initializing an array that just contains the meta-data: .RS .PP .CS array set meta $state(meta) .CE .PP Some of the meta-data keys are listed below, but the HTTP standard defines more, and servers are free to add their own. .TP \fBContent-Type\fR . The type of the URL contents. Examples include \fBtext/html\fR, \fBimage/gif,\fR \fBapplication/postscript\fR and \fBapplication/x-tcl\fR. .TP \fBContent-Length\fR . The advertised size of the contents. The actual size obtained by \fB::http::geturl\fR is available as \fBstate(currentsize)\fR. .TP \fBLocation\fR . An alternate URL that contains the requested data. .RE .TP \fBposterror\fR . The error, if any, that occurred while writing the post query data to the server. .TP \fBstatus\fR . Either \fBok\fR, for successful completion, \fBreset\fR for user-reset, \fBtimeout\fR if a timeout occurred before the transaction could complete, or \fBerror\fR for an error condition. During the transaction this value is the empty string. .TP \fBtotalsize\fR . A copy of the \fBContent-Length\fR meta-data value. .TP \fBtype\fR . A copy of the \fBContent-Type\fR meta-data value. .TP \fBurl\fR . The requested URL. .RE .SH EXAMPLE .PP This example creates a procedure to copy a URL to a file while printing a progress meter, and prints the meta-data associated with the URL. .PP .CS proc httpcopy { url file {chunk 4096} } { set out [open $file w] set token [\fB::http::geturl\fR $url -channel $out \e -progress httpCopyProgress -blocksize $chunk] close $out # This ends the line started by httpCopyProgress puts stderr "" upvar #0 $token state set max 0 foreach {name value} $state(meta) { if {[string length $name] > $max} { set max [string length $name] } if {[regexp -nocase ^location$ $name]} { # Handle URL redirects puts stderr "Location:$value" return [httpcopy [string trim $value] $file $chunk] } } incr max foreach {name value} $state(meta) { puts [format "%-*s %s" $max $name: $value] } return $token } proc httpCopyProgress {args} { puts -nonewline stderr . flush stderr } .CE .SH "SEE ALSO" safe(n), socket(n), safesock(n) .SH KEYWORDS internet, security policy, socket, www '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/SaveResult.30000644000175000017500000001231012663660065014512 0ustar sergeisergei'\" '\" Copyright (c) 1997 by Sun Microsystems, Inc. '\" Contributions from Don Porter, NIST, 2004. (not subject to US copyright) '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_SaveResult 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_SaveInterpState, Tcl_RestoreInterpState, Tcl_DiscardInterpState, Tcl_SaveResult, Tcl_RestoreResult, Tcl_DiscardResult \- save and restore an interpreter's state .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_InterpState \fBTcl_SaveInterpState\fR(\fIinterp, status\fR) .sp int \fBTcl_RestoreInterpState\fR(\fIinterp, state\fR) .sp \fBTcl_DiscardInterpState\fR(\fIstate\fR) .sp \fBTcl_SaveResult\fR(\fIinterp, savedPtr\fR) .sp \fBTcl_RestoreResult\fR(\fIinterp, savedPtr\fR) .sp \fBTcl_DiscardResult\fR(\fIsavedPtr\fR) .SH ARGUMENTS .AS Tcl_InterpState savedPtr .AP Tcl_Interp *interp in Interpreter for which state should be saved. .AP int status in Return code value to save as part of interpreter state. .AP Tcl_InterpState state in Saved state token to be restored or discarded. .AP Tcl_SavedResult *savedPtr in Pointer to location where interpreter result should be saved or restored. .BE .SH DESCRIPTION .PP These routines allows a C procedure to take a snapshot of the current state of an interpreter so that it can be restored after a call to \fBTcl_Eval\fR or some other routine that modifies the interpreter state. There are two triplets of routines meant to work together. .PP The first triplet stores the snapshot of interpreter state in an opaque token returned by \fBTcl_SaveInterpState\fR. That token value may then be passed back to one of \fBTcl_RestoreInterpState\fR or \fBTcl_DiscardInterpState\fR, depending on whether the interp state is to be restored. So long as one of the latter two routines is called, Tcl will take care of memory management. .PP The second triplet stores the snapshot of only the interpreter result (not its complete state) in memory allocated by the caller. These routines are passed a pointer to a \fBTcl_SavedResult\fR structure that is used to store enough information to restore the interpreter result. This structure can be allocated on the stack of the calling procedure. These routines do not save the state of any error information in the interpreter (e.g. the \fB\-errorcode\fR or \fB\-errorinfo\fR return options, when an error is in progress). .PP Because the routines \fBTcl_SaveInterpState\fR, \fBTcl_RestoreInterpState\fR, and \fBTcl_DiscardInterpState\fR perform a superset of the functions provided by the other routines, any new code should only make use of the more powerful routines. The older, weaker routines \fBTcl_SaveResult\fR, \fBTcl_RestoreResult\fR, and \fBTcl_DiscardResult\fR continue to exist only for the sake of existing programs that may already be using them. .PP \fBTcl_SaveInterpState\fR takes a snapshot of those portions of interpreter state that make up the full result of script evaluation. This include the interpreter result, the return code (passed in as the \fIstatus\fR argument, and any return options, including \fB\-errorinfo\fR and \fB\-errorcode\fR when an error is in progress. This snapshot is returned as an opaque token of type \fBTcl_InterpState\fR. The call to \fBTcl_SaveInterpState\fR does not itself change the state of the interpreter. Unlike \fBTcl_SaveResult\fR, it does not reset the interpreter. .PP \fBTcl_RestoreInterpState\fR accepts a \fBTcl_InterpState\fR token previously returned by \fBTcl_SaveInterpState\fR and restores the state of the interp to the state held in that snapshot. The return value of \fBTcl_RestoreInterpState\fR is the status value originally passed to \fBTcl_SaveInterpState\fR when the snapshot token was created. .PP \fBTcl_DiscardInterpState\fR is called to release a \fBTcl_InterpState\fR token previously returned by \fBTcl_SaveInterpState\fR when that snapshot is not to be restored to an interp. .PP The \fBTcl_InterpState\fR token returned by \fBTcl_SaveInterpState\fR must eventually be passed to either \fBTcl_RestoreInterpState\fR or \fBTcl_DiscardInterpState\fR to avoid a memory leak. Once the \fBTcl_InterpState\fR token is passed to one of them, the token is no longer valid and should not be used anymore. .PP \fBTcl_SaveResult\fR moves the string and value results of \fIinterp\fR into the location specified by \fIstatePtr\fR. \fBTcl_SaveResult\fR clears the result for \fIinterp\fR and leaves the result in its normal empty initialized state. .PP \fBTcl_RestoreResult\fR moves the string and value results from \fIstatePtr\fR back into \fIinterp\fR. Any result or error that was already in the interpreter will be cleared. The \fIstatePtr\fR is left in an uninitialized state and cannot be used until another call to \fBTcl_SaveResult\fR. .PP \fBTcl_DiscardResult\fR releases the saved interpreter state stored at \fBstatePtr\fR. The state structure is left in an uninitialized state and cannot be used until another call to \fBTcl_SaveResult\fR. .PP Once \fBTcl_SaveResult\fR is called to save the interpreter result, either \fBTcl_RestoreResult\fR or \fBTcl_DiscardResult\fR must be called to properly clean up the memory associated with the saved state. .SH KEYWORDS result, state, interp tcl8.6.5/doc/Async.30000644000175000017500000001511612663660065013501 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_AsyncCreate 3 7.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_AsyncCreate, Tcl_AsyncMark, Tcl_AsyncInvoke, Tcl_AsyncDelete, Tcl_AsyncReady \- handle asynchronous events .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_AsyncHandler \fBTcl_AsyncCreate\fR(\fIproc, clientData\fR) .sp \fBTcl_AsyncMark\fR(\fIasync\fR) .sp int \fBTcl_AsyncInvoke\fR(\fIinterp, code\fR) .sp \fBTcl_AsyncDelete\fR(\fIasync\fR) .sp int \fBTcl_AsyncReady\fR() .SH ARGUMENTS .AS Tcl_AsyncHandler clientData .AP Tcl_AsyncProc *proc in Procedure to invoke to handle an asynchronous event. .AP ClientData clientData in One-word value to pass to \fIproc\fR. .AP Tcl_AsyncHandler async in Token for asynchronous event handler. .AP Tcl_Interp *interp in Tcl interpreter in which command was being evaluated when handler was invoked, or NULL if handler was invoked when there was no interpreter active. .AP int code in Completion code from command that just completed in \fIinterp\fR, or 0 if \fIinterp\fR is NULL. .BE .SH DESCRIPTION .PP These procedures provide a safe mechanism for dealing with asynchronous events such as signals. If an event such as a signal occurs while a Tcl script is being evaluated then it is not safe to take any substantive action to process the event. For example, it is not safe to evaluate a Tcl script since the interpreter may already be in the middle of evaluating a script; it may not even be safe to allocate memory, since a memory allocation could have been in progress when the event occurred. The only safe approach is to set a flag indicating that the event occurred, then handle the event later when the world has returned to a clean state, such as after the current Tcl command completes. .PP \fBTcl_AsyncCreate\fR, \fBTcl_AsyncDelete\fR, and \fBTcl_AsyncReady\fR are thread sensitive. They access and/or set a thread-specific data structure in the event of a core built with \fI\-\-enable\-threads\fR. The token created by \fBTcl_AsyncCreate\fR contains the needed thread information it was called from so that calling \fBTcl_AsyncMark\fR(\fItoken\fR) will only yield the origin thread into the asynchronous handler. .PP \fBTcl_AsyncCreate\fR creates an asynchronous handler and returns a token for it. The asynchronous handler must be created before any occurrences of the asynchronous event that it is intended to handle (it is not safe to create a handler at the time of an event). When an asynchronous event occurs the code that detects the event (such as a signal handler) should call \fBTcl_AsyncMark\fR with the token for the handler. \fBTcl_AsyncMark\fR will mark the handler as ready to execute, but it will not invoke the handler immediately. Tcl will call the \fIproc\fR associated with the handler later, when the world is in a safe state, and \fIproc\fR can then carry out the actions associated with the asynchronous event. \fIProc\fR should have arguments and result that match the type \fBTcl_AsyncProc\fR: .PP .CS typedef int \fBTcl_AsyncProc\fR( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR, int \fIcode\fR); .CE .PP The \fIclientData\fR will be the same as the \fIclientData\fR argument passed to \fBTcl_AsyncCreate\fR when the handler was created. If \fIproc\fR is invoked just after a command has completed execution in an interpreter, then \fIinterp\fR will identify the interpreter in which the command was evaluated and \fIcode\fR will be the completion code returned by that command. The command's result will be present in the interpreter's result. When \fIproc\fR returns, whatever it leaves in the interpreter's result will be returned as the result of the command and the integer value returned by \fIproc\fR will be used as the new completion code for the command. .PP It is also possible for \fIproc\fR to be invoked when no interpreter is active. This can happen, for example, if an asynchronous event occurs while the application is waiting for interactive input or an X event. In this case \fIinterp\fR will be NULL and \fIcode\fR will be 0, and the return value from \fIproc\fR will be ignored. .PP The procedure \fBTcl_AsyncInvoke\fR is called to invoke all of the handlers that are ready. The procedure \fBTcl_AsyncReady\fR will return non-zero whenever any asynchronous handlers are ready; it can be checked to avoid calls to \fBTcl_AsyncInvoke\fR when there are no ready handlers. Tcl calls \fBTcl_AsyncReady\fR after each command is evaluated and calls \fBTcl_AsyncInvoke\fR if needed. Applications may also call \fBTcl_AsyncInvoke\fR at interesting times for that application. For example, Tcl's event handler calls \fBTcl_AsyncReady\fR after each event and calls \fBTcl_AsyncInvoke\fR if needed. The \fIinterp\fR and \fIcode\fR arguments to \fBTcl_AsyncInvoke\fR have the same meaning as for \fIproc\fR: they identify the active interpreter, if any, and the completion code from the command that just completed. .PP \fBTcl_AsyncDelete\fR removes an asynchronous handler so that its \fIproc\fR will never be invoked again. A handler can be deleted even when ready, and it will still not be invoked. .PP If multiple handlers become active at the same time, the handlers are invoked in the order they were created (oldest handler first). The \fIcode\fR and the interpreter's result for later handlers reflect the values returned by earlier handlers, so that the most recently created handler has last say about the interpreter's result and completion code. If new handlers become ready while handlers are executing, \fBTcl_AsyncInvoke\fR will invoke them all; at each point it invokes the highest-priority (oldest) ready handler, repeating this over and over until there are no longer any ready handlers. .SH WARNING .PP It is almost always a bad idea for an asynchronous event handler to modify the interpreter's result or return a code different from its \fIcode\fR argument. This sort of behavior can disrupt the execution of scripts in subtle ways and result in bugs that are extremely difficult to track down. If an asynchronous event handler needs to evaluate Tcl scripts then it should first save the interpreter's state by calling \fBTcl_SaveInterpState\fR, passing in the \fIcode\fR argument. When the asynchronous handler is finished it should restore the interpreter's state by calling \fBTcl_RestoreInterpState\fR, and then returning the \fIcode\fR argument. .SH KEYWORDS asynchronous event, handler, signal, Tcl_SaveInterpState, thread tcl8.6.5/doc/lreverse.n0000644000175000017500000000153312663660065014344 0ustar sergeisergei'\" '\" Copyright (c) 2006 by Donal K. Fellows. All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lreverse n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lreverse \- Reverse the order of a list .SH SYNOPSIS \fBlreverse \fIlist\fR .BE .SH DESCRIPTION .PP The \fBlreverse\fR command returns a list that has the same elements as its input list, \fIlist\fR, except with the elements in the reverse order. .SH EXAMPLES .CS \fBlreverse\fR {a a b c} \fI\(-> c b a a\fR \fBlreverse\fR {a b {c d} e f} \fI\(-> f e {c d} b a\fR .CE .SH "SEE ALSO" list(n), lsearch(n), lsort(n) .SH KEYWORDS element, list, reverse '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/tailcall.n0000644000175000017500000000361712663660065014307 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 tailcall n 8.6 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME tailcall \- Replace the current procedure with another command .SH SYNOPSIS \fBtailcall \fIcommand\fR ?\fIarg ...\fR? .BE .SH DESCRIPTION .PP The \fBtailcall\fR command replaces the currently executing procedure, lambda application, or method with another command. The \fIcommand\fR, which will have \fIarg ...\fR passed as arguments if they are supplied, will be looked up in the current namespace context, not in the caller's. Apart from that difference in resolution, it is equivalent to: .PP .CS return [uplevel 1 [list \fIcommand\fR ?\fIarg ...\fR?]] .CE .PP This command may not be invoked from within an \fBuplevel\fR into a procedure or inside a \fBcatch\fR inside a procedure or lambda. '\" TODO: sort out the mess with the [try] command! .SH EXAMPLE .PP Compute the factorial of a number. .PP .CS proc factorial {n {accum 1}} { if {$n < 2} { return $accum } \fBtailcall\fR factorial [expr {$n - 1}] [expr {$accum * $n}] } .CE .PP Print the elements of a list with alternating lines having different indentations. .PP .CS proc printList {theList} { if {[llength $theList]} { puts "> [lindex $theList 0]" \fBtailcall\fR printList2 [lrange $theList 1 end] } } proc printList2 {theList} { if {[llength $theList]} { puts "< [lindex $theList 0]" \fBtailcall\fR printList [lrange $theList 1 end] } } .CE .SH "SEE ALSO" apply(n), proc(n), uplevel(n) .SH KEYWORDS call, recursion, tail recursion '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/OpenFileChnl.30000644000175000017500000007503612663660065014741 0ustar sergeisergei'\" '\" Copyright (c) 1996-1997 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_OpenFileChannel 3 8.3 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_MakeFileChannel, Tcl_GetChannel, Tcl_GetChannelNames, Tcl_GetChannelNamesEx, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_DetachChannel, Tcl_IsStandardChannel, Tcl_Close, Tcl_ReadChars, Tcl_Read, Tcl_GetsObj, Tcl_Gets, Tcl_WriteObj, Tcl_WriteChars, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_TruncateChannel, Tcl_GetChannelOption, Tcl_SetChannelOption, Tcl_Eof, Tcl_InputBlocked, Tcl_InputBuffered, Tcl_OutputBuffered, Tcl_Ungets, Tcl_ReadRaw, Tcl_WriteRaw \- buffered I/O facilities using channels .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Channel \fBTcl_OpenFileChannel\fR(\fIinterp, fileName, mode, permissions\fR) .sp Tcl_Channel \fBTcl_OpenCommandChannel\fR(\fIinterp, argc, argv, flags\fR) .sp Tcl_Channel \fBTcl_MakeFileChannel\fR(\fIhandle, readOrWrite\fR) .sp Tcl_Channel \fBTcl_GetChannel\fR(\fIinterp, channelName, modePtr\fR) .sp int \fBTcl_GetChannelNames\fR(\fIinterp\fR) .sp int \fBTcl_GetChannelNamesEx\fR(\fIinterp, pattern\fR) .sp void \fBTcl_RegisterChannel\fR(\fIinterp, channel\fR) .sp int \fBTcl_UnregisterChannel\fR(\fIinterp, channel\fR) .sp int \fBTcl_DetachChannel\fR(\fIinterp, channel\fR) .sp int \fBTcl_IsStandardChannel\fR(\fIchannel\fR) .sp int \fBTcl_Close\fR(\fIinterp, channel\fR) .sp int \fBTcl_ReadChars\fR(\fIchannel, readObjPtr, charsToRead, appendFlag\fR) .sp int \fBTcl_Read\fR(\fIchannel, readBuf, bytesToRead\fR) .sp int \fBTcl_GetsObj\fR(\fIchannel, lineObjPtr\fR) .sp int \fBTcl_Gets\fR(\fIchannel, lineRead\fR) .sp int \fBTcl_Ungets\fR(\fIchannel, input, inputLen, addAtEnd\fR) .sp int \fBTcl_WriteObj\fR(\fIchannel, writeObjPtr\fR) .sp int \fBTcl_WriteChars\fR(\fIchannel, charBuf, bytesToWrite\fR) .sp int \fBTcl_Write\fR(\fIchannel, byteBuf, bytesToWrite\fR) .sp int \fBTcl_ReadRaw\fR(\fIchannel, readBuf, bytesToRead\fR) .sp int \fBTcl_WriteRaw\fR(\fIchannel, byteBuf, bytesToWrite\fR) .sp int \fBTcl_Eof\fR(\fIchannel\fR) .sp int \fBTcl_Flush\fR(\fIchannel\fR) .sp int \fBTcl_InputBlocked\fR(\fIchannel\fR) .sp int \fBTcl_InputBuffered\fR(\fIchannel\fR) .sp int \fBTcl_OutputBuffered\fR(\fIchannel\fR) .sp Tcl_WideInt \fBTcl_Seek\fR(\fIchannel, offset, seekMode\fR) .sp Tcl_WideInt \fBTcl_Tell\fR(\fIchannel\fR) .sp int \fBTcl_TruncateChannel\fR(\fIchannel, length\fR) .sp int \fBTcl_GetChannelOption\fR(\fIinterp, channel, optionName, optionValue\fR) .sp int \fBTcl_SetChannelOption\fR(\fIinterp, channel, optionName, newValue\fR) .sp .SH ARGUMENTS .AS Tcl_DString *channelName in/out .AP Tcl_Interp *interp in Used for error reporting and to look up a channel registered in it. .AP "const char" *fileName in The name of a local or network file. .AP "const char" *mode in Specifies how the file is to be accessed. May have any of the values allowed for the \fImode\fR argument to the Tcl \fBopen\fR command. .AP int permissions in POSIX-style permission flags such as 0644. If a new file is created, these permissions will be set on the created file. .AP int argc in The number of elements in \fIargv\fR. .AP "const char" **argv in Arguments for constructing a command pipeline. These values have the same meaning as the non-switch arguments to the Tcl \fBexec\fR command. .AP int flags in Specifies the disposition of the stdio handles in pipeline: OR-ed combination of \fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, \fBTCL_STDERR\fR, and \fBTCL_ENFORCE_MODE\fR. If \fBTCL_STDIN\fR is set, stdin for the first child in the pipe is the pipe channel, otherwise it is the same as the standard input of the invoking process; likewise for \fBTCL_STDOUT\fR and \fBTCL_STDERR\fR. If \fBTCL_ENFORCE_MODE\fR is not set, then the pipe can redirect stdio handles to override the stdio handles for which \fBTCL_STDIN\fR, \fBTCL_STDOUT\fR and \fBTCL_STDERR\fR have been set. If it is set, then such redirections cause an error. .AP ClientData handle in Operating system specific handle for I/O to a file. For Unix this is a file descriptor, for Windows it is a HANDLE. .AP int readOrWrite in OR-ed combination of \fBTCL_READABLE\fR and \fBTCL_WRITABLE\fR to indicate what operations are valid on \fIhandle\fR. .AP "const char" *channelName in The name of the channel. .AP int *modePtr out Points at an integer variable that will receive an OR-ed combination of \fBTCL_READABLE\fR and \fBTCL_WRITABLE\fR denoting whether the channel is open for reading and writing. .AP "const char" *pattern in The pattern to match on, passed to Tcl_StringMatch, or NULL. .AP Tcl_Channel channel in A Tcl channel for input or output. Must have been the return value from a procedure such as \fBTcl_OpenFileChannel\fR. .AP Tcl_Obj *readObjPtr in/out A pointer to a Tcl value in which to store the characters read from the channel. .AP int charsToRead in The number of characters to read from the channel. If the channel's encoding is \fBbinary\fR, this is equivalent to the number of bytes to read from the channel. .AP int appendFlag in If non-zero, data read from the channel will be appended to the value. Otherwise, the data will replace the existing contents of the value. .AP char *readBuf out A buffer in which to store the bytes read from the channel. .AP int bytesToRead in The number of bytes to read from the channel. The buffer \fIreadBuf\fR must be large enough to hold this many bytes. .AP Tcl_Obj *lineObjPtr in/out A pointer to a Tcl value in which to store the line read from the channel. The line read will be appended to the current value of the value. .AP Tcl_DString *lineRead in/out A pointer to a Tcl dynamic string in which to store the line read from the channel. Must have been initialized by the caller. The line read will be appended to any data already in the dynamic string. .AP "const char" *input in The input to add to a channel buffer. .AP int inputLen in Length of the input .AP int addAtEnd in Flag indicating whether the input should be added to the end or beginning of the channel buffer. .AP Tcl_Obj *writeObjPtr in A pointer to a Tcl value whose contents will be output to the channel. .AP "const char" *charBuf in A buffer containing the characters to output to the channel. .AP "const char" *byteBuf in A buffer containing the bytes to output to the channel. .AP int bytesToWrite in The number of bytes to consume from \fIcharBuf\fR or \fIbyteBuf\fR and output to the channel. .AP Tcl_WideInt offset in How far to move the access point in the channel at which the next input or output operation will be applied, measured in bytes from the position given by \fIseekMode\fR. May be either positive or negative. .AP int seekMode in Relative to which point to seek; used with \fIoffset\fR to calculate the new access point for the channel. Legal values are \fBSEEK_SET\fR, \fBSEEK_CUR\fR, and \fBSEEK_END\fR. .AP Tcl_WideInt length in The (non-negative) length to truncate the channel the channel to. .AP "const char" *optionName in The name of an option applicable to this channel, such as \fB\-blocking\fR. May have any of the values accepted by the \fBfconfigure\fR command. .AP Tcl_DString *optionValue in Where to store the value of an option or a list of all options and their values. Must have been initialized by the caller. .AP "const char" *newValue in New value for the option given by \fIoptionName\fR. .BE .SH DESCRIPTION .PP The Tcl channel mechanism provides a device-independent and platform-independent mechanism for performing buffered input and output operations on a variety of file, socket, and device types. The channel mechanism is extensible to new channel types, by providing a low-level channel driver for the new type; the channel driver interface is described in the manual entry for \fBTcl_CreateChannel\fR. The channel mechanism provides a buffering scheme modeled after Unix's standard I/O, and it also allows for nonblocking I/O on channels. .PP The procedures described in this manual entry comprise the C APIs of the generic layer of the channel architecture. For a description of the channel driver architecture and how to implement channel drivers for new types of channels, see the manual entry for \fBTcl_CreateChannel\fR. .SH TCL_OPENFILECHANNEL .PP \fBTcl_OpenFileChannel\fR opens a file specified by \fIfileName\fR and returns a channel handle that can be used to perform input and output on the file. This API is modeled after the \fBfopen\fR procedure of the Unix standard I/O library. The syntax and meaning of all arguments is similar to those given in the Tcl \fBopen\fR command when opening a file. If an error occurs while opening the channel, \fBTcl_OpenFileChannel\fR returns NULL and records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. In addition, if \fIinterp\fR is non-NULL, \fBTcl_OpenFileChannel\fR leaves an error message in \fIinterp\fR's result after any error. As of Tcl 8.4, the value-based API \fBTcl_FSOpenFileChannel\fR should be used in preference to \fBTcl_OpenFileChannel\fR wherever possible. .PP The newly created channel is not registered in the supplied interpreter; to register it, use \fBTcl_RegisterChannel\fR, described below. If one of the standard channels, \fBstdin\fR, \fBstdout\fR or \fBstderr\fR was previously closed, the act of creating the new channel also assigns it as a replacement for the standard channel. .SH TCL_OPENCOMMANDCHANNEL .PP \fBTcl_OpenCommandChannel\fR provides a C-level interface to the functions of the \fBexec\fR and \fBopen\fR commands. It creates a sequence of subprocesses specified by the \fIargv\fR and \fIargc\fR arguments and returns a channel that can be used to communicate with these subprocesses. The \fIflags\fR argument indicates what sort of communication will exist with the command pipeline. .PP If the \fBTCL_STDIN\fR flag is set then the standard input for the first subprocess will be tied to the channel: writing to the channel will provide input to the subprocess. If \fBTCL_STDIN\fR is not set, then standard input for the first subprocess will be the same as this application's standard input. If \fBTCL_STDOUT\fR is set then standard output from the last subprocess can be read from the channel; otherwise it goes to this application's standard output. If \fBTCL_STDERR\fR is set, standard error output for all subprocesses is returned to the channel and results in an error when the channel is closed; otherwise it goes to this application's standard error. If \fBTCL_ENFORCE_MODE\fR is not set, then \fIargc\fR and \fIargv\fR can redirect the stdio handles to override \fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, and \fBTCL_STDERR\fR; if it is set, then it is an error for argc and argv to override stdio channels for which \fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, and \fBTCL_STDERR\fR have been set. .PP If an error occurs while opening the channel, \fBTcl_OpenCommandChannel\fR returns NULL and records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. In addition, \fBTcl_OpenCommandChannel\fR leaves an error message in the interpreter's result if \fIinterp\fR is not NULL. .PP The newly created channel is not registered in the supplied interpreter; to register it, use \fBTcl_RegisterChannel\fR, described below. If one of the standard channels, \fBstdin\fR, \fBstdout\fR or \fBstderr\fR was previously closed, the act of creating the new channel also assigns it as a replacement for the standard channel. .SH TCL_MAKEFILECHANNEL .PP \fBTcl_MakeFileChannel\fR makes a \fBTcl_Channel\fR from an existing, platform-specific, file handle. The newly created channel is not registered in the supplied interpreter; to register it, use \fBTcl_RegisterChannel\fR, described below. If one of the standard channels, \fBstdin\fR, \fBstdout\fR or \fBstderr\fR was previously closed, the act of creating the new channel also assigns it as a replacement for the standard channel. .SH TCL_GETCHANNEL .PP \fBTcl_GetChannel\fR returns a channel given the \fIchannelName\fR used to create it with \fBTcl_CreateChannel\fR and a pointer to a Tcl interpreter in \fIinterp\fR. If a channel by that name is not registered in that interpreter, the procedure returns NULL. If the \fImodePtr\fR argument is not NULL, it points at an integer variable that will receive an OR-ed combination of \fBTCL_READABLE\fR and \fBTCL_WRITABLE\fR describing whether the channel is open for reading and writing. .PP \fBTcl_GetChannelNames\fR and \fBTcl_GetChannelNamesEx\fR write the names of the registered channels to the interpreter's result as a list value. \fBTcl_GetChannelNamesEx\fR will filter these names according to the \fIpattern\fR. If \fIpattern\fR is NULL, then it will not do any filtering. The return value is \fBTCL_OK\fR if no errors occurred writing to the result, otherwise it is \fBTCL_ERROR\fR, and the error message is left in the interpreter's result. .SH TCL_REGISTERCHANNEL .PP \fBTcl_RegisterChannel\fR adds a channel to the set of channels accessible in \fIinterp\fR. After this call, Tcl programs executing in that interpreter can refer to the channel in input or output operations using the name given in the call to \fBTcl_CreateChannel\fR. After this call, the channel becomes the property of the interpreter, and the caller should not call \fBTcl_Close\fR for the channel; the channel will be closed automatically when it is unregistered from the interpreter. .PP Code executing outside of any Tcl interpreter can call \fBTcl_RegisterChannel\fR with \fIinterp\fR as NULL, to indicate that it wishes to hold a reference to this channel. Subsequently, the channel can be registered in a Tcl interpreter and it will only be closed when the matching number of calls to \fBTcl_UnregisterChannel\fR have been made. This allows code executing outside of any interpreter to safely hold a reference to a channel that is also registered in a Tcl interpreter. .PP This procedure interacts with the code managing the standard channels. If no standard channels were initialized before the first call to \fBTcl_RegisterChannel\fR, they will get initialized by that call. See \fBTcl_StandardChannels\fR for a general treatise about standard channels and the behavior of the Tcl library with regard to them. .SH TCL_UNREGISTERCHANNEL .PP \fBTcl_UnregisterChannel\fR removes a channel from the set of channels accessible in \fIinterp\fR. After this call, Tcl programs will no longer be able to use the channel's name to refer to the channel in that interpreter. If this operation removed the last registration of the channel in any interpreter, the channel is also closed and destroyed. .PP Code not associated with a Tcl interpreter can call \fBTcl_UnregisterChannel\fR with \fIinterp\fR as NULL, to indicate to Tcl that it no longer holds a reference to that channel. If this is the last reference to the channel, it will now be closed. \fBTcl_UnregisterChannel\fR is very similar to \fBTcl_DetachChannel\fR except that it will also close the channel if no further references to it exist. .SH TCL_DETACHCHANNEL .PP \fBTcl_DetachChannel\fR removes a channel from the set of channels accessible in \fIinterp\fR. After this call, Tcl programs will no longer be able to use the channel's name to refer to the channel in that interpreter. Beyond that, this command has no further effect. It cannot be used on the standard channels (\fBstdout\fR, \fBstderr\fR, \fBstdin\fR), and will return \fBTCL_ERROR\fR if passed one of those channels. .PP Code not associated with a Tcl interpreter can call \fBTcl_DetachChannel\fR with \fIinterp\fR as NULL, to indicate to Tcl that it no longer holds a reference to that channel. If this is the last reference to the channel, unlike \fBTcl_UnregisterChannel\fR, it will not be closed. .SH TCL_ISSTANDARDCHANNEL .PP \fBTcl_IsStandardChannel\fR tests whether a channel is one of the three standard channels, \fBstdin\fR, \fBstdout\fR or \fBstderr\fR. If so, it returns 1, otherwise 0. .PP No attempt is made to check whether the given channel or the standard channels are initialized or otherwise valid. .SH TCL_CLOSE .PP \fBTcl_Close\fR destroys the channel \fIchannel\fR, which must denote a currently open channel. The channel should not be registered in any interpreter when \fBTcl_Close\fR is called. Buffered output is flushed to the channel's output device prior to destroying the channel, and any buffered input is discarded. If this is a blocking channel, the call does not return until all buffered data is successfully sent to the channel's output device. If this is a nonblocking channel and there is buffered output that cannot be written without blocking, the call returns immediately; output is flushed in the background and the channel will be closed once all of the buffered data has been output. In this case errors during flushing are not reported. .PP If the channel was closed successfully, \fBTcl_Close\fR returns \fBTCL_OK\fR. If an error occurs, \fBTcl_Close\fR returns \fBTCL_ERROR\fR and records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. If the channel is being closed synchronously and an error occurs during closing of the channel and \fIinterp\fR is not NULL, an error message is left in the interpreter's result. .PP Note: it is not safe to call \fBTcl_Close\fR on a channel that has been registered using \fBTcl_RegisterChannel\fR; see the documentation for \fBTcl_RegisterChannel\fR, above, for details. If the channel has ever been given as the \fBchan\fR argument in a call to \fBTcl_RegisterChannel\fR, you should instead use \fBTcl_UnregisterChannel\fR, which will internally call \fBTcl_Close\fR when all calls to \fBTcl_RegisterChannel\fR have been matched by corresponding calls to \fBTcl_UnregisterChannel\fR. .SH "TCL_READCHARS AND TCL_READ" .PP \fBTcl_ReadChars\fR consumes bytes from \fIchannel\fR, converting the bytes to UTF-8 based on the channel's encoding and storing the produced data in \fIreadObjPtr\fR's string representation. The return value of \fBTcl_ReadChars\fR is the number of characters, up to \fIcharsToRead\fR, that were stored in \fIreadObjPtr\fR. If an error occurs while reading, the return value is \-1 and \fBTcl_ReadChars\fR records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. .PP Setting \fIcharsToRead\fR to \fB\-1\fR will cause the command to read all characters currently available (non-blocking) or everything until eof (blocking mode). .PP The return value may be smaller than the value to read, indicating that less data than requested was available. This is called a \fIshort read\fR. In blocking mode, this can only happen on an end-of-file. In nonblocking mode, a short read can also occur if there is not enough input currently available: \fBTcl_ReadChars\fR returns a short count rather than waiting for more data. .PP If the channel is in blocking mode, a return value of zero indicates an end-of-file condition. If the channel is in nonblocking mode, a return value of zero indicates either that no input is currently available or an end-of-file condition. Use \fBTcl_Eof\fR and \fBTcl_InputBlocked\fR to tell which of these conditions actually occurred. .PP \fBTcl_ReadChars\fR translates the various end-of-line representations into the canonical \fB\en\fR internal representation according to the current end-of-line recognition mode. End-of-line recognition and the various platform-specific modes are described in the manual entry for the Tcl \fBfconfigure\fR command. .PP As a performance optimization, when reading from a channel with the encoding \fBbinary\fR, the bytes are not converted to UTF-8 as they are read. Instead, they are stored in \fIreadObjPtr\fR's internal representation as a byte-array value. The string representation of this value will only be constructed if it is needed (e.g., because of a call to \fBTcl_GetStringFromObj\fR). In this way, byte-oriented data can be read from a channel, manipulated by calling \fBTcl_GetByteArrayFromObj\fR and related functions, and then written to a channel without the expense of ever converting to or from UTF-8. .PP \fBTcl_Read\fR is similar to \fBTcl_ReadChars\fR, except that it does not do encoding conversions, regardless of the channel's encoding. It is deprecated and exists for backwards compatibility with non-internationalized Tcl extensions. It consumes bytes from \fIchannel\fR and stores them in \fIreadBuf\fR, performing end-of-line translations on the way. The return value of \fBTcl_Read\fR is the number of bytes, up to \fIbytesToRead\fR, written in \fIreadBuf\fR. The buffer produced by \fBTcl_Read\fR is not null-terminated. Its contents are valid from the zeroth position up to and excluding the position indicated by the return value. .PP \fBTcl_ReadRaw\fR is the same as \fBTcl_Read\fR but does not compensate for stacking. While \fBTcl_Read\fR (and the other functions in the API) always get their data from the topmost channel in the stack the supplied channel is part of, \fBTcl_ReadRaw\fR does not. Thus this function is \fBonly\fR usable for transformational channel drivers, i.e. drivers used in the middle of a stack of channels, to move data from the channel below into the transformation. .SH "TCL_GETSOBJ AND TCL_GETS" .PP \fBTcl_GetsObj\fR consumes bytes from \fIchannel\fR, converting the bytes to UTF-8 based on the channel's encoding, until a full line of input has been seen. If the channel's encoding is \fBbinary\fR, each byte read from the channel is treated as an individual Unicode character. All of the characters of the line except for the terminating end-of-line character(s) are appended to \fIlineObjPtr\fR's string representation. The end-of-line character(s) are read and discarded. .PP If a line was successfully read, the return value is greater than or equal to zero and indicates the number of bytes stored in \fIlineObjPtr\fR. If an error occurs, \fBTcl_GetsObj\fR returns \-1 and records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. \fBTcl_GetsObj\fR also returns \-1 if the end of the file is reached; the \fBTcl_Eof\fR procedure can be used to distinguish an error from an end-of-file condition. .PP If the channel is in nonblocking mode, the return value can also be \-1 if no data was available or the data that was available did not contain an end-of-line character. When \-1 is returned, the \fBTcl_InputBlocked\fR procedure may be invoked to determine if the channel is blocked because of input unavailability. .PP \fBTcl_Gets\fR is the same as \fBTcl_GetsObj\fR except the resulting characters are appended to the dynamic string given by \fIlineRead\fR rather than a Tcl value. .SH "TCL_UNGETS" .PP \fBTcl_Ungets\fR is used to add data to the input queue of a channel, at either the head or tail of the queue. The pointer \fIinput\fR points to the data that is to be added. The length of the input to add is given by \fIinputLen\fR. A non-zero value of \fIaddAtEnd\fR indicates that the data is to be added at the end of queue; otherwise it will be added at the head of the queue. If \fIchannel\fR has a .QW sticky EOF set, no data will be added to the input queue. \fBTcl_Ungets\fR returns \fIinputLen\fR or \-1 if an error occurs. .SH "TCL_WRITECHARS, TCL_WRITEOBJ, AND TCL_WRITE" .PP \fBTcl_WriteChars\fR accepts \fIbytesToWrite\fR bytes of character data at \fIcharBuf\fR. The UTF-8 characters in the buffer are converted to the channel's encoding and queued for output to \fIchannel\fR. If \fIbytesToWrite\fR is negative, \fBTcl_WriteChars\fR expects \fIcharBuf\fR to be null-terminated and it outputs everything up to the null. .PP Data queued for output may not appear on the output device immediately, due to internal buffering. If the data should appear immediately, call \fBTcl_Flush\fR after the call to \fBTcl_WriteChars\fR, or set the \fB\-buffering\fR option on the channel to \fBnone\fR. If you wish the data to appear as soon as a complete line is accepted for output, set the \fB\-buffering\fR option on the channel to \fBline\fR mode. .PP The return value of \fBTcl_WriteChars\fR is a count of how many bytes were accepted for output to the channel. This is either greater than zero to indicate success or \-1 to indicate that an error occurred. If an error occurs, \fBTcl_WriteChars\fR records a POSIX error code that may be retrieved with \fBTcl_GetErrno\fR. .PP Newline characters in the output data are translated to platform-specific end-of-line sequences according to the \fB\-translation\fR option for the channel. This is done even if the channel has no encoding. .PP \fBTcl_WriteObj\fR is similar to \fBTcl_WriteChars\fR except it accepts a Tcl value whose contents will be output to the channel. The UTF-8 characters in \fIwriteObjPtr\fR's string representation are converted to the channel's encoding and queued for output to \fIchannel\fR. As a performance optimization, when writing to a channel with the encoding \fBbinary\fR, UTF-8 characters are not converted as they are written. Instead, the bytes in \fIwriteObjPtr\fR's internal representation as a byte-array value are written to the channel. The byte-array representation of the value will be constructed if it is needed. In this way, byte-oriented data can be read from a channel, manipulated by calling \fBTcl_GetByteArrayFromObj\fR and related functions, and then written to a channel without the expense of ever converting to or from UTF-8. .PP \fBTcl_Write\fR is similar to \fBTcl_WriteChars\fR except that it does not do encoding conversions, regardless of the channel's encoding. It is deprecated and exists for backwards compatibility with non-internationalized Tcl extensions. It accepts \fIbytesToWrite\fR bytes of data at \fIbyteBuf\fR and queues them for output to \fIchannel\fR. If \fIbytesToWrite\fR is negative, \fBTcl_Write\fR expects \fIbyteBuf\fR to be null-terminated and it outputs everything up to the null. .PP \fBTcl_WriteRaw\fR is the same as \fBTcl_Write\fR but does not compensate for stacking. While \fBTcl_Write\fR (and the other functions in the API) always feed their input to the topmost channel in the stack the supplied channel is part of, \fBTcl_WriteRaw\fR does not. Thus this function is \fBonly\fR usable for transformational channel drivers, i.e. drivers used in the middle of a stack of channels, to move data from the transformation into the channel below it. .SH TCL_FLUSH .PP \fBTcl_Flush\fR causes all of the buffered output data for \fIchannel\fR to be written to its underlying file or device as soon as possible. If the channel is in blocking mode, the call does not return until all the buffered data has been sent to the channel or some error occurred. The call returns immediately if the channel is nonblocking; it starts a background flush that will write the buffered data to the channel eventually, as fast as the channel is able to absorb it. .PP The return value is normally \fBTCL_OK\fR. If an error occurs, \fBTcl_Flush\fR returns \fBTCL_ERROR\fR and records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. .SH TCL_SEEK .PP \fBTcl_Seek\fR moves the access point in \fIchannel\fR where subsequent data will be read or written. Buffered output is flushed to the channel and buffered input is discarded, prior to the seek operation. .PP \fBTcl_Seek\fR normally returns the new access point. If an error occurs, \fBTcl_Seek\fR returns \-1 and records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. After an error, the access point may or may not have been moved. .SH TCL_TELL .PP \fBTcl_Tell\fR returns the current access point for a channel. The returned value is \-1 if the channel does not support seeking. .SH TCL_TRUNCATECHANNEL .PP \fBTcl_TruncateChannel\fR truncates the file underlying \fIchannel\fR to a given \fIlength\fR of bytes. It returns \fBTCL_OK\fR if the operation succeeded, and \fBTCL_ERROR\fR otherwise. .SH TCL_GETCHANNELOPTION .PP \fBTcl_GetChannelOption\fR retrieves, in \fIoptionValue\fR, the value of one of the options currently in effect for a channel, or a list of all options and their values. The \fIchannel\fR argument identifies the channel for which to query an option or retrieve all options and their values. If \fIoptionName\fR is not NULL, it is the name of the option to query; the option's value is copied to the Tcl dynamic string denoted by \fIoptionValue\fR. If \fIoptionName\fR is NULL, the function stores an alternating list of option names and their values in \fIoptionValue\fR, using a series of calls to \fBTcl_DStringAppendElement\fR. The various preexisting options and their possible values are described in the manual entry for the Tcl \fBfconfigure\fR command. Other options can be added by each channel type. These channel type specific options are described in the manual entry for the Tcl command that creates a channel of that type; for example, the additional options for TCP based channels are described in the manual entry for the Tcl \fBsocket\fR command. The procedure normally returns \fBTCL_OK\fR. If an error occurs, it returns \fBTCL_ERROR\fR and calls \fBTcl_SetErrno\fR to store an appropriate POSIX error code. .SH TCL_SETCHANNELOPTION .PP \fBTcl_SetChannelOption\fR sets a new value \fInewValue\fR for an option \fIoptionName\fR on \fIchannel\fR. The procedure normally returns \fBTCL_OK\fR. If an error occurs, it returns \fBTCL_ERROR\fR; in addition, if \fIinterp\fR is non-NULL, \fBTcl_SetChannelOption\fR leaves an error message in the interpreter's result. .SH TCL_EOF .PP \fBTcl_Eof\fR returns a nonzero value if \fIchannel\fR encountered an end of file during the last input operation. .SH TCL_INPUTBLOCKED .PP \fBTcl_InputBlocked\fR returns a nonzero value if \fIchannel\fR is in nonblocking mode and the last input operation returned less data than requested because there was insufficient data available. The call always returns zero if the channel is in blocking mode. .SH TCL_INPUTBUFFERED .PP \fBTcl_InputBuffered\fR returns the number of bytes of input currently buffered in the internal buffers for a channel. If the channel is not open for reading, this function always returns zero. .SH TCL_OUTPUTBUFFERED .PP \fBTcl_OutputBuffered\fR returns the number of bytes of output currently buffered in the internal buffers for a channel. If the channel is not open for writing, this function always returns zero. .SH "PLATFORM ISSUES" .PP The handles returned from \fBTcl_GetChannelHandle\fR depend on the platform and the channel type. On Unix platforms, the handle is always a Unix file descriptor as returned from the \fBopen\fR system call. On Windows platforms, the handle is a file \fBHANDLE\fR when the channel was created with \fBTcl_OpenFileChannel\fR, \fBTcl_OpenCommandChannel\fR, or \fBTcl_MakeFileChannel\fR. Other channel types may return a different type of handle on Windows platforms. .SH "SEE ALSO" DString(3), fconfigure(n), filename(n), fopen(3), Tcl_CreateChannel(3) .SH KEYWORDS access point, blocking, buffered I/O, channel, channel driver, end of file, flush, input, nonblocking, output, read, seek, write tcl8.6.5/doc/string.n0000644000175000017500000004516612663660065014035 0ustar sergeisergei.\" .\" Copyright (c) 1993 The Regents of the University of California. .\" Copyright (c) 1994-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 string n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS .\" Note: do not modify the .SH NAME line immediately below! .SH NAME string \- Manipulate strings .SH SYNOPSIS \fBstring \fIoption arg \fR?\fIarg ...?\fR .BE .SH DESCRIPTION .PP Performs one of several string operations, depending on \fIoption\fR. The legal \fIoption\fRs (which may be abbreviated) are: .TP \fBstring cat\fR ?\fIstring1\fR? ?\fIstring2...\fR? .VS 8.6.2 Concatenate the given \fIstring\fRs just like placing them directly next to each other and return the resulting compound string. If no \fIstring\fRs are present, the result is an empty string. .RS .PP This primitive is occasionally handier than juxtaposition of strings when mixed quoting is wanted, or when the aim is to return the result of a concatenation without resorting to \fBreturn\fR \fB\-level 0\fR, and is more efficient than building a list of arguments and using \fBjoin\fR with an empty join string. .RE .VE .TP \fBstring compare\fR ?\fB\-nocase\fR? ?\fB\-length\fI length\fR? \fIstring1 string2\fR . Perform a character-by-character comparison of strings \fIstring1\fR and \fIstring2\fR. Returns \-1, 0, or 1, depending on whether \fIstring1\fR is lexicographically less than, equal to, or greater than \fIstring2\fR. If \fB\-length\fR is specified, then only the first \fIlength\fR characters are used in the comparison. If \fB\-length\fR is negative, it is ignored. If \fB\-nocase\fR is specified, then the strings are compared in a case-insensitive manner. .TP \fBstring equal\fR ?\fB\-nocase\fR? ?\fB\-length\fI length\fR? \fIstring1 string2\fR . Perform a character-by-character comparison of strings \fIstring1\fR and \fIstring2\fR. Returns 1 if \fIstring1\fR and \fIstring2\fR are identical, or 0 when not. If \fB\-length\fR is specified, then only the first \fIlength\fR characters are used in the comparison. If \fB\-length\fR is negative, it is ignored. If \fB\-nocase\fR is specified, then the strings are compared in a case-insensitive manner. .TP \fBstring first \fIneedleString haystackString\fR ?\fIstartIndex\fR? . Search \fIhaystackString\fR for a sequence of characters that exactly match the characters in \fIneedleString\fR. If found, return the index of the first character in the first such match within \fIhaystackString\fR. If not found, return \-1. If \fIstartIndex\fR is specified (in any of the forms described in \fBSTRING INDICES\fR), then the search is constrained to start with the character in \fIhaystackString\fR specified by the index. For example, .RS .PP .CS \fBstring first a 0a23456789abcdef 5\fR .CE .PP will return \fB10\fR, but .PP .CS \fBstring first a 0123456789abcdef 11\fR .CE .PP will return \fB\-1\fR. .RE .TP \fBstring index \fIstring charIndex\fR . Returns the \fIcharIndex\fR'th character of the \fIstring\fR argument. A \fIcharIndex\fR of 0 corresponds to the first character of the string. \fIcharIndex\fR may be specified as described in the \fBSTRING INDICES\fR section. .RS .PP If \fIcharIndex\fR is less than 0 or greater than or equal to the length of the string then this command returns an empty string. .RE .TP \fBstring is \fIclass\fR ?\fB\-strict\fR? ?\fB\-failindex \fIvarname\fR? \fIstring\fR . Returns 1 if \fIstring\fR is a valid member of the specified character class, otherwise returns 0. If \fB\-strict\fR is specified, then an empty string returns 0, otherwise an empty string will return 1 on any class. If \fB\-failindex\fR is specified, then if the function returns 0, the index in the string where the class was no longer valid will be stored in the variable named \fIvarname\fR. The \fIvarname\fR will not be set if \fBstring is\fR returns 1. The following character classes are recognized (the class name can be abbreviated): .RS .IP \fBalnum\fR 12 Any Unicode alphabet or digit character. .IP \fBalpha\fR 12 Any Unicode alphabet character. .IP \fBascii\fR 12 Any character with a value less than \eu0080 (those that are in the 7\-bit ascii range). .IP \fBboolean\fR 12 Any of the forms allowed to \fBTcl_GetBoolean\fR. .IP \fBcontrol\fR 12 Any Unicode control character. .IP \fBdigit\fR 12 Any Unicode digit character. Note that this includes characters outside of the [0\-9] range. .IP \fBdouble\fR 12 Any of the valid forms for a double in Tcl, with optional surrounding whitespace. In case of under/overflow in the value, 0 is returned and the \fIvarname\fR will contain \-1. .IP \fBentier\fR 12 .VS 8.6 Any of the valid string formats for an integer value of arbitrary size in Tcl, with optional surrounding whitespace. The formats accepted are exactly those accepted by the C routine \fBTcl_GetBignumFromObj\fR. .VE .IP \fBfalse\fR 12 Any of the forms allowed to \fBTcl_GetBoolean\fR where the value is false. .IP \fBgraph\fR 12 Any Unicode printing character, except space. .IP \fBinteger\fR 12 Any of the valid string formats for a 32-bit integer value in Tcl, with optional surrounding whitespace. In case of under/overflow in the value, 0 is returned and the \fIvarname\fR will contain \-1. .IP \fBlist\fR 12 Any proper list structure, with optional surrounding whitespace. In case of improper list structure, 0 is returned and the \fIvarname\fR will contain the index of the .QW element where the list parsing fails, or \-1 if this cannot be determined. .IP \fBlower\fR 12 Any Unicode lower case alphabet character. .IP \fBprint\fR 12 Any Unicode printing character, including space. .IP \fBpunct\fR 12 Any Unicode punctuation character. .IP \fBspace\fR 12 Any Unicode whitespace character, mongolian vowel separator (U+180e), zero width space (U+200b), word joiner (U+2060) or zero width no-break space (U+feff) (=BOM). .IP \fBtrue\fR 12 Any of the forms allowed to \fBTcl_GetBoolean\fR where the value is true. .IP \fBupper\fR 12 Any upper case alphabet character in the Unicode character set. .IP \fBwideinteger\fR 12 Any of the valid forms for a wide integer in Tcl, with optional surrounding whitespace. In case of under/overflow in the value, 0 is returned and the \fIvarname\fR will contain \-1. .IP \fBwordchar\fR 12 Any Unicode word character. That is any alphanumeric character, and any Unicode connector punctuation characters (e.g. underscore). .IP \fBxdigit\fR 12 Any hexadecimal digit character ([0\-9A\-Fa\-f]). .PP In the case of \fBboolean\fR, \fBtrue\fR and \fBfalse\fR, if the function will return 0, then the \fIvarname\fR will always be set to 0, due to the varied nature of a valid boolean value. .RE .TP \fBstring last \fIneedleString haystackString\fR ?\fIlastIndex\fR? . Search \fIhaystackString\fR for a sequence of characters that exactly match the characters in \fIneedleString\fR. If found, return the index of the first character in the last such match within \fIhaystackString\fR. If there is no match, then return \-1. If \fIlastIndex\fR is specified (in any of the forms described in \fBSTRING INDICES\fR), then only the characters in \fIhaystackString\fR at or before the specified \fIlastIndex\fR will be considered by the search. For example, .RS .PP .CS \fBstring last a 0a23456789abcdef 15\fR .CE .PP will return \fB10\fR, but .PP .CS \fBstring last a 0a23456789abcdef 9\fR .CE .PP will return \fB1\fR. .RE .TP \fBstring length \fIstring\fR . Returns a decimal string giving the number of characters in \fIstring\fR. Note that this is not necessarily the same as the number of bytes used to store the string. If the value is a byte array value (such as those returned from reading a binary encoded channel), then this will return the actual byte length of the value. .TP \fBstring map\fR ?\fB\-nocase\fR? \fImapping string\fR . Replaces substrings in \fIstring\fR based on the key-value pairs in \fImapping\fR. \fImapping\fR is a list of \fIkey value key value ...\fR as in the form returned by \fBarray get\fR. Each instance of a key in the string will be replaced with its corresponding value. If \fB\-nocase\fR is specified, then matching is done without regard to case differences. Both \fIkey\fR and \fIvalue\fR may be multiple characters. Replacement is done in an ordered manner, so the key appearing first in the list will be checked first, and so on. \fIstring\fR is only iterated over once, so earlier key replacements will have no affect for later key matches. For example, .RS .PP .CS \fBstring map {abc 1 ab 2 a 3 1 0} 1abcaababcabababc\fR .CE .PP will return the string \fB01321221\fR. .PP Note that if an earlier \fIkey\fR is a prefix of a later one, it will completely mask the later one. So if the previous example is reordered like this, .PP .CS \fBstring map {1 0 ab 2 a 3 abc 1} 1abcaababcabababc\fR .CE .PP it will return the string \fB02c322c222c\fR. .RE .TP \fBstring match\fR ?\fB\-nocase\fR? \fIpattern\fR \fIstring\fR . See if \fIpattern\fR matches \fIstring\fR; return 1 if it does, 0 if it does not. If \fB\-nocase\fR is specified, then the pattern attempts to match against the string in a case insensitive manner. For the two strings to match, their contents must be identical except that the following special sequences may appear in \fIpattern\fR: .RS .IP \fB*\fR 10 Matches any sequence of characters in \fIstring\fR, including a null string. .IP \fB?\fR 10 Matches any single character in \fIstring\fR. .IP \fB[\fIchars\fB]\fR 10 Matches any character in the set given by \fIchars\fR. If a sequence of the form \fIx\fB\-\fIy\fR appears in \fIchars\fR, then any character between \fIx\fR and \fIy\fR, inclusive, will match. When used with \fB\-nocase\fR, the end points of the range are converted to lower case first. Whereas {[A\-z]} matches .QW _ when matching case-sensitively (since .QW _ falls between the .QW Z and .QW a ), with \fB\-nocase\fR this is considered like {[A\-Za\-z]} (and probably what was meant in the first place). .IP \fB\e\fIx\fR 10 Matches the single character \fIx\fR. This provides a way of avoiding the special interpretation of the characters \fB*?[]\e\fR in \fIpattern\fR. .RE .TP \fBstring range \fIstring first last\fR . Returns a range of consecutive characters from \fIstring\fR, starting with the character whose index is \fIfirst\fR and ending with the character whose index is \fIlast\fR. An index of 0 refers to the first character of the string. \fIfirst\fR and \fIlast\fR may be specified as for the \fBindex\fR method. If \fIfirst\fR is less than zero then it is treated as if it were zero, and if \fIlast\fR is greater than or equal to the length of the string then it is treated as if it were \fBend\fR. If \fIfirst\fR is greater than \fIlast\fR then an empty string is returned. .TP \fBstring repeat \fIstring count\fR . Returns \fIstring\fR repeated \fIcount\fR number of times. .TP \fBstring replace \fIstring first last\fR ?\fInewstring\fR? . Removes a range of consecutive characters from \fIstring\fR, starting with the character whose index is \fIfirst\fR and ending with the character whose index is \fIlast\fR. An index of 0 refers to the first character of the string. \fIFirst\fR and \fIlast\fR may be specified as for the \fBindex\fR method. If \fInewstring\fR is specified, then it is placed in the removed character range. If \fIfirst\fR is less than zero then it is treated as if it were zero, and if \fIlast\fR is greater than or equal to the length of the string then it is treated as if it were \fBend\fR. If \fIfirst\fR is greater than \fIlast\fR or the length of the initial string, or \fIlast\fR is less than 0, then the initial string is returned untouched. .TP \fBstring reverse \fIstring\fR . Returns a string that is the same length as \fIstring\fR but with its characters in the reverse order. .TP \fBstring tolower \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR? . Returns a value equal to \fIstring\fR except that all upper (or title) case letters have been converted to lower case. If \fIfirst\fR is specified, it refers to the first char index in the string to start modifying. If \fIlast\fR is specified, it refers to the char index in the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be specified using the forms described in \fBSTRING INDICES\fR. .TP \fBstring totitle \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR? . Returns a value equal to \fIstring\fR except that the first character in \fIstring\fR is converted to its Unicode title case variant (or upper case if there is no title case variant) and the rest of the string is converted to lower case. If \fIfirst\fR is specified, it refers to the first char index in the string to start modifying. If \fIlast\fR is specified, it refers to the char index in the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be specified using the forms described in \fBSTRING INDICES\fR. .TP \fBstring toupper \fIstring\fR ?\fIfirst\fR? ?\fIlast\fR? . Returns a value equal to \fIstring\fR except that all lower (or title) case letters have been converted to upper case. If \fIfirst\fR is specified, it refers to the first char index in the string to start modifying. If \fIlast\fR is specified, it refers to the char index in the string to stop at (inclusive). \fIfirst\fR and \fIlast\fR may be specified using the forms described in \fBSTRING INDICES\fR. .TP \fBstring trim \fIstring\fR ?\fIchars\fR? . Returns a value equal to \fIstring\fR except that any leading or trailing characters present in the string given by \fIchars\fR are removed. If \fIchars\fR is not specified then white space is removed (any character for which \fBstring is space\fR returns 1, and "\0"). .TP \fBstring trimleft \fIstring\fR ?\fIchars\fR? . Returns a value equal to \fIstring\fR except that any leading characters present in the string given by \fIchars\fR are removed. If \fIchars\fR is not specified then white space is removed (any character for which \fBstring is space\fR returns 1, and "\0"). .TP \fBstring trimright \fIstring\fR ?\fIchars\fR? . Returns a value equal to \fIstring\fR except that any trailing characters present in the string given by \fIchars\fR are removed. If \fIchars\fR is not specified then white space is removed (any character for which \fBstring is space\fR returns 1, and "\0"). .SS "OBSOLETE SUBCOMMANDS" .PP These subcommands are currently supported, but are likely to go away in a future release as their functionality is either virtually never used or highly misleading. .TP \fBstring bytelength \fIstring\fR . Returns a decimal string giving the number of bytes used to represent \fIstring\fR in memory when encoded as Tcl's internal modified UTF\-8; Tcl may use other encodings for \fIstring\fR as well, and does not guarantee to only use a single encoding for a particular \fIstring\fR. Because UTF\-8 uses a variable number of bytes to represent Unicode characters, the byte length will not be the same as the character length in general. The cases where a script cares about the byte length are rare. .RS .PP In almost all cases, you should use the \fBstring length\fR operation (including determining the length of a Tcl byte array value). Refer to the \fBTcl_NumUtfChars\fR manual entry for more details on the UTF\-8 representation. .PP 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 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 ever be used by Tcl's implementation, the number of bytes used to store the representation is of very low value (except to C extension code, which has direct access for the purpose of memory management, etc.) .PP \fICompatibility note:\fR it is likely that this subcommand will be withdrawn in a future version of Tcl. It is better to use the \fBencoding convertto\fR command to convert a string to a known encoding and then apply \fBstring length\fR to that. .PP .CS \fBstring length\fR [encoding convertto utf-8 $theString] .CE .RE .TP \fBstring wordend \fIstring charIndex\fR . Returns the index of the character just after the last one in the word containing character \fIcharIndex\fR of \fIstring\fR. \fIcharIndex\fR may be specified using the forms in \fBSTRING INDICES\fR. A word is considered to be any contiguous range of alphanumeric (Unicode letters or decimal digits) or underscore (Unicode connector punctuation) characters, or any single character other than these. .TP \fBstring wordstart \fIstring charIndex\fR . Returns the index of the first character in the word containing character \fIcharIndex\fR of \fIstring\fR. \fIcharIndex\fR may be specified using the forms in \fBSTRING INDICES\fR. A word is considered to be any contiguous range of alphanumeric (Unicode letters or decimal digits) or underscore (Unicode connector punctuation) characters, or any single character other than these. .SH "STRING INDICES" .PP When referring to indices into a string (e.g., for \fBstring index\fR or \fBstring range\fR) the following formats are supported: .IP \fIinteger\fR 10 For any index value that passes \fBstring is integer \-strict\fR, the char specified at this integral index (e.g., \fB2\fR would refer to the .QW c in .QW abcd ). .IP \fBend\fR 10 The last char of the string (e.g., \fBend\fR would refer to the .QW d in .QW abcd ). .IP \fBend\-\fIN\fR 10 The last char of the string minus the specified integer offset \fIN\fR (e.g., .QW \fBend\-1\fR would refer to the .QW c in .QW abcd ). .IP \fBend+\fIN\fR 10 The last char of the string plus the specified integer offset \fIN\fR (e.g., .QW \fBend+\-1\fR would refer to the .QW c in .QW abcd ). .IP \fIM\fB+\fIN\fR 10 The char specified at the integral index that is the sum of integer values \fIM\fR and \fIN\fR (e.g., .QW \fB1+1\fR would refer to the .QW c in .QW abcd ). .IP \fIM\fB\-\fIN\fR 10 The char specified at the integral index that is the difference of integer values \fIM\fR and \fIN\fR (e.g., .QW \fB2\-1\fR would refer to the .QW b in .QW abcd ). .PP In the specifications above, the integer value \fIM\fR contains no trailing whitespace and the integer value \fIN\fR contains no leading whitespace. .SH EXAMPLE .PP Test if the string in the variable \fIstring\fR is a proper non-empty prefix of the string \fBfoobar\fR. .PP .CS set length [\fBstring length\fR $string] if {$length == 0} { set isPrefix 0 } else { set isPrefix [\fBstring equal\fR \-length $length $string "foobar"] } .CE .SH "SEE ALSO" expr(n), list(n) .SH KEYWORDS case conversion, compare, index, match, pattern, string, word, equal, ctype, character, reverse .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/TclZlib.30000644000175000017500000003054312663660065013770 0ustar sergeisergei'\" '\" Copyright (c) 2008 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH TclZlib 3 8.6 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_ZlibAdler32, Tcl_ZlibCRC32, Tcl_ZlibDeflate, Tcl_ZlibInflate, Tcl_ZlibStreamChecksum, Tcl_ZlibStreamClose, Tcl_ZlibStreamEof, Tcl_ZlibStreamGet, Tcl_ZlibStreamGetCommandName, Tcl_ZlibStreamInit, Tcl_ZlibStreamPut \- compression and decompression functions .SH SYNOPSIS .nf #include .sp int \fBTcl_ZlibDeflate\fR(\fIinterp, format, dataObj, level, dictObj\fR) .sp int \fBTcl_ZlibInflate\fR(\fIinterp, format, dataObj, dictObj\fR) .sp unsigned int \fBTcl_ZlibCRC32\fR(\fIinitValue, bytes, length\fR) .sp unsigned int \fBTcl_ZlibAdler32\fR(\fIinitValue, bytes, length\fR) .sp int \fBTcl_ZlibStreamInit\fR(\fIinterp, mode, format, level, dictObj, zshandlePtr\fR) .sp Tcl_Obj * \fBTcl_ZlibStreamGetCommandName\fR(\fIzshandle\fR) .sp int \fBTcl_ZlibStreamEof\fR(\fIzshandle\fR) .sp int \fBTcl_ZlibStreamClose\fR(\fIzshandle\fR) .sp int \fBTcl_ZlibStreamReset\fR(\fIzshandle\fR) .sp int \fBTcl_ZlibStreamChecksum\fR(\fIzshandle\fR) .sp int \fBTcl_ZlibStreamPut\fR(\fIzshandle, dataObj, flush\fR) .sp int \fBTcl_ZlibStreamGet\fR(\fIzshandle, dataObj, count\fR) .sp \fBTcl_ZlibStreamSetCompressionDictionary\fR(\fIzshandle, compDict\fR) .fi .SH ARGUMENTS .AS Tcl_ZlibStream zshandle in .AP Tcl_Interp *interp in The interpreter to store resulting compressed or uncompressed data in. Also where any error messages are written. For \fBTcl_ZlibStreamInit\fR, this can be NULL to create a stream that is not bound to a command. .AP int format in What format of compressed data to work with. Must be one of \fBTCL_ZLIB_FORMAT_ZLIB\fR for zlib-format data, \fBTCL_ZLIB_FORMAT_GZIP\fR for gzip-format data, or \fBTCL_ZLIB_FORMAT_RAW\fR for raw compressed data. In addition, for decompression only, \fBTCL_ZLIB_FORMAT_AUTO\fR may also be chosen which can automatically detect whether the compressed data was in zlib or gzip format. .AP Tcl_Obj *dataObj in/out A byte-array value containing the data to be compressed or decompressed, or to which the data extracted from the stream is appended when passed to \fBTcl_ZlibStreamGet\fR. .AP int level in What level of compression to use. Should be a number from 0 to 9 or one of the following: \fBTCL_ZLIB_COMPRESS_NONE\fR for no compression, \fBTCL_ZLIB_COMPRESS_FAST\fR for fast but inefficient compression, \fBTCL_ZLIB_COMPRESS_BEST\fR for slow but maximal compression, or \fBTCL_ZLIB_COMPRESS_DEFAULT\fR for the level recommended by the zlib library. .AP Tcl_Obj *dictObj in/out A dictionary that contains, or which will be updated to contain, a description of the gzip header associated with the compressed data. Only useful when the \fIformat\fR is \fBTCL_ZLIB_FORMAT_GZIP\fR or \fBTCL_ZLIB_FORMAT_AUTO\fR. If a NULL is passed, a default header will be used on compression and the header will be ignored (apart from integrity checks) on decompression. See the section \fBGZIP OPTIONS DICTIONARY\fR for details about the contents of this dictionary. .AP "unsigned int" initValue in The initial value for the checksum algorithm. .AP "unsigned char" *bytes in An array of bytes to run the checksum algorithm over, or NULL to get the recommended initial value for the checksum algorithm. .AP int length in The number of bytes in the array. .AP int mode in What mode to operate the stream in. Should be either \fBTCL_ZLIB_STREAM_DEFLATE\fR for a compressing stream or \fBTCL_ZLIB_STREAM_INFLATE\fR for a decompressing stream. .AP Tcl_ZlibStream *zshandlePtr out A pointer to a variable in which to write the abstract token for the stream upon successful creation. .AP Tcl_ZlibStream zshandle in The abstract token for the stream to operate on. .AP int flush in Whether and how to flush the stream after writing the data to it. Must be one of: \fBTCL_ZLIB_NO_FLUSH\fR if no flushing is to be done, \fBTCL_ZLIB_FLUSH\fR if the currently compressed data must be made available for access using \fBTcl_ZlibStreamGet\fR, \fBTCL_ZLIB_FULLFLUSH\fR if the stream must be put into a state where the decompressor can recover from on corruption, or \fBTCL_ZLIB_FINALIZE\fR to ensure that the stream is finished and that any trailer demanded by the format is written. .AP int count in The maximum number of bytes to get from the stream, or -1 to get all remaining bytes from the stream's buffers. .AP Tcl_Obj *compDict in A byte array value that is the compression dictionary to use with the stream. Note that this is \fInot a Tcl dictionary\fR, and it is recommended that this only ever be used with streams that were created with their \fIformat\fR set to \fBTCL_ZLIB_FORMAT_ZLIB\fR because the other formats have no mechanism to indicate whether a compression dictionary was present other than to fail on decompression. .BE .SH DESCRIPTION These functions form the interface from the Tcl library to the Zlib library by Jean-loup Gailly and Mark Adler. .PP \fBTcl_ZlibDeflate\fR and \fBTcl_ZlibInflate\fR respectively compress and decompress the data contained in the \fIdataObj\fR argument, according to the \fIformat\fR and, for compression, \fIlevel\fR arguments. The dictionary in the \fIdictObj\fR parameter is used to convey additional header information about the compressed data when the compression format supports it; currently, the dictionary is only used when the \fIformat\fR parameter is \fBTCL_ZLIB_FORMAT_GZIP\fR or \fBTCL_ZLIB_FORMAT_AUTO\fR. For details of the contents of the dictionary, see the \fBGZIP OPTIONS DICTIONARY\fR section below. Upon success, both functions leave the resulting compressed or decompressed data in a byte-array value that is the Tcl interpreter's result; the returned value is a standard Tcl result code. .PP \fBTcl_ZlibAdler32\fR and \fBTcl_ZlibCRC32\fR compute checksums on arrays of bytes, returning the computed checksum. Checksums are computed incrementally, allowing data to be processed one block at a time, but this requires the caller to maintain the current checksum and pass it in as the \fIinitValue\fR parameter; the initial value to use for this can be obtained by using NULL for the \fIbytes\fR parameter instead of a pointer to the array of bytes to compute the checksum over. Thus, typical usage in the single data block case is like this: .PP .CS checksum = \fBTcl_ZlibCRC32\fR(\fBTcl_ZlibCRC32\fR(0,NULL,0), data, length); .CE .PP Note that the Adler-32 algorithm is not a real checksum, but instead is a related type of hash that works best on longer data. .SS "ZLIB STREAMS" .PP \fBTcl_ZlibStreamInit\fR creates a compressing or decompressing stream that is linked to a Tcl command, according to its arguments, and provides an abstract token for the stream and returns a normal Tcl result code; \fBTcl_ZlibStreamGetCommandName\fR returns the name of that command given the stream token, or NULL if the stream has no command. Streams are not designed to be thread-safe; each stream should only ever be used from the thread that created it. When working with gzip streams, a dictionary (fields as given in the \fBGZIP OPTIONS DICTIONARY\fR section below) can be given via the \fIdictObj\fR parameter that on compression allows control over the generated headers, and on decompression allows discovery of the existing headers. Note that the dictionary will be written to on decompression once sufficient data has been read to have a complete header. This means that the dictionary must be an unshared value in that case; a blank value created with \fBTcl_NewObj\fR is suggested. .PP Once a stream has been constructed, \fBTcl_ZlibStreamPut\fR is used to add data to the stream and \fBTcl_ZlibStreamGet\fR is used to retrieve data from the stream after processing. Both return normal Tcl result codes and leave an error message in the result of the interpreter that the stream is registered with in the error case (if such a registration has been performed). With \fBTcl_ZlibStreamPut\fR, the data buffer value passed to it should not be modified afterwards. With \fBTcl_ZlibStreamGet\fR, the data buffer value passed to it will have the data bytes appended to it. Internally to the stream, data is kept compressed so as to minimize the cost of buffer space. .PP \fBTcl_ZlibStreamChecksum\fR returns the checksum computed over the uncompressed data according to the format, and \fBTcl_ZlibStreamEof\fR returns a boolean value indicating whether the end of the uncompressed data has been reached. .PP \fBTcl_ZlibStreamSetCompressionDictionary\fR is used to control the compression dictionary used with the stream, a compression dictionary being an array of bytes (such as might be created with \fBTcl_NewByteArrayObj\fR) that is used to initialize the compression engine rather than leaving it to create it on the fly from the data being compressed. Setting a compression dictionary allows for more efficient compression in the case where the start of the data is highly regular, but it does require both the compressor and the decompressor to agreee on the value to use. Compression dictionaries are only fully supported for zlib-format data; on compression, they must be set before any data is sent in with \fBTcl_ZlibStreamPut\fR, and on decompression they should be set when \fBTcl_ZlibStreamGet\fR produces an \fBerror\fR with its \fB\-errorcode\fR set to .QW "\fBZLIB NEED_DICT\fI code\fR" ; the \fIcode\fR will be the Adler-32 checksum (see \fBTcl_ZlibAdler32\fR) of the compression dictionary sought. (Note that this is only true for zlib-format streams; gzip streams ignore compression dictionaries as the format specification doesn't permit them, and raw streams just produce a data error if the compression dictionary is missing or incorrect.) .PP If you wish to clear a stream and reuse it for a new compression or decompression action, \fBTcl_ZlibStreamReset\fR will do this and return a normal Tcl result code to indicate whether it was successful; if the stream is registered with an interpreter, an error message will be left in the interpreter result when this function returns TCL_ERROR. Finally, \fBTcl_ZlibStreamClose\fR will clean up the stream and delete the associated command: using \fBTcl_DeleteCommand\fR on the stream's command is equivalent (when such a command exists). .SH "GZIP OPTIONS DICTIONARY" .PP The \fIdictObj\fR parameter to \fBTcl_ZlibDeflate\fR, \fBTcl_ZlibInflate\fR and \fBTcl_ZlibStreamInit\fR is used to pass a dictionary of options about that is used to describe the gzip header in the compressed data. When creating compressed data, the dictionary is read and when unpacking compressed data the dictionary is written (in which case the \fIdictObj\fR parameter must refer to an unshared dictionary value). .PP The following fields in the dictionary value are understood. All other fields are ignored. No field is required when creating a gzip-format stream. .TP \fBcomment\fR . This holds the comment field of the header, if present. If absent, no comment was supplied (on decompression) or will be created (on compression). .TP \fBcrc\fR . A boolean value describing whether a CRC of the header is computed. Note that the \fBgzip\fR program does \fInot\fR use or allow a CRC on the header. .TP \fBfilename\fR . The name of the file that held the uncompressed data. This should not contain any directory separators, and should be sanitized before use on decompression with \fBfile tail\fR. .TP \fBos\fR . The operating system type code field from the header (if not the .QW unknown value). See RFC 1952 for the meaning of these codes. On compression, if this is absent then the field will be set to the .QW unknown value. .TP \fBsize\fR . The size of the uncompressed data. This is ignored on compression; the size of the data compressed depends on how much data is supplied to the compression engine. .TP \fBtime\fR . The time field from the header if non-zero, expected to be the time that the file named by the \fBfilename\fR field was modified. Suitable for use with \fBclock format\fR. On creation, the right value to use is that from \fBclock seconds\fR or \fBfile mtime\fR. .TP \fBtype\fR . The type of the uncompressed data (either \fBbinary\fR or \fBtext\fR) if known. .SH "PORTABILITY NOTES" These functions will fail gracefully if Tcl is not linked with the zlib library. .SH "SEE ALSO" Tcl_NewByteArrayObj(3), zlib(n) '\"Tcl_StackChannel(3) .SH "KEYWORDS" compress, decompress, deflate, gzip, inflate '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/history.n0000644000175000017500000001014012663660065014210 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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 history n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME history \- Manipulate the history list .SH SYNOPSIS \fBhistory \fR?\fIoption\fR? ?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP The \fBhistory\fR command performs one of several operations related to recently-executed commands recorded in a history list. Each of these recorded commands is referred to as an .QW event . When specifying an event to the \fBhistory\fR command, the following forms may be used: .IP [1] A number: if positive, it refers to the event with that number (all events are numbered starting at 1). If the number is negative, it selects an event relative to the current event (\fB\-1\fR refers to the previous event, \fB\-2\fR to the one before that, and so on). Event \fB0\fR refers to the current event. .IP [2] A string: selects the most recent event that matches the string. An event is considered to match the string either if the string is the same as the first characters of the event, or if the string matches the event in the sense of the \fBstring match\fR command. .PP The \fBhistory\fR command can take any of the following forms: .TP \fBhistory\fR Same as \fBhistory info\fR, described below. .TP \fBhistory add\fI command \fR?\fBexec\fR? Adds the \fIcommand\fR argument to the history list as a new event. If \fBexec\fR is specified (or abbreviated) then the command is also executed and its result is returned. If \fBexec\fR is not specified then an empty string is returned as result. .TP \fBhistory change\fI newValue\fR ?\fIevent\fR? Replaces the value recorded for an event with \fInewValue\fR. \fIEvent\fR specifies the event to replace, and defaults to the \fIcurrent\fR event (not event \fB\-1\fR). This command is intended for use in commands that implement new forms of history substitution and wish to replace the current event (which invokes the substitution) with the command created through substitution. The return value is an empty string. .TP \fBhistory clear\fR Erase the history list. The current keep limit is retained. The history event numbers are reset. .TP \fBhistory event\fR ?\fIevent\fR? Returns the value of the event given by \fIevent\fR. \fIEvent\fR defaults to \fB\-1\fR. .TP \fBhistory info \fR?\fIcount\fR? Returns a formatted string (intended for humans to read) giving the event number and contents for each of the events in the history list except the current event. If \fIcount\fR is specified then only the most recent \fIcount\fR events are returned. .TP \fBhistory keep \fR?\fIcount\fR? This command may be used to change the size of the history list to \fIcount\fR events. Initially, 20 events are retained in the history list. If \fIcount\fR is not specified, the current keep limit is returned. .TP \fBhistory nextid\fR Returns the number of the next event to be recorded in the history list. It is useful for things like printing the event number in command-line prompts. .TP \fBhistory redo \fR?\fIevent\fR? Re-executes the command indicated by \fIevent\fR and returns its result. \fIEvent\fR defaults to \fB\-1\fR. This command results in history revision: see below for details. .SH "HISTORY REVISION" .PP Pre-8.0 Tcl had a complex history revision mechanism. The current mechanism is more limited, and the old history operations \fBsubstitute\fR and \fBwords\fR have been removed. (As a consolation, the \fBclear\fR operation was added.) .PP The history option \fBredo\fR results in much simpler .QW "history revision" . When this option is invoked then the most recent event is modified to eliminate the history command and replace it with the result of the history command. If you want to redo an event without modifying history, then use the \fBevent\fR operation to retrieve some event, and the \fBadd\fR operation to add it to history and execute it. .SH KEYWORDS event, history, record tcl8.6.5/doc/tell.n0000644000175000017500000000306412663660065013456 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 tell n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME tell \- Return current access position for an open channel .SH SYNOPSIS \fBtell \fIchannelId\fR .BE .SH DESCRIPTION .PP Returns an integer string giving the current access position in \fIchannelId\fR. This value returned is a byte offset that can be passed to \fBseek\fR in order to set the channel to a particular position. Note that this value is in terms of bytes, not characters like \fBread\fR. The value returned is -1 for channels that do not support seeking. .PP \fIChannelId\fR must be an identifier for an open channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. .SH EXAMPLE .PP Read a line from a file channel only if it starts with \fBfoobar\fR: .PP .CS # Save the offset in case we need to undo the read... set offset [\fBtell\fR $chan] if {[read $chan 6] eq "foobar"} { gets $chan line } else { set line {} # Undo the read... seek $chan $offset } .CE .SH "SEE ALSO" file(n), open(n), close(n), gets(n), seek(n), Tcl_StandardChannels(3) .SH KEYWORDS access position, channel, seeking tcl8.6.5/doc/load.n0000644000175000017500000001747312663660065013446 0ustar sergeisergei'\" '\" 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 load n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME 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 .br \fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName packageName 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 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. \fIinterp\fR is the path name of the interpreter into which to load the package (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 Once the file has been loaded into the application's address space, 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 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 converted to upper case and all other letters are converted to lower case. For example, if \fIpackageName\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 initializes the safe interpreter only with partial functionality provided by the package 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( 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 of the \fBload\fR command will be the result returned by the initialization procedure. .PP The actual loading of a file will only be done once for each \fIfileName\fR in an application. If a given \fIfileName\fR is loaded into multiple 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 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 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 \fBload libxyz4.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 be specified. The \fBload\fR command first searches for a statically loaded package (one that has been registered by calling the \fBTcl_StaticPackage\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 different files have been \fBload\fRed with different versions of the package, 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 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. .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 of the \fB\-global\fR or \fB\-lazy\fR option may lead to crashes in your application later (in case of symbol conflicts resp. missing symbols), which cannot be detected during the \fBload\fR. So, only use this when you know what you are doing, you will not get a nice error message when something is wrong with the loaded library. .SH "PORTABILITY ISSUES" .TP \fBWindows\fR\0\0\0\0\0 . When a load fails with .QW "library not found" error, it is also possible that a dependent library was not found. To see the dependent libraries, type .QW "dumpbin -imports " in a DOS console to see what the library must import. When loading a DLL in the current directory, Windows will ignore .QW ./ as a path specifier and use a search heuristic to find the DLL instead. To avoid this, load the DLL with: .RS .PP .CS \fBload\fR [file join [pwd] mylib.DLL] .CE .RE .SH BUGS .PP If the same file is \fBload\fRed by different \fIfileName\fRs, it will be loaded into the process's address space multiple times. The behavior of this varies from system to system (some systems may detect the redundant loads, others may not). .SH EXAMPLE .PP The following is a minimal extension: .PP .CS #include #include static int fooCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { printf("called with %d arguments\en", objc); return TCL_OK; } int Foo_Init(Tcl_Interp *interp) { if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { return TCL_ERROR; } printf("creating foo command"); Tcl_CreateObjCommand(interp, "foo", fooCmd, NULL, NULL); return TCL_OK; } .CE .PP When built into a shared/dynamic library with a suitable name (e.g. \fBfoo.dll\fR on Windows, \fBlibfoo.so\fR on Solaris and Linux) it can then be loaded into Tcl with the following: .PP .CS # Load the extension switch $tcl_platform(platform) { windows { \fBload\fR [file join [pwd] foo.dll] } unix { \fBload\fR [file join [pwd] libfoo[info sharedlibextension]] } } # Now execute the command defined by the extension foo .CE .SH "SEE ALSO" info sharedlibextension, package(n), Tcl_StaticPackage(3), safe(n) .SH KEYWORDS binary code, dynamic library, load, safe interpreter, shared library '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/CrtObjCmd.30000644000175000017500000003161112663660065014231 0ustar sergeisergei'\" '\" Copyright (c) 1996-1997 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_CreateObjCommand 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CreateObjCommand, Tcl_DeleteCommand, Tcl_DeleteCommandFromToken, Tcl_GetCommandInfo, Tcl_GetCommandInfoFromToken, Tcl_SetCommandInfo, Tcl_SetCommandInfoFromToken, Tcl_GetCommandName, Tcl_GetCommandFullName, Tcl_GetCommandFromObj \- implement new commands in C .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Command \fBTcl_CreateObjCommand\fR(\fIinterp, cmdName, proc, clientData, deleteProc\fR) .sp int \fBTcl_DeleteCommand\fR(\fIinterp, cmdName\fR) .sp int \fBTcl_DeleteCommandFromToken\fR(\fIinterp, token\fR) .sp int \fBTcl_GetCommandInfo\fR(\fIinterp, cmdName, infoPtr\fR) .sp int \fBTcl_SetCommandInfo\fR(\fIinterp, cmdName, infoPtr\fR) .sp int \fBTcl_GetCommandInfoFromToken\fR(\fItoken, infoPtr\fR) .sp int \fBTcl_SetCommandInfoFromToken\fR(\fItoken, infoPtr\fR) .sp const char * \fBTcl_GetCommandName\fR(\fIinterp, token\fR) .sp void \fBTcl_GetCommandFullName\fR(\fIinterp, token, objPtr\fR) .sp Tcl_Command \fBTcl_GetCommandFromObj\fR(\fIinterp, objPtr\fR) .SH ARGUMENTS .AS Tcl_CmdDeleteProc *deleteProc in/out .AP Tcl_Interp *interp in Interpreter in which to create a new command or that contains a command. .AP char *cmdName in Name of command. .AP Tcl_ObjCmdProc *proc in Implementation of the new command: \fIproc\fR will be called whenever \fIcmdName\fR is invoked as a command. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR and \fIdeleteProc\fR. .AP Tcl_CmdDeleteProc *deleteProc in Procedure to call before \fIcmdName\fR is deleted from the interpreter; allows for command-specific cleanup. If NULL, then no procedure is called before the command is deleted. .AP Tcl_Command token in Token for command, returned by previous call to \fBTcl_CreateObjCommand\fR. The command must not have been deleted. .AP Tcl_CmdInfo *infoPtr in/out Pointer to structure containing various information about a Tcl command. .AP Tcl_Obj *objPtr in Value containing the name of a Tcl command. .BE .SH DESCRIPTION .PP \fBTcl_CreateObjCommand\fR defines a new command in \fIinterp\fR and associates it with procedure \fIproc\fR such that whenever \fIname\fR is invoked as a Tcl command (e.g., via a call to \fBTcl_EvalObjEx\fR) the Tcl interpreter will call \fIproc\fR to process the command. .PP \fBTcl_CreateObjCommand\fR deletes any existing command \fIname\fR already associated with the interpreter (however see below for an exception where the existing command is not deleted). It returns a token that may be used to refer to the command in subsequent calls to \fBTcl_GetCommandName\fR. If \fIname\fR contains any \fB::\fR namespace qualifiers, then the command is added to the specified namespace; otherwise the command is added to the global namespace. If \fBTcl_CreateObjCommand\fR is called for an interpreter that is in the process of being deleted, then it does not create a new command and it returns NULL. \fIproc\fR should have arguments and result that match the type \fBTcl_ObjCmdProc\fR: .PP .CS typedef int \fBTcl_ObjCmdProc\fR( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR, int \fIobjc\fR, Tcl_Obj *const \fIobjv\fR[]); .CE .PP When \fIproc\fR is invoked, the \fIclientData\fR and \fIinterp\fR parameters will be copies of the \fIclientData\fR and \fIinterp\fR arguments given to \fBTcl_CreateObjCommand\fR. Typically, \fIclientData\fR points to an application-specific data structure that describes what to do when the command procedure is invoked. \fIObjc\fR and \fIobjv\fR describe the arguments to the command, \fIobjc\fR giving the number of argument values (including the command name) and \fIobjv\fR giving the values of the arguments. The \fIobjv\fR array will contain \fIobjc\fR values, pointing to the argument values. Unlike \fIargv\fR[\fIargv\fR] used in a string-based command procedure, \fIobjv\fR[\fIobjc\fR] will not contain NULL. .PP Additionally, when \fIproc\fR is invoked, it must not modify the contents of the \fIobjv\fR array by assigning new pointer values to any element of the array (for example, \fIobjv\fR[\fB2\fR] = \fBNULL\fR) because this will cause memory to be lost and the runtime stack to be corrupted. The \fBconst\fR in the declaration of \fIobjv\fR will cause ANSI-compliant compilers to report any such attempted assignment as an error. However, it is acceptable to modify the internal representation of any individual value argument. For instance, the user may call \fBTcl_GetIntFromObj\fR on \fIobjv\fR[\fB2\fR] to obtain the integer representation of that value; that call may change the type of the value that \fIobjv\fR[\fB2\fR] points at, but will not change where \fIobjv\fR[\fB2\fR] points. .PP \fIproc\fR must return an integer code that is either \fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR. See the Tcl overview man page for details on what these codes mean. Most normal commands will only return \fBTCL_OK\fR or \fBTCL_ERROR\fR. In addition, if \fIproc\fR needs to return a non-empty result, it can call \fBTcl_SetObjResult\fR to set the interpreter's result. In the case of a \fBTCL_OK\fR return code this gives the result of the command, and in the case of \fBTCL_ERROR\fR this gives an error message. Before invoking a command procedure, \fBTcl_EvalObjEx\fR sets interpreter's result to point to a value representing an empty string, so simple commands can return an empty result by doing nothing at all. .PP The contents of the \fIobjv\fR array belong to Tcl and are not guaranteed to persist once \fIproc\fR returns: \fIproc\fR should not modify them. Call \fBTcl_SetObjResult\fR if you want to return something from the \fIobjv\fR array. .PP Ordinarily, \fBTcl_CreateObjCommand\fR deletes any existing command \fIname\fR already associated with the interpreter. However, if the existing command was created by a previous call to \fBTcl_CreateCommand\fR, \fBTcl_CreateObjCommand\fR does not delete the command but instead arranges for the Tcl interpreter to call the \fBTcl_ObjCmdProc\fR \fIproc\fR in the future. The old string-based \fBTcl_CmdProc\fR associated with the command is retained and its address can be obtained by subsequent \fBTcl_GetCommandInfo\fR calls. This is done for backwards compatibility. .PP \fIDeleteProc\fR will be invoked when (if) \fIname\fR is deleted. This can occur through a call to \fBTcl_DeleteCommand\fR, \fBTcl_DeleteCommandFromToken\fR, or \fBTcl_DeleteInterp\fR, or by replacing \fIname\fR in another call to \fBTcl_CreateObjCommand\fR. \fIDeleteProc\fR is invoked before the command is deleted, and gives the application an opportunity to release any structures associated with the command. \fIDeleteProc\fR should have arguments and result that match the type \fBTcl_CmdDeleteProc\fR: .PP .CS typedef void \fBTcl_CmdDeleteProc\fR( ClientData \fIclientData\fR); .CE .PP The \fIclientData\fR argument will be the same as the \fIclientData\fR argument passed to \fBTcl_CreateObjCommand\fR. .PP \fBTcl_DeleteCommand\fR deletes a command from a command interpreter. Once the call completes, attempts to invoke \fIcmdName\fR in \fIinterp\fR will result in errors. If \fIcmdName\fR is not bound as a command in \fIinterp\fR then \fBTcl_DeleteCommand\fR does nothing and returns -1; otherwise it returns 0. There are no restrictions on \fIcmdName\fR: it may refer to a built-in command, an application-specific command, or a Tcl procedure. If \fIname\fR contains any \fB::\fR namespace qualifiers, the command is deleted from the specified namespace. .PP Given a token returned by \fBTcl_CreateObjCommand\fR, \fBTcl_DeleteCommandFromToken\fR deletes the command from a command interpreter. It will delete a command even if that command has been renamed. Once the call completes, attempts to invoke the command in \fIinterp\fR will result in errors. If the command corresponding to \fItoken\fR has already been deleted from \fIinterp\fR then \fBTcl_DeleteCommand\fR does nothing and returns -1; otherwise it returns 0. .PP \fBTcl_GetCommandInfo\fR checks to see whether its \fIcmdName\fR argument exists as a command in \fIinterp\fR. \fIcmdName\fR may include \fB::\fR namespace qualifiers to identify a command in a particular namespace. If the command is not found, then it returns 0. Otherwise it places information about the command in the \fBTcl_CmdInfo\fR structure pointed to by \fIinfoPtr\fR and returns 1. A \fBTcl_CmdInfo\fR structure has the following fields: .PP .CS typedef struct Tcl_CmdInfo { int \fIisNativeObjectProc\fR; Tcl_ObjCmdProc *\fIobjProc\fR; ClientData \fIobjClientData\fR; Tcl_CmdProc *\fIproc\fR; ClientData \fIclientData\fR; Tcl_CmdDeleteProc *\fIdeleteProc\fR; ClientData \fIdeleteData\fR; Tcl_Namespace *\fInamespacePtr\fR; } \fBTcl_CmdInfo\fR; .CE .PP The \fIisNativeObjectProc\fR field has the value 1 if \fBTcl_CreateObjCommand\fR was called to register the command; it is 0 if only \fBTcl_CreateCommand\fR was called. It allows a program to determine whether it is faster to call \fIobjProc\fR or \fIproc\fR: \fIobjProc\fR is normally faster if \fIisNativeObjectProc\fR has the value 1. The fields \fIobjProc\fR and \fIobjClientData\fR have the same meaning as the \fIproc\fR and \fIclientData\fR arguments to \fBTcl_CreateObjCommand\fR; they hold information about the value-based command procedure that the Tcl interpreter calls to implement the command. The fields \fIproc\fR and \fIclientData\fR hold information about the string-based command procedure that implements the command. If \fBTcl_CreateCommand\fR was called for this command, this is the procedure passed to it; otherwise, this is a compatibility procedure registered by \fBTcl_CreateObjCommand\fR that simply calls the command's value-based procedure after converting its string arguments to Tcl values. The field \fIdeleteData\fR is the ClientData value to pass to \fIdeleteProc\fR; it is normally the same as \fIclientData\fR but may be set independently using the \fBTcl_SetCommandInfo\fR procedure. The field \fInamespacePtr\fR holds a pointer to the Tcl_Namespace that contains the command. .PP \fBTcl_GetCommandInfoFromToken\fR is identical to \fBTcl_GetCommandInfo\fR except that it uses a command token returned from \fBTcl_CreateObjCommand\fR in place of the command name. If the \fItoken\fR parameter is NULL, it returns 0; otherwise, it returns 1 and fills in the structure designated by \fIinfoPtr\fR. .PP \fBTcl_SetCommandInfo\fR is used to modify the procedures and ClientData values associated with a command. Its \fIcmdName\fR argument is the name of a command in \fIinterp\fR. \fIcmdName\fR may include \fB::\fR namespace qualifiers to identify a command in a particular namespace. If this command does not exist then \fBTcl_SetCommandInfo\fR returns 0. Otherwise, it copies the information from \fI*infoPtr\fR to Tcl's internal structure for the command and returns 1. .PP \fBTcl_SetCommandInfoFromToken\fR is identical to \fBTcl_SetCommandInfo\fR except that it takes a command token as returned by \fBTcl_CreateObjCommand\fR instead of the command name. If the \fItoken\fR parameter is NULL, it returns 0. Otherwise, it copies the information from \fI*infoPtr\fR to Tcl's internal structure for the command and returns 1. .PP Note that \fBTcl_SetCommandInfo\fR and \fBTcl_SetCommandInfoFromToken\fR both allow the ClientData for a command's deletion procedure to be given a different value than the ClientData for its command procedure. .PP Note that neither \fBTcl_SetCommandInfo\fR nor \fBTcl_SetCommandInfoFromToken\fR will change a command's namespace. Use \fBTcl_Eval\fR to call the \fBrename\fR command to do that. .PP \fBTcl_GetCommandName\fR provides a mechanism for tracking commands that have been renamed. Given a token returned by \fBTcl_CreateObjCommand\fR when the command was created, \fBTcl_GetCommandName\fR returns the string name of the command. If the command has been renamed since it was created, then \fBTcl_GetCommandName\fR returns the current name. This name does not include any \fB::\fR namespace qualifiers. The command corresponding to \fItoken\fR must not have been deleted. The string returned by \fBTcl_GetCommandName\fR is in dynamic memory owned by Tcl and is only guaranteed to retain its value as long as the command is not deleted or renamed; callers should copy the string if they need to keep it for a long time. .PP \fBTcl_GetCommandFullName\fR produces the fully qualified name of a command from a command token. The name, including all namespace prefixes, is appended to the value specified by \fIobjPtr\fR. .PP \fBTcl_GetCommandFromObj\fR returns a token for the command specified by the name in a \fBTcl_Obj\fR. The command name is resolved relative to the current namespace. Returns NULL if the command is not found. .SH "SEE ALSO" Tcl_CreateCommand(3), Tcl_ResetResult(3), Tcl_SetObjResult(3) .SH KEYWORDS bind, command, create, delete, namespace, value tcl8.6.5/doc/exec.n0000644000175000017500000003707412663660065013452 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2006 Donal K. Fellows. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH exec n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME exec \- Invoke subprocesses .SH SYNOPSIS \fBexec \fR?\fIswitches\fR? \fIarg \fR?\fIarg ...\fR? ?\fB&\fR? .BE .SH DESCRIPTION .PP This command treats its arguments as the specification 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. .PP If the initial arguments to \fBexec\fR start with \fB\-\fR then they are treated as command-line switches and are not part of the pipeline specification. The following switches are currently supported: .TP 13 \fB\-ignorestderr\fR . Stops the \fBexec\fR command from treating the output of messages to the pipeline's standard error channel as an error case. .TP 13 \fB\-keepnewline\fR . Retains a trailing newline in the pipeline's output. Normally a trailing newline will be deleted. .TP 13 \fB\-\|\-\fR . Marks the end of switches. The argument following this one will be treated as the first \fIarg\fR even if it starts with a \fB\-\fR. .PP If an \fIarg\fR (or pair of \fIarg\fRs) has one of the forms described below then it is used by \fBexec\fR to control the flow of input and output among the subprocess(es). Such arguments will not be passed to the subprocess(es). In forms such as .QW "\fB<\fR \fIfileName\fR" , \fIfileName\fR may either be in a separate argument from .QW \fB<\fR or in the same argument with no intervening space (i.e. .QW \fB<\fIfileName\fR ). .TP 15 \fB|\fR . Separates distinct commands in the pipeline. The standard output of the preceding command will be piped into the standard input of the next command. .TP 15 \fB|&\fR . Separates distinct commands in the pipeline. Both standard output and standard error of the preceding command will be piped into the standard input of the next command. This form of redirection overrides forms such as 2> and >&. .TP 15 \fB<\0\fIfileName\fR . The file named by \fIfileName\fR is opened and used as the standard input for the first command in the pipeline. .TP 15 \fB<@\0\fIfileId\fR . \fIFileId\fR must be the identifier for an open file, such as the return value from a previous call to \fBopen\fR. It is used as the standard input for the first command in the pipeline. \fIFileId\fR must have been opened for reading. .TP 15 \fB<<\0\fIvalue\fR . \fIValue\fR is passed to the first command as its standard input. .TP 15 \fB>\0\fIfileName\fR . Standard output from the last command is redirected to the file named \fIfileName\fR, overwriting its previous contents. .TP 15 \fB2>\0\fIfileName\fR . Standard error from all commands in the pipeline is redirected to the file named \fIfileName\fR, overwriting its previous contents. .TP 15 \fB>&\0\fIfileName\fR . Both standard output from the last command and standard error from all commands are redirected to the file named \fIfileName\fR, overwriting its previous contents. .TP 15 \fB>>\0\fIfileName\fR . Standard output from the last command is redirected to the file named \fIfileName\fR, appending to it rather than overwriting it. .TP 15 \fB2>>\0\fIfileName\fR . Standard error from all commands in the pipeline is redirected to the file named \fIfileName\fR, appending to it rather than overwriting it. .TP 15 \fB>>&\0\fIfileName\fR . Both standard output from the last command and standard error from all commands are redirected to the file named \fIfileName\fR, appending to it rather than overwriting it. .TP 15 \fB>@\0\fIfileId\fR . \fIFileId\fR must be the identifier for an open file, such as the return value from a previous call to \fBopen\fR. Standard output from the last command is redirected to \fIfileId\fR's file, which must have been opened for writing. .TP 15 \fB2>@\0\fIfileId\fR . \fIFileId\fR must be the identifier for an open file, such as the return value from a previous call to \fBopen\fR. Standard error from all commands in the pipeline is redirected to \fIfileId\fR's file. The file must have been opened for writing. .TP 15 \fB2>@1\0\fR . Standard error from all commands in the pipeline is redirected to the command result. This operator is only valid at the end of the command pipeline. .TP 15 \fB>&@\0\fIfileId\fR . \fIFileId\fR must be the identifier for an open file, such as the return value from a previous call to \fBopen\fR. Both standard output from the last command and standard error from all commands are redirected to \fIfileId\fR's file. The file must have been opened for writing. .PP If standard output has not been redirected then the \fBexec\fR command returns the standard output from the last command in the pipeline, unless .QW 2>@1 was specified, in which case standard error is included as well. If any of the commands in the pipeline exit abnormally or are killed or suspended, then \fBexec\fR will return an error and the error message will include the pipeline's output followed by error messages describing the abnormal terminations; the \fB\-errorcode\fR return option will contain additional information about the last abnormal termination encountered. If any of the commands writes to its standard error file and that standard error is not redirected and \fB\-ignorestderr\fR is not specified, then \fBexec\fR will return an error; the error message will include the pipeline's standard output, followed by messages about abnormal terminations (if any), followed by the standard error output. .PP If the last character of the result or error message is a newline then that character is normally deleted from the result or error message. This is consistent with other Tcl return values, which do not normally end with newlines. However, if \fB\-keepnewline\fR is specified then the trailing newline is retained. .PP If standard input is not redirected with .QW < , .QW << or .QW <@ then the standard input for the first command in the pipeline is taken from the application's current standard input. .PP If the last \fIarg\fR is .QW & then the pipeline will be executed in background. In this case the \fBexec\fR command will return a list whose elements are the process identifiers for all of the subprocesses in the pipeline. The standard output from the last command in the pipeline will go to the application's standard output if it has not been redirected, and error output from all of the commands in the pipeline will go to the application's standard error file unless redirected. .PP The first word in each command is taken as the command name; tilde-substitution is performed on it, and if the result contains no slashes then the directories in the PATH environment variable are searched for an executable by the given name. If the name contains a slash then it must refer to an executable reachable from the current directory. No .QW glob expansion or other shell-like substitutions are performed on the arguments to commands. .SH "PORTABILITY ISSUES" .TP \fBWindows\fR (all versions) . Reading from or writing to a socket, using the .QW \fB@\0\fIfileId\fR notation, does not work. When reading from a socket, a 16-bit DOS application will hang and a 32-bit application will return immediately with end-of-file. When either type of application writes to a socket, the information is instead sent to the console, if one is present, or is discarded. .RS .PP The Tk console text widget does not provide real standard IO capabilities. Under Tk, when redirecting from standard input, all applications will see an immediate end-of-file; information redirected to standard output or standard error will be discarded. .PP Either forward or backward slashes are accepted as path separators for arguments to Tcl commands. When executing an application, the path name specified for the application may also contain forward or backward slashes as path separators. Bear in mind, however, that most Windows applications accept arguments with forward slashes only as option delimiters and backslashes only in paths. Any arguments to an application that specify a path name with forward slashes will not automatically be converted to use the backslash character. If an argument contains forward slashes as the path separator, it may or may not be recognized as a path name, depending on the program. .PP Additionally, when calling a 16-bit DOS or Windows 3.X application, all path names must use the short, cryptic, path format (e.g., using .QW applba~1.def instead of .QW applbakery.default ), which can be obtained with the .QW "\fBfile attributes\fI fileName \fB\-shortname\fR" command. .PP Two or more forward or backward slashes in a row in a path refer to a network path. For example, a simple concatenation of the root directory \fBc:/\fR with a subdirectory \fB/windows/system\fR will yield \fBc://windows/system\fR (two slashes together), which refers to the mount point called \fBsystem\fR on the machine called \fBwindows\fR (and the \fBc:/\fR is ignored), and is not equivalent to \fBc:/windows/system\fR, which describes a directory on the current computer. The \fBfile join\fR command should be used to concatenate path components. .PP Note that there are two general types of Win32 console applications: .RS .IP [1] CLI \(em CommandLine Interface, simple stdio exchange. \fBnetstat.exe\fR for example. .IP [2] TUI \(em Textmode User Interface, any application that accesses the console API for doing such things as cursor movement, setting text color, detecting key presses and mouse movement, etc. An example would be \fBtelnet.exe\fR from Windows 2000. These types of applications are not common in a windows environment, but do exist. .RE .PP \fBexec\fR will not work well with TUI applications when a console is not present, as is done when launching applications under wish. It is desirable to have console applications hidden and detached. This is a designed-in limitation as \fBexec\fR wants to communicate over pipes. The Expect extension addresses this issue when communicating with a TUI application. .PP When attempting to execute an application, \fBexec\fR first searches for the name as it was specified. Then, in order, \fB.com\fR, \fB.exe\fR, and \fB.bat\fR are appended to the end of the specified name and it searches for the longer name. If a directory name was not specified as part of the application name, the following directories are automatically searched in order when attempting to locate the application: .IP \(bu 3 The directory from which the Tcl executable was loaded. .IP \(bu 3 The current directory. .IP \(bu 3 The Windows NT 32-bit system directory. .IP \(bu 3 The Windows NT 16-bit system directory. .IP \(bu 3 The Windows NT home directory. .IP \(bu 3 The directories listed in the path. .PP In order to execute shell built-in commands like \fBdir\fR and \fBcopy\fR, the caller must prepend the desired command with .QW "\fBcmd.exe /c\0\fR" because built-in commands are not implemented using executables. .RE .TP \fBUnix\fR (including Mac OS X) . The \fBexec\fR command is fully functional and works as described. .SH "UNIX EXAMPLES" .PP Here are some examples of the use of the \fBexec\fR command on Unix. To execute a simple program and get its result: .PP .CS \fBexec\fR uname -a .CE .SS "WORKING WITH NON-ZERO RESULTS" .PP To execute a program that can return a non-zero result, you should wrap the call to \fBexec\fR in \fBcatch\fR and check the contents of the \fB\-errorcode\fR return option if you have an error: .PP .CS set status 0 if {[catch {\fBexec\fR grep foo bar.txt} results options]} { set details [dict get $options -errorcode] if {[lindex $details 0] eq "CHILDSTATUS"} { set status [lindex $details 2] } else { # Some other error; regenerate it to let caller handle return -options $options -level 0 $results } } .CE .VS 8.6 .PP This is more easily written using the \fBtry\fR command, as that makes it simpler to trap specific types of errors. This is done using code like this: .PP .CS try { set results [\fBexec\fR grep foo bar.txt] set status 0 } trap CHILDSTATUS {results options} { set status [lindex [dict get $options -errorcode] 2] } .CE .VE 8.6 .SS "WORKING WITH QUOTED ARGUMENTS" .PP When translating a command from a Unix shell invocation, care should be taken over the fact that single quote characters have no special significance to Tcl. Thus: .PP .CS awk '{sum += $1} END {print sum}' numbers.list .CE .PP would be translated into something like: .PP .CS \fBexec\fR awk {{sum += $1} END {print sum}} numbers.list .CE .SS "WORKING WITH GLOBBING" .PP If you are converting invocations involving shell globbing, you should remember that Tcl does not handle globbing or expand things into multiple arguments by default. Instead you should write things like this: .PP .CS \fBexec\fR ls -l {*}[glob *.tcl] .CE .SS "WORKING WITH USER-SUPPLIED SHELL SCRIPT FRAGMENTS" .PP One useful technique can be to expose to users of a script the ability to specify a fragment of shell script to execute that will have some data passed in on standard input that was produced by the Tcl program. This is a common technique for using the \fIlpr\fR program for printing. By far the simplest way of doing this is to pass the user's script to the user's shell for processing, as this avoids a lot of complexity with parsing other languages. .PP .CS set lprScript [\fIget from user...\fR] set postscriptData [\fIgenerate somehow...\fR] \fBexec\fR $env(SHELL) -c $lprScript << $postscriptData .CE .SH "WINDOWS EXAMPLES" .PP Here are some examples of the use of the \fBexec\fR command on Windows. To start an instance of \fInotepad\fR editing a file without waiting for the user to finish editing the file: .PP .CS \fBexec\fR notepad myfile.txt & .CE .PP To print a text file using \fInotepad\fR: .PP .CS \fBexec\fR notepad /p myfile.txt .CE .SS "WORKING WITH CONSOLE PROGRAMS" .PP If a program calls other programs, such as is common with compilers, then you may need to resort to batch files to hide the console windows that sometimes pop up: .PP .CS \fBexec\fR cmp.bat somefile.c -o somefile .CE .PP With the file \fIcmp.bat\fR looking something like: .PP .CS @gcc %1 %2 %3 %4 %5 %6 %7 %8 %9 .CE .SS "WORKING WITH COMMAND BUILT-INS" .PP Sometimes you need to be careful, as different programs may have the same name and be in the path. It can then happen that typing a command at the DOS prompt finds \fIa different program\fR than the same command run via \fBexec\fR. This is because of the (documented) differences in behaviour between \fBexec\fR and DOS batch files. .PP When in doubt, use the command \fBauto_execok\fR: it will return the complete path to the program as seen by the \fBexec\fR command. This applies especially when you want to run .QW internal commands like \fIdir\fR from a Tcl script (if you just want to list filenames, use the \fBglob\fR command.) To do that, use this: .PP .CS \fBexec\fR {*}[auto_execok dir] *.tcl .CE .SS "WORKING WITH NATIVE FILENAMES" .PP Many programs on Windows require filename arguments to be passed in with backslashes as pathname separators. This is done with the help of the \fBfile nativename\fR command. For example, to make a directory (on NTFS) encrypted so that only the current user can access it requires use of the \fICIPHER\fR command, like this: .PP .CS set secureDir "~/Desktop/Secure Directory" file mkdir $secureDir \fBexec\fR CIPHER /e /s:[file nativename $secureDir] .CE .SH "SEE ALSO" error(n), file(n), open(n) .SH KEYWORDS execute, pipeline, redirection, subprocess '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/Environment.30000644000175000017500000000204712663660065014727 0ustar sergeisergei'\" '\" Copyright (c) 1997-1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_PutEnv 3 "7.5" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_PutEnv \- procedures to manipulate the environment .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_PutEnv\fR(\fIassignment\fR) .SH ARGUMENTS .AS "const char" *assignment .AP "const char" *assignment in Info about environment variable in the format .QW \fINAME\fB=\fIvalue\fR . The \fIassignment\fR argument is in the system encoding. .BE .SH DESCRIPTION .PP \fBTcl_PutEnv\fR sets an environment variable. The information is passed in a single string of the form .QW \fINAME\fB=\fIvalue\fR . This procedure is intended to be a stand-in for the UNIX \fBputenv\fR system call. All Tcl-based applications using \fBputenv\fR should redefine it to \fBTcl_PutEnv\fR so that they will interface properly to the Tcl runtime. .SH "SEE ALSO" env(n) .SH KEYWORDS environment, variable tcl8.6.5/doc/Hash.30000644000175000017500000003242612663660065013312 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_Hash 3 "" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_InitHashTable, Tcl_InitCustomHashTable, Tcl_InitObjHashTable, Tcl_DeleteHashTable, Tcl_CreateHashEntry, Tcl_DeleteHashEntry, Tcl_FindHashEntry, Tcl_GetHashValue, Tcl_SetHashValue, Tcl_GetHashKey, Tcl_FirstHashEntry, Tcl_NextHashEntry, Tcl_HashStats \- procedures to manage hash tables .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_InitHashTable\fR(\fItablePtr, keyType\fR) .sp \fBTcl_InitCustomHashTable\fR(\fItablePtr, keyType, typePtr\fR) .sp \fBTcl_InitObjHashTable\fR(\fItablePtr\fR) .sp \fBTcl_DeleteHashTable\fR(\fItablePtr\fR) .sp Tcl_HashEntry * \fBTcl_CreateHashEntry\fR(\fItablePtr, key, newPtr\fR) .sp \fBTcl_DeleteHashEntry\fR(\fIentryPtr\fR) .sp Tcl_HashEntry * \fBTcl_FindHashEntry\fR(\fItablePtr, key\fR) .sp ClientData \fBTcl_GetHashValue\fR(\fIentryPtr\fR) .sp \fBTcl_SetHashValue\fR(\fIentryPtr, value\fR) .sp void * \fBTcl_GetHashKey\fR(\fItablePtr, entryPtr\fR) .sp Tcl_HashEntry * \fBTcl_FirstHashEntry\fR(\fItablePtr, searchPtr\fR) .sp Tcl_HashEntry * \fBTcl_NextHashEntry\fR(\fIsearchPtr\fR) .sp char * \fBTcl_HashStats\fR(\fItablePtr\fR) .SH ARGUMENTS .AS "const Tcl_HashKeyType" *searchPtr out .AP Tcl_HashTable *tablePtr in Address of hash table structure (for all procedures but \fBTcl_InitHashTable\fR, this must have been initialized by previous call to \fBTcl_InitHashTable\fR). .AP int keyType in Kind of keys to use for new hash table. Must be either \fBTCL_STRING_KEYS\fR, \fBTCL_ONE_WORD_KEYS\fR, \fBTCL_CUSTOM_TYPE_KEYS\fR, \fBTCL_CUSTOM_PTR_KEYS\fR, or an integer value greater than 1. .AP Tcl_HashKeyType *typePtr in Address of structure which defines the behavior of the hash table. .AP "const void" *key in Key to use for probe into table. Exact form depends on \fIkeyType\fR used to create table. .AP int *newPtr out The word at \fI*newPtr\fR is set to 1 if a new entry was created and 0 if there was already an entry for \fIkey\fR. .AP Tcl_HashEntry *entryPtr in Pointer to hash table entry. .AP ClientData value in New value to assign to hash table entry. Need not have type ClientData, but must fit in same space as ClientData. .AP Tcl_HashSearch *searchPtr in Pointer to record to use to keep track of progress in enumerating all the entries in a hash table. .BE .SH DESCRIPTION .PP A hash table consists of zero or more entries, each consisting of a key and a value. Given the key for an entry, the hashing routines can very quickly locate the entry, and hence its value. There may be at most one entry in a hash table with a particular key, but many entries may have the same value. Keys can take one of four forms: strings, one-word values, integer arrays, or custom keys defined by a Tcl_HashKeyType structure (See section \fBTHE TCL_HASHKEYTYPE STRUCTURE\fR below). All of the keys in a given table have the same form, which is specified when the table is initialized. .PP The value of a hash table entry can be anything that fits in the same space as a .QW "char *" pointer. Values for hash table entries are managed entirely by clients, not by the hash module itself. Typically each entry's value is a pointer to a data structure managed by client code. .PP Hash tables grow gracefully as the number of entries increases, so that there are always less than three entries per hash bucket, on average. This allows for fast lookups regardless of the number of entries in a table. .PP The core provides three functions for the initialization of hash tables, Tcl_InitHashTable, Tcl_InitObjHashTable and Tcl_InitCustomHashTable. .PP \fBTcl_InitHashTable\fR initializes a structure that describes a new hash table. The space for the structure is provided by the caller, not by the hash module. The value of \fIkeyType\fR indicates what kinds of keys will be used for all entries in the table. All of the key types described later are allowed, with the exception of \fBTCL_CUSTOM_TYPE_KEYS\fR and \fBTCL_CUSTOM_PTR_KEYS\fR. .PP \fBTcl_InitObjHashTable\fR is a wrapper around \fBTcl_InitCustomHashTable\fR and initializes a hash table whose keys are Tcl_Obj *. .PP \fBTcl_InitCustomHashTable\fR initializes a structure that describes a new hash table. The space for the structure is provided by the caller, not by the hash module. The value of \fIkeyType\fR indicates what kinds of keys will be used for all entries in the table. \fIKeyType\fR must have one of the following values: .IP \fBTCL_STRING_KEYS\fR 25 Keys are null-terminated strings. They are passed to hashing routines using the address of the first character of the string. .IP \fBTCL_ONE_WORD_KEYS\fR 25 Keys are single-word values; they are passed to hashing routines and stored in hash table entries as .QW "char *" values. The pointer value is the key; it need not (and usually does not) actually point to a string. .IP \fBTCL_CUSTOM_TYPE_KEYS\fR 25 Keys are of arbitrary type, and are stored in the entry. Hashing and comparison is determined by \fItypePtr\fR. The Tcl_HashKeyType structure is described in the section \fBTHE TCL_HASHKEYTYPE STRUCTURE\fR below. .IP \fBTCL_CUSTOM_PTR_KEYS\fR 25 Keys are pointers to an arbitrary type, and are stored in the entry. Hashing and comparison is determined by \fItypePtr\fR. The Tcl_HashKeyType structure is described in the section \fBTHE TCL_HASHKEYTYPE STRUCTURE\fR below. .IP \fIother\fR 25 If \fIkeyType\fR is not one of the above, then it must be an integer value greater than 1. In this case the keys will be arrays of .QW int values, where \fIkeyType\fR gives the number of ints in each key. This allows structures to be used as keys. All keys must have the same size. Array keys are passed into hashing functions using the address of the first int in the array. .PP \fBTcl_DeleteHashTable\fR deletes all of the entries in a hash table and frees up the memory associated with the table's bucket array and entries. It does not free the actual table structure (pointed to by \fItablePtr\fR), since that memory is assumed to be managed by the client. \fBTcl_DeleteHashTable\fR also does not free or otherwise manipulate the values of the hash table entries. If the entry values point to dynamically-allocated memory, then it is the client's responsibility to free these structures before deleting the table. .PP \fBTcl_CreateHashEntry\fR locates the entry corresponding to a particular key, creating a new entry in the table if there was not already one with the given key. If an entry already existed with the given key then \fI*newPtr\fR is set to zero. If a new entry was created, then \fI*newPtr\fR is set to a non-zero value and the value of the new entry will be set to zero. The return value from \fBTcl_CreateHashEntry\fR is a pointer to the entry, which may be used to retrieve and modify the entry's value or to delete the entry from the table. .PP \fBTcl_DeleteHashEntry\fR will remove an existing entry from a table. The memory associated with the entry itself will be freed, but the client is responsible for any cleanup associated with the entry's value, such as freeing a structure that it points to. .PP \fBTcl_FindHashEntry\fR is similar to \fBTcl_CreateHashEntry\fR except that it does not create a new entry if the key doesn't exist; instead, it returns NULL as result. .PP \fBTcl_GetHashValue\fR and \fBTcl_SetHashValue\fR are used to read and write an entry's value, respectively. Values are stored and retrieved as type .QW ClientData , which is large enough to hold a pointer value. On almost all machines this is large enough to hold an integer value too. .PP \fBTcl_GetHashKey\fR returns the key for a given hash table entry, either as a pointer to a string, a one-word .PQ "char *" key, or as a pointer to the first word of an array of integers, depending on the \fIkeyType\fR used to create a hash table. In all cases \fBTcl_GetHashKey\fR returns a result with type .QW "char *" . When the key is a string or array, the result of \fBTcl_GetHashKey\fR points to information in the table entry; this information will remain valid until the entry is deleted or its table is deleted. .PP \fBTcl_FirstHashEntry\fR and \fBTcl_NextHashEntry\fR may be used to scan all of the entries in a hash table. A structure of type .QW Tcl_HashSearch , provided by the client, is used to keep track of progress through the table. \fBTcl_FirstHashEntry\fR initializes the search record and returns the first entry in the table (or NULL if the table is empty). Each subsequent call to \fBTcl_NextHashEntry\fR returns the next entry in the table or NULL if the end of the table has been reached. A call to \fBTcl_FirstHashEntry\fR followed by calls to \fBTcl_NextHashEntry\fR will return each of the entries in the table exactly once, in an arbitrary order. It is inadvisable to modify the structure of the table, e.g. by creating or deleting entries, while the search is in progress, with the exception of deleting the entry returned by \fBTcl_FirstHashEntry\fR or \fBTcl_NextHashEntry\fR. .PP \fBTcl_HashStats\fR returns a dynamically-allocated string with overall information about a hash table, such as the number of entries it contains, the number of buckets in its hash array, and the utilization of the buckets. It is the caller's responsibility to free the result string by passing it to \fBckfree\fR. .PP The header file \fBtcl.h\fR defines the actual data structures used to implement hash tables. This is necessary so that clients can allocate Tcl_HashTable structures and so that macros can be used to read and write the values of entries. However, users of the hashing routines should never refer directly to any of the fields of any of the hash-related data structures; use the procedures and macros defined here. .SH "THE TCL_HASHKEYTYPE STRUCTURE" .PP Extension writers can define new hash key types by defining four procedures, initializing a \fBTcl_HashKeyType\fR structure to describe the type, and calling \fBTcl_InitCustomHashTable\fR. The \fBTcl_HashKeyType\fR structure is defined as follows: .PP .CS typedef struct Tcl_HashKeyType { int \fIversion\fR; int \fIflags\fR; Tcl_HashKeyProc *\fIhashKeyProc\fR; Tcl_CompareHashKeysProc *\fIcompareKeysProc\fR; Tcl_AllocHashEntryProc *\fIallocEntryProc\fR; Tcl_FreeHashEntryProc *\fIfreeEntryProc\fR; } \fBTcl_HashKeyType\fR; .CE .PP The \fIversion\fR member is the version of the table. If this structure is extended in future then the version can be used to distinguish between different structures. It should be set to \fBTCL_HASH_KEY_TYPE_VERSION\fR. .PP The \fIflags\fR member is 0 or one or more of the following values OR'ed together: .IP \fBTCL_HASH_KEY_RANDOMIZE_HASH\fR 25 There are some things, pointers for example which do not hash well because they do not use the lower bits. If this flag is set then the hash table will attempt to rectify this by randomizing the bits and then using the upper N bits as the index into the table. .IP \fBTCL_HASH_KEY_SYSTEM_HASH\fR 25 This flag forces Tcl to use the memory allocation procedures provided by the operating system when allocating and freeing memory used to store the hash table data structures, and not any of Tcl's own customized memory allocation routines. This is important if the hash table is to be used in the implementation of a custom set of allocation routines, or something that a custom set of allocation routines might depend on, in order to avoid any circular dependency. .PP The \fIhashKeyProc\fR member contains the address of a function called to calculate a hash value for the key. .PP .CS typedef unsigned int \fBTcl_HashKeyProc\fR( Tcl_HashTable *\fItablePtr\fR, void *\fIkeyPtr\fR); .CE .PP If this is NULL then \fIkeyPtr\fR is used and \fBTCL_HASH_KEY_RANDOMIZE_HASH\fR is assumed. .PP The \fIcompareKeysProc\fR member contains the address of a function called to compare two keys. .PP .CS typedef int \fBTcl_CompareHashKeysProc\fR( void *\fIkeyPtr\fR, Tcl_HashEntry *\fIhPtr\fR); .CE .PP If this is NULL then the \fIkeyPtr\fR pointers are compared. If the keys do not match then the function returns 0, otherwise it returns 1. .PP The \fIallocEntryProc\fR member contains the address of a function called to allocate space for an entry and initialize the key and clientData. .PP .CS typedef Tcl_HashEntry *\fBTcl_AllocHashEntryProc\fR( Tcl_HashTable *\fItablePtr\fR, void *\fIkeyPtr\fR); .CE .PP If this is NULL then \fBTcl_Alloc\fR is used to allocate enough space for a Tcl_HashEntry, the key pointer is assigned to key.oneWordValue and the clientData is set to NULL. String keys and array keys use this function to allocate enough space for the entry and the key in one block, rather than doing it in two blocks. This saves space for a pointer to the key from the entry and another memory allocation. Tcl_Obj* keys use this function to allocate enough space for an entry and increment the reference count on the value. .PP The \fIfreeEntryProc\fR member contains the address of a function called to free space for an entry. .PP .CS typedef void \fBTcl_FreeHashEntryProc\fR( Tcl_HashEntry *\fIhPtr\fR); .CE .PP If this is NULL then \fBTcl_Free\fR is used to free the space for the entry. Tcl_Obj* keys use this function to decrement the reference count on the value. .SH KEYWORDS hash table, key, lookup, search, value tcl8.6.5/doc/Encoding.30000644000175000017500000006430712663660065014160 0ustar sergeisergei'\" '\" Copyright (c) 1997-1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_GetEncoding 3 "8.1" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternal, Tcl_WinTCharToUtf, Tcl_WinUtfToTChar, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath, Tcl_GetDefaultEncodingDir, Tcl_SetDefaultEncodingDir \- procedures for creating and using encodings .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Encoding \fBTcl_GetEncoding\fR(\fIinterp, name\fR) .sp void \fBTcl_FreeEncoding\fR(\fIencoding\fR) .sp int \fBTcl_GetEncodingFromObj\fR(\fIinterp, objPtr, encodingPtr\fR) .sp char * \fBTcl_ExternalToUtfDString\fR(\fIencoding, src, srcLen, dstPtr\fR) .sp char * \fBTcl_UtfToExternalDString\fR(\fIencoding, src, srcLen, dstPtr\fR) .sp int \fBTcl_ExternalToUtf\fR(\fIinterp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr\fR) .sp int \fBTcl_UtfToExternal\fR(\fIinterp, encoding, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr\fR) .sp char * \fBTcl_WinTCharToUtf\fR(\fItsrc, srcLen, dstPtr\fR) .sp TCHAR * \fBTcl_WinUtfToTChar\fR(\fIsrc, srcLen, dstPtr\fR) .sp const char * \fBTcl_GetEncodingName\fR(\fIencoding\fR) .sp int \fBTcl_SetSystemEncoding\fR(\fIinterp, name\fR) .sp const char * \fBTcl_GetEncodingNameFromEnvironment\fR(\fIbufPtr\fR) .sp void \fBTcl_GetEncodingNames\fR(\fIinterp\fR) .sp Tcl_Encoding \fBTcl_CreateEncoding\fR(\fItypePtr\fR) .sp Tcl_Obj * \fBTcl_GetEncodingSearchPath\fR() .sp int \fBTcl_SetEncodingSearchPath\fR(\fIsearchPath\fR) .sp const char * \fBTcl_GetDefaultEncodingDir\fR(\fIvoid\fR) .sp void \fBTcl_SetDefaultEncodingDir\fR(\fIpath\fR) .SH ARGUMENTS .AS "const Tcl_EncodingType" *dstWrotePtr in/out .AP Tcl_Interp *interp in Interpreter to use for error reporting, or NULL if no error reporting is desired. .AP "const char" *name in Name of encoding to load. .AP Tcl_Encoding encoding in The encoding to query, free, or use for converting text. If \fIencoding\fR is NULL, the current system encoding is used. .AP Tcl_Obj *objPtr in Name of encoding to get token for. .AP Tcl_Encoding *encodingPtr out Points to storage where encoding token is to be written. .AP "const char" *src in For the \fBTcl_ExternalToUtf\fR functions, an array of bytes in the specified encoding that are to be converted to UTF-8. For the \fBTcl_UtfToExternal\fR and \fBTcl_WinUtfToTChar\fR functions, an array of UTF-8 characters to be converted to the specified encoding. .AP "const TCHAR" *tsrc in An array of Windows TCHAR characters to convert to UTF-8. .AP int srcLen in Length of \fIsrc\fR or \fItsrc\fR in bytes. If the length is negative, the encoding-specific length of the string is used. .AP Tcl_DString *dstPtr out Pointer to an uninitialized or free \fBTcl_DString\fR in which the converted result will be stored. .AP int flags in Various flag bits OR-ed together. \fBTCL_ENCODING_START\fR signifies that the source buffer is the first block in a (potentially multi-block) input stream, telling the conversion routine to reset to an initial state and perform any initialization that needs to occur before the first byte is converted. \fBTCL_ENCODING_END\fR signifies that the source buffer is the last block in a (potentially multi-block) input stream, telling the conversion routine to perform any finalization that needs to occur after the last byte is converted and then to reset to an initial state. \fBTCL_ENCODING_STOPONERROR\fR signifies that the conversion routine should return immediately upon reading a source character that does not exist in the target encoding; otherwise a default fallback character will automatically be substituted. .AP Tcl_EncodingState *statePtr in/out Used when converting a (generally long or indefinite length) byte stream in a piece-by-piece fashion. The conversion routine stores its current state in \fI*statePtr\fR after \fIsrc\fR (the buffer containing the current piece) has been converted; that state information must be passed back when converting the next piece of the stream so the conversion routine knows what state it was in when it left off at the end of the last piece. May be NULL, in which case the value specified for \fIflags\fR is ignored and the source buffer is assumed to contain the complete string to convert. .AP char *dst out Buffer in which the converted result will be stored. No more than \fIdstLen\fR bytes will be stored in \fIdst\fR. .AP int dstLen in The maximum length of the output buffer \fIdst\fR in bytes. .AP int *srcReadPtr out Filled with the number of bytes from \fIsrc\fR that were actually converted. This may be less than the original source length if there was a problem converting some source characters. May be NULL. .AP int *dstWrotePtr out Filled with the number of bytes that were actually stored in the output buffer as a result of the conversion. May be NULL. .AP int *dstCharsPtr out Filled with the number of characters that correspond to the number of bytes stored in the output buffer. May be NULL. .AP Tcl_DString *bufPtr out Storage for the prescribed system encoding name. .AP "const Tcl_EncodingType" *typePtr in Structure that defines a new type of encoding. .AP Tcl_Obj *searchPath in List of filesystem directories in which to search for encoding data files. .AP "const char" *path in A path to the location of the encoding file. .BE .SH INTRODUCTION .PP These routines convert between Tcl's internal character representation, UTF-8, and character representations used by various operating systems or file systems, such as Unicode, ASCII, or Shift-JIS. When operating on strings, such as such as obtaining the names of files or displaying characters using international fonts, the strings must be translated into one or possibly multiple formats that the various system calls can use. For instance, on a Japanese Unix workstation, a user might obtain a filename represented in the EUC-JP file encoding and then translate the characters to the jisx0208 font encoding in order to display the filename in a Tk widget. The purpose of the encoding package is to help bridge the translation gap. UTF-8 provides an intermediate staging ground for all the various encodings. In the example above, text would be translated into UTF-8 from whatever file encoding the operating system is using. Then it would be translated from UTF-8 into whatever font encoding the display routines require. .PP Some basic encodings are compiled into Tcl. Others can be defined by the user or dynamically loaded from encoding files in a platform-independent manner. .SH DESCRIPTION .PP \fBTcl_GetEncoding\fR finds an encoding given its \fIname\fR. The name may refer to a built-in Tcl encoding, a user-defined encoding registered by calling \fBTcl_CreateEncoding\fR, or a dynamically-loadable encoding file. The return value is a token that represents the encoding and can be used in subsequent calls to procedures such as \fBTcl_GetEncodingName\fR, \fBTcl_FreeEncoding\fR, and \fBTcl_UtfToExternal\fR. If the name did not refer to any known or loadable encoding, NULL is returned and an error message is returned in \fIinterp\fR. .PP The encoding package maintains a database of all encodings currently in use. The first time \fIname\fR is seen, \fBTcl_GetEncoding\fR returns an encoding with a reference count of 1. If the same \fIname\fR is requested further times, then the reference count for that encoding is incremented without the overhead of allocating a new encoding and all its associated data structures. .PP When an \fIencoding\fR is no longer needed, \fBTcl_FreeEncoding\fR should be called to release it. When an \fIencoding\fR is no longer in use anywhere (i.e., it has been freed as many times as it has been gotten) \fBTcl_FreeEncoding\fR will release all storage the encoding was using and delete it from the database. .PP \fBTcl_GetEncodingFromObj\fR treats the string representation of \fIobjPtr\fR as an encoding name, and finds an encoding with that name, just as \fBTcl_GetEncoding\fR does. When an encoding is found, it is cached within the \fBobjPtr\fR value for future reference, the \fBTcl_Encoding\fR token is written to the storage pointed to by \fIencodingPtr\fR, and the value \fBTCL_OK\fR is returned. If no such encoding is found, the value \fBTCL_ERROR\fR is returned, and no writing to \fB*\fR\fIencodingPtr\fR takes place. Just as with \fBTcl_GetEncoding\fR, the caller should call \fBTcl_FreeEncoding\fR on the resulting encoding token when that token will no longer be used. .PP \fBTcl_ExternalToUtfDString\fR converts a source buffer \fIsrc\fR from the specified \fIencoding\fR into UTF-8. The converted bytes are stored in \fIdstPtr\fR, which is then null-terminated. The caller should eventually call \fBTcl_DStringFree\fR to free any information stored in \fIdstPtr\fR. When converting, if any of the characters in the source buffer cannot be represented in the target encoding, a default fallback character will be used. The return value is a pointer to the value stored in the DString. .PP \fBTcl_ExternalToUtf\fR converts a source buffer \fIsrc\fR from the specified \fIencoding\fR into UTF-8. Up to \fIsrcLen\fR bytes are converted from the source buffer and up to \fIdstLen\fR converted bytes are stored in \fIdst\fR. In all cases, \fI*srcReadPtr\fR is filled with the number of bytes that were successfully converted from \fIsrc\fR and \fI*dstWrotePtr\fR is filled with the corresponding number of bytes that were stored in \fIdst\fR. The return value is one of the following: .RS .IP \fBTCL_OK\fR 29 All bytes of \fIsrc\fR were converted. .IP \fBTCL_CONVERT_NOSPACE\fR 29 The destination buffer was not large enough for all of the converted data; as many characters as could fit were converted though. .IP \fBTCL_CONVERT_MULTIBYTE\fR 29 The last few bytes in the source buffer were the beginning of a multibyte sequence, but more bytes were needed to complete this sequence. A subsequent call to the conversion routine should pass a buffer containing the unconverted bytes that remained in \fIsrc\fR plus some further bytes from the source stream to properly convert the formerly split-up multibyte sequence. .IP \fBTCL_CONVERT_SYNTAX\fR 29 The source buffer contained an invalid character sequence. This may occur if the input stream has been damaged or if the input encoding method was misidentified. .IP \fBTCL_CONVERT_UNKNOWN\fR 29 The source buffer contained a character that could not be represented in the target encoding and \fBTCL_ENCODING_STOPONERROR\fR was specified. .RE .LP \fBTcl_UtfToExternalDString\fR converts a source buffer \fIsrc\fR from UTF-8 into the specified \fIencoding\fR. The converted bytes are stored in \fIdstPtr\fR, which is then terminated with the appropriate encoding-specific null. The caller should eventually call \fBTcl_DStringFree\fR to free any information stored in \fIdstPtr\fR. When converting, if any of the characters in the source buffer cannot be represented in the target encoding, a default fallback character will be used. The return value is a pointer to the value stored in the DString. .PP \fBTcl_UtfToExternal\fR converts a source buffer \fIsrc\fR from UTF-8 into the specified \fIencoding\fR. Up to \fIsrcLen\fR bytes are converted from the source buffer and up to \fIdstLen\fR converted bytes are stored in \fIdst\fR. In all cases, \fI*srcReadPtr\fR is filled with the number of bytes that were successfully converted from \fIsrc\fR and \fI*dstWrotePtr\fR is filled with the corresponding number of bytes that were stored in \fIdst\fR. The return values are the same as the return values for \fBTcl_ExternalToUtf\fR. .PP \fBTcl_WinUtfToTChar\fR and \fBTcl_WinTCharToUtf\fR are Windows-only convenience functions for converting between UTF-8 and Windows strings based on the TCHAR type which is by convention a Unicode character on Windows NT. These functions are essentially wrappers around \fBTcl_UtfToExternalDString\fR and \fBTcl_ExternalToUtfDString\fR that convert to and from the Unicode encoding. .PP \fBTcl_GetEncodingName\fR is roughly the inverse of \fBTcl_GetEncoding\fR. Given an \fIencoding\fR, the return value is the \fIname\fR argument that was used to create the encoding. The string returned by \fBTcl_GetEncodingName\fR is only guaranteed to persist until the \fIencoding\fR is deleted. The caller must not modify this string. .PP \fBTcl_SetSystemEncoding\fR sets the default encoding that should be used whenever the user passes a NULL value for the \fIencoding\fR argument to any of the other encoding functions. If \fIname\fR is NULL, the system encoding is reset to the default system encoding, \fBbinary\fR. If the name did not refer to any known or loadable encoding, \fBTCL_ERROR\fR is returned and an error message is left in \fIinterp\fR. Otherwise, this procedure increments the reference count of the new system encoding, decrements the reference count of the old system encoding, and returns \fBTCL_OK\fR. .PP \fBTcl_GetEncodingNameFromEnvironment\fR provides a means for the Tcl library to report the encoding name it believes to be the correct one to use as the system encoding, based on system calls and examination of the environment suitable for the platform. It accepts \fIbufPtr\fR, a pointer to an uninitialized or freed \fBTcl_DString\fR and writes the encoding name to it. The \fBTcl_DStringValue\fR is returned. .PP \fBTcl_GetEncodingNames\fR sets the \fIinterp\fR result to a list consisting of the names of all the encodings that are currently defined or can be dynamically loaded, searching the encoding path specified by \fBTcl_SetDefaultEncodingDir\fR. This procedure does not ensure that the dynamically-loadable encoding files contain valid data, but merely that they exist. .PP \fBTcl_CreateEncoding\fR defines a new encoding and registers the C procedures that are called back to convert between the encoding and UTF-8. Encodings created by \fBTcl_CreateEncoding\fR are thereafter visible in the database used by \fBTcl_GetEncoding\fR. Just as with the \fBTcl_GetEncoding\fR procedure, the return value is a token that represents the encoding and can be used in subsequent calls to other encoding functions. \fBTcl_CreateEncoding\fR returns an encoding with a reference count of 1. If an encoding with the specified \fIname\fR already exists, then its entry in the database is replaced with the new encoding; the token for the old encoding will remain valid and continue to behave as before, but users of the new token will now call the new encoding procedures. .PP The \fItypePtr\fR argument to \fBTcl_CreateEncoding\fR contains information about the name of the encoding and the procedures that will be called to convert between this encoding and UTF-8. It is defined as follows: .PP .CS typedef struct Tcl_EncodingType { const char *\fIencodingName\fR; Tcl_EncodingConvertProc *\fItoUtfProc\fR; Tcl_EncodingConvertProc *\fIfromUtfProc\fR; Tcl_EncodingFreeProc *\fIfreeProc\fR; ClientData \fIclientData\fR; int \fInullSize\fR; } \fBTcl_EncodingType\fR; .CE .PP The \fIencodingName\fR provides a string name for the encoding, by which it can be referred in other procedures such as \fBTcl_GetEncoding\fR. The \fItoUtfProc\fR refers to a callback procedure to invoke to convert text from this encoding into UTF-8. The \fIfromUtfProc\fR refers to a callback procedure to invoke to convert text from UTF-8 into this encoding. The \fIfreeProc\fR refers to a callback procedure to invoke when this encoding is deleted. The \fIfreeProc\fR field may be NULL. The \fIclientData\fR contains an arbitrary one-word value passed to \fItoUtfProc\fR, \fIfromUtfProc\fR, and \fIfreeProc\fR whenever they are called. Typically, this is a pointer to a data structure containing encoding-specific information that can be used by the callback procedures. For instance, two very similar encodings such as \fBascii\fR and \fBmacRoman\fR may use the same callback procedure, but use different values of \fIclientData\fR to control its behavior. The \fInullSize\fR specifies the number of zero bytes that signify end-of-string in this encoding. It must be \fB1\fR (for single-byte or multi-byte encodings like ASCII or Shift-JIS) or \fB2\fR (for double-byte encodings like Unicode). Constant-sized encodings with 3 or more bytes per character (such as CNS11643) are not accepted. .PP The callback procedures \fItoUtfProc\fR and \fIfromUtfProc\fR should match the type \fBTcl_EncodingConvertProc\fR: .PP .CS typedef int \fBTcl_EncodingConvertProc\fR( ClientData \fIclientData\fR, const char *\fIsrc\fR, int \fIsrcLen\fR, int \fIflags\fR, Tcl_EncodingState *\fIstatePtr\fR, char *\fIdst\fR, int \fIdstLen\fR, int *\fIsrcReadPtr\fR, int *\fIdstWrotePtr\fR, int *\fIdstCharsPtr\fR); .CE .PP The \fItoUtfProc\fR and \fIfromUtfProc\fR procedures are called by the \fBTcl_ExternalToUtf\fR or \fBTcl_UtfToExternal\fR family of functions to perform the actual conversion. The \fIclientData\fR parameter to these procedures is the same as the \fIclientData\fR field specified to \fBTcl_CreateEncoding\fR when the encoding was created. The remaining arguments to the callback procedures are the same as the arguments, documented at the top, to \fBTcl_ExternalToUtf\fR or \fBTcl_UtfToExternal\fR, with the following exceptions. If the \fIsrcLen\fR argument to one of those high-level functions is negative, the value passed to the callback procedure will be the appropriate encoding-specific string length of \fIsrc\fR. If any of the \fIsrcReadPtr\fR, \fIdstWrotePtr\fR, or \fIdstCharsPtr\fR arguments to one of the high-level functions is NULL, the corresponding value passed to the callback procedure will be a non-NULL location. .PP The callback procedure \fIfreeProc\fR, if non-NULL, should match the type \fBTcl_EncodingFreeProc\fR: .PP .CS typedef void \fBTcl_EncodingFreeProc\fR( ClientData \fIclientData\fR); .CE .PP This \fIfreeProc\fR function is called when the encoding is deleted. The \fIclientData\fR parameter is the same as the \fIclientData\fR field specified to \fBTcl_CreateEncoding\fR when the encoding was created. .PP \fBTcl_GetEncodingSearchPath\fR and \fBTcl_SetEncodingSearchPath\fR are called to access and set the list of filesystem directories searched for encoding data files. .PP The value returned by \fBTcl_GetEncodingSearchPath\fR is the value stored by the last successful call to \fBTcl_SetEncodingSearchPath\fR. If no calls to \fBTcl_SetEncodingSearchPath\fR have occurred, Tcl will compute an initial value based on the environment. There is one encoding search path for the entire process, shared by all threads in the process. .PP \fBTcl_SetEncodingSearchPath\fR stores \fIsearchPath\fR and returns \fBTCL_OK\fR, unless \fIsearchPath\fR is not a valid Tcl list, which causes \fBTCL_ERROR\fR to be returned. The elements of \fIsearchPath\fR are not verified as existing readable filesystem directories. When searching for encoding data files takes place, and non-existent or non-readable filesystem directories on the \fIsearchPath\fR are silently ignored. .PP \fBTcl_GetDefaultEncodingDir\fR and \fBTcl_SetDefaultEncodingDir\fR are obsolete interfaces best replaced with calls to \fBTcl_GetEncodingSearchPath\fR and \fBTcl_SetEncodingSearchPath\fR. They are called to access and set the first element of the \fIsearchPath\fR list. Since Tcl searches \fIsearchPath\fR for encoding data files in list order, these routines establish the .QW default directory in which to find encoding data files. .SH "ENCODING FILES" Space would prohibit precompiling into Tcl every possible encoding algorithm, so many encodings are stored on disk as dynamically-loadable encoding files. This behavior also allows the user to create additional encoding files that can be loaded using the same mechanism. These encoding files contain information about the tables and/or escape sequences used to map between an external encoding and Unicode. The external encoding may consist of single-byte, multi-byte, or double-byte characters. .PP Each dynamically-loadable encoding is represented as a text file. The initial line of the file, beginning with a .QW # symbol, is a comment that provides a human-readable description of the file. The next line identifies the type of encoding file. It can be one of the following letters: .IP "[1] \fBS\fR" A single-byte encoding, where one character is always one byte long in the encoding. An example is \fBiso8859-1\fR, used by many European languages. .IP "[2] \fBD\fR" A double-byte encoding, where one character is always two bytes long in the encoding. An example is \fBbig5\fR, used for Chinese text. .IP "[3] \fBM\fR" A multi-byte encoding, where one character may be either one or two bytes long. Certain bytes are lead bytes, indicating that another byte must follow and that together the two bytes represent one character. Other bytes are not lead bytes and represent themselves. An example is \fBshiftjis\fR, used by many Japanese computers. .IP "[4] \fBE\fR" An escape-sequence encoding, specifying that certain sequences of bytes do not represent characters, but commands that describe how following bytes should be interpreted. .PP The rest of the lines in the file depend on the type. .PP Cases [1], [2], and [3] are collectively referred to as table-based encoding files. The lines in a table-based encoding file are in the same format as this example taken from the \fBshiftjis\fR encoding (this is not the complete file): .PP .CS # Encoding file: shiftjis, multi-byte M 003F 0 40 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D203E007F 0080000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 81 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 300030013002FF0CFF0E30FBFF1AFF1BFF1FFF01309B309C00B4FF4000A8FF3E FFE3FF3F30FD30FE309D309E30034EDD30053006300730FC20152010FF0F005C 301C2016FF5C2026202520182019201C201DFF08FF0930143015FF3BFF3DFF5B FF5D30083009300A300B300C300D300E300F30103011FF0B221200B100D70000 00F7FF1D2260FF1CFF1E22662267221E22342642264000B0203220332103FFE5 FF0400A200A3FF05FF03FF06FF0AFF2000A72606260525CB25CF25CE25C725C6 25A125A025B325B225BD25BC203B301221922190219121933013000000000000 000000000000000000000000000000002208220B2286228722822283222A2229 000000000000000000000000000000002227222800AC21D221D4220022030000 0000000000000000000000000000000000000000222022A52312220222072261 2252226A226B221A223D221D2235222B222C0000000000000000000000000000 212B2030266F266D266A2020202100B6000000000000000025EF000000000000 .CE .PP The third line of the file is three numbers. The first number is the fallback character (in base 16) to use when converting from UTF-8 to this encoding. The second number is a \fB1\fR if this file represents the encoding for a symbol font, or \fB0\fR otherwise. The last number (in base 10) is how many pages of data follow. .PP Subsequent lines in the example above are pages that describe how to map from the encoding into 2-byte Unicode. The first line in a page identifies the page number. Following it are 256 double-byte numbers, arranged as 16 rows of 16 numbers. Given a character in the encoding, the high byte of that character is used to select which page, and the low byte of that character is used as an index to select one of the double-byte numbers in that page \- the value obtained being the corresponding Unicode character. By examination of the example above, one can see that the characters 0x7E and 0x8163 in \fBshiftjis\fR map to 203E and 2026 in Unicode, respectively. .PP Following the first page will be all the other pages, each in the same format as the first: one number identifying the page followed by 256 double-byte Unicode characters. If a character in the encoding maps to the Unicode character 0000, it means that the character does not actually exist. If all characters on a page would map to 0000, that page can be omitted. .PP Case [4] is the escape-sequence encoding file. The lines in an this type of file are in the same format as this example taken from the \fBiso2022-jp\fR encoding: .PP .CS .ta 1.5i # Encoding file: iso2022-jp, escape-driven E init {} final {} iso8859-1 \ex1b(B jis0201 \ex1b(J jis0208 \ex1b$@ jis0208 \ex1b$B jis0212 \ex1b$(D gb2312 \ex1b$A ksc5601 \ex1b$(C .CE .PP In the file, the first column represents an option and the second column is the associated value. \fBinit\fR is a string to emit or expect before the first character is converted, while \fBfinal\fR is a string to emit or expect after the last character. All other options are names of table-based encodings; the associated value is the escape-sequence that marks that encoding. Tcl syntax is used for the values; in the above example, for instance, .QW \fB{}\fR represents the empty string and .QW \fB\ex1b\fR represents character 27. .PP When \fBTcl_GetEncoding\fR encounters an encoding \fIname\fR that has not been loaded, it attempts to load an encoding file called \fIname\fB.enc\fR from the \fBencoding\fR subdirectory of each directory that Tcl searches for its script library. If the encoding file exists, but is malformed, an error message will be left in \fIinterp\fR. .SH KEYWORDS utf, encoding, convert tcl8.6.5/doc/SetErrno.30000644000175000017500000000405412663660065014164 0ustar sergeisergei'\" '\" Copyright (c) 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_SetErrno 3 8.3 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_SetErrno, Tcl_GetErrno, Tcl_ErrnoId, Tcl_ErrnoMsg \- manipulate errno to store and retrieve error codes .SH SYNOPSIS .nf \fB#include \fR .sp void \fBTcl_SetErrno\fR(\fIerrorCode\fR) .sp int \fBTcl_GetErrno\fR() .sp const char * \fBTcl_ErrnoId\fR() .sp const char * \fBTcl_ErrnoMsg\fR(\fIerrorCode\fR) .sp .SH ARGUMENTS .AS int errorCode .AP int errorCode in A POSIX error code such as \fBENOENT\fR. .BE .SH DESCRIPTION .PP \fBTcl_SetErrno\fR and \fBTcl_GetErrno\fR provide portable access to the \fBerrno\fR variable, which is used to record a POSIX error code after system calls and other operations such as \fBTcl_Gets\fR. These procedures are necessary because global variable accesses cannot be made across module boundaries on some platforms. .PP \fBTcl_SetErrno\fR sets the \fBerrno\fR variable to the value of the \fIerrorCode\fR argument C procedures that wish to return error information to their callers via \fBerrno\fR should call \fBTcl_SetErrno\fR rather than setting \fBerrno\fR directly. .PP \fBTcl_GetErrno\fR returns the current value of \fBerrno\fR. Procedures wishing to access \fBerrno\fR should call this procedure instead of accessing \fBerrno\fR directly. .PP \fBTcl_ErrnoId\fR and \fBTcl_ErrnoMsg\fR return string representations of \fBerrno\fR values. \fBTcl_ErrnoId\fR returns a machine-readable textual identifier such as .QW EACCES that corresponds to the current value of \fBerrno\fR. \fBTcl_ErrnoMsg\fR returns a human-readable string such as .QW "permission denied" that corresponds to the value of its \fIerrorCode\fR argument. The \fIerrorCode\fR argument is typically the value returned by \fBTcl_GetErrno\fR. The strings returned by these functions are statically allocated and the caller must not free or modify them. .SH KEYWORDS errno, error code, global variables tcl8.6.5/doc/foreach.n0000644000175000017500000000622612663660065014130 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 foreach n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME foreach \- Iterate over all elements in one or more lists .SH SYNOPSIS \fBforeach \fIvarname list body\fR .br \fBforeach \fIvarlist1 list1\fR ?\fIvarlist2 list2 ...\fR? \fIbody\fR .BE .SH DESCRIPTION .PP The \fBforeach\fR command implements a loop where the loop variable(s) take on values from one or more lists. In the simplest case there is one loop variable, \fIvarname\fR, and one list, \fIlist\fR, that is a list of values to assign to \fIvarname\fR. The \fIbody\fR argument is a Tcl script. For each element of \fIlist\fR (in order from first to last), \fBforeach\fR assigns the contents of the element to \fIvarname\fR as if the \fBlindex\fR command had been used to extract the element, then calls the Tcl interpreter to execute \fIbody\fR. .PP In the general case there can be more than one value list (e.g., \fIlist1\fR and \fIlist2\fR), and each value list can be associated with a list of loop variables (e.g., \fIvarlist1\fR and \fIvarlist2\fR). During each iteration of the loop the variables of each \fIvarlist\fR are assigned consecutive values from the corresponding \fIlist\fR. Values in each \fIlist\fR are used in order from first to last, and each value is used exactly once. The total number of loop iterations is large enough to use up all the values from all the value lists. If a value list does not contain enough elements for each of its loop variables in each iteration, empty values are used for the missing elements. .PP The \fBbreak\fR and \fBcontinue\fR statements may be invoked inside \fIbody\fR, with the same effect as in the \fBfor\fR command. \fBForeach\fR returns an empty string. .SH EXAMPLES .PP This loop prints every value in a list together with the square and cube of the value: .PP .CS '\" Maintainers: notice the tab hacking below! .ta 3i set values {1 3 5 7 2 4 6 8} ;# Odd numbers first, for fun! puts "Value\etSquare\etCube" ;# Neat-looking header \fBforeach\fR x $values { ;# Now loop and print... puts " $x\et [expr {$x**2}]\et [expr {$x**3}]" } .CE .PP The following loop uses i and j as loop variables to iterate over pairs of elements of a single list. .PP .CS set x {} \fBforeach\fR {i j} {a b c d e f} { lappend x $j $i } # The value of x is "b a d c f e" # There are 3 iterations of the loop. .CE .PP The next loop uses i and j to iterate over two lists in parallel. .PP .CS set x {} \fBforeach\fR i {a b c} j {d e f g} { lappend x $i $j } # The value of x is "a d b e c f {} g" # There are 4 iterations of the loop. .CE .PP The two forms are combined in the following example. .PP .CS set x {} \fBforeach\fR i {a b c} {j k} {d e f g} { lappend x $i $j $k } # The value of x is "a d e b f g c {} {}" # There are 3 iterations of the loop. .CE .SH "SEE ALSO" for(n), while(n), break(n), continue(n) .SH KEYWORDS foreach, iteration, list, loop tcl8.6.5/doc/dde.n0000644000175000017500000002000112663660065013240 0ustar sergeisergei'\" '\" Copyright (c) 1997 Sun Microsystems, Inc. '\" Copyright (c) 2001 ActiveState Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH dde n 1.4 dde "Tcl Bundled Packages" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME dde \- Execute a Dynamic Data Exchange command .SH SYNOPSIS .sp \fBpackage require dde 1.4\fR .sp \fBdde servername\fR ?\fB\-force\fR? ?\fB\-handler \fIproc\fR? ?\fB\-\|\-\fR? ?\fItopic\fR? .sp .VS 8.6 \fBdde execute\fR ?\fB\-async\fR? ?\fB\-binary\fR? \fIservice topic data\fR .sp \fBdde poke\fR ?\fB\-binary\fR? \fIservice topic item data\fR .VE 8.6 .sp \fBdde request\fR ?\fB\-binary\fR? \fIservice topic item\fR .sp \fBdde services \fIservice topic\fR .sp \fBdde eval\fR ?\fB\-async\fR? \fItopic cmd \fR?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP This command allows an application to send Dynamic Data Exchange (DDE) command when running under Microsoft Windows. Dynamic Data Exchange is a mechanism where applications can exchange raw data. Each DDE transaction needs a \fIservice name\fR and a \fItopic\fR. Both the \fIservice name\fR and \fItopic\fR are application defined; Tcl uses the service name \fBTclEval\fR, while the topic name is the name of the interpreter given by \fBdde servername\fR. Other applications have their own \fIservice names\fR and \fItopics\fR. For instance, Microsoft Excel has the service name \fBExcel\fR. .PP .SH "DDE COMMANDS" .PP The following commands are a subset of the full Dynamic Data Exchange set of commands. .TP \fBdde servername \fR?\fB\-force\fR? ?\fB\-handler \fIproc\fR? ?\fB\-\|\-\fR? ?\fItopic\fR? . \fBdde servername\fR registers the interpreter as a DDE server with the service name \fBTclEval\fR and the topic name specified by \fItopic\fR. If no \fItopic\fR is given, \fBdde servername\fR returns the name of the current topic or the empty string if it is not registered as a service. If the given \fItopic\fR name is already in use, then a suffix of the form .QW " #2" or .QW " #3" is appended to the name to make it unique. The command's result will be the name actually used. The \fB\-force\fR option is used to force registration of precisely the given \fItopic\fR name. .RS .PP The \fB\-handler\fR option specifies a Tcl procedure that will be called to process calls to the dde server. If the package has been loaded into a safe interpreter then a \fB\-handler\fR procedure must be defined. The procedure is called with all the arguments provided by the remote call. .RE .TP \fBdde execute\fR ?\fB\-async\fR? ?\fB\-binary\fR? \fIservice topic data\fR . \fBdde execute\fR takes the \fIdata\fR and sends it to the server indicated by \fIservice\fR with the topic indicated by \fItopic\fR. Typically, \fIservice\fR is the name of an application, and \fItopic\fR is a file to work on. The \fIdata\fR field is given to the remote application. Typically, the application treats the \fIdata\fR field as a script, and the script is run in the application. The \fB\-async\fR option requests asynchronous invocation. The command returns an error message if the script did not run, unless the \fB\-async\fR flag was used, in which case the command returns immediately with no error. .VS 8.6 Without the \fB\-binary\fR option all data will be sent in unicode. For dde clients which don't implement the CF_UNICODE clipboard format, this will automatically be translated to the system encoding. You can use the \fB\-binary\fR option in combination with the result of \fBencoding convertto\fR to send data in any other encoding. .VE 8.6 .TP \fBdde poke\fR ?\fB\-binary\fR? \fIservice topic item data\fR . \fBdde poke\fR passes the \fIdata\fR to the server indicated by \fIservice\fR using the \fItopic\fR and \fIitem\fR specified. Typically, \fIservice\fR is the name of an application. \fItopic\fR is application specific but can be a command to the server or the name of a file to work on. The \fIitem\fR is also application specific and is often not used, but it must always be non-null. The \fIdata\fR field is given to the remote application. .VS 8.6 Without the \fB\-binary\fR option all data will be sent in unicode. For dde clients which don't implement the CF_UNICODE clipboard format, this will automatically be translated to the system encoding. You can use the \fB\-binary\fR option in combination with the result of \fBencoding convertto\fR to send data in any other encoding. .VE 8.6 .TP \fBdde request\fR ?\fB\-binary\fR? \fIservice topic item\fR . \fBdde request\fR is typically used to get the value of something; the value of a cell in Microsoft Excel or the text of a selection in Microsoft Word. \fIservice\fR is typically the name of an application, \fItopic\fR is typically the name of the file, and \fIitem\fR is application-specific. The command returns the value of \fIitem\fR as defined in the application. Normally this is interpreted to be a string with terminating null. If \fB\-binary\fR is specified, the result is returned as a byte array. .TP \fBdde services \fIservice topic\fR . \fBdde services\fR returns a list of service-topic pairs that currently exist on the machine. If \fIservice\fR and \fItopic\fR are both empty strings ({}), then all service-topic pairs currently available on the system are returned. If \fIservice\fR is empty and \fItopic\fR is not, then all services with the specified topic are returned. If \fIservice\fR is non-empty and \fItopic\fR is, all topics for a given service are returned. If both are non-empty, if that service-topic pair currently exists, it is returned; otherwise, an empty string is returned. .TP \fBdde eval\fR ?\fB\-async\fR? \fItopic cmd \fR?\fIarg arg ...\fR? . \fBdde eval\fR evaluates a command and its arguments using the interpreter specified by \fItopic\fR. The DDE service must be the \fBTclEval\fR service. The \fB\-async\fR option requests asynchronous invocation. The command returns an error message if the script did not run, unless the \fB\-async\fR flag was used, in which case the command returns immediately with no error. This command can be used to replace send on Windows. .SH "DDE AND TCL" .PP A Tcl interpreter always has a service name of \fBTclEval\fR. Each different interpreter of all running Tcl applications must be given a unique name specified by \fBdde servername\fR. Each interp is available as a DDE topic only if the \fBdde servername\fR command was used to set the name of the topic for each interp. So a \fBdde services TclEval {}\fR command will return a list of service-topic pairs, where each of the currently running interps will be a topic. .PP When Tcl processes a \fBdde execute\fR command, the data for the execute is run as a script in the interp named by the topic of the \fBdde execute\fR command. .PP When Tcl processes a \fBdde request\fR command, it returns the value of the variable given in the dde command in the context of the interp named by the dde topic. Tcl reserves the variable \fB$TCLEVAL$EXECUTE$RESULT\fR for internal use, and \fBdde request\fR commands for that variable will give unpredictable results. .PP An external application which wishes to run a script in Tcl should have that script store its result in a variable, run the \fBdde execute\fR command, and then run \fBdde request\fR to get the value of the variable. .PP When using DDE, be careful to ensure that the event queue is flushed using either \fBupdate\fR or \fBvwait\fR. This happens by default when using \fBwish\fR unless a blocking command is called (such as \fBexec\fR without adding the \fB&\fR to place the process in the background). If for any reason the event queue is not flushed, DDE commands may hang until the event queue is flushed. This can create a deadlock situation. .SH EXAMPLE .PP This asks Internet Explorer (which must already be running) to go to a particularly important website: .PP .CS package require dde \fBdde execute\fR -async iexplore WWW_OpenURL http://www.tcl.tk/ .CE .SH "SEE ALSO" tk(n), winfo(n), send(n) .SH KEYWORDS application, dde, name, remote execution '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/cd.n0000644000175000017500000000217012663660065013101 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 cd n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME cd \- Change working directory .SH SYNOPSIS \fBcd \fR?\fIdirName\fR? .BE .SH DESCRIPTION .PP Change the current working directory to \fIdirName\fR, or to the home directory (as specified in the HOME environment variable) if \fIdirName\fR is not given. Returns an empty string. Note that the current working directory is a per-process resource; the \fBcd\fR command changes the working directory for all interpreters and (in a threaded environment) all threads. .SH EXAMPLES .PP Change to the home directory of the user \fBfred\fR: .PP .CS \fBcd\fR ~fred .CE .PP Change to the directory \fBlib\fR that is a sibling directory of the current one: .PP .CS \fBcd\fR ../lib .CE .SH "SEE ALSO" filename(n), glob(n), pwd(n) .SH KEYWORDS working directory tcl8.6.5/doc/CmdCmplt.30000644000175000017500000000171312663660065014125 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_CommandComplete 3 "" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CommandComplete \- Check for unmatched braces in a Tcl command .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_CommandComplete\fR(\fIcmd\fR) .SH ARGUMENTS .AS "const char" *cmd .AP "const char" *cmd in Command string to test for completeness. .BE .SH DESCRIPTION .PP \fBTcl_CommandComplete\fR takes a Tcl command string as argument and determines whether it contains one or more complete commands (i.e. there are no unclosed quotes, braces, brackets, or variable references). If the command string is complete then it returns 1; otherwise it returns 0. .SH KEYWORDS complete command, partial command tcl8.6.5/doc/Object.30000644000175000017500000003347012663660065013635 0ustar sergeisergei'\" '\" Copyright (c) 1996-1997 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_Obj 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_NewObj, Tcl_DuplicateObj, Tcl_IncrRefCount, Tcl_DecrRefCount, Tcl_IsShared, Tcl_InvalidateStringRep \- manipulate Tcl values .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * \fBTcl_NewObj\fR() .sp Tcl_Obj * \fBTcl_DuplicateObj\fR(\fIobjPtr\fR) .sp \fBTcl_IncrRefCount\fR(\fIobjPtr\fR) .sp \fBTcl_DecrRefCount\fR(\fIobjPtr\fR) .sp int \fBTcl_IsShared\fR(\fIobjPtr\fR) .sp \fBTcl_InvalidateStringRep\fR(\fIobjPtr\fR) .SH ARGUMENTS .AS Tcl_Obj *objPtr .AP Tcl_Obj *objPtr in Points to a value; must have been the result of a previous call to \fBTcl_NewObj\fR. .BE .SH INTRODUCTION .PP This man page presents an overview of Tcl values (called \fBTcl_Obj\fRs for historical reasons) and how they are used. It also describes generic procedures for managing Tcl values. These procedures are used to create and copy values, and increment and decrement the count of references (pointers) to values. The procedures are used in conjunction with ones that operate on specific types of values such as \fBTcl_GetIntFromObj\fR and \fBTcl_ListObjAppendElement\fR. The individual procedures are described along with the data structures they manipulate. .PP Tcl's \fIdual-ported\fR values provide a general-purpose mechanism for storing and exchanging Tcl values. They largely replace the use of strings in Tcl. For example, they are used to store variable values, command arguments, command results, and scripts. Tcl values behave like strings but also hold an internal representation that can be manipulated more efficiently. For example, a Tcl list is now represented as a value that holds the list's string representation as well as an array of pointers to the values for each list element. Dual-ported values avoid most runtime type conversions. They also improve the speed of many operations since an appropriate representation is immediately available. The compiler itself uses Tcl values to cache the instruction bytecodes resulting from compiling scripts. .PP The two representations are a cache of each other and are computed lazily. That is, each representation is only computed when necessary, it is computed from the other representation, and, once computed, it is saved. In addition, a change in one representation invalidates the other one. As an example, a Tcl program doing integer calculations can operate directly on a variable's internal machine integer representation without having to constantly convert between integers and strings. Only when it needs a string representing the variable's value, say to print it, will the program regenerate the string representation from the integer. Although values contain an internal representation, their semantics are defined in terms of strings: an up-to-date string can always be obtained, and any change to the value will be reflected in that string when the value's string representation is fetched. Because of this representation invalidation and regeneration, it is dangerous for extension writers to access \fBTcl_Obj\fR fields directly. It is better to access Tcl_Obj information using procedures like \fBTcl_GetStringFromObj\fR and \fBTcl_GetString\fR. .PP Values are allocated on the heap and are referenced using a pointer to their \fBTcl_Obj\fR structure. Values are shared as much as possible. This significantly reduces storage requirements because some values such as long lists are very large. Also, most Tcl values are only read and never modified. This is especially true for procedure arguments, which can be shared between the caller and the called procedure. Assignment and argument binding is done by simply assigning a pointer to the value. Reference counting is used to determine when it is safe to reclaim a value's storage. .PP Tcl values are typed. A value's internal representation is controlled by its type. Several types are predefined in the Tcl core including integer, double, list, and bytecode. Extension writers can extend the set of types by defining their own \fBTcl_ObjType\fR structs. .SH "THE TCL_OBJ STRUCTURE" .PP Each Tcl value is represented by a \fBTcl_Obj\fR structure which is defined as follows. .PP .CS typedef struct Tcl_Obj { int \fIrefCount\fR; char *\fIbytes\fR; int \fIlength\fR; const Tcl_ObjType *\fItypePtr\fR; union { long \fIlongValue\fR; double \fIdoubleValue\fR; void *\fIotherValuePtr\fR; Tcl_WideInt \fIwideValue\fR; struct { void *\fIptr1\fR; void *\fIptr2\fR; } \fItwoPtrValue\fR; struct { void *\fIptr\fR; unsigned long \fIvalue\fR; } \fIptrAndLongRep\fR; } \fIinternalRep\fR; } \fBTcl_Obj\fR; .CE .PP The \fIbytes\fR and the \fIlength\fR members together hold a value's UTF-8 string representation, which is a \fIcounted string\fR not containing null bytes (UTF-8 null characters should be encoded as a two byte sequence: 192, 128.) \fIbytes\fR points to the first byte of the string representation. The \fIlength\fR member gives the number of bytes. The byte array must always have a null byte after the last data byte, at offset \fIlength\fR; this allows string representations to be treated as conventional null-terminated C strings. C programs use \fBTcl_GetStringFromObj\fR and \fBTcl_GetString\fR to get a value's string representation. If \fIbytes\fR is NULL, the string representation is invalid. .PP A value's type manages its internal representation. The member \fItypePtr\fR points to the Tcl_ObjType structure that describes the type. If \fItypePtr\fR is NULL, the internal representation is invalid. .PP The \fIinternalRep\fR union member holds a value's internal representation. This is either a (long) integer, a double-precision floating-point number, a pointer to a value containing additional information needed by the value's type to represent the value, a Tcl_WideInt integer, two arbitrary pointers, or a pair made up of an unsigned long integer and a pointer. .PP The \fIrefCount\fR member is used to tell when it is safe to free a value's storage. It holds the count of active references to the value. Maintaining the correct reference count is a key responsibility of extension writers. Reference counting is discussed below in the section \fBSTORAGE MANAGEMENT OF VALUES\fR. .PP Although extension writers can directly access the members of a Tcl_Obj structure, it is much better to use the appropriate procedures and macros. For example, extension writers should never read or update \fIrefCount\fR directly; they should use macros such as \fBTcl_IncrRefCount\fR and \fBTcl_IsShared\fR instead. .PP A key property of Tcl values is that they hold two representations. A value typically starts out containing only a string representation: it is untyped and has a NULL \fItypePtr\fR. A value containing an empty string or a copy of a specified string is created using \fBTcl_NewObj\fR or \fBTcl_NewStringObj\fR respectively. A value's string value is gotten with \fBTcl_GetStringFromObj\fR or \fBTcl_GetString\fR and changed with \fBTcl_SetStringObj\fR. If the value is later passed to a procedure like \fBTcl_GetIntFromObj\fR that requires a specific internal representation, the procedure will create one and set the value's \fItypePtr\fR. The internal representation is computed from the string representation. A value's two representations are duals of each other: changes made to one are reflected in the other. For example, \fBTcl_ListObjReplace\fR will modify a value's internal representation and the next call to \fBTcl_GetStringFromObj\fR or \fBTcl_GetString\fR will reflect that change. .PP Representations are recomputed lazily for efficiency. A change to one representation made by a procedure such as \fBTcl_ListObjReplace\fR is not reflected immediately in the other representation. Instead, the other representation is marked invalid so that it is only regenerated if it is needed later. Most C programmers never have to be concerned with how this is done and simply use procedures such as \fBTcl_GetBooleanFromObj\fR or \fBTcl_ListObjIndex\fR. Programmers that implement their own value types must check for invalid representations and mark representations invalid when necessary. The procedure \fBTcl_InvalidateStringRep\fR is used to mark a value's string representation invalid and to free any storage associated with the old string representation. .PP Values usually remain one type over their life, but occasionally a value must be converted from one type to another. For example, a C program might build up a string in a value with repeated calls to \fBTcl_AppendToObj\fR, and then call \fBTcl_ListObjIndex\fR to extract a list element from the value. The same value holding the same string value can have several different internal representations at different times. Extension writers can also force a value to be converted from one type to another using the \fBTcl_ConvertToType\fR procedure. Only programmers that create new value types need to be concerned about how this is done. A procedure defined as part of the value type's implementation creates a new internal representation for a value and changes its \fItypePtr\fR. See the man page for \fBTcl_RegisterObjType\fR to see how to create a new value type. .SH "EXAMPLE OF THE LIFETIME OF A VALUE" .PP As an example of the lifetime of a value, consider the following sequence of commands: .PP .CS \fBset x 123\fR .CE .PP This assigns to \fIx\fR an untyped value whose \fIbytes\fR member points to \fB123\fR and \fIlength\fR member contains 3. The value's \fItypePtr\fR member is NULL. .PP .CS \fBputs "x is $x"\fR .CE .PP \fIx\fR's string representation is valid (since \fIbytes\fR is non-NULL) and is fetched for the command. .PP .CS \fBincr x\fR .CE .PP The \fBincr\fR command first gets an integer from \fIx\fR's value by calling \fBTcl_GetIntFromObj\fR. This procedure checks whether the value is already an integer value. Since it is not, it converts the value by setting the value's \fIinternalRep.longValue\fR member to the integer \fB123\fR and setting the value's \fItypePtr\fR to point to the integer Tcl_ObjType structure. Both representations are now valid. \fBincr\fR increments the value's integer internal representation then invalidates its string representation (by calling \fBTcl_InvalidateStringRep\fR) since the string representation no longer corresponds to the internal representation. .PP .CS \fBputs "x is now $x"\fR .CE .PP The string representation of \fIx\fR's value is needed and is recomputed. The string representation is now \fB124\fR and both representations are again valid. .SH "STORAGE MANAGEMENT OF VALUES" .PP Tcl values are allocated on the heap and are shared as much as possible to reduce storage requirements. Reference counting is used to determine when a value is no longer needed and can safely be freed. A value just created by \fBTcl_NewObj\fR or \fBTcl_NewStringObj\fR has \fIrefCount\fR 0. The macro \fBTcl_IncrRefCount\fR increments the reference count when a new reference to the value is created. The macro \fBTcl_DecrRefCount\fR decrements the count when a reference is no longer needed and, if the value's reference count drops to zero, frees its storage. A value shared by different code or data structures has \fIrefCount\fR greater than 1. Incrementing a value's reference count ensures that it will not be freed too early or have its value change accidentally. .PP As an example, the bytecode interpreter shares argument values between calling and called Tcl procedures to avoid having to copy values. It assigns the call's argument values to the procedure's formal parameter variables. In doing so, it calls \fBTcl_IncrRefCount\fR to increment the reference count of each argument since there is now a new reference to it from the formal parameter. When the called procedure returns, the interpreter calls \fBTcl_DecrRefCount\fR to decrement each argument's reference count. When a value's reference count drops less than or equal to zero, \fBTcl_DecrRefCount\fR reclaims its storage. Most command procedures do not have to be concerned about reference counting since they use a value's value immediately and do not retain a pointer to the value after they return. However, if they do retain a pointer to a value in a data structure, they must be careful to increment its reference count since the retained pointer is a new reference. .PP Command procedures that directly modify values such as those for \fBlappend\fR and \fBlinsert\fR must be careful to copy a shared value before changing it. They must first check whether the value is shared by calling \fBTcl_IsShared\fR. If the value is shared they must copy the value by using \fBTcl_DuplicateObj\fR; this returns a new duplicate of the original value that has \fIrefCount\fR 0. If the value is not shared, the command procedure .QW "owns" the value and can safely modify it directly. For example, the following code appears in the command procedure that implements \fBlinsert\fR. This procedure modifies the list value passed to it in \fIobjv[1]\fR by inserting \fIobjc-3\fR new elements before \fIindex\fR. .PP .CS listPtr = objv[1]; if (\fBTcl_IsShared\fR(listPtr)) { listPtr = \fBTcl_DuplicateObj\fR(listPtr); } result = Tcl_ListObjReplace(interp, listPtr, index, 0, (objc-3), &(objv[3])); .CE .PP As another example, \fBincr\fR's command procedure must check whether the variable's value is shared before incrementing the integer in its internal representation. If it is shared, it needs to duplicate the value in order to avoid accidentally changing values in other data structures. .SH "SEE ALSO" Tcl_ConvertToType(3), Tcl_GetIntFromObj(3), Tcl_ListObjAppendElement(3), Tcl_ListObjIndex(3), Tcl_ListObjReplace(3), Tcl_RegisterObjType(3) .SH KEYWORDS internal representation, value, value creation, value type, reference counting, string representation, type conversion tcl8.6.5/doc/refchan.n0000644000175000017500000003551212663660065014127 0ustar sergeisergei'\" '\" Copyright (c) 2006 Andreas Kupries '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH refchan n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS .\" Note: do not modify the .SH NAME line immediately below! .SH NAME refchan \- command handler API of reflected channels .SH SYNOPSIS \fBcmdPrefix \fIoption\fR ?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP The Tcl-level handler for a reflected channel has to be a command with subcommands (termed an \fIensemble\fR, as it is a command such as that created by \fBnamespace ensemble\fR \fBcreate\fR, though the implementation of handlers for reflected channel \fIis not\fR tied to \fBnamespace ensemble\fRs in any way; see \fBEXAMPLE\fR below for how to build an \fBoo::class\fR that supports the API). Note that \fIcmdPrefix\fR is whatever was specified in the call to \fBchan create\fR, and may consist of multiple arguments; this will be expanded to multiple words in place of the prefix. .PP Of all the possible subcommands, the handler \fImust\fR support \fBinitialize\fR, \fBfinalize\fR, and \fBwatch\fR. Support for the other subcommands is optional. .SS "MANDATORY SUBCOMMANDS" .TP \fIcmdPrefix \fBinitialize \fIchannelId mode\fR . An invocation of this subcommand will be the first call the \fIcmdPrefix\fR will receive for the specified new \fIchannelId\fR. It is the responsibility of this subcommand to set up any internal data structures required to keep track of the channel and its state. .RS .PP The return value of the method has to be a list containing the names of all subcommands supported by the \fIcmdPrefix\fR. This also tells the Tcl core which version of the API for reflected channels is used by this command handler. .PP Any error thrown by the method will abort the creation of the channel and no channel will be created. The thrown error will appear as error thrown by \fBchan create\fR. Any exception other than an \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as (and converted to) an error. .PP \fBNote:\fR If the creation of the channel was aborted due to failures here, then the \fBfinalize\fR subcommand will not be called. .PP The \fImode\fR argument tells the handler whether the channel was opened for reading, writing, or both. It is a list containing any of the strings \fBread\fR or \fBwrite\fR. The list will always contain at least one element. .PP The subcommand must throw an error if the chosen mode is not supported by the \fIcmdPrefix\fR. .RE .TP \fIcmdPrefix \fBfinalize \fIchannelId\fR . An invocation of this subcommand will be the last call the \fIcmdPrefix\fR will receive for the specified \fIchannelId\fR. It will be generated just before the destruction of the data structures of the channel held by the Tcl core. The command handler \fImust not\fR access the \fIchannelId\fR anymore in no way. Upon this subcommand being called, any internal resources allocated to this channel must be cleaned up. .RS .PP The return value of this subcommand is ignored. .PP If the subcommand throws an error the command which caused its invocation (usually \fBchan close\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. .PP This subcommand is not invoked if the creation of the channel was aborted during \fBinitialize\fR (See above). .RE .TP \fIcmdPrefix \fBwatch \fIchannelId eventspec\fR . This subcommand notifies the \fIcmdPrefix\fR that the specified \fIchannelId\fR is interested in the events listed in the \fIeventspec\fR. This argument is a list containing any of \fBread\fR and \fBwrite\fR. The list may be empty, which signals that the channel does not wish to be notified of any events. In that situation, the handler should disable event generation completely. .RS .PP \fBWarning:\fR Any return value of the subcommand is ignored. This includes all errors thrown by the subcommand, \fBbreak\fR, \fBcontinue\fR, and custom return codes. .PP This subcommand interacts with \fBchan postevent\fR. Trying to post an event which was not listed in the last call to \fBwatch\fR will cause \fBchan postevent\fR to throw an error. .RE .SS "OPTIONAL SUBCOMMANDS" .TP \fIcmdPrefix \fBread \fIchannelId count\fR . This \fIoptional\fR subcommand is called when the user requests data from the channel \fIchannelId\fR. \fIcount\fR specifies how many \fIbytes\fR have been requested. If the subcommand is not supported then it is not possible to read from the channel handled by the command. .RS .PP The return value of this subcommand is taken as the requested data \fIbytes\fR. If the returned data contains more bytes than requested, an error will be signaled and later thrown by the command which performed the read (usually \fBgets\fR or \fBread\fR). However, returning fewer bytes than requested is acceptable. .PP Note that returning nothing (0 bytes) is a signal to the higher layers that \fBEOF\fR has been reached on the channel. To signal that the channel is out of data right now, but has not yet reached \fBEOF\fR, it is necessary to throw the error "EAGAIN", i.e. to either .PP .CS return -code error EAGAIN .CE or .CS error EAGAIN .CE .PP For extensibility any error whose value is a negative integer number will cause the higher layers to set the C-level variable "\fBerrno\fR" to the absolute value of this number, signaling a system error. However, note that the exact mapping between these error numbers and their meanings is operating system dependent. .PP For example, while on Linux both .PP .CS return -code error -11 .CE and .CS error -11 .CE .PP are equivalent to the examples above, using the more readable string "EAGAIN", this is not true for BSD, where the equivalent number is -35. .PP The symbolic string however is the same across systems, and internally translated to the correct number. No other error value has such a mapping to a symbolic string. .PP If the subcommand throws any other error, the command which caused its invocation (usually \fBgets\fR, or \fBread\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 \fBwrite \fIchannelId data\fR . This \fIoptional\fR subcommand is called when the user writes data to the channel \fIchannelId\fR. The \fIdata\fR argument contains \fIbytes\fR, not characters. Any type of transformation (EOL, encoding) configured for the channel has already been applied at this point. If this subcommand is not supported then it is not possible to write to the channel handled by the command. .RS .PP The return value of the subcommand is taken as the number of bytes written by the channel. Anything non-numeric will cause an error to be signaled and later thrown by the command which performed the write. A negative value implies that the write failed. Returning a value greater than the number of bytes given to the handler, or zero, is forbidden and will cause the Tcl core to throw an error. .PP To signal that the channel is not able to accept data for writing right now, it is necessary to throw the error "EAGAIN", i.e. to either .PP .CS return -code error EAGAIN .CE or .CS error EAGAIN .CE .PP For extensibility any error whose value is a negative integer number will cause the higher layers to set the C-level variable "\fBerrno\fR" to the absolute value of this number, signaling a system error. However, note that the exact mapping between these error numbers and their meanings is operating system dependent. .PP For example, while on Linux both .PP .CS return -code error -11 .CE and .CS error -11 .CE .PP are equivalent to the examples above, using the more readable string "EAGAIN", this is not true for BSD, where the equivalent number is -35. .PP The symbolic string however is the same across systems, and internally translated to the correct number. No other error value has such a mapping to a symbolic string. .PP If the subcommand throws any other error the command which caused its invocation (usually \fBputs\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 \fBseek \fIchannelId offset base\fR . This \fIoptional\fR subcommand is responsible for the handling of \fBchan seek\fR and \fBchan tell\fR requests on the channel \fIchannelId\fR. If it is not supported then seeking will not be possible for the channel. .RS .PP The \fIbase\fR argument is the same as the equivalent argument of the builtin \fBchan seek\fR, namely: .TP 10 \fBstart\fR . Seeking is relative to the beginning of the channel. .TP 10 \fBcurrent\fR . Seeking is relative to the current seek position. .TP 10 \fBend\fR . Seeking is relative to the end of the channel. .PP The \fIoffset\fR is an integer number specifying the amount of \fBbytes\fR to seek forward or backward. A positive number should seek forward, and a negative number should seek backward. A channel may provide only limited seeking. For example sockets can seek forward, but not backward. .PP The return value of the subcommand is taken as the (new) location of the channel, counted from the start. This has to be an integer number greater than or equal to zero. If the subcommand throws an error the command which caused its invocation (usually \fBchan seek\fR, or \fBchan tell\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. .PP The offset/base combination of 0/\fBcurrent\fR signals a \fBchan tell\fR request, i.e.,\ seek nothing relative to the current location, making the new location identical to the current one, which is then returned. .RE .TP \fIcmdPrefix \fBconfigure \fIchannelId option value\fR . This \fIoptional\fR subcommand is for setting the type-specific options of channel \fIchannelId\fR. The \fIoption\fR argument indicates the option to be written, and the \fIvalue\fR argument indicates the value to set the option to. .RS .PP This subcommand will never try to update more than one option at a time; that is behavior implemented in the Tcl channel core. .PP The return value of the subcommand is ignored. .PP If the subcommand throws an error the command which performed the (re)configuration or query (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 \fBcget \fIchannelId option\fR . This \fIoptional\fR subcommand is used when reading a single type-specific option of channel \fIchannelId\fR. If this subcommand is supported then the subcommand \fBcgetall\fR must be supported as well. .RS .PP The subcommand should return the value of the specified \fIoption\fR. .PP If the subcommand throws an error, the command which performed the (re)configuration or query (usually \fBfconfigure\fR or \fBchan configure\fR) will appear to have thrown this error. Any exception beyond \fIerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error. .RE .TP \fIcmdPrefix \fBcgetall \fIchannelId\fR . This \fIoptional\fR subcommand is used for reading all type-specific options of channel \fIchannelId\fR. If this subcommand is supported then the subcommand \fBcget\fR has to be supported as well. .RS .PP The subcommand should return a list of all options and their values. This list must have an even number of elements. .PP If the subcommand throws an error the command which performed the (re)configuration or query (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 \fBblocking \fIchannelId mode\fR . This \fIoptional\fR subcommand handles changes to the blocking mode of the channel \fIchannelId\fR. The \fImode\fR is a boolean flag. A true value means that the channel has to be set to blocking, and a false value means that the channel should be non-blocking. .RS .PP The return value of the subcommand is ignored. .PP If the subcommand throws an error the command which caused its 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 .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. .PP The function \fBTcl_DriverGetHandleProc\fR is not supported; i.e.,\ reflected channels do not have OS specific handles. .PP The function \fBTcl_DriverHandlerProc\fR is not supported. This driver function is relevant only for stacked channels, i.e.,\ transformations. Reflected channels are always base channels, not transformations. .PP The function \fBTcl_DriverFlushProc\fR is not supported. This is because the current generic I/O layer of Tcl does not use this function anywhere at all. Therefore support at the Tcl level makes no sense either. This may be altered in the future (through extending the API defined here and changing its version number) should the function be used at some time in the future. .SH EXAMPLE .PP This demonstrates how to make a channel that reads from a string. .PP .CS oo::class create stringchan { variable data pos constructor {string {encoding {}}} { if {$encoding eq ""} {set encoding [encoding system]} set data [encoding convertto $encoding $string] set pos 0 } method \fBinitialize\fR {ch mode} { return "initialize finalize watch read seek" } method \fBfinalize\fR {ch} { my destroy } method \fBwatch\fR {ch events} { # Must be present but we ignore it because we do not # post any events } # Must be present on a readable channel method \fBread\fR {ch count} { set d [string range $data $pos [expr {$pos+$count-1}]] incr pos [string length $d] return $d } # This method is optional, but useful for the example below method \fBseek\fR {ch offset base} { switch $base { start { set pos $offset } current { incr pos $offset } end { set pos [string length $data] incr pos $offset } } if {$pos < 0} { set pos 0 } elseif {$pos > [string length $data]} { set pos [string length $data] } return $pos } } # Now we create an instance... set string "The quick brown fox jumps over the lazy dog.\\n" set ch [\fBchan create\fR read [stringchan new $string]] puts [gets $ch]; # Prints the whole string seek $ch -5 end; puts [read $ch]; # Prints just the last word .CE .SH "SEE ALSO" chan(n), transchan(n) .SH KEYWORDS API, channel, ensemble, prefix, reflection '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/CrtChannel.30000644000175000017500000011503412663660065014445 0ustar sergeisergei'\" '\" Copyright (c) 1996-1997 Sun Microsystems, Inc. '\" Copyright (c) 1997-2000 Ajuba Solutions. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. .TH Tcl_CreateChannel 3 8.4 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelHandle, Tcl_GetChannelMode, Tcl_GetChannelBufferSize, Tcl_SetChannelBufferSize, Tcl_NotifyChannel, Tcl_BadChannelOption, Tcl_ChannelName, Tcl_ChannelVersion, Tcl_ChannelBlockModeProc, Tcl_ChannelCloseProc, Tcl_ChannelClose2Proc, Tcl_ChannelInputProc, Tcl_ChannelOutputProc, Tcl_ChannelSeekProc, Tcl_ChannelWideSeekProc, Tcl_ChannelTruncateProc, Tcl_ChannelSetOptionProc, Tcl_ChannelGetOptionProc, Tcl_ChannelWatchProc, Tcl_ChannelGetHandleProc, Tcl_ChannelFlushProc, Tcl_ChannelHandlerProc, Tcl_ChannelThreadActionProc, Tcl_IsChannelShared, Tcl_IsChannelRegistered, Tcl_CutChannel, Tcl_SpliceChannel, Tcl_IsChannelExisting, Tcl_ClearChannelHandlers, Tcl_GetChannelThread, Tcl_ChannelBuffered \- procedures for creating and manipulating channels .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Channel \fBTcl_CreateChannel\fR(\fItypePtr, channelName, instanceData, mask\fR) .sp ClientData \fBTcl_GetChannelInstanceData\fR(\fIchannel\fR) .sp const Tcl_ChannelType * \fBTcl_GetChannelType\fR(\fIchannel\fR) .sp const char * \fBTcl_GetChannelName\fR(\fIchannel\fR) .sp int \fBTcl_GetChannelHandle\fR(\fIchannel, direction, handlePtr\fR) .sp Tcl_ThreadId \fBTcl_GetChannelThread\fR(\fIchannel\fR) .sp int \fBTcl_GetChannelMode\fR(\fIchannel\fR) .sp int \fBTcl_GetChannelBufferSize\fR(\fIchannel\fR) .sp \fBTcl_SetChannelBufferSize\fR(\fIchannel, size\fR) .sp \fBTcl_NotifyChannel\fR(\fIchannel, mask\fR) .sp int \fBTcl_BadChannelOption\fR(\fIinterp, optionName, optionList\fR) .sp int \fBTcl_IsChannelShared\fR(\fIchannel\fR) .sp int \fBTcl_IsChannelRegistered\fR(\fIinterp, channel\fR) .sp int \fBTcl_IsChannelExisting\fR(\fIchannelName\fR) .sp void \fBTcl_CutChannel\fR(\fIchannel\fR) .sp void \fBTcl_SpliceChannel\fR(\fIchannel\fR) .sp void \fBTcl_ClearChannelHandlers\fR(\fIchannel\fR) .sp int \fBTcl_ChannelBuffered\fR(\fIchannel\fR) .sp const char * \fBTcl_ChannelName\fR(\fItypePtr\fR) .sp Tcl_ChannelTypeVersion \fBTcl_ChannelVersion\fR(\fItypePtr\fR) .sp Tcl_DriverBlockModeProc * \fBTcl_ChannelBlockModeProc\fR(\fItypePtr\fR) .sp Tcl_DriverCloseProc * \fBTcl_ChannelCloseProc\fR(\fItypePtr\fR) .sp Tcl_DriverClose2Proc * \fBTcl_ChannelClose2Proc\fR(\fItypePtr\fR) .sp Tcl_DriverInputProc * \fBTcl_ChannelInputProc\fR(\fItypePtr\fR) .sp Tcl_DriverOutputProc * \fBTcl_ChannelOutputProc\fR(\fItypePtr\fR) .sp Tcl_DriverSeekProc * \fBTcl_ChannelSeekProc\fR(\fItypePtr\fR) .sp Tcl_DriverWideSeekProc * \fBTcl_ChannelWideSeekProc\fR(\fItypePtr\fR) .sp Tcl_DriverThreadActionProc * \fBTcl_ChannelThreadActionProc\fR(\fItypePtr\fR) .sp Tcl_DriverTruncateProc * \fBTcl_ChannelTruncateProc\fR(\fItypePtr\fR) .sp Tcl_DriverSetOptionProc * \fBTcl_ChannelSetOptionProc\fR(\fItypePtr\fR) .sp Tcl_DriverGetOptionProc * \fBTcl_ChannelGetOptionProc\fR(\fItypePtr\fR) .sp Tcl_DriverWatchProc * \fBTcl_ChannelWatchProc\fR(\fItypePtr\fR) .sp Tcl_DriverGetHandleProc * \fBTcl_ChannelGetHandleProc\fR(\fItypePtr\fR) .sp Tcl_DriverFlushProc * \fBTcl_ChannelFlushProc\fR(\fItypePtr\fR) .sp Tcl_DriverHandlerProc * \fBTcl_ChannelHandlerProc\fR(\fItypePtr\fR) .sp .SH ARGUMENTS .AS "const Tcl_ChannelType" *channelName .AP "const Tcl_ChannelType" *typePtr in Points to a structure containing the addresses of procedures that can be called to perform I/O and other functions on the channel. .AP "const char" *channelName in The name of this channel, such as \fBfile3\fR; must not be in use by any other channel. Can be NULL, in which case the channel is created without a name. If the created channel is assigned to one of the standard channels (\fBstdin\fR, \fBstdout\fR or \fBstderr\fR), the assigned channel name will be the name of the standard channel. .AP ClientData instanceData in Arbitrary one-word value to be associated with this channel. This value is passed to procedures in \fItypePtr\fR when they are invoked. .AP int mask in OR-ed combination of \fBTCL_READABLE\fR and \fBTCL_WRITABLE\fR to indicate whether a channel is readable and writable. .AP Tcl_Channel channel in The channel to operate on. .AP int direction in \fBTCL_READABLE\fR means the input handle is wanted; \fBTCL_WRITABLE\fR means the output handle is wanted. .AP ClientData *handlePtr out Points to the location where the desired OS-specific handle should be stored. .AP int size in The size, in bytes, of buffers to allocate in this channel. .AP int mask in An OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR and \fBTCL_EXCEPTION\fR that indicates events that have occurred on this channel. .AP Tcl_Interp *interp in Current interpreter. (can be NULL) .AP "const char" *optionName in Name of the invalid option. .AP "const char" *optionList in Specific options list (space separated words, without .QW \- ) to append to the standard generic options list. Can be NULL for generic options error message only. .BE .SH DESCRIPTION .PP Tcl uses a two-layered channel architecture. It provides a generic upper layer to enable C and Tcl programs to perform input and output using the same APIs for a variety of files, devices, sockets etc. The generic C APIs are described in the manual entry for \fBTcl_OpenFileChannel\fR. .PP The lower layer provides type-specific channel drivers for each type of device supported on each platform. This manual entry describes the C APIs used to communicate between the generic layer and the type-specific channel drivers. It also explains how new types of channels can be added by providing new channel drivers. .PP Channel drivers consist of a number of components: First, each channel driver provides a \fBTcl_ChannelType\fR structure containing pointers to functions implementing the various operations used by the generic layer to communicate with the channel driver. The \fBTcl_ChannelType\fR structure and the functions referenced by it are described in the section \fBTCL_CHANNELTYPE\fR, below. .PP Second, channel drivers usually provide a Tcl command to create instances of that type of channel. For example, the Tcl \fBopen\fR command creates channels that use the file and command channel drivers, and the Tcl \fBsocket\fR command creates channels that use TCP sockets for network communication. .PP Third, a channel driver optionally provides a C function to open channel instances of that type. For example, \fBTcl_OpenFileChannel\fR opens a channel that uses the file channel driver, and \fBTcl_OpenTcpClient\fR opens a channel that uses the TCP network protocol. These creation functions typically use \fBTcl_CreateChannel\fR internally to open the channel. .PP To add a new type of channel you must implement a C API or a Tcl command that opens a channel by invoking \fBTcl_CreateChannel\fR. When your driver calls \fBTcl_CreateChannel\fR it passes in a \fBTcl_ChannelType\fR structure describing the driver's I/O procedures. The generic layer will then invoke the functions referenced in that structure to perform operations on the channel. .PP \fBTcl_CreateChannel\fR opens a new channel and associates the supplied \fItypePtr\fR and \fIinstanceData\fR with it. The channel is opened in the mode indicated by \fImask\fR. For a discussion of channel drivers, their operations and the \fBTcl_ChannelType\fR structure, see the section \fBTCL_CHANNELTYPE\fR, below. .PP \fBTcl_CreateChannel\fR interacts with the code managing the standard channels. Once a standard channel was initialized either through a call to \fBTcl_GetStdChannel\fR or a call to \fBTcl_SetStdChannel\fR closing this standard channel will cause the next call to \fBTcl_CreateChannel\fR to make the new channel the new standard channel too. See \fBTcl_StandardChannels\fR for a general treatise about standard channels and the behavior of the Tcl library with regard to them. .PP \fBTcl_GetChannelInstanceData\fR returns the instance data associated with the channel in \fIchannel\fR. This is the same as the \fIinstanceData\fR argument in the call to \fBTcl_CreateChannel\fR that created this channel. .PP \fBTcl_GetChannelType\fR returns a pointer to the \fBTcl_ChannelType\fR structure used by the channel in the \fIchannel\fR argument. This is the same as the \fItypePtr\fR argument in the call to \fBTcl_CreateChannel\fR that created this channel. .PP \fBTcl_GetChannelName\fR returns a string containing the name associated with the channel, or NULL if the \fIchannelName\fR argument to \fBTcl_CreateChannel\fR was NULL. .PP \fBTcl_GetChannelHandle\fR places the OS-specific device handle associated with \fIchannel\fR for the given \fIdirection\fR in the location specified by \fIhandlePtr\fR and returns \fBTCL_OK\fR. If the channel does not have a device handle for the specified direction, then \fBTCL_ERROR\fR is returned instead. Different channel drivers will return different types of handle. Refer to the manual entries for each driver to determine what type of handle is returned. .PP \fBTcl_GetChannelThread\fR returns the id of the thread currently managing the specified \fIchannel\fR. This allows channel drivers to send their file events to the correct event queue even for a multi-threaded core. .PP \fBTcl_GetChannelMode\fR returns an OR-ed combination of \fBTCL_READABLE\fR and \fBTCL_WRITABLE\fR, indicating whether the channel is open for input and output. .PP \fBTcl_GetChannelBufferSize\fR returns the size, in bytes, of buffers allocated to store input or output in \fIchannel\fR. If the value was not set by a previous call to \fBTcl_SetChannelBufferSize\fR, described below, then the default value of 4096 is returned. .PP \fBTcl_SetChannelBufferSize\fR sets the size, in bytes, of buffers that will be allocated in subsequent operations on the channel to store input or output. The \fIsize\fR argument should be between one and one million, allowing buffers of one byte to one million bytes. If \fIsize\fR is outside this range, \fBTcl_SetChannelBufferSize\fR sets the buffer size to 4096. .PP \fBTcl_NotifyChannel\fR is called by a channel driver to indicate to the generic layer that the events specified by \fImask\fR have occurred on the channel. Channel drivers are responsible for invoking this function whenever the channel handlers need to be called for the channel. See \fBWATCHPROC\fR below for more details. .PP \fBTcl_BadChannelOption\fR is called from driver specific \fIsetOptionProc\fR or \fIgetOptionProc\fR to generate a complete error message. .PP \fBTcl_ChannelBuffered\fR returns the number of bytes of input currently buffered in the internal buffer (push back area) of the channel itself. It does not report about the data in the overall buffers for the stack of channels the supplied channel is part of. .PP \fBTcl_IsChannelShared\fR checks the refcount of the specified \fIchannel\fR and returns whether the \fIchannel\fR was shared among multiple interpreters (result == 1) or not (result == 0). .PP \fBTcl_IsChannelRegistered\fR checks whether the specified \fIchannel\fR is registered in the given \fIinterp\fRreter (result == 1) or not (result == 0). .PP \fBTcl_IsChannelExisting\fR checks whether a channel with the specified name is registered in the (thread)-global list of all channels (result == 1) or not (result == 0). .PP \fBTcl_CutChannel\fR removes the specified \fIchannel\fR from the (thread)global list of all channels (of the current thread). Application to a channel still registered in some interpreter is not allowed. Also notifies the driver if the \fBTcl_ChannelType\fR version is \fBTCL_CHANNEL_VERSION_4\fR (or higher), and \fBTcl_DriverThreadActionProc\fR is defined for it. .PP \fBTcl_SpliceChannel\fR adds the specified \fIchannel\fR to the (thread)global list of all channels (of the current thread). Application to a channel registered in some interpreter is not allowed. Also notifies the driver if the \fBTcl_ChannelType\fR version is \fBTCL_CHANNEL_VERSION_4\fR (or higher), and \fBTcl_DriverThreadActionProc\fR is defined for it. .PP \fBTcl_ClearChannelHandlers\fR removes all channel handlers and event scripts associated with the specified \fIchannel\fR, thus shutting down all event processing for this channel. .SH TCL_CHANNELTYPE .PP A channel driver provides a \fBTcl_ChannelType\fR structure that contains pointers to functions that implement the various operations on a channel; these operations are invoked as needed by the generic layer. The structure was versioned starting in Tcl 8.3.2/8.4 to correct a problem with stacked channel drivers. See the \fBOLD CHANNEL TYPES\fR section below for details about the old structure. .PP The \fBTcl_ChannelType\fR structure contains the following fields: .PP .CS typedef struct Tcl_ChannelType { const char *\fItypeName\fR; Tcl_ChannelTypeVersion \fIversion\fR; Tcl_DriverCloseProc *\fIcloseProc\fR; Tcl_DriverInputProc *\fIinputProc\fR; Tcl_DriverOutputProc *\fIoutputProc\fR; Tcl_DriverSeekProc *\fIseekProc\fR; Tcl_DriverSetOptionProc *\fIsetOptionProc\fR; Tcl_DriverGetOptionProc *\fIgetOptionProc\fR; Tcl_DriverWatchProc *\fIwatchProc\fR; Tcl_DriverGetHandleProc *\fIgetHandleProc\fR; Tcl_DriverClose2Proc *\fIclose2Proc\fR; Tcl_DriverBlockModeProc *\fIblockModeProc\fR; Tcl_DriverFlushProc *\fIflushProc\fR; Tcl_DriverHandlerProc *\fIhandlerProc\fR; Tcl_DriverWideSeekProc *\fIwideSeekProc\fR; Tcl_DriverThreadActionProc *\fIthreadActionProc\fR; Tcl_DriverTruncateProc *\fItruncateProc\fR; } \fBTcl_ChannelType\fR; .CE .PP It is not necessary to provide implementations for all channel operations. Those which are not necessary may be set to NULL in the struct: \fIblockModeProc\fR, \fIseekProc\fR, \fIsetOptionProc\fR, \fIgetOptionProc\fR, \fIgetHandleProc\fR, and \fIclose2Proc\fR, in addition to \fIflushProc\fR, \fIhandlerProc\fR, \fIthreadActionProc\fR, and \fItruncateProc\fR. Other functions that cannot be implemented in a meaningful way should return \fBEINVAL\fR when called, to indicate that the operations they represent are not available. Also note that \fIwideSeekProc\fR can be NULL if \fIseekProc\fR is. .PP The user should only use the above structure for \fBTcl_ChannelType\fR instantiation. When referencing fields in a \fBTcl_ChannelType\fR structure, the following functions should be used to obtain the values: \fBTcl_ChannelName\fR, \fBTcl_ChannelVersion\fR, \fBTcl_ChannelBlockModeProc\fR, \fBTcl_ChannelCloseProc\fR, \fBTcl_ChannelClose2Proc\fR, \fBTcl_ChannelInputProc\fR, \fBTcl_ChannelOutputProc\fR, \fBTcl_ChannelSeekProc\fR, \fBTcl_ChannelWideSeekProc\fR, \fBTcl_ChannelThreadActionProc\fR, \fBTcl_ChannelTruncateProc\fR, \fBTcl_ChannelSetOptionProc\fR, \fBTcl_ChannelGetOptionProc\fR, \fBTcl_ChannelWatchProc\fR, \fBTcl_ChannelGetHandleProc\fR, \fBTcl_ChannelFlushProc\fR, or \fBTcl_ChannelHandlerProc\fR. .PP The change to the structures was made in such a way that standard channel types are binary compatible. However, channel types that use stacked channels (i.e. TLS, Trf) have new versions to correspond to the above change since the previous code for stacked channels had problems. .SS TYPENAME .PP The \fItypeName\fR field contains a null-terminated string that identifies the type of the device implemented by this driver, e.g. \fBfile\fR or \fBsocket\fR. .PP This value can be retrieved with \fBTcl_ChannelName\fR, which returns a pointer to the string. .SS VERSION .PP The \fIversion\fR field should be set to the version of the structure that you require. \fBTCL_CHANNEL_VERSION_2\fR is the minimum recommended. \fBTCL_CHANNEL_VERSION_3\fR must be set to specify the \fIwideSeekProc\fR member. \fBTCL_CHANNEL_VERSION_4\fR must be set to specify the \fIthreadActionProc\fR member (includes \fIwideSeekProc\fR). \fBTCL_CHANNEL_VERSION_5\fR must be set to specify the \fItruncateProc\fR members (includes \fIwideSeekProc\fR and \fIthreadActionProc\fR). If it is not set to any of these, then this \fBTcl_ChannelType\fR is assumed to have the original structure. See \fBOLD CHANNEL TYPES\fR for more details. While Tcl will recognize and function with either structures, stacked channels must be of at least \fBTCL_CHANNEL_VERSION_2\fR to function correctly. .PP This value can be retrieved with \fBTcl_ChannelVersion\fR, which returns one of \fBTCL_CHANNEL_VERSION_5\fR, \fBTCL_CHANNEL_VERSION_4\fR, \fBTCL_CHANNEL_VERSION_3\fR, \fBTCL_CHANNEL_VERSION_2\fR or \fBTCL_CHANNEL_VERSION_1\fR. .SS BLOCKMODEPROC .PP The \fIblockModeProc\fR field contains the address of a function called by the generic layer to set blocking and nonblocking mode on the device. \fIBlockModeProc\fR should match the following prototype: .PP .CS typedef int \fBTcl_DriverBlockModeProc\fR( ClientData \fIinstanceData\fR, int \fImode\fR); .CE .PP The \fIinstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR when this channel was created. The \fImode\fR argument is either \fBTCL_MODE_BLOCKING\fR or \fBTCL_MODE_NONBLOCKING\fR to set the device into blocking or nonblocking mode. The function should return zero if the operation was successful, or a nonzero POSIX error code if the operation failed. .PP If the operation is successful, the function can modify the supplied \fIinstanceData\fR to record that the channel entered blocking or nonblocking mode and to implement the blocking or nonblocking behavior. For some device types, the blocking and nonblocking behavior can be implemented by the underlying operating system; for other device types, the behavior must be emulated in the channel driver. .PP This value can be retrieved with \fBTcl_ChannelBlockModeProc\fR, which returns a pointer to the function. .PP A channel driver \fBnot\fR supplying a \fIblockModeProc\fR has to be very, very careful. It has to tell the generic layer exactly which blocking mode is acceptable to it, and should this also document for the user so that the blocking mode of the channel is not changed to an unacceptable value. Any confusion here may lead the interpreter into a (spurious and difficult to find) deadlock. .SS "CLOSEPROC AND CLOSE2PROC" .PP The \fIcloseProc\fR field contains the address of a function called by the generic layer to clean up driver-related information when the channel is closed. \fICloseProc\fR must match the following prototype: .PP .CS typedef int \fBTcl_DriverCloseProc\fR( ClientData \fIinstanceData\fR, Tcl_Interp *\fIinterp\fR); .CE .PP The \fIinstanceData\fR argument is the same as the value provided to \fBTcl_CreateChannel\fR when the channel was created. The function should release any storage maintained by the channel driver for this channel, and close the input and output devices encapsulated by this channel. All queued output will have been flushed to the device before this function is called, and no further driver operations will be invoked on this instance after calling the \fIcloseProc\fR. If the close operation is successful, the procedure should return zero; otherwise it should return a nonzero POSIX error code. In addition, if an error occurs and \fIinterp\fR is not NULL, the procedure should store an error message in the interpreter's result. .PP Alternatively, channels that support closing the read and write sides independently may set \fIcloseProc\fR to \fBTCL_CLOSE2PROC\fR and set \fIclose2Proc\fR to the address of a function that matches the following prototype: .PP .CS typedef int \fBTcl_DriverClose2Proc\fR( ClientData \fIinstanceData\fR, Tcl_Interp *\fIinterp\fR, int \fIflags\fR); .CE .PP The \fIclose2Proc\fR will be called with \fIflags\fR set to an OR'ed combination of \fBTCL_CLOSE_READ\fR or \fBTCL_CLOSE_WRITE\fR to indicate that the driver should close the read and/or write side of the channel. The channel driver may be invoked to perform additional operations on the channel after \fIclose2Proc\fR is called to close one or both sides of the channel. If \fIflags\fR is \fB0\fR (zero), the driver should close the channel in the manner described above for \fIcloseProc\fR. No further operations will be invoked on this instance after \fIclose2Proc\fR is called with all flags cleared. In all cases, the \fIclose2Proc\fR function should return zero if the close operation was successful; otherwise it should return a nonzero POSIX error code. In addition, if an error occurs and \fIinterp\fR is not NULL, the procedure should store an error message in the interpreter's result. .PP The \fIcloseProc\fR and \fIclose2Proc\fR values can be retrieved with \fBTcl_ChannelCloseProc\fR or \fBTcl_ChannelClose2Proc\fR, which return a pointer to the respective function. .SS INPUTPROC .PP The \fIinputProc\fR field contains the address of a function called by the generic layer to read data from the file or device and store it in an internal buffer. \fIInputProc\fR must match the following prototype: .PP .CS typedef int \fBTcl_DriverInputProc\fR( ClientData \fIinstanceData\fR, char *\fIbuf\fR, int \fIbufSize\fR, int *\fIerrorCodePtr\fR); .CE .PP \fIInstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR when the channel was created. The \fIbuf\fR argument points to an array of bytes in which to store input from the device, and the \fIbufSize\fR argument indicates how many bytes are available at \fIbuf\fR. .PP The \fIerrorCodePtr\fR argument points to an integer variable provided by the generic layer. If an error occurs, the function should set the variable to a POSIX error code that identifies the error that occurred. .PP The function should read data from the input device encapsulated by the channel and store it at \fIbuf\fR. On success, the function should return a nonnegative integer indicating how many bytes were read from the input device and stored at \fIbuf\fR. On error, the function should return -1. If an error occurs after some data has been read from the device, that data is lost. .PP If \fIinputProc\fR can determine that the input device has some data available but less than requested by the \fIbufSize\fR argument, the function should only attempt to read as much data as is available and return without blocking. If the input device has no data available whatsoever and the channel is in nonblocking mode, the function should return an \fBEAGAIN\fR error. If the input device has no data available whatsoever and the channel is in blocking mode, the function should block for the shortest possible time until at least one byte of data can be read from the device; then, it should return as much data as it can read without blocking. .PP This value can be retrieved with \fBTcl_ChannelInputProc\fR, which returns a pointer to the function. .SS OUTPUTPROC .PP The \fIoutputProc\fR field contains the address of a function called by the generic layer to transfer data from an internal buffer to the output device. \fIOutputProc\fR must match the following prototype: .PP .CS typedef int \fBTcl_DriverOutputProc\fR( ClientData \fIinstanceData\fR, const char *\fIbuf\fR, int \fItoWrite\fR, int *\fIerrorCodePtr\fR); .CE .PP \fIInstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR when the channel was created. The \fIbuf\fR argument contains an array of bytes to be written to the device, and the \fItoWrite\fR argument indicates how many bytes are to be written from the \fIbuf\fR argument. .PP The \fIerrorCodePtr\fR argument points to an integer variable provided by the generic layer. If an error occurs, the function should set this variable to a POSIX error code that identifies the error. .PP The function should write the data at \fIbuf\fR to the output device encapsulated by the channel. On success, the function should return a nonnegative integer indicating how many bytes were written to the output device. The return value is normally the same as \fItoWrite\fR, but may be less in some cases such as if the output operation is interrupted by a signal. If an error occurs the function should return -1. In case of error, some data may have been written to the device. .PP If the channel is nonblocking and the output device is unable to absorb any data whatsoever, the function should return -1 with an \fBEAGAIN\fR error without writing any data. .PP This value can be retrieved with \fBTcl_ChannelOutputProc\fR, which returns a pointer to the function. .SS "SEEKPROC AND WIDESEEKPROC" .PP The \fIseekProc\fR field contains the address of a function called by the generic layer to move the access point at which subsequent input or output operations will be applied. \fISeekProc\fR must match the following prototype: .PP .CS typedef int \fBTcl_DriverSeekProc\fR( ClientData \fIinstanceData\fR, long \fIoffset\fR, int \fIseekMode\fR, int *\fIerrorCodePtr\fR); .CE .PP The \fIinstanceData\fR argument is the same as the value given to \fBTcl_CreateChannel\fR when this channel was created. \fIOffset\fR and \fIseekMode\fR have the same meaning as for the \fBTcl_Seek\fR procedure (described in the manual entry for \fBTcl_OpenFileChannel\fR). .PP The \fIerrorCodePtr\fR argument points to an integer variable provided by the generic layer for returning \fBerrno\fR values from the function. The function should set this variable to a POSIX error code if an error occurs. The function should store an \fBEINVAL\fR error code if the channel type does not implement seeking. .PP The return value is the new access point or -1 in case of error. If an error occurred, the function should not move the access point. .PP If there is a non-NULL \fIseekProc\fR field, the \fIwideSeekProc\fR field may contain the address of an alternative function to use which handles wide (i.e. larger than 32-bit) offsets, so allowing seeks within files larger than 2GB. The \fIwideSeekProc\fR will be called in preference to the \fIseekProc\fR, but both must be defined if the \fIwideSeekProc\fR is defined. \fIWideSeekProc\fR must match the following prototype: .PP .CS typedef Tcl_WideInt \fBTcl_DriverWideSeekProc\fR( ClientData \fIinstanceData\fR, Tcl_WideInt \fIoffset\fR, int \fIseekMode\fR, int *\fIerrorCodePtr\fR); .CE .PP The arguments and return values mean the same thing as with \fIseekProc\fR above, except that the type of offsets and the return type are different. .PP The \fIseekProc\fR value can be retrieved with \fBTcl_ChannelSeekProc\fR, which returns a pointer to the function, and similarly the \fIwideSeekProc\fR can be retrieved with \fBTcl_ChannelWideSeekProc\fR. .SS SETOPTIONPROC .PP The \fIsetOptionProc\fR field contains the address of a function called by the generic layer to set a channel type specific option on a channel. \fIsetOptionProc\fR must match the following prototype: .PP .CS typedef int \fBTcl_DriverSetOptionProc\fR( ClientData \fIinstanceData\fR, Tcl_Interp *\fIinterp\fR, const char *\fIoptionName\fR, const char *\fInewValue\fR); .CE .PP \fIoptionName\fR is the name of an option to set, and \fInewValue\fR is the new value for that option, as a string. The \fIinstanceData\fR is the same as the value given to \fBTcl_CreateChannel\fR when this channel was created. The function should do whatever channel type specific action is required to implement the new value of the option. .PP Some options are handled by the generic code and this function is never called to set them, e.g. \fB\-blockmode\fR. Other options are specific to each channel type and the \fIsetOptionProc\fR procedure of the channel driver will get called to implement them. The \fIsetOptionProc\fR field can be NULL, which indicates that this channel type supports no type specific options. .PP If the option value is successfully modified to the new value, the function returns \fBTCL_OK\fR. It should call \fBTcl_BadChannelOption\fR which itself returns \fBTCL_ERROR\fR if the \fIoptionName\fR is unrecognized. If \fInewValue\fR specifies a value for the option that is not supported or if a system call error occurs, the function should leave an error message in the \fIresult\fR field of \fIinterp\fR if \fIinterp\fR is not NULL. The function should also call \fBTcl_SetErrno\fR to store an appropriate POSIX error code. .PP This value can be retrieved with \fBTcl_ChannelSetOptionProc\fR, which returns a pointer to the function. .SS GETOPTIONPROC .PP The \fIgetOptionProc\fR field contains the address of a function called by the generic layer to get the value of a channel type specific option on a channel. \fIgetOptionProc\fR must match the following prototype: .PP .CS typedef int \fBTcl_DriverGetOptionProc\fR( ClientData \fIinstanceData\fR, Tcl_Interp *\fIinterp\fR, const char *\fIoptionName\fR, Tcl_DString *\fIoptionValue\fR); .CE .PP \fIOptionName\fR is the name of an option supported by this type of channel. If the option name is not NULL, the function stores its current value, as a string, in the Tcl dynamic string \fIoptionValue\fR. If \fIoptionName\fR is NULL, the function stores in \fIoptionValue\fR an alternating list of all supported options and their current values. On success, the function returns \fBTCL_OK\fR. It should call \fBTcl_BadChannelOption\fR which itself returns \fBTCL_ERROR\fR if the \fIoptionName\fR is unrecognized. If a system call error occurs, the function should leave an error message in the result of \fIinterp\fR if \fIinterp\fR is not NULL. The function should also call \fBTcl_SetErrno\fR to store an appropriate POSIX error code. .PP Some options are handled by the generic code and this function is never called to retrieve their value, e.g. \fB\-blockmode\fR. Other options are specific to each channel type and the \fIgetOptionProc\fR procedure of the channel driver will get called to implement them. The \fIgetOptionProc\fR field can be NULL, which indicates that this channel type supports no type specific options. .PP This value can be retrieved with \fBTcl_ChannelGetOptionProc\fR, which returns a pointer to the function. .SS WATCHPROC .PP The \fIwatchProc\fR field contains the address of a function called by the generic layer to initialize the event notification mechanism to notice events of interest on this channel. \fIWatchProc\fR should match the following prototype: .PP .CS typedef void \fBTcl_DriverWatchProc\fR( ClientData \fIinstanceData\fR, int \fImask\fR); .CE .PP The \fIinstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR when this channel was created. The \fImask\fR argument is an OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR and \fBTCL_EXCEPTION\fR; it indicates events the caller is interested in noticing on this channel. .PP The function should initialize device type specific mechanisms to notice when an event of interest is present on the channel. When one or more of the designated events occurs on the channel, the channel driver is responsible for calling \fBTcl_NotifyChannel\fR to inform the generic channel module. The driver should take care not to starve other channel drivers or sources of callbacks by invoking Tcl_NotifyChannel too frequently. Fairness can be insured by using the Tcl event queue to allow the channel event to be scheduled in sequence with other events. See the description of \fBTcl_QueueEvent\fR for details on how to queue an event. .PP This value can be retrieved with \fBTcl_ChannelWatchProc\fR, which returns a pointer to the function. .SS GETHANDLEPROC .PP The \fIgetHandleProc\fR field contains the address of a function called by the generic layer to retrieve a device-specific handle from the channel. \fIGetHandleProc\fR should match the following prototype: .PP .CS typedef int \fBTcl_DriverGetHandleProc\fR( ClientData \fIinstanceData\fR, int \fIdirection\fR, ClientData *\fIhandlePtr\fR); .CE .PP \fIInstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR when this channel was created. The \fIdirection\fR argument is either \fBTCL_READABLE\fR to retrieve the handle used for input, or \fBTCL_WRITABLE\fR to retrieve the handle used for output. .PP If the channel implementation has device-specific handles, the function should retrieve the appropriate handle associated with the channel, according the \fIdirection\fR argument. The handle should be stored in the location referred to by \fIhandlePtr\fR, and \fBTCL_OK\fR should be returned. If the channel is not open for the specified direction, or if the channel implementation does not use device handles, the function should return \fBTCL_ERROR\fR. .PP This value can be retrieved with \fBTcl_ChannelGetHandleProc\fR, which returns a pointer to the function. .SS FLUSHPROC .PP The \fIflushProc\fR field is currently reserved for future use. It should be set to NULL. \fIFlushProc\fR should match the following prototype: .PP .CS typedef int \fBTcl_DriverFlushProc\fR( ClientData \fIinstanceData\fR); .CE .PP This value can be retrieved with \fBTcl_ChannelFlushProc\fR, which returns a pointer to the function. .SS HANDLERPROC .PP The \fIhandlerProc\fR field contains the address of a function called by the generic layer to notify the channel that an event occurred. It should be defined for stacked channel drivers that wish to be notified of events that occur on the underlying (stacked) channel. \fIHandlerProc\fR should match the following prototype: .PP .CS typedef int \fBTcl_DriverHandlerProc\fR( ClientData \fIinstanceData\fR, int \fIinterestMask\fR); .CE .PP \fIInstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR when this channel was created. The \fIinterestMask\fR is an OR-ed combination of \fBTCL_READABLE\fR or \fBTCL_WRITABLE\fR; it indicates what type of event occurred on this channel. .PP This value can be retrieved with \fBTcl_ChannelHandlerProc\fR, which returns a pointer to the function. .SS "THREADACTIONPROC" .PP The \fIthreadActionProc\fR field contains the address of the function called by the generic layer when a channel is created, closed, or going to move to a different thread, i.e. whenever thread-specific driver state might have to initialized or updated. It can be NULL. The action \fITCL_CHANNEL_THREAD_REMOVE\fR is used to notify the driver that it should update or remove any thread-specific data it might be maintaining for the channel. .PP The action \fITCL_CHANNEL_THREAD_INSERT\fR is used to notify the driver that it should update or initialize any thread-specific data it might be maintaining using the calling thread as the associate. See \fBTcl_CutChannel\fR and \fBTcl_SpliceChannel\fR for more detail. .PP .CS typedef void \fBTcl_DriverThreadActionProc\fR( ClientData \fIinstanceData\fR, int \fIaction\fR); .CE .PP \fIInstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR when this channel was created. .PP These values can be retrieved with \fBTcl_ChannelThreadActionProc\fR, which returns a pointer to the function. .SS "TRUNCATEPROC" .PP The \fItruncateProc\fR field contains the address of the function called by the generic layer when a channel is truncated to some length. It can be NULL. .PP .CS typedef int \fBTcl_DriverTruncateProc\fR( ClientData \fIinstanceData\fR, Tcl_WideInt \fIlength\fR); .CE .PP \fIInstanceData\fR is the same as the value passed to \fBTcl_CreateChannel\fR when this channel was created, and \fIlength\fR is the new length of the underlying file, which should not be negative. The result should be 0 on success or an errno code (suitable for use with \fBTcl_SetErrno\fR) on failure. .PP These values can be retrieved with \fBTcl_ChannelTruncateProc\fR, which returns a pointer to the function. .SH TCL_BADCHANNELOPTION .PP This procedure generates a .QW "bad option" error message in an (optional) interpreter. It is used by channel drivers when an invalid Set/Get option is requested. Its purpose is to concatenate the generic options list to the specific ones and factorize the generic options error message string. .PP It always returns \fBTCL_ERROR\fR .PP An error message is generated in \fIinterp\fR's result value to indicate that a command was invoked with a bad option. The message has the form .CS bad option "blah": should be one of <...generic options...>+<...specific options...> .CE so you get for instance: .CS bad option "-blah": should be one of -blocking, -buffering, -buffersize, -eofchar, -translation, -peername, or -sockname .CE when called with \fIoptionList\fR equal to .QW "peername sockname" .PP .QW blah is the \fIoptionName\fR argument and .QW "" is a space separated list of specific option words. The function takes good care of inserting minus signs before each option, commas after, and an .QW or before the last option. .SH "OLD CHANNEL TYPES" The original (8.3.1 and below) \fBTcl_ChannelType\fR structure contains the following fields: .PP .CS typedef struct Tcl_ChannelType { const char *\fItypeName\fR; Tcl_DriverBlockModeProc *\fIblockModeProc\fR; Tcl_DriverCloseProc *\fIcloseProc\fR; Tcl_DriverInputProc *\fIinputProc\fR; Tcl_DriverOutputProc *\fIoutputProc\fR; Tcl_DriverSeekProc *\fIseekProc\fR; Tcl_DriverSetOptionProc *\fIsetOptionProc\fR; Tcl_DriverGetOptionProc *\fIgetOptionProc\fR; Tcl_DriverWatchProc *\fIwatchProc\fR; Tcl_DriverGetHandleProc *\fIgetHandleProc\fR; Tcl_DriverClose2Proc *\fIclose2Proc\fR; } \fBTcl_ChannelType\fR; .CE .PP It is still possible to create channel with the above structure. The internal channel code will determine the version. It is imperative to use the new \fBTcl_ChannelType\fR structure if you are creating a stacked channel driver, due to problems with the earlier stacked channel implementation (in 8.2.0 to 8.3.1). .PP Prior to 8.4.0 (i.e. during the later releases of 8.3 and early part of the 8.4 development cycle) the \fBTcl_ChannelType\fR structure contained the following fields: .PP .CS typedef struct Tcl_ChannelType { const char *\fItypeName\fR; Tcl_ChannelTypeVersion \fIversion\fR; Tcl_DriverCloseProc *\fIcloseProc\fR; Tcl_DriverInputProc *\fIinputProc\fR; Tcl_DriverOutputProc *\fIoutputProc\fR; Tcl_DriverSeekProc *\fIseekProc\fR; Tcl_DriverSetOptionProc *\fIsetOptionProc\fR; Tcl_DriverGetOptionProc *\fIgetOptionProc\fR; Tcl_DriverWatchProc *\fIwatchProc\fR; Tcl_DriverGetHandleProc *\fIgetHandleProc\fR; Tcl_DriverClose2Proc *\fIclose2Proc\fR; Tcl_DriverBlockModeProc *\fIblockModeProc\fR; Tcl_DriverFlushProc *\fIflushProc\fR; Tcl_DriverHandlerProc *\fIhandlerProc\fR; Tcl_DriverTruncateProc *\fItruncateProc\fR; } \fBTcl_ChannelType\fR; .CE .PP When the above structure is registered as a channel type, the \fIversion\fR field should always be \fBTCL_CHANNEL_VERSION_2\fR. .SH "SEE ALSO" Tcl_Close(3), Tcl_OpenFileChannel(3), Tcl_SetErrno(3), Tcl_QueueEvent(3), Tcl_StackChannel(3), Tcl_GetStdChannel(3) .SH KEYWORDS blocking, channel driver, channel registration, channel type, nonblocking tcl8.6.5/doc/DumpActiveMemory.30000644000175000017500000000432712663660065015660 0ustar sergeisergei'\" '\" Copyright (c) 1992-1999 Karl Lehenbauer and Mark Diekhans. '\" Copyright (c) 2000 by Scriptics Corporation. '\" All rights reserved. '\" .TH "Tcl_DumpActiveMemory" 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_DumpActiveMemory, Tcl_InitMemory, Tcl_ValidateAllMemory \- Validated memory allocation interface .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_DumpActiveMemory\fR(\fIfileName\fR) .sp void \fBTcl_InitMemory\fR(\fIinterp\fR) .sp void \fBTcl_ValidateAllMemory\fR(\fIfileName, line\fR) .SH ARGUMENTS .AS Tcl_Interp *fileName .AP Tcl_Interp *interp in Tcl interpreter in which to add commands. .AP "const char" *fileName in For \fBTcl_DumpActiveMemory\fR, name of the file to which memory information will be written. For \fBTcl_ValidateAllMemory\fR, name of the file from which the call is being made (normally \fB__FILE__\fR). .AP int line in Line number at which the call to \fBTcl_ValidateAllMemory\fR is made (normally \fB__LINE__\fR). .BE .SH DESCRIPTION These functions provide access to Tcl memory debugging information. They are only functional when Tcl has been compiled with \fBTCL_MEM_DEBUG\fR defined at compile-time. When \fBTCL_MEM_DEBUG\fR is not defined, these functions are all no-ops. .PP \fBTcl_DumpActiveMemory\fR will output a list of all currently allocated memory to the specified file. The information output for each allocated block of memory is: starting and ending addresses (excluding guard zone), size, source file where \fBckalloc\fR was called to allocate the block and line number in that file. It is especially useful to call \fBTcl_DumpActiveMemory\fR after the Tcl interpreter has been deleted. .PP \fBTcl_InitMemory\fR adds the Tcl \fBmemory\fR command to the interpreter given by \fIinterp\fR. \fBTcl_InitMemory\fR is called by \fBTcl_Main\fR. .PP \fBTcl_ValidateAllMemory\fR forces a validation of the guard zones of all currently allocated blocks of memory. Normally validation of a block occurs when its freed, unless full validation is enabled, in which case validation of all blocks occurs when \fBckalloc\fR and \fBckfree\fR are called. This function forces the validation to occur at any point. .SH "SEE ALSO" TCL_MEM_DEBUG, memory .SH KEYWORDS memory, debug tcl8.6.5/doc/namespace.n0000644000175000017500000010646312663660065014461 0ustar sergeisergei'\" '\" Copyright (c) 1993-1997 Bell Labs Innovations for Lucent Technologies '\" Copyright (c) 1997 Sun Microsystems, Inc. '\" Copyright (c) 2000 Scriptics Corporation. '\" Copyright (c) 2004-2005 Donal K. Fellows. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH namespace n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME namespace \- create and manipulate contexts for commands and variables .SH SYNOPSIS \fBnamespace \fR?\fIsubcommand\fR? ?\fIarg ...\fR? .BE .SH DESCRIPTION .PP The \fBnamespace\fR command lets you create, access, and destroy separate contexts for commands and variables. See the section \fBWHAT IS A NAMESPACE?\fR below for a brief overview of namespaces. The legal values of \fIsubcommand\fR are listed below. Note that you can abbreviate the \fIsubcommand\fRs. .TP \fBnamespace children \fR?\fInamespace\fR? ?\fIpattern\fR? . Returns a list of all child namespaces that belong to the namespace \fInamespace\fR. If \fInamespace\fR is not specified, then the children are returned for the current namespace. This command returns fully-qualified names, which start with a double colon (\fB::\fR). If the optional \fIpattern\fR is given, then this command returns only the names that match the glob-style pattern. The actual pattern used is determined as follows: a pattern that starts with double colon (\fB::\fR) is used directly, otherwise the namespace \fInamespace\fR (or the fully-qualified name of the current namespace) is prepended onto the pattern. .TP \fBnamespace code \fIscript\fR . Captures the current namespace context for later execution of the script \fIscript\fR. It returns a new script in which \fIscript\fR has been wrapped in a \fBnamespace inscope\fR command. The new script has two important properties. First, it can be evaluated in any namespace and will cause \fIscript\fR to be evaluated in the current namespace (the one where the \fBnamespace code\fR command was invoked). Second, additional arguments can be appended to the resulting script and they will be passed to \fIscript\fR as additional arguments. For example, suppose the command \fBset script [namespace code {foo bar}]\fR is invoked in namespace \fB::a::b\fR. Then \fBeval $script [list x y]\fR can be executed in any namespace (assuming the value of \fBscript\fR has been passed in properly) and will have the same effect as the command \fB::namespace eval ::a::b {foo bar x y}\fR. This command is needed because extensions like Tk normally execute callback scripts in the global namespace. A scoped command captures a command together with its namespace context in a way that allows it to be executed properly later. See the section \fBSCOPED SCRIPTS\fR for some examples of how this is used to create callback scripts. .TP \fBnamespace current\fR . Returns the fully-qualified name for the current namespace. The actual name of the global namespace is .MT (i.e., an empty string), but this command returns \fB::\fR for the global namespace as a convenience to programmers. .TP \fBnamespace delete \fR?\fInamespace namespace ...\fR? . Each namespace \fInamespace\fR is deleted and all variables, procedures, and child namespaces contained in the namespace are deleted. If a procedure is currently executing inside the namespace, the namespace will be kept alive until the procedure returns; however, the namespace is marked to prevent other code from looking it up by name. If a namespace does not exist, this command returns an error. If no namespace names are given, this command does nothing. .TP \fBnamespace ensemble\fR \fIsubcommand\fR ?\fIarg ...\fR? . Creates and manipulates a command that is formed out of an ensemble of subcommands. See the section \fBENSEMBLES\fR below for further details. .TP \fBnamespace eval\fR \fInamespace arg\fR ?\fIarg ...\fR? . Activates a namespace called \fInamespace\fR and evaluates some code in that context. If the namespace does not already exist, it is created. If more than one \fIarg\fR argument is specified, the arguments are concatenated together with a space between each one in the same fashion as the \fBeval\fR command, and the result is evaluated. .RS .PP If \fInamespace\fR has leading namespace qualifiers and any leading namespaces do not exist, they are automatically created. .RE .TP \fBnamespace exists\fR \fInamespace\fR . Returns \fB1\fR if \fInamespace\fR is a valid namespace in the current context, returns \fB0\fR otherwise. .TP \fBnamespace export \fR?\fB\-clear\fR? ?\fIpattern pattern ...\fR? . Specifies which commands are exported from a namespace. The exported commands are those that can be later imported into another namespace using a \fBnamespace import\fR command. Both commands defined in a namespace and commands the namespace has previously imported can be exported by a namespace. The commands do not have to be defined at the time the \fBnamespace export\fR command is executed. Each \fIpattern\fR may contain glob-style special characters, but it may not include any namespace qualifiers. That is, the pattern can only specify commands in the current (exporting) namespace. Each \fIpattern\fR is appended onto the namespace's list of export patterns. If the \fB\-clear\fR flag is given, the namespace's export pattern list is reset to empty before any \fIpattern\fR arguments are appended. If no \fIpattern\fRs are given and the \fB\-clear\fR flag is not given, this command returns the namespace's current export list. .TP \fBnamespace forget \fR?\fIpattern pattern ...\fR? . Removes previously imported commands from a namespace. Each \fIpattern\fR is a simple or qualified name such as \fBx\fR, \fBfoo::x\fR or \fBa::b::p*\fR. Qualified names contain double colons (\fB::\fR) and qualify a name with the name of one or more namespaces. Each .QW "qualified pattern" is qualified with the name of an exporting namespace and may have glob-style special characters in the command name at the end of the qualified name. Glob characters may not appear in a namespace name. For each .QW "simple pattern" this command deletes the matching commands of the current namespace that were imported from a different namespace. For .QW "qualified patterns" , this command first finds the matching exported commands. It then checks whether any of those commands were previously imported by the current namespace. If so, this command deletes the corresponding imported commands. In effect, this un-does the action of a \fBnamespace import\fR command. .TP \fBnamespace import \fR?\fB\-force\fR? ?\fIpattern\fR \fIpattern ...\fR? . Imports commands into a namespace, or queries the set of imported commands in a namespace. When no arguments are present, \fBnamespace import\fR returns the list of commands in the current namespace that have been imported from other namespaces. The commands in the returned list are in the format of simple names, with no namespace qualifiers at all. This format is suitable for composition with \fBnamespace forget\fR (see \fBEXAMPLES\fR below). .RS .PP When \fIpattern\fR arguments are present, each \fIpattern\fR is a qualified name like \fBfoo::x\fR or \fBa::p*\fR. That is, it includes the name of an exporting namespace and may have glob-style special characters in the command name at the end of the qualified name. Glob characters may not appear in a namespace name. When the namespace name is not fully qualified (i.e., does not start with a namespace separator) it is resolved as a namespace name in the way described in the \fBNAME RESOLUTION\fR section; it is an error if no namespace with that name can be found. .PP All the commands that match a \fIpattern\fR string and which are currently exported from their namespace are added to the current namespace. This is done by creating a new command in the current namespace that points to the exported command in its original namespace; when the new imported command is called, it invokes the exported command. This command normally returns an error if an imported command conflicts with an existing command. However, if the \fB\-force\fR option is given, imported commands will silently replace existing commands. The \fBnamespace import\fR command has snapshot semantics: that is, only requested commands that are currently defined in the exporting namespace are imported. In other words, you can import only the commands that are in a namespace at the time when the \fBnamespace import\fR command is executed. If another command is defined and exported in this namespace later on, it will not be imported. .RE .TP \fBnamespace inscope\fR \fInamespace\fR \fIscript\fR ?\fIarg ...\fR? . Executes a script in the context of the specified \fInamespace\fR. This command is not expected to be used directly by programmers; calls to it are generated implicitly when applications use \fBnamespace code\fR commands to create callback scripts that the applications then register with, e.g., Tk widgets. The \fBnamespace inscope\fR command is much like the \fBnamespace eval\fR command except that the \fInamespace\fR must already exist, and \fBnamespace inscope\fR appends additional \fIarg\fRs as proper list elements. .RS .PP .CS \fBnamespace inscope ::foo $script $x $y $z\fR .CE .PP is equivalent to .PP .CS \fBnamespace eval ::foo [concat $script [list $x $y $z]]\fR .CE .PP thus additional arguments will not undergo a second round of substitution, as is the case with \fBnamespace eval\fR. .RE .TP \fBnamespace origin \fIcommand\fR . Returns the fully-qualified name of the original command to which the imported command \fIcommand\fR refers. When a command is imported into a namespace, a new command is created in that namespace that points to the actual command in the exporting namespace. If a command is imported into a sequence of namespaces \fIa, b,...,n\fR where each successive namespace just imports the command from the previous namespace, this command returns the fully-qualified name of the original command in the first namespace, \fIa\fR. If \fIcommand\fR does not refer to an imported command, the command's own fully-qualified name is returned. .TP \fBnamespace parent\fR ?\fInamespace\fR? . Returns the fully-qualified name of the parent namespace for namespace \fInamespace\fR. If \fInamespace\fR is not specified, the fully-qualified name of the current namespace's parent is returned. .TP \fBnamespace path\fR ?\fInamespaceList\fR? . Returns the command resolution path of the current namespace. If \fInamespaceList\fR is specified as a list of named namespaces, the current namespace's command resolution path is set to those namespaces and returns the empty list. The default command resolution path is always empty. See the section \fBNAME RESOLUTION\fR below for an explanation of the rules regarding name resolution. .TP \fBnamespace qualifiers\fR \fIstring\fR . Returns any leading namespace qualifiers for \fIstring\fR. Qualifiers are namespace names separated by double colons (\fB::\fR). For the \fIstring\fR \fB::foo::bar::x\fR, this command returns \fB::foo::bar\fR, and for \fB::\fR it returns an empty string. This command is the complement of the \fBnamespace tail\fR command. Note that it does not check whether the namespace names are, in fact, the names of currently defined namespaces. .TP \fBnamespace tail\fR \fIstring\fR . Returns the simple name at the end of a qualified string. Qualifiers are namespace names separated by double colons (\fB::\fR). For the \fIstring\fR \fB::foo::bar::x\fR, this command returns \fBx\fR, and for \fB::\fR it returns an empty string. This command is the complement of the \fBnamespace qualifiers\fR command. It does not check whether the namespace names are, in fact, the names of currently defined namespaces. .TP \fBnamespace upvar\fR \fInamespace\fR ?\fIotherVar myVar \fR...? . This command arranges for zero or more local variables in the current procedure to refer to variables in \fInamespace\fR. The namespace name is resolved as described in section \fBNAME RESOLUTION\fR. The command \fBnamespace upvar $ns a b\fR has the same behaviour as \fBupvar 0 ${ns}::a b\fR, with the sole exception of the resolution rules used for qualified namespace or variable names. \fBnamespace upvar\fR returns an empty string. .TP \fBnamespace unknown\fR ?\fIscript\fR? . Sets or returns the unknown command handler for the current namespace. The handler is invoked when a command called from within the namespace cannot be found in the current namespace, the namespace's path nor in the global namespace. The \fIscript\fR argument, if given, should be a well formed list representing a command name and optional arguments. When the handler is invoked, the full invocation line will be appended to the script and the result evaluated in the context of the namespace. The default handler for all namespaces is \fB::unknown\fR. If no argument is given, it returns the handler for the current namespace. .TP \fBnamespace which\fR ?\fB\-command\fR? ?\fB\-variable\fR? \fIname\fR . Looks up \fIname\fR as either a command or variable and returns its fully-qualified name. For example, if \fIname\fR does not exist in the current namespace but does exist in the global namespace, this command returns a fully-qualified name in the global namespace. If the command or variable does not exist, this command returns an empty string. If the variable has been created but not defined, such as with the \fBvariable\fR command or through a \fBtrace\fR on the variable, this command will return the fully-qualified name of the variable. If no flag is given, \fIname\fR is treated as a command name. See the section \fBNAME RESOLUTION\fR below for an explanation of the rules regarding name resolution. .SH "WHAT IS A NAMESPACE?" .PP A namespace is a collection of commands and variables. It encapsulates the commands and variables to ensure that they will not interfere with the commands and variables of other namespaces. Tcl has always had one such collection, which we refer to as the \fIglobal namespace\fR. The global namespace holds all global variables and commands. The \fBnamespace eval\fR command lets you create new namespaces. For example, .PP .CS \fBnamespace eval\fR Counter { \fBnamespace export\fR bump variable num 0 proc bump {} { variable num incr num } } .CE .PP creates a new namespace containing the variable \fBnum\fR and the procedure \fBbump\fR. The commands and variables in this namespace are separate from other commands and variables in the same program. If there is a command named \fBbump\fR in the global namespace, for example, it will be different from the command \fBbump\fR in the \fBCounter\fR namespace. .PP Namespace variables resemble global variables in Tcl. They exist outside of the procedures in a namespace but can be accessed in a procedure via the \fBvariable\fR command, as shown in the example above. .PP Namespaces are dynamic. You can add and delete commands and variables at any time, so you can build up the contents of a namespace over time using a series of \fBnamespace eval\fR commands. For example, the following series of commands has the same effect as the namespace definition shown above: .PP .CS \fBnamespace eval\fR Counter { variable num 0 proc bump {} { variable num return [incr num] } } \fBnamespace eval\fR Counter { proc test {args} { return $args } } \fBnamespace eval\fR Counter { rename test "" } .CE .PP Note that the \fBtest\fR procedure is added to the \fBCounter\fR namespace, and later removed via the \fBrename\fR command. .PP Namespaces can have other namespaces within them, so they nest hierarchically. A nested namespace is encapsulated inside its parent namespace and can not interfere with other namespaces. .SH "QUALIFIED NAMES" .PP Each namespace has a textual name such as \fBhistory\fR or \fB::safe::interp\fR. Since namespaces may nest, qualified names are used to refer to commands, variables, and child namespaces contained inside namespaces. Qualified names are similar to the hierarchical path names for Unix files or Tk widgets, except that \fB::\fR is used as the separator instead of \fB/\fR or \fB.\fR. The topmost or global namespace has the name .MT (i.e., an empty string), although \fB::\fR is a synonym. As an example, the name \fB::safe::interp::create\fR refers to the command \fBcreate\fR in the namespace \fBinterp\fR that is a child of namespace \fB::safe\fR, which in turn is a child of the global namespace, \fB::\fR. .PP If you want to access commands and variables from another namespace, you must use some extra syntax. Names must be qualified by the namespace that contains them. From the global namespace, we might access the \fBCounter\fR procedures like this: .PP .CS Counter::bump 5 Counter::Reset .CE .PP We could access the current count like this: .PP .CS puts "count = $Counter::num" .CE .PP When one namespace contains another, you may need more than one qualifier to reach its elements. If we had a namespace \fBFoo\fR that contained the namespace \fBCounter\fR, you could invoke its \fBbump\fR procedure from the global namespace like this: .PP .CS Foo::Counter::bump 3 .CE .PP You can also use qualified names when you create and rename commands. For example, you could add a procedure to the \fBFoo\fR namespace like this: .PP .CS proc Foo::Test {args} {return $args} .CE .PP And you could move the same procedure to another namespace like this: .PP .CS rename Foo::Test Bar::Test .CE .PP There are a few remaining points about qualified names that we should cover. Namespaces have nonempty names except for the global namespace. \fB::\fR is disallowed in simple command, variable, and namespace names except as a namespace separator. Extra colons in any separator part of a qualified name are ignored; i.e. two or more colons are treated as a namespace separator. A trailing \fB::\fR in a qualified variable or command name refers to the variable or command named {}. However, a trailing \fB::\fR in a qualified namespace name is ignored. .SH "NAME RESOLUTION" .PP In general, all Tcl commands that take variable and command names support qualified names. This means you can give qualified names to such commands as \fBset\fR, \fBproc\fR, \fBrename\fR, and \fBinterp alias\fR. If you provide a fully-qualified name that starts with a \fB::\fR, there is no question about what command, variable, or namespace you mean. However, if the name does not start with a \fB::\fR (i.e., is \fIrelative\fR), Tcl follows basic rules for looking it up: .IP \(bu \fBVariable names\fR are always resolved by looking first in the current namespace, and then in the global namespace. .IP \(bu \fBCommand names\fR are always resolved by looking in the current namespace first. If not found there, they are searched for in every namespace on the current namespace's command path (which is empty by default). If not found there, command names are looked up in the global namespace (or, failing that, are processed by the appropriate \fBnamespace unknown\fR handler.) .IP \(bu \fBNamespace names\fR are always resolved by looking in only the current namespace. .PP In the following example, .PP .CS set traceLevel 0 \fBnamespace eval\fR Debug { printTrace $traceLevel } .CE .PP Tcl looks for \fBtraceLevel\fR in the namespace \fBDebug\fR and then in the global namespace. It looks up the command \fBprintTrace\fR in the same way. If a variable or command name is not found in either context, the name is undefined. To make this point absolutely clear, consider the following example: .PP .CS set traceLevel 0 \fBnamespace eval\fR Foo { variable traceLevel 3 \fBnamespace eval\fR Debug { printTrace $traceLevel } } .CE .PP Here Tcl looks for \fBtraceLevel\fR first in the namespace \fBFoo::Debug\fR. Since it is not found there, Tcl then looks for it in the global namespace. The variable \fBFoo::traceLevel\fR is completely ignored during the name resolution process. .PP You can use the \fBnamespace which\fR command to clear up any question about name resolution. For example, the command: .PP .CS \fBnamespace eval\fR Foo::Debug {\fBnamespace which\fR \-variable traceLevel} .CE .PP returns \fB::traceLevel\fR. On the other hand, the command, .PP .CS \fBnamespace eval\fR Foo {\fBnamespace which\fR \-variable traceLevel} .CE .PP returns \fB::Foo::traceLevel\fR. .PP As mentioned above, namespace names are looked up differently than the names of variables and commands. Namespace names are always resolved in the current namespace. This means, for example, that a \fBnamespace eval\fR command that creates a new namespace always creates a child of the current namespace unless the new namespace name begins with \fB::\fR. .PP Tcl has no access control to limit what variables, commands, or namespaces you can reference. If you provide a qualified name that resolves to an element by the name resolution rule above, you can access the element. .PP You can access a namespace variable from a procedure in the same namespace by using the \fBvariable\fR command. Much like the \fBglobal\fR command, this creates a local link to the namespace variable. If necessary, it also creates the variable in the current namespace and initializes it. Note that the \fBglobal\fR command only creates links to variables in the global namespace. It is not necessary to use a \fBvariable\fR command if you always refer to the namespace variable using an appropriate qualified name. .SH "IMPORTING COMMANDS" .PP Namespaces are often used to represent libraries. Some library commands are used so frequently that it is a nuisance to type their qualified names. For example, suppose that all of the commands in a package like BLT are contained in a namespace called \fBBlt\fR. Then you might access these commands like this: .PP .CS Blt::graph .g \-background red Blt::table . .g 0,0 .CE .PP If you use the \fBgraph\fR and \fBtable\fR commands frequently, you may want to access them without the \fBBlt::\fR prefix. You can do this by importing the commands into the current namespace, like this: .PP .CS \fBnamespace import\fR Blt::* .CE .PP This adds all exported commands from the \fBBlt\fR namespace into the current namespace context, so you can write code like this: .PP .CS graph .g \-background red table . .g 0,0 .CE .PP The \fBnamespace import\fR command only imports commands from a namespace that that namespace exported with a \fBnamespace export\fR command. .PP Importing \fIevery\fR command from a namespace is generally a bad idea since you do not know what you will get. It is better to import just the specific commands you need. For example, the command .PP .CS \fBnamespace import\fR Blt::graph Blt::table .CE .PP imports only the \fBgraph\fR and \fBtable\fR commands into the current context. .PP If you try to import a command that already exists, you will get an error. This prevents you from importing the same command from two different packages. But from time to time (perhaps when debugging), you may want to get around this restriction. You may want to reissue the \fBnamespace import\fR command to pick up new commands that have appeared in a namespace. In that case, you can use the \fB\-force\fR option, and existing commands will be silently overwritten: .PP .CS \fBnamespace import\fR \-force Blt::graph Blt::table .CE .PP If for some reason, you want to stop using the imported commands, you can remove them with a \fBnamespace forget\fR command, like this: .PP .CS \fBnamespace forget\fR Blt::* .CE .PP This searches the current namespace for any commands imported from \fBBlt\fR. If it finds any, it removes them. Otherwise, it does nothing. After this, the \fBBlt\fR commands must be accessed with the \fBBlt::\fR prefix. .PP When you delete a command from the exporting namespace like this: .PP .CS rename Blt::graph "" .CE .PP the command is automatically removed from all namespaces that import it. .SH "EXPORTING COMMANDS" You can export commands from a namespace like this: .PP .CS \fBnamespace eval\fR Counter { \fBnamespace export\fR bump reset variable Num 0 variable Max 100 proc bump {{by 1}} { variable Num incr Num $by Check return $Num } proc reset {} { variable Num set Num 0 } proc Check {} { variable Num variable Max if {$Num > $Max} { error "too high!" } } } .CE .PP The procedures \fBbump\fR and \fBreset\fR are exported, so they are included when you import from the \fBCounter\fR namespace, like this: .PP .CS \fBnamespace import\fR Counter::* .CE .PP However, the \fBCheck\fR procedure is not exported, so it is ignored by the import operation. .PP The \fBnamespace import\fR command only imports commands that were declared as exported by their namespace. The \fBnamespace export\fR command specifies what commands may be imported by other namespaces. If a \fBnamespace import\fR command specifies a command that is not exported, the command is not imported. .SH "SCOPED SCRIPTS" .PP The \fBnamespace code\fR command is the means by which a script may be packaged for evaluation in a namespace other than the one in which it was created. It is used most often to create event handlers, Tk bindings, and traces for evaluation in the global context. For instance, the following code indicates how to direct a variable \fBtrace\fR callback into the current namespace: .PP .CS \fBnamespace eval\fR a { variable b proc theTraceCallback { n1 n2 op } { upvar 1 $n1 var puts "the value of $n1 has changed to $var" return } trace add variable b write [\fBnamespace code\fR theTraceCallback] } set a::b c .CE .PP When executed, it prints the message: .PP .CS the value of a::b has changed to c .CE .SH ENSEMBLES .PP The \fBnamespace ensemble\fR is used to create and manipulate ensemble commands, which are commands formed by grouping subcommands together. The commands typically come from the current namespace when the ensemble was created, though this is configurable. Note that there may be any number of ensembles associated with any namespace (including none, which is true of all namespaces by default), though all the ensembles associated with a namespace are deleted when that namespace is deleted. The link between an ensemble command and its namespace is maintained however the ensemble is renamed. .PP Three subcommands of the \fBnamespace ensemble\fR command are defined: .TP \fBnamespace ensemble create\fR ?\fIoption value ...\fR? . Creates a new ensemble command linked to the current namespace, returning the fully qualified name of the command created. The arguments to \fBnamespace ensemble create\fR allow the configuration of the command as if with the \fBnamespace ensemble configure\fR command. If not overridden with the \fB\-command\fR option, this command creates an ensemble with exactly the same name as the linked namespace. See the section \fBENSEMBLE OPTIONS\fR below for a full list of options supported and their effects. .TP \fBnamespace ensemble configure \fIcommand\fR ?\fIoption\fR? ?\fIvalue ...\fR? . Retrieves the value of an option associated with the ensemble command named \fIcommand\fR, or updates some options associated with that ensemble command. See the section \fBENSEMBLE OPTIONS\fR below for a full list of options supported and their effects. .TP \fBnamespace ensemble exists\fR \fIcommand\fR . Returns a boolean value that describes whether the command \fIcommand\fR exists and is an ensemble command. This command only ever returns an error if the number of arguments to the command is wrong. .PP When called, an ensemble command takes its first argument and looks it up (according to the rules described below) to discover a list of words to replace the ensemble command and subcommand with. The resulting list of words is then evaluated (with no further substitutions) as if that was what was typed originally (i.e. by passing the list of words through \fBTcl_EvalObjv\fR) and returning the result of the command. Note that it is legal to make the target of an ensemble rewrite be another (or even the same) ensemble command. The ensemble command will not be visible through the use of the \fBuplevel\fR or \fBinfo level\fR commands. .SS "ENSEMBLE OPTIONS" .PP The following options, supported by the \fBnamespace ensemble create\fR and \fBnamespace ensemble configure\fR commands, control how an ensemble command behaves: .TP \fB\-map\fR . When non-empty, this option supplies a dictionary that provides a mapping from subcommand names to a list of prefix words to substitute in place of the ensemble command and subcommand words (in a manner similar to an alias created with \fBinterp alias\fR; the words are not reparsed after substitution); if the first word of any target is not fully qualified when set, it is assumed to be relative to the \fIcurrent\fR namespace and changed to be exactly that (that is, it is always fully qualified when read). When this option is empty, the mapping will be from the local name of the subcommand to its fully-qualified name. Note that when this option is non-empty and the \fB\-subcommands\fR option is empty, the ensemble subcommand names will be exactly those words that have mappings in the dictionary. .TP \fB\-parameters\fR .VS 8.6 This option gives a list of named arguments (the names being used during generation of error messages) that are passed by the caller of the ensemble between the name of the ensemble and the subcommand argument. By default, it is the empty list. .VE 8.6 .TP \fB\-prefixes\fR . This option (which is enabled by default) controls whether the ensemble command recognizes unambiguous prefixes of its subcommands. When turned off, the ensemble command requires exact matching of subcommand names. .TP \fB\-subcommands\fR . When non-empty, this option lists exactly what subcommands are in the ensemble. The mapping for each of those commands will be either whatever is defined in the \fB\-map\fR option, or to the command with the same name in the namespace linked to the ensemble. If this option is empty, the subcommands of the namespace will either be the keys of the dictionary listed in the \fB\-map\fR option or the exported commands of the linked namespace at the time of the invocation of the ensemble command. .TP \fB\-unknown\fR . When non-empty, this option provides a partial command (to which all the words that are arguments to the ensemble command, including the fully-qualified name of the ensemble, are appended) to handle the case where an ensemble subcommand is not recognized and would otherwise generate an error. When empty (the default) an error (in the style of \fBTcl_GetIndexFromObj\fR) is generated whenever the ensemble is unable to determine how to implement a particular subcommand. See \fBUNKNOWN HANDLER BEHAVIOUR\fR for more details. .PP The following extra option is allowed by \fBnamespace ensemble create\fR: .TP \fB\-command\fR . This write-only option allows the name of the ensemble created by \fBnamespace ensemble create\fR to be anything in any existing namespace. The default value for this option is the fully-qualified name of the namespace in which the \fBnamespace ensemble create\fR command is invoked. .PP The following extra option is allowed by \fBnamespace ensemble configure\fR: .TP \fB\-namespace\fR . This read-only option allows the retrieval of the fully-qualified name of the namespace which the ensemble was created within. .SS "UNKNOWN HANDLER BEHAVIOUR" .PP If an unknown handler is specified for an ensemble, that handler is called when the ensemble command would otherwise return an error due to it being unable to decide which subcommand to invoke. The exact conditions under which that occurs are controlled by the \fB\-subcommands\fR, \fB\-map\fR and \fB\-prefixes\fR options as described above. .PP To execute the unknown handler, the ensemble mechanism takes the specified \fB\-unknown\fR option and appends each argument of the attempted ensemble command invocation (including the ensemble command itself, expressed as a fully qualified name). It invokes the resulting command in the scope of the attempted call. If the execution of the unknown handler terminates normally, the ensemble engine reparses the subcommand (as described below) and tries to dispatch it again, which is ideal for when the ensemble's configuration has been updated by the unknown subcommand handler. Any other kind of termination of the unknown handler is treated as an error. .PP The result of the unknown handler is expected to be a list (it is an error if it is not). If the list is an empty list, the ensemble command attempts to look up the original subcommand again and, if it is not found this time, an error will be generated just as if the \fB\-unknown\fR handler was not there (i.e. for any particular invocation of an ensemble, its unknown handler will be called at most once.) This makes it easy for the unknown handler to update the ensemble or its backing namespace so as to provide an implementation of the desired subcommand and reparse. .PP When the result is a non-empty list, the words of that list are used to replace the ensemble command and subcommand, just as if they had been looked up in the \fB\-map\fR. It is up to the unknown handler to supply all namespace qualifiers if the implementing subcommand is not in the namespace of the caller of the ensemble command. Also note that when ensemble commands are chained (e.g. if you make one of the commands that implement an ensemble subcommand into an ensemble, in a manner similar to the \fBtext\fR widget's tag and mark subcommands) then the rewrite happens in the context of the caller of the outermost ensemble. That is to say that ensembles do not in themselves place any namespace contexts on the Tcl call stack. .PP Where an empty \fB\-unknown\fR handler is given (the default), the ensemble command will generate an error message based on the list of commands that the ensemble has defined (formatted similarly to the error message from \fBTcl_GetIndexFromObj\fR). This is the error that will be thrown when the subcommand is still not recognized during reparsing. It is also an error for an \fB\-unknown\fR handler to delete its namespace. .SH EXAMPLES Create a namespace containing a variable and an exported command: .PP .CS \fBnamespace eval\fR foo { variable bar 0 proc grill {} { variable bar puts "called [incr bar] times" } \fBnamespace export\fR grill } .CE .PP Call the command defined in the previous example in various ways. .PP .CS # Direct call ::foo::grill # Use the command resolution path to find the name \fBnamespace eval\fR boo { \fBnamespace path\fR ::foo grill } # Import into current namespace, then call local alias \fBnamespace import\fR foo::grill grill # Create two ensembles, one with the default name and one with a # specified name. Then call through the ensembles. \fBnamespace eval\fR foo { \fBnamespace ensemble\fR create \fBnamespace ensemble\fR create -command ::foobar } foo grill foobar grill .CE .PP Look up where the command imported in the previous example came from: .PP .CS puts "grill came from [\fBnamespace origin\fR grill]" .CE .PP Remove all imported commands from the current namespace: .PP .CS namespace forget {*}[namespace import] .CE .PP .VS 8.6 Create an ensemble for simple working with numbers, using the \fB\-parameters\fR option to allow the operator to be put between the first and second arguments. .PP .CS \fBnamespace eval\fR do { \fBnamespace export\fR * \fBnamespace ensemble\fR create -parameters x proc plus {x y} {expr { $x + $y }} proc minus {x y} {expr { $x - $y }} } # In use, the ensemble works like this: puts [do 1 plus [do 9 minus 7]] .CE .VE 8.6 .SH "SEE ALSO" interp(n), upvar(n), variable(n) .SH KEYWORDS command, ensemble, exported, internal, variable '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/Backslash.30000644000175000017500000000265012663660065014316 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_Backslash 3 "8.1" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_Backslash \- parse a backslash sequence .SH SYNOPSIS .nf \fB#include \fR .sp char \fBTcl_Backslash\fR(\fIsrc, countPtr\fR) .SH ARGUMENTS .AS char *countPtr out .AP char *src in Pointer to a string starting with a backslash. .AP int *countPtr out If \fIcountPtr\fR is not NULL, \fI*countPtr\fR gets filled in with number of characters in the backslash sequence, including the backslash character. .BE .SH DESCRIPTION .PP The use of \fBTcl_Backslash\fR is deprecated in favor of \fBTcl_UtfBackslash\fR. .PP This is a utility procedure provided for backwards compatibility with non-internationalized Tcl extensions. It parses a backslash sequence and returns the low byte of the Unicode character corresponding to the sequence. \fBTcl_Backslash\fR modifies \fI*countPtr\fR to contain the number of characters in the backslash sequence. .PP See the Tcl manual entry for information on the valid backslash sequences. All of the sequences described in the Tcl manual entry are supported by \fBTcl_Backslash\fR. .SH "SEE ALSO" Tcl(n), Tcl_UtfBackslash(3) .SH KEYWORDS backslash, parse tcl8.6.5/doc/apply.n0000644000175000017500000000633512663660065013647 0ustar sergeisergei'\" '\" Copyright (c) 2006 Miguel Sofer '\" Copyright (c) 2006 Donal K. Fellows '\" .TH apply n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME apply \- Apply an anonymous function .SH SYNOPSIS \fBapply \fIfunc\fR ?\fIarg1 arg2 ...\fR? .BE .SH DESCRIPTION .PP The command \fBapply\fR applies the function \fIfunc\fR to the arguments \fIarg1 arg2 ...\fR and returns the result. .PP The function \fIfunc\fR is a two element list \fI{args body}\fR or a three element list \fI{args body namespace}\fR (as if the \fBlist\fR command had been used). The first element \fIargs\fR specifies the formal arguments to \fIfunc\fR. The specification of the formal arguments \fIargs\fR is shared with the \fBproc\fR command, and is described in detail in the corresponding manual page. .PP The contents of \fIbody\fR are executed by the Tcl interpreter after the local variables corresponding to the formal arguments are given the values of the actual parameters \fIarg1 arg2 ...\fR. When \fIbody\fR is being executed, variable names normally refer to local variables, which are created automatically when referenced and deleted when \fBapply\fR returns. One local variable is automatically created for each of the function's arguments. Global variables can only be accessed by invoking the \fBglobal\fR command or the \fBupvar\fR command. Namespace variables can only be accessed by invoking the \fBvariable\fR command or the \fBupvar\fR command. .PP The invocation of \fBapply\fR adds a call frame to Tcl's evaluation stack (the stack of frames accessed via \fBuplevel\fR). The execution of \fIbody\fR proceeds in this call frame, in the namespace given by \fInamespace\fR or in the global namespace if none was specified. If given, \fInamespace\fR is interpreted relative to the global namespace even if its name does not start with .QW :: . .PP The semantics of \fBapply\fR can also be described by: .PP .CS proc apply {fun args} { set len [llength $fun] if {($len < 2) || ($len > 3)} { error "can't interpret \e"$fun\e" as anonymous function" } lassign $fun argList body ns set name ::$ns::[getGloballyUniqueName] set body0 { rename [lindex [info level 0] 0] {} } proc $name $argList ${body0}$body set code [catch {uplevel 1 $name $args} res opt] return -options $opt $res } .CE .SH EXAMPLES .PP This shows how to make a simple general command that applies a transformation to each element of a list. .PP .CS proc map {lambda list} { set result {} foreach item $list { lappend result [\fBapply\fR $lambda $item] } return $result } map {x {return [string length $x]:$x}} {a bb ccc dddd} \fI\(-> 1:a 2:bb 3:ccc 4:dddd\fR map {x {expr {$x**2 + 3*$x - 2}}} {-4 -3 -2 -1 0 1 2 3 4} \fI\(-> 2 -2 -4 -4 -2 2 8 16 26\fR .CE .PP The \fBapply\fR command is also useful for defining callbacks for use in the \fBtrace\fR command: .PP .CS set vbl "123abc" trace add variable vbl write {\fBapply\fR {{v1 v2 op} { upvar 1 $v1 v puts "updated variable to \e"$v\e"" }}} set vbl 123 set vbl abc .CE .SH "SEE ALSO" proc(n), uplevel(n) .SH KEYWORDS anonymous function, argument, lambda, procedure, '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/ParseCmd.30000644000175000017500000005114512663660065014124 0ustar sergeisergei'\" '\" Copyright (c) 1997 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_ParseCommand 3 8.3 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_ParseCommand, Tcl_ParseExpr, Tcl_ParseBraces, Tcl_ParseQuotedString, Tcl_ParseVarName, Tcl_ParseVar, Tcl_FreeParse, Tcl_EvalTokens, Tcl_EvalTokensStandard \- parse Tcl scripts and expressions .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_ParseCommand\fR(\fIinterp, start, numBytes, nested, parsePtr\fR) .sp int \fBTcl_ParseExpr\fR(\fIinterp, start, numBytes, parsePtr\fR) .sp int \fBTcl_ParseBraces\fR(\fIinterp, start, numBytes, parsePtr, append, termPtr\fR) .sp int \fBTcl_ParseQuotedString\fR(\fIinterp, start, numBytes, parsePtr, append, termPtr\fR) .sp int \fBTcl_ParseVarName\fR(\fIinterp, start, numBytes, parsePtr, append\fR) .sp const char * \fBTcl_ParseVar\fR(\fIinterp, start, termPtr\fR) .sp \fBTcl_FreeParse\fR(\fIusedParsePtr\fR) .sp Tcl_Obj * \fBTcl_EvalTokens\fR(\fIinterp, tokenPtr, numTokens\fR) .sp int \fBTcl_EvalTokensStandard\fR(\fIinterp, tokenPtr, numTokens\fR) .SH ARGUMENTS .AS Tcl_Interp *usedParsePtr out .AP Tcl_Interp *interp out For procedures other than \fBTcl_FreeParse\fR, \fBTcl_EvalTokens\fR and \fBTcl_EvalTokensStandard\fR, used only for error reporting; if NULL, then no error messages are left after errors. For \fBTcl_EvalTokens\fR and \fBTcl_EvalTokensStandard\fR, determines the context for evaluating the script and also is used for error reporting; must not be NULL. .AP "const char" *start in Pointer to first character in string to parse. .AP int numBytes in Number of bytes in string to parse, not including any terminating null character. If less than 0 then the script consists of all characters following \fIstart\fR up to the first null character. .AP int nested in Non-zero means that the script is part of a command substitution so an unquoted close bracket should be treated as a command terminator. If zero, close brackets have no special meaning. .AP int append in Non-zero means that \fI*parsePtr\fR already contains valid tokens; the new tokens should be appended to those already present. Zero means that \fI*parsePtr\fR is uninitialized; any information in it is ignored. This argument is normally 0. .AP Tcl_Parse *parsePtr out Points to structure to fill in with information about the parsed command, expression, variable name, etc. Any previous information in this structure is ignored, unless \fIappend\fR is non-zero in a call to \fBTcl_ParseBraces\fR, \fBTcl_ParseQuotedString\fR, or \fBTcl_ParseVarName\fR. .AP "const char" **termPtr out If not NULL, points to a location where \fBTcl_ParseBraces\fR, \fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVar\fR will store a pointer to the character just after the terminating character (the close-brace, the last character of the variable name, or the close-quote (respectively)) if the parse was successful. .AP Tcl_Parse *usedParsePtr in Points to structure that was filled in by a previous call to \fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseVarName\fR, etc. .BE .SH DESCRIPTION .PP These procedures parse Tcl commands or portions of Tcl commands such as expressions or references to variables. Each procedure takes a pointer to a script (or portion thereof) and fills in the structure pointed to by \fIparsePtr\fR with a collection of tokens describing the information that was parsed. The procedures normally return \fBTCL_OK\fR. However, if an error occurs then they return \fBTCL_ERROR\fR, leave an error message in \fIinterp\fR's result (if \fIinterp\fR is not NULL), and leave nothing in \fIparsePtr\fR. .PP \fBTcl_ParseCommand\fR is a procedure that parses Tcl scripts. Given a pointer to a script, it parses the first command from the script. If the command was parsed successfully, \fBTcl_ParseCommand\fR returns \fBTCL_OK\fR and fills in the structure pointed to by \fIparsePtr\fR with information about the structure of the command (see below for details). If an error occurred in parsing the command then \fBTCL_ERROR\fR is returned, an error message is left in \fIinterp\fR's result, and no information is left at \fI*parsePtr\fR. .PP \fBTcl_ParseExpr\fR parses Tcl expressions. Given a pointer to a script containing an expression, \fBTcl_ParseExpr\fR parses the expression. If the expression was parsed successfully, \fBTcl_ParseExpr\fR returns \fBTCL_OK\fR and fills in the structure pointed to by \fIparsePtr\fR with information about the structure of the expression (see below for details). If an error occurred in parsing the command then \fBTCL_ERROR\fR is returned, an error message is left in \fIinterp\fR's result, and no information is left at \fI*parsePtr\fR. .PP \fBTcl_ParseBraces\fR parses a string or command argument enclosed in braces such as \fB{hello}\fR or \fB{string \et with \et tabs}\fR from the beginning of its argument \fIstart\fR. The first character of \fIstart\fR must be \fB{\fR. If the braced string was parsed successfully, \fBTcl_ParseBraces\fR returns \fBTCL_OK\fR, fills in the structure pointed to by \fIparsePtr\fR with information about the structure of the string (see below for details), and stores a pointer to the character just after the terminating \fB}\fR in the location given by \fI*termPtr\fR. If an error occurs while parsing the string then \fBTCL_ERROR\fR is returned, an error message is left in \fIinterp\fR's result, and no information is left at \fI*parsePtr\fR or \fI*termPtr\fR. .PP \fBTcl_ParseQuotedString\fR parses a double-quoted string such as \fB"sum is [expr {$a+$b}]"\fR from the beginning of the argument \fIstart\fR. The first character of \fIstart\fR must be \fB\N'34'\fR. If the double-quoted string was parsed successfully, \fBTcl_ParseQuotedString\fR returns \fBTCL_OK\fR, fills in the structure pointed to by \fIparsePtr\fR with information about the structure of the string (see below for details), and stores a pointer to the character just after the terminating \fB\N'34'\fR in the location given by \fI*termPtr\fR. If an error occurs while parsing the string then \fBTCL_ERROR\fR is returned, an error message is left in \fIinterp\fR's result, and no information is left at \fI*parsePtr\fR or \fI*termPtr\fR. .PP \fBTcl_ParseVarName\fR parses a Tcl variable reference such as \fB$abc\fR or \fB$x([expr {$index + 1}])\fR from the beginning of its \fIstart\fR argument. The first character of \fIstart\fR must be \fB$\fR. If a variable name was parsed successfully, \fBTcl_ParseVarName\fR returns \fBTCL_OK\fR and fills in the structure pointed to by \fIparsePtr\fR with information about the structure of the variable name (see below for details). If an error occurs while parsing the command then \fBTCL_ERROR\fR is returned, an error message is left in \fIinterp\fR's result (if \fIinterp\fR is not NULL), and no information is left at \fI*parsePtr\fR. .PP \fBTcl_ParseVar\fR parse a Tcl variable reference such as \fB$abc\fR or \fB$x([expr {$index + 1}])\fR from the beginning of its \fIstart\fR argument. The first character of \fIstart\fR must be \fB$\fR. If the variable name is parsed successfully, \fBTcl_ParseVar\fR returns a pointer to the string value of the variable. If an error occurs while parsing, then NULL is returned and an error message is left in \fIinterp\fR's result. .PP The information left at \fI*parsePtr\fR by \fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR, \fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR may include dynamically allocated memory. If these five parsing procedures return \fBTCL_OK\fR then the caller must invoke \fBTcl_FreeParse\fR to release the storage at \fI*parsePtr\fR. These procedures ignore any existing information in \fI*parsePtr\fR (unless \fIappend\fR is non-zero), so if repeated calls are being made to any of them then \fBTcl_FreeParse\fR must be invoked once after each call. .PP \fBTcl_EvalTokensStandard\fR evaluates a sequence of parse tokens from a Tcl_Parse structure. The tokens typically consist of all the tokens in a word or all the tokens that make up the index for a reference to an array variable. \fBTcl_EvalTokensStandard\fR performs the substitutions requested by the tokens and concatenates the resulting values. The return value from \fBTcl_EvalTokensStandard\fR is a Tcl completion code with one of the values \fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR, or possibly some other integer value originating in an extension. In addition, a result value or error message is left in \fIinterp\fR's result; it can be retrieved using \fBTcl_GetObjResult\fR. .PP \fBTcl_EvalTokens\fR differs from \fBTcl_EvalTokensStandard\fR only in the return convention used: it returns the result in a new Tcl_Obj. The reference count of the value returned as result has been incremented, so the caller must invoke \fBTcl_DecrRefCount\fR when it is finished with the value. If an error or other exception occurs while evaluating the tokens (such as a reference to a non-existent variable) then the return value is NULL and an error message is left in \fIinterp\fR's result. The use of \fBTcl_EvalTokens\fR is deprecated. .SH "TCL_PARSE STRUCTURE" .PP \fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR, \fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR return parse information in two data structures, Tcl_Parse and Tcl_Token: .PP .CS typedef struct Tcl_Parse { const char *\fIcommentStart\fR; int \fIcommentSize\fR; const char *\fIcommandStart\fR; int \fIcommandSize\fR; int \fInumWords\fR; Tcl_Token *\fItokenPtr\fR; int \fInumTokens\fR; ... } \fBTcl_Parse\fR; typedef struct Tcl_Token { int \fItype\fR; const char *\fIstart\fR; int \fIsize\fR; int \fInumComponents\fR; } \fBTcl_Token\fR; .CE .PP The first five fields of a Tcl_Parse structure are filled in only by \fBTcl_ParseCommand\fR. These fields are not used by the other parsing procedures. .PP \fBTcl_ParseCommand\fR fills in a Tcl_Parse structure with information that describes one Tcl command and any comments that precede the command. If there are comments, the \fIcommentStart\fR field points to the \fB#\fR character that begins the first comment and \fIcommentSize\fR indicates the number of bytes in all of the comments preceding the command, including the newline character that terminates the last comment. If the command is not preceded by any comments, \fIcommentSize\fR is 0. \fBTcl_ParseCommand\fR also sets the \fIcommandStart\fR field to point to the first character of the first word in the command (skipping any comments and leading space) and \fIcommandSize\fR gives the total number of bytes in the command, including the character pointed to by \fIcommandStart\fR up to and including the newline, close bracket, or semicolon character that terminates the command. The \fInumWords\fR field gives the total number of words in the command. .PP All parsing procedures set the remaining fields, \fItokenPtr\fR and \fInumTokens\fR. The \fItokenPtr\fR field points to the first in an array of Tcl_Token structures that describe the components of the entity being parsed. The \fInumTokens\fR field gives the total number of tokens present in the array. Each token contains four fields. The \fItype\fR field selects one of several token types that are described below. The \fIstart\fR field points to the first character in the token and the \fIsize\fR field gives the total number of characters in the token. Some token types, such as \fBTCL_TOKEN_WORD\fR and \fBTCL_TOKEN_VARIABLE\fR, consist of several component tokens, which immediately follow the parent token; the \fInumComponents\fR field describes how many of these there are. The \fItype\fR field has one of the following values: .TP 20 \fBTCL_TOKEN_WORD\fR . This token ordinarily describes one word of a command but it may also describe a quoted or braced string in an expression. The token describes a component of the script that is the result of concatenating together a sequence of subcomponents, each described by a separate subtoken. The token starts with the first non-blank character of the component (which may be a double-quote or open brace) and includes all characters in the component up to but not including the space, semicolon, close bracket, close quote, or close brace that terminates the component. The \fInumComponents\fR field counts the total number of sub-tokens that make up the word, including sub-tokens of \fBTCL_TOKEN_VARIABLE\fR and \fBTCL_TOKEN_BS\fR tokens. .TP \fBTCL_TOKEN_SIMPLE_WORD\fR . This token has the same meaning as \fBTCL_TOKEN_WORD\fR, except that the word is guaranteed to consist of a single \fBTCL_TOKEN_TEXT\fR sub-token. The \fInumComponents\fR field is always 1. .TP \fBTCL_TOKEN_EXPAND_WORD\fR . This token has the same meaning as \fBTCL_TOKEN_WORD\fR, except that the command parser notes this word began with the expansion prefix \fB{*}\fR, indicating that after substitution, the list value of this word should be expanded to form multiple arguments in command evaluation. This token type can only be created by Tcl_ParseCommand. .TP \fBTCL_TOKEN_TEXT\fR . The token describes a range of literal text that is part of a word. The \fInumComponents\fR field is always 0. .TP \fBTCL_TOKEN_BS\fR . The token describes a backslash sequence such as \fB\en\fR or \fB\e0xa3\fR. The \fInumComponents\fR field is always 0. .TP \fBTCL_TOKEN_COMMAND\fR . The token describes a command whose result must be substituted into the word. The token includes the square brackets that surround the command. The \fInumComponents\fR field is always 0 (the nested command is not parsed; call \fBTcl_ParseCommand\fR recursively if you want to see its tokens). .TP \fBTCL_TOKEN_VARIABLE\fR . The token describes a variable substitution, including the \fB$\fR, variable name, and array index (if there is one) up through the close parenthesis that terminates the index. This token is followed by one or more additional tokens that describe the variable name and array index. If \fInumComponents\fR is 1 then the variable is a scalar and the next token is a \fBTCL_TOKEN_TEXT\fR token that gives the variable name. If \fInumComponents\fR is greater than 1 then the variable is an array: the first sub-token is a \fBTCL_TOKEN_TEXT\fR token giving the array name and the remaining sub-tokens are \fBTCL_TOKEN_TEXT\fR, \fBTCL_TOKEN_BS\fR, \fBTCL_TOKEN_COMMAND\fR, and \fBTCL_TOKEN_VARIABLE\fR tokens that must be concatenated to produce the array index. The \fInumComponents\fR field includes nested sub-tokens that are part of \fBTCL_TOKEN_VARIABLE\fR tokens in the array index. .TP \fBTCL_TOKEN_SUB_EXPR\fR . The token describes one subexpression of an expression (or an entire expression). A subexpression may consist of a value such as an integer literal, variable substitution, or parenthesized subexpression; it may also consist of an operator and its operands. The token starts with the first non-blank character of the subexpression up to but not including the space, brace, close-paren, or bracket that terminates the subexpression. This token is followed by one or more additional tokens that describe the subexpression. If the first sub-token after the \fBTCL_TOKEN_SUB_EXPR\fR token is a \fBTCL_TOKEN_OPERATOR\fR token, the subexpression consists of an operator and its token operands. If the operator has no operands, the subexpression consists of just the \fBTCL_TOKEN_OPERATOR\fR token. Each operand is described by a \fBTCL_TOKEN_SUB_EXPR\fR token. Otherwise, the subexpression is a value described by one of the token types \fBTCL_TOKEN_WORD\fR, \fBTCL_TOKEN_TEXT\fR, \fBTCL_TOKEN_BS\fR, \fBTCL_TOKEN_COMMAND\fR, \fBTCL_TOKEN_VARIABLE\fR, and \fBTCL_TOKEN_SUB_EXPR\fR. The \fInumComponents\fR field counts the total number of sub-tokens that make up the subexpression; this includes the sub-tokens for any nested \fBTCL_TOKEN_SUB_EXPR\fR tokens. .TP \fBTCL_TOKEN_OPERATOR\fR . The token describes one operator of an expression such as \fB&&\fR or \fBhypot\fR. A \fBTCL_TOKEN_OPERATOR\fR token is always preceded by a \fBTCL_TOKEN_SUB_EXPR\fR token that describes the operator and its operands; the \fBTCL_TOKEN_SUB_EXPR\fR token's \fInumComponents\fR field can be used to determine the number of operands. A binary operator such as \fB*\fR is followed by two \fBTCL_TOKEN_SUB_EXPR\fR tokens that describe its operands. A unary operator like \fB\-\fR is followed by a single \fBTCL_TOKEN_SUB_EXPR\fR token for its operand. If the operator is a math function such as \fBlog10\fR, the \fBTCL_TOKEN_OPERATOR\fR token will give its name and the following \fBTCL_TOKEN_SUB_EXPR\fR tokens will describe its operands; if there are no operands (as with \fBrand\fR), no \fBTCL_TOKEN_SUB_EXPR\fR tokens follow. There is one trinary operator, \fB?\fR, that appears in if-then-else subexpressions such as \fIx\fB?\fIy\fB:\fIz\fR; in this case, the \fB?\fR \fBTCL_TOKEN_OPERATOR\fR token is followed by three \fBTCL_TOKEN_SUB_EXPR\fR tokens for the operands \fIx\fR, \fIy\fR, and \fIz\fR. The \fInumComponents\fR field for a \fBTCL_TOKEN_OPERATOR\fR token is always 0. .PP After \fBTcl_ParseCommand\fR returns, the first token pointed to by the \fItokenPtr\fR field of the Tcl_Parse structure always has type \fBTCL_TOKEN_WORD\fR or \fBTCL_TOKEN_SIMPLE_WORD\fR or \fBTCL_TOKEN_EXPAND_WORD\fR. It is followed by the sub-tokens that must be concatenated to produce the value of that word. The next token is the \fBTCL_TOKEN_WORD\fR or \fBTCL_TOKEN_SIMPLE_WORD\fR of \fBTCL_TOKEN_EXPAND_WORD\fR token for the second word, followed by sub-tokens for that word, and so on until all \fInumWords\fR have been accounted for. .PP After \fBTcl_ParseExpr\fR returns, the first token pointed to by the \fItokenPtr\fR field of the Tcl_Parse structure always has type \fBTCL_TOKEN_SUB_EXPR\fR. It is followed by the sub-tokens that must be evaluated to produce the value of the expression. Only the token information in the Tcl_Parse structure is modified: the \fIcommentStart\fR, \fIcommentSize\fR, \fIcommandStart\fR, and \fIcommandSize\fR fields are not modified by \fBTcl_ParseExpr\fR. .PP After \fBTcl_ParseBraces\fR returns, the array of tokens pointed to by the \fItokenPtr\fR field of the Tcl_Parse structure will contain a single \fBTCL_TOKEN_TEXT\fR token if the braced string does not contain any backslash-newlines. If the string does contain backslash-newlines, the array of tokens will contain one or more \fBTCL_TOKEN_TEXT\fR or \fBTCL_TOKEN_BS\fR sub-tokens that must be concatenated to produce the value of the string. If the braced string was just \fB{}\fR (that is, the string was empty), the single \fBTCL_TOKEN_TEXT\fR token will have a \fIsize\fR field containing zero; this ensures that at least one token appears to describe the braced string. Only the token information in the Tcl_Parse structure is modified: the \fIcommentStart\fR, \fIcommentSize\fR, \fIcommandStart\fR, and \fIcommandSize\fR fields are not modified by \fBTcl_ParseBraces\fR. .PP After \fBTcl_ParseQuotedString\fR returns, the array of tokens pointed to by the \fItokenPtr\fR field of the Tcl_Parse structure depends on the contents of the quoted string. It will consist of one or more \fBTCL_TOKEN_TEXT\fR, \fBTCL_TOKEN_BS\fR, \fBTCL_TOKEN_COMMAND\fR, and \fBTCL_TOKEN_VARIABLE\fR sub-tokens. The array always contains at least one token; for example, if the argument \fIstart\fR is empty, the array returned consists of a single \fBTCL_TOKEN_TEXT\fR token with a zero \fIsize\fR field. Only the token information in the Tcl_Parse structure is modified: the \fIcommentStart\fR, \fIcommentSize\fR, \fIcommandStart\fR, and \fIcommandSize\fR fields are not modified. .PP After \fBTcl_ParseVarName\fR returns, the first token pointed to by the \fItokenPtr\fR field of the Tcl_Parse structure always has type \fBTCL_TOKEN_VARIABLE\fR. It is followed by the sub-tokens that make up the variable name as described above. The total length of the variable name is contained in the \fIsize\fR field of the first token. As in \fBTcl_ParseExpr\fR, only the token information in the Tcl_Parse structure is modified by \fBTcl_ParseVarName\fR: the \fIcommentStart\fR, \fIcommentSize\fR, \fIcommandStart\fR, and \fIcommandSize\fR fields are not modified. .PP All of the character pointers in the Tcl_Parse and Tcl_Token structures refer to characters in the \fIstart\fR argument passed to \fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR, \fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR. .PP There are additional fields in the Tcl_Parse structure after the \fInumTokens\fR field, but these are for the private use of \fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR, \fBTcl_ParseQuotedString\fR, and \fBTcl_ParseVarName\fR; they should not be referenced by code outside of these procedures. .SH KEYWORDS backslash substitution, braces, command, expression, parse, token, variable substitution tcl8.6.5/doc/Exit.30000644000175000017500000001353212663660065013335 0ustar sergeisergei'\" '\" 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_Exit 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_Exit, Tcl_Finalize, Tcl_CreateExitHandler, Tcl_DeleteExitHandler, Tcl_ExitThread, Tcl_FinalizeThread, Tcl_CreateThreadExitHandler, Tcl_DeleteThreadExitHandler, Tcl_SetExitProc \- end the application or thread (and invoke exit handlers) .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_Exit\fR(\fIstatus\fR) .sp \fBTcl_Finalize\fR() .sp \fBTcl_CreateExitHandler\fR(\fIproc, clientData\fR) .sp \fBTcl_DeleteExitHandler\fR(\fIproc, clientData\fR) .sp \fBTcl_ExitThread\fR(\fIstatus\fR) .sp \fBTcl_FinalizeThread\fR() .sp \fBTcl_CreateThreadExitHandler\fR(\fIproc, clientData\fR) .sp \fBTcl_DeleteThreadExitHandler\fR(\fIproc, clientData\fR) .sp Tcl_ExitProc * \fBTcl_SetExitProc\fR(\fIproc\fR) .SH ARGUMENTS .AS Tcl_ExitProc clientData .AP int status in Provides information about why the application or thread exited. Exact meaning may be platform-specific. 0 usually means a normal exit, any nonzero value usually means that an error occurred. .AP Tcl_ExitProc *proc in Procedure to invoke before exiting application, or (for \fBTcl_SetExitProc\fR) NULL to uninstall the current application exit procedure. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR. .BE .SH DESCRIPTION .PP The procedures described here provide a graceful mechanism to end the execution of a \fBTcl\fR application. Exit handlers are invoked to cleanup the application's state before ending the execution of \fBTcl\fR code. .PP Invoke \fBTcl_Exit\fR to end a \fBTcl\fR application and to exit from this process. This procedure is invoked by the \fBexit\fR command, and can be invoked anyplace else to terminate the application. No-one should ever invoke the \fBexit\fR system procedure directly; always invoke \fBTcl_Exit\fR instead, so that it can invoke exit handlers. Note that if other code invokes \fBexit\fR system procedure directly, or otherwise causes the application to terminate without calling \fBTcl_Exit\fR, the exit handlers will not be run. \fBTcl_Exit\fR internally invokes the \fBexit\fR system call, thus it never returns control to its caller. If an application exit handler has been installed (see \fBTcl_SetExitProc\fR), that handler is invoked with an argument consisting of the exit status (cast to ClientData); the application exit handler should not return control to Tcl. .PP \fBTcl_Finalize\fR is similar to \fBTcl_Exit\fR except that it does not exit from the current process. It is useful for cleaning up when a process is finished using \fBTcl\fR but wishes to continue executing, and when \fBTcl\fR is used in a dynamically loaded extension that is about to be unloaded. Your code should always invoke \fBTcl_Finalize\fR when \fBTcl\fR is being unloaded, to ensure proper cleanup. \fBTcl_Finalize\fR can be safely called more than once. .PP \fBTcl_ExitThread\fR is used to terminate the current thread and invoke per-thread exit handlers. This finalization is done by \fBTcl_FinalizeThread\fR, which you can call if you just want to clean up per-thread state and invoke the thread exit handlers. \fBTcl_Finalize\fR calls \fBTcl_FinalizeThread\fR for the current thread automatically. .PP \fBTcl_CreateExitHandler\fR arranges for \fIproc\fR to be invoked by \fBTcl_Finalize\fR and \fBTcl_Exit\fR. \fBTcl_CreateThreadExitHandler\fR arranges for \fIproc\fR to be invoked by \fBTcl_FinalizeThread\fR and \fBTcl_ExitThread\fR. This provides a hook for cleanup operations such as flushing buffers and freeing global memory. \fIProc\fR should match the type \fBTcl_ExitProc\fR: .PP .CS typedef void \fBTcl_ExitProc\fR( ClientData \fIclientData\fR); .CE .PP The \fIclientData\fR parameter to \fIproc\fR is a copy of the \fIclientData\fR argument given to \fBTcl_CreateExitHandler\fR or \fBTcl_CreateThreadExitHandler\fR when the callback was created. Typically, \fIclientData\fR points to a data structure containing application-specific information about what to do in \fIproc\fR. .PP \fBTcl_DeleteExitHandler\fR and \fBTcl_DeleteThreadExitHandler\fR may be called to delete a previously-created exit handler. It removes the handler indicated by \fIproc\fR and \fIclientData\fR so that no call to \fIproc\fR will be made. If no such handler exists then \fBTcl_DeleteExitHandler\fR or \fBTcl_DeleteThreadExitHandler\fR does nothing. .PP \fBTcl_Finalize\fR and \fBTcl_Exit\fR execute all registered exit handlers, in reverse order from the order in which they were registered. This matches the natural order in which extensions are loaded and unloaded; if extension \fBA\fR loads extension \fBB\fR, it usually unloads \fBB\fR before it itself is unloaded. If extension \fBA\fR registers its exit handlers before loading extension \fBB\fR, this ensures that any exit handlers for \fBB\fR will be executed before the exit handlers for \fBA\fR. .PP \fBTcl_Finalize\fR and \fBTcl_Exit\fR call \fBTcl_FinalizeThread\fR and the thread exit handlers \fIafter\fR the process-wide exit handlers. This is because thread finalization shuts down the I/O channel system, so any attempt at I/O by the global exit handlers will vanish into the bitbucket. .PP \fBTcl_SetExitProc\fR installs an application exit handler, returning the previously-installed application exit handler or NULL if no application handler was installed. If an application exit handler is installed, that exit handler takes over complete responsibility for finalization of Tcl's subsystems via \fBTcl_Finalize\fR at an appropriate time. The argument passed to \fIproc\fR when it is invoked will be the exit status code (as passed to \fBTcl_Exit\fR) cast to a ClientData value. .SH "SEE ALSO" exit(n) .SH KEYWORDS abort, callback, cleanup, dynamic loading, end application, exit, unloading, thread tcl8.6.5/doc/GetOpnFl.30000644000175000017500000000407212663660065014101 0ustar sergeisergei'\" '\" Copyright (c) 1996-1997 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_GetOpenFile 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_GetOpenFile \- Return a FILE* for a channel registered in the given interpreter (Unix only) .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_GetOpenFile\fR(\fIinterp, chanID, write, checkUsage, filePtr\fR) .sp .SH ARGUMENTS .AS Tcl_Interp checkUsage out .AP Tcl_Interp *interp in Tcl interpreter from which file handle is to be obtained. .AP "const char" *chanID in String identifying channel, such as \fBstdin\fR or \fBfile4\fR. .AP int write in Non-zero means the file will be used for writing, zero means it will be used for reading. .AP int checkUsage in If non-zero, then an error will be generated if the file was not opened for the access indicated by \fIwrite\fR. .AP ClientData *filePtr out Points to word in which to store pointer to FILE structure for the file given by \fIchanID\fR. .BE .SH DESCRIPTION .PP \fBTcl_GetOpenFile\fR takes as argument a file identifier of the form returned by the \fBopen\fR command and returns at \fI*filePtr\fR a pointer to the FILE structure for the file. The \fIwrite\fR argument indicates whether the FILE pointer will be used for reading or writing. In some cases, such as a channel that connects to a pipeline of subprocesses, different FILE pointers will be returned for reading and writing. \fBTcl_GetOpenFile\fR normally returns \fBTCL_OK\fR. If an error occurs in \fBTcl_GetOpenFile\fR (e.g. \fIchanID\fR did not make any sense or \fIcheckUsage\fR was set and the file was not opened for the access specified by \fIwrite\fR) then \fBTCL_ERROR\fR is returned and the interpreter's result will contain an error message. In the current implementation \fIcheckUsage\fR is ignored and consistency checks are always performed. .PP Note that this interface is only supported on the Unix platform. .SH KEYWORDS channel, file handle, permissions, pipeline, read, write tcl8.6.5/doc/regexp.n0000644000175000017500000001550012663660065014006 0ustar sergeisergei'\" '\" Copyright (c) 1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH regexp n 8.3 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME regexp \- Match a regular expression against a string .SH SYNOPSIS \fBregexp \fR?\fIswitches\fR? \fIexp string \fR?\fImatchVar\fR? ?\fIsubMatchVar subMatchVar ...\fR? .BE .SH DESCRIPTION .PP Determines whether the regular expression \fIexp\fR matches part or all of \fIstring\fR and returns 1 if it does, 0 if it does not, unless \fB\-inline\fR is specified (see below). (Regular expression matching is described in the \fBre_syntax\fR reference page.) .PP If additional arguments are specified after \fIstring\fR then they are treated as the names of variables in which to return information about which part(s) of \fIstring\fR matched \fIexp\fR. \fIMatchVar\fR will be set to the range of \fIstring\fR that matched all of \fIexp\fR. The first \fIsubMatchVar\fR will contain the characters in \fIstring\fR that matched the leftmost parenthesized subexpression within \fIexp\fR, the next \fIsubMatchVar\fR will contain the characters that matched the next parenthesized subexpression to the right in \fIexp\fR, and so on. .PP If the initial arguments to \fBregexp\fR start with \fB\-\fR then they are treated as switches. The following switches are currently supported: .TP 15 \fB\-about\fR . Instead of attempting to match the regular expression, returns a list containing information about the regular expression. The first element of the list is a subexpression count. The second element is a list of property names that describe various attributes of the regular expression. This switch is primarily intended for debugging purposes. .TP 15 \fB\-expanded\fR . Enables use of the expanded regular expression syntax where whitespace and comments are ignored. This is the same as specifying the \fB(?x)\fR embedded option (see the \fBre_syntax\fR manual page). .TP 15 \fB\-indices\fR . Changes what is stored in the \fImatchVar\fR and \fIsubMatchVar\fRs. Instead of storing the matching characters from \fIstring\fR, each variable will contain a list of two decimal strings giving the indices in \fIstring\fR of the first and last characters in the matching range of characters. .TP 15 \fB\-line\fR . Enables newline-sensitive matching. By default, newline is a completely ordinary character with no special meaning. With this flag, .QW [^ bracket expressions and .QW . never match newline, .QW ^ matches an empty string after any newline in addition to its normal function, and .QW $ matches an empty string before any newline in addition to its normal function. This flag is equivalent to specifying both \fB\-linestop\fR and \fB\-lineanchor\fR, or the \fB(?n)\fR embedded option (see the \fBre_syntax\fR manual page). .TP 15 \fB\-linestop\fR . Changes the behavior of .QW [^ bracket expressions and .QW . so that they stop at newlines. This is the same as specifying the \fB(?p)\fR embedded option (see the \fBre_syntax\fR manual page). .TP 15 \fB\-lineanchor\fR . Changes the behavior of .QW ^ and .QW $ (the .QW anchors ) so they match the beginning and end of a line respectively. This is the same as specifying the \fB(?w)\fR embedded option (see the \fBre_syntax\fR manual page). .TP 15 \fB\-nocase\fR . Causes upper-case characters in \fIstring\fR to be treated as lower case during the matching process. .TP 15 \fB\-all\fR . Causes the regular expression to be matched as many times as possible in the string, returning the total number of matches found. If this is specified with match variables, they will contain information for the last match only. .TP 15 \fB\-inline\fR . Causes the command to return, as a list, the data that would otherwise be placed in match variables. When using \fB\-inline\fR, match variables may not be specified. If used with \fB\-all\fR, the list will be concatenated at each iteration, such that a flat list is always returned. For each match iteration, the command will append the overall match data, plus one element for each subexpression in the regular expression. Examples are: .RS .PP .CS \fBregexp\fR -inline -- {\ew(\ew)} " inlined " \fI\(-> in n\fR \fBregexp\fR -all -inline -- {\ew(\ew)} " inlined " \fI\(-> in n li i ne e\fR .CE .RE .TP 15 \fB\-start\fR \fIindex\fR . Specifies a character index offset into the string to start matching the regular expression at. The \fIindex\fR value is interpreted in the same manner as the \fIindex\fR argument to \fBstring index\fR. When using this switch, .QW ^ will not match the beginning of the line, and \eA will still match the start of the string at \fIindex\fR. If \fB\-indices\fR is specified, the indices will be indexed starting from the absolute beginning of the input string. \fIindex\fR will be constrained to the bounds of the input string. .TP 15 \fB\-\|\-\fR . Marks the end of switches. The argument following this one will be treated as \fIexp\fR even if it starts with a \fB\-\fR. .PP If there are more \fIsubMatchVar\fRs than parenthesized subexpressions within \fIexp\fR, or if a particular subexpression in \fIexp\fR does not match the string (e.g. because it was in a portion of the expression that was not matched), then the corresponding \fIsubMatchVar\fR will be set to .QW "\fB\-1 \-1\fR" if \fB\-indices\fR has been specified or to an empty string otherwise. .SH EXAMPLES .PP Find the first occurrence of a word starting with \fBfoo\fR in a string that is not actually an instance of \fBfoobar\fR, and get the letters following it up to the end of the word into a variable: .PP .CS \fBregexp\fR {\emfoo(?!bar\eM)(\ew*)} $string \-> restOfWord .CE .PP Note that the whole matched substring has been placed in the variable .QW \fB\->\fR , which is a name chosen to look nice given that we are not actually interested in its contents. .PP Find the index of the word \fBbadger\fR (in any case) within a string and store that in the variable \fBlocation\fR: .PP .CS \fBregexp\fR \-indices {(?i)\embadger\eM} $string location .CE .PP This could also be written as a \fIbasic\fR regular expression (as opposed to using the default syntax of \fIadvanced\fR regular expressions) match by prefixing the expression with a suitable flag: .PP .CS \fBregexp\fR \-indices {(?ib)\e} $string location .CE .PP This counts the number of octal digits in a string: .PP .CS \fBregexp\fR \-all {[0\-7]} $string .CE .PP This lists all words (consisting of all sequences of non-whitespace characters) in a string, and is useful as a more powerful version of the \fBsplit\fR command: .PP .CS \fBregexp\fR \-all \-inline {\eS+} $string .CE .SH "SEE ALSO" re_syntax(n), regsub(n), string(n) .SH KEYWORDS match, parsing, pattern, regular expression, splitting, string '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/file.n0000644000175000017500000005323212663660065013437 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 file n 8.3 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME file \- Manipulate file names and attributes .SH SYNOPSIS \fBfile \fIoption\fR \fIname\fR ?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP This command provides several operations on a file's name or attributes. \fIName\fR is the name of a file; if it starts with a tilde, then tilde substitution is done before executing the command (see the manual entry for \fBfilename\fR for details). \fIOption\fR indicates what to do with the file name. Any unique abbreviation for \fIoption\fR is acceptable. The valid options are: .TP \fBfile atime \fIname\fR ?\fItime\fR? . Returns a decimal string giving the time at which file \fIname\fR was last accessed. If \fItime\fR is specified, it is an access time to set for the file. The time is measured in the standard POSIX fashion as seconds from a fixed starting time (often January 1, 1970). If the file does not exist or its access time cannot be queried or set then an error is generated. On Windows, FAT file systems do not support access time. .TP \fBfile attributes \fIname\fR .TP \fBfile attributes \fIname\fR ?\fIoption\fR? .TP \fBfile attributes \fIname\fR ?\fIoption value option value...\fR? . This subcommand returns or sets platform specific values associated with a file. The first form returns a list of the platform specific flags and their values. The second form returns the value for the specific option. The third form sets one or more of the values. The values are as follows: .RS .PP On Unix, \fB\-group\fR gets or sets the group name for the file. A group id can be given to the command, but it returns a group name. \fB\-owner\fR gets or sets the user name of the owner of the file. The command returns the owner name, but the numerical id can be passed when setting the owner. \fB\-permissions\fR sets or retrieves the octal code that chmod(1) uses. This command does also has limited support for setting using the symbolic attributes for chmod(1), of the form [ugo]?[[+\-=][rwxst],[...]], where multiple symbolic attributes can be separated by commas (example: \fBu+s,go\-rw\fR add sticky bit for user, remove read and write permissions for group and other). A simplified \fBls\fR style string, of the form rwxrwxrwx (must be 9 characters), is also supported (example: \fBrwxr\-xr\-t\fR is equivalent to 01755). On versions of Unix supporting file flags, \fB\-readonly\fR gives the value or sets or clears the readonly attribute of the file, i.e. the user immutable flag \fBuchg\fR to chflags(1). .PP On Windows, \fB\-archive\fR gives the value or sets or clears the archive attribute of the file. \fB\-hidden\fR gives the value or sets or clears the hidden attribute of the file. \fB\-longname\fR will expand each path element to its long version. This attribute cannot be set. \fB\-readonly\fR gives the value or sets or clears the readonly attribute of the file. \fB\-shortname\fR gives a string where every path element is replaced with its short (8.3) version of the name. This attribute cannot be set. \fB\-system\fR gives or sets or clears the value of the system attribute of the file. .PP On Mac OS X and Darwin, \fB\-creator\fR gives or sets the Finder creator type of the file. \fB\-hidden\fR gives or sets or clears the hidden attribute of the file. \fB\-readonly\fR gives or sets or clears the readonly attribute of the file. \fB\-rsrclength\fR gives the length of the resource fork of the file, this attribute can only be set to the value 0, which results in the resource fork being stripped off the file. .RE .TP \fBfile channels\fR ?\fIpattern\fR? . If \fIpattern\fR is not specified, returns a list of names of all registered open channels in this interpreter. If \fIpattern\fR is specified, only those names matching \fIpattern\fR are returned. Matching is determined using the same rules as for \fBstring match\fR. .TP \fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR \fItarget\fR .TP \fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR ?\fIsource\fR ...? \fItargetDir\fR . The first form makes a copy of the file or directory \fIsource\fR under the pathname \fItarget\fR. If \fItarget\fR is an existing directory, then the second form is used. The second form makes a copy inside \fItargetDir\fR of each \fIsource\fR file listed. If a directory is specified as a \fIsource\fR, then the contents of the directory will be recursively copied into \fItargetDir\fR. Existing files will not be overwritten unless the \fB\-force\fR option is specified (when Tcl will also attempt to adjust permissions on the destination file or directory if that is necessary to allow the copy to proceed). When copying within a single filesystem, \fIfile copy\fR will copy soft links (i.e. the links themselves are copied, not the things they point to). Trying to overwrite a non-empty directory, overwrite a directory with a file, or overwrite a file with a directory will all result in errors even if \fB\-force\fR was specified. Arguments are processed in the order specified, halting at the first error, if any. A \fB\-\|\-\fR marks the end of switches; the argument following the \fB\-\|\-\fR will be treated as a \fIsource\fR even if it starts with a \fB\-\fR. .TP \fBfile delete \fR?\fB\-force\fR? ?\fB\-\|\-\fR? ?\fIpathname\fR ... ? . Removes the file or directory specified by each \fIpathname\fR argument. Non-empty directories will be removed only if the \fB\-force\fR option is specified. When operating on symbolic links, the links themselves will be deleted, not the objects they point to. Trying to delete a non-existent file is not considered an error. Trying to delete a read-only file will cause the file to be deleted, even if the \fB\-force\fR flags is not specified. If the \fB\-force\fR option is specified on a directory, Tcl will attempt both to change permissions and move the current directory .QW pwd out of the given path if that is necessary to allow the deletion to proceed. Arguments are processed in the order specified, halting at the first error, if any. A \fB\-\|\-\fR marks the end of switches; the argument following the \fB\-\|\-\fR will be treated as a \fIpathname\fR even if it starts with a \fB\-\fR. .TP \fBfile dirname \fIname\fR Returns a name comprised of all of the path components in \fIname\fR excluding the last element. If \fIname\fR is a relative file name and only contains one path element, then returns .QW \fB.\fR . If \fIname\fR refers to a root directory, then the root directory is returned. For example, .RS .PP .CS \fBfile dirname\fR c:/ .CE .PP returns \fBc:/\fR. .PP Note that tilde substitution will only be performed if it is necessary to complete the command. For example, .PP .CS \fBfile dirname\fR ~/src/foo.c .CE .PP returns \fB~/src\fR, whereas .PP .CS \fBfile dirname\fR ~ .CE .PP returns \fB/home\fR (or something similar). .RE .TP \fBfile executable \fIname\fR . Returns \fB1\fR if file \fIname\fR is executable by the current user, \fB0\fR otherwise. .TP \fBfile exists \fIname\fR . Returns \fB1\fR if file \fIname\fR exists and the current user has search privileges for the directories leading to it, \fB0\fR otherwise. .TP \fBfile extension \fIname\fR . Returns all of the characters in \fIname\fR after and including the last dot in the last element of \fIname\fR. If there is no dot in the last element of \fIname\fR then returns the empty string. .TP \fBfile isdirectory \fIname\fR . Returns \fB1\fR if file \fIname\fR is a directory, \fB0\fR otherwise. .TP \fBfile isfile \fIname\fR . Returns \fB1\fR if file \fIname\fR is a regular file, \fB0\fR otherwise. .TP \fBfile join \fIname\fR ?\fIname ...\fR? . Takes one or more file names and combines them, using the correct path separator for the current platform. If a particular \fIname\fR is relative, then it will be joined to the previous file name argument. Otherwise, any earlier arguments will be discarded, and joining will proceed from the current argument. For example, .RS .PP .CS \fBfile join\fR a b /foo bar .CE .PP returns \fB/foo/bar\fR. .PP Note that any of the names can contain separators, and that the result is always canonical for the current platform: \fB/\fR for Unix and Windows. .RE .TP \fBfile link\fR ?\fI\-linktype\fR? \fIlinkName\fR ?\fItarget\fR? . If only one argument is given, that argument is assumed to be \fIlinkName\fR, and this command returns the value of the link given by \fIlinkName\fR (i.e. the name of the file it points to). If \fIlinkName\fR is not a link or its value cannot be read (as, for example, seems to be the case with hard links, which look just like ordinary files), then an error is returned. .RS .PP If 2 arguments are given, then these are assumed to be \fIlinkName\fR and \fItarget\fR. If \fIlinkName\fR already exists, or if \fItarget\fR does not exist, an error will be returned. Otherwise, Tcl creates a new link called \fIlinkName\fR which points to the existing filesystem object at \fItarget\fR (which is also the returned value), where the type of the link is platform-specific (on Unix a symbolic link will be the default). This is useful for the case where the user wishes to create a link in a cross-platform way, and does not care what type of link is created. .PP If the user wishes to make a link of a specific type only, (and signal an error if for some reason that is not possible), then the optional \fI\-linktype\fR argument should be given. Accepted values for \fI\-linktype\fR are .QW \fB\-symbolic\fR and .QW \fB\-hard\fR . .PP On Unix, symbolic links can be made to relative paths, and those paths must be relative to the actual \fIlinkName\fR's location (not to the cwd), but on all other platforms where relative links are not supported, target paths will always be converted to absolute, normalized form before the link is created (and therefore relative paths are interpreted as relative to the cwd). Furthermore, .QW ~user paths are always expanded to absolute form. When creating links on filesystems that either do not support any links, or do not support the specific type requested, an error message will be returned. Most Unix platforms support both symbolic and hard links (the latter for files only). Windows supports symbolic directory links and hard file links on NTFS drives. .RE .TP \fBfile lstat \fIname varName\fR . Same as \fBstat\fR option (see below) except uses the \fIlstat\fR kernel call instead of \fIstat\fR. This means that if \fIname\fR refers to a symbolic link the information returned in \fIvarName\fR is for the link rather than the file it refers to. On systems that do not support symbolic links this option behaves exactly the same as the \fBstat\fR option. .TP \fBfile mkdir\fR ?\fIdir\fR ...? . Creates each directory specified. For each pathname \fIdir\fR specified, this command will create all non-existing parent directories as well as \fIdir\fR itself. If an existing directory is specified, then no action is taken and no error is returned. Trying to overwrite an existing file with a directory will result in an error. Arguments are processed in the order specified, halting at the first error, if any. .TP \fBfile mtime \fIname\fR ?\fItime\fR? . Returns a decimal string giving the time at which file \fIname\fR was last modified. If \fItime\fR is specified, it is a modification time to set for the file (equivalent to Unix \fBtouch\fR). The time is measured in the standard POSIX fashion as seconds from a fixed starting time (often January 1, 1970). If the file does not exist or its modified time cannot be queried or set then an error is generated. .TP \fBfile nativename \fIname\fR . Returns the platform-specific name of the file. This is useful if the filename is needed to pass to a platform-specific call, such as to a subprocess via \fBexec\fR under Windows (see \fBEXAMPLES\fR below). .TP \fBfile normalize \fIname\fR . Returns a unique normalized path representation for the file-system object (file, directory, link, etc), whose string value can be used as a unique identifier for it. A normalized path is an absolute path which has all .QW ../ and .QW ./ removed. Also it is one which is in the .QW standard format for the native platform. On Unix, this means the segments leading up to the path must be free of symbolic links/aliases (but the very last path component may be a symbolic link), and on Windows it also means we want the long form with that form's case-dependence (which gives us a unique, case-dependent path). The one exception concerning the last link in the path is necessary, because Tcl or the user may wish to operate on the actual symbolic link itself (for example \fBfile delete\fR, \fBfile rename\fR, \fBfile copy\fR are defined to operate on symbolic links, not on the things that they point to). .TP \fBfile owned \fIname\fR . Returns \fB1\fR if file \fIname\fR is owned by the current user, \fB0\fR otherwise. .TP \fBfile pathtype \fIname\fR . Returns one of \fBabsolute\fR, \fBrelative\fR, \fBvolumerelative\fR. If \fIname\fR refers to a specific file on a specific volume, the path type will be \fBabsolute\fR. If \fIname\fR refers to a file relative to the current working directory, then the path type will be \fBrelative\fR. If \fIname\fR refers to a file relative to the current working directory on a specified volume, or to a specific file on the current working volume, then the path type is \fBvolumerelative\fR. .TP \fBfile readable \fIname\fR . Returns \fB1\fR if file \fIname\fR is readable by the current user, \fB0\fR otherwise. .TP \fBfile readlink \fIname\fR . Returns the value of the symbolic link given by \fIname\fR (i.e. the name of the file it points to). If \fIname\fR is not a symbolic link or its value cannot be read, then an error is returned. On systems that do not support symbolic links this option is undefined. .TP \fBfile rename \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR \fItarget\fR .TP \fBfile rename \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR ?\fIsource\fR ...? \fItargetDir\fR . The first form takes the file or directory specified by pathname \fIsource\fR and renames it to \fItarget\fR, moving the file if the pathname \fItarget\fR specifies a name in a different directory. If \fItarget\fR is an existing directory, then the second form is used. The second form moves each \fIsource\fR file or directory into the directory \fItargetDir\fR. Existing files will not be overwritten unless the \fB\-force\fR option is specified. When operating inside a single filesystem, Tcl will rename symbolic links rather than the things that they point to. Trying to overwrite a non-empty directory, overwrite a directory with a file, or a file with a directory will all result in errors. Arguments are processed in the order specified, halting at the first error, if any. A \fB\-\|\-\fR marks the end of switches; the argument following the \fB\-\|\-\fR will be treated as a \fIsource\fR even if it starts with a \fB\-\fR. .TP \fBfile rootname \fIname\fR . Returns all of the characters in \fIname\fR up to but not including the last .QW . character in the last component of name. If the last component of \fIname\fR does not contain a dot, then returns \fIname\fR. .TP \fBfile separator\fR ?\fIname\fR? . If no argument is given, returns the character which is used to separate path segments for native files on this platform. If a path is given, the filesystem responsible for that path is asked to return its separator character. If no file system accepts \fIname\fR, an error is generated. .TP \fBfile size \fIname\fR . Returns a decimal string giving the size of file \fIname\fR in bytes. If the file does not exist or its size cannot be queried then an error is generated. .TP \fBfile split \fIname\fR . Returns a list whose elements are the path components in \fIname\fR. The first element of the list will have the same path type as \fIname\fR. All other elements will be relative. Path separators will be discarded unless they are needed to ensure that an element is unambiguously relative. For example, under Unix .RS .PP .CS \fBfile split\fR /foo/~bar/baz .CE .PP returns .QW \fB/\0\0foo\0\0./~bar\0\0baz\fR to ensure that later commands that use the third component do not attempt to perform tilde substitution. .RE .TP \fBfile stat \fIname varName\fR . Invokes the \fBstat\fR kernel call on \fIname\fR, and uses the variable given by \fIvarName\fR to hold information returned from the kernel call. \fIVarName\fR is treated as an array variable, and the following elements of that variable are set: \fBatime\fR, \fBctime\fR, \fBdev\fR, \fBgid\fR, \fBino\fR, \fBmode\fR, \fBmtime\fR, \fBnlink\fR, \fBsize\fR, \fBtype\fR, \fBuid\fR. Each element except \fBtype\fR is a decimal string with the value of the corresponding field from the \fBstat\fR return structure; see the manual entry for \fBstat\fR for details on the meanings of the values. The \fBtype\fR element gives the type of the file in the same form returned by the command \fBfile type\fR. This command returns an empty string. .TP \fBfile system \fIname\fR . Returns a list of one or two elements, the first of which is the name of the filesystem to use for the file, and the second, if given, an arbitrary string representing the filesystem-specific nature or type of the location within that filesystem. If a filesystem only supports one type of file, the second element may not be supplied. For example the native files have a first element .QW native , and a second element which when given is a platform-specific type name for the file's system (e.g. .QW NTFS , .QW FAT , on Windows). A generic virtual file system might return the list .QW "vfs ftp" to represent a file on a remote ftp site mounted as a virtual filesystem through an extension called .QW vfs . If the file does not belong to any filesystem, an error is generated. .TP \fBfile tail \fIname\fR . Returns all of the characters in the last filesystem component of \fIname\fR. Any trailing directory separator in \fIname\fR is ignored. If \fIname\fR contains no separators then returns \fIname\fR. So, \fBfile tail a/b\fR, \fBfile tail a/b/\fR and \fBfile tail b\fR all return \fBb\fR. .TP \fBfile tempfile\fR ?\fInameVar\fR? ?\fItemplate\fR? '\" TIP #210 .VS 8.6 Creates a temporary file and returns a read-write channel opened on that file. If the \fInameVar\fR is given, it specifies a variable that the name of the temporary file will be written into; if absent, Tcl will attempt to arrange for the temporary file to be deleted once it is no longer required. If the \fItemplate\fR is present, it specifies parts of the template of the filename to use when creating it (such as the directory, base-name or extension) though some platforms may ignore some or all of these parts and use a built-in default instead. .RS .PP Note that temporary files are \fIonly\fR ever created on the native filesystem. As such, they can be relied upon to be used with operating-system native APIs and external programs that require a filename. .RE .VE 8.6 .TP \fBfile type \fIname\fR . Returns a string giving the type of file \fIname\fR, which will be one of \fBfile\fR, \fBdirectory\fR, \fBcharacterSpecial\fR, \fBblockSpecial\fR, \fBfifo\fR, \fBlink\fR, or \fBsocket\fR. .TP \fBfile volumes\fR . Returns the absolute paths to the volumes mounted on the system, as a proper Tcl list. Without any virtual filesystems mounted as root volumes, on UNIX, the command will always return .QW / , since all filesystems are locally mounted. On Windows, it will return a list of the available local drives (e.g. .QW "a:/ c:/" ). If any virtual filesystem has mounted additional volumes, they will be in the returned list. .TP \fBfile writable \fIname\fR . Returns \fB1\fR if file \fIname\fR is writable by the current user, \fB0\fR otherwise. .SH "PORTABILITY ISSUES" .TP \fBUnix\fR\0\0\0\0\0\0\0 . These commands always operate using the real user and group identifiers, not the effective ones. .TP \fBWindows\fR\0\0\0\0 . The \fBfile owned\fR subcommand currently always reports that the current user is the owner of the file, without regard for what the operating system believes to be true, making an ownership test useless. This issue (#3613671) may be fixed in a future release of Tcl. .SH EXAMPLES .PP This procedure shows how to search for C files in a given directory that have a correspondingly-named object file in the current directory: .PP .CS proc findMatchingCFiles {dir} { set files {} switch $::tcl_platform(platform) { windows { set ext .obj } unix { set ext .o } } foreach file [glob \-nocomplain \-directory $dir *.c] { set objectFile [\fBfile tail\fR [\fBfile rootname\fR $file]]$ext if {[\fBfile exists\fR $objectFile]} { lappend files $file } } return $files } .CE .PP Rename a file and leave a symbolic link pointing from the old location to the new place: .PP .CS set oldName foobar.txt set newName foo/bar.txt # Make sure that where we're going to move to exists... if {![\fBfile isdirectory\fR [\fBfile dirname\fR $newName]]} { \fBfile mkdir\fR [\fBfile dirname\fR $newName] } \fBfile rename\fR $oldName $newName \fBfile link\fR \-symbolic $oldName $newName .CE .PP On Windows, a file can be .QW started easily enough (equivalent to double-clicking on it in the Explorer interface) but the name passed to the operating system must be in native format: .PP .CS exec {*}[auto_execok start] {} [\fBfile nativename\fR ~/example.txt] .CE .SH "SEE ALSO" filename(n), open(n), close(n), eof(n), gets(n), tell(n), seek(n), fblocked(n), flush(n) .SH KEYWORDS attributes, copy files, delete files, directory, file, move files, name, rename files, stat, user '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/clock.n0000644000175000017500000011760412663660065013617 0ustar sergeisergei'\" '\" Generated from file './doc/clock.dt' by tcllib/doctools with format 'nroff' '\" Copyright (c) 2004 Kevin B. Kenny . All rights reserved. '\" .TH "clock" n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS .SH NAME clock \- Obtain and manipulate dates and times .SH "SYNOPSIS" package require \fBTcl 8.5\fR .sp \fBclock add\fR \fItimeVal\fR ?\fIcount unit...\fR? ?\fI\-option value\fR? .sp \fBclock clicks\fR ?\fI\-option\fR? .sp \fBclock format\fR \fItimeVal\fR ?\fI\-option value\fR...? .sp \fBclock microseconds\fR .sp \fBclock milliseconds\fR .sp \fBclock scan\fR \fIinputString\fR ?\fI\-option value\fR...? .sp \fBclock seconds\fR .sp .BE .SH "DESCRIPTION" .PP The \fBclock\fR command performs several operations that obtain and manipulate values that represent times. The command supports several subcommands that determine what action is carried out by the command. .TP \fBclock add\fR \fItimeVal\fR ?\fIcount unit...\fR? ?\fI\-option value\fR? Adds a (possibly negative) offset to a time that is expressed as an integer number of seconds. See \fBCLOCK ARITHMETIC\fR for a full description. .TP \fBclock clicks\fR ?\fI\-option\fR? If no \fI\-option\fR argument is supplied, returns a high-resolution time value as a system-dependent integer value. The unit of the value is system-dependent but should be the highest resolution clock available on the system such as a CPU cycle counter. See \fBHIGH RESOLUTION TIMERS\fR for a full description. .RS .PP If the \fI\-option\fR argument is \fB\-milliseconds\fR, then the command is synonymous with \fBclock milliseconds\fR (see below). This usage is obsolete, and \fBclock milliseconds\fR is to be considered the preferred way of obtaining a count of milliseconds. .PP If the \fI\-option\fR argument is \fB\-microseconds\fR, then the command is synonymous with \fBclock microseconds\fR (see below). This usage is obsolete, and \fBclock microseconds\fR is to be considered the preferred way of obtaining a count of microseconds. .RE .TP \fBclock format\fR \fItimeVal\fR ?\fI\-option value\fR...? Formats a time that is expressed as an integer number of seconds into a format intended for consumption by users or external programs. See \fBFORMATTING TIMES\fR for a full description. .TP \fBclock microseconds\fR Returns the current time as an integer number of microseconds. See \fBHIGH RESOLUTION TIMERS\fR for a full description. .TP \fBclock milliseconds\fR Returns the current time as an integer number of milliseconds. See \fBHIGH RESOLUTION TIMERS\fR for a full description. .TP \fBclock scan\fR \fIinputString\fR ?\fI\-option value\fR...? Scans a time that is expressed as a character string and produces an integer number of seconds. See \fBSCANNING TIMES\fR for a full description. .TP \fBclock seconds\fR Returns the current time as an integer number of seconds. .SS "PARAMETERS" .TP \fIcount\fR An integer representing a count of some unit of time. See \fBCLOCK ARITHMETIC\fR for the details. .TP \fItimeVal\fR An integer value passed to the \fBclock\fR command that represents an absolute time as a number of seconds from the \fIepoch time\fR of 1 January 1970, 00:00 UTC. Note that the count of seconds does not include any leap seconds; seconds are counted as if each UTC day has exactly 86400 seconds. Tcl responds to leap seconds by speeding or slowing its clock by a tiny fraction for some minutes until it is back in sync with UTC; its data model does not represent minutes that have 59 or 61 seconds. .TP \fIunit\fR One of the words, \fBseconds\fR, \fBminutes\fR, \fBhours\fR, \fBdays\fR, \fBweeks\fR, \fBmonths\fR, or \fByears\fR, or any unique prefix of such a word. Used in conjunction with \fIcount\fR to identify an interval of time, for example, \fI3 seconds\fR or \fI1 year\fR. .SS "OPTIONS" .TP \fB\-base\fR time Specifies that any relative times present in a \fBclock scan\fR command are to be given relative to \fItime\fR. \fItime\fR must be expressed as a count of nominal seconds from the epoch time of 1 January 1970, 00:00 UTC. .TP \fB\-format\fR format Specifies the desired output format for \fBclock format\fR or the expected input format for \fBclock scan\fR. The \fIformat\fR string consists of any number of characters other than the per-cent sign .PQ \fB%\fR interspersed with any number of \fIformat groups\fR, which are two-character sequences beginning with the per-cent sign. The permissible format groups, and their interpretation, are described under \fBFORMAT GROUPS\fR. .RS .PP On \fBclock format\fR, the default format is .PP .CS %a %b %d %H:%M:%S %Z %Y .CE .PP On \fBclock scan\fR, the lack of a \fB\-format\fR option indicates that a .QW "free format scan" is requested; see \fBFREE FORM SCAN\fR for a description of what happens. .RE .TP \fB\-gmt\fR boolean If \fIboolean\fR is true, specifies that a time specified to \fBclock add\fR, \fBclock format\fR or \fBclock scan\fR should be processed in UTC. If \fIboolean\fR is false, the processing defaults to the local time zone. This usage is obsolete; the correct current usage is to specify the UTC time zone with .QW "\fB\-timezone\fR \fI:UTC\fR" or any of the equivalent ways to specify it. .TP \fB\-locale\fR localeName Specifies that locale-dependent scanning and formatting (and date arithmetic for dates preceding the adoption of the Gregorian calendar) is to be done in the locale identified by \fIlocaleName\fR. The locale name may be any of the locales acceptable to the \fBmsgcat\fR package, or it may be the special name \fIsystem\fR, which represents the current locale of the process, or the null string, which represents Tcl's default locale. .RS .PP The effect of locale on scanning and formatting is discussed in the descriptions of the individual format groups under \fBFORMAT GROUPS\fR. The effect of locale on clock arithmetic is discussed under \fBCLOCK ARITHMETIC\fR. .RE .TP \fB\-timezone\fR zoneName Specifies that clock arithmetic, formatting, and scanning are to be done according to the rules for the time zone specified by \fIzoneName\fR. The permissible values, and their interpretation, are discussed under \fBTIME ZONES\fR. On subcommands that expect a \fB\-timezone\fR argument, the default is to use the \fIcurrent time zone\fR. The current time zone is determined, in order of preference, by: .RS .IP [1] the environment variable \fBTCL_TZ\fR. .IP [2] the environment variable \fBTZ\fR. .IP [3] on Windows systems, the time zone settings from the Control Panel. .RE .PP If none of these is present, the C \fBlocaltime\fR and \fBmktime\fR functions are used to attempt to convert times between local and Greenwich. On 32-bit systems, this approach is likely to have bugs, particularly for times that lie outside the window (approximately the years 1902 to 2037) that can be represented in a 32-bit integer. .SH "CLOCK ARITHMETIC" .PP The \fBclock add\fR command performs clock arithmetic on a value (expressed as nominal seconds from the epoch time of 1 January 1970, 00:00 UTC) given as its first argument. The remaining arguments (other than the possible \fB\-timezone\fR, \fB\-locale\fR and \fB\-gmt\fR options) are integers and keywords in alternation, where the keywords are chosen from \fBseconds\fR, \fBminutes\fR, \fBhours\fR, \fBdays\fR, \fBweeks\fR, \fBmonths\fR, or \fByears\fR, or any unique prefix of such a word. .PP Addition of seconds, minutes and hours is fairly straightforward; the given time increment (times sixty for minutes, or 3600 for hours) is simply added to the \fItimeVal\fR given to the \fBclock add\fR command. The result is interpreted as a nominal number of seconds from the Epoch. .PP Surprising results may be obtained when crossing a point at which a leap second is inserted or removed; the \fBclock add\fR command simply ignores leap seconds and therefore assumes that times come in sequence, 23:59:58, 23:59:59, 00:00:00. (This assumption is handled by the fact that Tcl's model of time reacts to leap seconds by speeding or slowing the clock by a minuscule amount until Tcl's time is back in step with the world. .PP The fact that adding and subtracting hours is defined in terms of absolute time means that it will add fixed amounts of time in time zones that observe summer time (Daylight Saving Time). For example, the following code sets the value of \fBx\fR to \fB04:00:00\fR because the clock has changed in the interval in question. .PP .CS set s [\fBclock scan\fR {2004-10-30 05:00:00} \e -format {%Y-%m-%d %H:%M:%S} \e -timezone :America/New_York] set a [\fBclock add\fR $s 24 hours -timezone :America/New_York] set x [\fBclock format\fR $a \e -format {%H:%M:%S} -timezone :America/New_York] .CE .PP Adding and subtracting days and weeks is accomplished by converting the given time to a calendar day and time of day in the appropriate time zone and locale. The requisite number of days (weeks are converted to days by multiplying by seven) is added to the calendar day, and the date and time are then converted back to a count of seconds from the epoch time. .PP Adding and subtracting a given number of days across the point that the time changes at the start or end of summer time (Daylight Saving Time) results in the \fIsame local time\fR on the day in question. For instance, the following code sets the value of \fBx\fR to \fB05:00:00\fR. .PP .CS set s [\fBclock scan\fR {2004-10-30 05:00:00} \e -format {%Y-%m-%d %H:%M:%S} \e -timezone :America/New_York] set a [\fBclock add\fR $s 1 day -timezone :America/New_York] set x [\fBclock format\fR $a \e -format {%H:%M:%S} -timezone :America/New_York] .CE .PP In cases of ambiguity, where the same local time happens twice on the same day, the earlier time is used. In cases where the conversion yields an impossible time (for instance, 02:30 during the Spring Daylight Saving Time change using US rules), the time is converted as if the clock had not changed. Thus, the following code will set the value of \fBx\fR to \fB03:30:00\fR. .PP .CS set s [\fBclock scan\fR {2004-04-03 02:30:00} \e -format {%Y-%m-%d %H:%M:%S} \e -timezone :America/New_York] set a [\fBclock add\fR $s 1 day -timezone :America/New_York] set x [\fBclock format\fR $a \e -format {%H:%M:%S} -timezone :America/New_York] .CE .PP Adding a given number of days or weeks works correctly across the conversion between the Julian and Gregorian calendars; the omitted days are skipped. The following code sets \fBz\fR to \fB1752-09-14\fR. .PP .CS set x [\fBclock scan\fR 1752-09-02 -format %Y-%m-%d -locale en_US] set y [\fBclock add\fR $x 1 day -locale en_US] set z [\fBclock format\fR $y -format %Y-%m-%d -locale en_US] .CE .PP In the bizarre case that adding the given number of days yields a date that does not exist because it falls within the dropped days of the Julian-to-Gregorian conversion, the date is converted as if it was on the Julian calendar. .PP Adding a number of months, or a number of years, is similar; it converts the given time to a calendar date and time of day. It then adds the requisite number of months or years, and reconverts the resulting date and time of day to an absolute time. .PP If the resulting date is impossible because the month has too few days (for example, when adding 1 month to 31 January), the last day of the month is substituted. Thus, adding 1 month to 31 January will result in 28 February in a common year or 29 February in a leap year. .PP The rules for handling anomalies relating to summer time and to the Gregorian calendar are the same when adding/subtracting months and years as they are when adding/subtracting days and weeks. .PP If multiple \fIcount unit\fR pairs are present on the command, they are evaluated consecutively, from left to right. .SH "HIGH RESOLUTION TIMERS" .PP Most of the subcommands supported by the \fBclock\fR command deal with times represented as a count of seconds from the epoch time, and this is the representation that \fBclock seconds\fR returns. There are three exceptions, which are all intended for use where higher-resolution times are required. \fBclock milliseconds\fR returns the count of milliseconds from the epoch time, and \fBclock microseconds\fR returns the count of microseconds from the epoch time. In addition, there is a \fBclock clicks\fR command that returns a platform-dependent high-resolution timer. Unlike \fBclock seconds\fR and \fBclock milliseconds\fR, the value of \fBclock clicks\fR is not guaranteed to be tied to any fixed epoch; it is simply intended to be the most precise interval timer available, and is intended only for relative timing studies such as benchmarks. .SH "FORMATTING TIMES" .PP The \fBclock format\fR command produces times for display to a user or writing to an external medium. The command accepts times that are expressed in seconds from the epoch time of 1 January 1970, 00:00 UTC, as returned by \fBclock seconds\fR, \fBclock scan\fR, \fBclock add\fR, \fBfile atime\fR or \fBfile mtime\fR. .PP If a \fB\-format\fR option is present, the following argument is a string that specifies how the date and time are to be formatted. The string consists of any number of characters other than the per-cent sign .PQ \fB%\fR interspersed with any number of \fIformat groups\fR, which are two-character sequences beginning with the per-cent sign. The permissible format groups, and their interpretation, are described under \fBFORMAT GROUPS\fR. .PP If a \fB\-timezone\fR option is present, the following argument is a string that specifies the time zone in which the date and time are to be formatted. As an alternative to .QW "\fB\-timezone\fR \fI:UTC\fR" , the obsolete usage .QW "\fB\-gmt\fR \fItrue\fR" may be used. See \fBTIME ZONES\fR for the permissible variants for the time zone. .PP If a \fB\-locale\fR option is present, the following argument is a string that specifies the locale in which the time is to be formatted, in the same format that is used for the \fBmsgcat\fR package. Note that the default, if \fB\-locale\fR is not specified, is the root locale \fB{}\fR rather than the current locale. The current locale may be obtained by using \fB\-locale\fR \fBcurrent\fR. In addition, some platforms support a \fBsystem\fR locale that reflects the user's current choices. For instance, on Windows, the format that the user has selected from dates and times in the Control Panel can be obtained by using the \fBsystem\fR locale. On platforms that do not define a user selection of date and time formats separate from \fBLC_TIME\fR, \fB\-locale\fR \fBsystem\fR is synonymous with \fB\-locale\fR \fBcurrent\fR. .SH "SCANNING TIMES" .PP The \fBclock scan\fR command accepts times that are formatted as strings and converts them to counts of seconds from the epoch time of 1 January 1970, 00:00 UTC. It normally takes a \fB\-format\fR option that is followed by a string describing the expected format of the input. (See \fBFREE FORM SCAN\fR for the effect of \fBclock scan\fR without such an argument.) The string consists of any number of characters other than the per-cent sign .PQ \fB%\fR "" , interspersed with any number of \fIformat groups\fR, which are two-character sequences beginning with the per-cent sign. The permissible format groups, and their interpretation, are described under \fBFORMAT GROUPS\fR. .PP If a \fB\-timezone\fR option is present, the following argument is a string that specifies the time zone in which the date and time are to be interpreted. As an alternative to \fB\-timezone\fR \fI:UTC\fR, the obsolete usage \fB\-gmt\fR \fItrue\fR may be used. See \fBTIME ZONES\fR for the permissible variants for the time zone. .PP If a \fB\-locale\fR option is present, the following argument is a string that specifies the locale in which the time is to be interpreted, in the same format that is used for the \fBmsgcat\fR package. Note that the default, if \fB\-locale\fR is not specified, is the root locale \fB{}\fR rather than the current locale. The current locale may be obtained by using \fB\-locale\fR \fBcurrent\fR. In addition, some platforms support a \fBsystem\fR locale that reflects the user's current choices. For instance, on Windows, the format that the user has selected from dates and times in the Control Panel can be obtained by using the \fBsystem\fR locale. On platforms that do not define a user selection of date and time formats separate from \fBLC_TIME\fR, \fB\-locale\fR \fBsystem\fR is synonymous with \fB\-locale\fR \fBcurrent\fR. .PP If a \fB\-base\fR option is present, the following argument is a time (expressed in seconds from the epoch time) that is used as a \fIbase time\fR for interpreting relative times. If no \fB\-base\fR option is present, the base time is the current time. .PP Scanning of times in fixed format works by determining three things: the date, the time of day, and the time zone. These three are then combined into a point in time, which is returned as the number of seconds from the epoch. .PP Before scanning begins, the format string is preprocessed to replace \fB%c\fR, \fB%Ec\fR, \fB%x\fR, \fB%Ex\fR, \fB%X\fR. \fB%Ex\fR, \fB%r\fR, \fB%R\fR, \fB%T\fR, \fB%D\fR, \fB%EY\fR and \fB%+\fR format groups with counterparts that are appropriate to the current locale and contain none of the above groups. For instance, \fB%D\fR will (in the \fBen_US\fR locale) be replaced with \fB%m/%d/%Y\fR. .PP The date is determined according to the fields that are present in the preprocessed format string. In order of preference: .IP [1] If the string contains a \fB%s\fR format group, representing seconds from the epoch, that group is used to determine the date. .IP [2] If the string contains a \fB%J\fR format group, representing the Julian Day Number, that group is used to determine the date. .IP [3] If the string contains a complete set of format groups specifying century, year, month, and day of month; century, year, and day of year; or ISO8601 fiscal year, week of year, and day of week; those groups are combined and used to determine the date. If more than one complete set is present, the one at the rightmost position in the string is used. .IP [4] If the string lacks a century but contains a set of format groups specifying year of century, month and day of month; year of century and day of year; or two-digit ISO8601 fiscal year, week of year, and day of week; those groups are combined and used to determine the date. If more than one complete set is present, the one at the rightmost position in the string is used. The year is presumed to lie in the range 1938 to 2037 inclusive. .IP [5] If the string entirely lacks any specification for the year (or contains the year only on the locale's alternative calendar) and contains a set of format groups specifying month and day of month, day of year, or week of year and day of week, those groups are combined and used to determine the date. If more than one complete set is present, the one at the rightmost position in the string is used. The year is determined by interpreting the base time in the given time zone. .IP [6] If the string contains none of the above sets, but has a day of the month or day of the week, the day of the month or day of the week are used to determine the date by interpreting the base time in the given time zone and returning the given day of the current week or month. (The week runs from Monday to Sunday, ISO8601-fashion.) If both day of month and day of week are present, the day of the month takes priority. .IP [7] If none of the above rules results in a usable date, the date of the base time in the given time zone is used. .PP The time is also determined according to the fields that are present in the preprocessed format string. In order of preference: .IP [1] If the string contains a \fB%s\fR format group, representing seconds from the epoch, that group determines the time of day. .IP [2] If the string contains either an hour on the 24-hour clock or an hour on the 12-hour clock plus an AM/PM indicator, that hour determines the hour of the day. If the string further contains a group specifying the minute of the hour, that group combines with the hour. If the string further contains a group specifying the second of the minute, that group combines with the hour and minute. .IP [3] If the string contains neither a \fB%s\fR format group nor a group specifying the hour of the day, then midnight (\fB00:00\fR, the start of the given date) is used. The time zone is determined by either the \fB\-timezone\fR or \fB\-gmt\fR options, or by using the current time zone. .PP If a format string lacks a \fB%z\fR or \fB%Z\fR format group, it is possible for the time to be ambiguous because it appears twice in the same day, once without and once with Daylight Saving Time. If this situation occurs, the first occurrence of the time is chosen. (For this reason, it is wise to have the input string contain the time zone when converting local times. This caveat does not apply to UTC times.) .SH "FORMAT GROUPS" .PP The following format groups are recognized by the \fBclock scan\fR and \fBclock format\fR commands. .TP \fB%a\fR On output, receives an abbreviation (\fIe.g.,\fR \fBMon\fR) for the day of the week in the given locale. On input, matches the name of the day of the week in the given locale (in either abbreviated or full form, or any unique prefix of either form). .TP \fB%A\fR On output, receives the full name (\fIe.g.,\fR \fBMonday\fR) of the day of the week in the given locale. On input, matches the name of the day of the week in the given locale (in either abbreviated or full form, or any unique prefix of either form). .TP \fB%b\fR On output, receives an abbreviation (\fIe.g.,\fR \fBJan\fR) for the name of the month in the given locale. On input, matches the name of the month in the given locale (in either abbreviated or full form, or any unique prefix of either form). .TP \fB%B\fR On output, receives the full name (\fIe.g.,\fR \fBJanuary\fR) of the month in the given locale. On input, matches the name of the month in the given locale (in either abbreviated or full form, or any unique prefix of either form). .TP \fB%c\fR On output, receives a localized representation of date and time of day; the localized representation is expected to use the Gregorian calendar. On input, matches whatever \fB%c\fR produces. .TP \fB%C\fR On output, receives the number of the century in Indo-Arabic numerals. On input, matches one or two digits, possibly with leading whitespace, that are expected to be the number of the century. .TP \fB%d\fR On output, produces the number of the day of the month, as two decimal digits. On input, matches one or two digits, possibly with leading whitespace, that are expected to be the number of the day of the month. .TP \fB%D\fR This format group is synonymous with \fB%m/%d/%Y\fR. It should be used only in exchanging data within the \fBen_US\fR locale, since other locales typically do not use this order for the fields of the date. .TP \fB%e\fR On output, produces the number of the day of the month, as one or two decimal digits (with a leading blank for one-digit dates). On input, matches one or two digits, possibly with leading whitespace, that are expected to be the number of the day of the month. .TP \fB%Ec\fR On output, produces a locale-dependent representation of the date and time of day in the locale's alternative calendar. On input, matches whatever \fB%Ec\fR produces. The locale's alternative calendar need not be the Gregorian calendar. .TP \fB%EC\fR On output, produces a locale-dependent name of an era in the locale's alternative calendar. On input, matches the name of the era or any unique prefix. .TP \fB%EE\fR On output, produces the string \fBB.C.E.\fR or \fBC.E.\fR, or a string of the same meaning in the locale, to indicate whether \fB%Y\fR refers to years before or after Year 1 of the Common Era. On input, accepts the string \fBB.C.E.\fR, \fBB.C.\fR, \fBC.E.\fR, \fBA.D.\fR, or the abbreviation appropriate to the current locale, and uses it to fix whether \fB%Y\fR refers to years before or after Year 1 of the Common Era. .TP \fB%Ex\fR On output, produces a locale-dependent representation of the date in the locale's alternative calendar. On input, matches whatever \fB%Ex\fR produces. The locale's alternative calendar need not be the Gregorian calendar. .TP \fB%EX\fR On output, produces a locale-dependent representation of the time of day in the locale's alternative numerals. On input, matches whatever \fB%EX\fR produces. .TP \fB%Ey\fR On output, produces a locale-dependent number of the year of the era in the locale's alternative calendar and numerals. On input, matches such a number. .TP \fB%EY\fR On output, produces a representation of the year in the locale's alternative calendar and numerals. On input, matches what \fB%EY\fR produces. Often synonymous with \fB%EC%Ey\fR. .TP \fB%g\fR On output, produces a two-digit year number suitable for use with the week-based ISO8601 calendar; that is, the year number corresponds to the week number produced by \fB%V\fR. On input, accepts such a two-digit year number, possibly with leading whitespace. .TP \fB%G\fR On output, produces a four-digit year number suitable for use with the week-based ISO8601 calendar; that is, the year number corresponds to the week number produced by \fB%V\fR. On input, accepts such a four-digit year number, possibly with leading whitespace. .TP \fB%h\fR This format group is synonymous with \fB%b\fR. .TP \fB%H\fR On output, produces a two-digit number giving the hour of the day (00-23) on a 24-hour clock. On input, accepts such a number. .TP \fB%I\fR On output, produces a two-digit number giving the hour of the day (12-11) on a 12-hour clock. On input, accepts such a number. .TP \fB%j\fR On output, produces a three-digit number giving the day of the year (001-366). On input, accepts such a number. .TP \fB%J\fR On output, produces a string of digits giving the Julian Day Number. On input, accepts a string of digits and interprets it as a Julian Day Number. The Julian Day Number is a count of the number of calendar days that have elapsed since 1 January, 4713 BCE of the proleptic Julian calendar. The epoch time of 1 January 1970 corresponds to Julian Day Number 2440588. .TP \fB%k\fR On output, produces a one- or two-digit number giving the hour of the day (0-23) on a 24-hour clock. On input, accepts such a number. .TP \fB%l\fR On output, produces a one- or two-digit number giving the hour of the day (12-11) on a 12-hour clock. On input, accepts such a number. .TP \fB%m\fR On output, produces the number of the month (01-12) with exactly two digits. On input, accepts two digits and interprets them as the number of the month. .TP \fB%M\fR On output, produces the number of the minute of the hour (00-59) with exactly two digits. On input, accepts two digits and interprets them as the number of the minute of the hour. .TP \fB%N\fR On output, produces the number of the month (1-12) with one or two digits, and a leading blank for one-digit dates. On input, accepts one or two digits, possibly with leading whitespace, and interprets them as the number of the month. .TP \fB%Od\fR, \fB%Oe\fR, \fB%OH\fR, \fB%OI\fR, \fB%Ok\fR, \fB%Ol\fR, \fB%Om\fR, \fB%OM\fR, \fB%OS\fR, \fB%Ou\fR, \fB%Ow\fR, \fB%Oy\fR All of these format groups are synonymous with their counterparts without the .QW \fBO\fR , except that the string is produced and parsed in the locale-dependent alternative numerals. .TP \fB%p\fR On output, produces an indicator for the part of the day, \fBAM\fR or \fBPM\fR, appropriate to the given locale. If the script of the given locale supports multiple letterforms, lowercase is preferred. On input, matches the representation \fBAM\fR or \fBPM\fR in the given locale, in either case. .TP \fB%P\fR On output, produces an indicator for the part of the day, \fBam\fR or \fBpm\fR, appropriate to the given locale. If the script of the given locale supports multiple letterforms, uppercase is preferred. On input, matches the representation \fBAM\fR or \fBPM\fR in the given locale, in either case. .TP \fB%Q\fR This format group is reserved for internal use within the Tcl library. .TP \fB%r\fR On output, produces a locale-dependent time of day representation on a 12-hour clock. On input, accepts whatever \fB%r\fR produces. .TP \fB%R\fR On output, the time in 24-hour notation (%H:%M). For a version including the seconds, see \fB%T\fR below. On input, accepts whatever \fB%R\fR produces. .TP \fB%s\fR On output, simply formats the \fItimeVal\fR argument as a decimal integer and inserts it into the output string. On input, accepts a decimal integer and uses is as the time value without any further processing. Since \fB%s\fR uniquely determines a point in time, it overrides all other input formats. .TP \fB%S\fR On output, produces a two-digit number of the second of the minute (00-59). On input, accepts two digits and uses them as the second of the minute. .TP \fB%t\fR On output, produces a TAB character. On input, matches a TAB character. .TP \fB%T\fR Synonymous with \fB%H:%M:%S\fR. .TP \fB%u\fR On output, produces the number of the day of the week (\fB1\fR\(->Monday, \fB7\fR\(->Sunday). On input, accepts a single digit and interprets it as the day of the week. Sunday may be either \fB0\fR or \fB7\fR. .TP \fB%U\fR On output, produces the ordinal number of the week of the year (00-53). The first Sunday of the year is the first day of week 01. On input accepts two digits which are otherwise ignored. This format group is never used in determining an input date. This interpretation of the week of the year was once common in US banking but is now largely obsolete. See \fB%V\fR for the ISO8601 week number. .TP \fB%V\fR On output, produces the number of the ISO8601 week as a two digit number (01-53). Week 01 is the week containing January 4; or the first week of the year containing at least 4 days; or the week containing the first Thursday of the year (the three statements are equivalent). Each week begins on a Monday. On input, accepts the ISO8601 week number. .TP \fB%w\fR On output, produces the ordinal number of the day of the week (Sunday==0; Saturday==6). On input, accepts a single digit and interprets it as the day of the week; Sunday may be represented as either 0 or 7. Note that \fB%w\fR is not the ISO8601 weekday number, which is produced and accepted by \fB%u\fR. .TP \fB%W\fR On output, produces a week number (00-53) within the year; week 01 begins on the first Monday of the year. On input, accepts two digits, which are otherwise ignored. This format group is never used in determining an input date. It is not the ISO8601 week number; that week is produced and accepted by \fB%V\fR. .TP \fB%x\fR On output, produces the date in a locale-dependent representation. On input, accepts whatever \fB%x\fR produces and is used to determine calendar date. .TP \fB%X\fR On output, produces the time of day in a locale-dependent representation. On input, accepts whatever \fB%X\fR produces and is used to determine time of day. .TP \fB%y\fR On output, produces the two-digit year of the century. On input, accepts two digits, and is used to determine calendar date. The date is presumed to lie between 1938 and 2037 inclusive. Note that \fB%y\fR does not yield a year appropriate for use with the ISO8601 week number \fB%V\fR; programs should use \fB%g\fR for that purpose. .TP \fB%Y\fR On output, produces the four-digit calendar year. On input, accepts four digits and may be used to determine calendar date. Note that \fB%Y\fR does not yield a year appropriate for use with the ISO8601 week number \fB%V\fR; programs should use \fB%G\fR for that purpose. .TP \fB%z\fR On output, produces the current time zone, expressed in hours and minutes east (+hhmm) or west (\-hhmm) of Greenwich. On input, accepts a time zone specifier (see \fBTIME ZONES\fR below) that will be used to determine the time zone. .TP \fB%Z\fR On output, produces the current time zone's name, possibly translated to the given locale. On input, accepts a time zone specifier (see \fBTIME ZONES\fR below) that will be used to determine the time zone. This option should, in general, be used on input only when parsing RFC822 dates. Other uses are fraught with ambiguity; for instance, the string \fBBST\fR may represent British Summer Time or Brazilian Standard Time. It is recommended that date/time strings for use by computers use numeric time zones instead. .TP \fB%%\fR On output, produces a literal .QW \fB%\fR character. On input, matches a literal .QW \fB%\fR character. .TP \fB%+\fR Synonymous with .QW "\fB%a %b %e %H:%M:%S %Z %Y\fR" . .SH "TIME ZONES" .PP When the \fBclock\fR command is processing a local time, it has several possible sources for the time zone to use. In order of preference, they are: .IP [1] A time zone specified inside a string being parsed and matched by a \fB%z\fR or \fB%Z\fR format group. .IP [2] A time zone specified with the \fB\-timezone\fR option to the \fBclock\fR command (or, equivalently, by \fB\-gmt\fR \fB1\fR). .IP [3] A time zone specified in an environment variable \fBTCL_TZ\fR. .IP [4] A time zone specified in an environment variable \fBTZ\fR. .IP [5] The local time zone from the Control Panel on Windows systems. .IP [6] The C library's idea of the local time zone, as defined by the \fBmktime\fR and \fBlocaltime\fR functions. .PP In case [1] \fIonly,\fR the string is tested to see if it is one of the strings: .PP .CS gmt ut utc bst wet wat at nft nst ndt ast adt est edt cst cdt mst mdt pst pdt yst ydt hst hdt cat ahst nt idlw cet cest met mewt mest swt sst eet eest bt it zp4 zp5 ist zp6 wast wadt jt cct jst cast cadt east eadt gst nzt nzst nzdt idle .CE .PP If it is a string in the above list, it designates a known time zone, and is interpreted as such. .PP For time zones in case [1] that do not match any of the above strings, and always for cases [2]-[6], the following rules apply. .PP If the time zone begins with a colon, it is one of a standardized list of names like \fB:America/New_York\fR that give the rules for various locales. A complete list of the location names is too lengthy to be listed here. On most Tcl installations, the definitions of the locations are to be found in named files in the directory .QW "\fI/no_backup/tools/lib/tcl8.5/clock/tzdata\fR" . On some Unix systems, these files are omitted, and the definitions are instead obtained from system files in .QW "\fI/usr/share/zoneinfo\fR" , .QW "\fI/usr/share/lib/zoneinfo\fR" or .QW "\fI/usr/local/etc/zoneinfo\fR" . As a special case, the name \fB:localtime\fR refers to the local time zone as defined by the C library. .PP A time zone string consisting of a plus or minus sign followed by four or six decimal digits is interpreted as an offset in hours, minutes, and seconds (if six digits are present) from UTC. The plus sign denotes a sign east of Greenwich; the minus sign one west of Greenwich. .PP A time zone string conforming to the Posix specification of the \fBTZ\fR environment variable will be recognized. The specification may be found at \fIhttp://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html\fR. .PP If the Posix time zone string contains a DST (Daylight Savings Time) part, but doesn't contain a rule stating when DST starts or ends, then default rules are used. For Timezones with an offset between 0 and +12, the current European/Russian rules are used, otherwise the current US rules are used. In Europe (offset +0 to +2) the switch to summertime is done each last Sunday in March at 1:00 GMT, and the switch back is each last Sunday in October at 2:00 GMT. In Russia (offset +3 to +12), the switch dates are the same, only the switch to summertime is at 2:00 local time, and the switch back is at 3:00 local time in all time zones. The US switch to summertime takes place each second Sunday in March at 2:00 local time, and the switch back is each first Sunday in November at 3:00 local time. These default rules mean that in all European, Russian and US (or compatible) time zones, DST calculations will be correct for dates in 2007 and later, unless in the future the rules change again. .PP Any other time zone string is processed by prefixing a colon and attempting to use it as a location name, as above. .SH "LOCALIZATION" .PP Developers wishing to localize the date and time formatting and parsing are referred to \fIhttp://tip.tcl.tk/173\fR for a specification. .SH "FREE FORM SCAN" .PP If the \fBclock scan\fR command is invoked without a \fB\-format\fR option, then it requests a \fIfree-form scan.\fR \fI This form of scan is deprecated.\fR The reason for the deprecation is that there are too many ambiguities. (Does the string .QW 2000 represent a year, a time of day, or a quantity?) No set of rules for interpreting free-form dates and times has been found to give unsurprising results in all cases. .PP If free-form scan is used, only the \fB\-base\fR and \fB\-gmt\fR options are accepted. The \fB\-timezone\fR and \fB\-locale\fR options will result in an error if \fB\-format\fR is not supplied. .PP For the benefit of users who need to understand legacy code that uses free-form scan, the documentation for how free-form scan interprets a string is included here: .PP If only a time is specified, the current date is assumed. If the \fIinputString\fR does not contain a time zone mnemonic, the local time zone is assumed, unless the \fB\-gmt\fR argument is true, in which case the clock value is calculated assuming that the specified time is relative to Greenwich Mean Time. \fB\-gmt\fR, if specified, affects only the computed time value; it does not impact the interpretation of \fB\-base\fR. .PP If the \fB\-base\fR flag is specified, the next argument should contain an integer clock value. Only the date in this value is used, not the time. This is useful for determining the time on a specific day or doing other date-relative conversions. .PP The \fIinputString\fR argument consists of zero or more specifications of the following form: .TP \fItime\fR A time of day, which is of the form: \fBhh?:mm?:ss?? ?meridian? ?zone?\fR or \fBhhmm ?meridian? ?zone?\fR If no meridian is specified, \fBhh\fR is interpreted on a 24-hour clock. .TP \fIdate\fR A specific month and day with optional year. The acceptable formats are .QW "\fBmm/dd\fR?\fB/yy\fR?" , .QW "\fBmonthname dd\fR?\fB, yy\fR?" , .QW "\fBday, dd monthname \fR?\fByy\fR?" , .QW "\fBdd monthname yy\fR" , .QW "?\fBCC\fR?\fByymmdd\fR" , and .QW "\fBdd-monthname-\fR?\fBCC\fR?\fByy\fR" . The default year is the current year. If the year is less than 100, we treat the years 00-68 as 2000-2068 and the years 69-99 as 1969-1999. Not all platforms can represent the years 38-70, so an error may result if these years are used. .TP \fIISO 8601 point-in-time\fR An ISO 8601 point-in-time specification, such as .QW \fICCyymmdd\fBT\fIhhmmss\fR, where \fBT\fR is the literal .QW T , .QW "\fICCyymmdd hhmmss\fR" , or .QW \fICCyymmdd\fBT\fIhh:mm:ss\fR . Note that only these three formats are accepted. The command does \fInot\fR accept the full range of point-in-time specifications specified in ISO8601. Other formats can be recognized by giving an explicit \fB\-format\fR option to the \fBclock scan\fR command. .TP \fIrelative time\fR A specification relative to the current time. The format is \fBnumber unit\fR. Acceptable units are \fByear\fR, \fBfortnight\fR, \fBmonth\fR, \fBweek\fR, \fBday\fR, \fBhour\fR, \fBminute\fR (or \fBmin\fR), and \fBsecond\fR (or \fBsec\fR). The unit can be specified as a singular or plural, as in \fB3 weeks\fR. These modifiers may also be specified: \fBtomorrow\fR, \fByesterday\fR, \fBtoday\fR, \fBnow\fR, \fBlast\fR, \fBthis\fR, \fBnext\fR, \fBago\fR. .PP The actual date is calculated according to the following steps. .PP First, any absolute date and/or time is processed and converted. Using that time as the base, day-of-week specifications are added. Next, relative specifications are used. If a date or day is specified, and no absolute or relative time is given, midnight is used. Finally, a correction is applied so that the correct hour of the day is produced after allowing for daylight savings time differences and the correct date is given when going from the end of a long month to a short month. .SH "SEE ALSO" msgcat(n) .SH KEYWORDS clock, date, time .SH "COPYRIGHT" Copyright (c) 2004 Kevin B. Kenny . All rights reserved. '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/return.n0000644000175000017500000003215112663660065014034 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Contributions from Don Porter, NIST, 2003. (not subject to US copyright) '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH return n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME return \- Return from a procedure, or set return code of a script .SH SYNOPSIS \fBreturn \fR?\fIresult\fR? .sp \fBreturn \fR?\fB\-code \fIcode\fR? ?\fIresult\fR? .sp \fBreturn \fR?\fIoption value \fR...? ?\fIresult\fR? .BE .SH DESCRIPTION .PP In its simplest usage, the \fBreturn\fR command is used without options in the body of a procedure to immediately return control to the caller of the procedure. If a \fIresult\fR argument is provided, its value becomes the result of the procedure passed back to the caller. If \fIresult\fR is not specified then an empty string will be returned to the caller as the result of the procedure. .PP The \fBreturn\fR command serves a similar function within script files that are evaluated by the \fBsource\fR command. When \fBsource\fR evaluates the contents of a file as a script, an invocation of the \fBreturn\fR command will cause script evaluation to immediately cease, and the value \fIresult\fR (or an empty string) will be returned as the result of the \fBsource\fR command. .SH "EXCEPTIONAL RETURN CODES" .PP In addition to the result of a procedure, the return code of a procedure may also be set by \fBreturn\fR through use of the \fB\-code\fR option. In the usual case where the \fB\-code\fR option is not specified the procedure will return normally. However, the \fB\-code\fR option may be used to generate an exceptional return from the procedure. \fICode\fR may have any of the following values: .TP 13 \fBok\fR (or \fB0\fR) . Normal return: same as if the option is omitted. The return code of the procedure is 0 (\fBTCL_OK\fR). .TP 13 \fBerror\fR (or \fB1\fR) . Error return: the return code of the procedure is 1 (\fBTCL_ERROR\fR). The procedure command behaves in its calling context as if it were the command \fBerror\fR \fIresult\fR. See below for additional options. .TP 13 \fBreturn\fR (or \fB2\fR) . The return code of the procedure is 2 (\fBTCL_RETURN\fR). The procedure command behaves in its calling context as if it were the command \fBreturn\fR (with no arguments). .TP 13 \fBbreak\fR (or \fB3\fR) . The return code of the procedure is 3 (\fBTCL_BREAK\fR). The procedure command behaves in its calling context as if it were the command \fBbreak\fR. .TP 13 \fBcontinue\fR (or \fB4\fR) . The return code of the procedure is 4 (\fBTCL_CONTINUE\fR). The procedure command behaves in its calling context as if it were the command \fBcontinue\fR. .TP 13 \fIvalue\fR . \fIValue\fR must be an integer; it will be returned as the return code for the current procedure. .LP When a procedure wants to signal that it has received invalid arguments from its caller, it may use \fBreturn -code error\fR with \fIresult\fR set to a suitable error message. Otherwise usage of the \fBreturn -code\fR option is mostly limited to procedures that implement a new control structure. .PP The \fBreturn \-code\fR command acts similarly within script files that are evaluated by the \fBsource\fR command. During the evaluation of the contents of a file as a script by \fBsource\fR, an invocation of the \fBreturn \-code \fIcode\fR command will cause the return code of \fBsource\fR to be \fIcode\fR. .SH "RETURN OPTIONS" .PP In addition to a result and a return code, evaluation of a command in Tcl also produces a dictionary of return options. In general usage, all \fIoption value\fR pairs given as arguments to \fBreturn\fR become entries in the return options dictionary, and any values at all are acceptable except as noted below. The \fBcatch\fR command may be used to capture all of this information \(em the return code, the result, and the return options dictionary \(em that arise from evaluation of a script. .PP As documented above, the \fB\-code\fR entry in the return options dictionary receives special treatment by Tcl. There are other return options also recognized and treated specially by Tcl. They are: .TP \fB\-errorcode \fIlist\fR . The \fB\-errorcode\fR option receives special treatment only when the value of the \fB\-code\fR option is \fBTCL_ERROR\fR. Then the \fIlist\fR value is meant to be additional information about the error, presented as a Tcl list for further processing by programs. If no \fB\-errorcode\fR option is provided to \fBreturn\fR when the \fB\-code error\fR option is provided, Tcl will set the value of the \fB\-errorcode\fR entry in the return options dictionary to the default value of \fBNONE\fR. The \fB\-errorcode\fR return option will also be stored in the global variable \fBerrorCode\fR. .TP \fB\-errorinfo \fIinfo\fR . The \fB\-errorinfo\fR option receives special treatment only when the value of the \fB\-code\fR option is \fBTCL_ERROR\fR. Then \fIinfo\fR is the initial stack trace, meant to provide to a human reader additional information about the context in which the error occurred. The stack trace will also be stored in the global variable \fBerrorInfo\fR. If no \fB\-errorinfo\fR option is provided to \fBreturn\fR when the \fB\-code error\fR option is provided, Tcl will provide its own initial stack trace value in the entry for \fB\-errorinfo\fR. Tcl's initial stack trace will include only the call to the procedure, and stack unwinding will append information about higher stack levels, but there will be no information about the context of the error within the procedure. Typically the \fIinfo\fR value is supplied from the value of \fB\-errorinfo\fR in a return options dictionary captured by the \fBcatch\fR command (or from the copy of that information stored in the global variable \fBerrorInfo\fR). .TP \fB\-errorstack \fIlist\fR .VS 8.6 The \fB\-errorstack\fR option receives special treatment only when the value of the \fB\-code\fR option is \fBTCL_ERROR\fR. Then \fIlist\fR is the initial error stack, recording actual argument values passed to each proc level. The error stack will also be reachable through \fBinfo errorstack\fR. If no \fB\-errorstack\fR option is provided to \fBreturn\fR when the \fB\-code error\fR option is provided, Tcl will provide its own initial error stack in the entry for \fB\-errorstack\fR. Tcl's initial error stack will include only the call to the procedure, and stack unwinding will append information about higher stack levels, but there will be no information about the context of the error within the procedure. Typically the \fIlist\fR value is supplied from the value of \fB\-errorstack\fR in a return options dictionary captured by the \fBcatch\fR command (or from the copy of that information from \fBinfo errorstack\fR). .VE 8.6 .TP \fB\-level \fIlevel\fR . The \fB\-level\fR and \fB\-code\fR options work together to set the return code to be returned by one of the commands currently being evaluated. The \fIlevel\fR value must be a non-negative integer representing a number of levels on the call stack. It defines the number of levels up the stack at which the return code of a command currently being evaluated should be \fIcode\fR. If no \fB\-level\fR option is provided, the default value of \fIlevel\fR is 1, so that \fBreturn\fR sets the return code that the current procedure returns to its caller, 1 level up the call stack. The mechanism by which these options work is described in more detail below. .TP \fB\-options \fIoptions\fR . The value \fIoptions\fR must be a valid dictionary. The entries of that dictionary are treated as additional \fIoption value\fR pairs for the \fBreturn\fR command. .SH "RETURN CODE HANDLING MECHANISMS" .PP Return codes are used in Tcl to control program flow. A Tcl script is a sequence of Tcl commands. So long as each command evaluation returns a return code of \fBTCL_OK\fR, evaluation will continue to the next command in the script. Any exceptional return code (non-\fBTCL_OK\fR) returned by a command evaluation causes the flow on to the next command to be interrupted. Script evaluation ceases, and the exceptional return code from the command becomes the return code of the full script evaluation. This is the mechanism by which errors during script evaluation cause an interruption and unwinding of the call stack. It is also the mechanism by which commands like \fBbreak\fR, \fBcontinue\fR, and \fBreturn\fR cause script evaluation to terminate without evaluating all commands in sequence. .PP Some of Tcl's built-in commands evaluate scripts as part of their functioning. These commands can make use of exceptional return codes to enable special features. For example, the built-in Tcl commands that provide loops \(em such as \fBwhile\fR, \fBfor\fR, and \fBforeach\fR \(em evaluate a script that is the body of the loop. If evaluation of the loop body returns the return code of \fBTCL_BREAK\fR or \fBTCL_CONTINUE\fR, the loop command can react in such a way as to give the \fBbreak\fR and \fBcontinue\fR commands their documented interpretation in loops. .PP Procedure invocation also involves evaluation of a script, the body of the procedure. Procedure invocation provides special treatment when evaluation of the procedure body returns the return code \fBTCL_RETURN\fR. In that circumstance, the \fB\-level\fR entry in the return options dictionary is decremented. If after decrementing, the value of the \fB\-level\fR entry is 0, then the value of the \fB\-code\fR entry becomes the return code of the procedure. If after decrementing, the value of the \fB\-level\fR entry is greater than zero, then the return code of the procedure is \fBTCL_RETURN\fR. If the procedure invocation occurred during the evaluation of the body of another procedure, the process will repeat itself up the call stack, decrementing the value of the \fB\-level\fR entry at each level, so that the \fIcode\fR will be the return code of the current command \fIlevel\fR levels up the call stack. The \fBsource\fR command performs the same handling of the \fBTCL_RETURN\fR return code, which explains the similarity of \fBreturn\fR invocation during a \fBsource\fR to \fBreturn\fR invocation within a procedure. .PP The return code of the \fBreturn\fR command itself triggers this special handling by procedure invocation. If \fBreturn\fR is provided the option \fB\-level 0\fR, then the return code of the \fBreturn\fR command itself will be the value \fIcode\fR of the \fB\-code\fR option (or \fBTCL_OK\fR by default). Any other value for the \fB\-level\fR option (including the default value of 1) will cause the return code of the \fBreturn\fR command itself to be \fBTCL_RETURN\fR, triggering a return from the enclosing procedure. .SH EXAMPLES .PP First, a simple example of using \fBreturn\fR to return from a procedure, interrupting the procedure body. .PP .CS proc printOneLine {} { puts "line 1" ;# This line will be printed. \fBreturn\fR puts "line 2" ;# This line will not be printed. } .CE .PP Next, an example of using \fBreturn\fR to set the value returned by the procedure. .PP .CS proc returnX {} {\fBreturn\fR X} puts [returnX] ;# prints "X" .CE .PP Next, a more complete example, using \fBreturn -code error\fR to report invalid arguments. .PP .CS proc factorial {n} { if {![string is integer $n] || ($n < 0)} { \fBreturn\fR -code error \e "expected non-negative integer,\e but got \e"$n\e"" } if {$n < 2} { \fBreturn\fR 1 } set m [expr {$n - 1}] set code [catch {factorial $m} factor] if {$code != 0} { \fBreturn\fR -code $code $factor } set product [expr {$n * $factor}] if {$product < 0} { \fBreturn\fR -code error \e "overflow computing factorial of $n" } \fBreturn\fR $product } .CE .PP Next, a procedure replacement for \fBbreak\fR. .PP .CS proc myBreak {} { \fBreturn\fR -code break } .CE .PP With the \fB\-level 0\fR option, \fBreturn\fR itself can serve as a replacement for \fBbreak\fR, with the help of \fBinterp alias\fR. .PP .CS interp alias {} Break {} \fBreturn\fR -level 0 -code break .CE .PP An example of using \fBcatch\fR and \fBreturn -options\fR to re-raise a caught error: .PP .CS proc doSomething {} { set resource [allocate] catch { # Long script of operations # that might raise an error } result options deallocate $resource \fBreturn\fR -options $options $result } .CE .PP Finally an example of advanced use of the \fBreturn\fR options to create a procedure replacement for \fBreturn\fR itself: .PP .CS proc myReturn {args} { set result "" if {[llength $args] % 2} { set result [lindex $args end] set args [lrange $args 0 end-1] } set options [dict merge {-level 1} $args] dict incr options -level \fBreturn\fR -options $options $result } .CE .SH "SEE ALSO" break(n), catch(n), continue(n), dict(n), error(n), errorCode(n), errorInfo(n), proc(n), source(n), throw(n), try(n) .SH KEYWORDS break, catch, continue, error, exception, procedure, result, return .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/DoWhenIdle.30000644000175000017500000000653412663660065014412 0ustar sergeisergei'\" '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-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_DoWhenIdle 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_DoWhenIdle, Tcl_CancelIdleCall \- invoke a procedure when there are no pending events .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_DoWhenIdle\fR(\fIproc, clientData\fR) .sp \fBTcl_CancelIdleCall\fR(\fIproc, clientData\fR) .SH ARGUMENTS .AS Tcl_IdleProc clientData .AP Tcl_IdleProc *proc in Procedure to invoke. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR. .BE .SH DESCRIPTION .PP \fBTcl_DoWhenIdle\fR arranges for \fIproc\fR to be invoked when the application becomes idle. The application is considered to be idle when \fBTcl_DoOneEvent\fR has been called, could not find any events to handle, and is about to go to sleep waiting for an event to occur. At this point all pending \fBTcl_DoWhenIdle\fR handlers are invoked. For each call to \fBTcl_DoWhenIdle\fR there will be a single call to \fIproc\fR; after \fIproc\fR is invoked the handler is automatically removed. \fBTcl_DoWhenIdle\fR is only usable in programs that use \fBTcl_DoOneEvent\fR to dispatch events. .PP \fIProc\fR should have arguments and result that match the type \fBTcl_IdleProc\fR: .PP .CS typedef void \fBTcl_IdleProc\fR( ClientData \fIclientData\fR); .CE .PP The \fIclientData\fR parameter to \fIproc\fR is a copy of the \fIclientData\fR argument given to \fBTcl_DoWhenIdle\fR. Typically, \fIclientData\fR points to a data structure containing application-specific information about what \fIproc\fR should do. .PP \fBTcl_CancelIdleCall\fR may be used to cancel one or more previous calls to \fBTcl_DoWhenIdle\fR: if there is a \fBTcl_DoWhenIdle\fR handler registered for \fIproc\fR and \fIclientData\fR, then it is removed without invoking it. If there is more than one handler on the idle list that refers to \fIproc\fR and \fIclientData\fR, all of the handlers are removed. If no existing handlers match \fIproc\fR and \fIclientData\fR then nothing happens. .PP \fBTcl_DoWhenIdle\fR is most useful in situations where (a) a piece of work will have to be done but (b) it is possible that something will happen in the near future that will change what has to be done or require something different to be done. \fBTcl_DoWhenIdle\fR allows the actual work to be deferred until all pending events have been processed. At this point the exact work to be done will presumably be known and it can be done exactly once. .PP For example, \fBTcl_DoWhenIdle\fR might be used by an editor to defer display updates until all pending commands have been processed. Without this feature, redundant redisplays might occur in some situations, such as the processing of a command file. .SH BUGS .PP At present it is not safe for an idle callback to reschedule itself continuously. This will interact badly with certain features of Tk that attempt to wait for all idle callbacks to complete. If you would like for an idle callback to reschedule itself continuously, it is better to use a timer handler with a zero timeout period. .SH "SEE ALSO" after(n), Tcl_CreateFileHandler(3), Tcl_CreateTimerHandler(3) .SH KEYWORDS callback, defer, idle callback tcl8.6.5/doc/format.n0000644000175000017500000002456212663660065014014 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 format n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME format \- Format a string in the style of sprintf .SH SYNOPSIS \fBformat \fIformatString \fR?\fIarg arg ...\fR? .BE .SH INTRODUCTION .PP This command generates a formatted string in a fashion similar to the ANSI C \fBsprintf\fR procedure. \fIFormatString\fR indicates how to format the result, using \fB%\fR conversion specifiers as in \fBsprintf\fR, and the additional arguments, if any, provide values to be substituted into the result. The return value from \fBformat\fR is the formatted string. .SH "DETAILS ON FORMATTING" .PP The command operates by scanning \fIformatString\fR from left to right. Each character from the format string is appended to the result string unless it is a percent sign. If the character is a \fB%\fR then it is not copied to the result string. Instead, the characters following the \fB%\fR character are treated as a conversion specifier. The conversion specifier controls the conversion of the next successive \fIarg\fR to a particular format and the result is appended to the result string in place of the conversion specifier. If there are multiple conversion specifiers in the format string, then each one controls the conversion of one additional \fIarg\fR. The \fBformat\fR command must be given enough \fIarg\fRs to meet the needs of all of the conversion specifiers in \fIformatString\fR. .PP Each conversion specifier may contain up to six different parts: an XPG3 position specifier, a set of flags, a minimum field width, a precision, a size modifier, and a conversion character. Any of these fields may be omitted except for the conversion character. The fields that are present must appear in the order given above. The paragraphs below discuss each of these fields in turn. .SS "OPTIONAL POSITIONAL SPECIFIER" .PP If the \fB%\fR is followed by a decimal number and a \fB$\fR, as in .QW \fB%2$d\fR , then the value to convert is not taken from the next sequential argument. Instead, it is taken from the argument indicated by the number, where 1 corresponds to the first \fIarg\fR. If the conversion specifier requires multiple arguments because of \fB*\fR characters in the specifier then successive arguments are used, starting with the argument given by the number. This follows the XPG3 conventions for positional specifiers. If there are any positional specifiers in \fIformatString\fR then all of the specifiers must be positional. .SS "OPTIONAL FLAGS" .PP The second portion of a conversion specifier may contain any of the following flag characters, in any order: .TP 10 \fB\-\fR Specifies that the converted argument should be left-justified in its field (numbers are normally right-justified with leading spaces if needed). .TP 10 \fB+\fR Specifies that a number should always be printed with a sign, even if positive. .TP 10 \fIspace\fR Specifies that a space should be added to the beginning of the number if the first character is not a sign. .TP 10 \fB0\fR Specifies that the number should be padded on the left with zeroes instead of spaces. .TP 10 \fB#\fR Requests an alternate output form. For \fBo\fR and \fBO\fR conversions it guarantees that the first digit is always \fB0\fR. For \fBx\fR or \fBX\fR conversions, \fB0x\fR or \fB0X\fR (respectively) will be added to the beginning of the result unless it is zero. For \fBb\fR conversions, \fB0b\fR will be added to the beginning of the result unless it is zero. For all floating-point conversions (\fBe\fR, \fBE\fR, \fBf\fR, \fBg\fR, and \fBG\fR) it guarantees that the result always has a decimal point. For \fBg\fR and \fBG\fR conversions it specifies that trailing zeroes should not be removed. .SS "OPTIONAL FIELD WIDTH" .PP The third portion of a conversion specifier is a decimal number giving a minimum field width for this conversion. It is typically used to make columns line up in tabular printouts. If the converted argument contains fewer characters than the minimum field width then it will be padded so that it is as wide as the minimum field width. Padding normally occurs by adding extra spaces on the left of the converted argument, but the \fB0\fR and \fB\-\fR flags may be used to specify padding with zeroes on the left or with spaces on the right, respectively. If the minimum field width is specified as \fB*\fR rather than a number, then the next argument to the \fBformat\fR command determines the minimum field width; it must be an integer value. .SS "OPTIONAL PRECISION/BOUND" .PP The fourth portion of a conversion specifier is a precision, which consists of a period followed by a number. The number is used in different ways for different conversions. For \fBe\fR, \fBE\fR, and \fBf\fR conversions it specifies the number of digits to appear to the right of the decimal point. For \fBg\fR and \fBG\fR conversions it specifies the total number of digits to appear, including those on both sides of the decimal point (however, trailing zeroes after the decimal point will still be omitted unless the \fB#\fR flag has been specified). For integer conversions, it specifies a minimum number of digits to print (leading zeroes will be added if necessary). For \fBs\fR conversions it specifies the maximum number of characters to be printed; if the string is longer than this then the trailing characters will be dropped. If the precision is specified with \fB*\fR rather than a number then the next argument to the \fBformat\fR command determines the precision; it must be a numeric string. .SS "OPTIONAL SIZE MODIFIER" .PP The fifth part of a conversion specifier is a size modifier, which must be \fBll\fR, \fBh\fR, or \fBl\fR. If it is \fBll\fR it specifies that an integer value is taken without truncation for conversion to a formatted substring. If it is \fBh\fR it specifies that an integer value is truncated to a 16-bit range before converting. This option is rarely useful. If it is \fBl\fR it specifies that the integer value is truncated to the same range as that produced by the \fBwide()\fR function of the \fBexpr\fR command (at least a 64-bit range). If neither \fBh\fR nor \fBl\fR are present, the integer value is truncated to the same range as that produced by the \fBint()\fR function of the \fBexpr\fR command (at least a 32-bit range, but determined by the value of the \fBwordSize\fR element of the \fBtcl_platform\fR array). .SS "MANDATORY CONVERSION TYPE" .PP The last thing in a conversion specifier is an alphabetic character that determines what kind of conversion to perform. The following conversion characters are currently supported: .TP 10 \fBd\fR Convert integer to signed decimal string. .TP 10 \fBu\fR Convert integer to unsigned decimal string. .TP 10 \fBi\fR Convert integer to signed decimal string (equivalent to \fBd\fR). .TP 10 \fBo\fR Convert integer to unsigned octal string. .TP 10 \fBx\fR or \fBX\fR Convert integer to unsigned hexadecimal string, using digits .QW 0123456789abcdef for \fBx\fR and .QW 0123456789ABCDEF for \fBX\fR). .TP 10 \fBb\fR Convert integer to binary string, using digits 0 and 1. .TP 10 \fBc\fR Convert integer to the Unicode character it represents. .TP 10 \fBs\fR No conversion; just insert string. .TP 10 \fBf\fR Convert number to signed decimal string of the form \fIxx.yyy\fR, where the number of \fIy\fR's is determined by the precision (default: 6). If the precision is 0 then no decimal point is output. .TP 10 \fBe\fR or \fBE\fR Convert number to scientific notation in the form \fIx.yyy\fBe\(+-\fIzz\fR, where the number of \fIy\fR's is determined by the precision (default: 6). If the precision is 0 then no decimal point is output. If the \fBE\fR form is used then \fBE\fR is printed instead of \fBe\fR. .TP 10 \fBg\fR or \fBG\fR If the exponent is less than \-4 or greater than or equal to the precision, then convert number as for \fB%e\fR or \fB%E\fR. Otherwise convert as for \fB%f\fR. Trailing zeroes and a trailing decimal point are omitted. .TP 10 \fB%\fR No conversion: just insert \fB%\fR. .SH "DIFFERENCES FROM ANSI SPRINTF" .PP The behavior of the format command is the same as the ANSI C \fBsprintf\fR procedure except for the following differences: .IP [1] Tcl guarantees that it will be working with UNICODE characters. .IP [2] \fB%p\fR and \fB%n\fR specifiers are not supported. .IP [3] For \fB%c\fR conversions the argument must be an integer value, which will then be converted to the corresponding character value. .IP [4] The size modifiers are ignored when formatting floating-point values. The \fBll\fR modifier has no \fBsprintf\fR counterpart. The \fBb\fR specifier has no \fBsprintf\fR counterpart. .SH EXAMPLES .PP Convert the numeric value of a UNICODE character to the character itself: .PP .CS set value 120 set char [\fBformat\fR %c $value] .CE .PP Convert the output of \fBtime\fR into seconds to an accuracy of hundredths of a second: .PP .CS set us [lindex [time $someTclCode] 0] puts [\fBformat\fR "%.2f seconds to execute" [expr {$us / 1e6}]] .CE .PP Create a packed X11 literal color specification: .PP .CS # Each color-component should be in range (0..255) set color [\fBformat\fR "#%02x%02x%02x" $r $g $b] .CE .PP Use XPG3 format codes to allow reordering of fields (a technique that is often used in localized message catalogs; see \fBmsgcat\fR) without reordering the data values passed to \fBformat\fR: .PP .CS set fmt1 "Today, %d shares in %s were bought at $%.2f each" puts [\fBformat\fR $fmt1 123 "Global BigCorp" 19.37] set fmt2 "Bought %2\e$s equity ($%3$.2f x %1\e$d) today" puts [\fBformat\fR $fmt2 123 "Global BigCorp" 19.37] .CE .PP Print a small table of powers of three: .PP .CS # Set up the column widths set w1 5 set w2 10 # Make a nice header (with separator) for the table first set sep +-[string repeat - $w1]-+-[string repeat - $w2]-+ puts $sep puts [\fBformat\fR "| %-*s | %-*s |" $w1 "Index" $w2 "Power"] puts $sep # Print the contents of the table set p 1 for {set i 0} {$i<=20} {incr i} { puts [\fBformat\fR "| %*d | %*ld |" $w1 $i $w2 $p] set p [expr {wide($p) * 3}] } # Finish off by printing the separator again puts $sep .CE .SH "SEE ALSO" scan(n), sprintf(3), string(n) .SH KEYWORDS conversion specifier, format, sprintf, string, substitution '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/TraceVar.30000644000175000017500000004075212663660065014137 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_TraceVar 3 7.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_TraceVar, Tcl_TraceVar2, Tcl_UntraceVar, Tcl_UntraceVar2, Tcl_VarTraceInfo, Tcl_VarTraceInfo2 \- monitor accesses to a variable .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_TraceVar(\fIinterp, varName, flags, proc, clientData\fB)\fR .sp int \fBTcl_TraceVar2(\fIinterp, name1, name2, flags, proc, clientData\fB)\fR .sp \fBTcl_UntraceVar(\fIinterp, varName, flags, proc, clientData\fB)\fR .sp \fBTcl_UntraceVar2(\fIinterp, name1, name2, flags, proc, clientData\fB)\fR .sp ClientData \fBTcl_VarTraceInfo(\fIinterp, varName, flags, proc, prevClientData\fB)\fR .sp ClientData \fBTcl_VarTraceInfo2(\fIinterp, name1, name2, flags, proc, prevClientData\fB)\fR .SH ARGUMENTS .AS Tcl_VarTraceProc prevClientData .AP Tcl_Interp *interp in Interpreter containing variable. .AP "const char" *varName in Name of variable. May refer to a scalar variable, to an array variable with no index, or to an array variable with a parenthesized index. .AP int flags in OR-ed combination of the values \fBTCL_TRACE_READS\fR, \fBTCL_TRACE_WRITES\fR, \fBTCL_TRACE_UNSETS\fR, \fBTCL_TRACE_ARRAY\fR, \fBTCL_GLOBAL_ONLY\fR, \fBTCL_NAMESPACE_ONLY\fR, \fBTCL_TRACE_RESULT_DYNAMIC\fR and \fBTCL_TRACE_RESULT_OBJECT\fR. Not all flags are used by all procedures. See below for more information. .AP Tcl_VarTraceProc *proc in Procedure to invoke whenever one of the traced operations occurs. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR. .AP "const char" *name1 in Name of scalar or array variable (without array index). .AP "const char" *name2 in For a trace on an element of an array, gives the index of the element. For traces on scalar variables or on whole arrays, is NULL. .AP ClientData prevClientData in If non-NULL, gives last value returned by \fBTcl_VarTraceInfo\fR or \fBTcl_VarTraceInfo2\fR, so this call will return information about next trace. If NULL, this call will return information about first trace. .BE .SH DESCRIPTION .PP \fBTcl_TraceVar\fR allows a C procedure to monitor and control access to a Tcl variable, so that the C procedure is invoked whenever the variable is read or written or unset. If the trace is created successfully then \fBTcl_TraceVar\fR returns \fBTCL_OK\fR. If an error occurred (e.g. \fIvarName\fR specifies an element of an array, but the actual variable is not an array) then \fBTCL_ERROR\fR is returned and an error message is left in the interpreter's result. .PP The \fIflags\fR argument to \fBTcl_TraceVar\fR indicates when the trace procedure is to be invoked and provides information for setting up the trace. It consists of an OR-ed combination of any of the following values: .TP \fBTCL_GLOBAL_ONLY\fR Normally, the variable will be looked up at the current level of procedure call; if this bit is set then the variable will be looked up at global level, ignoring any active procedures. .TP \fBTCL_NAMESPACE_ONLY\fR Normally, the variable will be looked up at the current level of procedure call; if this bit is set then the variable will be looked up in the current namespace, ignoring any active procedures. .TP \fBTCL_TRACE_READS\fR Invoke \fIproc\fR whenever an attempt is made to read the variable. .TP \fBTCL_TRACE_WRITES\fR Invoke \fIproc\fR whenever an attempt is made to modify the variable. .TP \fBTCL_TRACE_UNSETS\fR Invoke \fIproc\fR whenever the variable is unset. A variable may be unset either explicitly by an \fBunset\fR command, or implicitly when a procedure returns (its local variables are automatically unset) or when the interpreter is deleted (all variables are automatically unset). .TP \fBTCL_TRACE_ARRAY\fR Invoke \fIproc\fR whenever the array command is invoked. This gives the trace procedure a chance to update the array before array names or array get is called. Note that this is called before an array set, but that will trigger write traces. .TP \fBTCL_TRACE_RESULT_DYNAMIC\fR The result of invoking the \fIproc\fR is a dynamically allocated string that will be released by the Tcl library via a call to \fBckfree\fR. Must not be specified at the same time as \fBTCL_TRACE_RESULT_OBJECT\fR. .TP \fBTCL_TRACE_RESULT_OBJECT\fR The result of invoking the \fIproc\fR is a Tcl_Obj* (cast to a char*) with a reference count of at least one. The ownership of that reference will be transferred to the Tcl core for release (when the core has finished with it) via a call to \fBTcl_DecrRefCount\fR. Must not be specified at the same time as \fBTCL_TRACE_RESULT_DYNAMIC\fR. .PP Whenever one of the specified operations occurs on the variable, \fIproc\fR will be invoked. It should have arguments and result that match the type \fBTcl_VarTraceProc\fR: .PP .CS typedef char *\fBTcl_VarTraceProc\fR( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR, char *\fIname1\fR, char *\fIname2\fR, int \fIflags\fR); .CE .PP The \fIclientData\fR and \fIinterp\fR parameters will have the same values as those passed to \fBTcl_TraceVar\fR when the trace was created. \fIClientData\fR typically points to an application-specific data structure that describes what to do when \fIproc\fR is invoked. \fIName1\fR and \fIname2\fR give the name of the traced variable in the normal two-part form (see the description of \fBTcl_TraceVar2\fR below for details). \fIFlags\fR is an OR-ed combination of bits providing several pieces of information. One of the bits \fBTCL_TRACE_READS\fR, \fBTCL_TRACE_WRITES\fR, \fBTCL_TRACE_ARRAY\fR, or \fBTCL_TRACE_UNSETS\fR will be set in \fIflags\fR to indicate which operation is being performed on the variable. The bit \fBTCL_GLOBAL_ONLY\fR will be set whenever the variable being accessed is a global one not accessible from the current level of procedure call: the trace procedure will need to pass this flag back to variable-related procedures like \fBTcl_GetVar\fR if it attempts to access the variable. The bit \fBTCL_NAMESPACE_ONLY\fR will be set whenever the variable being accessed is a namespace one not accessible from the current level of procedure call: the trace procedure will need to pass this flag back to variable-related procedures like \fBTcl_GetVar\fR if it attempts to access the variable. The bit \fBTCL_TRACE_DESTROYED\fR will be set in \fIflags\fR if the trace is about to be destroyed; this information may be useful to \fIproc\fR so that it can clean up its own internal data structures (see the section \fBTCL_TRACE_DESTROYED\fR below for more details). Lastly, the bit \fBTCL_INTERP_DESTROYED\fR will be set if the entire interpreter is being destroyed. When this bit is set, \fIproc\fR must be especially careful in the things it does (see the section \fBTCL_INTERP_DESTROYED\fR below). The trace procedure's return value should normally be NULL; see \fBERROR RETURNS\fR below for information on other possibilities. .PP \fBTcl_UntraceVar\fR may be used to remove a trace. If the variable specified by \fIinterp\fR, \fIvarName\fR, and \fIflags\fR has a trace set with \fIflags\fR, \fIproc\fR, and \fIclientData\fR, then the corresponding trace is removed. If no such trace exists, then the call to \fBTcl_UntraceVar\fR has no effect. The same bits are valid for \fIflags\fR as for calls to \fBTcl_TraceVar\fR. .PP \fBTcl_VarTraceInfo\fR may be used to retrieve information about traces set on a given variable. The return value from \fBTcl_VarTraceInfo\fR is the \fIclientData\fR associated with a particular trace. The trace must be on the variable specified by the \fIinterp\fR, \fIvarName\fR, and \fIflags\fR arguments (only the \fBTCL_GLOBAL_ONLY\fR and \fBTCL_NAMESPACE_ONLY\fR bits from \fIflags\fR is used; other bits are ignored) and its trace procedure must the same as the \fIproc\fR argument. If the \fIprevClientData\fR argument is NULL then the return value corresponds to the first (most recently created) matching trace, or NULL if there are no matching traces. If the \fIprevClientData\fR argument is not NULL, then it should be the return value from a previous call to \fBTcl_VarTraceInfo\fR. In this case, the new return value will correspond to the next matching trace after the one whose \fIclientData\fR matches \fIprevClientData\fR, or NULL if no trace matches \fIprevClientData\fR or if there are no more matching traces after it. This mechanism makes it possible to step through all of the traces for a given variable that have the same \fIproc\fR. .SH "TWO-PART NAMES" .PP The procedures \fBTcl_TraceVar2\fR, \fBTcl_UntraceVar2\fR, and \fBTcl_VarTraceInfo2\fR are identical to \fBTcl_TraceVar\fR, \fBTcl_UntraceVar\fR, and \fBTcl_VarTraceInfo\fR, respectively, except that the name of the variable consists of two parts. \fIName1\fR gives the name of a scalar variable or array, and \fIname2\fR gives the name of an element within an array. When \fIname2\fR is NULL, \fIname1\fR may contain both an array and an element name: if the name contains an open parenthesis and ends with a close parenthesis, then the value between the parentheses is treated as an element name (which can have any string value) and the characters before the first open parenthesis are treated as the name of an array variable. If \fIname2\fR is NULL and \fIname1\fR does not refer to an array element it means that either the variable is a scalar or the trace is to be set on the entire array rather than an individual element (see WHOLE-ARRAY TRACES below for more information). .SH "ACCESSING VARIABLES DURING TRACES" .PP During read, write, and array traces, the trace procedure can read, write, or unset the traced variable using \fBTcl_GetVar2\fR, \fBTcl_SetVar2\fR, and other procedures. While \fIproc\fR is executing, traces are temporarily disabled for the variable, so that calls to \fBTcl_GetVar2\fR and \fBTcl_SetVar2\fR will not cause \fIproc\fR or other trace procedures to be invoked again. Disabling only occurs for the variable whose trace procedure is active; accesses to other variables will still be traced. However, if a variable is unset during a read or write trace then unset traces will be invoked. .PP During unset traces the variable has already been completely expunged. It is possible for the trace procedure to read or write the variable, but this will be a new version of the variable. Traces are not disabled during unset traces as they are for read and write traces, but existing traces have been removed from the variable before any trace procedures are invoked. If new traces are set by unset trace procedures, these traces will be invoked on accesses to the variable by the trace procedures. .SH "CALLBACK TIMING" .PP When read tracing has been specified for a variable, the trace procedure will be invoked whenever the variable's value is read. This includes \fBset\fR Tcl commands, \fB$\fR-notation in Tcl commands, and invocations of the \fBTcl_GetVar\fR and \fBTcl_GetVar2\fR procedures. \fIProc\fR is invoked just before the variable's value is returned. It may modify the value of the variable to affect what is returned by the traced access. If it unsets the variable then the access will return an error just as if the variable never existed. .PP When write tracing has been specified for a variable, the trace procedure will be invoked whenever the variable's value is modified. This includes \fBset\fR commands, commands that modify variables as side effects (such as \fBcatch\fR and \fBscan\fR), and calls to the \fBTcl_SetVar\fR and \fBTcl_SetVar2\fR procedures). \fIProc\fR will be invoked after the variable's value has been modified, but before the new value of the variable has been returned. It may modify the value of the variable to override the change and to determine the value actually returned by the traced access. If it deletes the variable then the traced access will return an empty string. .PP When array tracing has been specified, the trace procedure will be invoked at the beginning of the array command implementation, before any of the operations like get, set, or names have been invoked. The trace procedure can modify the array elements with \fBTcl_SetVar\fR and \fBTcl_SetVar2\fR. .PP When unset tracing has been specified, the trace procedure will be invoked whenever the variable is destroyed. The traces will be called after the variable has been completely unset. .SH "WHOLE-ARRAY TRACES" .PP If a call to \fBTcl_TraceVar\fR or \fBTcl_TraceVar2\fR specifies the name of an array variable without an index into the array, then the trace will be set on the array as a whole. This means that \fIproc\fR will be invoked whenever any element of the array is accessed in the ways specified by \fIflags\fR. When an array is unset, a whole-array trace will be invoked just once, with \fIname1\fR equal to the name of the array and \fIname2\fR NULL; it will not be invoked once for each element. .SH "MULTIPLE TRACES" .PP It is possible for multiple traces to exist on the same variable. When this happens, all of the trace procedures will be invoked on each access, in order from most-recently-created to least-recently-created. When there exist whole-array traces for an array as well as traces on individual elements, the whole-array traces are invoked before the individual-element traces. If a read or write trace unsets the variable then all of the unset traces will be invoked but the remainder of the read and write traces will be skipped. .SH "ERROR RETURNS" .PP Under normal conditions trace procedures should return NULL, indicating successful completion. If \fIproc\fR returns a non-NULL value it signifies that an error occurred. The return value must be a pointer to a static character string containing an error message, unless (\fIexactly\fR one of) the \fBTCL_TRACE_RESULT_DYNAMIC\fR and \fBTCL_TRACE_RESULT_OBJECT\fR flags is set, which specify that the result is either a dynamic string (to be released with \fBckfree\fR) or a Tcl_Obj* (cast to char* and to be released with \fBTcl_DecrRefCount\fR) containing the error message. If a trace procedure returns an error, no further traces are invoked for the access and the traced access aborts with the given message. Trace procedures can use this facility to make variables read-only, for example (but note that the value of the variable will already have been modified before the trace procedure is called, so the trace procedure will have to restore the correct value). .PP The return value from \fIproc\fR is only used during read and write tracing. During unset traces, the return value is ignored and all relevant trace procedures will always be invoked. .SH "RESTRICTIONS" .PP A trace procedure can be called at any time, even when there is a partially formed result in the interpreter's result area. If the trace procedure does anything that could damage this result (such as calling \fBTcl_Eval\fR) then it must save the original values of the interpreter's \fBresult\fR and \fBfreeProc\fR fields and restore them before it returns. .SH "UNDEFINED VARIABLES" .PP It is legal to set a trace on an undefined variable. The variable will still appear to be undefined until the first time its value is set. If an undefined variable is traced and then unset, the unset will fail with an error .PQ "no such variable" "" , but the trace procedure will still be invoked. .SH "TCL_TRACE_DESTROYED FLAG" .PP In an unset callback to \fIproc\fR, the \fBTCL_TRACE_DESTROYED\fR bit is set in \fIflags\fR if the trace is being removed as part of the deletion. Traces on a variable are always removed whenever the variable is deleted; the only time \fBTCL_TRACE_DESTROYED\fR is not set is for a whole-array trace invoked when only a single element of an array is unset. .SH "TCL_INTERP_DESTROYED" .PP When an interpreter is destroyed, unset traces are called for all of its variables. The \fBTCL_INTERP_DESTROYED\fR bit will be set in the \fIflags\fR argument passed to the trace procedures. Trace procedures must be extremely careful in what they do if the \fBTCL_INTERP_DESTROYED\fR bit is set. It is not safe for the procedures to invoke any Tcl procedures on the interpreter, since its state is partially deleted. All that trace procedures should do under these circumstances is to clean up and free their own internal data structures. .SH BUGS .PP Tcl does not do any error checking to prevent trace procedures from misusing the interpreter during traces with \fBTCL_INTERP_DESTROYED\fR set. .PP Array traces are not yet integrated with the Tcl \fBinfo exists\fR command, nor is there Tcl-level access to array traces. .SH "SEE ALSO" trace(n) .SH KEYWORDS clientData, trace, variable tcl8.6.5/doc/FileSystem.30000644000175000017500000020607312663660065014514 0ustar sergeisergei'\" '\" Copyright (c) 2001 Vincent Darley '\" Copyright (c) 2008-2010 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Filesystem 3 8.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_FSRegister, Tcl_FSUnregister, Tcl_FSData, Tcl_FSMountsChanged, Tcl_FSGetFileSystemForPath, Tcl_FSGetPathType, Tcl_FSCopyFile, Tcl_FSCopyDirectory, Tcl_FSCreateDirectory, Tcl_FSDeleteFile, Tcl_FSRemoveDirectory, Tcl_FSRenameFile, Tcl_FSListVolumes, Tcl_FSEvalFile, Tcl_FSEvalFileEx, Tcl_FSLoadFile, Tcl_FSUnloadFile, Tcl_FSMatchInDirectory, Tcl_FSLink, Tcl_FSLstat, Tcl_FSUtime, Tcl_FSFileAttrsGet, Tcl_FSFileAttrsSet, Tcl_FSFileAttrStrings, Tcl_FSStat, Tcl_FSAccess, Tcl_FSOpenFileChannel, Tcl_FSGetCwd, Tcl_FSChdir, Tcl_FSPathSeparator, Tcl_FSJoinPath, Tcl_FSSplitPath, Tcl_FSEqualPaths, Tcl_FSGetNormalizedPath, Tcl_FSJoinToPath, Tcl_FSConvertToPathType, Tcl_FSGetInternalRep, Tcl_FSGetTranslatedPath, Tcl_FSGetTranslatedStringPath, Tcl_FSNewNativePath, Tcl_FSGetNativePath, Tcl_FSFileSystemInfo, Tcl_GetAccessTimeFromStat, Tcl_GetBlockSizeFromStat, Tcl_GetBlocksFromStat, Tcl_GetChangeTimeFromStat, Tcl_GetDeviceTypeFromStat, Tcl_GetFSDeviceFromStat, Tcl_GetFSInodeFromStat, Tcl_GetGroupIdFromStat, Tcl_GetLinkCountFromStat, Tcl_GetModeFromStat, Tcl_GetModificationTimeFromStat, Tcl_GetSizeFromStat, Tcl_GetUserIdFromStat, Tcl_AllocStatBuf \- procedures to interact with any filesystem .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_FSRegister\fR(\fIclientData, fsPtr\fR) .sp int \fBTcl_FSUnregister\fR(\fIfsPtr\fR) .sp ClientData \fBTcl_FSData\fR(\fIfsPtr\fR) .sp void \fBTcl_FSMountsChanged\fR(\fIfsPtr\fR) .sp const Tcl_Filesystem * \fBTcl_FSGetFileSystemForPath\fR(\fIpathPtr\fR) .sp Tcl_PathType \fBTcl_FSGetPathType\fR(\fIpathPtr\fR) .sp int \fBTcl_FSCopyFile\fR(\fIsrcPathPtr, destPathPtr\fR) .sp int \fBTcl_FSCopyDirectory\fR(\fIsrcPathPtr, destPathPtr, errorPtr\fR) .sp int \fBTcl_FSCreateDirectory\fR(\fIpathPtr\fR) .sp int \fBTcl_FSDeleteFile\fR(\fIpathPtr\fR) .sp int \fBTcl_FSRemoveDirectory\fR(\fIpathPtr, int recursive, errorPtr\fR) .sp int \fBTcl_FSRenameFile\fR(\fIsrcPathPtr, destPathPtr\fR) .sp Tcl_Obj * \fBTcl_FSListVolumes\fR(\fIvoid\fR) .sp int \fBTcl_FSEvalFileEx\fR(\fIinterp, pathPtr, encodingName\fR) .sp int \fBTcl_FSEvalFile\fR(\fIinterp, pathPtr\fR) .sp int \fBTcl_FSLoadFile\fR(\fIinterp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, loadHandlePtr, unloadProcPtr\fR) .sp .VS 8.6 int \fBTcl_FSUnloadFile\fR(\fIinterp, loadHandle\fR) .VE 8.6 .sp int \fBTcl_FSMatchInDirectory\fR(\fIinterp, resultPtr, pathPtr, pattern, types\fR) .sp Tcl_Obj * \fBTcl_FSLink\fR(\fIlinkNamePtr, toPtr, linkAction\fR) .sp int \fBTcl_FSLstat\fR(\fIpathPtr, statPtr\fR) .sp int \fBTcl_FSUtime\fR(\fIpathPtr, tval\fR) .sp int \fBTcl_FSFileAttrsGet\fR(\fIinterp, int index, pathPtr, objPtrRef\fR) .sp int \fBTcl_FSFileAttrsSet\fR(\fIinterp, int index, pathPtr, Tcl_Obj *objPtr\fR) .sp const char *const * \fBTcl_FSFileAttrStrings\fR(\fIpathPtr, objPtrRef\fR) .sp int \fBTcl_FSStat\fR(\fIpathPtr, statPtr\fR) .sp int \fBTcl_FSAccess\fR(\fIpathPtr, mode\fR) .sp Tcl_Channel \fBTcl_FSOpenFileChannel\fR(\fIinterp, pathPtr, modeString, permissions\fR) .sp Tcl_Obj * \fBTcl_FSGetCwd\fR(\fIinterp\fR) .sp int \fBTcl_FSChdir\fR(\fIpathPtr\fR) .sp Tcl_Obj * \fBTcl_FSPathSeparator\fR(\fIpathPtr\fR) .sp Tcl_Obj * \fBTcl_FSJoinPath\fR(\fIlistObj, elements\fR) .sp Tcl_Obj * \fBTcl_FSSplitPath\fR(\fIpathPtr, lenPtr\fR) .sp int \fBTcl_FSEqualPaths\fR(\fIfirstPtr, secondPtr\fR) .sp Tcl_Obj * \fBTcl_FSGetNormalizedPath\fR(\fIinterp, pathPtr\fR) .sp Tcl_Obj * \fBTcl_FSJoinToPath\fR(\fIbasePtr, objc, objv\fR) .sp int \fBTcl_FSConvertToPathType\fR(\fIinterp, pathPtr\fR) .sp ClientData \fBTcl_FSGetInternalRep\fR(\fIpathPtr, fsPtr\fR) .sp Tcl_Obj * \fBTcl_FSGetTranslatedPath\fR(\fIinterp, pathPtr\fR) .sp const char * \fBTcl_FSGetTranslatedStringPath\fR(\fIinterp, pathPtr\fR) .sp Tcl_Obj * \fBTcl_FSNewNativePath\fR(\fIfsPtr, clientData\fR) .sp const void * \fBTcl_FSGetNativePath\fR(\fIpathPtr\fR) .sp Tcl_Obj * \fBTcl_FSFileSystemInfo\fR(\fIpathPtr\fR) .sp Tcl_StatBuf * \fBTcl_AllocStatBuf\fR() .sp .VS 8.6 Tcl_WideInt \fBTcl_GetAccessTimeFromStat\fR(\fIstatPtr\fR) .sp unsigned \fBTcl_GetBlockSizeFromStat\fR(\fIstatPtr\fR) .sp Tcl_WideUInt \fBTcl_GetBlocksFromStat\fR(\fIstatPtr\fR) .sp Tcl_WideInt \fBTcl_GetChangeTimeFromStat\fR(\fIstatPtr\fR) .sp int \fBTcl_GetDeviceTypeFromStat\fR(\fIstatPtr\fR) .sp unsigned \fBTcl_GetFSDeviceFromStat\fR(\fIstatPtr\fR) .sp unsigned \fBTcl_GetFSInodeFromStat\fR(\fIstatPtr\fR) .sp int \fBTcl_GetGroupIdFromStat\fR(\fIstatPtr\fR) .sp int \fBTcl_GetLinkCountFromStat\fR(\fIstatPtr\fR) .sp unsigned \fBTcl_GetModeFromStat\fR(\fIstatPtr\fR) .sp Tcl_WideInt \fBTcl_GetModificationTimeFromStat\fR(\fIstatPtr\fR) .sp Tcl_WideUInt \fBTcl_GetSizeFromStat\fR(\fIstatPtr\fR) .sp int \fBTcl_GetUserIdFromStat\fR(\fIstatPtr\fR) .VE 8.6 .SH ARGUMENTS .AS Tcl_GlobTypeData **srcPathPtr out .AP "const Tcl_Filesystem" *fsPtr in Points to a structure containing the addresses of procedures that can be called to perform the various filesystem operations. .AP Tcl_Obj *pathPtr in The path represented by this value is used for the operation in question. If the value does not already have an internal \fBpath\fR representation, it will be converted to have one. .AP Tcl_Obj *srcPathPtr in As for \fIpathPtr\fR, but used for the source file for a copy or rename operation. .AP Tcl_Obj *destPathPtr in As for \fIpathPtr\fR, but used for the destination filename for a copy or rename operation. .AP "const char" *encodingName in The encoding of the data stored in the file identified by \fIpathPtr\fR and to be evaluated. .AP "const char" *pattern in Only files or directories matching this pattern will be returned. .AP Tcl_GlobTypeData *types in Only files or directories matching the type descriptions contained in this structure will be returned. This parameter may be NULL. .AP Tcl_Interp *interp in Interpreter to use either for results, evaluation, or reporting error messages. .AP ClientData clientData in The native description of the path value to create. .AP Tcl_Obj *firstPtr in The first of two path values to compare. The value may be converted to \fBpath\fR type. .AP Tcl_Obj *secondPtr in The second of two path values to compare. The value may be converted to \fBpath\fR type. .AP Tcl_Obj *listObj in The list of path elements to operate on with a \fBjoin\fR operation. .AP int elements in If non-negative, the number of elements in the \fIlistObj\fR which should be joined together. If negative, then all elements are joined. .AP Tcl_Obj **errorPtr out In the case of an error, filled with a value containing the name of the file which caused an error in the various copy/rename operations. .AP Tcl_Obj **objPtrRef out Filled with a value containing the result of the operation. .AP Tcl_Obj *resultPtr out Pre-allocated value in which to store (using \fBTcl_ListObjAppendElement\fR) the list of files or directories which are successfully matched. .AP int mode in Mask consisting of one or more of R_OK, W_OK, X_OK and F_OK. R_OK, W_OK and X_OK request checking whether the file exists and has read, write and execute permissions, respectively. F_OK just requests checking for the existence of the file. .AP Tcl_StatBuf *statPtr out The structure that contains the result of a stat or lstat operation. .AP "const char" *sym1 in 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 Filled with the init function for this code. .AP Tcl_PackageInitProc **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 function when it is called. .AP Tcl_LoadHandle *loadHandlePtr out Filled with an abstract token representing the loaded file. .AP Tcl_FSUnloadFileProc **unloadProcPtr out Filled with the function to use to unload this piece of code. .AP Tcl_LoadHandle loadHandle in Handle to the loaded library to be unloaded. .AP utimbuf *tval in The access and modification times in this structure are read and used to set those values for a given file. .AP "const char" *modeString in Specifies how the file is to be accessed. May have any of the values allowed for the \fImode\fR argument to the Tcl \fBopen\fR command. .AP int permissions in POSIX-style permission flags such as 0644. If a new file is created, these permissions will be set on the created file. .AP int *lenPtr out If non-NULL, filled with the number of elements in the split path. .AP Tcl_Obj *basePtr in The base path on to which to join the given elements. May be NULL. .AP int objc in The number of elements in \fIobjv\fR. .AP "Tcl_Obj *const" objv[] in The elements to join to the given base path. .AP Tcl_Obj *linkNamePtr in The name of the link to be created or read. .AP Tcl_Obj *toPtr in What the link called \fIlinkNamePtr\fR should be linked to, or NULL if the symbolic link specified by \fIlinkNamePtr\fR is to be read. .AP int linkAction in OR-ed combination of flags indicating what kind of link should be created (will be ignored if \fItoPtr\fR is NULL). Valid bits to set are \fBTCL_CREATE_SYMBOLIC_LINK\fR and \fBTCL_CREATE_HARD_LINK\fR. When both flags are set and the underlying filesystem can do either, symbolic links are preferred. .BE .SH DESCRIPTION .PP There are several reasons for calling the \fBTcl_FS\fR API functions (e.g.\ \fBTcl_FSAccess\fR and \fBTcl_FSStat\fR) rather than calling system level functions like \fBaccess\fR and \fBstat\fR directly. First, they will work cross-platform, so an extension which calls them should work unmodified on Unix and Windows. Second, the Windows implementation of some of these functions fixes some bugs in the system level calls. Third, these function calls deal with any .QW "Utf to platform-native" path conversions which may be required (and may cache the results of such conversions for greater efficiency on subsequent calls). Fourth, and perhaps most importantly, all of these functions are .QW "virtual filesystem aware" . Any virtual filesystem (VFS for short) which has been registered (through \fBTcl_FSRegister\fR) may reroute file access to alternative media or access methods. This means that all of these functions (and therefore the corresponding \fBfile\fR, \fBglob\fR, \fBpwd\fR, \fBcd\fR, \fBopen\fR, etc.\ Tcl commands) may be operate on .QW files which are not native files in the native filesystem. This also means that any Tcl extension which accesses the filesystem (FS for short) through this API is automatically .QW "virtual filesystem aware" . Of course, if an extension accesses the native filesystem directly (through platform-specific APIs, for example), then Tcl cannot intercept such calls. .PP If appropriate VFSes have been registered, the .QW files may, to give two examples, be remote (e.g.\ situated on a remote ftp server) or archived (e.g.\ lying inside a .zip archive). Such registered filesystems provide a lookup table of functions to implement all or some of the functionality listed here. Finally, the \fBTcl_FSStat\fR and \fBTcl_FSLstat\fR calls abstract away from what the .QW "struct stat" buffer is actually declared to be, allowing the same code to be used both on systems with and systems without support for files larger than 2GB in size. .PP The \fBTcl_FS\fR API is \fBTcl_Obj\fR-ified and may cache internal representations and other path-related strings (e.g.\ the current working directory). One side-effect of this is that one must not pass in values with a reference count of zero to any of these functions. If such calls were handled, they might result in memory leaks (under some circumstances, the filesystem code may wish to retain a reference to the passed in value, and so one must not assume that after any of these calls return, the value still has a reference count of zero - it may have been incremented) or in a direct segmentation fault (or other memory access error) due to the value being freed part way through the complex value manipulation required to ensure that the path is fully normalized and absolute for filesystem determination. The practical lesson to learn from this is that .PP .CS Tcl_Obj *path = Tcl_NewStringObj(...); Tcl_FS\fIWhatever\fR(path); Tcl_DecrRefCount(path); .CE .PP is wrong, and may cause memory errors. The \fIpath\fR must have its reference count incremented before passing it in, or decrementing it. For this reason, values with a reference count of zero are considered not to be valid filesystem paths and calling any Tcl_FS API function with such a value will result in no action being taken. .SS "FS API FUNCTIONS" \fBTcl_FSCopyFile\fR attempts to copy the file given by \fIsrcPathPtr\fR to the path name given by \fIdestPathPtr\fR. If the two paths given lie in the same filesystem (according to \fBTcl_FSGetFileSystemForPath\fR) then that filesystem's .QW "copy file" function is called (if it is non-NULL). Otherwise the function returns -1 and sets the \fBerrno\fR global C variable to the .QW EXDEV POSIX error code (which signifies a .QW "cross-domain link" ). .PP \fBTcl_FSCopyDirectory\fR attempts to copy the directory given by \fIsrcPathPtr\fR to the path name given by \fIdestPathPtr\fR. If the two paths given lie in the same filesystem (according to \fBTcl_FSGetFileSystemForPath\fR) then that filesystem's .QW "copy file" function is called (if it is non-NULL). Otherwise the function returns -1 and sets the \fBerrno\fR global C variable to the .QW EXDEV POSIX error code (which signifies a .QW "cross-domain link" ). .PP \fBTcl_FSCreateDirectory\fR attempts to create the directory given by \fIpathPtr\fR by calling the owning filesystem's .QW "create directory" function. .PP \fBTcl_FSDeleteFile\fR attempts to delete the file given by \fIpathPtr\fR by calling the owning filesystem's .QW "delete file" function. .PP \fBTcl_FSRemoveDirectory\fR attempts to remove the directory given by \fIpathPtr\fR by calling the owning filesystem's .QW "remove directory" function. .PP \fBTcl_FSRenameFile\fR attempts to rename the file or directory given by \fIsrcPathPtr\fR to the path name given by \fIdestPathPtr\fR. If the two paths given lie in the same filesystem (according to \fBTcl_FSGetFileSystemForPath\fR) then that filesystem's .QW "rename file" function is called (if it is non-NULL). Otherwise the function returns -1 and sets the \fBerrno\fR global C variable to the .QW EXDEV POSIX error code (which signifies a .QW "cross-domain link" ). .PP \fBTcl_FSListVolumes\fR calls each filesystem which has a non-NULL .QW "list volumes" function and asks them to return their list of root volumes. It accumulates the return values in a list which is returned to the caller (with a reference count of 0). .PP \fBTcl_FSEvalFileEx\fR reads the file given by \fIpathPtr\fR using the encoding identified by \fIencodingName\fR and evaluates its contents as a Tcl script. It returns the same information as \fBTcl_EvalObjEx\fR. If \fIencodingName\fR is NULL, the system encoding is used for reading the file contents. If the file could not be read then a Tcl error is returned to describe why the file could not be read. The eofchar for files is .QW \e32 (^Z) for all platforms. If you require a .QW ^Z in code for string comparison, you can use .QW \e032 or .QW \eu001a , which will be safely substituted by the Tcl interpreter into .QW ^Z . \fBTcl_FSEvalFile\fR is a simpler version of \fBTcl_FSEvalFileEx\fR that always uses the system encoding when reading the file. .PP \fBTcl_FSLoadFile\fR dynamically loads a binary code file into memory and returns the addresses of two procedures within that file, if they are defined. The appropriate function for the filesystem to which \fIpathPtr\fR belongs will be called. If that filesystem does not implement this function (most virtual filesystems will not, because of OS limitations in dynamically loading binary code), Tcl will attempt to copy the file to a temporary directory and load that temporary file. .VS 8.6 \fBTcl_FSUnloadFile\fR reverses the operation, asking for the library indicated by the \fIloadHandle\fR to be removed from the process. Note that, unlike with the \fBunload\fR command, this does not give the library any opportunity to clean up. .VE 8.6 .PP Both the above functions return a standard Tcl completion code. If an error occurs, an error message is left in the \fIinterp\fR's result. .PP .VS 8.6 The token provided via the variable indicated by \fIloadHandlePtr\fR may be used with \fBTcl_FindSymbol\fR. .VE 8.6 .PP \fBTcl_FSMatchInDirectory\fR is used by the globbing code to search a directory for all files which match a given pattern. The appropriate function for the filesystem to which \fIpathPtr\fR belongs will be called. .PP The return value is a standard Tcl result indicating whether an error occurred in globbing. Error messages are placed in interp (unless interp is NULL, which is allowed), but good results are placed in the resultPtr given. .PP Note that the \fBglob\fR code implements recursive patterns internally, so this function will only ever be passed simple patterns, which can be matched using the logic of \fBstring match\fR. To handle recursion, Tcl will call this function frequently asking only for directories to be returned. A special case of being called with a NULL pattern indicates that the path needs to be checked only for the correct type. .PP \fBTcl_FSLink\fR replaces the library version of \fBreadlink\fR, and extends it to support the creation of links. The appropriate function for the filesystem to which \fIlinkNamePtr\fR belongs will be called. .PP If the \fItoPtr\fR is NULL, a .QW "read link" action is performed. The result is a Tcl_Obj specifying the contents of the symbolic link given by \fIlinkNamePtr\fR, or NULL if the link could not be read. The result is owned by the caller, which should call \fBTcl_DecrRefCount\fR when the result is no longer needed. If the \fItoPtr\fR is not NULL, Tcl should create a link of one of the types passed in in the \fIlinkAction\fR flag. This flag is an ORed combination of \fBTCL_CREATE_SYMBOLIC_LINK\fR and \fBTCL_CREATE_HARD_LINK\fR. Where a choice exists (i.e.\ more than one flag is passed in), the Tcl convention is to prefer symbolic links. When a link is successfully created, the return value should be \fItoPtr\fR (which is therefore already owned by the caller). If unsuccessful, NULL is returned. .PP \fBTcl_FSLstat\fR fills the \fITcl_StatBuf\fR structure \fIstatPtr\fR with information about the specified file. You do not need any access rights to the file to get this information but you need search rights to all directories named in the path leading to the file. The \fITcl_StatBuf\fR structure includes info regarding device, inode (always 0 on Windows), privilege mode, nlink (always 1 on Windows), user id (always 0 on Windows), group id (always 0 on Windows), rdev (same as device on Windows), size, last access time, last modification time, and last metadata change time. See \fBPORTABLE STAT RESULT API\fR for a description of how to write portable code to allocate and access the \fITcl_StatBuf\fR structure. .PP If \fIpath\fR exists, \fBTcl_FSLstat\fR returns 0 and the stat structure is filled with data. Otherwise, -1 is returned, and no stat info is given. .PP \fBTcl_FSUtime\fR replaces the library version of utime. .PP This returns 0 on success and -1 on error (as per the \fButime\fR documentation). If successful, the function will update the .QW atime and .QW mtime values of the file given. .PP \fBTcl_FSFileAttrsGet\fR implements read access for the hookable \fBfile attributes\fR subcommand. The appropriate function for the filesystem to which \fIpathPtr\fR belongs will be called. .PP If the result is \fBTCL_OK\fR, then a value was placed in \fIobjPtrRef\fR, which will only be temporarily valid (unless \fBTcl_IncrRefCount\fR is called). .PP \fBTcl_FSFileAttrsSet\fR implements write access for the hookable \fBfile attributes\fR subcommand. The appropriate function for the filesystem to which \fIpathPtr\fR belongs will be called. .PP \fBTcl_FSFileAttrStrings\fR implements part of the hookable \fBfile attributes\fR subcommand. The appropriate function for the filesystem to which \fIpathPtr\fR belongs will be called. .PP The called procedure may either return an array of strings, or may instead return NULL and place a Tcl list into the given \fIobjPtrRef\fR. Tcl will take that list and first increment its reference count before using it. On completion of that use, Tcl will decrement its reference count. Hence if the list should be disposed of by Tcl when done, it should have a reference count of zero, and if the list should not be disposed of, the filesystem should ensure it retains a reference count to the value. .PP \fBTcl_FSAccess\fR checks whether the process would be allowed to read, write or test for existence of the file (or other filesystem object) whose name is \fIpathname\fR. If \fIpathname\fR is a symbolic link on Unix, then permissions of the file referred by this symbolic link are tested. .PP On success (all requested permissions granted), zero is returned. On error (at least one bit in mode asked for a permission that is denied, or some other error occurred), -1 is returned. .PP \fBTcl_FSStat\fR fills the \fITcl_StatBuf\fR structure \fIstatPtr\fR with information about the specified file. You do not need any access rights to the file to get this information but you need search rights to all directories named in the path leading to the file. The \fITcl_StatBuf\fR structure includes info regarding device, inode (always 0 on Windows), privilege mode, nlink (always 1 on Windows), user id (always 0 on Windows), group id (always 0 on Windows), rdev (same as device on Windows), size, last access time, last modification time, and last metadata change time. See \fBPORTABLE STAT RESULT API\fR for a description of how to write portable code to allocate and access the \fITcl_StatBuf\fR structure. .PP If \fIpath\fR exists, \fBTcl_FSStat\fR returns 0 and the stat structure is filled with data. Otherwise, -1 is returned, and no stat info is given. .PP \fBTcl_FSOpenFileChannel\fR opens a file specified by \fIpathPtr\fR and returns a channel handle that can be used to perform input and output on the file. This API is modeled after the \fBfopen\fR procedure of the Unix standard I/O library. The syntax and meaning of all arguments is similar to those given in the Tcl \fBopen\fR command when opening a file. If an error occurs while opening the channel, \fBTcl_FSOpenFileChannel\fR returns NULL and records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. In addition, if \fIinterp\fR is non-NULL, \fBTcl_FSOpenFileChannel\fR leaves an error message in \fIinterp\fR's result after any error. .PP The newly created channel is not registered in the supplied interpreter; to register it, use \fBTcl_RegisterChannel\fR. If one of the standard channels, \fBstdin\fR, \fBstdout\fR or \fBstderr\fR was previously closed, the act of creating the new channel also assigns it as a replacement for the standard channel. .PP \fBTcl_FSGetCwd\fR replaces the library version of \fBgetcwd\fR. .PP It returns the Tcl library's current working directory. This may be different to the native platform's working directory, which happens when the current working directory is not in the native filesystem. .PP The result is a pointer to a Tcl_Obj specifying the current directory, or NULL if the current directory could not be determined. If NULL is returned, an error message is left in the \fIinterp\fR's result. .PP The result already has its reference count incremented for the caller. When it is no longer needed, that reference count should be decremented. This is needed for thread-safety purposes, to allow multiple threads to access this and related functions, while ensuring the results are always valid. .PP \fBTcl_FSChdir\fR replaces the library version of \fBchdir\fR. The path is normalized and then passed to the filesystem which claims it. If that filesystem does not implement this function, Tcl will fallback to a combination of \fBstat\fR and \fBaccess\fR to check whether the directory exists and has appropriate permissions. .PP For results, see \fBchdir\fR documentation. If successful, we keep a record of the successful path in \fIcwdPathPtr\fR for subsequent calls to \fBTcl_FSGetCwd\fR. .PP \fBTcl_FSPathSeparator\fR returns the separator character to be used for most specific element of the path specified by \fIpathPtr\fR (i.e.\ the last part of the path). .PP The separator is returned as a Tcl_Obj containing a string of length 1. If the path is invalid, NULL is returned. .PP \fBTcl_FSJoinPath\fR takes the given Tcl_Obj, which must be a valid list (which is allowed to have a reference count of zero), and returns the path value given by considering the first \fIelements\fR elements as valid path segments (each path segment may be a complete path, a partial path or just a single possible directory or file name). If any path segment is actually an absolute path, then all prior path segments are discarded. If \fIelements\fR is less than 0, we use the entire list. .PP It is possible that the returned value is actually an element of the given list, so the caller should be careful to increment the reference count of the result before freeing the list. .PP The returned value, typically with a reference count of zero (but it could be shared under some conditions), contains the joined path. The caller must add a reference count to the value before using it. In particular, the returned value could be an element of the given list, so freeing the list might free the value prematurely if no reference count has been taken. If the number of elements is zero, then the returned value will be an empty-string Tcl_Obj. .PP \fBTcl_FSSplitPath\fR takes the given Tcl_Obj, which should be a valid path, and returns a Tcl list value containing each segment of that path as an element. It returns a list value with a reference count of zero. If the passed in \fIlenPtr\fR is non-NULL, the variable it points to will be updated to contain the number of elements in the returned list. .PP \fBTcl_FSEqualPaths\fR tests whether the two paths given represent the same filesystem object. It returns 1 if the paths are equal, and 0 if they are different. If either path is NULL, 0 is always returned. .PP \fBTcl_FSGetNormalizedPath\fR this important function attempts to extract from the given Tcl_Obj a unique normalized path representation, whose string value can be used as a unique identifier for the file. .PP It returns the normalized path value, owned by Tcl, or NULL if the path was invalid or could otherwise not be successfully converted. Extraction of absolute, normalized paths is very efficient (because the filesystem operates on these representations internally), although the result when the filesystem contains numerous symbolic links may not be the most user-friendly version of a path. The return value is owned by Tcl and has a lifetime equivalent to that of the \fIpathPtr\fR passed in (unless that is a relative path, in which case the normalized path value may be freed any time the cwd changes) - the caller can of course increment the reference count if it wishes to maintain a copy for longer. .PP \fBTcl_FSJoinToPath\fR takes the given value, which should usually be a valid path or NULL, and joins onto it the array of paths segments given. .PP Returns a value, typically with reference count of zero (but it could be shared under some conditions), containing the joined path. The caller must add a reference count to the value before using it. If any of the values passed into this function (\fIpathPtr\fR or \fIpath\fR elements) have a reference count of zero, they will be freed when this function returns. .PP \fBTcl_FSConvertToPathType\fR tries to convert the given Tcl_Obj to a valid Tcl path type, taking account of the fact that the cwd may have changed even if this value is already supposedly of the correct type. The filename may begin with .QW ~ (to indicate current user's home directory) or .QW ~ (to indicate any user's home directory). .PP If the conversion succeeds (i.e.\ the value is a valid path in one of the current filesystems), then \fBTCL_OK\fR is returned. Otherwise \fBTCL_ERROR\fR is returned, and an error message may be left in the interpreter. .PP \fBTcl_FSGetInternalRep\fR extracts the internal representation of a given path value, in the given filesystem. If the path value belongs to a different filesystem, we return NULL. If the internal representation is currently NULL, we attempt to generate it, by calling the filesystem's \fBTcl_FSCreateInternalRepProc\fR. .PP Returns NULL or a valid internal path representation. This internal representation is cached, so that repeated calls to this function will not require additional conversions. .PP \fBTcl_FSGetTranslatedPath\fR attempts to extract the translated path from the given Tcl_Obj. .PP If the translation succeeds (i.e.\ the value is a valid path), then it is returned. Otherwise NULL will be returned, and an error message may be left in the interpreter. A .QW translated path is one which contains no .QW ~ or .QW ~user sequences (these have been expanded to their current representation in the filesystem). The value returned is owned by the caller, which must store it or call \fBTcl_DecrRefCount\fR to ensure memory is freed. This function is of little practical use, and \fBTcl_FSGetNormalizedPath\fR or \fBTcl_FSGetNativePath\fR are usually better functions to use for most purposes. .PP \fBTcl_FSGetTranslatedStringPath\fR does the same as \fBTcl_FSGetTranslatedPath\fR, but returns a character string or NULL. The string returned is dynamically allocated and owned by the caller, which must store it or call \fBckfree\fR to ensure it is freed. Again, \fBTcl_FSGetNormalizedPath\fR or \fBTcl_FSGetNativePath\fR are usually better functions to use for most purposes. .PP \fBTcl_FSNewNativePath\fR performs something like the reverse of the usual obj->path->nativerep conversions. If some code retrieves a path in native form (from, e.g.\ \fBreadlink\fR or a native dialog), and that path is to be used at the Tcl level, then calling this function is an efficient way of creating the appropriate path value type. .PP The resulting value is a pure .QW path value, which will only receive a UTF-8 string representation if that is required by some Tcl code. .PP \fBTcl_FSGetNativePath\fR is for use by the Win/Unix native filesystems, so that they can easily retrieve the native (char* or TCHAR*) representation of a path. This function is a convenience wrapper around \fBTcl_FSGetInternalRep\fR. It may be desirable in the future to have non-string-based native representations (for example, on MacOSX, a representation using a fileSpec of FSRef structure would probably be more efficient). On Windows a full Unicode representation would allow for paths of unlimited length. Currently the representation is simply a character string which may contain either the relative path or a complete, absolute normalized path in the native encoding (complex conditions dictate which of these will be provided, so neither can be relied upon, unless the path is known to be absolute). If you need a native path which must be absolute, then you should ask for the native version of a normalized path. If for some reason a non-absolute, non-normalized version of the path is needed, that must be constructed separately (e.g.\ using \fBTcl_FSGetTranslatedPath\fR). .PP The native representation is cached so that repeated calls to this function will not require additional conversions. The return value is owned by Tcl and has a lifetime equivalent to that of the \fIpathPtr\fR passed in (unless that is a relative path, in which case the native representation may be freed any time the cwd changes). .PP \fBTcl_FSFileSystemInfo\fR returns a list of two elements. The first element is the name of the filesystem (e.g. .QW native , .QW vfs , .QW zip , or .QW prowrap , perhaps), and the second is the particular type of the given path within that filesystem (which is filesystem dependent). The second element may be empty if the filesystem does not provide a further categorization of files. .PP A valid list value is returned, unless the path value is not recognized, when NULL will be returned. .PP \fBTcl_FSGetFileSystemForPath\fR returns a pointer to the \fBTcl_Filesystem\fR which accepts this path as valid. .PP If no filesystem will accept the path, NULL is returned. .PP \fBTcl_FSGetPathType\fR determines whether the given path is relative to the current directory, relative to the current volume, or absolute. .PP It returns one of \fBTCL_PATH_ABSOLUTE\fR, \fBTCL_PATH_RELATIVE\fR, or \fBTCL_PATH_VOLUME_RELATIVE\fR .SS "PORTABLE STAT RESULT API" .PP \fBTcl_AllocStatBuf\fR allocates a \fITcl_StatBuf\fR on the system heap (which may be deallocated by being passed to \fBckfree\fR). This allows extensions to invoke \fBTcl_FSStat\fR and \fBTcl_FSLstat\fR without being dependent on the size of the buffer. That in turn depends on the flags used to build Tcl. .PP .VS 8.6 The portable fields of a \fITcl_StatBuf\fR may be read using the following functions, each of which returns the value of the corresponding field listed in the table below. Note that on some platforms there may be other fields in the \fITcl_StatBuf\fR as it is an alias for a suitable system structure, but only the portable ones are made available here. See your system documentation for a full description of these fields. .DS .ta \w'\fBTcl_GetModificationTimeFromStat\fR\0\0\0\0'u \fIAccess Function\fR \fIField\fR \fBTcl_GetFSDeviceFromStat\fR st_dev \fBTcl_GetFSInodeFromStat\fR st_ino \fBTcl_GetModeFromStat\fR st_mode \fBTcl_GetLinkCountFromStat\fR st_nlink \fBTcl_GetUserIdFromStat\fR st_uid \fBTcl_GetGroupIdFromStat\fR st_gid \fBTcl_GetDeviceTypeFromStat\fR st_rdev \fBTcl_GetAccessTimeFromStat\fR st_atime \fBTcl_GetModificationTimeFromStat\fR st_mtime \fBTcl_GetChangeTimeFromStat\fR st_ctime \fBTcl_GetSizeFromStat\fR st_size \fBTcl_GetBlocksFromStat\fR st_blocks \fBTcl_GetBlockSizeFromStat\fR st_blksize .DE .VE 8.6 .SH "THE VIRTUAL FILESYSTEM API" .PP A filesystem provides a \fBTcl_Filesystem\fR structure that contains pointers to functions that implement the various operations on a filesystem; these operations are invoked as needed by the generic layer, which generally occurs through the functions listed above. .PP The \fBTcl_Filesystem\fR structures are manipulated using the following methods. .PP \fBTcl_FSRegister\fR takes a pointer to a filesystem structure and an optional piece of data to associated with that filesystem. On calling this function, Tcl will attach the filesystem to the list of known filesystems, and it will become fully functional immediately. Tcl does not check if the same filesystem is registered multiple times (and in general that is not a good thing to do). \fBTCL_OK\fR will be returned. .PP \fBTcl_FSUnregister\fR removes the given filesystem structure from the list of known filesystems, if it is known, and returns \fBTCL_OK\fR. If the filesystem is not currently registered, \fBTCL_ERROR\fR is returned. .PP \fBTcl_FSData\fR will return the ClientData associated with the given filesystem, if that filesystem is registered. Otherwise it will return NULL. .PP \fBTcl_FSMountsChanged\fR is used to inform the Tcl's core that the set of mount points for the given (already registered) filesystem have changed, and that cached file representations may therefore no longer be correct. .SS "THE TCL_FILESYSTEM STRUCTURE" .PP The \fBTcl_Filesystem\fR structure contains the following fields: .PP .CS typedef struct Tcl_Filesystem { const char *\fItypeName\fR; int \fIstructureLength\fR; Tcl_FSVersion \fIversion\fR; Tcl_FSPathInFilesystemProc *\fIpathInFilesystemProc\fR; Tcl_FSDupInternalRepProc *\fIdupInternalRepProc\fR; Tcl_FSFreeInternalRepProc *\fIfreeInternalRepProc\fR; Tcl_FSInternalToNormalizedProc *\fIinternalToNormalizedProc\fR; Tcl_FSCreateInternalRepProc *\fIcreateInternalRepProc\fR; Tcl_FSNormalizePathProc *\fInormalizePathProc\fR; Tcl_FSFilesystemPathTypeProc *\fIfilesystemPathTypeProc\fR; Tcl_FSFilesystemSeparatorProc *\fIfilesystemSeparatorProc\fR; Tcl_FSStatProc *\fIstatProc\fR; Tcl_FSAccessProc *\fIaccessProc\fR; Tcl_FSOpenFileChannelProc *\fIopenFileChannelProc\fR; Tcl_FSMatchInDirectoryProc *\fImatchInDirectoryProc\fR; Tcl_FSUtimeProc *\fIutimeProc\fR; Tcl_FSLinkProc *\fIlinkProc\fR; Tcl_FSListVolumesProc *\fIlistVolumesProc\fR; Tcl_FSFileAttrStringsProc *\fIfileAttrStringsProc\fR; Tcl_FSFileAttrsGetProc *\fIfileAttrsGetProc\fR; Tcl_FSFileAttrsSetProc *\fIfileAttrsSetProc\fR; Tcl_FSCreateDirectoryProc *\fIcreateDirectoryProc\fR; Tcl_FSRemoveDirectoryProc *\fIremoveDirectoryProc\fR; Tcl_FSDeleteFileProc *\fIdeleteFileProc\fR; Tcl_FSCopyFileProc *\fIcopyFileProc\fR; Tcl_FSRenameFileProc *\fIrenameFileProc\fR; Tcl_FSCopyDirectoryProc *\fIcopyDirectoryProc\fR; Tcl_FSLstatProc *\fIlstatProc\fR; Tcl_FSLoadFileProc *\fIloadFileProc\fR; Tcl_FSGetCwdProc *\fIgetCwdProc\fR; Tcl_FSChdirProc *\fIchdirProc\fR; } \fBTcl_Filesystem\fR; .CE .PP Except for the first three fields in this structure which contain simple data elements, all entries contain addresses of functions called by the generic filesystem layer to perform the complete range of filesystem related actions. .PP The many functions in this structure are broken down into three categories: infrastructure functions (almost all of which must be implemented), operational functions (which must be implemented if a complete filesystem is provided), and efficiency functions (which need only be implemented if they can be done so efficiently, or if they have side-effects which are required by the filesystem; Tcl has less efficient emulations it can fall back on). It is important to note that, in the current version of Tcl, most of these fallbacks are only used to handle commands initiated in Tcl, not in C. What this means is, that if a \fBfile rename\fR command is issued in Tcl, and the relevant filesystem(s) do not implement their \fITcl_FSRenameFileProc\fR, Tcl's core will instead fallback on a combination of other filesystem functions (it will use \fITcl_FSCopyFileProc\fR followed by \fITcl_FSDeleteFileProc\fR, and if \fITcl_FSCopyFileProc\fR is not implemented there is a further fallback). However, if a \fITcl_FSRenameFileProc\fR command is issued at the C level, no such fallbacks occur. This is true except for the last four entries in the filesystem table (\fBlstat\fR, \fBload\fR, \fBgetcwd\fR and \fBchdir\fR) for which fallbacks do in fact occur at the C level. .PP Any functions which take path names in Tcl_Obj form take those names in UTF\-8 form. The filesystem infrastructure API is designed to support efficient, cached conversion of these UTF\-8 paths to other native representations. .SS "EXAMPLE FILESYSTEM DEFINITION" .PP Here is the filesystem lookup table used by the .QW vfs extension which allows filesystem actions to be implemented in Tcl. .PP .CS static Tcl_Filesystem vfsFilesystem = { "tclvfs", sizeof(Tcl_Filesystem), TCL_FILESYSTEM_VERSION_1, &VfsPathInFilesystem, &VfsDupInternalRep, &VfsFreeInternalRep, /* No internal to normalized, since we don't create * any pure 'internal' Tcl_Obj path representations */ NULL, /* No create native rep function, since we don't use * it and don't choose to support uses of * Tcl_FSNewNativePath */ NULL, /* Normalize path isn't needed - we assume paths only * have one representation */ NULL, &VfsFilesystemPathType, &VfsFilesystemSeparator, &VfsStat, &VfsAccess, &VfsOpenFileChannel, &VfsMatchInDirectory, &VfsUtime, /* We choose not to support symbolic links inside our * VFS's */ NULL, &VfsListVolumes, &VfsFileAttrStrings, &VfsFileAttrsGet, &VfsFileAttrsSet, &VfsCreateDirectory, &VfsRemoveDirectory, &VfsDeleteFile, /* No copy file; use the core fallback mechanism */ NULL, /* No rename file; use the core fallback mechanism */ NULL, /* No copy directory; use the core fallback mechanism */ NULL, /* Core will use stat for lstat */ NULL, /* No load; use the core fallback mechanism */ NULL, /* We don't need a getcwd or chdir; the core's own * internal value is suitable */ NULL, NULL }; .CE .SH "FILESYSTEM INFRASTRUCTURE" .PP These fields contain basic information about the filesystem structure and addresses of functions which are used to associate a particular filesystem with a file path, and deal with the internal handling of path representations, for example copying and freeing such representations. .SS TYPENAME .PP The \fItypeName\fR field contains a null-terminated string that identifies the type of the filesystem implemented, e.g. .QW native , .QW zip or .QW vfs . .SS "STRUCTURE LENGTH" .PP The \fIstructureLength\fR field is generally implemented as \fIsizeof(Tcl_Filesystem)\fR, and is there to allow easier binary backwards compatibility if the size of the structure changes in a future Tcl release. .SS VERSION .PP The \fIversion\fR field should be set to \fBTCL_FILESYSTEM_VERSION_1\fR. .SS PATHINFILESYSTEMPROC .PP The \fIpathInFilesystemProc\fR field contains the address of a function which is called to determine whether a given path value belongs to this filesystem or not. Tcl will only call the rest of the filesystem functions with a path for which this function has returned \fBTCL_OK\fR. If the path does not belong, -1 should be returned (the behavior of Tcl for any other return value is not defined). If \fBTCL_OK\fR is returned, then the optional \fIclientDataPtr\fR output parameter can be used to return an internal (filesystem specific) representation of the path, which will be cached inside the path value, and may be retrieved efficiently by the other filesystem functions. Tcl will simultaneously cache the fact that this path belongs to this filesystem. Such caches are invalidated when filesystem structures are added or removed from Tcl's internal list of known filesystems. .PP .CS typedef int \fBTcl_FSPathInFilesystemProc\fR( Tcl_Obj *\fIpathPtr\fR, ClientData *\fIclientDataPtr\fR); .CE .SS DUPINTERNALREPPROC .PP This function makes a copy of a path's internal representation, and is called when Tcl needs to duplicate a path value. If NULL, Tcl will simply not copy the internal representation, which may then need to be regenerated later. .PP .CS typedef ClientData \fBTcl_FSDupInternalRepProc\fR( ClientData \fIclientData\fR); .CE .SS FREEINTERNALREPPROC Free the internal representation. This must be implemented if internal representations need freeing (i.e.\ if some memory is allocated when an internal representation is generated), but may otherwise be NULL. .PP .CS typedef void \fBTcl_FSFreeInternalRepProc\fR( ClientData \fIclientData\fR); .CE .SS INTERNALTONORMALIZEDPROC .PP Function to convert internal representation to a normalized path. Only required if the filesystem creates pure path values with no string/path representation. The return value is a Tcl value whose string representation is the normalized path. .PP .CS typedef Tcl_Obj *\fBTcl_FSInternalToNormalizedProc\fR( ClientData \fIclientData\fR); .CE .SS CREATEINTERNALREPPROC .PP Function to take a path value, and calculate an internal representation for it, and store that native representation in the value. May be NULL if paths have no internal representation, or if the \fITcl_FSPathInFilesystemProc\fR for this filesystem always immediately creates an internal representation for paths it accepts. .PP .CS typedef ClientData \fBTcl_FSCreateInternalRepProc\fR( Tcl_Obj *\fIpathPtr\fR); .CE .SS NORMALIZEPATHPROC .PP Function to normalize a path. Should be implemented for all filesystems which can have multiple string representations for the same path value. In Tcl, every .QW path must have a single unique .QW normalized string representation. Depending on the filesystem, there may be more than one unnormalized string representation which refers to that path (e.g.\ a relative path, a path with different character case if the filesystem is case insensitive, a path contain a reference to a home directory such as .QW ~ , a path containing symbolic links, etc). If the very last component in the path is a symbolic link, it should not be converted into the value it points to (but its case or other aspects should be made unique). All other path components should be converted from symbolic links. This one exception is required to agree with Tcl's semantics with \fBfile delete\fR, \fBfile rename\fR, \fBfile copy\fR operating on symbolic links. This function may be called with \fInextCheckpoint\fR either at the beginning of the path (i.e.\ zero), at the end of the path, or at any intermediate file separator in the path. It will never point to any other arbitrary position in the path. In the last of the three valid cases, the implementation can assume that the path up to and including the file separator is known and normalized. .PP .CS typedef int \fBTcl_FSNormalizePathProc\fR( Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIpathPtr\fR, int \fInextCheckpoint\fR); .CE .SH "FILESYSTEM OPERATIONS" .PP The fields in this section of the structure contain addresses of functions which are called to carry out the basic filesystem operations. A filesystem which expects to be used with the complete standard Tcl command set must implement all of these. If some of them are not implemented, then certain Tcl commands may fail when operating on paths within that filesystem. However, in some instances this may be desirable (for example, a read-only filesystem should not implement the last four functions, and a filesystem which does not support symbolic links need not implement the \fBreadlink\fR function, etc. The Tcl core expects filesystems to behave in this way). .SS FILESYSTEMPATHTYPEPROC .PP Function to determine the type of a path in this filesystem. May be NULL, in which case no type information will be available to users of the filesystem. The .QW type is used only for informational purposes, and should be returned as the string representation of the Tcl_Obj which is returned. A typical return value might be .QW networked , .QW zip or .QW ftp . The Tcl_Obj result is owned by the filesystem and so Tcl will increment the reference count of that value if it wishes to retain a reference to it. .PP .CS typedef Tcl_Obj *\fBTcl_FSFilesystemPathTypeProc\fR( Tcl_Obj *\fIpathPtr\fR); .CE .SS FILESYSTEMSEPARATORPROC .PP Function to return the separator character(s) for this filesystem. This need only be implemented if the filesystem wishes to use a different separator than the standard string .QW / . Amongst other uses, it is returned by the \fBfile separator\fR command. The return value should be a value with reference count of zero. .PP .CS typedef Tcl_Obj *\fBTcl_FSFilesystemSeparatorProc\fR( Tcl_Obj *\fIpathPtr\fR); .CE .SS STATPROC .PP Function to process a \fBTcl_FSStat\fR call. Must be implemented for any reasonable filesystem, since many Tcl level commands depend crucially upon it (e.g.\ \fBfile atime\fR, \fBfile isdirectory\fR, \fBfile size\fR, \fBglob\fR). .PP .CS typedef int \fBTcl_FSStatProc\fR( Tcl_Obj *\fIpathPtr\fR, Tcl_StatBuf *\fIstatPtr\fR); .CE .PP The \fBTcl_FSStatProc\fR fills the stat structure \fIstatPtr\fR with information about the specified file. You do not need any access rights to the file to get this information but you need search rights to all directories named in the path leading to the file. The stat structure includes info regarding device, inode (always 0 on Windows), privilege mode, nlink (always 1 on Windows), user id (always 0 on Windows), group id (always 0 on Windows), rdev (same as device on Windows), size, last access time, last modification time, and last metadata change time. .PP If the file represented by \fIpathPtr\fR exists, the \fBTcl_FSStatProc\fR returns 0 and the stat structure is filled with data. Otherwise, -1 is returned, and no stat info is given. .SS ACCESSPROC .PP Function to process a \fBTcl_FSAccess\fR call. Must be implemented for any reasonable filesystem, since many Tcl level commands depend crucially upon it (e.g.\ \fBfile exists\fR, \fBfile readable\fR). .PP .CS typedef int \fBTcl_FSAccessProc\fR( Tcl_Obj *\fIpathPtr\fR, int \fImode\fR); .CE .PP The \fBTcl_FSAccessProc\fR checks whether the process would be allowed to read, write or test for existence of the file (or other filesystem object) whose name is in \fIpathPtr\fR. If the pathname refers to a symbolic link, then the permissions of the file referred by this symbolic link should be tested. .PP On success (all requested permissions granted), zero is returned. On error (at least one bit in mode asked for a permission that is denied, or some other error occurred), -1 is returned. .SS OPENFILECHANNELPROC .PP Function to process a \fBTcl_FSOpenFileChannel\fR call. Must be implemented for any reasonable filesystem, since any operations which require open or accessing a file's contents will use it (e.g.\ \fBopen\fR, \fBencoding\fR, and many Tk commands). .PP .CS typedef Tcl_Channel \fBTcl_FSOpenFileChannelProc\fR( Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIpathPtr\fR, int \fImode\fR, int \fIpermissions\fR); .CE .PP The \fBTcl_FSOpenFileChannelProc\fR opens a file specified by \fIpathPtr\fR and returns a channel handle that can be used to perform input and output on the file. This API is modeled after the \fBfopen\fR procedure of the Unix standard I/O library. The syntax and meaning of all arguments is similar to those given in the Tcl \fBopen\fR command when opening a file, where the \fImode\fR argument is a combination of the POSIX flags O_RDONLY, O_WRONLY, etc. If an error occurs while opening the channel, the \fBTcl_FSOpenFileChannelProc\fR returns NULL and records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. In addition, if \fIinterp\fR is non-NULL, the \fBTcl_FSOpenFileChannelProc\fR leaves an error message in \fIinterp\fR's result after any error. .PP The newly created channel must not be registered in the supplied interpreter by a \fBTcl_FSOpenFileChannelProc\fR; that task is up to the caller of \fBTcl_FSOpenFileChannel\fR (if necessary). If one of the standard channels, \fBstdin\fR, \fBstdout\fR or \fBstderr\fR was previously closed, the act of creating the new channel also assigns it as a replacement for the standard channel. .SS MATCHINDIRECTORYPROC .PP Function to process a \fBTcl_FSMatchInDirectory\fR call. If not implemented, then glob and recursive copy functionality will be lacking in the filesystem (and this may impact commands like \fBencoding names\fR which use glob functionality internally). .PP .CS typedef int \fBTcl_FSMatchInDirectoryProc\fR( Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIresultPtr\fR, Tcl_Obj *\fIpathPtr\fR, const char *\fIpattern\fR, Tcl_GlobTypeData *\fItypes\fR); .CE .PP The function should return all files or directories (or other filesystem objects) which match the given pattern and accord with the \fItypes\fR specification given. There are two ways in which this function may be called. If \fIpattern\fR is NULL, then \fIpathPtr\fR is a full path specification of a single file or directory which should be checked for existence and correct type. Otherwise, \fIpathPtr\fR is a directory, the contents of which the function should search for files or directories which have the correct type. In either case, \fIpathPtr\fR can be assumed to be both non-NULL and non-empty. It is not currently documented whether \fIpathPtr\fR will have a file separator at its end of not, so code should be flexible to both possibilities. .PP The return value is a standard Tcl result indicating whether an error occurred in the matching process. Error messages are placed in \fIinterp\fR, unless \fIinterp\fR in NULL in which case no error message need be generated; on a \fBTCL_OK\fR result, results should be added to the \fIresultPtr\fR value given (which can be assumed to be a valid unshared Tcl list). The matches added to \fIresultPtr\fR should include any path prefix given in \fIpathPtr\fR (this usually means they will be absolute path specifications). Note that if no matches are found, that simply leads to an empty result; errors are only signaled for actual file or filesystem problems which may occur during the matching process. .PP The \fBTcl_GlobTypeData\fR structure passed in the \fItypes\fR parameter contains the following fields: .PP .CS typedef struct Tcl_GlobTypeData { /* Corresponds to bcdpfls as in 'find -t' */ int \fItype\fR; /* Corresponds to file permissions */ int \fIperm\fR; /* Acceptable mac type */ Tcl_Obj *\fImacType\fR; /* Acceptable mac creator */ Tcl_Obj *\fImacCreator\fR; } \fBTcl_GlobTypeData\fR; .CE .PP There are two specific cases which it is important to handle correctly, both when \fItypes\fR is non-NULL. The two cases are when \fItypes->types & TCL_GLOB_TYPE_DIR\fR or \fItypes->types & TCL_GLOB_TYPE_MOUNT\fR are true (and in particular when the other flags are false). In the first of these cases, the function must list the contained directories. Tcl uses this to implement recursive globbing, so it is critical that filesystems implement directory matching correctly. In the second of these cases, with \fBTCL_GLOB_TYPE_MOUNT\fR, the filesystem must list the mount points which lie within the given \fIpathPtr\fR (and in this case, \fIpathPtr\fR need not lie within the same filesystem - different to all other cases in which this function is called). Support for this is critical if Tcl is to have seamless transitions between from one filesystem to another. .SS UTIMEPROC .PP Function to process a \fBTcl_FSUtime\fR call. Required to allow setting (not reading) of times with \fBfile mtime\fR, \fBfile atime\fR and the open-r/open-w/fcopy implementation of \fBfile copy\fR. .PP .CS typedef int \fBTcl_FSUtimeProc\fR( Tcl_Obj *\fIpathPtr\fR, struct utimbuf *\fItval\fR); .CE .PP The access and modification times of the file specified by \fIpathPtr\fR should be changed to the values given in the \fItval\fR structure. .PP The return value should be 0 on success and -1 on an error, as with the system \fButime\fR. .SS LINKPROC .PP Function to process a \fBTcl_FSLink\fR call. Should be implemented only if the filesystem supports links, and may otherwise be NULL. .PP .CS typedef Tcl_Obj *\fBTcl_FSLinkProc\fR( Tcl_Obj *\fIlinkNamePtr\fR, Tcl_Obj *\fItoPtr\fR, int \fIlinkAction\fR); .CE .PP If \fItoPtr\fR is NULL, the function is being asked to read the contents of a link. The result is a Tcl_Obj specifying the contents of the link given by \fIlinkNamePtr\fR, or NULL if the link could not be read. The result is owned by the caller (and should therefore have its ref count incremented before being returned). Any callers should call \fBTcl_DecrRefCount\fR on this result when it is no longer needed. If \fItoPtr\fR is not NULL, the function should attempt to create a link. The result in this case should be \fItoPtr\fR if the link was successful and NULL otherwise. In this case the result is not owned by the caller (i.e.\ no reference count manipulations on either end are needed). See the documentation for \fBTcl_FSLink\fR for the correct interpretation of the \fIlinkAction\fR flags. .SS LISTVOLUMESPROC .PP Function to list any filesystem volumes added by this filesystem. Should be implemented only if the filesystem adds volumes at the head of the filesystem, so that they can be returned by \fBfile volumes\fR. .PP .CS typedef Tcl_Obj *\fBTcl_FSListVolumesProc\fR(void); .CE .PP The result should be a list of volumes added by this filesystem, or NULL (or an empty list) if no volumes are provided. The result value is considered to be owned by the filesystem (not by Tcl's core), but should be given a reference count for Tcl. Tcl will use the contents of the list and then decrement that reference count. This allows filesystems to choose whether they actually want to retain a .QW "master list" of volumes or not (if not, they generate the list on the fly and pass it to Tcl with a reference count of 1 and then forget about the list, if yes, then they simply increment the reference count of their master list and pass it to Tcl which will copy the contents and then decrement the count back to where it was). .PP Therefore, Tcl considers return values from this proc to be read-only. .SS FILEATTRSTRINGSPROC .PP Function to list all attribute strings which are valid for this filesystem. If not implemented the filesystem will not support the \fBfile attributes\fR command. This allows arbitrary additional information to be attached to files in the filesystem. If it is not implemented, there is no need to implement the \fBget\fR and \fBset\fR methods. .PP .CS typedef const char *const *\fBTcl_FSFileAttrStringsProc\fR( Tcl_Obj *\fIpathPtr\fR, Tcl_Obj **\fIobjPtrRef\fR); .CE .PP The called function may either return an array of strings, or may instead return NULL and place a Tcl list into the given \fIobjPtrRef\fR. Tcl will take that list and first increment its reference count before using it. On completion of that use, Tcl will decrement its reference count. Hence if the list should be disposed of by Tcl when done, it should have a reference count of zero, and if the list should not be disposed of, the filesystem should ensure it returns a value with a reference count of at least one. .SS FILEATTRSGETPROC .PP Function to process a \fBTcl_FSFileAttrsGet\fR call, used by \fBfile attributes\fR. .PP .CS typedef int \fBTcl_FSFileAttrsGetProc\fR( Tcl_Interp *\fIinterp\fR, int \fIindex\fR, Tcl_Obj *\fIpathPtr\fR, Tcl_Obj **\fIobjPtrRef\fR); .CE .PP Returns a standard Tcl return code. The attribute value retrieved, which corresponds to the \fIindex\fR'th element in the list returned by the \fBTcl_FSFileAttrStringsProc\fR, is a Tcl_Obj placed in \fIobjPtrRef\fR (if \fBTCL_OK\fR was returned) and is likely to have a reference count of zero. Either way we must either store it somewhere (e.g.\ the Tcl result), or Incr/Decr its reference count to ensure it is properly freed. .SS FILEATTRSSETPROC .PP Function to process a \fBTcl_FSFileAttrsSet\fR call, used by \fBfile attributes\fR. If the filesystem is read-only, there is no need to implement this. .PP .CS typedef int \fBTcl_FSFileAttrsSetProc\fR( Tcl_Interp *\fIinterp\fR, int \fIindex\fR, Tcl_Obj *\fIpathPtr\fR, Tcl_Obj *\fIobjPtr\fR); .CE .PP The attribute value of the \fIindex\fR'th element in the list returned by the Tcl_FSFileAttrStringsProc should be set to the \fIobjPtr\fR given. .SS CREATEDIRECTORYPROC .PP Function to process a \fBTcl_FSCreateDirectory\fR call. Should be implemented unless the FS is read-only. .PP .CS typedef int \fBTcl_FSCreateDirectoryProc\fR( Tcl_Obj *\fIpathPtr\fR); .CE .PP The return value is a standard Tcl result indicating whether an error occurred in the process. If successful, a new directory should have been added to the filesystem in the location specified by \fIpathPtr\fR. .SS REMOVEDIRECTORYPROC .PP Function to process a \fBTcl_FSRemoveDirectory\fR call. Should be implemented unless the FS is read-only. .PP .CS typedef int \fBTcl_FSRemoveDirectoryProc\fR( Tcl_Obj *\fIpathPtr\fR, int \fIrecursive\fR, Tcl_Obj **\fIerrorPtr\fR); .CE .PP The return value is a standard Tcl result indicating whether an error occurred in the process. If successful, the directory specified by \fIpathPtr\fR should have been removed from the filesystem. If the \fIrecursive\fR flag is given, then a non-empty directory should be deleted without error. If this flag is not given, then and the directory is non-empty a POSIX .QW EEXIST error should be signaled. If an error does occur, the name of the file or directory which caused the error should be placed in \fIerrorPtr\fR. .SS DELETEFILEPROC .PP Function to process a \fBTcl_FSDeleteFile\fR call. Should be implemented unless the FS is read-only. .PP .CS typedef int \fBTcl_FSDeleteFileProc\fR( Tcl_Obj *\fIpathPtr\fR); .CE .PP The return value is a standard Tcl result indicating whether an error occurred in the process. If successful, the file specified by \fIpathPtr\fR should have been removed from the filesystem. Note that, if the filesystem supports symbolic links, Tcl will always call this function and not Tcl_FSRemoveDirectoryProc when needed to delete them (even if they are symbolic links to directories). .SH "FILESYSTEM EFFICIENCY" .PP These functions need not be implemented for a particular filesystem because the core has a fallback implementation available. See each individual description for the consequences of leaving the field NULL. .SS LSTATPROC .PP Function to process a \fBTcl_FSLstat\fR call. If not implemented, Tcl will attempt to use the \fIstatProc\fR defined above instead. Therefore it need only be implemented if a filesystem can differentiate between \fBstat\fR and \fBlstat\fR calls. .PP .CS typedef int \fBTcl_FSLstatProc\fR( Tcl_Obj *\fIpathPtr\fR, Tcl_StatBuf *\fIstatPtr\fR); .CE .PP The behavior of this function is very similar to that of the \fBTcl_FSStatProc\fR defined above, except that if it is applied to a symbolic link, it returns information about the link, not about the target file. .SS COPYFILEPROC .PP Function to process a \fBTcl_FSCopyFile\fR call. If not implemented Tcl will fall back on \fBopen\fR-r, \fBopen\fR-w and \fBfcopy\fR as a copying mechanism. Therefore it need only be implemented if the filesystem can perform that action more efficiently. .PP .CS typedef int \fBTcl_FSCopyFileProc\fR( Tcl_Obj *\fIsrcPathPtr\fR, Tcl_Obj *\fIdestPathPtr\fR); .CE .PP The return value is a standard Tcl result indicating whether an error occurred in the copying process. Note that, \fIdestPathPtr\fR is the name of the file which should become the copy of \fIsrcPathPtr\fR. It is never the name of a directory into which \fIsrcPathPtr\fR could be copied (i.e.\ the function is much simpler than the Tcl level \fBfile copy\fR subcommand). Note that, if the filesystem supports symbolic links, Tcl will always call this function and not \fIcopyDirectoryProc\fR when needed to copy them (even if they are symbolic links to directories). Finally, if the filesystem determines it cannot support the \fBfile copy\fR action, calling \fBTcl_SetErrno(EXDEV)\fR and returning a non-\fBTCL_OK\fR result will tell Tcl to use its standard fallback mechanisms. .SS RENAMEFILEPROC .PP Function to process a \fBTcl_FSRenameFile\fR call. If not implemented, Tcl will fall back on a copy and delete mechanism. Therefore it need only be implemented if the filesystem can perform that action more efficiently. .PP .CS typedef int \fBTcl_FSRenameFileProc\fR( Tcl_Obj *\fIsrcPathPtr\fR, Tcl_Obj *\fIdestPathPtr\fR); .CE .PP The return value is a standard Tcl result indicating whether an error occurred in the renaming process. If the filesystem determines it cannot support the \fBfile rename\fR action, calling \fBTcl_SetErrno(EXDEV)\fR and returning a non-\fBTCL_OK\fR result will tell Tcl to use its standard fallback mechanisms. .SS COPYDIRECTORYPROC .PP Function to process a \fBTcl_FSCopyDirectory\fR call. If not implemented, Tcl will fall back on a recursive \fBfile mkdir\fR, \fBfile copy\fR mechanism. Therefore it need only be implemented if the filesystem can perform that action more efficiently. .PP .CS typedef int \fBTcl_FSCopyDirectoryProc\fR( Tcl_Obj *\fIsrcPathPtr\fR, Tcl_Obj *\fIdestPathPtr\fR, Tcl_Obj **\fIerrorPtr\fR); .CE .PP The return value is a standard Tcl result indicating whether an error occurred in the copying process. If an error does occur, the name of the file or directory which caused the error should be placed in \fIerrorPtr\fR. Note that, \fIdestPathPtr\fR is the name of the directory-name which should become the mirror-image of \fIsrcPathPtr\fR. It is not the name of a directory into which \fIsrcPathPtr\fR should be copied (i.e.\ the function is much simpler than the Tcl level \fBfile copy\fR subcommand). Finally, if the filesystem determines it cannot support the directory copy action, calling \fBTcl_SetErrno(EXDEV)\fR and returning a non-\fBTCL_OK\fR result will tell Tcl to use its standard fallback mechanisms. .SS LOADFILEPROC .PP Function to process a \fBTcl_FSLoadFile\fR call. If not implemented, Tcl will fall back on a copy to native-temp followed by a \fBTcl_FSLoadFile\fR on that temporary copy. Therefore it need only be implemented if the filesystem can load code directly, or it can be implemented simply to return \fBTCL_ERROR\fR to disable load functionality in this filesystem entirely. .PP .CS typedef int \fBTcl_FSLoadFileProc\fR( Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIpathPtr\fR, Tcl_LoadHandle *\fIhandlePtr\fR, Tcl_FSUnloadFileProc *\fIunloadProcPtr\fR); .CE .PP Returns a standard Tcl completion code. If an error occurs, an error message is left in the \fIinterp\fR's result. The function dynamically loads a binary code file into memory. On a successful load, the \fIhandlePtr\fR should be filled with a token for the dynamically loaded file, and the \fIunloadProcPtr\fR should be filled in with the address of a procedure. The unload procedure will be called with the given \fBTcl_LoadHandle\fR as its only parameter when Tcl needs to unload the file. For example, for the native filesystem, the \fBTcl_LoadHandle\fR returned is currently a token which can be used in the private \fBTclpFindSymbol\fR to access functions in the new code. Each filesystem is free to define the \fBTcl_LoadHandle\fR as it requires. Finally, if the filesystem determines it cannot support the file load action, calling \fBTcl_SetErrno(EXDEV)\fR and returning a non-\fBTCL_OK\fR result will tell Tcl to use its standard fallback mechanisms. .SS UNLOADFILEPROC .PP Function to unload a previously successfully loaded file. If load was implemented, then this should also be implemented, if there is any cleanup action required. .PP .CS typedef void \fBTcl_FSUnloadFileProc\fR( Tcl_LoadHandle \fIloadHandle\fR); .CE .SS GETCWDPROC .PP Function to process a \fBTcl_FSGetCwd\fR call. Most filesystems need not implement this. It will usually only be called once, if \fBgetcwd\fR is called before \fBchdir\fR. May be NULL. .PP .CS typedef Tcl_Obj *\fBTcl_FSGetCwdProc\fR( Tcl_Interp *\fIinterp\fR); .CE .PP If the filesystem supports a native notion of a current working directory (which might perhaps change independent of Tcl), this function should return that cwd as the result, or NULL if the current directory could not be determined (e.g.\ the user does not have appropriate permissions on the cwd directory). If NULL is returned, an error message is left in the \fIinterp\fR's result. .SS CHDIRPROC .PP Function to process a \fBTcl_FSChdir\fR call. If filesystems do not implement this, it will be emulated by a series of directory access checks. Otherwise, virtual filesystems which do implement it need only respond with a positive return result if the \fIpathPtr\fR is a valid, accessible directory in their filesystem. They need not remember the result, since that will be automatically remembered for use by \fBTcl_FSGetCwd\fR. Real filesystems should carry out the correct action (i.e.\ call the correct system \fBchdir\fR API). .PP .CS typedef int \fBTcl_FSChdirProc\fR( Tcl_Obj *\fIpathPtr\fR); .CE .PP The \fBTcl_FSChdirProc\fR changes the applications current working directory to the value specified in \fIpathPtr\fR. The function returns -1 on error or 0 on success. .SH "SEE ALSO" cd(n), file(n), filename(n), load(n), open(n), pwd(n), source(n), unload(n) .SH KEYWORDS stat, access, filesystem, vfs, virtual filesystem tcl8.6.5/doc/Notifier.30000644000175000017500000007221512663660065014206 0ustar sergeisergei'\" '\" Copyright (c) 1998-1999 Scriptics Corporation '\" Copyright (c) 1995-1997 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 Notifier 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CreateEventSource, Tcl_DeleteEventSource, Tcl_SetMaxBlockTime, Tcl_QueueEvent, Tcl_ThreadQueueEvent, Tcl_ThreadAlert, Tcl_GetCurrentThread, Tcl_DeleteEvents, Tcl_InitNotifier, Tcl_FinalizeNotifier, Tcl_WaitForEvent, Tcl_AlertNotifier, Tcl_SetTimer, Tcl_ServiceAll, Tcl_ServiceEvent, Tcl_GetServiceMode, Tcl_SetServiceMode, Tcl_ServiceModeHook, Tcl_SetNotifier \- the event queue and notifier interfaces .SH SYNOPSIS .nf \fB#include \fR .sp void \fBTcl_CreateEventSource\fR(\fIsetupProc, checkProc, clientData\fR) .sp void \fBTcl_DeleteEventSource\fR(\fIsetupProc, checkProc, clientData\fR) .sp void \fBTcl_SetMaxBlockTime\fR(\fItimePtr\fR) .sp void \fBTcl_QueueEvent\fR(\fIevPtr, position\fR) .sp void \fBTcl_ThreadQueueEvent\fR(\fIthreadId, evPtr, position\fR) .sp void \fBTcl_ThreadAlert\fR(\fIthreadId\fR) .sp Tcl_ThreadId \fBTcl_GetCurrentThread\fR() .sp void \fBTcl_DeleteEvents\fR(\fIdeleteProc, clientData\fR) .sp ClientData \fBTcl_InitNotifier\fR() .sp void \fBTcl_FinalizeNotifier\fR(\fIclientData\fR) .sp int \fBTcl_WaitForEvent\fR(\fItimePtr\fR) .sp void \fBTcl_AlertNotifier\fR(\fIclientData\fR) .sp void \fBTcl_SetTimer\fR(\fItimePtr\fR) .sp int \fBTcl_ServiceAll\fR() .sp int \fBTcl_ServiceEvent\fR(\fIflags\fR) .sp int \fBTcl_GetServiceMode\fR() .sp int \fBTcl_SetServiceMode\fR(\fImode\fR) .sp void \fBTcl_ServiceModeHook\fR(\fImode\fR) .sp void \fBTcl_SetNotifier\fR(\fInotifierProcPtr\fR) .SH ARGUMENTS .AS Tcl_EventDeleteProc *notifierProcPtr .AP Tcl_EventSetupProc *setupProc in Procedure to invoke to prepare for event wait in \fBTcl_DoOneEvent\fR. .AP Tcl_EventCheckProc *checkProc in Procedure for \fBTcl_DoOneEvent\fR to invoke after waiting for events. Checks to see if any events have occurred and, if so, queues them. .AP ClientData clientData in Arbitrary one-word value to pass to \fIsetupProc\fR, \fIcheckProc\fR, or \fIdeleteProc\fR. .AP "const Tcl_Time" *timePtr in Indicates the maximum amount of time to wait for an event. This is specified as an interval (how long to wait), not an absolute time (when to wakeup). If the pointer passed to \fBTcl_WaitForEvent\fR is NULL, it means there is no maximum wait time: wait forever if necessary. .AP Tcl_Event *evPtr in An event to add to the event queue. The storage for the event must have been allocated by the caller using \fBTcl_Alloc\fR or \fBckalloc\fR. .AP Tcl_QueuePosition position in Where to add the new event in the queue: \fBTCL_QUEUE_TAIL\fR, \fBTCL_QUEUE_HEAD\fR, or \fBTCL_QUEUE_MARK\fR. .AP Tcl_ThreadId threadId in A unique identifier for a thread. .AP Tcl_EventDeleteProc *deleteProc in Procedure to invoke for each queued event in \fBTcl_DeleteEvents\fR. .AP int flags in What types of events to service. These flags are the same as those passed to \fBTcl_DoOneEvent\fR. .AP int mode in Indicates whether events should be serviced by \fBTcl_ServiceAll\fR. Must be one of \fBTCL_SERVICE_NONE\fR or \fBTCL_SERVICE_ALL\fR. .AP Tcl_NotifierProcs* notifierProcPtr in Structure of function pointers describing notifier procedures that are to replace the ones installed in the executable. See \fBREPLACING THE NOTIFIER\fR for details. .BE .SH INTRODUCTION .PP The interfaces described here are used to customize the Tcl event loop. The two most common customizations are to add new sources of events and to merge Tcl's event loop with some other event loop, such as one provided by an application in which Tcl is embedded. Each of these tasks is described in a separate section below. .PP The procedures in this manual entry are the building blocks out of which the Tcl event notifier is constructed. The event notifier is the lowest layer in the Tcl event mechanism. It consists of three things: .IP [1] Event sources: these represent the ways in which events can be generated. For example, there is a timer event source that implements the \fBTcl_CreateTimerHandler\fR procedure and the \fBafter\fR command, and there is a file event source that implements the \fBTcl_CreateFileHandler\fR procedure on Unix systems. An event source must work with the notifier to detect events at the right times, record them on the event queue, and eventually notify higher-level software that they have occurred. The procedures \fBTcl_CreateEventSource\fR, \fBTcl_DeleteEventSource\fR, and \fBTcl_SetMaxBlockTime\fR, \fBTcl_QueueEvent\fR, and \fBTcl_DeleteEvents\fR are used primarily by event sources. .IP [2] The event queue: for non-threaded applications, there is a single queue for the whole application, containing events that have been detected but not yet serviced. Event sources place events onto the queue so that they may be processed in order at appropriate times during the event loop. The event queue guarantees a fair discipline of event handling, so that no event source can starve the others. It also allows events to be saved for servicing at a future time. Threaded applications work in a similar manner, except that there is a separate event queue for each thread containing a Tcl interpreter. \fBTcl_QueueEvent\fR is used (primarily by event sources) to add events to the event queue and \fBTcl_DeleteEvents\fR is used to remove events from the queue without processing them. In a threaded application, \fBTcl_QueueEvent\fR adds an event to the current thread's queue, and \fBTcl_ThreadQueueEvent\fR adds an event to a queue in a specific thread. .IP [3] The event loop: in order to detect and process events, the application enters a loop that waits for events to occur, places them on the event queue, and then processes them. Most applications will do this by calling the procedure \fBTcl_DoOneEvent\fR, which is described in a separate manual entry. .PP Most Tcl applications need not worry about any of the internals of the Tcl notifier. However, the notifier now has enough flexibility to be retargeted either for a new platform or to use an external event loop (such as the Motif event loop, when Tcl is embedded in a Motif application). The procedures \fBTcl_WaitForEvent\fR and \fBTcl_SetTimer\fR are normally implemented by Tcl, but may be replaced with new versions to retarget the notifier (the \fBTcl_InitNotifier\fR, \fBTcl_AlertNotifier\fR, \fBTcl_FinalizeNotifier\fR, \fBTcl_Sleep\fR, \fBTcl_CreateFileHandler\fR, and \fBTcl_DeleteFileHandler\fR must also be replaced; see CREATING A NEW NOTIFIER below for details). The procedures \fBTcl_ServiceAll\fR, \fBTcl_ServiceEvent\fR, \fBTcl_GetServiceMode\fR, and \fBTcl_SetServiceMode\fR are provided to help connect Tcl's event loop to an external event loop such as Motif's. .SH "NOTIFIER BASICS" .PP The easiest way to understand how the notifier works is to consider what happens when \fBTcl_DoOneEvent\fR is called. \fBTcl_DoOneEvent\fR is passed a \fIflags\fR argument that indicates what sort of events it is OK to process and also whether or not to block if no events are ready. \fBTcl_DoOneEvent\fR does the following things: .IP [1] Check the event queue to see if it contains any events that can be serviced. If so, service the first possible event, remove it from the queue, and return. It does this by calling \fBTcl_ServiceEvent\fR and passing in the \fIflags\fR argument. .IP [2] Prepare to block for an event. To do this, \fBTcl_DoOneEvent\fR invokes a \fIsetup procedure\fR in each event source. The event source will perform event-source specific initialization and possibly call \fBTcl_SetMaxBlockTime\fR to limit how long \fBTcl_WaitForEvent\fR will block if no new events occur. .IP [3] Call \fBTcl_WaitForEvent\fR. This procedure is implemented differently on different platforms; it waits for an event to occur, based on the information provided by the event sources. It may cause the application to block if \fItimePtr\fR specifies an interval other than 0. \fBTcl_WaitForEvent\fR returns when something has happened, such as a file becoming readable or the interval given by \fItimePtr\fR expiring. If there are no events for \fBTcl_WaitForEvent\fR to wait for, so that it would block forever, then it returns immediately and \fBTcl_DoOneEvent\fR returns 0. .IP [4] Call a \fIcheck procedure\fR in each event source. The check procedure determines whether any events of interest to this source occurred. If so, the events are added to the event queue. .IP [5] Check the event queue to see if it contains any events that can be serviced. If so, service the first possible event, remove it from the queue, and return. .IP [6] See if there are idle callbacks pending. If so, invoke all of them and return. .IP [7] Either return 0 to indicate that no events were ready, or go back to step [2] if blocking was requested by the caller. .SH "CREATING A NEW EVENT SOURCE" .PP An event source consists of three procedures invoked by the notifier, plus additional C procedures that are invoked by higher-level code to arrange for event-driven callbacks. The three procedures called by the notifier consist of the setup and check procedures described above, plus an additional procedure that is invoked when an event is removed from the event queue for servicing. .PP The procedure \fBTcl_CreateEventSource\fR creates a new event source. Its arguments specify the setup procedure and check procedure for the event source. \fISetupProc\fR should match the following prototype: .PP .CS typedef void \fBTcl_EventSetupProc\fR( ClientData \fIclientData\fR, int \fIflags\fR); .CE .PP The \fIclientData\fR argument will be the same as the \fIclientData\fR argument to \fBTcl_CreateEventSource\fR; it is typically used to point to private information managed by the event source. The \fIflags\fR argument will be the same as the \fIflags\fR argument passed to \fBTcl_DoOneEvent\fR except that it will never be 0 (\fBTcl_DoOneEvent\fR replaces 0 with \fBTCL_ALL_EVENTS\fR). \fIFlags\fR indicates what kinds of events should be considered; if the bit corresponding to this event source is not set, the event source should return immediately without doing anything. For example, the file event source checks for the \fBTCL_FILE_EVENTS\fR bit. .PP \fISetupProc\fR's job is to make sure that the application wakes up when events of the desired type occur. This is typically done in a platform-dependent fashion. For example, under Unix an event source might call \fBTcl_CreateFileHandler\fR; under Windows it might request notification with a Windows event. For timer-driven event sources such as timer events or any polled event, the event source can call \fBTcl_SetMaxBlockTime\fR to force the application to wake up after a specified time even if no events have occurred. If no event source calls \fBTcl_SetMaxBlockTime\fR then \fBTcl_WaitForEvent\fR will wait as long as necessary for an event to occur; otherwise, it will only wait as long as the shortest interval passed to \fBTcl_SetMaxBlockTime\fR by one of the event sources. If an event source knows that it already has events ready to report, it can request a zero maximum block time. For example, the setup procedure for the X event source looks to see if there are events already queued. If there are, it calls \fBTcl_SetMaxBlockTime\fR with a 0 block time so that \fBTcl_WaitForEvent\fR does not block if there is no new data on the X connection. The \fItimePtr\fR argument to \fBTcl_WaitForEvent\fR points to a structure that describes a time interval in seconds and microseconds: .PP .CS typedef struct Tcl_Time { long \fIsec\fR; long \fIusec\fR; } \fBTcl_Time\fR; .CE .PP The \fIusec\fR field should be less than 1000000. .PP Information provided to \fBTcl_SetMaxBlockTime\fR is only used for the next call to \fBTcl_WaitForEvent\fR; it is discarded after \fBTcl_WaitForEvent\fR returns. The next time an event wait is done each of the event sources' setup procedures will be called again, and they can specify new information for that event wait. .PP If the application uses an external event loop rather than \fBTcl_DoOneEvent\fR, the event sources may need to call \fBTcl_SetMaxBlockTime\fR at other times. For example, if a new event handler is registered that needs to poll for events, the event source may call \fBTcl_SetMaxBlockTime\fR to set the block time to zero to force the external event loop to call Tcl. In this case, \fBTcl_SetMaxBlockTime\fR invokes \fBTcl_SetTimer\fR with the shortest interval seen since the last call to \fBTcl_DoOneEvent\fR or \fBTcl_ServiceAll\fR. .PP In addition to the generic procedure \fBTcl_SetMaxBlockTime\fR, other platform-specific procedures may also be available for \fIsetupProc\fR, if there is additional information needed by \fBTcl_WaitForEvent\fR on that platform. For example, on Unix systems the \fBTcl_CreateFileHandler\fR interface can be used to wait for file events. .PP The second procedure provided by each event source is its check procedure, indicated by the \fIcheckProc\fR argument to \fBTcl_CreateEventSource\fR. \fICheckProc\fR must match the following prototype: .PP .CS typedef void \fBTcl_EventCheckProc\fR( ClientData \fIclientData\fR, int \fIflags\fR); .CE .PP The arguments to this procedure are the same as those for \fIsetupProc\fR. \fBCheckProc\fR is invoked by \fBTcl_DoOneEvent\fR after it has waited for events. Presumably at least one event source is now prepared to queue an event. \fBTcl_DoOneEvent\fR calls each of the event sources in turn, so they all have a chance to queue any events that are ready. The check procedure does two things. First, it must see if any events have triggered. Different event sources do this in different ways. .PP If an event source's check procedure detects an interesting event, it must add the event to Tcl's event queue. To do this, the event source calls \fBTcl_QueueEvent\fR. The \fIevPtr\fR argument is a pointer to a dynamically allocated structure containing the event (see below for more information on memory management issues). Each event source can define its own event structure with whatever information is relevant to that event source. However, the first element of the structure must be a structure of type \fBTcl_Event\fR, and the address of this structure is used when communicating between the event source and the rest of the notifier. A \fBTcl_Event\fR has the following definition: .PP .CS typedef struct { Tcl_EventProc *\fIproc\fR; struct Tcl_Event *\fInextPtr\fR; } \fBTcl_Event\fR; .CE .PP The event source must fill in the \fIproc\fR field of the event before calling \fBTcl_QueueEvent\fR. The \fInextPtr\fR is used to link together the events in the queue and should not be modified by the event source. .PP An event may be added to the queue at any of three positions, depending on the \fIposition\fR argument to \fBTcl_QueueEvent\fR: .IP \fBTCL_QUEUE_TAIL\fR 24 Add the event at the back of the queue, so that all other pending events will be serviced first. This is almost always the right place for new events. .IP \fBTCL_QUEUE_HEAD\fR 24 Add the event at the front of the queue, so that it will be serviced before all other queued events. .IP \fBTCL_QUEUE_MARK\fR 24 Add the event at the front of the queue, unless there are other events at the front whose position is \fBTCL_QUEUE_MARK\fR; if so, add the new event just after all other \fBTCL_QUEUE_MARK\fR events. This value of \fIposition\fR is used to insert an ordered sequence of events at the front of the queue, such as a series of Enter and Leave events synthesized during a grab or ungrab operation in Tk. .PP When it is time to handle an event from the queue (steps 1 and 4 above) \fBTcl_ServiceEvent\fR will invoke the \fIproc\fR specified in the first queued \fBTcl_Event\fR structure. \fIProc\fR must match the following prototype: .PP .CS typedef int \fBTcl_EventProc\fR( Tcl_Event *\fIevPtr\fR, int \fIflags\fR); .CE .PP The first argument to \fIproc\fR is a pointer to the event, which will be the same as the first argument to the \fBTcl_QueueEvent\fR call that added the event to the queue. The second argument to \fIproc\fR is the \fIflags\fR argument for the current call to \fBTcl_ServiceEvent\fR; this is used by the event source to return immediately if its events are not relevant. .PP It is up to \fIproc\fR to handle the event, typically by invoking one or more Tcl commands or C-level callbacks. Once the event source has finished handling the event it returns 1 to indicate that the event can be removed from the queue. If for some reason the event source decides that the event cannot be handled at this time, it may return 0 to indicate that the event should be deferred for processing later; in this case \fBTcl_ServiceEvent\fR will go on to the next event in the queue and attempt to service it. There are several reasons why an event source might defer an event. One possibility is that events of this type are excluded by the \fIflags\fR argument. For example, the file event source will always return 0 if the \fBTCL_FILE_EVENTS\fR bit is not set in \fIflags\fR. Another example of deferring events happens in Tk if \fBTk_RestrictEvents\fR has been invoked to defer certain kinds of window events. .PP When \fIproc\fR returns 1, \fBTcl_ServiceEvent\fR will remove the event from the event queue and free its storage. Note that the storage for an event must be allocated by the event source (using \fBTcl_Alloc\fR or the Tcl macro \fBckalloc\fR) before calling \fBTcl_QueueEvent\fR, but it will be freed by \fBTcl_ServiceEvent\fR, not by the event source. .PP Threaded applications work in a similar manner, except that there is a separate event queue for each thread containing a Tcl interpreter. Calling \fBTcl_QueueEvent\fR in a multithreaded application adds an event to the current thread's queue. To add an event to another thread's queue, use \fBTcl_ThreadQueueEvent\fR. \fBTcl_ThreadQueueEvent\fR accepts as an argument a Tcl_ThreadId argument, which uniquely identifies a thread in a Tcl application. To obtain the Tcl_ThreadId for the current thread, use the \fBTcl_GetCurrentThread\fR procedure. (A thread would then need to pass this identifier to other threads for those threads to be able to add events to its queue.) After adding an event to another thread's queue, you then typically need to call \fBTcl_ThreadAlert\fR to .QW "wake up" that thread's notifier to alert it to the new event. .PP \fBTcl_DeleteEvents\fR can be used to explicitly remove one or more events from the event queue. \fBTcl_DeleteEvents\fR calls \fIproc\fR for each event in the queue, deleting those for with the procedure returns 1. Events for which the procedure returns 0 are left in the queue. \fIProc\fR should match the following prototype: .PP .CS typedef int \fBTcl_EventDeleteProc\fR( Tcl_Event *\fIevPtr\fR, ClientData \fIclientData\fR); .CE .PP The \fIclientData\fR argument will be the same as the \fIclientData\fR argument to \fBTcl_DeleteEvents\fR; it is typically used to point to private information managed by the event source. The \fIevPtr\fR will point to the next event in the queue. .PP \fBTcl_DeleteEventSource\fR deletes an event source. The \fIsetupProc\fR, \fIcheckProc\fR, and \fIclientData\fR arguments must exactly match those provided to the \fBTcl_CreateEventSource\fR for the event source to be deleted. If no such source exists, \fBTcl_DeleteEventSource\fR has no effect. .SH "CREATING A NEW NOTIFIER" .PP The notifier consists of all the procedures described in this manual entry, plus \fBTcl_DoOneEvent\fR and \fBTcl_Sleep\fR, which are available on all platforms, and \fBTcl_CreateFileHandler\fR and \fBTcl_DeleteFileHandler\fR, which are Unix-specific. Most of these procedures are generic, in that they are the same for all notifiers. However, none of the procedures are notifier-dependent: \fBTcl_InitNotifier\fR, \fBTcl_AlertNotifier\fR, \fBTcl_FinalizeNotifier\fR, \fBTcl_SetTimer\fR, \fBTcl_Sleep\fR, \fBTcl_WaitForEvent\fR, \fBTcl_CreateFileHandler\fR, \fBTcl_DeleteFileHandler\fR and \fBTcl_ServiceModeHook\fR. To support a new platform or to integrate Tcl with an application-specific event loop, you must write new versions of these procedures. .PP \fBTcl_InitNotifier\fR initializes the notifier state and returns a handle to the notifier state. Tcl calls this procedure when initializing a Tcl interpreter. Similarly, \fBTcl_FinalizeNotifier\fR shuts down the notifier, and is called by \fBTcl_Finalize\fR when shutting down a Tcl interpreter. .PP \fBTcl_WaitForEvent\fR is the lowest-level procedure in the notifier; it is responsible for waiting for an .QW interesting event to occur or for a given time to elapse. Before \fBTcl_WaitForEvent\fR is invoked, each of the event sources' setup procedure will have been invoked. The \fItimePtr\fR argument to \fBTcl_WaitForEvent\fR gives the maximum time to block for an event, based on calls to \fBTcl_SetMaxBlockTime\fR made by setup procedures and on other information (such as the \fBTCL_DONT_WAIT\fR bit in \fIflags\fR). .PP Ideally, \fBTcl_WaitForEvent\fR should only wait for an event to occur; it should not actually process the event in any way. Later on, the event sources will process the raw events and create Tcl_Events on the event queue in their \fIcheckProc\fR procedures. However, on some platforms (such as Windows) this is not possible; events may be processed in \fBTcl_WaitForEvent\fR, including queuing Tcl_Events and more (for example, callbacks for native widgets may be invoked). The return value from \fBTcl_WaitForEvent\fR must be either 0, 1, or \-1. On platforms such as Windows where events get processed in \fBTcl_WaitForEvent\fR, a return value of 1 means that there may be more events still pending that have not been processed. This is a sign to the caller that it must call \fBTcl_WaitForEvent\fR again if it wants all pending events to be processed. A 0 return value means that calling \fBTcl_WaitForEvent\fR again will not have any effect: either this is a platform where \fBTcl_WaitForEvent\fR only waits without doing any event processing, or \fBTcl_WaitForEvent\fR knows for sure that there are no additional events to process (e.g. it returned because the time elapsed). Finally, a return value of \-1 means that the event loop is no longer operational and the application should probably unwind and terminate. Under Windows this happens when a WM_QUIT message is received; under Unix it happens when \fBTcl_WaitForEvent\fR would have waited forever because there were no active event sources and the timeout was infinite. .PP \fBTcl_AlertNotifier\fR is used in multithreaded applications to allow any thread to .QW "wake up" the notifier to alert it to new events on its queue. \fBTcl_AlertNotifier\fR requires as an argument the notifier handle returned by \fBTcl_InitNotifier\fR. .PP If the notifier will be used with an external event loop, then it must also support the \fBTcl_SetTimer\fR interface. \fBTcl_SetTimer\fR is invoked by \fBTcl_SetMaxBlockTime\fR whenever the maximum blocking time has been reduced. \fBTcl_SetTimer\fR should arrange for the external event loop to invoke \fBTcl_ServiceAll\fR after the specified interval even if no events have occurred. This interface is needed because \fBTcl_WaitForEvent\fR is not invoked when there is an external event loop. If the notifier will only be used from \fBTcl_DoOneEvent\fR, then \fBTcl_SetTimer\fR need not do anything. .PP \fBTcl_ServiceModeHook\fR is called by the platform-independent portion of the notifier when client code makes a call to \fBTcl_SetServiceMode\fR. This hook is provided to support operating systems that require special event handling when the application is in a modal loop (the Windows notifier, for instance, uses this hook to create a communication window). .PP On Unix systems, the file event source also needs support from the notifier. The file event source consists of the \fBTcl_CreateFileHandler\fR and \fBTcl_DeleteFileHandler\fR procedures, which are described in the \fBTcl_CreateFileHandler\fR manual page. .PP The \fBTcl_Sleep\fR and \fBTcl_DoOneEvent\fR interfaces are described in their respective manual pages. .PP The easiest way to create a new notifier is to look at the code for an existing notifier, such as the files \fBunix/tclUnixNotfy.c\fR or \fBwin/tclWinNotify.c\fR in the Tcl source distribution. .SH "REPLACING THE NOTIFIER" .PP A notifier that has been written according to the conventions above can also be installed in a running process in place of the standard notifier. This mechanism is used so that a single executable can be used (with the standard notifier) as a stand-alone program and reused (with a replacement notifier in a loadable extension) as an extension to another program, such as a Web browser plugin. .PP To do this, the extension makes a call to \fBTcl_SetNotifier\fR passing a pointer to a \fBTcl_NotifierProcs\fR data structure. The structure has the following layout: .PP .CS typedef struct Tcl_NotifierProcs { Tcl_SetTimerProc *\fIsetTimerProc\fR; Tcl_WaitForEventProc *\fIwaitForEventProc\fR; Tcl_CreateFileHandlerProc *\fIcreateFileHandlerProc\fR; Tcl_DeleteFileHandlerProc *\fIdeleteFileHandlerProc\fR; Tcl_InitNotifierProc *\fIinitNotifierProc\fR; Tcl_FinalizeNotifierProc *\fIfinalizeNotifierProc\fR; Tcl_AlertNotifierProc *\fIalertNotifierProc\fR; Tcl_ServiceModeHookProc *\fIserviceModeHookProc\fR; } \fBTcl_NotifierProcs\fR; .CE .PP Following the call to \fBTcl_SetNotifier\fR, the pointers given in the \fBTcl_NotifierProcs\fR structure replace whatever notifier had been installed in the process. .PP It is extraordinarily unwise to replace a running notifier. Normally, \fBTcl_SetNotifier\fR should be called at process initialization time before the first call to \fBTcl_InitNotifier\fR. .SH "EXTERNAL EVENT LOOPS" .PP The notifier interfaces are designed so that Tcl can be embedded into applications that have their own private event loops. In this case, the application does not call \fBTcl_DoOneEvent\fR except in the case of recursive event loops such as calls to the Tcl commands \fBupdate\fR or \fBvwait\fR. Most of the time is spent in the external event loop of the application. In this case the notifier must arrange for the external event loop to call back into Tcl when something happens on the various Tcl event sources. These callbacks should arrange for appropriate Tcl events to be placed on the Tcl event queue. .PP Because the external event loop is not calling \fBTcl_DoOneEvent\fR on a regular basis, it is up to the notifier to arrange for \fBTcl_ServiceEvent\fR to be called whenever events are pending on the Tcl event queue. The easiest way to do this is to invoke \fBTcl_ServiceAll\fR at the end of each callback from the external event loop. This will ensure that all of the event sources are polled, any queued events are serviced, and any pending idle handlers are processed before returning control to the application. In addition, event sources that need to poll for events can call \fBTcl_SetMaxBlockTime\fR to force the external event loop to call Tcl even if no events are available on the system event queue. .PP As a side effect of processing events detected in the main external event loop, Tcl may invoke \fBTcl_DoOneEvent\fR to start a recursive event loop in commands like \fBvwait\fR. \fBTcl_DoOneEvent\fR will invoke the external event loop, which will result in callbacks as described in the preceding paragraph, which will result in calls to \fBTcl_ServiceAll\fR. However, in these cases it is undesirable to service events in \fBTcl_ServiceAll\fR. Servicing events there is unnecessary because control will immediately return to the external event loop and hence to \fBTcl_DoOneEvent\fR, which can service the events itself. Furthermore, \fBTcl_DoOneEvent\fR is supposed to service only a single event, whereas \fBTcl_ServiceAll\fR normally services all pending events. To handle this situation, \fBTcl_DoOneEvent\fR sets a flag for \fBTcl_ServiceAll\fR that causes it to return without servicing any events. This flag is called the \fIservice mode\fR; \fBTcl_DoOneEvent\fR restores it to its previous value before it returns. .PP In some cases, however, it may be necessary for \fBTcl_ServiceAll\fR to service events even when it has been invoked from \fBTcl_DoOneEvent\fR. This happens when there is yet another recursive event loop invoked via an event handler called by \fBTcl_DoOneEvent\fR (such as one that is part of a native widget). In this case, \fBTcl_DoOneEvent\fR may not have a chance to service events so \fBTcl_ServiceAll\fR must service them all. Any recursive event loop that calls an external event loop rather than \fBTcl_DoOneEvent\fR must reset the service mode so that all events get processed in \fBTcl_ServiceAll\fR. This is done by invoking the \fBTcl_SetServiceMode\fR procedure. If \fBTcl_SetServiceMode\fR is passed \fBTCL_SERVICE_NONE\fR, then calls to \fBTcl_ServiceAll\fR will return immediately without processing any events. If \fBTcl_SetServiceMode\fR is passed \fBTCL_SERVICE_ALL\fR, then calls to \fBTcl_ServiceAll\fR will behave normally. \fBTcl_SetServiceMode\fR returns the previous value of the service mode, which should be restored when the recursive loop exits. \fBTcl_GetServiceMode\fR returns the current value of the service mode. .SH "SEE ALSO" Tcl_CreateFileHandler(3), Tcl_DeleteFileHandler(3), Tcl_Sleep(3), Tcl_DoOneEvent(3), Thread(3) .SH KEYWORDS event, notifier, event queue, event sources, file events, timer, idle, service mode, threads tcl8.6.5/doc/lmap.n0000644000175000017500000000604112663660065013445 0ustar sergeisergei'\" '\" Copyright (c) 2012 Trevor Davel '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lmap n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lmap \- Iterate over all elements in one or more lists and collect results .SH SYNOPSIS \fBlmap \fIvarname list body\fR .br \fBlmap \fIvarlist1 list1\fR ?\fIvarlist2 list2 ...\fR? \fIbody\fR .BE .SH DESCRIPTION .PP The \fBlmap\fR command implements a loop where the loop variable(s) take on values from one or more lists, and the loop returns a list of results collected from each iteration. .PP In the simplest case there is one loop variable, \fIvarname\fR, and one list, \fIlist\fR, that is a list of values to assign to \fIvarname\fR. The \fIbody\fR argument is a Tcl script. For each element of \fIlist\fR (in order from first to last), \fBlmap\fR assigns the contents of the element to \fIvarname\fR as if the \fBlindex\fR command had been used to extract the element, then calls the Tcl interpreter to execute \fIbody\fR. If execution of the body completes normally then the result of the body is appended to an accumulator list. \fBlmap\fR returns the accumulator list. .PP In the general case there can be more than one value list (e.g., \fIlist1\fR and \fIlist2\fR), and each value list can be associated with a list of loop variables (e.g., \fIvarlist1\fR and \fIvarlist2\fR). During each iteration of the loop the variables of each \fIvarlist\fR are assigned consecutive values from the corresponding \fIlist\fR. Values in each \fIlist\fR are used in order from first to last, and each value is used exactly once. The total number of loop iterations is large enough to use up all the values from all the value lists. If a value list does not contain enough elements for each of its loop variables in each iteration, empty values are used for the missing elements. .PP The \fBbreak\fR and \fBcontinue\fR statements may be invoked inside \fIbody\fR, with the same effect as in the \fBfor\fR and \fBforeach\fR commands. In these cases the body does not complete normally and the result is not appended to the accumulator list. .SH EXAMPLES .PP Zip lists together: .PP .CS set list1 {a b c d} set list2 {1 2 3 4} set zipped [\fBlmap\fR a $list1 b $list2 {list $a $b}] # The value of zipped is "{a 1} {b 2} {c 3} {d 4}" .CE .PP Filter a list to remove odd values: .PP .CS set values {1 2 3 4 5 6 7 8} proc isEven {n} {expr {($n % 2) == 0}} set goodOnes [\fBlmap\fR x $values {expr { [isEven $x] ? $x : [continue] }}] # The value of goodOnes is "2 4 6 8" .CE .PP Take a prefix from a list based on the contents of the list: .PP .CS set values {8 7 6 5 4 3 2 1} proc isGood {counter} {expr {$n > 3}} set prefix [\fBlmap\fR x $values {expr { [isGood $x] ? $x : [break] }}] # The value of prefix is "8 7 6 5 4" .CE .SH "SEE ALSO" break(n), continue(n), for(n), foreach(n), while(n) .SH KEYWORDS foreach, iteration, list, loop, map '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/LinkVar.30000644000175000017500000002111512663660065013766 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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_LinkVar 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_LinkVar, Tcl_UnlinkVar, Tcl_UpdateLinkedVar \- link Tcl variable to C variable .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_LinkVar\fR(\fIinterp, varName, addr, type\fR) .sp \fBTcl_UnlinkVar\fR(\fIinterp, varName\fR) .sp \fBTcl_UpdateLinkedVar\fR(\fIinterp, varName\fR) .SH ARGUMENTS .AS Tcl_Interp writable .AP Tcl_Interp *interp in Interpreter that contains \fIvarName\fR. Also used by \fBTcl_LinkVar\fR to return error messages. .AP "const char" *varName in Name of global variable. .AP char *addr in Address of C variable that is to be linked to \fIvarName\fR. .AP int type in Type of C variable. Must be one of \fBTCL_LINK_INT\fR, \fBTCL_LINK_UINT\fR, \fBTCL_LINK_CHAR\fR, \fBTCL_LINK_UCHAR\fR, \fBTCL_LINK_SHORT\fR, \fBTCL_LINK_USHORT\fR, \fBTCL_LINK_LONG\fR, \fBTCL_LINK_ULONG\fR, \fBTCL_LINK_WIDE_INT\fR, \fBTCL_LINK_WIDE_UINT\fR, \fBTCL_LINK_FLOAT\fR, \fBTCL_LINK_DOUBLE\fR, \fBTCL_LINK_BOOLEAN\fR, or \fBTCL_LINK_STRING\fR, optionally OR'ed with \fBTCL_LINK_READ_ONLY\fR to make Tcl variable read-only. .BE .SH DESCRIPTION .PP \fBTcl_LinkVar\fR uses variable traces to keep the Tcl variable named by \fIvarName\fR in sync with the C variable at the address given by \fIaddr\fR. Whenever the Tcl variable is read the value of the C variable will be returned, and whenever the Tcl variable is written the C variable will be updated to have the same value. \fBTcl_LinkVar\fR normally returns \fBTCL_OK\fR; if an error occurs while setting up the link (e.g. because \fIvarName\fR is the name of array) then \fBTCL_ERROR\fR is returned and the interpreter's result contains an error message. .PP The \fItype\fR argument specifies the type of the C variable, and must have one of the following values, optionally OR'ed with \fBTCL_LINK_READ_ONLY\fR: .TP \fBTCL_LINK_INT\fR The C variable is of type \fBint\fR. Any value written into the Tcl variable must have a proper integer form acceptable to \fBTcl_GetIntFromObj\fR; attempts to write non-integer values into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_UINT\fR The C variable is of type \fBunsigned int\fR. Any value written into the Tcl variable must have a proper unsigned integer form acceptable to \fBTcl_GetWideIntFromObj\fR and in the platform's defined range for the \fBunsigned int\fR type; attempts to write non-integer values (or values outside the range) into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_CHAR\fR The C variable is of type \fBchar\fR. Any value written into the Tcl variable must have a proper integer form acceptable to \fBTcl_GetIntFromObj\fR and be in the range of the \fBchar\fR datatype; attempts to write non-integer or out-of-range values into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_UCHAR\fR The C variable is of type \fBunsigned char\fR. Any value written into the Tcl variable must have a proper unsigned integer form acceptable to \fBTcl_GetIntFromObj\fR and in the platform's defined range for the \fBunsigned char\fR type; attempts to write non-integer values (or values outside the range) into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_SHORT\fR The C variable is of type \fBshort\fR. Any value written into the Tcl variable must have a proper integer form acceptable to \fBTcl_GetIntFromObj\fR and be in the range of the \fBshort\fR datatype; attempts to write non-integer or out-of-range values into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_USHORT\fR The C variable is of type \fBunsigned short\fR. Any value written into the Tcl variable must have a proper unsigned integer form acceptable to \fBTcl_GetIntFromObj\fR and in the platform's defined range for the \fBunsigned short\fR type; attempts to write non-integer values (or values outside the range) into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_LONG\fR The C variable is of type \fBlong\fR. Any value written into the Tcl variable must have a proper integer form acceptable to \fBTcl_GetLongFromObj\fR; attempts to write non-integer or out-of-range values into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_ULONG\fR The C variable is of type \fBunsigned long\fR. Any value written into the Tcl variable must have a proper unsigned integer form acceptable to \fBTcl_GetWideIntFromObj\fR and in the platform's defined range for the \fBunsigned long\fR type; attempts to write non-integer values (or values outside the range) into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_DOUBLE\fR The C variable is of type \fBdouble\fR. Any value written into the Tcl variable must have a proper real form acceptable to \fBTcl_GetDoubleFromObj\fR; attempts to write non-real values into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_FLOAT\fR The C variable is of type \fBfloat\fR. Any value written into the Tcl variable must have a proper real form acceptable to \fBTcl_GetDoubleFromObj\fR and must be within the range acceptable for a \fBfloat\fR; attempts to write non-real values (or values outside the range) into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_WIDE_INT\fR The C variable is of type \fBTcl_WideInt\fR (which is an integer type at least 64-bits wide on all platforms that can support it.) Any value written into the Tcl variable must have a proper integer form acceptable to \fBTcl_GetWideIntFromObj\fR; attempts to write non-integer values into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_WIDE_UINT\fR The C variable is of type \fBTcl_WideUInt\fR (which is an unsigned integer type at least 64-bits wide on all platforms that can support it.) Any value written into the Tcl variable must have a proper unsigned integer form acceptable to \fBTcl_GetWideIntFromObj\fR (it will be cast to unsigned); .\" FIXME! Use bignums instead. attempts to write non-integer values into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_BOOLEAN\fR The C variable is of type \fBint\fR. If its value is zero then it will read from Tcl as .QW 0 ; otherwise it will read from Tcl as .QW 1 . Whenever \fIvarName\fR is modified, the C variable will be set to a 0 or 1 value. Any value written into the Tcl variable must have a proper boolean form acceptable to \fBTcl_GetBooleanFromObj\fR; attempts to write non-boolean values into \fIvarName\fR will be rejected with Tcl errors. .TP \fBTCL_LINK_STRING\fR The C variable is of type \fBchar *\fR. If its value is not NULL then it must be a pointer to a string allocated with \fBTcl_Alloc\fR or \fBckalloc\fR. Whenever the Tcl variable is modified the current C string will be freed and new memory will be allocated to hold a copy of the variable's new value. If the C variable contains a NULL pointer then the Tcl variable will read as .QW NULL . .PP If the \fBTCL_LINK_READ_ONLY\fR flag is present in \fItype\fR then the variable will be read-only from Tcl, so that its value can only be changed by modifying the C variable. Attempts to write the variable from Tcl will be rejected with errors. .PP \fBTcl_UnlinkVar\fR removes the link previously set up for the variable given by \fIvarName\fR. If there does not exist a link for \fIvarName\fR then the procedure has no effect. .PP \fBTcl_UpdateLinkedVar\fR may be invoked after the C variable has changed to force the Tcl variable to be updated immediately. In many cases this procedure is not needed, since any attempt to read the Tcl variable will return the latest value of the C variable. However, if a trace has been set on the Tcl variable (such as a Tk widget that wishes to display the value of the variable), the trace will not trigger when the C variable has changed. \fBTcl_UpdateLinkedVar\fR ensures that any traces on the Tcl variable are invoked. .PP Note that, as with any call to a Tcl interpreter, \fBTcl_UpdateLinkedVar\fR must be called from the same thread that created the interpreter. The safest mechanism is to ensure that the C variable is only ever updated from the same thread that created the interpreter (possibly in response to an event posted with \fBTcl_ThreadQueueEvent\fR), but when it is necessary to update the variable in a separate thread, it is advised that \fBTcl_AsyncMark\fR be used to indicate to the thread hosting the interpreter that it is ready to run \fBTcl_UpdateLinkedVar\fR. .SH "SEE ALSO" Tcl_TraceVar(3) .SH KEYWORDS boolean, integer, link, read-only, real, string, trace, variable tcl8.6.5/doc/update.n0000644000175000017500000000443512663660065014003 0ustar sergeisergei'\" '\" Copyright (c) 1990-1992 The Regents of the University of California. '\" Copyright (c) 1994-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 update n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME update \- Process pending events and idle callbacks .SH SYNOPSIS \fBupdate\fR ?\fBidletasks\fR? .BE .SH DESCRIPTION .PP This command is used to bring the application .QW "up to date" by entering the event loop repeatedly until all pending events (including idle callbacks) have been processed. .PP If the \fBidletasks\fR keyword is specified as an argument to the command, then no new events or errors are processed; only idle callbacks are invoked. This causes operations that are normally deferred, such as display updates and window layout calculations, to be performed immediately. .PP The \fBupdate idletasks\fR command is useful in scripts where changes have been made to the application's state and you want those changes to appear on the display immediately, rather than waiting for the script to complete. Most display updates are performed as idle callbacks, so \fBupdate idletasks\fR will cause them to run. However, there are some kinds of updates that only happen in response to events, such as those triggered by window size changes; these updates will not occur in \fBupdate idletasks\fR. .PP The \fBupdate\fR command with no options is useful in scripts where you are performing a long-running computation but you still want the application to respond to events such as user interactions; if you occasionally call \fBupdate\fR then user input will be processed during the next call to \fBupdate\fR. .SH EXAMPLE .PP Run computations for about a second and then finish: .PP .CS set x 1000 set done 0 after 1000 set done 1 while {!$done} { # A very silly example! set x [expr {log($x) ** 2.8}] # Test to see if our time-limit has been hit. This would # also give a chance for serving network sockets and, if # the Tk package is loaded, updating a user interface. \fBupdate\fR } .CE .SH "SEE ALSO" after(n), interp(n) .SH KEYWORDS asynchronous I/O, event, flush, handler, idle, update tcl8.6.5/doc/lrepeat.n0000644000175000017500000000222612663660065014151 0ustar sergeisergei'\" '\" Copyright (c) 2003 by Simon Geard. All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lrepeat n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lrepeat \- Build a list by repeating elements .SH SYNOPSIS \fBlrepeat \fIcount \fR?\fIelement ...\fR? .BE .SH DESCRIPTION .PP The \fBlrepeat\fR command creates a list of size \fIcount * number of elements\fR by repeating \fIcount\fR times the sequence of elements \fIelement ...\fR. \fIcount\fR must be a non-negative integer, \fIelement\fR can be any Tcl value. Note that \fBlrepeat 1 element ...\fR is identical to \fBlist element ...\fR. .SH EXAMPLES .CS \fBlrepeat\fR 3 a \fI\(-> a a a\fR \fBlrepeat\fR 3 [\fBlrepeat\fR 3 0] \fI\(-> {0 0 0} {0 0 0} {0 0 0}\fR \fBlrepeat\fR 3 a b c \fI\(-> a b c a b c a b c\fR \fBlrepeat\fR 3 [\fBlrepeat\fR 2 a] b c \fI\(-> {a a} b c {a a} b c {a a} b c\fR .CE .SH "SEE ALSO" list(n), lappend(n), linsert(n), llength(n), lset(n) .SH KEYWORDS element, index, list tcl8.6.5/doc/filename.n0000644000175000017500000001650212663660065014277 0ustar sergeisergei'\" '\" 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 filename n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME filename \- File name conventions supported by Tcl commands .BE .SH INTRODUCTION .PP All Tcl commands and C procedures that take file names as arguments expect the file names to be in one of three forms, depending on the current platform. On each platform, Tcl supports file names in the standard forms(s) for that platform. In addition, on all platforms, Tcl supports a Unix-like syntax intended to provide a convenient way of constructing simple file names. However, scripts that are intended to be portable should not assume a particular form for file names. Instead, portable scripts must use the \fBfile split\fR and \fBfile join\fR commands to manipulate file names (see the \fBfile\fR manual entry for more details). .SH "PATH TYPES" .PP File names are grouped into three general types based on the starting point for the path used to specify the file: absolute, relative, and volume-relative. Absolute names are completely qualified, giving a path to the file relative to a particular volume and the root directory on that volume. Relative names are unqualified, giving a path to the file relative to the current working directory. Volume-relative names are partially qualified, either giving the path relative to the root directory on the current volume, or relative to the current directory of the specified volume. The \fBfile pathtype\fR command can be used to determine the type of a given path. .SH "PATH SYNTAX" .PP The rules for native names depend on the value reported in the Tcl \fBplatform\fR element of the \fBtcl_platform\fR array: .TP 10 \fBUnix\fR On Unix and Apple MacOS X platforms, Tcl uses path names where the components are separated by slashes. Path names may be relative or absolute, and file names may contain any character other than slash. The file names \fB\&.\fR and \fB\&..\fR are special and refer to the current directory and the parent of the current directory respectively. Multiple adjacent slash characters are interpreted as a single separator. Any number of trailing slash characters at the end of a path are simply ignored, so the paths \fBfoo\fR, \fBfoo/\fR and \fBfoo//\fR are all identical, and in particular \fBfoo/\fR does not necessarily mean a directory is being referred. .RS .PP The following examples illustrate various forms of path names: .TP 15 \fB/\fR Absolute path to the root directory. .TP 15 \fB/etc/passwd\fR Absolute path to the file named \fBpasswd\fR in the directory \fBetc\fR in the root directory. .TP 15 \fB\&.\fR Relative path to the current directory. .TP 15 \fBfoo\fR Relative path to the file \fBfoo\fR in the current directory. .TP 15 \fBfoo/bar\fR Relative path to the file \fBbar\fR in the directory \fBfoo\fR in the current directory. .TP 15 \fB\&../foo\fR Relative path to the file \fBfoo\fR in the directory above the current directory. .RE .TP \fBWindows\fR On Microsoft Windows platforms, Tcl supports both drive-relative and UNC style names. Both \fB/\fR and \fB\e\fR may be used as directory separators in either type of name. Drive-relative names consist of an optional drive specifier followed by an absolute or relative path. UNC paths follow the general form \fB\e\eservername\esharename\epath\efile\fR, but must at the very least contain the server and share components, i.e. \fB\e\eservername\esharename\fR. In both forms, the file names \fB.\fR and \fB..\fR are special and refer to the current directory and the parent of the current directory respectively. The following examples illustrate various forms of path names: .RS .TP 15 \fB\&\e\eHost\eshare/file\fR Absolute UNC path to a file called \fBfile\fR in the root directory of the export point \fBshare\fR on the host \fBHost\fR. Note that repeated use of \fBfile dirname\fR on this path will give \fB//Host/share\fR, and will never give just \fB//Host\fR. .TP 15 \fBc:foo\fR Volume-relative path to a file \fBfoo\fR in the current directory on drive \fBc\fR. .TP 15 \fBc:/foo\fR Absolute path to a file \fBfoo\fR in the root directory of drive \fBc\fR. .TP 15 \fBfoo\ebar\fR Relative path to a file \fBbar\fR in the \fBfoo\fR directory in the current directory on the current volume. .TP 15 \fB\&\efoo\fR Volume-relative path to a file \fBfoo\fR in the root directory of the current volume. .TP 15 \fB\&\e\efoo\fR Volume-relative path to a file \fBfoo\fR in the root directory of the current volume. This is not a valid UNC path, so the assumption is that the extra backslashes are superfluous. .RE .SH "TILDE SUBSTITUTION" .PP In addition to the file name rules described above, Tcl also supports \fIcsh\fR-style tilde substitution. If a file name starts with a tilde, then the file name will be interpreted as if the first element is replaced with the location of the home directory for the given user. If the tilde is followed immediately by a separator, then the \fB$HOME\fR environment variable is substituted. Otherwise the characters between the tilde and the next separator are taken as a user name, which is used to retrieve the user's home directory for substitution. This works on Unix, MacOS X and Windows (except very old releases). .PP Old Windows platforms do not support tilde substitution when a user name follows the tilde. On these platforms, attempts to use a tilde followed by a user name will generate an error that the user does not exist when Tcl attempts to interpret that part of the path or otherwise access the file. The behaviour of these paths when not trying to interpret them is the same as on Unix. File names that have a tilde without a user name will be correctly substituted using the \fB$HOME\fR environment variable, just like for Unix. .SH "PORTABILITY ISSUES" .PP Not all file systems are case sensitive, so scripts should avoid code that depends on the case of characters in a file name. In addition, the character sets allowed on different devices may differ, so scripts should choose file names that do not contain special characters like: \fB<>:?"/\e|\fR. '\""\" reset emacs highlighting The safest approach is to use names consisting of alphanumeric characters only. Care should be taken with filenames which contain spaces (common on Windows systems) and filenames where the backslash is the directory separator (Windows native path names). Also Windows 3.1 only supports file names with a root of no more than 8 characters and an extension of no more than 3 characters. .PP On Windows platforms there are file and path length restrictions. Complete paths or filenames longer than about 260 characters will lead to errors in most file operations. .PP Another Windows peculiarity is that any number of trailing dots .QW . in filenames are totally ignored, so, for example, attempts to create a file or directory with a name .QW foo. will result in the creation of a file/directory with name .QW foo . This fact is reflected in the results of \fBfile normalize\fR. Furthermore, a file name consisting only of dots .QW ......... or dots with trailing characters .QW .....abc is illegal. .SH "SEE ALSO" file(n), glob(n) .SH KEYWORDS current directory, absolute file name, relative file name, volume-relative file name, portability tcl8.6.5/doc/append.n0000644000175000017500000000244212663660065013764 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 append n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME append \- Append to variable .SH SYNOPSIS \fBappend \fIvarName \fR?\fIvalue value value ...\fR? .BE .SH DESCRIPTION .PP Append all of the \fIvalue\fR arguments to the current value of variable \fIvarName\fR. If \fIvarName\fR does not exist, it is given a value equal to the concatenation of all the \fIvalue\fR arguments. The result of this command is the new value stored in variable \fIvarName\fR. This command provides an efficient way to build up long variables incrementally. For example, .QW "\fBappend a $b\fR" is much more efficient than .QW "\fBset a $a$b\fR" if \fB$a\fR is long. .SH EXAMPLE Building a string of comma-separated numbers piecemeal using a loop. .PP .CS set var 0 for {set i 1} {$i<=10} {incr i} { \fBappend\fR var "," $i } puts $var # Prints 0,1,2,3,4,5,6,7,8,9,10 .CE .SH "SEE ALSO" concat(n), lappend(n) .SH KEYWORDS append, variable '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/memory.n0000644000175000017500000001076612663660065014035 0ustar sergeisergei'\" '\" Copyright (c) 1992-1999 by Karl Lehenbauer and Mark Diekhans '\" Copyright (c) 2000 by Scriptics Corporation. '\" All rights reserved. '\" .TH memory n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS .SH NAME memory \- Control Tcl memory debugging capabilities .SH SYNOPSIS \fBmemory \fIoption \fR?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP The \fBmemory\fR command gives the Tcl developer control of Tcl's memory debugging capabilities. The memory command has several suboptions, which are described below. It is only available when Tcl has been compiled with memory debugging enabled (when \fBTCL_MEM_DEBUG\fR is defined at compile time), and after \fBTcl_InitMemory\fR has been called. .TP \fBmemory active\fR \fIfile\fR . Write a list of all currently allocated memory to the specified \fIfile\fR. .TP \fBmemory break_on_malloc\fR \fIcount\fR . After the \fIcount\fR allocations have been performed, \fBckalloc\fR outputs a message to this effect and that it is now attempting to enter the C debugger. Tcl will then issue a \fISIGINT\fR signal against itself. If you are running Tcl under a C debugger, it should then enter the debugger command mode. .TP \fBmemory info\fR . Returns a report containing the total allocations and frees since Tcl began, the current packets allocated (the current number of calls to \fBckalloc\fR not met by a corresponding call to \fBckfree\fR), the current bytes allocated, and the maximum number of packets and bytes allocated. .TP \fBmemory init \fR[\fBon\fR|\fBoff\fR] . Turn on or off the pre-initialization of all allocated memory with bogus bytes. Useful for detecting the use of uninitialized values. .TP \fBmemory objs \fIfile\fR . Causes a list of all allocated Tcl_Obj values to be written to the specified \fIfile\fR immediately, together with where they were allocated. Useful for checking for leaks of values. .TP \fBmemory onexit\fR \fIfile\fR . Causes a list of all allocated memory to be written to the specified \fIfile\fR during the finalization of Tcl's memory subsystem. Useful for checking that memory is properly cleaned up during process exit. .TP \fBmemory tag\fR \fIstring\fR . Each packet of memory allocated by \fBckalloc\fR can have associated with it a string-valued tag. In the lists of allocated memory generated by \fBmemory active\fR and \fBmemory onexit\fR, the tag for each packet is printed along with other information about the packet. The \fBmemory tag\fR command sets the tag value for subsequent calls to \fBckalloc\fR to be \fIstring\fR. .TP \fBmemory trace \fR[\fBon\fR|\fBoff\fR] . Turns memory tracing on or off. When memory tracing is on, every call to \fBckalloc\fR causes a line of trace information to be written to \fIstderr\fR, consisting of the word \fIckalloc\fR, followed by the address returned, the amount of memory allocated, and the C filename and line number of the code performing the allocation. For example: .RS .PP .CS ckalloc 40e478 98 tclProc.c 1406 .CE .PP Calls to \fBckfree\fR are traced in the same manner. .RE .TP \fBmemory trace_on_at_malloc\fR \fIcount\fR . Enable memory tracing after \fIcount\fR \fBckalloc\fRs have been performed. For example, if you enter \fBmemory trace_on_at_malloc 100\fR, after the 100th call to \fBckalloc\fR, memory trace information will begin being displayed for all allocations and frees. Since there can be a lot of memory activity before a problem occurs, judicious use of this option can reduce the slowdown caused by tracing (and the amount of trace information produced), if you can identify a number of allocations that occur before the problem sets in. The current number of memory allocations that have occurred since Tcl started is printed on a guard zone failure. .TP \fBmemory validate \fR[\fBon\fR|\fBoff\fR] . Turns memory validation on or off. When memory validation is enabled, on every call to \fBckalloc\fR or \fBckfree\fR, the guard zones are checked for every piece of memory currently in existence that was allocated by \fBckalloc\fR. This has a large performance impact and should only be used when overwrite problems are strongly suspected. The advantage of enabling memory validation is that a guard zone overwrite can be detected on the first call to \fBckalloc\fR or \fBckfree\fR after the overwrite occurred, rather than when the specific memory with the overwritten guard zone(s) is freed, which may occur long after the overwrite occurred. .SH "SEE ALSO" ckalloc, ckfree, Tcl_ValidateAllMemory, Tcl_DumpActiveMemory, TCL_MEM_DEBUG .SH KEYWORDS memory, debug '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/TraceCmd.30000644000175000017500000001517412663660065014112 0ustar sergeisergei'\" '\" Copyright (c) 2002 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_TraceCommand 3 7.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CommandTraceInfo, Tcl_TraceCommand, Tcl_UntraceCommand \- monitor renames and deletes of a command .SH SYNOPSIS .nf \fB#include \fR .sp ClientData \fBTcl_CommandTraceInfo(\fIinterp, cmdName, flags, proc, prevClientData\fB)\fR .sp int \fBTcl_TraceCommand(\fIinterp, cmdName, flags, proc, clientData\fB)\fR .sp void \fBTcl_UntraceCommand(\fIinterp, cmdName, flags, proc, clientData\fB)\fR .SH ARGUMENTS .AS Tcl_CommandTraceProc prevClientData .AP Tcl_Interp *interp in Interpreter containing the command. .AP "const char" *cmdName in Name of command. .AP int flags in OR'ed collection of the values \fBTCL_TRACE_RENAME\fR and \fBTCL_TRACE_DELETE\fR. .AP Tcl_CommandTraceProc *proc in Procedure to call when specified operations occur to \fIcmdName\fR. .AP ClientData clientData in Arbitrary argument to pass to \fIproc\fR. .AP ClientData prevClientData in If non-NULL, gives last value returned by \fBTcl_CommandTraceInfo\fR, so this call will return information about next trace. If NULL, this call will return information about first trace. .BE .SH DESCRIPTION .PP \fBTcl_TraceCommand\fR allows a C procedure to monitor operations performed on a Tcl command, so that the C procedure is invoked whenever the command is renamed or deleted. If the trace is created successfully then \fBTcl_TraceCommand\fR returns \fBTCL_OK\fR. If an error occurred (e.g. \fIcmdName\fR specifies a non-existent command) then \fBTCL_ERROR\fR is returned and an error message is left in the interpreter's result. .PP The \fIflags\fR argument to \fBTcl_TraceCommand\fR indicates when the trace procedure is to be invoked. It consists of an OR'ed combination of any of the following values: .TP \fBTCL_TRACE_RENAME\fR Invoke \fIproc\fR whenever the command is renamed. .TP \fBTCL_TRACE_DELETE\fR Invoke \fIproc\fR when the command is deleted. .PP Whenever one of the specified operations occurs to the command, \fIproc\fR will be invoked. It should have arguments and result that match the type \fBTcl_CommandTraceProc\fR: .PP .CS typedef void \fBTcl_CommandTraceProc\fR( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR, const char *\fIoldName\fR, const char *\fInewName\fR, int \fIflags\fR); .CE .PP The \fIclientData\fR and \fIinterp\fR parameters will have the same values as those passed to \fBTcl_TraceCommand\fR when the trace was created. \fIClientData\fR typically points to an application-specific data structure that describes what to do when \fIproc\fR is invoked. \fIOldName\fR gives the name of the command being renamed, and \fInewName\fR gives the name that the command is being renamed to (or NULL when the command is being deleted.) \fIFlags\fR is an OR'ed combination of bits potentially providing several pieces of information. One of the bits \fBTCL_TRACE_RENAME\fR and \fBTCL_TRACE_DELETE\fR will be set in \fIflags\fR to indicate which operation is being performed on the command. The bit \fBTCL_TRACE_DESTROYED\fR will be set in \fIflags\fR if the trace is about to be destroyed; this information may be useful to \fIproc\fR so that it can clean up its own internal data structures (see the section \fBTCL_TRACE_DESTROYED\fR below for more details). Because the deletion of commands can take place as part of the deletion of the interp that contains them, \fIproc\fR must be careful about checking what the passed in \fIinterp\fR value can be called upon to do. The routine \fBTcl_InterpDeleted\fR is an important tool for this. When \fBTcl_InterpDeleted\fR returns 1, \fIproc\fR will not be able to invoke any scripts in \fIinterp\fR. The function of \fIproc\fR in that circumstance is limited to the cleanup of its own data structures. .PP \fBTcl_UntraceCommand\fR may be used to remove a trace. If the command specified by \fIinterp\fR, \fIcmdName\fR, and \fIflags\fR has a trace set with \fIflags\fR, \fIproc\fR, and \fIclientData\fR, then the corresponding trace is removed. If no such trace exists, then the call to \fBTcl_UntraceCommand\fR has no effect. The same bits are valid for \fIflags\fR as for calls to \fBTcl_TraceCommand\fR. .PP \fBTcl_CommandTraceInfo\fR may be used to retrieve information about traces set on a given command. The return value from \fBTcl_CommandTraceInfo\fR is the \fIclientData\fR associated with a particular trace. The trace must be on the command specified by the \fIinterp\fR, \fIcmdName\fR, and \fIflags\fR arguments (note that currently the flags are ignored; \fIflags\fR should be set to 0 for future compatibility) and its trace procedure must the same as the \fIproc\fR argument. If the \fIprevClientData\fR argument is NULL then the return value corresponds to the first (most recently created) matching trace, or NULL if there are no matching traces. If the \fIprevClientData\fR argument is not NULL, then it should be the return value from a previous call to \fBTcl_CommandTraceInfo\fR. In this case, the new return value will correspond to the next matching trace after the one whose \fIclientData\fR matches \fIprevClientData\fR, or NULL if no trace matches \fIprevClientData\fR or if there are no more matching traces after it. This mechanism makes it possible to step through all of the traces for a given command that have the same \fIproc\fR. .SH "CALLING COMMANDS DURING TRACES" .PP During rename traces, the command being renamed is visible with both names simultaneously, and the command still exists during delete traces, unless the interp that contains it is being deleted. However, there is no mechanism for signaling that an error occurred in a trace procedure, so great care should be taken that errors do not get silently lost. .SH "MULTIPLE TRACES" .PP It is possible for multiple traces to exist on the same command. When this happens, all of the trace procedures will be invoked on each access, in order from most-recently-created to least-recently-created. Attempts to delete the command during a delete trace will fail silently, since the command is already scheduled for deletion anyway. If the command being renamed is renamed by one of its rename traces, that renaming takes precedence over the one that triggered the trace and the collection of traces will not be reexecuted; if several traces rename the command, the last renaming takes precedence. .SH "TCL_TRACE_DESTROYED FLAG" .PP In a delete callback to \fIproc\fR, the \fBTCL_TRACE_DESTROYED\fR bit is set in \fIflags\fR. .\" Perhaps need some more comments here? - DKF .SH KEYWORDS clientData, trace, command tcl8.6.5/doc/time.n0000644000175000017500000000217212663660065013453 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 time n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME time \- Time the execution of a script .SH SYNOPSIS \fBtime \fIscript\fR ?\fIcount\fR? .BE .SH DESCRIPTION .PP This command will call the Tcl interpreter \fIcount\fR times to evaluate \fIscript\fR (or once if \fIcount\fR is not specified). It will then return a string of the form .PP .CS \fB503.2 microseconds per iteration\fR .CE .PP which indicates the average amount of time required per iteration, in microseconds. Time is measured in elapsed time, not CPU time. .SH EXAMPLE Estimate how long it takes for a simple Tcl \fBfor\fR loop to count to a thousand: .PP .CS time { for {set i 0} {$i<1000} {incr i} { # empty body } } .CE .SH "SEE ALSO" clock(n) .SH KEYWORDS script, time .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/InitStubs.30000644000175000017500000000666112663660065014355 0ustar sergeisergei'\" '\" Copyright (c) 1998-1999 Scriptics Corporation '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_InitStubs 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_InitStubs \- initialize the Tcl stubs mechanism .SH SYNOPSIS .nf \fB#include \fR .sp const char * \fBTcl_InitStubs\fR(\fIinterp, version, exact\fR) .SH ARGUMENTS .AS Tcl_Interp *interp .AP Tcl_Interp *interp in Tcl interpreter handle. .AP "const char" *version in A version string consisting of one or more decimal numbers separated by dots. .AP int exact in Non-zero means that only the particular version specified by \fIversion\fR is acceptable. Zero means that versions newer than \fIversion\fR are also acceptable as long as they have the same major version number as \fIversion\fR. .BE .SH INTRODUCTION .PP The Tcl stubs mechanism defines a way to dynamically bind extensions to a particular Tcl implementation at run time. This provides two significant benefits to Tcl users: .IP 1) 5 Extensions that use the stubs mechanism can be loaded into multiple versions of Tcl without being recompiled or relinked. .IP 2) 5 Extensions that use the stubs mechanism can be dynamically loaded into statically-linked Tcl applications. .PP The stubs mechanism accomplishes this by exporting function tables that define an interface to the Tcl API. The extension then accesses the Tcl API through offsets into the function table, so there are no direct references to any of the Tcl library's symbols. This redirection is transparent to the extension, so an extension writer can continue to use all public Tcl functions as documented. .PP The stubs mechanism requires no changes to applications incorporating Tcl interpreters. Only developers creating C-based Tcl extensions need to take steps to use the stubs mechanism with their extensions. .PP Enabling the stubs mechanism for an extension requires the following steps: .IP 1) 5 Call \fBTcl_InitStubs\fR in the extension before calling any other Tcl functions. .IP 2) 5 Define the \fBUSE_TCL_STUBS\fR symbol. Typically, you would include the \fB\-DUSE_TCL_STUBS\fR flag when compiling the extension. .IP 3) 5 Link the extension with the Tcl stubs library instead of the standard Tcl library. For example, to use the Tcl 8.6 ABI on Unix platforms, the library name is \fIlibtclstub8.6.a\fR; on Windows platforms, the library name is \fItclstub86.lib\fR. .PP If the extension also requires the Tk API, it must also call \fBTk_InitStubs\fR to initialize the Tk stubs interface and link with the Tk stubs libraries. See the \fBTk_InitStubs\fR page for more information. .SH DESCRIPTION \fBTcl_InitStubs\fR attempts to initialize the stub table pointers and ensure that the correct version of Tcl is loaded. In addition to an interpreter handle, it accepts as arguments a version number and a Boolean flag indicating whether the extension requires an exact version match or not. If \fIexact\fR is 0, then the extension is indicating that newer versions of Tcl are acceptable as long as they have the same major version number as \fIversion\fR; non-zero means that only the specified \fIversion\fR is acceptable. \fBTcl_InitStubs\fR returns a string containing the actual version of Tcl satisfying the request, or NULL if the Tcl version is not acceptable, does not support stubs, or any other error condition occurred. .SH "SEE ALSO" Tk_InitStubs .SH KEYWORDS stubs tcl8.6.5/doc/CrtTrace.30000644000175000017500000002052312663660065014131 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2002 by Kevin B. Kenny . All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_CreateTrace 3 "" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CreateTrace, Tcl_CreateObjTrace, Tcl_DeleteTrace \- arrange for command execution to be traced .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Trace \fBTcl_CreateTrace\fR(\fIinterp, level, proc, clientData\fR) .sp Tcl_Trace \fBTcl_CreateObjTrace\fR(\fIinterp, level, flags, objProc, clientData, deleteProc\fR) .sp \fBTcl_DeleteTrace\fR(\fIinterp, trace\fR) .SH ARGUMENTS .AS Tcl_CmdObjTraceDeleteProc *deleteProc .AP Tcl_Interp *interp in Interpreter containing command to be traced or untraced. .AP int level in Only commands at or below this nesting level will be traced unless 0 is specified. 1 means top-level commands only, 2 means top-level commands or those that are invoked as immediate consequences of executing top-level commands (procedure bodies, bracketed commands, etc.) and so on. A value of 0 means that commands at any level are traced. .AP int flags in Flags governing the trace execution. See below for details. .AP Tcl_CmdObjTraceProc *objProc in Procedure to call for each command that is executed. See below for details of the calling sequence. .AP Tcl_CmdTraceProc *proc in Procedure to call for each command that is executed. See below for details on the calling sequence. .AP ClientData clientData in Arbitrary one-word value to pass to \fIobjProc\fR or \fIproc\fR. .AP Tcl_CmdObjTraceDeleteProc *deleteProc in Procedure to call when the trace is deleted. See below for details of the calling sequence. A NULL pointer is permissible and results in no callback when the trace is deleted. .AP Tcl_Trace trace in Token for trace to be removed (return value from previous call to \fBTcl_CreateTrace\fR). .BE .SH DESCRIPTION .PP \fBTcl_CreateObjTrace\fR arranges for command tracing. After it is called, \fIobjProc\fR will be invoked before the Tcl interpreter calls any command procedure when evaluating commands in \fIinterp\fR. The return value from \fBTcl_CreateObjTrace\fR is a token for the trace, which may be passed to \fBTcl_DeleteTrace\fR to remove the trace. There may be many traces in effect simultaneously for the same interpreter. .PP \fIobjProc\fR should have arguments and result that match the type, \fBTcl_CmdObjTraceProc\fR: .PP .CS typedef int \fBTcl_CmdObjTraceProc\fR( \fBClientData\fR \fIclientData\fR, \fBTcl_Interp\fR* \fIinterp\fR, int \fIlevel\fR, const char *\fIcommand\fR, \fBTcl_Command\fR \fIcommandToken\fR, int \fIobjc\fR, \fBTcl_Obj\fR *const \fIobjv\fR[]); .CE .PP The \fIclientData\fR and \fIinterp\fR parameters are copies of the corresponding arguments given to \fBTcl_CreateTrace\fR. \fIClientData\fR typically points to an application-specific data structure that describes what to do when \fIobjProc\fR is invoked. The \fIlevel\fR parameter gives the nesting level of the command (1 for top-level commands passed to \fBTcl_Eval\fR by the application, 2 for the next-level commands passed to \fBTcl_Eval\fR as part of parsing or interpreting level-1 commands, and so on). The \fIcommand\fR parameter points to a string containing the text of the command, before any argument substitution. The \fIcommandToken\fR parameter is a Tcl command token that identifies the command to be invoked. The token may be passed to \fBTcl_GetCommandName\fR, \fBTcl_GetCommandInfoFromToken\fR, or \fBTcl_SetCommandInfoFromToken\fR to manipulate the definition of the command. The \fIobjc\fR and \fIobjv\fR parameters designate the final parameter count and parameter vector that will be passed to the command, and have had all substitutions performed. .PP The \fIobjProc\fR callback is expected to return a standard Tcl status return code. If this code is \fBTCL_OK\fR (the normal case), then the Tcl interpreter will invoke the command. Any other return code is treated as if the command returned that status, and the command is \fInot\fR invoked. .PP The \fIobjProc\fR callback must not modify \fIobjv\fR in any way. It is, however, permissible to change the command by calling \fBTcl_SetCommandTokenInfo\fR prior to returning. Any such change takes effect immediately, and the command is invoked with the new information. .PP Tracing will only occur for commands at nesting level less than or equal to the \fIlevel\fR parameter (i.e. the \fIlevel\fR parameter to \fIobjProc\fR will always be less than or equal to the \fIlevel\fR parameter to \fBTcl_CreateTrace\fR). .PP Tracing has a significant effect on runtime performance because it causes the bytecode compiler to refrain from generating in-line code for Tcl commands such as \fBif\fR and \fBwhile\fR in order that they may be traced. If traces for the built-in commands are not required, the \fIflags\fR parameter may be set to the constant value \fBTCL_ALLOW_INLINE_COMPILATION\fR. In this case, traces on built-in commands may or may not result in trace callbacks, depending on the state of the interpreter, but run-time performance will be improved significantly. (This functionality is desirable, for example, when using \fBTcl_CreateObjTrace\fR to implement an execution time profiler.) .PP Calls to \fIobjProc\fR will be made by the Tcl parser immediately before it calls the command procedure for the command (\fIcmdProc\fR). This occurs after argument parsing and substitution, so tracing for substituted commands occurs before tracing of the commands containing the substitutions. If there is a syntax error in a command, or if there is no command procedure associated with a command name, then no tracing will occur for that command. If a string passed to Tcl_Eval contains multiple commands (bracketed, or on different lines) then multiple calls to \fIobjProc\fR will occur, one for each command. .PP \fBTcl_DeleteTrace\fR removes a trace, so that no future calls will be made to the procedure associated with the trace. After \fBTcl_DeleteTrace\fR returns, the caller should never again use the \fItrace\fR token. .PP When \fBTcl_DeleteTrace\fR is called, the interpreter invokes the \fIdeleteProc\fR that was passed as a parameter to \fBTcl_CreateObjTrace\fR. The \fIdeleteProc\fR must match the type, \fBTcl_CmdObjTraceDeleteProc\fR: .PP .CS typedef void \fBTcl_CmdObjTraceDeleteProc\fR( \fBClientData\fR \fIclientData\fR); .CE .PP The \fIclientData\fR parameter will be the same as the \fIclientData\fR parameter that was originally passed to \fBTcl_CreateObjTrace\fR. .PP \fBTcl_CreateTrace\fR is an alternative interface for command tracing, \fInot recommended for new applications\fR. It is provided for backward compatibility with code that was developed for older versions of the Tcl interpreter. It is similar to \fBTcl_CreateObjTrace\fR, except that its \fIproc\fR parameter should have arguments and result that match the type \fBTcl_CmdTraceProc\fR: .PP .CS typedef void \fBTcl_CmdTraceProc\fR( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR, int \fIlevel\fR, char *\fIcommand\fR, Tcl_CmdProc *\fIcmdProc\fR, ClientData \fIcmdClientData\fR, int \fIargc\fR, const char *\fIargv\fR[]); .CE .PP The parameters to the \fIproc\fR callback are similar to those of the \fIobjProc\fR callback above. The \fIcommandToken\fR is replaced with \fIcmdProc\fR, a pointer to the (string-based) command procedure that will be invoked; and \fIcmdClientData\fR, the client data that will be passed to the procedure. The \fIobjc\fR parameter is replaced with an \fIargv\fR parameter, that gives the arguments to the command as character strings. \fIProc\fR must not modify the \fIcommand\fR or \fIargv\fR strings. .PP If a trace created with \fBTcl_CreateTrace\fR is in effect, inline compilation of Tcl commands such as \fBif\fR and \fBwhile\fR is always disabled. There is no notification when a trace created with \fBTcl_CreateTrace\fR is deleted. There is no way to be notified when the trace created by \fBTcl_CreateTrace\fR is deleted. There is no way for the \fIproc\fR associated with a call to \fBTcl_CreateTrace\fR to abort execution of \fIcommand\fR. .SH KEYWORDS command, create, delete, interpreter, trace tcl8.6.5/doc/license.terms0000644000175000017500000000431712663660066015040 0ustar sergeisergeiThis software is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. tcl8.6.5/doc/define.n0000644000175000017500000004141012663660065013745 0ustar sergeisergei'\" '\" Copyright (c) 2007 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH define n 0.3 TclOO "TclOO Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME oo::define, oo::objdefine \- define and configure classes and objects .SH SYNOPSIS .nf package require TclOO \fBoo::define\fI class defScript\fR \fBoo::define\fI class subcommand arg\fR ?\fIarg ...\fR? \fBoo::objdefine\fI object defScript\fR \fBoo::objdefine\fI object subcommand arg\fR ?\fIarg ...\fR? .fi .BE .SH DESCRIPTION The \fBoo::define\fR command is used to control the configuration of classes, and the \fBoo::objdefine\fR command is used to control the configuration of objects (including classes as instance objects), with the configuration being applied to the entity named in the \fIclass\fR or the \fIobject\fR argument. Configuring a class also updates the configuration of all subclasses of the class and all objects that are instances of that class or which mix it in (as modified by any per-instance configuration). The way in which the configuration is done is controlled by either the \fIdefScript\fR argument or by the \fIsubcommand\fR and following \fIarg\fR arguments; when the second is present, it is exactly as if all the arguments from \fIsubcommand\fR onwards are made into a list and that list is used as the \fIdefScript\fR argument. .SS "CONFIGURING CLASSES" .PP The following commands are supported in the \fIdefScript\fR for \fBoo::define\fR, each of which may also be used in the \fIsubcommand\fR form: .TP \fBconstructor\fI argList bodyScript\fR . This creates or updates the constructor for a class. The formal arguments to the constructor (defined using the same format as for the Tcl \fBproc\fR command) will be \fIargList\fR, and the body of the constructor will be \fIbodyScript\fR. When the body of the constructor is evaluated, the current namespace of the constructor will be a namespace that is unique to the object being constructed. Within the constructor, the \fBnext\fR command should be used to call the superclasses' constructors. If \fIbodyScript\fR is the empty string, the constructor will be deleted. .TP \fBdeletemethod\fI name\fR ?\fIname ...\fR . This deletes each of the methods called \fIname\fR from a class. The methods must have previously existed in that class. Does not affect the superclasses of the class, nor does it affect the subclasses or instances of the class (except when they have a call chain through the class being modified). .TP \fBdestructor\fI bodyScript\fR . This creates or updates the destructor for a class. Destructors take no arguments, and the body of the destructor will be \fIbodyScript\fR. The destructor is called when objects of the class are deleted, and when called will have the object's unique namespace as the current namespace. Destructors should use the \fBnext\fR command to call the superclasses' destructors. Note that destructors are not called in all situations (e.g. if the interpreter is destroyed). If \fIbodyScript\fR is the empty string, the destructor will be deleted. .RS Note that errors during the evaluation of a destructor \fIare not returned\fR to the code that causes the destruction of an object. Instead, they are passed to the currently-defined \fBbgerror\fR handler. .RE .TP \fBexport\fI name \fR?\fIname ...\fR? . This arranges for each of the named methods, \fIname\fR, to be exported (i.e. usable outside an instance through the instance object's command) by the class being defined. Note that the methods themselves may be actually defined by a superclass; subclass exports override superclass visibility, and may in turn be overridden by instances. .TP \fBfilter\fR ?\fI\-slotOperation\fR? ?\fImethodName ...\fR? .VS This slot (see \fBSLOTTED DEFINITIONS\fR below) .VE sets or updates the list of method names that are used to guard whether method call to instances of the class may be called and what the method's results are. Each \fImethodName\fR names a single filtering method (which may be exposed or not exposed); it is not an error for a non-existent method to be named since they may be defined by subclasses. .VS By default, this slot works by appending. .VE .TP \fBforward\fI name cmdName \fR?\fIarg ...\fR? . This creates or updates a forwarded method called \fIname\fR. The method is defined be forwarded to the command called \fIcmdName\fR, with additional arguments, \fIarg\fR etc., added before those arguments specified by the caller of the method. The \fIcmdName\fR will always be resolved using the rules of the invoking objects' namespaces, i.e., when \fIcmdName\fR is not fully-qualified, the command will be searched for in each object's namespace, using the instances' namespace's path, or by looking in the global namespace. The method will be exported if \fIname\fR starts with a lower-case letter, and non-exported otherwise. .TP \fBmethod\fI name argList bodyScript\fR . This creates or updates a method that is implemented as a procedure-like script. The name of the method is \fIname\fR, the formal arguments to the method (defined using the same format as for the Tcl \fBproc\fR command) will be \fIargList\fR, and the body of the method will be \fIbodyScript\fR. When the body of the method is evaluated, the current namespace of the method will be a namespace that is unique to the current object. The method will be exported if \fIname\fR starts with a lower-case letter, and non-exported otherwise; this behavior can be overridden via \fBexport\fR and \fBunexport\fR. .TP \fBmixin\fR ?\fI\-slotOperation\fR? ?\fIclassName ...\fR? .VS This slot (see \fBSLOTTED DEFINITIONS\fR below) .VE sets or updates the list of additional classes that are to be mixed into all the instances of the class being defined. Each \fIclassName\fR argument names a single class that is to be mixed in. .VS By default, this slot works by replacement. .VE .TP \fBrenamemethod\fI fromName toName\fR . This renames the method called \fIfromName\fR in a class to \fItoName\fR. The method must have previously existed in the class, and \fItoName\fR must not previously refer to a method in that class. Does not affect the superclasses of the class, nor does it affect the subclasses or instances of the class (except when they have a call chain through the class being modified). Does not change the export status of the method; if it was exported before, it will be afterwards. .TP \fBself\fI subcommand arg ...\fR .TP \fBself\fI script\fR . This command is equivalent to calling \fBoo::objdefine\fR on the class being defined (see \fBCONFIGURING OBJECTS\fR below for a description of the supported values of \fIsubcommand\fR). It follows the same general pattern of argument handling as the \fBoo::define\fR and \fBoo::objdefine\fR commands, and .QW "\fBoo::define \fIcls \fBself \fIsubcommand ...\fR" operates identically to .QW "\fBoo::objdefine \fIcls subcommand ...\fR" . .TP \fBsuperclass\fR ?\fI\-slotOperation\fR? ?\fIclassName ...\fR? .VS This slot (see \fBSLOTTED DEFINITIONS\fR below) .VE allows the alteration of the superclasses of the class being defined. Each \fIclassName\fR argument names one class that is to be a superclass of the defined class. Note that objects must not be changed from being classes to being non-classes or vice-versa, that an empty parent class is equivalent to \fBoo::object\fR, and that the parent classes of \fBoo::object\fR and \fBoo::class\fR may not be modified. .VS By default, this slot works by replacement. .VE .TP \fBunexport\fI name \fR?\fIname ...\fR? . This arranges for each of the named methods, \fIname\fR, to be not exported (i.e. not usable outside the instance through the instance object's command, but instead just through the \fBmy\fR command visible in each object's context) by the class being defined. Note that the methods themselves may be actually defined by a superclass; subclass unexports override superclass visibility, and may be overridden by instance unexports. .TP \fBvariable\fR ?\fI\-slotOperation\fR? ?\fIname ...\fR? .VS This slot (see \fBSLOTTED DEFINITIONS\fR below) arranges for each of the named variables to be automatically made available in the methods, constructor and destructor declared by the class being defined. Each variable name must not have any namespace separators and must not look like an array access. All variables will be actually present in the instance object on which the method is executed. Note that the variable lists declared by a superclass or subclass are completely disjoint, as are variable lists declared by instances; the list of variable names is just for methods (and constructors and destructors) declared by this class. By default, this slot works by appending. .VE .SS "CONFIGURING OBJECTS" .PP The following commands are supported in the \fIdefScript\fR for \fBoo::objdefine\fR, each of which may also be used in the \fIsubcommand\fR form: .TP \fBclass\fI className\fR . This allows the class of an object to be changed after creation. Note that the class's constructors are not called when this is done, and so the object may well be in an inconsistent state unless additional configuration work is done. .TP \fBdeletemethod\fI name\fR ?\fIname ...\fR . This deletes each of the methods called \fIname\fR from an object. The methods must have previously existed in that object. Does not affect the classes that the object is an instance of. .TP \fBexport\fI name \fR?\fIname ...\fR? . This arranges for each of the named methods, \fIname\fR, to be exported (i.e. usable outside the object through the object's command) by the object being defined. Note that the methods themselves may be actually defined by a class or superclass; object exports override class visibility. .TP \fBfilter\fR ?\fI\-slotOperation\fR? ?\fImethodName ...\fR? .VS This slot (see \fBSLOTTED DEFINITIONS\fR below) .VE sets or updates the list of method names that are used to guard whether a method call to the object may be called and what the method's results are. Each \fImethodName\fR names a single filtering method (which may be exposed or not exposed); it is not an error for a non-existent method to be named. Note that the actual list of filters also depends on the filters set upon any classes that the object is an instance of. .VS By default, this slot works by appending. .VE .TP \fBforward\fI name cmdName \fR?\fIarg ...\fR? . This creates or updates a forwarded object method called \fIname\fR. The method is defined be forwarded to the command called \fIcmdName\fR, with additional arguments, \fIarg\fR etc., added before those arguments specified by the caller of the method. Forwarded methods should be deleted using the \fBmethod\fR subcommand. The method will be exported if \fIname\fR starts with a lower-case letter, and non-exported otherwise. .TP \fBmethod\fI name argList bodyScript\fR . This creates, updates or deletes an object method. The name of the method is \fIname\fR, the formal arguments to the method (defined using the same format as for the Tcl \fBproc\fR command) will be \fIargList\fR, and the body of the method will be \fIbodyScript\fR. When the body of the method is evaluated, the current namespace of the method will be a namespace that is unique to the object. The method will be exported if \fIname\fR starts with a lower-case letter, and non-exported otherwise. .TP \fBmixin\fR ?\fI\-slotOperation\fR? ?\fIclassName ...\fR? .VS This slot (see \fBSLOTTED DEFINITIONS\fR below) .VE sets or updates a per-object list of additional classes that are to be mixed into the object. Each argument, \fIclassName\fR, names a single class that is to be mixed in. .VS By default, this slot works by replacement. .VE .TP \fBrenamemethod\fI fromName toName\fR . This renames the method called \fIfromName\fR in an object to \fItoName\fR. The method must have previously existed in the object, and \fItoName\fR must not previously refer to a method in that object. Does not affect the classes that the object is an instance of. Does not change the export status of the method; if it was exported before, it will be afterwards. .TP \fBunexport\fI name \fR?\fIname ...\fR? . This arranges for each of the named methods, \fIname\fR, to be not exported (i.e. not usable outside the object through the object's command, but instead just through the \fBmy\fR command visible in the object's context) by the object being defined. Note that the methods themselves may be actually defined by a class; instance unexports override class visibility. .TP \fBvariable\fR ?\fI\-slotOperation\fR? ?\fIname ...\fR? .VS This slot (see \fBSLOTTED DEFINITIONS\fR below) arranges for each of the named variables to be automatically made available in the methods declared by the object being defined. Each variable name must not have any namespace separators and must not look like an array access. All variables will be actually present in the object on which the method is executed. Note that the variable lists declared by the classes and mixins of which the object is an instance are completely disjoint; the list of variable names is just for methods declared by this object. By default, this slot works by appending. .SH "SLOTTED DEFINITIONS" Some of the configurable definitions of a class or object are \fIslotted definitions\fR. This means that the configuration is implemented by a slot object, that is an instance of the class \fBoo::Slot\fR, which manages a list of values (class names, variable names, etc.) that comprises the contents of the slot. The class defines three operations (as methods) that may be done on the slot: .VE .TP \fIslot\fR \fB\-append\fR ?\fImember ...\fR? .VS This appends the given \fImember\fR elements to the slot definition. .VE .TP \fIslot\fR \fB\-clear\fR .VS This sets the slot definition to the empty list. .VE .TP \fIslot\fR \fB\-set\fR ?\fImember ...\fR? .VS This replaces the slot definition with the given \fImember\fR elements. .PP A consequence of this is that any use of a slot's default operation where the first member argument begins with a hyphen will be an error. One of the above operations should be used explicitly in those circumstances. .SS "SLOT IMPLEMENTATION" Internally, slot objects also define a method \fB\-\-default\-operation\fR which is forwarded to the default operation of the slot (thus, for the class .QW \fBvariable\fR slot, this is forwarded to .QW "\fBmy \-append\fR" ), and these methods which provide the implementation interface: .VE .TP \fIslot\fR \fBGet\fR .VS Returns a list that is the current contents of the slot. This method must always be called from a stack frame created by a call to \fBoo::define\fR or \fBoo::objdefine\fR. .VE .TP \fIslot\fR \fBSet \fIelementList\fR .VS Sets the contents of the slot to the list \fIelementList\fR and returns the empty string. This method must always be called from a stack frame created by a call to \fBoo::define\fR or \fBoo::objdefine\fR. .PP The implementation of these methods is slot-dependent (and responsible for accessing the correct part of the class or object definition). Slots also have an unknown method handler to tie all these pieces together, and they hide their \fBdestroy\fR method so that it is not invoked inadvertently. It is \fIrecommended\fR that any user changes to the slot mechanism be restricted to defining new operations whose names start with a hyphen. .VE .SH EXAMPLES This example demonstrates how to use both forms of the \fBoo::define\fR and \fBoo::objdefine\fR commands (they work in the same way), as well as illustrating four of the subcommands of them. .PP .CS oo::class create c c create o \fBoo::define\fR c \fBmethod\fR foo {} { puts "world" } \fBoo::objdefine\fR o { \fBmethod\fR bar {} { my Foo "hello " my foo } \fBforward\fR Foo ::puts -nonewline \fBunexport\fR foo } o bar \fI\(-> prints "hello world"\fR o foo \fI\(-> error "unknown method foo"\fR o Foo Bar \fI\(-> error "unknown method Foo"\fR \fBoo::objdefine\fR o \fBrenamemethod\fR bar lollipop o lollipop \fI\(-> prints "hello world"\fR .CE .PP This example shows how additional classes can be mixed into an object. It also shows how \fBmixin\fR is a slot that supports appending: .PP .CS oo::object create inst inst m1 \fI\(-> error "unknown method m1"\fR inst m2 \fI\(-> error "unknown method m2"\fR oo::class create A { \fBmethod\fR m1 {} { puts "red brick" } } \fBoo::objdefine\fR inst { \fBmixin\fR A } inst m1 \fI\(-> prints "red brick"\fR inst m2 \fI\(-> error "unknown method m2"\fR oo::class create B { \fBmethod\fR m2 {} { puts "blue brick" } } \fBoo::objdefine\fR inst { \fBmixin -append\fR B } inst m1 \fI\(-> prints "red brick"\fR inst m2 \fI\(-> prints "blue brick"\fR .CE .SH "SEE ALSO" next(n), oo::class(n), oo::object(n) .SH KEYWORDS class, definition, method, object, slot .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: tcl8.6.5/doc/SetVar.30000644000175000017500000002407112663660065013630 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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_SetVar 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_SetVar2Ex, Tcl_SetVar, Tcl_SetVar2, Tcl_ObjSetVar2, Tcl_GetVar2Ex, Tcl_GetVar, Tcl_GetVar2, Tcl_ObjGetVar2, Tcl_UnsetVar, Tcl_UnsetVar2 \- manipulate Tcl variables .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * \fBTcl_SetVar2Ex\fR(\fIinterp, name1, name2, newValuePtr, flags\fR) .sp const char * \fBTcl_SetVar\fR(\fIinterp, varName, newValue, flags\fR) .sp const char * \fBTcl_SetVar2\fR(\fIinterp, name1, name2, newValue, flags\fR) .sp Tcl_Obj * \fBTcl_ObjSetVar2\fR(\fIinterp, part1Ptr, part2Ptr, newValuePtr, flags\fR) .sp Tcl_Obj * \fBTcl_GetVar2Ex\fR(\fIinterp, name1, name2, flags\fR) .sp const char * \fBTcl_GetVar\fR(\fIinterp, varName, flags\fR) .sp const char * \fBTcl_GetVar2\fR(\fIinterp, name1, name2, flags\fR) .sp Tcl_Obj * \fBTcl_ObjGetVar2\fR(\fIinterp, part1Ptr, part2Ptr, flags\fR) .sp int \fBTcl_UnsetVar\fR(\fIinterp, varName, flags\fR) .sp int \fBTcl_UnsetVar2\fR(\fIinterp, name1, name2, flags\fR) .SH ARGUMENTS .AS Tcl_Interp *newValuePtr .AP Tcl_Interp *interp in Interpreter containing variable. .AP "const char" *name1 in Contains the name of an array variable (if \fIname2\fR is non-NULL) or (if \fIname2\fR is NULL) either the name of a scalar variable or a complete name including both variable name and index. May include \fB::\fR namespace qualifiers to specify a variable in a particular namespace. .AP "const char" *name2 in If non-NULL, gives name of element within array; in this case \fIname1\fR must refer to an array variable. .AP Tcl_Obj *newValuePtr in Points to a Tcl value containing the new value for the variable. .AP int flags in OR-ed combination of bits providing additional information. See below for valid values. .AP "const char" *varName in Name of variable. May include \fB::\fR namespace qualifiers to specify a variable in a particular namespace. May refer to a scalar variable or an element of an array. .AP "const char" *newValue in New value for variable, specified as a null-terminated string. A copy of this value is stored in the variable. .AP Tcl_Obj *part1Ptr in Points to a Tcl value containing the variable's name. The name may include a series of \fB::\fR namespace qualifiers to specify a variable in a particular namespace. May refer to a scalar variable or an element of an array variable. .AP Tcl_Obj *part2Ptr in If non-NULL, points to a value containing the name of an element within an array and \fIpart1Ptr\fR must refer to an array variable. .BE .SH DESCRIPTION .PP These procedures are used to create, modify, read, and delete Tcl variables from C code. .PP \fBTcl_SetVar2Ex\fR, \fBTcl_SetVar\fR, \fBTcl_SetVar2\fR, and \fBTcl_ObjSetVar2\fR will create a new variable or modify an existing one. These procedures set the given variable to the value given by \fInewValuePtr\fR or \fInewValue\fR and return a pointer to the variable's new value, which is stored in Tcl's variable structure. \fBTcl_SetVar2Ex\fR and \fBTcl_ObjSetVar2\fR take the new value as a Tcl_Obj and return a pointer to a Tcl_Obj. \fBTcl_SetVar\fR and \fBTcl_SetVar2\fR take the new value as a string and return a string; they are usually less efficient than \fBTcl_ObjSetVar2\fR. Note that the return value may be different than the \fInewValuePtr\fR or \fInewValue\fR argument, due to modifications made by write traces. If an error occurs in setting the variable (e.g. an array variable is referenced without giving an index into the array) NULL is returned and an error message is left in \fIinterp\fR's result if the \fBTCL_LEAVE_ERR_MSG\fR \fIflag\fR bit is set. .PP \fBTcl_GetVar2Ex\fR, \fBTcl_GetVar\fR, \fBTcl_GetVar2\fR, and \fBTcl_ObjGetVar2\fR return the current value of a variable. The arguments to these procedures are treated in the same way as the arguments to the procedures described above. Under normal circumstances, the return value is a pointer to the variable's value. For \fBTcl_GetVar2Ex\fR and \fBTcl_ObjGetVar2\fR the value is returned as a pointer to a Tcl_Obj. For \fBTcl_GetVar\fR and \fBTcl_GetVar2\fR the value is returned as a string; this is usually less efficient, so \fBTcl_GetVar2Ex\fR or \fBTcl_ObjGetVar2\fR are preferred. If an error occurs while reading the variable (e.g. the variable does not exist or an array element is specified for a scalar variable), then NULL is returned and an error message is left in \fIinterp\fR's result if the \fBTCL_LEAVE_ERR_MSG\fR \fIflag\fR bit is set. .PP \fBTcl_UnsetVar\fR and \fBTcl_UnsetVar2\fR may be used to remove a variable, so that future attempts to read the variable will return an error. The arguments to these procedures are treated in the same way as the arguments to the procedures above. If the variable is successfully removed then \fBTCL_OK\fR is returned. If the variable cannot be removed because it does not exist then \fBTCL_ERROR\fR is returned and an error message is left in \fIinterp\fR's result if the \fBTCL_LEAVE_ERR_MSG\fR \fIflag\fR bit is set. If an array element is specified, the given element is removed but the array remains. If an array name is specified without an index, then the entire array is removed. .PP The name of a variable may be specified to these procedures in four ways: .IP [1] If \fBTcl_SetVar\fR, \fBTcl_GetVar\fR, or \fBTcl_UnsetVar\fR is invoked, the variable name is given as a single string, \fIvarName\fR. If \fIvarName\fR contains an open parenthesis and ends with a close parenthesis, then the value between the parentheses is treated as an index (which can have any string value) and the characters before the first open parenthesis are treated as the name of an array variable. If \fIvarName\fR does not have parentheses as described above, then the entire string is treated as the name of a scalar variable. .IP [2] If the \fIname1\fR and \fIname2\fR arguments are provided and \fIname2\fR is non-NULL, then an array element is specified and the array name and index have already been separated by the caller: \fIname1\fR contains the name and \fIname2\fR contains the index. An error is generated if \fIname1\fR contains an open parenthesis and ends with a close parenthesis (array element) and \fIname2\fR is non-NULL. .IP [3] If \fIname2\fR is NULL, \fIname1\fR is treated just like \fIvarName\fR in case [1] above (it can be either a scalar or an array element variable name). .PP The \fIflags\fR argument may be used to specify any of several options to the procedures. It consists of an OR-ed combination of the following bits. .TP \fBTCL_GLOBAL_ONLY\fR Under normal circumstances the procedures look up variables as follows. If a procedure call is active in \fIinterp\fR, the variable is looked up at the current level of procedure call. Otherwise, the variable is looked up first in the current namespace, then in the global namespace. However, if this bit is set in \fIflags\fR then the variable is looked up only in the global namespace even if there is a procedure call active. If both \fBTCL_GLOBAL_ONLY\fR and \fBTCL_NAMESPACE_ONLY\fR are given, \fBTCL_GLOBAL_ONLY\fR is ignored. .TP \fBTCL_NAMESPACE_ONLY\fR If this bit is set in \fIflags\fR then the variable is looked up only in the current namespace; if a procedure is active its variables are ignored, and the global namespace is also ignored unless it is the current namespace. .TP \fBTCL_LEAVE_ERR_MSG\fR If an error is returned and this bit is set in \fIflags\fR, then an error message will be left in the interpreter's result, where it can be retrieved with \fBTcl_GetObjResult\fR or \fBTcl_GetStringResult\fR. If this flag bit is not set then no error message is left and the interpreter's result will not be modified. .TP \fBTCL_APPEND_VALUE\fR If this bit is set then \fInewValuePtr\fR or \fInewValue\fR is appended to the current value instead of replacing it. If the variable is currently undefined, then the bit is ignored. This bit is only used by the \fBTcl_Set*\fR procedures. .TP \fBTCL_LIST_ELEMENT\fR If this bit is set, then \fInewValue\fR is converted to a valid Tcl list element before setting (or appending to) the variable. A separator space is appended before the new list element unless the list element is going to be the first element in a list or sublist (i.e. the variable's current value is empty, or contains the single character .QW { , or ends in .QW " }" ). When appending, the original value of the variable must also be a valid list, so that the operation is the appending of a new list element onto a list. .PP \fBTcl_GetVar\fR and \fBTcl_GetVar2\fR return the current value of a variable. The arguments to these procedures are treated in the same way as the arguments to \fBTcl_SetVar\fR and \fBTcl_SetVar2\fR. Under normal circumstances, the return value is a pointer to the variable's value (which is stored in Tcl's variable structure and will not change before the next call to \fBTcl_SetVar\fR or \fBTcl_SetVar2\fR). \fBTcl_GetVar\fR and \fBTcl_GetVar2\fR use the flag bits \fBTCL_GLOBAL_ONLY\fR and \fBTCL_LEAVE_ERR_MSG\fR, both of which have the same meaning as for \fBTcl_SetVar\fR. If an error occurs in reading the variable (e.g. the variable does not exist or an array element is specified for a scalar variable), then NULL is returned. .PP \fBTcl_UnsetVar\fR and \fBTcl_UnsetVar2\fR may be used to remove a variable, so that future calls to \fBTcl_GetVar\fR or \fBTcl_GetVar2\fR for the variable will return an error. The arguments to these procedures are treated in the same way as the arguments to \fBTcl_GetVar\fR and \fBTcl_GetVar2\fR. If the variable is successfully removed then \fBTCL_OK\fR is returned. If the variable cannot be removed because it does not exist then \fBTCL_ERROR\fR is returned. If an array element is specified, the given element is removed but the array remains. If an array name is specified without an index, then the entire array is removed. .SH "SEE ALSO" Tcl_GetObjResult, Tcl_GetStringResult, Tcl_TraceVar .SH KEYWORDS array, get variable, interpreter, scalar, set, unset, value, variable tcl8.6.5/doc/seek.n0000644000175000017500000000546512663660065013454 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 seek n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME seek \- Change the access position for an open channel .SH SYNOPSIS \fBseek \fIchannelId offset \fR?\fIorigin\fR? .BE .SH DESCRIPTION .PP Changes the current access position for \fIchannelId\fR. .PP \fIChannelId\fR must be an identifier for an open channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. .PP The \fIoffset\fR and \fIorigin\fR arguments specify the position at which the next read or write will occur for \fIchannelId\fR. \fIOffset\fR must be an integer (which may be negative) and \fIorigin\fR must be one of the following: .TP 10 \fBstart\fR . The new access position will be \fIoffset\fR bytes from the start of the underlying file or device. .TP 10 \fBcurrent\fR . The new access position will be \fIoffset\fR bytes from the current access position; a negative \fIoffset\fR moves the access position backwards in the underlying file or device. .TP 10 \fBend\fR . The new access position will be \fIoffset\fR bytes from the end of the file or device. A negative \fIoffset\fR places the access position before the end of file, and a positive \fIoffset\fR places the access position after the end of file. .PP The \fIorigin\fR argument defaults to \fBstart\fR. .PP The command flushes all buffered output for the channel before the command returns, even if the channel is in non-blocking mode. It also discards any buffered and unread input. This command returns an empty string. An error occurs if this command is applied to channels whose underlying file or device does not support seeking. .PP Note that \fIoffset\fR values are byte offsets, not character offsets. Both \fBseek\fR and \fBtell\fR operate in terms of bytes, not characters, unlike \fBread\fR. .SH EXAMPLES .PP Read a file twice: .PP .CS set f [open file.txt] set data1 [read $f] \fBseek\fR $f 0 set data2 [read $f] close $f # $data1 eq $data2 if the file wasn't updated .CE .PP Read the last 10 bytes from a file: .PP .CS set f [open file.data] # This is guaranteed to work with binary data but # may fail with other encodings... fconfigure $f -translation binary \fBseek\fR $f -10 end set data [read $f 10] close $f .CE .SH "SEE ALSO" file(n), open(n), close(n), gets(n), tell(n), Tcl_StandardChannels(3) .SH KEYWORDS access position, file, seek '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/SetRecLmt.30000644000175000017500000000350612663660065014266 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_SetRecursionLimit 3 7.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_SetRecursionLimit \- set maximum allowable nesting depth in interpreter .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_SetRecursionLimit\fR(\fIinterp, depth\fR) .SH ARGUMENTS .AS Tcl_Interp *interp .AP Tcl_Interp *interp in Interpreter whose recursion limit is to be set. Must be greater than zero. .AP int depth in New limit for nested calls to \fBTcl_Eval\fR for \fIinterp\fR. .BE .SH DESCRIPTION .PP At any given time Tcl enforces a limit on the number of recursive calls that may be active for \fBTcl_Eval\fR and related procedures such as \fBTcl_GlobalEval\fR. Any call to \fBTcl_Eval\fR that exceeds this depth is aborted with an error. By default the recursion limit is 1000. .PP \fBTcl_SetRecursionLimit\fR may be used to change the maximum allowable nesting depth for an interpreter. The \fIdepth\fR argument specifies a new limit for \fIinterp\fR, and \fBTcl_SetRecursionLimit\fR returns the old limit. To read out the old limit without modifying it, invoke \fBTcl_SetRecursionLimit\fR with \fIdepth\fR equal to 0. .PP The \fBTcl_SetRecursionLimit\fR only sets the size of the Tcl call stack: it cannot by itself prevent stack overflows on the C stack being used by the application. If your machine has a limit on the size of the C stack, you may get stack overflows before reaching the limit set by \fBTcl_SetRecursionLimit\fR. If this happens, see if there is a mechanism in your system for increasing the maximum size of the C stack. .SH KEYWORDS nesting depth, recursion tcl8.6.5/doc/glob.n0000644000175000017500000002043012663660065013435 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 glob n 8.3 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME glob \- Return names of files that match patterns .SH SYNOPSIS \fBglob \fR?\fIswitches\fR? ?\fIpattern ...\fR? .BE .SH DESCRIPTION .PP This command performs file name .QW globbing in a fashion similar to the csh shell or bash shell. It returns a list of the files whose names match any of the \fIpattern\fR arguments. No particular order is guaranteed in the list, so if a sorted list is required the caller should use \fBlsort\fR. .SS OPTIONS .PP If the initial arguments to \fBglob\fR start with \fB\-\fR then they are treated as switches. The following switches are currently supported: .TP \fB\-directory\fR \fIdirectory\fR . Search for files which match the given patterns starting in the given \fIdirectory\fR. This allows searching of directories whose name contains glob-sensitive characters without the need to quote such characters explicitly. This option may not be used in conjunction with \fB\-path\fR, which is used to allow searching for complete file paths whose names may contain glob-sensitive characters. .TP \fB\-join\fR . The remaining pattern arguments, after option processing, are treated as a single pattern obtained by joining the arguments with directory separators. .TP \fB\-nocomplain\fR . Allows an empty list to be returned without error; without this switch an error is returned if the result list would be empty. .TP \fB\-path\fR \fIpathPrefix\fR . Search for files with the given \fIpathPrefix\fR where the rest of the name matches the given patterns. This allows searching for files with names similar to a given file (as opposed to a directory) even when the names contain glob-sensitive characters. This option may not be used in conjunction with \fB\-directory\fR. For example, to find all files with the same root name as $path, but differing extensions, you should use .QW "\fBglob \-path [file rootname $path] .*\fR" which will work even if \fB$path\fR contains numerous glob-sensitive characters. .TP \fB\-tails\fR . Only return the part of each file found which follows the last directory named in any \fB\-directory\fR or \fB\-path\fR path specification. Thus .QW "\fBglob \-tails \-directory $dir *\fR" is equivalent to .QW "\fBset pwd [pwd]; cd $dir; glob *; cd $pwd\fR" . For \fB\-path\fR specifications, the returned names will include the last path segment, so .QW "\fBglob \-tails \-path [file rootname ~/foo.tex] .*\fR" will return paths like \fBfoo.aux foo.bib foo.tex\fR etc. .TP \fB\-types\fR \fItypeList\fR . Only list files or directories which match \fItypeList\fR, where the items in the list have two forms. The first form is like the \-type option of the Unix find command: \fIb\fR (block special file), \fIc\fR (character special file), \fId\fR (directory), \fIf\fR (plain file), \fIl\fR (symbolic link), \fIp\fR (named pipe), or \fIs\fR (socket), where multiple types may be specified in the list. \fBGlob\fR will return all files which match at least one of the types given. Note that symbolic links will be returned both if \fB\-types l\fR is given, or if the target of a link matches the requested type. So, a link to a directory will be returned if \fB\-types d\fR was specified. .RS .PP The second form specifies types where all the types given must match. These are \fIr\fR, \fIw\fR, \fIx\fR as file permissions, and \fIreadonly\fR, \fIhidden\fR as special permission cases. On the Macintosh, MacOS types and creators are also supported, where any item which is four characters long is assumed to be a MacOS type (e.g. \fBTEXT\fR). Items which are of the form \fI{macintosh type XXXX}\fR or \fI{macintosh creator XXXX}\fR will match types or creators respectively. Unrecognized types, or specifications of multiple MacOS types/creators will signal an error. .PP The two forms may be mixed, so \fB\-types {d f r w}\fR will find all regular files OR directories that have both read AND write permissions. The following are equivalent: .PP .CS \fBglob \-type d *\fR \fBglob */\fR .CE .PP except that the first case doesn't return the trailing .QW / and is more platform independent. .RE .TP \fB\-\|\-\fR . Marks the end of switches. The argument following this one will be treated as a \fIpattern\fR even if it starts with a \fB\-\fR. .SS "GLOBBING PATTERNS" .PP The \fIpattern\fR arguments may contain any of the following special characters, which are a superset of those supported by \fBstring match\fR: .TP 10 \fB?\fR . Matches any single character. .TP 10 \fB*\fR . Matches any sequence of zero or more characters. .TP 10 \fB[\fIchars\fB]\fR . Matches any single character in \fIchars\fR. If \fIchars\fR contains a sequence of the form \fIa\fB\-\fIb\fR then any character between \fIa\fR and \fIb\fR (inclusive) will match. .TP 10 \fB\e\fIx\fR . Matches the character \fIx\fR. .TP 10 \fB{\fIa\fB,\fIb\fB,\fI...\fR} . Matches any of the sub-patterns \fIa\fR, \fIb\fR, etc. .PP On Unix, as with csh, a .QW . \| at the beginning of a file's name or just after a .QW / must be matched explicitly or with a {} construct, unless the \fB\-types hidden\fR flag is given (since .QW . \| at the beginning of a file's name indicates that it is hidden). On other platforms, files beginning with a .QW . \| are handled no differently to any others, except the special directories .QW . \| and .QW .. \| which must be matched explicitly (this is to avoid a recursive pattern like .QW "glob \-join * * * *" from recursing up the directory hierarchy as well as down). In addition, all .QW / characters must be matched explicitly. .LP If the first character in a \fIpattern\fR is .QW ~ then it refers to the home directory for the user whose name follows the .QW ~ . If the .QW ~ is followed immediately by .QW / then the value of the HOME environment variable is used. .PP The \fBglob\fR command differs from csh globbing in two ways. First, it does not sort its result list (use the \fBlsort\fR command if you want the list sorted). Second, \fBglob\fR only returns the names of files that actually exist; in csh no check for existence is made unless a pattern contains a ?, *, or [] construct. .LP When the \fBglob\fR command returns relative paths whose filenames start with a tilde .QW ~ (for example through \fBglob *\fR or \fBglob \-tails\fR, the returned list will not quote the tilde with .QW ./ . This means care must be taken if those names are later to be used with \fBfile join\fR, to avoid them being interpreted as absolute paths pointing to a given user's home directory. .SH "WINDOWS PORTABILITY ISSUES" .PP For Windows UNC names, the servername and sharename components of the path may not contain ?, *, or [] constructs. On Windows NT, if \fIpattern\fR is of the form .QW \fB~\fIusername\fB@\fIdomain\fR , it refers to the home directory of the user whose account information resides on the specified NT domain server. Otherwise, user account information is obtained from the local computer. .PP Since the backslash character has a special meaning to the glob command, glob patterns containing Windows style path separators need special care. The pattern .QW \fIC:\e\efoo\e\e*\fR is interpreted as .QW \fIC:\efoo\e*\fR where .QW \fI\ef\fR will match the single character .QW \fIf\fR and .QW \fI\e*\fR will match the single character .QW \fI*\fR and will not be interpreted as a wildcard character. One solution to this problem is to use the Unix style forward slash as a path separator. Windows style paths can be converted to Unix style paths with the command .QW "\fBfile join\fR \fB$path\fR" or .QW "\fBfile normalize\fR \fB$path\fR" . .SH EXAMPLES .PP Find all the Tcl files in the current directory: .PP .CS \fBglob\fR *.tcl .CE .PP Find all the Tcl files in the user's home directory, irrespective of what the current directory is: .PP .CS \fBglob\fR \-directory ~ *.tcl .CE .PP Find all subdirectories of the current directory: .PP .CS \fBglob\fR \-type d * .CE .PP Find all files whose name contains an .QW a , a .QW b or the sequence .QW cde : .PP .CS \fBglob\fR \-type f *{a,b,cde}* .CE .SH "SEE ALSO" file(n) .SH KEYWORDS exist, file, glob, pattern '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/lset.n0000644000175000017500000001060312663660065013462 0ustar sergeisergei'\" '\" Copyright (c) 2001 by Kevin B. Kenny . All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lset n 8.4 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lset \- Change an element in a list .SH SYNOPSIS \fBlset \fIvarName ?index ...? newValue\fR .BE .SH DESCRIPTION .PP The \fBlset\fR command accepts a parameter, \fIvarName\fR, which it interprets as the name of a variable containing a Tcl list. It also accepts zero or more \fIindices\fR into the list. The indices may be presented either consecutively on the command line, or grouped in a Tcl list and presented as a single argument. Finally, it accepts a new value for an element of \fIvarName\fR. .PP If no indices are presented, the command takes the form: .PP .CS \fBlset\fR varName newValue .CE .PP or .PP .CS \fBlset\fR varName {} newValue .CE .PP In this case, \fInewValue\fR replaces the old value of the variable \fIvarName\fR. .PP When presented with a single index, the \fBlset\fR command treats the content of the \fIvarName\fR variable as a Tcl list. It addresses the \fIindex\fR'th element in it (0 refers to the first element of the list). When interpreting the list, \fBlset\fR observes the same rules concerning braces and quotes and backslashes as the Tcl command interpreter; however, variable substitution and command substitution do not occur. The command constructs a new list in which the designated element is replaced with \fInewValue\fR. This new list is stored in the variable \fIvarName\fR, and is also the return value from the \fBlset\fR command. .PP If \fIindex\fR is negative or greater than the number of elements in \fI$varName\fR, then an error occurs. .PP If \fIindex\fR is equal to the number of elements in \fI$varName\fR, then the given element is appended to the list. .PP The interpretation of each simple \fIindex\fR value is the same as for the command \fBstring index\fR, supporting simple index arithmetic and indices relative to the end of the list. .PP If additional \fIindex\fR arguments are supplied, then each argument is used in turn to address an element within a sublist designated by the previous indexing operation, allowing the script to alter elements in sublists (or append elements to sublists). The command, .PP .CS \fBlset\fR a 1 2 newValue .CE .PP or .PP .CS \fBlset\fR a {1 2} newValue .CE .PP replaces element 2 of sublist 1 with \fInewValue\fR. .PP The integer appearing in each \fIindex\fR argument must be greater than or equal to zero. The integer appearing in each \fIindex\fR argument must be less than or equal to the length of the corresponding list. In other words, the \fBlset\fR command can change the size of a list only by appending an element (setting the one after the current end). If an index is outside the permitted range, an error is reported. .SH EXAMPLES .PP In each of these examples, the initial value of \fIx\fR is: .PP .CS set x [list [list a b c] [list d e f] [list g h i]] \fI\(-> {a b c} {d e f} {g h i}\fR .CE .PP The indicated return value also becomes the new value of \fIx\fR (except in the last case, which is an error which leaves the value of \fIx\fR unchanged.) .PP .CS \fBlset\fR x {j k l} \fI\(-> j k l\fR \fBlset\fR x {} {j k l} \fI\(-> j k l\fR \fBlset\fR x 0 j \fI\(-> j {d e f} {g h i}\fR \fBlset\fR x 2 j \fI\(-> {a b c} {d e f} j\fR \fBlset\fR x end j \fI\(-> {a b c} {d e f} j\fR \fBlset\fR x end-1 j \fI\(-> {a b c} j {g h i}\fR \fBlset\fR x 2 1 j \fI\(-> {a b c} {d e f} {g j i}\fR \fBlset\fR x {2 1} j \fI\(-> {a b c} {d e f} {g j i}\fR \fBlset\fR x {2 3} j \fI\(-> list index out of range\fR .CE .PP In the following examples, the initial value of \fIx\fR is: .PP .CS set x [list [list [list a b] [list c d]] \e [list [list e f] [list g h]]] \fI\(-> {{a b} {c d}} {{e f} {g h}}\fR .CE .PP The indicated return value also becomes the new value of \fIx\fR. .PP .CS \fBlset\fR x 1 1 0 j \fI\(-> {{a b} {c d}} {{e f} {j h}}\fR \fBlset\fR x {1 1 0} j \fI\(-> {{a b} {c d}} {{e f} {j h}}\fR .CE .SH "SEE ALSO" list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n), lsort(n), lrange(n), lreplace(n), string(n) .SH KEYWORDS element, index, list, replace, set '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/Utf.30000644000175000017500000002517612663660065013171 0ustar sergeisergei'\" '\" Copyright (c) 1997 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 Utf 3 "8.1" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_UniChar, Tcl_UniCharToUtf, Tcl_UtfToUniChar, Tcl_UniCharToUtfDString, Tcl_UtfToUniCharDString, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharNcasecmp, Tcl_UniCharCaseMatch, Tcl_UtfNcmp, Tcl_UtfNcasecmp, Tcl_UtfCharComplete, Tcl_NumUtfChars, Tcl_UtfFindFirst, Tcl_UtfFindLast, Tcl_UtfNext, Tcl_UtfPrev, Tcl_UniCharAtIndex, Tcl_UtfAtIndex, Tcl_UtfBackslash \- routines for manipulating UTF-8 strings .SH SYNOPSIS .nf \fB#include \fR .sp typedef ... \fBTcl_UniChar\fR; .sp int \fBTcl_UniCharToUtf\fR(\fIch, buf\fR) .sp int \fBTcl_UtfToUniChar\fR(\fIsrc, chPtr\fR) .sp char * \fBTcl_UniCharToUtfDString\fR(\fIuniStr, uniLength, dsPtr\fR) .sp Tcl_UniChar * \fBTcl_UtfToUniCharDString\fR(\fIsrc, length, dsPtr\fR) .sp int \fBTcl_UniCharLen\fR(\fIuniStr\fR) .sp int \fBTcl_UniCharNcmp\fR(\fIucs, uct, numChars\fR) .sp int \fBTcl_UniCharNcasecmp\fR(\fIucs, uct, numChars\fR) .sp int \fBTcl_UniCharCaseMatch\fR(\fIuniStr, uniPattern, nocase\fR) .sp int \fBTcl_UtfNcmp\fR(\fIcs, ct, numChars\fR) .sp int \fBTcl_UtfNcasecmp\fR(\fIcs, ct, numChars\fR) .sp int \fBTcl_UtfCharComplete\fR(\fIsrc, length\fR) .sp int \fBTcl_NumUtfChars\fR(\fIsrc, length\fR) .sp const char * \fBTcl_UtfFindFirst\fR(\fIsrc, ch\fR) .sp const char * \fBTcl_UtfFindLast\fR(\fIsrc, ch\fR) .sp const char * \fBTcl_UtfNext\fR(\fIsrc\fR) .sp const char * \fBTcl_UtfPrev\fR(\fIsrc, start\fR) .sp Tcl_UniChar \fBTcl_UniCharAtIndex\fR(\fIsrc, index\fR) .sp const char * \fBTcl_UtfAtIndex\fR(\fIsrc, index\fR) .sp int \fBTcl_UtfBackslash\fR(\fIsrc, readPtr, dst\fR) .SH ARGUMENTS .AS "const Tcl_UniChar" *uniPattern in/out .AP char *buf out Buffer in which the UTF-8 representation of the Tcl_UniChar is stored. At most \fBTCL_UTF_MAX\fR bytes are stored in the buffer. .AP int ch in The Tcl_UniChar to be converted or examined. .AP Tcl_UniChar *chPtr out Filled with the Tcl_UniChar represented by the head of the UTF-8 string. .AP "const char" *src in Pointer to a UTF-8 string. .AP "const char" *cs in Pointer to a UTF-8 string. .AP "const char" *ct in Pointer to a UTF-8 string. .AP "const Tcl_UniChar" *uniStr in A null-terminated Unicode string. .AP "const Tcl_UniChar" *ucs in A null-terminated Unicode string. .AP "const Tcl_UniChar" *uct in A null-terminated Unicode string. .AP "const Tcl_UniChar" *uniPattern in A null-terminated Unicode string. .AP int length in The length of the UTF-8 string in bytes (not UTF-8 characters). If negative, all bytes up to the first null byte are used. .AP int uniLength in The length of the Unicode string in characters. Must be greater than or equal to 0. .AP "Tcl_DString" *dsPtr in/out A pointer to a previously initialized \fBTcl_DString\fR. .AP "unsigned long" numChars in The number of characters to compare. .AP "const char" *start in Pointer to the beginning of a UTF-8 string. .AP int index in The index of a character (not byte) in the UTF-8 string. .AP int *readPtr out If non-NULL, filled with the number of bytes in the backslash sequence, including the backslash character. .AP char *dst out Buffer in which the bytes represented by the backslash sequence are stored. At most \fBTCL_UTF_MAX\fR bytes are stored in the buffer. .AP int nocase in Specifies whether the match should be done case-sensitive (0) or case-insensitive (1). .BE .SH DESCRIPTION .PP These routines convert between UTF-8 strings and Tcl_UniChars. A Tcl_UniChar is a Unicode character represented as an unsigned, fixed-size quantity. A UTF-8 character is a Unicode character represented as a varying-length sequence of up to \fBTCL_UTF_MAX\fR bytes. A multibyte UTF-8 sequence consists of a lead byte followed by some number of trail bytes. .PP \fBTCL_UTF_MAX\fR is the maximum number of bytes that it takes to represent one Unicode character in the UTF-8 representation. .PP \fBTcl_UniCharToUtf\fR stores the Tcl_UniChar \fIch\fR as a UTF-8 string in starting at \fIbuf\fR. The return value is the number of bytes stored in \fIbuf\fR. .PP \fBTcl_UtfToUniChar\fR reads one UTF-8 character starting at \fIsrc\fR and stores it as a Tcl_UniChar in \fI*chPtr\fR. The return value is the number of bytes read from \fIsrc\fR. The caller must ensure that the source buffer is long enough such that this routine does not run off the end and dereference non-existent or random memory; if the source buffer is known to be null-terminated, this will not happen. If the input is not in proper UTF-8 format, \fBTcl_UtfToUniChar\fR will store the first byte of \fIsrc\fR in \fI*chPtr\fR as a Tcl_UniChar between 0x0000 and 0x00ff and return 1. .PP \fBTcl_UniCharToUtfDString\fR converts the given Unicode string to UTF-8, storing the result in a previously initialized \fBTcl_DString\fR. You must specify \fIuniLength\fR, the length of the given Unicode string. The return value is a pointer to the UTF-8 representation of the Unicode string. Storage for the return value is appended to the end of the \fBTcl_DString\fR. .PP \fBTcl_UtfToUniCharDString\fR converts the given UTF-8 string to Unicode, storing the result in the previously initialized \fBTcl_DString\fR. In the argument \fIlength\fR, you may either specify the length of the given UTF-8 string in bytes or .QW \-1 , in which case \fBTcl_UtfToUniCharDString\fR uses \fBstrlen\fR to calculate the length. The return value is a pointer to the Unicode representation of the UTF-8 string. Storage for the return value is appended to the end of the \fBTcl_DString\fR. The Unicode string is terminated with a Unicode null character. .PP \fBTcl_UniCharLen\fR corresponds to \fBstrlen\fR for Unicode characters. It accepts a null-terminated Unicode string and returns the number of Unicode characters (not bytes) in that string. .PP \fBTcl_UniCharNcmp\fR and \fBTcl_UniCharNcasecmp\fR correspond to \fBstrncmp\fR and \fBstrncasecmp\fR, respectively, for Unicode characters. They accept two null-terminated Unicode strings and the number of characters to compare. Both strings are assumed to be at least \fInumChars\fR characters long. \fBTcl_UniCharNcmp\fR compares the two strings character-by-character according to the Unicode character ordering. It returns an integer greater than, equal to, or less than 0 if the first string is greater than, equal to, or less than the second string respectively. \fBTcl_UniCharNcasecmp\fR is the Unicode case insensitive version. .PP \fBTcl_UniCharCaseMatch\fR is the Unicode equivalent to \fBTcl_StringCaseMatch\fR. It accepts a null-terminated Unicode string, a Unicode pattern, and a boolean value specifying whether the match should be case sensitive and returns whether the string matches the pattern. .PP \fBTcl_UtfNcmp\fR corresponds to \fBstrncmp\fR for UTF-8 strings. It accepts two null-terminated UTF-8 strings and the number of characters to compare. (Both strings are assumed to be at least \fInumChars\fR characters long.) \fBTcl_UtfNcmp\fR compares the two strings character-by-character according to the Unicode character ordering. It returns an integer greater than, equal to, or less than 0 if the first string is greater than, equal to, or less than the second string respectively. .PP \fBTcl_UtfNcasecmp\fR corresponds to \fBstrncasecmp\fR for UTF-8 strings. It is similar to \fBTcl_UtfNcmp\fR except comparisons ignore differences in case when comparing upper, lower or title case 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 Tcl_UniChar 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 \fIsrc\fR. The length of the source string is \fIlength\fR bytes. If the length is negative, all bytes up to the first null byte are used. .PP \fBTcl_UtfFindFirst\fR corresponds to \fBstrchr\fR for UTF-8 strings. It returns a pointer to the first occurrence of the Tcl_UniChar \fIch\fR in the null-terminated UTF-8 string \fIsrc\fR. The null terminator is considered part of the UTF-8 string. .PP \fBTcl_UtfFindLast\fR corresponds to \fBstrrchr\fR for UTF-8 strings. It returns a pointer to the last occurrence of the Tcl_UniChar \fIch\fR in the null-terminated UTF-8 string \fIsrc\fR. The null terminator is considered part of the UTF-8 string. .PP 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. .PP Given \fIsrc\fR, a pointer to some location in a UTF-8 string (or to a null byte immediately following such a string), \fBTcl_UtfPrev\fR returns a pointer to the closest preceding byte that starts a UTF-8 character. This function will not back up to a position before \fIstart\fR, the start of the UTF-8 string. If \fIsrc\fR was already at \fIstart\fR, the return value will be \fIstart\fR. .PP \fBTcl_UniCharAtIndex\fR corresponds to a C string array dereference or the Pascal Ord() function. It returns the Tcl_UniChar represented at the specified character (not byte) \fIindex\fR in the UTF-8 string \fIsrc\fR. The source string must contain at least \fIindex\fR characters. Behavior is undefined if a negative \fIindex\fR is given. .PP \fBTcl_UtfAtIndex\fR returns a pointer to the specified character (not byte) \fIindex\fR in the UTF-8 string \fIsrc\fR. The source string must contain at least \fIindex\fR characters. This is equivalent to calling \fBTcl_UtfNext\fR \fIindex\fR times. If a negative \fIindex\fR is given, the return pointer points to the first character in the source string. .PP \fBTcl_UtfBackslash\fR is a utility procedure used by several of the Tcl commands. It parses a backslash sequence and stores the properly formed UTF-8 character represented by the backslash sequence in the output buffer \fIdst\fR. At most \fBTCL_UTF_MAX\fR bytes are stored in the buffer. \fBTcl_UtfBackslash\fR modifies \fI*readPtr\fR to contain the number of bytes in the backslash sequence, including the backslash character. The return value is the number of bytes stored in the output buffer. .PP See the \fBTcl\fR manual entry for information on the valid backslash sequences. All of the sequences described in the Tcl manual entry are supported by \fBTcl_UtfBackslash\fR. .SH KEYWORDS utf, unicode, backslash tcl8.6.5/doc/variable.n0000644000175000017500000000603012663660065014277 0ustar sergeisergei'\" '\" Copyright (c) 1993-1997 Bell Labs Innovations for Lucent Technologies '\" Copyright (c) 1997 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 variable n 8.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME variable \- create and initialize a namespace variable .SH SYNOPSIS \fBvariable \fR\fIname\fR .sp \fBvariable \fR?\fIname value...\fR? .BE .SH DESCRIPTION .PP This command is normally used within a \fBnamespace eval\fR command to create one or more variables within a namespace. Each variable \fIname\fR is initialized with \fIvalue\fR. The \fIvalue\fR for the last variable is optional. .PP If a variable \fIname\fR does not exist, it is created. In this case, if \fIvalue\fR is specified, it is assigned to the newly created variable. If no \fIvalue\fR is specified, the new variable is left undefined. If the variable already exists, it is set to \fIvalue\fR if \fIvalue\fR is specified or left unchanged if no \fIvalue\fR is given. Normally, \fIname\fR is unqualified (does not include the names of any containing namespaces), and the variable is created in the current namespace. If \fIname\fR includes any namespace qualifiers, the variable is created in the specified namespace. If the variable is not defined, it will be visible to the \fBnamespace which\fR command, but not to the \fBinfo exists\fR command. .PP If the \fBvariable\fR command is executed inside a Tcl procedure, it creates local variables linked to the corresponding namespace variables (and therefore these variables are listed by \fBinfo vars\fR.) In this way the \fBvariable\fR command resembles the \fBglobal\fR command, although the \fBglobal\fR command only links to variables in the global namespace. If any \fIvalue\fRs are given, they are used to modify the values of the associated namespace variables. If a namespace variable does not exist, it is created and optionally initialized. .PP A \fIname\fR argument cannot reference an element within an array. Instead, \fIname\fR should reference the entire array, and the initialization \fIvalue\fR should be left off. After the variable has been declared, elements within the array can be set using ordinary \fBset\fR or \fBarray\fR commands. .SH EXAMPLES .PP Create a variable in a namespace: .PP .CS namespace eval foo { \fBvariable\fR bar 12345 } .CE .PP Create an array in a namespace: .PP .CS namespace eval someNS { \fBvariable\fR someAry array set someAry { someName someValue otherName otherValue } } .CE .PP Access variables in namespaces from a procedure: .PP .CS namespace eval foo { proc spong {} { # Variable in this namespace \fBvariable\fR bar puts "bar is $bar" # Variable in another namespace \fBvariable\fR ::someNS::someAry parray someAry } } .CE .SH "SEE ALSO" global(n), namespace(n), upvar(n) .SH KEYWORDS global, namespace, procedure, variable tcl8.6.5/doc/unload.n0000644000175000017500000001626612663660065014010 0ustar sergeisergei'\" '\" Copyright (c) 2003 George Petasis . '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH unload n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME unload \- Unload machine code .SH SYNOPSIS \fBunload \fR?\fIswitches\fR? \fIfileName\fR .br \fBunload \fR?\fIswitches\fR? \fIfileName packageName\fR .br \fBunload \fR?\fIswitches\fR? \fIfileName packageName interp\fR .BE .SH DESCRIPTION .PP This command tries to unload shared libraries previously loaded 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 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. The \fIinterp\fR argument is the path name of the interpreter from which to unload the package (see the \fBinterp\fR manual entry for details); if \fIinterp\fR is omitted, it defaults to the interpreter in which the \fBunload\fR command was invoked. .PP If the initial arguments to \fBunload\fR start with \fB\-\fR then they are treated as switches. The following switches are currently supported: .TP \fB\-nocomplain\fR . Suppresses all error messages. If this switch is given, \fBunload\fR will never report an error. .TP \fB\-keeplibrary\fR . This switch will prevent \fBunload\fR from issuing the operating system call that will unload the library from the process. .TP \fB\-\|\-\fR . Marks the end of switches. The argument following this one will be treated as a \fIfileName\fR even if it starts with a \fB\-\fR. .SS "UNLOAD OPERATION" .PP When a file containing a shared library is loaded through the \fBload\fR command, Tcl associates two reference counts to the library file. The first counter shows how many times the library has been loaded into normal (trusted) interpreters while the second describes how many times the library has been loaded into safe interpreters. As a file containing a shared library can be loaded only once by Tcl (with the first \fBload\fR call on the file), these counters track how many interpreters use the library. Each subsequent call to \fBload\fR after the first simply increments the proper reference count. .PP \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 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 converted to upper case and all other letters are converted to lower case. For example, if \fIpackageName\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 of the initialization procedure will be \fIpkg\fB_SafeUnload\fR instead of \fIpkg\fB_Unload\fR. .PP If \fBunload\fR determines that a library is not unloadable (or unload functionality has been disabled during compilation), an error will be returned. If the library is unloadable, then \fBunload\fR will call the unload procedure. If the unload procedure returns \fBTCL_OK\fR, \fBunload\fR will proceed and decrease the proper reference count (depending on the target interpreter type). When both reference counts have reached 0, the library will be detached from the process. .SS "UNLOAD HOOK PROTOTYPE" .PP The unload procedure must match the following prototype: .PP .CS typedef int \fBTcl_PackageUnloadProc\fR( Tcl_Interp *\fIinterp\fR, int \fIflags\fR); .CE .PP The \fIinterp\fR argument identifies the interpreter from which the library is to be unloaded. The unload 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. In this case, the result of the \fBunload\fR command will be the result returned by the unload procedure. .PP The \fIflags\fR argument can be either \fBTCL_UNLOAD_DETACH_FROM_INTERPRETER\fR or \fBTCL_UNLOAD_DETACH_FROM_PROCESS\fR. In case the library will remain attached to the process after the unload procedure returns (i.e. because the library is used by other interpreters), \fBTCL_UNLOAD_DETACH_FROM_INTERPRETER\fR will be defined. However, if the library is used only by the target interpreter and the library will be detached from the application as soon as the unload procedure returns, the \fIflags\fR argument will be set to \fBTCL_UNLOAD_DETACH_FROM_PROCESS\fR. .SS NOTES .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 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. .SH "PORTABILITY ISSUES" .TP \fBUnix\fR\0\0\0\0\0 . Not all unix operating systems support library unloading. Under such an operating system \fBunload\fR returns an error (unless \fB\-nocomplain\fR has been specified). .SH BUGS .PP If the same file is \fBload\fRed by different \fIfileName\fRs, it will be loaded into the process's address space multiple times. The behavior of this varies from system to system (some systems may detect the redundant loads, others may not). In case a library has been silently detached by the operating system (and as a result Tcl thinks the library is still loaded), it may be dangerous to use \fBunload\fR on such a library (as the library will be completely detached from the application while some interpreters will continue to use it). .SH EXAMPLE .PP If an unloadable module in the file \fBfoobar.dll\fR had been loaded using the \fBload\fR command like this (on Windows): .PP .CS load c:/some/dir/foobar.dll .CE .PP then it would be unloaded like this: .PP .CS \fBunload\fR c:/some/dir/foobar.dll .CE .PP This allows a C code module to be installed temporarily into a long-running Tcl program and then removed again (either because it is no longer needed or because it is being updated with a new version) without having to shut down the overall Tcl process. .SH "SEE ALSO" info sharedlibextension, load(n), safe(n) .SH KEYWORDS binary code, unloading, safe interpreter, shared library .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/UniCharIsAlpha.30000644000175000017500000000506712663660065015223 0ustar sergeisergei'\" '\" Copyright (c) 1997 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_UniCharIsAlpha 3 "8.1" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_UniCharIsAlnum, Tcl_UniCharIsAlpha, Tcl_UniCharIsControl, Tcl_UniCharIsDigit, Tcl_UniCharIsGraph, Tcl_UniCharIsLower, Tcl_UniCharIsPrint, Tcl_UniCharIsPunct, Tcl_UniCharIsSpace, Tcl_UniCharIsUpper, Tcl_UniCharIsWordChar \- routines for classification of Tcl_UniChar characters .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_UniCharIsAlnum\fR(\fIch\fR) .sp int \fBTcl_UniCharIsAlpha\fR(\fIch\fR) .sp int \fBTcl_UniCharIsControl\fR(\fIch\fR) .sp int \fBTcl_UniCharIsDigit\fR(\fIch\fR) .sp int \fBTcl_UniCharIsGraph\fR(\fIch\fR) .sp int \fBTcl_UniCharIsLower\fR(\fIch\fR) .sp int \fBTcl_UniCharIsPrint\fR(\fIch\fR) .sp int \fBTcl_UniCharIsPunct\fR(\fIch\fR) .sp int \fBTcl_UniCharIsSpace\fR(\fIch\fR) .sp int \fBTcl_UniCharIsUpper\fR(\fIch\fR) .sp int \fBTcl_UniCharIsWordChar\fR(\fIch\fR) .SH ARGUMENTS .AS int ch .AP int ch in The Tcl_UniChar to be examined. .BE .SH DESCRIPTION .PP All of the routines described examine Tcl_UniChars and return a boolean value. A non-zero return value means that the character does belong to the character class associated with the called routine. The rest of this document just describes the character classes associated with the various routines. .PP Note: A Tcl_UniChar is a Unicode character represented as an unsigned, fixed-size quantity. .SH "CHARACTER CLASSES" .PP \fBTcl_UniCharIsAlnum\fR tests if the character is an alphanumeric Unicode character. .PP \fBTcl_UniCharIsAlpha\fR tests if the character is an alphabetic Unicode character. .PP \fBTcl_UniCharIsControl\fR tests if the character is a Unicode control character. .PP \fBTcl_UniCharIsDigit\fR tests if the character is a numeric Unicode character. .PP \fBTcl_UniCharIsGraph\fR tests if the character is any Unicode print character except space. .PP \fBTcl_UniCharIsLower\fR tests if the character is a lowercase Unicode character. .PP \fBTcl_UniCharIsPrint\fR tests if the character is a Unicode print character. .PP \fBTcl_UniCharIsPunct\fR tests if the character is a Unicode punctuation character. .PP \fBTcl_UniCharIsSpace\fR tests if the character is a whitespace Unicode character. .PP \fBTcl_UniCharIsUpper\fR tests if the character is an uppercase Unicode character. .PP \fBTcl_UniCharIsWordChar\fR tests if the character is alphanumeric or a connector punctuation mark. .SH KEYWORDS unicode, classification tcl8.6.5/doc/scan.n0000644000175000017500000002613212663660065013443 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2000 Scriptics Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH scan n 8.4 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME scan \- Parse string using conversion specifiers in the style of sscanf .SH SYNOPSIS \fBscan \fIstring format \fR?\fIvarName varName ...\fR? .BE .SH INTRODUCTION .PP This command parses substrings from an input string in a fashion similar to the ANSI C \fBsscanf\fR procedure and returns a count of the number of conversions performed, or -1 if the end of the input string is reached before any conversions have been performed. \fIString\fR gives the input to be parsed and \fIformat\fR indicates how to parse it, using \fB%\fR conversion specifiers as in \fBsscanf\fR. Each \fIvarName\fR gives the name of a variable; when a substring is scanned from \fIstring\fR that matches a conversion specifier, the substring is assigned to the corresponding variable. If no \fIvarName\fR variables are specified, then \fBscan\fR works in an inline manner, returning the data that would otherwise be stored in the variables as a list. In the inline case, an empty string is returned when the end of the input string is reached before any conversions have been performed. .SH "DETAILS ON SCANNING" .PP \fBScan\fR operates by scanning \fIstring\fR and \fIformat\fR together. If the next character in \fIformat\fR is a blank or tab then it matches any number of white space characters in \fIstring\fR (including zero). Otherwise, if it is not a \fB%\fR character then it must match the next character of \fIstring\fR. When a \fB%\fR is encountered in \fIformat\fR, it indicates the start of a conversion specifier. A conversion specifier contains up to four fields after the \fB%\fR: a XPG3 position specifier (or a \fB*\fR to indicate the converted value is to be discarded instead of assigned to any variable); a number indicating a maximum substring width; a size modifier; and a conversion character. All of these fields are optional except for the conversion character. The fields that are present must appear in the order given above. .PP When \fBscan\fR finds a conversion specifier in \fIformat\fR, it first skips any white-space characters in \fIstring\fR (unless the conversion character is \fB[\fR or \fBc\fR). Then it converts the next input characters according to the conversion specifier and stores the result in the variable given by the next argument to \fBscan\fR. .SS "OPTIONAL POSITIONAL SPECIFIER" .PP If the \fB%\fR is followed by a decimal number and a \fB$\fR, as in .QW \fB%2$d\fR , then the variable to use is not taken from the next sequential argument. Instead, it is taken from the argument indicated by the number, where 1 corresponds to the first \fIvarName\fR. If there are any positional specifiers in \fIformat\fR then all of the specifiers must be positional. Every \fIvarName\fR on the argument list must correspond to exactly one conversion specifier or an error is generated, or in the inline case, any position can be specified at most once and the empty positions will be filled in with empty strings. .SS "OPTIONAL SIZE MODIFIER" .PP The size modifier field is used only when scanning a substring into one of Tcl's integer values. The size modifier field dictates the integer range acceptable to be stored in a variable, or, for the inline case, in a position in the result list. The syntactically valid values for the size modifier are \fBh\fR, \fBL\fR, \fBl\fR, and \fBll\fR. The \fBh\fR size modifier value is equivalent to the absence of a size modifier in the the conversion specifier. Either one indicates the integer range to be stored is limited to the same range produced by the \fBint()\fR function of the \fBexpr\fR command. The \fBL\fR size modifier is equivalent to the \fBl\fR size modifier. Either one indicates the integer range to be stored is limited to the same range produced by the \fBwide()\fR function of the \fBexpr\fR command. The \fBll\fR size modifier indicates that the integer range to be stored is unlimited. .SS "MANDATORY CONVERSION CHARACTER" .PP The following conversion characters are supported: .TP \fBd\fR . The input substring must be a decimal integer. It is read in and the integer value is stored in the variable, truncated as required by the size modifier value. .TP \fBo\fR . The input substring must be an octal integer. It is read in and the integer value is stored in the variable, truncated as required by the size modifier value. .TP \fBx\fR or \fBX\fR . The input substring must be a hexadecimal integer. It is read in and the integer value is stored in the variable, truncated as required by the size modifier value. .TP \fBb\fR . The input substring must be a binary integer. It is read in and the integer value is stored in the variable, truncated as required by the size modifier value. .TP \fBu\fR . The input substring must be a decimal integer. The integer value is truncated as required by the size modifier value, and the corresponding unsigned value for that truncated range is computed and stored in the variable as a decimal string. The conversion makes no sense without reference to a truncation range, so the size modifier \fBll\fR is not permitted in combination with conversion character \fBu\fR. .TP \fBi\fR . The input substring must be an integer. The base (i.e. decimal, binary, octal, or hexadecimal) is determined in the same fashion as described in \fBexpr\fR. The integer value is stored in the variable, truncated as required by the size modifier value. .TP \fBc\fR . A single character is read in and its Unicode value is stored in the variable as an integer value. Initial white space is not skipped in this case, so the input substring may be a white-space character. .TP \fBs\fR . The input substring consists of all the characters up to the next white-space character; the characters are copied to the variable. .TP \fBe\fR or \fBf\fR or \fBg\fR or \fBE\fR or \fBG\fR . The input substring must be a floating-point number consisting of an optional sign, a string of decimal digits possibly containing a decimal point, and an optional exponent consisting of an \fBe\fR or \fBE\fR followed by an optional sign and a string of decimal digits. It is read in and stored in the variable as a floating-point value. .TP \fB[\fIchars\fB]\fR . The input substring consists of one or more characters in \fIchars\fR. The matching string is stored in the variable. If the first character between the brackets is a \fB]\fR then it is treated as part of \fIchars\fR rather than the closing bracket for the set. If \fIchars\fR contains a sequence of the form \fIa\fB\-\fIb\fR then any character between \fIa\fR and \fIb\fR (inclusive) will match. If the first or last character between the brackets is a \fB\-\fR, then it is treated as part of \fIchars\fR rather than indicating a range. .TP \fB[^\fIchars\fB]\fR . The input substring consists of one or more characters not in \fIchars\fR. The matching string is stored in the variable. If the character immediately following the \fB^\fR is a \fB]\fR then it is treated as part of the set rather than the closing bracket for the set. If \fIchars\fR contains a sequence of the form \fIa\fB\-\fIb\fR then any character between \fIa\fR and \fIb\fR (inclusive) will be excluded from the set. If the first or last character between the brackets is a \fB\-\fR, then it is treated as part of \fIchars\fR rather than indicating a range value. .TP \fBn\fR . No input is consumed from the input string. Instead, the total number of characters scanned from the input string so far is stored in the variable. .PP The number of characters read from the input for a conversion is the largest number that makes sense for that particular conversion (e.g. as many decimal digits as possible for \fB%d\fR, as many octal digits as possible for \fB%o\fR, and so on). The input substring for a given conversion terminates either when a white-space character is encountered or when the maximum substring width has been reached, whichever comes first. If a \fB*\fR is present in the conversion specifier then no variable is assigned and the next scan argument is not consumed. .SH "DIFFERENCES FROM ANSI SSCANF" .PP The behavior of the \fBscan\fR command is the same as the behavior of the ANSI C \fBsscanf\fR procedure except for the following differences: .IP [1] \fB%p\fR conversion specifier is not supported. .IP [2] For \fB%c\fR conversions a single character value is converted to a decimal string, which is then assigned to the corresponding \fIvarName\fR; no substring width may be specified for this conversion. .IP [3] The \fBh\fR modifier is always ignored and the \fBl\fR and \fBL\fR modifiers are ignored when converting real values (i.e. type \fBdouble\fR is used for the internal representation). The \fBll\fR modifier has no \fBsscanf\fR counterpart. .IP [4] If the end of the input string is reached before any conversions have been performed and no variables are given, an empty string is returned. .SH EXAMPLES .PP Convert a UNICODE character to its numeric value: .PP .CS set char "x" set value [\fBscan\fR $char %c] .CE .PP Parse a simple color specification of the form \fI#RRGGBB\fR using hexadecimal conversions with substring sizes: .PP .CS set string "#08D03F" \fBscan\fR $string "#%2x%2x%2x" r g b .CE .PP Parse a \fIHH:MM\fR time string, noting that this avoids problems with octal numbers by forcing interpretation as decimals (if we did not care, we would use the \fB%i\fR conversion instead): .PP .CS set string "08:08" ;# *Not* octal! if {[\fBscan\fR $string "%d:%d" hours minutes] != 2} { error "not a valid time string" } # We have to understand numeric ranges ourselves... if {$minutes < 0 || $minutes > 59} { error "invalid number of minutes" } .CE .PP Break a string up into sequences of non-whitespace characters (note the use of the \fB%n\fR conversion so that we get skipping over leading whitespace correct): .PP .CS set string " a string {with braced words} + leading space " set words {} while {[\fBscan\fR $string %s%n word length] == 2} { lappend words $word set string [string range $string $length end] } .CE .PP Parse a simple coordinate string, checking that it is complete by looking for the terminating character explicitly: .PP .CS set string "(5.2,-4e-2)" # Note that the spaces before the literal parts of # the scan pattern are significant, and that ")" is # the Unicode character \eu0029 if { [\fBscan\fR $string " (%f ,%f %c" x y last] != 3 || $last != 0x0029 } then { error "invalid coordinate string" } puts "X=$x, Y=$y" .CE .PP An interactive session demonstrating the truncation of integer values determined by size modifiers: .PP .CS \fI%\fR set tcl_platform(wordSize) 4 \fI%\fR scan 20000000000000000000 %d 2147483647 \fI%\fR scan 20000000000000000000 %ld 9223372036854775807 \fI%\fR scan 20000000000000000000 %lld 20000000000000000000 .CE .SH "SEE ALSO" format(n), sscanf(3) .SH KEYWORDS conversion specifier, parse, scan '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/ObjectType.30000644000175000017500000002431612663660065014476 0ustar sergeisergei'\" '\" Copyright (c) 1996-1997 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_ObjType 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_RegisterObjType, Tcl_GetObjType, Tcl_AppendAllObjTypes, Tcl_ConvertToType \- manipulate Tcl value types .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_RegisterObjType\fR(\fItypePtr\fR) .sp const Tcl_ObjType * \fBTcl_GetObjType\fR(\fItypeName\fR) .sp int \fBTcl_AppendAllObjTypes\fR(\fIinterp, objPtr\fR) .sp int \fBTcl_ConvertToType\fR(\fIinterp, objPtr, typePtr\fR) .SH ARGUMENTS .AS "const char" *typeName .AP "const Tcl_ObjType" *typePtr in Points to the structure containing information about the Tcl value type. This storage must live forever, typically by being statically allocated. .AP "const char" *typeName in The name of a Tcl value type that \fBTcl_GetObjType\fR should look up. .AP Tcl_Interp *interp in Interpreter to use for error reporting. .AP Tcl_Obj *objPtr in For \fBTcl_AppendAllObjTypes\fR, this points to the value onto which it appends the name of each value type as a list element. For \fBTcl_ConvertToType\fR, this points to a value that must have been the result of a previous call to \fBTcl_NewObj\fR. .BE .SH DESCRIPTION .PP The procedures in this man page manage Tcl value types (sometimes referred to as object types or \fBTcl_ObjType\fRs for historical reasons). They are used to register new value types, look up types, and force conversions from one type to another. .PP \fBTcl_RegisterObjType\fR registers a new Tcl value type in the table of all value types that \fBTcl_GetObjType\fR can look up by name. There are other value types supported by Tcl as well, which Tcl chooses not to register. Extensions can likewise choose to register the value types they create or not. The argument \fItypePtr\fR points to a Tcl_ObjType structure that describes the new type by giving its name and by supplying pointers to four procedures that implement the type. If the type table already contains a type with the same name as in \fItypePtr\fR, it is replaced with the new type. The Tcl_ObjType structure is described in the section \fBTHE TCL_OBJTYPE STRUCTURE\fR below. .PP \fBTcl_GetObjType\fR returns a pointer to the registered Tcl_ObjType with name \fItypeName\fR. It returns NULL if no type with that name is registered. .PP \fBTcl_AppendAllObjTypes\fR appends the name of each registered value type as a list element onto the Tcl value referenced by \fIobjPtr\fR. The return value is \fBTCL_OK\fR unless there was an error converting \fIobjPtr\fR to a list value; in that case \fBTCL_ERROR\fR is returned. .PP \fBTcl_ConvertToType\fR converts a value from one type to another if possible. It creates a new internal representation for \fIobjPtr\fR appropriate for the target type \fItypePtr\fR and sets its \fItypePtr\fR member as determined by calling the \fItypePtr->setFromAnyProc\fR routine. Any internal representation for \fIobjPtr\fR's old type is freed. If an error occurs during conversion, it returns \fBTCL_ERROR\fR and leaves an error message in the result value for \fIinterp\fR unless \fIinterp\fR is NULL. Otherwise, it returns \fBTCL_OK\fR. Passing a NULL \fIinterp\fR allows this procedure to be used as a test whether the conversion can be done (and in fact was done). .VS 8.5 .PP In many cases, the \fItypePtr->setFromAnyProc\fR routine will set \fIobjPtr->typePtr\fR to the argument value \fItypePtr\fR, but that is no longer guaranteed. The \fIsetFromAnyProc\fR is free to set the internal representation for \fIobjPtr\fR to make use of another related Tcl_ObjType, if it sees fit. .VE 8.5 .SH "THE TCL_OBJTYPE STRUCTURE" .PP Extension writers can define new value types by defining four procedures and initializing a Tcl_ObjType structure to describe the type. Extension writers may also pass a pointer to their Tcl_ObjType structure to \fBTcl_RegisterObjType\fR if they wish to permit other extensions to look up their Tcl_ObjType by name with the \fBTcl_GetObjType\fR routine. The \fBTcl_ObjType\fR structure is defined as follows: .PP .CS typedef struct Tcl_ObjType { const char *\fIname\fR; Tcl_FreeInternalRepProc *\fIfreeIntRepProc\fR; Tcl_DupInternalRepProc *\fIdupIntRepProc\fR; Tcl_UpdateStringProc *\fIupdateStringProc\fR; Tcl_SetFromAnyProc *\fIsetFromAnyProc\fR; } \fBTcl_ObjType\fR; .CE .SS "THE NAME FIELD" .PP The \fIname\fR member describes the name of the type, e.g. \fBint\fR. When a type is registered, this is the name used by callers of \fBTcl_GetObjType\fR to lookup the type. For unregistered types, the \fIname\fR field is primarily of value for debugging. The remaining four members are pointers to procedures called by the generic Tcl value code: .SS "THE SETFROMANYPROC FIELD" .PP The \fIsetFromAnyProc\fR member contains the address of a function called to create a valid internal representation from a value's string representation. .PP .CS typedef int \fBTcl_SetFromAnyProc\fR( Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIobjPtr\fR); .CE .PP If an internal representation cannot be created from the string, it returns \fBTCL_ERROR\fR and puts a message describing the error in the result value for \fIinterp\fR unless \fIinterp\fR is NULL. If \fIsetFromAnyProc\fR is successful, it stores the new internal representation, sets \fIobjPtr\fR's \fItypePtr\fR member to point to the \fBTcl_ObjType\fR struct corresponding to the new internal representation, and returns \fBTCL_OK\fR. Before setting the new internal representation, the \fIsetFromAnyProc\fR must free any internal representation of \fIobjPtr\fR's old type; it does this by calling the old type's \fIfreeIntRepProc\fR if it is not NULL. .PP As an example, the \fIsetFromAnyProc\fR for the built-in Tcl list type gets an up-to-date string representation for \fIobjPtr\fR by calling \fBTcl_GetStringFromObj\fR. It parses the string to verify it is in a valid list format and to obtain each element value in the list, and, if this succeeds, stores the list elements in \fIobjPtr\fR's internal representation and sets \fIobjPtr\fR's \fItypePtr\fR member to point to the list type's Tcl_ObjType structure. .PP Do not release \fIobjPtr\fR's old internal representation unless you replace it with a new one or reset the \fItypePtr\fR member to NULL. .PP The \fIsetFromAnyProc\fR member may be set to NULL, if the routines making use of the internal representation have no need to derive that internal representation from an arbitrary string value. However, in this case, passing a pointer to the type to \fBTcl_ConvertToType\fR will lead to a panic, so to avoid this possibility, the type should \fInot\fR be registered. .SS "THE UPDATESTRINGPROC FIELD" .PP The \fIupdateStringProc\fR member contains the address of a function called to create a valid string representation from a value's internal representation. .PP .CS typedef void \fBTcl_UpdateStringProc\fR( Tcl_Obj *\fIobjPtr\fR); .CE .PP \fIobjPtr\fR's \fIbytes\fR member is always NULL when it is called. It must always set \fIbytes\fR non-NULL before returning. We require the string representation's byte array to have a null after the last byte, at offset \fIlength\fR, and to have no null bytes before that; this allows string representations to be treated as conventional null character-terminated C strings. These restrictions are easily met by using Tcl's internal UTF encoding for the string representation, same as one would do for other Tcl routines accepting string values as arguments. Storage for the byte array must be allocated in the heap by \fBTcl_Alloc\fR or \fBckalloc\fR. Note that \fIupdateStringProc\fRs must allocate enough storage for the string's bytes and the terminating null byte. .PP The \fIupdateStringProc\fR for Tcl's built-in double type, for example, calls Tcl_PrintDouble to write to a buffer of size TCL_DOUBLE_SPACE, then allocates and copies the string representation to just enough space to hold it. A pointer to the allocated space is stored in the \fIbytes\fR member. .PP The \fIupdateStringProc\fR member may be set to NULL, if the routines making use of the internal representation are written so that the string representation is never invalidated. Failure to meet this obligation will lead to panics or crashes when \fBTcl_GetStringFromObj\fR or other similar routines ask for the string representation. .SS "THE DUPINTREPPROC FIELD" .PP The \fIdupIntRepProc\fR member contains the address of a function called to copy an internal representation from one value to another. .PP .CS typedef void \fBTcl_DupInternalRepProc\fR( Tcl_Obj *\fIsrcPtr\fR, Tcl_Obj *\fIdupPtr\fR); .CE .PP \fIdupPtr\fR's internal representation is made a copy of \fIsrcPtr\fR's internal representation. Before the call, \fIsrcPtr\fR's internal representation is valid and \fIdupPtr\fR's is not. \fIsrcPtr\fR's value type determines what copying its internal representation means. .PP For example, the \fIdupIntRepProc\fR for the Tcl integer type simply copies an integer. The built-in list type's \fIdupIntRepProc\fR uses a far more sophisticated scheme to continue sharing storage as much as it reasonably can. .SS "THE FREEINTREPPROC FIELD" .PP The \fIfreeIntRepProc\fR member contains the address of a function that is called when a value is freed. .PP .CS typedef void \fBTcl_FreeInternalRepProc\fR( Tcl_Obj *\fIobjPtr\fR); .CE .PP The \fIfreeIntRepProc\fR function can deallocate the storage for the value's internal representation and do other type-specific processing necessary when a value is freed. .PP For example, the list type's \fIfreeIntRepProc\fR respects the storage sharing scheme established by the \fIdupIntRepProc\fR so that it only frees storage when the last value sharing it is being freed. .PP The \fIfreeIntRepProc\fR member can be set to NULL to indicate that the internal representation does not require freeing. The \fIfreeIntRepProc\fR implementation must not access the \fIbytes\fR member of the value, since Tcl makes its own internal uses of that field during value deletion. The defined tasks for the \fIfreeIntRepProc\fR have no need to consult the \fIbytes\fR member. .SH "SEE ALSO" Tcl_NewObj(3), Tcl_DecrRefCount(3), Tcl_IncrRefCount(3) .SH KEYWORDS internal representation, value, value type, string representation, type conversion tcl8.6.5/doc/ByteArrObj.30000644000175000017500000001004712663660065014425 0ustar sergeisergei'\" '\" Copyright (c) 1997 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_ByteArrayObj 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_NewByteArrayObj, Tcl_SetByteArrayObj, Tcl_GetByteArrayFromObj, Tcl_SetByteArrayLength \- manipulate Tcl values as a arrays of bytes .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * \fBTcl_NewByteArrayObj\fR(\fIbytes, length\fR) .sp void \fBTcl_SetByteArrayObj\fR(\fIobjPtr, bytes, length\fR) .sp unsigned char * \fBTcl_GetByteArrayFromObj\fR(\fIobjPtr, lengthPtr\fR) .sp unsigned char * \fBTcl_SetByteArrayLength\fR(\fIobjPtr, length\fR) .SH ARGUMENTS .AS "const unsigned char" *lengthPtr in/out .AP "const unsigned char" *bytes in The array of bytes used to initialize or set a byte-array value. May be NULL even if \fIlength\fR is non-zero. .AP int length in The length of the array of bytes. It must be >= 0. .AP Tcl_Obj *objPtr in/out For \fBTcl_SetByteArrayObj\fR, this points to the value to be converted to byte-array type. For \fBTcl_GetByteArrayFromObj\fR and \fBTcl_SetByteArrayLength\fR, this points to the value from which to get the byte-array value; if \fIobjPtr\fR does not already point to a byte-array value, it will be converted to one. .AP int *lengthPtr out If non-NULL, filled with the length of the array of bytes in the value. .BE .SH DESCRIPTION .PP These procedures are used to create, modify, and read Tcl byte-array values from C code. Byte-array values are typically used to hold the results of binary IO operations or data structures created with the \fBbinary\fR command. In Tcl, an array of bytes is not equivalent to a string. Conceptually, a string is an array of Unicode characters, while a byte-array is an array of 8-bit quantities with no implicit meaning. Accessor functions are provided to get the string representation of a byte-array or to convert an arbitrary value to a byte-array. Obtaining the string representation of a byte-array value (by calling \fBTcl_GetStringFromObj\fR) produces a properly formed UTF-8 sequence with a one-to-one mapping between the bytes in the internal representation and the UTF-8 characters in the string representation. .PP \fBTcl_NewByteArrayObj\fR and \fBTcl_SetByteArrayObj\fR will create a new value of byte-array type or modify an existing value to have a byte-array type. Both of these procedures set the value's type to be byte-array and set the value's internal representation to a copy of the array of bytes given by \fIbytes\fR. \fBTcl_NewByteArrayObj\fR returns a pointer to a newly allocated value with a reference count of zero. \fBTcl_SetByteArrayObj\fR invalidates any old string representation and, if the value is not already a byte-array value, frees any old internal representation. If \fIbytes\fR is NULL then the new byte array contains arbitrary values. .PP \fBTcl_GetByteArrayFromObj\fR converts a Tcl value to byte-array type and returns a pointer to the value's new internal representation as an array of bytes. The length of this array is stored in \fIlengthPtr\fR if \fIlengthPtr\fR is non-NULL. The storage for the array of bytes is owned by the value and should not be freed. The contents of the array may be modified by the caller only if the value is not shared and the caller invalidates the string representation. .PP \fBTcl_SetByteArrayLength\fR converts the Tcl value to byte-array type and changes the length of the value's internal representation as an array of bytes. If \fIlength\fR is greater than the space currently allocated for the array, the array is reallocated to the new length; the newly allocated bytes at the end of the array have arbitrary values. If \fIlength\fR is less than the space currently allocated for the array, the length of array is reduced to the new length. The return value is a pointer to the value's new array of bytes. .SH "SEE ALSO" Tcl_GetStringFromObj, Tcl_NewObj, Tcl_IncrRefCount, Tcl_DecrRefCount .SH KEYWORDS value, binary data, byte array, utf, unicode, internationalization tcl8.6.5/doc/lsort.n0000644000175000017500000001650712663660065013667 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 1999 Scriptics Corporation '\" Copyright (c) 2001 Kevin B. Kenny . All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lsort n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lsort \- Sort the elements of a list .SH SYNOPSIS \fBlsort \fR?\fIoptions\fR? \fIlist\fR .BE .SH DESCRIPTION .PP This command sorts the elements of \fIlist\fR, returning a new list in sorted order. The implementation of the \fBlsort\fR command uses the merge\-sort algorithm which is a stable sort that has O(n log n) performance characteristics. .PP By default ASCII sorting is used with the result returned in increasing order. However, any of the following options may be specified before \fIlist\fR to control the sorting process (unique abbreviations are accepted): .TP \fB\-ascii\fR . Use string comparison with Unicode code-point collation order (the name is for backward-compatibility reasons.) This is the default. .TP \fB\-dictionary\fR . Use dictionary-style comparison. This is the same as \fB\-ascii\fR except (a) case is ignored except as a tie-breaker and (b) if two strings contain embedded numbers, the numbers compare as integers, not characters. For example, in \fB\-dictionary\fR mode, \fBbigBoy\fR sorts between \fBbigbang\fR and \fBbigboy\fR, and \fBx10y\fR sorts between \fBx9y\fR and \fBx11y\fR. .TP \fB\-integer\fR . Convert list elements to integers and use integer comparison. .TP \fB\-real\fR . Convert list elements to floating-point values and use floating comparison. .TP \fB\-command\0\fIcommand\fR . Use \fIcommand\fR as a comparison command. To compare two elements, evaluate a Tcl script consisting of \fIcommand\fR with the two elements appended as additional arguments. The script should return an integer less than, equal to, or greater than zero if the first element is to be considered less than, equal to, or greater than the second, respectively. .TP \fB\-increasing\fR . Sort the list in increasing order .PQ smallest "items first" . This is the default. .TP \fB\-decreasing\fR . Sort the list in decreasing order .PQ largest "items first" . .TP \fB\-indices\fR . Return a list of indices into \fIlist\fR in sorted order instead of the values themselves. .TP \fB\-index\0\fIindexList\fR . If this option is specified, each of the elements of \fIlist\fR must itself be a proper Tcl sublist (unless \fB\-stride\fR is used). Instead of sorting based on whole sublists, \fBlsort\fR will extract the \fIindexList\fR'th element from each sublist (as if the overall element and the \fIindexList\fR were passed to \fBlindex\fR) and sort based on the given element. For example, .RS .PP .CS \fBlsort\fR -integer -index 1 \e {{First 24} {Second 18} {Third 30}} .CE .PP returns \fB{Second 18} {First 24} {Third 30}\fR, .PP '\" '\" This example is from the test suite! '\" .CS \fBlsort\fR -index end-1 \e {{a 1 e i} {b 2 3 f g} {c 4 5 6 d h}} .CE .PP returns \fB{c 4 5 6 d h} {a 1 e i} {b 2 3 f g}\fR, and .PP .CS \fBlsort\fR -index {0 1} { {{b i g} 12345} {{d e m o} 34512} {{c o d e} 54321} } .CE .PP returns \fB{{d e m o} 34512} {{b i g} 12345} {{c o d e} 54321}\fR (because \fBe\fR sorts before \fBi\fR which sorts before \fBo\fR.) This option is much more efficient than using \fB\-command\fR to achieve the same effect. .RE .TP \fB\-stride\0\fIstrideLength\fR . If this option is specified, the list is treated as consisting of groups of \fIstrideLength\fR elements and the groups are sorted by either their first element or, if the \fB\-index\fR option is used, by the element within each group given by the first index passed to \fB\-index\fR (which is then ignored by \fB\-index\fR). Elements always remain in the same position within their group. .RS .PP The list length must be an integer multiple of \fIstrideLength\fR, which in turn must be at least 2. .PP For example, .PP .CS \fBlsort\fR \-stride 2 {carrot 10 apple 50 banana 25} .CE .PP returns .QW "apple 50 banana 25 carrot 10" , and .PP .CS \fBlsort\fR \-stride 2 \-index 1 \-integer {carrot 10 apple 50 banana 25} .CE .PP returns .QW "carrot 10 banana 25 apple 50" . .RE .TP \fB\-nocase\fR . Causes comparisons to be handled in a case-insensitive manner. Has no effect if combined with the \fB\-dictionary\fR, \fB\-integer\fR, or \fB\-real\fR options. .TP \fB\-unique\fR . If this option is specified, then only the last set of duplicate elements found in the list will be retained. Note that duplicates are determined relative to the comparison used in the sort. Thus if \fB\-index 0\fR is used, \fB{1 a}\fR and \fB{1 b}\fR would be considered duplicates and only the second element, \fB{1 b}\fR, would be retained. .SH "NOTES" .PP The options to \fBlsort\fR only control what sort of comparison is used, and do not necessarily constrain what the values themselves actually are. This distinction is only noticeable when the list to be sorted has fewer than two elements. .PP The \fBlsort\fR command is reentrant, meaning it is safe to use as part of the implementation of a command used in the \fB\-command\fR option. .SH "EXAMPLES" .PP Sorting a list using ASCII sorting: .PP .CS \fI%\fR \fBlsort\fR {a10 B2 b1 a1 a2} B2 a1 a10 a2 b1 .CE .PP Sorting a list using Dictionary sorting: .PP .CS \fI%\fR \fBlsort\fR -dictionary {a10 B2 b1 a1 a2} a1 a2 a10 b1 B2 .CE .PP Sorting lists of integers: .PP .CS \fI%\fR \fBlsort\fR -integer {5 3 1 2 11 4} 1 2 3 4 5 11 \fI%\fR \fBlsort\fR -integer {1 2 0x5 7 0 4 -1} -1 0 1 2 4 0x5 7 .CE .PP Sorting lists of floating-point numbers: .PP .CS \fI%\fR \fBlsort\fR -real {5 3 1 2 11 4} 1 2 3 4 5 11 \fI%\fR \fBlsort\fR -real {.5 0.07e1 0.4 6e-1} 0.4 .5 6e-1 0.07e1 .CE .PP Sorting using indices: .PP .CS \fI%\fR # Note the space character before the c \fI%\fR \fBlsort\fR {{a 5} { c 3} {b 4} {e 1} {d 2}} { c 3} {a 5} {b 4} {d 2} {e 1} \fI%\fR \fBlsort\fR -index 0 {{a 5} { c 3} {b 4} {e 1} {d 2}} {a 5} {b 4} { c 3} {d 2} {e 1} \fI%\fR \fBlsort\fR -index 1 {{a 5} { c 3} {b 4} {e 1} {d 2}} {e 1} {d 2} { c 3} {b 4} {a 5} .CE .PP .VS 8.6 Sorting a dictionary: .PP .CS \fI%\fR set d [dict create c d a b h i f g c e] c e a b h i f g \fI%\fR \fBlsort\fR -stride 2 $d a b c e f g h i .CE .PP Sorting using striding and multiple indices: .PP .CS \fI%\fR # Note the first index value is relative to the group \fI%\fR \fBlsort\fR \-stride 3 \-index {0 1} \e {{Bob Smith} 25 Audi {Jane Doe} 40 Ford} {{Jane Doe} 40 Ford {Bob Smith} 25 Audi} .CE .VE 8.6 .PP Stripping duplicate values using sorting: .PP .CS \fI%\fR \fBlsort\fR -unique {a b c a b c a b c} a b c .CE .PP More complex sorting using a comparison function: .PP .CS \fI%\fR proc compare {a b} { set a0 [lindex $a 0] set b0 [lindex $b 0] if {$a0 < $b0} { return -1 } elseif {$a0 > $b0} { return 1 } return [string compare [lindex $a 1] [lindex $b 1]] } \fI%\fR \fBlsort\fR -command compare \e {{3 apple} {0x2 carrot} {1 dingo} {2 banana}} {1 dingo} {2 banana} {0x2 carrot} {3 apple} .CE .SH "SEE ALSO" list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n), lset(n), lrange(n), lreplace(n) .SH KEYWORDS element, list, order, sort '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/PrintDbl.30000644000175000017500000000356512663660065014147 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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_PrintDouble 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_PrintDouble \- Convert floating value to string .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_PrintDouble\fR(\fIinterp, value, dst\fR) .SH ARGUMENTS .AS Tcl_Interp *interp out .AP Tcl_Interp *interp in Before Tcl 8.0, the \fBtcl_precision\fR variable in this interpreter controlled the conversion. As of Tcl 8.0, this argument is ignored and the conversion is controlled by the \fBtcl_precision\fR variable that is now shared by all interpreters. .AP double value in Floating-point value to be converted. .AP char *dst out Where to store the string representing \fIvalue\fR. Must have at least \fBTCL_DOUBLE_SPACE\fR characters of storage. .BE .SH DESCRIPTION .PP \fBTcl_PrintDouble\fR generates a string that represents the value of \fIvalue\fR and stores it in memory at the location given by \fIdst\fR. It uses \fB%g\fR format to generate the string, with one special twist: the string is guaranteed to contain either a .QW . or an .QW e so that it does not look like an integer. Where \fB%g\fR would generate an integer with no decimal point, \fBTcl_PrintDouble\fR adds .QW .0 . .PP If the \fBtcl_precision\fR value is non-zero, the result will have precisely that many digits of significance. If the value is zero (the default), the result will have the fewest digits needed to represent the number in such a way that \fBTcl_NewDoubleObj\fR will generate the same number when presented with the given string. IEEE semantics of rounding to even apply to the conversion. .SH KEYWORDS conversion, double-precision, floating-point, string tcl8.6.5/doc/SourceRCFile.30000644000175000017500000000151712663660065014711 0ustar sergeisergei'\" '\" Copyright (c) 1998-2000 by Scriptics Corporation. '\" All rights reserved. '\" .TH Tcl_SourceRCFile 3 8.3 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_SourceRCFile \- source the Tcl rc file .SH SYNOPSIS .nf \fB#include \fR .sp void \fBTcl_SourceRCFile\fR(\fIinterp\fR) .SH ARGUMENTS .AS Tcl_Interp *interp .AP Tcl_Interp *interp in Tcl interpreter to source rc file into. .BE .SH DESCRIPTION .PP \fBTcl_SourceRCFile\fR is used to source the Tcl rc file at startup. It is typically invoked by Tcl_Main or Tk_Main. The name of the file sourced is obtained from the global variable \fBtcl_rcFileName\fR in the interpreter given by \fIinterp\fR. If this variable is not defined, or if the file it indicates cannot be found, no action is taken. .SH KEYWORDS application-specific initialization, main program, rc file tcl8.6.5/doc/concat.n0000644000175000017500000000312612663660065013764 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 concat n 8.3 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME concat \- Join lists together .SH SYNOPSIS \fBconcat\fI \fR?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP This command joins each of its arguments together with spaces after trimming leading and trailing white-space from each of them. If all of the arguments are lists, this has the same effect as concatenating them into a single list. It permits any number of arguments; if no \fIarg\fRs are supplied, the result is an empty string. .SH EXAMPLES Although \fBconcat\fR will concatenate lists, flattening them in the process (so giving the following interactive session): .PP .CS \fI%\fR \fBconcat\fR a b {c d e} {f {g h}} \fIa b c d e f {g h}\fR .CE .PP it will also concatenate things that are not lists, as can be seen from this session: .PP .CS \fI%\fR \fBconcat\fR " a b {c " d " e} f" \fIa b {c d e} f\fR .CE .PP Note also that the concatenation does not remove spaces from the middle of values, as can be seen here: .PP .CS \fI%\fR \fBconcat\fR "a b c" { d e f } \fIa b c d e f\fR .CE .PP (i.e., there are three spaces between each of the \fBa\fR, the \fBb\fR and the \fBc\fR). .SH "SEE ALSO" append(n), eval(n), join(n) .SH KEYWORDS concatenate, join, list '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/lindex.n0000644000175000017500000000641512663660065014004 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2001 by Kevin B. Kenny . All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lindex n 8.4 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lindex \- Retrieve an element from a list .SH SYNOPSIS \fBlindex \fIlist ?index ...?\fR .BE .SH DESCRIPTION .PP The \fBlindex\fR command accepts a parameter, \fIlist\fR, which it treats as a Tcl list. It also accepts zero or more \fIindices\fR into the list. The indices may be presented either consecutively on the command line, or grouped in a Tcl list and presented as a single argument. .PP If no indices are presented, the command takes the form: .PP .CS \fBlindex \fIlist\fR .CE .PP or .PP .CS \fBlindex \fIlist\fR {} .CE .PP In this case, the return value of \fBlindex\fR is simply the value of the \fIlist\fR parameter. .PP When presented with a single index, the \fBlindex\fR command treats \fIlist\fR as a Tcl list and returns the \fIindex\fR'th element from it (0 refers to the first element of the list). In extracting the element, \fBlindex\fR observes the same rules concerning braces and quotes and backslashes as the Tcl command interpreter; however, variable substitution and command substitution do not occur. If \fIindex\fR is negative or greater than or equal to the number of elements in \fIvalue\fR, then an empty string is returned. The interpretation of each simple \fIindex\fR value is the same as for the command \fBstring index\fR, supporting simple index arithmetic and indices relative to the end of the list. .PP If additional \fIindex\fR arguments are supplied, then each argument is used in turn to select an element from the previous indexing operation, allowing the script to select elements from sublists. The command, .PP .CS \fBlindex\fR $a 1 2 3 .CE .PP or .PP .CS \fBlindex\fR $a {1 2 3} .CE .PP is synonymous with .PP .CS \fBlindex\fR [\fBlindex\fR [\fBlindex\fR $a 1] 2] 3 .CE .SH EXAMPLES .PP Lists can be indexed into from either end: .PP .CS \fBlindex\fR {a b c} 0 \fI\(-> a\fR \fBlindex\fR {a b c} 2 \fI\(-> c\fR \fBlindex\fR {a b c} end \fI\(-> c\fR \fBlindex\fR {a b c} end-1 \fI\(-> b\fR .CE .PP Lists or sequences of indices allow selection into lists of lists: .PP .CS \fBlindex\fR {a b c} \fI\(-> a b c\fR \fBlindex\fR {a b c} {} \fI\(-> a b c\fR \fBlindex\fR {{a b c} {d e f} {g h i}} 2 1 \fI\(-> h\fR \fBlindex\fR {{a b c} {d e f} {g h i}} {2 1} \fI\(-> h\fR \fBlindex\fR {{{a b} {c d}} {{e f} {g h}}} 1 1 0 \fI\(-> g\fR \fBlindex\fR {{{a b} {c d}} {{e f} {g h}}} {1 1 0} \fI\(-> g\fR .CE .PP List indices may also perform limited computation, adding or subtracting fixed amounts from other indices: .PP .CS set idx 1 \fBlindex\fR {a b c d e f} $idx+2 \fI\(-> d\fR set idx 3 \fBlindex\fR {a b c d e f} $idx+2 \fI\(-> f\fR .CE .SH "SEE ALSO" list(n), lappend(n), linsert(n), llength(n), lsearch(n), lset(n), lsort(n), lrange(n), lreplace(n), string(n) .SH KEYWORDS element, index, list '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/pwd.n0000644000175000017500000000222312663660065013304 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 pwd n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME pwd \- Return the absolute path of the current working directory .SH SYNOPSIS \fBpwd\fR .BE .SH DESCRIPTION .PP Returns the absolute path name of the current working directory. .SH EXAMPLE .PP Sometimes it is useful to change to a known directory when running some external command using \fBexec\fR, but it is important to keep the application usually running in the directory that it was started in (unless the user specifies otherwise) since that minimizes user confusion. The way to do this is to save the current directory while the external command is being run: .PP .CS set tarFile [file normalize somefile.tar] set savedDir [\fBpwd\fR] cd /tmp exec tar -xf $tarFile cd $savedDir .CE .SH "SEE ALSO" file(n), cd(n), glob(n), filename(n) .SH KEYWORDS working directory tcl8.6.5/doc/SplitPath.30000644000175000017500000000652312663660065014336 0ustar sergeisergei'\" '\" Copyright (c) 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_SplitPath 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_SplitPath, Tcl_JoinPath, Tcl_GetPathType \- manipulate platform-dependent file paths .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_SplitPath\fR(\fIpath, argcPtr, argvPtr\fR) .sp char * \fBTcl_JoinPath\fR(\fIargc, argv, resultPtr\fR) .sp Tcl_PathType \fBTcl_GetPathType\fR(\fIpath\fR) .SH ARGUMENTS .AS "const char *const" ***argvPtr in/out .AP "const char" *path in File path in a form appropriate for the current platform (see the \fBfilename\fR manual entry for acceptable forms for path names). .AP int *argcPtr out Filled in with number of path elements in \fIpath\fR. .AP "const char" ***argvPtr out \fI*argvPtr\fR will be filled in with the address of an array of pointers to the strings that are the extracted elements of \fIpath\fR. There will be \fI*argcPtr\fR valid entries in the array, followed by a NULL entry. .AP int argc in Number of elements in \fIargv\fR. .AP "const char *const" *argv in Array of path elements to merge together into a single path. .AP Tcl_DString *resultPtr in/out A pointer to an initialized \fBTcl_DString\fR to which the result of \fBTcl_JoinPath\fR will be appended. .BE .SH DESCRIPTION .PP These procedures have been superseded by the Tcl-value-aware procedures in the \fBFileSystem\fR man page, which are more efficient. .PP These procedures may be used to disassemble and reassemble file paths in a platform independent manner: they provide C-level access to the same functionality as the \fBfile split\fR, \fBfile join\fR, and \fBfile pathtype\fR commands. .PP \fBTcl_SplitPath\fR breaks a path into its constituent elements, returning an array of pointers to the elements using \fIargcPtr\fR and \fIargvPtr\fR. The area of memory pointed to by \fI*argvPtr\fR is dynamically allocated; in addition to the array of pointers, it also holds copies of all the path elements. It is the caller's responsibility to free all of this storage. For example, suppose that you have called \fBTcl_SplitPath\fR with the following code: .PP .CS int argc; char *path; char **argv; \&... Tcl_SplitPath(string, &argc, &argv); .CE .PP Then you should eventually free the storage with a call like the following: .PP .CS Tcl_Free((char *) argv); .CE .PP \fBTcl_JoinPath\fR is the inverse of \fBTcl_SplitPath\fR: it takes a collection of path elements given by \fIargc\fR and \fIargv\fR and generates a result string that is a properly constructed path. The result string is appended to \fIresultPtr\fR. \fIResultPtr\fR must refer to an initialized \fBTcl_DString\fR. .PP If the result of \fBTcl_SplitPath\fR is passed to \fBTcl_JoinPath\fR, the result will refer to the same location, but may not be in the same form. This is because \fBTcl_SplitPath\fR and \fBTcl_JoinPath\fR eliminate duplicate path separators and return a normalized form for each platform. .PP \fBTcl_GetPathType\fR returns the type of the specified \fIpath\fR, where \fBTcl_PathType\fR is one of \fBTCL_PATH_ABSOLUTE\fR, \fBTCL_PATH_RELATIVE\fR, or \fBTCL_PATH_VOLUME_RELATIVE\fR. See the \fBfilename\fR manual entry for a description of the path types for each platform. .SH KEYWORDS file, filename, join, path, split, type tcl8.6.5/doc/split.n0000644000175000017500000000515512663660065013654 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 split n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME split \- Split a string into a proper Tcl list .SH SYNOPSIS \fBsplit \fIstring \fR?\fIsplitChars\fR? .BE .SH DESCRIPTION .PP Returns a list created by splitting \fIstring\fR at each character that is in the \fIsplitChars\fR argument. Each element of the result list will consist of the characters from \fIstring\fR that lie between instances of the characters in \fIsplitChars\fR. Empty list elements will be generated if \fIstring\fR contains adjacent characters in \fIsplitChars\fR, or if the first or last character of \fIstring\fR is in \fIsplitChars\fR. If \fIsplitChars\fR is an empty string then each character of \fIstring\fR becomes a separate element of the result list. \fISplitChars\fR defaults to the standard white-space characters. .SH EXAMPLES .PP Divide up a USENET group name into its hierarchical components: .PP .CS \fBsplit\fR "comp.lang.tcl" . \fI\(-> comp lang tcl\fR .CE .PP See how the \fBsplit\fR command splits on \fIevery\fR character in \fIsplitChars\fR, which can result in information loss if you are not careful: .PP .CS \fBsplit\fR "alpha beta gamma" "temp" \fI\(-> al {ha b} {} {a ga} {} a\fR .CE .PP Extract the list words from a string that is not a well-formed list: .PP .CS \fBsplit\fR "Example with {unbalanced brace character" \fI\(-> Example with \e{unbalanced brace character\fR .CE .PP Split a string into its constituent characters .PP .CS \fBsplit\fR "Hello world" {} \fI\(-> H e l l o { } w o r l d\fR .CE .SS "PARSING RECORD-ORIENTED FILES" .PP Parse a Unix /etc/passwd file, which consists of one entry per line, with each line consisting of a colon-separated list of fields: .PP .CS ## Read the file set fid [open /etc/passwd] set content [read $fid] close $fid ## Split into records on newlines set records [\fBsplit\fR $content "\en"] ## Iterate over the records foreach rec $records { ## Split into fields on colons set fields [\fBsplit\fR $rec ":"] ## Assign fields to variables and print some out... lassign $fields \e userName password uid grp longName homeDir shell puts "$longName uses [file tail $shell] for a login shell" } .CE .SH "SEE ALSO" join(n), list(n), string(n) .SH KEYWORDS list, split, string '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/next.n0000644000175000017500000001672412663660065013503 0ustar sergeisergei'\" '\" Copyright (c) 2007 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH next n 0.1 TclOO "TclOO Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME next, nextto \- invoke superclass method implementations .SH SYNOPSIS .nf package require TclOO \fBnext\fR ?\fIarg ...\fR? \fBnextto\fI class\fR ?\fIarg ...\fR? .fi .BE .SH DESCRIPTION .PP The \fBnext\fR command is used to call implementations of a method by a class, superclass or mixin that are overridden by the current method. It can only be used from within a method. It is also used within filters to indicate the point where a filter calls the actual implementation (the filter may decide to not go along the chain, and may process the results of going along the chain of methods as it chooses). The result of the \fBnext\fR command is the result of the next method in the method chain; if there are no further methods in the method chain, the result of \fBnext\fR will be an error. The arguments, \fIarg\fR, to \fBnext\fR are the arguments to pass to the next method in the chain. .PP The \fBnextto\fR command is the same as the \fBnext\fR command, except that it takes an additional \fIclass\fR argument that identifies a class whose implementation of the current method chain (see \fBinfo object\fR \fBcall\fR) should be used; the method implementation selected will be the one provided by the given class, and it must refer to an existing non-filter invocation that lies further along the chain than the current implementation. .SH "THE METHOD CHAIN" .PP When a method of an object is invoked, things happen in several stages: .IP [1] The structure of the object, its class, superclasses, filters, and mixins, are examined to build a \fImethod chain\fR, which contains a list of method implementations to invoke. .IP [2] The first method implementation on the chain is invoked. .IP [3] If that method implementation invokes the \fBnext\fR command, the next method implementation is invoked (with its arguments being those that were passed to \fBnext\fR). .IP [4] The result from the overall method call is the result from the outermost method implementation; inner method implementations return their results through \fBnext\fR. .IP [5] The method chain is cached for future use. .SS "METHOD SEARCH ORDER" .PP When constructing the method chain, method implementations are searched for in the following order: .IP [1] In the classes mixed into the object, in class traversal order. The list of mixins is checked in natural order. .IP [2] In the classes mixed into the classes of the object, with sources of mixing in being searched in class traversal order. Within each class, the list of mixins is processed in natural order. .IP [3] In the object itself. .IP [4] In the object's class. .IP [5] In the superclasses of the class, following each superclass in a depth-first fashion in the natural order of the superclass list. .PP Any particular method implementation always comes as \fIlate\fR in the resulting list of implementations as possible; this means that if some class, A, is both mixed into a class, B, and is also a superclass of B, the instances of B will always treat A as a superclass from the perspective of inheritance. This is true even when the multiple inheritance is processed indirectly. .SS FILTERS .PP When an object has a list of filter names set upon it, or is an instance of a class (or has mixed in a class) that has a list of filter names set upon it, before every invocation of any method the filters are processed. Filter implementations are found in class traversal order, as are the lists of filter names (each of which is traversed in natural list order). Explicitly invoking a method used as a filter will cause that method to be invoked twice, once as a filter and once as a normal method. .PP Each filter should decide for itself whether to permit the execution to go forward to the proper implementation of the method (which it does by invoking the \fBnext\fR command as filters are inserted into the front of the method call chain) and is responsible for returning the result of \fBnext\fR. .PP Filters are invoked when processing an invokation of the \fBunknown\fR method because of a failure to locate a method implementation, but \fInot\fR when invoking either constructors or destructors. (Note however that the \fBdestroy\fR method is a conventional method, and filters are invoked as normal when it is called.) .SH EXAMPLES .PP This example demonstrates how to use the \fBnext\fR command to call the (super)class's implementation of a method. The script: .PP .CS oo::class create theSuperclass { method example {args} { puts "in the superclass, args = $args" } } oo::class create theSubclass { superclass theSuperclass method example {args} { puts "before chaining from subclass, args = $args" \fBnext\fR a {*}$args b \fBnext\fR pureSynthesis puts "after chaining from subclass" } } theSubclass create obj oo::objdefine obj method example args { puts "per-object method, args = $args" \fBnext\fR x {*}$args y \fBnext\fR } obj example 1 2 3 .CE .PP prints the following: .PP .CS per-object method, args = 1 2 3 before chaining from subclass, args = x 1 2 3 y in the superclass, args = a x 1 2 3 y b in the superclass, args = pureSynthesis after chaining from subclass before chaining from subclass, args = in the superclass, args = a b in the superclass, args = pureSynthesis after chaining from subclass .CE .PP This example demonstrates how to build a simple cache class that applies memoization to all the method calls of the objects it is mixed into, and shows how it can make a difference to computation times: .PP .CS oo::class create cache { filter Memoize method Memoize args { \fI# Do not filter the core method implementations\fR if {[lindex [self target] 0] eq "::oo::object"} { return [\fBnext\fR {*}$args] } \fI# Check if the value is already in the cache\fR my variable ValueCache set key [self target],$args if {[info exist ValueCache($key)]} { return $ValueCache($key) } \fI# Compute value, insert into cache, and return it\fR return [set ValueCache($key) [\fBnext\fR {*}$args]] } method flushCache {} { my variable ValueCache unset ValueCache \fI# Skip the caching\fR return -level 2 "" } } oo::object create demo oo::objdefine demo { mixin cache method compute {a b c} { after 3000 \fI;# Simulate deep thought\fR return [expr {$a + $b * $c}] } method compute2 {a b c} { after 3000 \fI;# Simulate deep thought\fR return [expr {$a * $b + $c}] } } puts [demo compute 1 2 3] \fI\(-> prints "7" after delay\fR puts [demo compute2 4 5 6] \fI\(-> prints "26" after delay\fR puts [demo compute 1 2 3] \fI\(-> prints "7" instantly\fR puts [demo compute2 4 5 6] \fI\(-> prints "26" instantly\fR puts [demo compute 4 5 6] \fI\(-> prints "34" after delay\fR puts [demo compute 4 5 6] \fI\(-> prints "34" instantly\fR puts [demo compute 1 2 3] \fI\(-> prints "7" instantly\fR demo flushCache puts [demo compute 1 2 3] \fI\(-> prints "7" after delay\fR .CE .SH "SEE ALSO" oo::class(n), oo::define(n), oo::object(n), self(n) .SH KEYWORDS call, method, method chain .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: tcl8.6.5/doc/binary.n0000644000175000017500000010465612663660065014013 0ustar sergeisergei'\" '\" Copyright (c) 1997 by Sun Microsystems, Inc. '\" Copyright (c) 2008 by Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH binary n 8.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME binary \- Insert and extract fields from binary strings .SH SYNOPSIS .VS 8.6 \fBbinary decode \fIformat\fR ?\fI\-option value ...\fR? \fIdata\fR .br \fBbinary encode \fIformat\fR ?\fI\-option value ...\fR? \fIdata\fR .br .VE 8.6 \fBbinary format \fIformatString \fR?\fIarg arg ...\fR? .br \fBbinary scan \fIstring formatString \fR?\fIvarName varName ...\fR? .BE .SH DESCRIPTION .PP This command provides facilities for manipulating binary data. The subcommand \fBbinary format\fR creates a binary string from normal Tcl values. For example, given the values 16 and 22, on a 32-bit architecture, it might produce an 8-byte binary string consisting of two 4-byte integers, one for each of the numbers. The subcommand \fBbinary scan\fR, does the opposite: it extracts data from a binary string and returns it as ordinary Tcl string values. .VS 8.6 The \fBbinary encode\fR and \fBbinary decode\fR subcommands convert binary data to or from string encodings such as base64 (used in MIME messages for example). .VE 8.6 .PP Note that other operations on binary data, such as taking a subsequence of it, getting its length, or reinterpreting it as a string in some encoding, are done by other Tcl commands (respectively \fBstring range\fR, \fBstring length\fR and \fBencoding convertfrom\fR in the example cases). A binary string in Tcl is merely one where all the characters it contains are in the range \eu0000\-\eu00FF. .SH "BINARY ENCODE AND DECODE" .VS 8.6 .PP When encoding binary data as a readable string, the starting binary data is passed to the \fBbinary encode\fR command, together with the name of the encoding to use and any encoding-specific options desired. Data which has been encoded can be converted back to binary form using \fBbinary decode\fR. The following formats and options are supported. .TP \fBbase64\fR . The \fBbase64\fR binary encoding is commonly used in mail messages and XML documents, and uses mostly upper and lower case letters and digits. It has the distinction of being able to be rewrapped arbitrarily without losing information. .RS .PP During encoding, the following options are supported: .TP \fB\-maxlen \fIlength\fR . Indicates that the output should be split into lines of no more than \fIlength\fR characters. By default, lines are not split. .TP \fB\-wrapchar \fIcharacter\fR . Indicates that, when lines are split because of the \fB\-maxlen\fR option, \fIcharacter\fR should be used to separate lines. By default, this is a newline character, .QW \en . .PP During decoding, the following options are supported: .TP \fB\-strict\fR . Instructs the decoder to throw an error if it encounters whitespace characters. Otherwise it ignores them. .RE .TP \fBhex\fR . The \fBhex\fR binary encoding converts each byte to a pair of hexadecimal digits in big-endian form. .RS .PP No options are supported during encoding. During decoding, the following options are supported: .TP \fB\-strict\fR . Instructs the decoder to throw an error if it encounters whitespace characters. Otherwise it ignores them. .RE .TP \fBuuencode\fR . The \fBuuencode\fR binary encoding used to be common for transfer of data between Unix systems and on USENET, but is less common these days, having been largely superseded by the \fBbase64\fR binary encoding. .RS .PP During encoding, the following options are supported (though changing them may produce files that other implementations of decoders cannot process): .TP \fB\-maxlen \fIlength\fR . Indicates that the output should be split into lines of no more than \fIlength\fR characters. By default, lines are split every 61 characters, and this must be in the range 3 to 85 due to limitations in the encoding. .TP \fB\-wrapchar \fIcharacter\fR . Indicates that, when lines are split because of the \fB\-maxlen\fR option, \fIcharacter\fR should be used to separate lines. By default, this is a newline character, .QW \en . .PP During decoding, the following options are supported: .TP \fB\-strict\fR . Instructs the decoder to throw an error if it encounters unexpected whitespace characters. Otherwise it ignores them. .PP Note that neither the encoder nor the decoder handle the header and footer of the uuencode format. .RE .VE 8.6 .SH "BINARY FORMAT" .PP The \fBbinary format\fR command generates a binary string whose layout is specified by the \fIformatString\fR and whose contents come from the additional arguments. The resulting binary value is returned. .PP The \fIformatString\fR consists of a sequence of zero or more field specifiers separated by zero or more spaces. Each field specifier is a single type character followed by an optional flag character followed by an optional numeric \fIcount\fR. Most field specifiers consume one argument to obtain the value to be formatted. The type character specifies how the value is to be formatted. The \fIcount\fR typically indicates how many items of the specified type are taken from the value. If present, the \fIcount\fR is a non-negative decimal integer or \fB*\fR, which normally indicates that all of the items in the value are to be used. If the number of arguments does not match the number of fields in the format string that consume arguments, then an error is generated. The flag character is ignored for \fBbinary format\fR. .PP Here is a small example to clarify the relation between the field specifiers and the arguments: .CS \fBbinary format\fR d3d {1.0 2.0 3.0 4.0} 0.1 .CE .PP The first argument is a list of four numbers, but because of the count of 3 for the associated field specifier, only the first three will be used. The second argument is associated with the second field specifier. The resulting binary string contains the four numbers 1.0, 2.0, 3.0 and 0.1. .PP Each type-count pair moves an imaginary cursor through the binary data, storing bytes at the current position and advancing the cursor to just after the last byte stored. The cursor is initially at position 0 at the beginning of the data. The type may be any one of the following characters: .IP \fBa\fR 5 Stores a byte string of length \fIcount\fR in the output string. Every character is taken as modulo 256 (i.e. the low byte of every character is used, and the high byte discarded) so when storing character strings not wholly expressible using the characters \eu0000-\eu00ff, the \fBencoding convertto\fR command should be used first to change the string into an external representation if this truncation is not desired (i.e. if the characters are not part of the ISO 8859\-1 character set.) If \fIarg\fR has fewer than \fIcount\fR bytes, then additional zero bytes are used to pad out the field. If \fIarg\fR is longer than the specified length, the extra characters will be ignored. If \fIcount\fR is \fB*\fR, then all of the bytes in \fIarg\fR will be formatted. If \fIcount\fR is omitted, then one character will be formatted. For example, .RS .CS \fBbinary format\fR a7a*a alpha bravo charlie .CE will return a string equivalent to \fBalpha\e000\e000bravoc\fR, .CS \fBbinary format\fR a* [encoding convertto utf-8 \eu20ac] .CE will return a string equivalent to \fB\e342\e202\e254\fR (which is the UTF-8 byte sequence for a Euro-currency character) and .CS \fBbinary format\fR a* [encoding convertto iso8859-15 \eu20ac] .CE will return a string equivalent to \fB\e244\fR (which is the ISO 8859\-15 byte sequence for a Euro-currency character). Contrast these last two with: .CS \fBbinary format\fR a* \eu20ac .CE which returns a string equivalent to \fB\e254\fR (i.e. \fB\exac\fR) by truncating the high-bits of the character, and which is probably not what is desired. .RE .IP \fBA\fR 5 This form is the same as \fBa\fR except that spaces are used for padding instead of nulls. For example, .RS .CS \fBbinary format\fR A6A*A alpha bravo charlie .CE will return \fBalpha bravoc\fR. .RE .IP \fBb\fR 5 Stores a string of \fIcount\fR binary digits in low-to-high order within each byte in the output string. \fIArg\fR must contain a sequence of \fB1\fR and \fB0\fR characters. The resulting bytes are emitted in first to last order with the bits being formatted in low-to-high order within each byte. If \fIarg\fR has fewer than \fIcount\fR digits, then zeros will be used for the remaining bits. If \fIarg\fR has more than the specified number of digits, the extra digits will be ignored. If \fIcount\fR is \fB*\fR, then all of the digits in \fIarg\fR will be formatted. If \fIcount\fR is omitted, then one digit will be formatted. If the number of bits formatted does not end at a byte boundary, the remaining bits of the last byte will be zeros. For example, .RS .CS \fBbinary format\fR b5b* 11100 111000011010 .CE will return a string equivalent to \fB\ex07\ex87\ex05\fR. .RE .IP \fBB\fR 5 This form is the same as \fBb\fR except that the bits are stored in high-to-low order within each byte. For example, .RS .CS \fBbinary format\fR B5B* 11100 111000011010 .CE will return a string equivalent to \fB\exe0\exe1\exa0\fR. .RE .IP \fBH\fR 5 Stores a string of \fIcount\fR hexadecimal digits in high-to-low within each byte in the output string. \fIArg\fR must contain a sequence of characters in the set .QW 0123456789abcdefABCDEF . The resulting bytes are emitted in first to last order with the hex digits being formatted in high-to-low order within each byte. If \fIarg\fR has fewer than \fIcount\fR digits, then zeros will be used for the remaining digits. If \fIarg\fR has more than the specified number of digits, the extra digits will be ignored. If \fIcount\fR is \fB*\fR, then all of the digits in \fIarg\fR will be formatted. If \fIcount\fR is omitted, then one digit will be formatted. If the number of digits formatted does not end at a byte boundary, the remaining bits of the last byte will be zeros. For example, .RS .CS \fBbinary format\fR H3H*H2 ab DEF 987 .CE will return a string equivalent to \fB\exab\ex00\exde\exf0\ex98\fR. .RE .IP \fBh\fR 5 This form is the same as \fBH\fR except that the digits are stored in low-to-high order within each byte. This is seldom required. For example, .RS .CS \fBbinary format\fR h3h*h2 AB def 987 .CE will return a string equivalent to \fB\exba\ex00\exed\ex0f\ex89\fR. .RE .IP \fBc\fR 5 Stores one or more 8-bit integer values in the output string. If no \fIcount\fR is specified, then \fIarg\fR must consist of an integer value. If \fIcount\fR is specified, \fIarg\fR must consist of a list containing at least that many integers. The low-order 8 bits of each integer are stored as a one-byte value at the cursor position. If \fIcount\fR is \fB*\fR, then all of the integers in the list are formatted. If the number of elements in the list is greater than \fIcount\fR, then the extra elements are ignored. For example, .RS .CS \fBbinary format\fR c3cc* {3 -3 128 1} 260 {2 5} .CE will return a string equivalent to \fB\ex03\exfd\ex80\ex04\ex02\ex05\fR, whereas .CS \fBbinary format\fR c {2 5} .CE will generate an error. .RE .IP \fBs\fR 5 This form is the same as \fBc\fR except that it stores one or more 16-bit integers in little-endian byte order in the output string. The low-order 16-bits of each integer are stored as a two-byte value at the cursor position with the least significant byte stored first. For example, .RS .CS \fBbinary format\fR s3 {3 -3 258 1} .CE will return a string equivalent to \fB\ex03\ex00\exfd\exff\ex02\ex01\fR. .RE .IP \fBS\fR 5 This form is the same as \fBs\fR except that it stores one or more 16-bit integers in big-endian byte order in the output string. For example, .RS .CS \fBbinary format\fR S3 {3 -3 258 1} .CE will return a string equivalent to \fB\ex00\ex03\exff\exfd\ex01\ex02\fR. .RE .IP \fBt\fR 5 This form (mnemonically \fItiny\fR) is the same as \fBs\fR and \fBS\fR except that it stores the 16-bit integers in the output string in the native byte order of the machine where the Tcl script is running. To determine what the native byte order of the machine is, refer to the \fBbyteOrder\fR element of the \fBtcl_platform\fR array. .IP \fBi\fR 5 This form is the same as \fBc\fR except that it stores one or more 32-bit integers in little-endian byte order in the output string. The low-order 32-bits of each integer are stored as a four-byte value at the cursor position with the least significant byte stored first. For example, .RS .CS \fBbinary format\fR i3 {3 -3 65536 1} .CE will return a string equivalent to \fB\ex03\ex00\ex00\ex00\exfd\exff\exff\exff\ex00\ex00\ex01\ex00\fR .RE .IP \fBI\fR 5 This form is the same as \fBi\fR except that it stores one or more one or more 32-bit integers in big-endian byte order in the output string. For example, .RS .CS \fBbinary format\fR I3 {3 -3 65536 1} .CE will return a string equivalent to \fB\ex00\ex00\ex00\ex03\exff\exff\exff\exfd\ex00\ex01\ex00\ex00\fR .RE .IP \fBn\fR 5 This form (mnemonically \fInumber\fR or \fInormal\fR) is the same as \fBi\fR and \fBI\fR except that it stores the 32-bit integers in the output string in the native byte order of the machine where the Tcl script is running. To determine what the native byte order of the machine is, refer to the \fBbyteOrder\fR element of the \fBtcl_platform\fR array. .IP \fBw\fR 5 This form is the same as \fBc\fR except that it stores one or more 64-bit integers in little-endian byte order in the output string. The low-order 64-bits of each integer are stored as an eight-byte value at the cursor position with the least significant byte stored first. For example, .RS .CS \fBbinary format\fR w 7810179016327718216 .CE will return the string \fBHelloTcl\fR .RE .IP \fBW\fR 5 This form is the same as \fBw\fR except that it stores one or more one or more 64-bit integers in big-endian byte order in the output string. For example, .RS .CS \fBbinary format\fR Wc 4785469626960341345 110 .CE will return the string \fBBigEndian\fR .RE .IP \fBm\fR 5 This form (mnemonically the mirror of \fBw\fR) is the same as \fBw\fR and \fBW\fR except that it stores the 64-bit integers in the output string in the native byte order of the machine where the Tcl script is running. To determine what the native byte order of the machine is, refer to the \fBbyteOrder\fR element of the \fBtcl_platform\fR array. .IP \fBf\fR 5 This form is the same as \fBc\fR except that it stores one or more one or more single-precision floating point numbers in the machine's native representation in the output string. This representation is not portable across architectures, so it should not be used to communicate floating point numbers across the network. The size of a floating point number may vary across architectures, so the number of bytes that are generated may vary. If the value overflows the machine's native representation, then the value of FLT_MAX as defined by the system will be used instead. Because Tcl uses double-precision floating point numbers internally, there may be some loss of precision in the conversion to single-precision. For example, on a Windows system running on an Intel Pentium processor, .RS .CS \fBbinary format\fR f2 {1.6 3.4} .CE will return a string equivalent to \fB\excd\excc\excc\ex3f\ex9a\ex99\ex59\ex40\fR. .RE .IP \fBr\fR 5 This form (mnemonically \fIreal\fR) is the same as \fBf\fR except that it stores the single-precision floating point numbers in little-endian order. This conversion only produces meaningful output when used on machines which use the IEEE floating point representation (very common, but not universal.) .IP \fBR\fR 5 This form is the same as \fBr\fR except that it stores the single-precision floating point numbers in big-endian order. .IP \fBd\fR 5 This form is the same as \fBf\fR except that it stores one or more one or more double-precision floating point numbers in the machine's native representation in the output string. For example, on a Windows system running on an Intel Pentium processor, .RS .CS \fBbinary format\fR d1 {1.6} .CE will return a string equivalent to \fB\ex9a\ex99\ex99\ex99\ex99\ex99\exf9\ex3f\fR. .RE .IP \fBq\fR 5 This form (mnemonically the mirror of \fBd\fR) is the same as \fBd\fR except that it stores the double-precision floating point numbers in little-endian order. This conversion only produces meaningful output when used on machines which use the IEEE floating point representation (very common, but not universal.) .IP \fBQ\fR 5 This form is the same as \fBq\fR except that it stores the double-precision floating point numbers in big-endian order. .IP \fBx\fR 5 Stores \fIcount\fR null bytes in the output string. If \fIcount\fR is not specified, stores one null byte. If \fIcount\fR is \fB*\fR, generates an error. This type does not consume an argument. For example, .RS .CS \fBbinary format\fR a3xa3x2a3 abc def ghi .CE will return a string equivalent to \fBabc\e000def\e000\e000ghi\fR. .RE .IP \fBX\fR 5 Moves the cursor back \fIcount\fR bytes in the output string. If \fIcount\fR is \fB*\fR or is larger than the current cursor position, then the cursor is positioned at location 0 so that the next byte stored will be the first byte in the result string. If \fIcount\fR is omitted then the cursor is moved back one byte. This type does not consume an argument. For example, .RS .CS \fBbinary format\fR a3X*a3X2a3 abc def ghi .CE will return \fBdghi\fR. .RE .IP \fB@\fR 5 Moves the cursor to the absolute location in the output string specified by \fIcount\fR. Position 0 refers to the first byte in the output string. If \fIcount\fR refers to a position beyond the last byte stored so far, then null bytes will be placed in the uninitialized locations and the cursor will be placed at the specified location. If \fIcount\fR is \fB*\fR, then the cursor is moved to the current end of the output string. If \fIcount\fR is omitted, then an error will be generated. This type does not consume an argument. For example, .RS .CS \fBbinary format\fR a5@2a1@*a3@10a1 abcde f ghi j .CE will return \fBabfdeghi\e000\e000j\fR. .RE .SH "BINARY SCAN" .PP The \fBbinary scan\fR command parses fields from a binary string, returning the number of conversions performed. \fIString\fR gives the input bytes to be parsed (one byte per character, and characters not representable as a byte have their high bits chopped) and \fIformatString\fR indicates how to parse it. Each \fIvarName\fR gives the name of a variable; when a field is scanned from \fIstring\fR the result is assigned to the corresponding variable. .PP As with \fBbinary format\fR, the \fIformatString\fR consists of a sequence of zero or more field specifiers separated by zero or more spaces. Each field specifier is a single type character followed by an optional flag character followed by an optional numeric \fIcount\fR. Most field specifiers consume one argument to obtain the variable into which the scanned values should be placed. The type character specifies how the binary data is to be interpreted. The \fIcount\fR typically indicates how many items of the specified type are taken from the data. If present, the \fIcount\fR is a non-negative decimal integer or \fB*\fR, which normally indicates that all of the remaining items in the data are to be used. If there are not enough bytes left after the current cursor position to satisfy the current field specifier, then the corresponding variable is left untouched and \fBbinary scan\fR returns immediately with the number of variables that were set. If there are not enough arguments for all of the fields in the format string that consume arguments, then an error is generated. The flag character .QW u may be given to cause some types to be read as unsigned values. The flag is accepted for all field types but is ignored for non-integer fields. .PP A similar example as with \fBbinary format\fR should explain the relation between field specifiers and arguments in case of the binary scan subcommand: .CS \fBbinary scan\fR $bytes s3s first second .CE .PP This command (provided the binary string in the variable \fIbytes\fR is long enough) assigns a list of three integers to the variable \fIfirst\fR and assigns a single value to the variable \fIsecond\fR. If \fIbytes\fR contains fewer than 8 bytes (i.e. four 2-byte integers), no assignment to \fIsecond\fR will be made, and if \fIbytes\fR contains fewer than 6 bytes (i.e. three 2-byte integers), no assignment to \fIfirst\fR will be made. Hence: .CS puts [\fBbinary scan\fR abcdefg s3s first second] puts $first puts $second .CE will print (assuming neither variable is set previously): .CS 1 25185 25699 26213 can't read "second": no such variable .CE .PP It is \fIimportant\fR to note that the \fBc\fR, \fBs\fR, and \fBS\fR (and \fBi\fR and \fBI\fR on 64bit systems) will be scanned into long data size values. In doing this, values that have their high bit set (0x80 for chars, 0x8000 for shorts, 0x80000000 for ints), will be sign extended. Thus the following will occur: .CS set signShort [\fBbinary format\fR s1 0x8000] \fBbinary scan\fR $signShort s1 val; \fI# val == 0xFFFF8000\fR .CE If you require unsigned values you can include the .QW u flag character following the field type. For example, to read an unsigned short value: .CS set signShort [\fBbinary format\fR s1 0x8000] \fBbinary scan\fR $signShort su1 val; \fI# val == 0x00008000\fR .CE .PP Each type-count pair moves an imaginary cursor through the binary data, reading bytes from the current position. The cursor is initially at position 0 at the beginning of the data. The type may be any one of the following characters: .IP \fBa\fR 5 The data is a byte string of length \fIcount\fR. If \fIcount\fR is \fB*\fR, then all of the remaining bytes in \fIstring\fR will be scanned into the variable. If \fIcount\fR is omitted, then one byte will be scanned. All bytes scanned will be interpreted as being characters in the range \eu0000-\eu00ff so the \fBencoding convertfrom\fR command will be needed if the string is not a binary string or a string encoded in ISO 8859\-1. For example, .RS .CS \fBbinary scan\fR abcde\e000fghi a6a10 var1 var2 .CE will return \fB1\fR with the string equivalent to \fBabcde\e000\fR stored in \fIvar1\fR and \fIvar2\fR left unmodified, and .CS \fBbinary scan\fR \e342\e202\e254 a* var1 set var2 [encoding convertfrom utf-8 $var1] .CE will store a Euro-currency character in \fIvar2\fR. .RE .IP \fBA\fR 5 This form is the same as \fBa\fR, except trailing blanks and nulls are stripped from the scanned value before it is stored in the variable. For example, .RS .CS \fBbinary scan\fR "abc efghi \e000" A* var1 .CE will return \fB1\fR with \fBabc efghi\fR stored in \fIvar1\fR. .RE .IP \fBb\fR 5 The data is turned into a string of \fIcount\fR binary digits in low-to-high order represented as a sequence of .QW 1 and .QW 0 characters. The data bytes are scanned in first to last order with the bits being taken in low-to-high order within each byte. Any extra bits in the last byte are ignored. If \fIcount\fR is \fB*\fR, then all of the remaining bits in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one bit will be scanned. For example, .RS .CS \fBbinary scan\fR \ex07\ex87\ex05 b5b* var1 var2 .CE will return \fB2\fR with \fB11100\fR stored in \fIvar1\fR and \fB1110000110100000\fR stored in \fIvar2\fR. .RE .IP \fBB\fR 5 This form is the same as \fBb\fR, except the bits are taken in high-to-low order within each byte. For example, .RS .CS \fBbinary scan\fR \ex70\ex87\ex05 B5B* var1 var2 .CE will return \fB2\fR with \fB01110\fR stored in \fIvar1\fR and \fB1000011100000101\fR stored in \fIvar2\fR. .RE .IP \fBH\fR 5 The data is turned into a string of \fIcount\fR hexadecimal digits in high-to-low order represented as a sequence of characters in the set .QW 0123456789abcdef . The data bytes are scanned in first to last order with the hex digits being taken in high-to-low order within each byte. Any extra bits in the last byte are ignored. If \fIcount\fR is \fB*\fR, then all of the remaining hex digits in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one hex digit will be scanned. For example, .RS .CS \fBbinary scan\fR \ex07\exC6\ex05\ex1f\ex34 H3H* var1 var2 .CE will return \fB2\fR with \fB07c\fR stored in \fIvar1\fR and \fB051f34\fR stored in \fIvar2\fR. .RE .IP \fBh\fR 5 This form is the same as \fBH\fR, except the digits are taken in reverse (low-to-high) order within each byte. For example, .RS .CS \fBbinary scan\fR \ex07\ex86\ex05\ex12\ex34 h3h* var1 var2 .CE will return \fB2\fR with \fB706\fR stored in \fIvar1\fR and \fB502143\fR stored in \fIvar2\fR. .PP Note that most code that wishes to parse the hexadecimal digits from multiple bytes in order should use the \fBH\fR format. .RE .IP \fBc\fR 5 The data is turned into \fIcount\fR 8-bit signed integers and stored in the corresponding variable as a list. If \fIcount\fR is \fB*\fR, then all of the remaining bytes in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one 8-bit integer will be scanned. For example, .RS .CS \fBbinary scan\fR \ex07\ex86\ex05 c2c* var1 var2 .CE will return \fB2\fR with \fB7 -122\fR stored in \fIvar1\fR and \fB5\fR stored in \fIvar2\fR. Note that the integers returned are signed, but they can be converted to unsigned 8-bit quantities using an expression like: .CS set num [expr { $num & 0xff }] .CE .RE .IP \fBs\fR 5 The data is interpreted as \fIcount\fR 16-bit signed integers represented in little-endian byte order. The integers are stored in the corresponding variable as a list. If \fIcount\fR is \fB*\fR, then all of the remaining bytes in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one 16-bit integer will be scanned. For example, .RS .CS \fBbinary scan\fR \ex05\ex00\ex07\ex00\exf0\exff s2s* var1 var2 .CE will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. Note that the integers returned are signed, but they can be converted to unsigned 16-bit quantities using an expression like: .CS set num [expr { $num & 0xffff }] .CE .RE .IP \fBS\fR 5 This form is the same as \fBs\fR except that the data is interpreted as \fIcount\fR 16-bit signed integers represented in big-endian byte order. For example, .RS .CS \fBbinary scan\fR \ex00\ex05\ex00\ex07\exff\exf0 S2S* var1 var2 .CE will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. .RE .IP \fBt\fR 5 The data is interpreted as \fIcount\fR 16-bit signed integers represented in the native byte order of the machine running the Tcl script. It is otherwise identical to \fBs\fR and \fBS\fR. To determine what the native byte order of the machine is, refer to the \fBbyteOrder\fR element of the \fBtcl_platform\fR array. .IP \fBi\fR 5 The data is interpreted as \fIcount\fR 32-bit signed integers represented in little-endian byte order. The integers are stored in the corresponding variable as a list. If \fIcount\fR is \fB*\fR, then all of the remaining bytes in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one 32-bit integer will be scanned. For example, .RS .CS set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exf0\exff\exff\exff \fBbinary scan\fR $str i2i* var1 var2 .CE will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. Note that the integers returned are signed, but they can be converted to unsigned 32-bit quantities using an expression like: .CS set num [expr { $num & 0xffffffff }] .CE .RE .IP \fBI\fR 5 This form is the same as \fBI\fR except that the data is interpreted as \fIcount\fR 32-bit signed integers represented in big-endian byte order. For example, .RS .CS set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exff\exff\exff\exf0 \fBbinary scan\fR $str I2I* var1 var2 .CE will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. .RE .IP \fBn\fR 5 The data is interpreted as \fIcount\fR 32-bit signed integers represented in the native byte order of the machine running the Tcl script. It is otherwise identical to \fBi\fR and \fBI\fR. To determine what the native byte order of the machine is, refer to the \fBbyteOrder\fR element of the \fBtcl_platform\fR array. .IP \fBw\fR 5 The data is interpreted as \fIcount\fR 64-bit signed integers represented in little-endian byte order. The integers are stored in the corresponding variable as a list. If \fIcount\fR is \fB*\fR, then all of the remaining bytes in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one 64-bit integer will be scanned. For example, .RS .CS set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exf0\exff\exff\exff \fBbinary scan\fR $str wi* var1 var2 .CE will return \fB2\fR with \fB30064771077\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. Note that the integers returned are signed and cannot be represented by Tcl as unsigned values. .RE .IP \fBW\fR 5 This form is the same as \fBw\fR except that the data is interpreted as \fIcount\fR 64-bit signed integers represented in big-endian byte order. For example, .RS .CS set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exff\exff\exff\exf0 \fBbinary scan\fR $str WI* var1 var2 .CE will return \fB2\fR with \fB21474836487\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. .RE .IP \fBm\fR 5 The data is interpreted as \fIcount\fR 64-bit signed integers represented in the native byte order of the machine running the Tcl script. It is otherwise identical to \fBw\fR and \fBW\fR. To determine what the native byte order of the machine is, refer to the \fBbyteOrder\fR element of the \fBtcl_platform\fR array. .IP \fBf\fR 5 The data is interpreted as \fIcount\fR single-precision floating point numbers in the machine's native representation. The floating point numbers are stored in the corresponding variable as a list. If \fIcount\fR is \fB*\fR, then all of the remaining bytes in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one single-precision floating point number will be scanned. The size of a floating point number may vary across architectures, so the number of bytes that are scanned may vary. If the data does not represent a valid floating point number, the resulting value is undefined and compiler dependent. For example, on a Windows system running on an Intel Pentium processor, .RS .CS \fBbinary scan\fR \ex3f\excc\excc\excd f var1 .CE will return \fB1\fR with \fB1.6000000238418579\fR stored in \fIvar1\fR. .RE .IP \fBr\fR 5 This form is the same as \fBf\fR except that the data is interpreted as \fIcount\fR single-precision floating point number in little-endian order. This conversion is not portable to the minority of systems not using IEEE floating point representations. .IP \fBR\fR 5 This form is the same as \fBf\fR except that the data is interpreted as \fIcount\fR single-precision floating point number in big-endian order. This conversion is not portable to the minority of systems not using IEEE floating point representations. .IP \fBd\fR 5 This form is the same as \fBf\fR except that the data is interpreted as \fIcount\fR double-precision floating point numbers in the machine's native representation. For example, on a Windows system running on an Intel Pentium processor, .RS .CS \fBbinary scan\fR \ex9a\ex99\ex99\ex99\ex99\ex99\exf9\ex3f d var1 .CE will return \fB1\fR with \fB1.6000000000000001\fR stored in \fIvar1\fR. .RE .IP \fBq\fR 5 This form is the same as \fBd\fR except that the data is interpreted as \fIcount\fR double-precision floating point number in little-endian order. This conversion is not portable to the minority of systems not using IEEE floating point representations. .IP \fBQ\fR 5 This form is the same as \fBd\fR except that the data is interpreted as \fIcount\fR double-precision floating point number in big-endian order. This conversion is not portable to the minority of systems not using IEEE floating point representations. .IP \fBx\fR 5 Moves the cursor forward \fIcount\fR bytes in \fIstring\fR. If \fIcount\fR is \fB*\fR or is larger than the number of bytes after the current cursor position, then the cursor is positioned after the last byte in \fIstring\fR. If \fIcount\fR is omitted, then the cursor is moved forward one byte. Note that this type does not consume an argument. For example, .RS .CS \fBbinary scan\fR \ex01\ex02\ex03\ex04 x2H* var1 .CE will return \fB1\fR with \fB0304\fR stored in \fIvar1\fR. .RE .IP \fBX\fR 5 Moves the cursor back \fIcount\fR bytes in \fIstring\fR. If \fIcount\fR is \fB*\fR or is larger than the current cursor position, then the cursor is positioned at location 0 so that the next byte scanned will be the first byte in \fIstring\fR. If \fIcount\fR is omitted then the cursor is moved back one byte. Note that this type does not consume an argument. For example, .RS .CS \fBbinary scan\fR \ex01\ex02\ex03\ex04 c2XH* var1 var2 .CE will return \fB2\fR with \fB1 2\fR stored in \fIvar1\fR and \fB020304\fR stored in \fIvar2\fR. .RE .IP \fB@\fR 5 Moves the cursor to the absolute location in the data string specified by \fIcount\fR. Note that position 0 refers to the first byte in \fIstring\fR. If \fIcount\fR refers to a position beyond the end of \fIstring\fR, then the cursor is positioned after the last byte. If \fIcount\fR is omitted, then an error will be generated. For example, .RS .CS \fBbinary scan\fR \ex01\ex02\ex03\ex04 c2@1H* var1 var2 .CE will return \fB2\fR with \fB1 2\fR stored in \fIvar1\fR and \fB020304\fR stored in \fIvar2\fR. .RE .SH "PORTABILITY ISSUES" .PP The \fBr\fR, \fBR\fR, \fBq\fR and \fBQ\fR conversions will only work reliably for transferring data between computers which are all using IEEE floating point representations. This is very common, but not universal. To transfer floating-point numbers portably between all architectures, use their textual representation (as produced by \fBformat\fR) instead. .SH EXAMPLES .PP This is a procedure to write a Tcl string to a binary-encoded channel as UTF-8 data preceded by a length word: .PP .CS proc \fIwriteString\fR {channel string} { set data [encoding convertto utf-8 $string] puts -nonewline [\fBbinary format\fR Ia* \e [string length $data] $data] } .CE .PP This procedure reads a string from a channel that was written by the previously presented \fIwriteString\fR procedure: .PP .CS proc \fIreadString\fR {channel} { if {![\fBbinary scan\fR [read $channel 4] I length]} { error "missing length" } set data [read $channel $length] return [encoding convertfrom utf-8 $data] } .CE .PP This converts the contents of a file (named in the variable \fIfilename\fR) to base64 and prints them: .PP .CS set f [open $filename rb] set data [read $f] close $f puts [\fBbinary encode\fR base64 \-maxlen 64 $data] .CE .SH "SEE ALSO" encoding(n), format(n), scan(n), string(n), tcl_platform(n) .SH KEYWORDS binary, format, scan '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/DoOneEvent.30000644000175000017500000001005312663660065014425 0ustar sergeisergei'\" '\" Copyright (c) 1990-1992 The Regents of the University of California. '\" Copyright (c) 1994-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_DoOneEvent 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_DoOneEvent \- wait for events and invoke event handlers .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_DoOneEvent\fR(\fIflags\fR) .SH ARGUMENTS .AS int flags .AP int flags in This parameter is normally zero. It may be an OR-ed combination of any of the following flag bits: \fBTCL_WINDOW_EVENTS\fR, \fBTCL_FILE_EVENTS\fR, \fBTCL_TIMER_EVENTS\fR, \fBTCL_IDLE_EVENTS\fR, \fBTCL_ALL_EVENTS\fR, or \fBTCL_DONT_WAIT\fR. .BE .SH DESCRIPTION .PP This procedure is the entry point to Tcl's event loop; it is responsible for waiting for events and dispatching event handlers created with procedures such as \fBTk_CreateEventHandler\fR, \fBTcl_CreateFileHandler\fR, \fBTcl_CreateTimerHandler\fR, and \fBTcl_DoWhenIdle\fR. \fBTcl_DoOneEvent\fR checks to see if events are already present on the Tcl event queue; if so, it calls the handler(s) for the first (oldest) event, removes it from the queue, and returns. If there are no events ready to be handled, then \fBTcl_DoOneEvent\fR checks for new events from all possible sources. If any are found, it puts all of them on Tcl's event queue, calls handlers for the first event on the queue, and returns. If no events are found, \fBTcl_DoOneEvent\fR checks for \fBTcl_DoWhenIdle\fR callbacks; if any are found, it invokes all of them and returns. Finally, if no events or idle callbacks have been found, then \fBTcl_DoOneEvent\fR sleeps until an event occurs; then it adds any new events to the Tcl event queue, calls handlers for the first event, and returns. The normal return value is 1 to signify that some event was processed (see below for other alternatives). .PP If the \fIflags\fR argument to \fBTcl_DoOneEvent\fR is non-zero, it restricts the kinds of events that will be processed by \fBTcl_DoOneEvent\fR. \fIFlags\fR may be an OR-ed combination of any of the following bits: .TP 27 \fBTCL_WINDOW_EVENTS\fR \- Process window system events. .TP 27 \fBTCL_FILE_EVENTS\fR \- Process file events. .TP 27 \fBTCL_TIMER_EVENTS\fR \- Process timer events. .TP 27 \fBTCL_IDLE_EVENTS\fR \- Process idle callbacks. .TP 27 \fBTCL_ALL_EVENTS\fR \- Process all kinds of events: equivalent to OR-ing together all of the above flags or specifying none of them. .TP 27 \fBTCL_DONT_WAIT\fR \- Do not sleep: process only events that are ready at the time of the call. .LP If any of the flags \fBTCL_WINDOW_EVENTS\fR, \fBTCL_FILE_EVENTS\fR, \fBTCL_TIMER_EVENTS\fR, or \fBTCL_IDLE_EVENTS\fR is set, then the only events that will be considered are those for which flags are set. Setting none of these flags is equivalent to the value \fBTCL_ALL_EVENTS\fR, which causes all event types to be processed. If an application has defined additional event sources with \fBTcl_CreateEventSource\fR, then additional \fIflag\fR values may also be valid, depending on those event sources. .PP The \fBTCL_DONT_WAIT\fR flag causes \fBTcl_DoOneEvent\fR not to put the process to sleep: it will check for events but if none are found then it returns immediately with a return value of 0 to indicate that no work was done. \fBTcl_DoOneEvent\fR will also return 0 without doing anything if the only alternative is to block forever (this can happen, for example, if \fIflags\fR is \fBTCL_IDLE_EVENTS\fR and there are no \fBTcl_DoWhenIdle\fR callbacks pending, or if no event handlers or timer handlers exist). .PP \fBTcl_DoOneEvent\fR may be invoked recursively. For example, it is possible to invoke \fBTcl_DoOneEvent\fR recursively from a handler called by \fBTcl_DoOneEvent\fR. This sort of operation is useful in some modal situations, such as when a notification dialog has been popped up and an application wishes to wait for the user to click a button in the dialog before doing anything else. .SH KEYWORDS callback, event, handler, idle, timer tcl8.6.5/doc/chan.n0000644000175000017500000011355512663660065013436 0ustar sergeisergei'\" '\" Copyright (c) 2005-2006 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. .TH chan n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME chan \- Read, write and manipulate channels .SH SYNOPSIS \fBchan \fIoption\fR ?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP This command provides several operations for reading from, writing to and otherwise manipulating open channels (such as have been created with the \fBopen\fR and \fBsocket\fR commands, or the default named channels \fBstdin\fR, \fBstdout\fR or \fBstderr\fR which correspond to the process's standard input, output and error streams respectively). \fIOption\fR indicates what to do with the channel; any unique abbreviation for \fIoption\fR is acceptable. Valid options are: .TP \fBchan blocked \fIchannelId\fR . This tests whether the last input operation on the channel called \fIchannelId\fR failed because it would have otherwise caused the process to block, and returns 1 if that was the case. It returns 0 otherwise. Note that this only ever returns 1 when the channel has been configured to be non-blocking; all Tcl channels have blocking turned on by default. .TP \fBchan close \fIchannelId\fR ?\fIdirection\fR? . Close and destroy the channel called \fIchannelId\fR. Note that this deletes all existing file-events registered on the channel. .VS 8.6 If the \fIdirection\fR argument (which must be \fBread\fR or \fBwrite\fR or any unique abbreviation of them) is present, the channel will only be half-closed, so that it can go from being read-write to write-only or read-only respectively. If a read-only channel is closed for reading, it is the same as if the channel is fully closed, and respectively similar for write-only channels. Without the \fIdirection\fR argument, the channel is closed for both reading and writing (but only if those directions are currently open). It is an error to close a read-only channel for writing, or a write-only channel for reading. .VE 8.6 .RS .PP As part of closing the channel, all buffered output is flushed to the channel's output device (only if the channel is ceasing to be writable), any buffered input is discarded (only if the channel is ceasing to be readable), the underlying operating system resource is closed and \fIchannelId\fR becomes unavailable for future use (both only if the channel is being completely closed). .PP If the channel is blocking and the channel is ceasing to be writable, the command does not return until all output is flushed. If the channel is non-blocking and there is unflushed output, the channel remains open and the command returns immediately; output will be flushed in the background and the channel will be closed when all the flushing is complete. .PP If \fIchannelId\fR is a blocking channel for a command pipeline then \fBchan close\fR waits for the child processes to complete. .PP If the channel is shared between interpreters, then \fBchan close\fR makes \fIchannelId\fR unavailable in the invoking interpreter but has no other effect until all of the sharing interpreters have closed the channel. When the last interpreter in which the channel is registered invokes \fBchan close\fR (or \fBclose\fR), the cleanup actions described above occur. With half-closing, the half-close of the channel only applies to the current interpreter's view of the channel until all channels have closed it in that direction (or completely). See the \fBinterp\fR command for a description of channel sharing. .PP Channels are automatically fully closed when an interpreter is destroyed and when the process exits. Channels are switched to blocking mode, to ensure that all output is correctly flushed before the process exits. .PP The command returns an empty string, and may generate an error if an error occurs while flushing output. If a command in a command pipeline created with \fBopen\fR returns an error, \fBchan close\fR generates an error (similar to the \fBexec\fR command.) .PP .VS 8.6 Note that half-closes of sockets and command pipelines can have important side effects because they result in a shutdown() or close() of the underlying system resource, which can change how other processes or systems respond to the Tcl program. .VE 8.6 .RE .TP \fBchan configure \fIchannelId\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?... . Query or set the configuration options of the channel named \fIchannelId\fR. .RS .PP If no \fIoptionName\fR or \fIvalue\fR arguments are supplied, the command returns a list containing alternating option names and values for the channel. If \fIoptionName\fR is supplied but no \fIvalue\fR then the command returns the current value of the given option. If one or more pairs of \fIoptionName\fR and \fIvalue\fR are supplied, the command sets each of the named options to the corresponding \fIvalue\fR; in this case the return value is an empty string. .PP The options described below are supported for all channels. In addition, each channel type may add options that only it supports. See the manual entry for the command that creates each type of channel for the options supported by that specific type of channel. For example, see the manual entry for the \fBsocket\fR command for additional options for sockets, and the \fBopen\fR command for additional options for serial devices. .TP \fB\-blocking\fR \fIboolean\fR . The \fB\-blocking\fR option determines whether I/O operations on the channel can cause the process to block indefinitely. The value of the option must be a proper boolean value. Channels are normally in blocking mode; if a channel is placed into non-blocking mode it will affect the operation of the \fBchan gets\fR, \fBchan read\fR, \fBchan puts\fR, \fBchan flush\fR, and \fBchan close\fR commands; see the documentation for those commands for details. For non-blocking mode to work correctly, the application must be using the Tcl event loop (e.g. by calling \fBTcl_DoOneEvent\fR or invoking the \fBvwait\fR command). .TP \fB\-buffering\fR \fInewValue\fR . If \fInewValue\fR is \fBfull\fR then the I/O system will buffer output until its internal buffer is full or until the \fBchan flush\fR command is invoked. If \fInewValue\fR is \fBline\fR, then the I/O system will automatically flush output for the channel whenever a newline character is output. If \fInewValue\fR is \fBnone\fR, the I/O system will flush automatically after every output operation. The default is for \fB\-buffering\fR to be set to \fBfull\fR except for channels that connect to terminal-like devices; for these channels the initial setting is \fBline\fR. Additionally, \fBstdin\fR and \fBstdout\fR are initially set to \fBline\fR, and \fBstderr\fR is set to \fBnone\fR. .TP \fB\-buffersize\fR \fInewSize\fR . \fINewvalue\fR must be an integer; its value is used to set the size of buffers, in bytes, subsequently allocated for this channel to store input or output. \fINewvalue\fR must be a number of no more than one million, allowing buffers of up to one million bytes in size. .TP \fB\-encoding\fR \fIname\fR . This option is used to specify the encoding of the channel as one of the named encodings returned by \fBencoding names\fR or the special value \fBbinary\fR, so that the data can be converted to and from Unicode for use in Tcl. For instance, in order for Tcl to read characters from a Japanese file in \fBshiftjis\fR and properly process and display the contents, the encoding would be set to \fBshiftjis\fR. Thereafter, when reading from the channel, the bytes in the Japanese file would be converted to Unicode as they are read. Writing is also supported \- as Tcl strings are written to the channel they will automatically be converted to the specified encoding on output. .RS .PP If a file contains pure binary data (for instance, a JPEG image), the encoding for the channel should be configured to be \fBbinary\fR. Tcl will then assign no interpretation to the data in the file and simply read or write raw bytes. The Tcl \fBbinary\fR command can be used to manipulate this byte-oriented data. It is usually better to set the \fB\-translation\fR option to \fBbinary\fR when you want to transfer binary data, as this turns off the other automatic interpretations of the bytes in the stream as well. .PP The default encoding for newly opened channels is the same platform- and locale-dependent system encoding used for interfacing with the operating system, as returned by \fBencoding system\fR. .RE .TP \fB\-eofchar\fR \fIchar\fR .TP \fB\-eofchar\fR \fB{\fIinChar outChar\fB}\fR . This option supports DOS file systems that use Control-z (\ex1a) as an end of file marker. If \fIchar\fR is not an empty string, then this character signals end-of-file when it is encountered during input. For output, the end-of-file character is output when the channel is closed. If \fIchar\fR is the empty string, then there is no special end of file character marker. For read-write channels, a two-element list specifies the end of file marker for input and output, respectively. As a convenience, when setting the end-of-file character for a read-write channel you can specify a single value that will apply to both reading and writing. When querying the end-of-file character of a read-write channel, a two-element list will always be returned. The default value for \fB\-eofchar\fR is the empty string in all cases except for files under Windows. In that case the \fB\-eofchar\fR is Control-z (\ex1a) for reading and the empty string for writing. The acceptable range for \fB\-eofchar\fR values is \ex01 - \ex7f; attempting to set \fB\-eofchar\fR to a value outside of this range will generate an error. .TP \fB\-translation\fR \fImode\fR .TP \fB\-translation\fR \fB{\fIinMode outMode\fB}\fR . In Tcl scripts the end of a line is always represented using a single newline character (\en). However, in actual files and devices the end of a line may be represented differently on different platforms, or even for different devices on the same platform. For example, under UNIX newlines are used in files, whereas carriage-return-linefeed sequences are normally used in network connections. On input (i.e., with \fBchan gets\fR and \fBchan read\fR) the Tcl I/O system automatically translates the external end-of-line representation into newline characters. Upon output (i.e., with \fBchan puts\fR), the I/O system translates newlines to the external end-of-line representation. The default translation mode, \fBauto\fR, handles all the common cases automatically, but the \fB\-translation\fR option provides explicit control over the end of line translations. .RS .PP The value associated with \fB\-translation\fR is a single item for read-only and write-only channels. The value is a two-element list for read-write channels; the read translation mode is the first element of the list, and the write translation mode is the second element. As a convenience, when setting the translation mode for a read-write channel you can specify a single value that will apply to both reading and writing. When querying the translation mode of a read-write channel, a two-element list will always be returned. The following values are currently supported: .TP \fBauto\fR . As the input translation mode, \fBauto\fR treats any of newline (\fBlf\fR), carriage return (\fBcr\fR), or carriage return followed by a newline (\fBcrlf\fR) as the end of line representation. The end of line representation can even change from line-to-line, and all cases are translated to a newline. As the output translation mode, \fBauto\fR chooses a platform specific representation; for sockets on all platforms Tcl chooses \fBcrlf\fR, for all Unix flavors, it chooses \fBlf\fR, and for the various flavors of Windows it chooses \fBcrlf\fR. The default setting for \fB\-translation\fR is \fBauto\fR for both input and output. .TP \fBbinary\fR . No end-of-line translations are performed. This is nearly identical to \fBlf\fR mode, except that in addition \fBbinary\fR mode also sets the end-of-file character to the empty string (which disables it) and sets the encoding to \fBbinary\fR (which disables encoding filtering). See the description of \fB\-eofchar\fR and \fB\-encoding\fR for more information. .TP \fBcr\fR . The end of a line in the underlying file or device is represented by a single carriage return character. As the input translation mode, \fBcr\fR mode converts carriage returns to newline characters. As the output translation mode, \fBcr\fR mode translates newline characters to carriage returns. .TP \fBcrlf\fR . The end of a line in the underlying file or device is represented by a carriage return character followed by a linefeed character. As the input translation mode, \fBcrlf\fR mode converts carriage-return-linefeed sequences to newline characters. As the output translation mode, \fBcrlf\fR mode translates newline characters to carriage-return-linefeed sequences. This mode is typically used on Windows platforms and for network connections. .TP \fBlf\fR . The end of a line in the underlying file or device is represented by a single newline (linefeed) character. In this mode no translations occur during either input or output. This mode is typically used on UNIX platforms. .RE .RE .TP \fBchan copy \fIinputChan outputChan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR? . Copy data from the channel \fIinputChan\fR, which must have been opened for reading, to the channel \fIoutputChan\fR, which must have been opened for writing. The \fBchan copy\fR command leverages the buffering in the Tcl I/O system to avoid extra copies and to avoid buffering too much data in main memory when copying large files to slow destinations like network sockets. .RS .PP The \fBchan copy\fR command transfers data from \fIinputChan\fR until end of file or \fIsize\fR bytes have been transferred. If no \fB\-size\fR argument is given, then the copy goes until end of file. All the data read from \fIinputChan\fR is copied to \fIoutputChan\fR. Without the \fB\-command\fR option, \fBchan copy\fR blocks until the copy is complete and returns the number of bytes written to \fIoutputChan\fR. .PP The \fB\-command\fR argument makes \fBchan copy\fR work in the background. In this case it returns immediately and the \fIcallback\fR is invoked later when the copy completes. The \fIcallback\fR is called with one or two additional arguments that indicates how many bytes were written to \fIoutputChan\fR. If an error occurred during the background copy, the second argument is the error string associated with the error. With a background copy, it is not necessary to put \fIinputChan\fR or \fIoutputChan\fR into non-blocking mode; the \fBchan copy\fR command takes care of that automatically. However, it is necessary to enter the event loop by using the \fBvwait\fR command or by using Tk. .PP You are not allowed to do other I/O operations with \fIinputChan\fR or \fIoutputChan\fR during a background \fBchan copy\fR. If either \fIinputChan\fR or \fIoutputChan\fR get closed while the copy is in progress, the current copy is stopped and the command callback is \fInot\fR made. If \fIinputChan\fR is closed, then all data already queued for \fIoutputChan\fR is written out. .PP Note that \fIinputChan\fR can become readable during a background copy. You should turn off any \fBchan event\fR or \fBfileevent\fR handlers during a background copy so those handlers do not interfere with the copy. Any I/O attempted by a \fBchan event\fR or \fBfileevent\fR handler will get a .QW "channel busy" error. .PP \fBChan copy\fR translates end-of-line sequences in \fIinputChan\fR and \fIoutputChan\fR according to the \fB\-translation\fR option for these channels (see \fBchan configure\fR above). The translations mean that the number of bytes read from \fIinputChan\fR can be different than the number of bytes written to \fIoutputChan\fR. Only the number of bytes written to \fIoutputChan\fR is reported, either as the return value of a synchronous \fBchan copy\fR or as the argument to the callback for an asynchronous \fBchan copy\fR. .PP \fBChan copy\fR obeys the encodings and character translations configured for the channels. This means that the incoming characters are converted internally first UTF-8 and then into the encoding of the channel \fBchan copy\fR writes to (see \fBchan configure\fR above for details on the \fB\-encoding\fR and \fB\-translation\fR options). No conversion is done if both channels are set to encoding \fBbinary\fR and have matching translations. If only the output channel is set to encoding \fBbinary\fR the system will write the internal UTF-8 representation of the incoming characters. If only the input channel is set to encoding \fBbinary\fR the system will assume that the incoming bytes are valid UTF-8 characters and convert them according to the output encoding. The behaviour of the system for bytes which are not valid UTF-8 characters is undefined in this case. .RE .TP \fBchan create \fImode cmdPrefix\fR . This subcommand creates a new script level channel using the command prefix \fIcmdPrefix\fR as its handler. Any such channel is called a \fBreflected\fR channel. The specified command prefix, \fBcmdPrefix\fR, must be a non-empty list, and should provide the API described in the \fBrefchan\fR manual page. The handle of the new channel is returned as the result of the \fBchan create\fR command, and the channel is open. Use either \fBclose\fR or \fBchan close\fR to remove the channel. .RS .PP The argument \fImode\fR specifies if the new channel is opened for reading, writing, or both. It has to be a list containing any of the strings .QW \fBread\fR or .QW \fBwrite\fR . The list must have at least one element, as a channel you can neither write to nor read from makes no sense. The handler command for the new channel must support the chosen mode, or an error is thrown. .PP The command prefix is executed in the global namespace, at the top of call stack, following the appending of arguments as described in the \fBrefchan\fR manual page. Command resolution happens at the time of the call. Renaming the command, or destroying it means that the next call of a handler method may fail, causing the channel command invoking the handler to fail as well. Depending on the subcommand being invoked, the error message may not be able to explain the reason for that failure. .PP Every channel created with this subcommand knows which interpreter it was created in, and only ever executes its handler command in that interpreter, even if the channel was shared with and/or was moved into a different interpreter. Each reflected channel also knows the thread it was created in, and executes its handler command only in that thread, even if the channel was moved into a different thread. To this end all invocations of the handler are forwarded to the original thread by posting special events to it. This means that the original thread (i.e. the thread that executed the \fBchan create\fR command) must have an active event loop, i.e. it must be able to process such events. Otherwise the thread sending them will \fIblock indefinitely\fR. Deadlock may occur. .PP Note that this permits the creation of a channel whose two endpoints live in two different threads, providing a stream-oriented bridge between these threads. In other words, we can provide a way for regular stream communication between threads instead of having to send commands. .PP When a thread or interpreter is deleted, all channels created with this subcommand and using this thread/interpreter as their computing base are deleted as well, in all interpreters they have been shared with or moved into, and in whatever thread they have been transferred to. While this pulls the rug out under the other thread(s) and/or interpreter(s), this cannot be avoided. Trying to use such a channel will cause the generation of a regular error about unknown channel handles. .PP This subcommand is \fBsafe\fR and made accessible to safe interpreters. While it arranges for the execution of arbitrary Tcl code the system also makes sure that the code is always executed within the safe interpreter. .RE .TP \fBchan eof \fIchannelId\fR . Test whether the last input operation on the channel called \fIchannelId\fR failed because the end of the data stream was reached, returning 1 if end-of-file was reached, and 0 otherwise. .TP \fBchan event \fIchannelId event\fR ?\fIscript\fR? . Arrange for the Tcl script \fIscript\fR to be installed as a \fIfile event handler\fR to be called whenever the channel called \fIchannelId\fR enters the state described by \fIevent\fR (which must be either \fBreadable\fR or \fBwritable\fR); only one such handler may be installed per event per channel at a time. If \fIscript\fR is the empty string, the current handler is deleted (this also happens if the channel is closed or the interpreter deleted). If \fIscript\fR is omitted, the currently installed script is returned (or an empty string if no such handler is installed). The callback is only performed if the event loop is being serviced (e.g. via \fBvwait\fR or \fBupdate\fR). .RS .PP A file event handler is a binding between a channel and a script, such that the script is evaluated whenever the channel becomes readable or writable. File event handlers are most commonly used to allow data to be received from another process on an event-driven basis, so that the receiver can continue to interact with the user or with other channels while waiting for the data to arrive. If an application invokes \fBchan gets\fR or \fBchan read\fR on a blocking channel when there is no input data available, the process will block; until the input data arrives, it will not be able to service other events, so it will appear to the user to .QW "freeze up" . With \fBchan event\fR, the process can tell when data is present and only invoke \fBchan gets\fR or \fBchan read\fR when they will not block. .PP A channel is considered to be readable if there is unread data available on the underlying device. A channel is also considered to be readable if there is unread data in an input buffer, except in the special case where the most recent attempt to read from the channel was a \fBchan gets\fR call that could not find a complete line in the input buffer. This feature allows a file to be read a line at a time in non-blocking mode using events. A channel is also considered to be readable if an end of file or error condition is present on the underlying file or device. It is important for \fIscript\fR to check for these conditions and handle them appropriately; for example, if there is no special check for end of file, an infinite loop may occur where \fIscript\fR reads no data, returns, and is immediately invoked again. .PP A channel is considered to be writable if at least one byte of data can be written to the underlying file or device without blocking, or if an error condition is present on the underlying file or device. Note that client sockets opened in asynchronous mode become writable when they become connected or if the connection fails. .PP Event-driven I/O works best for channels that have been placed into non-blocking mode with the \fBchan configure\fR command. In blocking mode, a \fBchan puts\fR command may block if you give it more data than the underlying file or device can accept, and a \fBchan gets\fR or \fBchan read\fR command will block if you attempt to read more data than is ready; no events will be processed while the commands block. In non-blocking mode \fBchan puts\fR, \fBchan read\fR, and \fBchan gets\fR never block. .PP The script for a file event is executed at global level (outside the context of any Tcl procedure) in the interpreter in which the \fBchan event\fR command was invoked. If an error occurs while executing the script then the command registered with \fBinterp bgerror\fR is used to report the error. In addition, the file event handler is deleted if it ever returns an error; this is done in order to prevent infinite loops due to buggy handlers. .RE .TP \fBchan flush \fIchannelId\fR . Ensures that all pending output for the channel called \fIchannelId\fR is written. .RS .PP If the channel is in blocking mode the command does not return until all the buffered output has been flushed to the channel. If the channel is in non-blocking mode, the command may return before all buffered output has been flushed; the remainder will be flushed in the background as fast as the underlying file or device is able to absorb it. .RE .TP \fBchan gets \fIchannelId\fR ?\fIvarName\fR? . Reads the next line from the channel called \fIchannelId\fR. If \fIvarName\fR is not specified, the result of the command will be the line that has been read (without a trailing newline character) or an empty string upon end-of-file or, in non-blocking mode, if the data available is exhausted. If \fIvarName\fR is specified, the line that has been read will be written to the variable called \fIvarName\fR and result will be the number of characters that have been read or -1 if end-of-file was reached or, in non-blocking mode, if the data available is exhausted. .RS .PP If an end-of-file occurs while part way through reading a line, the partial line will be returned (or written into \fIvarName\fR). When \fIvarName\fR is not specified, the end-of-file case can be distinguished from an empty line using the \fBchan eof\fR command, and the partial-line-but-non-blocking case can be distinguished with the \fBchan blocked\fR command. .RE .TP \fBchan names\fR ?\fIpattern\fR? . Produces a list of all channel names. If \fIpattern\fR is specified, only those channel names that match it (according to the rules of \fBstring match\fR) will be returned. .TP \fBchan pending \fImode channelId\fR . Depending on whether \fImode\fR is \fBinput\fR or \fBoutput\fR, returns the number of bytes of input or output (respectively) currently buffered internally for \fIchannelId\fR (especially useful in a readable event callback to impose application-specific limits on input line lengths to avoid a potential denial-of-service attack where a hostile user crafts an extremely long line that exceeds the available memory to buffer it). Returns -1 if the channel was not opened for the mode in question. .TP \fBchan pipe\fR .VS 8.6 Creates a standalone pipe whose read- and write-side channels are returned as a 2-element list, the first element being the read side and the second the write side. Can be useful e.g. to redirect separately \fBstderr\fR and \fBstdout\fR from a subprocess. To do this, spawn with "2>@" or ">@" redirection operators onto the write side of a pipe, and then immediately close it in the parent. This is necessary to get an EOF on the read side once the child has exited or otherwise closed its output. .VE 8.6 .TP \fBchan pop \fIchannelId\fR .VS 8.6 Removes the topmost transformation from the channel \fIchannelId\fR, if there is any. If there are no transformations added to \fIchannelId\fR, this is equivalent to \fBchan close\fR of that channel. The result is normally the empty string, but can be an error in some situations (i.e. where the underlying system stream is closed and that results in an error). .VE 8.6 .TP \fBchan postevent \fIchannelId eventSpec\fR . This subcommand is used by command handlers specified with \fBchan create\fR. It notifies the channel represented by the handle \fIchannelId\fR that the event(s) listed in the \fIeventSpec\fR have occurred. The argument has to be a list containing any of the strings \fBread\fR and \fBwrite\fR. The list must contain at least one element as it does not make sense to invoke the command if there are no events to post. .RS .PP Note that this subcommand can only be used with channel handles that were created/opened by \fBchan create\fR. All other channels will cause this subcommand to report an error. .PP As only the Tcl level of a channel, i.e. its command handler, should post events to it we also restrict the usage of this command to the interpreter that created the channel. In other words, posting events to a reflected channel from an interpreter that does not contain it's implementation is not allowed. Attempting to post an event from any other interpreter will cause this subcommand to report an error. .PP Another restriction is that it is not possible to post events that the I/O core has not registered an interest in. Trying to do so will cause the method to throw an error. See the command handler method \fBwatch\fR described in \fBrefchan\fR, the document specifying the API of command handlers for reflected channels. .PP This command is \fBsafe\fR and made accessible to safe interpreters. It can trigger the execution of \fBchan event\fR handlers, whether in the current interpreter or in other interpreters or other threads, even where the event is posted from a safe interpreter and listened for by a trusted interpreter. \fBChan event\fR handlers are \fIalways\fR executed in the interpreter that set them up. .RE .TP \fBchan push \fIchannelId cmdPrefix\fR .VS 8.6 Adds a new transformation on top of the channel \fIchannelId\fR. The \fIcmdPrefix\fR argument describes a list of one or more words which represent a handler that will be used to implement the transformation. The command prefix must provide the API described in the \fBtranschan\fR manual page. The result of this subcommand is a handle to the transformation. Note that it is important to make sure that the transformation is capable of supporting the channel mode that it is used with or this can make the channel neither readable nor writable. .VE 8.6 .TP \fBchan puts\fR ?\fB\-nonewline\fR? ?\fIchannelId\fR? \fIstring\fR . Writes \fIstring\fR to the channel named \fIchannelId\fR followed by a newline character. A trailing newline character is written unless the optional flag \fB\-nonewline\fR is given. If \fIchannelId\fR is omitted, the string is written to the standard output channel, \fBstdout\fR. .RS .PP Newline characters in the output are translated by \fBchan puts\fR to platform-specific end-of-line sequences according to the currently configured value of the \fB\-translation\fR option for the channel (for example, on PCs newlines are normally replaced with carriage-return-linefeed sequences; see \fBchan configure\fR above for details). .PP Tcl buffers output internally, so characters written with \fBchan puts\fR may not appear immediately on the output file or device; Tcl will normally delay output until the buffer is full or the channel is closed. You can force output to appear immediately with the \fBchan flush\fR command. .PP When the output buffer fills up, the \fBchan puts\fR command will normally block until all the buffered data has been accepted for output by the operating system. If \fIchannelId\fR is in non-blocking mode then the \fBchan puts\fR command will not block even if the operating system cannot accept the data. Instead, Tcl continues to buffer the data and writes it in the background as fast as the underlying file or device can accept it. The application must use the Tcl event loop for non-blocking output to work; otherwise Tcl never finds out that the file or device is ready for more output data. It is possible for an arbitrarily large amount of data to be buffered for a channel in non-blocking mode, which could consume a large amount of memory. To avoid wasting memory, non-blocking I/O should normally be used in an event-driven fashion with the \fBchan event\fR command (do not invoke \fBchan puts\fR unless you have recently been notified via a file event that the channel is ready for more output data). .RE .TP \fBchan read \fIchannelId\fR ?\fInumChars\fR? .TP \fBchan read \fR?\fB\-nonewline\fR? \fIchannelId\fR . In the first form, the result will be the next \fInumChars\fR characters read from the channel named \fIchannelId\fR; if \fInumChars\fR is omitted, all characters up to the point when the channel would signal a failure (whether an end-of-file, blocked or other error condition) are read. In the second form (i.e. when \fInumChars\fR has been omitted) the flag \fB\-nonewline\fR may be given to indicate that any trailing newline in the string that has been read should be trimmed. .RS .PP If \fIchannelId\fR is in non-blocking mode, \fBchan read\fR may not read as many characters as requested: once all available input has been read, the command will return the data that is available rather than blocking for more input. If the channel is configured to use a multi-byte encoding, then there may actually be some bytes remaining in the internal buffers that do not form a complete character. These bytes will not be returned until a complete character is available or end-of-file is reached. The \fB\-nonewline\fR switch is ignored if the command returns before reaching the end of the file. .PP \fBChan read\fR translates end-of-line sequences in the input into newline characters according to the \fB\-translation\fR option for the channel (see \fBchan configure\fR above for a discussion on the ways in which \fBchan configure\fR will alter input). .PP When reading from a serial port, most applications should configure the serial port channel to be non-blocking, like this: .PP .CS \fBchan configure \fIchannelId \fB\-blocking \fI0\fR. .CE .PP Then \fBchan read\fR behaves much like described above. Note that most serial ports are comparatively slow; it is entirely possible to get a \fBreadable\fR event for each character read from them. Care must be taken when using \fBchan read\fR on blocking serial ports: .TP \fBchan read \fIchannelId numChars\fR . In this form \fBchan read\fR blocks until \fInumChars\fR have been received from the serial port. .TP \fBchan read \fIchannelId\fR . In this form \fBchan read\fR blocks until the reception of the end-of-file character, see \fBchan configure -eofchar\fR. If there no end-of-file character has been configured for the channel, then \fBchan read\fR will block forever. .RE .TP \fBchan seek \fIchannelId offset\fR ?\fIorigin\fR? . Sets the current access position within the underlying data stream for the channel named \fIchannelId\fR to be \fIoffset\fR bytes relative to \fIorigin\fR. \fIOffset\fR must be an integer (which may be negative) and \fIorigin\fR must be one of the following: .RS .TP 10 \fBstart\fR . The new access position will be \fIoffset\fR bytes from the start of the underlying file or device. .TP 10 \fBcurrent\fR . The new access position will be \fIoffset\fR bytes from the current access position; a negative \fIoffset\fR moves the access position backwards in the underlying file or device. .TP 10 \fBend\fR . The new access position will be \fIoffset\fR bytes from the end of the file or device. A negative \fIoffset\fR places the access position before the end of file, and a positive \fIoffset\fR places the access position after the end of file. .PP The \fIorigin\fR argument defaults to \fBstart\fR. .PP \fBChan seek\fR flushes all buffered output for the channel before the command returns, even if the channel is in non-blocking mode. It also discards any buffered and unread input. This command returns an empty string. An error occurs if this command is applied to channels whose underlying file or device does not support seeking. .PP Note that \fIoffset\fR values are byte offsets, not character offsets. Both \fBchan seek\fR and \fBchan tell\fR operate in terms of bytes, not characters, unlike \fBchan read\fR. .RE .TP \fBchan tell \fIchannelId\fR . Returns a number giving the current access position within the underlying data stream for the channel named \fIchannelId\fR. This value returned is a byte offset that can be passed to \fBchan seek\fR in order to set the channel to a particular position. Note that this value is in terms of bytes, not characters like \fBchan read\fR. The value returned is -1 for channels that do not support seeking. .TP \fBchan truncate \fIchannelId\fR ?\fIlength\fR? . Sets the byte length of the underlying data stream for the channel named \fIchannelId\fR to be \fIlength\fR (or to the current byte offset within the underlying data stream if \fIlength\fR is omitted). The channel is flushed before truncation. . .SH EXAMPLES .PP This opens a file using a known encoding (CP1252, a very common encoding on Windows), searches for a string, rewrites that part, and truncates the file after a further two lines. .PP .CS set f [open somefile.txt r+] \fBchan configure\fR $f -encoding cp1252 set offset 0 \fI# Search for string "FOOBAR" in the file\fR while {[\fBchan gets\fR $f line] >= 0} { set idx [string first FOOBAR $line] if {$idx > -1} { \fI# Found it; rewrite line\fR \fBchan seek\fR $f [expr {$offset + $idx}] \fBchan puts\fR -nonewline $f BARFOO \fI# Skip to end of following line, and truncate\fR \fBchan gets\fR $f \fBchan gets\fR $f \fBchan truncate\fR $f \fI# Stop searching the file now\fR break } \fI# Save offset of start of next line for later\fR set offset [\fBchan tell\fR $f] } \fBchan close\fR $f .CE .PP A network server that does echoing of its input line-by-line without preventing servicing of other connections at the same time. .PP .CS # This is a very simple logger... proc log {message} { \fBchan puts\fR stdout $message } # This is called whenever a new client connects to the server proc connect {chan host port} { set clientName [format <%s:%d> $host $port] log "connection from $clientName" \fBchan configure\fR $chan -blocking 0 -buffering line \fBchan event\fR $chan readable [list echoLine $chan $clientName] } # This is called whenever either at least one byte of input # data is available, or the channel was closed by the client. proc echoLine {chan clientName} { \fBchan gets\fR $chan line if {[\fBchan eof\fR $chan]} { log "finishing connection from $clientName" \fBchan close\fR $chan } elseif {![\fBchan blocked\fR $chan]} { # Didn't block waiting for end-of-line log "$clientName - $line" \fBchan puts\fR $chan $line } } # Create the server socket and enter the event-loop to wait # for incoming connections... socket -server connect 12345 vwait forever .CE .SH "SEE ALSO" close(n), eof(n), fblocked(n), fconfigure(n), fcopy(n), file(n), fileevent(n), flush(n), gets(n), open(n), puts(n), read(n), seek(n), socket(n), tell(n), refchan(n), transchan(n) .SH KEYWORDS channel, input, output, events, offset '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/linsert.n0000644000175000017500000000416112663660065014175 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2001 Kevin B. Kenny . All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH linsert n 8.2 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME linsert \- Insert elements into a list .SH SYNOPSIS \fBlinsert \fIlist index \fR?\fIelement element ...\fR? .BE .SH DESCRIPTION .PP This command produces a new list from \fIlist\fR by inserting all of the \fIelement\fR arguments just before the \fIindex\fR'th element of \fIlist\fR. Each \fIelement\fR argument will become a separate element of the new list. If \fIindex\fR is less than or equal to zero, then the new elements are inserted at the beginning of the list, and if \fIindex\fR is greater or equal to the length of \fIlist\fR, it is as if it was \fBend\fR. As with \fBstring index\fR, the \fIindex\fR value supports both simple index arithmetic and end-relative indexing. .PP Subject to the restrictions that indices must refer to locations inside the list and that the \fIelement\fRs will always be inserted in order, insertions are done so that when \fIindex\fR is start-relative, the first \fIelement\fR will be at that index in the resulting list, and when \fIindex\fR is end-relative, the last \fIelement\fR will be at that index in the resulting list. .SH EXAMPLE .PP Putting some values into a list, first indexing from the start and then indexing from the end, and then chaining them together: .PP .CS set oldList {the fox jumps over the dog} set midList [\fBlinsert\fR $oldList 1 quick] set newList [\fBlinsert\fR $midList end-1 lazy] # The old lists still exist though... set newerList [\fBlinsert\fR [\fBlinsert\fR $oldList end-1 quick] 1 lazy] .CE .SH "SEE ALSO" list(n), lappend(n), lindex(n), llength(n), lsearch(n), lset(n), lsort(n), lrange(n), lreplace(n), string(n) .SH KEYWORDS element, insert, list '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/CallDel.30000644000175000017500000000471312663660065013725 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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_CallWhenDeleted 3 7.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CallWhenDeleted, Tcl_DontCallWhenDeleted \- Arrange for callback when interpreter is deleted .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_CallWhenDeleted\fR(\fIinterp\fR, \fIproc\fR, \fIclientData\fR) .sp \fBTcl_DontCallWhenDeleted\fR(\fIinterp\fR, \fIproc\fR, \fIclientData\fR) .SH ARGUMENTS .AS Tcl_InterpDeleteProc clientData .AP Tcl_Interp *interp in Interpreter with which to associated callback. .AP Tcl_InterpDeleteProc *proc in Procedure to call when \fIinterp\fR is deleted. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR. .BE .SH DESCRIPTION .PP \fBTcl_CallWhenDeleted\fR arranges for \fIproc\fR to be called by \fBTcl_DeleteInterp\fR if/when \fIinterp\fR is deleted at some future time. \fIProc\fR will be invoked just before the interpreter is deleted, but the interpreter will still be valid at the time of the call. \fIProc\fR should have arguments and result that match the type \fBTcl_InterpDeleteProc\fR: .PP .CS typedef void \fBTcl_InterpDeleteProc\fR( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR); .CE .PP The \fIclientData\fR and \fIinterp\fR parameters are copies of the \fIclientData\fR and \fIinterp\fR arguments given to \fBTcl_CallWhenDeleted\fR. Typically, \fIclientData\fR points to an application-specific data structure that \fIproc\fR uses to perform cleanup when an interpreter is about to go away. \fIProc\fR does not return a value. .PP \fBTcl_DontCallWhenDeleted\fR cancels a previous call to \fBTcl_CallWhenDeleted\fR with the same arguments, so that \fIproc\fR will not be called after all when \fIinterp\fR is deleted. If there is no deletion callback that matches \fIinterp\fR, \fIproc\fR, and \fIclientData\fR then the call to \fBTcl_DontCallWhenDeleted\fR has no effect. .PP Note that if the callback is being used to delete a resource that \fImust\fR be released on exit, \fBTcl_CreateExitHandler\fR should be used to ensure that a callback is received even if the application terminates without deleting the interpreter. .SH "SEE ALSO" Tcl_CreateExitHandler(3), Tcl_CreateThreadExitHandler(3) .SH KEYWORDS callback, cleanup, delete, interpreter tcl8.6.5/doc/upvar.n0000644000175000017500000001107612663660065013655 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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 upvar n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME upvar \- Create link to variable in a different stack frame .SH SYNOPSIS \fBupvar \fR?\fIlevel\fR? \fIotherVar myVar \fR?\fIotherVar myVar \fR...? .BE .SH DESCRIPTION .PP This command arranges for one or more local variables in the current procedure to refer to variables in an enclosing procedure call or to global variables. \fILevel\fR may have any of the forms permitted for the \fBuplevel\fR command, and may be omitted (it defaults to \fB1\fR). For each \fIotherVar\fR argument, \fBupvar\fR makes the variable by that name in the procedure frame given by \fIlevel\fR (or at global level, if \fIlevel\fR is \fB#0\fR) accessible in the current procedure by the name given in the corresponding \fImyVar\fR argument. The variable named by \fIotherVar\fR need not exist at the time of the call; it will be created the first time \fImyVar\fR is referenced, just like an ordinary variable. There must not exist a variable by the name \fImyVar\fR at the time \fBupvar\fR is invoked. \fIMyVar\fR is always treated as the name of a variable, not an array element. An error is returned if the name looks like an array element, such as \fBa(b)\fR. \fIOtherVar\fR may refer to a scalar variable, an array, or an array element. \fBUpvar\fR returns an empty string. .PP The \fBupvar\fR command simplifies the implementation of call-by-name procedure calling and also makes it easier to build new control constructs as Tcl procedures. For example, consider the following procedure: .PP .CS proc \fIadd2\fR name { \fBupvar\fR $name x set x [expr {$x + 2}] } .CE .PP If \fIadd2\fR is invoked with an argument giving the name of a variable, it adds two to the value of that variable. Although \fIadd2\fR could have been implemented using \fBuplevel\fR instead of \fBupvar\fR, \fBupvar\fR makes it simpler for \fIadd2\fR to access the variable in the caller's procedure frame. .PP \fBnamespace eval\fR is another way (besides procedure calls) that the Tcl naming context can change. It adds a call frame to the stack to represent the namespace context. This means each \fBnamespace eval\fR command counts as another call level for \fBuplevel\fR and \fBupvar\fR commands. For example, \fBinfo level\fR \fB1\fR will return a list describing a command that is either the outermost procedure call or the outermost \fBnamespace eval\fR command. Also, \fBuplevel #0\fR evaluates a script at top-level in the outermost namespace (the global namespace). .PP If an upvar variable is unset (e.g. \fBx\fR in \fBadd2\fR above), the \fBunset\fR operation affects the variable it is linked to, not the upvar variable. There is no way to unset an upvar variable except by exiting the procedure in which it is defined. However, it is possible to retarget an upvar variable by executing another \fBupvar\fR command. .SH "TRACES AND UPVAR" .PP Upvar interacts with traces in a straightforward but possibly unexpected manner. If a variable trace is defined on \fIotherVar\fR, that trace will be triggered by actions involving \fImyVar\fR. However, the trace procedure will be passed the name of \fImyVar\fR, rather than the name of \fIotherVar\fR. Thus, the output of the following code will be .QW "\fIlocalVar\fR" rather than .QW "\fIoriginalVar\fR" : .PP .CS proc \fItraceproc\fR { name index op } { puts $name } proc \fIsetByUpvar\fR { name value } { \fBupvar\fR $name localVar set localVar $value } set originalVar 1 trace variable originalVar w \fItraceproc\fR \fIsetByUpvar\fR originalVar 2 .CE .PP If \fIotherVar\fR refers to an element of an array, then variable traces set for the entire array will not be invoked when \fImyVar\fR is accessed (but traces on the particular element will still be invoked). In particular, if the array is \fBenv\fR, then changes made to \fImyVar\fR will not be passed to subprocesses correctly. .SH EXAMPLE A \fBdecr\fR command that works like \fBincr\fR except it subtracts the value from the variable instead of adding it: .PP .CS proc decr {varName {decrement 1}} { \fBupvar\fR 1 $varName var incr var [expr {-$decrement}] } .CE .SH "SEE ALSO" global(n), namespace(n), uplevel(n), variable(n) .SH KEYWORDS context, frame, global, level, namespace, procedure, upvar, variable .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/StdChannels.30000644000175000017500000001136612663660065014635 0ustar sergeisergei'\" '\" Copyright (c) 2001 by ActiveState Corporation '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH "Standard Channels" 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_StandardChannels \- How the Tcl library deals with the standard channels .BE .SH DESCRIPTION .PP This page explains the initialization and use of standard channels in the Tcl library. .PP The term \fIstandard channels\fR comes out of the Unix world and refers to the three channels automatically opened by the OS for each new application. They are \fBstdin\fR, \fBstdout\fR and \fBstderr\fR. The first is the standard input an application can read from, the other two refer to writable channels, one for regular output and the other for error messages. .PP Tcl generalizes this concept in a cross-platform way and exposes standard channels to the script level. .SS "APPLICATION PROGRAMMING INTERFACES" .PP The public API procedures dealing directly with standard channels are \fBTcl_GetStdChannel\fR and \fBTcl_SetStdChannel\fR. Additional public APIs to consider are \fBTcl_RegisterChannel\fR, \fBTcl_CreateChannel\fR and \fBTcl_GetChannel\fR. .SH "INITIALIZATION OF TCL STANDARD CHANNELS" .PP Standard channels are initialized by the Tcl library in three cases: when explicitly requested, when implicitly required before returning channel information, or when implicitly required during registration of a new channel. .PP These cases differ in how they handle unavailable platform- specific standard channels. (A channel is not .QW available if it could not be successfully opened; for example, in a Tcl application run as a Windows NT service.) .TP 1) A single standard channel is initialized when it is explicitly specified in a call to \fBTcl_SetStdChannel\fR. The states of the other standard channels are unaffected. .RS .PP Missing platform-specific standard channels do not matter here. This approach is not available at the script level. .RE .TP 2) All uninitialized standard channels are initialized to platform-specific default values: .RS .TP (a) when open channels are listed with \fBTcl_GetChannelNames\fR (or the \fBfile channels\fR script command), or .TP (b) when information about any standard channel is requested with a call to \fBTcl_GetStdChannel\fR, or with a call to \fBTcl_GetChannel\fR which specifies one of the standard names (\fBstdin\fR, \fBstdout\fR and \fBstderr\fR). .PP In case of missing platform-specific standard channels, the Tcl standard channels are considered as initialized and then immediately closed. This means that the first three Tcl channels then opened by the application are designated as the Tcl standard channels. .RE .TP 3) All uninitialized standard channels are initialized to platform-specific default values when a user-requested channel is registered with \fBTcl_RegisterChannel\fR. .PP In case of unavailable platform-specific standard channels the channel whose creation caused the initialization of the Tcl standard channels is made a normal channel. The next three Tcl channels opened by the application are designated as the Tcl standard channels. In other words, of the first four Tcl channels opened by the application the second to fourth are designated as the Tcl standard channels. .SH "RE-INITIALIZATION OF TCL STANDARD CHANNELS" .PP Once a Tcl standard channel is initialized through one of the methods above, closing this Tcl standard channel will cause the next call to \fBTcl_CreateChannel\fR to make the new channel the new standard channel, too. If more than one Tcl standard channel was closed \fBTcl_CreateChannel\fR will fill the empty slots in the order \fBstdin\fR, \fBstdout\fR and \fBstderr\fR. .PP \fBTcl_CreateChannel\fR will not try to reinitialize an empty slot if that slot was not initialized before. It is this behavior which enables an application to employ method 1 of initialization, i.e. to create and designate their own Tcl standard channels. .SH "SHELL-SPECIFIC DETAILS" .SS tclsh .PP The Tcl shell (or rather the function \fBTcl_Main\fR, which forms the core of the shell's implementation) uses method 2 to initialize the standard channels. .SS wish .PP The windowing shell (or rather the function \fBTk_MainEx\fR, which forms the core of the shell's implementation) uses method 1 to initialize the standard channels (See \fBTk_InitConsoleChannels\fR) on non-Unix platforms. On Unix platforms, \fBTk_MainEx\fR implicitly uses method 2 to initialize the standard channels. .SH "SEE ALSO" Tcl_CreateChannel(3), Tcl_RegisterChannel(3), Tcl_GetChannel(3), Tcl_GetStdChannel(3), Tcl_SetStdChannel(3), Tk_InitConsoleChannels(3), tclsh(1), wish(1), Tcl_Main(3), Tk_MainEx(3) .SH KEYWORDS standard channels tcl8.6.5/doc/regsub.n0000644000175000017500000001370512663660065014010 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2000 Scriptics Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH regsub n 8.3 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME regsub \- Perform substitutions based on regular expression pattern matching .SH SYNOPSIS \fBregsub \fR?\fIswitches\fR? \fIexp string subSpec \fR?\fIvarName\fR? .BE .SH DESCRIPTION .PP This command matches the regular expression \fIexp\fR against \fIstring\fR, and either copies \fIstring\fR to the variable whose name is given by \fIvarName\fR or returns \fIstring\fR if \fIvarName\fR is not present. (Regular expression matching is described in the \fBre_syntax\fR reference page.) If there is a match, then while copying \fIstring\fR to \fIvarName\fR (or to the result of this command if \fIvarName\fR is not present) the portion of \fIstring\fR that matched \fIexp\fR is replaced with \fIsubSpec\fR. If \fIsubSpec\fR contains a .QW & or .QW \e0 , then it is replaced in the substitution with the portion of \fIstring\fR that matched \fIexp\fR. If \fIsubSpec\fR contains a .QW \e\fIn\fR , where \fIn\fR is a digit between 1 and 9, then it is replaced in the substitution with the portion of \fIstring\fR that matched the \fIn\fR'th parenthesized subexpression of \fIexp\fR. Additional backslashes may be used in \fIsubSpec\fR to prevent special interpretation of .QW & , .QW \e0 , .QW \e\fIn\fR and backslashes. The use of backslashes in \fIsubSpec\fR tends to interact badly with the Tcl parser's use of backslashes, so it is generally safest to enclose \fIsubSpec\fR in braces if it includes backslashes. .LP If the initial arguments to \fBregsub\fR start with \fB\-\fR then they are treated as switches. The following switches are currently supported: .TP \fB\-all\fR . All ranges in \fIstring\fR that match \fIexp\fR are found and substitution is performed for each of these ranges. Without this switch only the first matching range is found and substituted. If \fB\-all\fR is specified, then .QW & and .QW \e\fIn\fR sequences are handled for each substitution using the information from the corresponding match. .TP \fB\-expanded\fR . Enables use of the expanded regular expression syntax where whitespace and comments are ignored. This is the same as specifying the \fB(?x)\fR embedded option (see the \fBre_syntax\fR manual page). .TP \fB\-line\fR . Enables newline-sensitive matching. By default, newline is a completely ordinary character with no special meaning. With this flag, .QW [^ bracket expressions and .QW . never match newline, .QW ^ matches an empty string after any newline in addition to its normal function, and .QW $ matches an empty string before any newline in addition to its normal function. This flag is equivalent to specifying both \fB\-linestop\fR and \fB\-lineanchor\fR, or the \fB(?n)\fR embedded option (see the \fBre_syntax\fR manual page). .TP \fB\-linestop\fR . Changes the behavior of .QW [^ bracket expressions and .QW . so that they stop at newlines. This is the same as specifying the \fB(?p)\fR embedded option (see the \fBre_syntax\fR manual page). .TP \fB\-lineanchor\fR . Changes the behavior of .QW ^ and .QW $ (the .QW anchors ) so they match the beginning and end of a line respectively. This is the same as specifying the \fB(?w)\fR embedded option (see the \fBre_syntax\fR manual page). .TP \fB\-nocase\fR . Upper-case characters in \fIstring\fR will be converted to lower-case before matching against \fIexp\fR; however, substitutions specified by \fIsubSpec\fR use the original unconverted form of \fIstring\fR. .TP \fB\-start\fR \fIindex\fR . Specifies a character index offset into the string to start matching the regular expression at. The \fIindex\fR value is interpreted in the same manner as the \fIindex\fR argument to \fBstring index\fR. When using this switch, .QW ^ will not match the beginning of the line, and \eA will still match the start of the string at \fIindex\fR. \fIindex\fR will be constrained to the bounds of the input string. .TP \fB\-\|\-\fR . Marks the end of switches. The argument following this one will be treated as \fIexp\fR even if it starts with a \fB\-\fR. .PP If \fIvarName\fR is supplied, the command returns a count of the number of matching ranges that were found and replaced, otherwise the string after replacement is returned. See the manual entry for \fBregexp\fR for details on the interpretation of regular expressions. .SH EXAMPLES .PP Replace (in the string in variable \fIstring\fR) every instance of \fBfoo\fR which is a word by itself with \fBbar\fR: .PP .CS \fBregsub\fR -all {\emfoo\eM} $string bar string .CE .PP or (using the .QW "basic regular expression" syntax): .PP .CS \fBregsub\fR -all {(?b)\e} $string bar string .CE .PP Insert double-quotes around the first instance of the word \fBinteresting\fR, however it is capitalized. .PP .CS \fBregsub\fR -nocase {\eyinteresting\ey} $string {"&"} string .CE .PP Convert all non-ASCII and Tcl-significant characters into \eu escape sequences by using \fBregsub\fR and \fBsubst\fR in combination: .PP .CS # This RE is just a character class for almost everything "bad" set RE {[][{};#\e\e\e$ \er\et\eu0080-\euffff]} # We will substitute with a fragment of Tcl script in brackets set substitution {[format \e\e\e\eu%04x [scan "\e\e&" %c]]} # Now we apply the substitution to get a subst-string that # will perform the computational parts of the conversion. Note # that newline is handled specially through \fBstring map\fR since # backslash-newline is a special sequence. set quoted [subst [string map {\en {\e\eu000a}} \e [\fBregsub\fR -all $RE $string $substitution]]] .CE .SH "SEE ALSO" regexp(n), re_syntax(n), subst(n), string(n) .SH KEYWORDS match, pattern, quoting, regular expression, substitution '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/fblocked.n0000644000175000017500000000447612663653206014276 0ustar sergeisergei'\" '\" Copyright (c) 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 fblocked n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fblocked \- Test whether the last input operation exhausted all available input .SH SYNOPSIS \fBfblocked \fIchannelId\fR .BE .SH DESCRIPTION .PP The \fBfblocked\fR command returns 1 if the most recent input operation on \fIchannelId\fR returned less information than requested because all available input was exhausted. For example, if \fBgets\fR is invoked when there are only three characters available for input and no end-of-line sequence, \fBgets\fR returns an empty string and a subsequent call to \fBfblocked\fR will return 1. .PP \fIChannelId\fR must be an identifier for an open channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. .SH EXAMPLE The \fBfblocked\fR command is particularly useful when writing network servers, as it allows you to write your code in a line-by-line style without preventing the servicing of other connections. This can be seen in this simple echo-service: .PP .CS # This is called whenever a new client connects to the server proc connect {chan host port} { set clientName [format <%s:%d> $host $port] puts "connection from $clientName" fconfigure $chan -blocking 0 -buffering line fileevent $chan readable [list echoLine $chan $clientName] } # This is called whenever either at least one byte of input # data is available, or the channel was closed by the client. proc echoLine {chan clientName} { gets $chan line if {[eof $chan]} { puts "finishing connection from $clientName" close $chan } elseif {![\fBfblocked\fR $chan]} { # Didn't block waiting for end-of-line puts "$clientName - $line" puts $chan $line } } # Create the server socket and enter the event-loop to wait # for incoming connections... socket -server connect 12345 vwait forever .CE .SH "SEE ALSO" gets(n), open(n), read(n), socket(n), Tcl_StandardChannels(3) .SH KEYWORDS blocking, nonblocking tcl8.6.5/doc/Alloc.30000644000175000017500000000575212663660065013463 0ustar sergeisergei'\" '\" 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_Alloc 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_Alloc, Tcl_Free, Tcl_Realloc, Tcl_AttemptAlloc, Tcl_AttemptRealloc, ckalloc, ckfree, ckrealloc, attemptckalloc, attemptckrealloc \- allocate or free heap memory .SH SYNOPSIS .nf \fB#include \fR .sp char * \fBTcl_Alloc\fR(\fIsize\fR) .sp void \fBTcl_Free\fR(\fIptr\fR) .sp char * \fBTcl_Realloc\fR(\fIptr, size\fR) .sp char * \fBTcl_AttemptAlloc\fR(\fIsize\fR) .sp char * \fBTcl_AttemptRealloc\fR(\fIptr, size\fR) .sp char * \fBckalloc\fR(\fIsize\fR) .sp void \fBckfree\fR(\fIptr\fR) .sp char * \fBckrealloc\fR(\fIptr, size\fR) .sp char * \fBattemptckalloc\fR(\fIsize\fR) .sp char * \fBattemptckrealloc\fR(\fIptr, size\fR) .SH ARGUMENTS .AS char *size .AP "unsigned int" size in Size in bytes of the memory block to allocate. .AP char *ptr in Pointer to memory block to free or realloc. .BE .SH DESCRIPTION .PP These procedures provide a platform and compiler independent interface for memory allocation. Programs that need to transfer ownership of memory blocks between Tcl and other modules should use these routines rather than the native \fBmalloc()\fR and \fBfree()\fR routines provided by the C run-time library. .PP \fBTcl_Alloc\fR returns a pointer to a block of at least \fIsize\fR bytes suitably aligned for any use. .PP \fBTcl_Free\fR makes the space referred to by \fIptr\fR available for further allocation. .PP \fBTcl_Realloc\fR changes the size of the block pointed to by \fIptr\fR to \fIsize\fR bytes and returns a pointer to the new block. The contents will be unchanged up to the lesser of the new and old sizes. The returned location may be different from \fIptr\fR. If \fIptr\fR is NULL, this is equivalent to calling \fBTcl_Alloc\fR with just the \fIsize\fR argument. .PP \fBTcl_AttemptAlloc\fR and \fBTcl_AttemptRealloc\fR are identical in function to \fBTcl_Alloc\fR and \fBTcl_Realloc\fR, except that \fBTcl_AttemptAlloc\fR and \fBTcl_AttemptRealloc\fR will not cause the Tcl interpreter to \fBpanic\fR if the memory allocation fails. If the allocation fails, these functions will return NULL. Note that on some platforms, but not all, attempting to allocate a zero-sized block of memory will also cause these functions to return NULL. .PP The procedures \fBckalloc\fR, \fBckfree\fR, \fBckrealloc\fR, \fBattemptckalloc\fR, and \fBattemptckrealloc\fR are implemented as macros. Normally, they are synonyms for the corresponding procedures documented on this page. When Tcl and all modules calling Tcl are compiled with \fBTCL_MEM_DEBUG\fR defined, however, these macros are redefined to be special debugging versions of these procedures. To support Tcl's memory debugging within a module, use the macros rather than direct calls to \fBTcl_Alloc\fR, etc. .SH KEYWORDS alloc, allocation, free, malloc, memory, realloc, TCL_MEM_DEBUG tcl8.6.5/doc/Class.30000644000175000017500000002421212663660065013466 0ustar sergeisergei'\" '\" Copyright (c) 2007 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_Class 3 0.1 TclOO "TclOO Library Functions" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_ClassGetMetadata, Tcl_ClassSetMetadata, Tcl_CopyObjectInstance, Tcl_GetClassAsObject, Tcl_GetObjectAsClass, Tcl_GetObjectCommand, Tcl_GetObjectFromObj, Tcl_GetObjectName, Tcl_GetObjectNamespace, Tcl_NewObjectInstance, Tcl_ObjectDeleted, Tcl_ObjectGetMetadata, Tcl_ObjectGetMethodNameMapper, Tcl_ObjectSetMetadata, Tcl_ObjectSetMethodNameMapper \- manipulate objects and classes .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Object \fBTcl_GetObjectFromObj\fR(\fIinterp, objPtr\fR) .sp Tcl_Object \fBTcl_GetClassAsObject\fR(\fIclass\fR) .sp Tcl_Class \fBTcl_GetObjectAsClass\fR(\fIobject\fR) .sp Tcl_Obj * \fBTcl_GetObjectName\fR(\fIinterp, object\fR) .sp Tcl_Command \fBTcl_GetObjectCommand\fR(\fIobject\fR) .sp Tcl_Namespace * \fBTcl_GetObjectNamespace\fR(\fIobject\fR) .sp Tcl_Object \fBTcl_NewObjectInstance\fR(\fIinterp, class, name, nsName, objc, objv, skip\fR) .sp Tcl_Object \fBTcl_CopyObjectInstance\fR(\fIinterp, object, name, nsName\fR) .sp int \fBTcl_ObjectDeleted\fR(\fIobject\fR) .sp ClientData \fBTcl_ObjectGetMetadata\fR(\fIobject, metaTypePtr\fR) .sp \fBTcl_ObjectSetMetadata\fR(\fIobject, metaTypePtr, metadata\fR) .sp ClientData \fBTcl_ClassGetMetadata\fR(\fIclass, metaTypePtr\fR) .sp \fBTcl_ClassSetMetadata\fR(\fIclass, metaTypePtr, metadata\fR) .sp Tcl_ObjectMapMethodNameProc \fBTcl_ObjectGetMethodNameMapper\fR(\fIobject\fR) .sp \fBTcl_ObjectSetMethodNameMapper\fR(\fIobject\fR, \fImethodNameMapper\fR) .SH ARGUMENTS .AS ClientData metadata in/out .AP Tcl_Interp *interp in/out Interpreter providing the context for looking up or creating an object, and into whose result error messages will be written on failure. .AP Tcl_Obj *objPtr in The name of the object to look up. .AP Tcl_Object object in Reference to the object to operate upon. .AP Tcl_Class class in Reference to the class to operate upon. .AP "const char" *name in The name of the object to create, or NULL if a new unused name is to be automatically selected. .AP "const char" *nsName in The name of the namespace to create for the object's private use, or NULL if a new unused name is to be automatically selected. The namespace must not already exist. .AP int objc in The number of elements in the \fIobjv\fR array. .AP "Tcl_Obj *const" *objv in The arguments to the command to create the instance of the class. .AP int skip in The number of arguments at the start of the argument array, \fIobjv\fR, that are not arguments to any constructors. .AP Tcl_ObjectMetadataType *metaTypePtr in The type of \fImetadata\fR being set with \fBTcl_ClassSetMetadata\fR or retrieved with \fBTcl_ClassGetMetadata\fR. .AP ClientData metadata in An item of metadata to attach to the class, or NULL to remove the metadata associated with a particular \fImetaTypePtr\fR. .AP "Tcl_ObjectMapMethodNameProc" "methodNameMapper" in A pointer to a function to call to adjust the mapping of objects and method names to implementations, or NULL when no such mapping is required. .BE .SH DESCRIPTION .PP Objects are typed entities that have a set of operations ("methods") associated with them. Classes are objects that can manufacture objects. Each class can be viewed as an object itself; the object view can be retrieved using \fBTcl_GetClassAsObject\fR which always returns the object when applied to a non-destroyed class, and an object can be viewed as a class with the aid of the \fBTcl_GetObjectAsClass\fR (which either returns the class, or NULL if the object is not a class). An object may be looked up using the \fBTcl_GetObjectFromObj\fR function, which either returns an object or NULL (with an error message in the interpreter result) if the object cannot be found. The correct way to look up a class by name is to look up the object with that name, and then to use \fBTcl_GetObjectAsClass\fR. .PP Every object has its own command and namespace associated with it. The command may be retrieved using the \fBTcl_GetObjectCommand\fR function, the name of the object (and hence the name of the command) with \fBTcl_GetObjectName\fR, and the namespace may be retrieved using the \fBTcl_GetObjectNamespace\fR function. Note that the Tcl_Obj reference returned by \fBTcl_GetObjectName\fR is a shared reference. .PP Instances of classes are created using \fBTcl_NewObjectInstance\fR, which creates an object from any class (and which is internally called by both the \fBcreate\fR and \fBnew\fR methods of the \fBoo::class\fR class). It takes parameters that optionally give the name of the object and namespace to create, and which describe the arguments to pass to the class's constructor (if any). The result of the function will be either a reference to the newly created object, or NULL if the creation failed (when an error message will be left in the interpreter result). In addition, objects may be copied by using \fBTcl_CopyObjectInstance\fR which creates a copy of an object without running any constructors. .SH "OBJECT AND CLASS METADATA" .PP Every object and every class may have arbitrary amounts of metadata attached to it, which the object or class attaches no meaning to beyond what is described in a Tcl_ObjectMetadataType structure instance. Metadata to be attached is described by the type of the metadata (given in the \fImetaTypePtr\fR argument) and an arbitrary pointer (the \fImetadata\fR argument) that are given to \fBTcl_ObjectSetMetadata\fR and \fBTcl_ClassSetMetadata\fR, and a particular piece of metadata can be retrieved given its type using \fBTcl_ObjectGetMetadata\fR and \fBTcl_ClassGetMetadata\fR. If the \fImetadata\fR parameter to either \fBTcl_ObjectSetMetadata\fR or \fBTcl_ClassSetMetadata\fR is NULL, the metadata is removed if it was attached, and the results of \fBTcl_ObjectGetMetadata\fR and \fBTcl_ClassGetMetadata\fR are NULL if the given type of metadata was not attached. It is not an error to request or remove a piece of metadata that was not attached. .SS "TCL_OBJECTMETADATATYPE STRUCTURE" .PP The contents of the Tcl_ObjectMetadataType structure are as follows: .PP .CS typedef const struct { int \fIversion\fR; const char *\fIname\fR; Tcl_ObjectMetadataDeleteProc *\fIdeleteProc\fR; Tcl_CloneProc *\fIcloneProc\fR; } \fBTcl_ObjectMetadataType\fR; .CE .PP The \fIversion\fR field allows for future expansion of the structure, and should always be declared equal to TCL_OO_METADATA_VERSION_CURRENT. The \fIname\fR field provides a human-readable name for the type, and is reserved for debugging. .PP The \fIdeleteProc\fR field gives a function of type Tcl_ObjectMetadataDeleteProc that is used to delete a particular piece of metadata, and is called when the attached metadata is replaced or removed; the field must not be NULL. .PP The \fIcloneProc\fR field gives a function that is used to copy a piece of metadata (used when a copy of an object is created using \fBTcl_CopyObjectInstance\fR); if NULL, the metadata will be just directly copied. .SS "TCL_OBJECTMETADATADELETEPROC FUNCTION SIGNATURE" .PP Functions matching this signature are used to delete metadata associated with a class or object. .PP .CS typedef void \fBTcl_ObjectMetadataDeleteProc\fR( ClientData \fImetadata\fR); .CE .PP The \fImetadata\fR argument gives the address of the metadata to be deleted. .SS "TCL_CLONEPROC FUNCTION SIGNATURE" .PP Functions matching this signature are used to create copies of metadata associated with a class or object. .PP .CS typedef int \fBTcl_CloneProc\fR( Tcl_Interp *\fIinterp\fR, ClientData \fIsrcMetadata\fR, ClientData *\fIdstMetadataPtr\fR); .CE .PP The \fIinterp\fR argument gives a place to write an error message when the attempt to clone the object is to fail, in which case the clone procedure must also return TCL_ERROR; it should return TCL_OK otherwise. The \fIsrcMetadata\fR argument gives the address of the metadata to be cloned, and the cloned metadata should be written into the variable pointed to by \fIdstMetadataPtr\fR; a NULL should be written if the metadata is to not be cloned but the overall object copy operation is still to succeed. .SH "OBJECT METHOD NAME MAPPING" It is possible to control, on a per-object basis, what methods are invoked when a particular method is invoked. Normally this is done by looking up the method name in the object and then in the class hierarchy, but fine control of exactly what the value used to perform the look up is afforded through the ability to set a method name mapper callback via \fBTcl_ObjectSetMethodNameMapper\fR (and its introspection counterpart, \fBTcl_ObjectGetMethodNameMapper\fR, which returns the current mapper). The current mapper (if any) is invoked immediately before looking up what chain of method implementations is to be used. .SS "TCL_OBJECTMAPMETHODNAMEPROC FUNCTION SIGNATURE" The \fITcl_ObjectMapMethodNameProc\fR callback is defined as follows: .PP .CS typedef int \fBTcl_ObjectMapMethodNameProc\fR( Tcl_Interp *\fIinterp\fR, Tcl_Object \fIobject\fR, Tcl_Class *\fIstartClsPtr\fR, Tcl_Obj *\fImethodNameObj\fR); .CE .PP If the result is TCL_OK, the remapping is assumed to have been done. If the result is TCL_ERROR, an error message will have been left in \fIinterp\fR and the method call will fail. If the result is TCL_BREAK, the standard method name lookup rules will be used; the behavior of other result codes is currently undefined. The \fIobject\fR parameter says which object is being processed. The \fIstartClsPtr\fR parameter points to a variable that contains the first class to provide a definition in the method chain to process, or NULL if the whole chain is to be processed (the argument itself is never NULL); this variable may be updated by the callback. The \fImethodNameObj\fR parameter gives an unshared object containing the name of the method being invoked, as provided by the user; this object may be updated by the callback. .SH "SEE ALSO" Method(3), oo::class(n), oo::copy(n), oo::define(n), oo::object(n) .SH KEYWORDS class, constructor, object .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: tcl8.6.5/doc/puts.n0000644000175000017500000000655112663660065013515 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 puts n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME puts \- Write to a channel .SH SYNOPSIS \fBputs \fR?\fB\-nonewline\fR? ?\fIchannelId\fR? \fIstring\fR .BE .SH DESCRIPTION .PP Writes the characters given by \fIstring\fR to the channel given by \fIchannelId\fR. .PP \fIChannelId\fR must be an identifier for an open channel such as a Tcl standard channel (\fBstdout\fR or \fBstderr\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. The channel must have been opened for output. .PP If no \fIchannelId\fR is specified then it defaults to \fBstdout\fR. \fBPuts\fR normally outputs a newline character after \fIstring\fR, but this feature may be suppressed by specifying the \fB\-nonewline\fR switch. .PP Newline characters in the output are translated by \fBputs\fR to platform-specific end-of-line sequences according to the current value of the \fB\-translation\fR option for the channel (for example, on PCs newlines are normally replaced with carriage-return-linefeed sequences. See the \fBfconfigure\fR manual entry for a discussion on ways in which \fBfconfigure\fR will alter output. .PP Tcl buffers output internally, so characters written with \fBputs\fR may not appear immediately on the output file or device; Tcl will normally delay output until the buffer is full or the channel is closed. You can force output to appear immediately with the \fBflush\fR command. .PP When the output buffer fills up, the \fBputs\fR command will normally block until all the buffered data has been accepted for output by the operating system. If \fIchannelId\fR is in nonblocking mode then the \fBputs\fR command will not block even if the operating system cannot accept the data. Instead, Tcl continues to buffer the data and writes it in the background as fast as the underlying file or device can accept it. The application must use the Tcl event loop for nonblocking output to work; otherwise Tcl never finds out that the file or device is ready for more output data. It is possible for an arbitrarily large amount of data to be buffered for a channel in nonblocking mode, which could consume a large amount of memory. To avoid wasting memory, nonblocking I/O should normally be used in an event-driven fashion with the \fBfileevent\fR command (do not invoke \fBputs\fR unless you have recently been notified via a file event that the channel is ready for more output data). .SH EXAMPLES .PP Write a short message to the console (or wherever \fBstdout\fR is directed): .PP .CS \fBputs\fR "Hello, World!" .CE .PP Print a message in several parts: .PP .CS \fBputs\fR -nonewline "Hello, " \fBputs\fR "World!" .CE .PP Print a message to the standard error channel: .PP .CS \fBputs\fR stderr "Hello, World!" .CE .PP Append a log message to a file: .PP .CS set chan [open my.log a] set timestamp [clock format [clock seconds]] \fBputs\fR $chan "$timestamp - Hello, World!" close $chan .CE .SH "SEE ALSO" file(n), fileevent(n), Tcl_StandardChannels(3) .SH KEYWORDS channel, newline, output, write tcl8.6.5/doc/ToUpper.30000644000175000017500000000565312663660065014027 0ustar sergeisergei'\" '\" Copyright (c) 1997 by Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_UtfToUpper 3 "8.1" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_UniCharToUpper, Tcl_UniCharToLower, Tcl_UniCharToTitle, Tcl_UtfToUpper, Tcl_UtfToLower, Tcl_UtfToTitle \- routines for manipulating the case of Unicode characters and UTF-8 strings .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_UniChar \fBTcl_UniCharToUpper\fR(\fIch\fR) .sp Tcl_UniChar \fBTcl_UniCharToLower\fR(\fIch\fR) .sp Tcl_UniChar \fBTcl_UniCharToTitle\fR(\fIch\fR) .sp int \fBTcl_UtfToUpper\fR(\fIstr\fR) .sp int \fBTcl_UtfToLower\fR(\fIstr\fR) .sp int \fBTcl_UtfToTitle\fR(\fIstr\fR) .SH ARGUMENTS .AS char *str in/out .AP int ch in The Tcl_UniChar to be converted. .AP char *str in/out Pointer to UTF-8 string to be converted in place. .BE .SH DESCRIPTION .PP The first three routines convert the case of individual Unicode characters: .PP If \fIch\fR represents a lower-case character, \fBTcl_UniCharToUpper\fR returns the corresponding upper-case character. If no upper-case character is defined, it returns the character unchanged. .PP If \fIch\fR represents an upper-case character, \fBTcl_UniCharToLower\fR returns the corresponding lower-case character. If no lower-case character is defined, it returns the character unchanged. .PP If \fIch\fR represents a lower-case character, \fBTcl_UniCharToTitle\fR returns the corresponding title-case character. If no title-case character is defined, it returns the corresponding upper-case character. If no upper-case character is defined, it returns the character unchanged. Title-case is defined for a small number of characters that have a different appearance when they are at the beginning of a capitalized word. .PP The next three routines convert the case of UTF-8 strings in place in memory: .PP \fBTcl_UtfToUpper\fR changes every UTF-8 character in \fIstr\fR to upper-case. Because changing the case of a character may change its size, the byte offset of each character in the resulting string may differ from its original location. \fBTcl_UtfToUpper\fR writes a null byte at the end of the converted string. \fBTcl_UtfToUpper\fR returns the new length of the string in bytes. This new length is guaranteed to be no longer than the original string length. .PP \fBTcl_UtfToLower\fR is the same as \fBTcl_UtfToUpper\fR except it turns each character in the string into its lower-case equivalent. .PP \fBTcl_UtfToTitle\fR is the same as \fBTcl_UtfToUpper\fR except it turns the first character in the string into its title-case equivalent and all following characters into their lower-case equivalents. .SH BUGS .PP At this time, the case conversions are only defined for the ISO8859-1 characters. Unicode characters above 0x00ff are not modified by these routines. .SH KEYWORDS utf, unicode, toupper, tolower, totitle, case tcl8.6.5/doc/rename.n0000644000175000017500000000264312663660065013767 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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 rename n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME rename \- Rename or delete a command .SH SYNOPSIS \fBrename \fIoldName newName\fR .BE .SH DESCRIPTION .PP Rename the command that used to be called \fIoldName\fR so that it is now called \fInewName\fR. If \fInewName\fR is an empty string then \fIoldName\fR is deleted. \fIoldName\fR and \fInewName\fR may include namespace qualifiers (names of containing namespaces). If a command is renamed into a different namespace, future invocations of it will execute in the new namespace. The \fBrename\fR command returns an empty string as result. .SH EXAMPLE .PP The \fBrename\fR command can be used to wrap the standard Tcl commands with your own monitoring machinery. For example, you might wish to count how often the \fBsource\fR command is called: .PP .CS \fBrename\fR ::source ::theRealSource set sourceCount 0 proc ::source args { global sourceCount puts "called source for the [incr sourceCount]'th time" uplevel 1 ::theRealSource $args } .CE .SH "SEE ALSO" namespace(n), proc(n) .SH KEYWORDS command, delete, namespace, rename tcl8.6.5/doc/GetStdChan.30000644000175000017500000000702312663660065014406 0ustar sergeisergei'\" '\" Copyright (c) 1996 by Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_GetStdChannel 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_GetStdChannel, Tcl_SetStdChannel \- procedures for retrieving and replacing the standard channels .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Channel \fBTcl_GetStdChannel\fR(\fItype\fR) .sp \fBTcl_SetStdChannel\fR(\fIchannel, type\fR) .sp .SH ARGUMENTS .AS Tcl_Channel channel .AP int type in The identifier for the standard channel to retrieve or modify. Must be one of \fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, or \fBTCL_STDERR\fR. .AP Tcl_Channel channel in The channel to use as the new value for the specified standard channel. .BE .SH DESCRIPTION .PP Tcl defines three special channels that are used by various I/O related commands if no other channels are specified. The standard input channel has a channel name of \fBstdin\fR and is used by \fBread\fR and \fBgets\fR. The standard output channel is named \fBstdout\fR and is used by \fBputs\fR. The standard error channel is named \fBstderr\fR and is used for reporting errors. In addition, the standard channels are inherited by any child processes created using \fBexec\fR or \fBopen\fR in the absence of any other redirections. .PP The standard channels are actually aliases for other normal channels. The current channel associated with a standard channel can be retrieved by calling \fBTcl_GetStdChannel\fR with one of \fBTCL_STDIN\fR, \fBTCL_STDOUT\fR, or \fBTCL_STDERR\fR as the \fItype\fR. The return value will be a valid channel, or NULL. .PP A new channel can be set for the standard channel specified by \fItype\fR by calling \fBTcl_SetStdChannel\fR with a new channel or NULL in the \fIchannel\fR argument. If the specified channel is closed by a later call to \fBTcl_Close\fR, then the corresponding standard channel will automatically be set to NULL. .PP If a non-NULL value for \fIchannel\fR is passed to \fBTcl_SetStdChannel\fR, then that same value should be passed to \fBTcl_RegisterChannel\fR, like so: .PP .CS Tcl_RegisterChannel(NULL, channel); .CE .PP This is a workaround for a misfeature in \fBTcl_SetStdChannel\fR that it fails to do some reference counting housekeeping. This misfeature cannot be corrected without contradicting the assumptions of some existing code that calls \fBTcl_SetStdChannel\fR. .PP If \fBTcl_GetStdChannel\fR is called before \fBTcl_SetStdChannel\fR, Tcl will construct a new channel to wrap the appropriate platform-specific standard file handle. If \fBTcl_SetStdChannel\fR is called before \fBTcl_GetStdChannel\fR, then the default channel will not be created. .PP If one of the standard channels is set to NULL, either by calling \fBTcl_SetStdChannel\fR with a NULL \fIchannel\fR argument, or by calling \fBTcl_Close\fR on the channel, then the next call to \fBTcl_CreateChannel\fR will automatically set the standard channel with the newly created channel. If more than one standard channel is NULL, then the standard channels will be assigned starting with standard input, followed by standard output, with standard error being last. .PP See \fBTcl_StandardChannels\fR for a general treatise about standard channels and the behavior of the Tcl library with regard to them. .SH "SEE ALSO" Tcl_Close(3), Tcl_CreateChannel(3), Tcl_Main(3), tclsh(1) .SH KEYWORDS standard channel, standard input, standard output, standard error tcl8.6.5/doc/global.n0000644000175000017500000000351612663660065013760 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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 global n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME global \- Access global variables .SH SYNOPSIS \fBglobal \fR?\fIvarname ...\fR? .BE .SH DESCRIPTION .PP This command has no effect unless executed in the context of a proc body. If the \fBglobal\fR command is executed in the context of a proc body, it creates local variables linked to the corresponding global variables (though these linked variables, like those created by \fBupvar\fR, are not included in the list returned by \fBinfo locals\fR). .PP If \fIvarname\fR contains namespace qualifiers, the local variable's name is the unqualified name of the global variable, as determined by the \fBnamespace tail\fR command. .PP \fIvarname\fR is always treated as the name of a variable, not an array element. An error is returned if the name looks like an array element, such as \fBa(b)\fR. .SH EXAMPLES .PP This procedure sets the namespace variable \fI::a::x\fR .PP .CS proc reset {} { \fBglobal\fR a::x set x 0 } .CE .PP This procedure accumulates the strings passed to it in a global buffer, separated by newlines. It is useful for situations when you want to build a message piece-by-piece (as if with \fBputs\fR) but send that full message in a single piece (e.g. over a connection opened with \fBsocket\fR or as part of a counted HTTP response). .PP .CS proc accum {string} { \fBglobal\fR accumulator append accumulator $string \en } .CE .SH "SEE ALSO" namespace(n), upvar(n), variable(n) .SH KEYWORDS global, namespace, procedure, variable tcl8.6.5/doc/OpenTcp.30000644000175000017500000001651112663660065013774 0ustar sergeisergei'\" '\" Copyright (c) 1996-7 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_OpenTcpClient 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_OpenTcpClient, Tcl_MakeTcpClientChannel, Tcl_OpenTcpServer \- procedures to open channels using TCP sockets .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Channel \fBTcl_OpenTcpClient\fR(\fIinterp, port, host, myaddr, myport, async\fR) .sp Tcl_Channel \fBTcl_MakeTcpClientChannel\fR(\fIsock\fR) .sp Tcl_Channel \fBTcl_OpenTcpServer\fR(\fIinterp, port, myaddr, proc, clientData\fR) .sp .SH ARGUMENTS .AS Tcl_TcpAcceptProc clientData .AP Tcl_Interp *interp in Tcl interpreter to use for error reporting. If non-NULL and an error occurs, an error message is left in the interpreter's result. .AP int port in A port number to connect to as a client or to listen on as a server. .AP "const char" *host in A string specifying a host name or address for the remote end of the connection. .AP int myport in A port number for the client's end of the socket. If 0, a port number is allocated at random. .AP "const char" *myaddr in A string specifying the host name or address for network interface to use for the local end of the connection. If NULL, a default interface is chosen. .AP int async in If nonzero, the client socket is connected asynchronously to the server. .AP ClientData sock in Platform-specific handle for client TCP socket. .AP Tcl_TcpAcceptProc *proc in Pointer to a procedure to invoke each time a new connection is accepted via the socket. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR. .BE .SH DESCRIPTION .PP These functions are convenience procedures for creating channels that communicate over TCP sockets. The operations on a channel are described in the manual entry for \fBTcl_OpenFileChannel\fR. .SS TCL_OPENTCPCLIENT .PP \fBTcl_OpenTcpClient\fR opens a client TCP socket connected to a \fIport\fR on a specific \fIhost\fR, and returns a channel that can be used to communicate with the server. The host to connect to can be specified either as a domain name style name (e.g. \fBwww.sunlabs.com\fR), or as a string containing the alphanumeric representation of its four-byte address (e.g. \fB127.0.0.1\fR). Use the string \fBlocalhost\fR to connect to a TCP socket on the host on which the function is invoked. .PP The \fImyaddr\fR and \fImyport\fR arguments allow a client to specify an address for the local end of the connection. If \fImyaddr\fR is NULL, then an interface is chosen automatically by the operating system. If \fImyport\fR is 0, then a port number is chosen at random by the operating system. .PP If \fIasync\fR is zero, the call to \fBTcl_OpenTcpClient\fR returns only after the client socket has either successfully connected to the server, or the attempted connection has failed. If \fIasync\fR is nonzero the socket is connected asynchronously and the returned channel may not yet be connected to the server when the call to \fBTcl_OpenTcpClient\fR returns. If the channel is in blocking mode and an input or output operation is done on the channel before the connection is completed or fails, that operation will wait until the connection either completes successfully or fails. If the channel is in nonblocking mode, the input or output operation will return immediately and a subsequent call to \fBTcl_InputBlocked\fR on the channel will return nonzero. .PP The returned channel is opened for reading and writing. If an error occurs in opening the socket, \fBTcl_OpenTcpClient\fR returns NULL and records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. In addition, if \fIinterp\fR is non-NULL, an error message is left in the interpreter's result. .PP The newly created channel is not registered in the supplied interpreter; to register it, use \fBTcl_RegisterChannel\fR. If one of the standard channels, \fBstdin\fR, \fBstdout\fR or \fBstderr\fR was previously closed, the act of creating the new channel also assigns it as a replacement for the standard channel. .SS TCL_MAKETCPCLIENTCHANNEL .PP \fBTcl_MakeTcpClientChannel\fR creates a \fBTcl_Channel\fR around an existing, platform specific, handle for a client TCP socket. .PP The newly created channel is not registered in the supplied interpreter; to register it, use \fBTcl_RegisterChannel\fR. If one of the standard channels, \fBstdin\fR, \fBstdout\fR or \fBstderr\fR was previously closed, the act of creating the new channel also assigns it as a replacement for the standard channel. .SS TCL_OPENTCPSERVER .PP \fBTcl_OpenTcpServer\fR opens a TCP socket on the local host on a specified \fIport\fR and uses the Tcl event mechanism to accept requests from clients to connect to it. The \fImyaddr\fR argument specifies the network interface. If \fImyaddr\fR is NULL the special address INADDR_ANY should be used to allow connections from any network interface. Each time a client connects to this socket, Tcl creates a channel for the new connection and invokes \fIproc\fR with information about the channel. \fIProc\fR must match the following prototype: .PP .CS typedef void \fBTcl_TcpAcceptProc\fR( ClientData \fIclientData\fR, Tcl_Channel \fIchannel\fR, char *\fIhostName\fR, int \fIport\fR); .CE .PP The \fIclientData\fR argument will be the same as the \fIclientData\fR argument to \fBTcl_OpenTcpServer\fR, \fIchannel\fR will be the handle for the new channel, \fIhostName\fR points to a string containing the name of the client host making the connection, and \fIport\fR will contain the client's port number. The new channel is opened for both input and output. If \fIproc\fR raises an error, the connection is closed automatically. \fIProc\fR has no return value, but if it wishes to reject the connection it can close \fIchannel\fR. .PP \fBTcl_OpenTcpServer\fR normally returns a pointer to a channel representing the server socket. If an error occurs, \fBTcl_OpenTcpServer\fR returns NULL and records a POSIX error code that can be retrieved with \fBTcl_GetErrno\fR. In addition, if the interpreter is non-NULL, an error message is left in the interpreter's result. .PP The channel returned by \fBTcl_OpenTcpServer\fR cannot be used for either input or output. It is simply a handle for the socket used to accept connections. The caller can close the channel to shut down the server and disallow further connections from new clients. .PP TCP server channels operate correctly only in applications that dispatch events through \fBTcl_DoOneEvent\fR or through Tcl commands such as \fBvwait\fR; otherwise Tcl will never notice that a connection request from a remote client is pending. .PP The newly created channel is not registered in the supplied interpreter; to register it, use \fBTcl_RegisterChannel\fR. If one of the standard channels, \fBstdin\fR, \fBstdout\fR or \fBstderr\fR was previously closed, the act of creating the new channel also assigns it as a replacement for the standard channel. .SH "PLATFORM ISSUES" .PP On Unix platforms, the socket handle is a Unix file descriptor as returned by the \fBsocket\fR system call. On the Windows platform, the socket handle is a \fBSOCKET\fR as defined in the WinSock API. .SH "SEE ALSO" Tcl_OpenFileChannel(3), Tcl_RegisterChannel(3), vwait(n) .SH KEYWORDS channel, client, server, socket, TCP tcl8.6.5/doc/ExprLongObj.30000644000175000017500000000716012663660065014615 0ustar sergeisergei'\" '\" Copyright (c) 1996-1997 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_ExprLongObj 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj, Tcl_ExprObj \- evaluate an expression .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_ExprLongObj\fR(\fIinterp, objPtr, longPtr\fR) .sp int \fBTcl_ExprDoubleObj\fR(\fIinterp, objPtr, doublePtr\fR) .sp int \fBTcl_ExprBooleanObj\fR(\fIinterp, objPtr, booleanPtr\fR) .sp int \fBTcl_ExprObj\fR(\fIinterp, objPtr, resultPtrPtr\fR) .SH ARGUMENTS .AS Tcl_Interp **resultPtrPtr out .AP Tcl_Interp *interp in Interpreter in whose context to evaluate \fIobjPtr\fR. .AP Tcl_Obj *objPtr in Pointer to a value containing the expression to evaluate. .AP long *longPtr out Pointer to location in which to store the integer value of the expression. .AP int *doublePtr out Pointer to location in which to store the floating-point value of the expression. .AP int *booleanPtr out Pointer to location in which to store the 0/1 boolean value of the expression. .AP Tcl_Obj **resultPtrPtr out Pointer to location in which to store a pointer to the value that is the result of the expression. .BE .SH DESCRIPTION .PP These four procedures all evaluate an expression, returning the result in one of four different forms. The expression is given by the \fIobjPtr\fR argument, and it can have any of the forms accepted by the \fBexpr\fR command. .PP The \fIinterp\fR argument refers to an interpreter used to evaluate the expression (e.g. for variables and nested Tcl commands) and to return error information. .PP For all of these procedures the return value is a standard Tcl result: \fBTCL_OK\fR means the expression was successfully evaluated, and \fBTCL_ERROR\fR means that an error occurred while evaluating the expression. If \fBTCL_ERROR\fR is returned, then a message describing the error can be retrieved using \fBTcl_GetObjResult\fR. If an error occurs while executing a Tcl command embedded in the expression then that error will be returned. .PP If the expression is successfully evaluated, then its value is returned in one of four forms, depending on which procedure is invoked. \fBTcl_ExprLongObj\fR stores an integer value at \fI*longPtr\fR. If the expression's actual value is a floating-point number, then it is truncated to an integer. If the expression's actual value is a non-numeric string then an error is returned. .PP \fBTcl_ExprDoubleObj\fR stores a floating-point value at \fI*doublePtr\fR. If the expression's actual value is an integer, it is converted to floating-point. If the expression's actual value is a non-numeric string then an error is returned. .PP \fBTcl_ExprBooleanObj\fR stores a 0/1 integer value at \fI*booleanPtr\fR. If the expression's actual value is an integer or floating-point number, then they store 0 at \fI*booleanPtr\fR if the value was zero and 1 otherwise. If the expression's actual value is a non-numeric string then it must be one of the values accepted by \fBTcl_GetBoolean\fR such as .QW yes or .QW no , or else an error occurs. .PP If \fBTcl_ExprObj\fR successfully evaluates the expression, it stores a pointer to the Tcl value containing the expression's value at \fI*resultPtrPtr\fR. In this case, the caller is responsible for calling \fBTcl_DecrRefCount\fR to decrement the value's reference count when it is finished with the value. .SH "SEE ALSO" Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean, Tcl_ExprString, Tcl_GetObjResult .SH KEYWORDS boolean, double, evaluate, expression, integer, value, string tcl8.6.5/doc/eval.n0000644000175000017500000000531512663660065013446 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 eval n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME eval \- Evaluate a Tcl script .SH SYNOPSIS \fBeval \fIarg \fR?\fIarg ...\fR? .BE .SH DESCRIPTION .PP \fBEval\fR takes one or more arguments, which together comprise a Tcl script containing one or more commands. \fBEval\fR concatenates all its arguments in the same fashion as the \fBconcat\fR command, passes the concatenated string to the Tcl interpreter recursively, and returns the result of that evaluation (or any error generated by it). Note that the \fBlist\fR command quotes sequences of words in such a way that they are not further expanded by the \fBeval\fR command. .SH EXAMPLES .PP Often, it is useful to store a fragment of a script in a variable and execute it later on with extra values appended. This technique is used in a number of places throughout the Tcl core (e.g. in \fBfcopy\fR, \fBlsort\fR and \fBtrace\fR command callbacks). This example shows how to do this using core Tcl commands: .PP .CS set script { puts "logging now" lappend $myCurrentLogVar } set myCurrentLogVar log1 # Set up a switch of logging variable part way through! after 20000 set myCurrentLogVar log2 for {set i 0} {$i<10} {incr i} { # Introduce a random delay after [expr {int(5000 * rand())}] update ;# Check for the asynch log switch \fBeval\fR $script $i [clock clicks] } .CE .PP Note that in the most common case (where the script fragment is actually just a list of words forming a command prefix), it is better to use \fB{*}$script\fR when doing this sort of invocation pattern. It is less general than the \fBeval\fR command, and hence easier to make robust in practice. The following procedure acts in a way that is analogous to the \fBlappend\fR command, except it inserts the argument values at the start of the list in the variable: .PP .CS proc lprepend {varName args} { upvar 1 $varName var # Ensure that the variable exists and contains a list lappend var # Now we insert all the arguments in one go set var [\fBeval\fR [list linsert $var 0] $args] } .CE .PP However, the last line would now normally be written without \fBeval\fR, like this: .PP .CS set var [linsert $var 0 {*}$args] .CE .SH "SEE ALSO" catch(n), concat(n), error(n), errorCode(n), errorInfo(n), interp(n), list(n), namespace(n), subst(n), uplevel(n) .SH KEYWORDS concatenate, evaluate, script '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/AssocData.30000644000175000017500000000672612663660065014275 0ustar sergeisergei'\" '\" 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_SetAssocData 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_GetAssocData, Tcl_SetAssocData, Tcl_DeleteAssocData \- manage associations of string keys and user specified data with Tcl interpreters .SH SYNOPSIS .nf \fB#include \fR .sp ClientData \fBTcl_GetAssocData\fR(\fIinterp, key, delProcPtr\fR) .sp \fBTcl_SetAssocData\fR(\fIinterp, key, delProc, clientData\fR) .sp \fBTcl_DeleteAssocData\fR(\fIinterp, key\fR) .SH ARGUMENTS .AS Tcl_InterpDeleteProc **delProcPtr .AP Tcl_Interp *interp in Interpreter in which to execute the specified command. .AP "const char" *key in Key for association with which to store data or from which to delete or retrieve data. Typically the module prefix for a package. .AP Tcl_InterpDeleteProc *delProc in Procedure to call when \fIinterp\fR is deleted. .AP Tcl_InterpDeleteProc **delProcPtr in Pointer to location in which to store address of current deletion procedure for association. Ignored if NULL. .AP ClientData clientData in Arbitrary one-word value associated with the given key in this interpreter. This data is owned by the caller. .BE .SH DESCRIPTION .PP These procedures allow extensions to associate their own data with a Tcl interpreter. An association consists of a string key, typically the name of the extension, and a one-word value, which is typically a pointer to a data structure holding data specific to the extension. Tcl makes no interpretation of either the key or the value for an association. .PP Storage management is facilitated by storing with each association a procedure to call when the interpreter is deleted. This procedure can dispose of the storage occupied by the client's data in any way it sees fit. .PP \fBTcl_SetAssocData\fR creates an association between a string key and a user specified datum in the given interpreter. If there is already an association with the given \fIkey\fR, \fBTcl_SetAssocData\fR overwrites it with the new information. It is up to callers to organize their use of names to avoid conflicts, for example, by using package names as the keys. If the \fIdeleteProc\fR argument is non-NULL it specifies the address of a procedure to invoke if the interpreter is deleted before the association is deleted. \fIDeleteProc\fR should have arguments and result that match the type \fBTcl_InterpDeleteProc\fR: .PP .CS typedef void \fBTcl_InterpDeleteProc\fR( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR); .CE .PP When \fIdeleteProc\fR is invoked the \fIclientData\fR and \fIinterp\fR arguments will be the same as the corresponding arguments passed to \fBTcl_SetAssocData\fR. The deletion procedure will \fInot\fR be invoked if the association is deleted before the interpreter is deleted. .PP \fBTcl_GetAssocData\fR returns the datum stored in the association with the specified key in the given interpreter, and if the \fIdelProcPtr\fR field is non-\fBNULL\fR, the address indicated by it gets the address of the delete procedure stored with this association. If no association with the specified key exists in the given interpreter \fBTcl_GetAssocData\fR returns \fBNULL\fR. .PP \fBTcl_DeleteAssocData\fR deletes an association with a specified key in the given interpreter. Then it calls the deletion procedure. .SH KEYWORDS association, data, deletion procedure, interpreter, key tcl8.6.5/doc/SplitList.30000644000175000017500000001677512663660065014367 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_SplitList 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_SplitList, Tcl_Merge, Tcl_ScanElement, Tcl_ConvertElement, Tcl_ScanCountedElement, Tcl_ConvertCountedElement \- manipulate Tcl lists .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_SplitList\fR(\fIinterp, list, argcPtr, argvPtr\fR) .sp char * \fBTcl_Merge\fR(\fIargc, argv\fR) .sp int \fBTcl_ScanElement\fR(\fIsrc, flagsPtr\fR) .sp int \fBTcl_ScanCountedElement\fR(\fIsrc, length, flagsPtr\fR) .sp int \fBTcl_ConvertElement\fR(\fIsrc, dst, flags\fR) .sp int \fBTcl_ConvertCountedElement\fR(\fIsrc, length, dst, flags\fR) .SH ARGUMENTS .AS "const char *const" ***argvPtr out .AP Tcl_Interp *interp out Interpreter to use for error reporting. If NULL, then no error message is left. .AP char *list in Pointer to a string with proper list structure. .AP int *argcPtr out Filled in with number of elements in \fIlist\fR. .AP "const char" ***argvPtr out \fI*argvPtr\fR will be filled in with the address of an array of pointers to the strings that are the extracted elements of \fIlist\fR. There will be \fI*argcPtr\fR valid entries in the array, followed by a NULL entry. .AP int argc in Number of elements in \fIargv\fR. .AP "const char *const" *argv in Array of strings to merge together into a single list. Each string will become a separate element of the list. .AP "const char" *src in String that is to become an element of a list. .AP int *flagsPtr in Pointer to word to fill in with information about \fIsrc\fR. The value of *\fIflagsPtr\fR must be passed to \fBTcl_ConvertElement\fR. .AP int length in Number of bytes in string \fIsrc\fR. .AP char *dst in Place to copy converted list element. Must contain enough characters to hold converted string. .AP int flags in Information about \fIsrc\fR. Must be value returned by previous call to \fBTcl_ScanElement\fR, possibly OR-ed with \fBTCL_DONT_USE_BRACES\fR. .BE .SH DESCRIPTION .PP These procedures may be used to disassemble and reassemble Tcl lists. \fBTcl_SplitList\fR breaks a list up into its constituent elements, returning an array of pointers to the elements using \fIargcPtr\fR and \fIargvPtr\fR. While extracting the arguments, \fBTcl_SplitList\fR obeys the usual rules for backslash substitutions and braces. The area of memory pointed to by \fI*argvPtr\fR is dynamically allocated; in addition to the array of pointers, it also holds copies of all the list elements. It is the caller's responsibility to free up all of this storage. For example, suppose that you have called \fBTcl_SplitList\fR with the following code: .PP .CS int argc, code; char *string; char **argv; \&... code = \fBTcl_SplitList\fR(interp, string, &argc, &argv); .CE .PP Then you should eventually free the storage with a call like the following: .PP .CS Tcl_Free((char *) argv); .CE .PP \fBTcl_SplitList\fR normally returns \fBTCL_OK\fR, which means the list was successfully parsed. If there was a syntax error in \fIlist\fR, then \fBTCL_ERROR\fR is returned and the interpreter's result will point to an error message describing the problem (if \fIinterp\fR was not NULL). If \fBTCL_ERROR\fR is returned then no memory is allocated and \fI*argvPtr\fR is not modified. .PP \fBTcl_Merge\fR is the inverse of \fBTcl_SplitList\fR: it takes a collection of strings given by \fIargc\fR and \fIargv\fR and generates a result string that has proper list structure. This means that commands like \fBindex\fR may be used to extract the original elements again. In addition, if the result of \fBTcl_Merge\fR is passed to \fBTcl_Eval\fR, it will be parsed into \fIargc\fR words whose values will be the same as the \fIargv\fR strings passed to \fBTcl_Merge\fR. \fBTcl_Merge\fR will modify the list elements with braces and/or backslashes in order to produce proper Tcl list structure. The result string is dynamically allocated using \fBTcl_Alloc\fR; the caller must eventually release the space using \fBTcl_Free\fR. .PP If the result of \fBTcl_Merge\fR is passed to \fBTcl_SplitList\fR, the elements returned by \fBTcl_SplitList\fR will be identical to those passed into \fBTcl_Merge\fR. However, the converse is not true: if \fBTcl_SplitList\fR is passed a given string, and the resulting \fIargc\fR and \fIargv\fR are passed to \fBTcl_Merge\fR, the resulting string may not be the same as the original string passed to \fBTcl_SplitList\fR. This is because \fBTcl_Merge\fR may use backslashes and braces differently than the original string. .PP \fBTcl_ScanElement\fR and \fBTcl_ConvertElement\fR are the procedures that do all of the real work of \fBTcl_Merge\fR. \fBTcl_ScanElement\fR scans its \fIsrc\fR argument and determines how to use backslashes and braces when converting it to a list element. It returns an overestimate of the number of characters required to represent \fIsrc\fR as a list element, and it stores information in \fI*flagsPtr\fR that is needed by \fBTcl_ConvertElement\fR. .PP \fBTcl_ConvertElement\fR is a companion procedure to \fBTcl_ScanElement\fR. It does the actual work of converting a string to a list element. Its \fIflags\fR argument must be the same as the value returned by \fBTcl_ScanElement\fR. \fBTcl_ConvertElement\fR writes a proper list element to memory starting at *\fIdst\fR and returns a count of the total number of characters written, which will be no more than the result returned by \fBTcl_ScanElement\fR. \fBTcl_ConvertElement\fR writes out only the actual list element without any leading or trailing spaces: it is up to the caller to include spaces between adjacent list elements. .PP \fBTcl_ConvertElement\fR uses one of two different approaches to handle the special characters in \fIsrc\fR. Wherever possible, it handles special characters by surrounding the string with braces. This produces clean-looking output, but cannot be used in some situations, such as when \fIsrc\fR contains unmatched braces. In these situations, \fBTcl_ConvertElement\fR handles special characters by generating backslash sequences for them. The caller may insist on the second approach by OR-ing the flag value returned by \fBTcl_ScanElement\fR with \fBTCL_DONT_USE_BRACES\fR. Although this will produce an uglier result, it is useful in some special situations, such as when \fBTcl_ConvertElement\fR is being used to generate a portion of an argument for a Tcl command. In this case, surrounding \fIsrc\fR with curly braces would cause the command not to be parsed correctly. .PP By default, \fBTcl_ConvertElement\fR will use quoting in its output to be sure the first character of an element is not the hash character .PQ # . This is to be sure the first element of any list passed to \fBeval\fR is not mis-parsed as the beginning of a comment. When a list element is not the first element of a list, this quoting is not necessary. When the caller can be sure that the element is not the first element of a list, it can disable quoting of the leading hash character by OR-ing the flag value returned by \fBTcl_ScanElement\fR with \fBTCL_DONT_QUOTE_HASH\fR. .PP \fBTcl_ScanCountedElement\fR and \fBTcl_ConvertCountedElement\fR are the same as \fBTcl_ScanElement\fR and \fBTcl_ConvertElement\fR, except the length of string \fIsrc\fR is specified by the \fIlength\fR argument, and the string may contain embedded nulls. .SH "SEE ALSO" Tcl_ListObjGetElements(3) .SH KEYWORDS backslash, convert, element, list, merge, split, strings tcl8.6.5/doc/Concat.30000644000175000017500000000331312663660065013627 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_Concat 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_Concat \- concatenate a collection of strings .SH SYNOPSIS .nf \fB#include \fR .sp const char * \fBTcl_Concat\fR(\fIargc, argv\fR) .SH ARGUMENTS .AS "const char *const" argv[] .AP int argc in Number of strings. .AP "const char *const" argv[] in Array of strings to concatenate. Must have \fIargc\fR entries. .BE .SH DESCRIPTION .PP \fBTcl_Concat\fR is a utility procedure used by several of the Tcl commands. Given a collection of strings, it concatenates them together into a single string, with the original strings separated by spaces. This procedure behaves differently than \fBTcl_Merge\fR, in that the arguments are simply concatenated: no effort is made to ensure proper list structure. However, in most common usage the arguments will all be proper lists themselves; if this is true, then the result will also have proper list structure. .PP \fBTcl_Concat\fR eliminates leading and trailing white space as it copies strings from \fBargv\fR to the result. If an element of \fBargv\fR consists of nothing but white space, then that string is ignored entirely. This white-space removal was added to make the output of the \fBconcat\fR command cleaner-looking. .PP The result string is dynamically allocated using \fBTcl_Alloc\fR; the caller must eventually release the space by calling \fBTcl_Free\fR. .SH "SEE ALSO" Tcl_ConcatObj .SH KEYWORDS concatenate, strings tcl8.6.5/doc/continue.n0000644000175000017500000000253112663660065014340 0ustar sergeisergei'\" '\" Copyright (c) 1993-1994 The Regents of the University of California. '\" Copyright (c) 1994-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 continue n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME continue \- Skip to the next iteration of a loop .SH SYNOPSIS \fBcontinue\fR .BE .SH DESCRIPTION .PP This command is typically invoked inside the body of a looping command such as \fBfor\fR or \fBforeach\fR or \fBwhile\fR. It returns a 4 (\fBTCL_CONTINUE\fR) result code, which causes a continue exception to occur. The exception causes the current script to be aborted out to the innermost containing loop command, which then continues with the next iteration of the loop. Catch exceptions are also handled in a few other situations, such as the \fBcatch\fR command and the outermost scripts of procedure bodies. .SH EXAMPLE .PP Print a line for each of the integers from 0 to 10 \fIexcept\fR 5: .PP .CS for {set x 0} {$x<10} {incr x} { if {$x == 5} { \fBcontinue\fR } puts "x is $x" } .CE .SH "SEE ALSO" break(n), for(n), foreach(n), return(n), while(n) .SH KEYWORDS continue, iteration, loop '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/exit.n0000644000175000017500000000254012663660065013465 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 exit n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME exit \- End the application .SH SYNOPSIS \fBexit \fR?\fIreturnCode\fR? .BE .SH DESCRIPTION .PP Terminate the process, returning \fIreturnCode\fR to the system as the exit status. If \fIreturnCode\fR is not specified then it defaults to 0. .SH EXAMPLE .PP Since non-zero exit codes are usually interpreted as error cases by the calling process, the \fBexit\fR command is an important part of signaling that something fatal has gone wrong. This code fragment is useful in scripts to act as a general problem trap: .PP .CS proc main {} { # ... put the real main code in here ... } if {[catch {main} msg options]} { puts stderr "unexpected script error: $msg" if {[info exists env(DEBUG)]} { puts stderr "---- BEGIN TRACE ----" puts stderr [dict get $options -errorinfo] puts stderr "---- END TRACE ----" } # Reserve code 1 for "expected" error exits... \fBexit\fR 2 } .CE .SH "SEE ALSO" exec(n) .SH KEYWORDS abort, exit, process tcl8.6.5/doc/my.n0000644000175000017500000000316112663660065013141 0ustar sergeisergei'\" '\" Copyright (c) 2007 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH my n 0.1 TclOO "TclOO Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME my \- invoke any method of current object .SH SYNOPSIS .nf package require TclOO \fBmy\fI methodName\fR ?\fIarg ...\fR? .fi .BE .SH DESCRIPTION .PP The \fBmy\fR command is used to allow methods of objects to invoke any method of the object (or its class). In particular, the set of valid values for \fImethodName\fR is the set of all methods supported by an object and its superclasses, including those that are not exported. The object upon which the method is invoked is always the one that is the current context of the method (i.e. the object that is returned by \fBself object\fR) from which the \fBmy\fR command is invoked. .PP Each object has its own \fBmy\fR command, contained in its instance namespace. .SH EXAMPLES .PP This example shows basic use of \fBmy\fR to use the \fBvariables\fR method of the \fBoo::object\fR class, which is not publicly visible by default: .PP .CS oo::class create c { method count {} { \fBmy\fR variable counter puts [incr counter] } } c create o o count \fI\(-> prints "1"\fR o count \fI\(-> prints "2"\fR o count \fI\(-> prints "3"\fR .CE .SH "SEE ALSO" next(n), oo::object(n), self(n) .SH KEYWORDS method, method visibility, object, private method, public method .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: tcl8.6.5/doc/StrMatch.30000644000175000017500000000313012663660065014142 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_StringMatch 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_StringMatch, Tcl_StringCaseMatch \- test whether a string matches a pattern .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_StringMatch\fR(\fIstr\fR, \fIpattern\fR) .sp int \fBTcl_StringCaseMatch\fR(\fIstr\fR, \fIpattern\fR, \fIflags\fR) .SH ARGUMENTS .AS "const char" *pattern .AP "const char" *str in String to test. .AP "const char" *pattern in Pattern to match against string. May contain special characters from the set *?\e[]. .AP int flags in OR-ed combination of match flags, currently only \fBTCL_MATCH_NOCASE\fR. 0 specifies a case-sensitive search. .BE .SH DESCRIPTION .PP This utility procedure determines whether a string matches a given pattern. If it does, then \fBTcl_StringMatch\fR returns 1. Otherwise \fBTcl_StringMatch\fR returns 0. The algorithm used for matching is the same algorithm used in the \fBstring match\fR Tcl command and is similar to the algorithm used by the C-shell for file name matching; see the Tcl manual entry for details. .PP In \fBTcl_StringCaseMatch\fR, the algorithm is the same, but you have the option to make the matching case-insensitive. If you choose this (by passing \fBTCL_MATCH_NOCASE\fR), then the string and pattern are essentially matched in the lower case. .SH KEYWORDS match, pattern, string tcl8.6.5/doc/CrtTimerHdlr.30000644000175000017500000000547712663660065015000 0ustar sergeisergei'\" '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-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_CreateTimerHandler 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CreateTimerHandler, Tcl_DeleteTimerHandler \- call a procedure at a given time .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_TimerToken \fBTcl_CreateTimerHandler\fR(\fImilliseconds, proc, clientData\fR) .sp \fBTcl_DeleteTimerHandler\fR(\fItoken\fR) .SH ARGUMENTS .AS Tcl_TimerToken milliseconds .AP int milliseconds in How many milliseconds to wait before invoking \fIproc\fR. .AP Tcl_TimerProc *proc in Procedure to invoke after \fImilliseconds\fR have elapsed. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR. .AP Tcl_TimerToken token in Token for previously created timer handler (the return value from some previous call to \fBTcl_CreateTimerHandler\fR). .BE .SH DESCRIPTION .PP \fBTcl_CreateTimerHandler\fR arranges for \fIproc\fR to be invoked at a time \fImilliseconds\fR milliseconds in the future. The callback to \fIproc\fR will be made by \fBTcl_DoOneEvent\fR, so \fBTcl_CreateTimerHandler\fR is only useful in programs that dispatch events through \fBTcl_DoOneEvent\fR or through Tcl commands such as \fBvwait\fR. The call to \fIproc\fR may not be made at the exact time given by \fImilliseconds\fR: it will be made at the next opportunity after that time. For example, if \fBTcl_DoOneEvent\fR is not called until long after the time has elapsed, or if there are other pending events to process before the call to \fIproc\fR, then the call to \fIproc\fR will be delayed. .PP \fIProc\fR should have arguments and return value that match the type \fBTcl_TimerProc\fR: .PP .CS typedef void \fBTcl_TimerProc\fR( ClientData \fIclientData\fR); .CE .PP The \fIclientData\fR parameter to \fIproc\fR is a copy of the \fIclientData\fR argument given to \fBTcl_CreateTimerHandler\fR when the callback was created. Typically, \fIclientData\fR points to a data structure containing application-specific information about what to do in \fIproc\fR. .PP \fBTcl_DeleteTimerHandler\fR may be called to delete a previously created timer handler. It deletes the handler indicated by \fItoken\fR so that no call to \fIproc\fR will be made; if that handler no longer exists (e.g. because the time period has already elapsed and \fIproc\fR has been invoked then \fBTcl_DeleteTimerHandler\fR does nothing. The tokens returned by \fBTcl_CreateTimerHandler\fR never have a value of NULL, so if NULL is passed to \fBTcl_DeleteTimerHandler\fR then the procedure does nothing. .SH "SEE ALSO" after(n), Tcl_CreateFileHandler(3), Tcl_DoWhenIdle(3) .SH KEYWORDS callback, clock, handler, timer tcl8.6.5/doc/Panic.30000644000175000017500000000651112663660065013455 0ustar sergeisergei'\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_Panic 3 8.4 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_Panic, Tcl_PanicVA, Tcl_SetPanicProc \- report fatal error and abort .SH SYNOPSIS .nf \fB#include \fR .sp void \fBTcl_Panic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR) .sp void \fBTcl_PanicVA\fR(\fIformat\fR, \fIargList\fR) .sp void \fBTcl_SetPanicProc\fR(\fIpanicProc\fR) .sp .SH ARGUMENTS .AS Tcl_PanicProc *panicProc .AP "const char*" format in A printf-style format string. .AP "" arg in Arguments matching the format string. .AP va_list argList in An argument list of arguments matching the format string. Must have been initialized using \fBva_start\fR, and cleared using \fBva_end\fR. .AP Tcl_PanicProc *panicProc in Procedure to report fatal error message and abort. .BE .SH DESCRIPTION .PP When the Tcl library detects that its internal data structures are in an inconsistent state, or that its C procedures have been called in a manner inconsistent with their documentation, it calls \fBTcl_Panic\fR to display a message describing the error and abort the process. The \fIformat\fR argument is a format string describing how to format the remaining arguments \fIarg\fR into an error message, according to the same formatting rules used by the \fBprintf\fR family of functions. The same formatting rules are also used by the built-in Tcl command \fBformat\fR. .PP In a freshly loaded Tcl library, \fBTcl_Panic\fR prints the formatted error message to the standard error file of the process, and then calls \fBabort\fR to terminate the process. \fBTcl_Panic\fR does not return. On Windows, when a debugger is running, the formatted error message is sent to the debugger in stead. If the windows executable does not have a stderr channel (e.g. \fBwish.exe\fR), then a system dialog box is used to display the panic message. .PP \fBTcl_SetPanicProc\fR may be used to modify the behavior of \fBTcl_Panic\fR. The \fIpanicProc\fR argument should match the type \fBTcl_PanicProc\fR: .PP .CS typedef void \fBTcl_PanicProc\fR( const char *\fBformat\fR, \fBarg\fR, \fBarg\fR,...); .CE .PP After \fBTcl_SetPanicProc\fR returns, any future calls to \fBTcl_Panic\fR will call \fIpanicProc\fR, passing along the \fIformat\fR and \fIarg\fR arguments. \fIpanicProc\fR should avoid making calls into the Tcl library, or into other libraries that may call the Tcl library, since the original call to \fBTcl_Panic\fR indicates the Tcl library is not in a state of reliable operation. .PP The typical use of \fBTcl_SetPanicProc\fR arranges for the error message to be displayed or reported in a manner more suitable for the application or the platform. .PP Although the primary callers of \fBTcl_Panic\fR are the procedures of the Tcl library, \fBTcl_Panic\fR is a public function and may be called by any extension or application that wishes to abort the process and have a panic message displayed the same way that panic messages from Tcl will be displayed. .PP \fBTcl_PanicVA\fR is the same as \fBTcl_Panic\fR except that instead of taking a variable number of arguments it takes an argument list. .SH "SEE ALSO" abort(3), printf(3), exec(n), format(n) .SH KEYWORDS abort, fatal, error tcl8.6.5/doc/Sleep.30000644000175000017500000000205312663660065013470 0ustar sergeisergei'\" '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-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_Sleep 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_Sleep \- delay execution for a given number of milliseconds .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_Sleep\fR(\fIms\fR) .SH ARGUMENTS .AS int ms .AP int ms in Number of milliseconds to sleep. .BE .SH DESCRIPTION .PP This procedure delays the calling process by the number of milliseconds given by the \fIms\fR parameter and returns after that time has elapsed. It is typically used for things like flashing a button, where the delay is short and the application need not do anything while it waits. For longer delays where the application needs to respond to other events during the delay, the procedure \fBTcl_CreateTimerHandler\fR should be used instead of \fBTcl_Sleep\fR. .SH KEYWORDS sleep, time, wait tcl8.6.5/doc/Method.30000644000175000017500000002466012663660065013650 0ustar sergeisergei'\" '\" Copyright (c) 2007 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_Method 3 0.1 TclOO "TclOO Library Functions" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_ClassSetConstructor, Tcl_ClassSetDestructor, Tcl_MethodDeclarerClass, Tcl_MethodDeclarerObject, Tcl_MethodIsPublic, Tcl_MethodIsType, Tcl_MethodName, Tcl_NewInstanceMethod, Tcl_NewMethod, Tcl_ObjectContextInvokeNext, Tcl_ObjectContextIsFiltering, Tcl_ObjectContextMethod, Tcl_ObjectContextObject, Tcl_ObjectContextSkippedArgs \- manipulate methods and method-call contexts .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Method \fBTcl_NewMethod\fR(\fIinterp, class, nameObj, isPublic, methodTypePtr, clientData\fR) .sp Tcl_Method \fBTcl_NewInstanceMethod\fR(\fIinterp, object, nameObj, isPublic, methodTypePtr, clientData\fR) .sp \fBTcl_ClassSetConstructor\fR(\fIinterp, class, method\fR) .sp \fBTcl_ClassSetDestructor\fR(\fIinterp, class, method\fR) .sp Tcl_Class \fBTcl_MethodDeclarerClass\fR(\fImethod\fR) .sp Tcl_Object \fBTcl_MethodDeclarerObject\fR(\fImethod\fR) .sp Tcl_Obj * \fBTcl_MethodName\fR(\fImethod\fR) .sp int \fBTcl_MethodIsPublic\fR(\fImethod\fR) .sp int \fBTcl_MethodIsType\fR(\fImethod, methodTypePtr, clientDataPtr\fR) .sp int \fBTcl_ObjectContextInvokeNext\fR(\fIinterp, context, objc, objv, skip\fR) .sp int \fBTcl_ObjectContextIsFiltering\fR(\fIcontext\fR) .sp Tcl_Method \fBTcl_ObjectContextMethod\fR(\fIcontext\fR) .sp Tcl_Object \fBTcl_ObjectContextObject\fR(\fIcontext\fR) .sp int \fBTcl_ObjectContextSkippedArgs\fR(\fIcontext\fR) .SH ARGUMENTS .AS ClientData clientData in .AP Tcl_Interp *interp in/out The interpreter holding the object or class to create or update a method in. .AP Tcl_Object object in The object to create the method in. .AP Tcl_Class class in The class to create the method in. .AP Tcl_Obj *nameObj in The name of the method to create. Should not be NULL unless creating constructors or destructors. .AP int isPublic in A flag saying what the visibility of the method is. The only supported public values of this flag are 0 for a non-exported method, and 1 for an exported method. .AP Tcl_MethodType *methodTypePtr in A description of the type of the method to create, or the type of method to compare against. .AP ClientData clientData in A piece of data that is passed to the implementation of the method without interpretation. .AP ClientData *clientDataPtr out A pointer to a variable in which to write the \fIclientData\fR value supplied when the method was created. If NULL, the \fIclientData\fR value will not be retrieved. .AP Tcl_Method method in A reference to a method to query. .AP Tcl_ObjectContext context in A reference to a method-call context. Note that client code \fImust not\fR retain a reference to a context. .AP int objc in The number of arguments to pass to the method implementation. .AP "Tcl_Obj *const" *objv in An array of arguments to pass to the method implementation. .AP int skip in The number of arguments passed to the method implementation that do not represent "real" arguments. .BE .SH DESCRIPTION .PP A method is an operation carried out on an object that is associated with the object. Every method must be attached to either an object or a class; methods attached to a class are associated with all instances (direct and indirect) of that class. .PP Given a method, the entity that declared it can be found using \fBTcl_MethodDeclarerClass\fR which returns the class that the method is attached to (or NULL if the method is not attached to any class) and \fBTcl_MethodDeclarerObject\fR which returns the object that the method is attached to (or NULL if the method is not attached to an object). The name of the method can be retrieved with \fBTcl_MethodName\fR and whether the method is exported is retrieved with \fBTcl_MethodIsPublic\fR. The type of the method can also be introspected upon to a limited degree; the function \fBTcl_MethodIsType\fR returns whether a method is of a particular type, assigning the per-method \fIclientData\fR to the variable pointed to by \fIclientDataPtr\fR if (that is non-NULL) if the type is matched. .SS "METHOD CREATION" .PP Methods are created by \fBTcl_NewMethod\fR and \fBTcl_NewInstanceMethod\fR, which create a method attached to a class or an object respectively. In both cases, the \fInameObj\fR argument gives the name of the method to create, the \fIisPublic\fR argument states whether the method should be exported initially, the \fImethodTypePtr\fR argument describes the implementation of the method (see the \fBMETHOD TYPES\fR section below) and the \fIclientData\fR argument gives some implementation-specific data that is passed on to the implementation of the method when it is called. .PP When the \fInameObj\fR argument to \fBTcl_NewMethod\fR is NULL, an unnamed method is created, which is used for constructors and destructors. Constructors should be installed into their class using the \fBTcl_ClassSetConstructor\fR function, and destructors (which must not require any arguments) should be installed into their class using the \fBTcl_ClassSetDestructor\fR function. Unnamed methods should not be used for any other purpose, and named methods should not be used as either constructors or destructors. Also note that a NULL \fImethodTypePtr\fR is used to provide internal signaling, and should not be used in client code. .SS "METHOD CALL CONTEXTS" .PP When a method is called, a method-call context reference is passed in as one of the arguments to the implementation function. This context can be inspected to provide information about the caller, but should not be retained beyond the moment when the method call terminates. .PP The method that is being called can be retrieved from the context by using \fBTcl_ObjectContextMethod\fR, and the object that caused the method to be invoked can be retrieved with \fBTcl_ObjectContextObject\fR. The number of arguments that are to be skipped (e.g. the object name and method name in a normal method call) is read with \fBTcl_ObjectContextSkippedArgs\fR, and the context can also report whether it is working as a filter for another method through \fBTcl_ObjectContextIsFiltering\fR. .PP During the execution of a method, the method implementation may choose to invoke the stages of the method call chain that come after the current method implementation. This (the core of the \fBnext\fR command) is done using \fBTcl_ObjectContextInvokeNext\fR. Note that this function does not manipulate the call-frame stack, unlike the \fBnext\fR command; if the method implementation has pushed one or more extra frames on the stack as part of its implementation, it is also responsible for temporarily popping those frames from the stack while the \fBTcl_ObjectContextInvokeNext\fR function is executing. Note also that the method-call context is \fInever\fR deleted during the execution of this function. .SH "METHOD TYPES" .PP The types of methods are described by a pointer to a Tcl_MethodType structure, which is defined as: .PP .CS typedef struct { int \fIversion\fR; const char *\fIname\fR; Tcl_MethodCallProc *\fIcallProc\fR; Tcl_MethodDeleteProc *\fIdeleteProc\fR; Tcl_CloneProc *\fIcloneProc\fR; } \fBTcl_MethodType\fR; .CE .PP The \fIversion\fR field allows for future expansion of the structure, and should always be declared equal to TCL_OO_METHOD_VERSION_CURRENT. The \fIname\fR field provides a human-readable name for the type, and is the value that is exposed via the \fBinfo class methodtype\fR and \fBinfo object methodtype\fR Tcl commands. .PP The \fIcallProc\fR field gives a function that is called when the method is invoked; it must never be NULL. .PP The \fIdeleteProc\fR field gives a function that is used to delete a particular method, and is called when the method is replaced or removed; if the field is NULL, it is assumed that the method's \fIclientData\fR needs no special action to delete. .PP The \fIcloneProc\fR field is either a function that is used to copy a method's \fIclientData\fR (as part of \fBTcl_CopyObjectInstance\fR) or NULL to indicate that the \fIclientData\fR can just be copied directly. .SS "TCL_METHODCALLPROC FUNCTION SIGNATURE" .PP Functions matching this signature are called when the method is invoked. .PP .CS typedef int \fBTcl_MethodCallProc\fR( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR, Tcl_ObjectContext \fIobjectContext\fR, int \fIobjc\fR, Tcl_Obj *const *\fIobjv\fR); .CE .PP The \fIclientData\fR argument to a Tcl_MethodCallProc is the value that was given when the method was created, the \fIinterp\fR is a place in which to execute scripts and access variables as well as being where to put the result of the method, and the \fIobjc\fR and \fIobjv\fR fields give the parameter objects to the method. The calling context of the method can be discovered through the \fIobjectContext\fR argument, and the return value from a Tcl_MethodCallProc is any Tcl return code (e.g. TCL_OK, TCL_ERROR). .SS "TCL_METHODDELETEPROC FUNCTION SIGNATURE" .PP Functions matching this signature are used when a method is deleted, whether through a new method being created or because the object or class is deleted. .PP .CS typedef void \fBTcl_MethodDeleteProc\fR( ClientData \fIclientData\fR); .CE .PP The \fIclientData\fR argument to a Tcl_MethodDeleteProc will be the same as the value passed to the \fIclientData\fR argument to \fBTcl_NewMethod\fR or \fBTcl_NewInstanceMethod\fR when the method was created. .SS "TCL_CLONEPROC FUNCTION SIGNATURE" .PP Functions matching this signature are used to copy a method when the object or class is copied using \fBTcl_CopyObjectInstance\fR (or \fBoo::copy\fR). .PP .CS typedef int \fBTcl_CloneProc\fR( Tcl_Interp *\fIinterp\fR, ClientData \fIoldClientData\fR, ClientData *\fInewClientDataPtr\fR); .CE .PP The \fIinterp\fR argument gives a place to write an error message when the attempt to clone the object is to fail, in which case the clone procedure must also return TCL_ERROR; it should return TCL_OK otherwise. The \fIoldClientData\fR field to a Tcl_CloneProc gives the value from the method being copied from, and the \fInewClientDataPtr\fR field will point to a variable in which to write the value for the method being copied to. .SH "SEE ALSO" Class(3), oo::class(n), oo::define(n), oo::object(n) .SH KEYWORDS constructor, method, object .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: tcl8.6.5/doc/if.n0000644000175000017500000000460112663660065013112 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 if n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME if \- Execute scripts conditionally .SH SYNOPSIS \fBif \fIexpr1 \fR?\fBthen\fR? \fIbody1 \fBelseif \fIexpr2 \fR?\fBthen\fR? \fIbody2\fR \fBelseif\fR ... ?\fBelse\fR? ?\fIbodyN\fR? .BE .SH DESCRIPTION .PP The \fIif\fR command evaluates \fIexpr1\fR as an expression (in the same way that \fBexpr\fR evaluates its argument). The value of the expression must be a boolean (a numeric value, where 0 is false and anything is true, or a string value such as \fBtrue\fR or \fByes\fR for true and \fBfalse\fR or \fBno\fR for false); if it is true then \fIbody1\fR is executed by passing it to the Tcl interpreter. Otherwise \fIexpr2\fR is evaluated as an expression and if it is true then \fBbody2\fR is executed, and so on. If none of the expressions evaluates to true then \fIbodyN\fR is executed. The \fBthen\fR and \fBelse\fR arguments are optional .QW "noise words" to make the command easier to read. There may be any number of \fBelseif\fR clauses, including zero. \fIBodyN\fR may also be omitted as long as \fBelse\fR is omitted too. The return value from the command is the result of the body script that was executed, or an empty string if none of the expressions was non-zero and there was no \fIbodyN\fR. .SH EXAMPLES .PP A simple conditional: .PP .CS \fBif\fR {$vbl == 1} { puts "vbl is one" } .CE .PP With an \fBelse\fR-clause: .PP .CS \fBif\fR {$vbl == 1} { puts "vbl is one" } \fBelse\fR { puts "vbl is not one" } .CE .PP With an \fBelseif\fR-clause too: .PP .CS \fBif\fR {$vbl == 1} { puts "vbl is one" } \fBelseif\fR {$vbl == 2} { puts "vbl is two" } \fBelse\fR { puts "vbl is not one or two" } .CE .PP Remember, expressions can be multi-line, but in that case it can be a good idea to use the optional \fBthen\fR keyword for clarity: .PP .CS \fBif\fR { $vbl == 1 || $vbl == 2 || $vbl == 3 } \fBthen\fR { puts "vbl is one, two or three" } .CE .SH "SEE ALSO" expr(n), for(n), foreach(n) .SH KEYWORDS boolean, conditional, else, false, if, true '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/list.n0000644000175000017500000000313412663660065013467 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2001 Kevin B. Kenny . All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH list n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME list \- Create a list .SH SYNOPSIS \fBlist \fR?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP This command returns a list comprised of all the \fIarg\fRs, or an empty string if no \fIarg\fRs are specified. Braces and backslashes get added as necessary, so that the \fBlindex\fR command may be used on the result to re-extract the original arguments, and also so that \fBeval\fR may be used to execute the resulting list, with \fIarg1\fR comprising the command's name and the other \fIarg\fRs comprising its arguments. \fBList\fR produces slightly different results than \fBconcat\fR: \fBconcat\fR removes one level of grouping before forming the list, while \fBlist\fR works directly from the original arguments. .SH EXAMPLE .PP The command .PP .CS \fBlist\fR a b "c d e " " f {g h}" .CE .PP will return .PP .CS \fBa b {c d e } { f {g h}}\fR .CE .PP while \fBconcat\fR with the same arguments will return .PP .CS \fBa b c d e f {g h}\fR .CE .SH "SEE ALSO" lappend(n), lindex(n), linsert(n), llength(n), lrange(n), lrepeat(n), lreplace(n), lsearch(n), lset(n), lsort(n) .SH KEYWORDS element, list, quoting '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/case.n0000644000175000017500000000477612663660065013444 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 case n 7.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME case \- Evaluate one of several scripts, depending on a given value .SH SYNOPSIS \fBcase\fI string \fR?\fBin\fR? \fIpatList body \fR?\fIpatList body \fR...? .sp \fBcase\fI string \fR?\fBin\fR? {\fIpatList body \fR?\fIpatList body \fR...?} .BE .SH DESCRIPTION .PP \fINote: the \fBcase\fI command is obsolete and is supported only for backward compatibility. At some point in the future it may be removed entirely. You should use the \fBswitch\fI command instead.\fR .PP The \fBcase\fR command matches \fIstring\fR against each of the \fIpatList\fR arguments in order. Each \fIpatList\fR argument is a list of one or more patterns. If any of these patterns matches \fIstring\fR then \fBcase\fR evaluates the following \fIbody\fR argument by passing it recursively to the Tcl interpreter and returns the result of that evaluation. Each \fIpatList\fR argument consists of a single pattern or list of patterns. Each pattern may contain any of the wild-cards described under \fBstring match\fR. If a \fIpatList\fR argument is \fBdefault\fR, the corresponding body will be evaluated if no \fIpatList\fR matches \fIstring\fR. If no \fIpatList\fR argument matches \fIstring\fR and no default is given, then the \fBcase\fR command returns an empty string. .PP Two syntaxes are provided for the \fIpatList\fR and \fIbody\fR arguments. The first uses a separate argument for each of the patterns and commands; this form is convenient if substitutions are desired on some of the patterns or commands. The second form places all of the patterns and commands together into a single argument; the argument must have proper list structure, with the elements of the list being the patterns and commands. The second form makes it easy to construct multi-line case commands, since the braces around the whole list make it unnecessary to include a backslash at the end of each line. Since the \fIpatList\fR arguments are in braces in the second form, no command or variable substitutions are performed on them; this makes the behavior of the second form different than the first form in some cases. .SH "SEE ALSO" switch(n) .SH KEYWORDS case, match, regular expression tcl8.6.5/doc/trace.n0000644000175000017500000004326512663660065013623 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2000 Ajuba Solutions. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH trace n "8.4" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME trace \- Monitor variable accesses, command usages and command executions .SH SYNOPSIS \fBtrace \fIoption\fR ?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP This command causes Tcl commands to be executed whenever certain operations are invoked. The legal \fIoption\fRs (which may be abbreviated) are: .TP \fBtrace add \fItype name ops ?args?\fR Where \fItype\fR is \fBcommand\fR, \fBexecution\fR, or \fBvariable\fR. .RS .TP \fBtrace add command\fR \fIname ops commandPrefix\fR . Arrange for \fIcommandPrefix\fR to be executed (with additional arguments) whenever command \fIname\fR is modified in one of the ways given by the list \fIops\fR. \fIName\fR will be resolved using the usual namespace resolution rules used by commands. If the command does not exist, an error will be thrown. .RS .PP \fIOps\fR indicates which operations are of interest, and is a list of one or more of the following items: .TP \fBrename\fR . Invoke \fIcommandPrefix\fR whenever the traced command is renamed. Note that renaming to the empty string is considered deletion, and will not be traced with .QW \fBrename\fR . .TP \fBdelete\fR . Invoke \fIcommandPrefix\fR when the traced command is deleted. Commands can be deleted explicitly by using the \fBrename\fR command to rename the command to an empty string. Commands are also deleted when the interpreter is deleted, but traces will not be invoked because there is no interpreter in which to execute them. .PP When the trace triggers, depending on the operations being traced, a number of arguments are appended to \fIcommandPrefix\fR so that the actual command is as follows: .PP .CS \fIcommandPrefix oldName newName op\fR .CE .PP \fIOldName\fR and \fInewName\fR give the traced command's current (old) name, and the name to which it is being renamed (the empty string if this is a .QW delete operation). \fIOp\fR indicates what operation is being performed on the command, and is one of \fBrename\fR or \fBdelete\fR as defined above. The trace operation cannot be used to stop a command from being deleted. Tcl will always remove the command once the trace is complete. Recursive renaming or deleting will not cause further traces of the same type to be evaluated, so a delete trace which itself deletes the command, or a rename trace which itself renames the command will not cause further trace evaluations to occur. Both \fIoldName\fR and \fInewName\fR are fully qualified with any namespace(s) in which they appear. .RE .TP \fBtrace add execution\fR \fIname ops commandPrefix\fR . Arrange for \fIcommandPrefix\fR to be executed (with additional arguments) whenever command \fIname\fR is executed, with traces occurring at the points indicated by the list \fIops\fR. \fIName\fR will be resolved using the usual namespace resolution rules used by commands. If the command does not exist, an error will be thrown. .RS .PP \fIOps\fR indicates which operations are of interest, and is a list of one or more of the following items: .TP \fBenter\fR Invoke \fIcommandPrefix\fR whenever the command \fIname\fR is executed, just before the actual execution takes place. .TP \fBleave\fR Invoke \fIcommandPrefix\fR whenever the command \fIname\fR is executed, just after the actual execution takes place. .TP \fBenterstep\fR . Invoke \fIcommandPrefix\fR for every Tcl command which is executed from the start of the execution of the procedure \fIname\fR until that procedure finishes. \fICommandPrefix\fR is invoked just before the actual execution of the Tcl command being reported takes place. For example if we have .QW "proc foo {} { puts \N'34'hello\N'34' }" , then an \fIenterstep\fR trace would be invoked just before .QW "\fIputs \N'34'hello\N'34'\fR" is executed. Setting an \fIenterstep\fR trace on a command \fIname\fR that does not refer to a procedure will not result in an error and is simply ignored. .TP \fBleavestep\fR . Invoke \fIcommandPrefix\fR for every Tcl command which is executed from the start of the execution of the procedure \fIname\fR until that procedure finishes. \fICommandPrefix\fR is invoked just after the actual execution of the Tcl command being reported takes place. Setting a \fIleavestep\fR trace on a command \fIname\fR that does not refer to a procedure will not result in an error and is simply ignored. .PP When the trace triggers, depending on the operations being traced, a number of arguments are appended to \fIcommandPrefix\fR so that the actual command is as follows: .PP For \fBenter\fR and \fBenterstep\fR operations: .PP .CS \fIcommandPrefix command-string op\fR .CE .PP \fICommand-string\fR gives the complete current command being executed (the traced command for a \fBenter\fR operation, an arbitrary command for a \fBenterstep\fR operation), including all arguments in their fully expanded form. \fIOp\fR indicates what operation is being performed on the command execution, and is one of \fBenter\fR or \fBenterstep\fR as defined above. The trace operation can be used to stop the command from executing, by deleting the command in question. Of course when the command is subsequently executed, an .QW "invalid command" error will occur. .PP For \fBleave\fR and \fBleavestep\fR operations: .PP .CS \fIcommandPrefix command-string code result op\fR .CE .PP \fICommand-string\fR gives the complete current command being executed (the traced command for a \fBenter\fR operation, an arbitrary command for a \fBenterstep\fR operation), including all arguments in their fully expanded form. \fICode\fR gives the result code of that execution, and \fIresult\fR the result string. \fIOp\fR indicates what operation is being performed on the command execution, and is one of \fBleave\fR or \fBleavestep\fR as defined above. Note that the creation of many \fBenterstep\fR or \fBleavestep\fR traces can lead to unintuitive results, since the invoked commands from one trace can themselves lead to further command invocations for other traces. .PP \fICommandPrefix\fR executes in the same context as the code that invoked the traced operation: thus the \fIcommandPrefix\fR, if invoked from a procedure, will have access to the same local variables as code in the procedure. This context may be different than the context in which the trace was created. If \fIcommandPrefix\fR invokes a procedure (which it normally does) then the procedure will have to use \fBupvar\fR or \fBuplevel\fR commands if it wishes to access the local variables of the code which invoked the trace operation. .PP While \fIcommandPrefix\fR is executing during an execution trace, traces on \fIname\fR are temporarily disabled. This allows the \fIcommandPrefix\fR to execute \fIname\fR in its body without invoking any other traces again. If an error occurs while executing the \fIcommandPrefix\fR, then the command \fIname\fR as a whole will return that same error. .PP When multiple traces are set on \fIname\fR, then for \fIenter\fR and \fIenterstep\fR operations, the traced commands are invoked in the reverse order of how the traces were originally created; and for \fIleave\fR and \fIleavestep\fR operations, the traced commands are invoked in the original order of creation. .PP The behavior of execution traces is currently undefined for a command \fIname\fR imported into another namespace. .RE .TP \fBtrace add variable\fI name ops commandPrefix\fR Arrange for \fIcommandPrefix\fR to be executed whenever variable \fIname\fR is accessed in one of the ways given by the list \fIops\fR. \fIName\fR may refer to a normal variable, an element of an array, or to an array as a whole (i.e. \fIname\fR may be just the name of an array, with no parenthesized index). If \fIname\fR refers to a whole array, then \fIcommandPrefix\fR is invoked whenever any element of the array is manipulated. If the variable does not exist, it will be created but will not be given a value, so it will be visible to \fBnamespace which\fR queries, but not to \fBinfo exists\fR queries. .RS .PP \fIOps\fR indicates which operations are of interest, and is a list of one or more of the following items: .TP \fBarray\fR Invoke \fIcommandPrefix\fR whenever the variable is accessed or modified via the \fBarray\fR command, provided that \fIname\fR is not a scalar variable at the time that the \fBarray\fR command is invoked. If \fIname\fR is a scalar variable, the access via the \fBarray\fR command will not trigger the trace. .TP \fBread\fR Invoke \fIcommandPrefix\fR whenever the variable is read. .TP \fBwrite\fR Invoke \fIcommandPrefix\fR whenever the variable is written. .TP \fBunset\fR Invoke \fIcommandPrefix\fR whenever the variable is unset. Variables can be unset explicitly with the \fBunset\fR command, or implicitly when procedures return (all of their local variables are unset). Variables are also unset when interpreters are deleted, but traces will not be invoked because there is no interpreter in which to execute them. .PP When the trace triggers, three arguments are appended to \fIcommandPrefix\fR so that the actual command is as follows: .PP .CS \fIcommandPrefix name1 name2 op\fR .CE .PP \fIName1\fR and \fIname2\fR give the name(s) for the variable being accessed: if the variable is a scalar then \fIname1\fR gives the variable's name and \fIname2\fR is an empty string; if the variable is an array element then \fIname1\fR gives the name of the array and name2 gives the index into the array; if an entire array is being deleted and the trace was registered on the overall array, rather than a single element, then \fIname1\fR gives the array name and \fIname2\fR is an empty string. \fIName1\fR and \fIname2\fR are not necessarily the same as the name used in the \fBtrace variable\fR command: the \fBupvar\fR command allows a procedure to reference a variable under a different name. \fIOp\fR indicates what operation is being performed on the variable, and is one of \fBread\fR, \fBwrite\fR, or \fBunset\fR as defined above. .PP \fICommandPrefix\fR executes in the same context as the code that invoked the traced operation: if the variable was accessed as part of a Tcl procedure, then \fIcommandPrefix\fR will have access to the same local variables as code in the procedure. This context may be different than the context in which the trace was created. If \fIcommandPrefix\fR invokes a procedure (which it normally does) then the procedure will have to use \fBupvar\fR or \fBuplevel\fR if it wishes to access the traced variable. Note also that \fIname1\fR may not necessarily be the same as the name used to set the trace on the variable; differences can occur if the access is made through a variable defined with the \fBupvar\fR command. .PP For read and write traces, \fIcommandPrefix\fR can modify the variable to affect the result of the traced operation. If \fIcommandPrefix\fR modifies the value of a variable during a read or write trace, then the new value will be returned as the result of the traced operation. The return value from \fIcommandPrefix\fR is ignored except that if it returns an error of any sort then the traced operation also returns an error with the same error message returned by the trace command (this mechanism can be used to implement read-only variables, for example). For write traces, \fIcommandPrefix\fR is invoked after the variable's value has been changed; it can write a new value into the variable to override the original value specified in the write operation. To implement read-only variables, \fIcommandPrefix\fR will have to restore the old value of the variable. .PP While \fIcommandPrefix\fR is executing during a read or write trace, traces on the variable are temporarily disabled. This means that reads and writes invoked by \fIcommandPrefix\fR will occur directly, without invoking \fIcommandPrefix\fR (or any other traces) again. However, if \fIcommandPrefix\fR unsets the variable then unset traces will be invoked. .PP When an unset trace is invoked, the variable has already been deleted: it will appear to be undefined with no traces. If an unset occurs because of a procedure return, then the trace will be invoked in the variable context of the procedure being returned to: the stack frame of the returning procedure will no longer exist. Traces are not disabled during unset traces, so if an unset trace command creates a new trace and accesses the variable, the trace will be invoked. Any errors in unset traces are ignored. .PP If there are multiple traces on a variable they are invoked in order of creation, most-recent first. If one trace returns an error, then no further traces are invoked for the variable. If an array element has a trace set, and there is also a trace set on the array as a whole, the trace on the overall array is invoked before the one on the element. .PP Once created, the trace remains in effect either until the trace is removed with the \fBtrace remove variable\fR command described below, until the variable is unset, or until the interpreter is deleted. Unsetting an element of array will remove any traces on that element, but will not remove traces on the overall array. .PP This command returns an empty string. .RE .RE .TP \fBtrace remove \fItype name opList commandPrefix\fR Where \fItype\fR is either \fBcommand\fR, \fBexecution\fR or \fBvariable\fR. .RS .TP \fBtrace remove command\fI name opList commandPrefix\fR If there is a trace set on command \fIname\fR with the operations and command given by \fIopList\fR and \fIcommandPrefix\fR, then the trace is removed, so that \fIcommandPrefix\fR will never again be invoked. Returns an empty string. If \fIname\fR does not exist, the command will throw an error. .TP \fBtrace remove execution\fI name opList commandPrefix\fR If there is a trace set on command \fIname\fR with the operations and command given by \fIopList\fR and \fIcommandPrefix\fR, then the trace is removed, so that \fIcommandPrefix\fR will never again be invoked. Returns an empty string. If \fIname\fR does not exist, the command will throw an error. .TP \fBtrace remove variable\fI name opList commandPrefix\fR If there is a trace set on variable \fIname\fR with the operations and command given by \fIopList\fR and \fIcommandPrefix\fR, then the trace is removed, so that \fIcommandPrefix\fR will never again be invoked. Returns an empty string. .RE .TP \fBtrace info \fItype name\fR Where \fItype\fR is either \fBcommand\fR, \fBexecution\fR or \fBvariable\fR. .RS .TP \fBtrace info command\fI name\fR Returns a list containing one element for each trace currently set on command \fIname\fR. Each element of the list is itself a list containing two elements, which are the \fIopList\fR and \fIcommandPrefix\fR associated with the trace. If \fIname\fR does not have any traces set, then the result of the command will be an empty string. If \fIname\fR does not exist, the command will throw an error. .TP \fBtrace info execution\fI name\fR Returns a list containing one element for each trace currently set on command \fIname\fR. Each element of the list is itself a list containing two elements, which are the \fIopList\fR and \fIcommandPrefix\fR associated with the trace. If \fIname\fR does not have any traces set, then the result of the command will be an empty string. If \fIname\fR does not exist, the command will throw an error. .TP \fBtrace info variable\fI name\fR Returns a list containing one element for each trace currently set on variable \fIname\fR. Each element of the list is itself a list containing two elements, which are the \fIopList\fR and \fIcommandPrefix\fR associated with the trace. If \fIname\fR does not exist or does not have any traces set, then the result of the command will be an empty string. .RE .PP For backwards compatibility, three other subcommands are available: .RS .TP \fBtrace variable \fIname ops command\fR This is equivalent to \fBtrace add variable \fIname ops command\fR. .TP \fBtrace vdelete \fIname ops command\fR This is equivalent to \fBtrace remove variable \fIname ops command\fR .TP \fBtrace vinfo \fIname\fR This is equivalent to \fBtrace info variable \fIname\fR .RE .PP These subcommands are deprecated and will likely be removed in a future version of Tcl. They use an older syntax in which \fBarray\fR, \fBread\fR, \fBwrite\fR, \fBunset\fR are replaced by \fBa\fR, \fBr\fR, \fBw\fR and \fBu\fR respectively, and the \fIops\fR argument is not a list, but simply a string concatenation of the operations, such as \fBrwua\fR. .SH EXAMPLES .PP Print a message whenever either of the global variables \fBfoo\fR and \fBbar\fR are updated, even if they have a different local name at the time (which can be done with the \fBupvar\fR command): .PP .CS proc tracer {varname args} { upvar #0 $varname var puts "$varname was updated to be \e"$var\e"" } \fBtrace add\fR variable foo write "tracer foo" \fBtrace add\fR variable bar write "tracer bar" .CE .PP Ensure that the global variable \fBfoobar\fR always contains the product of the global variables \fBfoo\fR and \fBbar\fR: .PP .CS proc doMult args { global foo bar foobar set foobar [expr {$foo * $bar}] } \fBtrace add\fR variable foo write doMult \fBtrace add\fR variable bar write doMult .CE .PP Print a trace of what commands are executed during the processing of a Tcl procedure: .PP .CS proc x {} { y } proc y {} { z } proc z {} { puts hello } proc report args {puts [info level 0]} \fBtrace add\fR execution x enterstep report x \(-> \fIreport y enterstep\fR \fIreport z enterstep\fR \fIreport {puts hello} enterstep\fR \fIhello\fR .CE .SH "SEE ALSO" set(n), unset(n) .SH KEYWORDS read, command, rename, variable, write, trace, unset .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/SetResult.30000644000175000017500000002471512663660065014363 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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_SetResult 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_SetObjResult, Tcl_GetObjResult, Tcl_SetResult, Tcl_GetStringResult, Tcl_AppendResult, Tcl_AppendResultVA, Tcl_AppendElement, Tcl_ResetResult, Tcl_TransferResult, Tcl_FreeResult \- manipulate Tcl result .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_SetObjResult\fR(\fIinterp, objPtr\fR) .sp Tcl_Obj * \fBTcl_GetObjResult\fR(\fIinterp\fR) .sp \fBTcl_SetResult\fR(\fIinterp, result, freeProc\fR) .sp const char * \fBTcl_GetStringResult\fR(\fIinterp\fR) .sp \fBTcl_AppendResult\fR(\fIinterp, result, result, ... , \fB(char *) NULL\fR) .sp \fBTcl_AppendResultVA\fR(\fIinterp, argList\fR) .sp \fBTcl_ResetResult\fR(\fIinterp\fR) .sp .VS 8.6 \fBTcl_TransferResult\fR(\fIsourceInterp, result, targetInterp\fR) .VE 8.6 .sp \fBTcl_AppendElement\fR(\fIinterp, element\fR) .sp \fBTcl_FreeResult\fR(\fIinterp\fR) .SH ARGUMENTS .AS Tcl_FreeProc sourceInterp out .AP Tcl_Interp *interp out Interpreter whose result is to be modified or read. .AP Tcl_Obj *objPtr in Tcl value to become result for \fIinterp\fR. .AP char *result in String value to become result for \fIinterp\fR or to be appended to the existing result. .AP "const char" *element in String value to append as a list element to the existing result of \fIinterp\fR. .AP Tcl_FreeProc *freeProc in Address of procedure to call to release storage at \fIresult\fR, or \fBTCL_STATIC\fR, \fBTCL_DYNAMIC\fR, or \fBTCL_VOLATILE\fR. .AP va_list argList in An argument list which must have been initialized using \fBva_start\fR, and cleared using \fBva_end\fR. .AP Tcl_Interp *sourceInterp in .VS 8.6 Interpreter that the result and error information should be copied from. .VE 8.6 .AP Tcl_Interp *targetInterp in .VS 8.6 Interpreter that the result and error information should be copied to. .VE 8.6 .AP int result in .VS 8.6 If \fBTCL_OK\fR, only copy the result. If \fBTCL_ERROR\fR, copy the error information as well. .VE 8.6 .BE .SH DESCRIPTION .PP The procedures described here are utilities for manipulating the result value in a Tcl interpreter. The interpreter result may be either a Tcl value or a string. For example, \fBTcl_SetObjResult\fR and \fBTcl_SetResult\fR set the interpreter result to, respectively, a value and a string. Similarly, \fBTcl_GetObjResult\fR and \fBTcl_GetStringResult\fR return the interpreter result as a value and as a string. The procedures always keep the string and value forms of the interpreter result consistent. For example, if \fBTcl_SetObjResult\fR is called to set the result to a value, then \fBTcl_GetStringResult\fR is called, it will return the value's string representation. .PP \fBTcl_SetObjResult\fR arranges for \fIobjPtr\fR to be the result for \fIinterp\fR, replacing any existing result. The result is left pointing to the value referenced by \fIobjPtr\fR. \fIobjPtr\fR's reference count is incremented since there is now a new reference to it from \fIinterp\fR. The reference count for any old result value is decremented and the old result value is freed if no references to it remain. .PP \fBTcl_GetObjResult\fR returns the result for \fIinterp\fR as a value. The value's reference count is not incremented; if the caller needs to retain a long-term pointer to the value they should use \fBTcl_IncrRefCount\fR to increment its reference count in order to keep it from being freed too early or accidentally changed. .PP \fBTcl_SetResult\fR arranges for \fIresult\fR to be the result for the current Tcl command in \fIinterp\fR, replacing any existing result. The \fIfreeProc\fR argument specifies how to manage the storage for the \fIresult\fR argument; it is discussed in the section \fBTHE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT\fR below. If \fIresult\fR is \fBNULL\fR, then \fIfreeProc\fR is ignored and \fBTcl_SetResult\fR re-initializes \fIinterp\fR's result to point to an empty string. .PP \fBTcl_GetStringResult\fR returns the result for \fIinterp\fR as a string. If the result was set to a value by a \fBTcl_SetObjResult\fR call, the value form will be converted to a string and returned. If the value's string representation contains null bytes, this conversion will lose information. For this reason, programmers are encouraged to write their code to use the new value API procedures and to call \fBTcl_GetObjResult\fR instead. .PP \fBTcl_ResetResult\fR clears the result for \fIinterp\fR and leaves the result in its normal empty initialized state. If the result is a value, its reference count is decremented and the result is left pointing to an unshared value representing an empty string. If the result is a dynamically allocated string, its memory is free*d and the result is left as a empty string. \fBTcl_ResetResult\fR also clears the error state managed by \fBTcl_AddErrorInfo\fR, \fBTcl_AddObjErrorInfo\fR, and \fBTcl_SetErrorCode\fR. .PP \fBTcl_AppendResult\fR makes it easy to build up Tcl results in pieces. It takes each of its \fIresult\fR arguments and appends them in order to the current result associated with \fIinterp\fR. If the result is in its initialized empty state (e.g. a command procedure was just invoked or \fBTcl_ResetResult\fR was just called), then \fBTcl_AppendResult\fR sets the result to the concatenation of its \fIresult\fR arguments. \fBTcl_AppendResult\fR may be called repeatedly as additional pieces of the result are produced. \fBTcl_AppendResult\fR takes care of all the storage management issues associated with managing \fIinterp\fR's result, such as allocating a larger result area if necessary. It also manages conversion to and from the \fIresult\fR field of the \fIinterp\fR so as to handle backward-compatibility with old-style extensions. Any number of \fIresult\fR arguments may be passed in a single call; the last argument in the list must be a NULL pointer. .PP \fBTcl_AppendResultVA\fR is the same as \fBTcl_AppendResult\fR except that instead of taking a variable number of arguments it takes an argument list. .PP .VS 8.6 \fBTcl_TransferResult\fR moves a result from one interpreter to another, optionally (dependent on the \fIresult\fR parameter) including the error information dictionary as well. The interpreters must be in the same thread. The source interpreter will have its result reset by this operation. .VE 8.6 .SH "DEPRECATED INTERFACES" .SS "OLD STRING PROCEDURES" .PP Use of the following procedures (is deprecated since they manipulate the Tcl result as a string. Procedures such as \fBTcl_SetObjResult\fR that manipulate the result as a value can be significantly more efficient. .PP \fBTcl_AppendElement\fR is similar to \fBTcl_AppendResult\fR in that it allows results to be built up in pieces. However, \fBTcl_AppendElement\fR takes only a single \fIelement\fR argument and it appends that argument to the current result as a proper Tcl list element. \fBTcl_AppendElement\fR adds backslashes or braces if necessary to ensure that \fIinterp\fR's result can be parsed as a list and that \fIelement\fR will be extracted as a single element. Under normal conditions, \fBTcl_AppendElement\fR will add a space character to \fIinterp\fR's result just before adding the new list element, so that the list elements in the result are properly separated. However if the new list element is the first in a list or sub-list (i.e. \fIinterp\fR's current result is empty, or consists of the single character .QW { , or ends in the characters .QW " {" ) then no space is added. .PP \fBTcl_FreeResult\fR performs part of the work of \fBTcl_ResetResult\fR. It frees up the memory associated with \fIinterp\fR's result. It also sets \fIinterp->freeProc\fR to zero, but does not change \fIinterp->result\fR or clear error state. \fBTcl_FreeResult\fR is most commonly used when a procedure is about to replace one result value with another. .SS "DIRECT ACCESS TO INTERP->RESULT" .PP It used to be legal for programs to directly read and write \fIinterp->result\fR to manipulate the interpreter result. The Tcl headers no longer permit this access by default, and C code still doing this must be updated to use supported routines \fBTcl_GetObjResult\fR, \fBTcl_GetStringResult\fR, \fBTcl_SetObjResult\fR, and \fBTcl_SetResult\fR. As a migration aid, access can be restored with the compiler directive .CS #define USE_INTERP_RESULT .CE but this is meant only to offer life support to otherwise dead code. .SH "THE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT" .PP \fBTcl_SetResult\fR's \fIfreeProc\fR argument specifies how the Tcl system is to manage the storage for the \fIresult\fR argument. If \fBTcl_SetResult\fR or \fBTcl_SetObjResult\fR are called at a time when \fIinterp\fR holds a string result, they do whatever is necessary to dispose of the old string result (see the \fBTcl_Interp\fR manual entry for details on this). .PP If \fIfreeProc\fR is \fBTCL_STATIC\fR it means that \fIresult\fR refers to an area of static storage that is guaranteed not to be modified until at least the next call to \fBTcl_Eval\fR. If \fIfreeProc\fR is \fBTCL_DYNAMIC\fR it means that \fIresult\fR was allocated with a call to \fBTcl_Alloc\fR and is now the property of the Tcl system. \fBTcl_SetResult\fR will arrange for the string's storage to be released by calling \fBTcl_Free\fR when it is no longer needed. If \fIfreeProc\fR is \fBTCL_VOLATILE\fR it means that \fIresult\fR points to an area of memory that is likely to be overwritten when \fBTcl_SetResult\fR returns (e.g. it points to something in a stack frame). In this case \fBTcl_SetResult\fR will make a copy of the string in dynamically allocated storage and arrange for the copy to be the result for the current Tcl command. .PP If \fIfreeProc\fR is not one of the values \fBTCL_STATIC\fR, \fBTCL_DYNAMIC\fR, and \fBTCL_VOLATILE\fR, then it is the address of a procedure that Tcl should call to free the string. This allows applications to use non-standard storage allocators. When Tcl no longer needs the storage for the string, it will call \fIfreeProc\fR. \fIFreeProc\fR should have arguments and result that match the type \fBTcl_FreeProc\fR: .PP .CS typedef void \fBTcl_FreeProc\fR( char *\fIblockPtr\fR); .CE .PP When \fIfreeProc\fR is called, its \fIblockPtr\fR will be set to the value of \fIresult\fR passed to \fBTcl_SetResult\fR. .SH "SEE ALSO" Tcl_AddErrorInfo, Tcl_CreateObjCommand, Tcl_SetErrorCode, Tcl_Interp .SH KEYWORDS append, command, element, list, value, result, return value, interpreter tcl8.6.5/doc/throw.n0000644000175000017500000000334012663660065013656 0ustar sergeisergei'\" '\" Copyright (c) 2008 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH throw n 8.6 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME throw \- Generate a machine-readable error .SH SYNOPSIS \fBthrow\fI type message\fR .BE .SH DESCRIPTION .PP This command causes the current evaluation to be unwound with an error. The error created is described by the \fItype\fR and \fImessage\fR arguments: \fItype\fR must contain a list of words describing the error in a form that is machine-readable (and which will form the error-code part of the result dictionary), and \fImessage\fR should contain text that is intended for display to a human being. .PP The stack will be unwound until the error is trapped by a suitable \fBcatch\fR or \fBtry\fR command. If it reaches the event loop without being trapped, it will be reported through the \fBbgerror\fR mechanism. If it reaches the top level of script evaluation in \fBtclsh\fR, it will be printed on the console before, in the non-interactive case, causing an exit (the behavior in other programs will depend on the details of how Tcl is embedded and used). .PP By convention, the words in the \fItype\fR argument should go from most general to most specific. .SH EXAMPLES .PP The following produces an error that is identical to that produced by \fBexpr\fR when trying to divide a value by zero. .PP .CS \fBthrow\fR {ARITH DIVZERO {divide by zero}} {divide by zero} .CE .SH "SEE ALSO" catch(n), error(n), errorCode(n), errorInfo(n), return(n), try(n) .SH "KEYWORDS" error, exception '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/lassign.n0000644000175000017500000000353012663660065014154 0ustar sergeisergei'\" '\" Copyright (c) 1992-1999 Karl Lehenbauer & Mark Diekhans '\" Copyright (c) 2004 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lassign n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lassign \- Assign list elements to variables .SH SYNOPSIS \fBlassign \fIlist \fR?\fIvarName ...\fR? .BE .SH DESCRIPTION .PP This command treats the value \fIlist\fR as a list and assigns successive elements from that list to the variables given by the \fIvarName\fR arguments in order. If there are more variable names than list elements, the remaining variables are set to the empty string. If there are more list elements than variables, a list of unassigned elements is returned. .SH EXAMPLES .PP An illustration of how multiple assignment works, and what happens when there are either too few or too many elements. .PP .CS \fBlassign\fR {a b c} x y z ;# Empty return puts $x ;# Prints "a" puts $y ;# Prints "b" puts $z ;# Prints "c" \fBlassign\fR {d e} x y z ;# Empty return puts $x ;# Prints "d" puts $y ;# Prints "e" puts $z ;# Prints "" \fBlassign\fR {f g h i} x y ;# Returns "h i" puts $x ;# Prints "f" puts $y ;# Prints "g" .CE .PP The \fBlassign\fR command has other uses. It can be used to create the analogue of the .QW shift command in many shell languages like this: .PP .CS set ::argv [\fBlassign\fR $::argv argumentToReadOff] .CE .SH "SEE ALSO" lindex(n), list(n), lrange(n), lset(n), set(n) .SH KEYWORDS assign, element, list, multiple, set, variable '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/DictObj.30000644000175000017500000002454112663660065013744 0ustar sergeisergei'\" '\" Copyright (c) 2003 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_DictObj 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_NewDictObj, Tcl_DictObjPut, Tcl_DictObjGet, Tcl_DictObjRemove, Tcl_DictObjSize, Tcl_DictObjFirst, Tcl_DictObjNext, Tcl_DictObjDone, Tcl_DictObjPutKeyList, Tcl_DictObjRemoveKeyList \- manipulate Tcl values as dictionaries .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * \fBTcl_NewDictObj\fR() .sp int \fBTcl_DictObjGet\fR(\fIinterp, dictPtr, keyPtr, valuePtrPtr\fR) .sp int \fBTcl_DictObjPut\fR(\fIinterp, dictPtr, keyPtr, valuePtr\fR) .sp int \fBTcl_DictObjRemove\fR(\fIinterp, dictPtr, keyPtr\fR) .sp int \fBTcl_DictObjSize\fR(\fIinterp, dictPtr, sizePtr\fR) .sp int \fBTcl_DictObjFirst\fR(\fIinterp, dictPtr, searchPtr, keyPtrPtr, valuePtrPtr, donePtr\fR) .sp void \fBTcl_DictObjNext\fR(\fIsearchPtr, keyPtrPtr, valuePtrPtr, donePtr\fR) .sp void \fBTcl_DictObjDone\fR(\fIsearchPtr\fR) .sp int \fBTcl_DictObjPutKeyList\fR(\fIinterp, dictPtr, keyc, keyv, valuePtr\fR) .sp int \fBTcl_DictObjRemoveKeyList\fR(\fIinterp, dictPtr, keyc, keyv\fR) .SH ARGUMENTS .AS Tcl_DictSearch "**valuePtrPtr" in/out .AP Tcl_Interp *interp in If an error occurs while converting a value to be a dictionary value, an error message is left in the interpreter's result value unless \fIinterp\fR is NULL. .AP Tcl_Obj *dictPtr in/out Points to the dictionary value to be manipulated. If \fIdictPtr\fR does not already point to a dictionary value, an attempt will be made to convert it to one. .AP Tcl_Obj *keyPtr in Points to the key for the key/value pair being manipulated within the dictionary value. .AP Tcl_Obj **keyPtrPtr out Points to a variable that will have the key from a key/value pair placed within it. May be NULL to indicate that the caller is not interested in the key. .AP Tcl_Obj *valuePtr in Points to the value for the key/value pair being manipulated within the dictionary value (or sub-value, in the case of \fBTcl_DictObjPutKeyList\fR.) .AP Tcl_Obj **valuePtrPtr out Points to a variable that will have the value from a key/value pair placed within it. For \fBTcl_DictObjFirst\fR and \fBTcl_DictObjNext\fR, this may be NULL to indicate that the caller is not interested in the value. .AP int *sizePtr out Points to a variable that will have the number of key/value pairs contained within the dictionary placed within it. .AP Tcl_DictSearch *searchPtr in/out Pointer to record to use to keep track of progress in enumerating all key/value pairs in a dictionary. The contents of the record will be initialized by the call to \fBTcl_DictObjFirst\fR. If the enumerating is to be terminated before all values in the dictionary have been returned, the search record \fImust\fR be passed to \fBTcl_DictObjDone\fR to enable the internal locks to be released. .AP int *donePtr out Points to a variable that will have a non-zero value written into it when the enumeration of the key/value pairs in a dictionary has completed, and a zero otherwise. .AP int keyc in Indicates the number of keys that will be supplied in the \fIkeyv\fR array. .AP "Tcl_Obj *const" *keyv in Array of \fIkeyc\fR pointers to values that \fBTcl_DictObjPutKeyList\fR and \fBTcl_DictObjRemoveKeyList\fR will use to locate the key/value pair to manipulate within the sub-dictionaries of the main dictionary value passed to them. .BE .SH DESCRIPTION .PP Tcl dictionary values have an internal representation that supports efficient mapping from keys to values and which guarantees that the particular ordering of keys within the dictionary remains the same modulo any keys being deleted (which removes them from the order) or added (which adds them to the end of the order). If reinterpreted as a list, the values at the even-valued indices in the list will be the keys of the dictionary, and each will be followed (in the odd-valued index) by the value associated with that key. .PP The procedures described in this man page are used to create, modify, index, and iterate over dictionary values from C code. .PP \fBTcl_NewDictObj\fR creates a new, empty dictionary value. The string representation of the value will be invalid, and the reference count of the value will be zero. .PP \fBTcl_DictObjGet\fR looks up the given key within the given dictionary and writes a pointer to the value associated with that key into the variable pointed to by \fIvaluePtrPtr\fR, or a NULL if the key has no mapping within the dictionary. The result of this procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be converted to a dictionary. .PP \fBTcl_DictObjPut\fR updates the given dictionary so that the given key maps to the given value; any key may exist at most once in any particular dictionary. The dictionary must not be shared, but the key and value may be. This procedure may increase the reference count of both key and value if it proves necessary to store them. Neither key nor value should be NULL. The result of this procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be converted to a dictionary. .PP \fBTcl_DictObjRemove\fR updates the given dictionary so that the given key has no mapping to any value. The dictionary must not be shared, but the key may be. The key actually stored in the dictionary will have its reference count decremented if it was present. It is not an error if the key did not previously exist. The result of this procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be converted to a dictionary. .PP \fBTcl_DictObjSize\fR updates the given variable with the number of key/value pairs currently in the given dictionary. The result of this procedure is \fBTCL_OK\fR, or \fBTCL_ERROR\fR if the \fIdictPtr\fR cannot be converted to a dictionary. .PP \fBTcl_DictObjFirst\fR commences an iteration across all the key/value pairs in the given dictionary, placing the key and value in the variables pointed to by the \fIkeyPtrPtr\fR and \fIvaluePtrPtr\fR arguments (which may be NULL to indicate that the caller is uninterested in they key or variable respectively.) The next key/value pair in the dictionary may be retrieved with \fBTcl_DictObjNext\fR. Concurrent updates of the dictionary's internal representation will not modify the iteration processing unless the dictionary is unshared, when this will trigger premature termination of the iteration instead (which Tcl scripts cannot trigger via the \fBdict\fR command.) The \fIsearchPtr\fR argument points to a piece of context that is used to identify which particular iteration is being performed, and is initialized by the call to \fBTcl_DictObjFirst\fR. The \fIdonePtr\fR argument points to a variable that is updated to be zero of there are further key/value pairs to be iterated over, or non-zero if the iteration is complete. The order of iteration is implementation-defined. If the \fIdictPtr\fR argument cannot be converted to a dictionary, \fBTcl_DictObjFirst\fR returns \fBTCL_ERROR\fR and the iteration is not commenced, and otherwise it returns \fBTCL_OK\fR. .PP When \fBTcl_DictObjFirst\fR is called upon a dictionary, a lock is placed on the dictionary to enable that dictionary to be iterated over safely without regard for whether the dictionary is modified during the iteration. Because of this, once the iteration over a dictionary's keys has finished (whether because all values have been iterated over as indicated by the variable indicated by the \fIdonePtr\fR argument being set to one, or because no further values are required) the \fBTcl_DictObjDone\fR function must be called with the same \fIsearchPtr\fR as was passed to \fBTcl_DictObjFirst\fR so that the internal locks can be released. Once a particular \fIsearchPtr\fR is passed to \fBTcl_DictObjDone\fR, passing it to \fBTcl_DictObjNext\fR (without first initializing it with \fBTcl_DictObjFirst\fR) will result in no values being produced and the variable pointed to by \fIdonePtr\fR being set to one. It is safe to call \fBTcl_DictObjDone\fR multiple times on the same \fIsearchPtr\fR for each call to \fBTcl_DictObjFirst\fR. .PP The procedures \fBTcl_DictObjPutKeyList\fR and \fBTcl_DictObjRemoveKeyList\fR are the close analogues of \fBTcl_DictObjPut\fR and \fBTcl_DictObjRemove\fR respectively, except that instead of working with a single dictionary, they are designed to operate on a nested tree of dictionaries, with inner dictionaries stored as values inside outer dictionaries. The \fIkeyc\fR and \fIkeyv\fR arguments specify a list of keys (with outermost keys first) that acts as a path to the key/value pair to be affected. Note that there is no corresponding operation for reading a value for a path as this is easy to construct from repeated use of \fBTcl_DictObjGet\fR. With \fBTcl_DictObjPutKeyList\fR, nested dictionaries are created for non-terminal keys where they do not already exist. With \fBTcl_DictObjRemoveKeyList\fR, all non-terminal keys must exist and have dictionaries as their values. .SH EXAMPLE Using the dictionary iteration interface to search determine if there is a key that maps to itself: .PP .CS Tcl_DictSearch search; Tcl_Obj *key, *value; int done; /* * Assume interp and objPtr are parameters. This is the * idiomatic way to start an iteration over the dictionary; it * sets a lock on the internal representation that ensures that * there are no concurrent modification issues when normal * reference count management is also used. The lock is * released automatically when the loop is finished, but must * be released manually when an exceptional exit from the loop * is performed. However it is safe to try to release the lock * even if we've finished iterating over the loop. */ if (\fBTcl_DictObjFirst\fR(interp, objPtr, &search, &key, &value, &done) != TCL_OK) { return TCL_ERROR; } for (; !done ; \fBTcl_DictObjNext\fR(&search, &key, &value, &done)) { /* * Note that strcmp() is not a good way of comparing * values and is just used here for demonstration * purposes. */ if (!strcmp(Tcl_GetString(key), Tcl_GetString(value))) { break; } } \fBTcl_DictObjDone\fR(&search); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(!done)); return TCL_OK; .CE .SH "SEE ALSO" Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_InitObjHashTable .SH KEYWORDS dict, dict value, dictionary, dictionary value, hash table, iteration, value tcl8.6.5/doc/tclsh.10000644000175000017500000001367112663660065013543 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 tclsh 1 "" Tcl "Tcl Applications" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME tclsh \- Simple shell containing Tcl interpreter .SH SYNOPSIS \fBtclsh\fR ?\fB\-encoding \fIname\fR? ?\fIfileName arg arg ...\fR? .BE .SH DESCRIPTION .PP \fBTclsh\fR is a shell-like application that reads Tcl commands from its standard input or from a file and evaluates them. If invoked with no arguments then it runs interactively, reading Tcl commands from standard input and printing command results and error messages to standard output. It runs until the \fBexit\fR command is invoked or until it reaches end-of-file on its standard input. If there exists a file \fB.tclshrc\fR (or \fBtclshrc.tcl\fR on the Windows platforms) in the home directory of the user, interactive \fBtclsh\fR evaluates the file as a Tcl script just before reading the first command from standard input. .SH "SCRIPT FILES" .PP If \fBtclsh\fR is invoked with arguments then the first few arguments specify the name of a script file, and, optionally, the encoding of the text data stored in that script file. Any additional arguments are made available to the script as variables (see below). Instead of reading commands from standard input \fBtclsh\fR will read Tcl commands from the named file; \fBtclsh\fR will exit when it reaches the end of the file. The end of the file may be marked either by the physical end of the medium, or by the character, .QW \e032 .PQ \eu001a ", control-Z" . If this character is present in the file, the \fBtclsh\fR application will read text up to but not including the character. An application that requires this character in the file may safely encode it as .QW \e032 , .QW \ex1a , or .QW \eu001a ; or may generate it by use of commands such as \fBformat\fR or \fBbinary\fR. There is no automatic evaluation of \fB.tclshrc\fR when the name of a script file is presented on the \fBtclsh\fR command line, but the script file can always \fBsource\fR it if desired. .PP If you create a Tcl script in a file whose first line is .PP .CS \fB#!/usr/local/bin/tclsh\fR .CE .PP then you can invoke the script file directly from your shell if you mark the file as executable. This assumes that \fBtclsh\fR has been installed in the default location in /usr/local/bin; if it is installed somewhere else then you will have to modify the above line to match. Many UNIX systems do not allow the \fB#!\fR line to exceed about 30 characters in length, so be sure that the \fBtclsh\fR executable can be accessed with a short file name. .PP An even better approach is to start your script files with the following three lines: .PP .CS \fB#!/bin/sh # the next line restarts using tclsh \e exec tclsh "$0" ${1+"$@"}\fR .CE .PP This approach has three advantages over the approach in the previous paragraph. First, the location of the \fBtclsh\fR binary does not have to be hard-wired into the script: it can be anywhere in your shell search path. Second, it gets around the 30-character file name limit in the previous approach. Third, this approach will work even if \fBtclsh\fR is itself a shell script (this is done on some systems in order to handle multiple architectures or operating systems: the \fBtclsh\fR script selects one of several binaries to run). The three lines cause both \fBsh\fR and \fBtclsh\fR to process the script, but the \fBexec\fR is only executed by \fBsh\fR. \fBsh\fR processes the script first; it treats the second line as a comment and executes the third line. The \fBexec\fR statement cause the shell to stop processing and instead to start up \fBtclsh\fR to reprocess the entire script. When \fBtclsh\fR starts up, it treats all three lines as comments, since the backslash at the end of the second line causes the third line to be treated as part of the comment on the second line. .PP You should note that it is also common practice to install tclsh with its version number as part of the name. This has the advantage of allowing multiple versions of Tcl to exist on the same system at once, but also the disadvantage of making it harder to write scripts that start up uniformly across different versions of Tcl. .SH "VARIABLES" .PP \fBTclsh\fR sets the following global Tcl variables in addition to those created by the Tcl library itself (such as \fBenv\fR, which maps environment variables such as \fBPATH\fR into Tcl): .TP 15 \fBargc\fR . Contains a count of the number of \fIarg\fR arguments (0 if none), not including the name of the script file. .TP 15 \fBargv\fR . Contains a Tcl list whose elements are the \fIarg\fR arguments, in order, or an empty string if there are no \fIarg\fR arguments. .TP 15 \fBargv0\fR . Contains \fIfileName\fR if it was specified. Otherwise, contains the name by which \fBtclsh\fR was invoked. .TP 15 \fBtcl_interactive\fR . Contains 1 if \fBtclsh\fR is running interactively (no \fIfileName\fR was specified and standard input is a terminal-like device), 0 otherwise. .SH PROMPTS .PP When \fBtclsh\fR is invoked interactively it normally prompts for each command with .QW "\fB% \fR" . You can change the prompt by setting the global variables \fBtcl_prompt1\fR and \fBtcl_prompt2\fR. If variable \fBtcl_prompt1\fR exists then it must consist of a Tcl script to output a prompt; instead of outputting a prompt \fBtclsh\fR will evaluate the script in \fBtcl_prompt1\fR. The variable \fBtcl_prompt2\fR is used in a similar way when a newline is typed but the current command is not yet complete; if \fBtcl_prompt2\fR is not set then no prompt is output for incomplete commands. .SH "STANDARD CHANNELS" .PP See \fBTcl_StandardChannels\fR for more explanations. .SH "SEE ALSO" auto_path(n), encoding(n), env(n), fconfigure(n) .SH KEYWORDS application, argument, interpreter, prompt, script file, shell tcl8.6.5/doc/NRE.30000644000175000017500000003126312663660065013051 0ustar sergeisergei.\" .\" Copyright (c) 2008 by Kevin B. Kenny. .\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH NRE 3 8.6 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_NRCreateCommand, Tcl_NRCallObjProc, Tcl_NREvalObj, Tcl_NREvalObjv, Tcl_NRCmdSwap, Tcl_NRExprObj, Tcl_NRAddCallback \- Non-Recursive (stackless) evaluation of Tcl scripts. .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Command \fBTcl_NRCreateCommand\fR(\fIinterp, cmdName, proc, nreProc, clientData, deleteProc\fR) .sp int \fBTcl_NRCallObjProc\fR(\fIinterp, nreProc, clientData, objc, objv\fR) .sp int \fBTcl_NREvalObj\fR(\fIinterp, objPtr, flags\fR) .sp int \fBTcl_NREvalObjv\fR(\fIinterp, objc, objv, flags\fR) .sp int \fBTcl_NRCmdSwap\fR(\fIinterp, cmd, objc, objv, flags\fR) .sp int \fBTcl_NRExprObj\fR(\fIinterp, objPtr, resultPtr\fR) .sp void \fBTcl_NRAddCallback\fR(\fIinterp, postProcPtr, data0, data1, data2, data3\fR) .fi .SH ARGUMENTS .AS Tcl_CmdDeleteProc *interp in .AP Tcl_Interp *interp in Interpreter in which to create or evaluate a command. .AP char *cmdName in Name of a new command to create. .AP Tcl_ObjCmdProc *proc in Implementation of a command that will be called whenever \fIcmdName\fR is invoked as a command in the unoptimized way. .AP Tcl_ObjCmdProc *nreProc in Implementation of a command that will be called whenever \fIcmdName\fR is invoked and requested to conserve the C stack. .AP ClientData clientData in Arbitrary one-word value that will be passed to \fIproc\fR, \fInreProc\fR, \fIdeleteProc\fR and \fIobjProc\fR. .AP Tcl_CmdDeleteProc *deleteProc in/out Procedure to call before \fIcmdName\fR is deleted from the interpreter. This procedure allows for command-specific cleanup. If \fIdeleteProc\fR is \fBNULL\fR, then no procedure is called before the command is deleted. .AP int objc in Count of parameters provided to the implementation of a command. .AP Tcl_Obj **objv in Pointer to an array of Tcl values. Each value holds the value of a single word in the command to execute. .AP Tcl_Obj *objPtr in Pointer to a Tcl_Obj whose value is a script or expression to execute. .AP int flags in ORed combination of flag bits that specify additional options. \fBTCL_EVAL_GLOBAL\fR is the only flag that is currently supported. .\" TODO: This is a lie. But kbk didn't grasp TCL_EVAL_INVOKE and .\" TCL_EVAL_NOERR well enough to document them. .AP Tcl_Command cmd in Token for a command that is to be used instead of the currently executing command. .AP Tcl_Obj *resultPtr out Pointer to an unshared Tcl_Obj where the result of expression evaluation is written. .AP Tcl_NRPostProc *postProcPtr in Pointer to a function that will be invoked when the command currently executing in the interpreter designated by \fIinterp\fR completes. .AP ClientData data0 in .AP ClientData data1 in .AP ClientData data2 in .AP ClientData data3 in \fIdata0\fR through \fIdata3\fR are four one-word values that will be passed to the function designated by \fIpostProcPtr\fR when it is invoked. .BE .SH DESCRIPTION .PP This series of C functions provides an interface whereby commands that are implemented in C can be evaluated, and invoke Tcl commands scripts and scripts, without consuming space on the C stack. The non-recursive evaluation is done by installing a \fItrampoline\fR, a small piece of code that invokes a command or script, and then executes a series of callbacks when the command or script returns. .PP The \fBTcl_NRCreateCommand\fR function creates a Tcl command in the interpreter designated by \fIinterp\fR that is prepared to handle nonrecursive evaluation with a trampoline. The \fIcmdName\fR argument gives the name of the new command. If \fIcmdName\fR contains any namespace qualifiers, then the new command is added to the specified namespace; otherwise, it is added to the global namespace. \fIproc\fR gives the procedure that will be called when the interpreter wishes to evaluate the command in an unoptimized manner, and \fInreProc\fR is the procedure that will be called when the interpreter wishes to evaluate the command using a trampoline. \fIdeleteProc\fR is a function that will be called before the command is deleted from the interpreter. When any of the three functions is invoked, it is passed the \fIclientData\fR parameter. .PP \fBTcl_NRCreateCommand\fR deletes any existing command \fIname\fR already associated with the interpreter (however see below for an exception where the existing command is not deleted). It returns a token that may be used to refer to the command in subsequent calls to \fBTcl_GetCommandName\fR. If \fBTcl_NRCreateCommand\fR is called for an interpreter that is in the process of being deleted, then it does not create a new command, does not delete any existing command of the same name, and returns NULL. .PP The \fIproc\fR and \fInreProc\fR function are expected to conform to all the rules set forth for the \fIproc\fR argument to \fBTcl_CreateObjCommand\fR(3) (\fIq.v.\fR). .PP When a command that is written to cope with evaluation via trampoline is invoked without a trampoline on the stack, it will usually respond to the invocation by creating a trampoline and calling the trampoline-enabled implementation of the same command. This call is done by means of \fBTcl_NRCallObjProc\fR. In the call to \fBTcl_NRCallObjProc\fR, the \fIinterp\fR, \fIclientData\fR, \fIobjc\fR and \fIobjv\fR parameters should be the same ones that were passed to \fIproc\fR. The \fInreProc\fR parameter should designate the trampoline-enabled implementation of the command. .PP \fBTcl_NREvalObj\fR arranges for the script contained in \fIobjPtr\fR to be evaluated in the interpreter designated by \fIinterp\fR after the current command (which must be trampoline-enabled) returns. It is the method by which a command may invoke a script without consuming space on the C stack. Similarly, \fBTcl_NREvalObjv\fR arranges to invoke a single Tcl command whose words have already been separated and substituted. The \fIobjc\fR and \fIobjv\fR parameters give the words of the command to be evaluated when execution reaches the trampoline. .PP \fBTcl_NRCmdSwap\fR allows for trampoline evaluation of a command whose resolution is already known. The \fIcmd\fR parameter gives a \fBTcl_Command\fR token (returned from \fBTcl_CreateObjCommand\fR or \fBTcl_GetCommandFromObj\fR) identifying the command to be invoked in the trampoline; this command must match the word in \fIobjv[0]\fR. The remaining arguments are as for \fBTcl_NREvalObjv\fR. .PP \fBTcl_NREvalObj\fR, \fBTcl_NREvalObjv\fR and \fBTcl_NRCmdSwap\fR all accept a \fIflags\fR parameter, which is an OR-ed-together set of bits to control evaluation. At the present time, the only supported flag available to callers is \fBTCL_EVAL_GLOBAL\fR. .\" TODO: Again, this is a lie. Do we want to explain TCL_EVAL_INVOKE .\" and TCL_EVAL_NOERR? If the \fBTCL_EVAL_GLOBAL\fR flag is set, the script or command is evaluated in the global namespace. If it is not set, it is evaluated in the current namespace. .PP \fBTcl_NRExprObj\fR arranges for the expression contained in \fIobjPtr\fR to be evaluated in the interpreter designated by \fIinterp\fR after the current command (which must be trampoline-enabled) returns. It is the method by which a command may evaluate a Tcl expression without consuming space on the C stack. The argument \fIresultPtr\fR is a pointer to an unshared Tcl_Obj where the result of expression evaluation is to be written. If expression evaluation returns any code other than TCL_OK, the \fIresultPtr\fR value is left untouched. .PP All of the routines return \fBTCL_OK\fR if command or expression invocation has been scheduled successfully. If for any reason the scheduling cannot be completed (for example, if the interpreter is unable to find the requested command), they return \fBTCL_ERROR\fR with an appropriate message left in the interpreter's result. .PP \fBTcl_NRAddCallback\fR arranges to have a C function called when the current trampoline-enabled command in the Tcl interpreter designated by \fIinterp\fR returns. The \fIpostProcPtr\fR argument is a pointer to the callback function, which must have arguments and return value consistent with the \fBTcl_NRPostProc\fR data type: .PP .CS typedef int \fBTcl_NRPostProc\fR( \fBClientData\fR \fIdata\fR[], \fBTcl_Interp\fR *\fIinterp\fR, int \fIresult\fR); .CE .PP When the trampoline invokes the callback function, the \fIdata\fR parameter will point to an array containing the four one-word quantities that were passed to \fBTcl_NRAddCallback\fR in the \fIdata0\fR through \fIdata3\fR parameters. The Tcl interpreter will be designated by the \fIinterp\fR parameter, and the \fIresult\fR parameter will contain the result (\fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR or \fBTCL_CONTINUE\fR) that was returned by the command evaluation. The callback function is expected, in turn, either to return a \fIresult\fR to control further evaluation. .PP Multiple \fBTcl_NRAddCallback\fR invocations may request multiple callbacks, which may be to the same or different callback functions. If multiple callbacks are requested, they are executed in last-in, first-out order, that is, the most recently requested callback is executed first. .SH EXAMPLE .PP The usual pattern for Tcl commands that invoke other Tcl commands is something like: .PP .CS int \fITheCmdOldObjProc\fR( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int result; Tcl_Obj *objPtr; \fI... preparation ...\fR result = \fBTcl_EvalObjEx\fR(interp, objPtr, 0); \fI... postprocessing ...\fR return result; } \fBTcl_CreateObjCommand\fR(interp, "theCommand", \fITheCmdOldObjProc\fR, clientData, TheCmdDeleteProc); .CE .PP To enable a command like this one for trampoline-based evaluation, it must be split into three pieces: .IP \(bu A non-trampoline implementation, \fITheCmdNewObjProc\fR, which will simply create a trampoline and invoke the trampoline-based implementation. .IP \(bu A trampoline-enabled implementation, \fITheCmdNRObjProc\fR. This function will perform the initialization, request that the trampoline call the postprocessing routine after command evaluation, and finally, request that the trampoline call the inner command. .IP \(bu A postprocessing routine, \fITheCmdPostProc\fR. This function will perform the postprocessing formerly done after the return from the inner command in \fITheCmdObjProc\fR. .PP The non-trampoline implementation is simple and stylized, containing a single statement: .PP .CS int \fITheCmdNewObjProc\fR( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { return \fBTcl_NRCallObjProc\fR(interp, \fITheCmdNRObjProc\fR, clientData, objc, objv); } .CE .PP The trampoline-enabled implementation requests postprocessing, and returns to the trampoline requesting command evaluation. .PP .CS int \fITheCmdNRObjProc\fR ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *objPtr; \fI... preparation ...\fR \fBTcl_NRAddCallback\fR(interp, \fITheCmdPostProc\fR, data0, data1, data2, data3); /* \fIdata0 .. data3\fR are up to four one-word items to * pass to the postprocessing procedure */ return \fBTcl_NREvalObj\fR(interp, objPtr, 0); } .CE .PP The postprocessing procedure does whatever the original command did upon return from the inner evaluation. .PP .CS int \fITheCmdNRPostProc\fR( ClientData data[], Tcl_Interp *interp, int result) { /* \fIdata[0] .. data[3]\fR are the four words of data * passed to \fBTcl_NRAddCallback\fR */ \fI... postprocessing ...\fR return result; } .CE .PP If \fItheCommand\fR is a command that results in multiple commands or scripts being evaluated, its postprocessing routine may schedule additional postprocessing and then request another command evaluation by means of \fBTcl_NREvalObj\fR or one of the other evaluation routines. Looping and sequencing constructs may be implemented in this way. .PP Finally, to install a trampoline-enabled command in the interpreter, \fBTcl_NRCreateCommand\fR is used in place of \fBTcl_CreateObjCommand\fR. It accepts two command procedures instead of one. The first is for use when no trampoline is yet on the stack, and the second is for use when there is already a trampoline in place. .PP .CS \fBTcl_NRCreateCommand\fR(interp, "theCommand", \fITheCmdNewObjProc\fR, \fITheCmdNRObjProc\fR, clientData, TheCmdDeleteProc); .CE .SH "SEE ALSO" Tcl_CreateCommand(3), Tcl_CreateObjCommand(3), Tcl_EvalObjEx(3), Tcl_GetCommandFromObj(3), Tcl_ExprObj(3) .SH KEYWORDS stackless, nonrecursive, execute, command, global, value, result, script .SH COPYRIGHT Copyright (c) 2008 by Kevin B. Kenny tcl8.6.5/doc/Init.30000644000175000017500000000132012663660065013317 0ustar sergeisergei'\" '\" Copyright (c) 1998-2000 by Scriptics Corporation. '\" All rights reserved. '\" .TH Tcl_Init 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_Init \- find and source initialization script .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_Init\fR(\fIinterp\fR) .SH ARGUMENTS .AS Tcl_Interp *interp .AP Tcl_Interp *interp in Interpreter to initialize. .BE .SH DESCRIPTION .PP \fBTcl_Init\fR is a helper procedure that finds and \fBsource\fRs the \fBinit.tcl\fR script, which should exist somewhere on the Tcl library path. .PP \fBTcl_Init\fR is typically called from \fBTcl_AppInit\fR procedures. .SH "SEE ALSO" Tcl_AppInit, Tcl_Main .SH KEYWORDS application, initialization, interpreter tcl8.6.5/doc/Interp.30000644000175000017500000001365312663660065013671 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_Interp 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_Interp \- client-visible fields of interpreter structures .SH SYNOPSIS .nf \fB#include \fR .sp typedef struct { char *\fIresult\fR; Tcl_FreeProc *\fIfreeProc\fR; int \fIerrorLine\fR; } \fBTcl_Interp\fR; typedef void \fBTcl_FreeProc\fR( char *\fIblockPtr\fR); .BE .SH DESCRIPTION .PP The \fBTcl_CreateInterp\fR procedure returns a pointer to a Tcl_Interp structure. Callers of \fBTcl_CreateInterp\fR should use this pointer as an opaque token, suitable for nothing other than passing back to other routines in the Tcl interface. Accessing fields directly through the pointer as described below is no longer supported. The supported public routines \fBTcl_SetResult\fR, \fBTcl_GetResult\fR, \fBTcl_SetErrorLine\fR, \fBTcl_GetErrorLine\fR must be used instead. .PP For legacy programs and extensions no longer being maintained, compiles against the Tcl 8.6 header files are only possible with the compiler directives .CS #define USE_INTERP_RESULT .CE and/or .CS #define USE_INTERP_ERRORLINE .CE depending on which fields of the \fBTcl_Interp\fR struct are accessed. These directives may be embedded in code or supplied via compiler options. .PP The \fIresult\fR and \fIfreeProc\fR fields are used to return results or error messages from commands. This information is returned by command procedures back to \fBTcl_Eval\fR, and by \fBTcl_Eval\fR back to its callers. The \fIresult\fR field points to the string that represents the result or error message, and the \fIfreeProc\fR field tells how to dispose of the storage for the string when it is not needed anymore. The easiest way for command procedures to manipulate these fields is to call procedures like \fBTcl_SetResult\fR or \fBTcl_AppendResult\fR; they will hide all the details of managing the fields. The description below is for those procedures that manipulate the fields directly. .PP Whenever a command procedure returns, it must ensure that the \fIresult\fR field of its interpreter points to the string being returned by the command. The \fIresult\fR field must always point to a valid string. If a command wishes to return no result then \fIinterp->result\fR should point to an empty string. Normally, results are assumed to be statically allocated, which means that the contents will not change before the next time \fBTcl_Eval\fR is called or some other command procedure is invoked. In this case, the \fIfreeProc\fR field must be zero. Alternatively, a command procedure may dynamically allocate its return value (e.g. using \fBTcl_Alloc\fR) and store a pointer to it in \fIinterp->result\fR. In this case, the command procedure must also set \fIinterp->freeProc\fR to the address of a procedure that can free the value, or \fBTCL_DYNAMIC\fR if the storage was allocated directly by Tcl or by a call to \fBTcl_Alloc\fR. If \fIinterp->freeProc\fR is non-zero, then Tcl will call \fIfreeProc\fR to free the space pointed to by \fIinterp->result\fR before it invokes the next command. If a client procedure overwrites \fIinterp->result\fR when \fIinterp->freeProc\fR is non-zero, then it is responsible for calling \fIfreeProc\fR to free the old \fIinterp->result\fR (the \fBTcl_FreeResult\fR macro should be used for this purpose). .PP \fIFreeProc\fR should have arguments and result that match the \fBTcl_FreeProc\fR declaration above: it receives a single argument which is a pointer to the result value to free. In most applications \fBTCL_DYNAMIC\fR is the only non-zero value ever used for \fIfreeProc\fR. However, an application may store a different procedure address in \fIfreeProc\fR in order to use an alternate memory allocator or in order to do other cleanup when the result memory is freed. .PP As part of processing each command, \fBTcl_Eval\fR initializes \fIinterp->result\fR and \fIinterp->freeProc\fR just before calling the command procedure for the command. The \fIfreeProc\fR field will be initialized to zero, and \fIinterp->result\fR will point to an empty string. Commands that do not return any value can simply leave the fields alone. Furthermore, the empty string pointed to by \fIresult\fR is actually part of an array of \fBTCL_RESULT_SIZE\fR characters (approximately 200). If a command wishes to return a short string, it can simply copy it to the area pointed to by \fIinterp->result\fR. Or, it can use the sprintf procedure to generate a short result string at the location pointed to by \fIinterp->result\fR. .PP It is a general convention in Tcl-based applications that the result of an interpreter is normally in the initialized state described in the previous paragraph. Procedures that manipulate an interpreter's result (e.g. by returning an error) will generally assume that the result has been initialized when the procedure is called. If such a procedure is to be called after the result has been changed, then \fBTcl_ResetResult\fR should be called first to reset the result to its initialized state. The direct use of \fIinterp->result\fR is strongly deprecated (see \fBTcl_SetResult\fR). .PP The \fIerrorLine\fR field is valid only after \fBTcl_Eval\fR returns a \fBTCL_ERROR\fR return code. In this situation the \fIerrorLine\fR field identifies the line number of the command being executed when the error occurred. The line numbers are relative to the command being executed: 1 means the first line of the command passed to \fBTcl_Eval\fR, 2 means the second line, and so on. The \fIerrorLine\fR field is typically used in conjunction with \fBTcl_AddErrorInfo\fR to report information about where an error occurred. \fIErrorLine\fR should not normally be modified except by \fBTcl_Eval\fR. .SH KEYWORDS free, initialized, interpreter, malloc, result tcl8.6.5/doc/BackgdErr.30000644000175000017500000000613512663660065014251 0ustar sergeisergei'\" '\" Copyright (c) 1992-1994 The Regents of the University of California. '\" Copyright (c) 1994-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_BackgroundError 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_BackgroundException, Tcl_BackgroundError \- report Tcl exception that occurred in background processing .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_BackgroundException\fR(\fIinterp, code\fR) .sp \fBTcl_BackgroundError\fR(\fIinterp\fR) .SH ARGUMENTS .AS Tcl_Interp *interp .AP Tcl_Interp *interp in Interpreter in which the exception occurred. .AP int code in The exceptional return code to be reported. .BE .SH DESCRIPTION .PP This procedure is typically invoked when a Tcl exception (any return code other than TCL_OK) occurs during .QW "background processing" such as executing an event handler. When such an exception occurs, the condition is reported to Tcl or to a widget or some other C code, and there is not usually any obvious way for that code to report the exception to the user. In these cases the code calls \fBTcl_BackgroundException\fR with an \fIinterp\fR argument identifying the interpreter in which the exception occurred, and a \fIcode\fR argument holding the return code value of the exception. The state of the interpreter, including any error message in the interpreter result, and the values of any entries in the return options dictionary, is captured and saved. \fBTcl_BackgroundException\fR then arranges for the event loop to invoke at some later time the command registered in that interpreter to handle background errors by the \fBinterp bgerror\fR command, passing the captured values as arguments. The registered handler command is meant to report the exception in an application-specific fashion. The handler command receives two arguments, the result of the interp, and the return options of the interp at the time the error occurred. If the application registers no handler command, the default handler command will attempt to call \fBbgerror\fR to report the error. If an error condition arises while invoking the handler command, then \fBTcl_BackgroundException\fR reports the error itself by printing a message on the standard error file. .PP \fBTcl_BackgroundException\fR does not invoke the handler command immediately because this could potentially interfere with scripts that are in process at the time the error occurred. Instead, it invokes the handler command later as an idle callback. .PP It is possible for many background exceptions to accumulate before the handler command is invoked. When this happens, each of the exceptions is processed in order. However, if the handler command returns a break exception, then all remaining error reports for the interpreter are skipped. .PP The \fBTcl_BackgroundError\fR routine is an older and simpler interface useful when the exception code reported is \fBTCL_ERROR\fR. It is equivalent to: .PP .CS Tcl_BackgroundException(interp, TCL_ERROR); .CE .SH KEYWORDS background, bgerror, error, interp tcl8.6.5/doc/DoubleObj.30000644000175000017500000000511312663660065014265 0ustar sergeisergei'\" '\" Copyright (c) 1996-1997 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_DoubleObj 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_NewDoubleObj, Tcl_SetDoubleObj, Tcl_GetDoubleFromObj \- manipulate Tcl values as floating-point values .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * \fBTcl_NewDoubleObj\fR(\fIdoubleValue\fR) .sp \fBTcl_SetDoubleObj\fR(\fIobjPtr, doubleValue\fR) .sp int \fBTcl_GetDoubleFromObj\fR(\fIinterp, objPtr, doublePtr\fR) .SH ARGUMENTS .AS Tcl_Interp doubleValue in/out .AP double doubleValue in A double-precision floating-point value used to initialize or set a Tcl value. .AP Tcl_Obj *objPtr in/out For \fBTcl_SetDoubleObj\fR, this points to the value in which to store a double value. For \fBTcl_GetDoubleFromObj\fR, this refers to the value from which to retrieve a double value. .AP Tcl_Interp *interp in/out When non-NULL, an error message is left here when double value retrieval fails. .AP double *doublePtr out Points to place to store the double value obtained from \fIobjPtr\fR. .BE .SH DESCRIPTION .PP These procedures are used to create, modify, and read Tcl values that hold double-precision floating-point values. .PP \fBTcl_NewDoubleObj\fR creates and returns a new Tcl value initialized to the double value \fIdoubleValue\fR. The returned Tcl value is unshared. .PP \fBTcl_SetDoubleObj\fR sets the value of an existing Tcl value pointed to by \fIobjPtr\fR to the double value \fIdoubleValue\fR. The \fIobjPtr\fR argument must point to an unshared Tcl value. Any attempt to set the value of a shared Tcl value violates Tcl's copy-on-write policy. Any existing string representation or internal representation in the unshared Tcl value will be freed as a consequence of setting the new value. .PP \fBTcl_GetDoubleFromObj\fR attempts to retrieve a double value from the Tcl value \fIobjPtr\fR. If the attempt succeeds, then \fBTCL_OK\fR is returned, and the double value is written to the storage pointed to by \fIdoublePtr\fR. If the attempt fails, then \fBTCL_ERROR\fR is returned, and if \fIinterp\fR is non-NULL, an error message is left in \fIinterp\fR. The \fBTcl_ObjType\fR of \fIobjPtr\fR may be changed to make subsequent calls to \fBTcl_GetDoubleFromObj\fR more efficient. '\" TODO: add discussion of treatment of NaN value .SH "SEE ALSO" Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult .SH KEYWORDS double, double value, double type, internal representation, value, value type, string representation tcl8.6.5/doc/prefix.n0000644000175000017500000000641012663660065014011 0ustar sergeisergei'\" '\" Copyright (c) 2008 Peter Spjuth '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH prefix n 8.6 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME tcl::prefix \- facilities for prefix matching .SH SYNOPSIS .nf \fB::tcl::prefix all\fR \fItable\fR \fIstring\fR \fB::tcl::prefix longest\fR \fItable\fR \fIstring\fR \fB::tcl::prefix match\fR \fI?option ...?\fR \fItable\fR \fIstring\fR .fi .BE .SH DESCRIPTION .PP This document describes commands looking up a prefix in a list of strings. The following commands are supported: .TP \fB::tcl::prefix all\fR \fItable\fR \fIstring\fR . Returns a list of all elements in \fItable\fR that begin with the prefix \fIstring\fR. .TP \fB::tcl::prefix longest\fR \fItable\fR \fIstring\fR . Returns the longest common prefix of all elements in \fItable\fR that begin with the prefix \fIstring\fR. .TP \fB::tcl::prefix match\fR ?\fIoptions\fR? \fItable\fR \fIstring\fR . If \fIstring\fR equals one element in \fItable\fR or is a prefix to exactly one element, the matched element is returned. If not, the result depends on the \fB\-error\fR option. (It is recommended that the \fItable\fR be sorted before use with this subcommand, so that the list of matches presented in the error message also becomes sorted, though this is not strictly necessary for the operation of this subcommand itself.) .RS .TP \fB\-exact\fR\0 . Accept only exact matches. .TP \fB\-message\0\fIstring\fR . Use \fIstring\fR in the error message at a mismatch. Default is .QW option . .TP \fB\-error\0\fIoptions\fR . The \fIoptions\fR are used when no match is found. If \fIoptions\fR is empty, no error is generated and an empty string is returned. Otherwise the \fIoptions\fR are used as \fBreturn\fR options when generating the error message. The default corresponds to setting .QW "\-level 0" . Example: If .QW "\fB\-error\fR {\-errorcode MyError \-level 1}" is used, an error would be generated as: .RS .PP .CS return \-errorcode MyError \-level 1 \-code error \e "ambiguous option ..." .CE .RE .RE .SH "EXAMPLES" .PP Basic use: .PP .CS namespace import ::tcl::prefix \fBprefix match\fR {apa bepa cepa} apa \fI\(-> apa\fR \fBprefix match\fR {apa bepa cepa} a \fI\(-> apa\fR \fBprefix match\fR \-exact {apa bepa cepa} a \fI\(-> bad option "a": must be apa, bepa, or cepa\fR \fBprefix match\fR \-message "switch" {apa ada bepa cepa} a \fI\(-> ambiguous switch "a": must be apa, ada, bepa, or cepa\fR \fBprefix longest\fR {fblocked fconfigure fcopy file fileevent flush} fc \fI\(-> fco\fR \fBprefix all\fR {fblocked fconfigure fcopy file fileevent flush} fc \fI\(-> fconfigure fcopy\fR .CE .PP Simplifying option matching: .PP .CS array set opts {\-apa 1 \-bepa "" \-cepa 0} foreach {arg val} $args { set opts([\fBprefix match\fR {\-apa \-bepa \-cepa} $arg]) $val } .CE .PP Creating a \fBswitch\fR that supports prefixes: .PP .CS switch [\fBprefix match\fR {apa bepa cepa} $arg] { apa { } bepa { } cepa { } } .CE .SH "SEE ALSO" lsearch(n), namespace(n), string(n), Tcl_GetIndexFromObj(3) .SH "KEYWORDS" prefix, table lookup '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/tm.n0000644000175000017500000002464012663660065013141 0ustar sergeisergei'\" '\" Copyright (c) 2004-2010 Andreas Kupries '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH tm n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME tm \- Facilities for locating and loading of Tcl Modules .SH SYNOPSIS .nf \fB::tcl::tm::path add \fR?\fIpath\fR...? \fB::tcl::tm::path remove \fR?\fIpath\fR...? \fB::tcl::tm::path list\fR \fB::tcl::tm::roots \fR?\fIpath\fR...? .fi .BE .SH DESCRIPTION .PP This document describes the facilities for locating and loading Tcl Modules (see \fBMODULE DEFINITION\fR for the definition of a Tcl Module). The following commands are supported: .TP \fB::tcl::tm::path add \fR?\fIpath\fR...? . The paths are added at the head to the list of module paths, in order of appearance. This means that the last argument ends up as the new head of the list. .RS .PP The command enforces the restriction that no path may be an ancestor directory of any other path on the list. If any of the new paths violates this restriction an error will be raised, before any of the paths have been added. In other words, if only one path argument violates the restriction then none will be added. .PP If a path is already present as is, no error will be raised and no action will be taken. .PP Paths are searched later in the order of their appearance in the list. As they are added to the front of the list they are searched in reverse order of addition. In other words, the paths added last are looked at first. .RE .TP \fB::tcl::tm::path remove \fR?\fIpath\fR...? . Removes the paths from the list of module paths. The command silently ignores all paths which are not on the list. .TP \fB::tcl::tm::path list\fR . Returns a list containing all registered module paths, in the order that they are searched for modules. .TP \fB::tcl::tm::roots \fR?\fIpath\fR...? . Similar to \fBpath add\fR, and layered on top of it. This command takes a list of paths, extends each with .QW "\fBtcl\fIX\fB/site-tcl\fR" , and .QW "\fBtcl\fIX\fB/\fIX\fB.\fIy\fR" , for major version \fIX\fR of the Tcl interpreter and minor version \fIy\fR less than or equal to the minor version of the interpreter, and adds the resulting set of paths to the list of paths to search. .RS .PP This command is used internally by the system to set up the system-specific default paths. .PP The command has been exposed to allow a build system to define additional root paths beyond those described by this document. .RE .SH "MODULE DEFINITION" .PP A Tcl Module is a Tcl Package contained in a single file, and no other files required by it. This file has to be \fBsource\fRable. In other words, a Tcl Module is always imported via: .PP .CS source module_file .CE .PP The \fBload\fR command is not directly used. This restriction is not an actual limitation, as some may believe. Ever since 8.4 the Tcl \fBsource\fR command reads only until the first ^Z character. This allows us to combine an arbitrary Tcl script with arbitrary binary data into one file, where the script processes the attached data in any it chooses to fully import and activate the package. .PP The name of a module file has to match the regular expression: .PP .CS ([_[:alpha:]][:_[:alnum:]]*)-([[:digit:]].*)\e.tm .CE .PP The first capturing parentheses provides the name of the package, the second clause its version. In addition to matching the pattern, the extracted version number must not raise an error when used in the command: .PP .CS package vcompare $version 0 .CE .SH "FINDING MODULES" .PP The directory tree for storing Tcl modules is separate from other parts of the filesystem and independent of \fBauto_path\fR. .PP Tcl Modules are searched for in all directories listed in the result of the command \fB::tcl::tm::path list\fR. This is called the \fIModule path\fR. Neither the \fBauto_path\fR nor the \fBtcl_pkgPath\fR variables are used. All directories on the module path have to obey one restriction: .RS .PP For any two directories, neither is an ancestor directory of the other. .RE .PP This is required to avoid ambiguities in package naming. If for example the two directories .QW "\fIfoo/\fR" and .QW "\fIfoo/cool\fR" were on the path a package named \fBcool::ice\fR could be found via the names \fBcool::ice\fR or \fBice\fR, the latter potentially obscuring a package named \fBice\fR, unqualified. .PP Before the search is started, the name of the requested package is translated into a partial path, using the following algorithm: .RS .PP All occurrences of .QW "\fB::\fR" in the package name are replaced by the appropriate directory separator character for the platform we are on. On Unix, for example, this is .QW "\fB/\fR" . .RE .PP Example: .RS .PP The requested package is \fBencoding::base64\fR. The generated partial path is .QW "\fIencoding/base64\fR" . .RE .PP After this translation the package is looked for in all module paths, by combining them one-by-one, first to last with the partial path to form a complete search pattern. Note that the search algorithm rejects all files where the filename does not match the regular expression given in the section \fBMODULE DEFINITION\fR. For the remaining files \fIprovide scripts\fR are generated and added to the package ifneeded database. .PP The algorithm falls back to the previous unknown handler when none of the found module files satisfy the request. If the request was satisfied the fall-back is ignored. .PP Note that packages in module form have \fIno\fR control over the \fIindex\fR and \fIprovide script\fRs entered into the package database for them. For a module file \fBMF\fR the \fIindex script\fR is always: .PP .CS package ifneeded \fBPNAME PVERSION\fR [list source \fBMF\fR] .CE .PP and the \fIprovide script\fR embedded in the above is: .PP .CS source \fBMF\fR .CE .PP Both package name \fBPNAME\fR and package version \fBPVERSION\fR are extracted from the filename \fBMF\fR according to the definition below: .PP .CS \fBMF\fR = /module_path/\fBPNAME\(fm\fR-\fBPVERSION\fR.tm .CE .PP Where \fBPNAME\(fm\fR is the partial path of the module as defined in section \fBFINDING MODULES\fR, and translated into \fBPNAME\fR by changing all directory separators to .QW "\fB::\fR" , and \fBmodule_path\fR is the path (from the list of paths to search) that we found the module file under. .PP Note also that we are here creating a connection between package names and paths. Tcl is case-sensitive when it comes to comparing package names, but there are filesystems which are not, like NTFS. Luckily these filesystems do store the case of the name, despite not using the information when comparing. .PP Given the above we allow the names for packages in Tcl modules to have mixed-case, but also require that there are no collisions when comparing names in a case-insensitive manner. In other words, if a package \fBFoo\fR is deployed in the form of a Tcl Module, packages like \fBfoo\fR, \fBfOo\fR, etc. are not allowed anymore. .SH "DEFAULT PATHS" .PP The default list of paths on the module path is computed by a \fBtclsh\fR as follows, where \fIX\fR is the major version of the Tcl interpreter and \fIy\fR is less than or equal to the minor version of the Tcl interpreter. .PP All the default paths are added to the module path, even those paths which do not exist. Non-existent paths are filtered out during actual searches. This enables a user to create one of the paths searched when needed and all running applications will automatically pick up any modules placed in them. .PP The paths are added in the order as they are listed below, and for lists of paths defined by an environment variable in the order they are found in the variable. .SS "SYSTEM SPECIFIC PATHS" .TP \fBfile normalize [info library]/../tcl\fIX\fB/\fIX\fB.\fIy\fR . In other words, the interpreter will look into a directory specified by its major version and whose minor versions are less than or equal to the minor version of the interpreter. .RS .PP For example for Tcl 8.4 the paths searched are: .PP .CS \fB[info library]/../tcl8/8.4\fR \fB[info library]/../tcl8/8.3\fR \fB[info library]/../tcl8/8.2\fR \fB[info library]/../tcl8/8.1\fR \fB[info library]/../tcl8/8.0\fR .CE .PP This definition assumes that a package defined for Tcl \fIX\fB.\fIy\fR can also be used by all interpreters which have the same major number \fIX\fR and a minor number greater than \fIy\fR. .RE .TP \fBfile normalize EXEC/tcl\fIX\fB/\fIX\fB.\fIy\fR . Where \fBEXEC\fR is \fBfile normalize [info nameofexecutable]/../lib\fR or \fBfile normalize [::tcl::pkgconfig get libdir,runtime]\fR .RS .PP This sets of paths is handled equivalently to the set coming before, except that it is anchored in \fBEXEC_PREFIX\fR. For a build with \fBPREFIX\fR = \fBEXEC_PREFIX\fR the two sets are identical. .RE .SS "SITE SPECIFIC PATHS" .TP \fBfile normalize [info library]/../tcl\fIX\fB/site-tcl\fR . Note that this is always a single entry because \fIX\fR is always a specific value (the current major version of Tcl). .SS "USER SPECIFIC PATHS" .TP \fB$::env(TCL\fIX\fB_\fIy\fB_TM_PATH)\fR . A list of paths, separated by either \fB:\fR (Unix) or \fB;\fR (Windows). This is user and site specific as this environment variable can be set not only by the user's profile, but by system configuration scripts as well. .TP \fB$::env(TCL\fIX\fB.\fIy\fB_TM_PATH)\fR . Same meaning and content as the previous variable. However the use of dot '.' to separate major and minor version number makes this name less to non-portable and its use is discouraged. Support of this variable has been kept only for backward compatibility with the original specification, i.e. TIP 189. .PP These paths are seen and therefore shared by all Tcl shells in the \fB$::env(PATH)\fR of the user. .PP Note that \fIX\fR and \fIy\fR follow the general rules set out above. In other words, Tcl 8.4, for example, will look at these 10 environment variables: .PP .CS \fB$::env(TCL8.4_TM_PATH)\fR \fB$::env(TCL8_4_TM_PATH)\fR \fB$::env(TCL8.3_TM_PATH)\fR \fB$::env(TCL8_3_TM_PATH)\fR \fB$::env(TCL8.2_TM_PATH)\fR \fB$::env(TCL8_2_TM_PATH)\fR \fB$::env(TCL8.1_TM_PATH)\fR \fB$::env(TCL8_1_TM_PATH)\fR \fB$::env(TCL8.0_TM_PATH)\fR \fB$::env(TCL8_0_TM_PATH)\fR .CE .SH "SEE ALSO" package(n), Tcl Improvement Proposal #189 .QW "\fITcl Modules\fR" (online at http://tip.tcl.tk/189.html), Tcl Improvement Proposal #190 .QW "\fIImplementation Choices for Tcl Modules\fR" (online at http://tip.tcl.tk/190.html) .SH "KEYWORDS" modules, package .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/error.n0000644000175000017500000000452112663660065013646 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 error n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME error \- Generate an error .SH SYNOPSIS \fBerror \fImessage\fR ?\fIinfo\fR? ?\fIcode\fR? .BE .SH DESCRIPTION .PP Returns a \fBTCL_ERROR\fR code, which causes command interpretation to be unwound. \fIMessage\fR is a string that is returned to the application to indicate what went wrong. .PP The \fB\-errorinfo\fR return option of an interpreter is used to accumulate a stack trace of what was in progress when an error occurred; as nested commands unwind, the Tcl interpreter adds information to the \fB\-errorinfo\fR return option. If the \fIinfo\fR argument is present, it is used to initialize the \fB\-errorinfo\fR return options and the first increment of unwind information will not be added by the Tcl interpreter. In other words, the command containing the \fBerror\fR command will not appear in the stack trace; in its place will be \fIinfo\fR. Historically, this feature had been most useful in conjunction with the \fBcatch\fR command: if a caught error cannot be handled successfully, \fIinfo\fR can be used to return a stack trace reflecting the original point of occurrence of the error: .PP .CS catch {...} errMsg set savedInfo $::errorInfo \&... \fBerror\fR $errMsg $savedInfo .CE .PP When working with Tcl 8.5 or later, the following code should be used instead: .PP .CS catch {...} errMsg options \&... return -options $options $errMsg .CE .PP If the \fIcode\fR argument is present, then its value is stored in the \fB\-errorcode\fR return option. The \fB\-errorcode\fR return option is intended to hold a machine-readable description of the error in cases where such information is available; see the \fBreturn\fR manual page for information on the proper format for this option's value. .SH EXAMPLE .PP Generate an error if a basic mathematical operation fails: .PP .CS if {1+2 != 3} { \fBerror\fR "something is very wrong with addition" } .CE .SH "SEE ALSO" catch(n), return(n) .SH KEYWORDS error, exception '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/expr.n0000644000175000017500000003727112663660065013503 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-2000 Sun Microsystems, Inc. '\" Copyright (c) 2005 by Kevin B. Kenny . All rights reserved '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH expr n 8.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME expr \- Evaluate an expression .SH SYNOPSIS \fBexpr \fIarg \fR?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP Concatenates \fIarg\fRs (adding separator spaces between them), evaluates the result as a Tcl expression, and returns the value. The operators permitted in Tcl expressions include a subset of the operators permitted in C expressions. For those operators common to both Tcl and C, Tcl applies the same meaning and precedence as the corresponding C operators. Expressions almost always yield numeric results (integer or floating-point values). For example, the expression .PP .CS \fBexpr\fR 8.2 + 6 .CE .PP evaluates to 14.2. Tcl expressions differ from C expressions in the way that operands are specified. Also, Tcl expressions support non-numeric operands and string comparisons, as well as some additional operators not found in C. .SS OPERANDS .PP A Tcl expression consists of a combination of operands, operators, parentheses and commas. White space may be used between the operands and operators and parentheses (or commas); it is ignored by the expression's instructions. Where possible, operands are interpreted as integer values. Integer values may be specified in decimal (the normal case), in binary (if the first two characters of the operand are \fB0b\fR), in octal (if the first two characters of the operand are \fB0o\fR), or in hexadecimal (if the first two characters of the operand are \fB0x\fR). For compatibility with older Tcl releases, an octal integer value is also indicated simply when the first character of the operand is \fB0\fR, whether or not the second character is also \fBo\fR. If an operand does not have one of the integer formats given above, then it is treated as a floating-point number if that is possible. Floating-point numbers may be specified in any of several common formats making use of the decimal digits, the decimal point \fB.\fR, the characters \fBe\fR or \fBE\fR indicating scientific notation, and the sign characters \fB+\fR or \fB\-\fR. For example, all of the following are valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16. Also recognized as floating point values are the strings \fBInf\fR and \fBNaN\fR making use of any case for each character. If no numeric interpretation is possible (note that all literal operands that are not numeric or boolean must be quoted with either braces or with double quotes), then an operand is left as a string (and only a limited set of operators may be applied to it). .PP Operands may be specified in any of the following ways: .IP [1] As a numeric value, either integer or floating-point. .IP [2] As a boolean value, using any form understood by \fBstring is\fR \fBboolean\fR. .IP [3] As a Tcl variable, using standard \fB$\fR notation. The variable's value will be used as the operand. .IP [4] As a string enclosed in double-quotes. The expression parser will perform backslash, variable, and command substitutions on the information between the quotes, and use the resulting value as the operand .IP [5] As a string enclosed in braces. The characters between the open brace and matching close brace will be used as the operand without any substitutions. .IP [6] As a Tcl command enclosed in brackets. The command will be executed and its result will be used as the operand. .IP [7] As a mathematical function whose arguments have any of the above forms for operands, such as \fBsin($x)\fR. See \fBMATH FUNCTIONS\fR below for a discussion of how mathematical functions are handled. .PP Where the above substitutions occur (e.g. inside quoted strings), they are performed by the expression's instructions. However, the command parser may already have performed one round of substitution before the expression processor was called. As discussed below, it is usually best to enclose expressions in braces to prevent the command parser from performing substitutions on the contents. .PP For some examples of simple expressions, suppose the variable \fBa\fR has the value 3 and the variable \fBb\fR has the value 6. Then the command on the left side of each of the lines below will produce the value on the right side of the line: .PP .CS .ta 6c \fBexpr\fR 3.1 + $a \fI6.1\fR \fBexpr\fR 2 + "$a.$b" \fI5.6\fR \fBexpr\fR 4*[llength "6 2"] \fI8\fR \fBexpr\fR {{word one} < "word $a"} \fI0\fR .CE .SS OPERATORS .PP The valid operators (most of which are also available as commands in the \fBtcl::mathop\fR namespace; see the \fBmathop\fR(n) manual page for details) are listed below, grouped in decreasing order of precedence: .TP 20 \fB\-\0\0+\0\0~\0\0!\fR . Unary minus, unary plus, bit-wise NOT, logical NOT. None of these operators may be applied to string operands, and bit-wise NOT may be applied only to integers. .TP 20 \fB**\fR . Exponentiation. Valid for any numeric operands. .TP 20 \fB*\0\0/\0\0%\fR . Multiply, divide, remainder. None of these operators may be applied to string operands, and remainder may be applied only to integers. The remainder will always have the same sign as the divisor and an absolute value smaller than the absolute value of the divisor. .RS .PP When applied to integers, the division and remainder operators can be considered to partition the number line into a sequence of equal-sized adjacent non-overlapping pieces where each piece is the size of the divisor; the division result identifies which piece the divisor lay within, and the remainder result identifies where within that piece the divisor lay. A consequence of this is that the result of .QW "-57 \fB/\fR 10" is always -6, and the result of .QW "-57 \fB%\fR 10" is always 3. .RE .TP 20 \fB+\0\0\-\fR . Add and subtract. Valid for any numeric operands. .TP 20 \fB<<\0\0>>\fR . Left and right shift. Valid for integer operands only. A right shift always propagates the sign bit. .TP 20 \fB<\0\0>\0\0<=\0\0>=\fR . Boolean less, greater, less than or equal, and greater than or equal. Each operator produces 1 if the condition is true, 0 otherwise. These operators may be applied to strings as well as numeric operands, in which case string comparison is used. .TP 20 \fB==\0\0!=\fR . Boolean equal and not equal. Each operator produces a zero/one result. Valid for all operand types. .TP 20 \fBeq\0\0ne\fR . Boolean string equal and string not equal. Each operator produces a zero/one result. The operand types are interpreted only as strings. .TP 20 \fBin\0\0ni\fR . List containment and negated list containment. Each operator produces a zero/one result and treats its first argument as a string and its second argument as a Tcl list. The \fBin\fR operator indicates whether the first argument is a member of the second argument list; the \fBni\fR operator inverts the sense of the result. .TP 20 \fB&\fR . Bit-wise AND. Valid for integer operands only. .TP 20 \fB^\fR . Bit-wise exclusive OR. Valid for integer operands only. .TP 20 \fB|\fR . Bit-wise OR. Valid for integer operands only. .TP 20 \fB&&\fR . Logical AND. Produces a 1 result if both operands are non-zero, 0 otherwise. Valid for boolean and numeric (integers or floating-point) operands only. .TP 20 \fB||\fR . Logical OR. Produces a 0 result if both operands are zero, 1 otherwise. Valid for boolean and numeric (integers or floating-point) operands only. .TP 20 \fIx\fB?\fIy\fB:\fIz\fR . If-then-else, as in C. If \fIx\fR evaluates to non-zero, then the result is the value of \fIy\fR. Otherwise the result is the value of \fIz\fR. The \fIx\fR operand must have a boolean or numeric value. .PP See the C manual for more details on the results produced by each operator. The exponentiation operator promotes types like the multiply and divide operators, and produces a result that is the same as the output of the \fBpow\fR function (after any type conversions.) All of the binary operators but exponentiation group left-to-right within the same precedence level; exponentiation groups right-to-left. For example, the command .PP .CS \fBexpr\fR {4*2 < 7} .CE .PP returns 0, while .PP .CS \fBexpr\fR {2**3**2} .CE .PP returns 512. .PP The \fB&&\fR, \fB||\fR, and \fB?:\fR operators have .QW "lazy evaluation" , just as in C, which means that operands are not evaluated if they are not needed to determine the outcome. For example, in the command .PP .CS \fBexpr\fR {$v ? [a] : [b]} .CE .PP only one of .QW \fB[a]\fR or .QW \fB[b]\fR will actually be evaluated, depending on the value of \fB$v\fR. Note, however, that this is only true if the entire expression is enclosed in braces; otherwise the Tcl parser will evaluate both .QW \fB[a]\fR and .QW \fB[b]\fR before invoking the \fBexpr\fR command. .SS "MATH FUNCTIONS" .PP When the expression parser encounters a mathematical function such as \fBsin($x)\fR, it replaces it with a call to an ordinary Tcl function in the \fBtcl::mathfunc\fR namespace. The processing of an expression such as: .PP .CS \fBexpr\fR {sin($x+$y)} .CE .PP is the same in every way as the processing of: .PP .CS \fBexpr\fR {[tcl::mathfunc::sin [\fBexpr\fR {$x+$y}]]} .CE .PP which in turn is the same as the processing of: .PP .CS tcl::mathfunc::sin [\fBexpr\fR {$x+$y}] .CE .PP The executor will search for \fBtcl::mathfunc::sin\fR using the usual rules for resolving functions in namespaces. Either \fB::tcl::mathfunc::sin\fR or \fB[namespace current]::tcl::mathfunc::sin\fR will satisfy the request, and others may as well (depending on the current \fBnamespace path\fR setting). .PP Some mathematical functions have several arguments, separated by commas like in C. Thus: .PP .CS \fBexpr\fR {hypot($x,$y)} .CE .PP ends up as .PP .CS tcl::mathfunc::hypot $x $y .CE .PP See the \fBmathfunc\fR(n) manual page for the math functions that are available by default. .SS "TYPES, OVERFLOW, AND PRECISION" .PP All internal computations involving integers are done calling on the LibTomMath multiple precision integer library as required so that all integer calculations are performed exactly. Note that in Tcl releases prior to 8.5, integer calculations were performed with one of the C types \fIlong int\fR or \fITcl_WideInt\fR, causing implicit range truncation in those calculations where values overflowed the range of those types. Any code that relied on these implicit truncations will need to explicitly add \fBint()\fR or \fBwide()\fR function calls to expressions at the points where such truncation is required to take place. .PP All internal computations involving floating-point are done with the C type \fIdouble\fR. When converting a string to floating-point, exponent overflow is detected and results in the \fIdouble\fR value of \fBInf\fR or \fB\-Inf\fR as appropriate. Floating-point overflow and underflow are detected to the degree supported by the hardware, which is generally pretty reliable. .PP Conversion among internal representations for integer, floating-point, and string operands is done automatically as needed. For arithmetic computations, integers are used until some floating-point number is introduced, after which floating-point is used. For example, .PP .CS \fBexpr\fR {5 / 4} .CE .PP returns 1, while .PP .CS \fBexpr\fR {5 / 4.0} \fBexpr\fR {5 / ( [string length "abcd"] + 0.0 )} .CE .PP both return 1.25. Floating-point values are always returned with a .QW \fB.\fR or an .QW \fBe\fR so that they will not look like integer values. For example, .PP .CS \fBexpr\fR {20.0/5.0} .CE .PP returns \fB4.0\fR, not \fB4\fR. .SS "STRING OPERATIONS" .PP String values may be used as operands of the comparison operators, although the expression evaluator tries to do comparisons as integer or floating-point when it can, i.e., when all arguments to the operator allow numeric interpretations, except in the case of the \fBeq\fR and \fBne\fR operators. If one of the operands of a comparison is a string and the other has a numeric value, a canonical string representation of the numeric operand value is generated to compare with the string operand. Canonical string representation for integer values is a decimal string format. Canonical string representation for floating-point values is that produced by the \fB%g\fR format specifier of Tcl's \fBformat\fR command. For example, the commands .PP .CS \fBexpr\fR {"0x03" > "2"} \fBexpr\fR {"0y" > "0x12"} .CE .PP both return 1. The first comparison is done using integer comparison, and the second is done using string comparison. Because of Tcl's tendency to treat values as numbers whenever possible, it is not generally a good idea to use operators like \fB==\fR when you really want string comparison and the values of the operands could be arbitrary; it is better in these cases to use the \fBeq\fR or \fBne\fR operators, or the \fBstring\fR command instead. .SH "PERFORMANCE CONSIDERATIONS" .PP Enclose expressions in braces for the best speed and the smallest storage requirements. This allows the Tcl bytecode compiler to generate the best code. .PP As mentioned above, expressions are substituted twice: once by the Tcl parser and once by the \fBexpr\fR command. For example, the commands .PP .CS set a 3 set b {$a + 2} \fBexpr\fR $b*4 .CE .PP return 11, not a multiple of 4. This is because the Tcl parser will first substitute \fB$a + 2\fR for the variable \fBb\fR, then the \fBexpr\fR command will evaluate the expression \fB$a + 2*4\fR. .PP Most expressions do not require a second round of substitutions. Either they are enclosed in braces or, if not, their variable and command substitutions yield numbers or strings that do not themselves require substitutions. However, because a few unbraced expressions need two rounds of substitutions, the bytecode compiler must emit additional instructions to handle this situation. The most expensive code is required for unbraced expressions that contain command substitutions. These expressions must be implemented by generating new code each time the expression is executed. When the expression is unbraced to allow the substitution of a function or operator, consider using the commands documented in the \fBmathfunc\fR(n) or \fBmathop\fR(n) manual pages directly instead. .SH EXAMPLES .PP Define a procedure that computes an .QW interesting mathematical function: .PP .CS proc tcl::mathfunc::calc {x y} { \fBexpr\fR { ($x**2 - $y**2) / exp($x**2 + $y**2) } } .CE .PP Convert polar coordinates into cartesian coordinates: .PP .CS # convert from ($radius,$angle) set x [\fBexpr\fR { $radius * cos($angle) }] set y [\fBexpr\fR { $radius * sin($angle) }] .CE .PP Convert cartesian coordinates into polar coordinates: .PP .CS # convert from ($x,$y) set radius [\fBexpr\fR { hypot($y, $x) }] set angle [\fBexpr\fR { atan2($y, $x) }] .CE .PP Print a message describing the relationship of two string values to each other: .PP .CS puts "a and b are [\fBexpr\fR {$a eq $b ? {equal} : {different}}]" .CE .PP Set a variable to whether an environment variable is both defined at all and also set to a true boolean value: .PP .CS set isTrue [\fBexpr\fR { [info exists ::env(SOME_ENV_VAR)] && [string is true -strict $::env(SOME_ENV_VAR)] }] .CE .PP Generate a random integer in the range 0..99 inclusive: .PP .CS set randNum [\fBexpr\fR { int(100 * rand()) }] .CE .SH "SEE ALSO" array(n), for(n), if(n), mathfunc(n), mathop(n), namespace(n), proc(n), string(n), Tcl(n), while(n) .SH KEYWORDS arithmetic, boolean, compare, expression, fuzzy comparison .SH COPYRIGHT .nf Copyright (c) 1993 The Regents of the University of California. Copyright (c) 1994-2000 Sun Microsystems Incorporated. Copyright (c) 2005 by Kevin B. Kenny . All rights reserved. .fi '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/pkgMkIndex.n0000644000175000017500000002460112663660065014557 0ustar sergeisergei'\" '\" Copyright (c) 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 pkg_mkIndex n 8.3 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME pkg_mkIndex \- Build an index for automatic loading of packages .SH SYNOPSIS .nf \fBpkg_mkIndex\fR ?\fIoptions...\fR? \fIdir\fR ?\fIpattern pattern ...\fR? .fi .BE .SH DESCRIPTION .PP \fBPkg_mkIndex\fR is a utility procedure that is part of the standard Tcl library. It is used to create index files that allow packages to be loaded automatically when \fBpackage require\fR commands are executed. To use \fBpkg_mkIndex\fR, follow these steps: .IP [1] Create the package(s). Each package may consist of one or more Tcl script files or binary files. Binary files must be suitable for loading with the \fBload\fR command with a single argument; for example, if the file is \fBtest.so\fR it must be possible to load this file with the command \fBload test.so\fR. Each script file must contain a \fBpackage provide\fR command to declare the package and version number, and each binary file must contain a call to \fBTcl_PkgProvide\fR. .IP [2] Create the index by invoking \fBpkg_mkIndex\fR. The \fIdir\fR argument gives the name of a directory and each \fIpattern\fR argument is a \fBglob\fR-style pattern that selects script or binary files in \fIdir\fR. The default pattern is \fB*.tcl\fR and \fB*.[info sharedlibextension]\fR. .RS .PP \fBPkg_mkIndex\fR will create a file \fBpkgIndex.tcl\fR in \fIdir\fR with package information about all the files given by the \fIpattern\fR arguments. It does this by loading each file into a slave interpreter and seeing what packages and new commands appear (this is why it is essential to have \fBpackage provide\fR commands or \fBTcl_PkgProvide\fR calls in the files, as described above). If you have a package split among scripts and binary files, or if you have dependencies among files, you may have to use the \fB\-load\fR option or adjust the order in which \fBpkg_mkIndex\fR processes the files. See \fBCOMPLEX CASES\fR below. .RE .IP [3] Install the package as a subdirectory of one of the directories given by the \fBtcl_pkgPath\fR variable. If \fB$tcl_pkgPath\fR contains more than one directory, machine-dependent packages (e.g., those that contain binary shared libraries) should normally be installed under the first directory and machine-independent packages (e.g., those that contain only Tcl scripts) should be installed under the second directory. The subdirectory should include the package's script and/or binary files as well as the \fBpkgIndex.tcl\fR file. As long as the package is installed as a subdirectory of a directory in \fB$tcl_pkgPath\fR it will automatically be found during \fBpackage require\fR commands. .RS .PP If you install the package anywhere else, then you must ensure that the directory containing the package is in the \fBauto_path\fR global variable or an immediate subdirectory of one of the directories in \fBauto_path\fR. \fBAuto_path\fR contains a list of directories that are searched by both the auto-loader and the package loader; by default it includes \fB$tcl_pkgPath\fR. The package loader also checks all of the subdirectories of the directories in \fBauto_path\fR. You can add a directory to \fBauto_path\fR explicitly in your application, or you can add the directory to your \fBTCLLIBPATH\fR environment variable: if this environment variable is present, Tcl initializes \fBauto_path\fR from it during application startup. .RE .IP [4] Once the above steps have been taken, all you need to do to use a package is to invoke \fBpackage require\fR. For example, if versions 2.1, 2.3, and 3.1 of package \fBTest\fR have been indexed by \fBpkg_mkIndex\fR, the command \fBpackage require Test\fR will make version 3.1 available and the command \fBpackage require \-exact Test 2.1\fR will make version 2.1 available. There may be many versions of a package in the various index files in \fBauto_path\fR, but only one will actually be loaded in a given interpreter, based on the first call to \fBpackage require\fR. Different versions of a package may be loaded in different interpreters. .SH OPTIONS The optional switches are: .TP 15 \fB\-direct\fR The generated index will implement direct loading of the package upon \fBpackage require\fR. This is the default. .TP 15 \fB\-lazy\fR The generated index will manage to delay loading the package until the use of one of the commands provided by the package, instead of loading it immediately upon \fBpackage require\fR. This is not compatible with the use of \fIauto_reset\fR, and therefore its use is discouraged. .TP 15 \fB\-load \fIpkgPat\fR The index process will pre-load any packages that exist in the current interpreter and match \fIpkgPat\fR into the slave interpreter used to generate the index. The pattern match uses string match rules, but without making case distinctions. See \fBCOMPLEX CASES\fR below. .TP 15 \fB\-verbose\fR Generate output during the indexing process. Output is via the \fBtclLog\fR procedure, which by default prints to stderr. .TP 15 \fB\-\-\fR End of the flags, in case \fIdir\fR begins with a dash. .SH "PACKAGES AND THE AUTO-LOADER" .PP The package management facilities overlap somewhat with the auto-loader, in that both arrange for files to be loaded on-demand. However, package management is a higher-level mechanism that uses the auto-loader for the last step in the loading process. It is generally better to index a package with \fBpkg_mkIndex\fR rather than \fBauto_mkindex\fR because the package mechanism provides version control: several versions of a package can be made available in the index files, with different applications using different versions based on \fBpackage require\fR commands. In contrast, \fBauto_mkindex\fR does not understand versions so it can only handle a single version of each package. It is probably not a good idea to index a given package with both \fBpkg_mkIndex\fR and \fBauto_mkindex\fR. If you use \fBpkg_mkIndex\fR to index a package, its commands cannot be invoked until \fBpackage require\fR has been used to select a version; in contrast, packages indexed with \fBauto_mkindex\fR can be used immediately since there is no version control. .SH "HOW IT WORKS" .PP \fBPkg_mkIndex\fR depends on the \fBpackage unknown\fR command, the \fBpackage ifneeded\fR command, and the auto-loader. The first time a \fBpackage require\fR command is invoked, the \fBpackage unknown\fR script is invoked. This is set by Tcl initialization to a script that evaluates all of the \fBpkgIndex.tcl\fR files in the \fBauto_path\fR. The \fBpkgIndex.tcl\fR files contain \fBpackage ifneeded\fR commands for each version of each available package; these commands invoke \fBpackage provide\fR commands to announce the availability of the package, and they setup auto-loader information to load the files of the package. If the \fB\-lazy\fR flag was provided when the \fBpkgIndex.tcl\fR was generated, a given file of a given version of a given package is not actually loaded until the first time one of its commands is invoked. Thus, after invoking \fBpackage require\fR you may not see the package's commands in the interpreter, but you will be able to invoke the commands and they will be auto-loaded. .SH "DIRECT LOADING" .PP Some packages, for instance packages which use namespaces and export commands or those which require special initialization, might select that their package files be loaded immediately upon \fBpackage require\fR instead of delaying the actual loading to the first use of one of the package's command. This is the default mode when generating the package index. It can be overridden by specifying the \fB\-lazy\fR argument. .SH "COMPLEX CASES" Most complex cases of dependencies among scripts and binary files, and packages being split among scripts and binary files are handled OK. However, you may have to adjust the order in which files are processed by \fBpkg_mkIndex\fR. These issues are described in detail below. .PP If each script or file contains one package, and packages are only contained in one file, then things are easy. You simply specify all files to be indexed in any order with some glob patterns. .PP In general, it is OK for scripts to have dependencies on other packages. If scripts contain \fBpackage require\fR commands, these are stubbed out in the interpreter used to process the scripts, so these do not cause problems. If scripts call into other packages in global code, these calls are handled by a stub \fBunknown\fR command. However, if scripts make variable references to other package's variables in global code, these will cause errors. That is also bad coding style. .PP If binary files have dependencies on other packages, things can become tricky because it is not possible to stub out C-level APIs such as \fBTcl_PkgRequire\fR API when loading a binary file. For example, suppose the BLT package requires Tk, and expresses this with a call to \fBTcl_PkgRequire\fR in its \fBBlt_Init\fR routine. To support this, you must run \fBpkg_mkIndex\fR in an interpreter that has Tk loaded. You can achieve this with the \fB\-load \fIpkgPat\fR option. If you specify this option, \fBpkg_mkIndex\fR will load any packages listed by \fBinfo loaded\fR and that match \fIpkgPat\fR into the interpreter used to process files. In most cases this will satisfy the \fBTcl_PkgRequire\fR calls made by binary files. .PP If you are indexing two binary files and one depends on the other, you should specify the one that has dependencies last. This way the one without dependencies will get loaded and indexed, and then the package it provides will be available when the second file is processed. You may also need to load the first package into the temporary interpreter used to create the index by using the \fB\-load\fR flag; it will not hurt to specify package patterns that are not yet loaded. .PP If you have a package that is split across scripts and a binary file, then you should avoid the \fB\-load\fR flag. The problem is that if you load a package before computing the index it masks any other files that provide part of the same package. If you must use \fB\-load\fR, then you must specify the scripts first; otherwise the package loaded from the binary file may mask the package defined by the scripts. .SH "SEE ALSO" package(n) .SH KEYWORDS auto-load, index, package, version '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/StaticPkg.30000644000175000017500000000552212663660065014315 0ustar sergeisergei'\" '\" 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 \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. .SH KEYWORDS initialization procedure, package, static linking .SH "SEE ALSO" load(n), package(n), Tcl_PkgRequire(3) tcl8.6.5/doc/subst.n0000644000175000017500000001120612663660065013653 0ustar sergeisergei'\" '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2001 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH subst n 7.4 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME subst \- Perform backslash, command, and variable substitutions .SH SYNOPSIS \fBsubst \fR?\fB\-nobackslashes\fR? ?\fB\-nocommands\fR? ?\fB\-novariables\fR? \fIstring\fR .BE .SH DESCRIPTION .PP This command performs variable substitutions, command substitutions, and backslash substitutions on its \fIstring\fR argument and returns the fully-substituted result. The substitutions are performed in exactly the same way as for Tcl commands. As a result, the \fIstring\fR argument is actually substituted twice, once by the Tcl parser in the usual fashion for Tcl commands, and again by the \fIsubst\fR command. .PP If any of the \fB\-nobackslashes\fR, \fB\-nocommands\fR, or \fB\-novariables\fR are specified, then the corresponding substitutions are not performed. For example, if \fB\-nocommands\fR is specified, command substitution is not performed: open and close brackets are treated as ordinary characters with no special interpretation. .PP Note that the substitution of one kind can include substitution of other kinds. For example, even when the \fB\-novariables\fR option is specified, command substitution is performed without restriction. This means that any variable substitution necessary to complete the command substitution will still take place. Likewise, any command substitution necessary to complete a variable substitution will take place, even when \fB\-nocommands\fR is specified. See the \fBEXAMPLES\fR below. .PP If an error occurs during substitution, then \fBsubst\fR will return that error. If a break exception occurs during command or variable substitution, the result of the whole substitution will be the string (as substituted) up to the start of the substitution that raised the exception. If a continue exception occurs during the evaluation of a command or variable substitution, an empty string will be substituted for that entire command or variable substitution (as long as it is well-formed Tcl.) If a return exception occurs, or any other return code is returned during command or variable substitution, then the returned value is substituted for that substitution. See the \fBEXAMPLES\fR below. In this way, all exceptional return codes are .QW caught by \fBsubst\fR. The \fBsubst\fR command itself will either return an error, or will complete successfully. .SH EXAMPLES .PP When it performs its substitutions, \fIsubst\fR does not give any special treatment to double quotes or curly braces (except within command substitutions) so the script .PP .CS set a 44 \fBsubst\fR {xyz {$a}} .CE .PP returns .QW "\fBxyz {44}\fR" , not .QW "\fBxyz {$a}\fR" and the script .PP .CS set a "p\e} q \e{r" \fBsubst\fR {xyz {$a}} .CE .PP returns .QW "\fBxyz {p} q {r}\fR" , not .QW "\fBxyz {p\e} q \e{r}\fR". .PP When command substitution is performed, it includes any variable substitution necessary to evaluate the script. .PP .CS set a 44 \fBsubst\fR -novariables {$a [format $a]} .CE .PP returns .QW "\fB$a 44\fR" , not .QW "\fB$a $a\fR" . Similarly, when variable substitution is performed, it includes any command substitution necessary to retrieve the value of the variable. .PP .CS proc b {} {return c} array set a {c c [b] tricky} \fBsubst\fR -nocommands {[b] $a([b])} .CE .PP returns .QW "\fB[b] c\fR" , not .QW "\fB[b] tricky\fR" . .PP The continue and break exceptions allow command substitutions to prevent substitution of the rest of the command substitution and the rest of \fIstring\fR respectively, giving script authors more options when processing text using \fIsubst\fR. For example, the script .PP .CS \fBsubst\fR {abc,[break],def} .CE .PP returns .QW \fBabc,\fR , not .QW \fBabc,,def\fR and the script .PP .CS \fBsubst\fR {abc,[continue;expr {1+2}],def} .CE .PP returns .QW \fBabc,,def\fR , not .QW \fBabc,3,def\fR . .PP Other exceptional return codes substitute the returned value .PP .CS \fBsubst\fR {abc,[return foo;expr {1+2}],def} .CE .PP returns .QW \fBabc,foo,def\fR , not .QW \fBabc,3,def\fR and .PP .CS \fBsubst\fR {abc,[return -code 10 foo;expr {1+2}],def} .CE .PP also returns .QW \fBabc,foo,def\fR , not .QW \fBabc,3,def\fR . .SH "SEE ALSO" Tcl(n), eval(n), break(n), continue(n) .SH KEYWORDS backslash substitution, command substitution, quoting, substitution, variable substitution .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/GetTime.30000644000175000017500000001042712663660065013762 0ustar sergeisergei'\" '\" Copyright (c) 2001 by Kevin B. Kenny . '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_GetTime 3 8.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_GetTime, Tcl_SetTimeProc, Tcl_QueryTimeProc \- get date and time .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_GetTime\fR(\fItimePtr\fR) .sp \fBTcl_SetTimeProc\fR(\fIgetProc, scaleProc, clientData\fR) .sp \fBTcl_QueryTimeProc\fR(\fIgetProcPtr, scaleProcPtr, clientDataPtr\fR) .SH ARGUMENTS .AS Tcl_GetTimeProc *getProc in .AP Tcl_Time *timePtr out Points to memory in which to store the date and time information. .AP Tcl_GetTimeProc getProc in Pointer to handler function replacing \fBTcl_GetTime\fR's access to the OS. .AP Tcl_ScaleTimeProc scaleProc in Pointer to handler function for the conversion of time delays in the virtual domain to real-time. .AP ClientData clientData in Value passed through to the two handler functions. .AP Tcl_GetTimeProc *getProcPtr out Pointer to place the currently registered get handler function into. .AP Tcl_ScaleTimeProc *scaleProcPtr out Pointer to place the currently registered scale handler function into. .AP ClientData *clientDataPtr out Pointer to place the currently registered pass-through value into. .BE .SH DESCRIPTION .PP The \fBTcl_GetTime\fR function retrieves the current time as a \fITcl_Time\fR structure in memory the caller provides. This structure has the following definition: .PP .CS typedef struct Tcl_Time { long \fIsec\fR; long \fIusec\fR; } \fBTcl_Time\fR; .CE .PP On return, the \fIsec\fR member of the structure is filled in with the number of seconds that have elapsed since the \fIepoch:\fR the epoch is the point in time of 00:00 UTC, 1 January 1970. This number does \fInot\fR count leap seconds \- an interval of one day advances it by 86400 seconds regardless of whether a leap second has been inserted. .PP The \fIusec\fR member of the structure is filled in with the number of microseconds that have elapsed since the start of the second designated by \fIsec\fR. The Tcl library makes every effort to keep this number as precise as possible, subject to the limitations of the computer system. On multiprocessor variants of Windows, this number may be limited to the 10- or 20-ms granularity of the system clock. (On single-processor Windows systems, the \fIusec\fR field is derived from a performance counter and is highly precise.) .SS "VIRTUALIZED TIME" .PP The \fBTcl_SetTimeProc\fR function registers two related handler functions with the core. The first handler function is a replacement for \fBTcl_GetTime\fR, or rather the OS access made by \fBTcl_GetTime\fR. The other handler function is used by the Tcl notifier to convert wait/block times from the virtual domain into real time. .PP The \fBTcl_QueryTimeProc\fR function returns the currently registered handler functions. If no external handlers were set then this will return the standard handlers accessing and processing the native time of the OS. The arguments to the function are allowed to be NULL; and any argument which is NULL is ignored and not set. .PP The signatures of the handler functions are as follows: .PP .CS typedef void \fBTcl_GetTimeProc\fR( Tcl_Time *\fItimebuf\fR, ClientData \fIclientData\fR); typedef void \fBTcl_ScaleTimeProc\fR( Tcl_Time *\fItimebuf\fR, ClientData \fIclientData\fR); .CE .PP The \fItimebuf\fR fields contain the time to manipulate, and the \fIclientData\fR fields contain a pointer supplied at the time the handler functions were registered. .PP Any handler pair specified has to return data which is consistent between them. In other words, setting one handler of the pair to something assuming a 10-times slowdown, and the other handler of the pair to something assuming a two-times slowdown is wrong and not allowed. .PP The set handler functions are allowed to run the delivered time backwards, however this should be avoided. We have to allow it as the native time can run backwards as the user can fiddle with the system time one way or other. Note that the insertion of the hooks will not change the behavior of the Tcl core with regard to this situation, i.e. the existing behavior is retained. .SH "SEE ALSO" clock(n) .SH KEYWORDS date, time tcl8.6.5/doc/man.macros0000644000175000017500000001326212663653206014320 0ustar sergeisergei.\" The -*- nroff -*- definitions below are for supplemental macros used .\" in Tcl/Tk manual entries. .\" .\" .AP type name in/out ?indent? .\" Start paragraph describing an argument to a library procedure. .\" type is type of argument (int, etc.), in/out is either "in", "out", .\" or "in/out" to describe whether procedure reads or modifies arg, .\" and indent is equivalent to second arg of .IP (shouldn't ever be .\" needed; use .AS below instead) .\" .\" .AS ?type? ?name? .\" Give maximum sizes of arguments for setting tab stops. Type and .\" name are examples of largest possible arguments that will be passed .\" to .AP later. If args are omitted, default tab stops are used. .\" .\" .BS .\" Start box enclosure. From here until next .BE, everything will be .\" enclosed in one large box. .\" .\" .BE .\" End of box enclosure. .\" .\" .CS .\" Begin code excerpt. .\" .\" .CE .\" End code excerpt. .\" .\" .VS ?version? ?br? .\" Begin vertical sidebar, for use in marking newly-changed parts .\" of man pages. The first argument is ignored and used for recording .\" the version when the .VS was added, so that the sidebars can be .\" found and removed when they reach a certain age. If another argument .\" is present, then a line break is forced before starting the sidebar. .\" .\" .VE .\" End of vertical sidebar. .\" .\" .DS .\" Begin an indented unfilled display. .\" .\" .DE .\" End of indented unfilled display. .\" .\" .SO ?manpage? .\" Start of list of standard options for a Tk widget. The manpage .\" argument defines where to look up the standard options; if .\" omitted, defaults to "options". The options follow on successive .\" lines, in three columns separated by tabs. .\" .\" .SE .\" End of list of standard options for a Tk widget. .\" .\" .OP cmdName dbName dbClass .\" Start of description of a specific option. cmdName gives the .\" option's name as specified in the class command, dbName gives .\" the option's name in the option database, and dbClass gives .\" the option's class in the option database. .\" .\" .UL arg1 arg2 .\" Print arg1 underlined, then print arg2 normally. .\" .\" .QW arg1 ?arg2? .\" Print arg1 in quotes, then arg2 normally (for trailing punctuation). .\" .\" .PQ arg1 ?arg2? .\" Print an open parenthesis, arg1 in quotes, then arg2 normally .\" (for trailing punctuation) and then a closing parenthesis. .\" .\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. .if t .wh -1.3i ^B .nr ^l \n(.l .ad b .\" # Start an argument description .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. .\" # define tabbing values for .AP .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out .\" # BS - start boxed text .\" # ^y = starting y location .\" # ^b = 1 .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. .\" # BE - end boxed text (draw box now) .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. .\" # VS - start vertical sidebar .\" # ^Y = starting y location .\" # ^v = 1 (for troff; for nroff this doesn't matter) .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. .\" # VE - end of vertical sidebar .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. .\" # Special macro to handle page bottom: finish off current .\" # box/sidebar if in box/sidebar mode, then invoked standard .\" # page bottom macro. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, .\" draw two sides but no top otherwise. .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .\} .if \\n(^v \{\ .nr ^x \\n(^tu+1v-\\n(^Yu \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c .\} .bp 'fi .ev .if \\n(^b \{\ .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. .\" # DS - begin display .de DS .RS .nf .sp .. .\" # DE - end display .de DE .fi .RE .sp .. .\" # SO - start of list of standard options .de SO 'ie '\\$1'' .ds So \\fBoptions\\fR 'el .ds So \\fB\\$1\\fR .SH "STANDARD OPTIONS" .LP .nf .ta 5.5c 11c .ft B .. .\" # SE - end of list of standard options .de SE .fi .ft R .LP See the \\*(So manual entry for details on the standard options. .. .\" # OP - start of full description for a single option .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. .\" # CS - begin code excerpt .de CS .RS .nf .ta .25i .5i .75i 1i .. .\" # CE - end code excerpt .de CE .fi .RE .. .\" # UL - underline word .de UL \\$1\l'|0\(ul'\\$2 .. .\" # QW - apply quotation marks to word .de QW .ie '\\*(lq'"' ``\\$1''\\$2 .\"" fix emacs highlighting .el \\*(lq\\$1\\*(rq\\$2 .. .\" # PQ - apply parens and quotation marks to word .de PQ .ie '\\*(lq'"' (``\\$1''\\$2)\\$3 .\"" fix emacs highlighting .el (\\*(lq\\$1\\*(rq\\$2)\\$3 .. .\" # QR - quoted range .de QR .ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3 .\"" fix emacs highlighting .el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3 .. .\" # MT - "empty" string .de MT .QW "" .. tcl8.6.5/doc/Load.30000644000175000017500000000550112663660065013300 0ustar sergeisergei'\" '\" Copyright (c) 2009-2010 Kevin B. Kenny '\" Copyright (c) 2010 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Load 3 8.6 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_LoadFile, Tcl_FindSymbol \- platform-independent dynamic library loading .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_LoadFile\fR(\fIinterp, pathPtr, symbols, flags, procPtrs, loadHandlePtr\fR) .sp void * \fBTcl_FindSymbol\fR(\fIinterp, loadHandle, symbol\fR) .SH ARGUMENTS .AS Tcl_LoadHandle loadHandle in .AP Tcl_Interp *interp in Interpreter to use for reporting error messages. .AP Tcl_Obj *pathPtr in The name of the file to load. If it is a single name, the library search path of the current environment will be used to resolve it. .AP "const char *const" symbols[] in Array of names of symbols to be resolved during the load of the library, or NULL if no symbols are to be resolved. If an array is given, the last entry in the array must be NULL. .AP int flags in The value should normally be 0, but \fITCL_LOAD_GLOBAL\fR or \fITCL_LOAD_LAZY\fR or a combination of those two is allowed as well. .AP void *procPtrs out Points to an array that will hold the addresses of the functions described in the \fIsymbols\fR argument. Should be NULL if no symbols are to be resolved. .AP Tcl_LoadHandle *loadHandlePtr out Points to a variable that will hold the handle to the abstract token describing the library that has been loaded. .AP Tcl_LoadHandle loadHandle in Abstract token describing the library to look up a symbol in. .AP "const char" *symbol in The name of the symbol to look up. .BE .SH DESCRIPTION .PP \fBTcl_LoadFile\fR loads a file from the filesystem (including potentially any virtual filesystem that has been installed) and provides a handle to it that may be used in further operations. The \fIsymbols\fR array, if non-NULL, supplies a set of names of symbols (typically functions) that must be resolved from the library and which will be stored in the array indicated by \fIprocPtrs\fR. If any of the symbols is not resolved, the loading of the file will fail with an error message left in the interpreter (if that is non-NULL). The result of \fBTcl_LoadFile\fR is a standard Tcl error code. The library may be unloaded with \fBTcl_FSUnloadFile\fR. .PP \fBTcl_FindSymbol\fR locates a symbol in a loaded library and returns it. If the symbol cannot be found, it returns NULL and sets an error message in the given \fIinterp\fR (if that is non-NULL). Note that it is unsafe to use this operation on a handle that has been passed to \fBTcl_FSUnloadFile\fR. .SH "SEE ALSO" Tcl_FSLoadFile(3), Tcl_FSUnloadFile(3), load(n), unload(n) .SH KEYWORDS binary code, loading, shared library '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/uplevel.n0000644000175000017500000000766512663660065014205 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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 uplevel n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME uplevel \- Execute a script in a different stack frame .SH SYNOPSIS \fBuplevel \fR?\fIlevel\fR?\fI arg \fR?\fIarg ...\fR? .BE .SH DESCRIPTION .PP All of the \fIarg\fR arguments are concatenated as if they had been passed to \fBconcat\fR; the result is then evaluated in the variable context indicated by \fIlevel\fR. \fBUplevel\fR returns the result of that evaluation. .PP If \fIlevel\fR is an integer then it gives a distance (up the procedure calling stack) to move before executing the command. If \fIlevel\fR consists of \fB#\fR followed by a number then the number gives an absolute level number. If \fIlevel\fR is omitted then it defaults to \fB1\fR. \fILevel\fR cannot be defaulted if the first \fIcommand\fR argument starts with a digit or \fB#\fR. .PP For example, suppose that procedure \fBa\fR was invoked from top-level, and that it called \fBb\fR, and that \fBb\fR called \fBc\fR. Suppose that \fBc\fR invokes the \fBuplevel\fR command. If \fIlevel\fR is \fB1\fR or \fB#2\fR or omitted, then the command will be executed in the variable context of \fBb\fR. If \fIlevel\fR is \fB2\fR or \fB#1\fR then the command will be executed in the variable context of \fBa\fR. If \fIlevel\fR is \fB3\fR or \fB#0\fR then the command will be executed at top-level (only global variables will be visible). .PP The \fBuplevel\fR command causes the invoking procedure to disappear from the procedure calling stack while the command is being executed. In the above example, suppose \fBc\fR invokes the command .PP .CS \fBuplevel\fR 1 {set x 43; d} .CE .PP where \fBd\fR is another Tcl procedure. The \fBset\fR command will modify the variable \fBx\fR in \fBb\fR's context, and \fBd\fR will execute at level 3, as if called from \fBb\fR. If it in turn executes the command .PP .CS \fBuplevel\fR {set x 42} .CE .PP then the \fBset\fR command will modify the same variable \fBx\fR in \fBb\fR's context: the procedure \fBc\fR does not appear to be on the call stack when \fBd\fR is executing. The \fBinfo level\fR command may be used to obtain the level of the current procedure. .PP \fBUplevel\fR makes it possible to implement new control constructs as Tcl procedures (for example, \fBuplevel\fR could be used to implement the \fBwhile\fR construct as a Tcl procedure). .PP The \fBnamespace eval\fR and \fBapply\fR commands offer other ways (besides procedure calls) that the Tcl naming context can change. They add a call frame to the stack to represent the namespace context. This means each \fBnamespace eval\fR command counts as another call level for \fBuplevel\fR and \fBupvar\fR commands. For example, \fBinfo level 1\fR will return a list describing a command that is either the outermost procedure call or the outermost \fBnamespace eval\fR command. Also, \fBuplevel #0\fR evaluates a script at top-level in the outermost namespace (the global namespace). .SH EXAMPLE As stated above, the \fBuplevel\fR command is useful for creating new control constructs. This example shows how (without error handling) it can be used to create a \fBdo\fR command that is the counterpart of \fBwhile\fR except for always performing the test after running the loop body: .PP .CS proc do {body while condition} { if {$while ne "while"} { error "required word missing" } set conditionCmd [list expr $condition] while {1} { \fBuplevel\fR 1 $body if {![\fBuplevel\fR 1 $conditionCmd]} { break } } } .CE .SH "SEE ALSO" apply(n), namespace(n), upvar(n) .SH KEYWORDS context, level, namespace, stack frame, variable .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/source.n0000644000175000017500000000427412663660065014022 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2000 Scriptics Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH source n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME source \- Evaluate a file or resource as a Tcl script .SH SYNOPSIS \fBsource \fIfileName\fR .sp \fBsource\fR \fB\-encoding \fIencodingName fileName\fR .BE .SH DESCRIPTION .PP This command takes the contents of the specified file or resource and passes it to the Tcl interpreter as a text script. The return value from \fBsource\fR is the return value of the last command executed in the script. If an error occurs in evaluating the contents of the script then the \fBsource\fR command will return that error. If a \fBreturn\fR command is invoked from within the script then the remainder of the file will be skipped and the \fBsource\fR command will return normally with the result from the \fBreturn\fR command. .PP The end-of-file character for files is .QW \e32 (^Z) for all platforms. The source command will read files up to this character. This restriction does not exist for the \fBread\fR or \fBgets\fR commands, allowing for files containing code and data segments (scripted documents). If you require a .QW ^Z in code for string comparison, you can use .QW \e032 or .QW \eu001a , which will be safely substituted by the Tcl interpreter into .QW ^Z . .PP A leading BOM (Byte order mark) contained in the file is ignored for unicode encodings (utf-8, unicode). .PP The \fB\-encoding\fR option is used to specify the encoding of the data stored in \fIfileName\fR. When the \fB\-encoding\fR option is omitted, the system encoding is assumed. .SH EXAMPLE .PP Run the script in the file \fBfoo.tcl\fR and then the script in the file \fBbar.tcl\fR: .PP .CS \fBsource\fR foo.tcl \fBsource\fR bar.tcl .CE .PP Alternatively: .PP .CS foreach scriptFile {foo.tcl bar.tcl} { \fBsource\fR $scriptFile } .CE .SH "SEE ALSO" file(n), cd(n), encoding(n), info(n) .SH KEYWORDS file, script tcl8.6.5/doc/break.n0000644000175000017500000000247512663660065013607 0ustar sergeisergei'\" '\" Copyright (c) 1993-1994 The Regents of the University of California. '\" Copyright (c) 1994-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 break n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME break \- Abort looping command .SH SYNOPSIS \fBbreak\fR .BE .SH DESCRIPTION .PP This command is typically invoked inside the body of a looping command such as \fBfor\fR or \fBforeach\fR or \fBwhile\fR. It returns a 3 (\fBTCL_BREAK\fR) result code, which causes a break exception to occur. The exception causes the current script to be aborted out to the innermost containing loop command, which then aborts its execution and returns normally. Break exceptions are also handled in a few other situations, such as the \fBcatch\fR command, Tk event bindings, and the outermost scripts of procedure bodies. .SH EXAMPLE .PP Print a line for each of the integers from 0 to 5: .PP .CS for {set x 0} {$x<10} {incr x} { if {$x > 5} { \fBbreak\fR } puts "x is $x" } .CE .SH "SEE ALSO" catch(n), continue(n), for(n), foreach(n), return(n), while(n) .SH KEYWORDS abort, break, loop '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/CrtSlave.30000644000175000017500000002364112663660065014151 0ustar sergeisergei'\" '\" 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_CreateSlave 3 7.6 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_IsSafe, Tcl_MakeSafe, Tcl_CreateSlave, Tcl_GetSlave, Tcl_GetMaster, Tcl_GetInterpPath, Tcl_CreateAlias, Tcl_CreateAliasObj, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_ExposeCommand, Tcl_HideCommand \- manage multiple Tcl interpreters, aliases and hidden commands .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_IsSafe\fR(\fIinterp\fR) .sp int \fBTcl_MakeSafe\fR(\fIinterp\fR) .sp Tcl_Interp * \fBTcl_CreateSlave\fR(\fIinterp, slaveName, isSafe\fR) .sp Tcl_Interp * \fBTcl_GetSlave\fR(\fIinterp, slaveName\fR) .sp Tcl_Interp * \fBTcl_GetMaster\fR(\fIinterp\fR) .sp int \fBTcl_GetInterpPath\fR(\fIaskingInterp, slaveInterp\fR) .sp int \fBTcl_CreateAlias\fR(\fIslaveInterp, slaveCmd, targetInterp, targetCmd, argc, argv\fR) .sp int \fBTcl_CreateAliasObj\fR(\fIslaveInterp, slaveCmd, targetInterp, targetCmd, objc, objv\fR) .sp int \fBTcl_GetAlias\fR(\fIinterp, slaveCmd, targetInterpPtr, targetCmdPtr, argcPtr, argvPtr\fR) .sp int \fBTcl_GetAliasObj\fR(\fIinterp, slaveCmd, targetInterpPtr, targetCmdPtr, objcPtr, objvPtr\fR) .sp int \fBTcl_ExposeCommand\fR(\fIinterp, hiddenCmdName, cmdName\fR) .sp int \fBTcl_HideCommand\fR(\fIinterp, cmdName, hiddenCmdName\fR) .SH ARGUMENTS .AS "const char *const" **targetInterpPtr out .AP Tcl_Interp *interp in Interpreter in which to execute the specified command. .AP "const char" *slaveName in Name of slave interpreter to create or manipulate. .AP int isSafe in If non-zero, a .QW safe slave that is suitable for running untrusted code is created, otherwise a trusted slave is created. .AP Tcl_Interp *slaveInterp in Interpreter to use for creating the source command for an alias (see below). .AP "const char" *slaveCmd in Name of source command for alias. .AP Tcl_Interp *targetInterp in Interpreter that contains the target command for an alias. .AP "const char" *targetCmd in Name of target command for alias in \fItargetInterp\fR. .AP int argc in Count of additional arguments to pass to the alias command. .AP "const char *const" *argv in Vector of strings, the additional arguments to pass to the alias command. This storage is owned by the caller. .AP int objc in Count of additional value arguments to pass to the aliased command. .AP Tcl_Obj **objv in Vector of Tcl_Obj structures, the additional value arguments to pass to the aliased command. This storage is owned by the caller. .AP Tcl_Interp **targetInterpPtr in Pointer to location to store the address of the interpreter where a target command is defined for an alias. .AP "const char" **targetCmdPtr out Pointer to location to store the address of the name of the target command for an alias. .AP int *argcPtr out Pointer to location to store count of additional arguments to be passed to the alias. The location is in storage owned by the caller. .AP "const char" ***argvPtr out Pointer to location to store a vector of strings, the additional arguments to pass to an alias. The location is in storage owned by the caller, the vector of strings is owned by the called function. .AP int *objcPtr out Pointer to location to store count of additional value arguments to be passed to the alias. The location is in storage owned by the caller. .AP Tcl_Obj ***objvPtr out Pointer to location to store a vector of Tcl_Obj structures, the additional arguments to pass to an alias command. The location is in storage owned by the caller, the vector of Tcl_Obj structures is owned by the called function. .AP "const char" *cmdName in Name of an exposed command to hide or create. .AP "const char" *hiddenCmdName in Name under which a hidden command is stored and with which it can be exposed or invoked. .BE .SH DESCRIPTION .PP These procedures are intended for access to the multiple interpreter facility from inside C programs. They enable managing multiple interpreters in a hierarchical relationship, and the management of aliases, commands that when invoked in one interpreter execute a command in another interpreter. The return value for those procedures that return an \fBint\fR is either \fBTCL_OK\fR or \fBTCL_ERROR\fR. If \fBTCL_ERROR\fR is returned then the \fBresult\fR field of the interpreter contains an error message. .PP \fBTcl_CreateSlave\fR creates a new interpreter as a slave of \fIinterp\fR. It also creates a slave command named \fIslaveName\fR in \fIinterp\fR which allows \fIinterp\fR to manipulate the new slave. If \fIisSafe\fR is zero, the command creates a trusted slave in which Tcl code has access to all the Tcl commands. If it is \fB1\fR, the command creates a .QW safe slave in which Tcl code has access only to set of Tcl commands defined as .QW "Safe Tcl" ; see the manual entry for the Tcl \fBinterp\fR command for details. If the creation of the new slave interpreter failed, \fBNULL\fR is returned. .PP \fBTcl_IsSafe\fR returns \fB1\fR if \fIinterp\fR is .QW safe (was created with the \fBTCL_SAFE_INTERPRETER\fR flag specified), \fB0\fR otherwise. .PP \fBTcl_MakeSafe\fR marks \fIinterp\fR as .QW safe , so that future calls to \fBTcl_IsSafe\fR will return 1. It also removes all known potentially-unsafe core functionality (both commands and variables) from \fIinterp\fR. However, it cannot know what parts of an extension or application are safe and does not make any attempt to remove those parts, so safety is not guaranteed after calling \fBTcl_MakeSafe\fR. Callers will want to take care with their use of \fBTcl_MakeSafe\fR to avoid false claims of safety. For many situations, \fBTcl_CreateSlave\fR may be a better choice, since it creates interpreters in a known-safe state. .PP \fBTcl_GetSlave\fR returns a pointer to a slave interpreter of \fIinterp\fR. The slave interpreter is identified by \fIslaveName\fR. If no such slave interpreter exists, \fBNULL\fR is returned. .PP \fBTcl_GetMaster\fR returns a pointer to the master interpreter of \fIinterp\fR. If \fIinterp\fR has no master (it is a top-level interpreter) then \fBNULL\fR is returned. .PP \fBTcl_GetInterpPath\fR sets the \fIresult\fR field in \fIaskingInterp\fR to the relative path between \fIaskingInterp\fR and \fIslaveInterp\fR; \fIslaveInterp\fR must be a slave of \fIaskingInterp\fR. If the computation of the relative path succeeds, \fBTCL_OK\fR is returned, else \fBTCL_ERROR\fR is returned and the \fIresult\fR field in \fIaskingInterp\fR contains the error message. .PP \fBTcl_CreateAlias\fR creates a command named \fIslaveCmd\fR in \fIslaveInterp\fR that when invoked, will cause the command \fItargetCmd\fR to be invoked in \fItargetInterp\fR. The arguments specified by the strings contained in \fIargv\fR are always prepended to any arguments supplied in the invocation of \fIslaveCmd\fR and passed to \fItargetCmd\fR. This operation returns \fBTCL_OK\fR if it succeeds, or \fBTCL_ERROR\fR if it fails; in that case, an error message is left in the value result of \fIslaveInterp\fR. Note that there are no restrictions on the ancestry relationship (as created by \fBTcl_CreateSlave\fR) between \fIslaveInterp\fR and \fItargetInterp\fR. Any two interpreters can be used, without any restrictions on how they are related. .PP \fBTcl_CreateAliasObj\fR is similar to \fBTcl_CreateAlias\fR except that it takes a vector of values to pass as additional arguments instead of a vector of strings. .PP \fBTcl_GetAlias\fR returns information about an alias \fIaliasName\fR in \fIinterp\fR. Any of the result fields can be \fBNULL\fR, in which case the corresponding datum is not returned. If a result field is non\-\fBNULL\fR, the address indicated is set to the corresponding datum. For example, if \fItargetNamePtr\fR is non\-\fBNULL\fR it is set to a pointer to the string containing the name of the target command. .PP \fBTcl_GetAliasObj\fR is similar to \fBTcl_GetAlias\fR except that it returns a pointer to a vector of Tcl_Obj structures instead of a vector of strings. .PP \fBTcl_ExposeCommand\fR moves the command named \fIhiddenCmdName\fR from the set of hidden commands to the set of exposed commands, putting it under the name \fIcmdName\fR. \fIHiddenCmdName\fR must be the name of an existing hidden command, or the operation will return \fBTCL_ERROR\fR and leave an error message in the \fIresult\fR field in \fIinterp\fR. If an exposed command named \fIcmdName\fR already exists, the operation returns \fBTCL_ERROR\fR and leaves an error message in the value result of \fIinterp\fR. If the operation succeeds, it returns \fBTCL_OK\fR. After executing this command, attempts to use \fIcmdName\fR in a call to \fBTcl_Eval\fR or with the Tcl \fBeval\fR command will again succeed. .PP \fBTcl_HideCommand\fR moves the command named \fIcmdName\fR from the set of exposed commands to the set of hidden commands, under the name \fIhiddenCmdName\fR. \fICmdName\fR must be the name of an existing exposed command, or the operation will return \fBTCL_ERROR\fR and leave an error message in the value result of \fIinterp\fR. Currently both \fIcmdName\fR and \fIhiddenCmdName\fR must not contain namespace qualifiers, or the operation will return \fBTCL_ERROR\fR and leave an error message in the value result of \fIinterp\fR. The \fICmdName\fR will be looked up in the global namespace, and not relative to the current namespace, even if the current namespace is not the global one. If a hidden command whose name is \fIhiddenCmdName\fR already exists, the operation also returns \fBTCL_ERROR\fR and the \fIresult\fR field in \fIinterp\fR contains an error message. If the operation succeeds, it returns \fBTCL_OK\fR. After executing this command, attempts to use \fIcmdName\fR in a call to \fBTcl_Eval\fR or with the Tcl \fBeval\fR command will fail. .PP For a description of the Tcl interface to multiple interpreters, see \fIinterp(n)\fR. .SH "SEE ALSO" interp .SH KEYWORDS alias, command, exposed commands, hidden commands, interpreter, invoke, master, slave tcl8.6.5/doc/object.n0000644000175000017500000001156012663660065013764 0ustar sergeisergei'\" '\" Copyright (c) 2007-2008 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH object n 0.1 TclOO "TclOO Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME oo::object \- root class of the class hierarchy .SH SYNOPSIS .nf package require TclOO \fBoo::object\fI method \fR?\fIarg ...\fR? .fi .SH "CLASS HIERARCHY" .nf \fBoo::object\fR .fi .BE .SH DESCRIPTION .PP The \fBoo::object\fR class is the root class of the object hierarchy; every object is an instance of this class. Since classes are themselves objects, they are instances of this class too. Objects are always referred to by their name, and may be \fBrename\fRd while maintaining their identity. .PP Instances of objects may be made with either the \fBcreate\fR or \fBnew\fR methods of the \fBoo::object\fR object itself, or by invoking those methods on any of the subclass objects; see \fBoo::class\fR for more details. The configuration of individual objects (i.e., instance-specific methods, mixed-in classes, etc.) may be controlled with the \fBoo::objdefine\fR command. .PP Each object has a unique namespace associated with it, the instance namespace. This namespace holds all the instance variables of the object, and will be the current namespace whenever a method of the object is invoked (including a method of the class of the object). When the object is destroyed, its instance namespace is deleted. The instance namespace contains the object's \fBmy\fR command, which may be used to invoke non-exported methods of the object or to create a reference to the object for the purpose of invocation which persists across renamings of the object. .SS CONSTRUCTOR The \fBoo::object\fR class does not define an explicit constructor. .SS DESTRUCTOR The \fBoo::object\fR class does not define an explicit destructor. .SS "EXPORTED METHODS" The \fBoo::object\fR class supports the following exported methods: .TP \fIobj \fBdestroy\fR . This method destroys the object, \fIobj\fR, that it is invoked upon, invoking any destructors on the object's class in the process. It is equivalent to using \fBrename\fR to delete the object command. The result of this method is always the empty string. .SS "NON-EXPORTED METHODS" .PP The \fBoo::object\fR class supports the following non-exported methods: .TP \fIobj \fBeval\fR ?\fIarg ...\fR? . This method concatenates the arguments, \fIarg\fR, as if with \fBconcat\fR, and then evaluates the resulting script in the namespace that is uniquely associated with \fIobj\fR, returning the result of the evaluation. .TP \fIobj \fBunknown ?\fImethodName\fR? ?\fIarg ...\fR? . This method is called when an attempt to invoke the method \fImethodName\fR on object \fIobj\fR fails. The arguments that the user supplied to the method are given as \fIarg\fR arguments. .VS If \fImethodName\fR is absent, the object was invoked with no method name at all (or any other arguments). .VE The default implementation (i.e., the one defined by the \fBoo::object\fR class) generates a suitable error, detailing what methods the object supports given whether the object was invoked by its public name or through the \fBmy\fR command. .TP \fIobj \fBvariable \fR?\fIvarName ...\fR? . This method arranges for each variable called \fIvarName\fR to be linked from the object \fIobj\fR's unique namespace into the caller's context. Thus, if it is invoked from inside a procedure then the namespace variable in the object is linked to the local variable in the procedure. Each \fIvarName\fR argument must not have any namespace separators in it. The result is the empty string. .TP \fIobj \fBvarname \fIvarName\fR . This method returns the globally qualified name of the variable \fIvarName\fR in the unique namespace for the object \fIobj\fR. .TP \fIobj \fB \fIsourceObjectName\fR .VS This method is used by the \fBoo::object\fR command to copy the state of one object to another. It is responsible for copying the procedures and variables of the namespace of the source object (\fIsourceObjectName\fR) to the current object. It does not copy any other types of commands or any traces on the variables; that can be added if desired by overriding this method in a subclass. .VE .SH EXAMPLES .PP This example demonstrates basic use of an object. .PP .CS set obj [\fBoo::object\fR new] $obj foo \fI\(-> error "unknown method foo"\fR oo::objdefine $obj method foo {} { my \fBvariable\fR count puts "bar[incr count]" } $obj foo \fI\(-> prints "bar1"\fR $obj foo \fI\(-> prints "bar2"\fR $obj variable count \fI\(-> error "unknown method variable"\fR $obj \fBdestroy\fR $obj foo \fI\(-> error "unknown command obj"\fR .CE .SH "SEE ALSO" my(n), oo::class(n) .SH KEYWORDS base class, class, object, root class .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: tcl8.6.5/doc/GetInt.30000644000175000017500000000606412663660065013620 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_GetInt 3 "" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_GetInt, Tcl_GetDouble, Tcl_GetBoolean \- convert from string to integer, double, or boolean .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_GetInt\fR(\fIinterp, src, intPtr\fR) .sp int \fBTcl_GetDouble\fR(\fIinterp, src, doublePtr\fR) .sp int \fBTcl_GetBoolean\fR(\fIinterp, src, boolPtr\fR) .SH ARGUMENTS .AS Tcl_Interp *doublePtr out .AP Tcl_Interp *interp in Interpreter to use for error reporting. .AP "const char" *src in Textual value to be converted. .AP int *intPtr out Points to place to store integer value converted from \fIsrc\fR. .AP double *doublePtr out Points to place to store double-precision floating-point value converted from \fIsrc\fR. .AP int *boolPtr out Points to place to store boolean value (0 or 1) converted from \fIsrc\fR. .BE .SH DESCRIPTION .PP These procedures convert from strings to integers or double-precision floating-point values or booleans (represented as 0- or 1-valued integers). Each of the procedures takes a \fIsrc\fR argument, converts it to an internal form of a particular type, and stores the converted value at the location indicated by the procedure's third argument. If all goes well, each of the procedures returns \fBTCL_OK\fR. If \fIsrc\fR does not have the proper syntax for the desired type then \fBTCL_ERROR\fR is returned, an error message is left in the interpreter's result, and nothing is stored at *\fIintPtr\fR or *\fIdoublePtr\fR or *\fIboolPtr\fR. .PP \fBTcl_GetInt\fR expects \fIsrc\fR to consist of a collection of integer digits, optionally signed and optionally preceded by white space. If the first two characters of \fIsrc\fR after the optional white space and sign are .QW 0x then \fIsrc\fR is expected to be in hexadecimal form; otherwise, if the first such character is .QW 0 then \fIsrc\fR is expected to be in octal form; otherwise, \fIsrc\fR is expected to be in decimal form. .PP \fBTcl_GetDouble\fR expects \fIsrc\fR to consist of a floating-point number, which is: white space; a sign; a sequence of digits; a decimal point; a sequence of digits; the letter .QW e ; a signed decimal exponent; and more white space. Any of the fields may be omitted, except that the digits either before or after the decimal point must be present and if the .QW e is present then it must be followed by the exponent number. .PP \fBTcl_GetBoolean\fR expects \fIsrc\fR to specify a boolean value. If \fIsrc\fR is any of \fB0\fR, \fBfalse\fR, \fBno\fR, or \fBoff\fR, then \fBTcl_GetBoolean\fR stores a zero value at \fI*boolPtr\fR. If \fIsrc\fR is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\fR, then 1 is stored at \fI*boolPtr\fR. Any of these values may be abbreviated, and upper-case spellings are also acceptable. .SH KEYWORDS boolean, conversion, double, floating-point, integer tcl8.6.5/doc/bgerror.n0000644000175000017500000000774612663660065014173 0ustar sergeisergei'\" '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-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 bgerror n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME bgerror \- Command invoked to process background errors .SH SYNOPSIS \fBbgerror \fImessage\fR .BE .SH DESCRIPTION .PP Release 8.5 of Tcl supports the \fBinterp bgerror\fR command, which allows applications to register in an interpreter the command that will handle background errors in that interpreter. In older releases of Tcl, this level of control was not available, and applications could control the handling of background errors only by creating a command with the particular command name \fBbgerror\fR in the global namespace of an interpreter. The following documentation describes the interface requirements of the \fBbgerror\fR command an application might define to retain compatibility with pre-8.5 releases of Tcl. Applications intending to support only Tcl releases 8.5 and later should simply make use of \fBinterp bgerror\fR. .PP The \fBbgerror\fR command does not exist as built-in part of Tcl. Instead, individual applications or users can define a \fBbgerror\fR command (e.g. as a Tcl procedure) if they wish to handle background errors. .PP A background error is one that occurs in an event handler or some other command that did not originate with the application. For example, if an error occurs while executing a command specified with the \fBafter\fR command, then it is a background error. For a non-background error, the error can simply be returned up through nested Tcl command evaluations until it reaches the top-level code in the application; then the application can report the error in whatever way it wishes. When a background error occurs, the unwinding ends in the Tcl library and there is no obvious way for Tcl to report the error. .PP When Tcl detects a background error, it saves information about the error and invokes a handler command registered by \fBinterp bgerror\fR later as an idle event handler. The default handler command in turn calls the \fBbgerror\fR command . Before invoking \fBbgerror\fR, Tcl restores the \fBerrorInfo\fR and \fBerrorCode\fR variables to their values at the time the error occurred, then it invokes \fBbgerror\fR with the error message as its only argument. Tcl assumes that the application has implemented the \fBbgerror\fR command, and that the command will report the error in a way that makes sense for the application. Tcl will ignore any result returned by the \fBbgerror\fR command as long as no error is generated. .PP If another Tcl error occurs within the \fBbgerror\fR command (for example, because no \fBbgerror\fR command has been defined) then Tcl reports the error itself by writing a message to stderr. .PP If several background errors accumulate before \fBbgerror\fR is invoked to process them, \fBbgerror\fR will be invoked once for each error, in the order they occurred. However, if \fBbgerror\fR returns with a break exception, then any remaining errors are skipped without calling \fBbgerror\fR. .PP If you are writing code that will be used by others as part of a package or other kind of library, consider avoiding \fBbgerror\fR. The reason for this is that the application programmer may also want to define a \fBbgerror\fR, or use other code that does and thus will have trouble integrating your code. .SH "EXAMPLE" .PP This \fBbgerror\fR procedure appends errors to a file, with a timestamp. .PP .CS proc bgerror {message} { set timestamp [clock format [clock seconds]] set fl [open mylog.txt {WRONLY CREAT APPEND}] puts $fl "$timestamp: bgerror in $::argv '$message'" close $fl } .CE .SH "SEE ALSO" after(n), errorCode(n), errorInfo(n), interp(n) .SH KEYWORDS background error, reporting '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/Limit.30000644000175000017500000001726212663660065013506 0ustar sergeisergei'\" '\" Copyright (c) 2004 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_LimitCheck 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_LimitAddHandler, Tcl_LimitCheck, Tcl_LimitExceeded, Tcl_LimitGetCommands, Tcl_LimitGetGranularity, Tcl_LimitGetTime, Tcl_LimitReady, Tcl_LimitRemoveHandler, Tcl_LimitSetCommands, Tcl_LimitSetGranularity, Tcl_LimitSetTime, Tcl_LimitTypeEnabled, Tcl_LimitTypeExceeded, Tcl_LimitTypeReset, Tcl_LimitTypeSet \- manage and check resource limits on interpreters .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_LimitCheck\fR(\fIinterp\fR) .sp int \fBTcl_LimitReady\fR(\fIinterp\fR) .sp int \fBTcl_LimitExceeded\fR(\fIinterp\fR) .sp int \fBTcl_LimitTypeExceeded\fR(\fIinterp, type\fR) .sp int \fBTcl_LimitTypeEnabled\fR(\fIinterp, type\fR) .sp void \fBTcl_LimitTypeSet\fR(\fIinterp, type\fR) .sp void \fBTcl_LimitTypeReset\fR(\fIinterp, type\fR) .sp int \fBTcl_LimitGetCommands\fR(\fIinterp\fR) .sp void \fBTcl_LimitSetCommands\fR(\fIinterp, commandLimit\fR) .sp void \fBTcl_LimitGetTime\fR(\fIinterp, timeLimitPtr\fR) .sp void \fBTcl_LimitSetTime\fR(\fIinterp, timeLimitPtr\fR) .sp int \fBTcl_LimitGetGranularity\fR(\fIinterp, type\fR) .sp void \fBTcl_LimitSetGranularity\fR(\fIinterp, type, granularity\fR) .sp void \fBTcl_LimitAddHandler\fR(\fIinterp, type, handlerProc, clientData, deleteProc\fR) .sp void \fBTcl_LimitRemoveHandler\fR(\fIinterp, type, handlerProc, clientData\fR) .SH ARGUMENTS .AS Tcl_LimitHandlerDeleteProc commandLimit in/out .AP Tcl_Interp *interp in Interpreter that the limit being managed applies to or that will have its limits checked. .AP int type in The type of limit that the operation refers to. This must be either \fBTCL_LIMIT_COMMANDS\fR or \fBTCL_LIMIT_TIME\fR. .AP int commandLimit in The maximum number of commands (as reported by \fBinfo cmdcount\fR) that may be executed in the interpreter. .AP Tcl_Time *timeLimitPtr in/out A pointer to a structure that will either have the new time limit read from (\fBTcl_LimitSetTime\fR) or the current time limit written to (\fBTcl_LimitGetTime\fR). .AP int granularity in Divisor that indicates how often a particular limit should really be checked. Must be at least 1. .AP Tcl_LimitHandlerProc *handlerProc in Function to call when a particular limit is exceeded. If the \fIhandlerProc\fR removes or raises the limit during its processing, the limited interpreter will be permitted to continue to process after the handler returns. Many handlers may be attached to the same interpreter limit; their order of execution is not defined, and they must be identified by \fIhandlerProc\fR and \fIclientData\fR when they are deleted. .AP ClientData clientData in Arbitrary pointer-sized word used to pass some context to the \fIhandlerProc\fR function. .AP Tcl_LimitHandlerDeleteProc *deleteProc in Function to call whenever a handler is deleted. May be NULL if the \fIclientData\fR requires no deletion. .BE .SH DESCRIPTION .PP Tcl's interpreter resource limit subsystem allows for close control over how much computation time a script may use, and is useful for cases where a program is divided into multiple pieces where some parts are more trusted than others (e.g. web application servers). .PP Every interpreter may have a limit on the wall-time for execution, and a limit on the number of commands that the interpreter may execute. Since checking of these limits is potentially expensive (especially the time limit), each limit also has a checking granularity, which is a divisor for an internal count of the number of points in the core where a check may be performed (which is immediately before executing a command and at an unspecified frequency between running commands, which can happen in empty-bodied \fBwhile\fR loops). .PP The final component of the limit engine is a callback scheme which allows for notifications of when a limit has been exceeded. These callbacks can just provide logging, or may allocate more resources to the interpreter to permit it to continue processing longer. .PP When a limit is exceeded (and the callbacks have run; the order of execution of the callbacks is unspecified) execution in the limited interpreter is stopped by raising an error and setting a flag that prevents the \fBcatch\fR command in that interpreter from trapping that error. It is up to the context that started execution in that interpreter (typically a master interpreter) to handle the error. .SH "LIMIT CHECKING API" .PP To check the resource limits for an interpreter, call \fBTcl_LimitCheck\fR, which returns \fBTCL_OK\fR if the limit was not exceeded (after processing callbacks) and \fBTCL_ERROR\fR if the limit was exceeded (in which case an error message is also placed in the interpreter result). That function should only be called when \fBTcl_LimitReady\fR returns non-zero so that granularity policy is enforced. This API is designed to be similar in usage to \fBTcl_AsyncReady\fR and \fBTcl_AsyncInvoke\fR. .PP When writing code that may behave like \fBcatch\fR in respect of errors, you should only trap an error if \fBTcl_LimitExceeded\fR returns zero. If it returns non-zero, the interpreter is in a limit-exceeded state and errors should be allowed to propagate to the calling context. You can also check whether a particular type of limit has been exceeded using \fBTcl_LimitTypeExceeded\fR. .SH "LIMIT CONFIGURATION" .PP To check whether a limit has been set (but not whether it has actually been exceeded) on an interpreter, call \fBTcl_LimitTypeEnabled\fR with the type of limit you want to check. To enable a particular limit call \fBTcl_LimitTypeSet\fR, and to disable a limit call \fBTcl_LimitTypeReset\fR. .PP The level of a command limit may be set using \fBTcl_LimitSetCommands\fR, and retrieved using \fBTcl_LimitGetCommands\fR. Similarly for a time limit with \fBTcl_LimitSetTime\fR and \fBTcl_LimitGetTime\fR respectively, but with that API the time limit is copied from and to the Tcl_Time structure that the \fItimeLimitPtr\fR argument points to. .PP The checking granularity for a particular limit may be set using \fBTcl_LimitSetGranularity\fR and retrieved using \fBTcl_LimitGetGranularity\fR. Note that granularities must always be positive. .SS "LIMIT CALLBACKS" .PP To add a handler callback to be invoked when a limit is exceeded, call \fBTcl_LimitAddHandler\fR. The \fIhandlerProc\fR argument describes the function that will actually be called; it should have the following prototype: .PP .CS typedef void \fBTcl_LimitHandlerProc\fR( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR); .CE .PP The \fIclientData\fR argument to the handler will be whatever is passed to the \fIclientData\fR argument to \fBTcl_LimitAddHandler\fR, and the \fIinterp\fR is the interpreter that had its limit exceeded. .PP The \fIdeleteProc\fR argument to \fBTcl_LimitAddHandler\fR is a function to call to delete the \fIclientData\fR value. It may be \fBTCL_STATIC\fR or NULL if no deletion action is necessary, or \fBTCL_DYNAMIC\fR if all that is necessary is to free the structure with \fBTcl_Free\fR. Otherwise, it should refer to a function with the following prototype: .PP .CS typedef void \fBTcl_LimitHandlerDeleteProc\fR( ClientData \fIclientData\fR); .CE .PP A limit handler may be deleted using \fBTcl_LimitRemoveHandler\fR; the handler removed will be the first one found (out of the handlers added with \fBTcl_LimitAddHandler\fR) with exactly matching \fItype\fR, \fIhandlerProc\fR and \fIclientData\fR arguments. This function always invokes the \fIdeleteProc\fR on the \fIclientData\fR (unless the \fIdeleteProc\fR was NULL or \fBTCL_STATIC\fR). .SH KEYWORDS interpreter, resource, limit, commands, time, callback tcl8.6.5/doc/GetVersion.30000644000175000017500000000314012663660065014503 0ustar sergeisergei'\" '\" Copyright (c) 1999 Scriptics Corporation '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_GetVersion 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_GetVersion \- get the version of the library at runtime .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_GetVersion\fR(\fImajor, minor, patchLevel, type\fR) .SH ARGUMENTS .AS Tcl_ReleaseType *patchLevel out .AP int *major out Major version number of the Tcl library. .AP int *minor out Minor version number of the Tcl library. .AP int *patchLevel out The patch level of the Tcl library (or alpha or beta number). .AP Tcl_ReleaseType *type out The type of release, also indicates the type of patch level. Can be one of \fBTCL_ALPHA_RELEASE\fR, \fBTCL_BETA_RELEASE\fR, or \fBTCL_FINAL_RELEASE\fR. .BE .SH DESCRIPTION .PP \fBTcl_GetVersion\fR should be used to query the version number of the Tcl library at runtime. This is useful when using a dynamically loaded Tcl library or when writing a stubs-aware extension. For instance, if you write an extension that is linked against the Tcl stubs library, it could be loaded into a program linked to an older version of Tcl than you expected. Use \fBTcl_GetVersion\fR to verify that fact, and possibly to change the behavior of your extension. .PP \fBTcl_GetVersion\fR accepts NULL for any of the arguments. For instance if you do not care about the \fIpatchLevel\fR of the library, pass a NULL for the \fIpatchLevel\fR argument. .SH KEYWORDS version, patchlevel, major, minor, alpha, beta, release tcl8.6.5/doc/re_syntax.n0000644000175000017500000006632612663660065014544 0ustar sergeisergei'\" '\" Copyright (c) 1998 Sun Microsystems, Inc. '\" Copyright (c) 1999 Scriptics Corporation '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .so man.macros .ie '\w'o''\w'\C'^o''' .ds qo \C'^o' .el .ds qo u .TH re_syntax n "8.1" Tcl "Tcl Built-In Commands" .BS .SH NAME re_syntax \- Syntax of Tcl regular expressions .BE .SH DESCRIPTION .PP A \fIregular expression\fR describes strings of characters. It's a pattern that matches certain strings and does not match others. .SH "DIFFERENT FLAVORS OF REs" Regular expressions .PQ RE s , as defined by POSIX, come in two flavors: \fIextended\fR REs .PQ ERE s and \fIbasic\fR REs .PQ BRE s . EREs are roughly those of the traditional \fIegrep\fR, while BREs are roughly those of the traditional \fIed\fR. This implementation adds a third flavor, \fIadvanced\fR REs .PQ ARE s , basically EREs with some significant extensions. .PP This manual page primarily describes AREs. BREs mostly exist for backward compatibility in some old programs; they will be discussed at the end. POSIX EREs are almost an exact subset of AREs. Features of AREs that are not present in EREs will be indicated. .SH "REGULAR EXPRESSION SYNTAX" .PP Tcl regular expressions are implemented using the package written by Henry Spencer, based on the 1003.2 spec and some (not quite all) of the Perl5 extensions (thanks, Henry!). Much of the description of regular expressions below is copied verbatim from his manual entry. .PP An ARE is one or more \fIbranches\fR, separated by .QW \fB|\fR , matching anything that matches any of the branches. .PP A branch is zero or more \fIconstraints\fR or \fIquantified atoms\fR, concatenated. It matches a match for the first, followed by a match for the second, etc; an empty branch matches the empty string. .SS QUANTIFIERS A quantified atom is an \fIatom\fR possibly followed by a single \fIquantifier\fR. Without a quantifier, it matches a single match for the atom. The quantifiers, and what a so-quantified atom matches, are: .RS 2 .TP 6 \fB*\fR . a sequence of 0 or more matches of the atom .TP \fB+\fR . a sequence of 1 or more matches of the atom .TP \fB?\fR . a sequence of 0 or 1 matches of the atom .TP \fB{\fIm\fB}\fR . a sequence of exactly \fIm\fR matches of the atom .TP \fB{\fIm\fB,}\fR . a sequence of \fIm\fR or more matches of the atom .TP \fB{\fIm\fB,\fIn\fB}\fR . a sequence of \fIm\fR through \fIn\fR (inclusive) matches of the atom; \fIm\fR may not exceed \fIn\fR .TP \fB*? +? ?? {\fIm\fB}? {\fIm\fB,}? {\fIm\fB,\fIn\fB}?\fR . \fInon-greedy\fR quantifiers, which match the same possibilities, but prefer the smallest number rather than the largest number of matches (see \fBMATCHING\fR) .RE .PP The forms using \fB{\fR and \fB}\fR are known as \fIbound\fRs. The numbers \fIm\fR and \fIn\fR are unsigned decimal integers with permissible values from 0 to 255 inclusive. .SS ATOMS An atom is one of: .RS 2 .IP \fB(\fIre\fB)\fR 6 matches a match for \fIre\fR (\fIre\fR is any regular expression) with the match noted for possible reporting .IP \fB(?:\fIre\fB)\fR as previous, but does no reporting (a .QW non-capturing set of parentheses) .IP \fB()\fR matches an empty string, noted for possible reporting .IP \fB(?:)\fR matches an empty string, without reporting .IP \fB[\fIchars\fB]\fR a \fIbracket expression\fR, matching any one of the \fIchars\fR (see \fBBRACKET EXPRESSIONS\fR for more detail) .IP \fB.\fR matches any single character .IP \fB\e\fIk\fR matches the non-alphanumeric character \fIk\fR taken as an ordinary character, e.g. \fB\e\e\fR matches a backslash character .IP \fB\e\fIc\fR where \fIc\fR is alphanumeric (possibly followed by other characters), an \fIescape\fR (AREs only), see \fBESCAPES\fR below .IP \fB{\fR when followed by a character other than a digit, matches the left-brace character .QW \fB{\fR ; when followed by a digit, it is the beginning of a \fIbound\fR (see above) .IP \fIx\fR where \fIx\fR is a single character with no other significance, matches that character. .RE .SS CONSTRAINTS A \fIconstraint\fR matches an empty string when specific conditions are met. A constraint may not be followed by a quantifier. The simple constraints are as follows; some more constraints are described later, under \fBESCAPES\fR. .RS 2 .TP 8 \fB^\fR . matches at the beginning of a line .TP \fB$\fR . matches at the end of a line .TP \fB(?=\fIre\fB)\fR . \fIpositive lookahead\fR (AREs only), matches at any point where a substring matching \fIre\fR begins .TP \fB(?!\fIre\fB)\fR . \fInegative lookahead\fR (AREs only), matches at any point where no substring matching \fIre\fR begins .RE .PP The lookahead constraints may not contain back references (see later), and all parentheses within them are considered non-capturing. .PP An RE may not end with .QW \fB\e\fR . .SH "BRACKET EXPRESSIONS" A \fIbracket expression\fR is a list of characters enclosed in .QW \fB[\|]\fR . It normally matches any single character from the list (but see below). If the list begins with .QW \fB^\fR , it matches any single character (but see below) \fInot\fR from the rest of the list. .PP If two characters in the list are separated by .QW \fB\-\fR , this is shorthand for the full \fIrange\fR of characters between those two (inclusive) in the collating sequence, e.g. .QW \fB[0\-9]\fR in Unicode matches any conventional decimal digit. Two ranges may not share an endpoint, so e.g. .QW \fBa\-c\-e\fR is illegal. Ranges in Tcl always use the Unicode collating sequence, but other programs may use other collating sequences and this can be a source of incompatibility between programs. .PP To include a literal \fB]\fR or \fB\-\fR in the list, the simplest method is to enclose it in \fB[.\fR and \fB.]\fR to make it a collating element (see below). Alternatively, make it the first character (following a possible .QW \fB^\fR ), or (AREs only) precede it with .QW \fB\e\fR . Alternatively, for .QW \fB\-\fR , make it the last character, or the second endpoint of a range. To use a literal \fB\-\fR as the first endpoint of a range, make it a collating element or (AREs only) precede it with .QW \fB\e\fR . With the exception of these, some combinations using \fB[\fR (see next paragraphs), and escapes, all other special characters lose their special significance within a bracket expression. .SS "CHARACTER CLASSES" Within a bracket expression, the name of a \fIcharacter class\fR enclosed in \fB[:\fR and \fB:]\fR stands for the list of all characters (not all collating elements!) belonging to that class. Standard character classes are: .IP \fBalpha\fR 8 A letter. .IP \fBupper\fR 8 An upper-case letter. .IP \fBlower\fR 8 A lower-case letter. .IP \fBdigit\fR 8 A decimal digit. .IP \fBxdigit\fR 8 A hexadecimal digit. .IP \fBalnum\fR 8 An alphanumeric (letter or digit). .IP \fBprint\fR 8 A "printable" (same as graph, except also including space). .IP \fBblank\fR 8 A space or tab character. .IP \fBspace\fR 8 A character producing white space in displayed text. .IP \fBpunct\fR 8 A punctuation character. .IP \fBgraph\fR 8 A character with a visible representation (includes both \fBalnum\fR and \fBpunct\fR). .IP \fBcntrl\fR 8 A control character. .PP A locale may provide others. A character class may not be used as an endpoint of a range. .RS .PP (\fINote:\fR the current Tcl implementation has only one locale, the Unicode locale, which supports exactly the above classes.) .RE .SS "BRACKETED CONSTRAINTS" There are two special cases of bracket expressions: the bracket expressions .QW \fB[[:<:]]\fR and .QW \fB[[:>:]]\fR are constraints, matching empty strings at the beginning and end of a word respectively. .\" note, discussion of escapes below references this definition of word A word is defined as a sequence of word characters that is neither preceded nor followed by word characters. A word character is an \fIalnum\fR character or an underscore .PQ \fB_\fR "" . These special bracket expressions are deprecated; users of AREs should use constraint escapes instead (see below). .SS "COLLATING ELEMENTS" Within a bracket expression, a collating element (a character, a multi-character sequence that collates as if it were a single character, or a collating-sequence name for either) enclosed in \fB[.\fR and \fB.]\fR stands for the sequence of characters of that collating element. The sequence is a single element of the bracket expression's list. A bracket expression in a locale that has multi-character collating elements can thus match more than one character. So (insidiously), a bracket expression that starts with \fB^\fR can match multi-character collating elements even if none of them appear in the bracket expression! .RS .PP (\fINote:\fR Tcl has no multi-character collating elements. This information is only for illustration.) .RE .PP For example, assume the collating sequence includes a \fBch\fR multi-character collating element. Then the RE .QW \fB[[.ch.]]*c\fR (zero or more .QW \fBch\fRs followed by .QW \fBc\fR ) matches the first five characters of .QW \fBchchcc\fR . Also, the RE .QW \fB[^c]b\fR matches all of .QW \fBchb\fR (because .QW \fB[^c]\fR matches the multi-character .QW \fBch\fR ). .SS "EQUIVALENCE CLASSES" Within a bracket expression, a collating element enclosed in \fB[=\fR and \fB=]\fR is an equivalence class, standing for the sequences of characters of all collating elements equivalent to that one, including itself. (If there are no other equivalent collating elements, the treatment is as if the enclosing delimiters were .QW \fB[.\fR \& and .QW \fB.]\fR .) For example, if \fBo\fR and \fB\*(qo\fR are the members of an equivalence class, then .QW \fB[[=o=]]\fR , .QW \fB[[=\*(qo=]]\fR , and .QW \fB[o\*(qo]\fR \& are all synonymous. An equivalence class may not be an endpoint of a range. .RS .PP (\fINote:\fR Tcl implements only the Unicode locale. It does not define any equivalence classes. The examples above are just illustrations.) .RE .SH ESCAPES Escapes (AREs only), which begin with a \fB\e\fR followed by an alphanumeric character, come in several varieties: character entry, class shorthands, constraint escapes, and back references. A \fB\e\fR followed by an alphanumeric character but not constituting a valid escape is illegal in AREs. In EREs, there are no escapes: outside a bracket expression, a \fB\e\fR followed by an alphanumeric character merely stands for that character as an ordinary character, and inside a bracket expression, \fB\e\fR is an ordinary character. (The latter is the one actual incompatibility between EREs and AREs.) .SS "CHARACTER-ENTRY ESCAPES" Character-entry escapes (AREs only) exist to make it easier to specify non-printing and otherwise inconvenient characters in REs: .RS 2 .TP 5 \fB\ea\fR . alert (bell) character, as in C .TP \fB\eb\fR . backspace, as in C .TP \fB\eB\fR . synonym for \fB\e\fR to help reduce backslash doubling in some applications where there are multiple levels of backslash processing .TP \fB\ec\fIX\fR . (where \fIX\fR is any character) the character whose low-order 5 bits are the same as those of \fIX\fR, and whose other bits are all zero .TP \fB\ee\fR . the character whose collating-sequence name is .QW \fBESC\fR , or failing that, the character with octal value 033 .TP \fB\ef\fR . formfeed, as in C .TP \fB\en\fR . newline, as in C .TP \fB\er\fR . carriage return, as in C .TP \fB\et\fR . horizontal tab, as in C .TP \fB\eu\fIwxyz\fR . (where \fIwxyz\fR is one up to four hexadecimal digits) the Unicode character \fBU+\fIwxyz\fR in the local byte ordering .TP \fB\eU\fIstuvwxyz\fR . (where \fIstuvwxyz\fR is one up to eight hexadecimal digits) reserved for a Unicode extension up to 21 bits. The digits are parsed until the first non-hexadecimal character is encountered, the maximun of eight hexadecimal digits are reached, or an overflow would occur in the maximum value of \fBU+\fI10ffff\fR. .TP \fB\ev\fR . vertical tab, as in C are all available. .TP \fB\ex\fIhh\fR . (where \fIhh\fR is one or two hexadecimal digits) the character whose hexadecimal value is \fB0x\fIhh\fR. .TP \fB\e0\fR . the character whose value is \fB0\fR .TP \fB\e\fIxyz\fR . (where \fIxyz\fR is exactly three octal digits, and is not a \fIback reference\fR (see below)) the character whose octal value is \fB0\fIxyz\fR. The first digit must be in the range 0-3, otherwise the two-digit form is assumed. .TP \fB\e\fIxy\fR . (where \fIxy\fR is exactly two octal digits, and is not a \fIback reference\fR (see below)) the character whose octal value is \fB0\fIxy\fR .RE .PP Hexadecimal digits are .QR \fB0\fR \fB9\fR , .QR \fBa\fR \fBf\fR , and .QR \fBA\fR \fBF\fR . Octal digits are .QR \fB0\fR \fB7\fR . .PP The character-entry escapes are always taken as ordinary characters. For example, \fB\e135\fR is \fB]\fR in Unicode, but \fB\e135\fR does not terminate a bracket expression. Beware, however, that some applications (e.g., C compilers and the Tcl interpreter if the regular expression is not quoted with braces) interpret such sequences themselves before the regular-expression package gets to see them, which may require doubling (quadrupling, etc.) the .QW \fB\e\fR . .SS "CLASS-SHORTHAND ESCAPES" Class-shorthand escapes (AREs only) provide shorthands for certain commonly-used character classes: .RS 2 .TP 10 \fB\ed\fR . \fB[[:digit:]]\fR .TP \fB\es\fR . \fB[[:space:]]\fR .TP \fB\ew\fR . \fB[[:alnum:]_]\fR (note underscore) .TP \fB\eD\fR . \fB[^[:digit:]]\fR .TP \fB\eS\fR . \fB[^[:space:]]\fR .TP \fB\eW\fR . \fB[^[:alnum:]_]\fR (note underscore) .RE .PP Within bracket expressions, .QW \fB\ed\fR , .QW \fB\es\fR , and .QW \fB\ew\fR \& lose their outer brackets, and .QW \fB\eD\fR , .QW \fB\eS\fR , and .QW \fB\eW\fR \& are illegal. (So, for example, .QW \fB[a-c\ed]\fR is equivalent to .QW \fB[a-c[:digit:]]\fR . Also, .QW \fB[a-c\eD]\fR , which is equivalent to .QW \fB[a-c^[:digit:]]\fR , is illegal.) .SS "CONSTRAINT ESCAPES" A constraint escape (AREs only) is a constraint, matching the empty string if specific conditions are met, written as an escape: .RS 2 .TP 6 \fB\eA\fR . matches only at the beginning of the string (see \fBMATCHING\fR, below, for how this differs from .QW \fB^\fR ) .TP \fB\em\fR . matches only at the beginning of a word .TP \fB\eM\fR . matches only at the end of a word .TP \fB\ey\fR . matches only at the beginning or end of a word .TP \fB\eY\fR . matches only at a point that is not the beginning or end of a word .TP \fB\eZ\fR . matches only at the end of the string (see \fBMATCHING\fR, below, for how this differs from .QW \fB$\fR ) .TP \fB\e\fIm\fR . (where \fIm\fR is a nonzero digit) a \fIback reference\fR, see below .TP \fB\e\fImnn\fR . (where \fIm\fR is a nonzero digit, and \fInn\fR is some more digits, and the decimal value \fImnn\fR is not greater than the number of closing capturing parentheses seen so far) a \fIback reference\fR, see below .RE .PP A word is defined as in the specification of .QW \fB[[:<:]]\fR and .QW \fB[[:>:]]\fR above. Constraint escapes are illegal within bracket expressions. .SS "BACK REFERENCES" A back reference (AREs only) matches the same string matched by the parenthesized subexpression specified by the number, so that (e.g.) .QW \fB([bc])\e1\fR matches .QW \fBbb\fR or .QW \fBcc\fR but not .QW \fBbc\fR . The subexpression must entirely precede the back reference in the RE. Subexpressions are numbered in the order of their leading parentheses. Non-capturing parentheses do not define subexpressions. .PP There is an inherent historical ambiguity between octal character-entry escapes and back references, which is resolved by heuristics, as hinted at above. A leading zero always indicates an octal escape. A single non-zero digit, not followed by another digit, is always taken as a back reference. A multi-digit sequence not starting with a zero is taken as a back reference if it comes after a suitable subexpression (i.e. the number is in the legal range for a back reference), and otherwise is taken as octal. .SH "METASYNTAX" In addition to the main syntax described above, there are some special forms and miscellaneous syntactic facilities available. .PP Normally the flavor of RE being used is specified by application-dependent means. However, this can be overridden by a \fIdirector\fR. If an RE of any flavor begins with .QW \fB***:\fR , the rest of the RE is an ARE. If an RE of any flavor begins with .QW \fB***=\fR , the rest of the RE is taken to be a literal string, with all characters considered ordinary characters. .PP An ARE may begin with \fIembedded options\fR: a sequence \fB(?\fIxyz\fB)\fR (where \fIxyz\fR is one or more alphabetic characters) specifies options affecting the rest of the RE. These supplement, and can override, any options specified by the application. The available option letters are: .RS 2 .TP 3 \fBb\fR . rest of RE is a BRE .TP 3 \fBc\fR . case-sensitive matching (usual default) .TP 3 \fBe\fR . rest of RE is an ERE .TP 3 \fBi\fR . case-insensitive matching (see \fBMATCHING\fR, below) .TP 3 \fBm\fR . historical synonym for \fBn\fR .TP 3 \fBn\fR . newline-sensitive matching (see \fBMATCHING\fR, below) .TP 3 \fBp\fR . partial newline-sensitive matching (see \fBMATCHING\fR, below) .TP 3 \fBq\fR . rest of RE is a literal .PQ quoted string, all ordinary characters .TP 3 \fBs\fR . non-newline-sensitive matching (usual default) .TP 3 \fBt\fR . tight syntax (usual default; see below) .TP 3 \fBw\fR . inverse partial newline-sensitive .PQ weird matching (see \fBMATCHING\fR, below) .TP 3 \fBx\fR . expanded syntax (see below) .RE .PP Embedded options take effect at the \fB)\fR terminating the sequence. They are available only at the start of an ARE, and may not be used later within it. .PP In addition to the usual (\fItight\fR) RE syntax, in which all characters are significant, there is an \fIexpanded\fR syntax, available in all flavors of RE with the \fB\-expanded\fR switch, or in AREs with the embedded x option. In the expanded syntax, white-space characters are ignored and all characters between a \fB#\fR and the following newline (or the end of the RE) are ignored, permitting paragraphing and commenting a complex RE. There are three exceptions to that basic rule: .IP \(bu 3 a white-space character or .QW \fB#\fR preceded by .QW \fB\e\fR is retained .IP \(bu 3 white space or .QW \fB#\fR within a bracket expression is retained .IP \(bu 3 white space and comments are illegal within multi-character symbols like the ARE .QW \fB(?:\fR or the BRE .QW \fB\e(\fR .PP Expanded-syntax white-space characters are blank, tab, newline, and any character that belongs to the \fIspace\fR character class. .PP Finally, in an ARE, outside bracket expressions, the sequence .QW \fB(?#\fIttt\fB)\fR (where \fIttt\fR is any text not containing a .QW \fB)\fR ) is a comment, completely ignored. Again, this is not allowed between the characters of multi-character symbols like .QW \fB(?:\fR . Such comments are more a historical artifact than a useful facility, and their use is deprecated; use the expanded syntax instead. .PP \fINone\fR of these metasyntax extensions is available if the application (or an initial .QW \fB***=\fR director) has specified that the user's input be treated as a literal string rather than as an RE. .SH MATCHING In the event that an RE could match more than one substring of a given string, the RE matches the one starting earliest in the string. If the RE could match more than one substring starting at that point, its choice is determined by its \fIpreference\fR: either the longest substring, or the shortest. .PP Most atoms, and all constraints, have no preference. A parenthesized RE has the same preference (possibly none) as the RE. A quantified atom with quantifier \fB{\fIm\fB}\fR or \fB{\fIm\fB}?\fR has the same preference (possibly none) as the atom itself. A quantified atom with other normal quantifiers (including \fB{\fIm\fB,\fIn\fB}\fR with \fIm\fR equal to \fIn\fR) prefers longest match. A quantified atom with other non-greedy quantifiers (including \fB{\fIm\fB,\fIn\fB}?\fR with \fIm\fR equal to \fIn\fR) prefers shortest match. A branch has the same preference as the first quantified atom in it which has a preference. An RE consisting of two or more branches connected by the \fB|\fR operator prefers longest match. .PP Subject to the constraints imposed by the rules for matching the whole RE, subexpressions also match the longest or shortest possible substrings, based on their preferences, with subexpressions starting earlier in the RE taking priority over ones starting later. Note that outer subexpressions thus take priority over their component subexpressions. .PP The quantifiers \fB{1,1}\fR and \fB{1,1}?\fR can be used to force longest and shortest preference, respectively, on a subexpression or a whole RE. .RS .PP \fBNOTE:\fR This means that you can usually make a RE be non-greedy overall by putting \fB{1,1}?\fR after one of the first non-constraint atoms or parenthesized sub-expressions in it. \fIIt pays to experiment\fR with the placing of this non-greediness override on a suitable range of input texts when you are writing a RE if you are using this level of complexity. .PP For example, this regular expression is non-greedy, and will match the shortest substring possible given that .QW \fBabc\fR will be matched as early as possible (the quantifier does not change that): .PP .CS ab{1,1}?c.*x.*cba .CE .PP The atom .QW \fBa\fR has no greediness preference, we explicitly give one for .QW \fBb\fR , and the remaining quantifiers are overridden to be non-greedy by the preceding non-greedy quantifier. .RE .PP Match lengths are measured in characters, not collating elements. An empty string is considered longer than no match at all. For example, .QW \fBbb*\fR matches the three middle characters of .QW \fBabbbc\fR , .QW \fB(week|wee)(night|knights)\fR matches all ten characters of .QW \fBweeknights\fR , when .QW \fB(.*).*\fR is matched against .QW \fBabc\fR the parenthesized subexpression matches all three characters, and when .QW \fB(a*)*\fR is matched against .QW \fBbc\fR both the whole RE and the parenthesized subexpression match an empty string. .PP If case-independent matching is specified, the effect is much as if all case distinctions had vanished from the alphabet. When an alphabetic that exists in multiple cases appears as an ordinary character outside a bracket expression, it is effectively transformed into a bracket expression containing both cases, so that \fBx\fR becomes .QW \fB[xX]\fR . When it appears inside a bracket expression, all case counterparts of it are added to the bracket expression, so that .QW \fB[x]\fR becomes .QW \fB[xX]\fR and .QW \fB[^x]\fR becomes .QW \fB[^xX]\fR . .PP If newline-sensitive matching is specified, \fB.\fR and bracket expressions using \fB^\fR will never match the newline character (so that matches will never cross newlines unless the RE explicitly arranges it) and \fB^\fR and \fB$\fR will match the empty string after and before a newline respectively, in addition to matching at beginning and end of string respectively. ARE \fB\eA\fR and \fB\eZ\fR continue to match beginning or end of string \fIonly\fR. .PP If partial newline-sensitive matching is specified, this affects \fB.\fR and bracket expressions as with newline-sensitive matching, but not \fB^\fR and \fB$\fR. .PP If inverse partial newline-sensitive matching is specified, this affects \fB^\fR and \fB$\fR as with newline-sensitive matching, but not \fB.\fR and bracket expressions. This is not very useful but is provided for symmetry. .SH "LIMITS AND COMPATIBILITY" No particular limit is imposed on the length of REs. Programs intended to be highly portable should not employ REs longer than 256 bytes, as a POSIX-compliant implementation can refuse to accept such REs. .PP The only feature of AREs that is actually incompatible with POSIX EREs is that \fB\e\fR does not lose its special significance inside bracket expressions. All other ARE features use syntax which is illegal or has undefined or unspecified effects in POSIX EREs; the \fB***\fR syntax of directors likewise is outside the POSIX syntax for both BREs and EREs. .PP Many of the ARE extensions are borrowed from Perl, but some have been changed to clean them up, and a few Perl extensions are not present. Incompatibilities of note include .QW \fB\eb\fR , .QW \fB\eB\fR , the lack of special treatment for a trailing newline, the addition of complemented bracket expressions to the things affected by newline-sensitive matching, the restrictions on parentheses and back references in lookahead constraints, and the longest/shortest-match (rather than first-match) matching semantics. .PP The matching rules for REs containing both normal and non-greedy quantifiers have changed since early beta-test versions of this package. (The new rules are much simpler and cleaner, but do not work as hard at guessing the user's real intentions.) .PP Henry Spencer's original 1986 \fIregexp\fR package, still in widespread use (e.g., in pre-8.1 releases of Tcl), implemented an early version of today's EREs. There are four incompatibilities between \fIregexp\fR's near-EREs .PQ RREs " for short" and AREs. In roughly increasing order of significance: .IP \(bu 3 In AREs, \fB\e\fR followed by an alphanumeric character is either an escape or an error, while in RREs, it was just another way of writing the alphanumeric. This should not be a problem because there was no reason to write such a sequence in RREs. .IP \(bu 3 \fB{\fR followed by a digit in an ARE is the beginning of a bound, while in RREs, \fB{\fR was always an ordinary character. Such sequences should be rare, and will often result in an error because following characters will not look like a valid bound. .IP \(bu 3 In AREs, \fB\e\fR remains a special character within .QW \fB[\|]\fR , so a literal \fB\e\fR within \fB[\|]\fR must be written .QW \fB\e\e\fR . \fB\e\e\fR also gives a literal \fB\e\fR within \fB[\|]\fR in RREs, but only truly paranoid programmers routinely doubled the backslash. .IP \(bu 3 AREs report the longest/shortest match for the RE, rather than the first found in a specified search order. This may affect some RREs which were written in the expectation that the first match would be reported. (The careful crafting of RREs to optimize the search order for fast matching is obsolete (AREs examine all possible matches in parallel, and their performance is largely insensitive to their complexity) but cases where the search order was exploited to deliberately find a match which was \fInot\fR the longest/shortest will need rewriting.) .SH "BASIC REGULAR EXPRESSIONS" BREs differ from EREs in several respects. .QW \fB|\fR , .QW \fB+\fR , and \fB?\fR are ordinary characters and there is no equivalent for their functionality. The delimiters for bounds are \fB\e{\fR and .QW \fB\e}\fR , with \fB{\fR and \fB}\fR by themselves ordinary characters. The parentheses for nested subexpressions are \fB\e(\fR and .QW \fB\e)\fR , with \fB(\fR and \fB)\fR by themselves ordinary characters. \fB^\fR is an ordinary character except at the beginning of the RE or the beginning of a parenthesized subexpression, \fB$\fR is an ordinary character except at the end of the RE or the end of a parenthesized subexpression, and \fB*\fR is an ordinary character if it appears at the beginning of the RE or the beginning of a parenthesized subexpression (after a possible leading .QW \fB^\fR ). Finally, single-digit back references are available, and \fB\e<\fR and \fB\e>\fR are synonyms for .QW \fB[[:<:]]\fR and .QW \fB[[:>:]]\fR respectively; no other escapes are available. .SH "SEE ALSO" RegExp(3), regexp(n), regsub(n), lsearch(n), switch(n), text(n) .SH KEYWORDS match, regular expression, string .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/Access.30000644000175000017500000000564312663660065013631 0ustar sergeisergei'\" '\" Copyright (c) 1998-1999 Scriptics Corporation '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_Access 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_Access, Tcl_Stat \- check file permissions and other attributes .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_Access\fR(\fIpath\fR, \fImode\fR) .sp int \fBTcl_Stat\fR(\fIpath\fR, \fIstatPtr\fR) .SH ARGUMENTS .AS "struct stat" *statPtr out .AP char *path in Native name of the file to check the attributes of. .AP int mode in Mask consisting of one or more of \fBR_OK\fR, \fBW_OK\fR, \fBX_OK\fR and \fBF_OK\fR. \fBR_OK\fR, \fBW_OK\fR and \fBX_OK\fR request checking whether the file exists and has read, write and execute permissions, respectively. \fBF_OK\fR just requests a check for the existence of the file. .AP "struct stat" *statPtr out The structure that contains the result. .BE .SH DESCRIPTION .PP As of Tcl 8.4, the object-based APIs \fBTcl_FSAccess\fR and \fBTcl_FSStat\fR should be used in preference to \fBTcl_Access\fR and \fBTcl_Stat\fR, wherever possible. Those functions also support Tcl's virtual filesystem layer, which these do not. .SS "OBSOLETE FUNCTIONS" .PP There are two reasons for calling \fBTcl_Access\fR and \fBTcl_Stat\fR rather than calling system level functions \fBaccess\fR and \fBstat\fR directly. First, the Windows implementation of both functions fixes some bugs in the system level calls. Second, both \fBTcl_Access\fR and \fBTcl_Stat\fR (as well as \fBTcl_OpenFileChannelProc\fR) hook into a linked list of functions. This allows the possibility to reroute file access to alternative media or access methods. .PP \fBTcl_Access\fR checks whether the process would be allowed to read, write or test for existence of the file (or other file system object) whose name is \fIpath\fR. If \fIpath\fR is a symbolic link on Unix, then permissions of the file referred by this symbolic link are tested. .PP On success (all requested permissions granted), zero is returned. On error (at least one bit in mode asked for a permission that is denied, or some other error occurred), -1 is returned. .PP \fBTcl_Stat\fR fills the stat structure \fIstatPtr\fR with information about the specified file. You do not need any access rights to the file to get this information but you need search rights to all directories named in the path leading to the file. The stat structure includes info regarding device, inode (always 0 on Windows), privilege mode, nlink (always 1 on Windows), user id (always 0 on Windows), group id (always 0 on Windows), rdev (same as device on Windows), size, last access time, last modification time, and creation time. .PP If \fIpath\fR exists, \fBTcl_Stat\fR returns 0 and the stat structure is filled with data. Otherwise, -1 is returned, and no stat info is given. .SH KEYWORDS stat, access .SH "SEE ALSO" Tcl_FSAccess(3), Tcl_FSStat(3) tcl8.6.5/doc/self.n0000644000175000017500000001224512663660065013450 0ustar sergeisergei'\" '\" Copyright (c) 2007 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH self n 0.1 TclOO "TclOO Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME self \- method call internal introspection .SH SYNOPSIS .nf package require TclOO \fBself\fR ?\fIsubcommand\fR? .fi .BE .SH DESCRIPTION The \fBself\fR command, which should only be used from within the context of a call to a method (i.e. inside a method, constructor or destructor body) is used to allow the method to discover information about how it was called. It takes an argument, \fIsubcommand\fR, that tells it what sort of information is actually desired; if omitted the result will be the same as if \fBself object\fR was invoked. The supported subcommands are: .TP \fBself call\fR . This returns a two-element list describing the method implementations used to implement the current call chain. The first element is the same as would be reported by \fBinfo object\fR \fBcall\fR for the current method (except that this also reports useful values from within constructors and destructors, whose names are reported as \fB\fR and \fB\fR respectively), and the second element is an index into the first element's list that indicates which actual implementation is currently executing (the first implementation to execute is always at index 0). .TP \fBself caller\fR . When the method was invoked from inside another object method, this subcommand returns a three element list describing the containing object and method. The first element describes the declaring object or class of the method, the second element is the name of the object on which the containing method was invoked, and the third element is the name of the method (with the strings \fB\fR and \fB\fR indicating constructors and destructors respectively). .TP \fBself class\fR . This returns the name of the class that the current method was defined within. Note that this will change as the chain of method implementations is traversed with \fBnext\fR, and that if the method was defined on an object then this will fail. .RS .PP If you want the class of the current object, you need to use this other construct: .PP .CS info object class [\fBself object\fR] .CE .RE .TP \fBself filter\fR . When invoked inside a filter, this subcommand returns a three element list describing the filter. The first element gives the name of the object or class that declared the filter (note that this may be different from the object or class that provided the implementation of the filter), the second element is either \fBobject\fR or \fBclass\fR depending on whether the declaring entity was an object or class, and the third element is the name of the filter. .TP \fBself method\fR . This returns the name of the current method (with the strings \fB\fR and \fB\fR indicating constructors and destructors respectively). .TP \fBself namespace\fR . This returns the name of the unique namespace of the object that the method was invoked upon. .TP \fBself next\fR . When invoked from a method that is not at the end of a call chain (i.e. where the \fBnext\fR command will invoke an actual method implementation), this subcommand returns a two element list describing the next element in the method call chain; the first element is the name of the class or object that declares the next part of the call chain, and the second element is the name of the method (with the strings \fB\fR and \fB\fR indicating constructors and destructors respectively). If invoked from a method that is at the end of a call chain, this subcommand returns the empty string. .TP \fBself object\fR . This returns the name of the object that the method was invoked upon. .TP \fBself target\fR . When invoked inside a filter implementation, this subcommand returns a two element list describing the method being filtered. The first element will be the name of the declarer of the method, and the second element will be the actual name of the method. .SH EXAMPLES .PP This example shows basic use of \fBself\fR to provide information about the current object: .PP .CS oo::class create c { method foo {} { puts "this is the [\fBself\fR] object" } } c create a c create b a foo \fI\(-> prints "this is the ::a object"\fR b foo \fI\(-> prints "this is the ::b object"\fR .CE .PP This demonstrates what a method call chain looks like, and how traversing along it changes the index into it: .PP .CS oo::class create c { method x {} { puts "Cls: [\fBself call\fR]" } } c create a oo::objdefine a { method x {} { puts "Obj: [\fBself call\fR]" next puts "Obj: [\fBself call\fR]" } } a x \fI\(-> Obj: {{method x object method} {method x ::c method}} 0\fR \fI\(-> Cls: {{method x object method} {method x ::c method}} 1\fR \fI\(-> Obj: {{method x object method} {method x ::c method}} 0\fR .CE .SH "SEE ALSO" info(n), next(n) .SH KEYWORDS call, introspection, object .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: tcl8.6.5/doc/lreplace.n0000644000175000017500000000543412663660065014310 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2001 Kevin B. Kenny . All rights reserved. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH lreplace n 7.4 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME lreplace \- Replace elements in a list with new elements .SH SYNOPSIS \fBlreplace \fIlist first last \fR?\fIelement element ...\fR? .BE .SH DESCRIPTION .PP \fBlreplace\fR returns a new list formed by replacing one or more elements of \fIlist\fR with the \fIelement\fR arguments. \fIfirst\fR and \fIlast\fR are index values specifying the first and last elements of the range to replace. The index values \fIfirst\fR and \fIlast\fR are interpreted the same as index values for the command \fBstring index\fR, supporting simple index arithmetic and indices relative to the end of the list. 0 refers to the first element of the list, and \fBend\fR refers to the last element of the list. If \fIlist\fR is empty, then \fIfirst\fR and \fIlast\fR are ignored. .PP If \fIfirst\fR is less than zero, it is considered to refer to before the first element of the list. For non-empty lists, the element indicated by \fIfirst\fR must exist or \fIfirst\fR must indicate before the start of the list. .PP If \fIlast\fR is less than \fIfirst\fR, then any specified elements will be inserted into the list before the point specified by \fIfirst\fR with no elements being deleted. .PP The \fIelement\fR arguments specify zero or more new arguments to be added to the list in place of those that were deleted. Each \fIelement\fR argument will become a separate element of the list. If no \fIelement\fR arguments are specified, then the elements between \fIfirst\fR and \fIlast\fR are simply deleted. If \fIlist\fR is empty, any \fIelement\fR arguments are added to the end of the list. .SH EXAMPLES .PP Replacing an element of a list with another: .PP .CS % \fBlreplace\fR {a b c d e} 1 1 foo a foo c d e .CE .PP Replacing two elements of a list with three: .PP .CS % \fBlreplace\fR {a b c d e} 1 2 three more elements a three more elements d e .CE .PP Deleting the last element from a list in a variable: .PP .CS % set var {a b c d e} a b c d e % set var [\fBlreplace\fR $var end end] a b c d .CE .PP A procedure to delete a given element from a list: .PP .CS proc lremove {listVariable value} { upvar 1 $listVariable var set idx [lsearch -exact $var $value] set var [\fBlreplace\fR $var $idx $idx] } .CE .SH "SEE ALSO" list(n), lappend(n), lindex(n), linsert(n), llength(n), lsearch(n), lset(n), lrange(n), lsort(n), string(n) .SH KEYWORDS element, list, replace tcl8.6.5/doc/Translate.30000644000175000017500000000547412663660065014367 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_TranslateFileName 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_TranslateFileName \- convert file name to native form and replace tilde with home directory .SH SYNOPSIS .nf \fB#include \fR .sp char * \fBTcl_TranslateFileName\fR(\fIinterp\fR, \fIname\fR, \fIbufferPtr\fR) .SH ARGUMENTS .AS Tcl_DString *bufferPtr in/out .AP Tcl_Interp *interp in Interpreter in which to report an error, if any. .AP "const char" *name in File name, which may start with a .QW ~ . .AP Tcl_DString *bufferPtr in/out If needed, this dynamic string is used to store the new file name. At the time of the call it should be uninitialized or free. The caller must eventually call \fBTcl_DStringFree\fR to free up anything stored here. .BE .SH DESCRIPTION .PP This utility procedure translates a file name to a platform-specific form which, after being converted to the appropriate encoding, is suitable for passing to the local operating system. In particular, it converts network names into native form and does tilde substitution. .PP However, with the advent of the newer \fBTcl_FSGetNormalizedPath\fR and \fBTcl_FSGetNativePath\fR, there is no longer any need to use this procedure. In particular, \fBTcl_FSGetNativePath\fR performs all the necessary translation and encoding conversion, is virtual-filesystem aware, and caches the native result for faster repeated calls. Finally \fBTcl_FSGetNativePath\fR does not require you to free anything afterwards. .PP If \fBTcl_TranslateFileName\fR has to do tilde substitution or translate the name then it uses the dynamic string at \fI*bufferPtr\fR to hold the new string it generates. After \fBTcl_TranslateFileName\fR returns a non-NULL result, the caller must eventually invoke \fBTcl_DStringFree\fR to free any information placed in \fI*bufferPtr\fR. The caller need not know whether or not \fBTcl_TranslateFileName\fR actually used the string; \fBTcl_TranslateFileName\fR initializes \fI*bufferPtr\fR even if it does not use it, so the call to \fBTcl_DStringFree\fR will be safe in either case. .PP If an error occurs (e.g. because there was no user by the given name) then NULL is returned and an error message will be left in the interpreter's result. When an error occurs, \fBTcl_TranslateFileName\fR frees the dynamic string itself so that the caller need not call \fBTcl_DStringFree\fR. .PP The caller is responsible for making sure that the interpreter's result has its default empty value when \fBTcl_TranslateFileName\fR is invoked. .SH "SEE ALSO" filename(n) .SH KEYWORDS file name, home directory, tilde, translate, user tcl8.6.5/doc/Namespace.30000644000175000017500000001436012663660065014320 0ustar sergeisergei'\" '\" Copyright (c) 2003 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" '\" Note that some of these functions do not seem to belong, but they '\" were all introduced with the same TIP (#139) '\" .TH Tcl_Namespace 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_AppendExportList, Tcl_CreateNamespace, Tcl_DeleteNamespace, Tcl_Export, Tcl_FindCommand, Tcl_FindNamespace, Tcl_ForgetImport, Tcl_GetCurrentNamespace, Tcl_GetGlobalNamespace, Tcl_GetNamespaceUnknownHandler, Tcl_Import, Tcl_SetNamespaceUnknownHandler \- manipulate namespaces .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Namespace * \fBTcl_CreateNamespace\fR(\fIinterp, name, clientData, deleteProc\fR) .sp \fBTcl_DeleteNamespace\fR(\fInsPtr\fR) .sp int \fBTcl_AppendExportList\fR(\fIinterp, nsPtr, objPtr\fR) .sp int \fBTcl_Export\fR(\fIinterp, nsPtr, pattern, resetListFirst\fR) .sp int \fBTcl_Import\fR(\fIinterp, nsPtr, pattern, allowOverwrite\fR) .sp int \fBTcl_ForgetImport\fR(\fIinterp, nsPtr, pattern\fR) .sp Tcl_Namespace * \fBTcl_GetCurrentNamespace\fR(\fIinterp\fR) .sp Tcl_Namespace * \fBTcl_GetGlobalNamespace\fR(\fIinterp\fR) .sp Tcl_Namespace * \fBTcl_FindNamespace\fR(\fIinterp, name, contextNsPtr, flags\fR) .sp Tcl_Command \fBTcl_FindCommand\fR(\fIinterp, name, contextNsPtr, flags\fR) .sp Tcl_Obj * \fBTcl_GetNamespaceUnknownHandler(\fIinterp, nsPtr\fR) .sp int \fBTcl_SetNamespaceUnknownHandler(\fIinterp, nsPtr, handlerPtr\fR) .SH ARGUMENTS .AS Tcl_NamespaceDeleteProc allowOverwrite in/out .AP Tcl_Interp *interp in/out The interpreter in which the namespace exists and where name lookups are performed. Also where error result messages are written. .AP "const char" *name in The name of the namespace or command to be created or accessed. .AP ClientData clientData in A context pointer by the creator of the namespace. Not interpreted by Tcl at all. .AP Tcl_NamespaceDeleteProc *deleteProc in A pointer to function to call when the namespace is deleted, or NULL if no such callback is to be performed. .AP Tcl_Namespace *nsPtr in The namespace to be manipulated, or NULL (for other than \fBTcl_DeleteNamespace\fR) to manipulate the current namespace. .AP Tcl_Obj *objPtr out A reference to an unshared value to which the function output will be written. .AP "const char" *pattern in The glob-style pattern (see \fBTcl_StringMatch\fR) that describes the commands to be imported or exported. .AP int resetListFirst in Whether the list of export patterns should be reset before adding the current pattern to it. .AP int allowOverwrite in Whether new commands created by this import action can overwrite existing commands. .AP Tcl_Namespace *contextNsPtr in The location in the namespace hierarchy where the search for a namespace or command should be conducted relative to when the search term is not rooted at the global namespace. NULL indicates the current namespace. .AP int flags in OR-ed combination of bits controlling how the search is to be performed. The following flags are supported: \fBTCL_GLOBAL_ONLY\fR (indicates that the search is always to be conducted relative to the global namespace), \fBTCL_NAMESPACE_ONLY\fR (just for \fBTcl_FindCommand\fR; indicates that the search is always to be conducted relative to the context namespace), and \fBTCL_LEAVE_ERR_MSG\fR (indicates that an error message should be left in the interpreter if the search fails.) .AP Tcl_Obj *handlerPtr in A script fragment to be installed as the unknown command handler for the namespace, or NULL to reset the handler to its default. .BE .SH DESCRIPTION .PP Namespaces are hierarchic naming contexts that can contain commands and variables. They also maintain a list of patterns that describes what commands are exported, and can import commands that have been exported by other namespaces. Namespaces can also be manipulated through the Tcl command \fBnamespace\fR. .PP The \fITcl_Namespace\fR structure encapsulates a namespace, and is guaranteed to have the following fields in it: \fIname\fR (the local name of the namespace, with no namespace separator characters in it, with empty denoting the global namespace), \fIfullName\fR (the fully specified name of the namespace), \fIclientData\fR, \fIdeleteProc\fR (the values specified in the call to \fBTcl_CreateNamespace\fR), and \fIparentPtr\fR (a pointer to the containing namespace, or NULL for the global namespace.) .PP \fBTcl_CreateNamespace\fR creates a new namespace. The \fIdeleteProc\fR will have the following type signature: .PP .CS typedef void \fBTcl_NamespaceDeleteProc\fR( ClientData \fIclientData\fR); .CE .PP \fBTcl_DeleteNamespace\fR deletes a namespace, calling the \fIdeleteProc\fR defined for the namespace (if any). .PP \fBTcl_AppendExportList\fR retrieves the export patterns for a namespace given namespace and appends them (as list items) to \fIobjPtr\fR. .PP \fBTcl_Export\fR sets and appends to the export patterns for a namespace. Patterns are appended unless the \fIresetListFirst\fR flag is true. .PP \fBTcl_Import\fR imports commands matching a pattern into a namespace. Note that the pattern must include the name of the namespace to import from. This function returns an error if an attempt to import a command over an existing command is made, unless the \fIallowOverwrite\fR flag has been set. .PP \fBTcl_ForgetImport\fR removes imports matching a pattern. .PP \fBTcl_GetCurrentNamespace\fR returns the current namespace for an interpreter. .PP \fBTcl_GetGlobalNamespace\fR returns the global namespace for an interpreter. .PP \fBTcl_FindNamespace\fR searches for a namespace named \fIname\fR within the context of the namespace \fIcontextNsPtr\fR. If the namespace cannot be found, NULL is returned. .PP \fBTcl_FindCommand\fR searches for a command named \fIname\fR within the context of the namespace \fIcontextNsPtr\fR. If the command cannot be found, NULL is returned. .PP \fBTcl_GetNamespaceUnknownHandler\fR returns the unknown command handler for the namespace, or NULL if none is set. .PP \fBTcl_SetNamespaceUnknownHandler\fR sets the unknown command handler for the namespace. If \fIhandlerPtr\fR is NULL, then the handler is reset to its default. .SH "SEE ALSO" Tcl_CreateCommand(3), Tcl_ListObjAppendList(3), Tcl_SetVar(3) .SH KEYWORDS namespace, command tcl8.6.5/doc/transchan.n0000644000175000017500000001513512663660065014501 0ustar sergeisergei'\" '\" Copyright (c) 2008 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH transchan n 8.6 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME transchan \- command handler API of channel transforms .SH SYNOPSIS \fBcmdPrefix \fIoption\fR ?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP The Tcl-level handler for a channel transformation has to be a command with subcommands (termed an \fIensemble\fR despite not implying that it must be created with \fBnamespace ensemble create\fR; this mechanism is not tied to \fBnamespace ensemble\fR in any way). Note that \fIcmdPrefix\fR is whatever was specified in the call to \fBchan push\fR, and may consist of multiple arguments; this will be expanded to multiple words in place of the prefix. .PP Of all the possible subcommands, the handler \fImust\fR support \fBinitialize\fR and \fBfinalize\fR. Transformations for writable channels must also support \fBwrite\fR, and transformations for readable channels must also support \fBread\fR. .PP Note that in the descriptions below \fIcmdPrefix\fR may be more than one word, and \fIhandle\fR is the value returned by the \fBchan push\fR call used to create the transformation. .SS "GENERIC SUBCOMMANDS" .PP The following subcommands are relevant to all types of channel. .TP \fIcmdPrefix \fBclear \fIhandle\fR . This optional subcommand is called to signify to the transformation that any data stored in internal buffers (either incoming or outgoing) must be cleared. It is called when a \fBchan seek\fR is performed on the channel being transformed. .TP \fIcmdPrefix \fBfinalize \fIhandle\fR . This mandatory subcommand is called last for the given \fIhandle\fR, and then never again, and it exists to allow for cleaning up any Tcl-level data structures associated with the transformation. \fIWarning!\fR Any errors thrown by this subcommand will be ignored. It is not guaranteed to be called if the interpreter is deleted. .TP \fIcmdPrefix \fBinitialize \fIhandle mode\fR . This mandatory subcommand is called first, and then never again (for the given \fIhandle\fR). Its responsibility is to initialize all parts of the transformation at the Tcl level. The \fImode\fR is a list containing any of \fBread \fRand \fBwrite\fR. .RS .TP \fBwrite\fR . implies that the channel is writable. .TP \fBread\fR . implies that the channel is readable. .PP The return value of the subcommand should be a list containing the names of all subcommands supported by this handler. Any error thrown by the subcommand will prevent the creation of the transformation. The thrown error will appear as error thrown by \fBchan push\fR. .RE .SS "READ-RELATED SUBCOMMANDS" .PP These subcommands are used for handling transformations applied to readable channels; though strictly \fBread \fRis optional, it must be supported if any of the others is or the channel will be made non-readable. .TP \fIcmdPrefix \fBdrain \fIhandle\fR . This optional subcommand is called whenever data in the transformation input (i.e. read) buffer has to be forced upward, i.e. towards the user or script. The result returned by the method is taken as the \fIbinary\fR data to push upward to the level above this transformation (the reader or a higher-level transformation). .RS .PP In other words, when this method is called the transformation cannot defer the actual transformation operation anymore and has to transform all data waiting in its internal read buffers and return the result of that action. .RE .TP \fIcmdPrefix \fBlimit? \fIhandle\fR . This optional subcommand is called to allow the Tcl I/O engine to determine how far ahead it should read. If present, it should return an integer number greater than zero which indicates how many bytes ahead should be read, or an integer less than zero to indicate that the I/O engine may read as far ahead as it likes. .TP \fIcmdPrefix \fBread \fIhandle buffer\fR . This subcommand, which must be present if the transformation is to work with readable channels, is called whenever the base channel, or a transformation below this transformation, pushes data upward. The \fIbuffer\fR contains the binary data which has been given to us from below. It is the responsibility of this subcommand to actually transform the data. The result returned by the subcommand is taken as the binary data to push further upward to the transformation above this transformation. This can also be the user or script that originally read from the channel. .RS .PP Note that the result is allowed to be empty, or even less than the data we received; the transformation is not required to transform everything given to it right now. It is allowed to store incoming data in internal buffers and to defer the actual transformation until it has more data. .RE .SS "WRITE-RELATED SUBCOMMANDS" .PP These subcommands are used for handling transformations applied to writable channels; though strictly \fBwrite\fR is optional, it must be supported if any of the others is or the channel will be made non-writable. .TP \fIcmdPrefix \fBflush \fIhandle\fR . This optional subcommand is called whenever data in the transformation 'write' buffer has to be forced downward, i.e. towards the base channel. The result returned by the subcommand is taken as the binary data to write to the transformation below the current transformation. This can be the base channel as well. .RS .PP In other words, when this subcommand is called the transformation cannot defer the actual transformation operation anymore and has to transform all data waiting in its internal write buffers and return the result of that action. .RE .TP \fIcmdPrefix \fBwrite \fIhandle buffer\fR . This subcommand, which must be present if the transformation is to work with writable channels, is called whenever the user, or a transformation above this transformation, writes data downward. The \fIbuffer\fR contains the binary data which has been written to us. It is the responsibility of this subcommand to actually transform the data. .RS .PP The result returned by the subcommand is taken as the binary data to write to the transformation below this transformation. This can be the base channel as well. Note that the result is allowed to be empty, or less than the data we got; the transformation is not required to transform everything which was written to it right now. It is allowed to store this data in internal buffers and to defer the actual transformation until it has more data. .RE .SH "SEE ALSO" chan(n), refchan(n) .SH KEYWORDS API, channel, ensemble, prefix, transformation '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/try.n0000644000175000017500000000772112663660065013340 0ustar sergeisergei'\" '\" Copyright (c) 2008 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH try n 8.6 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME try \- Trap and process errors and exceptions .SH SYNOPSIS \fBtry\fI body\fR ?\fIhandler...\fR? ?\fBfinally\fI script\fR? .BE .SH DESCRIPTION .PP This command executes the script \fIbody\fR and, depending on what the outcome of that script is (normal exit, error, or some other exceptional result), runs a handler script to deal with the case. Once that has all happened, if the \fBfinally\fR clause is present, the \fIscript\fR it includes will be run and the result of the handler (or the \fIbody\fR if no handler matched) is allowed to continue to propagate. Note that the \fBfinally\fR clause is processed even if an error occurs and irrespective of which, if any, \fIhandler\fR is used. .PP The \fIhandler\fR clauses are each expressed as several words, and must have one of the following forms: .TP \fBon \fIcode variableList script\fR . This clause matches if the evaluation of \fIbody\fR completed with the exception code \fIcode\fR. The \fIcode\fR may be expressed as an integer or one of the following literal words: \fBok\fR, \fBerror\fR, \fBreturn\fR, \fBbreak\fR, or \fBcontinue\fR. Those literals correspond to the integers 0 through 4 respectively. .TP \fBtrap \fIpattern variableList script\fR . This clause matches if the evaluation of \fIbody\fR resulted in an error and the prefix of the \fB\-errorcode\fR from the interpreter's status dictionary is equal to the \fIpattern\fR. The number of prefix words taken from the \fB\-errorcode\fR is equal to the list-length of \fIpattern\fR, and inter-word spaces are normalized in both the \fB\-errorcode\fR and \fIpattern\fR before comparison. .PP The \fIvariableList\fR word in each \fIhandler\fR is always interpreted as a list of variable names. If the first word of the list is present and non-empty, it names a variable into which the result of the evaluation of \fIbody\fR (from the main \fBtry\fR) will be placed; this will contain the human-readable form of any errors. If the second word of the list is present and non-empty, it names a variable into which the options dictionary of the interpreter at the moment of completion of execution of \fIbody\fR will be placed. .PP The \fIscript\fR word of each \fIhandler\fR is also always interpreted the same: as a Tcl script to evaluate if the clause is matched. If \fIscript\fR is a literal .QW \- and the \fIhandler\fR is not the last one, the \fIscript\fR of the following \fIhandler\fR is invoked instead (just like with the \fBswitch\fR command). .PP Note that \fIhandler\fR clauses are matched against in order, and that the first matching one is always selected. At most one \fIhandler\fR clause will selected. As a consequence, an \fBon error\fR will mask any subsequent \fBtrap\fR in the \fBtry\fR. Also note that \fBon error\fR is equivalent to \fBtrap {}\fR. .PP If an exception (i.e. any non-\fBok\fR result) occurs during the evaluation of either the \fIhandler\fR or the \fBfinally\fR clause, the original exception's status dictionary will be added to the new exception's status dictionary under the \fB\-during\fR key. .SH EXAMPLES .PP Ensure that a file is closed no matter what: .PP .CS set f [open /some/file/name a] \fBtry\fR { puts $f "some message" # ... } \fBfinally\fR { close $f } .CE .PP Handle different reasons for a file to not be openable for reading: .PP .CS \fBtry\fR { set f [open /some/file/name w] } \fBtrap\fR {POSIX EISDIR} {} { puts "failed to open /some/file/name: it's a directory" } \fBtrap\fR {POSIX ENOENT} {} { puts "failed to open /some/file/name: it doesn't exist" } .CE .SH "SEE ALSO" catch(n), error(n), return(n), throw(n) .SH "KEYWORDS" cleanup, error, exception, final, resource management '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/info.n0000644000175000017500000007146612663660065013464 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 Sun Microsystems, Inc. '\" Copyright (c) 1993-1997 Bell Labs Innovations for Lucent Technologies '\" Copyright (c) 1998-2000 Ajuba Solutions '\" Copyright (c) 2007-2012 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH info n 8.4 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME info \- Return information about the state of the Tcl interpreter .SH SYNOPSIS \fBinfo \fIoption \fR?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP This command provides information about various internals of the Tcl interpreter. The legal \fIoption\fRs (which may be abbreviated) are: .TP \fBinfo args \fIprocname\fR . Returns a list containing the names of the arguments to procedure \fIprocname\fR, in order. \fIProcname\fR must be the name of a Tcl command procedure. .TP \fBinfo body \fIprocname\fR . Returns the body of procedure \fIprocname\fR. \fIProcname\fR must be the name of a Tcl command procedure. .TP \fBinfo class\fI subcommand class\fR ?\fIarg ...\fR .VS 8.6 Returns information about the class, \fIclass\fR. The \fIsubcommand\fRs are described in \fBCLASS INTROSPECTION\fR below. .VE 8.6 .TP \fBinfo cmdcount\fR . Returns a count of the total number of commands that have been invoked in this interpreter. .TP \fBinfo commands \fR?\fIpattern\fR? . If \fIpattern\fR is not specified, returns a list of names of all the Tcl commands visible (i.e. executable without using a qualified name) to the current namespace, including both the built-in commands written in C and the command procedures defined using the \fBproc\fR command. If \fIpattern\fR is specified, only those names matching \fIpattern\fR are returned. Matching is determined using the same rules as for \fBstring match\fR. \fIpattern\fR can be a qualified name like \fBFoo::print*\fR. That is, it may specify a particular namespace using a sequence of namespace names separated by double colons (\fB::\fR), and may have pattern matching special characters at the end to specify a set of commands in that namespace. If \fIpattern\fR is a qualified name, the resulting list of command names has each one qualified with the name of the specified namespace, and only the commands defined in the named namespace are returned. .\" Technically, most of this hasn't changed; that's mostly just the .\" way it always worked. Hardly anyone knew that though. .TP \fBinfo complete \fIcommand\fR . Returns 1 if \fIcommand\fR is a complete Tcl command in the sense of having no unclosed quotes, braces, brackets or array element names. If the command does not appear to be complete then 0 is returned. This command is typically used in line-oriented input environments to allow users to type in commands that span multiple lines; if the command is not complete, the script can delay evaluating it until additional lines have been typed to complete the command. .TP \fBinfo coroutine\fR .VS 8.6 Returns the name of the currently executing \fBcoroutine\fR, or the empty string if either no coroutine is currently executing, or the current coroutine has been deleted (but has not yet returned or yielded since deletion). .VE 8.6 .TP \fBinfo default \fIprocname arg varname\fR . \fIProcname\fR must be the name of a Tcl command procedure and \fIarg\fR must be the name of an argument to that procedure. If \fIarg\fR does not have a default value then the command returns \fB0\fR. Otherwise it returns \fB1\fR and places the default value of \fIarg\fR into variable \fIvarname\fR. .TP \fBinfo errorstack \fR?\fIinterp\fR? .VS 8.6 Returns, in a form that is programmatically easy to parse, the function names and arguments at each level from the call stack of the last error in the given \fIinterp\fR, or in the current one if not specified. .RS .PP This form is an even-sized list alternating tokens and parameters. Tokens are currently either \fBCALL\fR, \fBUP\fR, or \fBINNER\fR, but other values may be introduced in the future. \fBCALL\fR indicates a procedure call, and its parameter is the corresponding \fBinfo level\fR \fB0\fR. \fBUP\fR indicates a shift in variable frames generated by \fBuplevel\fR or similar, and applies to the previous \fBCALL\fR item. Its parameter is the level offset. \fBINNER\fR identifies the .QW "inner context" , which is the innermost atomic command or bytecode instruction that raised the error, along with its arguments when available. While \fBCALL\fR and \fBUP\fR allow to follow complex call paths, \fBINNER\fR homes in on the offending operation in the innermost procedure call, even going to sub-expression granularity. .PP This information is also present in the \fB\-errorstack\fR entry of the options dictionary returned by 3-argument \fBcatch\fR; \fBinfo errorstack\fR is a convenient way of retrieving it for uncaught errors at top-level in an interactive \fBtclsh\fR. .RE .VE 8.6 .TP \fBinfo exists \fIvarName\fR . Returns \fB1\fR if the variable named \fIvarName\fR exists in the current context (either as a global or local variable) and has been defined by being given a value, returns \fB0\fR otherwise. .TP \fBinfo frame\fR ?\fInumber\fR? . This command provides access to all frames on the stack, even those hidden from \fBinfo level\fR. If \fInumber\fR is not specified, this command returns a number giving the frame level of the command. This is 1 if the command is invoked at top-level. If \fInumber\fR is specified, then the result is a dictionary containing the location information for the command at the \fInumber\fRed level on the stack. .RS .PP If \fInumber\fR is positive (> 0) then it selects a particular stack level (1 refers to the outer-most active command, 2 to the command it called, and so on, up to the current frame level which refers to \fBinfo frame\fR itself); otherwise it gives a level relative to the current command (0 refers to the current command, i.e., \fBinfo frame\fR itself, -1 to its caller, and so on). .PP This is similar to how \fBinfo level\fR works, except that this subcommand reports all frames, like \fBsource\fRd scripts, \fBeval\fRs, \fBuplevel\fRs, etc. .PP Note that for nested commands, like .QW "foo [bar [x]]" , only .QW x will be seen by an \fBinfo frame\fR invoked within .QW x . This is the same as for \fBinfo level\fR and error stack traces. .PP The result dictionary may contain the keys listed below, with the specified meanings for their values: .TP \fBtype\fR . This entry is always present and describes the nature of the location for the command. The recognized values are \fBsource\fR, \fBproc\fR, \fBeval\fR, and \fBprecompiled\fR. .RS .TP \fBsource\fR\0\0\0\0\0\0\0\0 . means that the command is found in a script loaded by the \fBsource\fR command. .TP \fBproc\fR\0\0\0\0\0\0\0\0 . means that the command is found in dynamically created procedure body. .TP \fBeval\fR\0\0\0\0\0\0\0\0 . means that the command is executed by \fBeval\fR or \fBuplevel\fR. .TP \fBprecompiled\fR\0\0\0\0\0\0\0\0 . means that the command is found in a pre-compiled script (loadable by the package \fBtbcload\fR), and no further information will be available. .RE .TP \fBline\fR . This entry provides the number of the line the command is at inside of the script it is a part of. This information is not present for type \fBprecompiled\fR. For type \fBsource\fR this information is counted relative to the beginning of the file, whereas for the last two types the line is counted relative to the start of the script. .TP \fBfile\fR . This entry is present only for type \fBsource\fR. It provides the normalized path of the file the command is in. .TP \fBcmd\fR . This entry provides the string representation of the command. This is usually the unsubstituted form, however for commands which are a canonically-constructed list (e.g., as produced by the \fBlist\fR command) executed by \fBeval\fR it is the substituted form as they have no other string representation. Care is taken that the canonicality property of the latter is not spoiled. .TP \fBproc\fR . This entry is present only if the command is found in the body of a regular Tcl procedure. It then provides the name of that procedure. .TP \fBlambda\fR . This entry is present only if the command is found in the body of an anonymous Tcl procedure, i.e. a lambda. It then provides the entire definition of the lambda in question. .TP \fBlevel\fR . This entry is present only if the queried frame has a corresponding frame returned by \fBinfo level\fR. It provides the index of this frame, relative to the current level (0 and negative numbers). .PP A thing of note is that for procedures statically defined in files the locations of commands in their bodies will be reported with type \fBsource\fR and absolute line numbers, and not as type \fBproc\fR. The same is true for procedures nested in statically defined procedures, and literal eval scripts in files or statically defined procedures. .PP In contrast, procedure definitions and \fBeval\fR within a dynamically \fBeval\fRuated environment count line numbers relative to the start of their script, even if they would be able to count relative to the start of the outer dynamic script. That type of number usually makes more sense. .PP A different way of describing this behaviour is that file based locations are tracked as deeply as possible, and where this is not possible the lines are counted based on the smallest possible \fBeval\fR or procedure body, as that scope is usually easier to find than any dynamic outer scope. .PP The syntactic form \fB{*}\fR is handled like \fBeval\fR. I.e. if it is given a literal list argument the system tracks the line number within the list words as well, and otherwise all line numbers are counted relative to the start of each word (smallest scope) .RE .TP \fBinfo functions \fR?\fIpattern\fR? . If \fIpattern\fR is not specified, returns a list of all the math functions currently defined. If \fIpattern\fR is specified, only those functions whose name matches \fIpattern\fR are returned. Matching is determined using the same rules as for \fBstring match\fR. .TP \fBinfo globals \fR?\fIpattern\fR? . If \fIpattern\fR is not specified, returns a list of all the names of currently-defined global variables. Global variables are variables in the global namespace. If \fIpattern\fR is specified, only those names matching \fIpattern\fR are returned. Matching is determined using the same rules as for \fBstring match\fR. .TP \fBinfo hostname\fR . Returns the name of the computer on which this invocation is being executed. Note that this name is not guaranteed to be the fully qualified domain name of the host. Where machines have several different names (as is common on systems with both TCP/IP (DNS) and NetBIOS-based networking installed,) it is the name that is suitable for TCP/IP networking that is returned. .TP \fBinfo level\fR ?\fInumber\fR? . If \fInumber\fR is not specified, this command returns a number giving the stack level of the invoking procedure, or 0 if the command is invoked at top-level. If \fInumber\fR is specified, then the result is a list consisting of the name and arguments for the procedure call at level \fInumber\fR on the stack. If \fInumber\fR is positive then it selects a particular stack level (1 refers to the top-most active procedure, 2 to the procedure it called, and so on); otherwise it gives a level relative to the current level (0 refers to the current procedure, -1 to its caller, and so on). See the \fBuplevel\fR command for more information on what stack levels mean. .TP \fBinfo library\fR . Returns the name of the library directory in which standard Tcl scripts are stored. This is actually the value of the \fBtcl_library\fR variable and may be changed by setting \fBtcl_library\fR. .TP \fBinfo loaded \fR?\fIinterp\fR? . Returns a list describing all of the packages that have been loaded into \fIinterp\fR with the \fBload\fR command. Each list element is a sub-list with two elements consisting of the name of the file from which the package was loaded and the name of the package. For statically-loaded packages the file name will be an empty string. If \fIinterp\fR is omitted then information is returned for all packages loaded in any interpreter in the process. To get a list of just the packages in the current interpreter, specify an empty string for the \fIinterp\fR argument. .TP \fBinfo locals \fR?\fIpattern\fR? . If \fIpattern\fR is not specified, returns a list of all the names of currently-defined local variables, including arguments to the current procedure, if any. Variables defined with the \fBglobal\fR, \fBupvar\fR and \fBvariable\fR commands will not be returned. If \fIpattern\fR is specified, only those names matching \fIpattern\fR are returned. Matching is determined using the same rules as for \fBstring match\fR. .TP \fBinfo nameofexecutable\fR . Returns the full path name of the binary file from which the application was invoked. If Tcl was unable to identify the file, then an empty string is returned. .TP \fBinfo object\fI subcommand object\fR ?\fIarg ...\fR .VS 8.6 Returns information about the object, \fIobject\fR. The \fIsubcommand\fRs are described in \fBOBJECT INTROSPECTION\fR below. .VE 8.6 .TP \fBinfo patchlevel\fR . Returns the value of the global variable \fBtcl_patchLevel\fR, which holds the exact version of the Tcl library by default. .TP \fBinfo procs \fR?\fIpattern\fR? . If \fIpattern\fR is not specified, returns a list of all the names of Tcl command procedures in the current namespace. If \fIpattern\fR is specified, only those procedure names in the current namespace matching \fIpattern\fR are returned. Matching is determined using the same rules as for \fBstring match\fR. If \fIpattern\fR contains any namespace separators, they are used to select a namespace relative to the current namespace (or relative to the global namespace if \fIpattern\fR starts with \fB::\fR) to match within; the matching pattern is taken to be the part after the last namespace separator. .TP \fBinfo script\fR ?\fIfilename\fR? . If a Tcl script file is currently being evaluated (i.e. there is a call to \fBTcl_EvalFile\fR active or there is an active invocation of the \fBsource\fR command), then this command returns the name of the innermost file being processed. If \fIfilename\fR is specified, then the return value of this command will be modified for the duration of the active invocation to return that name. This is useful in virtual file system applications. Otherwise the command returns an empty string. .TP \fBinfo sharedlibextension\fR . Returns the extension used on this platform for the names of files containing shared libraries (for example, \fB.so\fR under Solaris). If shared libraries are not supported on this platform then an empty string is returned. .TP \fBinfo tclversion\fR . Returns the value of the global variable \fBtcl_version\fR, which holds the major and minor version of the Tcl library by default. .TP \fBinfo vars\fR ?\fIpattern\fR? . If \fIpattern\fR is not specified, returns a list of all the names of currently-visible variables. This includes locals and currently-visible globals. If \fIpattern\fR is specified, only those names matching \fIpattern\fR are returned. Matching is determined using the same rules as for \fBstring match\fR. \fIpattern\fR can be a qualified name like \fBFoo::option*\fR. That is, it may specify a particular namespace using a sequence of namespace names separated by double colons (\fB::\fR), and may have pattern matching special characters at the end to specify a set of variables in that namespace. If \fIpattern\fR is a qualified name, the resulting list of variable names has each matching namespace variable qualified with the name of its namespace. Note that a currently-visible variable may not yet .QW exist if it has not been set (e.g. a variable declared but not set by \fBvariable\fR). .SS "CLASS INTROSPECTION" .VS 8.6 .PP The following \fIsubcommand\fR values are supported by \fBinfo class\fR: .VE 8.6 .TP \fBinfo class call\fI class method\fR .VS Returns a description of the method implementations that are used to provide a stereotypical instance of \fIclass\fR's implementation of \fImethod\fR (stereotypical instances being objects instantiated by a class without having any object-specific definitions added). This consists of a list of lists of four elements, where each sublist consists of a word that describes the general type of method implementation (being one of \fBmethod\fR for an ordinary method, \fBfilter\fR for an applied filter, and \fBunknown\fR for a method that is invoked as part of unknown method handling), a word giving the name of the particular method invoked (which is always the same as \fImethod\fR for the \fBmethod\fR type, and .QW \fBunknown\fR for the \fBunknown\fR type), a word giving the fully qualified name of the class that defined the method, and a word describing the type of method implementation (see \fBinfo class methodtype\fR). .RS .PP Note that there is no inspection of whether the method implementations actually use \fBnext\fR to transfer control along the call chain. .RE .VE 8.6 .TP \fBinfo class constructor\fI class\fR .VS 8.6 This subcommand returns a description of the definition of the constructor of class \fIclass\fR. The definition is described as a two element list; the first element is the list of arguments to the constructor in a form suitable for passing to another call to \fBproc\fR or a method definition, and the second element is the body of the constructor. If no constructor is present, this returns the empty list. .VE 8.6 .TP \fBinfo class definition\fI class method\fR .VS 8.6 This subcommand returns a description of the definition of the method named \fImethod\fR of class \fIclass\fR. The definition is described as a two element list; the first element is the list of arguments to the method in a form suitable for passing to another call to \fBproc\fR or a method definition, and the second element is the body of the method. .VE 8.6 .TP \fBinfo class destructor\fI class\fR .VS 8.6 This subcommand returns the body of the destructor of class \fIclass\fR. If no destructor is present, this returns the empty string. .VE 8.6 .TP \fBinfo class filters\fI class\fR .VS 8.6 This subcommand returns the list of filter methods set on the class. .VE 8.6 .TP \fBinfo class forward\fI class method\fR .VS 8.6 This subcommand returns the argument list for the method forwarding called \fImethod\fR that is set on the class called \fIclass\fR. .VE 8.6 .TP \fBinfo class instances\fI class\fR ?\fIpattern\fR? .VS 8.6 This subcommand returns a list of instances of class \fIclass\fR. If the optional \fIpattern\fR argument is present, it constrains the list of returned instances to those that match it according to the rules of \fBstring match\fR. .VE 8.6 .TP \fBinfo class methods\fI class\fR ?\fIoptions...\fR? .VS 8.6 This subcommand returns a list of all public (i.e. exported) methods of the class called \fIclass\fR. Any of the following \fIoption\fRs may be specified, controlling exactly which method names are returned: .RS .VE 8.6 .TP \fB\-all\fR .VS 8.6 If the \fB\-all\fR flag is given, the list of methods will include those methods defined not just by the class, but also by the class's superclasses and mixins. .VE 8.6 .TP \fB\-private\fR .VS 8.6 If the \fB\-private\fR flag is given, the list of methods will also include the private (i.e. non-exported) methods of the class (and superclasses and mixins, if \fB\-all\fR is also given). .RE .VE 8.6 .TP \fBinfo class methodtype\fI class method\fR .VS 8.6 This subcommand returns a description of the type of implementation used for the method named \fImethod\fR of class \fIclass\fR. When the result is \fBmethod\fR, further information can be discovered with \fBinfo class definition\fR, and when the result is \fBforward\fR, further information can be discovered with \fBinfo class forward\fR. .VE 8.6 .TP \fBinfo class mixins\fI class\fR .VS 8.6 This subcommand returns a list of all classes that have been mixed into the class named \fIclass\fR. .VE 8.6 .TP \fBinfo class subclasses\fI class\fR ?\fIpattern\fR? .VS 8.6 This subcommand returns a list of direct subclasses of class \fIclass\fR. If the optional \fIpattern\fR argument is present, it constrains the list of returned classes to those that match it according to the rules of \fBstring match\fR. .VE 8.6 .TP \fBinfo class superclasses\fI class\fR .VS 8.6 This subcommand returns a list of direct superclasses of class \fIclass\fR in inheritance precedence order. .VE 8.6 .TP \fBinfo class variables\fI class\fR .VS 8.6 This subcommand returns a list of all variables that have been declared for the class named \fIclass\fR (i.e. that are automatically present in the class's methods, constructor and destructor). .SS "OBJECT INTROSPECTION" .PP The following \fIsubcommand\fR values are supported by \fBinfo object\fR: .VE 8.6 .TP \fBinfo object call\fI object method\fR .VS 8.6 Returns a description of the method implementations that are used to provide \fIobject\fR's implementation of \fImethod\fR. This consists of a list of lists of four elements, where each sublist consists of a word that describes the general type of method implementation (being one of \fBmethod\fR for an ordinary method, \fBfilter\fR for an applied filter, and \fBunknown\fR for a method that is invoked as part of unknown method handling), a word giving the name of the particular method invoked (which is always the same as \fImethod\fR for the \fBmethod\fR type, and .QW \fBunknown\fR for the \fBunknown\fR type), a word giving what defined the method (the fully qualified name of the class, or the literal string \fBobject\fR if the method implementation is on an instance), and a word describing the type of method implementation (see \fBinfo object methodtype\fR). .RS .PP Note that there is no inspection of whether the method implementations actually use \fBnext\fR to transfer control along the call chain. .RE .VE 8.6 .TP \fBinfo object class\fI object\fR ?\fIclassName\fR? .VS 8.6 If \fIclassName\fR is unspecified, this subcommand returns class of the \fIobject\fR object. If \fIclassName\fR is present, this subcommand returns a boolean value indicating whether the \fIobject\fR is of that class. .VE 8.6 .TP \fBinfo object definition\fI object method\fR .VS 8.6 This subcommand returns a description of the definition of the method named \fImethod\fR of object \fIobject\fR. The definition is described as a two element list; the first element is the list of arguments to the method in a form suitable for passing to another call to \fBproc\fR or a method definition, and the second element is the body of the method. .VE 8.6 .TP \fBinfo object filters\fI object\fR .VS 8.6 This subcommand returns the list of filter methods set on the object. .VE 8.6 .TP \fBinfo object forward\fI object method\fR .VS 8.6 This subcommand returns the argument list for the method forwarding called \fImethod\fR that is set on the object called \fIobject\fR. .VE 8.6 .TP \fBinfo object isa\fI category object\fR ?\fIarg\fR? .VS 8.6 This subcommand tests whether an object belongs to a particular category, returning a boolean value that indicates whether the \fIobject\fR argument meets the criteria for the category. The supported categories are: .VE 8.6 .RS .TP \fBinfo object isa class\fI object\fR .VS 8.6 This returns whether \fIobject\fR is a class (i.e. an instance of \fBoo::class\fR or one of its subclasses). .VE 8.6 .TP \fBinfo object isa metaclass\fI object\fR .VS 8.6 This returns whether \fIobject\fR is a class that can manufacture classes (i.e. is \fBoo::class\fR or a subclass of it). .VE 8.6 .TP \fBinfo object isa mixin\fI object class\fR .VS 8.6 This returns whether \fIclass\fR is directly mixed into \fIobject\fR. .VE 8.6 .TP \fBinfo object isa object\fI object\fR .VS 8.6 This returns whether \fIobject\fR really is an object. .VE 8.6 .TP \fBinfo object isa typeof\fI object class\fR .VS 8.6 This returns whether \fIclass\fR is the type of \fIobject\fR (i.e. whether \fIobject\fR is an instance of \fIclass\fR or one of its subclasses, whether direct or indirect). .RE .VE 8.6 .TP \fBinfo object methods\fI object\fR ?\fIoption...\fR? .VS 8.6 This subcommand returns a list of all public (i.e. exported) methods of the object called \fIobject\fR. Any of the following \fIoption\fRs may be specified, controlling exactly which method names are returned: .RS .VE 8.6 .TP \fB\-all\fR .VS 8.6 If the \fB\-all\fR flag is given, the list of methods will include those methods defined not just by the object, but also by the object's class and mixins, plus the superclasses of those classes. .VE 8.6 .TP \fB\-private\fR .VS 8.6 If the \fB\-private\fR flag is given, the list of methods will also include the private (i.e. non-exported) methods of the object (and classes, if \fB\-all\fR is also given). .RE .VE 8.6 .TP \fBinfo object methodtype\fI object method\fR .VS 8.6 This subcommand returns a description of the type of implementation used for the method named \fImethod\fR of object \fIobject\fR. When the result is \fBmethod\fR, further information can be discovered with \fBinfo object definition\fR, and when the result is \fBforward\fR, further information can be discovered with \fBinfo object forward\fR. .VE 8.6 .TP \fBinfo object mixins\fI object\fR .VS 8.6 This subcommand returns a list of all classes that have been mixed into the object named \fIobject\fR. .VE 8.6 .TP \fBinfo object namespace\fI object\fR .VS 8.6 This subcommand returns the name of the internal namespace of the object named \fIobject\fR. .VE 8.6 .TP \fBinfo object variables\fI object\fR .VS 8.6 This subcommand returns a list of all variables that have been declared for the object named \fIobject\fR (i.e. that are automatically present in the object's methods). .VE 8.6 .TP \fBinfo object vars\fI object\fR ?\fIpattern\fR? .VS 8.6 This subcommand returns a list of all variables in the private namespace of the object named \fIobject\fR. If the optional \fIpattern\fR argument is given, it is a filter (in the syntax of a \fBstring match\fR glob pattern) that constrains the list of variables returned. Note that this is different from the list returned by \fBinfo object variables\fR; that can include variables that are currently unset, whereas this can include variables that are not automatically included by any of \fIobject\fR's methods (or those of its class, superclasses or mixins). .VE 8.6 .SH EXAMPLES .PP This command prints out a procedure suitable for saving in a Tcl script: .PP .CS proc printProc {procName} { set result [list proc $procName] set formals {} foreach var [\fBinfo args\fR $procName] { if {[\fBinfo default\fR $procName $var def]} { lappend formals [list $var $def] } else { # Still need the list-quoting because variable # names may properly contain spaces. lappend formals [list $var] } } puts [lappend result $formals [\fBinfo body\fR $procName]] } .CE .SS "EXAMPLES WITH OBJECTS" .VS 8.6 .PP Every object necessarily knows what its class is; this information is trivially extractable through introspection: .PP .CS oo::class create c c create o puts [\fBinfo object class\fR o] \fI\(-> prints "::c"\fR puts [\fBinfo object class\fR c] \fI\(-> prints "::oo::class"\fR .CE .PP The introspection capabilities can be used to discover what class implements a method and get how it is defined. This procedure illustrates how: .PP .CS proc getDef {obj method} { foreach inf [\fBinfo object call\fR $obj $method] { lassign $inf calltype name locus methodtype # Assume no forwards or filters, and hence no $calltype # or $methodtype checks... if {$locus eq "object"} { return [\fBinfo object definition\fR $obj $name] } else { return [\fBinfo class definition\fR $locus $name] } } error "no definition for $method" } .CE .PP This is an alternate way of looking up the definition; it is implemented by manually scanning the list of methods up the inheritance tree. This code assumes that only single inheritance is in use, and that there is no complex use of mixed-in classes (in such cases, using \fBinfo object call\fR as above is the simplest way of doing this by far): .PP .CS proc getDef {obj method} { if {$method in [\fBinfo object methods\fR $obj]} { # Assume no forwards return [\fBinfo object definition\fR $obj $method] } set cls [\fBinfo object class\fR $obj] while {$method ni [\fBinfo class methods\fR $cls]} { # Assume the simple case set cls [lindex [\fBinfo class superclass\fR $cls] 0] if {$cls eq ""} { error "no definition for $method" } } # Assume no forwards return [\fBinfo class definition\fR $cls $method] } .CE .VE 8.6 .SH "SEE ALSO" .VS 8.6 global(n), oo::class(n), oo::define(n), oo::object(n), proc(n), self(n), .VE 8.6 tcl_library(n), tcl_patchLevel(n), tcl_version(n) .SH KEYWORDS command, information, interpreter, introspection, level, namespace, .VS 8.6 object, .VE 8.6 procedure, variable '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/AppInit.30000644000175000017500000000567212663660065013776 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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_AppInit 3 7.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_AppInit \- perform application-specific initialization .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_AppInit\fR(\fIinterp\fR) .SH ARGUMENTS .AS Tcl_Interp *interp .AP Tcl_Interp *interp in Interpreter for the application. .BE .SH DESCRIPTION .PP \fBTcl_AppInit\fR is a .QW hook procedure that is invoked by the main programs for Tcl applications such as \fBtclsh\fR and \fBwish\fR. Its purpose is to allow new Tcl applications to be created without modifying the main programs provided as part of Tcl and Tk. To create a new application you write a new version of \fBTcl_AppInit\fR to replace the default version provided by Tcl, then link your new \fBTcl_AppInit\fR with the Tcl library. .PP \fBTcl_AppInit\fR is invoked by \fBTcl_Main\fR and \fBTk_Main\fR after their own initialization and before entering the main loop to process commands. Here are some examples of things that \fBTcl_AppInit\fR might do: .IP [1] Call initialization procedures for various packages used by the application. Each initialization procedure adds new commands to \fIinterp\fR for its package and performs other package-specific initialization. .IP [2] Process command-line arguments, which can be accessed from the Tcl variables \fBargv\fR and \fBargv0\fR in \fIinterp\fR. .IP [3] Invoke a startup script to initialize the application. .IP [4] Use the routines \fBTcl_SetStartupScript\fR and \fBTcl_GetStartupScript\fR to set or query the file and encoding that the active \fBTcl_Main\fR or \fBTk_Main\fR routine will use as a startup script. .LP \fBTcl_AppInit\fR returns \fBTCL_OK\fR or \fBTCL_ERROR\fR. If it returns \fBTCL_ERROR\fR then it must leave an error message in for the interpreter's result; otherwise the result is ignored. .PP In addition to \fBTcl_AppInit\fR, your application should also contain a procedure \fBmain\fR that calls \fBTcl_Main\fR as follows: .PP .CS Tcl_Main(argc, argv, Tcl_AppInit); .CE .PP The third argument to \fBTcl_Main\fR gives the address of the application-specific initialization procedure to invoke. This means that you do not have to use the name \fBTcl_AppInit\fR for the procedure, but in practice the name is nearly always \fBTcl_AppInit\fR (in versions before Tcl 7.4 the name \fBTcl_AppInit\fR was implicit; there was no way to specify the procedure explicitly). The best way to get started is to make a copy of the file \fBtclAppInit.c\fR from the Tcl library or source directory. It already contains a \fBmain\fR procedure and a template for \fBTcl_AppInit\fR that you can modify for your application. .SH "SEE ALSO" Tcl_Main(3) .SH KEYWORDS application, argument, command, initialization, interpreter tcl8.6.5/doc/proc.n0000644000175000017500000001057112663660065013462 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 proc n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME proc \- Create a Tcl procedure .SH SYNOPSIS \fBproc \fIname args body\fR .BE .SH DESCRIPTION .PP The \fBproc\fR command creates a new Tcl procedure named \fIname\fR, replacing any existing command or procedure there may have been by that name. Whenever the new command is invoked, the contents of \fIbody\fR will be executed by the Tcl interpreter. Normally, \fIname\fR is unqualified (does not include the names of any containing namespaces), and the new procedure is created in the current namespace. If \fIname\fR includes any namespace qualifiers, the procedure is created in the specified namespace. \fIArgs\fR specifies the formal arguments to the procedure. It consists of a list, possibly empty, each of whose elements specifies one argument. Each argument specifier is also a list with either one or two fields. If there is only a single field in the specifier then it is the name of the argument; if there are two fields, then the first is the argument name and the second is its default value. Arguments with default values that are followed by non-defaulted arguments become required arguments. In 8.6 this will be considered an error. .PP When \fIname\fR is invoked a local variable will be created for each of the formal arguments to the procedure; its value will be the value of corresponding argument in the invoking command or the argument's default value. Actual arguments are assigned to formal arguments strictly in order. Arguments with default values need not be specified in a procedure invocation. However, there must be enough actual arguments for all the formal arguments that do not have defaults, and there must not be any extra actual arguments. Arguments with default values that are followed by non-defaulted arguments become required arguments (in 8.6 it will be considered an error). There is one special case to permit procedures with variable numbers of arguments. If the last formal argument has the name \fBargs\fR, then a call to the procedure may contain more actual arguments than the procedure has formal arguments. In this case, all of the actual arguments starting at the one that would be assigned to \fBargs\fR are combined into a list (as if the \fBlist\fR command had been used); this combined value is assigned to the local variable \fBargs\fR. .PP When \fIbody\fR is being executed, variable names normally refer to local variables, which are created automatically when referenced and deleted when the procedure returns. One local variable is automatically created for each of the procedure's arguments. Other variables can only be accessed by invoking one of the \fBglobal\fR, \fBvariable\fR, \fBupvar\fR or \fBnamespace upvar\fR commands. The current namespace when \fIbody\fR is executed will be the namespace that the procedure's name exists in, which will be the namespace that it was created in unless it has been changed with \fBrename\fR. '\" We may change this! It makes [variable] unstable when renamed and is '\" frankly pretty crazy, but doing it right is harder than it looks. .PP The \fBproc\fR command returns an empty string. When a procedure is invoked, the procedure's return value is the value specified in a \fBreturn\fR command. If the procedure does not execute an explicit \fBreturn\fR, then its return value is the value of the last command executed in the procedure's body. If an error occurs while executing the procedure body, then the procedure-as-a-whole will return that same error. .SH EXAMPLES .PP This is a procedure that accepts arbitrarily many arguments and prints them out, one by one. .PP .CS \fBproc\fR printArguments args { foreach arg $args { puts $arg } } .CE .PP This procedure is a bit like the \fBincr\fR command, except it multiplies the contents of the named variable by the value, which defaults to \fB2\fR: .PP .CS \fBproc\fR mult {varName {multiplier 2}} { upvar 1 $varName var set var [expr {$var * $multiplier}] } .CE .SH "SEE ALSO" info(n), unknown(n) .SH KEYWORDS argument, procedure '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/encoding.n0000644000175000017500000001073012663660065014302 0ustar sergeisergei'\" '\" Copyright (c) 1998 by Scriptics Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH encoding n "8.1" Tcl "Tcl Built-In Commands" .so man.macros .BS .SH NAME encoding \- Manipulate encodings .SH SYNOPSIS \fBencoding \fIoption\fR ?\fIarg arg ...\fR? .BE .SH INTRODUCTION .PP Strings in Tcl are logically a sequence of 16-bit Unicode characters. These strings are represented in memory as a sequence of bytes that may be in one of several encodings: modified UTF\-8 (which uses 1 to 3 bytes per character), 16-bit .QW Unicode (which uses 2 bytes per character, with an endianness that is dependent on the host architecture), and binary (which uses a single byte per character but only handles a restricted range of characters). Tcl does not guarantee to always use the same encoding for the same string. .PP Different operating system interfaces or applications may generate strings in other encodings such as Shift\-JIS. The \fBencoding\fR command helps to bridge the gap between Unicode and these other formats. .SH DESCRIPTION .PP Performs one of several encoding related operations, depending on \fIoption\fR. The legal \fIoption\fRs are: .TP \fBencoding convertfrom\fR ?\fIencoding\fR? \fIdata\fR . Convert \fIdata\fR to Unicode from the specified \fIencoding\fR. The characters in \fIdata\fR are treated as binary data where the lower 8-bits of each character is taken as a single byte. The resulting sequence of bytes is treated as a string in the specified \fIencoding\fR. If \fIencoding\fR is not specified, the current system encoding is used. .TP \fBencoding convertto\fR ?\fIencoding\fR? \fIstring\fR . Convert \fIstring\fR from Unicode to the specified \fIencoding\fR. The result is a sequence of bytes that represents the converted string. Each byte is stored in the lower 8-bits of a Unicode character (indeed, the resulting string is a binary string as far as Tcl is concerned, at least initially). If \fIencoding\fR is not specified, the current system encoding is used. .TP \fBencoding dirs\fR ?\fIdirectoryList\fR? . Tcl can load encoding data files from the file system that describe additional encodings for it to work with. This command sets the search path for \fB*.enc\fR encoding data files to the list of directories \fIdirectoryList\fR. If \fIdirectoryList\fR is omitted then the command returns the current list of directories that make up the search path. It is an error for \fIdirectoryList\fR to not be a valid list. If, when a search for an encoding data file is happening, an element in \fIdirectoryList\fR does not refer to a readable, searchable directory, that element is ignored. .TP \fBencoding names\fR . Returns a list containing the names of all of the encodings that are currently available. The encodings .QW utf-8 and .QW iso8859-1 are guaranteed to be present in the list. .TP \fBencoding system\fR ?\fIencoding\fR? . Set the system encoding to \fIencoding\fR. If \fIencoding\fR is omitted then the command returns the current system encoding. The system encoding is used whenever Tcl passes strings to system calls. .SH EXAMPLE .PP It is common practice to write script files using a text editor that produces output in the euc-jp encoding, which represents the ASCII characters as singe bytes and Japanese characters as two bytes. This makes it easy to embed literal strings that correspond to non-ASCII characters by simply typing the strings in place in the script. However, because the \fBsource\fR command always reads files using the current system encoding, Tcl will only source such files correctly when the encoding used to write the file is the same. This tends not to be true in an internationalized setting. For example, if such a file was sourced in North America (where the ISO8859\-1 is normally used), each byte in the file would be treated as a separate character that maps to the 00 page in Unicode. The resulting Tcl strings will not contain the expected Japanese characters. Instead, they will contain a sequence of Latin-1 characters that correspond to the bytes of the original string. The \fBencoding\fR command can be used to convert this string to the expected Japanese Unicode characters. For example, .PP .CS set s [\fBencoding convertfrom\fR euc-jp "\exA4\exCF"] .CE .PP would return the Unicode string .QW "\eu306F" , which is the Hiragana letter HA. .SH "SEE ALSO" Tcl_GetEncoding(3) .SH KEYWORDS encoding, unicode .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/catch.n0000644000175000017500000001300112663660065013570 0ustar sergeisergei'\" '\" Copyright (c) 1993-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Contributions from Don Porter, NIST, 2003. (not subject to US copyright) '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH catch n "8.5" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME catch \- Evaluate script and trap exceptional returns .SH SYNOPSIS \fBcatch\fI script \fR?\fIresultVarName\fR? ?\fIoptionsVarName\fR? .BE .SH DESCRIPTION .PP The \fBcatch\fR command may be used to prevent errors from aborting command interpretation. The \fBcatch\fR command calls the Tcl interpreter recursively to execute \fIscript\fR, and always returns without raising an error, regardless of any errors that might occur while executing \fIscript\fR. .PP If \fIscript\fR raises an error, \fBcatch\fR will return a non-zero integer value corresponding to the exceptional return code returned by evaluation of \fIscript\fR. Tcl defines the normal return code from script evaluation to be zero (0), or \fBTCL_OK\fR. Tcl also defines four exceptional return codes: 1 (\fBTCL_ERROR\fR), 2 (\fBTCL_RETURN\fR), 3 (\fBTCL_BREAK\fR), and 4 (\fBTCL_CONTINUE\fR). Errors during evaluation of a script are indicated by a return code of \fBTCL_ERROR\fR. The other exceptional return codes are returned by the \fBreturn\fR, \fBbreak\fR, and \fBcontinue\fR commands and in other special situations as documented. Tcl packages can define new commands that return other integer values as return codes as well, and scripts that make use of the \fBreturn \-code\fR command can also have return codes other than the five defined by Tcl. .PP If the \fIresultVarName\fR argument is given, then the variable it names is set to the result of the script evaluation. When the return code from the script is 1 (\fBTCL_ERROR\fR), the value stored in \fIresultVarName\fR is an error message. When the return code from the script is 0 (\fBTCL_OK\fR), the value stored in \fIresultVarName\fR is the value returned from \fIscript\fR. .PP If the \fIoptionsVarName\fR argument is given, then the variable it names is set to a dictionary of return options returned by evaluation of \fIscript\fR. Tcl specifies two entries that are always defined in the dictionary: \fB\-code\fR and \fB\-level\fR. When the return code from evaluation of \fIscript\fR is not \fBTCL_RETURN\fR, the value of the \fB\-level\fR entry will be 0, and the value of the \fB\-code\fR entry will be the same as the return code. Only when the return code is \fBTCL_RETURN\fR will the values of the \fB\-level\fR and \fB\-code\fR entries be something else, as further described in the documentation for the \fBreturn\fR command. .PP When the return code from evaluation of \fIscript\fR is \fBTCL_ERROR\fR, four additional entries are defined in the dictionary of return options stored in \fIoptionsVarName\fR: \fB\-errorinfo\fR, \fB\-errorcode\fR, \fB\-errorline\fR, and .VS 8.6 \fB\-errorstack\fR. .VE 8.6 The value of the \fB\-errorinfo\fR entry is a formatted stack trace containing more information about the context in which the error happened. The formatted stack trace is meant to be read by a person. The value of the \fB\-errorcode\fR entry is additional information about the error stored as a list. The \fB\-errorcode\fR value is meant to be further processed by programs, and may not be particularly readable by people. The value of the \fB\-errorline\fR entry is an integer indicating which line of \fIscript\fR was being evaluated when the error occurred. .VS 8.6 The value of the \fB\-errorstack\fR entry is an even-sized list made of token-parameter pairs accumulated while unwinding the stack. The token may be .QW \fBCALL\fR , in which case the parameter is a list made of the proc name and arguments at the corresponding level; or it may be .QW \fBUP\fR , in which case the parameter is the relative level (as in \fBuplevel\fR) of the previous \fBCALL\fR. The salient differences with respect to \fB\-errorinfo\fR are that: .IP [1] it is a machine-readable form that is amenable to processing with [\fBforeach\fR {tok prm} ...], .IP [2] it contains the true (substituted) values passed to the functions, instead of the static text of the calling sites, and .IP [3] it is coarser-grained, with only one element per stack frame (like procs; no separate elements for \fBforeach\fR constructs for example). .VE 8.6 .PP The values of the \fB\-errorinfo\fR and \fB\-errorcode\fR entries of the most recent error are also available as values of the global variables \fB::errorInfo\fR and \fB::errorCode\fR respectively. .VS 8.6 The value of the \fB\-errorstack\fR entry surfaces as \fBinfo errorstack\fR. .VE 8.6 .PP Tcl packages may provide commands that set other entries in the dictionary of return options, and the \fBreturn\fR command may be used by scripts to set return options in addition to those defined above. .SH EXAMPLES .PP The \fBcatch\fR command may be used in an \fBif\fR to branch based on the success of a script. .PP .CS if { [\fBcatch\fR {open $someFile w} fid] } { puts stderr "Could not open $someFile for writing\en$fid" exit 1 } .CE .PP There are more complex examples of \fBcatch\fR usage in the documentation for the \fBreturn\fR command. .SH "SEE ALSO" break(n), continue(n), dict(n), error(n), errorCode(n), errorInfo(n), info(n), return(n) .SH KEYWORDS catch, error, exception '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/safe.n0000644000175000017500000003624112663660065013437 0ustar sergeisergei'\" '\" 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 "Safe Tcl" n 8.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME safe \- Creating and manipulating safe interpreters .SH SYNOPSIS \fB::safe::interpCreate\fR ?\fIslave\fR? ?\fIoptions...\fR? .sp \fB::safe::interpInit\fR \fIslave\fR ?\fIoptions...\fR? .sp \fB::safe::interpConfigure\fR \fIslave\fR ?\fIoptions...\fR? .sp \fB::safe::interpDelete\fR \fIslave\fR .sp \fB::safe::interpAddToAccessPath\fR \fIslave\fR \fIdirectory\fR .sp \fB::safe::interpFindInAccessPath\fR \fIslave\fR \fIdirectory\fR .sp \fB::safe::setLogCmd\fR ?\fIcmd arg...\fR? .SS OPTIONS .PP ?\fB\-accessPath\fR \fIpathList\fR? ?\fB\-statics\fR \fIboolean\fR? ?\fB\-noStatics\fR? ?\fB\-nested\fR \fIboolean\fR? ?\fB\-nestedLoadOk\fR? ?\fB\-deleteHook\fR \fIscript\fR? .BE .SH DESCRIPTION Safe Tcl is a mechanism for executing untrusted Tcl scripts safely and for providing mediated access by such scripts to potentially dangerous functionality. .PP Safe Tcl ensures that untrusted Tcl scripts cannot harm the hosting application. It prevents integrity and privacy attacks. Untrusted Tcl scripts are prevented from corrupting the state of the hosting application or computer. Untrusted scripts are also prevented from disclosing information stored on the hosting computer or in the hosting application to any party. .PP Safe Tcl allows a master interpreter to create safe, restricted interpreters that contain a set of predefined aliases for the \fBsource\fR, \fBload\fR, \fBfile\fR, \fBencoding\fR, and \fBexit\fR commands and are able to use the auto-loading and package mechanisms. .PP No knowledge of the file system structure is leaked to the safe interpreter, because it has access only to a virtualized path containing tokens. When the safe interpreter requests to source a file, it uses the token in the virtual path as part of the file name to source; the master interpreter transparently translates the token into a real directory name and executes the requested operation (see the section \fBSECURITY\fR below for details). Different levels of security can be selected by using the optional flags of the commands described below. .PP All commands provided in the master interpreter by Safe Tcl reside in the \fBsafe\fR namespace. .SH COMMANDS The following commands are provided in the master interpreter: .TP \fB::safe::interpCreate\fR ?\fIslave\fR? ?\fIoptions...\fR? Creates a safe interpreter, installs the aliases described in the section \fBALIASES\fR and initializes the auto-loading and package mechanism as specified by the supplied \fIoptions\fR. See the \fBOPTIONS\fR section below for a description of the optional arguments. If the \fIslave\fR argument is omitted, a name will be generated. \fB::safe::interpCreate\fR always returns the interpreter name. .TP \fB::safe::interpInit\fR \fIslave\fR ?\fIoptions...\fR? This command is similar to \fBinterpCreate\fR except it that does not create the safe interpreter. \fIslave\fR must have been created by some other means, like \fBinterp create\fR \fB\-safe\fR. .TP \fB::safe::interpConfigure\fR \fIslave\fR ?\fIoptions...\fR? If no \fIoptions\fR are given, returns the settings for all options for the named safe interpreter as a list of options and their current values for that \fIslave\fR. If a single additional argument is provided, it will return a list of 2 elements \fIname\fR and \fIvalue\fR where \fIname\fR is the full name of that option and \fIvalue\fR the current value for that option and the \fIslave\fR. If more than two additional arguments are provided, it will reconfigure the safe interpreter and change each and only the provided options. See the section on \fBOPTIONS\fR below for options description. Example of use: .RS .PP .CS # Create new interp with the same configuration as "$i0": set i1 [safe::interpCreate {*}[safe::interpConfigure $i0]] # Get the current deleteHook set dh [safe::interpConfigure $i0 \-del] # Change (only) the statics loading ok attribute of an # interp and its deleteHook (leaving the rest unchanged): safe::interpConfigure $i0 \-delete {foo bar} \-statics 0 .CE .RE .TP \fB::safe::interpDelete\fR \fIslave\fR Deletes the safe interpreter and cleans up the corresponding master interpreter data structures. If a \fIdeleteHook\fR script was specified for this interpreter it is evaluated before the interpreter is deleted, with the name of the interpreter as an additional argument. .TP \fB::safe::interpFindInAccessPath\fR \fIslave\fR \fIdirectory\fR This command finds and returns the token for the real directory \fIdirectory\fR in the safe interpreter's current virtual access path. It generates an error if the directory is not found. Example of use: .RS .PP .CS $slave eval [list set tk_library \e [::safe::interpFindInAccessPath $name $tk_library]] .CE .RE .TP \fB::safe::interpAddToAccessPath\fR \fIslave\fR \fIdirectory\fR This command adds \fIdirectory\fR to the virtual path maintained for the safe interpreter in the master, and returns the token that can be used in the safe interpreter to obtain access to files in that directory. If the directory is already in the virtual path, it only returns the token without adding the directory to the virtual path again. Example of use: .RS .PP .CS $slave eval [list set tk_library \e [::safe::interpAddToAccessPath $name $tk_library]] .CE .RE .TP \fB::safe::setLogCmd\fR ?\fIcmd arg...\fR? This command installs a script that will be called when interesting life cycle events occur for a safe interpreter. When called with no arguments, it returns the currently installed script. When called with one argument, an empty string, the currently installed script is removed and logging is turned off. The script will be invoked with one additional argument, a string describing the event of interest. The main purpose is to help in debugging safe interpreters. Using this facility you can get complete error messages while the safe interpreter gets only generic error messages. This prevents a safe interpreter from seeing messages about failures and other events that might contain sensitive information such as real directory names. .RS .PP Example of use: .PP .CS ::safe::setLogCmd puts stderr .CE .PP Below is the output of a sample session in which a safe interpreter attempted to source a file not found in its virtual access path. Note that the safe interpreter only received an error message saying that the file was not found: .PP .CS NOTICE for slave interp10 : Created NOTICE for slave interp10 : Setting accessPath=(/foo/bar) staticsok=1 nestedok=0 deletehook=() NOTICE for slave interp10 : auto_path in interp10 has been set to {$p(:0:)} ERROR for slave interp10 : /foo/bar/init.tcl: no such file or directory .CE .RE .SS OPTIONS The following options are common to \fB::safe::interpCreate\fR, \fB::safe::interpInit\fR, and \fB::safe::interpConfigure\fR. Any option name can be abbreviated to its minimal non-ambiguous name. Option names are not case sensitive. .TP \fB\-accessPath\fR \fIdirectoryList\fR This option sets the list of directories from which the safe interpreter can \fBsource\fR and \fBload\fR files. If this option is not specified, or if it is given as the empty list, the safe interpreter will use the same directories as its master for auto-loading. See the section \fBSECURITY\fR below for more detail about virtual paths, tokens and access control. .TP \fB\-statics\fR \fIboolean\fR This option specifies if the safe interpreter will be allowed to load statically linked packages (like \fBload {} Tk\fR). The default value is \fBtrue\fR : safe interpreters are allowed to load statically linked packages. .TP \fB\-noStatics\fR This option is a convenience shortcut for \fB\-statics false\fR and thus specifies that the safe interpreter will not be allowed to load statically linked packages. .TP \fB\-nested\fR \fIboolean\fR This option specifies if the safe interpreter will be allowed to load packages into its own sub-interpreters. The default value is \fBfalse\fR : safe interpreters are not allowed to load packages into their own sub-interpreters. .TP \fB\-nestedLoadOk\fR This option is a convenience shortcut for \fB\-nested true\fR and thus specifies the safe interpreter will be allowed to load packages into its own sub-interpreters. .TP \fB\-deleteHook\fR \fIscript\fR When this option is given a non-empty \fIscript\fR, it will be evaluated in the master with the name of the safe interpreter as an additional argument just before actually deleting the safe interpreter. Giving an empty value removes any currently installed deletion hook script for that safe interpreter. The default value (\fB{}\fR) is not to have any deletion call back. .SH ALIASES The following aliases are provided in a safe interpreter: .TP \fBsource\fR \fIfileName\fR The requested file, a Tcl source file, is sourced into the safe interpreter if it is found. The \fBsource\fR alias can only source files from directories in the virtual path for the safe interpreter. The \fBsource\fR alias requires the safe interpreter to use one of the token names in its virtual path to denote the directory in which the file to be sourced can be found. See the section on \fBSECURITY\fR for more discussion of restrictions on valid filenames. .TP \fBload\fR \fIfileName\fR The requested file, a shared object file, is dynamically loaded into the safe interpreter if it is found. The filename must contain a token name mentioned in the virtual path for the safe interpreter for it to be found successfully. Additionally, the shared object file must contain a safe entry point; see the manual page for the \fBload\fR command for more details. .TP \fBfile\fR ?\fIsubCmd args...\fR? The \fBfile\fR alias provides access to a safe subset of the subcommands of the \fBfile\fR command; it allows only \fBdirname\fR, \fBjoin\fR, \fBextension\fR, \fBroot\fR, \fBtail\fR, \fBpathname\fR and \fBsplit\fR subcommands. For more details on what these subcommands do see the manual page for the \fBfile\fR command. .TP \fBencoding\fR ?\fIsubCmd args...\fR? The \fBencoding\fR alias provides access to a safe subset of the subcommands of the \fBencoding\fR command; it disallows setting of the system encoding, but allows all other subcommands including \fBsystem\fR to check the current encoding. .TP \fBexit\fR The calling interpreter is deleted and its computation is stopped, but the Tcl process in which this interpreter exists is not terminated. .SH SECURITY Safe Tcl does not attempt to completely prevent annoyance and denial of service attacks. These forms of attack prevent the application or user from temporarily using the computer to perform useful work, for example by consuming all available CPU time or all available screen real estate. These attacks, while aggravating, are deemed to be of lesser importance in general than integrity and privacy attacks that Safe Tcl is to prevent. .PP The commands available in a safe interpreter, in addition to the safe set as defined in \fBinterp\fR manual page, are mediated aliases for \fBsource\fR, \fBload\fR, \fBexit\fR, and safe subsets of \fBfile\fR and \fBencoding\fR. The safe interpreter can also auto-load code and it can request that packages be loaded. .PP Because some of these commands access the local file system, there is a potential for information leakage about its directory structure. To prevent this, commands that take file names as arguments in a safe interpreter use tokens instead of the real directory names. These tokens are translated to the real directory name while a request to, e.g., source a file is mediated by the master interpreter. This virtual path system is maintained in the master interpreter for each safe interpreter created by \fB::safe::interpCreate\fR or initialized by \fB::safe::interpInit\fR and the path maps tokens accessible in the safe interpreter into real path names on the local file system thus preventing safe interpreters from gaining knowledge about the structure of the file system of the host on which the interpreter is executing. The only valid file names arguments for the \fBsource\fR and \fBload\fR aliases provided to the slave are path in the form of \fB[file join \fItoken filename\fB]\fR (i.e. when using the native file path formats: \fItoken\fB/\fIfilename\fR on Unix and \fItoken\fB\e\fIfilename\fR on Windows), where \fItoken\fR is representing one of the directories of the \fIaccessPath\fR list and \fIfilename\fR is one file in that directory (no sub directories access are allowed). .PP When a token is used in a safe interpreter in a request to source or load a file, the token is checked and translated to a real path name and the file to be sourced or loaded is located on the file system. The safe interpreter never gains knowledge of the actual path name under which the file is stored on the file system. .PP To further prevent potential information leakage from sensitive files that are accidentally included in the set of files that can be sourced by a safe interpreter, the \fBsource\fR alias restricts access to files meeting the following constraints: the file name must fourteen characters or shorter, must not contain more than one dot .PQ \fB.\fR "" , must end up with the extension .PQ \fB.tcl\fR or be called .PQ \fBtclIndex\fR . .PP Each element of the initial access path list will be assigned a token that will be set in the slave \fBauto_path\fR and the first element of that list will be set as the \fBtcl_library\fR for that slave. .PP If the access path argument is not given or is the empty list, the default behavior is to let the slave access the same packages as the master has access to (Or to be more precise: only packages written in Tcl (which by definition cannot be dangerous as they run in the slave interpreter) and C extensions that provides a _SafeInit entry point). For that purpose, the master's \fBauto_path\fR will be used to construct the slave access path. In order that the slave successfully loads the Tcl library files (which includes the auto-loading mechanism itself) the \fBtcl_library\fR will be added or moved to the first position if necessary, in the slave access path, so the slave \fBtcl_library\fR will be the same as the master's (its real path will still be invisible to the slave though). In order that auto-loading works the same for the slave and the master in this by default case, the first-level sub directories of each directory in the master \fBauto_path\fR will also be added (if not already included) to the slave access path. You can always specify a more restrictive path for which sub directories will never be searched by explicitly specifying your directory list with the \fB\-accessPath\fR flag instead of relying on this default mechanism. .PP When the \fIaccessPath\fR is changed after the first creation or initialization (i.e. through \fBinterpConfigure -accessPath \fR\fIlist\fR), an \fBauto_reset\fR is automatically evaluated in the safe interpreter to synchronize its \fBauto_index\fR with the new token list. .SH "SEE ALSO" interp(n), library(n), load(n), package(n), source(n), unknown(n) .SH KEYWORDS alias, auto\-loading, auto_mkindex, load, master interpreter, safe interpreter, slave interpreter, source '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/incr.n0000644000175000017500000000320012663660065013441 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 incr n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME incr \- Increment the value of a variable .SH SYNOPSIS \fBincr \fIvarName \fR?\fIincrement\fR? .BE .SH DESCRIPTION .PP Increments the value stored in the variable whose name is \fIvarName\fR. The value of the variable must be an integer. If \fIincrement\fR is supplied then its value (which must be an integer) is added to the value of variable \fIvarName\fR; otherwise 1 is added to \fIvarName\fR. The new value is stored as a decimal string in variable \fIvarName\fR and also returned as result. .PP Starting with the Tcl 8.5 release, the variable \fIvarName\fR passed to \fBincr\fR may be unset, and in that case, it will be set to the value \fIincrement\fR or to the default increment value of \fB1\fR. .SH EXAMPLES .PP Add one to the contents of the variable \fIx\fR: .PP .CS \fBincr\fR x .CE .PP Add 42 to the contents of the variable \fIx\fR: .PP .CS \fBincr\fR x 42 .CE .PP Add the contents of the variable \fIy\fR to the contents of the variable \fIx\fR: .PP .CS \fBincr\fR x $y .CE .PP Add nothing at all to the variable \fIx\fR (often useful for checking whether an argument to a procedure is actually integral and generating an error if it is not): .PP .CS \fBincr\fR x 0 .CE .SH "SEE ALSO" expr(n), set(n) .SH KEYWORDS add, increment, variable, value tcl8.6.5/doc/CrtFileHdlr.30000644000175000017500000000702312663660065014564 0ustar sergeisergei'\" '\" Copyright (c) 1990-1994 The Regents of the University of California. '\" Copyright (c) 1994-1997 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_CreateFileHandler 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CreateFileHandler, Tcl_DeleteFileHandler \- associate procedure callbacks with files or devices (Unix only) .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_CreateFileHandler\fR(\fIfd, mask, proc, clientData\fR) .sp \fBTcl_DeleteFileHandler\fR(\fIfd\fR) .SH ARGUMENTS .AS Tcl_FileProc clientData .AP int fd in Unix file descriptor for an open file or device. .AP int mask in Conditions under which \fIproc\fR should be called: OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR, and \fBTCL_EXCEPTION\fR. May be set to 0 to temporarily disable a handler. .AP Tcl_FileProc *proc in Procedure to invoke whenever the file or device indicated by \fIfile\fR meets the conditions specified by \fImask\fR. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR. .BE .SH DESCRIPTION .PP \fBTcl_CreateFileHandler\fR arranges for \fIproc\fR to be invoked in the future whenever I/O becomes possible on a file or an exceptional condition exists for the file. The file is indicated by \fIfd\fR, and the conditions of interest are indicated by \fImask\fR. For example, if \fImask\fR is \fBTCL_READABLE\fR, \fIproc\fR will be called when the file is readable. The callback to \fIproc\fR is made by \fBTcl_DoOneEvent\fR, so \fBTcl_CreateFileHandler\fR is only useful in programs that dispatch events through \fBTcl_DoOneEvent\fR or through Tcl commands such as \fBvwait\fR. .PP \fIProc\fR should have arguments and result that match the type \fBTcl_FileProc\fR: .PP .CS typedef void \fBTcl_FileProc\fR( ClientData \fIclientData\fR, int \fImask\fR); .CE .PP The \fIclientData\fR parameter to \fIproc\fR is a copy of the \fIclientData\fR argument given to \fBTcl_CreateFileHandler\fR when the callback was created. Typically, \fIclientData\fR points to a data structure containing application-specific information about the file. \fIMask\fR is an integer mask indicating which of the requested conditions actually exists for the file; it will contain a subset of the bits in the \fImask\fR argument to \fBTcl_CreateFileHandler\fR. .PP There may exist only one handler for a given file at a given time. If \fBTcl_CreateFileHandler\fR is called when a handler already exists for \fIfd\fR, then the new callback replaces the information that was previously recorded. .PP \fBTcl_DeleteFileHandler\fR may be called to delete the file handler for \fIfd\fR; if no handler exists for the file given by \fIfd\fR then the procedure has no effect. .PP The purpose of file handlers is to enable an application to respond to events while waiting for files to become ready for I/O. For this to work correctly, the application may need to use non-blocking I/O operations on the files for which handlers are declared. Otherwise the application may block if it reads or writes too much data; while waiting for the I/O to complete the application will not be able to service other events. Use \fBTcl_SetChannelOption\fR with \fB\-blocking\fR to set the channel into blocking or nonblocking mode as required. .PP Note that these interfaces are only supported by the Unix implementation of the Tcl notifier. .SH "SEE ALSO" fileevent(n), Tcl_CreateTimerHandler(3), Tcl_DoWhenIdle(3) .SH KEYWORDS callback, file, handler tcl8.6.5/doc/PkgRequire.30000644000175000017500000000653412663660065014506 0ustar sergeisergei'\" '\" Copyright (c) 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_PkgRequire 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_PkgRequire, Tcl_PkgRequireEx, Tcl_PkgRequireProc, Tcl_PkgPresent, Tcl_PkgPresentEx, Tcl_PkgProvide, Tcl_PkgProvideEx \- package version control .SH SYNOPSIS .nf \fB#include \fR .sp const char * \fBTcl_PkgRequire\fR(\fIinterp, name, version, exact\fR) .sp const char * \fBTcl_PkgRequireEx\fR(\fIinterp, name, version, exact, clientDataPtr\fR) .sp int \fBTcl_PkgRequireProc\fR(\fIinterp, name, objc, objv, clientDataPtr\fR) .sp const char * \fBTcl_PkgPresent\fR(\fIinterp, name, version, exact\fR) .sp const char * \fBTcl_PkgPresentEx\fR(\fIinterp, name, version, exact, clientDataPtr\fR) .sp int \fBTcl_PkgProvide\fR(\fIinterp, name, version\fR) .sp int \fBTcl_PkgProvideEx\fR(\fIinterp, name, version, clientData\fR) .SH ARGUMENTS .AS void *clientDataPtr out .AP Tcl_Interp *interp in Interpreter where package is needed or available. .AP "const char" *name in Name of package. .AP "const char" *version in A version string consisting of one or more decimal numbers separated by dots. .AP int exact in Non-zero means that only the particular version specified by \fIversion\fR is acceptable. Zero means that newer versions than \fIversion\fR are also acceptable as long as they have the same major version number as \fIversion\fR. .AP "const void" *clientData in Arbitrary value to be associated with the package. .AP void *clientDataPtr out Pointer to place to store the value associated with the matching package. It is only changed if the pointer is not NULL and the function completed successfully. The storage can be any pointer type with the same size as a void pointer. .AP int objc in Number of requirements. .AP Tcl_Obj* objv[] in Array of requirements. .BE .SH DESCRIPTION .PP These procedures provide C-level interfaces to Tcl's package and version management facilities. .PP \fBTcl_PkgRequire\fR is equivalent to the \fBpackage require\fR command, \fBTcl_PkgPresent\fR is equivalent to the \fBpackage present\fR command, and \fBTcl_PkgProvide\fR is equivalent to the \fBpackage provide\fR command. .PP See the documentation for the Tcl commands for details on what these procedures do. .PP If \fBTcl_PkgPresent\fR or \fBTcl_PkgRequire\fR complete successfully they return a pointer to the version string for the version of the package that is provided in the interpreter (which may be different than \fIversion\fR); if an error occurs they return NULL and leave an error message in the interpreter's result. .PP \fBTcl_PkgProvide\fR returns \fBTCL_OK\fR if it completes successfully; if an error occurs it returns \fBTCL_ERROR\fR and leaves an error message in the interpreter's result. .PP \fBTcl_PkgProvideEx\fR, \fBTcl_PkgPresentEx\fR and \fBTcl_PkgRequireEx\fR allow the setting and retrieving of the client data associated with the package. In all other respects they are equivalent to the matching functions. .PP \fBTcl_PkgRequireProc\fR is the form of \fBpackage require\fR handling multiple requirements. The other forms are present for backward compatibility and translate their invocations to this form. .SH KEYWORDS package, present, provide, require, version .SH "SEE ALSO" package(n), Tcl_StaticPackage(3) tcl8.6.5/doc/unknown.n0000644000175000017500000001004612663660065014213 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 unknown n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME unknown \- Handle attempts to use non-existent commands .SH SYNOPSIS \fBunknown \fIcmdName \fR?\fIarg arg ...\fR? .BE .SH DESCRIPTION .PP This command is invoked by the Tcl interpreter whenever a script tries to invoke a command that does not exist. The default implementation of \fBunknown\fR is a library procedure defined when Tcl initializes an interpreter. You can override the default \fBunknown\fR to change its functionality, or you can register a new handler for individual namespaces using the \fBnamespace unknown\fR command. Note that there is no default implementation of \fBunknown\fR in a safe interpreter. .PP If the Tcl interpreter encounters a command name for which there is not a defined command (in either the current namespace, or the global namespace), then Tcl checks for the existence of an unknown handler for the current namespace. By default, this handler is a command named \fB::unknown\fR. If there is no such command, then the interpreter returns an error. If the \fBunknown\fR command exists (or a new handler has been registered for the current namespace), then it is invoked with arguments consisting of the fully-substituted name and arguments for the original non-existent command. The \fBunknown\fR command typically does things like searching through library directories for a command procedure with the name \fIcmdName\fR, or expanding abbreviated command names to full-length, or automatically executing unknown commands as sub-processes. In some cases (such as expanding abbreviations) \fBunknown\fR will change the original command slightly and then (re-)execute it. The result of the \fBunknown\fR command is used as the result for the original non-existent command. .PP The default implementation of \fBunknown\fR behaves as follows. It first calls the \fBauto_load\fR library procedure to load the command. If this succeeds, then it executes the original command with its original arguments. If the auto-load fails then \fBunknown\fR calls \fBauto_execok\fR to see if there is an executable file by the name \fIcmd\fR. If so, it invokes the Tcl \fBexec\fR command with \fIcmd\fR and all the \fIargs\fR as arguments. If \fIcmd\fR cannot be auto-executed, \fBunknown\fR checks to see if the command was invoked at top-level and outside of any script. If so, then \fBunknown\fR takes two additional steps. First, it sees if \fIcmd\fR has one of the following three forms: \fB!!\fR, \fB!\fIevent\fR, or \fB^\fIold\fB^\fInew\fR?\fB^\fR?. If so, then \fBunknown\fR carries out history substitution in the same way that \fBcsh\fR would for these constructs. Finally, \fBunknown\fR checks to see if \fIcmd\fR is a unique abbreviation for an existing Tcl command. If so, it expands the command name and executes the command with the original arguments. If none of the above efforts has been able to execute the command, \fBunknown\fR generates an error return. If the global variable \fBauto_noload\fR is defined, then the auto-load step is skipped. If the global variable \fBauto_noexec\fR is defined then the auto-exec step is skipped. Under normal circumstances the return value from \fBunknown\fR is the return value from the command that was eventually executed. .SH EXAMPLE Arrange for the \fBunknown\fR command to have its standard behavior except for first logging the fact that a command was not found: .PP .CS # Save the original one so we can chain to it rename \fBunknown\fR _original_unknown # Provide our own implementation proc \fBunknown\fR args { puts stderr "WARNING: unknown command: $args" uplevel 1 [list _original_unknown {*}$args] } .CE .SH "SEE ALSO" info(n), proc(n), interp(n), library(n), namespace(n) .SH KEYWORDS error, non-existent command, unknown tcl8.6.5/doc/unset.n0000644000175000017500000000425612663660065013660 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2000 Ajuba Solutions. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH unset n 8.4 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME unset \- Delete variables .SH SYNOPSIS \fBunset \fR?\fB\-nocomplain\fR? ?\fB\-\-\fR? ?\fIname name name ...\fR? .BE .SH DESCRIPTION .PP This command removes one or more variables. Each \fIname\fR is a variable name, specified in any of the ways acceptable to the \fBset\fR command. If a \fIname\fR refers to an element of an array then that element is removed without affecting the rest of the array. If a \fIname\fR consists of an array name with no parenthesized index, then the entire array is deleted. The \fBunset\fR command returns an empty string as result. If \fB\-nocomplain\fR is specified as the first argument, any possible errors are suppressed. The option may not be abbreviated, in order to disambiguate it from possible variable names. The option \fB\-\-\fR indicates the end of the options, and should be used if you wish to remove a variable with the same name as any of the options. If an error occurs during variable deletion, any variables after the named one causing the error are not deleted. An error can occur when the named variable does not exist, or the name refers to an array element but the variable is a scalar, or the name refers to a variable in a non-existent namespace. .SH EXAMPLE .PP Create an array containing a mapping from some numbers to their squares and remove the array elements for non-prime numbers: .PP .CS array set squares { 1 1 6 36 2 4 7 49 3 9 8 64 4 16 9 81 5 25 10 100 } puts "The squares are:" parray squares \fBunset\fR squares(1) squares(4) squares(6) \fBunset\fR squares(8) squares(9) squares(10) puts "The prime squares are:" parray squares .CE .SH "SEE ALSO" set(n), trace(n), upvar(n) .SH KEYWORDS remove, variable '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/TCL_MEM_DEBUG.30000644000175000017500000000717412663660065014457 0ustar sergeisergei'\" '\" Copyright (c) 1992-1999 Karl Lehenbauer and Mark Diekhans. '\" Copyright (c) 2000 by Scriptics Corporation. '\" All rights reserved. '\" .TH TCL_MEM_DEBUG 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME TCL_MEM_DEBUG \- Compile-time flag to enable Tcl memory debugging .BE .SH DESCRIPTION When Tcl is compiled with \fBTCL_MEM_DEBUG\fR defined, a powerful set of memory debugging aids is included in the compiled binary. This includes C and Tcl functions which can aid with debugging memory leaks, memory allocation overruns, and other memory related errors. .SH "ENABLING MEMORY DEBUGGING" .PP To enable memory debugging, Tcl should be recompiled from scratch with \fBTCL_MEM_DEBUG\fR defined (e.g. by passing the \fI\-\-enable\-symbols=mem\fR flag to the \fIconfigure\fR script when building). This will also compile in a non-stub version of \fBTcl_InitMemory\fR to add the \fBmemory\fR command to Tcl. .PP \fBTCL_MEM_DEBUG\fR must be either left defined for all modules or undefined for all modules that are going to be linked together. If they are not, link errors will occur, with either \fBTcl_DbCkfree\fR and \fBTcl_DbCkalloc\fR or \fBTcl_Alloc\fR and \fBTcl_Free\fR being undefined. .PP Once memory debugging support has been compiled into Tcl, the C functions \fBTcl_ValidateAllMemory\fR, and \fBTcl_DumpActiveMemory\fR, and the Tcl \fBmemory\fR command can be used to validate and examine memory usage. .SH "GUARD ZONES" .PP When memory debugging is enabled, whenever a call to \fBckalloc\fR is made, slightly more memory than requested is allocated so the memory debugging code can keep track of the allocated memory, and eight-byte .QW "guard zones" are placed in front of and behind the space that will be returned to the caller. (The sizes of the guard zones are defined by the C #define \fBLOW_GUARD_SIZE\fR and #define \fBHIGH_GUARD_SIZE\fR in the file \fIgeneric/tclCkalloc.c\fR \(em it can be extended if you suspect large overwrite problems, at some cost in performance.) A known pattern is written into the guard zones and, on a call to \fBckfree\fR, the guard zones of the space being freed are checked to see if either zone has been modified in any way. If one has been, the guard bytes and their new contents are identified, and a .QW "low guard failed" or .QW "high guard failed" message is issued. The .QW "guard failed" message includes the address of the memory packet and the file name and line number of the code that called \fBckfree\fR. This allows you to detect the common sorts of one-off problems, where not enough space was allocated to contain the data written, for example. .SH "DEBUGGING DIFFICULT MEMORY CORRUPTION PROBLEMS" .PP Normally, Tcl compiled with memory debugging enabled will make it easy to isolate a corruption problem. Turning on memory validation with the memory command can help isolate difficult problems. If you suspect (or know) that corruption is occurring before the Tcl interpreter comes up far enough for you to issue commands, you can set \fBMEM_VALIDATE\fR define, recompile tclCkalloc.c and rebuild Tcl. This will enable memory validation from the first call to \fBckalloc\fR, again, at a large performance impact. .PP If you are desperate and validating memory on every call to \fBckalloc\fR and \fBckfree\fR is not enough, you can explicitly call \fBTcl_ValidateAllMemory\fR directly at any point. It takes a \fIchar *\fR and an \fIint\fR which are normally the filename and line number of the caller, but they can actually be anything you want. Remember to remove the calls after you find the problem. .SH "SEE ALSO" ckalloc, memory, Tcl_ValidateAllMemory, Tcl_DumpActiveMemory .SH KEYWORDS memory, debug tcl8.6.5/doc/mathop.n0000644000175000017500000002524512663660065014013 0ustar sergeisergei.\" .\" Copyright (c) 2006-2007 Donal K. Fellows. .\" .\" See the file "license.terms" for information on usage and redistribution .\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. .\" .TH mathop n 8.5 Tcl "Tcl Mathematical Operator Commands" .so man.macros .BS .\" Note: do not modify the .SH NAME line immediately below! .SH NAME mathop \- Mathematical operators as Tcl commands .SH SYNOPSIS package require \fBTcl 8.5\fR .sp \fB::tcl::mathop::!\fR \fInumber\fR .br \fB::tcl::mathop::~\fR \fInumber\fR .br \fB::tcl::mathop::+\fR ?\fInumber\fR ...? .br \fB::tcl::mathop::\-\fR \fInumber\fR ?\fInumber\fR ...? .br \fB::tcl::mathop::*\fR ?\fInumber\fR ...? .br \fB::tcl::mathop::/\fR \fInumber\fR ?\fInumber\fR ...? .br \fB::tcl::mathop::%\fR \fInumber number\fR .br \fB::tcl::mathop::**\fR ?\fInumber\fR ...? .br \fB::tcl::mathop::&\fR ?\fInumber\fR ...? .br \fB::tcl::mathop::|\fR ?\fInumber\fR ...? .br \fB::tcl::mathop::^\fR ?\fInumber\fR ...? .br \fB::tcl::mathop::<<\fR \fInumber number\fR .br \fB::tcl::mathop::>>\fR \fInumber number\fR .br \fB::tcl::mathop::==\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::!=\fR \fIarg arg\fR .br \fB::tcl::mathop::<\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::<=\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::>=\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::>\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::eq\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::ne\fR \fIarg arg\fR .br \fB::tcl::mathop::in\fR \fIarg list\fR .br \fB::tcl::mathop::ni\fR \fIarg list\fR .sp .BE .SH DESCRIPTION .PP The commands in the \fB::tcl::mathop\fR namespace implement the same set of operations as supported by the \fBexpr\fR command. All are exported from the namespace, but are not imported into any other namespace by default. Note that renaming, reimplementing or deleting any of the commands in the namespace does \fInot\fR alter the way that the \fBexpr\fR command behaves, and nor does defining any new commands in the \fB::tcl::mathop\fR namespace. .PP The following operator commands are supported: .DS .ta 2c 4c 6c 8c \fB~\fR \fB!\fR \fB+\fR \fB\-\fR \fB*\fR \fB/\fR \fB%\fR \fB**\fR \fB&\fR \fB|\fR \fB^\fR \fB>>\fR \fB<<\fR \fB==\fR \fBeq\fR \fB!=\fR \fBne\fR \fB<\fR \fB<=\fR \fB>\fR \fB>=\fR \fBin\fR \fBni\fR .DE .SS "MATHEMATICAL OPERATORS" .PP The behaviors of the mathematical operator commands are as follows: .TP \fB!\fR \fIboolean\fR . Returns the boolean negation of \fIboolean\fR, where \fIboolean\fR may be any numeric value or any other form of boolean value (i.e. it returns truth if the argument is falsity or zero, and falsity if the argument is truth or non-zero). .TP \fB+\fR ?\fInumber\fR ...? . Returns the sum of arbitrarily many arguments. Each \fInumber\fR argument may be any numeric value. If no arguments are given, the result will be zero (the summation identity). .TP \fB\-\fR \fInumber\fR ?\fInumber\fR ...? . If only a single \fInumber\fR argument is given, returns the negation of that numeric value. Otherwise returns the number that results when all subsequent numeric values are subtracted from the first one. All \fInumber\fR arguments must be numeric values. At least one argument must be given. .TP \fB*\fR ?\fInumber\fR ...? . Returns the product of arbitrarily many arguments. Each \fInumber\fR may be any numeric value. If no arguments are given, the result will be one (the multiplicative identity). .TP \fB/\fR \fInumber\fR ?\fInumber\fR ...? . If only a single \fInumber\fR argument is given, returns the reciprocal of that numeric value (i.e. the value obtained by dividing 1.0 by that value). Otherwise returns the number that results when the first numeric argument is divided by all subsequent numeric arguments. All \fInumber\fR arguments must be numeric values. At least one argument must be given. .RS .PP Note that when the leading values in the list of arguments are integers, integer division will be used for those initial steps (i.e. the intermediate results will be as if the functions \fIfloor\fR and \fIint\fR are applied to them, in that order). If all values in the operation are integers, the result will be an integer. .RE .TP \fB%\fR \fInumber number\fR . Returns the integral modulus (i.e., remainder) of the first argument with respect to the second. Each \fInumber\fR must have an integral value. Also, the sign of the result will be the same as the sign of the second \fInumber\fR, which must not be zero. .RS .PP Note that Tcl defines this operation exactly even for negative numbers, so that the following command returns a true value (omitting the namespace for clarity): .PP .CS \fB==\fR [\fB*\fR [\fB/\fI x y\fR] \fIy\fR] [\fB\-\fI x\fR [\fB%\fI x y\fR]] .CE .RE .TP \fB**\fR ?\fInumber\fR ...? . Returns the result of raising each value to the power of the result of recursively operating on the result of processing the following arguments, so .QW "\fB** 2 3 4\fR" is the same as .QW "\fB** 2 [** 3 4]\fR" . Each \fInumber\fR may be any numeric value, though the second number must not be fractional if the first is negative. If no arguments are given, the result will be one, and if only one argument is given, the result will be that argument. The result will have an integral value only when all arguments are integral values. .SS "COMPARISON OPERATORS" .PP The behaviors of the comparison operator commands (most of which operate preferentially on numeric arguments) are as follows: .TP \fB==\fR ?\fIarg\fR ...? . Returns whether each argument is equal to the arguments on each side of it in the sense of the \fBexpr\fR == operator (\fIi.e.\fR, numeric comparison if possible, exact string comparison otherwise). If fewer than two arguments are given, this operation always returns a true value. .TP \fBeq\fR ?\fIarg\fR ...? . Returns whether each argument is equal to the arguments on each side of it using exact string comparison. If fewer than two arguments are given, this operation always returns a true value. .TP \fB!=\fR \fIarg arg\fR . Returns whether the two arguments are not equal to each other, in the sense of the \fBexpr\fR != operator (\fIi.e.\fR, numeric comparison if possible, exact string comparison otherwise). .TP \fBne\fR \fIarg arg\fR . Returns whether the two arguments are not equal to each other using exact string comparison. .TP \fB<\fR ?\fIarg\fR ...? . Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be strictly more than the one preceding it. Comparisons are performed preferentially on the numeric values, and are otherwise performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. When the arguments are numeric but should be compared as strings, the \fBstring compare\fR command should be used instead. .TP \fB<=\fR ?\fIarg\fR ...? . Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be equal to or more than the one preceding it. Comparisons are performed preferentially on the numeric values, and are otherwise performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. When the arguments are numeric but should be compared as strings, the \fBstring compare\fR command should be used instead. .TP \fB>\fR ?\fIarg\fR ...? . Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be strictly less than the one preceding it. Comparisons are performed preferentially on the numeric values, and are otherwise performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. When the arguments are numeric but should be compared as strings, the \fBstring compare\fR command should be used instead. .TP \fB>=\fR ?\fIarg\fR ...? . Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be equal to or less than the one preceding it. Comparisons are performed preferentially on the numeric values, and are otherwise performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. When the arguments are numeric but should be compared as strings, the \fBstring compare\fR command should be used instead. .SS "BIT-WISE OPERATORS" .PP The behaviors of the bit-wise operator commands (all of which only operate on integral arguments) are as follows: .TP \fB~\fR \fInumber\fR . Returns the bit-wise negation of \fInumber\fR. \fINumber\fR may be an integer of any size. Note that the result of this operation will always have the opposite sign to the input \fInumber\fR. .TP \fB&\fR ?\fInumber\fR ...? . Returns the bit-wise AND of each of the arbitrarily many arguments. Each \fInumber\fR must have an integral value. If no arguments are given, the result will be minus one. .TP \fB|\fR ?\fInumber\fR ...? . Returns the bit-wise OR of each of the arbitrarily many arguments. Each \fInumber\fR must have an integral value. If no arguments are given, the result will be zero. .TP \fB^\fR ?\fInumber\fR ...? . Returns the bit-wise XOR of each of the arbitrarily many arguments. Each \fInumber\fR must have an integral value. If no arguments are given, the result will be zero. .TP \fB<<\fR \fInumber number\fR . Returns the result of bit-wise shifting the first argument left by the number of bits specified in the second argument. Each \fInumber\fR must have an integral value. .TP \fB>>\fR \fInumber number\fR . Returns the result of bit-wise shifting the first argument right by the number of bits specified in the second argument. Each \fInumber\fR must have an integral value. .SS "LIST OPERATORS" .PP The behaviors of the list-oriented operator commands are as follows: .TP \fBin\fR \fIarg list\fR . Returns whether the value \fIarg\fR is present in the list \fIlist\fR (according to exact string comparison of elements). .TP \fBni\fR \fIarg list\fR . Returns whether the value \fIarg\fR is not present in the list \fIlist\fR (according to exact string comparison of elements). .SH EXAMPLES .PP The simplest way to use the operators is often by using \fBnamespace path\fR to make the commands available. This has the advantage of not affecting the set of commands defined by the current namespace. .PP .CS namespace path {\fB::tcl::mathop\fR ::tcl::mathfunc} \fI# Compute the sum of some numbers\fR set sum [\fB+\fR 1 2 3] \fI# Compute the average of a list\fR set list {1 2 3 4 5 6} set mean [\fB/\fR [\fB+\fR {*}$list] [double [llength $list]]] \fI# Test for list membership\fR set gotIt [\fBin\fR 3 $list] \fI# Test to see if a value is within some defined range\fR set inRange [\fB<=\fR 1 $x 5] \fI# Test to see if a list is sorted\fR set sorted [\fB<=\fR {*}$list] .CE .SH "SEE ALSO" expr(n), mathfunc(n), namespace(n) .SH KEYWORDS command, expression, operator '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/tclvars.n0000644000175000017500000005236212663660065014201 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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 tclvars n 8.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME argc, argv, argv0, auto_path, env, errorCode, errorInfo, tcl_interactive, tcl_library, tcl_nonwordchars, tcl_patchLevel, tcl_pkgPath, tcl_platform, tcl_precision, tcl_rcFileName, tcl_traceCompile, tcl_traceExec, tcl_wordchars, tcl_version \- Variables used by Tcl .BE .SH DESCRIPTION .PP The following global variables are created and managed automatically by the Tcl library. Except where noted below, these variables should normally be treated as read-only by application-specific code and by users. .TP \fBauto_path\fR . If set, then it must contain a valid Tcl list giving directories to search during auto-load operations (including for package index files when using the default \fBpackage unknown\fR handler). This variable is initialized during startup to contain, in order: the directories listed in the \fBTCLLIBPATH\fR environment variable, the directory named by the \fBtcl_library\fR global variable, the parent directory of \fBtcl_library\fR, the directories listed in the \fBtcl_pkgPath\fR variable. Additional locations to look for files and package indices should normally be added to this variable using \fBlappend\fR. .RS .PP Additional variables relating to package management exist. More details are listed in the \fBVARIABLES\fR section of the \fBlibrary\fR manual page. .RE .TP \fBenv\fR . This variable is maintained by Tcl as an array whose elements are the environment variables for the process. Reading an element will return the value of the corresponding environment variable. Setting an element of the array will modify the corresponding environment variable or create a new one if it does not already exist. Unsetting an element of \fBenv\fR will remove the corresponding environment variable. Changes to the \fBenv\fR array will affect the environment passed to children by commands like \fBexec\fR. If the entire \fBenv\fR array is unset then Tcl will stop monitoring \fBenv\fR accesses and will not update environment variables. .RS .PP Under Windows, the environment variables PATH and COMSPEC in any capitalization are converted automatically to upper case. For instance, the PATH variable could be exported by the operating system as .QW path , .QW Path , .QW PaTh , etc., causing otherwise simple Tcl code to have to support many special cases. All other environment variables inherited by Tcl are left unmodified. Setting an env array variable to blank is the same as unsetting it as this is the behavior of the underlying Windows OS. It should be noted that relying on an existing and empty environment variable will not work on Windows and is discouraged for cross-platform usage. .PP The following elements of \fBenv\fR are special to Tcl: .TP \fBenv(HOME)\fR . This environment variable, if set, gives the location of the directory considered to be the current user's home directory, and to which a call of \fBcd\fR without arguments or with just .QW ~ as an argument will change into. Most platforms set this correctly by default; it does not normally need to be set by user code. .TP \fBenv(TCL_LIBRARY)\fR . If set, then it specifies the location of the directory containing library scripts (the value of this variable will be assigned to the \fBtcl_library\fR variable and therefore returned by the command \fBinfo library\fR). If this variable is not set then a default value is used. .RS .PP Note that this environment variable should \fInot\fR normally be set. .RE .TP \fBenv(TCLLIBPATH)\fR . If set, then it must contain a valid Tcl list giving directories to search during auto-load operations. Directories must be specified in Tcl format, using .QW / as the path separator, regardless of platform. This variable is only used when initializing the \fBauto_path\fR variable. .TP \fBenv(TCL_TZ)\fR, \fBenv(TZ)\fR . These specify the default timezone used for parsing and formatting times and dates in the \fBclock\fR command. On many platforms, the TZ environment variable is set up by the operating system. .TP \fBenv(LC_ALL)\fR, \fBenv(LC_MESSAGES)\fR, \fBenv(LANG)\fR . These environment variables are used by the \fBmsgcat\fR package to determine what locale to format messages using. .TP \fBenv(TCL_INTERP_DEBUG_FRAME)\fR . If existing, it has the same effect as running \fBinterp debug\fR \fB{} -frame 1\fR as the very first command of each new Tcl interpreter. .RE .TP \fBerrorCode\fR . This variable holds the value of the \fB\-errorcode\fR return option set by the most recent error that occurred in this interpreter. This list value represents additional information about the error in a form that is easy to process with programs. The first element of the list identifies a general class of errors, and determines the format of the rest of the list. The following formats for \fB\-errorcode\fR return options are used by the Tcl core; individual applications may define additional formats. .RS .TP \fBARITH\fI code msg\fR . This format is used when an arithmetic error occurs (e.g. an attempt to divide zero by zero in the \fBexpr\fR command). \fICode\fR identifies the precise error and \fImsg\fR provides a human-readable description of the error. \fICode\fR will be either DIVZERO (for an attempt to divide by zero), DOMAIN (if an argument is outside the domain of a function, such as acos(\-3)), IOVERFLOW (for integer overflow), OVERFLOW (for a floating-point overflow), or UNKNOWN (if the cause of the error cannot be determined). .RS .PP Detection of these errors depends in part on the underlying hardware and system libraries. .RE .TP \fBCHILDKILLED\fI pid sigName msg\fR . This format is used when a child process has been killed because of a signal. The \fIpid\fR element will be the process's identifier (in decimal). The \fIsigName\fR element will be the symbolic name of the signal that caused the process to terminate; it will be one of the names from the include file signal.h, such as \fBSIGPIPE\fR. The \fImsg\fR element will be a short human-readable message describing the signal, such as .QW "write on pipe with no readers" for \fBSIGPIPE\fR. .TP \fBCHILDSTATUS\fI pid code\fR . This format is used when a child process has exited with a non-zero exit status. The \fIpid\fR element will be the process's identifier (in decimal) and the \fIcode\fR element will be the exit code returned by the process (also in decimal). .TP \fBCHILDSUSP\fI pid sigName msg\fR . This format is used when a child process has been suspended because of a signal. The \fIpid\fR element will be the process's identifier, in decimal. The \fIsigName\fR element will be the symbolic name of the signal that caused the process to suspend; this will be one of the names from the include file signal.h, such as \fBSIGTTIN\fR. The \fImsg\fR element will be a short human-readable message describing the signal, such as .QW "background tty read" for \fBSIGTTIN\fR. .TP \fBNONE\fR . This format is used for errors where no additional information is available for an error besides the message returned with the error. In these cases the \fB\-errorcode\fR return option will consist of a list containing a single element whose contents are \fBNONE\fR. .TP \fBPOSIX \fIerrName msg\fR . If the first element is \fBPOSIX\fR, then the error occurred during a POSIX kernel call. The \fIerrName\fR element will contain the symbolic name of the error that occurred, such as \fBENOENT\fR; this will be one of the values defined in the include file errno.h. The \fImsg\fR element will be a human-readable message corresponding to \fIerrName\fR, such as .QW "no such file or directory" for the \fBENOENT\fR case. .TP \fBTCL\fR ... . Indicates some sort of problem generated in relation to Tcl itself, e.g. a failure to look up a channel or variable. .PP To set the \fB\-errorcode\fR return option, applications should use library procedures such as \fBTcl_SetObjErrorCode\fR, \fBTcl_SetReturnOptions\fR, and \fBTcl_PosixError\fR, or they may invoke the \fB\-errorcode\fR option of the \fBreturn\fR command. If none of these methods for setting the error code has been used, the Tcl interpreter will reset the variable to \fBNONE\fR after the next error. .RE .TP \fBerrorInfo\fR . This variable holds the value of the \fB\-errorinfo\fR return option set by the most recent error that occurred in this interpreter. This string value will contain one or more lines identifying the Tcl commands and procedures that were being executed when the most recent error occurred. Its contents take the form of a stack trace showing the various nested Tcl commands that had been invoked at the time of the error. .TP \fBtcl_library\fR . This variable holds the name of a directory containing the system library of Tcl scripts, such as those used for auto-loading. The value of this variable is returned by the \fBinfo library\fR command. See the \fBlibrary\fR manual entry for details of the facilities provided by the Tcl script library. Normally each application or package will have its own application-specific script library in addition to the Tcl script library; each application should set a global variable with a name like \fB$\fIapp\fB_library\fR (where \fIapp\fR is the application's name) to hold the network file name for that application's library directory. The initial value of \fBtcl_library\fR is set when an interpreter is created by searching several different directories until one is found that contains an appropriate Tcl startup script. If the \fBTCL_LIBRARY\fR environment variable exists, then the directory it names is checked first. If \fBTCL_LIBRARY\fR is not set or doesn't refer to an appropriate directory, then Tcl checks several other directories based on a compiled-in default location, the location of the binary containing the application, and the current working directory. .TP \fBtcl_patchLevel\fR . When an interpreter is created Tcl initializes this variable to hold a string giving the current patch level for Tcl, such as \fB8.4.16\fR for Tcl 8.4 with the first sixteen official patches, or \fB8.5b3\fR for the third beta release of Tcl 8.5. The value of this variable is returned by the \fBinfo patchlevel\fR command. .TP \fBtcl_pkgPath\fR . This variable holds a list of directories indicating where packages are normally installed. It is not used on Windows. It typically contains either one or two entries; if it contains two entries, the first is normally a directory for platform-dependent packages (e.g., shared library binaries) and the second is normally a directory for platform-independent packages (e.g., script files). Typically a package is installed as a subdirectory of one of the entries in the \fBtcl_pkgPath\fR variable. The directories in the \fBtcl_pkgPath\fR variable are included by default in the \fBauto_path\fR variable, so they and their immediate subdirectories are automatically searched for packages during \fBpackage require\fR commands. Note: \fBtcl_pkgPath\fR is not intended to be modified by the application. Its value is added to \fBauto_path\fR at startup; changes to \fBtcl_pkgPath\fR are not reflected in \fBauto_path\fR. If you want Tcl to search additional directories for packages you should add the names of those directories to \fBauto_path\fR, not \fBtcl_pkgPath\fR. .TP \fBtcl_platform\fR . This is an associative array whose elements contain information about the platform on which the application is running, such as the name of the operating system, its current release number, and the machine's instruction set. The elements listed below will always be defined, but they may have empty strings as values if Tcl could not retrieve any relevant information. In addition, extensions and applications may add additional values to the array. The predefined elements are: .RS .TP \fBbyteOrder\fR . The native byte order of this machine: either \fBlittleEndian\fR or \fBbigEndian\fR. .TP \fBdebug\fR . If this variable exists, then the interpreter was compiled with and linked to a debug-enabled C run-time. This variable will only exist on Windows, so extension writers can specify which package to load depending on the C run-time library that is in use. This is not an indication that this core contains symbols. .TP \fBengine\fR . The name of the Tcl language implementation. When the interpreter is first created, this is always set to the string \fBTcl\fR. .TP \fBmachine\fR . The instruction set executed by this machine, such as \fBintel\fR, \fBPPC\fR, \fB68k\fR, or \fBsun4m\fR. On UNIX machines, this is the value returned by \fBuname -m\fR. .TP \fBos\fR . The name of the operating system running on this machine, such as \fBWindows NT\fR or \fBSunOS\fR. On UNIX machines, this is the value returned by \fBuname -s\fR. .TP \fBosVersion\fR . The version number for the operating system running on this machine. On UNIX machines, this is the value returned by \fBuname -r\fR. .TP \fBpathSeparator\fR .VS 8.6 '\" Defined by TIP #315 The character that should be used to \fBsplit\fR PATH-like environment variables into their corresponding list of directory names. .VE 8.6 .TP \fBplatform\fR . Either \fBwindows\fR, or \fBunix\fR. This identifies the general operating environment of the machine. .TP \fBpointerSize\fR . This gives the size of the native-machine pointer in bytes (strictly, it is same as the result of evaluating \fIsizeof(void*)\fR in C.) .TP \fBthreaded\fR . If this variable exists, then the interpreter was compiled with threads enabled. .TP \fBuser\fR . This identifies the current user based on the login information available on the platform. This value comes from the getuid() and getpwuid() system calls on Unix, and the value from the GetUserName() system call on Windows. .TP \fBwordSize\fR . This gives the size of the native-machine word in bytes (strictly, it is same as the result of evaluating \fIsizeof(long)\fR in C.) .RE .TP \fBtcl_precision\fR . This variable controls the number of digits to generate when converting floating-point values to strings. It defaults to 0. \fIApplications should not change this value;\fR it is provided for compatibility with legacy code. .PP .RS The default value of 0 is special, meaning that Tcl should convert numbers using as few digits as possible while still distinguishing any floating point number from its nearest neighbours. It differs from using an arbitrarily high value for \fItcl_precision\fR in that an inexact number like \fI1.4\fR will convert as \fI1.4\fR rather than \fI1.3999999999999999\fR even though the latter is nearer to the exact value of the binary number. .RE .PP .RS If \fBtcl_precision\fR is not zero, then when Tcl converts a floating point number, it creates a decimal representation of at most \fBtcl_precision\fR significant digits; the result may be shorter if the shorter result represents the original number exactly. If no result of at most \fBtcl_precision\fR digits is an exact representation of the original number, the one that is closest to the original number is chosen. If the original number lies precisely between two equally accurate decimal representations, then the one with an even value for the least significant digit is chosen; for instance, if \fBtcl_precision\fR is 3, then 0.3125 will convert to 0.312, not 0.313, while 0.6875 will convert to 0.688, not 0.687. Any string of trailing zeroes that remains is trimmed. .RE .PP .RS a \fBtcl_precision\fR value of 17 digits is .QW perfect for IEEE floating-point in that it allows double-precision values to be converted to strings and back to binary with no loss of information. For this reason, you will often see it as a value in legacy code that must run on Tcl versions before 8.5. It is no longer recommended; as noted above, a zero value is the preferred method. .RE .PP .RS All interpreters in a thread share a single \fBtcl_precision\fR value: changing it in one interpreter will affect all other interpreters as well. Safe interpreters are not allowed to modify the variable. .RE .PP .RS Valid values for \fBtcl_precision\fR range from 0 to 17. .RE .TP \fBtcl_rcFileName\fR . This variable is used during initialization to indicate the name of a user-specific startup file. If it is set by application-specific initialization, then the Tcl startup code will check for the existence of this file and \fBsource\fR it if it exists. For example, for \fBwish\fR the variable is set to \fB~/.wishrc\fR for Unix and \fB~/wishrc.tcl\fR for Windows. .TP \fBtcl_traceCompile\fR . The value of this variable can be set to control how much tracing information is displayed during bytecode compilation. By default, \fBtcl_traceCompile\fR is zero and no information is displayed. Setting \fBtcl_traceCompile\fR to 1 generates a one-line summary in \fBstdout\fR whenever a procedure or top-level command is compiled. Setting it to 2 generates a detailed listing in \fBstdout\fR of the bytecode instructions emitted during every compilation. This variable is useful in tracking down suspected problems with the Tcl compiler. .PP .RS This variable and functionality only exist if \fBTCL_COMPILE_DEBUG\fR was defined during Tcl's compilation. .RE .TP \fBtcl_traceExec\fR . The value of this variable can be set to control how much tracing information is displayed during bytecode execution. By default, \fBtcl_traceExec\fR is zero and no information is displayed. Setting \fBtcl_traceExec\fR to 1 generates a one-line trace in \fBstdout\fR on each call to a Tcl procedure. Setting it to 2 generates a line of output whenever any Tcl command is invoked that contains the name of the command and its arguments. Setting it to 3 produces a detailed trace showing the result of executing each bytecode instruction. Note that when \fBtcl_traceExec\fR is 2 or 3, commands such as \fBset\fR and \fBincr\fR that have been entirely replaced by a sequence of bytecode instructions are not shown. Setting this variable is useful in tracking down suspected problems with the bytecode compiler and interpreter. .PP .RS This variable and functionality only exist if \fBTCL_COMPILE_DEBUG\fR was defined during Tcl's compilation. .RE .TP \fBtcl_wordchars\fR . The value of this variable is a regular expression that can be set to control what are considered .QW word characters, for instances like selecting a word by double-clicking in text in Tk. It is platform dependent. On Windows, it defaults to \fB\eS\fR, meaning anything but a Unicode space character. Otherwise it defaults to \fB\ew\fR, which is any Unicode word character (number, letter, or underscore). .TP \fBtcl_nonwordchars\fR . The value of this variable is a regular expression that can be set to control what are considered .QW non-word characters, for instances like selecting a word by double-clicking in text in Tk. It is platform dependent. On Windows, it defaults to \fB\es\fR, meaning any Unicode space character. Otherwise it defaults to \fB\eW\fR, which is anything but a Unicode word character (number, letter, or underscore). .TP \fBtcl_version\fR . When an interpreter is created Tcl initializes this variable to hold the version number for this version of Tcl in the form \fIx.y\fR. Changes to \fIx\fR represent major changes with probable incompatibilities and changes to \fIy\fR represent small enhancements and bug fixes that retain backward compatibility. The value of this variable is returned by the \fBinfo tclversion\fR command. .SH "OTHER GLOBAL VARIABLES" .PP The following variables are only guaranteed to exist in \fBtclsh\fR and \fBwish\fR executables; the Tcl library does not define them itself but many Tcl environments do. .TP 6 \fBargc\fR . The number of arguments to \fBtclsh\fR or \fBwish\fR. .TP 6 \fBargv\fR . Tcl list of arguments to \fBtclsh\fR or \fBwish\fR. .TP 6 \fBargv0\fR . The script that \fBtclsh\fR or \fBwish\fR started executing (if it was specified) or otherwise the name by which \fBtclsh\fR or \fBwish\fR was invoked. .TP 6 \fBtcl_interactive\fR . Contains 1 if \fBtclsh\fR or \fBwish\fR is running interactively (no script was specified and standard input is a terminal-like device), 0 otherwise. .SH EXAMPLES .PP To add a directory to the collection of locations searched by \fBpackage require\fR, e.g., because of some application-specific packages that are used, the \fBauto_path\fR variable needs to be updated: .PP .CS lappend ::\fBauto_path\fR [file join [pwd] "theLibDir"] .CE .PP A simple though not very robust way to handle command line arguments of the form .QW "\-foo 1 \-bar 2" is to load them into an array having first loaded in the default settings: .CS array set arguments {-foo 0 -bar 0 -grill 0} array set arguments $::\fBargv\fR puts "foo is $arguments(-foo)" puts "bar is $arguments(-bar)" puts "grill is $arguments(-grill)" .CE .PP The \fBargv0\fR global variable can be used (in conjunction with the \fBinfo script\fR command) to determine whether the current script is being executed as the main script or loaded as a library. This is useful because it allows a single script to be used as both a library and a demonstration of that library: .PP .CS if {$::\fBargv0\fR eq [info script]} { # running as: tclsh example.tcl } else { package provide Example 1.0 } .CE .SH "SEE ALSO" eval(n), library(n), tclsh(1), tkvars(n), wish(1) .SH KEYWORDS arithmetic, bytecode, compiler, error, environment, POSIX, precision, subprocess, user, variables '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/SubstObj.30000644000175000017500000000527712663660065014166 0ustar sergeisergei'\" '\" Copyright (c) 2001 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_SubstObj 3 8.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_SubstObj \- perform substitutions on Tcl values .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * \fBTcl_SubstObj\fR(\fIinterp, objPtr, flags\fR) .SH ARGUMENTS .AS Tcl_Interp **termPtr .AP Tcl_Interp *interp in Interpreter in which to execute Tcl scripts and lookup variables. If an error occurs, the interpreter's result is modified to hold an error message. .AP Tcl_Obj *objPtr in A Tcl value containing the string to perform substitutions on. .AP int flags in ORed combination of flag bits that specify which substitutions to perform. The flags \fBTCL_SUBST_COMMANDS\fR, \fBTCL_SUBST_VARIABLES\fR and \fBTCL_SUBST_BACKSLASHES\fR are currently supported, and \fBTCL_SUBST_ALL\fR is provided as a convenience for the common case where all substitutions are desired. .BE .SH DESCRIPTION .PP The \fBTcl_SubstObj\fR function is used to perform substitutions on strings in the fashion of the \fBsubst\fR command. It gets the value of the string contained in \fIobjPtr\fR and scans it, copying characters and performing the chosen substitutions as it goes to an output value which is returned as the result of the function. In the event of an error occurring during the execution of a command or variable substitution, the function returns NULL and an error message is left in \fIinterp\fR's result. .PP Three kinds of substitutions are supported. When the \fBTCL_SUBST_BACKSLASHES\fR bit is set in \fIflags\fR, sequences that look like backslash substitutions for Tcl commands are replaced by their corresponding character. .PP When the \fBTCL_SUBST_VARIABLES\fR bit is set in \fIflags\fR, sequences that look like variable substitutions for Tcl commands are replaced by the contents of the named variable. .PP When the \fBTCL_SUBST_COMMANDS\fR bit is set in \fIflags\fR, sequences that look like command substitutions for Tcl commands are replaced by the result of evaluating that script. Where an uncaught .QW "continue exception" occurs during the evaluation of a command substitution, an empty string is substituted for the command. Where an uncaught .QW "break exception" occurs during the evaluation of a command substitution, the result of the whole substitution on \fIobjPtr\fR will be truncated at the point immediately before the start of the command substitution, and no characters will be added to the result or substitutions performed after that point. .SH "SEE ALSO" subst(n) .SH KEYWORDS backslash substitution, command substitution, variable substitution tcl8.6.5/doc/join.n0000644000175000017500000000223112663660065013450 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 join n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME join \- Create a string by joining together list elements .SH SYNOPSIS \fBjoin \fIlist \fR?\fIjoinString\fR? .BE .SH DESCRIPTION .PP The \fIlist\fR argument must be a valid Tcl list. This command returns the string formed by joining all of the elements of \fIlist\fR together with \fIjoinString\fR separating each adjacent pair of elements. The \fIjoinString\fR argument defaults to a space character. .SH EXAMPLES .PP Making a comma-separated list: .PP .CS set data {1 2 3 4 5} \fBjoin\fR $data ", " \fB\(-> 1, 2, 3, 4, 5\fR .CE .PP Using \fBjoin\fR to flatten a list by a single level: .PP .CS set data {1 {2 3} 4 {5 {6 7} 8}} \fBjoin\fR $data \fB\(-> 1 2 3 4 5 {6 7} 8\fR .CE .SH "SEE ALSO" list(n), lappend(n), split(n) .SH KEYWORDS element, join, list, separator tcl8.6.5/doc/CrtChnlHdlr.30000644000175000017500000000723712663660065014600 0ustar sergeisergei'\" '\" Copyright (c) 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_CreateChannelHandler 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_CreateChannelHandler, Tcl_DeleteChannelHandler \- call a procedure when a channel becomes readable or writable .SH SYNOPSIS .nf .nf \fB#include \fR .sp void \fBTcl_CreateChannelHandler\fR(\fIchannel, mask, proc, clientData\fR) .sp void \fBTcl_DeleteChannelHandler\fR(\fIchannel, proc, clientData\fR) .sp .SH ARGUMENTS .AS Tcl_ChannelProc clientData .AP Tcl_Channel channel in Tcl channel such as returned by \fBTcl_CreateChannel\fR. .AP int mask in Conditions under which \fIproc\fR should be called: OR-ed combination of \fBTCL_READABLE\fR, \fBTCL_WRITABLE\fR and \fBTCL_EXCEPTION\fR. Specify a zero value to temporarily disable an existing handler. .AP Tcl_FileProc *proc in Procedure to invoke whenever the channel indicated by \fIchannel\fR meets the conditions specified by \fImask\fR. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR. .BE .SH DESCRIPTION .PP \fBTcl_CreateChannelHandler\fR arranges for \fIproc\fR to be called in the future whenever input or output becomes possible on the channel identified by \fIchannel\fR, or whenever an exceptional condition exists for \fIchannel\fR. The conditions of interest under which \fIproc\fR will be invoked are specified by the \fImask\fR argument. See the manual entry for \fBfileevent\fR for a precise description of what it means for a channel to be readable or writable. \fIProc\fR must conform to the following prototype: .PP .CS typedef void \fBTcl_ChannelProc\fR( ClientData \fIclientData\fR, int \fImask\fR); .CE .PP The \fIclientData\fR argument is the same as the value passed to \fBTcl_CreateChannelHandler\fR when the handler was created. Typically, \fIclientData\fR points to a data structure containing application-specific information about the channel. \fIMask\fR is an integer mask indicating which of the requested conditions actually exists for the channel; it will contain a subset of the bits from the \fImask\fR argument to \fBTcl_CreateChannelHandler\fR when the handler was created. .PP Each channel handler is identified by a unique combination of \fIchannel\fR, \fIproc\fR and \fIclientData\fR. There may be many handlers for a given channel as long as they do not have the same \fIchannel\fR, \fIproc\fR, and \fIclientData\fR. If \fBTcl_CreateChannelHandler\fR is invoked when there is already a handler for \fIchannel\fR, \fIproc\fR, and \fIclientData\fR, then no new handler is created; instead, the \fImask\fR is changed for the existing handler. .PP \fBTcl_DeleteChannelHandler\fR deletes a channel handler identified by \fIchannel\fR, \fIproc\fR and \fIclientData\fR; if no such handler exists, the call has no effect. .PP Channel handlers are invoked via the Tcl event mechanism, so they are only useful in applications that are event-driven. Note also that the conditions specified in the \fImask\fR argument to \fIproc\fR may no longer exist when \fIproc\fR is invoked: for example, if there are two handlers for \fBTCL_READABLE\fR on the same channel, the first handler could consume all of the available input so that the channel is no longer readable when the second handler is invoked. For this reason it may be useful to use nonblocking I/O on channels for which there are event handlers. .SH "SEE ALSO" Notifier(3), Tcl_CreateChannel(3), Tcl_OpenFileChannel(3), vwait(n). .SH KEYWORDS blocking, callback, channel, events, handler, nonblocking. tcl8.6.5/doc/RecEvalObj.30000644000175000017500000000361212663660065014376 0ustar sergeisergei'\" '\" Copyright (c) 1997 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_RecordAndEvalObj 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_RecordAndEvalObj \- save command on history list before evaluating .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_RecordAndEvalObj\fR(\fIinterp, cmdPtr, flags\fR) .SH ARGUMENTS .AS Tcl_Interp *interp .AP Tcl_Interp *interp in Tcl interpreter in which to evaluate command. .AP Tcl_Obj *cmdPtr in Points to a Tcl value containing a command (or sequence of commands) to execute. .AP int flags in An OR'ed combination of flag bits. \fBTCL_NO_EVAL\fR means record the command but do not evaluate it. \fBTCL_EVAL_GLOBAL\fR means evaluate the command at global level instead of the current stack level. .BE .SH DESCRIPTION .PP \fBTcl_RecordAndEvalObj\fR is invoked to record a command as an event on the history list and then execute it using \fBTcl_EvalObjEx\fR (or \fBTcl_GlobalEvalObj\fR if the \fBTCL_EVAL_GLOBAL\fR bit is set in \fIflags\fR). It returns a completion code such as \fBTCL_OK\fR just like \fBTcl_EvalObjEx\fR, as well as a result value containing additional information (a result value or error message) that can be retrieved using \fBTcl_GetObjResult\fR. If you do not want the command recorded on the history list then you should invoke \fBTcl_EvalObjEx\fR instead of \fBTcl_RecordAndEvalObj\fR. Normally \fBTcl_RecordAndEvalObj\fR is only called with top-level commands typed by the user, since the purpose of history is to allow the user to re-issue recently invoked commands. If the \fIflags\fR argument contains the \fBTCL_NO_EVAL\fR bit then the command is recorded without being evaluated. .SH "SEE ALSO" Tcl_EvalObjEx, Tcl_GetObjResult .SH KEYWORDS command, event, execute, history, interpreter, value, record tcl8.6.5/doc/library.n0000644000175000017500000003451612663660065014170 0ustar sergeisergei'\" '\" Copyright (c) 1991-1993 The Regents of the University of California. '\" Copyright (c) 1994-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 library n "8.0" Tcl "Tcl Built-In Commands" .so man.macros .BS .SH NAME auto_execok, auto_import, auto_load, auto_mkindex, auto_qualify, auto_reset, tcl_findLibrary, parray, tcl_endOfWord, tcl_startOfNextWord, tcl_startOfPreviousWord, tcl_wordBreakAfter, tcl_wordBreakBefore \- standard library of Tcl procedures .SH SYNOPSIS .nf \fBauto_execok \fIcmd\fR \fBauto_import \fIpattern\fR \fBauto_load \fIcmd\fR \fBauto_mkindex \fIdir pattern pattern ...\fR \fBauto_qualify \fIcommand namespace\fR \fBauto_reset\fR \fBtcl_findLibrary \fIbasename version patch initScript enVarName varName\fR \fBparray \fIarrayName\fR ?\fIpattern\fR? \fBtcl_endOfWord \fIstr start\fR \fBtcl_startOfNextWord \fIstr start\fR \fBtcl_startOfPreviousWord \fIstr start\fR \fBtcl_wordBreakAfter \fIstr start\fR \fBtcl_wordBreakBefore \fIstr start\fR .BE .SH INTRODUCTION .PP Tcl includes a library of Tcl procedures for commonly-needed functions. The procedures defined in the Tcl library are generic ones suitable for use by many different applications. The location of the Tcl library is returned by the \fBinfo library\fR command. In addition to the Tcl library, each application will normally have its own library of support procedures as well; the location of this library is normally given by the value of the \fB$\fIapp\fB_library\fR global variable, where \fIapp\fR is the name of the application. For example, the location of the Tk library is kept in the variable \fBtk_library\fR. .PP To access the procedures in the Tcl library, an application should source the file \fBinit.tcl\fR in the library, for example with the Tcl command .PP .CS \fBsource [file join [info library] init.tcl]\fR .CE .PP If the library procedure \fBTcl_Init\fR is invoked from an application's \fBTcl_AppInit\fR procedure, this happens automatically. The code in \fBinit.tcl\fR will define the \fBunknown\fR procedure and arrange for the other procedures to be loaded on-demand using the auto-load mechanism defined below. .SH "COMMAND PROCEDURES" .PP The following procedures are provided in the Tcl library: .TP \fBauto_execok \fIcmd\fR Determines whether there is an executable file or shell builtin by the name \fIcmd\fR. If so, it returns a list of arguments to be passed to \fBexec\fR to execute the executable file or shell builtin named by \fIcmd\fR. If not, it returns an empty string. This command examines the directories in the current search path (given by the PATH environment variable) in its search for an executable file named \fIcmd\fR. On Windows platforms, the search is expanded with the same directories and file extensions as used by \fBexec\fR. \fBAuto_execok\fR remembers information about previous searches in an array named \fBauto_execs\fR; this avoids the path search in future calls for the same \fIcmd\fR. The command \fBauto_reset\fR may be used to force \fBauto_execok\fR to forget its cached information. .TP \fBauto_import \fIpattern\fR \fBAuto_import\fR is invoked during \fBnamespace import\fR to see if the imported commands specified by \fIpattern\fR reside in an autoloaded library. If so, the commands are loaded so that they will be available to the interpreter for creating the import links. If the commands do not reside in an autoloaded library, \fBauto_import\fR does nothing. The pattern matching is performed according to the matching rules of \fBnamespace import\fR. .TP \fBauto_load \fIcmd\fR This command attempts to load the definition for a Tcl command named \fIcmd\fR. To do this, it searches an \fIauto-load path\fR, which is a list of one or more directories. The auto-load path is given by the global variable \fBauto_path\fR if it exists. If there is no \fBauto_path\fR variable, then the TCLLIBPATH environment variable is used, if it exists. Otherwise the auto-load path consists of just the Tcl library directory. Within each directory in the auto-load path there must be a file \fBtclIndex\fR that describes one or more commands defined in that directory and a script to evaluate to load each of the commands. The \fBtclIndex\fR file should be generated with the \fBauto_mkindex\fR command. If \fIcmd\fR is found in an index file, then the appropriate script is evaluated to create the command. The \fBauto_load\fR command returns 1 if \fIcmd\fR was successfully created. The command returns 0 if there was no index entry for \fIcmd\fR or if the script did not actually define \fIcmd\fR (e.g. because index information is out of date). If an error occurs while processing the script, then that error is returned. \fBAuto_load\fR only reads the index information once and saves it in the array \fBauto_index\fR; future calls to \fBauto_load\fR check for \fIcmd\fR in the array rather than re-reading the index files. The cached index information may be deleted with the command \fBauto_reset\fR. This will force the next \fBauto_load\fR command to reload the index database from disk. .TP \fBauto_mkindex \fIdir pattern pattern ...\fR . Generates an index suitable for use by \fBauto_load\fR. The command searches \fIdir\fR for all files whose names match any of the \fIpattern\fR arguments (matching is done with the \fBglob\fR command), generates an index of all the Tcl command procedures defined in all the matching files, and stores the index information in a file named \fBtclIndex\fR in \fIdir\fR. If no pattern is given a pattern of \fB*.tcl\fR will be assumed. For example, the command .RS .PP .CS \fBauto_mkindex foo *.tcl\fR .CE .PP will read all the \fB.tcl\fR files in subdirectory \fBfoo\fR and generate a new index file \fBfoo/tclIndex\fR. .PP \fBAuto_mkindex\fR parses the Tcl scripts by sourcing them into a slave interpreter and monitoring the proc and namespace commands that are executed. Extensions can use the (undocumented) auto_mkindex_parser package to register other commands that can contribute to the auto_load index. You will have to read through auto.tcl to see how this works. .PP \fBAuto_mkindex_old\fR (which has the same syntax as \fBauto_mkindex\fR) parses the Tcl scripts in a relatively unsophisticated way: if any line contains the word .QW \fBproc\fR as its first characters then it is assumed to be a procedure definition and the next word of the line is taken as the procedure's name. Procedure definitions that do not appear in this way (e.g.\ they have spaces before the \fBproc\fR) will not be indexed. If your script contains .QW dangerous code, such as global initialization code or procedure names with special characters like \fB$\fR, \fB*\fR, \fB[\fR or \fB]\fR, you are safer using \fBauto_mkindex_old\fR. .RE .TP \fBauto_reset\fR . Destroys all the information cached by \fBauto_execok\fR and \fBauto_load\fR. This information will be re-read from disk the next time it is needed. \fBAuto_reset\fR also deletes any procedures listed in the auto-load index, so that fresh copies of them will be loaded the next time that they are used. .TP \fBauto_qualify \fIcommand namespace\fR Computes a list of fully qualified names for \fIcommand\fR. This list mirrors the path a standard Tcl interpreter follows for command lookups: first it looks for the command in the current namespace, and then in the global namespace. Accordingly, if \fIcommand\fR is relative and \fInamespace\fR is not \fB::\fR, the list returned has two elements: \fIcommand\fR scoped by \fInamespace\fR, as if it were a command in the \fInamespace\fR namespace; and \fIcommand\fR as if it were a command in the global namespace. Otherwise, if either \fIcommand\fR is absolute (it begins with \fB::\fR), or \fInamespace\fR is \fB::\fR, the list contains only \fIcommand\fR as if it were a command in the global namespace. .RS .PP \fBAuto_qualify\fR is used by the auto-loading facilities in Tcl, both for producing auto-loading indexes such as \fIpkgIndex.tcl\fR, and for performing the actual auto-loading of functions at runtime. .RE .TP \fBtcl_findLibrary \fIbasename version patch initScript enVarName varName\fR This is a standard search procedure for use by extensions during their initialization. They call this procedure to look for their script library in several standard directories. The last component of the name of the library directory is normally \fIbasenameversion\fR (e.g., tk8.0), but it might be .QW library when in the build hierarchies. The \fIinitScript\fR file will be sourced into the interpreter once it is found. The directory in which this file is found is stored into the global variable \fIvarName\fR. If this variable is already defined (e.g., by C code during application initialization) then no searching is done. Otherwise the search looks in these directories: the directory named by the environment variable \fIenVarName\fR; relative to the Tcl library directory; relative to the executable file in the standard installation bin or bin/\fIarch\fR directory; relative to the executable file in the current build tree; relative to the executable file in a parallel build tree. .TP \fBparray \fIarrayName\fR ?\fIpattern\fR? Prints on standard output the names and values of all the elements in the array \fIarrayName\fR, or just the names that match \fIpattern\fR (using the matching rules of \fBstring match\fR) and their values if \fIpattern\fR is given. \fIArrayName\fR must be an array accessible to the caller of \fBparray\fR. It may be either local or global. .TP \fBtcl_endOfWord \fIstr start\fR Returns the index of the first end-of-word location that occurs after a starting index \fIstart\fR in the string \fIstr\fR. An end-of-word location is defined to be the first non-word character following the first word character after the starting point. Returns -1 if there are no more end-of-word locations after the starting point. See the description of \fBtcl_wordchars\fR and \fBtcl_nonwordchars\fR below for more details on how Tcl determines which characters are word characters. .TP \fBtcl_startOfNextWord \fIstr start\fR Returns the index of the first start-of-word location that occurs after a starting index \fIstart\fR in the string \fIstr\fR. A start-of-word location is defined to be the first word character following a non-word character. Returns \-1 if there are no more start-of-word locations after the starting point. .TP \fBtcl_startOfPreviousWord \fIstr start\fR Returns the index of the first start-of-word location that occurs before a starting index \fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more start-of-word locations before the starting point. .TP \fBtcl_wordBreakAfter \fIstr start\fR Returns the index of the first word boundary after the starting index \fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more boundaries after the starting point in the given string. The index returned refers to the second character of the pair that comprises a boundary. .TP \fBtcl_wordBreakBefore \fIstr start\fR Returns the index of the first word boundary before the starting index \fIstart\fR in the string \fIstr\fR. Returns \-1 if there are no more boundaries before the starting point in the given string. The index returned refers to the second character of the pair that comprises a boundary. .SH "VARIABLES" .PP The following global variables are defined or used by the procedures in the Tcl library. They fall into two broad classes, handling unknown commands and packages, and determining what are words. .SS "AUTOLOADING AND PACKAGE MANAGEMENT VARIABLES" .TP \fBauto_execs\fR Used by \fBauto_execok\fR to record information about whether particular commands exist as executable files. .TP \fBauto_index\fR Used by \fBauto_load\fR to save the index information read from disk. .TP \fBauto_noexec\fR If set to any value, then \fBunknown\fR will not attempt to auto-exec any commands. .TP \fBauto_noload\fR If set to any value, then \fBunknown\fR will not attempt to auto-load any commands. .TP \fBauto_path\fR . If set, then it must contain a valid Tcl list giving directories to search during auto-load operations (including for package index files when using the default \fBpackage unknown\fR handler). This variable is initialized during startup to contain, in order: the directories listed in the \fBTCLLIBPATH\fR environment variable, the directory named by the \fBtcl_library\fR global variable, the parent directory of \fBtcl_library\fR, the directories listed in the \fBtcl_pkgPath\fR variable. Additional locations to look for files and package indices should normally be added to this variable using \fBlappend\fR. .TP \fBenv(TCL_LIBRARY)\fR If set, then it specifies the location of the directory containing library scripts (the value of this variable will be assigned to the \fBtcl_library\fR variable and therefore returned by the command \fBinfo library\fR). If this variable is not set then a default value is used. .TP \fBenv(TCLLIBPATH)\fR If set, then it must contain a valid Tcl list giving directories to search during auto-load operations. Directories must be specified in Tcl format, using .QW / as the path separator, regardless of platform. This variable is only used when initializing the \fBauto_path\fR variable. .SS "WORD BOUNDARY DETERMINATION VARIABLES" These variables are only used in the \fBtcl_endOfWord\fR, \fBtcl_startOfNextWord\fR, \fBtcl_startOfPreviousWord\fR, \fBtcl_wordBreakAfter\fR, and \fBtcl_wordBreakBefore\fR commands. .TP \fBtcl_nonwordchars\fR This variable contains a regular expression that is used by routines like \fBtcl_endOfWord\fR to identify whether a character is part of a word or not. If the pattern matches a character, the character is considered to be a non-word character. On Windows platforms, spaces, tabs, and newlines are considered non-word characters. Under Unix, everything but numbers, letters and underscores are considered non-word characters. .TP \fBtcl_wordchars\fR This variable contains a regular expression that is used by routines like \fBtcl_endOfWord\fR to identify whether a character is part of a word or not. If the pattern matches a character, the character is considered to be a word character. On Windows platforms, words are comprised of any character that is not a space, tab, or newline. Under Unix, words are comprised of numbers, letters or underscores. .SH "SEE ALSO" env(n), info(n), re_syntax(n) .SH KEYWORDS auto-exec, auto-load, library, unknown, word, whitespace '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/platform.n0000644000175000017500000000632612663660065014346 0ustar sergeisergei'\" '\" Copyright (c) 2006 ActiveState Software Inc '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH "platform" n 1.0.4 platform "Tcl Bundled Packages" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME platform \- System identification support code and utilities .SH SYNOPSIS .nf \fBpackage require platform ?1.0.10?\fR .sp \fBplatform::generic\fR \fBplatform::identify\fR \fBplatform::patterns \fIidentifier\fR .fi .BE .SH DESCRIPTION .PP The \fBplatform\fR package provides several utility commands useful for the identification of the architecture of a machine running Tcl. .PP Whilst Tcl provides the \fBtcl_platform\fR array for identifying the current architecture (in particular, the platform and machine elements) this is not always sufficient. This is because (on Unix machines) \fBtcl_platform\fR reflects the values returned by the \fBuname\fR command and these are not standardized across platforms and architectures. In addition, on at least one platform (AIX) the \fBtcl_platform(machine)\fR contains the CPU serial number. .PP Consequently, individual applications need to manipulate the values in \fBtcl_platform\fR (along with the output of system specific utilities) - which is both inconvenient for developers, and introduces the potential for inconsistencies in identifying architectures and in naming conventions. .PP The \fBplatform\fR package prevents such fragmentation - i.e., it establishes a standard naming convention for architectures running Tcl and makes it more convenient for developers to identify the current architecture a Tcl program is running on. .SH COMMANDS .TP \fBplatform::identify\fR . This command returns an identifier describing the platform the Tcl core is running on. The returned identifier has the general format \fIOS\fR-\fICPU\fR. The \fIOS\fR part of the identifier may contain details like kernel version, libc version, etc., and this information may contain dashes as well. The \fICPU\fR part will not contain dashes, making the preceding dash the last dash in the result. .TP \fBplatform::generic\fR . This command returns a simplified identifier describing the platform the Tcl core is running on. In contrast to \fBplatform::identify\fR it leaves out details like kernel version, libc version, etc. The returned identifier has the general format \fIOS\fR-\fICPU\fR. .TP \fBplatform::patterns \fIidentifier\fR . This command takes an identifier as returned by \fBplatform::identify\fR and returns a list of identifiers describing compatible architectures. .SH EXAMPLE .PP This can be used to allow an application to be shipped with multiple builds of a shared library, so that the same package works on many versions of an operating system. For example: .PP .CS \fBpackage require platform\fR # Assume that app script is .../theapp/bin/theapp.tcl set binDir [file dirname [file normalize [info script]]] set libDir [file join $binDir .. lib] set platLibDir [file join $libDir [\fBplatform::identify\fR]] load [file join $platLibDir support[info sharedlibextension]] .CE .SH KEYWORDS operating system, cpu architecture, platform, architecture '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/doc/ListObj.30000644000175000017500000002421712663660065013774 0ustar sergeisergei'\" '\" Copyright (c) 1996-1997 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_ListObj 3 8.0 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_ListObjAppendList, Tcl_ListObjAppendElement, Tcl_NewListObj, Tcl_SetListObj, Tcl_ListObjGetElements, Tcl_ListObjLength, Tcl_ListObjIndex, Tcl_ListObjReplace \- manipulate Tcl values as lists .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_ListObjAppendList\fR(\fIinterp, listPtr, elemListPtr\fR) .sp int \fBTcl_ListObjAppendElement\fR(\fIinterp, listPtr, objPtr\fR) .sp Tcl_Obj * \fBTcl_NewListObj\fR(\fIobjc, objv\fR) .sp \fBTcl_SetListObj\fR(\fIobjPtr, objc, objv\fR) .sp int \fBTcl_ListObjGetElements\fR(\fIinterp, listPtr, objcPtr, objvPtr\fR) .sp int \fBTcl_ListObjLength\fR(\fIinterp, listPtr, intPtr\fR) .sp int \fBTcl_ListObjIndex\fR(\fIinterp, listPtr, index, objPtrPtr\fR) .sp int \fBTcl_ListObjReplace\fR(\fIinterp, listPtr, first, count, objc, objv\fR) .SH ARGUMENTS .AS "Tcl_Obj *const" *elemListPtr in/out .AP Tcl_Interp *interp in If an error occurs while converting a value to be a list value, an error message is left in the interpreter's result value unless \fIinterp\fR is NULL. .AP Tcl_Obj *listPtr in/out Points to the list value to be manipulated. If \fIlistPtr\fR does not already point to a list value, an attempt will be made to convert it to one. .AP Tcl_Obj *elemListPtr in/out For \fBTcl_ListObjAppendList\fR, this points to a list value containing elements to be appended onto \fIlistPtr\fR. Each element of *\fIelemListPtr\fR will become a new element of \fIlistPtr\fR. If *\fIelemListPtr\fR is not NULL and does not already point to a list value, an attempt will be made to convert it to one. .AP Tcl_Obj *objPtr in For \fBTcl_ListObjAppendElement\fR, points to the Tcl value that will be appended to \fIlistPtr\fR. For \fBTcl_SetListObj\fR, this points to the Tcl value that will be converted to a list value containing the \fIobjc\fR elements of the array referenced by \fIobjv\fR. .AP int *objcPtr in Points to location where \fBTcl_ListObjGetElements\fR stores the number of element values in \fIlistPtr\fR. .AP Tcl_Obj ***objvPtr out A location where \fBTcl_ListObjGetElements\fR stores a pointer to an array of pointers to the element values of \fIlistPtr\fR. .AP int objc in The number of Tcl values that \fBTcl_NewListObj\fR will insert into a new list value, and \fBTcl_ListObjReplace\fR will insert into \fIlistPtr\fR. For \fBTcl_SetListObj\fR, the number of Tcl values to insert into \fIobjPtr\fR. .AP "Tcl_Obj *const" objv[] in An array of pointers to values. \fBTcl_NewListObj\fR will insert these values into a new list value and \fBTcl_ListObjReplace\fR will insert them into an existing \fIlistPtr\fR. Each value will become a separate list element. .AP int *intPtr out Points to location where \fBTcl_ListObjLength\fR stores the length of the list. .AP int index in Index of the list element that \fBTcl_ListObjIndex\fR is to return. The first element has index 0. .AP Tcl_Obj **objPtrPtr out Points to place where \fBTcl_ListObjIndex\fR is to store a pointer to the resulting list element value. .AP int first in Index of the starting list element that \fBTcl_ListObjReplace\fR is to replace. The list's first element has index 0. .AP int count in The number of elements that \fBTcl_ListObjReplace\fR is to replace. .BE .SH DESCRIPTION .PP Tcl list values have an internal representation that supports the efficient indexing and appending. The procedures described in this man page are used to create, modify, index, and append to Tcl list values from C code. .PP \fBTcl_ListObjAppendList\fR and \fBTcl_ListObjAppendElement\fR both add one or more values to the end of the list value referenced by \fIlistPtr\fR. \fBTcl_ListObjAppendList\fR appends each element of the list value referenced by \fIelemListPtr\fR while \fBTcl_ListObjAppendElement\fR appends the single value referenced by \fIobjPtr\fR. Both procedures will convert the value referenced by \fIlistPtr\fR to a list value if necessary. If an error occurs during conversion, both procedures return \fBTCL_ERROR\fR and leave an error message in the interpreter's result value if \fIinterp\fR is not NULL. Similarly, if \fIelemListPtr\fR does not already refer to a list value, \fBTcl_ListObjAppendList\fR will attempt to convert it to one and if an error occurs during conversion, will return \fBTCL_ERROR\fR and leave an error message in the interpreter's result value if interp is not NULL. Both procedures invalidate any old string representation of \fIlistPtr\fR and, if it was converted to a list value, free any old internal representation. Similarly, \fBTcl_ListObjAppendList\fR frees any old internal representation of \fIelemListPtr\fR if it converts it to a list value. After appending each element in \fIelemListPtr\fR, \fBTcl_ListObjAppendList\fR increments the element's reference count since \fIlistPtr\fR now also refers to it. For the same reason, \fBTcl_ListObjAppendElement\fR increments \fIobjPtr\fR's reference count. If no error occurs, the two procedures return \fBTCL_OK\fR after appending the values. .PP \fBTcl_NewListObj\fR and \fBTcl_SetListObj\fR create a new value or modify an existing value to hold the \fIobjc\fR elements of the array referenced by \fIobjv\fR where each element is a pointer to a Tcl value. If \fIobjc\fR is less than or equal to zero, they return an empty value. The new value's string representation is left invalid. The two procedures increment the reference counts of the elements in \fIobjc\fR since the list value now refers to them. The new list value returned by \fBTcl_NewListObj\fR has reference count zero. .PP \fBTcl_ListObjGetElements\fR returns a count and a pointer to an array of the elements in a list value. It returns the count by storing it in the address \fIobjcPtr\fR. Similarly, it returns the array pointer by storing it in the address \fIobjvPtr\fR. The memory pointed to is managed by Tcl and should not be freed or written to by the caller. If the list is empty, 0 is stored at \fIobjcPtr\fR and NULL at \fIobjvPtr\fR. If \fIlistPtr\fR is not already a list value, \fBTcl_ListObjGetElements\fR will attempt to convert it to one; if the conversion fails, it returns \fBTCL_ERROR\fR and leaves an error message in the interpreter's result value if \fIinterp\fR is not NULL. Otherwise it returns \fBTCL_OK\fR after storing the count and array pointer. .PP \fBTcl_ListObjLength\fR returns the number of elements in the list value referenced by \fIlistPtr\fR. It returns this count by storing an integer in the address \fIintPtr\fR. If the value is not already a list value, \fBTcl_ListObjLength\fR will attempt to convert it to one; if the conversion fails, it returns \fBTCL_ERROR\fR and leaves an error message in the interpreter's result value if \fIinterp\fR is not NULL. Otherwise it returns \fBTCL_OK\fR after storing the list's length. .PP The procedure \fBTcl_ListObjIndex\fR returns a pointer to the value at element \fIindex\fR in the list referenced by \fIlistPtr\fR. It returns this value by storing a pointer to it in the address \fIobjPtrPtr\fR. If \fIlistPtr\fR does not already refer to a list value, \fBTcl_ListObjIndex\fR will attempt to convert it to one; if the conversion fails, it returns \fBTCL_ERROR\fR and leaves an error message in the interpreter's result value if \fIinterp\fR is not NULL. If the index is out of range, that is, \fIindex\fR is negative or greater than or equal to the number of elements in the list, \fBTcl_ListObjIndex\fR stores a NULL in \fIobjPtrPtr\fR and returns \fBTCL_OK\fR. Otherwise it returns \fBTCL_OK\fR after storing the element's value pointer. The reference count for the list element is not incremented; the caller must do that if it needs to retain a pointer to the element. .PP \fBTcl_ListObjReplace\fR replaces zero or more elements of the list referenced by \fIlistPtr\fR with the \fIobjc\fR values in the array referenced by \fIobjv\fR. If \fIlistPtr\fR does not point to a list value, \fBTcl_ListObjReplace\fR will attempt to convert it to one; if the conversion fails, it returns \fBTCL_ERROR\fR and leaves an error message in the interpreter's result value if \fIinterp\fR is not NULL. Otherwise, it returns \fBTCL_OK\fR after replacing the values. If \fIobjv\fR is NULL, no new elements are added. If the argument \fIfirst\fR is zero or negative, it refers to the first element. If \fIfirst\fR is greater than or equal to the number of elements in the list, then no elements are deleted; the new elements are appended to the list. \fIcount\fR gives the number of elements to replace. If \fIcount\fR is zero or negative then no elements are deleted; the new elements are simply inserted before the one designated by \fIfirst\fR. \fBTcl_ListObjReplace\fR invalidates \fIlistPtr\fR's old string representation. The reference counts of any elements inserted from \fIobjv\fR are incremented since the resulting list now refers to them. Similarly, the reference counts for any replaced values are decremented. .PP Because \fBTcl_ListObjReplace\fR combines both element insertion and deletion, it can be used to implement a number of list operations. For example, the following code inserts the \fIobjc\fR values referenced by the array of value pointers \fIobjv\fR just before the element \fIindex\fR of the list referenced by \fIlistPtr\fR: .PP .CS result = \fBTcl_ListObjReplace\fR(interp, listPtr, index, 0, objc, objv); .CE .PP Similarly, the following code appends the \fIobjc\fR values referenced by the array \fIobjv\fR to the end of the list \fIlistPtr\fR: .PP .CS result = \fBTcl_ListObjLength\fR(interp, listPtr, &length); if (result == TCL_OK) { result = \fBTcl_ListObjReplace\fR(interp, listPtr, length, 0, objc, objv); } .CE .PP The \fIcount\fR list elements starting at \fIfirst\fR can be deleted by simply calling \fBTcl_ListObjReplace\fR with a NULL \fIobjvPtr\fR: .PP .CS result = \fBTcl_ListObjReplace\fR(interp, listPtr, first, count, 0, NULL); .CE .SH "SEE ALSO" Tcl_NewObj(3), Tcl_DecrRefCount(3), Tcl_IncrRefCount(3), Tcl_GetObjResult(3) .SH KEYWORDS append, index, insert, internal representation, length, list, list value, list type, value, value type, replace, string representation tcl8.6.5/doc/OOInitStubs.30000644000175000017500000000367012663660065014610 0ustar sergeisergei'\" '\" Copyright (c) 2012 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_OOInitStubs 3 1.0 TclOO "TclOO Library Functions" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_OOInitStubs \- initialize library access to TclOO functionality .SH SYNOPSIS .nf \fB#include \fR .sp const char * \fBTcl_OOInitStubs\fR(\fIinterp\fR) .fi .SH ARGUMENTS .AS Tcl_Interp *interp in .AP Tcl_Interp *interp in The Tcl interpreter that the TclOO API is integrated with and whose C interface is going to be used. .BE .SH DESCRIPTION .PP When an extension library is going to use the C interface exposed by TclOO, it should use \fBTcl_OOInitStubs\fR to initialize its access to that interface from within its \fI*\fB_Init\fR (or \fI*\fB_SafeInit\fR) function, passing in the \fIinterp\fR that was passed into that routine as context. If the result of calling \fBTcl_OOInitStubs\fR is NULL, the initialization failed and an error message will have been left in the interpreter's result. Otherwise, the initialization succeeded and the TclOO API may thereafter be used; the version of the TclOO API is returned. .PP When using this function, either the C #define symbol \fBUSE_TCLOO_STUBS\fR should be defined and your library code linked against the Tcl stub library, or that #define symbol should \fInot\fR be defined and your library code linked against the Tcl main library directly. .SH "BACKWARD COMPATIBILITY NOTE" .PP If you are linking against the Tcl 8.5 forward compatibility package for TclOO, \fIonly\fR the stub-enabled configuration is supported and you should also link against the TclOO independent stub library; that library is an integrated part of the main Tcl stub library in Tcl 8.6. .SH KEYWORDS stubs .SH "SEE ALSO" Tcl_InitStubs(3) .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: tcl8.6.5/doc/open.n0000644000175000017500000004060312663660065013457 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 open n 8.3 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME open \- Open a file-based or command pipeline channel .SH SYNOPSIS .sp \fBopen \fIfileName\fR .br \fBopen \fIfileName access\fR .br \fBopen \fIfileName access permissions\fR .BE .SH DESCRIPTION .PP This command opens a file, serial port, or command pipeline and returns a channel identifier that may be used in future invocations of commands like \fBread\fR, \fBputs\fR, and \fBclose\fR. If the first character of \fIfileName\fR is not \fB|\fR then the command opens a file: \fIfileName\fR gives the name of the file to open, and it must conform to the conventions described in the \fBfilename\fR manual entry. .PP The \fIaccess\fR argument, if present, indicates the way in which the file (or command pipeline) is to be accessed. In the first form \fIaccess\fR may have any of the following values: .TP 15 \fBr\fR . Open the file for reading only; the file must already exist. This is the default value if \fIaccess\fR is not specified. .TP 15 \fBr+\fR . Open the file for both reading and writing; the file must already exist. .TP 15 \fBw\fR . Open the file for writing only. Truncate it if it exists. If it does not exist, create a new file. .TP 15 \fBw+\fR . Open the file for reading and writing. Truncate it if it exists. If it does not exist, create a new file. .TP 15 \fBa\fR . Open the file for writing only. If the file does not exist, create a new empty file. Set the file pointer to the end of the file prior to each write. .TP 15 \fBa+\fR . Open the file for reading and writing. If the file does not exist, create a new empty file. Set the initial access position to the end of the file. .PP All of the legal \fIaccess\fR values above may have the character \fBb\fR added as the second or third character in the value to indicate that the opened channel should be configured as if with the \fBfconfigure\fR \fB\-translation binary\fR option, making the channel suitable for 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. One of the flags must be either \fBRDONLY\fR, \fBWRONLY\fR or \fBRDWR\fR. .TP 15 \fBRDONLY\fR . Open the file for reading only. .TP 15 \fBWRONLY\fR . Open the file for writing only. .TP 15 \fBRDWR\fR . Open the file for both reading and writing. .TP 15 \fBAPPEND\fR . Set the file pointer to the end of the file prior to each write. .TP 15 \fBBINARY\fR . Configure the opened channel with the \fB\-translation binary\fR option. .TP 15 \fBCREAT\fR . Create the file if it does not already exist (without this flag it is an error for the file not to exist). .TP 15 \fBEXCL\fR . If \fBCREAT\fR is also specified, an error is returned if the file already exists. .TP 15 \fBNOCTTY\fR . If the file is a terminal device, this flag prevents the file from becoming the controlling terminal of the process. .TP 15 \fBNONBLOCK\fR . Prevents the process from blocking while opening the file, and possibly in subsequent I/O operations. The exact behavior of this flag is system- and device-dependent; its use is discouraged (it is better to use the \fBfconfigure\fR command to put a file in nonblocking mode). For details refer to your system documentation on the \fBopen\fR system call's \fBO_NONBLOCK\fR flag. .TP 15 \fBTRUNC\fR . If the file exists it is truncated to zero length. .PP If a new file is created as part of opening it, \fIpermissions\fR (an integer) is used to set the permissions for the new file in conjunction with the process's file mode creation mask. \fIPermissions\fR defaults to 0666. .SH "COMMAND PIPELINES" .PP If the first character of \fIfileName\fR is .QW \fB|\fR then the remaining characters of \fIfileName\fR are treated as a list of arguments that describe a command pipeline to invoke, in the same style as the arguments for \fBexec\fR. In this case, the channel identifier returned by \fBopen\fR may be used to write to the command's input pipe or read from its output pipe, depending on the value of \fIaccess\fR. If write-only access is used (e.g. \fIaccess\fR is .QW \fBw\fR ), then standard output for the pipeline is directed to the current standard output unless overridden by the command. If read-only access is used (e.g. \fIaccess\fR is .QW \fBr\fR ), standard input for the pipeline is taken from the current standard input unless overridden by the command. The id of the spawned process is accessible through the \fBpid\fR command, using the channel id returned by \fBopen\fR as argument. .PP If the command (or one of the commands) executed in the command pipeline returns an error (according to the definition in \fBexec\fR), a Tcl error is generated when \fBclose\fR is called on the channel unless the pipeline is in non-blocking mode then no exit status is returned (a silent \fBclose\fR with -blocking 0). .PP It is often useful to use the \fBfileevent\fR command with pipelines so other processing may happen at the same time as running the command in the background. .SH "SERIAL COMMUNICATIONS" .PP If \fIfileName\fR refers to a serial port, then the specified serial port is opened and initialized in a platform-dependent manner. Acceptable values for the \fIfileName\fR to use to open a serial port are described in the PORTABILITY ISSUES section. .PP The \fBfconfigure\fR command can be used to query and set additional configuration options specific to serial ports (where supported): .TP \fB\-mode\fR \fIbaud\fB,\fIparity\fB,\fIdata\fB,\fIstop\fR . This option is a set of 4 comma-separated values: the baud rate, parity, number of data bits, and number of stop bits for this serial port. The \fIbaud\fR rate is a simple integer that specifies the connection speed. \fIParity\fR is one of the following letters: \fBn\fR, \fBo\fR, \fBe\fR, \fBm\fR, \fBs\fR; respectively signifying the parity options of .QW none , .QW odd , .QW even , .QW mark , or .QW space . \fIData\fR is the number of data bits and should be an integer from 5 to 8, while \fIstop\fR is the number of stop bits and should be the integer 1 or 2. .TP \fB\-handshake\fR \fItype\fR . (Windows and Unix). This option is used to setup automatic handshake control. Note that not all handshake types maybe supported by your operating system. The \fItype\fR parameter is case-independent. .RS .PP If \fItype\fR is \fBnone\fR then any handshake is switched off. \fBrtscts\fR activates hardware handshake. Hardware handshake signals are described below. For software handshake \fBxonxoff\fR the handshake characters can be redefined with \fB\-xchar\fR. An additional hardware handshake \fBdtrdsr\fR is available only under Windows. There is no default handshake configuration, the initial value depends on your operating system settings. The \fB\-handshake\fR option cannot be queried. .RE .TP \fB\-queue\fR . (Windows and Unix). The \fB\-queue\fR option can only be queried. It returns a list of two integers representing the current number of bytes in the input and output queue respectively. .TP \fB\-timeout\fR \fImsec\fR . (Windows and Unix). This option is used to set the timeout for blocking read operations. It specifies the maximum interval between the reception of two bytes in milliseconds. For Unix systems the granularity is 100 milliseconds. The \fB\-timeout\fR option does not affect write operations or nonblocking reads. This option cannot be queried. .TP \fB\-ttycontrol\fR \fI{signal boolean signal boolean ...}\fR . (Windows and Unix). This option is used to setup the handshake output lines (see below) permanently or to send a BREAK over the serial line. The \fIsignal\fR names are case-independent. \fB{RTS 1 DTR 0}\fR sets the RTS output to high and the DTR output to low. The BREAK condition (see below) is enabled and disabled with \fB{BREAK 1}\fR and \fB{BREAK 0}\fR respectively. It is not a good idea to change the \fBRTS\fR (or \fBDTR\fR) signal with active hardware handshake \fBrtscts\fR (or \fBdtrdsr\fR). The result is unpredictable. The \fB\-ttycontrol\fR option cannot be queried. .TP \fB\-ttystatus\fR . (Windows and Unix). The \fB\-ttystatus\fR option can only be queried. It returns the current modem status and handshake input signals (see below). The result is a list of signal,value pairs with a fixed order, e.g. \fB{CTS 1 DSR 0 RING 1 DCD 0}\fR. The \fIsignal\fR names are returned upper case. .TP \fB\-xchar\fR \fI{xonChar xoffChar}\fR . (Windows and Unix). This option is used to query or change the software handshake characters. Normally the operating system default should be DC1 (0x11) and DC3 (0x13) representing the ASCII standard XON and XOFF characters. .TP \fB\-pollinterval\fR \fImsec\fR . (Windows only). This option is used to set the maximum time between polling for fileevents. This affects the time interval between checking for events throughout the Tcl interpreter (the smallest value always wins). Use this option only if you want to poll the serial port more or less often than 10 msec (the default). .TP \fB\-sysbuffer\fR \fIinSize\fR .TP \fB\-sysbuffer\fR \fI{inSize outSize}\fR . (Windows only). This option is used to change the size of Windows system buffers for a serial channel. Especially at higher communication rates the default input buffer size of 4096 bytes can overrun for latent systems. The first form specifies the input buffer size, in the second form both input and output buffers are defined. .TP \fB\-lasterror\fR . (Windows only). This option is query only. In case of a serial communication error, \fBread\fR or \fBputs\fR returns a general Tcl file I/O error. \fBfconfigure\fR \fB\-lasterror\fR can be called to get a list of error details. See below for an explanation of the various error codes. .SH "SERIAL PORT SIGNALS" .PP RS-232 is the most commonly used standard electrical interface for serial communications. A negative voltage (-3V..-12V) define a mark (on=1) bit and a positive voltage (+3..+12V) define a space (off=0) bit (RS-232C). The following signals are specified for incoming and outgoing data, status lines and handshaking. Here we are using the terms \fIworkstation\fR for your computer and \fImodem\fR for the external device, because some signal names (DCD, RI) come from modems. Of course your external device may use these signal lines for other purposes. .IP \fBTXD\fR(output) \fBTransmitted Data:\fR Outgoing serial data. .IP \fBRXD\fR(input) \fBReceived Data:\fRIncoming serial data. .IP \fBRTS\fR(output) \fBRequest To Send:\fR This hardware handshake line informs the modem that your workstation is ready to receive data. Your workstation may automatically reset this signal to indicate that the input buffer is full. .IP \fBCTS\fR(input) \fBClear To Send:\fR The complement to RTS. Indicates that the modem is ready to receive data. .IP \fBDTR\fR(output) \fBData Terminal Ready:\fR This signal tells the modem that the workstation is ready to establish a link. DTR is often enabled automatically whenever a serial port is opened. .IP \fBDSR\fR(input) \fBData Set Ready:\fR The complement to DTR. Tells the workstation that the modem is ready to establish a link. .IP \fBDCD\fR(input) \fBData Carrier Detect:\fR This line becomes active when a modem detects a .QW Carrier signal. .IP \fBRI\fR(input) \fBRing Indicator:\fR Goes active when the modem detects an incoming call. .IP \fBBREAK\fR A BREAK condition is not a hardware signal line, but a logical zero on the TXD or RXD lines for a long period of time, usually 250 to 500 milliseconds. Normally a receive or transmit data signal stays at the mark (on=1) voltage until the next character is transferred. A BREAK is sometimes used to reset the communications line or change the operating mode of communications hardware. .SH "ERROR CODES (Windows only)" .PP A lot of different errors may occur during serial read operations or during event polling in background. The external device may have been switched off, the data lines may be noisy, system buffers may overrun or your mode settings may be wrong. That is why a reliable software should always \fBcatch\fR serial read operations. In cases of an error Tcl returns a general file I/O error. Then \fBfconfigure\fR \fB\-lasterror\fR may help to locate the problem. The following error codes may be returned. .TP 10 \fBRXOVER\fR . Windows input buffer overrun. The data comes faster than your scripts reads it or your system is overloaded. Use \fBfconfigure\fR \fB\-sysbuffer\fR to avoid a temporary bottleneck and/or make your script faster. .TP 10 \fBTXFULL\fR . Windows output buffer overrun. Complement to RXOVER. This error should practically not happen, because Tcl cares about the output buffer status. .TP 10 \fBOVERRUN\fR . UART buffer overrun (hardware) with data lost. The data comes faster than the system driver receives it. Check your advanced serial port settings to enable the FIFO (16550) buffer and/or setup a lower(1) interrupt threshold value. .TP 10 \fBRXPARITY\fR . A parity error has been detected by your UART. Wrong parity settings with \fBfconfigure\fR \fB\-mode\fR or a noisy data line (RXD) may cause this error. .TP 10 \fBFRAME\fR . A stop-bit error has been detected by your UART. Wrong mode settings with \fBfconfigure\fR \fB\-mode\fR or a noisy data line (RXD) may cause this error. .TP 10 \fBBREAK\fR . A BREAK condition has been detected by your UART (see above). .SH "PORTABILITY ISSUES" .TP \fBWindows \fR . Valid values for \fIfileName\fR to open a serial port are of the form \fBcom\fIX\fB\fR, where \fIX\fR is a number, generally from 1 to 9. A legacy form accepted as well is \fBcom\fIX\fB:\fR. This notation only works for serial ports from 1 to 9. An attempt to open a serial port that does not exist or has a number greater than 9 will fail. An alternate form of opening serial ports is to use the filename \fB//./comX\fR, where X is any number that corresponds to a serial port. .PP .RS When running Tcl interactively, there may be some strange interactions between the real console, if one is present, and a command pipeline that uses standard input or output. If a command pipeline is opened for reading, some of the lines entered at the console will be sent to the command pipeline and some will be sent to the Tcl evaluator. If a command pipeline is opened for writing, keystrokes entered into the console are not visible until the pipe is closed. These problems only occur because both Tcl and the child 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. .RE .TP \fBUnix\fR\0\0\0\0\0\0\0 . Valid values for \fIfileName\fR to open a serial port are generally of the form \fB/dev/tty\fIX\fR, where \fIX\fR is \fBa\fR or \fBb\fR, but the name of any pseudo-file that maps to a serial port may be used. Advanced configuration options are only supported for serial ports when Tcl is built to use the POSIX serial interface. .RS .PP When running Tcl interactively, there may be some strange interactions between the console, if one is present, and a command pipeline that uses standard input. If a command pipeline is opened for reading, some of the lines entered at the console will be sent to the command pipeline and some will be sent to the Tcl evaluator. This problem only occurs because both Tcl and the child 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, but is redirected from a file, then the above problem does not occur. .RE .PP See the \fBPORTABILITY ISSUES\fR section of the \fBexec\fR command for additional information not specific to command pipelines about executing applications on the various platforms .SH "EXAMPLE" .PP Open a command pipeline and catch any errors: .PP .CS set fl [\fBopen\fR "| ls this_file_does_not_exist"] set data [read $fl] if {[catch {close $fl} err]} { puts "ls command failed: $err" } .CE .SH "SEE ALSO" file(n), close(n), filename(n), fconfigure(n), gets(n), read(n), puts(n), exec(n), pid(n), fopen(3) .SH KEYWORDS access mode, append, create, file, non-blocking, open, permissions, pipeline, process, serial '\"Local Variables: '\"mode: nroff '\"End: tcl8.6.5/doc/Tcl_Main.30000644000175000017500000002132412663660065014110 0ustar sergeisergei'\" '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" Copyright (c) 2000 Ajuba Solutions. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_Main 3 8.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_Main, Tcl_SetStartupScript, Tcl_GetStartupScript, Tcl_SetMainLoop \- main program, startup script, and event loop definition for Tcl-based applications .SH SYNOPSIS .nf \fB#include \fR .sp \fBTcl_Main\fR(\fIargc, argv, appInitProc\fR) .sp \fBTcl_SetStartupScript\fR(\fIpath, encoding\fR) .sp Tcl_Obj * \fBTcl_GetStartupScript\fR(\fIencodingPtr\fR) .sp \fBTcl_SetMainLoop\fR(\fImainLoopProc\fR) .SH ARGUMENTS .AS Tcl_MainLoopProc *mainLoopProc .AP int argc in Number of elements in \fIargv\fR. .AP char *argv[] in Array of strings containing command-line arguments. On Windows, when using -DUNICODE, the parameter type changes to wchar_t *. .AP Tcl_AppInitProc *appInitProc in Address of an application-specific initialization procedure. The value for this argument is usually \fBTcl_AppInit\fR. .AP Tcl_Obj *path in Name of file to use as startup script, or NULL. .AP "const char" *encoding in Encoding of file to use as startup script, or NULL. .AP "const char" **encodingPtr out If non-NULL, location to write a copy of the (const char *) pointing to the encoding name. .AP Tcl_MainLoopProc *mainLoopProc in Address of an application-specific event loop procedure. .BE .SH DESCRIPTION .PP \fBTcl_Main\fR can serve as the main program for Tcl-based shell applications. A .QW "shell application" is a program like tclsh or wish that supports both interactive interpretation of Tcl and evaluation of a script contained in a file given as a command line argument. \fBTcl_Main\fR is offered as a convenience to developers of shell applications, so they do not have to reproduce all of the code for proper initialization of the Tcl library and interactive shell operation. Other styles of embedding Tcl in an application are not supported by \fBTcl_Main\fR. Those must be achieved by calling lower level functions in the Tcl library directly. .PP The \fBTcl_Main\fR function has been offered by the Tcl library since release Tcl 7.4. In older releases of Tcl, the Tcl library itself defined a function \fBmain\fR, but that lacks flexibility of embedding style and having a function \fBmain\fR in a library (particularly a shared library) causes problems on many systems. Having \fBmain\fR in the Tcl library would also make it hard to use Tcl in C++ programs, since C++ programs must have special C++ \fBmain\fR functions. .PP Normally each shell application contains a small \fBmain\fR function that does nothing but invoke \fBTcl_Main\fR. \fBTcl_Main\fR then does all the work of creating and running a \fBtclsh\fR-like application. .PP \fBTcl_Main\fR is not provided by the public interface of Tcl's stub library. Programs that call \fBTcl_Main\fR must be linked against the standard Tcl library. Extensions (stub-enabled or not) are not intended to call \fBTcl_Main\fR. .PP \fBTcl_Main\fR is not thread-safe. It should only be called by a single master thread of a multi-threaded application. This restriction is not a problem with normal use described above. .PP \fBTcl_Main\fR and therefore all applications based upon it, like \fBtclsh\fR, use \fBTcl_GetStdChannel\fR to initialize the standard channels to their default values. See \fBTcl_StandardChannels\fR for more information. .PP \fBTcl_Main\fR supports two modes of operation, depending on whether the filename and encoding of a startup script has been established. The routines \fBTcl_SetStartupScript\fR and \fBTcl_GetStartupScript\fR are the tools for controlling this configuration of \fBTcl_Main\fR. .PP \fBTcl_SetStartupScript\fR registers the value \fIpath\fR as the name of the file for \fBTcl_Main\fR to evaluate as its startup script. The value \fIencoding\fR is Tcl's name for the encoding used to store the text in that file. A value of \fBNULL\fR for \fIencoding\fR is a signal to use the system encoding. A value of \fBNULL\fR for \fIpath\fR erases any existing registration so that \fBTcl_Main\fR will not evaluate any startup script. .PP \fBTcl_GetStartupScript\fR queries the registered file name and encoding set by the most recent \fBTcl_SetStartupScript\fR call in the same thread. The stored file name is returned, and the stored encoding name is written to space pointed to by \fIencodingPtr\fR, when that is not NULL. .PP The file name and encoding values managed by the routines \fBTcl_SetStartupScript\fR and \fBTcl_GetStartupScript\fR are stored per-thread. Although the storage and retrieval functions of these routines work in any thread, only those calls in the same master thread as \fBTcl_Main\fR can have any influence on it. .PP The caller of \fBTcl_Main\fR may call \fBTcl_SetStartupScript\fR first to establish its desired startup script. If \fBTcl_Main\fR finds that no such startup script has been established, it consults the first few arguments in \fIargv\fR. If they match ?\fB\-encoding \fIname\fR? \fIfileName\fR, where \fIfileName\fR does not begin with the character \fI\-\fR, then \fIfileName\fR is taken to be the name of a file containing a \fIstartup script\fR, and \fIname\fR is taken to be the name of the encoding of the contents of that file. \fBTcl_Main\fR then calls \fBTcl_SetStartupScript\fR with these values. .PP \fBTcl_Main\fR then defines in its master interpreter the Tcl variables \fIargc\fR, \fIargv\fR, \fIargv0\fR, and \fItcl_interactive\fR, as described in the documentation for \fBtclsh\fR. .PP When it has finished its own initialization, but before it processes commands, \fBTcl_Main\fR calls the procedure given by the \fIappInitProc\fR argument. This procedure provides a .QW hook for the application to perform its own initialization of the interpreter created by \fBTcl_Main\fR, such as defining application-specific commands. The application initialization routine might also call \fBTcl_SetStartupScript\fR to (re-)set the file and encoding to be used as a startup script. The procedure must have an interface that matches the type \fBTcl_AppInitProc\fR: .PP .CS typedef int \fBTcl_AppInitProc\fR( Tcl_Interp *\fIinterp\fR); .CE .PP \fIAppInitProc\fR is almost always a pointer to \fBTcl_AppInit\fR; for more details on this procedure, see the documentation for \fBTcl_AppInit\fR. .PP When the \fIappInitProc\fR is finished, \fBTcl_Main\fR calls \fBTcl_GetStartupScript\fR to determine what startup script has been requested, if any. If a startup script has been provided, \fBTcl_Main\fR attempts to evaluate it. Otherwise, interactive mode begins with examination of the variable \fItcl_rcFileName\fR in the master interpreter. If that variable exists and holds the name of a readable file, the contents of that file are evaluated in the master interpreter. Then interactive operations begin, with prompts and command evaluation results written to the standard output channel, and commands read from the standard input channel and then evaluated. The prompts written to the standard output channel may be customized by defining the Tcl variables \fItcl_prompt1\fR and \fItcl_prompt2\fR as described in the documentation for \fBtclsh\fR. The prompts and command evaluation results are written to the standard output channel only if the Tcl variable \fItcl_interactive\fR in the master interpreter holds a non-zero integer value. .PP \fBTcl_SetMainLoop\fR allows setting an event loop procedure to be run. This allows, for example, Tk to be dynamically loaded and set its event loop. The event loop will run following the startup script. If you are in interactive mode, setting the main loop procedure will cause the prompt to become fileevent based and then the loop procedure is called. When the loop procedure returns in interactive mode, interactive operation will continue. The main loop procedure must have an interface that matches the type \fBTcl_MainLoopProc\fR: .PP .CS typedef void \fBTcl_MainLoopProc\fR(void); .CE .PP \fBTcl_Main\fR does not return. Normally a program based on \fBTcl_Main\fR will terminate when the \fBexit\fR command is evaluated. In interactive mode, if an EOF or channel error is encountered on the standard input channel, then \fBTcl_Main\fR itself will evaluate the \fBexit\fR command after the main loop procedure (if any) returns. In non-interactive mode, after \fBTcl_Main\fR evaluates the startup script, and the main loop procedure (if any) returns, \fBTcl_Main\fR will also evaluate the \fBexit\fR command. .SH "SEE ALSO" tclsh(1), Tcl_GetStdChannel(3), Tcl_StandardChannels(3), Tcl_AppInit(3), exit(n), encoding(n) .SH KEYWORDS application-specific initialization, command-line arguments, main program tcl8.6.5/doc/CrtCloseHdlr.30000644000175000017500000000337612663660065014761 0ustar sergeisergei'\" '\" Copyright (c) 1994-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_CreateCloseHandler 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_CreateCloseHandler, Tcl_DeleteCloseHandler \- arrange for callbacks when channels are closed .SH SYNOPSIS .nf \fB#include \fR .sp void \fBTcl_CreateCloseHandler\fR(\fIchannel, proc, clientData\fR) .sp void \fBTcl_DeleteCloseHandler\fR(\fIchannel, proc, clientData\fR) .sp .SH ARGUMENTS .AS Tcl_CloseProc clientData .AP Tcl_Channel channel in The channel for which to create or delete a close callback. .AP Tcl_CloseProc *proc in The procedure to call as the callback. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR. .BE .SH DESCRIPTION .PP \fBTcl_CreateCloseHandler\fR arranges for \fIproc\fR to be called when \fIchannel\fR is closed with \fBTcl_Close\fR or \fBTcl_UnregisterChannel\fR, or using the Tcl \fBclose\fR command. \fIProc\fR should match the following prototype: .PP .CS typedef void \fBTcl_CloseProc\fR( ClientData \fIclientData\fR); .CE .PP The \fIclientData\fR is the same as the value provided in the call to \fBTcl_CreateCloseHandler\fR. .PP \fBTcl_DeleteCloseHandler\fR removes a close callback for \fIchannel\fR. The \fIproc\fR and \fIclientData\fR identify which close callback to remove; \fBTcl_DeleteCloseHandler\fR does nothing if its \fIproc\fR and \fIclientData\fR arguments do not match the \fIproc\fR and \fIclientData\fR for a close handler for \fIchannel\fR. .SH "SEE ALSO" close(n), Tcl_Close(3), Tcl_UnregisterChannel(3) .SH KEYWORDS callback, channel closing tcl8.6.5/doc/Signal.30000644000175000017500000000175612663660065013646 0ustar sergeisergei'\" '\" Copyright (c) 2001 ActiveState Tool Corp. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_SignalId 3 8.3 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_SignalId, Tcl_SignalMsg \- Convert signal codes .SH SYNOPSIS .nf \fB#include \fR .sp const char * \fBTcl_SignalId\fR(\fIsig\fR) .sp const char * \fBTcl_SignalMsg\fR(\fIsig\fR) .sp .SH ARGUMENTS .AS int sig .AP int sig in A POSIX signal number such as \fBSIGPIPE\fR. .BE .SH DESCRIPTION .PP \fBTcl_SignalId\fR and \fBTcl_SignalMsg\fR return a string representation of the provided signal number (\fIsig\fR). \fBTcl_SignalId\fR returns a machine-readable textual identifier such as .QW SIGPIPE . \fBTcl_SignalMsg\fR returns a human-readable string such as .QW "bus error" . The strings returned by these functions are statically allocated and the caller must not free or modify them. .SH KEYWORDS signals, signal numbers tcl8.6.5/doc/GetHostName.30000644000175000017500000000120512663660065014574 0ustar sergeisergei'\" '\" Copyright (c) 1998-2000 by Scriptics Corporation. '\" All rights reserved. '\" .TH Tcl_GetHostName 3 8.3 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_GetHostName \- get the name of the local host .SH SYNOPSIS .nf \fB#include \fR .sp const char * \fBTcl_GetHostName\fR() .BE .SH DESCRIPTION .PP \fBTcl_GetHostName\fR is a utility procedure used by some of the Tcl commands. It returns a pointer to a string containing the name for the current machine, or an empty string if the name cannot be determined. The string is statically allocated, and the caller must not modify of free it. .PP .SH KEYWORDS hostname tcl8.6.5/doc/SetChanErr.30000644000175000017500000001405612663660065014424 0ustar sergeisergei'\" '\" Copyright (c) 2005 Andreas Kupries '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_SetChannelError 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Tcl_SetChannelError, Tcl_SetChannelErrorInterp, Tcl_GetChannelError, Tcl_GetChannelErrorInterp \- functions to create/intercept Tcl errors by channel drivers. .SH SYNOPSIS .nf \fB#include \fR .sp void \fBTcl_SetChannelError\fR(\fIchan, msg\fR) .sp void \fBTcl_SetChannelErrorInterp\fR(\fIinterp, msg\fR) .sp void \fBTcl_GetChannelError\fR(\fIchan, msgPtr\fR) .sp void \fBTcl_GetChannelErrorInterp\fR(\fIinterp, msgPtr\fR) .sp .SH ARGUMENTS .AS Tcl_Channel chan .AP Tcl_Channel chan in Refers to the Tcl channel whose bypass area is accessed. .AP Tcl_Interp* interp in Refers to the Tcl interpreter whose bypass area is accessed. .AP Tcl_Obj* msg in Error message put into a bypass area. A list of return options and values, followed by a string message. Both message and the option/value information are optional. .AP Tcl_Obj** msgPtr out Reference to a place where the message stored in the accessed bypass area can be stored in. .BE .SH DESCRIPTION .PP The current definition of a Tcl channel driver does not permit the direct return of arbitrary error messages, except for the setting and retrieval of channel options. All other functions are restricted to POSIX error codes. .PP The functions described here overcome this limitation. Channel drivers are allowed to use \fBTcl_SetChannelError\fR and \fBTcl_SetChannelErrorInterp\fR to place arbitrary error messages in \fBbypass areas\fR defined for channels and interpreters. And the generic I/O layer uses \fBTcl_GetChannelError\fR and \fBTcl_GetChannelErrorInterp\fR to look for messages in the bypass areas and arrange for their return as errors. The POSIX error codes set by a driver are used now if and only if no messages are present. .PP \fBTcl_SetChannelError\fR stores error information in the bypass area of the specified channel. The number of references to the \fBmsg\fR value goes up by one. Previously stored information will be discarded, by releasing the reference held by the channel. The channel reference must not be NULL. .PP \fBTcl_SetChannelErrorInterp\fR stores error information in the bypass area of the specified interpreter. The number of references to the \fBmsg\fR value goes up by one. Previously stored information will be discarded, by releasing the reference held by the interpreter. The interpreter reference must not be NULL. .PP \fBTcl_GetChannelError\fR places either the error message held in the bypass area of the specified channel into \fImsgPtr\fR, or NULL; and resets the bypass, that is, after an invocation all following invocations will return NULL, until an intervening invocation of \fBTcl_SetChannelError\fR with a non-NULL message. The \fImsgPtr\fR must not be NULL. The reference count of the message is not touched. The reference previously held by the channel is now held by the caller of the function and it is its responsibility to release that reference when it is done with the value. .PP \fBTcl_GetChannelErrorInterp\fR places either the error message held in the bypass area of the specified interpreter into \fImsgPtr\fR, or NULL; and resets the bypass, that is, after an invocation all following invocations will return NULL, until an intervening invocation of \fBTcl_SetChannelErrorInterp\fR with a non-NULL message. The \fImsgPtr\fR must not be NULL. The reference count of the message is not touched. The reference previously held by the interpreter is now held by the caller of the function and it is its responsibility to release that reference when it is done with the value. .PP Which functions of a channel driver are allowed to use which bypass function is listed below, as is which functions of the public channel API may leave a messages in the bypass areas. .IP \fBTcl_DriverCloseProc\fR May use \fBTcl_SetChannelErrorInterp\fR, and only this function. .IP \fBTcl_DriverInputProc\fR May use \fBTcl_SetChannelError\fR, and only this function. .IP \fBTcl_DriverOutputProc\fR May use \fBTcl_SetChannelError\fR, and only this function. .IP \fBTcl_DriverSeekProc\fR May use \fBTcl_SetChannelError\fR, and only this function. .IP \fBTcl_DriverWideSeekProc\fR May use \fBTcl_SetChannelError\fR, and only this function. .IP \fBTcl_DriverSetOptionProc\fR Has already the ability to pass arbitrary error messages. Must \fInot\fR use any of the new functions. .IP \fBTcl_DriverGetOptionProc\fR Has already the ability to pass arbitrary error messages. Must \fInot\fR use any of the new functions. .IP \fBTcl_DriverWatchProc\fR Must \fInot\fR use any of the new functions. Is internally called and has no ability to return any type of error whatsoever. .IP \fBTcl_DriverBlockModeProc\fR May use \fBTcl_SetChannelError\fR, and only this function. .IP \fBTcl_DriverGetHandleProc\fR Must \fInot\fR use any of the new functions. It is only a low-level function, and not used by Tcl commands. .IP \fBTcl_DriverHandlerProc\fR Must \fInot\fR use any of the new functions. Is internally called and has no ability to return any type of error whatsoever. .PP Given the information above the following public functions of the Tcl C API are affected by these changes; when these functions are called, the channel may now contain a stored arbitrary error message requiring processing by the caller. .DS .ta 1.9i 4i \fBTcl_Flush\fR \fBTcl_GetsObj\fR \fBTcl_Gets\fR \fBTcl_ReadChars\fR \fBTcl_ReadRaw\fR \fBTcl_Read\fR \fBTcl_Seek\fR \fBTcl_StackChannel\fR \fBTcl_Tell\fR \fBTcl_WriteChars\fR \fBTcl_WriteObj\fR \fBTcl_WriteRaw\fR \fBTcl_Write\fR .DE .PP All other API functions are unchanged. In particular, the functions below leave all their error information in the interpreter result. .DS .ta 1.9i 4i \fBTcl_Close\fR \fBTcl_UnstackChannel\fR \fBTcl_UnregisterChannel\fR .DE .SH "SEE ALSO" Tcl_Close(3), Tcl_OpenFileChannel(3), Tcl_SetErrno(3) .SH KEYWORDS channel driver, error messages, channel type tcl8.6.5/doc/packagens.n0000644000175000017500000000360212663660065014450 0ustar sergeisergei'\" '\" Copyright (c) 1998-2000 by Scriptics Corporation. '\" All rights reserved. '\" .TH pkg::create n 8.3 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME pkg::create \- Construct an appropriate 'package ifneeded' command for a given package specification .SH SYNOPSIS \fB::pkg::create\fR \fB\-name \fIpackageName \fB\-version \fIpackageVersion\fR ?\fB\-load \fIfilespec\fR? ... ?\fB\-source \fIfilespec\fR? ... .BE .SH DESCRIPTION .PP \fB::pkg::create\fR is a utility procedure that is part of the standard Tcl library. It is used to create an appropriate \fBpackage ifneeded\fR command for a given package specification. It can be used to construct a \fBpkgIndex.tcl\fR file for use with the \fBpackage\fR mechanism. .SH OPTIONS The parameters supported are: .TP \fB\-name \fIpackageName\fR This parameter specifies the name of the package. It is required. .TP \fB\-version \fIpackageVersion\fR 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 \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 list of procedures is empty or omitted, \fB::pkg::create\fR will set up the library for direct loading (see \fBpkg_mkIndex\fR). Any number of \fB\-load\fR parameters may be specified. .TP \fB\-source \fIfilespec\fR This parameter is similar to the \fB\-load\fR parameter, except that it specifies a Tcl library that must be loaded with the \fBsource\fR command. Any number of \fB\-source\fR parameters may be specified. .PP At least one \fB\-load\fR or \fB\-source\fR parameter must be given. .SH "SEE ALSO" package(n) .SH KEYWORDS auto-load, index, package, version tcl8.6.5/doc/UpVar.30000644000175000017500000000547312663660065013466 0ustar sergeisergei'\" '\" Copyright (c) 1994 The Regents of the University of California. '\" Copyright (c) 1994-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_UpVar 3 7.4 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_UpVar, Tcl_UpVar2 \- link one variable to another .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_UpVar(\fIinterp, frameName, sourceName, destName, flags\fB)\fR .sp int \fBTcl_UpVar2(\fIinterp, frameName, name1, name2, destName, flags\fB)\fR .SH ARGUMENTS .AS "const char" *sourceName .AP Tcl_Interp *interp in Interpreter containing variables; also used for error reporting. .AP "const char" *frameName in Identifies the stack frame containing source variable. May have any of the forms accepted by the \fBupvar\fR command, such as \fB#0\fR or \fB1\fR. .AP "const char" *sourceName in Name of source variable, in the frame given by \fIframeName\fR. May refer to a scalar variable or to an array variable with a parenthesized index. .AP "const char" *destName in Name of destination variable, which is to be linked to source variable so that references to \fIdestName\fR refer to the other variable. Must not currently exist except as an upvar-ed variable. .AP int flags in One of \fBTCL_GLOBAL_ONLY\fR, \fBTCL_NAMESPACE_ONLY\fR or 0; if non-zero, then \fIdestName\fR is a global or namespace variable; otherwise it is local to the current procedure (or current namespace if no procedure is active). .AP "const char" *name1 in First part of source variable's name (scalar name, or name of array without array index). .AP "const char" *name2 in If source variable is an element of an array, gives the index of the element. For scalar source variables, is NULL. .BE .SH DESCRIPTION .PP \fBTcl_UpVar\fR and \fBTcl_UpVar2\fR provide the same functionality as the \fBupvar\fR command: they make a link from a source variable to a destination variable, so that references to the destination are passed transparently through to the source. The name of the source variable may be specified either as a single string such as \fBxyx\fR or \fBa(24)\fR (by calling \fBTcl_UpVar\fR) or in two parts where the array name has been separated from the element name (by calling \fBTcl_UpVar2\fR). The destination variable name is specified in a single string; it may not be an array element. .PP Both procedures return either \fBTCL_OK\fR or \fBTCL_ERROR\fR, and they leave an error message in the interpreter's result if an error occurs. .PP As with the \fBupvar\fR command, the source variable need not exist; if it does exist, unsetting it later does not destroy the link. The destination variable may exist at the time of the call, but if so it must exist as a linked variable. .SH KEYWORDS linked variable, upvar, variable tcl8.6.5/doc/set.n0000644000175000017500000000470112663660065013310 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 set n "" Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME set \- Read and write variables .SH SYNOPSIS \fBset \fIvarName \fR?\fIvalue\fR? .BE .SH DESCRIPTION .PP Returns the value of variable \fIvarName\fR. If \fIvalue\fR is specified, then set the value of \fIvarName\fR to \fIvalue\fR, creating a new variable if one does not already exist, and return its value. If \fIvarName\fR contains an open parenthesis and ends with a close parenthesis, then it refers to an array element: the characters before the first open parenthesis are the name of the array, and the characters between the parentheses are the index within the array. Otherwise \fIvarName\fR refers to a scalar variable. .PP If \fIvarName\fR includes namespace qualifiers (in the array name if it refers to an array element), or if \fIvarName\fR is unqualified (does not include the names of any containing namespaces) but no procedure is active, \fIvarName\fR refers to a namespace variable resolved according to the rules described under \fBNAME RESOLUTION\fR in the \fBnamespace\fR manual page. .PP If a procedure is active and \fIvarName\fR is unqualified, then \fIvarName\fR refers to a parameter or local variable of the procedure, unless \fIvarName\fR was declared to resolve differently through one of the \fBglobal\fR, \fBvariable\fR or \fBupvar\fR commands. .SH EXAMPLES .PP Store a random number in the variable \fIr\fR: .PP .CS \fBset\fR r [expr {rand()}] .CE .PP Store a short message in an array element: .PP .CS \fBset\fR anAry(msg) "Hello, World!" .CE .PP Store a short message in an array element specified by a variable: .PP .CS \fBset\fR elemName "msg" \fBset\fR anAry($elemName) "Hello, World!" .CE .PP Copy a value into the variable \fIout\fR from a variable whose name is stored in the \fIvbl\fR (note that it is often easier to use arrays in practice instead of doing double-dereferencing): .PP .CS \fBset\fR in0 "small random" \fBset\fR in1 "large random" \fBset\fR vbl in[expr {rand() >= 0.5}] \fBset\fR out [\fBset\fR $vbl] .CE .SH "SEE ALSO" expr(n), global(n), namespace(n), proc(n), trace(n), unset(n), upvar(n), variable(n) .SH KEYWORDS read, write, variable tcl8.6.5/doc/FindExec.30000644000175000017500000000451412663660065014111 0ustar sergeisergei'\" '\" 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_FindExecutable 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_FindExecutable, Tcl_GetNameOfExecutable \- identify or return the name of the binary file containing the application .SH SYNOPSIS .nf \fB#include \fR .sp void \fBTcl_FindExecutable\fR(\fIargv0\fR) .sp const char * \fBTcl_GetNameOfExecutable\fR() .SH ARGUMENTS .AS char *argv0 .AP char *argv0 in The first command-line argument to the program, which gives the application's name. .BE .SH DESCRIPTION .PP The \fBTcl_FindExecutable\fR procedure computes the full path name of the executable file from which the application was invoked and saves it for Tcl's internal use. The executable's path name is needed for several purposes in Tcl. For example, it is needed on some platforms in the implementation of the \fBload\fR command. It is also returned by the \fBinfo nameofexecutable\fR command. .PP On UNIX platforms this procedure is typically invoked as the very first thing in the application's main program; it must be passed \fIargv[0]\fR as its argument. It is important not to change the working directory before the invocation. \fBTcl_FindExecutable\fR uses \fIargv0\fR along with the \fBPATH\fR environment variable to find the application's executable, if possible. If it fails to find the binary, then future calls to \fBinfo nameofexecutable\fR will return an empty string. .PP On Windows platforms this procedure is typically invoked as the very first thing in the application's main program as well; Its \fIargv[0]\fR argument is only used to indicate whether the executable has a stderr channel (any non-null value) or not (the value null). If \fBTcl_SetPanicProc\fR is never called and no debugger is running, this determines whether the panic message is sent to stderr or to a standard system dialog. .PP \fBTcl_GetNameOfExecutable\fR simply returns a pointer to the internal full path name of the executable file as computed by \fBTcl_FindExecutable\fR. This procedure call is the C API equivalent to the \fBinfo nameofexecutable\fR command. NULL is returned if the internal full path name has not been computed or unknown. .SH KEYWORDS binary, executable file tcl8.6.5/doc/flush.n0000644000175000017500000000303312663660065013633 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 flush n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME flush \- Flush buffered output for a channel .SH SYNOPSIS \fBflush \fIchannelId\fR .BE .SH DESCRIPTION .PP Flushes any output that has been buffered for \fIchannelId\fR. .PP \fIChannelId\fR must be an identifier for an open channel such as a Tcl standard channel (\fBstdout\fR or \fBstderr\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. The channel must have been opened for writing. .PP If the channel is in blocking mode the command does not return until all the buffered output has been flushed to the channel. If the channel is in nonblocking mode, the command may return before all buffered output has been flushed; the remainder will be flushed in the background as fast as the underlying file or device is able to absorb it. .SH EXAMPLE .PP Prompt for the user to type some information in on the console: .PP .CS puts -nonewline "Please type your name: " \fBflush\fR stdout gets stdin name puts "Hello there, $name!" .CE .SH "SEE ALSO" file(n), open(n), socket(n), Tcl_StandardChannels(3) .SH KEYWORDS blocking, buffer, channel, flush, nonblocking, output tcl8.6.5/doc/CrtInterp.30000644000175000017500000001557712663660065014351 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-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_CreateInterp 3 7.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CreateInterp, Tcl_DeleteInterp, Tcl_InterpActive, Tcl_InterpDeleted \- create and delete Tcl command interpreters .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Interp * \fBTcl_CreateInterp\fR() .sp \fBTcl_DeleteInterp\fR(\fIinterp\fR) .sp int \fBTcl_InterpDeleted\fR(\fIinterp\fR) .sp .VS 8.6 int \fBTcl_InterpActive\fR(\fIinterp\fR) .VE 8.6 .SH ARGUMENTS .AS Tcl_Interp *interp .AP Tcl_Interp *interp in Token for interpreter to be destroyed or queried. .BE .SH DESCRIPTION .PP \fBTcl_CreateInterp\fR creates a new interpreter structure and returns a token for it. The token is required in calls to most other Tcl procedures, such as \fBTcl_CreateCommand\fR, \fBTcl_Eval\fR, and \fBTcl_DeleteInterp\fR. The token returned by \fBTcl_CreateInterp\fR may only be passed to Tcl routines called from the same thread as the original \fBTcl_CreateInterp\fR call. It is not safe for multiple threads to pass the same token to Tcl's routines. The new interpreter is initialized with the built-in Tcl commands and with standard variables like \fBtcl_platform\fR and \fBenv\fR. To bind in additional commands, call \fBTcl_CreateCommand\fR, and to create additional variables, call \fBTcl_SetVar\fR. .PP \fBTcl_DeleteInterp\fR marks an interpreter as deleted; the interpreter will eventually be deleted when all calls to \fBTcl_Preserve\fR for it have been matched by calls to \fBTcl_Release\fR. At that time, all of the resources associated with it, including variables, procedures, and application-specific command bindings, will be deleted. After \fBTcl_DeleteInterp\fR returns any attempt to use \fBTcl_Eval\fR on the interpreter will fail and return \fBTCL_ERROR\fR. After the call to \fBTcl_DeleteInterp\fR it is safe to examine the interpreter's result, query or set the values of variables, define, undefine or retrieve procedures, and examine the runtime evaluation stack. See below, in the section \fBINTERPRETERS AND MEMORY MANAGEMENT\fR for details. .PP \fBTcl_InterpDeleted\fR returns nonzero if \fBTcl_DeleteInterp\fR was called with \fIinterp\fR as its argument; this indicates that the interpreter will eventually be deleted, when the last call to \fBTcl_Preserve\fR for it is matched by a call to \fBTcl_Release\fR. If nonzero is returned, further calls to \fBTcl_Eval\fR in this interpreter will return \fBTCL_ERROR\fR. .PP \fBTcl_InterpDeleted\fR is useful in deletion callbacks to distinguish between when only the memory the callback is responsible for is being deleted and when the whole interpreter is being deleted. In the former case the callback may recreate the data being deleted, but this would lead to an infinite loop if the interpreter were being deleted. .PP .VS 8.6 \fBTcl_InterpActive\fR is useful for determining whether there is any execution of scripts ongoing in an interpreter, which is a useful piece of information when Tcl is embedded in a garbage-collected environment and it becomes necessary to determine whether the interpreter is a candidate for deletion. The function returns a true value if the interpreter has at least one active execution running inside it, and a false value otherwise. .VE 8.6 .SH "INTERPRETERS AND MEMORY MANAGEMENT" .PP \fBTcl_DeleteInterp\fR can be called at any time on an interpreter that may be used by nested evaluations and C code in various extensions. Tcl implements a simple mechanism that allows callers to use interpreters without worrying about the interpreter being deleted in a nested call, and without requiring special code to protect the interpreter, in most cases. This mechanism ensures that nested uses of an interpreter can safely continue using it even after \fBTcl_DeleteInterp\fR is called. .PP The mechanism relies on matching up calls to \fBTcl_Preserve\fR with calls to \fBTcl_Release\fR. If \fBTcl_DeleteInterp\fR has been called, only when the last call to \fBTcl_Preserve\fR is matched by a call to \fBTcl_Release\fR, will the interpreter be freed. See the manual entry for \fBTcl_Preserve\fR for a description of these functions. .PP The rules for when the user of an interpreter must call \fBTcl_Preserve\fR and \fBTcl_Release\fR are simple: .TP \fBInterpreters Passed As Arguments\fR . Functions that are passed an interpreter as an argument can safely use the interpreter without any special protection. Thus, when you write an extension consisting of new Tcl commands, no special code is needed to protect interpreters received as arguments. This covers the majority of all uses. .TP \fBInterpreter Creation And Deletion\fR . When a new interpreter is created and used in a call to \fBTcl_Eval\fR, \fBTcl_VarEval\fR, \fBTcl_GlobalEval\fR, \fBTcl_SetVar\fR, or \fBTcl_GetVar\fR, a pair of calls to \fBTcl_Preserve\fR and \fBTcl_Release\fR should be wrapped around all uses of the interpreter. Remember that it is unsafe to use the interpreter once \fBTcl_Release\fR has been called. To ensure that the interpreter is properly deleted when it is no longer needed, call \fBTcl_InterpDeleted\fR to test if some other code already called \fBTcl_DeleteInterp\fR; if not, call \fBTcl_DeleteInterp\fR before calling \fBTcl_Release\fR in your own code. .TP \fBRetrieving An Interpreter From A Data Structure\fR . When an interpreter is retrieved from a data structure (e.g. the client data of a callback) for use in one of the evaluation functions (\fBTcl_Eval\fR, \fBTcl_VarEval\fR, \fBTcl_GlobalEval\fR, \fBTcl_EvalObjv\fR, etc.) or variable access functions (\fBTcl_SetVar\fR, \fBTcl_GetVar\fR, \fBTcl_SetVar2Ex\fR, etc.), a pair of calls to \fBTcl_Preserve\fR and \fBTcl_Release\fR should be wrapped around all uses of the interpreter; it is unsafe to reuse the interpreter once \fBTcl_Release\fR has been called. If an interpreter is stored inside a callback data structure, an appropriate deletion cleanup mechanism should be set up by the code that creates the data structure so that the interpreter is removed from the data structure (e.g. by setting the field to NULL) when the interpreter is deleted. Otherwise, you may be using an interpreter that has been freed and whose memory may already have been reused. .PP All uses of interpreters in Tcl and Tk have already been protected. Extension writers should ensure that their code also properly protects any additional interpreters used, as described above. .PP .VS 8.6 Note that the protection mechanisms do not work well with conventional garbage collection systems. When in such a managed environment, \fBTcl_InterpActive\fR should be used to determine when an interpreter is a candidate for deletion due to inactivity. .VE 8.6 .SH "SEE ALSO" Tcl_Preserve(3), Tcl_Release(3) .SH KEYWORDS command, create, delete, interpreter tcl8.6.5/doc/Thread.30000644000175000017500000002314112663660065013630 0ustar sergeisergei'\" '\" Copyright (c) 1999 Scriptics Corporation '\" Copyright (c) 1998 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Threads 3 "8.1" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_ConditionNotify, Tcl_ConditionWait, Tcl_ConditionFinalize, Tcl_GetThreadData, Tcl_MutexLock, Tcl_MutexUnlock, Tcl_MutexFinalize, Tcl_CreateThread, Tcl_JoinThread \- Tcl thread support .SH SYNOPSIS .nf \fB#include \fR .sp void \fBTcl_ConditionNotify\fR(\fIcondPtr\fR) .sp void \fBTcl_ConditionWait\fR(\fIcondPtr, mutexPtr, timePtr\fR) .sp void \fBTcl_ConditionFinalize\fR(\fIcondPtr\fR) .sp Void * \fBTcl_GetThreadData\fR(\fIkeyPtr, size\fR) .sp void \fBTcl_MutexLock\fR(\fImutexPtr\fR) .sp void \fBTcl_MutexUnlock\fR(\fImutexPtr\fR) .sp void \fBTcl_MutexFinalize\fR(\fImutexPtr\fR) .sp int \fBTcl_CreateThread\fR(\fIidPtr, proc, clientData, stackSize, flags\fR) .sp int \fBTcl_JoinThread\fR(\fIid, result\fR) .SH ARGUMENTS .AS Tcl_CreateThreadProc proc out .AP Tcl_Condition *condPtr in A condition variable, which must be associated with a mutex lock. .AP Tcl_Mutex *mutexPtr in A mutex lock. .AP "const Tcl_Time" *timePtr in A time limit on the condition wait. NULL to wait forever. Note that a polling value of 0 seconds does not make much sense. .AP Tcl_ThreadDataKey *keyPtr in This identifies a block of thread local storage. The key should be static and process-wide, yet each thread will end up associating a different block of storage with this key. .AP int *size in The size of the thread local storage block. This amount of data is allocated and initialized to zero the first time each thread calls \fBTcl_GetThreadData\fR. .AP Tcl_ThreadId *idPtr out The referred storage will contain the id of the newly created thread as returned by the operating system. .AP Tcl_ThreadId id in Id of the thread waited upon. .AP Tcl_ThreadCreateProc *proc in This procedure will act as the \fBmain()\fR of the newly created thread. The specified \fIclientData\fR will be its sole argument. .AP ClientData clientData in Arbitrary information. Passed as sole argument to the \fIproc\fR. .AP int stackSize in The size of the stack given to the new thread. .AP int flags in Bitmask containing flags allowing the caller to modify behavior of the new thread. .AP int *result out The referred storage is used to place the exit code of the thread waited upon into it. .BE .SH INTRODUCTION Beginning with the 8.1 release, the Tcl core is thread safe, which allows you to incorporate Tcl into multithreaded applications without customizing the Tcl core. Starting with the 8.6 release, Tcl multithreading support is on by default. To disable Tcl multithreading support, you must include the \fB\-\|\-disable-threads\fR option to \fBconfigure\fR when you configure and compile your Tcl core. .PP An important constraint of the Tcl threads implementation is that \fIonly the thread that created a Tcl interpreter can use that interpreter\fR. In other words, multiple threads can not access the same Tcl interpreter. (However, a single thread can safely create and use multiple interpreters.) .SH DESCRIPTION Tcl provides \fBTcl_CreateThread\fR for creating threads. The caller can determine the size of the stack given to the new thread and modify the behavior through the supplied \fIflags\fR. The value \fBTCL_THREAD_STACK_DEFAULT\fR for the \fIstackSize\fR indicates that the default size as specified by the operating system is to be used for the new thread. As for the flags, currently only the values \fBTCL_THREAD_NOFLAGS\fR and \fBTCL_THREAD_JOINABLE\fR are defined. The first of them invokes the default behavior with no special settings. Using the second value marks the new thread as \fIjoinable\fR. This means that another thread can wait for the such marked thread to exit and join it. .PP Restrictions: On some UNIX systems the pthread-library does not contain the functionality to specify the stack size of a thread. The specified value for the stack size is ignored on these systems. Windows currently does not support joinable threads. This flag value is therefore ignored on this platform. .PP Tcl provides the \fBTcl_ExitThread\fR and \fBTcl_FinalizeThread\fR functions for terminating threads and invoking optional per-thread exit handlers. See the \fBTcl_Exit\fR page for more information on these procedures. .PP The \fBTcl_JoinThread\fR function is provided to allow threads to wait upon the exit of another thread, which must have been marked as joinable through usage of the \fBTCL_THREAD_JOINABLE\fR-flag during its creation via \fBTcl_CreateThread\fR. .PP Trying to wait for the exit of a non-joinable thread or a thread which is already waited upon will result in an error. Waiting for a joinable thread which already exited is possible, the system will retain the necessary information until after the call to \fBTcl_JoinThread\fR. This means that not calling \fBTcl_JoinThread\fR for a joinable thread will cause a memory leak. .PP The \fBTcl_GetThreadData\fR call returns a pointer to a block of thread-private data. Its argument is a key that is shared by all threads and a size for the block of storage. The storage is automatically allocated and initialized to all zeros the first time each thread asks for it. The storage is automatically deallocated by \fBTcl_FinalizeThread\fR. .SS "SYNCHRONIZATION AND COMMUNICATION" Tcl provides \fBTcl_ThreadQueueEvent\fR and \fBTcl_ThreadAlert\fR for handling event queuing in multithreaded applications. See the \fBNotifier\fR manual page for more information on these procedures. .PP A mutex is a lock that is used to serialize all threads through a piece of code by calling \fBTcl_MutexLock\fR and \fBTcl_MutexUnlock\fR. If one thread holds a mutex, any other thread calling \fBTcl_MutexLock\fR will block until \fBTcl_MutexUnlock\fR is called. A mutex can be destroyed after its use by calling \fBTcl_MutexFinalize\fR. The result of locking a mutex twice from the same thread is undefined. On some platforms it will result in a deadlock. The \fBTcl_MutexLock\fR, \fBTcl_MutexUnlock\fR and \fBTcl_MutexFinalize\fR procedures are defined as empty macros if not compiling with threads enabled. For declaration of mutexes the \fBTCL_DECLARE_MUTEX\fR macro should be used. This macro assures correct mutex handling even when the core is compiled without threads enabled. .PP A condition variable is used as a signaling mechanism: a thread can lock a mutex and then wait on a condition variable with \fBTcl_ConditionWait\fR. This atomically releases the mutex lock and blocks the waiting thread until another thread calls \fBTcl_ConditionNotify\fR. The caller of \fBTcl_ConditionNotify\fR should have the associated mutex held by previously calling \fBTcl_MutexLock\fR, but this is not enforced. Notifying the condition variable unblocks all threads waiting on the condition variable, but they do not proceed until the mutex is released with \fBTcl_MutexUnlock\fR. The implementation of \fBTcl_ConditionWait\fR automatically locks the mutex before returning. .PP The caller of \fBTcl_ConditionWait\fR should be prepared for spurious notifications by calling \fBTcl_ConditionWait\fR within a while loop that tests some invariant. .PP A condition variable can be destroyed after its use by calling \fBTcl_ConditionFinalize\fR. .PP The \fBTcl_ConditionNotify\fR, \fBTcl_ConditionWait\fR and \fBTcl_ConditionFinalize\fR procedures are defined as empty macros if not compiling with threads enabled. .SS INITIALIZATION .PP All of these synchronization objects are self-initializing. They are implemented as opaque pointers that should be NULL upon first use. The mutexes and condition variables are either cleaned up by process exit handlers (if living that long) or explicitly by calls to \fBTcl_MutexFinalize\fR or \fBTcl_ConditionFinalize\fR. Thread local storage is reclaimed during \fBTcl_FinalizeThread\fR. .SH "SCRIPT-LEVEL ACCESS TO THREADS" .PP Tcl provides no built-in commands for scripts to use to create, manage, or join threads, nor any script-level access to mutex or condition variables. It provides such facilities only via C interfaces, and leaves it up to packages to expose these matters to the script level. One such package is the \fBThread\fR package. .SH EXAMPLE .PP To create a thread with portable code, its implementation function should be declared as follows: .PP .CS static \fBTcl_ThreadCreateProc\fR MyThreadImplFunc; .CE .PP It should then be defined like this example, which just counts up to a given value and then finishes. .PP .CS static \fBTcl_ThreadCreateType\fR MyThreadImplFunc( ClientData clientData) { int i, limit = (int) clientData; for (i=0 ; i\fR .sp int \fBTcl_ExprLong\fR(\fIinterp, expr, longPtr\fR) .sp int \fBTcl_ExprDouble\fR(\fIinterp, expr, doublePtr\fR) .sp int \fBTcl_ExprBoolean\fR(\fIinterp, expr, booleanPtr\fR) .sp int \fBTcl_ExprString\fR(\fIinterp, expr\fR) .SH ARGUMENTS .AS Tcl_Interp *booleanPtr out .AP Tcl_Interp *interp in Interpreter in whose context to evaluate \fIexpr\fR. .AP "const char" *expr in Expression to be evaluated. .AP long *longPtr out Pointer to location in which to store the integer value of the expression. .AP int *doublePtr out Pointer to location in which to store the floating-point value of the expression. .AP int *booleanPtr out Pointer to location in which to store the 0/1 boolean value of the expression. .BE .SH DESCRIPTION .PP These four procedures all evaluate the expression given by the \fIexpr\fR argument and return the result in one of four different forms. The expression can have any of the forms accepted by the \fBexpr\fR command. Note that these procedures have been largely replaced by the value-based procedures \fBTcl_ExprLongObj\fR, \fBTcl_ExprDoubleObj\fR, \fBTcl_ExprBooleanObj\fR, and \fBTcl_ExprObj\fR. Those value-based procedures evaluate an expression held in a Tcl value instead of a string. The value argument can retain an internal representation that is more efficient to execute. .PP The \fIinterp\fR argument refers to an interpreter used to evaluate the expression (e.g. for variables and nested Tcl commands) and to return error information. .PP For all of these procedures the return value is a standard Tcl result: \fBTCL_OK\fR means the expression was successfully evaluated, and \fBTCL_ERROR\fR means that an error occurred while evaluating the expression. If \fBTCL_ERROR\fR is returned then the interpreter's result will hold a message describing the error. If an error occurs while executing a Tcl command embedded in the expression then that error will be returned. .PP If the expression is successfully evaluated, then its value is returned in one of four forms, depending on which procedure is invoked. \fBTcl_ExprLong\fR stores an integer value at \fI*longPtr\fR. If the expression's actual value is a floating-point number, then it is truncated to an integer. If the expression's actual value is a non-numeric string then an error is returned. .PP \fBTcl_ExprDouble\fR stores a floating-point value at \fI*doublePtr\fR. If the expression's actual value is an integer, it is converted to floating-point. If the expression's actual value is a non-numeric string then an error is returned. .PP \fBTcl_ExprBoolean\fR stores a 0/1 integer value at \fI*booleanPtr\fR. If the expression's actual value is an integer or floating-point number, then they store 0 at \fI*booleanPtr\fR if the value was zero and 1 otherwise. If the expression's actual value is a non-numeric string then it must be one of the values accepted by \fBTcl_GetBoolean\fR such as .QW yes or .QW no , or else an error occurs. .PP \fBTcl_ExprString\fR returns the value of the expression as a string stored in the interpreter's result. .SH "SEE ALSO" Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj, Tcl_ExprObj .SH KEYWORDS boolean, double, evaluate, expression, integer, value, string tcl8.6.5/doc/CrtCommand.30000644000175000017500000001425612663660065014457 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 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_CreateCommand 3 "" Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_CreateCommand \- implement new commands in C .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Command \fBTcl_CreateCommand\fR(\fIinterp, cmdName, proc, clientData, deleteProc\fR) .SH ARGUMENTS .AS Tcl_CmdDeleteProc *deleteProc .AP Tcl_Interp *interp in Interpreter in which to create new command. .AP "const char" *cmdName in Name of command. .AP Tcl_CmdProc *proc in Implementation of new command: \fIproc\fR will be called whenever \fIcmdName\fR is invoked as a command. .AP ClientData clientData in Arbitrary one-word value to pass to \fIproc\fR and \fIdeleteProc\fR. .AP Tcl_CmdDeleteProc *deleteProc in Procedure to call before \fIcmdName\fR is deleted from the interpreter; allows for command-specific cleanup. If NULL, then no procedure is called before the command is deleted. .BE .SH DESCRIPTION .PP \fBTcl_CreateCommand\fR defines a new command in \fIinterp\fR and associates it with procedure \fIproc\fR such that whenever \fIcmdName\fR is invoked as a Tcl command (via a call to \fBTcl_Eval\fR) the Tcl interpreter will call \fIproc\fR to process the command. It differs from \fBTcl_CreateObjCommand\fR in that a new string-based command is defined; that is, a command procedure is defined that takes an array of argument strings instead of values. The value-based command procedures registered by \fBTcl_CreateObjCommand\fR can execute significantly faster than the string-based command procedures defined by \fBTcl_CreateCommand\fR. This is because they take Tcl values as arguments and those values can retain an internal representation that can be manipulated more efficiently. Also, Tcl's interpreter now uses values internally. In order to invoke a string-based command procedure registered by \fBTcl_CreateCommand\fR, it must generate and fetch a string representation from each argument value before the call. New commands should be defined using \fBTcl_CreateObjCommand\fR. We support \fBTcl_CreateCommand\fR for backwards compatibility. .PP The procedures \fBTcl_DeleteCommand\fR, \fBTcl_GetCommandInfo\fR, and \fBTcl_SetCommandInfo\fR are used in conjunction with \fBTcl_CreateCommand\fR. .PP \fBTcl_CreateCommand\fR will delete an existing command \fIcmdName\fR, if one is already associated with the interpreter. It returns a token that may be used to refer to the command in subsequent calls to \fBTcl_GetCommandName\fR. If \fIcmdName\fR contains any \fB::\fR namespace qualifiers, then the command is added to the specified namespace; otherwise the command is added to the global namespace. If \fBTcl_CreateCommand\fR is called for an interpreter that is in the process of being deleted, then it does not create a new command and it returns NULL. \fIProc\fR should have arguments and result that match the type \fBTcl_CmdProc\fR: .PP .CS typedef int \fBTcl_CmdProc\fR( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR, int \fIargc\fR, const char *\fIargv\fR[]); .CE .PP When \fIproc\fR is invoked the \fIclientData\fR and \fIinterp\fR parameters will be copies of the \fIclientData\fR and \fIinterp\fR arguments given to \fBTcl_CreateCommand\fR. Typically, \fIclientData\fR points to an application-specific data structure that describes what to do when the command procedure is invoked. \fIArgc\fR and \fIargv\fR describe the arguments to the command, \fIargc\fR giving the number of arguments (including the command name) and \fIargv\fR giving the values of the arguments as strings. The \fIargv\fR array will contain \fIargc\fR+1 values; the first \fIargc\fR values point to the argument strings, and the last value is NULL. Note that the argument strings should not be modified as they may point to constant strings or may be shared with other parts of the interpreter. .PP Note that the argument strings are encoded in normalized UTF-8 since version 8.1 of Tcl. .PP \fIProc\fR must return an integer code that is expected to be one of \fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR. See the Tcl overview man page for details on what these codes mean. Most normal commands will only return \fBTCL_OK\fR or \fBTCL_ERROR\fR. In addition, \fIproc\fR must set the interpreter result; in the case of a \fBTCL_OK\fR return code this gives the result of the command, and in the case of \fBTCL_ERROR\fR it gives an error message. The \fBTcl_SetResult\fR procedure provides an easy interface for setting the return value; for complete details on how the interpreter result field is managed, see the \fBTcl_Interp\fR man page. Before invoking a command procedure, \fBTcl_Eval\fR sets the interpreter result to point to an empty string, so simple commands can return an empty result by doing nothing at all. .PP The contents of the \fIargv\fR array belong to Tcl and are not guaranteed to persist once \fIproc\fR returns: \fIproc\fR should not modify them, nor should it set the interpreter result to point anywhere within the \fIargv\fR values. Call \fBTcl_SetResult\fR with status \fBTCL_VOLATILE\fR if you want to return something from the \fIargv\fR array. .PP \fIDeleteProc\fR will be invoked when (if) \fIcmdName\fR is deleted. This can occur through a call to \fBTcl_DeleteCommand\fR or \fBTcl_DeleteInterp\fR, or by replacing \fIcmdName\fR in another call to \fBTcl_CreateCommand\fR. \fIDeleteProc\fR is invoked before the command is deleted, and gives the application an opportunity to release any structures associated with the command. \fIDeleteProc\fR should have arguments and result that match the type \fBTcl_CmdDeleteProc\fR: .PP .CS typedef void \fBTcl_CmdDeleteProc\fR( ClientData \fIclientData\fR); .CE .PP The \fIclientData\fR argument will be the same as the \fIclientData\fR argument passed to \fBTcl_CreateCommand\fR. .SH "SEE ALSO" Tcl_CreateObjCommand, Tcl_DeleteCommand, Tcl_GetCommandInfo, Tcl_SetCommandInfo, Tcl_GetCommandName, Tcl_SetObjResult .SH KEYWORDS bind, command, create, delete, interpreter, namespace tcl8.6.5/doc/copy.n0000644000175000017500000000463712663660065013477 0ustar sergeisergei'\" '\" Copyright (c) 2007 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH copy n 0.1 TclOO "TclOO Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME oo::copy \- create copies of objects and classes .SH SYNOPSIS .nf package require TclOO \fBoo::copy\fI sourceObject \fR?\fItargetObject\fR? .fi .BE .SH DESCRIPTION .PP The \fBoo::copy\fR command creates a copy of an object or class. It takes the name of the object or class to be copied, \fIsourceObject\fR, and optionally the name of the object or class to create, \fItargetObject\fR, which will be resolved relative to the current namespace if not an absolute qualified name. If \fItargetObject\fR is omitted, a new name is chosen. The copied object will be of the same class as the source object, and will have all its per-object methods copied. If it is a class, it will also have all the class methods in the class copied, but it will not have any of its instances copied. .PP .VS After the \fItargetObject\fR has been created and all definitions of its configuration (e.g., methods, filters, mixins) copied, the \fB\fR method of \fItargetObject\fR will be invoked, to allow for customization of the created object such as installing related variable traces. The only argument given will be \fIsourceObject\fR. The default implementation of this method (in \fBoo::object\fR) just copies the procedures and variables in the namespace of \fIsourceObject\fR to the namespace of \fItargetObject\fR. If this method call does not return a result that is successful (i.e., an error or other kind of exception) then the \fItargetObject\fR will be deleted and an error returned. .VE .PP The result of the \fBoo::copy\fR command will be the fully-qualified name of the new object or class. .SH EXAMPLES .PP This example creates an object, copies it, modifies the source object, and then demonstrates that the copied object is indeed a copy. .PP .CS oo::object create src oo::objdefine src method msg {} {puts foo} \fBoo::copy\fR src dst oo::objdefine src method msg {} {puts bar} src msg \fI\(-> prints "bar"\fR dst msg \fI\(-> prints "foo"\fR .CE .SH "SEE ALSO" oo::class(n), oo::define(n), oo::object(n) .SH KEYWORDS clone, copy, duplication, object .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: tcl8.6.5/doc/Eval.30000644000175000017500000002107612663660065013315 0ustar sergeisergei'\" '\" Copyright (c) 1989-1993 The Regents of the University of California. '\" Copyright (c) 1994-1997 Sun Microsystems, Inc. '\" Copyright (c) 2000 Scriptics Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_Eval 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_EvalObjEx, Tcl_EvalFile, Tcl_EvalObjv, Tcl_Eval, Tcl_EvalEx, Tcl_GlobalEval, Tcl_GlobalEvalObj, Tcl_VarEval, Tcl_VarEvalVA \- execute Tcl scripts .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_EvalObjEx\fR(\fIinterp, objPtr, flags\fR) .sp int \fBTcl_EvalFile\fR(\fIinterp, fileName\fR) .sp int \fBTcl_EvalObjv\fR(\fIinterp, objc, objv, flags\fR) .sp int \fBTcl_Eval\fR(\fIinterp, script\fR) .sp int \fBTcl_EvalEx\fR(\fIinterp, script, numBytes, flags\fR) .sp int \fBTcl_GlobalEval\fR(\fIinterp, script\fR) .sp int \fBTcl_GlobalEvalObj\fR(\fIinterp, objPtr\fR) .sp int \fBTcl_VarEval\fR(\fIinterp, part, part, ... \fB(char *) NULL\fR) .sp int \fBTcl_VarEvalVA\fR(\fIinterp, argList\fR) .SH ARGUMENTS .AS Tcl_Interp **termPtr .AP Tcl_Interp *interp in Interpreter in which to execute the script. The interpreter's result is modified to hold the result or error message from the script. .AP Tcl_Obj *objPtr in A Tcl value containing the script to execute. .AP int flags in ORed combination of flag bits that specify additional options. \fBTCL_EVAL_GLOBAL\fR and \fBTCL_EVAL_DIRECT\fR are currently supported. .AP "const char" *fileName in Name of a file containing a Tcl script. .AP int objc in The number of values in the array pointed to by \fIobjPtr\fR; this is also the number of words in the command. .AP Tcl_Obj **objv in Points to an array of pointers to values; each value holds the value of a single word in the command to execute. .AP int numBytes in The number of bytes in \fIscript\fR, not including any null terminating character. If \-1, then all characters up to the first null byte are used. .AP "const char" *script in Points to first byte of script to execute (null-terminated and UTF-8). .AP char *part in String forming part of a Tcl script. .AP va_list argList in An argument list which must have been initialized using \fBva_start\fR, and cleared using \fBva_end\fR. .BE .SH DESCRIPTION .PP The procedures described here are invoked to execute Tcl scripts in various forms. \fBTcl_EvalObjEx\fR is the core procedure and is used by many of the others. It executes the commands in the script stored in \fIobjPtr\fR until either an error occurs or the end of the script is reached. If this is the first time \fIobjPtr\fR has been executed, its commands are compiled into bytecode instructions which are then executed. The bytecodes are saved in \fIobjPtr\fR so that the compilation step can be skipped if the value is evaluated again in the future. .PP The return value from \fBTcl_EvalObjEx\fR (and all the other procedures described here) is a Tcl completion code with one of the values \fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR, or possibly some other integer value originating in an extension. In addition, a result value or error message is left in \fIinterp\fR's result; it can be retrieved using \fBTcl_GetObjResult\fR. .PP \fBTcl_EvalFile\fR reads the file given by \fIfileName\fR and evaluates its contents as a Tcl script. It returns the same information as \fBTcl_EvalObjEx\fR. If the file could not be read then a Tcl error is returned to describe why the file could not be read. The eofchar for files is .QW \e32 (^Z) for all platforms. If you require a .QW ^Z in code for string comparison, you can use .QW \e032 or .QW \eu001a , which will be safely substituted by the Tcl interpreter into .QW ^Z . .PP \fBTcl_EvalObjv\fR executes a single pre-parsed command instead of a script. The \fIobjc\fR and \fIobjv\fR arguments contain the values of the words for the Tcl command, one word in each value in \fIobjv\fR. \fBTcl_EvalObjv\fR evaluates the command and returns a completion code and result just like \fBTcl_EvalObjEx\fR. The caller of \fBTcl_EvalObjv\fR has to manage the reference count of the elements of \fIobjv\fR, insuring that the values are valid until \fBTcl_EvalObjv\fR returns. .PP \fBTcl_Eval\fR is similar to \fBTcl_EvalObjEx\fR except that the script to be executed is supplied as a string instead of a value and no compilation occurs. The string should be a proper UTF-8 string as converted by \fBTcl_ExternalToUtfDString\fR or \fBTcl_ExternalToUtf\fR when it is known to possibly contain upper ASCII characters whose possible combinations might be a UTF-8 special code. The string is parsed and executed directly (using \fBTcl_EvalObjv\fR) instead of compiling it and executing the bytecodes. In situations where it is known that the script will never be executed again, \fBTcl_Eval\fR may be faster than \fBTcl_EvalObjEx\fR. \fBTcl_Eval\fR returns a completion code and result just like \fBTcl_EvalObjEx\fR. Note: for backward compatibility with versions before Tcl 8.0, \fBTcl_Eval\fR copies the value result in \fIinterp\fR to \fIinterp->result\fR (use is deprecated) where it can be accessed directly. This makes \fBTcl_Eval\fR somewhat slower than \fBTcl_EvalEx\fR, which does not do the copy. .PP \fBTcl_EvalEx\fR is an extended version of \fBTcl_Eval\fR that takes additional arguments \fInumBytes\fR and \fIflags\fR. For the efficiency reason given above, \fBTcl_EvalEx\fR is generally preferred over \fBTcl_Eval\fR. .PP \fBTcl_GlobalEval\fR and \fBTcl_GlobalEvalObj\fR are older procedures that are now deprecated. They are similar to \fBTcl_EvalEx\fR and \fBTcl_EvalObjEx\fR except that the script is evaluated in the global namespace and its variable context consists of global variables only (it ignores any Tcl procedures that are active). These functions are equivalent to using the \fBTCL_EVAL_GLOBAL\fR flag (see below). .PP \fBTcl_VarEval\fR takes any number of string arguments of any length, concatenates them into a single string, then calls \fBTcl_Eval\fR to execute that string as a Tcl command. It returns the result of the command and also modifies \fIinterp->result\fR in the same way as \fBTcl_Eval\fR. The last argument to \fBTcl_VarEval\fR must be NULL to indicate the end of arguments. \fBTcl_VarEval\fR is now deprecated. .PP \fBTcl_VarEvalVA\fR is the same as \fBTcl_VarEval\fR except that instead of taking a variable number of arguments it takes an argument list. Like \fBTcl_VarEval\fR, \fBTcl_VarEvalVA\fR is deprecated. .SH "FLAG BITS" .PP Any ORed combination of the following values may be used for the \fIflags\fR argument to procedures such as \fBTcl_EvalObjEx\fR: .TP 23 \fBTCL_EVAL_DIRECT\fR . This flag is only used by \fBTcl_EvalObjEx\fR; it is ignored by other procedures. If this flag bit is set, the script is not compiled to bytecodes; instead it is executed directly as is done by \fBTcl_EvalEx\fR. The \fBTCL_EVAL_DIRECT\fR flag is useful in situations where the contents of a value are going to change immediately, so the bytecodes will not be reused in a future execution. In this case, it is faster to execute the script directly. .TP 23 \fBTCL_EVAL_GLOBAL\fR . If this flag is set, the script is processed at global level. This means that it is evaluated in the global namespace and its variable context consists of global variables only (it ignores any Tcl procedures that are active). .SH "MISCELLANEOUS DETAILS" .PP During the processing of a Tcl command it is legal to make nested calls to evaluate other commands (this is how procedures and some control structures are implemented). If a code other than \fBTCL_OK\fR is returned from a nested \fBTcl_EvalObjEx\fR invocation, then the caller should normally return immediately, passing that same return code back to its caller, and so on until the top-level application is reached. A few commands, like \fBfor\fR, will check for certain return codes, like \fBTCL_BREAK\fR and \fBTCL_CONTINUE\fR, and process them specially without returning. .PP \fBTcl_EvalObjEx\fR keeps track of how many nested \fBTcl_EvalObjEx\fR invocations are in progress for \fIinterp\fR. If a code of \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR is about to be returned from the topmost \fBTcl_EvalObjEx\fR invocation for \fIinterp\fR, it converts the return code to \fBTCL_ERROR\fR and sets \fIinterp\fR's result to an error message indicating that the \fBreturn\fR, \fBbreak\fR, or \fBcontinue\fR command was invoked in an inappropriate place. This means that top-level applications should never see a return code from \fBTcl_EvalObjEx\fR other then \fBTCL_OK\fR or \fBTCL_ERROR\fR. .SH KEYWORDS execute, file, global, result, script, value tcl8.6.5/doc/msgcat.n0000644000175000017500000005562612663660065014007 0ustar sergeisergei'\" '\" Copyright (c) 1998 Mark Harrison. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH "msgcat" n 1.5 msgcat "Tcl Bundled Packages" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME msgcat \- Tcl message catalog .SH SYNOPSIS \fBpackage require Tcl 8.5\fR .sp \fBpackage require msgcat 1.6\fR .sp \fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR? .sp \fB::msgcat::mcmax ?\fIsrc-string src-string ...\fR? .sp .VS "TIP 412" \fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? \fIsrc-string\fR .VE "TIP 412" .sp \fB::msgcat::mclocale \fR?\fInewLocale\fR? .sp \fB::msgcat::mcpreferences\fR .sp .VS "TIP 412" \fB::msgcat::mcloadedlocales subcommand\fR ?\fIlocale\fR? .VE "TIP 412" .sp \fB::msgcat::mcload \fIdirname\fR .sp \fB::msgcat::mcset \fIlocale src-string \fR?\fItranslate-string\fR? .sp \fB::msgcat::mcmset \fIlocale src-trans-list\fR .sp \fB::msgcat::mcflset \fIsrc-string \fR?\fItranslate-string\fR? .sp \fB::msgcat::mcflmset \fIsrc-trans-list\fR .sp \fB::msgcat::mcunknown \fIlocale src-string\fR ?\fIarg arg ...\fR? .sp .VS "TIP 412" \fB::msgcat::mcpackagelocale subcommand\fR ?\fIlocale\fR? .sp \fB::msgcat::mcpackageconfig subcommand\fR \fIoption\fR ?\fIvalue\fR? .sp \fB::msgcat::mcforgetpackage\fR .VE "TIP 412" .BE .SH DESCRIPTION .PP The \fBmsgcat\fR package provides a set of functions that can be used to manage multi-lingual user interfaces. Text strings are defined in a .QW "message catalog" which is independent from the application, and which can be edited or localized without modifying the application source code. New languages or locales may be provided by adding a new file to the message catalog. .PP \fBmsgcat\fR distinguises packages by its namespace. Each package has its own message catalog and configuration settings in \fBmsgcat\fR. .PP A \fIlocale\fR is a specification string describing a user language like \fBde_ch\fR for Swiss German. In \fBmsgcat\fR, there is a global locale initialized by the system locale of the current system. Each package may decide to use the global locale or to use a package specific locale. .PP The global locale may be changed on demand, for example by a user initiated language change or within a multi user application like a web server. .SH COMMANDS .TP \fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR? . Returns a translation of \fIsrc-string\fR according to the current locale. If additional arguments past \fIsrc-string\fR are given, the \fBformat\fR command is used to substitute the additional arguments in the translation of \fIsrc-string\fR. .RS .PP \fB::msgcat::mc\fR will search the messages defined in the current namespace for a translation of \fIsrc-string\fR; if none is found, it will search in the parent of the current namespace, and so on until it reaches the global namespace. If no translation string exists, \fB::msgcat::mcunknown\fR is called and the string returned from \fB::msgcat::mcunknown\fR is returned. .PP \fB::msgcat::mc\fR is the main function used to localize an application. Instead of using an English string directly, an application can pass the English string through \fB::msgcat::mc\fR and use the result. If an application is written for a single language in this fashion, then it is easy to add support for additional languages later simply by defining new message catalog entries. .RE .TP \fB::msgcat::mcmax ?\fIsrc-string src-string ...\fR? . Given several source strings, \fB::msgcat::mcmax\fR returns the length of the longest translated string. This is useful when designing localized GUIs, which may require that all buttons, for example, be a fixed width (which will be the width of the widest button). .TP \fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? \fIsrc-string\fR . .VS "TIP 412" Return true, if there is a translation for the given \fIsrc-string\fR. .PP .RS The search may be limited by the option \fB\-exactnamespace\fR to only check the current namespace and not any parent namespaces. .PP It may also be limited by the option \fB\-exactlocale\fR to only check the first prefered locale (e.g. first element returned by \fB::msgcat::mcpreferences\fR if global locale is used). .RE .VE "TIP 412" .TP \fB::msgcat::mclocale \fR?\fInewLocale\fR? . This function sets the locale to \fInewLocale\fR. If \fInewLocale\fR is omitted, the current locale is returned, otherwise the current locale is set to \fInewLocale\fR. msgcat stores and compares the locale in a case-insensitive manner, and returns locales in lowercase. The initial locale is determined by the locale specified in the user's environment. See \fBLOCALE SPECIFICATION\fR below for a description of the locale string format. .RS .PP .VS "TIP 412" If the locale is set, the preference list of locales is evaluated. Locales in this list are loaded now, if not jet loaded. .VE "TIP 412" .RE .TP \fB::msgcat::mcpreferences\fR . Returns an ordered list of the locales preferred by the user, based on the user's language specification. The list is ordered from most specific to least preference. The list is derived from the current locale set in msgcat by \fB::msgcat::mclocale\fR, and cannot be set independently. For example, if the current locale is en_US_funky, then \fB::msgcat::mcpreferences\fR returns \fB{en_us_funky en_us en {}}\fR. .TP \fB::msgcat:mcloadedlocales subcommand\fR ?\fIlocale\fR? . This group of commands manage the list of loaded locales for packages not setting a package locale. .PP .RS The subcommand \fBget\fR returns the list of currently loaded locales. .PP The subcommand \fBpresent\fR requires the argument \fIlocale\fR and returns true, if this locale is loaded. .PP The subcommand \fBclear\fR removes all locales and their data, which are not in the current preference list. .RE .TP \fB::msgcat::mcload \fIdirname\fR . .VS "TIP 412" Searches the specified directory for files that match the language specifications returned by \fB::msgcat::mcloadedlocales get\fR (or \fBmsgcat::mcpackagelocale preferences\fR if a package locale is set) (note that these are all lowercase), extended by the file extension .QW .msg . Each matching file is read in order, assuming a UTF-8 encoding. The file contents are then evaluated as a Tcl script. This means that Unicode characters may be present in the message file either directly in their UTF-8 encoded form, or by use of the backslash-u quoting recognized by Tcl evaluation. The number of message files which matched the specification and were loaded is returned. .RS .PP In addition, the given folder is stored in the \fBmsgcat\fR package configuration option \fImcfolder\fR to eventually load message catalog files required by a locale change. .VE "TIP 412" .RE .TP \fB::msgcat::mcset \fIlocale src-string \fR?\fItranslate-string\fR? . Sets the translation for \fIsrc-string\fR to \fItranslate-string\fR in the specified \fIlocale\fR and the current namespace. If \fItranslate-string\fR is not specified, \fIsrc-string\fR is used for both. The function returns \fItranslate-string\fR. .TP \fB::msgcat::mcmset \fIlocale src-trans-list\fR . Sets the translation for multiple source strings in \fIsrc-trans-list\fR in the specified \fIlocale\fR and the current namespace. \fIsrc-trans-list\fR must have an even number of elements and is in the form {\fIsrc-string translate-string\fR ?\fIsrc-string translate-string ...\fR?} \fB::msgcat::mcmset\fR can be significantly faster than multiple invocations of \fB::msgcat::mcset\fR. The function returns the number of translations set. .TP \fB::msgcat::mcflset \fIsrc-string \fR?\fItranslate-string\fR? Sets the translation for \fIsrc-string\fR to \fItranslate-string\fR in the current namespace for the locale implied by the name of the message catalog being loaded via \fB::msgcat::mcload\fR. If \fItranslate-string\fR is not specified, \fIsrc-string\fR is used for both. The function returns \fItranslate-string\fR. .TP \fB::msgcat::mcflmset \fIsrc-trans-list\fR Sets the translation for multiple source strings in \fIsrc-trans-list\fR in the current namespace for the locale implied by the name of the message catalog being loaded via \fB::msgcat::mcload\fR. \fIsrc-trans-list\fR must have an even number of elements and is in the form {\fIsrc-string translate-string\fR ?\fIsrc-string translate-string ...\fR?} \fB::msgcat::mcflmset\fR can be significantly faster than multiple invocations of \fB::msgcat::mcflset\fR. The function returns the number of translations set. .TP \fB::msgcat::mcunknown \fIlocale src-string\fR ?\fIarg arg ...\fR? . This routine is called by \fB::msgcat::mc\fR in the case when a translation for \fIsrc-string\fR is not defined in the current locale. The default action is to return \fIsrc-string\fR passed by format if there are any arguments. This procedure can be redefined by the application, for example to log error messages for each unknown string. The \fB::msgcat::mcunknown\fR procedure is invoked at the same stack context as the call to \fB::msgcat::mc\fR. The return value of \fB::msgcat::mcunknown\fR is used as the return value for the call to \fB::msgcat::mc\fR. .VS "TIP 412" .RS .PP Note that this routine is only called if the concerned package did not set a package locale unknown command name. .RE .TP \fB::msgcat::mcforgetpackage\fR . The calling package clears all its state within the \fBmsgcat\fR package including all settings and translations. .VE "TIP 412" .PP .SH "LOCALE SPECIFICATION" .PP The locale is specified to \fBmsgcat\fR by a locale string passed to \fB::msgcat::mclocale\fR. The locale string consists of a language code, an optional country code, and an optional system-specific code, each separated by .QW _ . The country and language codes are specified in standards ISO-639 and ISO-3166. For example, the locale .QW en specifies English and .QW en_US specifies U.S. English. .PP When the msgcat package is first loaded, the locale is initialized according to the user's environment. The variables \fBenv(LC_ALL)\fR, \fBenv(LC_MESSAGES)\fR, and \fBenv(LANG)\fR are examined in order. The first of them to have a non-empty value is used to determine the initial locale. The value is parsed according to the XPG4 pattern .PP .CS language[_country][.codeset][@modifier] .CE .PP to extract its parts. The initial locale is then set by calling \fB::msgcat::mclocale\fR with the argument .PP .CS language[_country][_modifier] .CE .PP On Windows and Cygwin, if none of those environment variables is set, msgcat will attempt to extract locale information from the registry. From Windows Vista on, the RFC4747 locale name "lang-script-country-options" is transformed to the locale as "lang_country_script" (Example: sr-Latn-CS -> sr_cs_latin). For Windows XP, the language id is transformed analoguously (Example: 0c1a -> sr_yu_cyrillic). If all these attempts to discover an initial locale from the user's environment fail, msgcat defaults to an initial locale of .QW C . .PP When a locale is specified by the user, a .QW "best match" search is performed during string translation. For example, if a user specifies en_GB_Funky, the locales .QW en_gb_funky , .QW en_gb , .QW en and .MT (the empty string) are searched in order until a matching translation string is found. If no translation string is available, then the unknown handler is called. .SH "NAMESPACES AND MESSAGE CATALOGS" .PP Strings stored in the message catalog are stored relative to the namespace from which they were added. This allows multiple packages to use the same strings without fear of collisions with other packages. It also allows the source string to be shorter and less prone to typographical error. .PP For example, executing the code .PP .CS \fB::msgcat::mcset\fR en hello "hello from ::" namespace eval foo { \fB::msgcat::mcset\fR en hello "hello from ::foo" } puts [\fB::msgcat::mc\fR hello] namespace eval foo {puts [\fB::msgcat::mc\fR hello]} .CE .PP will print .PP .CS hello from :: hello from ::foo .CE .PP When searching for a translation of a message, the message catalog will search first the current namespace, then the parent of the current namespace, and so on until the global namespace is reached. This allows child namespaces to .QW inherit messages from their parent namespace. .PP For example, executing (in the .QW en locale) the code .PP .CS \fB::msgcat::mcset\fR en m1 ":: message1" \fB::msgcat::mcset\fR en m2 ":: message2" \fB::msgcat::mcset\fR en m3 ":: message3" namespace eval ::foo { \fB::msgcat::mcset\fR en m2 "::foo message2" \fB::msgcat::mcset\fR en m3 "::foo message3" } namespace eval ::foo::bar { \fB::msgcat::mcset\fR en m3 "::foo::bar message3" } namespace import \fB::msgcat::mc\fR puts "[\fBmc\fR m1]; [\fBmc\fR m2]; [\fBmc\fR m3]" namespace eval ::foo {puts "[\fBmc\fR m1]; [\fBmc\fR m2]; [\fBmc\fR m3]"} namespace eval ::foo::bar {puts "[\fBmc\fR m1]; [\fBmc\fR m2]; [\fBmc\fR m3]"} .CE .PP will print .PP .CS :: message1; :: message2; :: message3 :: message1; ::foo message2; ::foo message3 :: message1; ::foo message2; ::foo::bar message3 .CE .SH "LOCATION AND FORMAT OF MESSAGE FILES" .PP Message files can be located in any directory, subject to the following conditions: .IP [1] All message files for a package are in the same directory. .IP [2] The message file name is a msgcat locale specifier (all lowercase) followed by .QW .msg . For example: .PP .CS es.msg \(em spanish en_gb.msg \(em United Kingdom English .CE .PP \fIException:\fR The message file for the root locale .MT is called .QW \fBROOT.msg\fR . This exception is made so as not to cause peculiar behavior, such as marking the message file as .QW hidden on Unix file systems. .IP [3] The file contains a series of calls to \fBmcflset\fR and \fBmcflmset\fR, setting the necessary translation strings for the language, likely enclosed in a \fBnamespace eval\fR so that all source strings are tied to the namespace of the package. For example, a short \fBes.msg\fR might contain: .PP .CS namespace eval ::mypackage { \fB::msgcat::mcflset\fR "Free Beer" "Cerveza Gratis" } .CE .SH "RECOMMENDED MESSAGE SETUP FOR PACKAGES" .PP If a package is installed into a subdirectory of the \fBtcl_pkgPath\fR and loaded via \fBpackage require\fR, the following procedure is recommended. .IP [1] During package installation, create a subdirectory \fBmsgs\fR under your package directory. .IP [2] Copy your *.msg files into that directory. .IP [3] Add the following command to your package initialization script: .PP .CS # load language files, stored in msgs subdirectory \fB::msgcat::mcload\fR [file join [file dirname [info script]] msgs] .CE .SH "POSITIONAL CODES FOR FORMAT AND SCAN COMMANDS" .PP It is possible that a message string used as an argument to \fBformat\fR might have positionally dependent parameters that might need to be repositioned. For example, it might be syntactically desirable to rearrange the sentence structure while translating. .PP .CS format "We produced %d units in location %s" $num $city format "In location %s we produced %d units" $city $num .CE .PP This can be handled by using the positional parameters: .PP .CS format "We produced %1\e$d units in location %2\e$s" $num $city format "In location %2\e$s we produced %1\e$d units" $num $city .CE .PP Similarly, positional parameters can be used with \fBscan\fR to extract values from internationalized strings. Note that it is not necessary to pass the output of \fB::msgcat::mc\fR to \fBformat\fR directly; by passing the values to substitute in as arguments, the formatting substitution is done directly. .PP .CS \fBmsgcat::mc\fR {Produced %1$d at %2$s} $num $city # ... where that key is mapped to one of the # human-oriented versions by \fBmsgcat::mcset\fR .CE .VS "TIP 412" .SH Package private locale .PP A package using \fBmsgcat\fR may choose to use its own package private locale and its own set of loaded locales, independent to the global locale set by \fB::msgcat::mclocale\fR. .PP This allows a package to change its locale without causing any locales load or removal in other packages and not to invoke the global locale change callback (see below). .PP This action is controled by the following ensemble: .TP \fB::msgcat::mcpackagelocale set\fR ?\fIlocale\fR? . Set or change a package private locale. The package private locale is set to the given \fIlocale\fR if the \fIlocale\fR is given. If the option \fIlocale\fR is not given, the package is set to package private locale mode, but no locale is changed (e.g. if the global locale was valid for the package before, it is copied to the package private locale). .PP .RS This command may cause the load of locales. .RE .TP \fB::msgcat::mcpackagelocale get\fR . Return the package private locale or the global locale, if no package private locale is set. .TP \fB::msgcat::mcpackagelocale preferences\fR . Return the package private preferences or the global preferences, if no package private locale is set. .TP \fB::msgcat::mcpackagelocale loaded\fR . Return the list of locales loaded for this package. .TP \fB::msgcat::mcpackagelocale isset\fR . Returns true, if a package private locale is set. .TP \fB::msgcat::mcpackagelocale unset\fR . Unset the package private locale and use the globale locale. Load and remove locales to adjust the list of loaded locales for the package to the global loaded locales list. .TP \fB::msgcat::mcpackagelocale present\fR \fIlocale\fR . Returns true, if the given locale is loaded for the package. .TP \fB::msgcat::mcpackagelocale clear\fR . Clear any loaded locales of the package not present in the package preferences. .PP .SH Changing package options .PP Each package using msgcat has a set of options within \fBmsgcat\fR. The package options are described in the next sectionPackage options. Each package option may be set or unset individually using the following ensemble: .TP \fB::msgcat::mcpackageconfig get\fR \fIoption\fR . Return the current value of the given \fIoption\fR. This call returns an error if the option is not set for the package. .TP \fB::msgcat::mcpackageconfig isset\fR \fIoption\fR . Returns 1, if the given \fIoption\fR is set for the package, 0 otherwise. .TP \fB::msgcat::mcpackageconfig set\fR \fIoption\fR \fIvalue\fR . Set the given \fIoption\fR to the given \fIvalue\fR. This may invoke additional actions in dependency of the \fIoption\fR. The return value is 0 or the number of loaded packages for the option \fBmcfolder\fR. .TP \fB::msgcat::mcpackageconfig unset\fR \fIoption\fR . Unsets the given \fIoption\fR for the package. No action is taken if the \fIoption\fR is not set for the package. The empty string is returned. .SS Package options .PP The following package options are available for each package: .TP \fBmcfolder\fR . This is the message folder of the package. This option is set by mcload and by the subcommand set. Both are identical and both return the number of loaded message catalog files. .RS .PP Setting or changing this value will load all locales contained in the preferences valid for the package. This implies also to invoke any set loadcmd (see below). .PP Unsetting this value will disable message file load for the package. .RE .TP \fBloadcmd\fR . This callback is invoked before a set of message catalog files are loaded for the package which has this property set. .PP .RS This callback may be used to do any preparation work for message file load or to get the message data from another source like a data base. In this case, no message files are used (mcfolder is unset). .PP See section \fBcallback invocation\fR below. The parameter list appended to this callback is the list of locales to load. .PP If this callback is changed, it is called with the preferences valid for the package. .RE .TP \fBchangecmd\fR . This callback is invoked when a default local change was performed. Its purpose is to allow a package to update any dependency on the default locale like showing the GUI in another language. .PP .RS See the callback invocation section below. The parameter list appended to this callback is \fBmcpreferences\fR. The registered callbacks are invoked in no particular order. .RE .TP \fBunknowncmd\fR . Use a package locale mcunknown procedure instead of the standard version supplied by the msgcat package (msgcat::mcunknown). .PP .RS The called procedure must return the formatted message which will finally be returned by msgcat::mc. .PP A generic unknown handler is used if set to the empty string. This consists in returning the key if no arguments are given. With given arguments, format is used to process the arguments. .PP See section \fBcallback invocation\fR below. The appended arguments are identical to \fB::msgcat::mcunknown\fR. .RE .SS Callback invocation A package may decide to register one or multiple callbacks, as described above. .PP Callbacks are invoked, if: .PP 1. the callback command is set, .PP 2. the command is not the empty string, .PP 3. the registering namespace exists. .PP If a called routine fails with an error, the \fBbgerror\fR routine for the interpreter is invoked after command completion. Only exception is the callback \fBunknowncmd\fR, where an error causes the invoking \fBmc\fR-command to fail with that error. .PP .SS Examples Packages which display a GUI may update their widgets when the global locale changes. To register to a callback, use: .CS namespace eval gui { msgcat::mcpackageconfig changecmd updateGUI proc updateGui args { puts "New locale is '[lindex $args 0]'." } } % msgcat::mclocale fr fr % New locale is 'fr'. .CE .PP If locales (or additional locales) are contained in another source like a data base, a package may use the load callback and not mcload: .CS namespace eval db { msgcat::mcpackageconfig loadcmd loadMessages proc loadMessages args { foreach locale $args { if {[LocaleInDB $locale]} { msgcat::mcmset $locale [GetLocaleList $locale] } } } } .CE .PP The \fBclock\fR command implementation uses \fBmsgcat\fR with a package locale to implement the command line parameter \fB-locale\fR. Here are some sketches of the implementation: .PP First, a package locale is initialized and the generic unknown function is desactivated: .CS msgcat::mcpackagelocale set msgcat::mcpackageconfig unknowncmd "" .CE As an example, the user requires the week day in a certain locale as follows: .CS clock format clock seconds -format %A -locale fr .CE \fBclock\fR sets the package locale to \fBfr\fR and looks for the day name as follows: .CS msgcat::mcpackagelocale set $locale return [lindex [msgcat::mc DAYS_OF_WEEK_FULL] $day] ### Returns "mercredi" .CE Within \fBclock\fR, some message-catalog items are heavy in computation and thus are dynamically cached using: .CS proc ::tcl::clock::LocalizeFormat { locale format } { set key FORMAT_$format if { [::msgcat::mcexists -exactlocale -exactnamespace $key] } { return [mc $key] } #...expensive computation of format clipped... mcset $locale $key $format return $format } .CE .VE "TIP 412" .SH CREDITS .PP The message catalog code was developed by Mark Harrison. .SH "SEE ALSO" format(n), scan(n), namespace(n), package(n) .SH KEYWORDS internationalization, i18n, localization, l10n, message, text, translation .\" Local Variables: .\" mode: nroff .\" End: tcl8.6.5/doc/ParseArgs.30000644000175000017500000001610712663660065014314 0ustar sergeisergei'\" '\" Copyright (c) 2008 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_ParseArgsObjv 3 8.6 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_ParseArgsObjv \- parse arguments according to a tabular description .SH SYNOPSIS .nf \fB#include \fR .sp int \fBTcl_ParseArgsObjv\fR(\fIinterp, argTable, objcPtr, objv, remObjv\fR) .SH ARGUMENTS .AS "const Tcl_ArgvInfo" ***remObjv in/out .AP Tcl_Interp *interp out Where to store error messages. .AP "const Tcl_ArgvInfo" *argTable in Pointer to array of option descriptors. .AP int *objcPtr in/out A pointer to variable holding number of arguments in \fIobjv\fR. Will be modified to hold number of arguments left in the unprocessed argument list stored in \fIremObjv\fR. .AP "Tcl_Obj *const" *objv in The array of arguments to be parsed. .AP Tcl_Obj ***remObjv out Pointer to a variable that will hold the array of unprocessed arguments. Should be NULL if no return of unprocessed arguments is required. If \fIobjcPtr\fR is updated to a non-zero value, the array returned through this must be deallocated using \fBckfree\fR. .BE .SH DESCRIPTION .PP The \fBTcl_ParseArgsObjv\fR function provides a system for parsing argument lists of the form .QW "\fB\-someName \fIsomeValue\fR ..." . Such argument lists are commonly found both in the arguments to a program and in the arguments to an individual Tcl command. This parser assumes that the order of the arguments does not matter, other than in so far as later copies of a duplicated option overriding earlier ones. .PP The argument array is described by the \fIobjcPtr\fR and \fIobjv\fR parameters, and an array of unprocessed arguments is returned through the \fIobjcPtr\fR and \fIremObjv\fR parameters; if no return of unprocessed arguments is desired, the \fIremObjv\fR parameter should be NULL. If any problems happen, including if the .QW "generate help" option is selected, an error message is left in the interpreter result and TCL_ERROR is returned. Otherwise, the interpreter result is left unchanged and TCL_OK is returned. .PP The collection of arguments to be parsed is described by the \fIargTable\fR parameter. This points to a table of descriptor structures that is terminated by an entry with the \fItype\fR field set to TCL_ARGV_END. As convenience, the following prototypical entries are provided: .TP \fBTCL_ARGV_AUTO_HELP\fR . Enables the argument processor to provide help when passed the argument .QW \fB\-help\fR . .TP \fBTCL_ARGV_AUTO_REST\fR . Instructs the argument processor that arguments after .QW \fB\-\-\fR are to be unprocessed. .TP \fBTCL_ARGV_TABLE_END\fR . Marks the end of the table of argument descriptors. .SS "ARGUMENT DESCRIPTOR ENTRIES" .PP Each entry of the argument descriptor table must be a structure of type \fBTcl_ArgvInfo\fR. The structure is defined as this: .PP .CS typedef struct { int \fItype\fR; const char *\fIkeyStr\fR; void *\fIsrcPtr\fR; void *\fIdstPtr\fR; const char *\fIhelpStr\fR; ClientData \fIclientData\fR; } \fBTcl_ArgvInfo\fR; .CE .PP The \fIkeyStr\fR field contains the name of the option; by convention, this will normally begin with a .QW \fB\-\fR character. The \fItype\fR, \fIsrcPtr\fR, \fIdstPtr\fR and \fIclientData\fR fields describe the interpretation of the value of the argument, as described below. The \fIhelpStr\fR field gives some text that is used to provide help to users when they request it. .PP As noted above, the \fItype\fR field is used to describe the interpretation of the argument's value. The following values are acceptable values for \fItype\fR: .TP \fBTCL_ARGV_CONSTANT\fR . The argument does not take any following value argument. If this argument is present, the int pointed to by the \fIsrcPtr\fR field is copied to the \fIdstPtr\fR field. The \fIclientData\fR field is ignored. .TP \fBTCL_ARGV_END\fR . This value marks the end of all option descriptors in the table. All other fields are ignored. .TP \fBTCL_ARGV_FLOAT\fR . This argument takes a following floating point value argument. The value (once parsed by \fBTcl_GetDoubleFromObj\fR) will be stored as a double-precision value in the variable pointed to by the \fIdstPtr\fR field. The \fIsrcPtr\fR and \fIclientData\fR fields are ignored. .TP \fBTCL_ARGV_FUNC\fR . This argument optionally takes a following value argument; it is up to the handler callback function passed in \fIsrcPtr\fR to decide. That function will have the following signature: .RS .PP .CS typedef int (\fBTcl_ArgvFuncProc\fR)( ClientData \fIclientData\fR, Tcl_Obj *\fIobjPtr\fR, void *\fIdstPtr\fR); .CE .PP The result is a boolean value indicating whether to consume the following argument. The \fIclientData\fR is the value from the table entry, the \fIobjPtr\fR is the value that represents the following argument or NULL if there are no following arguments at all, and the \fIdstPtr\fR argument to the \fBTcl_ArgvFuncProc\fR is the location to write the parsed value to. .RE .TP \fBTCL_ARGV_GENFUNC\fR . This argument takes zero or more following arguments; the handler callback function passed in \fIsrcPtr\fR returns how many (or a negative number to signal an error, in which case it should also set the interpreter result). The function will have the following signature: .RS .PP .CS typedef int (\fBTcl_ArgvGenFuncProc\fR)( ClientData \fIclientData\fR, Tcl_Interp *\fIinterp\fR, int \fIobjc\fR, Tcl_Obj *const *\fIobjv\fR, void *\fIdstPtr\fR); .CE .PP The \fIclientData\fR is the value from the table entry, the \fIinterp\fR is where to store any error messages, the \fIkeyStr\fR is the name of the argument, \fIobjc\fR and \fIobjv\fR describe an array of all the remaining arguments, and \fIdstPtr\fR argument to the \fBTcl_ArgvGenFuncProc\fR is the location to write the parsed value (or values) to. .RE .TP \fBTCL_ARGV_HELP\fR . This special argument does not take any following value argument, but instead causes \fBTcl_ParseArgsObjv\fR to generate an error message describing the arguments supported. All other fields except the \fIhelpStr\fR field are ignored. .TP \fBTCL_ARGV_INT\fR . This argument takes a following integer value argument. The value (once parsed by \fBTcl_GetIntFromObj\fR) will be stored as an int in the variable pointed to by the \fIdstPtr\fR field. The \fIsrcPtr\fR field is ignored. .TP \fBTCL_ARGV_REST\fR . This special argument does not take any following value argument, but instead marks all following arguments to be left unprocessed. The \fIsrcPtr\fR, \fIdstPtr\fR and \fIclientData\fR fields are ignored. .TP \fBTCL_ARGV_STRING\fR . This argument takes a following string value argument. A pointer to the string will be stored at \fIdstPtr\fR; the string inside will have a lifetime linked to the lifetime of the string representation of the argument value that it came from, and so should be copied if it needs to be retained. The \fIsrcPtr\fR and \fIclientData\fR fields are ignored. .SH "SEE ALSO" Tcl_GetIndexFromObj(3), Tcl_Main(3), Tcl_CreateObjCommand(3) .SH KEYWORDS argument, parse '\" Local Variables: '\" fill-column: 78 '\" End: tcl8.6.5/doc/GetCwd.30000644000175000017500000000327312663660065013602 0ustar sergeisergei'\" '\" Copyright (c) 1998-1999 Scriptics Corporation '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_GetCwd 3 8.1 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_GetCwd, Tcl_Chdir \- manipulate the current working directory .SH SYNOPSIS .nf \fB#include \fR .sp char * \fBTcl_GetCwd\fR(\fIinterp\fR, \fIbufferPtr\fR) .sp int \fBTcl_Chdir\fR(\fIpath\fR) .SH ARGUMENTS .AS Tcl_DString *bufferPtr in/out .AP Tcl_Interp *interp in Interpreter in which to report an error, if any. .AP Tcl_DString *bufferPtr in/out This dynamic string is used to store the current working directory. At the time of the call it should be uninitialized or free. The caller must eventually call \fBTcl_DStringFree\fR to free up anything stored here. .AP char *path in File path in UTF\-8 format. .BE .SH DESCRIPTION .PP These procedures may be used to manipulate the current working directory for the application. They provide C\-level access to the same functionality as the Tcl \fBpwd\fR command. .PP \fBTcl_GetCwd\fR returns a pointer to a string specifying the current directory, or NULL if the current directory could not be determined. If NULL is returned, an error message is left in the \fIinterp\fR's result. Storage for the result string is allocated in bufferPtr; the caller must call \fBTcl_DStringFree()\fR when the result is no longer needed. The format of the path is UTF\-8. .PP \fBTcl_Chdir\fR changes the applications current working directory to the value specified in \fIpath\fR. The format of the passed in string must be UTF\-8. The function returns -1 on error or 0 on success. .SH KEYWORDS pwd tcl8.6.5/doc/BoolObj.30000644000175000017500000000721412663660065013752 0ustar sergeisergei'\" '\" Copyright (c) 1996-1997 Sun Microsystems, Inc. '\" Contributions from Don Porter, NIST, 2005. (not subject to US copyright) '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH Tcl_BooleanObj 3 8.5 Tcl "Tcl Library Procedures" .so man.macros .BS .SH NAME Tcl_NewBooleanObj, Tcl_SetBooleanObj, Tcl_GetBooleanFromObj \- store/retrieve boolean value in a Tcl_Obj .SH SYNOPSIS .nf \fB#include \fR .sp Tcl_Obj * \fBTcl_NewBooleanObj\fR(\fIboolValue\fR) .sp \fBTcl_SetBooleanObj\fR(\fIobjPtr, boolValue\fR) .sp int \fBTcl_GetBooleanFromObj\fR(\fIinterp, objPtr, boolPtr\fR) .SH ARGUMENTS .AS Tcl_Interp boolValue in/out .AP int boolValue in Integer value to be stored as a boolean value in a Tcl_Obj. .AP Tcl_Obj *objPtr in/out Points to the Tcl_Obj in which to store, or from which to retrieve a boolean value. .AP Tcl_Interp *interp in/out If a boolean value cannot be retrieved, an error message is left in the interpreter's result value unless \fIinterp\fR is NULL. .AP int *boolPtr out Points to place where \fBTcl_GetBooleanFromObj\fR stores the boolean value (0 or 1) obtained from \fIobjPtr\fR. .BE .SH DESCRIPTION .PP These procedures are used to pass boolean values to and from Tcl as Tcl_Obj's. When storing a boolean value into a Tcl_Obj, any non-zero integer value in \fIboolValue\fR is taken to be the boolean value \fB1\fR, and the integer value \fB0\fR is taken to be the boolean value \fB0\fR. .PP \fBTcl_NewBooleanObj\fR creates a new Tcl_Obj, stores the boolean value \fIboolValue\fR in it, and returns a pointer to the new Tcl_Obj. The new Tcl_Obj has reference count of zero. .PP \fBTcl_SetBooleanObj\fR accepts \fIobjPtr\fR, a pointer to an existing Tcl_Obj, and stores in the Tcl_Obj \fI*objPtr\fR the boolean value \fIboolValue\fR. This is a write operation on \fI*objPtr\fR, so \fIobjPtr\fR must be unshared. Attempts to write to a shared Tcl_Obj will panic. A successful write of \fIboolValue\fR into \fI*objPtr\fR implies the freeing of any former value stored in \fI*objPtr\fR. .PP \fBTcl_GetBooleanFromObj\fR attempts to retrieve a boolean value from the value stored in \fI*objPtr\fR. If \fIobjPtr\fR holds a string value recognized by \fBTcl_GetBoolean\fR, then the recognized boolean value is written at the address given by \fIboolPtr\fR. If \fIobjPtr\fR holds any value recognized as a number by Tcl, then if that value is zero a 0 is written at the address given by \fIboolPtr\fR and if that value is non-zero a 1 is written at the address given by \fIboolPtr\fR. In all cases where a value is written at the address given by \fIboolPtr\fR, \fBTcl_GetBooleanFromObj\fR returns \fBTCL_OK\fR. If the value of \fIobjPtr\fR does not meet any of the conditions above, then \fBTCL_ERROR\fR is returned and an error message is left in the interpreter's result unless \fIinterp\fR is NULL. \fBTcl_GetBooleanFromObj\fR may also make changes to the internal fields of \fI*objPtr\fR so that future calls to \fBTcl_GetBooleanFromObj\fR on the same \fIobjPtr\fR can be performed more efficiently. .PP Note that the routines \fBTcl_GetBooleanFromObj\fR and \fBTcl_GetBoolean\fR are not functional equivalents. The set of values for which \fBTcl_GetBooleanFromObj\fR will return \fBTCL_OK\fR is strictly larger than the set of values for which \fBTcl_GetBoolean\fR will do the same. For example, the value .QW 5 passed to \fBTcl_GetBooleanFromObj\fR will lead to a \fBTCL_OK\fR return (and the boolean value 1), while the same value passed to \fBTcl_GetBoolean\fR will lead to a \fBTCL_ERROR\fR return. .SH "SEE ALSO" Tcl_NewObj, Tcl_IsShared, Tcl_GetBoolean .SH KEYWORDS boolean, value tcl8.6.5/doc/gets.n0000644000175000017500000000472712663660065013467 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 gets n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME gets \- Read a line from a channel .SH SYNOPSIS \fBgets \fIchannelId\fR ?\fIvarName\fR? .BE .SH DESCRIPTION .PP This command reads the next line from \fIchannelId\fR, returns everything in the line up to (but not including) the end-of-line character(s), and discards the end-of-line character(s). .PP \fIChannelId\fR must be an identifier for an open channel such as the Tcl standard input channel (\fBstdin\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. The channel must have been opened for input. .PP If \fIvarName\fR is omitted the line is returned as the result of the command. If \fIvarName\fR is specified then the line is placed in the variable by that name and the return value is a count of the number of characters returned. .PP If end of file occurs while scanning for an end of line, the command returns whatever input is available up to the end of file. If \fIchannelId\fR is in non-blocking mode and there is not a full line of input available, the command returns an empty string and does not consume any input. If \fIvarName\fR is specified and an empty string is returned in \fIvarName\fR because of end-of-file or because of insufficient data in non-blocking mode, then the return count is -1. Note that if \fIvarName\fR is not specified then the end-of-file and no-full-line-available cases can produce the same results as if there were an input line consisting only of the end-of-line character(s). The \fBeof\fR and \fBfblocked\fR commands can be used to distinguish these three cases. .SH "EXAMPLE" This example reads a file one line at a time and prints it out with the current line number attached to the start of each line. .PP .CS set chan [open "some.file.txt"] set lineNumber 0 while {[\fBgets\fR $chan line] >= 0} { puts "[incr lineNumber]: $line" } close $chan .CE .SH "SEE ALSO" file(n), eof(n), fblocked(n), Tcl_StandardChannels(3) .SH KEYWORDS blocking, channel, end of file, end of line, line, non-blocking, read '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: tcl8.6.5/doc/eof.n0000644000175000017500000000306212663660065013265 0ustar sergeisergei'\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-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 eof n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME eof \- Check for end of file condition on channel .SH SYNOPSIS \fBeof \fIchannelId\fR .BE .SH DESCRIPTION .PP Returns 1 if an end of file condition occurred during the most recent input operation on \fIchannelId\fR (such as \fBgets\fR), 0 otherwise. .PP \fIChannelId\fR must be an identifier for an open channel such as a Tcl standard channel (\fBstdin\fR, \fBstdout\fR, or \fBstderr\fR), the return value from an invocation of \fBopen\fR or \fBsocket\fR, or the result of a channel creation command provided by a Tcl extension. .SH EXAMPLES .PP Read and print out the contents of a file line-by-line: .PP .CS set f [open somefile.txt] while {1} { set line [gets $f] if {[\fBeof\fR $f]} { close $f break } puts "Read line: $line" } .CE .PP Read and print out the contents of a file by fixed-size records: .PP .CS set f [open somefile.dat] fconfigure $f -translation binary set recordSize 40 while {1} { set record [read $f $recordSize] if {[\fBeof\fR $f]} { close $f break } puts "Read record: $record" } .CE .SH "SEE ALSO" file(n), open(n), close(n), fblocked(n), Tcl_StandardChannels(3) .SH KEYWORDS channel, end of file tcl8.6.5/doc/package.n0000644000175000017500000003211712663660065014112 0ustar sergeisergei'\" '\" Copyright (c) 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 package n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME package \- Facilities for package loading and version control .SH SYNOPSIS .nf \fBpackage forget\fR ?\fIpackage package ...\fR? \fBpackage ifneeded \fIpackage version\fR ?\fIscript\fR? \fBpackage names\fR \fBpackage present \fIpackage \fR?\fIrequirement...\fR? \fBpackage present \-exact \fIpackage version\fR \fBpackage provide \fIpackage \fR?\fIversion\fR? \fBpackage require \fIpackage \fR?\fIrequirement...\fR? \fBpackage require \-exact \fIpackage version\fR \fBpackage unknown \fR?\fIcommand\fR? \fBpackage vcompare \fIversion1 version2\fR \fBpackage versions \fIpackage\fR \fBpackage vsatisfies \fIversion requirement...\fR \fBpackage prefer \fR?\fBlatest\fR|\fBstable\fR? .fi .BE .SH DESCRIPTION .PP This command keeps a simple database of the packages available for use by the current interpreter and how to load them into the interpreter. It supports multiple versions of each package and arranges for the correct version of a package to be loaded based on what is needed by the application. This command also detects and reports version clashes. Typically, only the \fBpackage require\fR and \fBpackage provide\fR commands are invoked in normal Tcl scripts; the other commands are used primarily by system scripts that maintain the package database. .PP The behavior of the \fBpackage\fR command is determined by its first argument. The following forms are permitted: .TP \fBpackage forget\fR ?\fIpackage package ...\fR? . Removes all information about each specified package from this interpreter, including information provided by both \fBpackage ifneeded\fR and \fBpackage provide\fR. .TP \fBpackage ifneeded \fIpackage version\fR ?\fIscript\fR? . This command typically appears only in system configuration scripts to set up the package database. It indicates that a particular version of a particular package is available if needed, and that the package can be added to the interpreter by executing \fIscript\fR. The script is saved in a database for use by subsequent \fBpackage require\fR commands; typically, \fIscript\fR sets up auto-loading for the commands in the package (or calls \fBload\fR and/or \fBsource\fR directly), then invokes \fBpackage provide\fR to indicate that the package is present. There may be information in the database for several different versions of a single package. If the database already contains information for \fIpackage\fR and \fIversion\fR, the new \fIscript\fR replaces the existing one. If the \fIscript\fR argument is omitted, the current script for version \fIversion\fR of package \fIpackage\fR is returned, or an empty string if no \fBpackage ifneeded\fR command has been invoked for this \fIpackage\fR and \fIversion\fR. .TP \fBpackage names\fR . Returns a list of the names of all packages in the interpreter for which a version has been provided (via \fBpackage provide\fR) or for which a \fBpackage ifneeded\fR script is available. The order of elements in the list is arbitrary. .TP \fBpackage present\fR ?\fB\-exact\fR? \fIpackage\fR ?\fIrequirement...\fR? . This command is equivalent to \fBpackage require\fR except that it does not try and load the package if it is not already loaded. .TP \fBpackage provide \fIpackage \fR?\fIversion\fR? . This command is invoked to indicate that version \fIversion\fR of package \fIpackage\fR is now present in the interpreter. It is typically invoked once as part of an \fBifneeded\fR script, and again by the package itself when it is finally loaded. An error occurs if a different version of \fIpackage\fR has been provided by a previous \fBpackage provide\fR command. If the \fIversion\fR argument is omitted, then the command returns the version number that is currently provided, or an empty string if no \fBpackage provide\fR command has been invoked for \fIpackage\fR in this interpreter. .TP \fBpackage require \fR\fIpackage \fR?\fIrequirement...\fR? . This command is typically invoked by Tcl code that wishes to use a particular version of a particular package. The arguments indicate which package is wanted, and the command ensures that a suitable version of the package is loaded into the interpreter. If the command succeeds, it returns the version number that is loaded; otherwise it generates an error. .RS .PP A suitable version of the package is any version which satisfies at least one of the requirements, per the rules of \fBpackage vsatisfies\fR. If multiple versions are suitable the implementation with the highest version is chosen. This last part is additionally influenced by the selection mode set with \fBpackage prefer\fR. .PP In the .QW stable selection mode the command will select the highest stable version satisfying the requirements, if any. If no stable version satisfies the requirements, the highest unstable version satisfying the requirements will be selected. In the .QW latest selection mode the command will accept the highest version satisfying all the requirements, regardless of its stableness. .PP If a version of \fIpackage\fR has already been provided (by invoking the \fBpackage provide\fR command), then its version number must satisfy the \fIrequirement\fRs and the command returns immediately. Otherwise, the command searches the database of information provided by previous \fBpackage ifneeded\fR commands to see if an acceptable version of the package is available. If so, the script for the highest acceptable version number is evaluated in the global namespace; it must do whatever is necessary to load the package, including calling \fBpackage provide\fR for the package. If the \fBpackage ifneeded\fR database does not contain an acceptable version of the package and a \fBpackage unknown\fR command has been specified for the interpreter then that command is evaluated in the global namespace; when it completes, Tcl checks again to see if the package is now provided or if there is a \fBpackage ifneeded\fR script for it. If all of these steps fail to provide an acceptable version of the package, then the command returns an error. .RE .TP \fBpackage require \-exact \fIpackage version\fR . This form of the command is used when only the given \fIversion\fR of \fIpackage\fR is acceptable to the caller. This command is equivalent to \fBpackage require \fIpackage version\fR-\fIversion\fR. .TP \fBpackage unknown \fR?\fIcommand\fR? . This command supplies a .QW "last resort" command to invoke during \fBpackage require\fR if no suitable version of a package can be found in the \fBpackage ifneeded\fR database. If the \fIcommand\fR argument is supplied, it contains the first part of a command; when the command is invoked during a \fBpackage require\fR command, Tcl appends one or more additional arguments giving the desired package name and requirements. For example, if \fIcommand\fR is \fBfoo bar\fR and later the command \fBpackage require test 2.4\fR is invoked, then Tcl will execute the command \fBfoo bar test 2.4\fR to load the package. If no requirements are supplied to the \fBpackage require\fR command, then only the name will be added to invoked command. If the \fBpackage unknown\fR command is invoked without a \fIcommand\fR argument, then the current \fBpackage unknown\fR script is returned, or an empty string if there is none. If \fIcommand\fR is specified as an empty string, then the current \fBpackage unknown\fR script is removed, if there is one. .TP \fBpackage vcompare \fIversion1 version2\fR . Compares the two version numbers given by \fIversion1\fR and \fIversion2\fR. Returns -1 if \fIversion1\fR is an earlier version than \fIversion2\fR, 0 if they are equal, and 1 if \fIversion1\fR is later than \fIversion2\fR. .TP \fBpackage versions \fIpackage\fR . Returns a list of all the version numbers of \fIpackage\fR for which information has been provided by \fBpackage ifneeded\fR commands. .TP \fBpackage vsatisfies \fIversion requirement...\fR . Returns 1 if the \fIversion\fR satisfies at least one of the given requirements, and 0 otherwise. Each \fIrequirement\fR is allowed to have any of the forms: .RS .TP min . This form is called .QW min-bounded . .TP min- . This form is called .QW min-unbound . .TP min-max . This form is called .QW bounded . .RE .RS .PP where .QW min and .QW max are valid version numbers. The legacy syntax is a special case of the extended syntax, keeping backward compatibility. Regarding satisfaction the rules are: .RE .RS .IP [1] The \fIversion\fR has to pass at least one of the listed \fIrequirement\fRs to be satisfactory. .IP [2] A version satisfies a .QW bounded requirement when .RS .IP [a] For \fImin\fR equal to the \fImax\fR if, and only if the \fIversion\fR is equal to the \fImin\fR. .IP [b] Otherwise if, and only if the \fIversion\fR is greater than or equal to the \fImin\fR, and less than the \fImax\fR, where both \fImin\fR and \fImax\fR have been padded internally with .QW a0 . Note that while the comparison to \fImin\fR is inclusive, the comparison to \fImax\fR is exclusive. .RE .IP [3] A .QW min-bounded requirement is a .QW bounded requirement in disguise, with the \fImax\fR part implicitly specified as the next higher major version number of the \fImin\fR part. A version satisfies it per the rules above. .IP [4] A \fIversion\fR satisfies a .QW min-unbound requirement if, and only if it is greater than or equal to the \fImin\fR, where the \fImin\fR has been padded internally with .QW a0 . There is no constraint to a maximum. .RE .TP \fBpackage prefer \fR?\fBlatest\fR|\fBstable\fR? With no arguments, the commands returns either .QW latest or .QW stable , whichever describes the current mode of selection logic used by \fBpackage require\fR. .RS .PP When passed the argument .QW latest , it sets the selection logic mode to .QW latest . .PP When passed the argument .QW stable , if the mode is already .QW stable , that value is kept. If the mode is already .QW latest , then the attempt to set it back to .QW stable is ineffective and the mode value remains .QW latest . .PP When passed any other value as an argument, raise an invalid argument error. .PP When an interpreter is created, its initial selection mode value is set to .QW stable unless the environment variable \fBTCL_PKG_PREFER_LATEST\fR is set. If that environment variable is defined (with any value) then the initial (and permanent) selection mode value is set to .QW latest . .RE .SH "VERSION NUMBERS" .PP Version numbers consist of one or more decimal numbers separated by dots, such as 2 or 1.162 or 3.1.13.1. The first number is called the major version number. Larger numbers correspond to later versions of a package, with leftmost numbers having greater significance. For example, version 2.1 is later than 1.3 and version 3.4.6 is later than 3.3.5. Missing fields are equivalent to zeroes: version 1.3 is the same as version 1.3.0 and 1.3.0.0, so it is earlier than 1.3.1 or 1.3.0.2. In addition, the letters .QW a (alpha) and/or .QW b (beta) may appear exactly once to replace a dot for separation. These letters semantically add a negative specifier into the version, where .QW a is \-2, and .QW b is \-1. Each may be specified only once, and .QW a or .QW b are mutually exclusive in a specifier. Thus 1.3a1 becomes (semantically) 1.3.\-2.1, 1.3b1 is 1.3.\-1.1. Negative numbers are not directly allowed in version specifiers. A version number not containing the letters .QW a or .QW b as specified above is called a \fBstable\fR version, whereas presence of the letters causes the version to be called is \fBunstable\fR. A later version number is assumed to be upwards compatible with an earlier version number as long as both versions have the same major version number. For example, Tcl scripts written for version 2.3 of a package should work unchanged under versions 2.3.2, 2.4, and 2.5.1. Changes in the major version number signify incompatible changes: if code is written to use version 2.1 of a package, it is not guaranteed to work unmodified with either version 1.7.3 or version 3.1. .SH "PACKAGE INDICES" .PP The recommended way to use packages in Tcl is to invoke \fBpackage require\fR and \fBpackage provide\fR commands in scripts, and use the procedure \fBpkg_mkIndex\fR to create package index files. Once you have done this, packages will be loaded automatically in response to \fBpackage require\fR commands. See the documentation for \fBpkg_mkIndex\fR for details. .SH EXAMPLES .PP To state that a Tcl script requires the Tk and http packages, put this at the top of the script: .PP .CS \fBpackage require\fR Tk \fBpackage require\fR http .CE .PP To test to see if the Snack package is available and load if it is (often useful for optional enhancements to programs where the loss of the functionality is not critical) do this: .PP .CS if {[catch {\fBpackage require\fR Snack}]} { # Error thrown - package not found. # Set up a dummy interface to work around the absence } else { # We have the package, configure the app to use it } .CE .SH "SEE ALSO" msgcat(n), packagens(n), pkgMkIndex(n) .SH KEYWORDS package, version '\" Local Variables: '\" mode: nroff '\" End: tcl8.6.5/license.terms0000644000175000017500000000431712663660066014273 0ustar sergeisergeiThis software is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. tcl8.6.5/win/0000755000175000017500000000000012665173607012367 5ustar sergeisergeitcl8.6.5/win/makefile.vc0000644000175000017500000012265412663660066014506 0ustar sergeisergei#------------------------------------------------------------- # makefile.vc -- # # Microsoft Visual C++ makefile for use with nmake.exe v1.62+ (VC++ 5.0+) # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # Copyright (c) 1995-1996 Sun Microsystems, Inc. # Copyright (c) 1998-2000 Ajuba Solutions. # Copyright (c) 2001-2005 ActiveState Corporation. # Copyright (c) 2001-2004 David Gravereaux. # Copyright (c) 2003-2008 Pat Thoyts. #------------------------------------------------------------------------------ # Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or # VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir) !if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(VCINSTALLDIR) && !defined(MSSDK) && !defined(WINDOWSSDKDIR) MSG = ^ You need to run vcvars32.bat from Developer Studio or setenv.bat from the^ Platform SDK first to setup the environment. Jump to this line to read^ the build instructions. !error $(MSG) !endif #------------------------------------------------------------------------------ # HOW TO USE this makefile: # # 1) It is now necessary to have MSVCDir, MSDevDir or MSSDK set in the # environment. This is used as a check to see if vcvars32.bat had been # run prior to running nmake or during the installation of Microsoft # Visual C++, MSVCDir had been set globally and the PATH adjusted. # Either way is valid. # # You'll need to run vcvars32.bat contained in the MsDev's vc(98)/bin # directory to setup the proper environment, if needed, for your # current setup. This is a needed bootstrap requirement and allows the # swapping of different environments to be easier. # # 2) To use the Platform SDK (not expressly needed), run setenv.bat after # vcvars32.bat according to the instructions for it. This can also # turn on the 64-bit compiler, if your SDK has it. # # 3) Targets are: # release -- Builds the core, the shell and the dlls. (default) # dlls -- Just builds the windows extensions # shell -- Just builds the shell and the core. # core -- Only builds the core [tclXX.(dll|lib)]. # all -- Builds everything. # test -- Builds and runs the test suite. # tcltest -- Just builds the test shell. # install -- Installs the built binaries and libraries to $(INSTALLDIR) # as the root of the install tree. # tidy/clean/hose -- varying levels of cleaning. # genstubs -- Rebuilds the Stubs table and support files (dev only). # depend -- Generates an accurate set of source dependancies for this # makefile. Helpful to avoid problems when the sources are # refreshed and you rebuild, but can "overbuild" when common # headers like tclInt.h just get small changes. # htmlhelp -- Builds a Windows .chm help file for Tcl and Tk from the # troff manual pages found in $(ROOT)\doc. You need to # have installed the HTML Help Compiler package from Microsoft # to produce the .chm file. # winhelp -- (deprecated) Builds the windows .hlp file for Tcl from # the troff man files found in $(ROOT)\doc. This type of # help file is deprecated by Microsoft in favour of html # help files (.chm) # # 4) Macros usable on the commandline: # INSTALLDIR= # Sets where to install Tcl from the built binaries. # C:\Progra~1\Tcl is assumed when not specified. # # OPTS=loimpact,msvcrt,nothreads,pdbs,profile,static,staticpkg,symbols,thrdalloc,tclalloc,unchecked,none # Sets special options for the core. The default is for none. # Any combination of the above may be used (comma separated). # 'none' will over-ride everything to nothing. # # loimpact = Adds a flag for how NT treats the heap to keep memory # in use, low. This is said to impact alloc performance. # msvcrt = Affects the static option only to switch it from # using libcmt(d) as the C runtime [by default] to # msvcrt(d). This is useful for static embedding # support. # nothreads= Turns off full multithreading support. # pdbs = Build detached symbols for release builds. # profile = Adds profiling hooks. Map file is assumed. # static = Builds a static library of the core instead of a # dll. The static library will contain the dde and reg # extensions. External applications who want to use # this, need to link with the stub library as well as # the static Tcl library.The shell will be static (and # large), as well. # staticpkg = Affects the static option only to switch # tclshXX.exe to have the dde and reg extension linked # inside it. # symbols = Debug build. Links to the debug C runtime, disables # optimizations and creates pdb symbols files. # thrdalloc = Use the thread allocator (shared global free pool) # This is the default on threaded builds. # tclalloc = Use the old non-thread allocator # unchecked= Allows a symbols build to not use the debug # enabled runtime (msvcrt.dll not msvcrtd.dll # or libcmt.lib not libcmtd.lib). # # STATS=compdbg,memdbg,none # Sets optional memory and bytecode compiler debugging code added # to the core. The default is for none. Any combination of the # above may be used (comma separated). 'none' will over-ride # everything to nothing. # # compdbg = Enables byte compilation logging. # memdbg = Enables the debugging memory allocator. # # CHECKS=64bit,fullwarn,nodep,none # Sets special macros for checking compatability. # # 64bit = Enable 64bit portability warnings (if available) # fullwarn = Builds with full compiler and link warnings enabled. # Very verbose. # nodep = Turns off compatability macros to ensure the core # isn't being built with deprecated functions. # # MACHINE=(ALPHA|AMD64|IA64|IX86) # Set the machine type used for the compiler, linker, and # resource compiler. This hook is needed to tell the tools # when alternate platforms are requested. IX86 is the default # when not specified. If the CPU environment variable has been # set (ie: recent Platform SDK) then MACHINE is set from CPU. # # TMP_DIR= # OUT_DIR= # Hooks to allow the intermediate and output directories to be # changed. $(OUT_DIR) is assumed to be # $(BINROOT)\(Release|Debug) based on if symbols are requested. # $(TMP_DIR) will de $(OUT_DIR)\ by default. # # TESTPAT= # Reads the tests requested to be run from this file. # # CFG_ENCODING=encoding # name of encoding for configuration information. Defaults # to cp1252 # # 5) Examples: # # Basic syntax of calling nmake looks like this: # nmake [-nologo] -f makefile.vc [target|macrodef [target|macrodef] [...]] # # Standard (no frills) # c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat # Setting environment for using Microsoft Visual C++ tools. # c:\tcl_src\win\>nmake -f makefile.vc release # c:\tcl_src\win\>nmake -f makefile.vc install INSTALLDIR=c:\progra~1\tcl # # Building for Win64 # c:\tcl_src\win\>c:\progra~1\micros~1\vc98\bin\vcvars32.bat # Setting environment for using Microsoft Visual C++ tools. # c:\tcl_src\win\>c:\progra~1\platfo~1\setenv.bat /pre64 /RETAIL # Targeting Windows pre64 RETAIL # c:\tcl_src\win\>nmake -f makefile.vc MACHINE=IA64 # #------------------------------------------------------------------------------ #============================================================================== ############################################################################### # //==================================================================\\ # >>[ -> Do not modify below this line. <- ]<< # >>[ Please, use the commandline macros to modify how Tcl is built. ]<< # >>[ If you need more features, send us a patch for more macros. ]<< # \\==================================================================// ############################################################################### #============================================================================== #------------------------------------------------------------------------------ !if !exist("makefile.vc") MSG = ^ You must run this makefile only from the directory it is in.^ Please `cd` to its location first. !error $(MSG) !endif PROJECT = tcl !include "rules.vc" STUBPREFIX = $(PROJECT)stub DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION) VERSION = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION) DDEDOTVERSION = 1.4 DDEVERSION = $(DDEDOTVERSION:.=) REGDOTVERSION = 1.3 REGVERSION = $(REGDOTVERSION:.=) BINROOT = $(MAKEDIR) # originally . ROOT = $(MAKEDIR)\.. # originally .. TCLIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib TCLLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT) TCLLIB = $(OUT_DIR)\$(TCLLIBNAME) TCLSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib TCLSTUBLIB = $(OUT_DIR)\$(TCLSTUBLIBNAME) TCLSHNAME = $(PROJECT)sh$(VERSION)$(SUFX).exe TCLSH = $(OUT_DIR)\$(TCLSHNAME) TCLREGLIBNAME = $(PROJECT)reg$(REGVERSION)$(SUFX:t=).$(EXT) TCLREGLIB = $(OUT_DIR)\$(TCLREGLIBNAME) TCLDDELIBNAME = $(PROJECT)dde$(DDEVERSION)$(SUFX:t=).$(EXT) TCLDDELIB = $(OUT_DIR)\$(TCLDDELIBNAME) TCLTEST = $(OUT_DIR)\$(PROJECT)test.exe CAT32 = $(OUT_DIR)\cat32.exe # Can we run what we build? IX86 runs on all architectures. !ifndef TCLSH_NATIVE !if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)" TCLSH_NATIVE = $(TCLSH) !else !error You must explicitly set TCLSH_NATIVE for cross-compilation !endif !endif ### Make sure we use backslash only. LIB_INSTALL_DIR = $(_INSTALLDIR)\lib BIN_INSTALL_DIR = $(_INSTALLDIR)\bin DOC_INSTALL_DIR = $(_INSTALLDIR)\doc SCRIPT_INSTALL_DIR = $(_INSTALLDIR)\lib\tcl$(DOTVERSION) INCLUDE_INSTALL_DIR = $(_INSTALLDIR)\include TCLSHOBJS = \ $(TMP_DIR)\tclAppInit.obj \ !if !$(STATIC_BUILD) !if $(TCL_USE_STATIC_PACKAGES) $(TMP_DIR)\tclWinReg.obj \ $(TMP_DIR)\tclWinDde.obj \ !endif !endif $(TMP_DIR)\tclsh.res TCLTESTOBJS = \ $(TMP_DIR)\tclTest.obj \ $(TMP_DIR)\tclTestObj.obj \ $(TMP_DIR)\tclTestProcBodyObj.obj \ $(TMP_DIR)\tclThreadTest.obj \ $(TMP_DIR)\tclWinTest.obj \ !if !$(STATIC_BUILD) !if $(TCL_USE_STATIC_PACKAGES) $(TMP_DIR)\tclWinReg.obj \ $(TMP_DIR)\tclWinDde.obj \ !endif !endif $(TMP_DIR)\testMain.obj COREOBJS = \ $(TMP_DIR)\regcomp.obj \ $(TMP_DIR)\regerror.obj \ $(TMP_DIR)\regexec.obj \ $(TMP_DIR)\regfree.obj \ $(TMP_DIR)\tclAlloc.obj \ $(TMP_DIR)\tclAssembly.obj \ $(TMP_DIR)\tclAsync.obj \ $(TMP_DIR)\tclBasic.obj \ $(TMP_DIR)\tclBinary.obj \ $(TMP_DIR)\tclCkalloc.obj \ $(TMP_DIR)\tclClock.obj \ $(TMP_DIR)\tclCmdAH.obj \ $(TMP_DIR)\tclCmdIL.obj \ $(TMP_DIR)\tclCmdMZ.obj \ $(TMP_DIR)\tclCompCmds.obj \ $(TMP_DIR)\tclCompCmdsGR.obj \ $(TMP_DIR)\tclCompCmdsSZ.obj \ $(TMP_DIR)\tclCompExpr.obj \ $(TMP_DIR)\tclCompile.obj \ $(TMP_DIR)\tclConfig.obj \ $(TMP_DIR)\tclDate.obj \ $(TMP_DIR)\tclDictObj.obj \ $(TMP_DIR)\tclDisassemble.obj \ $(TMP_DIR)\tclEncoding.obj \ $(TMP_DIR)\tclEnsemble.obj \ $(TMP_DIR)\tclEnv.obj \ $(TMP_DIR)\tclEvent.obj \ $(TMP_DIR)\tclExecute.obj \ $(TMP_DIR)\tclFCmd.obj \ $(TMP_DIR)\tclFileName.obj \ $(TMP_DIR)\tclGet.obj \ $(TMP_DIR)\tclHash.obj \ $(TMP_DIR)\tclHistory.obj \ $(TMP_DIR)\tclIndexObj.obj \ $(TMP_DIR)\tclInterp.obj \ $(TMP_DIR)\tclIO.obj \ $(TMP_DIR)\tclIOCmd.obj \ $(TMP_DIR)\tclIOGT.obj \ $(TMP_DIR)\tclIOSock.obj \ $(TMP_DIR)\tclIOUtil.obj \ $(TMP_DIR)\tclIORChan.obj \ $(TMP_DIR)\tclIORTrans.obj \ $(TMP_DIR)\tclLink.obj \ $(TMP_DIR)\tclListObj.obj \ $(TMP_DIR)\tclLiteral.obj \ $(TMP_DIR)\tclLoad.obj \ $(TMP_DIR)\tclMain.obj \ $(TMP_DIR)\tclMain2.obj \ $(TMP_DIR)\tclNamesp.obj \ $(TMP_DIR)\tclNotify.obj \ $(TMP_DIR)\tclOO.obj \ $(TMP_DIR)\tclOOBasic.obj \ $(TMP_DIR)\tclOOCall.obj \ $(TMP_DIR)\tclOODefineCmds.obj \ $(TMP_DIR)\tclOOInfo.obj \ $(TMP_DIR)\tclOOMethod.obj \ $(TMP_DIR)\tclOOStubInit.obj \ $(TMP_DIR)\tclObj.obj \ $(TMP_DIR)\tclOptimize.obj \ $(TMP_DIR)\tclPanic.obj \ $(TMP_DIR)\tclParse.obj \ $(TMP_DIR)\tclPathObj.obj \ $(TMP_DIR)\tclPipe.obj \ $(TMP_DIR)\tclPkg.obj \ $(TMP_DIR)\tclPkgConfig.obj \ $(TMP_DIR)\tclPosixStr.obj \ $(TMP_DIR)\tclPreserve.obj \ $(TMP_DIR)\tclProc.obj \ $(TMP_DIR)\tclRegexp.obj \ $(TMP_DIR)\tclResolve.obj \ $(TMP_DIR)\tclResult.obj \ $(TMP_DIR)\tclScan.obj \ $(TMP_DIR)\tclStringObj.obj \ $(TMP_DIR)\tclStrToD.obj \ $(TMP_DIR)\tclStubInit.obj \ $(TMP_DIR)\tclThread.obj \ $(TMP_DIR)\tclThreadAlloc.obj \ $(TMP_DIR)\tclThreadJoin.obj \ $(TMP_DIR)\tclThreadStorage.obj \ $(TMP_DIR)\tclTimer.obj \ $(TMP_DIR)\tclTomMathInterface.obj \ $(TMP_DIR)\tclTrace.obj \ $(TMP_DIR)\tclUtf.obj \ $(TMP_DIR)\tclUtil.obj \ $(TMP_DIR)\tclVar.obj \ $(TMP_DIR)\tclZlib.obj ZLIBOBJS = \ $(TMP_DIR)\adler32.obj \ $(TMP_DIR)\compress.obj \ $(TMP_DIR)\crc32.obj \ $(TMP_DIR)\deflate.obj \ $(TMP_DIR)\infback.obj \ $(TMP_DIR)\inffast.obj \ $(TMP_DIR)\inflate.obj \ $(TMP_DIR)\inftrees.obj \ $(TMP_DIR)\trees.obj \ $(TMP_DIR)\uncompr.obj \ $(TMP_DIR)\zutil.obj TOMMATHOBJS = \ $(TMP_DIR)\bncore.obj \ $(TMP_DIR)\bn_reverse.obj \ $(TMP_DIR)\bn_fast_s_mp_mul_digs.obj \ $(TMP_DIR)\bn_fast_s_mp_sqr.obj \ $(TMP_DIR)\bn_mp_add.obj \ $(TMP_DIR)\bn_mp_add_d.obj \ $(TMP_DIR)\bn_mp_and.obj \ $(TMP_DIR)\bn_mp_clamp.obj \ $(TMP_DIR)\bn_mp_clear.obj \ $(TMP_DIR)\bn_mp_clear_multi.obj \ $(TMP_DIR)\bn_mp_cmp.obj \ $(TMP_DIR)\bn_mp_cmp_d.obj \ $(TMP_DIR)\bn_mp_cmp_mag.obj \ $(TMP_DIR)\bn_mp_cnt_lsb.obj \ $(TMP_DIR)\bn_mp_copy.obj \ $(TMP_DIR)\bn_mp_count_bits.obj \ $(TMP_DIR)\bn_mp_div.obj \ $(TMP_DIR)\bn_mp_div_d.obj \ $(TMP_DIR)\bn_mp_div_2.obj \ $(TMP_DIR)\bn_mp_div_2d.obj \ $(TMP_DIR)\bn_mp_div_3.obj \ $(TMP_DIR)\bn_mp_exch.obj \ $(TMP_DIR)\bn_mp_expt_d.obj \ $(TMP_DIR)\bn_mp_grow.obj \ $(TMP_DIR)\bn_mp_init.obj \ $(TMP_DIR)\bn_mp_init_copy.obj \ $(TMP_DIR)\bn_mp_init_multi.obj \ $(TMP_DIR)\bn_mp_init_set.obj \ $(TMP_DIR)\bn_mp_init_set_int.obj \ $(TMP_DIR)\bn_mp_init_size.obj \ $(TMP_DIR)\bn_mp_karatsuba_mul.obj \ $(TMP_DIR)\bn_mp_karatsuba_sqr.obj \ $(TMP_DIR)\bn_mp_lshd.obj \ $(TMP_DIR)\bn_mp_mod.obj \ $(TMP_DIR)\bn_mp_mod_2d.obj \ $(TMP_DIR)\bn_mp_mul.obj \ $(TMP_DIR)\bn_mp_mul_2.obj \ $(TMP_DIR)\bn_mp_mul_2d.obj \ $(TMP_DIR)\bn_mp_mul_d.obj \ $(TMP_DIR)\bn_mp_neg.obj \ $(TMP_DIR)\bn_mp_or.obj \ $(TMP_DIR)\bn_mp_radix_size.obj \ $(TMP_DIR)\bn_mp_radix_smap.obj \ $(TMP_DIR)\bn_mp_read_radix.obj \ $(TMP_DIR)\bn_mp_rshd.obj \ $(TMP_DIR)\bn_mp_set.obj \ $(TMP_DIR)\bn_mp_set_int.obj \ $(TMP_DIR)\bn_mp_shrink.obj \ $(TMP_DIR)\bn_mp_sqr.obj \ $(TMP_DIR)\bn_mp_sqrt.obj \ $(TMP_DIR)\bn_mp_sub.obj \ $(TMP_DIR)\bn_mp_sub_d.obj \ $(TMP_DIR)\bn_mp_to_unsigned_bin.obj \ $(TMP_DIR)\bn_mp_to_unsigned_bin_n.obj \ $(TMP_DIR)\bn_mp_toom_mul.obj \ $(TMP_DIR)\bn_mp_toom_sqr.obj \ $(TMP_DIR)\bn_mp_toradix_n.obj \ $(TMP_DIR)\bn_mp_unsigned_bin_size.obj \ $(TMP_DIR)\bn_mp_xor.obj \ $(TMP_DIR)\bn_mp_zero.obj \ $(TMP_DIR)\bn_s_mp_add.obj \ $(TMP_DIR)\bn_s_mp_mul_digs.obj \ $(TMP_DIR)\bn_s_mp_sqr.obj \ $(TMP_DIR)\bn_s_mp_sub.obj PLATFORMOBJS = \ $(TMP_DIR)\tclWin32Dll.obj \ $(TMP_DIR)\tclWinChan.obj \ $(TMP_DIR)\tclWinConsole.obj \ $(TMP_DIR)\tclWinError.obj \ $(TMP_DIR)\tclWinFCmd.obj \ $(TMP_DIR)\tclWinFile.obj \ $(TMP_DIR)\tclWinInit.obj \ $(TMP_DIR)\tclWinLoad.obj \ $(TMP_DIR)\tclWinNotify.obj \ $(TMP_DIR)\tclWinPipe.obj \ $(TMP_DIR)\tclWinSerial.obj \ $(TMP_DIR)\tclWinSock.obj \ $(TMP_DIR)\tclWinThrd.obj \ $(TMP_DIR)\tclWinTime.obj \ !if $(STATIC_BUILD) $(TMP_DIR)\tclWinReg.obj \ $(TMP_DIR)\tclWinDde.obj \ !else $(TMP_DIR)\tcl.res !endif TCLOBJS = $(COREOBJS) $(ZLIBOBJS) $(TOMMATHOBJS) $(PLATFORMOBJS) TCLSTUBOBJS = \ $(TMP_DIR)\tclStubLib.obj \ $(TMP_DIR)\tclTomMathStubLib.obj \ $(TMP_DIR)\tclOOStubLib.obj ### The following paths CANNOT have spaces in them. COMPATDIR = $(ROOT)\compat DOCDIR = $(ROOT)\doc GENERICDIR = $(ROOT)\generic TOMMATHDIR = $(ROOT)\libtommath TOOLSDIR = $(ROOT)\tools WINDIR = $(ROOT)\win PKGSDIR = $(ROOT)\pkgs #--------------------------------------------------------------------- # Compile flags #--------------------------------------------------------------------- !if !$(DEBUG) !if $(OPTIMIZING) ### This cranks the optimization level to maximize speed cdebug = -O2 $(OPTIMIZATIONS) !else cdebug = !endif !if $(SYMBOLS) cdebug = $(cdebug) -Zi !endif !else if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64" ### Warnings are too many, can't support warnings into errors. cdebug = -Zi -Od $(DEBUGFLAGS) !else cdebug = -Zi -WX $(DEBUGFLAGS) !endif ### Declarations common to all compiler options cwarn = $(WARNINGS) -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE cflags = -nologo -c $(COMPILERFLAGS) $(cwarn) -Fp$(TMP_DIR)^\ !if $(MSVCRT) !if $(DEBUG) && !$(UNCHECKED) crt = -MDd !else crt = -MD !endif !else !if $(DEBUG) && !$(UNCHECKED) crt = -MTd !else crt = -MT !endif !endif TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)" -I"$(TOMMATHDIR)" TCL_DEFINES = -DTCL_TOMMATH -DMP_PREC=4 -Dinline=__inline -DHAVE_ZLIB=1 BASE_CFLAGS = $(cflags) $(cdebug) $(crt) $(TCL_INCLUDES) $(TCL_DEFINES) CON_CFLAGS = $(cflags) $(cdebug) $(crt) -DCONSOLE TCL_CFLAGS = $(BASE_CFLAGS) $(OPTDEFINES) STUB_CFLAGS = $(cflags) $(cdebug) $(OPTDEFINES) #--------------------------------------------------------------------- # Link flags #--------------------------------------------------------------------- !if $(DEBUG) ldebug = -debug -debugtype:cv !else ldebug = -release -opt:ref -opt:icf,3 !if $(SYMBOLS) ldebug = $(ldebug) -debug -debugtype:cv !endif !endif ### Declarations common to all linker options lflags = -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug) !if $(PROFILE) lflags = $(lflags) -profile !endif !if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900 lflags = $(lflags) -nodefaultlib:libucrt.lib !endif !if $(ALIGN98_HACK) && !$(STATIC_BUILD) ### Align sections for PE size savings. lflags = $(lflags) -opt:nowin98 !else if !$(ALIGN98_HACK) && $(STATIC_BUILD) ### Align sections for speed in loading by choosing the virtual page size. lflags = $(lflags) -align:4096 !endif !if $(LOIMPACT) lflags = $(lflags) -ws:aggressive !endif dlllflags = $(lflags) -dll conlflags = $(lflags) -subsystem:console guilflags = $(lflags) -subsystem:windows baselibs = netapi32.lib kernel32.lib user32.lib advapi32.lib userenv.lib ws2_32.lib # Avoid 'unresolved external symbol __security_cookie' errors. # c.f. http://support.microsoft.com/?id=894573 !if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64" !if $(VCVERSION) > 1399 && $(VCVERSION) < 1500 baselibs = $(baselibs) bufferoverflowU.lib !endif !endif !if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900 baselibs = $(baselibs) ucrt.lib !endif #--------------------------------------------------------------------- # TclTest flags #--------------------------------------------------------------------- !if "$(TESTPAT)" != "" TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT) !endif #--------------------------------------------------------------------- # Project specific targets #--------------------------------------------------------------------- release: setup $(TCLSH) $(TCLSTUBLIB) dlls pkgs core: setup $(TCLLIB) $(TCLSTUBLIB) shell: setup $(TCLSH) dlls: setup $(TCLREGLIB) $(TCLDDELIB) all: setup $(TCLSH) $(TCLSTUBLIB) dlls $(CAT32) pkgs tcltest: setup $(TCLTEST) dlls $(CAT32) install: install-binaries install-libraries install-docs install-pkgs test: test-core test-pkgs test-core: setup $(TCLTEST) dlls $(CAT32) set TCL_LIBRARY=$(ROOT:\=/)/library !if "$(OS)" == "Windows_NT" || "$(MSVCDIR)" == "IDE" $(DEBUGGER) $(TCLTEST) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) -loadfile << package ifneeded dde 1.4.0 [list load "$(TCLDDELIB:\=/)" dde] package ifneeded registry 1.3.1 [list load "$(TCLREGLIB:\=/)" registry] << !else @echo Please wait while the tests are collected... $(TCLTEST) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) -loadfile << > tests.log package ifneeded dde 1.4.0 "$(TCLDDELIB:\=/)" dde] package ifneeded registry 1.3.1 "$(TCLREGLIB:\=/)" registry] << type tests.log | more !endif runtest: setup $(TCLTEST) dlls $(CAT32) set TCL_LIBRARY=$(ROOT:\=/)/library $(DEBUGGER) $(TCLTEST) $(SCRIPT) runshell: setup $(TCLSH) dlls set TCL_LIBRARY=$(ROOT:\=/)/library $(DEBUGGER) $(TCLSH) $(SCRIPT) setup: @if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR) @if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR) !if !$(STATIC_BUILD) $(TCLIMPLIB): $(TCLLIB) !endif $(TCLLIB): $(TCLOBJS) !if $(STATIC_BUILD) $(lib32) -nologo $(LINKERFLAGS) -out:$@ @<< $** << !else $(link32) $(dlllflags) -base:@$(WINDIR)\coffbase.txt,tcl -out:$@ \ $(baselibs) @<< $** << $(_VC_MANIFEST_EMBED_DLL) !endif $(TCLSTUBLIB): $(TCLSTUBOBJS) $(lib32) -nologo $(LINKERFLAGS) -nodefaultlib -out:$@ $(TCLSTUBOBJS) $(TCLSH): $(TCLSHOBJS) $(TCLSTUBLIB) $(TCLIMPLIB) $(link32) $(conlflags) -stack:2300000 -out:$@ $(baselibs) $** $(_VC_MANIFEST_EMBED_EXE) $(TCLTEST): $(TCLTESTOBJS) $(TCLSTUBLIB) $(TCLIMPLIB) $(link32) $(conlflags) -stack:2300000 -out:$@ $(baselibs) $** $(_VC_MANIFEST_EMBED_EXE) !if $(STATIC_BUILD) $(TCLDDELIB): $(TMP_DIR)\tclWinDde.obj $(lib32) -nologo $(LINKERFLAGS) -out:$@ $** !else $(TCLDDELIB): $(TMP_DIR)\tclWinDde.obj $(TCLSTUBLIB) $(link32) $(dlllflags) -base:@$(WINDIR)\coffbase.txt,tcldde -out:$@ \ $** $(baselibs) $(_VC_MANIFEST_EMBED_DLL) !endif !if $(STATIC_BUILD) $(TCLREGLIB): $(TMP_DIR)\tclWinReg.obj $(lib32) -nologo $(LINKERFLAGS) -out:$@ $** !else $(TCLREGLIB): $(TMP_DIR)\tclWinReg.obj $(TCLSTUBLIB) $(link32) $(dlllflags) -base:@$(WINDIR)\coffbase.txt,tclreg -out:$@ \ $** $(baselibs) $(_VC_MANIFEST_EMBED_DLL) !endif pkgs: @for /d %d in ($(PKGSDIR)\*) do \ @if exist "%~fd\win\makefile.vc" ( \ pushd "%~fd\win" & \ $(MAKE) -$(MAKEFLAGS) -f makefile.vc TCLDIR=$(ROOT) &\ popd \ ) test-pkgs: @for /d %d in ($(PKGSDIR)\*) do \ @if exist "%~fd\win\makefile.vc" ( \ pushd "%~fd\win" & \ $(MAKE) -$(MAKEFLAGS) -f makefile.vc TCLDIR=$(ROOT) test &\ popd \ ) install-pkgs: @for /d %d in ($(PKGSDIR)\*) do \ @if exist "%~fd\win\makefile.vc" ( \ pushd "%~fd\win" & \ $(MAKE) -$(MAKEFLAGS) -f makefile.vc TCLDIR=$(ROOT) install &\ popd \ ) clean-pkgs: @for /d %d in ($(PKGSDIR)\*) do \ @if exist "%~fd\win\makefile.vc" ( \ pushd "%~fd\win" & \ $(MAKE) -$(MAKEFLAGS) -f makefile.vc TCLDIR=$(ROOT) clean &\ popd \ ) $(CAT32): $(WINDIR)\cat.c $(cc32) $(CON_CFLAGS) -Fo$(TMP_DIR)\ $? $(link32) $(conlflags) -out:$@ -stack:16384 $(TMP_DIR)\cat.obj \ $(baselibs) $(_VC_MANIFEST_EMBED_EXE) #--------------------------------------------------------------------- # Regenerate the stubs files. [Development use only] #--------------------------------------------------------------------- genstubs: !if !exist($(TCLSH)) @echo Build tclsh first! !else $(TCLSH) $(TOOLSDIR:\=/)/genStubs.tcl $(GENERICDIR:\=/) \ $(GENERICDIR:\=/)/tcl.decls $(GENERICDIR:\=/)/tclInt.decls \ $(GENERICDIR:\=/)/tclTomMath.decls $(TCLSH) $(TOOLSDIR:\=/)/genStubs.tcl $(GENERICDIR:\=/) \ $(GENERICDIR:\=/)/tclOO.decls !endif #---------------------------------------------------------------------- # The following target generates the file generic/tclTomMath.h. # It needs to be run (and the results checked) after updating # to a new release of libtommath. #---------------------------------------------------------------------- gentommath_h: !if !exist($(TCLSH)) @echo Build tclsh first! !else $(TCLSH) "$(TOOLSDIR:\=/)/fix_tommath_h.tcl" \ "$(TOMMATHDIR:\=/)/tommath.h" \ > "$(GENERICDIR)\tclTomMath.h" !endif #--------------------------------------------------------------------- # Build the Windows HTML help file. #--------------------------------------------------------------------- # NOTE: you can define HHC on the command-line to override this !ifndef HHC HHC=""%ProgramFiles%\HTML Help Workshop\hhc.exe"" !endif HTMLDIR=$(ROOT)\html HTMLBASE=TclTk$(VERSION) HHPFILE=$(HTMLDIR)\$(HTMLBASE).hhp CHMFILE=$(HTMLDIR)\$(HTMLBASE).chm htmlhelp: chmsetup $(CHMFILE) $(CHMFILE): $(DOCDIR)\* @$(TCLSH) $(TOOLSDIR)\tcltk-man2html.tcl @echo Compiling HTML help project @$(HHC) <<$(HHPFILE) >NUL [OPTIONS] Compatibility=1.1 or later Compiled file=$(HTMLBASE).chm Display compile progress=no Error log file=$(HTMLBASE).log Language=0x409 English (United States) Title=Tcl/Tk $(DOT_VERSION) Help [FILES] contents.htm docs.css Keywords TclCmd TclLib TkCmd TkLib UserCmd << chmsetup: @if not exist $(HTMLDIR)\nul mkdir $(HTMLDIR) #------------------------------------------------------------------------- # Build the old-style Windows .hlp file #------------------------------------------------------------------------- TCLHLPBASE = $(PROJECT)$(VERSION) HELPFILE = $(OUT_DIR)\$(TCLHLPBASE).hlp HELPCNT = $(OUT_DIR)\$(TCLHLPBASE).cnt DOCTMP_DIR = $(OUT_DIR)\$(PROJECT)_docs HELPRTF = $(DOCTMP_DIR)\$(PROJECT).rtf MAN2HELP = $(DOCTMP_DIR)\man2help.tcl MAN2HELP2 = $(DOCTMP_DIR)\man2help2.tcl INDEX = $(DOCTMP_DIR)\index.tcl BMP = $(DOCTMP_DIR)\feather.bmp BMP_NOPATH = feather.bmp MAN2TCL = $(DOCTMP_DIR)\man2tcl.exe winhelp: docsetup $(HELPFILE) docsetup: @if not exist $(DOCTMP_DIR)\nul mkdir $(DOCTMP_DIR) $(MAN2HELP) $(MAN2HELP2) $(INDEX) $(BMP): $(TOOLSDIR)\$$(@F) @$(CPY) $(TOOLSDIR)\$(@F) $(@D) $(HELPFILE): $(HELPRTF) $(BMP) cd $(DOCTMP_DIR) start /wait hcrtf.exe -x <<$(PROJECT).hpj [OPTIONS] COMPRESS=12 Hall Zeck LCID=0x409 0x0 0x0 ; English (United States) TITLE=Tcl/Tk Reference Manual BMROOT=. CNT=$(@B).cnt HLP=$(@B).hlp [FILES] $(PROJECT).rtf [WINDOWS] main="Tcl/Tk Reference Manual",,27648,(r15263976),(r65535) [CONFIG] BrowseButtons() CreateButton(1, "Web", ExecFile("http://www.tcl.tk")) CreateButton(2, "SF", ExecFile("http://sf.net/projects/tcl")) CreateButton(3, "Wiki", ExecFile("http://wiki.tcl.tk")) CreateButton(4, "FAQ", ExecFile("http://www.purl.org/NET/Tcl-FAQ/")) << cd $(MAKEDIR) @$(CPY) "$(DOCTMP_DIR)\$(@B).hlp" "$(OUT_DIR)" @$(CPY) "$(DOCTMP_DIR)\$(@B).cnt" "$(OUT_DIR)" $(MAN2TCL): $(TOOLSDIR)\$$(@B).c $(cc32) $(TCL_CFLAGS) -Fo$(@D)\ $(TOOLSDIR)\$(@B).c $(link32) $(conlflags) -out:$@ -stack:16384 $(@D)\man2tcl.obj $(_VC_MANIFEST_EMBED_EXE) $(HELPRTF): $(MAN2TCL) $(MAN2HELP) $(MAN2HELP2) $(INDEX) $(DOCDIR)\* $(TCLSH) $(MAN2HELP) -bitmap $(BMP_NOPATH) $(PROJECT) $(VERSION) $(DOCDIR:\=/) install-docs: !if exist("$(CHMFILE)") @echo Installing compiled HTML help @$(CPY) "$(CHMFILE)" "$(DOC_INSTALL_DIR)\" !endif !if exist("$(HELPFILE)") @echo Installing Windows help @$(CPY) "$(HELPFILE)" "$(DOC_INSTALL_DIR)\" @$(CPY) "$(HELPCNT)" "$(DOC_INSTALL_DIR)\" !endif #--------------------------------------------------------------------- # Build tclConfig.sh for the TEA build system. #--------------------------------------------------------------------- tclConfig: $(OUT_DIR)\tclConfig.sh $(OUT_DIR)\tclConfig.sh: $(WINDIR)\tclConfig.sh.in @echo Creating tclConfig.sh @nmakehlp -s << $** >$@ @TCL_DLL_FILE@ $(TCLLIBNAME) @TCL_VERSION@ $(DOTVERSION) @TCL_MAJOR_VERSION@ $(TCL_MAJOR_VERSION) @TCL_MINOR_VERSION@ $(TCL_MINOR_VERSION) @TCL_PATCH_LEVEL@ $(TCL_PATCH_LEVEL) @CC@ $(CC) @DEFS@ $(TCL_CFLAGS) @CFLAGS_DEBUG@ -nologo -c -W3 -YX -Fp$(TMP_DIR)\ -MDd @CFLAGS_OPTIMIZE@ -nologo -c -W3 -YX -Fp$(TMP_DIR)\ -MD @LDFLAGS_DEBUG@ -nologo -machine:$(MACHINE) -debug -debugtype:cv @LDFLAGS_OPTIMIZE@ -nologo -machine:$(MACHINE) -release -opt:ref -opt:icf,3 @TCL_DBGX@ $(SUFX) @TCL_LIB_FILE@ $(PROJECT)$(VERSION)$(SUFX).lib @TCL_NEEDS_EXP_FILE@ @LIBS@ $(baselibs) @prefix@ $(_INSTALLDIR) @exec_prefix@ $(BIN_INSTALL_DIR) @SHLIB_CFLAGS@ @STLIB_CFLAGS@ @CFLAGS_WARNING@ -W3 @EXTRA_CFLAGS@ -YX @SHLIB_LD@ $(link32) $(dlllflags) @STLIB_LD@ $(lib32) -nologo @SHLIB_LD_LIBS@ $(baselibs) @SHLIB_SUFFIX@ .dll @DL_LIBS@ @LDFLAGS@ @TCL_LD_SEARCH_FLAGS@ @LIBOBJS@ @RANLIB@ @TCL_LIB_FLAG@ @TCL_BUILD_LIB_SPEC@ @TCL_LIB_SPEC@ $(LIB_INSTALL_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib @TCL_INCLUDE_SPEC@ -I$(INCLUDE_INSTALL_DIR) @TCL_LIB_VERSIONS_OK@ @TCL_SRC_DIR@ $(ROOT) @TCL_PACKAGE_PATH@ @TCL_STUB_LIB_FILE@ $(TCLSTUBLIBNAME) @TCL_STUB_LIB_FLAG@ $(TCLSTUBLIBNAME) @TCL_STUB_LIB_SPEC@ -L$(LIB_INSTALL_DIR) $(TCLSTUBLIBNAME) @TCL_THREADS@ $(TCL_THREADS) @TCL_BUILD_STUB_LIB_SPEC@ -L$(OUT_DIR) $(TCLSTUBLIBNAME) @TCL_BUILD_STUB_LIB_PATH@ $(TCLSTUBLIB) @TCL_STUB_LIB_PATH@ $(LIB_INSTALL_DIR)\$(TCLSTUBLIBNAME) @CFG_TCL_EXPORT_FILE_SUFFIX@ $(VERSION)$(SUFX).lib @CFG_TCL_SHARED_LIB_SUFFIX@ $(VERSION)$(SUFX).dll @CFG_TCL_UNSHARED_LIB_SUFFIX@ $(VERSION)$(SUFX).lib !if $(STATIC_BUILD) @TCL_SHARED_BUILD@ 0 !else @TCL_SHARED_BUILD@ 1 !endif << #--------------------------------------------------------------------- # The following target generates the file generic/tclDate.c # from the yacc grammar found in generic/tclGetDate.y. This is # only run by hand as yacc is not available in all environments. # The name of the .c file is different than the name of the .y file # so that make doesn't try to automatically regenerate the .c file. #--------------------------------------------------------------------- gendate: bison --output-file=$(GENERICDIR)/tclDate.c \ --name-prefix=TclDate \ $(GENERICDIR)/tclGetDate.y #--------------------------------------------------------------------- # Special case object file targets #--------------------------------------------------------------------- $(TMP_DIR)\testMain.obj: $(WINDIR)\tclAppInit.c $(cc32) $(TCL_CFLAGS) -DTCL_TEST \ -DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \ -Fo$@ $? $(TMP_DIR)\tclMain2.obj: $(GENERICDIR)\tclMain.c $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -DTCL_ASCII_MAIN \ -Fo$@ $? $(TMP_DIR)\tclTest.obj: $(GENERICDIR)\tclTest.c $(cc32) $(TCL_CFLAGS) -Fo$@ $? $(TMP_DIR)\tclTestObj.obj: $(GENERICDIR)\tclTestObj.c $(cc32) $(TCL_CFLAGS) -Fo$@ $? $(TMP_DIR)\tclWinTest.obj: $(WINDIR)\tclWinTest.c $(cc32) $(TCL_CFLAGS) -Fo$@ $? $(TMP_DIR)\tclZlib.obj: $(GENERICDIR)\tclZlib.c $(cc32) $(TCL_CFLAGS) -I$(COMPATDIR)\zlib -DBUILD_tcl -Fo$@ $? $(TMP_DIR)\tclPkgConfig.obj: $(GENERICDIR)\tclPkgConfig.c $(cc32) -DBUILD_tcl $(TCL_CFLAGS) \ -DCFG_INSTALL_LIBDIR="\"$(LIB_INSTALL_DIR:\=\\)\"" \ -DCFG_INSTALL_BINDIR="\"$(BIN_INSTALL_DIR:\=\\)\"" \ -DCFG_INSTALL_SCRDIR="\"$(SCRIPT_INSTALL_DIR:\=\\)\"" \ -DCFG_INSTALL_INCDIR="\"$(INCLUDE_INSTALL_DIR:\=\\)\"" \ -DCFG_INSTALL_DOCDIR="\"$(DOC_INSTALL_DIR:\=\\)\"" \ -DCFG_RUNTIME_LIBDIR="\"$(LIB_INSTALL_DIR:\=\\)\"" \ -DCFG_RUNTIME_BINDIR="\"$(BIN_INSTALL_DIR:\=\\)\"" \ -DCFG_RUNTIME_SCRDIR="\"$(SCRIPT_INSTALL_DIR:\=\\)\"" \ -DCFG_RUNTIME_INCDIR="\"$(INCLUDE_INSTALL_DIR:\=\\)\"" \ -DCFG_RUNTIME_DOCDIR="\"$(DOC_INSTALL_DIR:\=\\)\"" \ -Fo$@ $? $(TMP_DIR)\tclAppInit.obj: $(WINDIR)\tclAppInit.c $(cc32) $(TCL_CFLAGS) \ -DTCL_USE_STATIC_PACKAGES=$(TCL_USE_STATIC_PACKAGES) \ -Fo$@ $? ### The following objects should be built using the stub interfaces ### *ALL* extensions need to built with -DTCL_THREADS=1 $(TMP_DIR)\tclWinReg.obj: $(WINDIR)\tclWinReg.c !if $(STATIC_BUILD) $(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DSTATIC_BUILD -Fo$@ $? !else $(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DUSE_TCL_STUBS -Fo$@ $? !endif $(TMP_DIR)\tclWinDde.obj: $(WINDIR)\tclWinDde.c !if $(STATIC_BUILD) $(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DSTATIC_BUILD -Fo$@ $? !else $(cc32) $(TCL_CFLAGS) -DTCL_THREADS=1 -DUSE_TCL_STUBS -Fo$@ $? !endif ### The following objects are part of the stub library and should not ### be built as DLL objects. -Zl is used to avoid a dependency on any ### specific C run-time. $(TMP_DIR)\tclStubLib.obj: $(GENERICDIR)\tclStubLib.c $(cc32) $(STUB_CFLAGS) -Zl -DSTATIC_BUILD $(TCL_INCLUDES) -Fo$@ $? $(TMP_DIR)\tclTomMathStubLib.obj: $(GENERICDIR)\tclTomMathStubLib.c $(cc32) $(STUB_CFLAGS) -Zl -DSTATIC_BUILD $(TCL_INCLUDES) -Fo$@ $? $(TMP_DIR)\tclOOStubLib.obj: $(GENERICDIR)\tclOOStubLib.c $(cc32) $(STUB_CFLAGS) -Zl -DSTATIC_BUILD $(TCL_INCLUDES) -Fo$@ $? $(TMP_DIR)\tclsh.exe.manifest: $(WINDIR)\tclsh.exe.manifest.in @nmakehlp -s << $** >$@ @MACHINE@ $(MACHINE:IX86=X86) @TCL_WIN_VERSION@ $(DOTVERSION).0.0 << #--------------------------------------------------------------------- # Generate the source dependencies. Having dependency rules will # improve incremental build accuracy without having to resort to a # full rebuild just because some non-global header file like # tclCompile.h was changed. These rules aren't needed when building # from scratch. #--------------------------------------------------------------------- depend: !if !exist($(TCLSH)) @echo Build tclsh first! !else $(TCLSH) $(TOOLSDIR:\=/)/mkdepend.tcl -vc32 -out:"$(OUT_DIR)\depend.mk" \ -passthru:"-DBUILD_tcl $(TCL_INCLUDES)" $(GENERICDIR),$$(GENERICDIR) \ $(COMPATDIR),$$(COMPATDIR) $(TOMMATHDIR),$$(TOMMATHDIR) $(WINDIR),$$(WINDIR) @<< $(TCLOBJS) << !endif #--------------------------------------------------------------------- # Dependency rules #--------------------------------------------------------------------- !if exist("$(OUT_DIR)\depend.mk") !include "$(OUT_DIR)\depend.mk" !message *** Dependency rules in use. !else !message *** Dependency rules are not being used. !endif ### add a spacer in the output !message #--------------------------------------------------------------------- # Implicit rules. A limitation exists with nmake that requires that # source directory can not contain spaces in the path. This an # absolute. #--------------------------------------------------------------------- {$(WINDIR)}.c{$(TMP_DIR)}.obj:: $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<< $< << {$(TOMMATHDIR)}.c{$(TMP_DIR)}.obj:: $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<< $< << {$(GENERICDIR)}.c{$(TMP_DIR)}.obj:: $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<< $< << {$(COMPATDIR)}.c{$(TMP_DIR)}.obj:: $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<< $< << {$(COMPATDIR)\zlib}.c{$(TMP_DIR)}.obj:: $(cc32) $(TCL_CFLAGS) -DBUILD_tcl -Fo$(TMP_DIR)\ @<< $< << {$(WINDIR)}.rc{$(TMP_DIR)}.res: $(rc32) -fo $@ -r -i "$(GENERICDIR)" -i "$(TMP_DIR)" \ -d DEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \ -d TCL_THREADS=$(TCL_THREADS) \ -d STATIC_BUILD=$(STATIC_BUILD) \ $< $(TMP_DIR)\tclsh.res: $(TMP_DIR)\tclsh.exe.manifest .SUFFIXES: .SUFFIXES:.c .rc #--------------------------------------------------------------------- # Installation. #--------------------------------------------------------------------- install-binaries: @echo Installing to '$(_INSTALLDIR)' @echo Installing $(TCLLIBNAME) !if "$(TCLLIB)" != "$(TCLIMPLIB)" @$(CPY) "$(TCLLIB)" "$(BIN_INSTALL_DIR)\" !endif @$(CPY) "$(TCLIMPLIB)" "$(LIB_INSTALL_DIR)\" !if exist($(TCLSH)) @echo Installing $(TCLSHNAME) @$(CPY) "$(TCLSH)" "$(BIN_INSTALL_DIR)\" !endif @echo Installing $(TCLSTUBLIBNAME) @$(CPY) "$(TCLSTUBLIB)" "$(LIB_INSTALL_DIR)\" #" emacs fix install-libraries: tclConfig install-msgs install-tzdata @if not exist "$(SCRIPT_INSTALL_DIR)$(NULL)" \ $(MKDIR) "$(SCRIPT_INSTALL_DIR)" @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8$(NULL)" \ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8" @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4$(NULL)" \ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4" @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4\platform$(NULL)" \ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4\platform" @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.5$(NULL)" \ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.5" @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.6$(NULL)" \ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.6" @echo Installing header files @$(CPY) "$(GENERICDIR)\tcl.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclDecls.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclOO.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclOODecls.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclPlatDecls.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclTomMath.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(GENERICDIR)\tclTomMathDecls.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(TOMMATHDIR)\tommath_class.h" "$(INCLUDE_INSTALL_DIR)\" @$(CPY) "$(TOMMATHDIR)\tommath_superclass.h" "$(INCLUDE_INSTALL_DIR)\" @echo Installing library files to $(SCRIPT_INSTALL_DIR) @$(CPY) "$(ROOT)\library\history.tcl" "$(SCRIPT_INSTALL_DIR)\" @$(CPY) "$(ROOT)\library\init.tcl" "$(SCRIPT_INSTALL_DIR)\" @$(CPY) "$(ROOT)\library\clock.tcl" "$(SCRIPT_INSTALL_DIR)\" @$(CPY) "$(ROOT)\library\tm.tcl" "$(SCRIPT_INSTALL_DIR)\" @$(CPY) "$(ROOT)\library\parray.tcl" "$(SCRIPT_INSTALL_DIR)\" @$(CPY) "$(ROOT)\library\safe.tcl" "$(SCRIPT_INSTALL_DIR)\" @$(CPY) "$(ROOT)\library\tclIndex" "$(SCRIPT_INSTALL_DIR)\" @$(CPY) "$(ROOT)\library\package.tcl" "$(SCRIPT_INSTALL_DIR)\" @$(CPY) "$(ROOT)\library\word.tcl" "$(SCRIPT_INSTALL_DIR)\" @$(CPY) "$(ROOT)\library\auto.tcl" "$(SCRIPT_INSTALL_DIR)\" @$(CPY) "$(OUT_DIR)\tclConfig.sh" "$(LIB_INSTALL_DIR)\" @$(CPY) "$(WINDIR)\tclooConfig.sh" "$(LIB_INSTALL_DIR)\" @echo Installing library http1.0 directory @$(CPY) "$(ROOT)\library\http1.0\*.tcl" \ "$(SCRIPT_INSTALL_DIR)\http1.0\" @echo Installing library opt0.4 directory @$(CPY) "$(ROOT)\library\opt\*.tcl" \ "$(SCRIPT_INSTALL_DIR)\opt0.4\" @echo Installing package http $(PKG_HTTP_VER) as a Tcl Module @$(COPY) "$(ROOT)\library\http\http.tcl" \ "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.6\http-$(PKG_HTTP_VER).tm" @echo Installing package msgcat $(PKG_MSGCAT_VER) as a Tcl Module @$(COPY) "$(ROOT)\library\msgcat\msgcat.tcl" \ "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.5\msgcat-$(PKG_MSGCAT_VER).tm" @echo Installing package tcltest $(PKG_TCLTEST_VER) as a Tcl Module @$(COPY) "$(ROOT)\library\tcltest\tcltest.tcl" \ "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.5\tcltest-$(PKG_TCLTEST_VER).tm" @echo Installing package platform $(PKG_PLATFORM_VER) as a Tcl Module @$(COPY) "$(ROOT)\library\platform\platform.tcl" \ "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4\platform-$(PKG_PLATFORM_VER).tm" @echo Installing package platform::shell $(PKG_SHELL_VER) as a Tcl Module @$(COPY) "$(ROOT)\library\platform\shell.tcl" \ "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.4\platform\shell-$(PKG_SHELL_VER).tm" @echo Installing $(TCLDDELIBNAME) !if $(STATIC_BUILD) !if !$(TCL_USE_STATIC_PACKAGES) @$(CPY) "$(TCLDDELIB)" "$(LIB_INSTALL_DIR)\" !endif !else @$(CPY) "$(TCLDDELIB)" "$(LIB_INSTALL_DIR)\dde$(DDEDOTVERSION)\" @$(CPY) "$(ROOT)\library\dde\pkgIndex.tcl" \ "$(LIB_INSTALL_DIR)\dde$(DDEDOTVERSION)\" !endif @echo Installing $(TCLREGLIBNAME) !if $(STATIC_BUILD) !if !$(TCL_USE_STATIC_PACKAGES) @$(CPY) "$(TCLREGLIB)" "$(LIB_INSTALL_DIR)\" !endif !else @$(CPY) "$(TCLREGLIB)" "$(LIB_INSTALL_DIR)\reg$(REGDOTVERSION)\" @$(CPY) "$(ROOT)\library\reg\pkgIndex.tcl" \ "$(LIB_INSTALL_DIR)\reg$(REGDOTVERSION)\" !endif @echo Installing encodings @$(CPY) "$(ROOT)\library\encoding\*.enc" \ "$(SCRIPT_INSTALL_DIR)\encoding\" #" emacs fix install-tzdata: @echo Installing time zone data @set TCL_LIBRARY=$(ROOT:\=/)/library @$(TCLSH_NATIVE) "$(ROOT:\=/)/tools/installData.tcl" \ "$(ROOT:\=/)/library/tzdata" "$(SCRIPT_INSTALL_DIR)/tzdata" install-msgs: @echo Installing message catalogs @set TCL_LIBRARY=$(ROOT:\=/)/library @$(TCLSH_NATIVE) "$(ROOT:\=/)/tools/installData.tcl" \ "$(ROOT:\=/)/library/msgs" "$(SCRIPT_INSTALL_DIR)/msgs" #--------------------------------------------------------------------- # Clean up #--------------------------------------------------------------------- tidy: !if "$(TCLLIB)" != "$(TCLIMPLIB)" @echo Removing $(TCLLIB) ... @if exist $(TCLLIB) del $(TCLLIB) !endif @echo Removing $(TCLIMPLIB) ... @if exist $(TCLIMPLIB) del $(TCLIMPLIB) @echo Removing $(TCLSH) ... @if exist $(TCLSH) del $(TCLSH) @echo Removing $(TCLTEST) ... @if exist $(TCLTEST) del $(TCLTEST) @echo Removing $(TCLDDELIB) ... @if exist $(TCLDDELIB) del $(TCLDDELIB) @echo Removing $(TCLREGLIB) ... @if exist $(TCLREGLIB) del $(TCLREGLIB) clean: clean-pkgs @echo Cleaning $(TMP_DIR)\* ... @if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR) @echo Cleaning $(WINDIR)\nmakehlp.obj ... @if exist $(WINDIR)\nmakehlp.obj del $(WINDIR)\nmakehlp.obj @echo Cleaning $(WINDIR)\nmakehlp.exe ... @if exist $(WINDIR)\nmakehlp.exe del $(WINDIR)\nmakehlp.exe @echo Cleaning $(WINDIR)\_junk.pch ... @if exist $(WINDIR)\_junk.pch del $(WINDIR)\_junk.pch @echo Cleaning $(WINDIR)\vercl.x ... @if exist $(WINDIR)\vercl.x del $(WINDIR)\vercl.x @echo Cleaning $(WINDIR)\vercl.i ... @if exist $(WINDIR)\vercl.i del $(WINDIR)\vercl.i @echo Cleaning $(WINDIR)\versions.vc ... @if exist $(WINDIR)\versions.vc del $(WINDIR)\versions.vc realclean: hose hose: @echo Hosing $(OUT_DIR)\* ... @if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR) # Local Variables: # mode: makefile # End: tcl8.6.5/win/tclAppInit.c0000644000175000017500000002020412663660066014576 0ustar sergeisergei/* * tclAppInit.c -- * * Provides a default version of the main program and Tcl_AppInit * procedure for tclsh and other Tcl-based applications (without Tk). * Note that this program must be built in Win32 console mode to work * properly. * * Copyright (c) 1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tcl.h" #define WIN32_LEAN_AND_MEAN #define STRICT /* See MSDN Article Q83456 */ #include #undef STRICT #undef WIN32_LEAN_AND_MEAN #include #include #include #ifdef TCL_TEST extern Tcl_PackageInitProc Tcltest_Init; extern Tcl_PackageInitProc Tcltest_SafeInit; #endif /* TCL_TEST */ #if defined(STATIC_BUILD) && TCL_USE_STATIC_PACKAGES extern Tcl_PackageInitProc Registry_Init; extern Tcl_PackageInitProc Dde_Init; extern Tcl_PackageInitProc Dde_SafeInit; #endif #ifdef TCL_BROKEN_MAINARGS int _CRT_glob = 0; static void setargv(int *argcPtr, TCHAR ***argvPtr); #endif /* TCL_BROKEN_MAINARGS */ /* * The following #if block allows you to change the AppInit function by using * a #define of TCL_LOCAL_APPINIT instead of rewriting this entire file. The * #if checks for that #define and uses Tcl_AppInit if it does not exist. */ #ifndef TCL_LOCAL_APPINIT #define TCL_LOCAL_APPINIT Tcl_AppInit #endif #ifndef MODULE_SCOPE # define MODULE_SCOPE extern #endif MODULE_SCOPE int TCL_LOCAL_APPINIT(Tcl_Interp *); /* * The following #if block allows you to change how Tcl finds the startup * script, prime the library or encoding paths, fiddle with the argv, etc., * without needing to rewrite Tcl_Main() */ #ifdef TCL_LOCAL_MAIN_HOOK MODULE_SCOPE int TCL_LOCAL_MAIN_HOOK(int *argc, TCHAR ***argv); #endif /* *---------------------------------------------------------------------- * * main -- * * This is the main program for the application. * * Results: * None: Tcl_Main never returns here, so this procedure never returns * either. * * Side effects: * Just about anything, since from here we call arbitrary Tcl code. * *---------------------------------------------------------------------- */ #ifdef TCL_BROKEN_MAINARGS int main( int argc, /* Number of command-line arguments. */ char *dummy[]) /* Not used. */ { TCHAR **argv; #else int _tmain( int argc, /* Number of command-line arguments. */ TCHAR *argv[]) /* Values of command-line arguments. */ { #endif TCHAR *p; /* * Set up the default locale to be standard "C" locale so parsing is * performed correctly. */ setlocale(LC_ALL, "C"); #ifdef TCL_BROKEN_MAINARGS /* * Get our args from the c-runtime. Ignore command line. */ setargv(&argc, &argv); #endif /* * Forward slashes substituted for backslashes. */ for (p = argv[0]; *p != '\0'; p++) { if (*p == '\\') { *p = '/'; } } #ifdef TCL_LOCAL_MAIN_HOOK TCL_LOCAL_MAIN_HOOK(&argc, &argv); #endif Tcl_Main(argc, argv, TCL_LOCAL_APPINIT); return 0; /* Needed only to prevent compiler warning. */ } /* *---------------------------------------------------------------------- * * Tcl_AppInit -- * * This procedure performs application-specific initialization. Most * applications, especially those that incorporate additional packages, * will have their own version of this procedure. * * Results: * Returns a standard Tcl completion code, and leaves an error message in * the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- */ int Tcl_AppInit( Tcl_Interp *interp) /* Interpreter for application. */ { if ((Tcl_Init)(interp) == TCL_ERROR) { return TCL_ERROR; } #if defined(STATIC_BUILD) && TCL_USE_STATIC_PACKAGES if (Registry_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(interp, "registry", Registry_Init, NULL); if (Dde_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(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); #endif /* TCL_TEST */ /* * Call the init procedures for included packages. Each call should look * like this: * * if (Mod_Init(interp) == TCL_ERROR) { * return TCL_ERROR; * } * * where "Mod" is the name of the module. (Dynamically-loadable packages * should have the same entry-point name.) */ /* * Call Tcl_CreateCommand for application-specific commands, if they * weren't already created by the init procedures called above. */ /* * Specify a user-specific startup file to invoke if the application is * run interactively. Typically the startup file is "~/.apprc" where "app" * is the name of the application. If this line is deleted then no * user-specific startup file will be run under any conditions. */ (Tcl_ObjSetVar2)(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL, Tcl_NewStringObj("~/tclshrc.tcl", -1), TCL_GLOBAL_ONLY); return TCL_OK; } /* *------------------------------------------------------------------------- * * setargv -- * * Parse the Windows command line string into argc/argv. Done here * because we don't trust the builtin argument parser in crt0. Windows * applications are responsible for breaking their command line into * arguments. * * 2N backslashes + quote -> N backslashes + begin quoted string * 2N + 1 backslashes + quote -> literal * N backslashes + non-quote -> literal * quote + quote in a quoted string -> single quote * quote + quote not in quoted string -> empty string * quote -> begin quoted string * * Results: * Fills argcPtr with the number of arguments and argvPtr with the array * of arguments. * * Side effects: * Memory allocated. * *-------------------------------------------------------------------------- */ #ifdef TCL_BROKEN_MAINARGS static void setargv( int *argcPtr, /* Filled with number of argument strings. */ TCHAR ***argvPtr) /* Filled with argument strings (malloc'd). */ { TCHAR *cmdLine, *p, *arg, *argSpace; TCHAR **argv; int argc, size, inquote, copy, slashes; cmdLine = GetCommandLine(); /* * Precompute an overly pessimistic guess at the number of arguments in * the command line by counting non-space spans. */ size = 2; for (p = cmdLine; *p != '\0'; p++) { if ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ size++; while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ p++; } if (*p == '\0') { break; } } } /* Make sure we don't call ckalloc through the (not yet initialized) stub table */ #undef Tcl_Alloc #undef Tcl_DbCkalloc argSpace = ckalloc(size * sizeof(char *) + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR)); argv = (TCHAR **) argSpace; argSpace += size * (sizeof(char *)/sizeof(TCHAR)); size--; p = cmdLine; for (argc = 0; argc < size; argc++) { argv[argc] = arg = argSpace; while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ p++; } if (*p == '\0') { break; } inquote = 0; slashes = 0; while (1) { copy = 1; while (*p == '\\') { slashes++; p++; } if (*p == '"') { if ((slashes & 1) == 0) { copy = 0; if ((inquote) && (p[1] == '"')) { p++; copy = 1; } else { inquote = !inquote; } } slashes >>= 1; } while (slashes) { *arg = '\\'; arg++; slashes--; } if ((*p == '\0') || (!inquote && ((*p == ' ') || (*p == '\t')))) { /* INTL: ISO space. */ break; } if (copy != 0) { *arg = *p; arg++; } p++; } *arg = '\0'; argSpace = arg + 1; } argv[argc] = NULL; *argcPtr = argc; *argvPtr = argv; } #endif /* TCL_BROKEN_MAINARGS */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tclsh.exe.manifest.in0000644000175000017500000000322112665173607016417 0ustar sergeisergei Tcl command line shell (tclsh) true tcl8.6.5/win/tclWinInt.h0000644000175000017500000000526412663660066014460 0ustar sergeisergei/* * tclWinInt.h -- * * Declarations of Windows-specific shared variables and procedures. * * Copyright (c) 1994-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. */ #ifndef _TCLWININT #define _TCLWININT #include "tclInt.h" #ifdef HAVE_NO_SEH /* * Unlike Borland and Microsoft, we don't register exception handlers by * pushing registration records onto the runtime stack. Instead, we register * them by creating an TCLEXCEPTION_REGISTRATION within the activation record. */ typedef struct TCLEXCEPTION_REGISTRATION { struct TCLEXCEPTION_REGISTRATION *link; EXCEPTION_DISPOSITION (*handler)( struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*); void *ebp; void *esp; int status; } TCLEXCEPTION_REGISTRATION; #endif /* * Some versions of Borland C have a define for the OSVERSIONINFO for * Win32s and for NT, but not for Windows 95. * Define VER_PLATFORM_WIN32_CE for those without newer headers. */ #ifndef VER_PLATFORM_WIN32_WINDOWS #define VER_PLATFORM_WIN32_WINDOWS 1 #endif #ifndef VER_PLATFORM_WIN32_CE #define VER_PLATFORM_WIN32_CE 3 #endif #ifdef _WIN64 # define TCL_I_MODIFIER "I" #else # define TCL_I_MODIFIER "" #endif /* * Declarations of functions that are not accessible by way of the * stubs table. */ MODULE_SCOPE char TclWinDriveLetterForVolMountPoint( const TCHAR *mountPoint); MODULE_SCOPE void TclWinEncodingsCleanup(); MODULE_SCOPE void TclWinInit(HINSTANCE hInst); MODULE_SCOPE TclFile TclWinMakeFile(HANDLE handle); MODULE_SCOPE Tcl_Channel TclWinOpenConsoleChannel(HANDLE handle, char *channelName, int permissions); MODULE_SCOPE Tcl_Channel TclWinOpenFileChannel(HANDLE handle, char *channelName, int permissions, int appendMode); MODULE_SCOPE Tcl_Channel TclWinOpenSerialChannel(HANDLE handle, char *channelName, int permissions); MODULE_SCOPE HANDLE TclWinSerialOpen(HANDLE handle, const TCHAR *name, DWORD access); MODULE_SCOPE int TclWinSymLinkCopyDirectory(const TCHAR *LinkOriginal, const TCHAR *LinkCopy); MODULE_SCOPE int TclWinSymLinkDelete(const TCHAR *LinkOriginal, int linkOnly); #if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) MODULE_SCOPE void TclWinFreeAllocCache(void); MODULE_SCOPE void TclFreeAllocCache(void *); MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex(void); MODULE_SCOPE void * TclpGetAllocCache(void); MODULE_SCOPE void TclpSetAllocCache(void *); #endif /* TCL_THREADS */ /* Needed by tclWinFile.c and tclWinFCmd.c */ #ifndef FILE_ATTRIBUTE_REPARSE_POINT #define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400 #endif #endif /* _TCLWININT */ tcl8.6.5/win/tclWinFCmd.c0000644000175000017500000015062412663660066014533 0ustar sergeisergei/* * tclWinFCmd.c * * This file implements the Windows specific portion of file manipulation * subcommands of the "file" command. * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclWinInt.h" /* * The following constants specify the type of callback when * TraverseWinTree() calls the traverseProc() */ #define DOTREE_PRED 1 /* pre-order directory */ #define DOTREE_POSTD 2 /* post-order directory */ #define DOTREE_F 3 /* regular file */ #define DOTREE_LINK 4 /* symbolic link */ /* * Callbacks for file attributes code. */ static int GetWinFileAttributes(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); static int GetWinFileLongName(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); static int GetWinFileShortName(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); static int SetWinFileAttributes(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj *attributePtr); static int CannotSetAttribute(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj *attributePtr); /* * Constants and variables necessary for file attributes subcommand. */ enum { WIN_ARCHIVE_ATTRIBUTE, WIN_HIDDEN_ATTRIBUTE, WIN_LONGNAME_ATTRIBUTE, WIN_READONLY_ATTRIBUTE, WIN_SHORTNAME_ATTRIBUTE, WIN_SYSTEM_ATTRIBUTE }; static const int attributeArray[] = {FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_HIDDEN, 0, FILE_ATTRIBUTE_READONLY, 0, FILE_ATTRIBUTE_SYSTEM}; const char *const tclpFileAttrStrings[] = { "-archive", "-hidden", "-longname", "-readonly", "-shortname", "-system", (char *) NULL }; const TclFileAttrProcs tclpFileAttrProcs[] = { {GetWinFileAttributes, SetWinFileAttributes}, {GetWinFileAttributes, SetWinFileAttributes}, {GetWinFileLongName, CannotSetAttribute}, {GetWinFileAttributes, SetWinFileAttributes}, {GetWinFileShortName, CannotSetAttribute}, {GetWinFileAttributes, SetWinFileAttributes}}; /* * Prototype for the TraverseWinTree callback function. */ typedef int (TraversalProc)(const TCHAR *srcPtr, const TCHAR *dstPtr, int type, Tcl_DString *errorPtr); /* * Declarations for local functions defined in this file: */ static void StatError(Tcl_Interp *interp, Tcl_Obj *fileName); static int ConvertFileNameFormat(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, int longShort, Tcl_Obj **attributePtrPtr); static int DoCopyFile(const TCHAR *srcPtr, const TCHAR *dstPtr); static int DoCreateDirectory(const TCHAR *pathPtr); static int DoRemoveJustDirectory(const TCHAR *nativeSrc, int ignoreError, Tcl_DString *errorPtr); static int DoRemoveDirectory(Tcl_DString *pathPtr, int recursive, Tcl_DString *errorPtr); static int DoRenameFile(const TCHAR *nativeSrc, const TCHAR *dstPtr); static int TraversalCopy(const TCHAR *srcPtr, const TCHAR *dstPtr, int type, Tcl_DString *errorPtr); static int TraversalDelete(const TCHAR *srcPtr, const TCHAR *dstPtr, int type, Tcl_DString *errorPtr); static int TraverseWinTree(TraversalProc *traverseProc, Tcl_DString *sourcePtr, Tcl_DString *dstPtr, Tcl_DString *errorPtr); /* *--------------------------------------------------------------------------- * * TclpObjRenameFile, DoRenameFile -- * * Changes the name of an existing file or directory, from src to dst. * If src and dst refer to the same file or directory, does nothing and * returns success. Otherwise if dst already exists, it will be deleted * and replaced by src subject to the following conditions: * If src is a directory, dst may be an empty directory. * If src is a file, dst may be a file. * In any other situation where dst already exists, the rename will fail. * * Results: * If the file or directory was successfully renamed, returns TCL_OK. * Otherwise the return value is TCL_ERROR and errno is set to indicate * the error. Some possible values for errno are: * * ENAMETOOLONG: src or dst names are too long. * EACCES: src or dst parent directory can't be read and/or written. * EEXIST: dst is a non-empty directory. * EINVAL: src is a root directory or dst is a subdirectory of src. * EISDIR: dst is a directory, but src is not. * ENOENT: src doesn't exist. src or dst is "". * ENOTDIR: src is a directory, but dst is not. * EXDEV: src and dst are on different filesystems. * * EACCES: exists an open file already referring to src or dst. * EACCES: src or dst specify the current working directory (NT). * EACCES: src specifies a char device (nul:, com1:, etc.) * EEXIST: dst specifies a char device (nul:, com1:, etc.) (NT) * EACCES: dst specifies a char device (nul:, com1:, etc.) (95) * * Side effects: * The implementation supports cross-filesystem renames of files, but the * caller should be prepared to emulate cross-filesystem renames of * directories if errno is EXDEV. * *--------------------------------------------------------------------------- */ int TclpObjRenameFile( Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr) { return DoRenameFile(Tcl_FSGetNativePath(srcPathPtr), Tcl_FSGetNativePath(destPathPtr)); } static int DoRenameFile( const TCHAR *nativeSrc, /* Pathname of file or dir to be renamed * (native). */ const TCHAR *nativeDst) /* New pathname for file or directory * (native). */ { #if defined(HAVE_NO_SEH) && !defined(_WIN64) TCLEXCEPTION_REGISTRATION registration; #endif DWORD srcAttr, dstAttr; int retval = -1; /* * The MoveFile API acts differently under Win95/98 and NT WRT NULL and * "". Avoid passing these values. */ if (nativeSrc == NULL || nativeSrc[0] == '\0' || nativeDst == NULL || nativeDst[0] == '\0') { Tcl_SetErrno(ENOENT); return TCL_ERROR; } /* * The MoveFile API would throw an exception under NT if one of the * arguments is a char block device. */ #if defined(HAVE_NO_SEH) && !defined(_WIN64) /* * Don't have SEH available, do things the hard way. Note that this needs * to be one block of asm, to avoid stack imbalance; also, it is illegal * for one asm block to contain a jump to another. */ __asm__ __volatile__ ( /* * Pick up params before messing with the stack. */ "movl %[nativeDst], %%ebx" "\n\t" "movl %[nativeSrc], %%ecx" "\n\t" /* * Construct an TCLEXCEPTION_REGISTRATION to protect the call to * MoveFile. */ "leal %[registration], %%edx" "\n\t" "movl %%fs:0, %%eax" "\n\t" "movl %%eax, 0x0(%%edx)" "\n\t" /* link */ "leal 1f, %%eax" "\n\t" "movl %%eax, 0x4(%%edx)" "\n\t" /* handler */ "movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */ "movl %%esp, 0xc(%%edx)" "\n\t" /* esp */ "movl $0, 0x10(%%edx)" "\n\t" /* status */ /* * Link the TCLEXCEPTION_REGISTRATION on the chain. */ "movl %%edx, %%fs:0" "\n\t" /* * Call MoveFile(nativeSrc, nativeDst) */ "pushl %%ebx" "\n\t" "pushl %%ecx" "\n\t" "movl %[moveFile], %%eax" "\n\t" "call *%%eax" "\n\t" /* * Come here on normal exit. Recover the TCLEXCEPTION_REGISTRATION and * put the status return from MoveFile into it. */ "movl %%fs:0, %%edx" "\n\t" "movl %%eax, 0x10(%%edx)" "\n\t" "jmp 2f" "\n" /* * Come here on an exception. Recover the TCLEXCEPTION_REGISTRATION */ "1:" "\t" "movl %%fs:0, %%edx" "\n\t" "movl 0x8(%%edx), %%edx" "\n\t" /* * Come here however we exited. Restore context from the * TCLEXCEPTION_REGISTRATION in case the stack is unbalanced. */ "2:" "\t" "movl 0xc(%%edx), %%esp" "\n\t" "movl 0x8(%%edx), %%ebp" "\n\t" "movl 0x0(%%edx), %%eax" "\n\t" "movl %%eax, %%fs:0" "\n\t" : /* No outputs */ : [registration] "m" (registration), [nativeDst] "m" (nativeDst), [nativeSrc] "m" (nativeSrc), [moveFile] "r" (MoveFile) : "%eax", "%ebx", "%ecx", "%edx", "memory" ); if (registration.status != FALSE) { retval = TCL_OK; } #else #ifndef HAVE_NO_SEH __try { #endif if ((*MoveFile)(nativeSrc, nativeDst) != FALSE) { retval = TCL_OK; } #ifndef HAVE_NO_SEH } __except (EXCEPTION_EXECUTE_HANDLER) {} #endif #endif if (retval != -1) { return retval; } TclWinConvertError(GetLastError()); srcAttr = GetFileAttributes(nativeSrc); dstAttr = GetFileAttributes(nativeDst); if (srcAttr == 0xffffffff) { if (GetFullPathName(nativeSrc, 0, NULL, NULL) >= MAX_PATH) { errno = ENAMETOOLONG; return TCL_ERROR; } srcAttr = 0; } if (dstAttr == 0xffffffff) { if (GetFullPathName(nativeDst, 0, NULL, NULL) >= MAX_PATH) { errno = ENAMETOOLONG; return TCL_ERROR; } dstAttr = 0; } if (errno == EBADF) { errno = EACCES; return TCL_ERROR; } if (errno == EACCES) { decode: if (srcAttr & FILE_ATTRIBUTE_DIRECTORY) { TCHAR *nativeSrcRest, *nativeDstRest; const char **srcArgv, **dstArgv; int size, srcArgc, dstArgc; TCHAR nativeSrcPath[MAX_PATH]; TCHAR nativeDstPath[MAX_PATH]; Tcl_DString srcString, dstString; const char *src, *dst; size = GetFullPathName(nativeSrc, MAX_PATH, nativeSrcPath, &nativeSrcRest); if ((size == 0) || (size > MAX_PATH)) { return TCL_ERROR; } size = GetFullPathName(nativeDst, MAX_PATH, nativeDstPath, &nativeDstRest); if ((size == 0) || (size > MAX_PATH)) { return TCL_ERROR; } CharLower(nativeSrcPath); CharLower(nativeDstPath); src = Tcl_WinTCharToUtf(nativeSrcPath, -1, &srcString); dst = Tcl_WinTCharToUtf(nativeDstPath, -1, &dstString); /* * Check whether the destination path is actually inside the * source path. This is true if the prefix matches, and the next * character is either end-of-string or a directory separator */ if ((strncmp(src, dst, (size_t) Tcl_DStringLength(&srcString))==0) && (dst[Tcl_DStringLength(&srcString)] == '\\' || dst[Tcl_DStringLength(&srcString)] == '/' || dst[Tcl_DStringLength(&srcString)] == '\0')) { /* * Trying to move a directory into itself. */ errno = EINVAL; Tcl_DStringFree(&srcString); Tcl_DStringFree(&dstString); return TCL_ERROR; } Tcl_SplitPath(src, &srcArgc, &srcArgv); Tcl_SplitPath(dst, &dstArgc, &dstArgv); Tcl_DStringFree(&srcString); Tcl_DStringFree(&dstString); if (srcArgc == 1) { /* * They are trying to move a root directory. Whether or not it * is across filesystems, this cannot be done. */ Tcl_SetErrno(EINVAL); } else if ((srcArgc > 0) && (dstArgc > 0) && (strcmp(srcArgv[0], dstArgv[0]) != 0)) { /* * If src is a directory and dst filesystem != src filesystem, * errno should be EXDEV. It is very important to get this * behavior, so that the caller can respond to a cross * filesystem rename by simulating it with copy and delete. * The MoveFile system call already handles the case of moving * a file between filesystems. */ Tcl_SetErrno(EXDEV); } ckfree(srcArgv); ckfree(dstArgv); } /* * Other types of access failure is that dst is a read-only * filesystem, that an open file referred to src or dest, or that src * or dest specified the current working directory on the current * filesystem. EACCES is returned for those cases. */ } else if (Tcl_GetErrno() == EEXIST) { /* * Reports EEXIST any time the target already exists. If it makes * sense, remove the old file and try renaming again. */ if (srcAttr & FILE_ATTRIBUTE_DIRECTORY) { if (dstAttr & FILE_ATTRIBUTE_DIRECTORY) { /* * Overwrite empty dst directory with src directory. The * following call will remove an empty directory. If it fails, * it's because it wasn't empty. */ if (DoRemoveJustDirectory(nativeDst, 0, NULL) == TCL_OK) { /* * Now that that empty directory is gone, we can try * renaming again. If that fails, we'll put this empty * directory back, for completeness. */ if (MoveFile(nativeSrc, nativeDst) != FALSE) { return TCL_OK; } /* * Some new error has occurred. Don't know what it could * be, but report this one. */ TclWinConvertError(GetLastError()); CreateDirectory(nativeDst, NULL); SetFileAttributes(nativeDst, dstAttr); if (Tcl_GetErrno() == EACCES) { /* * Decode the EACCES to a more meaningful error. */ goto decode; } } } else { /* (dstAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 */ Tcl_SetErrno(ENOTDIR); } } else { /* (srcAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 */ if (dstAttr & FILE_ATTRIBUTE_DIRECTORY) { Tcl_SetErrno(EISDIR); } else { /* * Overwrite existing file by: * * 1. Rename existing file to temp name. * 2. Rename old file to new name. * 3. If success, delete temp file. If failure, put temp file * back to old name. */ TCHAR *nativeRest, *nativeTmp, *nativePrefix; int result, size; TCHAR tempBuf[MAX_PATH]; size = GetFullPathName(nativeDst, MAX_PATH, tempBuf, &nativeRest); if ((size == 0) || (size > MAX_PATH) || (nativeRest == NULL)) { return TCL_ERROR; } nativeTmp = (TCHAR *) tempBuf; nativeRest[0] = L'\0'; result = TCL_ERROR; nativePrefix = (TCHAR *) L"tclr"; if (GetTempFileName(nativeTmp, nativePrefix, 0, tempBuf) != 0) { /* * Strictly speaking, need the following DeleteFile and * MoveFile to be joined as an atomic operation so no * other app comes along in the meantime and creates the * same temp file. */ nativeTmp = tempBuf; DeleteFile(nativeTmp); if (MoveFile(nativeDst, nativeTmp) != FALSE) { if (MoveFile(nativeSrc, nativeDst) != FALSE) { SetFileAttributes(nativeTmp, FILE_ATTRIBUTE_NORMAL); DeleteFile(nativeTmp); return TCL_OK; } else { DeleteFile(nativeDst); MoveFile(nativeTmp, nativeDst); } } /* * Can't backup dst file or move src file. Return that * error. Could happen if an open file refers to dst. */ TclWinConvertError(GetLastError()); if (Tcl_GetErrno() == EACCES) { /* * Decode the EACCES to a more meaningful error. */ goto decode; } } return result; } } } return TCL_ERROR; } /* *--------------------------------------------------------------------------- * * TclpObjCopyFile, DoCopyFile -- * * Copy a single file (not a directory). If dst already exists and is not * a directory, it is removed. * * Results: * If the file was successfully copied, returns TCL_OK. Otherwise the * return value is TCL_ERROR and errno is set to indicate the error. * Some possible values for errno are: * * EACCES: src or dst parent directory can't be read and/or written. * EISDIR: src or dst is a directory. * ENOENT: src doesn't exist. src or dst is "". * * EACCES: exists an open file already referring to dst (95). * EACCES: src specifies a char device (nul:, com1:, etc.) (NT) * ENOENT: src specifies a char device (nul:, com1:, etc.) (95) * * Side effects: * It is not an error to copy to a char device. * *--------------------------------------------------------------------------- */ int TclpObjCopyFile( Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr) { return DoCopyFile(Tcl_FSGetNativePath(srcPathPtr), Tcl_FSGetNativePath(destPathPtr)); } static int DoCopyFile( const TCHAR *nativeSrc, /* Pathname of file to be copied (native). */ const TCHAR *nativeDst) /* Pathname of file to copy to (native). */ { #if defined(HAVE_NO_SEH) && !defined(_WIN64) TCLEXCEPTION_REGISTRATION registration; #endif int retval = -1; /* * The CopyFile API acts differently under Win95/98 and NT WRT NULL and * "". Avoid passing these values. */ if (nativeSrc == NULL || nativeSrc[0] == '\0' || nativeDst == NULL || nativeDst[0] == '\0') { Tcl_SetErrno(ENOENT); return TCL_ERROR; } /* * The CopyFile API would throw an exception under NT if one of the * arguments is a char block device. */ #if defined(HAVE_NO_SEH) && !defined(_WIN64) /* * Don't have SEH available, do things the hard way. Note that this needs * to be one block of asm, to avoid stack imbalance; also, it is illegal * for one asm block to contain a jump to another. */ __asm__ __volatile__ ( /* * Pick up parameters before messing with the stack */ "movl %[nativeDst], %%ebx" "\n\t" "movl %[nativeSrc], %%ecx" "\n\t" /* * Construct an TCLEXCEPTION_REGISTRATION to protect the call to * CopyFile. */ "leal %[registration], %%edx" "\n\t" "movl %%fs:0, %%eax" "\n\t" "movl %%eax, 0x0(%%edx)" "\n\t" /* link */ "leal 1f, %%eax" "\n\t" "movl %%eax, 0x4(%%edx)" "\n\t" /* handler */ "movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */ "movl %%esp, 0xc(%%edx)" "\n\t" /* esp */ "movl $0, 0x10(%%edx)" "\n\t" /* status */ /* * Link the TCLEXCEPTION_REGISTRATION on the chain. */ "movl %%edx, %%fs:0" "\n\t" /* * Call CopyFile(nativeSrc, nativeDst, 0) */ "movl %[copyFile], %%eax" "\n\t" "pushl $0" "\n\t" "pushl %%ebx" "\n\t" "pushl %%ecx" "\n\t" "call *%%eax" "\n\t" /* * Come here on normal exit. Recover the TCLEXCEPTION_REGISTRATION and * put the status return from CopyFile into it. */ "movl %%fs:0, %%edx" "\n\t" "movl %%eax, 0x10(%%edx)" "\n\t" "jmp 2f" "\n" /* * Come here on an exception. Recover the TCLEXCEPTION_REGISTRATION */ "1:" "\t" "movl %%fs:0, %%edx" "\n\t" "movl 0x8(%%edx), %%edx" "\n\t" /* * Come here however we exited. Restore context from the * TCLEXCEPTION_REGISTRATION in case the stack is unbalanced. */ "2:" "\t" "movl 0xc(%%edx), %%esp" "\n\t" "movl 0x8(%%edx), %%ebp" "\n\t" "movl 0x0(%%edx), %%eax" "\n\t" "movl %%eax, %%fs:0" "\n\t" : /* No outputs */ : [registration] "m" (registration), [nativeDst] "m" (nativeDst), [nativeSrc] "m" (nativeSrc), [copyFile] "r" (CopyFile) : "%eax", "%ebx", "%ecx", "%edx", "memory" ); if (registration.status != FALSE) { retval = TCL_OK; } #else #ifndef HAVE_NO_SEH __try { #endif if (CopyFile(nativeSrc, nativeDst, 0) != FALSE) { retval = TCL_OK; } #ifndef HAVE_NO_SEH } __except (EXCEPTION_EXECUTE_HANDLER) {} #endif #endif if (retval != -1) { return retval; } TclWinConvertError(GetLastError()); if (Tcl_GetErrno() == EBADF) { Tcl_SetErrno(EACCES); return TCL_ERROR; } if (Tcl_GetErrno() == EACCES) { DWORD srcAttr, dstAttr; srcAttr = GetFileAttributes(nativeSrc); dstAttr = GetFileAttributes(nativeDst); if (srcAttr != 0xffffffff) { if (dstAttr == 0xffffffff) { dstAttr = 0; } if ((srcAttr & FILE_ATTRIBUTE_DIRECTORY) || (dstAttr & FILE_ATTRIBUTE_DIRECTORY)) { if (srcAttr & FILE_ATTRIBUTE_REPARSE_POINT) { /* Source is a symbolic link -- copy it */ if (TclWinSymLinkCopyDirectory(nativeSrc, nativeDst)==0) { return TCL_OK; } } Tcl_SetErrno(EISDIR); } if (dstAttr & FILE_ATTRIBUTE_READONLY) { SetFileAttributes(nativeDst, dstAttr & ~((DWORD)FILE_ATTRIBUTE_READONLY)); if (CopyFile(nativeSrc, nativeDst, 0) != FALSE) { return TCL_OK; } /* * Still can't copy onto dst. Return that error, and restore * attributes of dst. */ TclWinConvertError(GetLastError()); SetFileAttributes(nativeDst, dstAttr); } } } return TCL_ERROR; } /* *--------------------------------------------------------------------------- * * TclpObjDeleteFile, TclpDeleteFile -- * * Removes a single file (not a directory). * * Results: * If the file was successfully deleted, returns TCL_OK. Otherwise the * return value is TCL_ERROR and errno is set to indicate the error. * Some possible values for errno are: * * EACCES: a parent directory can't be read and/or written. * EISDIR: path is a directory. * ENOENT: path doesn't exist or is "". * * EACCES: exists an open file already referring to path. * EACCES: path is a char device (nul:, com1:, etc.) * * Side effects: * The file is deleted, even if it is read-only. * *--------------------------------------------------------------------------- */ int TclpObjDeleteFile( Tcl_Obj *pathPtr) { return TclpDeleteFile(Tcl_FSGetNativePath(pathPtr)); } int TclpDeleteFile( const void *nativePath) /* Pathname of file to be removed (native). */ { DWORD attr; const TCHAR *path = nativePath; /* * The DeleteFile API acts differently under Win95/98 and NT WRT NULL and * "". Avoid passing these values. */ if (path == NULL || path[0] == '\0') { Tcl_SetErrno(ENOENT); return TCL_ERROR; } if (DeleteFile(path) != FALSE) { return TCL_OK; } TclWinConvertError(GetLastError()); if (Tcl_GetErrno() == EACCES) { attr = GetFileAttributes(path); if (attr != 0xffffffff) { if (attr & FILE_ATTRIBUTE_DIRECTORY) { if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { /* * It is a symbolic link - remove it. */ if (TclWinSymLinkDelete(path, 0) == 0) { return TCL_OK; } } /* * If we fall through here, it is a directory. * * Windows NT reports removing a directory as EACCES instead * of EISDIR. */ Tcl_SetErrno(EISDIR); } else if (attr & FILE_ATTRIBUTE_READONLY) { int res = SetFileAttributes(path, attr & ~((DWORD) FILE_ATTRIBUTE_READONLY)); if ((res != 0) && (DeleteFile(path) != FALSE)) { return TCL_OK; } TclWinConvertError(GetLastError()); if (res != 0) { SetFileAttributes(path, attr); } } } } else if (Tcl_GetErrno() == ENOENT) { attr = GetFileAttributes(path); if (attr != 0xffffffff) { if (attr & FILE_ATTRIBUTE_DIRECTORY) { /* * Windows 95 reports removing a directory as ENOENT instead * of EISDIR. */ Tcl_SetErrno(EISDIR); } } } else if (Tcl_GetErrno() == EINVAL) { /* * Windows NT reports removing a char device as EINVAL instead of * EACCES. */ Tcl_SetErrno(EACCES); } return TCL_ERROR; } /* *--------------------------------------------------------------------------- * * TclpObjCreateDirectory -- * * Creates the specified directory. All parent directories of the * specified directory must already exist. The directory is automatically * created with permissions so that user can access the new directory and * create new files or subdirectories in it. * * Results: * If the directory was successfully created, returns TCL_OK. Otherwise * the return value is TCL_ERROR and errno is set to indicate the error. * Some possible values for errno are: * * EACCES: a parent directory can't be read and/or written. * EEXIST: path already exists. * ENOENT: a parent directory doesn't exist. * * Side effects: * A directory is created. * *--------------------------------------------------------------------------- */ int TclpObjCreateDirectory( Tcl_Obj *pathPtr) { return DoCreateDirectory(Tcl_FSGetNativePath(pathPtr)); } static int DoCreateDirectory( const TCHAR *nativePath) /* Pathname of directory to create (native). */ { if (CreateDirectory(nativePath, NULL) == 0) { DWORD error = GetLastError(); TclWinConvertError(error); return TCL_ERROR; } return TCL_OK; } /* *--------------------------------------------------------------------------- * * TclpObjCopyDirectory -- * * Recursively copies a directory. The target directory dst must not * already exist. Note that this function does not merge two directory * hierarchies, even if the target directory is an an empty directory. * * Results: * If the directory was successfully copied, returns TCL_OK. Otherwise * the return value is TCL_ERROR, errno is set to indicate the error, and * the pathname of the file that caused the error is stored in errorPtr. * See TclpCreateDirectory and TclpCopyFile for a description of possible * values for errno. * * Side effects: * An exact copy of the directory hierarchy src will be created with the * name dst. If an error occurs, the error will be returned immediately, * and remaining files will not be processed. * *--------------------------------------------------------------------------- */ int TclpObjCopyDirectory( Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr) { Tcl_DString ds; Tcl_DString srcString, dstString; Tcl_Obj *normSrcPtr, *normDestPtr; int ret; normSrcPtr = Tcl_FSGetNormalizedPath(NULL,srcPathPtr); normDestPtr = Tcl_FSGetNormalizedPath(NULL,destPathPtr); if ((normSrcPtr == NULL) || (normDestPtr == NULL)) { return TCL_ERROR; } Tcl_WinUtfToTChar(Tcl_GetString(normSrcPtr), -1, &srcString); Tcl_WinUtfToTChar(Tcl_GetString(normDestPtr), -1, &dstString); ret = TraverseWinTree(TraversalCopy, &srcString, &dstString, &ds); Tcl_DStringFree(&srcString); Tcl_DStringFree(&dstString); if (ret != TCL_OK) { if (!strcmp(Tcl_DStringValue(&ds), TclGetString(normSrcPtr))) { *errorPtr = srcPathPtr; } else if (!strcmp(Tcl_DStringValue(&ds), TclGetString(normDestPtr))) { *errorPtr = destPathPtr; } else { *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1); } Tcl_DStringFree(&ds); Tcl_IncrRefCount(*errorPtr); } return ret; } /* *---------------------------------------------------------------------- * * TclpObjRemoveDirectory, DoRemoveDirectory -- * * Removes directory (and its contents, if the recursive flag is set). * * Results: * If the directory was successfully removed, returns TCL_OK. Otherwise * the return value is TCL_ERROR, errno is set to indicate the error, and * the pathname of the file that caused the error is stored in errorPtr. * Some possible values for errno are: * * EACCES: path directory can't be read and/or written. * EEXIST: path is a non-empty directory. * EINVAL: path is root directory or current directory. * ENOENT: path doesn't exist or is "". * ENOTDIR: path is not a directory. * * EACCES: path is a char device (nul:, com1:, etc.) (95) * EINVAL: path is a char device (nul:, com1:, etc.) (NT) * * Side effects: * Directory removed. If an error occurs, the error will be returned * immediately, and remaining files will not be deleted. * *---------------------------------------------------------------------- */ int TclpObjRemoveDirectory( Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr) { Tcl_DString ds; Tcl_Obj *normPtr = NULL; int ret; if (recursive) { /* * In the recursive case, the string rep is used to construct a * Tcl_DString which may be used extensively, so we can't optimize * this case easily. */ Tcl_DString native; normPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (normPtr == NULL) { return TCL_ERROR; } Tcl_WinUtfToTChar(Tcl_GetString(normPtr), -1, &native); ret = DoRemoveDirectory(&native, recursive, &ds); Tcl_DStringFree(&native); } else { ret = DoRemoveJustDirectory(Tcl_FSGetNativePath(pathPtr), 0, &ds); } if (ret != TCL_OK) { if (Tcl_DStringLength(&ds) > 0) { if (normPtr != NULL && !strcmp(Tcl_DStringValue(&ds), TclGetString(normPtr))) { *errorPtr = pathPtr; } else { *errorPtr = TclDStringToObj(&ds); } Tcl_IncrRefCount(*errorPtr); } Tcl_DStringFree(&ds); } return ret; } static int DoRemoveJustDirectory( const TCHAR *nativePath, /* Pathname of directory to be removed * (native). */ int ignoreError, /* If non-zero, don't initialize the errorPtr * under some circumstances on return. */ Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free DString * filled with UTF-8 name of file causing * error. */ { DWORD attr; /* * The RemoveDirectory API acts differently under Win95/98 and NT WRT NULL * and "". Avoid passing these values. */ if (nativePath == NULL || nativePath[0] == '\0') { Tcl_SetErrno(ENOENT); goto end; } attr = GetFileAttributes(nativePath); if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { /* * It is a symbolic link - remove it. */ if (TclWinSymLinkDelete(nativePath, 0) == 0) { return TCL_OK; } } else { /* * Ordinary directory. */ if (RemoveDirectory(nativePath) != FALSE) { return TCL_OK; } } TclWinConvertError(GetLastError()); if (Tcl_GetErrno() == EACCES) { attr = GetFileAttributes(nativePath); if (attr != 0xffffffff) { if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { /* * Windows 95 reports calling RemoveDirectory on a file as an * EACCES, not an ENOTDIR. */ Tcl_SetErrno(ENOTDIR); goto end; } if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { /* * It is a symbolic link - remove it. */ if (TclWinSymLinkDelete(nativePath, 1) != 0) { goto end; } } if (attr & FILE_ATTRIBUTE_READONLY) { attr &= ~FILE_ATTRIBUTE_READONLY; if (SetFileAttributes(nativePath, attr) == FALSE) { goto end; } if (RemoveDirectory(nativePath) != FALSE) { return TCL_OK; } TclWinConvertError(GetLastError()); SetFileAttributes(nativePath, attr | FILE_ATTRIBUTE_READONLY); } } } if (Tcl_GetErrno() == ENOTEMPTY) { /* * The caller depends on EEXIST to signify that the directory is not * empty, not ENOTEMPTY. */ Tcl_SetErrno(EEXIST); } if ((ignoreError != 0) && (Tcl_GetErrno() == EEXIST)) { /* * If we're being recursive, this error may actually be ok, so we * don't want to initialise the errorPtr yet. */ return TCL_ERROR; } end: if (errorPtr != NULL) { char *p; Tcl_WinTCharToUtf(nativePath, -1, errorPtr); p = Tcl_DStringValue(errorPtr); for (; *p; ++p) { if (*p == '\\') *p = '/'; } } return TCL_ERROR; } static int DoRemoveDirectory( Tcl_DString *pathPtr, /* Pathname of directory to be removed * (native). */ int recursive, /* If non-zero, removes directories that are * nonempty. Otherwise, will only remove empty * directories. */ Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free DString * filled with UTF-8 name of file causing * error. */ { int res = DoRemoveJustDirectory((const TCHAR *)Tcl_DStringValue(pathPtr), recursive, errorPtr); if ((res == TCL_ERROR) && (recursive != 0) && (Tcl_GetErrno() == EEXIST)) { /* * The directory is nonempty, but the recursive flag has been * specified, so we recursively remove all the files in the directory. */ return TraverseWinTree(TraversalDelete, pathPtr, NULL, errorPtr); } else { return res; } } /* *--------------------------------------------------------------------------- * * TraverseWinTree -- * * Traverse directory tree specified by sourcePtr, calling the function * traverseProc for each file and directory encountered. If destPtr is * non-null, each of name in the sourcePtr directory is appended to the * directory specified by destPtr and passed as the second argument to * traverseProc(). * * Results: * Standard Tcl result. * * Side effects: * None caused by TraverseWinTree, however the user specified * traverseProc() may change state. If an error occurs, the error will be * returned immediately, and remaining files will not be processed. * *--------------------------------------------------------------------------- */ static int TraverseWinTree( TraversalProc *traverseProc,/* Function to call for every file and * directory in source hierarchy. */ Tcl_DString *sourcePtr, /* Pathname of source directory to be * traversed (native). */ Tcl_DString *targetPtr, /* Pathname of directory to traverse in * parallel with source directory (native), * may be NULL. */ Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free DString * filled with UTF-8 name of file causing * error. */ { DWORD sourceAttr; TCHAR *nativeSource, *nativeTarget, *nativeErrfile; int result, found, sourceLen, targetLen = 0, oldSourceLen, oldTargetLen; HANDLE handle; WIN32_FIND_DATA data; nativeErrfile = NULL; result = TCL_OK; oldTargetLen = 0; /* lint. */ nativeSource = (TCHAR *) Tcl_DStringValue(sourcePtr); nativeTarget = (TCHAR *) (targetPtr == NULL ? NULL : Tcl_DStringValue(targetPtr)); oldSourceLen = Tcl_DStringLength(sourcePtr); sourceAttr = GetFileAttributes(nativeSource); if (sourceAttr == 0xffffffff) { nativeErrfile = nativeSource; goto end; } if (sourceAttr & FILE_ATTRIBUTE_REPARSE_POINT) { /* * Process the symbolic link */ return traverseProc(nativeSource, nativeTarget, DOTREE_LINK, errorPtr); } if ((sourceAttr & FILE_ATTRIBUTE_DIRECTORY) == 0) { /* * Process the regular file */ return traverseProc(nativeSource, nativeTarget, DOTREE_F, errorPtr); } Tcl_DStringAppend(sourcePtr, (char *) TEXT("\\*.*"), 4 * sizeof(TCHAR) + 1); Tcl_DStringSetLength(sourcePtr, Tcl_DStringLength(sourcePtr) - 1); nativeSource = (TCHAR *) Tcl_DStringValue(sourcePtr); handle = FindFirstFile(nativeSource, &data); if (handle == INVALID_HANDLE_VALUE) { /* * Can't read directory. */ TclWinConvertError(GetLastError()); nativeErrfile = nativeSource; goto end; } Tcl_DStringSetLength(sourcePtr, oldSourceLen + 1); Tcl_DStringSetLength(sourcePtr, oldSourceLen); result = traverseProc(nativeSource, nativeTarget, DOTREE_PRED, errorPtr); if (result != TCL_OK) { FindClose(handle); return result; } sourceLen = oldSourceLen + sizeof(TCHAR); Tcl_DStringAppend(sourcePtr, (char *) TEXT("\\"), sizeof(TCHAR) + 1); Tcl_DStringSetLength(sourcePtr, sourceLen); if (targetPtr != NULL) { oldTargetLen = Tcl_DStringLength(targetPtr); targetLen = oldTargetLen; targetLen += sizeof(TCHAR); Tcl_DStringAppend(targetPtr, (char *) TEXT("\\"), sizeof(TCHAR) + 1); Tcl_DStringSetLength(targetPtr, targetLen); } found = 1; for (; found; found = FindNextFile(handle, &data)) { TCHAR *nativeName; int len; TCHAR *wp = data.cFileName; if (*wp == '.') { wp++; if (*wp == '.') { wp++; } if (*wp == '\0') { continue; } } nativeName = (TCHAR *) data.cFileName; len = _tcslen(data.cFileName) * sizeof(TCHAR); /* * Append name after slash, and recurse on the file. */ Tcl_DStringAppend(sourcePtr, (char *) nativeName, len + 1); Tcl_DStringSetLength(sourcePtr, Tcl_DStringLength(sourcePtr) - 1); if (targetPtr != NULL) { Tcl_DStringAppend(targetPtr, (char *) nativeName, len + 1); Tcl_DStringSetLength(targetPtr, Tcl_DStringLength(targetPtr) - 1); } result = TraverseWinTree(traverseProc, sourcePtr, targetPtr, errorPtr); if (result != TCL_OK) { break; } /* * Remove name after slash. */ Tcl_DStringSetLength(sourcePtr, sourceLen); if (targetPtr != NULL) { Tcl_DStringSetLength(targetPtr, targetLen); } } FindClose(handle); /* * Strip off the trailing slash we added. */ Tcl_DStringSetLength(sourcePtr, oldSourceLen + 1); Tcl_DStringSetLength(sourcePtr, oldSourceLen); if (targetPtr != NULL) { Tcl_DStringSetLength(targetPtr, oldTargetLen + 1); Tcl_DStringSetLength(targetPtr, oldTargetLen); } if (result == TCL_OK) { /* * Call traverseProc() on a directory after visiting all the * files in that directory. */ result = traverseProc((const TCHAR *)Tcl_DStringValue(sourcePtr), (const TCHAR *)(targetPtr == NULL ? NULL : Tcl_DStringValue(targetPtr)), DOTREE_POSTD, errorPtr); } end: if (nativeErrfile != NULL) { TclWinConvertError(GetLastError()); if (errorPtr != NULL) { Tcl_WinTCharToUtf(nativeErrfile, -1, errorPtr); } result = TCL_ERROR; } return result; } /* *---------------------------------------------------------------------- * * TraversalCopy * * Called from TraverseUnixTree in order to execute a recursive copy of a * directory. * * Results: * Standard Tcl result. * * Side effects: * Depending on the value of type, src may be copied to dst. * *---------------------------------------------------------------------- */ static int TraversalCopy( const TCHAR *nativeSrc, /* Source pathname to copy. */ const TCHAR *nativeDst, /* Destination pathname of copy. */ int type, /* Reason for call - see TraverseWinTree() */ Tcl_DString *errorPtr) /* If non-NULL, initialized DString filled * with UTF-8 name of file causing error. */ { switch (type) { case DOTREE_F: if (DoCopyFile(nativeSrc, nativeDst) == TCL_OK) { return TCL_OK; } break; case DOTREE_LINK: if (TclWinSymLinkCopyDirectory(nativeSrc, nativeDst) == TCL_OK) { return TCL_OK; } break; case DOTREE_PRED: if (DoCreateDirectory(nativeDst) == TCL_OK) { DWORD attr = GetFileAttributes(nativeSrc); if (SetFileAttributes(nativeDst, attr) != FALSE) { return TCL_OK; } TclWinConvertError(GetLastError()); } break; case DOTREE_POSTD: return TCL_OK; } /* * There shouldn't be a problem with src, because we already checked it to * get here. */ if (errorPtr != NULL) { Tcl_WinTCharToUtf(nativeDst, -1, errorPtr); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TraversalDelete -- * * Called by function TraverseWinTree for every file and directory that * it encounters in a directory hierarchy. This function unlinks files, * and removes directories after all the containing files have been * processed. * * Results: * Standard Tcl result. * * Side effects: * Files or directory specified by src will be deleted. If an error * occurs, the windows error is converted to a Posix error and errno is * set accordingly. * *---------------------------------------------------------------------- */ static int TraversalDelete( const TCHAR *nativeSrc, /* Source pathname to delete. */ const TCHAR *dstPtr, /* Not used. */ int type, /* Reason for call - see TraverseWinTree() */ Tcl_DString *errorPtr) /* If non-NULL, initialized DString filled * with UTF-8 name of file causing error. */ { switch (type) { case DOTREE_F: if (TclpDeleteFile(nativeSrc) == TCL_OK) { return TCL_OK; } break; case DOTREE_LINK: if (DoRemoveJustDirectory(nativeSrc, 0, NULL) == TCL_OK) { return TCL_OK; } break; case DOTREE_PRED: return TCL_OK; case DOTREE_POSTD: if (DoRemoveJustDirectory(nativeSrc, 0, NULL) == TCL_OK) { return TCL_OK; } break; } if (errorPtr != NULL) { Tcl_WinTCharToUtf(nativeSrc, -1, errorPtr); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * StatError -- * * Sets the object result with the appropriate error. * * Results: * None. * * Side effects: * The interp's object result is set with an error message based on the * objIndex, fileName and errno. * *---------------------------------------------------------------------- */ static void StatError( Tcl_Interp *interp, /* The interp that has the error */ Tcl_Obj *fileName) /* The name of the file which caused the * error. */ { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf("could not read \"%s\": %s", TclGetString(fileName), Tcl_PosixError(interp))); } /* *---------------------------------------------------------------------- * * GetWinFileAttributes -- * * Returns a Tcl_Obj containing the value of a file attribute. This * routine gets the -hidden, -readonly or -system attribute. * * Results: * Standard Tcl result and a Tcl_Obj in attributePtrPtr. The object will * have ref count 0. If the return value is not TCL_OK, attributePtrPtr * is not touched. * * Side effects: * A new object is allocated if the file is valid. * *---------------------------------------------------------------------- */ static int GetWinFileAttributes( Tcl_Interp *interp, /* The interp we are using for errors. */ int objIndex, /* The index of the attribute. */ Tcl_Obj *fileName, /* The name of the file. */ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */ { DWORD result; const TCHAR *nativeName; int attr; nativeName = Tcl_FSGetNativePath(fileName); result = GetFileAttributes(nativeName); if (result == 0xffffffff) { StatError(interp, fileName); return TCL_ERROR; } attr = (int)(result & attributeArray[objIndex]); if ((objIndex == WIN_HIDDEN_ATTRIBUTE) && (attr != 0)) { /* * It is hidden. However there is a bug on some Windows OSes in which * root volumes (drives) formatted as NTFS are declared hidden when * they are not (and cannot be). * * We test for, and fix that case, here. */ int len; const char *str = Tcl_GetStringFromObj(fileName,&len); if (len < 4) { if (len == 0) { /* * Not sure if this is possible, but we pass it on anyway. */ } else if (len == 1 && (str[0] == '/' || str[0] == '\\')) { /* * Path is pointing to the root volume. */ attr = 0; } else if ((str[1] == ':') && (len == 2 || (str[2] == '/' || str[2] == '\\'))) { /* * Path is of the form 'x:' or 'x:/' or 'x:\' */ attr = 0; } } } *attributePtrPtr = Tcl_NewBooleanObj(attr); return TCL_OK; } /* *---------------------------------------------------------------------- * * ConvertFileNameFormat -- * * Returns a Tcl_Obj containing either the long or short version of the * file name. * * Results: * Standard Tcl result and a Tcl_Obj in attributePtrPtr. The object will * have ref count 0. If the return value is not TCL_OK, attributePtrPtr * is not touched. * * Warning: if you pass this function a drive name like 'c:' it will * actually return the current working directory on that drive. To avoid * this, make sure the drive name ends in a slash, like this 'c:/'. * * Side effects: * A new object is allocated if the file is valid. * *---------------------------------------------------------------------- */ static int ConvertFileNameFormat( Tcl_Interp *interp, /* The interp we are using for errors. */ int objIndex, /* The index of the attribute. */ Tcl_Obj *fileName, /* The name of the file. */ int longShort, /* 0 to short name, 1 to long name. */ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */ { int pathc, i; Tcl_Obj *splitPath; splitPath = Tcl_FSSplitPath(fileName, &pathc); if (splitPath == NULL || pathc == 0) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not read \"%s\": no such file or directory", Tcl_GetString(fileName))); errno = ENOENT; Tcl_PosixError(interp); } goto cleanup; } /* * We will decrement this again at the end. It is safer to do this in * case any of the calls below retain a reference to splitPath. */ Tcl_IncrRefCount(splitPath); for (i = 0; i < pathc; i++) { Tcl_Obj *elt; char *pathv; int pathLen; Tcl_ListObjIndex(NULL, splitPath, i, &elt); pathv = Tcl_GetStringFromObj(elt, &pathLen); if ((pathv[0] == '/') || ((pathLen == 3) && (pathv[1] == ':')) || (strcmp(pathv, ".") == 0) || (strcmp(pathv, "..") == 0)) { /* * Handle "/", "//machine/export", "c:/", "." or ".." by just * copying the string literally. Uppercase the drive letter, just * because it looks better under Windows to do so. */ simple: /* * Here we are modifying the string representation in place. * * I believe this is legal, since this won't affect any file * representation this thing may have. */ pathv[0] = (char) Tcl_UniCharToUpper(UCHAR(pathv[0])); } else { Tcl_Obj *tempPath; Tcl_DString ds; Tcl_DString dsTemp; const TCHAR *nativeName; const char *tempString; int tempLen; WIN32_FIND_DATA data; HANDLE handle; DWORD attr; tempPath = Tcl_FSJoinPath(splitPath, i+1); Tcl_IncrRefCount(tempPath); /* * We'd like to call Tcl_FSGetNativePath(tempPath) but that is * likely to lead to infinite loops. */ Tcl_DStringInit(&ds); tempString = Tcl_GetStringFromObj(tempPath,&tempLen); nativeName = Tcl_WinUtfToTChar(tempString, tempLen, &ds); Tcl_DecrRefCount(tempPath); handle = FindFirstFile(nativeName, &data); if (handle == INVALID_HANDLE_VALUE) { /* * FindFirstFile() doesn't like root directories. We would * only get a root directory here if the caller specified "c:" * or "c:." and the current directory on the drive was the * root directory */ attr = GetFileAttributes(nativeName); if ((attr!=0xFFFFFFFF) && (attr & FILE_ATTRIBUTE_DIRECTORY)) { Tcl_DStringFree(&ds); goto simple; } } if (handle == INVALID_HANDLE_VALUE) { Tcl_DStringFree(&ds); if (interp != NULL) { StatError(interp, fileName); } goto cleanup; } nativeName = data.cAlternateFileName; if (longShort) { if (data.cFileName[0] != '\0') { nativeName = data.cFileName; } } else { if (data.cAlternateFileName[0] == '\0') { nativeName = (TCHAR *) data.cFileName; } } /* * Purify reports a extraneous UMR in Tcl_WinTCharToUtf() trying * to dereference nativeName as a Unicode string. I have proven to * myself that purify is wrong by running the following example * when nativeName == data.w.cAlternateFileName and noting that * purify doesn't complain about the first line, but does complain * about the second. * * fprintf(stderr, "%d\n", data.w.cAlternateFileName[0]); * fprintf(stderr, "%d\n", ((WCHAR *) nativeName)[0]); */ Tcl_DStringInit(&dsTemp); Tcl_WinTCharToUtf(nativeName, -1, &dsTemp); Tcl_DStringFree(&ds); /* * Deal with issues of tildes being absolute. */ if (Tcl_DStringValue(&dsTemp)[0] == '~') { TclNewLiteralStringObj(tempPath, "./"); Tcl_AppendToObj(tempPath, Tcl_DStringValue(&dsTemp), Tcl_DStringLength(&dsTemp)); Tcl_DStringFree(&dsTemp); } else { tempPath = TclDStringToObj(&dsTemp); } Tcl_ListObjReplace(NULL, splitPath, i, 1, 1, &tempPath); FindClose(handle); } } *attributePtrPtr = Tcl_FSJoinPath(splitPath, -1); if (splitPath != NULL) { /* * Unfortunately, the object we will return may have its only refCount * as part of the list splitPath. This means if we free splitPath, the * object will disappear. So, we have to be very careful here. * Unfortunately this means we must manipulate the object's refCount * directly. */ Tcl_IncrRefCount(*attributePtrPtr); Tcl_DecrRefCount(splitPath); --(*attributePtrPtr)->refCount; } return TCL_OK; cleanup: if (splitPath != NULL) { Tcl_DecrRefCount(splitPath); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * GetWinFileLongName -- * * Returns a Tcl_Obj containing the long version of the file name. * * Results: * Standard Tcl result and a Tcl_Obj in attributePtrPtr. The object will * have ref count 0. If the return value is not TCL_OK, attributePtrPtr * is not touched. * * Side effects: * A new object is allocated if the file is valid. * *---------------------------------------------------------------------- */ static int GetWinFileLongName( Tcl_Interp *interp, /* The interp we are using for errors. */ int objIndex, /* The index of the attribute. */ Tcl_Obj *fileName, /* The name of the file. */ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */ { return ConvertFileNameFormat(interp, objIndex, fileName, 1, attributePtrPtr); } /* *---------------------------------------------------------------------- * * GetWinFileShortName -- * * Returns a Tcl_Obj containing the short version of the file name. * * Results: * Standard Tcl result and a Tcl_Obj in attributePtrPtr. The object will * have ref count 0. If the return value is not TCL_OK, attributePtrPtr * is not touched. * * Side effects: * A new object is allocated if the file is valid. * *---------------------------------------------------------------------- */ static int GetWinFileShortName( Tcl_Interp *interp, /* The interp we are using for errors. */ int objIndex, /* The index of the attribute. */ Tcl_Obj *fileName, /* The name of the file. */ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */ { return ConvertFileNameFormat(interp, objIndex, fileName, 0, attributePtrPtr); } /* *---------------------------------------------------------------------- * * SetWinFileAttributes -- * * Set the file attributes to the value given by attributePtr. This * routine sets the -hidden, -readonly, or -system attributes. * * Results: * Standard TCL error. * * Side effects: * The file's attribute is set. * *---------------------------------------------------------------------- */ static int SetWinFileAttributes( Tcl_Interp *interp, /* The interp we are using for errors. */ int objIndex, /* The index of the attribute. */ Tcl_Obj *fileName, /* The name of the file. */ Tcl_Obj *attributePtr) /* The new value of the attribute. */ { DWORD fileAttributes, old; int yesNo, result; const TCHAR *nativeName; nativeName = Tcl_FSGetNativePath(fileName); fileAttributes = old = GetFileAttributes(nativeName); if (fileAttributes == 0xffffffff) { StatError(interp, fileName); return TCL_ERROR; } result = Tcl_GetBooleanFromObj(interp, attributePtr, &yesNo); if (result != TCL_OK) { return result; } if (yesNo) { fileAttributes |= (attributeArray[objIndex]); } else { fileAttributes &= ~(attributeArray[objIndex]); } if ((fileAttributes != old) && !SetFileAttributes(nativeName, fileAttributes)) { StatError(interp, fileName); return TCL_ERROR; } return result; } /* *---------------------------------------------------------------------- * * SetWinFileLongName -- * * The attribute in question is a readonly attribute and cannot be set. * * Results: * TCL_ERROR * * Side effects: * The object result is set to a pertinent error message. * *---------------------------------------------------------------------- */ static int CannotSetAttribute( Tcl_Interp *interp, /* The interp we are using for errors. */ int objIndex, /* The index of the attribute. */ Tcl_Obj *fileName, /* The name of the file. */ Tcl_Obj *attributePtr) /* The new value of the attribute. */ { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "cannot set attribute \"%s\" for file \"%s\": attribute is readonly", tclpFileAttrStrings[objIndex], Tcl_GetString(fileName))); errno = EINVAL; Tcl_PosixError(interp); return TCL_ERROR; } /* *--------------------------------------------------------------------------- * * TclpObjListVolumes -- * * Lists the currently mounted volumes * * Results: * The list of volumes. * * Side effects: * None * *--------------------------------------------------------------------------- */ Tcl_Obj * TclpObjListVolumes(void) { Tcl_Obj *resultPtr, *elemPtr; char buf[40 * 4]; /* There couldn't be more than 30 drives??? */ int i; char *p; resultPtr = Tcl_NewObj(); /* * On Win32s: * GetLogicalDriveStrings() isn't implemented. * GetLogicalDrives() returns incorrect information. */ if (GetLogicalDriveStringsA(sizeof(buf), buf) == 0) { /* * GetVolumeInformation() will detects all drives, but causes * chattering on empty floppy drives. We only do this if * GetLogicalDriveStrings() didn't work. It has also been reported * that on some laptops it takes a while for GetVolumeInformation() to * return when pinging an empty floppy drive, another reason to try to * avoid calling it. */ buf[1] = ':'; buf[2] = '/'; buf[3] = '\0'; for (i = 0; i < 26; i++) { buf[0] = (char) ('a' + i); if (GetVolumeInformationA(buf, NULL, 0, NULL, NULL, NULL, NULL, 0) || (GetLastError() == ERROR_NOT_READY)) { elemPtr = Tcl_NewStringObj(buf, -1); Tcl_ListObjAppendElement(NULL, resultPtr, elemPtr); } } } else { for (p = buf; *p != '\0'; p += 4) { p[2] = '/'; elemPtr = Tcl_NewStringObj(p, -1); Tcl_ListObjAppendElement(NULL, resultPtr, elemPtr); } } Tcl_IncrRefCount(resultPtr); return resultPtr; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tclWinPipe.c0000644000175000017500000024441112663660066014615 0ustar sergeisergei/* * tclWinPipe.c -- * * This file implements the Windows-specific exec pipeline functions, the * "pipe" channel driver, and the "pid" Tcl command. * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclWinInt.h" /* * The following variable is used to tell whether this module has been * initialized. */ static int initialized = 0; /* * The pipeMutex locks around access to the initialized and procList * variables, and it is used to protect background threads from being * terminated while they are using APIs that hold locks. */ TCL_DECLARE_MUTEX(pipeMutex) /* * The following defines identify the various types of applications that run * under windows. There is special case code for the various types. */ #define APPL_NONE 0 #define APPL_DOS 1 #define APPL_WIN3X 2 #define APPL_WIN32 3 /* * The following constants and structures are used to encapsulate the state of * various types of files used in a pipeline. This used to have a 1 && 2 that * supported Win32s. */ #define WIN_FILE 3 /* Basic Win32 file. */ /* * This structure encapsulates the common state associated with all file types * used in a pipeline. */ typedef struct { int type; /* One of the file types defined above. */ HANDLE handle; /* Open file handle. */ } WinFile; /* * This list is used to map from pids to process handles. */ typedef struct ProcInfo { HANDLE hProcess; DWORD dwProcessId; struct ProcInfo *nextPtr; } ProcInfo; static ProcInfo *procList; /* * Bit masks used in the flags field of the PipeInfo structure below. */ #define PIPE_PENDING (1<<0) /* Message is pending in the queue. */ #define PIPE_ASYNC (1<<1) /* Channel is non-blocking. */ /* * Bit masks used in the sharedFlags field of the PipeInfo structure below. */ #define PIPE_EOF (1<<2) /* Pipe has reached EOF. */ #define PIPE_EXTRABYTE (1<<3) /* The reader thread has consumed one byte. */ /* * TODO: It appears the whole EXTRABYTE machinery is in place to support * outdated Win 95 systems. If this can be confirmed, much code can be * deleted. */ /* * This structure describes per-instance data for a pipe based channel. */ typedef struct PipeInfo { struct PipeInfo *nextPtr; /* Pointer to next registered pipe. */ Tcl_Channel channel; /* Pointer to channel structure. */ int validMask; /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which operations are valid on the file. */ int watchMask; /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which events should be reported. */ int flags; /* State flags, see above for a list. */ TclFile readFile; /* Output from pipe. */ TclFile writeFile; /* Input from pipe. */ TclFile errorFile; /* Error output from pipe. */ int numPids; /* Number of processes attached to pipe. */ Tcl_Pid *pidPtr; /* Pids of attached processes. */ Tcl_ThreadId threadId; /* Thread to which events should be reported. * This value is used by the reader/writer * threads. */ HANDLE writeThread; /* Handle to writer thread. */ HANDLE readThread; /* Handle to reader thread. */ HANDLE writable; /* Manual-reset event to signal when the * writer thread has finished waiting for the * current buffer to be written. */ HANDLE readable; /* Manual-reset event to signal when the * reader thread has finished waiting for * input. */ HANDLE startWriter; /* Auto-reset event used by the main thread to * signal when the writer thread should * attempt to write to the pipe. */ HANDLE stopWriter; /* Manual-reset event used to alert the reader * thread to fall-out and exit */ HANDLE startReader; /* Auto-reset event used by the main thread to * signal when the reader thread should * attempt to read from the pipe. */ HANDLE stopReader; /* Manual-reset event used to alert the reader * thread to fall-out and exit */ DWORD writeError; /* An error caused by the last background * write. Set to 0 if no error has been * detected. This word is shared with the * writer thread so access must be * synchronized with the writable object. */ char *writeBuf; /* Current background output buffer. Access is * synchronized with the writable object. */ int writeBufLen; /* Size of write buffer. Access is * synchronized with the writable object. */ int toWrite; /* Current amount to be written. Access is * synchronized with the writable object. */ int readFlags; /* Flags that are shared with the reader * thread. Access is synchronized with the * readable object. */ char extraByte; /* Buffer for extra character consumed by * reader thread. This byte is shared with the * reader thread so access must be * synchronized with the readable object. */ } PipeInfo; typedef struct { /* * The following pointer refers to the head of the list of pipes that are * being watched for file events. */ PipeInfo *firstPipePtr; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * The following structure is what is added to the Tcl event queue when pipe * events are generated. */ typedef struct { Tcl_Event header; /* Information that is standard for all * events. */ PipeInfo *infoPtr; /* Pointer to pipe info structure. Note that * we still have to verify that the pipe * exists before dereferencing this * pointer. */ } PipeEvent; /* * Declarations for functions used only in this file. */ static int ApplicationType(Tcl_Interp *interp, const char *fileName, char *fullName); static void BuildCommandLine(const char *executable, int argc, const char **argv, Tcl_DString *linePtr); static BOOL HasConsole(void); static int PipeBlockModeProc(ClientData instanceData, int mode); static void PipeCheckProc(ClientData clientData, int flags); static int PipeClose2Proc(ClientData instanceData, Tcl_Interp *interp, int flags); static int PipeEventProc(Tcl_Event *evPtr, int flags); static int PipeGetHandleProc(ClientData instanceData, int direction, ClientData *handlePtr); static void PipeInit(void); static int PipeInputProc(ClientData instanceData, char *buf, int toRead, int *errorCode); static int PipeOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCode); static DWORD WINAPI PipeReaderThread(LPVOID arg); static void PipeSetupProc(ClientData clientData, int flags); static void PipeWatchProc(ClientData instanceData, int mask); static DWORD WINAPI PipeWriterThread(LPVOID arg); static int TempFileName(TCHAR name[MAX_PATH]); static int WaitForRead(PipeInfo *infoPtr, int blocking); static void PipeThreadActionProc(ClientData instanceData, int action); /* * This structure describes the channel type structure for command pipe based * I/O. */ static const Tcl_ChannelType pipeChannelType = { "pipe", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ TCL_CLOSE2PROC, /* Close proc. */ PipeInputProc, /* Input proc. */ PipeOutputProc, /* Output proc. */ NULL, /* Seek proc. */ NULL, /* Set option proc. */ NULL, /* Get option proc. */ PipeWatchProc, /* Set up notifier to watch the channel. */ PipeGetHandleProc, /* Get an OS handle from channel. */ PipeClose2Proc, /* close2proc */ PipeBlockModeProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ NULL, /* wide seek proc */ PipeThreadActionProc, /* thread action proc */ NULL /* truncate */ }; /* *---------------------------------------------------------------------- * * PipeInit -- * * This function initializes the static variables for this file. * * Results: * None. * * Side effects: * Creates a new event source. * *---------------------------------------------------------------------- */ static void PipeInit(void) { ThreadSpecificData *tsdPtr; /* * Check the initialized flag first, then check again in the mutex. This * is a speed enhancement. */ if (!initialized) { Tcl_MutexLock(&pipeMutex); if (!initialized) { initialized = 1; procList = NULL; } Tcl_MutexUnlock(&pipeMutex); } tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey); if (tsdPtr == NULL) { tsdPtr = TCL_TSD_INIT(&dataKey); tsdPtr->firstPipePtr = NULL; Tcl_CreateEventSource(PipeSetupProc, PipeCheckProc, NULL); } } /* *---------------------------------------------------------------------- * * TclpFinalizePipes -- * * This function is called from Tcl_FinalizeThread to finalize the * platform specific pipe subsystem. * * Results: * None. * * Side effects: * Removes the pipe event source. * *---------------------------------------------------------------------- */ void TclpFinalizePipes(void) { ThreadSpecificData *tsdPtr; tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey); if (tsdPtr != NULL) { Tcl_DeleteEventSource(PipeSetupProc, PipeCheckProc, NULL); } } /* *---------------------------------------------------------------------- * * PipeSetupProc -- * * This function is invoked before Tcl_DoOneEvent blocks waiting for an * event. * * Results: * None. * * Side effects: * Adjusts the block time if needed. * *---------------------------------------------------------------------- */ void PipeSetupProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { PipeInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; int block = 1; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } /* * Look to see if any events are already pending. If they are, poll. */ for (infoPtr = tsdPtr->firstPipePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->watchMask & TCL_WRITABLE) { if (WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT) { block = 0; } } if (infoPtr->watchMask & TCL_READABLE) { if (WaitForRead(infoPtr, 0) >= 0) { block = 0; } } } if (!block) { Tcl_SetMaxBlockTime(&blockTime); } } /* *---------------------------------------------------------------------- * * PipeCheckProc -- * * This function is called by Tcl_DoOneEvent to check the pipe event * source for events. * * Results: * None. * * Side effects: * May queue an event. * *---------------------------------------------------------------------- */ static void PipeCheckProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { PipeInfo *infoPtr; PipeEvent *evPtr; int needEvent; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } /* * Queue events for any ready pipes that don't already have events queued. */ for (infoPtr = tsdPtr->firstPipePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->flags & PIPE_PENDING) { continue; } /* * Queue an event if the pipe is signaled for reading or writing. */ needEvent = 0; if ((infoPtr->watchMask & TCL_WRITABLE) && (WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT)) { needEvent = 1; } if ((infoPtr->watchMask & TCL_READABLE) && (WaitForRead(infoPtr, 0) >= 0)) { needEvent = 1; } if (needEvent) { infoPtr->flags |= PIPE_PENDING; evPtr = ckalloc(sizeof(PipeEvent)); evPtr->header.proc = PipeEventProc; evPtr->infoPtr = infoPtr; Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL); } } } /* *---------------------------------------------------------------------- * * TclWinMakeFile -- * * This function constructs a new TclFile from a given data and type * value. * * Results: * Returns a newly allocated WinFile as a TclFile. * * Side effects: * None. * *---------------------------------------------------------------------- */ TclFile TclWinMakeFile( HANDLE handle) /* Type-specific data. */ { WinFile *filePtr; filePtr = ckalloc(sizeof(WinFile)); filePtr->type = WIN_FILE; filePtr->handle = handle; return (TclFile)filePtr; } /* *---------------------------------------------------------------------- * * TempFileName -- * * Gets a temporary file name and deals with the fact that the temporary * file path provided by Windows may not actually exist if the TMP or * TEMP environment variables refer to a non-existent directory. * * Results: * 0 if error, non-zero otherwise. If non-zero is returned, the name * buffer will be filled with a name that can be used to construct a * temporary file. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TempFileName( TCHAR name[MAX_PATH]) /* Buffer in which name for temporary file * gets stored. */ { const TCHAR *prefix = TEXT("TCL"); if (GetTempPath(MAX_PATH, name) != 0) { if (GetTempFileName(name, prefix, 0, name) != 0) { return 1; } } name[0] = '.'; name[1] = '\0'; return GetTempFileName(name, prefix, 0, name); } /* *---------------------------------------------------------------------- * * TclpMakeFile -- * * Make a TclFile from a channel. * * Results: * Returns a new TclFile or NULL on failure. * * Side effects: * None. * *---------------------------------------------------------------------- */ TclFile TclpMakeFile( Tcl_Channel channel, /* Channel to get file from. */ int direction) /* Either TCL_READABLE or TCL_WRITABLE. */ { HANDLE handle; if (Tcl_GetChannelHandle(channel, direction, (ClientData *) &handle) == TCL_OK) { return TclWinMakeFile(handle); } else { return (TclFile) NULL; } } /* *---------------------------------------------------------------------- * * TclpOpenFile -- * * This function opens files for use in a pipeline. * * Results: * Returns a newly allocated TclFile structure containing the file * handle. * * Side effects: * None. * *---------------------------------------------------------------------- */ TclFile TclpOpenFile( const char *path, /* The name of the file to open. */ int mode) /* In what mode to open the file? */ { HANDLE handle; DWORD accessMode, createMode, shareMode, flags; Tcl_DString ds; const TCHAR *nativePath; /* * Map the access bits to the NT access mode. */ switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) { case O_RDONLY: accessMode = GENERIC_READ; break; case O_WRONLY: accessMode = GENERIC_WRITE; break; case O_RDWR: accessMode = (GENERIC_READ | GENERIC_WRITE); break; default: TclWinConvertError(ERROR_INVALID_FUNCTION); return NULL; } /* * Map the creation flags to the NT create mode. */ switch (mode & (O_CREAT | O_EXCL | O_TRUNC)) { case (O_CREAT | O_EXCL): case (O_CREAT | O_EXCL | O_TRUNC): createMode = CREATE_NEW; break; case (O_CREAT | O_TRUNC): createMode = CREATE_ALWAYS; break; case O_CREAT: createMode = OPEN_ALWAYS; break; case O_TRUNC: case (O_TRUNC | O_EXCL): createMode = TRUNCATE_EXISTING; break; default: createMode = OPEN_EXISTING; break; } nativePath = Tcl_WinUtfToTChar(path, -1, &ds); /* * If the file is not being created, use the existing file attributes. */ flags = 0; if (!(mode & O_CREAT)) { flags = GetFileAttributes(nativePath); if (flags == 0xFFFFFFFF) { flags = 0; } } /* * Set up the file sharing mode. We want to allow simultaneous access. */ shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; /* * Now we get to create the file. */ handle = CreateFile(nativePath, accessMode, shareMode, NULL, createMode, flags, NULL); Tcl_DStringFree(&ds); if (handle == INVALID_HANDLE_VALUE) { DWORD err; err = GetLastError(); if ((err & 0xffffL) == ERROR_OPEN_FAILED) { err = (mode & O_CREAT) ? ERROR_FILE_EXISTS : ERROR_FILE_NOT_FOUND; } TclWinConvertError(err); return NULL; } /* * Seek to the end of file if we are writing. */ if (mode & (O_WRONLY|O_APPEND)) { SetFilePointer(handle, 0, NULL, FILE_END); } return TclWinMakeFile(handle); } /* *---------------------------------------------------------------------- * * TclpCreateTempFile -- * * This function opens a unique file with the property that it will be * deleted when its file handle is closed. The temporary file is created * in the system temporary directory. * * Results: * Returns a valid TclFile, or NULL on failure. * * Side effects: * Creates a new temporary file. * *---------------------------------------------------------------------- */ TclFile TclpCreateTempFile( const char *contents) /* String to write into temp file, or NULL. */ { TCHAR name[MAX_PATH]; const char *native; Tcl_DString dstring; HANDLE handle; if (TempFileName(name) == 0) { return NULL; } handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE, NULL); if (handle == INVALID_HANDLE_VALUE) { goto error; } /* * Write the file out, doing line translations on the way. */ if (contents != NULL) { DWORD result, length; const char *p; int toCopy; /* * Convert the contents from UTF to native encoding */ native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring); toCopy = Tcl_DStringLength(&dstring); for (p = native; toCopy > 0; p++, toCopy--) { if (*p == '\n') { length = p - native; if (length > 0) { if (!WriteFile(handle, native, length, &result, NULL)) { goto error; } } if (!WriteFile(handle, "\r\n", 2, &result, NULL)) { goto error; } native = p+1; } } length = p - native; if (length > 0) { if (!WriteFile(handle, native, length, &result, NULL)) { goto error; } } Tcl_DStringFree(&dstring); if (SetFilePointer(handle, 0, NULL, FILE_BEGIN) == 0xFFFFFFFF) { goto error; } } return TclWinMakeFile(handle); error: /* * Free the native representation of the contents if necessary. */ if (contents != NULL) { Tcl_DStringFree(&dstring); } TclWinConvertError(GetLastError()); CloseHandle(handle); DeleteFile(name); return NULL; } /* *---------------------------------------------------------------------- * * TclpTempFileName -- * * This function returns a unique filename. * * Results: * Returns a valid Tcl_Obj* with refCount 0, or NULL on failure. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * TclpTempFileName(void) { TCHAR fileName[MAX_PATH]; if (TempFileName(fileName) == 0) { return NULL; } return TclpNativeToNormalized(fileName); } /* *---------------------------------------------------------------------- * * TclpCreatePipe -- * * Creates an anonymous pipe. * * Results: * Returns 1 on success, 0 on failure. * * Side effects: * Creates a pipe. * *---------------------------------------------------------------------- */ int TclpCreatePipe( TclFile *readPipe, /* Location to store file handle for read side * of pipe. */ TclFile *writePipe) /* Location to store file handle for write * side of pipe. */ { HANDLE readHandle, writeHandle; if (CreatePipe(&readHandle, &writeHandle, NULL, 0) != 0) { *readPipe = TclWinMakeFile(readHandle); *writePipe = TclWinMakeFile(writeHandle); return 1; } TclWinConvertError(GetLastError()); return 0; } /* *---------------------------------------------------------------------- * * TclpCloseFile -- * * Closes a pipeline file handle. These handles are created by * TclpOpenFile, TclpCreatePipe, or TclpMakeFile. * * Results: * 0 on success, -1 on failure. * * Side effects: * The file is closed and deallocated. * *---------------------------------------------------------------------- */ int TclpCloseFile( TclFile file) /* The file to close. */ { WinFile *filePtr = (WinFile *) file; switch (filePtr->type) { case WIN_FILE: /* * Don't close the Win32 handle if the handle is a standard channel * during the thread exit process. Otherwise, one thread may kill the * stdio of another. */ if (!TclInThreadExit() || ((GetStdHandle(STD_INPUT_HANDLE) != filePtr->handle) && (GetStdHandle(STD_OUTPUT_HANDLE) != filePtr->handle) && (GetStdHandle(STD_ERROR_HANDLE) != filePtr->handle))) { if (filePtr->handle != NULL && CloseHandle(filePtr->handle) == FALSE) { TclWinConvertError(GetLastError()); ckfree(filePtr); return -1; } } break; default: Tcl_Panic("TclpCloseFile: unexpected file type"); } ckfree(filePtr); return 0; } /* *-------------------------------------------------------------------------- * * TclpGetPid -- * * Given a HANDLE to a child process, return the process id for that * child process. * * Results: * Returns the process id for the child process. If the pid was not known * by Tcl, either because the pid was not created by Tcl or the child * process has already been reaped, -1 is returned. * * Side effects: * None. * *-------------------------------------------------------------------------- */ int TclpGetPid( Tcl_Pid pid) /* The HANDLE of the child process. */ { ProcInfo *infoPtr; PipeInit(); Tcl_MutexLock(&pipeMutex); for (infoPtr = procList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->hProcess == (HANDLE) pid) { Tcl_MutexUnlock(&pipeMutex); return infoPtr->dwProcessId; } } Tcl_MutexUnlock(&pipeMutex); return (unsigned long) -1; } /* *---------------------------------------------------------------------- * * TclpCreateProcess -- * * Create a child process that has the specified files as its standard * input, output, and error. The child process runs asynchronously under * Windows NT and Windows 9x, and runs with the same environment * variables as the creating process. * * The complete Windows search path is searched to find the specified * executable. If an executable by the given name is not found, * automatically tries appending ".com", ".exe", and ".bat" to the * executable name. * * Results: * The return value is TCL_ERROR and an error message is left in the * interp's result if there was a problem creating the child process. * Otherwise, the return value is TCL_OK and *pidPtr is filled with the * process id of the child process. * * Side effects: * A process is created. * *---------------------------------------------------------------------- */ int TclpCreateProcess( Tcl_Interp *interp, /* Interpreter in which to leave errors that * occurred when creating the child process. * Error messages from the child process * itself are sent to errorFile. */ int argc, /* Number of arguments in following array. */ const char **argv, /* Array of argument strings. argv[0] contains * the name of the executable converted to * native format (using the * Tcl_TranslateFileName call). Additional * arguments have not been converted. */ TclFile inputFile, /* If non-NULL, gives the file to use as input * for the child process. If inputFile file is * not readable or is NULL, the child will * receive no standard input. */ TclFile outputFile, /* If non-NULL, gives the file that receives * output from the child process. If * outputFile file is not writeable or is * NULL, output from the child will be * discarded. */ TclFile errorFile, /* If non-NULL, gives the file that receives * errors from the child process. If errorFile * file is not writeable or is NULL, errors * from the child will be discarded. errorFile * may be the same as outputFile. */ Tcl_Pid *pidPtr) /* If this function is successful, pidPtr is * filled with the process id of the child * process. */ { int result, applType, createFlags; Tcl_DString cmdLine; /* Complete command line (TCHAR). */ STARTUPINFO startInfo; PROCESS_INFORMATION procInfo; SECURITY_ATTRIBUTES secAtts; HANDLE hProcess, h, inputHandle, outputHandle, errorHandle; char execPath[MAX_PATH * TCL_UTF_MAX]; WinFile *filePtr; PipeInit(); applType = ApplicationType(interp, argv[0], execPath); if (applType == APPL_NONE) { return TCL_ERROR; } result = TCL_ERROR; Tcl_DStringInit(&cmdLine); hProcess = GetCurrentProcess(); /* * STARTF_USESTDHANDLES must be used to pass handles to child process. * Using SetStdHandle() and/or dup2() only works when a console mode * parent process is spawning an attached console mode child process. */ ZeroMemory(&startInfo, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); startInfo.dwFlags = STARTF_USESTDHANDLES; startInfo.hStdInput = INVALID_HANDLE_VALUE; startInfo.hStdOutput= INVALID_HANDLE_VALUE; startInfo.hStdError = INVALID_HANDLE_VALUE; secAtts.nLength = sizeof(SECURITY_ATTRIBUTES); secAtts.lpSecurityDescriptor = NULL; secAtts.bInheritHandle = TRUE; /* * We have to check the type of each file, since we cannot duplicate some * file types. */ inputHandle = INVALID_HANDLE_VALUE; if (inputFile != NULL) { filePtr = (WinFile *)inputFile; if (filePtr->type == WIN_FILE) { inputHandle = filePtr->handle; } } outputHandle = INVALID_HANDLE_VALUE; if (outputFile != NULL) { filePtr = (WinFile *)outputFile; if (filePtr->type == WIN_FILE) { outputHandle = filePtr->handle; } } errorHandle = INVALID_HANDLE_VALUE; if (errorFile != NULL) { filePtr = (WinFile *)errorFile; if (filePtr->type == WIN_FILE) { errorHandle = filePtr->handle; } } /* * Duplicate all the handles which will be passed off as stdin, stdout and * stderr of the child process. The duplicate handles are set to be * inheritable, so the child process can use them. */ if (inputHandle == INVALID_HANDLE_VALUE) { /* * If handle was not set, stdin should return immediate EOF. Under * Windows95, some applications (both 16 and 32 bit!) cannot read from * the NUL device; they read from console instead. When running tk, * this is fatal because the child process would hang forever waiting * for EOF from the unmapped console window used by the helper * application. * * Fortunately, the helper application detects a closed pipe as an * immediate EOF and can pass that information to the child process. */ if (CreatePipe(&startInfo.hStdInput, &h, &secAtts, 0) != FALSE) { CloseHandle(h); } } else { DuplicateHandle(hProcess, inputHandle, hProcess, &startInfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS); } if (startInfo.hStdInput == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't duplicate input handle: %s", Tcl_PosixError(interp))); goto end; } if (outputHandle == INVALID_HANDLE_VALUE) { /* * If handle was not set, output should be sent to an infinitely deep * sink. Under Windows 95, some 16 bit applications cannot have stdout * redirected to NUL; they send their output to the console instead. * Some applications, like "more" or "dir /p", when outputting * multiple pages to the console, also then try and read from the * console to go the next page. When running tk, this is fatal because * the child process would hang forever waiting for input from the * unmapped console window used by the helper application. * * Fortunately, the helper application will detect a closed pipe as a * sink. */ startInfo.hStdOutput = CreateFile(TEXT("NUL:"), GENERIC_WRITE, 0, &secAtts, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); } else { DuplicateHandle(hProcess, outputHandle, hProcess, &startInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); } if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't duplicate output handle: %s", Tcl_PosixError(interp))); goto end; } if (errorHandle == INVALID_HANDLE_VALUE) { /* * If handle was not set, errors should be sent to an infinitely deep * sink. */ startInfo.hStdError = CreateFile(TEXT("NUL:"), GENERIC_WRITE, 0, &secAtts, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } else { DuplicateHandle(hProcess, errorHandle, hProcess, &startInfo.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS); } if (startInfo.hStdError == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't duplicate error handle: %s", Tcl_PosixError(interp))); goto end; } /* * If we do not have a console window, then we must run DOS and WIN32 * console mode applications as detached processes. This tells the loader * that the child application should not inherit the console, and that it * should not create a new console window for the child application. The * child application should get its stdio from the redirection handles * provided by this application, and run in the background. * * If we are starting a GUI process, they don't automatically get a * console, so it doesn't matter if they are started as foreground or * detached processes. The GUI window will still pop up to the foreground. */ if (TclWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { if (HasConsole()) { createFlags = 0; } else if (applType == APPL_DOS) { /* * Under NT, 16-bit DOS applications will not run unless they can * be attached to a console. If we are running without a console, * run the 16-bit program as an normal process inside of a hidden * console application, and then run that hidden console as a * detached process. */ startInfo.wShowWindow = SW_HIDE; startInfo.dwFlags |= STARTF_USESHOWWINDOW; createFlags = CREATE_NEW_CONSOLE; TclDStringAppendLiteral(&cmdLine, "cmd.exe /c"); } else { createFlags = DETACHED_PROCESS; } } else { if (HasConsole()) { createFlags = 0; } else { createFlags = DETACHED_PROCESS; } if (applType == APPL_DOS) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "DOS application process not supported on this platform", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "DOS_APP", NULL); goto end; } } /* * cmdLine gets the full command line used to invoke the executable, * including the name of the executable itself. The command line arguments * in argv[] are stored in cmdLine separated by spaces. Special characters * in individual arguments from argv[] must be quoted when being stored in * cmdLine. * * When calling any application, bear in mind that arguments that specify * a path name are not converted. If an argument contains forward slashes * as path separators, it may or may not be recognized as a path name, * depending on the program. In general, most applications accept forward * slashes only as option delimiters and backslashes only as paths. * * Additionally, when calling a 16-bit dos or windows application, all * path names must use the short, cryptic, path format (e.g., using * ab~1.def instead of "a b.default"). */ BuildCommandLine(execPath, argc, argv, &cmdLine); if (CreateProcess(NULL, (TCHAR *) Tcl_DStringValue(&cmdLine), NULL, NULL, TRUE, (DWORD) createFlags, NULL, NULL, &startInfo, &procInfo) == 0) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf("couldn't execute \"%s\": %s", argv[0], Tcl_PosixError(interp))); goto end; } /* * This wait is used to force the OS to give some time to the DOS process. */ if (applType == APPL_DOS) { WaitForSingleObject(procInfo.hProcess, 50); } /* * "When an application spawns a process repeatedly, a new thread instance * will be created for each process but the previous instances may not be * cleaned up. This results in a significant virtual memory loss each time * the process is spawned. If there is a WaitForInputIdle() call between * CreateProcess() and CloseHandle(), the problem does not occur." PSS ID * Number: Q124121 */ WaitForInputIdle(procInfo.hProcess, 5000); CloseHandle(procInfo.hThread); *pidPtr = (Tcl_Pid) procInfo.hProcess; if (*pidPtr != 0) { TclWinAddProcess(procInfo.hProcess, procInfo.dwProcessId); } result = TCL_OK; end: Tcl_DStringFree(&cmdLine); if (startInfo.hStdInput != INVALID_HANDLE_VALUE) { CloseHandle(startInfo.hStdInput); } if (startInfo.hStdOutput != INVALID_HANDLE_VALUE) { CloseHandle(startInfo.hStdOutput); } if (startInfo.hStdError != INVALID_HANDLE_VALUE) { CloseHandle(startInfo.hStdError); } return result; } /* *---------------------------------------------------------------------- * * HasConsole -- * * Determines whether the current application is attached to a console. * * Results: * Returns TRUE if this application has a console, else FALSE. * * Side effects: * None. * *---------------------------------------------------------------------- */ static BOOL HasConsole(void) { HANDLE handle; handle = CreateFileA("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (handle != INVALID_HANDLE_VALUE) { CloseHandle(handle); return TRUE; } else { return FALSE; } } /* *-------------------------------------------------------------------- * * ApplicationType -- * * Search for the specified program and identify if it refers to a DOS, * Windows 3.X, or Win32 program. Used to determine how to invoke a * program, or if it can even be invoked. * * It is possible to almost positively identify DOS and Windows * applications that contain the appropriate magic numbers. However, DOS * .com files do not seem to contain a magic number; if the program name * ends with .com and could not be identified as a Windows .com file, it * will be assumed to be a DOS application, even if it was just random * data. If the program name does not end with .com, no such assumption * is made. * * The Win32 function GetBinaryType incorrectly identifies any junk file * that ends with .exe as a dos executable and some executables that * don't end with .exe as not executable. Plus it doesn't exist under * win95, so I won't feel bad about reimplementing functionality. * * Results: * The return value is one of APPL_DOS, APPL_WIN3X, or APPL_WIN32 if the * filename referred to the corresponding application type. If the file * name could not be found or did not refer to any known application * type, APPL_NONE is returned and an error message is left in interp. * .bat files are identified as APPL_DOS. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ApplicationType( Tcl_Interp *interp, /* Interp, for error message. */ const char *originalName, /* Name of the application to find. */ char fullName[]) /* Filled with complete path to * application. */ { int applType, i, nameLen, found; HANDLE hFile; TCHAR *rest; char *ext; char buf[2]; DWORD attr, read; IMAGE_DOS_HEADER header; Tcl_DString nameBuf, ds; const TCHAR *nativeName; TCHAR nativeFullPath[MAX_PATH]; static const char extensions[][5] = {"", ".com", ".exe", ".bat"}; /* * Look for the program as an external program. First try the name as it * is, then try adding .com, .exe, and .bat, in that order, to the name, * looking for an executable. * * Using the raw SearchPath() function doesn't do quite what is necessary. * If the name of the executable already contains a '.' character, it will * not try appending the specified extension when searching (in other * words, SearchPath will not find the program "a.b.exe" if the arguments * specified "a.b" and ".exe"). So, first look for the file as it is * named. Then manually append the extensions, looking for a match. */ applType = APPL_NONE; Tcl_DStringInit(&nameBuf); Tcl_DStringAppend(&nameBuf, originalName, -1); nameLen = Tcl_DStringLength(&nameBuf); for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) { Tcl_DStringSetLength(&nameBuf, nameLen); Tcl_DStringAppend(&nameBuf, extensions[i], -1); nativeName = Tcl_WinUtfToTChar(Tcl_DStringValue(&nameBuf), Tcl_DStringLength(&nameBuf), &ds); found = SearchPath(NULL, nativeName, NULL, MAX_PATH, nativeFullPath, &rest); Tcl_DStringFree(&ds); if (found == 0) { continue; } /* * Ignore matches on directories or data files, return if identified a * known type. */ attr = GetFileAttributes(nativeFullPath); if ((attr == 0xffffffff) || (attr & FILE_ATTRIBUTE_DIRECTORY)) { continue; } strcpy(fullName, Tcl_WinTCharToUtf(nativeFullPath, -1, &ds)); Tcl_DStringFree(&ds); ext = strrchr(fullName, '.'); if ((ext != NULL) && (strcasecmp(ext, ".bat") == 0)) { applType = APPL_DOS; break; } hFile = CreateFile(nativeFullPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { continue; } header.e_magic = 0; ReadFile(hFile, (void *) &header, sizeof(header), &read, NULL); if (header.e_magic != IMAGE_DOS_SIGNATURE) { /* * Doesn't have the magic number for relocatable executables. If * filename ends with .com, assume it's a DOS application anyhow. * Note that we didn't make this assumption at first, because some * supposed .com files are really 32-bit executables with all the * magic numbers and everything. */ CloseHandle(hFile); if ((ext != NULL) && (strcasecmp(ext, ".com") == 0)) { applType = APPL_DOS; break; } continue; } if (header.e_lfarlc != sizeof(header)) { /* * All Windows 3.X and Win32 and some DOS programs have this value * set here. If it doesn't, assume that since it already had the * other magic number it was a DOS application. */ CloseHandle(hFile); applType = APPL_DOS; break; } /* * The DWORD at header.e_lfanew points to yet another magic number. */ buf[0] = '\0'; SetFilePointer(hFile, header.e_lfanew, NULL, FILE_BEGIN); ReadFile(hFile, (void *) buf, 2, &read, NULL); CloseHandle(hFile); if ((buf[0] == 'N') && (buf[1] == 'E')) { applType = APPL_WIN3X; } else if ((buf[0] == 'P') && (buf[1] == 'E')) { applType = APPL_WIN32; } else { /* * Strictly speaking, there should be a test that there is an 'L' * and 'E' at buf[0..1], to identify the type as DOS, but of * course we ran into a DOS executable that _doesn't_ have the * magic number - specifically, one compiled using the Lahey * Fortran90 compiler. */ applType = APPL_DOS; } break; } Tcl_DStringFree(&nameBuf); if (applType == APPL_NONE) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf("couldn't execute \"%s\": %s", originalName, Tcl_PosixError(interp))); return APPL_NONE; } if ((applType == APPL_DOS) || (applType == APPL_WIN3X)) { /* * Replace long path name of executable with short path name for * 16-bit applications. Otherwise the application may not be able to * correctly parse its own command line to separate off the * application name from the arguments. */ GetShortPathName(nativeFullPath, nativeFullPath, MAX_PATH); strcpy(fullName, Tcl_WinTCharToUtf(nativeFullPath, -1, &ds)); Tcl_DStringFree(&ds); } return applType; } /* *---------------------------------------------------------------------- * * BuildCommandLine -- * * The command line arguments are stored in linePtr separated by spaces, * in a form that CreateProcess() understands. Special characters in * individual arguments from argv[] must be quoted when being stored in * cmdLine. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void BuildCommandLine( const char *executable, /* Full path of executable (including * extension). Replacement for argv[0]. */ int argc, /* Number of arguments. */ const char **argv, /* Argument strings in UTF. */ Tcl_DString *linePtr) /* Initialized Tcl_DString that receives the * command line (TCHAR). */ { const char *arg, *start, *special; int quote, i; Tcl_DString ds; Tcl_DStringInit(&ds); /* * Prime the path. Add a space separator if we were primed with something. */ TclDStringAppendDString(&ds, linePtr); if (Tcl_DStringLength(linePtr) > 0) { TclDStringAppendLiteral(&ds, " "); } for (i = 0; i < argc; i++) { if (i == 0) { arg = executable; } else { arg = argv[i]; TclDStringAppendLiteral(&ds, " "); } quote = 0; if (arg[0] == '\0') { quote = 1; } else { int count; Tcl_UniChar ch; for (start = arg; *start != '\0'; start += count) { count = Tcl_UtfToUniChar(start, &ch); if (Tcl_UniCharIsSpace(ch)) { /* INTL: ISO space. */ quote = 1; break; } } } if (quote) { TclDStringAppendLiteral(&ds, "\""); } start = arg; for (special = arg; ; ) { if ((*special == '\\') && (special[1] == '\\' || special[1] == '"' || (quote && special[1] == '\0'))) { Tcl_DStringAppend(&ds, start, (int) (special - start)); start = special; while (1) { special++; if (*special == '"' || (quote && *special == '\0')) { /* * N backslashes followed a quote -> insert N * 2 + 1 * backslashes then a quote. */ Tcl_DStringAppend(&ds, start, (int) (special - start)); break; } if (*special != '\\') { break; } } Tcl_DStringAppend(&ds, start, (int) (special - start)); start = special; } if (*special == '"') { Tcl_DStringAppend(&ds, start, (int) (special - start)); TclDStringAppendLiteral(&ds, "\\\""); start = special + 1; } if (*special == '\0') { break; } special++; } Tcl_DStringAppend(&ds, start, (int) (special - start)); if (quote) { TclDStringAppendLiteral(&ds, "\""); } } Tcl_DStringFree(linePtr); Tcl_WinUtfToTChar(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), linePtr); Tcl_DStringFree(&ds); } /* *---------------------------------------------------------------------- * * TclpCreateCommandChannel -- * * This function is called by Tcl_OpenCommandChannel to perform the * platform specific channel initialization for a command channel. * * Results: * Returns a new channel or NULL on failure. * * Side effects: * Allocates a new channel. * *---------------------------------------------------------------------- */ Tcl_Channel TclpCreateCommandChannel( TclFile readFile, /* If non-null, gives the file for reading. */ TclFile writeFile, /* If non-null, gives the file for writing. */ TclFile errorFile, /* If non-null, gives the file where errors * can be read. */ int numPids, /* The number of pids in the pid array. */ Tcl_Pid *pidPtr) /* An array of process identifiers. */ { char channelName[16 + TCL_INTEGER_SPACE]; DWORD id; PipeInfo *infoPtr = ckalloc(sizeof(PipeInfo)); PipeInit(); infoPtr->watchMask = 0; infoPtr->flags = 0; infoPtr->readFlags = 0; infoPtr->readFile = readFile; infoPtr->writeFile = writeFile; infoPtr->errorFile = errorFile; infoPtr->numPids = numPids; infoPtr->pidPtr = pidPtr; infoPtr->writeBuf = 0; infoPtr->writeBufLen = 0; infoPtr->writeError = 0; infoPtr->channel = NULL; infoPtr->validMask = 0; infoPtr->threadId = Tcl_GetCurrentThread(); if (readFile != NULL) { /* * Start the background reader thread. */ infoPtr->readable = CreateEvent(NULL, TRUE, TRUE, NULL); infoPtr->startReader = CreateEvent(NULL, FALSE, FALSE, NULL); infoPtr->stopReader = CreateEvent(NULL, TRUE, FALSE, NULL); infoPtr->readThread = CreateThread(NULL, 256, PipeReaderThread, infoPtr, 0, &id); SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST); infoPtr->validMask |= TCL_READABLE; } else { infoPtr->readThread = 0; } if (writeFile != NULL) { /* * Start the background writer thread. */ infoPtr->writable = CreateEvent(NULL, TRUE, TRUE, NULL); infoPtr->startWriter = CreateEvent(NULL, FALSE, FALSE, NULL); infoPtr->stopWriter = CreateEvent(NULL, TRUE, FALSE, NULL); infoPtr->writeThread = CreateThread(NULL, 256, PipeWriterThread, infoPtr, 0, &id); SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST); infoPtr->validMask |= TCL_WRITABLE; } /* * For backward compatibility with previous versions of Tcl, we use * "file%d" as the base name for pipes even though it would be more * natural to use "pipe%d". Use the pointer to keep the channel names * unique, in case channels share handles (stdin/stdout). */ sprintf(channelName, "file%" TCL_I_MODIFIER "x", (size_t) infoPtr); infoPtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName, infoPtr, infoPtr->validMask); /* * Pipes have AUTO translation mode on Windows and ^Z eof char, which * means that a ^Z will be appended to them at close. This is needed for * Windows programs that expect a ^Z at EOF. */ Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto"); Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}"); return infoPtr->channel; } /* *---------------------------------------------------------------------- * * Tcl_CreatePipe -- * * System dependent interface to create a pipe for the [chan pipe] * command. Stolen from TclX. * * Results: * TCL_OK or TCL_ERROR. * *---------------------------------------------------------------------- */ int Tcl_CreatePipe( Tcl_Interp *interp, /* Errors returned in result.*/ Tcl_Channel *rchan, /* Where to return the read side. */ Tcl_Channel *wchan, /* Where to return the write side. */ int flags) /* Reserved for future use. */ { HANDLE readHandle, writeHandle; SECURITY_ATTRIBUTES sec; sec.nLength = sizeof(SECURITY_ATTRIBUTES); sec.lpSecurityDescriptor = NULL; sec.bInheritHandle = FALSE; if (!CreatePipe(&readHandle, &writeHandle, &sec, 0)) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "pipe creation failed: %s", Tcl_PosixError(interp))); return TCL_ERROR; } *rchan = Tcl_MakeFileChannel((ClientData) readHandle, TCL_READABLE); Tcl_RegisterChannel(interp, *rchan); *wchan = Tcl_MakeFileChannel((ClientData) writeHandle, TCL_WRITABLE); Tcl_RegisterChannel(interp, *wchan); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclGetAndDetachPids -- * * Stores a list of the command PIDs for a command channel in the * interp's result. * * Results: * None. * * Side effects: * Modifies the interp's result. * *---------------------------------------------------------------------- */ void TclGetAndDetachPids( Tcl_Interp *interp, Tcl_Channel chan) { PipeInfo *pipePtr; const Tcl_ChannelType *chanTypePtr; Tcl_Obj *pidsObj; int i; /* * Punt if the channel is not a command channel. */ chanTypePtr = Tcl_GetChannelType(chan); if (chanTypePtr != &pipeChannelType) { return; } pipePtr = Tcl_GetChannelInstanceData(chan); TclNewObj(pidsObj); for (i = 0; i < pipePtr->numPids; i++) { Tcl_ListObjAppendElement(NULL, pidsObj, Tcl_NewWideIntObj((unsigned) TclpGetPid(pipePtr->pidPtr[i]))); Tcl_DetachPids(1, &pipePtr->pidPtr[i]); } Tcl_SetObjResult(interp, pidsObj); if (pipePtr->numPids > 0) { ckfree(pipePtr->pidPtr); pipePtr->numPids = 0; } } /* *---------------------------------------------------------------------- * * PipeBlockModeProc -- * * Set blocking or non-blocking mode on channel. * * Results: * 0 if successful, errno when failed. * * Side effects: * Sets the device into blocking or non-blocking mode. * *---------------------------------------------------------------------- */ static int PipeBlockModeProc( ClientData instanceData, /* Instance data for channel. */ int mode) /* TCL_MODE_BLOCKING or * TCL_MODE_NONBLOCKING. */ { PipeInfo *infoPtr = (PipeInfo *) instanceData; /* * Pipes on Windows can not be switched between blocking and nonblocking, * hence we have to emulate the behavior. This is done in the input * function by checking against a bit in the state. We set or unset the * bit here to cause the input function to emulate the correct behavior. */ if (mode == TCL_MODE_NONBLOCKING) { infoPtr->flags |= PIPE_ASYNC; } else { infoPtr->flags &= ~(PIPE_ASYNC); } return 0; } /* *---------------------------------------------------------------------- * * PipeClose2Proc -- * * Closes a pipe based IO channel. * * Results: * 0 on success, errno otherwise. * * Side effects: * Closes the physical channel. * *---------------------------------------------------------------------- */ static int PipeClose2Proc( ClientData instanceData, /* Pointer to PipeInfo structure. */ Tcl_Interp *interp, /* For error reporting. */ int flags) /* Flags that indicate which side to close. */ { PipeInfo *pipePtr = (PipeInfo *) instanceData; Tcl_Channel errChan; int errorCode, result; PipeInfo *infoPtr, **nextPtrPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); DWORD exitCode; errorCode = 0; result = 0; if ((!flags || flags == TCL_CLOSE_READ) && (pipePtr->readFile != NULL)) { /* * Clean up the background thread if necessary. Note that this must be * done before we can close the file, since the thread may be blocking * trying to read from the pipe. */ if (pipePtr->readThread) { /* * The thread may already have closed on its own. Check its exit * code. */ GetExitCodeThread(pipePtr->readThread, &exitCode); if (exitCode == STILL_ACTIVE) { /* * Set the stop event so that if the reader thread is blocked * in PipeReaderThread on WaitForMultipleEvents, it will exit * cleanly. */ SetEvent(pipePtr->stopReader); /* * Wait at most 20 milliseconds for the reader thread to * close. */ if (WaitForSingleObject(pipePtr->readThread, 20) == WAIT_TIMEOUT) { /* * The thread must be blocked waiting for the pipe to * become readable in ReadFile(). There isn't a clean way * to exit the thread from this condition. We should * terminate the child process instead to get the reader * thread to fall out of ReadFile with a FALSE. (below) is * not the correct way to do this, but will stay here * until a better solution is found. * * Note that we need to guard against terminating the * thread while it is in the middle of Tcl_ThreadAlert * because it won't be able to release the notifier lock. */ Tcl_MutexLock(&pipeMutex); /* BUG: this leaks memory */ TerminateThread(pipePtr->readThread, 0); Tcl_MutexUnlock(&pipeMutex); } } CloseHandle(pipePtr->readThread); CloseHandle(pipePtr->readable); CloseHandle(pipePtr->startReader); CloseHandle(pipePtr->stopReader); pipePtr->readThread = NULL; } if (TclpCloseFile(pipePtr->readFile) != 0) { errorCode = errno; } pipePtr->validMask &= ~TCL_READABLE; pipePtr->readFile = NULL; } if ((!flags || flags & TCL_CLOSE_WRITE) && (pipePtr->writeFile != NULL)) { if (pipePtr->writeThread) { /* * Wait for the writer thread to finish the current buffer, then * terminate the thread and close the handles. If the channel is * nonblocking but blocked during exit, bail out since the worker * thread is not interruptible and we want TIP#398-fast-exit. */ if (TclInExit() && (pipePtr->flags & PIPE_ASYNC)) { /* give it a chance to leave honorably */ SetEvent(pipePtr->stopWriter); if (WaitForSingleObject(pipePtr->writable, 0) == WAIT_TIMEOUT) { return EWOULDBLOCK; } } else { WaitForSingleObject(pipePtr->writable, INFINITE); } /* * The thread may already have closed on it's own. Check its exit * code. */ GetExitCodeThread(pipePtr->writeThread, &exitCode); if (exitCode == STILL_ACTIVE) { /* * Set the stop event so that if the reader thread is blocked * in PipeReaderThread on WaitForMultipleEvents, it will exit * cleanly. */ SetEvent(pipePtr->stopWriter); /* * Wait at most 20 milliseconds for the reader thread to * close. */ if (WaitForSingleObject(pipePtr->writeThread, 20) == WAIT_TIMEOUT) { /* * The thread must be blocked waiting for the pipe to * consume input in WriteFile(). There isn't a clean way * to exit the thread from this condition. We should * terminate the child process instead to get the writer * thread to fall out of WriteFile with a FALSE. (below) * is not the correct way to do this, but will stay here * until a better solution is found. * * Note that we need to guard against terminating the * thread while it is in the middle of Tcl_ThreadAlert * because it won't be able to release the notifier lock. */ Tcl_MutexLock(&pipeMutex); /* BUG: this leaks memory */ TerminateThread(pipePtr->writeThread, 0); Tcl_MutexUnlock(&pipeMutex); } } CloseHandle(pipePtr->writeThread); CloseHandle(pipePtr->writable); CloseHandle(pipePtr->startWriter); CloseHandle(pipePtr->stopWriter); pipePtr->writeThread = NULL; } if (TclpCloseFile(pipePtr->writeFile) != 0) { if (errorCode == 0) { errorCode = errno; } } pipePtr->validMask &= ~TCL_WRITABLE; pipePtr->writeFile = NULL; } pipePtr->watchMask &= pipePtr->validMask; /* * Don't free the channel if any of the flags were set. */ if (flags) { return errorCode; } /* * Remove the file from the list of watched files. */ for (nextPtrPtr = &(tsdPtr->firstPipePtr), infoPtr = *nextPtrPtr; infoPtr != NULL; nextPtrPtr = &infoPtr->nextPtr, infoPtr = *nextPtrPtr) { if (infoPtr == (PipeInfo *)pipePtr) { *nextPtrPtr = infoPtr->nextPtr; break; } } if ((pipePtr->flags & PIPE_ASYNC) || TclInExit()) { /* * If the channel is non-blocking or Tcl is being cleaned up, just * detach the children PIDs, reap them (important if we are in a * dynamic load module), and discard the errorFile. */ Tcl_DetachPids(pipePtr->numPids, pipePtr->pidPtr); Tcl_ReapDetachedProcs(); if (pipePtr->errorFile) { if (TclpCloseFile(pipePtr->errorFile) != 0) { if (errorCode == 0) { errorCode = errno; } } } result = 0; } else { /* * Wrap the error file into a channel and give it to the cleanup * routine. */ if (pipePtr->errorFile) { WinFile *filePtr = (WinFile *) pipePtr->errorFile; errChan = Tcl_MakeFileChannel((ClientData) filePtr->handle, TCL_READABLE); ckfree(filePtr); } else { errChan = NULL; } result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr, errChan); } if (pipePtr->numPids > 0) { ckfree(pipePtr->pidPtr); } if (pipePtr->writeBuf != NULL) { ckfree(pipePtr->writeBuf); } ckfree(pipePtr); if (errorCode == 0) { return result; } return errorCode; } /* *---------------------------------------------------------------------- * * PipeInputProc -- * * Reads input from the IO channel into the buffer given. Returns count * of how many bytes were actually read, and an error indication. * * Results: * A count of how many bytes were read is returned and an error * indication is returned in an output argument. * * Side effects: * Reads input from the actual channel. * *---------------------------------------------------------------------- */ static int PipeInputProc( ClientData instanceData, /* Pipe state. */ char *buf, /* Where to store data read. */ int bufSize, /* How much space is available in the * buffer? */ int *errorCode) /* Where to store error code. */ { PipeInfo *infoPtr = (PipeInfo *) instanceData; WinFile *filePtr = (WinFile*) infoPtr->readFile; DWORD count, bytesRead = 0; int result; *errorCode = 0; /* * Synchronize with the reader thread. */ result = WaitForRead(infoPtr, (infoPtr->flags & PIPE_ASYNC) ? 0 : 1); /* * If an error occurred, return immediately. */ if (result == -1) { *errorCode = errno; return -1; } if (infoPtr->readFlags & PIPE_EXTRABYTE) { /* * The reader thread consumed 1 byte as a side effect of waiting so we * need to move it into the buffer. */ *buf = infoPtr->extraByte; infoPtr->readFlags &= ~PIPE_EXTRABYTE; buf++; bufSize--; bytesRead = 1; /* * If further read attempts would block, return what we have. */ if (result == 0) { return bytesRead; } } /* * Attempt to read bufSize bytes. The read will return immediately if * there is any data available. Otherwise it will block until at least one * byte is available or an EOF occurs. */ if (ReadFile(filePtr->handle, (LPVOID) buf, (DWORD) bufSize, &count, (LPOVERLAPPED) NULL) == TRUE) { return bytesRead + count; } else if (bytesRead) { /* * Ignore errors if we have data to return. */ return bytesRead; } TclWinConvertError(GetLastError()); if (errno == EPIPE) { infoPtr->readFlags |= PIPE_EOF; return 0; } *errorCode = errno; return -1; } /* *---------------------------------------------------------------------- * * PipeOutputProc -- * * Writes the given output on the IO channel. Returns count of how many * characters were actually written, and an error indication. * * Results: * A count of how many characters were written is returned and an error * indication is returned in an output argument. * * Side effects: * Writes output on the actual channel. * *---------------------------------------------------------------------- */ static int PipeOutputProc( ClientData instanceData, /* Pipe state. */ const char *buf, /* The data buffer. */ int toWrite, /* How many bytes to write? */ int *errorCode) /* Where to store error code. */ { PipeInfo *infoPtr = (PipeInfo *) instanceData; WinFile *filePtr = (WinFile*) infoPtr->writeFile; DWORD bytesWritten, timeout; *errorCode = 0; timeout = (infoPtr->flags & PIPE_ASYNC) ? 0 : INFINITE; if (WaitForSingleObject(infoPtr->writable, timeout) == WAIT_TIMEOUT) { /* * The writer thread is blocked waiting for a write to complete and * the channel is in non-blocking mode. */ errno = EWOULDBLOCK; goto error; } /* * Check for a background error on the last write. */ if (infoPtr->writeError) { TclWinConvertError(infoPtr->writeError); infoPtr->writeError = 0; goto error; } if (infoPtr->flags & PIPE_ASYNC) { /* * The pipe is non-blocking, so copy the data into the output buffer * and restart the writer thread. */ if (toWrite > infoPtr->writeBufLen) { /* * Reallocate the buffer to be large enough to hold the data. */ if (infoPtr->writeBuf) { ckfree(infoPtr->writeBuf); } infoPtr->writeBufLen = toWrite; infoPtr->writeBuf = ckalloc(toWrite); } memcpy(infoPtr->writeBuf, buf, (size_t) toWrite); infoPtr->toWrite = toWrite; ResetEvent(infoPtr->writable); SetEvent(infoPtr->startWriter); bytesWritten = toWrite; } else { /* * In the blocking case, just try to write the buffer directly. This * avoids an unnecessary copy. */ if (WriteFile(filePtr->handle, (LPVOID) buf, (DWORD) toWrite, &bytesWritten, (LPOVERLAPPED) NULL) == FALSE) { TclWinConvertError(GetLastError()); goto error; } } return bytesWritten; error: *errorCode = errno; return -1; } /* *---------------------------------------------------------------------- * * PipeEventProc -- * * This function is invoked by Tcl_ServiceEvent when a file event reaches * the front of the event queue. This function invokes Tcl_NotifyChannel * on the pipe. * * Results: * Returns 1 if the event was handled, meaning it should be removed from * the queue. Returns 0 if the event was not handled, meaning it should * stay on the queue. The only time the event isn't handled is if the * TCL_FILE_EVENTS flag bit isn't set. * * Side effects: * Whatever the notifier callback does. * *---------------------------------------------------------------------- */ static int PipeEventProc( Tcl_Event *evPtr, /* Event to service. */ int flags) /* Flags that indicate what events to * handle, such as TCL_FILE_EVENTS. */ { PipeEvent *pipeEvPtr = (PipeEvent *)evPtr; PipeInfo *infoPtr; int mask; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; } /* * Search through the list of watched pipes for the one whose handle * matches the event. We do this rather than simply dereferencing the * handle in the event so that pipes can be deleted while the event is in * the queue. */ for (infoPtr = tsdPtr->firstPipePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (pipeEvPtr->infoPtr == infoPtr) { infoPtr->flags &= ~(PIPE_PENDING); break; } } /* * Remove stale events. */ if (!infoPtr) { return 1; } /* * Check to see if the pipe is readable. Note that we can't tell if a pipe * is writable, so we always report it as being writable unless we have * detected EOF. */ mask = 0; if ((infoPtr->watchMask & TCL_WRITABLE) && (WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT)) { mask = TCL_WRITABLE; } if ((infoPtr->watchMask & TCL_READABLE) && (WaitForRead(infoPtr,0) >= 0)) { if (infoPtr->readFlags & PIPE_EOF) { mask = TCL_READABLE; } else { mask |= TCL_READABLE; } } /* * Inform the channel of the events. */ Tcl_NotifyChannel(infoPtr->channel, infoPtr->watchMask & mask); return 1; } /* *---------------------------------------------------------------------- * * PipeWatchProc -- * * Called by the notifier to set up to watch for events on this channel. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void PipeWatchProc( ClientData instanceData, /* Pipe state. */ int mask) /* What events to watch for, OR-ed combination * of TCL_READABLE, TCL_WRITABLE and * TCL_EXCEPTION. */ { PipeInfo **nextPtrPtr, *ptr; PipeInfo *infoPtr = (PipeInfo *) instanceData; int oldMask = infoPtr->watchMask; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Since most of the work is handled by the background threads, we just * need to update the watchMask and then force the notifier to poll once. */ infoPtr->watchMask = mask & infoPtr->validMask; if (infoPtr->watchMask) { Tcl_Time blockTime = { 0, 0 }; if (!oldMask) { infoPtr->nextPtr = tsdPtr->firstPipePtr; tsdPtr->firstPipePtr = infoPtr; } Tcl_SetMaxBlockTime(&blockTime); } else { if (oldMask) { /* * Remove the pipe from the list of watched pipes. */ for (nextPtrPtr = &(tsdPtr->firstPipePtr), ptr = *nextPtrPtr; ptr != NULL; nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) { if (infoPtr == ptr) { *nextPtrPtr = ptr->nextPtr; break; } } } } } /* *---------------------------------------------------------------------- * * PipeGetHandleProc -- * * Called from Tcl_GetChannelHandle to retrieve OS handles from inside a * command pipeline based channel. * * Results: * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if there is no * handle for the specified direction. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PipeGetHandleProc( ClientData instanceData, /* The pipe state. */ int direction, /* TCL_READABLE or TCL_WRITABLE */ ClientData *handlePtr) /* Where to store the handle. */ { PipeInfo *infoPtr = (PipeInfo *) instanceData; WinFile *filePtr; if (direction == TCL_READABLE && infoPtr->readFile) { filePtr = (WinFile*) infoPtr->readFile; *handlePtr = (ClientData) filePtr->handle; return TCL_OK; } if (direction == TCL_WRITABLE && infoPtr->writeFile) { filePtr = (WinFile*) infoPtr->writeFile; *handlePtr = (ClientData) filePtr->handle; return TCL_OK; } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_WaitPid -- * * Emulates the waitpid system call. * * Results: * Returns 0 if the process is still alive, -1 on an error, or the pid on * a clean close. * * Side effects: * Unless WNOHANG is set and the wait times out, the process information * record will be deleted and the process handle will be closed. * *---------------------------------------------------------------------- */ Tcl_Pid Tcl_WaitPid( Tcl_Pid pid, int *statPtr, int options) { ProcInfo *infoPtr = NULL, **prevPtrPtr; DWORD flags; Tcl_Pid result; DWORD ret, exitCode; PipeInit(); /* * If no pid is specified, do nothing. */ if (pid == 0) { *statPtr = 0; return 0; } /* * Find the process and cut it from the process list. */ Tcl_MutexLock(&pipeMutex); prevPtrPtr = &procList; for (infoPtr = procList; infoPtr != NULL; prevPtrPtr = &infoPtr->nextPtr, infoPtr = infoPtr->nextPtr) { if (infoPtr->hProcess == (HANDLE) pid) { *prevPtrPtr = infoPtr->nextPtr; break; } } Tcl_MutexUnlock(&pipeMutex); /* * If the pid is not one of the processes we know about (we started it) * then do nothing. */ if (infoPtr == NULL) { *statPtr = 0; return 0; } /* * Officially "wait" for it to finish. We either poll (WNOHANG) or wait * for an infinite amount of time. */ if (options & WNOHANG) { flags = 0; } else { flags = INFINITE; } ret = WaitForSingleObject(infoPtr->hProcess, flags); if (ret == WAIT_TIMEOUT) { *statPtr = 0; if (options & WNOHANG) { /* * Re-insert this infoPtr back on the list. */ Tcl_MutexLock(&pipeMutex); infoPtr->nextPtr = procList; procList = infoPtr; Tcl_MutexUnlock(&pipeMutex); return 0; } else { result = 0; } } else if (ret == WAIT_OBJECT_0) { GetExitCodeProcess(infoPtr->hProcess, &exitCode); /* * Does the exit code look like one of the exception codes? */ switch (exitCode) { case EXCEPTION_FLT_DENORMAL_OPERAND: case EXCEPTION_FLT_DIVIDE_BY_ZERO: case EXCEPTION_FLT_INEXACT_RESULT: case EXCEPTION_FLT_INVALID_OPERATION: case EXCEPTION_FLT_OVERFLOW: case EXCEPTION_FLT_STACK_CHECK: case EXCEPTION_FLT_UNDERFLOW: case EXCEPTION_INT_DIVIDE_BY_ZERO: case EXCEPTION_INT_OVERFLOW: *statPtr = 0xC0000000 | SIGFPE; break; case EXCEPTION_PRIV_INSTRUCTION: case EXCEPTION_ILLEGAL_INSTRUCTION: *statPtr = 0xC0000000 | SIGILL; break; case EXCEPTION_ACCESS_VIOLATION: case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: case EXCEPTION_STACK_OVERFLOW: case EXCEPTION_NONCONTINUABLE_EXCEPTION: case EXCEPTION_INVALID_DISPOSITION: case EXCEPTION_GUARD_PAGE: case EXCEPTION_INVALID_HANDLE: *statPtr = 0xC0000000 | SIGSEGV; break; case EXCEPTION_DATATYPE_MISALIGNMENT: *statPtr = 0xC0000000 | SIGBUS; break; case EXCEPTION_BREAKPOINT: case EXCEPTION_SINGLE_STEP: *statPtr = 0xC0000000 | SIGTRAP; break; case CONTROL_C_EXIT: *statPtr = 0xC0000000 | SIGINT; break; default: /* * Non-exceptional, normal, exit code. Note that the exit code is * truncated to a signed short range [-32768,32768) whether it * fits into this range or not. * * BUG: Even though the exit code is a DWORD, it is understood by * convention to be a signed integer, yet there isn't enough room * to fit this into the POSIX style waitstatus mask without * truncating it. */ *statPtr = exitCode; break; } result = pid; } else { errno = ECHILD; *statPtr = 0xC0000000 | ECHILD; result = (Tcl_Pid) -1; } /* * Officially close the process handle. */ CloseHandle(infoPtr->hProcess); ckfree(infoPtr); return result; } /* *---------------------------------------------------------------------- * * TclWinAddProcess -- * * Add a process to the process list so that we can use Tcl_WaitPid on * the process. * * Results: * None * * Side effects: * Adds the specified process handle to the process list so Tcl_WaitPid * knows about it. * *---------------------------------------------------------------------- */ void TclWinAddProcess( void *hProcess, /* Handle to process */ unsigned long id) /* Global process identifier */ { ProcInfo *procPtr = ckalloc(sizeof(ProcInfo)); PipeInit(); procPtr->hProcess = hProcess; procPtr->dwProcessId = id; Tcl_MutexLock(&pipeMutex); procPtr->nextPtr = procList; procList = procPtr; Tcl_MutexUnlock(&pipeMutex); } /* *---------------------------------------------------------------------- * * Tcl_PidObjCmd -- * * This function is invoked to process the "pid" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_PidObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* Argument strings. */ { Tcl_Channel chan; const Tcl_ChannelType *chanTypePtr; PipeInfo *pipePtr; int i; Tcl_Obj *resultPtr; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?channelId?"); return TCL_ERROR; } if (objc == 1) { Tcl_SetObjResult(interp, Tcl_NewWideIntObj((unsigned) getpid())); } else { chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } chanTypePtr = Tcl_GetChannelType(chan); if (chanTypePtr != &pipeChannelType) { return TCL_OK; } pipePtr = (PipeInfo *) Tcl_GetChannelInstanceData(chan); resultPtr = Tcl_NewObj(); for (i = 0; i < pipePtr->numPids; i++) { Tcl_ListObjAppendElement(/*interp*/ NULL, resultPtr, Tcl_NewWideIntObj((unsigned) TclpGetPid(pipePtr->pidPtr[i]))); } Tcl_SetObjResult(interp, resultPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * WaitForRead -- * * Wait until some data is available, the pipe is at EOF or the reader * thread is blocked waiting for data (if the channel is in non-blocking * mode). * * Results: * Returns 1 if pipe is readable. Returns 0 if there is no data on the * pipe, but there is buffered data. Returns -1 if an error occurred. If * an error occurred, the threads may not be synchronized. * * Side effects: * Updates the shared state flags and may consume 1 byte of data from the * pipe. If no error occurred, the reader thread is blocked waiting for a * signal from the main thread. * *---------------------------------------------------------------------- */ static int WaitForRead( PipeInfo *infoPtr, /* Pipe state. */ int blocking) /* Indicates whether call should be blocking * or not. */ { DWORD timeout, count; HANDLE *handle = ((WinFile *) infoPtr->readFile)->handle; while (1) { /* * Synchronize with the reader thread. */ timeout = blocking ? INFINITE : 0; if (WaitForSingleObject(infoPtr->readable, timeout) == WAIT_TIMEOUT) { /* * The reader thread is blocked waiting for data and the channel * is in non-blocking mode. */ errno = EWOULDBLOCK; return -1; } /* * At this point, the two threads are synchronized, so it is safe to * access shared state. */ /* * If the pipe has hit EOF, it is always readable. */ if (infoPtr->readFlags & PIPE_EOF) { return 1; } /* * Check to see if there is any data sitting in the pipe. */ if (PeekNamedPipe(handle, (LPVOID) NULL, (DWORD) 0, (LPDWORD) NULL, &count, (LPDWORD) NULL) != TRUE) { TclWinConvertError(GetLastError()); /* * Check to see if the peek failed because of EOF. */ if (errno == EPIPE) { infoPtr->readFlags |= PIPE_EOF; return 1; } /* * Ignore errors if there is data in the buffer. */ if (infoPtr->readFlags & PIPE_EXTRABYTE) { return 0; } else { return -1; } } /* * We found some data in the pipe, so it must be readable. */ if (count > 0) { return 1; } /* * The pipe isn't readable, but there is some data sitting in the * buffer, so return immediately. */ if (infoPtr->readFlags & PIPE_EXTRABYTE) { return 0; } /* * There wasn't any data available, so reset the thread and try again. */ ResetEvent(infoPtr->readable); SetEvent(infoPtr->startReader); } } /* *---------------------------------------------------------------------- * * PipeReaderThread -- * * This function runs in a separate thread and waits for input to become * available on a pipe. * * Results: * None. * * Side effects: * Signals the main thread when input become available. May cause the * main thread to wake up by posting a message. May consume one byte from * the pipe for each wait operation. Will cause a memory leak of ~4k, if * forcefully terminated with TerminateThread(). * *---------------------------------------------------------------------- */ static DWORD WINAPI PipeReaderThread( LPVOID arg) { PipeInfo *infoPtr = (PipeInfo *)arg; HANDLE *handle = ((WinFile *) infoPtr->readFile)->handle; DWORD count, err; int done = 0; HANDLE wEvents[2]; DWORD waitResult; wEvents[0] = infoPtr->stopReader; wEvents[1] = infoPtr->startReader; while (!done) { /* * Wait for the main thread to signal before attempting to wait on the * pipe becoming readable. */ waitResult = WaitForMultipleObjects(2, wEvents, FALSE, INFINITE); if (waitResult != (WAIT_OBJECT_0 + 1)) { /* * The start event was not signaled. It might be the stop event or * an error, so exit. */ break; } /* * Try waiting for 0 bytes. This will block until some data is * available on NT, but will return immediately on Win 95. So, if no * data is available after the first read, we block until we can read * a single byte off of the pipe. */ if (ReadFile(handle, NULL, 0, &count, NULL) == FALSE || PeekNamedPipe(handle, NULL, 0, NULL, &count, NULL) == FALSE) { /* * The error is a result of an EOF condition, so set the EOF bit * before signalling the main thread. */ err = GetLastError(); if (err == ERROR_BROKEN_PIPE) { infoPtr->readFlags |= PIPE_EOF; done = 1; } else if (err == ERROR_INVALID_HANDLE) { break; } } else if (count == 0) { if (ReadFile(handle, &(infoPtr->extraByte), 1, &count, NULL) != FALSE) { /* * One byte was consumed as a side effect of waiting for the * pipe to become readable. */ infoPtr->readFlags |= PIPE_EXTRABYTE; } else { err = GetLastError(); if (err == ERROR_BROKEN_PIPE) { /* * The error is a result of an EOF condition, so set the * EOF bit before signalling the main thread. */ infoPtr->readFlags |= PIPE_EOF; done = 1; } else if (err == ERROR_INVALID_HANDLE) { break; } } } /* * Signal the main thread by signalling the readable event and then * waking up the notifier thread. */ SetEvent(infoPtr->readable); /* * Alert the foreground thread. Note that we need to treat this like a * critical section so the foreground thread does not terminate this * thread while we are holding a mutex in the notifier code. */ Tcl_MutexLock(&pipeMutex); if (infoPtr->threadId != NULL) { /* * TIP #218. When in flight ignore the event, no one will receive * it anyway. */ Tcl_ThreadAlert(infoPtr->threadId); } Tcl_MutexUnlock(&pipeMutex); } return 0; } /* *---------------------------------------------------------------------- * * PipeWriterThread -- * * This function runs in a separate thread and writes data onto a pipe. * * Results: * Always returns 0. * * Side effects: * Signals the main thread when an output operation is completed. May * cause the main thread to wake up by posting a message. * *---------------------------------------------------------------------- */ static DWORD WINAPI PipeWriterThread( LPVOID arg) { PipeInfo *infoPtr = (PipeInfo *)arg; HANDLE *handle = ((WinFile *) infoPtr->writeFile)->handle; DWORD count, toWrite; char *buf; int done = 0; HANDLE wEvents[2]; DWORD waitResult; wEvents[0] = infoPtr->stopWriter; wEvents[1] = infoPtr->startWriter; while (!done) { /* * Wait for the main thread to signal before attempting to write. */ waitResult = WaitForMultipleObjects(2, wEvents, FALSE, INFINITE); if (waitResult != (WAIT_OBJECT_0 + 1)) { /* * The start event was not signaled. It might be the stop event or * an error, so exit. */ if (waitResult == WAIT_OBJECT_0) { SetEvent(infoPtr->writable); } break; } buf = infoPtr->writeBuf; toWrite = infoPtr->toWrite; /* * Loop until all of the bytes are written or an error occurs. */ while (toWrite > 0) { if (WriteFile(handle, buf, toWrite, &count, NULL) == FALSE) { infoPtr->writeError = GetLastError(); done = 1; break; } else { toWrite -= count; buf += count; } } /* * Signal the main thread by signalling the writable event and then * waking up the notifier thread. */ SetEvent(infoPtr->writable); /* * Alert the foreground thread. Note that we need to treat this like a * critical section so the foreground thread does not terminate this * thread while we are holding a mutex in the notifier code. */ Tcl_MutexLock(&pipeMutex); if (infoPtr->threadId != NULL) { /* * TIP #218. When in flight ignore the event, no one will receive * it anyway. */ Tcl_ThreadAlert(infoPtr->threadId); } Tcl_MutexUnlock(&pipeMutex); } return 0; } /* *---------------------------------------------------------------------- * * PipeThreadActionProc -- * * Insert or remove any thread local refs to this channel. * * Results: * None. * * Side effects: * Changes thread local list of valid channels. * *---------------------------------------------------------------------- */ static void PipeThreadActionProc( ClientData instanceData, int action) { PipeInfo *infoPtr = (PipeInfo *) instanceData; /* * We do not access firstPipePtr in the thread structures. This is not for * all pipes managed by the thread, but only those we are watching. * Removal of the filevent handlers before transfer thus takes care of * this structure. */ Tcl_MutexLock(&pipeMutex); if (action == TCL_CHANNEL_THREAD_INSERT) { /* * We can't copy the thread information from the channel when the * channel is created. At this time the channel back pointer has not * been set yet. However in that case the threadId has already been * set by TclpCreateCommandChannel itself, so the structure is still * good. */ PipeInit(); if (infoPtr->channel != NULL) { infoPtr->threadId = Tcl_GetChannelThread(infoPtr->channel); } } else { infoPtr->threadId = NULL; } Tcl_MutexUnlock(&pipeMutex); } /* *---------------------------------------------------------------------- * * TclpOpenTemporaryFile -- * * Creates a temporary file, possibly based on the supplied bits and * pieces of template supplied in the first three arguments. If the * fourth argument is non-NULL, it contains a Tcl_Obj to store the name * of the temporary file in (and it is caller's responsibility to clean * up). If the fourth argument is NULL, try to arrange for the temporary * file to go away once it is no longer needed. * * Results: * A read-write Tcl Channel open on the file. * *---------------------------------------------------------------------- */ Tcl_Channel TclpOpenTemporaryFile( Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj) { TCHAR name[MAX_PATH]; char *namePtr; HANDLE handle; DWORD flags = FILE_ATTRIBUTE_TEMPORARY; int length, counter, counter2; Tcl_DString buf; if (!resultingNameObj) { flags |= FILE_FLAG_DELETE_ON_CLOSE; } namePtr = (char *) name; length = GetTempPath(MAX_PATH, name); if (length == 0) { goto gotError; } namePtr += length * sizeof(TCHAR); if (basenameObj) { const char *string = Tcl_GetString(basenameObj); Tcl_WinUtfToTChar(string, basenameObj->length, &buf); memcpy(namePtr, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf)); namePtr += Tcl_DStringLength(&buf); Tcl_DStringFree(&buf); } else { const TCHAR *baseStr = TEXT("TCL"); int length = 3 * sizeof(TCHAR); memcpy(namePtr, baseStr, length); namePtr += length; } counter = TclpGetClicks() % 65533; counter2 = 1024; /* Only try this many times! Prevents * an infinite loop. */ do { char number[TCL_INTEGER_SPACE + 4]; sprintf(number, "%d.TMP", counter); counter = (unsigned short) (counter + 1); Tcl_WinUtfToTChar(number, strlen(number), &buf); Tcl_DStringSetLength(&buf, Tcl_DStringLength(&buf) + 1); memcpy(namePtr, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf) + 1); Tcl_DStringFree(&buf); handle = CreateFile(name, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, flags, NULL); } while (handle == INVALID_HANDLE_VALUE && --counter2 > 0 && GetLastError() == ERROR_FILE_EXISTS); if (handle == INVALID_HANDLE_VALUE) { goto gotError; } if (resultingNameObj) { Tcl_Obj *tmpObj = TclpNativeToNormalized(name); Tcl_AppendObjToObj(resultingNameObj, tmpObj); TclDecrRefCount(tmpObj); } return Tcl_MakeFileChannel((ClientData) handle, TCL_READABLE|TCL_WRITABLE); gotError: TclWinConvertError(GetLastError()); return NULL; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/makefile.bc0000644000175000017500000004630012663660066014453 0ustar sergeisergei# # Makefile for Borland C++ 5.5 (or C++ Builder 5), adapted from the makefile # for Visual C++ that came with tcl 8.3.3 # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # Copyright (c) 1995-1996 Sun Microsystems, Inc. # Copyright (c) 1998-1999 by Scriptics Corporation. # TIP #59 information. # # This makefile does not set the following configuration cpp # defines. Behind the defines are the makefile variables listed to set # to -D... when that feature is enabled. # # - TCL_CFG_PROFILED PROFDEFINES # - TCL_CFG_OPTIMIZED OPTDEFINES # - TCL_CFG_DO64BIT SIXFOURDEFINES # Have a look at the complete description on how to build and test Tcl with # the current Borland compilers at www.ratiosoft.com/tcl/borland. # # Usage: # - Adapt the paths below to match your compiler's location # - Make sure the compiler's bin directory is on your path # - Open a console # - To make a debug version enter # make -fmakefile.bc -DNODEBUG=0 xxx # where 'xxx' is the target you want (e.g. 'all', 'test', ...) # Please note: I omitted the 'd' suffix for debug versions because Tcl # will always call tclpip83.dll and not tclpip83d.dll, causing an error. # ^ # Besides, the debug version goes into a separate directory, so there # should be no problem having DLLs and EXEs with the same name. # If you prefer your debug version having the 'd' suffix just uncomment # the line # #DBGX = d # # - To make a 'normal' version enter # make -fmakefile.bc xxx # where 'xxx' is the target you want (e.g. 'all', 'test', ...) # # DISCLAIMER: # This makefile has an experimental status - that is those targets which # have been modified do in fact compile and link with Borland's C++ # Builder 5 and with the free Borland compiler (Borland C++ 5.5). # However the author assumes no responsiblity for any effect which the use of # this makefile or of the resulting programs might have on your system. # # Not yet modified: # - The 'plug-in-DLL' and the associated shell. # # Suggestions and / or improvements are always welcome. # # May 2001, H. Giese (hgiese@ratiosoft.com) # # Does not depend on the presence of any environment variables in # order to compile tcl; all needed information is derived from # location of the compiler directories. # # Project directories # # ROOT = top of source tree # # TOOLS32 = location of Borland development tools. # # INSTALLDIR = where the install-targets should copy the binaries and # support files # ROOT = .. INSTALLDIR = c:\program files\tcl # If you have C++ Builder 5 or the free Borland C++ 5.5 compiler # adapt the following paths as appropriate for your system TOOLS32 = c:\dev\bcc55 TOOLS32_rc = c:\dev\bcc55 #TOOLS32 = c:\bc55 #TOOLS32_rc = c:\bc55 cc32 = "$(TOOLS32)\bin\bcc32.exe" link32 = "$(TOOLS32)\bin\ilink32.exe" lib32 = "$(TOOLS32)\bin\tlib.exe" rc32 = "$(TOOLS32_rc)\bin\brcc32.exe" include32 = -I"$(TOOLS32)\include" libpath32 = -L"$(TOOLS32)\lib" # Uncomment the following line to compile with thread support #THREADDEFINES = -DTCL_THREADS=1 # Allow definition of NDEBUG via command line # Set NODEBUG to 0 to compile with symbols !if !defined(NODEBUG) NODEBUG = 1 !endif # CFG_ENCODING=encoding # name of encoding for configuration information. Defaults # to cp1252 !if !defined(CFG_ENCODING) CFG_ENCODING = \"cp1252\" !endif # The following defines can be used to control the amount of debugging # code that is added to the compilation. # # -DTCL_MEM_DEBUG Enables the debugging memory allocator. # -DTCL_COMPILE_DEBUG Enables byte compilation logging. # -DTCL_COMPILE_STATS Enables byte compilation statistics gathering. # -DUSE_TCLALLOC=0 Disables the Tcl memory allocator in favor # of the native malloc implementation. This is # needed when using Purify. # #DEBUGDEFINES = -DTCL_MEM_DEBUG -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS #DEBUGDEFINES = -DUSE_TCLALLOC=0 ###################################################################### # Do not modify below this line ###################################################################### NAMEPREFIX = tcl STUBPREFIX = $(NAMEPREFIX)stub DOTVERSION = 8.6 VERSION = 86 DDEVERSION = 14 DDEDOTVERSION = 1.4 REGVERSION = 13 REGDOTVERSION = 1.3 BINROOT = .. !IF "$(NODEBUG)" == "1" TMPDIRNAME = Release DBGX = SYMDEFINES = -DNDEBUG !ELSE TMPDIRNAME = Debug #DBGX = d DBGX = SYMDEFINES = -DTCL_CFG_DEBUG !ENDIF TMPDIR = $(BINROOT)\$(TMPDIRNAME) OUTDIRNAME = $(TMPDIRNAME) OUTDIR = $(TMPDIR) TCLLIB = $(OUTDIR)\$(NAMEPREFIX)$(VERSION)$(DBGX).lib TCLDLLNAME = $(NAMEPREFIX)$(VERSION)$(DBGX).dll TCLDLL = $(OUTDIR)\$(TCLDLLNAME) TCLSTUBLIBNAME = $(STUBPREFIX)$(VERSION)$(DBGX).lib TCLSTUBLIB = $(OUTDIR)\$(TCLSTUBLIBNAME) TCLPLUGINLIB = $(OUTDIR)\$(NAMEPREFIX)$(VERSION)p$(DBGX).lib TCLPLUGINDLLNAME = $(NAMEPREFIX)$(VERSION)p$(DBGX).dll TCLPLUGINDLL = $(OUTDIR)\$(TCLPLUGINDLLNAME) TCLSH = $(OUTDIR)\$(NAMEPREFIX)sh$(VERSION)$(DBGX).exe TCLSHP = $(OUTDIR)\$(NAMEPREFIX)shp$(VERSION)$(DBGX).exe TCLREGDLLNAME = $(NAMEPREFIX)reg$(REGVERSION)$(DBGX).dll TCLREGDLL = $(OUTDIR)\$(TCLREGDLLNAME) TCLDDEDLLNAME = $(NAMEPREFIX)dde$(DDEVERSION)$(DBGX).dll TCLDDEDLL = $(OUTDIR)\$(TCLDDEDLLNAME) TCLTEST = $(OUTDIR)\$(NAMEPREFIX)test.exe CAT32 = $(TMPDIR)\cat32.exe RMDIR = .\rmd.bat MKDIR = .\mkd.bat RM = del LIB_INSTALL_DIR = $(INSTALLDIR)\lib BIN_INSTALL_DIR = $(INSTALLDIR)\bin SCRIPT_INSTALL_DIR = $(INSTALLDIR)\lib\tcl$(DOTVERSION) INCLUDE_INSTALL_DIR = $(INSTALLDIR)\include TCLSHOBJS = \ $(TMPDIR)\tclAppInit.obj TCLTESTOBJS = \ $(TMPDIR)\tclTest.obj \ $(TMPDIR)\tclTestObj.obj \ $(TMPDIR)\tclTestProcBodyObj.obj \ $(TMPDIR)\tclThreadTest.obj \ $(TMPDIR)\tclWinTest.obj \ $(TMPDIR)\testMain.obj TCLOBJS = \ $(TMPDIR)\regcomp.obj \ $(TMPDIR)\regexec.obj \ $(TMPDIR)\regfree.obj \ $(TMPDIR)\regerror.obj \ $(TMPDIR)\tclAlloc.obj \ $(TMPDIR)\tclAsync.obj \ $(TMPDIR)\tclBasic.obj \ $(TMPDIR)\tclBinary.obj \ $(TMPDIR)\tclCkalloc.obj \ $(TMPDIR)\tclClock.obj \ $(TMPDIR)\tclCmdAH.obj \ $(TMPDIR)\tclCmdIL.obj \ $(TMPDIR)\tclCmdMZ.obj \ $(TMPDIR)\tclCompCmds.obj \ $(TMPDIR)\tclCompCmdsGR.obj \ $(TMPDIR)\tclCompCmdsSZ.obj \ $(TMPDIR)\tclCompExpr.obj \ $(TMPDIR)\tclCompile.obj \ $(TMPDIR)\tclConfig.obj \ $(TMPDIR)\tclDate.obj \ $(TMPDIR)\tclDictObj.obj \ $(TMPDIR)\tclDisassemble.obj \ $(TMPDIR)\tclEncoding.obj \ $(TMPDIR)\tclEnsemble.obj \ $(TMPDIR)\tclEnv.obj \ $(TMPDIR)\tclEvent.obj \ $(TMPDIR)\tclExecute.obj \ $(TMPDIR)\tclFCmd.obj \ $(TMPDIR)\tclFileName.obj \ $(TMPDIR)\tclGet.obj \ $(TMPDIR)\tclHash.obj \ $(TMPDIR)\tclHistory.obj \ $(TMPDIR)\tclIndexObj.obj \ $(TMPDIR)\tclInterp.obj \ $(TMPDIR)\tclIO.obj \ $(TMPDIR)\tclIOCmd.obj \ $(TMPDIR)\tclIOGT.obj \ $(TMPDIR)\tclIOSock.obj \ $(TMPDIR)\tclIOUtil.obj \ $(TMPDIR)\tclLink.obj \ $(TMPDIR)\tclLiteral.obj \ $(TMPDIR)\tclListObj.obj \ $(TMPDIR)\tclLoad.obj \ $(TMPDIR)\tclMain.obj \ $(TMPDIR)\tclNamesp.obj \ $(TMPDIR)\tclNotify.obj \ $(TMPDIR)\tclOO.obj \ $(TMPDIR)\tclOOBasic.obj \ $(TMPDIR)\tclOOCall.obj \ $(TMPDIR)\tclOODefineCmds.obj \ $(TMPDIR)\tclOOInfo.obj \ $(TMPDIR)\tclOOMethod.obj \ $(TMPDIR)\tclOOStubInit.obj \ $(TMPDIR)\tclObj.obj \ $(TMPDIR)\tclOptimize.obj \ $(TMPDIR)\tclPanic.obj \ $(TMPDIR)\tclParse.obj \ $(TMPDIR)\tclPipe.obj \ $(TMPDIR)\tclPkg.obj \ $(TMPDIR)\tclPkgConfig.obj \ $(TMPDIR)\tclPosixStr.obj \ $(TMPDIR)\tclPreserve.obj \ $(TMPDIR)\tclProc.obj \ $(TMPDIR)\tclRegexp.obj \ $(TMPDIR)\tclResolve.obj \ $(TMPDIR)\tclResult.obj \ $(TMPDIR)\tclScan.obj \ $(TMPDIR)\tclStringObj.obj \ $(TMPDIR)\tclStubInit.obj \ $(TMPDIR)\tclThread.obj \ $(TMPDIR)\tclThreadJoin.obj \ $(TMPDIR)\tclTimer.obj \ $(TMPDIR)\tclTrace.obj \ $(TMPDIR)\tclUtf.obj \ $(TMPDIR)\tclUtil.obj \ $(TMPDIR)\tclVar.obj \ $(TMPDIR)\tclWin32Dll.obj \ $(TMPDIR)\tclWinChan.obj \ $(TMPDIR)\tclWinConsole.obj \ $(TMPDIR)\tclWinSerial.obj \ $(TMPDIR)\tclWinError.obj \ $(TMPDIR)\tclWinFCmd.obj \ $(TMPDIR)\tclWinFile.obj \ $(TMPDIR)\tclWinInit.obj \ $(TMPDIR)\tclWinLoad.obj \ $(TMPDIR)\tclWinNotify.obj \ $(TMPDIR)\tclWinPipe.obj \ $(TMPDIR)\tclWinSock.obj \ $(TMPDIR)\tclWinThrd.obj \ $(TMPDIR)\tclWinTime.obj \ $(TMPDIR)\tclZlib.obj TCLSTUBOBJS = \ $(TMPDIR)\tclStubLib.obj \ $(TMPDIR)\tclTomMathStubLib.obj \ $(TMPDIR)\tclOOStubLib.obj WINDIR = $(ROOT)\win GENERICDIR = $(ROOT)\generic TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)" TCL_DEFINES = $(DEBUGDEFINES) $(THREADDEFINES) $(SYMDEFINES) \ $(PROFDEFINES) $(OPTDEFINES) $(SIXFOURDEFINES) \ -DTCL_CFGVAL_ENCODING=${CFG_ENCODING} ### TODO: Add -DHAVE_ZLIB=1 ###################################################################### # Compiler flags ###################################################################### !IF "$(NODEBUG)" == "1" # these macros cause maximum optimization and no symbols cdebug = -v- -vi- -O2 -D_DEBUG !ELSE # these macros enable debugging cdebug = -k -Od -r- -v -vi- -y !ENDIF SYSDEFINES = _MT;NO_STRICT;_NO_VCL # declarations common to all compiler options cbase = -c -q -3 -a4 -g0 -tWM -Ve -Vx -X- WARNINGS = -w-rch -w-pch -w-par -w-dup -w-pro -w-dpu ccons = -tWC INCLUDEPATH = $(include32) $(TCL_INCLUDES) CFLAGS = $(cdebug) $(cbase) $(INCLUDEPATH) $(WARNINGS) -D$(SYSDEFINES) TCL_CFLAGS = $(CFLAGS) $(TCL_DEFINES) CONS_CFLAGS = $(CFLAGS) $(TCL_DEFINES) $(ccons) ###################################################################### # Linker flags ###################################################################### !IF "$(NODEBUG)" == "1" ldebug = !ELSE ldebug = -v !ENDIF # declarations common to all linker options LNFLAGS = -D"" -Gn -I$(TMPDIR) -x $(ldebug) $(libpath32) # -Gi: create lib file (is -Gl in doc) # -aa: Windows app, -ap: Windows console app LNFLAGS_DLL = -ap -Gi -Tpd LNFLAGS_CONS = -ap -Tpe LNLIBS = import32 cw32mt ###################################################################### # Project specific targets ###################################################################### release: setup $(TCLSH) dlls dlls: setup $(TCLREGDLL) $(TCLDDEDLL) all: setup $(TCLSH) dlls $(CAT32) tcltest: setup $(TCLTEST) dlls $(CAT32) plugin: setup $(TCLPLUGINDLL) $(TCLSHP) install: install-binaries install-libraries test: setup $(TCLTEST) dlls $(CAT32) set TCL_LIBRARY=$(ROOT)/library $(TCLTEST) $(ROOT)/tests/all.tcl setup: @if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR) &\ echo *** Created directory '$(OUT_DIR)' @if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR) &\ echo *** Created directory '$(TMP_DIR)' $(TCLLIB): $(TCLDLL) $(TCLDLL): $(TCLOBJS) $(TMPDIR)\$(NAMEPREFIX).res $(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_DLL) $(TOOLS32)\lib\c0d32 @&&! $(TCLOBJS), $@, -x, $(LNLIBS),, $(TMPDIR)\$(NAMEPREFIX).res ! $(TCLSTUBLIB): $(TCLSTUBOBJS) $(lib32) /u $@ $(TCLSTUBOBJS) $(TCLPLUGINLIB): $(TCLPLUGINDLL) $(TCLPLUGINDLL): $(TCLOBJS) $(TMPDIR)\tcl.res $(link32) $(ldebug) $(dlllflags) \ -out:$@ $(TMPDIR)\tcl.res $(guilibsdll) @&&! $(TCLOBJS) ! $(TCLSH): $(TCLSHOBJS) $(TCLLIB) $(TMPDIR)\$(NAMEPREFIX)sh.res $(link32) $(ldebug) -S:2400000 $(LNFLAGS) $(LNFLAGS_CONS) $(TOOLS32)\lib\c0x32 @&&! $(TCLSHOBJS), $@, -x, $(LNLIBS) $(TCLLIB),, $(TMPDIR)\$(NAMEPREFIX)sh.res ! $(TCLSHP): $(TCLSHOBJS) $(TCLPLUGINLIB) $(TMPDIR)\tclsh.res $(link32) $(ldebug) $(conlflags) $(TMPDIR)\tclsh.res -stack:2300000 \ -out:$@ $(conlibsdll) $(TCLPLUGINLIB) $(TCLSHOBJS) $(TCLTEST): $(TCLTESTOBJS) $(TCLLIB) $(TMPDIR)\$(NAMEPREFIX)sh.res $(link32) $(ldebug) -S:2400000 $(LNFLAGS) $(LNFLAGS_CONS) $(TOOLS32)\lib\c0x32 @&&! $(TCLTESTOBJS), $@, -x, $(LNLIBS) $(TCLLIB),, $(TMPDIR)\$(NAMEPREFIX)sh.res ! $(TCLDDEDLL): $(TMPDIR)\tclWinDde.obj $(TCLSTUBLIB) $(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_DLL) $(TOOLS32)\lib\c0d32 \ $(TMPDIR)\tclWinDde.obj, $@, -x, $(LNLIBS) $(TCLSTUBLIB),, \ $(TMPDIR)\$(NAMEPREFIX).res $(TCLREGDLL): $(TMPDIR)\tclWinReg.obj $(TCLSTUBLIB) $(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_DLL) $(TOOLS32)\lib\c0d32 \ $(TMPDIR)\tclWinReg.obj, $@, -x, $(LNLIBS) $(TCLSTUBLIB),, \ $(TMPDIR)\$(NAMEPREFIX).res $(CAT32): $(WINDIR)\cat.c $(cc32) $(CONS_CFLAGS) -o$(TMPDIR)\cat.obj $? $(link32) $(ldebug) $(LNFLAGS) $(LNFLAGS_CONS) $(TOOLS32)\lib\c0x32 \ $(TMPDIR)\cat.obj, $@, -x, $(LNLIBS),, install-binaries: $(TCLSH) $(MKDIR) "$(BIN_INSTALL_DIR)" $(MKDIR) "$(LIB_INSTALL_DIR)" @echo Installing $(TCLDLLNAME) @copy "$(TCLDLL)" "$(BIN_INSTALL_DIR)" @copy "$(TCLLIB)" "$(LIB_INSTALL_DIR)" @echo Installing "$(TCLSH)" @copy "$(TCLSH)" "$(BIN_INSTALL_DIR)" @echo Installing $(TCLSTUBLIBNAME) @copy "$(TCLSTUBLIB)" "$(LIB_INSTALL_DIR)" @echo Installing $(WINDIR)\tclooConfig.sh @copy "$(WINDIR)\tclooConfig.sh" "$(LIB_INSTALL_DIR)" install-libraries: -@$(MKDIR) "$(LIB_INSTALL_DIR)" -@$(MKDIR) "$(INCLUDE_INSTALL_DIR)" -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)" @echo Installing http1.0 -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\http1.0" -@copy "$(ROOT)\library\http1.0\http.tcl" "$(SCRIPT_INSTALL_DIR)\http1.0" -@copy "$(ROOT)\library\http1.0\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\http1.0" @echo Installing http2.8 -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\http2.8" -@copy "$(ROOT)\library\http\http.tcl" "$(SCRIPT_INSTALL_DIR)\http2.8" -@copy "$(ROOT)\library\http\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\http2.8" @echo Installing opt0.4 -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\opt0.4" -@copy "$(ROOT)\library\opt\optparse.tcl" "$(SCRIPT_INSTALL_DIR)\opt0.4" -@copy "$(ROOT)\library\opt\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\opt0.4" @echo Installing msgcat1.5 -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\msgcat1.5" -@copy "$(ROOT)\library\msgcat\msgcat.tcl" "$(SCRIPT_INSTALL_DIR)\msgcat1.5" -@copy "$(ROOT)\library\msgcat\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\msgcat1.5" @echo Installing tcltest2.3 -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\tcltest2.3" -@copy "$(ROOT)\library\tcltest\tcltest.tcl" "$(SCRIPT_INSTALL_DIR)\tcltest2.3" -@copy "$(ROOT)\library\tcltest\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\tcltest2.3" @echo Installing platform1.0 -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\platform1.0" -@copy "$(ROOT)\library\platform\platform.tcl" "$(SCRIPT_INSTALL_DIR)\platform1.0" -@copy "$(ROOT)\library\platform\shell.tcl" "$(SCRIPT_INSTALL_DIR)\platform1.0" -@copy "$(ROOT)\library\platform\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\platform1.0" @echo Installing $(TCLDDEDLLNAME) -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\dde1.3" -@copy "$(TCLDDEDLL)" "$(SCRIPT_INSTALL_DIR)\dde1.3" -@copy "$(ROOT)\library\dde\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\dde1.3" @echo Installing $(TCLREGDLLNAME) -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\reg1.2" -@copy "$(TCLREGDLL)" "$(SCRIPT_INSTALL_DIR)\reg1.3" -@copy "$(ROOT)\library\reg\pkgIndex.tcl" "$(SCRIPT_INSTALL_DIR)\reg1.2" @echo Installing encoding files -@$(MKDIR) "$(SCRIPT_INSTALL_DIR)\encoding" -@copy "$(ROOT)\library\encoding\*.enc" "$(SCRIPT_INSTALL_DIR)\encoding" @echo Installing library files -@copy "$(GENERICDIR)\tcl.h" "$(INCLUDE_INSTALL_DIR)" -@copy "$(GENERICDIR)\tclDecls.h" "$(INCLUDE_INSTALL_DIR)" -@copy "$(GENERICDIR)\tclOO.h" "$(INCLUDE_INSTALL_DIR)" -@copy "$(GENERICDIR)\tclOODecls.h" "$(INCLUDE_INSTALL_DIR)" -@copy "$(GENERICDIR)\tclPlatDecls.h" "$(INCLUDE_INSTALL_DIR)" -@copy "$(ROOT)\library\history.tcl" "$(SCRIPT_INSTALL_DIR)" -@copy "$(ROOT)\library\init.tcl" "$(SCRIPT_INSTALL_DIR)" -@copy "$(ROOT)\library\parray.tcl" "$(SCRIPT_INSTALL_DIR)" -@copy "$(ROOT)\library\safe.tcl" "$(SCRIPT_INSTALL_DIR)" -@copy "$(ROOT)\library\tclIndex" "$(SCRIPT_INSTALL_DIR)" -@copy "$(ROOT)\library\package.tcl" "$(SCRIPT_INSTALL_DIR)" -@copy "$(ROOT)\library\word.tcl" "$(SCRIPT_INSTALL_DIR)" -@copy "$(ROOT)\library\auto.tcl" "$(SCRIPT_INSTALL_DIR)" # # Regenerate the stubs files. # genstubs: tclsh$(VERSION) $(ROOT)\tools\genStubs.tcl $(GENERICDIR) \ $(GENERICDIR)\tcl.decls $(GENERICDIR)\tclInt.decls # # Special case object file targets # $(TMPDIR)\tclWinInit.obj: $(WINDIR)\tclWinInit.c $(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$(TMPDIR)\$@ $? $(TMPDIR)\testMain.obj: $(WINDIR)\tclAppInit.c $(cc32) $(TCL_CFLAGS) -DTCL_TEST -o$(TMPDIR)\testMain.obj $? $(TMPDIR)\tclTest.obj: $(GENERICDIR)\tclTest.c $(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $? $(TMPDIR)\tclTestObj.obj: $(GENERICDIR)\tclTestObj.c $(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $? $(TMPDIR)\tclWinTest.obj: $(WINDIR)\tclWinTest.c $(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $? $(TMP_DIR)\tclPkgConfig.obj: $(GENERICDIR)\tclPkgConfig.c $(cc32) $(TCL_CFLAGS) \ -DCFG_INSTALL_EXEC_PREFIX=\"$(INSTALL_EXEC_PREFIX)\" \ -DCFG_INSTALL_PREFIX=\"$(INSTALL_PREFIX)\" \ -DCFG_RUNTIME_EXEC_PREFIX=\"$(RUNTIME_EXEC_PREFIX)\" \ -DCFG_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \ -o$(TMPDIR)\$@ $? $(TMPDIR)\tclAppInit.obj : $(WINDIR)\tclAppInit.c $(cc32) $(TCL_CFLAGS) -o$(TMPDIR)\$@ $? # The following objects should be built using the stub interfaces # tclWinReg: Produces errors in ANSI mode $(TMPDIR)\tclWinReg.obj : $(WINDIR)\tclWinReg.c $(cc32) $(TCL_CFLAGS) -DUSE_TCL_STUBS -o$(TMPDIR)\$@ $? # tclWinDde: Produces errors in ANSI mode $(TMPDIR)\tclWinDde.obj : $(WINDIR)\tclWinDde.c $(cc32) $(TCL_CFLAGS) -DUSE_TCL_STUBS -o$(TMPDIR)\$@ $? # The following objects are part of the stub library and should not # be built as DLL objects but none of the symbols should be exported $(TMPDIR)\tclStubLib.obj : $(GENERICDIR)\tclStubLib.c $(cc32) $(TCL_CFLAGS) -DSTATIC_BUILD -o$(TMPDIR)\$@ $? $(TMPDIR)\tclTomMathStubLib.obj : $(GENERICDIR)\tclTomMathStubLib.c $(cc32) $(TCL_CFLAGS) -DSTATIC_BUILD -o$(TMPDIR)\$@ $? $(TMPDIR)\tclOOStubLib.obj : $(GENERICDIR)\tclOOStubLib.c $(cc32) $(TCL_CFLAGS) -DSTATIC_BUILD -o$(TMPDIR)\$@ $? # Dedependency rules $(GENERICDIR)\regcomp.c: \ $(GENERICDIR)\regguts.h \ $(GENERICDIR)\regc_lex.c \ $(GENERICDIR)\regc_color.c \ $(GENERICDIR)\regc_nfa.c \ $(GENERICDIR)\regc_cvec.c \ $(GENERICDIR)\regc_locale.c $(GENERICDIR)\regcustom.h: \ $(GENERICDIR)\tclInt.h \ $(GENERICDIR)\tclPort.h \ $(GENERICDIR)\regex.h $(GENERICDIR)\regexec.c: \ $(GENERICDIR)\rege_dfa.c \ $(GENERICDIR)\regguts.h $(GENERICDIR)\regerror.c: $(GENERICDIR)\regguts.h $(GENERICDIR)\regfree.c: $(GENERICDIR)\regguts.h $(GENERICDIR)\regfronts.c: $(GENERICDIR)\regguts.h $(GENERICDIR)\regguts.h: $(GENERICDIR)\regcustom.h # # Implicit rules # {$(WINDIR)}.c{$(TMPDIR)}.obj: $(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$@ $< {$(GENERICDIR)}.c{$(TMPDIR)}.obj: $(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$@ $< {$(ROOT)\compat}.c{$(TMPDIR)}.obj: $(cc32) -DBUILD_tcl $(TCL_CFLAGS) -o$@ $< {$(WINDIR)}.rc{$(TMPDIR)}.res: $(rc32) $(INCLUDEPATH) -D$(USERDEFINES);$(SYSDEFINES) -fo$@ $< clean: -@$(RM) $(OUTDIR)\*.exp -@$(RM) $(OUTDIR)\*.lib -@$(RM) $(OUTDIR)\*.dll -@$(RM) $(OUTDIR)\*.exe -@$(RM) $(OUTDIR)\*.pdb -@$(RM) $(TMPDIR)\*.pch -@$(RM) $(TMPDIR)\*.obj -@$(RM) $(TMPDIR)\*.res -@$(RM) $(TMPDIR)\*.exe -@$(RMDIR) $(OUTDIR) -@$(RMDIR) $(TMPDIR) # Local Variables: # mode: makefile # End: tcl8.6.5/win/tcl.rc0000644000175000017500000000276012663660066013502 0ustar sergeisergei// Version Resource Script // #include #include // // build-up the name suffix that defines the type of build this is. // #if TCL_THREADS #define SUFFIX_THREADS "t" #else #define SUFFIX_THREADS "" #endif #if DEBUG && !UNCHECKED #define SUFFIX_DEBUG "g" #else #define SUFFIX_DEBUG "" #endif #define SUFFIX SUFFIX_THREADS SUFFIX_DEBUG LANGUAGE 0x9, 0x1 /* LANG_ENGLISH, SUBLANG_DEFAULT */ VS_VERSION_INFO VERSIONINFO FILEVERSION TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL PRODUCTVERSION TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL FILEFLAGSMASK 0x3fL #ifdef DEBUG FILEFLAGS VS_FF_DEBUG #else FILEFLAGS 0x0L #endif FILEOS VOS__WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */ BEGIN VALUE "FileDescription", "Tcl DLL\0" VALUE "OriginalFilename", "tcl" STRINGIFY(TCL_MAJOR_VERSION) STRINGIFY(TCL_MINOR_VERSION) SUFFIX ".dll\0" VALUE "CompanyName", "ActiveState Corporation\0" VALUE "FileVersion", TCL_PATCH_LEVEL VALUE "LegalCopyright", "Copyright \251 2001 by ActiveState Corporation, et al\0" VALUE "ProductName", "Tcl " TCL_VERSION " for Windows\0" VALUE "ProductVersion", TCL_PATCH_LEVEL END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END tcl8.6.5/win/tclWinTime.c0000644000175000017500000007730412663660066014623 0ustar sergeisergei/* * tclWinTime.c -- * * Contains Windows specific versions of Tcl functions that obtain time * values from the operating system. * * Copyright 1995-1998 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #define SECSPERDAY (60L * 60L * 24L) #define SECSPERYEAR (SECSPERDAY * 365L) #define SECSPER4YEAR (SECSPERYEAR * 4L + SECSPERDAY) /* * Number of samples over which to estimate the performance counter. */ #define SAMPLES 64 /* * The following arrays contain the day of year for the last day of each * month, where index 1 is January. */ static const int normalDays[] = { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 }; static const int leapDays[] = { -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; typedef struct ThreadSpecificData { char tzName[64]; /* Time zone name */ struct tm tm; /* time information */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * Data for managing high-resolution timers. */ typedef struct TimeInfo { CRITICAL_SECTION cs; /* Mutex guarding this structure. */ int initialized; /* Flag == 1 if this structure is * initialized. */ int perfCounterAvailable; /* Flag == 1 if the hardware has a performance * counter. */ HANDLE calibrationThread; /* Handle to the thread that keeps the virtual * clock calibrated. */ HANDLE readyEvent; /* System event used to trigger the requesting * thread when the clock calibration procedure * is initialized for the first time. */ HANDLE exitEvent; /* Event to signal out of an exit handler to * tell the calibration loop to terminate. */ LARGE_INTEGER nominalFreq; /* Nominal frequency of the system performance * counter, that is, the value returned from * QueryPerformanceFrequency. */ /* * The following values are used for calculating virtual time. Virtual * time is always equal to: * lastFileTime + (current perf counter - lastCounter) * * 10000000 / curCounterFreq * and lastFileTime and lastCounter are updated any time that virtual time * is returned to a caller. */ ULARGE_INTEGER fileTimeLastCall; LARGE_INTEGER perfCounterLastCall; LARGE_INTEGER curCounterFreq; /* * Data used in developing the estimate of performance counter frequency */ Tcl_WideUInt fileTimeSample[SAMPLES]; /* Last 64 samples of system time. */ Tcl_WideInt perfCounterSample[SAMPLES]; /* Last 64 samples of performance counter. */ int sampleNo; /* Current sample number. */ } TimeInfo; static TimeInfo timeInfo = { { NULL, 0, 0, NULL, NULL, 0 }, 0, 0, (HANDLE) NULL, (HANDLE) NULL, (HANDLE) NULL, #ifdef HAVE_CAST_TO_UNION (LARGE_INTEGER) (Tcl_WideInt) 0, (ULARGE_INTEGER) (DWORDLONG) 0, (LARGE_INTEGER) (Tcl_WideInt) 0, (LARGE_INTEGER) (Tcl_WideInt) 0, #else 0, 0, 0, 0, #endif { 0 }, { 0 }, 0 }; /* * Declarations for functions defined later in this file. */ static struct tm * ComputeGMT(const time_t *tp); static void StopCalibration(ClientData clientData); static DWORD WINAPI CalibrationThread(LPVOID arg); static void UpdateTimeEachSecond(void); static void ResetCounterSamples(Tcl_WideUInt fileTime, Tcl_WideInt perfCounter, Tcl_WideInt perfFreq); static Tcl_WideInt AccumulateSample(Tcl_WideInt perfCounter, Tcl_WideUInt fileTime); static void NativeScaleTime(Tcl_Time* timebuf, ClientData clientData); static void NativeGetTime(Tcl_Time* timebuf, ClientData clientData); /* * TIP #233 (Virtualized Time): Data for the time hooks, if any. */ Tcl_GetTimeProc *tclGetTimeProcPtr = NativeGetTime; Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime; ClientData tclTimeClientData = NULL; /* *---------------------------------------------------------------------- * * TclpGetSeconds -- * * This procedure returns the number of seconds from the epoch. On most * Unix systems the epoch is Midnight Jan 1, 1970 GMT. * * Results: * Number of seconds from the epoch. * * Side effects: * None. * *---------------------------------------------------------------------- */ unsigned long TclpGetSeconds(void) { Tcl_Time t; tclGetTimeProcPtr(&t, tclTimeClientData); /* Tcl_GetTime inlined. */ return t.sec; } /* *---------------------------------------------------------------------- * * TclpGetClicks -- * * This procedure returns a value that represents the highest resolution * clock available on the system. There are no guarantees on what the * resolution will be. In Tcl we will call this value a "click". The * start time is also system dependant. * * Results: * Number of clicks from some start time. * * Side effects: * None. * *---------------------------------------------------------------------- */ unsigned long TclpGetClicks(void) { /* * Use the Tcl_GetTime abstraction to get the time in microseconds, as * nearly as we can, and return it. */ Tcl_Time now; /* Current Tcl time */ unsigned long retval; /* Value to return */ tclGetTimeProcPtr(&now, tclTimeClientData); /* Tcl_GetTime inlined */ retval = (now.sec * 1000000) + now.usec; return retval; } /* *---------------------------------------------------------------------- * * Tcl_GetTime -- * * Gets the current system time in seconds and microseconds since the * beginning of the epoch: 00:00 UCT, January 1, 1970. * * Results: * Returns the current time in timePtr. * * Side effects: * On the first call, initializes a set of static variables to keep track * of the base value of the performance counter, the corresponding wall * clock (obtained through ftime) and the frequency of the performance * counter. Also spins a thread whose function is to wake up periodically * and monitor these values, adjusting them as necessary to correct for * drift in the performance counter's oscillator. * *---------------------------------------------------------------------- */ void Tcl_GetTime( Tcl_Time *timePtr) /* Location to store time information. */ { tclGetTimeProcPtr(timePtr, tclTimeClientData); } /* *---------------------------------------------------------------------- * * NativeScaleTime -- * * TIP #233: Scale from virtual time to the real-time. For native scaling * the relationship is 1:1 and nothing has to be done. * * Results: * Scales the time in timePtr. * * Side effects: * See above. * *---------------------------------------------------------------------- */ static void NativeScaleTime( Tcl_Time *timePtr, ClientData clientData) { /* * Native scale is 1:1. Nothing is done. */ } /* *---------------------------------------------------------------------- * * NativeGetTime -- * * TIP #233: Gets the current system time in seconds and microseconds * since the beginning of the epoch: 00:00 UCT, January 1, 1970. * * Results: * Returns the current time in timePtr. * * Side effects: * On the first call, initializes a set of static variables to keep track * of the base value of the performance counter, the corresponding wall * clock (obtained through ftime) and the frequency of the performance * counter. Also spins a thread whose function is to wake up periodically * and monitor these values, adjusting them as necessary to correct for * drift in the performance counter's oscillator. * *---------------------------------------------------------------------- */ static void NativeGetTime( Tcl_Time *timePtr, ClientData clientData) { struct _timeb t; int useFtime = 1; /* Flag == TRUE if we need to fall back on * ftime rather than using the perf counter. */ /* * Initialize static storage on the first trip through. * * Note: Outer check for 'initialized' is a performance win since it * avoids an extra mutex lock in the common case. */ if (!timeInfo.initialized) { TclpInitLock(); if (!timeInfo.initialized) { 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 != (Tcl_WideInt)1193182 * && timeInfo.nominalFreq.QuadPart != (Tcl_WideInt)3579545 */ && timeInfo.nominalFreq.QuadPart > (Tcl_WideInt) 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; unsigned 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 */ == 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) { DWORD id; InitializeCriticalSection(&timeInfo.cs); timeInfo.readyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); timeInfo.exitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); timeInfo.calibrationThread = CreateThread(NULL, 256, CalibrationThread, (LPVOID) NULL, 0, &id); SetThreadPriority(timeInfo.calibrationThread, THREAD_PRIORITY_HIGHEST); /* * Wait for the thread just launched to start running, and * create an exit handler that kills it so that it doesn't * outlive unloading tclXX.dll */ WaitForSingleObject(timeInfo.readyEvent, INFINITE); CloseHandle(timeInfo.readyEvent); Tcl_CreateExitHandler(StopCalibration, NULL); } timeInfo.initialized = TRUE; } TclpInitUnlock(); } if (timeInfo.perfCounterAvailable && timeInfo.curCounterFreq.QuadPart!=0) { /* * Query the performance counter and use it to calculate the current * time. */ LARGE_INTEGER curCounter; /* Current performance counter. */ Tcl_WideInt curFileTime;/* Current estimated time, expressed as 100-ns * ticks since the Windows epoch. */ static LARGE_INTEGER posixEpoch; /* Posix epoch expressed as 100-ns ticks since * the windows epoch. */ Tcl_WideInt usecSincePosixEpoch; /* Current microseconds since Posix epoch. */ posixEpoch.LowPart = 0xD53E8000; posixEpoch.HighPart = 0x019DB1DE; EnterCriticalSection(&timeInfo.cs); QueryPerformanceCounter(&curCounter); /* * If it appears to be more than 1.1 seconds since the last trip * through the calibration loop, the performance counter may have * jumped forward. (See MSDN Knowledge Base article Q274323 for a * description of the hardware problem that makes this test * necessary.) If the counter jumps, we don't want to use it directly. * Instead, we must return system time. Eventually, the calibration * loop should recover. */ if (curCounter.QuadPart - timeInfo.perfCounterLastCall.QuadPart < 11 * timeInfo.curCounterFreq.QuadPart / 10) { curFileTime = timeInfo.fileTimeLastCall.QuadPart + ((curCounter.QuadPart - timeInfo.perfCounterLastCall.QuadPart) * 10000000 / timeInfo.curCounterFreq.QuadPart); timeInfo.fileTimeLastCall.QuadPart = curFileTime; timeInfo.perfCounterLastCall.QuadPart = curCounter.QuadPart; usecSincePosixEpoch = (curFileTime - posixEpoch.QuadPart) / 10; timePtr->sec = (long) (usecSincePosixEpoch / 1000000); timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000); useFtime = 0; } LeaveCriticalSection(&timeInfo.cs); } if (useFtime) { /* * High resolution timer is not available. Just use ftime. */ _ftime(&t); timePtr->sec = (long)t.time; timePtr->usec = t.millitm * 1000; } } /* *---------------------------------------------------------------------- * * StopCalibration -- * * Turns off the calibration thread in preparation for exiting the * process. * * Results: * None. * * Side effects: * Sets the 'exitEvent' event in the 'timeInfo' structure to ask the * thread in question to exit, and waits for it to do so. * *---------------------------------------------------------------------- */ static void StopCalibration( ClientData unused) /* Client data is unused */ { SetEvent(timeInfo.exitEvent); /* * If Tcl_Finalize was called from DllMain, the calibration thread is in a * paused state so we need to timeout and continue. */ WaitForSingleObject(timeInfo.calibrationThread, 100); CloseHandle(timeInfo.exitEvent); CloseHandle(timeInfo.calibrationThread); } /* *---------------------------------------------------------------------- * * TclpGetDate -- * * This function converts between seconds and struct tm. If useGMT is * true, then the returned date will be in Greenwich Mean Time (GMT). * Otherwise, it will be in the local time zone. * * Results: * Returns a static tm structure. * * Side effects: * None. * *---------------------------------------------------------------------- */ struct tm * TclpGetDate( const time_t *t, int useGMT) { struct tm *tmPtr; time_t time; if (!useGMT) { tzset(); /* * If we are in the valid range, let the C run-time library handle it. * Otherwise we need to fake it. Note that this algorithm ignores * daylight savings time before the epoch. */ /* * Hm, Borland's localtime manages to return NULL under certain * circumstances (e.g. wintime.test, test 1.2). Nobody tests for this, * since 'localtime' isn't supposed to do this, possibly leading to * crashes. * * Patch: We only call this function if we are at least one day into * the epoch, else we handle it ourselves (like we do for times < 0). * H. Giese, June 2003 */ #ifdef __BORLANDC__ #define LOCALTIME_VALIDITY_BOUNDARY SECSPERDAY #else #define LOCALTIME_VALIDITY_BOUNDARY 0 #endif if (*t >= LOCALTIME_VALIDITY_BOUNDARY) { return TclpLocaltime(t); } time = *t - timezone; /* * If we aren't near to overflowing the long, just add the bias and * use the normal calculation. Otherwise we will need to adjust the * result at the end. */ if (*t < (LONG_MAX - 2*SECSPERDAY) && *t > (LONG_MIN + 2*SECSPERDAY)) { tmPtr = ComputeGMT(&time); } else { tmPtr = ComputeGMT(t); tzset(); /* * Add the bias directly to the tm structure to avoid overflow. * Propagate seconds overflow into minutes, hours and days. */ time = tmPtr->tm_sec - timezone; tmPtr->tm_sec = (int)(time % 60); if (tmPtr->tm_sec < 0) { tmPtr->tm_sec += 60; 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; tmPtr->tm_hour = (int)(time % 24); if (tmPtr->tm_hour < 0) { tmPtr->tm_hour += 24; time -= 24; } time /= 24; tmPtr->tm_mday += (int)time; tmPtr->tm_yday += (int)time; tmPtr->tm_wday = (tmPtr->tm_wday + (int)time) % 7; } } else { tmPtr = ComputeGMT(t); } return tmPtr; } /* *---------------------------------------------------------------------- * * ComputeGMT -- * * This function computes GMT given the number of seconds since the epoch * (midnight Jan 1 1970). * * Results: * Returns a (per thread) statically allocated struct tm. * * Side effects: * Updates the values of the static struct tm. * *---------------------------------------------------------------------- */ static struct tm * ComputeGMT( const time_t *tp) { struct tm *tmPtr; long tmp, rem; int isLeap; const int *days; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); tmPtr = &tsdPtr->tm; /* * Compute the 4 year span containing the specified time. */ tmp = (long)(*tp / SECSPER4YEAR); rem = (long)(*tp % SECSPER4YEAR); /* * Correct for weird mod semantics so the remainder is always positive. */ if (rem < 0) { tmp--; rem += SECSPER4YEAR; } /* * Compute the year after 1900 by taking the 4 year span and adjusting for * the remainder. This works because 2000 is a leap year, and 1900/2100 * are out of the range. */ tmp = (tmp * 4) + 70; isLeap = 0; if (rem >= SECSPERYEAR) { /* 1971, etc. */ tmp++; rem -= SECSPERYEAR; if (rem >= SECSPERYEAR) { /* 1972, etc. */ tmp++; rem -= SECSPERYEAR; if (rem >= SECSPERYEAR + SECSPERDAY) { /* 1973, etc. */ tmp++; rem -= SECSPERYEAR + SECSPERDAY; } else { isLeap = 1; } } } tmPtr->tm_year = tmp; /* * Compute the day of year and leave the seconds in the current day in the * remainder. */ tmPtr->tm_yday = rem / SECSPERDAY; rem %= SECSPERDAY; /* * Compute the time of day. */ tmPtr->tm_hour = rem / 3600; rem %= 3600; tmPtr->tm_min = rem / 60; tmPtr->tm_sec = rem % 60; /* * Compute the month and day of month. */ days = (isLeap) ? leapDays : normalDays; for (tmp = 1; days[tmp] < tmPtr->tm_yday; tmp++) { /* empty body */ } tmPtr->tm_mon = --tmp; tmPtr->tm_mday = tmPtr->tm_yday - days[tmp]; /* * Compute day of week. Epoch started on a Thursday. */ tmPtr->tm_wday = (long)(*tp / SECSPERDAY) + 4; if ((*tp % SECSPERDAY) < 0) { tmPtr->tm_wday--; } tmPtr->tm_wday %= 7; if (tmPtr->tm_wday < 0) { tmPtr->tm_wday += 7; } return tmPtr; } /* *---------------------------------------------------------------------- * * CalibrationThread -- * * Thread that manages calibration of the hi-resolution time derived from * the performance counter, to keep it synchronized with the system * clock. * * Parameters: * arg - Client data from the CreateThread call. This parameter points to * the static TimeInfo structure. * * Return value: * None. This thread embeds an infinite loop. * * Side effects: * At an interval of 1s, this thread performs virtual time discipline. * * Note: When this thread is entered, TclpInitLock has been called to * safeguard the static storage. There is therefore no synchronization in the * body of this procedure. * *---------------------------------------------------------------------- */ static DWORD WINAPI CalibrationThread( LPVOID arg) { FILETIME curFileTime; DWORD waitResult; /* * Get initial system time and performance counter. */ GetSystemTimeAsFileTime(&curFileTime); QueryPerformanceCounter(&timeInfo.perfCounterLastCall); QueryPerformanceFrequency(&timeInfo.curCounterFreq); timeInfo.fileTimeLastCall.LowPart = curFileTime.dwLowDateTime; timeInfo.fileTimeLastCall.HighPart = curFileTime.dwHighDateTime; ResetCounterSamples(timeInfo.fileTimeLastCall.QuadPart, timeInfo.perfCounterLastCall.QuadPart, timeInfo.curCounterFreq.QuadPart); /* * Wake up the calling thread. When it wakes up, it will release the * initialization lock. */ SetEvent(timeInfo.readyEvent); /* * Run the calibration once a second. */ while (timeInfo.perfCounterAvailable) { /* * If the exitEvent is set, break out of the loop. */ waitResult = WaitForSingleObjectEx(timeInfo.exitEvent, 1000, FALSE); if (waitResult == WAIT_OBJECT_0) { break; } UpdateTimeEachSecond(); } /* lint */ return (DWORD) 0; } /* *---------------------------------------------------------------------- * * UpdateTimeEachSecond -- * * Callback from the waitable timer in the clock calibration thread that * updates system time. * * Parameters: * info - Pointer to the static TimeInfo structure * * Results: * None. * * Side effects: * Performs virtual time calibration discipline. * *---------------------------------------------------------------------- */ static void UpdateTimeEachSecond(void) { LARGE_INTEGER curPerfCounter; /* Current value returned from * QueryPerformanceCounter. */ FILETIME curSysTime; /* Current system time. */ LARGE_INTEGER curFileTime; /* File time at the time this callback was * scheduled. */ Tcl_WideInt estFreq; /* Estimated perf counter frequency. */ Tcl_WideInt vt0; /* Tcl time right now. */ Tcl_WideInt vt1; /* Tcl time one second from now. */ Tcl_WideInt tdiff; /* Difference between system clock and Tcl * time. */ Tcl_WideInt driftFreq; /* Frequency needed to drift virtual time into * step over 1 second. */ /* * Sample performance counter and system time. */ QueryPerformanceCounter(&curPerfCounter); GetSystemTimeAsFileTime(&curSysTime); curFileTime.LowPart = curSysTime.dwLowDateTime; curFileTime.HighPart = curSysTime.dwHighDateTime; EnterCriticalSection(&timeInfo.cs); /* * We devide by timeInfo.curCounterFreq.QuadPart in several places. That * value should always be positive on a correctly functioning system. But * it is good to be defensive about such matters. So if something goes * wrong and the value does goes to zero, we clear the * timeInfo.perfCounterAvailable in order to cause the calibration thread * to shut itself down, then return without additional processing. */ if (timeInfo.curCounterFreq.QuadPart == 0){ LeaveCriticalSection(&timeInfo.cs); timeInfo.perfCounterAvailable = 0; return; } /* * Several things may have gone wrong here that have to be checked for. * (1) The performance counter may have jumped. * (2) The system clock may have been reset. * * In either case, we'll need to reinitialize the circular buffer with * samples relative to the current system time and the NOMINAL performance * frequency (not the actual, because the actual has probably run slow in * the first case). Our estimated frequency will be the nominal frequency. * * Store the current sample into the circular buffer of samples, and * estimate the performance counter frequency. */ estFreq = AccumulateSample(curPerfCounter.QuadPart, (Tcl_WideUInt) curFileTime.QuadPart); /* * We want to adjust things so that time appears to be continuous. * Virtual file time, right now, is * * vt0 = 10000000 * (curPerfCounter - perfCounterLastCall) * / curCounterFreq * + fileTimeLastCall * * Ideally, we would like to drift the clock into place over a period of 2 * sec, so that virtual time 2 sec from now will be * * vt1 = 20000000 + curFileTime * * The frequency that we need to use to drift the counter back into place * is estFreq * 20000000 / (vt1 - vt0) */ vt0 = 10000000 * (curPerfCounter.QuadPart - timeInfo.perfCounterLastCall.QuadPart) / timeInfo.curCounterFreq.QuadPart + timeInfo.fileTimeLastCall.QuadPart; vt1 = 20000000 + curFileTime.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, * compute the drift frequency and fill in everything. */ tdiff = vt0 - curFileTime.QuadPart; if (tdiff > 10000000 || tdiff < -10000000) { timeInfo.fileTimeLastCall.QuadPart = curFileTime.QuadPart; timeInfo.curCounterFreq.QuadPart = estFreq; } else { driftFreq = estFreq * 20000000 / (vt1 - vt0); if (driftFreq > 1003*estFreq/1000) { driftFreq = 1003*estFreq/1000; } else if (driftFreq < 997*estFreq/1000) { driftFreq = 997*estFreq/1000; } timeInfo.fileTimeLastCall.QuadPart = vt0; timeInfo.curCounterFreq.QuadPart = driftFreq; } timeInfo.perfCounterLastCall.QuadPart = curPerfCounter.QuadPart; LeaveCriticalSection(&timeInfo.cs); } /* *---------------------------------------------------------------------- * * ResetCounterSamples -- * * Fills the sample arrays in 'timeInfo' with dummy values that will * yield the current performance counter and frequency. * * Results: * None. * * Side effects: * The array of samples is filled in so that it appears that there are * SAMPLES samples at one-second intervals, separated by precisely the * given frequency. * *---------------------------------------------------------------------- */ static void ResetCounterSamples( Tcl_WideUInt fileTime, /* Current file time */ Tcl_WideInt perfCounter, /* Current performance counter */ Tcl_WideInt perfFreq) /* Target performance frequency */ { int i; for (i=SAMPLES-1 ; i>=0 ; --i) { timeInfo.perfCounterSample[i] = perfCounter; timeInfo.fileTimeSample[i] = fileTime; perfCounter -= perfFreq; fileTime -= 10000000; } timeInfo.sampleNo = 0; } /* *---------------------------------------------------------------------- * * AccumulateSample -- * * Updates the circular buffer of performance counter and system time * samples with a new data point. * * Results: * None. * * Side effects: * The new data point replaces the oldest point in the circular buffer, * and the descriptive statistics are updated to accumulate the new * point. * * Several things may have gone wrong here that have to be checked for. * (1) The performance counter may have jumped. * (2) The system clock may have been reset. * * In either case, we'll need to reinitialize the circular buffer with samples * relative to the current system time and the NOMINAL performance frequency * (not the actual, because the actual has probably run slow in the first * case). */ static Tcl_WideInt AccumulateSample( Tcl_WideInt perfCounter, Tcl_WideUInt fileTime) { Tcl_WideUInt workFTSample; /* File time sample being removed from or * added to the circular buffer. */ Tcl_WideInt workPCSample; /* Performance counter sample being removed * from or added to the circular buffer. */ Tcl_WideUInt lastFTSample; /* Last file time sample recorded */ Tcl_WideInt lastPCSample; /* Last performance counter sample recorded */ Tcl_WideInt FTdiff; /* Difference between last FT and current */ Tcl_WideInt PCdiff; /* Difference between last PC and current */ Tcl_WideInt estFreq; /* Estimated performance counter frequency */ /* * Test for jumps and reset the samples if we have one. */ if (timeInfo.sampleNo == 0) { lastPCSample = timeInfo.perfCounterSample[timeInfo.sampleNo + SAMPLES - 1]; lastFTSample = timeInfo.fileTimeSample[timeInfo.sampleNo + SAMPLES - 1]; } else { lastPCSample = timeInfo.perfCounterSample[timeInfo.sampleNo - 1]; lastFTSample = timeInfo.fileTimeSample[timeInfo.sampleNo - 1]; } PCdiff = perfCounter - lastPCSample; FTdiff = fileTime - lastFTSample; if (PCdiff < timeInfo.nominalFreq.QuadPart * 9 / 10 || PCdiff > timeInfo.nominalFreq.QuadPart * 11 / 10 || FTdiff < 9000000 || FTdiff > 11000000) { ResetCounterSamples(fileTime, perfCounter, timeInfo.nominalFreq.QuadPart); return timeInfo.nominalFreq.QuadPart; } else { /* * Estimate the frequency. */ workPCSample = timeInfo.perfCounterSample[timeInfo.sampleNo]; workFTSample = timeInfo.fileTimeSample[timeInfo.sampleNo]; estFreq = 10000000 * (perfCounter - workPCSample) / (fileTime - workFTSample); timeInfo.perfCounterSample[timeInfo.sampleNo] = perfCounter; timeInfo.fileTimeSample[timeInfo.sampleNo] = (Tcl_WideInt) fileTime; /* * Advance the sample number. */ if (++timeInfo.sampleNo >= SAMPLES) { timeInfo.sampleNo = 0; } return estFreq; } } /* *---------------------------------------------------------------------- * * TclpGmtime -- * * Wrapper around the 'gmtime' library function to make it thread safe. * * Results: * Returns a pointer to a 'struct tm' in thread-specific data. * * Side effects: * Invokes gmtime or gmtime_r as appropriate. * *---------------------------------------------------------------------- */ struct tm * TclpGmtime( const time_t *timePtr) /* Pointer to the number of seconds since the * local system's epoch */ { /* * The MS implementation of gmtime is thread safe because it returns the * time in a block of thread-local storage, and Windows does not provide a * Posix gmtime_r function. */ return gmtime(timePtr); } /* *---------------------------------------------------------------------- * * TclpLocaltime -- * * Wrapper around the 'localtime' library function to make it thread * safe. * * Results: * Returns a pointer to a 'struct tm' in thread-specific data. * * Side effects: * Invokes localtime or localtime_r as appropriate. * *---------------------------------------------------------------------- */ struct tm * TclpLocaltime( const time_t *timePtr) /* Pointer to the number of seconds since the * local system's epoch */ { /* * The MS implementation of localtime is thread safe because it returns * the time in a block of thread-local storage, and Windows does not * provide a Posix localtime_r function. */ return localtime(timePtr); } /* *---------------------------------------------------------------------- * * Tcl_SetTimeProc -- * * TIP #233 (Virtualized Time): Registers two handlers for the * virtualization of Tcl's access to time information. * * Results: * None. * * Side effects: * Remembers the handlers, alters core behaviour. * *---------------------------------------------------------------------- */ void Tcl_SetTimeProc( Tcl_GetTimeProc *getProc, Tcl_ScaleTimeProc *scaleProc, ClientData clientData) { tclGetTimeProcPtr = getProc; tclScaleTimeProcPtr = scaleProc; tclTimeClientData = clientData; } /* *---------------------------------------------------------------------- * * Tcl_QueryTimeProc -- * * TIP #233 (Virtualized Time): Query which time handlers are registered. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_QueryTimeProc( Tcl_GetTimeProc **getProc, Tcl_ScaleTimeProc **scaleProc, ClientData *clientData) { if (getProc) { *getProc = tclGetTimeProcPtr; } if (scaleProc) { *scaleProc = tclScaleTimeProcPtr; } if (clientData) { *clientData = tclTimeClientData; } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tclsh.rc0000644000175000017500000000362012663660066014031 0ustar sergeisergei// // Version Resource Script // #include #include // // build-up the name suffix that defines the type of build this is. // #if TCL_THREADS #define SUFFIX_THREADS "t" #else #define SUFFIX_THREADS "" #endif #if STATIC_BUILD #define SUFFIX_STATIC "s" #else #define SUFFIX_STATIC "" #endif #if DEBUG && !UNCHECKED #define SUFFIX_DEBUG "g" #else #define SUFFIX_DEBUG "" #endif #define SUFFIX SUFFIX_THREADS SUFFIX_STATIC SUFFIX_DEBUG LANGUAGE 0x9, 0x1 /* LANG_ENGLISH, SUBLANG_DEFAULT */ VS_VERSION_INFO VERSIONINFO FILEVERSION TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL PRODUCTVERSION TCL_MAJOR_VERSION,TCL_MINOR_VERSION,TCL_RELEASE_LEVEL,TCL_RELEASE_SERIAL FILEFLAGSMASK 0x3fL #ifdef DEBUG FILEFLAGS VS_FF_DEBUG #else FILEFLAGS 0x0L #endif FILEOS VOS__WINDOWS32 FILETYPE VFT_APP FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "Tclsh Application\0" VALUE "OriginalFilename", "tclsh" STRINGIFY(TCL_MAJOR_VERSION) STRINGIFY(TCL_MINOR_VERSION) SUFFIX ".exe\0" VALUE "CompanyName", "ActiveState Corporation\0" VALUE "FileVersion", TCL_PATCH_LEVEL VALUE "LegalCopyright", "Copyright \251 2000 by ActiveState Corporation, et al\0" VALUE "ProductName", "Tcl " TCL_VERSION " for Windows\0" VALUE "ProductVersion", TCL_PATCH_LEVEL END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END // // Icon // tclsh ICON DISCARDABLE "tclsh.ico" // // This is needed for Windows 8.1 onwards. // #ifndef RT_MANIFEST #define RT_MANIFEST 24 #endif #ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 #endif CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "tclsh.exe.manifest" tcl8.6.5/win/buildall.vc.bat0000644000175000017500000000536412663660066015264 0ustar sergeisergei@echo off :: This is an example batchfile for building everything. Please :: edit this (or make your own) for your needs and wants using :: the instructions for calling makefile.vc found in makefile.vc set SYMBOLS= :OPTIONS if "%1" == "/?" goto help if /i "%1" == "/help" goto help if %1.==symbols. goto SYMBOLS if %1.==debug. goto SYMBOLS goto OPTIONS_DONE :SYMBOLS set SYMBOLS=symbols shift goto OPTIONS :OPTIONS_DONE :: reset errorlevel cd > nul :: You might have installed your developer studio to add itself to the :: path or have already run vcvars32.bat. Testing these envars proves :: cl.exe and friends are in your path. :: if defined VCINSTALLDIR (goto :startBuilding) if defined MSDEVDIR (goto :startBuilding) if defined MSVCDIR (goto :startBuilding) if defined MSSDK (goto :startBuilding) if defined WINDOWSSDKDIR (goto :startBuilding) :: We need to run the development environment batch script that comes :: with developer studio (v4,5,6,7,etc...) All have it. This path :: might not be correct. You should call it yourself prior to running :: this batchfile. :: call "C:\Program Files\Microsoft Developer Studio\vc98\bin\vcvars32.bat" if errorlevel 1 (goto no_vcvars) :startBuilding echo. echo Sit back and have a cup of coffee while this grinds through ;) echo You asked for *everything*, remember? echo. title Building Tcl, please wait... :: makefile.vc uses this for its default anyways, but show its use here :: just to be explicit and convey understanding to the user. Setting :: the INSTALLDIR envar prior to running this batchfile affects all builds. :: if "%INSTALLDIR%" == "" set INSTALLDIR=C:\Program Files\Tcl :: Build the normal stuff along with the help file. :: set OPTS=none if not %SYMBOLS%.==. set OPTS=symbols nmake -nologo -f makefile.vc release htmlhelp OPTS=%OPTS% %1 if errorlevel 1 goto error :: Build the static core and shell. :: set OPTS=static,msvcrt if not %SYMBOLS%.==. set OPTS=symbols,static,msvcrt nmake -nologo -f makefile.vc shell OPTS=%OPTS% %1 if errorlevel 1 goto error set OPTS= set SYMBOLS= goto end :error echo *** BOOM! *** goto end :no_vcvars echo vcvars32.bat was not run prior to this batchfile, nor are the MS tools in your path. goto out :help title buildall.vc.bat help message echo usage: echo %0 : builds Tcl for all build types (do this first) echo %0 install : installs all the release builds (do this second) echo %0 symbols : builds Tcl for all debugging build types echo %0 symbols install : install all the debug builds. echo. goto out :end title Building Tcl, please wait... DONE! echo DONE! goto out :out pause title Command Prompt tcl8.6.5/win/tclWinChan.c0000644000175000017500000012113112663660066014562 0ustar sergeisergei/* * tclWinChan.c * * Channel drivers for Windows channels based on files, command pipes and * TCP sockets. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclWinInt.h" #include "tclIO.h" /* * State flags used in the info structures below. */ #define FILE_PENDING (1<<0) /* Message is pending in the queue. */ #define FILE_ASYNC (1<<1) /* Channel is non-blocking. */ #define FILE_APPEND (1<<2) /* File is in append mode. */ #define FILE_TYPE_SERIAL (FILE_TYPE_PIPE+1) #define FILE_TYPE_CONSOLE (FILE_TYPE_PIPE+2) /* * The following structure contains per-instance data for a file based channel. */ typedef struct FileInfo { Tcl_Channel channel; /* Pointer to channel structure. */ int validMask; /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which operations are valid on the file. */ int watchMask; /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which events should be reported. */ int flags; /* State flags, see above for a list. */ HANDLE handle; /* Input/output file. */ struct FileInfo *nextPtr; /* Pointer to next registered file. */ int dirty; /* Boolean flag. Set if the OS may have data * pending on the channel. */ } FileInfo; typedef struct ThreadSpecificData { /* * List of all file channels currently open. */ FileInfo *firstFilePtr; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * The following structure is what is added to the Tcl event queue when file * events are generated. */ typedef struct FileEvent { Tcl_Event header; /* Information that is standard for all * events. */ FileInfo *infoPtr; /* Pointer to file info structure. Note that * we still have to verify that the file * exists before dereferencing this * pointer. */ } FileEvent; /* * Static routines for this file: */ static int FileBlockProc(ClientData instanceData, int mode); static void FileChannelExitHandler(ClientData clientData); static void FileCheckProc(ClientData clientData, int flags); static int FileCloseProc(ClientData instanceData, Tcl_Interp *interp); static int FileEventProc(Tcl_Event *evPtr, int flags); static int FileGetHandleProc(ClientData instanceData, int direction, ClientData *handlePtr); static ThreadSpecificData *FileInit(void); static int FileInputProc(ClientData instanceData, char *buf, int toRead, int *errorCode); static int FileOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCode); static int FileSeekProc(ClientData instanceData, long offset, int mode, int *errorCode); static Tcl_WideInt FileWideSeekProc(ClientData instanceData, Tcl_WideInt offset, int mode, int *errorCode); static void FileSetupProc(ClientData clientData, int flags); static void FileWatchProc(ClientData instanceData, int mask); static void FileThreadActionProc(ClientData instanceData, int action); static int FileTruncateProc(ClientData instanceData, Tcl_WideInt length); static DWORD FileGetType(HANDLE handle); static int NativeIsComPort(const TCHAR *nativeName); /* * This structure describes the channel type structure for file based IO. */ static const Tcl_ChannelType fileChannelType = { "file", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ FileCloseProc, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ FileSeekProc, /* Seek proc. */ NULL, /* Set option proc. */ NULL, /* Get option proc. */ FileWatchProc, /* Set up the notifier to watch the channel. */ FileGetHandleProc, /* Get an OS handle from channel. */ NULL, /* close2proc. */ FileBlockProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ FileWideSeekProc, /* Wide seek proc. */ FileThreadActionProc, /* Thread action proc. */ FileTruncateProc /* Truncate proc. */ }; /* *---------------------------------------------------------------------- * * FileInit -- * * This function creates the window used to simulate file events. * * Results: * None. * * Side effects: * Creates a new window and creates an exit handler. * *---------------------------------------------------------------------- */ static ThreadSpecificData * FileInit(void) { ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey); if (tsdPtr == NULL) { tsdPtr = TCL_TSD_INIT(&dataKey); tsdPtr->firstFilePtr = NULL; Tcl_CreateEventSource(FileSetupProc, FileCheckProc, NULL); Tcl_CreateThreadExitHandler(FileChannelExitHandler, NULL); } return tsdPtr; } /* *---------------------------------------------------------------------- * * FileChannelExitHandler -- * * This function is called to cleanup the channel driver before Tcl is * unloaded. * * Results: * None. * * Side effects: * Destroys the communication window. * *---------------------------------------------------------------------- */ static void FileChannelExitHandler( ClientData clientData) /* Old window proc */ { Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL); } /* *---------------------------------------------------------------------- * * FileSetupProc -- * * This function is invoked before Tcl_DoOneEvent blocks waiting for an * event. * * Results: * None. * * Side effects: * Adjusts the block time if needed. * *---------------------------------------------------------------------- */ void FileSetupProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { FileInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } /* * Check to see if there is a ready file. If so, poll. */ for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->watchMask) { Tcl_SetMaxBlockTime(&blockTime); break; } } } /* *---------------------------------------------------------------------- * * FileCheckProc -- * * This function is called by Tcl_DoOneEvent to check the file event * source for events. * * Results: * None. * * Side effects: * May queue an event. * *---------------------------------------------------------------------- */ static void FileCheckProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { FileEvent *evPtr; FileInfo *infoPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } /* * Queue events for any ready files that don't already have events queued * (caused by persistent states that won't generate WinSock events). */ for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->watchMask && !(infoPtr->flags & FILE_PENDING)) { infoPtr->flags |= FILE_PENDING; evPtr = ckalloc(sizeof(FileEvent)); evPtr->header.proc = FileEventProc; evPtr->infoPtr = infoPtr; Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL); } } } /* *---------------------------------------------------------------------- * * FileEventProc -- * * This function is invoked by Tcl_ServiceEvent when a file event reaches * the front of the event queue. This function invokes Tcl_NotifyChannel * on the file. * * Results: * Returns 1 if the event was handled, meaning it should be removed from * the queue. Returns 0 if the event was not handled, meaning it should * stay on the queue. The only time the event isn't handled is if the * TCL_FILE_EVENTS flag bit isn't set. * * Side effects: * Whatever the notifier callback does. * *---------------------------------------------------------------------- */ static int FileEventProc( Tcl_Event *evPtr, /* Event to service. */ int flags) /* Flags that indicate what events to handle, * such as TCL_FILE_EVENTS. */ { FileEvent *fileEvPtr = (FileEvent *)evPtr; FileInfo *infoPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; } /* * Search through the list of watched files for the one whose handle * matches the event. We do this rather than simply dereferencing the * handle in the event so that files can be deleted while the event is in * the queue. */ for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (fileEvPtr->infoPtr == infoPtr) { infoPtr->flags &= ~(FILE_PENDING); Tcl_NotifyChannel(infoPtr->channel, infoPtr->watchMask); break; } } return 1; } /* *---------------------------------------------------------------------- * * FileBlockProc -- * * Set blocking or non-blocking mode on channel. * * Results: * 0 if successful, errno when failed. * * Side effects: * Sets the device into blocking or non-blocking mode. * *---------------------------------------------------------------------- */ static int FileBlockProc( ClientData instanceData, /* Instance data for channel. */ int mode) /* TCL_MODE_BLOCKING or * TCL_MODE_NONBLOCKING. */ { FileInfo *infoPtr = instanceData; /* * Files on Windows can not be switched between blocking and nonblocking, * hence we have to emulate the behavior. This is done in the input * function by checking against a bit in the state. We set or unset the * bit here to cause the input function to emulate the correct behavior. */ if (mode == TCL_MODE_NONBLOCKING) { infoPtr->flags |= FILE_ASYNC; } else { infoPtr->flags &= ~(FILE_ASYNC); } return 0; } /* *---------------------------------------------------------------------- * * FileCloseProc -- * * Closes the IO channel. * * Results: * 0 if successful, the value of errno if failed. * * Side effects: * Closes the physical channel * *---------------------------------------------------------------------- */ static int FileCloseProc( ClientData instanceData, /* Pointer to FileInfo structure. */ Tcl_Interp *interp) /* Not used. */ { FileInfo *fileInfoPtr = instanceData; FileInfo *infoPtr; ThreadSpecificData *tsdPtr; int errorCode = 0; /* * Remove the file from the watch list. */ FileWatchProc(instanceData, 0); /* * Don't close the Win32 handle if the handle is a standard channel during * the thread exit process. Otherwise, one thread may kill the stdio of * another. */ if (!TclInThreadExit() || ((GetStdHandle(STD_INPUT_HANDLE) != fileInfoPtr->handle) && (GetStdHandle(STD_OUTPUT_HANDLE) != fileInfoPtr->handle) && (GetStdHandle(STD_ERROR_HANDLE) != fileInfoPtr->handle))) { if (CloseHandle(fileInfoPtr->handle) == FALSE) { TclWinConvertError(GetLastError()); errorCode = errno; } } /* * See if this FileInfo* is still on the thread local list. */ tsdPtr = TCL_TSD_INIT(&dataKey); for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr == fileInfoPtr) { /* * This channel exists on the thread local list. It should have * been removed by an earlier Threadaction call, but do that now * since just deallocating fileInfoPtr would leave an deallocated * pointer on the thread local list. */ FileThreadActionProc(fileInfoPtr,TCL_CHANNEL_THREAD_REMOVE); break; } } ckfree(fileInfoPtr); return errorCode; } /* *---------------------------------------------------------------------- * * FileSeekProc -- * * Seeks on a file-based channel. Returns the new position. * * Results: * -1 if failed, the new position if successful. If failed, it also sets * *errorCodePtr to the error code. * * Side effects: * Moves the location at which the channel will be accessed in future * operations. * *---------------------------------------------------------------------- */ static int FileSeekProc( ClientData instanceData, /* File state. */ long offset, /* Offset to seek to. */ int mode, /* Relative to where should we seek? */ int *errorCodePtr) /* To store error code. */ { FileInfo *infoPtr = instanceData; LONG newPos, newPosHigh, oldPos, oldPosHigh; DWORD moveMethod; *errorCodePtr = 0; if (mode == SEEK_SET) { moveMethod = FILE_BEGIN; } else if (mode == SEEK_CUR) { moveMethod = FILE_CURRENT; } else { moveMethod = FILE_END; } /* * Save our current place in case we need to roll-back the seek. */ oldPosHigh = 0; oldPos = SetFilePointer(infoPtr->handle, 0, &oldPosHigh, FILE_CURRENT); if (oldPos == (LONG)INVALID_SET_FILE_POINTER) { DWORD winError = GetLastError(); if (winError != NO_ERROR) { TclWinConvertError(winError); *errorCodePtr = errno; return -1; } } newPosHigh = (offset < 0 ? -1 : 0); newPos = SetFilePointer(infoPtr->handle, offset, &newPosHigh, moveMethod); if (newPos == (LONG)INVALID_SET_FILE_POINTER) { DWORD winError = GetLastError(); if (winError != NO_ERROR) { TclWinConvertError(winError); *errorCodePtr = errno; return -1; } } /* * Check for expressability in our return type, and roll-back otherwise. */ if (newPosHigh != 0) { *errorCodePtr = EOVERFLOW; SetFilePointer(infoPtr->handle, oldPos, &oldPosHigh, FILE_BEGIN); return -1; } return (int) newPos; } /* *---------------------------------------------------------------------- * * FileWideSeekProc -- * * Seeks on a file-based channel. Returns the new position. * * Results: * -1 if failed, the new position if successful. If failed, it also sets * *errorCodePtr to the error code. * * Side effects: * Moves the location at which the channel will be accessed in future * operations. * *---------------------------------------------------------------------- */ static Tcl_WideInt FileWideSeekProc( ClientData instanceData, /* File state. */ Tcl_WideInt offset, /* Offset to seek to. */ int mode, /* Relative to where should we seek? */ int *errorCodePtr) /* To store error code. */ { FileInfo *infoPtr = instanceData; DWORD moveMethod; LONG newPos, newPosHigh; *errorCodePtr = 0; if (mode == SEEK_SET) { moveMethod = FILE_BEGIN; } else if (mode == SEEK_CUR) { moveMethod = FILE_CURRENT; } else { moveMethod = FILE_END; } newPosHigh = Tcl_WideAsLong(offset >> 32); newPos = SetFilePointer(infoPtr->handle, Tcl_WideAsLong(offset), &newPosHigh, moveMethod); if (newPos == (LONG)INVALID_SET_FILE_POINTER) { DWORD winError = GetLastError(); if (winError != NO_ERROR) { TclWinConvertError(winError); *errorCodePtr = errno; return -1; } } return (((Tcl_WideInt)((unsigned)newPos)) | (Tcl_LongAsWide(newPosHigh) << 32)); } /* *---------------------------------------------------------------------- * * FileTruncateProc -- * * Truncates a file-based channel. Returns the error code. * * Results: * 0 if successful, POSIX-y error code if it failed. * * Side effects: * Truncates the file, may move file pointers too. * *---------------------------------------------------------------------- */ static int FileTruncateProc( ClientData instanceData, /* File state. */ Tcl_WideInt length) /* Length to truncate at. */ { FileInfo *infoPtr = instanceData; LONG newPos, newPosHigh, oldPos, oldPosHigh; /* * Save where we were... */ oldPosHigh = 0; oldPos = SetFilePointer(infoPtr->handle, 0, &oldPosHigh, FILE_CURRENT); if (oldPos == (LONG)INVALID_SET_FILE_POINTER) { DWORD winError = GetLastError(); if (winError != NO_ERROR) { TclWinConvertError(winError); return errno; } } /* * Move to where we want to truncate */ newPosHigh = Tcl_WideAsLong(length >> 32); newPos = SetFilePointer(infoPtr->handle, Tcl_WideAsLong(length), &newPosHigh, FILE_BEGIN); if (newPos == (LONG)INVALID_SET_FILE_POINTER) { DWORD winError = GetLastError(); if (winError != NO_ERROR) { TclWinConvertError(winError); return errno; } } /* * Perform the truncation (unlike POSIX ftruncate(), we needed to move to * the location to truncate at first). */ if (!SetEndOfFile(infoPtr->handle)) { TclWinConvertError(GetLastError()); return errno; } /* * Move back. If this last step fails, we don't care; it's just a "best * effort" attempt to restore our file pointer to where it was. */ SetFilePointer(infoPtr->handle, oldPos, &oldPosHigh, FILE_BEGIN); return 0; } /* *---------------------------------------------------------------------- * * FileInputProc -- * * Reads input from the IO channel into the buffer given. Returns count * of how many bytes were actually read, and an error indication. * * Results: * A count of how many bytes were read is returned and an error * indication is returned in an output argument. * * Side effects: * Reads input from the actual channel. * *---------------------------------------------------------------------- */ static int FileInputProc( ClientData instanceData, /* File state. */ char *buf, /* Where to store data read. */ int bufSize, /* Num bytes available in buffer. */ int *errorCode) /* Where to store error code. */ { FileInfo *infoPtr = instanceData; DWORD bytesRead; *errorCode = 0; /* * TODO: This comment appears to be out of date. We *do* have a * console driver, over in tclWinConsole.c. After some Windows * developer confirms, this comment should be revised. * * Note that we will block on reads from a console buffer until a full * line has been entered. The only way I know of to get around this is to * write a console driver. We should probably do this at some point, but * for now, we just block. The same problem exists for files being read * over the network. */ if (ReadFile(infoPtr->handle, (LPVOID) buf, (DWORD) bufSize, &bytesRead, (LPOVERLAPPED) NULL) != FALSE) { return bytesRead; } TclWinConvertError(GetLastError()); *errorCode = errno; if (errno == EPIPE) { return 0; } return -1; } /* *---------------------------------------------------------------------- * * FileOutputProc -- * * Writes the given output on the IO channel. Returns count of how many * characters were actually written, and an error indication. * * Results: * A count of how many characters were written is returned and an error * indication is returned in an output argument. * * Side effects: * Writes output on the actual channel. * *---------------------------------------------------------------------- */ static int FileOutputProc( ClientData instanceData, /* File state. */ const char *buf, /* The data buffer. */ int toWrite, /* How many bytes to write? */ int *errorCode) /* Where to store error code. */ { FileInfo *infoPtr = instanceData; DWORD bytesWritten; *errorCode = 0; /* * If we are writing to a file that was opened with O_APPEND, we need to * seek to the end of the file before writing the current buffer. */ if (infoPtr->flags & FILE_APPEND) { SetFilePointer(infoPtr->handle, 0, NULL, FILE_END); } if (WriteFile(infoPtr->handle, (LPVOID) buf, (DWORD) toWrite, &bytesWritten, (LPOVERLAPPED) NULL) == FALSE) { TclWinConvertError(GetLastError()); *errorCode = errno; return -1; } infoPtr->dirty = 1; return bytesWritten; } /* *---------------------------------------------------------------------- * * FileWatchProc -- * * Called by the notifier to set up to watch for events on this channel. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void FileWatchProc( ClientData instanceData, /* File state. */ int mask) /* What events to watch for; OR-ed combination * of TCL_READABLE, TCL_WRITABLE and * TCL_EXCEPTION. */ { FileInfo *infoPtr = instanceData; Tcl_Time blockTime = { 0, 0 }; /* * Since the file is always ready for events, we set the block time to * zero so we will poll. */ infoPtr->watchMask = mask & infoPtr->validMask; if (infoPtr->watchMask) { Tcl_SetMaxBlockTime(&blockTime); } } /* *---------------------------------------------------------------------- * * FileGetHandleProc -- * * Called from Tcl_GetChannelHandle to retrieve OS handles from a file * based channel. * * Results: * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if there is no * handle for the specified direction. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FileGetHandleProc( ClientData instanceData, /* The file state. */ int direction, /* TCL_READABLE or TCL_WRITABLE */ ClientData *handlePtr) /* Where to store the handle. */ { FileInfo *infoPtr = instanceData; if (direction & infoPtr->validMask) { *handlePtr = (ClientData) infoPtr->handle; return TCL_OK; } else { return TCL_ERROR; } } /* *---------------------------------------------------------------------- * * TclpOpenFileChannel -- * * Open an File based channel on Unix systems. * * Results: * The new channel or NULL. If NULL, the output argument errorCodePtr is * set to a POSIX error. * * Side effects: * May open the channel and may cause creation of a file on the file * system. * *---------------------------------------------------------------------- */ Tcl_Channel TclpOpenFileChannel( Tcl_Interp *interp, /* Interpreter for error reporting; can be * NULL. */ Tcl_Obj *pathPtr, /* Name of file to open. */ int mode, /* POSIX mode. */ int permissions) /* If the open involves creating a file, with * what modes to create it? */ { Tcl_Channel channel = 0; int channelPermissions = 0; DWORD accessMode = 0, createMode, shareMode, flags; const TCHAR *nativeName; HANDLE handle; char channelName[16 + TCL_INTEGER_SPACE]; TclFile readFile = NULL, writeFile = NULL; nativeName = Tcl_FSGetNativePath(pathPtr); if (nativeName == NULL) { if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "couldn't open \"", TclGetString(pathPtr), "\": filename is invalid on this platform", NULL); } return NULL; } switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) { case O_RDONLY: accessMode = GENERIC_READ; channelPermissions = TCL_READABLE; break; case O_WRONLY: accessMode = GENERIC_WRITE; channelPermissions = TCL_WRITABLE; break; case O_RDWR: accessMode = (GENERIC_READ | GENERIC_WRITE); channelPermissions = (TCL_READABLE | TCL_WRITABLE); break; default: Tcl_Panic("TclpOpenFileChannel: invalid mode value"); break; } /* * Map the creation flags to the NT create mode. */ switch (mode & (O_CREAT | O_EXCL | O_TRUNC)) { case (O_CREAT | O_EXCL): case (O_CREAT | O_EXCL | O_TRUNC): createMode = CREATE_NEW; break; case (O_CREAT | O_TRUNC): createMode = CREATE_ALWAYS; break; case O_CREAT: createMode = OPEN_ALWAYS; break; case O_TRUNC: case (O_TRUNC | O_EXCL): createMode = TRUNCATE_EXISTING; break; default: createMode = OPEN_EXISTING; break; } /* * [2413550] Avoid double-open of serial ports on Windows * Special handling for Windows serial ports by a "name-hint" * to directly open it with the OVERLAPPED flag set. */ if( NativeIsComPort(nativeName) ) { handle = TclWinSerialOpen(INVALID_HANDLE_VALUE, nativeName, accessMode); if (handle == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "couldn't open serial \"", TclGetString(pathPtr), "\": ", Tcl_PosixError(interp), NULL); } return NULL; } /* * For natively named Windows serial ports we are done. */ channel = TclWinOpenSerialChannel(handle, channelName, channelPermissions); return channel; } /* * If the file is being created, get the file attributes from the * permissions argument, else use the existing file attributes. */ if (mode & O_CREAT) { if (permissions & S_IWRITE) { flags = FILE_ATTRIBUTE_NORMAL; } else { flags = FILE_ATTRIBUTE_READONLY; } } else { flags = GetFileAttributes(nativeName); if (flags == 0xFFFFFFFF) { flags = 0; } } /* * Set up the file sharing mode. We want to allow simultaneous access. */ shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; /* * Now we get to create the file. */ handle = CreateFile(nativeName, accessMode, shareMode, NULL, createMode, flags, (HANDLE) NULL); if (handle == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); if ((err & 0xffffL) == ERROR_OPEN_FAILED) { err = (mode & O_CREAT) ? ERROR_FILE_EXISTS : ERROR_FILE_NOT_FOUND; } TclWinConvertError(err); if (interp != (Tcl_Interp *) NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); } return NULL; } channel = NULL; switch (FileGetType(handle)) { case FILE_TYPE_SERIAL: /* * Natively named serial ports "com1-9", "\\\\.\\comXX" are * already done with the code above. * Here we handle all other serial port names. * * Reopen channel for OVERLAPPED operation. Normally this shouldn't * fail, because the channel exists. */ handle = TclWinSerialOpen(handle, nativeName, accessMode); if (handle == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); if (interp != (Tcl_Interp *) NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't reopen serial \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); } return NULL; } channel = TclWinOpenSerialChannel(handle, channelName, channelPermissions); break; case FILE_TYPE_CONSOLE: channel = TclWinOpenConsoleChannel(handle, channelName, channelPermissions); break; case FILE_TYPE_PIPE: if (channelPermissions & TCL_READABLE) { readFile = TclWinMakeFile(handle); } if (channelPermissions & TCL_WRITABLE) { writeFile = TclWinMakeFile(handle); } channel = TclpCreateCommandChannel(readFile, writeFile, NULL, 0, NULL); break; case FILE_TYPE_CHAR: case FILE_TYPE_DISK: case FILE_TYPE_UNKNOWN: channel = TclWinOpenFileChannel(handle, channelName, channelPermissions, (mode & O_APPEND) ? FILE_APPEND : 0); break; default: /* * The handle is of an unknown type, probably /dev/nul equivalent or * possibly a closed handle. */ channel = NULL; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open \"%s\": bad file type", TclGetString(pathPtr))); Tcl_SetErrorCode(interp, "TCL", "VALUE", "CHANNEL", "BAD_TYPE", NULL); break; } return channel; } /* *---------------------------------------------------------------------- * * Tcl_MakeFileChannel -- * * Creates a Tcl_Channel from an existing platform specific file handle. * * Results: * The Tcl_Channel created around the preexisting file. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_MakeFileChannel( ClientData rawHandle, /* OS level handle */ int mode) /* ORed combination of TCL_READABLE and * TCL_WRITABLE to indicate file mode. */ { #if defined(HAVE_NO_SEH) && !defined(_WIN64) TCLEXCEPTION_REGISTRATION registration; #endif char channelName[16 + TCL_INTEGER_SPACE]; Tcl_Channel channel = NULL; HANDLE handle = (HANDLE) rawHandle; HANDLE dupedHandle; TclFile readFile = NULL, writeFile = NULL; BOOL result; if (mode == 0) { return NULL; } switch (FileGetType(handle)) { case FILE_TYPE_SERIAL: channel = TclWinOpenSerialChannel(handle, channelName, mode); break; case FILE_TYPE_CONSOLE: channel = TclWinOpenConsoleChannel(handle, channelName, mode); break; case FILE_TYPE_PIPE: if (mode & TCL_READABLE) { readFile = TclWinMakeFile(handle); } if (mode & TCL_WRITABLE) { writeFile = TclWinMakeFile(handle); } channel = TclpCreateCommandChannel(readFile, writeFile, NULL, 0, NULL); break; case FILE_TYPE_DISK: case FILE_TYPE_CHAR: channel = TclWinOpenFileChannel(handle, channelName, mode, 0); break; case FILE_TYPE_UNKNOWN: default: /* * The handle is of an unknown type. Test the validity of this OS * handle by duplicating it, then closing the dupe. The Win32 API * doesn't provide an IsValidHandle() function, so we have to emulate * it here. This test will not work on a console handle reliably, * which is why we can't test every handle that comes into this * function in this way. */ result = DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &dupedHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); if (result == 0) { /* * Unable to make a duplicate. It's definately invalid at this * point. */ return NULL; } /* * Use structured exception handling (Win32 SEH) to protect the close * of this duped handle which might throw EXCEPTION_INVALID_HANDLE. */ result = 0; #if defined(HAVE_NO_SEH) && !defined(_WIN64) /* * Don't have SEH available, do things the hard way. Note that this * needs to be one block of asm, to avoid stack imbalance; also, it is * illegal for one asm block to contain a jump to another. */ __asm__ __volatile__ ( /* * Pick up parameters before messing with the stack */ "movl %[dupedHandle], %%ebx" "\n\t" /* * Construct an TCLEXCEPTION_REGISTRATION to protect the call to * CloseHandle. */ "leal %[registration], %%edx" "\n\t" "movl %%fs:0, %%eax" "\n\t" "movl %%eax, 0x0(%%edx)" "\n\t" /* link */ "leal 1f, %%eax" "\n\t" "movl %%eax, 0x4(%%edx)" "\n\t" /* handler */ "movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */ "movl %%esp, 0xc(%%edx)" "\n\t" /* esp */ "movl $0, 0x10(%%edx)" "\n\t" /* status */ /* * Link the TCLEXCEPTION_REGISTRATION on the chain. */ "movl %%edx, %%fs:0" "\n\t" /* * Call CloseHandle(dupedHandle). */ "pushl %%ebx" "\n\t" "call _CloseHandle@4" "\n\t" /* * Come here on normal exit. Recover the TCLEXCEPTION_REGISTRATION * and put a TRUE status return into it. */ "movl %%fs:0, %%edx" "\n\t" "movl $1, %%eax" "\n\t" "movl %%eax, 0x10(%%edx)" "\n\t" "jmp 2f" "\n" /* * Come here on an exception. Recover the TCLEXCEPTION_REGISTRATION */ "1:" "\t" "movl %%fs:0, %%edx" "\n\t" "movl 0x8(%%edx), %%edx" "\n\t" /* * Come here however we exited. Restore context from the * TCLEXCEPTION_REGISTRATION in case the stack is unbalanced. */ "2:" "\t" "movl 0xc(%%edx), %%esp" "\n\t" "movl 0x8(%%edx), %%ebp" "\n\t" "movl 0x0(%%edx), %%eax" "\n\t" "movl %%eax, %%fs:0" "\n\t" : /* No outputs */ : [registration] "m" (registration), [dupedHandle] "m" (dupedHandle) : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory" ); result = registration.status; #else #ifndef HAVE_NO_SEH __try { #endif CloseHandle(dupedHandle); result = 1; #ifndef HAVE_NO_SEH } __except (EXCEPTION_EXECUTE_HANDLER) {} #endif #endif if (result == FALSE) { return NULL; } /* * Fall through, the handle is valid. * * Create the undefined channel, anyways, because we know the handle * is valid to something. */ channel = TclWinOpenFileChannel(handle, channelName, mode, 0); } return channel; } /* *---------------------------------------------------------------------- * * TclpGetDefaultStdChannel -- * * Constructs a channel for the specified standard OS handle. * * Results: * Returns the specified default standard channel, or NULL. * * Side effects: * May cause the creation of a standard channel and the underlying file. * *---------------------------------------------------------------------- */ Tcl_Channel TclpGetDefaultStdChannel( int type) /* One of TCL_STDIN, TCL_STDOUT, or * TCL_STDERR. */ { Tcl_Channel channel; HANDLE handle; int mode = -1; const char *bufMode = NULL; DWORD handleId = (DWORD) -1; /* Standard handle to retrieve. */ switch (type) { case TCL_STDIN: handleId = STD_INPUT_HANDLE; mode = TCL_READABLE; bufMode = "line"; break; case TCL_STDOUT: handleId = STD_OUTPUT_HANDLE; mode = TCL_WRITABLE; bufMode = "line"; break; case TCL_STDERR: handleId = STD_ERROR_HANDLE; mode = TCL_WRITABLE; bufMode = "none"; break; default: Tcl_Panic("TclGetDefaultStdChannel: Unexpected channel type"); break; } handle = GetStdHandle(handleId); /* * Note that we need to check for 0 because Windows may return 0 if this * is not a console mode application, even though this is not a valid * handle. */ if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)) { return (Tcl_Channel) NULL; } channel = Tcl_MakeFileChannel(handle, mode); if (channel == NULL) { return (Tcl_Channel) NULL; } /* * Set up the normal channel options for stdio handles. */ if (Tcl_SetChannelOption(NULL,channel,"-translation","auto")!=TCL_OK || Tcl_SetChannelOption(NULL,channel,"-eofchar","\032 {}")!=TCL_OK || Tcl_SetChannelOption(NULL,channel,"-buffering",bufMode)!=TCL_OK) { Tcl_Close(NULL, channel); return (Tcl_Channel) NULL; } return channel; } /* *---------------------------------------------------------------------- * * TclWinOpenFileChannel -- * * Constructs a File channel for the specified standard OS handle. This * is a helper function to break up the construction of channels into * File, Console, or Serial. * * Results: * Returns the new channel, or NULL. * * Side effects: * May open the channel and may cause creation of a file on the file * system. * *---------------------------------------------------------------------- */ Tcl_Channel TclWinOpenFileChannel( HANDLE handle, /* Win32 HANDLE to swallow */ char *channelName, /* Buffer to receive channel name */ int permissions, /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION, indicating * which operations are valid on the file. */ int appendMode) /* OR'ed combination of bits indicating what * additional configuration of the channel is * present. */ { FileInfo *infoPtr; ThreadSpecificData *tsdPtr = FileInit(); /* * See if a channel with this handle already exists. */ for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->handle == (HANDLE) handle) { return (permissions==infoPtr->validMask) ? infoPtr->channel : NULL; } } infoPtr = ckalloc(sizeof(FileInfo)); /* * TIP #218. Removed the code inserting the new structure into the global * list. This is now handled in the thread action callbacks, and only * there. */ infoPtr->nextPtr = NULL; infoPtr->validMask = permissions; infoPtr->watchMask = 0; infoPtr->flags = appendMode; infoPtr->handle = handle; infoPtr->dirty = 0; sprintf(channelName, "file%" TCL_I_MODIFIER "x", (size_t) infoPtr); infoPtr->channel = Tcl_CreateChannel(&fileChannelType, channelName, infoPtr, permissions); /* * Files have default translation of AUTO and ^Z eof char, which means * that a ^Z will be accepted as EOF when reading. */ Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto"); Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}"); return infoPtr->channel; } /* *---------------------------------------------------------------------- * * TclWinFlushDirtyChannels -- * * Flush all dirty channels to disk, so that requesting the size of any * file returns the correct value. * * Results: * None. * * Side effects: * Information is actually written to disk now, rather than later. Don't * call this too often, or there will be a performance hit (i.e. only * call when we need to ask for the size of a file). * *---------------------------------------------------------------------- */ void TclWinFlushDirtyChannels(void) { FileInfo *infoPtr; ThreadSpecificData *tsdPtr = FileInit(); /* * Flush all channels which are dirty, i.e. may have data pending in the * OS. */ for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->dirty) { FlushFileBuffers(infoPtr->handle); infoPtr->dirty = 0; } } } /* *---------------------------------------------------------------------- * * FileThreadActionProc -- * * Insert or remove any thread local refs to this channel. * * Results: * None. * * Side effects: * Changes thread local list of valid channels. * *---------------------------------------------------------------------- */ static void FileThreadActionProc( ClientData instanceData, int action) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); FileInfo *infoPtr = instanceData; if (action == TCL_CHANNEL_THREAD_INSERT) { infoPtr->nextPtr = tsdPtr->firstFilePtr; tsdPtr->firstFilePtr = infoPtr; } else { FileInfo **nextPtrPtr; int removed = 0; for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL; nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { if ((*nextPtrPtr) == infoPtr) { (*nextPtrPtr) = infoPtr->nextPtr; removed = 1; break; } } /* * This could happen if the channel was created in one thread and then * moved to another without updating the thread local data in each * thread. */ if (!removed) { Tcl_Panic("file info ptr not on thread channel list"); } } } /* *---------------------------------------------------------------------- * * FileGetType -- * * Given a file handle, return its type * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ DWORD FileGetType( HANDLE handle) /* Opened file handle */ { DWORD type; type = GetFileType(handle); /* * If the file is a character device, we need to try to figure out whether * it is a serial port, a console, or something else. We test for the * console case first because this is more common. */ if ((type == FILE_TYPE_CHAR) || ((type == FILE_TYPE_UNKNOWN) && !GetLastError())) { DWORD consoleParams; if (GetConsoleMode(handle, &consoleParams)) { type = FILE_TYPE_CONSOLE; } else { DCB dcb; dcb.DCBlength = sizeof(DCB); if (GetCommState(handle, &dcb)) { type = FILE_TYPE_SERIAL; } } } return type; } /* *---------------------------------------------------------------------- * * NativeIsComPort -- * * Determines if a path refers to a Windows serial port. * A simple and efficient solution is to use a "name hint" to detect * COM ports by their filename instead of resorting to a syscall * to detect serialness after the fact. * The following patterns cover common serial port names: * COM[1-9] * \\.\COM[0-9]+ * * Results: * 1 = serial port, 0 = not. * *---------------------------------------------------------------------- */ static int NativeIsComPort( const TCHAR *nativePath) /* Path of file to access, native encoding. */ { const WCHAR *p = (const WCHAR *) nativePath; int i, len = wcslen(p); /* * 1. Look for com[1-9]:? */ if ( (len == 4) && (_wcsnicmp(p, L"com", 3) == 0) ) { /* * The 4th character must be a digit 1..9 */ if ( (p[3] < L'1') || (p[3] > L'9') ) { return 0; } return 1; } /* * 2. Look for \\.\com[0-9]+ */ if ((len >= 8) && (_wcsnicmp(p, L"\\\\.\\com", 7) == 0)) { /* * Charaters 8..end must be a digits 0..9 */ for ( i=7; i '9') ) { return 0; } } return 1; } return 0; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tclWinPort.h0000644000175000017500000003145712663660066014655 0ustar sergeisergei/* * tclWinPort.h -- * * This header file handles porting issues that occur because of * differences between Windows and Unix. It should be the only * file that contains #ifdefs to handle different flavors of OS. * * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLWINPORT #define _TCLWINPORT #if !defined(_WIN64) && defined(BUILD_tcl) /* See [Bug 3354324]: file mtime sets wrong time */ # define _USE_32BIT_TIME_T #endif /* * We must specify the lower version we intend to support. * * WINVER = 0x0500 means Windows 2000 and above */ #ifndef WINVER # define WINVER 0x0501 #endif #ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0501 #endif #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN /* Compatibility to older visual studio / windows platform SDK */ #if !defined(MAXULONG_PTR) typedef DWORD DWORD_PTR; typedef DWORD_PTR * PDWORD_PTR; #endif /* * Ask for the winsock function typedefs, also. */ #define INCL_WINSOCK_API_TYPEDEFS 1 #include #include #ifdef HAVE_WSPIAPI_H # include #endif #ifdef CHECK_UNICODE_CALLS # define _UNICODE # define UNICODE # define __TCHAR_DEFINED typedef float *_TCHAR; # define _TCHAR_DEFINED typedef float *TCHAR; #endif /* CHECK_UNICODE_CALLS */ /* * Pull in the typedef of TCHAR for windows. */ #include #ifndef _TCHAR_DEFINED /* Borland seems to forget to set this. */ typedef _TCHAR TCHAR; # define _TCHAR_DEFINED #endif #if defined(_MSC_VER) && defined(__STDC__) /* VS2005 SP1 misses this. See [Bug #3110161] */ typedef _TCHAR TCHAR; #endif /* *--------------------------------------------------------------------------- * The following sets of #includes and #ifdefs are required to get Tcl to * compile under the windows compilers. *--------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #ifndef __GNUC__ # define strncasecmp _strnicmp # define strcasecmp _stricmp #endif /* * Need to block out these includes for building extensions with MetroWerks * compiler for Win32. */ #ifndef __MWERKS__ #include #include # ifdef __BORLANDC__ # include # else # include # endif /* __BORLANDC__ */ #endif /* __MWERKS__ */ /* * The following defines redefine the Windows Socket errors as * BSD errors so Tcl_PosixError can do the right thing. */ #ifndef ENOTEMPTY # define ENOTEMPTY 41 /* Directory not empty */ #endif #ifndef EREMOTE # define EREMOTE 66 /* The object is remote */ #endif #ifndef EPFNOSUPPORT # define EPFNOSUPPORT 96 /* Protocol family not supported */ #endif #ifndef EADDRINUSE # define EADDRINUSE 100 /* Address already in use */ #endif #ifndef EADDRNOTAVAIL # define EADDRNOTAVAIL 101 /* Can't assign requested address */ #endif #ifndef EAFNOSUPPORT # define EAFNOSUPPORT 102 /* Address family not supported */ #endif #ifndef EALREADY # define EALREADY 103 /* Operation already in progress */ #endif #ifndef EBADMSG # define EBADMSG 104 /* Not a data message */ #endif #ifndef ECANCELED # define ECANCELED 105 /* Canceled */ #endif #ifndef ECONNABORTED # define ECONNABORTED 106 /* Software caused connection abort */ #endif #ifndef ECONNREFUSED # define ECONNREFUSED 107 /* Connection refused */ #endif #ifndef ECONNRESET # define ECONNRESET 108 /* Connection reset by peer */ #endif #ifndef EDESTADDRREQ # define EDESTADDRREQ 109 /* Destination address required */ #endif #ifndef EHOSTUNREACH # define EHOSTUNREACH 110 /* No route to host */ #endif #ifndef EIDRM # define EIDRM 111 /* Identifier removed */ #endif #ifndef EINPROGRESS # define EINPROGRESS 112 /* Operation now in progress */ #endif #ifndef EISCONN # define EISCONN 113 /* Socket is already connected */ #endif #ifndef ELOOP # define ELOOP 114 /* Symbolic link loop */ #endif #ifndef EMSGSIZE # define EMSGSIZE 115 /* Message too long */ #endif #ifndef ENETDOWN # define ENETDOWN 116 /* Network is down */ #endif #ifndef ENETRESET # define ENETRESET 117 /* Network dropped connection on reset */ #endif #ifndef ENETUNREACH # define ENETUNREACH 118 /* Network is unreachable */ #endif #ifndef ENOBUFS # define ENOBUFS 119 /* No buffer space available */ #endif #ifndef ENODATA # define ENODATA 120 /* No data available */ #endif #ifndef ENOLINK # define ENOLINK 121 /* Link has be severed */ #endif #ifndef ENOMSG # define ENOMSG 122 /* No message of desired type */ #endif #ifndef ENOPROTOOPT # define ENOPROTOOPT 123 /* Protocol not available */ #endif #ifndef ENOSR # define ENOSR 124 /* Out of stream resources */ #endif #ifndef ENOSTR # define ENOSTR 125 /* Not a stream device */ #endif #ifndef ENOTCONN # define ENOTCONN 126 /* Socket is not connected */ #endif #ifndef ENOTRECOVERABLE # define ENOTRECOVERABLE 127 /* Not recoverable */ #endif #ifndef ENOTSOCK # define ENOTSOCK 128 /* Socket operation on non-socket */ #endif #ifndef ENOTSUP # define ENOTSUP 129 /* Operation not supported */ #endif #ifndef EOPNOTSUPP # define EOPNOTSUPP 130 /* Operation not supported on socket */ #endif #ifndef EOTHER # define EOTHER 131 /* Other error */ #endif #ifndef EOVERFLOW # define EOVERFLOW 132 /* File too big */ #endif #ifndef EOWNERDEAD # define EOWNERDEAD 133 /* Owner dead */ #endif #ifndef EPROTO # define EPROTO 134 /* Protocol error */ #endif #ifndef EPROTONOSUPPORT # define EPROTONOSUPPORT 135 /* Protocol not supported */ #endif #ifndef EPROTOTYPE # define EPROTOTYPE 136 /* Protocol wrong type for socket */ #endif #ifndef ETIME # define ETIME 137 /* Timer expired */ #endif #ifndef ETIMEDOUT # define ETIMEDOUT 138 /* Connection timed out */ #endif #ifndef ETXTBSY # define ETXTBSY 139 /* Text file or pseudo-device busy */ #endif #ifndef EWOULDBLOCK # define EWOULDBLOCK 140 /* Operation would block */ #endif /* Visual Studio doesn't have these, so just choose some high numbers */ #ifndef ESOCKTNOSUPPORT # define ESOCKTNOSUPPORT 240 /* Socket type not supported */ #endif #ifndef ESHUTDOWN # define ESHUTDOWN 241 /* Can't send after socket shutdown */ #endif #ifndef ETOOMANYREFS # define ETOOMANYREFS 242 /* Too many references: can't splice */ #endif #ifndef EHOSTDOWN # define EHOSTDOWN 243 /* Host is down */ #endif #ifndef EUSERS # define EUSERS 244 /* Too many users (for UFS) */ #endif #ifndef EDQUOT # define EDQUOT 245 /* Disc quota exceeded */ #endif #ifndef ESTALE # define ESTALE 246 /* Stale NFS file handle */ #endif /* * Signals not known to the standard ANSI signal.h. These are used * by Tcl_WaitPid() and generic/tclPosixStr.c */ #ifndef SIGTRAP # define SIGTRAP 5 #endif #ifndef SIGBUS # define SIGBUS 10 #endif /* * Supply definitions for macros to query wait status, if not already * defined in header files above. */ #if TCL_UNION_WAIT # define WAIT_STATUS_TYPE union wait #else # define WAIT_STATUS_TYPE int #endif /* TCL_UNION_WAIT */ #ifndef WIFEXITED # define WIFEXITED(stat) (((*((int *) &(stat))) & 0xC0000000) == 0) #endif #ifndef WEXITSTATUS # define WEXITSTATUS(stat) (*((int *) &(stat))) #endif #ifndef WIFSIGNALED # define WIFSIGNALED(stat) ((*((int *) &(stat))) & 0xC0000000) #endif #ifndef WTERMSIG # define WTERMSIG(stat) ((*((int *) &(stat))) & 0x7f) #endif #ifndef WIFSTOPPED # define WIFSTOPPED(stat) 0 #endif #ifndef WSTOPSIG # define WSTOPSIG(stat) (((*((int *) &(stat))) >> 8) & 0xff) #endif /* * Define constants for waitpid() system call if they aren't defined * by a system header file. */ #ifndef WNOHANG # define WNOHANG 1 #endif #ifndef WUNTRACED # define WUNTRACED 2 #endif /* * Define access mode constants if they aren't already defined. */ #ifndef F_OK # define F_OK 00 #endif #ifndef X_OK # define X_OK 01 #endif #ifndef W_OK # define W_OK 02 #endif #ifndef R_OK # define R_OK 04 #endif /* * Define macros to query file type bits, if they're not already * defined. */ #ifndef S_IFLNK # define S_IFLNK 0120000 /* Symbolic Link */ #endif #ifndef S_ISREG # ifdef S_IFREG # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) # else # define S_ISREG(m) 0 # endif #endif /* !S_ISREG */ #ifndef S_ISDIR # ifdef S_IFDIR # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) # else # define S_ISDIR(m) 0 # endif #endif /* !S_ISDIR */ #ifndef S_ISCHR # ifdef S_IFCHR # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) # else # define S_ISCHR(m) 0 # endif #endif /* !S_ISCHR */ #ifndef S_ISBLK # ifdef S_IFBLK # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) # else # define S_ISBLK(m) 0 # endif #endif /* !S_ISBLK */ #ifndef S_ISFIFO # ifdef S_IFIFO # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) # else # define S_ISFIFO(m) 0 # endif #endif /* !S_ISFIFO */ #ifndef S_ISLNK # ifdef S_IFLNK # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) # else # define S_ISLNK(m) 0 # endif #endif /* !S_ISLNK */ /* * Define MAXPATHLEN in terms of MAXPATH if available */ #ifndef MAXPATH # define MAXPATH MAX_PATH #endif /* MAXPATH */ #ifndef MAXPATHLEN # define MAXPATHLEN MAXPATH #endif /* MAXPATHLEN */ /* * Define pid_t and uid_t if they're not already defined. */ #if ! TCL_PID_T # define pid_t int #endif /* !TCL_PID_T */ #if ! TCL_UID_T # define uid_t int #endif /* !TCL_UID_T */ /* * Visual C++ has some odd names for common functions, so we need to * define a few macros to handle them. Also, it defines EDEADLOCK and * EDEADLK as the same value, which confuses Tcl_ErrnoId(). */ #if defined(_MSC_VER) || defined(__MSVCRT__) # define environ _environ # if defined(_MSC_VER) && (_MSC_VER < 1600) # define hypot _hypot # endif # define exception _exception # undef EDEADLOCK # if defined(_MSC_VER) && (_MSC_VER >= 1700) # define timezone _timezone # endif #endif /* _MSC_VER || __MSVCRT__ */ /* * Borland's timezone and environ functions. */ #ifdef __BORLANDC__ # define timezone _timezone # define environ _environ #endif /* __BORLANDC__ */ #ifdef __WATCOMC__ # if !defined(__CHAR_SIGNED__) # error "You must use the -j switch to ensure char is signed." # endif #endif /* * MSVC 8.0 started to mark many standard C library functions depreciated * including the *printf family and others. Tell it to shut up. * (_MSC_VER is 1200 for VC6, 1300 or 1310 for vc7.net, 1400 for 8.0) */ #if defined(_MSC_VER) && (_MSC_VER >= 1400) # pragma warning(disable:4244) # pragma warning(disable:4267) # pragma warning(disable:4996) #endif /* *--------------------------------------------------------------------------- * The following macros and declarations represent the interface between * generic and windows-specific parts of Tcl. Some of the macros may * override functions declared in tclInt.h. *--------------------------------------------------------------------------- */ /* * The default platform eol translation on Windows is TCL_TRANSLATE_CRLF: */ #define TCL_PLATFORM_TRANSLATION TCL_TRANSLATE_CRLF /* * Declare dynamic loading extension macro. */ #define TCL_SHLIB_EXT ".dll" /* * The following define ensures that we use the native putenv * implementation to modify the environment array. This keeps * the C level environment in synch with the system level environment. */ #define USE_PUTENV 1 #define USE_PUTENV_FOR_UNSET 1 /* * Msvcrt's putenv() copies the string rather than takes ownership of it. */ #if defined(_MSC_VER) || defined(__MSVCRT__) # define HAVE_PUTENV_THAT_COPIES 1 #endif /* * Older version of Mingw are known to lack a MWMO_ALERTABLE define. */ #if !defined(MWMO_ALERTABLE) # define MWMO_ALERTABLE 2 #endif /* * The following defines wrap the system memory allocation routines for * use by tclAlloc.c. */ #define TclpSysAlloc(size, isBin) ((void*)HeapAlloc(GetProcessHeap(), \ (DWORD)0, (DWORD)size)) #define TclpSysFree(ptr) (HeapFree(GetProcessHeap(), \ (DWORD)0, (HGLOBAL)ptr)) #define TclpSysRealloc(ptr, size) ((void*)HeapReAlloc(GetProcessHeap(), \ (DWORD)0, (LPVOID)ptr, (DWORD)size)) /* This type is not defined in the Windows headers */ #define socklen_t int /* * The following macros have trivial definitions, allowing generic code to * address platform-specific issues. */ #define TclpReleaseFile(file) ckfree((char *) file) /* * The following macros and declarations wrap the C runtime library * functions. */ #define TclpExit exit #ifndef INVALID_SET_FILE_POINTER #define INVALID_SET_FILE_POINTER 0xFFFFFFFF #endif /* INVALID_SET_FILE_POINTER */ #ifndef LABEL_SECURITY_INFORMATION # define LABEL_SECURITY_INFORMATION (0x00000010L) #endif #endif /* _TCLWINPORT */ tcl8.6.5/win/coffbase.txt0000644000175000017500000000322512663660066014700 0ustar sergeisergei; ; This file defines the virtual base addresses for the Dynamic Link Libraries ; that are part of the Tcl system. The first token on a line is the key (or name ; of the DLL) and the second token is the virtual base address, in hexidecimal. ; The third token is the maximum size of the DLL image file, including symbols. ; ; Using a specified "prefered load address" should speed loading time by avoiding ; relocations (NT supported only). It is assumed extension authors will contribute ; their modules to this grand-master list. You can use the dumpbin utility with ; the /headers option to get the "size of image" data (already in hex). If the ; maximum size is too small a linker warning will occur. Modules can overlap when ; they're mutually exclusive. This info is placed in the DLL's PE header by the ; linker with the `-base:@$(TCLDIR)\win\coffbase.txt,` option. tcl 0x10000000 0x00200000 tcldde 0x10200000 0x00010000 tclreg 0x10210000 0x00010000 tk 0x10220000 0x00200000 expect 0x10480000 0x00080000 itcl 0x10500000 0x00080000 itk 0x10580000 0x00080000 bltlite 0x10600000 0x00080000 blt 0x10680000 0x00080000 iocpsock 0x10700000 0x00080000 tls 0x10780000 0x00100000 winico 0x10880000 0x00010000 sample 0x108B0000 0x00010000 tile 0x10900000 0x00080000 memchan 0x109D0000 0x00010000 tdom 0x109E0000 0x00080000 tclvfs 0x10A70000 0x00010000 tkvideo 0x10B00000 0x00010000 tclsdl 0x10B20000 0x00080000 vqtcl 0x10C00000 0x00010000 tdbc 0x10C40000 0x00010000 thread 0x10C80000 0x00020000 ; ; insert new packages here ; snack 0x1E000000 0x00400000 sound 0x1E400000 0x00400000 snackogg 0x1E800000 0x00200000 tcl8.6.5/win/configure.in0000644000175000017500000003317212665173607014706 0ustar sergeisergei#! /bin/bash -norc # This file is an input file used by the GNU "autoconf" program to # generate the file "configure", which is run during Tcl installation # to configure the system for the local environment. AC_INIT(../generic/tcl.h) AC_PREREQ(2.59) # The following define is needed when building with Cygwin since newer # versions of autoconf incorrectly set SHELL to /bin/bash instead of # /bin/sh. The bash shell seems to suffer from some strange failures. SHELL=/bin/sh TCL_VERSION=8.6 TCL_MAJOR_VERSION=8 TCL_MINOR_VERSION=6 TCL_PATCH_LEVEL=".5" VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION TCL_DDE_VERSION=1.4 TCL_DDE_MAJOR_VERSION=1 TCL_DDE_MINOR_VERSION=4 DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION TCL_REG_VERSION=1.3 TCL_REG_MAJOR_VERSION=1 TCL_REG_MINOR_VERSION=3 REGVER=$TCL_REG_MAJOR_VERSION$TCL_REG_MINOR_VERSION PKG_CFG_ARGS=$@ #------------------------------------------------------------------------ # Empty slate for bundled packages, to avoid stale configuration #------------------------------------------------------------------------ rm -Rf pkgs #------------------------------------------------------------------------ # Handle the --prefix=... option #------------------------------------------------------------------------ if test "${prefix}" = "NONE"; then prefix=/usr/local fi if test "${exec_prefix}" = "NONE"; then exec_prefix=$prefix fi # libdir must be a fully qualified path (not ${exec_prefix}/lib) eval libdir="$libdir" #------------------------------------------------------------------------ # Standard compiler checks #------------------------------------------------------------------------ # If the user did not set CFLAGS, set it now to keep # the AC_PROG_CC macro from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi AC_PROG_CC AC_C_INLINE AC_HEADER_STDC AC_CHECK_TOOL(AR, ar) AC_CHECK_TOOL(RANLIB, ranlib) AC_CHECK_TOOL(RC, windres) #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- AC_PROG_MAKE_SET #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) #-------------------------------------------------------------------- AC_OBJEXT AC_EXEEXT #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. #-------------------------------------------------------------------- SC_ENABLE_THREADS #------------------------------------------------------------------------ # Embedded configuration information, encoding to use for the values, TIP #59 #------------------------------------------------------------------------ SC_TCL_CFG_ENCODING #-------------------------------------------------------------------- # The statements below define a collection of symbols related to # building libtcl as a shared library instead of a static library. #-------------------------------------------------------------------- SC_ENABLE_SHARED #-------------------------------------------------------------------- # The statements below define a collection of compile flags. This # macro depends on the value of SHARED_BUILD, and should be called # after SC_ENABLE_SHARED checks the configure switches. #-------------------------------------------------------------------- SC_CONFIG_CFLAGS # Cross-compiling case ${host_alias} in *mingw32*) TCL_EXE="tclsh" ;; *) TCL_EXE="TCL_LIBRARY=\"\${LIBRARY_DIR}\"; export TCL_LIBRARY; ./\${TCLSH}" ;; esac #------------------------------------------------------------------------ # Add stuff for zlib; note that this is mostly done in the makefile now # as we just assume that the platform hasn't got a usable z.lib #------------------------------------------------------------------------ AS_IF([test "${enable_shared+set}" = "set"], [ enableval="$enable_shared" tcl_ok=$enableval ], [ tcl_ok=yes ]) AS_IF([test "$tcl_ok" = "yes"], [ AC_SUBST(ZLIB_DLL_FILE,[\${ZLIB_DLL_FILE}]) AS_IF([test "$do64bit" = "yes"], [ AS_IF([test "$GCC" == "yes"],[ AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win64/libz.dll.a]) ], [ AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win64/zdll.lib]) ]) ], [ AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win32/zdll.lib]) ]) ], [ AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}]) ]) AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?]) AC_CHECK_TYPE([intptr_t], [ AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [ AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [ for tcl_cv_intptr_t in "int" "long" "long long" none; do if test "$tcl_cv_intptr_t" != none; then AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT], [[sizeof (void *) <= sizeof ($tcl_cv_intptr_t)]])], [tcl_ok=yes], [tcl_ok=no]) test "$tcl_ok" = yes && break; fi done]) if test "$tcl_cv_intptr_t" != none; then AC_DEFINE_UNQUOTED([intptr_t], [$tcl_cv_intptr_t], [Signed integer type wide enough to hold a pointer.]) fi ]) AC_CHECK_TYPE([uintptr_t], [ AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [ AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [ for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \ none; do if test "$tcl_cv_uintptr_t" != none; then AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT], [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])], [tcl_ok=yes], [tcl_ok=no]) test "$tcl_ok" = yes && break; fi done]) if test "$tcl_cv_uintptr_t" != none; then AC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer type wide enough to hold a pointer.]) fi ]) #-------------------------------------------------------------------- # Perform additinal compiler tests. #-------------------------------------------------------------------- # See if declarations like FINDEX_INFO_LEVELS are # missing from winbase.h. This is known to be # a problem with VC++ 5.2. AC_CACHE_CHECK(for FINDEX_INFO_LEVELS in winbase.h, tcl_cv_findex_enums, AC_TRY_COMPILE([ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN ], [ FINDEX_INFO_LEVELS i; FINDEX_SEARCH_OPS j; ], tcl_cv_findex_enums=yes, tcl_cv_findex_enums=no) ) if test "$tcl_cv_findex_enums" = "no"; then AC_DEFINE(HAVE_NO_FINDEX_ENUMS, 1, [Defined when enums are missing from winbase.h]) fi # See if the compiler supports intrinsics. AC_CACHE_CHECK(for intrinsics support in compiler, tcl_cv_intrinsics, AC_TRY_LINK([ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN #include ], [ __cpuidex(0,0,0); ], tcl_cv_intrinsics=yes, tcl_cv_intrinsics=no) ) if test "$tcl_cv_intrinsics" = "yes"; then AC_DEFINE(HAVE_INTRIN_H, 1, [Defined when the compilers supports intrinsics]) fi # See if the header file is present AC_CACHE_CHECK(for wspiapi.h, tcl_cv_wspiapi_h, AC_TRY_COMPILE([ #include ], [], tcl_cv_wspiapi_h=yes, tcl_cv_wspiapi_h=no) ) if test "$tcl_cv_wspiapi_h" = "yes"; then AC_DEFINE(HAVE_WSPIAPI_H, 1, [Defined when wspiapi.h exists]) fi # See if declarations like FINDEX_INFO_LEVELS are # missing from winbase.h. This is known to be # a problem with VC++ 5.2. AC_CACHE_CHECK(for FINDEX_INFO_LEVELS in winbase.h, tcl_cv_findex_enums, AC_TRY_COMPILE([ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN ], [ FINDEX_INFO_LEVELS i; FINDEX_SEARCH_OPS j; ], tcl_cv_findex_enums=yes, tcl_cv_findex_enums=no) ) if test "$tcl_cv_findex_enums" = "no"; then AC_DEFINE(HAVE_NO_FINDEX_ENUMS, 1, [Defined when enums are missing from winbase.h]) fi #-------------------------------------------------------------------- # Set the default compiler switches based on the --enable-symbols # option. This macro depends on C flags, and should be called # after SC_CONFIG_CFLAGS macro is called. #-------------------------------------------------------------------- SC_ENABLE_SYMBOLS TCL_DBGX=${DBGX} #-------------------------------------------------------------------- # Embed the manifest if we can determine how #-------------------------------------------------------------------- SC_EMBED_MANIFEST #------------------------------------------------------------------------ # tclConfig.sh refers to this by a different name #------------------------------------------------------------------------ TCL_SHARED_BUILD=${SHARED_BUILD} #-------------------------------------------------------------------- # Perform final evaluations of variables with possible substitutions. #-------------------------------------------------------------------- TCL_SHARED_LIB_SUFFIX="\${NODOT_VERSION}${DLLSUFFIX}" TCL_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}" TCL_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}" eval "TCL_SRC_DIR=\"`cd $srcdir/..; $CYGPATH $(pwd)`\"" eval "TCL_DLL_FILE=tcl${VER}${DLLSUFFIX}" eval "TCL_STUB_LIB_FILE=\"${LIBPREFIX}tclstub${VER}${LIBSUFFIX}\"" eval "TCL_STUB_LIB_FLAG=\"-ltclstub${VER}${LIBFLAGSUFFIX}\"" eval "TCL_BUILD_STUB_LIB_SPEC=\"-L`$CYGPATH $(pwd)` ${TCL_STUB_LIB_FLAG}\"" eval "TCL_STUB_LIB_SPEC=\"-L${libdir} ${TCL_STUB_LIB_FLAG}\"" eval "TCL_BUILD_STUB_LIB_PATH=\"`$CYGPATH $(pwd)`/${TCL_STUB_LIB_FILE}\"" eval "TCL_STUB_LIB_PATH=\"${libdir}/${TCL_STUB_LIB_FILE}\"" eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${LIBSUFFIX}\"" eval "TCL_BUILD_LIB_SPEC=\"-L`$CYGPATH $(pwd)` -ltcl${VER}${FLAGSUFFIX}\"" eval "TCL_LIB_SPEC=\"-L${libdir} -ltcl${VER}${FLAGSUFFIX}\"" # Install time header dir can be set via --includedir eval "TCL_INCLUDE_SPEC=\"-I${includedir}\"" eval "DLLSUFFIX=${DLLSUFFIX}" eval "LIBPREFIX=${LIBPREFIX}" eval "LIBSUFFIX=${LIBSUFFIX}" eval "EXESUFFIX=${EXESUFFIX}" CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX} CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX} CFG_TCL_EXPORT_FILE_SUFFIX=${TCL_EXPORT_FILE_SUFFIX} #-------------------------------------------------------------------- # Adjust the defines for how the resources are built depending # on symbols and static vs. shared. #-------------------------------------------------------------------- if test ${SHARED_BUILD} = 0 ; then if test "${DBGX}" = "g"; then RC_DEFINES="${RC_DEFINE} STATIC_BUILD ${RC_DEFINE} DEBUG" else RC_DEFINES="${RC_DEFINE} STATIC_BUILD" fi else if test "${DBGX}" = "g"; then RC_DEFINES="${RC_DEFINE} DEBUG" else RC_DEFINES="" fi fi #-------------------------------------------------------------------- # The statements below define the symbol TCL_PACKAGE_PATH, which # gives a list of directories that may contain packages. The list # consists of one directory for machine-dependent binaries and # another for platform-independent scripts. #-------------------------------------------------------------------- if test "$prefix/lib" != "$libdir"; then TCL_PACKAGE_PATH="${libdir} ${prefix}/lib" else TCL_PACKAGE_PATH="${prefix}/lib" fi # The tclsh.exe.manifest requires these # TCL_WIN_VERSION is the 4 dotted pair Windows version format which needs # the release level, and must account for interim release versioning case "$TCL_PATCH_LEVEL" in *a*) TCL_RELEASE_LEVEL=0 ;; *b*) TCL_RELEASE_LEVEL=1 ;; *) TCL_RELEASE_LEVEL=2 ;; esac TCL_WIN_VERSION="$TCL_VERSION.$TCL_RELEASE_LEVEL.`echo $TCL_PATCH_LEVEL | tr -d ab.`" AC_SUBST(TCL_WIN_VERSION) # X86|AMD64|IA64 for manifest AC_SUBST(MACHINE) AC_SUBST(TCL_VERSION) AC_SUBST(TCL_MAJOR_VERSION) AC_SUBST(TCL_MINOR_VERSION) AC_SUBST(TCL_PATCH_LEVEL) AC_SUBST(PKG_CFG_ARGS) AC_SUBST(TCL_EXE) AC_SUBST(TCL_LIB_FILE) AC_SUBST(TCL_LIB_FLAG) AC_SUBST(TCL_STATIC_LIB_FILE) AC_SUBST(TCL_STATIC_LIB_FLAG) AC_SUBST(TCL_IMPORT_LIB_FILE) AC_SUBST(TCL_IMPORT_LIB_FLAG) # empty on win AC_SUBST(TCL_LIB_SPEC) AC_SUBST(TCL_STUB_LIB_FILE) AC_SUBST(TCL_STUB_LIB_FLAG) AC_SUBST(TCL_STUB_LIB_SPEC) AC_SUBST(TCL_STUB_LIB_PATH) AC_SUBST(TCL_INCLUDE_SPEC) AC_SUBST(TCL_BUILD_STUB_LIB_SPEC) AC_SUBST(TCL_BUILD_STUB_LIB_PATH) AC_SUBST(TCL_DLL_FILE) AC_SUBST(TCL_SRC_DIR) AC_SUBST(TCL_BIN_DIR) AC_SUBST(TCL_DBGX) AC_SUBST(CFG_TCL_SHARED_LIB_SUFFIX) AC_SUBST(CFG_TCL_UNSHARED_LIB_SUFFIX) AC_SUBST(CFG_TCL_EXPORT_FILE_SUFFIX) # win/tcl.m4 doesn't set (CFLAGS) AC_SUBST(CFLAGS_DEFAULT) AC_SUBST(EXTRA_CFLAGS) AC_SUBST(CYGPATH) AC_SUBST(DEPARG) AC_SUBST(CC_OBJNAME) AC_SUBST(CC_EXENAME) # win/tcl.m4 doesn't set (LDFLAGS) AC_SUBST(LDFLAGS_DEFAULT) AC_SUBST(LDFLAGS_DEBUG) AC_SUBST(LDFLAGS_OPTIMIZE) AC_SUBST(LDFLAGS_CONSOLE) AC_SUBST(LDFLAGS_WINDOW) AC_SUBST(AR) AC_SUBST(RANLIB) AC_SUBST(STLIB_LD) AC_SUBST(SHLIB_LD) AC_SUBST(SHLIB_LD_LIBS) AC_SUBST(SHLIB_CFLAGS) AC_SUBST(SHLIB_SUFFIX) AC_SUBST(TCL_SHARED_BUILD) AC_SUBST(LIBS) AC_SUBST(LIBS_GUI) AC_SUBST(DLLSUFFIX) AC_SUBST(LIBPREFIX) AC_SUBST(LIBSUFFIX) AC_SUBST(EXESUFFIX) AC_SUBST(LIBRARIES) AC_SUBST(MAKE_LIB) AC_SUBST(MAKE_STUB_LIB) AC_SUBST(POST_MAKE_LIB) AC_SUBST(MAKE_DLL) AC_SUBST(MAKE_EXE) # empty on win, but needs sub'ing AC_SUBST(TCL_BUILD_LIB_SPEC) AC_SUBST(TCL_LD_SEARCH_FLAGS) AC_SUBST(TCL_NEEDS_EXP_FILE) AC_SUBST(TCL_BUILD_EXP_FILE) AC_SUBST(TCL_EXP_FILE) AC_SUBST(DL_LIBS) AC_SUBST(TCL_LIB_VERSIONS_OK) AC_SUBST(TCL_PACKAGE_PATH) # win only AC_SUBST(TCL_DDE_VERSION) AC_SUBST(TCL_DDE_MAJOR_VERSION) AC_SUBST(TCL_DDE_MINOR_VERSION) AC_SUBST(TCL_REG_VERSION) AC_SUBST(TCL_REG_MAJOR_VERSION) AC_SUBST(TCL_REG_MINOR_VERSION) AC_SUBST(RC) AC_SUBST(RC_OUT) AC_SUBST(RC_TYPE) AC_SUBST(RC_INCLUDE) AC_SUBST(RC_DEFINE) AC_SUBST(RC_DEFINES) AC_SUBST(RES) AC_OUTPUT(Makefile tclConfig.sh tcl.hpj tclsh.exe.manifest) dnl Local Variables: dnl mode: autoconf; dnl End: tcl8.6.5/win/tclWin32Dll.c0000644000175000017500000004623412663660066014603 0ustar sergeisergei/* * tclWin32Dll.c -- * * This file contains the DLL entry point and other low-level bit bashing * code that needs inline assembly. * * Copyright (c) 1995-1996 Sun Microsystems, Inc. * Copyright (c) 1998-2000 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclWinInt.h" #if defined(HAVE_INTRIN_H) # include #endif /* * The following variables keep track of information about this DLL on a * per-instance basis. Each time this DLL is loaded, it gets its own new data * segment with its own copy of all static and global information. */ static HINSTANCE hInstance; /* HINSTANCE of this DLL. */ static int platformId; /* Running under NT, or 95/98? */ /* * VC++ 5.x has no 'cpuid' assembler instruction, so we must emulate it */ #if defined(_MSC_VER) && (_MSC_VER <= 1100) #define cpuid __asm __emit 0fh __asm __emit 0a2h #endif static Tcl_Encoding winTCharEncoding = NULL; /* * The following declaration is for the VC++ DLL entry point. */ BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID reserved); /* * The following structure and linked list is to allow us to map between * volume mount points and drive letters on the fly (no Win API exists for * this). */ typedef struct MountPointMap { const TCHAR *volumeName; /* Native wide string volume name. */ TCHAR driveLetter; /* Drive letter corresponding to the volume * name. */ struct MountPointMap *nextPtr; /* Pointer to next structure in list, or * NULL. */ } MountPointMap; /* * This is the head of the linked list, which is protected by the mutex which * follows, for thread-enabled builds. */ MountPointMap *driveLetterLookup = NULL; TCL_DECLARE_MUTEX(mountPointMap) /* * We will need this below. */ #ifdef _WIN32 #ifndef STATIC_BUILD /* *---------------------------------------------------------------------- * * DllEntryPoint -- * * This wrapper function is used by Borland to invoke the initialization * code for Tcl. It simply calls the DllMain routine. * * Results: * See DllMain. * * Side effects: * See DllMain. * *---------------------------------------------------------------------- */ BOOL APIENTRY DllEntryPoint( HINSTANCE hInst, /* Library instance handle. */ DWORD reason, /* Reason this function is being called. */ LPVOID reserved) /* Not used. */ { return DllMain(hInst, reason, reserved); } /* *---------------------------------------------------------------------- * * DllMain -- * * This routine is called by the VC++ C run time library init code, or * the DllEntryPoint routine. It is responsible for initializing various * dynamically loaded libraries. * * Results: * TRUE on sucess, FALSE on failure. * * Side effects: * Initializes most rudimentary Windows bits. * *---------------------------------------------------------------------- */ BOOL APIENTRY DllMain( HINSTANCE hInst, /* Library instance handle. */ DWORD reason, /* Reason this function is being called. */ LPVOID reserved) /* Not used. */ { switch (reason) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hInst); TclWinInit(hInst); return TRUE; /* * DLL_PROCESS_DETACH is unnecessary as the user should call * Tcl_Finalize explicitly before unloading Tcl. */ } return TRUE; } #endif /* !STATIC_BUILD */ #endif /* _WIN32 */ /* *---------------------------------------------------------------------- * * TclWinGetTclInstance -- * * Retrieves the global library instance handle. * * Results: * Returns the global library instance handle. * * Side effects: * None. * *---------------------------------------------------------------------- */ HINSTANCE TclWinGetTclInstance(void) { return hInstance; } /* *---------------------------------------------------------------------- * * TclWinInit -- * * This function initializes the internal state of the tcl library. * * Results: * None. * * Side effects: * Initializes the tclPlatformId variable. * *---------------------------------------------------------------------- */ void TclWinInit( HINSTANCE hInst) /* Library instance handle. */ { OSVERSIONINFOW os; hInstance = hInst; os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); GetVersionExW(&os); platformId = os.dwPlatformId; /* * We no longer support Win32s or Win9x, so just in case someone manages * to get a runtime there, make sure they know that. */ if (platformId == VER_PLATFORM_WIN32s) { Tcl_Panic("Win32s is not a supported platform"); } if (platformId == VER_PLATFORM_WIN32_WINDOWS) { Tcl_Panic("Windows 9x is not a supported platform"); } TclWinResetInterfaces(); } /* *---------------------------------------------------------------------- * * TclWinGetPlatformId -- * * Determines whether running under NT, 95, or Win32s, to allow runtime * conditional code. * * Results: * The return value is one of: * VER_PLATFORM_WIN32s Win32s on Windows 3.1 (not supported) * VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95, 98, ME (not supported) * VER_PLATFORM_WIN32_NT Win32 on Windows NT, 2000, XP * VER_PLATFORM_WIN32_CE Win32 on Windows CE * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclWinGetPlatformId(void) { return platformId; } /* *------------------------------------------------------------------------- * * TclWinNoBackslash -- * * We're always iterating through a string in Windows, changing the * backslashes to slashes for use in Tcl. * * Results: * All backslashes in given string are changed to slashes. * * Side effects: * None. * *------------------------------------------------------------------------- */ char * TclWinNoBackslash( char *path) /* String to change. */ { char *p; for (p = path; *p != '\0'; p++) { if (*p == '\\') { *p = '/'; } } return path; } /* *--------------------------------------------------------------------------- * * TclpSetInterfaces -- * * A helper proc that initializes winTCharEncoding. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */ void TclpSetInterfaces(void) { TclWinResetInterfaces(); winTCharEncoding = Tcl_GetEncoding(NULL, "unicode"); } /* *--------------------------------------------------------------------------- * * TclWinEncodingsCleanup -- * * Called during finalization to free up any encodings we use. * * We also clean up any memory allocated in our mount point map which is * used to follow certain kinds of symlinks. That code should never be * used once encodings are taken down. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */ void TclWinEncodingsCleanup(void) { MountPointMap *dlIter, *dlIter2; TclWinResetInterfaces(); /* * Clean up the mount point map. */ Tcl_MutexLock(&mountPointMap); dlIter = driveLetterLookup; while (dlIter != NULL) { dlIter2 = dlIter->nextPtr; ckfree(dlIter->volumeName); ckfree(dlIter); dlIter = dlIter2; } Tcl_MutexUnlock(&mountPointMap); } /* *--------------------------------------------------------------------------- * * TclWinResetInterfaces -- * * Called during finalization to reset us to a safe state for reuse. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */ void TclWinResetInterfaces(void) { if (winTCharEncoding != NULL) { Tcl_FreeEncoding(winTCharEncoding); winTCharEncoding = NULL; } } /* *-------------------------------------------------------------------- * * TclWinDriveLetterForVolMountPoint * * Unfortunately, Windows provides no easy way at all to get hold of the * drive letter for a volume mount point, but we need that information to * understand paths correctly. So, we have to build an associated array * to find these correctly, and allow quick and easy lookup from volume * mount points to drive letters. * * We assume here that we are running on a system for which the wide * character interfaces are used, which is valid for Win 2000 and WinXP * which are the only systems on which this function will ever be called. * * Result: * The drive letter, or -1 if no drive letter corresponds to the given * mount point. * *-------------------------------------------------------------------- */ char TclWinDriveLetterForVolMountPoint( const TCHAR *mountPoint) { MountPointMap *dlIter, *dlPtr2; TCHAR Target[55]; /* Target of mount at mount point */ TCHAR drive[4] = TEXT("A:\\"); /* * Detect the volume mounted there. Unfortunately, there is no simple way * to map a unique volume name to a DOS drive letter. So, we have to build * an associative array. */ Tcl_MutexLock(&mountPointMap); dlIter = driveLetterLookup; while (dlIter != NULL) { if (_tcscmp(dlIter->volumeName, mountPoint) == 0) { /* * We need to check whether this information is still valid, since * either the user or various programs could have adjusted the * mount points on the fly. */ drive[0] = (TCHAR) dlIter->driveLetter; /* * Try to read the volume mount point and see where it points. */ if (GetVolumeNameForVolumeMountPoint(drive, Target, 55) != 0) { if (_tcscmp(dlIter->volumeName, Target) == 0) { /* * Nothing has changed. */ Tcl_MutexUnlock(&mountPointMap); return (char) dlIter->driveLetter; } } /* * If we reach here, unfortunately, this mount point is no longer * valid at all. */ if (driveLetterLookup == dlIter) { dlPtr2 = dlIter; driveLetterLookup = dlIter->nextPtr; } else { for (dlPtr2 = driveLetterLookup; dlPtr2 != NULL; dlPtr2 = dlPtr2->nextPtr) { if (dlPtr2->nextPtr == dlIter) { dlPtr2->nextPtr = dlIter->nextPtr; dlPtr2 = dlIter; break; } } } /* * Now dlPtr2 points to the structure to free. */ ckfree(dlPtr2->volumeName); ckfree(dlPtr2); /* * Restart the loop - we could try to be clever and continue half * way through, but the logic is a bit messy, so it's cleanest * just to restart. */ dlIter = driveLetterLookup; continue; } dlIter = dlIter->nextPtr; } /* * We couldn't find it, so we must iterate over the letters. */ for (drive[0] = L'A'; drive[0] <= L'Z'; drive[0]++) { /* * Try to read the volume mount point and see where it points. */ if (GetVolumeNameForVolumeMountPoint(drive, Target, 55) != 0) { int alreadyStored = 0; for (dlIter = driveLetterLookup; dlIter != NULL; dlIter = dlIter->nextPtr) { if (_tcscmp(dlIter->volumeName, Target) == 0) { alreadyStored = 1; break; } } if (!alreadyStored) { dlPtr2 = ckalloc(sizeof(MountPointMap)); dlPtr2->volumeName = TclNativeDupInternalRep(Target); dlPtr2->driveLetter = (char) drive[0]; dlPtr2->nextPtr = driveLetterLookup; driveLetterLookup = dlPtr2; } } } /* * Try again. */ for (dlIter = driveLetterLookup; dlIter != NULL; dlIter = dlIter->nextPtr) { if (_tcscmp(dlIter->volumeName, mountPoint) == 0) { Tcl_MutexUnlock(&mountPointMap); return (char) dlIter->driveLetter; } } /* * The volume doesn't appear to correspond to a drive letter - we remember * that fact and store '-1' so we don't have to look it up each time. */ dlPtr2 = ckalloc(sizeof(MountPointMap)); dlPtr2->volumeName = TclNativeDupInternalRep((ClientData) mountPoint); dlPtr2->driveLetter = -1; dlPtr2->nextPtr = driveLetterLookup; driveLetterLookup = dlPtr2; Tcl_MutexUnlock(&mountPointMap); return -1; } /* *--------------------------------------------------------------------------- * * Tcl_WinUtfToTChar, Tcl_WinTCharToUtf -- * * Convert between UTF-8 and Unicode when running Windows NT or the * current ANSI code page when running Windows 95. * * On Mac, Unix, and Windows 95, all strings exchanged between Tcl and * the OS are "char" oriented. We need only one Tcl_Encoding to convert * between UTF-8 and the system's native encoding. We use NULL to * represent that encoding. * * On NT, some strings exchanged between Tcl and the OS are "char" * oriented, while others are in Unicode. We need two Tcl_Encoding APIs * depending on whether we are targeting a "char" or Unicode interface. * * Calling Tcl_UtfToExternal() or Tcl_ExternalToUtf() with an encoding of * NULL should always used to convert between UTF-8 and the system's * "char" oriented encoding. The following two functions are used in * Windows-specific code to convert between UTF-8 and Unicode strings * (NT) or "char" strings(95). This saves you the trouble of writing the * following type of fragment over and over: * * if (running NT) { * encoding <- Tcl_GetEncoding("unicode"); * nativeBuffer <- UtfToExternal(encoding, utfBuffer); * Tcl_FreeEncoding(encoding); * } else { * nativeBuffer <- UtfToExternal(NULL, utfBuffer); * } * * By convention, in Windows a TCHAR is a character in the ANSI code page * on Windows 95, a Unicode character on Windows NT. If you plan on * targeting a Unicode interfaces when running on NT and a "char" * oriented interface while running on 95, these functions should be * used. If you plan on targetting the same "char" oriented function on * both 95 and NT, use Tcl_UtfToExternal() with an encoding of NULL. * * Results: * The result is a pointer to the string in the desired target encoding. * Storage for the result string is allocated in dsPtr; the caller must * call Tcl_DStringFree() when the result is no longer needed. * * Side effects: * None. * *--------------------------------------------------------------------------- */ TCHAR * Tcl_WinUtfToTChar( const char *string, /* Source string in UTF-8. */ int len, /* Source string length in bytes, or < 0 for * strlen(). */ Tcl_DString *dsPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { return (TCHAR *) Tcl_UtfToExternalDString(winTCharEncoding, string, len, dsPtr); } char * Tcl_WinTCharToUtf( const TCHAR *string, /* Source string in Unicode when running NT, * ANSI when running 95. */ int len, /* Source string length in bytes, or < 0 for * platform-specific string length. */ Tcl_DString *dsPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { return Tcl_ExternalToUtfDString(winTCharEncoding, (const char *) string, len, dsPtr); } /* *------------------------------------------------------------------------ * * TclWinCPUID -- * * Get CPU ID information on an Intel box under Windows * * Results: * Returns TCL_OK if successful, TCL_ERROR if CPUID is not supported or * fails. * * Side effects: * If successful, stores EAX, EBX, ECX and EDX registers after the CPUID * instruction in the four integers designated by 'regsPtr' * *---------------------------------------------------------------------- */ int TclWinCPUID( unsigned int index, /* Which CPUID value to retrieve. */ unsigned int *regsPtr) /* Registers after the CPUID. */ { int status = TCL_ERROR; #if defined(HAVE_INTRIN_H) && defined(_WIN64) __cpuid(regsPtr, index); status = TCL_OK; #elif defined(__GNUC__) # if defined(_WIN64) /* * Execute the CPUID instruction with the given index, and store results * off 'regPtr'. */ __asm__ __volatile__( /* * Do the CPUID instruction, and save the results in the 'regsPtr' * area. */ "movl %[rptr], %%edi" "\n\t" "movl %[index], %%eax" "\n\t" "cpuid" "\n\t" "movl %%eax, 0x0(%%edi)" "\n\t" "movl %%ebx, 0x4(%%edi)" "\n\t" "movl %%ecx, 0x8(%%edi)" "\n\t" "movl %%edx, 0xc(%%edi)" "\n\t" : /* No outputs */ : [index] "m" (index), [rptr] "m" (regsPtr) : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); status = TCL_OK; # else TCLEXCEPTION_REGISTRATION registration; /* * Execute the CPUID instruction with the given index, and store results * off 'regPtr'. */ __asm__ __volatile__( /* * Construct an TCLEXCEPTION_REGISTRATION to protect the CPUID * instruction (early 486's don't have CPUID) */ "leal %[registration], %%edx" "\n\t" "movl %%fs:0, %%eax" "\n\t" "movl %%eax, 0x0(%%edx)" "\n\t" /* link */ "leal 1f, %%eax" "\n\t" "movl %%eax, 0x4(%%edx)" "\n\t" /* handler */ "movl %%ebp, 0x8(%%edx)" "\n\t" /* ebp */ "movl %%esp, 0xc(%%edx)" "\n\t" /* esp */ "movl %[error], 0x10(%%edx)" "\n\t" /* status */ /* * Link the TCLEXCEPTION_REGISTRATION on the chain */ "movl %%edx, %%fs:0" "\n\t" /* * Do the CPUID instruction, and save the results in the 'regsPtr' * area. */ "movl %[rptr], %%edi" "\n\t" "movl %[index], %%eax" "\n\t" "cpuid" "\n\t" "movl %%eax, 0x0(%%edi)" "\n\t" "movl %%ebx, 0x4(%%edi)" "\n\t" "movl %%ecx, 0x8(%%edi)" "\n\t" "movl %%edx, 0xc(%%edi)" "\n\t" /* * Come here on a normal exit. Recover the TCLEXCEPTION_REGISTRATION and * store a TCL_OK status. */ "movl %%fs:0, %%edx" "\n\t" "movl %[ok], %%eax" "\n\t" "movl %%eax, 0x10(%%edx)" "\n\t" "jmp 2f" "\n" /* * Come here on an exception. Get the TCLEXCEPTION_REGISTRATION that we * previously put on the chain. */ "1:" "\t" "movl %%fs:0, %%edx" "\n\t" "movl 0x8(%%edx), %%edx" "\n\t" /* * Come here however we exited. Restore context from the * TCLEXCEPTION_REGISTRATION in case the stack is unbalanced. */ "2:" "\t" "movl 0xc(%%edx), %%esp" "\n\t" "movl 0x8(%%edx), %%ebp" "\n\t" "movl 0x0(%%edx), %%eax" "\n\t" "movl %%eax, %%fs:0" "\n\t" : /* No outputs */ : [index] "m" (index), [rptr] "m" (regsPtr), [registration] "m" (registration), [ok] "i" (TCL_OK), [error] "i" (TCL_ERROR) : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); status = registration.status; # endif /* !_WIN64 */ #elif defined(_MSC_VER) # if defined(_WIN64) __cpuid(regsPtr, index); status = TCL_OK; # else /* * Define a structure in the stack frame to hold the registers. */ struct { DWORD dw0; DWORD dw1; DWORD dw2; DWORD dw3; } regs; regs.dw0 = index; /* * Execute the CPUID instruction and save regs in the stack frame. */ _try { _asm { push ebx push ecx push edx mov eax, regs.dw0 cpuid mov regs.dw0, eax mov regs.dw1, ebx mov regs.dw2, ecx mov regs.dw3, edx pop edx pop ecx pop ebx } /* * Copy regs back out to the caller. */ regsPtr[0] = regs.dw0; regsPtr[1] = regs.dw1; regsPtr[2] = regs.dw2; regsPtr[3] = regs.dw3; status = TCL_OK; } __except(EXCEPTION_EXECUTE_HANDLER) { /* do nothing */ } # endif #else /* * Don't know how to do assembly code for this compiler and/or * architecture. */ #endif return status; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/nmakehlp.c0000644000175000017500000004217012663660066014334 0ustar sergeisergei/* * ---------------------------------------------------------------------------- * nmakehlp.c -- * * This is used to fix limitations within nmake and the environment. * * Copyright (c) 2002 by David Gravereaux. * Copyright (c) 2006 by Pat Thoyts * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * ---------------------------------------------------------------------------- */ #define _CRT_SECURE_NO_DEPRECATE #include #define NO_SHLWAPI_GDI #define NO_SHLWAPI_STREAM #define NO_SHLWAPI_REG #include #pragma comment (lib, "user32.lib") #pragma comment (lib, "kernel32.lib") #pragma comment (lib, "shlwapi.lib") #include #include /* * This library is required for x64 builds with _some_ versions of MSVC */ #if defined(_M_IA64) || defined(_M_AMD64) #if _MSC_VER >= 1400 && _MSC_VER < 1500 #pragma comment(lib, "bufferoverflowU") #endif #endif /* ISO hack for dumb VC++ */ #ifdef _MSC_VER #define snprintf _snprintf #endif /* protos */ static int CheckForCompilerFeature(const char *option); static int CheckForLinkerFeature(const char *option); static int IsIn(const char *string, const char *substring); static int SubstituteFile(const char *substs, const char *filename); static int QualifyPath(const char *path); static const char *GetVersionFromFile(const char *filename, const char *match, int numdots); static DWORD WINAPI ReadFromPipe(LPVOID args); /* globals */ #define CHUNK 25 #define STATICBUFFERSIZE 1000 typedef struct { HANDLE pipe; char buffer[STATICBUFFERSIZE]; } pipeinfo; pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'}; pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'}; /* * exitcodes: 0 == no, 1 == yes, 2 == error */ int main( int argc, char *argv[]) { char msg[300]; DWORD dwWritten; int chars; /* * Make sure children (cl.exe and link.exe) are kept quiet. */ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); /* * Make sure the compiler and linker aren't effected by the outside world. */ SetEnvironmentVariable("CL", ""); SetEnvironmentVariable("LINK", ""); if (argc > 1 && *argv[1] == '-') { switch (*(argv[1]+1)) { case 'c': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -c \n" "Tests for whether cl.exe supports an option\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return CheckForCompilerFeature(argv[2]); case 'l': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -l \n" "Tests for whether link.exe supports an option\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return CheckForLinkerFeature(argv[2]); case 'f': if (argc == 2) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -f \n" "Find a substring within another\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } else if (argc == 3) { /* * If the string is blank, there is no match. */ return 0; } else { return IsIn(argv[2], argv[3]); } case 's': if (argc == 2) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -s \n" "Perform a set of string map type substutitions on a file\n" "exitcodes: 0\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return SubstituteFile(argv[2], argv[3]); case 'V': if (argc != 4) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -V filename matchstring\n" "Extract a version from a file:\n" "eg: pkgIndex.tcl \"package ifneeded http\"", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 0; } printf("%s\n", GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0')); return 0; case 'Q': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -Q path\n" "Emit the fully qualified path\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return QualifyPath(argv[2]); } } chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -c|-f|-l|-Q|-s|-V ...\n" "This is a little helper app to equalize shell differences between WinNT and\n" "Win9x and get nmake.exe to accomplish its job.\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } static int CheckForCompilerFeature( const char *option) { STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; DWORD threadID; char msg[300]; BOOL ok; HANDLE hProcess, h, pipeThreads[2]; char cmdline[100]; hProcess = GetCurrentProcess(); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = INVALID_HANDLE_VALUE; ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = FALSE; /* * Create a non-inheritible pipe. */ CreatePipe(&Out.pipe, &h, &sa, 0); /* * Dupe the write side, make it inheritible, and close the original. */ DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Same as above, but for the error side. */ CreatePipe(&Err.pipe, &h, &sa, 0); DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Base command line. */ lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch "); /* * Append our option for testing */ lstrcat(cmdline, option); /* * Filename to compile, which exists, but is nothing and empty. */ lstrcat(cmdline, " .\\nul"); ok = CreateProcess( NULL, /* Module name. */ cmdline, /* Command line. */ NULL, /* Process handle not inheritable. */ NULL, /* Thread handle not inheritable. */ TRUE, /* yes, inherit handles. */ DETACHED_PROCESS, /* No console for you. */ NULL, /* Use parent's environment block. */ NULL, /* Use parent's starting directory. */ &si, /* Pointer to STARTUPINFO structure. */ &pi); /* Pointer to PROCESS_INFORMATION structure. */ if (!ok) { DWORD err = GetLastError(); int chars = snprintf(msg, sizeof(msg) - 1, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], (300-chars), 0); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); return 2; } /* * Close our references to the write handles that have now been inherited. */ CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); WaitForInputIdle(pi.hProcess, 5000); CloseHandle(pi.hThread); /* * Start the pipe reader threads. */ pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); /* * Block waiting for the process to end. */ WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); /* * Wait for our pipe to get done reading, should it be a little slow. */ WaitForMultipleObjects(2, pipeThreads, TRUE, 500); CloseHandle(pipeThreads[0]); CloseHandle(pipeThreads[1]); /* * Look for the commandline warning code in both streams. * - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002. */ return !(strstr(Out.buffer, "D4002") != NULL || strstr(Err.buffer, "D4002") != NULL || strstr(Out.buffer, "D9002") != NULL || strstr(Err.buffer, "D9002") != NULL || strstr(Out.buffer, "D2021") != NULL || strstr(Err.buffer, "D2021") != NULL); } static int CheckForLinkerFeature( const char *option) { STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; DWORD threadID; char msg[300]; BOOL ok; HANDLE hProcess, h, pipeThreads[2]; char cmdline[100]; hProcess = GetCurrentProcess(); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = INVALID_HANDLE_VALUE; ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* * Create a non-inheritible pipe. */ CreatePipe(&Out.pipe, &h, &sa, 0); /* * Dupe the write side, make it inheritible, and close the original. */ DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Same as above, but for the error side. */ CreatePipe(&Err.pipe, &h, &sa, 0); DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Base command line. */ lstrcpy(cmdline, "link.exe -nologo "); /* * Append our option for testing. */ lstrcat(cmdline, option); ok = CreateProcess( NULL, /* Module name. */ cmdline, /* Command line. */ NULL, /* Process handle not inheritable. */ NULL, /* Thread handle not inheritable. */ TRUE, /* yes, inherit handles. */ DETACHED_PROCESS, /* No console for you. */ NULL, /* Use parent's environment block. */ NULL, /* Use parent's starting directory. */ &si, /* Pointer to STARTUPINFO structure. */ &pi); /* Pointer to PROCESS_INFORMATION structure. */ if (!ok) { DWORD err = GetLastError(); int chars = snprintf(msg, sizeof(msg) - 1, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], (300-chars), 0); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); return 2; } /* * Close our references to the write handles that have now been inherited. */ CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); WaitForInputIdle(pi.hProcess, 5000); CloseHandle(pi.hThread); /* * Start the pipe reader threads. */ pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); /* * Block waiting for the process to end. */ WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); /* * Wait for our pipe to get done reading, should it be a little slow. */ WaitForMultipleObjects(2, pipeThreads, TRUE, 500); CloseHandle(pipeThreads[0]); CloseHandle(pipeThreads[1]); /* * Look for the commandline warning code in the stderr stream. */ return !(strstr(Out.buffer, "LNK1117") != NULL || strstr(Err.buffer, "LNK1117") != NULL || strstr(Out.buffer, "LNK4044") != NULL || strstr(Err.buffer, "LNK4044") != NULL); } static DWORD WINAPI ReadFromPipe( LPVOID args) { pipeinfo *pi = (pipeinfo *) args; char *lastBuf = pi->buffer; DWORD dwRead; BOOL ok; again: if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) { CloseHandle(pi->pipe); return (DWORD)-1; } ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L); if (!ok || dwRead == 0) { CloseHandle(pi->pipe); return 0; } lastBuf += dwRead; goto again; return 0; /* makes the compiler happy */ } static int IsIn( const char *string, const char *substring) { return (strstr(string, substring) != NULL); } /* * GetVersionFromFile -- * Looks for a match string in a file and then returns the version * following the match where a version is anything acceptable to * package provide or package ifneeded. */ static const char * GetVersionFromFile( const char *filename, const char *match, int numdots) { size_t cbBuffer = 100; static char szBuffer[100]; char *szResult = NULL; FILE *fp = fopen(filename, "rt"); if (fp != NULL) { /* * Read data until we see our match string. */ while (fgets(szBuffer, cbBuffer, fp) != NULL) { LPSTR p, q; p = strstr(szBuffer, match); if (p != NULL) { /* * Skip to first digit after the match. */ p += strlen(match); while (*p && !isdigit(*p)) { ++p; } /* * Find ending whitespace. */ q = p; while (*q && (strchr("0123456789.ab", *q)) && ((!strchr(".ab", *q) && (!strchr("ab", q[-1])) || --numdots))) { ++q; } memcpy(szBuffer, p, q - p); szBuffer[q-p] = 0; szResult = szBuffer; break; } } fclose(fp); } return szResult; } /* * List helpers for the SubstituteFile function */ typedef struct list_item_t { struct list_item_t *nextPtr; char * key; char * value; } list_item_t; /* insert a list item into the list (list may be null) */ static list_item_t * list_insert(list_item_t **listPtrPtr, const char *key, const char *value) { list_item_t *itemPtr = malloc(sizeof(list_item_t)); if (itemPtr) { itemPtr->key = strdup(key); itemPtr->value = strdup(value); itemPtr->nextPtr = NULL; while(*listPtrPtr) { listPtrPtr = &(*listPtrPtr)->nextPtr; } *listPtrPtr = itemPtr; } return itemPtr; } static void list_free(list_item_t **listPtrPtr) { list_item_t *tmpPtr, *listPtr = *listPtrPtr; while (listPtr) { tmpPtr = listPtr; listPtr = listPtr->nextPtr; free(tmpPtr->key); free(tmpPtr->value); free(tmpPtr); } } /* * SubstituteFile -- * As windows doesn't provide anything useful like sed and it's unreliable * to use the tclsh you are building against (consider x-platform builds - * eg compiling AMD64 target from IX86) we provide a simple substitution * option here to handle autoconf style substitutions. * The substitution file is whitespace and line delimited. The file should * consist of lines matching the regular expression: * \s*\S+\s+\S*$ * * Usage is something like: * nmakehlp -S << $** > $@ * @PACKAGE_NAME@ $(PACKAGE_NAME) * @PACKAGE_VERSION@ $(PACKAGE_VERSION) * << */ static int SubstituteFile( const char *substitutions, const char *filename) { size_t cbBuffer = 1024; static char szBuffer[1024], szCopy[1024]; char *szResult = NULL; list_item_t *substPtr = NULL; FILE *fp, *sp; fp = fopen(filename, "rt"); if (fp != NULL) { /* * Build a list of substutitions from the first filename */ sp = fopen(substitutions, "rt"); if (sp != NULL) { while (fgets(szBuffer, cbBuffer, sp) != NULL) { unsigned char *ks, *ke, *vs, *ve; ks = (unsigned char*)szBuffer; while (ks && *ks && isspace(*ks)) ++ks; ke = ks; while (ke && *ke && !isspace(*ke)) ++ke; vs = ke; while (vs && *vs && isspace(*vs)) ++vs; ve = vs; while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; *ke = 0, *ve = 0; list_insert(&substPtr, (char*)ks, (char*)vs); } fclose(sp); } /* debug: dump the list */ #ifdef _DEBUG { int n = 0; list_item_t *p = NULL; for (p = substPtr; p != NULL; p = p->nextPtr, ++n) { fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value); } } #endif /* * Run the substitutions over each line of the input */ while (fgets(szBuffer, cbBuffer, fp) != NULL) { list_item_t *p = NULL; for (p = substPtr; p != NULL; p = p->nextPtr) { char *m = strstr(szBuffer, p->key); if (m) { char *cp, *op, *sp; cp = szCopy; op = szBuffer; while (op != m) *cp++ = *op++; sp = p->value; while (sp && *sp) *cp++ = *sp++; op += strlen(p->key); while (*op) *cp++ = *op++; *cp = 0; memcpy(szBuffer, szCopy, sizeof(szCopy)); } } printf(szBuffer); } list_free(&substPtr); } fclose(fp); return 0; } /* * QualifyPath -- * * This composes the current working directory with a provided path * and returns the fully qualified and normalized path. * Mostly needed to setup paths for testing. */ static int QualifyPath( const char *szPath) { char szCwd[MAX_PATH + 1]; char szTmp[MAX_PATH + 1]; char *p; GetCurrentDirectory(MAX_PATH, szCwd); while ((p = strchr(szPath, '/')) && *p) *p = '\\'; PathCombine(szTmp, szCwd, szPath); PathCanonicalize(szCwd, szTmp); printf("%s\n", szCwd); return 0; } /* * Local variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * indent-tabs-mode: t * tab-width: 8 * End: */ tcl8.6.5/win/license.terms0000644000175000017500000000431712663660066015070 0ustar sergeisergeiThis software is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. tcl8.6.5/win/tcl.dsw0000644000175000017500000000102112663660066013660 0ustar sergeisergeiMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "tcl"=.\tcl.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### tcl8.6.5/win/tclsh.ico0000644000175000017500000015727612663653133014215 0ustar sergeisergei @@ (BÖ00 ¨%þB  ¨¦h ˆ Ny hÖ‚00¨>‡ ¨ æ£HްhÖ·00¨>» ¨æÉÈŽÒhVÙ(@€ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿYÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ7Ôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÚØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ—ÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ%ÿÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0ÿÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0ÿÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0ÿÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0ÿÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0ÿÿÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ3ÿÿþ%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–ÿÿÿî ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ{ÿÿÿÿÿ¤ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ.—ôÿÿÿÿÿÿÿñ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ+m×ÿÿÿÿÿÿÿÆÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ@÷ÿÿÿÿÿÿÿÿÅÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ/ñÿñqsnæÿÿÿR2Õ% µòÿç+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕÿ*+)ñÝààÿÑÑÈôûÿÿmC#ï¤e4ÿ•\/ÖÆÿàÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿˆÿòÙÜÛÿìîîÿÝàÚþÕÿÿmC#ï¤e4ÿ¤e4ÿ¡c3í ¯ÿÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúÿ˜›˜ýìîîÿìîîÿÔÎÁÿ ´ÿÿmC#ï¤e4ÿ¤e4ÿ¤e4ÿ¤e4õ ´ÿžÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿbÿóêììÿìîîÿìîîÿıšÿ-¦ÿÿkB"í¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ`1ÛÖþ;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ·ÿ}}zúèíìÿëííÿëîîÿ´’pÿ]9©ÿÿU4á¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿyK'­ýÎÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæûdd_åòêììÿÞâÝÿ¥j9ÿŒV-¼ÿÿ:$Ù¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ü ³ÿgÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿÿ öìîîÿÏÅ·ÿ¤e4ÿ¤e4ãìÿ! Ú¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ›`1ð¡c3þN(±ýÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþóø òìîîÿî—ÿ¤e4ÿ¤e4ÿÂÿ â¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿX.Éë Øðÿ.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÷552ñìîîÿ®–ÿ¤e4ÿ¤e4ÿ+¦ÿ÷Ÿb3ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ7"£ÿÿÿ‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLLIóìîîÿðšÿ¤e4ÿ¤e4ÿ{K'²ÿÿuH%ó¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¡d3êÐþ€qÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ5ÿGFCòìîîÿÅ´žÿ¤e4ÿ¤e4ÿ¤e4ëßÿ:$Ù¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿrF$­ýÙ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿEÿ&%#ñìîîÿǶ¢ÿ¤e4ÿ¤e4ÿ¤e4ÿ«ÿ å¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ý «ÿ¤ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ÿ öìîîÿɺ§ÿ¤e4ÿ¤e4ÿ¤e4ÿ`;§ÿÿ’Z.ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ•\0ÆòÿVÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõÿáããÿÔÐÄÿ¤e4ÿ¤e4ÿ¤e4ÿ d3Ôñÿ\9ä¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ ¥ÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎÿ¶¸¸ÿâçåÿ§qDÿ¤e4ÿ¤e4ÿ¤e4ÿ µÿ" Ù¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ“[/Ãôÿ\ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¤ÿbb^öìîîÿ¸š{ÿ¤e4ÿ¤e4ÿ¤e4ÿF,¡ÿô¢d3ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ§ÿØÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿnÿôìîîÿÄ´ÿ¤e4ÿ¤e4ÿ¤e4ÿ”[/¾üÿ|L'÷¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿY.¿öÿ\ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ¹¼»ÿÒÎÁÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ü ´ÿ+ؤe4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ ªÿÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐÿ^^Zöâçåÿ¨sGÿ¤e4ÿ¤e4ÿ¤e4ÿrG$ªÿù–]0ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿP)±þÿ6ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿõìîîÿº ƒÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4õÂÿH,ܤe4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ú»ÿšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ0ÿÿ´¸¶ÿʼªÿ©vJÿȾ¬ÿ¨tHÿ¤e4ÿ\:£ÿí¡c3ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿc=¥ÿó ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßÿ[[WößáÜÿÞàÛÿëîîÿ±Šfÿ¤e4ÿ¤e4ëÓÿe? è¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤d4ìÓÿcÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}ÿõêììÿ–›–ðÔ××ÿ¶–vÿ¤e4ÿ¤e4ÿG, ÿ à¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿA) ÿÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúÿ''%áÿ¨­¬ÿ» ƒÿ¤e4ÿ¤e4ÿ¡c3ßáÿO)õ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿŸb2Øèÿ,ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©ÿÿÿ‚„ûƵžÿ¤e4ÿ¤e4ÿ¤e4ÿ3¡ÿ( ؤe4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ% £ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ@ÿ×ÿ^^ZöØØÐÿ¤g6ÿ¤e4ÿ¤e4ÿša1Ðìû‘Y.ü¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ“Z.À÷íÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°û21/òëîîÿ³’pÿ¤e4ÿ¤e4ÿ¤e4ÿA(¡ÿ5!Ù¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ ­ÿXÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒþËÎÍÿȺ¥ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ñÅø•\/þ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿxK&¸ ÍÙÿ½ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿ[[XößáÜÿªxMÿ¤e4ÿ¤e4ÿ¤e4ÿ„Q*»÷;$Ù¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4÷´ÿÛ†ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ6ÿøâääÿÇ»¨ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ,¦õ˜]0ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ˜^/Óâü-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÿstpùåèåÿ®…`ÿ¤e4ÿ¤e4ÿ¤e4ÿ£d4ïÂB(Û¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿf? ¨ý¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ'üúÃÄÃÿÎÆ·ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ—^0Ö Úš_1ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4þªÿUÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ˜ÿ"" òåèèÿ»¢†ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ}M'¸P1Ù¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ|L'­ÿ¾ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÙÿlmiøáãÞÿ¯‚[ÿ¤e4ÿ®ƒ]ÿ¤e4ÿ¤e4ÿN(פe4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ñÎöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ.öü§ª§ýÔÑÇÿ§n@ÿÔÖÌÿ·—wÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ3 ¡ÿ:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿdÿ÷»½»þÒÖÌÿêííÿÒÒÈÿ¤g6ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿZ.¹ÿxÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ÿ óÌÎÎÿ¥¦žé…ˆ„û¼¥‹ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e3ßè±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿñ/0,Ô öÊÌÅÿ©rEÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4üÇÊÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÌÿÿÿGGDôÎǸÿ¤g6ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ °ÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖûÿmnj÷Ä´ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ" ¤ñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿt½ÿ€ƒ~ùÁ®–ÿ¤f5ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ-¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéÿHJFñÄÀ²ÿ¨sGÿ¤e4ÿ¤e4ÿ¤e4ÿ1¡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁÿ ñY\Víž“ö¦k<ÿ¤e4ÿ5!¡ÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿxöÿÿécZLá4(¯ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿqØÿÿÿ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ5q¬ÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßÿÿÿÿÿÿÿŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿðÿÿÿÿÿÿøÿÿÿÿÿÿøÿÿÿÿÿÿðÿÿÿÿÿÿàÿÿÿÿÿÀ?ÿÿÿÿÿÀÿÿÿÿÿÀÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿ ÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿðÿÿÿÿÿðÿÿÿÿðÿÿÿÿð?ÿÿÿÿø?ÿÿÿÿø?ÿÿÿÿüÿÿÿÿüÿÿÿÿüÿÿÿÿþÿÿÿÿþ€ÿÿÿÿÿ€ÿÿÿÿÿ€ÿÿÿÿÿÀÿÿÿÿÿÀÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿðÿÿÿÿÿøÿÿÿÿÿüÿÿÿÿÿüÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿðÿÿÿÿÿÿøÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁÿÿÿÿÿÿÿùÿÿ(0` ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ Ü ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿžÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ5ÿÿœÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠÿÿöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿB­ÿÿÿÿì} ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ4—ûÿÿÿÿÿzÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿoÿùÿÿðÿ÷`ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ>û 不 ïÿÿ8"ÒwI&ÅÌÿnÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèíÐÓÑÿßßÙýàÿ,Ò¤e4ÿ¡c3ò ´üJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–ÿ¼½»þìîîÿÖÏÃÿ ¼ÿ! Ó¤e4ÿ¤e4ÿ£e4ø Ãòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿç*)&íìîîÿìîîÿDZšÿ% ªÿפe4ÿ¤e4ÿ¤e4ÿˆT+Çö¤ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ)ÿVWSîhicðìîîÿ¶“rÿR1ªÿ ܤe4ÿ¤e4ÿ¤e4ÿ¤e4ÿ0ªþ9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ9ÿÿ<;7íäæãÿ¦k<ÿO(»ÿ ä¤e4ÿ¤e4ÿ¤e4ÿˆT*×|L'ÑÛ¨ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿG½ÏWUOðÛ×Îÿ¤e4ÿ¢d3ãñð¤e4ÿ¤e4ÿ¤e4ÿW-Êöÿõ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÏqpjõÜÙÑÿ¤e4ÿ¤e4ÿ ¹ÿˆT+÷¤e4ÿ¤e4ÿ¤e4ÿ% ¬ÿ 7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïmkfôÝÜÖÿ¤e4ÿ¤e4ÿJ-«ÿN0Ö¤e4ÿ¤e4ÿ¤e4ÿš_1ÛëÂÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìHFBîßßÚÿ¤e4ÿ¤e4ÿ”Z/Êýפe4ÿ¤e4ÿ¤e4ÿ¤e4ÿ<$ªÿƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÁ'&#íçëêÿ«yNÿ¤e4ÿ¤e4ýÊ÷Ÿb2ÿ¤e4ÿ¤e4ÿ¤e4ÿ c3êÜùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ— õêììÿ¼Ÿ‚ÿ¤e4ÿ¤e4ÿ0ªÿsG$é¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿU4¬ÿ”ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿiÿ¦¨¥þ˼ªÿ¤e4ÿ¤e4ÿ}M(¹ÿ6!Ò¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4õÌ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýLJFïÚÙÐÿ¤e4ÿ¤e4ÿ¤e4ôÔé¢d3ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿiA!±ÿŠÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºöåéèÿ¯‚[ÿ¤e4ÿ¤e4ÿM/«ÿh@!á¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4öÑêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ^ÿ ¡žý¿¤Šÿ¨rEÿ¬{Rÿ¡c4éá Ú¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿL/«ÿUÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ õFD@îØÔÊÿßÞØÿ½¢†ÿ¤e4ÿ:$ªÿƒP)ð¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ c3ææºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¦ö¾¾¸ù‚‚|ôì“ÿ¤e4ÿa2Þì' Ò¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ.«þ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿIÿû)'$ìȹ¤ÿ¤e4ÿ¤e4ÿ) «ù–\/û¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ•\/Ñöƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéç òÛÚÒÿ¥f6ÿ¤e4ÿ”]/Òó@(Ó¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ²äÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ`FþÖÙØÿ´mÿ¤e4ÿ¤e4ÿB)ªðœ`1þ¤e4ÿ¤e4ÿ¤e4ÿa2ópD$¶ÿLÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ýigcô˽«ÿ¤e4ÿ¤e4ÿ¤e4ù ¾I-Õ¤e4ÿ¤e4ÿ¤e4ÿh@!²þöœÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´ óãääÿ´Žkÿ¤e4ÿ¤e4ÿ–\/Ø Úža2ÿ¤e4ÿ¤e4ÿ¤e4ÿ! ®õÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ.þ{zvöØÕËÿ¦j:ÿ¤e4ÿ¤e4ÿd> ±S3פe4ÿ¤e4ÿ¤e4ÿ b4êÕ¤ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¤øÆÈÅþï™ÿ¤e4ÿ¤e4ÿ¤e4ÿC*½ c3ÿ¤e4ÿ¤e4ÿ¤e4ÿd= ¯þ.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâ$#!íãæãÿ¯‚[ÿ¥j:ÿ§pCÿŸb3ê‰T+ì¤e4ÿ¤e4ÿ¤e4ÿ¢d4êæwÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ/ó]\WñÔÌÀÿÁ«“ÿűšÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ" ­¶ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿNýxwrõäèæÿ·º´ú¬{Qÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿe> °òÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿvýiieé ðĸ§ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿzL'¸ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸÿþKKHð¼ „ÿ¤e4ÿ¤e4ÿ¤e4ÿ¤e4ÿŒV-Âÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ½LòBB>í²Žmÿ¤e4ÿ¤e4ÿ¤e4ÿœb2ÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿZÿ22/츢Šþ¤e4ÿ¤e4ÿ¤e4áö ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿPë îUTLä›eò¤f5ôã$ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿˆØþàì)ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ)zÊ,ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÇÿÿÿÿÿ‡ÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿüÿÿÿø?ÿÿÿøÿÿÿøÿÿÿøÿÿÿøÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿ€ÿÿÿàÿÿÿà?ÿÿÿàÿÿÿð?ÿÿÿð?ÿÿÿø?ÿÿÿüÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿðÿÿÿÿøÿÿÿÿüÿÿÿÿÿßÿ( @ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ Gÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿœhÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿhÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿhÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿhÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2ÿ¨ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ÿû>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´ÿÿÿñ$ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ» èÿäð‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‹%# çÒÓÎüò Ò‘Z.ß À”ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿø×Ø×ÿÙÓÉÿÌÙ¤e4ÿ¤e4û Âjÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿg,+)è­¬¨úÉ´Ÿÿ ·â¤e4ÿ¤e4ÿŒV-ÐÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ|ûvsmóº•uÿC)²ì¤e4ÿ¤e4ÿh@!à Ê[ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,Би¶lÿO)Çý˜]0ü¤e4ÿ‡S+Îù‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿž‹†ø·‘pÿ¤e4úÞ`;ؤe4ÿ¤e4ÿ  µ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„gc]ð¼œÿ¤e4ÿ! ³$ Τe4ÿ¤e4ÿ–\/Ýç"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿY42.é̺§ÿ¤e4ÿjA!·ì£e4ÿ¤e4ÿ¤e4ÿ6!¯´ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÒÏÇÿ¤e4ÿ c3êë{M'å¤e4ÿ¤e4ÿžb3êäIÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¾ŒŠ…÷­|Sÿ¤e4ÿ/° Ϥe4ÿ¤e4ÿ¤e4ÿ5!¯µÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿa2/,èÍÀ¯ÿê‘ÿ—]/ÝòŒU,ï¤e4ÿ¤e4ÿ—]/Üñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿó\YSâ¼°¡ÿ¤e4ÿ" ´,ˤe4ÿ¤e4ÿ¤e4ÿ ¶|ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©õ¡ —ú¤e4ÿX-Ôñ—]0ø¤e4ÿ¤e4ÿƒQ*ÊÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ){olgñ³‰eÿ¤e4ÿ6!³>&ˤe4ÿ¤e4ÿrF%ÉàCÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ4 îÏÁ³ÿ¤e4ÿ£d4÷ Çža2ý¤e4ÿ€N)Éí.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°xuoòº—wÿ¤e4ÿW-×^:Ϥe4ÿ¤e4ÿ;$¯„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&鸞˜ø©qDÿ¦l=ÿ€O(ؤe4ÿ¤e4ÿža2äßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿJ ûÕÎÁÿ¥i9ÿ¤e4ÿ¤e4ÿ¤e4ÿ·.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿqèRQMçÀ§ÿ¤e4ÿ¤e4ÿ¤e4ÿ8"¯^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ›äNMGë®Yÿ¤e4ÿ¤e4ÿI-±fÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®983æµ”vÿ¤e4ÿ[8µkÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ“ êVQIß]J7Æpÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿh¹oÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ÿÿÿ÷ÿÿÿ÷ÿÿÿ÷ÿÿÿóÿÿÿãÿÿÿÁÿÿÿÀÿÿÿ€ÿÿ€ÿÿ€?ÿÿ€?ÿÿ€ÿÿ€ÿÿ€ÿÿÀÿÿÀÿÿÀÿÿàÿÿàÿÿàÿÿøÿÿøÿÿøÿÿüÿÿþÿÿÿÿÿÿÿÿÿÁÿÿÿáÿÿÿýÿ(0 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿFÿjÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿCéÿûAÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿkâþ ͽ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ'&$!äÜÝÙÿÖh@!×€O)ѹÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿeppkñÓÆ·ÿ ·[8Фe4ÿH,¸]ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~æÃ¨ÿW5¶L/ʤe4ÿP1¼ÉÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿѦÿ‘Z.Ô ˤe4ÿ„Q*ÐÉ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËǯ˜ÿ¤e4ý Ò£d4ÿ¤e4ÿ ¹@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ»Æ½±ý¤e4ÿ¹|L'ä¤e4ÿ”[/ÝÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿq}wñ§m?ÿe> »+ˤe4ÿ¤e4ÿ,´^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,)&åÈ·£ÿ°‚[ûÔ—]0÷¤e4ÿ’Z.ؽÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÃHFBæÀ¢‡ÿP1¸=%ʤe4ÿ¤e4ÿº(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿS¦›Œø¡c3ô Ñža2ü¤e4ÿxJ&ÂŒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿCgd\ë¨oBÿ~M(ÎV5̤e4ÿ=&³¨ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚ¼«šü¤e4ÿe> É£d4ÿ£e4ú · ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿM.-)æ¼¢†ÿ°‚]üa2ø¤e4ÿV5¶IÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿrXWRê“…ñ¥h8ÿ¤e4ÿ‘Y.Ó‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ™Æ {ò¤e4ÿŸb2áŒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿµvpdæ©~Xð†ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿY¯…ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿ÿÿ¿ÿÿ¿ÿÿ¿ÿÿÿÿÿþÿþÿþÿþÿþÿþÿÿÿÿÿÿÿÿ€ÿÀÿÀÿàÿð?ÿð?ÿü?ÿÿ?(  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿYÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ-ÐÿxÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅMKDßÿï7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¥ÿÿÿýÿÛ‡EÿÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¨óÇÿÿÛ‡EÿU3á…ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ«óÇÿÿÛ‡EÿÙ…DÿÊÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŒóÇÿóÇÿÿÛ‡EÿQ2Ú°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ# ÙóÇÿÿÛ‡EÿÛ‡Eÿ¨ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢óÇÿóÇÿÿÛ‡EÿÌÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÍóÇÿc=ÿÛ‡EÿU4ЧÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸóÇÿóÇÿ“Z.ÿÛ‡EÿªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŸóÇÿóÇÿÛ‡Eÿ¯ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿš&*(êóÇÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿK&&#Êžÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿýÿùÿðÿðð?ð?ðøøüüþÿÿÏ(0`ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ¥§ 8"wI&ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐÓÑßßÙ,¤e4¡c3 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¼½»ìîîÖÏà ! ¤e4¤e4£e4 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*)&ìîîìîîDZš% ¤e4¤e4¤e4ˆT+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVWShicìîî¶“rR1 ¤e4¤e4¤e4¤e40ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ<;7äæã¦k S3¤e4¤e4¤e4 b4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÆÈÅe4¤e4¤e4C* c3¤e4¤e4¤e4d= ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$#!ãæã¯‚[¥j:§pCŸb3‰T+¤e4¤e4¤e4¢d4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ]\WÔÌÀÁ«“űš¤e4¤e4¤e4¤e4¤e4¤e4" ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿxwräèæ·º´¬{Q¤e4¤e4¤e4¤e4¤e4e> ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿiie ĸ§¤e4¤e4¤e4¤e4¤e4zL'ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿKKH¼ „¤e4¤e4¤e4¤e4ŒV-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿBB>²Žm¤e4¤e4¤e4œb2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ22/¸¢Š¤e4¤e4¤e4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ UTL›e¤f5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÇÿÿÿÿÿ‡ÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿüÿÿÿø?ÿÿÿøÿÿÿøÿÿÿøÿÿÿøÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿ€ÿÿÿàÿÿÿà?ÿÿÿàÿÿÿð?ÿÿÿð?ÿÿÿø?ÿÿÿüÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿðÿÿÿÿøÿÿÿÿüÿÿÿÿÿßÿ( @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ%# ÒÓÎ ‘Z. ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿר×ÙÓɤe4¤e4 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,+)­¬¨É´Ÿ ¤e4¤e4ŒV-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿvsmº•uC)¤e4¤e4h@! ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‘жlO)˜]0¤e4‡S+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‹†·‘p¤e4`;¤e4¤e4  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgc]¼œ¤e4! $ ¤e4¤e4–\/ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ42.̺§¤e4jA!£e4¤e4¤e46!ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÏǤe4 c3{M'¤e4¤e4žb3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŒŠ…­|S¤e4/ ¤e4¤e4¤e45!ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2/,ÍÀ¯Ãª‘—]/ŒU,¤e4¤e4—]/ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ\YS¼°¡¤e4" ,¤e4¤e4¤e4 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¡ —¤e4X-—]0¤e4¤e4ƒQ*ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿolg³‰e¤e46!>&¤e4¤e4rF%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÏÁ³¤e4£d4 ža2¤e4€N)ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿxuoº—w¤e4W-^:¤e4¤e4;$ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¤ ˜©qD¦l=€O(¤e4¤e4ža2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¸® ÕÎÁ¥i9¤e4¤e4¤e4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRQMÀ§¤e4¤e4¤e48"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿNMG®Y¤e4¤e4I-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ983µ”v¤e4[8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ VQI]J7ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ÿÿÿ÷ÿÿÿ÷ÿÿÿ÷ÿÿÿóÿÿÿãÿÿÿÁÿÿÿÀÿÿÿ€ÿÿ€ÿÿ€?ÿÿ€?ÿÿ€ÿÿ€ÿÿ€ÿÿÀÿÿÀÿÿÀÿÿàÿÿàÿÿàÿÿøÿÿøÿÿøÿÿüÿÿþÿÿÿÿÿÿÿÿÿÁÿÿÿáÿÿÿýÿ(0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&$!ÜÝÙh@!€O)ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿppkÓÆ· [8¤e4H,ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèW5L/¤e4P1ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¦‘Z. ¤e4„Q*ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿǯ˜¤e4 £d4¤e4 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿƽ±¤e4|L'¤e4”[/ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}w§m?e> +¤e4¤e4,ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,)&È·£°‚[—]0¤e4’Z.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ HFBÀ¢‡P1=%¤e4¤e4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¦›Œ¡c3 ža2¤e4xJ&ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgd\¨oB~M(V5¤e4=&ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¼«š¤e4e> £d4£e4 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ.-)¼¢†°‚]a2¤e4V5ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿXWR“…¥h8¤e4‘Y.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ {¤e4Ÿb2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿvpd©~Xÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿ÿÿ¿ÿÿ¿ÿÿ¿ÿÿÿÿÿþÿþÿþÿþÿþÿþÿÿÿÿÿÿÿÿ€ÿÀÿÀÿàÿð?ÿð?ÿü?ÿÿ?( ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿMKDÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛ‡EÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÇÛ‡EU3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÇÛ‡EÙ…DÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÇóÇÛ‡EQ2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ óÇÛ‡EÛ‡EÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÇóÇÛ‡Eÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ óÇc=Û‡EU4ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÇóÇ“Z.Û‡EÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÇóÇÛ‡Eÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&*(óÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&&#ÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿýÿùÿðÿðð?ð?ðøøüüþÿÿÏ(0`           ! ! " % ' ) ,6!8":$$#!'&#@()'$B)C**)&J-L/M/N0R1S3U422/d= <;7e> h@!pD$BB>sG$FD@wI&HFB|L'}M(LJFKKHƒP)ˆT*ˆT+‰T+ŒV-W-UTLWUO”Z/VWS•\/–\/”]/š_1œ`1]\Wa2ža2œb2Ÿb2Ÿb3 b4 c3¡c3¡c4¢d3¢d4£e4¤e4¤f5¥f6¥j:¦j:¦k<igchiciiemkf§pC¨rEqpj«yN¬{Q¬{R{zv›e¯‚[‚‚|´Žk²Žm´m¶“r¼Ÿ‚¼ „½¢†¸¢Š ¡ž¿¤Š¥§ ¦¨¥Á«“ì“ï™Å±šÇ±šÄ¸§È¹¤·º´Ë¼ªË½«¼½»¾¾¸ÆÈÅÔÌÀÖÏÃØÔÊÐÓÑØÕËÛ×ÎÚÙÐÜÙÑÛÚÒÖÙØÝÜÖßÞØßßÙßßÚãääãæãäæãäèæåéèçëêêìììîî}$= ˜"_Z‰¡ __^ ,¡¡ƒ___Lf¡v1____6œd ___D?J‘_\___Hk“__E___h–__-0___P>™__K____'Ÿl__V___Y w__;____3~‡__@#_____A’___\____žq__/8_____{|jn[_____.<Ž—y_%C____Y Šr€______)…__!N____M”a_O(_____•u__*Q___S9eˆ______šs__N T___oc__2___X ‹___+Y___5&›qbiWF___]RŒ‚______†m_____7g„_____Bx____G:t___U4z___Ip` ÿÿÿÿÿÿÿÿïÿÿÿÿÿïÿÿÿÿÿÇÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÏÿÿÿÿÿÇÿÿÿÿÿÏÿÿÿÿÿÇÿÿÿÿÿƒÿÿÿÿýÿÿÿÿþÿÿÿÿüÿÿÿþ?ÿÿÿø?ÿÿÿø(¿ÿÿÿø_ÿÿÿø /ÿÿÿðÿÿÿþÿÿÿüÿÿÿü/ÿÿÿüÿÿÿþÿÿÿüÿÿÿþ ÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿ‚ÿÿÿÿÿÿÿ€€ÿÿÿÿÀÿÿÿà"?ÿÿÿàÿÿÿð ¿ÿÿÿðÿÿÿø?ÿÿÿüÿÿÿþ€ÿÿÿÿ_ÿÿÿÿ€ÿÿÿÿ€ÿÿÿÿàÿÿÿÿðÿÿÿÿþÿÿÿÿÿ_ÿ( @          ! " $ 5!8";$%# >&,+)2/,42.[8983jA!{M'€N)€O(O)NMGƒQ*‡S+VQIRQMŒU,ŒV-W-X-‘Z.–\/—]/—]0˜]0ža2žb3 c3£d4£e4¤e4gc]¥i9¦l=olg©qDvsmxuo­|S®Y³‰eŒŠ…‹†¶l·‘p‘е”vº•uº—w¼œ¡ —¤ ˜À§Ãª‘­¬¨¸® ¼°¡É´ŸÌº§ÍÀ¯ÏÁ³ÕÎÁÒÏÇÙÓÉÒÓÎ×Ø× ^2_] <<TW <<<<-R<<<)E<<#L<",ÿÿÿÿÿ÷ÿÿÿóÿÿÿ÷ÿÿÿ÷ÿÿÿ÷ÿÿÿãÿÿÿÁÿÿÿàÿÿÿÀÿÿ€¿ÿÿ?ÿÿˆ¿ÿÿÀÿÿ‚?ÿÿ€ÿÿÀ/ÿÿÀÿÿâÿÿÀÿÿè‹ÿÿàÿÿø‹ÿÿðÿÿø#ÿÿüÿÿþÿÿÿÿÿÿ‚ÿÿÿÁÿÿÿâÿÿÿõÿ(0   +,=%&$!=&,)&L/.-)P1V5e> h@!HFBxJ&|L'~M(€O)„Q*‘Z.”[/—]0a2ža2Ÿb2¡c3£d4£e4¤e4¥h8gd\§m?¨oBvpdppk©~X}w°‚[°‚] {“…¦›Œ¼¢†À¢‡Â¦Ã¨¼«šÇ¯˜È·£Æ½±ÓÆ·ÜÝÙB 1A + <+;"+!>+)+ @++#3. ++ ?4$+:++8(&+-/+=+)*95%+7,+6+'02 ÿÿÿÿ¿ÿÿ¿ÿÿ?ÿÿ¿ÿÿÿþ/ÿþÿþ/ÿüCÿþ#ÿþÿþ#ÿÿÿÿÿÿÿˆÿÿÀÿàÿÿÀÿè¿ÿðÿþ?ÿÿ?(  &&#&*(Q2U3U4c=MKD“Z.Ù…DÛ‡EóÇÿÿÿ          ÿÿýÿýÿñÿøÿðø?ð?ø?øø?üþþÿÿßtcl8.6.5/win/configure0000755000175000017500000053646712665173607014323 0ustar sergeisergei#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59. # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="../generic/tcl.h" # Factoring default headers for most tests. ac_includes_default="\ #include #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if STDC_HEADERS # include # include #else # if HAVE_STDLIB_H # include # endif #endif #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #endif #if HAVE_STRINGS_H # include #endif #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #if HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP AR ac_ct_AR RANLIB ac_ct_RANLIB RC ac_ct_RC SET_MAKE TCL_THREADS CYGPATH CELIB_DIR DL_LIBS CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING ZLIB_DLL_FILE ZLIB_LIBS ZLIB_OBJS CFLAGS_DEFAULT LDFLAGS_DEFAULT VC_MANIFEST_EMBED_DLL VC_MANIFEST_EMBED_EXE TCL_WIN_VERSION MACHINE TCL_VERSION TCL_MAJOR_VERSION TCL_MINOR_VERSION TCL_PATCH_LEVEL PKG_CFG_ARGS TCL_EXE TCL_LIB_FILE TCL_LIB_FLAG TCL_STATIC_LIB_FILE TCL_STATIC_LIB_FLAG TCL_IMPORT_LIB_FILE TCL_IMPORT_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_STUB_LIB_PATH TCL_INCLUDE_SPEC TCL_BUILD_STUB_LIB_SPEC TCL_BUILD_STUB_LIB_PATH TCL_DLL_FILE TCL_SRC_DIR TCL_BIN_DIR TCL_DBGX CFG_TCL_SHARED_LIB_SUFFIX CFG_TCL_UNSHARED_LIB_SUFFIX CFG_TCL_EXPORT_FILE_SUFFIX EXTRA_CFLAGS DEPARG CC_OBJNAME CC_EXENAME LDFLAGS_DEBUG LDFLAGS_OPTIMIZE LDFLAGS_CONSOLE LDFLAGS_WINDOW STLIB_LD SHLIB_LD SHLIB_LD_LIBS SHLIB_CFLAGS SHLIB_SUFFIX TCL_SHARED_BUILD LIBS_GUI DLLSUFFIX LIBPREFIX LIBSUFFIX EXESUFFIX LIBRARIES MAKE_LIB MAKE_STUB_LIB POST_MAKE_LIB MAKE_DLL MAKE_EXE TCL_BUILD_LIB_SPEC TCL_LD_SEARCH_FLAGS TCL_NEEDS_EXP_FILE TCL_BUILD_EXP_FILE TCL_EXP_FILE TCL_LIB_VERSIONS_OK TCL_PACKAGE_PATH TCL_DDE_VERSION TCL_DDE_MAJOR_VERSION TCL_DDE_MINOR_VERSION TCL_REG_VERSION TCL_REG_MAJOR_VERSION TCL_REG_MINOR_VERSION RC_OUT RC_TYPE RC_INCLUDE RC_DEFINE RC_DEFINES RES LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias ac_env_CC_set=${CC+set} ac_env_CC_value=$CC ac_cv_env_CC_set=${CC+set} ac_cv_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_env_CPP_set=${CPP+set} ac_env_CPP_value=$CPP ac_cv_env_CPP_set=${CPP+set} ac_cv_env_CPP_value=$CPP # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-threads build with threads (default: on) --enable-shared build and link with shared libraries (default: on) --enable-64bit enable 64bit support (where applicable) --enable-wince enable Win/CE support (where applicable) --enable-symbols build with debugging symbols (default: off) --enable-embedded-manifest embed manifest if possible (default: yes) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-encoding encoding for configuration values --with-celib=DIR use Windows/CE support library from DIR Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd $ac_popdir done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # The following define is needed when building with Cygwin since newer # versions of autoconf incorrectly set SHELL to /bin/bash instead of # /bin/sh. The bash shell seems to suffer from some strange failures. SHELL=/bin/sh TCL_VERSION=8.6 TCL_MAJOR_VERSION=8 TCL_MINOR_VERSION=6 TCL_PATCH_LEVEL=".5" VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION TCL_DDE_VERSION=1.4 TCL_DDE_MAJOR_VERSION=1 TCL_DDE_MINOR_VERSION=4 DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION TCL_REG_VERSION=1.3 TCL_REG_MAJOR_VERSION=1 TCL_REG_MINOR_VERSION=3 REGVER=$TCL_REG_MAJOR_VERSION$TCL_REG_MINOR_VERSION PKG_CFG_ARGS=$@ #------------------------------------------------------------------------ # Empty slate for bundled packages, to avoid stale configuration #------------------------------------------------------------------------ rm -Rf pkgs #------------------------------------------------------------------------ # Handle the --prefix=... option #------------------------------------------------------------------------ if test "${prefix}" = "NONE"; then prefix=/usr/local fi if test "${exec_prefix}" = "NONE"; then exec_prefix=$prefix fi # libdir must be a fully qualified path (not ${exec_prefix}/lib) eval libdir="$libdir" #------------------------------------------------------------------------ # Standard compiler checks #------------------------------------------------------------------------ # If the user did not set CFLAGS, set it now to keep # the AC_PROG_CC macro from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Find the output, starting from the most likely. This scheme is # not robust to junk in `.', hence go to wildcards (a.*) only as a last # resort. # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= # b.out is created by i960 compilers. for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; conftest.$ac_ext ) # This is the source file. ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` # FIXME: I believe we export ac_cv_exeext for Libtool, # but it would be cool to find out if it's true. Does anybody # maintain Libtool? --akim. export ac_cv_exeext break;; * ) break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6 # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6 echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` export ac_cv_exeext break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6 rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6 OBJEXT=$ac_cv_objext ac_objext=$OBJEXT echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std1 is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std1. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking for inline" >&5 echo $ECHO_N "checking for inline... $ECHO_C" >&6 if test "${ac_cv_c_inline+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_inline=$ac_kw; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done fi echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 echo "${ECHO_T}$ac_cv_c_inline" >&6 case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6 ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6 if test "${ac_cv_prog_egrep+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 echo "${ECHO_T}$ac_cv_prog_egrep" >&6 EGREP=$ac_cv_prog_egrep echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_AR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="${ac_tool_prefix}ar" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then echo "$as_me:$LINENO: result: $AR" >&5 echo "${ECHO_T}$AR" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_AR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="ar" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 echo "${ECHO_T}$ac_ct_AR" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi AR=$ac_ct_AR else AR="$ac_cv_prog_AR" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi RANLIB=$ac_ct_RANLIB else RANLIB="$ac_cv_prog_RANLIB" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. set dummy ${ac_tool_prefix}windres; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_RC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RC"; then ac_cv_prog_RC="$RC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RC="${ac_tool_prefix}windres" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi RC=$ac_cv_prog_RC if test -n "$RC"; then echo "$as_me:$LINENO: result: $RC" >&5 echo "${ECHO_T}$RC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_RC"; then ac_ct_RC=$RC # Extract the first word of "windres", so it can be a program name with args. set dummy windres; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_RC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RC"; then ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RC="windres" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_RC=$ac_cv_prog_ac_ct_RC if test -n "$ac_ct_RC"; then echo "$as_me:$LINENO: result: $ac_ct_RC" >&5 echo "${ECHO_T}$ac_ct_RC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi RC=$ac_ct_RC else RC="$ac_cv_prog_RC" fi #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftest.make fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 SET_MAKE= else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 SET_MAKE="MAKE=${MAKE-make}" fi #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) #-------------------------------------------------------------------- #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. #-------------------------------------------------------------------- echo "$as_me:$LINENO: checking for building with threads" >&5 echo $ECHO_N "checking for building with threads... $ECHO_C" >&6 # Check whether --enable-threads or --disable-threads was given. if test "${enable_threads+set}" = set; then enableval="$enable_threads" tcl_ok=$enableval else tcl_ok=yes fi; if test "$tcl_ok" = "yes"; then echo "$as_me:$LINENO: result: yes (default)" >&5 echo "${ECHO_T}yes (default)" >&6 TCL_THREADS=1 cat >>confdefs.h <<\_ACEOF #define TCL_THREADS 1 _ACEOF # USE_THREAD_ALLOC tells us to try the special thread-based # allocator that significantly reduces lock contention cat >>confdefs.h <<\_ACEOF #define USE_THREAD_ALLOC 1 _ACEOF else TCL_THREADS=0 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi #------------------------------------------------------------------------ # Embedded configuration information, encoding to use for the values, TIP #59 #------------------------------------------------------------------------ # Check whether --with-encoding or --without-encoding was given. if test "${with_encoding+set}" = set; then withval="$with_encoding" with_tcencoding=${withval} fi; if test x"${with_tcencoding}" != x ; then cat >>confdefs.h <<_ACEOF #define TCL_CFGVAL_ENCODING "${with_tcencoding}" _ACEOF else # Default encoding on windows is not "iso8859-1" cat >>confdefs.h <<\_ACEOF #define TCL_CFGVAL_ENCODING "cp1252" _ACEOF fi #-------------------------------------------------------------------- # The statements below define a collection of symbols related to # building libtcl as a shared library instead of a static library. #-------------------------------------------------------------------- echo "$as_me:$LINENO: checking how to build libraries" >&5 echo $ECHO_N "checking how to build libraries... $ECHO_C" >&6 # Check whether --enable-shared or --disable-shared was given. if test "${enable_shared+set}" = set; then enableval="$enable_shared" tcl_ok=$enableval else tcl_ok=yes fi; if test "${enable_shared+set}" = set; then enableval="$enable_shared" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" ; then echo "$as_me:$LINENO: result: shared" >&5 echo "${ECHO_T}shared" >&6 SHARED_BUILD=1 else echo "$as_me:$LINENO: result: static" >&5 echo "${ECHO_T}static" >&6 SHARED_BUILD=0 cat >>confdefs.h <<\_ACEOF #define STATIC_BUILD 1 _ACEOF fi #-------------------------------------------------------------------- # The statements below define a collection of compile flags. This # macro depends on the value of SHARED_BUILD, and should be called # after SC_ENABLE_SHARED checks the configure switches. #-------------------------------------------------------------------- # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Step 0: Enable 64 bit support? echo "$as_me:$LINENO: checking if 64bit support is requested" >&5 echo $ECHO_N "checking if 64bit support is requested... $ECHO_C" >&6 # Check whether --enable-64bit or --disable-64bit was given. if test "${enable_64bit+set}" = set; then enableval="$enable_64bit" do64bit=$enableval else do64bit=no fi; echo "$as_me:$LINENO: result: $do64bit" >&5 echo "${ECHO_T}$do64bit" >&6 # Cross-compiling options for Windows/CE builds echo "$as_me:$LINENO: checking if Windows/CE build is requested" >&5 echo $ECHO_N "checking if Windows/CE build is requested... $ECHO_C" >&6 # Check whether --enable-wince or --disable-wince was given. if test "${enable_wince+set}" = set; then enableval="$enable_wince" doWince=$enableval else doWince=no fi; echo "$as_me:$LINENO: result: $doWince" >&5 echo "${ECHO_T}$doWince" >&6 echo "$as_me:$LINENO: checking for Windows/CE celib directory" >&5 echo $ECHO_N "checking for Windows/CE celib directory... $ECHO_C" >&6 # Check whether --with-celib or --without-celib was given. if test "${with_celib+set}" = set; then withval="$with_celib" CELIB_DIR=$withval else CELIB_DIR=NO_CELIB fi; echo "$as_me:$LINENO: result: $CELIB_DIR" >&5 echo "${ECHO_T}$CELIB_DIR" >&6 # Set some defaults (may get changed below) EXTRA_CFLAGS="" cat >>confdefs.h <<\_ACEOF #define MODULE_SCOPE extern _ACEOF # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CYGPATH+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CYGPATH"; then ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CYGPATH="cygpath -m" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" fi fi CYGPATH=$ac_cv_prog_CYGPATH if test -n "$CYGPATH"; then echo "$as_me:$LINENO: result: $CYGPATH" >&5 echo "${ECHO_T}$CYGPATH" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi SHLIB_SUFFIX=".dll" # MACHINE is IX86 for LINK, but this is used by the manifest, # which requires x86|amd64|ia64. MACHINE="X86" if test "$GCC" = "yes"; then echo "$as_me:$LINENO: checking for cross-compile version of gcc" >&5 echo $ECHO_N "checking for cross-compile version of gcc... $ECHO_C" >&6 if test "${ac_cv_cross+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifndef _WIN32 #error cross-compiler #endif int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_cross=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_cross=yes fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_cross" >&5 echo "${ECHO_T}$ac_cv_cross" >&6 if test "$ac_cv_cross" = "yes"; then case "$do64bit" in amd64|x64|yes) CC="x86_64-w64-mingw32-gcc" LD="x86_64-w64-mingw32-ld" AR="x86_64-w64-mingw32-ar" RANLIB="x86_64-w64-mingw32-ranlib" RC="x86_64-w64-mingw32-windres" ;; *) CC="i686-w64-mingw32-gcc" LD="i686-w64-mingw32-ld" AR="i686-w64-mingw32-ar" RANLIB="i686-w64-mingw32-ranlib" RC="i686-w64-mingw32-windres" ;; esac fi fi # Check for a bug in gcc's windres that causes the # compile to fail when a Windows native path is # passed into windres. The mingw toolchain requires # Windows native paths while Cygwin should work # with both. Avoid the bug by passing a POSIX # path when using the Cygwin toolchain. if test "$GCC" = "yes" && test "$CYGPATH" != "echo" ; then conftest=/tmp/conftest.rc echo "STRINGTABLE BEGIN" > $conftest echo "101 \"name\"" >> $conftest echo "END" >> $conftest echo "$as_me:$LINENO: checking for Windows native path bug in windres" >&5 echo $ECHO_N "checking for Windows native path bug in windres... $ECHO_C" >&6 cyg_conftest=`$CYGPATH $conftest` if { ac_try='$RC -o conftest.res.o $cyg_conftest' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } ; then echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 else echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 CYGPATH=echo fi conftest= cyg_conftest= fi if test "$CYGPATH" = "echo"; then DEPARG='"$<"' else DEPARG='"$(shell $(CYGPATH) $<)"' fi # set various compiler flags depending on whether we are using gcc or cl if test "${GCC}" = "yes" ; then extra_cflags="-pipe" extra_ldflags="-pipe -static-libgcc" echo "$as_me:$LINENO: checking for mingw32 version of gcc" >&5 echo $ECHO_N "checking for mingw32 version of gcc... $ECHO_C" >&6 if test "${ac_cv_win32+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef _WIN32 #error win32 #endif int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_win32=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_win32=yes fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_win32" >&5 echo "${ECHO_T}$ac_cv_win32" >&6 if test "$ac_cv_win32" != "yes"; then { { echo "$as_me:$LINENO: error: ${CC} cannot produce win32 executables." >&5 echo "$as_me: error: ${CC} cannot produce win32 executables." >&2;} { (exit 1); exit 1; }; } fi hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -mwindows -municode -Dmain=xxmain" echo "$as_me:$LINENO: checking for working -municode linker flag" >&5 echo $ECHO_N "checking for working -municode linker flag... $ECHO_C" >&6 if test "${ac_cv_municode+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int APIENTRY wWinMain(HINSTANCE a, HINSTANCE b, LPWSTR c, int d) {return 0;} int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_municode=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_municode=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_municode" >&5 echo "${ECHO_T}$ac_cv_municode" >&6 CFLAGS=$hold_cflags if test "$ac_cv_municode" = "yes" ; then extra_ldflags="$extra_ldflags -municode" else extra_cflags="$extra_cflags -DTCL_BROKEN_MAINARGS" fi fi echo "$as_me:$LINENO: checking compiler flags" >&5 echo $ECHO_N "checking compiler flags... $ECHO_C" >&6 if test "${GCC}" = "yes" ; then SHLIB_LD="" SHLIB_LD_LIBS='${LIBS}' LIBS="-lnetapi32 -lkernel32 -luser32 -ladvapi32 -luserenv -lws2_32" # mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32" STLIB_LD='${AR} cr' RC_OUT=-o RC_TYPE= RC_INCLUDE=--include RC_DEFINE=--define RES=res.o MAKE_LIB="\${STLIB_LD} \$@" MAKE_STUB_LIB="\${STLIB_LD} \$@" POST_MAKE_LIB="\${RANLIB} \$@" MAKE_EXE="\${CC} -o \$@" LIBPREFIX="lib" if test "${SHARED_BUILD}" = "0" ; then # static echo "$as_me:$LINENO: result: using static flags" >&5 echo "${ECHO_T}using static flags" >&6 runtime= LIBRARIES="\${STATIC_LIBRARIES}" EXESUFFIX="s\${DBGX}.exe" else # dynamic echo "$as_me:$LINENO: result: using shared flags" >&5 echo "${ECHO_T}using shared flags" >&6 # ad-hoc check to see if CC supports -shared. if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then { { echo "$as_me:$LINENO: error: ${CC} does not support the -shared option. You will need to upgrade to a newer version of the toolchain." >&5 echo "$as_me: error: ${CC} does not support the -shared option. You will need to upgrade to a newer version of the toolchain." >&2;} { (exit 1); exit 1; }; } fi runtime= # Add SHLIB_LD_LIBS to the Make rule, not here. EXESUFFIX="\${DBGX}.exe" LIBRARIES="\${SHARED_LIBRARIES}" fi # Link with gcc since ld does not link to default libs like # -luser32 and -lmsvcrt by default. SHLIB_LD='${CC} -shared' SHLIB_LD_LIBS='${LIBS}' MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \$@ ${extra_ldflags} \ -Wl,--out-implib,\$(patsubst %.dll,lib%.a,\$@)" # DLLSUFFIX is separate because it is the building block for # users of tclConfig.sh that may build shared or static. DLLSUFFIX="\${DBGX}.dll" LIBSUFFIX="\${DBGX}.a" LIBFLAGSUFFIX="\${DBGX}" SHLIB_SUFFIX=.dll EXTRA_CFLAGS="${extra_cflags}" CFLAGS_DEBUG=-g CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" CFLAGS_WARNING="-Wall -Wdeclaration-after-statement" LDFLAGS_DEBUG= LDFLAGS_OPTIMIZE= # Specify the CC output file names based on the target name CC_OBJNAME="-o \$@" CC_EXENAME="-o \$@" # Specify linker flags depending on the type of app being # built -- Console vs. Window. # # ORIGINAL COMMENT: # We need to pass -e _WinMain@16 so that ld will use # WinMain() instead of main() as the entry point. We can't # use autoconf to check for this case since it would need # to run an executable and that does not work when # cross compiling. Remove this -e workaround once we # require a gcc that does not have this bug. # # MK NOTE: Tk should use a different mechanism. This causes # interesting problems, such as wish dying at startup. #LDFLAGS_WINDOW="-mwindows -e _WinMain@16 ${extra_ldflags}" LDFLAGS_CONSOLE="-mconsole ${extra_ldflags}" LDFLAGS_WINDOW="-mwindows ${extra_ldflags}" case "$do64bit" in amd64|x64|yes) MACHINE="AMD64" ; # assume AMD64 as default 64-bit build echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6 ;; ia64) MACHINE="IA64" echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6 ;; *) cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifndef _WIN64 #error 32-bit #endif int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then tcl_win_64bit=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_win_64bit=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test "$tcl_win_64bit" = "yes" ; then do64bit=amd64 MACHINE="AMD64" echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6 fi ;; esac else if test "${SHARED_BUILD}" = "0" ; then # static echo "$as_me:$LINENO: result: using static flags" >&5 echo "${ECHO_T}using static flags" >&6 runtime=-MT LIBRARIES="\${STATIC_LIBRARIES}" EXESUFFIX="s\${DBGX}.exe" else # dynamic echo "$as_me:$LINENO: result: using shared flags" >&5 echo "${ECHO_T}using shared flags" >&6 runtime=-MD # Add SHLIB_LD_LIBS to the Make rule, not here. LIBRARIES="\${SHARED_LIBRARIES}" EXESUFFIX="\${DBGX}.exe" case "x`echo \${VisualStudioVersion}`" in x1[4-9]*) lflags="${lflags} -nodefaultlib:libucrt.lib" ;; *) ;; esac fi MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\$@" # DLLSUFFIX is separate because it is the building block for # users of tclConfig.sh that may build shared or static. DLLSUFFIX="\${DBGX}.dll" LIBSUFFIX="\${DBGX}.lib" LIBFLAGSUFFIX="\${DBGX}" # This is a 2-stage check to make sure we have the 64-bit SDK # We have to know where the SDK is installed. # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs if test "$do64bit" != "no" ; then if test "x${MSSDK}x" = "xx" ; then MSSDK="C:/Progra~1/Microsoft Platform SDK" fi MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'` PATH64="" case "$do64bit" in amd64|x64|yes) MACHINE="AMD64" ; # assume AMD64 as default 64-bit build PATH64="${MSSDK}/Bin/Win64/x86/AMD64" ;; ia64) MACHINE="IA64" PATH64="${MSSDK}/Bin/Win64" ;; esac if test ! -d "${PATH64}" ; then { echo "$as_me:$LINENO: WARNING: Could not find 64-bit $MACHINE SDK" >&5 echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK" >&2;} fi echo "$as_me:$LINENO: result: Using 64-bit $MACHINE mode" >&5 echo "${ECHO_T} Using 64-bit $MACHINE mode" >&6 fi LIBS="netapi32.lib kernel32.lib user32.lib advapi32.lib userenv.lib ws2_32.lib" case "x`echo \${VisualStudioVersion}`" in x1[4-9]*) LIBS="$LIBS ucrt.lib" ;; *) ;; esac if test "$do64bit" != "no" ; then # The space-based-path will work for the Makefile, but will # not work if AC_TRY_COMPILE is called. TEA has the # TEA_PATH_NOSPACE to avoid this issue. # Check if _WIN64 is already recognized, and if so we don't # need to modify CC. echo "$as_me:$LINENO: checking whether _WIN64 is declared" >&5 echo $ECHO_N "checking whether _WIN64 is declared... $ECHO_C" >&6 if test "${ac_cv_have_decl__WIN64+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { #ifndef _WIN64 char *p = (char *) _WIN64; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_have_decl__WIN64=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl__WIN64=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_have_decl__WIN64" >&5 echo "${ECHO_T}$ac_cv_have_decl__WIN64" >&6 if test $ac_cv_have_decl__WIN64 = yes; then : else CC="\"${PATH64}/cl.exe\" -I\"${MSSDK}/Include\" \ -I\"${MSSDK}/Include/crt\" \ -I\"${MSSDK}/Include/crt/sys\"" fi RC="\"${MSSDK}/bin/rc.exe\"" CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d" # Do not use -O2 for Win64 - this has proved buggy in code gen. CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}" lflags="${lflags} -nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\"" LINKBIN="\"${PATH64}/link.exe\"" # Avoid 'unresolved external symbol __security_cookie' errors. # c.f. http://support.microsoft.com/?id=894573 LIBS="$LIBS bufferoverflowU.lib" else RC="rc" # -Od - no optimization # -WX - warnings as errors CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d" # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy) CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}" lflags="${lflags} -nologo" LINKBIN="link" fi if test "$doWince" != "no" ; then # Set defaults for common evc4/PPC2003 setup # Currently Tcl requires 300+, possibly 420+ for sockets CEVERSION=420; # could be 211 300 301 400 420 ... TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ... ARCH=ARM; # could be ARM MIPS X86EM ... PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002" if test "$doWince" != "yes"; then # If !yes then the user specified something # Reset ARCH to allow user to skip specifying it ARCH= eval `echo $doWince | awk -F "," '{ \ if (length($1)) { printf "CEVERSION=\"%s\"\n", $1; \ if ($1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \ if (length($2)) { printf "TARGETCPU=\"%s\"\n", toupper($2) }; \ if (length($3)) { printf "ARCH=\"%s\"\n", toupper($3) }; \ if (length($4)) { printf "PLATFORM=\"%s\"\n", $4 }; \ }'` if test "x${ARCH}" = "x" ; then ARCH=$TARGETCPU; fi fi OSVERSION=WCE$CEVERSION; if test "x${WCEROOT}" = "x" ; then WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0" if test ! -d "${WCEROOT}" ; then WCEROOT="C:/Program Files/Microsoft eMbedded Tools" fi fi if test "x${SDKROOT}" = "x" ; then SDKROOT="C:/Program Files/Windows CE Tools" if test ! -d "${SDKROOT}" ; then SDKROOT="C:/Windows CE Tools" fi fi # The space-based-path will work for the Makefile, but will # not work if AC_TRY_COMPILE is called. WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'` SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'` CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` if test ! -d "${CELIB_DIR}/inc"; then { { echo "$as_me:$LINENO: error: Invalid celib directory \"${CELIB_DIR}\"" >&5 echo "$as_me: error: Invalid celib directory \"${CELIB_DIR}\"" >&2;} { (exit 1); exit 1; }; } fi if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"\ -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then { { echo "$as_me:$LINENO: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&5 echo "$as_me: error: could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" >&2;} { (exit 1); exit 1; }; } else CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include" if test -d "${CEINCLUDE}/${TARGETCPU}" ; then CEINCLUDE="${CEINCLUDE}/${TARGETCPU}" fi CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" fi fi if test "$doWince" != "no" ; then CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin" if test "${TARGETCPU}" = "X86"; then CC="${CEBINROOT}/cl.exe" else CC="${CEBINROOT}/cl${ARCH}.exe" fi CC="\"${CC}\" -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\"" RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" arch=`echo ${ARCH} | awk '{print tolower($0)}'` defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _DLL _WINDOWS" for i in $defs ; do cat >>confdefs.h <<_ACEOF #define $i 1 _ACEOF done # if test "${ARCH}" = "X86EM"; then # AC_DEFINE_UNQUOTED(_WIN32_WCE_EMULATION) # fi cat >>confdefs.h <<_ACEOF #define _WIN32_WCE $CEVERSION _ACEOF cat >>confdefs.h <<_ACEOF #define UNDER_CE $CEVERSION _ACEOF CFLAGS_DEBUG="-nologo -Zi -Od" CFLAGS_OPTIMIZE="-nologo -O2" lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'` lflags="-nodefaultlib -MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" LINKBIN="\"${CEBINROOT}/link.exe\"" if test "${CEVERSION}" -lt 400 ; then LIBS="coredll.lib corelibc.lib winsock.lib" else LIBS="coredll.lib corelibc.lib ws2.lib" fi # celib currently stuck at wce300 status #LIBS="$LIBS \${CELIB_DIR}/wince-${ARCH}-pocket-${OSVERSION}-release/celib.lib" LIBS="$LIBS \"\${CELIB_DIR}/wince-${ARCH}-pocket-wce300-release/celib.lib\"" LIBS_GUI="commctrl.lib commdlg.lib" else LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib" fi SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}" SHLIB_LD_LIBS='${LIBS}' # link -lib only works when -lib is the first arg STLIB_LD="${LINKBIN} -lib ${lflags}" RC_OUT=-fo RC_TYPE=-r RC_INCLUDE=-i RC_DEFINE=-d RES=res MAKE_LIB="\${STLIB_LD} -out:\$@" MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\$@" POST_MAKE_LIB= MAKE_EXE="\${CC} -Fe\$@" LIBPREFIX="" CFLAGS_DEBUG="${CFLAGS_DEBUG} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE" CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE" EXTRA_CFLAGS="" CFLAGS_WARNING="-W3" LDFLAGS_DEBUG="-debug" LDFLAGS_OPTIMIZE="-release" # Specify the CC output file names based on the target name CC_OBJNAME="-Fo\$@" CC_EXENAME="-Fe\"\$(shell \$(CYGPATH) '\$@')\"" # Specify linker flags depending on the type of app being # built -- Console vs. Window. if test "$doWince" != "no" -a "${TARGETCPU}" != "X86"; then LDFLAGS_CONSOLE="-link ${lflags}" LDFLAGS_WINDOW=${LDFLAGS_CONSOLE} else LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" fi fi if test "$do64bit" != "no" ; then cat >>confdefs.h <<\_ACEOF #define TCL_CFG_DO64BIT 1 _ACEOF fi if test "${GCC}" = "yes" ; then echo "$as_me:$LINENO: checking for SEH support in compiler" >&5 echo $ECHO_N "checking for SEH support in compiler... $ECHO_C" >&6 if test "${tcl_cv_seh+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then tcl_cv_seh=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main(int argc, char** argv) { int a, b = 0; __try { a = 666 / b; } __except (EXCEPTION_EXECUTE_HANDLER) { return 0; } return 1; } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then tcl_cv_seh=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) tcl_cv_seh=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $tcl_cv_seh" >&5 echo "${ECHO_T}$tcl_cv_seh" >&6 if test "$tcl_cv_seh" = "no" ; then cat >>confdefs.h <<\_ACEOF #define HAVE_NO_SEH 1 _ACEOF fi # # Check to see if the excpt.h include file provided contains the # definition for EXCEPTION_DISPOSITION; if not, which is the case # with Cygwin's version as of 2002-04-10, define it to be int, # sufficient for getting the current code to work. # echo "$as_me:$LINENO: checking for EXCEPTION_DISPOSITION support in include files" >&5 echo $ECHO_N "checking for EXCEPTION_DISPOSITION support in include files... $ECHO_C" >&6 if test "${tcl_cv_eh_disposition+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ # define WIN32_LEAN_AND_MEAN # include # undef WIN32_LEAN_AND_MEAN int main () { EXCEPTION_DISPOSITION x; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then tcl_cv_eh_disposition=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_eh_disposition=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $tcl_cv_eh_disposition" >&5 echo "${ECHO_T}$tcl_cv_eh_disposition" >&6 if test "$tcl_cv_eh_disposition" = "no" ; then cat >>confdefs.h <<\_ACEOF #define EXCEPTION_DISPOSITION int _ACEOF fi # Check to see if winnt.h defines CHAR, SHORT, and LONG # even if VOID has already been #defined. The win32api # used by mingw and cygwin is known to do this. echo "$as_me:$LINENO: checking for winnt.h that ignores VOID define" >&5 echo $ECHO_N "checking for winnt.h that ignores VOID define... $ECHO_C" >&6 if test "${tcl_cv_winnt_ignore_void+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define VOID void #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main () { CHAR c; SHORT s; LONG l; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then tcl_cv_winnt_ignore_void=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_winnt_ignore_void=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $tcl_cv_winnt_ignore_void" >&5 echo "${ECHO_T}$tcl_cv_winnt_ignore_void" >&6 if test "$tcl_cv_winnt_ignore_void" = "yes" ; then cat >>confdefs.h <<\_ACEOF #define HAVE_WINNT_IGNORE_VOID 1 _ACEOF fi # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. echo "$as_me:$LINENO: checking for cast to union support" >&5 echo $ECHO_N "checking for cast to union support... $ECHO_C" >&6 if test "${tcl_cv_cast_to_union+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { union foo { int i; double d; }; union foo f = (union foo) (int) 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then tcl_cv_cast_to_union=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_cast_to_union=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $tcl_cv_cast_to_union" >&5 echo "${ECHO_T}$tcl_cv_cast_to_union" >&6 if test "$tcl_cv_cast_to_union" = "yes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_CAST_TO_UNION 1 _ACEOF fi fi # DL_LIBS is empty, but then we match the Unix version # Cross-compiling case ${host_alias} in *mingw32*) TCL_EXE="tclsh" ;; *) TCL_EXE="TCL_LIBRARY=\"\${LIBRARY_DIR}\"; export TCL_LIBRARY; ./\${TCLSH}" ;; esac #------------------------------------------------------------------------ # Add stuff for zlib; note that this is mostly done in the makefile now # as we just assume that the platform hasn't got a usable z.lib #------------------------------------------------------------------------ if test "${enable_shared+set}" = "set"; then enableval="$enable_shared" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes"; then ZLIB_DLL_FILE=\${ZLIB_DLL_FILE} if test "$do64bit" = "yes"; then if test "$GCC" == "yes"; then ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win64/libz.dll.a else ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win64/zdll.lib fi else ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win32/zdll.lib fi else ZLIB_OBJS=\${ZLIB_OBJS} fi cat >>confdefs.h <<\_ACEOF #define HAVE_ZLIB 1 _ACEOF echo "$as_me:$LINENO: checking for intptr_t" >&5 echo $ECHO_N "checking for intptr_t... $ECHO_C" >&6 if test "${ac_cv_type_intptr_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((intptr_t *) 0) return 0; if (sizeof (intptr_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_intptr_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_intptr_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_intptr_t" >&5 echo "${ECHO_T}$ac_cv_type_intptr_t" >&6 if test $ac_cv_type_intptr_t = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_INTPTR_T 1 _ACEOF else echo "$as_me:$LINENO: checking for pointer-size signed integer type" >&5 echo $ECHO_N "checking for pointer-size signed integer type... $ECHO_C" >&6 if test "${tcl_cv_intptr_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else for tcl_cv_intptr_t in "int" "long" "long long" none; do if test "$tcl_cv_intptr_t" != none; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_intptr_t))]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then tcl_ok=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_ok=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext test "$tcl_ok" = yes && break; fi done fi echo "$as_me:$LINENO: result: $tcl_cv_intptr_t" >&5 echo "${ECHO_T}$tcl_cv_intptr_t" >&6 if test "$tcl_cv_intptr_t" != none; then cat >>confdefs.h <<_ACEOF #define intptr_t $tcl_cv_intptr_t _ACEOF fi fi echo "$as_me:$LINENO: checking for uintptr_t" >&5 echo $ECHO_N "checking for uintptr_t... $ECHO_C" >&6 if test "${ac_cv_type_uintptr_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if ((uintptr_t *) 0) return 0; if (sizeof (uintptr_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_uintptr_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_uintptr_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_uintptr_t" >&5 echo "${ECHO_T}$ac_cv_type_uintptr_t" >&6 if test $ac_cv_type_uintptr_t = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_UINTPTR_T 1 _ACEOF else echo "$as_me:$LINENO: checking for pointer-size unsigned integer type" >&5 echo $ECHO_N "checking for pointer-size unsigned integer type... $ECHO_C" >&6 if test "${tcl_cv_uintptr_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \ none; do if test "$tcl_cv_uintptr_t" != none; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_uintptr_t))]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then tcl_ok=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_ok=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext test "$tcl_ok" = yes && break; fi done fi echo "$as_me:$LINENO: result: $tcl_cv_uintptr_t" >&5 echo "${ECHO_T}$tcl_cv_uintptr_t" >&6 if test "$tcl_cv_uintptr_t" != none; then cat >>confdefs.h <<_ACEOF #define uintptr_t $tcl_cv_uintptr_t _ACEOF fi fi #-------------------------------------------------------------------- # Perform additinal compiler tests. #-------------------------------------------------------------------- # See if declarations like FINDEX_INFO_LEVELS are # missing from winbase.h. This is known to be # a problem with VC++ 5.2. echo "$as_me:$LINENO: checking for FINDEX_INFO_LEVELS in winbase.h" >&5 echo $ECHO_N "checking for FINDEX_INFO_LEVELS in winbase.h... $ECHO_C" >&6 if test "${tcl_cv_findex_enums+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main () { FINDEX_INFO_LEVELS i; FINDEX_SEARCH_OPS j; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then tcl_cv_findex_enums=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_findex_enums=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $tcl_cv_findex_enums" >&5 echo "${ECHO_T}$tcl_cv_findex_enums" >&6 if test "$tcl_cv_findex_enums" = "no"; then cat >>confdefs.h <<\_ACEOF #define HAVE_NO_FINDEX_ENUMS 1 _ACEOF fi # See if the compiler supports intrinsics. echo "$as_me:$LINENO: checking for intrinsics support in compiler" >&5 echo $ECHO_N "checking for intrinsics support in compiler... $ECHO_C" >&6 if test "${tcl_cv_intrinsics+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN #include int main () { __cpuidex(0,0,0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then tcl_cv_intrinsics=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_intrinsics=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $tcl_cv_intrinsics" >&5 echo "${ECHO_T}$tcl_cv_intrinsics" >&6 if test "$tcl_cv_intrinsics" = "yes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_INTRIN_H 1 _ACEOF fi # See if the header file is present echo "$as_me:$LINENO: checking for wspiapi.h" >&5 echo $ECHO_N "checking for wspiapi.h... $ECHO_C" >&6 if test "${tcl_cv_wspiapi_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then tcl_cv_wspiapi_h=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_wspiapi_h=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $tcl_cv_wspiapi_h" >&5 echo "${ECHO_T}$tcl_cv_wspiapi_h" >&6 if test "$tcl_cv_wspiapi_h" = "yes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_WSPIAPI_H 1 _ACEOF fi # See if declarations like FINDEX_INFO_LEVELS are # missing from winbase.h. This is known to be # a problem with VC++ 5.2. echo "$as_me:$LINENO: checking for FINDEX_INFO_LEVELS in winbase.h" >&5 echo $ECHO_N "checking for FINDEX_INFO_LEVELS in winbase.h... $ECHO_C" >&6 if test "${tcl_cv_findex_enums+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main () { FINDEX_INFO_LEVELS i; FINDEX_SEARCH_OPS j; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then tcl_cv_findex_enums=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 tcl_cv_findex_enums=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $tcl_cv_findex_enums" >&5 echo "${ECHO_T}$tcl_cv_findex_enums" >&6 if test "$tcl_cv_findex_enums" = "no"; then cat >>confdefs.h <<\_ACEOF #define HAVE_NO_FINDEX_ENUMS 1 _ACEOF fi #-------------------------------------------------------------------- # Set the default compiler switches based on the --enable-symbols # option. This macro depends on C flags, and should be called # after SC_CONFIG_CFLAGS macro is called. #-------------------------------------------------------------------- echo "$as_me:$LINENO: checking for build with symbols" >&5 echo $ECHO_N "checking for build with symbols... $ECHO_C" >&6 # Check whether --enable-symbols or --disable-symbols was given. if test "${enable_symbols+set}" = set; then enableval="$enable_symbols" tcl_ok=$enableval else tcl_ok=no fi; # FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT. if test "$tcl_ok" = "no"; then CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)' LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)' DBGX="" cat >>confdefs.h <<\_ACEOF #define NDEBUG 1 _ACEOF echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 cat >>confdefs.h <<\_ACEOF #define TCL_CFG_OPTIMIZED 1 _ACEOF else CFLAGS_DEFAULT='$(CFLAGS_DEBUG)' LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)' DBGX=g if test "$tcl_ok" = "yes"; then echo "$as_me:$LINENO: result: yes (standard debugging)" >&5 echo "${ECHO_T}yes (standard debugging)" >&6 fi fi if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then cat >>confdefs.h <<\_ACEOF #define TCL_MEM_DEBUG 1 _ACEOF fi if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then cat >>confdefs.h <<\_ACEOF #define TCL_COMPILE_DEBUG 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define TCL_COMPILE_STATS 1 _ACEOF fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then echo "$as_me:$LINENO: result: enabled symbols mem compile debugging" >&5 echo "${ECHO_T}enabled symbols mem compile debugging" >&6 else echo "$as_me:$LINENO: result: enabled $tcl_ok debugging" >&5 echo "${ECHO_T}enabled $tcl_ok debugging" >&6 fi fi TCL_DBGX=${DBGX} #-------------------------------------------------------------------- # Embed the manifest if we can determine how #-------------------------------------------------------------------- echo "$as_me:$LINENO: checking whether to embed manifest" >&5 echo $ECHO_N "checking whether to embed manifest... $ECHO_C" >&6 # Check whether --enable-embedded-manifest or --disable-embedded-manifest was given. if test "${enable_embedded_manifest+set}" = set; then enableval="$enable_embedded_manifest" embed_ok=$enableval else embed_ok=yes fi; VC_MANIFEST_EMBED_DLL= VC_MANIFEST_EMBED_EXE= result=no if test "$embed_ok" = "yes" -a "${SHARED_BUILD}" = "1" \ -a "$GCC" != "yes" ; then # Add the magic to embed the manifest into the dll/exe cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if defined(_MSC_VER) && _MSC_VER >= 1400 print("manifest needed") #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "manifest needed" >/dev/null 2>&1; then # Could do a CHECK_PROG for mt, but should always be with MSVC8+ # Could add 'if test -f' check, but manifest should be created # in this compiler case # Add in a manifest argument that may be specified # XXX Needs improvement so that the test for existence accounts # XXX for a provided (known) manifest VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;2 ; fi" VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;1 ; fi" result=yes if test "x" != x ; then result="yes ()" fi fi rm -f conftest* fi echo "$as_me:$LINENO: result: $result" >&5 echo "${ECHO_T}$result" >&6 #------------------------------------------------------------------------ # tclConfig.sh refers to this by a different name #------------------------------------------------------------------------ TCL_SHARED_BUILD=${SHARED_BUILD} #-------------------------------------------------------------------- # Perform final evaluations of variables with possible substitutions. #-------------------------------------------------------------------- TCL_SHARED_LIB_SUFFIX="\${NODOT_VERSION}${DLLSUFFIX}" TCL_UNSHARED_LIB_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}" TCL_EXPORT_FILE_SUFFIX="\${NODOT_VERSION}${LIBSUFFIX}" eval "TCL_SRC_DIR=\"`cd $srcdir/..; $CYGPATH $(pwd)`\"" eval "TCL_DLL_FILE=tcl${VER}${DLLSUFFIX}" eval "TCL_STUB_LIB_FILE=\"${LIBPREFIX}tclstub${VER}${LIBSUFFIX}\"" eval "TCL_STUB_LIB_FLAG=\"-ltclstub${VER}${LIBFLAGSUFFIX}\"" eval "TCL_BUILD_STUB_LIB_SPEC=\"-L`$CYGPATH $(pwd)` ${TCL_STUB_LIB_FLAG}\"" eval "TCL_STUB_LIB_SPEC=\"-L${libdir} ${TCL_STUB_LIB_FLAG}\"" eval "TCL_BUILD_STUB_LIB_PATH=\"`$CYGPATH $(pwd)`/${TCL_STUB_LIB_FILE}\"" eval "TCL_STUB_LIB_PATH=\"${libdir}/${TCL_STUB_LIB_FILE}\"" eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${LIBSUFFIX}\"" eval "TCL_BUILD_LIB_SPEC=\"-L`$CYGPATH $(pwd)` -ltcl${VER}${FLAGSUFFIX}\"" eval "TCL_LIB_SPEC=\"-L${libdir} -ltcl${VER}${FLAGSUFFIX}\"" # Install time header dir can be set via --includedir eval "TCL_INCLUDE_SPEC=\"-I${includedir}\"" eval "DLLSUFFIX=${DLLSUFFIX}" eval "LIBPREFIX=${LIBPREFIX}" eval "LIBSUFFIX=${LIBSUFFIX}" eval "EXESUFFIX=${EXESUFFIX}" CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX} CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX} CFG_TCL_EXPORT_FILE_SUFFIX=${TCL_EXPORT_FILE_SUFFIX} #-------------------------------------------------------------------- # Adjust the defines for how the resources are built depending # on symbols and static vs. shared. #-------------------------------------------------------------------- if test ${SHARED_BUILD} = 0 ; then if test "${DBGX}" = "g"; then RC_DEFINES="${RC_DEFINE} STATIC_BUILD ${RC_DEFINE} DEBUG" else RC_DEFINES="${RC_DEFINE} STATIC_BUILD" fi else if test "${DBGX}" = "g"; then RC_DEFINES="${RC_DEFINE} DEBUG" else RC_DEFINES="" fi fi #-------------------------------------------------------------------- # The statements below define the symbol TCL_PACKAGE_PATH, which # gives a list of directories that may contain packages. The list # consists of one directory for machine-dependent binaries and # another for platform-independent scripts. #-------------------------------------------------------------------- if test "$prefix/lib" != "$libdir"; then TCL_PACKAGE_PATH="${libdir} ${prefix}/lib" else TCL_PACKAGE_PATH="${prefix}/lib" fi # The tclsh.exe.manifest requires these # TCL_WIN_VERSION is the 4 dotted pair Windows version format which needs # the release level, and must account for interim release versioning case "$TCL_PATCH_LEVEL" in *a*) TCL_RELEASE_LEVEL=0 ;; *b*) TCL_RELEASE_LEVEL=1 ;; *) TCL_RELEASE_LEVEL=2 ;; esac TCL_WIN_VERSION="$TCL_VERSION.$TCL_RELEASE_LEVEL.`echo $TCL_PATCH_LEVEL | tr -d ab.`" # X86|AMD64|IA64 for manifest # empty on win # win/tcl.m4 doesn't set (CFLAGS) # win/tcl.m4 doesn't set (LDFLAGS) # empty on win, but needs sub'ing # win only ac_config_files="$ac_config_files Makefile tclConfig.sh tcl.hpj tclsh.exe.manifest" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then we branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. cat >confdef2opt.sed <<\_ACEOF t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g t quote s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g t quote d : quote s,[ `~#$^&*(){}\\|;'"<>?],\\&,g s,\[,\\&,g s,\],\\&,g s,\$,$$,g p _ACEOF # We use echo to avoid assuming a particular line-breaking character. # The extra dot is to prevent the shell from consuming trailing # line-breaks from the sub-command output. A line-break within # single-quotes doesn't work because, if this script is created in a # platform that uses two characters for line-breaks (e.g., DOS), tr # would break. ac_LF_and_DOT=`echo; echo .` DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` rm -f confdef2opt.sed ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by $as_me, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "tclConfig.sh" ) CONFIG_FILES="$CONFIG_FILES tclConfig.sh" ;; "tcl.hpj" ) CONFIG_FILES="$CONFIG_FILES tcl.hpj" ;; "tclsh.exe.manifest" ) CONFIG_FILES="$CONFIG_FILES tclsh.exe.manifest" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t s,@CPP@,$CPP,;t t s,@EGREP@,$EGREP,;t t s,@AR@,$AR,;t t s,@ac_ct_AR@,$ac_ct_AR,;t t s,@RANLIB@,$RANLIB,;t t s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@RC@,$RC,;t t s,@ac_ct_RC@,$ac_ct_RC,;t t s,@SET_MAKE@,$SET_MAKE,;t t s,@TCL_THREADS@,$TCL_THREADS,;t t s,@CYGPATH@,$CYGPATH,;t t s,@CELIB_DIR@,$CELIB_DIR,;t t s,@DL_LIBS@,$DL_LIBS,;t t s,@CFLAGS_DEBUG@,$CFLAGS_DEBUG,;t t s,@CFLAGS_OPTIMIZE@,$CFLAGS_OPTIMIZE,;t t s,@CFLAGS_WARNING@,$CFLAGS_WARNING,;t t s,@ZLIB_DLL_FILE@,$ZLIB_DLL_FILE,;t t s,@ZLIB_LIBS@,$ZLIB_LIBS,;t t s,@ZLIB_OBJS@,$ZLIB_OBJS,;t t s,@CFLAGS_DEFAULT@,$CFLAGS_DEFAULT,;t t s,@LDFLAGS_DEFAULT@,$LDFLAGS_DEFAULT,;t t s,@VC_MANIFEST_EMBED_DLL@,$VC_MANIFEST_EMBED_DLL,;t t s,@VC_MANIFEST_EMBED_EXE@,$VC_MANIFEST_EMBED_EXE,;t t s,@TCL_WIN_VERSION@,$TCL_WIN_VERSION,;t t s,@MACHINE@,$MACHINE,;t t s,@TCL_VERSION@,$TCL_VERSION,;t t s,@TCL_MAJOR_VERSION@,$TCL_MAJOR_VERSION,;t t s,@TCL_MINOR_VERSION@,$TCL_MINOR_VERSION,;t t s,@TCL_PATCH_LEVEL@,$TCL_PATCH_LEVEL,;t t s,@PKG_CFG_ARGS@,$PKG_CFG_ARGS,;t t s,@TCL_EXE@,$TCL_EXE,;t t s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t s,@TCL_LIB_FLAG@,$TCL_LIB_FLAG,;t t s,@TCL_STATIC_LIB_FILE@,$TCL_STATIC_LIB_FILE,;t t s,@TCL_STATIC_LIB_FLAG@,$TCL_STATIC_LIB_FLAG,;t t s,@TCL_IMPORT_LIB_FILE@,$TCL_IMPORT_LIB_FILE,;t t s,@TCL_IMPORT_LIB_FLAG@,$TCL_IMPORT_LIB_FLAG,;t t s,@TCL_LIB_SPEC@,$TCL_LIB_SPEC,;t t s,@TCL_STUB_LIB_FILE@,$TCL_STUB_LIB_FILE,;t t s,@TCL_STUB_LIB_FLAG@,$TCL_STUB_LIB_FLAG,;t t s,@TCL_STUB_LIB_SPEC@,$TCL_STUB_LIB_SPEC,;t t s,@TCL_STUB_LIB_PATH@,$TCL_STUB_LIB_PATH,;t t s,@TCL_INCLUDE_SPEC@,$TCL_INCLUDE_SPEC,;t t s,@TCL_BUILD_STUB_LIB_SPEC@,$TCL_BUILD_STUB_LIB_SPEC,;t t s,@TCL_BUILD_STUB_LIB_PATH@,$TCL_BUILD_STUB_LIB_PATH,;t t s,@TCL_DLL_FILE@,$TCL_DLL_FILE,;t t s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t s,@TCL_DBGX@,$TCL_DBGX,;t t s,@CFG_TCL_SHARED_LIB_SUFFIX@,$CFG_TCL_SHARED_LIB_SUFFIX,;t t s,@CFG_TCL_UNSHARED_LIB_SUFFIX@,$CFG_TCL_UNSHARED_LIB_SUFFIX,;t t s,@CFG_TCL_EXPORT_FILE_SUFFIX@,$CFG_TCL_EXPORT_FILE_SUFFIX,;t t s,@EXTRA_CFLAGS@,$EXTRA_CFLAGS,;t t s,@DEPARG@,$DEPARG,;t t s,@CC_OBJNAME@,$CC_OBJNAME,;t t s,@CC_EXENAME@,$CC_EXENAME,;t t s,@LDFLAGS_DEBUG@,$LDFLAGS_DEBUG,;t t s,@LDFLAGS_OPTIMIZE@,$LDFLAGS_OPTIMIZE,;t t s,@LDFLAGS_CONSOLE@,$LDFLAGS_CONSOLE,;t t s,@LDFLAGS_WINDOW@,$LDFLAGS_WINDOW,;t t s,@STLIB_LD@,$STLIB_LD,;t t s,@SHLIB_LD@,$SHLIB_LD,;t t s,@SHLIB_LD_LIBS@,$SHLIB_LD_LIBS,;t t s,@SHLIB_CFLAGS@,$SHLIB_CFLAGS,;t t s,@SHLIB_SUFFIX@,$SHLIB_SUFFIX,;t t s,@TCL_SHARED_BUILD@,$TCL_SHARED_BUILD,;t t s,@LIBS_GUI@,$LIBS_GUI,;t t s,@DLLSUFFIX@,$DLLSUFFIX,;t t s,@LIBPREFIX@,$LIBPREFIX,;t t s,@LIBSUFFIX@,$LIBSUFFIX,;t t s,@EXESUFFIX@,$EXESUFFIX,;t t s,@LIBRARIES@,$LIBRARIES,;t t s,@MAKE_LIB@,$MAKE_LIB,;t t s,@MAKE_STUB_LIB@,$MAKE_STUB_LIB,;t t s,@POST_MAKE_LIB@,$POST_MAKE_LIB,;t t s,@MAKE_DLL@,$MAKE_DLL,;t t s,@MAKE_EXE@,$MAKE_EXE,;t t s,@TCL_BUILD_LIB_SPEC@,$TCL_BUILD_LIB_SPEC,;t t s,@TCL_LD_SEARCH_FLAGS@,$TCL_LD_SEARCH_FLAGS,;t t s,@TCL_NEEDS_EXP_FILE@,$TCL_NEEDS_EXP_FILE,;t t s,@TCL_BUILD_EXP_FILE@,$TCL_BUILD_EXP_FILE,;t t s,@TCL_EXP_FILE@,$TCL_EXP_FILE,;t t s,@TCL_LIB_VERSIONS_OK@,$TCL_LIB_VERSIONS_OK,;t t s,@TCL_PACKAGE_PATH@,$TCL_PACKAGE_PATH,;t t s,@TCL_DDE_VERSION@,$TCL_DDE_VERSION,;t t s,@TCL_DDE_MAJOR_VERSION@,$TCL_DDE_MAJOR_VERSION,;t t s,@TCL_DDE_MINOR_VERSION@,$TCL_DDE_MINOR_VERSION,;t t s,@TCL_REG_VERSION@,$TCL_REG_VERSION,;t t s,@TCL_REG_MAJOR_VERSION@,$TCL_REG_MAJOR_VERSION,;t t s,@TCL_REG_MINOR_VERSION@,$TCL_REG_MINOR_VERSION,;t t s,@RC_OUT@,$RC_OUT,;t t s,@RC_TYPE@,$RC_TYPE,;t t s,@RC_INCLUDE@,$RC_INCLUDE,;t t s,@RC_DEFINE@,$RC_DEFINE,;t t s,@RC_DEFINES@,$RC_DEFINES,;t t s,@RES@,$RES,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi tcl8.6.5/win/tclWinNotify.c0000644000175000017500000003640512663653210015163 0ustar sergeisergei/* * tclWinNotify.c -- * * This file contains Windows-specific procedures for the notifier, which * is the lowest-level part of the Tcl event loop. This file works * together with ../generic/tclNotify.c. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * The follwing static indicates whether this module has been initialized. */ #define INTERVAL_TIMER 1 /* Handle of interval timer. */ #define WM_WAKEUP WM_USER /* Message that is send by * Tcl_AlertNotifier. */ /* * The following static structure contains the state information for the * Windows implementation of the Tcl notifier. One of these structures is * created for each thread that is using the notifier. */ typedef struct ThreadSpecificData { CRITICAL_SECTION crit; /* Monitor for this notifier. */ DWORD thread; /* Identifier for thread associated with this * notifier. */ HANDLE event; /* Event object used to wake up the notifier * thread. */ int pending; /* Alert message pending, this field is locked * by the notifierMutex. */ HWND hwnd; /* Messaging window. */ int timeout; /* Current timeout value. */ int timerActive; /* 1 if interval timer is running. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * The following static indicates the number of threads that have initialized * notifiers. It controls the lifetime of the TclNotifier window class. * * You must hold the notifierMutex lock before accessing this variable. */ static int notifierCount = 0; static const TCHAR classname[] = TEXT("TclNotifier"); TCL_DECLARE_MUTEX(notifierMutex) /* * Static routines defined in this file. */ static LRESULT CALLBACK NotifierProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); /* *---------------------------------------------------------------------- * * Tcl_InitNotifier -- * * Initializes the platform specific notifier state. * * 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 { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); WNDCLASS class; /* * Register Notifier window class if this is the first thread to use * this module. */ Tcl_MutexLock(¬ifierMutex); if (notifierCount == 0) { class.style = 0; class.cbClsExtra = 0; class.cbWndExtra = 0; class.hInstance = TclWinGetTclInstance(); class.hbrBackground = NULL; class.lpszMenuName = NULL; class.lpszClassName = classname; class.lpfnWndProc = NotifierProc; class.hIcon = NULL; class.hCursor = NULL; if (!RegisterClass(&class)) { Tcl_Panic("Unable to register TclNotifier window class"); } } notifierCount++; Tcl_MutexUnlock(¬ifierMutex); tsdPtr->pending = 0; tsdPtr->timerActive = 0; InitializeCriticalSection(&tsdPtr->crit); tsdPtr->hwnd = NULL; tsdPtr->thread = GetCurrentThreadId(); tsdPtr->event = CreateEvent(NULL, TRUE /* manual */, FALSE /* !signaled */, NULL); return tsdPtr; } } /* *---------------------------------------------------------------------- * * Tcl_FinalizeNotifier -- * * This function is called to cleanup the notifier state before a thread * is terminated. * * Results: * None. * * Side effects: * May dispose of the notifier window and class. * *---------------------------------------------------------------------- */ void Tcl_FinalizeNotifier( ClientData clientData) /* Pointer to notifier data. */ { if (tclNotifierHooks.finalizeNotifierProc) { tclNotifierHooks.finalizeNotifierProc(clientData); return; } else { 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. */ if (tsdPtr == NULL) { return; } DeleteCriticalSection(&tsdPtr->crit); CloseHandle(tsdPtr->event); /* * Clean up the timer and messaging window for this thread. */ 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. */ Tcl_MutexLock(¬ifierMutex); notifierCount--; if (notifierCount == 0) { UnregisterClass(classname, TclWinGetTclInstance()); } Tcl_MutexUnlock(¬ifierMutex); } } /* *---------------------------------------------------------------------- * * 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 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. * * Results: * None. * * Side effects: * Sends a message to the messaging window for the notifier if there * isn't already one pending. * *---------------------------------------------------------------------- */ void Tcl_AlertNotifier( ClientData clientData) /* Pointer to thread data. */ { if (tclNotifierHooks.alertNotifierProc) { tclNotifierHooks.alertNotifierProc(clientData); return; } else { 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) { /* * We do need to lock around access to the pending flag. */ EnterCriticalSection(&tsdPtr->crit); if (!tsdPtr->pending) { PostMessage(tsdPtr->hwnd, WM_WAKEUP, 0, 0); } tsdPtr->pending = 1; LeaveCriticalSection(&tsdPtr->crit); } else { SetEvent(tsdPtr->event); } } } /* *---------------------------------------------------------------------- * * Tcl_SetTimer -- * * This procedure sets the current notifier timer value. The notifier * will ensure that Tcl_ServiceAll() is called after the specified * interval, even if no events have occurred. * * Results: * None. * * Side effects: * Replaces any previous timer. * *---------------------------------------------------------------------- */ void Tcl_SetTimer( const Tcl_Time *timePtr) /* Maximum block time, or NULL. */ { if (tclNotifierHooks.setTimerProc) { tclNotifierHooks.setTimerProc(timePtr); return; } else { 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; } 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; } } tsdPtr->timeout = timeout; if (timeout != 0) { tsdPtr->timerActive = 1; SetTimer(tsdPtr->hwnd, INTERVAL_TIMER, (unsigned long) tsdPtr->timeout, NULL); } else { tsdPtr->timerActive = 0; KillTimer(tsdPtr->hwnd, INTERVAL_TIMER); } } } /* *---------------------------------------------------------------------- * * Tcl_ServiceModeHook -- * * This function is invoked whenever the service mode changes. * * Results: * None. * * Side effects: * If this is the first time the notifier is set into TCL_SERVICE_ALL, * then the communication window is created. * *---------------------------------------------------------------------- */ void Tcl_ServiceModeHook( int mode) /* Either TCL_SERVICE_ALL, or * TCL_SERVICE_NONE. */ { if (tclNotifierHooks.serviceModeHookProc) { tclNotifierHooks.serviceModeHookProc(mode); return; } else { 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 (mode == TCL_SERVICE_ALL && !tsdPtr->hwnd) { tsdPtr->hwnd = CreateWindow(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. */ Tcl_AlertNotifier(tsdPtr); } } } /* *---------------------------------------------------------------------- * * NotifierProc -- * * This procedure is invoked by Windows to process events on the notifier * window. Messages will be sent to this window in response to external * timer events or calls to TclpAlertTsdPtr-> * * Results: * A standard windows result. * * Side effects: * Services any pending events. * *---------------------------------------------------------------------- */ static LRESULT CALLBACK NotifierProc( HWND hwnd, /* Passed on... */ UINT message, /* What messsage is this? */ WPARAM wParam, /* Passed on... */ LPARAM lParam) /* Passed on... */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (message == WM_WAKEUP) { EnterCriticalSection(&tsdPtr->crit); tsdPtr->pending = 0; LeaveCriticalSection(&tsdPtr->crit); } else if (message != WM_TIMER) { return DefWindowProc(hwnd, message, wParam, lParam); } /* * Process all of the runnable events. */ Tcl_ServiceAll(); return 0; } /* *---------------------------------------------------------------------- * * Tcl_WaitForEvent -- * * This function is called by Tcl_DoOneEvent to wait for new events on * the message queue. If the block time is 0, then Tcl_WaitForEvent just * polls the event queue without blocking. * * Results: * Returns -1 if a WM_QUIT message is detected, returns 1 if a message * was dispatched, otherwise returns 0. * * Side effects: * Dispatches a message to a window procedure, which could do anything. * *---------------------------------------------------------------------- */ int Tcl_WaitForEvent( 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; /* * Compute the timeout in milliseconds. */ if (timePtr) { /* * TIP #233 (Virtualized Time). Convert virtual domain delay to * real-time. */ Tcl_Time myTime; myTime.sec = timePtr->sec; myTime.usec = timePtr->usec; if (myTime.sec != 0 || myTime.usec != 0) { tclScaleTimeProcPtr(&myTime, tclTimeClientData); } 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 (!PeekMessage(&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: 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; } } /* * Check to see if there are any messages to process. */ if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { /* * Retrieve and dispatch the first message. */ result = GetMessage(&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); DispatchMessage(&msg); status = 1; } } else { status = 0; } end: ResetEvent(tsdPtr->event); return status; } } /* *---------------------------------------------------------------------- * * Tcl_Sleep -- * * Delay execution for the specified number of milliseconds. * * Results: * None. * * Side effects: * Time passes. * *---------------------------------------------------------------------- */ void Tcl_Sleep( int ms) /* Number of milliseconds to sleep. */ { /* * Simply calling 'Sleep' for the requisite number of milliseconds can * make the process appear to wake up early because it isn't synchronized * with the CPU performance counter that is used in tclWinTime.c. This * behavior is probably benign, but messes up some of the corner cases in * the test suite. We get around this problem by repeating the 'Sleep' * call as many times as necessary to make the clock advance by the * requisite amount. */ Tcl_Time now; /* Current wall clock time. */ Tcl_Time desired; /* Desired wakeup time. */ Tcl_Time vdelay; /* Time to sleep, for scaling virtual -> * real. */ DWORD sleepTime; /* Time to sleep, real-time */ vdelay.sec = ms / 1000; vdelay.usec = (ms % 1000) * 1000; Tcl_GetTime(&now); desired.sec = now.sec + vdelay.sec; desired.usec = now.usec + vdelay.usec; if (desired.usec > 1000000) { ++desired.sec; desired.usec -= 1000000; } /* * TIP #233: Scale delay from virtual to real-time. */ tclScaleTimeProcPtr(&vdelay, tclTimeClientData); sleepTime = vdelay.sec * 1000 + vdelay.usec / 1000; for (;;) { SleepEx(sleepTime, TRUE); Tcl_GetTime(&now); if (now.sec > desired.sec) { break; } else if ((now.sec == desired.sec) && (now.usec >= desired.usec)) { break; } vdelay.sec = desired.sec - now.sec; vdelay.usec = desired.usec - now.usec; tclScaleTimeProcPtr(&vdelay, tclTimeClientData); sleepTime = vdelay.sec * 1000 + vdelay.usec / 1000; } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tclWinDde.c0000644000175000017500000014525112663660066014416 0ustar sergeisergei/* * tclWinDde.c -- * * This file provides functions that implement the "send" command, * allowing commands to be passed from interpreter to interpreter. * * Copyright (c) 1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #undef STATIC_BUILD #ifndef USE_TCL_STUBS # define USE_TCL_STUBS #endif #include "tclInt.h" #include #include #ifndef UNICODE # undef CP_WINUNICODE # define CP_WINUNICODE CP_WINANSI # undef Tcl_WinTCharToUtf # define Tcl_WinTCharToUtf(a,b,c) Tcl_ExternalToUtfDString(NULL,a,b,c) # undef Tcl_WinUtfToTChar # define Tcl_WinUtfToTChar(a,b,c) Tcl_UtfToExternalDString(NULL,a,b,c) #endif #if !defined(NDEBUG) /* test POKE server Implemented for debug mode only */ # undef CBF_FAIL_POKES # define CBF_FAIL_POKES 0 #endif /* * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the Dde_Init * declaration is in the source file itself, which is only accessed when we * are building a library. DO NOT MOVE BEFORE ANY #include LINES. ONLY USE * EXTERN TO INDICATE EXPORTED FUNCTIONS FROM NOW ON. */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLEXPORT /* * The following structure is used to keep track of the interpreters * registered by this process. */ typedef struct RegisteredInterp { struct RegisteredInterp *nextPtr; /* The next interp this application knows * about. */ TCHAR *name; /* Interpreter's name (malloc-ed). */ Tcl_Obj *handlerPtr; /* The server handler command */ Tcl_Interp *interp; /* The interpreter attached to this name. */ } RegisteredInterp; /* * Used to keep track of conversations. */ typedef struct Conversation { struct Conversation *nextPtr; /* The next conversation in the list. */ RegisteredInterp *riPtr; /* The info we know about the conversation. */ HCONV hConv; /* The DDE handle for this conversation. */ Tcl_Obj *returnPackagePtr; /* The result package for this conversation. */ } Conversation; typedef struct DdeEnumServices { Tcl_Interp *interp; int result; ATOM service; ATOM topic; HWND hwnd; } DdeEnumServices; typedef struct ThreadSpecificData { Conversation *currentConversations; /* A list of conversations currently being * processed. */ RegisteredInterp *interpListPtr; /* List of all interpreters registered in the * current process. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * The following variables cannot be placed in thread-local storage. The Mutex * ddeMutex guards access to the ddeInstance. */ static HSZ ddeServiceGlobal = 0; static DWORD ddeInstance; /* The application instance handle given to us * by DdeInitialize. */ static int ddeIsServer = 0; #define TCL_DDE_VERSION "1.4.0" #define TCL_DDE_PACKAGE_NAME "dde" #define TCL_DDE_SERVICE_NAME TEXT("TclEval") #define TCL_DDE_EXECUTE_RESULT TEXT("$TCLEVAL$EXECUTE$RESULT") #define DDE_FLAG_ASYNC 1 #define DDE_FLAG_BINARY 2 #define DDE_FLAG_FORCE 4 TCL_DECLARE_MUTEX(ddeMutex) /* * Forward declarations for functions defined later in this file. */ static LRESULT CALLBACK DdeClientWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static int DdeCreateClient(struct DdeEnumServices *es); static BOOL CALLBACK DdeEnumWindowsCallback(HWND hwndTarget, LPARAM lParam); static void DdeExitProc(ClientData clientData); static int DdeGetServicesList(Tcl_Interp *interp, const TCHAR *serviceName, const TCHAR *topicName); static HDDEDATA CALLBACK DdeServerProc(UINT uType, UINT uFmt, HCONV hConv, HSZ ddeTopic, HSZ ddeItem, HDDEDATA hData, DWORD dwData1, DWORD dwData2); static LRESULT DdeServicesOnAck(HWND hwnd, WPARAM wParam, LPARAM lParam); static void DeleteProc(ClientData clientData); static Tcl_Obj * ExecuteRemoteObject(RegisteredInterp *riPtr, Tcl_Obj *ddeObjectPtr); static int MakeDdeConnection(Tcl_Interp *interp, const TCHAR *name, HCONV *ddeConvPtr); static void SetDdeError(Tcl_Interp *interp); static int DdeObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); EXTERN int Dde_Init(Tcl_Interp *interp); EXTERN int Dde_SafeInit(Tcl_Interp *interp); /* *---------------------------------------------------------------------- * * Dde_Init -- * * This function initializes the dde command. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Dde_Init( Tcl_Interp *interp) { if (!Tcl_InitStubs(interp, "8.1", 0)) { return TCL_ERROR; } #ifdef UNICODE if (TclWinGetPlatformId() < VER_PLATFORM_WIN32_NT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "Win32s and Windows 9x are not supported platforms", -1)); return TCL_ERROR; } #endif Tcl_CreateObjCommand(interp, "dde", DdeObjCmd, NULL, NULL); Tcl_CreateExitHandler(DdeExitProc, NULL); return Tcl_PkgProvide(interp, TCL_DDE_PACKAGE_NAME, TCL_DDE_VERSION); } /* *---------------------------------------------------------------------- * * Dde_SafeInit -- * * This function initializes the dde command within a safe interp * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Dde_SafeInit( Tcl_Interp *interp) { int result = Dde_Init(interp); if (result == TCL_OK) { Tcl_HideCommand(interp, "dde", "dde"); } return result; } /* *---------------------------------------------------------------------- * * Initialize -- * * Initialize the global DDE instance. * * Results: * None. * * Side effects: * Registers the DDE server proc. * *---------------------------------------------------------------------- */ static void Initialize(void) { int nameFound = 0; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * See if the application is already registered; if so, remove its current * name from the registry. The deletion of the command will take care of * disposing of this entry. */ if (tsdPtr->interpListPtr != NULL) { nameFound = 1; } /* * Make sure that the DDE server is there. This is done only once, add an * exit handler tear it down. */ if (ddeInstance == 0) { Tcl_MutexLock(&ddeMutex); if (ddeInstance == 0) { if (DdeInitialize(&ddeInstance, (PFNCALLBACK) DdeServerProc, CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS | CBF_FAIL_POKES, 0) != DMLERR_NO_ERROR) { ddeInstance = 0; } } Tcl_MutexUnlock(&ddeMutex); } if ((ddeServiceGlobal == 0) && (nameFound != 0)) { Tcl_MutexLock(&ddeMutex); if ((ddeServiceGlobal == 0) && (nameFound != 0)) { ddeIsServer = 1; Tcl_CreateExitHandler(DdeExitProc, NULL); ddeServiceGlobal = DdeCreateStringHandle(ddeInstance, TCL_DDE_SERVICE_NAME, CP_WINUNICODE); DdeNameService(ddeInstance, ddeServiceGlobal, 0L, DNS_REGISTER); } else { ddeIsServer = 0; } Tcl_MutexUnlock(&ddeMutex); } } /* *---------------------------------------------------------------------- * * DdeSetServerName -- * * This function is called to associate an ASCII name with a Dde server. * If the interpreter has already been named, the name replaces the old * one. * * Results: * The return value is the name actually given to the interp. This will * normally be the same as name, but if name was already in use for a Dde * Server then a name of the form "name #2" will be chosen, with a high * enough number to make the name unique. * * Side effects: * Registration info is saved, thereby allowing the "send" command to be * used later to invoke commands in the application. In addition, the * "send" command is created in the application's interpreter. The * registration will be removed automatically if the interpreter is * deleted or the "send" command is removed. * *---------------------------------------------------------------------- */ static const TCHAR * DdeSetServerName( Tcl_Interp *interp, const TCHAR *name, /* The name that will be used to refer to the * interpreter in later "send" commands. Must * be globally unique. */ int flags, /* DDE_FLAG_FORCE or 0 */ Tcl_Obj *handlerPtr) /* Name of the optional proc/command to handle * incoming Dde eval's */ { int suffix, offset; RegisteredInterp *riPtr, *prevPtr; Tcl_DString dString; const TCHAR *actualName; Tcl_Obj *srvListPtr = NULL, **srvPtrPtr = NULL; int n, srvCount = 0, lastSuffix, r = TCL_OK; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * See if the application is already registered; if so, remove its current * name from the registry. The deletion of the command will take care of * disposing of this entry. */ for (riPtr = tsdPtr->interpListPtr, prevPtr = NULL; riPtr != NULL; prevPtr = riPtr, riPtr = riPtr->nextPtr) { if (riPtr->interp == interp) { if (name != NULL) { if (prevPtr == NULL) { tsdPtr->interpListPtr = tsdPtr->interpListPtr->nextPtr; } else { prevPtr->nextPtr = riPtr->nextPtr; } break; } else { /* * The name was NULL, so the caller is asking for the name of * the current interp. */ return riPtr->name; } } } if (name == NULL) { /* * The name was NULL, so the caller is asking for the name of the * current interp, but it doesn't have a name. */ return TEXT(""); } /* * Get the list of currently registered Tcl interpreters by calling the * internal implementation of the 'dde services' command. */ Tcl_DStringInit(&dString); actualName = name; if (!(flags & DDE_FLAG_FORCE)) { r = DdeGetServicesList(interp, TCL_DDE_SERVICE_NAME, NULL); if (r == TCL_OK) { srvListPtr = Tcl_GetObjResult(interp); } if (r == TCL_OK) { r = Tcl_ListObjGetElements(interp, srvListPtr, &srvCount, &srvPtrPtr); } if (r != TCL_OK) { Tcl_WinUtfToTChar(Tcl_GetStringResult(interp), -1, &dString); OutputDebugString((TCHAR *) Tcl_DStringValue(&dString)); Tcl_DStringFree(&dString); return NULL; } /* * Pick a name to use for the application. Use "name" if it's not * already in use. Otherwise add a suffix such as " #2", trying larger * and larger numbers until we eventually find one that is unique. */ offset = lastSuffix = 0; suffix = 1; while (suffix != lastSuffix) { lastSuffix = suffix; if (suffix > 1) { if (suffix == 2) { Tcl_DStringAppend(&dString, (char *)name, _tcslen(name) * sizeof(TCHAR)); Tcl_DStringAppend(&dString, (char *)TEXT(" #"), 2 * sizeof(TCHAR)); offset = Tcl_DStringLength(&dString); Tcl_DStringSetLength(&dString, offset + sizeof(TCHAR) * TCL_INTEGER_SPACE); actualName = (TCHAR *) Tcl_DStringValue(&dString); } _sntprintf((TCHAR *) (Tcl_DStringValue(&dString) + offset), TCL_INTEGER_SPACE, TEXT("%d"), suffix); } /* * See if the name is already in use, if so increment suffix. */ for (n = 0; n < srvCount; ++n) { Tcl_Obj* namePtr; Tcl_DString ds; Tcl_ListObjIndex(interp, srvPtrPtr[n], 1, &namePtr); Tcl_WinUtfToTChar(Tcl_GetString(namePtr), -1, &ds); if (_tcscmp(actualName, (TCHAR *)Tcl_DStringValue(&ds)) == 0) { suffix++; Tcl_DStringFree(&ds); break; } Tcl_DStringFree(&ds); } } } /* * We have found a unique name. Now add it to the registry. */ riPtr = ckalloc(sizeof(RegisteredInterp)); riPtr->interp = interp; riPtr->name = ckalloc((_tcslen(actualName) + 1) * sizeof(TCHAR)); riPtr->nextPtr = tsdPtr->interpListPtr; riPtr->handlerPtr = handlerPtr; if (riPtr->handlerPtr != NULL) { Tcl_IncrRefCount(riPtr->handlerPtr); } tsdPtr->interpListPtr = riPtr; _tcscpy(riPtr->name, actualName); if (Tcl_IsSafe(interp)) { Tcl_ExposeCommand(interp, "dde", "dde"); } Tcl_CreateObjCommand(interp, "dde", DdeObjCmd, riPtr, DeleteProc); if (Tcl_IsSafe(interp)) { Tcl_HideCommand(interp, "dde", "dde"); } Tcl_DStringFree(&dString); /* * Re-initialize with the new name. */ Initialize(); return riPtr->name; } /* *---------------------------------------------------------------------- * * DdeGetRegistrationPtr * * Retrieve the registration info for an interpreter. * * Results: * Returns a pointer to the registration structure or NULL * * Side effects: * None * *---------------------------------------------------------------------- */ static RegisteredInterp * DdeGetRegistrationPtr( Tcl_Interp *interp) { RegisteredInterp *riPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); for (riPtr = tsdPtr->interpListPtr; riPtr != NULL; riPtr = riPtr->nextPtr) { if (riPtr->interp == interp) { break; } } return riPtr; } /* *---------------------------------------------------------------------- * * DeleteProc * * This function is called when the command "dde" is destroyed. * * Results: * none * * Side effects: * The interpreter given by riPtr is unregistered. * *---------------------------------------------------------------------- */ static void DeleteProc( ClientData clientData) /* The interp we are deleting passed as * ClientData. */ { RegisteredInterp *riPtr = (RegisteredInterp *) clientData; RegisteredInterp *searchPtr, *prevPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); for (searchPtr = tsdPtr->interpListPtr, prevPtr = NULL; (searchPtr != NULL) && (searchPtr != riPtr); prevPtr = searchPtr, searchPtr = searchPtr->nextPtr) { /* * Empty loop body. */ } if (searchPtr != NULL) { if (prevPtr == NULL) { tsdPtr->interpListPtr = tsdPtr->interpListPtr->nextPtr; } else { prevPtr->nextPtr = searchPtr->nextPtr; } } ckfree(riPtr->name); if (riPtr->handlerPtr) { Tcl_DecrRefCount(riPtr->handlerPtr); } Tcl_EventuallyFree(clientData, TCL_DYNAMIC); } /* *---------------------------------------------------------------------- * * ExecuteRemoteObject -- * * Takes the package delivered by DDE and executes it in the server's * interpreter. * * Results: * A list Tcl_Obj * that describes what happened. The first element is * the numerical return code (TCL_ERROR, etc.). The second element is the * result of the script. If the return result was TCL_ERROR, then the * third element will be the value of the global "errorCode", and the * fourth will be the value of the global "errorInfo". The return result * will have a refCount of 0. * * Side effects: * A Tcl script is run, which can cause all kinds of other things to * happen. * *---------------------------------------------------------------------- */ static Tcl_Obj * ExecuteRemoteObject( RegisteredInterp *riPtr, /* Info about this server. */ Tcl_Obj *ddeObjectPtr) /* The object to execute. */ { Tcl_Obj *returnPackagePtr; int result = TCL_OK; if (riPtr->handlerPtr == NULL && Tcl_IsSafe(riPtr->interp)) { Tcl_SetObjResult(riPtr->interp, Tcl_NewStringObj("permission denied: " "a handler procedure must be defined for use in a safe " "interp", -1)); Tcl_SetErrorCode(riPtr->interp, "TCL", "DDE", "SECURITY_CHECK", NULL); result = TCL_ERROR; } if (riPtr->handlerPtr != NULL) { /* * Add the dde request data to the handler proc list. */ Tcl_Obj *cmdPtr = Tcl_DuplicateObj(riPtr->handlerPtr); result = Tcl_ListObjAppendElement(riPtr->interp, cmdPtr, ddeObjectPtr); if (result == TCL_OK) { ddeObjectPtr = cmdPtr; } } if (result == TCL_OK) { result = Tcl_EvalObjEx(riPtr->interp, ddeObjectPtr, TCL_EVAL_GLOBAL); } returnPackagePtr = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(NULL, returnPackagePtr, Tcl_NewIntObj(result)); Tcl_ListObjAppendElement(NULL, returnPackagePtr, Tcl_GetObjResult(riPtr->interp)); if (result == TCL_ERROR) { Tcl_Obj *errorObjPtr = Tcl_GetVar2Ex(riPtr->interp, "errorCode", NULL, TCL_GLOBAL_ONLY); if (errorObjPtr) { Tcl_ListObjAppendElement(NULL, returnPackagePtr, errorObjPtr); } errorObjPtr = Tcl_GetVar2Ex(riPtr->interp, "errorInfo", NULL, TCL_GLOBAL_ONLY); if (errorObjPtr) { Tcl_ListObjAppendElement(NULL, returnPackagePtr, errorObjPtr); } } return returnPackagePtr; } /* *---------------------------------------------------------------------- * * DdeServerProc -- * * Handles all transactions for this server. Can handle execute, request, * and connect protocols. Dde will call this routine when a client * attempts to run a dde command using this server. * * Results: * A DDE Handle with the result of the dde command. * * Side effects: * Depending on which command is executed, arbitrary Tcl scripts can be * run. * *---------------------------------------------------------------------- */ static HDDEDATA CALLBACK DdeServerProc( UINT uType, /* The type of DDE transaction we are * performing. */ UINT uFmt, /* The format that data is sent or received */ HCONV hConv, /* The conversation associated with the * current transaction. */ HSZ ddeTopic, HSZ ddeItem, /* String handles. Transaction-type * dependent. */ HDDEDATA hData, /* DDE data. Transaction-type dependent. */ DWORD dwData1, DWORD dwData2) /* Transaction-dependent data. */ { Tcl_DString dString; int len; DWORD dlen; TCHAR *utilString; Tcl_Obj *ddeObjectPtr; HDDEDATA ddeReturn = NULL; RegisteredInterp *riPtr; Conversation *convPtr, *prevConvPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); switch(uType) { case XTYP_CONNECT: /* * Dde is trying to initialize a conversation with us. Check and make * sure we have a valid topic. */ len = DdeQueryString(ddeInstance, ddeTopic, NULL, 0, CP_WINUNICODE); Tcl_DStringInit(&dString); Tcl_DStringSetLength(&dString, (len + 1) * sizeof(TCHAR) - 1); utilString = (TCHAR *) Tcl_DStringValue(&dString); DdeQueryString(ddeInstance, ddeTopic, utilString, (DWORD) len + 1, CP_WINUNICODE); for (riPtr = tsdPtr->interpListPtr; riPtr != NULL; riPtr = riPtr->nextPtr) { if (_tcsicmp(utilString, riPtr->name) == 0) { Tcl_DStringFree(&dString); return (HDDEDATA) TRUE; } } Tcl_DStringFree(&dString); return (HDDEDATA) FALSE; case XTYP_CONNECT_CONFIRM: /* * Dde has decided that we can connect, so it gives us a conversation * handle. We need to keep track of it so we know which execution * result to return in an XTYP_REQUEST. */ len = DdeQueryString(ddeInstance, ddeTopic, NULL, 0, CP_WINUNICODE); Tcl_DStringInit(&dString); Tcl_DStringSetLength(&dString, (len + 1) * sizeof(TCHAR) - 1); utilString = (TCHAR *) Tcl_DStringValue(&dString); DdeQueryString(ddeInstance, ddeTopic, utilString, (DWORD) len + 1, CP_WINUNICODE); for (riPtr = tsdPtr->interpListPtr; riPtr != NULL; riPtr = riPtr->nextPtr) { if (_tcsicmp(riPtr->name, utilString) == 0) { convPtr = ckalloc(sizeof(Conversation)); convPtr->nextPtr = tsdPtr->currentConversations; convPtr->returnPackagePtr = NULL; convPtr->hConv = hConv; convPtr->riPtr = riPtr; tsdPtr->currentConversations = convPtr; break; } } Tcl_DStringFree(&dString); return (HDDEDATA) TRUE; case XTYP_DISCONNECT: /* * The client has disconnected from our server. Forget this * conversation. */ for (convPtr = tsdPtr->currentConversations, prevConvPtr = NULL; convPtr != NULL; prevConvPtr = convPtr, convPtr = convPtr->nextPtr) { if (hConv == convPtr->hConv) { if (prevConvPtr == NULL) { tsdPtr->currentConversations = convPtr->nextPtr; } else { prevConvPtr->nextPtr = convPtr->nextPtr; } if (convPtr->returnPackagePtr != NULL) { Tcl_DecrRefCount(convPtr->returnPackagePtr); } ckfree(convPtr); break; } } return (HDDEDATA) TRUE; case XTYP_REQUEST: /* * This could be either a request for a value of a Tcl variable, or it * could be the send command requesting the results of the last * execute. */ if ((uFmt != CF_TEXT) && (uFmt != CF_UNICODETEXT)) { return (HDDEDATA) FALSE; } ddeReturn = (HDDEDATA) FALSE; for (convPtr = tsdPtr->currentConversations; (convPtr != NULL) && (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) { /* * Empty loop body. */ } if (convPtr != NULL) { char *returnString; len = DdeQueryString(ddeInstance, ddeItem, NULL, 0, CP_WINUNICODE); Tcl_DStringInit(&dString); Tcl_DStringSetLength(&dString, (len + 1) * sizeof(TCHAR) - 1); utilString = (TCHAR *) Tcl_DStringValue(&dString); DdeQueryString(ddeInstance, ddeItem, utilString, (DWORD) len + 1, CP_WINUNICODE); if (_tcsicmp(utilString, TCL_DDE_EXECUTE_RESULT) == 0) { if (uFmt == CF_TEXT) { returnString = Tcl_GetStringFromObj(convPtr->returnPackagePtr, &len); } else { returnString = (char *) Tcl_GetUnicodeFromObj(convPtr->returnPackagePtr, &len); len = sizeof(TCHAR) * len + 1; } ddeReturn = DdeCreateDataHandle(ddeInstance, (BYTE *)returnString, (DWORD) len+1, 0, ddeItem, uFmt, 0); } else { if (Tcl_IsSafe(convPtr->riPtr->interp)) { ddeReturn = NULL; } else { Tcl_DString ds; Tcl_Obj *variableObjPtr; Tcl_WinTCharToUtf(utilString, -1, &ds); variableObjPtr = Tcl_GetVar2Ex( convPtr->riPtr->interp, Tcl_DStringValue(&ds), NULL, TCL_GLOBAL_ONLY); if (variableObjPtr != NULL) { if (uFmt == CF_TEXT) { returnString = Tcl_GetStringFromObj( variableObjPtr, &len); } else { returnString = (char *) Tcl_GetUnicodeFromObj( variableObjPtr, &len); len = sizeof(TCHAR) * len + 1; } ddeReturn = DdeCreateDataHandle(ddeInstance, (BYTE *)returnString, (DWORD) len+1, 0, ddeItem, uFmt, 0); } else { ddeReturn = NULL; } Tcl_DStringFree(&ds); } } Tcl_DStringFree(&dString); } return ddeReturn; #if !CBF_FAIL_POKES case XTYP_POKE: /* * This is a poke for a Tcl variable, only implemented in * debug/UNICODE mode. */ ddeReturn = DDE_FNOTPROCESSED; if ((uFmt != CF_TEXT) && (uFmt != CF_UNICODETEXT)) { return ddeReturn; } for (convPtr = tsdPtr->currentConversations; (convPtr != NULL) && (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) { /* * Empty loop body. */ } if (convPtr && !Tcl_IsSafe(convPtr->riPtr->interp)) { Tcl_DString ds; Tcl_Obj *variableObjPtr; len = DdeQueryString(ddeInstance, ddeItem, NULL, 0, CP_WINUNICODE); Tcl_DStringInit(&dString); Tcl_DStringSetLength(&dString, (len + 1) * sizeof(TCHAR) - 1); utilString = (TCHAR *) Tcl_DStringValue(&dString); DdeQueryString(ddeInstance, ddeItem, utilString, (DWORD) len + 1, CP_WINUNICODE); Tcl_WinTCharToUtf(utilString, -1, &ds); utilString = (TCHAR *) DdeAccessData(hData, &dlen); if (uFmt == CF_TEXT) { variableObjPtr = Tcl_NewStringObj((char *)utilString, -1); } else { variableObjPtr = Tcl_NewUnicodeObj(utilString, -1); } Tcl_SetVar2Ex(convPtr->riPtr->interp, Tcl_DStringValue(&ds), NULL, variableObjPtr, TCL_GLOBAL_ONLY); Tcl_DStringFree(&ds); Tcl_DStringFree(&dString); ddeReturn = (HDDEDATA) DDE_FACK; } return ddeReturn; #endif case XTYP_EXECUTE: { /* * Execute this script. The results will be saved into a list object * which will be retreived later. See ExecuteRemoteObject. */ Tcl_Obj *returnPackagePtr; char *string; for (convPtr = tsdPtr->currentConversations; (convPtr != NULL) && (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) { /* * Empty loop body. */ } if (convPtr == NULL) { return (HDDEDATA) DDE_FNOTPROCESSED; } utilString = (TCHAR *) DdeAccessData(hData, &dlen); string = (char *) utilString; if (!dlen) { /* Empty binary array. */ ddeObjectPtr = Tcl_NewObj(); } else if ((dlen & 1) || utilString[(dlen>>1)-1]) { /* Cannot be unicode, so assume utf-8 */ if (!string[dlen-1]) { dlen--; } ddeObjectPtr = Tcl_NewStringObj(string, dlen); } else { /* unicode */ dlen >>= 1; ddeObjectPtr = Tcl_NewUnicodeObj((Tcl_UniChar *)utilString, dlen - 1); } Tcl_IncrRefCount(ddeObjectPtr); DdeUnaccessData(hData); if (convPtr->returnPackagePtr != NULL) { Tcl_DecrRefCount(convPtr->returnPackagePtr); } convPtr->returnPackagePtr = NULL; returnPackagePtr = ExecuteRemoteObject(convPtr->riPtr, ddeObjectPtr); Tcl_IncrRefCount(returnPackagePtr); for (convPtr = tsdPtr->currentConversations; (convPtr != NULL) && (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) { /* * Empty loop body. */ } if (convPtr != NULL) { convPtr->returnPackagePtr = returnPackagePtr; } else { Tcl_DecrRefCount(returnPackagePtr); } Tcl_DecrRefCount(ddeObjectPtr); if (returnPackagePtr == NULL) { return (HDDEDATA) DDE_FNOTPROCESSED; } else { return (HDDEDATA) DDE_FACK; } } case XTYP_WILDCONNECT: { /* * Dde wants a list of services and topics that we support. */ HSZPAIR *returnPtr; int i; int numItems; for (i = 0, riPtr = tsdPtr->interpListPtr; riPtr != NULL; i++, riPtr = riPtr->nextPtr) { /* * Empty loop body. */ } numItems = i; ddeReturn = DdeCreateDataHandle(ddeInstance, NULL, (numItems + 1) * sizeof(HSZPAIR), 0, 0, 0, 0); returnPtr = (HSZPAIR *) DdeAccessData(ddeReturn, &dlen); len = dlen; for (i = 0, riPtr = tsdPtr->interpListPtr; i < numItems; i++, riPtr = riPtr->nextPtr) { returnPtr[i].hszSvc = DdeCreateStringHandle(ddeInstance, TCL_DDE_SERVICE_NAME, CP_WINUNICODE); returnPtr[i].hszTopic = DdeCreateStringHandle(ddeInstance, riPtr->name, CP_WINUNICODE); } returnPtr[i].hszSvc = NULL; returnPtr[i].hszTopic = NULL; DdeUnaccessData(ddeReturn); return ddeReturn; } default: return NULL; } } /* *---------------------------------------------------------------------- * * DdeExitProc -- * * Gets rid of our DDE server when we go away. * * Results: * None. * * Side effects: * The DDE server is deleted. * *---------------------------------------------------------------------- */ static void DdeExitProc( ClientData clientData) /* Not used in this handler. */ { DdeNameService(ddeInstance, NULL, 0, DNS_UNREGISTER); DdeUninitialize(ddeInstance); ddeInstance = 0; } /* *---------------------------------------------------------------------- * * MakeDdeConnection -- * * This function is a utility used to connect to a DDE server when given * a server name and a topic name. * * Results: * A standard Tcl result. * * Side effects: * Passes back a conversation through ddeConvPtr * *---------------------------------------------------------------------- */ static int MakeDdeConnection( Tcl_Interp *interp, /* Used to report errors. */ const TCHAR *name, /* The connection to use. */ HCONV *ddeConvPtr) { HSZ ddeTopic, ddeService; HCONV ddeConv; ddeService = DdeCreateStringHandle(ddeInstance, TCL_DDE_SERVICE_NAME, CP_WINUNICODE); ddeTopic = DdeCreateStringHandle(ddeInstance, name, CP_WINUNICODE); ddeConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL); DdeFreeStringHandle(ddeInstance, ddeService); DdeFreeStringHandle(ddeInstance, ddeTopic); if (ddeConv == (HCONV) NULL) { if (interp != NULL) { Tcl_DString dString; Tcl_WinTCharToUtf(name, -1, &dString); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "no registered server named \"%s\"", Tcl_DStringValue(&dString))); Tcl_DStringFree(&dString); Tcl_SetErrorCode(interp, "TCL", "DDE", "NO_SERVER", NULL); } return TCL_ERROR; } *ddeConvPtr = ddeConv; return TCL_OK; } /* *---------------------------------------------------------------------- * * DdeGetServicesList -- * * This function obtains the list of DDE services. * * The functions between here and this function are all involved with * handling the DDE callbacks for this. They are: DdeCreateClient, * DdeClientWindowProc, DdeServicesOnAck, and DdeEnumWindowsCallback * * Results: * A standard Tcl result. * * Side effects: * Sets the services list into the interp result. * *---------------------------------------------------------------------- */ static int DdeCreateClient( struct DdeEnumServices *es) { WNDCLASSEX wc; static const TCHAR *szDdeClientClassName = TEXT("TclEval client class"); static const TCHAR *szDdeClientWindowName = TEXT("TclEval client window"); memset(&wc, 0, sizeof(wc)); wc.cbSize = sizeof(wc); wc.lpfnWndProc = DdeClientWindowProc; wc.lpszClassName = szDdeClientClassName; wc.cbWndExtra = sizeof(struct DdeEnumServices *); /* * Register and create the callback window. */ RegisterClassEx(&wc); es->hwnd = CreateWindowEx(0, szDdeClientClassName, szDdeClientWindowName, WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, (LPVOID)es); return TCL_OK; } static LRESULT CALLBACK DdeClientWindowProc( HWND hwnd, /* What window is the message for */ UINT uMsg, /* The type of message received */ WPARAM wParam, LPARAM lParam) /* (Potentially) our local handle */ { switch (uMsg) { case WM_CREATE: { LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam; struct DdeEnumServices *es = (struct DdeEnumServices *) lpcs->lpCreateParams; #ifdef _WIN64 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) es); #else SetWindowLong(hwnd, GWL_USERDATA, (LONG) es); #endif return (LRESULT) 0L; } case WM_DDE_ACK: return DdeServicesOnAck(hwnd, wParam, lParam); default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } } static LRESULT DdeServicesOnAck( HWND hwnd, WPARAM wParam, LPARAM lParam) { HWND hwndRemote = (HWND)wParam; ATOM service = (ATOM)LOWORD(lParam); ATOM topic = (ATOM)HIWORD(lParam); struct DdeEnumServices *es; TCHAR sz[255]; Tcl_DString dString; #ifdef _WIN64 es = (struct DdeEnumServices *) GetWindowLongPtr(hwnd, GWLP_USERDATA); #else es = (struct DdeEnumServices *) GetWindowLong(hwnd, GWL_USERDATA); #endif if ((es->service == (ATOM)0 || es->service == service) && (es->topic == (ATOM)0 || es->topic == topic)) { Tcl_Obj *matchPtr = Tcl_NewListObj(0, NULL); Tcl_Obj *resultPtr = Tcl_GetObjResult(es->interp); GlobalGetAtomName(service, sz, 255); Tcl_WinTCharToUtf(sz, -1, &dString); Tcl_ListObjAppendElement(NULL, matchPtr, Tcl_NewStringObj(Tcl_DStringValue(&dString), -1)); Tcl_DStringFree(&dString); GlobalGetAtomName(topic, sz, 255); Tcl_WinTCharToUtf(sz, -1, &dString); Tcl_ListObjAppendElement(NULL, matchPtr, Tcl_NewStringObj(Tcl_DStringValue(&dString), -1)); Tcl_DStringFree(&dString); /* * Adding the hwnd as a third list element provides a unique * identifier in the case of multiple servers with the name * application and topic names. */ /* * Needs a TIP though: * Tcl_ListObjAppendElement(NULL, matchPtr, * Tcl_NewLongObj((long)hwndRemote)); */ if (Tcl_IsShared(resultPtr)) { resultPtr = Tcl_DuplicateObj(resultPtr); } if (Tcl_ListObjAppendElement(es->interp, resultPtr, matchPtr) == TCL_OK) { Tcl_SetObjResult(es->interp, resultPtr); } } /* * Tell the server we are no longer interested. */ PostMessage(hwndRemote, WM_DDE_TERMINATE, (WPARAM)hwnd, 0L); return 0L; } static BOOL CALLBACK DdeEnumWindowsCallback( HWND hwndTarget, LPARAM lParam) { DWORD_PTR dwResult = 0; struct DdeEnumServices *es = (struct DdeEnumServices *) lParam; SendMessageTimeout(hwndTarget, WM_DDE_INITIATE, (WPARAM)es->hwnd, MAKELONG(es->service, es->topic), SMTO_ABORTIFHUNG, 1000, &dwResult); return TRUE; } static int DdeGetServicesList( Tcl_Interp *interp, const TCHAR *serviceName, const TCHAR *topicName) { struct DdeEnumServices es; es.interp = interp; es.result = TCL_OK; es.service = (serviceName == NULL) ? (ATOM)0 : GlobalAddAtom(serviceName); es.topic = (topicName == NULL) ? (ATOM)0 : GlobalAddAtom(topicName); Tcl_ResetResult(interp); /* our list is to be appended to result. */ DdeCreateClient(&es); EnumWindows(DdeEnumWindowsCallback, (LPARAM)&es); if (IsWindow(es.hwnd)) { DestroyWindow(es.hwnd); } if (es.service != (ATOM)0) { GlobalDeleteAtom(es.service); } if (es.topic != (ATOM)0) { GlobalDeleteAtom(es.topic); } return es.result; } /* *---------------------------------------------------------------------- * * SetDdeError -- * * Sets the interp result to a cogent error message describing the last * DDE error. * * Results: * None. * * Side effects: * The interp's result object is changed. * *---------------------------------------------------------------------- */ static void SetDdeError( Tcl_Interp *interp) /* The interp to put the message in. */ { const char *errorMessage, *errorCode; switch (DdeGetLastError(ddeInstance)) { case DMLERR_DATAACKTIMEOUT: case DMLERR_EXECACKTIMEOUT: case DMLERR_POKEACKTIMEOUT: errorMessage = "remote interpreter did not respond"; errorCode = "TIMEOUT"; break; case DMLERR_BUSY: errorMessage = "remote server is busy"; errorCode = "BUSY"; break; case DMLERR_NOTPROCESSED: errorMessage = "remote server cannot handle this command"; errorCode = "NOCANDO"; break; default: errorMessage = "dde command failed"; errorCode = "FAILED"; } Tcl_SetObjResult(interp, Tcl_NewStringObj(errorMessage, -1)); Tcl_SetErrorCode(interp, "TCL", "DDE", errorCode, NULL); } /* *---------------------------------------------------------------------- * * DdeObjCmd -- * * This function is invoked to process the "dde" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DdeObjCmd( ClientData clientData, /* Used only for deletion */ Tcl_Interp *interp, /* The interp we are sending from */ int objc, /* Number of arguments */ Tcl_Obj *const *objv) /* The arguments */ { static const char *const ddeCommands[] = { "servername", "execute", "poke", "request", "services", "eval", (char *) NULL}; enum DdeSubcommands { DDE_SERVERNAME, DDE_EXECUTE, DDE_POKE, DDE_REQUEST, DDE_SERVICES, DDE_EVAL }; static const char *const ddeSrvOptions[] = { "-force", "-handler", "--", NULL }; enum DdeSrvOptions { DDE_SERVERNAME_EXACT, DDE_SERVERNAME_HANDLER, DDE_SERVERNAME_LAST, }; static const char *const ddeExecOptions[] = { "-async", "-binary", NULL }; enum DdeExecOptions { DDE_EXEC_ASYNC, DDE_EXEC_BINARY }; static const char *const ddeEvalOptions[] = { "-async", NULL }; static const char *const ddeReqOptions[] = { "-binary", NULL }; int index, i, length, argIndex; int flags = 0, result = TCL_OK, firstArg = 0; HSZ ddeService = NULL, ddeTopic = NULL, ddeItem = NULL, ddeCookie = NULL; HDDEDATA ddeData = NULL, ddeItemData = NULL, ddeReturn; HCONV hConv = NULL; const TCHAR *serviceName = NULL, *topicName = NULL; const char *string; DWORD ddeResult; Tcl_Obj *objPtr, *handlerPtr = NULL; /* * Initialize DDE server/client */ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "command ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], ddeCommands, "command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum DdeSubcommands) index) { case DDE_SERVERNAME: for (i = 2; i < objc; i++) { if (Tcl_GetIndexFromObj(interp, objv[i], ddeSrvOptions, "option", 0, &argIndex) != TCL_OK) { /* * If it is the last argument, it might be a server name * instead of a bad argument. */ if (i != objc-1) { return TCL_ERROR; } Tcl_ResetResult(interp); break; } if (argIndex == DDE_SERVERNAME_EXACT) { flags |= DDE_FLAG_FORCE; } else if (argIndex == DDE_SERVERNAME_HANDLER) { if ((objc - i) == 1) { /* return current handler */ RegisteredInterp *riPtr = DdeGetRegistrationPtr(interp); if (riPtr && riPtr->handlerPtr) { Tcl_SetObjResult(interp, riPtr->handlerPtr); } else { Tcl_ResetResult(interp); } return TCL_OK; } handlerPtr = objv[++i]; } else if (argIndex == DDE_SERVERNAME_LAST) { i++; break; } } if ((objc - i) > 1) { Tcl_ResetResult(interp); Tcl_WrongNumArgs(interp, 2, objv, "?-force? ?-handler proc? ?--? ?serverName?"); return TCL_ERROR; } firstArg = (objc == i) ? 1 : i; break; case DDE_EXECUTE: if (objc == 5) { firstArg = 2; break; } else if (objc >= 6 && objc <= 7) { firstArg = objc - 3; for (i = 2; i < firstArg; i++) { if (Tcl_GetIndexFromObj(interp, objv[i], ddeExecOptions, "option", 0, &argIndex) != TCL_OK) { goto wrongDdeExecuteArgs; } if (argIndex == DDE_EXEC_ASYNC) { flags |= DDE_FLAG_ASYNC; } else { flags |= DDE_FLAG_BINARY; } } break; } /* otherwise... */ wrongDdeExecuteArgs: Tcl_WrongNumArgs(interp, 2, objv, "?-async? ?-binary? serviceName topicName value"); return TCL_ERROR; case DDE_POKE: if (objc == 6) { firstArg = 2; break; } else if ((objc == 7) && (Tcl_GetIndexFromObj(NULL, objv[2], ddeReqOptions, "option", 0, &argIndex) == TCL_OK)) { flags |= DDE_FLAG_BINARY; firstArg = 3; break; } /* * Otherwise... */ Tcl_WrongNumArgs(interp, 2, objv, "?-binary? serviceName topicName item value"); return TCL_ERROR; case DDE_REQUEST: if (objc == 5) { firstArg = 2; break; } else if ((objc == 6) && (Tcl_GetIndexFromObj(NULL, objv[2], ddeReqOptions, "option", 0, &argIndex) == TCL_OK)) { flags |= DDE_FLAG_BINARY; firstArg = 3; break; } /* * Otherwise ... */ Tcl_WrongNumArgs(interp, 2, objv, "?-binary? serviceName topicName value"); return TCL_ERROR; case DDE_SERVICES: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "serviceName topicName"); return TCL_ERROR; } firstArg = 2; break; case DDE_EVAL: if (objc < 4) { wrongDdeEvalArgs: Tcl_WrongNumArgs(interp, 2, objv, "?-async? serviceName args"); return TCL_ERROR; } else { firstArg = 2; if (Tcl_GetIndexFromObj(NULL, objv[2], ddeEvalOptions, "option", 0, &argIndex) == TCL_OK) { if (objc < 5) { goto wrongDdeEvalArgs; } flags |= DDE_FLAG_ASYNC; firstArg++; } break; } } Initialize(); if (firstArg != 1) { #ifdef UNICODE serviceName = Tcl_GetUnicodeFromObj(objv[firstArg], &length); #else serviceName = Tcl_GetStringFromObj(objv[firstArg], &length); #endif } else { length = 0; } if (length == 0) { serviceName = NULL; } else if ((index != DDE_SERVERNAME) && (index != DDE_EVAL)) { ddeService = DdeCreateStringHandle(ddeInstance, (void *) serviceName, CP_WINUNICODE); } if ((index != DDE_SERVERNAME) && (index != DDE_EVAL)) { #ifdef UNICODE topicName = (TCHAR *) Tcl_GetUnicodeFromObj(objv[firstArg + 1], &length); #else topicName = Tcl_GetStringFromObj(objv[firstArg + 1], &length); #endif if (length == 0) { topicName = NULL; } else { ddeTopic = DdeCreateStringHandle(ddeInstance, (void *) topicName, CP_WINUNICODE); } } switch ((enum DdeSubcommands) index) { case DDE_SERVERNAME: serviceName = DdeSetServerName(interp, serviceName, flags, handlerPtr); if (serviceName != NULL) { #ifdef UNICODE Tcl_SetObjResult(interp, Tcl_NewUnicodeObj((Tcl_UniChar *) serviceName, -1)); #else Tcl_SetObjResult(interp, Tcl_NewStringObj(serviceName, -1)); #endif } else { Tcl_ResetResult(interp); } break; case DDE_EXECUTE: { int dataLength; const Tcl_UniChar *dataString; if (flags & DDE_FLAG_BINARY) { dataString = (const Tcl_UniChar *) Tcl_GetByteArrayFromObj(objv[firstArg + 2], &dataLength); } else { dataString = Tcl_GetUnicodeFromObj(objv[firstArg + 2], &dataLength); dataLength = (dataLength + 1) * sizeof(Tcl_UniChar); } if (dataLength <= 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot execute null data", -1)); Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", NULL); result = TCL_ERROR; break; } hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL); DdeFreeStringHandle(ddeInstance, ddeService); DdeFreeStringHandle(ddeInstance, ddeTopic); if (hConv == NULL) { SetDdeError(interp); result = TCL_ERROR; break; } ddeData = DdeCreateDataHandle(ddeInstance, (BYTE *) dataString, (DWORD) dataLength, 0, 0, (flags & DDE_FLAG_BINARY) ? CF_TEXT : CF_UNICODETEXT, 0); if (ddeData != NULL) { if (flags & DDE_FLAG_ASYNC) { DdeClientTransaction((LPBYTE) ddeData, 0xFFFFFFFF, hConv, 0, (flags & DDE_FLAG_BINARY) ? CF_TEXT : CF_UNICODETEXT, XTYP_EXECUTE, TIMEOUT_ASYNC, &ddeResult); DdeAbandonTransaction(ddeInstance, hConv, ddeResult); } else { ddeReturn = DdeClientTransaction((LPBYTE) ddeData, 0xFFFFFFFF, hConv, 0, (flags & DDE_FLAG_BINARY) ? CF_TEXT : CF_UNICODETEXT, XTYP_EXECUTE, 30000, NULL); if (ddeReturn == 0) { SetDdeError(interp); result = TCL_ERROR; } } DdeFreeDataHandle(ddeData); } else { SetDdeError(interp); result = TCL_ERROR; } break; } case DDE_REQUEST: { #ifdef UNICODE const TCHAR *itemString = (TCHAR *) Tcl_GetUnicodeFromObj(objv[firstArg + 2], &length); #else const TCHAR *itemString = Tcl_GetStringFromObj(objv[firstArg + 2], &length); #endif if (length == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot request value of null data", -1)); Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", NULL); result = TCL_ERROR; goto cleanup; } hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL); DdeFreeStringHandle(ddeInstance, ddeService); DdeFreeStringHandle(ddeInstance, ddeTopic); if (hConv == NULL) { SetDdeError(interp); result = TCL_ERROR; } else { Tcl_Obj *returnObjPtr; ddeItem = DdeCreateStringHandle(ddeInstance, (void *) itemString, CP_WINUNICODE); if (ddeItem != NULL) { ddeData = DdeClientTransaction(NULL, 0, hConv, ddeItem, (flags & DDE_FLAG_BINARY) ? CF_TEXT : CF_UNICODETEXT, XTYP_REQUEST, 5000, NULL); if (ddeData == NULL) { SetDdeError(interp); result = TCL_ERROR; } else { DWORD tmp; const Tcl_UniChar *dataString = (const Tcl_UniChar *) DdeAccessData(ddeData, &tmp); if (flags & DDE_FLAG_BINARY) { returnObjPtr = Tcl_NewByteArrayObj((BYTE *) dataString, (int) tmp); } else { tmp >>= 1; if (tmp && !dataString[(tmp-1)]) { --tmp; } returnObjPtr = Tcl_NewUnicodeObj(dataString, (int) tmp); } DdeUnaccessData(ddeData); DdeFreeDataHandle(ddeData); Tcl_SetObjResult(interp, returnObjPtr); } } else { SetDdeError(interp); result = TCL_ERROR; } } break; } case DDE_POKE: { #ifdef UNICODE const TCHAR *itemString = (TCHAR *) Tcl_GetUnicodeFromObj(objv[firstArg + 2], &length); #else const TCHAR *itemString = Tcl_GetStringFromObj(objv[firstArg + 2], &length); #endif BYTE *dataString; if (length == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot have a null item", -1)); Tcl_SetErrorCode(interp, "TCL", "DDE", "NULL", NULL); result = TCL_ERROR; goto cleanup; } if (flags & DDE_FLAG_BINARY) { dataString = (BYTE *) Tcl_GetByteArrayFromObj(objv[firstArg + 3], &length); } else { dataString = (BYTE *) Tcl_GetUnicodeFromObj(objv[firstArg + 3], &length); length = 2 * length + 1; } hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL); DdeFreeStringHandle(ddeInstance, ddeService); DdeFreeStringHandle(ddeInstance, ddeTopic); if (hConv == NULL) { SetDdeError(interp); result = TCL_ERROR; } else { ddeItem = DdeCreateStringHandle(ddeInstance, (void *) itemString, CP_WINUNICODE); if (ddeItem != NULL) { ddeData = DdeClientTransaction(dataString, (DWORD) length, hConv, ddeItem, (flags & DDE_FLAG_BINARY) ? CF_TEXT : CF_UNICODETEXT, XTYP_POKE, 5000, NULL); if (ddeData == NULL) { SetDdeError(interp); result = TCL_ERROR; } } else { SetDdeError(interp); result = TCL_ERROR; } } break; } case DDE_SERVICES: result = DdeGetServicesList(interp, serviceName, topicName); break; case DDE_EVAL: { RegisteredInterp *riPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (serviceName == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid service name \"\"", -1)); Tcl_SetErrorCode(interp, "TCL", "DDE", "NO_SERVER", NULL); result = TCL_ERROR; goto cleanup; } objc -= firstArg + 1; objv += firstArg + 1; /* * See if the target interpreter is local. If so, execute the command * directly without going through the DDE server. Don't exchange * objects between interps. The target interp could compile an object, * producing a bytecode structure that refers to other objects owned * by the target interp. If the target interp is then deleted, the * bytecode structure would be referring to deallocated objects. */ for (riPtr = tsdPtr->interpListPtr; riPtr != NULL; riPtr = riPtr->nextPtr) { if (_tcsicmp(serviceName, riPtr->name) == 0) { break; } } if (riPtr != NULL) { Tcl_Interp *sendInterp; /* * This command is to a local interp. No need to go through the * server. */ Tcl_Preserve(riPtr); sendInterp = riPtr->interp; Tcl_Preserve(sendInterp); /* * Don't exchange objects between interps. The target interp would * compile an object, producing a bytecode structure that refers * to other objects owned by the target interp. If the target * interp is then deleted, the bytecode structure would be * referring to deallocated objects. */ if (Tcl_IsSafe(riPtr->interp) && riPtr->handlerPtr == NULL) { Tcl_SetObjResult(riPtr->interp, Tcl_NewStringObj( "permission denied: a handler procedure must be" " defined for use in a safe interp", -1)); Tcl_SetErrorCode(interp, "TCL", "DDE", "SECURITY_CHECK", NULL); result = TCL_ERROR; } if (result == TCL_OK) { if (objc == 1) objPtr = objv[0]; else { objPtr = Tcl_ConcatObj(objc, objv); } if (riPtr->handlerPtr != NULL) { /* add the dde request data to the handler proc list */ /* *result = Tcl_ListObjReplace(sendInterp, objPtr, 0, 0, 1, * &(riPtr->handlerPtr)); */ Tcl_Obj *cmdPtr = Tcl_DuplicateObj(riPtr->handlerPtr); result = Tcl_ListObjAppendElement(sendInterp, cmdPtr, objPtr); if (result == TCL_OK) { objPtr = cmdPtr; } } } if (result == TCL_OK) { Tcl_IncrRefCount(objPtr); result = Tcl_EvalObjEx(sendInterp, objPtr, TCL_EVAL_GLOBAL); Tcl_DecrRefCount(objPtr); } if (interp != sendInterp) { if (result == TCL_ERROR) { /* * An error occurred, so transfer error information from * the destination interpreter back to our interpreter. */ Tcl_ResetResult(interp); objPtr = Tcl_GetVar2Ex(sendInterp, "errorInfo", NULL, TCL_GLOBAL_ONLY); if (objPtr) { string = Tcl_GetStringFromObj(objPtr, &length); Tcl_AddObjErrorInfo(interp, string, length); } objPtr = Tcl_GetVar2Ex(sendInterp, "errorCode", NULL, TCL_GLOBAL_ONLY); if (objPtr) { Tcl_SetObjErrorCode(interp, objPtr); } } Tcl_SetObjResult(interp, Tcl_GetObjResult(sendInterp)); } Tcl_Release(riPtr); Tcl_Release(sendInterp); } else { /* * This is a non-local request. Send the script to the server and * poll it for a result. */ if (MakeDdeConnection(interp, serviceName, &hConv) != TCL_OK) { invalidServerResponse: Tcl_SetObjResult(interp, Tcl_NewStringObj("invalid data returned from server", -1)); Tcl_SetErrorCode(interp, "TCL", "DDE", "BAD_RESPONSE", NULL); result = TCL_ERROR; goto cleanup; } objPtr = Tcl_ConcatObj(objc, objv); string = (const char *) Tcl_GetUnicodeFromObj(objPtr, &length); ddeItemData = DdeCreateDataHandle(ddeInstance, (BYTE *) string, (DWORD) 2*length+2, 0, 0, CF_UNICODETEXT, 0); if (flags & DDE_FLAG_ASYNC) { ddeData = DdeClientTransaction((LPBYTE) ddeItemData, 0xFFFFFFFF, hConv, 0, CF_UNICODETEXT, XTYP_EXECUTE, TIMEOUT_ASYNC, &ddeResult); DdeAbandonTransaction(ddeInstance, hConv, ddeResult); } else { ddeData = DdeClientTransaction((LPBYTE) ddeItemData, 0xFFFFFFFF, hConv, 0, CF_UNICODETEXT, XTYP_EXECUTE, 30000, NULL); if (ddeData != 0) { ddeCookie = DdeCreateStringHandle(ddeInstance, TCL_DDE_EXECUTE_RESULT, CP_WINUNICODE); ddeData = DdeClientTransaction(NULL, 0, hConv, ddeCookie, CF_UNICODETEXT, XTYP_REQUEST, 30000, NULL); } } Tcl_DecrRefCount(objPtr); if (ddeData == 0) { SetDdeError(interp); result = TCL_ERROR; goto cleanup; } if (!(flags & DDE_FLAG_ASYNC)) { Tcl_Obj *resultPtr; Tcl_UniChar *ddeDataString; /* * The return handle has a two or four element list in it. The * first element is the return code (TCL_OK, TCL_ERROR, etc.). * The second is the result of the script. If the return code * is TCL_ERROR, then the third element is the value of the * variable "errorCode", and the fourth is the value of the * variable "errorInfo". */ resultPtr = Tcl_NewObj(); length = DdeGetData(ddeData, NULL, 0, 0); ddeDataString = ckalloc(length); DdeGetData(ddeData, (BYTE *) ddeDataString, (DWORD) length, 0); length = (length >> 1) - 1; resultPtr = Tcl_NewUnicodeObj(ddeDataString, length); ckfree(ddeDataString); if (Tcl_ListObjIndex(NULL, resultPtr, 0, &objPtr) != TCL_OK) { Tcl_DecrRefCount(resultPtr); goto invalidServerResponse; } if (Tcl_GetIntFromObj(NULL, objPtr, &result) != TCL_OK) { Tcl_DecrRefCount(resultPtr); goto invalidServerResponse; } if (result == TCL_ERROR) { Tcl_ResetResult(interp); if (Tcl_ListObjIndex(NULL, resultPtr, 3, &objPtr) != TCL_OK) { Tcl_DecrRefCount(resultPtr); goto invalidServerResponse; } length = -1; string = Tcl_GetStringFromObj(objPtr, &length); Tcl_AddObjErrorInfo(interp, string, length); Tcl_ListObjIndex(NULL, resultPtr, 2, &objPtr); Tcl_SetObjErrorCode(interp, objPtr); } if (Tcl_ListObjIndex(NULL, resultPtr, 1, &objPtr) != TCL_OK) { Tcl_DecrRefCount(resultPtr); goto invalidServerResponse; } Tcl_SetObjResult(interp, objPtr); Tcl_DecrRefCount(resultPtr); } } } } cleanup: if (ddeCookie != NULL) { DdeFreeStringHandle(ddeInstance, ddeCookie); } if (ddeItem != NULL) { DdeFreeStringHandle(ddeInstance, ddeItem); } if (ddeItemData != NULL) { DdeFreeDataHandle(ddeItemData); } if (ddeData != NULL) { DdeFreeDataHandle(ddeData); } if (hConv != NULL) { DdeDisconnect(hConv); } return result; } /* * Local variables: * mode: c * indent-tabs-mode: t * tab-width: 8 * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tclWinFile.c0000755000175000017500000023221112663660066014575 0ustar sergeisergei/* * tclWinFile.c -- * * This file contains temporary wrappers around UNIX file handling * functions. These wrappers map the UNIX functions to Win32 HANDLE-style * files, which can be manipulated through the Win32 console redirection * interfaces. * * Copyright (c) 1995-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclWinInt.h" #include "tclFileSystem.h" #include #include #include /* For TclpGetUserHome(). */ #include /* For TclpGetUserHome(). */ #ifdef _MSC_VER # pragma comment(lib, "userenv.lib") #endif /* * The number of 100-ns intervals between the Windows system epoch (1601-01-01 * on the proleptic Gregorian calendar) and the Posix epoch (1970-01-01). */ #define POSIX_EPOCH_AS_FILETIME \ ((Tcl_WideInt) 116444736 * (Tcl_WideInt) 1000000000) /* * Declarations for 'link' related information. This information should come * with VC++ 6.0, but is not in some older SDKs. In any case it is not well * documented. */ #ifndef IO_REPARSE_TAG_RESERVED_ONE # define IO_REPARSE_TAG_RESERVED_ONE 0x000000001 #endif #ifndef IO_REPARSE_TAG_RESERVED_RANGE # define IO_REPARSE_TAG_RESERVED_RANGE 0x000000001 #endif #ifndef IO_REPARSE_TAG_VALID_VALUES # define IO_REPARSE_TAG_VALID_VALUES 0x0E000FFFF #endif #ifndef IO_REPARSE_TAG_HSM # define IO_REPARSE_TAG_HSM 0x0C0000004 #endif #ifndef IO_REPARSE_TAG_NSS # define IO_REPARSE_TAG_NSS 0x080000005 #endif #ifndef IO_REPARSE_TAG_NSSRECOVER # define IO_REPARSE_TAG_NSSRECOVER 0x080000006 #endif #ifndef IO_REPARSE_TAG_SIS # define IO_REPARSE_TAG_SIS 0x080000007 #endif #ifndef IO_REPARSE_TAG_DFS # define IO_REPARSE_TAG_DFS 0x080000008 #endif #ifndef IO_REPARSE_TAG_RESERVED_ZERO # define IO_REPARSE_TAG_RESERVED_ZERO 0x00000000 #endif #ifndef FILE_FLAG_OPEN_REPARSE_POINT # define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000 #endif #ifndef IO_REPARSE_TAG_MOUNT_POINT # define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 #endif #ifndef IsReparseTagValid # define IsReparseTagValid(x) \ (!((x)&~IO_REPARSE_TAG_VALID_VALUES)&&((x)>IO_REPARSE_TAG_RESERVED_RANGE)) #endif #ifndef IO_REPARSE_TAG_SYMBOLIC_LINK # define IO_REPARSE_TAG_SYMBOLIC_LINK IO_REPARSE_TAG_RESERVED_ZERO #endif #ifndef FILE_SPECIAL_ACCESS # define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS) #endif #ifndef FSCTL_SET_REPARSE_POINT # define FSCTL_SET_REPARSE_POINT \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) # define FSCTL_GET_REPARSE_POINT \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) # define FSCTL_DELETE_REPARSE_POINT \ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) #endif #ifndef INVALID_FILE_ATTRIBUTES #define INVALID_FILE_ATTRIBUTES ((DWORD)-1) #endif /* * Maximum reparse buffer info size. The max user defined reparse data is * 16KB, plus there's a header. */ #define MAX_REPARSE_SIZE 17000 /* * Undocumented REPARSE_MOUNTPOINT_HEADER_SIZE structure definition. This is * found in winnt.h. * * IMPORTANT: caution when using this structure, since the actual structures * used will want to store a full path in the 'PathBuffer' field, but there * isn't room (there's only a single WCHAR!). Therefore one must artificially * create a larger space of memory and then cast it to this type. We use the * 'DUMMY_REPARSE_BUFFER' struct just below to deal with this problem. */ #define REPARSE_MOUNTPOINT_HEADER_SIZE 8 #ifndef REPARSE_DATA_BUFFER_HEADER_SIZE typedef struct _REPARSE_DATA_BUFFER { DWORD ReparseTag; WORD ReparseDataLength; WORD Reserved; union { struct { WORD SubstituteNameOffset; WORD SubstituteNameLength; WORD PrintNameOffset; WORD PrintNameLength; ULONG Flags; WCHAR PathBuffer[1]; } SymbolicLinkReparseBuffer; struct { WORD SubstituteNameOffset; WORD SubstituteNameLength; WORD PrintNameOffset; WORD PrintNameLength; WCHAR PathBuffer[1]; } MountPointReparseBuffer; struct { BYTE DataBuffer[1]; } GenericReparseBuffer; }; } REPARSE_DATA_BUFFER; #endif typedef struct { REPARSE_DATA_BUFFER dummy; WCHAR dummyBuf[MAX_PATH * 3]; } DUMMY_REPARSE_BUFFER; /* * Other typedefs required by this code. */ static time_t ToCTime(FILETIME fileTime); static void FromCTime(time_t posixTime, FILETIME *fileTime); /* * Declarations for local functions defined in this file: */ static int NativeAccess(const TCHAR *path, int mode); static int NativeDev(const TCHAR *path); static int NativeStat(const TCHAR *path, Tcl_StatBuf *statPtr, int checkLinks); static unsigned short NativeStatMode(DWORD attr, int checkLinks, int isExec); static int NativeIsExec(const TCHAR *path); static int NativeReadReparse(const TCHAR *LinkDirectory, REPARSE_DATA_BUFFER *buffer, DWORD desiredAccess); static int NativeWriteReparse(const TCHAR *LinkDirectory, REPARSE_DATA_BUFFER *buffer); static int NativeMatchType(int isDrive, DWORD attr, const TCHAR *nativeName, Tcl_GlobTypeData *types); static int WinIsDrive(const char *name, int nameLen); static int WinIsReserved(const char *path); static Tcl_Obj * WinReadLink(const TCHAR *LinkSource); static Tcl_Obj * WinReadLinkDirectory(const TCHAR *LinkDirectory); static int WinLink(const TCHAR *LinkSource, const TCHAR *LinkTarget, int linkAction); static int WinSymLinkDirectory(const TCHAR *LinkDirectory, const TCHAR *LinkTarget); MODULE_SCOPE TCL_NORETURN void tclWinDebugPanic(const char *format, ...); /* *-------------------------------------------------------------------- * * WinLink -- * * Make a link from source to target. * *-------------------------------------------------------------------- */ static int WinLink( const TCHAR *linkSourcePath, const TCHAR *linkTargetPath, int linkAction) { TCHAR tempFileName[MAX_PATH]; TCHAR *tempFilePart; DWORD attr; /* * Get the full path referenced by the target. */ if (!GetFullPathName(linkTargetPath, MAX_PATH, tempFileName, &tempFilePart)) { /* * Invalid file. */ TclWinConvertError(GetLastError()); return -1; } /* * Make sure source file doesn't exist. */ attr = GetFileAttributes(linkSourcePath); if (attr != INVALID_FILE_ATTRIBUTES) { Tcl_SetErrno(EEXIST); return -1; } /* * Get the full path referenced by the source file/directory. */ if (!GetFullPathName(linkSourcePath, MAX_PATH, tempFileName, &tempFilePart)) { /* * Invalid file. */ TclWinConvertError(GetLastError()); return -1; } /* * Check the target. */ attr = GetFileAttributes(linkTargetPath); if (attr == INVALID_FILE_ATTRIBUTES) { /* * The target doesn't exist. */ TclWinConvertError(GetLastError()); } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { /* * It is a file. */ if (linkAction & TCL_CREATE_HARD_LINK) { if (CreateHardLink(linkSourcePath, linkTargetPath, NULL)) { /* * Success! */ return 0; } TclWinConvertError(GetLastError()); } else if (linkAction & TCL_CREATE_SYMBOLIC_LINK) { /* * Can't symlink files. */ Tcl_SetErrno(ENOTDIR); } else { Tcl_SetErrno(ENODEV); } } else { /* * We've got a directory. Now check whether what we're trying to do is * reasonable. */ if (linkAction & TCL_CREATE_SYMBOLIC_LINK) { return WinSymLinkDirectory(linkSourcePath, linkTargetPath); } else if (linkAction & TCL_CREATE_HARD_LINK) { /* * Can't hard link directories. */ Tcl_SetErrno(EISDIR); } else { Tcl_SetErrno(ENODEV); } } return -1; } /* *-------------------------------------------------------------------- * * WinReadLink -- * * What does 'LinkSource' point to? * *-------------------------------------------------------------------- */ static Tcl_Obj * WinReadLink( const TCHAR *linkSourcePath) { TCHAR tempFileName[MAX_PATH]; TCHAR *tempFilePart; DWORD attr; /* * Get the full path referenced by the target. */ if (!GetFullPathName(linkSourcePath, MAX_PATH, tempFileName, &tempFilePart)) { /* * Invalid file. */ TclWinConvertError(GetLastError()); return NULL; } /* * Make sure source file does exist. */ attr = GetFileAttributes(linkSourcePath); if (attr == INVALID_FILE_ATTRIBUTES) { /* * The source doesn't exist. */ TclWinConvertError(GetLastError()); return NULL; } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { /* * It is a file - this is not yet supported. */ Tcl_SetErrno(ENOTDIR); return NULL; } return WinReadLinkDirectory(linkSourcePath); } /* *-------------------------------------------------------------------- * * WinSymLinkDirectory -- * * This routine creates a NTFS junction, using the undocumented * FSCTL_SET_REPARSE_POINT structure Win2K uses for mount points and * junctions. * * Assumption that linkTargetPath is a valid, existing directory. * * Returns: * Zero on success. * *-------------------------------------------------------------------- */ static int WinSymLinkDirectory( const TCHAR *linkDirPath, const TCHAR *linkTargetPath) { DUMMY_REPARSE_BUFFER dummy; REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER *) &dummy; int len; WCHAR nativeTarget[MAX_PATH]; WCHAR *loop; /* * Make the native target name. */ memcpy(nativeTarget, L"\\??\\", 4 * sizeof(WCHAR)); memcpy(nativeTarget + 4, linkTargetPath, sizeof(WCHAR) * (1+wcslen((WCHAR *) linkTargetPath))); len = wcslen(nativeTarget); /* * We must have backslashes only. This is VERY IMPORTANT. If we have any * forward slashes everything appears to work, but the resulting symlink * is useless! */ for (loop = nativeTarget; *loop != 0; loop++) { if (*loop == L'/') { *loop = L'\\'; } } if ((nativeTarget[len-1] == L'\\') && (nativeTarget[len-2] != L':')) { nativeTarget[len-1] = 0; } /* * Build the reparse info. */ memset(reparseBuffer, 0, sizeof(DUMMY_REPARSE_BUFFER)); reparseBuffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; reparseBuffer->MountPointReparseBuffer.SubstituteNameLength = wcslen(nativeTarget) * sizeof(WCHAR); reparseBuffer->Reserved = 0; reparseBuffer->MountPointReparseBuffer.PrintNameLength = 0; reparseBuffer->MountPointReparseBuffer.PrintNameOffset = reparseBuffer->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR); memcpy(reparseBuffer->MountPointReparseBuffer.PathBuffer, nativeTarget, sizeof(WCHAR) + reparseBuffer->MountPointReparseBuffer.SubstituteNameLength); reparseBuffer->ReparseDataLength = reparseBuffer->MountPointReparseBuffer.SubstituteNameLength+12; return NativeWriteReparse(linkDirPath, reparseBuffer); } /* *-------------------------------------------------------------------- * * TclWinSymLinkCopyDirectory -- * * Copy a Windows NTFS junction. This function assumes that LinkOriginal * exists and is a valid junction point, and that LinkCopy does not * exist. * * Returns: * Zero on success. * *-------------------------------------------------------------------- */ int TclWinSymLinkCopyDirectory( const TCHAR *linkOrigPath, /* Existing junction - reparse point */ const TCHAR *linkCopyPath) /* Will become a duplicate junction */ { DUMMY_REPARSE_BUFFER dummy; REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER *) &dummy; if (NativeReadReparse(linkOrigPath, reparseBuffer, GENERIC_READ)) { return -1; } return NativeWriteReparse(linkCopyPath, reparseBuffer); } /* *-------------------------------------------------------------------- * * TclWinSymLinkDelete -- * * Delete a Windows NTFS junction. Once the junction information is * deleted, the filesystem object becomes an ordinary directory. Unless * 'linkOnly' is given, that directory is also removed. * * Assumption that LinkOriginal is a valid, existing junction. * * Returns: * Zero on success. * *-------------------------------------------------------------------- */ int TclWinSymLinkDelete( const TCHAR *linkOrigPath, int linkOnly) { /* * It is a symbolic link - remove it. */ DUMMY_REPARSE_BUFFER dummy; REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER *) &dummy; HANDLE hFile; DWORD returnedLength; memset(reparseBuffer, 0, sizeof(DUMMY_REPARSE_BUFFER)); reparseBuffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; hFile = CreateFile(linkOrigPath, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile != INVALID_HANDLE_VALUE) { if (!DeviceIoControl(hFile, FSCTL_DELETE_REPARSE_POINT, reparseBuffer, REPARSE_MOUNTPOINT_HEADER_SIZE,NULL,0,&returnedLength,NULL)) { /* * Error setting junction. */ TclWinConvertError(GetLastError()); CloseHandle(hFile); } else { CloseHandle(hFile); if (!linkOnly) { RemoveDirectory(linkOrigPath); } return 0; } } return -1; } /* *-------------------------------------------------------------------- * * WinReadLinkDirectory -- * * This routine reads a NTFS junction, using the undocumented * FSCTL_GET_REPARSE_POINT structure Win2K uses for mount points and * junctions. * * Assumption that LinkDirectory is a valid, existing directory. * * Returns: * A Tcl_Obj with refCount of 1 (i.e. owned by the caller), or NULL if * anything went wrong. * * In the future we should enhance this to return a path object rather * than a string. * *-------------------------------------------------------------------- */ static Tcl_Obj * WinReadLinkDirectory( const TCHAR *linkDirPath) { int attr, len, offset; DUMMY_REPARSE_BUFFER dummy; REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER *) &dummy; Tcl_Obj *retVal; Tcl_DString ds; const char *copy; attr = GetFileAttributes(linkDirPath); if (!(attr & FILE_ATTRIBUTE_REPARSE_POINT)) { goto invalidError; } if (NativeReadReparse(linkDirPath, reparseBuffer, 0)) { return NULL; } switch (reparseBuffer->ReparseTag) { case 0x80000000|IO_REPARSE_TAG_SYMBOLIC_LINK: case IO_REPARSE_TAG_SYMBOLIC_LINK: case IO_REPARSE_TAG_MOUNT_POINT: /* * Certain native path representations on Windows have a special * prefix to indicate that they are to be treated specially. For * example extremely long paths, or symlinks, or volumes mounted * inside directories. * * There is an assumption in this code that 'wide' interfaces are * being used (see tclWin32Dll.c), which is true for the only systems * which support reparse tags at present. If that changes in the * future, this code will have to be generalised. */ offset = 0; #ifdef UNICODE if (reparseBuffer->MountPointReparseBuffer.PathBuffer[0] == L'\\') { /* * Check whether this is a mounted volume. */ if (wcsncmp(reparseBuffer->MountPointReparseBuffer.PathBuffer, L"\\??\\Volume{",11) == 0) { char drive; /* * There is some confusion between \??\ and \\?\ which we have * to fix here. It doesn't seem very well documented. */ reparseBuffer->MountPointReparseBuffer.PathBuffer[1]=L'\\'; /* * Check if a corresponding drive letter exists, and use that * if it is found */ drive = TclWinDriveLetterForVolMountPoint( reparseBuffer->MountPointReparseBuffer.PathBuffer); if (drive != -1) { char driveSpec[3] = { '\0', ':', '\0' }; driveSpec[0] = drive; retVal = Tcl_NewStringObj(driveSpec,2); Tcl_IncrRefCount(retVal); return retVal; } /* * This is actually a mounted drive, which doesn't exists as a * DOS drive letter. This means the path isn't actually a * link, although we partially treat it like one ('file type' * will return 'link'), but then the link will actually just * be treated like an ordinary directory. I don't believe any * serious inconsistency will arise from this, but it is * something to be aware of. */ goto invalidError; } else if (wcsncmp(reparseBuffer->MountPointReparseBuffer .PathBuffer, L"\\\\?\\",4) == 0) { /* * Strip off the prefix. */ offset = 4; } else if (wcsncmp(reparseBuffer->MountPointReparseBuffer .PathBuffer, L"\\??\\",4) == 0) { /* * Strip off the prefix. */ offset = 4; } } #endif /* UNICODE */ Tcl_WinTCharToUtf((const TCHAR *) reparseBuffer->MountPointReparseBuffer.PathBuffer, (int) reparseBuffer->MountPointReparseBuffer .SubstituteNameLength, &ds); copy = Tcl_DStringValue(&ds)+offset; len = Tcl_DStringLength(&ds)-offset; retVal = Tcl_NewStringObj(copy,len); Tcl_IncrRefCount(retVal); Tcl_DStringFree(&ds); return retVal; } invalidError: Tcl_SetErrno(EINVAL); return NULL; } /* *-------------------------------------------------------------------- * * NativeReadReparse -- * * Read the junction/reparse information from a given NTFS directory. * * Assumption that linkDirPath is a valid, existing directory. * * Returns: * Zero on success. * *-------------------------------------------------------------------- */ static int NativeReadReparse( const TCHAR *linkDirPath, /* The junction to read */ REPARSE_DATA_BUFFER *buffer,/* Pointer to buffer. Cannot be NULL */ DWORD desiredAccess) { HANDLE hFile; DWORD returnedLength; hFile = CreateFile(linkDirPath, desiredAccess, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile == INVALID_HANDLE_VALUE) { /* * Error creating directory. */ TclWinConvertError(GetLastError()); return -1; } /* * Get the link. */ if (!DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, sizeof(DUMMY_REPARSE_BUFFER), &returnedLength, NULL)) { /* * Error setting junction. */ TclWinConvertError(GetLastError()); CloseHandle(hFile); return -1; } CloseHandle(hFile); if (!IsReparseTagValid(buffer->ReparseTag)) { Tcl_SetErrno(EINVAL); return -1; } return 0; } /* *-------------------------------------------------------------------- * * NativeWriteReparse -- * * Write the reparse information for a given directory. * * Assumption that LinkDirectory does not exist. * *-------------------------------------------------------------------- */ static int NativeWriteReparse( const TCHAR *linkDirPath, REPARSE_DATA_BUFFER *buffer) { HANDLE hFile; DWORD returnedLength; /* * Create the directory - it must not already exist. */ if (CreateDirectory(linkDirPath, NULL) == 0) { /* * Error creating directory. */ TclWinConvertError(GetLastError()); return -1; } hFile = CreateFile(linkDirPath, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile == INVALID_HANDLE_VALUE) { /* * Error creating directory. */ TclWinConvertError(GetLastError()); return -1; } /* * Set the link. */ if (!DeviceIoControl(hFile, FSCTL_SET_REPARSE_POINT, buffer, (DWORD) buffer->ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE, NULL, 0, &returnedLength, NULL)) { /* * Error setting junction. */ TclWinConvertError(GetLastError()); CloseHandle(hFile); RemoveDirectory(linkDirPath); return -1; } CloseHandle(hFile); /* * We succeeded. */ return 0; } /* *---------------------------------------------------------------------- * * tclWinDebugPanic -- * * Display a message. If a debugger is present, present it directly to * the debugger, otherwise use a MessageBox. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ TCL_NORETURN void tclWinDebugPanic( const char *format, ...) { #define TCL_MAX_WARN_LEN 1024 va_list argList; char buf[TCL_MAX_WARN_LEN * TCL_UTF_MAX]; WCHAR msgString[TCL_MAX_WARN_LEN]; va_start(argList, format); vsnprintf(buf, sizeof(buf), format, argList); msgString[TCL_MAX_WARN_LEN-1] = L'\0'; MultiByteToWideChar(CP_UTF8, 0, buf, -1, msgString, TCL_MAX_WARN_LEN); /* * Truncate MessageBox string if it is too long to not overflow the screen * and cause possible oversized window error. */ if (msgString[TCL_MAX_WARN_LEN-1] != L'\0') { memcpy(msgString + (TCL_MAX_WARN_LEN - 5), L" ...", 5 * sizeof(WCHAR)); } if (IsDebuggerPresent()) { OutputDebugStringW(msgString); } else { MessageBeep(MB_ICONEXCLAMATION); MessageBoxW(NULL, msgString, L"Fatal Error", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); } #if defined(__GNUC__) __builtin_trap(); #elif defined(_WIN64) __debugbreak(); #elif defined(_MSC_VER) _asm {int 3} #else DebugBreak(); #endif abort(); } /* *--------------------------------------------------------------------------- * * TclpFindExecutable -- * * This function computes the absolute path name of the current * application. * * Results: * None. * * Side effects: * The computed path is stored. * *--------------------------------------------------------------------------- */ void TclpFindExecutable( const char *argv0) /* If NULL, install PanicMessageBox, otherwise * ignore. */ { WCHAR wName[MAX_PATH]; char name[MAX_PATH * TCL_UTF_MAX]; /* * Under Windows we ignore argv0, and return the path for the file used to * create this process. Only if it is NULL, install a new panic handler. */ if (argv0 == NULL) { Tcl_SetPanicProc(tclWinDebugPanic); } #ifdef UNICODE GetModuleFileNameW(NULL, wName, MAX_PATH); #else GetModuleFileNameA(NULL, name, sizeof(name)); /* * Convert to WCHAR to get out of ANSI codepage */ MultiByteToWideChar(CP_ACP, 0, name, -1, wName, MAX_PATH); #endif WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, sizeof(name), NULL, NULL); TclWinNoBackslash(name); TclSetObjNameOfExecutable(Tcl_NewStringObj(name, -1), NULL); } /* *---------------------------------------------------------------------- * * TclpMatchInDirectory -- * * This routine is used by the globbing code to search a directory for * all files which match a given pattern. * * Results: * The return value is a standard Tcl result indicating whether an error * occurred in globbing. Errors are left in interp, good results are * lappended to resultPtr (which must be a valid object). * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclpMatchInDirectory( Tcl_Interp *interp, /* Interpreter to receive errors. */ Tcl_Obj *resultPtr, /* List object to lappend results. */ Tcl_Obj *pathPtr, /* Contains path to directory to search. */ const char *pattern, /* Pattern to match against. */ Tcl_GlobTypeData *types) /* Object containing list of acceptable types. * May be NULL. In particular the directory * flag is very important. */ { const TCHAR *native; if (types != NULL && types->type == TCL_GLOB_TYPE_MOUNT) { /* * The native filesystem never adds mounts. */ return TCL_OK; } if (pattern == NULL || (*pattern == '\0')) { Tcl_Obj *norm = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (norm != NULL) { /* * Match a single file directly. */ int len; DWORD attr; WIN32_FILE_ATTRIBUTE_DATA data; const char *str = Tcl_GetStringFromObj(norm,&len); native = Tcl_FSGetNativePath(pathPtr); if (GetFileAttributesEx(native, GetFileExInfoStandard, &data) != TRUE) { return TCL_OK; } attr = data.dwFileAttributes; if (NativeMatchType(WinIsDrive(str,len), attr, native, types)) { Tcl_ListObjAppendElement(interp, resultPtr, pathPtr); } } return TCL_OK; } else { DWORD attr; HANDLE handle; WIN32_FIND_DATA data; const char *dirName; /* UTF-8 dir name, later with pattern * appended. */ int dirLength; int matchSpecialDots; Tcl_DString ds; /* Native encoding of dir, also used * temporarily for other things. */ Tcl_DString dsOrig; /* UTF-8 encoding of dir. */ Tcl_Obj *fileNamePtr; char lastChar; /* * Get the normalized path representation (the main thing is we dont * want any '~' sequences). */ fileNamePtr = Tcl_FSGetNormalizedPath(interp, pathPtr); if (fileNamePtr == NULL) { return TCL_ERROR; } /* * Verify that the specified path exists and is actually a directory. */ native = Tcl_FSGetNativePath(pathPtr); if (native == NULL) { return TCL_OK; } attr = GetFileAttributes(native); if ((attr == INVALID_FILE_ATTRIBUTES) || ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0)) { return TCL_OK; } /* * Build up the directory name for searching, including a trailing * directory separator. */ Tcl_DStringInit(&dsOrig); dirName = Tcl_GetStringFromObj(fileNamePtr, &dirLength); Tcl_DStringAppend(&dsOrig, dirName, dirLength); lastChar = dirName[dirLength -1]; if ((lastChar != '\\') && (lastChar != '/') && (lastChar != ':')) { TclDStringAppendLiteral(&dsOrig, "/"); dirLength++; } dirName = Tcl_DStringValue(&dsOrig); /* * We need to check all files in the directory, so we append '*.*' to * the path, unless the pattern we've been given is rather simple, * when we can use that instead. */ if (strpbrk(pattern, "[]\\") == NULL) { /* * The pattern is a simple one containing just '*' and/or '?'. * This means we can get the OS to help us, by passing it the * pattern. */ dirName = Tcl_DStringAppend(&dsOrig, pattern, -1); } else { dirName = TclDStringAppendLiteral(&dsOrig, "*.*"); } native = Tcl_WinUtfToTChar(dirName, -1, &ds); if ((types == NULL) || (types->type != TCL_GLOB_TYPE_DIR)) { handle = FindFirstFile(native, &data); } else { /* * We can be more efficient, for pure directory requests. */ handle = FindFirstFileEx(native, FindExInfoStandard, &data, FindExSearchLimitToDirectories, NULL, 0); } if (handle == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); Tcl_DStringFree(&ds); if (err == ERROR_FILE_NOT_FOUND) { /* * We used our 'pattern' above, and matched nothing. This * means we just return TCL_OK, indicating no results found. */ Tcl_DStringFree(&dsOrig); return TCL_OK; } TclWinConvertError(err); if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read directory \"%s\": %s", Tcl_DStringValue(&dsOrig), Tcl_PosixError(interp))); } Tcl_DStringFree(&dsOrig); return TCL_ERROR; } Tcl_DStringFree(&ds); /* * We may use this later, so we must restore it to its length * including the directory delimiter. */ Tcl_DStringSetLength(&dsOrig, dirLength); /* * Check to see if the pattern should match the special . and * .. names, referring to the current directory, or the directory * above. We need a special check for this because paths beginning * with a dot are not considered hidden on Windows, and so otherwise a * relative glob like 'glob -join * *' will actually return * './. ../..' etc. */ if ((pattern[0] == '.') || ((pattern[0] == '\\') && (pattern[1] == '.'))) { matchSpecialDots = 1; } else { matchSpecialDots = 0; } /* * Now iterate over all of the files in the directory, starting with * the first one we found. */ do { const char *utfname; int checkDrive = 0, isDrive; DWORD attr; native = data.cFileName; attr = data.dwFileAttributes; utfname = Tcl_WinTCharToUtf(native, -1, &ds); if (!matchSpecialDots) { /* * If it is exactly '.' or '..' then we ignore it. */ if ((utfname[0] == '.') && (utfname[1] == '\0' || (utfname[1] == '.' && utfname[2] == '\0'))) { Tcl_DStringFree(&ds); continue; } } else if (utfname[0] == '.' && utfname[1] == '.' && utfname[2] == '\0') { /* * Have to check if this is a drive below, so we can correctly * match 'hidden' and not hidden files. */ checkDrive = 1; } /* * Check to see if the file matches the pattern. Note that we are * ignoring the case sensitivity flag because Windows doesn't * honor case even if the volume is case sensitive. If the volume * also doesn't preserve case, then we previously returned the * lower case form of the name. This didn't seem quite right since * there are non-case-preserving volumes that actually return * mixed case. So now we are returning exactly what we get from * the system. */ if (Tcl_StringCaseMatch(utfname, pattern, 1)) { /* * If the file matches, then we need to process the remainder * of the path. */ if (checkDrive) { const char *fullname = Tcl_DStringAppend(&dsOrig, utfname, Tcl_DStringLength(&ds)); isDrive = WinIsDrive(fullname, Tcl_DStringLength(&dsOrig)); Tcl_DStringSetLength(&dsOrig, dirLength); } else { isDrive = 0; } if (NativeMatchType(isDrive, attr, native, types)) { Tcl_ListObjAppendElement(interp, resultPtr, TclNewFSPathObj(pathPtr, utfname, Tcl_DStringLength(&ds))); } } /* * Free ds here to ensure that native is valid above. */ Tcl_DStringFree(&ds); } while (FindNextFile(handle, &data) == TRUE); FindClose(handle); Tcl_DStringFree(&dsOrig); return TCL_OK; } } /* * Does the given path represent a root volume? We need this special case * because for NTFS root volumes, the getFileAttributesProc returns a 'hidden' * attribute when it should not. */ static int WinIsDrive( const char *name, /* Name (UTF-8) */ int len) /* Length of name */ { int remove = 0; while (len > 4) { if ((name[len-1] != '.' || name[len-2] != '.') || (name[len-3] != '/' && name[len-3] != '\\')) { /* * We don't have '/..' at the end. */ if (remove == 0) { break; } remove--; while (len > 0) { len--; if (name[len] == '/' || name[len] == '\\') { break; } } if (len < 4) { len++; break; } } else { /* * We do have '/..' */ len -= 3; remove++; } } if (len < 4) { if (len == 0) { /* * Not sure if this is possible, but we pass it on anyway. */ } else if (len == 1 && (name[0] == '/' || name[0] == '\\')) { /* * Path is pointing to the root volume. */ return 1; } else if ((name[1] == ':') && (len == 2 || (name[2] == '/' || name[2] == '\\'))) { /* * Path is of the form 'x:' or 'x:/' or 'x:\' */ return 1; } } return 0; } /* * Does the given path represent a reserved window path name? If not return 0, * if true, return the number of characters of the path that we actually want * (not any trailing :). */ static int WinIsReserved( const char *path) /* Path in UTF-8 */ { if ((path[0] == 'c' || path[0] == 'C') && (path[1] == 'o' || path[1] == 'O')) { if ((path[2] == 'm' || path[2] == 'M') && path[3] >= '1' && path[3] <= '9') { /* * May have match for 'com[1-9]:?', which is a serial port. */ if (path[4] == '\0') { return 4; } else if (path [4] == ':' && path[5] == '\0') { return 4; } } else if ((path[2] == 'n' || path[2] == 'N') && path[3] == '\0') { /* * Have match for 'con' */ return 3; } } else if ((path[0] == 'l' || path[0] == 'L') && (path[1] == 'p' || path[1] == 'P') && (path[2] == 't' || path[2] == 'T')) { if (path[3] >= '1' && path[3] <= '9') { /* * May have match for 'lpt[1-9]:?' */ if (path[4] == '\0') { return 4; } else if (path [4] == ':' && path[5] == '\0') { return 4; } } } else if (!strcasecmp(path, "prn") || !strcasecmp(path, "nul") || !strcasecmp(path, "aux")) { /* * Have match for 'prn', 'nul' or 'aux'. */ return 3; } return 0; } /* *---------------------------------------------------------------------- * * NativeMatchType -- * * This function needs a special case for a path which is a root volume, * because for NTFS root volumes, the getFileAttributesProc returns a * 'hidden' attribute when it should not. * * We never make any calls to a 'get attributes' routine here, since we * have arranged things so that our caller already knows such * information. * * Results: * 0 = file doesn't match * 1 = file matches * *---------------------------------------------------------------------- */ static int NativeMatchType( int isDrive, /* Is this a drive. */ DWORD attr, /* We already know the attributes for the * file. */ const TCHAR *nativeName, /* Native path to check. */ Tcl_GlobTypeData *types) /* Type description to match against. */ { /* * 'attr' represents the attributes of the file, but we only want to * retrieve this info if it is absolutely necessary because it is an * expensive call. Unfortunately, to deal with hidden files properly, we * must always retrieve it. */ if (types == NULL) { /* * If invisible, don't return the file. */ return !(attr & FILE_ATTRIBUTE_HIDDEN && !isDrive); } if (attr & FILE_ATTRIBUTE_HIDDEN && !isDrive) { /* * If invisible. */ if ((types->perm == 0) || !(types->perm & TCL_GLOB_PERM_HIDDEN)) { return 0; } } else { /* * Visible. */ if (types->perm & TCL_GLOB_PERM_HIDDEN) { return 0; } } if (types->perm != 0) { if (((types->perm & TCL_GLOB_PERM_RONLY) && !(attr & FILE_ATTRIBUTE_READONLY)) || ((types->perm & TCL_GLOB_PERM_R) && (0 /* File exists => R_OK on Windows */)) || ((types->perm & TCL_GLOB_PERM_W) && (attr & FILE_ATTRIBUTE_READONLY)) || ((types->perm & TCL_GLOB_PERM_X) && (!(attr & FILE_ATTRIBUTE_DIRECTORY) && !NativeIsExec(nativeName)))) { return 0; } } if ((types->type & TCL_GLOB_TYPE_DIR) && (attr & FILE_ATTRIBUTE_DIRECTORY)) { /* * Quicker test for directory, which is a common case. */ return 1; } else if (types->type != 0) { unsigned short st_mode; int isExec = NativeIsExec(nativeName); st_mode = NativeStatMode(attr, 0, isExec); /* * In order bcdpfls as in 'find -t' */ if (((types->type&TCL_GLOB_TYPE_BLOCK) && S_ISBLK(st_mode)) || ((types->type&TCL_GLOB_TYPE_CHAR) && S_ISCHR(st_mode)) || ((types->type&TCL_GLOB_TYPE_DIR) && S_ISDIR(st_mode)) || ((types->type&TCL_GLOB_TYPE_PIPE) && S_ISFIFO(st_mode)) || #ifdef S_ISSOCK ((types->type&TCL_GLOB_TYPE_SOCK) && S_ISSOCK(st_mode)) || #endif ((types->type&TCL_GLOB_TYPE_FILE) && S_ISREG(st_mode))) { /* * Do nothing - this file is ok. */ } else { #ifdef S_ISLNK if (types->type & TCL_GLOB_TYPE_LINK) { st_mode = NativeStatMode(attr, 1, isExec); if (S_ISLNK(st_mode)) { return 1; } } #endif /* S_ISLNK */ return 0; } } return 1; } /* *---------------------------------------------------------------------- * * TclpGetUserHome -- * * This function takes the passed in user name and finds the * corresponding home directory specified in the password file. * * Results: * The result is a pointer to a string specifying the user's home * directory, or NULL if the user's home directory could not be * determined. Storage for the result string is allocated in bufferPtr; * the caller must call Tcl_DStringFree() when the result is no longer * needed. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * TclpGetUserHome( const char *name, /* User name for desired home directory. */ Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with * name of user's home directory. */ { const char *result = NULL; USER_INFO_1 *uiPtr, **uiPtrPtr = &uiPtr; Tcl_DString ds; int nameLen = -1; int badDomain = 0; char *domain; WCHAR *wName, *wHomeDir, *wDomain, **wDomainPtr = &wDomain; WCHAR buf[MAX_PATH]; Tcl_DStringInit(bufferPtr); wDomain = NULL; domain = strchr(name, '@'); if (domain != NULL) { Tcl_DStringInit(&ds); wName = Tcl_UtfToUniCharDString(domain + 1, -1, &ds); badDomain = NetGetDCName(NULL, wName, (LPBYTE *) wDomainPtr); Tcl_DStringFree(&ds); nameLen = domain - name; } if (badDomain == 0) { Tcl_DStringInit(&ds); wName = Tcl_UtfToUniCharDString(name, nameLen, &ds); if (NetUserGetInfo(wDomain, wName, 1, (LPBYTE *) uiPtrPtr) == 0) { wHomeDir = uiPtr->usri1_home_dir; if ((wHomeDir != NULL) && (wHomeDir[0] != L'\0')) { Tcl_UniCharToUtfDString(wHomeDir, lstrlenW(wHomeDir), bufferPtr); } else { /* * User exists but has no home dir. Return * "{GetProfilesDirectory}/". */ DWORD i, size = MAX_PATH; GetProfilesDirectoryW(buf, &size); for (i = 0; i < size; ++i){ if (buf[i] == '\\') buf[i] = '/'; } Tcl_UniCharToUtfDString(buf, size-1, bufferPtr); Tcl_DStringAppend(bufferPtr, "/", -1); Tcl_DStringAppend(bufferPtr, name, -1); } result = Tcl_DStringValue(bufferPtr); NetApiBufferFree((void *) uiPtr); } Tcl_DStringFree(&ds); } if (wDomain != NULL) { NetApiBufferFree((void *) wDomain); } if (result == NULL) { /* * Look in the "Password Lists" section of system.ini for the local * user. There are also entries in that section that begin with a "*" * character that are used by Windows for other purposes; ignore user * names beginning with a "*". */ char buf[MAX_PATH]; if (name[0] != '*') { if (GetPrivateProfileStringA("Password Lists", name, "", buf, MAX_PATH, "system.ini") > 0) { /* * User exists, but there is no such thing as a home directory * in system.ini. Return "{Windows drive}:/". */ GetWindowsDirectoryA(buf, MAX_PATH); Tcl_DStringAppend(bufferPtr, buf, 3); result = Tcl_DStringValue(bufferPtr); } } } return result; } /* *--------------------------------------------------------------------------- * * NativeAccess -- * * This function replaces the library version of access(), fixing the * following bugs: * * 1. access() returns that all files have execute permission. * * Results: * See access documentation. * * Side effects: * See access documentation. * *--------------------------------------------------------------------------- */ static int NativeAccess( const TCHAR *nativePath, /* Path of file to access, native encoding. */ int mode) /* Permission setting. */ { DWORD attr; attr = GetFileAttributes(nativePath); if (attr == INVALID_FILE_ATTRIBUTES) { /* * File might not exist. */ DWORD lasterror = GetLastError(); if (lasterror != ERROR_SHARING_VIOLATION) { TclWinConvertError(lasterror); return -1; } } if (mode == F_OK) { /* * File exists, nothing else to check. */ return 0; } if ((mode & W_OK) && (attr & FILE_ATTRIBUTE_READONLY) && !(attr & FILE_ATTRIBUTE_DIRECTORY)) { /* * The attributes say the file is not writable. If the file is a * regular file (i.e., not a directory), then the file is not * writable, full stop. For directories, the read-only bit is * (mostly) ignored by Windows, so we can't ascertain anything about * directory access from the attrib data. However, if we have the * advanced 'getFileSecurityProc', then more robust ACL checks * will be done below. */ Tcl_SetErrno(EACCES); return -1; } if (mode & X_OK) { if (!(attr & FILE_ATTRIBUTE_DIRECTORY) && !NativeIsExec(nativePath)) { /* * It's not a directory and doesn't have the correct extension. * Therefore it can't be executable */ Tcl_SetErrno(EACCES); return -1; } } /* * It looks as if the permissions are ok, but if we are on NT, 2000 or XP, * we have a more complex permissions structure so we try to check that. * The code below is remarkably complex for such a simple thing as finding * what permissions the OS has set for a file. */ #ifdef UNICODE { SECURITY_DESCRIPTOR *sdPtr = NULL; unsigned long size; PSID pSid = 0; BOOL SidDefaulted; SID_IDENTIFIER_AUTHORITY samba_unmapped = {{0, 0, 0, 0, 0, 22}}; GENERIC_MAPPING genMap; HANDLE hToken = NULL; DWORD desiredAccess = 0, grantedAccess = 0; BOOL accessYesNo = FALSE; PRIVILEGE_SET privSet; DWORD privSetSize = sizeof(PRIVILEGE_SET); int error; /* * First find out how big the buffer needs to be. */ size = 0; GetFileSecurity(nativePath, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION, 0, 0, &size); /* * Should have failed with ERROR_INSUFFICIENT_BUFFER */ error = GetLastError(); if (error != ERROR_INSUFFICIENT_BUFFER) { /* * Most likely case is ERROR_ACCESS_DENIED, which we will convert * to EACCES - just what we want! */ TclWinConvertError((DWORD) error); return -1; } /* * Now size contains the size of buffer needed. */ sdPtr = (SECURITY_DESCRIPTOR *) HeapAlloc(GetProcessHeap(), 0, size); if (sdPtr == NULL) { goto accessError; } /* * Call GetFileSecurity() for real. */ if (!GetFileSecurity(nativePath, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION, sdPtr, size, &size)) { /* * Error getting owner SD */ goto accessError; } /* * As of Samba 3.0.23 (10-Jul-2006), unmapped users and groups are * assigned to SID domains S-1-22-1 and S-1-22-2, where "22" is the * top-level authority. If the file owner and group is unmapped then * the ACL access check below will only test against world access, * which is likely to be more restrictive than the actual access * restrictions. Since the ACL tests are more likely wrong than * right, skip them. Moreover, the unix owner access permissions are * usually mapped to the Windows attributes, so if the user is the * file owner then the attrib checks above are correct (as far as they * go). */ if(!GetSecurityDescriptorOwner(sdPtr,&pSid,&SidDefaulted) || memcmp(GetSidIdentifierAuthority(pSid),&samba_unmapped, sizeof(SID_IDENTIFIER_AUTHORITY))==0) { HeapFree(GetProcessHeap(), 0, sdPtr); return 0; /* Attrib tests say access allowed. */ } /* * Perform security impersonation of the user and open the resulting * thread token. */ if (!ImpersonateSelf(SecurityImpersonation)) { /* * Unable to perform security impersonation. */ goto accessError; } if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE | TOKEN_QUERY, FALSE, &hToken)) { /* * Unable to get current thread's token. */ goto accessError; } RevertToSelf(); /* * Setup desiredAccess according to the access priveleges we are * checking. */ if (mode & R_OK) { desiredAccess |= FILE_GENERIC_READ; } if (mode & W_OK) { desiredAccess |= FILE_GENERIC_WRITE; } if (mode & X_OK) { desiredAccess |= FILE_GENERIC_EXECUTE; } memset(&genMap, 0x0, sizeof(GENERIC_MAPPING)); genMap.GenericRead = FILE_GENERIC_READ; genMap.GenericWrite = FILE_GENERIC_WRITE; genMap.GenericExecute = FILE_GENERIC_EXECUTE; genMap.GenericAll = FILE_ALL_ACCESS; /* * Perform access check using the token. */ if (!AccessCheck(sdPtr, hToken, desiredAccess, &genMap, &privSet, &privSetSize, &grantedAccess, &accessYesNo)) { /* * Unable to perform access check. */ accessError: TclWinConvertError(GetLastError()); if (sdPtr != NULL) { HeapFree(GetProcessHeap(), 0, sdPtr); } if (hToken != NULL) { CloseHandle(hToken); } return -1; } /* * Clean up. */ HeapFree(GetProcessHeap(), 0, sdPtr); CloseHandle(hToken); if (!accessYesNo) { Tcl_SetErrno(EACCES); return -1; } } #endif /* !UNICODE */ return 0; } /* *---------------------------------------------------------------------- * * NativeIsExec -- * * Determines if a path is executable. On windows this is simply defined * by whether the path ends in any of ".exe", ".com", or ".bat" * * Results: * 1 = executable, 0 = not. * *---------------------------------------------------------------------- */ static int NativeIsExec( const TCHAR *path) { int len = _tcslen(path); if (len < 5) { return 0; } if (path[len-4] != '.') { return 0; } if ((_tcsicmp(path+len-3, TEXT("exe")) == 0) || (_tcsicmp(path+len-3, TEXT("com")) == 0) || (_tcsicmp(path+len-3, TEXT("bat")) == 0)) { return 1; } return 0; } /* *---------------------------------------------------------------------- * * TclpObjChdir -- * * This function replaces the library version of chdir(). * * Results: * See chdir() documentation. * * Side effects: * See chdir() documentation. * *---------------------------------------------------------------------- */ int TclpObjChdir( Tcl_Obj *pathPtr) /* Path to new working directory. */ { int result; const TCHAR *nativePath; nativePath = Tcl_FSGetNativePath(pathPtr); if (!nativePath) { return -1; } result = SetCurrentDirectory(nativePath); if (result == 0) { TclWinConvertError(GetLastError()); return -1; } return 0; } /* *---------------------------------------------------------------------- * * TclpGetCwd -- * * This function replaces the library version of getcwd(). (Obsolete * function, only retained for old extensions which may call it * directly). * * Results: * The result is a pointer to a string specifying the current directory, * or NULL if the current directory could not be determined. If NULL is * returned, an error message is left in the interp's result. Storage for * the result string is allocated in bufferPtr; the caller must call * Tcl_DStringFree() when the result is no longer needed. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * TclpGetCwd( Tcl_Interp *interp, /* If non-NULL, used for error reporting. */ Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with * name of current directory. */ { TCHAR buffer[MAX_PATH]; char *p; WCHAR *native; if (GetCurrentDirectory(MAX_PATH, buffer) == 0) { TclWinConvertError(GetLastError()); if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error getting working directory name: %s", Tcl_PosixError(interp))); } return NULL; } /* * Watch for the weird Windows c:\\UNC syntax. */ native = (WCHAR *) buffer; if ((native[0] != '\0') && (native[1] == ':') && (native[2] == '\\') && (native[3] == '\\')) { native += 2; } Tcl_WinTCharToUtf((TCHAR *) native, -1, bufferPtr); /* * Convert to forward slashes for easier use in scripts. */ for (p = Tcl_DStringValue(bufferPtr); *p != '\0'; p++) { if (*p == '\\') { *p = '/'; } } return Tcl_DStringValue(bufferPtr); } int TclpObjStat( Tcl_Obj *pathPtr, /* Path of file to stat. */ Tcl_StatBuf *statPtr) /* Filled with results of stat call. */ { /* * Ensure correct file sizes by forcing the OS to write any pending data * to disk. This is done only for channels which are dirty, i.e. have been * written to since the last flush here. */ TclWinFlushDirtyChannels(); return NativeStat(Tcl_FSGetNativePath(pathPtr), statPtr, 0); } /* *---------------------------------------------------------------------- * * NativeStat -- * * This function replaces the library version of stat(), fixing the * following bugs: * * 1. stat("c:") returns an error. * 2. Borland stat() return time in GMT instead of localtime. * 3. stat("\\server\mount") would return error. * 4. Accepts slashes or backslashes. * 5. st_dev and st_rdev were wrong for UNC paths. * * Results: * See stat documentation. * * Side effects: * See stat documentation. * *---------------------------------------------------------------------- */ static int NativeStat( const TCHAR *nativePath, /* Path of file to stat */ Tcl_StatBuf *statPtr, /* Filled with results of stat call. */ int checkLinks) /* If non-zero, behave like 'lstat' */ { DWORD attr; int dev, nlink = 1; unsigned short mode; unsigned int inode = 0; HANDLE fileHandle; /* * If we can use 'createFile' on this, then we can use the resulting * fileHandle to read more information (nlink, ino) than we can get from * other attributes reading APIs. If not, then we try to fall back on the * 'getFileAttributesExProc', and if that isn't available, then on even * simpler routines. */ fileHandle = CreateFile(nativePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); if (fileHandle != INVALID_HANDLE_VALUE) { BY_HANDLE_FILE_INFORMATION data; if (GetFileInformationByHandle(fileHandle,&data) != TRUE) { CloseHandle(fileHandle); Tcl_SetErrno(ENOENT); return -1; } CloseHandle(fileHandle); attr = data.dwFileAttributes; statPtr->st_size = ((Tcl_WideInt) data.nFileSizeLow) | (((Tcl_WideInt) data.nFileSizeHigh) << 32); statPtr->st_atime = ToCTime(data.ftLastAccessTime); statPtr->st_mtime = ToCTime(data.ftLastWriteTime); statPtr->st_ctime = ToCTime(data.ftCreationTime); /* * On Unix, for directories, nlink apparently depends on the number of * files in the directory. We could calculate that, but it would be a * bit of a performance penalty, I think. Hence we just use what * Windows gives us, which is the same as Unix for files, at least. */ nlink = data.nNumberOfLinks; /* * Unfortunately our stat definition's inode field (unsigned short) * will throw away most of the precision we have here, which means we * can't rely on inode as a unique identifier of a file. We'd really * like to do something like how we handle 'st_size'. */ inode = data.nFileIndexHigh | data.nFileIndexLow; } else { /* * Fall back on the less capable routines. This means no nlink or ino. */ WIN32_FILE_ATTRIBUTE_DATA data; if (GetFileAttributesEx(nativePath, GetFileExInfoStandard, &data) != TRUE) { HANDLE hFind; WIN32_FIND_DATA ffd; DWORD lasterror = GetLastError(); if (lasterror != ERROR_SHARING_VIOLATION) { TclWinConvertError(lasterror); return -1; } hFind = FindFirstFile(nativePath, &ffd); if (hFind == INVALID_HANDLE_VALUE) { TclWinConvertError(GetLastError()); return -1; } memcpy(&data, &ffd, sizeof(data)); FindClose(hFind); } attr = data.dwFileAttributes; statPtr->st_size = ((Tcl_WideInt) data.nFileSizeLow) | (((Tcl_WideInt) data.nFileSizeHigh) << 32); statPtr->st_atime = ToCTime(data.ftLastAccessTime); statPtr->st_mtime = ToCTime(data.ftLastWriteTime); statPtr->st_ctime = ToCTime(data.ftCreationTime); } dev = NativeDev(nativePath); mode = NativeStatMode(attr, checkLinks, NativeIsExec(nativePath)); statPtr->st_dev = (dev_t) dev; statPtr->st_ino = inode; statPtr->st_mode = mode; statPtr->st_nlink = nlink; statPtr->st_uid = 0; statPtr->st_gid = 0; statPtr->st_rdev = (dev_t) dev; return 0; } /* *---------------------------------------------------------------------- * * NativeDev -- * * Calculate just the 'st_dev' field of a 'stat' structure. * *---------------------------------------------------------------------- */ static int NativeDev( const TCHAR *nativePath) /* Full path of file to stat */ { int dev; Tcl_DString ds; TCHAR nativeFullPath[MAX_PATH]; TCHAR *nativePart; const char *fullPath; GetFullPathName(nativePath, MAX_PATH, nativeFullPath, &nativePart); fullPath = Tcl_WinTCharToUtf(nativeFullPath, -1, &ds); if ((fullPath[0] == '\\') && (fullPath[1] == '\\')) { const char *p; DWORD dw; const TCHAR *nativeVol; Tcl_DString volString; p = strchr(fullPath + 2, '\\'); p = strchr(p + 1, '\\'); if (p == NULL) { /* * Add terminating backslash to fullpath or GetVolumeInformation() * won't work. */ fullPath = TclDStringAppendLiteral(&ds, "\\"); p = fullPath + Tcl_DStringLength(&ds); } else { p++; } nativeVol = Tcl_WinUtfToTChar(fullPath, p - fullPath, &volString); dw = (DWORD) -1; GetVolumeInformation(nativeVol, NULL, 0, &dw, NULL, NULL, NULL, 0); /* * GetFullPathName() turns special devices like "NUL" into "\\.\NUL", * but GetVolumeInformation() returns failure for "\\.\NUL". This will * cause "NUL" to get a drive number of -1, which makes about as much * sense as anything since the special devices don't live on any * drive. */ dev = dw; Tcl_DStringFree(&volString); } else if ((fullPath[0] != '\0') && (fullPath[1] == ':')) { dev = Tcl_UniCharToLower(fullPath[0]) - 'a'; } else { dev = -1; } Tcl_DStringFree(&ds); return dev; } /* *---------------------------------------------------------------------- * * NativeStatMode -- * * Calculate just the 'st_mode' field of a 'stat' structure. * * In many places we don't need the full stat structure, and it's much * faster just to calculate these pieces, if that's all we need. * *---------------------------------------------------------------------- */ static unsigned short NativeStatMode( DWORD attr, int checkLinks, int isExec) { int mode; if (checkLinks && (attr & FILE_ATTRIBUTE_REPARSE_POINT)) { /* * It is a link. */ mode = S_IFLNK; } else { mode = (attr & FILE_ATTRIBUTE_DIRECTORY) ? S_IFDIR|S_IEXEC : S_IFREG; } mode |= (attr & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD|S_IWRITE; if (isExec) { mode |= S_IEXEC; } /* * Propagate the S_IREAD, S_IWRITE, S_IEXEC bits to the group and other * positions. */ mode |= (mode & (S_IREAD|S_IWRITE|S_IEXEC)) >> 3; mode |= (mode & (S_IREAD|S_IWRITE|S_IEXEC)) >> 6; return (unsigned short) mode; } /* *------------------------------------------------------------------------ * * ToCTime -- * * Converts a Windows FILETIME to a time_t in UTC. * * Results: * Returns the count of seconds from the Posix epoch. * *------------------------------------------------------------------------ */ static time_t ToCTime( FILETIME fileTime) /* UTC time */ { LARGE_INTEGER convertedTime; convertedTime.LowPart = fileTime.dwLowDateTime; convertedTime.HighPart = (LONG) fileTime.dwHighDateTime; return (time_t) ((convertedTime.QuadPart - (Tcl_WideInt) POSIX_EPOCH_AS_FILETIME) / (Tcl_WideInt) 10000000); } /* *------------------------------------------------------------------------ * * FromCTime -- * * Converts a time_t to a Windows FILETIME * * Results: * Returns the count of 100-ns ticks seconds from the Windows epoch. * *------------------------------------------------------------------------ */ static void FromCTime( time_t posixTime, FILETIME *fileTime) /* UTC Time */ { LARGE_INTEGER convertedTime; convertedTime.QuadPart = ((LONGLONG) posixTime) * 10000000 + POSIX_EPOCH_AS_FILETIME; fileTime->dwLowDateTime = convertedTime.LowPart; fileTime->dwHighDateTime = convertedTime.HighPart; } /* *--------------------------------------------------------------------------- * * TclpGetNativeCwd -- * * This function replaces the library version of getcwd(). * * Results: * The input and output are filesystem paths in native form. The result * is either the given clientData, if the working directory hasn't * changed, or a new clientData (owned by our caller), giving the new * native path, or NULL if the current directory could not be determined. * If NULL is returned, the caller can examine the standard posix error * codes to determine the cause of the problem. * * Side effects: * None. * *---------------------------------------------------------------------- */ ClientData TclpGetNativeCwd( ClientData clientData) { TCHAR buffer[MAX_PATH]; if (GetCurrentDirectory(MAX_PATH, buffer) == 0) { TclWinConvertError(GetLastError()); return NULL; } if (clientData != NULL) { if (_tcscmp((const TCHAR*)clientData, buffer) == 0) { return clientData; } } return TclNativeDupInternalRep(buffer); } int TclpObjAccess( Tcl_Obj *pathPtr, int mode) { return NativeAccess(Tcl_FSGetNativePath(pathPtr), mode); } int TclpObjLstat( Tcl_Obj *pathPtr, Tcl_StatBuf *statPtr) { /* * Ensure correct file sizes by forcing the OS to write any pending data * to disk. This is done only for channels which are dirty, i.e. have been * written to since the last flush here. */ TclWinFlushDirtyChannels(); return NativeStat(Tcl_FSGetNativePath(pathPtr), statPtr, 1); } #ifdef S_IFLNK Tcl_Obj * TclpObjLink( Tcl_Obj *pathPtr, Tcl_Obj *toPtr, int linkAction) { if (toPtr != NULL) { int res; const TCHAR *LinkTarget; const TCHAR *LinkSource = Tcl_FSGetNativePath(pathPtr); Tcl_Obj *normalizedToPtr = Tcl_FSGetNormalizedPath(NULL, toPtr); if (normalizedToPtr == NULL) { return NULL; } LinkTarget = Tcl_FSGetNativePath(normalizedToPtr); if (LinkSource == NULL || LinkTarget == NULL) { return NULL; } res = WinLink(LinkSource, LinkTarget, linkAction); if (res == 0) { return toPtr; } else { return NULL; } } else { const TCHAR *LinkSource = Tcl_FSGetNativePath(pathPtr); if (LinkSource == NULL) { return NULL; } return WinReadLink(LinkSource); } } #endif /* S_IFLNK */ /* *--------------------------------------------------------------------------- * * TclpFilesystemPathType -- * * This function is part of the native filesystem support, and returns * the path type of the given path. Returns NTFS or FAT or whatever is * returned by the 'volume information' proc. * * Results: * NULL at present. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj * TclpFilesystemPathType( Tcl_Obj *pathPtr) { #define VOL_BUF_SIZE 32 int found; TCHAR volType[VOL_BUF_SIZE]; char *firstSeparator; const char *path; Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (normPath == NULL) { return NULL; } path = Tcl_GetString(normPath); if (path == NULL) { return NULL; } firstSeparator = strchr(path, '/'); if (firstSeparator == NULL) { found = GetVolumeInformation(Tcl_FSGetNativePath(pathPtr), NULL, 0, NULL, NULL, NULL, volType, VOL_BUF_SIZE); } else { Tcl_Obj *driveName = Tcl_NewStringObj(path, firstSeparator - path+1); Tcl_IncrRefCount(driveName); found = GetVolumeInformation(Tcl_FSGetNativePath(driveName), NULL, 0, NULL, NULL, NULL, volType, VOL_BUF_SIZE); Tcl_DecrRefCount(driveName); } if (found == 0) { return NULL; } else { Tcl_DString ds; Tcl_WinTCharToUtf(volType, -1, &ds); return TclDStringToObj(&ds); } #undef VOL_BUF_SIZE } /* * This define can be turned on to experiment with a different way of * normalizing paths (using a different Windows API). Unfortunately the new * path seems to take almost exactly the same amount of time as the old path! * The primary time taken by normalization is in * GetFileAttributesEx/FindFirstFile or GetFileAttributesEx/GetLongPathName. * Conversion to/from native is not a significant factor at all. * * Also, since we have to check for symbolic links (reparse points) then we * have to call GetFileAttributes on each path segment anyway, so there's no * benefit to doing anything clever there. */ /* #define TclNORM_LONG_PATH */ /* *--------------------------------------------------------------------------- * * TclpObjNormalizePath -- * * This function scans through a path specification and replaces it, in * place, with a normalized version. This means using the 'longname', and * expanding any symbolic links contained within the path. * * Results: * The new 'nextCheckpoint' value, giving as far as we could understand * in the path. * * Side effects: * The pathPtr string, which must contain a valid path, is possibly * modified in place. * *--------------------------------------------------------------------------- */ int TclpObjNormalizePath( Tcl_Interp *interp, Tcl_Obj *pathPtr, int nextCheckpoint) { char *lastValidPathEnd = NULL; Tcl_DString dsNorm; /* This will hold the normalized string. */ char *path, *currentPathEndPosition; Tcl_Obj *temp = NULL; int isDrive = 1; Tcl_DString ds; /* Some workspace. */ Tcl_DStringInit(&dsNorm); path = Tcl_GetString(pathPtr); currentPathEndPosition = path + nextCheckpoint; if (*currentPathEndPosition == '/') { currentPathEndPosition++; } while (1) { char cur = *currentPathEndPosition; if ((cur=='/' || cur==0) && (path != currentPathEndPosition)) { /* * Reached directory separator, or end of string. */ WIN32_FILE_ATTRIBUTE_DATA data; const TCHAR *nativePath = Tcl_WinUtfToTChar(path, currentPathEndPosition - path, &ds); if (GetFileAttributesEx(nativePath, GetFileExInfoStandard, &data) != TRUE) { /* * File doesn't exist. */ if (isDrive) { int len = WinIsReserved(path); if (len > 0) { /* * Actually it does exist - COM1, etc. */ int i; for (i=0 ; i= L'a') { wc -= (L'a' - L'A'); ((WCHAR *) nativePath)[i] = wc; } } Tcl_DStringAppend(&dsNorm, (const char *)nativePath, (int)(sizeof(WCHAR) * len)); lastValidPathEnd = currentPathEndPosition; } else if (nextCheckpoint == 0) { /* Path starts with a drive designation * that's not actually on the system. * We still must normalize up past the * first separator. [Bug 3603434] */ currentPathEndPosition++; } } Tcl_DStringFree(&ds); break; } /* * File 'nativePath' does exist if we get here. We now want to * check if it is a symlink and otherwise continue with the * rest of the path. */ /* * Check for symlinks, except at last component of path (we * don't follow final symlinks). Also a drive (C:/) for * example, may sometimes have the reparse flag set for some * reason I don't understand. We therefore don't perform this * check for drives. */ if (cur != 0 && !isDrive && data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT){ Tcl_Obj *to = WinReadLinkDirectory(nativePath); if (to != NULL) { /* * Read the reparse point ok. Now, reparse points need * not be normalized, otherwise we could use: * * Tcl_GetStringFromObj(to, &pathLen); * nextCheckpoint = pathLen; * * So, instead we have to start from the beginning. */ nextCheckpoint = 0; Tcl_AppendToObj(to, currentPathEndPosition, -1); /* * Convert link to forward slashes. */ for (path = Tcl_GetString(to); *path != 0; path++) { if (*path == '\\') { *path = '/'; } } path = Tcl_GetString(to); currentPathEndPosition = path + nextCheckpoint; if (temp != NULL) { Tcl_DecrRefCount(temp); } temp = to; /* * Reset variables so we can restart normalization. */ isDrive = 1; Tcl_DStringFree(&dsNorm); Tcl_DStringFree(&ds); continue; } } #ifndef TclNORM_LONG_PATH /* * Now we convert the tail of the current path to its 'long * form', and append it to 'dsNorm' which holds the current * normalized path */ if (isDrive) { WCHAR drive = ((WCHAR *) nativePath)[0]; if (drive >= L'a') { drive -= (L'a' - L'A'); ((WCHAR *) nativePath)[0] = drive; } Tcl_DStringAppend(&dsNorm, (const char *)nativePath, Tcl_DStringLength(&ds)); } else { char *checkDots = NULL; if (lastValidPathEnd[1] == '.') { checkDots = lastValidPathEnd + 1; while (checkDots < currentPathEndPosition) { if (*checkDots != '.') { checkDots = NULL; break; } checkDots++; } } if (checkDots != NULL) { int dotLen = currentPathEndPosition-lastValidPathEnd; /* * Path is just dots. We shouldn't really ever see a * path like that. However, to be nice we at least * don't mangle the path - we just add the dots as a * path segment and continue. */ Tcl_DStringAppend(&dsNorm, ((const char *)nativePath) + Tcl_DStringLength(&ds) - (dotLen * sizeof(TCHAR)), (int)(dotLen * sizeof(TCHAR))); } else { /* * Normal path. */ WIN32_FIND_DATAW fData; HANDLE handle; handle = FindFirstFileW((WCHAR *) nativePath, &fData); if (handle == INVALID_HANDLE_VALUE) { /* * This is usually the '/' in 'c:/' at end of * string. */ Tcl_DStringAppend(&dsNorm, (const char *) L"/", sizeof(WCHAR)); } else { WCHAR *nativeName; if (fData.cFileName[0] != '\0') { nativeName = fData.cFileName; } else { nativeName = fData.cAlternateFileName; } FindClose(handle); Tcl_DStringAppend(&dsNorm, (const char *) L"/", sizeof(WCHAR)); Tcl_DStringAppend(&dsNorm, (const char *) nativeName, (int) (wcslen(nativeName)*sizeof(WCHAR))); } } } #endif /* !TclNORM_LONG_PATH */ Tcl_DStringFree(&ds); lastValidPathEnd = currentPathEndPosition; if (cur == 0) { break; } /* * If we get here, we've got past one directory delimiter, so * we know it is no longer a drive. */ isDrive = 0; } currentPathEndPosition++; #ifdef TclNORM_LONG_PATH /* * Convert the entire known path to long form. */ if (1) { WCHAR wpath[MAX_PATH]; const TCHAR *nativePath = Tcl_WinUtfToTChar(path, lastValidPathEnd - path, &ds); DWORD wpathlen = GetLongPathNameProc(nativePath, (TCHAR *) wpath, MAX_PATH); /* * We have to make the drive letter uppercase. */ if (wpath[0] >= L'a') { wpath[0] -= (L'a' - L'A'); } Tcl_DStringAppend(&dsNorm, (const char *) wpath, wpathlen * sizeof(WCHAR)); Tcl_DStringFree(&ds); } #endif /* TclNORM_LONG_PATH */ } /* * Common code path for all Windows platforms. */ nextCheckpoint = currentPathEndPosition - path; if (lastValidPathEnd != NULL) { /* * Concatenate the normalized string in dsNorm with the tail of the * path which we didn't recognise. The string in dsNorm is in the * native encoding, so we have to convert it to Utf. */ Tcl_WinTCharToUtf((const TCHAR *) Tcl_DStringValue(&dsNorm), Tcl_DStringLength(&dsNorm), &ds); nextCheckpoint = Tcl_DStringLength(&ds); if (*lastValidPathEnd != 0) { /* * Not the end of the string. */ int len; char *path; Tcl_Obj *tmpPathPtr; tmpPathPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), nextCheckpoint); Tcl_AppendToObj(tmpPathPtr, lastValidPathEnd, -1); path = Tcl_GetStringFromObj(tmpPathPtr, &len); Tcl_SetStringObj(pathPtr, path, len); Tcl_DecrRefCount(tmpPathPtr); } else { /* * End of string was reached above. */ Tcl_SetStringObj(pathPtr, Tcl_DStringValue(&ds), nextCheckpoint); } Tcl_DStringFree(&ds); } Tcl_DStringFree(&dsNorm); /* * This must be done after we are totally finished with 'path' as we are * sharing the same underlying string. */ if (temp != NULL) { Tcl_DecrRefCount(temp); } return nextCheckpoint; } /* *--------------------------------------------------------------------------- * * TclWinVolumeRelativeNormalize -- * * Only Windows has volume-relative paths. These paths are rather rare, * but it is nice if Tcl can handle them. It is much better if we can * handle them here, rather than in the native fs code, because we really * need to have a real absolute path just below. * * We do not let this block compile on non-Windows platforms because the * test suite's manual forcing of tclPlatform can otherwise cause this * code path to be executed, causing various errors because * volume-relative paths really do not exist. * * Results: * A valid normalized path. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj * TclWinVolumeRelativeNormalize( Tcl_Interp *interp, const char *path, Tcl_Obj **useThisCwdPtr) { Tcl_Obj *absolutePath, *useThisCwd; useThisCwd = Tcl_FSGetCwd(interp); if (useThisCwd == NULL) { return NULL; } if (path[0] == '/') { /* * Path of form /foo/bar which is a path in the root directory of the * current volume. */ const char *drive = Tcl_GetString(useThisCwd); absolutePath = Tcl_NewStringObj(drive,2); Tcl_AppendToObj(absolutePath, path, -1); Tcl_IncrRefCount(absolutePath); /* * We have a refCount on the cwd. */ } else { /* * Path of form C:foo/bar, but this only makes sense if the cwd is * also on drive C. */ int cwdLen; const char *drive = Tcl_GetStringFromObj(useThisCwd, &cwdLen); char drive_cur = path[0]; if (drive_cur >= 'a') { drive_cur -= ('a' - 'A'); } if (drive[0] == drive_cur) { absolutePath = Tcl_DuplicateObj(useThisCwd); /* * We have a refCount on the cwd, which we will release later. */ if (drive[cwdLen-1] != '/' && (path[2] != '\0')) { /* * Only add a trailing '/' if needed, which is if there isn't * one already, and if we are going to be adding some more * characters. */ Tcl_AppendToObj(absolutePath, "/", 1); } } else { Tcl_DecrRefCount(useThisCwd); useThisCwd = NULL; /* * The path is not in the current drive, but is volume-relative. * The way Tcl 8.3 handles this is that it treats such a path as * relative to the root of the drive. We therefore behave the same * here. This behaviour is, however, different to that of the * windows command-line. If we want to fix this at some point in * the future (at the expense of a behaviour change to Tcl), we * could use the '_dgetdcwd' Win32 API to get the drive's cwd. */ absolutePath = Tcl_NewStringObj(path, 2); Tcl_AppendToObj(absolutePath, "/", 1); } Tcl_IncrRefCount(absolutePath); Tcl_AppendToObj(absolutePath, path+2, -1); } *useThisCwdPtr = useThisCwd; return absolutePath; } /* *--------------------------------------------------------------------------- * * TclpNativeToNormalized -- * * Convert native format to a normalized path object, with refCount of * zero. * * Currently assumes all native paths are actually normalized already, so * if the path given is not normalized this will actually just convert to * a valid string path, but not necessarily a normalized one. * * Results: * A valid normalized path. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj * TclpNativeToNormalized( ClientData clientData) { Tcl_DString ds; Tcl_Obj *objPtr; int len; char *copy, *p; Tcl_WinTCharToUtf((const TCHAR *) clientData, -1, &ds); copy = Tcl_DStringValue(&ds); len = Tcl_DStringLength(&ds); /* * Certain native path representations on Windows have this special prefix * to indicate that they are to be treated specially. For example * extremely long paths, or symlinks. */ if (*copy == '\\') { if (0 == strncmp(copy,"\\??\\",4)) { copy += 4; len -= 4; } else if (0 == strncmp(copy,"\\\\?\\",4)) { copy += 4; len -= 4; } } /* * Ensure we are using forward slashes only. */ for (p = copy; *p != '\0'; p++) { if (*p == '\\') { *p = '/'; } } objPtr = Tcl_NewStringObj(copy,len); Tcl_DStringFree(&ds); return objPtr; } /* *--------------------------------------------------------------------------- * * TclNativeCreateNativeRep -- * * Create a native representation for the given path. * * Results: * The nativePath representation. * * Side effects: * Memory will be allocated. The path may need to be normalized. * *--------------------------------------------------------------------------- */ ClientData TclNativeCreateNativeRep( Tcl_Obj *pathPtr) { WCHAR *nativePathPtr = NULL; const char *str; Tcl_Obj *validPathPtr; size_t len; WCHAR *wp; if (TclFSCwdIsNative()) { /* * The cwd is native, which means we can use the translated path * without worrying about normalization (this will also usually be * shorter so the utf-to-external conversion will be somewhat faster). */ validPathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr); if (validPathPtr == NULL) { return NULL; } /* refCount of validPathPtr was already incremented in Tcl_FSGetTranslatedPath */ } else { /* * Make sure the normalized path is set. */ validPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (validPathPtr == NULL) { return NULL; } /* validPathPtr returned from Tcl_FSGetNormalizedPath is owned by Tcl, so incr refCount here */ Tcl_IncrRefCount(validPathPtr); } str = Tcl_GetString(validPathPtr); len = validPathPtr->length; if (strlen(str)!=(unsigned int)len) { /* String contains NUL-bytes. This is invalid. */ goto done; } /* For a reserved device, strip a possible postfix ':' */ len = WinIsReserved(str); if (len == 0) { /* Let MultiByteToWideChar check for other invalid sequences, like * 0xC0 0x80 (== overlong NUL). See bug [3118489]: NUL in filenames */ len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, 0, 0); if (len==0) { goto done; } } /* Overallocate 6 chars, making some room for extended paths */ wp = nativePathPtr = ckalloc( (len+6) * sizeof(WCHAR) ); if (nativePathPtr==0) { goto done; } MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, nativePathPtr, len+1); /* ** If path starts with "//?/" or "\\?\" (extended path), translate ** any slashes to backslashes but leave the '?' intact */ if ((str[0]=='\\' || str[0]=='/') && (str[1]=='\\' || str[1]=='/') && str[2]=='?' && (str[3]=='\\' || str[3]=='/')) { wp[0] = wp[1] = wp[3] = '\\'; str += 4; wp += 4; } /* ** If there is no "\\?\" prefix but there is a drive or UNC ** path prefix and the path is larger than MAX_PATH chars, ** no Win32 API function can handle that unless it is ** prefixed with the extended path prefix. See: ** **/ if (((str[0]>='A'&&str[0]<='Z') || (str[0]>='a'&&str[0]<='z')) && str[1]==':') { if (wp==nativePathPtr && len>MAX_PATH && (str[2]=='\\' || str[2]=='/')) { memmove(wp+4, wp, len*sizeof(WCHAR)); memcpy(wp, L"\\\\?\\", 4*sizeof(WCHAR)); wp += 4; } /* ** If (remainder of) path starts with ":", ** leave the ':' intact. */ wp += 2; } else if (wp==nativePathPtr && len>MAX_PATH && (str[0]=='\\' || str[0]=='/') && (str[1]=='\\' || str[1]=='/') && str[2]!='?') { memmove(wp+6, wp, len*sizeof(WCHAR)); memcpy(wp, L"\\\\?\\UNC", 7*sizeof(WCHAR)); wp += 7; } /* ** In the remainder of the path, translate invalid characters to ** characters in the Unicode private use area. */ while (*wp != '\0') { if ((*wp < ' ') || wcschr(L"\"*:<>?|", *wp)) { *wp |= 0xF000; } else if (*wp == '/') { *wp = '\\'; } ++wp; } done: TclDecrRefCount(validPathPtr); return nativePathPtr; } /* *--------------------------------------------------------------------------- * * TclNativeDupInternalRep -- * * Duplicate the native representation. * * Results: * The copied native representation, or NULL if it is not possible to * copy the representation. * * Side effects: * Memory allocation for the copy. * *--------------------------------------------------------------------------- */ ClientData TclNativeDupInternalRep( ClientData clientData) { char *copy; size_t len; if (clientData == NULL) { return NULL; } len = sizeof(TCHAR) * (_tcslen((const TCHAR *) clientData) + 1); copy = ckalloc(len); memcpy(copy, clientData, len); return copy; } /* *--------------------------------------------------------------------------- * * TclpUtime -- * * Set the modification date for a file. * * Results: * 0 on success, -1 on error. * * Side effects: * Sets errno to a representation of any Windows problem that's observed * in the process. * *--------------------------------------------------------------------------- */ int TclpUtime( Tcl_Obj *pathPtr, /* File to modify */ struct utimbuf *tval) /* New modification date structure */ { int res = 0; HANDLE fileHandle; const TCHAR *native; DWORD attr = 0; DWORD flags = FILE_ATTRIBUTE_NORMAL; FILETIME lastAccessTime, lastModTime; FromCTime(tval->actime, &lastAccessTime); FromCTime(tval->modtime, &lastModTime); native = Tcl_FSGetNativePath(pathPtr); attr = GetFileAttributes(native); if (attr != INVALID_FILE_ATTRIBUTES && attr & FILE_ATTRIBUTE_DIRECTORY) { flags = FILE_FLAG_BACKUP_SEMANTICS; } /* * We use the native APIs (not 'utime') because there are some daylight * savings complications that utime gets wrong. */ fileHandle = CreateFile(native, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, flags, NULL); if (fileHandle == INVALID_HANDLE_VALUE || !SetFileTime(fileHandle, NULL, &lastAccessTime, &lastModTime)) { TclWinConvertError(GetLastError()); res = -1; } if (fileHandle != INVALID_HANDLE_VALUE) { CloseHandle(fileHandle); } return res; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tclWinThrd.c0000644000175000017500000006312312663660066014620 0ustar sergeisergei/* * tclWinThread.c -- * * This file implements the Windows-specific thread operations. * * Copyright (c) 1998 by Sun Microsystems, Inc. * Copyright (c) 1999 by Scriptics Corporation * Copyright (c) 2008 by George Peter Staplin * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclWinInt.h" #include /* Workaround for mingw versions which don't provide this in float.h */ #ifndef _MCW_EM # define _MCW_EM 0x0008001F /* Error masks */ # define _MCW_RC 0x00000300 /* Rounding */ # define _MCW_PC 0x00030000 /* Precision */ _CRTIMP unsigned int __cdecl _controlfp (unsigned int unNew, unsigned int unMask); #endif /* * This is the master lock used to serialize access to other serialization * data structures. */ static CRITICAL_SECTION masterLock; static int init = 0; #define MASTER_LOCK TclpMasterLock() #define MASTER_UNLOCK TclpMasterUnlock() /* * This is the master lock used to serialize initialization and finalization * of Tcl as a whole. */ static CRITICAL_SECTION initLock; /* * allocLock is used by Tcl's version of malloc for synchronization. For * obvious reasons, cannot use any dyamically allocated storage. */ #ifdef TCL_THREADS static struct Tcl_Mutex_ { CRITICAL_SECTION crit; } allocLock; static Tcl_Mutex allocLockPtr = &allocLock; static int allocOnce = 0; #endif /* TCL_THREADS */ /* * The joinLock serializes Create- and ExitThread. This is necessary to * prevent a race where a new joinable thread exits before the creating thread * had the time to create the necessary data structures in the emulation * layer. */ static CRITICAL_SECTION joinLock; /* * Condition variables are implemented with a combination of a per-thread * Windows Event and a per-condition waiting queue. The idea is that each * thread has its own Event that it waits on when it is doing a ConditionWait; * it uses the same event for all condition variables because it only waits on * one at a time. Each condition variable has a queue of waiting threads, and * a mutex used to serialize access to this queue. * * Special thanks to David Nichols and Jim Davidson for advice on the * Condition Variable implementation. */ /* * The per-thread event and queue pointers. */ #ifdef TCL_THREADS typedef struct ThreadSpecificData { HANDLE condEvent; /* Per-thread condition event */ struct ThreadSpecificData *nextPtr; /* Queue pointers */ struct ThreadSpecificData *prevPtr; int flags; /* See flags below */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; #endif /* TCL_THREADS */ /* * State bits for the thread. * WIN_THREAD_UNINIT Uninitialized. Must be zero because of the way * ThreadSpecificData is created. * WIN_THREAD_RUNNING Running, not waiting. * WIN_THREAD_BLOCKED Waiting, or trying to wait. */ #define WIN_THREAD_UNINIT 0x0 #define WIN_THREAD_RUNNING 0x1 #define WIN_THREAD_BLOCKED 0x2 /* * The per condition queue pointers and the Mutex used to serialize access to * the queue. */ typedef struct WinCondition { CRITICAL_SECTION condLock; /* Lock to serialize queuing on the * condition. */ struct ThreadSpecificData *firstPtr; /* Queue pointers */ struct ThreadSpecificData *lastPtr; } WinCondition; /* * Additions by AOL for specialized thread memory allocator. */ #ifdef USE_THREAD_ALLOC static int once; static DWORD tlsKey; typedef struct allocMutex { Tcl_Mutex tlock; CRITICAL_SECTION wlock; } allocMutex; #endif /* USE_THREAD_ALLOC */ /* * The per thread data passed from TclpThreadCreate * to TclWinThreadStart. */ typedef struct WinThread { LPTHREAD_START_ROUTINE lpStartAddress; /* Original startup routine */ LPVOID lpParameter; /* Original startup data */ unsigned int fpControl; /* Floating point control word from the * main thread */ } WinThread; /* *---------------------------------------------------------------------- * * TclWinThreadStart -- * * This procedure is the entry point for all new threads created * by Tcl on Windows. * * Results: * Various, depending on the result of the wrapped thread start * routine. * * Side effects: * Arbitrary, since user code is executed. * *---------------------------------------------------------------------- */ static DWORD WINAPI TclWinThreadStart( LPVOID lpParameter) /* The WinThread structure pointer passed * from TclpThreadCreate */ { WinThread *winThreadPtr = (WinThread *) lpParameter; unsigned int fpmask; LPTHREAD_START_ROUTINE lpOrigStartAddress; LPVOID lpOrigParameter; if (!winThreadPtr) { return TCL_ERROR; } fpmask = _MCW_EM | _MCW_RC | _MCW_PC; #if defined(_MSC_VER) && _MSC_VER >= 1200 fpmask |= _MCW_DN; #endif _controlfp(winThreadPtr->fpControl, fpmask); lpOrigStartAddress = winThreadPtr->lpStartAddress; lpOrigParameter = winThreadPtr->lpParameter; ckfree((char *)winThreadPtr); return lpOrigStartAddress(lpOrigParameter); } /* *---------------------------------------------------------------------- * * TclpThreadCreate -- * * This procedure creates a new thread. * * Results: * TCL_OK if the thread could be created. The thread ID is returned in a * parameter. * * Side effects: * A new thread is created. * *---------------------------------------------------------------------- */ int TclpThreadCreate( Tcl_ThreadId *idPtr, /* Return, the ID of the thread. */ Tcl_ThreadCreateProc *proc, /* Main() function of the thread. */ ClientData clientData, /* The one argument to Main(). */ int stackSize, /* Size of stack for the new thread. */ int flags) /* Flags controlling behaviour of the new * thread. */ { WinThread *winThreadPtr; /* Per-thread startup info */ HANDLE tHandle; winThreadPtr = (WinThread *)ckalloc(sizeof(WinThread)); winThreadPtr->lpStartAddress = (LPTHREAD_START_ROUTINE) proc; winThreadPtr->lpParameter = clientData; winThreadPtr->fpControl = _controlfp(0, 0); EnterCriticalSection(&joinLock); *idPtr = 0; /* must initialize as Tcl_Thread is a pointer and * on WIN64 sizeof void* != sizeof unsigned */ #if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__) tHandle = (HANDLE) _beginthreadex(NULL, (unsigned) stackSize, (Tcl_ThreadCreateProc*) TclWinThreadStart, winThreadPtr, 0, (unsigned *)idPtr); #else tHandle = CreateThread(NULL, (DWORD) stackSize, TclWinThreadStart, winThreadPtr, 0, (LPDWORD)idPtr); #endif if (tHandle == NULL) { LeaveCriticalSection(&joinLock); return TCL_ERROR; } else { if (flags & TCL_THREAD_JOINABLE) { TclRememberJoinableThread(*idPtr); } /* * The only purpose of this is to decrement the reference count so the * OS resources will be reaquired when the thread closes. */ CloseHandle(tHandle); LeaveCriticalSection(&joinLock); return TCL_OK; } } /* *---------------------------------------------------------------------- * * Tcl_JoinThread -- * * This procedure waits upon the exit of the specified thread. * * Results: * TCL_OK if the wait was successful, TCL_ERROR else. * * Side effects: * The result area is set to the exit code of the thread we * waited upon. * *---------------------------------------------------------------------- */ int Tcl_JoinThread( Tcl_ThreadId threadId, /* Id of the thread to wait upon */ int *result) /* Reference to the storage the result of the * thread we wait upon will be written into. */ { return TclJoinThread(threadId, result); } /* *---------------------------------------------------------------------- * * TclpThreadExit -- * * This procedure terminates the current thread. * * Results: * None. * * Side effects: * This procedure terminates the current thread. * *---------------------------------------------------------------------- */ void TclpThreadExit( int status) { EnterCriticalSection(&joinLock); TclSignalExitThread(Tcl_GetCurrentThread(), status); LeaveCriticalSection(&joinLock); #if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__) _endthreadex((unsigned) status); #else ExitThread((DWORD) status); #endif } /* *---------------------------------------------------------------------- * * Tcl_GetCurrentThread -- * * This procedure returns the ID of the currently running thread. * * Results: * A thread ID. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_ThreadId Tcl_GetCurrentThread(void) { return (Tcl_ThreadId)(size_t)GetCurrentThreadId(); } /* *---------------------------------------------------------------------- * * TclpInitLock * * This procedure is used to grab a lock that serializes initialization * and finalization of Tcl. On some platforms this may also initialize * the mutex used to serialize creation of more mutexes and thread local * storage keys. * * Results: * None. * * Side effects: * Acquire the initialization mutex. * *---------------------------------------------------------------------- */ void TclpInitLock(void) { if (!init) { /* * There is a fundamental race here that is solved by creating the * first Tcl interpreter in a single threaded environment. Once the * interpreter has been created, it is safe to create more threads * that create interpreters in parallel. */ init = 1; InitializeCriticalSection(&joinLock); InitializeCriticalSection(&initLock); InitializeCriticalSection(&masterLock); } EnterCriticalSection(&initLock); } /* *---------------------------------------------------------------------- * * TclpInitUnlock * * This procedure is used to release a lock that serializes * initialization and finalization of Tcl. * * Results: * None. * * Side effects: * Release the initialization mutex. * *---------------------------------------------------------------------- */ void TclpInitUnlock(void) { LeaveCriticalSection(&initLock); } /* *---------------------------------------------------------------------- * * TclpMasterLock * * This procedure is used to grab a lock that serializes creation of * mutexes, condition variables, and thread local storage keys. * * This lock must be different than the initLock because the initLock is * held during creation of syncronization objects. * * Results: * None. * * Side effects: * Acquire the master mutex. * *---------------------------------------------------------------------- */ void TclpMasterLock(void) { if (!init) { /* * There is a fundamental race here that is solved by creating the * first Tcl interpreter in a single threaded environment. Once the * interpreter has been created, it is safe to create more threads * that create interpreters in parallel. */ init = 1; InitializeCriticalSection(&joinLock); InitializeCriticalSection(&initLock); InitializeCriticalSection(&masterLock); } EnterCriticalSection(&masterLock); } /* *---------------------------------------------------------------------- * * TclpMasterUnlock * * This procedure is used to release a lock that serializes creation and * deletion of synchronization objects. * * Results: * None. * * Side effects: * Release the master mutex. * *---------------------------------------------------------------------- */ void TclpMasterUnlock(void) { LeaveCriticalSection(&masterLock); } /* *---------------------------------------------------------------------- * * Tcl_GetAllocMutex * * This procedure returns a pointer to a statically initialized mutex for * use by the memory allocator. The alloctor must use this lock, because * all other locks are allocated... * * Results: * A pointer to a mutex that is suitable for passing to Tcl_MutexLock and * Tcl_MutexUnlock. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Mutex * Tcl_GetAllocMutex(void) { #ifdef TCL_THREADS if (!allocOnce) { InitializeCriticalSection(&allocLock.crit); allocOnce = 1; } return &allocLockPtr; #else return NULL; #endif } /* *---------------------------------------------------------------------- * * TclpFinalizeLock * * This procedure is used to destroy all private resources used in this * file. * * Results: * None. * * Side effects: * Destroys everything private. TclpInitLock must be held entering this * function. * *---------------------------------------------------------------------- */ void TclFinalizeLock(void) { MASTER_LOCK; DeleteCriticalSection(&joinLock); /* * Destroy the critical section that we are holding! */ DeleteCriticalSection(&masterLock); init = 0; #ifdef TCL_THREADS if (allocOnce) { DeleteCriticalSection(&allocLock.crit); allocOnce = 0; } #endif LeaveCriticalSection(&initLock); /* * Destroy the critical section that we were holding. */ DeleteCriticalSection(&initLock); } #ifdef TCL_THREADS /* locally used prototype */ static void FinalizeConditionEvent(ClientData data); /* *---------------------------------------------------------------------- * * Tcl_MutexLock -- * * This procedure is invoked to lock a mutex. This is a self initializing * mutex that is automatically finalized during Tcl_Finalize. * * Results: * None. * * Side effects: * May block the current thread. The mutex is aquired when this returns. * *---------------------------------------------------------------------- */ void Tcl_MutexLock( Tcl_Mutex *mutexPtr) /* The lock */ { CRITICAL_SECTION *csPtr; if (*mutexPtr == NULL) { MASTER_LOCK; /* * Double inside master lock check to avoid a race. */ if (*mutexPtr == NULL) { csPtr = ckalloc(sizeof(CRITICAL_SECTION)); InitializeCriticalSection(csPtr); *mutexPtr = (Tcl_Mutex)csPtr; TclRememberMutex(mutexPtr); } MASTER_UNLOCK; } csPtr = *((CRITICAL_SECTION **)mutexPtr); EnterCriticalSection(csPtr); } /* *---------------------------------------------------------------------- * * Tcl_MutexUnlock -- * * This procedure is invoked to unlock a mutex. * * Results: * None. * * Side effects: * The mutex is released when this returns. * *---------------------------------------------------------------------- */ void Tcl_MutexUnlock( Tcl_Mutex *mutexPtr) /* The lock */ { CRITICAL_SECTION *csPtr = *((CRITICAL_SECTION **)mutexPtr); LeaveCriticalSection(csPtr); } /* *---------------------------------------------------------------------- * * TclpFinalizeMutex -- * * This procedure is invoked to clean up one mutex. This is only safe to * call at the end of time. * * Results: * None. * * Side effects: * The mutex list is deallocated. * *---------------------------------------------------------------------- */ void TclpFinalizeMutex( Tcl_Mutex *mutexPtr) { CRITICAL_SECTION *csPtr = *(CRITICAL_SECTION **)mutexPtr; if (csPtr != NULL) { DeleteCriticalSection(csPtr); ckfree(csPtr); *mutexPtr = NULL; } } /* *---------------------------------------------------------------------- * * Tcl_ConditionWait -- * * This procedure is invoked to wait on a condition variable. The mutex * is atomically released as part of the wait, and automatically grabbed * when the condition is signaled. * * The mutex must be held when this procedure is called. * * Results: * None. * * Side effects: * May block the current thread. The mutex is aquired when this returns. * Will allocate memory for a HANDLE and initialize this the first time * this Tcl_Condition is used. * *---------------------------------------------------------------------- */ void Tcl_ConditionWait( Tcl_Condition *condPtr, /* Really (WinCondition **) */ Tcl_Mutex *mutexPtr, /* Really (CRITICAL_SECTION **) */ const Tcl_Time *timePtr) /* Timeout on waiting period */ { WinCondition *winCondPtr; /* Per-condition queue head */ CRITICAL_SECTION *csPtr; /* Caller's Mutex, after casting */ DWORD wtime; /* Windows time value */ int timeout; /* True if we got a timeout */ int doExit = 0; /* True if we need to do exit setup */ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Self initialize the two parts of the condition. The per-condition and * per-thread parts need to be handled independently. */ if (tsdPtr->flags == WIN_THREAD_UNINIT) { MASTER_LOCK; /* * Create the per-thread event and queue pointers. */ if (tsdPtr->flags == WIN_THREAD_UNINIT) { tsdPtr->condEvent = CreateEvent(NULL, TRUE /* manual reset */, FALSE /* non signaled */, NULL); tsdPtr->nextPtr = NULL; tsdPtr->prevPtr = NULL; tsdPtr->flags = WIN_THREAD_RUNNING; doExit = 1; } MASTER_UNLOCK; if (doExit) { /* * Create a per-thread exit handler to clean up the condEvent. We * must be careful to do this outside the Master Lock because * Tcl_CreateThreadExitHandler uses its own ThreadSpecificData, * and initializing that may drop back into the Master Lock. */ Tcl_CreateThreadExitHandler(FinalizeConditionEvent, tsdPtr); } } if (*condPtr == NULL) { MASTER_LOCK; /* * Initialize the per-condition queue pointers and Mutex. */ if (*condPtr == NULL) { winCondPtr = ckalloc(sizeof(WinCondition)); InitializeCriticalSection(&winCondPtr->condLock); winCondPtr->firstPtr = NULL; winCondPtr->lastPtr = NULL; *condPtr = (Tcl_Condition) winCondPtr; TclRememberCondition(condPtr); } MASTER_UNLOCK; } csPtr = *((CRITICAL_SECTION **)mutexPtr); winCondPtr = *((WinCondition **)condPtr); if (timePtr == NULL) { wtime = INFINITE; } else { wtime = timePtr->sec * 1000 + timePtr->usec / 1000; } /* * Queue the thread on the condition, using the per-condition lock for * serialization. */ tsdPtr->flags = WIN_THREAD_BLOCKED; tsdPtr->nextPtr = NULL; EnterCriticalSection(&winCondPtr->condLock); tsdPtr->prevPtr = winCondPtr->lastPtr; /* A: */ winCondPtr->lastPtr = tsdPtr; if (tsdPtr->prevPtr != NULL) { tsdPtr->prevPtr->nextPtr = tsdPtr; } if (winCondPtr->firstPtr == NULL) { winCondPtr->firstPtr = tsdPtr; } /* * Unlock the caller's mutex and wait for the condition, or a timeout. * There is a minor issue here in that we don't count down the timeout if * we get notified, but another thread grabs the condition before we do. * In that race condition we'll wait again for the full timeout. Timed * waits are dubious anyway. Either you have the locking protocol wrong * and are masking a deadlock, or you are using conditions to pause your * thread. */ LeaveCriticalSection(csPtr); timeout = 0; while (!timeout && (tsdPtr->flags & WIN_THREAD_BLOCKED)) { ResetEvent(tsdPtr->condEvent); LeaveCriticalSection(&winCondPtr->condLock); if (WaitForSingleObjectEx(tsdPtr->condEvent, wtime, TRUE) == WAIT_TIMEOUT) { timeout = 1; } EnterCriticalSection(&winCondPtr->condLock); } /* * Be careful on timeouts because the signal might arrive right around the * time limit and someone else could have taken us off the queue. */ if (timeout) { if (tsdPtr->flags & WIN_THREAD_RUNNING) { timeout = 0; } else { /* * When dequeuing, we can leave the tsdPtr->nextPtr and * tsdPtr->prevPtr with dangling pointers because they are * reinitialilzed w/out reading them when the thread is enqueued * later. */ if (winCondPtr->firstPtr == tsdPtr) { winCondPtr->firstPtr = tsdPtr->nextPtr; } else { tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr; } if (winCondPtr->lastPtr == tsdPtr) { winCondPtr->lastPtr = tsdPtr->prevPtr; } else { tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr; } tsdPtr->flags = WIN_THREAD_RUNNING; } } LeaveCriticalSection(&winCondPtr->condLock); EnterCriticalSection(csPtr); } /* *---------------------------------------------------------------------- * * Tcl_ConditionNotify -- * * This procedure is invoked to signal a condition variable. * * The mutex must be held during this call to avoid races, but this * interface does not enforce that. * * Results: * None. * * Side effects: * May unblock another thread. * *---------------------------------------------------------------------- */ void Tcl_ConditionNotify( Tcl_Condition *condPtr) { WinCondition *winCondPtr; ThreadSpecificData *tsdPtr; if (*condPtr != NULL) { winCondPtr = *((WinCondition **)condPtr); if (winCondPtr == NULL) { return; } /* * Loop through all the threads waiting on the condition and notify * them (i.e., broadcast semantics). The queue manipulation is guarded * by the per-condition coordinating mutex. */ EnterCriticalSection(&winCondPtr->condLock); while (winCondPtr->firstPtr != NULL) { tsdPtr = winCondPtr->firstPtr; winCondPtr->firstPtr = tsdPtr->nextPtr; if (winCondPtr->lastPtr == tsdPtr) { winCondPtr->lastPtr = NULL; } tsdPtr->flags = WIN_THREAD_RUNNING; tsdPtr->nextPtr = NULL; tsdPtr->prevPtr = NULL; /* Not strictly necessary, see A: */ SetEvent(tsdPtr->condEvent); } LeaveCriticalSection(&winCondPtr->condLock); } else { /* * No-one has used the condition variable, so there are no waiters. */ } } /* *---------------------------------------------------------------------- * * FinalizeConditionEvent -- * * This procedure is invoked to clean up the per-thread event used to * implement condition waiting. This is only safe to call at the end of * time. * * Results: * None. * * Side effects: * The per-thread event is closed. * *---------------------------------------------------------------------- */ static void FinalizeConditionEvent( ClientData data) { ThreadSpecificData *tsdPtr = (ThreadSpecificData *) data; tsdPtr->flags = WIN_THREAD_UNINIT; CloseHandle(tsdPtr->condEvent); } /* *---------------------------------------------------------------------- * * TclpFinalizeCondition -- * * This procedure is invoked to clean up a condition variable. This is * only safe to call at the end of time. * * This assumes the Master Lock is held. * * Results: * None. * * Side effects: * The condition variable is deallocated. * *---------------------------------------------------------------------- */ void TclpFinalizeCondition( Tcl_Condition *condPtr) { WinCondition *winCondPtr = *(WinCondition **)condPtr; /* * Note - this is called long after the thread-local storage is reclaimed. * The per-thread condition waiting event is reclaimed earlier in a * per-thread exit handler, which is called before thread local storage is * reclaimed. */ if (winCondPtr != NULL) { DeleteCriticalSection(&winCondPtr->condLock); ckfree(winCondPtr); *condPtr = NULL; } } /* * Additions by AOL for specialized thread memory allocator. */ #ifdef USE_THREAD_ALLOC Tcl_Mutex * TclpNewAllocMutex(void) { struct allocMutex *lockPtr; lockPtr = malloc(sizeof(struct allocMutex)); if (lockPtr == NULL) { Tcl_Panic("could not allocate lock"); } lockPtr->tlock = (Tcl_Mutex) &lockPtr->wlock; InitializeCriticalSection(&lockPtr->wlock); return &lockPtr->tlock; } void TclpFreeAllocMutex( Tcl_Mutex *mutex) /* The alloc mutex to free. */ { allocMutex *lockPtr = (allocMutex *) mutex; if (!lockPtr) { return; } DeleteCriticalSection(&lockPtr->wlock); free(lockPtr); } void * TclpGetAllocCache(void) { void *result; if (!once) { /* * We need to make sure that TclpFreeAllocCache is called on each * thread that calls this, but only on threads that call this. */ tlsKey = TlsAlloc(); once = 1; if (tlsKey == TLS_OUT_OF_INDEXES) { Tcl_Panic("could not allocate thread local storage"); } } result = TlsGetValue(tlsKey); if ((result == NULL) && (GetLastError() != NO_ERROR)) { Tcl_Panic("TlsGetValue failed from TclpGetAllocCache"); } return result; } void TclpSetAllocCache( void *ptr) { BOOL success; success = TlsSetValue(tlsKey, ptr); if (!success) { Tcl_Panic("TlsSetValue failed from TclpSetAllocCache"); } } void TclpFreeAllocCache( void *ptr) { BOOL success; if (ptr != NULL) { /* * Called by us in TclpFinalizeThreadData when a thread exits and * destroys the tsd key which stores allocator caches. */ TclFreeAllocCache(ptr); success = TlsSetValue(tlsKey, NULL); if (!success) { Tcl_Panic("TlsSetValue failed from TclpFreeAllocCache"); } } else if (once) { /* * Called by us in TclFinalizeThreadAlloc() during the library * finalization initiated from Tcl_Finalize() */ success = TlsFree(tlsKey); if (!success) { Tcl_Panic("TlsFree failed from TclpFreeAllocCache"); } once = 0; /* reset for next time. */ } } #endif /* USE_THREAD_ALLOC */ void * TclpThreadCreateKey(void) { DWORD *key; key = TclpSysAlloc(sizeof *key, 0); if (key == NULL) { Tcl_Panic("unable to allocate thread key!"); } *key = TlsAlloc(); if (*key == TLS_OUT_OF_INDEXES) { Tcl_Panic("unable to allocate thread-local storage"); } return key; } void TclpThreadDeleteKey( void *keyPtr) { DWORD *key = keyPtr; if (!TlsFree(*key)) { Tcl_Panic("unable to delete key"); } TclpSysFree(keyPtr); } void TclpThreadSetMasterTSD( void *tsdKeyPtr, void *ptr) { DWORD *key = tsdKeyPtr; if (!TlsSetValue(*key, ptr)) { Tcl_Panic("unable to set master TSD value"); } } void * TclpThreadGetMasterTSD( void *tsdKeyPtr) { DWORD *key = tsdKeyPtr; return TlsGetValue(*key); } #endif /* TCL_THREADS */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tclWinInit.c0000644000175000017500000004422712663660066014626 0ustar sergeisergei/* * tclWinInit.c -- * * Contains the Windows-specific interpreter initialization functions. * * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclWinInt.h" #include #include #include /* * GetUserName() is found in advapi32.dll */ #ifdef _MSC_VER # pragma comment(lib, "advapi32.lib") #endif /* * The following declaration is a workaround for some Microsoft brain damage. * The SYSTEM_INFO structure is different in various releases, even though the * layout is the same. So we overlay our own structure on top of it so we can * access the interesting slots in a uniform way. */ typedef struct { WORD wProcessorArchitecture; WORD wReserved; } OemId; /* * The following macros are missing from some versions of winnt.h. */ #ifndef PROCESSOR_ARCHITECTURE_INTEL #define PROCESSOR_ARCHITECTURE_INTEL 0 #endif #ifndef PROCESSOR_ARCHITECTURE_MIPS #define PROCESSOR_ARCHITECTURE_MIPS 1 #endif #ifndef PROCESSOR_ARCHITECTURE_ALPHA #define PROCESSOR_ARCHITECTURE_ALPHA 2 #endif #ifndef PROCESSOR_ARCHITECTURE_PPC #define PROCESSOR_ARCHITECTURE_PPC 3 #endif #ifndef PROCESSOR_ARCHITECTURE_SHX #define PROCESSOR_ARCHITECTURE_SHX 4 #endif #ifndef PROCESSOR_ARCHITECTURE_ARM #define PROCESSOR_ARCHITECTURE_ARM 5 #endif #ifndef PROCESSOR_ARCHITECTURE_IA64 #define PROCESSOR_ARCHITECTURE_IA64 6 #endif #ifndef PROCESSOR_ARCHITECTURE_ALPHA64 #define PROCESSOR_ARCHITECTURE_ALPHA64 7 #endif #ifndef PROCESSOR_ARCHITECTURE_MSIL #define PROCESSOR_ARCHITECTURE_MSIL 8 #endif #ifndef PROCESSOR_ARCHITECTURE_AMD64 #define PROCESSOR_ARCHITECTURE_AMD64 9 #endif #ifndef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 #define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10 #endif #ifndef PROCESSOR_ARCHITECTURE_UNKNOWN #define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF #endif /* * The following arrays contain the human readable strings for the Windows * platform and processor values. */ #define NUMPLATFORMS 4 static const char *const platforms[NUMPLATFORMS] = { "Win32s", "Windows 95", "Windows NT", "Windows CE" }; #define NUMPROCESSORS 11 static const char *const processors[NUMPROCESSORS] = { "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil", "amd64", "ia32_on_win64" }; /* * The default directory in which the init.tcl file is expected to be found. */ static TclInitProcessGlobalValueProc InitializeDefaultLibraryDir; static ProcessGlobalValue defaultLibraryDir = {0, 0, NULL, NULL, InitializeDefaultLibraryDir, NULL, NULL}; static TclInitProcessGlobalValueProc InitializeSourceLibraryDir; static ProcessGlobalValue sourceLibraryDir = {0, 0, NULL, NULL, InitializeSourceLibraryDir, NULL, NULL}; static void AppendEnvironment(Tcl_Obj *listPtr, const char *lib); static int ToUtf(const WCHAR *wSrc, char *dst); /* *--------------------------------------------------------------------------- * * TclpInitPlatform -- * * Initialize all the platform-dependant things like signals, * floating-point error handling and sockets. * * Called at process initialization time. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */ void TclpInitPlatform(void) { WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2, 2); tclPlatform = TCL_PLATFORM_WINDOWS; /* * Initialize the winsock library. On Windows XP and higher this * can never fail. */ WSAStartup(wVersionRequested, &wsaData); #ifdef STATIC_BUILD /* * If we are in a statically linked executable, then we need to explicitly * initialize the Windows function tables here since DllMain() will not be * invoked. */ TclWinInit(GetModuleHandle(NULL)); #endif } /* *------------------------------------------------------------------------- * * TclpInitLibraryPath -- * * This is the fallback routine that sets the library path if the * application has not set one by the first time it is needed. * * Results: * None. * * Side effects: * Sets the library path to an initial value. * *------------------------------------------------------------------------- */ void TclpInitLibraryPath( char **valuePtr, int *lengthPtr, Tcl_Encoding *encodingPtr) { #define LIBRARY_SIZE 64 Tcl_Obj *pathPtr; char installLib[LIBRARY_SIZE]; const char *bytes; pathPtr = Tcl_NewObj(); /* * Initialize the substring used when locating the script library. The * installLib variable computes the script library path relative to the * installed DLL. */ sprintf(installLib, "lib/tcl%s", TCL_VERSION); /* * Look for the library relative to the TCL_LIBRARY env variable. If the * last dirname in the TCL_LIBRARY path does not match the last dirname in * the installLib variable, use the last dir name of installLib in * addition to the orginal TCL_LIBRARY path. */ AppendEnvironment(pathPtr, installLib); /* * Look for the library in its default location. */ Tcl_ListObjAppendElement(NULL, pathPtr, TclGetProcessGlobalValue(&defaultLibraryDir)); /* * Look for the library in its source checkout location. */ Tcl_ListObjAppendElement(NULL, pathPtr, TclGetProcessGlobalValue(&sourceLibraryDir)); *encodingPtr = NULL; bytes = Tcl_GetStringFromObj(pathPtr, lengthPtr); *valuePtr = ckalloc((*lengthPtr) + 1); memcpy(*valuePtr, bytes, (size_t)(*lengthPtr)+1); Tcl_DecrRefCount(pathPtr); } /* *--------------------------------------------------------------------------- * * AppendEnvironment -- * * Append the value of the TCL_LIBRARY environment variable onto the path * pointer. If the env variable points to another version of tcl (e.g. * "tcl7.6") also append the path to this version (e.g., * "tcl7.6/../tcl8.2") * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static void AppendEnvironment( Tcl_Obj *pathPtr, const char *lib) { int pathc; WCHAR wBuf[MAX_PATH]; char buf[MAX_PATH * TCL_UTF_MAX]; Tcl_Obj *objPtr; Tcl_DString ds; const char **pathv; char *shortlib; /* * The shortlib value needs to be the tail component of the lib path. For * example, "lib/tcl8.4" -> "tcl8.4" while "usr/share/tcl8.5" -> "tcl8.5". */ for (shortlib = (char *) &lib[strlen(lib)-1]; shortlib>lib ; shortlib--) { if (*shortlib == '/') { if ((unsigned)(shortlib - lib) == strlen(lib) - 1) { Tcl_Panic("last character in lib cannot be '/'"); } shortlib++; break; } } if (shortlib == lib) { Tcl_Panic("no '/' character found in lib"); } /* * The "L" preceeding the TCL_LIBRARY string is used to tell VC++ that * this is a unicode string. */ if (GetEnvironmentVariableW(L"TCL_LIBRARY", wBuf, MAX_PATH) == 0) { buf[0] = '\0'; GetEnvironmentVariableA("TCL_LIBRARY", buf, MAX_PATH); } else { ToUtf(wBuf, buf); } if (buf[0] != '\0') { objPtr = Tcl_NewStringObj(buf, -1); Tcl_ListObjAppendElement(NULL, pathPtr, objPtr); TclWinNoBackslash(buf); Tcl_SplitPath(buf, &pathc, &pathv); /* * The lstrcmpi() will work even if pathv[pathc-1] is random UTF-8 * chars because I know shortlib is ascii. */ if ((pathc > 0) && (lstrcmpiA(shortlib, pathv[pathc - 1]) != 0)) { /* * TCL_LIBRARY is set but refers to a different tcl installation * than the current version. Try fiddling with the specified * directory to make it refer to this installation by removing the * old "tclX.Y" and substituting the current version string. */ pathv[pathc - 1] = shortlib; Tcl_DStringInit(&ds); (void) Tcl_JoinPath(pathc, pathv, &ds); objPtr = TclDStringToObj(&ds); } else { objPtr = Tcl_NewStringObj(buf, -1); } Tcl_ListObjAppendElement(NULL, pathPtr, objPtr); ckfree(pathv); } } /* *--------------------------------------------------------------------------- * * InitializeDefaultLibraryDir -- * * Locate the Tcl script library default location relative to the * location of the Tcl DLL. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static void InitializeDefaultLibraryDir( char **valuePtr, int *lengthPtr, Tcl_Encoding *encodingPtr) { HMODULE hModule = TclWinGetTclInstance(); WCHAR wName[MAX_PATH + LIBRARY_SIZE]; char name[(MAX_PATH + LIBRARY_SIZE) * TCL_UTF_MAX]; char *end, *p; if (GetModuleFileNameW(hModule, wName, MAX_PATH) == 0) { GetModuleFileNameA(hModule, name, MAX_PATH); } else { ToUtf(wName, name); } end = strrchr(name, '\\'); *end = '\0'; p = strrchr(name, '\\'); if (p != NULL) { end = p; } *end = '\\'; TclWinNoBackslash(name); sprintf(end + 1, "lib/tcl%s", TCL_VERSION); *lengthPtr = strlen(name); *valuePtr = ckalloc(*lengthPtr + 1); *encodingPtr = NULL; memcpy(*valuePtr, name, (size_t) *lengthPtr + 1); } /* *--------------------------------------------------------------------------- * * InitializeSourceLibraryDir -- * * Locate the Tcl script library default location relative to the * location of the Tcl DLL as it exists in the build output directory * associated with the source checkout. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static void InitializeSourceLibraryDir( char **valuePtr, int *lengthPtr, Tcl_Encoding *encodingPtr) { HMODULE hModule = TclWinGetTclInstance(); WCHAR wName[MAX_PATH + LIBRARY_SIZE]; char name[(MAX_PATH + LIBRARY_SIZE) * TCL_UTF_MAX]; char *end, *p; if (GetModuleFileNameW(hModule, wName, MAX_PATH) == 0) { GetModuleFileNameA(hModule, name, MAX_PATH); } else { ToUtf(wName, name); } end = strrchr(name, '\\'); *end = '\0'; p = strrchr(name, '\\'); if (p != NULL) { end = p; } *end = '\\'; TclWinNoBackslash(name); sprintf(end + 1, "../library"); *lengthPtr = strlen(name); *valuePtr = ckalloc(*lengthPtr + 1); *encodingPtr = NULL; memcpy(*valuePtr, name, (size_t) *lengthPtr + 1); } /* *--------------------------------------------------------------------------- * * ToUtf -- * * Convert a char string to a UTF string. * * Results: * None. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static int ToUtf( const WCHAR *wSrc, char *dst) { char *start; start = dst; while (*wSrc != '\0') { dst += Tcl_UniCharToUtf(*wSrc, dst); wSrc++; } *dst = '\0'; return (int) (dst - start); } /* *--------------------------------------------------------------------------- * * TclpSetInitialEncodings -- * * Based on the locale, determine the encoding of the operating system * and the default encoding for newly opened files. * * Called at process initialization time, and part way through startup, * we verify that the initial encodings were correctly setup. Depending * on Tcl's environment, there may not have been enough information first * time through (above). * * Results: * None. * * Side effects: * The Tcl library path is converted from native encoding to UTF-8, on * the first call, and the encodings may be changed on first or second * call. * *--------------------------------------------------------------------------- */ void TclpSetInitialEncodings(void) { Tcl_DString encodingName; TclpSetInterfaces(); Tcl_SetSystemEncoding(NULL, Tcl_GetEncodingNameFromEnvironment(&encodingName)); Tcl_DStringFree(&encodingName); } void TclWinSetInterfaces( int dummy) /* Not used. */ { TclpSetInterfaces(); } const char * Tcl_GetEncodingNameFromEnvironment( Tcl_DString *bufPtr) { Tcl_DStringInit(bufPtr); Tcl_DStringSetLength(bufPtr, 2+TCL_INTEGER_SPACE); wsprintfA(Tcl_DStringValue(bufPtr), "cp%d", GetACP()); Tcl_DStringSetLength(bufPtr, strlen(Tcl_DStringValue(bufPtr))); return Tcl_DStringValue(bufPtr); } /* *--------------------------------------------------------------------------- * * TclpSetVariables -- * * Performs platform-specific interpreter initialization related to the * tcl_platform and env variables, and other platform-specific things. * * Results: * None. * * Side effects: * Sets "tcl_platform", and "env(HOME)" Tcl variables. * *---------------------------------------------------------------------- */ void TclpSetVariables( Tcl_Interp *interp) /* Interp to initialize. */ { const char *ptr; char buffer[TCL_INTEGER_SPACE * 2]; union { SYSTEM_INFO info; OemId oemId; } sys; static OSVERSIONINFOW osInfo; static int osInfoInitialized = 0; Tcl_DString ds; TCHAR szUserName[UNLEN+1]; DWORD cchUserNameLen = UNLEN; Tcl_SetVar2Ex(interp, "tclDefaultLibrary", NULL, TclGetProcessGlobalValue(&defaultLibraryDir), TCL_GLOBAL_ONLY); if (!osInfoInitialized) { HANDLE handle = LoadLibraryW(L"NTDLL"); int(__stdcall *getversion)(void *) = (int(__stdcall *)(void *)) GetProcAddress(handle, "RtlGetVersion"); osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); if (!getversion || getversion(&osInfo)) { GetVersionExW(&osInfo); } if (handle) { FreeLibrary(handle); } osInfoInitialized = 1; } GetSystemInfo(&sys.info); /* * Define the tcl_platform array. */ Tcl_SetVar2(interp, "tcl_platform", "platform", "windows", TCL_GLOBAL_ONLY); if (osInfo.dwPlatformId < NUMPLATFORMS) { Tcl_SetVar2(interp, "tcl_platform", "os", platforms[osInfo.dwPlatformId], TCL_GLOBAL_ONLY); } wsprintfA(buffer, "%d.%d", osInfo.dwMajorVersion, osInfo.dwMinorVersion); Tcl_SetVar2(interp, "tcl_platform", "osVersion", buffer, TCL_GLOBAL_ONLY); if (sys.oemId.wProcessorArchitecture < NUMPROCESSORS) { Tcl_SetVar2(interp, "tcl_platform", "machine", processors[sys.oemId.wProcessorArchitecture], TCL_GLOBAL_ONLY); } #ifdef _DEBUG /* * The existence of the "debug" element of the tcl_platform array * indicates that this particular Tcl shell has been compiled with debug * information. Using "info exists tcl_platform(debug)" a Tcl script can * direct the interpreter to load debug versions of DLLs with the load * command. */ Tcl_SetVar2(interp, "tcl_platform", "debug", "1", TCL_GLOBAL_ONLY); #endif /* * Set up the HOME environment variable from the HOMEDRIVE & HOMEPATH * environment variables, if necessary. */ Tcl_DStringInit(&ds); ptr = Tcl_GetVar2(interp, "env", "HOME", TCL_GLOBAL_ONLY); if (ptr == NULL) { ptr = Tcl_GetVar2(interp, "env", "HOMEDRIVE", TCL_GLOBAL_ONLY); if (ptr != NULL) { Tcl_DStringAppend(&ds, ptr, -1); } ptr = Tcl_GetVar2(interp, "env", "HOMEPATH", TCL_GLOBAL_ONLY); if (ptr != NULL) { Tcl_DStringAppend(&ds, ptr, -1); } if (Tcl_DStringLength(&ds) > 0) { Tcl_SetVar2(interp, "env", "HOME", Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY); } else { Tcl_SetVar2(interp, "env", "HOME", "c:\\", TCL_GLOBAL_ONLY); } } /* * Initialize the user name from the environment first, since this is much * faster than asking the system. * Note: cchUserNameLen is number of characters including nul terminator. */ Tcl_DStringInit(&ds); if (TclGetEnv("USERNAME", &ds) == NULL) { if (GetUserName(szUserName, &cchUserNameLen) != 0) { int cbUserNameLen = cchUserNameLen - 1; cbUserNameLen *= sizeof(TCHAR); Tcl_WinTCharToUtf(szUserName, cbUserNameLen, &ds); } } Tcl_SetVar2(interp, "tcl_platform", "user", Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY); Tcl_DStringFree(&ds); /* * Define what the platform PATH separator is. [TIP #315] */ Tcl_SetVar2(interp, "tcl_platform","pathSeparator", ";", TCL_GLOBAL_ONLY); } /* *---------------------------------------------------------------------- * * TclpFindVariable -- * * Locate the entry in environ for a given name. On Unix this routine is * case sensitive, on Windows this matches mioxed case. * * Results: * The return value is the index in environ of an entry with the name * "name", or -1 if there is no such entry. The integer at *lengthPtr is * filled in with the length of name (if a matching entry is found) or * the length of the environ array (if no matching entry is found). * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclpFindVariable( const char *name, /* Name of desired environment variable * (UTF-8). */ int *lengthPtr) /* Used to return length of name (for * successful searches) or number of non-NULL * entries in environ (for unsuccessful * searches). */ { int i, length, result = -1; register const char *env, *p1, *p2; char *envUpper, *nameUpper; Tcl_DString envString; /* * Convert the name to all upper case for the case insensitive comparison. */ length = strlen(name); nameUpper = ckalloc(length + 1); memcpy(nameUpper, name, (size_t) length+1); Tcl_UtfToUpper(nameUpper); Tcl_DStringInit(&envString); for (i = 0, env = environ[i]; env != NULL; i++, env = environ[i]) { /* * Chop the env string off after the equal sign, then Convert the name * to all upper case, so we do not have to convert all the characters * after the equal sign. */ envUpper = Tcl_ExternalToUtfDString(NULL, env, -1, &envString); p1 = strchr(envUpper, '='); if (p1 == NULL) { continue; } length = (int) (p1 - envUpper); Tcl_DStringSetLength(&envString, length+1); Tcl_UtfToUpper(envUpper); p1 = envUpper; p2 = nameUpper; for (; *p2 == *p1; p1++, p2++) { /* NULL loop body. */ } if ((*p1 == '=') && (*p2 == '\0')) { *lengthPtr = length; result = i; goto done; } Tcl_DStringFree(&envString); } *lengthPtr = i; done: Tcl_DStringFree(&envString); ckfree(nameUpper); return result; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tclWinLoad.c0000644000175000017500000002621312663660066014575 0ustar sergeisergei/* * tclWinLoad.c -- * * This function provides a version of the TclLoadFile that works with * the Windows "LoadLibrary" and "GetProcAddress" API for dynamic * loading. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclWinInt.h" /* * Native name of the directory in the native filesystem where DLLs used in * this process are copied prior to loading, and mutex used to protect its * allocation. */ static WCHAR *dllDirectoryName = NULL; static Tcl_Mutex dllDirectoryNameMutex; /* * Static functions defined within this file. */ static void * FindSymbol(Tcl_Interp *interp, Tcl_LoadHandle loadHandle, const char *symbol); static int InitDLLDirectoryName(void); static void UnloadFile(Tcl_LoadHandle loadHandle); /* *---------------------------------------------------------------------- * * TclpDlopen -- * * Dynamically loads a binary code file into memory and returns a handle * to the new code. * * Results: * A standard Tcl completion code. If an error occurs, an error message * is left in the interp's result. * * Side effects: * New code suddenly appears in memory. * *---------------------------------------------------------------------- */ int TclpDlopen( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Obj *pathPtr, /* Name of the file containing the desired * code (UTF-8). */ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr, /* Filled with address of Tcl_FSUnloadFileProc * function which should be used for this * file. */ int flags) { HINSTANCE hInstance; const TCHAR *nativeName; Tcl_LoadHandle handlePtr; /* * First try the full path the user gave us. This is particularly * important if the cwd is inside a vfs, and we are trying to load using a * relative path. */ nativeName = Tcl_FSGetNativePath(pathPtr); hInstance = LoadLibraryEx(nativeName,NULL,LOAD_WITH_ALTERED_SEARCH_PATH); if (hInstance == NULL) { /* * Let the OS loader examine the binary search path for whatever * string the user gave us which hopefully refers to a file on the * binary path. */ Tcl_DString ds; nativeName = Tcl_WinUtfToTChar(Tcl_GetString(pathPtr), -1, &ds); hInstance = LoadLibraryEx(nativeName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); Tcl_DStringFree(&ds); } if (hInstance == NULL) { DWORD lastError = GetLastError(); Tcl_Obj *errMsg = Tcl_ObjPrintf("couldn't load library \"%s\": ", Tcl_GetString(pathPtr)); /* * Check for possible DLL errors. This doesn't work quite right, * because Windows seems to only return ERROR_MOD_NOT_FOUND for just * about any problem, but it's better than nothing. It'd be even * better if there was a way to get what DLLs */ if (interp) { switch (lastError) { case ERROR_MOD_NOT_FOUND: Tcl_SetErrorCode(interp, "WIN_LOAD", "MOD_NOT_FOUND", NULL); goto notFoundMsg; case ERROR_DLL_NOT_FOUND: Tcl_SetErrorCode(interp, "WIN_LOAD", "DLL_NOT_FOUND", NULL); notFoundMsg: Tcl_AppendToObj(errMsg, "this library or a dependent library" " could not be found in library path", -1); break; case ERROR_PROC_NOT_FOUND: Tcl_SetErrorCode(interp, "WIN_LOAD", "PROC_NOT_FOUND", NULL); Tcl_AppendToObj(errMsg, "A function specified in the import" " table could not be resolved by the system. Windows" " is not telling which one, I'm sorry.", -1); break; case ERROR_INVALID_DLL: Tcl_SetErrorCode(interp, "WIN_LOAD", "INVALID_DLL", NULL); Tcl_AppendToObj(errMsg, "this library or a dependent library" " is damaged", -1); break; case ERROR_DLL_INIT_FAILED: Tcl_SetErrorCode(interp, "WIN_LOAD", "DLL_INIT_FAILED", NULL); Tcl_AppendToObj(errMsg, "the library initialization" " routine failed", -1); break; default: TclWinConvertError(lastError); Tcl_AppendToObj(errMsg, Tcl_PosixError(interp), -1); } Tcl_SetObjResult(interp, errMsg); } return TCL_ERROR; } /* * Succeded; package everything up for Tcl. */ handlePtr = ckalloc(sizeof(struct Tcl_LoadHandle_)); handlePtr->clientData = (ClientData) hInstance; handlePtr->findSymbolProcPtr = &FindSymbol; handlePtr->unloadFileProcPtr = &UnloadFile; *loadHandle = handlePtr; *unloadProcPtr = &UnloadFile; return TCL_OK; } /* *---------------------------------------------------------------------- * * FindSymbol -- * * Looks up a symbol, by name, through a handle associated with a * previously loaded piece of code (shared library). * * Results: * Returns a pointer to the function associated with 'symbol' if it is * found. Otherwise returns NULL and may leave an error message in the * interp's result. * *---------------------------------------------------------------------- */ static void * FindSymbol( Tcl_Interp *interp, Tcl_LoadHandle loadHandle, const char *symbol) { HINSTANCE hInstance = (HINSTANCE) loadHandle->clientData; Tcl_PackageInitProc *proc = NULL; /* * For each symbol, check for both Symbol and _Symbol, since Borland * generates C symbols with a leading '_' by default. */ proc = (void *) GetProcAddress(hInstance, symbol); if (proc == NULL) { Tcl_DString ds; const char *sym2; Tcl_DStringInit(&ds); TclDStringAppendLiteral(&ds, "_"); sym2 = Tcl_DStringAppend(&ds, symbol, -1); proc = (Tcl_PackageInitProc *) GetProcAddress(hInstance, sym2); Tcl_DStringFree(&ds); } if (proc == NULL && interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "cannot find symbol \"%s\"", symbol)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, NULL); } return proc; } /* *---------------------------------------------------------------------- * * UnloadFile -- * * Unloads a dynamically loaded binary code file from memory. Code * pointers in the formerly loaded file are no longer valid after calling * this function. * * Results: * None. * * Side effects: * Code removed from memory. * *---------------------------------------------------------------------- */ static void UnloadFile( Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to * TclpDlopen(). The loadHandle is a token * that represents the loaded file. */ { HINSTANCE hInstance = (HINSTANCE) loadHandle->clientData; FreeLibrary(hInstance); ckfree(loadHandle); } /* *---------------------------------------------------------------------- * * TclGuessPackageName -- * * If the "load" command is invoked without providing a package name, * this function is invoked to try to figure it out. * * Results: * Always returns 0 to indicate that we couldn't figure out a package * name; generic code will then try to guess the package from the file * name. A return value of 1 would have meant that we figured out the * package name and put it in bufPtr. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclGuessPackageName( const char *fileName, /* Name of file containing package (already * translated to local form if needed). */ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package * name to this if possible. */ { return 0; } /* *---------------------------------------------------------------------- * * TclpTempFileNameForLibrary -- * * Constructs a temporary file name for loading a shared object (DLL). * * Results: * Returns the constructed file name. * * On Windows, a DLL is identified by the final component of its path name. * Cross linking among DLL's (and hence, preloading) will not work unless this * name is preserved when copying a DLL from a VFS to a temp file for * preloading. For this reason, all DLLs in a given process are copied to a * temp directory, and their names are preserved. * *---------------------------------------------------------------------- */ Tcl_Obj * TclpTempFileNameForLibrary( Tcl_Interp *interp, /* Tcl interpreter. */ Tcl_Obj *path) /* Path name of the DLL in the VFS. */ { Tcl_Obj *fileName; /* Name of the temp file. */ Tcl_Obj *tail; /* Tail of the source path. */ Tcl_MutexLock(&dllDirectoryNameMutex); if (dllDirectoryName == NULL) { if (InitDLLDirectoryName() == TCL_ERROR) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't create temporary directory: %s", Tcl_PosixError(interp))); Tcl_MutexUnlock(&dllDirectoryNameMutex); return NULL; } } Tcl_MutexUnlock(&dllDirectoryNameMutex); /* * Now we know where to put temporary DLLs, construct the name. */ fileName = TclpNativeToNormalized(dllDirectoryName); tail = TclPathPart(interp, path, TCL_PATH_TAIL); if (tail == NULL) { Tcl_DecrRefCount(fileName); return NULL; } Tcl_AppendToObj(fileName, "/", 1); Tcl_AppendObjToObj(fileName, tail); return fileName; } /* *---------------------------------------------------------------------- * * InitDLLDirectoryName -- * * Helper for TclpTempFileNameForLibrary; builds a temporary directory * that is specific to the current process. Should only be called once * per process start. Caller must hold dllDirectoryNameMutex. * * Results: * Tcl result code. * * Side-effects: * Creates temp directory. * Allocates memory pointed to by dllDirectoryName. * *---------------------------------------------------------------------- * [Candidate for process global?] */ static int InitDLLDirectoryName(void) { size_t nameLen; /* Length of the temp folder name. */ WCHAR name[MAX_PATH]; /* Path name of the temp folder. */ DWORD id; /* The process id. */ DWORD lastError; /* Last error to happen in Win API. */ int i; /* * Determine the name of the directory to use, and create it. (Keep * trying with new names until an attempt to create the directory * succeeds) */ nameLen = GetTempPathW(MAX_PATH, name); if (nameLen >= MAX_PATH-12) { Tcl_SetErrno(ENAMETOOLONG); return TCL_ERROR; } wcscpy(name+nameLen, L"TCLXXXXXXXX"); nameLen += 11; id = GetCurrentProcessId(); lastError = ERROR_ALREADY_EXISTS; for (i=0 ; i<256 ; i++) { wsprintfW(name+nameLen-8, L"%08x", id); if (CreateDirectoryW(name, NULL)) { /* * Issue: we don't schedule this directory for deletion by anyone. * Can we ask the OS to do this for us? There appears to be * potential for using CreateFile (with the flag * FILE_FLAG_BACKUP_SEMANTICS) and RemoveDirectory to do this... */ goto copyToGlobalBuffer; } lastError = GetLastError(); if (lastError != ERROR_ALREADY_EXISTS) { break; } id *= 16777619; } TclWinConvertError(lastError); return TCL_ERROR; /* * Store our computed value in the global. */ copyToGlobalBuffer: dllDirectoryName = ckalloc((nameLen+1) * sizeof(WCHAR)); wcscpy(dllDirectoryName, name); return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tclWinError.c0000644000175000017500000002675712663660066015024 0ustar sergeisergei/* * tclWinError.c -- * * This file contains code for converting from Win32 errors to errno * errors. * * Copyright (c) 1995-1996 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * The following table contains the mapping from Win32 errors to errno errors. */ static const unsigned char errorTable[] = { 0, EINVAL, /* ERROR_INVALID_FUNCTION 1 */ ENOENT, /* ERROR_FILE_NOT_FOUND 2 */ ENOENT, /* ERROR_PATH_NOT_FOUND 3 */ EMFILE, /* ERROR_TOO_MANY_OPEN_FILES 4 */ EACCES, /* ERROR_ACCESS_DENIED 5 */ EBADF, /* ERROR_INVALID_HANDLE 6 */ ENOMEM, /* ERROR_ARENA_TRASHED 7 */ ENOMEM, /* ERROR_NOT_ENOUGH_MEMORY 8 */ ENOMEM, /* ERROR_INVALID_BLOCK 9 */ E2BIG, /* ERROR_BAD_ENVIRONMENT 10 */ ENOEXEC, /* ERROR_BAD_FORMAT 11 */ EACCES, /* ERROR_INVALID_ACCESS 12 */ EINVAL, /* ERROR_INVALID_DATA 13 */ EFAULT, /* ERROR_OUT_OF_MEMORY 14 */ ENOENT, /* ERROR_INVALID_DRIVE 15 */ EACCES, /* ERROR_CURRENT_DIRECTORY 16 */ EXDEV, /* ERROR_NOT_SAME_DEVICE 17 */ ENOENT, /* ERROR_NO_MORE_FILES 18 */ EROFS, /* ERROR_WRITE_PROTECT 19 */ ENXIO, /* ERROR_BAD_UNIT 20 */ EBUSY, /* ERROR_NOT_READY 21 */ EIO, /* ERROR_BAD_COMMAND 22 */ EIO, /* ERROR_CRC 23 */ EIO, /* ERROR_BAD_LENGTH 24 */ EIO, /* ERROR_SEEK 25 */ EIO, /* ERROR_NOT_DOS_DISK 26 */ ENXIO, /* ERROR_SECTOR_NOT_FOUND 27 */ EBUSY, /* ERROR_OUT_OF_PAPER 28 */ EIO, /* ERROR_WRITE_FAULT 29 */ EIO, /* ERROR_READ_FAULT 30 */ EIO, /* ERROR_GEN_FAILURE 31 */ EACCES, /* ERROR_SHARING_VIOLATION 32 */ EACCES, /* ERROR_LOCK_VIOLATION 33 */ ENXIO, /* ERROR_WRONG_DISK 34 */ ENFILE, /* ERROR_FCB_UNAVAILABLE 35 */ ENFILE, /* ERROR_SHARING_BUFFER_EXCEEDED 36 */ EINVAL, /* 37 */ EINVAL, /* 38 */ ENOSPC, /* ERROR_HANDLE_DISK_FULL 39 */ EINVAL, /* 40 */ EINVAL, /* 41 */ EINVAL, /* 42 */ EINVAL, /* 43 */ EINVAL, /* 44 */ EINVAL, /* 45 */ EINVAL, /* 46 */ EINVAL, /* 47 */ EINVAL, /* 48 */ EINVAL, /* 49 */ ENODEV, /* ERROR_NOT_SUPPORTED 50 */ EBUSY, /* ERROR_REM_NOT_LIST 51 */ EEXIST, /* ERROR_DUP_NAME 52 */ ENOENT, /* ERROR_BAD_NETPATH 53 */ EBUSY, /* ERROR_NETWORK_BUSY 54 */ ENODEV, /* ERROR_DEV_NOT_EXIST 55 */ EAGAIN, /* ERROR_TOO_MANY_CMDS 56 */ EIO, /* ERROR_ADAP_HDW_ERR 57 */ EIO, /* ERROR_BAD_NET_RESP 58 */ EIO, /* ERROR_UNEXP_NET_ERR 59 */ EINVAL, /* ERROR_BAD_REM_ADAP 60 */ EFBIG, /* ERROR_PRINTQ_FULL 61 */ ENOSPC, /* ERROR_NO_SPOOL_SPACE 62 */ ENOENT, /* ERROR_PRINT_CANCELLED 63 */ ENOENT, /* ERROR_NETNAME_DELETED 64 */ EACCES, /* ERROR_NETWORK_ACCESS_DENIED 65 */ ENODEV, /* ERROR_BAD_DEV_TYPE 66 */ ENOENT, /* ERROR_BAD_NET_NAME 67 */ ENFILE, /* ERROR_TOO_MANY_NAMES 68 */ EIO, /* ERROR_TOO_MANY_SESS 69 */ EAGAIN, /* ERROR_SHARING_PAUSED 70 */ EINVAL, /* ERROR_REQ_NOT_ACCEP 71 */ EAGAIN, /* ERROR_REDIR_PAUSED 72 */ EINVAL, /* 73 */ EINVAL, /* 74 */ EINVAL, /* 75 */ EINVAL, /* 76 */ EINVAL, /* 77 */ EINVAL, /* 78 */ EINVAL, /* 79 */ EEXIST, /* ERROR_FILE_EXISTS 80 */ EINVAL, /* 81 */ ENOSPC, /* ERROR_CANNOT_MAKE 82 */ EIO, /* ERROR_FAIL_I24 83 */ ENFILE, /* ERROR_OUT_OF_STRUCTURES 84 */ EEXIST, /* ERROR_ALREADY_ASSIGNED 85 */ EPERM, /* ERROR_INVALID_PASSWORD 86 */ EINVAL, /* ERROR_INVALID_PARAMETER 87 */ EIO, /* ERROR_NET_WRITE_FAULT 88 */ EAGAIN, /* ERROR_NO_PROC_SLOTS 89 */ EINVAL, /* 90 */ EINVAL, /* 91 */ EINVAL, /* 92 */ EINVAL, /* 93 */ EINVAL, /* 94 */ EINVAL, /* 95 */ EINVAL, /* 96 */ EINVAL, /* 97 */ EINVAL, /* 98 */ EINVAL, /* 99 */ EINVAL, /* 100 */ EINVAL, /* 101 */ EINVAL, /* 102 */ EINVAL, /* 103 */ EINVAL, /* 104 */ EINVAL, /* 105 */ EINVAL, /* 106 */ EXDEV, /* ERROR_DISK_CHANGE 107 */ EAGAIN, /* ERROR_DRIVE_LOCKED 108 */ EPIPE, /* ERROR_BROKEN_PIPE 109 */ ENOENT, /* ERROR_OPEN_FAILED 110 */ EINVAL, /* ERROR_BUFFER_OVERFLOW 111 */ ENOSPC, /* ERROR_DISK_FULL 112 */ EMFILE, /* ERROR_NO_MORE_SEARCH_HANDLES 113 */ EBADF, /* ERROR_INVALID_TARGET_HANDLE 114 */ EFAULT, /* ERROR_PROTECTION_VIOLATION 115 */ EINVAL, /* 116 */ EINVAL, /* 117 */ EINVAL, /* 118 */ EINVAL, /* 119 */ EINVAL, /* 120 */ EINVAL, /* 121 */ EINVAL, /* 122 */ ENOENT, /* ERROR_INVALID_NAME 123 */ EINVAL, /* 124 */ EINVAL, /* 125 */ EINVAL, /* 126 */ EINVAL, /* ERROR_PROC_NOT_FOUND 127 */ ECHILD, /* ERROR_WAIT_NO_CHILDREN 128 */ ECHILD, /* ERROR_CHILD_NOT_COMPLETE 129 */ EBADF, /* ERROR_DIRECT_ACCESS_HANDLE 130 */ EINVAL, /* ERROR_NEGATIVE_SEEK 131 */ ESPIPE, /* ERROR_SEEK_ON_DEVICE 132 */ EINVAL, /* 133 */ EINVAL, /* 134 */ EINVAL, /* 135 */ EINVAL, /* 136 */ EINVAL, /* 137 */ EINVAL, /* 138 */ EINVAL, /* 139 */ EINVAL, /* 140 */ EINVAL, /* 141 */ EAGAIN, /* ERROR_BUSY_DRIVE 142 */ EINVAL, /* 143 */ EINVAL, /* 144 */ EEXIST, /* ERROR_DIR_NOT_EMPTY 145 */ EINVAL, /* 146 */ EINVAL, /* 147 */ EINVAL, /* 148 */ EINVAL, /* 149 */ EINVAL, /* 150 */ EINVAL, /* 151 */ EINVAL, /* 152 */ EINVAL, /* 153 */ EINVAL, /* 154 */ EINVAL, /* 155 */ EINVAL, /* 156 */ EINVAL, /* 157 */ EACCES, /* ERROR_NOT_LOCKED 158 */ EINVAL, /* 159 */ EINVAL, /* 160 */ ENOENT, /* ERROR_BAD_PATHNAME 161 */ EINVAL, /* 162 */ EINVAL, /* 163 */ EINVAL, /* 164 */ EINVAL, /* 165 */ EINVAL, /* 166 */ EACCES, /* ERROR_LOCK_FAILED 167 */ EINVAL, /* 168 */ EINVAL, /* 169 */ EINVAL, /* 170 */ EINVAL, /* 171 */ EINVAL, /* 172 */ EINVAL, /* 173 */ EINVAL, /* 174 */ EINVAL, /* 175 */ EINVAL, /* 176 */ EINVAL, /* 177 */ EINVAL, /* 178 */ EINVAL, /* 179 */ EINVAL, /* 180 */ EINVAL, /* 181 */ EINVAL, /* 182 */ EEXIST, /* ERROR_ALREADY_EXISTS 183 */ ECHILD, /* ERROR_NO_CHILD_PROCESS 184 */ EINVAL, /* 185 */ EINVAL, /* 186 */ EINVAL, /* 187 */ EINVAL, /* 188 */ EINVAL, /* 189 */ EINVAL, /* 190 */ EINVAL, /* 191 */ EINVAL, /* 192 */ EINVAL, /* 193 */ EINVAL, /* 194 */ EINVAL, /* 195 */ EINVAL, /* 196 */ EINVAL, /* 197 */ EINVAL, /* 198 */ EINVAL, /* 199 */ EINVAL, /* 200 */ EINVAL, /* 201 */ EINVAL, /* 202 */ EINVAL, /* 203 */ EINVAL, /* 204 */ EINVAL, /* 205 */ ENAMETOOLONG,/* ERROR_FILENAME_EXCED_RANGE 206 */ EINVAL, /* 207 */ EINVAL, /* 208 */ EINVAL, /* 209 */ EINVAL, /* 210 */ EINVAL, /* 211 */ EINVAL, /* 212 */ EINVAL, /* 213 */ EINVAL, /* 214 */ EINVAL, /* 215 */ EINVAL, /* 216 */ EINVAL, /* 217 */ EINVAL, /* 218 */ EINVAL, /* 219 */ EINVAL, /* 220 */ EINVAL, /* 221 */ EINVAL, /* 222 */ EINVAL, /* 223 */ EINVAL, /* 224 */ EINVAL, /* 225 */ EINVAL, /* 226 */ EINVAL, /* 227 */ EINVAL, /* 228 */ EINVAL, /* 229 */ EPIPE, /* ERROR_BAD_PIPE 230 */ EAGAIN, /* ERROR_PIPE_BUSY 231 */ EPIPE, /* ERROR_NO_DATA 232 */ EPIPE, /* ERROR_PIPE_NOT_CONNECTED 233 */ EINVAL, /* 234 */ EINVAL, /* 235 */ EINVAL, /* 236 */ EINVAL, /* 237 */ EINVAL, /* 238 */ EINVAL, /* 239 */ EINVAL, /* 240 */ EINVAL, /* 241 */ EINVAL, /* 242 */ EINVAL, /* 243 */ EINVAL, /* 244 */ EINVAL, /* 245 */ EINVAL, /* 246 */ EINVAL, /* 247 */ EINVAL, /* 248 */ EINVAL, /* 249 */ EINVAL, /* 250 */ EINVAL, /* 251 */ EINVAL, /* 252 */ EINVAL, /* 253 */ EINVAL, /* 254 */ EINVAL, /* 255 */ EINVAL, /* 256 */ EINVAL, /* 257 */ EINVAL, /* 258 */ EINVAL, /* 259 */ EINVAL, /* 260 */ EINVAL, /* 261 */ EINVAL, /* 262 */ EINVAL, /* 263 */ EINVAL, /* 264 */ EINVAL, /* 265 */ EINVAL, /* 266 */ ENOTDIR /* ERROR_DIRECTORY 267 */ }; /* * The following table contains the mapping from WinSock errors to * errno errors. */ static const unsigned char wsaErrorTable[] = { EWOULDBLOCK, /* WSAEWOULDBLOCK */ EINPROGRESS, /* WSAEINPROGRESS */ EALREADY, /* WSAEALREADY */ ENOTSOCK, /* WSAENOTSOCK */ EDESTADDRREQ, /* WSAEDESTADDRREQ */ EMSGSIZE, /* WSAEMSGSIZE */ EPROTOTYPE, /* WSAEPROTOTYPE */ ENOPROTOOPT, /* WSAENOPROTOOPT */ EPROTONOSUPPORT, /* WSAEPROTONOSUPPORT */ ESOCKTNOSUPPORT, /* WSAESOCKTNOSUPPORT */ EOPNOTSUPP, /* WSAEOPNOTSUPP */ EPFNOSUPPORT, /* WSAEPFNOSUPPORT */ EAFNOSUPPORT, /* WSAEAFNOSUPPORT */ EADDRINUSE, /* WSAEADDRINUSE */ EADDRNOTAVAIL, /* WSAEADDRNOTAVAIL */ ENETDOWN, /* WSAENETDOWN */ ENETUNREACH, /* WSAENETUNREACH */ ENETRESET, /* WSAENETRESET */ ECONNABORTED, /* WSAECONNABORTED */ ECONNRESET, /* WSAECONNRESET */ ENOBUFS, /* WSAENOBUFS */ EISCONN, /* WSAEISCONN */ ENOTCONN, /* WSAENOTCONN */ ESHUTDOWN, /* WSAESHUTDOWN */ ETOOMANYREFS, /* WSAETOOMANYREFS */ ETIMEDOUT, /* WSAETIMEDOUT */ ECONNREFUSED, /* WSAECONNREFUSED */ ELOOP, /* WSAELOOP */ ENAMETOOLONG, /* WSAENAMETOOLONG */ EHOSTDOWN, /* WSAEHOSTDOWN */ EHOSTUNREACH, /* WSAEHOSTUNREACH */ ENOTEMPTY, /* WSAENOTEMPTY */ EAGAIN, /* WSAEPROCLIM */ EUSERS, /* WSAEUSERS */ EDQUOT, /* WSAEDQUOT */ ESTALE, /* WSAESTALE */ EREMOTE /* WSAEREMOTE */ }; /* *---------------------------------------------------------------------- * * TclWinConvertError -- * * This routine converts a Win32 error into an errno value. * * Results: * None. * * Side effects: * Sets the errno global variable. * *---------------------------------------------------------------------- */ void TclWinConvertError( DWORD errCode) /* Win32 error code. */ { if (errCode >= sizeof(errorTable)/sizeof(errorTable[0])) { errCode -= WSAEWOULDBLOCK; if (errCode >= sizeof(wsaErrorTable)/sizeof(wsaErrorTable[0])) { Tcl_SetErrno(errorTable[1]); } else { Tcl_SetErrno(wsaErrorTable[errCode]); } } else { Tcl_SetErrno(errorTable[errCode]); } } #ifdef __CYGWIN__ /* *---------------------------------------------------------------------- * * tclWinDebugPanic -- * * Display a message. If a debugger is present, present it directly to * the debugger, otherwise send it to stderr. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ TCL_NORETURN void tclWinDebugPanic( const char *format, ...) { #define TCL_MAX_WARN_LEN 1024 va_list argList; va_start(argList, format); if (IsDebuggerPresent()) { WCHAR msgString[TCL_MAX_WARN_LEN]; char buf[TCL_MAX_WARN_LEN * TCL_UTF_MAX]; vsnprintf(buf, sizeof(buf), format, argList); msgString[TCL_MAX_WARN_LEN-1] = L'\0'; MultiByteToWideChar(CP_UTF8, 0, buf, -1, msgString, TCL_MAX_WARN_LEN); /* * Truncate MessageBox string if it is too long to not overflow the buffer. */ if (msgString[TCL_MAX_WARN_LEN-1] != L'\0') { memcpy(msgString + (TCL_MAX_WARN_LEN - 5), L" ...", 5 * sizeof(WCHAR)); } OutputDebugStringW(msgString); } else { vfprintf(stderr, format, argList); fprintf(stderr, "\n"); fflush(stderr); } # if defined(__GNUC__) __builtin_trap(); # else DebugBreak(); # endif abort(); } #endif /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * End: */ tcl8.6.5/win/rules.vc0000644000175000017500000004544512663660066014065 0ustar sergeisergei#------------------------------------------------------------------------------ # rules.vc -- # # Microsoft Visual C++ makefile include for decoding the commandline # macros. This file does not need editing to build Tcl. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # Copyright (c) 2001-2003 David Gravereaux. # Copyright (c) 2003-2008 Patrick Thoyts #------------------------------------------------------------------------------ !ifndef _RULES_VC _RULES_VC = 1 cc32 = $(CC) # built-in default. link32 = link lib32 = lib rc32 = $(RC) # built-in default. !ifndef INSTALLDIR ### Assume the normal default. _INSTALLDIR = C:\Program Files\Tcl !else ### Fix the path separators. _INSTALLDIR = $(INSTALLDIR:/=\) !endif #---------------------------------------------------------- # Set the proper copy method to avoid overwrite questions # to the user when copying files and selecting the right # "delete all" method. #---------------------------------------------------------- !if "$(OS)" == "Windows_NT" RMDIR = rmdir /S /Q ERRNULL = 2>NUL !if ![ver | find "4.0" > nul] CPY = echo y | xcopy /i >NUL COPY = copy >NUL !else CPY = xcopy /i /y >NUL COPY = copy /y >NUL !endif !else # "$(OS)" != "Windows_NT" CPY = xcopy /i >_JUNK.OUT # On Win98 NUL does not work here. COPY = copy >_JUNK.OUT # On Win98 NUL does not work here. RMDIR = deltree /Y NULL = \NUL # Used in testing directory existence ERRNULL = >NUL # Win9x shell cannot redirect stderr !endif MKDIR = mkdir #------------------------------------------------------------------------------ # Determine the host and target architectures and compiler version. #------------------------------------------------------------------------------ _HASH=^# _VC_MANIFEST_EMBED_EXE= _VC_MANIFEST_EMBED_DLL= VCVER=0 !if ![echo VCVERSION=_MSC_VER > vercl.x] \ && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \ && ![echo ARCH=IX86 >> vercl.x] \ && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \ && ![echo ARCH=AMD64 >> vercl.x] \ && ![echo $(_HASH)endif >> vercl.x] \ && ![cl -nologo -TC -P vercl.x $(ERRNULL)] !include vercl.i !if ![echo VCVER= ^\> vercl.vc] \ && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc] !include vercl.vc !endif !endif !if ![del $(ERRNUL) /q/f vercl.x vercl.i vercl.vc] !endif !if ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i x86] NATIVE_ARCH=IX86 !else NATIVE_ARCH=AMD64 !endif # Since MSVC8 we must deal with manifest resources. !if $(VCVERSION) >= 1400 _VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1 _VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2 !endif !ifndef MACHINE MACHINE=$(ARCH) !endif !ifndef CFG_ENCODING CFG_ENCODING = \"cp1252\" !endif !message =============================================================================== #---------------------------------------------------------- # build the helper app we need to overcome nmake's limiting # environment. #---------------------------------------------------------- !if !exist(nmakehlp.exe) !if [$(cc32) -nologo nmakehlp.c -link -subsystem:console > nul] !endif !endif #---------------------------------------------------------- # Test for compiler features #---------------------------------------------------------- ### test for optimizations !if [nmakehlp -c -Ot] !message *** Compiler has 'Optimizations' OPTIMIZING = 1 !else !message *** Compiler does not have 'Optimizations' OPTIMIZING = 0 !endif OPTIMIZATIONS = !if [nmakehlp -c -Ot] OPTIMIZATIONS = $(OPTIMIZATIONS) -Ot !endif !if [nmakehlp -c -Oi] OPTIMIZATIONS = $(OPTIMIZATIONS) -Oi !endif !if [nmakehlp -c -Op] OPTIMIZATIONS = $(OPTIMIZATIONS) -Op !endif !if [nmakehlp -c -fp:strict] OPTIMIZATIONS = $(OPTIMIZATIONS) -fp:strict !endif !if [nmakehlp -c -Gs] OPTIMIZATIONS = $(OPTIMIZATIONS) -Gs !endif !if [nmakehlp -c -GS] OPTIMIZATIONS = $(OPTIMIZATIONS) -GS !endif !if [nmakehlp -c -GL] OPTIMIZATIONS = $(OPTIMIZATIONS) -GL !endif DEBUGFLAGS = !if [nmakehlp -c -RTC1] DEBUGFLAGS = $(DEBUGFLAGS) -RTC1 !elseif [nmakehlp -c -GZ] DEBUGFLAGS = $(DEBUGFLAGS) -GZ !endif COMPILERFLAGS =-W3 -DUNICODE -D_UNICODE # In v13 -GL and -YX are incompatible. !if [nmakehlp -c -YX] !if ![nmakehlp -c -GL] OPTIMIZATIONS = $(OPTIMIZATIONS) -YX !endif !endif !if "$(MACHINE)" == "IX86" ### test for pentium errata !if [nmakehlp -c -QI0f] !message *** Compiler has 'Pentium 0x0f fix' COMPILERFLAGS = $(COMPILERFLAGS) -QI0f !else !message *** Compiler does not have 'Pentium 0x0f fix' !endif !endif !if "$(MACHINE)" == "IA64" ### test for Itanium errata !if [nmakehlp -c -QIA64_Bx] !message *** Compiler has 'B-stepping errata workarounds' COMPILERFLAGS = $(COMPILERFLAGS) -QIA64_Bx !else !message *** Compiler does not have 'B-stepping errata workarounds' !endif !endif !if "$(MACHINE)" == "IX86" ### test for -align:4096, when align:512 will do. !if [nmakehlp -l -opt:nowin98] !message *** Linker has 'Win98 alignment problem' ALIGN98_HACK = 1 !else !message *** Linker does not have 'Win98 alignment problem' ALIGN98_HACK = 0 !endif !else ALIGN98_HACK = 0 !endif LINKERFLAGS = !if [nmakehlp -l -ltcg] LINKERFLAGS =-ltcg !endif #---------------------------------------------------------- # Decode the options requested. #---------------------------------------------------------- !if "$(OPTS)" == "" || [nmakehlp -f "$(OPTS)" "none"] STATIC_BUILD = 0 TCL_THREADS = 1 DEBUG = 0 SYMBOLS = 0 PROFILE = 0 PGO = 0 MSVCRT = 1 LOIMPACT = 0 TCL_USE_STATIC_PACKAGES = 0 USE_THREAD_ALLOC = 1 UNCHECKED = 0 !else !if [nmakehlp -f $(OPTS) "static"] !message *** Doing static STATIC_BUILD = 1 !else STATIC_BUILD = 0 !endif !if [nmakehlp -f $(OPTS) "msvcrt"] !message *** Doing msvcrt MSVCRT = 1 !else !if !$(STATIC_BUILD) MSVCRT = 1 !else MSVCRT = 0 !endif !endif !if [nmakehlp -f $(OPTS) "staticpkg"] && $(STATIC_BUILD) !message *** Doing staticpkg TCL_USE_STATIC_PACKAGES = 1 !else TCL_USE_STATIC_PACKAGES = 0 !endif !if [nmakehlp -f $(OPTS) "nothreads"] !message *** Compile explicitly for non-threaded tcl TCL_THREADS = 0 USE_THREAD_ALLOC= 0 !else TCL_THREADS = 1 USE_THREAD_ALLOC= 1 !endif !if [nmakehlp -f $(OPTS) "symbols"] !message *** Doing symbols DEBUG = 1 !else DEBUG = 0 !endif !if [nmakehlp -f $(OPTS) "pdbs"] !message *** Doing pdbs SYMBOLS = 1 !else SYMBOLS = 0 !endif !if [nmakehlp -f $(OPTS) "profile"] !message *** Doing profile PROFILE = 1 !else PROFILE = 0 !endif !if [nmakehlp -f $(OPTS) "pgi"] !message *** Doing profile guided optimization instrumentation PGO = 1 !elseif [nmakehlp -f $(OPTS) "pgo"] !message *** Doing profile guided optimization PGO = 2 !else PGO = 0 !endif !if [nmakehlp -f $(OPTS) "loimpact"] !message *** Doing loimpact LOIMPACT = 1 !else LOIMPACT = 0 !endif !if [nmakehlp -f $(OPTS) "thrdalloc"] !message *** Doing thrdalloc USE_THREAD_ALLOC = 1 !endif !if [nmakehlp -f $(OPTS) "tclalloc"] !message *** Doing tclalloc USE_THREAD_ALLOC = 0 !endif !if [nmakehlp -f $(OPTS) "unchecked"] !message *** Doing unchecked UNCHECKED = 1 !else UNCHECKED = 0 !endif !endif #---------------------------------------------------------- # Figure-out how to name our intermediate and output directories. # We wouldn't want different builds to use the same .obj files # by accident. #---------------------------------------------------------- #---------------------------------------- # Naming convention: # t = full thread support. # s = static library (as opposed to an # import library) # g = linked to the debug enabled C # run-time. # x = special static build when it # links to the dynamic C run-time. #---------------------------------------- SUFX = tsgx !if $(DEBUG) BUILDDIRTOP = Debug !else BUILDDIRTOP = Release !endif !if "$(MACHINE)" != "IX86" BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE) !endif !if $(VCVER) > 6 BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER) !endif !if !$(DEBUG) || $(DEBUG) && $(UNCHECKED) SUFX = $(SUFX:g=) !endif TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX !if !$(STATIC_BUILD) TMP_DIRFULL = $(TMP_DIRFULL:Static=) SUFX = $(SUFX:s=) EXT = dll TMP_DIRFULL = $(TMP_DIRFULL:X=) SUFX = $(SUFX:x=) !else TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=) EXT = lib !if !$(MSVCRT) TMP_DIRFULL = $(TMP_DIRFULL:X=) SUFX = $(SUFX:x=) !endif !endif !if !$(TCL_THREADS) TMP_DIRFULL = $(TMP_DIRFULL:Threaded=) SUFX = $(SUFX:t=) !endif !ifndef TMP_DIR TMP_DIR = $(TMP_DIRFULL) !ifndef OUT_DIR OUT_DIR = .\$(BUILDDIRTOP) !endif !else !ifndef OUT_DIR OUT_DIR = $(TMP_DIR) !endif !endif #---------------------------------------------------------- # Decode the statistics requested. #---------------------------------------------------------- !if "$(STATS)" == "" || [nmakehlp -f "$(STATS)" "none"] TCL_MEM_DEBUG = 0 TCL_COMPILE_DEBUG = 0 !else !if [nmakehlp -f $(STATS) "memdbg"] !message *** Doing memdbg TCL_MEM_DEBUG = 1 !else TCL_MEM_DEBUG = 0 !endif !if [nmakehlp -f $(STATS) "compdbg"] !message *** Doing compdbg TCL_COMPILE_DEBUG = 1 !else TCL_COMPILE_DEBUG = 0 !endif !endif #---------------------------------------------------------- # Decode the checks requested. #---------------------------------------------------------- !if "$(CHECKS)" == "" || [nmakehlp -f "$(CHECKS)" "none"] TCL_NO_DEPRECATED = 0 WARNINGS = -W3 !else !if [nmakehlp -f $(CHECKS) "nodep"] !message *** Doing nodep check TCL_NO_DEPRECATED = 1 !else TCL_NO_DEPRECATED = 0 !endif !if [nmakehlp -f $(CHECKS) "fullwarn"] !message *** Doing full warnings check WARNINGS = -W4 !if [nmakehlp -l -warn:3] LINKERFLAGS = $(LINKERFLAGS) -warn:3 !endif !else WARNINGS = -W3 !endif !if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64] !message *** Doing 64bit portability warnings WARNINGS = $(WARNINGS) -Wp64 !endif !endif !if $(PGO) > 1 !if [nmakehlp -l -ltcg:pgoptimize] LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pgoptimize !else MSG=^ This compiler does not support profile guided optimization. !error $(MSG) !endif !elseif $(PGO) > 0 !if [nmakehlp -l -ltcg:pginstrument] LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pginstrument !else MSG=^ This compiler does not support profile guided optimization. !error $(MSG) !endif !endif #---------------------------------------------------------- # Set our defines now armed with our options. #---------------------------------------------------------- OPTDEFINES = -DTCL_CFGVAL_ENCODING=$(CFG_ENCODING) -DSTDC_HEADERS !if $(TCL_MEM_DEBUG) OPTDEFINES = $(OPTDEFINES) -DTCL_MEM_DEBUG !endif !if $(TCL_COMPILE_DEBUG) OPTDEFINES = $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS !endif !if $(TCL_THREADS) OPTDEFINES = $(OPTDEFINES) -DTCL_THREADS=1 !if $(USE_THREAD_ALLOC) OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_ALLOC=1 !endif !endif !if $(STATIC_BUILD) OPTDEFINES = $(OPTDEFINES) -DSTATIC_BUILD !endif !if $(TCL_NO_DEPRECATED) OPTDEFINES = $(OPTDEFINES) -DTCL_NO_DEPRECATED !endif !if !$(DEBUG) OPTDEFINES = $(OPTDEFINES) -DNDEBUG !if $(OPTIMIZING) OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_OPTIMIZED !endif !endif !if $(PROFILE) OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_PROFILED !endif !if "$(MACHINE)" == "IA64" || "$(MACHINE)" == "AMD64" OPTDEFINES = $(OPTDEFINES) -DTCL_CFG_DO64BIT !endif !if $(VCVERSION) < 1300 OPTDEFINES = $(OPTDEFINES) -DNO_STRTOI64 !endif #---------------------------------------------------------- # Locate the Tcl headers to build against #---------------------------------------------------------- !if "$(PROJECT)" == "tcl" _TCL_H = ..\generic\tcl.h !else # If INSTALLDIR set to tcl root dir then reset to the lib dir. !if exist("$(_INSTALLDIR)\include\tcl.h") _INSTALLDIR=$(_INSTALLDIR)\lib !endif !if !defined(TCLDIR) !if exist("$(_INSTALLDIR)\..\include\tcl.h") TCLINSTALL = 1 _TCLDIR = $(_INSTALLDIR)\.. _TCL_H = $(_INSTALLDIR)\..\include\tcl.h TCLDIR = $(_INSTALLDIR)\.. !else MSG=^ Failed to find tcl.h. Set the TCLDIR macro. !error $(MSG) !endif !else _TCLDIR = $(TCLDIR:/=\) !if exist("$(_TCLDIR)\include\tcl.h") TCLINSTALL = 1 _TCL_H = $(_TCLDIR)\include\tcl.h !elseif exist("$(_TCLDIR)\generic\tcl.h") TCLINSTALL = 0 _TCL_H = $(_TCLDIR)\generic\tcl.h !else MSG =^ Failed to find tcl.h. The TCLDIR macro does not appear correct. !error $(MSG) !endif !endif !endif #-------------------------------------------------------------- # Extract various version numbers from tcl headers # The generated file is then included in the makefile. #-------------------------------------------------------------- !if [echo REM = This file is generated from rules.vc > versions.vc] !endif !if [echo TCL_MAJOR_VERSION = \>> versions.vc] \ && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc] !endif !if [echo TCL_MINOR_VERSION = \>> versions.vc] \ && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc] !endif !if [echo TCL_PATCH_LEVEL = \>> versions.vc] \ && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc] !endif # If building the tcl core then we need additional package versions !if "$(PROJECT)" == "tcl" !if [echo PKG_HTTP_VER = \>> versions.vc] \ && [nmakehlp -V ..\library\http\pkgIndex.tcl http >> versions.vc] !endif !if [echo PKG_TCLTEST_VER = \>> versions.vc] \ && [nmakehlp -V ..\library\tcltest\pkgIndex.tcl tcltest >> versions.vc] !endif !if [echo PKG_MSGCAT_VER = \>> versions.vc] \ && [nmakehlp -V ..\library\msgcat\pkgIndex.tcl msgcat >> versions.vc] !endif !if [echo PKG_PLATFORM_VER = \>> versions.vc] \ && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform " >> versions.vc] !endif !if [echo PKG_SHELL_VER = \>> versions.vc] \ && [nmakehlp -V ..\library\platform\pkgIndex.tcl "platform::shell" >> versions.vc] !endif !if [echo PKG_DDE_VER = \>> versions.vc] \ && [nmakehlp -V ..\library\dde\pkgIndex.tcl "dde " >> versions.vc] !endif !if [echo PKG_REG_VER =\>> versions.vc] \ && [nmakehlp -V ..\library\reg\pkgIndex.tcl registry >> versions.vc] !endif !endif !include versions.vc #-------------------------------------------------------------- # Setup tcl version dependent stuff headers #-------------------------------------------------------------- !if "$(PROJECT)" != "tcl" TCL_VERSION = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION) !if $(TCLINSTALL) TCLSH = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe" !if !exist($(TCLSH)) && $(TCL_THREADS) TCLSH = "$(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe" !endif TCLSTUBLIB = "$(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib" TCLIMPLIB = "$(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib" TCL_LIBRARY = $(_TCLDIR)\lib TCLREGLIB = "$(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib" TCLDDELIB = "$(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib" COFFBASE = \must\have\tcl\sources\to\build\this\target TCLTOOLSDIR = \must\have\tcl\sources\to\build\this\target TCL_INCLUDES = -I"$(_TCLDIR)\include" !else TCLSH = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe" !if !exist($(TCLSH)) && $(TCL_THREADS) TCLSH = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe" !endif TCLSTUBLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib" TCLIMPLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib" TCL_LIBRARY = $(_TCLDIR)\library TCLREGLIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib" TCLDDELIB = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib" COFFBASE = "$(_TCLDIR)\win\coffbase.txt" TCLTOOLSDIR = $(_TCLDIR)\tools TCL_INCLUDES = -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win" !endif !endif #------------------------------------------------------------------------- # Locate the Tk headers to build against #------------------------------------------------------------------------- !if "$(PROJECT)" == "tk" _TK_H = ..\generic\tk.h _INSTALLDIR = $(_INSTALLDIR)\.. !endif !ifdef PROJECT_REQUIRES_TK !if !defined(TKDIR) !if exist("$(_INSTALLDIR)\..\include\tk.h") TKINSTALL = 1 _TKDIR = $(_INSTALLDIR)\.. _TK_H = $(_TKDIR)\include\tk.h TKDIR = $(_TKDIR) !elseif exist("$(_TCLDIR)\include\tk.h") TKINSTALL = 1 _TKDIR = $(_TCLDIR) _TK_H = $(_TKDIR)\include\tk.h TKDIR = $(_TKDIR) !endif !else _TKDIR = $(TKDIR:/=\) !if exist("$(_TKDIR)\include\tk.h") TKINSTALL = 1 _TK_H = $(_TKDIR)\include\tk.h !elseif exist("$(_TKDIR)\generic\tk.h") TKINSTALL = 0 _TK_H = $(_TKDIR)\generic\tk.h !else MSG =^ Failed to find tk.h. The TKDIR macro does not appear correct. !error $(MSG) !endif !endif !endif #------------------------------------------------------------------------- # Extract Tk version numbers #------------------------------------------------------------------------- !if defined(PROJECT_REQUIRES_TK) || "$(PROJECT)" == "tk" !if [echo TK_MAJOR_VERSION = \>> versions.vc] \ && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc] !endif !if [echo TK_MINOR_VERSION = \>> versions.vc] \ && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc] !endif !if [echo TK_PATCH_LEVEL = \>> versions.vc] \ && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc] !endif !include versions.vc TK_DOTVERSION = $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION) TK_VERSION = $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION) !if "$(PROJECT)" != "tk" !if $(TKINSTALL) WISH = "$(_TKDIR)\bin\wish$(TK_VERSION)$(SUFX).exe" TKSTUBLIB = "$(_TKDIR)\lib\tkstub$(TK_VERSION).lib" TKIMPLIB = "$(_TKDIR)\lib\tk$(TK_VERSION)$(SUFX).lib" TK_INCLUDES = -I"$(_TKDIR)\include" !else WISH = "$(_TKDIR)\win\$(BUILDDIRTOP)\wish$(TCL_VERSION)$(SUFX).exe" TKSTUBLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tkstub$(TCL_VERSION).lib" TKIMPLIB = "$(_TKDIR)\win\$(BUILDDIRTOP)\tk$(TCL_VERSION)$(SUFX).lib" TK_INCLUDES = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib" !endif !endif !endif #---------------------------------------------------------- # Display stats being used. #---------------------------------------------------------- !message *** Intermediate directory will be '$(TMP_DIR)' !message *** Output directory will be '$(OUT_DIR)' !message *** Suffix for binaries will be '$(SUFX)' !message *** Optional defines are '$(OPTDEFINES)' !message *** Compiler version $(VCVER). Target machine is $(MACHINE) !message *** Host architecture is $(NATIVE_ARCH) !message *** Compiler options '$(COMPILERFLAGS) $(OPTIMIZATIONS) $(DEBUGFLAGS) $(WARNINGS)' !message *** Link options '$(LINKERFLAGS)' !endif tcl8.6.5/win/tcl.m40000644000175000017500000011305112665173607013414 0ustar sergeisergei#------------------------------------------------------------------------ # SC_PATH_TCLCONFIG -- # # Locate the tclConfig.sh file and perform a sanity check on # the Tcl compile flags # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tcl=... # # Defines the following vars: # TCL_BIN_DIR Full path to the directory containing # the tclConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([SC_PATH_TCLCONFIG], [ # # Ok, lets find the tcl configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tcl # if test x"${no_tcl}" = x ; then # we reset no_tcl in case something fails here no_tcl=true AC_ARG_WITH(tcl, AC_HELP_STRING([--with-tcl], [directory containing tcl configuration (tclConfig.sh)]), with_tclconfig="${withval}") AC_MSG_CHECKING([for Tcl configuration]) AC_CACHE_VAL(ac_cv_c_tclconfig,[ # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then case "${with_tclconfig}" in */tclConfig.sh ) if test -f "${with_tclconfig}"; then AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself]) with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" fi ;; esac if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" else AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tcl \ `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tcl \ `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /cygdrive/c/Tcl/lib 2>/dev/null` \ `ls -d /cygdrive/c/Progra~1/Tcl/lib 2>/dev/null` \ `ls -d /c/Tcl/lib 2>/dev/null` \ `ls -d /c/Progra~1/Tcl/lib 2>/dev/null` \ `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ${srcdir}/../tcl \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # SC_PATH_TKCONFIG -- # # Locate the tkConfig.sh file # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tk=... # # Defines the following vars: # TK_BIN_DIR Full path to the directory containing # the tkConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([SC_PATH_TKCONFIG], [ # # Ok, lets find the tk configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tk # if test x"${no_tk}" = x ; then # we reset no_tk in case something fails here no_tk=true AC_ARG_WITH(tk, AC_HELP_STRING([--with-tk], [directory containing tk configuration (tkConfig.sh)]), with_tkconfig="${withval}") AC_MSG_CHECKING([for Tk configuration]) AC_CACHE_VAL(ac_cv_c_tkconfig,[ # First check to see if --with-tkconfig was specified. if test x"${with_tkconfig}" != x ; then case "${with_tkconfig}" in */tkConfig.sh ) if test -f "${with_tkconfig}"; then AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself]) with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" fi ;; esac if test -f "${with_tkconfig}/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" else AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) fi fi # then check for a private Tk library if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ../tk \ `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tk \ `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tk \ `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/win/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/win; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /cygdrive/c/Tcl/lib 2>/dev/null` \ `ls -d /cygdrive/c/Progra~1/Tcl/lib 2>/dev/null` \ `ls -d /c/Tcl/lib 2>/dev/null` \ `ls -d /c/Progra~1/Tcl/lib 2>/dev/null` \ `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ${srcdir}/../tk \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/win/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/win; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tkconfig}" = x ; then TK_BIN_DIR="# no Tk configs found" AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) else no_tk= TK_BIN_DIR="${ac_cv_c_tkconfig}" AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # SC_LOAD_TCLCONFIG -- # # Load the tclConfig.sh file. # # Arguments: # # Requires the following vars to be set: # TCL_BIN_DIR # # Results: # # Substitutes the following vars: # TCL_BIN_DIR # TCL_SRC_DIR # TCL_LIB_FILE # #------------------------------------------------------------------------ AC_DEFUN([SC_LOAD_TCLCONFIG], [ AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh]) if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then AC_MSG_RESULT([loading]) . "${TCL_BIN_DIR}/tclConfig.sh" else AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh]) fi # # If the TCL_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TCL_LIB_SPEC will be set to the value # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC # instead of TCL_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. # if test -f $TCL_BIN_DIR/Makefile ; then TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC} TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC} TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH} fi # # eval is required to do the TCL_DBGX substitution # eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" AC_SUBST(TCL_VERSION) AC_SUBST(TCL_BIN_DIR) AC_SUBST(TCL_SRC_DIR) AC_SUBST(TCL_LIB_FILE) AC_SUBST(TCL_LIB_FLAG) AC_SUBST(TCL_LIB_SPEC) AC_SUBST(TCL_STUB_LIB_FILE) AC_SUBST(TCL_STUB_LIB_FLAG) AC_SUBST(TCL_STUB_LIB_SPEC) AC_SUBST(TCL_DEFS) ]) #------------------------------------------------------------------------ # SC_LOAD_TKCONFIG -- # # Load the tkConfig.sh file # # Arguments: # # Requires the following vars to be set: # TK_BIN_DIR # # Results: # # Sets the following vars that should be in tkConfig.sh: # TK_BIN_DIR #------------------------------------------------------------------------ AC_DEFUN([SC_LOAD_TKCONFIG], [ AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh]) if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then AC_MSG_RESULT([loading]) . "${TK_BIN_DIR}/tkConfig.sh" else AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh]) fi AC_SUBST(TK_BIN_DIR) AC_SUBST(TK_SRC_DIR) AC_SUBST(TK_LIB_FILE) ]) #------------------------------------------------------------------------ # SC_ENABLE_SHARED -- # # Allows the building of shared libraries # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-shared=yes|no # # Defines the following vars: # STATIC_BUILD Used for building import/export libraries # on Windows. # # Sets the following vars: # SHARED_BUILD Value of 1 or 0 #------------------------------------------------------------------------ AC_DEFUN([SC_ENABLE_SHARED], [ AC_MSG_CHECKING([how to build libraries]) AC_ARG_ENABLE(shared, [ --enable-shared build and link with shared libraries (default: on)], [tcl_ok=$enableval], [tcl_ok=yes]) if test "${enable_shared+set}" = set; then enableval="$enable_shared" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" ; then AC_MSG_RESULT([shared]) SHARED_BUILD=1 else AC_MSG_RESULT([static]) SHARED_BUILD=0 AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?]) fi ]) #------------------------------------------------------------------------ # SC_ENABLE_THREADS -- # # Specify if thread support should be enabled # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-threads=yes|no # # Defines the following vars: # TCL_THREADS #------------------------------------------------------------------------ AC_DEFUN([SC_ENABLE_THREADS], [ AC_MSG_CHECKING(for building with threads) AC_ARG_ENABLE(threads, [ --enable-threads build with threads (default: on)], [tcl_ok=$enableval], [tcl_ok=yes]) if test "$tcl_ok" = "yes"; then AC_MSG_RESULT([yes (default)]) TCL_THREADS=1 AC_DEFINE(TCL_THREADS) # USE_THREAD_ALLOC tells us to try the special thread-based # allocator that significantly reduces lock contention AC_DEFINE(USE_THREAD_ALLOC) else TCL_THREADS=0 AC_MSG_RESULT(no) fi AC_SUBST(TCL_THREADS) ]) #------------------------------------------------------------------------ # SC_ENABLE_SYMBOLS -- # # Specify if debugging symbols should be used. # Memory (TCL_MEM_DEBUG) and compile (TCL_COMPILE_DEBUG) debugging # can also be enabled. # # Arguments: # none # # Requires the following vars to be set in the Makefile: # CFLAGS_DEBUG # CFLAGS_OPTIMIZE # # Results: # # Adds the following arguments to configure: # --enable-symbols # # Defines the following vars: # CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true # Sets to $(CFLAGS_OPTIMIZE) if false # LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true # Sets to $(LDFLAGS_OPTIMIZE) if false # DBGX Debug library extension # #------------------------------------------------------------------------ AC_DEFUN([SC_ENABLE_SYMBOLS], [ AC_MSG_CHECKING([for build with symbols]) AC_ARG_ENABLE(symbols, [ --enable-symbols build with debugging symbols (default: off)], [tcl_ok=$enableval], [tcl_ok=no]) # FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT. if test "$tcl_ok" = "no"; then CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)' LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)' DBGX="" AC_DEFINE(NDEBUG, 1, [Is no debugging enabled?]) AC_MSG_RESULT([no]) AC_DEFINE(TCL_CFG_OPTIMIZED) else CFLAGS_DEFAULT='$(CFLAGS_DEBUG)' LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)' DBGX=g if test "$tcl_ok" = "yes"; then AC_MSG_RESULT([yes (standard debugging)]) fi fi AC_SUBST(CFLAGS_DEFAULT) AC_SUBST(LDFLAGS_DEFAULT) if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?]) fi if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then AC_DEFINE(TCL_COMPILE_DEBUG, 1, [Is bytecode debugging enabled?]) AC_DEFINE(TCL_COMPILE_STATS, 1, [Are bytecode statistics enabled?]) fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then AC_MSG_RESULT([enabled symbols mem compile debugging]) else AC_MSG_RESULT([enabled $tcl_ok debugging]) fi fi ]) #-------------------------------------------------------------------- # SC_CONFIG_CFLAGS # # Try to determine the proper flags to pass to the compiler # for building shared libraries and other such nonsense. # # NOTE: The backslashes in quotes below are substituted twice # due to the fact that they are in a macro and then inlined # in the final configure script. # # Arguments: # none # # Results: # # Can the following vars: # EXTRA_CFLAGS # CFLAGS_DEBUG # CFLAGS_OPTIMIZE # CFLAGS_WARNING # LDFLAGS_DEBUG # LDFLAGS_OPTIMIZE # LDFLAGS_CONSOLE # LDFLAGS_WINDOW # CC_OBJNAME # CC_EXENAME # CYGPATH # STLIB_LD # SHLIB_LD # SHLIB_LD_LIBS # LIBS # AR # RC # RES # # MAKE_LIB # MAKE_STUB_LIB # MAKE_EXE # MAKE_DLL # # LIBSUFFIX # LIBFLAGSUFFIX # LIBPREFIX # LIBRARIES # EXESUFFIX # DLLSUFFIX # #-------------------------------------------------------------------- AC_DEFUN([SC_CONFIG_CFLAGS], [ # Step 0: Enable 64 bit support? AC_MSG_CHECKING([if 64bit support is requested]) AC_ARG_ENABLE(64bit,[ --enable-64bit enable 64bit support (where applicable)], [do64bit=$enableval], [do64bit=no]) AC_MSG_RESULT($do64bit) # Cross-compiling options for Windows/CE builds AC_MSG_CHECKING([if Windows/CE build is requested]) AC_ARG_ENABLE(wince,[ --enable-wince enable Win/CE support (where applicable)], [doWince=$enableval], [doWince=no]) AC_MSG_RESULT($doWince) AC_MSG_CHECKING([for Windows/CE celib directory]) AC_ARG_WITH(celib,[ --with-celib=DIR use Windows/CE support library from DIR], CELIB_DIR=$withval, CELIB_DIR=NO_CELIB) AC_MSG_RESULT([$CELIB_DIR]) # Set some defaults (may get changed below) EXTRA_CFLAGS="" AC_DEFINE(MODULE_SCOPE, [extern], [No need to mark inidividual symbols as hidden]) AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo) SHLIB_SUFFIX=".dll" # MACHINE is IX86 for LINK, but this is used by the manifest, # which requires x86|amd64|ia64. MACHINE="X86" if test "$GCC" = "yes"; then AC_CACHE_CHECK(for cross-compile version of gcc, ac_cv_cross, AC_TRY_COMPILE([ #ifndef _WIN32 #error cross-compiler #endif ], [], ac_cv_cross=no, ac_cv_cross=yes) ) if test "$ac_cv_cross" = "yes"; then case "$do64bit" in amd64|x64|yes) CC="x86_64-w64-mingw32-gcc" LD="x86_64-w64-mingw32-ld" AR="x86_64-w64-mingw32-ar" RANLIB="x86_64-w64-mingw32-ranlib" RC="x86_64-w64-mingw32-windres" ;; *) CC="i686-w64-mingw32-gcc" LD="i686-w64-mingw32-ld" AR="i686-w64-mingw32-ar" RANLIB="i686-w64-mingw32-ranlib" RC="i686-w64-mingw32-windres" ;; esac fi fi # Check for a bug in gcc's windres that causes the # compile to fail when a Windows native path is # passed into windres. The mingw toolchain requires # Windows native paths while Cygwin should work # with both. Avoid the bug by passing a POSIX # path when using the Cygwin toolchain. if test "$GCC" = "yes" && test "$CYGPATH" != "echo" ; then conftest=/tmp/conftest.rc echo "STRINGTABLE BEGIN" > $conftest echo "101 \"name\"" >> $conftest echo "END" >> $conftest AC_MSG_CHECKING([for Windows native path bug in windres]) cyg_conftest=`$CYGPATH $conftest` if AC_TRY_COMMAND($RC -o conftest.res.o $cyg_conftest) ; then AC_MSG_RESULT([no]) else AC_MSG_RESULT([yes]) CYGPATH=echo fi conftest= cyg_conftest= fi if test "$CYGPATH" = "echo"; then DEPARG='"$<"' else DEPARG='"$(shell $(CYGPATH) $<)"' fi # set various compiler flags depending on whether we are using gcc or cl if test "${GCC}" = "yes" ; then extra_cflags="-pipe" extra_ldflags="-pipe -static-libgcc" AC_CACHE_CHECK(for mingw32 version of gcc, ac_cv_win32, AC_TRY_COMPILE([ #ifdef _WIN32 #error win32 #endif ], [], ac_cv_win32=no, ac_cv_win32=yes) ) if test "$ac_cv_win32" != "yes"; then AC_MSG_ERROR([${CC} cannot produce win32 executables.]) fi hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -mwindows -municode -Dmain=xxmain" AC_CACHE_CHECK(for working -municode linker flag, ac_cv_municode, AC_TRY_LINK([ #include int APIENTRY wWinMain(HINSTANCE a, HINSTANCE b, LPWSTR c, int d) {return 0;} ], [], ac_cv_municode=yes, ac_cv_municode=no) ) CFLAGS=$hold_cflags if test "$ac_cv_municode" = "yes" ; then extra_ldflags="$extra_ldflags -municode" else extra_cflags="$extra_cflags -DTCL_BROKEN_MAINARGS" fi fi AC_MSG_CHECKING([compiler flags]) if test "${GCC}" = "yes" ; then SHLIB_LD="" SHLIB_LD_LIBS='${LIBS}' LIBS="-lnetapi32 -lkernel32 -luser32 -ladvapi32 -luserenv -lws2_32" # mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32" STLIB_LD='${AR} cr' RC_OUT=-o RC_TYPE= RC_INCLUDE=--include RC_DEFINE=--define RES=res.o MAKE_LIB="\${STLIB_LD} \[$]@" MAKE_STUB_LIB="\${STLIB_LD} \[$]@" POST_MAKE_LIB="\${RANLIB} \[$]@" MAKE_EXE="\${CC} -o \[$]@" LIBPREFIX="lib" if test "${SHARED_BUILD}" = "0" ; then # static AC_MSG_RESULT([using static flags]) runtime= LIBRARIES="\${STATIC_LIBRARIES}" EXESUFFIX="s\${DBGX}.exe" else # dynamic AC_MSG_RESULT([using shared flags]) # ad-hoc check to see if CC supports -shared. if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then AC_MSG_ERROR([${CC} does not support the -shared option. You will need to upgrade to a newer version of the toolchain.]) fi runtime= # Add SHLIB_LD_LIBS to the Make rule, not here. EXESUFFIX="\${DBGX}.exe" LIBRARIES="\${SHARED_LIBRARIES}" fi # Link with gcc since ld does not link to default libs like # -luser32 and -lmsvcrt by default. SHLIB_LD='${CC} -shared' SHLIB_LD_LIBS='${LIBS}' MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \[$]@ ${extra_ldflags} \ -Wl,--out-implib,\$(patsubst %.dll,lib%.a,\[$]@)" # DLLSUFFIX is separate because it is the building block for # users of tclConfig.sh that may build shared or static. DLLSUFFIX="\${DBGX}.dll" LIBSUFFIX="\${DBGX}.a" LIBFLAGSUFFIX="\${DBGX}" SHLIB_SUFFIX=.dll EXTRA_CFLAGS="${extra_cflags}" CFLAGS_DEBUG=-g CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" CFLAGS_WARNING="-Wall -Wdeclaration-after-statement" LDFLAGS_DEBUG= LDFLAGS_OPTIMIZE= # Specify the CC output file names based on the target name CC_OBJNAME="-o \[$]@" CC_EXENAME="-o \[$]@" # Specify linker flags depending on the type of app being # built -- Console vs. Window. # # ORIGINAL COMMENT: # We need to pass -e _WinMain@16 so that ld will use # WinMain() instead of main() as the entry point. We can't # use autoconf to check for this case since it would need # to run an executable and that does not work when # cross compiling. Remove this -e workaround once we # require a gcc that does not have this bug. # # MK NOTE: Tk should use a different mechanism. This causes # interesting problems, such as wish dying at startup. #LDFLAGS_WINDOW="-mwindows -e _WinMain@16 ${extra_ldflags}" LDFLAGS_CONSOLE="-mconsole ${extra_ldflags}" LDFLAGS_WINDOW="-mwindows ${extra_ldflags}" case "$do64bit" in amd64|x64|yes) MACHINE="AMD64" ; # assume AMD64 as default 64-bit build AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) ;; ia64) MACHINE="IA64" AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) ;; *) AC_TRY_COMPILE([ #ifndef _WIN64 #error 32-bit #endif ], [], tcl_win_64bit=yes, tcl_win_64bit=no ) if test "$tcl_win_64bit" = "yes" ; then do64bit=amd64 MACHINE="AMD64" AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) fi ;; esac else if test "${SHARED_BUILD}" = "0" ; then # static AC_MSG_RESULT([using static flags]) runtime=-MT LIBRARIES="\${STATIC_LIBRARIES}" EXESUFFIX="s\${DBGX}.exe" else # dynamic AC_MSG_RESULT([using shared flags]) runtime=-MD # Add SHLIB_LD_LIBS to the Make rule, not here. LIBRARIES="\${SHARED_LIBRARIES}" EXESUFFIX="\${DBGX}.exe" case "x`echo \${VisualStudioVersion}`" in x1[[4-9]]*) lflags="${lflags} -nodefaultlib:libucrt.lib" ;; *) ;; esac fi MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\[$]@" # DLLSUFFIX is separate because it is the building block for # users of tclConfig.sh that may build shared or static. DLLSUFFIX="\${DBGX}.dll" LIBSUFFIX="\${DBGX}.lib" LIBFLAGSUFFIX="\${DBGX}" # This is a 2-stage check to make sure we have the 64-bit SDK # We have to know where the SDK is installed. # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs if test "$do64bit" != "no" ; then if test "x${MSSDK}x" = "xx" ; then MSSDK="C:/Progra~1/Microsoft Platform SDK" fi MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'` PATH64="" case "$do64bit" in amd64|x64|yes) MACHINE="AMD64" ; # assume AMD64 as default 64-bit build PATH64="${MSSDK}/Bin/Win64/x86/AMD64" ;; ia64) MACHINE="IA64" PATH64="${MSSDK}/Bin/Win64" ;; esac if test ! -d "${PATH64}" ; then AC_MSG_WARN([Could not find 64-bit $MACHINE SDK]) fi AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) fi LIBS="netapi32.lib kernel32.lib user32.lib advapi32.lib userenv.lib ws2_32.lib" case "x`echo \${VisualStudioVersion}`" in x1[[4-9]]*) LIBS="$LIBS ucrt.lib" ;; *) ;; esac if test "$do64bit" != "no" ; then # The space-based-path will work for the Makefile, but will # not work if AC_TRY_COMPILE is called. TEA has the # TEA_PATH_NOSPACE to avoid this issue. # Check if _WIN64 is already recognized, and if so we don't # need to modify CC. AC_CHECK_DECL([_WIN64], [], [CC="\"${PATH64}/cl.exe\" -I\"${MSSDK}/Include\" \ -I\"${MSSDK}/Include/crt\" \ -I\"${MSSDK}/Include/crt/sys\""]) RC="\"${MSSDK}/bin/rc.exe\"" CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d" # Do not use -O2 for Win64 - this has proved buggy in code gen. CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}" lflags="${lflags} -nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\"" LINKBIN="\"${PATH64}/link.exe\"" # Avoid 'unresolved external symbol __security_cookie' errors. # c.f. http://support.microsoft.com/?id=894573 LIBS="$LIBS bufferoverflowU.lib" else RC="rc" # -Od - no optimization # -WX - warnings as errors CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d" # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy) CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}" lflags="${lflags} -nologo" LINKBIN="link" fi if test "$doWince" != "no" ; then # Set defaults for common evc4/PPC2003 setup # Currently Tcl requires 300+, possibly 420+ for sockets CEVERSION=420; # could be 211 300 301 400 420 ... TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ... ARCH=ARM; # could be ARM MIPS X86EM ... PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002" if test "$doWince" != "yes"; then # If !yes then the user specified something # Reset ARCH to allow user to skip specifying it ARCH= eval `echo $doWince | awk -F "," '{ \ if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \ if ([$]1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \ if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \ if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \ if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \ }'` if test "x${ARCH}" = "x" ; then ARCH=$TARGETCPU; fi fi OSVERSION=WCE$CEVERSION; if test "x${WCEROOT}" = "x" ; then WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0" if test ! -d "${WCEROOT}" ; then WCEROOT="C:/Program Files/Microsoft eMbedded Tools" fi fi if test "x${SDKROOT}" = "x" ; then SDKROOT="C:/Program Files/Windows CE Tools" if test ! -d "${SDKROOT}" ; then SDKROOT="C:/Windows CE Tools" fi fi # The space-based-path will work for the Makefile, but will # not work if AC_TRY_COMPILE is called. WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'` SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'` CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` if test ! -d "${CELIB_DIR}/inc"; then AC_MSG_ERROR([Invalid celib directory "${CELIB_DIR}"]) fi if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"\ -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]]) else CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include" if test -d "${CEINCLUDE}/${TARGETCPU}" ; then CEINCLUDE="${CEINCLUDE}/${TARGETCPU}" fi CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" fi fi if test "$doWince" != "no" ; then CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin" if test "${TARGETCPU}" = "X86"; then CC="${CEBINROOT}/cl.exe" else CC="${CEBINROOT}/cl${ARCH}.exe" fi CC="\"${CC}\" -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\"" RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" arch=`echo ${ARCH} | awk '{print tolower([$]0)}'` defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _DLL _WINDOWS" for i in $defs ; do AC_DEFINE_UNQUOTED($i) done # if test "${ARCH}" = "X86EM"; then # AC_DEFINE_UNQUOTED(_WIN32_WCE_EMULATION) # fi AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION) AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION) CFLAGS_DEBUG="-nologo -Zi -Od" CFLAGS_OPTIMIZE="-nologo -O2" lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'` lflags="-nodefaultlib -MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" LINKBIN="\"${CEBINROOT}/link.exe\"" AC_SUBST(CELIB_DIR) if test "${CEVERSION}" -lt 400 ; then LIBS="coredll.lib corelibc.lib winsock.lib" else LIBS="coredll.lib corelibc.lib ws2.lib" fi # celib currently stuck at wce300 status #LIBS="$LIBS \${CELIB_DIR}/wince-${ARCH}-pocket-${OSVERSION}-release/celib.lib" LIBS="$LIBS \"\${CELIB_DIR}/wince-${ARCH}-pocket-wce300-release/celib.lib\"" LIBS_GUI="commctrl.lib commdlg.lib" else LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib" fi SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}" SHLIB_LD_LIBS='${LIBS}' # link -lib only works when -lib is the first arg STLIB_LD="${LINKBIN} -lib ${lflags}" RC_OUT=-fo RC_TYPE=-r RC_INCLUDE=-i RC_DEFINE=-d RES=res MAKE_LIB="\${STLIB_LD} -out:\[$]@" MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@" POST_MAKE_LIB= MAKE_EXE="\${CC} -Fe\[$]@" LIBPREFIX="" CFLAGS_DEBUG="${CFLAGS_DEBUG} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE" CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE" EXTRA_CFLAGS="" CFLAGS_WARNING="-W3" LDFLAGS_DEBUG="-debug" LDFLAGS_OPTIMIZE="-release" # Specify the CC output file names based on the target name CC_OBJNAME="-Fo\[$]@" CC_EXENAME="-Fe\"\$(shell \$(CYGPATH) '\[$]@')\"" # Specify linker flags depending on the type of app being # built -- Console vs. Window. if test "$doWince" != "no" -a "${TARGETCPU}" != "X86"; then LDFLAGS_CONSOLE="-link ${lflags}" LDFLAGS_WINDOW=${LDFLAGS_CONSOLE} else LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" fi fi if test "$do64bit" != "no" ; then AC_DEFINE(TCL_CFG_DO64BIT) fi if test "${GCC}" = "yes" ; then AC_CACHE_CHECK(for SEH support in compiler, tcl_cv_seh, AC_TRY_RUN([ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main(int argc, char** argv) { int a, b = 0; __try { a = 666 / b; } __except (EXCEPTION_EXECUTE_HANDLER) { return 0; } return 1; } ], tcl_cv_seh=yes, tcl_cv_seh=no, tcl_cv_seh=no) ) if test "$tcl_cv_seh" = "no" ; then AC_DEFINE(HAVE_NO_SEH, 1, [Defined when mingw does not support SEH]) fi # # Check to see if the excpt.h include file provided contains the # definition for EXCEPTION_DISPOSITION; if not, which is the case # with Cygwin's version as of 2002-04-10, define it to be int, # sufficient for getting the current code to work. # AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files, tcl_cv_eh_disposition, AC_TRY_COMPILE([ # define WIN32_LEAN_AND_MEAN # include # undef WIN32_LEAN_AND_MEAN ],[ EXCEPTION_DISPOSITION x; ], tcl_cv_eh_disposition=yes, tcl_cv_eh_disposition=no) ) if test "$tcl_cv_eh_disposition" = "no" ; then AC_DEFINE(EXCEPTION_DISPOSITION, int, [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION]) fi # Check to see if winnt.h defines CHAR, SHORT, and LONG # even if VOID has already been #defined. The win32api # used by mingw and cygwin is known to do this. AC_CACHE_CHECK(for winnt.h that ignores VOID define, tcl_cv_winnt_ignore_void, AC_TRY_COMPILE([ #define VOID void #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN ], [ CHAR c; SHORT s; LONG l; ], tcl_cv_winnt_ignore_void=yes, tcl_cv_winnt_ignore_void=no) ) if test "$tcl_cv_winnt_ignore_void" = "yes" ; then AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1, [Defined when cygwin/mingw ignores VOID define in winnt.h]) fi # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. AC_CACHE_CHECK(for cast to union support, tcl_cv_cast_to_union, AC_TRY_COMPILE([], [ union foo { int i; double d; }; union foo f = (union foo) (int) 0; ], tcl_cv_cast_to_union=yes, tcl_cv_cast_to_union=no) ) if test "$tcl_cv_cast_to_union" = "yes"; then AC_DEFINE(HAVE_CAST_TO_UNION, 1, [Defined when compiler supports casting to union type.]) fi fi # DL_LIBS is empty, but then we match the Unix version AC_SUBST(DL_LIBS) AC_SUBST(CFLAGS_DEBUG) AC_SUBST(CFLAGS_OPTIMIZE) AC_SUBST(CFLAGS_WARNING) ]) #------------------------------------------------------------------------ # SC_WITH_TCL -- # # Location of the Tcl build directory. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tcl=... # # Defines the following vars: # TCL_BIN_DIR Full path to the tcl build dir. #------------------------------------------------------------------------ AC_DEFUN([SC_WITH_TCL], [ if test -d ../../tcl8.6$1/win; then TCL_BIN_DEFAULT=../../tcl8.6$1/win else TCL_BIN_DEFAULT=../../tcl8.6/win fi AC_ARG_WITH(tcl, [ --with-tcl=DIR use Tcl 8.6 binaries from DIR], TCL_BIN_DIR=$withval, TCL_BIN_DIR=`cd $TCL_BIN_DEFAULT; pwd`) if test ! -d $TCL_BIN_DIR; then AC_MSG_ERROR(Tcl directory $TCL_BIN_DIR does not exist) fi if test ! -f $TCL_BIN_DIR/Makefile; then AC_MSG_ERROR(There is no Makefile in $TCL_BIN_DIR: perhaps you did not specify the Tcl *build* directory (not the toplevel Tcl directory) or you forgot to configure Tcl?) else echo "building against Tcl binaries in: $TCL_BIN_DIR" fi AC_SUBST(TCL_BIN_DIR) ]) #------------------------------------------------------------------------ # SC_PROG_TCLSH # Locate a tclsh shell installed on the system path. This macro # will only find a Tcl shell that already exists on the system. # It will not find a Tcl shell in the Tcl build directory or # a Tcl shell that has been installed from the Tcl build directory. # If a Tcl shell can't be located on the PATH, then TCLSH_PROG will # be set to "". Extensions should take care not to create Makefile # rules that are run by default and depend on TCLSH_PROG. An # extension can't assume that an executable Tcl shell exists at # build time. # # Arguments # none # # Results # Subst's the following values: # TCLSH_PROG #------------------------------------------------------------------------ AC_DEFUN([SC_PROG_TCLSH], [ AC_MSG_CHECKING([for tclsh]) AC_CACHE_VAL(ac_cv_path_tclsh, [ search_path=`echo ${PATH} | sed -e 's/:/ /g'` for dir in $search_path ; do for j in `ls -r $dir/tclsh[[8-9]]*.exe 2> /dev/null` \ `ls -r $dir/tclsh* 2> /dev/null` ; do if test x"$ac_cv_path_tclsh" = x ; then if test -f "$j" ; then ac_cv_path_tclsh=$j break fi fi done done ]) if test -f "$ac_cv_path_tclsh" ; then TCLSH_PROG="$ac_cv_path_tclsh" AC_MSG_RESULT($TCLSH_PROG) else # It is not an error if an installed version of Tcl can't be located. TCLSH_PROG="" AC_MSG_RESULT([No tclsh found on PATH]) fi AC_SUBST(TCLSH_PROG) ]) #------------------------------------------------------------------------ # SC_BUILD_TCLSH # Determine the fully qualified path name of the tclsh executable # in the Tcl build directory. This macro will correctly determine # the name of the tclsh executable even if tclsh has not yet # been built in the build directory. The build tclsh must be used # when running tests from an extension build directory. It is not # correct to use the TCLSH_PROG in cases like this. # # Arguments # none # # Results # Subst's the following values: # BUILD_TCLSH #------------------------------------------------------------------------ AC_DEFUN([SC_BUILD_TCLSH], [ AC_MSG_CHECKING([for tclsh in Tcl build directory]) BUILD_TCLSH=${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT} AC_MSG_RESULT($BUILD_TCLSH) AC_SUBST(BUILD_TCLSH) ]) #-------------------------------------------------------------------- # SC_TCL_CFG_ENCODING TIP #59 # # Declare the encoding to use for embedded configuration information. # # Arguments: # None. # # Results: # Might append to the following vars: # DEFS (implicit) # # Will define the following vars: # TCL_CFGVAL_ENCODING # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_CFG_ENCODING], [ AC_ARG_WITH(encoding, [ --with-encoding encoding for configuration values], with_tcencoding=${withval}) if test x"${with_tcencoding}" != x ; then AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}") else # Default encoding on windows is not "iso8859-1" AC_DEFINE(TCL_CFGVAL_ENCODING,"cp1252") fi ]) #-------------------------------------------------------------------- # SC_EMBED_MANIFEST # # Figure out if we can embed the manifest where necessary # # Arguments: # An optional manifest to merge into DLL/EXE. # # Results: # Will define the following vars: # VC_MANIFEST_EMBED_DLL # VC_MANIFEST_EMBED_EXE # #-------------------------------------------------------------------- AC_DEFUN([SC_EMBED_MANIFEST], [ AC_MSG_CHECKING(whether to embed manifest) AC_ARG_ENABLE(embedded-manifest, AC_HELP_STRING([--enable-embedded-manifest], [embed manifest if possible (default: yes)]), [embed_ok=$enableval], [embed_ok=yes]) VC_MANIFEST_EMBED_DLL= VC_MANIFEST_EMBED_EXE= result=no if test "$embed_ok" = "yes" -a "${SHARED_BUILD}" = "1" \ -a "$GCC" != "yes" ; then # Add the magic to embed the manifest into the dll/exe AC_EGREP_CPP([manifest needed], [ #if defined(_MSC_VER) && _MSC_VER >= 1400 print("manifest needed") #endif ], [ # Could do a CHECK_PROG for mt, but should always be with MSVC8+ # Could add 'if test -f' check, but manifest should be created # in this compiler case # Add in a manifest argument that may be specified # XXX Needs improvement so that the test for existence accounts # XXX for a provided (known) manifest VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest $1 -outputresource:\[$]@\;2 ; fi" VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest $1 -outputresource:\[$]@\;1 ; fi" result=yes if test "x$1" != x ; then result="yes ($1)" fi ]) fi AC_MSG_RESULT([$result]) AC_SUBST(VC_MANIFEST_EMBED_DLL) AC_SUBST(VC_MANIFEST_EMBED_EXE) ]) tcl8.6.5/win/tclWinConsole.c0000644000175000017500000011542312663660066015322 0ustar sergeisergei/* * tclWinConsole.c -- * * This file implements the Windows-specific console functions, and the * "console" channel driver. * * Copyright (c) 1999 by Scriptics Corp. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclWinInt.h" /* * The following variable is used to tell whether this module has been * initialized. */ static int initialized = 0; /* * The consoleMutex locks around access to the initialized variable, and it is * used to protect background threads from being terminated while they are * using APIs that hold locks. */ TCL_DECLARE_MUTEX(consoleMutex) /* * Bit masks used in the flags field of the ConsoleInfo structure below. */ #define CONSOLE_PENDING (1<<0) /* Message is pending in the queue. */ #define CONSOLE_ASYNC (1<<1) /* Channel is non-blocking. */ /* * Bit masks used in the sharedFlags field of the ConsoleInfo structure below. */ #define CONSOLE_EOF (1<<2) /* Console has reached EOF. */ #define CONSOLE_BUFFERED (1<<3) /* Data was read into a buffer by the reader * thread. */ #define CONSOLE_BUFFER_SIZE (8*1024) /* * Structure containing handles associated with one of the special console * threads. */ typedef struct ConsoleThreadInfo { HANDLE thread; /* Handle to reader or writer thread. */ HANDLE readyEvent; /* Manual-reset event to signal _to_ the main * thread when the worker thread has finished * waiting for its normal work to happen. */ HANDLE startEvent; /* Auto-reset event used by the main thread to * signal when the thread should attempt to do * its normal work. */ HANDLE stopEvent; /* Auto-reset event used by the main thread to * signal when the thread should exit. */ } ConsoleThreadInfo; /* * This structure describes per-instance data for a console based channel. */ typedef struct ConsoleInfo { HANDLE handle; int type; struct ConsoleInfo *nextPtr;/* Pointer to next registered console. */ Tcl_Channel channel; /* Pointer to channel structure. */ int validMask; /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which operations are valid on the file. */ int watchMask; /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which events should be reported. */ int flags; /* State flags, see above for a list. */ Tcl_ThreadId threadId; /* Thread to which events should be reported. * This value is used by the reader/writer * threads. */ ConsoleThreadInfo writer; /* A specialized thread for handling * asynchronous writes to the console; the * waiting starts when a start event is sent, * and a reset event is sent back to the main * thread when the write is done. A stop event * is used to terminate the thread. */ ConsoleThreadInfo reader; /* A specialized thread for handling * asynchronous reads from the console; the * waiting starts when a start event is sent, * and a reset event is sent back to the main * thread when input is available. A stop * event is used to terminate the thread. */ DWORD writeError; /* An error caused by the last background * write. Set to 0 if no error has been * detected. This word is shared with the * writer thread so access must be * synchronized with the writable object. */ char *writeBuf; /* Current background output buffer. Access is * synchronized with the writable object. */ int writeBufLen; /* Size of write buffer. Access is * synchronized with the writable object. */ int toWrite; /* Current amount to be written. Access is * synchronized with the writable object. */ int readFlags; /* Flags that are shared with the reader * thread. Access is synchronized with the * readable object. */ int bytesRead; /* Number of bytes in the buffer. */ int offset; /* Number of bytes read out of the buffer. */ char buffer[CONSOLE_BUFFER_SIZE]; /* Data consumed by reader thread. */ } ConsoleInfo; typedef struct ThreadSpecificData { /* * The following pointer refers to the head of the list of consoles that * are being watched for file events. */ ConsoleInfo *firstConsolePtr; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * The following structure is what is added to the Tcl event queue when * console events are generated. */ typedef struct ConsoleEvent { Tcl_Event header; /* Information that is standard for all * events. */ ConsoleInfo *infoPtr; /* Pointer to console info structure. Note * that we still have to verify that the * console exists before dereferencing this * pointer. */ } ConsoleEvent; /* * Declarations for functions used only in this file. */ static int ConsoleBlockModeProc(ClientData instanceData, int mode); static void ConsoleCheckProc(ClientData clientData, int flags); static int ConsoleCloseProc(ClientData instanceData, Tcl_Interp *interp); static int ConsoleEventProc(Tcl_Event *evPtr, int flags); static void ConsoleExitHandler(ClientData clientData); static int ConsoleGetHandleProc(ClientData instanceData, int direction, ClientData *handlePtr); static void ConsoleInit(void); static int ConsoleInputProc(ClientData instanceData, char *buf, int toRead, int *errorCode); static int ConsoleOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCode); static DWORD WINAPI ConsoleReaderThread(LPVOID arg); static void ConsoleSetupProc(ClientData clientData, int flags); static void ConsoleWatchProc(ClientData instanceData, int mask); static DWORD WINAPI ConsoleWriterThread(LPVOID arg); static void ProcExitHandler(ClientData clientData); static int WaitForRead(ConsoleInfo *infoPtr, int blocking); static void ConsoleThreadActionProc(ClientData instanceData, int action); static BOOL ReadConsoleBytes(HANDLE hConsole, LPVOID lpBuffer, DWORD nbytes, LPDWORD nbytesread); static BOOL WriteConsoleBytes(HANDLE hConsole, const void *lpBuffer, DWORD nbytes, LPDWORD nbyteswritten); static void StartChannelThread(ConsoleInfo *infoPtr, ConsoleThreadInfo *threadInfoPtr, LPTHREAD_START_ROUTINE threadProc); static void StopChannelThread(ConsoleThreadInfo *threadInfoPtr); /* * This structure describes the channel type structure for command console * based IO. */ static const Tcl_ChannelType consoleChannelType = { "console", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ ConsoleCloseProc, /* Close proc. */ ConsoleInputProc, /* Input proc. */ ConsoleOutputProc, /* Output proc. */ NULL, /* Seek proc. */ NULL, /* Set option proc. */ NULL, /* Get option proc. */ ConsoleWatchProc, /* Set up notifier to watch the channel. */ ConsoleGetHandleProc, /* Get an OS handle from channel. */ NULL, /* close2proc. */ ConsoleBlockModeProc, /* Set blocking or non-blocking mode. */ NULL, /* Flush proc. */ NULL, /* Handler proc. */ NULL, /* Wide seek proc. */ ConsoleThreadActionProc, /* Thread action proc. */ NULL /* Truncation proc. */ }; /* *---------------------------------------------------------------------- * * ReadConsoleBytes, WriteConsoleBytes -- * * Wrapper for ReadConsole{A,W}, that takes and returns number of bytes * instead of number of TCHARS. * *---------------------------------------------------------------------- */ static BOOL ReadConsoleBytes( HANDLE hConsole, LPVOID lpBuffer, DWORD nbytes, LPDWORD nbytesread) { DWORD ntchars; BOOL result; int tcharsize = sizeof(TCHAR); /* * If user types a Ctrl-Break or Ctrl-C, ReadConsole will return * success with ntchars == 0 and GetLastError() will be * ERROR_OPERATION_ABORTED. We do not want to treat this case * as EOF so we will loop around again. If no Ctrl signal handlers * have been established, the default signal OS handler in a separate * thread will terminate the program. If a Ctrl signal handler * has been established (through an extension for example), it * will run and take whatever action it deems appropriate. */ do { result = ReadConsole(hConsole, lpBuffer, nbytes / tcharsize, &ntchars, NULL); } while (result && ntchars == 0 && GetLastError() == ERROR_OPERATION_ABORTED); if (nbytesread != NULL) { *nbytesread = ntchars * tcharsize; } return result; } static BOOL WriteConsoleBytes( HANDLE hConsole, const void *lpBuffer, DWORD nbytes, LPDWORD nbyteswritten) { DWORD ntchars; BOOL result; int tcharsize = sizeof(TCHAR); result = WriteConsole(hConsole, lpBuffer, nbytes / tcharsize, &ntchars, NULL); if (nbyteswritten != NULL) { *nbyteswritten = ntchars * tcharsize; } return result; } /* *---------------------------------------------------------------------- * * ConsoleInit -- * * This function initializes the static variables for this file. * * Results: * None. * * Side effects: * Creates a new event source. * *---------------------------------------------------------------------- */ static void ConsoleInit(void) { /* * Check the initialized flag first, then check again in the mutex. This * is a speed enhancement. */ if (!initialized) { Tcl_MutexLock(&consoleMutex); if (!initialized) { initialized = 1; Tcl_CreateExitHandler(ProcExitHandler, NULL); } Tcl_MutexUnlock(&consoleMutex); } if (TclThreadDataKeyGet(&dataKey) == NULL) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); tsdPtr->firstConsolePtr = NULL; Tcl_CreateEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL); Tcl_CreateThreadExitHandler(ConsoleExitHandler, NULL); } } /* *---------------------------------------------------------------------- * * ConsoleExitHandler -- * * This function is called to cleanup the console module before Tcl is * unloaded. * * Results: * None. * * Side effects: * Removes the console event source. * *---------------------------------------------------------------------- */ static void ConsoleExitHandler( ClientData clientData) /* Old window proc. */ { Tcl_DeleteEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL); } /* *---------------------------------------------------------------------- * * ProcExitHandler -- * * This function is called to cleanup the process list before Tcl is * unloaded. * * Results: * None. * * Side effects: * Resets the process list. * *---------------------------------------------------------------------- */ static void ProcExitHandler( ClientData clientData) /* Old window proc. */ { Tcl_MutexLock(&consoleMutex); initialized = 0; Tcl_MutexUnlock(&consoleMutex); } /* *---------------------------------------------------------------------- * * ConsoleSetupProc -- * * This procedure is invoked before Tcl_DoOneEvent blocks waiting for an * event. * * Results: * None. * * Side effects: * Adjusts the block time if needed. * *---------------------------------------------------------------------- */ void ConsoleSetupProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { ConsoleInfo *infoPtr; Tcl_Time blockTime = { 0, 0 }; int block = 1; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } /* * Look to see if any events are already pending. If they are, poll. */ for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->watchMask & TCL_WRITABLE) { if (WaitForSingleObject(infoPtr->writer.readyEvent, 0) != WAIT_TIMEOUT) { block = 0; } } if (infoPtr->watchMask & TCL_READABLE) { if (WaitForRead(infoPtr, 0) >= 0) { block = 0; } } } if (!block) { Tcl_SetMaxBlockTime(&blockTime); } } /* *---------------------------------------------------------------------- * * ConsoleCheckProc -- * * This procedure is called by Tcl_DoOneEvent to check the console event * source for events. * * Results: * None. * * Side effects: * May queue an event. * *---------------------------------------------------------------------- */ static void ConsoleCheckProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { ConsoleInfo *infoPtr; int needEvent; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } /* * Queue events for any ready consoles that don't already have events * queued. */ for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->flags & CONSOLE_PENDING) { continue; } /* * Queue an event if the console is signaled for reading or writing. */ needEvent = 0; if (infoPtr->watchMask & TCL_WRITABLE) { if (WaitForSingleObject(infoPtr->writer.readyEvent, 0) != WAIT_TIMEOUT) { needEvent = 1; } } if (infoPtr->watchMask & TCL_READABLE) { if (WaitForRead(infoPtr, 0) >= 0) { needEvent = 1; } } if (needEvent) { ConsoleEvent *evPtr = ckalloc(sizeof(ConsoleEvent)); infoPtr->flags |= CONSOLE_PENDING; evPtr->header.proc = ConsoleEventProc; evPtr->infoPtr = infoPtr; Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL); } } } /* *---------------------------------------------------------------------- * * ConsoleBlockModeProc -- * * Set blocking or non-blocking mode on channel. * * Results: * 0 if successful, errno when failed. * * Side effects: * Sets the device into blocking or non-blocking mode. * *---------------------------------------------------------------------- */ static int ConsoleBlockModeProc( ClientData instanceData, /* Instance data for channel. */ int mode) /* TCL_MODE_BLOCKING or * TCL_MODE_NONBLOCKING. */ { ConsoleInfo *infoPtr = instanceData; /* * Consoles on Windows can not be switched between blocking and * nonblocking, hence we have to emulate the behavior. This is done in the * input function by checking against a bit in the state. We set or unset * the bit here to cause the input function to emulate the correct * behavior. */ if (mode == TCL_MODE_NONBLOCKING) { infoPtr->flags |= CONSOLE_ASYNC; } else { infoPtr->flags &= ~CONSOLE_ASYNC; } return 0; } /* *---------------------------------------------------------------------- * * StartChannelThread, StopChannelThread -- * * Helpers that codify how to ask one of the console service threads to * start and stop. * *---------------------------------------------------------------------- */ static void StartChannelThread( ConsoleInfo *infoPtr, ConsoleThreadInfo *threadInfoPtr, LPTHREAD_START_ROUTINE threadProc) { DWORD id; threadInfoPtr->readyEvent = CreateEvent(NULL, TRUE, TRUE, NULL); threadInfoPtr->startEvent = CreateEvent(NULL, FALSE, FALSE, NULL); threadInfoPtr->stopEvent = CreateEvent(NULL, FALSE, FALSE, NULL); threadInfoPtr->thread = CreateThread(NULL, 256, threadProc, infoPtr, 0, &id); SetThreadPriority(threadInfoPtr->thread, THREAD_PRIORITY_HIGHEST); } static void StopChannelThread( ConsoleThreadInfo *threadInfoPtr) { DWORD exitCode = 0; /* * The thread may already have closed on it's own. Check it's exit * code. */ GetExitCodeThread(threadInfoPtr->thread, &exitCode); if (exitCode == STILL_ACTIVE) { /* * Set the stop event so that if the reader thread is blocked in * ConsoleReaderThread on WaitForMultipleEvents, it will exit cleanly. */ SetEvent(threadInfoPtr->stopEvent); /* * Wait at most 20 milliseconds for the reader thread to close. */ if (WaitForSingleObject(threadInfoPtr->thread, 20) == WAIT_TIMEOUT) { /* * Forcibly terminate the background thread as a last resort. * Note that we need to guard against terminating the thread while * it is in the middle of Tcl_ThreadAlert because it won't be able * to release the notifier lock. */ Tcl_MutexLock(&consoleMutex); /* BUG: this leaks memory. */ TerminateThread(threadInfoPtr->thread, 0); Tcl_MutexUnlock(&consoleMutex); } } /* * Close all the handles associated with the thread, and set the thread * handle field to NULL to mark that the thread has been cleaned up. */ CloseHandle(threadInfoPtr->thread); CloseHandle(threadInfoPtr->readyEvent); CloseHandle(threadInfoPtr->startEvent); CloseHandle(threadInfoPtr->stopEvent); threadInfoPtr->thread = NULL; } /* *---------------------------------------------------------------------- * * ConsoleCloseProc -- * * Closes a console based IO channel. * * Results: * 0 on success, errno otherwise. * * Side effects: * Closes the physical channel. * *---------------------------------------------------------------------- */ static int ConsoleCloseProc( ClientData instanceData, /* Pointer to ConsoleInfo structure. */ Tcl_Interp *interp) /* For error reporting. */ { ConsoleInfo *consolePtr = instanceData; int errorCode = 0; ConsoleInfo *infoPtr, **nextPtrPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Clean up the background thread if necessary. Note that this must be * done before we can close the file, since the thread may be blocking * trying to read from the console. */ if (consolePtr->reader.thread) { StopChannelThread(&consolePtr->reader); } consolePtr->validMask &= ~TCL_READABLE; /* * Wait for the writer thread to finish the current buffer, then terminate * the thread and close the handles. If the channel is nonblocking, there * should be no pending write operations. */ if (consolePtr->writer.thread) { if (consolePtr->toWrite) { /* * We only need to wait if there is something to write. This may * prevent infinite wait on exit. [Python Bug 216289] */ WaitForSingleObject(consolePtr->writer.readyEvent, INFINITE); } StopChannelThread(&consolePtr->writer); } consolePtr->validMask &= ~TCL_WRITABLE; /* * Don't close the Win32 handle if the handle is a standard channel during * the thread exit process. Otherwise, one thread may kill the stdio of * another. */ if (!TclInThreadExit() || ((GetStdHandle(STD_INPUT_HANDLE) != consolePtr->handle) && (GetStdHandle(STD_OUTPUT_HANDLE) != consolePtr->handle) && (GetStdHandle(STD_ERROR_HANDLE) != consolePtr->handle))) { if (CloseHandle(consolePtr->handle) == FALSE) { TclWinConvertError(GetLastError()); errorCode = errno; } } consolePtr->watchMask &= consolePtr->validMask; /* * Remove the file from the list of watched files. */ for (nextPtrPtr = &(tsdPtr->firstConsolePtr), infoPtr = *nextPtrPtr; infoPtr != NULL; nextPtrPtr = &infoPtr->nextPtr, infoPtr = *nextPtrPtr) { if (infoPtr == (ConsoleInfo *) consolePtr) { *nextPtrPtr = infoPtr->nextPtr; break; } } if (consolePtr->writeBuf != NULL) { ckfree(consolePtr->writeBuf); consolePtr->writeBuf = 0; } ckfree(consolePtr); return errorCode; } /* *---------------------------------------------------------------------- * * ConsoleInputProc -- * * Reads input from the IO channel into the buffer given. Returns count * of how many bytes were actually read, and an error indication. * * Results: * A count of how many bytes were read is returned and an error * indication is returned in an output argument. * * Side effects: * Reads input from the actual channel. * *---------------------------------------------------------------------- */ static int ConsoleInputProc( ClientData instanceData, /* Console state. */ char *buf, /* Where to store data read. */ int bufSize, /* How much space is available in the * buffer? */ int *errorCode) /* Where to store error code. */ { ConsoleInfo *infoPtr = instanceData; DWORD count, bytesRead = 0; int result; *errorCode = 0; /* * Synchronize with the reader thread. */ result = WaitForRead(infoPtr, (infoPtr->flags & CONSOLE_ASYNC) ? 0 : 1); /* * If an error occurred, return immediately. */ if (result == -1) { *errorCode = errno; return -1; } if (infoPtr->readFlags & CONSOLE_BUFFERED) { /* * Data is stored in the buffer. */ if (bufSize < (infoPtr->bytesRead - infoPtr->offset)) { memcpy(buf, &infoPtr->buffer[infoPtr->offset], (size_t) bufSize); bytesRead = bufSize; infoPtr->offset += bufSize; } else { memcpy(buf, &infoPtr->buffer[infoPtr->offset], (size_t) bufSize); bytesRead = infoPtr->bytesRead - infoPtr->offset; /* * Reset the buffer. */ infoPtr->readFlags &= ~CONSOLE_BUFFERED; infoPtr->offset = 0; } return bytesRead; } /* * Attempt to read bufSize bytes. The read will return immediately if * there is any data available. Otherwise it will block until at least one * byte is available or an EOF occurs. */ if (ReadConsoleBytes(infoPtr->handle, (LPVOID) buf, (DWORD) bufSize, &count) == TRUE) { /* * TODO: This potentially writes beyond the limits specified * by the caller. In practice this is harmless, since all writes * are into ChannelBuffers, and those have padding, but still * ought to remove this, unless some Windows wizard can give * a reason not to. */ buf[count] = '\0'; return count; } return -1; } /* *---------------------------------------------------------------------- * * ConsoleOutputProc -- * * Writes the given output on the IO channel. Returns count of how many * characters were actually written, and an error indication. * * Results: * A count of how many characters were written is returned and an error * indication is returned in an output argument. * * Side effects: * Writes output on the actual channel. * *---------------------------------------------------------------------- */ static int ConsoleOutputProc( ClientData instanceData, /* Console state. */ const char *buf, /* The data buffer. */ int toWrite, /* How many bytes to write? */ int *errorCode) /* Where to store error code. */ { ConsoleInfo *infoPtr = instanceData; ConsoleThreadInfo *threadInfo = &infoPtr->reader; DWORD bytesWritten, timeout; *errorCode = 0; timeout = (infoPtr->flags & CONSOLE_ASYNC) ? 0 : INFINITE; if (WaitForSingleObject(threadInfo->readyEvent,timeout) == WAIT_TIMEOUT) { /* * The writer thread is blocked waiting for a write to complete and * the channel is in non-blocking mode. */ errno = EWOULDBLOCK; goto error; } /* * Check for a background error on the last write. */ if (infoPtr->writeError) { TclWinConvertError(infoPtr->writeError); infoPtr->writeError = 0; goto error; } if (infoPtr->flags & CONSOLE_ASYNC) { /* * The console is non-blocking, so copy the data into the output * buffer and restart the writer thread. */ if (toWrite > infoPtr->writeBufLen) { /* * Reallocate the buffer to be large enough to hold the data. */ if (infoPtr->writeBuf) { ckfree(infoPtr->writeBuf); } infoPtr->writeBufLen = toWrite; infoPtr->writeBuf = ckalloc(toWrite); } memcpy(infoPtr->writeBuf, buf, (size_t) toWrite); infoPtr->toWrite = toWrite; ResetEvent(threadInfo->readyEvent); SetEvent(threadInfo->startEvent); bytesWritten = toWrite; } else { /* * In the blocking case, just try to write the buffer directly. This * avoids an unnecessary copy. */ if (WriteConsoleBytes(infoPtr->handle, buf, (DWORD) toWrite, &bytesWritten) == FALSE) { TclWinConvertError(GetLastError()); goto error; } } return bytesWritten; error: *errorCode = errno; return -1; } /* *---------------------------------------------------------------------- * * ConsoleEventProc -- * * This function is invoked by Tcl_ServiceEvent when a file event reaches * the front of the event queue. This procedure invokes Tcl_NotifyChannel * on the console. * * Results: * Returns 1 if the event was handled, meaning it should be removed from * the queue. Returns 0 if the event was not handled, meaning it should * stay on the queue. The only time the event isn't handled is if the * TCL_FILE_EVENTS flag bit isn't set. * * Side effects: * Whatever the notifier callback does. * *---------------------------------------------------------------------- */ static int ConsoleEventProc( Tcl_Event *evPtr, /* Event to service. */ int flags) /* Flags that indicate what events to handle, * such as TCL_FILE_EVENTS. */ { ConsoleEvent *consoleEvPtr = (ConsoleEvent *) evPtr; ConsoleInfo *infoPtr; int mask; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; } /* * Search through the list of watched consoles for the one whose handle * matches the event. We do this rather than simply dereferencing the * handle in the event so that consoles can be deleted while the event is * in the queue. */ for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (consoleEvPtr->infoPtr == infoPtr) { infoPtr->flags &= ~CONSOLE_PENDING; break; } } /* * Remove stale events. */ if (!infoPtr) { return 1; } /* * Check to see if the console is readable. Note that we can't tell if a * console is writable, so we always report it as being writable unless we * have detected EOF. */ mask = 0; if (infoPtr->watchMask & TCL_WRITABLE) { if (WaitForSingleObject(infoPtr->writer.readyEvent, 0) != WAIT_TIMEOUT) { mask = TCL_WRITABLE; } } if (infoPtr->watchMask & TCL_READABLE) { if (WaitForRead(infoPtr, 0) >= 0) { if (infoPtr->readFlags & CONSOLE_EOF) { mask = TCL_READABLE; } else { mask |= TCL_READABLE; } } } /* * Inform the channel of the events. */ Tcl_NotifyChannel(infoPtr->channel, infoPtr->watchMask & mask); return 1; } /* *---------------------------------------------------------------------- * * ConsoleWatchProc -- * * Called by the notifier to set up to watch for events on this channel. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void ConsoleWatchProc( ClientData instanceData, /* Console state. */ int mask) /* What events to watch for, OR-ed combination * of TCL_READABLE, TCL_WRITABLE and * TCL_EXCEPTION. */ { ConsoleInfo **nextPtrPtr, *ptr; ConsoleInfo *infoPtr = instanceData; int oldMask = infoPtr->watchMask; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Since most of the work is handled by the background threads, we just * need to update the watchMask and then force the notifier to poll once. */ infoPtr->watchMask = mask & infoPtr->validMask; if (infoPtr->watchMask) { Tcl_Time blockTime = { 0, 0 }; if (!oldMask) { infoPtr->nextPtr = tsdPtr->firstConsolePtr; tsdPtr->firstConsolePtr = infoPtr; } Tcl_SetMaxBlockTime(&blockTime); } else if (oldMask) { /* * Remove the console from the list of watched consoles. */ for (nextPtrPtr = &(tsdPtr->firstConsolePtr), ptr = *nextPtrPtr; ptr != NULL; nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) { if (infoPtr == ptr) { *nextPtrPtr = ptr->nextPtr; break; } } } } /* *---------------------------------------------------------------------- * * ConsoleGetHandleProc -- * * Called from Tcl_GetChannelHandle to retrieve OS handles from inside a * command consoleline based channel. * * Results: * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if there is no * handle for the specified direction. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ConsoleGetHandleProc( ClientData instanceData, /* The console state. */ int direction, /* TCL_READABLE or TCL_WRITABLE. */ ClientData *handlePtr) /* Where to store the handle. */ { ConsoleInfo *infoPtr = instanceData; *handlePtr = infoPtr->handle; return TCL_OK; } /* *---------------------------------------------------------------------- * * WaitForRead -- * * Wait until some data is available, the console is at EOF or the reader * thread is blocked waiting for data (if the channel is in non-blocking * mode). * * Results: * Returns 1 if console is readable. Returns 0 if there is no data on the * console, but there is buffered data. Returns -1 if an error occurred. * If an error occurred, the threads may not be synchronized. * * Side effects: * Updates the shared state flags. If no error occurred, the reader * thread is blocked waiting for a signal from the main thread. * *---------------------------------------------------------------------- */ static int WaitForRead( ConsoleInfo *infoPtr, /* Console state. */ int blocking) /* Indicates whether call should be blocking * or not. */ { DWORD timeout, count; HANDLE *handle = infoPtr->handle; ConsoleThreadInfo *threadInfo = &infoPtr->reader; INPUT_RECORD input; while (1) { /* * Synchronize with the reader thread. */ timeout = blocking ? INFINITE : 0; if (WaitForSingleObject(threadInfo->readyEvent, timeout) == WAIT_TIMEOUT) { /* * The reader thread is blocked waiting for data and the channel * is in non-blocking mode. */ errno = EWOULDBLOCK; return -1; } /* * At this point, the two threads are synchronized, so it is safe to * access shared state. */ /* * If the console has hit EOF, it is always readable. */ if (infoPtr->readFlags & CONSOLE_EOF) { return 1; } if (PeekConsoleInput(handle, &input, 1, &count) == FALSE) { /* * Check to see if the peek failed because of EOF. */ TclWinConvertError(GetLastError()); if (errno == EOF) { infoPtr->readFlags |= CONSOLE_EOF; return 1; } /* * Ignore errors if there is data in the buffer. */ if (infoPtr->readFlags & CONSOLE_BUFFERED) { return 0; } else { return -1; } } /* * If there is data in the buffer, the console must be readable (since * it is a line-oriented device). */ if (infoPtr->readFlags & CONSOLE_BUFFERED) { return 1; } /* * There wasn't any data available, so reset the thread and try again. */ ResetEvent(threadInfo->readyEvent); SetEvent(threadInfo->startEvent); } } /* *---------------------------------------------------------------------- * * ConsoleReaderThread -- * * This function runs in a separate thread and waits for input to become * available on a console. * * Results: * None. * * Side effects: * Signals the main thread when input become available. May cause the * main thread to wake up by posting a message. May one line from the * console for each wait operation. * *---------------------------------------------------------------------- */ static DWORD WINAPI ConsoleReaderThread( LPVOID arg) { ConsoleInfo *infoPtr = arg; HANDLE *handle = infoPtr->handle; ConsoleThreadInfo *threadInfo = &infoPtr->reader; DWORD waitResult; HANDLE wEvents[2]; /* * The first event takes precedence. */ wEvents[0] = threadInfo->stopEvent; wEvents[1] = threadInfo->startEvent; for (;;) { /* * Wait for the main thread to signal before attempting to wait. */ waitResult = WaitForMultipleObjects(2, wEvents, FALSE, INFINITE); if (waitResult != (WAIT_OBJECT_0 + 1)) { /* * The start event was not signaled. It must be the stop event or * an error, so exit this thread. */ break; } /* * Look for data on the console, but first ignore any events that are * not KEY_EVENTs. */ if (ReadConsoleBytes(handle, infoPtr->buffer, CONSOLE_BUFFER_SIZE, (LPDWORD) &infoPtr->bytesRead) != FALSE) { /* * Data was stored in the buffer. */ infoPtr->readFlags |= CONSOLE_BUFFERED; } else { DWORD err = GetLastError(); if (err == (DWORD) EOF) { infoPtr->readFlags = CONSOLE_EOF; } } /* * Signal the main thread by signalling the readable event and then * waking up the notifier thread. */ SetEvent(threadInfo->readyEvent); /* * Alert the foreground thread. Note that we need to treat this like a * critical section so the foreground thread does not terminate this * thread while we are holding a mutex in the notifier code. */ Tcl_MutexLock(&consoleMutex); if (infoPtr->threadId != NULL) { /* * TIP #218. When in flight ignore the event, no one will receive * it anyway. */ Tcl_ThreadAlert(infoPtr->threadId); } Tcl_MutexUnlock(&consoleMutex); } return 0; } /* *---------------------------------------------------------------------- * * ConsoleWriterThread -- * * This function runs in a separate thread and writes data onto a * console. * * Results: * Always returns 0. * * Side effects: * Signals the main thread when an output operation is completed. May * cause the main thread to wake up by posting a message. * *---------------------------------------------------------------------- */ static DWORD WINAPI ConsoleWriterThread( LPVOID arg) { ConsoleInfo *infoPtr = arg; HANDLE *handle = infoPtr->handle; ConsoleThreadInfo *threadInfo = &infoPtr->writer; DWORD count, toWrite, waitResult; char *buf; HANDLE wEvents[2]; /* * The first event takes precedence. */ wEvents[0] = threadInfo->stopEvent; wEvents[1] = threadInfo->startEvent; for (;;) { /* * Wait for the main thread to signal before attempting to write. */ waitResult = WaitForMultipleObjects(2, wEvents, FALSE, INFINITE); if (waitResult != (WAIT_OBJECT_0 + 1)) { /* * The start event was not signaled. It must be the stop event or * an error, so exit this thread. */ break; } buf = infoPtr->writeBuf; toWrite = infoPtr->toWrite; /* * Loop until all of the bytes are written or an error occurs. */ while (toWrite > 0) { if (WriteConsoleBytes(handle, buf, (DWORD) toWrite, &count) == FALSE) { infoPtr->writeError = GetLastError(); break; } toWrite -= count; buf += count; } /* * Signal the main thread by signalling the writable event and then * waking up the notifier thread. */ SetEvent(threadInfo->readyEvent); /* * Alert the foreground thread. Note that we need to treat this like a * critical section so the foreground thread does not terminate this * thread while we are holding a mutex in the notifier code. */ Tcl_MutexLock(&consoleMutex); if (infoPtr->threadId != NULL) { /* * TIP #218. When in flight ignore the event, no one will receive * it anyway. */ Tcl_ThreadAlert(infoPtr->threadId); } Tcl_MutexUnlock(&consoleMutex); } return 0; } /* *---------------------------------------------------------------------- * * TclWinOpenConsoleChannel -- * * Constructs a Console channel for the specified standard OS handle. * This is a helper function to break up the construction of channels * into File, Console, or Serial. * * Results: * Returns the new channel, or NULL. * * Side effects: * May open the channel. * *---------------------------------------------------------------------- */ Tcl_Channel TclWinOpenConsoleChannel( HANDLE handle, char *channelName, int permissions) { char encoding[4 + TCL_INTEGER_SPACE]; ConsoleInfo *infoPtr; DWORD modes; ConsoleInit(); /* * See if a channel with this handle already exists. */ infoPtr = ckalloc(sizeof(ConsoleInfo)); memset(infoPtr, 0, sizeof(ConsoleInfo)); infoPtr->validMask = permissions; infoPtr->handle = handle; infoPtr->channel = (Tcl_Channel) NULL; wsprintfA(encoding, "cp%d", GetConsoleCP()); infoPtr->threadId = Tcl_GetCurrentThread(); /* * Use the pointer for the name of the result channel. This keeps the * channel names unique, since some may share handles (stdin/stdout/stderr * for instance). */ sprintf(channelName, "file%" TCL_I_MODIFIER "x", (size_t) infoPtr); infoPtr->channel = Tcl_CreateChannel(&consoleChannelType, channelName, infoPtr, permissions); if (permissions & TCL_READABLE) { /* * Make sure the console input buffer is ready for only character * input notifications and the buffer is set for line buffering. IOW, * we only want to catch when complete lines are ready for reading. */ GetConsoleMode(infoPtr->handle, &modes); modes &= ~(ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT); modes |= ENABLE_LINE_INPUT; SetConsoleMode(infoPtr->handle, modes); StartChannelThread(infoPtr, &infoPtr->reader, ConsoleReaderThread); } if (permissions & TCL_WRITABLE) { StartChannelThread(infoPtr, &infoPtr->writer, ConsoleWriterThread); } /* * Files have default translation of AUTO and ^Z eof char, which means * that a ^Z will be accepted as EOF when reading. */ Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto"); Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}"); #ifdef UNICODE Tcl_SetChannelOption(NULL, infoPtr->channel, "-encoding", "unicode"); #else Tcl_SetChannelOption(NULL, infoPtr->channel, "-encoding", encoding); #endif return infoPtr->channel; } /* *---------------------------------------------------------------------- * * ConsoleThreadActionProc -- * * Insert or remove any thread local refs to this channel. * * Results: * None. * * Side effects: * Changes thread local list of valid channels. * *---------------------------------------------------------------------- */ static void ConsoleThreadActionProc( ClientData instanceData, int action) { ConsoleInfo *infoPtr = instanceData; /* * We do not access firstConsolePtr in the thread structures. This is not * for all serials managed by the thread, but only those we are watching. * Removal of the filevent handlers before transfer thus takes care of * this structure. */ Tcl_MutexLock(&consoleMutex); if (action == TCL_CHANNEL_THREAD_INSERT) { /* * We can't copy the thread information from the channel when the * channel is created. At this time the channel back pointer has not * been set yet. However in that case the threadId has already been * set by TclpCreateCommandChannel itself, so the structure is still * good. */ ConsoleInit(); if (infoPtr->channel != NULL) { infoPtr->threadId = Tcl_GetChannelThread(infoPtr->channel); } } else { infoPtr->threadId = NULL; } Tcl_MutexUnlock(&consoleMutex); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tclWinSerial.c0000644000175000017500000016420412663660066015140 0ustar sergeisergei/* * tclWinSerial.c -- * * This file implements the Windows-specific serial port functions, and * the "serial" channel driver. * * Copyright (c) 1999 by Scriptics Corp. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Serial functionality implemented by Rolf.Schroedter@dlr.de */ #include "tclWinInt.h" /* * The following variable is used to tell whether this module has been * initialized. */ static int initialized = 0; /* * The serialMutex locks around access to the initialized variable, and it is * used to protect background threads from being terminated while they are * using APIs that hold locks. */ TCL_DECLARE_MUTEX(serialMutex) /* * Bit masks used in the flags field of the SerialInfo structure below. */ #define SERIAL_PENDING (1<<0) /* Message is pending in the queue. */ #define SERIAL_ASYNC (1<<1) /* Channel is non-blocking. */ /* * Bit masks used in the sharedFlags field of the SerialInfo structure below. */ #define SERIAL_EOF (1<<2) /* Serial has reached EOF. */ #define SERIAL_ERROR (1<<4) /* * Default time to block between checking status on the serial port. */ #define SERIAL_DEFAULT_BLOCKTIME 10 /* 10 msec */ /* * Define Win32 read/write error masks returned by ClearCommError() */ #define SERIAL_READ_ERRORS \ (CE_RXOVER | CE_OVERRUN | CE_RXPARITY | CE_FRAME | CE_BREAK) #define SERIAL_WRITE_ERRORS \ (CE_TXFULL | CE_PTO) /* * This structure describes per-instance data for a serial based channel. */ typedef struct SerialInfo { HANDLE handle; struct SerialInfo *nextPtr; /* Pointer to next registered serial. */ Tcl_Channel channel; /* Pointer to channel structure. */ int validMask; /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which operations are valid on the file. */ int watchMask; /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which events should be reported. */ int flags; /* State flags, see above for a list. */ int readable; /* Flag that the channel is readable. */ int writable; /* Flag that the channel is writable. */ int blockTime; /* Maximum blocktime in msec. */ unsigned int lastEventTime; /* Time in milliseconds since last readable * event. */ /* Next readable event only after blockTime */ DWORD error; /* pending error code returned by * ClearCommError() */ DWORD lastError; /* last error code, can be fetched with * fconfigure chan -lasterror */ DWORD sysBufRead; /* Win32 system buffer size for read ops, * default=4096 */ DWORD sysBufWrite; /* Win32 system buffer size for write ops, * default=4096 */ Tcl_ThreadId threadId; /* Thread to which events should be reported. * This value is used by the reader/writer * threads. */ OVERLAPPED osRead; /* OVERLAPPED structure for read operations. */ OVERLAPPED osWrite; /* OVERLAPPED structure for write operations */ HANDLE writeThread; /* Handle to writer thread. */ CRITICAL_SECTION csWrite; /* Writer thread synchronisation. */ HANDLE evWritable; /* Manual-reset event to signal when the * writer thread has finished waiting for the * current buffer to be written. */ HANDLE evStartWriter; /* Auto-reset event used by the main thread to * signal when the writer thread should * attempt to write to the serial. */ HANDLE evStopWriter; /* Auto-reset event used by the main thread to * signal when the writer thread should close. */ DWORD writeError; /* An error caused by the last background * write. Set to 0 if no error has been * detected. This word is shared with the * writer thread so access must be * synchronized with the evWritable object. */ char *writeBuf; /* Current background output buffer. Access is * synchronized with the evWritable object. */ int writeBufLen; /* Size of write buffer. Access is * synchronized with the evWritable object. */ int toWrite; /* Current amount to be written. Access is * synchronized with the evWritable object. */ int writeQueue; /* Number of bytes pending in output queue. * Offset to DCB.cbInQue. Used to query * [fconfigure -queue] */ } SerialInfo; typedef struct ThreadSpecificData { /* * The following pointer refers to the head of the list of serials that * are being watched for file events. */ SerialInfo *firstSerialPtr; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * The following structure is what is added to the Tcl event queue when serial * events are generated. */ typedef struct SerialEvent { Tcl_Event header; /* Information that is standard for all * events. */ SerialInfo *infoPtr; /* Pointer to serial info structure. Note that * we still have to verify that the serial * exists before dereferencing this * pointer. */ } SerialEvent; /* * We don't use timeouts. */ static COMMTIMEOUTS no_timeout = { 0, /* ReadIntervalTimeout */ 0, /* ReadTotalTimeoutMultiplier */ 0, /* ReadTotalTimeoutConstant */ 0, /* WriteTotalTimeoutMultiplier */ 0, /* WriteTotalTimeoutConstant */ }; /* * Declarations for functions used only in this file. */ static int SerialBlockProc(ClientData instanceData, int mode); static void SerialCheckProc(ClientData clientData, int flags); static int SerialCloseProc(ClientData instanceData, Tcl_Interp *interp); static int SerialEventProc(Tcl_Event *evPtr, int flags); static void SerialExitHandler(ClientData clientData); static int SerialGetHandleProc(ClientData instanceData, int direction, ClientData *handlePtr); static ThreadSpecificData *SerialInit(void); static int SerialInputProc(ClientData instanceData, char *buf, int toRead, int *errorCode); static int SerialOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCode); static void SerialSetupProc(ClientData clientData, int flags); static void SerialWatchProc(ClientData instanceData, int mask); static void ProcExitHandler(ClientData clientData); static int SerialGetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); static int SerialSetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, const char *value); static DWORD WINAPI SerialWriterThread(LPVOID arg); static void SerialThreadActionProc(ClientData instanceData, int action); static int SerialBlockingRead(SerialInfo *infoPtr, LPVOID buf, DWORD bufSize, LPDWORD lpRead, LPOVERLAPPED osPtr); static int SerialBlockingWrite(SerialInfo *infoPtr, LPVOID buf, DWORD bufSize, LPDWORD lpWritten, LPOVERLAPPED osPtr); /* * This structure describes the channel type structure for command serial * based IO. */ static const Tcl_ChannelType serialChannelType = { "serial", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ SerialCloseProc, /* Close proc. */ SerialInputProc, /* Input proc. */ SerialOutputProc, /* Output proc. */ NULL, /* Seek proc. */ SerialSetOptionProc, /* Set option proc. */ SerialGetOptionProc, /* Get option proc. */ SerialWatchProc, /* Set up notifier to watch the channel. */ SerialGetHandleProc, /* Get an OS handle from channel. */ NULL, /* close2proc. */ SerialBlockProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ NULL, /* wide seek proc */ SerialThreadActionProc, /* thread action proc */ NULL /* truncate */ }; /* *---------------------------------------------------------------------- * * SerialInit -- * * This function initializes the static variables for this file. * * Results: * None. * * Side effects: * Creates a new event source. * *---------------------------------------------------------------------- */ static ThreadSpecificData * SerialInit(void) { ThreadSpecificData *tsdPtr; /* * Check the initialized flag first, then check it again in the mutex. * This is a speed enhancement. */ if (!initialized) { Tcl_MutexLock(&serialMutex); if (!initialized) { initialized = 1; Tcl_CreateExitHandler(ProcExitHandler, NULL); } Tcl_MutexUnlock(&serialMutex); } tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); if (tsdPtr == NULL) { tsdPtr = TCL_TSD_INIT(&dataKey); tsdPtr->firstSerialPtr = NULL; Tcl_CreateEventSource(SerialSetupProc, SerialCheckProc, NULL); Tcl_CreateThreadExitHandler(SerialExitHandler, NULL); } return tsdPtr; } /* *---------------------------------------------------------------------- * * SerialExitHandler -- * * This function is called to cleanup the serial module before Tcl is * unloaded. * * Results: * None. * * Side effects: * Removes the serial event source. * *---------------------------------------------------------------------- */ static void SerialExitHandler( ClientData clientData) /* Old window proc */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); SerialInfo *infoPtr; /* * Clear all eventually pending output. Otherwise Tcl's exit could totally * block, because it performs a blocking flush on all open channels. Note * that serial write operations may be blocked due to handshake. */ for (infoPtr = tsdPtr->firstSerialPtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { PurgeComm(infoPtr->handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); } Tcl_DeleteEventSource(SerialSetupProc, SerialCheckProc, NULL); } /* *---------------------------------------------------------------------- * * ProcExitHandler -- * * This function is called to cleanup the process list before Tcl is * unloaded. * * Results: * None. * * Side effects: * Resets the process list. * *---------------------------------------------------------------------- */ static void ProcExitHandler( ClientData clientData) /* Old window proc */ { Tcl_MutexLock(&serialMutex); initialized = 0; Tcl_MutexUnlock(&serialMutex); } /* *---------------------------------------------------------------------- * * SerialBlockTime -- * * Wrapper to set Tcl's block time in msec * * Results: * None. * * Side effects: * Updates the maximum blocking time. * *---------------------------------------------------------------------- */ static void SerialBlockTime( int msec) /* milli-seconds */ { Tcl_Time blockTime; blockTime.sec = msec / 1000; blockTime.usec = (msec % 1000) * 1000; Tcl_SetMaxBlockTime(&blockTime); } /* *---------------------------------------------------------------------- * * SerialGetMilliseconds -- * * Get current time in milliseconds,ignoring integer overruns. * * Results: * The current time. * * Side effects: * None. * *---------------------------------------------------------------------- */ static unsigned int SerialGetMilliseconds(void) { Tcl_Time time; Tcl_GetTime(&time); return (time.sec * 1000 + time.usec / 1000); } /* *---------------------------------------------------------------------- * * SerialSetupProc -- * * This procedure is invoked before Tcl_DoOneEvent blocks waiting for an * event. * * Results: * None. * * Side effects: * Adjusts the block time if needed. * *---------------------------------------------------------------------- */ void SerialSetupProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { SerialInfo *infoPtr; int block = 1; int msec = INT_MAX; /* min. found block time */ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } /* * Look to see if any events handlers installed. If they are, do not * block. */ for (infoPtr=tsdPtr->firstSerialPtr ; infoPtr!=NULL ; infoPtr=infoPtr->nextPtr) { if (infoPtr->watchMask & TCL_WRITABLE) { if (WaitForSingleObject(infoPtr->evWritable, 0) != WAIT_TIMEOUT) { block = 0; msec = min(msec, infoPtr->blockTime); } } if (infoPtr->watchMask & TCL_READABLE) { block = 0; msec = min(msec, infoPtr->blockTime); } } if (!block) { SerialBlockTime(msec); } } /* *---------------------------------------------------------------------- * * SerialCheckProc -- * * This procedure is called by Tcl_DoOneEvent to check the serial event * source for events. * * Results: * None. * * Side effects: * May queue an event. * *---------------------------------------------------------------------- */ static void SerialCheckProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { SerialInfo *infoPtr; SerialEvent *evPtr; int needEvent; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); COMSTAT cStat; unsigned int time; if (!(flags & TCL_FILE_EVENTS)) { return; } /* * Queue events for any ready serials that don't already have events * queued. */ for (infoPtr=tsdPtr->firstSerialPtr ; infoPtr!=NULL ; infoPtr=infoPtr->nextPtr) { if (infoPtr->flags & SERIAL_PENDING) { continue; } needEvent = 0; /* * If WRITABLE watch mask is set look for infoPtr->evWritable object. */ if (infoPtr->watchMask & TCL_WRITABLE && WaitForSingleObject(infoPtr->evWritable, 0) != WAIT_TIMEOUT) { infoPtr->writable = 1; needEvent = 1; } /* * If READABLE watch mask is set call ClearCommError to poll cbInQue. * Window errors are ignored here. */ if (infoPtr->watchMask & TCL_READABLE) { if (ClearCommError(infoPtr->handle, &infoPtr->error, &cStat)) { /* * Look for characters already pending in windows queue. If * they are, poll. */ if (infoPtr->watchMask & TCL_READABLE) { /* * Force fileevent after serial read error. */ if ((cStat.cbInQue > 0) || (infoPtr->error & SERIAL_READ_ERRORS)) { infoPtr->readable = 1; time = SerialGetMilliseconds(); if ((unsigned int) (time - infoPtr->lastEventTime) >= (unsigned int) infoPtr->blockTime) { needEvent = 1; infoPtr->lastEventTime = time; } } } } } /* * Queue an event if the serial is signaled for reading or writing. */ if (needEvent) { infoPtr->flags |= SERIAL_PENDING; evPtr = ckalloc(sizeof(SerialEvent)); evPtr->header.proc = SerialEventProc; evPtr->infoPtr = infoPtr; Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL); } } } /* *---------------------------------------------------------------------- * * SerialBlockProc -- * * Set blocking or non-blocking mode on channel. * * Results: * 0 if successful, errno when failed. * * Side effects: * Sets the device into blocking or non-blocking mode. * *---------------------------------------------------------------------- */ static int SerialBlockProc( ClientData instanceData, /* Instance data for channel. */ int mode) /* TCL_MODE_BLOCKING or * TCL_MODE_NONBLOCKING. */ { int errorCode = 0; SerialInfo *infoPtr = (SerialInfo *) instanceData; /* * Only serial READ can be switched between blocking & nonblocking using * COMMTIMEOUTS. Serial write emulates blocking & nonblocking by the * SerialWriterThread. */ if (mode == TCL_MODE_NONBLOCKING) { infoPtr->flags |= SERIAL_ASYNC; } else { infoPtr->flags &= ~(SERIAL_ASYNC); } return errorCode; } /* *---------------------------------------------------------------------- * * SerialCloseProc -- * * Closes a serial based IO channel. * * Results: * 0 on success, errno otherwise. * * Side effects: * Closes the physical channel. * *---------------------------------------------------------------------- */ static int SerialCloseProc( ClientData instanceData, /* Pointer to SerialInfo structure. */ Tcl_Interp *interp) /* For error reporting. */ { SerialInfo *serialPtr = (SerialInfo *) instanceData; int errorCode, result = 0; SerialInfo *infoPtr, **nextPtrPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); DWORD exitCode; errorCode = 0; if (serialPtr->validMask & TCL_READABLE) { PurgeComm(serialPtr->handle, PURGE_RXABORT | PURGE_RXCLEAR); CloseHandle(serialPtr->osRead.hEvent); } serialPtr->validMask &= ~TCL_READABLE; if (serialPtr->validMask & TCL_WRITABLE) { /* * Generally we cannot wait for a pending write operation because it * may hang due to handshake * WaitForSingleObject(serialPtr->evWritable, INFINITE); */ /* * The thread may have already closed on it's own. Check it's exit * code. */ GetExitCodeThread(serialPtr->writeThread, &exitCode); if (exitCode == STILL_ACTIVE) { /* * Set the stop event so that if the writer thread is blocked in * SerialWriterThread on WaitForMultipleEvents, it will exit * cleanly. */ SetEvent(serialPtr->evStopWriter); /* * Wait at most 20 milliseconds for the writer thread to close. */ if (WaitForSingleObject(serialPtr->writeThread, 20) == WAIT_TIMEOUT) { /* * Forcibly terminate the background thread as a last resort. * Note that we need to guard against terminating the thread * while it is in the middle of Tcl_ThreadAlert because it * won't be able to release the notifier lock. */ Tcl_MutexLock(&serialMutex); /* BUG: this leaks memory */ TerminateThread(serialPtr->writeThread, 0); Tcl_MutexUnlock(&serialMutex); } } CloseHandle(serialPtr->writeThread); CloseHandle(serialPtr->osWrite.hEvent); CloseHandle(serialPtr->evWritable); CloseHandle(serialPtr->evStartWriter); CloseHandle(serialPtr->evStopWriter); serialPtr->writeThread = NULL; PurgeComm(serialPtr->handle, PURGE_TXABORT | PURGE_TXCLEAR); } serialPtr->validMask &= ~TCL_WRITABLE; DeleteCriticalSection(&serialPtr->csWrite); /* * Don't close the Win32 handle if the handle is a standard channel during * the thread exit process. Otherwise, one thread may kill the stdio of * another. */ if (!TclInThreadExit() || ((GetStdHandle(STD_INPUT_HANDLE) != serialPtr->handle) && (GetStdHandle(STD_OUTPUT_HANDLE) != serialPtr->handle) && (GetStdHandle(STD_ERROR_HANDLE) != serialPtr->handle))) { if (CloseHandle(serialPtr->handle) == FALSE) { TclWinConvertError(GetLastError()); errorCode = errno; } } serialPtr->watchMask &= serialPtr->validMask; /* * Remove the file from the list of watched files. */ for (nextPtrPtr=&(tsdPtr->firstSerialPtr), infoPtr=*nextPtrPtr; infoPtr!=NULL; nextPtrPtr=&infoPtr->nextPtr, infoPtr=*nextPtrPtr) { if (infoPtr == (SerialInfo *)serialPtr) { *nextPtrPtr = infoPtr->nextPtr; break; } } /* * Wrap the error file into a channel and give it to the cleanup routine. */ if (serialPtr->writeBuf != NULL) { ckfree(serialPtr->writeBuf); serialPtr->writeBuf = NULL; } ckfree(serialPtr); if (errorCode == 0) { return result; } return errorCode; } /* *---------------------------------------------------------------------- * * SerialBlockingRead -- * * Perform a blocking read into the buffer given. Returns count of how * many bytes were actually read, and an error indication. * * Results: * A count of how many bytes were read is returned and an error * indication is returned. * * Side effects: * Reads input from the actual channel. * *---------------------------------------------------------------------- */ static int SerialBlockingRead( SerialInfo *infoPtr, /* Serial info structure */ LPVOID buf, /* The input buffer pointer */ DWORD bufSize, /* The number of bytes to read */ LPDWORD lpRead, /* Returns number of bytes read */ LPOVERLAPPED osPtr) /* OVERLAPPED structure */ { /* * Perform overlapped blocking read. * 1. Reset the overlapped event * 2. Start overlapped read operation * 3. Wait for completion */ /* * Set Offset to ZERO, otherwise NT4.0 may report an error. */ osPtr->Offset = osPtr->OffsetHigh = 0; ResetEvent(osPtr->hEvent); if (!ReadFile(infoPtr->handle, buf, bufSize, lpRead, osPtr)) { if (GetLastError() != ERROR_IO_PENDING) { /* * ReadFile failed, but it isn't delayed. Report error. */ return FALSE; } else { /* * Read is pending, wait for completion, timeout? */ if (!GetOverlappedResult(infoPtr->handle, osPtr, lpRead, TRUE)) { return FALSE; } } } else { /* * ReadFile completed immediately. */ } return TRUE; } /* *---------------------------------------------------------------------- * * SerialBlockingWrite -- * * Perform a blocking write from the buffer given. Returns count of how * many bytes were actually written, and an error indication. * * Results: * A count of how many bytes were written is returned and an error * indication is returned. * * Side effects: * Writes output to the actual channel. * *---------------------------------------------------------------------- */ static int SerialBlockingWrite( SerialInfo *infoPtr, /* Serial info structure */ LPVOID buf, /* The output buffer pointer */ DWORD bufSize, /* The number of bytes to write */ LPDWORD lpWritten, /* Returns number of bytes written */ LPOVERLAPPED osPtr) /* OVERLAPPED structure */ { int result; /* * Perform overlapped blocking write. * 1. Reset the overlapped event * 2. Remove these bytes from the output queue counter * 3. Start overlapped write operation * 3. Remove these bytes from the output queue counter * 4. Wait for completion * 5. Adjust the output queue counter */ ResetEvent(osPtr->hEvent); EnterCriticalSection(&infoPtr->csWrite); infoPtr->writeQueue -= bufSize; /* * Set Offset to ZERO, otherwise NT4.0 may report an error */ osPtr->Offset = osPtr->OffsetHigh = 0; result = WriteFile(infoPtr->handle, buf, bufSize, lpWritten, osPtr); LeaveCriticalSection(&infoPtr->csWrite); if (result == FALSE) { int err = GetLastError(); switch (err) { case ERROR_IO_PENDING: /* * Write is pending, wait for completion. */ if (!GetOverlappedResult(infoPtr->handle, osPtr, lpWritten, TRUE)) { return FALSE; } break; case ERROR_COUNTER_TIMEOUT: /* * Write timeout handled in SerialOutputProc. */ break; default: /* * WriteFile failed, but it isn't delayed. Report error. */ return FALSE; } } else { /* * WriteFile completed immediately. */ } EnterCriticalSection(&infoPtr->csWrite); infoPtr->writeQueue += (*lpWritten - bufSize); LeaveCriticalSection(&infoPtr->csWrite); return TRUE; } /* *---------------------------------------------------------------------- * * SerialInputProc -- * * Reads input from the IO channel into the buffer given. Returns count * of how many bytes were actually read, and an error indication. * * Results: * A count of how many bytes were read is returned and an error * indication is returned in an output argument. * * Side effects: * Reads input from the actual channel. * *---------------------------------------------------------------------- */ static int SerialInputProc( ClientData instanceData, /* Serial state. */ char *buf, /* Where to store data read. */ int bufSize, /* How much space is available in the * buffer? */ int *errorCode) /* Where to store error code. */ { SerialInfo *infoPtr = (SerialInfo *) instanceData; DWORD bytesRead = 0; COMSTAT cStat; *errorCode = 0; /* * Check if there is a CommError pending from SerialCheckProc */ if (infoPtr->error & SERIAL_READ_ERRORS) { goto commError; } /* * Look for characters already pending in windows queue. This is the * mainly restored good old code from Tcl8.0 */ if (ClearCommError(infoPtr->handle, &infoPtr->error, &cStat)) { /* * Check for errors here, but not in the evSetup/Check procedures. */ if (infoPtr->error & SERIAL_READ_ERRORS) { goto commError; } if (infoPtr->flags & SERIAL_ASYNC) { /* * NON_BLOCKING mode: Avoid blocking by reading more bytes than * available in input buffer. */ if (cStat.cbInQue > 0) { if ((DWORD) bufSize > cStat.cbInQue) { bufSize = cStat.cbInQue; } } else { errno = *errorCode = EWOULDBLOCK; return -1; } } else { /* * BLOCKING mode: Tcl trys to read a full buffer of 4 kBytes here. */ if (cStat.cbInQue > 0) { if ((DWORD) bufSize > cStat.cbInQue) { bufSize = cStat.cbInQue; } } else { bufSize = 1; } } } if (bufSize == 0) { return bytesRead = 0; } /* * Perform blocking read. Doesn't block in non-blocking mode, because we * checked the number of available bytes. */ if (SerialBlockingRead(infoPtr, (LPVOID) buf, (DWORD) bufSize, &bytesRead, &infoPtr->osRead) == FALSE) { TclWinConvertError(GetLastError()); *errorCode = errno; return -1; } return bytesRead; commError: infoPtr->lastError = infoPtr->error; /* save last error code */ infoPtr->error = 0; /* reset error code */ *errorCode = EIO; /* to return read-error only once */ return -1; } /* *---------------------------------------------------------------------- * * SerialOutputProc -- * * Writes the given output on the IO channel. Returns count of how many * characters were actually written, and an error indication. * * Results: * A count of how many characters were written is returned and an error * indication is returned in an output argument. * * Side effects: * Writes output on the actual channel. * *---------------------------------------------------------------------- */ static int SerialOutputProc( ClientData instanceData, /* Serial state. */ const char *buf, /* The data buffer. */ int toWrite, /* How many bytes to write? */ int *errorCode) /* Where to store error code. */ { SerialInfo *infoPtr = (SerialInfo *) instanceData; DWORD bytesWritten, timeout; *errorCode = 0; /* * At EXIT Tcl trys to flush all open channels in blocking mode. We avoid * blocking output after ExitProc or CloseHandler(chan) has been called by * checking the corrresponding variables. */ if (!initialized || TclInExit()) { return toWrite; } /* * Check if there is a CommError pending from SerialCheckProc */ if (infoPtr->error & SERIAL_WRITE_ERRORS) { infoPtr->lastError = infoPtr->error; /* save last error code */ infoPtr->error = 0; /* reset error code */ errno = EIO; goto error; } timeout = (infoPtr->flags & SERIAL_ASYNC) ? 0 : INFINITE; if (WaitForSingleObject(infoPtr->evWritable, timeout) == WAIT_TIMEOUT) { /* * The writer thread is blocked waiting for a write to complete and * the channel is in non-blocking mode. */ errno = EWOULDBLOCK; goto error1; } /* * Check for a background error on the last write. */ if (infoPtr->writeError) { TclWinConvertError(infoPtr->writeError); infoPtr->writeError = 0; goto error1; } /* * Remember the number of bytes in output queue */ EnterCriticalSection(&infoPtr->csWrite); infoPtr->writeQueue += toWrite; LeaveCriticalSection(&infoPtr->csWrite); if (infoPtr->flags & SERIAL_ASYNC) { /* * The serial is non-blocking, so copy the data into the output buffer * and restart the writer thread. */ if (toWrite > infoPtr->writeBufLen) { /* * Reallocate the buffer to be large enough to hold the data. */ if (infoPtr->writeBuf) { ckfree(infoPtr->writeBuf); } infoPtr->writeBufLen = toWrite; infoPtr->writeBuf = ckalloc(toWrite); } memcpy(infoPtr->writeBuf, buf, (size_t) toWrite); infoPtr->toWrite = toWrite; ResetEvent(infoPtr->evWritable); SetEvent(infoPtr->evStartWriter); bytesWritten = (DWORD) toWrite; } else { /* * In the blocking case, just try to write the buffer directly. This * avoids an unnecessary copy. */ if (!SerialBlockingWrite(infoPtr, (LPVOID) buf, (DWORD) toWrite, &bytesWritten, &infoPtr->osWrite)) { goto writeError; } if (bytesWritten != (DWORD) toWrite) { /* * Write timeout. */ infoPtr->lastError |= CE_PTO; errno = EIO; goto error; } } return (int) bytesWritten; writeError: TclWinConvertError(GetLastError()); error: /* * Reset the output queue counter on error during blocking output */ /* * EnterCriticalSection(&infoPtr->csWrite); * infoPtr->writeQueue = 0; * LeaveCriticalSection(&infoPtr->csWrite); */ error1: *errorCode = errno; return -1; } /* *---------------------------------------------------------------------- * * SerialEventProc -- * * This function is invoked by Tcl_ServiceEvent when a file event reaches * the front of the event queue. This procedure invokes Tcl_NotifyChannel * on the serial. * * Results: * Returns 1 if the event was handled, meaning it should be removed from * the queue. Returns 0 if the event was not handled, meaning it should * stay on the queue. The only time the event isn't handled is if the * TCL_FILE_EVENTS flag bit isn't set. * * Side effects: * Whatever the notifier callback does. * *---------------------------------------------------------------------- */ static int SerialEventProc( Tcl_Event *evPtr, /* Event to service. */ int flags) /* Flags that indicate what events to handle, * such as TCL_FILE_EVENTS. */ { SerialEvent *serialEvPtr = (SerialEvent *)evPtr; SerialInfo *infoPtr; int mask; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return 0; } /* * Search through the list of watched serials for the one whose handle * matches the event. We do this rather than simply dereferencing the * handle in the event so that serials can be deleted while the event is * in the queue. */ for (infoPtr = tsdPtr->firstSerialPtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (serialEvPtr->infoPtr == infoPtr) { infoPtr->flags &= ~(SERIAL_PENDING); break; } } /* * Remove stale events. */ if (!infoPtr) { return 1; } /* * Check to see if the serial is readable. Note that we can't tell if a * serial is writable, so we always report it as being writable unless we * have detected EOF. */ mask = 0; if (infoPtr->watchMask & TCL_WRITABLE) { if (infoPtr->writable) { mask |= TCL_WRITABLE; infoPtr->writable = 0; } } if (infoPtr->watchMask & TCL_READABLE) { if (infoPtr->readable) { mask |= TCL_READABLE; infoPtr->readable = 0; } } /* * Inform the channel of the events. */ Tcl_NotifyChannel(infoPtr->channel, infoPtr->watchMask & mask); return 1; } /* *---------------------------------------------------------------------- * * SerialWatchProc -- * * Called by the notifier to set up to watch for events on this channel. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void SerialWatchProc( ClientData instanceData, /* Serial state. */ int mask) /* What events to watch for, OR-ed combination * of TCL_READABLE, TCL_WRITABLE and * TCL_EXCEPTION. */ { SerialInfo **nextPtrPtr, *ptr; SerialInfo *infoPtr = (SerialInfo *) instanceData; int oldMask = infoPtr->watchMask; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Since the file is always ready for events, we set the block time so we * will poll. */ infoPtr->watchMask = mask & infoPtr->validMask; if (infoPtr->watchMask) { if (!oldMask) { infoPtr->nextPtr = tsdPtr->firstSerialPtr; tsdPtr->firstSerialPtr = infoPtr; } SerialBlockTime(infoPtr->blockTime); } else if (oldMask) { /* * Remove the serial port from the list of watched serial ports. */ for (nextPtrPtr=&(tsdPtr->firstSerialPtr), ptr=*nextPtrPtr; ptr!=NULL; nextPtrPtr=&ptr->nextPtr, ptr=*nextPtrPtr) { if (infoPtr == ptr) { *nextPtrPtr = ptr->nextPtr; break; } } } } /* *---------------------------------------------------------------------- * * SerialGetHandleProc -- * * Called from Tcl_GetChannelHandle to retrieve OS handles from inside a * command serial port based channel. * * Results: * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if there is no * handle for the specified direction. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int SerialGetHandleProc( ClientData instanceData, /* The serial state. */ int direction, /* TCL_READABLE or TCL_WRITABLE */ ClientData *handlePtr) /* Where to store the handle. */ { SerialInfo *infoPtr = (SerialInfo *) instanceData; *handlePtr = (ClientData) infoPtr->handle; return TCL_OK; } /* *---------------------------------------------------------------------- * * SerialWriterThread -- * * This function runs in a separate thread and writes data onto a serial. * * Results: * Always returns 0. * * Side effects: * Signals the main thread when an output operation is completed. May * cause the main thread to wake up by posting a message. * *---------------------------------------------------------------------- */ static DWORD WINAPI SerialWriterThread( LPVOID arg) { SerialInfo *infoPtr = (SerialInfo *)arg; DWORD bytesWritten, toWrite, waitResult; char *buf; OVERLAPPED myWrite; /* Have an own OVERLAPPED in this thread. */ HANDLE wEvents[2]; /* * The stop event takes precedence by being first in the list. */ wEvents[0] = infoPtr->evStopWriter; wEvents[1] = infoPtr->evStartWriter; for (;;) { /* * Wait for the main thread to signal before attempting to write. */ waitResult = WaitForMultipleObjects(2, wEvents, FALSE, INFINITE); if (waitResult != (WAIT_OBJECT_0 + 1)) { /* * The start event was not signaled. It might be the stop event or * an error, so exit. */ break; } buf = infoPtr->writeBuf; toWrite = infoPtr->toWrite; myWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* * Loop until all of the bytes are written or an error occurs. */ while (toWrite > 0) { /* * Check for pending writeError. Ignore all write operations until * the user has been notified. */ if (infoPtr->writeError) { break; } if (SerialBlockingWrite(infoPtr, (LPVOID) buf, (DWORD) toWrite, &bytesWritten, &myWrite) == FALSE) { infoPtr->writeError = GetLastError(); break; } if (bytesWritten != toWrite) { /* * Write timeout. */ infoPtr->writeError = ERROR_WRITE_FAULT; break; } toWrite -= bytesWritten; buf += bytesWritten; } CloseHandle(myWrite.hEvent); /* * Signal the main thread by signalling the evWritable event and then * waking up the notifier thread. */ SetEvent(infoPtr->evWritable); /* * Alert the foreground thread. Note that we need to treat this like a * critical section so the foreground thread does not terminate this * thread while we are holding a mutex in the notifier code. */ Tcl_MutexLock(&serialMutex); if (infoPtr->threadId != NULL) { /* * TIP #218: When in flight ignore the event, no one will receive * it anyway. */ Tcl_ThreadAlert(infoPtr->threadId); } Tcl_MutexUnlock(&serialMutex); } return 0; } /* *---------------------------------------------------------------------- * * TclWinSerialOpen -- * * Opens or Reopens the serial port with the OVERLAPPED FLAG set * * Results: * Returns the new handle, or INVALID_HANDLE_VALUE. * If an existing channel is specified it is closed and reopened. * * Side effects: * May close/reopen the original handle * *---------------------------------------------------------------------- */ HANDLE TclWinSerialOpen( HANDLE handle, const TCHAR *name, DWORD access) { SerialInit(); /* * If an open channel is specified, close it */ if ( handle != INVALID_HANDLE_VALUE && CloseHandle(handle) == FALSE) { return INVALID_HANDLE_VALUE; } /* * Multithreaded I/O needs the overlapped flag set otherwise * ClearCommError blocks under Windows NT/2000 until serial output is * finished */ handle = CreateFile(name, access, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); return handle; } /* *---------------------------------------------------------------------- * * TclWinOpenSerialChannel -- * * Constructs a Serial port channel for the specified standard OS handle. * This is a helper function to break up the construction of channels * into File, Console, or Serial. * * Results: * Returns the new channel, or NULL. * * Side effects: * May open the channel * *---------------------------------------------------------------------- */ Tcl_Channel TclWinOpenSerialChannel( HANDLE handle, char *channelName, int permissions) { SerialInfo *infoPtr; DWORD id; SerialInit(); infoPtr = ckalloc(sizeof(SerialInfo)); memset(infoPtr, 0, sizeof(SerialInfo)); infoPtr->validMask = permissions; infoPtr->handle = handle; infoPtr->channel = (Tcl_Channel) NULL; infoPtr->readable = 0; infoPtr->writable = 1; infoPtr->toWrite = infoPtr->writeQueue = 0; infoPtr->blockTime = SERIAL_DEFAULT_BLOCKTIME; infoPtr->lastEventTime = 0; infoPtr->lastError = infoPtr->error = 0; infoPtr->threadId = Tcl_GetCurrentThread(); infoPtr->sysBufRead = 4096; infoPtr->sysBufWrite = 4096; /* * Use the pointer to keep the channel names unique, in case the handles * are shared between multiple channels (stdin/stdout). */ sprintf(channelName, "file%" TCL_I_MODIFIER "x", (size_t) infoPtr); infoPtr->channel = Tcl_CreateChannel(&serialChannelType, channelName, infoPtr, permissions); SetupComm(handle, infoPtr->sysBufRead, infoPtr->sysBufWrite); PurgeComm(handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); /* * Default is blocking. */ SetCommTimeouts(handle, &no_timeout); InitializeCriticalSection(&infoPtr->csWrite); if (permissions & TCL_READABLE) { infoPtr->osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); } if (permissions & TCL_WRITABLE) { /* * Initially the channel is writable and the writeThread is idle. */ infoPtr->osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); infoPtr->evWritable = CreateEvent(NULL, TRUE, TRUE, NULL); infoPtr->evStartWriter = CreateEvent(NULL, FALSE, FALSE, NULL); infoPtr->evStopWriter = CreateEvent(NULL, FALSE, FALSE, NULL); infoPtr->writeThread = CreateThread(NULL, 256, SerialWriterThread, infoPtr, 0, &id); } /* * Files have default translation of AUTO and ^Z eof char, which means * that a ^Z will be accepted as EOF when reading. */ Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto"); Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}"); return infoPtr->channel; } /* *---------------------------------------------------------------------- * * SerialErrorStr -- * * Converts a Win32 serial error code to a list of readable errors. * * Results: * None. * * Side effects: * Generates readable errors in the supplied DString. * *---------------------------------------------------------------------- */ static void SerialErrorStr( DWORD error, /* Win32 serial error code. */ Tcl_DString *dsPtr) /* Where to store string. */ { if (error & CE_RXOVER) { Tcl_DStringAppendElement(dsPtr, "RXOVER"); } if (error & CE_OVERRUN) { Tcl_DStringAppendElement(dsPtr, "OVERRUN"); } if (error & CE_RXPARITY) { Tcl_DStringAppendElement(dsPtr, "RXPARITY"); } if (error & CE_FRAME) { Tcl_DStringAppendElement(dsPtr, "FRAME"); } if (error & CE_BREAK) { Tcl_DStringAppendElement(dsPtr, "BREAK"); } if (error & CE_TXFULL) { Tcl_DStringAppendElement(dsPtr, "TXFULL"); } if (error & CE_PTO) { /* PTO used to signal WRITE-TIMEOUT */ Tcl_DStringAppendElement(dsPtr, "TIMEOUT"); } if (error & ~((DWORD) (SERIAL_READ_ERRORS | SERIAL_WRITE_ERRORS))) { char buf[TCL_INTEGER_SPACE + 1]; wsprintfA(buf, "%d", error); Tcl_DStringAppendElement(dsPtr, buf); } } /* *---------------------------------------------------------------------- * * SerialModemStatusStr -- * * Converts a Win32 modem status list of readable flags * * Result: * None. * * Side effects: * Appends modem status flag strings to the given DString. * *---------------------------------------------------------------------- */ static void SerialModemStatusStr( DWORD status, /* Win32 modem status. */ Tcl_DString *dsPtr) /* Where to store string. */ { Tcl_DStringAppendElement(dsPtr, "CTS"); Tcl_DStringAppendElement(dsPtr, (status & MS_CTS_ON) ? "1" : "0"); Tcl_DStringAppendElement(dsPtr, "DSR"); Tcl_DStringAppendElement(dsPtr, (status & MS_DSR_ON) ? "1" : "0"); Tcl_DStringAppendElement(dsPtr, "RING"); Tcl_DStringAppendElement(dsPtr, (status & MS_RING_ON) ? "1" : "0"); Tcl_DStringAppendElement(dsPtr, "DCD"); Tcl_DStringAppendElement(dsPtr, (status & MS_RLSD_ON) ? "1" : "0"); } /* *---------------------------------------------------------------------- * * SerialSetOptionProc -- * * Sets an option on a channel. * * Results: * A standard Tcl result. Also sets the interp's result on error if * interp is not NULL. * * Side effects: * May modify an option on a device. * *---------------------------------------------------------------------- */ static int SerialSetOptionProc( ClientData instanceData, /* File state. */ Tcl_Interp *interp, /* For error reporting - can be NULL. */ const char *optionName, /* Which option to set? */ const char *value) /* New value for option. */ { SerialInfo *infoPtr; DCB dcb; BOOL result, flag; size_t len, vlen; Tcl_DString ds; const TCHAR *native; int argc; const char **argv; infoPtr = (SerialInfo *) instanceData; /* * Parse options. This would be far easier if we had Tcl_Objs to work with * as that would let us use Tcl_GetIndexFromObj()... */ len = strlen(optionName); vlen = strlen(value); /* * Option -mode baud,parity,databits,stopbits */ if ((len > 2) && (strncmp(optionName, "-mode", len) == 0)) { if (!GetCommState(infoPtr->handle, &dcb)) { goto getStateFailed; } native = Tcl_WinUtfToTChar(value, -1, &ds); result = BuildCommDCB(native, &dcb); Tcl_DStringFree(&ds); if (result == FALSE) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad value \"%s\" for -mode: should be baud,parity,data,stop", value)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", NULL); } return TCL_ERROR; } /* * Default settings for serial communications. */ dcb.fBinary = TRUE; dcb.fErrorChar = FALSE; dcb.fNull = FALSE; dcb.fAbortOnError = FALSE; if (!SetCommState(infoPtr->handle, &dcb)) { goto setStateFailed; } return TCL_OK; } /* * Option -handshake none|xonxoff|rtscts|dtrdsr */ if ((len > 1) && (strncmp(optionName, "-handshake", len) == 0)) { if (!GetCommState(infoPtr->handle, &dcb)) { goto getStateFailed; } /* * Reset all handshake options. DTR and RTS are ON by default. */ dcb.fOutX = dcb.fInX = FALSE; dcb.fOutxCtsFlow = dcb.fOutxDsrFlow = dcb.fDsrSensitivity = FALSE; dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fRtsControl = RTS_CONTROL_ENABLE; dcb.fTXContinueOnXoff = FALSE; /* * Adjust the handshake limits. Yes, the XonXoff limits seem to * influence even hardware handshake. */ dcb.XonLim = (WORD) (infoPtr->sysBufRead*1/2); dcb.XoffLim = (WORD) (infoPtr->sysBufRead*1/4); if (strncasecmp(value, "NONE", vlen) == 0) { /* * Leave all handshake options disabled. */ } else if (strncasecmp(value, "XONXOFF", vlen) == 0) { dcb.fOutX = dcb.fInX = TRUE; } else if (strncasecmp(value, "RTSCTS", vlen) == 0) { dcb.fOutxCtsFlow = TRUE; dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; } else if (strncasecmp(value, "DTRDSR", vlen) == 0) { dcb.fOutxDsrFlow = TRUE; dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; } else { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad value \"%s\" for -handshake: must be one of" " xonxoff, rtscts, dtrdsr or none", value)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "HANDSHAKE", NULL); } return TCL_ERROR; } if (!SetCommState(infoPtr->handle, &dcb)) { goto setStateFailed; } return TCL_OK; } /* * Option -xchar {\x11 \x13} */ if ((len > 1) && (strncmp(optionName, "-xchar", len) == 0)) { if (!GetCommState(infoPtr->handle, &dcb)) { goto getStateFailed; } if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } if (argc != 2) { badXchar: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad value for -xchar: should be a list of" " two elements with each a single character", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "XCHAR", NULL); } ckfree(argv); return TCL_ERROR; } /* * These dereferences are safe, even in the zero-length string cases, * because that just makes the xon/xoff character into NUL. When the * character looks like it is UTF-8 encoded, decode it before casting * into the format required for the Win guts. Note that this does not * convert character sets; it is expected that when people set the * control characters to something large and custom, they'll know the * hex/octal value rather than the printable form. */ dcb.XonChar = argv[0][0]; dcb.XoffChar = argv[1][0]; if (argv[0][0] & 0x80 || argv[1][0] & 0x80) { Tcl_UniChar character; int charLen; charLen = Tcl_UtfToUniChar(argv[0], &character); if (argv[0][charLen]) { goto badXchar; } dcb.XonChar = (char) character; charLen = Tcl_UtfToUniChar(argv[1], &character); if (argv[1][charLen]) { goto badXchar; } dcb.XoffChar = (char) character; } ckfree(argv); if (!SetCommState(infoPtr->handle, &dcb)) { goto setStateFailed; } return TCL_OK; } /* * Option -ttycontrol {DTR 1 RTS 0 BREAK 0} */ if ((len > 4) && (strncmp(optionName, "-ttycontrol", len) == 0)) { int i, result = TCL_OK; if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } if ((argc % 2) == 1) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad value \"%s\" for -ttycontrol: should be " "a list of signal,value pairs", value)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "TTYCONTROL", NULL); } ckfree(argv); return TCL_ERROR; } for (i = 0; i < argc - 1; i += 2) { if (Tcl_GetBoolean(interp, argv[i+1], &flag) == TCL_ERROR) { result = TCL_ERROR; break; } if (strncasecmp(argv[i], "DTR", strlen(argv[i])) == 0) { if (!EscapeCommFunction(infoPtr->handle, (DWORD) (flag ? SETDTR : CLRDTR))) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can't set DTR signal", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE", "TTY_SIGNAL", NULL); } result = TCL_ERROR; break; } } else if (strncasecmp(argv[i], "RTS", strlen(argv[i])) == 0) { if (!EscapeCommFunction(infoPtr->handle, (DWORD) (flag ? SETRTS : CLRRTS))) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can't set RTS signal", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE", "TTY_SIGNAL", NULL); } result = TCL_ERROR; break; } } else if (strncasecmp(argv[i], "BREAK", strlen(argv[i])) == 0) { if (!EscapeCommFunction(infoPtr->handle, (DWORD) (flag ? SETBREAK : CLRBREAK))) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can't set BREAK signal", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FCONFIGURE", "TTY_SIGNAL", NULL); } result = TCL_ERROR; break; } } else { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad signal name \"%s\" for -ttycontrol: must be" " DTR, RTS or BREAK", argv[i])); Tcl_SetErrorCode(interp, "TCL", "VALUE", "TTY_SIGNAL", NULL); } result = TCL_ERROR; break; } } ckfree(argv); return result; } /* * Option -sysbuffer {read_size write_size} * Option -sysbuffer read_size */ if ((len > 1) && (strncmp(optionName, "-sysbuffer", len) == 0)) { /* * -sysbuffer 4096 or -sysbuffer {64536 4096} */ size_t inSize = (size_t) -1, outSize = (size_t) -1; if (Tcl_SplitList(interp, value, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } if (argc == 1) { inSize = atoi(argv[0]); outSize = infoPtr->sysBufWrite; } else if (argc == 2) { inSize = atoi(argv[0]); outSize = atoi(argv[1]); } ckfree(argv); if ((argc < 1) || (argc > 2) || (inSize <= 0) || (outSize <= 0)) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad value \"%s\" for -sysbuffer: should be " "a list of one or two integers > 0", value)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "SYS_BUFFER", NULL); } return TCL_ERROR; } if (!SetupComm(infoPtr->handle, inSize, outSize)) { if (interp != NULL) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't setup comm buffers: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } infoPtr->sysBufRead = inSize; infoPtr->sysBufWrite = outSize; /* * Adjust the handshake limits. Yes, the XonXoff limits seem to * influence even hardware handshake. */ if (!GetCommState(infoPtr->handle, &dcb)) { goto getStateFailed; } dcb.XonLim = (WORD) (infoPtr->sysBufRead*1/2); dcb.XoffLim = (WORD) (infoPtr->sysBufRead*1/4); if (!SetCommState(infoPtr->handle, &dcb)) { goto setStateFailed; } return TCL_OK; } /* * Option -pollinterval msec */ if ((len > 1) && (strncmp(optionName, "-pollinterval", len) == 0)) { if (Tcl_GetInt(interp, value, &(infoPtr->blockTime)) != TCL_OK) { return TCL_ERROR; } return TCL_OK; } /* * Option -timeout msec */ if ((len > 2) && (strncmp(optionName, "-timeout", len) == 0)) { int msec; COMMTIMEOUTS tout = {0,0,0,0,0}; if (Tcl_GetInt(interp, value, &msec) != TCL_OK) { return TCL_ERROR; } tout.ReadTotalTimeoutConstant = msec; if (!SetCommTimeouts(infoPtr->handle, &tout)) { if (interp != NULL) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't set comm timeouts: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } return TCL_OK; } return Tcl_BadChannelOption(interp, optionName, "mode handshake pollinterval sysbuffer timeout ttycontrol xchar"); getStateFailed: if (interp != NULL) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get comm state: %s", Tcl_PosixError(interp))); } return TCL_ERROR; setStateFailed: if (interp != NULL) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't set comm state: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * SerialGetOptionProc -- * * Gets a mode associated with an IO channel. If the optionName arg is * non NULL, retrieves the value of that option. If the optionName arg is * NULL, retrieves a list of alternating option names and values for the * given channel. * * Results: * A standard Tcl result. Also sets the supplied DString to the string * value of the option(s) returned. * * Side effects: * The string returned by this function is in static storage and may be * reused at any time subsequent to the call. * *---------------------------------------------------------------------- */ static int SerialGetOptionProc( ClientData instanceData, /* File state. */ Tcl_Interp *interp, /* For error reporting - can be NULL. */ const char *optionName, /* Option to get. */ Tcl_DString *dsPtr) /* Where to store value(s). */ { SerialInfo *infoPtr; DCB dcb; size_t len; int valid = 0; /* Flag if valid option parsed. */ infoPtr = (SerialInfo *) instanceData; if (optionName == NULL) { len = 0; } else { len = strlen(optionName); } /* * Get option -mode */ if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-mode"); } if (len==0 || (len>2 && (strncmp(optionName, "-mode", len) == 0))) { char parity; const char *stop; char buf[2 * TCL_INTEGER_SPACE + 16]; if (!GetCommState(infoPtr->handle, &dcb)) { if (interp != NULL) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get comm state: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } valid = 1; parity = 'n'; if (dcb.Parity <= 4) { parity = "noems"[dcb.Parity]; } stop = (dcb.StopBits == ONESTOPBIT) ? "1" : (dcb.StopBits == ONE5STOPBITS) ? "1.5" : "2"; wsprintfA(buf, "%d,%c,%d,%s", dcb.BaudRate, parity, dcb.ByteSize, stop); Tcl_DStringAppendElement(dsPtr, buf); } /* * Get option -pollinterval */ if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-pollinterval"); } if (len==0 || (len>1 && strncmp(optionName, "-pollinterval", len)==0)) { char buf[TCL_INTEGER_SPACE + 1]; valid = 1; wsprintfA(buf, "%d", infoPtr->blockTime); Tcl_DStringAppendElement(dsPtr, buf); } /* * Get option -sysbuffer */ if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-sysbuffer"); Tcl_DStringStartSublist(dsPtr); } if (len==0 || (len>1 && strncmp(optionName, "-sysbuffer", len) == 0)) { char buf[TCL_INTEGER_SPACE + 1]; valid = 1; wsprintfA(buf, "%d", infoPtr->sysBufRead); Tcl_DStringAppendElement(dsPtr, buf); wsprintfA(buf, "%d", infoPtr->sysBufWrite); Tcl_DStringAppendElement(dsPtr, buf); } if (len == 0) { Tcl_DStringEndSublist(dsPtr); } /* * Get option -xchar */ if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-xchar"); Tcl_DStringStartSublist(dsPtr); } if (len==0 || (len>1 && strncmp(optionName, "-xchar", len) == 0)) { char buf[4]; valid = 1; if (!GetCommState(infoPtr->handle, &dcb)) { if (interp != NULL) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get comm state: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } sprintf(buf, "%c", dcb.XonChar); Tcl_DStringAppendElement(dsPtr, buf); sprintf(buf, "%c", dcb.XoffChar); Tcl_DStringAppendElement(dsPtr, buf); } if (len == 0) { Tcl_DStringEndSublist(dsPtr); } /* * Get option -lasterror * * Option is readonly and returned by [fconfigure chan -lasterror] but not * returned by unnamed [fconfigure chan]. */ if (len>1 && strncmp(optionName, "-lasterror", len)==0) { valid = 1; SerialErrorStr(infoPtr->lastError, dsPtr); } /* * get option -queue * * Option is readonly and returned by [fconfigure chan -queue]. */ if (len>1 && strncmp(optionName, "-queue", len)==0) { char buf[TCL_INTEGER_SPACE + 1]; COMSTAT cStat; DWORD error; int inBuffered, outBuffered, count; valid = 1; /* * Query the pending data in Tcl's internal queues. */ inBuffered = Tcl_InputBuffered(infoPtr->channel); outBuffered = Tcl_OutputBuffered(infoPtr->channel); /* * Query the number of bytes in our output queue: * 1. The bytes pending in the output thread * 2. The bytes in the system drivers buffer * The writer thread should not interfere this action. */ EnterCriticalSection(&infoPtr->csWrite); ClearCommError(infoPtr->handle, &error, &cStat); count = (int) cStat.cbOutQue + infoPtr->writeQueue; LeaveCriticalSection(&infoPtr->csWrite); wsprintfA(buf, "%d", inBuffered + cStat.cbInQue); Tcl_DStringAppendElement(dsPtr, buf); wsprintfA(buf, "%d", outBuffered + count); Tcl_DStringAppendElement(dsPtr, buf); } /* * get option -ttystatus * * Option is readonly and returned by [fconfigure chan -ttystatus] but not * returned by unnamed [fconfigure chan]. */ if (len>4 && strncmp(optionName, "-ttystatus", len)==0) { DWORD status; if (!GetCommModemStatus(infoPtr->handle, &status)) { if (interp != NULL) { TclWinConvertError(GetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get tty status: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } valid = 1; SerialModemStatusStr(status, dsPtr); } if (valid) { return TCL_OK; } return Tcl_BadChannelOption(interp, optionName, "mode pollinterval lasterror queue sysbuffer ttystatus xchar"); } /* *---------------------------------------------------------------------- * * SerialThreadActionProc -- * * Insert or remove any thread local refs to this channel. * * Results: * None. * * Side effects: * Changes thread local list of valid channels. * *---------------------------------------------------------------------- */ static void SerialThreadActionProc( ClientData instanceData, int action) { SerialInfo *infoPtr = (SerialInfo *) instanceData; /* * We do not access firstSerialPtr in the thread structures. This is not * for all serials managed by the thread, but only those we are watching. * Removal of the filevent handlers before transfer thus takes care of * this structure. */ Tcl_MutexLock(&serialMutex); if (action == TCL_CHANNEL_THREAD_INSERT) { /* * We can't copy the thread information from the channel when the * channel is created. At this time the channel back pointer has not * been set yet. However in that case the threadId has already been * set by TclpCreateCommandChannel itself, so the structure is still * good. */ SerialInit(); if (infoPtr->channel != NULL) { infoPtr->threadId = Tcl_GetChannelThread(infoPtr->channel); } } else { infoPtr->threadId = NULL; } Tcl_MutexUnlock(&serialMutex); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/tcl.dsp0000644000175000017500000007020612663660066013664 0ustar sergeisergei# Microsoft Developer Studio Project File - Name="tcl" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) External Target" 0x0106 CFG=tcl - Win32 Debug Static !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "tcl.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "tcl.mak" CFG="tcl - Win32 Debug Static" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "tcl - Win32 Release" (based on "Win32 (x86) External Target") !MESSAGE "tcl - Win32 Debug" (based on "Win32 (x86) External Target") !MESSAGE "tcl - Win32 Debug Static" (based on "Win32 (x86) External Target") !MESSAGE "tcl - Win32 Release Static" (based on "Win32 (x86) External Target") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" !IF "$(CFG)" == "tcl - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release\tcl_Dynamic" # PROP BASE Cmd_Line "nmake -nologo -f makefile.vc OPTS=none MSVCDIR=IDE" # PROP BASE Rebuild_Opt "-a" # PROP BASE Target_File "Release\tclsh85.exe" # PROP BASE Bsc_Name "" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release\tcl_Dynamic" # PROP Cmd_Line "nmake -nologo -f makefile.vc OPTS=threads MSVCDIR=IDE" # PROP Rebuild_Opt "clean release" # PROP Target_File "Release\tclsh85t.exe" # PROP Bsc_Name "" # PROP Target_Dir "" !ELSEIF "$(CFG)" == "tcl - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug\tcl_Dynamic" # PROP BASE Cmd_Line "nmake -nologo -f makefile.vc OPTS=symbols MSVCDIR=IDE" # PROP BASE Rebuild_Opt "-a" # PROP BASE Target_File "Debug\tclsh85g.exe" # PROP BASE Bsc_Name "" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug\tcl_Dynamic" # PROP Cmd_Line "nmake -nologo -f makefile.vc OPTS=threads,symbols MSVCDIR=IDE" # PROP Rebuild_Opt "clean release" # PROP Target_File "Debug\tclsh85tg.exe" # PROP Bsc_Name "" # PROP Target_Dir "" !ELSEIF "$(CFG)" == "tcl - Win32 Debug Static" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug\tcl_Static" # PROP BASE Cmd_Line "nmake -nologo -f makefile.vc OPTS=symbols,static MSVCDIR=IDE" # PROP BASE Rebuild_Opt "-a" # PROP BASE Target_File "Debug\tclsh85sg.exe" # PROP BASE Bsc_Name "" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug\tcl_Static" # PROP Cmd_Line "nmake -nologo -f makefile.vc OPTS=symbols,static MSVCDIR=IDE" # PROP Rebuild_Opt "-a" # PROP Target_File "Debug\tclsh85sg.exe" # PROP Bsc_Name "" # PROP Target_Dir "" !ELSEIF "$(CFG)" == "tcl - Win32 Release Static" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release\tcl_Static" # PROP BASE Cmd_Line "nmake -nologo -f makefile.vc OPTS=static MSVCDIR=IDE" # PROP BASE Rebuild_Opt "-a" # PROP BASE Target_File "Release\tclsh85s.exe" # PROP BASE Bsc_Name "" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release\tcl_Static" # PROP Cmd_Line "nmake -nologo -f makefile.vc OPTS=static MSVCDIR=IDE" # PROP Rebuild_Opt "-a" # PROP Target_File "Release\tclsh85s.exe" # PROP Bsc_Name "" # PROP Target_Dir "" !ENDIF # Begin Target # Name "tcl - Win32 Release" # Name "tcl - Win32 Debug" # Name "tcl - Win32 Debug Static" # Name "tcl - Win32 Release Static" !IF "$(CFG)" == "tcl - Win32 Release" !ELSEIF "$(CFG)" == "tcl - Win32 Debug" !ELSEIF "$(CFG)" == "tcl - Win32 Debug Static" !ELSEIF "$(CFG)" == "tcl - Win32 Release Static" !ENDIF # Begin Group "compat" # PROP Default_Filter "" # Begin Source File SOURCE=..\compat\dirent.h # End Source File # Begin Source File SOURCE=..\compat\dirent2.h # End Source File # Begin Source File SOURCE=..\compat\dlfcn.h # End Source File # Begin Source File SOURCE=..\compat\fixstrtod.c # End Source File # Begin Source File SOURCE=..\compat\float.h # End Source File # Begin Source File SOURCE=..\compat\gettod.c # End Source File # Begin Source File SOURCE=..\compat\limits.h # End Source File # Begin Source File SOURCE=..\compat\memcmp.c # End Source File # Begin Source File SOURCE=..\compat\opendir.c # End Source File # Begin Source File SOURCE=..\compat\README # End Source File # Begin Source File SOURCE=..\compat\stdlib.h # End Source File # Begin Source File SOURCE=..\compat\string.h # End Source File # Begin Source File SOURCE=..\compat\strncasecmp.c # End Source File # Begin Source File SOURCE=..\compat\strstr.c # End Source File # Begin Source File SOURCE=..\compat\strtod.c # End Source File # Begin Source File SOURCE=..\compat\strtol.c # End Source File # Begin Source File SOURCE=..\compat\strtoul.c # End Source File # Begin Source File SOURCE=..\compat\tclErrno.h # End Source File # Begin Source File SOURCE=..\compat\unistd.h # End Source File # Begin Source File SOURCE=..\compat\waitpid.c # End Source File # End Group # Begin Group "doc" # PROP Default_Filter "" # Begin Source File SOURCE=..\doc\Access.3 # End Source File # Begin Source File SOURCE=..\doc\AddErrInfo.3 # End Source File # Begin Source File SOURCE=..\doc\after.n # End Source File # Begin Source File SOURCE=..\doc\Alloc.3 # End Source File # Begin Source File SOURCE=..\doc\AllowExc.3 # End Source File # Begin Source File SOURCE=..\doc\append.n # End Source File # Begin Source File SOURCE=..\doc\AppInit.3 # End Source File # Begin Source File SOURCE=..\doc\array.n # End Source File # Begin Source File SOURCE=..\doc\AssocData.3 # End Source File # Begin Source File SOURCE=..\doc\Async.3 # End Source File # Begin Source File SOURCE=..\doc\BackgdErr.3 # End Source File # Begin Source File SOURCE=..\doc\Backslash.3 # End Source File # Begin Source File SOURCE=..\doc\bgerror.n # End Source File # Begin Source File SOURCE=..\doc\binary.n # End Source File # Begin Source File SOURCE=..\doc\BoolObj.3 # End Source File # Begin Source File SOURCE=..\doc\break.n # End Source File # Begin Source File SOURCE=..\doc\ByteArrObj.3 # End Source File # Begin Source File SOURCE=..\doc\CallDel.3 # End Source File # Begin Source File SOURCE=..\doc\case.n # End Source File # Begin Source File SOURCE=..\doc\catch.n # End Source File # Begin Source File SOURCE=..\doc\cd.n # End Source File # Begin Source File SOURCE=..\doc\ChnlStack.3 # End Source File # Begin Source File SOURCE=..\doc\clock.n # End Source File # Begin Source File SOURCE=..\doc\close.n # End Source File # Begin Source File SOURCE=..\doc\CmdCmplt.3 # End Source File # Begin Source File SOURCE=..\doc\Concat.3 # End Source File # Begin Source File SOURCE=..\doc\concat.n # End Source File # Begin Source File SOURCE=..\doc\continue.n # End Source File # Begin Source File SOURCE=..\doc\CrtChannel.3 # End Source File # Begin Source File SOURCE=..\doc\CrtChnlHdlr.3 # End Source File # Begin Source File SOURCE=..\doc\CrtCloseHdlr.3 # End Source File # Begin Source File SOURCE=..\doc\CrtCommand.3 # End Source File # Begin Source File SOURCE=..\doc\CrtFileHdlr.3 # End Source File # Begin Source File SOURCE=..\doc\CrtInterp.3 # End Source File # Begin Source File SOURCE=..\doc\CrtMathFnc.3 # End Source File # Begin Source File SOURCE=..\doc\CrtObjCmd.3 # End Source File # Begin Source File SOURCE=..\doc\CrtSlave.3 # End Source File # Begin Source File SOURCE=..\doc\CrtTimerHdlr.3 # End Source File # Begin Source File SOURCE=..\doc\CrtTrace.3 # End Source File # Begin Source File SOURCE=..\doc\dde.n # End Source File # Begin Source File SOURCE=..\doc\DetachPids.3 # End Source File # Begin Source File SOURCE=..\doc\DoOneEvent.3 # End Source File # Begin Source File SOURCE=..\doc\DoubleObj.3 # End Source File # Begin Source File SOURCE=..\doc\DoWhenIdle.3 # End Source File # Begin Source File SOURCE=..\doc\DString.3 # End Source File # Begin Source File SOURCE=..\doc\DumpActiveMemory.3 # End Source File # Begin Source File SOURCE=..\doc\Encoding.3 # End Source File # Begin Source File SOURCE=..\doc\encoding.n # End Source File # Begin Source File SOURCE=..\doc\Environment.3 # End Source File # Begin Source File SOURCE=..\doc\eof.n # End Source File # Begin Source File SOURCE=..\doc\error.n # End Source File # Begin Source File SOURCE=..\doc\Eval.3 # End Source File # Begin Source File SOURCE=..\doc\eval.n # End Source File # Begin Source File SOURCE=..\doc\exec.n # End Source File # Begin Source File SOURCE=..\doc\Exit.3 # End Source File # Begin Source File SOURCE=..\doc\exit.n # End Source File # Begin Source File SOURCE=..\doc\expr.n # End Source File # Begin Source File SOURCE=..\doc\ExprLong.3 # End Source File # Begin Source File SOURCE=..\doc\ExprLongObj.3 # End Source File # Begin Source File SOURCE=..\doc\fblocked.n # End Source File # Begin Source File SOURCE=..\doc\fconfigure.n # End Source File # Begin Source File SOURCE=..\doc\fcopy.n # End Source File # Begin Source File SOURCE=..\doc\file.n # End Source File # Begin Source File SOURCE=..\doc\fileevent.n # End Source File # Begin Source File SOURCE=..\doc\filename.n # End Source File # Begin Source File SOURCE=..\doc\FileSystem.3 # End Source File # Begin Source File SOURCE=..\doc\FindExec.3 # End Source File # Begin Source File SOURCE=..\doc\flush.n # End Source File # Begin Source File SOURCE=..\doc\for.n # End Source File # Begin Source File SOURCE=..\doc\foreach.n # End Source File # Begin Source File SOURCE=..\doc\format.n # End Source File # Begin Source File SOURCE=..\doc\GetCwd.3 # End Source File # Begin Source File SOURCE=..\doc\GetHostName.3 # End Source File # Begin Source File SOURCE=..\doc\GetIndex.3 # End Source File # Begin Source File SOURCE=..\doc\GetInt.3 # End Source File # Begin Source File SOURCE=..\doc\GetOpnFl.3 # End Source File # Begin Source File SOURCE=..\doc\gets.n # End Source File # Begin Source File SOURCE=..\doc\GetStdChan.3 # End Source File # Begin Source File SOURCE=..\doc\GetVersion.3 # End Source File # Begin Source File SOURCE=..\doc\glob.n # End Source File # Begin Source File SOURCE=..\doc\global.n # End Source File # Begin Source File SOURCE=..\doc\Hash.3 # End Source File # Begin Source File SOURCE=..\doc\history.n # End Source File # Begin Source File SOURCE=..\doc\http.n # End Source File # Begin Source File SOURCE=..\doc\if.n # End Source File # Begin Source File SOURCE=..\doc\incr.n # End Source File # Begin Source File SOURCE=..\doc\info.n # End Source File # Begin Source File SOURCE=..\doc\Init.3 # End Source File # Begin Source File SOURCE=..\doc\InitStubs.3 # End Source File # Begin Source File SOURCE=..\doc\Interp.3 # End Source File # Begin Source File SOURCE=..\doc\interp.n # End Source File # Begin Source File SOURCE=..\doc\IntObj.3 # End Source File # Begin Source File SOURCE=..\doc\join.n # End Source File # Begin Source File SOURCE=..\doc\lappend.n # End Source File # Begin Source File SOURCE=..\doc\library.n # End Source File # Begin Source File SOURCE=..\doc\lindex.n # End Source File # Begin Source File SOURCE=..\doc\LinkVar.3 # End Source File # Begin Source File SOURCE=..\doc\linsert.n # End Source File # Begin Source File SOURCE=..\doc\list.n # End Source File # Begin Source File SOURCE=..\doc\ListObj.3 # End Source File # Begin Source File SOURCE=..\doc\llength.n # End Source File # Begin Source File SOURCE=..\doc\load.n # End Source File # Begin Source File SOURCE=..\doc\lrange.n # End Source File # Begin Source File SOURCE=..\doc\lreplace.n # End Source File # Begin Source File SOURCE=..\doc\lsearch.n # End Source File # Begin Source File SOURCE=..\doc\lsort.n # End Source File # Begin Source File SOURCE=..\doc\man.macros # End Source File # Begin Source File SOURCE=..\doc\memory.n # End Source File # Begin Source File SOURCE=..\doc\msgcat.n # End Source File # Begin Source File SOURCE=..\doc\namespace.n # End Source File # Begin Source File SOURCE=..\doc\Notifier.3 # End Source File # Begin Source File SOURCE=..\doc\Object.3 # End Source File # Begin Source File SOURCE=..\doc\ObjectType.3 # End Source File # Begin Source File SOURCE=..\doc\open.n # End Source File # Begin Source File SOURCE=..\doc\OpenFileChnl.3 # End Source File # Begin Source File SOURCE=..\doc\OpenTcp.3 # End Source File # Begin Source File SOURCE=..\doc\package.n # End Source File # Begin Source File SOURCE=..\doc\packagens.n # End Source File # Begin Source File SOURCE=..\doc\Panic.3 # End Source File # Begin Source File SOURCE=..\doc\ParseCmd.3 # End Source File # Begin Source File SOURCE=..\doc\pid.n # End Source File # Begin Source File SOURCE=..\doc\pkgMkIndex.n # End Source File # Begin Source File SOURCE=..\doc\PkgRequire.3 # End Source File # Begin Source File SOURCE=..\doc\Preserve.3 # End Source File # Begin Source File SOURCE=..\doc\PrintDbl.3 # End Source File # Begin Source File SOURCE=..\doc\proc.n # End Source File # Begin Source File SOURCE=..\doc\puts.n # End Source File # Begin Source File SOURCE=..\doc\pwd.n # End Source File # Begin Source File SOURCE=..\doc\re_syntax.n # End Source File # Begin Source File SOURCE=..\doc\read.n # End Source File # Begin Source File SOURCE=..\doc\RecEvalObj.3 # End Source File # Begin Source File SOURCE=..\doc\RecordEval.3 # End Source File # Begin Source File SOURCE=..\doc\RegExp.3 # End Source File # Begin Source File SOURCE=..\doc\regexp.n # End Source File # Begin Source File SOURCE=..\doc\registry.n # End Source File # Begin Source File SOURCE=..\doc\regsub.n # End Source File # Begin Source File SOURCE=..\doc\rename.n # End Source File # Begin Source File SOURCE=..\doc\return.n # End Source File # Begin Source File SOURCE=..\doc\safe.n # End Source File # Begin Source File SOURCE=..\doc\SaveResult.3 # End Source File # Begin Source File SOURCE=..\doc\scan.n # End Source File # Begin Source File SOURCE=..\doc\seek.n # End Source File # Begin Source File SOURCE=..\doc\set.n # End Source File # Begin Source File SOURCE=..\doc\SetErrno.3 # End Source File # Begin Source File SOURCE=..\doc\SetRecLmt.3 # End Source File # Begin Source File SOURCE=..\doc\SetResult.3 # End Source File # Begin Source File SOURCE=..\doc\SetVar.3 # End Source File # Begin Source File SOURCE=..\doc\Signal.3 # End Source File # Begin Source File SOURCE=..\doc\Sleep.3 # End Source File # Begin Source File SOURCE=..\doc\socket.n # End Source File # Begin Source File SOURCE=..\doc\source.n # End Source File # Begin Source File SOURCE=..\doc\SourceRCFile.3 # End Source File # Begin Source File SOURCE=..\doc\split.n # End Source File # Begin Source File SOURCE=..\doc\SplitList.3 # End Source File # Begin Source File SOURCE=..\doc\SplitPath.3 # End Source File # Begin Source File SOURCE=..\doc\StaticPkg.3 # End Source File # Begin Source File SOURCE=..\doc\StdChannels.3 # End Source File # Begin Source File SOURCE=..\doc\string.n # End Source File # Begin Source File SOURCE=..\doc\StringObj.3 # End Source File # Begin Source File SOURCE=..\doc\StrMatch.3 # End Source File # Begin Source File SOURCE=..\doc\subst.n # End Source File # Begin Source File SOURCE=..\doc\SubstObj.3 # End Source File # Begin Source File SOURCE=..\doc\switch.n # End Source File # Begin Source File SOURCE=..\doc\Tcl.n # End Source File # Begin Source File SOURCE=..\doc\Tcl_Main.3 # End Source File # Begin Source File SOURCE=..\doc\TCL_MEM_DEBUG.3 # End Source File # Begin Source File SOURCE=..\doc\tclsh.1 # End Source File # Begin Source File SOURCE=..\doc\tcltest.n # End Source File # Begin Source File SOURCE=..\doc\tclvars.n # End Source File # Begin Source File SOURCE=..\doc\tell.n # End Source File # Begin Source File SOURCE=..\doc\Thread.3 # End Source File # Begin Source File SOURCE=..\doc\time.n # End Source File # Begin Source File SOURCE=..\doc\ToUpper.3 # End Source File # Begin Source File SOURCE=..\doc\trace.n # End Source File # Begin Source File SOURCE=..\doc\TraceVar.3 # End Source File # Begin Source File SOURCE=..\doc\Translate.3 # End Source File # Begin Source File SOURCE=..\doc\UniCharIsAlpha.3 # End Source File # Begin Source File SOURCE=..\doc\unknown.n # End Source File # Begin Source File SOURCE=..\doc\unset.n # End Source File # Begin Source File SOURCE=..\doc\update.n # End Source File # Begin Source File SOURCE=..\doc\uplevel.n # End Source File # Begin Source File SOURCE=..\doc\UpVar.3 # End Source File # Begin Source File SOURCE=..\doc\upvar.n # End Source File # Begin Source File SOURCE=..\doc\Utf.3 # End Source File # Begin Source File SOURCE=..\doc\variable.n # End Source File # Begin Source File SOURCE=..\doc\vwait.n # End Source File # Begin Source File SOURCE=..\doc\while.n # End Source File # Begin Source File SOURCE=..\doc\WrongNumArgs.3 # End Source File # End Group # Begin Group "generic" # PROP Default_Filter "" # Begin Source File SOURCE=..\generic\README # End Source File # Begin Source File SOURCE=..\generic\regc_color.c # End Source File # Begin Source File SOURCE=..\generic\regc_cvec.c # End Source File # Begin Source File SOURCE=..\generic\regc_lex.c # End Source File # Begin Source File SOURCE=..\generic\regc_locale.c # End Source File # Begin Source File SOURCE=..\generic\regc_nfa.c # End Source File # Begin Source File SOURCE=..\generic\regcomp.c # End Source File # Begin Source File SOURCE=..\generic\regcustom.h # End Source File # Begin Source File SOURCE=..\generic\rege_dfa.c # End Source File # Begin Source File SOURCE=..\generic\regerror.c # End Source File # Begin Source File SOURCE=..\generic\regerrs.h # End Source File # Begin Source File SOURCE=..\generic\regex.h # End Source File # Begin Source File SOURCE=..\generic\regexec.c # End Source File # Begin Source File SOURCE=..\generic\regfree.c # End Source File # Begin Source File SOURCE=..\generic\regfronts.c # End Source File # Begin Source File SOURCE=..\generic\regguts.h # End Source File # Begin Source File SOURCE=..\generic\tcl.decls # End Source File # Begin Source File SOURCE=..\generic\tcl.h # End Source File # Begin Source File SOURCE=..\generic\tclAlloc.c # End Source File # Begin Source File SOURCE=..\generic\tclAsync.c # End Source File # Begin Source File SOURCE=..\generic\tclBasic.c # End Source File # Begin Source File SOURCE=..\generic\tclBinary.c # End Source File # Begin Source File SOURCE=..\generic\tclCkalloc.c # End Source File # Begin Source File SOURCE=..\generic\tclClock.c # End Source File # Begin Source File SOURCE=..\generic\tclCmdAH.c # End Source File # Begin Source File SOURCE=..\generic\tclCmdIL.c # End Source File # Begin Source File SOURCE=..\generic\tclCmdMZ.c # End Source File # Begin Source File SOURCE=..\generic\tclCompCmds.c # End Source File # Begin Source File SOURCE=..\generic\tclCompExpr.c # End Source File # Begin Source File SOURCE=..\generic\tclCompile.c # End Source File # Begin Source File SOURCE=..\generic\tclCompile.h # End Source File # Begin Source File SOURCE=..\generic\tclDate.c # End Source File # Begin Source File SOURCE=..\generic\tclDecls.h # End Source File # Begin Source File SOURCE=..\generic\tclEncoding.c # End Source File # Begin Source File SOURCE=..\generic\tclEnv.c # End Source File # Begin Source File SOURCE=..\generic\tclEvent.c # End Source File # Begin Source File SOURCE=..\generic\tclExecute.c # End Source File # Begin Source File SOURCE=..\generic\tclFCmd.c # End Source File # Begin Source File SOURCE=..\generic\tclFileName.c # End Source File # Begin Source File SOURCE=..\generic\tclGet.c # End Source File # Begin Source File SOURCE=..\generic\tclGetDate.y # End Source File # Begin Source File SOURCE=..\generic\tclHash.c # End Source File # Begin Source File SOURCE=..\generic\tclHistory.c # End Source File # Begin Source File SOURCE=..\generic\tclIndexObj.c # End Source File # Begin Source File SOURCE=..\generic\tclInt.decls # End Source File # Begin Source File SOURCE=..\generic\tclInt.h # End Source File # Begin Source File SOURCE=..\generic\tclIntDecls.h # End Source File # Begin Source File SOURCE=..\generic\tclInterp.c # End Source File # Begin Source File SOURCE=..\generic\tclIntPlatDecls.h # End Source File # Begin Source File SOURCE=..\generic\tclIO.c # End Source File # Begin Source File SOURCE=..\generic\tclIO.h # End Source File # Begin Source File SOURCE=..\generic\tclIOCmd.c # End Source File # Begin Source File SOURCE=..\generic\tclIOGT.c # End Source File # Begin Source File SOURCE=..\generic\tclIOSock.c # End Source File # Begin Source File SOURCE=..\generic\tclIOUtil.c # End Source File # Begin Source File SOURCE=..\generic\tclLink.c # End Source File # Begin Source File SOURCE=..\generic\tclListObj.c # End Source File # Begin Source File SOURCE=..\generic\tclLiteral.c # End Source File # Begin Source File SOURCE=..\generic\tclLoad.c # End Source File # Begin Source File SOURCE=..\generic\tclLoadNone.c # End Source File # Begin Source File SOURCE=..\generic\tclMain.c # End Source File # Begin Source File SOURCE=..\generic\tclNamesp.c # End Source File # Begin Source File SOURCE=..\generic\tclNotify.c # End Source File # Begin Source File SOURCE=..\generic\tclObj.c # End Source File # Begin Source File SOURCE=..\generic\tclPanic.c # End Source File # Begin Source File SOURCE=..\generic\tclParse.c # End Source File # Begin Source File SOURCE=..\generic\tclPipe.c # End Source File # Begin Source File SOURCE=..\generic\tclPkg.c # End Source File # Begin Source File SOURCE=..\generic\tclPlatDecls.h # End Source File # Begin Source File SOURCE=..\generic\tclPort.h # End Source File # Begin Source File SOURCE=..\generic\tclPosixStr.c # End Source File # Begin Source File SOURCE=..\generic\tclPreserve.c # End Source File # Begin Source File SOURCE=..\generic\tclProc.c # End Source File # Begin Source File SOURCE=..\generic\tclRegexp.c # End Source File # Begin Source File SOURCE=..\generic\tclRegexp.h # End Source File # Begin Source File SOURCE=..\generic\tclResolve.c # End Source File # Begin Source File SOURCE=..\generic\tclResult.c # End Source File # Begin Source File SOURCE=..\generic\tclScan.c # End Source File # Begin Source File SOURCE=..\generic\tclStringObj.c # End Source File # Begin Source File SOURCE=..\generic\tclStubInit.c # End Source File # Begin Source File SOURCE=..\generic\tclStubLib.c # End Source File # Begin Source File SOURCE=..\generic\tclOOStubLib.c # End Source File # Begin Source File SOURCE=..\generic\tclTomMathStubLib.c # End Source File # Begin Source File SOURCE=..\generic\tclTest.c # End Source File # Begin Source File SOURCE=..\generic\tclTestObj.c # End Source File # Begin Source File SOURCE=..\generic\tclTestProcBodyObj.c # End Source File # Begin Source File SOURCE=..\generic\tclThread.c # End Source File # Begin Source File SOURCE=..\generic\tclThreadJoin.c # End Source File # Begin Source File SOURCE=..\generic\tclThreadTest.c # End Source File # Begin Source File SOURCE=..\generic\tclTimer.c # End Source File # Begin Source File SOURCE=..\generic\tclUniData.c # End Source File # Begin Source File SOURCE=..\generic\tclUtf.c # End Source File # Begin Source File SOURCE=..\generic\tclUtil.c # End Source File # Begin Source File SOURCE=..\generic\tclVar.c # End Source File # End Group # Begin Group "library" # PROP Default_Filter "" # Begin Source File SOURCE=..\library\auto.tcl # End Source File # Begin Source File SOURCE=..\library\history.tcl # End Source File # Begin Source File SOURCE=..\library\init.tcl # End Source File # Begin Source File SOURCE=..\library\ldAout.tcl # End Source File # Begin Source File SOURCE=..\library\package.tcl # End Source File # Begin Source File SOURCE=..\library\parray.tcl # End Source File # Begin Source File SOURCE=..\library\safe.tcl # End Source File # Begin Source File SOURCE=..\library\tclIndex # End Source File # Begin Source File SOURCE=..\library\word.tcl # End Source File # End Group # Begin Group "mac" # PROP Default_Filter "" # End Group # Begin Group "tests" # PROP Default_Filter "" # End Group # Begin Group "tools" # PROP Default_Filter "" # End Group # Begin Group "unix" # PROP Default_Filter "" # End Group # Begin Group "win" # PROP Default_Filter "" # Begin Source File SOURCE=.\aclocal.m4 # End Source File # Begin Source File SOURCE=.\cat.c # End Source File # Begin Source File SOURCE=.\configure # End Source File # Begin Source File SOURCE=.\configure.in # End Source File # Begin Source File SOURCE=.\makefile.bc # End Source File # Begin Source File SOURCE=.\Makefile.in # End Source File # Begin Source File SOURCE=.\makefile.vc # End Source File # Begin Source File SOURCE=.\mkd.bat # End Source File # Begin Source File SOURCE=.\README # End Source File # Begin Source File SOURCE=.\README.binary # End Source File # Begin Source File SOURCE=.\rmd.bat # End Source File # Begin Source File SOURCE=.\rules.vc # End Source File # Begin Source File SOURCE=.\tcl.hpj.in # End Source File # Begin Source File SOURCE=.\tcl.m4 # End Source File # Begin Source File SOURCE=.\tcl.rc # End Source File # Begin Source File SOURCE=.\tclAppInit.c # End Source File # Begin Source File SOURCE=.\tclConfig.sh.in # End Source File # Begin Source File SOURCE=.\tclsh.ico # End Source File # Begin Source File SOURCE=.\tclsh.rc # End Source File # Begin Source File SOURCE=.\tclWin32Dll.c # End Source File # Begin Source File SOURCE=.\tclWinChan.c # End Source File # Begin Source File SOURCE=.\tclWinConsole.c # End Source File # Begin Source File SOURCE=.\tclWinDde.c # End Source File # Begin Source File SOURCE=.\tclWinError.c # End Source File # Begin Source File SOURCE=.\tclWinFCmd.c # End Source File # Begin Source File SOURCE=.\tclWinFile.c # End Source File # Begin Source File SOURCE=.\tclWinInit.c # End Source File # Begin Source File SOURCE=.\tclWinInt.h # End Source File # Begin Source File SOURCE=.\tclWinLoad.c # End Source File # Begin Source File SOURCE=.\tclWinNotify.c # End Source File # Begin Source File SOURCE=.\tclWinPipe.c # End Source File # Begin Source File SOURCE=.\tclWinPort.h # End Source File # Begin Source File SOURCE=.\tclWinReg.c # End Source File # Begin Source File SOURCE=.\tclWinSerial.c # End Source File # Begin Source File SOURCE=.\tclWinSock.c # End Source File # Begin Source File SOURCE=.\tclWinTest.c # End Source File # Begin Source File SOURCE=.\tclWinThrd.c # End Source File # Begin Source File SOURCE=.\tclWinTime.c # End Source File # End Group # End Target # End Project tcl8.6.5/win/Makefile.in0000644000175000017500000006777612665173607014463 0ustar sergeisergei# # This file is a Makefile for Tcl. If it has the name "Makefile.in" then it # is a template for a Makefile; to generate the actual Makefile, run # "./configure", which is a configuration script generated by the "autoconf" # program (constructs like "@foo@" will get replaced in the actual Makefile. VERSION = @TCL_VERSION@ #-------------------------------------------------------------------------- # Things you can change to personalize the Makefile for your own site (you can # make these changes in either Makefile.in or Makefile, but changes to # Makefile will get lost if you re-run the configuration script). #-------------------------------------------------------------------------- # Default top-level directories in which to install architecture-specific # files (exec_prefix) and machine-independent files such as scripts (prefix). # The values specified here may be overridden at configure-time with the # --exec-prefix and --prefix options to the "configure" script. prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ includedir = @includedir@ datarootdir = @datarootdir@ mandir = @mandir@ # The following definition can be set to non-null for special systems like AFS # with replication. It allows the pathnames used for installation to be # different than those used for actually reference files at run-time. # INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files. INSTALL_ROOT = # Directory from which applications will reference the library of Tcl scripts # (note: you can set the TCL_LIBRARY environment variable at run-time to # override this value): TCL_LIBRARY = $(prefix)/lib/tcl$(VERSION) # Path to use at runtime to refer to LIB_INSTALL_DIR: LIB_RUNTIME_DIR = $(libdir) # Directory in which to install the program tclsh: BIN_INSTALL_DIR = $(INSTALL_ROOT)$(bindir) # Directory in which to install the .a or .so binary for the Tcl library: LIB_INSTALL_DIR = $(INSTALL_ROOT)$(libdir) # Path name to use when installing library scripts. SCRIPT_INSTALL_DIR = $(INSTALL_ROOT)$(TCL_LIBRARY) # Directory in which to install the include file tcl.h: INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir) # Directory in which to (optionally) install the private tcl headers: PRIVATE_INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(includedir) # Top-level directory in which to install manual entries: MAN_INSTALL_DIR = $(INSTALL_ROOT)$(mandir) # Directory in which to install manual entry for tclsh: MAN1_INSTALL_DIR = $(MAN_INSTALL_DIR)/man1 # Directory in which to install manual entries for Tcl's C library procedures: MAN3_INSTALL_DIR = $(MAN_INSTALL_DIR)/man3 # Directory in which to install manual entries for the built-in Tcl commands: MANN_INSTALL_DIR = $(MAN_INSTALL_DIR)/mann # Libraries built with optimization switches have this additional extension TCL_DBGX = @TCL_DBGX@ # warning flags CFLAGS_WARNING = @CFLAGS_WARNING@ # The default switches for optimization or debugging CFLAGS_DEBUG = @CFLAGS_DEBUG@ CFLAGS_OPTIMIZE = @CFLAGS_OPTIMIZE@ # To change the compiler switches, for example to change from optimization to # debugging symbols, change the following line: #CFLAGS = $(CFLAGS_DEBUG) #CFLAGS = $(CFLAGS_OPTIMIZE) #CFLAGS = $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE) CFLAGS = @CFLAGS@ @CFLAGS_DEFAULT@ -DUNICODE -D_UNICODE # To compile without backward compatibility and deprecated code uncomment the # following NO_DEPRECATED_FLAGS = #NO_DEPRECATED_FLAGS = -DTCL_NO_DEPRECATED # To enable compilation debugging reverse the comment characters on one of the # following lines. COMPILE_DEBUG_FLAGS = #COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG #COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS SRC_DIR = @srcdir@ ROOT_DIR = @srcdir@/.. TOP_DIR = $(shell cd @srcdir@/..; pwd -P) GENERIC_DIR = $(TOP_DIR)/generic TOMMATH_DIR = $(TOP_DIR)/libtommath WIN_DIR = $(TOP_DIR)/win COMPAT_DIR = $(TOP_DIR)/compat PKGS_DIR = $(TOP_DIR)/pkgs ZLIB_DIR = $(COMPAT_DIR)/zlib # Converts a POSIX path to a Windows native path. CYGPATH = @CYGPATH@ libdir_native = $(shell $(CYGPATH) '$(libdir)') bindir_native = $(shell $(CYGPATH) '$(bindir)') includedir_native = $(shell $(CYGPATH) '$(includedir)') mandir_native = $(shell $(CYGPATH) '$(mandir)') TCL_LIBRARY_NATIVE = $(shell $(CYGPATH) '$(TCL_LIBRARY)') GENERIC_DIR_NATIVE = $(shell $(CYGPATH) '$(GENERIC_DIR)') TOMMATH_DIR_NATIVE = $(shell $(CYGPATH) '$(TOMMATH_DIR)') WIN_DIR_NATIVE = $(shell $(CYGPATH) '$(WIN_DIR)') ROOT_DIR_NATIVE = $(shell $(CYGPATH) '$(ROOT_DIR)') ZLIB_DIR_NATIVE = $(shell $(CYGPATH) '$(ZLIB_DIR)') #GENERIC_DIR_NATIVE = $(GENERIC_DIR) #TOMMATH_DIR_NATIVE = $(TOMMATH_DIR) #WIN_DIR_NATIVE = $(WIN_DIR) #ROOT_DIR_NATIVE = $(ROOT_DIR) # Fully qualify library path so that `make test` # does not depend on the current directory. LIBRARY_DIR1 = $(shell cd '$(ROOT_DIR_NATIVE)/library' ; pwd -P) LIBRARY_DIR = $(shell $(CYGPATH) '$(LIBRARY_DIR1)') DLLSUFFIX = @DLLSUFFIX@ LIBSUFFIX = @LIBSUFFIX@ EXESUFFIX = @EXESUFFIX@ VER = @TCL_MAJOR_VERSION@@TCL_MINOR_VERSION@ DOTVER = @TCL_MAJOR_VERSION@.@TCL_MINOR_VERSION@ DDEVER = @TCL_DDE_MAJOR_VERSION@@TCL_DDE_MINOR_VERSION@ DDEDOTVER = @TCL_DDE_MAJOR_VERSION@.@TCL_DDE_MINOR_VERSION@ REGVER = @TCL_REG_MAJOR_VERSION@@TCL_REG_MINOR_VERSION@ REGDOTVER = @TCL_REG_MAJOR_VERSION@.@TCL_REG_MINOR_VERSION@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_DLL_FILE = @TCL_DLL_FILE@ TCL_LIB_FILE = @TCL_LIB_FILE@ DDE_DLL_FILE = tcldde$(DDEVER)${DLLSUFFIX} DDE_LIB_FILE = @LIBPREFIX@tcldde$(DDEVER)${LIBSUFFIX} REG_DLL_FILE = tclreg$(REGVER)${DLLSUFFIX} REG_LIB_FILE = @LIBPREFIX@tclreg$(REGVER)${LIBSUFFIX} TEST_DLL_FILE = tcltest$(VER)${DLLSUFFIX} TEST_LIB_FILE = @LIBPREFIX@tcltest$(VER)${LIBSUFFIX} ZLIB_DLL_FILE = zlib1.dll SHARED_LIBRARIES = $(TCL_DLL_FILE) @ZLIB_DLL_FILE@ STATIC_LIBRARIES = $(TCL_LIB_FILE) TCLSH = tclsh$(VER)${EXESUFFIX} CAT32 = cat32$(EXEEXT) MAN2TCL = man2tcl$(EXEEXT) # For cross-compiled builds, TCL_EXE is the name of a tclsh executable that is # available *BEFORE* running make for the first time. Certain build targets # (make genstubs, make install) need it to be available on the PATH. This # executable should *NOT* be required just to do a normal build although # it can be required to run make dist. TCL_EXE = @TCL_EXE@ @SET_MAKE@ # Setting the VPATH variable to a list of paths will cause the Makefile to # look into these paths when resolving .c to .obj dependencies. VPATH = $(GENERIC_DIR):$(TOMMATH_DIR):$(WIN_DIR):$(COMPAT_DIR):$(ZLIB_DIR) AR = @AR@ RANLIB = @RANLIB@ CC = @CC@ RC = @RC@ RES = @RES@ AC_FLAGS = @EXTRA_CFLAGS@ @DEFS@ CPPFLAGS = @CPPFLAGS@ LDFLAGS_DEBUG = @LDFLAGS_DEBUG@ LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@ LDFLAGS = @LDFLAGS@ @LDFLAGS_DEFAULT@ LDFLAGS_CONSOLE = @LDFLAGS_CONSOLE@ LDFLAGS_WINDOW = @LDFLAGS_WINDOW@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ STLIB_LD = @STLIB_LD@ SHLIB_LD = @SHLIB_LD@ SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ SHLIB_CFLAGS = @SHLIB_CFLAGS@ SHLIB_SUFFIX = @SHLIB_SUFFIX@ LIBS = @LIBS@ $(shell $(CYGPATH) '@ZLIB_LIBS@') RMDIR = rm -rf MKDIR = mkdir -p SHELL = @SHELL@ RM = rm -f COPY = cp CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${TCL_SHLIB_CFLAGS} \ -I"${ZLIB_DIR_NATIVE}" -I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH \ -DMP_PREC=4 -I"${TOMMATH_DIR_NATIVE}" -I"${WIN_DIR_NATIVE}" \ ${AC_FLAGS} ${COMPILE_DEBUG_FLAGS} ${NO_DEPRECATED_FLAGS} CC_OBJNAME = @CC_OBJNAME@ CC_EXENAME = @CC_EXENAME@ STUB_CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \ -I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH -DMP_PREC=4 -I"${TOMMATH_DIR_NATIVE}" \ -I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \ ${COMPILE_DEBUG_FLAGS} TCLTEST_OBJS = \ tclTest.$(OBJEXT) \ tclTestObj.$(OBJEXT) \ tclTestProcBodyObj.$(OBJEXT) \ tclThreadTest.$(OBJEXT) \ tclWinTest.$(OBJEXT) GENERIC_OBJS = \ regcomp.$(OBJEXT) \ regexec.$(OBJEXT) \ regfree.$(OBJEXT) \ regerror.$(OBJEXT) \ tclAlloc.$(OBJEXT) \ tclAssembly.$(OBJEXT) \ tclAsync.$(OBJEXT) \ tclBasic.$(OBJEXT) \ tclBinary.$(OBJEXT) \ tclCkalloc.$(OBJEXT) \ tclClock.$(OBJEXT) \ tclCmdAH.$(OBJEXT) \ tclCmdIL.$(OBJEXT) \ tclCmdMZ.$(OBJEXT) \ tclCompCmds.$(OBJEXT) \ tclCompCmdsGR.$(OBJEXT) \ tclCompCmdsSZ.$(OBJEXT) \ tclCompExpr.$(OBJEXT) \ tclCompile.$(OBJEXT) \ tclConfig.$(OBJEXT) \ tclDate.$(OBJEXT) \ tclDictObj.$(OBJEXT) \ tclDisassemble.$(OBJEXT) \ tclEncoding.$(OBJEXT) \ tclEnsemble.$(OBJEXT) \ tclEnv.$(OBJEXT) \ tclEvent.$(OBJEXT) \ tclExecute.$(OBJEXT) \ tclFCmd.$(OBJEXT) \ tclFileName.$(OBJEXT) \ tclGet.$(OBJEXT) \ tclHash.$(OBJEXT) \ tclHistory.$(OBJEXT) \ tclIndexObj.$(OBJEXT) \ tclInterp.$(OBJEXT) \ tclIO.$(OBJEXT) \ tclIOCmd.$(OBJEXT) \ tclIOGT.$(OBJEXT) \ tclIORChan.$(OBJEXT) \ tclIORTrans.$(OBJEXT) \ tclIOSock.$(OBJEXT) \ tclIOUtil.$(OBJEXT) \ tclLink.$(OBJEXT) \ tclLiteral.$(OBJEXT) \ tclListObj.$(OBJEXT) \ tclLoad.$(OBJEXT) \ tclMain.$(OBJEXT) \ tclMain2.$(OBJEXT) \ tclNamesp.$(OBJEXT) \ tclNotify.$(OBJEXT) \ tclOO.$(OBJEXT) \ tclOOBasic.$(OBJEXT) \ tclOOCall.$(OBJEXT) \ tclOODefineCmds.$(OBJEXT) \ tclOOInfo.$(OBJEXT) \ tclOOMethod.$(OBJEXT) \ tclOOStubInit.$(OBJEXT) \ tclObj.$(OBJEXT) \ tclOptimize.$(OBJEXT) \ tclPanic.$(OBJEXT) \ tclParse.$(OBJEXT) \ tclPathObj.$(OBJEXT) \ tclPipe.$(OBJEXT) \ tclPkg.$(OBJEXT) \ tclPkgConfig.$(OBJEXT) \ tclPosixStr.$(OBJEXT) \ tclPreserve.$(OBJEXT) \ tclProc.$(OBJEXT) \ tclRegexp.$(OBJEXT) \ tclResolve.$(OBJEXT) \ tclResult.$(OBJEXT) \ tclScan.$(OBJEXT) \ tclStringObj.$(OBJEXT) \ tclStrToD.$(OBJEXT) \ tclStubInit.$(OBJEXT) \ tclThread.$(OBJEXT) \ tclThreadAlloc.$(OBJEXT) \ tclThreadJoin.$(OBJEXT) \ tclThreadStorage.$(OBJEXT) \ tclTimer.$(OBJEXT) \ tclTomMathInterface.$(OBJEXT) \ tclTrace.$(OBJEXT) \ tclUtf.$(OBJEXT) \ tclUtil.$(OBJEXT) \ tclVar.$(OBJEXT) \ tclZlib.$(OBJEXT) TOMMATH_OBJS = \ bncore.${OBJEXT} \ bn_reverse.${OBJEXT} \ bn_fast_s_mp_mul_digs.${OBJEXT} \ bn_fast_s_mp_sqr.${OBJEXT} \ bn_mp_add.${OBJEXT} \ bn_mp_add_d.${OBJEXT} \ bn_mp_and.${OBJEXT} \ bn_mp_clamp.${OBJEXT} \ bn_mp_clear.${OBJEXT} \ bn_mp_clear_multi.${OBJEXT} \ bn_mp_cmp.${OBJEXT} \ bn_mp_cmp_d.${OBJEXT} \ bn_mp_cmp_mag.${OBJEXT} \ bn_mp_cnt_lsb.${OBJEXT} \ bn_mp_copy.${OBJEXT} \ bn_mp_count_bits.${OBJEXT} \ bn_mp_div.${OBJEXT} \ bn_mp_div_d.${OBJEXT} \ bn_mp_div_2.${OBJEXT} \ bn_mp_div_2d.${OBJEXT} \ bn_mp_div_3.${OBJEXT} \ bn_mp_exch.${OBJEXT} \ bn_mp_expt_d.${OBJEXT} \ bn_mp_grow.${OBJEXT} \ bn_mp_init.${OBJEXT} \ bn_mp_init_copy.${OBJEXT} \ bn_mp_init_multi.${OBJEXT} \ bn_mp_init_set.${OBJEXT} \ bn_mp_init_set_int.${OBJEXT} \ bn_mp_init_size.${OBJEXT} \ bn_mp_karatsuba_mul.${OBJEXT} \ bn_mp_karatsuba_sqr.$(OBJEXT) \ bn_mp_lshd.${OBJEXT} \ bn_mp_mod.${OBJEXT} \ bn_mp_mod_2d.${OBJEXT} \ bn_mp_mul.${OBJEXT} \ bn_mp_mul_2.${OBJEXT} \ bn_mp_mul_2d.${OBJEXT} \ bn_mp_mul_d.${OBJEXT} \ bn_mp_neg.${OBJEXT} \ bn_mp_or.${OBJEXT} \ bn_mp_radix_size.${OBJEXT} \ bn_mp_radix_smap.${OBJEXT} \ bn_mp_read_radix.${OBJEXT} \ bn_mp_rshd.${OBJEXT} \ bn_mp_set.${OBJEXT} \ bn_mp_set_int.${OBJEXT} \ bn_mp_shrink.${OBJEXT} \ bn_mp_sqr.${OBJEXT} \ bn_mp_sqrt.${OBJEXT} \ bn_mp_sub.${OBJEXT} \ bn_mp_sub_d.${OBJEXT} \ bn_mp_to_unsigned_bin.${OBJEXT} \ bn_mp_to_unsigned_bin_n.${OBJEXT} \ bn_mp_toom_mul.${OBJEXT} \ bn_mp_toom_sqr.${OBJEXT} \ bn_mp_toradix_n.${OBJEXT} \ bn_mp_unsigned_bin_size.${OBJEXT} \ bn_mp_xor.${OBJEXT} \ bn_mp_zero.${OBJEXT} \ bn_s_mp_add.${OBJEXT} \ bn_s_mp_mul_digs.${OBJEXT} \ bn_s_mp_sqr.${OBJEXT} \ bn_s_mp_sub.${OBJEXT} WIN_OBJS = \ tclWin32Dll.$(OBJEXT) \ tclWinChan.$(OBJEXT) \ tclWinConsole.$(OBJEXT) \ tclWinSerial.$(OBJEXT) \ tclWinError.$(OBJEXT) \ tclWinFCmd.$(OBJEXT) \ tclWinFile.$(OBJEXT) \ tclWinInit.$(OBJEXT) \ tclWinLoad.$(OBJEXT) \ tclWinNotify.$(OBJEXT) \ tclWinPipe.$(OBJEXT) \ tclWinSock.$(OBJEXT) \ tclWinThrd.$(OBJEXT) \ tclWinTime.$(OBJEXT) DDE_OBJS = tclWinDde.$(OBJEXT) REG_OBJS = tclWinReg.$(OBJEXT) STUB_OBJS = \ tclStubLib.$(OBJEXT) \ tclTomMathStubLib.$(OBJEXT) \ tclOOStubLib.$(OBJEXT) TCLSH_OBJS = tclAppInit.$(OBJEXT) ZLIB_OBJS = \ adler32.$(OBJEXT) \ compress.$(OBJEXT) \ crc32.$(OBJEXT) \ deflate.$(OBJEXT) \ infback.$(OBJEXT) \ inffast.$(OBJEXT) \ inflate.$(OBJEXT) \ inftrees.$(OBJEXT) \ trees.$(OBJEXT) \ uncompr.$(OBJEXT) \ zutil.$(OBJEXT) TCL_OBJS = ${GENERIC_OBJS} $(TOMMATH_OBJS) ${WIN_OBJS} @ZLIB_OBJS@ TCL_DOCS = "$(ROOT_DIR_NATIVE)"/doc/*.[13n] all: binaries libraries doc packages tcltest: $(TCLSH) $(TEST_DLL_FILE) binaries: $(TCL_STUB_LIB_FILE) @LIBRARIES@ winextensions $(TCLSH) winextensions: ${DDE_DLL_FILE} ${REG_DLL_FILE} libraries: doc: $(TCLSH): $(TCLSH_OBJS) @LIBRARIES@ $(TCL_STUB_LIB_FILE) tclsh.$(RES) $(CC) $(CFLAGS) $(TCLSH_OBJS) $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) $(LIBS) \ tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE) @VC_MANIFEST_EMBED_EXE@ cat32.$(OBJEXT): cat.c $(CC) -c $(CC_SWITCHES) @DEPARG@ $(CC_OBJNAME) $(CAT32): cat32.$(OBJEXT) $(CC) $(CFLAGS) cat32.$(OBJEXT) $(CC_EXENAME) $(LIBS) $(LDFLAGS_CONSOLE) # The following targets are configured by autoconf to generate either a shared # library or static library ${TCL_STUB_LIB_FILE}: ${STUB_OBJS} @$(RM) ${TCL_STUB_LIB_FILE} @MAKE_STUB_LIB@ ${STUB_OBJS} @POST_MAKE_LIB@ ${TCL_DLL_FILE}: ${TCL_OBJS} tcl.$(RES) @ZLIB_DLL_FILE@ @$(RM) ${TCL_DLL_FILE} $(TCL_LIB_FILE) @MAKE_DLL@ ${TCL_OBJS} tcl.$(RES) $(SHLIB_LD_LIBS) @VC_MANIFEST_EMBED_DLL@ ${TCL_LIB_FILE}: ${TCL_OBJS} ${DDE_OBJS} ${REG_OBJS} @$(RM) ${TCL_LIB_FILE} @MAKE_LIB@ ${TCL_OBJS} ${DDE_OBJS} ${REG_OBJS} @POST_MAKE_LIB@ ${DDE_DLL_FILE}: ${TCL_STUB_LIB_FILE} ${DDE_OBJS} @MAKE_DLL@ ${DDE_OBJS} $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS) ${REG_DLL_FILE}: ${TCL_STUB_LIB_FILE} ${REG_OBJS} @MAKE_DLL@ ${REG_OBJS} $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS) ${TEST_DLL_FILE}: ${TCL_STUB_LIB_FILE} ${TCLTEST_OBJS} @$(RM) ${TEST_DLL_FILE} ${TEST_LIB_FILE} @MAKE_DLL@ ${TCLTEST_OBJS} $(TCL_STUB_LIB_FILE) $(SHLIB_LD_LIBS) # use pre-built zlib1.dll ${ZLIB_DLL_FILE}: ${TCL_STUB_LIB_FILE} @if test "@ZLIB_LIBS@set" != "${ZLIB_DIR_NATIVE}/win32/zdll.libset" ; then \ $(COPY) $(ZLIB_DIR)/win64/${ZLIB_DLL_FILE} ${ZLIB_DLL_FILE}; \ else \ $(COPY) $(ZLIB_DIR)/win32/${ZLIB_DLL_FILE} ${ZLIB_DLL_FILE}; \ fi; # Add the object extension to the implicit rules. By default .obj is not # automatically added. .SUFFIXES: .${OBJEXT} .SUFFIXES: .$(RES) .SUFFIXES: .rc # Special case object targets tclWinInit.${OBJEXT}: tclWinInit.c $(CC) -c $(CC_SWITCHES) -DBUILD_tcl $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME) tclWinPipe.${OBJEXT}: tclWinPipe.c $(CC) -c $(CC_SWITCHES) -DBUILD_tcl $(EXTFLAGS) @DEPARG@ $(CC_OBJNAME) testMain.${OBJEXT}: tclAppInit.c $(CC) -c $(CC_SWITCHES) -DTCL_TEST @DEPARG@ $(CC_OBJNAME) tclMain2.${OBJEXT}: tclMain.c $(CC) -c $(CC_SWITCHES) -DBUILD_tcl -DTCL_ASCII_MAIN @DEPARG@ $(CC_OBJNAME) # TIP #59, embedding of configuration information into the binary library. # # Part of Tcl's configuration information are the paths where it was installed # and where it will look for its libraries (which can be different). We derive # this information from the variables which can be overridden by the user. As # every path can be configured separately we do not remember one general # prefix/exec_prefix but all the different paths individually. tclPkgConfig.${OBJEXT}: tclPkgConfig.c $(CC) -c $(CC_SWITCHES) \ -DCFG_INSTALL_LIBDIR=\"$(LIB_INSTALL_DIR_NATIVE)\" \ -DCFG_INSTALL_BINDIR=\"$(BIN_INSTALL_DIR_NATIVE)\" \ -DCFG_INSTALL_SCRDIR=\"$(SCRIPT_INSTALL_DIR_NATIVE)\" \ -DCFG_INSTALL_INCDIR=\"$(INCLUDE_INSTALL_DIR_NATIVE)\" \ -DCFG_INSTALL_DOCDIR=\"$(MAN_INSTALL_DIR)\" \ \ -DCFG_RUNTIME_LIBDIR=\"$(libdir_native)\" \ -DCFG_RUNTIME_BINDIR=\"$(bindir_native)\" \ -DCFG_RUNTIME_SCRDIR=\"$(TCL_LIBRARY_NATIVE)\" \ -DCFG_RUNTIME_INCDIR=\"$(includedir_native)\" \ -DCFG_RUNTIME_DOCDIR=\"$(mandir_native)\" \ -DBUILD_tcl \ @DEPARG@ $(CC_OBJNAME) # The following objects are part of the stub library and should not be built # as DLL objects but none of the symbols should be exported tclStubLib.${OBJEXT}: tclStubLib.c $(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME) tclTomMathStubLib.${OBJEXT}: tclTomMathStubLib.c $(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME) tclOOStubLib.${OBJEXT}: tclOOStubLib.c $(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME) # Implicit rule for all object files that will end up in the Tcl library %.${OBJEXT}: %.c $(CC) -c $(CC_SWITCHES) -DBUILD_tcl @DEPARG@ $(CC_OBJNAME) .rc.$(RES): $(RC) @RC_OUT@ $@ @RC_TYPE@ @RC_DEFINES@ @RC_INCLUDE@ "$(GENERIC_DIR_NATIVE)" @RC_INCLUDE@ "$(WIN_DIR_NATIVE)" @DEPARG@ # The following target generates the file generic/tclDate.c from the yacc # grammar found in generic/tclGetDate.y. This is only run by hand as yacc is # not available in all environments. The name of the .c file is different than # the name of the .y file so that make doesn't try to automatically regenerate # the .c file. gendate: bison --output-file=$(GENERIC_DIR)/tclDate.c \ --name-prefix=TclDate \ --no-lines \ $(GENERIC_DIR)/tclGetDate.y # The following target generates the file generic/tclTomMath.h. It needs to be # run (and the results checked) after updating to a new release of libtommath. gentommath_h: $(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/fix_tommath_h.tcl" \ "$(TOMMATH_DIR_NATIVE)/tommath.h" \ > "$(GENERIC_DIR_NATIVE)/tclTomMath.h" install: all install-binaries install-libraries install-doc install-packages install-binaries: binaries @for i in "$(LIB_INSTALL_DIR)" "$(BIN_INSTALL_DIR)" ; \ do \ if [ ! -d $$i ] ; then \ echo "Making directory $$i"; \ $(MKDIR) $$i; \ chmod 755 $$i; \ else true; \ fi; \ done; @for i in dde${DDEDOTVER} reg${REGDOTVER}; \ do \ if [ ! -d $(LIB_INSTALL_DIR)/$$i ] ; then \ echo "Making directory $(LIB_INSTALL_DIR)/$$i"; \ $(MKDIR) $(LIB_INSTALL_DIR)/$$i; \ else true; \ fi; \ done; @for i in $(TCL_DLL_FILE) $(ZLIB_DLL_FILE) $(TCLSH); \ do \ if [ -f $$i ]; then \ echo "Installing $$i to $(BIN_INSTALL_DIR)/"; \ $(COPY) $$i "$(BIN_INSTALL_DIR)"; \ fi; \ done @for i in tclConfig.sh tclooConfig.sh $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE); \ do \ if [ -f $$i ]; then \ echo "Installing $$i to $(LIB_INSTALL_DIR)/"; \ $(COPY) $$i "$(LIB_INSTALL_DIR)"; \ fi; \ done @if [ -f $(DDE_DLL_FILE) ]; then \ echo Installing $(DDE_DLL_FILE); \ $(COPY) $(DDE_DLL_FILE) $(LIB_INSTALL_DIR)/dde${DDEDOTVER}; \ $(COPY) $(ROOT_DIR)/library/dde/pkgIndex.tcl \ $(LIB_INSTALL_DIR)/dde${DDEDOTVER}; \ fi @if [ -f $(DDE_LIB_FILE) ]; then \ echo Installing $(DDE_LIB_FILE); \ $(COPY) $(DDE_LIB_FILE) $(LIB_INSTALL_DIR)/dde${DDEDOTVER}; \ fi @if [ -f $(REG_DLL_FILE) ]; then \ echo Installing $(REG_DLL_FILE); \ $(COPY) $(REG_DLL_FILE) $(LIB_INSTALL_DIR)/reg${REGDOTVER}; \ $(COPY) $(ROOT_DIR)/library/reg/pkgIndex.tcl \ $(LIB_INSTALL_DIR)/reg${REGDOTVER}; \ fi @if [ -f $(REG_LIB_FILE) ]; then \ echo Installing $(REG_LIB_FILE); \ $(COPY) $(REG_LIB_FILE) $(LIB_INSTALL_DIR)/reg${REGDOTVER}; \ fi install-libraries: libraries install-tzdata install-msgs @for i in "$$($(CYGPATH) $(prefix)/lib)" "$(INCLUDE_INSTALL_DIR)" \ $(SCRIPT_INSTALL_DIR); \ do \ if [ ! -d $$i ] ; then \ echo "Making directory $$i"; \ $(MKDIR) $$i; \ else true; \ fi; \ done; @for i in http1.0 opt0.4 encoding ../tcl8 ../tcl8/8.4 ../tcl8/8.4/platform ../tcl8/8.5 ../tcl8/8.6; \ do \ if [ ! -d $(SCRIPT_INSTALL_DIR)/$$i ] ; then \ echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \ $(MKDIR) $(SCRIPT_INSTALL_DIR)/$$i; \ else true; \ fi; \ done; @echo "Installing header files"; @for i in "$(GENERIC_DIR)/tcl.h" "$(GENERIC_DIR)/tclDecls.h" \ "$(GENERIC_DIR)/tclOO.h" "$(GENERIC_DIR)/tclOODecls.h" \ "$(GENERIC_DIR)/tclPlatDecls.h" \ "$(GENERIC_DIR)/tclTomMath.h" \ "$(GENERIC_DIR)/tclTomMathDecls.h"; \ do \ $(COPY) "$$i" "$(INCLUDE_INSTALL_DIR)"; \ done; @echo "Installing library files to $(SCRIPT_INSTALL_DIR)"; @for i in $(ROOT_DIR)/library/*.tcl $(ROOT_DIR)/library/tclIndex; \ do \ $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \ done; @echo "Installing library http1.0 directory"; @for j in $(ROOT_DIR)/library/http1.0/*.tcl; \ do \ $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/http1.0"; \ done; @echo "Installing package http 2.8.9 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/http/http.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.6/http-2.8.9.tm; @echo "Installing library opt0.4 directory"; @for j in $(ROOT_DIR)/library/opt/*.tcl; \ do \ $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \ done; @echo "Installing package msgcat 1.6.0 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/msgcat-1.6.0.tm; @echo "Installing package tcltest 2.3.8 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/tcltest-2.3.8.tm; @echo "Installing package platform 1.0.14 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/platform/platform.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/platform-1.0.14.tm; @echo "Installing package platform::shell 1.1.4 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/platform/shell.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.4/platform/shell-1.1.4.tm; @echo "Installing encodings"; @for i in $(ROOT_DIR)/library/encoding/*.enc ; do \ $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)/encoding"; \ done; install-tzdata: @echo "Installing time zone data" @$(TCL_EXE) "$(ROOT_DIR)/tools/installData.tcl" \ "$(ROOT_DIR)/library/tzdata" "$(SCRIPT_INSTALL_DIR)/tzdata" install-msgs: @echo "Installing message catalogs" @$(TCL_EXE) "$(ROOT_DIR)/tools/installData.tcl" \ "$(ROOT_DIR)/library/msgs" "$(SCRIPT_INSTALL_DIR)/msgs" install-doc: doc # Optional target to install private headers install-private-headers: libraries @for i in $(PRIVATE_INCLUDE_INSTALL_DIR); \ do \ if [ ! -d $$i ] ; then \ echo "Making directory $$i"; \ $(MKDIR) $$i; \ else true; \ fi; \ done; @echo "Installing private header files"; @for i in "$(GENERIC_DIR)/tclInt.h" "$(GENERIC_DIR)/tclIntDecls.h" \ "$(GENERIC_DIR)/tclIntPlatDecls.h" "$(GENERIC_DIR)/tclPort.h" \ "$(GENERIC_DIR)/tclOOInt.h" "$(GENERIC_DIR)/tclOOIntDecls.h" \ "$(WIN_DIR)/tclWinPort.h" ; \ do \ $(COPY) "$$i" "$(PRIVATE_INCLUDE_INSTALL_DIR)"; \ done; # Specifying TESTFLAGS on the command line is the standard way to pass args to # tcltest, i.e.: # % make test TESTFLAGS="-verbose bps -file fileName.test" test: test-tcl test-packages test-tcl: binaries $(TCLSH) $(CAT32) $(TEST_DLL_FILE) TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \ ./$(TCLSH) "$(ROOT_DIR_NATIVE)/tests/all.tcl" $(TESTFLAGS) \ -load "package ifneeded Tcltest ${VERSION}@TCL_PATCH_LEVEL@ [list load [file normalize ${TEST_DLL_FILE}] Tcltest]; \ package ifneeded dde 1.4.0 [list load [file normalize ${DDE_DLL_FILE}] dde]; \ package ifneeded registry 1.3.1 [list load [file normalize ${REG_DLL_FILE}] registry]" | ./$(CAT32) # Useful target to launch a built tclsh with the proper path,... runtest: binaries $(TCLSH) $(TEST_DLL_FILE) @TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \ ./$(TCLSH) $(TESTFLAGS) -load "package ifneeded Tcltest ${VERSION}@TCL_PATCH_LEVEL@ [list load [file normalize ${TEST_DLL_FILE}] Tcltest]; \ package ifneeded dde 1.4.0 [list load [file normalize ${DDE_DLL_FILE}] dde]; \ package ifneeded registry 1.3.1 [list load [file normalize ${REG_DLL_FILE}] registry]" $(SCRIPT) # This target can be used to run tclsh from the build directory via # `make shell SCRIPT=foo.tcl` shell: binaries @TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \ ./$(TCLSH) $(SCRIPT) # This target can be used to run tclsh inside either gdb or insight gdb: binaries @echo "set env TCL_LIBRARY=$(LIBRARY_DIR)" > gdb.run gdb ./$(TCLSH) --command=gdb.run rm gdb.run depend: Makefile: $(SRC_DIR)/Makefile.in ./config.status cleanhelp: $(RM) *.hlp *.cnt *.GID *.rtf man2tcl.exe clean: cleanhelp clean-packages $(RM) *.lib *.a *.exp *.dll *.$(RES) *.${OBJEXT} *~ \#* TAGS a.out $(RM) $(TCLSH) $(CAT32) $(RM) *.pch *.ilk *.pdb distclean: distclean-packages clean $(RM) Makefile config.status config.cache config.log tclConfig.sh \ tcl.hpj config.status.lineno # # Bundled package targets # PKG_CFG_ARGS = @PKG_CFG_ARGS@ PKG_DIR = ./pkgs packages: @builddir=`$(CYGPATH) $$(pwd -P)`; \ for i in $(PKGS_DIR)/*; do \ if [ -d $$i ] ; then \ if [ -x $$i/configure ] ; then \ pkg=`basename $$i`; \ mkdir -p $(PKG_DIR)/$$pkg; \ if [ ! -f $(PKG_DIR)/$$pkg/Makefile ]; then \ ( cd $(PKG_DIR)/$$pkg; \ echo "Configuring package '$$i' wd = `$(CYGPATH) $$(pwd -P)`"; \ $$i/configure --with-tcl=$$builddir --with-tclinclude=$(GENERIC_DIR_NATIVE) $(PKG_CFG_ARGS) --enable-shared --enable-threads; ) \ fi ; \ echo "Building package '$$pkg'"; \ ( cd $(PKG_DIR)/$$pkg; $(MAKE); ) \ fi; \ fi; \ done; \ cd $$builddir install-packages: packages @builddir=`pwd -P`; \ for i in $(PKGS_DIR)/*; do \ if [ -d $$i ]; then \ pkg=`basename $$i`; \ if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \ echo "Installing package '$$pkg'"; \ ( cd $(PKG_DIR)/$$pkg; $(MAKE) install "DESTDIR=$(INSTALL_ROOT)"; ) \ fi; \ fi; \ done; \ cd $$builddir test-packages: tcltest packages @builddir=`pwd -P`; \ for i in $(PKGS_DIR)/*; do \ if [ -d $$i ]; then \ pkg=`basename $$i`; \ if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \ echo "Testing package '$$pkg'"; \ ( cd $(PKG_DIR)/$$pkg; $(MAKE) "LD_LIBRARY_PATH=$$builddir:${LD_LIBRARY_PATH}" "TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" "TCLLIBPATH=$$builddir/pkgs" test "TCLSH_PROG=$$builddir/${TCLSH}"; ) \ fi; \ fi; \ done; \ cd $$builddir clean-packages: @builddir=`pwd -P`; \ for i in $(PKGS_DIR)/*; do \ if [ -d $$i ]; then \ pkg=`basename $$i`; \ if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \ ( cd $(PKG_DIR)/$$pkg; $(MAKE) clean; ) \ fi; \ fi; \ done; \ cd $$builddir distclean-packages: @builddir=`pwd -P`; \ for i in $(PKGS_DIR)/*; do \ if [ -d $$i ]; then \ pkg=`basename $$i`; \ if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \ ( cd $(PKG_DIR)/$$pkg; $(MAKE) distclean; ) \ fi; \ cd $$builddir; \ rm -rf $(PKG_DIR)/$$pkg; \ fi; \ done; \ rm -rf $(PKG_DIR) # # Regenerate the stubs files. # $(GENERIC_DIR)/tclStubInit.c: $(GENERIC_DIR)/tcl.decls \ $(GENERIC_DIR)/tclInt.decls @echo "Warning: tclStubInit.c may be out of date." @echo "Developers may want to run \"make genstubs\" to regenerate." @echo "This warning can be safely ignored, do not report as a bug!" genstubs: $(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/genStubs.tcl" \ "$(GENERIC_DIR_NATIVE)" \ "$(GENERIC_DIR_NATIVE)/tcl.decls" \ "$(GENERIC_DIR_NATIVE)/tclInt.decls" \ "$(GENERIC_DIR_NATIVE)/tclTomMath.decls" $(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/genStubs.tcl" \ "$(GENERIC_DIR_NATIVE)" \ "$(GENERIC_DIR_NATIVE)/tclOO.decls" # # This target creates the HTML folder for Tcl & Tk and places it in # DISTDIR/html. It uses the tcltk-man2html.tcl tool from the Tcl group's tool # workspace. It depends on the Tcl & Tk being in directories called tcl8.* & # tk8.* up two directories from the TOOL_DIR. # TOOL_DIR=$(ROOT_DIR)/tools HTML_INSTALL_DIR=$(ROOT_DIR)/html html: $(MAKE) shell SCRIPT="$(TOOL_DIR)/tcltk-man2html.tcl --htmldir=$(HTML_INSTALL_DIR) --srcdir=$(ROOT_DIR)/.. $(BUILD_HTML_FLAGS)" html-tcl: $(TCLSH) $(MAKE) shell SCRIPT="$(TOOL_DIR)/tcltk-man2html.tcl --htmldir=$(HTML_INSTALL_DIR) --srcdir=$(ROOT_DIR)/.. $(BUILD_HTML_FLAGS) --tcl" html-tk: $(TCLSH) $(MAKE) shell SCRIPT="$(TOOL_DIR)/tcltk-man2html.tcl --htmldir=$(HTML_INSTALL_DIR) --srcdir=$(ROOT_DIR)/.. $(BUILD_HTML_FLAGS) --tk" # # The list of all the targets that do not correspond to real files. This stops # 'make' from getting confused when someone makes an error in a rule. # .PHONY: all tcltest binaries libraries doc gendate gentommath_h install .PHONY: install-binaries install-libraries install-tzdata install-msgs .PHONY: install-doc install-private-headers test test-tcl runtest shell .PHONY: gdb depend cleanhelp clean distclean packages install-packages .PHONY: test-packages clean-packages distclean-packages genstubs html .PHONY: html-tcl html-tk # DO NOT DELETE THIS LINE -- make depend depends on it. tcl8.6.5/win/tclooConfig.sh0000644000175000017500000000140512665173607015171 0ustar sergeisergei# tclooConfig.sh -- # # This shell script (for sh) is generated automatically by TclOO's configure # script, or would be except it has no values that we substitute. It will # create shell variables for most of the configuration options discovered by # the configure script. This script is intended to be included by TEA-based # configure scripts for TclOO extensions so that they don't have to figure # this all out for themselves. # # The information in this file is specific to a single platform. # These are mostly empty because no special steps are ever needed from Tcl 8.6 # onwards; all libraries and include files are just part of Tcl. TCLOO_LIB_SPEC="" TCLOO_STUB_LIB_SPEC="" TCLOO_INCLUDE_SPEC="" TCLOO_PRIVATE_INCLUDE_SPEC="" TCLOO_CFLAGS="" TCLOO_VERSION=1.0.4 tcl8.6.5/win/tclWinTest.c0000644000175000017500000004036012663660066014634 0ustar sergeisergei/* * tclWinTest.c -- * * Contains commands for platform specific tests on Windows. * * Copyright (c) 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. */ #ifndef USE_TCL_STUBS # define USE_TCL_STUBS #endif #include "tclInt.h" /* * For TestplatformChmod on Windows */ #ifdef _WIN32 #include #endif /* * MinGW 3.4.2 does not define this. */ #ifndef INHERITED_ACE #define INHERITED_ACE (0x10) #endif /* * Forward declarations of functions defined later in this file: */ static int TesteventloopCmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj *const objv[]); static int TestvolumetypeCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestwinclockCmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj *const objv[]); static int TestwinsleepCmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj *const objv[]); static Tcl_ObjCmdProc TestExceptionCmd; static int TestplatformChmod(const char *nativePath, int pmode); static int TestchmodCmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj *const objv[]); /* *---------------------------------------------------------------------- * * TclplatformtestInit -- * * Defines commands that test platform specific functionality for Windows * platforms. * * Results: * A standard Tcl result. * * Side effects: * Defines new commands. * *---------------------------------------------------------------------- */ int TclplatformtestInit( Tcl_Interp *interp) /* Interpreter to add commands to. */ { /* * Add commands for platform specific tests for Windows here. */ Tcl_CreateObjCommand(interp, "testchmod", TestchmodCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testeventloop", TesteventloopCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testvolumetype", TestvolumetypeCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testwinclock", TestwinclockCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testwinsleep", TestwinsleepCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testexcept", TestExceptionCmd, NULL, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TesteventloopCmd -- * * This function implements the "testeventloop" command. It is used to * test the Tcl notifier from an "external" event loop (i.e. not * Tcl_DoOneEvent()). * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TesteventloopCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static int *framePtr = NULL;/* Pointer to integer on stack frame of * innermost invocation of the "wait" * subcommand. */ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ..."); return TCL_ERROR; } if (strcmp(Tcl_GetString(objv[1]), "done") == 0) { *framePtr = 1; } else if (strcmp(Tcl_GetString(objv[1]), "wait") == 0) { int *oldFramePtr, done; int oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); /* * Save the old stack frame pointer and set up the current frame. */ oldFramePtr = framePtr; framePtr = &done; /* * Enter a standard Windows event loop until the flag changes. Note * that we do not explicitly call Tcl_ServiceEvent(). */ done = 0; while (!done) { MSG msg; if (!GetMessage(&msg, NULL, 0, 0)) { /* * The application is exiting, so repost the quit message and * start unwinding. */ PostQuitMessage((int) msg.wParam); break; } TranslateMessage(&msg); DispatchMessage(&msg); } (void) Tcl_SetServiceMode(oldMode); framePtr = oldFramePtr; } else { Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]), "\": must be done or wait", NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Testvolumetype -- * * This function implements the "testvolumetype" command. It is used to * check the volume type (FAT, NTFS) of a volume. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestvolumetypeCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { #define VOL_BUF_SIZE 32 int found; char volType[VOL_BUF_SIZE]; const char *path; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?name?"); return TCL_ERROR; } if (objc == 2) { /* * path has to be really a proper volume, but we don't get query APIs * for that until NT5 */ path = Tcl_GetString(objv[1]); } else { path = NULL; } found = GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, volType, VOL_BUF_SIZE); if (found == 0) { Tcl_AppendResult(interp, "could not get volume type for \"", (path?path:""), "\"", NULL); TclWinConvertError(GetLastError()); return TCL_ERROR; } Tcl_AppendResult(interp, volType, NULL); return TCL_OK; #undef VOL_BUF_SIZE } /* *---------------------------------------------------------------------- * * TestwinclockCmd -- * * Command that returns the seconds and microseconds portions of the * system clock and of the Tcl clock so that they can be compared to * validate that the Tcl clock is staying in sync. * * Usage: * testclock * * Parameters: * None. * * Results: * Returns a standard Tcl result comprising a four-element list: the * seconds and microseconds portions of the system clock, and the seconds * and microseconds portions of the Tcl clock. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestwinclockCmd( ClientData dummy, /* Unused */ Tcl_Interp* interp, /* Tcl interpreter */ int objc, /* Argument count */ Tcl_Obj *const objv[]) /* Argument vector */ { static const FILETIME posixEpoch = { 0xD53E8000, 0x019DB1DE }; /* The Posix epoch, expressed as a Windows * FILETIME */ Tcl_Time tclTime; /* Tcl clock */ FILETIME sysTime; /* System clock */ Tcl_Obj *result; /* Result of the command */ LARGE_INTEGER t1, t2; LARGE_INTEGER p1, p2; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, ""); return TCL_ERROR; } QueryPerformanceCounter(&p1); Tcl_GetTime(&tclTime); GetSystemTimeAsFileTime(&sysTime); t1.LowPart = posixEpoch.dwLowDateTime; t1.HighPart = posixEpoch.dwHighDateTime; t2.LowPart = sysTime.dwLowDateTime; t2.HighPart = sysTime.dwHighDateTime; t2.QuadPart -= t1.QuadPart; QueryPerformanceCounter(&p2); result = Tcl_NewObj(); Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj((int) (t2.QuadPart / 10000000))); Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj((int) ((t2.QuadPart / 10) % 1000000))); Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(tclTime.sec)); Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj(tclTime.usec)); Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(p1.QuadPart)); Tcl_ListObjAppendElement(interp, result, Tcl_NewWideIntObj(p2.QuadPart)); Tcl_SetObjResult(interp, result); return TCL_OK; } static int TestwinsleepCmd( ClientData clientData, /* Unused */ Tcl_Interp* interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const * objv) /* Parameter vector */ { int ms; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "ms"); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[1], &ms) != TCL_OK) { return TCL_ERROR; } Sleep((DWORD) ms); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestExceptionCmd -- * * Causes this process to end with the named exception. Used for testing * Tcl_WaitPid(). * * Usage: * testexcept * * Parameters: * Type of exception. * * Results: * None, this process closes now and doesn't return. * * Side effects: * This Tcl process closes, hard... Bang! * *---------------------------------------------------------------------- */ static int TestExceptionCmd( ClientData dummy, /* Unused */ Tcl_Interp* interp, /* Tcl interpreter */ int objc, /* Argument count */ Tcl_Obj *const objv[]) /* Argument vector */ { static const char *const cmds[] = { "access_violation", "datatype_misalignment", "array_bounds", "float_denormal", "float_divbyzero", "float_inexact", "float_invalidop", "float_overflow", "float_stack", "float_underflow", "int_divbyzero", "int_overflow", "private_instruction", "inpageerror", "illegal_instruction", "noncontinue", "stack_overflow", "invalid_disp", "guard_page", "invalid_handle", "ctrl+c", NULL }; static const DWORD exceptions[] = { EXCEPTION_ACCESS_VIOLATION, EXCEPTION_DATATYPE_MISALIGNMENT, EXCEPTION_ARRAY_BOUNDS_EXCEEDED, EXCEPTION_FLT_DENORMAL_OPERAND, EXCEPTION_FLT_DIVIDE_BY_ZERO, EXCEPTION_FLT_INEXACT_RESULT, EXCEPTION_FLT_INVALID_OPERATION, EXCEPTION_FLT_OVERFLOW, EXCEPTION_FLT_STACK_CHECK, EXCEPTION_FLT_UNDERFLOW, EXCEPTION_INT_DIVIDE_BY_ZERO, EXCEPTION_INT_OVERFLOW, EXCEPTION_PRIV_INSTRUCTION, EXCEPTION_IN_PAGE_ERROR, EXCEPTION_ILLEGAL_INSTRUCTION, EXCEPTION_NONCONTINUABLE_EXCEPTION, EXCEPTION_STACK_OVERFLOW, EXCEPTION_INVALID_DISPOSITION, EXCEPTION_GUARD_PAGE, EXCEPTION_INVALID_HANDLE, CONTROL_C_EXIT }; int cmd; if (objc != 2) { Tcl_WrongNumArgs(interp, 0, objv, ""); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], cmds, "command", 0, &cmd) != TCL_OK) { return TCL_ERROR; } /* * Make sure the GPF dialog doesn't popup. */ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); /* * As Tcl does not handle structured exceptions, this falls all the way * back up the instruction stack to the C run-time portion that called * main() where the process will now be terminated with this exception * code by the default handler the C run-time provides. */ /* SMASH! */ RaiseException(exceptions[cmd], EXCEPTION_NONCONTINUABLE, 0, NULL); /* NOTREACHED */ return TCL_OK; } static int TestplatformChmod( const char *nativePath, int pmode) { static const SECURITY_INFORMATION infoBits = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; static const DWORD readOnlyMask = FILE_DELETE_CHILD | FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | DELETE; /* * References to security functions (only available on NT and later). */ const BOOL set_readOnly = !(pmode & 0222); BOOL acl_readOnly_found = FALSE, curAclPresent, curAclDefaulted; SID_IDENTIFIER_AUTHORITY userSidAuthority = { SECURITY_WORLD_SID_AUTHORITY }; BYTE *secDesc = 0; DWORD secDescLen, attr, newAclSize; ACL_SIZE_INFORMATION ACLSize; PACL curAcl, newAcl = 0; WORD j; SID *userSid = 0; char *userDomain = 0; int res = 0; /* * Process the chmod request. */ attr = GetFileAttributesA(nativePath); /* * nativePath not found */ if (attr == 0xffffffff) { res = -1; goto done; } /* * If nativePath is not a directory, there is no special handling. */ if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { goto done; } /* * Set the result to error, if the ACL change is successful it will be * reset to 0. */ res = -1; /* * Read the security descriptor for the directory. Note the first call * obtains the size of the security descriptor. */ if (!GetFileSecurityA(nativePath, infoBits, NULL, 0, &secDescLen)) { DWORD secDescLen2 = 0; if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { goto done; } secDesc = ckalloc(secDescLen); if (!GetFileSecurityA(nativePath, infoBits, (PSECURITY_DESCRIPTOR) secDesc, secDescLen, &secDescLen2) || (secDescLen < secDescLen2)) { goto done; } } /* * Get the World SID. */ userSid = ckalloc(GetSidLengthRequired((UCHAR) 1)); InitializeSid(userSid, &userSidAuthority, (BYTE) 1); *(GetSidSubAuthority(userSid, 0)) = SECURITY_WORLD_RID; /* * If curAclPresent == false then curAcl and curAclDefaulted not valid. */ if (!GetSecurityDescriptorDacl((PSECURITY_DESCRIPTOR) secDesc, &curAclPresent, &curAcl, &curAclDefaulted)) { goto done; } if (!curAclPresent || !curAcl) { ACLSize.AclBytesInUse = 0; ACLSize.AceCount = 0; } else if (!GetAclInformation(curAcl, &ACLSize, sizeof(ACLSize), AclSizeInformation)) { goto done; } /* * Allocate memory for the new ACL. */ newAclSize = ACLSize.AclBytesInUse + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(userSid) - sizeof(DWORD); newAcl = ckalloc(newAclSize); /* * Initialize the new ACL. */ if (!InitializeAcl(newAcl, newAclSize, ACL_REVISION)) { goto done; } /* * Add denied to make readonly, this will be known as a "read-only tag". */ if (set_readOnly && !AddAccessDeniedAce(newAcl, ACL_REVISION, readOnlyMask, userSid)) { goto done; } acl_readOnly_found = FALSE; for (j = 0; j < ACLSize.AceCount; j++) { LPVOID pACE2; ACE_HEADER *phACE2; if (!GetAce(curAcl, j, &pACE2)) { goto done; } phACE2 = (ACE_HEADER *) pACE2; /* * Do NOT propagate inherited ACEs. */ if (phACE2->AceFlags & INHERITED_ACE) { continue; } /* * Skip the "read-only tag" restriction (either added above, or it is * being removed). */ if (phACE2->AceType == ACCESS_DENIED_ACE_TYPE) { ACCESS_DENIED_ACE *pACEd = (ACCESS_DENIED_ACE *) phACE2; if (pACEd->Mask == readOnlyMask && EqualSid(userSid, (PSID) &pACEd->SidStart)) { acl_readOnly_found = TRUE; continue; } } /* * Copy the current ACE from the old to the new ACL. */ if (!AddAce(newAcl, ACL_REVISION, MAXDWORD, (PACL *) pACE2, ((PACE_HEADER) pACE2)->AceSize)) { goto done; } } /* * Apply the new ACL. */ if (set_readOnly == acl_readOnly_found || SetNamedSecurityInfoA( (LPSTR) nativePath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, newAcl, NULL) == ERROR_SUCCESS) { res = 0; } done: if (secDesc) { ckfree(secDesc); } if (newAcl) { ckfree(newAcl); } if (userSid) { ckfree(userSid); } if (userDomain) { ckfree(userDomain); } if (res != 0) { return res; } /* * Run normal chmod command. */ return chmod(nativePath, pmode); } /* *--------------------------------------------------------------------------- * * TestchmodCmd -- * * Implements the "testchmod" cmd. Used when testing "file" command. The * only attribute used by the Windows platform is the user write flag; if * this is not set, the file is made read-only. Otherwise, the file is * made read-write. * * Results: * A standard Tcl result. * * Side effects: * Changes permissions of specified files. * *--------------------------------------------------------------------------- */ static int TestchmodCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Parameter count */ Tcl_Obj *const * objv) /* Parameter vector */ { int i, mode; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "mode file ?file ...?"); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[1], &mode) != TCL_OK) { return TCL_ERROR; } for (i = 2; i < objc; i++) { Tcl_DString buffer; const char *translated; translated = Tcl_TranslateFileName(interp, Tcl_GetString(objv[i]), &buffer); if (translated == NULL) { return TCL_ERROR; } if (TestplatformChmod(translated, mode) != 0) { Tcl_AppendResult(interp, translated, ": ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } Tcl_DStringFree(&buffer); } return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/cat.c0000644000175000017500000000133412663660066013301 0ustar sergeisergei/* * cat.c -- * * Program used when testing tclWinPipe.c * * Copyright (c) 1996 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifdef TCL_BROKEN_MAINARGS /* On mingw32 and cygwin this doesn't work */ # undef UNICODE # undef _UNICODE #endif #include #include #include #include int _tmain(void) { char buf[1024]; int n; const char *err; while (1) { n = read(0, buf, sizeof(buf)); if (n <= 0) { break; } write(1, buf, n); } err = (sizeof(int) == 2) ? "stderr16" : "stderr32"; write(2, err, strlen(err)); return 0; } tcl8.6.5/win/tclWinSock.c0000644000175000017500000025337512663660066014630 0ustar sergeisergei/* * tclWinSock.c -- * * This file contains Windows-specific socket related code. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * ----------------------------------------------------------------------- * The order and naming of functions in this file should minimize * the file diff to tclUnixSock.c. * ----------------------------------------------------------------------- * * General information on how this module works. * * - Each Tcl-thread with its sockets maintains an internal window to receive * socket messages from the OS. * * - To ensure that message reception is always running this window is * actually owned and handled by an internal thread. This we call the * co-thread of Tcl's thread. * * - The whole structure is set up by InitSockets() which is called for each * Tcl thread. The implementation of the co-thread is in SocketThread(), * and the messages are handled by SocketProc(). The connection between * both is not directly visible, it is done through a Win32 window class. * This class is initialized by InitSockets() as well, and used in the * creation of the message receiver windows. * * - An important thing to note is that *both* thread and co-thread have * access to the list of sockets maintained in the private TSD data of the * thread. The co-thread was given access to it upon creation through the * new thread's client-data. * * Because of this dual access the TSD data contains an OS mutex, the * "socketListLock", to mediate exclusion between thread and co-thread. * * The co-thread's access is all in SocketProc(). The thread's access is * through SocketEventProc() (1) and the functions called by it. * * (Ad 1) This is the handler function for all queued socket events, which * all the OS messages are translated to through the EventSource (2) * driven by the OS messages. * * (Ad 2) The main functions for this are SocketSetupProc() and * SocketCheckProc(). */ #include "tclWinInt.h" #ifdef _MSC_VER # pragma comment (lib, "ws2_32") #endif /* * Support for control over sockets' KEEPALIVE and NODELAY behavior is * currently disabled. */ #undef TCL_FEATURE_KEEPALIVE_NAGLE /* * Make sure to remove the redirection defines set in tclWinPort.h that is in * use in other sections of the core, except for us. */ #undef getservbyname #undef getsockopt #undef setsockopt /* * Helper macros to make parts of this file clearer. The macros do exactly * what they say on the tin. :-) They also only ever refer to their arguments * once, and so can be used without regard to side effects. */ #define SET_BITS(var, bits) ((var) |= (bits)) #define CLEAR_BITS(var, bits) ((var) &= ~(bits)) /* "sock" + a pointer in hex + \0 */ #define SOCK_CHAN_LENGTH (4 + sizeof(void *) * 2 + 1) #define SOCK_TEMPLATE "sock%p" /* * The following variable is used to tell whether this module has been * initialized. If 1, initialization of sockets was successful, if -1 then * socket initialization failed (WSAStartup failed). */ static int initialized = 0; static const TCHAR classname[] = TEXT("TclSocket"); TCL_DECLARE_MUTEX(socketMutex) /* * The following defines declare the messages used on socket windows. */ #define SOCKET_MESSAGE WM_USER+1 #define SOCKET_SELECT WM_USER+2 #define SOCKET_TERMINATE WM_USER+3 #define SELECT TRUE #define UNSELECT FALSE /* * This is needed to comply with the strict aliasing rules of GCC, but it also * simplifies casting between the different sockaddr types. */ typedef union { struct sockaddr sa; struct sockaddr_in sa4; struct sockaddr_in6 sa6; struct sockaddr_storage sas; } address; #ifndef IN6_ARE_ADDR_EQUAL #define IN6_ARE_ADDR_EQUAL IN6_ADDR_EQUAL #endif /* * This structure describes per-instance state of a tcp based channel. */ typedef struct TcpState TcpState; typedef struct TcpFdList { TcpState *statePtr; SOCKET fd; struct TcpFdList *next; } TcpFdList; struct TcpState { Tcl_Channel channel; /* Channel associated with this socket. */ struct TcpFdList *sockets; /* Windows SOCKET handle. */ int flags; /* Bit field comprised of the flags described * below. */ int watchEvents; /* OR'ed combination of FD_READ, FD_WRITE, * FD_CLOSE, FD_ACCEPT and FD_CONNECT that * indicate which events are interesting. */ volatile int readyEvents; /* OR'ed combination of FD_READ, FD_WRITE, * FD_CLOSE, FD_ACCEPT and FD_CONNECT that * indicate which events have occurred. * Set by notifier thread, access must be * protected by semaphore */ int selectEvents; /* OR'ed combination of FD_READ, FD_WRITE, * FD_CLOSE, FD_ACCEPT and FD_CONNECT that * indicate which events are currently being * selected. */ volatile int acceptEventCount; /* Count of the current number of FD_ACCEPTs * that have arrived and not yet processed. * Set by notifier thread, access must be * protected by semaphore */ Tcl_TcpAcceptProc *acceptProc; /* Proc to call on accept. */ ClientData acceptProcData; /* The data for the accept proc. */ /* * Only needed for client sockets */ struct addrinfo *addrlist; /* Addresses to connect to. */ struct addrinfo *addr; /* Iterator over addrlist. */ struct addrinfo *myaddrlist;/* Local address. */ struct addrinfo *myaddr; /* Iterator over myaddrlist. */ int connectError; /* Cache status of async socket. */ int cachedBlocking; /* Cache blocking mode of async socket. */ volatile int notifierConnectError; /* Async connect error set by notifier thread. * This error is still a windows error code. * Access must be protected by semaphore */ struct TcpState *nextPtr; /* The next socket on the per-thread socket * list. */ }; /* * These bits may be ORed together into the "flags" field of a TcpState * structure. */ #define TCP_NONBLOCKING (1<<0) /* Socket with non-blocking I/O */ #define TCP_ASYNC_CONNECT (1<<1) /* Async connect in progress. */ #define SOCKET_EOF (1<<2) /* A zero read happened on the * socket. */ #define SOCKET_PENDING (1<<3) /* A message has been sent for this * socket */ #define TCP_ASYNC_PENDING (1<<4) /* TcpConnect was called to * process an async connect. This * flag indicates that reentry is * still pending */ #define TCP_ASYNC_FAILED (1<<5) /* An async connect finally failed */ /* * The following structure is what is added to the Tcl event queue when a * socket event occurs. */ typedef struct { Tcl_Event header; /* Information that is standard for all * events. */ SOCKET socket; /* Socket descriptor that is ready. Used to * find the TcpState structure for the file * (can't point directly to the TcpState * structure because it could go away while * the event is queued). */ } SocketEvent; /* * This defines the minimum buffersize maintained by the kernel. */ #define TCP_BUFFER_SIZE 4096 typedef struct { HWND hwnd; /* Handle to window for socket messages. */ HANDLE socketThread; /* Thread handling the window */ Tcl_ThreadId threadId; /* Parent thread. */ HANDLE readyEvent; /* Event indicating that a socket event is * ready. Also used to indicate that the * socketThread has been initialized and has * started. */ HANDLE socketListLock; /* Win32 Event to lock the socketList */ TcpState *pendingTcpState; /* This socket is opened but not jet in the * list. This value is also checked by * the event structure. */ TcpState *socketList; /* Every open socket in this thread has an * entry on this list. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; static WNDCLASS windowClass; /* * Static routines for this file: */ static int TcpConnect(Tcl_Interp *interp, TcpState *state); static void InitSockets(void); static TcpState * NewSocketInfo(SOCKET socket); static void SocketExitHandler(ClientData clientData); static LRESULT CALLBACK SocketProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static int SocketsEnabled(void); static void TcpAccept(TcpFdList *fds, SOCKET newSocket, address addr); static int WaitForConnect(TcpState *statePtr, int *errorCodePtr); static int WaitForSocketEvent(TcpState *statePtr, int events, int *errorCodePtr); static void AddSocketInfoFd(TcpState *statePtr, SOCKET socket); static int FindFDInList(TcpState *statePtr, SOCKET socket); static DWORD WINAPI SocketThread(LPVOID arg); static void TcpThreadActionProc(ClientData instanceData, int action); static Tcl_EventCheckProc SocketCheckProc; static Tcl_EventProc SocketEventProc; static Tcl_EventSetupProc SocketSetupProc; static Tcl_DriverBlockModeProc TcpBlockModeProc; static Tcl_DriverCloseProc TcpCloseProc; static Tcl_DriverClose2Proc TcpClose2Proc; static Tcl_DriverSetOptionProc TcpSetOptionProc; static Tcl_DriverGetOptionProc TcpGetOptionProc; static Tcl_DriverInputProc TcpInputProc; static Tcl_DriverOutputProc TcpOutputProc; static Tcl_DriverWatchProc TcpWatchProc; static Tcl_DriverGetHandleProc TcpGetHandleProc; /* * This structure describes the channel type structure for TCP socket * based IO: */ static const Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ TcpCloseProc, /* Close proc. */ TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ NULL, /* Seek proc. */ TcpSetOptionProc, /* Set option proc. */ TcpGetOptionProc, /* Get option proc. */ TcpWatchProc, /* Initialize notifier. */ TcpGetHandleProc, /* Get OS handles out of channel. */ TcpClose2Proc, /* Close2 proc. */ TcpBlockModeProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ NULL, /* wide seek proc. */ TcpThreadActionProc, /* thread action proc. */ NULL /* truncate proc. */ }; /* * The following variable holds the network name of this host. */ static TclInitProcessGlobalValueProc InitializeHostName; static ProcessGlobalValue hostName = {0, 0, NULL, NULL, InitializeHostName, NULL, NULL}; /* * Address print debug functions */ #if 0 void printaddrinfo(struct addrinfo *ai, char *prefix) { char host[NI_MAXHOST], port[NI_MAXSERV]; getnameinfo(ai->ai_addr, ai->ai_addrlen, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV); } void printaddrinfolist(struct addrinfo *addrlist, char *prefix) { struct addrinfo *ai; for (ai = addrlist; ai != NULL; ai = ai->ai_next) { printaddrinfo(ai, prefix); } } #endif /* *---------------------------------------------------------------------- * * InitializeHostName -- * * This routine sets the process global value of the name of the local * host on which the process is running. * * Results: * None. * *---------------------------------------------------------------------- */ void InitializeHostName( char **valuePtr, int *lengthPtr, Tcl_Encoding *encodingPtr) { TCHAR tbuf[MAX_COMPUTERNAME_LENGTH + 1]; DWORD length = MAX_COMPUTERNAME_LENGTH + 1; Tcl_DString ds; if (GetComputerName(tbuf, &length) != 0) { /* * Convert string from native to UTF then change to lowercase. */ Tcl_UtfToLower(Tcl_WinTCharToUtf(tbuf, -1, &ds)); } else { Tcl_DStringInit(&ds); if (TclpHasSockets(NULL) == TCL_OK) { /* * The buffer size of 256 is recommended by the MSDN page that * documents gethostname() as being always adequate. */ Tcl_DString inDs; Tcl_DStringInit(&inDs); Tcl_DStringSetLength(&inDs, 256); if (gethostname(Tcl_DStringValue(&inDs), Tcl_DStringLength(&inDs)) == 0) { Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&inDs), -1, &ds); } Tcl_DStringFree(&inDs); } } *encodingPtr = Tcl_GetEncoding(NULL, "utf-8"); *lengthPtr = Tcl_DStringLength(&ds); *valuePtr = ckalloc((*lengthPtr) + 1); memcpy(*valuePtr, Tcl_DStringValue(&ds), (size_t)(*lengthPtr)+1); Tcl_DStringFree(&ds); } /* *---------------------------------------------------------------------- * * Tcl_GetHostName -- * * Returns the name of the local host. * * Results: * A string containing the network name for this machine, or an empty * string if we can't figure out the name. The caller must not modify or * free this string. * * Side effects: * Caches the name to return for future calls. * *---------------------------------------------------------------------- */ const char * Tcl_GetHostName(void) { return Tcl_GetString(TclGetProcessGlobalValue(&hostName)); } /* *---------------------------------------------------------------------- * * TclpHasSockets -- * * This function determines whether sockets are available on the current * system and returns an error in interp if they are not. Note that * interp may be NULL. * * Results: * Returns TCL_OK if the system supports sockets, or TCL_ERROR with an * error in interp (if non-NULL). * * Side effects: * If not already prepared, initializes the TSD structure and socket * message handling thread associated to the calling thread for the * subsystem of the driver. * *---------------------------------------------------------------------- */ int TclpHasSockets( Tcl_Interp *interp) /* Where to write an error message if sockets * are not present, or NULL if no such message * is to be written. */ { Tcl_MutexLock(&socketMutex); InitSockets(); Tcl_MutexUnlock(&socketMutex); if (SocketsEnabled()) { return TCL_OK; } if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "sockets are not available on this system", -1)); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclpFinalizeSockets -- * * This function is called from Tcl_FinalizeThread to finalize the * platform specific socket subsystem. Also, it may be called from within * this module to cleanup the state if unable to initialize the sockets * subsystem. * * Results: * None. * * Side effects: * Deletes the event source and destroys the socket thread. * *---------------------------------------------------------------------- */ void TclpFinalizeSockets(void) { ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); /* * Careful! This is a finalizer! */ if (tsdPtr == NULL) { return; } if (tsdPtr->socketThread != NULL) { if (tsdPtr->hwnd != NULL) { PostMessage(tsdPtr->hwnd, SOCKET_TERMINATE, 0, 0); /* * Wait for the thread to exit. This ensures that we are * completely cleaned up before we leave this function. */ WaitForSingleObject(tsdPtr->readyEvent, INFINITE); tsdPtr->hwnd = NULL; } CloseHandle(tsdPtr->socketThread); tsdPtr->socketThread = NULL; } if (tsdPtr->readyEvent != NULL) { CloseHandle(tsdPtr->readyEvent); tsdPtr->readyEvent = NULL; } if (tsdPtr->socketListLock != NULL) { CloseHandle(tsdPtr->socketListLock); tsdPtr->socketListLock = NULL; } Tcl_DeleteEventSource(SocketSetupProc, SocketCheckProc, NULL); } /* *---------------------------------------------------------------------- * * TcpBlockModeProc -- * * This function is invoked by the generic IO level to set blocking and * nonblocking mode on a TCP socket based channel. * * Results: * 0 if successful, errno when failed. * * Side effects: * Sets the device into blocking or nonblocking mode. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TcpBlockModeProc( ClientData instanceData, /* Socket state. */ int mode) /* The mode to set. Can be one of * TCL_MODE_BLOCKING or * TCL_MODE_NONBLOCKING. */ { TcpState *statePtr = instanceData; if (mode == TCL_MODE_NONBLOCKING) { statePtr->flags |= TCP_NONBLOCKING; } else { statePtr->flags &= ~(TCP_NONBLOCKING); } return 0; } /* *---------------------------------------------------------------------- * * WaitForConnect -- * * Check the state of an async connect process. If a connection * attempt terminated, process it, which may finalize it or may * start the next attempt. If a connect error occures, it is saved * in statePtr->connectError to be reported by 'fconfigure -error'. * * There are two modes of operation, defined by errorCodePtr: * * non-NULL: Called by explicite read/write command. block if * socket is blocking. * May return two error codes: * * EWOULDBLOCK: if connect is still in progress * * ENOTCONN: if connect failed. This would be the error * message of a rect or sendto syscall so this is * emulated here. * * Null: Called by a backround operation. Do not block and * don't return any error code. * * Results: * 0 if the connection has completed, -1 if still in progress * or there is an error. * * Side effects: * Processes socket events off the system queue. * May process asynchroneous connect. * *---------------------------------------------------------------------- */ static int WaitForConnect( TcpState *statePtr, /* State of the socket. */ int *errorCodePtr) /* Where to store errors? * A passed null-pointer activates background mode. */ { int result; int oldMode; ThreadSpecificData *tsdPtr; /* * Check if an async connect failed already and error reporting is demanded, * return the error ENOTCONN */ if (errorCodePtr != NULL && (statePtr->flags & TCP_ASYNC_FAILED)) { *errorCodePtr = ENOTCONN; return -1; } /* * Check if an async connect is running. If not return ok */ if (!(statePtr->flags & TCP_ASYNC_CONNECT)) { return 0; } /* * Be sure to disable event servicing so we are truly modal. */ oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE); /* * Loop in the blocking case until the connect signal is present */ while (1) { /* get statePtr lock */ tsdPtr = TclThreadDataKeyGet(&dataKey); WaitForSingleObject(tsdPtr->socketListLock, INFINITE); /* Check for connect event */ if (statePtr->readyEvents & FD_CONNECT) { /* Consume the connect event */ statePtr->readyEvents &= ~(FD_CONNECT); /* * For blocking sockets and foreground processing * disable async connect as we continue now synchoneously */ if ( errorCodePtr != NULL && ! (statePtr->flags & TCP_NONBLOCKING) ) { CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT); } /* Free list lock */ SetEvent(tsdPtr->socketListLock); /* * Continue connect. * If switched to synchroneous connect, the connect is terminated. */ result = TcpConnect(NULL, statePtr); /* Restore event service mode */ (void) Tcl_SetServiceMode(oldMode); /* * Check for Succesfull connect or async connect restart */ if (result == TCL_OK) { /* * Check for async connect restart * (not possible for foreground blocking operation) */ if ( statePtr->flags & TCP_ASYNC_PENDING ) { if (errorCodePtr != NULL) { *errorCodePtr = EWOULDBLOCK; } return -1; } return 0; } /* * Connect finally failed. * For foreground operation return ENOTCONN. */ if (errorCodePtr != NULL) { *errorCodePtr = ENOTCONN; } return -1; } /* Free list lock */ SetEvent(tsdPtr->socketListLock); /* * Background operation returns with no action as there was no connect * event */ if ( errorCodePtr == NULL ) { return -1; } /* * A non blocking socket waiting for an asyncronous connect * returns directly the error EWOULDBLOCK */ if (statePtr->flags & TCP_NONBLOCKING) { *errorCodePtr = EWOULDBLOCK; return -1; } /* * Wait until something happens. */ WaitForSingleObject(tsdPtr->readyEvent, INFINITE); } } /* *---------------------------------------------------------------------- * * TcpInputProc -- * * This function is invoked by the generic IO level to read input from a * TCP socket based channel. * * Results: * The number of bytes read is returned or -1 on error. An output * argument contains the POSIX error code on error, or zero if no error * occurred. * * Side effects: * Reads input from the input device of the channel. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TcpInputProc( ClientData instanceData, /* Socket state. */ char *buf, /* Where to store data read. */ int bufSize, /* How much space is available in the * buffer? */ int *errorCodePtr) /* Where to store error code. */ { TcpState *statePtr = instanceData; int bytesRead; DWORD error; ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); *errorCodePtr = 0; /* * Check that WinSock is initialized; do not call it if not, to prevent * system crashes. This can happen at exit time if the exit handler for * WinSock ran before other exit handlers that want to use sockets. */ if (!SocketsEnabled()) { *errorCodePtr = EFAULT; return -1; } /* * First check to see if EOF was already detected, to prevent calling the * socket stack after the first time EOF is detected. */ if (statePtr->flags & SOCKET_EOF) { return 0; } /* * Check if there is an async connect running. * For blocking sockets terminate connect, otherwise do one step. * For a non blocking socket return EWOULDBLOCK if connect not terminated */ if (WaitForConnect(statePtr, errorCodePtr) != 0) { return -1; } /* * No EOF, and it is connected, so try to read more from the socket. Note * that we clear the FD_READ bit because read events are level triggered * so a new event will be generated if there is still data available to be * read. We have to simulate blocking behavior here since we are always * using non-blocking sockets. */ while (1) { SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) UNSELECT, (LPARAM) statePtr); /* single fd operation: this proc is only called for a connected socket. */ bytesRead = recv(statePtr->sockets->fd, buf, bufSize, 0); statePtr->readyEvents &= ~(FD_READ); /* * Check for end-of-file condition or successful read. */ if (bytesRead == 0) { statePtr->flags |= SOCKET_EOF; } if (bytesRead != SOCKET_ERROR) { break; } /* * If an error occurs after the FD_CLOSE has arrived, then ignore the * error and report an EOF. */ if (statePtr->readyEvents & FD_CLOSE) { statePtr->flags |= SOCKET_EOF; bytesRead = 0; break; } error = WSAGetLastError(); /* * If an RST comes, then ignore the error and report an EOF just like * on unix. */ if (error == WSAECONNRESET) { statePtr->flags |= SOCKET_EOF; bytesRead = 0; break; } /* * Check for error condition or underflow in non-blocking case. */ if ((statePtr->flags & TCP_NONBLOCKING) || (error != WSAEWOULDBLOCK)) { TclWinConvertError(error); *errorCodePtr = Tcl_GetErrno(); bytesRead = -1; break; } /* * In the blocking case, wait until the file becomes readable or * closed and try again. */ if (!WaitForSocketEvent(statePtr, FD_READ|FD_CLOSE, errorCodePtr)) { bytesRead = -1; break; } } SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM)SELECT, (LPARAM)statePtr); return bytesRead; } /* *---------------------------------------------------------------------- * * TcpOutputProc -- * * This function is called by the generic IO level to write data to a * socket based channel. * * Results: * The number of bytes written or -1 on failure. * * Side effects: * Produces output on the socket. * *---------------------------------------------------------------------- */ static int TcpOutputProc( ClientData instanceData, /* Socket state. */ const char *buf, /* The data buffer. */ int toWrite, /* How many bytes to write? */ int *errorCodePtr) /* Where to store error code. */ { TcpState *statePtr = instanceData; int written; DWORD error; ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); *errorCodePtr = 0; /* * Check that WinSock is initialized; do not call it if not, to prevent * system crashes. This can happen at exit time if the exit handler for * WinSock ran before other exit handlers that want to use sockets. */ if (!SocketsEnabled()) { *errorCodePtr = EFAULT; return -1; } /* * Check if there is an async connect running. * For blocking sockets terminate connect, otherwise do one step. * For a non blocking socket return EWOULDBLOCK if connect not terminated */ if (WaitForConnect(statePtr, errorCodePtr) != 0) { return -1; } while (1) { SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) UNSELECT, (LPARAM) statePtr); /* single fd operation: this proc is only called for a connected socket. */ written = send(statePtr->sockets->fd, buf, toWrite, 0); if (written != SOCKET_ERROR) { /* * Since Windows won't generate a new write event until we hit an * overflow condition, we need to force the event loop to poll * until the condition changes. */ if (statePtr->watchEvents & FD_WRITE) { Tcl_Time blockTime = { 0, 0 }; Tcl_SetMaxBlockTime(&blockTime); } break; } /* * Check for error condition or overflow. In the event of overflow, we * need to clear the FD_WRITE flag so we can detect the next writable * event. Note that Windows only sends a new writable event after a * send fails with WSAEWOULDBLOCK. */ error = WSAGetLastError(); if (error == WSAEWOULDBLOCK) { statePtr->readyEvents &= ~(FD_WRITE); if (statePtr->flags & TCP_NONBLOCKING) { *errorCodePtr = EWOULDBLOCK; written = -1; break; } } else { TclWinConvertError(error); *errorCodePtr = Tcl_GetErrno(); written = -1; break; } /* * In the blocking case, wait until the file becomes writable or * closed and try again. */ if (!WaitForSocketEvent(statePtr, FD_WRITE|FD_CLOSE, errorCodePtr)) { written = -1; break; } } SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM)SELECT, (LPARAM)statePtr); return written; } /* *---------------------------------------------------------------------- * * TcpCloseProc -- * * This function is called by the generic IO level to perform channel * type specific cleanup on a socket based channel when the channel is * closed. * * Results: * 0 if successful, the value of errno if failed. * * Side effects: * Closes the socket. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TcpCloseProc( ClientData instanceData, /* The socket to close. */ Tcl_Interp *interp) /* Unused. */ { TcpState *statePtr = instanceData; /* TIP #218 */ int errorCode = 0; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Check that WinSock is initialized; do not call it if not, to prevent * system crashes. This can happen at exit time if the exit handler for * WinSock ran before other exit handlers that want to use sockets. */ if (SocketsEnabled()) { /* * Clean up the OS socket handle. The default Windows setting for a * socket is SO_DONTLINGER, which does a graceful shutdown in the * background. */ while ( statePtr->sockets != NULL ) { TcpFdList *thisfd = statePtr->sockets; statePtr->sockets = thisfd->next; if (closesocket(thisfd->fd) == SOCKET_ERROR) { TclWinConvertError((DWORD) WSAGetLastError()); errorCode = Tcl_GetErrno(); } ckfree(thisfd); } } if (statePtr->addrlist != NULL) { freeaddrinfo(statePtr->addrlist); } if (statePtr->myaddrlist != NULL) { freeaddrinfo(statePtr->myaddrlist); } /* * Clear an eventual tsd info list pointer. * This may be called, if an async socket connect fails or is closed * between connect and thread action callback. */ if (tsdPtr->pendingTcpState != NULL && tsdPtr->pendingTcpState == statePtr) { /* get infoPtr lock, because this concerns the notifier thread */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); tsdPtr->pendingTcpState = NULL; /* Free list lock */ SetEvent(tsdPtr->socketListLock); } /* * TIP #218. Removed the code removing the structure from the global * socket list. This is now done by the thread action callbacks, and only * there. This happens before this code is called. We can free without * fear of damaging the list. */ ckfree(statePtr); return errorCode; } /* *---------------------------------------------------------------------- * * TcpClose2Proc -- * * This function is called by the generic IO level to perform the channel * type specific part of a half-close: namely, a shutdown() on a socket. * * Results: * 0 if successful, the value of errno if failed. * * Side effects: * Shuts down one side of the socket. * *---------------------------------------------------------------------- */ static int TcpClose2Proc( ClientData instanceData, /* The socket to close. */ Tcl_Interp *interp, /* For error reporting. */ int flags) /* Flags that indicate which side to close. */ { TcpState *statePtr = instanceData; int errorCode = 0; int sd; /* * Shutdown the OS socket handle. */ switch(flags) { case TCL_CLOSE_READ: sd = SD_RECEIVE; break; case TCL_CLOSE_WRITE: sd = SD_SEND; break; default: if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "socket close2proc called bidirectionally", -1)); } return TCL_ERROR; } /* single fd operation: Tcl_OpenTcpServer() does not set TCL_READABLE or * TCL_WRITABLE so this should never be called for a server socket. */ if (shutdown(statePtr->sockets->fd, sd) == SOCKET_ERROR) { TclWinConvertError((DWORD) WSAGetLastError()); errorCode = Tcl_GetErrno(); } return errorCode; } /* *---------------------------------------------------------------------- * * TcpSetOptionProc -- * * Sets Tcp channel specific options. * * Results: * None, unless an error happens. * * Side effects: * Changes attributes of the socket at the system level. * *---------------------------------------------------------------------- */ static int TcpSetOptionProc( ClientData instanceData, /* Socket state. */ Tcl_Interp *interp, /* For error reporting - can be NULL. */ const char *optionName, /* Name of the option to set. */ const char *value) /* New value for option. */ { #ifdef TCL_FEATURE_KEEPALIVE_NAGLE TcpState *statePtr = instanceData; SOCKET sock; #endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/ /* * Check that WinSock is initialized; do not call it if not, to prevent * system crashes. This can happen at exit time if the exit handler for * WinSock ran before other exit handlers that want to use sockets. */ if (!SocketsEnabled()) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "winsock is not initialized", -1)); } return TCL_ERROR; } #ifdef TCL_FEATURE_KEEPALIVE_NAGLE #error "TCL_FEATURE_KEEPALIVE_NAGLE not reviewed for whether to treat statePtr->sockets as single fd or list" sock = statePtr->sockets->fd; if (!strcasecmp(optionName, "-keepalive")) { BOOL val = FALSE; int boolVar, rtn; if (Tcl_GetBoolean(interp, value, &boolVar) != TCL_OK) { return TCL_ERROR; } if (boolVar) { val = TRUE; } rtn = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (const char *) &val, sizeof(BOOL)); if (rtn != 0) { TclWinConvertError(WSAGetLastError()); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't set socket option: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } return TCL_OK; } else if (!strcasecmp(optionName, "-nagle")) { BOOL val = FALSE; int boolVar, rtn; if (Tcl_GetBoolean(interp, value, &boolVar) != TCL_OK) { return TCL_ERROR; } if (!boolVar) { val = TRUE; } rtn = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char *) &val, sizeof(BOOL)); if (rtn != 0) { TclWinConvertError(WSAGetLastError()); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't set socket option: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } return TCL_OK; } return Tcl_BadChannelOption(interp, optionName, "keepalive nagle"); #else return Tcl_BadChannelOption(interp, optionName, ""); #endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/ } /* *---------------------------------------------------------------------- * * TcpGetOptionProc -- * * Computes an option value for a TCP socket based channel, or a list of * all options and their values. * * Note: This code is based on code contributed by John Haxby. * * Results: * A standard Tcl result. The value of the specified option or a list of * all options and their values is returned in the supplied DString. Sets * Error message if needed. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TcpGetOptionProc( ClientData instanceData, /* Socket state. */ Tcl_Interp *interp, /* For error reporting - can be NULL. */ const char *optionName, /* Name of the option to retrieve the value * for, or NULL to get all options and their * values. */ Tcl_DString *dsPtr) /* Where to store the computed value; * initialized by caller. */ { TcpState *statePtr = instanceData; char host[NI_MAXHOST], port[NI_MAXSERV]; SOCKET sock; size_t len = 0; int reverseDNS = 0; #define SUPPRESS_RDNS_VAR "::tcl::unsupported::noReverseDNS" /* * Check that WinSock is initialized; do not call it if not, to prevent * system crashes. This can happen at exit time if the exit handler for * WinSock ran before other exit handlers that want to use sockets. */ if (!SocketsEnabled()) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "winsock is not initialized", -1)); } return TCL_ERROR; } /* * Go one step in async connect * If any error is thrown save it as backround error to report eventually below */ WaitForConnect(statePtr, NULL); sock = statePtr->sockets->fd; if (optionName != NULL) { len = strlen(optionName); } if ((len > 1) && (optionName[1] == 'e') && (strncmp(optionName, "-error", len) == 0)) { /* * Do not return any errors if async connect is running */ if ( ! (statePtr->flags & TCP_ASYNC_PENDING) ) { if ( statePtr->flags & TCP_ASYNC_FAILED ) { /* * In case of a failed async connect, eventually report the * connect error only once. * Do not report the system error, as this comes again and again. */ if ( statePtr->connectError != 0 ) { Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(statePtr->connectError), -1); statePtr->connectError = 0; } } else { /* * Report an eventual last error of the socket system */ int optlen; int ret; DWORD err; /* * Populater the err Variable with a possix error */ optlen = sizeof(int); ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&err, &optlen); /* * The error was not returned directly but should be * taken from WSA */ if (ret == SOCKET_ERROR) { err = WSAGetLastError(); } /* * Return error message */ if (err) { TclWinConvertError(err); Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(Tcl_GetErrno()), -1); } } } return TCL_OK; } if ((len > 1) && (optionName[1] == 'c') && (strncmp(optionName, "-connecting", len) == 0)) { Tcl_DStringAppend(dsPtr, (statePtr->flags & TCP_ASYNC_PENDING) ? "1" : "0", -1); return TCL_OK; } if (interp != NULL && Tcl_GetVar(interp, SUPPRESS_RDNS_VAR, 0) != NULL) { reverseDNS = NI_NUMERICHOST; } if ((len == 0) || ((len > 1) && (optionName[1] == 'p') && (strncmp(optionName, "-peername", len) == 0))) { address peername; socklen_t size = sizeof(peername); if ( (statePtr->flags & TCP_ASYNC_PENDING) ) { /* * In async connect output an empty string */ if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-peername"); Tcl_DStringAppendElement(dsPtr, ""); } else { return TCL_OK; } } else if ( getpeername(sock, (LPSOCKADDR) &(peername.sa), &size) == 0) { /* * Peername fetch succeeded - output list */ if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-peername"); Tcl_DStringStartSublist(dsPtr); } getnameinfo(&(peername.sa), size, host, sizeof(host), NULL, 0, NI_NUMERICHOST); Tcl_DStringAppendElement(dsPtr, host); getnameinfo(&(peername.sa), size, host, sizeof(host), port, sizeof(port), reverseDNS | NI_NUMERICSERV); Tcl_DStringAppendElement(dsPtr, host); Tcl_DStringAppendElement(dsPtr, port); if (len == 0) { Tcl_DStringEndSublist(dsPtr); } else { return TCL_OK; } } else { /* * getpeername failed - but if we were asked for all the options * (len==0), don't flag an error at that point because it could be * an fconfigure request on a server socket (such sockets have no * peer). {Copied from unix/tclUnixChan.c} */ if (len) { TclWinConvertError((DWORD) WSAGetLastError()); if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get peername: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } } } if ((len == 0) || ((len > 1) && (optionName[1] == 's') && (strncmp(optionName, "-sockname", len) == 0))) { TcpFdList *fds; address sockname; socklen_t size; int found = 0; if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-sockname"); Tcl_DStringStartSublist(dsPtr); } if ( (statePtr->flags & TCP_ASYNC_PENDING ) ) { /* * In async connect output an empty string */ found = 1; } else { for (fds = statePtr->sockets; fds != NULL; fds = fds->next) { sock = fds->fd; size = sizeof(sockname); if (getsockname(sock, &(sockname.sa), &size) >= 0) { int flags = reverseDNS; found = 1; getnameinfo(&sockname.sa, size, host, sizeof(host), NULL, 0, NI_NUMERICHOST); Tcl_DStringAppendElement(dsPtr, host); /* * We don't want to resolve INADDR_ANY and sin6addr_any; they * can sometimes cause problems (and never have a name). */ flags |= NI_NUMERICSERV; if (sockname.sa.sa_family == AF_INET) { if (sockname.sa4.sin_addr.s_addr == INADDR_ANY) { flags |= NI_NUMERICHOST; } } else if (sockname.sa.sa_family == AF_INET6) { if ((IN6_ARE_ADDR_EQUAL(&sockname.sa6.sin6_addr, &in6addr_any)) || (IN6_IS_ADDR_V4MAPPED(&sockname.sa6.sin6_addr) && sockname.sa6.sin6_addr.s6_addr[12] == 0 && sockname.sa6.sin6_addr.s6_addr[13] == 0 && sockname.sa6.sin6_addr.s6_addr[14] == 0 && sockname.sa6.sin6_addr.s6_addr[15] == 0)) { flags |= NI_NUMERICHOST; } } getnameinfo(&sockname.sa, size, host, sizeof(host), port, sizeof(port), flags); Tcl_DStringAppendElement(dsPtr, host); Tcl_DStringAppendElement(dsPtr, port); } } } if (found) { if (len) { return TCL_OK; } Tcl_DStringEndSublist(dsPtr); } else { if (interp) { TclWinConvertError((DWORD) WSAGetLastError()); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get sockname: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } } #ifdef TCL_FEATURE_KEEPALIVE_NAGLE if (len == 0 || !strncmp(optionName, "-keepalive", len)) { int optlen; BOOL opt = FALSE; if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-keepalive"); } optlen = sizeof(BOOL); getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, &optlen); if (opt) { Tcl_DStringAppendElement(dsPtr, "1"); } else { Tcl_DStringAppendElement(dsPtr, "0"); } if (len > 0) { return TCL_OK; } } if (len == 0 || !strncmp(optionName, "-nagle", len)) { int optlen; BOOL opt = FALSE; if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-nagle"); } optlen = sizeof(BOOL); getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, &optlen); if (opt) { Tcl_DStringAppendElement(dsPtr, "0"); } else { Tcl_DStringAppendElement(dsPtr, "1"); } if (len > 0) { return TCL_OK; } } #endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/ if (len > 0) { #ifdef TCL_FEATURE_KEEPALIVE_NAGLE return Tcl_BadChannelOption(interp, optionName, "connecting peername sockname keepalive nagle"); #else return Tcl_BadChannelOption(interp, optionName, "connecting peername sockname"); #endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/ } return TCL_OK; } /* *---------------------------------------------------------------------- * * TcpWatchProc -- * * Informs the channel driver of the events that the generic channel code * wishes to receive on this socket. * * Results: * None. * * Side effects: * May cause the notifier to poll if any of the specified conditions are * already true. * *---------------------------------------------------------------------- */ static void TcpWatchProc( ClientData instanceData, /* The socket state. */ int mask) /* Events of interest; an OR-ed combination of * TCL_READABLE, TCL_WRITABLE and * TCL_EXCEPTION. */ { TcpState *statePtr = instanceData; /* * Update the watch events mask. Only if the socket is not a server * socket. [Bug 557878] */ if (!statePtr->acceptProc) { statePtr->watchEvents = 0; if (mask & TCL_READABLE) { statePtr->watchEvents |= (FD_READ|FD_CLOSE); } if (mask & TCL_WRITABLE) { statePtr->watchEvents |= (FD_WRITE|FD_CLOSE); } /* * If there are any conditions already set, then tell the notifier to * poll rather than block. */ if (statePtr->readyEvents & statePtr->watchEvents) { Tcl_Time blockTime = { 0, 0 }; Tcl_SetMaxBlockTime(&blockTime); } } } /* *---------------------------------------------------------------------- * * TcpGetHandleProc -- * * Called from Tcl_GetChannelHandle to retrieve OS handles from inside a * TCP socket based channel. * * Results: * Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if there is no * handle for the specified direction. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TcpGetHandleProc( ClientData instanceData, /* The socket state. */ int direction, /* Not used. */ ClientData *handlePtr) /* Where to store the handle. */ { TcpState *statePtr = instanceData; *handlePtr = INT2PTR(statePtr->sockets->fd); return TCL_OK; } /* *---------------------------------------------------------------------- * * TcpConnect -- * * This function opens a new socket in client mode. * * This might be called in 3 circumstances: * - By a regular socket command * - By the event handler to continue an asynchroneous connect * - By a blocking socket function (gets/puts) to terminate the * connect synchroneously * * Results: * TCL_OK, if the socket was successfully connected or an asynchronous * connection is in progress. If an error occurs, TCL_ERROR is returned * and an error message is left in interp. * * Side effects: * Opens a socket. * * Remarks: * A single host name may resolve to more than one IP address, e.g. for * an IPv4/IPv6 dual stack host. For handling asyncronously connecting * sockets in the background for such hosts, this function can act as a * coroutine. On the first call, it sets up the control variables for the * two nested loops over the local and remote addresses. Once the first * connection attempt is in progress, it sets up itself as a writable * event handler for that socket, and returns. When the callback occurs, * control is transferred to the "reenter" label, right after the initial * return and the loops resume as if they had never been interrupted. * For syncronously connecting sockets, the loops work the usual way. * *---------------------------------------------------------------------- */ static int TcpConnect( Tcl_Interp *interp, /* For error reporting; can be NULL. */ TcpState *statePtr) { DWORD error; /* * We are started with async connect and the connect notification * was not jet received */ int async_connect = statePtr->flags & TCP_ASYNC_CONNECT; /* We were called by the event procedure and continue our loop */ int async_callback = statePtr->flags & TCP_ASYNC_PENDING; ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); if (async_callback) { goto reenter; } for (statePtr->addr = statePtr->addrlist; statePtr->addr != NULL; statePtr->addr = statePtr->addr->ai_next) { for (statePtr->myaddr = statePtr->myaddrlist; statePtr->myaddr != NULL; statePtr->myaddr = statePtr->myaddr->ai_next) { /* * No need to try combinations of local and remote addresses * of different families. */ if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) { continue; } /* * Close the socket if it is still open from the last unsuccessful * iteration. */ if (statePtr->sockets->fd != INVALID_SOCKET) { closesocket(statePtr->sockets->fd); } /* get statePtr lock */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); /* * Reset last error from last try */ statePtr->notifierConnectError = 0; Tcl_SetErrno(0); statePtr->sockets->fd = socket(statePtr->myaddr->ai_family, SOCK_STREAM, 0); /* Free list lock */ SetEvent(tsdPtr->socketListLock); /* continue on socket creation error */ if (statePtr->sockets->fd == INVALID_SOCKET) { TclWinConvertError((DWORD) WSAGetLastError()); continue; } /* * Win-NT has a misfeature that sockets are inherited in child * processes by default. Turn off the inherit bit. */ SetHandleInformation((HANDLE) statePtr->sockets->fd, HANDLE_FLAG_INHERIT, 0); /* * Set kernel space buffering */ TclSockMinimumBuffers((void *) statePtr->sockets->fd, TCP_BUFFER_SIZE); /* * Try to bind to a local port. */ if (bind(statePtr->sockets->fd, statePtr->myaddr->ai_addr, statePtr->myaddr->ai_addrlen) == SOCKET_ERROR) { TclWinConvertError((DWORD) WSAGetLastError()); continue; } /* * For asyncroneous connect set the socket in nonblocking mode * and activate connect notification */ if (async_connect) { TcpState *statePtr2; int in_socket_list = 0; /* get statePtr lock */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); /* * Bugfig for 336441ed59 to not ignore notifications until the * infoPtr is in the list. * Check if my statePtr is already in the tsdPtr->socketList * It is set after this call by TcpThreadActionProc and is set * on a second round. * * If not, we buffer my statePtr in the tsd memory so it is not * lost by the event procedure */ for (statePtr2 = tsdPtr->socketList; statePtr2 != NULL; statePtr2 = statePtr2->nextPtr) { if (statePtr2 == statePtr) { in_socket_list = 1; break; } } if (!in_socket_list) { tsdPtr->pendingTcpState = statePtr; } /* * Set connect mask to connect events * This is activated by a SOCKET_SELECT message to the notifier * thread. */ statePtr->selectEvents |= FD_CONNECT; /* * Free list lock */ SetEvent(tsdPtr->socketListLock); /* activate accept notification */ SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT, (LPARAM) statePtr); } /* * Attempt to connect to the remote socket. */ connect(statePtr->sockets->fd, statePtr->addr->ai_addr, statePtr->addr->ai_addrlen); error = WSAGetLastError(); TclWinConvertError(error); if (async_connect && error == WSAEWOULDBLOCK) { /* * Asynchroneous connect */ /* * Remember that we jump back behind this next round */ statePtr->flags |= TCP_ASYNC_PENDING; return TCL_OK; reenter: /* * Re-entry point for async connect after connect event or * blocking operation * * Clear the reenter flag */ statePtr->flags &= ~(TCP_ASYNC_PENDING); /* get statePtr lock */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); /* Get signaled connect error */ TclWinConvertError((DWORD) statePtr->notifierConnectError); /* Clear eventual connect flag */ statePtr->selectEvents &= ~(FD_CONNECT); /* Free list lock */ SetEvent(tsdPtr->socketListLock); } /* * Clear the tsd socket list pointer if we did not wait for * the FD_CONNECT asyncroneously */ tsdPtr->pendingTcpState = NULL; if (Tcl_GetErrno() == 0) { goto out; } } } out: /* * Socket connected or connection failed */ /* * Async connect terminated */ CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT); if ( Tcl_GetErrno() == 0 ) { /* * Succesfully connected */ /* * Set up the select mask for read/write events. */ statePtr->selectEvents = FD_READ | FD_WRITE | FD_CLOSE; /* * Register for interest in events in the select mask. Note that this * automatically places the socket into non-blocking mode. */ SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT, (LPARAM) statePtr); } else { /* * Connect failed */ /* * For async connect schedule a writable event to report the fail. */ if (async_callback) { /* * Set up the select mask for read/write events. */ statePtr->selectEvents = FD_WRITE|FD_READ; /* get statePtr lock */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); /* Signal ready readable and writable events */ statePtr->readyEvents |= FD_WRITE | FD_READ; /* Flag error to event routine */ statePtr->flags |= TCP_ASYNC_FAILED; /* Save connect error to be reported by 'fconfigure -error' */ statePtr->connectError = Tcl_GetErrno(); /* Free list lock */ SetEvent(tsdPtr->socketListLock); } /* * Error message on syncroneous connect */ if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open socket: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_OpenTcpClient -- * * Opens a TCP client socket and creates a channel around it. * * Results: * The channel or NULL if failed. An error message is returned in the * interpreter on failure. * * Side effects: * Opens a client socket and creates a new channel. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_OpenTcpClient( Tcl_Interp *interp, /* For error reporting; can be NULL. */ int port, /* Port number to open. */ const char *host, /* Host on which to open port. */ const char *myaddr, /* Client-side address */ int myport, /* Client-side port */ int async) /* If nonzero, attempt to do an asynchronous * connect. Otherwise we do a blocking * connect. */ { TcpState *statePtr; const char *errorMsg = NULL; struct addrinfo *addrlist = NULL, *myaddrlist = NULL; char channelName[SOCK_CHAN_LENGTH]; if (TclpHasSockets(interp) != TCL_OK) { return NULL; } /* * Check that WinSock is initialized; do not call it if not, to prevent * system crashes. This can happen at exit time if the exit handler for * WinSock ran before other exit handlers that want to use sockets. */ if (!SocketsEnabled()) { return NULL; } /* * Do the name lookups for the local and remote addresses. */ if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0, &errorMsg) || !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1, &errorMsg)) { if (addrlist != NULL) { freeaddrinfo(addrlist); } if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open socket: %s", errorMsg)); } return NULL; } statePtr = NewSocketInfo(INVALID_SOCKET); statePtr->addrlist = addrlist; statePtr->myaddrlist = myaddrlist; if (async) { statePtr->flags |= TCP_ASYNC_CONNECT; } /* * Create a new client socket and wrap it in a channel. */ if (TcpConnect(interp, statePtr) != TCL_OK) { TcpCloseProc(statePtr, NULL); return NULL; } sprintf(channelName, SOCK_TEMPLATE, statePtr); statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, statePtr, (TCL_READABLE | TCL_WRITABLE)); if (TCL_ERROR == Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf")) { Tcl_Close(NULL, statePtr->channel); return NULL; } else if (TCL_ERROR == Tcl_SetChannelOption(NULL, statePtr->channel, "-eofchar", "")) { Tcl_Close(NULL, statePtr->channel); return NULL; } return statePtr->channel; } /* *---------------------------------------------------------------------- * * Tcl_MakeTcpClientChannel -- * * Creates a Tcl_Channel from an existing client TCP socket. * * Results: * The Tcl_Channel wrapped around the preexisting TCP socket. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_MakeTcpClientChannel( ClientData sock) /* The socket to wrap up into a channel. */ { TcpState *statePtr; char channelName[SOCK_CHAN_LENGTH]; ThreadSpecificData *tsdPtr; if (TclpHasSockets(NULL) != TCL_OK) { return NULL; } tsdPtr = TclThreadDataKeyGet(&dataKey); /* * Set kernel space buffering and non-blocking. */ TclSockMinimumBuffers(sock, TCP_BUFFER_SIZE); statePtr = NewSocketInfo((SOCKET) sock); /* * Start watching for read/write events on the socket. */ statePtr->selectEvents = FD_READ | FD_CLOSE | FD_WRITE; SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM)SELECT, (LPARAM)statePtr); sprintf(channelName, SOCK_TEMPLATE, statePtr); statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, statePtr, (TCL_READABLE | TCL_WRITABLE)); Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf"); return statePtr->channel; } /* *---------------------------------------------------------------------- * * Tcl_OpenTcpServer -- * * Opens a TCP server socket and creates a channel around it. * * Results: * The channel or NULL if failed. If an error occurred, an error message * is left in the interp's result if interp is not NULL. * * Side effects: * Opens a server socket and creates a new channel. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_OpenTcpServer( Tcl_Interp *interp, /* For error reporting - may be NULL. */ int port, /* Port number to open. */ const char *myHost, /* Name of local host. */ Tcl_TcpAcceptProc *acceptProc, /* Callback for accepting connections from new * clients. */ ClientData acceptProcData) /* Data for the callback. */ { SOCKET sock = INVALID_SOCKET; unsigned short chosenport = 0; struct addrinfo *addrlist = NULL; struct addrinfo *addrPtr; /* Socket address to listen on. */ TcpState *statePtr = NULL; /* The returned value. */ char channelName[SOCK_CHAN_LENGTH]; u_long flag = 1; /* Indicates nonblocking mode. */ const char *errorMsg = NULL; ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); if (TclpHasSockets(interp) != TCL_OK) { return NULL; } /* * Check that WinSock is initialized; do not call it if not, to prevent * system crashes. This can happen at exit time if the exit handler for * WinSock ran before other exit handlers that want to use sockets. */ if (!SocketsEnabled()) { return NULL; } /* * Construct the addresses for each end of the socket. */ if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1, &errorMsg)) { goto error; } for (addrPtr = addrlist; addrPtr != NULL; addrPtr = addrPtr->ai_next) { sock = socket(addrPtr->ai_family, addrPtr->ai_socktype, addrPtr->ai_protocol); if (sock == INVALID_SOCKET) { TclWinConvertError((DWORD) WSAGetLastError()); continue; } /* * Win-NT has a misfeature that sockets are inherited in child * processes by default. Turn off the inherit bit. */ SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0); /* * Set kernel space buffering */ TclSockMinimumBuffers((void *)sock, TCP_BUFFER_SIZE); /* * Make sure we use the same port when opening two server sockets * for IPv4 and IPv6. * * As sockaddr_in6 uses the same offset and size for the port * member as sockaddr_in, we can handle both through the IPv4 API. */ if (port == 0 && chosenport != 0) { ((struct sockaddr_in *) addrPtr->ai_addr)->sin_port = htons(chosenport); } /* * Bind to the specified port. Note that we must not call * setsockopt with SO_REUSEADDR because Microsoft allows addresses * to be reused even if they are still in use. * * Bind should not be affected by the socket having already been * set into nonblocking mode. If there is trouble, this is one * place to look for bugs. */ if (bind(sock, addrPtr->ai_addr, addrPtr->ai_addrlen) == SOCKET_ERROR) { TclWinConvertError((DWORD) WSAGetLastError()); closesocket(sock); continue; } if (port == 0 && chosenport == 0) { address sockname; socklen_t namelen = sizeof(sockname); /* * Synchronize port numbers when binding to port 0 of multiple * addresses. */ if (getsockname(sock, &sockname.sa, &namelen) >= 0) { chosenport = ntohs(sockname.sa4.sin_port); } } /* * Set the maximum number of pending connect requests to the max * value allowed on each platform (Win32 and Win32s may be * different, and there may be differences between TCP/IP stacks). */ if (listen(sock, SOMAXCONN) == SOCKET_ERROR) { TclWinConvertError((DWORD) WSAGetLastError()); closesocket(sock); continue; } if (statePtr == NULL) { /* * Add this socket to the global list of sockets. */ statePtr = NewSocketInfo(sock); } else { AddSocketInfoFd( statePtr, sock ); } } error: if (addrlist != NULL) { freeaddrinfo(addrlist); } if (statePtr != NULL) { statePtr->acceptProc = acceptProc; statePtr->acceptProcData = acceptProcData; sprintf(channelName, SOCK_TEMPLATE, statePtr); statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, statePtr, 0); /* * Set up the select mask for connection request events. */ statePtr->selectEvents = FD_ACCEPT; /* * Register for interest in events in the select mask. Note that this * automatically places the socket into non-blocking mode. */ ioctlsocket(sock, (long) FIONBIO, &flag); SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT, (LPARAM) statePtr); if (Tcl_SetChannelOption(interp, statePtr->channel, "-eofchar", "") == TCL_ERROR) { Tcl_Close(NULL, statePtr->channel); return NULL; } return statePtr->channel; } if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open socket: %s", (errorMsg ? errorMsg : Tcl_PosixError(interp)))); } if (sock != INVALID_SOCKET) { closesocket(sock); } return NULL; } /* *---------------------------------------------------------------------- * * TcpAccept -- * Accept a TCP socket connection. This is called by the event loop. * * Results: * None. * * Side effects: * Creates a new connection socket. Calls the registered callback for the * connection acceptance mechanism. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static void TcpAccept( TcpFdList *fds, /* Server socket that accepted newSocket. */ SOCKET newSocket, /* Newly accepted socket. */ address addr) /* Address of new socket. */ { TcpState *newInfoPtr; TcpState *statePtr = fds->statePtr; int len = sizeof(addr); char channelName[SOCK_CHAN_LENGTH]; char host[NI_MAXHOST], port[NI_MAXSERV]; ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); /* * Win-NT has a misfeature that sockets are inherited in child processes * by default. Turn off the inherit bit. */ SetHandleInformation((HANDLE) newSocket, HANDLE_FLAG_INHERIT, 0); /* * Add this socket to the global list of sockets. */ newInfoPtr = NewSocketInfo(newSocket); /* * Select on read/write events and create the channel. */ newInfoPtr->selectEvents = (FD_READ | FD_WRITE | FD_CLOSE); SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT, (LPARAM) newInfoPtr); sprintf(channelName, SOCK_TEMPLATE, newInfoPtr); newInfoPtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, newInfoPtr, (TCL_READABLE | TCL_WRITABLE)); if (Tcl_SetChannelOption(NULL, newInfoPtr->channel, "-translation", "auto crlf") == TCL_ERROR) { Tcl_Close(NULL, newInfoPtr->channel); return; } if (Tcl_SetChannelOption(NULL, newInfoPtr->channel, "-eofchar", "") == TCL_ERROR) { Tcl_Close(NULL, newInfoPtr->channel); return; } /* * Invoke the accept callback function. */ if (statePtr->acceptProc != NULL) { getnameinfo(&(addr.sa), len, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV); statePtr->acceptProc(statePtr->acceptProcData, newInfoPtr->channel, host, atoi(port)); } } /* *---------------------------------------------------------------------- * * InitSockets -- * * Registers the event window for the socket notifier code. * * Assumes socketMutex is held. * * Results: * None. * * Side effects: * Register a new window class and creates a * window for use in asynchronous socket notification. * *---------------------------------------------------------------------- */ static void InitSockets(void) { DWORD id; ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); if (!initialized) { initialized = 1; TclCreateLateExitHandler(SocketExitHandler, NULL); /* * Create the async notification window with a new class. We must * create a new class to avoid a Windows 95 bug that causes us to get * the wrong message number for socket events if the message window is * a subclass of a static control. */ windowClass.style = 0; windowClass.cbClsExtra = 0; windowClass.cbWndExtra = 0; windowClass.hInstance = TclWinGetTclInstance(); windowClass.hbrBackground = NULL; windowClass.lpszMenuName = NULL; windowClass.lpszClassName = classname; windowClass.lpfnWndProc = SocketProc; windowClass.hIcon = NULL; windowClass.hCursor = NULL; if (!RegisterClass(&windowClass)) { TclWinConvertError(GetLastError()); goto initFailure; } } /* * Check for per-thread initialization. */ if (tsdPtr != NULL) { return; } /* * OK, this thread has never done anything with sockets before. Construct * a worker thread to handle asynchronous events related to sockets * assigned to _this_ thread. */ tsdPtr = TCL_TSD_INIT(&dataKey); tsdPtr->pendingTcpState = NULL; tsdPtr->socketList = NULL; tsdPtr->hwnd = NULL; tsdPtr->threadId = Tcl_GetCurrentThread(); tsdPtr->readyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (tsdPtr->readyEvent == NULL) { goto initFailure; } tsdPtr->socketListLock = CreateEvent(NULL, FALSE, TRUE, NULL); if (tsdPtr->socketListLock == NULL) { goto initFailure; } tsdPtr->socketThread = CreateThread(NULL, 256, SocketThread, tsdPtr, 0, &id); if (tsdPtr->socketThread == NULL) { goto initFailure; } SetThreadPriority(tsdPtr->socketThread, THREAD_PRIORITY_HIGHEST); /* * Wait for the thread to signal when the window has been created and if * it is ready to go. */ WaitForSingleObject(tsdPtr->readyEvent, INFINITE); if (tsdPtr->hwnd == NULL) { goto initFailure; /* Trouble creating the window. */ } Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL); return; initFailure: TclpFinalizeSockets(); initialized = -1; return; } /* *---------------------------------------------------------------------- * * SocketsEnabled -- * * Check that the WinSock was successfully initialized. * * Warning: * This check was useful in times of Windows98 where WinSock may * not be available. This is not the case any more. * This function may be removed with TCL 9.0 * * Results: * 1 if it is. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int SocketsEnabled(void) { int enabled; Tcl_MutexLock(&socketMutex); enabled = (initialized == 1); Tcl_MutexUnlock(&socketMutex); return enabled; } /* *---------------------------------------------------------------------- * * SocketExitHandler -- * * Callback invoked during exit clean up to delete the socket * communication window. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static void SocketExitHandler( ClientData clientData) /* Not used. */ { Tcl_MutexLock(&socketMutex); /* * Make sure the socket event handling window is cleaned-up for, at * most, this thread. */ TclpFinalizeSockets(); UnregisterClass(classname, TclWinGetTclInstance()); initialized = 0; Tcl_MutexUnlock(&socketMutex); } /* *---------------------------------------------------------------------- * * SocketSetupProc -- * * This function is invoked before Tcl_DoOneEvent blocks waiting for an * event. * * Results: * None. * * Side effects: * Adjusts the block time if needed. * *---------------------------------------------------------------------- */ void SocketSetupProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { TcpState *statePtr; Tcl_Time blockTime = { 0, 0 }; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } /* * Check to see if there is a ready socket. If so, poll. */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if (statePtr->readyEvents & (statePtr->watchEvents | FD_CONNECT | FD_ACCEPT) ) { Tcl_SetMaxBlockTime(&blockTime); break; } } SetEvent(tsdPtr->socketListLock); } /* *---------------------------------------------------------------------- * * SocketCheckProc -- * * This function is called by Tcl_DoOneEvent to check the socket event * source for events. * * Results: * None. * * Side effects: * May queue an event. * *---------------------------------------------------------------------- */ static void SocketCheckProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { TcpState *statePtr; SocketEvent *evPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!(flags & TCL_FILE_EVENTS)) { return; } /* * Queue events for any ready sockets that don't already have events * queued (caused by persistent states that won't generate WinSock * events). */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if ((statePtr->readyEvents & (statePtr->watchEvents | FD_CONNECT | FD_ACCEPT)) && !(statePtr->flags & SOCKET_PENDING) ) { statePtr->flags |= SOCKET_PENDING; evPtr = ckalloc(sizeof(SocketEvent)); evPtr->header.proc = SocketEventProc; evPtr->socket = statePtr->sockets->fd; Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL); } } SetEvent(tsdPtr->socketListLock); } /* *---------------------------------------------------------------------- * * SocketEventProc -- * * This function is called by Tcl_ServiceEvent when a socket event * reaches the front of the event queue. This function is responsible for * notifying the generic channel code. * * Results: * Returns 1 if the event was handled, meaning it should be removed from * the queue. Returns 0 if the event was not handled, meaning it should * stay on the queue. The only time the event isn't handled is if the * TCL_FILE_EVENTS flag bit isn't set. * * Side effects: * Whatever the channel callback functions do. * *---------------------------------------------------------------------- */ static int SocketEventProc( Tcl_Event *evPtr, /* Event to service. */ int flags) /* Flags that indicate what events to handle, * such as TCL_FILE_EVENTS. */ { TcpState *statePtr; SocketEvent *eventPtr = (SocketEvent *) evPtr; int mask = 0, events; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); TcpFdList *fds; SOCKET newSocket; address addr; int len; if (!(flags & TCL_FILE_EVENTS)) { return 0; } /* * Find the specified socket on the socket list. */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if (statePtr->sockets->fd == eventPtr->socket) { break; } } /* * Discard events that have gone stale. */ if (!statePtr) { SetEvent(tsdPtr->socketListLock); return 1; } /* * Clear flag that (this) event is pending */ statePtr->flags &= ~SOCKET_PENDING; /* * Continue async connect if pending and ready */ if ( statePtr->readyEvents & FD_CONNECT ) { if ( statePtr->flags & TCP_ASYNC_PENDING ) { /* * Do one step and save eventual connect error */ SetEvent(tsdPtr->socketListLock); WaitForConnect(statePtr,NULL); } else { /* * No async connect reenter pending. Just clear event. */ statePtr->readyEvents &= ~(FD_CONNECT); SetEvent(tsdPtr->socketListLock); } return 1; } /* * Handle connection requests directly. */ if (statePtr->readyEvents & FD_ACCEPT) { for (fds = statePtr->sockets; fds != NULL; fds = fds->next) { /* * Accept the incoming connection request. */ len = sizeof(address); newSocket = accept(fds->fd, &(addr.sa), &len); /* On Tcl server sockets with multiple OS fds we loop over the fds trying * an accept() on each, so we expect INVALID_SOCKET. There are also other * network stack conditions that can result in FD_ACCEPT but a subsequent * failure on accept() by the time we get around to it. * Access to sockets (acceptEventCount, readyEvents) in socketList * is still protected by the lock (prevents reintroduction of * SF Tcl Bug 3056775. */ if (newSocket == INVALID_SOCKET) { /* int err = WSAGetLastError(); */ continue; } /* * It is possible that more than one FD_ACCEPT has been sent, so an extra * count must be kept. Decrement the count, and reset the readyEvent bit * if the count is no longer > 0. */ statePtr->acceptEventCount--; if (statePtr->acceptEventCount <= 0) { statePtr->readyEvents &= ~(FD_ACCEPT); } SetEvent(tsdPtr->socketListLock); /* Caution: TcpAccept() has the side-effect of evaluating the server * accept script (via AcceptCallbackProc() in tclIOCmd.c), which can * close the server socket and invalidate statePtr and fds. * If TcpAccept() accepts a socket we must return immediately and let * SocketCheckProc queue additional FD_ACCEPT events. */ TcpAccept(fds, newSocket, addr); return 1; } /* Loop terminated with no sockets accepted; clear the ready mask so * we can detect the next connection request. Note that connection * requests are level triggered, so if there is a request already * pending, a new event will be generated. */ statePtr->acceptEventCount = 0; statePtr->readyEvents &= ~(FD_ACCEPT); SetEvent(tsdPtr->socketListLock); return 1; } SetEvent(tsdPtr->socketListLock); /* * Mask off unwanted events and compute the read/write mask so we can * notify the channel. */ events = statePtr->readyEvents & statePtr->watchEvents; if (events & FD_CLOSE) { /* * If the socket was closed and the channel is still interested in * read events, then we need to ensure that we keep polling for this * event until someone does something with the channel. Note that we * do this before calling Tcl_NotifyChannel so we don't have to watch * out for the channel being deleted out from under us. This may cause * a redundant trip through the event loop, but it's simpler than * trying to do unwind protection. */ Tcl_Time blockTime = { 0, 0 }; Tcl_SetMaxBlockTime(&blockTime); mask |= TCL_READABLE|TCL_WRITABLE; } else if (events & FD_READ) { /* * Throw the readable event if an async connect failed. */ if ( statePtr->flags & TCP_ASYNC_FAILED ) { mask |= TCL_READABLE; } else { fd_set readFds; struct timeval timeout; /* * We must check to see if data is really available, since someone * could have consumed the data in the meantime. Turn off async * notification so select will work correctly. If the socket is * still readable, notify the channel driver, otherwise reset the * async select handler and keep waiting. */ SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) UNSELECT, (LPARAM) statePtr); FD_ZERO(&readFds); FD_SET(statePtr->sockets->fd, &readFds); timeout.tv_usec = 0; timeout.tv_sec = 0; if (select(0, &readFds, NULL, NULL, &timeout) != 0) { mask |= TCL_READABLE; } else { statePtr->readyEvents &= ~(FD_READ); SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT, (LPARAM) statePtr); } } } /* * writable event */ if (events & FD_WRITE) { mask |= TCL_WRITABLE; } /* * Call registered event procedures */ if (mask) { Tcl_NotifyChannel(statePtr->channel, mask); } return 1; } /* *---------------------------------------------------------------------- * * AddSocketInfoFd -- * * This function adds a SOCKET file descriptor to the 'sockets' linked * list of a TcpState structure. * * Results: * None. * * Side effects: * None, except for allocation of memory. * *---------------------------------------------------------------------- */ static void AddSocketInfoFd( TcpState *statePtr, SOCKET socket) { TcpFdList *fds = statePtr->sockets; if ( fds == NULL ) { /* Add the first FD */ statePtr->sockets = ckalloc(sizeof(TcpFdList)); fds = statePtr->sockets; } else { /* Find end of list and append FD */ while ( fds->next != NULL ) { fds = fds->next; } fds->next = ckalloc(sizeof(TcpFdList)); fds = fds->next; } /* Populate new FD */ fds->fd = socket; fds->statePtr = statePtr; fds->next = NULL; } /* *---------------------------------------------------------------------- * * NewSocketInfo -- * * This function allocates and initializes a new TcpState structure. * * Results: * Returns a newly allocated TcpState. * * Side effects: * None, except for allocation of memory. * *---------------------------------------------------------------------- */ static TcpState * NewSocketInfo(SOCKET socket) { TcpState *statePtr = ckalloc(sizeof(TcpState)); memset(statePtr, 0, sizeof(TcpState)); /* * TIP #218. Removed the code inserting the new structure into the global * list. This is now handled in the thread action callbacks, and only * there. */ AddSocketInfoFd(statePtr, socket); return statePtr; } /* *---------------------------------------------------------------------- * * WaitForSocketEvent -- * * Waits until one of the specified events occurs on a socket. * For event FD_CONNECT use WaitForConnect. * * Results: * Returns 1 on success or 0 on failure, with an error code in * errorCodePtr. * * Side effects: * Processes socket events off the system queue. * *---------------------------------------------------------------------- */ static int WaitForSocketEvent( TcpState *statePtr, /* Information about this socket. */ int events, /* Events to look for. May be one of * FD_READ or FD_WRITE. */ int *errorCodePtr) /* Where to store errors? */ { int result = 1; int oldMode; ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); /* * Be sure to disable event servicing so we are truly modal. */ oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE); /* * Reset WSAAsyncSelect so we have a fresh set of events pending. */ SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) UNSELECT, (LPARAM) statePtr); SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT, (LPARAM) statePtr); while (1) { int event_found; /* get statePtr lock */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); /* Check if event occured */ event_found = (statePtr->readyEvents & events); /* Free list lock */ SetEvent(tsdPtr->socketListLock); /* exit loop if event occured */ if (event_found) { break; } /* Exit loop if event did not occur but this is a non-blocking channel */ if (statePtr->flags & TCP_NONBLOCKING) { *errorCodePtr = EWOULDBLOCK; result = 0; break; } /* * Wait until something happens. */ WaitForSingleObject(tsdPtr->readyEvent, INFINITE); } (void) Tcl_SetServiceMode(oldMode); return result; } /* *---------------------------------------------------------------------- * * SocketThread -- * * Helper thread used to manage the socket event handling window. * * Results: * 1 if unable to create socket event window, 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ static DWORD WINAPI SocketThread( LPVOID arg) { MSG msg; ThreadSpecificData *tsdPtr = arg; /* * Create a dummy window receiving socket events. */ tsdPtr->hwnd = CreateWindow(classname, classname, WS_TILED, 0, 0, 0, 0, NULL, NULL, windowClass.hInstance, arg); /* * Signalize thread creator that we are done creating the window. */ SetEvent(tsdPtr->readyEvent); /* * If unable to create the window, exit this thread immediately. */ if (tsdPtr->hwnd == NULL) { return 1; } /* * Process all messages on the socket window until WM_QUIT. This threads * exits only when instructed to do so by the call to * PostMessage(SOCKET_TERMINATE) in TclpFinalizeSockets(). */ while (GetMessage(&msg, NULL, 0, 0) > 0) { DispatchMessage(&msg); } /* * This releases waiters on thread exit in TclpFinalizeSockets() */ SetEvent(tsdPtr->readyEvent); return msg.wParam; } /* *---------------------------------------------------------------------- * * SocketProc -- * * This function is called when WSAAsyncSelect has been used to register * interest in a socket event, and the event has occurred. * * Results: * 0 on success. * * Side effects: * The flags for the given socket are updated to reflect the event that * occured. * *---------------------------------------------------------------------- */ static LRESULT CALLBACK SocketProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { int event, error; SOCKET socket; TcpState *statePtr; int info_found = 0; TcpFdList *fds = NULL; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) #ifdef _WIN64 GetWindowLongPtr(hwnd, GWLP_USERDATA); #else GetWindowLong(hwnd, GWL_USERDATA); #endif switch (message) { default: return DefWindowProc(hwnd, message, wParam, lParam); break; case WM_CREATE: /* * Store the initial tsdPtr, it's from a different thread, so it's not * directly accessible, but needed. */ #ifdef _WIN64 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) ((LPCREATESTRUCT)lParam)->lpCreateParams); #else SetWindowLong(hwnd, GWL_USERDATA, (LONG) ((LPCREATESTRUCT)lParam)->lpCreateParams); #endif break; case WM_DESTROY: PostQuitMessage(0); break; case SOCKET_MESSAGE: event = WSAGETSELECTEVENT(lParam); error = WSAGETSELECTERROR(lParam); socket = (SOCKET) wParam; WaitForSingleObject(tsdPtr->socketListLock, INFINITE); /* * Find the specified socket on the socket list and update its * eventState flag. */ for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if ( FindFDInList(statePtr,socket) ) { info_found = 1; break; } } /* * Check if there is a pending info structure not jet in the * list */ if ( !info_found && tsdPtr->pendingTcpState != NULL && FindFDInList(tsdPtr->pendingTcpState,socket) ) { statePtr = tsdPtr->pendingTcpState; info_found = 1; } if (info_found) { /* * Update the socket state. * * A count of FD_ACCEPTS is stored, so if an FD_CLOSE event * happens, then clear the FD_ACCEPT count. Otherwise, * increment the count if the current event is an FD_ACCEPT. */ if (event & FD_CLOSE) { statePtr->acceptEventCount = 0; statePtr->readyEvents &= ~(FD_WRITE|FD_ACCEPT); } else if (event & FD_ACCEPT) { statePtr->acceptEventCount++; } if (event & FD_CONNECT) { /* * Remember any error that occurred so we can report * connection failures. */ if (error != ERROR_SUCCESS) { statePtr->notifierConnectError = error; } } /* * Inform main thread about signaled events */ statePtr->readyEvents |= event; /* * Wake up the Main Thread. */ SetEvent(tsdPtr->readyEvent); Tcl_ThreadAlert(tsdPtr->threadId); } SetEvent(tsdPtr->socketListLock); break; case SOCKET_SELECT: statePtr = (TcpState *) lParam; for (fds = statePtr->sockets; fds != NULL; fds = fds->next) { if (wParam == SELECT) { WSAAsyncSelect(fds->fd, hwnd, SOCKET_MESSAGE, statePtr->selectEvents); } else { /* * Clear the selection mask */ WSAAsyncSelect(fds->fd, hwnd, 0, 0); } } break; case SOCKET_TERMINATE: DestroyWindow(hwnd); break; } return 0; } /* *---------------------------------------------------------------------- * * FindFDInList -- * * Return true, if the given file descriptior is contained in the * file descriptor list. * * Results: * true if found. * * Side effects: * *---------------------------------------------------------------------- */ static int FindFDInList( TcpState *statePtr, SOCKET socket) { TcpFdList *fds; for (fds = statePtr->sockets; fds != NULL; fds = fds->next) { if (fds->fd == socket) { return 1; } } return 0; } /* *---------------------------------------------------------------------- * * TclWinGetSockOpt, et al. -- * * Those functions are historically exported by the stubs table and * just use the original system calls now. * * Warning: * Those functions are depreciated and will be removed with TCL 9.0. * * Results: * As defined for each function. * * Side effects: * As defined for each function. * *---------------------------------------------------------------------- */ #undef TclWinGetSockOpt int TclWinGetSockOpt( SOCKET s, int level, int optname, char *optval, int *optlen) { return getsockopt(s, level, optname, optval, optlen); } #undef TclWinSetSockOpt int TclWinSetSockOpt( SOCKET s, int level, int optname, const char *optval, int optlen) { return setsockopt(s, level, optname, optval, optlen); } #undef TclpInetNtoa char * TclpInetNtoa( struct in_addr addr) { return inet_ntoa(addr); } #undef TclWinGetServByName struct servent * TclWinGetServByName( const char *name, const char *proto) { return getservbyname(name, proto); } /* *---------------------------------------------------------------------- * * TcpThreadActionProc -- * * Insert or remove any thread local refs to this channel. * * Results: * None. * * Side effects: * Changes thread local list of valid channels. * *---------------------------------------------------------------------- */ static void TcpThreadActionProc( ClientData instanceData, int action) { ThreadSpecificData *tsdPtr; TcpState *statePtr = instanceData; int notifyCmd; if (action == TCL_CHANNEL_THREAD_INSERT) { /* * Ensure that socket subsystem is initialized in this thread, or else * sockets will not work. */ Tcl_MutexLock(&socketMutex); InitSockets(); Tcl_MutexUnlock(&socketMutex); tsdPtr = TCL_TSD_INIT(&dataKey); WaitForSingleObject(tsdPtr->socketListLock, INFINITE); statePtr->nextPtr = tsdPtr->socketList; tsdPtr->socketList = statePtr; if (statePtr == tsdPtr->pendingTcpState) { tsdPtr->pendingTcpState = NULL; } SetEvent(tsdPtr->socketListLock); notifyCmd = SELECT; } else { TcpState **nextPtrPtr; int removed = 0; tsdPtr = TCL_TSD_INIT(&dataKey); /* * TIP #218, Bugfix: All access to socketList has to be protected by * the lock. */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL; nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { if ((*nextPtrPtr) == statePtr) { (*nextPtrPtr) = statePtr->nextPtr; removed = 1; break; } } SetEvent(tsdPtr->socketListLock); /* * This could happen if the channel was created in one thread and then * moved to another without updating the thread local data in each * thread. */ if (!removed) { Tcl_Panic("file info ptr not on thread channel list"); } notifyCmd = UNSELECT; } /* * Ensure that, or stop, notifications for the socket occur in this * thread. */ SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) notifyCmd, (LPARAM) statePtr); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * indent-tabs-mode: nil * End: */ tcl8.6.5/win/tclConfig.sh.in0000644000175000017500000001451512665173607015246 0ustar sergeisergei# tclConfig.sh -- # # This shell script (for sh) is generated automatically by Tcl's # configure script. It will create shell variables for most of # the configuration options discovered by the configure script. # This script is intended to be included by the configure scripts # for Tcl extensions so that they don't have to figure this all # out for themselves. # # The information in this file is specific to a single platform. TCL_DLL_FILE="@TCL_DLL_FILE@" # Tcl's version number. TCL_VERSION='@TCL_VERSION@' TCL_MAJOR_VERSION='@TCL_MAJOR_VERSION@' TCL_MINOR_VERSION='@TCL_MINOR_VERSION@' TCL_PATCH_LEVEL='@TCL_PATCH_LEVEL@' # C compiler to use for compilation. TCL_CC='@CC@' # -D flags for use with the C compiler. TCL_DEFS='@DEFS@' # If TCL was built with debugging symbols, generated libraries contain # this string at the end of the library name (before the extension). TCL_DBGX=@TCL_DBGX@ # Default flags used in an optimized and debuggable build, respectively. TCL_CFLAGS_DEBUG='@CFLAGS_DEBUG@' TCL_CFLAGS_OPTIMIZE='@CFLAGS_OPTIMIZE@' # Default linker flags used in an optimized and debuggable build, respectively. TCL_LDFLAGS_DEBUG='@LDFLAGS_DEBUG@' TCL_LDFLAGS_OPTIMIZE='@LDFLAGS_OPTIMIZE@' # Flag, 1: we built a shared lib, 0 we didn't TCL_SHARED_BUILD=@TCL_SHARED_BUILD@ # The name of the Tcl library (may be either a .a file or a shared library): TCL_LIB_FILE='@TCL_LIB_FILE@' # Flag to indicate whether shared libraries need export files. TCL_NEEDS_EXP_FILE=@TCL_NEEDS_EXP_FILE@ # String that can be evaluated to generate the part of the export file # name that comes after the "libxxx" (includes version number, if any, # extension, and anything else needed). May depend on the variables # VERSION. On most UNIX systems this is ${VERSION}.exp. TCL_EXPORT_FILE_SUFFIX='@CFG_TCL_EXPORT_FILE_SUFFIX@' # Additional libraries to use when linking Tcl. TCL_LIBS='@LIBS@' # Top-level directory in which Tcl's platform-independent files are # installed. TCL_PREFIX='@prefix@' # Top-level directory in which Tcl's platform-specific files (e.g. # executables) are installed. TCL_EXEC_PREFIX='@exec_prefix@' # Flags to pass to cc when compiling the components of a shared library: TCL_SHLIB_CFLAGS='@SHLIB_CFLAGS@' # Flags to pass to cc to get warning messages TCL_CFLAGS_WARNING='@CFLAGS_WARNING@' # Extra flags to pass to cc: TCL_EXTRA_CFLAGS='@EXTRA_CFLAGS@' # Base command to use for combining object files into a shared library: TCL_SHLIB_LD='@SHLIB_LD@' # Base command to use for combining object files into a static library: TCL_STLIB_LD='@STLIB_LD@' # Either '$LIBS' (if dependent libraries should be included when linking # shared libraries) or an empty string. See Tcl's configure.in for more # explanation. TCL_SHLIB_LD_LIBS='@SHLIB_LD_LIBS@' # Suffix to use for the name of a shared library. TCL_SHLIB_SUFFIX='@SHLIB_SUFFIX@' # Library file(s) to include in tclsh and other base applications # in order to provide facilities needed by DLOBJ above. TCL_DL_LIBS='@DL_LIBS@' # Flags to pass to the compiler when linking object files into # an executable tclsh or tcltest binary. TCL_LD_FLAGS='@LDFLAGS@' # Flags to pass to ld, such as "-R /usr/local/tcl/lib", that tell the # run-time dynamic linker where to look for shared libraries such as # libtcl.so. Used when linking applications. Only works if there # is a variable "LIB_RUNTIME_DIR" defined in the Makefile. TCL_LD_SEARCH_FLAGS='@TCL_LD_SEARCH_FLAGS@' # Additional object files linked with Tcl to provide compatibility # with standard facilities from ANSI C or POSIX. TCL_COMPAT_OBJS='@LIBOBJS@' # Name of the ranlib program to use. TCL_RANLIB='@RANLIB@' # -l flag to pass to the linker to pick up the Tcl library TCL_LIB_FLAG='@TCL_LIB_FLAG@' # String to pass to linker to pick up the Tcl library from its # build directory. TCL_BUILD_LIB_SPEC='@TCL_BUILD_LIB_SPEC@' # String to pass to linker to pick up the Tcl library from its # installed directory. TCL_LIB_SPEC='@TCL_LIB_SPEC@' # String to pass to the compiler so that an extension can # find installed Tcl headers. TCL_INCLUDE_SPEC='@TCL_INCLUDE_SPEC@' # Indicates whether a version numbers should be used in -l switches # ("ok" means it's safe to use switches like -ltcl7.5; "nodots" means # use switches like -ltcl75). SunOS and FreeBSD require "nodots", for # example. TCL_LIB_VERSIONS_OK='@TCL_LIB_VERSIONS_OK@' # String that can be evaluated to generate the part of a shared library # name that comes after the "libxxx" (includes version number, if any, # extension, and anything else needed). May depend on the variables # VERSION and SHLIB_SUFFIX. On most UNIX systems this is # ${VERSION}${SHLIB_SUFFIX}. TCL_SHARED_LIB_SUFFIX='@CFG_TCL_SHARED_LIB_SUFFIX@' # String that can be evaluated to generate the part of an unshared library # name that comes after the "libxxx" (includes version number, if any, # extension, and anything else needed). May depend on the variable # VERSION. On most UNIX systems this is ${VERSION}.a. TCL_UNSHARED_LIB_SUFFIX='@CFG_TCL_UNSHARED_LIB_SUFFIX@' # Location of the top-level source directory from which Tcl was built. # This is the directory that contains a README file as well as # subdirectories such as generic, unix, etc. If Tcl was compiled in a # different place than the directory containing the source files, this # points to the location of the sources, not the location where Tcl was # compiled. TCL_SRC_DIR='@TCL_SRC_DIR@' # List of standard directories in which to look for packages during # "package require" commands. Contains the "prefix" directory plus also # the "exec_prefix" directory, if it is different. TCL_PACKAGE_PATH='@TCL_PACKAGE_PATH@' # Tcl supports stub. TCL_SUPPORTS_STUBS=1 # The name of the Tcl stub library (.a): TCL_STUB_LIB_FILE='@TCL_STUB_LIB_FILE@' # -l flag to pass to the linker to pick up the Tcl stub library TCL_STUB_LIB_FLAG='@TCL_STUB_LIB_FLAG@' # String to pass to linker to pick up the Tcl stub library from its # build directory. TCL_BUILD_STUB_LIB_SPEC='@TCL_BUILD_STUB_LIB_SPEC@' # String to pass to linker to pick up the Tcl stub library from its # installed directory. TCL_STUB_LIB_SPEC='@TCL_STUB_LIB_SPEC@' # Path to the Tcl stub library in the build directory. TCL_BUILD_STUB_LIB_PATH='@TCL_BUILD_STUB_LIB_PATH@' # Path to the Tcl stub library in the install directory. TCL_STUB_LIB_PATH='@TCL_STUB_LIB_PATH@' # Flag, 1: we built Tcl with threads enabled, 0 we didn't TCL_THREADS=@TCL_THREADS@ tcl8.6.5/win/README0000644000175000017500000000572112663660066013252 0ustar sergeisergeiTcl 8.6 for Windows 1. Introduction --------------- This is the directory where you configure and compile the Windows version of Tcl. This directory also contains source files for Tcl that are specific to Microsoft Windows. The information in this file is maintained on the web at: http://www.tcl.tk/doc/howto/compile.html#win 2. Compiling Tcl ---------------- In order to compile Tcl for Windows, you need the following: Tcl 8.6 Source Distribution (plus any patches) and Visual C++ 6 or newer or Linux + MinGW-w64 [http://mingw-w64.sourceforge.net/] (win32 or win64) or Cygwin + MinGW-w64 [http://cygwin.com/install.html] (win32 or win64) or Darwin + MinGW-w64 [http://mingw-w64.sourceforge.net/] (win32 or win64) or Msys + MinGW-w64 [http://mingw-w64.sourceforge.net/] (win32 or win64) or Msys + MinGW [http://www.mingw.org/download.shtml] (win32 only) In practice, this release is built with Visual C++ 6.0 and the TEA Makefile. If you are building with Visual C++, in the "win" subdirectory of the source release, you will find "makefile.vc". This is the makefile for the Visual C++ compiler and uses the stock NMAKE tool. Detailed directions for using it, are in the comments of "makefile.vc". A quick example would be: C:\tcl_source\win\>nmake -f makefile.vc There is also a Developer Studio workspace and project file, too, if you would like to use them. If you are building with Linux, Cygwin or Msys, you can use the configure script that lives in the win subdirectory. The Linux/Cygwin/Msys based configure/build process works just like the UNIX one, so you will want to refer to ../unix/README for available configure options. If you want 64-bit executables (x86_64), you need to configure using the --enable-64bit option. Make sure that the x86_64-w64-mingw32 compiler is present. For Cygwin this compiler can be found in the "mingw64-x86_64-gcc-core" package, which can be installed through the normal Cygwin install process. If you only want 32-bit executables, the "mingw64-i686-gcc-core" package is what you need. For Linux, Darwin and Msys, you can download a suitable win32 or win64 compiler from [https://sourceforge.net/projects/mingw-w64/files/] Use the Makefile "install" target to install Tcl. It will install it according to the prefix options you provided in the correct directory structure. Note that in order to run tclsh86.exe, you must ensure that tcl86.dll is on your path, in the system directory, or in the directory containing tclsh86.exe. Note: Tcl no longer provides support for Win32s. 3. Test suite ------------- This distribution contains an extensive test suite for Tcl. Some of the tests are timing dependent and will fail from time to time. If a test is failing consistently, please send us a bug report with as much detail as you can manage to our tracker: http://core.tcl.tk/tcl/reportlist In order to run the test suite, you build the "test" target using the appropriate makefile for your compiler. tcl8.6.5/win/tclWinReg.c0000644000175000017500000011570312663660066014436 0ustar sergeisergei/* * tclWinReg.c -- * * This file contains the implementation of the "registry" Tcl built-in * command. This command is built as a dynamically loadable extension in * a separate DLL. * * Copyright (c) 1997 by Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #undef STATIC_BUILD #ifndef USE_TCL_STUBS # define USE_TCL_STUBS #endif #include "tclInt.h" #ifdef _MSC_VER # pragma comment (lib, "advapi32.lib") #endif #include #ifndef UNICODE # undef Tcl_WinTCharToUtf # define Tcl_WinTCharToUtf(a,b,c) Tcl_ExternalToUtfDString(NULL,a,b,c) # undef Tcl_WinUtfToTChar # define Tcl_WinUtfToTChar(a,b,c) Tcl_UtfToExternalDString(NULL,a,b,c) #endif /* !UNICODE */ /* * Ensure that we can say which registry is being accessed. */ #ifndef KEY_WOW64_64KEY # define KEY_WOW64_64KEY (0x0100) #endif #ifndef KEY_WOW64_32KEY # define KEY_WOW64_32KEY (0x0200) #endif /* * The maximum length of a sub-key name. */ #ifndef MAX_KEY_LENGTH # define MAX_KEY_LENGTH 256 #endif /* * The following macros convert between different endian ints. */ #define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x)) #define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x))) /* * The following flag is used in OpenKeys to indicate that the specified key * should be created if it doesn't currently exist. */ #define REG_CREATE 1 /* * The following tables contain the mapping from registry root names to the * system predefined keys. */ static const char *const rootKeyNames[] = { "HKEY_LOCAL_MACHINE", "HKEY_USERS", "HKEY_CLASSES_ROOT", "HKEY_CURRENT_USER", "HKEY_CURRENT_CONFIG", "HKEY_PERFORMANCE_DATA", "HKEY_DYN_DATA", NULL }; static const HKEY rootKeys[] = { HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, HKEY_DYN_DATA }; static const char REGISTRY_ASSOC_KEY[] = "registry::command"; /* * The following table maps from registry types to strings. Note that the * indices for this array are the same as the constants for the known registry * types so we don't need a separate table to hold the mapping. */ static const char *const typeNames[] = { "none", "sz", "expand_sz", "binary", "dword", "dword_big_endian", "link", "multi_sz", "resource_list", NULL }; static DWORD lastType = REG_RESOURCE_LIST; /* * Declarations for functions defined in this file. */ static void AppendSystemError(Tcl_Interp *interp, DWORD error); static int BroadcastValue(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static DWORD ConvertDWORD(DWORD type, DWORD value); static void DeleteCmd(ClientData clientData); static int DeleteKey(Tcl_Interp *interp, Tcl_Obj *keyNameObj, REGSAM mode); static int DeleteValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *valueNameObj, REGSAM mode); static int GetKeyNames(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *patternObj, REGSAM mode); static int GetType(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *valueNameObj, REGSAM mode); static int GetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *valueNameObj, REGSAM mode); static int GetValueNames(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *patternObj, REGSAM mode); static int OpenKey(Tcl_Interp *interp, Tcl_Obj *keyNameObj, REGSAM mode, int flags, HKEY *keyPtr); static DWORD OpenSubKey(char *hostName, HKEY rootKey, char *keyName, REGSAM mode, int flags, HKEY *keyPtr); static int ParseKeyName(Tcl_Interp *interp, char *name, char **hostNamePtr, HKEY *rootKeyPtr, char **keyNamePtr); static DWORD RecursiveDeleteKey(HKEY hStartKey, const TCHAR * pKeyName, REGSAM mode); static int RegistryObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int SetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *valueNameObj, Tcl_Obj *dataObj, Tcl_Obj *typeObj, REGSAM mode); DLLEXPORT int Registry_Init(Tcl_Interp *interp); DLLEXPORT int Registry_Unload(Tcl_Interp *interp, int flags); /* *---------------------------------------------------------------------- * * Registry_Init -- * * This function initializes the registry command. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Registry_Init( Tcl_Interp *interp) { Tcl_Command cmd; if (Tcl_InitStubs(interp, "8.5", 0) == NULL) { return TCL_ERROR; } cmd = Tcl_CreateObjCommand(interp, "registry", RegistryObjCmd, interp, DeleteCmd); Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, cmd); return Tcl_PkgProvide(interp, "registry", "1.3.1"); } /* *---------------------------------------------------------------------- * * Registry_Unload -- * * This function removes the registry command. * * Results: * A standard Tcl result. * * Side effects: * The registry command is deleted and the dll may be unloaded. * *---------------------------------------------------------------------- */ int Registry_Unload( Tcl_Interp *interp, /* Interpreter for unloading */ int flags) /* Flags passed by the unload system */ { Tcl_Command cmd; Tcl_Obj *objv[3]; /* * Unregister the registry package. There is no Tcl_PkgForget() */ objv[0] = Tcl_NewStringObj("package", -1); objv[1] = Tcl_NewStringObj("forget", -1); objv[2] = Tcl_NewStringObj("registry", -1); Tcl_EvalObjv(interp, 3, objv, TCL_EVAL_GLOBAL); /* * Delete the originally registered command. */ cmd = Tcl_GetAssocData(interp, REGISTRY_ASSOC_KEY, NULL); if (cmd != NULL) { Tcl_DeleteCommandFromToken(interp, cmd); } return TCL_OK; } /* *---------------------------------------------------------------------- * * DeleteCmd -- * * Cleanup the interp command token so that unloading doesn't try to * re-delete the command (which will crash). * * Results: * None. * * Side effects: * The unload command will not attempt to delete this command. * *---------------------------------------------------------------------- */ static void DeleteCmd( ClientData clientData) { Tcl_Interp *interp = clientData; Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, NULL); } /* *---------------------------------------------------------------------- * * RegistryObjCmd -- * * This function implements the Tcl "registry" command. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int RegistryObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument values. */ { int n = 1; int index, argc; REGSAM mode = 0; const char *errString = NULL; static const char *const subcommands[] = { "broadcast", "delete", "get", "keys", "set", "type", "values", NULL }; enum SubCmdIdx { BroadcastIdx, DeleteIdx, GetIdx, KeysIdx, SetIdx, TypeIdx, ValuesIdx }; static const char *const modes[] = { "-32bit", "-64bit", NULL }; if (objc < 2) { wrongArgs: Tcl_WrongNumArgs(interp, 1, objv, "?-32bit|-64bit? option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetString(objv[n])[0] == '-') { if (Tcl_GetIndexFromObj(interp, objv[n++], modes, "mode", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case 0: /* -32bit */ mode |= KEY_WOW64_32KEY; break; case 1: /* -64bit */ mode |= KEY_WOW64_64KEY; break; } if (objc < 3) { goto wrongArgs; } } if (Tcl_GetIndexFromObj(interp, objv[n++], subcommands, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } argc = (objc - n); switch (index) { case BroadcastIdx: /* broadcast */ if (argc == 1 || argc == 3) { int res = BroadcastValue(interp, argc, objv + n); if (res != TCL_BREAK) { return res; } } errString = "keyName ?-timeout milliseconds?"; break; case DeleteIdx: /* delete */ if (argc == 1) { return DeleteKey(interp, objv[n], mode); } else if (argc == 2) { return DeleteValue(interp, objv[n], objv[n+1], mode); } errString = "keyName ?valueName?"; break; case GetIdx: /* get */ if (argc == 2) { return GetValue(interp, objv[n], objv[n+1], mode); } errString = "keyName valueName"; break; case KeysIdx: /* keys */ if (argc == 1) { return GetKeyNames(interp, objv[n], NULL, mode); } else if (argc == 2) { return GetKeyNames(interp, objv[n], objv[n+1], mode); } errString = "keyName ?pattern?"; break; case SetIdx: /* set */ if (argc == 1) { HKEY key; /* * Create the key and then close it immediately. */ mode |= KEY_ALL_ACCESS; if (OpenKey(interp, objv[n], mode, 1, &key) != TCL_OK) { return TCL_ERROR; } RegCloseKey(key); return TCL_OK; } else if (argc == 3) { return SetValue(interp, objv[n], objv[n+1], objv[n+2], NULL, mode); } else if (argc == 4) { return SetValue(interp, objv[n], objv[n+1], objv[n+2], objv[n+3], mode); } errString = "keyName ?valueName data ?type??"; break; case TypeIdx: /* type */ if (argc == 2) { return GetType(interp, objv[n], objv[n+1], mode); } errString = "keyName valueName"; break; case ValuesIdx: /* values */ if (argc == 1) { return GetValueNames(interp, objv[n], NULL, mode); } else if (argc == 2) { return GetValueNames(interp, objv[n], objv[n+1], mode); } errString = "keyName ?pattern?"; break; } Tcl_WrongNumArgs(interp, (mode ? 3 : 2), objv, errString); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * DeleteKey -- * * This function deletes a registry key. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int DeleteKey( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Name of key to delete. */ REGSAM mode) /* Mode flags to pass. */ { char *tail, *buffer, *hostName, *keyName; const TCHAR *nativeTail; HKEY rootKey, subkey; DWORD result; Tcl_DString buf; REGSAM saveMode = mode; /* * Find the parent of the key being deleted and open it. */ keyName = Tcl_GetString(keyNameObj); buffer = ckalloc(keyNameObj->length + 1); strcpy(buffer, keyName); if (ParseKeyName(interp, buffer, &hostName, &rootKey, &keyName) != TCL_OK) { ckfree(buffer); return TCL_ERROR; } if (*keyName == '\0') { Tcl_SetObjResult(interp, Tcl_NewStringObj("bad key: cannot delete root keys", -1)); Tcl_SetErrorCode(interp, "WIN_REG", "DEL_ROOT_KEY", NULL); ckfree(buffer); return TCL_ERROR; } tail = strrchr(keyName, '\\'); if (tail) { *tail++ = '\0'; } else { tail = keyName; keyName = NULL; } mode |= KEY_ENUMERATE_SUB_KEYS | DELETE; result = OpenSubKey(hostName, rootKey, keyName, mode, 0, &subkey); if (result != ERROR_SUCCESS) { ckfree(buffer); if (result == ERROR_FILE_NOT_FOUND) { return TCL_OK; } Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to delete key: ", -1)); AppendSystemError(interp, result); return TCL_ERROR; } /* * Now we recursively delete the key and everything below it. */ nativeTail = Tcl_WinUtfToTChar(tail, -1, &buf); result = RecursiveDeleteKey(subkey, nativeTail, saveMode); Tcl_DStringFree(&buf); if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to delete key: ", -1)); AppendSystemError(interp, result); result = TCL_ERROR; } else { result = TCL_OK; } RegCloseKey(subkey); ckfree(buffer); return result; } /* *---------------------------------------------------------------------- * * DeleteValue -- * * This function deletes a value from a registry key. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int DeleteValue( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Name of key. */ Tcl_Obj *valueNameObj, /* Name of value to delete. */ REGSAM mode) /* Mode flags to pass. */ { HKEY key; char *valueName; size_t length; DWORD result; Tcl_DString ds; /* * Attempt to open the key for deletion. */ mode |= KEY_SET_VALUE; if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) { return TCL_ERROR; } valueName = Tcl_GetString(valueNameObj); length = valueNameObj->length; Tcl_WinUtfToTChar(valueName, length, &ds); result = RegDeleteValue(key, (const TCHAR *)Tcl_DStringValue(&ds)); Tcl_DStringFree(&ds); if (result != ERROR_SUCCESS) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unable to delete value \"%s\" from key \"%s\": ", Tcl_GetString(valueNameObj), Tcl_GetString(keyNameObj))); AppendSystemError(interp, result); result = TCL_ERROR; } else { result = TCL_OK; } RegCloseKey(key); return result; } /* *---------------------------------------------------------------------- * * GetKeyNames -- * * This function enumerates the subkeys of a given key. If the optional * pattern is supplied, then only keys that match the pattern will be * returned. * * Results: * Returns the list of subkeys in the result object of the interpreter, * or an error message on failure. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int GetKeyNames( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Key to enumerate. */ Tcl_Obj *patternObj, /* Optional match pattern. */ REGSAM mode) /* Mode flags to pass. */ { const char *pattern; /* Pattern being matched against subkeys */ HKEY key; /* Handle to the key being examined */ TCHAR buffer[MAX_KEY_LENGTH]; /* Buffer to hold the subkey name */ DWORD bufSize; /* Size of the buffer */ DWORD index; /* Position of the current subkey */ char *name; /* Subkey name */ Tcl_Obj *resultPtr; /* List of subkeys being accumulated */ int result = TCL_OK; /* Return value from this command */ Tcl_DString ds; /* Buffer to translate subkey name to UTF-8 */ if (patternObj) { pattern = Tcl_GetString(patternObj); } else { pattern = NULL; } /* * Attempt to open the key for enumeration. */ mode |= KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS; if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) { return TCL_ERROR; } /* * Enumerate the subkeys. */ resultPtr = Tcl_NewObj(); for (index = 0;; ++index) { bufSize = MAX_KEY_LENGTH; result = RegEnumKeyEx(key, index, buffer, &bufSize, NULL, NULL, NULL, NULL); if (result != ERROR_SUCCESS) { if (result == ERROR_NO_MORE_ITEMS) { result = TCL_OK; } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unable to enumerate subkeys of \"%s\": ", Tcl_GetString(keyNameObj))); AppendSystemError(interp, result); result = TCL_ERROR; } break; } Tcl_WinTCharToUtf(buffer, bufSize * sizeof(TCHAR), &ds); name = Tcl_DStringValue(&ds); if (pattern && !Tcl_StringMatch(name, pattern)) { Tcl_DStringFree(&ds); continue; } result = Tcl_ListObjAppendElement(interp, resultPtr, Tcl_NewStringObj(name, Tcl_DStringLength(&ds))); Tcl_DStringFree(&ds); if (result != TCL_OK) { break; } } if (result == TCL_OK) { Tcl_SetObjResult(interp, resultPtr); } else { Tcl_DecrRefCount(resultPtr); /* BUGFIX: Don't leak on failure. */ } RegCloseKey(key); return result; } /* *---------------------------------------------------------------------- * * GetType -- * * This function gets the type of a given registry value and places it in * the interpreter result. * * Results: * Returns a normal Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int GetType( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Name of key. */ Tcl_Obj *valueNameObj, /* Name of value to get. */ REGSAM mode) /* Mode flags to pass. */ { HKEY key; DWORD result, type; Tcl_DString ds; const char *valueName; const TCHAR *nativeValue; size_t length; /* * Attempt to open the key for reading. */ mode |= KEY_QUERY_VALUE; if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) { return TCL_ERROR; } /* * Get the type of the value. */ valueName = Tcl_GetString(valueNameObj); length = valueNameObj->length; nativeValue = Tcl_WinUtfToTChar(valueName, length, &ds); result = RegQueryValueEx(key, nativeValue, NULL, &type, NULL, NULL); Tcl_DStringFree(&ds); RegCloseKey(key); if (result != ERROR_SUCCESS) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unable to get type of value \"%s\" from key \"%s\": ", Tcl_GetString(valueNameObj), Tcl_GetString(keyNameObj))); AppendSystemError(interp, result); return TCL_ERROR; } /* * Set the type into the result. Watch out for unknown types. If we don't * know about the type, just use the numeric value. */ if (type > lastType) { Tcl_SetObjResult(interp, Tcl_NewIntObj((int) type)); } else { Tcl_SetObjResult(interp, Tcl_NewStringObj(typeNames[type], -1)); } return TCL_OK; } /* *---------------------------------------------------------------------- * * GetValue -- * * This function gets the contents of a registry value and places a list * containing the data and the type in the interpreter result. * * Results: * Returns a normal Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int GetValue( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Name of key. */ Tcl_Obj *valueNameObj, /* Name of value to get. */ REGSAM mode) /* Mode flags to pass. */ { HKEY key; const char *valueName; const TCHAR *nativeValue; DWORD result, length, type; Tcl_DString data, buf; size_t nameLen; /* * Attempt to open the key for reading. */ mode |= KEY_QUERY_VALUE; if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) { return TCL_ERROR; } /* * Initialize a Dstring to maximum statically allocated size we could get * one more byte by avoiding Tcl_DStringSetLength() and just setting * length to TCL_DSTRING_STATIC_SIZE, but this should be safer if the * implementation of Dstrings changes. * * This allows short values to be read from the registy in one call. * Longer values need a second call with an expanded DString. */ Tcl_DStringInit(&data); Tcl_DStringSetLength(&data, TCL_DSTRING_STATIC_SIZE - 1); length = TCL_DSTRING_STATIC_SIZE/sizeof(TCHAR) - 1; valueName = Tcl_GetString(valueNameObj); nameLen = valueNameObj->length; nativeValue = Tcl_WinUtfToTChar(valueName, nameLen, &buf); result = RegQueryValueEx(key, nativeValue, NULL, &type, (BYTE *) Tcl_DStringValue(&data), &length); while (result == ERROR_MORE_DATA) { /* * The Windows docs say that in this error case, we just need to * expand our buffer and request more data. Required for * HKEY_PERFORMANCE_DATA */ length = Tcl_DStringLength(&data) * (2 / sizeof(TCHAR)); Tcl_DStringSetLength(&data, (int) length * sizeof(TCHAR)); result = RegQueryValueEx(key, nativeValue, NULL, &type, (BYTE *) Tcl_DStringValue(&data), &length); } Tcl_DStringFree(&buf); RegCloseKey(key); if (result != ERROR_SUCCESS) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unable to get value \"%s\" from key \"%s\": ", Tcl_GetString(valueNameObj), Tcl_GetString(keyNameObj))); AppendSystemError(interp, result); Tcl_DStringFree(&data); return TCL_ERROR; } /* * If the data is a 32-bit quantity, store it as an integer object. If it * is a multi-string, store it as a list of strings. For null-terminated * strings, append up the to first null. Otherwise, store it as a binary * string. */ if (type == REG_DWORD || type == REG_DWORD_BIG_ENDIAN) { Tcl_SetObjResult(interp, Tcl_NewIntObj((int) ConvertDWORD(type, *((DWORD *) Tcl_DStringValue(&data))))); } else if (type == REG_MULTI_SZ) { char *p = Tcl_DStringValue(&data); char *end = Tcl_DStringValue(&data) + length; Tcl_Obj *resultPtr = Tcl_NewObj(); /* * Multistrings are stored as an array of null-terminated strings, * terminated by two null characters. Also do a bounds check in case * we get bogus data. */ while ((p < end) && *((Tcl_UniChar *) p) != 0) { Tcl_UniChar *up; Tcl_WinTCharToUtf((TCHAR *) p, -1, &buf); Tcl_ListObjAppendElement(interp, resultPtr, Tcl_NewStringObj(Tcl_DStringValue(&buf), Tcl_DStringLength(&buf))); up = (Tcl_UniChar *) p; while (*up++ != 0) {/* empty body */} p = (char *) up; Tcl_DStringFree(&buf); } Tcl_SetObjResult(interp, resultPtr); } else if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) { Tcl_WinTCharToUtf((TCHAR *) Tcl_DStringValue(&data), -1, &buf); Tcl_DStringResult(interp, &buf); } else { /* * Save binary data as a byte array. */ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj( (BYTE *) Tcl_DStringValue(&data), (int) length)); } Tcl_DStringFree(&data); return result; } /* *---------------------------------------------------------------------- * * GetValueNames -- * * This function enumerates the values of the a given key. If the * optional pattern is supplied, then only value names that match the * pattern will be returned. * * Results: * Returns the list of value names in the result object of the * interpreter, or an error message on failure. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int GetValueNames( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Key to enumerate. */ Tcl_Obj *patternObj, /* Optional match pattern. */ REGSAM mode) /* Mode flags to pass. */ { HKEY key; Tcl_Obj *resultPtr; DWORD index, size, result; Tcl_DString buffer, ds; const char *pattern, *name; /* * Attempt to open the key for enumeration. */ mode |= KEY_QUERY_VALUE; if (OpenKey(interp, keyNameObj, mode, 0, &key) != TCL_OK) { return TCL_ERROR; } resultPtr = Tcl_NewObj(); Tcl_DStringInit(&buffer); Tcl_DStringSetLength(&buffer, (int) (MAX_KEY_LENGTH * sizeof(TCHAR))); index = 0; result = TCL_OK; if (patternObj) { pattern = Tcl_GetString(patternObj); } else { pattern = NULL; } /* * Enumerate the values under the given subkey until we get an error, * indicating the end of the list. Note that we need to reset size after * each iteration because RegEnumValue smashes the old value. */ size = MAX_KEY_LENGTH; while (RegEnumValue(key,index, (TCHAR *)Tcl_DStringValue(&buffer), &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { size *= sizeof(TCHAR); Tcl_WinTCharToUtf((TCHAR *) Tcl_DStringValue(&buffer), (int) size, &ds); name = Tcl_DStringValue(&ds); if (!pattern || Tcl_StringMatch(name, pattern)) { result = Tcl_ListObjAppendElement(interp, resultPtr, Tcl_NewStringObj(name, Tcl_DStringLength(&ds))); if (result != TCL_OK) { Tcl_DStringFree(&ds); break; } } Tcl_DStringFree(&ds); index++; size = MAX_KEY_LENGTH; } Tcl_SetObjResult(interp, resultPtr); Tcl_DStringFree(&buffer); RegCloseKey(key); return result; } /* *---------------------------------------------------------------------- * * OpenKey -- * * This function opens the specified key. This function is a simple * wrapper around ParseKeyName and OpenSubKey. * * Results: * Returns the opened key in the keyPtr argument and a Tcl result code. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int OpenKey( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Key to open. */ REGSAM mode, /* Access mode. */ int flags, /* 0 or REG_CREATE. */ HKEY *keyPtr) /* Returned HKEY. */ { char *keyName, *buffer, *hostName; size_t length; HKEY rootKey; DWORD result; keyName = Tcl_GetString(keyNameObj); length = keyNameObj->length; buffer = ckalloc(length + 1); strcpy(buffer, keyName); result = ParseKeyName(interp, buffer, &hostName, &rootKey, &keyName); if (result == TCL_OK) { result = OpenSubKey(hostName, rootKey, keyName, mode, flags, keyPtr); if (result != ERROR_SUCCESS) { Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to open key: ", -1)); AppendSystemError(interp, result); result = TCL_ERROR; } else { result = TCL_OK; } } ckfree(buffer); return result; } /* *---------------------------------------------------------------------- * * OpenSubKey -- * * This function opens a given subkey of a root key on the specified * host. * * Results: * Returns the opened key in the keyPtr and a Windows error code as the * return value. * * Side effects: * None. * *---------------------------------------------------------------------- */ static DWORD OpenSubKey( char *hostName, /* Host to access, or NULL for local. */ HKEY rootKey, /* Root registry key. */ char *keyName, /* Subkey name. */ REGSAM mode, /* Access mode. */ int flags, /* 0 or REG_CREATE. */ HKEY *keyPtr) /* Returned HKEY. */ { DWORD result; Tcl_DString buf; /* * Attempt to open the root key on a remote host if necessary. */ if (hostName) { hostName = (char *) Tcl_WinUtfToTChar(hostName, -1, &buf); result = RegConnectRegistry((TCHAR *)hostName, rootKey, &rootKey); Tcl_DStringFree(&buf); if (result != ERROR_SUCCESS) { return result; } } /* * Now open the specified key with the requested permissions. Note that * this key must be closed by the caller. */ keyName = (char *) Tcl_WinUtfToTChar(keyName, -1, &buf); if (flags & REG_CREATE) { DWORD create; result = RegCreateKeyEx(rootKey, (TCHAR *)keyName, 0, NULL, REG_OPTION_NON_VOLATILE, mode, NULL, keyPtr, &create); } else if (rootKey == HKEY_PERFORMANCE_DATA) { /* * Here we fudge it for this special root key. See MSDN for more info * on HKEY_PERFORMANCE_DATA and the peculiarities surrounding it. */ *keyPtr = HKEY_PERFORMANCE_DATA; result = ERROR_SUCCESS; } else { result = RegOpenKeyEx(rootKey, (TCHAR *)keyName, 0, mode, keyPtr); } Tcl_DStringFree(&buf); /* * Be sure to close the root key since we are done with it now. */ if (hostName) { RegCloseKey(rootKey); } return result; } /* *---------------------------------------------------------------------- * * ParseKeyName -- * * This function parses a key name into the host, root, and subkey parts. * * Results: * The pointers to the start of the host and subkey names are returned in * the hostNamePtr and keyNamePtr variables. The specified root HKEY is * returned in rootKeyPtr. Returns a standard Tcl result. * * Side effects: * Modifies the name string by inserting nulls. * *---------------------------------------------------------------------- */ static int ParseKeyName( Tcl_Interp *interp, /* Current interpreter. */ char *name, char **hostNamePtr, HKEY *rootKeyPtr, char **keyNamePtr) { char *rootName; int result, index; Tcl_Obj *rootObj; /* * Split the key into host and root portions. */ *hostNamePtr = *keyNamePtr = rootName = NULL; if (name[0] == '\\') { if (name[1] == '\\') { *hostNamePtr = name; for (rootName = name+2; *rootName != '\0'; rootName++) { if (*rootName == '\\') { *rootName++ = '\0'; break; } } } } else { rootName = name; } if (!rootName) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad key \"%s\": must start with a valid root", name)); Tcl_SetErrorCode(interp, "WIN_REG", "NO_ROOT_KEY", NULL); return TCL_ERROR; } /* * Split the root into root and subkey portions. */ for (*keyNamePtr = rootName; **keyNamePtr != '\0'; (*keyNamePtr)++) { if (**keyNamePtr == '\\') { **keyNamePtr = '\0'; (*keyNamePtr)++; break; } } /* * Look for a matching root name. */ rootObj = Tcl_NewStringObj(rootName, -1); result = Tcl_GetIndexFromObj(interp, rootObj, rootKeyNames, "root name", TCL_EXACT, &index); Tcl_DecrRefCount(rootObj); if (result != TCL_OK) { return TCL_ERROR; } *rootKeyPtr = rootKeys[index]; return TCL_OK; } /* *---------------------------------------------------------------------- * * RecursiveDeleteKey -- * * This function recursively deletes all the keys below a starting key. * Although Windows 95 does this automatically, we still need to do this * for Windows NT. * * Results: * Returns a Windows error code. * * Side effects: * Deletes all of the keys and values below the given key. * *---------------------------------------------------------------------- */ static DWORD RecursiveDeleteKey( HKEY startKey, /* Parent of key to be deleted. */ const TCHAR *keyName, /* Name of key to be deleted in external * encoding, not UTF. */ REGSAM mode) /* Mode flags to pass. */ { DWORD result, size; Tcl_DString subkey; HKEY hKey; REGSAM saveMode = mode; static int checkExProc = 0; static FARPROC regDeleteKeyExProc = NULL; /* * Do not allow NULL or empty key name. */ if (!keyName || *keyName == '\0') { return ERROR_BADKEY; } mode |= KEY_ENUMERATE_SUB_KEYS | DELETE | KEY_QUERY_VALUE; result = RegOpenKeyEx(startKey, keyName, 0, mode, &hKey); if (result != ERROR_SUCCESS) { return result; } Tcl_DStringInit(&subkey); Tcl_DStringSetLength(&subkey, (int) (MAX_KEY_LENGTH * sizeof(TCHAR))); mode = saveMode; while (result == ERROR_SUCCESS) { /* * Always get index 0 because key deletion changes ordering. */ size = MAX_KEY_LENGTH; result = RegEnumKeyEx(hKey, 0, (TCHAR *)Tcl_DStringValue(&subkey), &size, NULL, NULL, NULL, NULL); if (result == ERROR_NO_MORE_ITEMS) { /* * RegDeleteKeyEx doesn't exist on non-64bit XP platforms, so we * can't compile with it in. We need to check for it at runtime * and use it if we find it. */ if (mode && !checkExProc) { HINSTANCE dllH; checkExProc = 1; dllH = LoadLibrary(TEXT("advapi32.dll")); if (dllH) { regDeleteKeyExProc = (FARPROC) GetProcAddress(dllH, "RegDeleteKeyExW"); } } if (mode && regDeleteKeyExProc) { result = regDeleteKeyExProc(startKey, keyName, mode, 0); } else { result = RegDeleteKey(startKey, keyName); } break; } else if (result == ERROR_SUCCESS) { result = RecursiveDeleteKey(hKey, (const TCHAR *) Tcl_DStringValue(&subkey), mode); } } Tcl_DStringFree(&subkey); RegCloseKey(hKey); return result; } /* *---------------------------------------------------------------------- * * SetValue -- * * This function sets the contents of a registry value. If the key or * value does not exist, it will be created. If it does exist, then the * data and type will be replaced. * * Results: * Returns a normal Tcl result. * * Side effects: * May create new keys or values. * *---------------------------------------------------------------------- */ static int SetValue( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Name of key. */ Tcl_Obj *valueNameObj, /* Name of value to set. */ Tcl_Obj *dataObj, /* Data to be written. */ Tcl_Obj *typeObj, /* Type of data to be written. */ REGSAM mode) /* Mode flags to pass. */ { int type; size_t length; DWORD result; HKEY key; const char *valueName; Tcl_DString nameBuf; if (typeObj == NULL) { type = REG_SZ; } else if (Tcl_GetIndexFromObj(interp, typeObj, typeNames, "type", 0, (int *) &type) != TCL_OK) { if (Tcl_GetIntFromObj(NULL, typeObj, (int *) &type) != TCL_OK) { return TCL_ERROR; } Tcl_ResetResult(interp); } mode |= KEY_ALL_ACCESS; if (OpenKey(interp, keyNameObj, mode, 1, &key) != TCL_OK) { return TCL_ERROR; } valueName = Tcl_GetString(valueNameObj); length = valueNameObj->length; valueName = (char *) Tcl_WinUtfToTChar(valueName, length, &nameBuf); if (type == REG_DWORD || type == REG_DWORD_BIG_ENDIAN) { int value; if (Tcl_GetIntFromObj(interp, dataObj, &value) != TCL_OK) { RegCloseKey(key); Tcl_DStringFree(&nameBuf); return TCL_ERROR; } value = ConvertDWORD((DWORD) type, (DWORD) value); result = RegSetValueEx(key, (TCHAR *) valueName, 0, (DWORD) type, (BYTE *) &value, sizeof(DWORD)); } else if (type == REG_MULTI_SZ) { Tcl_DString data, buf; int objc, i; Tcl_Obj **objv; if (Tcl_ListObjGetElements(interp, dataObj, &objc, &objv) != TCL_OK) { RegCloseKey(key); Tcl_DStringFree(&nameBuf); return TCL_ERROR; } /* * Append the elements as null terminated strings. Note that we must * not assume the length of the string in case there are embedded * nulls, which aren't allowed in REG_MULTI_SZ values. */ Tcl_DStringInit(&data); for (i = 0; i < objc; i++) { const char *bytes = Tcl_GetString(objv[i]); length = objv[i]->length; Tcl_DStringAppend(&data, bytes, length); /* * Add a null character to separate this value from the next. */ Tcl_DStringAppend(&data, "", 1); /* NUL-terminated string */ } Tcl_WinUtfToTChar(Tcl_DStringValue(&data), Tcl_DStringLength(&data)+1, &buf); result = RegSetValueEx(key, (TCHAR *) valueName, 0, (DWORD) type, (BYTE *) Tcl_DStringValue(&buf), (DWORD) Tcl_DStringLength(&buf)); Tcl_DStringFree(&data); Tcl_DStringFree(&buf); } else if (type == REG_SZ || type == REG_EXPAND_SZ) { Tcl_DString buf; const char *data = Tcl_GetString(dataObj); length = dataObj->length; data = (char *) Tcl_WinUtfToTChar(data, length, &buf); /* * Include the null in the length, padding if needed for Unicode. */ Tcl_DStringSetLength(&buf, Tcl_DStringLength(&buf)+1); length = Tcl_DStringLength(&buf) + 1; result = RegSetValueEx(key, (TCHAR *) valueName, 0, (DWORD) type, (BYTE *) data, (DWORD) length); Tcl_DStringFree(&buf); } else { BYTE *data; int bytelength; /* * Store binary data in the registry. */ data = (BYTE *) Tcl_GetByteArrayFromObj(dataObj, &bytelength); result = RegSetValueEx(key, (TCHAR *) valueName, 0, (DWORD) type, data, (DWORD) bytelength); } Tcl_DStringFree(&nameBuf); RegCloseKey(key); if (result != ERROR_SUCCESS) { Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to set value: ", -1)); AppendSystemError(interp, result); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * BroadcastValue -- * * This function broadcasts a WM_SETTINGCHANGE message to indicate to * other programs that we have changed the contents of a registry value. * * Results: * Returns a normal Tcl result. * * Side effects: * Will cause other programs to reload their system settings. * *---------------------------------------------------------------------- */ static int BroadcastValue( Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument values. */ { LRESULT result; DWORD_PTR sendResult; int timeout = 3000; size_t len; int unilen; const char *str; Tcl_Obj *objPtr; if (objc == 3) { str = Tcl_GetString(objv[1]); len = objv[1]->length; if ((len < 2) || (*str != '-') || strncmp(str, "-timeout", len)) { return TCL_BREAK; } if (Tcl_GetIntFromObj(interp, objv[2], &timeout) != TCL_OK) { return TCL_ERROR; } } str = (char*)Tcl_GetUnicodeFromObj(objv[0], &unilen); if (unilen == 0) { str = NULL; } /* * Use the ignore the result. */ result = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM) 0, (LPARAM) str, SMTO_ABORTIFHUNG, (UINT) timeout, &sendResult); objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewLongObj((long) result)); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewLongObj((long) sendResult)); Tcl_SetObjResult(interp, objPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * AppendSystemError -- * * This routine formats a Windows system error message and places it into * the interpreter result. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void AppendSystemError( Tcl_Interp *interp, /* Current interpreter. */ DWORD error) /* Result code from error. */ { int length; TCHAR *tMsgPtr, **tMsgPtrPtr = &tMsgPtr; const char *msg; char id[TCL_INTEGER_SPACE], msgBuf[24 + TCL_INTEGER_SPACE]; Tcl_DString ds; Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); if (Tcl_IsShared(resultPtr)) { resultPtr = Tcl_DuplicateObj(resultPtr); } length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (TCHAR *) tMsgPtrPtr, 0, NULL); if (length == 0) { sprintf(msgBuf, "unknown error: %ld", error); msg = msgBuf; } else { char *msgPtr; Tcl_WinTCharToUtf(tMsgPtr, -1, &ds); LocalFree(tMsgPtr); msgPtr = Tcl_DStringValue(&ds); length = Tcl_DStringLength(&ds); /* * Trim the trailing CR/LF from the system message. */ if (msgPtr[length-1] == '\n') { --length; } if (msgPtr[length-1] == '\r') { --length; } msgPtr[length] = 0; msg = msgPtr; } sprintf(id, "%ld", error); Tcl_SetErrorCode(interp, "WINDOWS", id, msg, NULL); Tcl_AppendToObj(resultPtr, msg, length); Tcl_SetObjResult(interp, resultPtr); if (length != 0) { Tcl_DStringFree(&ds); } } /* *---------------------------------------------------------------------- * * ConvertDWORD -- * * This function determines whether a DWORD needs to be byte swapped, and * returns the appropriately swapped value. * * Results: * Returns a converted DWORD. * * Side effects: * None. * *---------------------------------------------------------------------- */ static DWORD ConvertDWORD( DWORD type, /* Either REG_DWORD or REG_DWORD_BIG_ENDIAN */ DWORD value) /* The value to be converted. */ { const DWORD order = 1; DWORD localType; /* * Check to see if the low bit is in the first byte. */ localType = (*((const char *) &order) == 1) ? REG_DWORD : REG_DWORD_BIG_ENDIAN; return (type != localType) ? (DWORD) SWAPLONG(value) : value; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/win/aclocal.m40000644000175000017500000000003012665173607014220 0ustar sergeisergeibuiltin(include,tcl.m4) tcl8.6.5/win/tcl.hpj.in0000644000175000017500000000053412663660066014261 0ustar sergeisergei; This file is maintained by HCW. Do not modify this file directly. [OPTIONS] HCW=0 LCID=0x409 0x0 0x0 ;English (United States) REPORT=Yes TITLE=Tcl/Tk Reference Manual CNT=tcl86.cnt COPYRIGHT=Copyright © 2000 Ajuba Solutions HLP=tcl86.hlp [FILES] tcl.rtf [WINDOWS] main="Tcl/Tk Reference Manual",,0 [CONFIG] BrowseButtons() tcl8.6.5/ChangeLog.20050000644000175000017500000043450311555560472013737 0ustar sergeisergei2005-12-30 Kevin B. Kenny * generic/tclStubLib.c: Corrected a typo in "missing Stubs table pointer." 2005-12-27 Kevin B. Kenny * generic/tcl.decls: Destubbed TclTomMathInitializeStubs - it is in * generic/tcl.h: the stub library, not the main shared * generic/tclBasic.c: library. Exported Tcl_InitBignumFromDouble. * generic/tclExecute.c: * generic/tclInt.h: * generic/tclStrToD.c: * generic/tclDecls.h: * generic/tclStubLib.c: * generic/tclStubInit.c: Regenerated. * generic/clock.tcl: Reverted to using the time zone abbreviation and not its name to "stop the bleeding" on [Bug 1386377]. This is *not* a good long-term solution, but there may not be one. * libtommath/bn_mp_sqrt.c: Improved the initial approximation to the square root, roughly doubling the speed of the routine. (This is a local change that needs to be communicated to Tom.) * win/Makefile.in: Corrected a bug where tommath_class.h and tommath_superclass.h were not installed, making it impossible for client code to compile against the tommath stubs. * library/tzdata: Updated to Olson's tzdata2005r. (Latest changes to Daylight Saving Time in Canada, plus redefinition of the Posix-style zones [e.g., EST5EDT] to be locale-independent.) * libtommath: Updated to Tom St.Denis's release 0.37. 2005-12-20 Donal K. Fellows * generic/tclThreadAlloc.c (Tcl_GetMemoryInfo): Format values as longs and not ints, so they are less likely to wrap on 64-bit machines. 2005-12-19 Don Porter * generic/tclCmdMZ.c: Modified [string is double] to use * tests/string.test: TclParseNumber() to parse trailing whitespace. Ensures consistency, and makes it easier to cleanup after invalid internal reps left behind by parsing [Bugs 1360532 1382287]. * generic/tclParseExpr.c: Added TCL_PARSE_NO_WHITESPACE to * generic/tclScan.c: TclParseNumber() calls since [scan] and [expr] * tests/scan.test: parsing don't want spaces in parsed numbers. * generic/tclInt.h: Added TCL_PARSE_NO_WHITESPACE flag to the * generic/tclStrToD.c: TclParseNumber() interface. 2005-12-19 Donal K. Fellows * doc/Tcl.n: Clarify what is going on in variable substitution following thread on comp.lang.tcl. 2005-12-18 Donal K. Fellows * generic/tclCompCmds.c (TclCompileDictCmd): Ensure that we only do an 'endCatch' when there's a preceding 'beginCatch'. [Bug 1382528] Many thanks to Anton Kovalenko for finding this and pointing out that it was a catch stack handling problem! 2005-12-14 Daniel Steffen * generic/tclIOUtil.c: workaround gcc warning "comparison is always * generic/tclTest.c: false due to limited range of data type". * macosx/Tcl.xcode/project.pbxproj: * macosx/Tcl.xcodeproj/project.pbxproj: * unix/Makefile.in: add new tclTomMath* files. * generic/tclBasic.c: replace panic with Tcl_Panic. 2005-12-13 Kevin B. Kenny * generic/tcl.decls: Added changes to export an additional stubs * generic/tclBasic.c: table to represent the 'libtommath' routines * generic/tclDecls.h: that Tcl uses and export them to callers. * generic/tclInt.decls: Reran 'genstubs' * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclIntPlatDecls.h: * generic/tclStubInit.c: * generic/tclStubLib.c: * generic/tclTomMath.decls: * generic/tclTomMath.h: * generic/tclTomMathDecls.h: * generic/tclTomMathInterface.c: * generic/tommath.h: * tools/fix_tommath_h.tcl: * unix/Makefile.in: * win/Makefile.in: * win/makefile.vc: * generic/tclClock.c: Made changes to silence a number of compiler * generic/tclIO.c: warnings when building with mingw. * generic/tclIORChan.c: * generic/tclLink.c: * generic/tclListObj.c: * generic/tclObj.c: * generic/tclParseExpr.c: * generic/tclProc.c: * generic/tclTimer.c: * win/tclWinChan.c: * win/tclWinConsole.c: * win/tclWinDde.c: * win/tclWinFCmd.c: * win/tclWinFile.c: * win/tclWinReg.c: * win/tclWinSock.c: 2005-12-13 Donal K. Fellows * generic/tclExecute.c (TEBC:DICT_FIRST,DICT_DONE): Only decrease the references to the dictionary once the iteration completes. Do this by storing the dict in the iterator context variable. [Bug 1379349] Thanks to Ulrich Ring and Tobias Hippler for finding this. 2005-12-12 Jeff Hobbs * unix/tcl.m4, unix/configure: Fix sh quoting error reported in bash-3.1+ [Bug 1377619] (schafer) 2005-12-12 Kevin B. Kenny * doc/mathfunc.n: Changed two examples from the incorrect 'tcl::math::' to 'tcl::mathfunc::' [Bug 1378818] 2005-12-09 Mo DeJong * win/configure: Regen. * win/tcl.m4 (SC_CONFIG_CFLAGS): Define MACHINE for gcc builds. The lack of a definition of this variable in the manifest file was causing a runtime error in wish built with gcc. 2005-12-09 Donal K. Fellows * tests/lsearch.test (lsearch-10.8..10): If the -start is off the end, * generic/tclCmdIL.c (Tcl_LsearchObjCmd): searching should find nothing at all. [Bug 1374778] 2005-12-08 Jeff Hobbs * win/Makefile.in, win/makefile.vc: Add Win x64 and CE build support * win/tcl.m4, win/configure: CE still requires C code fixes. * generic/tcl.h: use struct __stat64 (not _stat64) for MSC_VER >= 1400 (i.e. latest Platform SDK). 2005-12-07 Donal K. Fellows * doc/socket.n: Cross-referenced the socket documentation better to the fconfigure documentation on the topic of asynch sockets. * doc/fconfigure.n: Added keyword to documentation of -blocking option so that people looking for "asynch" can find it as well. 2005-12-05 Daniel Steffen * unix/tclUnixPort.h (Darwin): fix incorrect __DARWIN_UNIX03 configure overrides that were originally copied from Darwin CVS (rdar://3693001) 2005-12-05 Kevin B. Kenny * tools/tclZIC.tcl: Updated to reflect changes in calling sequence when GetJulianDateFromEraYearMonthDay moved to C. * library/tzdata: Regenerated from Olson's tzdata2005p.tar.gz - the 'systemv' changes appear not to affect Tcl's processing of the dates. 2005-12-05 Daniel Steffen * unix/configure.in: move check for fts API to configure.in and run it * unix/tcl.m4: on all platforms, since Linux glibc2 and *BSDs also have this; using fts is more efficient than a recursive opendir/readdir. * unix/tclUnixFCmd.c (TraverseUnixTree): add support to fts code for platforms with stat64. * unix/configure: * unix/tclConfig.h.in: regen. 2005-12-05 Jeff Hobbs * unix/configure: Use fts file API on Darwin if available. * unix/tcl.m4: Addresses file delete issues in readdir noted * unix/tclUnixFCmd.c: in [Bug 1034337]. (steffen) Remove redundant stat call for each file in DoCopyFile. (steffen) 2005-12-02 Kevin B. Kenny * generic/tclClock.c: Moved a tiny bit more of [clock format] from run * library/clock.tcl: time to compile time, and fixed a l10n bug in the process. [Bug 1371446]. Also, conditoned the call to SetupTimeZone to speed the common case where TZData($timezone) already exists, and achieved a puny speedup by making ::tcl::clock::getenv not throw errors. * unix/Makefile.in: Made some changes to support a 'make' command that is present on some antiquated versions of Solaris. 2005-12-01 Kevin B. Kenny * library/clock.tcl: Continued rationalizing the code, eliminating numerous redundant [mc] calls. Added another time boost by precompiling a [::format] command to do the bulk of the work of [clock format]. 2005-12-01 Donal K. Fellows * unix/Makefile.in: Add remaining dependency info. While automated maintenance of this information would be good, having it at all is much better than a poke in the eye with a sharp stick... 2005-12-01 Daniel Steffen * generic/tclClock.c: fix warning. * unix/tcl.m4 (Darwin): fix error when MACOSX_DEPLOYMENT_TARGET unset * unix/configure: regen. 2005-11-30 Donal K. Fellows * unix/Makefile.in: Add dependency information relating to tclCompile.h since when the list of opcodes changes it is usually useful to rebuild everything that depends on it (but which is nonetheless a small fraction of the total set of Tcl source files). ***POTENTIAL INCOMPATIBILITY*** for bytecode savers/loaders. See below * generic/tclCompCmds.c (TclCompileSwitchCmd): Arrange for very simple [switch] invokations to be compiled into hash lookups into jump tables; only a very specific kind of [switch] can be safely compiled this way, but that happens to be the most common kind. This makes around 5-10% difference to the speed of execution of clock.test. * generic/tclExecute.c (TEBC:INST_JUMP_TABLE): New instruction to allow for jumps to locations looked up in a hashtable. Requires a new AuxData type, tclJumptableInfoType (supported by the functions DupJumptableInfo and FreeJumptableInfo in tclCompCmds.c) so anything that saves bytecode containing this *must* be updated! 2005-11-30 Kevin Kenny * generic/tclClock.c: Fixed a bad refcount in previous commit that led to a corrupted heap. Also silenced a warning that some compilers gave about the excessively long constant for JULIAN_SEC_POSIX_EPOCH. Also fixed a bug where [clock format] would fail in the :localtime zone for times before the Posix Epoch. Thanks to Miguel Sofer for pointing out all of these. Also rationalized the code a little bit by moving parts of [clock scan] into C, eliminating some code that was duplicated in the C and Tcl layers. 2005-11-29 Kevin Kenny * generic/tclBasic.c: Moved a big part of [clock format] down * generic/tclClock.c: to the C level in order to make it go faster. * generic/tclInt.h: Preliminary measurements suggest that it * generic/clock.tcl: more than doubles in speed with this change. 2005-11-29 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LsearchObjCmd): Allow [lsearch -regexp] to process REs that contain backreferences. This expensive mode of operation is only used if the RE would otherwise cause a compilation failure. [Bug 1366683] 2005-11-28 Kevin Kenny * tools/tclZIC.tcl (convertTimeOfDay): Corrected a typo that caused wrong DST transitions in any time zone where the transition is specified as local Standard Time (as opposed to wall-clock or UTC). (Also updated the code to be bignum-safe.) * tests/clock.test (clock-51.1): Added regression test for the above. * library/tzdata: Updated to Olson's 'tzdata2005o' (changes for Cuba, Nicaragua, Jordan, and Georgia) and regenerated. Thanks to Paul Mackerras for reporting this problem. 2005-11-27 Daniel Steffen * unix/tcl.m4 (Darwin): add 64bit support, check for Tiger copyfile(), add CFLAGS to SHLIB_LD to support passing -isysroot in env(CFLAGS) to configure (flag can't be present twice, so can't be in both CFLAGS and LDFLAGS during configure), don't use -prebind when deploying on 10.4, define TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING (rdar://3171542). (SC_ENABLE_LANGINFO, SC_TIME_HANDLER): add/fix caching, fix obsolete autoconf macros. Sync with tk/unix/tcl.m4. * unix/configure.in: fix obsolete autoconf macros, sync gratuitous formatting/ordering differences with tk/unix/configure.in. * unix/Makefile.in: add CFLAGS to tclsh/tcltest link to make executable linking the same as during configure (needed to avoid losing any linker relevant flags in CFLAGS, in particular flags that cannot be in LDFLAGS). Avoid concurrent linking of tclsh and compiling of tclTestInit.o or xtTestInit.o during parallel make. (checkstubs, checkdoc, checkexports): dependency and Darwin fixes (dist): add new macosx files. * unix/tclLoadDyld.c (TclpDlopen): use NSADDIMAGE_OPTION_WITH_SEARCHING on second NSAddImage only. [Bug 1204237] (TclGuessPackageName): should not be MODULE_SCOPE. (TclpLoadMemory): ppc64 and endian (i386) fixes, add support for loading universal (fat) bundles from memory. * unix/tclUnixFCmd.c: * macosx/tclMacOSXFCmd.c: ppc64 and endian (i386) fixes. (TclMacOSXCopyFileAttributes): add support for new Tiger copyfile() API to enable copying of xattrs & ACLs by [file copy]. * generic/tcl.h: add Darwin specifc configure overrides for TCL_WIDE defines to support fat compiles of ppc and ppc64 at the same time, (replaces Darwin CVS fix by emoy, rdar://3693001). add/correct location of version numbers in macosx files. * generic/tclInt.h: clarify fat compile comment. * unix/tclUnixPort.h: add Darwin specifc configure overrides to support fat compiles, where configure runs only once for multiple architectures (replaces Darwin CVS fix by emoy, rdar://3693001). * macosx/tclMacOSXBundle.c: * macosx/tclMacOSXNotify.c: * unix/tclUnixNotfy.c: * unix/tclUnixPort.h: fix #include order to support compile time override of HAVE_COREFOUNDATION in tclUnixPort.h when building for ppc64 * macosx/Tcl.pbproj/default.pbxuser (new file): * macosx/Tcl.pbproj/jingham.pbxuser: * macosx/Tcl.pbproj/project.pbxproj: * macosx/Tcl.xcode/default.pbxuser (new file): * macosx/Tcl.xcode/project.pbxproj (new file): * macosx/Tcl.xcodeproj/default.pbxuser (new file): * macosx/Tcl.xcodeproj/project.pbxproj (new file): new/updated projects for Xcode 2.2 on 10.4, Xcode 1.5 on 10.3 & ProjectBuilder on 10.2, with native tcltest targets and support for universal (fat) compiles. * macosx/README: clarification/cleanup, document new Xcode projects and universal (fat) builds via CFLAGS (i.e. all of ppc ppc64 i386 at once). * unix/Makefile.in: * unix/aclocal.m4: * unix/configure.in: * unix/dltest/Makefile.in: * macosx/configure.ac (new file): add support for inclusion of unix/configure.in by macosx/configure.ac, allows generation of a config headers enabled configure script in macosx (required by Xcode projects). * macosx/GNUmakefile: rename from Makefile to avoid overwriting by configure run in tcl/macosx, add support for reusing configure cache, build target fixes, remove GENERIC_FLAGS override now handled by tcl.m4. * generic/tcl.decls: add Tcl_Main declaration as comment to avoid 'checkstubs' target complaining about it missing from stubs. * generic/regex.h: * generic/tclDate.c: * generic/tclEnv.c: * generic/tclGetDate.y: * generic/tclIOUtil.c: * generic/tclObj.c: * generic/tclStubInit.c: * generic/tclStubLib.c: * generic/tclPathObj.c: * generic/tclThreadAlloc.c: * generic/tclThreadStorage.c: * generic/tclTrace.c: * generic/tclVar.c: * generic/tommath.h: * tools/fix_tommath_h.tcl: * unix/tclUnixFCmd.c: ensure externally visible symbols not contained in stubs table are declared as MODULE_SCOPE (or as static if not used outside of own source file). These changes allow 'make checkstubs' to complete without error on Darwin with gcc 4. * generic/rege_dfa.c (getvacant): * generic/regexec.c (cfind): * generic/tclCompExpr.c (CompileSubExpr): * generic/tclNamesp.c (NamespaceEnsembleCmd): * unix/tclUnixChan.c (TclUnixWaitForFile): initialise variables to silence gcc 4 warnings. * generic/tclExecute.c (TclExecuteByteCode): fix unused variable warning when NO_WIDE_TYPE is defined. * generic/regguts.h: only #define NDEBUG if not already #defined. * unix/tclUnixNotfy.c: * macosx/tclMacOSXNotify.c: sync whitespace & comments. * unix/tclUnixPort.h: * win/tclWinPort.h: remove declaration of obsolete&unused TclpMutex API. * unix/configure: * unix/tclConfig.h.in: regen. 2005-11-21 Andreas Kupries * unix/Makefile.in (install-libraries): Updated Makefile to new * win/Makefile.in (install-libraries): version of the http package. This fixes the ifneeded/provide mismatch reported when trying to require http. Should we maybe try to automatically extract the version number from the http code to prevent future breakage ? This follows the update of the version number by dgp on Nov 15 (No entry found in the ChangeLog). 2005-11-20 Joe English * generic/tclStubLib.c: Don't set tclStubsPtr to 0 when Tcl_PkgRequireEx() fails [Fix for [Bug 1091431] "Tcl_InitStubs failure crashes wish"] 2005-11-18 Miguel Sofer * tests/trace.test (trace-34.5): [Bug 1047286], added a second test illustrating the role of "ns in callStack" in the ns's visibility during deletion traces. 2005-11-18 Kevin B. Kenny * doc/clock.n: Restored several missing lines near the %w format group so that %w and %W are documented with their actual behaviour. [Bug 1359183] 2005-11-18 Jeff Hobbs * generic/tclIO.c (TclFinalizeIOSubsystem): preserve statePtr until we retrieve the next statePtr from it. 2005-11-18 Miguel Sofer * generic/tclObj.c (GetBignumFromObj): replace NULL with tclEmptyStringRep to stop memcpy from complaining in a debug build (the corresponding branch is eliminated by the optimiser otherwise). 2005-11-18 Andreas Kupries * generic/tclIO.c (TclFinalizeIOSubsystem): Applied Pat Thoyts' patch for [Bug 1359094]. This moves the retrieval of the next channel state to the end of the loop, as the called closeproc may close other channels, i.e. modify the list we are iterating, invalidating any pointer retrieved earlier. 2005-11-18 Don Porter * generic/tclListObj.c: Restored the SetListFromAny routine to the * generic/tclObj.c: "list" Tcl_ObjType, and restored the Tcl_RegisterObjType() call for "list". This addresses the needs of some "bridge" extensions to examine whether the Tcl_ObjType of a Tcl_Obj is that of the "list" Tcl_ObjType. 2005-11-18 Donal K. Fellows * library/http/http.tcl (http::geturl): Improved syntactic validation of URLs, and better error messages in some cases. [Bug 1358369] 2005-11-17 Miguel Sofer * tests/namespace.test: fix comment 2005-11-14 Don Porter * generic/tclStrToD.c: More data in the "can't happen" Tcl_Panic to aid debugging. * generic/tclBasic.c (CallCommandTraces): Save/restore the interp result during traces to fix [Bug 1355342]. 2005-11-13 Miguel Sofer * generic/tclInt.h: * generic/tclNamesp.c: * tests/namespace.test: fix for [Bug 1354540] and [Bug 1355942]. The new tests 7.3-6 and the modified 51.13 fail due to the unrelated [Bug 1355342] * tests/trace.test: added tests 20.13-16 for [Bug 1355342] 2005-11-12 Miguel Sofer * generic/tclBasic.c (Tcl_DeleteCommandFromToken): * generic/tclObj.c (Tcl_GetCommandFromObj): more partial fixes for [Bug 1354540] - making sure that cached references to a command being deleted cannot be made reusable by a delete trace. 2005-11-12 Donal K. Fellows * generic/tclNamesp.c (Tcl_FindCommand): Do not find commands in dead namespaces on the path. Partial fix for [Bug 1354540]. 2005-11-11 Don Porter * generic/tclInt.h: Revised TclParseNumber interface to enable * generic/tclScan.c: revision to the [scan] command implementation * generic/tclStrToD.c: to permit tests scan-4.44,55 to pass again. [Bug 1348067]. 2005-11-11 Miguel Sofer * generic/tclBasic.c (Tcl_DeleteCommandFromToken): * generic/tclObj.c (Tcl_GetCommandFromObj): bump the cmd epoch early to insure that cached references to this command are invalidated. Partial fix for [Bug 1352734] - at least insures that namespace-51.13 does not cause a panic. The test is still marked as knownbug, pending resolution of what is actually the correct return value ([Bug 1354540]) 2005-11-09 Kevin B. Kenny * generic/tclTimer.c: Changed [after] so that it behaves correctly * tests/timer.test: with negative arguments [Bug 1350293] and arguments that overflow a 32-bit word. [Bug 1350291] 2005-11-08 Don Porter * tests/compile.test: Updated tests with changed behavior * tests/execute.test: due to addition of bignums. * tests/expr-old.test: * tests/expr.test: * tests/parseExpr.test: * tests/platform.test: * tests/string.test: 2005-11-08 Jeff Hobbs * unix/tclUnixFCmd.c (MAX_READDIR_UNLINK_THRESHOLD): reduce to 130 based on errors seen on OS X 10.3 with lots of links in a dir. [Bug 1034337 followup] 2005-11-09 Donal K. Fellows * unix/Makefile.in (gdb-test): Added a new target to make it easier to run the test suite inside a debugger. 2005-11-08 Don Porter * tests/compExpr-old.test: Updated tests with changed behavior due to addition of bignums. * tests/expr.test: Portable tests expr-46.13-18 [Bug 1341368] * generic/tclPkg.c: Corrected inconsistencies in the value returned * tests/pkg.test: by Tcl_PkgRequire(Ex) so that the returned values will always agree with what is stored in the package database. This way repeated calls to Tcl_PkgRequire(Ex) have the same results. Thanks to Hemang Lavana. [Bug 1162286]. 2005-11-08 Donal K. Fellows * generic/tclTrace.c (TraceVarEx): Factor out heart of Tcl_TraceVar2 (TclTraceVariableObjCmd,TraceVarProc): Use the new internal API to arrange for the clientData to be cleaned up at the same time as the rest of the main trace record. This simplifies the code a bit at the same time. 2005-11-07 Miguel Sofer * tests/trace.test (trace-13.2-4): added tests to detect leak, see [Bug 1348775]. The recently added trace-8.9 test is now 13.4. 2005-11-07 Donal K. Fellows * tests/dict.test (dict-19.2): arrange for the stress testing code to only stress test the dict code and not the trace code as well. [Bug 1342858] 2005-11-05 Miguel Sofer * tests/trace.test (trace-8.9): added test to detect leak, see [Bug 1348775]. 2005-11-04 Pat Thoyts * win/tclWinPort.h: Applied [Patch 1267871] by Matt Newman for * win/tclWinPipe.c: extended error code support on Windows. * tests/exec.test: Tests for extended error codes. * generic/tclPipe.c: Permit long codes (platform macros permitting). 2005-11-04 Miguel Sofer * generic/tclBinary.c: * generic/tclCmdAH.c: * generic/tclCmdIL.c: * generic/tclCmdMZ.c: * generic/tclDictObj.c: * generic/tclExecute.c: * generic/tclIOCmd.c: * generic/tclLink.c: * generic/tclTest.c: * generic/tclVar.c: fix for [Bug 1334947]. The functions TclPtrSetVar, Tcl_ObjSetVar2 and Tcl_SetVar2Ex now always consume the newValuePtr argument - i.e., they will free a 0-refCount object if they failed to set the variable. Fixed all callers in the core. 2005-11-04 Kevin Kenny * generic/tclGetDate.y: Added abbreviations for the Korean * library/clock.tcl: timezone. [Patch 1298737] * generic/tclDate.c: Regenerated. * tools/findBadExternals.tcl: Added this script, which locates external symbols that do not begin with 'Tcl' or 'tcl' and hence might be in conflict with other link libraries. Thanks to George Peter Staplin for the idea and the initial version of the script. [Bug 1263012] * unix/Makefile.in: Trimmed a bunch of fat out of the tommath/ directory in 'make dist'. [RFE 1333318] * unix/tcl.m4: Added code to enable [load] on LynxOS. Thanks to heidibr@users.sf.net for the patch. [Bug 1163896]. Removed the last vestiges of GNU dld from the Unix build [RFE 1071992]. * unix/tclLoadDld.c: Removed. * unix/configure: Regenerated. 2005-11-04 Miguel Sofer * generic/tclInt.h: * generic/tclNamesp.c: * generic/tclVar.c: * tests/trace.test: fix for [Bugs 1338280/1337229]; changed to use the same approach as the 8.4 patch in the ticket (i.e., removed the patch committed on 2005-31-10). 2005-11-03 Pat Thoyts * win/tclWin32Dll.c: Applied [Patch 1256872] to provide unicode * win/tclWinConsole.c: support in the console on suitable systems. * win/tclWinInt.h: Patch by Anton Kovalenko 2005-11-02 Pat Thoyts Applied [Patch 1096916] to support building with MSVC 8. * generic/regerror.c: Avoid use of reserved word. * generic/tcl.h: Select the right Tcl_Stat structure * generic/tclDate.c: Casts to handle 64 bit time_t case. * tests/env.test: Include essential envvar on Win32 * win/nmakehlp.c: Handle new return codes. * win/makefile.vc: Use the selected options. * win/rules.vc: Check options are applicable * win/tclWinPort.h: Disable deprecated function warnings * win/tclWinSock.c: Provide default value to avoid warning. * win/tclWinTime.c: Add casts to handle 64bit time_t type. 2005-11-01 Don Porter * generic/tclTrace.c (TclCheckExecutionTraces): Corrected mistaken assumption that all command traces are set at the script level. Report/fix from Jacques H. de Villiers. [Bug 1337941] * tests/unixNotfy.test (1.1,2): Update error message whitespace to match changes in code. * tests/expr-old.test (expr-32.52): Use int(.) to restrict result of left shift to the C long range. * expr.test (expr-46.13): Added test that illustrates shortcoming of [Patch 1340260]. 2005-10-31 Miguel Sofer * generic/tclNamesp.c: fix for [Bugs 1338280/1337229]. Thanks Don. * tests/trace.test: fix duplicate test numbers 2005-10-31 Donal K. Fellows * win/tclWinSerial.c (SerialSetOptionProc): Cleaned up option parsing to produce more informative error messages and separate error and non-error code paths better. * tests/ioCmd.test (iocmd-8-19): Updated. 2005-10-29 Miguel Sofer * generic/tclTrace.c (TraceVarProc): [Bug 1337229], partial fix. Ensure that a second call with TCL_TRACE_DESTROYED does not lead to a second call to Tcl_EventuallyFree(). It is still true that that second call should not happen, so the bug is not completely fixed. * tests/trace.test (test-18.3-4): added tests for [Bug 1337229] and [Bug 1338280]. 2005-10-23 Vince Darley * generic/tclFileName.c: fix to memory leak in glob [Bug 1335006] Obj leak detection and patch by Eric Melbardis. * tests/fCmd.test: * win/tclWinFile.c: where appropriate windows API is available, try to set 'nlink' and 'ino' stat fields (previously they were always 0). [Bug 1325803] 2005-10-22 Miguel Sofer * tests/foreach.test (foreach-8.1): added test for [Bug 1189274] 2005-10-22 Miguel Sofer * generic/tclExecute.c (INST_INCR_*): fixed [Bug 1334570]. Obj leak detection and patch by Eric Melbardis. 2005-10-21 Kevin B. Kenny * generic/tclStrToD.c (RefineApproximation): Plugged a memory leak where two intermediate results were not freed on one return path. [Bug 1334461]. Thanks to Eric Melbardis for the patch. 2005-10-21 Donal K. Fellows * doc/binary.n: Clarify that virtually all code that uses the 'h' format in [binary scan] should be using the 'H' format instead. It is nearly always a bug to use the other! 2005-10-20 Miguel Sofer * generic/tclListObj.c (TclLsetFlat): * tests/lset.test (lset-10.3): fixed handling of unshared lists with shared sublists, [Bug 1333036] reported by neuronstorm. 2005-10-19 Donal K. Fellows * generic/tclIORChan.c (PassReceivedError,PassReceivedErrorInterp): Fix crash caused by passing -1 as the length to TclNewStringObj(). Only Tcl_NewStringObj (the function call, not the macro) handles that sort of thing correctly. This makes ioCmd.test pass again. 2005-10-19 Don Porter * generic/tclClock.c: Removed some dead code. * generic/tclCmdIL.c: * generic/tclCompCmds.c: * generic/tclDictObj.c: * generic/tclExecute.c: * generic/tclLiteral.c: * generic/tclParseExpr.c: * generic/tclScan.c: * generic/tclUtil.c: * generic/tclVar.c: 2005-10-19 Donal K. Fellows * generic/tclIORChan.c: General cleanup, removing checks that are unnecessary due to the general contracts of other functions in the core, converting to using ANSI declarations, etc. Note that nearly the whole file has changed, but it is often just cosmetic. 2005-10-19 Miguel Sofer * generic/tclExecute.c (INST_DICT_APPEND, INST_DICT_LAPPEND): fixed faulty peephole optimisation that can cause crashes, [Bug 1331475] reported by Aric Bills. 2005-10-18 Don Porter * generic/tclExecute.c: Added optimization for I32L64 systems to avoid using bignums to perform int multiplies. The improvement shows up most dramatically in tclbench's matrix.bench. 2005-10-15 Don Porter * generic/tclExecute.c: Restored some optimizations of the INST_INCR_SCALAR1_IMM opcode. 2005-10-14 Zoran Vasiljevic * generic/tclIO.c (Tcl_ClearChannelHandlers): removed change dated 2005-10-04 (see below). Look into [Bug 1323992] for detailed discussion. * generic/tcl.h: Fixed bad definition of CRTEXPORT which should have been CRTIMPORT rather. This broke compilation of generic/tclMain.c and was probably introduced by mistake while applying the fix for [Bug 1256937] below. 2005-10-14 Kevin Kenny * generic/tclExecute.c (TclIncrObj, TclExecuteByteCode): Tidied up a couple of infelicitous do {...} while(0) constructs. 2005-10-14 Pat Thoyts * generic/tcl.h: Fix for [Bug 1256937] - correctly decorate * generic/tclMain.c: imported functions from msvcrt in static builds. 2005-10-13 Donal K. Fellows * tests/format.test: "Forward"-port of test updates relating to [Bug 1284178]. The bug itself was fixed by TIP#237. 2005-10-13 Zoran Vasiljevic * generic/tclIO.c (Tcl_ClearChannelHandlers): temporary ifdef TCL_THREADS changes done to de-activate pending event processing when channel is being closed/cutted. 2005-10-13 Don Porter * generic/tclExecute.c: Removed obsolete use of NO_ERRNO_H. * tools/man2tcl.c: * unix/tcl.m4: * unix/tclConfig.h.in: * win/configure.in: * unix/configure: autoconf-2.59 * win/configure: * compat/tclErrno.h: Removed obsolete file. * generic/tclStrToD.c (TclParseNumber): Missing goto caused crash when parsing "Na". [Bug 1325833] 2005-10-12 Don Porter * generic/tclExecute.c (GetNumberFromObj): Restored some lost optimizations for empty string values. We avoid cost of a call to TclParseNumber just to tell us an empty string isn't a number. 2005-10-12 Donal K. Fellows * generic/tclPathObj.c (SetFsPathFromAny): TclGetString macro must not be combined with post-increment arguments. [Bug 1325099] 2005-10-12 Kevin Kenny * generic/tclExecute.c (Tcl_ExecuteByteCode, TclIncrObj): Several common cases inlined in hopes of gaining a little performance in [incr] 2005-10-10 Miguel Sofer * generic/tclCompCmds.c: New convenience macro CompileTokens(). 2005-10-10 Don Porter * generic/tclExecute.c: Corrections to the NO_WIDE_TYPE build. Also added missing "break" to a switch that broke wide XOR operations. 2005-10-10 Donal K. Fellows * generic/tclInterp.c (DeleteScriptLimitCallback) (SetScriptLimitCallback): Improve the interlocking between the script limit callback record and the hash table of current such records, to prevent crashes in callbacks that create callbacks. (Tcl_LimitSetTime): Reset the correct flag. Problem reported by Nicolas Castagne on comp.lang.tcl 2005-10-10 Miguel Sofer * generic/tclExecute.c: Fixing errors in last commit. (Two commits, the second removes wrong comment). 2005-10-09 Miguel Sofer * generic/tclBasic.c: * generic/tclExecute.c: * generic/tclStrToD.c: * generic/tclStringObj.c: Initialise variables to avoid compiler warnings ([Bug 1320818] among others). 2005-10-08 Don Porter TIP#237 IMPLEMENTATION [kennykb-numerics-branch] Resynchronized with the HEAD; at this checkpoint [-rkennykb-numerics-branch-20051008], the HEAD and kennykb-numerics-branch contain identical code. [kennykb-numerics-branch] Merge updates from HEAD * generic/tclExecute.c: More performance macros and special handling of the wide integer type for performance on 32-bit systems. 2005-10-07 Don Porter [kennykb-numerics-branch] * generic/tclExecute.c: Macro GetNumberFromObj() is version of TclGetNumberFromObj() that saves a function call for common uses. * generic/tclInt.h: Made #undef NO_WIDE_TYPE the default on 32-bit systems. Being able to use 64-bit values without leaping to mp_int should help with performance. * generic/tclObj.c: Bug fixes in the #undef NO_WIDE_TYPE * generic/tclExecute.c: configuration. * generic/tclExecute.c: Improved performance of comparison opcodes and bitwise operations and removed yet more dead code. 2005-10-07 Jeff Hobbs * unix/tclUnixFCmd.c (TraverseUnixTree): Adjust 2004-11-11 change to * tests/fCmd.test (fCmd-20.2): account for NFS special files with a readdir rewind threshold. [Bug 1034337] 2005-10-06 Don Porter [kennykb-numerics-branch] * generic/tclExecute.c: Improved performance of INST_RSHIFT and INST_LSHIFT. 2005-10-05 Don Porter [kennykb-numerics-branch] * generic/tclExecute.c: Improved performance of INST_MULT, INST_DIV, INST_ADD, and INST_SUB and replaced a "goto... label" with a "break from loop" in TclIncrObj() and removed some dead code. 2005-10-05 Andreas Kupries * generic/tclPipe.c (TclCreatePipeline): Fixed [Bug 1109294]. Applied the patch provided by David Gravereaux. * doc/CrtChannel.3: Fixed [Bug 1104682], by application of David Welton's patch for it, and added a note about wideSeekProc. * generic/tclIORChan.c (RcClose): Removed unreachable panic/return statements. This fixes the remainder of [Bug 1286256]. 2005-10-05 Jeff Hobbs * tests/env.test (env-6.1): * win/tclWinPort.h: define USE_PUTENV_FOR_UNSET 1 * generic/tclEnv.c (TclSetEnv, TclUnsetEnv): add USE_PUTENV_FOR_UNSET to existing USE_PUTENV define to account for various systems that have putenv(), but can't unset env vars with it. Note difference between Windows and Linux for actually unsetting the env var (use of '='). Correct the resizing of the environ array. We assume that we are in full ownership, but that's not correct.[Bug 979640] 2005-10-04 Don Porter [kennykb-numerics-branch] * generic/tclExecute.c: Updated TclIncrObj() to more efficiently add native long integers. Also updated IllegalExprOperandType and the INST_UMINUS, INST_UPLUS, INST_BITNOT, and INST_TRY_CVT_TO_NUMERIC sections for performance. * generic/tclBasic.c: Updated more callers to make use of TclGetNumberFromObj. Removed some dead code. 2005-10-04 Jeff Hobbs * win/tclWinSerial.c (SerialSetOptionProc): free argv [Bug 1067708] * tests/http.test: do not URI encode -._~ according * library/http/http.tcl (init): to RFC3986. [Bug 1182373] (aho) * unix/tclLoadShl.c (TclpDlopen): use DYNAMIC_PATH on second shl_load only. [Bug 1204237] * doc/scan.n: scan %[] requires "one or more chars" [Bug 1277503] * tests/winFile.test (getuser): allow valid Windows usernames. [Bug 1311285] * generic/tclParse.c (Tcl_ParseCommand): add code that recognizes {} in addition to {expand} for word expansion (make with -DALLOW_EMPTY_EXPAND). 2005-10-04 Zoran Vasiljevic * generic/tclIO.c (Tcl_ClearChannelHandlers): now deletes any outstanding timer for the channel. Also, prevents events still in the event queue from triggering on the current channel. * generic/tclTimer.c (Tcl_DeleteTimerHandler): bail out early if passed NULL argument. 2005-10-03 Don Porter [kennykb-numerics-branch] * generic/tclBasic.c: Re-implemented ExprRoundFunc and ExprEntierFunc to use TclGetNumberFromObj. * generic/tclInt.h: Added new routine TclGetNumberFromObj to * generic/tclObj.c: provide efficient access to the actual internal rep of a numeric Tcl_Obj without conversions. 2005-10-03 Kevin Kenny * tools/loadICU.tcl: Changed the file names of message catalogs to lowercase. * tools/makeTestCases.tcl: * library/tzdata/*: Olson's tzdata2005n.tar.gz. Includes new DST rules for USA and a number of changes to other locales. * tests/clock.test: Regenerated for new US DST rules. 2005-09-30 Don Porter * generic/tclMain.c: Separate encoding conversion of command line arguments from list formatting. [Bug 1306162]. 2005-09-30 Don Porter [kennykb-numerics-branch] * generic/tclStringObj.c: Bug fix: Missing cast to large enough integral size before << operations led to broken [format %llx] results. Thanks to Robert Henry for reporting the bug. 2005-09-29 Jeff Hobbs * doc/mathfunc.n: implementation for TIP #255, expr min/max * library/init.tcl: * tests/info.test, tests/expr-old.test: 2005-09-27 Don Porter [kennykb-numerics-branch] * generic/tcl.h: Changed name of the new Tcl_Obj intrep field * generic/tclObj.c: from "bignumValue" to "ptrAndLongRep" as * generic/tclProc.c: described in TIP 237, and more suitable for other more general uses. 2005-09-27 Donal K. Fellows * tests/binary.test (binary-14.18): Added test for [Bug 1116542] though the bug itself was already fixed by unrelated changes. 2005-09-26 Kevin Kenny [kennykb-numerics-branch] Merge updates from HEAD. 2005-09-26 Kevin Kenny * libtommath/: Updated to release 0.36. * generic/tommath.h: Regenerated. * generic/tclTomMathInterface.h: Added ten missing aliases for mp_* functions to avoid namespace pollution in Tcl's exported symbols. [Bug 1263012] 2005-09-23 Don Porter [kennykb-numerics-branch] * unix/Makefile.in: Added -DMP_PREC=4 switch to all compiles so * win/Makefile.in: that minimum memory requirements of mp_int's * win/makefile.vc: will not be quite so large. [Bug 1299153]. * generic/tclStrToD.c: Fixed memory leak. [Bug 1299803]. * generic/tclObj.c: 2005-09-20 Don Porter [kennykb-numerics-branch] * generic/tclExecute.c: Revise TclIncrObj() to call Tcl_GetBignumAndClearObj. * generic/tcl.decls: Add Tcl_GetBignumAndClearObj. * generic/tclObj.c: * generic/tclDecls.h: make genstubs * generic/tclStubInit.c: 2005-09-16 Don Porter [kennykb-numerics-branch] * generic/tclInt.h: Added TclBNInitBigNumFromWideInt() so * generic/tclTomMathInterface.c: that every caller isn't required to duplicate the sign logic to use the unsigned interface. * generic/tclBasic.c: Reduce the number of places where Tcl intrudes * generic/tclExecute.c: into the internal format details of the mp_int * generic/tclObj.c: struct. * generic/tclStrToD.c: * generic/tcLStringObj.c: * generic/tclTomMath.h: Added mp_cmp_d to routines from libtommath * unix/Makefile.in: used by Tcl. * win/Makefile.in: * win/makefile.vc: * libtommath/bn_mp_add_d.c: Bug fix. For mp_add_d(&a, d, &c), when &a has the value -d, then the value &c computed should be zero, but mp_add_d was producing an inconsistent zero value with a sign field of MP_NEG, something like a value of -0, which other routines in libtommath can't handle. * generic/tclExecute.c: Dropped all creation of "bigOne" values and just use tommath routines that accept the value "1" directly. 2005-09-15 Miguel Sofer * doc/ParseCmd.3: copy/paste fix [Bug 1292427] 2005-09-15 Don Porter [kennykb-numerics-branch] Merge updates from HEAD. * generic/tclStringObj.c (TclAppendFormattedObjs): Revision to eliminate one round of string copying. * generic/tclBasic.c: More callers of TclObjPrintf and * generic/tclCkalloc.c: TclFormatToErrorInfo. * generic/tclCmdMZ.c: * generic/tclExecute.c: * generic/tclIORChan.c: * generic/tclMain.c: * generic/tclProc.c: * generic/tclTimer.c: * generic/tclUtil.c: * unix/tclUnixFCmd.c * unix/configure: autoconf-2.59 2005-09-15 Donal K. Fellows * unix/tcl.m4 (SC_TCL_EARLY_FLAGS): Added extra hack to allow Tcl to transparently open large files on RHEL 3. [Bug 1287638] 2005-09-14 Don Porter * generic/tclStringObj.c: Bug fixes: ObjPrintfVA needed to support "*" fields and needed to interpret precision limits on %s conversions as a maximum number of bytes, not Tcl_UniChars, to take from the (char *) argument. * generic/tclBasic.c: Updated several callers to use * generic/tclCkalloc.c: TclFormatToErrorInfo() and/or * generic/tclCmdAH.c: TclObjPrintf(). * generic/tclCmdIL.c: * generic/tclCmdMZ.c: * generic/tclDictObj.c: * generic/tclExecute.c: * generic/tclIORChan.c: * generic/tclIOUtil.c: * generic/tclNamesp.c: * generic/tclProc.c: * library/init.tcl: Keep [unknown] in sync with errorInfo formatting rules. 2005-09-13 Don Porter * generic/tclBasic.c: First caller of TclFormatToErrorInfo. * generic/tclInt.h: Using stdarg.h conventions, add more * generic/tclStringObj.c: fixed arguments to TclFormatObj() and TclObjPrintf(). Added new routine TclFormatToErrorInfo(). * generic/tcl.h: Explicitly standardized on the use of stdarg.h * generic/tclBasic.c: conventions for functions with variable number * generic/tclInt.h: of arguments. Support for varargs.h has been * generic/tclPanic.c: implicitly gone for some time now. All * generic/tclResult.c: TCL_VARARGS* macros purged from Tcl sources, * generic/tclStringObj.c: leaving only some deprecated #define's * tools/genStubs.tcl: in tcl.h for the sake of older extensions. * generic/tclDecls.h: make genstubs * doc/AddErrInfo.3: Replaced all documented requirement for use of * doc/Eval.3: TCL_VARARGS_START() with requirement for use of * doc/Panic.3: va_start(). * doc/SetResult.3: * doc/StringObj.3: 2005-09-12 Don Porter [kennykb-numerics-branch] Merge updates from HEAD. * generic/tclCmdAH.c: Added support for the "ll" width * generic/tclStringObj.c: specifier to [format]. * generic/tclStringObj.c (TclAppendFormattedObjs): Bug fix: make sure %ld formats force the collection of a wide value, when the value could be a different long. 2005-09-09 Andreas Kupries * generic/tclIORChan.c (RcDecodeEventMask): Added missing type declaration for the parameter 'mask'. This fixes the [Bug 1286256]. The other warning can be removed only by removing the panic/return code. 2005-09-09 Don Porter [kennykb-numerics-branch] Merge updates from HEAD. 2005-09-09 Kevin Kenny * generic/tclStringObj.c: Added two missing casts to silence messages from MSVC6. 2005-09-09 Don Porter * generic/tclInt.h: New internal routine TclObjPrintf() * generic/tclStringObj.c: is similar to TclFormatObj() but accepts arguments in non-Tcl_Obj format. * generic/tclInt.h: New internal routines TclFormatObj() * generic/tclStringObj.c: and TclAppendFormattedObjs() to offer sprintf()-like means to append to Tcl_Obj. Work in progress toward [RFE 572392]. * generic/tclCmdAH.c: Compiler directive NEW_FORMAT when #define'd directs the [format] command to be implemented in terms of the new TclAppendFormattedObjs() routine. 2005-09-08 Donal K. Fellows TIP#254 IMPLEMENTATION * generic/tclLink.c (LinkTraceProc,ObjValue): Added many new of C var * generic/tcl.h: to link to, making it * doc/LinkVar.3: easier to seamlessly * generic/tclTest.c (TestlinkCmd): couple C code and Tcl * tests/link.test: scripts in an application. [Patch 1242844] 2005-09-07 Don Porter * generic/tclUtf.c (Tcl_UniCharToUtf): Corrected handling of negative * tests/utf.test (utf-1.5): Tcl_UniChar input value. Incorrect handling was producing byte sequences outside of Tcl's legal internal encoding. [Bug 1283976]. 2005-09-06 Donal K. Fellows * generic/tclInt.h (List): Added flag to keep track of whether a list * generic/tclListObj.c: with a string rep is provably canonical. * generic/tclUtil.c (Tcl_ConcatObj): Do efficient concatenation and * generic/tclBasic.c (Tcl_EvalObjEx): evaluation when the list is canonical, and not just when the list is pure. This should make the "pure list" hacking introduced in 8.3 much more robust. 2005-09-05 Donal K. Fellows * generic/tclObj.c (pendingObjDataKey): Added missing 'static' to stop symbol from leaking outside the Tcl library. [Bug 1263012] 2005-09-02 Don Porter [kennykb-numerics-branch] * generic/tclScan.c: Bug fix: The %o, %x, %i formats of [scan] must not accept any 0b or 0o prefixes. [scan $s %o] must continue to work even with KILL_OCTAL enabled. * generic/tclInt.h: Added TCL_PARSE_SCAN_PREFIXES to the flags * generic/tclStrToD.c: accepted by TclParseNumber. 2005-09-01 Andreas Kupries * unix/tclUnixSock.c (InitializeHostName): Synchronized use of static modifier in declaration and definition of function. * unix/tclUnixChan.c (FileTruncateProc): Synchronized use of static modifier in declaration and definition of function. * generic/tclResult.c (ReleaseKeys): Synchronized use of static modifier in declaration and definition of function. * generic/tclListObj.c (NewListIntRep): Synchronized use of static modifier in declaration and definition of function. * generic/tclEncoding.c (InitializeEncodingSearchPath): Synchronized use of static modifier in declaration and definition of function. * generic/tclEncoding.c (FillEncodingFileMap): Synchronized use of static modifier in declaration and definition of function. * generic/tclIORChan.c (RcNewHandle): Synchronized use of static modifier in declaration and definition of function. 2005-09-01 Don Porter [kennykb-numerics-branch] * generic/tclObj.c: TclParseNumber calls meant to parse an integer value now pass the TCL_PARSE_INTEGER_ONLY flag. * generic/tclScan.c: Extended [scan] to accept the %lld, %llo, %llx, and %lli formats. Numeric scanning is now done via TclParseNumber calls * generic/tclInt.h: Extended TclParseNumber to accept new flag * generic/tclStrToD.c: values TCL_PARSE_INTEGER_ONLY, TCL_PARSE_OCTAL_ONLY, and TCL_PARSE_HEXIDECIMAL_ONLY, to give caller more control over the parsing rules. 2005-08-31 Vince Darley * doc/FileSystem.3: * unix/tclUnixFile.c: * windows/tclWinFile.c: clarify that Tcl_FSMatchInDirectory may be called with a NULL interpreter, and fix the code so this is allowed. Tcl's core itself (tclEncoding.c:FillEncodingFileMap()) calls this with a NULL interpreter. 2005-08-30 Don Porter [kennykb-numerics-branch] * generic/tclObj.c: Extended bignum support to include bignums so large they will not pack into a Tcl_Obj. When they outgrow Tcl's string rep length limits, a panic will result. * generic/tclTomMath.h: Added mp_sqrt to routines from * unix/Makefile.in: libtommath used by Tcl. * win/Makefile.in: * win/makefile.vc: * generic/tclBasic.c: Extended sqrt(.) so that range covers the entire double range, accepting as many bignums in the domain as that will allow. 2005-08-29 Andreas Kupries * library/tm.tcl (::tcl::tm::roots): Accepted Don Porter's patch for [Bug 1189657]. Syncs the implementation to the specification (TIP #189) 2005-08-29 Don Porter [kennykb-numerics-branch] Merge updates from HEAD. * generic/tclBasic.c: Restored round(.) to the Tcl 8.4 rules. 2005-08-29 Kevin Kenny * generic/tclBasic.c (ExprMathFunc): Restored "round away from zero" * tests/expr.test (expr-46.*): behaviour to the "round" function. Added test cases for the behavior, including the awkward case of a number whose fractional part is 1/2-1/2ulp. [Bug 1275043] 2005-08-26 Andreas Kupries * generic/tclIO.c: Moved Tcl_{Cut,Splice}Channel to {Cut,Splice}Channel for internal use, and created new public functions for Tcl_{Cut,Splice}Channel which walk the whole stack of transformations and invoke the necessary thread actions. Added code to Tcl_(Un)StackChannel to properly invoke the thread actions when pushing and popping transformations on/from a channel. 2005-08-26 Donal K. Fellows * generic/tclNamesp.c (NamespaceEnsembleCmd): Reset the result after creating an ensemble to clear any result object sharing (potentially caused by delete traces) so that we can safely return the name of the ensemble. Previously, this caused crashes in Snit's test suite. 2005-08-25 Donal K. Fellows * generic/tclListObj.c (UpdateStringOfList): Stop uncontrolled and unsafe crashes from happening when working with very large string representations. [Bug 1267380] * generic/tclExecute.c (TEBC:INST_DICT_LAPPEND): Stop dropping a duplicated object on the floor, which was a memory leak (and a wrong result too). Thanks to Andreas Kupries for reporting this. 2005-08-25 Don Porter [kennykb-numerics-branch] Merge updates from HEAD * generic/tclExecute.c: Bug fix. INST_RSHIFT: shift of negative values produced incorrect results. * generic/tclExecute.c: Bug fix. INST_*SHIFT opcodes stack management. [expr 0<<6] should be 0, not 6. * generic/tclBasic.c: Extended the domain of round(.) to all non-Inf, non-NaN doubles, using bignums for the result as needed. 2005-08-24 Andreas Kupries TIP#219 IMPLEMENTATION * doc/SetChanErr.3: ** New File **. Documentation of the new channel API functions. * generic/tcl.decls: Stub declarations of the new channel API. * generic/tclDecls.h: Regenerated * generic/tclStubInit.c: * tclIORChan.c: ** New File **. Implementation of the reflected channel. * generic/tclInt.h: Integration of reflected channel and new error * generic/tclIO.c: propagation into the generic I/O core. * generic/tclIOCmd.c: * generic/tclIO.h: * library/init.tcl: * tests/io.test: Extended testsuite. * tests/ioCmd.test: * tests/chan.test: * generic/tclTest.c: * generic/tclThreadTest.c: * unix/Makefile.in: Integration into the build machinery. * win/Makefile.in: * win/Makefile.vc: 2005-08-24 Kevin Kenny * generic/tclStrToD.c (Tcl_DoubleDigits): Fixed the corner cases of * tests/binary.test (binary-65.*) formatting floating point numbers with the largest and smallest possible significands, and added test cases for them. 2005-08-24 Kevin Kenny [kennykb-numerics-branch] * generic/tclExecute.c: Corrected some TRACE bugs that prevented compilation with --enable-symbols=all. * generic/tclStrToD.c: Revised commentary to prepare for a renaming of the file, removed some dead code, and fixed a bug where TclBignumToDouble failed on huge negative numbers. * tests/binary.test (binary-65.*): Added missing 'ieeeFloatingPoint' to large/small significand tests. * tests/expr.test (expr-45.*) Added missing braces around expressions. 2005-08-24 Don Porter [kennykb-numerics-branch] * generic/tclBasic.c: Revised implementation of the ceil(.) and * generic/tclInt.h: floor(.) math functions in light of the * generic/tclStrToD.c: revised comparison operators, so that it is always true that ($x <= ceil($x)) and ($x >= floor($x)). The simple approach of "convert to double and call ceil() or floor()" could not guarantee that. * generic/tclExecute.c: Bug fix: TclBignumToDouble return -Inf when appropriate. Removed declarations of removed routines. * generic/tclExecute.c: Revised the type promotion rules of the comparison operators so that they form proper equivalence classes over the set of numeric strings. 2005-08-23 Mo DeJong * unix/configure.in: * win/configure: Regen. * win/configure.in: Update minimum autoconf version to 2.59. 2005-08-23 Kevin Kenny [kennykb-numerics-branch] * generic/tclCmdMZ.c (Tcl_StringObjCmd): * generic/tclInt.h: * generic/tclObj.c (Tcl_GetBooleanFromObj, SetDoubleFromAny, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_GetBignumFromObj): * generic/tclParseExpr.c (GetLexeme): * generic/tclScan.c (Tcl_ScanObjCmd): * generic/tclStrToD.c (TclParseNumber): * tests/binary.test (binary-62.1-65.7): * tests/expr.test (expr-40.1-42.1): * scan.test (scan-14.1,14.2): Modified Tcl_ParseNumber to accept an argument to force interpretation as decimal, and modified [scan] to use it. Corrected a bug where Not a Number with hexadecimal information bits returned consistently incorrect values. #ifdef-ed out some code that is needed only for IBM hexadecimal floating point. Fixed bugs in code to handle the corner cases of smallest and largest significands. Added test cases to improve test coverage in generic/tclStrToD.c. Added test cases for 0b notation (TIP #114). Removed TclStrToD, and the static functions that it calls, which are now dead code (TclParseNumber now does all input floating-point conversions.) 2005-08-23 Don Porter [kennykb-numerics-branch] * generic/tclStrToD.c: Bug fix: set shift magnitude properly whether we're expanding to mp_int type or not. * generic/tclExecute.c: Bug fix: ACCEPT_NAN under INST_UMINUS. * generic/tclStrToD.c: New macros TIP_114_FORMATS and KILL_OCTAL to configure acceptance of 0o and 0b numbers and rejection of "leading zero as octal". * generic/tclBasic.c: Re-used the guts of int(.) and wide(.) math functions to perform conversions in OldMathFuncProc. * generic/tclBasic.c: Support for ACCEPT_NAN. * generic/tclExecute.c: * generic/tclInt.decls: Restored TclExprFloatError to internal stubs * generic/tclBasic.c: table, and moved definition back to * generic/tclExecute.c: tclExecute.c from tclBasic.c to handle #undef ACCEPT_NAN. * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclInt.h: New internal macros TclIsNaN and TclIsInfinite * generic/tclBasic.c: replace the IS_NAN and IS_INF macros scattered * generic/tclExecute.c: here and there. * generic/tclObj.c: * generic/tclStrToD.c: * generic/tclUtil.c: 2005-08-22 Daniel Steffen * unix/tclConfig.h.in: autoheader-2.59. 2005-08-22 Don Porter [kennykb-numerics-branch] * generic/tclInt.h: New ACCEPT_NAN macro to mark code that * generic/tclCmdAH.c: supports or disables accepting of the NaN * generic/tclExecute.c: value at various points. * generic/tclLink.c: * generic/tclStrToD.c: Bug fix. Parsing of +/- Infinity was reversed. * generic/tclTestObj.c: Disabled unused [testconvertobj] command. * generic/tclBasic: Added [expr {entier(.)}]. Rewrote int(.) and wide(.) to use the same guts, accepting all non-Inf doubles as arguments. * generic/tclInt.h: New routine TclInitBignumFromDouble. * generic/tclStrToD.c: Modified to return code and write error message. * generic/tclInt.h: TCL_WIDE_INT_IS_LONG implies NO_WIDE_TYPE. * generic/tclObj.c: Removed now unnecessary tests of the * generic/tclStrToD.c: TCL_WIDE_INT_IS_LONG definition. * generic/tclInt.h: New internal routine TclSetBignumIntRep * generic/tclObj.c: consolidates packing of bignum value into a * generic/tclStrToD.c: Tcl_Obj within one source code file. * tests/expr.test: Corrected the wideIs64bit constraint. * tests/format.test: * tests/scan.test: 2005-08-21 Don Porter [kennykb-numerics-branch] * generic/tclInt.h: Moved TclParseInteger to tclUtil.c and * generic/tclParseExpr.c: made it static. * generic/tclUtil.c: * generic/tclInt.decls: Moved TclExprFloatError to tclBasic.c and made * generic/tclBasic.c: it static. * generic/tclExecute.c: * generitc/tclIntDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclExecute.c: errno, IS_NAN, IS_INF, LLD no longer called in this file; dropped/disabled support for them. * generic/tclCompExpr.c: errno no longer used in these files; * generic/tclParseExpr.c: dropped support "hack" for it. * generic/tclStrToD.c: Disabled out of date support "hack" for errno. * generic/tclBasic.c: Eliminated VerifyExprObjType. Initialize errno to zero in OldMathFuncProc. 2005-08-19 Don Porter [kennykb-numerics-branch] * generic/tclBasic.c: Updated OldMathFuncProc and ExprAbsFunc to do less invasion into numeric Tcl_Obj internals. Made ExprDoubleFunc, ExprIntFunc, ExprWideFunc, and ExprRoundFunc bignum-aware. Revised ExprSrandFunc error message. * generic/tclProc.c: Wrapped a few tclWideIntType uses in * generic/tclCmdMZ.c: #ifndef NO_WIDE_TYPE. * generic/tclInt.h: #define'd NO_WIDE_TYPE. * generic/tclVar.c: Replaced TclPtrIncrVar and TclPtrIncrWideVar * generic/tclInt.h: with TclPtrIncrObjVar and replaced TclIncrVar2 * generic/tclInt.decls: and TclIncrWideVar2 with TclIncrObjVar2. New routines call on TclIncrObj to do the work. * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclCmdIL.c: Rework Tcl_IncrObjCmd and the INST_*INCR* * generic/tclExecute.c: opcodes to use the new routines. 2005-08-18 Don Porter [kennykb-numerics-branch] * generic/tclExecute.c: Fixed string rep invalidation bug in * tests/dict.test (dict-11.17): INST_DICT_INCR_IMM rewrite. * generic/tclDictObj.c: DictIncrCmd rewrite to use TclIncrObj. * generic/tclInt.h: TclIncrObj static -> internal * generic/tclExecute.c: 2005-08-17 George Peter Staplin * generic/tclBasic.c: eliminate a namespace clash caused by BuiltinFuncTable not being static. * generic/tclObj.c: fix a namespace clash caused by a missing static for pendingObjData. 2005-08-17 Kevin Kenny * generic/tclEvent.c (Tcl_Finalize): Removed a copy-and-paste accident that caused a (mostly harmless) double finalize of the load and filesystem subsystems. * tests/clock.test: Eliminated the bad test clock-43.1, and split clock-50.1 into two tests, with a more permissive check on the error message for an out-of-range value. 2005-08-17 Kevin Kenny [kennykb-numerics-branch] * generic/tclBasic.c (Tcl_Expr{Long,Double}{,Obj}): Updated to * generic/tclTest.c: deal with * tests/expr-old.test: bignums (well, * tests/expr.test: mostly). Added a missing "errno=0;" in ExprUnaryFunc so that spurious error returns aren't detected. Added test cases for Tcl_Expr* and Tcl_Expr*Obj because there was very poor test coverage in those areas. * generic/tclParseExpr.c: Reworked parsing of numbers to call TclParseNumber rather than trying to do things locally. * generic/tclStrToD.c: Corrected a comment. Changed so that *endPtrPtr does not include any trailing whitespace. 2005-08-17 Don Porter [kennykb-numerics-branch] * generic/tclExecute.c: New routine TclIncrObj to centralize the increment operation needed in many places. Updated INST_DICT_INCR_IMM to make use of it. 2005-08-16 Don Porter [kennykb-numerics-branch] * generic/tclExecute.c: Made bit shifting opcodes and INST_MOD bignum-aware. * tests/scan.test: Making << bignum-aware means that repeated * tests/string.test: left shifting cannot turn a positive into a negative. Revised [int_range] and [largest_int] utility commands in the test suite that relied on that happening. Without revision they became infinite loops. * generic/tclExecute.c: Made binary bitwise opcodes bignum-aware. * generic/tclTomMath.h: Added mp_or and mp_xor to routines from * unix/Makefile.in: libtommath used by Tcl. * win/Makefile.in: * win/makefile.vc: 2005-08-15 Don Porter [kennykb-numerics-branch] Updates from HEAD. * generic/tclExecute.c: More revisions to IllegalExprOperandType. Merged INST_BITNOT with INST_UMINUS and make it bignum-aware according to the rule: ~a = -a - 1. Disabled unused code and noted more TODOs. * generic/tclInt.decls: Disabled TclLooksLikeInt() and all callers. * generic/tclUtil.c: * generic/tclCompCmds.c: * generic/tclBasic.c: Rewrite of VerifyExprObjType(). * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclExecute.c: Updated execution of comparison bytecodes to be bignum-aware, routing string compares through INST_STR_CMP. 2005-08-14 Don Porter [kennykb-numerics-branch] * generic/tclExecute.c: Updated execution of arithmetic bytecodes to be bignum-aware, and to allow calculations on NaN to produce a NaN result. INST_UMINUS updated to call mp_neg. * generic/tclTomMath.h: Added mp_and, mp_expt_d, and mp_neg to * unix/Makefile.in: routines from libtommath used by Tcl. * win/Makefile.in: * win/makefile.vc: 2005-08-13 Don Porter [kennykb-numerics-branch] * generic/tclObj.c: Extended Bignum auto-narrowing to auto-narrow to tclWideIntType when appropriate; this helps keep things working as the bytecode execution code is migrated to supporting bignums. * generic/tclExecute.c: Major overhaul of IllegalExprOperandType. Changed several TclNewFooObj() calls to more logically appropriate ones. Added several TODO comments marking opportunies for future work. Made more use of the eePtr->constants. Made INST_UMINUS bignum aware. 2005-08-12 Don Porter [kennykb-numerics-branch] * generic/tclExecute.c: Simplify doCondJump. Use eePtr->constants as result of INST_DICT_NEXT, INST_LAND, and INST_LOR. Separate INST_LNOT from INST_UMINUS and simplify. 2005-08-12 Kevin Kenny * generic/tclClock.c (MktimeObjCmd): * library/clock.tcl (GetSystemTimeZone, LoadZoneinfoFile) (ReadZoneinfoFile): * tests/clock.test (clock-50.1): Added functionality to read /etc/localtime if it exists, so that Tcl's time can track system time on Linux even if TZ is not set. Changed ::tcl::clock::Mktime to check for failure, and added a test case that mimics failure but is really success. 2005-08-11 Don Porter [kennykb-numerics-branch] * generic/tclExecute.c: Rewrite of INST_LAND/INST_LOR to take advantage of loss of "pure double" issues. Merged INST_UPLUS with INST_TRY_CVT_TO_NUMERIC and updated to use improved rules for impure "double"s as well. * generic/tclStrToD.c: Restored conditional generation of tclWideIntType values by TclParseNumber so that Tcl's not completely broken while bignum calculation support is incomplete. The NO_WIDE_TYPE macro can be used to disable this. * generic/tclBasic.c (ExprAbsFunc): First pass making [expr abs(.)] bignum-aware. 2005-08-11 Kevin Kenny * generic/tclEvent.c: Eliminated the USE_THREAD_STORAGE option * generic/tclInt.h: (which is on in every build generated by * generic/tclThread.c: by the standard configurator). * generic/tclThreadStorage.c: Eliminated the code for thread specific * unix/configure: data without USE_THREAD_STORAGE and * unix/tcl.m4: radically refactored the code for * unix/tclConfig.h.in: USE_THREAD_STORAGE so that it has fewer * unix/tclUnixThrd.c: dependencies on the order of * win/configure: finalization. (Also, made 'make * win/Makefile.in: distclean' on Windows clean just a little * win/rules.vc: bit cleaner.) * win/tcl.m4: * win/tclWinThrd.c: 2005-08-10 Don Porter [kennykb-numerics-branch] * generic/tclTomMath.h: Added mp_shrink, mp_to_unsigned_bin, * unix/Makefile.in: mp_to_unsigned_bin_n, and mp_unsigned_bin_size * win/Makefile.in: to routines from libtommath used by Tcl. * win/makefile.vc: * generic/tommath.h: make gentommath_h * generic/tclObj.c: Substantial rewrite to make all number parsing flow through TclParseNumber(). Also established the NO_WIDE_TYPE and BIGNUM_AUTO_NARROW #ifdef's to help track the assumptions of different portions of the code. * generic/tclInt.h: Added NO_WIDE_TYPE #ifdefs 2005-08-10 Kevin Kenny * generic/tclEvent.c (Tcl_Finalize): Pushed Tcl_FinalizeLoad and Tcl_ResetFilesystem down after Tcl_FinalizeThreadAlloc because we can't unload DLL's until after their TSD keys are finalized. (Note that we'll still see aborts if an unloaded DLL has TSD - that still needs to be fixed. * tests/compExpr-old.test (compExpr-3.8): Made tests conditional on * tests/expr.test (expr-3.8): 'unix' because they get stack overflows on Win32 threaded builds, 2005-08-09 Vince Darley * generic/tclPathObj.c: fix to [file rootname] bug in optimized code path reported on comp.lang.tcl. 2005-08-08 Don Porter [kennykb-numerics-branch] * generic/tclObj.c: Replaced some goto's with loops and started use of BIGNUM_AUTO_NARROW and NO_WIDE_TYPE. 2005-08-06 Donal K. Fellows * generic/tclThreadStorage.c: Stop exposing the guts of the thread storage system through the internal stubs table. Client code should always use the standard API. 2005-08-05 Don Porter [kennykb-numerics-branch] * generic/tclObj.c: Rewrote Tcl_GetDoubleFromObj(). 2005-08-05 Donal K. Fellows * unix/tclUnixInit.c (localeTable): Solaris uses a non-standard name for the cp1251 charset. Thanks to Victor Wagner for reporting this. [Bug 1252475] 2005-08-05 Kevin Kenny * win/makefile.vc: Removed unused file ldAout.tcl. * win/makefile.bc: [Bug 1244361] * tests/binary.test: Cleaned up testing for scanning of NaN. [Bug 1246264] * generic/tclBasic.c (ExprAbsFunc): Added code to handle the corner * tests/expr.test (expr-38.1): case of applying 'abs' to the smallest 32-bit integer. [Bug 1241572] 2005-08-04 Andreas Kupries * generic/tclIO.c (CloseChannel): Fixed comment nit, added apparently missing word to complete a sentence. * generic/tclObj.c (Tcl_DbDecrRefCount): Fixed whitespace nit in panic message. 2005-08-04 Don Porter [kennykb-numerics-branch] Updated from HEAD * generic/tclObj.c: Rewrote Tcl_GetBooleanFromObj() and supporting routines to make use of TclParseNumber. This reduces the potential number of times a string value must be scanned. * generic/tclObj.c: Simplified routines that manage the typeTable. Deleted the UpdateStringOfBoolean() routine, that can never be called. 2005-08-03 Don Porter * generic/tclCompExpr.c: Untangled some dependencies in the * generic/tclEvent.c: order of finalization routines. * generic/tclInt.h: [Bug 1251399] * generic/tclObj.c: 2005-08-02 Don Porter [kennykb-numerics-branch] Updated from HEAD 2005-07-30 Daniel Steffen * unix/tclLoadDyld.c (TclpDlopen, TclpLoadMemory): workarounds for bugs/changes in behaviour in Mac OS X 10.4 Tiger. 2005-07-29 Donal K. Fellows * generic/tclCmdIL.c (InfoGlobalsCmd): Even in high-speed mode, still have to take care with non-existant variables. [Bug 1247135] 2005-07-28 Mo DeJong * win/README: Update link to msys_mingw8.zip. 2005-07-28 Don Porter * tests/compExpr-old.test: Still more conversion of "nonPortable" * tests/error.test: tests into tests with constraints that * tests/expr-old.test: describe the limits of their * tests/expr.test: portability. Also more consolidation * tests/fileName.test: of constraint synonyms. * tests/format.test: wideis64bit, 64bitInts => wideIs64bit * tests/get.test: wideIntegerUnparsed => wideIs32bit * tests/load.test: wideIntExpressions => wideBiggerThanInt * tests/obj.test: * tests/parseExpr.test: Dropped "roundOffBug" constraint that * tests/string.test: protected from buggy sprintf. 2005-07-28 Donal K. Fellows * generic/tclPipe.c (TclCreatePipeline): Arrange for POSIX systems to * unix/tclUnixPipe.c (TclpOpenFile): use the O_APPEND flag for * tests/exec.test (exec-19.1): files opened in a pipeline like ">>this". Note that Windows cannot support such access; there is no equivalent flag on the handle that can be set at the kernel-call level. The test is unix-specific in every way. [Bug 1245953] 2005-07-27 Don Porter * generic/tclUtil.c: Converted the $::tcl_precision value to be kept per-thread to prevent different threads from stomping on each others' formatting prescriptions. ***POTENTIAL INCOMPATIBILITY*** Multi-threaded programs that set the value of ::tcl_precision will now have to set it in each thread. * tests/expr.test: Consolidated equivalent constraints into * tests/fileName.test: single definitions and (more precise) names: * tests/get.test: longis32bit, 32bit, !intsAre64bit => longIs32bit * tests/listObj.test: empty => emptyTest; winOnly => win * tests/obj.test: intsAre64bit => longIs64bit Also updated some "nonPortable" tests to use constraints that mark precisely what about them isn't portable, so the tests can run where they work. * library/init.tcl ([unknown]): Corrected return code handling in the portions of [unknown] that expand incomplete commands during interactive operations. [Bug 1214462]. 2005-07-26 Mo DeJong * unix/configure: Regen. * unix/configure.in: Check for a $prefix/share directory and add it the the package if found. This will check for Tcl packages in /usr/local/share when Tcl is configured with the default dist install. [Patch 1231015] 2005-07-26 Don Porter * generic/tclBasic.c (Tcl_CallWhenDeleted): Converted to use per-thread counter, rather than a process global one that required mutex protection. [RFE 1077194] * generic/tclNamesp.c (TclTeardownNamespace): Re-ordering so that * tests/trace.test (trace-34.4): command delete traces fire while the command still exists. [Bug 1047286] 2005-07-24 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_PROG_TCLSH, SC_BUILD_TCLSH): * win/configure: Regen. * win/tcl.m4 (SC_PROG_TCLSH, SC_BUILD_TCLSH): Split confused search for tclsh on PATH and build and install locations into two macros. SC_PROG_TCLSH searches just the PATH. SC_BUILD_TCLSH determines the name of the tclsh executable in the Tcl build directory. [Bug 1160114] [Patch 1244153] 2005-07-23 Don Porter * library/auto.tcl: Updates to the Tcl script library to make use * library/history.tcl: of Tcl 8.4 features. Forward port of * library/init.tcl: appropriate portions of [Patch 1237755]. * library/package.tcl: * library/safe.tcl: * library/word.tcl: 2005-07-23 Mo DeJong * tests/string.test: Add string is tests for functionality that was not tested. * win/README: Update msys + mingw URL. Remove old Cygwin + mingw info. 2005-07-23 Miguel Sofer * generic/tclExecute.c (INST_DICT_*): stop 2 compiler warnings for uninitialised variables. 2005-07-23 Donal K. Fellows * generic/tclExecute.c (TEBC:INST_DICT_INCR_IMM): Fix the incrementor to work correctly with wide values. 2005-07-21 Donal K. Fellows * generic/tclCompCmds.c (TclCompileDictCmd): First run at a compiler * generic/tclExecute.c (TclExecuteByteCode): for dictionaries. Also added an instruction to support 'finally'-like clauses, exposed more of the dict guts to the rest of the core, and defined a few tests to exercise more obscure parts of the compiler's operation that were bugs during development. 2005-07-21 Kevin B. Kenny * library/ldAout.tcl (***REMOVED***): Removed support for ancient * unix/configure: BSD's, IRIX 4, RISCos and * unix/Makefile.in: Ultrix. Removed two files whose * unix/tcl.m4: code is used only on those * unix/tclLoadAout.c (***REMOVED***): antique platforms. ***POTENTIAL INCOMPATIBILITY*** if anyone actually uses those platforms; it is to be noted though, that an error in the installer has actually not caused a necessary file to be installed on those platforms in several releases, and nobody's complained. 2005-07-16 Kevin B. Kenny * generic/tclStrToD.c (RefineResult): Plugged a stupid memory leak in RefineResult (called from Tcl_StrToD). [Tk Bug 1227781] 2005-07-15 Kevin B. Kenny * generic/tclClock.c (TclClockLocaltimeObjCmd,ThreadSafeLocalTime): * library/clock.tcl (GuessWindowsTimeZone, ClearCaches): * tests/clock.test (clock-49.1, clock-49.2): Handle correctly the case where localtime() returns NULL to report a conversion error. Also handle the case where the Windows registry contains timezone values that can be mapped to a tzdata file name but the corresponding file does not exist or is corrupted, by falling back on a Posix timezone string instead; this last case will avoid calls to localtime() in starpacks on Windows. [Bug 1237907] 2005-07-14 Donal K. Fellows * generic/tclCompile.c: Update to follow style guidelines. (TclPrintInstruction): Reorganize to do better printing out of bytecode with far fewer "special hacks" for particular opcodes. * generic/tclCompile.h: Requires two new opcode types. 2005-07-13 Don Porter * unix/tclUnixSock.c: Use a ProcessGlobalValue to store the value * win/tclWinSock.c: returned by Tcl_GetHostName() ([info hostname]). Also re-order initialization of the value on Windows to favor GetComputerName() over gethostname() as a source of the information. 2005-07-12 Kevin Kenny [kennykb-numerics-branch] Updated from HEAD * generic/tclCmdMZ.c (Tcl_StringObjCmd): * generic/tclInt.h: * generic/tclObj.c (Tcl_GetDoubleFromObj, SetDoubleFromAny) (Tcl_GetIntFromObj, SetIntOrWideFromAny): * generic/tclStrToD.c (TclParseNumber, etc.): * tclTomMathInterface.c (TclBNInitBignumFromWideUInt): * tests/obj.test (obj-1.1, obj-2.2, obj-3.1, obj-3.2): Initial attempt at an implementation of TIP #249, comprising a unified parser and modifications to the Tcl_Get*FromObj routines to use it. Further integration of the parser is necessary and planned. 2005-07-12 Donal K. Fellows * doc/lsearch.n: Clarify documentation of -exact option; wording was open to misinterpretation by non-English speakers. 2005-07-11 Donal K. Fellows * generic/tclExecute.c: General style cleanup. 2005-07-08 Mo DeJong * generic/tclExecute.c (TclExecuteByteCode): Reimplement long and wide type integer division and modulus operations so that the smallest and largest integer values are handled properly. The divide operation is more efficient since it no longer does a modulus or negation and only checks for a remainder when the quotient will be a negative number. The modulus operation is now a bit more complex because of a number of special cases dealing with the smallest and largest integers. * tests/expr.test: Add test cases for division and modulus operations on the smallest and largest integer values for 32 and 64 bit types. [Patch 1230205] 2005-07-06 Don Porter * generic/tclLink.c: Simplified LinkTraceProc [Bug 1208108]. 2005-07-05 Don Porter * unix/Makefile.in: Purged use of TCLTESTARGS [RFE 1161550]. * generic/tclUtil.c: Converted TclFormatInt() into a macro. * generic/tclInt.decls: [RFE 1194015] * generic/tclInt.h: * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclNamesp.c: Allow for [namespace import] of a command * tests/namespace.test: over a previous [namespace import] of itself without throwing an error. [RFE 1230597] 2005-07-04 Donal K. Fellows * generic/tclDictObj.c (DictForCmd, DictFilterCmd): Interlocking of dictionary internal representations is now done in the core of the dict iterator. Purge the last attempts at doing it at a higher level as they didn't work and were no longer needed. 2005-07-01 Zoran Vasiljevic * unix/tclUnixNotfy.c: protect against spurious wake-ups while waiting on the condition variable when tearing down the notifier thread [Bug 1222872]. 2005-06-28 Mo DeJong * generic/tclExecute.c (TclExecuteByteCode): When parsing an integer operand for a unary minus expression operator, check for a wide integer that is actually LONG_MIN. If found, convert back to a long int type. * tests/expr.test: Add constraint for 32bit long int type and 64bit wide int type. Add tests that parse the smallest/largest long int and wide int values. 2005-06-24 Kevin Kenny * generic/tclEvent.c (Tcl_Finalize): * generic/tclInt.h: * generic/tclPreserve.c (TclFinalizePreserve): Changed the finalization logic so that Tcl_Preserve finalizes after exit handlers run; a lot of code called from Tk's exit handlers presumes that Tcl_Preserve will still work even from an exit handler. 2005-06-24 Don Porter * library/auto.tcl: Make file safe to re-[source] without destroying registered auto_mkindex_parser hooks. 2005-06-23 Kevin Kenny * win/tclWinChan.c: More rewriting of __asm__ blocks that implement * win/tclWinFCmd.c: SEH in GCC, because mingw's gcc 3.4.2 is not as forgiving of violations committed by the old code and caused panics. [Bug 1225957] 2005-06-23 Daniel Steffen * tools/tcltk-man2html.tcl: fixed useversion glob pattern to accept multi-digit patchlevels. 2005-06-22 Don Porter * win/tclWinFile.c: Potential buffer overflow. [Bug 1225571] Thanks to Pat Thoyts for discovery and fix. 2005-06-22 Kevin Kenny * generic/tclInt.h: Changed the finalization * generic/tclEvent.c (Tcl_Finalize): logic to defer the * generic/tclIO.c (TclFinalizeIOSubsystem): shutdown of the pipe * unix/tclUnixPipe.c (TclFinalizePipes): management until after all * win/tclWinPipe.c (TclFinalizePipes): channels have been closed, in order to avoid a situation where the Windows PipeCloseProc2 would re-establish the exit handler after exit handlers had already run, corrupting the heap. [Bug 1225727] Also corrected a potential read of uninitialized memory in PipeClose2Proc [Bug 1225044] 2005-06-21 Andreas Kupries * generic/tclInt.h: Followup to change made on 2005-06-18 by Daniel Steffen. There are compilers (*) who error out on the redefinition of WORDS_BIGENDIAN. We have to undef the previous definition (on the command line) first to make this acceptable. (*): AIX native. 2005-06-21 Kevin B. Kenny * generic/tclFileName.c: Changed [file split] and [file join] to treat Windows drive letters similarly to ~ syntax and make sure that they appear with "./" in front when they are in intermediate components of the path. [Bug 1194458] * tests/fileName.test: Added test for the above bug. 2005-06-21 Don Porter * generic/tclBasic.c: Added missing walk of the list of active * generic/tclTrace.c: traces to cleanup references to traces being * generic/tclInt.h: deleted. [Bug 1201035] Made the walk of the * tests/trace.test (trace-34.*): active trace list aware of the direction of trace scanning, so the proper correction can be made. [Bug 1224585] 2005-06-21 Donal K. Fellows * unix/tcl.m4 (SC_ENABLE_SYMBOLS): Only enable the 'compile' special debugging feature when requested in configure.in; removes irrelevant junk from the configure files of extensions that use Tcl's tcl.m4. 2005-06-20 Donal K. Fellows * generic/tclCompile.h (INST_PUSH_RETURN_OPTIONS): New opcode to allow * generic/tclCompCmds.c (TclCompileCatchCmd): compilation of * generic/tclCompile.c: TIP#90 catch [Bug * generic/tclExecute.c (TclExecuteByteCode): 1219112] * generic/tclCompCmds.c (TclCompileSwitchCmd): Ensure we spill to the command form in all cases where it generates an error. 2005-06-20 Mo DeJong * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Generate an error if a mode argument like -exact is passed more than once to the switch command. The previous implementation silently accepted invalid switch invocations like [switch -exact -glob $str ...]. * tests/for.test: Check some error cases when invoking continue and break inside a for loop next script. * tests/switch.test: Add checks for shortened version of a mode argument like -exact. Add test for more than one mode argument. Add test for odd case of passing a variable as a body script. 2005-06-18 Daniel Steffen * generic/tclInt.h: ensure WORDS_BIGENDIAN is defined correctly with fat compiles on Darwin (i.e. ppc and i386 at the same time), the configure AC_C_BIGENDIAN check is not sufficient in this case because a single run of the compiler builds for two architectures with different endianness. * unix/tcl.m4 (Darwin): add -headerpad_max_install_names to LDFLAGS to ensure we can always relocate binaries with install_name_tool. * unix/configure: autoconf-2.59 2005-06-18 Donal K. Fellows * generic/tclCmdAH.c (Tcl_FormatObjCmd): Fix for [Bug 1154163]; only * tests/format.test: insert 'l' modifier when it is needed. 2005-06-17 Donal K. Fellows * generic/tclTimer.c (AfterDelay): Split out the code to manage synchronous-delay [after] commands. * tests/interp.test (interp-34.10): Time limits and synch-delay [after] did not mix well... [Bug 1221395] 2005-06-14 Donal K. Fellows * generic/tclBasic.c (Tcl_DeleteCommandFromToken): Only delete a * tests/namespace.test (namespace-49.2): command from the hashtable on reentrant processing if it has not been already deleted; at least three deletes of the same command are possible. [Bug 1220058] * generic/tclTrace.c (TraceCommandProc): Remove bogus error message creation when traces trigger in situations where the command has already been deleted. 2005-06-13 Vince Darley * generic/tclFCmd.c: correct fix to file mkdir 2005-06-09 [Bug 1219176] 2005-06-12 Donal K. Fellows * generic/tclCompCmds.c: Factor out some common idioms into named forms for greater clarity. 2005-06-10 Donal K. Fellows * doc/chan.n: Fold in the descriptive parts of the documentation for all the commands that [chan] builds on top of. 2005-06-09 Vince Darley * generic/tclFCmd.c: fix to race condition in file mkdir [Bug 1217375] * doc/glob.n: improve glob documentation [Bug 1190891] 2005-06-09 Donal K. Fellows * doc/expr.n, doc/mathfunc.n: Fix minor typos [Bug 1211078] and add mention of distinctly-relevant [namespace path] subcommand. 2005-06-07 Don Porter * generic/tclInt.h: Reduced the Tcl_ObjTypes "index", * generic/tclIndexObj.c: "ensembleCmd", "localVarName", and * generic/tclNamesp.c: "levelReference" to file static scope. * generic/tclProc.c: * generic/tclVar.c: * generic/tclObj.c: Restored registration of the "procbody" Tcl_ObjType, as required by the tclcompiler application. * generic/tclDecls.h: make genstubs * generic/tclStubInit.c: 2005-06-07 Donal K. Fellows * generic/tclIO.c (Tcl_ChannelTruncateProc): Stop proliferation of * generic/tcl.h: channel type versions * doc/CrtChannel.3: following advice from AKu Bump patchlevel to a4 to distinguish from a3 release. * generic/tclInt.h (INTERP_TRACE_IN_PROGRESS): Add flag so the error * generic/tclIndexObj.c (Tcl_WrongNumArgs): messages from ensembles * generic/tclIOCmd.c (Tcl_ReadObjCmd): can be correct. TIP#208 IMPLEMENTATION * library/init.tcl: Create the chan ensemble. * tests/chan.test: Rudimentary test suite. * doc/chan.n: General documentation. TRUNCATION API (part of TIP#208) * generic/tcl.h, generic/tcl.decls: Declaration of the API. * doc/CrtChannel.3, doc/OpenFileChnl.3: Documentation of the API. * generic/tclBasic.c (Tcl_CreateInterp): Create the mapping into Tcl. * generic/tclIOCmd.c (TclChanTruncateObjCmd): Implementation of Tcl-level truncation API. * generic/tclIO.c (Tcl_TruncateChannel): Generic C-level truncation API implementation. * unix/tclUnixChan.c (FileTruncateProc): Basic implementation of truncating driver. * win/tclWinChan.c (FileTruncateProc): Added implementation of file truncation for Windows. * tests/chan.test (chan-15.2): Added real test of truncation. 2005-06-06 Kevin B. Kenny * win/tclWin32Dll.c: Corrected another buglet in the assembly code for stack probing on Win32/gcc. [Bug 1213678] * generic/tclObj,c: Added missing 'static' on definition of UpdateStringOfBignum, and removed a 'switch' on a 'long long' operand (which HP-UX native 'cc' seems unable to handle). [Bug 1215775] 2005-06-04 Jeff Hobbs *** 8.5a3 TAGGED FOR RELEASE *** * unix/Makefile.in (dist): add libtommath 2005-06-03 Donal K. Fellows * library/parray.tcl (parray): Only generate the sorted list of element names once. Thanks to Andreas Leitgeb for spotting this. 2005-06-03 Daniel Steffen * macosx/Makefile: fixed 'embedded' target. 2005-06-02 Jeff Hobbs * unix/Makefile.in (html): add BUILD_HTML_FLAGS optional var * tools/tcltk-man2html.tcl: add a --useversion to prevent confusion when multiple Tcl source dirs exist. 2005-06-01 Don Porter * generic/tclBasic.c: For compatibility with earlier Tcl releases, * generic/tclResult.c: when a command procedure simply does a * generic/tclTest.c: "return TCL_RETURN;" we must interpret that * tests/result.test: the same as "return Tcl_SetReturnOptions(interp, Tcl_NewObj());" [Bug 1209759]. 2005-06-01 Donal K. Fellows * generic/tclCompCmds.c (TclCompileSwitchCmd): Allow compilation of -nocase -glob [switch]es (only one we know how to compile). TIP#241 IMPLEMENTATION from Joe Mistachkin * generic/tclCmdIL.c (Tcl_LsearchObjCmd, Tcl_LsortObjCmd): * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): Implementation of -nocase option for [lsearch], [lsort] and [switch] commands. * win/tclWinPort.h: Win uses nonstandard function names... * tests/cmdIL.test, tests/lsearch.test, tests/switch.test: Tests * doc/lsearch.n, doc/lsort.n, doc/switch.n: Docs * generic/tclCompCmds.c (TclCompileLindexCmd): Compile the most common case of [lindex] more efficiently. * unix/tclUnixNotfy.c (Tcl_FinalizeNotifier): Pass the correct number of arguments to Tcl_JoinThread. 2005-05-31 Donal K. Fellows * unix/configure.in, unix/tcl.m4: Standardize generation of help messages to always use AC_HELP_STRING and always (except for --with-tcl and --with-tk, where the default is complex) say what the default is. 2005-05-31 Zoran Vasiljevic * unix/tclUnixNotfy.c: the notifier thread is now created as joinable thread and it is properly joined in Tcl_FinalizeNotifier. This is an attempt to fix the [Bug 1082283]. 2005-05-30 Zoran Vasiljevic * win/tclWinThrd.c: Fixed [Bug 1204064] 2005-05-30 Donal K. Fellows TIP #229 IMPLEMENTATION * generic/tclNamesp.c (Tcl_FindCommand, TclResetShadowedCmdRefs) (NamespacePathCmd, SetNsPath, UnlinkNsPath, TclInvalidateNsPath): Implementation of the [namespace path] command and the command name resolution engine. * doc/info.n, doc/namespace.n: Doc updates. * tests/namespace.test (namespace-51.*): Test updates. * generic/tclResolve.c (BumpCmdRefEpochs, Tcl_SetNamespaceResolvers): * generic/tclBasic.c (Tcl_CreateCommand, Tcl_CreateObjCommand): Ensure that people don't see stale paths. * generic/tclInt.h (Namespace, NamespacePathEntry): Structure defs. * generic/tclCmdIL.c (InfoCommandsCmd): Updates to [info commands]. 2005-05-26 Daniel Steffen * macosx/Makefile: moved & corrected EMBEDDED_BUILD check. * unix/configure.in: corrected framework finalization to softlink stub library to Versions/8.x subdir instead of Versions/Current. * unix/configure: autoconf-2.59 2005-05-25 Jeff Hobbs * generic/tclCmdMZ.c (Tcl_TimeObjCmd): add necessary cast 2005-05-25 Don Porter TIP#182 IMPLEMENTATION [Patch 1165062] * doc/mathfunc.n: New built-in math function bool(). * generic/tclBasic.c: * tests/expr.test: * tests/info.test: 2005-05-24 Don Porter * library/init.tcl: Updated [unknown] to be sure the [return] * tests/init.test: options from an auto-loaded command are seen correctly by the caller. 2005-05-24 Daniel Steffen * tests/env.test: added DYLD_FRAMEWORK_PATH to the list of env vars that need to be handled specially. * macosx/Makefile: * macosx/README: * macosx/Tcl-Info.plist.in (new file): * unix/Makefile.in: * unix/configure.in: * unix/tcl.m4: * unix/tclUnixInit.c: moved all Darwin framework build support from macosx/Makefile into the standard unix configure/make buildsystem, the macosx/Makefile is no longer required to build Tcl.framework (but its functionality is still available for backwards compatibility). * unix/configure: autoconf-2.59 * generic/tclIOUtil.c (TclLoadFile): * generic/tclInt.h: * unix/tcl.m4: * unix/tclLoadDyld.c: added support for [load]ing .bundle binaries in addition to .dylib's: .bundle's can be [unload]ed (unlike .dylib's), and can be [load]ed from memory, e.g. directly from VFS without needing to be written out to a temporary location first. [Bug 1202209] * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 * generic/tclCmdMZ.c (Tcl_TimeObjCmd): change [time] called with a count > 1 to return a string with a float value instead of a rounded off integer. [Bug 1202178] * doc/expr.n: * doc/string.n: fixed roff syntax complaints from 'make html'. 2005-05-20 Don Porter * generic/tclParseExpr.c: Corrected parser to recognize all boolean literals accepted by Tcl_GetBoolean, including prefixes like "y" and "f", and to allow "eq" and "ne" as function names in the proper context. [Bug 1201589]. 2005-05-19 Donal K. Fellows * generic/tclBasic.c (TclEvalObjvInternal): Rewrite for greater clarity; although 'goto' is Bad, the contortions you have to go through to avoid it can be worse... 2005-05-19 Daniel Steffen * macosx/tclMacOSXNotify.c (Tcl_InitNotifier): fixed crashing CFRelease of runLoopSource in Tcl_InitNotifier (reported by Zoran): CFRunLoopAddSource doesn't CFRetain, so can only CFRelease the runLoopSource in Tcl_FinalizeNotifier. 2005-05-18 Don Porter * generic/tclBasic.c (Tcl_ExprBoolean): Rewrite as wrapper around Tcl_ExprBooleanObj. * generic/tclCmdMZ.c ([string is boolean/true/false]): Rewrite dropping string-based Tcl_GetBoolean call, so that internal reps are kept for subsequent quick boolean operations. * generic/tclExecute.c: Dropped most special handling of the "boolean" Tcl_ObjType, since that type should now be rarely encountered. * doc/BoolObj.3: Rewrite of documentation dropping many details about the internals of Tcl_Objs. Shorter documentation focuses on the function and use of the routines. * generic/tclInt.h: Revision to the "boolean" Tcl_ObjType, so that * generic/tclObj.c: only string values like "yes" and "false" are * tests/obj.test: kept as the "boolean" Tcl_ObjType. The string values "0" and "1" are kept as "int" Tcl_ObjType, which also produce quick calls to Tcl_GetBooleanFromObj(). Since this internal change means a Tcl_ConvertToType to a "boolean" Tcl_ObjType might not produce a Tcl_Obj of type "boolean", the registration of the "boolean" type is also removed. ***POTENTIAL INCOMPATIBILITY*** For callers of Tcl_GetObjType on the type name "boolean". 2005-05-17 Don Porter * generic/tclObj.c (TclInitObjSubsystem): Removed the * tests/listObj.test: registration of the Tcl_ObjType's "list", * tests/obj.test: "procbody", "index", "ensembleCommand", "localVarName", and "levelReference". The only reason to register a Tcl_ObjType is to have it returned by Tcl_GetObjType, and the only reason for that is to retrieve a (Tcl_ObjType *) to pass to Tcl_ConvertToType(). None of the types above can support a Tcl_ConvertToType() call; they panic. Better not to offer something than to lead users into a panic. ***POTENTIAL INCOMPATIBILITY*** For callers of Tcl_GetObjType on the type names listed above. 2005-05-15 Kevin Kenny * win/tclWin32Dll.c: conditioned definition of EXCEPTION_REGISTRATION structures on HAVE_NO_SEH, to fix a bug in buildability on MSVC. 2005-05-14 Daniel Steffen * generic/tclInt.decls: * generic/tclTest.c: * generic/tclUtil.c: * win/tclWin32Dll.c: fixed link error due to direct access by tclTest.c to the MODULE_SCOPE tclPlatform global: renamed existing TclWinGetPlatform() accessor to TclGetPlatform() and moved it to generic code so that it can be used by on all platforms where MODULE_SCOPE is enforced. * macosx/tclMacOSXBundle.c: * unix/tclUnixInit.c: * unix/tcl.m4 (Darwin): made use of CoreFoundation API configurable and added test of CoreFoundation availablility to allow building on ppc64, replaced HAVE_CFBUNDLE by HAVE_COREFOUNDATION; test for availability of Tiger or later OSSpinLockLock API. * unix/tclUnixNotfy.c: * unix/Makefile.in: * macosx/tclMacOSXNotify.c (new file): when CoreFoundation is available, use new CFRunLoop based notifier: allows easy integration with other event loops on Mac OS X, in particular the TkAqua Carbon event loop is now integrated via a standard tcl event source (instead of TkAqua upon loading having to finalize the exsting notifier and replace it with its custom version). [Patch 1202052] * tests/unixNotfy.test: don't run unthreaded tests on Darwin since notifier may be using threads even in unthreaded core. * unix/tclUnixPort.h: * unix/tcl.m4 (Darwin): test for thread-unsafe realpath during configure, as Darwin 7 and later realpath is threadsafe. * macosx/Makefile: enable configure caching. * unix/configure.in: wrap tclConfig.h header in #ifndef _TCLCONFIG so that it can be included more than once without warnings from gcc4.0 (as happens e.g. when including both tclInt.h and tclPort.h) * macosx/tclMacOSXBundle.c: * unix/tclUnixChan.c: * unix/tclLoadDyld.c: * unix/tclUnixInit.c: fixed gcc 4.0 warnings. * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 * generic/tclIntDecls.h: * generic/tclIntPlatDecls.h: * generic/tclStubInit.c: make genstubs 2005-05-13 Kevin Kenny * win/tclWin32Dll.c: Further rework of the SEH logic. All EXCEPTION_REGISTRATION records are now in the activation record rather than pushed on the stack. 2005-05-13 Don Porter * generic/tclBasic.c: Dropped the TCL_NO_MATH configuration. It's * generic/tclBinary.c: believed this has not been working in a long * generic/tclExecute.c: time. Tcl needs math.h. [RFE 1200680] * unix/Makefile.in: 2005-05-12 Kevin Kenny * doc/mathfunc.n: Changed NAME line to match the name of the page. 2005-05-11 Kevin Kenny [kennykb-numerics-branch] Resynchronized with the HEAD; at this checkpoint [-rkennykb-numerics-branch-20050511], the HEAD and kennykb-numerics-branch contain identical code. 2005-05-11 Kevin Kenny * generic/tclStrToD.c (TclStrToD, RefineResult, ParseNaN): Changed the code to cast 'char' to UCHAR explicitly when using ctype macros, to silence complaints from the Solaris compiler. 2005-05-10 Jeff Hobbs * unix/tclUnixFCmd.c: add lint attr to enum to satisfy strictly compliant compilers that don't like trailing ,s. * tests/string.test: string-10.[21-30] * generic/tclCmdMZ.c (Tcl_StringObjCmd): add extra checks to prevent possible UMR in unichar cmp function for string map. 2005-05-10 Kevin Kenny * generic/tclBinary.c (FormatNumber): Fixed a bug where NaN's resulted in reads of uninitialized memory when using 'd', 'q', or 'Q' format. * generic/tclStrToD.c (ParseNaN, TclFormatNaN): Added code to handle the peculiarities of HP's PA_RISC, which uses a different 'quiet' bit in NaN from everyone else. * libtommath/tommath_superclass.h: Corrected C++-style comment. 2005-05-10 Kevin Kenny Merged all changes on kennykb-numerics-branch back into the HEAD. TIP's 132 and 232 are now Final. 2005-05-10 Kevin Kenny [kennykb-numerics-branch] Merged changes from HEAD. 2005-05-10 Miguel Sofer * generic/tclExecute.c (ExponLong, ExponWide): * tests/expr.test (expr-23.34/35): fixed special case 'i**0' for i>0 [Bug 1198892] 2005-05-09 Kevin B. Kenny [kennykb-numerics-branch] * win/tclWin32Dll.c (TclpCheckStackSpace, TclWinCPUID): Reworked structured event handling to function even with -fomit-frame-pointers. 2005-05-08 Kevin B. Kenny [kennykb-numerics-branch] * generic/tclStrToD.c: Made code more portable by finding a workaround for MSVC's 'volatile' issue that does not require conditional compilation. * win/tclWin32Dll.c (TclWinCPUID): Removed structured event handling from the GCC code since (a) bad code is generated by the instruction scheduling with -O2, and (b) it's not needed on any reasonably modern CPU. 2005-05-07 Kevin B. Kenny [kennykb-numerics-branch] * generic/tclEvent.c: Moved initialization of tclStrToD.c's * generic/tclInt.h: static constants into a procedure called * generic/tclStrToD.c: from TclInitSubsystems to avoid double checked locking protocol. Cleaned up an issue where MSVC ignored the 'volatile' specifier, causing incorrect comparison of an underflowed number against zero. 2005-05-06 Jeff Hobbs * unix/tcl.m4, unix/configure: correct Solaris 10 (5.10) check and add support for x86_64 Solaris cc builds. 2005-05-05 Kevin B. Kenny [kennykb-numerics-branch] Merged with HEAD. 2005-05-05 Kevin B. Kenny * win/tclWinThrd.c: Corrected a compilation error on the --enable-threads configuration. 2005-05-05 Don Porter * generic/tclInt.decls: Converted TclMatchIsTrivial to a macro. * generic/tclInt.h: * generic/tclUtil.c: * generic/tclIntDecls.h: `make genstubs` * generic/tclStubInit.c: * generic/tclBasic.c: Added callers of TclMatchIsTrivial where a * generic/tclCmdIL.c: search can be done more efficiently when it is * generic/tclCompCmds.c:recognized that a pattern match is really an * generic/tclDictObj.c: exact match. [Patch 1076088] * generic/tclIO.c: * generic/tclNamesp.c: * generic/tclVar.c: * generic/tclCompCmds.c: Factored common efficiency trick into a macro named CompileWord. * generic/tclCompCmds.c: Replaced all instance of * generic/tclCompile.c: TCL_OUT_LINE_COMPILE with TCL_ERROR. * generic/tclInt.h: Now that we've eradicated the mistaken * tests/appendComp.test: notion of a "compile-time error", we can use the TCL_ERROR return code to signal any failure to produce bytecode. 2005-05-03 Don Porter * doc/DString.3: Eliminated use of identifier "string" in Tcl's * doc/Environment.3: public C API to avoid conflict/confusion with * doc/Eval.3: the std::string of C++. * doc/ExprLong.3, doc/ExprLongObj.3, doc/GetInt.3, doc/GetOpnFl.3: * doc/ParseCmd.3, doc/RegExp.3, doc/SetResult.3, doc/StrMatch.3: * doc/Utf.3, generic/tcl.decls, generic/tclBasic.c, generic/tclEnv.c: * generic/tclGet.c, generic/tclParse.c, generic/tclParseExpr.c: * generic/tclRegexp.c, generic/tclResult.c, generic/tclUtf.c: * generic/tclUtil.c, unix/tclUnixChan.c: * generic/tclDecls.h: `make genstubs` 2005-05-02 Don Porter * generic/tcl.decls: * generic/tclBasic.c: Simplified implementation of Tcl_ExprString. * tests/expr-old.test: * generic/tclDecls.h: `make genstubs` 2005-04-30 Daniel Steffen * unix/tclUnixNotfy.c: applied dkf's tkMacOSXNotify.c cleanup changes. 2005-04-29 Don Porter TIP#176 IMPLEMENTATION [Patch 1165695] * generic/tclUtil.c: Extended TclGetIntForIndex to recognize index formats including end+integer and integer+/-integer. * generic/tclCmdMZ.c: Extended the -start switch of [regexp] and [regsub] to accept all index formats known by TclGetIntForIndex. * doc/lindex.n: Updated docs to note new index formats. * doc/linsert.n, doc/lrange.n, doc/lreplace.n, doc/lsearch.n: * doc/lset.n, doc/lsort.n, doc/regexp.n, doc/regsub.n, doc/string.n: * tests/cmdIL.test: Updated tests. * tests/compile.test, tests/lindex.test, tests/linsert.test: * tests/lrange.test, tests/lreplace.test, tests/lsearch.test: * tests/lset.test, tests/regexp.test, tests/regexpComp.test: * tests/string.test, tests/stringComp.test, tests/util.test: 2005-04-28 Don Porter * tests/unixInit.test (7.1): Alternative fix for the 2004-11-11 commit. 2005-04-27 Don Porter * library/init.tcl: Corrected flaw in interactive command * tests/main.test: auto-completion. [Bug 1191409]. TIP#183 IMPLEMENTATION [Patch 577093] * generic/tclIOUtil.c (TclGetOpenModeEx): New routine. * generic/tclInt.h: * generic/tclIO.c (Tcl_OpenObjCmd): Support for "b" and * doc/open.n: "BINARY" in "access" argument to [open]. * tests/ioCmd.test: 2005-04-26 Kevin B. Kenny * generic/tclBinary.c (FormatNumber): Dredge the NaN out of the internal representation if Tcl_GetDoubleFromObj returns TCL_ERROR on a NaN. * generic/tclObj.c (Tcl_GetDoubleFromObj): Restored silent overflow/underflow behaviour that the merge of 2004-04-25 messed up. Thanks to Don Porter for calling attention to this bug. Also removed an uninitialised memory reference in this function that valgrind caught. Also changed to return TCL_ERROR on a pure NaN. * generic/tclStrToD.c (RefineResult): Added a test for the initial approximation being HUGE_VAL; this test avoids EDOM being returned from ldexp on some platforms on input values exceeding the floating point range. * tests/expr.test (expr-29.*, expr-30.*): Added further tests of overflow/underflow on input conversions. 2005-04-25 Kevin B. Kenny [kennykb-numerics-branch] Merged with HEAD. * doc/CrtMathFunc.n: Revised documentation for TIP 232 2005-04-25 Daniel Steffen * compat/string.h: fixed memchr() protoype for __APPLE__ so that we build on Mac OS X 10.1 again. * generic/tclNotify.c (TclFinalizeNotifier): fixed notifier not being finalized in unthreaded core (was testing for notifier initialization in current thread by checking thread id != 0 but thread id is always 0 in untreaded core). * win/tclWinNotify.c (Tcl_WaitForEvent): * unix/tclUnixNotfy.c (Tcl_WaitForEvent): don't call ScaleTimeProc for zero wait times (as specified in TIP 233). * unix/Makefile.in: added @PLAT_SRCS@ to SRCS and split out NOTIFY_SRCS from UNIX_SRCS for parity with UNIX_OBJS & NOTIFY_OBJS. * unix/tcl.m4 (Darwin): added configure checks for recently added linker flags -single_module and -search_paths_first to allow building with older tools (and on Mac OS X 10.1), use -single_module in SHLIB_LD and not just T{CL,K}_SHLIB_LD_EXTRAS, added unexporting from Tk of symbols from libtclstub to avoid duplicate symbol warnings, added PLAT_SRCS definition for Mac OS X, defined MODULE_SCOPE to __private_extern__. (SC_MISSING_POSIX_HEADERS): added caching of dirent.h check. * unix/configure: autoconf-2.59 2005-04-25 Kevin B. Kenny * library/tzdata/America/Boise: * library/tzdata/America/Chicago: * library/tzdata/America/Denver * library/tzdata/America/Indianapolis: * library/tzdata/America/Los_Angeles: * library/tzdata/America/Louisville: * library/tzdata/America/Managua: * library/tzdata/America/New_York: * library/tzdata/America/Phoenix: * library/tzdata/America/Port-au-Prince: * library/tzdata/America/Indiana/Knox: * library/tzdata/America/Indiana/Marengo: * library/tzdata/America/Indiana/Vevay: * library/tzdata/America/Kentucky/Monticello: * library/tzdata/America/North_Dakota/Center: * library/tzdata/Asia/Tehran: Olson's tzdata2005i. Corrects exact time at which Standard Time was adopted in the US (generally, noon, Standard Time, rather than noon, Local Mean Time). Adopts new civil rules for Nicaragua and Iran. 2005-04-25 Don Porter * library/init.tcl: Use "ni" and "in" operators. 2005-04-25 Miguel Sofer * generic/tclExecute.c: fix for [Bug 1189274]. 2005-04-24 Don Porter * generic/tclLiteral.c: Silence compiler warnings. * generic/tclObj.c: [Bug 1188863]. 2005-04-22 Don Porter The 2005-04-21 changes to Tcl_GetBooleanFromObj were done to bring it into agreement with its docs. Further investigation reveals it was the docs that were incorrect. * doc/BoolObj.3: Corrections to the documentation of Tcl_GetBooleanFromObj to bring it into agreement with what this public interface has always done, including noting the difference in function between Tcl_GetBooleanFromObj and Tcl_GetBoolean. * generic/tclGet.c: Revised Tcl_GetBoolean to no longer be a wrapper around Tcl_GetBooleanFromObj (different function!). * generic/tclObj.c: Removed TclGetTruthValueFromObj routine that was added yesterday. Revisions so that only Tcl_GetBoolean-approved values get the "boolean" Tcl_ObjType. This retains the fix for [Bug 1187123]. * tests/string.test: Test string-23.0 for Bug 1187123. * generic/tclInt.h: Revert most recent change. * generic/tclBasic.c: * generic/tclCompCmds.c: * generic/tclDictObj.c: * generic/tclExecute.c: * tests/obj.test: 2005-04-21 Don Porter * doc/GetInt.3: Convert argument "string" to "str" to agree with code. Also clarified a few details on int and double formats. * generic/tclGet.c: Radical code simplification. Converted Tcl_GetFoo() routines into wrappers around Tcl_GetFooFromObj(). Reduces code duplication, and the resulting potential for inconsistency. * generic/tclObj.c: Several changes: - Re-ordered error detection code so all values with trailing garbage receive a "not an integer" message instead of an "integer too large" message. - Removed inactive code meant to deal with strtoul* routines that fail to parse leading signs. All of them do, and if any are detected that do not, the correct fix is replacement with compat/strtoul*.c, not a lot of special care by the callers. - Tcl_GetDoubleFromObj now avoids shimmering away a "wideInt" intrep. - Fixed Tcl_GetBooleanFromObj to agree with its documentation and with Tcl_GetBoolean, accepting only "0" and "1" and not other numeric strings. [Bug 1187123] - Added new private routine TclGetTruthValueFromObj to perform the more permissive conversion of numeric values to boolean that is needed by the [expr] machinery. * generic/tclInt.h (TclGetTruthValueFromObj): New routine. * generic/tclExecute.c: Updated callers to call new routine. * generic/tclBasic.c: Updated callers to call new routine. * generic/tclCompCmds.c: Updated callers to call new routine. * generic/tclDictObj.c: Updated callers to call new routine. * tests/obj.test: Corrected bad tests that actually expected values like "47" and "0xac" to be accepted as booleans. * generic/tclLiteral.c: Disabled the code that forces some literals into the "int" Tcl_ObjType during registration. We can re-enable it if this change causes trouble, but it seems more sensible to let Tcl's "on-demand" shimmering rule, and not try to pre-guess things. 2005-04-20 Kevin B. Kenny [kennykb-numerics-branch] * doc/expr.n: * doc/mathfunc.n (new file): Revised documentation for TIP 232 2005-04-20 Don Porter * generic/tclGet.c (Tcl_GetInt): Corrected error that did not * generic/tclObj.c (Tcl_GetIntFromObj): permit 0x80000000 to be recognized as an integer on TCL_WIDE_INT_IS_LONG systems [Bug 1090869]. 2005-04-20 Kevin B. Kenny * generic/tclFileName.c: Silenced a compiler warning about '/*' within a comment. 2005-04-19 Don Porter * generic/tclBasic.c: Added unsupported command * generic/tclCmdAH.c: [::tcl::unsupported::EncodingDirs] to permit * generic/tclInt.h: query/set of the encoding search path at * generic/tclInterp.c: the script level. Updated init.tcl to make * library/init.tcl: use of the new command. Also updated several coding practices in init.tcl ("eq" for [string equal], etc.) 2005-04-19 Kevin B. Kenny * library/clock.tcl (Initialize): Put initialization code into a proc to avoid inadvertently clobbering global variables. [Bug 1185933] * tests/clock.test (clock-48.1): Added regression test for the above bug. Thanks to Ulrich Ring for reporting this bug. 2005-04-16 Miguel Sofer * generic/Var.c (Tcl_ArrayObjCmd - ARRAY_NAMES): fix Tcl_Obj leak. [Bug 1084111] 2005-04-16 Zoran Vasiljevic * generic/tclIOUtil.c: force clenaup of the interp result in TclLoadFile(). Some implementations of TclpFindSymbol() will seed the interp result with error message when unable to find the requested symbol (this is not considered to be an error). Set of changes correcting huge memory waste (not a leak) when a thread exits. This has been introduced in 8.4.7 within an attempt to correctly cleanup after ourselves when Tcl library is being unloaded with the Tcl_Finalize() call. This fixes the [Bug 1178445] * generic/tclInt.h: added prototypes for TclpFreeAllocCache() and TclFreeAllocCache() * generic/tclThreadAlloc.c: modified TclFinalizeThreadAlloc() to explicitly call TclpFreeAllocCache with the NULL-ptr as argument signalling cleanup of private tsd key used only by the threading allocator. * unix/tclUnixThrd.c: fixed TclpFreeAllocCache() to recognize when being called with NULL argument. This is a signal for it to clean up the tsd key associated with the threading allocator. * win/tclWinThrd.c: renamed TclWinFreeAllocCache to TclpFreeAllocCache and fixed to recognize when being called with NULL argument. This is a signal for it to clean up the tsd key associated with the threading allocator. 2005-04-13 Don Porter * tests/unixInit.test: Disabled obsolete tests and removed code * tests/encoding.test: that supported them. * generic/tclInterp.c: * library/init.tcl: Use auto-loading to bring in Tcl Module support * library/tclIndex: as needed. This reduces startup time by * library/tm.tcl: delaying this initialization to a later time. 2005-04-15 Miguel Sofer * generic/tclExecute.c: missing semicolons caused failure to compile with TCL_COMPILE_DEBUG. 2005-04-13 David Gravereaux * generic/tclIO.c (Tcl_SetChannelBufferSize): Lowest size limit * tests/io.test: changed from ten bytes to one byte. Need for * tests/iogt.test: this change was proven by Ross Cartlidge where [read stdin 1] was grabbing 10 bytes followed by starting a child process that was intended to continue reading from stdin. Even with -buffersize set to one, nine chars were getting lost by the buffersize over reading for the native read() caused by [read]. 2005-04-13 Don Porter * unix/tclUnixInit.c (TclpGetEncodingNameFromEnvironment): Reversed order of verifying candidate [encoding system] value, checking against a table in memory first before calling Tcl_GetEncoding and potentially scanning through the filesystem. Also ordered the table so that a binary search could be used within it. Improves startup time a bit more on some systems. 2005-04-13 Kevin B. Kenny * library/clock.n: Added a missing '--' on several [switch] commands to improve performance of [clock format] and related operations. [FRQ 1182459] 2005-04-13 Donal K. Fellows * doc/fcopy.n: Improved documentation on copying binary files, added an example and mentioned the use of [file copy]. * doc/fconfigure.n: Improved documentation of -encoding binary option. This is all following comments from Steve Manning on comp.lang.tcl that the current documentation was not clear. 2005-04-13 Miguel Sofer * generic/tclCompile.c:Commented out the functions TclPrintInstruction(), TclPrintObject() and TclPrintSource() when not debugging the compiler, as they are never called in that case. 2005-04-12 Don Porter * generic/tclInterp.c: Corrected bad syntax of Tcl_Panic() call. * generic/tclUtil.c (TclGetProcessGlobalValue): More robust handling of bad TclInitProcessGlobalValueProc behavior; an immediate panic rather than a mysterious crash later. * generic/tclEncoding.c: Several changes to the way the encodingFileMap cache is maintained. Previously, it was attempted to keep the file map filled and up to date with changes in the encoding search path. This contributed to slow startup times since it required an expensive "glob" operation to fill the cache. Now the validity of items in the cache are checked at the time they are used, so the cache is permitted to fall out of sync with the encoding search path. Only [encoding names] and Tcl_GetEncodingNames() now pay the full expense. [Bug 1177363] 2005-04-12 Kevin B. Kenny * compat/strstr.c: Added default definition of NULL to accommodate building on systems with badly broken headers. [Bug 1175161] 2005-04-11 Donal K. Fellows * tools/tclZIC.tcl: Rewrote to take advantage of more features of Tcl 8.5 (on which it was dependent anyway). Also added a [package require] line to formalize the relationship. 2005-04-11 Kevin Kenny [kennykb-numerics-branch] Merged with HEAD. Updated to libtommath 0.35. * generic/tclBasic.c: Attempted to repeat changes that applied to tclExecute.c in Miguel Sofer's commit of 2005-04-01, together with (possibly) a few more uses of his new object creation macros. Also plugged a memory leak in TclObjInvoke. [Bug 1180368] 2005-04-10 Kevin Kenny * library/tzdata/America/Montevideo: * library/tzdata/Asia/Almaty: * library/tzdata/Asia/Aqtau: * library/tzdata/Asia/Aqtobe: * library/tzdata/Asia/Baku: * library/tzdata/Asia/Jerusalem: * library/tzdata/Asia/Oral: * library/tzdata/Asia/Qyzylorda: * library/tzdata/Indian/Chagos: * library/tzdata/Indian/Cocos: Olson's tzdata2005h 2005-04-10 Don Porter * generic/tclBasic.c (TclObjInvoke): Plug memory leak. [Bug 1180368] 2005-04-09 Miguel Sofer * generic/tclExecute.c: fix possible leak of expansion Tcl_Objs 2005-04-09 Daniel Steffen * macosx/README: updated requirements for OS & developer tool versions and other small fixes/cleanup. * generic/tclListObj.c (Tcl_ListObjIndex): added missing NULL return when getting index from an empty list. * unix/tcl.m4 (Darwin): added -single_module linker flag to TCL_SHLIB_LD_EXTRAS and TK_SHLIB_LD_EXTRAS. * unix/configure: autoconf-2.59 2005-04-08 Don Porter * generic/tclInt.h (TclGetEncodingFromObj): New function to * generic/tclEncoding.c (TclGetEncodingFromObj): retrieve a Tcl_Encoding value, as well as cache it in the internal rep of a new "encoding" Tcl_ObjType. * generic/tclCmdAH.c (Tcl_EncodingObjCmd): Updated to call new function so that Tcl_Encoding's used by [encoding convert*] routines are not freed too quickly. [Bug 1077262] 2005-04-08 Donal K. Fellows * generic/tclCompCmds.c (TclCompileSwitchCmd): Rewritten to be able to handle the other form of [switch] and generate slightly simpler (but longer) code. 2005-04-06 Donal K. Fellows * doc/upvar.n, doc/unset.n, doc/tell.n, doc/tclvars.n, doc/subst.n: * doc/seek.n, doc/scan.n, doc/regsub.n, doc/registry.n, doc/regexp.n: * doc/read.n, doc/puts.n, doc/pkgMkIndex.n, doc/open.n, doc/lreplace.n: * doc/lrange.n, doc/load.n, doc/llength.n, doc/linsert.n, doc/lindex.n: * doc/lappend.n, doc/info.n, doc/gets.n, doc/format.n, doc/flush.n: * doc/fileevent.n, doc/file.n, doc/fblocked.n, doc/close.n: * doc/array.n, doc/Utf.3, doc/TraceVar.3, doc/StrMatch.3, doc/RegExp.3: * doc/PrintDbl.3, doc/OpenTcp.3, doc/OpenFileChnl.3, doc/Object.3: * doc/Notifier.3, doc/LinkVar.3, doc/IntObj.3, doc/Interp.3: * doc/GetOpnFl.3, doc/GetIndex.3, doc/Eval.3, doc/CrtMathFnc.3: * doc/CrtFileHdlr.3, doc/CrtCommand.3, doc/CrtChannel.3: * doc/Backslash.3: Purge old .VS/.VE macro instances. * tools/man2html2.tcl (IPmacro): Rewrote to understand what .IP really is (.IP and .TP are really just two ways of doing the same thing). Change below made this relevant. * doc/re_syntax.n: Change some uses of .TP to .IP to work around bugs in various *roff implementations. Also reworded the atom descriptions slightly. 2005-04-05 Don Porter * generic/tclExecute.c (ExprSrandFunc): Replaced incursions into the * generic/tclUtil.c (TclGetIntForIndex): intreps of numeric types with simpler calls of Tcl_GetIntFromObj and Tcl_GetLongFromObj, now that those routines are better behaved wrt shimmering. [Patch 1177219] 2005-04-05 Miguel Sofer * generic/tclInt.h: * generic/tclObj.c: Change in TclDecrRefCount and TclFreeObj, to speed up the freeing of simple Tcl_Obj [Patch 1174551] 2005-04-04 Miguel Sofer * generic/tclExecute.c: small opts in obj handling 2005-04-02 Miguel Sofer * generic/tclVar.c: converted a few function calls to macros. 2005-04-01 Miguel Sofer * doc/ListObj.3: * generic/tclBasic.c: * generic/tclCmdIL.c: * generic/tclConfig.c: * generic/tclExecute.c: * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclListObj.c: * generic/tclStubInit.c: * generic/tclVar.c: Changed the internal representation of lists to (a) reduce the malloc/free calls at list creation (from 2 to 1), (b) reduce the cost of handling empty lists (we now never create a list internal rep for them), (c) allow refcounting of the list internal rep. The latter permits insuring that the pointers returned by Tcl_ListObjGetElements remain valid even if the object shimmers away from its original list type. This is [Patch 1158008] * generic/tclExecute.c: * generic/tclInt.h: * generic/tclObj.c: * generic/tclStringObj.c: (1) defined new internal macros for creating and setting frequently used obj types (int,long, wideInt, double, string). Changed TEBC to use eg 'TclNewIntObj(objPtr, i)' to avoid the function call in 'objPtr = Tcl_NewIntObj(i)' (2) ExecEnv now stores two Tcl_Obj* pointing to the constants "0" and "1", for use by TEBC. (3) slight reduction in cost of INST_START_CMD 2005-03-31 Miguel Sofer * generic/tclExecute.c (INST_JUMP_TRUE/FALSE): replaced "test and branch" with "compute index into table" 2005-03-30 Donal K. Fellows * doc/FileSystem.3: Defined loadHandle argument. [Bug 1172401] 2005-03-29 Jeff Hobbs * win/tcl.m4, win/configure: do not require cygpath in macros to allow msys alone as an alternative. 2005-03-24 Don Porter * generic/tclCompile.h: Move the TclInterpReady() declaration from * generic/tclInt.h: tclCompile.h to tclInt.h. Should have been done as part of the 1115904 bug fix on 2005-03-18. * generic/tclThreadTest.c: Stop providing the phony package "Thread 1.0" when the [::testthread] command is defined. It's never used by anything, and conflicts with loading the real "Thread" package. 2005-03-18 Don Porter * generic/tclCompCmds.c (TclCompileIncrCmd): Corrected checks for immediate operand usage to permit leading space and sign characters. Restores more efficient bytecode for [incr x -1] that got lost in the CONST string reforms of Tcl 8.4. [Bug 1165671] * generic/tclBasic.c (Tcl_EvalEx): Restored recursion limit * generic/tclParse.c (TclSubstTokens): testing in nested command * tests/basic.test (basic-46.4): substitutions within direct * tests/parse.test (parse-19.*): script evaluation (Tcl_EvalEx) that got lost in the parser reforms of Tcl 8.1. Added tests for correct behavior. [Bug 1115904] 2005-03-15 Vince Darley * generic/tclFileName.c: * win/tclWinFile.c: * tests/winFCMd.test: fix to 'file pathtype' and 'file norm' failures on reserved filenames like 'COM1:', etc. 2005-03-15 Pat Thoyts * unix/tcl.m4: Updated the OpenBSD configuration and regenerated * unix/configure: the configure script. 2005-03-15 Kevin B. Kenny [kennykb-numerics-branch] Merged with HEAD. * generic/tclBasic.c (many): * generic/tclCompExpr.c (CompileMathFuncCall): * generic/tclCompile.h: * generic/tclExecute.c (many): * generic/tclParseExpr.c (ParsePrimaryExpr): * tests/compExpr-old.test: * tests/compExpr.test: * tests/compile.test: * tests/expr-old.test: * tests/expr.test: * tests/for.test: * tests/parseExpr.test: Initial implementation of TIP #232. * generic/tclObj.c (Tcl_DbNewBignumObj): Fixed typo that broke --enable-symbols=mem build * tests/binary.test (binary-40.3, binary-40.6): Corrected tests to allow NaN(7ffffffffffff). 2005-03-14 Miguel Sofer * generic/tclExecute.c: fixed INST_PUSH1's debugging code (wrong obj ref passed to TRACE_WITH_OBJ). 2005-03-14 Miguel Sofer * generic/tclCompile.c: fixed INST_RETURN's stack effect in tclInstructionTable (-1 instead of -2) 2005-03-10 Miguel Sofer * generic/tclCompCmds.c: removed debugging line 2005-03-10 Don Porter * generic/tclTrace.c (TclCheckInterpTraces): Corrected mistaken cast of ClientData to (TraceCommandInfo *) when not warranted. Thanks to Yuri Victorovich for the report. [Bug 1153871] * generic/tcl.h: Moved flag values TCL_TRACE_ENTER_EXEC and * generic/tclInt.h: TCL_TRACE_LEAVE_EXEC from public interface into private. Should be used only by internal workings of execution traces. 2005-03-09 Kevin B. Kenny [kennykb-numerics-branch] Merged from HEAD. * doc/PrintDbl.3: * doc/tclVars.n: Documented new semantics for tcl_precision. * generic/tclExecute.c (Tcl_ExecuteByteCode): Removed the check for division-by-zero on IEEE-754 machines. * generic/tclUtil.c (Tcl_PrintDouble): Corrected bug where numbers in the range [1e-4 .. 1.) were printed incorrectly. * tests/compExpr-old.test (compExpr-old-11.13): Revised test case for division by zero. * tests/expr-old.test (expr-34.11, expr-34.12): Revised test cases for overflow in pow() to deal with infinities. * tests/expr.test (expr-11.13, expr-29.1, expr-29.2): Revised test case for division by zero and for underflow on input conversions. * tests/parseExpr.test (parseExpr-16.11): Revised test case for overflow on input conversion. * tests/string.test (string-6.38 deleted): Removed test case for underflow on input conversion, which is no longer an error. * tests/util.test (util-10.*): Added test case for the bug in tclUtil.c 2005-03-08 Jeff Hobbs * win/makefile.vc: clarify necessary defined vars that can come from MSVC or the Platform SDK. 2005-03-07 Donal K. Fellows * doc/string.n: Minor typo. [Bug 1158247] 2005-03-07 Miguel Sofer * generic/tclExecute.c: new peephole optimisation for INST_PUSH1; fixed the peephole opt in INST_POP so that it is not used when TCL_COMPILE_DEBUG is defined. 2005-03-04 Kevin B. Kenny [kennykb-numerics-branch] * generic/tclCmdMZ.c: Changed [scan] to treat out-of-range floating point values as infinities and zeroes. * generic/tclExecute.c: Changed [expr] to be permissive about infinities, allowing them to propagate. * generic/tclGet.c: Changed Tcl_GetDouble to be permissive about over/underflow. * generic/tclObj.c: Changed SetDoubleFromAny to be permissive about over/underflow. * generic/tclParseExpr.c: Made [expr] permissive about input numbers out of range. 2005-03-03 Kevin B. Kenny [kennykb-numerics-branch] * generic/tclInt.h: * generic/tclStrToD.c (Tcl_DoubleDigits, TclFormatNaN): * generic/tclUtil.c (Tcl_PrintDouble): Changed the signature of TclDoubleDigits so that it accepts a pointer to the signum of the argument, and returns the signum via that pointer. Added very hacky code to handle IEEE signed zeroes in Tcl_DoubleDigits. (It can't be done other than as a hack until C9x; C89 simply doesn't deal with the concept of -0.0). Added output conversion of tagged NaN values. * generic/tclBinary.c (FormatNumber): Changed to allow [binary format] to handle NaN. * tests/binary.test (binary-60.1): Added a quick-n-dirty test to make sure that NaN's can be scanned and formatted. * generic/tclParseExpr.c (GetLexeme, ParseMaxDoubleLength): Modified so that tagged NaN (e.g., NaN(DEADBEEF)) can be recognized. 2005-03-02 Kevin B. Kenny [kennykb-numerics-branch] Merged with HEAD as of 2005-02-23. * generic/tclExecute.c: Broadened test for NaN to work on Windows. * generic/tclInt.h: * generic/tclStrToD.c (Tcl_DoubleDigits): * generic/tclUtil.c (Tcl_PrintDouble, TclPrecTraceProc): Added Tcl_DoubleDigits to format 'double' numbers with the minimum number of significant digits to yield correct rounding. Modified tcl_precision to accept 0 as a precision (meaning "minimum digits"), and made 0 the default. [TIP #132] * generic/tclObj.c: Made NaN's throw an error in Tcl_GetDoubleFromObj. * unix/Makefile.in: * win/Makefile.in: * win/makefile.vc: Added libtommath/bn_mp_init_set.c to the build. * libtommath/tommath.h (mp_iseven): Fixed a bug that caused zero to test 'odd'. * generic/tommath.h: Regenerated. * tests/binary.test: * tests/expr-old.test: * tests/expr.test: * tests/scan.test: Corrected a number of tests that depended on tcl_precision, and removed the {eformat} condition from tests that no longer require it. * tests/util.test: Corrected a number of tests that depended on tcl_precision, and removed the {eformat} condition from tests that no longer require it. Added a series of tests for correct rounding in Tcl_PrintDouble. [TIP #132]. 2005-03-01 David N. Welton * doc/CrtSlave.3: Changed to Tcl_Object to Tcl_Obj in the man page. 2005-02-24 Don Porter * library/tcltest/tcltest.tcl: Better use of [glob -types] to avoid * tests/tcltest.test: failed attempts to [source] a directory, and similar matters. Thanks to "mpettigr". [Bug 1119798] * library/tcltest/pkgIndex.tcl: Bump to tcltest 2.2.8 * unix/Makefile.in: * win/Makefile.in: 2005-02-23 Donal K. Fellows * doc/CrtChannel.3 (THREADACTIONPROC): Formatting fix. [Bug 1149605] 2005-02-17 Jeff Hobbs * win/tclWinFCmd.c (TraverseWinTree): use wcslen on wchar, not Tcl_UniCharLen. 2005-02-16 Miguel Sofer * doc/variable.n: fix for [Bug 1124160], variables are detected by [info vars] but not by [info locals]. 2005-02-11 Jeff Hobbs * unix/Makefile.in: remove SHLIB_LD_FLAGS (only for AIX, inlined into * unix/tcl.m4: SHLIB_LD). Combine AIX-* and AIX-5 branches in * unix/configure: SC_CONFIG_CFLAGS. Correct gcc builds for AIX-4+ and HP-UX-11. autoconf-2.59 gen'd. 2005-02-11 Miguel Sofer * tests/basic.test (basic-26.3): new test 2005-02-10 Miguel Sofer * generic/tclBasic.c (Tcl_EvalObjEx): * tests/basic.test (basic-26.2): preserve the arguments passed to TEOV in the pure-list branch, in case the list shimmers away. Fix for [Bug 1119369], reported by Peter MacDonald. 2005-02-10 Vince Darley * generic/tclFileName.c: fix for test failures introduced on 2005-01-17 [Bug 1119092] 2005-02-10 Donal K. Fellows * doc/binary.n: Made the documentation of sign bit masking and [binary scan] consistent. [Bug 1117017] 2005-02-08 David N. Welton * doc/CrtChannel.3: Typo: return->returns. 2005-02-06 Kevin B. Kenny [kennykb-numerics-branch] * generic/tclStrToD.c (TclStrToD, SafeLdExp): Added code to manage the FPU precision on gcc+x86. Enabled fast conversion of floats with small exponents now that precision is correct. * tests/expr.test: Corrected test for the smallest representible value to the right IEEE values. 2005-02-06 David N. Welton * doc/Thread.3: One-word grammar fix. 2005-02-05 David N. Welton * doc/Thread.3: Fixed sentence describing flags for Tcl_CreateThread. * doc/FileSystem.3: Cleaned up typo in Tcl_FSNewNativePath documentation. * generic/tclPathObj.c: Cleaned up typo in comment. 2005-02-03 Kevin B. Kenny [kennykb-numerics-branch] * generic/tclStrToD.c (TclStrToD, RefineResult, SafeLdExp): Added code to ensure that 'ldexp' is never called with a value that will underflow * tests/expr.test: Added tests for the smallest representible value, and rounding between it and zero. (The tests reflect current behaviour; plan is to change the specification of Tcl so that input conversion of doubles underflows silently.) 2005-02-02 Mo DeJong * generic/tclProc.c (TclInitCompiledLocals): Add check for type of the framePtr->procPtr->bodyPtr passed to TclInitCompiledLocals and panic if it is not the correct type. If the body of the proc is not of the compiled byte code type then the code will crash. This was discovered while tracking down a crash in Itcl, that crash is fixed by Itcl patch 1115085. 2005-02-01 Kevin B. Kenny [kennykb-numerics-branch] Merged with HEAD as of today. * generic/tclInt.decls: Changed numbers of new stubs to resolve a conflict. * generic/tclInt.h: Added new TclStrToD routine that replaces the native 'strtod' throughout Tcl. * generic/tclCmdMZ (Tcl_StringObjCmd): * generic/tclGet.c (Tcl_GetDouble): * generic/tclObj.c (SetBooleanFromAny, SetDoubleFromAny): * generic/tclParseExpr.c (GetLexeme): * generic/tclScan.c (Tcl_ScanObjCmd): Replaced all uses of the native 'strtod' with a TclStrToD routine that performs correct rounding and handles denormals. * generic/tclStrToD.c: (new file) New scanning function for extracting 'double' from a string that rounds correctly, and handles denormals and infinities. * unix/Makefile.in: * win/Makefile.in: * win/makefile.vc: Added tclStrToD.c and the tommath routines that support it. These changes represent a partial implementation of TIP #132. Output conversion of floating point numbers, and proper handling of infinities within expressions, still need to be addressed. 2005-02-01 Don Porter * generic/tclExecute.c (TclCompEvalObj): Removed stray statement left behind in prior code reorganization. 2005-01-31 Don Porter * unix/configure: autoconf-2.57 2005-01-30 Joe English * unix/configure.in: Restored two double-evals that were removed in the DBGX purge; these are still needed on some platforms to account for TCL_TRIM_DOTS. [Bug 1112654] * unix/configure: NOT REGENERATED: only have autoconf 2.59 here, need to find someone with autoconf 2.57. 2005-01-28 Jeff Hobbs * unix/configure, unix/tcl.m4: add solaris 64-bit gcc build support. [Bug 1021871] 2005-01-28 Donal K. Fellows * tests/expr-old.test (expr-old-37.2): Added test for [Bug 1109484] 2005-01-27 Jeff Hobbs * generic/tclBasic.c (Tcl_ExprBoolean, Tcl_ExprDouble) (Tcl_ExprLong): Fix to recognize Tcl_WideInt type. [Bug 1109484] 2005-01-26 Andreas Kupries TIP#218 IMPLEMENTATION * generic/tclDecls.h: Regenerated from tcl.decls. * generic/tclStubInit.c: * doc/CrtChannel.3: Documentation of extended API, * generic/tcl.decls: extended testsuite, and * generic/tcl.h: implementation. Removal of old * generic/tclIO.c: driver-specific TclpCut/Splice * generic/tclInt.h: functions. Replaced with generic * tests/io.test: thread-action calls through the * unix/tclUnixChan.c: new hooks. Update of all builtin * unix/tclUnixPipe.c: channel drivers to version 4. * unix/tclUnixSock.c: Windows drivers extended to * win/tclWinChan.c: manage thread state in a thread * win/tclWinConsole.c: action handler. * win/tclWinPipe.c: * win/tclWinSerial.c: * win/tclWinSock.c: 2005-01-25 Don Porter * library/auto.tcl: Updated [auto_reset] to clear auto-loaded commands in namespaces other than :: and to clear auto-loaded commands that do not happen to be procs. [Bug 1101670] ***POTENTIAL INCOMPATIBILITY*** 2005-01-25 Daniel Steffen * unix/tcl.m4 (Darwin): fixed bug with static build linking to dynamic library in /usr/lib etc instead of linking to static library earlier in search path. [Bug 956908] Removed obsolete references to Rhapsody. * unix/configure: autoconf-2.57 2005-01-21 Andreas Kupries * generic/tclStubInit.c: Regenerated the stubs support code from the * generic/tclDecls.h: modified tcl.decls (TIP #233, see below). * doc/GetTime.3: Implemented TIP #233, i.e. the * generic/tcl.decls: 'Virtualization of Tcl's Sense of Time'. * generic/tcl.h: Declared, implemented, and documented the * generic/tclInt.h: specified new API functions. Moved the * unix/tclUnixEvent.c: native (OS) access to time information * unix/tclUnixNotfy.c: into standard handler functions. Inserted * unix/tclUnixTime.c: hooks calling on the handlers where native * win/tclWinNotify.c: access was done before, and where scaling * win/tclWinTime.c: between domains (real/virtual) is required. 2005-01-21 Andreas Kupries * generic/tclThread.c: Typo police. Fixed some nits * generic/tclCmdAH.c: in header comments of functions. * generic/tclBasic.c: (Missing --). * generic/tclFileName.c: 2005-01-21 Donal K. Fellows * doc/FileSystem.3: Add missing ARGUMENTS section definitions for arguments to Tcl_FSLink. [Bug 1106272] 2005-01-21 Kevin B. Kenny [kennykb-numerics-branch] * unix/Makefile.in: Updated Makefile to build libtommath on Unix as well as Windows. [Bug 1106865] * generic/tclTestObj.c (TestbignumobjCmd): Silenced a compiler warning about a mismatched 'const'. 2005-01-20 Kevin B. Kenny [kennykb-numerics-branch] Development checkpoint. * compat/strtoll.c: Reverted to HEAD. * compat/strtoull.c: * doc/Ensemble.3: * generic/tclBasic.c: * generic/tclCmdIL.c: * generic/tclNamesp.c: * generic/tclPathObj.c: * generic/tclPort.h: * unix/configure: * unix/configure.in: * unix/tcl.m4: * win/configure: * win/configure.in: * win/rules.vc: * win/tcl.m4: * generic/tcl.h: Added declarations for bignum types, and for a 'bignumValue' in the Tcl_Obj structure. * generic/tclInt.h: Added declarations of interface procedures for memory allocation in libtommath. * generic/tcl.decls: Added new interface to bignum objects. * generic/tclInt.decls: Added internal stubs for bignum routines used by the test code in tclTestObj.c. * generic/tclDecls/h: Regen. * generic/tclIntDecls.h: * generic/tclStubInit.h: * tools/fix_tommath_h.tcl: (New file) Script to edit libtommath/tommath.h and produce generic/tommath.h so that storage classes, allocation routines, and data types conform to Tcl's conventions. * generic/tommath.h: (New file) Generated by the above. * generic/tclTomMath.h: (New file) Additional declarations to be included in tommath.h when building Tcl. * generic/tclTomMathInterface.c: (New file) Small 'glue' routines adapting tommath's API to Tcl. * libtommath/bn_fast_s_mp_mul_digs.c: * libtommath/bn_mp_mul_d.c: * libtommath/bn_mp_read_radix.c: * libtommath/tommath.h: Applied suggested changes from Tom St Denis that correct an off-by-one error in single-digit multiplication (leading to a pointer smash if uncorrected) and change the string argument to 'mp_read_radix' from 'char*' to 'const char*'. * libtommath/bn_mp_radix_size.c: Local patch to ensure that sufficient memory is requested even if the number has a single digit. * libtommath/bn_mp_read_radix.c: Local patch to return MP_VAL if the input string contains an invalid character. * generic/tclObj.c: Added accessor functions for bignums. * generic/tclTestObj.c: Added a 'testbignumobj' command to exercise the accessor functions for bignums. * win/Makefile.in: Added rules for making libtommath. 2005-01-19 Donal K. Fellows TIP#235 IMPLEMENTATION * doc/Ensemble.3: Documentation for the new public API. * generic/tclNamesp.c (Tcl_CreateEnsemble,...): Rename of * generic/tcl.decls: existing API into TIPped form. 2005-01-19 Mo DeJong * win/tclWinChan.c (FileCloseProc): Invoke TclpCutFileChannel() to remove a FileInfo from the thread local list before deallocating it. This should have been done via an earlier call to Tcl_CutChannel, but I was running into a crash in the next call to Tcl_CutChannel during the I/O finalization stage. 2005-01-18 Kevin Kenny * library/tzdata/GMT+0: * library/tzdata/GMT-0: * library/tzdata/GMT0: * library/tzdata/Greenwich: * library/tzdata/Navajo: * library/tzdata/Universal: * library/tzdata/Zulu: * library/tzdata/America/Asuncion: * library/tzdata/America/Rosario: * library/tzdata/Asia/Jerusalem: * library/tzdata/Brazil/Acre: Routine update per Olson's tzdata2005c. Removed links to links (Greenwich in several aliases; Navajo; Acre). Updated Paraguayan DST rules and "best guess" at this year's Israeli rules. 2005-01-17 Vince Darley * generic/tclFileName.c: fix for glob failure on Windows shares [Bug 1100542]. * doc/pkgMkIndex.n: added documentation that 'pkg_mkIndex -lazy' is not a good idea. [Bug 1101678] 2005-01-14 Donal K. Fellows * tests/compile.test (compile-17.1): Document known issue with binding time of compiled command interpretations in [expr]. * generic/tclIOUtil.c (TclFSFileAttrIndex): New helper function so that we don't need to hard-code attribute indexes. [Bug 1100671] 2005-01-13 Donal K. Fellows * doc/string.n: Removed the term 'set' from the documentation of the [string trim] commands, as it caused confusion. 2005-01-12 Donal K. Fellows * unix/tcl.m4 (SC_PATH_{TCL,TK}CONFIG): Added code to detect the case when the --with-tcl/--with-tk arguments point to the config scripts themselves and not their directory. If this is the case, they now complain but keep working. [FRQ 951247] * unix/configure: autoconf-2.57 2005-01-10 Joe English * unix/Makefile.in, unix/configure.in, unix/tcl.m4, * unix/tclConfig.sh.in, unix/dltest/Makefile.in: Remove ${DBGX}, ${TCL_DBGX} from Tcl build system [Patch 1081595]. * unix/configure: regenerated 2005-01-10 Donal K. Fellows * unix/tclUnixFCmd.c (TclUnixCopyFile): Convert u_int to unsigned to make clashes with types in standard C headers less of a problem. [Bug 1098829] 2005-01-09 Joe English * unix/tclUnixThrd.c, unix/tclUnixPort.h: Remove readdir_r() and related #ifdeffery (see [Bug 1095909]). * unix/tcl.m4, unix/tclConfig.h.in: Don't check for HAVE_READDIR_R. * unix/configure: Regenerated. 2005-01-06 Donal K. Fellows * library/http/http.tcl (http::mapReply): Significant performance enhancement by using [string map] instead of [regsub]/[subst], and update version requirement to Tcl8.4. [Bug 1020491] 2005-01-05 Donal K. Fellows * doc/lsearch.n, doc/re_syntax.n: Convert to other form of emacs mode control comment to prevent problems with old versions of man. [Bug 1085127] 2005-01-05 Pat Thoyts * tests/winDde.test: Fixed broken test result. 2005-01-05 Donal K. Fellows * generic/tclInt.h, generic/tclPort.h: Move the #include of tclConfig.h *first* before any reference to tcl.h so that the build configuration is loaded before the first reference to any system headers. Issue reported by Art Haas on tcl-core. 2005-01-04 Don Porter * tests/fCmd.test (fCmd-18.10): Added notNetworkFilesystem constraint. [Bug 456665] ****************************************************************** *** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2004" *** *** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003" *** *** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002" *** *** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" *** *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" *** *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" *** ****************************************************************** tcl8.6.5/ChangeLog.20020000644000175000017500000054236311555560472013740 0ustar sergeisergei2002-12-18 David Gravereaux * win/makefile.vc: some uses of xcopy swapped to the @$(CPY) macro. Reported by Joe Mistachkin . 2002-12-17 Jeff Hobbs * generic/tclNotify.c (TclFinalizeNotifier, Tcl_SetServiceMode): (Tcl_ThreadAlert): Check that the stub functions are non-NULL before calling them. They could be set to NULL by Tcl_SetNotifier. 2002-12-16 David Gravereaux * generic/tclPipe.c (TclCleanupChildren): * tests/winPipe.test: * win/tclWinPipe.c (Tcl_WaitPid): * win/tclWinTest.c: Gave Tcl_WaitPid the ability to return a Win32 exception code translated into a posix style SIG*. This allows [close] to report "CHILDKILLED" without the meaning getting lost in a truncated exit code. In TclCleanupChildren(), TclpGetPid() had to get moved to before Tcl_WaitPid() as the the handle is removed from the list taking away the ability to get the process id after the wait is done. This shouldn't effect the unix implimentaion unless waitpid is called with a pid of zero, meaning "any". I don't think it is.. 2002-12-13 Don Porter * unix/configure.in: Updated configure of CVS snapshots to reflect * win/configure.in: the 8.4.1.1 patchlevel. * unix/configure: autoconf * win/configure autoconf 2002-12-11 Don Porter * generic/tclProc.c (ProcessProcResultCode): Fix failure to propagate negative return codes up the call stack. [Bug 647307] * tests/proc.test (proc-6.1): Test for Bug 647307 * generic/tclParseExpr.c (TclParseInteger): Return 1 for the string "0x" (recognize leading "0" as an integer). [Bug 648441] * tests/parseExpr.test (parseExpr-19.1): Test for Bug 648441. 2002-12-09 Jeff Hobbs * win/tclWinThrd.c (TclpMasterUnlock): * generic/tclThread.c (TclFinalizeThreadData): TclpMasterUnlock must exist and be called unconditional of TCL_THREADS. [Bug 651139] 2002-12-08 David Gravereaux * win/tclWinSock.c (SocketThreadExitHandler, InitSockets): Check that the tsdPtr is valid before dereferencing as we call it from the exit handler, too [Bug 650353]. Another WSAStartup() loaded version comparison byte swap issue fixed. Although 0x0101 byte swapped is still 0x0101, properly claiming which is major/minor is more correct. 2002-12-06 Jeff Hobbs * generic/tclStubInit.c: regen * generic/tclIntPlatDecls.h: regen * generic/tclInt.decls: added TclWinResetInterface * win/tclWin32Dll.c (TclWinResetInterfaces): * win/tclWinInit.c (TclpSetInitialEncodings, WinEncodingsCleanup): add exit handler that resets the encoding information to a state where we can reuse Tcl. Following these changes, it is possible to reuse Tcl (following Tcl_FindExecutable or Tcl_CreateInterp) following a Tcl_Finalize. * generic/tclIOUtil.c (TclFinalizeFilesystem): reset statics to their original values on finalize to allow reuse of the library. 2002-12-04 David Gravereaux * win/tclWinPipe.c: reverted back to -r1.27 due to numerous test failures that need to be resolved first. The idea was good, but the details aren't. 2002-12-04 David Gravereaux * win/tclWinPipe.c (Tcl_WaitPid): When a process exits with an exception, pass this notice on to the caller with a SIG* code rather than truncating the exit code and missing the meaning. This allows TclCleanupChildren() to report "CHILDKILLED". This has a different behavior than unix in that closing the read pipe to a process sends the SIGPIPE signal which is returned as a SIGPIPE exit status. On windows, we send the process a CTRL_BREAK_EVENT and get back a CONTROL_C_EXIT which is documented to mean a SIGINT which seems wrong as a system, but is the correct exit status. 2002-12-04 Vince Darley * generic/tclIOUtil.c: fix to redirected 'load' in virtual filesystem for some Unix systems. * generic/tclEvent.c: the filesystem must be cleaned up before the encoding subsystem because it needs access to encodings. Fixes crash on exit observed in embedded applications. * generic/tclTestObj.c: patch omitted from previous change of 2002-11-13 2002-12-03 Jeff Hobbs * generic/tclStubLib.c (Tcl_InitStubs): prevent the cached check of tclStubsPtr to allow for repeated load/unload of the Tcl dll by hosting apps. [Bug 615304] 2002-12-03 David Gravereaux * win/tclAppInit.c (sigHandler): Protect from trying to close a NULL handle. * win/tclWinPipe.c (PipeClose2Proc, TclpCreateProcess): Send a real Win32 signal (CTRL_C_EVENT) when the read channel is brought down to alert the child to close on its side. Start the process with CREATE_NEW_PROCESS_GROUP to allow the ability to send these signals. The following test case now brings down the child without the use of an external [kill] command. % set p [open "|[info name]" w+] file8d5380 % pid $p 2876 % close $p <- now doesn't block in Tcl_WaitPid() % * win/tclWinPipe.c (PipeClose2Proc): Changed CTRL_C_EVENT to CTRL_BREAK_EVENT as it can't be ignored by the child and proved to work on [open "|netstat 1" w+] where CTRL_C_EVENT didn't. 2002-11-27 David Gravereaux * win/tclWinPort.h: Don't turn off winsock prototypes! TclX didn't like it. Even though the core doesn't use the prototypes, do offer them. * win/tclWinSock.c: Removed shutdown() from the function table as it wasn't referenced anywhere and cleaned-up some casting that that wasn't needed. * win/tclWinSock.c: WSAStartup() loaded version comparison error which resulted in 2.0 looking less than 1.1. * win/tclWinChan.c (Tcl_MakeFileChannel): return of DuplicateHandle() incorrectly used. [Bug 618852] 2002-11-26 Jeff Hobbs * generic/tclEncoding.c (TclFinalizeEncodingSubsystem): properly cleanup all encodings by using Tcl_FirstHashEntry in the while loop. * unix/Makefile.in (valgrind): add simple valgrind target * tests/exec.test: unset path var to allow singleproc testing * generic/tclInterp.c (AliasCreate): preserve/release interps to prevent possible FMR error in bad alias cases. 2002-11-26 David Gravereaux * win/tclWinPort.h: * win/tclWinSock.c: This patch does two things: 1) Cleans-up the winsock typedefs by using the typedefs provided by winsock2.h. This has no effect on how winsock is initialized; just makes the source code easier to read. [Patch 561305 561301] 2) Revamps how the socket message handler thread is brought up and down to allow for cleaner exits without the use of TerminateThread(). TerminateThread is evil. No attempt has been made to resolve [Bug 593810] which may need a new channel driver version for adding a registering function within the transfered thread to init the handler thread. IOW, initialization of the TSD structure is getting bypassed through the thread extension's [thread::transfer] command. 2002-11-26 David Gravereaux * win/tclWinConsole.c: * win/tclWinPipe.c: * win/tclWinSerial.c: * win/tclWinSock.c: * win/tclWinThrd.c: * win/tclWinTime.c: General cleanup of all worker threads used by the channel drivers. Eliminates the normal case where the worker thread is terminated ('cept the winsock one). Instead, use kernel events to signal a clean exit. Only when the worker thread is blocked on an I/O call is the thread terminated. Essentially, this makes all other channel worker threads behave like the PipeReaderThread() function for it's cleaner exit behavior. This appears to fix [Bug 597924] but needs 3rd party confirmation to close the issue. 2002-11-26 Mo DeJong * win/README: Update msys build env URL. This release #4 build both tcl and tk without problems. 2002-11-22 Jeff Hobbs * library/init.tcl: code cleanup to reduce use of * library/opt/optparse.tcl: string compare * tests/interp.test: interp-14.4 * generic/tclInterp.c (TclPreventAliasLoop): prevent seg fault when creating an alias command over the interp name. [Bug 641195] 2002-11-18 Jeff Hobbs * generic/tclUtil.c (SetEndOffsetFromAny): handle integer offset after the "end-" prefix. * generic/get.test: * generic/string.test: * generic/tclObj.c (SetIntFromAny, SetWideIntFromAny): * generic/tclGet.c (TclGetLong, Tcl_GetInt): simplify sign handling before calling strtoul(l). [Bug 634856] 2002-11-18 David Gravereaux * win/tclWinThrd.c (Tcl_CreateThread/TclpThreadExit): Fixed improper compiler macros that missed the VC++ compiler. This resulted in VC++ builds using CreateThread()/ExitThread() in place of the proper _beginthreadex()/_endthreadex(). This was a large error and am surprised I missed seeing it earlier. 2002-11-13 Jeff Hobbs * generic/regexpComp.test: added tests 22.* * generic/tclCompCmds.c (TclCompileRegexpCmd): add left and right anchoring (^ and $) recognition and check starting or ending .* to extend the number of REs that can be compiled to string match or string equal. 2002-11-13 Vince Darley * generic/tclCmdMZ.c: * tests/trace.test: applied patch from Hemang Levana to fix [Bug 615043] in execution traces with 'return -code error'. * generic/tclTestObj.c: * tests/stringObj.test: added 'knownBug' test for [Bug 635200] * generic/tclStringObj.c: corrected typos in comments * generic/tclFileName.c: * tests/fileName.test: applied patch for bug reported against tclvfs concerning handling of Windows serial ports like 'com1', 'lpt3' by the virtual filesystem code. * doc/RegExp.3: clarification of the 'extendMatch' return values. 2002-11-11 Jeff Hobbs * generic/tclUtil.c (Tcl_Backslash): use TclUtfToUniChar. (Tcl_StringCaseMatch): use TclUtfToUniChar and add further optimizations for the one-byte/char case. * generic/tclUtf.c: make use of TclUtfToUniChar macro throughout the functions, and add extra optimization to Tcl_NumUtfChars for one-byte/char case. * generic/tclVar.c (DisposeTraceResult, CallVarTraces): add proper static declarations. * generic/tclStringObj.c (Tcl_GetCharLength): optimize for the ascii char case. (Tcl_GetUniChar): remove unnecessary use of Tcl_UtfToUniChar. (FillUnicodeRep): Use TclUtfToUniChar. * generic/tclHash.c (HashStringKey): move string++ lower to save an instruction. * generic/tclExecute.c (TclExecuteByteCode): improve INST_STR_CMP to use memcmp in the one-byte/char case, also use direct index for INST_STR_INDEX in that case. * generic/tclEncoding.c (UtfToUtfProc, UtfToUnicodeProc): (TableFromUtfProc, EscapeFromUtfProc): Use TclUtfToUniChar. (UnicodeToUtfProc, TableToUtfProc): add 1-byte char optimizations for Tcl_UniCharToUtf call. These improve encoded channel conversion speeds by up to 20%. * tests/split.test: added 1-char string split tests * generic/tclCmdMZ.c (Tcl_SplitObjCmd): Use TclUtfToUniChar. Also added a special case for single-ascii-char splits. (Tcl_StringObjCmd): Use TclUtfToUniChar. For STR_RANGE, support getting ranges of ByteArrays (reverts change from 2000-05-26). (TraceExecutionProc) add proper static declaration. * generic/tclInt.h: add macro version of Tcl_UtfToUniChar (TclUtfToUniChar) that does the one-byte utf-char check without calling Tcl_UtfToUniChar, for use by the core. This brings notable speedups for primarily ascii string handling. * generic/tcl.h (TCL_PATCH_LEVEL): bump to 8.4.1.1 for patchlevel only. This interim number will only be reflected by [info patchlevel]. 2002-11-11 Kevin Kenny * doc/Tcl.n: Corrected indentation of the new language. Oops. 2002-11-10 Kevin Kenny * doc/Tcl.n: Added language to the Endekalogue to make it clear that substitutions always take place from left to right. [Bug 635644] 2002-11-06 Mo DeJong * changes: Note TclInExit TclInThreadExit changes. * generic/tclEvent.c (TclInExit, TclInThreadExit): Split out functionality of TclInExit to make it clear which one should be called in each situation. * generic/tclInt.decls: Declare TclInThreadExit. * generic/tclIntDecls.h: Regen. * generic/tclStubInit.c: Regen. * mac/tclMacChan.c (StdIOClose): * unix/tclUnixChan.c (FileCloseProc): * win/tclWinChan.c (FileCloseProc): * win/tclWinConsole.c (ConsoleCloseProc): * win/tclWinPipe.c (TclpCloseFile): * win/tclWinSerial.c (SerialCloseProc): Invoke the new TclInThreadExit method instead of TclInExit. 2002-11-06 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_CONFIG_CFLAGS): Generate a fatal configure error if no ar program can be found on the path. [Bug 582039] * win/configure: Regen. * win/configure.in: Check that AR, RANLIB, and RC are found on the path when building with gcc. 2002-11-03 David Gravereaux * win/tclAppInit.c: Calls Registry_Init() and Dde_Init() when STATIC_BUILD and TCL_USE_STATIC_PACKAGES macros are set. * win/makefile.vc: * win/rules.vc: linkexten option now sets the TCL_USE_STATIC_PACKAGES macro which also adds the registry and dde object files to the link of the shell. [Patch 479697] Also factored some additional macros that will be helpful for extension authors. Version grepping of tcl.h will need to be added to complete this. * win/buildall.vc.bat: Added more descriptive commentary. 2002-11-01 David Gravereaux * win/tclWinReg.c: Changed the Tcl_PkgProvide() line to declare the registry extension at version 1.1 from 1.0. 2002-10-31 Andreas Kupries * library/word.tcl: Changed $tcl_platform to $::tcl_platform to avoid possible scope trouble. 2002-10-29 Vince Darley * win/tclWinInt.h: * win/tclWin32Dll.c: added comments about certain NULL function pointers which will be filled in when Tcl_FindExecutable is called, so that users don't report invalid bugs on this topic. (No code changes at all). 2002-10-29 Daniel Steffen * unix/tclLoadDyld.c (TclpFindSymbol): pass all dyld error messages upstream [Bug 627546]. 2002-10-28 Andreas Kupries * library/dde/pkgIndex.tcl: * library/reg/pkgIndex.tcl: Changed the hardwired debug suffix (d) to the correct suffix (g). 2002-10-28 Don Porter * library/auto.tcl: Converted the Mac-specific [package unknown] * library/init.tcl: behavior to use a chaining mechanism to extend * library/package.tcl: the default [tclPkgUnknown]. [Bug 627660] * library/tclIndex: [Patch 624509] (steffen) 2002-10-26 David Gravereaux * win/makefile.vc: xcopy on NT 4.0 doesn't support the /Y switch (overwrite). Added logic to handle this. [Bug 618019] 2002-10-23 Donal K. Fellows * generic/tclInt.h: Removed definitions of obsolete HistoryEvent and HistoryRev structures (the history mechanism has been written in Tcl for some time now.) 2002-10-22 Jeff Hobbs *** 8.4.1 TAGGED FOR RELEASE *** * changes: updated for 8.4.1 release * win/Makefile.in: removed @MEM_DEBUG_FLAGS@ subst. * win/configure: regen * win/configure.in: removed SC_ENABLE_MEMDEBUG call * win/tcl.m4: replaced SC_ENABLE_MEMDEBUG with a more intelligent SC_ENABLE_SYMBOLS that takes yes|no|mem|compile|all as options now. 2002-10-22 Daniel Steffen * library/auto.tcl (tcl_findLibrary): * library/package.tcl (tclPkgUnknown): on macosx, search inside the Resources/Scripts subdirectory of any potential package directory. * macosx/Tcl.pbproj/project.pbxproj: add standard Frameworks dirs to TCL_PACKAGE_PATH make argument. * unix/tclUnixInit.c (TclpSetVariables): on macosx, add embedded framework dirs to tcl_pkgPath: @executable_path/../Frameworks and @executable_path/../PrivateFrameworks (if they exist), as well as the dirs in DYLD_FRAMEWORK_PATH (if set). [Patch 624509] use standard MAXPATHLEN instead of literal 1024 2002-10-22 Donal K. Fellows * doc/StringObj.3, doc/Object.3: Documented that Tcl_Obj's standard string form is a modified UTF-8; apparently, this was not mentioned anywhere in the main docs, and lead to [Bug 624919]. 2002-10-21 Daniel Steffen * macosx/Tcl.pbproj/project.pbxproj: bumped version to 8.4.1 * generic/tcl.h: Added reminder comment to edit macosx/Tcl.pbproj/project.pbxproj when version number changes. 2002-10-18 Jeff Hobbs * library/reg/pkgIndex.tcl: * win/configure: * win/configure.in: * win/Makefile.in: * win/makefile.vc: * win/makefile.bc: Updated to reg1.1 * doc/registry.n: Added support for broadcasting changes to the * tests/registry.test: registry Environment. Noted proper code in the * win/tclWinReg.c: docs. [Patch 625453] * unix/Makefile.in (dist): add any mac/tcl*.sea.hqx files 2002-10-17 Don Porter * generic/tclVar.c: Fixed code that check for proper # of args to * tests/var.test: [array names]. Added test. [Bug 624755] 2002-10-16 Jeff Hobbs * win/configure: add workaround for cygwin windres * win/tcl.m4 (SC_CONFIG_CFLAGS): problem. [Patch 624010] (howell) 2002-10-15 Jeff Hobbs * README: added archives.tcl.tk note * unix/configure: * unix/tcl.m4: Correct AIX-5 ppc build flags. Correct HP 11 64-bit gcc building. [Patch 601051] (martin) 2002-10-15 Vince Darley * generic/tclCmdMZ.c: * tests/trace.test: applied patch from Hemang Levana to fix [Bug 615043] in execution traces with idle tasks firing. 2002-10-14 Jeff Hobbs * generic/tclEnv.c (Tcl_PutEnv): correct possible mem leak. [Patch 623269] (brouwers) 2002-10-11 Donal K. Fellows * generic/tcl.h: Need a different strategy through the maze of #defines to let people building with Cygwin build correctly. Also made some comments less misleading... 2002-10-10 Jeff Hobbs * README: fixed minor nits [Bug 607776] (virden) * win/configure: * win/tcl.m4: enable USE_THREAD_ALLOC (new threaded allocator) by default in cygwin configure on Windows. 2002-10-10 Don Porter * doc/Tcl.n: Clarified that namespace separators are legal in the variable names during $-subtitution. [Bug 615139] * doc/regexp.n: Typo correction. Thanks Ronnie Brunner. [Bug 606826] 2002-10-10 Vince Darley * unix/tclLoadAout.c * unix/tclLoadDl.c * unix/tclLoadDld.c * unix/tclLoadDyld.c * unix/tclLoadNext.c * unix/tclLoadOSF.c * unix/tclLoadShl.c * win/tclWinLoad.c: allow either full paths or simply dll names to be specified when loading files (the latter will be looked up by the OS on your PATH/LD_LIBRARY_PATH as appropriate). Fixes [Bug 611108] 2002-10-09 Jeff Hobbs * unix/README: doc'ed --enable-symbols options. * unix/Makefile.in: removed @MEM_DEBUG_FLAGS@ subst. * unix/configure: regen * unix/configure.in: removed SC_ENABLE_MEMDEBUG call * unix/tcl.m4: replaced SC_ENABLE_MEMDEBUG with a more intelligent SC_ENABLE_SYMBOLS that takes yes|no|mem|compile|all as options now. 2002-10-09 Kevin B. Kenny * win/tclWinTime.c: Added code to set an exit handler that terminates the thread that calibrates the performance counter, so that the thread won't outlive unloading the Tcl DLL. [Bug 620735] 2002-10-09 Donal K. Fellows * doc/binary.n: More clarification of [binary scan]'s behaviour. 2002-10-09 Daniel Steffen * generic/tclIntDecls.h: fixed botched regen. 2002-10-09 Daniel Steffen * generic/tclInt.decls: made TclSetPreInitScript() declaration generic as it is used on mac & aqua as well. * generic/tclIntDecls.h: * generic/tclStubInit.c: regen. * generic/tclCompile.h: added prototype for TclCompileVariableCmd. * mac/tclMacPort.h: removed incorrect definitions and obsolete definitions. * mac/tclMacChan.c: removed obsolete GetOpenMode() and replaced associated constants with the analogues (they existing defs were inconsistent with which was causing havoc when Tcl_GetOpenMode was used instead of private GetOpenMode). * mac/tclMacFCmd.c: removed GenerateUniqueName(), use equivalent (and identically named) routine from MoreFiles instead. * mac/tclMacLoad.c: CONSTification, fixes to Vince's last changes. * mac/tclMacFile.c: * mac/tclMacTest.c: * mac/tclMacUnix.c: CONSTification. * mac/tclMacOSA.c: CONSTification, sprintf fixes, UH 3.4.x changes; fix for missing autoname token from TclOSACompileCmd. (bdesgraupes) * mac/AppleScript.html(AppleScript delete): doc fix. (bdesgraupes) * mac/tcltkMacBuildSupport.sea.hqx: updated MoreFiles to 1.5.3, updated build instructions for 8.4. * mac/tclMacProjects.sea.hqx: rebuilt archive. 2002-10-09 Donal K. Fellows * doc/Alloc.3: Added a note to mention that attempting to allocate a zero-length block can return NULL. [Tk Bug 619544] 2002-10-04 Donal K. Fellows * doc/binary.n: Doc improvements [Patch 616480] * tests/fCmd.test, tests/winFCmd.test: * tools/eolFix.tcl, tools/genStubs.tcl: [file exist] -> [file exists] Thanks to David Welton. 2002-10-03 Don Porter * doc/tcltest.n: fixed typo [Bug 618018]. Thanks to "JJM". 2002-10-03 Donal K. Fellows * tools/man2help2.tcl: * tests/http.test, tests/httpd, tests/httpold.test: * tests/env.test, tests/binary.test, tests/autoMkindex.test: * library/init.tcl, library/http/http.tcl: [info exist] should really be [info exists]. [Bug 602566] * doc/lsearch.n: Better specification of what happens when -sorted is mixed with other options. [Bug 617816] 2002-10-01 Jeff Hobbs * generic/tclProc.c (TclCreateProc): mask out VAR_UNDEFINED for precompiled locals to support 8.3 precompiled code. (Tcl_ProcObjCmd): correct 2002-09-26 fix to look for tclProcBodyType. 2002-10-01 Donal K. Fellows * doc/socket.n: Mentioned that ports may be specified as serivce names as well as integers. [Bug 616843] 2002-09-30 Jeff Hobbs * generic/tclCompCmds.c (TclCompileRegexpCmd): correct the checking for bad re's that didn't terminate the re string. Resultant compiles were correct, but much slower than necessary. 2002-09-29 David Gravereaux * win/tclAppInit.c: Added proper exiting conditions using Win32 console signals. This handles the existing lack of a Ctrl+C exit to call exit handlers when built for thread support. Also, properly handles exits from other conditions such as CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals. In all cases, exit handlers will be called. [Bug 219355] * win/makefile.vc: Added missing tclThreadAlloc.c to the build rules and defines USE_THREAD_ALLOC when TCL_THREADS is defined to get the new behavior by default. 2002-09-27 Don Porter * README: Bumped to version 8.4.1 to avoid confusion of * generic/tcl.h: CVS snapshots with the actual 8.4.0 release. * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf * win/configure: 2002-09-26 Jeff Hobbs * unix/configure: regen. * unix/tcl.m4: improve AIX-4/5 64bit compilation support. * generic/tclProc.c (Tcl_ProcObjCmd): correct overeager optimization of noop proc to handle the precompiled case. (sofer) * unix/ldAix (nmopts): add -X32_64 to make it work for 32 or 64bit mode compilation. * library/encoding/koi8-u.enc: removed extraneous spaces that confused encoding reader. [Bug 615115] * unix/Makefile.in: generate source dists with -src designator and do not generate .Z anymore (just .gz and .zip). 2002-09-18 Mumit Khan Added basic Cygwin support. * win/tcl.m4 (SC_PATH_TCLCONFIG): Support one-tree build. (SC_PATH_TKCONFIG): Likewise. (SC_PROG_TCLSH): Likewise. (SC_CONFIG_CFLAGS): Assume real Cygwin port and remove -mno-cygwin flags. Add -mwin32 to extra_cflags and extra_ldflags. Remove ``-e _WinMain@16'' from LDFLAGS_WINDOW. * win/configure.in: Allow Cygwin build. (SEH test): Define to be 1 instead of empty value. (EXCEPTION_DISPOSITION): Add test. * win/configure: Regenerate. * generic/tcl.h: Don't explicitly define __WIN32__ for Cygwin, let the user decide whether to use Windows or POSIX personality. (TCL_WIDE_INT_TYPE, TCL_LL_MODIFIER, struct Tcl_StatBuf): Define for Cygwin. * generic/tclEnv.c (Tcl_CygwinPutenv): putenv replacement for Cygwin. * generic/tclFileName.c (Tcl_TranslateFileName): Convert POSIX to native format. (TclDoGlob): Likewise. * generic/tclPlatDecls.h (TCHAR): Define for Cygwin. * win/tclWinPort.h (putenv, TclpSysAlloc, TclpSysFree, (TclpSysRealloc): Define for Cygwin. 2002-09-26 Daniel Steffen * macosx/Makefile: preserve environment value of INSTALL_ROOT. When embedding only use deployment build. Force relink before embedded build to ensure new linker flags are picked up. * macosx/Tcl.pbproj/project.pbxproj: add symbolic links to debug lib, stub libs and tclConfig.sh in framework toplevel. Configure target dependency fix. Fix to 'clean' action. Added private tcl headers to framework. Install tclsh symbolic link. Html doc build works when no installed tclsh available. Made html doc structure in framework more like in Apple frameworks. 2002-09-24 Donal K. Fellows * unix/tcl.m4 (SC_TCL_64BIT_FLAGS): Yet more robust 64-bit value detection to close [Bug 613117] on more systems. * generic/tclCompile.c (TclPrintSource): More CONSTifying. * generic/tclExecute.c (EvalStatsCmd): Object-ify to reduce warnings. Thanks to 'CoderX2' on the chat for bringing this to my attention... * unix/tcl.m4: Forgot to define TCL_WIDE_INT_IS_LONG at the appropriate moment. I believe this is the cause of [Bug 613117] * doc/lset.n: Changed 'list' to 'varName' for consistency with lappend documentation. Thanks to Glenn Jackman [Bug 611719] 2002-09-22 Don Porter * library/tcltest/tcltest.tcl: Corrected [puts -nonewline] within test bodies. Thanks to Harald Kirsch. [Bug 612786, Patch 612788] Also corrected reporting of body return code. Thanks to David Taback [Bug 611922] * library/tcltest/pkgIndex.tcl: Bump to version 2.2.1. * tests/tcltest.test: added tests for these bugs. 2002-09-15 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_CONFIG_CFLAGS): Add PEEK_XCLOSEIM define under Linux. This is used by Tk to double check that an X input context is cleaned up before it is closed. 2002-09-12 David Gravereaux * win/coffbase.txt: Added BLT to the virtual base address listings table should BLT's build tools decide to use it. 2002-09-12 Daniel Steffen * generic/tcl.h: * mac/tclMacApplication.r: * mac/tclMacLibrary.r: * mac/tclMacResource.r: unified use of the two equivalent resource compiler header inclusion defines RC_INVOKED and RESOURCE_INCLUDED, now use RC_INVOKED throughout. 2002-09-10 Mo DeJong * unix/README: Add note about building extensions with the same compiler Tcl was built with. [Tk Bug 592096] 2002-09-10 Daniel Steffen * macosx/Tcl.pbproj/project.pbxproj: disabled building html documentation during embedded build. 2002-09-10 Daniel Steffen * unix/Makefile.in: added DYLIB_INSTALL_DIR variable for macosx and set it to default value ${LIB_RUNTIME_DIR} * unix/tcl.m4 (Darwin): use DYLIB_INSTALL_DIR instead of LIB_RUNTIME_DIR in the -install_name argument to ld. * unix/configure: regen. * macosx/Tcl.pbproj/project.pbxproj: * macosx/Makefile: added support for building Tcl as an embedded framework, i.e. using an dyld install_name containing @executable_path/../Frameworks via the new DYLIB_INSTALL_DIR unix/Makefile variable. 2002-09-10 Jeff Hobbs *** 8.4.0 TAGGED FOR RELEASE *** 2002-09-06 Don Porter * doc/file.n: Format correction, and clarified [file normalize] returns an absolute path. * doc/tcltest.n: Added examples section, as long promised. 2002-09-06 Reinhard Max * tests/tcltest.test: Added nonRoot flag to tests 8.3, 8.4, and 8.12. 2002-09-05 Don Porter * doc/tcltest.n: Clarified phrasing. * generic/tclBasic.c (TclRenameCommand,CallCommandTraces): * tests/trace.test (trace-27.1): Corrected memory leak when a rename trace deleted the command being traced. Test added. Thanks to Hemang Lavana for the fix. [Bug 604609] * generic/tclVar.c (TclDeleteVars): Corrected logic for setting the TCL_INTERP_DESTROYED flag when calling variable traces. [Tk Bug 605121] 2002-09-04 Miguel Sofer * generic/tclVar.c (DeleteArray): leak plug [Bug 604239]. Thanks to dkf and dgp for the long and difficult discussion in the chat. 2002-09-03 Jeff Hobbs * generic/tclVar.c (Tcl_UpVar2): code cleanup to not use goto * unix/configure: remove -pthread from LIBS on FreeBSD in thread * unix/tcl.m4: enabled build. [Bug 602849] 2002-09-03 Miguel Sofer * generic/tclInterp.c (AliasCreate): a Tcl_Obj was leaked on error return from TclPreventAliasLoop. 2002-09-03 Daniel Steffen * macosx/Tcl.pbproj/project.pbxproj: Bumped version number to 8.4.0 and updated copyright info. 2002-09-03 Miguel Sofer * generic/tclVar.c (Tcl_UpVar2): a Tcl_Obj was being leaked on error return from TclGetFrame. 2002-09-03 Don Porter * changes: Updated changes for 8.4.0 release. 2002-09-02 Jeff Hobbs * unix/tclUnixFile.c (TclpObjLink): removed unnecessary/unfreed extra native char*. * unix/tclUnixChan.c (Tcl_MakeTcpClientChannel): make sure to init flags field of TcpState ptr to 0. * unix/configure: * unix/tcl.m4: added 64-bit gcc compilation support on HP-11. [Patch 601051] (martin) * README: Bumped version number to 8.4.0 * generic/tcl.h: * tools/tcl.wse.in: * unix/configure: * unix/configure.in: * unix/tcl.spec: * win/README.binary: * win/configure: * win/configure.in: * generic/tclInterp.c (SlaveCreate): make sure that the memory and checkmem commands are initialized in non-safe slave interpreters when TCL_MEM_DEBUG is used. [Bug 583445] * win/tclWinConsole.c (ConsoleCloseProc): only wait on writable pipe if there was something to write. This may prevent infinite wait on exit. * tests/exec.test: marked exec-18.1 unixOnly until the Windows incompatability (in the test, not the core) can be resolved. * tests/http.test (http-3.11): added close $fp that was causing an error on Windows because the file was not closed before deleting. * unix/tclUnixInit.c (Tcl_MacOSXGetLibraryPath): made this static function only appear when HAVE_CFBUNDLE is defined. 2002-08-31 Daniel Steffen * unix/tcl.m4: added TK_SHLIB_LD_EXTRAS analogue of existing TCL_SHLIB_LD_EXTRAS for linker settings only used when linking Tk. * unix/configure: regen 2002-08-31 Daniel Steffen *** macosx-8-4-branch merged into the mainline [Patch 602770] *** * generic/tcl.decls: added new macosx specific entry to stubs table. * tools/genStubs.tcl: added generation of platform guards for macosx. This is a little more complex than it seems, because MacOS X IS "unix" plus a little bit, for the purposes of Tcl. BUT unfortunately, Tk uses "unix" to mean X11. So added platform keys for macosx (the little added to "unix"), "aqua" and "x11" to distinguish these for Tk. * generic/tcl.h: added a #ifnded RESOURCE_INCLUDED so that tcl.h can be passed to the resource compiler. * generic/tcl.h: * generic/tclNotify.c: added a few Notifier procs, to be able to modify more bits of the Tcl notifier dynamically. Required to get Mac OS X Tk to live on top of the Tcl Unix threaded notifier. Changes the size of the Tcl_NotifierProcs structure, but doesn't move any elements around. * unix/tclUnixNotfy.c: moved the call to Tcl_ConditionNotify till AFTER we are done mucking with the pointer swap. Fixes cases where the thread waiting on the condition wakes & accesses the waitingListPtr before it gets reset, causing a hang. * library/auto.tcl (tcl_findLibrary): added checking the directories in the tcl_pkgPath for library files on macosx to enable support of the standard Mac OSX library locations. * unix/Makefile.in: * unix/configure.in: * unix/tcl.m4: added MAC_OSX_DIR. Added PLAT_OBJS to the OBJS: there are some MacOS X specific files now for Tcl, and when I get the resource & applescript stuff ported over, and restore support for FindFiles, etc, there will be a few more. Added LD_LIBRARY_PATH_VAR configure variable to avoid having to set all possible LD_LIBRARY_PATH analogues on all platforms. LD_LIBRARY_PATH_VAR is "LD_LIBRARY_PATH" by default, "LIBPATH" on AIX, "SHLIB_PATH" on HPUX and "DYLD_LIBRARY_PATH" on Mac OSX. Added configure option to package Tcl as a framework on Mac OSX. * macosx/tclMacOSXBundle.c (new): support for finding Tcl extension packaged as 'bundles' in the standard Mac OSX library locations. * unix/tclUnixInit.c: added support for findig the tcl script library inside Tcl packaged as a framework on Mac OSX. * macosx/Tcl.pbproj/jingham.pbxuser (new): * macosx/Tcl.pbproj/project.pbxproj (new): project for Apple's ProjectBuilder IDE. * macosx/Makefile (new): simple makefile for building the project from the command line via the ProjectBuilder tool 'pbxbuild'. * unix/configure: * generic/tclStubInit.c: * generic/tclPlatDecls.h: regen 2002-08-29 Andreas Kupries * win/tclWinThrd.c (TclpFinalizeThreadData, TclWinFreeAllocCache): Applied patch for [Bug 599428], provided by Miguel Sofer . 2002-08-28 David Gravereaux * generic/tclEnv.c: * unix/configure.in: * win/tclWinPort.h: putenv() on some systems copies the buffer rather than taking reference to it. This causes memory leaks and is know to effect mswindows (msvcrt) and NetBSD 1.5.2 . This patch tests for this behavior and turns on -DHAVE_PUTENV_THAT_COPIES=1 when approriate. Thanks to David Welton for assistance. [Bug 414910] * unix/configure: regen'd 2002-08-28 Donal K. Fellows * doc/eval.n: Added mention of list command and corrected "SEE ALSO". * unix/configure.in: Cache handling of ac_cv_type_socklen_t was wrong. [Bug 600931] reported by John Ellson. Fixed by putting the brackets where they belong. 2002-08-26 Miguel Sofer * generic/tclCompCmds.c: fix for [Bug 599788] (error in element name causing segfault), reported by Tom Wilkason. Fixed by copying the tokens instead of the source string. 2002-08-26 Miguel Sofer * generic/tclThreadAlloc.c: small optimisation, reducing the new allocator's overhead. 2002-08-23 Miguel Sofer * generic/tclObj.c (USE_THREAD_ALLOC): fixed leak [Bug 597936]. Thanks to Zoran Vasiljevic. 2002-08-23 Miguel Sofer * generic/tclThreadAlloc.c (USE_THREAD_ALLOC): moving objects between caches as a block, instead of one-by-one. 2002-08-22 Miguel Sofer * generic/tclBasic.c: * generic/tclCmdMZ.c: fix for freed memory r/w in delete traces [Bug 589863], patch by Hemang Lavana. 2002-08-20 Andreas Kupries * win/Makefile.in (CFLAGS): * unix/Makefile.in (MEM_DEBUG_FLAGS): Added usage of @MEM_DEBUG_FLAGS@. * win/configure.in: * unix/configure.in: Added usage of SC_ENABLE_MEMDEBUG. * win/tcl.m4: * unix/tcl.m4: Added macro SC_ENABLE_MEMDEBUG. Allows a user of configure to (de)activate memory validation and debugging (TCL_MEM_DEBUG). No need to modify the makefile anymore. 2002-08-20 Don Porter * generic/tclCkalloc.c: CONSTified MemoryCmd and CheckmemCmd. * README: Bumped version number to 8.4b3 to distinguish * generic/tcl.h: HEAD from the 8.4b2 release. * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/README.binary: * win/configure.in: * unix/configure: autoconf * win/configure: * library/http/http.tcl: Corrected installation directory of * library/msgcat/msgcat.tcl: the package tcltest 2.2. Added * library/opt/optparse.tcl: comments in other packages to remind * library/tcltest/tcltest.tcl: that installation directories need * unix/Makefile.in: updates to match increasing version * win/Makefile.in: numbers. [Bug 597450] * win/makefile.bc: * win/makefile.vc: 2002-08-19 Andreas Kupries * unix/tclUnixTest.c (TestfilehandlerCmd): Changed readable/writable to the more common readable|writable. Fixes [Bug 596034] reported by Larry Virden . 2002-08-16 Donal K. Fellows * tests/fCmd.test: Added test to make sure that the cause of the problem is detectable with an unpatched Tcl. * doc/ObjectType.3: Added note on the root cause of this problem to the documentation, since it is possible for user code to trigger this sort of behaviour too. * generic/tclIOUtil.c (SetFsPathFromAny): Objects should only have their old representation deleted when we know that we are about to install a new one. This stops a weird TclX bug under Linux with certain kinds of memory debugging enabled which essentally came down to a double-free of a string. 2002-08-14 Miguel Sofer * generic/tclInt.h: * generic/tclObj.c: (code cleanup) factored the parts in the macros TclNewObj() / TclDecrRefCount() into a common part for all memory allocators and two new macros TclAllocObjStorage() / TclFreeObjStorage() that are specific to each allocator and fully describe the differences. Removed allocator-specific code from tclObj.c by using the macros. 2002-08-12 Miguel Sofer * generic/tclCmdMZ.c: fixing UMR in delete traces, [Bug 589863]. 2002-08-08 David Gravereaux * tools/man2help.tcl: Fixed $argv handling bug where if -bitmap wasn't specified $argc was off by one. 2002-08-08 Miguel Sofer * tests/uplevel.test: added 6.1 to test [uplevel] with shadowed commands [Bug 524383] * tests/subst.test: added 5.8-10 as further tests for [Bug 495207] 2002-08-08 Don Porter * tests/README: Noted removal of defs.tcl. 2002-08-08 Jeff Hobbs * doc/lsearch.n: corrected lsearch docs to use -inline in examples. *** 8.4b2 TAGGED FOR RELEASE *** * tests/fCmd.test: * tests/unixFCmd.test: updated tests for new link copy behavior. * generic/tclFCmd.c (CopyRenameOneFile): changed the behavior to follow links to endpoints and copy that file/directory instead of just copying the surface link. This means that trying to copy a link that has no endpoint (danling link) is an error. [Patch 591647] (darley) (CopyRenameOneFile): this is currently disabled by default until further issues with such behavior (like relative links) can be handled correctly. * tests/README: slight wording improvements 2002-08-07 Miguel Sofer * docs/BoolObj.3: added description of valid string reps for a boolean object. [Bug 584794] * generic/tclObj.c: optimised Tcl_GetBooleanFromObj and SetBooleanFromAny to avoid parsing the string rep when it can be avoided. [Bugs 584650, 472576] 2002-08-07 Miguel Sofer * generic/tclCompile.h: * generic/tclObj.c: making tclCmdNameType static ([Bug 584567], Don Porter). 2002-08-07 Miguel Sofer * generic/tclObj.c (Tcl_NewObj): added conditional code for USE_THREAD_ALLOC; objects allocated through Tcl_NewObj() were otherwise being leaked. [Bug 587488] reported by Sven Sass. 2002-08-06 Daniel Steffen * generic/tclInt.decls: * unix/tclUnixThrd.c: Added stubs and implementations for non-threaded build for the tclUnixThrd.c procs TclpReaddir, TclpLocaltime, TclpGmtime and TclpInetNtoa. Fixes link errors in stubbed & threaded extensions that include tclUnixPort.h and use any of the procs readdir, localtime, gmtime or inet_ntoa (e.g. TclX 8.4) [Bug 589526] * generic/tclIntPlatDecls.h: * generic/tclStubInit.c: Regen. 2002-08-05 Don Porter * library/tcltest/tcltest.tcl: The setup and cleanup scripts are now * library/tcltest/pkgIndex.tcl: skipped when a test is skipped, fixing * tests/tcltest.test: [Bug 589859]. Test for bug added, and corrected tcltest package bumped to version 2.2. * generic/tcl.decls: Restored Tcl_Concat to return (char *). Like * generic/tclDecls.h: Tcl_Merge, it transfers ownership of a dynamic * generic/tclUtil.c: allocated string to the caller. 2002-08-04 Don Porter * doc/CmdCmplt.3: Applied Patch 585105 to fully CONST-ify all * doc/Concat.3: remaining public interfaces of Tcl. Notably, * doc/CrtCommand.3: the parser no longer writes on the string it * doc/CrtSlave.3: is parsing, so it is no longer necessary for * doc/CrtTrace.3: Tcl_Eval() to be given a writable string. Also * doc/Eval.3: the refactoring of the Tcl_*Var* routines by * doc/ExprLong.3: by Miguel Sofer is included, so that the * doc/LinkVar.3: "part1" argument for them no longer needs to * doc/ParseCmd.3: be writable either. * doc/SetVar.3: * doc/TraceVar.3: * doc/UpVar.3: Compatibility support has been enhanced so * generic/tcl.decls: that a #define of USE_NON_CONST will remove * generic/tcl.h: all possible source incompatibilities with the * generic/tclBasic.c: 8.3 version of the header file(s). The new * generic/tclCmdMZ.c: #define of USE_COMPAT_CONST now does what * generic/tclCompCmds.c:USE_NON_CONST used to do -- disable only those * generic/tclCompExpr.c:new CONST's that introduce irreconcilable * generic/tclCompile.c: incompatibilities. * generic/tclCompile.h: * generic/tclDecls.h: Several bugs are also fixed by this patch. * generic/tclEnv.c: [Bugs 584051,580433] [Patches 585105,582429] * generic/tclEvent.c: * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclInterp.c: * generic/tclLink.c: * generic/tclObj.c: * generic/tclParse.c: * generic/tclParseExpr.c: * generic/tclProc.c: * generic/tclTest.c: * generic/tclUtf.c: * generic/tclUtil.c: * generic/tclVar.c: * mac/tclMacTest.c: * tests/expr-old.test: * tests/parseExpr.test: * unix/tclUnixTest.c: * unix/tclXtTest.c: * win/tclWinTest.c: 2002-08-01 Miguel Sofer * generic/tclExecute.c: bugfix (reading freed memory). Testsuite passed on linux/i386, compile-13.1 hung on linux/alpha. 2002-08-01 Miguel Sofer * generic/tclExecute.c: added a reference count for the complete execution stack, instead of Tcl_Preserve/Tcl_Release. 2002-08-01 Mo DeJong * generic/tclCkalloc.c (TclFinalizeMemorySubsystem): Don't lock the ckalloc mutex before invoking the Tcl_DumpActiveMemory function since it also locks the same mutex. This code is only executed when "memory onexit filename" has been executed and Tcl is compiled with -DTCL_MEM_DEBUG. 2002-08-01 Reinhard Max * win/tclWinPort.h: The windows headers don't provide socklen_t, so we have to do it. 2002-07-31 Miguel Sofer * generic/tclInt.h (USE_THREAD_ALLOC): for unshared objects, TclDecrRefCount now frees the internal rep before the string rep - just like the non-macro Tcl_DecrRefCount/TclFreeObj [Bug 524802]. For the other allocators the fix was done on 2002-03-06. 2002-07-31 Miguel Sofer * generic/tclInterp.c: signed/unsigned comparison warning fixed (Vince Darley). 2002-07-31 Donal K. Fellows * unix/tcl.m4 (SC_BUGGY_STRTOD): Enabled caching of test results. * unix/tcl.m4 (SC_BUGGY_STRTOD): Solaris 2.8 still has a buggy strtod() implementation; make sure we detect it. * tests/expr.test (expr-22.*): Marked as non-portable because it seems that these tests have an annoying tendency to fail in unexpected ways. [Bugs 584825, 584950, 585986] 2002-07-30 Andreas Kupries * tests/io.test: * generic/tclIO.c (WriteChars): Added flag to break out of loop if nothing of the input is consumed at all, to prevent infinite looping of called with a non-UTF-8 string. Fixes Bug 584603 (partially). Added new test "io-60.1". Might need additional changes to Tcl_Main so that unprintable results are printed as binary data. 2002-07-29 Mo DeJong * unix/Makefile.in: Use CC_SEARCH_FLAGS instead of LD_SEARCH_FLAGS when linking with ${CC}. * unix/configure: Regen. * unix/configure.in: Don't subst CC_SEARCH_FLAGS or LD_SEARCH_FLAGS since this is now done in tcl.m4. * unix/tcl.m4 (SC_CONFIG_CFLAGS): Document and set CC_SEARCH_FLAGS whenever LD_SEARCH_FLAGS is set. [Patch 588290] 2002-07-29 Reinhard Max * unix/tcl.m4 (SC_SERIAL_PORT): Fixed detection for cases when configure's stdin is not a tty. * unix/tclUnixPort.h: * generic/tclIOSock.c: Changed size_t to socklen_t in socket-related function calls. * unix/configure.in: Added test and fallback definition for socklen_t. * unix/configure: generated. 2002-07-29 Miguel Sofer * generic/tclObj.c: fixed a comment * generic/tcl.h: * generic/tclBasic.c: * generic/tclInterp.c: added the new flag TCL_EVAL_INVOKE to the interface of the Tcl_Eval* functions, removing the TCL_EVAL_NO_TRACEBACK added yesterday: alias invocations not only require no tracebacks, but also look up the command name in the global scope - see new test interp-9.4 * tests/interp.test: added 9.3 to test for safety of aliases to hidden commands, 9.4 to test for correct command lookup scope. 2002-07-29 Donal K. Fellows * generic/regc_locale.c (cclass): [[:xdigit:]] is only a defined concept on western characters, so should not allow any unicode digit, and hence number of ranges in [[:xdigit:]] is fixed. * tests/reg.test: Added test to detect the bug. * generic/regc_cvec.c (newcvec): Corrected initial size value in character vector structure. [Bug 578363] Many thanks to pvgoran@users.sf.net for tracking this down. 2002-07-28 Miguel Sofer * generic/tcl.h: * generic/tclBasic.c: added the new flag TCL_EVAL_NO_TRACEBACK to the interface of the Tcl_Eval* functions. Modified the error message for too many nested evaluations. * generic/tclInterp.h: changed the Alias struct to be of variable length and store the prefix arguments directly (instead of a pointer to a Tcl_Obj list). Made AliasObjCmd call Tcl_EvalObjv instead of TclObjInvoke - thus making aliases trigger execution traces [Bug 582522]. * tests/interp.test: * tests/stack.test: adapted to the new error message. * tests/trace.test: added tests for aliases firing the exec traces. 2002-07-27 Mo DeJong * unix/Makefile.in: Revert fix for Tcl bug 529801 since it was incorrect and broke the build on other systems. Fix [Bug 587299]. Add MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL, SHLIB_LD_FLAGS, SHLIB_LD_LIBS, CC_SEARCH_FLAGS, LD_SEARCH_FLAGS, and LIB_FILE variables to support more generic library build/install rules. * unix/configure: Regen. * unix/configure.in: Move AC_PROG_RANLIB into tcl.m4. Move shared build test and setting of MAKE_LIB and MAKE_STUB_LIB into tcl.m4. Move subst of a number of variables into tcl.m4 where they are defined. * unix/tcl.m4 (SC_ENABLE_SYMBOLS, SC_CONFIG_CFLAGS): Subst vars where they are defined. Add MAKE_LIB, MAKE_STUB_LIB, INSTALL_LIB, and INSTALL_STUB_LIB rules to deal with the ugly details of running ranlib on static libs at build and install time. Replace TCL_SHLIB_LD_EXTRAS with SHLIB_LD_FLAGS and use it when building a shared library. * unix/tclConfig.sh.in: Add TCL_CC_SEARCH_FLAGS. 2002-07-26 Miguel Sofer * generic/tclExecute.c: fixed Tcl_Obj leak in code corresponding to the macro NEXT_INST_V(x, 0, 1) [Bug 587495]. 2002-07-26 Miguel Sofer * generic/tclVar.c (TclObjLookupVar): leak fix and improved comments. 2002-07-26 Jeff Hobbs * generic/tclVar.c (TclLookupVar): removed early returns that prevented the parens from being restored. Also removed goto label as it was not necessary. 2002-07-24 Miguel Sofer * generic/tclExecute.c: * tests/expr-old.test: fix for erroneous error messages in [expr], [Bug 587140] reported by Martin Lemburg. 2002-07-25 Joe English * generic/tclProc.c: fix for [Tk Bug 219218] "error handling with bgerror in Tk" 2002-07-24 Miguel Sofer * generic/tclExecute.c: restoring full TCL_COMPILE_DEBUG functionality. 2002-07-24 Don Porter * tests/unixInit.test: relaxed unixInit-3.1 to accept iso8859-15 as a valid C encoding. [Bug 575336] 2002-07-24 Miguel Sofer * generic/tclExecute.c: restoring the tcl_traceCompile functionality while I repair tcl_traceExec. The core now compiles and runs also under TCL_COMPILE_DEBUG, but execution in the bytecode engine can still not be traced. 2002-07-24 Daniel Steffen * unix/Makefile.in: * unix/configure.in: corrected fix for [Bug 529801]: ranlib only needed for static builds on Mac OS X. * unix/configure: Regen. * unix/tclLoadDyld.c: fixed small bugs introduced by Vince, implemented library unloading correctly (needs OS X 10.2). 2002-07-23 Joe English * doc/OpenFileChnl.3: (Updates from Larry Virden) * doc/open.n: * doc/tclsh.1: Fix section numbers in Unix man page references. * doc/lset.n: In EXAMPLES section, include command to set the initial value used in subsequent examples. * doc/http.n: Package version updated to 2.4. 2002-07-23 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_CONFIG_CFLAGS): Enable 64 bit compilation when using the native compiler on a 64 bit version of IRIX. [Bug 219220] 2002-07-23 Mo DeJong * unix/Makefile.in: Combine ranlib tests and avoid printing unless ranlib is actually run. 2002-07-23 Mo DeJong * unix/tcl.m4 (SC_PATH_X): Set XINCLUDES to "" instead of "# no special path needed" or "# no include files found" when x headers cannot be located. 2002-07-22 Vince Darley * generic/tclIOUtil.c: made tclNativeFilesystem static (since 07-19 changes removed its usage elsewhere), and added comments about its usage. * generic/tclLoad.c: * generic/tcl.h: * generic/tcl.decls: * doc/FileSystem.3: converted last load-related ClientData parameter to Tcl_LoadHandle opaque structure, removing a couple of casts in the process. * generic/tclInt.h: removed tclNativeFilesystem declaration since it is now static again. 2002-07-22 Donal K. Fellows * tests/expr.test (expr-22.*): Added tests to help detect the corrected handling. * generic/tclExecute.c (IllegalExprOperandType): Improved error message generated when attempting to manipulate Inf and NaN values. * generic/tclParseExpr.c (GetLexeme): Allowed parser to recognise 'Inf' as a floating-point number. [Bug 218000] 2002-07-21 Don Porter * tclIOUtil.c: Silence compiler warning. [Bug 584408]. 2002-07-19 Vince Darley * generic/tclIOUtil.c: fix to GetFilesystemRecord * win/tclWinFile.c: * unix/tclUnixFile.c: fix to subtle problem with links shown up by latest tclkit builds. 2002-07-19 Mo DeJong * unix/configure: * unix/configure.in: * win/configure: * win/configure.in: Add AC_PREREQ(2.13) in an attempt to make it more clear that the configure scripts must be generated with autoconf version 2.13. [Bug 583573] 2002-07-19 Vince Darley * unix/Makefile.in: fix to build on MacOS X [Bug 529801], bug report and fix from jcw. 2002-07-19 Donal K. Fellows * win/tclWinSerial.c (no_timeout): Made this variable static. * generic/tclExecute.c, generic/tclCompile.c, generic/tclBasic.c: * generic/tclCompile.h (builtinFuncTable, instructionTable): Added prefix to these symbols because they are visible outside the Tcl library. * generic/tclCompExpr.c (operatorTable): * unix/tclUnixTime.c (tmKey): * generic/tclIOUtil.c (theFilesystemEpoch, filesystemWantToModify, filesystemIteratorsInProgress, filesystemOkToModify): Made these variables static. * unix/tclUnixFile.c: Renamed nativeFilesystem to * win/tclWinFile.c: tclNativeFilesystem and declared * generic/tclIOUtil.c: it properly in tclInt.h * generic/tclInt.h: * generic/tclUtf.c (totalBytes): Made this array static and const. * generic/tclParse.c (typeTable): Made this array static and const. (Tcl_ParseBraces): Simplified error handling case so that scans are only performed when needed, and flags are simpler too. * license.terms: Added AS to list of copyright holders; it's only fair for the current gatekeepers to be listed here! * tests/cmdMZ.test: Renamed constraint for clarity. [Bug 583427] Added tests for the [time] command, which was previously only indirectly tested! 2002-07-18 Vince Darley * generic/tclInt.h: * generic/tcl.h: * */*Load*.c: added comments on changes of 07/17 and replaced clientData with Tcl_LoadHandle in all locations. * generic/tclFCmd.c: * tests/fileSystem.test: fixed a 'knownBug' with 'file attributes ""' * tests/winFCmd.test: * tests/winPipe.test: * tests/fCmd.test: * tessts/winFile.test: added 'pcOnly' constraint to some tests to make for more useful 'tests skipped' log from running all tests on non-Windows platforms. 2002-07-17 Miguel Sofer * generic/tclBasic.c (CallCommandTraces): delete traces now receive the FQ old name of the command. [Bug 582532] (Don Porter) 2002-07-18 Vince Darley * tests/ioUtil.test: added constraints to 1.4,2.4 so they don't run outside of tcltest. [Bugs 583276, 583277] 2002-07-17 Miguel Sofer * generic/tclVar.c (DupParsedVarName): nasty bug fixed, reported by Vince Darley. 2002-07-17 Miguel Sofer * generic/tclVar.c (TclPtrIncrVar): missing CONST in declarations, inconsistent with tclInt.h. Thanks to Vince Darley for reporting, boo to gcc for not complaining. 2002-07-17 Vince Darley * generic/tclInt.h: * generic/tclIOUtil.c: * generic/tclLoadNone.c: * unix/tclLoadAout.c: * unix/tclLoadDl.c: * unix/tclLoadDld.c: * unix/tclLoadDyld.c: * unix/tclLoadNext.c: * unix/tclLoadOSF.c: * unix/tclLoadShl.c: * mac/tclMacLoad.c: * win/tclWinLoad.c: modified to move more functionality to the generic code and avoid duplication. Partial replacement of internal uses of clientData with opaque Tcl_LoadHandle. A little further work still needed, but significant changes are done. 2002-07-17 D. Richard Hipp * library/msgcat/msgcat.tcl: fix a comment that was causing problems for programs (ex: mktclapp) that embed the initialization scripts in strings. 2002-07-17 Miguel Sofer * generic/tclInt.decls: * generic/tclIntDecls.h: * generic/tclStubInit.c: * generic/tclVar.c: removing the now redundant functions to access indexed variables: Tcl(Get|Set|Incr)IndexedScalar() and Tcl(Get|Set|Incr)ElementOfIndexedArray(). 2002-07-17 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Minor fixes to make this file compile with SunPro CC... 2002-07-17 Miguel Sofer * generic/tclExecute.c: modified to do variable lookup explicitly, and then either inlining the variable access or else calling the new TclPtr(Set|Get|Incr)Var functions in tclVar.c * generic/tclInt.h: declare some functions previously local to tclVar.c for usage by TEBC. * generic/tclVar.c: removed local declarations; moved all special accessor functions for indexed variables to the end of the file - they are unused and ready for removal, but left there for the time being as they are in the internal stubs table. ** WARNING FOR BYTECODE MAINTAINERS ** TCL_COMPILE_DEBUG is currently not functional; will be fixed ASAP. 2002-07-16 Mo DeJong * unix/Makefile.in: * win/Makefile.in: Add a more descriptive warning in the event `make genstubs` needs to be rerun. 2002-07-16 Mo DeJong * unix/Makefile.in: Use dltest.marker file to keep track of when the dltest package is up to date. This fixes [Bug 575768] since tcltest is no longer linked every time. * unix/dltest/Makefile.in: Create ../dltest.marker after a successful `make all` run in dltest. 2002-07-16 Mo DeJong * unix/configure: Regen. * unix/configure.in: Remove useless subst of TCL_BIN_DIR. 2002-07-15 Miguel Sofer * generic/tclVar.c: inaccurate comment fixed 2002-07-15 Miguel Sofer * generic/tclBasic.c (Tcl_AddObjErrorInfo): * generic/tclExecute.c (TclUpdateReturnInfo): * generic/tclInt.h: * generic/tclProc.c: Added two Tcl_Obj to the ExecEnv structure to hold the fully qualified names "::errorInfo" and "::errorCode" to cache the addresses of the corresponding variables. The two most frequent setters of these variables now profit from the new variable name caching. 2002-07-15 Miguel Sofer * generic/tclVar.c: refactorisation to reuse already looked-up Var pointers; definition of three new Tcl_Obj types to cache variable name parsing and lookup for later reuse; modification of internal functions to profit from the caching. * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclNamesp.c: adding CONST qualifiers to variable names passed to Tcl_FindNamespaceVar and to variable resolvers; adding CONST qualifier to the 'msg' argument to TclLookupVar. Needed to avoid code duplication in the new tclVar.c code. * tests/set-old.test: * tests/var.test: slight modification of error messages due to the modifications in the tclVar.c code. 2002-07-15 Don Porter * tests/unixInit.test: Improved constraints to protect /tmp. [Bug 581403] 2002-07-15 Vince Darley * tests/winFCmd.test: renamed 'win2000' and 'notWin2000' to more appropriate constraint names. * win/tclWinFile.c: updated comments to reflect 07-11 changes. * win/tclWinFCmd.c: made ConvertFileNameFormat static again, since no longer used in tclWinFile.c * mac/tclMacFile.c: completed TclpObjLink implementation which was previously lacking. * generic/tclIOUtil.c: comment cleanup and code speedup. 2002-07-14 Don Porter * generic/tclInt.h: Removed declarations that duplicated entries in the (internal) stub table. * library/tcltest/tcltest.tcl: Corrected errors in handling of configuration options -constraints and -limitconstraints. * README: Bumped HEAD to version 8.4b2 so we can * generic/tcl.h: distinguish it from the 8.4b1 release. * tools/tcl.wse.in: * unix/configure*: * unix/tcl.spec: * win/README.binary: * win/configure*: 2002-07-11 Vince Darley * doc/file.n: * win/tclWinFile.c: on Win 95/98/ME the long form of the path is used as a normalized form. This is required because short forms are not a robust representation. The file normalization function has been sped up, but more performance gains might be possible, if speed is still an issue on these platforms. 2002-07-11 Don Porter * library/tcltest/tcltest.tcl: Corrected reaction to existing but false ::tcl_interactive. * doc/Hash.3: Overlooked CONST documentation update. 2002-07-11 Donal K. Fellows * generic/tclCkalloc.c: ckalloc() and friends take the block size as an unsigned, so we should use %ud when reporting it in fprintf() and panic(). 2002-07-11 Miguel Sofer * generic/tclCompile.c: now setting local vars undefined at compile time, instead of waiting until the proc is initialized. * generic/tclProc.c: use macro TclSetVarUndefined instead of directly setting the flag. 2002-07-11 Donal K. Fellows * tests/cmdAH.test: [file attr -perm] is Unix-only, so add [catch] when not inside a suitably-protected test. 2002-07-10 Donal K. Fellows * tests/unixFCmd.test, tests/fileName.test: * tests/fCmd.test: Removed [exec] of Unix utilities that have equivalents in standard Tcl. [Bug 579268] Also simplified some of unixFCmd.test while I was at it. 2002-07-10 Don Porter * tests/tcltest.test: Greatly reduced the number of [exec]s, using slave interps instead. * library/tcltest/tcltest.tcl: Fixed bug uncovered in the conversion where a message was written to stdout instead of [outputChannel]. * tests/basic.test: Cleaned up, constrained, and reduced the * tests/compile.test: amount of [exec] usage in the test suite. * tests/encoding.test: * tests/env.test: * tests/event.test: * tests/exec.test: * tests/io.test: * tests/ioCmd.test: * tests/regexp.test: * tests/regexpComp.test: * tests/socket.test: * tests/tcltest.test: * tests/unixInit.test: * tests/winDde.test: * tests/winPipe.test: 2002-07-10 Donal K. Fellows * tests/cmdAH.test: Removed [exec] of Unix utilities. [Bug 579211] * tests/expr.test: Added tests to make sure that this works. * generic/tclExecute.c (ExprCallMathFunc): Functions should also be able to return wide-ints. [Bug 579284] 2002-07-08 Andreas Kupries * tests/socket.test: Fixed [Bug 578164]. The original reason for the was a DNS outage while running the testsuite. Changed [info hostname] to 127.0.0.1 to bypass DNS, knowing that we operate on the local host. 2002-07-08 Don Porter * doc/tcltest.n: Fixed incompatibility in [viewFile]. * library/tcltest/tcltest.tcl: Corrected docs. Bumped to 2.2.1. * library/tcltest/pkgIndex.tcl: [Bug 578163] 2002-07-08 Vince Darley * tests/cmdAH.test: * tests/fCmd.test: * tests/fileName.test: tests which rely on 'file link' need a constraint so they don't run on older Windows OS. [Bug 578158] * generic/tclIOUtil.c: * generic/tcl.h: * generic/tclInt.h: * generic/tclTest.c: * mac/tclMacChan.c: * unix/tclUnixChan.c: * win/tclWinChan.c: * doc/FileSystem.3: cleaned up internal handling of Tcl_FSOpenFileChannel to remove duplicate code, and make writing external vfs's clearer and easier. No functionality change. Also clarify that objects with refCount zero should not be passed in to the Tcl_FS API, and prevent segfaults from occuring on such user errors. [Bug 578617] 2002-07-06 Don Porter * tests/pkgMkIndex.test: Constrained tests of [load] package indexing to those platforms where the testing shared libraries have been built. [Bug 578166] 2002-07-05 Don Porter * changes: added recent changes 2002-07-05 Reinhard Max * generic/tclClock.c (FormatClock): Convert the format string to UTF8 before calling TclpStrftime, so that non-ASCII characters don't get mangled when the result string is being converted back. * tests/clock.test: Added a test for that. 2002-07-05 Donal K. Fellows * unix/Makefile.in (ro-test,ddd,GDB,DDD): Created new targets to allow running the test suite with a read-only current directory, running under ddd instead of gdb, and factored out some executable names for broken sites (like mine) where gdb and ddd are installed with non-standard names... * tests/httpold.test: Altered test names to httpold-* to avoid clashes with http.test, and stopped tests from failing when the current directory is not writable... * tests/event.test: Stop these tests from failing when the * tests/ioUtil.test: current directory is not writable... * tests/regexp.test: * tests/regexpComp.test: * tests/source.test: * tests/unixFile.test: * tests/unixNotfy.test: * tests/unixFCmd.test: Trying to make these test-files not * tests/macFCmd.test: bomb out with an error when the * tests/http.test: current directory is not writable... * tests/fileName.test: * tests/env.test: 2002-07-05 Jeff Hobbs *** 8.4b1 TAGGED FOR RELEASE *** 2002-07-04 Donal K. Fellows * tests/cmdMZ.test (cmdMZ-1.4): * tests/cmdAH.test: More fixing of writable-current-dir assumption. [Bug 575824] 2002-07-04 Miguel Sofer * tests/basic.test: Same issue as below; fixed [Bug 575817] 2002-07-04 Andreas Kupries * tests/socket.test: * tests/winPipe.test: * tests/pid.test: Fixed [Bug 575848]. See below for a description the general problem. * All the bugs below are instances of the same problem: The testsuite assumes [pwd] = [temporaryDirectory] and writable. * tests/iogt.test: Fixed [Bug 575860]. * tests/io.test: Fixed [Bug 575862]. * tests/exec.test: * tests/ioCmd.test: Fixed [Bug 575836]. 2002-07-03 Don Porter * tests/pkg1/direct1.tcl: removed * tests/pkg1/pkgIndex.tcl: removed * tests/pkgMkIndex.test: Imported auxilliary files from tests/pkg1 into the test file pkgMkIndex.test itself. Formatting fixes. * unix/Makefile.in: removed tests/pkg/* from `make dist` * tests/pkg/circ1.tcl: removed * tests/pkg/circ2.tcl: removed * tests/pkg/circ3.tcl: removed * tests/pkg/global.tcl: removed * tests/pkg/import.tcl: removed * tests/pkg/pkg1.tcl: removed * tests/pkg/pkg2_a.tcl: removed * tests/pkg/pkg2_b.tcl: removed * tests/pkg/pkg3.tcl: removed * tests/pkg/pkg4.tcl: removed * tests/pkg/pkg5.tcl: removed * tests/pkg/pkga.tcl: removed * tests/pkg/samename.tcl: removed * tests/pkg/simple.tcl: removed * tests/pkg/spacename.tcl: removed * tests/pkg/std.tcl: removed * tests/pkgMkIndex.test: Fixed [Bug 575857] where this test file expected to be able to write to [file join [testsDirectory] pkg]. Part of the fix was to import several auxilliary files into the test file itself. * tests/main.test: Cheap fix for [Bugs 575851, 575858]. Avoid * tests/tcltest.test: non-writable . by [cd [temporaryDirectory]]. * library/auto.tcl: Fix [tcl_findLibrary] to be sure it sets $varName only if a successful library script is found. [Bug 577033] 2002-07-03 Miguel Sofer * generic/tclCompCmds.c (TclCompileCatchCmd): return TCL_OUT_LINE_COMPILE instead of TCL_ERROR: let the failure happen at runtime so that it can be caught [Bug 577015]. 2002-07-02 Joe English * doc/tcltest.n: Markup fixes, spellcheck. 2002-07-02 Don Porter * doc/tcltest.n: more refinements of the documentation. * library/tcltest/tcltest.tcl: Added trace to be sure the stdio constraint is updated whenever the [interpreter] changes. * doc/tcltest.n: Reverted [makeFile] and [viewFile] to * library/tcltest/tcltest.tcl: their former behavior, and documented * tests/cmdAH.test: it. Corrected misspelling of hook * tests/event.test: procedure. Restored tests. * tests/http.test: * tests/io.test: * library/tcltest/tcltest.tcl: Simplified logic of [GetMatchingFiles] and [GetMatchingDirectories], removing special case processing. * doc/tcltest.n: More documentation updates. Reference sections are complete. Only examples need adding. 2002-07-02 Vince Darley * tests/fCmd.test: * generic/tclCmdAH.c: clearer error msgs for 'file link', as per the man page. 2002-07-01 Joe English * doc/Access.3: * doc/AddErrInfo.3: * doc/Alloc.3: * doc/Backslash.3: * doc/CrtChannel.3: * doc/CrtSlave.3: * doc/Encoding.3: * doc/Eval.3: * doc/FileSystem.3: * doc/Notifier.3: * doc/OpenFileChnl.3: * doc/ParseCmd.3: * doc/RegExp.3: * doc/Tcl_Main.3: * doc/Thread.3: * doc/TraceCmd.3: * doc/Utf.3: * doc/WrongNumArgs.3: * doc/binary.n: * doc/clock.n: * doc/expr.n: * doc/fconfigure.n: * doc/glob.n: * doc/http.n: * doc/interp.n: * doc/lsearch.n: * doc/lset.n: * doc/msgcat.n: * doc/packagens.n: * doc/pkgMkIndex.n: * doc/registry.n: * doc/resource.n: * doc/safe.n: * doc/scan.n: * doc/tclvars.n: Spell-check, fixed typos (Updates from Larry Virden). 2002-07-01 Donal K. Fellows * unix/tcl.m4 (SC_CONFIG_CFLAGS): Made Solaris use gcc for linking when building with gcc to resolve problems with undefined symbols being present when tcl library used with non-gcc linker at later stage. Symbols were compiler-generated, so it is the compiler's business to define them. [Bug 541181] 2002-07-01 Don Porter * doc/tcltest.n: more work in progress updating tcltest docs. * library/tcltest/tcltest.tcl: Change [configure -match] to stop treating an empty list as a list of the single pattern "*". Changed the default value to [list *] so default operation remains the same. * tests/pkg/samename.tcl: restored. needed by pkgMkIndex.test. * library/tcltest/tcltest.tcl: restored writeability testing of -tmpdir, augmented by a special exception for the deafault value. 2002-07-01 Donal K. Fellows * doc/concat.n: Documented the *real* behaviour of [concat]! 2002-06-30 Don Porter * doc/tcltest.n: more work in progress updating tcltest docs. * tests/README: Updated the instructions on running and * tests/cmdMZ.test: adding to the test suite. Also updated * tests/encoding.test: several tests, mostly to correctly create * tests/fCmd.test: and destroy any temporary files in the * tests/info.test: [temporaryDirectory] of tcltest. * tests/interp.test: * library/tcltest/tcltest.tcl: Stopped checking for writeability of -tmpdir value because no default directory can be guaranteed to be writeable. * tests/autoMkindex.tcl: removed. * tests/pkg/samename.tcl: removed. * tests/pkg/magicchar.tcl: removed. * tests/pkg/magicchar2.tcl: removed. * tests/autoMkindex.test: Updated auto_mkIndex tests to use [makeFile] and [removeFile] so tests are done in [temporaryDirecotry] where write access is guaranteed. * library/tcltest/tcltest.tcl: Fixed [makeFile] and [viewFile] to * tests/cmdAH.test: accurately reflect a file's contents. * tests/event.test: Updated tests that depended on buggy * tests/http.test: behavior. Also added warning messages * tests/io.test: to "-debug 1" operations to debug test * tests/iogt.test: calls to (make|remove)(File|Directory) * unix/mkLinks: `make mklinks` on 6-27 commits. 2002-06-28 Miguel Sofer * generic/tclCompile.h: modified the macro TclEmitPush to not call its first argument repeatedly or pass it to other macros, [Bug 575194] reported by Peter Spjuth. 2002-06-28 Don Porter * docs/tcltest.n: Doc revisions in progress. * library/tcltest/tcltest.tcl: Corrected -testdir default value. Was not reliable, and disagreed with docs! Thanks to Hemang Lavana. [Bug 575150] 2002-06-28 Donal K. Fellows * unix/tclUnixThrd.c: Renamed the Tcl_Platform* #defines to TclOS* * unix/tclUnixPipe.c: because they are only used internally. Also * unix/tclUnixFile.c: stopped double-#def of TclOSlstat [Bug 566099, * unix/tclUnixFCmd.c: post-rename] * unix/tclUnixChan.c: * unix/tclUnixPort.h: * doc/string.n: Improved documentation for [string last] along lines described in [Bug 574799] so it indicates that the supplied index marks the end of the search space. 2002-06-27 Don Porter * doc/dde.n: Work in progress updating the documentation * doc/http.n: of the packages that come bundled with * doc/msgcat.n: the Tcl source distribution, notably tcltest. * doc/registry.n: * doc/tcltest.n: * library/tcltest/tcltest.tcl: Made sure that the TCLTEST_OPTIONS environment variablle configures tcltest at package load time. 2002-06-26 Vince Darley * tests/fileSystem.test: * generic/tclIOUtil.c: fix to handling of empty paths "" which are not claimed by any filesystem [Bug 573758]. Ensure good error messages are given in all cases. * tests/cmdAH.test: * unix/tclUnixFCmd.c: fix to bug reported as part of [Patch 566669]. Thanks to Taguchi, Takeshi for the report. 2002-06-26 Reinhard Max * unix/tclUnixTime.c: Make [clock format] respect locale settings. * tests/clock.test: [Bug 565880]. ***POTENTIAL INCOMPATIBILITY*** 2002-06-26 Miguel Sofer * doc/CrtInterp.3: * doc/StringObj.3: clarifications by Don Porter, [Bug 493995] and [Bug 500930]. 2002-06-24 Don Porter * library/tcltest/tcltest.tcl: Corrected suppression of -verbose skip * tests/tcltest.test: and start by [test -output]. Also corrected test suite errors exposed by corrected code. [Bug 564656] 2002-06-25 Reinhard Max * unix/tcl.m4: New macro SC_CONFIG_MANPAGES. * unix/configure.in: Added support for symlinks and compression when * unix/Makefile.in: installing the manpages. [Patch 518052] * unix/mkLinks.tcl: Default is still hardlinks and no compression. * unix/mkLinks: generated * unix/configure: * unix/README: Added documentation for the new features. * unix/tcl.m4 (SC_PATH_TCLCONFIG): Replaced ${exec_prefix}/lib by ${libdir}. 2002-06-25 Donal K. Fellows * generic/tclUtil.c (TclGetIntForIndex): Fix of critical [Bug 533364] generated when the index is bad and the result is a shared object. The T_ASTO(T_GOR, ...) idiom likely exists elsewhere though. Also removed some cruft that just complicated things to no advantage. (SetEndOffsetFromAny): Same fix, though this wasn't on the path excited by the bug. 2002-06-24 Don Porter * library/tcltest/tcltest.tcl: Implementation of TIP 101. Adds abd * tests/parseOld.test: exports a [configure] command from * tests/tcltest.test: tcltest. 2002-06-22 Don Porter * changes: updated changes file for 8.4b1 release. * library/tcltest/tcltest.tcl: Corrections to tcltest and the Tcl * tests/basic.test: test suite so that a test with options * tests/cmdInfo.test: -constraints knownBug * tests/compile.test: -limitConstraints 1 only tests the * tests/encoding.test: knownBug tests. Mostly involves * tests/env.test: replacing direct access to the * tests/event.test: testConstraints array with calls to * tests/exec.test: the testConstraint command (which * tests/execute.test: requires tcltest version 2) * tests/fCmd.test: * tests/format.test: * tests/http.test: * tests/httpold.test: * tests/ioUtil.test: * tests/link.test: * tests/load.test: * tests/namespace.test: * tests/pkgMkIndex.test: * tests/reg.test: * tests/result.test: * tests/scan.test: * tests/stack.test: 2002-06-22 Donal K. Fellows * tools/tcl.wse.in (Disk Label), unix/tcl.spec (version): * win/README.binary, README, win/configure.in, unix/configure.in: * generic/tcl.h (TCL_RELEASE_*, TCL_PATCH_LEVEL): Bump to beta1. 2002-06-21 Joe English * generic/tclCompExpr.c: * generic/tclParseExpr.c: LogSyntaxError() should reset the interpreter result [Bug 550142 "Tcl_ExprObj -> abort"] 2002-06-21 Don Porter * unix/Makefile.in: Updated all package install directories * win/Makefile.in: to match current Major.minor versions * win/makefile.bc: of the packages. Added tcltest package * win/makefile.vc: to installation on Windows. * library/init.tcl: Corrected comments and namespace style issues. Thanks to Bruce Stephens. [Bug 572025] 2002-06-21 Vince Darley * tests/cmdAH.test: Added TIP#99 implementation of 'file * tests/fCmd.test: link'. Supports creation of symbolic and * tests/fileName.test: hard links in the native filesystems and * tests/fileSystem.test: in vfs's, when the individual filesystem * generic/tclTest.c: supports the concept. * generic/tclCmdAH.c: * generic/tclIOUtil.c: * generic/tcl.h: * generic/tcl.decls: * doc/FileSystem.3: * doc/file.n: * mac/tclMacFile.c: * unix/tclUnixFile.c: * win/tclWinFile.c: Also enhanced speed of 'file normalize' on Windows. 2002-06-20 Miguel Sofer * generic/tclBasic.c (TclEvalObjvInternal): fix for [Bug 571385] in the implementation of TIP#62 (command tracing). Vince Darley, Hemang Lavana & Don Porter: thanks. 2002-06-20 Miguel Sofer * generic/tclExecute.c (TclCompEvalObj): clarified and simplified the logic for compilation/recompilation. 2002-06-19 Joe English * doc/file.n: Fixed indentation. No substantive changes. 2002-06-19 Jeff Hobbs * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): get the resultPtr again as the Tcl_ObjSetVar2 may cause the result to change. [Patch 558324] (watson) 2002-06-19 Miguel Sofer * generic/tclExecute.c (TEBC): removing unused "for(;;)" loop; improved comments; re-indentation. 2002-06-18 Miguel Sofer * generic/tclExecute.c (TEBC): - elimination of duplicated code in the non-immediate INST_INCR instructions. - elimination of 103 (!) TclDecrRefCount macros. The different instructions now jump back to a common "DecrRefCount zone" at the top of the loop. The macro "ADJUST_PC" was replaced by two macros "NEXT_INST_F" and "NEXT_INST_V" that take three params (pcAdjustment, # of stack objects to discard, resultObjPtr handling flag). The only instructions that retain a TclDecrRefCount are INST_POP (for speed), the common code for the non-immediate INST_INCR, INST_FOREACH_STEP and the two INST_LSET. The object size of tclExecute.o was reduced by approx 20% since the start of the consolidation drive, while making room for some peep-hole optimisation at runtime. 2002-06-18 Miguel Sofer * generic/tclExecute.c (TEBC, INST_DONE): small bug in the panic code for tcl-stack corruption. 2002-06-17 David Gravereaux Trims to support the removal of RESOURCE_INCLUDED from rc scripts from [FRQ 565088]. * generic/tcl.h: moved the #ifndef RC_INVOKED start block up in the file. rc scripts don't need to know thread mutexes. * win/tcl.rc: * win/tclsh.rc: removed the #define RESOURCE_INCLUDED to let the built-in -DRC_INVOKED to the work. 2002-06-17 Jeff Hobbs * doc/CrtTrace.3: Added TIP#62 implementation of command * doc/trace.n: execution tracing [FRQ 462580] (lavana). * generic/tcl.h: This includes enter/leave tracing as well * generic/tclBasic.c: as inter-procedure stepping. * generic/tclCmdMZ.c: * generic/tclCompile.c: * generic/tclExecute.c: * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclStubInit.c: * generic/tclVar.c: * tests/trace.test: 2002-06-17 Andreas Kupries * win/tclWinPipe.c (BuildCommandLine): Fixed [Bug 554068] ([exec] on windows did not treat { in filenames well.). Bug reported by Vince Darley , patch provided by Vince too. 2002-06-17 Joe English * generic/tcl.h: #ifdef logic for K&R C backwards compatibility changed to assume modern C by default. See [FRQ 565088] for full details. 2002-06-17 Don Porter * doc/msgcat.n: Corrected en_UK references to en_GB. UK is not a country designation recognized in ISO 3166. * library/msgcat/msgcat.tcl: More Windows Registry locale codes from Bruno Haible. * doc/msgcat.n: * library/msgcat/msgcat.tcl: * library/msgcat/pkgIndex.tcl: * tests/msgcat.test: Revised locale initialization to interpret environment variable locale values according to XPG4, and to recognize the LC_ALL and LC_MESSAGES values over that of LANG. Also added many Windows Registry locale values to those recognized by msgcat. Revised tests and docs. Bumped to version 1.3. Thanks to Bruno Haible for the report and assistance crafting the solution. [Bug 525522, 525525] 2002-06-16 Miguel Sofer * generic/tclCompile.c (TclCompileTokens): a better algorithm for the previous bug fix. 2002-06-16 Miguel Sofer * generic/tclCompile.c (TclCompileTokens): * tests/compile.test: [Bug 569438] in the processing of dollar variables; report by Georgios Petasis. 2002-06-16 Miguel Sofer * generic/tclExecute.c: bug in the consolidation of the INCR_..._STK instructions; the bug could not be exercised as the (faulty) instruction INST_INCR_ARRAY_STK was never compiled-in (related to [Bug 569438]). 2002-06-14 Miguel Sofer * generic/tclExecute.c (TclExecuteByteCode): runtime peep-hole optimisation of variables (INST_STORE, INST_INCR) and commands (INST_INVOKE); faster check for the existence of a catch. (TclExecuteByteCode): runtime peep-hole optimisation of comparisons. (TclExecuteByteCode): runtime peep-hole optimisation of INST_FOREACH - relies on peculiarities of the code produced by the bytecode compiler. 2002-06-14 David Gravereaux * win/rules.vc: The test for compiler optimizations was in error. Thanks goes to Roy Terry for his assistance with this. 2002-06-14 Donal K. Fellows * doc/trace.n, tests/trace.test: * generic/tclCmdMZ.c (Tcl_TraceObjCmd,TclTraceCommandObjCmd) (TclTraceVariableObjCmd): Changed references to "trace list" to "trace info" as mandated by TIP#102. 2002-06-13 Miguel Sofer * generic/tclExecute.c (TclExecuteByteCode): consolidated code for the conditional branch instructions. 2002-06-13 Miguel Sofer * generic/tclExecute.c (TclExecuteByteCode): fixed the previous patch; wouldn't compile with TCL_COMPILE_DEBUG set. 2002-06-13 Miguel Sofer * generic/tclExecute.c (TclExecuteByteCode): consolidated the handling of exception returns to INST_INVOKE and INST_EVAL, as well as most of the code for INST_CONTINUE and INST_BREAK, in the new jump target "processExceptionReturn". 2002-06-13 Miguel Sofer * generic/tclExecute.c (TclExecuteByteCode): consolidated variable handling opcodes, replaced redundant code with some 'goto'. All store/append/lappend opcodes on the same data type now share the main code; same with incr opcodes. * generic/tclVar.c: added the bit TCL_TRACE_READS to the possible flags to Tcl_SetVar2Ex - it causes read traces to be fired prior to setting the variable. This is used in the core for [lappend]. ***NOTE*** the usage of TCL_TRACE_READS in Tcl_(Obj)?GetVar.* is not documented; there, it causes the call to create the variable if it does not exist. The new usage in Tcl_(Obj)?SetVar.* remains undocumented too ... 2002-06-13 Vince Darley * tests/fCmd.test: * tests/winFile.test: * tests/fileSystem.test: * generic/tclTest.c: * generic/tclCmdAH.c: * generic/tclIOUtil.c: * doc/FileSystem.3: * mac/tclMacFile.c: * unix/tclUnixFile.c: * win/tclWinFile.c: fixed up further so both compiles and actually works with VC++ 5 or 6. * win/tclWinInt.h: * win/tclWin32Dll.c: cleaned up code and vfs tests and added tests for the internal changes of 2002-06-12, to see whether WinTcl on NTFS can coexist peacefully with links in the filesystem. Added new test command 'testfilelink' to enable the newer code to be tested. * tests/fCmd.test: (made certain tests of 'testfilelink' not run on unix). 2002-06-12 Miguel Sofer * tclBasic.c (Tcl_DeleteTrace): fixed [Bug 568123] (thanks to Hemang Lavana) 2002-06-12 Jeff Hobbs * win/tclWinFile.c: corrected the symbolic link handling code to allow it to compile. Added real definition of REPARSE_DATA_BUFFER (found in winnt.h). Most of the added definitions appear to have correct, cross-Win-version equivalents in winnt.h and should be removed, but just making things "work" for now. 2002-06-12 Vince Darley * generic/tclIOUtil.c: * generic/tcl.decls: * generic/tclDecls.h: made code for Tcl_FSNewNativePath agree with man pages. * doc/FileSystem.3: clarified the circumstances under which certain functions are called in the presence of symlinks. * win/tclWinFile.c: * win/tclWinPort.h: * win/tclWinInt.h: * win/tclWinFCmd.c: Fix for Windows to allow 'file lstat', 'file type', 'glob -type l', 'file copy', 'file delete', 'file normalize', and all VFS code to work correctly in the presence of symlinks (previously Tcl's behaviour was not very well defined). This also fixes possible serious problems in all versions of WinTcl where 'file delete' on a NTFS symlink could delete the original, not the symlink. Note: symlinks cannot yet be created in pure Tcl. 2002-06-11 Miguel Sofer * generic/tclBasic.c: * generic/tclCompCmds.c: * generic/tclInt.h: reverted the new compilation functions; replaced by a more general approach described below. * generic/tclCompCmds.c: * generic/tclCompile.c: made *all* compiled variable access attempts create an indexed variable - even get or incr without previous set. This allows indexed access to local variables that are created and set at runtime, for example by [global], [upvar], [variable], [regexp], [regsub]. 2002-06-11 Miguel Sofer * doc/global.n: * doc/info.n: * test/info.test: * generic/tclCmdIL.c: fix for [Bug 567386], [info locals] was reporting some linked variables. * generic/tclBasic.c: * generic/tclCompCmds.c: * generic/tclInt.h: added compile functions for [global], [variable] and [upvar]. They just declare the new local variables, the commands themselves are not compiled-in. This gives a notably faster read access to these linked variables. 2002-06-11 Miguel Sofer * generic/tclExecute.c: optimised algorithm for exception range lookup; part of [Patch 453709]. 2002-06-10 Vince Darley * unix/tclUnixFCmd.c: fixed [Bug 566669] * generic/tclIOUtil.c: improved and sped up handling of native paths (duplication and conversion to normalized paths), particularly on Windows. * modified part of above commit, due to problems on Linux. Will re-examine bug report and evaluate more closely. 2002-06-07 Don Porter * tests/tcltest.test: More corrections to test suite so that tests of failing [test]s don't show up themselves as failing tests. 2002-06-07 Donal K. Fellows * generic/tclExecute.c: Tidied up headers in relation to float.h to cut the cruft and ensure DBL_MAX is defined since doubles seem to be the same size everywhere; if the assumption isn't true, the variant platforms had better have run configure... * unix/tclUnixPort.h (EOVERFLOW): Added code to define it if it wasn't previously defined. Also some other general tidying and adding of comments. [Bugs 563122, 564595] * compat/tclErrno.h: Added definition for EOVERFLOW copied from Solaris headers; I've been unable to find any uses of EFTYPE, which was the error code previously occupying the slot, in Tcl, or any definition of it in the Solaris headers. 2002-06-06 Mo DeJong * unix/dltest/Makefile.in: Remove hard coded CFLAGS=-g and add CFLAGS_DEBUG, CFLAGS_OPTIMIZE, and CFLAGS_DEFAULT varaibles. [Bug 565488] 2002-06-06 Don Porter * tests/tcltest.test: Corrections to test suite so that tests of failing [test]s don't show up themselves as failing tests. * tests/io.test: Fixed up namespace variable resolution issues revealed by running test suite with "-singleproc 1". * doc/tcltest.n: * library/tcltest/tcltest.tcl: * tests/tcltest.test: Several updates to tcltest. 1) changed to lazy initialization of test constraints 2) deprecated [initConstraintsHook] 3) repaired badly broken [limitConstraints]. 4) deprecated [threadReap] and [mainThread] [Patch 512214, Bug 558742, Bug 461000, Bug 534903] 2002-06-06 Daniel Steffen * unix/tclUnixThrd.c (TclpReaddir, TclpLocaltime, TclpGmtime): added mutex wrapped calls to readdir, localtime & gmtime in case their thread-safe *_r counterparts are not available. * unix/tcl.m4: added configure check for readdir_r * unix/tcl.m4 (Darwin): set TCL_DEFAULT_ENCODING to utf-8 on MacOSX (where posix file apis expect utf-8, not iso8859-1). * unix/configure: regen * unix/Makefile.in: set DYLD_LIBRARY_PATH in parallel to LD_LIBRARY_PATH for MacOSX dynamic linker. * generic/tclEnv.c (TclSetEnv): fix env var setting on MacOSX (adapted from [Patch 524352] by jkbonfield). 2002-06-05 Don Porter * doc/Tcl_Main.3: Documented $tcl_rcFileName and added more clarifications about the intended use of Tcl_Main(). [Bug 505651] 2002-06-05 Daniel Steffen * generic/tclFileName.c (TclGlob): mac specific fix to recent changes in 'glob -tails' handling. * mac/tclMacPort.h: * mac/tclMacChan.c: fixed TIP#91 bustage. * mac/tclMacResource.c (Tcl_MacConvertTextResource): added utf conversion of text resource contents. * tests/macFCmd.test (macFCmd-1.2): allow CWIE creator. 2002-06-04 Don Porter * library/tcltest/tcltest.tcl: * tests/init.test: * tests/tcltest.test: Added more TIP 85 tests from Arjen Markus. Converted tcltest.test to use a private namespace. Fixed bugs in [tcltest::Eval] revealed by calling [tcltest::test] from a non-global namespace, and namespace errors in init.test. 2002-06-04 Mo DeJong * win/README: Update msys+mingw URL. 2002-06-03 Don Porter * doc/tcltest.n: * library/tcltest/tcltest.tcl: * library/tcltest/pkgIndex.tcl: * tests/tcltest.test: Implementation of TIP 85. Allows tcltest users to add new legal values of the -match option to [test], associating each with a Tcl command that does the matching of expected results with actual results of tests. Thanks to Arjen Markus. => tcltest 2.1 [Patch 521362] 2002-06-03 Miguel Sofer * doc/namespace.n: added description of [namepace forget] behaviour for unqualified patterns. [Bug 559268] 2002-06-03 Miguel Sofer * generic/tclExecute.c: reverting an accidental modification in the last commit. 2002-06-03 Miguel Sofer * doc/Tcl.n: clarify the empty variable name issue ([Bug 549285] reported by Tom Krehbiel, patch by Don Porter). 2002-05-31 Don Porter * library/package.tcl: Fixed leak of slave interp in [pkg_mkIndex]. Thanks to Helmut for report. [Bug 550534] * tests/io.test: * tests/main.test: Use the "stdio" constraint to control whether an [open "|[interpreter]"] is attempted. * generic/tclExecute.c (TclMathInProgress,TclExecuteByteCode (ExprCallMathFunc): * generic/tclInt.h (TclMathInProgress): * unix/Makefile.in (tclMtherr.*): * unix/configure.in (NEED_MATHERR): * unix/tclAppInit.c (matherr): * unix/tclMtherr.c (removed file): * win/tclWinMtherr.c (_matherr): Removed internal routine TclMathInProgress and Unix implementation of matherr(). These are now obsolete, dealing with very old versions of the C math library. Windows version is retained in case Borland compilers require it, but it is inactive. Thanks to Joe English. [Bug 474335, Patch 555635] * unix/configure: regen 2002-05-30 Miguel Sofer * generic/tclCompExpr.c: * generic/tclCompile.c: * generic/tclCompile.h: removed exprIsJustVarRef and exprIsComparison from the ExprInfo and CompileEnv structs. These were set, but not used since dec 1999 [Bug 562383]. 2002-05-30 Vince Darley * generic/tclFileName.c (TclGlob): fix to longstanding 'knownBug' in fileName tests 15.2-15.4, and fix to a new Tcl 8.4 bug in certain uses of 'glob -tails'. * tests/fileName.test: removed 'knownBug' flag from some tests, added some new tests for above bugs. 2002-05-29 Jeff Hobbs * unix/configure: regen'ed * unix/configure.in: replaced bigendian check with autoconf standard AC_C_BIG_ENDIAN, which defined WORDS_BIGENDIAN on bigendian systems. * generic/tclUtf.c (Tcl_UniCharNcmp): * generic/tclInt.h (TclUniCharNcmp): use WORDS_BIGENDIAN instead of TCL_OPTIMIZE_UNICODE_COMPARE to enable memcmp alternative. * generic/tclExecute.c (TclExecuteByteCode INST_STR_CMP): * generic/tclCmdMZ.c (Tcl_StringObjCmd): changed the case for choosing the Tcl_UniCharNcmp compare to when both objs are of StringType, as benchmarks show that is the optimal check (both bigendian and littleendian systems). 2002-05-29 Don Porter * generic/tclMain.c: Removed "dummy" reference to Tcl_LinkVar. It is no longer needed since Tcl_Main() now actually calls Tcl_LinkVar(). Thanks to Joe English for pointing that out. 2002-05-29 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): * generic/tclCmdMZ.c (Tcl_StringObjCmd): Use the macro version. * generic/tclInt.h (TclUniCharNcmp): Optimised still further with a macro for use in sensitive places like tclExecute.c * generic/tclUtf.c (Tcl_UniCharNcmp): Use new flag to figure out when we can use an optimal comparison scheme, and default to the old scheme in other cases which is at least safe. * unix/configure.in (TCL_OPTIMIZE_UNICODE_COMPARE): New optional flag that indicates when we can use memcmp() to compare Unicode strings (i.e. when the high-byte of a Tcl_UniChar precedes the low-byte.) 2002-05-29 Jeff Hobbs * generic/tclInt.decls: * generic/tclIntDecls.h: * generic/tclStubInit.c: * generic/tclUtf.c: added TclpUtfNcmp2 private command that mirrors Tcl_UtfNcmp, but takes n in bytes, not utf-8 chars. This provides a faster alternative for comparing utf strings internally. (Tcl_UniCharNcmp, Tcl_UniCharNcasecmp): removed the explicit end of string check as it wasn't correct for the function (by doc and logic). * generic/tclCmdMZ.c (Tcl_StringObjCmd): reworked the string equal comparison code to use TclpUtfNcmp2 as well as short-circuit for equal objects or unequal length strings in the equal case. Removed the use of goto and streamlined the other parts. * generic/tclExecute.c (TclExecuteByteCode): added check for object equality in the comparison instructions. Added short-circuit for != length strings in INST_EQ, INST_NEQ and INST_STR_CMP. Reworked INST_STR_CMP to use TclpUtfNcmp2 where appropriate, and only use Tcl_UniCharNcmp when at least one of the objects is a Unicode obj with no utf bytes. * generic/tclCompCmds.c (TclCompileStringCmd): removed error creation in code that no longer throws an error. * tests/string.test: * tests/stringComp.test: added more string comparison checks. * tests/clock.test: better qualified 9.1 constraint check for %s. 2002-05-28 Jeff Hobbs * generic/tclThreadAlloc.c (TclpRealloc, TclpFree): protect against the case when NULL is based. * tests/clock.test: added clock-9.1 * compat/strftime.c: * generic/tclClock.c: * generic/tclInt.decls: * generic/tclIntDecls.h: * unix/tclUnixTime.c: fix for Windows msvcrt mem leak caused by using an env(TZ) setting trick for in clock format -gmt 1. This also makes %s seem to work correctly with -gmt 1 as well as making it a lot faster by avoid the env(TZ) hack. TclpStrftime now takes useGMT as an arg. [Bug 559376] 2002-05-28 Vince Darley * generic/tclIOUtil.c: fixes to Tcl_FSLoadFile when called on a file inside a vfs. This should avoid leaving temporary files sitting around on exit. [Bug 545579] 2002-05-27 Donal K. Fellows * win/tclWinError.c: Added comment on conversion of ERROR_NEGATIVE_SEEK because that is a mapping that really belongs, and not a catch-all case. * win/tclWinPort.h (EOVERFLOW): Should be either EFBIG or EINVAL * generic/tclPosixStr.c (Tcl_ErrnoId, Tcl_ErrnoMsg): EOVERFLOW can potentially be a synonym for EINVAL. 2002-05-24 Donal K. Fellows === Changes due to TIP#91 === * win/tclWinPort.h: Added declaration of EOVERFLOW. * doc/CrtChannel.3: Added documentation of wideSeekProc. * generic/tclIOGT.c (TransformSeekProc, TransformWideSeekProc): Adapted to use the new channel mechanism. * unix/tclUnixChan.c (FileSeekProc, FileWideSeekProc): Renamed FileSeekProc to FileWideSeekProc and created new FileSeekProc which has the old-style interface and which errors out with EOVERFLOW when the returned file position can't fit into the return type (int for historical reasons). * win/tclWinChan.c (FileSeekProc, FileWideSeekProc): Renamed FileSeekProc to FileWideSeekProc and created new FileSeekProc which has the old-style interface and which errors out with EOVERFLOW when the returned file position can't fit into the return type (int for historical reasons). * mac/tclMacChan.c (FileSeek): Reverted to old interface; Macs lack large-file support because I can't see how to add it. * generic/tclIO.c (Tcl_Seek, Tcl_Tell): Given these functions knowledge of the new arrangement of channel types. (Tcl_ChannelVersion): Added recognition of new version code. (HaveVersion): New function to do version checking. (Tcl_ChannelBlockModeProc, Tcl_ChannelFlushProc) (Tcl_ChannelHandlerProc): Made these functions use HaveVersion for ease of future maintainability. (Tcl_ChannelBlockModeProc): Obvious lookup function. * generic/tcl.h (Tcl_ChannelType): New wideSeekProc field, and seekProc type restored to old interpretation. (TCL_CHANNEL_VERSION_3): New channel version. 2002-05-24 Andreas Kupries * tests/winPipe.test: Applied patch for [Bug 549617]. Patch and bug report by Kevin Kenny . * win/tclWinSock.c (TcpWatchProc): Fixed [Bug 557878]. We are not allowed to mess with the watch mask if the socket is a server socket. I believe that the original reporter is George Peter Staplin. 2002-05-21 Mo DeJong * unix/configure: Regen. * unix/configure.in: Invoke SC_ENABLE_SHARED before calling SC_CONFIG_CFLAGS so that the SHARED_BUILD variable can be checked inside SC_CONFIG_CFLAGS. * unix/tcl.m4 (SC_CONFIG_CFLAGS): Pass -non_shared instead of -shared to ld when configured with --disable-shared under OSF. [Bug 540390] 2002-05-20 Daniel Steffen * generic/tclInt.h: added prototype for TclpFilesystemPathType(). * mac/tclMacChan.c: use MSL provided creator type if available instead of the default 'MPW '. 2002-05-16 Joe English * doc/CrtObjCmd.3: Added Tcl_GetCommandFromObj, Tcl_GetCommandFullName [Bugs 547987, 414921] 2002-05-14 Donal K. Fellows * unix/tclUnixChan.c (TtyOutputProc): #if/#endif-ed this function out to stop compiler warnings. Also much general tidying of comments in this file and removal of whitespace from blank lines. 2002-05-13 Donal K. Fellows * unix/tclUnixChan.c (SETBREAK): Solaris thinks ioctl() takes a signed second argument, and Linux thinks ioctl() takes an unsigned second argument. So need a longer definition of this macro to get neither to spew warnings... 2002-05-13 Vince Darley * generic/tclEvent.c: * generic/tclIOUtil.c: * generic/tclInt.h: clean up all memory allocated by the filesystem, via introduction of 'TclFinalizeFilesystem'. Move TclFinalizeLoad into TclFinalizeFilesystem so we can be sure it is called at just the right time. Fix bad comment also. [Bug 555078 and 'fs' part of 543549] * win/tclWinChan.c: fix comment referring to wrong function. 2002-05-10 Don Porter * tests/load.test: * tests/safe.test: * tests/tcltest.test: Corrected some list-quoting issues and other matters that cause tests to fail when the patch includes special characters. Report from Vince Darley. [Bug 554068] 2002-05-08 David Gravereaux * doc/file.n: * tools/man2tcl.c: * tools/man2help2.tcl: Thanks to Peter Spjuth , again. My prior fix for single-quote macro mis-understanding was wrong. Reverted to reimpliment the 'macro2' proc which handles single-quote macros and restored file.n text arrangement to avoid single-quotes on the first line. Sorry for all the confusion. 2002-05-08 David Gravereaux * tools/man2tcl.c: * tools/man2help2.tcl: Proper source of macro error misunderstanding single-quote as the leading macro command found and repaired. * doc/file.n: Reverted to prior state before I messed with it. 2002-05-08 Don Porter * library/tcltest/tcltest.tcl: Corrected [uplevel] quoting when [source]-ing test script in subdirectories. * tests/fileName.test: * tests/load.test: * tests/main.test: * tests/tcltest.test: * tests/unixInit.test: Fixes to test suite when there's a space in the working path. Thanks to Kevin Kenny. 2002-05-07 David Gravereaux -- Changes from Peter Spjuth * tools/man2tcl.c: Increased line buffer size and a bail-out if that should ever be over-run. * tools/man2help.tcl: Include Courier New font in rtf header. * tools/man2help2.tcl: Improved handling of CS/CE fields. Use Courier New for code samples and indent better. * doc/file.n: * doc/TraceCmd.3: winhelp conversion tools where understanding a ' as the first character on a line to be an unknown macro. Not knowing how to repair tools/man2tcl.c, I decided to rearrange the text in the docs instead. 2002-05-07 Vince Darley * generic/tclFileName.c: fix to similar segfault when using 'glob -types nonsense -dir dirname -join * *'. [Bug 553320] * doc/FileSystem.3: further documentation on vfs. * tests/cmdAH.test: * tests/fileSystem.test: * tests/pkgMkindex.test: Fix to testsuite bugs when running out of directory whose name contains '{' or '['. 2002-05-07 Miguel Sofer * tests/basic.test: Fix for [Bug 549607] * tests/encoding.test: Fix for [Bug 549610] These are testsuite bugs that caused failures when the filename contained spaces. Report & fix by Kevin Kenny. 2002-05-02 Vince Darley * generic/tclFileName.c: fix to freeing a bad object (i.e. segfault) when using 'glob -types nonsense -dir dirname'. * generic/tclWinFile.c: fix to [Bug 551306], also wrapped some long lines. * tests/fileName.test: added several tests for the above bugs. * doc/FileSystem.3: clarified documentation on refCount requirements of the object returned by the path type function. * generic/tclIOUtil.c: * win/tclWinFile.c: * unix/tclUnixFile.c: * mac/tclMacFile.c: moved TclpFilesystemPathType to the platform- specific directories, so we can add missing platform-specific implementations. On Windows, 'file system' now returns useful results like "native NTFS", "native FAT" for that system. Unix and MacOS still only return "native". * doc/file.n: clarified documentation. * tests/winFile.test: test for 'file system' returning correct values. * tests/fileSystem.test: test for 'file system' returning correct values. Clean up after failed previous test run. 2002-04-26 Jeff Hobbs * unix/configure: * unix/tcl.m4: change HP-11 SHLIB_LD_LIBS from "" to ${LIBS} so that the .sl knows its dependent libs. 2002-04-26 Donal K. Fellows * tests/obj.test (obj-11.[56]): Test conversion to boolean more thoroughly. * generic/tclObj.c (SetBooleanFromAny): Was not calling an integer parsing function on native 64-bit platforms! [Bug 548686] 2002-04-24 Jeff Hobbs * generic/tclInt.h: corrected TclRememberJoinableThread decl to use VOID instead of void. * generic/tclThreadJoin.c: noted that this code isn't needed on Unix. 2002-04-23 Jeff Hobbs * doc/exec.n: * doc/tclvars.n: doc updates [Patch 509426] (gravereaux) 2002-04-24 Daniel Steffen * mac/tclMacResource.r: added check of TCLTK_NO_LIBRARY_TEXT_RESOURCES #define to allow disabling the inclusion of the tcl library code in the resource fork of Tcl executables and shared libraries. 2002-04-23 Donal K. Fellows * doc/TraceCmd.3: New file that documents Tcl_CommandTraceInfo, Tcl_TraceCommand and Tcl_UntraceCommand [Bug 414927] 2002-04-22 Jeff Hobbs * generic/tclAlloc.c: * generic/tclInt.h: * generic/tclThreadAlloc.c (new): * unix/Makefile.in: * unix/tclUnixThrd.c: * win/Makefile.in: * win/tclWinInt.h: * win/tclWinThrd.c: added new threaded allocator contributed by AOL that significantly reduces lock contention when multiple threads are in use. Only Windows and Unix implementations are ready, and the Windows one may need work. It is only used by default on Unix for now, and requires that USE_THREAD_ALLOC be defined (--enable-threads on Unix will define this). * generic/tclIOUtil.c (Tcl_FSRegister, Tcl_FSUnregister): corrected calling of Tcl_ConditionWait to ensure that there would be a condition to wait upon. * generic/tclCmdAH.c (Tcl_FileObjCmd): added cast in FILE_SIZE. * win/tclWinFCmd.c (DoDeleteFile): check return of setattr API calls in file deletion for correct Win32 API handling. * win/Makefile.in: correct dependencies for shell, gdb, runtest targets. * doc/clock.n: * compat/strftime.c (_fmt): change strftime to correctly handle localized %c, %x and %X on Windows. Added some notes about how the other values could be further localized. 2002-04-19 Don Porter * generic/tclMain.c (Tcl_Main): Free the memory allocated for the startup script path. [Bug 543549] * library/msgcat/msgcat.tcl: [mcmax] wasn't using the caller's namespace when determining the max translated length. Also made revisions for better use of namespace variables and more efficient [uplevel]s. * doc/msgcat.n: * library/msgcat/msgcat.tcl: * library/msgcat/pkgIndex.tcl: Added [mcload] to the export list of msgcat; bumped to 1.2.3. [Bug 544727] 2002-04-20 Daniel Steffen * generic/tclInt.decls: * generic/tclIntPlatDecls.h: * generic/tclStubInit.c: * mac/tclMacFCmd.c: * mac/tclMacFile.c: * mac/tclMacUtil.c: Modified TclpObjNormalizePath to be alias file aware, and replaced various calls to FSpLocationFrom*Path by calls to new alias file aware versions FSpLLocationFrom*Path. The alias file aware routines don't resolve the last component of a path if it is an alias. This allows [file copy/delete] etc. to act correctly on alias files. (c.f. discussion in [Bug 511666]) 2002-04-19 Donal K. Fellows * tests/lindex.test (lindex-3.7): * generic/tclUtil.c (TclGetIntForIndex): Stopped indexes from hitting wide ints. [Bug 526717] 2002-04-18 Miguel Sofer * generic/tclNamesp.c: * tests/info.test: [Bug 545325] info level didn't report namespace eval, bug report by Richard Suchenwirth. 2002-04-18 Don Porter * doc/subst.n: Clarified documentation on handling unusual return codes during substitution, and on variable substitutions implied by command substitution, and vice versa. [Bug 536838] 2002-04-18 Donal K. Fellows * generic/tclCmdIL.c (InfoBodyCmd): * tests/info.test (info-2.6): Proc bodies without string reps would report as empty. [Bug 545644] * generic/tclCmdMZ.c (Tcl_SubstObj): More clarification for comment on behaviour when substitutions are not well-formed, prompted by [Bug 536831]; alas, removing the ill-defined behaviour is a lot of work. 2002-04-18 Miguel Sofer * generic/tclExecute.c: * tests/expr-old.test: fix for [Bug 542588] (Phil Ehrens), where "too large integers" were reported as "floating-point value" in [expr] error messages. 2002-04-17 Jeff Hobbs * generic/tclEncoding.c (EscapeFromUtfProc): * generic/tclIO.c (WriteChars, Tcl_Close): corrected the handling of outputting end escapes for escape-based encodings. [Bug 526524] (yamamoto) 2002-04-17 Don Porter * doc/tcltest.n: Removed [saveState] and [restoreState] from tcltest 2 documentation, effectively deprecating them. [Bug 495660] * library/tcltest/tcltest.tcl: Made separate export for commands kept only for tcltest 1 compatibility. * tests/iogt.test: Revised to run tests in a namespace, rather than use the useless and buggy [saveState] and [restoreState] commands of tcltest. Updated to use tcltest 2 as well. [Patch 544911] 2002-04-16 Don Porter * tests/io.test: Revised to run tests in a namespace, rather than use the useless and buggy [saveState] and [restoreState] commands of tcltest. Updated to use tcltest 2 as well. [Patch 544546] 2002-04-15 Miguel Sofer * generic/tclProc.c: * tests/proc-old.test: Improved stack trace for TCL_BREAK and TCL_CONTINUE returns from procs. Patch by Don Porter [Bug 536955]. * generic/tclExecute.c: * tests/compile.test: made bytecodes check for a catch before returning; the compiled [return] is otherwise non-catchable. [Bug 542142] reported by Andreas Kupries. 2002-04-15 Don Porter * tests/socket.test: Increased timeout values so that tests have time to successfully complete even on slow/busy machines. [Bug 523470] * doc/tcltest.n: * library/tcltest/tcltest.tcl: * tests/tcltest.test: Revised [tcltest::test] to return errors when called with invalid syntax and to accept exactly two arguments as documented. Improved error messages. [Bug 497446, Patch 513983] ***POTENTIAL INCOMPATIBILITY***: Incompatible with previous tcltest 2.* releases, found only in alpha releases of Tcl 8.4. 2002-04-11 Jeff Hobbs * generic/tclNotify.c (TclFinalizeNotifier): remove remaining unserviced events on finalization. * win/tcl.m4: Enabled COFF as well as CV style debug info with --enable-symbols to allow Dr. Watson users to see function info. More info on debugging levels can be obtained at: http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp * tests/ioCmd.test: fixed iocmd-8.15 to have mac and unixPc variants. * generic/tclParse.c (Tcl_ParseVar): conditionally incr obj refcount to prevent possible mem leak. 2002-04-08 Daniel Steffen * generic/tcl.h: no on mac. * mac/tclMacFile.c: minor fixes to Vince's changes from 03-24. * mac/tclMacOSA.c: * mac/tclMacResource.c: added missing Tcl_UtfToExternalDString conversions of resource file names. * mac/tclMacSock.c (TcpGetOptionProc): fixed bug introduced by Andreas on 02-25; changed strcmp's to strncmp's so that option comparison behaves like on other platforms. * mac/tcltkMacBuildSupport.sea.hqx (CW Pro6 changes): added support to allow Tk to hookup C library stderr/stdout to TkConsole. * tests/basic.test: * tests/cmdAH.test: * tests/encoding.test: * tests/fileSystem.test: * tests/ioCmd.test: fixed tests failing on mac: check for existence of [exec], changed some result strings. 2002-04-06 Jeff Hobbs * unix/tclUnixFCmd.c (Realpath): added a little extra code to initialize a realpath arg when compiling in PURIFY mode in order to prevent spurious purify warnings. We should really create our own realpath implementation, but this will at least quiet purify for now. 2002-04-05 Don Porter * generic/tclCmdMZ.c (Tcl_SubstObj): * tests/subst.test: Corrected [subst] so that return codes TCL_BREAK and TCL_CONTINUE returned by variable substitution have the same effect as when those codes are returned by command substitution. [Bug 536879] 2002-04-03 Jeff Hobbs * library/tcltest/tcltest.tcl: added getMatchingFiles back (alias to GetMatchingFiles), which was a public function in tcltest 1.0. 2002-04-01 Vince Darley * generic/tclEnv.c: * generic/tclIOUtil.c: invalidate filesystem cache when the user changes env(HOME). Fixes [Bug 535621]. Also cleaned up some of the documentation. * tests/fileSystem.test: added test for bug just fixed. 2002-04-01 Kevin Kenny * win/tclWinTime.c (Tcl_GetTime): made the checks of clock frequency more permissive to cope with the fact that Win98SE is observed to return 1.19318 in place of 1.193182 for the performance counter frequency. 2002-03-29 Jeff Hobbs * generic/tclCmdMZ.c (Tcl_TraceObjCmd, TraceVarProc) (TraceCommandProc, TclTraceCommandObjCmd): corrected potential double-free of traces on variables by flagging in Trace*Proc that it will free the var in case the eval wants to delete the var trace as well. [Bug 536937] Also converted Tcl_UntraceVar -> Tcl_UntraceVar2 and Tcl_Eval to Tcl_EvalEx in Trace*Proc for slight efficiency improvement. 2002-03-29 Don Porter * doc/AllowExc.3: * generic/tclBasic.c (Tcl_EvalObjv,Tcl_EvalEx,Tcl_EvalObjEx): * generic/tclCompile.h (TclCompEvalObj): * generic/tclExecute.c (TclCompEvalObj,TclExecuteByteCode): * tests/basic.test: Corrected problems with Tcl_AllowExceptions having influence over the wrong scope of Tcl_*Eval* calls. Patch from Miguel Sofer. Report from Jean-Claude Wippler. [Bug 219181] 2002-03-28 Don Porter * generic/tclVar.c: Refactored CallTraces to collect repeated handling of its returned value into CallTraces itself. 2002-03-28 David Gravereaux * tools/feather.bmp: * tools/man2help.tcl: * tools/man2help2.tcl: * win/makefile.vc: More winhelp target fixups. Added a feather bitmap to the non-scrollable area and changed the color to be yellow from a plain white. The colors can be whatever we want them to be, but thought I would start with something bold. [Bug 527941] * doc/SetVar.3: * doc/TraceVar.3: * doc/UpVar.3: .AP macro syntax repair. 2002-03-27 David Gravereaux * tools/man2help.tcl: * win/makefile.vc: winhelp target now copies all needed files from tools/ to a workarea under $(OUT_DIR) and builds it from there. No build cruft is left in tools/ anymore. All paths used in man2help.tcl are now relative to where the script is. [Bug 527941] 2002-03-27 David Gravereaux * win/.cvsignore: * win/buildall.vc.bat: * win/coffbase.txt: * win/makefile.vc: * win/nmakehlp.c (new): * win/rules.vc: First draft fix for [Bug 527941]. More changes need to done to the makehelp target to get to stop leaving build files in the tools/ directory. This does not address the syntax errors in the man files. Having the contents of tcl.hpj(.in) inside makefile.vc allows for version numbers to be replaced with macros. The new nmakehlp.c is built by rules.vc in preprocessing and removes the need to use tricky shell syntax that wasn't compatible on Win9x systems. Clean targets made Win9x complient. This is a first draft repair for [Bug 533862]. 2002-03-28 Miguel Sofer * generic/tclBasic.c (Tcl_EvalEx): passing the correct commandSize to TclEvalObjvInternal. [Bug 219362], fix by David Knoll. 2002-03-28 Miguel Sofer * generic/tclBasic.c (Tcl_EvalEx): * tests/basic.test: avoid exceptional returns at level 0. [Bug 219181] 2002-03-27 Don Porter * doc/tcltest.n ([mainThread]): * library/tcltest/tcltest.tcl: * tests/tcltest.test: Major code cleanup to deal with whitespace, coding conventions, and namespace issues, with several minor bugs fixed in the process. * tests/main.test: Added missing [after cancel]s. 2002-03-25 Don Porter * tests/main.test: Removed workarounds for Bug 495977. * library/tcltest/tcltest.tcl: Keep the value of $::auto_path unchanged, so that the tcltest package can test code that depends on auto-loading. If a testing application needs $::auto_path pruned, it should do that itself. [Bug 495726] Improve the processing of the -constraints option to [test] so that constraint lists can have arbitrary whitespace, and non-lists don't blow things up. [Bug 495977] Corrected faulty variable initialization. [Bug 534845] 2002-03-25 Miguel Sofer * doc/CrtTrace.3: small doc correction * generic/tclBasic.c (Tcl_DeleteTrace): Allow NULL callback on trace deletions. [Bug 534728] (Hemang Lavana) 2002-03-24 Miguel Sofer * generic/tclBasic.c (Tcl_EvalObjv): replaced obscure, incorrect code as described in [Bug 533907] (Don Porter). 2002-03-24 Don Porter * library/tcltest/tcltest.tcl: Use [interpreter] to set/query the executable currently running the tcltest package. [Bug 454050] * library/tcltest/tcltest.tcl: Allow non-proc commands to be used as the customization hooks. [Bug 495662] 2002-03-24 Vince Darley * generic/tclFilename.c: * generic/tclFCmd.c: * generic/tclTest.c: * generic/tcl.h: * generic/tclIOUtil.c: * win/tclWinFile.c: * win/tclWinFCmd.c: * win/tclWinPipe.c: * unix/tclUnixFile.c: * unix/tclUnixFCmd.c: * mac/tclMacFile.c: * doc/FileSystem.3: * doc/file.n: * tests/cmdAH.test: * tests/fileName.test: * tests/fileSystem.test: (new file) * tests/winFCmd.test: fix [Bug 511666] and [Bug 511658], and improved documentation of some aspects of the filesystem, particularly 'Tcl_FSMatchInDirectory' which now might match a single file/directory only, and 'file normalize' which wasn't very clear before. Removed inconsistency betweens docs and the Tcl_Filesystem structure. Also fixed [Bug 523217] and corrected file normalization on Unix so that it expands symbolic links. Added some new tests of the filesystem code (in the new file 'fileSystem.test'), and some extra tests for correct handling of symbolic links. Fix to [Bug 530960] which shows up on Win98. Made comparison with ".com" case insensitive in tclWinPipe.c ***POTENTIAL INCOMPATIBILITY***: But only between alpha releases (users of the new Tcl_Filesystem lookup table in Tcl 8.4a4 need to handle the new way in which Tcl may call Tcl_FSMatchInDirectory, and 'file normalize' on unix now behaves correctly). Only known impact is with the 'tclvfs' extension. 2002-03-22 Miguel Sofer * tests/basic.test (basic-46.1): adding test for [Bug 533758], fixed earlier today. 2002-03-22 Jeff Hobbs * win/tclWinInt.h: moved undef of TCL_STORAGE_CLASS. [Bug 478579] 2002-03-22 Miguel Sofer * generic/tclBasic.c (Tcl_EvalObjEx): * generic/tclExecute.c (TclCompEvalObj): fixed the errorInfo for return codes other than (TCL_OK, TCL_ERROR) to runLevel 0.[Bug 533758] Removed the static RecordTracebackInfo(), as its functionality is easily replicated by Tcl_LogCommandInfo. Bug and redundancy noted by Don Porter. 2002-03-21 Donal K. Fellows * doc/expr.n: Improved documentation for ceil and floor. [Bug 530535] 2002-03-20 Don Porter * doc/SetVar.3: * doc/TraceVar.3: * doc/UpVar.3: * generic/tcl.h (Tcl_VarTraceProc): * generic/tcl.decls (Tcl_GetVar2, Tcl_SetVar2, Tcl_TraceVar2, (Tcl_UnsetVar2, Tcl_UntraceVar2, Tcl_UpVar2, Tcl_VarTraceInfo2, (Tcl_GetVar2Ex, TclSetVar2Ex): * generic/tclCmdMZ.c (TraceVarProc): * generic/tclEnv.c (EnvTraceProc): * generic/tclEvent.c (VwaitVarProc): * generic/tclInt.decls (TclLookupVar,TclPrecTraceProc): * generic/tclLink.c (LinkTraceProc): * generic/tclUtil.c (TclPrecTraceProc): * generic/tclVar.c (CallTraces, MakeUpvar, VarErrMsg, TclLookupVar, (Tcl_GetVar2, Tcl_SetVar2, Tcl_TraceVar2, Tcl_UnsetVar2, (Tcl_UntraceVar2, Tcl_UpVar2, Tcl_VarTraceInfo2, Tcl_GetVar2Ex, (TclSetVar2Ex): Updated interfaces of generic/tclVar.c according to TIP 27. In particular, the "part2" arguments were CONSTified. [Patch 532642] * generic/tclDecls.h: * generic/tclIntDecls.h: make genstubs 2002-03-15 Donal K. Fellows * tests/compile.test (compile-12.3): Test to detect bug 530320. * generic/tclCompile.c (TclCompileTokens): Fixed buffer overrun reported in bug 530320. 2002-03-14 Mo DeJong * win/configure: Regen. * win/configure.in: Add configure time test for SEH support in the compiler. * win/tclWin32Dll.c (ESP, EBP, TclpCheckStackSpace, (_except_checkstackspace_handler): * win/tclWinChan.c (ESP, EBP, Tcl_MakeFileChannel, (_except_makefilechannel_handler): * win/tclWinFCmd.c (ESP, EBP, DoRenameFile, DoCopyFile, (_except_dorenamefile_handler, _except_docopyfile_handler): Implement SEH support under gcc using inline asm. Tcl and Tk should now compile with Mingw 1.1. [Patch 525746] 2002-03-14 Mo DeJong * win/tclWinFCmd.c (DoRenameFile, DoCopyFile): Handle an SEH exception with EXCEPTION_EXECUTE_HANDLER instead of restarting the faulting instruction with EXCEPTION_CONTINUE_EXECUTION. [Bug 466102] provides an example of how restarting could send Tcl into an infinite loop. [Patch 525746] 2002-03-11 Mo DeJong * win/tclWinFCmd.c (DoRenameFile, DoCopyFile, DoDeleteFile, (DoRemoveJustDirectory): Make sure we don't pass NULL or "" as a path name to Win32 API functions since this was crashing under Windows 98. 2002-03-11 Don Porter * library/tcltest/tcltest.tcl: * library/tcltest/pkgIndex.tcl: Bumped tcltest package to 2.0.2. 2002-03-11 Mo DeJong * library/tcltest/tcltest.tcl (getMatchingFiles): Pass a proper list to foreach to avoid munging a Windows patch like D:\Foo\Bar into D:FooBar before the glob. 2002-03-11 Mo DeJong * generic/tclEncoding.c: Fix typo in comment. * generic/tclIO.c (DoReadChars, ReadBytes, ReadChars): Use NULL value instead of pointer set to NULL to make things more clear. Reorder arguments so that they match the function signatures. Cleanup little typos and add more descriptive comment. 2002-03-08 Mo DeJong * win/README: Update to indicate that Mingw 1.1 is required to build Tcl. Add section describing new msys based build process. Update Cygwin build instructions so users know where to find Mingw 1.1. 2002-03-08 Jeff Hobbs * win/tclWinFCmd.c (DoCopyFile): correctly set retval to TCL_OK. 2002-03-07 Mo DeJong * win/tclWin32Dll.c (TclpCheckStackSpace): * win/tclWinFCmd.c (DoRenameFile, DoCopyFile): Replace hard coded constants with Win32 symbolic names. Move control flow statements out of __try blocks since the documentation indicates it is frowned upon. 2002-03-07 Don Porter * doc/interp.n: * generic/tclInterp.c (Tcl_InterpObjCmd, SlaveObjCmd, (SlaveRecursionLimit): * generic/tclTest.c: * tests/interp.test: Added the [interp recursionlimit] command to set/query the recursion limit of an interpreter. Proposal and implementation from Stephen Trier. [TIP 87, Patch 522849] 2002-03-06 Donal K. Fellows * generic/tcl.h, tools/tcl.wse.in, unix/configure.in, * unix/tcl.spec, win/README.binary, win/configure.in, README: Bumped patchlevel; this might need to change in the future, but it will help us distinguish between the CVS version and the most recent released version. 2002-03-06 Miguel Sofer * generic/tclInt.h: for unshared objects, TclDecrRefCount now frees the internal rep before the string rep - just like the non-macro Tcl_DecrRefCount/TclFreeObj. [Bug 524802] 2002-03-06 Donal K. Fellows * doc/lsearch.n: Documentation of new features, plus examples. * tests/lsearch.test: Tests of new features. * generic/tclCmdIL.c (Tcl_LsearchObjCmd): TIP#80 support. See http://purl.org/tcl/tip/80 for details. 2002-03-05 Jeff Hobbs *** 8.4a4 TAGGED FOR RELEASE *** * unix/tclUnixChan.c: initial remedy for [Bug 525783] flush problem introduced by TIP #35. This may not satisfy true serial channels, but it restores the correct flushing of std* channels on exit. * unix/README: added --enable-langinfo doc. * unix/tcl.spec: * tools/tcl.wse.in: fixed URL refs to use www.tcl.tk or SF. 2002-03-04 Jeff Hobbs * README: * mac/README: * unix/Makefile.in: * unix/README: * win/README: * win/README.binary: updated to use www.tcl.tk URL. * unix/Makefile.in: added older ChangeLogs to dist target. * tests/io.test: * tests/encoding.test: corrected iso2022 encoding results. added encoding-24.* * generic/tclEncoding.c (EscapeFromUtfProc): corrected output of escape codes as per RFC 1468. [Patch 474358] (taguchi) (TclFinalizeEncodingSubsystem): corrected potential double-free when encodings were finalized on exit. [Bugs 219314, 524674] 2002-03-01 Jeff Hobbs * library/encoding/iso2022-jp.enc: * library/encoding/iso2022.enc: * tools/encoding/iso2022-jp.esc: * tools/encoding/iso2022.esc: gave $B precedence over $@, based on comments (point 1) in [Bug 219283] (rfc 1468) * tests/encoding.test: added encoding-23.* tests * generic/tclIO.c (FilterInputBytes): reset the TCL_ENCODING_START flags in the ChannelState when using 'gets'. [Bug 523988] Also reduced the value of ENCODING_LINESIZE from 30 to 20 as this seems to improve the performance of 'gets' according to tclbench. 2002-02-28 Jeff Hobbs * generic/tclCmdMZ.c (TraceCommandProc): ensure that TraceCommandInfo structure was also deleted when a command was deleted to prevent a mem leak. * generic/tclBasic.c (Tcl_CreateObjTrace): set tracePtr->flags correctly. * generic/tclTimer.c (TimerExitProc): remove remaining events in tls on thread exit. 2002-02-28 Miguel Sofer * generic/tclNamesp.c: allow cached fully-qualified namespace names to be usable from different namespaces within the same interpreter without forcing a new lookup [Patch 458872]. 2002-02-28 Miguel Sofer * generic/tclExecute.c: Replaced a few direct stack accesses with the POP_OBJECT() macro [Bug 507181] (Don Porter). 2002-02-27 Don Porter * doc/GetIndex.3: * generic/tcl.decls (Tcl_GetIndexFromObjStruct): * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Revised the prototype of the Tcl_GetIndexFromObjStruct to take its struct table as a (CONST VOID *) argument, better describing what it is, maintaining source compatibility, and adding CONST correctness according to TIP 27. Thanks to Joe English for an elegant solution. [Bug 520304] * generic/tclDecls.h: make genstubs * generic/tclMain.c (Tcl_Main,StdinProc): Corrected some reference count management errors on the interactive command Tcl_Obj found by Purify. Thanks to Jeff Hobbs for the report and assistance. 2002-02-27 Jeff Hobbs * generic/tclBasic.c (Tcl_EvalTokensStandard): corrected mem leak in error case. * generic/tclTest.c (TestStatProc[123]): correct harmless UMRs. * generic/tclLink.c (Tcl_LinkVar): correct mem leak in error case. 2002-02-27 Andreas Kupries * tests/socket.test (2.7): Accepted and applied patch for [Bug 523470] provided by Don Porter to avoid timing problems in that test. * unix/tclUnixChan.c (TclpOpenFileChannel): Added code to regonize "/dev/tty" (by name) and to not handle it as tty / serial line. This is the controlling terminal and is special. Setting it into raw mode as is done for other tty's is a bad idea. This is a hackish fix for expect [Bug 520624]. The fix has limitation: Tcl_MakeFileChannel handles tty's specially too, but is unable to recognize /dev/tty as it only gets a file descriptor, and no name for it. 2002-02-26 Jeff Hobbs * generic/tclCmdAH.c (StoreStatData): corrected mem leak. * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): prevent obj leak in remedial regsub case. * generic/tclFileName.c (Tcl_TranslateFileName): decr refcount for error case to prevent mem leak. * generic/tclVar.c (Tcl_ArrayObjCmd): removed extra obj allocation. * unix/tclUnixSock.c (Tcl_GetHostName): added an extra gethostbyname check to guard against failure with truncated names returned by uname. * unix/configure: * unix/tcl.m4 (SC_SERIAL_PORT): added sys/modem.h check and defined _XOPEN_SOURCE_EXTENDED for HP-11 to get updated header decls. * unix/tclUnixChan.c: added Unix implementation of TIP #35, serial port support. [Patch 438509] (schroedter) 2002-02-26 Miguel Sofer * generic/tclCmpCmds.c: (bugfix to the bugfix, hopefully the last) Bugfix to the new [for] compiling code: was setting a exceptArray parameter using another param which wasn't yet initialised, thus filling it with noise. 2002-02-25 Andreas Kupries * mac/tclMacSock.c (TcpGetOptionProc): Changed to recognize the option "-error". Essentially ignores the option, always returning an empty string. 2002-02-25 Jeff Hobbs * doc/Alloc.3: * doc/LinkVar.3: * doc/ObjectType.3: * doc/PkgRequire.3: * doc/Preserve.3: * doc/TCL_MEM_DEBUG.3: Updated documentation to describe the ckalloc, ckfree, ckrealloc, attemptckalloc, and attemptckrealloc macros, and to accurately describe when and how they are used. [Bug 497459] (dgp) * generic/tclHash.c (AllocArrayEntry, AllocStringEntry): Before invoking ckalloc when creating a Tcl_HashEntry, check that the amount of memory being allocated is at least as large as sizeof(Tcl_HashEntry). The previous code was allocating memory regions that were one or two bytes short. [Bug 521950] (dejong) 2002-02-25 Miguel Sofer * generic/tclBasic.c (Tcl_EvalEx): avoiding a buffer overrun reported by Joe English, and restoring tcl7.6 behaviour for [subst]: badly terminated nested scripts will raise an error and not be evaluated. [Bug 495207] 2002-02-25 Don Porter * unix/tclUnixPort.h: corrected strtoll prototype mismatch on Tru64. * compat/strtod.c (strtod): simplified #includes * compat/strtol.c (strtol): gather result in a long before returning as a long: necessary on platforms where sizeof(int) != sizeof(long). 2002-02-25 Daniel Steffen * unix/tclLoadDyld.c: updated to use Mac OS X 10.1 dyld APIs that have more libdl-like semantics. [Bug 514392] 2002-02-25 Miguel Sofer * generic/tclCompCmds: fixing a bug in patch dated 2002-02-22, in the code for [for] and [while]. Under certain conditions, for long bodies, the exception range parameters were badly computed. Tests forthcoming: I still can't reproduce the conditions in the testsuite (!), although the bug (with assorted segfault or panic!) can be triggered from the console or with the new parse.bench in tclbench. 2002-02-25 Donal K. Fellows * compat/strtoul.c, compat/strtol.c, compat/strtod.c: Added UCHAR, CONST and #includes to clean up GCC output. 2002-02-23 Don Porter * compat/strtoull.c (strtoull): * compat/strtoll.c (strtoll): * compat/strtoul.c (strtoul): Fixed failure to handle leading sign symbols '+' and '-' and '0X' and raise overflow errors. [Bug 440916] Also corrects prototype and errno problems. 2002-02-23 Mo DeJong * configure: Regen. * unix/tcl.m4 (SC_CONFIG_CFLAGS): Link with -n32 instead of -32 when building on IRIX64-6.* system. [Bug 521707] 2002-02-22 Don Porter * generic/tclInt.h: * generic/tclObj.c: renamed global variable emptyString -> tclEmptyString because it is no longer static. * generic/tclPkg.c: Fix for panic when library is loaded on a platform without backlinking without proper use of stubs. [Bug 476537] 2002-02-22 Jeff Hobbs * tests/regexpComp.test: updated regexp-11.[1-4] to match changes in regexp.test for new regsub syntax * unix/configure: * unix/tcl.m4: added --enable-64bit support for AIX-4 (using -q64 flag) when using IBM's xlc compiler. * tests/safe.test: updated safe-8.5 and safe-8.7 * library/safe.tcl (CheckFileName): removed the limit on sourceable file names (was only *.tcl or tclIndex files with no more than one dot and 14 chars). There is enough internal protection in a safe interpreter already. [Tk Bug 521560] 2002-02-22 Miguel Sofer * generic/tclCompCmds: [FR 465811]. Optimising [if], [for] and [while] for constant conditions; in addition, [for] and [while] are now compiled with the "loop rotation" optimisation (thanks to Kevin Kenny). 2002-02-22 Donal K. Fellows --- TIP#76 CHANGES --- * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): Final-argument-less [regsub] returns the modified string. * doc/regsub.n: Updated docs. * tests/regexp.test: Updated and added tests. * compat/strtoll.c (strtoll): * compat/strtoull.c (strtoull): * unix/tclUnixPort.h: * win/tclWinPort.h: Const-ing 64-bit compatability declarations. Note that the return pointer is non-const because it is entirely legal for the functions to be called from somewhere that owns the string being passed. Fixes problem reported by Larry Virden. 2002-02-21 David Gravereaux * win/mkd.bat (removed): * win/coffbase.txt (new): * win/makefile.bc: * win/makefile.vc: Changed the 'setup' target to stop using the mkd.bat file and just make the directory right in the rule. Same change to makefile.bc. Neither configure.in nor Makefile.in use it. coffbase.txt will be the master list for our "prefered base addresses" set by the linker. This should improve load-time (NT only) by avoiding relocations. Submissions to the list by extension authors are encouraged. Added a 'tidy' target to compliment 'clean' and 'hose' to remove just the outputs. Also removed the $(winlibs) macro as it wasn't being used. Stuff left to do: 1) get the winhelp target to stop building in the tools/ directory. 2) stop using rmd.bat 3) add more dependacy rules. * win/tclAppInit.c: Reverted back to -r1.6, as the header file change to tclPort.h won't allow for easy embedded support outside of the source dist. Thanks to Don Porter for pointing this out to me. 2002-02-21 David Gravereaux * win/makefile.vc: * win/rules.vc: Added a new "loimpact" option that sets the -ws:aggressive linker option. Off by default. It's said to keep the heap use low at the expense of alloc speed. * win/tclAppInit.c: Changed #include "tcl.h" to be tclPort.h to remove the raw windows.h include. tclPort.h brings in windows.h already and lessens the pre-compiled-header mush and the randomly useless #pragma comment (lib,...) references throughout the big windows.h tree (as observed at high linker warning levels). 2002-02-21 Donal K. Fellows * generic/tcl.h: Better guessing of LP64/ILP32 architecture, but now sensitive to presence of (suitable) 2002-02-20 Don Porter * generic/tcl.decls (Tcl_RegExpRange,Tcl_GetIndexFromObjStruct): Overlooked a few source incompatibilities. Now using CONST84. * generic/tclDecls.h: make genstubs * generic/tcl.h (Tcl_CmdObjTraceProc): silence warning from Sun Workshop compiler. 2002-02-20 David Gravereaux * win/buildall.vc.bat: * win/makefile.vc: * win/rules.vc: General clean-ups. Added compiler and linker tests for a) the pentium 0x0F errata, b) optimizing (not all have this), and c) linker v6 section alignment confusion. All these are tested first to make sure any D4002 or LNK1117 warnings aren't displayed. The pentium 0x0F errata is a recommended switch. The v5 linker's section alignment default is 512, but the v6 linker was changed to 4096 in an attempt to speed loading on Win98. I changed the default to always be 512 across both linkers, unless linking statically, then 4096 is used for the claimed speed effect. Using a 512 alignment saves 12k bytes of dead space in the DLL. Added IA64 B-stepping errata switch when the compiler supports it. Added profiling to $(lflags) when requested and also removed the explict -entry option as the default works fine as is. Removed win/tclWinInit.c from the special case section to let it use the common implicit rule as the $(EXTFLAGS) macro it had was never referenced anywhere. 2002-02-20 Donal K. Fellows * generic/tcl.h: Added code to guess the correct settings for TCL_WIDE_INT_IS_LONG and TCL_WIDE_INT_TYPE when configure doesn't tell us them, as can happen with extensions. 2002-02-19 Donal K. Fellows * doc/format.n: Updated docs to list the specification. * generic/tclCmdAH.c (Tcl_FormatObjCmd): Made behaviour on 64-bit platforms correctly meet the specification, that %d works with the native word-sized integer, instead of trying to guess (wrongly) from the value being passed. 2002-02-19 Don Porter * changes: First draft of updated changes for 8.4a4 release. 2002-02-15 Jeff Hobbs * unix/tclUnixPort.h: add strtoll/strtoull declarations for platforms that do not define them. * generic/tclIndexObj.c (STRING_AT): removed ptrdiff_t cast and use of VOID* in default case (GNU-ism). 2002-02-15 Kevin Kenny * compat/strtoll.c: * compat/strtoul.c: * compat/strtoull.c: * generic/tclIOUtil.c: * generic/tclPosixStr.c: * generic/tclTest.c: * generic/tclTestObj.c: * tests/get.test: * win/Makefile.vc: Further tweaks to the TIP 72 patch to make it compile under VC++. 2002-02-15 Andreas Kupries * tclExecute.c: * tclIOGT.c: * tclIndexObj.c: Touchups to the TIP 72 patch to make it compileable under Windows again. The changes are not complete, there is one nasty regarding _stati64 2002-02-15 Donal K. Fellows +----------------------+ | TIP #72 IMPLEMENTED. | +----------------------+ There are a lot of changes from this TIP, so please see http://purl.org/tcl/tip/72.html for discussion of backward-compatability issues, but the main ones modifications are in: * generic/tcl.h: New types. * generic/tcl.decls: New public functions. * generic/tclExecute.c: 64-bit aware bytecode engine. * generic/tclBinary.c: 64-bit handling in [binary] command. * generic/tclScan.c: 64-bit handling in [scan] command. * generic/tclCmdAH.c: 64-bit handling in [file] and [format] commands. * generic/tclBasic.c: New "wordSize" entry in ::tcl_platform. * generic/tclFCmd.c: Large-file support (with many consequences.) * generic/tclIO.c: Large-file support (with many consequences.) * compat/strtoll.c, compat/strtoull.c: New support functions. * unix/tcl.m4, unix/configure: 64-bit support and greatly enhanced cacheing. Most other changes, including all those in doc/* and test/* as well as the majority in the platform directories, follow on from these. Also coming out of the woodwork: * generic/tclIndex.c: Better support for Cray PVP. * win/tclWinMtherr.c: Better Borland support. Note that, in a number of places through the Unix part of the platform support, there are Tcl_Platform* references. These are expanded into the correct way to call that particular underlying function, i.e. with or without a '64' suffix, and should be used by people working on the core in preference to the API functions they overlay so that the code remains portable depending on the presence or absence of 64-bit support on the underlying platform. ***POTENTIAL INCOMPATIBILITY***: Extracted from the TIP SUMMARY OF INCOMPATIBILITIES AND FIXES ====================================== The behaviour of expressions containing constants that appear positive but which have a negative internal representation will change, as these will now usually be interpreted as wide integers. This is always fixable by replacing the constant with int(constant). Extensions creating new channel types will need to be altered as different types are now in use in those areas. The change to the declaration of Tcl_FSStat and Tcl_FSLstat (which are the new preferred API in any case) are less serious as no non-alpha releases have been made yet with those API functions. Scripts that are lax about the use of the l modifier in format and scan will probably need to be rewritten. This should be very uncommon though as previously it had absolutely no effect. Extensions that create new math functions that take more than one argument will need to be recompiled (the size of Tcl_Value changes), and functions that accept arguments of any type (TCL_EITHER) will need to be rewritten to handle wide integer values. (I do not expect this to affect many extensions at all.) 2002-02-14 Andreas Kupries * generic/tclIOCmd.c (Tcl_GetsObjCmd): Trivial fix for [Bug 517503], a memory leak reported by Miguel Sofer . The leak happens if an error occurs for "set var [gets $chan]" and leak one empty object. 2002-02-12 David Gravereaux * djgpp/ (new directory) * djgpp/Makefile (new): * unix/tclAppInit.c: * unix/tclMtherr.c: * unix/tclUnixFCmd.c: * unix/tclUnixFile.c: * unix/tclUnixInit.c: * unix/tclUnixPort.h: Early stage of DJGPP support for building Tcl on DOS. Dynamic loading isn't working, yet. Requires watt32 for the TCP/IP stack. No autoconf, yet. Barely tested, but makes a working exe that runs Tcl in protected-mode, flat memory. [exec] and pipes will need the most work as multi-tasking on DOS has to be carefully. 2002-02-10 Kevin Kenny * doc/CrtObjCmd.3: * doc/CrtTrace.3: * generic/tcl.decls: * generic/tcl.h: * generic/tclBasic.c: * generic/tclInt.h: * generic/tclTest.c: * tests/basic.test: Added Tcl_CreateObjTrace, Tcl_GetCommandInfoFromToken and Tcl_SetCommandInfoFromToken. (TIPs #32 and #79.) * generic/tclDecls.h: * generic/tclStubInit.c: Regenerated Stubs tables. 2002-02-08 Jeff Hobbs * unix/configure: * unix/tcl.m4: added -pthread for FreeBSD to EXTRA_CFLAGS and LDFLAGS. Also triggered nodots only for FreeBSD-3. Added AC_DEFINE(_POSIX_PTHREAD_SEMANTICS) for Solaris. * unix/tclUnixPort.h: * unix/tclUnixThrd.c: added thread-safe versions of readdir, localtime, gmtime and inet_ntoa for threaded build. (jgdavidson) * generic/tclScan.c (Tcl_ScanObjCmd): prevented ckfree being called on a pointer to NULL. 2002-02-07 Don Porter * doc/DString.3: * doc/Encoding.3: * doc/GetCwd.3: * doc/SplitPath.3: * doc/Translate.3: * doc/Utf.3: * generic/tcl.decls: * generic/tcl.h: * generic/tclEncoding.c: * generic/tclEnv.c: * generic/tclFileName.c: * generic/tclIOUtil.c: * generic/tclUtf.c: * generic/tclUtil.c: * mac/tclMacInit.c: * unix/tclUnixFile.c: * unix/tclUnixInit.c: * unix/tclUnixPipe.c: * win/tclWin32Dll.c: * win/tclWinFCmd.c: * win/tclWinFile.c: * win/tclWinInit.c: Partial TIP 27 rollback. Following routines restored to return (char *): Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_JoinPath, Tcl_TranslateFileName, Tcl_ExternalToUtfDString, Tcl_UtfToExternalDString, Tcl_UniCharToUtfDString, Tcl_GetCwd, Tcl_WinTCharToUtf. Also restored Tcl_WinUtfToTChar to return (TCHAR *) and Tcl_UtfToUniCharDString to return (Tcl_UniChar *). Modified some callers. This change recognizes that Tcl_DStrings are de-facto white-box objects. * generic/tclDecls.h: * generic/tclPlatDecls.h: make genstubs * generic/tclCmdMZ.c: corrected use of C++-style comment. 2002-02-06 Jeff Hobbs * tests/scan.test: * generic/tclScan.c (Tcl_ScanObjCmd): corrected scan 0x... %x handling that didn't accept the 0x as a prelude to a base 16 number. [Bug 495213] * generic/tclCompCmds.c (TclCompileRegexpCmd): made early check for bad RE to stop checking further. * generic/tclCmdMZ.c (Tcl_RegsubObjCmd): added special case to search for simple 'string map' style regsub calls. Delayed creation of resultPtr object until an initial match is made, as the input string object can then be reused for no matches. (Tcl_StringObjCmd): optimization improvements to the STR_MAP algorithm for zero-length and nocase cases. * tests/regexp.test: * tests/regexpComp.test: extra code coverage tests. * tests/string.test: added 10.18 and 10.19 extra tests. * generic/regc_locale.c (casecmp): slight performance improvement. 2002-02-05 Don Porter * library/http/http.tcl: * library/http/pkgIndex.tcl: Corrected use of http::error when ::error was intended. Bump to http 2.4.2. 2002-02-04 Andreas Kupries * unix/tclUnixChan.c (FileOutputProc): Fixed [bug 465765] reported by Dale Talcott . Avoid writing nothing into a file as STREAM based implementations will consider this a EOF (if the file is a pipe). Not done in the generic layer as this type of writing is actually useful to check the state of a socket. * doc/open.n: Fixed [Bug 511540], added cross-reference to 'pid' as the command to use to retrieve the pid of a command pipeline created via 'open'. 2002-02-01 Jeff Hobbs * generic/tclCmdMZ.c (Tcl_RegexpObjCmd): handle quirky about case earlier to avoid shimmering problem. 2002-02-01 Andreas Kupries * tests/io.test: io-39.22 split into two tests, one platform dependent, the other not. -eofchar is not empty on the windows platform. 2002-02-01 Vince Darley * generic/tclTest.c: fix to picky windows compiler problem with the 'MainLoop' function declaration. 2002-01-31 Andreas Kupries * win/tclWinFCmd.c: TIP 27: Applied patch fixing CONST warnings on behalf of Don Porter . 2002-01-30 Don Porter * generic/tcl.decls: * generic/tcl.h: * generic/tclInt.h: For each interface identified in the TIP 27 changes below as a POTENTIAL INCOMPATIBILITY, the source of the incompatibility has been parameterized so that it can be removed. When compiling extension code against the Tcl header files, use the compiler flag -DUSE_NON_CONST to remove the irresolvable source incompatibilities introduced by the TIP 27 changes. Resolvable changes are left for extension authors to resolve. * generic/tclDecls.h: make genstubs 2002-01-30 Vince Darley * doc/FileSystem.3: added documentation for 3 public functions which had been overlooked. [Bug 507701] * unix/mkLinks: make mklinks 2002-01-29 Jeff Hobbs * tests/regexpComp.test: * generic/tclCompCmds.c (TclCompileRegexpCmd): enhanced to support -nocase and -- options. 2002-01-28 Mo DeJong * unix/tcl.m4 (SC_LOAD_TCLCONFIG): * win/tcl.m4 (SC_LOAD_TCLCONFIG): Set TCL_LIB_SPEC, TCL_STUB_LIB_SPEC, and TCL_STUB_LIB_PATH to the values of TCL_BUILD_LIB_SPEC, TCL_BUILD_STUB_LIB_SPEC, and TCL_BUILD_STUB_LIB_PATH when tclConfig.sh is loaded from the build directory. A Tcl extension should make use of the non-build versions of these variables since they will work in both cases. This modification was described in TIP 34. 2002-01-28 Jeff Hobbs * win/tclWinReg.c (regConnectRegistryProc,RecursiveDeleteKey) (DeleteKey,GetKeyNames,GetType,GetValue,OpenSubKey,SetValue): redid the CONSTification as previous changes caused failing tests. * tests/regexpComp.test (new): * generic/tclInt.h: * generic/tclBasic.c: added TclCompileRegexpCmd entry * generic/tclCompCmds.c (TclCompileStringCmd): corrected to return TCL_OUT_LINE_COMPILE instead of TCL_ERROR for parsing errors, so it only throws the error for runtime compile, in case the user modifies 'string'. (TclCompileRegexpCmd): first try at a byte-compiled regexp command. It handles static strings and ^$ bounded static strings. (TclCompileAppendCmd): made TclPushVarName call always use TCL_CREATE_VAR as numWords is always > 2 at that point. * generic/tclExecute.c (TclExecuteByteCode:INST_LIST): correct possibly dangerous decr in macro call. * win/tclWinInit.c (TclpFindVariable): CONSTification touch-up * win/tclWinReg.c (OpenSubKey): corrected bug introduced in CONSTification that dropped pointer reference. * ChangeLog.2000 (new file): * ChangeLog: broke changes from 2000 into ChangeLog.2000 to reduce size of the main ChangeLog. 2002-01-28 David Gravereaux * generic/tclPlatDecls.h: Added preprocessor logic to force a typedef of TCHAR when __STDC__ is defined when using the uncommon -Za compiler switch with the microsoft compiler. 2002-01-27 Don Porter * doc/package.n: Documented global namespace context for script evaluation by [package require]. 2002-01-27 Daniel Steffen * generic/tclInt.decls: * generic/tclIntPlatDecls.h: * mac/tclMacChan.c: * mac/tclMacFCmd.c: * mac/tclMacFile.c: * mac/tclMacInit.c: * mac/tclMacLoad.c: * mac/tclMacResource.c: * mac/tclMacSock.c: TIP 27 CONSTification induced changes * tests/event.test: * tests/main.test: added catches/constraints to test that use features that don't exist on the mac. 2002-01-25 Mo DeJong Make -eofchar and -translation options read only for server sockets. [Bug 496733] * generic/tclIO.c (Tcl_GetChannelOption, Tcl_SetChannelOption): Instead of returning nothing for the -translation option on a server socket, always return "auto". Return the empty string enclosed in quotes for the -eofchar option on a server socket. Fixup -eofchar usage message so that it matches the implementation. * tests/io.test: Add -eofchar tests and -translation tests to ensure options are read only on server sockets. * tests/socket.test: Update tests to account for -eofchar and -translation option changes. 2002-01-25 Don Porter * compat/strstr.c (strstr): * generic/tclCmdAH.c (Tcl_FormatObjCmd): * generic/tclCmdIL.c (InfoNameOfExecutableCmd): * generic/tclEnv.c (ReplaceString): * generic/tclFileName.c (ExtractWinRoot): * generic/tclIO.c (FlushChannel,Tcl_BadChannelOption): * generic/tclStringObj.c (AppendUnicodeToUtfRep): * generic/tclThreadTest.c (TclCreateThread): * generic/tclUtf.c (Tcl_UtfPrev): * mac/tclMacFCmd.c (TclpObjListVolumes): * mac/tclMacResource.c (TclMacRegisterResourceFork, (BuildResourceForkList): * win/tclWinInit.c (AppendEnvironment): Sought out and eliminated instances of CONST-casting that are no longer needed after the TIP 27 effort. * Following is [Patch 501006] * generic/tclInt.decls (Tcl_AddInterpResolvers, Tcl_Export, (Tcl_FindNamespace, Tcl_GetInterpResolvers, Tcl_ForgetImport, (Tcl_Import, Tcl_RemoveInterpResolvers): * generic/tclNamesp.c (Tcl_Export, Tcl_Import, Tcl_ForgetImport, (Tcl_FindNamespace): * generic/tclResolve.c (Tcl_AddInterpResolvers,Tcl_GetInterpResolvers, (Tcl_RemoveInterpResolvers): Updated APIs in generic/tclResolve.c and generic/tclNamesp.c according to the guidelines of TIP 27. * generic/tclIntDecls.h: make genstubs * Following is [Patch 505630] * doc/AddErrorInfo.3: * generic/tcl.decls (Tcl_LogCommandInfo): * generic/tclBasic.c (Tcl_LogCommandInfo): Updated interfaces of generic/tclBasic.cc according to TIP 27. * generic/tclDecls.h: make genstubs * Following is [Patch 506818] * doc/Hash.3: * generic/tcl.decls (Tcl_HashStats): * generic/tclHash.c (Tcl_HashStats): Updated APIs of generic/tclHash.c according to guidelines of TIP 27. * generic/tclDecls.h: make genstubs * generic/tclVar.c (Tcl_ArrayObjCmd): Updated callers. * Following is [Patch 506807] * doc/ObjectType.3: * generic/tcl.decls (Tcl_GetObjType): * generic/tclObj.c (Tcl_GetObjType): Updated APIs of generic/tclObj.c according to guidelines of TIP 27. * generic/tclDecls.h: make genstubs * Following is [Patch 507304] * doc/Encoding.3: * generic/tcl.decls (Tcl_WinUtfToTChar,Tcl_WinTCharToUtf): * win/tclWin32Dll.c (Tcl_WinUtfToTChar,Tcl_WinTCharToUtf): Updated interfaces in win/tclWin32Dll.c according to TIP 27. * generic/tclPlatDecls.h: make genstubs * generic/tclIOUtil.c (TclpNativeToNormalized): * win/tclWinFCmd.c (TclpObjNormalizePath): * win/tclWinFile.c (TclpFindExecutable,TclpMatchInDirectory, (NativeIsExec,NativeStat): * win/tclWinLoad.c (TclpLoadFile): * win/tclWinPipe.c (TclpOpenFile,ApplicationType): * win/tclWinReg.c (regConnectRegistryProc,RecursiveDeleteKey,DeleteKey, (GetKeyNames,GetType,GetValue,OpenSubKey,SetValue): * win/tclWinSerial.c (SerialSetOptionProc): Update callers. * Following is [Patch 505072] * doc/Concat.3: * doc/Encoding.3: * doc/Filesystem.3: * doc/Macintosh.3: * doc/OpenFileChnl.3 * doc/SetResult.3: * doc/SetVar.3: * doc/SplitList.3: * doc/SplitPath.3: * doc/Translate.3: * generic/tcl.h (Tcl_FSMatchInDirectoryProc): * generic/tclInt.h (TclpMatchInDirectory): * generic/tcl.decls (Tcl_Concat,Tcl_GetStringResult,Tcl_GetVar, (Tcl_GetVar2,Tcl_JoinPath,Tcl_Merge,Tcl_OpenCommandChannel,Tcl_SetVar, (Tcl_SetVar2,Tcl_SplitList,Tcl_SplitPath,Tcl_TranslateFileName, (Tcl_ExternalToUtfDString,Tcl_GetEncodingName,Tcl_UtfToExternalDString, (Tcl_GetDefaultEncodingDir,Tcl_SetDefaultEncodingDir, (Tcl_FSMatchInDirectory,Tcl_MacEvalResource,Tcl_MacFindResource): * generic/tclInt.decls (TclCreatePipeline,TclGetEnv,TclpGetCwd, (TclpCreateProcess): * mac/tclMacFile.c (TclpGetCwd): * generic/tclEncoding.c (Tcl_GetDefaultEncodingDir, (Tcl_SetDefaultEncodingDir,Tcl_GetEncodingName, (Tcl_ExternalToUtfDString,Tcl_UtfToExternalDString, OpenEncodingFile, (LoadEscapeEncoding): * generic/tclFileName.c (DoTildeSubst,Tcl_JoinPath,Tcl_SplitPath, (Tcl_TranslateFileName): * generic/tclIOUtil.c (Tcl_FSMatchInDirectory): * generic/tclPipe.c (FileForRedirect,TclCreatePipeline, (Tcl_OpenCommandChannel): * generic/tclResult.c (Tcl_GetStringResult): * generic/tclUtil.c (Tcl_Concat,Tcl_SplitList,Tcl_Merge): * generic/tclVar.c (Tcl_GetVar,Tcl_GetVar2,Tcl_SetVar,Tcl_SetVar2): * mac/tclMacResource.c (Tcl_MacEvalResource,Tcl_MacFindResource): Updated interfaces of generic/tclEncoding, generic/tclFilename.c, generic/tclIOUtil.c, generic/tclPipe.c, generic/tclResult.c, generic/tclUtil.c, generic/tclVar.c and mac/tclMacResource.c according to TIP 27. Tcl_TranslateFileName rewritten as wrapper around VFS-aware version. ***POTENTIAL INCOMPATIBILITY*** Includes source incompatibilities: argv arguments of Tcl_Concat, Tcl_JoinPath, Tcl_OpenCommandChannel, Tcl_Merge; argvPtr arguments of Tcl_SplitList and Tcl_SplitPath. * generic/tclDecls.h: * generic/tclIntDecls.h: make genstubs * generic/tclCkalloc.c (MemoryCmd): * generic/tclClock.c (FormatClock): * generic/tclCmdAH.c (Tcl_CaseObjCmd,Tcl_EncodingObjCmd,Tcl_FileObjCmd): * generic/tclCmdIL.c (InfoLibraryCmd,InfoPatchLevelCmd, (InfoTclVersionCmd): * generic/tclCompCmds.c (TclCompileForeachCmd): * generic/tclCompCmds.h (TclCompileForeachCmd): * generic/tclCompile.c (TclFindCompiledLocal): * generic/tclEnv.c (TclSetupEnv,TclSetEnv,Tcl_PutEnv,TclGetEnv, (EnvTraceProc): * generic/tclEvent.c (Tcl_BackgroundError): * generic/tclIO.c (Tcl_BadChannelOption,Tcl_SetChannelOption): * generic/tclIOCmd.c (Tcl_ExecObjCmd,Tcl_OpenObjCmd): * generic/tclIOSock.c (TclSockGetPort): * generic/tclIOUtil.c (SetFsPathFromAny): * generic/tclLink.c (LinkTraceProc): * generic/tclMain.c (Tcl_Main): * generic/tclNamesp.c (TclTeardownNamespace): * generic/tclProc.c (TclCreateProc): * generic/tclTest.c (TestregexpObjCmd,TesttranslatefilenameCmd, (TestchmodCmd,GetTimesCmd,TestsetCmd,TestOpenFileChannelProc1, (TestOpenFileChannelProc2,TestOpenFileChannelProc3,AsyncHandlerProc, (TestpanicCmd): * generic/tclThreadTest.c (ThreadErrorProc,ThreadEventProc): * generic/tclUtil.c (TclPrecTraceProc): * mac/tclMacFCmd.c (GetFileSpecs): * mac/tclMacFile.c (TclpMatchInDirectory): * mac/tclMacInit.c (TclpInitLibraryPath,Tcl_SourceRCFile): * mac/tclMacOSA.c (tclOSAStore,tclOSALoad): * mac/tclMacResource.c (Tcl_MacEvalResource): * unix/tclUnixFCmd.c (TclpObjNormalizePath): * unix/tclUnixFile.c (TclpMatchInDirectory,TclpGetUserHome,TclpGetCwd, (TclpReadLink): * unix/tclUnixInit.c (TclpInitLibraryPath,TclpSetVariables, (Tcl_SourceRCFile): * unix/tclUnixPipe.c (TclpOpenFile,TclpCreateTempFile, (TclpCreateProcess): * win/tclWinFile.c (TclpGetCwd,TclpMatchInDirectory): * win/tclWinInit.c (TclpInitLibraryPath,Tcl_SourceRCFile, (TclpSetVariables): * win/tclWinPipe.c (TclpCreateProcess): Updated callers. 2002-01-24 Don Porter * generic/tclIOUtil.c (SetFsPathFromAny): Corrected tilde-substitution of pathnames where > 1 separator follows the ~. [Bug 504950] 2002-01-24 Jeff Hobbs * library/http/pkgIndex.tcl: * library/http/http.tcl: don't add port in default case to handle broken servers. http bumped to 2.4.1 [Bug 504508] 2002-01-23 Andreas Kupries * unix/mkLinks: Regenerated. * doc/CrtChannel.3: * doc/ChnlStack.3: Moved documentation for 'Tcl_GetTopChannel' from 'CrtChannel' to 'ChnlStack'. Added documentation of 'Tcl_GetStackedChannel'. [Bug 506147] reported by Mark Patton . 2002-01-23 Don Porter * win/tclWinFile.c (NativeAccess,NativeStat,NativeIsExec, (TclpGetUserHome): * win/tclWinPort.h (TclWinSerialReopen): * win/tclWinSerial.c (TclWinSerialReopen): * win/tclWinSock.c (Tcl_OpenTcpServer): Corrections to earlier TIP 27 changes. Thanks to Andreas Kupries for the feedback. * generic/tclPlatDecls.h: make genstubs * doc/GetHostName.3: * doc/GetOpnFl.3: * doc/OpenTcp.3: * tcl.decls (Tcl_GetHostName,Tcl_GetOpenFile,Tcl_OpenTcpClient, (Tcl_OpenTclServer): * mac/tclMacSock.c (CreateSocket,Tcl_OpenTcpClient,Tcl_OpenTcpServer, (Tcl_GetHostName,GetHostFromString): * unix/tclUnixChan.c (CreateSocket,CreateSocketAddress, (Tcl_OpenTcpClient,Tcl_OpenTcpServer,Tcl_GetOpenFile): * unix/tclUnixSock.c (Tcl_GetHostName): * win/tclWinSock.c (CreateSocket,CreateSocketAddress, (Tcl_OpenTcpClient,Tcl_OpenTcpServer,Tcl_GetHostName): Updated socket interfaces according to TIP 27. * generic/tclCmdIL.c (InfoHostnameCmd): Updated callers. * generic/tclDecls.h: make genstubs 2002-01-21 David Gravereaux * generic/tclLoadNone.c: TclpLoadFile() didn't match proto of typedef Tcl_FSLoadFileProc. OK'd by vincentdarley. [Patch 502488] 2002-01-21 Andreas Kupries * generic/tclIO.c (WriteChars): Fix for [Bug 506297], reported by Martin Forssen . The encoding chosen in the script exposing the bug writes out three intro characters when TCL_ENCODING_START is set, but does not consume any input as TCL_ENCODING_END is cleared. As some output was generated the enclosing loop calls UtfToExternal again, again with START set. Three more characters in the out and still no use of input ... To break this infinite loop we remove TCL_ENCODING_START from the set of flags after the first call (no condition is required, the later calls remove an unset flag, which is a no-op). This causes the subsequent calls to UtfToExternal to consume and convert the actual input. 2002-01-21 Don Porter * generic/tclTest.c: Converted declarations of TestReport file system to more portable form. [Bug 501417] * generic/tcl.decls (Tcl_TraceCommand,Tcl_UntraceCommand, (Tcl_CommandTraceInfo): * generic/tclCmdMZ.c (Tcl_TraceCommand,Tcl_UntraceCommand, (Tcl_CommandTraceInfo): Updated APIs in generic/tclCmdMZ.c according to the guidelines of TIP 27. * generic/tclDecls.h: make genstubs 2002-01-18 Don Porter * win/tclWinChan.c: * win/tclWinFCmd.c: * win/tclWinFile.c: Overlooked callers of Tcl_FSGetNativePath * win/tclWinDde.c: * win/tclWinReg.c: Overlooked callers of Tcl_GetIndexFromObj 2002-01-18 Daniel Steffen * generic/tclThreadTest.c: * mac/tclMacChan.c: * mac/tclMacFCmd.c: * mac/tclMacFile.c: * mac/tclMacLoad.c: * mac/tclMacResource.c: TIP 27 CONSTification broke the mac build in a number of places. 2002-01-17 Andreas Kupries * generic/tclIOCmd.c (Tcl_GetsObjCmd): Fixed [Bug 504642] as reported by Brian Griffin , using his patch. Before the patch the generic I/O layer held an unannounced reference to the interp result to store the read line into. This unfortunately has disastrous results if the channel driver executes a tcl script to perform its operation, this freeing the interp result. In that case we are dereferencing essentially a dangling reference. It is not truly dangling because the object is in the free list, but this only causes us to smash the free list and have the error occur later somewhere else. The patch simply creates a new object for the line and later sets it into the interp result when we are done with reading. 2002-01-16 Mo DeJong * unix/tcl.m4 (SC_LOAD_TCLCONFIG): * win/tcl.m4 (SC_LOAD_TCLCONFIG): Subst TCL_DBGX into TCL_STUB_LIB_FILE and TCL_STUB_LIB_FLAG variables so that an extension does not need to subst TCL_DBGX into its makefile. [Tk Bug 504356] 2002-01-16 Don Porter * doc/FileSystem.3: * doc/GetCwd.3: * doc/GetIndex.3: * generic/tcl.decls (Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct, (Tcl_GetCwd, Tcl_FSFileAttrStrings, Tcl_FSGetNativePath, (Tcl_FSGetTranslatedStringPath): * generic/tcl.h (Tcl_FSFileAttrStringsProc): * generic/tclFCmd.c (TclFileAttrsCmd): * generic/tclIOUtil.c (Tcl_GetCwd,NativeFileAttrStrings, (Tcl_FSFileAttrStrings,Tcl_FSGetTranslatedStringPath, (Tcl_FSGetNativePath): * generic/tclIndexObj.c (Tcl_GetIndexFromObj, (Tcl_GetIndexFromObjStruct): More TIP 27 updates in tclIOUtil.c and tclIndexObj.c that were overlooked before. [Patch 504671] ***POTENTIAL INCOMPATIBILITY*** Includes a source incompatibility in the tablePtr arguments of the Tcl_GetIndexFromObj* routines. * generic/tclDecls.h: make genstubs * generic/tclBinary.c (Tcl_BinaryObjCmd): * generic/tclClock.c (Tcl_ClockObjCmd): * generic/tclCmdAH.c (Tcl_EncodingObjCmd, Tcl_FileObjCmd): * generic/tclCmdIL.c (Tcl_InfoObjCmd,Tcl_LsearchObjCmd,Tcl_LsortObjCmd): * generic/tclCmdMZ.c (Tcl_TraceObjCmd,Tcl_RegexpObjCmd,Tcl_RegsubObjCmd, (Tcl_StringObjCmd,Tcl_SubstObjCmd,Tcl_SwitchObjCmd, (TclTraceCommandObjCmd,TclTraceVariableObjCmd): * generic/tclCompCmds.c (TclCompileStringCmd): * generic/tclEvent.c (Tcl_UpdateObjCmd): * generic/tclFileName.c (Tcl_GlobObjCmd): * generic/tclIO.c (Tcl_FileEventObjCmd): * generic/tclIOCmd.c (Tcl_SeekObjCmd,Tcl_ExecObjCmd,Tcl_SocketObjCmd, (Tcl_FcopyObjCmd): * generic/tclInterp.c (Tcl_InterpObjCmd,SlaveObjCmd): * generic/tclNamesp.c (Tcl_NamespaceObjCmd): * generic/tclPkg.c (Tcl_PackageObjCmd): * generic/tclTest.c (Tcltest_Init,TestencodingObjCmd,TestgetplatformCmd, (TestlocaleCmd,TestregexpObjCmd,TestsaveresultCmd, (TestGetIndexFromObjStructObjCmd,TestReportFileAttrStrings): * generic/tclTestObj.c (TestindexObjCmd,TeststringObjCmd): * generic/tclTimer.c (Tcl_AfterObjCmd): * generic/tclVar.c (Tcl_ArrayObjCmd): * mac/tclMacFCmd.c (SetFileFinderAttributes): * unix/tclUnixChan.c (TclpOpenFileChannel): * unix/tclUnixFCmd.c (tclpFileAttrStrings): * unix/tclUnixFile.c (TclpObjAccess,TclpObjChdir,TclpObjStat, (TclpObjLstat): * win/tclWinFCmd.c (tclpFileAttrStrings): Updated callers. * doc/RegExp.3: * doc/Utf.3: * generic/tcl.decls: * generic/tclInt.decls: * generic/tclRegexp.c: * generic/tclUtf.c: Updated APIs in generic/tclUtf.c and generic/tclRegexp.c according to the guidelines of TIP 27. [Patch 471509] * generic/regc_locale.c (element,cclass): * generic/tclCmdMZ.c (Tcl_StringObjCmd): * generic/tclFileName.c (TclpGetNativePathType,SplitMacPath): * generic/tclIO.c (ReadChars): * mac/tclMacLoad.c (TclpLoadFile): * win/tclWinFile.c (TclpGetUserHome): Updated callers. * generic/tclDecls.h: * generic/tclIntDecls.h: make genstubs * doc/ParseCmd.3 (Tcl_ParseVar): * generic/tcl.decls (Tcl_ParseVar): * generic/tclParse.c (Tcl_ParseVar): * generic/tclTest.c (TestparsevarObjCmd): Updated APIs in generic/tclParse.c according to the guidelines of TIP 27. Updated callers. [Patch 501046] * generic/tclDecls.h: make genstubs * generic/tcl.decls (Tcl_RecordAndEval): * generic/tclDecls.h: make genstubs * generic/tclHistory.c (Tcl_RecordAndEval): Updated APIs in generic/tclHistory.c according to the guidelines of TIP 27. [Patch 504091] * doc/CrtSlave.3: * generic/tcl.decls (Tcl_CreateAlias, Tcl_CreateAliasObj, (Tcl_CreateSlave, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_GetSlave): * generic/tclInterp.c (Tcl_CreateAlias, Tcl_CreateAliasObj, (Tcl_CreateSlave, Tcl_GetAlias, Tcl_GetAliasObj, Tcl_GetSlave): Updated APIs in the file generic/tclInterp.c according to the guidelines of TIP 27. [Patch 501371] ***POTENTIAL INCOMPATIBILITY*** Includes a source incompatibility in the targetCmdPtr arguments of the Tcl_GetAlias* routines. * generic/tclDecls.h: make genstubs 2002-01-15 Don Porter * doc/SetErrno.3 (Tcl_ErrnoMsg): Corrected documentation for Tcl_ErrnoMsg; it takes an integer argument. Thanks to Georgios Petasis. [Bug 468183] * doc/AddErrInfo.3 (Tcl_PosixError): * doc/Eval.3 (Tcl_EvalFile): * doc/FileSystem.c (Tcl_FSOpenFileChannel,Tcl_FSOpenFileChannelProc): * doc/OpenFileChnl.3 (Tcl_OpenFileChannel): * doc/SetErrno.3 (Tcl_ErrnoId,Tcl_ErrnoMsg): * doc/Signal.3 (Tcl_SignalId,Tcl_SignalMsg): * generic/tcl.decls (Tcl_ErrnoId,TclErrnoMsg,Tcl_EvalFile, (Tcl_OpenFileChannel,Tcl_PosixError,Tcl_SignalId,Tcl_SignalMsg, (Tcl_FSOpenFileChannel): * generic/tcl.h (Tcl_FSOpenFileChannelProc): * generic/tclIO.c (FlushChannel): * generic/tclIOUtil.c (Tcl_OpenFileChannel,Tcl_EvalFile,TclGetOpenMode, (Tcl_PosixError,Tcl_FSOpenFileChannel): * generic/tclInt.decls (TclGetOpenMode): * generic/tclInt.h (TclOpenFileChannelProc_,TclGetOpenMode, (TclpOpenFileChannel): * generic/tclPipe.c (TclCleanupChildren): * generic/tclPosixStr.c (Tcl_ErrnoId,Tcl_ErrnoMsg,Tcl_SignalId, (Tcl_SignalMsg): * generic.tclTest.c (PretendTclpOpenFileChannel, (TestOpenFileChannelProc1,TestOpenFileChannelProc2, (TestOpenFileChannelProc3,TestReportOpenFileChannel): * mac/tclMacChan.c (TclpOpenFileChannel): * unix/tclUnixChan.c (TclpOpenFileChannel): * win/tclWinChan.c (TclpOpenFileChannel): Updated APIs in generic/tclIOUtil.c and generic/tclPosixStr.c according to the guidelines of TIP 27. Updated callers. [Patch 499196] * generic/tclDecls.h: * generic/tclIntDecls.h: make genstubs * doc/CrtChannel.3: * doc/OpenFileChnl.3: * generic/tcl.decls: * generic/tclIO.h: * generic/tclIO.c (DoWrite, Tcl_RegisterChannel, Tcl_GetChannel, (Tcl_CreateChannel, Tcl_GetChannelName, CloseChannel, Tcl_Write, (Tcl_WriteRaw, Tcl_Ungets, Tcl_BadChannelOption, Tcl_GetChannelOption, (Tcl_SetChannelOption, Tcl_GetChannelNamesEx, Tcl_ChannelName): Updated APIs in the file generic/tclIO.c according to the guidelines of TIP 27. Several minor documentation corrections as well. [Patch 503565] * generic/tclDecls.h: make genstubs * generic/tcl.h (Tcl_DriverOutputProc, Tcl_DriverGetOptionProc, (Tcl_DriverSetOptionProc): * generic/tclIOGT.c (TransformOutputProc, TransformGetOptionProc, (TransformSetOptionProc): * mac/tclMacChan.c (FileOutput, StdIOOutput): * man/tclMacSock.c (TcpGetOptionProc, TcpOutput): * unix/tclUnixChan.c (FileOutputProc, TcpGetOptionProc, TcpOutputProc, (TtyGetOptionProc, TtySetOptionProc): * unix/tclUnixPipe.c (PipeOuputProc): * win/tclWinChan.c (FileOutputProc): * win/tclWinConsole.c (ConsleOutputProc): * win/tclWinPipe.c (PipeOuputProc): * win/tclWinSerial.c (SerialOutputProc, SerialGetOptionProc, (SerialSetOptionProc): * win/tclWinSock.c (TcpGetOptionProc, TcpOutput): Updated channel driver interface according to the guidelines of TIP 27. See also [Bug 500348]. * doc/CrtChannel.3: * generic/tcl.h: * generic/tclIO.c: * generic/tclIO.h: * generic/tclInt.h: * tools/checkLibraryDoc.tcl: Moved Tcl_EolTranslation enum declaration from generic/tcl.h to generic/tclInt.h (renamed to TclEolTranslation). It is not used anywhere in Tcl's public interface. 2002-01-14 Don Porter * doc/GetIndex.3: * doc/WrongNumArgs.3: * generic/tcl.decls (Tcl_GetIndexFromObj, Tcl_GetIndexFromObjStruct, (Tcl_WrongNumArgs): * generic/tclIndexObj.c (Tcl_GetIndexFromObj,Tcl_GetIndexFromObjStruct, (Tcl_WrongNumArgs): Updated APIs in the file generic/tclIndexObj.c according to the guidelines of TIP 27. [Patch 501491] * generic/tclDecls.h: make genstubs 2002-01-11 Mo DeJong * unix/configure: Regen. * unix/configure.in: * win/configure: Regen. * win/configure.in: Use ${libdir} instead of ${exec_prefix}/lib to properly support the --libdir option to configure. [Bug 489370] 2002-01-11 Andreas Kupries * win/tclWinSerial.c (SerialSetOptionProc): Applied patch for [Bug 500348] supplied by Rolf Schroedter . The function modified the contents of the the 'value' string and now does not do this anymore. This is a followup to the change made on 2001-12-17. 2002-01-11 David Gravereaux * win/makefile.vc: Removed -GD compiler option. It was intended for future use, but MS is again changing the future at their whim. The D4002 warning was harmless though, but someone using VC .NET logged it as a concern. [Bug 501565] 2002-01-11 Mo DeJong * unix/Makefile.in: Burn Tcl build directory into tcltest executable to avoid crashes caused by ld loading a previously installed version of the tcl shared library. [Bug 218110] 2002-01-10 Don Porter , Kevin Kenny * unix/tclLoadDld.c (TclpLoadFile): syntax error: unbalanced parens. Kevin notes that it's far from clear that this file is ever included in an actual build; Linux without dlopen appears to be a nonexistent configuration. 2002-01-08 Don Porter , Kevin Kenny * doc/StaticPkg.3 (Tcl_StaticPackage): * generic/tcl.decls (Tcl_StaticPackage): * generic/tclDecls.h (Tcl_StaticPackage): * generic/tclInt.decls (TclGuessPackageName): * generic/tclInt.h (TclGuessPackageName): * generic/tclLoad.c (Tcl_StaticPackage): * generic/tclLoadNone.c (TclGuessPackageName): * mac/tclMacLoad.c (TclGuessPackageName): * unix/tclLoadAout.c (TclGuessPackageName): * unix/tclLoadDl.c (TclGuessPackageName): * unix/tclLoadDld.c (TclGuessPackageName): * unix/tclLoadDyld.c (TclGuessPackageName): * unix/tclLoadNext.c (TclGuessPackageName): * unix/tclLoadOSF.c (TclGuessPackageName): * unix/tclLoadShl.c (TclGuessPackageName): * win/tclWinLoad.c (TclGuessPackageName): Updated APIs in the files */tcl*Load*.c according to the guidelines of TIP 27. [Patch 501096] 2002-01-09 Don Porter * generic/tclTest.c (MainLoop): * tests/main.test (Tcl_Main-1.{3,4,5,6}): Corrected some non-portable tests from the new Tcl_Main changes. Thanks to Kevin Kenny. 2002-01-07 Don Porter * generic/tclEvent.c (TclInExit): * generic/tclIOUtil.c (SetFsPathFromAbsoluteNormalized, (SetFsPathFromAny,Tcl_FSNewNativePath,DupFsPathInternalRep): * generic/tclListObj.c (TclLsetList,TclLsetFlat): Added some type casts to satisfy picky compilers. * generic/tclMain.c: Bug fix: neglected the NULL case in TclGetStartupScriptFileName(). Broke Tk/wish. 2002-01-05 Don Porter * doc/Tcl_Main.3: * generic/tclMain.c: Substantial rewrite and expanded documentation of Tcl_Main to correct a number of bugs and flaws: - Interactive Tcl_Main can now enter a main loop, exit that loop and continue interactive operations. The loop may even exit in the midst of interactive command typing without loss of the partial command. [Bugs 486453, 474131] - Tcl_Main now gracefully handles deletion of its master interpreter. - Interactive Tcl_Main can now operate with non-blocking stdin - Interactive Tcl_Main can now detect EOF on stdin even in mid-command. [Bug 491341] - Added VFS-aware internal routines for managing the startup script selection. - Tcl variable 'tcl_interactive' is now linked to C variable 'tty' so that one can disable/enable interactive prompts at the script level when there is no startup script. This is meant for use by the test suite. - Consistent use of the Tcl libraries standard channels as returned by Tcl_GetStdChannel(); as opposed to the channels named 'stdin', 'stdout', and 'stderr' in the master interp, which can be different or unavailable. - Tcl_Main now calls Tcl_Exit() if evaluation of [exit] in the master interpreter returns, assuring Tcl_Main does not return. - Documented Tcl_Main's absence from public stub table - Documented that Tcl_Main does not return. - Documented Tcl variables set by Tcl_Main. - All prompts are done from a single procedure, Prompt. - Use of Tcl_Obj-enabled interfaces everywhere. * generic/tclInt.decls (TclGetStartupScriptPath, (TclSetStartupScriptPath): New internal VFS-aware routines for managing the startup script of Tcl_Main. * generic/tclIntDecls.h: * generic/tclStubInit.c: make genstubs * generic/tclTest.c (TestsetmainloopCmd,TestexitmainloopCmd, (Tcltest_Init,TestinterpdeleteCmd): * tests/main.test (new): Added new file to test suite that thoroughly tests generic/tclMain.c; added some new test commands for testing Tcl_SetMainLoop(). 2002-01-04 Don Porter * doc/Alloc.3: * doc/Concat.3: * doc/CrtMathFnc.3: * doc/Hash.3: * doc/Interp.3: * doc/LinkVar.3: * doc/ObjectType.3: * doc/PkgRequire.3: * doc/Preserve.3: * doc/SetResult.3: * doc/SplitList.3: * doc/SplitPath.3: * doc/TCL_MEM_DEBUG.3: Updated documentation to describe the ckalloc, ckfree, ckrealloc, attemptckalloc, and attemptckrealloc macros, and to accurately describe when and how they are used. [Bug 497459] * generic/tclThreadJoin.c (TclRememberJoinableThread,TclJoinThread): Replaced Tcl_Alloc and Tcl_Free calls with ckalloc and ckfree so that memory debugging is supported. 2002-01-04 Daniel Steffen * mac/tclMacTime.c (TclpGetTZName): fix for daylight savings TZName bug 2002-01-03 Don Porter * doc/FileSystem.3: * generic/tclIOUtil.c: Updated some old uses of "fileName" to new VFS terminology, "pathPtr". 2002-01-03 Donal K. Fellows * tests/basic.test (basic-39.4): Greatly simplified test while still leaving it so that it crashes when run without the fix to the [foreach] implementation. * generic/tclCmdAH.c (Tcl_ForeachObjCmd): Stopped [Bug 494348] from happening by not trying to be so clever with cacheing; if nothing untoward is happening anyway, the less efficient technique will only add a few instruction cycles (one function call and a few derefs/assigns per list per iteration, with no change in the number of tests) and if something odd *is* going on, the code is now far more robust. * tests/basic.test (basic-39.4): Reproducable script from [Bug 494348] 2002-01-02 Donal K. Fellows * tests/util.test (Wrapper_Tcl_StringMatch,util-5.*): Rewrote so the test is performed with the right internal function since [string match] no longer uses Tcl_StringCaseMatch internally. * tests/string.test (string-11.51): * generic/tclUtf.c (Tcl_UniCharCaseMatch): * generic/tclUtil.c (Tcl_StringCaseMatch): Fault with matching case-insensitive non-ASCII patterns containing upper case characters. [Bug 233257] ****************************************************************** *** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" *** *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" *** *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" *** ****************************************************************** tcl8.6.5/macosx/0000755000175000017500000000000012665173607013064 5ustar sergeisergeitcl8.6.5/macosx/tclMacOSXFCmd.c0000644000175000017500000004533112663660066015563 0ustar sergeisergei/* * tclMacOSXFCmd.c * * This file implements the MacOSX specific portion of file manipulation * subcommands of the "file" command. * * Copyright (c) 2003-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #ifdef HAVE_GETATTRLIST #include #include #include #endif /* Darwin 8 copyfile API. */ #ifdef HAVE_COPYFILE #ifdef HAVE_COPYFILE_H #include #if defined(HAVE_WEAK_IMPORT) && (MAC_OS_X_VERSION_MIN_REQUIRED < 1040) /* Support for weakly importing copyfile. */ #define WEAK_IMPORT_COPYFILE extern int copyfile(const char *from, const char *to, copyfile_state_t state, copyfile_flags_t flags) WEAK_IMPORT_ATTRIBUTE; #endif /* HAVE_WEAK_IMPORT */ #else /* HAVE_COPYFILE_H */ int copyfile(const char *from, const char *to, void *state, uint32_t flags); #define COPYFILE_ACL (1<<0) #define COPYFILE_XATTR (1<<2) #define COPYFILE_NOFOLLOW_SRC (1<<18) #if defined(HAVE_WEAK_IMPORT) && (MAC_OS_X_VERSION_MIN_REQUIRED < 1040) /* Support for weakly importing copyfile. */ #define WEAK_IMPORT_COPYFILE extern int copyfile(const char *from, const char *to, void *state, uint32_t flags) WEAK_IMPORT_ATTRIBUTE; #endif /* HAVE_WEAK_IMPORT */ #endif /* HAVE_COPYFILE_H */ #endif /* HAVE_COPYFILE */ #ifdef WEAK_IMPORT_COPYFILE #define MayUseCopyFile() (copyfile != NULL) #elif defined(HAVE_COPYFILE) #define MayUseCopyFile() (1) #else #define MayUseCopyFile() (0) #endif #include /* * Constants for file attributes subcommand. Need to be kept in sync with * tclUnixFCmd.c ! */ enum { UNIX_GROUP_ATTRIBUTE, UNIX_OWNER_ATTRIBUTE, UNIX_PERMISSIONS_ATTRIBUTE, #ifdef HAVE_CHFLAGS UNIX_READONLY_ATTRIBUTE, #endif #ifdef MAC_OSX_TCL MACOSX_CREATOR_ATTRIBUTE, MACOSX_TYPE_ATTRIBUTE, MACOSX_HIDDEN_ATTRIBUTE, MACOSX_RSRCLENGTH_ATTRIBUTE, #endif }; typedef u_int32_t OSType; static int GetOSTypeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, OSType *osTypePtr); static Tcl_Obj * NewOSTypeObj(const OSType newOSType); static int SetOSTypeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void UpdateStringOfOSType(Tcl_Obj *objPtr); static const Tcl_ObjType tclOSTypeType = { "osType", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ UpdateStringOfOSType, /* updateStringProc */ SetOSTypeFromAny /* setFromAnyProc */ }; enum { kIsInvisible = 0x4000, }; #define kFinfoIsInvisible (OSSwapHostToBigConstInt16(kIsInvisible)) typedef struct finderinfo { u_int32_t type; u_int32_t creator; u_int16_t fdFlags; u_int32_t location; u_int16_t reserved; u_int32_t extendedFileInfo[4]; } __attribute__ ((__packed__)) finderinfo; typedef struct fileinfobuf { u_int32_t info_length; u_int32_t data[8]; } fileinfobuf; /* *---------------------------------------------------------------------- * * TclMacOSXGetFileAttribute * * Gets a MacOSX attribute of a file. Which attribute is controlled by * objIndex. The object will have ref count 0. * * Results: * Standard TCL result. Returns a new Tcl_Obj in attributePtrPtr if there * is no error. * * Side effects: * A new object is allocated. * *---------------------------------------------------------------------- */ int TclMacOSXGetFileAttribute( Tcl_Interp *interp, /* The interp we are using for errors. */ int objIndex, /* The index of the attribute. */ Tcl_Obj *fileName, /* The name of the file (UTF-8). */ Tcl_Obj **attributePtrPtr) /* A pointer to return the object with. */ { #ifdef HAVE_GETATTRLIST int result; Tcl_StatBuf statBuf; struct attrlist alist; fileinfobuf finfo; finderinfo *finder = (finderinfo *) &finfo.data; off_t *rsrcForkSize = (off_t *) &finfo.data; const char *native; result = TclpObjStat(fileName, &statBuf); if (result != 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not read \"%s\": %s", TclGetString(fileName), Tcl_PosixError(interp))); return TCL_ERROR; } if (S_ISDIR(statBuf.st_mode) && objIndex != MACOSX_HIDDEN_ATTRIBUTE) { /* * Directories only support attribute "-hidden". */ errno = EISDIR; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid attribute: %s", Tcl_PosixError(interp))); return TCL_ERROR; } bzero(&alist, sizeof(struct attrlist)); alist.bitmapcount = ATTR_BIT_MAP_COUNT; if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) { alist.fileattr = ATTR_FILE_RSRCLENGTH; } else { alist.commonattr = ATTR_CMN_FNDRINFO; } native = Tcl_FSGetNativePath(fileName); result = getattrlist(native, &alist, &finfo, sizeof(fileinfobuf), 0); if (result != 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not read attributes of \"%s\": %s", TclGetString(fileName), Tcl_PosixError(interp))); return TCL_ERROR; } switch (objIndex) { case MACOSX_CREATOR_ATTRIBUTE: *attributePtrPtr = NewOSTypeObj( OSSwapBigToHostInt32(finder->creator)); break; case MACOSX_TYPE_ATTRIBUTE: *attributePtrPtr = NewOSTypeObj( OSSwapBigToHostInt32(finder->type)); break; case MACOSX_HIDDEN_ATTRIBUTE: *attributePtrPtr = Tcl_NewBooleanObj( (finder->fdFlags & kFinfoIsInvisible) != 0); break; case MACOSX_RSRCLENGTH_ATTRIBUTE: *attributePtrPtr = Tcl_NewWideIntObj(*rsrcForkSize); break; } return TCL_OK; #else Tcl_SetObjResult(interp, Tcl_NewStringObj( "Mac OS X file attributes not supported", -1)); Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", NULL); return TCL_ERROR; #endif /* HAVE_GETATTRLIST */ } /* *--------------------------------------------------------------------------- * * TclMacOSXSetFileAttribute -- * * Sets a MacOSX attribute of a file. Which attribute is controlled by * objIndex. * * Results: * Standard TCL result. * * Side effects: * As above. * *--------------------------------------------------------------------------- */ int TclMacOSXSetFileAttribute( Tcl_Interp *interp, /* The interp for error reporting. */ int objIndex, /* The index of the attribute. */ Tcl_Obj *fileName, /* The name of the file (UTF-8). */ Tcl_Obj *attributePtr) /* New owner for file. */ { #ifdef HAVE_GETATTRLIST int result; Tcl_StatBuf statBuf; struct attrlist alist; fileinfobuf finfo; finderinfo *finder = (finderinfo *) &finfo.data; off_t *rsrcForkSize = (off_t *) &finfo.data; const char *native; result = TclpObjStat(fileName, &statBuf); if (result != 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not read \"%s\": %s", TclGetString(fileName), Tcl_PosixError(interp))); return TCL_ERROR; } if (S_ISDIR(statBuf.st_mode) && objIndex != MACOSX_HIDDEN_ATTRIBUTE) { /* * Directories only support attribute "-hidden". */ errno = EISDIR; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid attribute: %s", Tcl_PosixError(interp))); return TCL_ERROR; } bzero(&alist, sizeof(struct attrlist)); alist.bitmapcount = ATTR_BIT_MAP_COUNT; if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) { alist.fileattr = ATTR_FILE_RSRCLENGTH; } else { alist.commonattr = ATTR_CMN_FNDRINFO; } native = Tcl_FSGetNativePath(fileName); result = getattrlist(native, &alist, &finfo, sizeof(fileinfobuf), 0); if (result != 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not read attributes of \"%s\": %s", TclGetString(fileName), Tcl_PosixError(interp))); return TCL_ERROR; } if (objIndex != MACOSX_RSRCLENGTH_ATTRIBUTE) { OSType t; int h; switch (objIndex) { case MACOSX_CREATOR_ATTRIBUTE: if (GetOSTypeFromObj(interp, attributePtr, &t) != TCL_OK) { return TCL_ERROR; } finder->creator = OSSwapHostToBigInt32(t); break; case MACOSX_TYPE_ATTRIBUTE: if (GetOSTypeFromObj(interp, attributePtr, &t) != TCL_OK) { return TCL_ERROR; } finder->type = OSSwapHostToBigInt32(t); break; case MACOSX_HIDDEN_ATTRIBUTE: if (Tcl_GetBooleanFromObj(interp, attributePtr, &h) != TCL_OK) { return TCL_ERROR; } if (h) { finder->fdFlags |= kFinfoIsInvisible; } else { finder->fdFlags &= ~kFinfoIsInvisible; } break; } result = setattrlist(native, &alist, &finfo.data, sizeof(finfo.data), 0); if (result != 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not set attributes of \"%s\": %s", TclGetString(fileName), Tcl_PosixError(interp))); return TCL_ERROR; } } else { Tcl_WideInt newRsrcForkSize; if (Tcl_GetWideIntFromObj(interp, attributePtr, &newRsrcForkSize) != TCL_OK) { return TCL_ERROR; } if (newRsrcForkSize != *rsrcForkSize) { Tcl_DString ds; /* * Only setting rsrclength to 0 to strip a file's resource fork is * supported. */ if (newRsrcForkSize != 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "setting nonzero rsrclength not supported", -1)); Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", NULL); return TCL_ERROR; } /* * Construct path to resource fork. */ Tcl_DStringInit(&ds); Tcl_DStringAppend(&ds, native, -1); Tcl_DStringAppend(&ds, _PATH_RSRCFORKSPEC, -1); result = truncate(Tcl_DStringValue(&ds), (off_t)0); if (result != 0) { /* * truncate() on a valid resource fork path may fail with a * permission error in some OS releases, try truncating with * open() instead: */ int fd = open(Tcl_DStringValue(&ds), O_WRONLY | O_TRUNC); if (fd > 0) { result = close(fd); } } Tcl_DStringFree(&ds); if (result != 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not truncate resource fork of \"%s\": %s", TclGetString(fileName), Tcl_PosixError(interp))); return TCL_ERROR; } } } return TCL_OK; #else Tcl_SetObjResult(interp, Tcl_NewStringObj( "Mac OS X file attributes not supported", -1)); Tcl_SetErrorCode(interp, "TCL", "UNSUPPORTED", NULL); return TCL_ERROR; #endif } /* *--------------------------------------------------------------------------- * * TclMacOSXCopyFileAttributes -- * * Copy the MacOSX attributes and resource fork (if present) from one * file to another. * * Results: * Standard Tcl result. * * Side effects: * MacOSX attributes and resource fork are updated in the new file to * reflect the old file. * *--------------------------------------------------------------------------- */ int TclMacOSXCopyFileAttributes( const char *src, /* Path name of source file (native). */ const char *dst, /* Path name of target file (native). */ const Tcl_StatBuf *statBufPtr) /* Stat info for source file */ { if (MayUseCopyFile()) { #ifdef HAVE_COPYFILE if (0 == copyfile(src, dst, NULL, (S_ISLNK(statBufPtr->st_mode) ? COPYFILE_XATTR | COPYFILE_NOFOLLOW_SRC : COPYFILE_XATTR | COPYFILE_ACL))) { return TCL_OK; } #endif /* HAVE_COPYFILE */ } else { #if (!defined(HAVE_COPYFILE) || defined(WEAK_IMPORT_COPYFILE)) && defined(HAVE_GETATTRLIST) struct attrlist alist; fileinfobuf finfo; off_t *rsrcForkSize = (off_t *) &finfo.data; Tcl_DString srcBuf, dstBuf; int result; bzero(&alist, sizeof(struct attrlist)); alist.bitmapcount = ATTR_BIT_MAP_COUNT; alist.commonattr = ATTR_CMN_FNDRINFO; if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) { return TCL_ERROR; } if (setattrlist(dst, &alist, &finfo.data, sizeof(finfo.data), 0)) { return TCL_ERROR; } /* * If we're a directory, we're done as they never have resource forks. */ if (S_ISDIR(statBufPtr->st_mode)) { return TCL_OK; } /* * We only copy a non-empty resource fork, so determine if that's the * case first. */ alist.commonattr = 0; alist.fileattr = ATTR_FILE_RSRCLENGTH; if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) { return TCL_ERROR; } else if (*rsrcForkSize == 0) { return TCL_OK; } /* * Construct paths to resource forks. */ Tcl_DStringInit(&srcBuf); Tcl_DStringAppend(&srcBuf, src, -1); Tcl_DStringAppend(&srcBuf, _PATH_RSRCFORKSPEC, -1); Tcl_DStringInit(&dstBuf); Tcl_DStringAppend(&dstBuf, dst, -1); Tcl_DStringAppend(&dstBuf, _PATH_RSRCFORKSPEC, -1); /* * Do the copy. */ result = TclUnixCopyFile(Tcl_DStringValue(&srcBuf), Tcl_DStringValue(&dstBuf), statBufPtr, 1); Tcl_DStringFree(&srcBuf); Tcl_DStringFree(&dstBuf); if (result == 0) { return TCL_OK; } #endif /* (!HAVE_COPYFILE || WEAK_IMPORT_COPYFILE) && HAVE_GETATTRLIST */ } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclMacOSXMatchType -- * * This routine is used by the globbing code to check if a file matches a * given mac type and/or creator code. * * Results: * The return value is 1, 0 or -1 indicating whether the file matches the * given criteria, does not match them, or an error occurred (in wich * case an error is left in interp). * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclMacOSXMatchType( Tcl_Interp *interp, /* Interpreter to receive errors. */ const char *pathName, /* Native path to check. */ const char *fileName, /* Native filename to check. */ Tcl_StatBuf *statBufPtr, /* Stat info for file to check */ Tcl_GlobTypeData *types) /* Type description to match against. */ { #ifdef HAVE_GETATTRLIST struct attrlist alist; fileinfobuf finfo; finderinfo *finder = (finderinfo *) &finfo.data; OSType osType; bzero(&alist, sizeof(struct attrlist)); alist.bitmapcount = ATTR_BIT_MAP_COUNT; alist.commonattr = ATTR_CMN_FNDRINFO; if (getattrlist(pathName, &alist, &finfo, sizeof(fileinfobuf), 0) != 0) { return 0; } if ((types->perm & TCL_GLOB_PERM_HIDDEN) && !((finder->fdFlags & kFinfoIsInvisible) || (*fileName == '.'))) { return 0; } if (S_ISDIR(statBufPtr->st_mode) && (types->macType || types->macCreator)) { /* * Directories don't support types or creators. */ return 0; } if (types->macType) { if (GetOSTypeFromObj(interp, types->macType, &osType) != TCL_OK) { return -1; } if (osType != OSSwapBigToHostInt32(finder->type)) { return 0; } } if (types->macCreator) { if (GetOSTypeFromObj(interp, types->macCreator, &osType) != TCL_OK) { return -1; } if (osType != OSSwapBigToHostInt32(finder->creator)) { return 0; } } #endif return 1; } /* *---------------------------------------------------------------------- * * GetOSTypeFromObj -- * * Attempt to return an OSType from the Tcl object "objPtr". * * Results: * Standard TCL result. If an error occurs during conversion, an error * message is left in interp->objResult. * * Side effects: * The string representation of objPtr will be updated if necessary. * *---------------------------------------------------------------------- */ static int GetOSTypeFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr, /* The object from which to get an OSType. */ OSType *osTypePtr) /* Place to store resulting OSType. */ { int result = TCL_OK; if (objPtr->typePtr != &tclOSTypeType) { result = SetOSTypeFromAny(interp, objPtr); } *osTypePtr = (OSType) objPtr->internalRep.longValue; return result; } /* *---------------------------------------------------------------------- * * NewOSTypeObj -- * * Create a new OSType object. * * Results: * The newly created OSType object is returned, it has ref count 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Tcl_Obj * NewOSTypeObj( const OSType osType) /* OSType used to initialize the new * object. */ { Tcl_Obj *objPtr; TclNewObj(objPtr); TclInvalidateStringRep(objPtr); objPtr->internalRep.longValue = (long) osType; objPtr->typePtr = &tclOSTypeType; return objPtr; } /* *---------------------------------------------------------------------- * * SetOSTypeFromAny -- * * Attempts to force the internal representation for a Tcl object to * tclOSTypeType, specifically. * * Results: * The return value is a standard object Tcl result. If an error occurs * during conversion, an error message is left in the interpreter's * result unless "interp" is NULL. * *---------------------------------------------------------------------- */ static int SetOSTypeFromAny( Tcl_Interp *interp, /* Tcl interpreter */ Tcl_Obj *objPtr) /* Pointer to the object to convert */ { const char *string; int length, result = TCL_OK; Tcl_DString ds; Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman"); string = Tcl_GetStringFromObj(objPtr, &length); Tcl_UtfToExternalDString(encoding, string, length, &ds); if (Tcl_DStringLength(&ds) > 4) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected Macintosh OS type but got \"%s\": ", string)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "MAC_OSTYPE", NULL); } result = TCL_ERROR; } else { OSType osType; char bytes[4] = {'\0','\0','\0','\0'}; memcpy(bytes, Tcl_DStringValue(&ds), (size_t)Tcl_DStringLength(&ds)); osType = (OSType) bytes[0] << 24 | (OSType) bytes[1] << 16 | (OSType) bytes[2] << 8 | (OSType) bytes[3]; TclFreeIntRep(objPtr); objPtr->internalRep.longValue = (long) osType; objPtr->typePtr = &tclOSTypeType; } Tcl_DStringFree(&ds); Tcl_FreeEncoding(encoding); return result; } /* *---------------------------------------------------------------------- * * UpdateStringOfOSType -- * * Update the string representation for an OSType object. Note: This * function does not free an existing old string rep so storage will be * lost if this has not already been done. * * Results: * None. * * Side effects: * The object's string is set to a valid string that results from the * OSType-to-string conversion. * *---------------------------------------------------------------------- */ static void UpdateStringOfOSType( register Tcl_Obj *objPtr) /* OSType object whose string rep to * update. */ { char string[5]; OSType osType = (OSType) objPtr->internalRep.longValue; Tcl_DString ds; Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman"); unsigned len; string[0] = (char) (osType >> 24); string[1] = (char) (osType >> 16); string[2] = (char) (osType >> 8); string[3] = (char) (osType); string[4] = '\0'; Tcl_ExternalToUtfDString(encoding, string, -1, &ds); len = (unsigned) Tcl_DStringLength(&ds) + 1; objPtr->bytes = ckalloc(len); memcpy(objPtr->bytes, Tcl_DStringValue(&ds), len); objPtr->length = Tcl_DStringLength(&ds); Tcl_DStringFree(&ds); Tcl_FreeEncoding(encoding); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/macosx/Tcl.xcodeproj/0000755000175000017500000000000012665173607015602 5ustar sergeisergeitcl8.6.5/macosx/Tcl.xcodeproj/project.pbxproj0000644000175000017500000067602112663660066020670 0ustar sergeisergei// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ F90509300913A72400327603 /* tclAppInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445508F272B9004A47F5 /* tclAppInit.c */; settings = {COMPILER_FLAGS = "-DTCL_TEST -DTCL_BUILDTIME_LIBRARY=\\\"$(TCL_SRCROOT)/library\\\""; }; }; F93599B30DF1F75400E04F67 /* tclOO.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B20DF1F75400E04F67 /* tclOO.c */; }; F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B60DF1F76100E04F67 /* tclOOBasic.c */; }; F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B80DF1F76600E04F67 /* tclOOCall.c */; }; F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */; }; F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BD0DF1F77400E04F67 /* tclOOInfo.c */; }; F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C10DF1F78300E04F67 /* tclOOMethod.c */; }; F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C30DF1F78800E04F67 /* tclOOStubInit.c */; }; F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */; }; F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */ = {isa = PBXBuildFile; fileRef = F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */; }; F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96437C90EF0D4B2003F468E /* tclZlib.c */; }; F96437E70EF0D652003F468E /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F96437E60EF0D652003F468E /* libz.dylib */; }; F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07408F2820D005CB29B /* CoreFoundation.framework */; }; F96D456F08F272BB004A47F5 /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED008F272A7004A47F5 /* regcomp.c */; }; F96D457208F272BB004A47F5 /* regerror.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED308F272A7004A47F5 /* regerror.c */; }; F96D457508F272BB004A47F5 /* regexec.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED608F272A7004A47F5 /* regexec.c */; }; F96D457608F272BB004A47F5 /* regfree.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED708F272A7004A47F5 /* regfree.c */; }; F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDC08F272A7004A47F5 /* tclAlloc.c */; settings = {COMPILER_FLAGS = "-DUSE_TCLALLOC=0"; }; }; F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDD08F272A7004A47F5 /* tclAsync.c */; }; F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDE08F272A7004A47F5 /* tclBasic.c */; }; F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDF08F272A7004A47F5 /* tclBinary.c */; }; F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE008F272A7004A47F5 /* tclCkalloc.c */; }; F96D458008F272BC004A47F5 /* tclClock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE108F272A7004A47F5 /* tclClock.c */; }; F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE208F272A7004A47F5 /* tclCmdAH.c */; }; F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE308F272A7004A47F5 /* tclCmdIL.c */; }; F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */; }; F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE508F272A7004A47F5 /* tclCompCmds.c */; }; F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE608F272A7004A47F5 /* tclCompExpr.c */; }; F96D458608F272BC004A47F5 /* tclCompile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE708F272A7004A47F5 /* tclCompile.c */; }; F96D458808F272BC004A47F5 /* tclConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE908F272A7004A47F5 /* tclConfig.c */; }; F96D458908F272BC004A47F5 /* tclDate.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEA08F272A7004A47F5 /* tclDate.c */; }; F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEC08F272A7004A47F5 /* tclDictObj.c */; }; F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EED08F272A7004A47F5 /* tclEncoding.c */; }; F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEE08F272A7004A47F5 /* tclEnv.c */; }; F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEF08F272A7004A47F5 /* tclEvent.c */; }; F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF008F272A7004A47F5 /* tclExecute.c */; }; F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF108F272A7004A47F5 /* tclFCmd.c */; }; F96D459108F272BC004A47F5 /* tclFileName.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF208F272A7004A47F5 /* tclFileName.c */; }; F96D459308F272BC004A47F5 /* tclGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF408F272A7004A47F5 /* tclGet.c */; }; F96D459508F272BC004A47F5 /* tclHash.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF608F272A7004A47F5 /* tclHash.c */; }; F96D459608F272BC004A47F5 /* tclHistory.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF708F272A7004A47F5 /* tclHistory.c */; }; F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF808F272A7004A47F5 /* tclIndexObj.c */; }; F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFC08F272A7004A47F5 /* tclInterp.c */; }; F96D459D08F272BC004A47F5 /* tclIO.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFE08F272A7004A47F5 /* tclIO.c */; }; F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0008F272A7004A47F5 /* tclIOCmd.c */; }; F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0108F272A7004A47F5 /* tclIOGT.c */; }; F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0208F272A7004A47F5 /* tclIORChan.c */; }; F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0308F272A7004A47F5 /* tclIOSock.c */; }; F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0408F272A7004A47F5 /* tclIOUtil.c */; }; F96D45A408F272BC004A47F5 /* tclLink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0508F272A7004A47F5 /* tclLink.c */; }; F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0608F272A7004A47F5 /* tclListObj.c */; }; F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0708F272A7004A47F5 /* tclLiteral.c */; }; F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0808F272A7004A47F5 /* tclLoad.c */; }; F96D45A908F272BC004A47F5 /* tclMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0A08F272A7004A47F5 /* tclMain.c */; }; F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0B08F272A7004A47F5 /* tclNamesp.c */; }; F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0C08F272A7004A47F5 /* tclNotify.c */; }; F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0D08F272A7004A47F5 /* tclObj.c */; }; F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0E08F272A7004A47F5 /* tclPanic.c */; }; F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0F08F272A7004A47F5 /* tclParse.c */; }; F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1108F272A7004A47F5 /* tclPathObj.c */; }; F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1208F272A7004A47F5 /* tclPipe.c */; }; F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1308F272A7004A47F5 /* tclPkg.c */; }; F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */; settings = {COMPILER_FLAGS = "-DCFG_INSTALL_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_INSTALL_BINDIR=\\\"$(BINDIR)\\\" -DCFG_INSTALL_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_INSTALL_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_INSTALL_DOCDIR=\\\"$(MANDIR)\\\" -DCFG_RUNTIME_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_RUNTIME_BINDIR=\\\"$(BINDIR)\\\" -DCFG_RUNTIME_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_RUNTIME_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_RUNTIME_DOCDIR=\\\"$(MANDIR)\\\""; }; }; F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1708F272A7004A47F5 /* tclPosixStr.c */; }; F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1808F272A7004A47F5 /* tclPreserve.c */; }; F96D45B808F272BC004A47F5 /* tclProc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1908F272A7004A47F5 /* tclProc.c */; }; F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1A08F272A7004A47F5 /* tclRegexp.c */; }; F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1C08F272A7004A47F5 /* tclResolve.c */; }; F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1D08F272A7004A47F5 /* tclResult.c */; }; F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1E08F272A7004A47F5 /* tclScan.c */; }; F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1F08F272A7004A47F5 /* tclStringObj.c */; }; F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2408F272A7004A47F5 /* tclStrToD.c */; }; F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2508F272A7004A47F5 /* tclStubInit.c */; }; F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2608F272A7004A47F5 /* tclStubLib.c */; }; F96D45C608F272BC004A47F5 /* tclTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2708F272A7004A47F5 /* tclTest.c */; }; F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2808F272A7004A47F5 /* tclTestObj.c */; }; F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */; }; F96D45C908F272BC004A47F5 /* tclThread.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2A08F272A7004A47F5 /* tclThread.c */; }; F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */; }; F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */; }; F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */; }; F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */; }; F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2F08F272A7004A47F5 /* tclTimer.c */; }; F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */; }; F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3208F272A7004A47F5 /* tclTrace.c */; }; F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3408F272A7004A47F5 /* tclUtf.c */; }; F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3508F272A7004A47F5 /* tclUtil.c */; }; F96D45D508F272BC004A47F5 /* tclVar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3608F272A7004A47F5 /* tclVar.c */; }; F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */; }; F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */; }; F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426908F272B3004A47F5 /* bn_mp_add.c */; }; F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */; }; F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */; }; F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426E08F272B3004A47F5 /* bn_mp_clear.c */; }; F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */; }; F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427008F272B3004A47F5 /* bn_mp_cmp.c */; }; F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; }; F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_cnt_lsb.c */; }; F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; }; F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; }; F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; }; F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; }; F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; }; F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_mp_div_3.c */; }; F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; }; F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; }; F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; }; F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428808F272B3004A47F5 /* bn_mp_init.c */; }; F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */; }; F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */; }; F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */; }; F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */; }; F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */; }; F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */; }; F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429508F272B3004A47F5 /* bn_mp_lshd.c */; }; F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429608F272B3004A47F5 /* bn_mp_mod.c */; }; F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */; }; F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429C08F272B3004A47F5 /* bn_mp_mul.c */; }; F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */; }; F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */; }; F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */; }; F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */; }; F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */; }; F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */; }; F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */; }; F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BA08F272B3004A47F5 /* bn_mp_set.c */; }; F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */; }; F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C108F272B3004A47F5 /* bn_mp_sub.c */; }; F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */; }; F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */; }; F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */; }; F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */; }; F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */; }; F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D008F272B3004A47F5 /* bn_reverse.c */; }; F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */; }; F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */; }; F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */; }; F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */; }; F96D495508F272C3004A47F5 /* bncore.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D708F272B3004A47F5 /* bncore.c */; }; F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */; }; F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */; }; F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */; }; F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445B08F272B9004A47F5 /* tclLoadDyld.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; }; F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445F08F272B9004A47F5 /* tclUnixChan.c */; }; F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446008F272B9004A47F5 /* tclUnixEvent.c */; }; F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446108F272B9004A47F5 /* tclUnixFCmd.c */; }; F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446208F272B9004A47F5 /* tclUnixFile.c */; }; F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446308F272B9004A47F5 /* tclUnixInit.c */; settings = {COMPILER_FLAGS = "-DTCL_LIBRARY=\\\"$(TCL_LIBRARY)\\\" -DTCL_PACKAGE_PATH=\\\"$(TCL_PACKAGE_PATH)\\\""; }; }; F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446408F272B9004A47F5 /* tclUnixNotfy.c */; }; F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446508F272B9004A47F5 /* tclUnixPipe.c */; }; F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446708F272B9004A47F5 /* tclUnixSock.c */; }; F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446808F272B9004A47F5 /* tclUnixTest.c */; }; F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; }; F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; }; F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; }; F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; }; F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; }; F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; }; F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */; }; F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; }; F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; }; F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; }; F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */; }; F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */; }; F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */; }; F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */ = {isa = PBXBuildFile; fileRef = F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */; }; F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */ = {isa = PBXBuildFile; fileRef = F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ F97258D20A868C6F00096C78 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 8DD76FA90486AB0100D96B5E; remoteInfo = tcltest; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 8DD76FB20486AB0100D96B5E /* tcltest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tcltest; sourceTree = BUILT_PRODUCTS_DIR; }; F915432A0EF201CF0032D1E8 /* zlib.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = zlib.test; sourceTree = ""; }; F915432D0EF201EE0032D1E8 /* zlib.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = zlib.n; sourceTree = ""; }; F9183E640EFC80CD0030B814 /* throw.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = throw.n; sourceTree = ""; }; F9183E650EFC80D70030B814 /* try.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = try.n; sourceTree = ""; }; F9183E6A0EFC81560030B814 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F9183E8F0EFC817B0030B814 /* tdbc */ = {isa = PBXFileReference; lastKnownFileType = folder; path = tdbc; sourceTree = ""; }; F91DC23C0E44C51B002CB8D1 /* nre.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = nre.test; sourceTree = ""; }; F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "Tclsh-Info.plist.in"; sourceTree = ""; }; F92D7F100DE777240033A13A /* tsdPerf.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tsdPerf.tcl; sourceTree = ""; }; F93599B20DF1F75400E04F67 /* tclOO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOO.c; sourceTree = ""; }; F93599B40DF1F75900E04F67 /* tclOO.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclOO.decls; sourceTree = ""; }; F93599B50DF1F75D00E04F67 /* tclOO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOO.h; sourceTree = ""; }; F93599B60DF1F76100E04F67 /* tclOOBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOBasic.c; sourceTree = ""; }; F93599B80DF1F76600E04F67 /* tclOOCall.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOCall.c; sourceTree = ""; }; F93599BA0DF1F76A00E04F67 /* tclOODecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOODecls.h; sourceTree = ""; }; F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOODefineCmds.c; sourceTree = ""; }; F93599BD0DF1F77400E04F67 /* tclOOInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOInfo.c; sourceTree = ""; }; F93599BF0DF1F77900E04F67 /* tclOOInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOInt.h; sourceTree = ""; }; F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOIntDecls.h; sourceTree = ""; }; F93599C10DF1F78300E04F67 /* tclOOMethod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOMethod.c; sourceTree = ""; }; F93599C30DF1F78800E04F67 /* tclOOStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubInit.c; sourceTree = ""; }; F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubLib.c; sourceTree = ""; }; F93599C80DF1F81900E04F67 /* oo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = oo.test; sourceTree = ""; }; F93599CF0DF1F87F00E04F67 /* Class.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Class.3; sourceTree = ""; }; F93599D00DF1F89E00E04F67 /* class.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = class.n; sourceTree = ""; }; F93599D20DF1F8DF00E04F67 /* copy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = copy.n; sourceTree = ""; }; F93599D30DF1F8F500E04F67 /* define.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = define.n; sourceTree = ""; }; F93599D40DF1F91900E04F67 /* Method.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Method.3; sourceTree = ""; }; F93599D50DF1F93700E04F67 /* my.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = my.n; sourceTree = ""; }; F93599D60DF1F95000E04F67 /* next.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = next.n; sourceTree = ""; }; F93599D70DF1F96800E04F67 /* object.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = object.n; sourceTree = ""; }; F93599D80DF1F98300E04F67 /* self.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = self.n; sourceTree = ""; }; F946FB8B0FBE3AED00CD6495 /* itcl */ = {isa = PBXFileReference; lastKnownFileType = folder; path = itcl; sourceTree = ""; }; F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORTrans.c; sourceTree = ""; }; F95FAFF90B34F1130072E431 /* macOSXLoad.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXLoad.test; sourceTree = ""; }; F96437C90EF0D4B2003F468E /* tclZlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclZlib.c; sourceTree = ""; }; F96437E60EF0D652003F468E /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = ""; }; F966C07408F2820D005CB29B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; F96D3DFA08F272A4004A47F5 /* ChangeLog */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = ChangeLog; sourceTree = ""; }; F96D3DFB08F272A4004A47F5 /* changes */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes; sourceTree = ""; }; F96D3DFD08F272A4004A47F5 /* Access.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Access.3; sourceTree = ""; }; F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AddErrInfo.3; sourceTree = ""; }; F96D3DFF08F272A4004A47F5 /* after.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = after.n; sourceTree = ""; }; F96D3E0008F272A4004A47F5 /* Alloc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Alloc.3; sourceTree = ""; }; F96D3E0108F272A4004A47F5 /* AllowExc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AllowExc.3; sourceTree = ""; }; F96D3E0208F272A4004A47F5 /* append.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = append.n; sourceTree = ""; }; F96D3E0308F272A4004A47F5 /* AppInit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AppInit.3; sourceTree = ""; }; F96D3E0408F272A5004A47F5 /* array.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = array.n; sourceTree = ""; }; F96D3E0508F272A5004A47F5 /* AssocData.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AssocData.3; sourceTree = ""; }; F96D3E0608F272A5004A47F5 /* Async.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Async.3; sourceTree = ""; }; F96D3E0708F272A5004A47F5 /* BackgdErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BackgdErr.3; sourceTree = ""; }; F96D3E0808F272A5004A47F5 /* Backslash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Backslash.3; sourceTree = ""; }; F96D3E0908F272A5004A47F5 /* bgerror.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bgerror.n; sourceTree = ""; }; F96D3E0A08F272A5004A47F5 /* binary.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = binary.n; sourceTree = ""; }; F96D3E0B08F272A5004A47F5 /* BoolObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BoolObj.3; sourceTree = ""; }; F96D3E0C08F272A5004A47F5 /* break.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = break.n; sourceTree = ""; }; F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ByteArrObj.3; sourceTree = ""; }; F96D3E0E08F272A5004A47F5 /* CallDel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CallDel.3; sourceTree = ""; }; F96D3E0F08F272A5004A47F5 /* case.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = case.n; sourceTree = ""; }; F96D3E1008F272A5004A47F5 /* catch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = catch.n; sourceTree = ""; }; F96D3E1108F272A5004A47F5 /* cd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = cd.n; sourceTree = ""; }; F96D3E1208F272A5004A47F5 /* chan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chan.n; sourceTree = ""; }; F96D3E1308F272A5004A47F5 /* ChnlStack.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ChnlStack.3; sourceTree = ""; }; F96D3E1408F272A5004A47F5 /* clock.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = clock.n; sourceTree = ""; }; F96D3E1508F272A5004A47F5 /* close.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = close.n; sourceTree = ""; }; F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CmdCmplt.3; sourceTree = ""; }; F96D3E1708F272A5004A47F5 /* Concat.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Concat.3; sourceTree = ""; }; F96D3E1808F272A5004A47F5 /* concat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = concat.n; sourceTree = ""; }; F96D3E1908F272A5004A47F5 /* continue.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = continue.n; sourceTree = ""; }; F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChannel.3; sourceTree = ""; }; F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChnlHdlr.3; sourceTree = ""; }; F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCloseHdlr.3; sourceTree = ""; }; F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCommand.3; sourceTree = ""; }; F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtFileHdlr.3; sourceTree = ""; }; F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = ""; }; F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = ""; }; F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = ""; }; F96D3E2208F272A5004A47F5 /* CrtSlave.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSlave.3; sourceTree = ""; }; F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = ""; }; F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = ""; }; F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = ""; }; F96D3E2608F272A5004A47F5 /* DetachPids.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DetachPids.3; sourceTree = ""; }; F96D3E2708F272A5004A47F5 /* dict.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dict.n; sourceTree = ""; }; F96D3E2808F272A5004A47F5 /* DictObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DictObj.3; sourceTree = ""; }; F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoOneEvent.3; sourceTree = ""; }; F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoubleObj.3; sourceTree = ""; }; F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoWhenIdle.3; sourceTree = ""; }; F96D3E2C08F272A5004A47F5 /* DString.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DString.3; sourceTree = ""; }; F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DumpActiveMemory.3; sourceTree = ""; }; F96D3E2E08F272A5004A47F5 /* Encoding.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Encoding.3; sourceTree = ""; }; F96D3E2F08F272A5004A47F5 /* encoding.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = encoding.n; sourceTree = ""; }; F96D3E3008F272A5004A47F5 /* Ensemble.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Ensemble.3; sourceTree = ""; }; F96D3E3108F272A5004A47F5 /* Environment.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Environment.3; sourceTree = ""; }; F96D3E3208F272A5004A47F5 /* eof.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eof.n; sourceTree = ""; }; F96D3E3308F272A5004A47F5 /* error.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = error.n; sourceTree = ""; }; F96D3E3408F272A5004A47F5 /* Eval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Eval.3; sourceTree = ""; }; F96D3E3508F272A5004A47F5 /* eval.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eval.n; sourceTree = ""; }; F96D3E3608F272A5004A47F5 /* exec.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exec.n; sourceTree = ""; }; F96D3E3708F272A5004A47F5 /* Exit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Exit.3; sourceTree = ""; }; F96D3E3808F272A5004A47F5 /* exit.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exit.n; sourceTree = ""; }; F96D3E3908F272A5004A47F5 /* expr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = expr.n; sourceTree = ""; }; F96D3E3A08F272A5004A47F5 /* ExprLong.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLong.3; sourceTree = ""; }; F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLongObj.3; sourceTree = ""; }; F96D3E3C08F272A5004A47F5 /* fblocked.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fblocked.n; sourceTree = ""; }; F96D3E3D08F272A5004A47F5 /* fconfigure.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fconfigure.n; sourceTree = ""; }; F96D3E3E08F272A5004A47F5 /* fcopy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fcopy.n; sourceTree = ""; }; F96D3E3F08F272A5004A47F5 /* file.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = file.n; sourceTree = ""; }; F96D3E4008F272A5004A47F5 /* fileevent.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fileevent.n; sourceTree = ""; }; F96D3E4108F272A5004A47F5 /* filename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = filename.n; sourceTree = ""; }; F96D3E4208F272A5004A47F5 /* FileSystem.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FileSystem.3; sourceTree = ""; }; F96D3E4308F272A5004A47F5 /* FindExec.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FindExec.3; sourceTree = ""; }; F96D3E4408F272A5004A47F5 /* flush.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = flush.n; sourceTree = ""; }; F96D3E4508F272A5004A47F5 /* for.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = for.n; sourceTree = ""; }; F96D3E4608F272A5004A47F5 /* foreach.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = foreach.n; sourceTree = ""; }; F96D3E4708F272A5004A47F5 /* format.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = format.n; sourceTree = ""; }; F96D3E4808F272A5004A47F5 /* GetCwd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCwd.3; sourceTree = ""; }; F96D3E4908F272A5004A47F5 /* GetHostName.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHostName.3; sourceTree = ""; }; F96D3E4A08F272A5004A47F5 /* GetIndex.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetIndex.3; sourceTree = ""; }; F96D3E4B08F272A5004A47F5 /* GetInt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetInt.3; sourceTree = ""; }; F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetOpnFl.3; sourceTree = ""; }; F96D3E4D08F272A5004A47F5 /* gets.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = gets.n; sourceTree = ""; }; F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetStdChan.3; sourceTree = ""; }; F96D3E4F08F272A5004A47F5 /* GetTime.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetTime.3; sourceTree = ""; }; F96D3E5008F272A5004A47F5 /* GetVersion.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVersion.3; sourceTree = ""; }; F96D3E5108F272A5004A47F5 /* glob.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = glob.n; sourceTree = ""; }; F96D3E5208F272A6004A47F5 /* global.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = global.n; sourceTree = ""; }; F96D3E5308F272A6004A47F5 /* Hash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Hash.3; sourceTree = ""; }; F96D3E5408F272A6004A47F5 /* history.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = history.n; sourceTree = ""; }; F96D3E5508F272A6004A47F5 /* http.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = http.n; sourceTree = ""; }; F96D3E5608F272A6004A47F5 /* if.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = if.n; sourceTree = ""; }; F96D3E5708F272A6004A47F5 /* incr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = incr.n; sourceTree = ""; }; F96D3E5808F272A6004A47F5 /* info.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = info.n; sourceTree = ""; }; F96D3E5908F272A6004A47F5 /* Init.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Init.3; sourceTree = ""; }; F96D3E5A08F272A6004A47F5 /* InitStubs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = InitStubs.3; sourceTree = ""; }; F96D3E5B08F272A6004A47F5 /* Interp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Interp.3; sourceTree = ""; }; F96D3E5C08F272A6004A47F5 /* interp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = interp.n; sourceTree = ""; }; F96D3E5D08F272A6004A47F5 /* IntObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = IntObj.3; sourceTree = ""; }; F96D3E5E08F272A6004A47F5 /* join.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = join.n; sourceTree = ""; }; F96D3E5F08F272A6004A47F5 /* lappend.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lappend.n; sourceTree = ""; }; F96D3E6008F272A6004A47F5 /* lassign.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lassign.n; sourceTree = ""; }; F96D3E6108F272A6004A47F5 /* library.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = library.n; sourceTree = ""; }; F96D3E6208F272A6004A47F5 /* Limit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Limit.3; sourceTree = ""; }; F96D3E6308F272A6004A47F5 /* lindex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lindex.n; sourceTree = ""; }; F96D3E6408F272A6004A47F5 /* LinkVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = LinkVar.3; sourceTree = ""; }; F96D3E6508F272A6004A47F5 /* linsert.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = linsert.n; sourceTree = ""; }; F96D3E6608F272A6004A47F5 /* list.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = list.n; sourceTree = ""; }; F96D3E6708F272A6004A47F5 /* ListObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ListObj.3; sourceTree = ""; }; F96D3E6808F272A6004A47F5 /* llength.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = llength.n; sourceTree = ""; }; F96D3E6908F272A6004A47F5 /* load.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = load.n; sourceTree = ""; }; F96D3E6A08F272A6004A47F5 /* lrange.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrange.n; sourceTree = ""; }; F96D3E6B08F272A6004A47F5 /* lrepeat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrepeat.n; sourceTree = ""; }; F96D3E6C08F272A6004A47F5 /* lreplace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lreplace.n; sourceTree = ""; }; F96D3E6D08F272A6004A47F5 /* lsearch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsearch.n; sourceTree = ""; }; F96D3E6E08F272A6004A47F5 /* lset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lset.n; sourceTree = ""; }; F96D3E6F08F272A6004A47F5 /* lsort.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsort.n; sourceTree = ""; }; F96D3E7008F272A6004A47F5 /* man.macros */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = man.macros; sourceTree = ""; }; F96D3E7108F272A6004A47F5 /* mathfunc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = mathfunc.n; sourceTree = ""; }; F96D3E7208F272A6004A47F5 /* memory.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = memory.n; sourceTree = ""; }; F96D3E7308F272A6004A47F5 /* msgcat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = msgcat.n; sourceTree = ""; }; F96D3E7408F272A6004A47F5 /* Namespace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Namespace.3; sourceTree = ""; }; F96D3E7508F272A6004A47F5 /* namespace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = namespace.n; sourceTree = ""; }; F96D3E7608F272A6004A47F5 /* Notifier.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Notifier.3; sourceTree = ""; }; F96D3E7708F272A6004A47F5 /* Object.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Object.3; sourceTree = ""; }; F96D3E7808F272A6004A47F5 /* ObjectType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ObjectType.3; sourceTree = ""; }; F96D3E7908F272A6004A47F5 /* open.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = open.n; sourceTree = ""; }; F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenFileChnl.3; sourceTree = ""; }; F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenTcp.3; sourceTree = ""; }; F96D3E7C08F272A6004A47F5 /* package.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = package.n; sourceTree = ""; }; F96D3E7D08F272A6004A47F5 /* packagens.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = packagens.n; sourceTree = ""; }; F96D3E7E08F272A6004A47F5 /* Panic.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Panic.3; sourceTree = ""; }; F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ParseCmd.3; sourceTree = ""; }; F96D3E8008F272A6004A47F5 /* pid.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pid.n; sourceTree = ""; }; F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pkgMkIndex.n; sourceTree = ""; }; F96D3E8208F272A6004A47F5 /* PkgRequire.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PkgRequire.3; sourceTree = ""; }; F96D3E8308F272A6004A47F5 /* Preserve.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Preserve.3; sourceTree = ""; }; F96D3E8408F272A6004A47F5 /* PrintDbl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PrintDbl.3; sourceTree = ""; }; F96D3E8508F272A6004A47F5 /* proc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = proc.n; sourceTree = ""; }; F96D3E8608F272A6004A47F5 /* puts.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = puts.n; sourceTree = ""; }; F96D3E8708F272A6004A47F5 /* pwd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pwd.n; sourceTree = ""; }; F96D3E8808F272A6004A47F5 /* re_syntax.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = re_syntax.n; sourceTree = ""; }; F96D3E8908F272A6004A47F5 /* read.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = read.n; sourceTree = ""; }; F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecEvalObj.3; sourceTree = ""; }; F96D3E8B08F272A6004A47F5 /* RecordEval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecordEval.3; sourceTree = ""; }; F96D3E8C08F272A6004A47F5 /* RegConfig.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegConfig.3; sourceTree = ""; }; F96D3E8D08F272A6004A47F5 /* RegExp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegExp.3; sourceTree = ""; }; F96D3E8E08F272A6004A47F5 /* regexp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regexp.n; sourceTree = ""; }; F96D3E8F08F272A6004A47F5 /* registry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = registry.n; sourceTree = ""; }; F96D3E9008F272A6004A47F5 /* regsub.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regsub.n; sourceTree = ""; }; F96D3E9108F272A6004A47F5 /* rename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = rename.n; sourceTree = ""; }; F96D3E9208F272A6004A47F5 /* return.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = return.n; sourceTree = ""; }; F96D3E9308F272A6004A47F5 /* safe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = safe.n; sourceTree = ""; }; F96D3E9408F272A6004A47F5 /* SaveResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SaveResult.3; sourceTree = ""; }; F96D3E9508F272A6004A47F5 /* scan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scan.n; sourceTree = ""; }; F96D3E9608F272A6004A47F5 /* seek.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = seek.n; sourceTree = ""; }; F96D3E9708F272A6004A47F5 /* set.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = set.n; sourceTree = ""; }; F96D3E9808F272A6004A47F5 /* SetChanErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetChanErr.3; sourceTree = ""; }; F96D3E9908F272A6004A47F5 /* SetErrno.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetErrno.3; sourceTree = ""; }; F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetRecLmt.3; sourceTree = ""; }; F96D3E9B08F272A7004A47F5 /* SetResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetResult.3; sourceTree = ""; }; F96D3E9C08F272A7004A47F5 /* SetVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetVar.3; sourceTree = ""; }; F96D3E9D08F272A7004A47F5 /* Signal.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Signal.3; sourceTree = ""; }; F96D3E9E08F272A7004A47F5 /* Sleep.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Sleep.3; sourceTree = ""; }; F96D3E9F08F272A7004A47F5 /* socket.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = socket.n; sourceTree = ""; }; F96D3EA008F272A7004A47F5 /* source.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = source.n; sourceTree = ""; }; F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SourceRCFile.3; sourceTree = ""; }; F96D3EA208F272A7004A47F5 /* split.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = split.n; sourceTree = ""; }; F96D3EA308F272A7004A47F5 /* SplitList.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitList.3; sourceTree = ""; }; F96D3EA408F272A7004A47F5 /* SplitPath.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitPath.3; sourceTree = ""; }; F96D3EA508F272A7004A47F5 /* StaticPkg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticPkg.3; sourceTree = ""; }; F96D3EA608F272A7004A47F5 /* StdChannels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StdChannels.3; sourceTree = ""; }; F96D3EA708F272A7004A47F5 /* string.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = string.n; sourceTree = ""; }; F96D3EA808F272A7004A47F5 /* StringObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StringObj.3; sourceTree = ""; }; F96D3EA908F272A7004A47F5 /* StrMatch.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StrMatch.3; sourceTree = ""; }; F96D3EAA08F272A7004A47F5 /* subst.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = subst.n; sourceTree = ""; }; F96D3EAB08F272A7004A47F5 /* SubstObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SubstObj.3; sourceTree = ""; }; F96D3EAC08F272A7004A47F5 /* switch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = switch.n; sourceTree = ""; }; F96D3EAD08F272A7004A47F5 /* Tcl.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl.n; sourceTree = ""; }; F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl_Main.3; sourceTree = ""; }; F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TCL_MEM_DEBUG.3; sourceTree = ""; }; F96D3EB008F272A7004A47F5 /* tclsh.1 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclsh.1; sourceTree = ""; }; F96D3EB108F272A7004A47F5 /* tcltest.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tcltest.n; sourceTree = ""; }; F96D3EB208F272A7004A47F5 /* tclvars.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclvars.n; sourceTree = ""; }; F96D3EB308F272A7004A47F5 /* tell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tell.n; sourceTree = ""; }; F96D3EB408F272A7004A47F5 /* Thread.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Thread.3; sourceTree = ""; }; F96D3EB508F272A7004A47F5 /* time.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = time.n; sourceTree = ""; }; F96D3EB608F272A7004A47F5 /* tm.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tm.n; sourceTree = ""; }; F96D3EB708F272A7004A47F5 /* ToUpper.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ToUpper.3; sourceTree = ""; }; F96D3EB808F272A7004A47F5 /* trace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = trace.n; sourceTree = ""; }; F96D3EB908F272A7004A47F5 /* TraceCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceCmd.3; sourceTree = ""; }; F96D3EBA08F272A7004A47F5 /* TraceVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceVar.3; sourceTree = ""; }; F96D3EBB08F272A7004A47F5 /* Translate.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Translate.3; sourceTree = ""; }; F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UniCharIsAlpha.3; sourceTree = ""; }; F96D3EBD08F272A7004A47F5 /* unknown.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unknown.n; sourceTree = ""; }; F96D3EBE08F272A7004A47F5 /* unload.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unload.n; sourceTree = ""; }; F96D3EBF08F272A7004A47F5 /* unset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unset.n; sourceTree = ""; }; F96D3EC008F272A7004A47F5 /* update.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = update.n; sourceTree = ""; }; F96D3EC108F272A7004A47F5 /* uplevel.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = uplevel.n; sourceTree = ""; }; F96D3EC208F272A7004A47F5 /* UpVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UpVar.3; sourceTree = ""; }; F96D3EC308F272A7004A47F5 /* upvar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = upvar.n; sourceTree = ""; }; F96D3EC408F272A7004A47F5 /* Utf.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Utf.3; sourceTree = ""; }; F96D3EC508F272A7004A47F5 /* variable.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = variable.n; sourceTree = ""; }; F96D3EC608F272A7004A47F5 /* vwait.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = vwait.n; sourceTree = ""; }; F96D3EC708F272A7004A47F5 /* while.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = while.n; sourceTree = ""; }; F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = WrongNumArgs.3; sourceTree = ""; }; F96D3ECA08F272A7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D3ECB08F272A7004A47F5 /* regc_color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_color.c; sourceTree = ""; }; F96D3ECC08F272A7004A47F5 /* regc_cvec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_cvec.c; sourceTree = ""; }; F96D3ECD08F272A7004A47F5 /* regc_lex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_lex.c; sourceTree = ""; }; F96D3ECE08F272A7004A47F5 /* regc_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_locale.c; sourceTree = ""; }; F96D3ECF08F272A7004A47F5 /* regc_nfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_nfa.c; sourceTree = ""; }; F96D3ED008F272A7004A47F5 /* regcomp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regcomp.c; sourceTree = ""; }; F96D3ED108F272A7004A47F5 /* regcustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regcustom.h; sourceTree = ""; }; F96D3ED208F272A7004A47F5 /* rege_dfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rege_dfa.c; sourceTree = ""; }; F96D3ED308F272A7004A47F5 /* regerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regerror.c; sourceTree = ""; }; F96D3ED408F272A7004A47F5 /* regerrs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regerrs.h; sourceTree = ""; }; F96D3ED508F272A7004A47F5 /* regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regex.h; sourceTree = ""; }; F96D3ED608F272A7004A47F5 /* regexec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regexec.c; sourceTree = ""; }; F96D3ED708F272A7004A47F5 /* regfree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfree.c; sourceTree = ""; }; F96D3ED808F272A7004A47F5 /* regfronts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfronts.c; sourceTree = ""; }; F96D3ED908F272A7004A47F5 /* regguts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regguts.h; sourceTree = ""; }; F96D3EDA08F272A7004A47F5 /* tcl.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcl.decls; sourceTree = ""; }; F96D3EDB08F272A7004A47F5 /* tcl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tcl.h; sourceTree = ""; }; F96D3EDC08F272A7004A47F5 /* tclAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAlloc.c; sourceTree = ""; }; F96D3EDD08F272A7004A47F5 /* tclAsync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAsync.c; sourceTree = ""; }; F96D3EDE08F272A7004A47F5 /* tclBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBasic.c; sourceTree = ""; }; F96D3EDF08F272A7004A47F5 /* tclBinary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBinary.c; sourceTree = ""; }; F96D3EE008F272A7004A47F5 /* tclCkalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCkalloc.c; sourceTree = ""; }; F96D3EE108F272A7004A47F5 /* tclClock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclClock.c; sourceTree = ""; }; F96D3EE208F272A7004A47F5 /* tclCmdAH.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdAH.c; sourceTree = ""; }; F96D3EE308F272A7004A47F5 /* tclCmdIL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdIL.c; sourceTree = ""; }; F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdMZ.c; sourceTree = ""; }; F96D3EE508F272A7004A47F5 /* tclCompCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompCmds.c; sourceTree = ""; }; F96D3EE608F272A7004A47F5 /* tclCompExpr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompExpr.c; sourceTree = ""; }; F96D3EE708F272A7004A47F5 /* tclCompile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompile.c; sourceTree = ""; }; F96D3EE808F272A7004A47F5 /* tclCompile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclCompile.h; sourceTree = ""; }; F96D3EE908F272A7004A47F5 /* tclConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclConfig.c; sourceTree = ""; }; F96D3EEA08F272A7004A47F5 /* tclDate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDate.c; sourceTree = ""; }; F96D3EEB08F272A7004A47F5 /* tclDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclDecls.h; sourceTree = ""; }; F96D3EEC08F272A7004A47F5 /* tclDictObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDictObj.c; sourceTree = ""; }; F96D3EED08F272A7004A47F5 /* tclEncoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEncoding.c; sourceTree = ""; }; F96D3EEE08F272A7004A47F5 /* tclEnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEnv.c; sourceTree = ""; }; F96D3EEF08F272A7004A47F5 /* tclEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEvent.c; sourceTree = ""; }; F96D3EF008F272A7004A47F5 /* tclExecute.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclExecute.c; sourceTree = ""; }; F96D3EF108F272A7004A47F5 /* tclFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFCmd.c; sourceTree = ""; }; F96D3EF208F272A7004A47F5 /* tclFileName.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFileName.c; sourceTree = ""; }; F96D3EF308F272A7004A47F5 /* tclFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclFileSystem.h; sourceTree = ""; }; F96D3EF408F272A7004A47F5 /* tclGet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclGet.c; sourceTree = ""; }; F96D3EF508F272A7004A47F5 /* tclGetDate.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = tclGetDate.y; sourceTree = ""; }; F96D3EF608F272A7004A47F5 /* tclHash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHash.c; sourceTree = ""; }; F96D3EF708F272A7004A47F5 /* tclHistory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHistory.c; sourceTree = ""; }; F96D3EF808F272A7004A47F5 /* tclIndexObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIndexObj.c; sourceTree = ""; }; F96D3EF908F272A7004A47F5 /* tclInt.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclInt.decls; sourceTree = ""; }; F96D3EFA08F272A7004A47F5 /* tclInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclInt.h; sourceTree = ""; }; F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntDecls.h; sourceTree = ""; }; F96D3EFC08F272A7004A47F5 /* tclInterp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclInterp.c; sourceTree = ""; }; F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntPlatDecls.h; sourceTree = ""; }; F96D3EFE08F272A7004A47F5 /* tclIO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIO.c; sourceTree = ""; }; F96D3EFF08F272A7004A47F5 /* tclIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIO.h; sourceTree = ""; }; F96D3F0008F272A7004A47F5 /* tclIOCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOCmd.c; sourceTree = ""; }; F96D3F0108F272A7004A47F5 /* tclIOGT.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOGT.c; sourceTree = ""; }; F96D3F0208F272A7004A47F5 /* tclIORChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORChan.c; sourceTree = ""; }; F96D3F0308F272A7004A47F5 /* tclIOSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOSock.c; sourceTree = ""; }; F96D3F0408F272A7004A47F5 /* tclIOUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOUtil.c; sourceTree = ""; }; F96D3F0508F272A7004A47F5 /* tclLink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLink.c; sourceTree = ""; }; F96D3F0608F272A7004A47F5 /* tclListObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclListObj.c; sourceTree = ""; }; F96D3F0708F272A7004A47F5 /* tclLiteral.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLiteral.c; sourceTree = ""; }; F96D3F0808F272A7004A47F5 /* tclLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoad.c; sourceTree = ""; }; F96D3F0908F272A7004A47F5 /* tclLoadNone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNone.c; sourceTree = ""; }; F96D3F0A08F272A7004A47F5 /* tclMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMain.c; sourceTree = ""; }; F96D3F0B08F272A7004A47F5 /* tclNamesp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNamesp.c; sourceTree = ""; }; F96D3F0C08F272A7004A47F5 /* tclNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNotify.c; sourceTree = ""; }; F96D3F0D08F272A7004A47F5 /* tclObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclObj.c; sourceTree = ""; }; F96D3F0E08F272A7004A47F5 /* tclPanic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPanic.c; sourceTree = ""; }; F96D3F0F08F272A7004A47F5 /* tclParse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclParse.c; sourceTree = ""; }; F96D3F1108F272A7004A47F5 /* tclPathObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPathObj.c; sourceTree = ""; }; F96D3F1208F272A7004A47F5 /* tclPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPipe.c; sourceTree = ""; }; F96D3F1308F272A7004A47F5 /* tclPkg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkg.c; sourceTree = ""; }; F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkgConfig.c; sourceTree = ""; }; F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPlatDecls.h; sourceTree = ""; }; F96D3F1608F272A7004A47F5 /* tclPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPort.h; sourceTree = ""; }; F96D3F1708F272A7004A47F5 /* tclPosixStr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPosixStr.c; sourceTree = ""; }; F96D3F1808F272A7004A47F5 /* tclPreserve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPreserve.c; sourceTree = ""; }; F96D3F1908F272A7004A47F5 /* tclProc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclProc.c; sourceTree = ""; }; F96D3F1A08F272A7004A47F5 /* tclRegexp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclRegexp.c; sourceTree = ""; }; F96D3F1B08F272A7004A47F5 /* tclRegexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclRegexp.h; sourceTree = ""; }; F96D3F1C08F272A7004A47F5 /* tclResolve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResolve.c; sourceTree = ""; }; F96D3F1D08F272A7004A47F5 /* tclResult.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResult.c; sourceTree = ""; }; F96D3F1E08F272A7004A47F5 /* tclScan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclScan.c; sourceTree = ""; }; F96D3F1F08F272A7004A47F5 /* tclStringObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStringObj.c; sourceTree = ""; }; F96D3F2408F272A7004A47F5 /* tclStrToD.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStrToD.c; sourceTree = ""; }; F96D3F2508F272A7004A47F5 /* tclStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubInit.c; sourceTree = ""; }; F96D3F2608F272A7004A47F5 /* tclStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubLib.c; sourceTree = ""; }; F96D3F2708F272A7004A47F5 /* tclTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTest.c; sourceTree = ""; }; F96D3F2808F272A7004A47F5 /* tclTestObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestObj.c; sourceTree = ""; }; F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestProcBodyObj.c; sourceTree = ""; }; F96D3F2A08F272A7004A47F5 /* tclThread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThread.c; sourceTree = ""; }; F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadAlloc.c; sourceTree = ""; }; F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadJoin.c; sourceTree = ""; }; F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadStorage.c; sourceTree = ""; }; F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadTest.c; sourceTree = ""; }; F96D3F2F08F272A7004A47F5 /* tclTimer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTimer.c; sourceTree = ""; }; F96D3F3008F272A7004A47F5 /* tclTomMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMath.h; sourceTree = ""; }; F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTomMathInterface.c; sourceTree = ""; }; F96D3F3208F272A7004A47F5 /* tclTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTrace.c; sourceTree = ""; }; F96D3F3308F272A7004A47F5 /* tclUniData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUniData.c; sourceTree = ""; }; F96D3F3408F272A7004A47F5 /* tclUtf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtf.c; sourceTree = ""; }; F96D3F3508F272A7004A47F5 /* tclUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtil.c; sourceTree = ""; }; F96D3F3608F272A7004A47F5 /* tclVar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclVar.c; sourceTree = ""; }; F96D3F3708F272A7004A47F5 /* tommath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath.h; sourceTree = ""; }; F96D3F3908F272A8004A47F5 /* auto.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = auto.tcl; sourceTree = ""; }; F96D3F3A08F272A8004A47F5 /* clock.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.tcl; sourceTree = ""; }; F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D3F8C08F272A8004A47F5 /* history.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.tcl; sourceTree = ""; }; F96D3F8E08F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = ""; }; F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D3F9108F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = ""; }; F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D3F9308F272A8004A47F5 /* init.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.tcl; sourceTree = ""; }; F96D3F9508F272A8004A47F5 /* msgcat.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.tcl; sourceTree = ""; }; F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D401808F272AA004A47F5 /* optparse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = optparse.tcl; sourceTree = ""; }; F96D401908F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D401A08F272AA004A47F5 /* package.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.tcl; sourceTree = ""; }; F96D401B08F272AA004A47F5 /* parray.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parray.tcl; sourceTree = ""; }; F96D401D08F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D401E08F272AA004A47F5 /* safe.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.tcl; sourceTree = ""; }; F96D401F08F272AA004A47F5 /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = ""; }; F96D402108F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D402208F272AA004A47F5 /* tcltest.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.tcl; sourceTree = ""; }; F96D402308F272AA004A47F5 /* tm.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.tcl; sourceTree = ""; }; F96D425B08F272B2004A47F5 /* word.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = word.tcl; sourceTree = ""; }; F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_mul_digs.c; sourceTree = ""; }; F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_sqr.c; sourceTree = ""; }; F96D426908F272B3004A47F5 /* bn_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add.c; sourceTree = ""; }; F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add_d.c; sourceTree = ""; }; F96D426C08F272B3004A47F5 /* bn_mp_and.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_and.c; sourceTree = ""; }; F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clamp.c; sourceTree = ""; }; F96D426E08F272B3004A47F5 /* bn_mp_clear.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear.c; sourceTree = ""; }; F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear_multi.c; sourceTree = ""; }; F96D427008F272B3004A47F5 /* bn_mp_cmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp.c; sourceTree = ""; }; F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_d.c; sourceTree = ""; }; F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_mag.c; sourceTree = ""; }; F96D427408F272B3004A47F5 /* bn_mp_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_copy.c; sourceTree = ""; }; F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_count_bits.c; sourceTree = ""; }; F96D427608F272B3004A47F5 /* bn_mp_div.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div.c; sourceTree = ""; }; F96D427708F272B3004A47F5 /* bn_mp_div_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2.c; sourceTree = ""; }; F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2d.c; sourceTree = ""; }; F96D427908F272B3004A47F5 /* bn_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_3.c; sourceTree = ""; }; F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_d.c; sourceTree = ""; }; F96D427E08F272B3004A47F5 /* bn_mp_exch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exch.c; sourceTree = ""; }; F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_d.c; sourceTree = ""; }; F96D428708F272B3004A47F5 /* bn_mp_grow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_grow.c; sourceTree = ""; }; F96D428808F272B3004A47F5 /* bn_mp_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init.c; sourceTree = ""; }; F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_copy.c; sourceTree = ""; }; F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_multi.c; sourceTree = ""; }; F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_set.c; sourceTree = ""; }; F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_size.c; sourceTree = ""; }; F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_mul.c; sourceTree = ""; }; F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_sqr.c; sourceTree = ""; }; F96D429508F272B3004A47F5 /* bn_mp_lshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_lshd.c; sourceTree = ""; }; F96D429608F272B3004A47F5 /* bn_mp_mod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod.c; sourceTree = ""; }; F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod_2d.c; sourceTree = ""; }; F96D429C08F272B3004A47F5 /* bn_mp_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul.c; sourceTree = ""; }; F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2.c; sourceTree = ""; }; F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2d.c; sourceTree = ""; }; F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_d.c; sourceTree = ""; }; F96D42A208F272B3004A47F5 /* bn_mp_neg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_neg.c; sourceTree = ""; }; F96D42A308F272B3004A47F5 /* bn_mp_or.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_or.c; sourceTree = ""; }; F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_size.c; sourceTree = ""; }; F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_smap.c; sourceTree = ""; }; F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_radix.c; sourceTree = ""; }; F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_rshd.c; sourceTree = ""; }; F96D42BA08F272B3004A47F5 /* bn_mp_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_set.c; sourceTree = ""; }; F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_shrink.c; sourceTree = ""; }; F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqr.c; sourceTree = ""; }; F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqrt.c; sourceTree = ""; }; F96D42C108F272B3004A47F5 /* bn_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub.c; sourceTree = ""; }; F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub_d.c; sourceTree = ""; }; F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin.c; sourceTree = ""; }; F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin_n.c; sourceTree = ""; }; F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_mul.c; sourceTree = ""; }; F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_sqr.c; sourceTree = ""; }; F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toradix_n.c; sourceTree = ""; }; F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_unsigned_bin_size.c; sourceTree = ""; }; F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_xor.c; sourceTree = ""; }; F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_zero.c; sourceTree = ""; }; F96D42D008F272B3004A47F5 /* bn_reverse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_reverse.c; sourceTree = ""; }; F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_add.c; sourceTree = ""; }; F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_mul_digs.c; sourceTree = ""; }; F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sqr.c; sourceTree = ""; }; F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sub.c; sourceTree = ""; }; F96D42D708F272B3004A47F5 /* bncore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bncore.c; sourceTree = ""; }; F96D432908F272B4004A47F5 /* tommath_class.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_class.h; sourceTree = ""; }; F96D432A08F272B4004A47F5 /* tommath_superclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_superclass.h; sourceTree = ""; }; F96D432B08F272B4004A47F5 /* license.terms */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = license.terms; sourceTree = ""; }; F96D432E08F272B5004A47F5 /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure.ac; sourceTree = ""; }; F96D432F08F272B5004A47F5 /* GNUmakefile */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = GNUmakefile; sourceTree = ""; }; F96D433108F272B5004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Tcl-Info.plist.in"; sourceTree = ""; }; F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXBundle.c; sourceTree = ""; }; F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXFCmd.c; sourceTree = ""; }; F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXNotify.c; sourceTree = ""; }; F96D434308F272B5004A47F5 /* README */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = README; sourceTree = ""; }; F96D434508F272B5004A47F5 /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = ""; }; F96D434608F272B5004A47F5 /* append.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = append.test; sourceTree = ""; }; F96D434708F272B5004A47F5 /* appendComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = appendComp.test; sourceTree = ""; }; F96D434808F272B5004A47F5 /* assocd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = assocd.test; sourceTree = ""; }; F96D434908F272B5004A47F5 /* async.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = async.test; sourceTree = ""; }; F96D434A08F272B5004A47F5 /* autoMkindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = autoMkindex.test; sourceTree = ""; }; F96D434B08F272B5004A47F5 /* basic.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = basic.test; sourceTree = ""; }; F96D434C08F272B5004A47F5 /* binary.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = binary.test; sourceTree = ""; }; F96D434D08F272B5004A47F5 /* case.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = case.test; sourceTree = ""; }; F96D434E08F272B5004A47F5 /* chan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chan.test; sourceTree = ""; }; F96D434F08F272B5004A47F5 /* clock.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.test; sourceTree = ""; }; F96D435008F272B5004A47F5 /* cmdAH.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdAH.test; sourceTree = ""; }; F96D435108F272B5004A47F5 /* cmdIL.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdIL.test; sourceTree = ""; }; F96D435208F272B5004A47F5 /* cmdInfo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdInfo.test; sourceTree = ""; }; F96D435308F272B5004A47F5 /* cmdMZ.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdMZ.test; sourceTree = ""; }; F96D435408F272B5004A47F5 /* compExpr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "compExpr-old.test"; sourceTree = ""; }; F96D435508F272B5004A47F5 /* compExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compExpr.test; sourceTree = ""; }; F96D435608F272B5004A47F5 /* compile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compile.test; sourceTree = ""; }; F96D435708F272B5004A47F5 /* concat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = concat.test; sourceTree = ""; }; F96D435808F272B5004A47F5 /* config.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = config.test; sourceTree = ""; }; F96D435908F272B5004A47F5 /* dcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dcall.test; sourceTree = ""; }; F96D435A08F272B5004A47F5 /* dict.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dict.test; sourceTree = ""; }; F96D435C08F272B5004A47F5 /* dstring.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dstring.test; sourceTree = ""; }; F96D435E08F272B5004A47F5 /* encoding.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = encoding.test; sourceTree = ""; }; F96D435F08F272B5004A47F5 /* env.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = env.test; sourceTree = ""; }; F96D436008F272B5004A47F5 /* error.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = error.test; sourceTree = ""; }; F96D436108F272B5004A47F5 /* eval.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eval.test; sourceTree = ""; }; F96D436208F272B5004A47F5 /* event.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = event.test; sourceTree = ""; }; F96D436308F272B5004A47F5 /* exec.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = exec.test; sourceTree = ""; }; F96D436408F272B5004A47F5 /* execute.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = execute.test; sourceTree = ""; }; F96D436508F272B5004A47F5 /* expr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "expr-old.test"; sourceTree = ""; }; F96D436608F272B5004A47F5 /* expr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = expr.test; sourceTree = ""; }; F96D436708F272B6004A47F5 /* fCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fCmd.test; sourceTree = ""; }; F96D436808F272B6004A47F5 /* fileName.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileName.test; sourceTree = ""; }; F96D436908F272B6004A47F5 /* fileSystem.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileSystem.test; sourceTree = ""; }; F96D436A08F272B6004A47F5 /* for-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "for-old.test"; sourceTree = ""; }; F96D436B08F272B6004A47F5 /* for.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = for.test; sourceTree = ""; }; F96D436C08F272B6004A47F5 /* foreach.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = foreach.test; sourceTree = ""; }; F96D436D08F272B6004A47F5 /* format.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = format.test; sourceTree = ""; }; F96D436E08F272B6004A47F5 /* get.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = get.test; sourceTree = ""; }; F96D436F08F272B6004A47F5 /* history.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.test; sourceTree = ""; }; F96D437008F272B6004A47F5 /* http.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.test; sourceTree = ""; }; F96D437108F272B6004A47F5 /* httpd */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd; sourceTree = ""; }; F96D437208F272B6004A47F5 /* httpold.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpold.test; sourceTree = ""; }; F96D437308F272B6004A47F5 /* if-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "if-old.test"; sourceTree = ""; }; F96D437408F272B6004A47F5 /* if.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = if.test; sourceTree = ""; }; F96D437508F272B6004A47F5 /* incr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "incr-old.test"; sourceTree = ""; }; F96D437608F272B6004A47F5 /* incr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = incr.test; sourceTree = ""; }; F96D437708F272B6004A47F5 /* indexObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = indexObj.test; sourceTree = ""; }; F96D437808F272B6004A47F5 /* info.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = info.test; sourceTree = ""; }; F96D437908F272B6004A47F5 /* init.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.test; sourceTree = ""; }; F96D437A08F272B6004A47F5 /* interp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = interp.test; sourceTree = ""; }; F96D437B08F272B6004A47F5 /* io.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = io.test; sourceTree = ""; }; F96D437C08F272B6004A47F5 /* ioCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ioCmd.test; sourceTree = ""; }; F96D437D08F272B6004A47F5 /* iogt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = iogt.test; sourceTree = ""; }; F96D437F08F272B6004A47F5 /* join.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = join.test; sourceTree = ""; }; F96D438008F272B6004A47F5 /* lindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lindex.test; sourceTree = ""; }; F96D438108F272B6004A47F5 /* link.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = link.test; sourceTree = ""; }; F96D438208F272B6004A47F5 /* linsert.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = linsert.test; sourceTree = ""; }; F96D438308F272B6004A47F5 /* list.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = list.test; sourceTree = ""; }; F96D438408F272B6004A47F5 /* listObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listObj.test; sourceTree = ""; }; F96D438508F272B6004A47F5 /* llength.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = llength.test; sourceTree = ""; }; F96D438608F272B6004A47F5 /* load.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = load.test; sourceTree = ""; }; F96D438708F272B6004A47F5 /* lrange.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrange.test; sourceTree = ""; }; F96D438808F272B6004A47F5 /* lrepeat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrepeat.test; sourceTree = ""; }; F96D438908F272B6004A47F5 /* lreplace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lreplace.test; sourceTree = ""; }; F96D438A08F272B6004A47F5 /* lsearch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsearch.test; sourceTree = ""; }; F96D438B08F272B6004A47F5 /* lset.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lset.test; sourceTree = ""; }; F96D438C08F272B6004A47F5 /* lsetComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsetComp.test; sourceTree = ""; }; F96D438D08F272B6004A47F5 /* macOSXFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXFCmd.test; sourceTree = ""; }; F96D438E08F272B6004A47F5 /* main.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = main.test; sourceTree = ""; }; F96D438F08F272B6004A47F5 /* misc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = misc.test; sourceTree = ""; }; F96D439008F272B6004A47F5 /* msgcat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.test; sourceTree = ""; }; F96D439108F272B6004A47F5 /* namespace-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "namespace-old.test"; sourceTree = ""; }; F96D439208F272B7004A47F5 /* namespace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = namespace.test; sourceTree = ""; }; F96D439308F272B7004A47F5 /* notify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notify.test; sourceTree = ""; }; F96D439408F272B7004A47F5 /* obj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obj.test; sourceTree = ""; }; F96D439508F272B7004A47F5 /* opt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = opt.test; sourceTree = ""; }; F96D439608F272B7004A47F5 /* package.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.test; sourceTree = ""; }; F96D439708F272B7004A47F5 /* parse.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parse.test; sourceTree = ""; }; F96D439808F272B7004A47F5 /* parseExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseExpr.test; sourceTree = ""; }; F96D439908F272B7004A47F5 /* parseOld.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseOld.test; sourceTree = ""; }; F96D439A08F272B7004A47F5 /* pid.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pid.test; sourceTree = ""; }; F96D439B08F272B7004A47F5 /* pkg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkg.test; sourceTree = ""; }; F96D439C08F272B7004A47F5 /* pkgMkIndex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgMkIndex.test; sourceTree = ""; }; F96D439D08F272B7004A47F5 /* platform.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.test; sourceTree = ""; }; F96D439E08F272B7004A47F5 /* proc-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "proc-old.test"; sourceTree = ""; }; F96D439F08F272B7004A47F5 /* proc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = proc.test; sourceTree = ""; }; F96D43A008F272B7004A47F5 /* pwd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pwd.test; sourceTree = ""; }; F96D43A108F272B7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D43A208F272B7004A47F5 /* reg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = reg.test; sourceTree = ""; }; F96D43A308F272B7004A47F5 /* regexp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexp.test; sourceTree = ""; }; F96D43A408F272B7004A47F5 /* regexpComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpComp.test; sourceTree = ""; }; F96D43A508F272B7004A47F5 /* registry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = registry.test; sourceTree = ""; }; F96D43A608F272B7004A47F5 /* remote.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = remote.tcl; sourceTree = ""; }; F96D43A708F272B7004A47F5 /* rename.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = rename.test; sourceTree = ""; }; F96D43A808F272B7004A47F5 /* result.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = result.test; sourceTree = ""; }; F96D43A908F272B7004A47F5 /* safe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.test; sourceTree = ""; }; F96D43AA08F272B7004A47F5 /* scan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scan.test; sourceTree = ""; }; F96D43AB08F272B7004A47F5 /* security.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = security.test; sourceTree = ""; }; F96D43AC08F272B7004A47F5 /* set-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "set-old.test"; sourceTree = ""; }; F96D43AD08F272B7004A47F5 /* set.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = set.test; sourceTree = ""; }; F96D43AE08F272B7004A47F5 /* socket.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = socket.test; sourceTree = ""; }; F96D43AF08F272B7004A47F5 /* source.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = source.test; sourceTree = ""; }; F96D43B008F272B7004A47F5 /* split.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = split.test; sourceTree = ""; }; F96D43B108F272B7004A47F5 /* stack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stack.test; sourceTree = ""; }; F96D43B208F272B7004A47F5 /* string.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = string.test; sourceTree = ""; }; F96D43B308F272B7004A47F5 /* stringComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringComp.test; sourceTree = ""; }; F96D43B408F272B7004A47F5 /* stringObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringObj.test; sourceTree = ""; }; F96D43B508F272B7004A47F5 /* subst.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = subst.test; sourceTree = ""; }; F96D43B608F272B7004A47F5 /* switch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = switch.test; sourceTree = ""; }; F96D43B708F272B7004A47F5 /* tcltest.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.test; sourceTree = ""; }; F96D43B808F272B7004A47F5 /* thread.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = thread.test; sourceTree = ""; }; F96D43B908F272B7004A47F5 /* timer.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = timer.test; sourceTree = ""; }; F96D43BA08F272B7004A47F5 /* tm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.test; sourceTree = ""; }; F96D43BB08F272B7004A47F5 /* trace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = trace.test; sourceTree = ""; }; F96D43BC08F272B7004A47F5 /* unixFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFCmd.test; sourceTree = ""; }; F96D43BD08F272B7004A47F5 /* unixFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFile.test; sourceTree = ""; }; F96D43BE08F272B7004A47F5 /* unixInit.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixInit.test; sourceTree = ""; }; F96D43BF08F272B7004A47F5 /* unixNotfy.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixNotfy.test; sourceTree = ""; }; F96D43C008F272B7004A47F5 /* unknown.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unknown.test; sourceTree = ""; }; F96D43C108F272B7004A47F5 /* unload.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unload.test; sourceTree = ""; }; F96D43C208F272B7004A47F5 /* uplevel.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uplevel.test; sourceTree = ""; }; F96D43C308F272B7004A47F5 /* upvar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = upvar.test; sourceTree = ""; }; F96D43C408F272B7004A47F5 /* utf.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = utf.test; sourceTree = ""; }; F96D43C508F272B7004A47F5 /* util.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = util.test; sourceTree = ""; }; F96D43C608F272B7004A47F5 /* var.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = var.test; sourceTree = ""; }; F96D43C708F272B7004A47F5 /* while-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "while-old.test"; sourceTree = ""; }; F96D43C808F272B7004A47F5 /* while.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = while.test; sourceTree = ""; }; F96D43C908F272B7004A47F5 /* winConsole.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winConsole.test; sourceTree = ""; }; F96D43CA08F272B7004A47F5 /* winDde.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winDde.test; sourceTree = ""; }; F96D43CB08F272B7004A47F5 /* winFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFCmd.test; sourceTree = ""; }; F96D43CC08F272B7004A47F5 /* winFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFile.test; sourceTree = ""; }; F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = ""; }; F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = ""; }; F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = ""; }; F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = ""; }; F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = ""; }; F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = ""; }; F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = ""; }; F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = ""; }; F96D442908F272B8004A47F5 /* loadICU.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = loadICU.tcl; sourceTree = ""; }; F96D442A08F272B8004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D442B08F272B8004A47F5 /* makeTestCases.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = makeTestCases.tcl; sourceTree = ""; }; F96D442C08F272B8004A47F5 /* man2help.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help.tcl; sourceTree = ""; }; F96D442D08F272B8004A47F5 /* man2help2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help2.tcl; sourceTree = ""; }; F96D442E08F272B8004A47F5 /* man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html.tcl; sourceTree = ""; }; F96D442F08F272B8004A47F5 /* man2html1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html1.tcl; sourceTree = ""; }; F96D443008F272B8004A47F5 /* man2html2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html2.tcl; sourceTree = ""; }; F96D443108F272B8004A47F5 /* man2tcl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = man2tcl.c; sourceTree = ""; }; F96D443208F272B8004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D443308F272B8004A47F5 /* regexpTestLib.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpTestLib.tcl; sourceTree = ""; }; F96D443508F272B8004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = ""; }; F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "tcltk-man2html.tcl"; sourceTree = ""; }; F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = ""; }; F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = ""; }; F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = ""; }; F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; F96D444208F272B9004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = ""; }; F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = ""; }; F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = ""; }; F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = ""; }; F96D444908F272B9004A47F5 /* pkge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkge.c; sourceTree = ""; }; F96D444B08F272B9004A47F5 /* pkgua.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgua.c; sourceTree = ""; }; F96D444C08F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D444D08F272B9004A47F5 /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = ""; }; F96D444E08F272B9004A47F5 /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = ""; }; F96D444F08F272B9004A47F5 /* ldAix */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ldAix; sourceTree = ""; }; F96D445008F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D445208F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D445308F272B9004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = ""; }; F96D445408F272B9004A47F5 /* tcl.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.spec; sourceTree = ""; }; F96D445508F272B9004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = ""; }; F96D445608F272B9004A47F5 /* tclConfig.h.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = tclConfig.h.in; sourceTree = ""; }; F96D445708F272B9004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = ""; }; F96D445808F272B9004A47F5 /* tclLoadAix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadAix.c; sourceTree = ""; }; F96D445908F272B9004A47F5 /* tclLoadDl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDl.c; sourceTree = ""; }; F96D445B08F272B9004A47F5 /* tclLoadDyld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDyld.c; sourceTree = ""; }; F96D445C08F272B9004A47F5 /* tclLoadNext.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNext.c; sourceTree = ""; }; F96D445D08F272B9004A47F5 /* tclLoadOSF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadOSF.c; sourceTree = ""; }; F96D445E08F272B9004A47F5 /* tclLoadShl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadShl.c; sourceTree = ""; }; F96D445F08F272B9004A47F5 /* tclUnixChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixChan.c; sourceTree = ""; }; F96D446008F272B9004A47F5 /* tclUnixEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixEvent.c; sourceTree = ""; }; F96D446108F272B9004A47F5 /* tclUnixFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFCmd.c; sourceTree = ""; }; F96D446208F272B9004A47F5 /* tclUnixFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFile.c; sourceTree = ""; }; F96D446308F272B9004A47F5 /* tclUnixInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixInit.c; sourceTree = ""; }; F96D446408F272B9004A47F5 /* tclUnixNotfy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixNotfy.c; sourceTree = ""; }; F96D446508F272B9004A47F5 /* tclUnixPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixPipe.c; sourceTree = ""; }; F96D446608F272B9004A47F5 /* tclUnixPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixPort.h; sourceTree = ""; }; F96D446708F272B9004A47F5 /* tclUnixSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixSock.c; sourceTree = ""; }; F96D446808F272B9004A47F5 /* tclUnixTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTest.c; sourceTree = ""; }; F96D446908F272B9004A47F5 /* tclUnixThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixThrd.c; sourceTree = ""; }; F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = ""; }; F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = ""; }; F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = ""; }; F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = ""; }; F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = ""; }; F96D447308F272BA004A47F5 /* coffbase.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = coffbase.txt; sourceTree = ""; }; F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; F96D447608F272BA004A47F5 /* makefile.bc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.bc; sourceTree = ""; }; F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = ""; }; F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = ""; }; F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = ""; }; F96D447D08F272BA004A47F5 /* stub16.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stub16.c; sourceTree = ""; }; F96D447E08F272BA004A47F5 /* tcl.dsp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsp; sourceTree = ""; }; F96D447F08F272BA004A47F5 /* tcl.dsw */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsw; sourceTree = ""; }; F96D448008F272BA004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = ""; }; F96D448108F272BA004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = ""; }; F96D448208F272BA004A47F5 /* tcl.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.rc; sourceTree = ""; }; F96D448308F272BA004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = ""; }; F96D448408F272BA004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = ""; }; F96D448608F272BA004A47F5 /* tclsh.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tclsh.rc; sourceTree = ""; }; F96D448708F272BA004A47F5 /* tclWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWin32Dll.c; sourceTree = ""; }; F96D448808F272BA004A47F5 /* tclWinChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinChan.c; sourceTree = ""; }; F96D448908F272BA004A47F5 /* tclWinConsole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinConsole.c; sourceTree = ""; }; F96D448A08F272BA004A47F5 /* tclWinDde.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinDde.c; sourceTree = ""; }; F96D448B08F272BA004A47F5 /* tclWinError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinError.c; sourceTree = ""; }; F96D448C08F272BA004A47F5 /* tclWinFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFCmd.c; sourceTree = ""; }; F96D448D08F272BA004A47F5 /* tclWinFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFile.c; sourceTree = ""; }; F96D448E08F272BA004A47F5 /* tclWinInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinInit.c; sourceTree = ""; }; F96D448F08F272BA004A47F5 /* tclWinInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinInt.h; sourceTree = ""; }; F96D449008F272BA004A47F5 /* tclWinLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinLoad.c; sourceTree = ""; }; F96D449108F272BA004A47F5 /* tclWinNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinNotify.c; sourceTree = ""; }; F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = ""; }; F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = ""; }; F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = ""; }; F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = ""; }; F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = ""; }; F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = ""; }; F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = ""; }; F96D449908F272BA004A47F5 /* tclWinThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinThrd.h; sourceTree = ""; }; F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = ""; }; F974D56C0FBE7D6300BF728B /* http11.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http11.test; sourceTree = ""; }; F974D56D0FBE7D6300BF728B /* httpd11.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd11.tcl; sourceTree = ""; }; F974D5720FBE7DC600BF728B /* coroutine.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = coroutine.n; sourceTree = ""; }; F974D5760FBE7E1900BF728B /* tailcall.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tailcall.n; sourceTree = ""; }; F974D5770FBE7E6100BF728B /* coroutine.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = coroutine.test; sourceTree = ""; }; F974D5780FBE7E6100BF728B /* tailcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tailcall.test; sourceTree = ""; }; F974D5790FBE7E9C00BF728B /* tcl.pc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.pc.in; sourceTree = ""; }; F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Common.xcconfig"; sourceTree = ""; }; F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Release.xcconfig"; sourceTree = ""; }; F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Debug.xcconfig"; sourceTree = ""; }; F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = ""; }; F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = ""; }; F99D61180EF5573A00BBFE01 /* TclZlib.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TclZlib.3; sourceTree = ""; }; F9A3084B08F2D4CE00BAE1AB /* tclsh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tclsh; sourceTree = BUILT_PRODUCTS_DIR; }; F9A3084E08F2D4F400BAE1AB /* Tcl.framework */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = Tcl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F9A493240CEBF38300B78AE2 /* chanio.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chanio.test; sourceTree = ""; }; F9ECB1120B26521500A28025 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F9ECB1130B26521500A28025 /* platform.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.tcl; sourceTree = ""; }; F9ECB1140B26521500A28025 /* shell.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = shell.tcl; sourceTree = ""; }; F9ECB1CA0B2652D300A28025 /* apply.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = apply.test; sourceTree = ""; }; F9ECB1CB0B26534C00A28025 /* mathop.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mathop.test; sourceTree = ""; }; F9ECB1E10B26543C00A28025 /* platform_shell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform_shell.n; sourceTree = ""; }; F9ECB1E20B26543C00A28025 /* platform.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform.n; sourceTree = ""; }; F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = tclDTrace.d; sourceTree = ""; }; F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixCompat.c; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 8DD76FAD0486AB0100D96B5E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */, F96437E70EF0D652003F468E /* libz.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 08FB7794FE84155DC02AAC07 /* Tcl */ = { isa = PBXGroup; children = ( F96D3DF608F27169004A47F5 /* Tcl Sources */, F966C06F08F281DC005CB29B /* Frameworks */, 1AB674ADFE9D54B511CA2CBB /* Products */, ); comments = "Copyright (c) 2004-2009 Daniel A. Steffen \nCopyright 2008-2009, Apple Inc.\n\nSee the file \"license.terms\" for information on usage and redistribution of\nthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n"; name = Tcl; path = .; sourceTree = SOURCE_ROOT; }; 1AB674ADFE9D54B511CA2CBB /* Products */ = { isa = PBXGroup; children = ( F9A3084B08F2D4CE00BAE1AB /* tclsh */, 8DD76FB20486AB0100D96B5E /* tcltest */, F9A3084E08F2D4F400BAE1AB /* Tcl.framework */, ); includeInIndex = 0; name = Products; sourceTree = ""; }; F9183E690EFC81560030B814 /* pkgs */ = { isa = PBXGroup; children = ( F9183E6A0EFC81560030B814 /* README */, F946FB8B0FBE3AED00CD6495 /* itcl */, F9183E8F0EFC817B0030B814 /* tdbc */, ); path = pkgs; sourceTree = ""; }; F966C06F08F281DC005CB29B /* Frameworks */ = { isa = PBXGroup; children = ( F966C07408F2820D005CB29B /* CoreFoundation.framework */, F96437E60EF0D652003F468E /* libz.dylib */, ); name = Frameworks; sourceTree = ""; }; F96D3DF608F27169004A47F5 /* Tcl Sources */ = { isa = PBXGroup; children = ( F96D3EC908F272A7004A47F5 /* generic */, F96D432C08F272B4004A47F5 /* macosx */, F96D443E08F272B9004A47F5 /* unix */, F96D425C08F272B2004A47F5 /* libtommath */, F96D446E08F272B9004A47F5 /* win */, F96D3F3808F272A7004A47F5 /* library */, F96D434408F272B5004A47F5 /* tests */, F96D3DFC08F272A4004A47F5 /* doc */, F96D43D008F272B8004A47F5 /* tools */, F9183E690EFC81560030B814 /* pkgs */, F96D3DFA08F272A4004A47F5 /* ChangeLog */, F96D3DFB08F272A4004A47F5 /* changes */, F96D434308F272B5004A47F5 /* README */, F96D432B08F272B4004A47F5 /* license.terms */, ); name = "Tcl Sources"; sourceTree = TCL_SRCROOT; }; F96D3DFC08F272A4004A47F5 /* doc */ = { isa = PBXGroup; children = ( F96D3DFD08F272A4004A47F5 /* Access.3 */, F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */, F96D3DFF08F272A4004A47F5 /* after.n */, F96D3E0008F272A4004A47F5 /* Alloc.3 */, F96D3E0108F272A4004A47F5 /* AllowExc.3 */, F96D3E0208F272A4004A47F5 /* append.n */, F96D3E0308F272A4004A47F5 /* AppInit.3 */, F96D3E0408F272A5004A47F5 /* array.n */, F96D3E0508F272A5004A47F5 /* AssocData.3 */, F96D3E0608F272A5004A47F5 /* Async.3 */, F96D3E0708F272A5004A47F5 /* BackgdErr.3 */, F96D3E0808F272A5004A47F5 /* Backslash.3 */, F96D3E0908F272A5004A47F5 /* bgerror.n */, F96D3E0A08F272A5004A47F5 /* binary.n */, F96D3E0B08F272A5004A47F5 /* BoolObj.3 */, F96D3E0C08F272A5004A47F5 /* break.n */, F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */, F96D3E0E08F272A5004A47F5 /* CallDel.3 */, F96D3E0F08F272A5004A47F5 /* case.n */, F96D3E1008F272A5004A47F5 /* catch.n */, F96D3E1108F272A5004A47F5 /* cd.n */, F96D3E1208F272A5004A47F5 /* chan.n */, F96D3E1308F272A5004A47F5 /* ChnlStack.3 */, F93599CF0DF1F87F00E04F67 /* Class.3 */, F93599D00DF1F89E00E04F67 /* class.n */, F96D3E1408F272A5004A47F5 /* clock.n */, F96D3E1508F272A5004A47F5 /* close.n */, F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */, F96D3E1708F272A5004A47F5 /* Concat.3 */, F96D3E1808F272A5004A47F5 /* concat.n */, F96D3E1908F272A5004A47F5 /* continue.n */, F93599D20DF1F8DF00E04F67 /* copy.n */, F974D5720FBE7DC600BF728B /* coroutine.n */, F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */, F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */, F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */, F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */, F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */, F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */, F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */, F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */, F96D3E2208F272A5004A47F5 /* CrtSlave.3 */, F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */, F96D3E2408F272A5004A47F5 /* CrtTrace.3 */, F96D3E2508F272A5004A47F5 /* dde.n */, F93599D30DF1F8F500E04F67 /* define.n */, F96D3E2608F272A5004A47F5 /* DetachPids.3 */, F96D3E2708F272A5004A47F5 /* dict.n */, F96D3E2808F272A5004A47F5 /* DictObj.3 */, F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */, F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */, F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */, F96D3E2C08F272A5004A47F5 /* DString.3 */, F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */, F96D3E2E08F272A5004A47F5 /* Encoding.3 */, F96D3E2F08F272A5004A47F5 /* encoding.n */, F96D3E3008F272A5004A47F5 /* Ensemble.3 */, F96D3E3108F272A5004A47F5 /* Environment.3 */, F96D3E3208F272A5004A47F5 /* eof.n */, F96D3E3308F272A5004A47F5 /* error.n */, F96D3E3408F272A5004A47F5 /* Eval.3 */, F96D3E3508F272A5004A47F5 /* eval.n */, F96D3E3608F272A5004A47F5 /* exec.n */, F96D3E3708F272A5004A47F5 /* Exit.3 */, F96D3E3808F272A5004A47F5 /* exit.n */, F96D3E3908F272A5004A47F5 /* expr.n */, F96D3E3A08F272A5004A47F5 /* ExprLong.3 */, F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */, F96D3E3C08F272A5004A47F5 /* fblocked.n */, F96D3E3D08F272A5004A47F5 /* fconfigure.n */, F96D3E3E08F272A5004A47F5 /* fcopy.n */, F96D3E3F08F272A5004A47F5 /* file.n */, F96D3E4008F272A5004A47F5 /* fileevent.n */, F96D3E4108F272A5004A47F5 /* filename.n */, F96D3E4208F272A5004A47F5 /* FileSystem.3 */, F96D3E4308F272A5004A47F5 /* FindExec.3 */, F96D3E4408F272A5004A47F5 /* flush.n */, F96D3E4508F272A5004A47F5 /* for.n */, F96D3E4608F272A5004A47F5 /* foreach.n */, F96D3E4708F272A5004A47F5 /* format.n */, F96D3E4808F272A5004A47F5 /* GetCwd.3 */, F96D3E4908F272A5004A47F5 /* GetHostName.3 */, F96D3E4A08F272A5004A47F5 /* GetIndex.3 */, F96D3E4B08F272A5004A47F5 /* GetInt.3 */, F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */, F96D3E4D08F272A5004A47F5 /* gets.n */, F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */, F96D3E4F08F272A5004A47F5 /* GetTime.3 */, F96D3E5008F272A5004A47F5 /* GetVersion.3 */, F96D3E5108F272A5004A47F5 /* glob.n */, F96D3E5208F272A6004A47F5 /* global.n */, F96D3E5308F272A6004A47F5 /* Hash.3 */, F96D3E5408F272A6004A47F5 /* history.n */, F96D3E5508F272A6004A47F5 /* http.n */, F96D3E5608F272A6004A47F5 /* if.n */, F96D3E5708F272A6004A47F5 /* incr.n */, F96D3E5808F272A6004A47F5 /* info.n */, F96D3E5908F272A6004A47F5 /* Init.3 */, F96D3E5A08F272A6004A47F5 /* InitStubs.3 */, F96D3E5B08F272A6004A47F5 /* Interp.3 */, F96D3E5C08F272A6004A47F5 /* interp.n */, F96D3E5D08F272A6004A47F5 /* IntObj.3 */, F96D3E5E08F272A6004A47F5 /* join.n */, F96D3E5F08F272A6004A47F5 /* lappend.n */, F96D3E6008F272A6004A47F5 /* lassign.n */, F96D3E6108F272A6004A47F5 /* library.n */, F96D3E6208F272A6004A47F5 /* Limit.3 */, F96D3E6308F272A6004A47F5 /* lindex.n */, F96D3E6408F272A6004A47F5 /* LinkVar.3 */, F96D3E6508F272A6004A47F5 /* linsert.n */, F96D3E6608F272A6004A47F5 /* list.n */, F96D3E6708F272A6004A47F5 /* ListObj.3 */, F96D3E6808F272A6004A47F5 /* llength.n */, F96D3E6908F272A6004A47F5 /* load.n */, F96D3E6A08F272A6004A47F5 /* lrange.n */, F96D3E6B08F272A6004A47F5 /* lrepeat.n */, F96D3E6C08F272A6004A47F5 /* lreplace.n */, F96D3E6D08F272A6004A47F5 /* lsearch.n */, F96D3E6E08F272A6004A47F5 /* lset.n */, F96D3E6F08F272A6004A47F5 /* lsort.n */, F96D3E7008F272A6004A47F5 /* man.macros */, F96D3E7108F272A6004A47F5 /* mathfunc.n */, F96D3E7208F272A6004A47F5 /* memory.n */, F93599D40DF1F91900E04F67 /* Method.3 */, F96D3E7308F272A6004A47F5 /* msgcat.n */, F93599D50DF1F93700E04F67 /* my.n */, F96D3E7408F272A6004A47F5 /* Namespace.3 */, F96D3E7508F272A6004A47F5 /* namespace.n */, F93599D60DF1F95000E04F67 /* next.n */, F96D3E7608F272A6004A47F5 /* Notifier.3 */, F96D3E7708F272A6004A47F5 /* Object.3 */, F93599D70DF1F96800E04F67 /* object.n */, F96D3E7808F272A6004A47F5 /* ObjectType.3 */, F96D3E7908F272A6004A47F5 /* open.n */, F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */, F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */, F96D3E7C08F272A6004A47F5 /* package.n */, F96D3E7D08F272A6004A47F5 /* packagens.n */, F96D3E7E08F272A6004A47F5 /* Panic.3 */, F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */, F96D3E8008F272A6004A47F5 /* pid.n */, F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */, F96D3E8208F272A6004A47F5 /* PkgRequire.3 */, F9ECB1E10B26543C00A28025 /* platform_shell.n */, F9ECB1E20B26543C00A28025 /* platform.n */, F96D3E8308F272A6004A47F5 /* Preserve.3 */, F96D3E8408F272A6004A47F5 /* PrintDbl.3 */, F96D3E8508F272A6004A47F5 /* proc.n */, F96D3E8608F272A6004A47F5 /* puts.n */, F96D3E8708F272A6004A47F5 /* pwd.n */, F96D3E8808F272A6004A47F5 /* re_syntax.n */, F96D3E8908F272A6004A47F5 /* read.n */, F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */, F96D3E8B08F272A6004A47F5 /* RecordEval.3 */, F96D3E8C08F272A6004A47F5 /* RegConfig.3 */, F96D3E8D08F272A6004A47F5 /* RegExp.3 */, F96D3E8E08F272A6004A47F5 /* regexp.n */, F96D3E8F08F272A6004A47F5 /* registry.n */, F96D3E9008F272A6004A47F5 /* regsub.n */, F96D3E9108F272A6004A47F5 /* rename.n */, F96D3E9208F272A6004A47F5 /* return.n */, F96D3E9308F272A6004A47F5 /* safe.n */, F96D3E9408F272A6004A47F5 /* SaveResult.3 */, F96D3E9508F272A6004A47F5 /* scan.n */, F96D3E9608F272A6004A47F5 /* seek.n */, F93599D80DF1F98300E04F67 /* self.n */, F96D3E9708F272A6004A47F5 /* set.n */, F96D3E9808F272A6004A47F5 /* SetChanErr.3 */, F96D3E9908F272A6004A47F5 /* SetErrno.3 */, F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */, F96D3E9B08F272A7004A47F5 /* SetResult.3 */, F96D3E9C08F272A7004A47F5 /* SetVar.3 */, F96D3E9D08F272A7004A47F5 /* Signal.3 */, F96D3E9E08F272A7004A47F5 /* Sleep.3 */, F96D3E9F08F272A7004A47F5 /* socket.n */, F96D3EA008F272A7004A47F5 /* source.n */, F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */, F96D3EA208F272A7004A47F5 /* split.n */, F96D3EA308F272A7004A47F5 /* SplitList.3 */, F96D3EA408F272A7004A47F5 /* SplitPath.3 */, F96D3EA508F272A7004A47F5 /* StaticPkg.3 */, F96D3EA608F272A7004A47F5 /* StdChannels.3 */, F96D3EA708F272A7004A47F5 /* string.n */, F96D3EA808F272A7004A47F5 /* StringObj.3 */, F96D3EA908F272A7004A47F5 /* StrMatch.3 */, F96D3EAA08F272A7004A47F5 /* subst.n */, F96D3EAB08F272A7004A47F5 /* SubstObj.3 */, F96D3EAC08F272A7004A47F5 /* switch.n */, F974D5760FBE7E1900BF728B /* tailcall.n */, F96D3EAD08F272A7004A47F5 /* Tcl.n */, F99D61180EF5573A00BBFE01 /* TclZlib.3 */, F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */, F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */, F96D3EB008F272A7004A47F5 /* tclsh.1 */, F96D3EB108F272A7004A47F5 /* tcltest.n */, F96D3EB208F272A7004A47F5 /* tclvars.n */, F96D3EB308F272A7004A47F5 /* tell.n */, F96D3EB408F272A7004A47F5 /* Thread.3 */, F9183E640EFC80CD0030B814 /* throw.n */, F96D3EB508F272A7004A47F5 /* time.n */, F96D3EB608F272A7004A47F5 /* tm.n */, F96D3EB708F272A7004A47F5 /* ToUpper.3 */, F96D3EB808F272A7004A47F5 /* trace.n */, F96D3EB908F272A7004A47F5 /* TraceCmd.3 */, F96D3EBA08F272A7004A47F5 /* TraceVar.3 */, F96D3EBB08F272A7004A47F5 /* Translate.3 */, F9183E650EFC80D70030B814 /* try.n */, F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */, F96D3EBD08F272A7004A47F5 /* unknown.n */, F96D3EBE08F272A7004A47F5 /* unload.n */, F96D3EBF08F272A7004A47F5 /* unset.n */, F96D3EC008F272A7004A47F5 /* update.n */, F96D3EC108F272A7004A47F5 /* uplevel.n */, F96D3EC208F272A7004A47F5 /* UpVar.3 */, F96D3EC308F272A7004A47F5 /* upvar.n */, F96D3EC408F272A7004A47F5 /* Utf.3 */, F96D3EC508F272A7004A47F5 /* variable.n */, F96D3EC608F272A7004A47F5 /* vwait.n */, F96D3EC708F272A7004A47F5 /* while.n */, F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */, F915432D0EF201EE0032D1E8 /* zlib.n */, ); path = doc; sourceTree = ""; }; F96D3EC908F272A7004A47F5 /* generic */ = { isa = PBXGroup; children = ( F96D3ECA08F272A7004A47F5 /* README */, F96D3ECB08F272A7004A47F5 /* regc_color.c */, F96D3ECC08F272A7004A47F5 /* regc_cvec.c */, F96D3ECD08F272A7004A47F5 /* regc_lex.c */, F96D3ECE08F272A7004A47F5 /* regc_locale.c */, F96D3ECF08F272A7004A47F5 /* regc_nfa.c */, F96D3ED008F272A7004A47F5 /* regcomp.c */, F96D3ED108F272A7004A47F5 /* regcustom.h */, F96D3ED208F272A7004A47F5 /* rege_dfa.c */, F96D3ED308F272A7004A47F5 /* regerror.c */, F96D3ED408F272A7004A47F5 /* regerrs.h */, F96D3ED508F272A7004A47F5 /* regex.h */, F96D3ED608F272A7004A47F5 /* regexec.c */, F96D3ED708F272A7004A47F5 /* regfree.c */, F96D3ED808F272A7004A47F5 /* regfronts.c */, F96D3ED908F272A7004A47F5 /* regguts.h */, F96D3EDA08F272A7004A47F5 /* tcl.decls */, F96D3EDB08F272A7004A47F5 /* tcl.h */, F96D3EDC08F272A7004A47F5 /* tclAlloc.c */, F96D3EDD08F272A7004A47F5 /* tclAsync.c */, F96D3EDE08F272A7004A47F5 /* tclBasic.c */, F96D3EDF08F272A7004A47F5 /* tclBinary.c */, F96D3EE008F272A7004A47F5 /* tclCkalloc.c */, F96D3EE108F272A7004A47F5 /* tclClock.c */, F96D3EE208F272A7004A47F5 /* tclCmdAH.c */, F96D3EE308F272A7004A47F5 /* tclCmdIL.c */, F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */, F96D3EE508F272A7004A47F5 /* tclCompCmds.c */, F96D3EE608F272A7004A47F5 /* tclCompExpr.c */, F96D3EE708F272A7004A47F5 /* tclCompile.c */, F96D3EE808F272A7004A47F5 /* tclCompile.h */, F96D3EE908F272A7004A47F5 /* tclConfig.c */, F96D3EEA08F272A7004A47F5 /* tclDate.c */, F96D3EEB08F272A7004A47F5 /* tclDecls.h */, F96D3EEC08F272A7004A47F5 /* tclDictObj.c */, F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */, F96D3EED08F272A7004A47F5 /* tclEncoding.c */, F96D3EEE08F272A7004A47F5 /* tclEnv.c */, F96D3EEF08F272A7004A47F5 /* tclEvent.c */, F96D3EF008F272A7004A47F5 /* tclExecute.c */, F96D3EF108F272A7004A47F5 /* tclFCmd.c */, F96D3EF208F272A7004A47F5 /* tclFileName.c */, F96D3EF308F272A7004A47F5 /* tclFileSystem.h */, F96D3EF408F272A7004A47F5 /* tclGet.c */, F96D3EF508F272A7004A47F5 /* tclGetDate.y */, F96D3EF608F272A7004A47F5 /* tclHash.c */, F96D3EF708F272A7004A47F5 /* tclHistory.c */, F96D3EF808F272A7004A47F5 /* tclIndexObj.c */, F96D3EF908F272A7004A47F5 /* tclInt.decls */, F96D3EFA08F272A7004A47F5 /* tclInt.h */, F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */, F96D3EFC08F272A7004A47F5 /* tclInterp.c */, F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */, F96D3EFE08F272A7004A47F5 /* tclIO.c */, F96D3EFF08F272A7004A47F5 /* tclIO.h */, F96D3F0008F272A7004A47F5 /* tclIOCmd.c */, F96D3F0108F272A7004A47F5 /* tclIOGT.c */, F96D3F0208F272A7004A47F5 /* tclIORChan.c */, F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */, F96D3F0308F272A7004A47F5 /* tclIOSock.c */, F96D3F0408F272A7004A47F5 /* tclIOUtil.c */, F96D3F0508F272A7004A47F5 /* tclLink.c */, F96D3F0608F272A7004A47F5 /* tclListObj.c */, F96D3F0708F272A7004A47F5 /* tclLiteral.c */, F96D3F0808F272A7004A47F5 /* tclLoad.c */, F96D3F0908F272A7004A47F5 /* tclLoadNone.c */, F96D3F0A08F272A7004A47F5 /* tclMain.c */, F96D3F0B08F272A7004A47F5 /* tclNamesp.c */, F96D3F0C08F272A7004A47F5 /* tclNotify.c */, F96D3F0D08F272A7004A47F5 /* tclObj.c */, F93599B20DF1F75400E04F67 /* tclOO.c */, F93599B40DF1F75900E04F67 /* tclOO.decls */, F93599B50DF1F75D00E04F67 /* tclOO.h */, F93599B60DF1F76100E04F67 /* tclOOBasic.c */, F93599B80DF1F76600E04F67 /* tclOOCall.c */, F93599BA0DF1F76A00E04F67 /* tclOODecls.h */, F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */, F93599BD0DF1F77400E04F67 /* tclOOInfo.c */, F93599BF0DF1F77900E04F67 /* tclOOInt.h */, F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */, F93599C10DF1F78300E04F67 /* tclOOMethod.c */, F93599C30DF1F78800E04F67 /* tclOOStubInit.c */, F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */, F96D3F0E08F272A7004A47F5 /* tclPanic.c */, F96D3F0F08F272A7004A47F5 /* tclParse.c */, F96D3F1108F272A7004A47F5 /* tclPathObj.c */, F96D3F1208F272A7004A47F5 /* tclPipe.c */, F96D3F1308F272A7004A47F5 /* tclPkg.c */, F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */, F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */, F96D3F1608F272A7004A47F5 /* tclPort.h */, F96D3F1708F272A7004A47F5 /* tclPosixStr.c */, F96D3F1808F272A7004A47F5 /* tclPreserve.c */, F96D3F1908F272A7004A47F5 /* tclProc.c */, F96D3F1A08F272A7004A47F5 /* tclRegexp.c */, F96D3F1B08F272A7004A47F5 /* tclRegexp.h */, F96D3F1C08F272A7004A47F5 /* tclResolve.c */, F96D3F1D08F272A7004A47F5 /* tclResult.c */, F96D3F1E08F272A7004A47F5 /* tclScan.c */, F96D3F1F08F272A7004A47F5 /* tclStringObj.c */, F96D3F2408F272A7004A47F5 /* tclStrToD.c */, F96D3F2508F272A7004A47F5 /* tclStubInit.c */, F96D3F2608F272A7004A47F5 /* tclStubLib.c */, F96D3F2708F272A7004A47F5 /* tclTest.c */, F96D3F2808F272A7004A47F5 /* tclTestObj.c */, F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */, F96D3F2A08F272A7004A47F5 /* tclThread.c */, F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */, F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */, F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */, F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */, F96D3F2F08F272A7004A47F5 /* tclTimer.c */, F9903CAF094FAADA004613E9 /* tclTomMath.decls */, F96D3F3008F272A7004A47F5 /* tclTomMath.h */, F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */, F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */, F96D3F3208F272A7004A47F5 /* tclTrace.c */, F96D3F3308F272A7004A47F5 /* tclUniData.c */, F96D3F3408F272A7004A47F5 /* tclUtf.c */, F96D3F3508F272A7004A47F5 /* tclUtil.c */, F96D3F3608F272A7004A47F5 /* tclVar.c */, F96437C90EF0D4B2003F468E /* tclZlib.c */, F96D3F3708F272A7004A47F5 /* tommath.h */, ); path = generic; sourceTree = ""; }; F96D3F3808F272A7004A47F5 /* library */ = { isa = PBXGroup; children = ( F96D3F3908F272A8004A47F5 /* auto.tcl */, F96D3F3A08F272A8004A47F5 /* clock.tcl */, F96D3F3B08F272A8004A47F5 /* dde */, F96D3F8C08F272A8004A47F5 /* history.tcl */, F96D3F8D08F272A8004A47F5 /* http */, F96D3F9008F272A8004A47F5 /* http1.0 */, F96D3F9308F272A8004A47F5 /* init.tcl */, F96D3F9408F272A8004A47F5 /* msgcat */, F96D401708F272AA004A47F5 /* opt */, F96D401A08F272AA004A47F5 /* package.tcl */, F96D401B08F272AA004A47F5 /* parray.tcl */, F9ECB1110B26521500A28025 /* platform */, F96D401C08F272AA004A47F5 /* reg */, F96D401E08F272AA004A47F5 /* safe.tcl */, F96D401F08F272AA004A47F5 /* tclIndex */, F96D402008F272AA004A47F5 /* tcltest */, F96D402308F272AA004A47F5 /* tm.tcl */, F96D425B08F272B2004A47F5 /* word.tcl */, ); path = library; sourceTree = ""; }; F96D3F3B08F272A8004A47F5 /* dde */ = { isa = PBXGroup; children = ( F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */, ); path = dde; sourceTree = ""; }; F96D3F8D08F272A8004A47F5 /* http */ = { isa = PBXGroup; children = ( F96D3F8E08F272A8004A47F5 /* http.tcl */, F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */, ); path = http; sourceTree = ""; }; F96D3F9008F272A8004A47F5 /* http1.0 */ = { isa = PBXGroup; children = ( F96D3F9108F272A8004A47F5 /* http.tcl */, F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */, ); path = http1.0; sourceTree = ""; }; F96D3F9408F272A8004A47F5 /* msgcat */ = { isa = PBXGroup; children = ( F96D3F9508F272A8004A47F5 /* msgcat.tcl */, F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */, ); path = msgcat; sourceTree = ""; }; F96D401708F272AA004A47F5 /* opt */ = { isa = PBXGroup; children = ( F96D401808F272AA004A47F5 /* optparse.tcl */, F96D401908F272AA004A47F5 /* pkgIndex.tcl */, ); path = opt; sourceTree = ""; }; F96D401C08F272AA004A47F5 /* reg */ = { isa = PBXGroup; children = ( F96D401D08F272AA004A47F5 /* pkgIndex.tcl */, ); path = reg; sourceTree = ""; }; F96D402008F272AA004A47F5 /* tcltest */ = { isa = PBXGroup; children = ( F96D402108F272AA004A47F5 /* pkgIndex.tcl */, F96D402208F272AA004A47F5 /* tcltest.tcl */, ); path = tcltest; sourceTree = ""; }; F96D425C08F272B2004A47F5 /* libtommath */ = { isa = PBXGroup; children = ( F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */, F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */, F96D426908F272B3004A47F5 /* bn_mp_add.c */, F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */, F96D426C08F272B3004A47F5 /* bn_mp_and.c */, F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */, F96D426E08F272B3004A47F5 /* bn_mp_clear.c */, F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */, F96D427008F272B3004A47F5 /* bn_mp_cmp.c */, F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */, F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */, F96D427408F272B3004A47F5 /* bn_mp_copy.c */, F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */, F96D427608F272B3004A47F5 /* bn_mp_div.c */, F96D427708F272B3004A47F5 /* bn_mp_div_2.c */, F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */, F96D427908F272B3004A47F5 /* bn_mp_div_3.c */, F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */, F96D427E08F272B3004A47F5 /* bn_mp_exch.c */, F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */, F96D428708F272B3004A47F5 /* bn_mp_grow.c */, F96D428808F272B3004A47F5 /* bn_mp_init.c */, F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */, F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */, F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */, F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */, F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */, F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */, F96D429508F272B3004A47F5 /* bn_mp_lshd.c */, F96D429608F272B3004A47F5 /* bn_mp_mod.c */, F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */, F96D429C08F272B3004A47F5 /* bn_mp_mul.c */, F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */, F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */, F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */, F96D42A208F272B3004A47F5 /* bn_mp_neg.c */, F96D42A308F272B3004A47F5 /* bn_mp_or.c */, F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */, F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */, F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */, F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */, F96D42BA08F272B3004A47F5 /* bn_mp_set.c */, F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */, F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */, F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */, F96D42C108F272B3004A47F5 /* bn_mp_sub.c */, F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */, F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */, F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */, F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */, F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */, F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */, F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */, F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */, F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */, F96D42D008F272B3004A47F5 /* bn_reverse.c */, F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */, F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */, F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */, F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */, F96D42D708F272B3004A47F5 /* bncore.c */, F96D432908F272B4004A47F5 /* tommath_class.h */, F96D432A08F272B4004A47F5 /* tommath_superclass.h */, ); path = libtommath; sourceTree = ""; }; F96D432C08F272B4004A47F5 /* macosx */ = { isa = PBXGroup; children = ( F96D432E08F272B5004A47F5 /* configure.ac */, F96D432F08F272B5004A47F5 /* GNUmakefile */, F96D433108F272B5004A47F5 /* README */, F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */, F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */, F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */, F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */, F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */, F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */, F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */, F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */, ); path = macosx; sourceTree = ""; }; F96D434408F272B5004A47F5 /* tests */ = { isa = PBXGroup; children = ( F96D434508F272B5004A47F5 /* all.tcl */, F96D434608F272B5004A47F5 /* append.test */, F96D434708F272B5004A47F5 /* appendComp.test */, F9ECB1CA0B2652D300A28025 /* apply.test */, F96D434808F272B5004A47F5 /* assocd.test */, F96D434908F272B5004A47F5 /* async.test */, F96D434A08F272B5004A47F5 /* autoMkindex.test */, F96D434B08F272B5004A47F5 /* basic.test */, F96D434C08F272B5004A47F5 /* binary.test */, F96D434D08F272B5004A47F5 /* case.test */, F96D434E08F272B5004A47F5 /* chan.test */, F9A493240CEBF38300B78AE2 /* chanio.test */, F96D434F08F272B5004A47F5 /* clock.test */, F96D435008F272B5004A47F5 /* cmdAH.test */, F96D435108F272B5004A47F5 /* cmdIL.test */, F96D435208F272B5004A47F5 /* cmdInfo.test */, F96D435308F272B5004A47F5 /* cmdMZ.test */, F96D435408F272B5004A47F5 /* compExpr-old.test */, F96D435508F272B5004A47F5 /* compExpr.test */, F96D435608F272B5004A47F5 /* compile.test */, F96D435708F272B5004A47F5 /* concat.test */, F96D435808F272B5004A47F5 /* config.test */, F974D5770FBE7E6100BF728B /* coroutine.test */, F96D435908F272B5004A47F5 /* dcall.test */, F96D435A08F272B5004A47F5 /* dict.test */, F96D435C08F272B5004A47F5 /* dstring.test */, F96D435E08F272B5004A47F5 /* encoding.test */, F96D435F08F272B5004A47F5 /* env.test */, F96D436008F272B5004A47F5 /* error.test */, F96D436108F272B5004A47F5 /* eval.test */, F96D436208F272B5004A47F5 /* event.test */, F96D436308F272B5004A47F5 /* exec.test */, F96D436408F272B5004A47F5 /* execute.test */, F96D436508F272B5004A47F5 /* expr-old.test */, F96D436608F272B5004A47F5 /* expr.test */, F96D436708F272B6004A47F5 /* fCmd.test */, F96D436808F272B6004A47F5 /* fileName.test */, F96D436908F272B6004A47F5 /* fileSystem.test */, F96D436A08F272B6004A47F5 /* for-old.test */, F96D436B08F272B6004A47F5 /* for.test */, F96D436C08F272B6004A47F5 /* foreach.test */, F96D436D08F272B6004A47F5 /* format.test */, F96D436E08F272B6004A47F5 /* get.test */, F96D436F08F272B6004A47F5 /* history.test */, F96D437008F272B6004A47F5 /* http.test */, F974D56C0FBE7D6300BF728B /* http11.test */, F96D437108F272B6004A47F5 /* httpd */, F974D56D0FBE7D6300BF728B /* httpd11.tcl */, F96D437208F272B6004A47F5 /* httpold.test */, F96D437308F272B6004A47F5 /* if-old.test */, F96D437408F272B6004A47F5 /* if.test */, F96D437508F272B6004A47F5 /* incr-old.test */, F96D437608F272B6004A47F5 /* incr.test */, F96D437708F272B6004A47F5 /* indexObj.test */, F96D437808F272B6004A47F5 /* info.test */, F96D437908F272B6004A47F5 /* init.test */, F96D437A08F272B6004A47F5 /* interp.test */, F96D437B08F272B6004A47F5 /* io.test */, F96D437C08F272B6004A47F5 /* ioCmd.test */, F96D437D08F272B6004A47F5 /* iogt.test */, F96D437F08F272B6004A47F5 /* join.test */, F96D438008F272B6004A47F5 /* lindex.test */, F96D438108F272B6004A47F5 /* link.test */, F96D438208F272B6004A47F5 /* linsert.test */, F96D438308F272B6004A47F5 /* list.test */, F96D438408F272B6004A47F5 /* listObj.test */, F96D438508F272B6004A47F5 /* llength.test */, F96D438608F272B6004A47F5 /* load.test */, F96D438708F272B6004A47F5 /* lrange.test */, F96D438808F272B6004A47F5 /* lrepeat.test */, F96D438908F272B6004A47F5 /* lreplace.test */, F96D438A08F272B6004A47F5 /* lsearch.test */, F96D438B08F272B6004A47F5 /* lset.test */, F96D438C08F272B6004A47F5 /* lsetComp.test */, F96D438D08F272B6004A47F5 /* macOSXFCmd.test */, F95FAFF90B34F1130072E431 /* macOSXLoad.test */, F96D438E08F272B6004A47F5 /* main.test */, F9ECB1CB0B26534C00A28025 /* mathop.test */, F96D438F08F272B6004A47F5 /* misc.test */, F96D439008F272B6004A47F5 /* msgcat.test */, F96D439108F272B6004A47F5 /* namespace-old.test */, F96D439208F272B7004A47F5 /* namespace.test */, F96D439308F272B7004A47F5 /* notify.test */, F91DC23C0E44C51B002CB8D1 /* nre.test */, F96D439408F272B7004A47F5 /* obj.test */, F93599C80DF1F81900E04F67 /* oo.test */, F96D439508F272B7004A47F5 /* opt.test */, F96D439608F272B7004A47F5 /* package.test */, F96D439708F272B7004A47F5 /* parse.test */, F96D439808F272B7004A47F5 /* parseExpr.test */, F96D439908F272B7004A47F5 /* parseOld.test */, F96D439A08F272B7004A47F5 /* pid.test */, F96D439B08F272B7004A47F5 /* pkg.test */, F96D439C08F272B7004A47F5 /* pkgMkIndex.test */, F96D439D08F272B7004A47F5 /* platform.test */, F96D439E08F272B7004A47F5 /* proc-old.test */, F96D439F08F272B7004A47F5 /* proc.test */, F96D43A008F272B7004A47F5 /* pwd.test */, F96D43A108F272B7004A47F5 /* README */, F96D43A208F272B7004A47F5 /* reg.test */, F96D43A308F272B7004A47F5 /* regexp.test */, F96D43A408F272B7004A47F5 /* regexpComp.test */, F96D43A508F272B7004A47F5 /* registry.test */, F96D43A608F272B7004A47F5 /* remote.tcl */, F96D43A708F272B7004A47F5 /* rename.test */, F96D43A808F272B7004A47F5 /* result.test */, F96D43A908F272B7004A47F5 /* safe.test */, F96D43AA08F272B7004A47F5 /* scan.test */, F96D43AB08F272B7004A47F5 /* security.test */, F96D43AC08F272B7004A47F5 /* set-old.test */, F96D43AD08F272B7004A47F5 /* set.test */, F96D43AE08F272B7004A47F5 /* socket.test */, F96D43AF08F272B7004A47F5 /* source.test */, F96D43B008F272B7004A47F5 /* split.test */, F96D43B108F272B7004A47F5 /* stack.test */, F96D43B208F272B7004A47F5 /* string.test */, F96D43B308F272B7004A47F5 /* stringComp.test */, F96D43B408F272B7004A47F5 /* stringObj.test */, F96D43B508F272B7004A47F5 /* subst.test */, F96D43B608F272B7004A47F5 /* switch.test */, F974D5780FBE7E6100BF728B /* tailcall.test */, F96D43B708F272B7004A47F5 /* tcltest.test */, F96D43B808F272B7004A47F5 /* thread.test */, F96D43B908F272B7004A47F5 /* timer.test */, F96D43BA08F272B7004A47F5 /* tm.test */, F96D43BB08F272B7004A47F5 /* trace.test */, F96D43BC08F272B7004A47F5 /* unixFCmd.test */, F96D43BD08F272B7004A47F5 /* unixFile.test */, F96D43BE08F272B7004A47F5 /* unixInit.test */, F96D43BF08F272B7004A47F5 /* unixNotfy.test */, F96D43C008F272B7004A47F5 /* unknown.test */, F96D43C108F272B7004A47F5 /* unload.test */, F96D43C208F272B7004A47F5 /* uplevel.test */, F96D43C308F272B7004A47F5 /* upvar.test */, F96D43C408F272B7004A47F5 /* utf.test */, F96D43C508F272B7004A47F5 /* util.test */, F96D43C608F272B7004A47F5 /* var.test */, F96D43C708F272B7004A47F5 /* while-old.test */, F96D43C808F272B7004A47F5 /* while.test */, F96D43C908F272B7004A47F5 /* winConsole.test */, F96D43CA08F272B7004A47F5 /* winDde.test */, F96D43CB08F272B7004A47F5 /* winFCmd.test */, F96D43CC08F272B7004A47F5 /* winFile.test */, F96D43CD08F272B7004A47F5 /* winNotify.test */, F96D43CE08F272B7004A47F5 /* winPipe.test */, F96D43CF08F272B7004A47F5 /* winTime.test */, F915432A0EF201CF0032D1E8 /* zlib.test */, ); path = tests; sourceTree = ""; }; F96D43D008F272B8004A47F5 /* tools */ = { isa = PBXGroup; children = ( F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */, F96D43D208F272B8004A47F5 /* configure */, F96D43D308F272B8004A47F5 /* configure.in */, F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */, F96D442508F272B8004A47F5 /* genStubs.tcl */, F96D442708F272B8004A47F5 /* index.tcl */, F96D442808F272B8004A47F5 /* installData.tcl */, F96D442908F272B8004A47F5 /* loadICU.tcl */, F96D442A08F272B8004A47F5 /* Makefile.in */, F96D442B08F272B8004A47F5 /* makeTestCases.tcl */, F96D442C08F272B8004A47F5 /* man2help.tcl */, F96D442D08F272B8004A47F5 /* man2help2.tcl */, F96D442E08F272B8004A47F5 /* man2html.tcl */, F96D442F08F272B8004A47F5 /* man2html1.tcl */, F96D443008F272B8004A47F5 /* man2html2.tcl */, F96D443108F272B8004A47F5 /* man2tcl.c */, F96D443208F272B8004A47F5 /* README */, F96D443308F272B8004A47F5 /* regexpTestLib.tcl */, F96D443508F272B8004A47F5 /* tcl.hpj.in */, F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */, F96D443A08F272B9004A47F5 /* tclZIC.tcl */, F92D7F100DE777240033A13A /* tsdPerf.tcl */, F96D443B08F272B9004A47F5 /* uniClass.tcl */, F96D443C08F272B9004A47F5 /* uniParse.tcl */, ); path = tools; sourceTree = ""; }; F96D443E08F272B9004A47F5 /* unix */ = { isa = PBXGroup; children = ( F96D444008F272B9004A47F5 /* aclocal.m4 */, F96D444108F272B9004A47F5 /* configure */, F96D444208F272B9004A47F5 /* configure.in */, F96D444308F272B9004A47F5 /* dltest */, F96D444D08F272B9004A47F5 /* install-sh */, F96D444E08F272B9004A47F5 /* installManPage */, F96D444F08F272B9004A47F5 /* ldAix */, F96D445008F272B9004A47F5 /* Makefile.in */, F96D445208F272B9004A47F5 /* README */, F96D445308F272B9004A47F5 /* tcl.m4 */, F974D5790FBE7E9C00BF728B /* tcl.pc.in */, F96D445408F272B9004A47F5 /* tcl.spec */, F96D445508F272B9004A47F5 /* tclAppInit.c */, F96D445608F272B9004A47F5 /* tclConfig.h.in */, F96D445708F272B9004A47F5 /* tclConfig.sh.in */, F96D445808F272B9004A47F5 /* tclLoadAix.c */, F96D445908F272B9004A47F5 /* tclLoadDl.c */, F96D445B08F272B9004A47F5 /* tclLoadDyld.c */, F96D445C08F272B9004A47F5 /* tclLoadNext.c */, F96D445D08F272B9004A47F5 /* tclLoadOSF.c */, F96D445E08F272B9004A47F5 /* tclLoadShl.c */, F96D445F08F272B9004A47F5 /* tclUnixChan.c */, F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */, F96D446008F272B9004A47F5 /* tclUnixEvent.c */, F96D446108F272B9004A47F5 /* tclUnixFCmd.c */, F96D446208F272B9004A47F5 /* tclUnixFile.c */, F96D446308F272B9004A47F5 /* tclUnixInit.c */, F96D446408F272B9004A47F5 /* tclUnixNotfy.c */, F96D446508F272B9004A47F5 /* tclUnixPipe.c */, F96D446608F272B9004A47F5 /* tclUnixPort.h */, F96D446708F272B9004A47F5 /* tclUnixSock.c */, F96D446808F272B9004A47F5 /* tclUnixTest.c */, F96D446908F272B9004A47F5 /* tclUnixThrd.c */, F96D446B08F272B9004A47F5 /* tclUnixTime.c */, F96D446C08F272B9004A47F5 /* tclXtNotify.c */, F96D446D08F272B9004A47F5 /* tclXtTest.c */, ); path = unix; sourceTree = ""; }; F96D444308F272B9004A47F5 /* dltest */ = { isa = PBXGroup; children = ( F96D444408F272B9004A47F5 /* Makefile.in */, F96D444508F272B9004A47F5 /* pkga.c */, F96D444608F272B9004A47F5 /* pkgb.c */, F96D444708F272B9004A47F5 /* pkgc.c */, F96D444808F272B9004A47F5 /* pkgd.c */, F96D444908F272B9004A47F5 /* pkge.c */, F96D444B08F272B9004A47F5 /* pkgua.c */, F96D444C08F272B9004A47F5 /* README */, ); path = dltest; sourceTree = ""; }; F96D446E08F272B9004A47F5 /* win */ = { isa = PBXGroup; children = ( F96D447008F272BA004A47F5 /* aclocal.m4 */, F96D447108F272BA004A47F5 /* buildall.vc.bat */, F96D447208F272BA004A47F5 /* cat.c */, F96D447308F272BA004A47F5 /* coffbase.txt */, F96D447408F272BA004A47F5 /* configure */, F96D447508F272BA004A47F5 /* configure.in */, F96D447608F272BA004A47F5 /* makefile.bc */, F96D447708F272BA004A47F5 /* Makefile.in */, F96D447808F272BA004A47F5 /* makefile.vc */, F96D447908F272BA004A47F5 /* nmakehlp.c */, F96D447A08F272BA004A47F5 /* README */, F96D447C08F272BA004A47F5 /* rules.vc */, F96D447D08F272BA004A47F5 /* stub16.c */, F96D447E08F272BA004A47F5 /* tcl.dsp */, F96D447F08F272BA004A47F5 /* tcl.dsw */, F96D448008F272BA004A47F5 /* tcl.hpj.in */, F96D448108F272BA004A47F5 /* tcl.m4 */, F96D448208F272BA004A47F5 /* tcl.rc */, F96D448308F272BA004A47F5 /* tclAppInit.c */, F96D448408F272BA004A47F5 /* tclConfig.sh.in */, F96D448608F272BA004A47F5 /* tclsh.rc */, F96D448708F272BA004A47F5 /* tclWin32Dll.c */, F96D448808F272BA004A47F5 /* tclWinChan.c */, F96D448908F272BA004A47F5 /* tclWinConsole.c */, F96D448A08F272BA004A47F5 /* tclWinDde.c */, F96D448B08F272BA004A47F5 /* tclWinError.c */, F96D448C08F272BA004A47F5 /* tclWinFCmd.c */, F96D448D08F272BA004A47F5 /* tclWinFile.c */, F96D448E08F272BA004A47F5 /* tclWinInit.c */, F96D448F08F272BA004A47F5 /* tclWinInt.h */, F96D449008F272BA004A47F5 /* tclWinLoad.c */, F96D449108F272BA004A47F5 /* tclWinNotify.c */, F96D449208F272BA004A47F5 /* tclWinPipe.c */, F96D449308F272BA004A47F5 /* tclWinPort.h */, F96D449408F272BA004A47F5 /* tclWinReg.c */, F96D449508F272BA004A47F5 /* tclWinSerial.c */, F96D449608F272BA004A47F5 /* tclWinSock.c */, F96D449708F272BA004A47F5 /* tclWinTest.c */, F96D449808F272BA004A47F5 /* tclWinThrd.c */, F96D449908F272BA004A47F5 /* tclWinThrd.h */, F96D449A08F272BA004A47F5 /* tclWinTime.c */, ); path = win; sourceTree = ""; }; F9ECB1110B26521500A28025 /* platform */ = { isa = PBXGroup; children = ( F9ECB1120B26521500A28025 /* pkgIndex.tcl */, F9ECB1130B26521500A28025 /* platform.tcl */, F9ECB1140B26521500A28025 /* shell.tcl */, ); path = platform; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 8DD76FA90486AB0100D96B5E /* tcltest */ = { isa = PBXNativeTarget; buildConfigurationList = F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */; buildPhases = ( F9A5C5F508F651A2008AE941 /* Configure Tcl */, 8DD76FAB0486AB0100D96B5E /* Sources */, 8DD76FAD0486AB0100D96B5E /* Frameworks */, F95FA74C0B32CE190072E431 /* Build dltest */, ); buildRules = ( ); dependencies = ( ); name = tcltest; productInstallPath = "$(BINDIR)"; productName = tcltest; productReference = 8DD76FB20486AB0100D96B5E /* tcltest */; productType = "com.apple.product-type.tool"; }; F97258A50A86873C00096C78 /* tests */ = { isa = PBXNativeTarget; buildConfigurationList = F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */; buildPhases = ( F97258A40A86873C00096C78 /* Run Testsuite */, ); buildRules = ( ); dependencies = ( F97258D30A868C6F00096C78 /* PBXTargetDependency */, ); name = tests; productName = tests; productType = "com.apple.product-type.bundle"; }; F9E61D16090A3E94002B3151 /* Tcl */ = { isa = PBXNativeTarget; buildConfigurationList = F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */; buildPhases = ( F97AF02F0B665DA900310EA2 /* Build Tcl */, ); buildRules = ( ); dependencies = ( ); name = Tcl; productName = tclsh; productReference = F9A3084B08F2D4CE00BAE1AB /* tclsh */; productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; }; buildConfigurationList = F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */; compatibilityVersion = "Xcode 3.2"; hasScannedForEncodings = 1; mainGroup = 08FB7794FE84155DC02AAC07 /* Tcl */; projectDirPath = ""; projectRoot = ..; targets = ( F9E61D16090A3E94002B3151 /* Tcl */, 8DD76FA90486AB0100D96B5E /* tcltest */, F97258A50A86873C00096C78 /* tests */, ); }; /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ F95FA74C0B32CE190072E431 /* Build dltest */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh", "$(TCL_SRCROOT)/generic/tclStubLib.c", "$(TCL_SRCROOT)/unix/dltest/pkga.c", "$(TCL_SRCROOT)/unix/dltest/pkgb.c", "$(TCL_SRCROOT)/unix/dltest/pkgc.c", "$(TCL_SRCROOT)/unix/dltest/pkgd.c", "$(TCL_SRCROOT)/unix/dltest/pkge.c", "$(TCL_SRCROOT)/unix/dltest/pkgua.c", ); name = "Build dltest"; outputPaths = ( "$(DERIVED_FILE_DIR)/tcl/dltest.marker", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = "## dltest build script phase\n\nrm -f \"${DERIVED_FILE_DIR}/tcl/dltest.marker\"\nmake -C \"${DERIVED_FILE_DIR}/tcl\" dltest.marker\nln -fsh \"${DERIVED_FILE_DIR}/tcl/dltest\" \"${CONFIGURATION_BUILD_DIR}\"\n"; showEnvVarsInLog = 0; }; F97258A40A86873C00096C78 /* Run Testsuite */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Run Testsuite"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = "if [ \"${ACTION:-build}\" == \"build\" ]; then\nif [ -z \"${HOME}\" ]; then export HOME=\"$(echo ~)\"; fi\ncd \"${TARGET_TEMP_DIR}\"; rm -rf \"${DERIVED_FILE_DIR}\"; mkdir -p \"${DERIVED_FILE_DIR}\"\nprintf '%s%s%s%s%s' '\npackage require tcltest 2.2\nnamespace import tcltest::*\nconfigure -testdir [file normalize {' \"${TCL_SRCROOT}\" '/tests}]\nconfigure -tmpdir [file normalize {' \"${DERIVED_FILE_DIR}\" '}]\nconfigure -verbose [concat [configure -verbose] line]\nrunAllTests\n' | \"${TEST_RIG}\"; TEST_RIG_RESULT=$?\n[ ${TEST_RIG_RESULT} -ne 0 ] && echo \"tcltest:0: error: tcltest exited abnormally with code ${TEST_RIG_RESULT}.\"\nexit ${TEST_RIG_RESULT}\nfi"; showEnvVarsInLog = 0; }; F97AF02F0B665DA900310EA2 /* Build Tcl */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${TARGET_TEMP_DIR}/.none", ); name = "Build Tcl"; outputPaths = ( "${TARGET_BUILD_DIR}/${EXECUTABLE_NAME}", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = "if [ -e \"${TARGET_BUILD_DIR}/tclsh\" ]; then\n mv -f \"${TARGET_BUILD_DIR}/tclsh\" \"${TARGET_BUILD_DIR}/tclsh${VERSION}\"\nfi\nexport CC=$(xcrun -find ${GCC} || echo ${GCC}); export LD=${CC}\ngnumake -C \"${TCL_SRCROOT}/macosx\" -j \"$(sysctl -n hw.activecpu)\" \"$(echo \"${ACTION}\" | sed -e s/build// -e s/clean/distclean/ -e s/..\\*/\\&-/)${MAKE_TARGET}\" CFLAGS_WARNING=\"${WARNING_CFLAGS}\" CFLAGS_OPTIMIZE=\"-O${GCC_OPTIMIZATION_LEVEL}\" SYMROOT=\"${BUILT_PRODUCTS_DIR}\" OBJ_DIR=\"${OBJECT_FILE_DIR}\" INSTALL_ROOT=\"${DSTROOT}\" PREFIX=\"${PREFIX}\" BINDIR=\"${BINDIR}\" LIBDIR=\"${FRAMEWORK_INSTALL_PATH}\" MANDIR=\"${MANDIR}\" EXTRA_CONFIGURE_ARGS=\"${CONFIGURE_ARGS}\" ${EXTRA_MAKE_FLAGS}\nresult=$?\nif [ -e \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" ]; then\n mv -f \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" \"${TARGET_BUILD_DIR}/tclsh\"\nfi\nif [ -e \"${BUILT_PRODUCTS_DIR}/tcltest\" ]; then\n\trm -f \"${BUILT_PRODUCTS_DIR}/tcltest\"\nfi\necho \"Done\"\nrm -f \"${SCRIPT_INPUT_FILE_0}\"\nexit ${result}\n"; showEnvVarsInLog = 0; }; F9A5C5F508F651A2008AE941 /* Configure Tcl */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(TCL_SRCROOT)/macosx/configure.ac", "$(TCL_SRCROOT)/unix/configure.in", "$(TCL_SRCROOT)/unix/tcl.m4", "$(TCL_SRCROOT)/unix/aclocal.m4", "$(TCL_SRCROOT)/unix/tclConfig.sh.in", "$(TCL_SRCROOT)/unix/Makefile.in", "$(TCL_SRCROOT)/unix/dltest/Makefile.in", ); name = "Configure Tcl"; outputPaths = ( "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 8DD76FAB0486AB0100D96B5E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( F96D456F08F272BB004A47F5 /* regcomp.c in Sources */, F96D457208F272BB004A47F5 /* regerror.c in Sources */, F96D457508F272BB004A47F5 /* regexec.c in Sources */, F96D457608F272BB004A47F5 /* regfree.c in Sources */, F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */, F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */, F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */, F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */, F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */, F96D458008F272BC004A47F5 /* tclClock.c in Sources */, F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */, F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */, F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */, F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */, F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */, F96D458608F272BC004A47F5 /* tclCompile.c in Sources */, F96D458808F272BC004A47F5 /* tclConfig.c in Sources */, F96D458908F272BC004A47F5 /* tclDate.c in Sources */, F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */, F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */, F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */, F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */, F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */, F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */, F96D459108F272BC004A47F5 /* tclFileName.c in Sources */, F96D459308F272BC004A47F5 /* tclGet.c in Sources */, F96D459508F272BC004A47F5 /* tclHash.c in Sources */, F96D459608F272BC004A47F5 /* tclHistory.c in Sources */, F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */, F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */, F96D459D08F272BC004A47F5 /* tclIO.c in Sources */, F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */, F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */, F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */, F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */, F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */, F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */, F96D45A408F272BC004A47F5 /* tclLink.c in Sources */, F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */, F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */, F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */, F96D45A908F272BC004A47F5 /* tclMain.c in Sources */, F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */, F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */, F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */, F93599B30DF1F75400E04F67 /* tclOO.c in Sources */, F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */, F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */, F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */, F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */, F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */, F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */, F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */, F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */, F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */, F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */, F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */, F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */, F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */, F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */, F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */, F96D45B808F272BC004A47F5 /* tclProc.c in Sources */, F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */, F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */, F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */, F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */, F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */, F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */, F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */, F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */, F96D45C608F272BC004A47F5 /* tclTest.c in Sources */, F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */, F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */, F96D45C908F272BC004A47F5 /* tclThread.c in Sources */, F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */, F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */, F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */, F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */, F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */, F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */, F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */, F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */, F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */, F96D45D508F272BC004A47F5 /* tclVar.c in Sources */, F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */, F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */, F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */, F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */, F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */, F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */, F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */, F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */, F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */, F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */, F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */, F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */, F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */, F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */, F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */, F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */, F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */, F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */, F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */, F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */, F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */, F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */, F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */, F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */, F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */, F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */, F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */, F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */, F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */, F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */, F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */, F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */, F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */, F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */, F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */, F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */, F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */, F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */, F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */, F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */, F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */, F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */, F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */, F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */, F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */, F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */, F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */, F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */, F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */, F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */, F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */, F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */, F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */, F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */, F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */, F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */, F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */, F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */, F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */, F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */, F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */, F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */, F96D495508F272C3004A47F5 /* bncore.c in Sources */, F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */, F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */, F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */, F90509300913A72400327603 /* tclAppInit.c in Sources */, F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */, F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */, F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */, F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */, F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */, F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */, F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */, F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */, F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */, F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */, F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */, F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */, F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */, F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ F97258D30A868C6F00096C78 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 8DD76FA90486AB0100D96B5E /* tcltest */; targetProxy = F97258D20A868C6F00096C78 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ F91BCC4F093152310042A6BF /* ReleaseUniversal */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = ReleaseUniversal; }; F91BCC50093152310042A6BF /* ReleaseUniversal */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = ReleaseUniversal; }; F91BCC51093152310042A6BF /* ReleaseUniversal */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.6; PREBINDING = NO; }; name = ReleaseUniversal; }; F93084370BB93D2800CD0B9E /* DebugMemCompile */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugMemCompile; }; F93084380BB93D2800CD0B9E /* DebugMemCompile */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugMemCompile; }; F93084390BB93D2800CD0B9E /* DebugMemCompile */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugMemCompile; }; F930843A0BB93D2800CD0B9E /* DebugMemCompile */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-symbols=all"; CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = DebugMemCompile; }; F9359B250DF212DA00E04F67 /* DebugGCov */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; GCC_GENERATE_TEST_COVERAGE_FILES = YES; GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS)", "-lgcov", ); PREBINDING = NO; }; name = DebugGCov; }; F9359B260DF212DA00E04F67 /* DebugGCov */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugGCov; }; F9359B270DF212DA00E04F67 /* DebugGCov */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugGCov; }; F9359B280DF212DA00E04F67 /* DebugGCov */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugGCov; }; F95CC8AC09158F3100EA5ACE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = Debug; }; F95CC8AD09158F3100EA5ACE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = Release; }; F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugNoFixAndContinue; }; F95CC8B109158F3100EA5ACE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)"; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "__private_extern__=extern", "$(GCC_PREPROCESSOR_DEFINITIONS)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; PRODUCT_NAME = tcltest; }; name = Debug; }; F95CC8B209158F3100EA5ACE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = Release; }; F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugNoFixAndContinue; }; F95CC8B609158F3100EA5ACE /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = Debug; }; F95CC8B709158F3100EA5ACE /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = Release; }; F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = DebugNoFixAndContinue; }; F97258A90A86873D00096C78 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = Debug; }; F97258AA0A86873D00096C78 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = Release; }; F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugNoFixAndContinue; }; F97258AC0A86873D00096C78 /* ReleaseUniversal */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = ReleaseUniversal; }; F97AED1B0B660B2100310EA2 /* Debug64bit */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = Debug64bit; }; F97AED1C0B660B2100310EA2 /* Debug64bit */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = Debug64bit; }; F97AED1D0B660B2100310EA2 /* Debug64bit */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = Debug64bit; }; F97AED1E0B660B2100310EA2 /* Debug64bit */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = "$(NATIVE_ARCH_64_BIT)"; CONFIGURE_ARGS = "--enable-64bit $(CONFIGURE_ARGS)"; CPPFLAGS = "-arch $(NATIVE_ARCH_64_BIT) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.6; PREBINDING = NO; }; name = Debug64bit; }; F987512F0DE7B57E00B1C9EC /* DebugNoCF */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-corefoundation"; CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = DebugNoCF; }; F98751300DE7B57E00B1C9EC /* DebugNoCF */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugNoCF; }; F98751310DE7B57E00B1C9EC /* DebugNoCF */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugNoCF; }; F98751320DE7B57E00B1C9EC /* DebugNoCF */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugNoCF; }; F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads --disable-corefoundation"; CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = DebugNoCFUnthreaded; }; F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugNoCFUnthreaded; }; F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugNoCFUnthreaded; }; F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugNoCFUnthreaded; }; F9988AB10D814C6500B6B03B /* Debug gcc40 */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; GCC_VERSION = 4.0; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = "Debug gcc40"; }; F9988AB20D814C6500B6B03B /* Debug gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = "Debug gcc40"; }; F9988AB30D814C6500B6B03B /* Debug gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)"; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "__private_extern__=extern", "$(GCC_PREPROCESSOR_DEFINITIONS)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; PRODUCT_NAME = tcltest; }; name = "Debug gcc40"; }; F9988AB40D814C6500B6B03B /* Debug gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = "Debug gcc40"; }; F9988AB50D814C7500B6B03B /* Debug llvm-gcc */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; GCC = "llvm-gcc"; GCC_VERSION = com.apple.compilers.llvmgcc42; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = "Debug llvm-gcc"; }; F9988AB60D814C7500B6B03B /* Debug llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = "Debug llvm-gcc"; }; F9988AB70D814C7500B6B03B /* Debug llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)"; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "__private_extern__=extern", "$(GCC_PREPROCESSOR_DEFINITIONS)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; PRODUCT_NAME = tcltest; }; name = "Debug llvm-gcc"; }; F9988AB80D814C7500B6B03B /* Debug llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = "Debug llvm-gcc"; }; F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)"; GCC_VERSION = 4.0; MACOSX_DEPLOYMENT_TARGET = 10.6; PREBINDING = NO; }; name = "ReleaseUniversal gcc40"; }; F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = "ReleaseUniversal gcc40"; }; F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = "ReleaseUniversal gcc40"; }; F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = "ReleaseUniversal gcc40"; }; F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)"; DEBUG_INFORMATION_FORMAT = dwarf; GCC = "llvm-gcc"; GCC_OPTIMIZATION_LEVEL = 4; "GCC_OPTIMIZATION_LEVEL[arch=ppc]" = s; GCC_VERSION = com.apple.compilers.llvmgcc42; MACOSX_DEPLOYMENT_TARGET = 10.6; PREBINDING = NO; }; name = "ReleaseUniversal llvm-gcc"; }; F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = "ReleaseUniversal llvm-gcc"; }; F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = "ReleaseUniversal llvm-gcc"; }; F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = "ReleaseUniversal llvm-gcc"; }; F99EE73B0BE835310060D4AF /* DebugUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugUnthreaded; }; F99EE73C0BE835310060D4AF /* DebugLeaks */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugLeaks; }; F99EE73D0BE835310060D4AF /* DebugUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugUnthreaded; }; F99EE73E0BE835310060D4AF /* DebugLeaks */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugLeaks; }; F99EE73F0BE835310060D4AF /* DebugUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugUnthreaded; }; F99EE7400BE835310060D4AF /* DebugLeaks */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugLeaks; }; F99EE7410BE835310060D4AF /* DebugUnthreaded */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads"; CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = DebugUnthreaded; }; F99EE7420BE835310060D4AF /* DebugLeaks */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; GCC_PREPROCESSOR_DEFINITIONS = ( PURIFY, "$(GCC_PREPROCESSOR_DEFINITIONS)", ); MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; RUN_CLANG_STATIC_ANALYZER = YES; }; name = DebugLeaks; }; F9A9D1EF0FC77787002A2BE3 /* Debug clang */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; GCC = clang; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = "Debug clang"; }; F9A9D1F00FC77787002A2BE3 /* Debug clang */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = "Debug clang"; }; F9A9D1F10FC77787002A2BE3 /* Debug clang */ = { isa = XCBuildConfiguration; buildSettings = { CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)"; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "__private_extern__=extern", "$(GCC_PREPROCESSOR_DEFINITIONS)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; PRODUCT_NAME = tcltest; }; name = "Debug clang"; }; F9A9D1F20FC77787002A2BE3 /* Debug clang */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = "Debug clang"; }; F9A9D1F30FC77799002A2BE3 /* ReleaseUniversal clang */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CFLAGS = "-arch i386 -arch x86_64 $(CFLAGS)"; DEBUG_INFORMATION_FORMAT = dwarf; GCC = clang; GCC_OPTIMIZATION_LEVEL = 4; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; MACOSX_DEPLOYMENT_TARGET = 10.6; PREBINDING = NO; }; name = "ReleaseUniversal clang"; }; F9A9D1F40FC77799002A2BE3 /* ReleaseUniversal clang */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = "ReleaseUniversal clang"; }; F9A9D1F50FC77799002A2BE3 /* ReleaseUniversal clang */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = "ReleaseUniversal clang"; }; F9A9D1F60FC77799002A2BE3 /* ReleaseUniversal clang */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = "ReleaseUniversal clang"; }; F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = ReleaseUniversal10.5SDK; }; F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = ReleaseUniversal10.5SDK; }; F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = ReleaseUniversal10.5SDK; }; F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)"; CPPFLAGS = "-isysroot $(SDKROOT) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.5; PREBINDING = NO; SDKROOT = macosx10.5; }; name = ReleaseUniversal10.5SDK; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */ = { isa = XCConfigurationList; buildConfigurations = ( F95CC8AC09158F3100EA5ACE /* Debug */, F9A9D1F00FC77787002A2BE3 /* Debug clang */, F9988AB60D814C7500B6B03B /* Debug llvm-gcc */, F9988AB20D814C6500B6B03B /* Debug gcc40 */, F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */, F99EE73B0BE835310060D4AF /* DebugUnthreaded */, F98751300DE7B57E00B1C9EC /* DebugNoCF */, F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */, F93084370BB93D2800CD0B9E /* DebugMemCompile */, F99EE73C0BE835310060D4AF /* DebugLeaks */, F9359B260DF212DA00E04F67 /* DebugGCov */, F97AED1B0B660B2100310EA2 /* Debug64bit */, F95CC8AD09158F3100EA5ACE /* Release */, F91BCC4F093152310042A6BF /* ReleaseUniversal */, F9A9D1F40FC77799002A2BE3 /* ReleaseUniversal clang */, F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */, F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */, F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */ = { isa = XCConfigurationList; buildConfigurations = ( F95CC8B109158F3100EA5ACE /* Debug */, F9A9D1F10FC77787002A2BE3 /* Debug clang */, F9988AB70D814C7500B6B03B /* Debug llvm-gcc */, F9988AB30D814C6500B6B03B /* Debug gcc40 */, F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */, F99EE73D0BE835310060D4AF /* DebugUnthreaded */, F98751310DE7B57E00B1C9EC /* DebugNoCF */, F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */, F93084380BB93D2800CD0B9E /* DebugMemCompile */, F99EE73E0BE835310060D4AF /* DebugLeaks */, F9359B270DF212DA00E04F67 /* DebugGCov */, F97AED1C0B660B2100310EA2 /* Debug64bit */, F95CC8B209158F3100EA5ACE /* Release */, F91BCC50093152310042A6BF /* ReleaseUniversal */, F9A9D1F50FC77799002A2BE3 /* ReleaseUniversal clang */, F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */, F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */, F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */ = { isa = XCConfigurationList; buildConfigurations = ( F95CC8B609158F3100EA5ACE /* Debug */, F9A9D1EF0FC77787002A2BE3 /* Debug clang */, F9988AB50D814C7500B6B03B /* Debug llvm-gcc */, F9988AB10D814C6500B6B03B /* Debug gcc40 */, F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */, F99EE7410BE835310060D4AF /* DebugUnthreaded */, F987512F0DE7B57E00B1C9EC /* DebugNoCF */, F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */, F930843A0BB93D2800CD0B9E /* DebugMemCompile */, F99EE7420BE835310060D4AF /* DebugLeaks */, F9359B250DF212DA00E04F67 /* DebugGCov */, F97AED1E0B660B2100310EA2 /* Debug64bit */, F95CC8B709158F3100EA5ACE /* Release */, F91BCC51093152310042A6BF /* ReleaseUniversal */, F9A9D1F30FC77799002A2BE3 /* ReleaseUniversal clang */, F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */, F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */, F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */ = { isa = XCConfigurationList; buildConfigurations = ( F97258A90A86873D00096C78 /* Debug */, F9A9D1F20FC77787002A2BE3 /* Debug clang */, F9988AB80D814C7500B6B03B /* Debug llvm-gcc */, F9988AB40D814C6500B6B03B /* Debug gcc40 */, F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */, F99EE73F0BE835310060D4AF /* DebugUnthreaded */, F98751320DE7B57E00B1C9EC /* DebugNoCF */, F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */, F93084390BB93D2800CD0B9E /* DebugMemCompile */, F99EE7400BE835310060D4AF /* DebugLeaks */, F9359B280DF212DA00E04F67 /* DebugGCov */, F97AED1D0B660B2100310EA2 /* Debug64bit */, F97258AA0A86873D00096C78 /* Release */, F97258AC0A86873D00096C78 /* ReleaseUniversal */, F9A9D1F60FC77799002A2BE3 /* ReleaseUniversal clang */, F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */, F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */, F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; /* End XCConfigurationList section */ }; rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; } tcl8.6.5/macosx/Tcl.xcodeproj/default.pbxuser0000644000175000017500000001365112663653132020640 0ustar sergeisergei// !$*UTF8*$! { 08FB7793FE84155DC02AAC07 /* Project object */ = { activeBuildConfigurationName = Debug; activeExecutable = F9E61D1C090A4282002B3151 /* tclsh */; activeTarget = F9E61D16090A3E94002B3151 /* Tcl */; codeSenseManager = F944EB9D08F798180049FDD4 /* Code sense */; executables = ( F9E61D1C090A4282002B3151 /* tclsh */, F944EB8F08F798100049FDD4 /* tcltest */, ); perUserDictionary = { com.apple.ide.smrt.PBXUserSmartGroupsKey.Rev10 = <040b73747265616d747970656481e8038401408484840e4e534d757461626c654172726179008484074e534172726179008484084e534f626a65637400858401690192848484134e534d757461626c6544696374696f6e6172790084840c4e5344696374696f6e6172790095960792848484084e53537472696e67019584012b046e616d658692849a9a14496d706c656d656e746174696f6e2046696c65738692849a9a195042585472616e7369656e744c6f636174696f6e4174546f708692849a9a06626f74746f6d8692849a9a0b707265666572656e63657386928497960892849a9a0669734c6561668692848484084e534e756d626572008484074e5356616c7565009584012a849696008692849a9a04726f6f748692849a9a093c50524f4a4543543e8692849a9a09726563757273697665869284a29da496018692849a9a05696d6167658692849a9a0b536d617274466f6c6465728692849a9a0763616e536176658692a892849a9a1250425850726f6a65637453636f70654b65798692849a9a035945538692849a9a0572656765788692849a9a065c2e286329248692849a9a07666e6d617463688692849a9a00868692849a9a146162736f6c75746550617468546f42756e646c658692849a9a008692849a9a0b6465736372697074696f6e8692849a9a103c6e6f206465736372697074696f6e3e8692849a9a08676c6f62616c49448692849a9a183143433045413430303433353045463930303434343130428692849a9a03636c7a8692849a9a1550425846696c656e616d65536d61727447726f7570868686>; }; sourceControlManager = F944EB9C08F798180049FDD4 /* Source Control */; userBuildSettings = { SYMROOT = "${SRCROOT}/../../build/tcl"; TCL_SRCROOT = "${SRCROOT}/../../tcl"; }; }; 8DD76FA90486AB0100D96B5E /* tcltest */ = { activeExec = 0; executables = ( F944EB8F08F798100049FDD4 /* tcltest */, ); }; F944EB8F08F798100049FDD4 /* tcltest */ = { isa = PBXExecutable; activeArgIndices = ( NO, NO, NO, ); argumentStrings = ( "${TCL_SRCROOT}/tests/all.tcl", "-singleproc 1", "-verbose \"bet\"", ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; displayName = "Executable Runner"; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; "PBXLSLaunchAction-1" = { PBXLSLaunchAction = 1; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXGDB_LaunchConfig; displayName = GDB; identifier = com.apple.Xcode.launch.GDBMI_Config; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 0; environmentEntries = ( { active = YES; name = TCL_LIBRARY; value = "${TCL_SRCROOT}/library"; }, { active = YES; name = TCLLIBPATH; value = /Library/Tcl; }, { active = NO; name = DYLD_PRINT_LIBRARIES; }, { active = NO; name = MallocBadFreeAbort; value = 1; }, { active = NO; name = MallocLogFile; value = /tmp/malloc.log; }, { active = NO; name = MallocStackLogging; value = 1; }, { active = NO; name = MallocStackLoggingNoCompact; value = 1; }, { active = NO; name = MallocPreScribble; value = 1; }, { active = NO; name = MallocScribble; value = 1; }, ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = tcltest; showTypeColumn = 0; sourceDirectories = ( ); }; F944EB9C08F798180049FDD4 /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; repositoryNamesForRoots = { .. = ""; }; scmConfiguration = { CVSToolPath = /usr/bin/cvs; CVSUseSSH = NO; SubversionToolPath = /usr/bin/svn; repositoryNamesForRoots = { .. = ""; }; }; scmType = scm.cvs; }; F944EB9D08F798180049FDD4 /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; F97258A50A86873C00096C78 /* tests */ = { activeExec = 0; }; F9E61D16090A3E94002B3151 /* Tcl */ = { activeExec = 0; executables = ( F9E61D1C090A4282002B3151 /* tclsh */, ); }; F9E61D1C090A4282002B3151 /* tclsh */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; displayName = "Executable Runner"; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; "PBXLSLaunchAction-1" = { PBXLSLaunchAction = 1; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXGDB_LaunchConfig; displayName = GDB; identifier = com.apple.Xcode.launch.GDBMI_Config; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; dataTipCustomDataFormattersEnabled = 1; dataTipShowTypeColumn = 1; dataTipSortType = 0; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = _debug; enableDebugStr = 0; environmentEntries = ( { active = NO; name = DYLD_PRINT_LIBRARIES; }, ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = tclsh; showTypeColumn = 0; sourceDirectories = ( ); }; } tcl8.6.5/macosx/Tcl-Debug.xcconfig0000644000175000017500000000122712663653210016345 0ustar sergeisergei// // Tcl-Debug.xcconfig -- // // This file contains the Xcode build settings for all Debug // project configurations in Tcl.xcodeproj. // // Copyright (c) 2007 Daniel A. Steffen // // See the file "license.terms" for information on usage and redistribution // of this file, and for a DISCLAIMER OF ALL WARRANTIES. #include "Tcl-Common.xcconfig" DEBUG_INFORMATION_FORMAT = dwarf DEAD_CODE_STRIPPING = NO DEPLOYMENT_POSTPROCESSING = NO GCC_OPTIMIZATION_LEVEL = 0 GCC_PREPROCESSOR_DEFINITIONS = $(TCL_DEFS) $(GCC_PREPROCESSOR_DEFINITIONS) CONFIGURE_ARGS = --enable-symbols $(TCL_CONFIGURE_ARGS) $(CONFIGURE_ARGS) MAKE_TARGET = develop tcl8.6.5/macosx/GNUmakefile0000644000175000017500000001625412663660066015144 0ustar sergeisergei######################################################################################################## # # Makefile wrapper to build tcl on Mac OS X in a way compatible with the tk/macosx Xcode buildsystem # uses the standard unix build system in tcl/unix (which can be used directly instead of this # if you are not using the tk/macosx projects). # # Copyright (c) 2002-2008 Daniel A. Steffen # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. ######################################################################################################## #------------------------------------------------------------------------------------------------------- # customizable settings DESTDIR ?= INSTALL_ROOT ?= ${DESTDIR} BUILD_DIR ?= ${CURDIR}/../../build SYMROOT ?= ${BUILD_DIR}/${PROJECT} OBJROOT ?= ${SYMROOT} EXTRA_CONFIGURE_ARGS ?= EXTRA_MAKE_ARGS ?= INSTALL_PATH ?= /Library/Frameworks PREFIX ?= /usr/local BINDIR ?= ${PREFIX}/bin LIBDIR ?= ${INSTALL_PATH} MANDIR ?= ${PREFIX}/man # set to non-empty value to install manpages in addition to html help: INSTALL_MANPAGES ?= #------------------------------------------------------------------------------------------------------- # meta targets meta := all install embedded install-embedded clean distclean test styles := develop deploy all := ${styles} all : ${all} install := ${styles:%=install-%} install : ${install} install-%: action := install- embedded := ${styles:%=embedded-%} embedded : embedded-deploy install-embedded := ${embedded:%=install-%} install-embedded : install-embedded-deploy clean := ${styles:%=clean-%} clean : ${clean} clean-%: action := clean- distclean := ${styles:%=distclean-%} distclean : ${distclean} distclean-%: action := distclean- test := ${styles:%=test-%} test : ${test} test-%: action := test- targets := $(foreach v,${meta},${$v}) #------------------------------------------------------------------------------------------------------- # build styles BUILD_STYLE = CONFIGURE_ARGS = OBJ_DIR = ${OBJROOT}/${BUILD_STYLE} empty := space := ${empty} ${empty} objdir = $(subst ${space},\ ,${OBJ_DIR}) develop_make_args := BUILD_STYLE=Development CONFIGURE_ARGS=--enable-symbols deploy_make_args := BUILD_STYLE=Deployment INSTALL_TARGET=install-strip \ EXTRA_CFLAGS=-DNDEBUG embedded_make_args := EMBEDDED_BUILD=1 install_make_args := INSTALL_BUILD=1 ${targets}: ${MAKE} ${action}${PROJECT} \ $(foreach s,${styles} embedded install,$(if $(findstring $s,$@),${${s}_make_args})) #------------------------------------------------------------------------------------------------------- # project specific settings PROJECT := tcl PRODUCT_NAME := Tcl UNIX_DIR := ${CURDIR}/../unix VERSION := $(shell awk -F= '/^TCL_VERSION/ {print $$2; nextfile}' ${UNIX_DIR}/configure.in) TCLSH := tclsh${VERSION} BUILD_TARGET := all tcltest INSTALL_TARGET := install export CPPROG := cp -p INSTALL_TARGETS = install-binaries install-headers install-libraries ifeq (${EMBEDDED_BUILD},) INSTALL_TARGETS += install-private-headers endif ifeq (${INSTALL_BUILD}_${EMBEDDED_BUILD}_${BUILD_STYLE},1__Deployment) INSTALL_TARGETS += install-packages html-tcl ifneq (${INSTALL_MANPAGES},) INSTALL_TARGETS += install-doc endif endif MAKE_VARS := INSTALL_ROOT INSTALL_TARGETS VERSION GENERIC_FLAGS MAKE_ARGS_V = $(foreach v,${MAKE_VARS},$v='${$v}') build-${PROJECT}: target = ${BUILD_TARGET} install-${PROJECT}: target = ${INSTALL_TARGET} clean-${PROJECT} distclean-${PROJECT} test-${PROJECT}: \ target = $* DO_MAKE = +${MAKE} -C "${OBJ_DIR}" ${target} ${MAKE_ARGS_V} ${MAKE_ARGS} ${EXTRA_MAKE_ARGS} #------------------------------------------------------------------------------------------------------- # build rules ${PROJECT}: ${MAKE} install-${PROJECT} INSTALL_ROOT="${OBJ_DIR}/" ${objdir}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure \ ${UNIX_DIR}/tclConfig.sh.in Tcl-Info.plist.in mkdir -p "${OBJ_DIR}" && cd "${OBJ_DIR}" && \ if [ ${UNIX_DIR}/configure -nt config.status ]; then ${UNIX_DIR}/configure -C \ --prefix="${PREFIX}" --bindir="${BINDIR}" --libdir="${LIBDIR}" \ --mandir="${MANDIR}" --enable-threads --enable-framework --enable-dtrace \ ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}; else ./config.status; fi build-${PROJECT}: ${objdir}/Makefile ${DO_MAKE} ifeq (${INSTALL_BUILD},) # symolic link hackery to trick # 'make install INSTALL_ROOT=${OBJ_DIR}' # into building Tcl.framework and tclsh in ${SYMROOT} @cd "${OBJ_DIR}" && mkdir -p $(dir $(subst ${space},\ ,./${LIBDIR})) $(dir $(subst ${space},\ ,./${BINDIR})) "${SYMROOT}" && \ rm -f "./${LIBDIR}" "./${BINDIR}" && ln -fs "${SYMROOT}" "./${LIBDIR}" && \ ln -fs "${SYMROOT}" "./${BINDIR}" && ln -fs "${OBJ_DIR}/tcltest" "${SYMROOT}" endif install-${PROJECT}: build-${PROJECT} ifeq (${EMBEDDED_BUILD}_${INSTALL_ROOT},1_) @echo "Cannot install-embedded with empty INSTALL_ROOT !" && false endif ifeq (${EMBEDDED_BUILD},1) @rm -rf "${INSTALL_ROOT}/${LIBDIR}/Tcl.framework" endif ${DO_MAKE} ifeq (${INSTALL_BUILD},1) ifeq (${EMBEDDED_BUILD},1) # if we are embedding frameworks, don't install tclsh @rm -f "${INSTALL_ROOT}${BINDIR}/${TCLSH}" && \ rmdir -p "${INSTALL_ROOT}${BINDIR}" 2>&- || true else # redo prebinding (when not building for Mac OS X 10.4 or later only) @if [ "`echo "$${MACOSX_DEPLOYMENT_TARGET}" | \ awk -F '10\\.' '{print int($$2)}'`" -lt 4 -a "`echo "$${CFLAGS}" | \ awk -F '-mmacosx-version-min=10\\.' '{print int($$2)}'`" -lt 4 ]; \ then cd ${INSTALL_ROOT}/; \ if [ ! -d usr/lib ]; then mkdir -p usr && ln -fs /usr/lib usr/ && RM_USRLIB=1; fi; \ if [ ! -d System ]; then ln -fs /System . && RM_SYSTEM=1; fi; \ redo_prebinding -r . "./${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}/${PRODUCT_NAME}"; \ redo_prebinding -r . "./${BINDIR}/${TCLSH}"; \ if [ -n "$${RM_USRLIB:-}" ]; then rm -f usr/lib; rmdir -p usr 2>&-; fi; \ if [ -n "$${RM_SYSTEM:-}" ]; then rm -f System; fi; fi # install tclsh symbolic link @ln -fs ${TCLSH} "${INSTALL_ROOT}${BINDIR}/tclsh" endif endif ifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_) # keep copy of debug library around, so that # Deployment build can be installed on top # of Development build without overwriting # the debug library @cd "${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}" && \ ln -f "${PRODUCT_NAME}" "${PRODUCT_NAME}_debug" endif clean-${PROJECT}: %-${PROJECT}: ${DO_MAKE} rm -rf "${SYMROOT}"/{${PRODUCT_NAME}.framework,${TCLSH},tcltest} rm -f "${OBJ_DIR}"{"${LIBDIR}","${BINDIR}"} && \ rmdir -p "${OBJ_DIR}"$(dir $(subst ${space},\ ,${LIBDIR})) 2>&- || true && \ rmdir -p "${OBJ_DIR}"$(dir $(subst ${space},\ ,${BINDIR})) 2>&- || true distclean-${PROJECT}: %-${PROJECT}: clean-${PROJECT} ${DO_MAKE} rm -rf "${OBJ_DIR}" test-${PROJECT}: %-${PROJECT}: build-${PROJECT} ${DO_MAKE} #------------------------------------------------------------------------------------------------------- .PHONY: ${meta} ${targets} ${PROJECT} build-${PROJECT} install-${PROJECT} \ clean-${PROJECT} distclean-${PROJECT} .NOTPARALLEL: #------------------------------------------------------------------------------------------------------- tcl8.6.5/macosx/Tclsh-Info.plist.in0000644000175000017500000000235412663653210016507 0ustar sergeisergei CFBundleDevelopmentRegion English CFBundleExecutable tclsh@TCL_VERSION@ CFBundleGetInfoString Tcl Shell @TCL_VERSION@@TCL_PATCH_LEVEL@, Copyright © 1987-@TCL_YEAR@ Tcl Core Team, Copyright © 2001-@TCL_YEAR@ Daniel A. Steffen, Copyright © 2001-2009 Apple Inc., Copyright © 2001-2002 Jim Ingham & Ian Reid CFBundleIdentifier com.tcltk.tclsh CFBundleInfoDictionaryVersion 6.0 CFBundleName tclsh CFBundlePackageType APPL CFBundleShortVersionString @TCL_VERSION@@TCL_PATCH_LEVEL@ CFBundleSignature TclS CFBundleVersion @TCL_VERSION@@TCL_PATCH_LEVEL@ tcl8.6.5/macosx/tclMacOSXBundle.c0000644000175000017500000001724412663653210016156 0ustar sergeisergei/* * tclMacOSXBundle.c -- * * This file implements functions that inspect CFBundle structures on * MacOS X. * * Copyright 2001-2009, Apple Inc. * Copyright (c) 2003-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclPort.h" #ifdef HAVE_COREFOUNDATION #include #ifndef TCL_DYLD_USE_DLFCN /* * Use preferred dlfcn API on 10.4 and later */ # if !defined(NO_DLFCN_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 # define TCL_DYLD_USE_DLFCN 1 # else # define TCL_DYLD_USE_DLFCN 0 # endif #endif /* TCL_DYLD_USE_DLFCN */ #ifndef TCL_DYLD_USE_NSMODULE /* * Use deprecated NSModule API only to support 10.3 and earlier: */ # if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 # define TCL_DYLD_USE_NSMODULE 1 # else # define TCL_DYLD_USE_NSMODULE 0 # endif #endif /* TCL_DYLD_USE_NSMODULE */ #if TCL_DYLD_USE_DLFCN #include #if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040 /* * Support for weakly importing dlfcn API. */ extern void * dlsym(void *handle, const char *symbol) WEAK_IMPORT_ATTRIBUTE; extern char * dlerror(void) WEAK_IMPORT_ATTRIBUTE; #endif #endif /* TCL_DYLD_USE_DLFCN */ #if TCL_DYLD_USE_NSMODULE #include #endif #if (TCL_DYLD_USE_DLFCN && MAC_OS_X_VERSION_MIN_REQUIRED < 1040) || \ (MAC_OS_X_VERSION_MIN_REQUIRED < 1050) MODULE_SCOPE long tclMacOSXDarwinRelease; #endif #ifdef TCL_DEBUG_LOAD #define TclLoadDbgMsg(m, ...) \ do { \ fprintf(stderr, "%s:%d: %s(): " m ".\n", \ strrchr(__FILE__, '/')+1, __LINE__, __func__, \ ##__VA_ARGS__); \ } while (0) #else #define TclLoadDbgMsg(m, ...) #endif /* TCL_DEBUG_LOAD */ /* * Forward declaration of functions defined in this file: */ static short OpenResourceMap(CFBundleRef bundleRef); #endif /* HAVE_COREFOUNDATION */ /* *---------------------------------------------------------------------- * * OpenResourceMap -- * * Wrapper that dynamically acquires the address for the function * CFBundleOpenBundleResourceMap before calling it, since it is only * present in full CoreFoundation on Mac OS X and not in CFLite on pure * Darwin. Factored out because it is moderately ugly code. * *---------------------------------------------------------------------- */ #ifdef HAVE_COREFOUNDATION static short OpenResourceMap( CFBundleRef bundleRef) { static int initialized = FALSE; static short (*openresourcemap)(CFBundleRef) = NULL; if (!initialized) { #if TCL_DYLD_USE_DLFCN #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 if (tclMacOSXDarwinRelease >= 8) #endif { openresourcemap = dlsym(RTLD_NEXT, "CFBundleOpenBundleResourceMap"); #ifdef TCL_DEBUG_LOAD if (!openresourcemap) { const char *errMsg = dlerror(); TclLoadDbgMsg("dlsym() failed: %s", errMsg); } #endif /* TCL_DEBUG_LOAD */ } if (!openresourcemap) #endif /* TCL_DYLD_USE_DLFCN */ { #if TCL_DYLD_USE_NSMODULE if (NSIsSymbolNameDefinedWithHint( "_CFBundleOpenBundleResourceMap", "CoreFoundation")) { NSSymbol nsSymbol = NSLookupAndBindSymbolWithHint( "_CFBundleOpenBundleResourceMap", "CoreFoundation"); if (nsSymbol) { openresourcemap = NSAddressOfSymbol(nsSymbol); } } #endif /* TCL_DYLD_USE_NSMODULE */ } initialized = TRUE; } if (openresourcemap) { return openresourcemap(bundleRef); } return -1; } #endif /* HAVE_COREFOUNDATION */ /* *---------------------------------------------------------------------- * * Tcl_MacOSXOpenBundleResources -- * * Given the bundle name for a shared library, this routine sets * libraryPath to the Resources/Scripts directory in the framework * package. If hasResourceFile is true, it will also open the main * resource file for the bundle. * * Results: * TCL_OK if the bundle could be opened, and the Scripts folder found. * TCL_ERROR otherwise. * * Side effects: * libraryVariableName may be set, and the resource file opened. * *---------------------------------------------------------------------- */ int Tcl_MacOSXOpenBundleResources( Tcl_Interp *interp, const char *bundleName, int hasResourceFile, int maxPathLen, char *libraryPath) { return Tcl_MacOSXOpenVersionedBundleResources(interp, bundleName, NULL, hasResourceFile, maxPathLen, libraryPath); } /* *---------------------------------------------------------------------- * * Tcl_MacOSXOpenVersionedBundleResources -- * * Given the bundle and version name for a shared library (version name * can be NULL to indicate latest version), this routine sets libraryPath * to the Resources/Scripts directory in the framework package. If * hasResourceFile is true, it will also open the main resource file for * the bundle. * * Results: * TCL_OK if the bundle could be opened, and the Scripts folder found. * TCL_ERROR otherwise. * * Side effects: * libraryVariableName may be set, and the resource file opened. * *---------------------------------------------------------------------- */ int Tcl_MacOSXOpenVersionedBundleResources( Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, int maxPathLen, char *libraryPath) { #ifdef HAVE_COREFOUNDATION CFBundleRef bundleRef, versionedBundleRef = NULL; CFStringRef bundleNameRef; CFURLRef libURL; libraryPath[0] = '\0'; bundleNameRef = CFStringCreateWithCString(NULL, bundleName, kCFStringEncodingUTF8); bundleRef = CFBundleGetBundleWithIdentifier(bundleNameRef); CFRelease(bundleNameRef); if (bundleVersion && bundleRef) { /* * Create bundle from bundleVersion subdirectory of 'Versions'. */ CFURLRef bundleURL = CFBundleCopyBundleURL(bundleRef); if (bundleURL) { CFStringRef bundleVersionRef = CFStringCreateWithCString(NULL, bundleVersion, kCFStringEncodingUTF8); if (bundleVersionRef) { CFComparisonResult versionComparison = kCFCompareLessThan; CFStringRef bundleTailRef = CFURLCopyLastPathComponent( bundleURL); if (bundleTailRef) { versionComparison = CFStringCompare(bundleTailRef, bundleVersionRef, 0); CFRelease(bundleTailRef); } if (versionComparison != kCFCompareEqualTo) { CFURLRef versURL = CFURLCreateCopyAppendingPathComponent( NULL, bundleURL, CFSTR("Versions"), TRUE); if (versURL) { CFURLRef versionedBundleURL = CFURLCreateCopyAppendingPathComponent( NULL, versURL, bundleVersionRef, TRUE); if (versionedBundleURL) { versionedBundleRef = CFBundleCreate(NULL, versionedBundleURL); if (versionedBundleRef) { bundleRef = versionedBundleRef; } CFRelease(versionedBundleURL); } CFRelease(versURL); } } CFRelease(bundleVersionRef); } CFRelease(bundleURL); } } if (bundleRef) { if (hasResourceFile) { (void) OpenResourceMap(bundleRef); } libURL = CFBundleCopyResourceURL(bundleRef, CFSTR("Scripts"), NULL, NULL); if (libURL) { /* * FIXME: This is a quick fix, it is probably not right for * internationalization. */ CFURLGetFileSystemRepresentation(libURL, TRUE, (unsigned char *) libraryPath, maxPathLen); CFRelease(libURL); } if (versionedBundleRef) { #if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 /* * Workaround CFBundle bug in Tiger and earlier. [Bug 2569449] */ if (tclMacOSXDarwinRelease >= 9) #endif { CFRelease(versionedBundleRef); } } } if (libraryPath[0]) { return TCL_OK; } #endif /* HAVE_COREFOUNDATION */ return TCL_ERROR; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/macosx/license.terms0000644000175000017500000000431712663660066015565 0ustar sergeisergeiThis software is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. tcl8.6.5/macosx/configure0000755000175000017500000115574012665171167015007 0ustar sergeisergei#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for tcl 8.6. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='tcl' PACKAGE_TARNAME='tcl' PACKAGE_VERSION='8.6' PACKAGE_STRING='tcl 8.6' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='DLTEST_SUFFIX DLTEST_LD EXTRA_TCLSH_LIBS EXTRA_BUILD_HTML EXTRA_INSTALL_BINARIES EXTRA_INSTALL EXTRA_APP_CC_SWITCHES EXTRA_CC_SWITCHES PACKAGE_DIR HTML_DIR PRIVATE_INCLUDE_DIR TCL_LIBRARY TCL_MODULE_PATH TCL_PACKAGE_PATH BUILD_DLTEST MAKEFILE_SHELL DTRACE_OBJ DTRACE_HDR DTRACE_SRC INSTALL_TZDATA TCL_HAS_LONGLONG TCL_UNSHARED_LIB_SUFFIX TCL_SHARED_LIB_SUFFIX TCL_LIB_VERSIONS_OK TCL_BUILD_LIB_SPEC LD_LIBRARY_PATH_VAR TCL_SHARED_BUILD CFG_TCL_UNSHARED_LIB_SUFFIX CFG_TCL_SHARED_LIB_SUFFIX TCL_SRC_DIR TCL_BUILD_STUB_LIB_PATH TCL_BUILD_STUB_LIB_SPEC TCL_INCLUDE_SPEC TCL_STUB_LIB_PATH TCL_STUB_LIB_SPEC TCL_STUB_LIB_FLAG TCL_STUB_LIB_FILE TCL_LIB_SPEC TCL_LIB_FLAG TCL_LIB_FILE PKG_CFG_ARGS TCL_YEAR TCL_PATCH_LEVEL TCL_MINOR_VERSION TCL_MAJOR_VERSION TCL_VERSION DTRACE LDFLAGS_DEFAULT CFLAGS_DEFAULT INSTALL_STUB_LIB DLL_INSTALL_DIR INSTALL_LIB MAKE_STUB_LIB MAKE_LIB SHLIB_SUFFIX SHLIB_CFLAGS SHLIB_LD_LIBS TK_SHLIB_LD_EXTRAS TCL_SHLIB_LD_EXTRAS SHLIB_LD STLIB_LD LD_SEARCH_FLAGS CC_SEARCH_FLAGS LDFLAGS_OPTIMIZE LDFLAGS_DEBUG CFLAGS_WARNING CFLAGS_OPTIMIZE CFLAGS_DEBUG LDAIX_SRC PLAT_SRCS PLAT_OBJS DL_OBJS DL_LIBS TCL_LIBS LIBOBJS AR RANLIB ZLIB_INCLUDE ZLIB_SRCS ZLIB_OBJS TCLSH_PROG TCL_THREADS EGREP GREP CPP OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC MAN_FLAGS target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_man_symlinks enable_man_compression enable_man_suffix enable_threads with_encoding enable_shared enable_64bit enable_64bit_vis enable_rpath enable_corefoundation enable_load enable_symbols enable_langinfo enable_dll_unloading with_tzdata enable_dtrace enable_framework ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures tcl 8.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/tcl] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of tcl 8.6:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-man-symlinks use symlinks for the manpages (default: off) --enable-man-compression=PROG compress the manpages with PROG (default: off) --enable-man-suffix=STRING use STRING as a suffix to manpage file names (default: no, tcl if enabled without specifying STRING) --enable-threads build with threads (default: on) --enable-shared build and link with shared libraries (default: on) --enable-64bit enable 64bit support (default: off) --enable-64bit-vis enable 64bit Sparc VIS support (default: off) --disable-rpath disable rpath support (default: on) --enable-corefoundation use CoreFoundation API on MacOSX (default: on) --enable-load allow dynamic loading and "load" command (default: on) --enable-symbols build with debugging symbols (default: off) --enable-langinfo use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on) --enable-dll-unloading enable the 'unload' command (default: on) --enable-dtrace build with DTrace support (default: off) --enable-framework package shared libraries in MacOSX frameworks (default: off) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-encoding encoding for configuration values (default: iso8859-1) --with-tzdata install timezone data (default: autodetect) Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF tcl configure 8.6 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by tcl $as_me 8.6, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers tclConfig.h:../unix/tclConfig.h.in" TCL_VERSION=8.6 TCL_MAJOR_VERSION=8 TCL_MINOR_VERSION=6 TCL_PATCH_LEVEL=".5" VERSION=${TCL_VERSION} EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"} EXTRA_BUILD_HTML=${EXTRA_BUILD_HTML:-"@:"} #------------------------------------------------------------------------ # Setup configure arguments for bundled packages #------------------------------------------------------------------------ PKG_CFG_ARGS="$ac_configure_args ${PKG_CFG_ARGS}" if test -r "$cache_file" -a -f "$cache_file"; then case $cache_file in [\\/]* | ?:[\\/]* ) pkg_cache_file=$cache_file ;; *) pkg_cache_file=../../$cache_file ;; esac PKG_CFG_ARGS="${PKG_CFG_ARGS} --cache-file=$pkg_cache_file" fi #------------------------------------------------------------------------ # Empty slate for bundled packages, to avoid stale configuration #------------------------------------------------------------------------ #rm -Rf pkgs if test -f Makefile; then make distclean-packages fi #------------------------------------------------------------------------ # Handle the --prefix=... option #------------------------------------------------------------------------ if test "${prefix}" = "NONE"; then prefix=/usr/local fi if test "${exec_prefix}" = "NONE"; then exec_prefix=$prefix fi # Make sure srcdir is fully qualified! srcdir="`cd "$srcdir" ; pwd`" TCL_SRC_DIR="`cd "$srcdir"/..; pwd`" #------------------------------------------------------------------------ # Compress and/or soft link the manpages? #------------------------------------------------------------------------ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use symlinks for manpages" >&5 $as_echo_n "checking whether to use symlinks for manpages... " >&6; } # Check whether --enable-man-symlinks was given. if test "${enable_man_symlinks+set}" = set; then : enableval=$enable_man_symlinks; test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks" else enableval="no" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5 $as_echo "$enableval" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to compress the manpages" >&5 $as_echo_n "checking whether to compress the manpages... " >&6; } # Check whether --enable-man-compression was given. if test "${enable_man_compression+set}" = set; then : enableval=$enable_man_compression; case $enableval in yes) as_fn_error $? "missing argument to --enable-man-compression" "$LINENO" 5;; no) ;; *) MAN_FLAGS="$MAN_FLAGS --compress $enableval";; esac else enableval="no" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5 $as_echo "$enableval" >&6; } if test "$enableval" != "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compressed file suffix" >&5 $as_echo_n "checking for compressed file suffix... " >&6; } touch TeST $enableval TeST Z=`ls TeST* | sed 's/^....//'` rm -f TeST* MAN_FLAGS="$MAN_FLAGS --extension $Z" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $Z" >&5 $as_echo "$Z" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to add a package name suffix for the manpages" >&5 $as_echo_n "checking whether to add a package name suffix for the manpages... " >&6; } # Check whether --enable-man-suffix was given. if test "${enable_man_suffix+set}" = set; then : enableval=$enable_man_suffix; case $enableval in yes) enableval="tcl" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";; no) ;; *) MAN_FLAGS="$MAN_FLAGS --suffix $enableval";; esac else enableval="no" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5 $as_echo "$enableval" >&6; } #------------------------------------------------------------------------ # Standard compiler checks #------------------------------------------------------------------------ # If the user did not set CFLAGS, set it now to keep # the AC_PROG_CC macro from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac #-------------------------------------------------------------------- # Supply substitutes for missing POSIX header files. Special notes: # - stdlib.h doesn't define strtol, strtoul, or # strtod insome versions of SunOS # - some versions of string.h don't declare procedures such # as strstr # Do this early, otherwise an autoconf bug throws errors on configure #-------------------------------------------------------------------- ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking dirent.h" >&5 $as_echo_n "checking dirent.h... " >&6; } if ${tcl_cv_dirent_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #ifndef _POSIX_SOURCE # ifdef __Lynx__ /* * Generate compilation error to make the test fail: Lynx headers * are only valid if really in the POSIX environment. */ missing_procedure(); # endif #endif DIR *d; struct dirent *entryPtr; char *p; d = opendir("foobar"); entryPtr = readdir(d); p = entryPtr->d_name; closedir(d); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_dirent_h=yes else tcl_cv_dirent_h=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_dirent_h" >&5 $as_echo "$tcl_cv_dirent_h" >&6; } if test $tcl_cv_dirent_h = no; then $as_echo "#define NO_DIRENT_H 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "float.h" "ac_cv_header_float_h" "$ac_includes_default" if test "x$ac_cv_header_float_h" = xyes; then : else $as_echo "#define NO_FLOAT_H 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "values.h" "ac_cv_header_values_h" "$ac_includes_default" if test "x$ac_cv_header_values_h" = xyes; then : else $as_echo "#define NO_VALUES_H 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : tcl_ok=1 else tcl_ok=0 fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strtol" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strtoul" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strtod" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* if test $tcl_ok = 0; then $as_echo "#define NO_STDLIB_H 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" if test "x$ac_cv_header_string_h" = xyes; then : tcl_ok=1 else tcl_ok=0 fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strstr" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "strerror" >/dev/null 2>&1; then : else tcl_ok=0 fi rm -f conftest* # See also memmove check below for a place where NO_STRING_H can be # set and why. if test $tcl_ok = 0; then $as_echo "#define NO_STRING_H 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "sys/wait.h" "ac_cv_header_sys_wait_h" "$ac_includes_default" if test "x$ac_cv_header_sys_wait_h" = xyes; then : else $as_echo "#define NO_SYS_WAIT_H 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" if test "x$ac_cv_header_dlfcn_h" = xyes; then : else $as_echo "#define NO_DLFCN_H 1" >>confdefs.h fi # OS/390 lacks sys/param.h (and doesn't need it, by chance). for ac_header in sys/param.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default" if test "x$ac_cv_header_sys_param_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_PARAM_H 1 _ACEOF fi done #-------------------------------------------------------------------- # Determines the correct executable file extension (.exe) #-------------------------------------------------------------------- #------------------------------------------------------------------------ # If we're using GCC, see if the compiler understands -pipe. If so, use it. # It makes compiling go faster. (This is only a performance feature.) #------------------------------------------------------------------------ if test -z "$no_pipe" && test -n "$GCC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5 $as_echo_n "checking if the compiler understands -pipe... " >&6; } if ${tcl_cv_cc_pipe+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_cc_pipe=yes else tcl_cv_cc_pipe=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5 $as_echo "$tcl_cv_cc_pipe" >&6; } if test $tcl_cv_cc_pipe = yes; then CFLAGS="$CFLAGS -pipe" fi fi #------------------------------------------------------------------------ # Threads support #------------------------------------------------------------------------ # Check whether --enable-threads was given. if test "${enable_threads+set}" = set; then : enableval=$enable_threads; tcl_ok=$enableval else tcl_ok=yes fi if test "${TCL_THREADS}" = 1; then tcl_threaded_core=1; fi if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then TCL_THREADS=1 # USE_THREAD_ALLOC tells us to try the special thread-based # allocator that significantly reduces lock contention $as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h $as_echo "#define _REENTRANT 1" >>confdefs.h if test "`uname -s`" = "SunOS" ; then $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h fi $as_echo "#define _THREAD_SAFE 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 $as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; } if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_pthread_mutex_init=yes else ac_cv_lib_pthread_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "no"; then # Check a little harder for __pthread_mutex_init in the same # library, as some systems hide it there until pthread.h is # defined. We could alternatively do an AC_TRY_COMPILE with # pthread.h, but that will work with libpthread really doesn't # exist, like AIX 4.2. [Bug: 4359] { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5 $as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; } if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char __pthread_mutex_init (); int main () { return __pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread___pthread_mutex_init=yes else ac_cv_lib_pthread___pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthread" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5 $as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; } if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthreads $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthreads_pthread_mutex_init=yes else ac_cv_lib_pthreads_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthreads" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5 $as_echo_n "checking for pthread_mutex_init in -lc... " >&6; } if ${ac_cv_lib_c_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_pthread_mutex_init=yes else ac_cv_lib_c_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5 $as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; } if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc_r $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_r_pthread_mutex_init=yes else ac_cv_lib_c_r_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -pthread" else TCL_THREADS=0 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&5 $as_echo "$as_me: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&2;} fi fi fi fi # Does the pthread-implementation provide # 'pthread_attr_setstacksize' ? ac_saved_libs=$LIBS LIBS="$LIBS $THREADS_LIBS" for ac_func in pthread_attr_setstacksize pthread_atfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done LIBS=$ac_saved_libs else TCL_THREADS=0 fi # Do checking message here to not mess up interleaved configure output { $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5 $as_echo_n "checking for building with threads... " >&6; } if test "${TCL_THREADS}" = 1; then $as_echo "#define TCL_THREADS 1" >>confdefs.h if test "${tcl_threaded_core}" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (threaded core)" >&5 $as_echo "yes (threaded core)" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi #------------------------------------------------------------------------ # Embedded configuration information, encoding to use for the values, TIP #59 #------------------------------------------------------------------------ # Check whether --with-encoding was given. if test "${with_encoding+set}" = set; then : withval=$with_encoding; with_tcencoding=${withval} fi if test x"${with_tcencoding}" != x ; then cat >>confdefs.h <<_ACEOF #define TCL_CFGVAL_ENCODING "${with_tcencoding}" _ACEOF else $as_echo "#define TCL_CFGVAL_ENCODING \"iso8859-1\"" >>confdefs.h fi #-------------------------------------------------------------------- # Look for libraries that we will need when compiling the Tcl shell #-------------------------------------------------------------------- #-------------------------------------------------------------------- # On a few very rare systems, all of the libm.a stuff is # already in libc.a. Set compiler flags accordingly. # Also, Linux requires the "ieee" library for math to work # right (and it must appear before "-lm"). #-------------------------------------------------------------------- ac_fn_c_check_func "$LINENO" "sin" "ac_cv_func_sin" if test "x$ac_cv_func_sin" = xyes; then : MATH_LIBS="" else MATH_LIBS="-lm" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lieee" >&5 $as_echo_n "checking for main in -lieee... " >&6; } if ${ac_cv_lib_ieee_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lieee $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ieee_main=yes else ac_cv_lib_ieee_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ieee_main" >&5 $as_echo "$ac_cv_lib_ieee_main" >&6; } if test "x$ac_cv_lib_ieee_main" = xyes; then : MATH_LIBS="-lieee $MATH_LIBS" fi #-------------------------------------------------------------------- # Interactive UNIX requires -linet instead of -lsocket, plus it # needs net/errno.h to define the socket-related error codes. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5 $as_echo_n "checking for main in -linet... " >&6; } if ${ac_cv_lib_inet_main+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-linet $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_inet_main=yes else ac_cv_lib_inet_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main" >&5 $as_echo "$ac_cv_lib_inet_main" >&6; } if test "x$ac_cv_lib_inet_main" = xyes; then : LIBS="$LIBS -linet" fi ac_fn_c_check_header_mongrel "$LINENO" "net/errno.h" "ac_cv_header_net_errno_h" "$ac_includes_default" if test "x$ac_cv_header_net_errno_h" = xyes; then : $as_echo "#define HAVE_NET_ERRNO_H 1" >>confdefs.h fi #-------------------------------------------------------------------- # Check for the existence of the -lsocket and -lnsl libraries. # The order here is important, so that they end up in the right # order in the command line generated by make. Here are some # special considerations: # 1. Use "connect" and "accept" to check for -lsocket, and # "gethostbyname" to check for -lnsl. # 2. Use each function name only once: can't redo a check because # autoconf caches the results of the last check and won't redo it. # 3. Use -lnsl and -lsocket only if they supply procedures that # aren't already present in the normal libraries. This is because # IRIX 5.2 has libraries, but they aren't needed and they're # bogus: they goof up name resolution if used. # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. # To get around this problem, check for both libraries together # if -lsocket doesn't work by itself. #-------------------------------------------------------------------- tcl_checkBoth=0 ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" if test "x$ac_cv_func_connect" = xyes; then : tcl_checkSocket=0 else tcl_checkSocket=1 fi if test "$tcl_checkSocket" = 1; then ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt" if test "x$ac_cv_func_setsockopt" = xyes; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5 $as_echo_n "checking for setsockopt in -lsocket... " >&6; } if ${ac_cv_lib_socket_setsockopt+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char setsockopt (); int main () { return setsockopt (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_setsockopt=yes else ac_cv_lib_socket_setsockopt=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5 $as_echo "$ac_cv_lib_socket_setsockopt" >&6; } if test "x$ac_cv_lib_socket_setsockopt" = xyes; then : LIBS="$LIBS -lsocket" else tcl_checkBoth=1 fi fi fi if test "$tcl_checkBoth" = 1; then tk_oldLibs=$LIBS LIBS="$LIBS -lsocket -lnsl" ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept" if test "x$ac_cv_func_accept" = xyes; then : tcl_checkNsl=0 else LIBS=$tk_oldLibs fi fi ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" if test "x$ac_cv_func_gethostbyname" = xyes; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 $as_echo_n "checking for gethostbyname in -lnsl... " >&6; } if ${ac_cv_lib_nsl_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nsl_gethostbyname=yes else ac_cv_lib_nsl_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 $as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : LIBS="$LIBS -lnsl" fi fi # Add the threads support libraries LIBS="$LIBS$THREADS_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5 $as_echo_n "checking how to build libraries... " >&6; } # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; tcl_ok=$enableval else tcl_ok=yes fi if test "${enable_shared+set}" = set; then enableval="$enable_shared" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5 $as_echo "shared" >&6; } SHARED_BUILD=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5 $as_echo "static" >&6; } SHARED_BUILD=0 $as_echo "#define STATIC_BUILD 1" >>confdefs.h fi #-------------------------------------------------------------------- # Look for a native installed tclsh binary (if available) # If one cannot be found then use the binary we build (fails for # cross compiling). This is used for NATIVE_TCLSH in Makefile. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 $as_echo_n "checking for tclsh... " >&6; } if ${ac_cv_path_tclsh+:} false; then : $as_echo_n "(cached) " >&6 else search_path=`echo ${PATH} | sed -e 's/:/ /g'` for dir in $search_path ; do for j in `ls -r $dir/tclsh[8-9]* 2> /dev/null` \ `ls -r $dir/tclsh* 2> /dev/null` ; do if test x"$ac_cv_path_tclsh" = x ; then if test -f "$j" ; then ac_cv_path_tclsh=$j break fi fi done done fi if test -f "$ac_cv_path_tclsh" ; then TCLSH_PROG="$ac_cv_path_tclsh" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TCLSH_PROG" >&5 $as_echo "$TCLSH_PROG" >&6; } else # It is not an error if an installed version of Tcl can't be located. TCLSH_PROG="" { $as_echo "$as_me:${as_lineno-$LINENO}: result: No tclsh found on PATH" >&5 $as_echo "No tclsh found on PATH" >&6; } fi if test "$TCLSH_PROG" = ""; then TCLSH_PROG='./${TCL_EXE}' fi #------------------------------------------------------------------------ # Add stuff for zlib #------------------------------------------------------------------------ zlib_ok=yes ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : ac_fn_c_check_type "$LINENO" "gz_header" "ac_cv_type_gz_header" "#include " if test "x$ac_cv_type_gz_header" = xyes; then : else zlib_ok=no fi else zlib_ok=no fi if test $zlib_ok = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflateSetHeader" >&5 $as_echo_n "checking for library containing deflateSetHeader... " >&6; } if ${ac_cv_search_deflateSetHeader+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char deflateSetHeader (); int main () { return deflateSetHeader (); ; return 0; } _ACEOF for ac_lib in '' z; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_deflateSetHeader=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_deflateSetHeader+:} false; then : break fi done if ${ac_cv_search_deflateSetHeader+:} false; then : else ac_cv_search_deflateSetHeader=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflateSetHeader" >&5 $as_echo "$ac_cv_search_deflateSetHeader" >&6; } ac_res=$ac_cv_search_deflateSetHeader if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else zlib_ok=no fi fi if test $zlib_ok = no; then : ZLIB_OBJS=\${ZLIB_OBJS} ZLIB_SRCS=\${ZLIB_SRCS} ZLIB_INCLUDE=-I\${ZLIB_DIR} fi $as_echo "#define HAVE_ZLIB 1" >>confdefs.h #-------------------------------------------------------------------- # The statements below define a collection of compile flags. This # macro depends on the value of SHARED_BUILD, and should be called # after SC_ENABLE_SHARED checks the configure switches. #-------------------------------------------------------------------- if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi # Step 0.a: Enable 64 bit support? { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5 $as_echo_n "checking if 64bit support is requested... " >&6; } # Check whether --enable-64bit was given. if test "${enable_64bit+set}" = set; then : enableval=$enable_64bit; do64bit=$enableval else do64bit=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5 $as_echo "$do64bit" >&6; } # Step 0.b: Enable Solaris 64 bit VIS support? { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5 $as_echo_n "checking if 64bit Sparc VIS support is requested... " >&6; } # Check whether --enable-64bit-vis was given. if test "${enable_64bit_vis+set}" = set; then : enableval=$enable_64bit_vis; do64bitVIS=$enableval else do64bitVIS=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5 $as_echo "$do64bitVIS" >&6; } # Force 64bit on with VIS if test "$do64bitVIS" = "yes"; then : do64bit=yes fi # Step 0.c: Check if visibility support is available. Do this here so # that platform specific alternatives can be used below if this fails. { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5 $as_echo_n "checking if compiler supports visibility \"hidden\"... " >&6; } if ${tcl_cv_cc_visibility_hidden+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ extern __attribute__((__visibility__("hidden"))) void f(void); void f(void) {} int main () { f(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_visibility_hidden=yes else tcl_cv_cc_visibility_hidden=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5 $as_echo "$tcl_cv_cc_visibility_hidden" >&6; } if test $tcl_cv_cc_visibility_hidden = yes; then : $as_echo "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h $as_echo "#define HAVE_HIDDEN 1" >>confdefs.h fi # Step 0.d: Disable -rpath support? { $as_echo "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5 $as_echo_n "checking if rpath support is requested... " >&6; } # Check whether --enable-rpath was given. if test "${enable_rpath+set}" = set; then : enableval=$enable_rpath; doRpath=$enableval else doRpath=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5 $as_echo "$doRpath" >&6; } # Step 1: set the variable "system" to hold the name and version number # for the system. { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5 $as_echo_n "checking system version... " >&6; } if ${tcl_cv_sys_version+:} false; then : $as_echo_n "(cached) " >&6 else if test -f /usr/lib/NextStep/software_version; then tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 $as_echo "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else # Special check for weird MP-RAS system (uname returns weird # results, and the version is kept in special file). if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then tcl_cv_sys_version=MP-RAS-`awk '{print $3}' /etc/.relid` fi if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 $as_echo "$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version # Step 2: check for existence of -ldl library. This is needed because # Linux can use either -ldl or -ldld for dynamic loading. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : have_dl=yes else have_dl=no fi # Require ranlib early so we can override it in special cases below. # Step 3: set configuration options based on system name and version. do64bit_ok=no # default to '{$LIBS}' and set to "" on per-platform necessary basis SHLIB_LD_LIBS='${LIBS}' LDFLAGS_ORIG="$LDFLAGS" # When ld needs options to work in 64-bit mode, put them in # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] # is disabled by the user. [Bug 1016796] LDFLAGS_ARCH="" UNSHARED_LIB_SUFFIX="" TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`' ECHO_VERSION='`echo ${VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g if test "$GCC" = yes; then : CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall" else CFLAGS_OPTIMIZE=-O CFLAGS_WARNING="" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="${ac_tool_prefix}ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" PLAT_OBJS="" PLAT_SRCS="" LDAIX_SRC="" if test x"${SHLIB_VERSION}" = x; then : SHLIB_VERSION="1.0" fi case $system in AIX-*) if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"; then : # AIX requires the _r compiler when gcc isn't being used case "${CC}" in *_r|*_r\ *) # ok ... ;; *) # Make sure only first arg gets _r CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5 $as_echo "Using $CC for compiling with threads" >&6; } fi LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" LD_LIBRARY_PATH_VAR="LIBPATH" # ldAix No longer needed with use of -bexpall/-brtl # but some extensions may still reference it LDAIX_SRC='$(UNIX_DIR)/ldAix' # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes; then : if test "$GCC" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} else do64bit_ok=yes CFLAGS="$CFLAGS -q64" LDFLAGS_ARCH="-q64" RANLIB="${RANLIB} -X64" AR="${AR} -X64" SHLIB_LD_FLAGS="-b64" fi fi if test "`uname -m`" = ia64; then : # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC SHLIB_LD="/usr/ccs/bin/ld -G -z text" # AIX-5 has dl* in libc.so DL_LIBS="" if test "$GCC" = yes; then : CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' else CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' fi LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' else if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared -Wl,-bexpall' else SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" LDFLAGS="$LDFLAGS -brtl" fi SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} -nostart' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" #----------------------------------------------------------- # Check for inet_ntoa in -lbind, for BeOS (which also needs # -lsocket, even if the network functions are in -lnet which # is always linked to, for compatibility. #----------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5 $as_echo_n "checking for inet_ntoa in -lbind... " >&6; } if ${ac_cv_lib_bind_inet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbind $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_ntoa (); int main () { return inet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bind_inet_ntoa=yes else ac_cv_lib_bind_inet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5 $as_echo "$ac_cv_lib_bind_inet_ntoa" >&6; } if test "x$ac_cv_lib_bind_inet_ntoa" = xyes; then : LIBS="$LIBS -lbind -lsocket" fi ;; BSD/OS-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; CYGWIN_*|MINGW32*) SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" DL_OBJS="tclLoadDl.o" PLAT_OBJS='${CYGWIN_OBJS}' PLAT_SRCS='${CYGWIN_SRCS}' DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" TCL_NEEDS_EXP_FILE=1 TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a' SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Cygwin version of gcc" >&5 $as_echo_n "checking for Cygwin version of gcc... " >&6; } if ${ac_cv_cygwin+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __CYGWIN__ #error cygwin #endif int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_cygwin=no else ac_cv_cygwin=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cygwin" >&5 $as_echo "$ac_cv_cygwin" >&6; } if test "$ac_cv_cygwin" = "no"; then as_fn_error $? "${CC} is not a cygwin compiler." "$LINENO" 5 fi if test "x${TCL_THREADS}" = "x0"; then as_fn_error $? "CYGWIN compile is only supported with --enable-threads" "$LINENO" 5 fi do64bit_ok=yes if test "x${SHARED_BUILD}" = "x1"; then echo "running cd ${TCL_SRC_DIR}/win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args" # The eval makes quoting arguments work. if cd ${TCL_SRC_DIR}/win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args; cd ../unix then : else { echo "configure: error: configure failed for ../win" 1>&2; exit 1; } fi fi ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; Haiku*) LDFLAGS="$LDFLAGS -Wl,--export-dynamic" SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}' DL_OBJS="tclLoadDl.o" DL_LIBS="-lroot" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5 $as_echo_n "checking for inet_ntoa in -lnetwork... " >&6; } if ${ac_cv_lib_network_inet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnetwork $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_ntoa (); int main () { return inet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_network_inet_ntoa=yes else ac_cv_lib_network_inet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5 $as_echo "$ac_cv_lib_network_inet_ntoa" >&6; } if test "x$ac_cv_lib_network_inet_ntoa" = xyes; then : LIBS="$LIBS -lnetwork" fi ;; HP-UX-*.11.*) # Use updated header definitions where possible $as_echo "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h $as_echo "#define _XOPEN_SOURCE 1" >>confdefs.h LIBS="$LIBS -lxnet" # Use the XOPEN network library if test "`uname -m`" = ia64; then : SHLIB_SUFFIX=".so" else SHLIB_SUFFIX=".sl" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = yes; then : SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' LD_LIBRARY_PATH_VAR="SHLIB_PATH" fi if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} else CFLAGS="$CFLAGS -z" fi # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc #CFLAGS="$CFLAGS +DAportable" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes"; then : if test "$GCC" = yes; then : case `${CC} -dumpmachine` in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD='${CC} -shared' if test $doRpath = yes; then : CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} ;; esac else do64bit_ok=yes CFLAGS="$CFLAGS +DD64" LDFLAGS_ARCH="+DD64" fi fi ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = yes; then : SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' LD_LIBRARY_PATH_VAR="SHLIB_PATH" fi ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" case " $LIBOBJS " in *" mkstemp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" ;; esac if test $doRpath = yes; then : CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' fi ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" case " $LIBOBJS " in *" mkstemp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" ;; esac if test $doRpath = yes; then : CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' fi if test "$GCC" = yes; then : CFLAGS="$CFLAGS -mabi=n32" LDFLAGS="$LDFLAGS -mabi=n32" else case $system in IRIX-6.3) # Use to build 6.2 compatible binaries on 6.3. CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" ;; *) CFLAGS="$CFLAGS -n32" ;; esac LDFLAGS="$LDFLAGS -n32" fi ;; IRIX64-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" case " $LIBOBJS " in *" mkstemp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" ;; esac if test $doRpath = yes; then : CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' fi # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes; then : if test "$GCC" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} else do64bit_ok=yes SHLIB_LD="ld -64 -shared -rdata_shared" CFLAGS="$CFLAGS -64" LDFLAGS_ARCH="-64" fi fi ;; Linux*|GNU*|NetBSD-Debian) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE="-O2" # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings # when you inline the string and math operations. Turn this off to # get rid of the warnings. #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES" SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}' DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" if test $doRpath = yes; then : CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "`uname -m`" = "alpha"; then : CFLAGS="$CFLAGS -mieee" fi if test $do64bit = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5 $as_echo_n "checking if compiler accepts -m64 flag... " >&6; } if ${tcl_cv_cc_m64+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS CFLAGS="$CFLAGS -m64" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_m64=yes else tcl_cv_cc_m64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5 $as_echo "$tcl_cv_cc_m64" >&6; } if test $tcl_cv_cc_m64 = yes; then : CFLAGS="$CFLAGS -m64" do64bit_ok=yes fi fi # The combo of gcc + glibc has a bug related to inlining of # functions like strtod(). The -fno-builtin flag should address # this problem but it does not work. The -fno-inline flag is kind # of overkill but it works. Disable inlining only when one of the # files in compat/*.c is being linked in. if test x"${USE_COMPAT}" != x; then : CFLAGS="$CFLAGS -fno-inline" fi ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD='${CC} -shared' DL_OBJS="tclLoadDl.o" DL_LIBS="-mshared -ldl" LD_FLAGS="-Wl,--export-dynamic" if test $doRpath = yes; then : CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' fi ;; MP-RAS-02*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; MP-RAS-*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,-Bexport" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OpenBSD-*) arch=`arch -s` case "$arch" in vax) # Equivalent using configure option --disable-load # Step 4 will set the necessary variables DL_OBJS="" SHLIB_LD_LIBS="" LDFLAGS="" ;; *) case "$arch" in alpha|sparc|sparc64) SHLIB_CFLAGS="-fPIC" ;; *) SHLIB_CFLAGS="-fpic" ;; esac SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" if test $doRpath = yes; then : CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' LDFLAGS="-Wl,-export-dynamic" ;; esac case "$arch" in vax) CFLAGS_OPTIMIZE="-O1" ;; sh) CFLAGS_OPTIMIZE="-O0" ;; *) CFLAGS_OPTIMIZE="-O2" ;; esac if test "${TCL_THREADS}" = "1"; then : # On OpenBSD: Compile with -pthread # Don't link with -lpthread LIBS=`echo $LIBS | sed s/-lpthread//` CFLAGS="$CFLAGS -pthread" fi # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; NetBSD-*) # NetBSD has ELF and can use 'cc -shared' to build shared libs SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" LDFLAGS="$LDFLAGS -export-dynamic" if test $doRpath = yes; then : CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "${TCL_THREADS}" = "1"; then : # The -pthread needs to go in the CFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" fi ;; FreeBSD-*) # This configuration from FreeBSD Ports. SHLIB_CFLAGS="-fPIC" SHLIB_LD="${CC} -shared" SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,-soname,\$@" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" LDFLAGS="" if test $doRpath = yes; then : CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' fi if test "${TCL_THREADS}" = "1"; then : # The -pthread needs to go in the LDFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LIBS" fi case $system in FreeBSD-3.*) # Version numbers are dot-stripped by system policy. TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .` UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so' TCL_LIB_VERSIONS_OK=nodots ;; esac ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" # To avoid discrepancies between what headers configure sees during # preprocessing tests and compiling tests, move any -isysroot and # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`" CFLAGS="`echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`" if test $do64bit = yes; then : case `arch` in ppc) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5 $as_echo_n "checking if compiler accepts -arch ppc64 flag... " >&6; } if ${tcl_cv_cc_arch_ppc64+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_arch_ppc64=yes else tcl_cv_cc_arch_ppc64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5 $as_echo "$tcl_cv_cc_arch_ppc64" >&6; } if test $tcl_cv_cc_arch_ppc64 = yes; then : CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" do64bit_ok=yes fi;; i386) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5 $as_echo_n "checking if compiler accepts -arch x86_64 flag... " >&6; } if ${tcl_cv_cc_arch_x86_64+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch x86_64" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_arch_x86_64=yes else tcl_cv_cc_arch_x86_64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5 $as_echo "$tcl_cv_cc_arch_x86_64" >&6; } if test $tcl_cv_cc_arch_x86_64 = yes; then : CFLAGS="$CFLAGS -arch x86_64" do64bit_ok=yes fi;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5 $as_echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};; esac else # Check for combined 32-bit and 64-bit fat build if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then : fat_32_64=yes fi fi SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5 $as_echo_n "checking if ld accepts -single_module flag... " >&6; } if ${tcl_cv_ld_single_module+:} false; then : $as_echo_n "(cached) " >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_ld_single_module=yes else tcl_cv_ld_single_module=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5 $as_echo "$tcl_cv_ld_single_module" >&6; } if test $tcl_cv_ld_single_module = yes; then : SHLIB_LD="${SHLIB_LD} -Wl,-single_module" fi SHLIB_SUFFIX=".dylib" DL_OBJS="tclLoadDyld.o" DL_LIBS="" # Don't use -prebind when building for Mac OS X 10.4 or later only: if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \ "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then : LDFLAGS="$LDFLAGS -prebind" fi LDFLAGS="$LDFLAGS -headerpad_max_install_names" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5 $as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; } if ${tcl_cv_ld_search_paths_first+:} false; then : $as_echo_n "(cached) " >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-search_paths_first" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_ld_search_paths_first=yes else tcl_cv_ld_search_paths_first=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5 $as_echo "$tcl_cv_ld_search_paths_first" >&6; } if test $tcl_cv_ld_search_paths_first = yes; then : LDFLAGS="$LDFLAGS -Wl,-search_paths_first" fi if test "$tcl_cv_cc_visibility_hidden" != yes; then : $as_echo "#define MODULE_SCOPE __private_extern__" >>confdefs.h fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" $as_echo "#define MAC_OSX_TCL 1" >>confdefs.h PLAT_OBJS='${MAC_OSX_OBJS}' PLAT_SRCS='${MAC_OSX_SRCS}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use CoreFoundation" >&5 $as_echo_n "checking whether to use CoreFoundation... " >&6; } # Check whether --enable-corefoundation was given. if test "${enable_corefoundation+set}" = set; then : enableval=$enable_corefoundation; tcl_corefoundation=$enableval else tcl_corefoundation=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_corefoundation" >&5 $as_echo "$tcl_corefoundation" >&6; } if test $tcl_corefoundation = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CoreFoundation.framework" >&5 $as_echo_n "checking for CoreFoundation.framework... " >&6; } if ${tcl_cv_lib_corefoundation+:} false; then : $as_echo_n "(cached) " >&6 else hold_libs=$LIBS if test "$fat_32_64" = yes; then : for v in CFLAGS CPPFLAGS LDFLAGS; do # On Tiger there is no 64-bit CF, so remove 64-bit # archs from CFLAGS et al. while testing for # presence of CF. 64-bit CF is disabled in # tclUnixPort.h if necessary. eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' done fi LIBS="$LIBS -framework CoreFoundation" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { CFBundleRef b = CFBundleGetMainBundle(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_lib_corefoundation=yes else tcl_cv_lib_corefoundation=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$fat_32_64" = yes; then : for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done fi LIBS=$hold_libs fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation" >&5 $as_echo "$tcl_cv_lib_corefoundation" >&6; } if test $tcl_cv_lib_corefoundation = yes; then : LIBS="$LIBS -framework CoreFoundation" $as_echo "#define HAVE_COREFOUNDATION 1" >>confdefs.h else tcl_corefoundation=no fi if test "$fat_32_64" = yes -a $tcl_corefoundation = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit CoreFoundation" >&5 $as_echo_n "checking for 64-bit CoreFoundation... " >&6; } if ${tcl_cv_lib_corefoundation_64+:} false; then : $as_echo_n "(cached) " >&6 else for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { CFBundleRef b = CFBundleGetMainBundle(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_lib_corefoundation_64=yes else tcl_cv_lib_corefoundation_64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation_64" >&5 $as_echo "$tcl_cv_lib_corefoundation_64" >&6; } if test $tcl_cv_lib_corefoundation_64 = no; then : $as_echo "#define NO_COREFOUNDATION_64 1" >>confdefs.h LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings" fi fi fi ;; NEXTSTEP-*) SHLIB_CFLAGS="" SHLIB_LD='${CC} -nostdlib -r' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadNext.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OS/390-*) SHLIB_LD_LIBS="" CFLAGS_OPTIMIZE="" # Optimizer is buggy $as_echo "#define _OE_SOCKETS 1" >>confdefs.h ;; OSF1-1.0|OSF1-1.1|OSF1-1.2) # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 SHLIB_CFLAGS="" # Hack: make package name same as library name SHLIB_LD='ld -R -export :' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadOSF.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OSF1-1.*) # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 SHLIB_CFLAGS="-fPIC" if test "$SHARED_BUILD" = 1; then : SHLIB_LD="ld -shared" else SHLIB_LD="ld -non_shared" fi SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OSF1-V*) # Digital OSF/1 SHLIB_CFLAGS="" if test "$SHARED_BUILD" = 1; then : SHLIB_LD='ld -shared -expect_unresolved "*"' else SHLIB_LD='ld -non_shared -expect_unresolved "*"' fi SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" if test $doRpath = yes; then : CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' fi if test "$GCC" = yes; then : CFLAGS="$CFLAGS -mieee" else CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" fi # see pthread_intro(3) for pthread support on osf1, k.furukawa if test "${TCL_THREADS}" = 1; then : CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" LIBS=`echo $LIBS | sed s/-lpthreads//` if test "$GCC" = yes; then : LIBS="$LIBS -lpthread -lmach -lexc" else CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" fi fi ;; QNX-6*) # QNX RTP # This may work for all QNX, but it was only reported for v6. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" # dlopen is in -lc on QNX DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) # Note, dlopen is available only on SCO 3.2.5 and greater. However, # this test works, since "uname -s" was non-standard in 3.2.4 and # below. if test "$GCC" = yes; then : SHLIB_CFLAGS="-fPIC -melf" LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" else SHLIB_CFLAGS="-Kpic -belf" LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" fi SHLIB_LD="ld -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SINIX*5.4*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-4*) SHLIB_CFLAGS="-PIC" SHLIB_LD="ld" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # SunOS can't handle version numbers with dots in them in library # specs, like -ltcl7.5, so use -ltcl75 instead. Also, it # requires an extra version number at the end of .so file names. # So, the library has to have a name like libtcl75.so.1.0 SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; SunOS-5.[0-6]) # Careful to not let 5.10+ fall into this case # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. $as_echo "#define _REENTRANT 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h SHLIB_CFLAGS="-KPIC" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} else SHLIB_LD="/usr/ccs/bin/ld -G -z text" CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi ;; SunOS-5*) # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. $as_echo "#define _REENTRANT 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h SHLIB_CFLAGS="-KPIC" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes; then : arch=`isainfo` if test "$arch" = "sparcv9 sparc"; then : if test "$GCC" = yes; then : if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;} else do64bit_ok=yes CFLAGS="$CFLAGS -m64 -mcpu=v9" LDFLAGS="$LDFLAGS -m64 -mcpu=v9" SHLIB_CFLAGS="-fPIC" fi else do64bit_ok=yes if test "$do64bitVIS" = yes; then : CFLAGS="$CFLAGS -xarch=v9a" LDFLAGS_ARCH="-xarch=v9a" else CFLAGS="$CFLAGS -xarch=v9" LDFLAGS_ARCH="-xarch=v9" fi # Solaris 64 uses this as well #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" fi else if test "$arch" = "amd64 i386"; then : if test "$GCC" = yes; then : case $system in SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) do64bit_ok=yes CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};; esac else do64bit_ok=yes case $system in SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} fi fi fi #-------------------------------------------------------------------- # On Solaris 5.x i386 with the sunpro compiler we need to link # with sunmath to get floating point rounding control #-------------------------------------------------------------------- if test "$GCC" = yes; then : use_sunmath=no else arch=`isainfo` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use -lsunmath for fp rounding control" >&5 $as_echo_n "checking whether to use -lsunmath for fp rounding control... " >&6; } if test "$arch" = "amd64 i386" -o "$arch" = "i386"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } MATH_LIBS="-lsunmath $MATH_LIBS" ac_fn_c_check_header_mongrel "$LINENO" "sunmath.h" "ac_cv_header_sunmath_h" "$ac_includes_default" if test "x$ac_cv_header_sunmath_h" = xyes; then : fi use_sunmath=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } use_sunmath=no fi fi SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "$do64bit_ok" = yes; then : if test "$arch" = "sparcv9 sparc"; then : # We need to specify -static-libgcc or we need to # add the path to the sparv9 libgcc. SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" # for finding sparcv9 libgcc, get the regular libgcc # path, remove so name and append 'sparcv9' #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" else if test "$arch" = "amd64 i386"; then : SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" fi fi fi else if test "$use_sunmath" = yes; then : textmode=textoff else textmode=text fi case $system in SunOS-5.[1-9][0-9]*|SunOS-5.[7-9]) SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";; *) SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";; esac CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' fi ;; UNIX_SV* | UnixWare-5*) SHLIB_CFLAGS="-KPIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers # that don't grok the -Bexport option. Test that it does. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5 $as_echo_n "checking for ld accepts -Bexport flag... " >&6; } if ${tcl_cv_ld_Bexport+:} false; then : $as_echo_n "(cached) " >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-Bexport" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_ld_Bexport=yes else tcl_cv_ld_Bexport=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5 $as_echo "$tcl_cv_ld_Bexport" >&6; } if test $tcl_cv_ld_Bexport = yes; then : LDFLAGS="$LDFLAGS -Wl,-Bexport" fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; esac if test "$do64bit" = yes -a "$do64bit_ok" = no; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 $as_echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} fi if test "$do64bit" = yes -a "$do64bit_ok" = yes; then : $as_echo "#define TCL_CFG_DO64BIT 1" >>confdefs.h fi # Step 4: disable dynamic loading if requested via a command-line switch. # Check whether --enable-load was given. if test "${enable_load+set}" = set; then : enableval=$enable_load; tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = no; then : DL_OBJS="" fi if test "x$DL_OBJS" != x; then : BUILD_DLTEST="\$(DLTEST_TARGETS)" else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&5 $as_echo "$as_me: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&2;} SHLIB_CFLAGS="" SHLIB_LD="" SHLIB_SUFFIX="" DL_OBJS="tclLoadNone.o" DL_LIBS="" LDFLAGS="$LDFLAGS_ORIG" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" BUILD_DLTEST="" fi LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" # If we're running gcc, then change the C flags for compiling shared # libraries to the right flags for gcc, instead of those for the # standard manufacturer compiler. if test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes; then : case $system in AIX-*) ;; BSD/OS*) ;; CYGWIN_*|MINGW32_*) ;; IRIX*) ;; NetBSD-*|FreeBSD-*|OpenBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac fi if test "$tcl_cv_cc_visibility_hidden" != yes; then : $as_echo "#define MODULE_SCOPE extern" >>confdefs.h fi if test "$SHARED_LIB_SUFFIX" = ""; then : SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}' fi if test "$UNSHARED_LIB_SUFFIX" = ""; then : UNSHARED_LIB_SUFFIX='${VERSION}.a' fi DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)" if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then : LIB_SUFFIX=${SHARED_LIB_SUFFIX} MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' if test "${SHLIB_SUFFIX}" = ".dll"; then : INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;' DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)" else INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' fi else LIB_SUFFIX=${UNSHARED_LIB_SUFFIX} if test "$RANLIB" = ""; then : MAKE_LIB='$(STLIB_LD) $@ ${OBJS}' else MAKE_LIB='${STLIB_LD} $@ ${OBJS} ; ${RANLIB} $@' fi INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' fi # Stub lib does not depend on shared/static configuration if test "$RANLIB" = ""; then : MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS}' else MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS} ; ${RANLIB} $@' fi INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"' # Define TCL_LIBS now that we know what DL_LIBS is. # The trick here is that we don't want to change the value of TCL_LIBS if # it is already set when tclConfig.sh had been loaded by Tk. if test "x${TCL_LIBS}" = x; then : TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}" fi # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5 $as_echo_n "checking for cast to union support... " >&6; } if ${tcl_cv_cast_to_union+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { union foo { int i; double d; }; union foo f = (union foo) (int) 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_cast_to_union=yes else tcl_cv_cast_to_union=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5 $as_echo "$tcl_cv_cast_to_union" >&6; } if test "$tcl_cv_cast_to_union" = "yes"; then $as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h fi # FIXME: This subst was left in only because the TCL_DL_LIBS # entry in tclConfig.sh uses it. It is not clear why someone # would use TCL_DL_LIBS instead of TCL_LIBS. cat >>confdefs.h <<_ACEOF #define TCL_SHLIB_EXT "${SHLIB_SUFFIX}" _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5 $as_echo_n "checking for build with symbols... " >&6; } # Check whether --enable-symbols was given. if test "${enable_symbols+set}" = set; then : enableval=$enable_symbols; tcl_ok=$enableval else tcl_ok=no fi # FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT. DBGX="" if test "$tcl_ok" = "no"; then CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)' LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)' $as_echo "#define NDEBUG 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define TCL_CFG_OPTIMIZED 1" >>confdefs.h else CFLAGS_DEFAULT='$(CFLAGS_DEBUG)' LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)' if test "$tcl_ok" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5 $as_echo "yes (standard debugging)" >&6; } fi fi if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then $as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h fi if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then $as_echo "#define TCL_COMPILE_DEBUG 1" >>confdefs.h $as_echo "#define TCL_COMPILE_STATS 1" >>confdefs.h fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem compile debugging" >&5 $as_echo "enabled symbols mem compile debugging" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5 $as_echo "enabled $tcl_ok debugging" >&6; } fi fi $as_echo "#define TCL_TOMMATH 1" >>confdefs.h $as_echo "#define MP_PREC 4" >>confdefs.h #-------------------------------------------------------------------- # Detect what compiler flags to set for 64-bit support. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5 $as_echo_n "checking for required early compiler flags... " >&6; } tcl_flags="" if ${tcl_cv_flag__isoc99_source+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__isoc99_source=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _ISOC99_SOURCE 1 #include int main () { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__isoc99_source=yes else tcl_cv_flag__isoc99_source=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then $as_echo "#define _ISOC99_SOURCE 1" >>confdefs.h tcl_flags="$tcl_flags _ISOC99_SOURCE" fi if ${tcl_cv_flag__largefile64_source+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct stat64 buf; int i = stat64("/", &buf); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__largefile64_source=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGEFILE64_SOURCE 1 #include int main () { struct stat64 buf; int i = stat64("/", &buf); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__largefile64_source=yes else tcl_cv_flag__largefile64_source=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x${tcl_cv_flag__largefile64_source}" = "xyes" ; then $as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h tcl_flags="$tcl_flags _LARGEFILE64_SOURCE" fi if ${tcl_cv_flag__largefile_source64+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *p = (char *)open64; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__largefile_source64=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGEFILE_SOURCE64 1 #include int main () { char *p = (char *)open64; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__largefile_source64=yes else tcl_cv_flag__largefile_source64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then $as_echo "#define _LARGEFILE_SOURCE64 1" >>confdefs.h tcl_flags="$tcl_flags _LARGEFILE_SOURCE64" fi if test "x${tcl_flags}" = "x" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5 $as_echo "${tcl_flags}" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type" >&5 $as_echo_n "checking for 64-bit integer type... " >&6; } if ${tcl_cv_type_64bit+:} false; then : $as_echo_n "(cached) " >&6 else tcl_cv_type_64bit=none # See if the compiler knows natively about __int64 cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { __int64 value = (__int64) 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_type_64bit=__int64 else tcl_type_64bit="long long" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # See if we should use long anyway Note that we substitute in the # type that is our current guess for a 64-bit type inside this check # program, so it should be modified only carefully... cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { switch (0) { case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_type_64bit=${tcl_type_64bit} fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "${tcl_cv_type_64bit}" = none ; then $as_echo "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: using long" >&5 $as_echo "using long" >&6; } else cat >>confdefs.h <<_ACEOF #define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit} _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}" >&5 $as_echo "${tcl_cv_type_64bit}" >&6; } # Now check for auxiliary declarations { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5 $as_echo_n "checking for struct dirent64... " >&6; } if ${tcl_cv_struct_dirent64+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct dirent64 p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_struct_dirent64=yes else tcl_cv_struct_dirent64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5 $as_echo "$tcl_cv_struct_dirent64" >&6; } if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then $as_echo "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5 $as_echo_n "checking for struct stat64... " >&6; } if ${tcl_cv_struct_stat64+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct stat64 p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_struct_stat64=yes else tcl_cv_struct_stat64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5 $as_echo "$tcl_cv_struct_stat64" >&6; } if test "x${tcl_cv_struct_stat64}" = "xyes" ; then $as_echo "#define HAVE_STRUCT_STAT64 1" >>confdefs.h fi for ac_func in open64 lseek64 do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5 $as_echo_n "checking for off64_t... " >&6; } if ${tcl_cv_type_off64_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { off64_t offset; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_type_off64_t=yes else tcl_cv_type_off64_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x${tcl_cv_type_off64_t}" = "xyes" && \ test "x${ac_cv_func_lseek64}" = "xyes" && \ test "x${ac_cv_func_open64}" = "xyes" ; then $as_echo "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi #-------------------------------------------------------------------- # Check endianness because we can optimize comparisons of # Tcl_UniChar strings to memcmp on big-endian systems. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac #-------------------------------------------------------------------- # Supply substitutes for missing POSIX library procedures, or # set flags so Tcl uses alternate procedures. #-------------------------------------------------------------------- # Check if Posix compliant getcwd exists, if not we'll use getwd. for ac_func in getcwd do : ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd" if test "x$ac_cv_func_getcwd" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETCWD 1 _ACEOF else $as_echo "#define USEGETWD 1" >>confdefs.h fi done # Nb: if getcwd uses popen and pwd(1) (like SunOS 4) we should really # define USEGETWD even if the posix getcwd exists. Add a test ? ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp" if test "x$ac_cv_func_mkstemp" = xyes; then : $as_echo "#define HAVE_MKSTEMP 1" >>confdefs.h else case " $LIBOBJS " in *" mkstemp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "opendir" "ac_cv_func_opendir" if test "x$ac_cv_func_opendir" = xyes; then : $as_echo "#define HAVE_OPENDIR 1" >>confdefs.h else case " $LIBOBJS " in *" opendir.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS opendir.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "strtol" "ac_cv_func_strtol" if test "x$ac_cv_func_strtol" = xyes; then : $as_echo "#define HAVE_STRTOL 1" >>confdefs.h else case " $LIBOBJS " in *" strtol.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strtol.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "waitpid" "ac_cv_func_waitpid" if test "x$ac_cv_func_waitpid" = xyes; then : $as_echo "#define HAVE_WAITPID 1" >>confdefs.h else case " $LIBOBJS " in *" waitpid.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS waitpid.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror" if test "x$ac_cv_func_strerror" = xyes; then : else $as_echo "#define NO_STRERROR 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getwd" "ac_cv_func_getwd" if test "x$ac_cv_func_getwd" = xyes; then : else $as_echo "#define NO_GETWD 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "wait3" "ac_cv_func_wait3" if test "x$ac_cv_func_wait3" = xyes; then : else $as_echo "#define NO_WAIT3 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "uname" "ac_cv_func_uname" if test "x$ac_cv_func_uname" = xyes; then : else $as_echo "#define NO_UNAME 1" >>confdefs.h fi if test "`uname -s`" = "Darwin" && test "${TCL_THREADS}" = 1 && \ test "`uname -r | awk -F. '{print $1}'`" -lt 7; then # prior to Darwin 7, realpath is not threadsafe, so don't # use it when threads are enabled, c.f. bug # 711232 ac_cv_func_realpath=no fi ac_fn_c_check_func "$LINENO" "realpath" "ac_cv_func_realpath" if test "x$ac_cv_func_realpath" = xyes; then : else $as_echo "#define NO_REALPATH 1" >>confdefs.h fi NEED_FAKE_RFC2553=0 for ac_func in getnameinfo getaddrinfo freeaddrinfo gai_strerror do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else NEED_FAKE_RFC2553=1 fi done ac_fn_c_check_type "$LINENO" "struct addrinfo" "ac_cv_type_struct_addrinfo" " #include #include #include #include " if test "x$ac_cv_type_struct_addrinfo" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_ADDRINFO 1 _ACEOF else NEED_FAKE_RFC2553=1 fi ac_fn_c_check_type "$LINENO" "struct in6_addr" "ac_cv_type_struct_in6_addr" " #include #include #include #include " if test "x$ac_cv_type_struct_in6_addr" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_IN6_ADDR 1 _ACEOF else NEED_FAKE_RFC2553=1 fi ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" " #include #include #include #include " if test "x$ac_cv_type_struct_sockaddr_in6" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_SOCKADDR_IN6 1 _ACEOF else NEED_FAKE_RFC2553=1 fi ac_fn_c_check_type "$LINENO" "struct sockaddr_storage" "ac_cv_type_struct_sockaddr_storage" " #include #include #include #include " if test "x$ac_cv_type_struct_sockaddr_storage" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_SOCKADDR_STORAGE 1 _ACEOF else NEED_FAKE_RFC2553=1 fi if test "x$NEED_FAKE_RFC2553" = "x1"; then $as_echo "#define NEED_FAKE_RFC2553 1" >>confdefs.h case " $LIBOBJS " in *" fake-rfc2553.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS fake-rfc2553.$ac_objext" ;; esac ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" if test "x$ac_cv_func_strlcpy" = xyes; then : fi fi #-------------------------------------------------------------------- # Look for thread-safe variants of some library functions. #-------------------------------------------------------------------- if test "${TCL_THREADS}" = 1; then ac_fn_c_check_func "$LINENO" "getpwuid_r" "ac_cv_func_getpwuid_r" if test "x$ac_cv_func_getpwuid_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwuid_r with 5 args" >&5 $as_echo_n "checking for getpwuid_r with 5 args... " >&6; } if ${tcl_cv_api_getpwuid_r_5+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { uid_t uid; struct passwd pw, *pwp; char buf[512]; int buflen = 512; (void) getpwuid_r(uid, &pw, buf, buflen, &pwp); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_getpwuid_r_5=yes else tcl_cv_api_getpwuid_r_5=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwuid_r_5" >&5 $as_echo "$tcl_cv_api_getpwuid_r_5" >&6; } tcl_ok=$tcl_cv_api_getpwuid_r_5 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETPWUID_R_5 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwuid_r with 4 args" >&5 $as_echo_n "checking for getpwuid_r with 4 args... " >&6; } if ${tcl_cv_api_getpwuid_r_4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { uid_t uid; struct passwd pw; char buf[512]; int buflen = 512; (void)getpwnam_r(uid, &pw, buf, buflen); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_getpwuid_r_4=yes else tcl_cv_api_getpwuid_r_4=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwuid_r_4" >&5 $as_echo "$tcl_cv_api_getpwuid_r_4" >&6; } tcl_ok=$tcl_cv_api_getpwuid_r_4 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETPWUID_R_4 1" >>confdefs.h fi fi if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETPWUID_R 1" >>confdefs.h fi fi ac_fn_c_check_func "$LINENO" "getpwnam_r" "ac_cv_func_getpwnam_r" if test "x$ac_cv_func_getpwnam_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwnam_r with 5 args" >&5 $as_echo_n "checking for getpwnam_r with 5 args... " >&6; } if ${tcl_cv_api_getpwnam_r_5+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { char *name; struct passwd pw, *pwp; char buf[512]; int buflen = 512; (void) getpwnam_r(name, &pw, buf, buflen, &pwp); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_getpwnam_r_5=yes else tcl_cv_api_getpwnam_r_5=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwnam_r_5" >&5 $as_echo "$tcl_cv_api_getpwnam_r_5" >&6; } tcl_ok=$tcl_cv_api_getpwnam_r_5 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETPWNAM_R_5 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwnam_r with 4 args" >&5 $as_echo_n "checking for getpwnam_r with 4 args... " >&6; } if ${tcl_cv_api_getpwnam_r_4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { char *name; struct passwd pw; char buf[512]; int buflen = 512; (void)getpwnam_r(name, &pw, buf, buflen); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_getpwnam_r_4=yes else tcl_cv_api_getpwnam_r_4=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getpwnam_r_4" >&5 $as_echo "$tcl_cv_api_getpwnam_r_4" >&6; } tcl_ok=$tcl_cv_api_getpwnam_r_4 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETPWNAM_R_4 1" >>confdefs.h fi fi if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETPWNAM_R 1" >>confdefs.h fi fi ac_fn_c_check_func "$LINENO" "getgrgid_r" "ac_cv_func_getgrgid_r" if test "x$ac_cv_func_getgrgid_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrgid_r with 5 args" >&5 $as_echo_n "checking for getgrgid_r with 5 args... " >&6; } if ${tcl_cv_api_getgrgid_r_5+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { gid_t gid; struct group gr, *grp; char buf[512]; int buflen = 512; (void) getgrgid_r(gid, &gr, buf, buflen, &grp); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_getgrgid_r_5=yes else tcl_cv_api_getgrgid_r_5=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrgid_r_5" >&5 $as_echo "$tcl_cv_api_getgrgid_r_5" >&6; } tcl_ok=$tcl_cv_api_getgrgid_r_5 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETGRGID_R_5 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrgid_r with 4 args" >&5 $as_echo_n "checking for getgrgid_r with 4 args... " >&6; } if ${tcl_cv_api_getgrgid_r_4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { gid_t gid; struct group gr; char buf[512]; int buflen = 512; (void)getgrgid_r(gid, &gr, buf, buflen); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_getgrgid_r_4=yes else tcl_cv_api_getgrgid_r_4=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrgid_r_4" >&5 $as_echo "$tcl_cv_api_getgrgid_r_4" >&6; } tcl_ok=$tcl_cv_api_getgrgid_r_4 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETGRGID_R_4 1" >>confdefs.h fi fi if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETGRGID_R 1" >>confdefs.h fi fi ac_fn_c_check_func "$LINENO" "getgrnam_r" "ac_cv_func_getgrnam_r" if test "x$ac_cv_func_getgrnam_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrnam_r with 5 args" >&5 $as_echo_n "checking for getgrnam_r with 5 args... " >&6; } if ${tcl_cv_api_getgrnam_r_5+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { char *name; struct group gr, *grp; char buf[512]; int buflen = 512; (void) getgrnam_r(name, &gr, buf, buflen, &grp); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_getgrnam_r_5=yes else tcl_cv_api_getgrnam_r_5=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrnam_r_5" >&5 $as_echo "$tcl_cv_api_getgrnam_r_5" >&6; } tcl_ok=$tcl_cv_api_getgrnam_r_5 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETGRNAM_R_5 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrnam_r with 4 args" >&5 $as_echo_n "checking for getgrnam_r with 4 args... " >&6; } if ${tcl_cv_api_getgrnam_r_4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { char *name; struct group gr; char buf[512]; int buflen = 512; (void)getgrnam_r(name, &gr, buf, buflen); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_getgrnam_r_4=yes else tcl_cv_api_getgrnam_r_4=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_getgrnam_r_4" >&5 $as_echo "$tcl_cv_api_getgrnam_r_4" >&6; } tcl_ok=$tcl_cv_api_getgrnam_r_4 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETGRNAM_R_4 1" >>confdefs.h fi fi if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETGRNAM_R 1" >>confdefs.h fi fi if test "`uname -s`" = "Darwin" && \ test "`uname -r | awk -F. '{print $1}'`" -gt 5; then # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX # are actually MT-safe as they always return pointers # from TSD instead of static storage. $as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h $as_echo "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h elif test "`uname -s`" = "HP-UX" && \ test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then # Starting with HPUX 11.00 (we believe), gethostbyX # are actually MT-safe as they always return pointers # from TSD instead of static storage. $as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h $as_echo "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h else ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r" if test "x$ac_cv_func_gethostbyname_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 6 args" >&5 $as_echo_n "checking for gethostbyname_r with 6 args... " >&6; } if ${tcl_cv_api_gethostbyname_r_6+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *name; struct hostent *he, *res; char buffer[2048]; int buflen = 2048; int h_errnop; (void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_gethostbyname_r_6=yes else tcl_cv_api_gethostbyname_r_6=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_6" >&5 $as_echo "$tcl_cv_api_gethostbyname_r_6" >&6; } tcl_ok=$tcl_cv_api_gethostbyname_r_6 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETHOSTBYNAME_R_6 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 5 args" >&5 $as_echo_n "checking for gethostbyname_r with 5 args... " >&6; } if ${tcl_cv_api_gethostbyname_r_5+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *name; struct hostent *he; char buffer[2048]; int buflen = 2048; int h_errnop; (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_gethostbyname_r_5=yes else tcl_cv_api_gethostbyname_r_5=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_5" >&5 $as_echo "$tcl_cv_api_gethostbyname_r_5" >&6; } tcl_ok=$tcl_cv_api_gethostbyname_r_5 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETHOSTBYNAME_R_5 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 3 args" >&5 $as_echo_n "checking for gethostbyname_r with 3 args... " >&6; } if ${tcl_cv_api_gethostbyname_r_3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *name; struct hostent *he; struct hostent_data data; (void) gethostbyname_r(name, he, &data); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_gethostbyname_r_3=yes else tcl_cv_api_gethostbyname_r_3=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyname_r_3" >&5 $as_echo "$tcl_cv_api_gethostbyname_r_3" >&6; } tcl_ok=$tcl_cv_api_gethostbyname_r_3 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETHOSTBYNAME_R_3 1" >>confdefs.h fi fi fi if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h fi fi ac_fn_c_check_func "$LINENO" "gethostbyaddr_r" "ac_cv_func_gethostbyaddr_r" if test "x$ac_cv_func_gethostbyaddr_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr_r with 7 args" >&5 $as_echo_n "checking for gethostbyaddr_r with 7 args... " >&6; } if ${tcl_cv_api_gethostbyaddr_r_7+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *addr; int length; int type; struct hostent *result; char buffer[2048]; int buflen = 2048; int h_errnop; (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen, &h_errnop); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_gethostbyaddr_r_7=yes else tcl_cv_api_gethostbyaddr_r_7=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyaddr_r_7" >&5 $as_echo "$tcl_cv_api_gethostbyaddr_r_7" >&6; } tcl_ok=$tcl_cv_api_gethostbyaddr_r_7 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETHOSTBYADDR_R_7 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr_r with 8 args" >&5 $as_echo_n "checking for gethostbyaddr_r with 8 args... " >&6; } if ${tcl_cv_api_gethostbyaddr_r_8+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *addr; int length; int type; struct hostent *result, *resultp; char buffer[2048]; int buflen = 2048; int h_errnop; (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen, &resultp, &h_errnop); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_api_gethostbyaddr_r_8=yes else tcl_cv_api_gethostbyaddr_r_8=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_gethostbyaddr_r_8" >&5 $as_echo "$tcl_cv_api_gethostbyaddr_r_8" >&6; } tcl_ok=$tcl_cv_api_gethostbyaddr_r_8 if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETHOSTBYADDR_R_8 1" >>confdefs.h fi fi if test "$tcl_ok" = yes; then $as_echo "#define HAVE_GETHOSTBYADDR_R 1" >>confdefs.h fi fi fi fi #--------------------------------------------------------------------------- # Check for serial port interface. # # termios.h is present on all POSIX systems. # sys/ioctl.h is almost always present, though what it contains # is system-specific. # sys/modem.h is needed on HP-UX. #--------------------------------------------------------------------------- for ac_header in termios.h do : ac_fn_c_check_header_mongrel "$LINENO" "termios.h" "ac_cv_header_termios_h" "$ac_includes_default" if test "x$ac_cv_header_termios_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TERMIOS_H 1 _ACEOF fi done for ac_header in sys/ioctl.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default" if test "x$ac_cv_header_sys_ioctl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_IOCTL_H 1 _ACEOF fi done for ac_header in sys/modem.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/modem.h" "ac_cv_header_sys_modem_h" "$ac_includes_default" if test "x$ac_cv_header_sys_modem_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_MODEM_H 1 _ACEOF fi done #-------------------------------------------------------------------- # Include sys/select.h if it exists and if it supplies things # that appear to be useful and aren't already in sys/types.h. # This appears to be true only on the RS/6000 under AIX. Some # systems like OSF/1 have a sys/select.h that's of no use, and # other systems like SCO UNIX have a sys/select.h that's # pernicious. If "fd_set" isn't defined anywhere then set a # special flag. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fd_set in sys/types" >&5 $as_echo_n "checking for fd_set in sys/types... " >&6; } if ${tcl_cv_type_fd_set+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { fd_set readMask, writeMask; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_type_fd_set=yes else tcl_cv_type_fd_set=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_type_fd_set" >&5 $as_echo "$tcl_cv_type_fd_set" >&6; } tcl_ok=$tcl_cv_type_fd_set if test $tcl_ok = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fd_mask in sys/select" >&5 $as_echo_n "checking for fd_mask in sys/select... " >&6; } if ${tcl_cv_grep_fd_mask+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "fd_mask" >/dev/null 2>&1; then : tcl_cv_grep_fd_mask=present else tcl_cv_grep_fd_mask=missing fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_grep_fd_mask" >&5 $as_echo "$tcl_cv_grep_fd_mask" >&6; } if test $tcl_cv_grep_fd_mask = present; then $as_echo "#define HAVE_SYS_SELECT_H 1" >>confdefs.h tcl_ok=yes fi fi if test $tcl_ok = no; then $as_echo "#define NO_FD_SET 1" >>confdefs.h fi #------------------------------------------------------------------------------ # Find out all about time handling differences. #------------------------------------------------------------------------------ for ac_header in sys/time.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" if test "x$ac_cv_header_sys_time_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_TIME_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi for ac_func in gmtime_r localtime_r mktime do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking tm_tzadj in struct tm" >&5 $as_echo_n "checking tm_tzadj in struct tm... " >&6; } if ${tcl_cv_member_tm_tzadj+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct tm tm; tm.tm_tzadj; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_member_tm_tzadj=yes else tcl_cv_member_tm_tzadj=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_member_tm_tzadj" >&5 $as_echo "$tcl_cv_member_tm_tzadj" >&6; } if test $tcl_cv_member_tm_tzadj = yes ; then $as_echo "#define HAVE_TM_TZADJ 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking tm_gmtoff in struct tm" >&5 $as_echo_n "checking tm_gmtoff in struct tm... " >&6; } if ${tcl_cv_member_tm_gmtoff+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct tm tm; tm.tm_gmtoff; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_member_tm_gmtoff=yes else tcl_cv_member_tm_gmtoff=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_member_tm_gmtoff" >&5 $as_echo "$tcl_cv_member_tm_gmtoff" >&6; } if test $tcl_cv_member_tm_gmtoff = yes ; then $as_echo "#define HAVE_TM_GMTOFF 1" >>confdefs.h fi # # Its important to include time.h in this check, as some systems # (like convex) have timezone functions, etc. # { $as_echo "$as_me:${as_lineno-$LINENO}: checking long timezone variable" >&5 $as_echo_n "checking long timezone variable... " >&6; } if ${tcl_cv_timezone_long+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { extern long timezone; timezone += 1; exit (0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_timezone_long=yes else tcl_cv_timezone_long=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_timezone_long" >&5 $as_echo "$tcl_cv_timezone_long" >&6; } if test $tcl_cv_timezone_long = yes ; then $as_echo "#define HAVE_TIMEZONE_VAR 1" >>confdefs.h else # # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. # { $as_echo "$as_me:${as_lineno-$LINENO}: checking time_t timezone variable" >&5 $as_echo_n "checking time_t timezone variable... " >&6; } if ${tcl_cv_timezone_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { extern time_t timezone; timezone += 1; exit (0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_timezone_time=yes else tcl_cv_timezone_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_timezone_time" >&5 $as_echo "$tcl_cv_timezone_time" >&6; } if test $tcl_cv_timezone_time = yes ; then $as_echo "#define HAVE_TIMEZONE_VAR 1" >>confdefs.h fi fi #-------------------------------------------------------------------- # Some systems (e.g., IRIX 4.0.5) lack some fields in struct stat. But # we might be able to use fstatfs instead. Some systems (OpenBSD?) also # lack blkcnt_t. #-------------------------------------------------------------------- if test "$ac_cv_cygwin" != "yes"; then ac_fn_c_check_member "$LINENO" "struct stat" "st_blocks" "ac_cv_member_struct_stat_st_blocks" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_blocks" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_STAT_ST_BLOCKS 1 _ACEOF fi ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_blksize" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_STAT_ST_BLKSIZE 1 _ACEOF fi fi ac_fn_c_check_type "$LINENO" "blkcnt_t" "ac_cv_type_blkcnt_t" "$ac_includes_default" if test "x$ac_cv_type_blkcnt_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BLKCNT_T 1 _ACEOF fi ac_fn_c_check_func "$LINENO" "fstatfs" "ac_cv_func_fstatfs" if test "x$ac_cv_func_fstatfs" = xyes; then : else $as_echo "#define NO_FSTATFS 1" >>confdefs.h fi #-------------------------------------------------------------------- # Some system have no memcmp or it does not work with 8 bit data, this # checks it and add memcmp.o to LIBOBJS if needed #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5 $as_echo_n "checking for working memcmp... " >&6; } if ${ac_cv_func_memcmp_working+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_memcmp_working=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Some versions of memcmp are not 8-bit clean. */ char c0 = '\100', c1 = '\200', c2 = '\201'; if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) return 1; /* The Next x86 OpenStep bug shows up only when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary. William Lewis provided this test program. */ { char foo[21]; char bar[21]; int i; for (i = 0; i < 4; i++) { char *a = foo + i; char *b = bar + i; strcpy (a, "--------01111111"); strcpy (b, "--------10000000"); if (memcmp (a, b, 16) >= 0) return 1; } return 0; } ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_memcmp_working=yes else ac_cv_func_memcmp_working=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5 $as_echo "$ac_cv_func_memcmp_working" >&6; } test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in *" memcmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;; esac #-------------------------------------------------------------------- # Some system like SunOS 4 and other BSD like systems have no memmove # (we assume they have bcopy instead). {The replacement define is in # compat/string.h} #-------------------------------------------------------------------- ac_fn_c_check_func "$LINENO" "memmove" "ac_cv_func_memmove" if test "x$ac_cv_func_memmove" = xyes; then : else $as_echo "#define NO_MEMMOVE 1" >>confdefs.h $as_echo "#define NO_STRING_H 1" >>confdefs.h fi #-------------------------------------------------------------------- # On some systems strstr is broken: it returns a pointer even even if # the original string is empty. #-------------------------------------------------------------------- ac_fn_c_check_func "$LINENO" "strstr" "ac_cv_func_strstr" if test "x$ac_cv_func_strstr" = xyes; then : tcl_ok=1 else tcl_ok=0 fi if test "$tcl_ok" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking proper strstr implementation" >&5 $as_echo_n "checking proper strstr implementation... " >&6; } if ${tcl_cv_strstr_unbroken+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : tcl_cv_strstr_unbroken=unknown else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main() { extern int strstr(); exit(strstr("\0test", "test") ? 1 : 0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : tcl_cv_strstr_unbroken=ok else tcl_cv_strstr_unbroken=broken fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strstr_unbroken" >&5 $as_echo "$tcl_cv_strstr_unbroken" >&6; } if test "$tcl_cv_strstr_unbroken" = "ok"; then tcl_ok=1 else tcl_ok=0 fi fi if test "$tcl_ok" = 0; then case " $LIBOBJS " in *" strstr.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strstr.$ac_objext" ;; esac USE_COMPAT=1 fi #-------------------------------------------------------------------- # Check for strtoul function. This is tricky because under some # versions of AIX strtoul returns an incorrect terminator # pointer for the string "0". #-------------------------------------------------------------------- ac_fn_c_check_func "$LINENO" "strtoul" "ac_cv_func_strtoul" if test "x$ac_cv_func_strtoul" = xyes; then : tcl_ok=1 else tcl_ok=0 fi if test "$tcl_ok" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking proper strtoul implementation" >&5 $as_echo_n "checking proper strtoul implementation... " >&6; } if ${tcl_cv_strtoul_unbroken+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : tcl_cv_strtoul_unbroken=unknown else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main() { extern int strtoul(); char *term, *string = "0"; exit(strtoul(string,&term,0) != 0 || term != string+1); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : tcl_cv_strtoul_unbroken=ok else tcl_cv_strtoul_unbroken=broken fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strtoul_unbroken" >&5 $as_echo "$tcl_cv_strtoul_unbroken" >&6; } if test "$tcl_cv_strtoul_unbroken" = "ok"; then tcl_ok=1 else tcl_ok=0 fi fi if test "$tcl_ok" = 0; then case " $LIBOBJS " in *" strtoul.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strtoul.$ac_objext" ;; esac USE_COMPAT=1 fi #-------------------------------------------------------------------- # Check for the strtod function. This is tricky because in some # versions of Linux strtod mis-parses strings starting with "+". #-------------------------------------------------------------------- ac_fn_c_check_func "$LINENO" "strtod" "ac_cv_func_strtod" if test "x$ac_cv_func_strtod" = xyes; then : tcl_ok=1 else tcl_ok=0 fi if test "$tcl_ok" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking proper strtod implementation" >&5 $as_echo_n "checking proper strtod implementation... " >&6; } if ${tcl_cv_strtod_unbroken+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : tcl_cv_strtod_unbroken=unknown else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main() { extern double strtod(); char *term, *string = " +69"; exit(strtod(string,&term) != 69 || term != string+4); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : tcl_cv_strtod_unbroken=ok else tcl_cv_strtod_unbroken=broken fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strtod_unbroken" >&5 $as_echo "$tcl_cv_strtod_unbroken" >&6; } if test "$tcl_cv_strtod_unbroken" = "ok"; then tcl_ok=1 else tcl_ok=0 fi fi if test "$tcl_ok" = 0; then case " $LIBOBJS " in *" strtod.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strtod.$ac_objext" ;; esac USE_COMPAT=1 fi #-------------------------------------------------------------------- # Under Solaris 2.4, strtod returns the wrong value for the # terminating character under some conditions. Check for this # and if the problem exists use a substitute procedure # "fixstrtod" that corrects the error. #-------------------------------------------------------------------- ac_fn_c_check_func "$LINENO" "strtod" "ac_cv_func_strtod" if test "x$ac_cv_func_strtod" = xyes; then : tcl_strtod=1 else tcl_strtod=0 fi if test "$tcl_strtod" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris2.4/Tru64 strtod bugs" >&5 $as_echo_n "checking for Solaris2.4/Tru64 strtod bugs... " >&6; } if ${tcl_cv_strtod_buggy+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : tcl_cv_strtod_buggy=buggy else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ extern double strtod(); int main() { char *infString="Inf", *nanString="NaN", *spaceString=" "; char *term; double value; value = strtod(infString, &term); if ((term != infString) && (term[-1] == 0)) { exit(1); } value = strtod(nanString, &term); if ((term != nanString) && (term[-1] == 0)) { exit(1); } value = strtod(spaceString, &term); if (term == (spaceString+1)) { exit(1); } exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : tcl_cv_strtod_buggy=ok else tcl_cv_strtod_buggy=buggy fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strtod_buggy" >&5 $as_echo "$tcl_cv_strtod_buggy" >&6; } if test "$tcl_cv_strtod_buggy" = buggy; then case " $LIBOBJS " in *" fixstrtod.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS fixstrtod.$ac_objext" ;; esac USE_COMPAT=1 $as_echo "#define strtod fixstrtod" >>confdefs.h fi fi #-------------------------------------------------------------------- # Check for various typedefs and provide substitutes if # they don't exist. #-------------------------------------------------------------------- ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" if test "x$ac_cv_type_mode_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define mode_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if ${ac_cv_type_uid_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then $as_echo "#define uid_t int" >>confdefs.h $as_echo "#define gid_t int" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5 $as_echo_n "checking for socklen_t... " >&6; } if ${tcl_cv_type_socklen_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { socklen_t foo; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_type_socklen_t=yes else tcl_cv_type_socklen_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_type_socklen_t" >&5 $as_echo "$tcl_cv_type_socklen_t" >&6; } if test $tcl_cv_type_socklen_t = no; then $as_echo "#define socklen_t int" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default" if test "x$ac_cv_type_intptr_t" = xyes; then : $as_echo "#define HAVE_INTPTR_T 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pointer-size signed integer type" >&5 $as_echo_n "checking for pointer-size signed integer type... " >&6; } if ${tcl_cv_intptr_t+:} false; then : $as_echo_n "(cached) " >&6 else for tcl_cv_intptr_t in "int" "long" "long long" none; do if test "$tcl_cv_intptr_t" != none; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_intptr_t))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_ok=yes else tcl_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$tcl_ok" = yes && break; fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_intptr_t" >&5 $as_echo "$tcl_cv_intptr_t" >&6; } if test "$tcl_cv_intptr_t" != none; then cat >>confdefs.h <<_ACEOF #define intptr_t $tcl_cv_intptr_t _ACEOF fi fi ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default" if test "x$ac_cv_type_uintptr_t" = xyes; then : $as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pointer-size unsigned integer type" >&5 $as_echo_n "checking for pointer-size unsigned integer type... " >&6; } if ${tcl_cv_uintptr_t+:} false; then : $as_echo_n "(cached) " >&6 else for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \ none; do if test "$tcl_cv_uintptr_t" != none; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_uintptr_t))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_ok=yes else tcl_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$tcl_ok" = yes && break; fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_uintptr_t" >&5 $as_echo "$tcl_cv_uintptr_t" >&6; } if test "$tcl_cv_uintptr_t" != none; then cat >>confdefs.h <<_ACEOF #define uintptr_t $tcl_cv_uintptr_t _ACEOF fi fi #-------------------------------------------------------------------- # If a system doesn't have an opendir function (man, that's old!) # then we have to supply a different version of dirent.h which # is compatible with the substitute version of opendir that's # provided. This version only works with V7-style directories. #-------------------------------------------------------------------- ac_fn_c_check_func "$LINENO" "opendir" "ac_cv_func_opendir" if test "x$ac_cv_func_opendir" = xyes; then : else $as_echo "#define USE_DIRENT2_H 1" >>confdefs.h fi #-------------------------------------------------------------------- # The check below checks whether defines the type # "union wait" correctly. It's needed because of weirdness in # HP-UX where "union wait" is defined in both the BSD and SYS-V # environments. Checking the usability of WIFEXITED seems to do # the trick. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking union wait" >&5 $as_echo_n "checking union wait... " >&6; } if ${tcl_cv_union_wait+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { union wait x; WIFEXITED(x); /* Generates compiler error if WIFEXITED * uses an int. */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_union_wait=yes else tcl_cv_union_wait=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_union_wait" >&5 $as_echo "$tcl_cv_union_wait" >&6; } if test $tcl_cv_union_wait = no; then $as_echo "#define NO_UNION_WAIT 1" >>confdefs.h fi #-------------------------------------------------------------------- # Check whether there is an strncasecmp function on this system. # This is a bit tricky because under SCO it's in -lsocket and # under Sequent Dynix it's in -linet. #-------------------------------------------------------------------- ac_fn_c_check_func "$LINENO" "strncasecmp" "ac_cv_func_strncasecmp" if test "x$ac_cv_func_strncasecmp" = xyes; then : tcl_ok=1 else tcl_ok=0 fi if test "$tcl_ok" = 0; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strncasecmp in -lsocket" >&5 $as_echo_n "checking for strncasecmp in -lsocket... " >&6; } if ${ac_cv_lib_socket_strncasecmp+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char strncasecmp (); int main () { return strncasecmp (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_strncasecmp=yes else ac_cv_lib_socket_strncasecmp=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_strncasecmp" >&5 $as_echo "$ac_cv_lib_socket_strncasecmp" >&6; } if test "x$ac_cv_lib_socket_strncasecmp" = xyes; then : tcl_ok=1 else tcl_ok=0 fi fi if test "$tcl_ok" = 0; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strncasecmp in -linet" >&5 $as_echo_n "checking for strncasecmp in -linet... " >&6; } if ${ac_cv_lib_inet_strncasecmp+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-linet $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char strncasecmp (); int main () { return strncasecmp (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_inet_strncasecmp=yes else ac_cv_lib_inet_strncasecmp=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_strncasecmp" >&5 $as_echo "$ac_cv_lib_inet_strncasecmp" >&6; } if test "x$ac_cv_lib_inet_strncasecmp" = xyes; then : tcl_ok=1 else tcl_ok=0 fi fi if test "$tcl_ok" = 0; then case " $LIBOBJS " in *" strncasecmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strncasecmp.$ac_objext" ;; esac USE_COMPAT=1 fi #-------------------------------------------------------------------- # The code below deals with several issues related to gettimeofday: # 1. Some systems don't provide a gettimeofday function at all # (set NO_GETTOD if this is the case). # 2. See if gettimeofday is declared in the header file. # if not, set the GETTOD_NOT_DECLARED flag so that tclPort.h can # declare it. #-------------------------------------------------------------------- ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" if test "x$ac_cv_func_gettimeofday" = xyes; then : else $as_echo "#define NO_GETTOD 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gettimeofday declaration" >&5 $as_echo_n "checking for gettimeofday declaration... " >&6; } if ${tcl_cv_grep_gettimeofday+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "gettimeofday" >/dev/null 2>&1; then : tcl_cv_grep_gettimeofday=present else tcl_cv_grep_gettimeofday=missing fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_grep_gettimeofday" >&5 $as_echo "$tcl_cv_grep_gettimeofday" >&6; } if test $tcl_cv_grep_gettimeofday = missing ; then $as_echo "#define GETTOD_NOT_DECLARED 1" >>confdefs.h fi #-------------------------------------------------------------------- # The following code checks to see whether it is possible to get # signed chars on this platform. This is needed in order to # properly generate sign-extended ints from character values. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5 $as_echo_n "checking whether char is unsigned... " >&6; } if ${ac_cv_c_char_unsigned+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(((char) -1) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_char_unsigned=no else ac_cv_c_char_unsigned=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_char_unsigned" >&5 $as_echo "$ac_cv_c_char_unsigned" >&6; } if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then $as_echo "#define __CHAR_UNSIGNED__ 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking signed char declarations" >&5 $as_echo_n "checking signed char declarations... " >&6; } if ${tcl_cv_char_signed+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { signed char *p; p = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_char_signed=yes else tcl_cv_char_signed=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_char_signed" >&5 $as_echo "$tcl_cv_char_signed" >&6; } if test $tcl_cv_char_signed = yes; then $as_echo "#define HAVE_SIGNED_CHAR 1" >>confdefs.h fi #-------------------------------------------------------------------- # Does putenv() copy or not? We need to know to avoid memory leaks. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a putenv() that copies the buffer" >&5 $as_echo_n "checking for a putenv() that copies the buffer... " >&6; } if ${tcl_cv_putenv_copy+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : tcl_cv_putenv_copy=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #define OURVAR "havecopy=yes" int main (int argc, char *argv[]) { char *foo, *bar; foo = (char *)strdup(OURVAR); putenv(foo); strcpy((char *)(strchr(foo, '=') + 1), "no"); bar = getenv("havecopy"); if (!strcmp(bar, "no")) { /* doesnt copy */ return 0; } else { /* does copy */ return 1; } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : tcl_cv_putenv_copy=no else tcl_cv_putenv_copy=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_putenv_copy" >&5 $as_echo "$tcl_cv_putenv_copy" >&6; } if test $tcl_cv_putenv_copy = yes; then $as_echo "#define HAVE_PUTENV_THAT_COPIES 1" >>confdefs.h fi #-------------------------------------------------------------------- # Check for support of nl_langinfo function #-------------------------------------------------------------------- # Check whether --enable-langinfo was given. if test "${enable_langinfo+set}" = set; then : enableval=$enable_langinfo; langinfo_ok=$enableval else langinfo_ok=yes fi HAVE_LANGINFO=0 if test "$langinfo_ok" = "yes"; then ac_fn_c_check_header_mongrel "$LINENO" "langinfo.h" "ac_cv_header_langinfo_h" "$ac_includes_default" if test "x$ac_cv_header_langinfo_h" = xyes; then : langinfo_ok=yes else langinfo_ok=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use nl_langinfo" >&5 $as_echo_n "checking whether to use nl_langinfo... " >&6; } if test "$langinfo_ok" = "yes"; then if ${tcl_cv_langinfo_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { nl_langinfo(CODESET); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_langinfo_h=yes else tcl_cv_langinfo_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_langinfo_h" >&5 $as_echo "$tcl_cv_langinfo_h" >&6; } if test $tcl_cv_langinfo_h = yes; then $as_echo "#define HAVE_LANGINFO 1" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: $langinfo_ok" >&5 $as_echo "$langinfo_ok" >&6; } fi #-------------------------------------------------------------------- # Check for support of chflags and mkstemps functions #-------------------------------------------------------------------- for ac_func in chflags mkstemps do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done #-------------------------------------------------------------------- # Check for support of isnan() function or macro #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking isnan" >&5 $as_echo_n "checking isnan... " >&6; } if ${tcl_cv_isnan+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { isnan(0.0); /* Generates an error if isnan is missing */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_isnan=yes else tcl_cv_isnan=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_isnan" >&5 $as_echo "$tcl_cv_isnan" >&6; } if test $tcl_cv_isnan = no; then $as_echo "#define NO_ISNAN 1" >>confdefs.h fi #-------------------------------------------------------------------- # Darwin specific API checks and defines #-------------------------------------------------------------------- if test "`uname -s`" = "Darwin" ; then for ac_func in getattrlist do : ac_fn_c_check_func "$LINENO" "getattrlist" "ac_cv_func_getattrlist" if test "x$ac_cv_func_getattrlist" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETATTRLIST 1 _ACEOF fi done for ac_header in copyfile.h do : ac_fn_c_check_header_mongrel "$LINENO" "copyfile.h" "ac_cv_header_copyfile_h" "$ac_includes_default" if test "x$ac_cv_header_copyfile_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_COPYFILE_H 1 _ACEOF fi done for ac_func in copyfile do : ac_fn_c_check_func "$LINENO" "copyfile" "ac_cv_func_copyfile" if test "x$ac_cv_func_copyfile" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_COPYFILE 1 _ACEOF fi done if test $tcl_corefoundation = yes; then for ac_header in libkern/OSAtomic.h do : ac_fn_c_check_header_mongrel "$LINENO" "libkern/OSAtomic.h" "ac_cv_header_libkern_OSAtomic_h" "$ac_includes_default" if test "x$ac_cv_header_libkern_OSAtomic_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBKERN_OSATOMIC_H 1 _ACEOF fi done for ac_func in OSSpinLockLock do : ac_fn_c_check_func "$LINENO" "OSSpinLockLock" "ac_cv_func_OSSpinLockLock" if test "x$ac_cv_func_OSSpinLockLock" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_OSSPINLOCKLOCK 1 _ACEOF fi done fi $as_echo "#define USE_VFORK 1" >>confdefs.h $as_echo "#define TCL_DEFAULT_ENCODING \"utf-8\"" >>confdefs.h $as_echo "#define TCL_LOAD_FROM_MEMORY 1" >>confdefs.h $as_echo "#define TCL_WIDE_CLICKS 1" >>confdefs.h for ac_header in AvailabilityMacros.h do : ac_fn_c_check_header_mongrel "$LINENO" "AvailabilityMacros.h" "ac_cv_header_AvailabilityMacros_h" "$ac_includes_default" if test "x$ac_cv_header_AvailabilityMacros_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_AVAILABILITYMACROS_H 1 _ACEOF fi done if test "$ac_cv_header_AvailabilityMacros_h" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if weak import is available" >&5 $as_echo_n "checking if weak import is available... " >&6; } if ${tcl_cv_cc_weak_import+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020 #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1020 #endif #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1020 #error MAC_OS_X_VERSION_MIN_REQUIRED < 1020 #endif int rand(void) __attribute__((weak_import)); int main () { rand(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_weak_import=yes else tcl_cv_cc_weak_import=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_weak_import" >&5 $as_echo "$tcl_cv_cc_weak_import" >&6; } if test $tcl_cv_cc_weak_import = yes; then $as_echo "#define HAVE_WEAK_IMPORT 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Darwin SUSv3 extensions are available" >&5 $as_echo_n "checking if Darwin SUSv3 extensions are available... " >&6; } if ${tcl_cv_cc_darwin_c_source+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050 #error __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050 #endif #elif MAC_OS_X_VERSION_MIN_REQUIRED < 1050 #error MAC_OS_X_VERSION_MIN_REQUIRED < 1050 #endif #define _DARWIN_C_SOURCE 1 #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_cc_darwin_c_source=yes else tcl_cv_cc_darwin_c_source=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_darwin_c_source" >&5 $as_echo "$tcl_cv_cc_darwin_c_source" >&6; } if test $tcl_cv_cc_darwin_c_source = yes; then $as_echo "#define _DARWIN_C_SOURCE 1" >>confdefs.h fi fi # Build .bundle dltest binaries in addition to .dylib DLTEST_LD='${CC} -bundle -Wl,-w ${CFLAGS} ${LDFLAGS}' DLTEST_SUFFIX=".bundle" else DLTEST_LD='${SHLIB_LD}' DLTEST_SUFFIX="" fi #-------------------------------------------------------------------- # Check for support of fts functions (readdir replacement) #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fts" >&5 $as_echo_n "checking for fts... " >&6; } if ${tcl_cv_api_fts+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { char*const p[2] = {"/", NULL}; FTS *f = fts_open(p, FTS_PHYSICAL|FTS_NOCHDIR|FTS_NOSTAT, NULL); FTSENT *e = fts_read(f); fts_close(f); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_api_fts=yes else tcl_cv_api_fts=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_api_fts" >&5 $as_echo "$tcl_cv_api_fts" >&6; } if test $tcl_cv_api_fts = yes; then $as_echo "#define HAVE_FTS 1" >>confdefs.h fi #-------------------------------------------------------------------- # The statements below check for systems where POSIX-style non-blocking # I/O (O_NONBLOCK) doesn't work or is unimplemented. On these systems # (mostly older ones), use the old BSD-style FIONBIO approach instead. #-------------------------------------------------------------------- for ac_header in sys/ioctl.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default" if test "x$ac_cv_header_sys_ioctl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_IOCTL_H 1 _ACEOF fi done for ac_header in sys/filio.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/filio.h" "ac_cv_header_sys_filio_h" "$ac_includes_default" if test "x$ac_cv_header_sys_filio_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_FILIO_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5 $as_echo_n "checking system version... " >&6; } if ${tcl_cv_sys_version+:} false; then : $as_echo_n "(cached) " >&6 else if test -f /usr/lib/NextStep/software_version; then tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 $as_echo "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else # Special check for weird MP-RAS system (uname returns weird # results, and the version is kept in special file). if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then tcl_cv_sys_version=MP-RAS-`awk '{print $3}' /etc/.relid` fi if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 $as_echo "$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version { $as_echo "$as_me:${as_lineno-$LINENO}: checking FIONBIO vs. O_NONBLOCK for nonblocking I/O" >&5 $as_echo_n "checking FIONBIO vs. O_NONBLOCK for nonblocking I/O... " >&6; } case $system in OSF*) $as_echo "#define USE_FIONBIO 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: FIONBIO" >&5 $as_echo "FIONBIO" >&6; } ;; SunOS-4*) $as_echo "#define USE_FIONBIO 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: FIONBIO" >&5 $as_echo "FIONBIO" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: O_NONBLOCK" >&5 $as_echo "O_NONBLOCK" >&6; } ;; esac #------------------------------------------------------------------------ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use dll unloading" >&5 $as_echo_n "checking whether to use dll unloading... " >&6; } # Check whether --enable-dll-unloading was given. if test "${enable_dll_unloading+set}" = set; then : enableval=$enable_dll_unloading; tcl_ok=$enableval else tcl_ok=yes fi if test $tcl_ok = yes; then $as_echo "#define TCL_UNLOAD_DLLS 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_ok" >&5 $as_echo "$tcl_ok" >&6; } #------------------------------------------------------------------------ # Check whether the timezone data is supplied by the OS or has # to be installed by Tcl. The default is autodetection, but can # be overriden on the configure command line either way. #------------------------------------------------------------------------ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for timezone data" >&5 $as_echo_n "checking for timezone data... " >&6; } # Check whether --with-tzdata was given. if test "${with_tzdata+set}" = set; then : withval=$with_tzdata; tcl_ok=$withval else tcl_ok=auto fi # # Any directories that get added here must also be added to the # search path in ::tcl::clock::Initialize (library/clock.tcl). # case $tcl_ok in no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: supplied by OS vendor" >&5 $as_echo "supplied by OS vendor" >&6; } ;; yes) # nothing to do here ;; auto*) if ${tcl_cv_dir_zoneinfo+:} false; then : $as_echo_n "(cached) " >&6 else for dir in /usr/share/zoneinfo \ /usr/share/lib/zoneinfo \ /usr/lib/zoneinfo do if test -f $dir/UTC -o -f $dir/GMT then tcl_cv_dir_zoneinfo="$dir" break fi done fi if test -n "$tcl_cv_dir_zoneinfo"; then tcl_ok=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dir" >&5 $as_echo "$dir" >&6; } else tcl_ok=yes fi ;; *) as_fn_error $? "invalid argument: $tcl_ok" "$LINENO" 5 ;; esac if test $tcl_ok = yes then { $as_echo "$as_me:${as_lineno-$LINENO}: result: supplied by Tcl" >&5 $as_echo "supplied by Tcl" >&6; } INSTALL_TZDATA=install-tzdata fi #-------------------------------------------------------------------- # DTrace support #-------------------------------------------------------------------- # Check whether --enable-dtrace was given. if test "${enable_dtrace+set}" = set; then : enableval=$enable_dtrace; tcl_ok=$enableval else tcl_ok=no fi if test $tcl_ok = yes; then ac_fn_c_check_header_mongrel "$LINENO" "sys/sdt.h" "ac_cv_header_sys_sdt_h" "$ac_includes_default" if test "x$ac_cv_header_sys_sdt_h" = xyes; then : tcl_ok=yes else tcl_ok=no fi fi if test $tcl_ok = yes; then # Extract the first word of "dtrace", so it can be a program name with args. set dummy dtrace; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_DTRACE+:} false; then : $as_echo_n "(cached) " >&6 else case $DTRACE in [\\/]* | ?:[\\/]*) ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:/usr/sbin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi DTRACE=$ac_cv_path_DTRACE if test -n "$DTRACE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 $as_echo "$DTRACE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$ac_cv_path_DTRACE" && tcl_ok=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable DTrace support" >&5 $as_echo_n "checking whether to enable DTrace support... " >&6; } MAKEFILE_SHELL='/bin/sh' if test $tcl_ok = yes; then $as_echo "#define USE_DTRACE 1" >>confdefs.h DTRACE_SRC="\${DTRACE_SRC}" DTRACE_HDR="\${DTRACE_HDR}" if test "`uname -s`" != "Darwin" ; then DTRACE_OBJ="\${DTRACE_OBJ}" if test "`uname -s`" = "SunOS" -a "$SHARED_BUILD" = "0" ; then # Need to create an intermediate object file to ensure tclDTrace.o # gets included when linking against the static tcl library. STLIB_LD='stlib_ld () { /usr/ccs/bin/ld -r -o $${1%.a}.o "$${@:2}" && '"${STLIB_LD}"' $${1} $${1%.a}.o ; } && stlib_ld' MAKEFILE_SHELL='/bin/bash' # Force use of Sun ar and ranlib, the GNU versions choke on # tclDTrace.o and the combined object file above. AR='/usr/ccs/bin/ar' RANLIB='/usr/ccs/bin/ranlib' fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_ok" >&5 $as_echo "$tcl_ok" >&6; } #-------------------------------------------------------------------- # The check below checks whether the cpuid instruction is usable. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the cpuid instruction is usable" >&5 $as_echo_n "checking whether the cpuid instruction is usable... " >&6; } if ${tcl_cv_cpuid+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { int index,regsPtr[4]; __asm__ __volatile__("mov %%ebx, %%edi \n\t" "cpuid \n\t" "mov %%ebx, %%esi \n\t" "mov %%edi, %%ebx \n\t" : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3]) : "a"(index) : "edi"); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cpuid=yes else tcl_cv_cpuid=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cpuid" >&5 $as_echo "$tcl_cv_cpuid" >&6; } if test $tcl_cv_cpuid = yes; then $as_echo "#define HAVE_CPUID 1" >>confdefs.h fi #-------------------------------------------------------------------- # The statements below define a collection of symbols related to # building libtcl as a shared library instead of a static library. #-------------------------------------------------------------------- TCL_UNSHARED_LIB_SUFFIX=${UNSHARED_LIB_SUFFIX} TCL_SHARED_LIB_SUFFIX=${SHARED_LIB_SUFFIX} eval "TCL_LIB_FILE=libtcl${LIB_SUFFIX}" # tclConfig.sh needs a version of the _LIB_SUFFIX that has been eval'ed # since on some platforms TCL_LIB_FILE contains shell escapes. # (See also: TCL_TRIM_DOTS). eval "TCL_LIB_FILE=${TCL_LIB_FILE}" TCL_LIBRARY='$(prefix)/lib/tcl$(VERSION)' PRIVATE_INCLUDE_DIR='$(includedir)' HTML_DIR='$(DISTDIR)/html' # Note: in the following variable, it's important to use the absolute # path name of the Tcl directory rather than "..": this is because # AIX remembers this path and will attempt to use it at run-time to look # up the Tcl library. if test "`uname -s`" = "Darwin" ; then if test "`uname -s`" = "Darwin" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to package libraries" >&5 $as_echo_n "checking how to package libraries... " >&6; } # Check whether --enable-framework was given. if test "${enable_framework+set}" = set; then : enableval=$enable_framework; enable_framework=$enableval else enable_framework=no fi if test $enable_framework = yes; then if test $SHARED_BUILD = 0; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Frameworks can only be built if --enable-shared is yes" >&5 $as_echo "$as_me: WARNING: Frameworks can only be built if --enable-shared is yes" >&2;} enable_framework=no fi if test $tcl_corefoundation = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Frameworks can only be used when CoreFoundation is available" >&5 $as_echo "$as_me: WARNING: Frameworks can only be used when CoreFoundation is available" >&2;} enable_framework=no fi fi if test $enable_framework = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: framework" >&5 $as_echo "framework" >&6; } FRAMEWORK_BUILD=1 else if test $SHARED_BUILD = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: shared library" >&5 $as_echo "shared library" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: static library" >&5 $as_echo "static library" >&6; } fi FRAMEWORK_BUILD=0 fi fi TCL_SHLIB_LD_EXTRAS="-compatibility_version ${TCL_VERSION} -current_version ${TCL_VERSION}`echo ${TCL_PATCH_LEVEL} | awk '{match($0, "\\\.[0-9]+"); print substr($0,RSTART,RLENGTH)}'`" TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -install_name "${DYLIB_INSTALL_DIR}"/${TCL_LIB_FILE}' echo "$LDFLAGS " | grep -q -- '-prebind ' && TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -seg1addr 0xa000000' TCL_SHLIB_LD_EXTRAS="${TCL_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tcl-Info.plist' EXTRA_TCLSH_LIBS='-sectcreate __TEXT __info_plist Tclsh-Info.plist' EXTRA_APP_CC_SWITCHES='-mdynamic-no-pic' ac_config_files="$ac_config_files Tcl-Info.plist:../macosx/Tcl-Info.plist.in Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in" TCL_YEAR="`date +%Y`" fi if test "$FRAMEWORK_BUILD" = "1" ; then $as_echo "#define TCL_FRAMEWORK 1" >>confdefs.h # Construct a fake local framework structure to make linking with # '-framework Tcl' and running of tcltest work ac_config_commands="$ac_config_commands Tcl.framework" LD_LIBRARY_PATH_VAR="DYLD_FRAMEWORK_PATH" # default install directory for bundled packages if test "${libdir}" = '${exec_prefix}/lib' -o "`basename ${libdir}`" = 'Frameworks'; then PACKAGE_DIR="/Library/Tcl" else PACKAGE_DIR="$libdir" fi if test "${libdir}" = '${exec_prefix}/lib'; then # override libdir default libdir="/Library/Frameworks" fi TCL_LIB_FILE="Tcl" TCL_LIB_FLAG="-framework Tcl" TCL_BUILD_LIB_SPEC="-F`pwd | sed -e 's/ /\\\\ /g'` -framework Tcl" TCL_LIB_SPEC="-F${libdir} -framework Tcl" libdir="${libdir}/Tcl.framework/Versions/\${VERSION}" TCL_LIBRARY="${libdir}/Resources/Scripts" includedir="${libdir}/Headers" PRIVATE_INCLUDE_DIR="${libdir}/PrivateHeaders" HTML_DIR="${libdir}/Resources/Documentation/Reference/Tcl" EXTRA_INSTALL="install-private-headers html-tcl" EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TclTOC.html' EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tcl-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"' EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"' EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tcl.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tclConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."' # Don't use AC_DEFINE for the following as the framework version define # needs to go into the Makefile even when using autoheader, so that we # can pick up a potential make override of VERSION. Also, don't put this # into CFLAGS as it should not go into tclConfig.sh EXTRA_CC_SWITCHES='-DTCL_FRAMEWORK_VERSION=\"$(VERSION)\"' else # libdir must be a fully qualified path and not ${exec_prefix}/lib eval libdir="$libdir" # default install directory for bundled packages PACKAGE_DIR="$libdir" if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then TCL_LIB_FLAG="-ltcl${TCL_VERSION}" else TCL_LIB_FLAG="-ltcl`echo ${TCL_VERSION} | tr -d .`" fi TCL_BUILD_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_LIB_FLAG}" TCL_LIB_SPEC="-L${libdir} ${TCL_LIB_FLAG}" fi VERSION='${VERSION}' eval "CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}" eval "CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}" VERSION=${TCL_VERSION} #-------------------------------------------------------------------- # The statements below define the symbol TCL_PACKAGE_PATH, which # gives a list of directories that may contain packages. The list # consists of one directory for machine-dependent binaries and # another for platform-independent scripts. #-------------------------------------------------------------------- if test "$FRAMEWORK_BUILD" = "1" ; then test -z "$TCL_PACKAGE_PATH" && \ TCL_PACKAGE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl ~/Library/Frameworks /Library/Frameworks /System/Library/Frameworks" test -z "$TCL_MODULE_PATH" && \ TCL_MODULE_PATH="~/Library/Tcl /Library/Tcl /System/Library/Tcl" elif test "$prefix/lib" != "$libdir"; then TCL_PACKAGE_PATH="${libdir} ${prefix}/lib ${TCL_PACKAGE_PATH}" else TCL_PACKAGE_PATH="${prefix}/lib ${TCL_PACKAGE_PATH}" fi #-------------------------------------------------------------------- # The statements below define various symbols relating to Tcl # stub support. #-------------------------------------------------------------------- # Replace ${VERSION} with contents of ${TCL_VERSION} # double-eval to account for TCL_TRIM_DOTS. # eval "TCL_STUB_LIB_FILE=libtclstub${TCL_UNSHARED_LIB_SUFFIX}" eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" eval "TCL_STUB_LIB_DIR=${libdir}" if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then TCL_STUB_LIB_FLAG="-ltclstub${TCL_VERSION}" else TCL_STUB_LIB_FLAG="-ltclstub`echo ${TCL_VERSION} | tr -d .`" fi TCL_BUILD_STUB_LIB_SPEC="-L`pwd | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" TCL_STUB_LIB_SPEC="-L${TCL_STUB_LIB_DIR} ${TCL_STUB_LIB_FLAG}" TCL_BUILD_STUB_LIB_PATH="`pwd`/${TCL_STUB_LIB_FILE}" TCL_STUB_LIB_PATH="${TCL_STUB_LIB_DIR}/${TCL_STUB_LIB_FILE}" # Install time header dir can be set via --includedir eval "TCL_INCLUDE_SPEC=\"-I${includedir}\"" #------------------------------------------------------------------------ # tclConfig.sh refers to this by a different name #------------------------------------------------------------------------ TCL_SHARED_BUILD=${SHARED_BUILD} ac_config_files="$ac_config_files Makefile:../unix/Makefile.in dltest/Makefile:../unix/dltest/Makefile.in tclConfig.sh:../unix/tclConfig.sh.in tcl.pc:../unix/tcl.pc.in" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H DEFS="-DHAVE_TCL_CONFIG_H -imacros tclConfig.h" CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS="" : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by tcl $as_me 8.6, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ tcl config.status 8.6 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # VERSION=${TCL_VERSION} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "tclConfig.h") CONFIG_HEADERS="$CONFIG_HEADERS tclConfig.h:../unix/tclConfig.h.in" ;; "Tcl-Info.plist") CONFIG_FILES="$CONFIG_FILES Tcl-Info.plist:../macosx/Tcl-Info.plist.in" ;; "Tclsh-Info.plist") CONFIG_FILES="$CONFIG_FILES Tclsh-Info.plist:../macosx/Tclsh-Info.plist.in" ;; "Tcl.framework") CONFIG_COMMANDS="$CONFIG_COMMANDS Tcl.framework" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile:../unix/Makefile.in" ;; "dltest/Makefile") CONFIG_FILES="$CONFIG_FILES dltest/Makefile:../unix/dltest/Makefile.in" ;; "tclConfig.sh") CONFIG_FILES="$CONFIG_FILES tclConfig.sh:../unix/tclConfig.sh.in" ;; "tcl.pc") CONFIG_FILES="$CONFIG_FILES tcl.pc:../unix/tcl.pc.in" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "Tcl.framework":C) n=Tcl && f=$n.framework && v=Versions/$VERSION && rm -rf $f && mkdir -p $f/$v/Resources && ln -s $v/$n $v/Resources $f && ln -s ../../../$n $f/$v && ln -s ../../../../$n-Info.plist $f/$v/Resources/Info.plist && unset n f v ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi tcl8.6.5/macosx/configure.ac0000644000175000017500000000065612663660066015357 0ustar sergeisergei#! /bin/bash -norc dnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run during Tcl installation dnl to configure the system for the local environment. dnl Ensure that the config (auto)headers support is used, then just dnl include the configure sources from ../unix: m4_include(../unix/aclocal.m4) m4_define(SC_USE_CONFIG_HEADERS) m4_include(../unix/configure.in) tcl8.6.5/macosx/Tcl-Release.xcconfig0000644000175000017500000000125612663653210016701 0ustar sergeisergei// // Tcl-Release.xcconfig -- // // This file contains the Xcode build settings for all Release // project configurations in Tcl.xcodeproj. // // Copyright (c) 2007 Daniel A. Steffen // // See the file "license.terms" for information on usage and redistribution // of this file, and for a DISCLAIMER OF ALL WARRANTIES. #include "Tcl-Common.xcconfig" DEBUG_INFORMATION_FORMAT = dwarf-with-dsym DEAD_CODE_STRIPPING = YES DEPLOYMENT_POSTPROCESSING = YES GCC_OPTIMIZATION_LEVEL = s GCC_PREPROCESSOR_DEFINITIONS = NDEBUG $(TCL_DEFS) $(GCC_PREPROCESSOR_DEFINITIONS) CONFIGURE_ARGS = --disable-symbols $(TCL_CONFIGURE_ARGS) $(CONFIGURE_ARGS) MAKE_TARGET = deploy tcl8.6.5/macosx/Tcl.xcode/0000755000175000017500000000000012665173607014707 5ustar sergeisergeitcl8.6.5/macosx/Tcl.xcode/project.pbxproj0000644000175000017500000066747012663660066020005 0ustar sergeisergei// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 45; objects = { /* Begin PBXBuildFile section */ F90509300913A72400327603 /* tclAppInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445508F272B9004A47F5 /* tclAppInit.c */; settings = {COMPILER_FLAGS = "-DTCL_TEST -DTCL_BUILDTIME_LIBRARY=\\\"$(TCL_SRCROOT)/library\\\""; }; }; F93599B30DF1F75400E04F67 /* tclOO.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B20DF1F75400E04F67 /* tclOO.c */; }; F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B60DF1F76100E04F67 /* tclOOBasic.c */; }; F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599B80DF1F76600E04F67 /* tclOOCall.c */; }; F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */; }; F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599BD0DF1F77400E04F67 /* tclOOInfo.c */; }; F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C10DF1F78300E04F67 /* tclOOMethod.c */; }; F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C30DF1F78800E04F67 /* tclOOStubInit.c */; }; F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */; }; F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */ = {isa = PBXBuildFile; fileRef = F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */; }; F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96437C90EF0D4B2003F468E /* tclZlib.c */; }; F96437E70EF0D652003F468E /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F96437E60EF0D652003F468E /* libz.dylib */; }; F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F966C07408F2820D005CB29B /* CoreFoundation.framework */; }; F96D456F08F272BB004A47F5 /* regcomp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED008F272A7004A47F5 /* regcomp.c */; }; F96D457208F272BB004A47F5 /* regerror.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED308F272A7004A47F5 /* regerror.c */; }; F96D457508F272BB004A47F5 /* regexec.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED608F272A7004A47F5 /* regexec.c */; }; F96D457608F272BB004A47F5 /* regfree.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3ED708F272A7004A47F5 /* regfree.c */; }; F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDC08F272A7004A47F5 /* tclAlloc.c */; settings = {COMPILER_FLAGS = "-DUSE_TCLALLOC=0"; }; }; F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDD08F272A7004A47F5 /* tclAsync.c */; }; F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDE08F272A7004A47F5 /* tclBasic.c */; }; F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EDF08F272A7004A47F5 /* tclBinary.c */; }; F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE008F272A7004A47F5 /* tclCkalloc.c */; }; F96D458008F272BC004A47F5 /* tclClock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE108F272A7004A47F5 /* tclClock.c */; }; F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE208F272A7004A47F5 /* tclCmdAH.c */; }; F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE308F272A7004A47F5 /* tclCmdIL.c */; }; F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */; }; F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE508F272A7004A47F5 /* tclCompCmds.c */; }; F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE608F272A7004A47F5 /* tclCompExpr.c */; }; F96D458608F272BC004A47F5 /* tclCompile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE708F272A7004A47F5 /* tclCompile.c */; }; F96D458808F272BC004A47F5 /* tclConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EE908F272A7004A47F5 /* tclConfig.c */; }; F96D458908F272BC004A47F5 /* tclDate.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEA08F272A7004A47F5 /* tclDate.c */; }; F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEC08F272A7004A47F5 /* tclDictObj.c */; }; F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EED08F272A7004A47F5 /* tclEncoding.c */; }; F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEE08F272A7004A47F5 /* tclEnv.c */; }; F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EEF08F272A7004A47F5 /* tclEvent.c */; }; F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF008F272A7004A47F5 /* tclExecute.c */; }; F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF108F272A7004A47F5 /* tclFCmd.c */; }; F96D459108F272BC004A47F5 /* tclFileName.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF208F272A7004A47F5 /* tclFileName.c */; }; F96D459308F272BC004A47F5 /* tclGet.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF408F272A7004A47F5 /* tclGet.c */; }; F96D459508F272BC004A47F5 /* tclHash.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF608F272A7004A47F5 /* tclHash.c */; }; F96D459608F272BC004A47F5 /* tclHistory.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF708F272A7004A47F5 /* tclHistory.c */; }; F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EF808F272A7004A47F5 /* tclIndexObj.c */; }; F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFC08F272A7004A47F5 /* tclInterp.c */; }; F96D459D08F272BC004A47F5 /* tclIO.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3EFE08F272A7004A47F5 /* tclIO.c */; }; F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0008F272A7004A47F5 /* tclIOCmd.c */; }; F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0108F272A7004A47F5 /* tclIOGT.c */; }; F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0208F272A7004A47F5 /* tclIORChan.c */; }; F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0308F272A7004A47F5 /* tclIOSock.c */; }; F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0408F272A7004A47F5 /* tclIOUtil.c */; }; F96D45A408F272BC004A47F5 /* tclLink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0508F272A7004A47F5 /* tclLink.c */; }; F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0608F272A7004A47F5 /* tclListObj.c */; }; F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0708F272A7004A47F5 /* tclLiteral.c */; }; F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0808F272A7004A47F5 /* tclLoad.c */; }; F96D45A908F272BC004A47F5 /* tclMain.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0A08F272A7004A47F5 /* tclMain.c */; }; F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0B08F272A7004A47F5 /* tclNamesp.c */; }; F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0C08F272A7004A47F5 /* tclNotify.c */; }; F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0D08F272A7004A47F5 /* tclObj.c */; }; F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0E08F272A7004A47F5 /* tclPanic.c */; }; F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F0F08F272A7004A47F5 /* tclParse.c */; }; F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1108F272A7004A47F5 /* tclPathObj.c */; }; F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1208F272A7004A47F5 /* tclPipe.c */; }; F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1308F272A7004A47F5 /* tclPkg.c */; }; F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */; settings = {COMPILER_FLAGS = "-DCFG_INSTALL_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_INSTALL_BINDIR=\\\"$(BINDIR)\\\" -DCFG_INSTALL_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_INSTALL_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_INSTALL_DOCDIR=\\\"$(MANDIR)\\\" -DCFG_RUNTIME_LIBDIR=\\\"$(LIBDIR)\\\" -DCFG_RUNTIME_BINDIR=\\\"$(BINDIR)\\\" -DCFG_RUNTIME_SCRDIR=\\\"$(TCL_LIBRARY)\\\" -DCFG_RUNTIME_INCDIR=\\\"$(INCLUDEDIR)\\\" -DCFG_RUNTIME_DOCDIR=\\\"$(MANDIR)\\\""; }; }; F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1708F272A7004A47F5 /* tclPosixStr.c */; }; F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1808F272A7004A47F5 /* tclPreserve.c */; }; F96D45B808F272BC004A47F5 /* tclProc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1908F272A7004A47F5 /* tclProc.c */; }; F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1A08F272A7004A47F5 /* tclRegexp.c */; }; F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1C08F272A7004A47F5 /* tclResolve.c */; }; F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1D08F272A7004A47F5 /* tclResult.c */; }; F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1E08F272A7004A47F5 /* tclScan.c */; }; F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F1F08F272A7004A47F5 /* tclStringObj.c */; }; F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2408F272A7004A47F5 /* tclStrToD.c */; }; F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2508F272A7004A47F5 /* tclStubInit.c */; }; F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2608F272A7004A47F5 /* tclStubLib.c */; }; F96D45C608F272BC004A47F5 /* tclTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2708F272A7004A47F5 /* tclTest.c */; }; F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2808F272A7004A47F5 /* tclTestObj.c */; }; F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */; }; F96D45C908F272BC004A47F5 /* tclThread.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2A08F272A7004A47F5 /* tclThread.c */; }; F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */; }; F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */; }; F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */; }; F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */; }; F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F2F08F272A7004A47F5 /* tclTimer.c */; }; F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */; }; F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3208F272A7004A47F5 /* tclTrace.c */; }; F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3408F272A7004A47F5 /* tclUtf.c */; }; F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3508F272A7004A47F5 /* tclUtil.c */; }; F96D45D508F272BC004A47F5 /* tclVar.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D3F3608F272A7004A47F5 /* tclVar.c */; }; F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */; }; F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */; }; F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426908F272B3004A47F5 /* bn_mp_add.c */; }; F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */; }; F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */; }; F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426E08F272B3004A47F5 /* bn_mp_clear.c */; }; F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */; }; F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427008F272B3004A47F5 /* bn_mp_cmp.c */; }; F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */; }; F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_cnt_lsb.c */; }; F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427408F272B3004A47F5 /* bn_mp_copy.c */; }; F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */; }; F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427608F272B3004A47F5 /* bn_mp_div.c */; }; F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427708F272B3004A47F5 /* bn_mp_div_2.c */; }; F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */; }; F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_mp_div_3.c */; }; F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */; }; F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427E08F272B3004A47F5 /* bn_mp_exch.c */; }; F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428708F272B3004A47F5 /* bn_mp_grow.c */; }; F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428808F272B3004A47F5 /* bn_mp_init.c */; }; F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */; }; F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */; }; F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */; }; F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */; }; F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */; }; F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */; }; F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429508F272B3004A47F5 /* bn_mp_lshd.c */; }; F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429608F272B3004A47F5 /* bn_mp_mod.c */; }; F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */; }; F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429C08F272B3004A47F5 /* bn_mp_mul.c */; }; F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */; }; F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */; }; F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */; }; F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */; }; F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */; }; F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */; }; F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */; }; F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BA08F272B3004A47F5 /* bn_mp_set.c */; }; F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */; }; F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C108F272B3004A47F5 /* bn_mp_sub.c */; }; F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */; }; F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */; }; F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */; }; F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */; }; F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */; }; F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D008F272B3004A47F5 /* bn_reverse.c */; }; F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */; }; F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */; }; F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */; }; F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */; }; F96D495508F272C3004A47F5 /* bncore.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42D708F272B3004A47F5 /* bncore.c */; }; F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */; }; F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */; }; F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */; }; F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445B08F272B9004A47F5 /* tclLoadDyld.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; }; F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D445F08F272B9004A47F5 /* tclUnixChan.c */; }; F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446008F272B9004A47F5 /* tclUnixEvent.c */; }; F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446108F272B9004A47F5 /* tclUnixFCmd.c */; }; F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446208F272B9004A47F5 /* tclUnixFile.c */; }; F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446308F272B9004A47F5 /* tclUnixInit.c */; settings = {COMPILER_FLAGS = "-DTCL_LIBRARY=\\\"$(TCL_LIBRARY)\\\" -DTCL_PACKAGE_PATH=\\\"$(TCL_PACKAGE_PATH)\\\""; }; }; F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446408F272B9004A47F5 /* tclUnixNotfy.c */; }; F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446508F272B9004A47F5 /* tclUnixPipe.c */; }; F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446708F272B9004A47F5 /* tclUnixSock.c */; }; F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446808F272B9004A47F5 /* tclUnixTest.c */; }; F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446908F272B9004A47F5 /* tclUnixThrd.c */; }; F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D446B08F272B9004A47F5 /* tclUnixTime.c */; }; F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */; }; F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A208F272B3004A47F5 /* bn_mp_neg.c */; }; F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */; }; F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D426C08F272B3004A47F5 /* bn_mp_and.c */; }; F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */; }; F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */; }; F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42A308F272B3004A47F5 /* bn_mp_or.c */; }; F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */; }; F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */; }; F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */; }; F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */; }; F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */ = {isa = PBXBuildFile; fileRef = F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */; }; F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */ = {isa = PBXBuildFile; fileRef = F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ F97258D20A868C6F00096C78 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 8DD76FA90486AB0100D96B5E; remoteInfo = tcltest; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 8DD76FB20486AB0100D96B5E /* tcltest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tcltest; sourceTree = BUILT_PRODUCTS_DIR; }; F915432A0EF201CF0032D1E8 /* zlib.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = zlib.test; sourceTree = ""; }; F915432D0EF201EE0032D1E8 /* zlib.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = zlib.n; sourceTree = ""; }; F9183E640EFC80CD0030B814 /* throw.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = throw.n; sourceTree = ""; }; F9183E650EFC80D70030B814 /* try.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = try.n; sourceTree = ""; }; F9183E6A0EFC81560030B814 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F9183E8F0EFC817B0030B814 /* tdbc */ = {isa = PBXFileReference; lastKnownFileType = folder; path = tdbc; sourceTree = ""; }; F91DC23C0E44C51B002CB8D1 /* nre.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = nre.test; sourceTree = ""; }; F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "Tclsh-Info.plist.in"; sourceTree = ""; }; F92D7F100DE777240033A13A /* tsdPerf.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tsdPerf.tcl; sourceTree = ""; }; F93599B20DF1F75400E04F67 /* tclOO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOO.c; sourceTree = ""; }; F93599B40DF1F75900E04F67 /* tclOO.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclOO.decls; sourceTree = ""; }; F93599B50DF1F75D00E04F67 /* tclOO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOO.h; sourceTree = ""; }; F93599B60DF1F76100E04F67 /* tclOOBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOBasic.c; sourceTree = ""; }; F93599B80DF1F76600E04F67 /* tclOOCall.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOCall.c; sourceTree = ""; }; F93599BA0DF1F76A00E04F67 /* tclOODecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOODecls.h; sourceTree = ""; }; F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOODefineCmds.c; sourceTree = ""; }; F93599BD0DF1F77400E04F67 /* tclOOInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOInfo.c; sourceTree = ""; }; F93599BF0DF1F77900E04F67 /* tclOOInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOInt.h; sourceTree = ""; }; F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclOOIntDecls.h; sourceTree = ""; }; F93599C10DF1F78300E04F67 /* tclOOMethod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOMethod.c; sourceTree = ""; }; F93599C30DF1F78800E04F67 /* tclOOStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubInit.c; sourceTree = ""; }; F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclOOStubLib.c; sourceTree = ""; }; F93599C80DF1F81900E04F67 /* oo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = oo.test; sourceTree = ""; }; F93599CF0DF1F87F00E04F67 /* Class.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Class.3; sourceTree = ""; }; F93599D00DF1F89E00E04F67 /* class.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = class.n; sourceTree = ""; }; F93599D20DF1F8DF00E04F67 /* copy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = copy.n; sourceTree = ""; }; F93599D30DF1F8F500E04F67 /* define.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = define.n; sourceTree = ""; }; F93599D40DF1F91900E04F67 /* Method.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Method.3; sourceTree = ""; }; F93599D50DF1F93700E04F67 /* my.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = my.n; sourceTree = ""; }; F93599D60DF1F95000E04F67 /* next.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = next.n; sourceTree = ""; }; F93599D70DF1F96800E04F67 /* object.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = object.n; sourceTree = ""; }; F93599D80DF1F98300E04F67 /* self.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = self.n; sourceTree = ""; }; F946FB8B0FBE3AED00CD6495 /* itcl */ = {isa = PBXFileReference; lastKnownFileType = folder; path = itcl; sourceTree = ""; }; F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORTrans.c; sourceTree = ""; }; F95FAFF90B34F1130072E431 /* macOSXLoad.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXLoad.test; sourceTree = ""; }; F96437C90EF0D4B2003F468E /* tclZlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclZlib.c; sourceTree = ""; }; F96437E60EF0D652003F468E /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = ""; }; F966C07408F2820D005CB29B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; F96D3DFA08F272A4004A47F5 /* ChangeLog */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = ChangeLog; sourceTree = ""; }; F96D3DFB08F272A4004A47F5 /* changes */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes; sourceTree = ""; }; F96D3DFD08F272A4004A47F5 /* Access.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Access.3; sourceTree = ""; }; F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AddErrInfo.3; sourceTree = ""; }; F96D3DFF08F272A4004A47F5 /* after.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = after.n; sourceTree = ""; }; F96D3E0008F272A4004A47F5 /* Alloc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Alloc.3; sourceTree = ""; }; F96D3E0108F272A4004A47F5 /* AllowExc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AllowExc.3; sourceTree = ""; }; F96D3E0208F272A4004A47F5 /* append.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = append.n; sourceTree = ""; }; F96D3E0308F272A4004A47F5 /* AppInit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AppInit.3; sourceTree = ""; }; F96D3E0408F272A5004A47F5 /* array.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = array.n; sourceTree = ""; }; F96D3E0508F272A5004A47F5 /* AssocData.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = AssocData.3; sourceTree = ""; }; F96D3E0608F272A5004A47F5 /* Async.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Async.3; sourceTree = ""; }; F96D3E0708F272A5004A47F5 /* BackgdErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BackgdErr.3; sourceTree = ""; }; F96D3E0808F272A5004A47F5 /* Backslash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Backslash.3; sourceTree = ""; }; F96D3E0908F272A5004A47F5 /* bgerror.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = bgerror.n; sourceTree = ""; }; F96D3E0A08F272A5004A47F5 /* binary.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = binary.n; sourceTree = ""; }; F96D3E0B08F272A5004A47F5 /* BoolObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = BoolObj.3; sourceTree = ""; }; F96D3E0C08F272A5004A47F5 /* break.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = break.n; sourceTree = ""; }; F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ByteArrObj.3; sourceTree = ""; }; F96D3E0E08F272A5004A47F5 /* CallDel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CallDel.3; sourceTree = ""; }; F96D3E0F08F272A5004A47F5 /* case.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = case.n; sourceTree = ""; }; F96D3E1008F272A5004A47F5 /* catch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = catch.n; sourceTree = ""; }; F96D3E1108F272A5004A47F5 /* cd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = cd.n; sourceTree = ""; }; F96D3E1208F272A5004A47F5 /* chan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = chan.n; sourceTree = ""; }; F96D3E1308F272A5004A47F5 /* ChnlStack.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ChnlStack.3; sourceTree = ""; }; F96D3E1408F272A5004A47F5 /* clock.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = clock.n; sourceTree = ""; }; F96D3E1508F272A5004A47F5 /* close.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = close.n; sourceTree = ""; }; F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CmdCmplt.3; sourceTree = ""; }; F96D3E1708F272A5004A47F5 /* Concat.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Concat.3; sourceTree = ""; }; F96D3E1808F272A5004A47F5 /* concat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = concat.n; sourceTree = ""; }; F96D3E1908F272A5004A47F5 /* continue.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = continue.n; sourceTree = ""; }; F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChannel.3; sourceTree = ""; }; F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtChnlHdlr.3; sourceTree = ""; }; F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCloseHdlr.3; sourceTree = ""; }; F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtCommand.3; sourceTree = ""; }; F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtFileHdlr.3; sourceTree = ""; }; F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = ""; }; F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = ""; }; F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = ""; }; F96D3E2208F272A5004A47F5 /* CrtSlave.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSlave.3; sourceTree = ""; }; F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = ""; }; F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = ""; }; F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = ""; }; F96D3E2608F272A5004A47F5 /* DetachPids.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DetachPids.3; sourceTree = ""; }; F96D3E2708F272A5004A47F5 /* dict.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dict.n; sourceTree = ""; }; F96D3E2808F272A5004A47F5 /* DictObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DictObj.3; sourceTree = ""; }; F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoOneEvent.3; sourceTree = ""; }; F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoubleObj.3; sourceTree = ""; }; F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DoWhenIdle.3; sourceTree = ""; }; F96D3E2C08F272A5004A47F5 /* DString.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DString.3; sourceTree = ""; }; F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = DumpActiveMemory.3; sourceTree = ""; }; F96D3E2E08F272A5004A47F5 /* Encoding.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Encoding.3; sourceTree = ""; }; F96D3E2F08F272A5004A47F5 /* encoding.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = encoding.n; sourceTree = ""; }; F96D3E3008F272A5004A47F5 /* Ensemble.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Ensemble.3; sourceTree = ""; }; F96D3E3108F272A5004A47F5 /* Environment.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Environment.3; sourceTree = ""; }; F96D3E3208F272A5004A47F5 /* eof.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eof.n; sourceTree = ""; }; F96D3E3308F272A5004A47F5 /* error.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = error.n; sourceTree = ""; }; F96D3E3408F272A5004A47F5 /* Eval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Eval.3; sourceTree = ""; }; F96D3E3508F272A5004A47F5 /* eval.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = eval.n; sourceTree = ""; }; F96D3E3608F272A5004A47F5 /* exec.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exec.n; sourceTree = ""; }; F96D3E3708F272A5004A47F5 /* Exit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Exit.3; sourceTree = ""; }; F96D3E3808F272A5004A47F5 /* exit.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = exit.n; sourceTree = ""; }; F96D3E3908F272A5004A47F5 /* expr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = expr.n; sourceTree = ""; }; F96D3E3A08F272A5004A47F5 /* ExprLong.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLong.3; sourceTree = ""; }; F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ExprLongObj.3; sourceTree = ""; }; F96D3E3C08F272A5004A47F5 /* fblocked.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fblocked.n; sourceTree = ""; }; F96D3E3D08F272A5004A47F5 /* fconfigure.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fconfigure.n; sourceTree = ""; }; F96D3E3E08F272A5004A47F5 /* fcopy.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fcopy.n; sourceTree = ""; }; F96D3E3F08F272A5004A47F5 /* file.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = file.n; sourceTree = ""; }; F96D3E4008F272A5004A47F5 /* fileevent.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = fileevent.n; sourceTree = ""; }; F96D3E4108F272A5004A47F5 /* filename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = filename.n; sourceTree = ""; }; F96D3E4208F272A5004A47F5 /* FileSystem.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FileSystem.3; sourceTree = ""; }; F96D3E4308F272A5004A47F5 /* FindExec.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = FindExec.3; sourceTree = ""; }; F96D3E4408F272A5004A47F5 /* flush.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = flush.n; sourceTree = ""; }; F96D3E4508F272A5004A47F5 /* for.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = for.n; sourceTree = ""; }; F96D3E4608F272A5004A47F5 /* foreach.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = foreach.n; sourceTree = ""; }; F96D3E4708F272A5004A47F5 /* format.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = format.n; sourceTree = ""; }; F96D3E4808F272A5004A47F5 /* GetCwd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetCwd.3; sourceTree = ""; }; F96D3E4908F272A5004A47F5 /* GetHostName.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetHostName.3; sourceTree = ""; }; F96D3E4A08F272A5004A47F5 /* GetIndex.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetIndex.3; sourceTree = ""; }; F96D3E4B08F272A5004A47F5 /* GetInt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetInt.3; sourceTree = ""; }; F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetOpnFl.3; sourceTree = ""; }; F96D3E4D08F272A5004A47F5 /* gets.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = gets.n; sourceTree = ""; }; F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetStdChan.3; sourceTree = ""; }; F96D3E4F08F272A5004A47F5 /* GetTime.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetTime.3; sourceTree = ""; }; F96D3E5008F272A5004A47F5 /* GetVersion.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = GetVersion.3; sourceTree = ""; }; F96D3E5108F272A5004A47F5 /* glob.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = glob.n; sourceTree = ""; }; F96D3E5208F272A6004A47F5 /* global.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = global.n; sourceTree = ""; }; F96D3E5308F272A6004A47F5 /* Hash.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Hash.3; sourceTree = ""; }; F96D3E5408F272A6004A47F5 /* history.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = history.n; sourceTree = ""; }; F96D3E5508F272A6004A47F5 /* http.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = http.n; sourceTree = ""; }; F96D3E5608F272A6004A47F5 /* if.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = if.n; sourceTree = ""; }; F96D3E5708F272A6004A47F5 /* incr.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = incr.n; sourceTree = ""; }; F96D3E5808F272A6004A47F5 /* info.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = info.n; sourceTree = ""; }; F96D3E5908F272A6004A47F5 /* Init.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Init.3; sourceTree = ""; }; F96D3E5A08F272A6004A47F5 /* InitStubs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = InitStubs.3; sourceTree = ""; }; F96D3E5B08F272A6004A47F5 /* Interp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Interp.3; sourceTree = ""; }; F96D3E5C08F272A6004A47F5 /* interp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = interp.n; sourceTree = ""; }; F96D3E5D08F272A6004A47F5 /* IntObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = IntObj.3; sourceTree = ""; }; F96D3E5E08F272A6004A47F5 /* join.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = join.n; sourceTree = ""; }; F96D3E5F08F272A6004A47F5 /* lappend.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lappend.n; sourceTree = ""; }; F96D3E6008F272A6004A47F5 /* lassign.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lassign.n; sourceTree = ""; }; F96D3E6108F272A6004A47F5 /* library.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = library.n; sourceTree = ""; }; F96D3E6208F272A6004A47F5 /* Limit.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Limit.3; sourceTree = ""; }; F96D3E6308F272A6004A47F5 /* lindex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lindex.n; sourceTree = ""; }; F96D3E6408F272A6004A47F5 /* LinkVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = LinkVar.3; sourceTree = ""; }; F96D3E6508F272A6004A47F5 /* linsert.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = linsert.n; sourceTree = ""; }; F96D3E6608F272A6004A47F5 /* list.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = list.n; sourceTree = ""; }; F96D3E6708F272A6004A47F5 /* ListObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ListObj.3; sourceTree = ""; }; F96D3E6808F272A6004A47F5 /* llength.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = llength.n; sourceTree = ""; }; F96D3E6908F272A6004A47F5 /* load.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = load.n; sourceTree = ""; }; F96D3E6A08F272A6004A47F5 /* lrange.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrange.n; sourceTree = ""; }; F96D3E6B08F272A6004A47F5 /* lrepeat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lrepeat.n; sourceTree = ""; }; F96D3E6C08F272A6004A47F5 /* lreplace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lreplace.n; sourceTree = ""; }; F96D3E6D08F272A6004A47F5 /* lsearch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsearch.n; sourceTree = ""; }; F96D3E6E08F272A6004A47F5 /* lset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lset.n; sourceTree = ""; }; F96D3E6F08F272A6004A47F5 /* lsort.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = lsort.n; sourceTree = ""; }; F96D3E7008F272A6004A47F5 /* man.macros */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = man.macros; sourceTree = ""; }; F96D3E7108F272A6004A47F5 /* mathfunc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = mathfunc.n; sourceTree = ""; }; F96D3E7208F272A6004A47F5 /* memory.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = memory.n; sourceTree = ""; }; F96D3E7308F272A6004A47F5 /* msgcat.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = msgcat.n; sourceTree = ""; }; F96D3E7408F272A6004A47F5 /* Namespace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Namespace.3; sourceTree = ""; }; F96D3E7508F272A6004A47F5 /* namespace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = namespace.n; sourceTree = ""; }; F96D3E7608F272A6004A47F5 /* Notifier.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Notifier.3; sourceTree = ""; }; F96D3E7708F272A6004A47F5 /* Object.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Object.3; sourceTree = ""; }; F96D3E7808F272A6004A47F5 /* ObjectType.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ObjectType.3; sourceTree = ""; }; F96D3E7908F272A6004A47F5 /* open.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = open.n; sourceTree = ""; }; F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenFileChnl.3; sourceTree = ""; }; F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = OpenTcp.3; sourceTree = ""; }; F96D3E7C08F272A6004A47F5 /* package.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = package.n; sourceTree = ""; }; F96D3E7D08F272A6004A47F5 /* packagens.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = packagens.n; sourceTree = ""; }; F96D3E7E08F272A6004A47F5 /* Panic.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Panic.3; sourceTree = ""; }; F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ParseCmd.3; sourceTree = ""; }; F96D3E8008F272A6004A47F5 /* pid.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pid.n; sourceTree = ""; }; F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pkgMkIndex.n; sourceTree = ""; }; F96D3E8208F272A6004A47F5 /* PkgRequire.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PkgRequire.3; sourceTree = ""; }; F96D3E8308F272A6004A47F5 /* Preserve.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Preserve.3; sourceTree = ""; }; F96D3E8408F272A6004A47F5 /* PrintDbl.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = PrintDbl.3; sourceTree = ""; }; F96D3E8508F272A6004A47F5 /* proc.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = proc.n; sourceTree = ""; }; F96D3E8608F272A6004A47F5 /* puts.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = puts.n; sourceTree = ""; }; F96D3E8708F272A6004A47F5 /* pwd.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = pwd.n; sourceTree = ""; }; F96D3E8808F272A6004A47F5 /* re_syntax.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = re_syntax.n; sourceTree = ""; }; F96D3E8908F272A6004A47F5 /* read.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = read.n; sourceTree = ""; }; F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecEvalObj.3; sourceTree = ""; }; F96D3E8B08F272A6004A47F5 /* RecordEval.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RecordEval.3; sourceTree = ""; }; F96D3E8C08F272A6004A47F5 /* RegConfig.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegConfig.3; sourceTree = ""; }; F96D3E8D08F272A6004A47F5 /* RegExp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = RegExp.3; sourceTree = ""; }; F96D3E8E08F272A6004A47F5 /* regexp.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regexp.n; sourceTree = ""; }; F96D3E8F08F272A6004A47F5 /* registry.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = registry.n; sourceTree = ""; }; F96D3E9008F272A6004A47F5 /* regsub.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = regsub.n; sourceTree = ""; }; F96D3E9108F272A6004A47F5 /* rename.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = rename.n; sourceTree = ""; }; F96D3E9208F272A6004A47F5 /* return.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = return.n; sourceTree = ""; }; F96D3E9308F272A6004A47F5 /* safe.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = safe.n; sourceTree = ""; }; F96D3E9408F272A6004A47F5 /* SaveResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SaveResult.3; sourceTree = ""; }; F96D3E9508F272A6004A47F5 /* scan.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = scan.n; sourceTree = ""; }; F96D3E9608F272A6004A47F5 /* seek.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = seek.n; sourceTree = ""; }; F96D3E9708F272A6004A47F5 /* set.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = set.n; sourceTree = ""; }; F96D3E9808F272A6004A47F5 /* SetChanErr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetChanErr.3; sourceTree = ""; }; F96D3E9908F272A6004A47F5 /* SetErrno.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetErrno.3; sourceTree = ""; }; F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetRecLmt.3; sourceTree = ""; }; F96D3E9B08F272A7004A47F5 /* SetResult.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetResult.3; sourceTree = ""; }; F96D3E9C08F272A7004A47F5 /* SetVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SetVar.3; sourceTree = ""; }; F96D3E9D08F272A7004A47F5 /* Signal.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Signal.3; sourceTree = ""; }; F96D3E9E08F272A7004A47F5 /* Sleep.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Sleep.3; sourceTree = ""; }; F96D3E9F08F272A7004A47F5 /* socket.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = socket.n; sourceTree = ""; }; F96D3EA008F272A7004A47F5 /* source.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = source.n; sourceTree = ""; }; F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SourceRCFile.3; sourceTree = ""; }; F96D3EA208F272A7004A47F5 /* split.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = split.n; sourceTree = ""; }; F96D3EA308F272A7004A47F5 /* SplitList.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitList.3; sourceTree = ""; }; F96D3EA408F272A7004A47F5 /* SplitPath.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SplitPath.3; sourceTree = ""; }; F96D3EA508F272A7004A47F5 /* StaticPkg.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticPkg.3; sourceTree = ""; }; F96D3EA608F272A7004A47F5 /* StdChannels.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StdChannels.3; sourceTree = ""; }; F96D3EA708F272A7004A47F5 /* string.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = string.n; sourceTree = ""; }; F96D3EA808F272A7004A47F5 /* StringObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StringObj.3; sourceTree = ""; }; F96D3EA908F272A7004A47F5 /* StrMatch.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StrMatch.3; sourceTree = ""; }; F96D3EAA08F272A7004A47F5 /* subst.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = subst.n; sourceTree = ""; }; F96D3EAB08F272A7004A47F5 /* SubstObj.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SubstObj.3; sourceTree = ""; }; F96D3EAC08F272A7004A47F5 /* switch.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = switch.n; sourceTree = ""; }; F96D3EAD08F272A7004A47F5 /* Tcl.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl.n; sourceTree = ""; }; F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Tcl_Main.3; sourceTree = ""; }; F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TCL_MEM_DEBUG.3; sourceTree = ""; }; F96D3EB008F272A7004A47F5 /* tclsh.1 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclsh.1; sourceTree = ""; }; F96D3EB108F272A7004A47F5 /* tcltest.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tcltest.n; sourceTree = ""; }; F96D3EB208F272A7004A47F5 /* tclvars.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tclvars.n; sourceTree = ""; }; F96D3EB308F272A7004A47F5 /* tell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tell.n; sourceTree = ""; }; F96D3EB408F272A7004A47F5 /* Thread.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Thread.3; sourceTree = ""; }; F96D3EB508F272A7004A47F5 /* time.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = time.n; sourceTree = ""; }; F96D3EB608F272A7004A47F5 /* tm.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tm.n; sourceTree = ""; }; F96D3EB708F272A7004A47F5 /* ToUpper.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = ToUpper.3; sourceTree = ""; }; F96D3EB808F272A7004A47F5 /* trace.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = trace.n; sourceTree = ""; }; F96D3EB908F272A7004A47F5 /* TraceCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceCmd.3; sourceTree = ""; }; F96D3EBA08F272A7004A47F5 /* TraceVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TraceVar.3; sourceTree = ""; }; F96D3EBB08F272A7004A47F5 /* Translate.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Translate.3; sourceTree = ""; }; F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UniCharIsAlpha.3; sourceTree = ""; }; F96D3EBD08F272A7004A47F5 /* unknown.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unknown.n; sourceTree = ""; }; F96D3EBE08F272A7004A47F5 /* unload.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unload.n; sourceTree = ""; }; F96D3EBF08F272A7004A47F5 /* unset.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = unset.n; sourceTree = ""; }; F96D3EC008F272A7004A47F5 /* update.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = update.n; sourceTree = ""; }; F96D3EC108F272A7004A47F5 /* uplevel.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = uplevel.n; sourceTree = ""; }; F96D3EC208F272A7004A47F5 /* UpVar.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = UpVar.3; sourceTree = ""; }; F96D3EC308F272A7004A47F5 /* upvar.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = upvar.n; sourceTree = ""; }; F96D3EC408F272A7004A47F5 /* Utf.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = Utf.3; sourceTree = ""; }; F96D3EC508F272A7004A47F5 /* variable.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = variable.n; sourceTree = ""; }; F96D3EC608F272A7004A47F5 /* vwait.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = vwait.n; sourceTree = ""; }; F96D3EC708F272A7004A47F5 /* while.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = while.n; sourceTree = ""; }; F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = WrongNumArgs.3; sourceTree = ""; }; F96D3ECA08F272A7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D3ECB08F272A7004A47F5 /* regc_color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_color.c; sourceTree = ""; }; F96D3ECC08F272A7004A47F5 /* regc_cvec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_cvec.c; sourceTree = ""; }; F96D3ECD08F272A7004A47F5 /* regc_lex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_lex.c; sourceTree = ""; }; F96D3ECE08F272A7004A47F5 /* regc_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_locale.c; sourceTree = ""; }; F96D3ECF08F272A7004A47F5 /* regc_nfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regc_nfa.c; sourceTree = ""; }; F96D3ED008F272A7004A47F5 /* regcomp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regcomp.c; sourceTree = ""; }; F96D3ED108F272A7004A47F5 /* regcustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regcustom.h; sourceTree = ""; }; F96D3ED208F272A7004A47F5 /* rege_dfa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rege_dfa.c; sourceTree = ""; }; F96D3ED308F272A7004A47F5 /* regerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regerror.c; sourceTree = ""; }; F96D3ED408F272A7004A47F5 /* regerrs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regerrs.h; sourceTree = ""; }; F96D3ED508F272A7004A47F5 /* regex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regex.h; sourceTree = ""; }; F96D3ED608F272A7004A47F5 /* regexec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regexec.c; sourceTree = ""; }; F96D3ED708F272A7004A47F5 /* regfree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfree.c; sourceTree = ""; }; F96D3ED808F272A7004A47F5 /* regfronts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = regfronts.c; sourceTree = ""; }; F96D3ED908F272A7004A47F5 /* regguts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = regguts.h; sourceTree = ""; }; F96D3EDA08F272A7004A47F5 /* tcl.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcl.decls; sourceTree = ""; }; F96D3EDB08F272A7004A47F5 /* tcl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tcl.h; sourceTree = ""; }; F96D3EDC08F272A7004A47F5 /* tclAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAlloc.c; sourceTree = ""; }; F96D3EDD08F272A7004A47F5 /* tclAsync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAsync.c; sourceTree = ""; }; F96D3EDE08F272A7004A47F5 /* tclBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBasic.c; sourceTree = ""; }; F96D3EDF08F272A7004A47F5 /* tclBinary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclBinary.c; sourceTree = ""; }; F96D3EE008F272A7004A47F5 /* tclCkalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCkalloc.c; sourceTree = ""; }; F96D3EE108F272A7004A47F5 /* tclClock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclClock.c; sourceTree = ""; }; F96D3EE208F272A7004A47F5 /* tclCmdAH.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdAH.c; sourceTree = ""; }; F96D3EE308F272A7004A47F5 /* tclCmdIL.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdIL.c; sourceTree = ""; }; F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCmdMZ.c; sourceTree = ""; }; F96D3EE508F272A7004A47F5 /* tclCompCmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompCmds.c; sourceTree = ""; }; F96D3EE608F272A7004A47F5 /* tclCompExpr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompExpr.c; sourceTree = ""; }; F96D3EE708F272A7004A47F5 /* tclCompile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclCompile.c; sourceTree = ""; }; F96D3EE808F272A7004A47F5 /* tclCompile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclCompile.h; sourceTree = ""; }; F96D3EE908F272A7004A47F5 /* tclConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclConfig.c; sourceTree = ""; }; F96D3EEA08F272A7004A47F5 /* tclDate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDate.c; sourceTree = ""; }; F96D3EEB08F272A7004A47F5 /* tclDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclDecls.h; sourceTree = ""; }; F96D3EEC08F272A7004A47F5 /* tclDictObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclDictObj.c; sourceTree = ""; }; F96D3EED08F272A7004A47F5 /* tclEncoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEncoding.c; sourceTree = ""; }; F96D3EEE08F272A7004A47F5 /* tclEnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEnv.c; sourceTree = ""; }; F96D3EEF08F272A7004A47F5 /* tclEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclEvent.c; sourceTree = ""; }; F96D3EF008F272A7004A47F5 /* tclExecute.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclExecute.c; sourceTree = ""; }; F96D3EF108F272A7004A47F5 /* tclFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFCmd.c; sourceTree = ""; }; F96D3EF208F272A7004A47F5 /* tclFileName.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclFileName.c; sourceTree = ""; }; F96D3EF308F272A7004A47F5 /* tclFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclFileSystem.h; sourceTree = ""; }; F96D3EF408F272A7004A47F5 /* tclGet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclGet.c; sourceTree = ""; }; F96D3EF508F272A7004A47F5 /* tclGetDate.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = tclGetDate.y; sourceTree = ""; }; F96D3EF608F272A7004A47F5 /* tclHash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHash.c; sourceTree = ""; }; F96D3EF708F272A7004A47F5 /* tclHistory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclHistory.c; sourceTree = ""; }; F96D3EF808F272A7004A47F5 /* tclIndexObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIndexObj.c; sourceTree = ""; }; F96D3EF908F272A7004A47F5 /* tclInt.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclInt.decls; sourceTree = ""; }; F96D3EFA08F272A7004A47F5 /* tclInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclInt.h; sourceTree = ""; }; F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntDecls.h; sourceTree = ""; }; F96D3EFC08F272A7004A47F5 /* tclInterp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclInterp.c; sourceTree = ""; }; F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIntPlatDecls.h; sourceTree = ""; }; F96D3EFE08F272A7004A47F5 /* tclIO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIO.c; sourceTree = ""; }; F96D3EFF08F272A7004A47F5 /* tclIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclIO.h; sourceTree = ""; }; F96D3F0008F272A7004A47F5 /* tclIOCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOCmd.c; sourceTree = ""; }; F96D3F0108F272A7004A47F5 /* tclIOGT.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOGT.c; sourceTree = ""; }; F96D3F0208F272A7004A47F5 /* tclIORChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIORChan.c; sourceTree = ""; }; F96D3F0308F272A7004A47F5 /* tclIOSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOSock.c; sourceTree = ""; }; F96D3F0408F272A7004A47F5 /* tclIOUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclIOUtil.c; sourceTree = ""; }; F96D3F0508F272A7004A47F5 /* tclLink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLink.c; sourceTree = ""; }; F96D3F0608F272A7004A47F5 /* tclListObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclListObj.c; sourceTree = ""; }; F96D3F0708F272A7004A47F5 /* tclLiteral.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLiteral.c; sourceTree = ""; }; F96D3F0808F272A7004A47F5 /* tclLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoad.c; sourceTree = ""; }; F96D3F0908F272A7004A47F5 /* tclLoadNone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNone.c; sourceTree = ""; }; F96D3F0A08F272A7004A47F5 /* tclMain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMain.c; sourceTree = ""; }; F96D3F0B08F272A7004A47F5 /* tclNamesp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNamesp.c; sourceTree = ""; }; F96D3F0C08F272A7004A47F5 /* tclNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclNotify.c; sourceTree = ""; }; F96D3F0D08F272A7004A47F5 /* tclObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclObj.c; sourceTree = ""; }; F96D3F0E08F272A7004A47F5 /* tclPanic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPanic.c; sourceTree = ""; }; F96D3F0F08F272A7004A47F5 /* tclParse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclParse.c; sourceTree = ""; }; F96D3F1108F272A7004A47F5 /* tclPathObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPathObj.c; sourceTree = ""; }; F96D3F1208F272A7004A47F5 /* tclPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPipe.c; sourceTree = ""; }; F96D3F1308F272A7004A47F5 /* tclPkg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkg.c; sourceTree = ""; }; F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPkgConfig.c; sourceTree = ""; }; F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPlatDecls.h; sourceTree = ""; }; F96D3F1608F272A7004A47F5 /* tclPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclPort.h; sourceTree = ""; }; F96D3F1708F272A7004A47F5 /* tclPosixStr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPosixStr.c; sourceTree = ""; }; F96D3F1808F272A7004A47F5 /* tclPreserve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclPreserve.c; sourceTree = ""; }; F96D3F1908F272A7004A47F5 /* tclProc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclProc.c; sourceTree = ""; }; F96D3F1A08F272A7004A47F5 /* tclRegexp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclRegexp.c; sourceTree = ""; }; F96D3F1B08F272A7004A47F5 /* tclRegexp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclRegexp.h; sourceTree = ""; }; F96D3F1C08F272A7004A47F5 /* tclResolve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResolve.c; sourceTree = ""; }; F96D3F1D08F272A7004A47F5 /* tclResult.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclResult.c; sourceTree = ""; }; F96D3F1E08F272A7004A47F5 /* tclScan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclScan.c; sourceTree = ""; }; F96D3F1F08F272A7004A47F5 /* tclStringObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStringObj.c; sourceTree = ""; }; F96D3F2408F272A7004A47F5 /* tclStrToD.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStrToD.c; sourceTree = ""; }; F96D3F2508F272A7004A47F5 /* tclStubInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubInit.c; sourceTree = ""; }; F96D3F2608F272A7004A47F5 /* tclStubLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclStubLib.c; sourceTree = ""; }; F96D3F2708F272A7004A47F5 /* tclTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTest.c; sourceTree = ""; }; F96D3F2808F272A7004A47F5 /* tclTestObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestObj.c; sourceTree = ""; }; F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTestProcBodyObj.c; sourceTree = ""; }; F96D3F2A08F272A7004A47F5 /* tclThread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThread.c; sourceTree = ""; }; F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadAlloc.c; sourceTree = ""; }; F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadJoin.c; sourceTree = ""; }; F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadStorage.c; sourceTree = ""; }; F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclThreadTest.c; sourceTree = ""; }; F96D3F2F08F272A7004A47F5 /* tclTimer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTimer.c; sourceTree = ""; }; F96D3F3008F272A7004A47F5 /* tclTomMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMath.h; sourceTree = ""; }; F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTomMathInterface.c; sourceTree = ""; }; F96D3F3208F272A7004A47F5 /* tclTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclTrace.c; sourceTree = ""; }; F96D3F3308F272A7004A47F5 /* tclUniData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUniData.c; sourceTree = ""; }; F96D3F3408F272A7004A47F5 /* tclUtf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtf.c; sourceTree = ""; }; F96D3F3508F272A7004A47F5 /* tclUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUtil.c; sourceTree = ""; }; F96D3F3608F272A7004A47F5 /* tclVar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclVar.c; sourceTree = ""; }; F96D3F3708F272A7004A47F5 /* tommath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath.h; sourceTree = ""; }; F96D3F3908F272A8004A47F5 /* auto.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = auto.tcl; sourceTree = ""; }; F96D3F3A08F272A8004A47F5 /* clock.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.tcl; sourceTree = ""; }; F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D3F8C08F272A8004A47F5 /* history.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.tcl; sourceTree = ""; }; F96D3F8E08F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = ""; }; F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D3F9108F272A8004A47F5 /* http.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.tcl; sourceTree = ""; }; F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D3F9308F272A8004A47F5 /* init.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.tcl; sourceTree = ""; }; F96D3F9508F272A8004A47F5 /* msgcat.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.tcl; sourceTree = ""; }; F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D401808F272AA004A47F5 /* optparse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = optparse.tcl; sourceTree = ""; }; F96D401908F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D401A08F272AA004A47F5 /* package.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.tcl; sourceTree = ""; }; F96D401B08F272AA004A47F5 /* parray.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parray.tcl; sourceTree = ""; }; F96D401D08F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D401E08F272AA004A47F5 /* safe.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.tcl; sourceTree = ""; }; F96D401F08F272AA004A47F5 /* tclIndex */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclIndex; sourceTree = ""; }; F96D402108F272AA004A47F5 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F96D402208F272AA004A47F5 /* tcltest.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.tcl; sourceTree = ""; }; F96D402308F272AA004A47F5 /* tm.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.tcl; sourceTree = ""; }; F96D425B08F272B2004A47F5 /* word.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = word.tcl; sourceTree = ""; }; F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_mul_digs.c; sourceTree = ""; }; F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_fast_s_mp_sqr.c; sourceTree = ""; }; F96D426908F272B3004A47F5 /* bn_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add.c; sourceTree = ""; }; F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_add_d.c; sourceTree = ""; }; F96D426C08F272B3004A47F5 /* bn_mp_and.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_and.c; sourceTree = ""; }; F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clamp.c; sourceTree = ""; }; F96D426E08F272B3004A47F5 /* bn_mp_clear.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear.c; sourceTree = ""; }; F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_clear_multi.c; sourceTree = ""; }; F96D427008F272B3004A47F5 /* bn_mp_cmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp.c; sourceTree = ""; }; F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_d.c; sourceTree = ""; }; F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_cmp_mag.c; sourceTree = ""; }; F96D427408F272B3004A47F5 /* bn_mp_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_copy.c; sourceTree = ""; }; F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_count_bits.c; sourceTree = ""; }; F96D427608F272B3004A47F5 /* bn_mp_div.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div.c; sourceTree = ""; }; F96D427708F272B3004A47F5 /* bn_mp_div_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2.c; sourceTree = ""; }; F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_2d.c; sourceTree = ""; }; F96D427908F272B3004A47F5 /* bn_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_3.c; sourceTree = ""; }; F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_div_d.c; sourceTree = ""; }; F96D427E08F272B3004A47F5 /* bn_mp_exch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_exch.c; sourceTree = ""; }; F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_d.c; sourceTree = ""; }; F96D428708F272B3004A47F5 /* bn_mp_grow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_grow.c; sourceTree = ""; }; F96D428808F272B3004A47F5 /* bn_mp_init.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init.c; sourceTree = ""; }; F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_copy.c; sourceTree = ""; }; F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_multi.c; sourceTree = ""; }; F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_set.c; sourceTree = ""; }; F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_init_size.c; sourceTree = ""; }; F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_mul.c; sourceTree = ""; }; F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_karatsuba_sqr.c; sourceTree = ""; }; F96D429508F272B3004A47F5 /* bn_mp_lshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_lshd.c; sourceTree = ""; }; F96D429608F272B3004A47F5 /* bn_mp_mod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod.c; sourceTree = ""; }; F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mod_2d.c; sourceTree = ""; }; F96D429C08F272B3004A47F5 /* bn_mp_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul.c; sourceTree = ""; }; F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2.c; sourceTree = ""; }; F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_2d.c; sourceTree = ""; }; F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_mul_d.c; sourceTree = ""; }; F96D42A208F272B3004A47F5 /* bn_mp_neg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_neg.c; sourceTree = ""; }; F96D42A308F272B3004A47F5 /* bn_mp_or.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_or.c; sourceTree = ""; }; F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_size.c; sourceTree = ""; }; F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_radix_smap.c; sourceTree = ""; }; F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_read_radix.c; sourceTree = ""; }; F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_rshd.c; sourceTree = ""; }; F96D42BA08F272B3004A47F5 /* bn_mp_set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_set.c; sourceTree = ""; }; F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_shrink.c; sourceTree = ""; }; F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqr.c; sourceTree = ""; }; F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sqrt.c; sourceTree = ""; }; F96D42C108F272B3004A47F5 /* bn_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub.c; sourceTree = ""; }; F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_sub_d.c; sourceTree = ""; }; F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin.c; sourceTree = ""; }; F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_to_unsigned_bin_n.c; sourceTree = ""; }; F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_mul.c; sourceTree = ""; }; F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toom_sqr.c; sourceTree = ""; }; F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_toradix_n.c; sourceTree = ""; }; F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_unsigned_bin_size.c; sourceTree = ""; }; F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_xor.c; sourceTree = ""; }; F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_zero.c; sourceTree = ""; }; F96D42D008F272B3004A47F5 /* bn_reverse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_reverse.c; sourceTree = ""; }; F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_add.c; sourceTree = ""; }; F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_mul_digs.c; sourceTree = ""; }; F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sqr.c; sourceTree = ""; }; F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_mp_sub.c; sourceTree = ""; }; F96D42D708F272B3004A47F5 /* bncore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bncore.c; sourceTree = ""; }; F96D432908F272B4004A47F5 /* tommath_class.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_class.h; sourceTree = ""; }; F96D432A08F272B4004A47F5 /* tommath_superclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tommath_superclass.h; sourceTree = ""; }; F96D432B08F272B4004A47F5 /* license.terms */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = license.terms; sourceTree = ""; }; F96D432E08F272B5004A47F5 /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure.ac; sourceTree = ""; }; F96D432F08F272B5004A47F5 /* GNUmakefile */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = GNUmakefile; sourceTree = ""; }; F96D433108F272B5004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */ = {isa = PBXFileReference; explicitFileType = text.plist; fileEncoding = 4; path = "Tcl-Info.plist.in"; sourceTree = ""; }; F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXBundle.c; sourceTree = ""; }; F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXFCmd.c; sourceTree = ""; }; F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclMacOSXNotify.c; sourceTree = ""; }; F96D434308F272B5004A47F5 /* README */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = README; sourceTree = ""; }; F96D434508F272B5004A47F5 /* all.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = all.tcl; sourceTree = ""; }; F96D434608F272B5004A47F5 /* append.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = append.test; sourceTree = ""; }; F96D434708F272B5004A47F5 /* appendComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = appendComp.test; sourceTree = ""; }; F96D434808F272B5004A47F5 /* assocd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = assocd.test; sourceTree = ""; }; F96D434908F272B5004A47F5 /* async.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = async.test; sourceTree = ""; }; F96D434A08F272B5004A47F5 /* autoMkindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = autoMkindex.test; sourceTree = ""; }; F96D434B08F272B5004A47F5 /* basic.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = basic.test; sourceTree = ""; }; F96D434C08F272B5004A47F5 /* binary.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = binary.test; sourceTree = ""; }; F96D434D08F272B5004A47F5 /* case.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = case.test; sourceTree = ""; }; F96D434E08F272B5004A47F5 /* chan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chan.test; sourceTree = ""; }; F96D434F08F272B5004A47F5 /* clock.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = clock.test; sourceTree = ""; }; F96D435008F272B5004A47F5 /* cmdAH.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdAH.test; sourceTree = ""; }; F96D435108F272B5004A47F5 /* cmdIL.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdIL.test; sourceTree = ""; }; F96D435208F272B5004A47F5 /* cmdInfo.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdInfo.test; sourceTree = ""; }; F96D435308F272B5004A47F5 /* cmdMZ.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = cmdMZ.test; sourceTree = ""; }; F96D435408F272B5004A47F5 /* compExpr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "compExpr-old.test"; sourceTree = ""; }; F96D435508F272B5004A47F5 /* compExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compExpr.test; sourceTree = ""; }; F96D435608F272B5004A47F5 /* compile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = compile.test; sourceTree = ""; }; F96D435708F272B5004A47F5 /* concat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = concat.test; sourceTree = ""; }; F96D435808F272B5004A47F5 /* config.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = config.test; sourceTree = ""; }; F96D435908F272B5004A47F5 /* dcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dcall.test; sourceTree = ""; }; F96D435A08F272B5004A47F5 /* dict.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dict.test; sourceTree = ""; }; F96D435C08F272B5004A47F5 /* dstring.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = dstring.test; sourceTree = ""; }; F96D435E08F272B5004A47F5 /* encoding.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = encoding.test; sourceTree = ""; }; F96D435F08F272B5004A47F5 /* env.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = env.test; sourceTree = ""; }; F96D436008F272B5004A47F5 /* error.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = error.test; sourceTree = ""; }; F96D436108F272B5004A47F5 /* eval.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eval.test; sourceTree = ""; }; F96D436208F272B5004A47F5 /* event.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = event.test; sourceTree = ""; }; F96D436308F272B5004A47F5 /* exec.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = exec.test; sourceTree = ""; }; F96D436408F272B5004A47F5 /* execute.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = execute.test; sourceTree = ""; }; F96D436508F272B5004A47F5 /* expr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "expr-old.test"; sourceTree = ""; }; F96D436608F272B5004A47F5 /* expr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = expr.test; sourceTree = ""; }; F96D436708F272B6004A47F5 /* fCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fCmd.test; sourceTree = ""; }; F96D436808F272B6004A47F5 /* fileName.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileName.test; sourceTree = ""; }; F96D436908F272B6004A47F5 /* fileSystem.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fileSystem.test; sourceTree = ""; }; F96D436A08F272B6004A47F5 /* for-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "for-old.test"; sourceTree = ""; }; F96D436B08F272B6004A47F5 /* for.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = for.test; sourceTree = ""; }; F96D436C08F272B6004A47F5 /* foreach.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = foreach.test; sourceTree = ""; }; F96D436D08F272B6004A47F5 /* format.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = format.test; sourceTree = ""; }; F96D436E08F272B6004A47F5 /* get.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = get.test; sourceTree = ""; }; F96D436F08F272B6004A47F5 /* history.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = history.test; sourceTree = ""; }; F96D437008F272B6004A47F5 /* http.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http.test; sourceTree = ""; }; F96D437108F272B6004A47F5 /* httpd */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd; sourceTree = ""; }; F96D437208F272B6004A47F5 /* httpold.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpold.test; sourceTree = ""; }; F96D437308F272B6004A47F5 /* if-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "if-old.test"; sourceTree = ""; }; F96D437408F272B6004A47F5 /* if.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = if.test; sourceTree = ""; }; F96D437508F272B6004A47F5 /* incr-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "incr-old.test"; sourceTree = ""; }; F96D437608F272B6004A47F5 /* incr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = incr.test; sourceTree = ""; }; F96D437708F272B6004A47F5 /* indexObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = indexObj.test; sourceTree = ""; }; F96D437808F272B6004A47F5 /* info.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = info.test; sourceTree = ""; }; F96D437908F272B6004A47F5 /* init.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = init.test; sourceTree = ""; }; F96D437A08F272B6004A47F5 /* interp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = interp.test; sourceTree = ""; }; F96D437B08F272B6004A47F5 /* io.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = io.test; sourceTree = ""; }; F96D437C08F272B6004A47F5 /* ioCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = ioCmd.test; sourceTree = ""; }; F96D437D08F272B6004A47F5 /* iogt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = iogt.test; sourceTree = ""; }; F96D437F08F272B6004A47F5 /* join.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = join.test; sourceTree = ""; }; F96D438008F272B6004A47F5 /* lindex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lindex.test; sourceTree = ""; }; F96D438108F272B6004A47F5 /* link.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = link.test; sourceTree = ""; }; F96D438208F272B6004A47F5 /* linsert.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = linsert.test; sourceTree = ""; }; F96D438308F272B6004A47F5 /* list.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = list.test; sourceTree = ""; }; F96D438408F272B6004A47F5 /* listObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = listObj.test; sourceTree = ""; }; F96D438508F272B6004A47F5 /* llength.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = llength.test; sourceTree = ""; }; F96D438608F272B6004A47F5 /* load.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = load.test; sourceTree = ""; }; F96D438708F272B6004A47F5 /* lrange.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrange.test; sourceTree = ""; }; F96D438808F272B6004A47F5 /* lrepeat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lrepeat.test; sourceTree = ""; }; F96D438908F272B6004A47F5 /* lreplace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lreplace.test; sourceTree = ""; }; F96D438A08F272B6004A47F5 /* lsearch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsearch.test; sourceTree = ""; }; F96D438B08F272B6004A47F5 /* lset.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lset.test; sourceTree = ""; }; F96D438C08F272B6004A47F5 /* lsetComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = lsetComp.test; sourceTree = ""; }; F96D438D08F272B6004A47F5 /* macOSXFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = macOSXFCmd.test; sourceTree = ""; }; F96D438E08F272B6004A47F5 /* main.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = main.test; sourceTree = ""; }; F96D438F08F272B6004A47F5 /* misc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = misc.test; sourceTree = ""; }; F96D439008F272B6004A47F5 /* msgcat.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = msgcat.test; sourceTree = ""; }; F96D439108F272B6004A47F5 /* namespace-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "namespace-old.test"; sourceTree = ""; }; F96D439208F272B7004A47F5 /* namespace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = namespace.test; sourceTree = ""; }; F96D439308F272B7004A47F5 /* notify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = notify.test; sourceTree = ""; }; F96D439408F272B7004A47F5 /* obj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = obj.test; sourceTree = ""; }; F96D439508F272B7004A47F5 /* opt.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = opt.test; sourceTree = ""; }; F96D439608F272B7004A47F5 /* package.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = package.test; sourceTree = ""; }; F96D439708F272B7004A47F5 /* parse.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parse.test; sourceTree = ""; }; F96D439808F272B7004A47F5 /* parseExpr.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseExpr.test; sourceTree = ""; }; F96D439908F272B7004A47F5 /* parseOld.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = parseOld.test; sourceTree = ""; }; F96D439A08F272B7004A47F5 /* pid.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pid.test; sourceTree = ""; }; F96D439B08F272B7004A47F5 /* pkg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkg.test; sourceTree = ""; }; F96D439C08F272B7004A47F5 /* pkgMkIndex.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgMkIndex.test; sourceTree = ""; }; F96D439D08F272B7004A47F5 /* platform.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.test; sourceTree = ""; }; F96D439E08F272B7004A47F5 /* proc-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "proc-old.test"; sourceTree = ""; }; F96D439F08F272B7004A47F5 /* proc.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = proc.test; sourceTree = ""; }; F96D43A008F272B7004A47F5 /* pwd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pwd.test; sourceTree = ""; }; F96D43A108F272B7004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D43A208F272B7004A47F5 /* reg.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = reg.test; sourceTree = ""; }; F96D43A308F272B7004A47F5 /* regexp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexp.test; sourceTree = ""; }; F96D43A408F272B7004A47F5 /* regexpComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpComp.test; sourceTree = ""; }; F96D43A508F272B7004A47F5 /* registry.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = registry.test; sourceTree = ""; }; F96D43A608F272B7004A47F5 /* remote.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = remote.tcl; sourceTree = ""; }; F96D43A708F272B7004A47F5 /* rename.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = rename.test; sourceTree = ""; }; F96D43A808F272B7004A47F5 /* result.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = result.test; sourceTree = ""; }; F96D43A908F272B7004A47F5 /* safe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = safe.test; sourceTree = ""; }; F96D43AA08F272B7004A47F5 /* scan.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = scan.test; sourceTree = ""; }; F96D43AB08F272B7004A47F5 /* security.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = security.test; sourceTree = ""; }; F96D43AC08F272B7004A47F5 /* set-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "set-old.test"; sourceTree = ""; }; F96D43AD08F272B7004A47F5 /* set.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = set.test; sourceTree = ""; }; F96D43AE08F272B7004A47F5 /* socket.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = socket.test; sourceTree = ""; }; F96D43AF08F272B7004A47F5 /* source.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = source.test; sourceTree = ""; }; F96D43B008F272B7004A47F5 /* split.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = split.test; sourceTree = ""; }; F96D43B108F272B7004A47F5 /* stack.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stack.test; sourceTree = ""; }; F96D43B208F272B7004A47F5 /* string.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = string.test; sourceTree = ""; }; F96D43B308F272B7004A47F5 /* stringComp.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringComp.test; sourceTree = ""; }; F96D43B408F272B7004A47F5 /* stringObj.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = stringObj.test; sourceTree = ""; }; F96D43B508F272B7004A47F5 /* subst.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = subst.test; sourceTree = ""; }; F96D43B608F272B7004A47F5 /* switch.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = switch.test; sourceTree = ""; }; F96D43B708F272B7004A47F5 /* tcltest.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tcltest.test; sourceTree = ""; }; F96D43B808F272B7004A47F5 /* thread.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = thread.test; sourceTree = ""; }; F96D43B908F272B7004A47F5 /* timer.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = timer.test; sourceTree = ""; }; F96D43BA08F272B7004A47F5 /* tm.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tm.test; sourceTree = ""; }; F96D43BB08F272B7004A47F5 /* trace.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = trace.test; sourceTree = ""; }; F96D43BC08F272B7004A47F5 /* unixFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFCmd.test; sourceTree = ""; }; F96D43BD08F272B7004A47F5 /* unixFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixFile.test; sourceTree = ""; }; F96D43BE08F272B7004A47F5 /* unixInit.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixInit.test; sourceTree = ""; }; F96D43BF08F272B7004A47F5 /* unixNotfy.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unixNotfy.test; sourceTree = ""; }; F96D43C008F272B7004A47F5 /* unknown.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unknown.test; sourceTree = ""; }; F96D43C108F272B7004A47F5 /* unload.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = unload.test; sourceTree = ""; }; F96D43C208F272B7004A47F5 /* uplevel.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uplevel.test; sourceTree = ""; }; F96D43C308F272B7004A47F5 /* upvar.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = upvar.test; sourceTree = ""; }; F96D43C408F272B7004A47F5 /* utf.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = utf.test; sourceTree = ""; }; F96D43C508F272B7004A47F5 /* util.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = util.test; sourceTree = ""; }; F96D43C608F272B7004A47F5 /* var.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = var.test; sourceTree = ""; }; F96D43C708F272B7004A47F5 /* while-old.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "while-old.test"; sourceTree = ""; }; F96D43C808F272B7004A47F5 /* while.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = while.test; sourceTree = ""; }; F96D43C908F272B7004A47F5 /* winConsole.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winConsole.test; sourceTree = ""; }; F96D43CA08F272B7004A47F5 /* winDde.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winDde.test; sourceTree = ""; }; F96D43CB08F272B7004A47F5 /* winFCmd.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFCmd.test; sourceTree = ""; }; F96D43CC08F272B7004A47F5 /* winFile.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winFile.test; sourceTree = ""; }; F96D43CD08F272B7004A47F5 /* winNotify.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winNotify.test; sourceTree = ""; }; F96D43CE08F272B7004A47F5 /* winPipe.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winPipe.test; sourceTree = ""; }; F96D43CF08F272B7004A47F5 /* winTime.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = winTime.test; sourceTree = ""; }; F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = ""; }; F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = ""; }; F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = ""; }; F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = ""; }; F96D442808F272B8004A47F5 /* installData.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = installData.tcl; sourceTree = ""; }; F96D442908F272B8004A47F5 /* loadICU.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = loadICU.tcl; sourceTree = ""; }; F96D442A08F272B8004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D442B08F272B8004A47F5 /* makeTestCases.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = makeTestCases.tcl; sourceTree = ""; }; F96D442C08F272B8004A47F5 /* man2help.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help.tcl; sourceTree = ""; }; F96D442D08F272B8004A47F5 /* man2help2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2help2.tcl; sourceTree = ""; }; F96D442E08F272B8004A47F5 /* man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html.tcl; sourceTree = ""; }; F96D442F08F272B8004A47F5 /* man2html1.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html1.tcl; sourceTree = ""; }; F96D443008F272B8004A47F5 /* man2html2.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = man2html2.tcl; sourceTree = ""; }; F96D443108F272B8004A47F5 /* man2tcl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = man2tcl.c; sourceTree = ""; }; F96D443208F272B8004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D443308F272B8004A47F5 /* regexpTestLib.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = regexpTestLib.tcl; sourceTree = ""; }; F96D443508F272B8004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = ""; }; F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = "tcltk-man2html.tcl"; sourceTree = ""; }; F96D443A08F272B9004A47F5 /* tclZIC.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclZIC.tcl; sourceTree = ""; }; F96D443B08F272B9004A47F5 /* uniClass.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniClass.tcl; sourceTree = ""; }; F96D443C08F272B9004A47F5 /* uniParse.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = uniParse.tcl; sourceTree = ""; }; F96D444008F272B9004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F96D444108F272B9004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; F96D444208F272B9004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; F96D444408F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D444508F272B9004A47F5 /* pkga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkga.c; sourceTree = ""; }; F96D444608F272B9004A47F5 /* pkgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgb.c; sourceTree = ""; }; F96D444708F272B9004A47F5 /* pkgc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgc.c; sourceTree = ""; }; F96D444808F272B9004A47F5 /* pkgd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgd.c; sourceTree = ""; }; F96D444908F272B9004A47F5 /* pkge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkge.c; sourceTree = ""; }; F96D444B08F272B9004A47F5 /* pkgua.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pkgua.c; sourceTree = ""; }; F96D444C08F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D444D08F272B9004A47F5 /* install-sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-sh"; sourceTree = ""; }; F96D444E08F272B9004A47F5 /* installManPage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = installManPage; sourceTree = ""; }; F96D444F08F272B9004A47F5 /* ldAix */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ldAix; sourceTree = ""; }; F96D445008F272B9004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D445208F272B9004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D445308F272B9004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = ""; }; F96D445408F272B9004A47F5 /* tcl.spec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.spec; sourceTree = ""; }; F96D445508F272B9004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = ""; }; F96D445608F272B9004A47F5 /* tclConfig.h.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = tclConfig.h.in; sourceTree = ""; }; F96D445708F272B9004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = ""; }; F96D445808F272B9004A47F5 /* tclLoadAix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadAix.c; sourceTree = ""; }; F96D445908F272B9004A47F5 /* tclLoadDl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDl.c; sourceTree = ""; }; F96D445B08F272B9004A47F5 /* tclLoadDyld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadDyld.c; sourceTree = ""; }; F96D445C08F272B9004A47F5 /* tclLoadNext.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadNext.c; sourceTree = ""; }; F96D445D08F272B9004A47F5 /* tclLoadOSF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadOSF.c; sourceTree = ""; }; F96D445E08F272B9004A47F5 /* tclLoadShl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclLoadShl.c; sourceTree = ""; }; F96D445F08F272B9004A47F5 /* tclUnixChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixChan.c; sourceTree = ""; }; F96D446008F272B9004A47F5 /* tclUnixEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixEvent.c; sourceTree = ""; }; F96D446108F272B9004A47F5 /* tclUnixFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFCmd.c; sourceTree = ""; }; F96D446208F272B9004A47F5 /* tclUnixFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixFile.c; sourceTree = ""; }; F96D446308F272B9004A47F5 /* tclUnixInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixInit.c; sourceTree = ""; }; F96D446408F272B9004A47F5 /* tclUnixNotfy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixNotfy.c; sourceTree = ""; }; F96D446508F272B9004A47F5 /* tclUnixPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixPipe.c; sourceTree = ""; }; F96D446608F272B9004A47F5 /* tclUnixPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclUnixPort.h; sourceTree = ""; }; F96D446708F272B9004A47F5 /* tclUnixSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixSock.c; sourceTree = ""; }; F96D446808F272B9004A47F5 /* tclUnixTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTest.c; sourceTree = ""; }; F96D446908F272B9004A47F5 /* tclUnixThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixThrd.c; sourceTree = ""; }; F96D446B08F272B9004A47F5 /* tclUnixTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixTime.c; sourceTree = ""; }; F96D446C08F272B9004A47F5 /* tclXtNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtNotify.c; sourceTree = ""; }; F96D446D08F272B9004A47F5 /* tclXtTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclXtTest.c; sourceTree = ""; }; F96D447008F272BA004A47F5 /* aclocal.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = aclocal.m4; sourceTree = ""; }; F96D447108F272BA004A47F5 /* buildall.vc.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = buildall.vc.bat; sourceTree = ""; }; F96D447208F272BA004A47F5 /* cat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cat.c; sourceTree = ""; }; F96D447308F272BA004A47F5 /* coffbase.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = coffbase.txt; sourceTree = ""; }; F96D447408F272BA004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = ""; }; F96D447508F272BA004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = ""; }; F96D447608F272BA004A47F5 /* makefile.bc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.bc; sourceTree = ""; }; F96D447708F272BA004A47F5 /* Makefile.in */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = Makefile.in; sourceTree = ""; }; F96D447808F272BA004A47F5 /* makefile.vc */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = makefile.vc; sourceTree = ""; }; F96D447908F272BA004A47F5 /* nmakehlp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmakehlp.c; sourceTree = ""; }; F96D447A08F272BA004A47F5 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; F96D447C08F272BA004A47F5 /* rules.vc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = rules.vc; sourceTree = ""; }; F96D447D08F272BA004A47F5 /* stub16.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stub16.c; sourceTree = ""; }; F96D447E08F272BA004A47F5 /* tcl.dsp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsp; sourceTree = ""; }; F96D447F08F272BA004A47F5 /* tcl.dsw */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.dsw; sourceTree = ""; }; F96D448008F272BA004A47F5 /* tcl.hpj.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.hpj.in; sourceTree = ""; }; F96D448108F272BA004A47F5 /* tcl.m4 */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tcl.m4; sourceTree = ""; }; F96D448208F272BA004A47F5 /* tcl.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.rc; sourceTree = ""; }; F96D448308F272BA004A47F5 /* tclAppInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclAppInit.c; sourceTree = ""; }; F96D448408F272BA004A47F5 /* tclConfig.sh.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = tclConfig.sh.in; sourceTree = ""; }; F96D448608F272BA004A47F5 /* tclsh.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tclsh.rc; sourceTree = ""; }; F96D448708F272BA004A47F5 /* tclWin32Dll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWin32Dll.c; sourceTree = ""; }; F96D448808F272BA004A47F5 /* tclWinChan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinChan.c; sourceTree = ""; }; F96D448908F272BA004A47F5 /* tclWinConsole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinConsole.c; sourceTree = ""; }; F96D448A08F272BA004A47F5 /* tclWinDde.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinDde.c; sourceTree = ""; }; F96D448B08F272BA004A47F5 /* tclWinError.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinError.c; sourceTree = ""; }; F96D448C08F272BA004A47F5 /* tclWinFCmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFCmd.c; sourceTree = ""; }; F96D448D08F272BA004A47F5 /* tclWinFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinFile.c; sourceTree = ""; }; F96D448E08F272BA004A47F5 /* tclWinInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinInit.c; sourceTree = ""; }; F96D448F08F272BA004A47F5 /* tclWinInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinInt.h; sourceTree = ""; }; F96D449008F272BA004A47F5 /* tclWinLoad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinLoad.c; sourceTree = ""; }; F96D449108F272BA004A47F5 /* tclWinNotify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinNotify.c; sourceTree = ""; }; F96D449208F272BA004A47F5 /* tclWinPipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinPipe.c; sourceTree = ""; }; F96D449308F272BA004A47F5 /* tclWinPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinPort.h; sourceTree = ""; }; F96D449408F272BA004A47F5 /* tclWinReg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinReg.c; sourceTree = ""; }; F96D449508F272BA004A47F5 /* tclWinSerial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSerial.c; sourceTree = ""; }; F96D449608F272BA004A47F5 /* tclWinSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinSock.c; sourceTree = ""; }; F96D449708F272BA004A47F5 /* tclWinTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTest.c; sourceTree = ""; }; F96D449808F272BA004A47F5 /* tclWinThrd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinThrd.c; sourceTree = ""; }; F96D449908F272BA004A47F5 /* tclWinThrd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclWinThrd.h; sourceTree = ""; }; F96D449A08F272BA004A47F5 /* tclWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclWinTime.c; sourceTree = ""; }; F974D56C0FBE7D6300BF728B /* http11.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = http11.test; sourceTree = ""; }; F974D56D0FBE7D6300BF728B /* httpd11.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = httpd11.tcl; sourceTree = ""; }; F974D5720FBE7DC600BF728B /* coroutine.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = coroutine.n; sourceTree = ""; }; F974D5760FBE7E1900BF728B /* tailcall.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = tailcall.n; sourceTree = ""; }; F974D5770FBE7E6100BF728B /* coroutine.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = coroutine.test; sourceTree = ""; }; F974D5780FBE7E6100BF728B /* tailcall.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tailcall.test; sourceTree = ""; }; F974D5790FBE7E9C00BF728B /* tcl.pc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tcl.pc.in; sourceTree = ""; }; F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Common.xcconfig"; sourceTree = ""; }; F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Release.xcconfig"; sourceTree = ""; }; F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Tcl-Debug.xcconfig"; sourceTree = ""; }; F9903CAF094FAADA004613E9 /* tclTomMath.decls */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = tclTomMath.decls; sourceTree = ""; }; F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tclTomMathDecls.h; sourceTree = ""; }; F99D61180EF5573A00BBFE01 /* TclZlib.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = TclZlib.3; sourceTree = ""; }; F9A3084B08F2D4CE00BAE1AB /* tclsh */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tclsh; sourceTree = BUILT_PRODUCTS_DIR; }; F9A3084E08F2D4F400BAE1AB /* Tcl.framework */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = Tcl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F9A493240CEBF38300B78AE2 /* chanio.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = chanio.test; sourceTree = ""; }; F9ECB1120B26521500A28025 /* pkgIndex.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = pkgIndex.tcl; sourceTree = ""; }; F9ECB1130B26521500A28025 /* platform.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = platform.tcl; sourceTree = ""; }; F9ECB1140B26521500A28025 /* shell.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = shell.tcl; sourceTree = ""; }; F9ECB1CA0B2652D300A28025 /* apply.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = apply.test; sourceTree = ""; }; F9ECB1CB0B26534C00A28025 /* mathop.test */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = mathop.test; sourceTree = ""; }; F9ECB1E10B26543C00A28025 /* platform_shell.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform_shell.n; sourceTree = ""; }; F9ECB1E20B26543C00A28025 /* platform.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = platform.n; sourceTree = ""; }; F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = tclDTrace.d; sourceTree = ""; }; F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tclUnixCompat.c; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 8DD76FAD0486AB0100D96B5E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( F966C07508F2820D005CB29B /* CoreFoundation.framework in Frameworks */, F96437E70EF0D652003F468E /* libz.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 08FB7794FE84155DC02AAC07 /* Tcl */ = { isa = PBXGroup; children = ( F96D3DF608F27169004A47F5 /* Tcl Sources */, F966C06F08F281DC005CB29B /* Frameworks */, 1AB674ADFE9D54B511CA2CBB /* Products */, ); comments = "Copyright (c) 2004-2009 Daniel A. Steffen \nCopyright 2008-2009, Apple Inc.\n\nSee the file \"license.terms\" for information on usage and redistribution of\nthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n\n"; name = Tcl; path = .; sourceTree = SOURCE_ROOT; }; 1AB674ADFE9D54B511CA2CBB /* Products */ = { isa = PBXGroup; children = ( F9A3084B08F2D4CE00BAE1AB /* tclsh */, 8DD76FB20486AB0100D96B5E /* tcltest */, F9A3084E08F2D4F400BAE1AB /* Tcl.framework */, ); includeInIndex = 0; name = Products; sourceTree = ""; }; F9183E690EFC81560030B814 /* pkgs */ = { isa = PBXGroup; children = ( F9183E6A0EFC81560030B814 /* README */, F946FB8B0FBE3AED00CD6495 /* itcl */, F9183E8F0EFC817B0030B814 /* tdbc */, ); path = pkgs; sourceTree = ""; }; F966C06F08F281DC005CB29B /* Frameworks */ = { isa = PBXGroup; children = ( F966C07408F2820D005CB29B /* CoreFoundation.framework */, F96437E60EF0D652003F468E /* libz.dylib */, ); name = Frameworks; sourceTree = ""; }; F96D3DF608F27169004A47F5 /* Tcl Sources */ = { isa = PBXGroup; children = ( F96D3EC908F272A7004A47F5 /* generic */, F96D432C08F272B4004A47F5 /* macosx */, F96D443E08F272B9004A47F5 /* unix */, F96D425C08F272B2004A47F5 /* libtommath */, F96D446E08F272B9004A47F5 /* win */, F96D3F3808F272A7004A47F5 /* library */, F96D434408F272B5004A47F5 /* tests */, F96D3DFC08F272A4004A47F5 /* doc */, F96D43D008F272B8004A47F5 /* tools */, F9183E690EFC81560030B814 /* pkgs */, F96D3DFA08F272A4004A47F5 /* ChangeLog */, F96D3DFB08F272A4004A47F5 /* changes */, F96D434308F272B5004A47F5 /* README */, F96D432B08F272B4004A47F5 /* license.terms */, ); name = "Tcl Sources"; sourceTree = TCL_SRCROOT; }; F96D3DFC08F272A4004A47F5 /* doc */ = { isa = PBXGroup; children = ( F96D3DFD08F272A4004A47F5 /* Access.3 */, F96D3DFE08F272A4004A47F5 /* AddErrInfo.3 */, F96D3DFF08F272A4004A47F5 /* after.n */, F96D3E0008F272A4004A47F5 /* Alloc.3 */, F96D3E0108F272A4004A47F5 /* AllowExc.3 */, F96D3E0208F272A4004A47F5 /* append.n */, F96D3E0308F272A4004A47F5 /* AppInit.3 */, F96D3E0408F272A5004A47F5 /* array.n */, F96D3E0508F272A5004A47F5 /* AssocData.3 */, F96D3E0608F272A5004A47F5 /* Async.3 */, F96D3E0708F272A5004A47F5 /* BackgdErr.3 */, F96D3E0808F272A5004A47F5 /* Backslash.3 */, F96D3E0908F272A5004A47F5 /* bgerror.n */, F96D3E0A08F272A5004A47F5 /* binary.n */, F96D3E0B08F272A5004A47F5 /* BoolObj.3 */, F96D3E0C08F272A5004A47F5 /* break.n */, F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */, F96D3E0E08F272A5004A47F5 /* CallDel.3 */, F96D3E0F08F272A5004A47F5 /* case.n */, F96D3E1008F272A5004A47F5 /* catch.n */, F96D3E1108F272A5004A47F5 /* cd.n */, F96D3E1208F272A5004A47F5 /* chan.n */, F96D3E1308F272A5004A47F5 /* ChnlStack.3 */, F93599CF0DF1F87F00E04F67 /* Class.3 */, F93599D00DF1F89E00E04F67 /* class.n */, F96D3E1408F272A5004A47F5 /* clock.n */, F96D3E1508F272A5004A47F5 /* close.n */, F96D3E1608F272A5004A47F5 /* CmdCmplt.3 */, F96D3E1708F272A5004A47F5 /* Concat.3 */, F96D3E1808F272A5004A47F5 /* concat.n */, F96D3E1908F272A5004A47F5 /* continue.n */, F93599D20DF1F8DF00E04F67 /* copy.n */, F974D5720FBE7DC600BF728B /* coroutine.n */, F96D3E1A08F272A5004A47F5 /* CrtChannel.3 */, F96D3E1B08F272A5004A47F5 /* CrtChnlHdlr.3 */, F96D3E1C08F272A5004A47F5 /* CrtCloseHdlr.3 */, F96D3E1D08F272A5004A47F5 /* CrtCommand.3 */, F96D3E1E08F272A5004A47F5 /* CrtFileHdlr.3 */, F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */, F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */, F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */, F96D3E2208F272A5004A47F5 /* CrtSlave.3 */, F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */, F96D3E2408F272A5004A47F5 /* CrtTrace.3 */, F96D3E2508F272A5004A47F5 /* dde.n */, F93599D30DF1F8F500E04F67 /* define.n */, F96D3E2608F272A5004A47F5 /* DetachPids.3 */, F96D3E2708F272A5004A47F5 /* dict.n */, F96D3E2808F272A5004A47F5 /* DictObj.3 */, F96D3E2908F272A5004A47F5 /* DoOneEvent.3 */, F96D3E2A08F272A5004A47F5 /* DoubleObj.3 */, F96D3E2B08F272A5004A47F5 /* DoWhenIdle.3 */, F96D3E2C08F272A5004A47F5 /* DString.3 */, F96D3E2D08F272A5004A47F5 /* DumpActiveMemory.3 */, F96D3E2E08F272A5004A47F5 /* Encoding.3 */, F96D3E2F08F272A5004A47F5 /* encoding.n */, F96D3E3008F272A5004A47F5 /* Ensemble.3 */, F96D3E3108F272A5004A47F5 /* Environment.3 */, F96D3E3208F272A5004A47F5 /* eof.n */, F96D3E3308F272A5004A47F5 /* error.n */, F96D3E3408F272A5004A47F5 /* Eval.3 */, F96D3E3508F272A5004A47F5 /* eval.n */, F96D3E3608F272A5004A47F5 /* exec.n */, F96D3E3708F272A5004A47F5 /* Exit.3 */, F96D3E3808F272A5004A47F5 /* exit.n */, F96D3E3908F272A5004A47F5 /* expr.n */, F96D3E3A08F272A5004A47F5 /* ExprLong.3 */, F96D3E3B08F272A5004A47F5 /* ExprLongObj.3 */, F96D3E3C08F272A5004A47F5 /* fblocked.n */, F96D3E3D08F272A5004A47F5 /* fconfigure.n */, F96D3E3E08F272A5004A47F5 /* fcopy.n */, F96D3E3F08F272A5004A47F5 /* file.n */, F96D3E4008F272A5004A47F5 /* fileevent.n */, F96D3E4108F272A5004A47F5 /* filename.n */, F96D3E4208F272A5004A47F5 /* FileSystem.3 */, F96D3E4308F272A5004A47F5 /* FindExec.3 */, F96D3E4408F272A5004A47F5 /* flush.n */, F96D3E4508F272A5004A47F5 /* for.n */, F96D3E4608F272A5004A47F5 /* foreach.n */, F96D3E4708F272A5004A47F5 /* format.n */, F96D3E4808F272A5004A47F5 /* GetCwd.3 */, F96D3E4908F272A5004A47F5 /* GetHostName.3 */, F96D3E4A08F272A5004A47F5 /* GetIndex.3 */, F96D3E4B08F272A5004A47F5 /* GetInt.3 */, F96D3E4C08F272A5004A47F5 /* GetOpnFl.3 */, F96D3E4D08F272A5004A47F5 /* gets.n */, F96D3E4E08F272A5004A47F5 /* GetStdChan.3 */, F96D3E4F08F272A5004A47F5 /* GetTime.3 */, F96D3E5008F272A5004A47F5 /* GetVersion.3 */, F96D3E5108F272A5004A47F5 /* glob.n */, F96D3E5208F272A6004A47F5 /* global.n */, F96D3E5308F272A6004A47F5 /* Hash.3 */, F96D3E5408F272A6004A47F5 /* history.n */, F96D3E5508F272A6004A47F5 /* http.n */, F96D3E5608F272A6004A47F5 /* if.n */, F96D3E5708F272A6004A47F5 /* incr.n */, F96D3E5808F272A6004A47F5 /* info.n */, F96D3E5908F272A6004A47F5 /* Init.3 */, F96D3E5A08F272A6004A47F5 /* InitStubs.3 */, F96D3E5B08F272A6004A47F5 /* Interp.3 */, F96D3E5C08F272A6004A47F5 /* interp.n */, F96D3E5D08F272A6004A47F5 /* IntObj.3 */, F96D3E5E08F272A6004A47F5 /* join.n */, F96D3E5F08F272A6004A47F5 /* lappend.n */, F96D3E6008F272A6004A47F5 /* lassign.n */, F96D3E6108F272A6004A47F5 /* library.n */, F96D3E6208F272A6004A47F5 /* Limit.3 */, F96D3E6308F272A6004A47F5 /* lindex.n */, F96D3E6408F272A6004A47F5 /* LinkVar.3 */, F96D3E6508F272A6004A47F5 /* linsert.n */, F96D3E6608F272A6004A47F5 /* list.n */, F96D3E6708F272A6004A47F5 /* ListObj.3 */, F96D3E6808F272A6004A47F5 /* llength.n */, F96D3E6908F272A6004A47F5 /* load.n */, F96D3E6A08F272A6004A47F5 /* lrange.n */, F96D3E6B08F272A6004A47F5 /* lrepeat.n */, F96D3E6C08F272A6004A47F5 /* lreplace.n */, F96D3E6D08F272A6004A47F5 /* lsearch.n */, F96D3E6E08F272A6004A47F5 /* lset.n */, F96D3E6F08F272A6004A47F5 /* lsort.n */, F96D3E7008F272A6004A47F5 /* man.macros */, F96D3E7108F272A6004A47F5 /* mathfunc.n */, F96D3E7208F272A6004A47F5 /* memory.n */, F93599D40DF1F91900E04F67 /* Method.3 */, F96D3E7308F272A6004A47F5 /* msgcat.n */, F93599D50DF1F93700E04F67 /* my.n */, F96D3E7408F272A6004A47F5 /* Namespace.3 */, F96D3E7508F272A6004A47F5 /* namespace.n */, F93599D60DF1F95000E04F67 /* next.n */, F96D3E7608F272A6004A47F5 /* Notifier.3 */, F96D3E7708F272A6004A47F5 /* Object.3 */, F93599D70DF1F96800E04F67 /* object.n */, F96D3E7808F272A6004A47F5 /* ObjectType.3 */, F96D3E7908F272A6004A47F5 /* open.n */, F96D3E7A08F272A6004A47F5 /* OpenFileChnl.3 */, F96D3E7B08F272A6004A47F5 /* OpenTcp.3 */, F96D3E7C08F272A6004A47F5 /* package.n */, F96D3E7D08F272A6004A47F5 /* packagens.n */, F96D3E7E08F272A6004A47F5 /* Panic.3 */, F96D3E7F08F272A6004A47F5 /* ParseCmd.3 */, F96D3E8008F272A6004A47F5 /* pid.n */, F96D3E8108F272A6004A47F5 /* pkgMkIndex.n */, F96D3E8208F272A6004A47F5 /* PkgRequire.3 */, F9ECB1E10B26543C00A28025 /* platform_shell.n */, F9ECB1E20B26543C00A28025 /* platform.n */, F96D3E8308F272A6004A47F5 /* Preserve.3 */, F96D3E8408F272A6004A47F5 /* PrintDbl.3 */, F96D3E8508F272A6004A47F5 /* proc.n */, F96D3E8608F272A6004A47F5 /* puts.n */, F96D3E8708F272A6004A47F5 /* pwd.n */, F96D3E8808F272A6004A47F5 /* re_syntax.n */, F96D3E8908F272A6004A47F5 /* read.n */, F96D3E8A08F272A6004A47F5 /* RecEvalObj.3 */, F96D3E8B08F272A6004A47F5 /* RecordEval.3 */, F96D3E8C08F272A6004A47F5 /* RegConfig.3 */, F96D3E8D08F272A6004A47F5 /* RegExp.3 */, F96D3E8E08F272A6004A47F5 /* regexp.n */, F96D3E8F08F272A6004A47F5 /* registry.n */, F96D3E9008F272A6004A47F5 /* regsub.n */, F96D3E9108F272A6004A47F5 /* rename.n */, F96D3E9208F272A6004A47F5 /* return.n */, F96D3E9308F272A6004A47F5 /* safe.n */, F96D3E9408F272A6004A47F5 /* SaveResult.3 */, F96D3E9508F272A6004A47F5 /* scan.n */, F96D3E9608F272A6004A47F5 /* seek.n */, F93599D80DF1F98300E04F67 /* self.n */, F96D3E9708F272A6004A47F5 /* set.n */, F96D3E9808F272A6004A47F5 /* SetChanErr.3 */, F96D3E9908F272A6004A47F5 /* SetErrno.3 */, F96D3E9A08F272A6004A47F5 /* SetRecLmt.3 */, F96D3E9B08F272A7004A47F5 /* SetResult.3 */, F96D3E9C08F272A7004A47F5 /* SetVar.3 */, F96D3E9D08F272A7004A47F5 /* Signal.3 */, F96D3E9E08F272A7004A47F5 /* Sleep.3 */, F96D3E9F08F272A7004A47F5 /* socket.n */, F96D3EA008F272A7004A47F5 /* source.n */, F96D3EA108F272A7004A47F5 /* SourceRCFile.3 */, F96D3EA208F272A7004A47F5 /* split.n */, F96D3EA308F272A7004A47F5 /* SplitList.3 */, F96D3EA408F272A7004A47F5 /* SplitPath.3 */, F96D3EA508F272A7004A47F5 /* StaticPkg.3 */, F96D3EA608F272A7004A47F5 /* StdChannels.3 */, F96D3EA708F272A7004A47F5 /* string.n */, F96D3EA808F272A7004A47F5 /* StringObj.3 */, F96D3EA908F272A7004A47F5 /* StrMatch.3 */, F96D3EAA08F272A7004A47F5 /* subst.n */, F96D3EAB08F272A7004A47F5 /* SubstObj.3 */, F96D3EAC08F272A7004A47F5 /* switch.n */, F974D5760FBE7E1900BF728B /* tailcall.n */, F96D3EAD08F272A7004A47F5 /* Tcl.n */, F99D61180EF5573A00BBFE01 /* TclZlib.3 */, F96D3EAE08F272A7004A47F5 /* Tcl_Main.3 */, F96D3EAF08F272A7004A47F5 /* TCL_MEM_DEBUG.3 */, F96D3EB008F272A7004A47F5 /* tclsh.1 */, F96D3EB108F272A7004A47F5 /* tcltest.n */, F96D3EB208F272A7004A47F5 /* tclvars.n */, F96D3EB308F272A7004A47F5 /* tell.n */, F96D3EB408F272A7004A47F5 /* Thread.3 */, F9183E640EFC80CD0030B814 /* throw.n */, F96D3EB508F272A7004A47F5 /* time.n */, F96D3EB608F272A7004A47F5 /* tm.n */, F96D3EB708F272A7004A47F5 /* ToUpper.3 */, F96D3EB808F272A7004A47F5 /* trace.n */, F96D3EB908F272A7004A47F5 /* TraceCmd.3 */, F96D3EBA08F272A7004A47F5 /* TraceVar.3 */, F96D3EBB08F272A7004A47F5 /* Translate.3 */, F9183E650EFC80D70030B814 /* try.n */, F96D3EBC08F272A7004A47F5 /* UniCharIsAlpha.3 */, F96D3EBD08F272A7004A47F5 /* unknown.n */, F96D3EBE08F272A7004A47F5 /* unload.n */, F96D3EBF08F272A7004A47F5 /* unset.n */, F96D3EC008F272A7004A47F5 /* update.n */, F96D3EC108F272A7004A47F5 /* uplevel.n */, F96D3EC208F272A7004A47F5 /* UpVar.3 */, F96D3EC308F272A7004A47F5 /* upvar.n */, F96D3EC408F272A7004A47F5 /* Utf.3 */, F96D3EC508F272A7004A47F5 /* variable.n */, F96D3EC608F272A7004A47F5 /* vwait.n */, F96D3EC708F272A7004A47F5 /* while.n */, F96D3EC808F272A7004A47F5 /* WrongNumArgs.3 */, F915432D0EF201EE0032D1E8 /* zlib.n */, ); path = doc; sourceTree = ""; }; F96D3EC908F272A7004A47F5 /* generic */ = { isa = PBXGroup; children = ( F96D3ECA08F272A7004A47F5 /* README */, F96D3ECB08F272A7004A47F5 /* regc_color.c */, F96D3ECC08F272A7004A47F5 /* regc_cvec.c */, F96D3ECD08F272A7004A47F5 /* regc_lex.c */, F96D3ECE08F272A7004A47F5 /* regc_locale.c */, F96D3ECF08F272A7004A47F5 /* regc_nfa.c */, F96D3ED008F272A7004A47F5 /* regcomp.c */, F96D3ED108F272A7004A47F5 /* regcustom.h */, F96D3ED208F272A7004A47F5 /* rege_dfa.c */, F96D3ED308F272A7004A47F5 /* regerror.c */, F96D3ED408F272A7004A47F5 /* regerrs.h */, F96D3ED508F272A7004A47F5 /* regex.h */, F96D3ED608F272A7004A47F5 /* regexec.c */, F96D3ED708F272A7004A47F5 /* regfree.c */, F96D3ED808F272A7004A47F5 /* regfronts.c */, F96D3ED908F272A7004A47F5 /* regguts.h */, F96D3EDA08F272A7004A47F5 /* tcl.decls */, F96D3EDB08F272A7004A47F5 /* tcl.h */, F96D3EDC08F272A7004A47F5 /* tclAlloc.c */, F96D3EDD08F272A7004A47F5 /* tclAsync.c */, F96D3EDE08F272A7004A47F5 /* tclBasic.c */, F96D3EDF08F272A7004A47F5 /* tclBinary.c */, F96D3EE008F272A7004A47F5 /* tclCkalloc.c */, F96D3EE108F272A7004A47F5 /* tclClock.c */, F96D3EE208F272A7004A47F5 /* tclCmdAH.c */, F96D3EE308F272A7004A47F5 /* tclCmdIL.c */, F96D3EE408F272A7004A47F5 /* tclCmdMZ.c */, F96D3EE508F272A7004A47F5 /* tclCompCmds.c */, F96D3EE608F272A7004A47F5 /* tclCompExpr.c */, F96D3EE708F272A7004A47F5 /* tclCompile.c */, F96D3EE808F272A7004A47F5 /* tclCompile.h */, F96D3EE908F272A7004A47F5 /* tclConfig.c */, F96D3EEA08F272A7004A47F5 /* tclDate.c */, F96D3EEB08F272A7004A47F5 /* tclDecls.h */, F96D3EEC08F272A7004A47F5 /* tclDictObj.c */, F9F4415D0C8BAE6F00BCCD67 /* tclDTrace.d */, F96D3EED08F272A7004A47F5 /* tclEncoding.c */, F96D3EEE08F272A7004A47F5 /* tclEnv.c */, F96D3EEF08F272A7004A47F5 /* tclEvent.c */, F96D3EF008F272A7004A47F5 /* tclExecute.c */, F96D3EF108F272A7004A47F5 /* tclFCmd.c */, F96D3EF208F272A7004A47F5 /* tclFileName.c */, F96D3EF308F272A7004A47F5 /* tclFileSystem.h */, F96D3EF408F272A7004A47F5 /* tclGet.c */, F96D3EF508F272A7004A47F5 /* tclGetDate.y */, F96D3EF608F272A7004A47F5 /* tclHash.c */, F96D3EF708F272A7004A47F5 /* tclHistory.c */, F96D3EF808F272A7004A47F5 /* tclIndexObj.c */, F96D3EF908F272A7004A47F5 /* tclInt.decls */, F96D3EFA08F272A7004A47F5 /* tclInt.h */, F96D3EFB08F272A7004A47F5 /* tclIntDecls.h */, F96D3EFC08F272A7004A47F5 /* tclInterp.c */, F96D3EFD08F272A7004A47F5 /* tclIntPlatDecls.h */, F96D3EFE08F272A7004A47F5 /* tclIO.c */, F96D3EFF08F272A7004A47F5 /* tclIO.h */, F96D3F0008F272A7004A47F5 /* tclIOCmd.c */, F96D3F0108F272A7004A47F5 /* tclIOGT.c */, F96D3F0208F272A7004A47F5 /* tclIORChan.c */, F95D77E90DFD820D00A8BF6F /* tclIORTrans.c */, F96D3F0308F272A7004A47F5 /* tclIOSock.c */, F96D3F0408F272A7004A47F5 /* tclIOUtil.c */, F96D3F0508F272A7004A47F5 /* tclLink.c */, F96D3F0608F272A7004A47F5 /* tclListObj.c */, F96D3F0708F272A7004A47F5 /* tclLiteral.c */, F96D3F0808F272A7004A47F5 /* tclLoad.c */, F96D3F0908F272A7004A47F5 /* tclLoadNone.c */, F96D3F0A08F272A7004A47F5 /* tclMain.c */, F96D3F0B08F272A7004A47F5 /* tclNamesp.c */, F96D3F0C08F272A7004A47F5 /* tclNotify.c */, F96D3F0D08F272A7004A47F5 /* tclObj.c */, F93599B20DF1F75400E04F67 /* tclOO.c */, F93599B40DF1F75900E04F67 /* tclOO.decls */, F93599B50DF1F75D00E04F67 /* tclOO.h */, F93599B60DF1F76100E04F67 /* tclOOBasic.c */, F93599B80DF1F76600E04F67 /* tclOOCall.c */, F93599BA0DF1F76A00E04F67 /* tclOODecls.h */, F93599BB0DF1F77000E04F67 /* tclOODefineCmds.c */, F93599BD0DF1F77400E04F67 /* tclOOInfo.c */, F93599BF0DF1F77900E04F67 /* tclOOInt.h */, F93599C00DF1F77D00E04F67 /* tclOOIntDecls.h */, F93599C10DF1F78300E04F67 /* tclOOMethod.c */, F93599C30DF1F78800E04F67 /* tclOOStubInit.c */, F93599C50DF1F78D00E04F67 /* tclOOStubLib.c */, F96D3F0E08F272A7004A47F5 /* tclPanic.c */, F96D3F0F08F272A7004A47F5 /* tclParse.c */, F96D3F1108F272A7004A47F5 /* tclPathObj.c */, F96D3F1208F272A7004A47F5 /* tclPipe.c */, F96D3F1308F272A7004A47F5 /* tclPkg.c */, F96D3F1408F272A7004A47F5 /* tclPkgConfig.c */, F96D3F1508F272A7004A47F5 /* tclPlatDecls.h */, F96D3F1608F272A7004A47F5 /* tclPort.h */, F96D3F1708F272A7004A47F5 /* tclPosixStr.c */, F96D3F1808F272A7004A47F5 /* tclPreserve.c */, F96D3F1908F272A7004A47F5 /* tclProc.c */, F96D3F1A08F272A7004A47F5 /* tclRegexp.c */, F96D3F1B08F272A7004A47F5 /* tclRegexp.h */, F96D3F1C08F272A7004A47F5 /* tclResolve.c */, F96D3F1D08F272A7004A47F5 /* tclResult.c */, F96D3F1E08F272A7004A47F5 /* tclScan.c */, F96D3F1F08F272A7004A47F5 /* tclStringObj.c */, F96D3F2408F272A7004A47F5 /* tclStrToD.c */, F96D3F2508F272A7004A47F5 /* tclStubInit.c */, F96D3F2608F272A7004A47F5 /* tclStubLib.c */, F96D3F2708F272A7004A47F5 /* tclTest.c */, F96D3F2808F272A7004A47F5 /* tclTestObj.c */, F96D3F2908F272A7004A47F5 /* tclTestProcBodyObj.c */, F96D3F2A08F272A7004A47F5 /* tclThread.c */, F96D3F2B08F272A7004A47F5 /* tclThreadAlloc.c */, F96D3F2C08F272A7004A47F5 /* tclThreadJoin.c */, F96D3F2D08F272A7004A47F5 /* tclThreadStorage.c */, F96D3F2E08F272A7004A47F5 /* tclThreadTest.c */, F96D3F2F08F272A7004A47F5 /* tclTimer.c */, F9903CAF094FAADA004613E9 /* tclTomMath.decls */, F96D3F3008F272A7004A47F5 /* tclTomMath.h */, F9903CB0094FAADA004613E9 /* tclTomMathDecls.h */, F96D3F3108F272A7004A47F5 /* tclTomMathInterface.c */, F96D3F3208F272A7004A47F5 /* tclTrace.c */, F96D3F3308F272A7004A47F5 /* tclUniData.c */, F96D3F3408F272A7004A47F5 /* tclUtf.c */, F96D3F3508F272A7004A47F5 /* tclUtil.c */, F96D3F3608F272A7004A47F5 /* tclVar.c */, F96437C90EF0D4B2003F468E /* tclZlib.c */, F96D3F3708F272A7004A47F5 /* tommath.h */, ); path = generic; sourceTree = ""; }; F96D3F3808F272A7004A47F5 /* library */ = { isa = PBXGroup; children = ( F96D3F3908F272A8004A47F5 /* auto.tcl */, F96D3F3A08F272A8004A47F5 /* clock.tcl */, F96D3F3B08F272A8004A47F5 /* dde */, F96D3F8C08F272A8004A47F5 /* history.tcl */, F96D3F8D08F272A8004A47F5 /* http */, F96D3F9008F272A8004A47F5 /* http1.0 */, F96D3F9308F272A8004A47F5 /* init.tcl */, F96D3F9408F272A8004A47F5 /* msgcat */, F96D401708F272AA004A47F5 /* opt */, F96D401A08F272AA004A47F5 /* package.tcl */, F96D401B08F272AA004A47F5 /* parray.tcl */, F9ECB1110B26521500A28025 /* platform */, F96D401C08F272AA004A47F5 /* reg */, F96D401E08F272AA004A47F5 /* safe.tcl */, F96D401F08F272AA004A47F5 /* tclIndex */, F96D402008F272AA004A47F5 /* tcltest */, F96D402308F272AA004A47F5 /* tm.tcl */, F96D425B08F272B2004A47F5 /* word.tcl */, ); path = library; sourceTree = ""; }; F96D3F3B08F272A8004A47F5 /* dde */ = { isa = PBXGroup; children = ( F96D3F3C08F272A8004A47F5 /* pkgIndex.tcl */, ); path = dde; sourceTree = ""; }; F96D3F8D08F272A8004A47F5 /* http */ = { isa = PBXGroup; children = ( F96D3F8E08F272A8004A47F5 /* http.tcl */, F96D3F8F08F272A8004A47F5 /* pkgIndex.tcl */, ); path = http; sourceTree = ""; }; F96D3F9008F272A8004A47F5 /* http1.0 */ = { isa = PBXGroup; children = ( F96D3F9108F272A8004A47F5 /* http.tcl */, F96D3F9208F272A8004A47F5 /* pkgIndex.tcl */, ); path = http1.0; sourceTree = ""; }; F96D3F9408F272A8004A47F5 /* msgcat */ = { isa = PBXGroup; children = ( F96D3F9508F272A8004A47F5 /* msgcat.tcl */, F96D3F9608F272A8004A47F5 /* pkgIndex.tcl */, ); path = msgcat; sourceTree = ""; }; F96D401708F272AA004A47F5 /* opt */ = { isa = PBXGroup; children = ( F96D401808F272AA004A47F5 /* optparse.tcl */, F96D401908F272AA004A47F5 /* pkgIndex.tcl */, ); path = opt; sourceTree = ""; }; F96D401C08F272AA004A47F5 /* reg */ = { isa = PBXGroup; children = ( F96D401D08F272AA004A47F5 /* pkgIndex.tcl */, ); path = reg; sourceTree = ""; }; F96D402008F272AA004A47F5 /* tcltest */ = { isa = PBXGroup; children = ( F96D402108F272AA004A47F5 /* pkgIndex.tcl */, F96D402208F272AA004A47F5 /* tcltest.tcl */, ); path = tcltest; sourceTree = ""; }; F96D425C08F272B2004A47F5 /* libtommath */ = { isa = PBXGroup; children = ( F96D426408F272B3004A47F5 /* bn_fast_s_mp_mul_digs.c */, F96D426608F272B3004A47F5 /* bn_fast_s_mp_sqr.c */, F96D426908F272B3004A47F5 /* bn_mp_add.c */, F96D426A08F272B3004A47F5 /* bn_mp_add_d.c */, F96D426C08F272B3004A47F5 /* bn_mp_and.c */, F96D426D08F272B3004A47F5 /* bn_mp_clamp.c */, F96D426E08F272B3004A47F5 /* bn_mp_clear.c */, F96D426F08F272B3004A47F5 /* bn_mp_clear_multi.c */, F96D427008F272B3004A47F5 /* bn_mp_cmp.c */, F96D427108F272B3004A47F5 /* bn_mp_cmp_d.c */, F96D427208F272B3004A47F5 /* bn_mp_cmp_mag.c */, F96D427408F272B3004A47F5 /* bn_mp_copy.c */, F96D427508F272B3004A47F5 /* bn_mp_count_bits.c */, F96D427608F272B3004A47F5 /* bn_mp_div.c */, F96D427708F272B3004A47F5 /* bn_mp_div_2.c */, F96D427808F272B3004A47F5 /* bn_mp_div_2d.c */, F96D427908F272B3004A47F5 /* bn_mp_div_3.c */, F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */, F96D427E08F272B3004A47F5 /* bn_mp_exch.c */, F96D427F08F272B3004A47F5 /* bn_mp_expt_d.c */, F96D428708F272B3004A47F5 /* bn_mp_grow.c */, F96D428808F272B3004A47F5 /* bn_mp_init.c */, F96D428908F272B3004A47F5 /* bn_mp_init_copy.c */, F96D428A08F272B3004A47F5 /* bn_mp_init_multi.c */, F96D428B08F272B3004A47F5 /* bn_mp_init_set.c */, F96D428D08F272B3004A47F5 /* bn_mp_init_size.c */, F96D429208F272B3004A47F5 /* bn_mp_karatsuba_mul.c */, F96D429308F272B3004A47F5 /* bn_mp_karatsuba_sqr.c */, F96D429508F272B3004A47F5 /* bn_mp_lshd.c */, F96D429608F272B3004A47F5 /* bn_mp_mod.c */, F96D429708F272B3004A47F5 /* bn_mp_mod_2d.c */, F96D429C08F272B3004A47F5 /* bn_mp_mul.c */, F96D429D08F272B3004A47F5 /* bn_mp_mul_2.c */, F96D429E08F272B3004A47F5 /* bn_mp_mul_2d.c */, F96D429F08F272B3004A47F5 /* bn_mp_mul_d.c */, F96D42A208F272B3004A47F5 /* bn_mp_neg.c */, F96D42A308F272B3004A47F5 /* bn_mp_or.c */, F96D42AB08F272B3004A47F5 /* bn_mp_radix_size.c */, F96D42AC08F272B3004A47F5 /* bn_mp_radix_smap.c */, F96D42AE08F272B3004A47F5 /* bn_mp_read_radix.c */, F96D42B908F272B3004A47F5 /* bn_mp_rshd.c */, F96D42BA08F272B3004A47F5 /* bn_mp_set.c */, F96D42BC08F272B3004A47F5 /* bn_mp_shrink.c */, F96D42BE08F272B3004A47F5 /* bn_mp_sqr.c */, F96D42C008F272B3004A47F5 /* bn_mp_sqrt.c */, F96D42C108F272B3004A47F5 /* bn_mp_sub.c */, F96D42C208F272B3004A47F5 /* bn_mp_sub_d.c */, F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */, F96D42C708F272B3004A47F5 /* bn_mp_to_unsigned_bin_n.c */, F96D42C808F272B3004A47F5 /* bn_mp_toom_mul.c */, F96D42C908F272B3004A47F5 /* bn_mp_toom_sqr.c */, F96D42CB08F272B3004A47F5 /* bn_mp_toradix_n.c */, F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */, F96D42CD08F272B3004A47F5 /* bn_mp_xor.c */, F96D42CE08F272B3004A47F5 /* bn_mp_zero.c */, F96D42D008F272B3004A47F5 /* bn_reverse.c */, F96D42D108F272B3004A47F5 /* bn_s_mp_add.c */, F96D42D308F272B3004A47F5 /* bn_s_mp_mul_digs.c */, F96D42D508F272B3004A47F5 /* bn_s_mp_sqr.c */, F96D42D608F272B3004A47F5 /* bn_s_mp_sub.c */, F96D42D708F272B3004A47F5 /* bncore.c */, F96D432908F272B4004A47F5 /* tommath_class.h */, F96D432A08F272B4004A47F5 /* tommath_superclass.h */, ); path = libtommath; sourceTree = ""; }; F96D432C08F272B4004A47F5 /* macosx */ = { isa = PBXGroup; children = ( F96D432E08F272B5004A47F5 /* configure.ac */, F96D432F08F272B5004A47F5 /* GNUmakefile */, F96D433108F272B5004A47F5 /* README */, F96D433908F272B5004A47F5 /* tclMacOSXBundle.c */, F96D433D08F272B5004A47F5 /* tclMacOSXFCmd.c */, F96D433E08F272B5004A47F5 /* tclMacOSXNotify.c */, F96D433208F272B5004A47F5 /* Tcl-Info.plist.in */, F91E62260C1AE686006C9D96 /* Tclsh-Info.plist.in */, F97AE7F10B65C1E900310EA2 /* Tcl-Common.xcconfig */, F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */, F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */, ); path = macosx; sourceTree = ""; }; F96D434408F272B5004A47F5 /* tests */ = { isa = PBXGroup; children = ( F96D434508F272B5004A47F5 /* all.tcl */, F96D434608F272B5004A47F5 /* append.test */, F96D434708F272B5004A47F5 /* appendComp.test */, F9ECB1CA0B2652D300A28025 /* apply.test */, F96D434808F272B5004A47F5 /* assocd.test */, F96D434908F272B5004A47F5 /* async.test */, F96D434A08F272B5004A47F5 /* autoMkindex.test */, F96D434B08F272B5004A47F5 /* basic.test */, F96D434C08F272B5004A47F5 /* binary.test */, F96D434D08F272B5004A47F5 /* case.test */, F96D434E08F272B5004A47F5 /* chan.test */, F9A493240CEBF38300B78AE2 /* chanio.test */, F96D434F08F272B5004A47F5 /* clock.test */, F96D435008F272B5004A47F5 /* cmdAH.test */, F96D435108F272B5004A47F5 /* cmdIL.test */, F96D435208F272B5004A47F5 /* cmdInfo.test */, F96D435308F272B5004A47F5 /* cmdMZ.test */, F96D435408F272B5004A47F5 /* compExpr-old.test */, F96D435508F272B5004A47F5 /* compExpr.test */, F96D435608F272B5004A47F5 /* compile.test */, F96D435708F272B5004A47F5 /* concat.test */, F96D435808F272B5004A47F5 /* config.test */, F974D5770FBE7E6100BF728B /* coroutine.test */, F96D435908F272B5004A47F5 /* dcall.test */, F96D435A08F272B5004A47F5 /* dict.test */, F96D435C08F272B5004A47F5 /* dstring.test */, F96D435E08F272B5004A47F5 /* encoding.test */, F96D435F08F272B5004A47F5 /* env.test */, F96D436008F272B5004A47F5 /* error.test */, F96D436108F272B5004A47F5 /* eval.test */, F96D436208F272B5004A47F5 /* event.test */, F96D436308F272B5004A47F5 /* exec.test */, F96D436408F272B5004A47F5 /* execute.test */, F96D436508F272B5004A47F5 /* expr-old.test */, F96D436608F272B5004A47F5 /* expr.test */, F96D436708F272B6004A47F5 /* fCmd.test */, F96D436808F272B6004A47F5 /* fileName.test */, F96D436908F272B6004A47F5 /* fileSystem.test */, F96D436A08F272B6004A47F5 /* for-old.test */, F96D436B08F272B6004A47F5 /* for.test */, F96D436C08F272B6004A47F5 /* foreach.test */, F96D436D08F272B6004A47F5 /* format.test */, F96D436E08F272B6004A47F5 /* get.test */, F96D436F08F272B6004A47F5 /* history.test */, F96D437008F272B6004A47F5 /* http.test */, F974D56C0FBE7D6300BF728B /* http11.test */, F96D437108F272B6004A47F5 /* httpd */, F974D56D0FBE7D6300BF728B /* httpd11.tcl */, F96D437208F272B6004A47F5 /* httpold.test */, F96D437308F272B6004A47F5 /* if-old.test */, F96D437408F272B6004A47F5 /* if.test */, F96D437508F272B6004A47F5 /* incr-old.test */, F96D437608F272B6004A47F5 /* incr.test */, F96D437708F272B6004A47F5 /* indexObj.test */, F96D437808F272B6004A47F5 /* info.test */, F96D437908F272B6004A47F5 /* init.test */, F96D437A08F272B6004A47F5 /* interp.test */, F96D437B08F272B6004A47F5 /* io.test */, F96D437C08F272B6004A47F5 /* ioCmd.test */, F96D437D08F272B6004A47F5 /* iogt.test */, F96D437F08F272B6004A47F5 /* join.test */, F96D438008F272B6004A47F5 /* lindex.test */, F96D438108F272B6004A47F5 /* link.test */, F96D438208F272B6004A47F5 /* linsert.test */, F96D438308F272B6004A47F5 /* list.test */, F96D438408F272B6004A47F5 /* listObj.test */, F96D438508F272B6004A47F5 /* llength.test */, F96D438608F272B6004A47F5 /* load.test */, F96D438708F272B6004A47F5 /* lrange.test */, F96D438808F272B6004A47F5 /* lrepeat.test */, F96D438908F272B6004A47F5 /* lreplace.test */, F96D438A08F272B6004A47F5 /* lsearch.test */, F96D438B08F272B6004A47F5 /* lset.test */, F96D438C08F272B6004A47F5 /* lsetComp.test */, F96D438D08F272B6004A47F5 /* macOSXFCmd.test */, F95FAFF90B34F1130072E431 /* macOSXLoad.test */, F96D438E08F272B6004A47F5 /* main.test */, F9ECB1CB0B26534C00A28025 /* mathop.test */, F96D438F08F272B6004A47F5 /* misc.test */, F96D439008F272B6004A47F5 /* msgcat.test */, F96D439108F272B6004A47F5 /* namespace-old.test */, F96D439208F272B7004A47F5 /* namespace.test */, F96D439308F272B7004A47F5 /* notify.test */, F91DC23C0E44C51B002CB8D1 /* nre.test */, F96D439408F272B7004A47F5 /* obj.test */, F93599C80DF1F81900E04F67 /* oo.test */, F96D439508F272B7004A47F5 /* opt.test */, F96D439608F272B7004A47F5 /* package.test */, F96D439708F272B7004A47F5 /* parse.test */, F96D439808F272B7004A47F5 /* parseExpr.test */, F96D439908F272B7004A47F5 /* parseOld.test */, F96D439A08F272B7004A47F5 /* pid.test */, F96D439B08F272B7004A47F5 /* pkg.test */, F96D439C08F272B7004A47F5 /* pkgMkIndex.test */, F96D439D08F272B7004A47F5 /* platform.test */, F96D439E08F272B7004A47F5 /* proc-old.test */, F96D439F08F272B7004A47F5 /* proc.test */, F96D43A008F272B7004A47F5 /* pwd.test */, F96D43A108F272B7004A47F5 /* README */, F96D43A208F272B7004A47F5 /* reg.test */, F96D43A308F272B7004A47F5 /* regexp.test */, F96D43A408F272B7004A47F5 /* regexpComp.test */, F96D43A508F272B7004A47F5 /* registry.test */, F96D43A608F272B7004A47F5 /* remote.tcl */, F96D43A708F272B7004A47F5 /* rename.test */, F96D43A808F272B7004A47F5 /* result.test */, F96D43A908F272B7004A47F5 /* safe.test */, F96D43AA08F272B7004A47F5 /* scan.test */, F96D43AB08F272B7004A47F5 /* security.test */, F96D43AC08F272B7004A47F5 /* set-old.test */, F96D43AD08F272B7004A47F5 /* set.test */, F96D43AE08F272B7004A47F5 /* socket.test */, F96D43AF08F272B7004A47F5 /* source.test */, F96D43B008F272B7004A47F5 /* split.test */, F96D43B108F272B7004A47F5 /* stack.test */, F96D43B208F272B7004A47F5 /* string.test */, F96D43B308F272B7004A47F5 /* stringComp.test */, F96D43B408F272B7004A47F5 /* stringObj.test */, F96D43B508F272B7004A47F5 /* subst.test */, F96D43B608F272B7004A47F5 /* switch.test */, F974D5780FBE7E6100BF728B /* tailcall.test */, F96D43B708F272B7004A47F5 /* tcltest.test */, F96D43B808F272B7004A47F5 /* thread.test */, F96D43B908F272B7004A47F5 /* timer.test */, F96D43BA08F272B7004A47F5 /* tm.test */, F96D43BB08F272B7004A47F5 /* trace.test */, F96D43BC08F272B7004A47F5 /* unixFCmd.test */, F96D43BD08F272B7004A47F5 /* unixFile.test */, F96D43BE08F272B7004A47F5 /* unixInit.test */, F96D43BF08F272B7004A47F5 /* unixNotfy.test */, F96D43C008F272B7004A47F5 /* unknown.test */, F96D43C108F272B7004A47F5 /* unload.test */, F96D43C208F272B7004A47F5 /* uplevel.test */, F96D43C308F272B7004A47F5 /* upvar.test */, F96D43C408F272B7004A47F5 /* utf.test */, F96D43C508F272B7004A47F5 /* util.test */, F96D43C608F272B7004A47F5 /* var.test */, F96D43C708F272B7004A47F5 /* while-old.test */, F96D43C808F272B7004A47F5 /* while.test */, F96D43C908F272B7004A47F5 /* winConsole.test */, F96D43CA08F272B7004A47F5 /* winDde.test */, F96D43CB08F272B7004A47F5 /* winFCmd.test */, F96D43CC08F272B7004A47F5 /* winFile.test */, F96D43CD08F272B7004A47F5 /* winNotify.test */, F96D43CE08F272B7004A47F5 /* winPipe.test */, F96D43CF08F272B7004A47F5 /* winTime.test */, F915432A0EF201CF0032D1E8 /* zlib.test */, ); path = tests; sourceTree = ""; }; F96D43D008F272B8004A47F5 /* tools */ = { isa = PBXGroup; children = ( F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */, F96D43D208F272B8004A47F5 /* configure */, F96D43D308F272B8004A47F5 /* configure.in */, F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */, F96D442508F272B8004A47F5 /* genStubs.tcl */, F96D442708F272B8004A47F5 /* index.tcl */, F96D442808F272B8004A47F5 /* installData.tcl */, F96D442908F272B8004A47F5 /* loadICU.tcl */, F96D442A08F272B8004A47F5 /* Makefile.in */, F96D442B08F272B8004A47F5 /* makeTestCases.tcl */, F96D442C08F272B8004A47F5 /* man2help.tcl */, F96D442D08F272B8004A47F5 /* man2help2.tcl */, F96D442E08F272B8004A47F5 /* man2html.tcl */, F96D442F08F272B8004A47F5 /* man2html1.tcl */, F96D443008F272B8004A47F5 /* man2html2.tcl */, F96D443108F272B8004A47F5 /* man2tcl.c */, F96D443208F272B8004A47F5 /* README */, F96D443308F272B8004A47F5 /* regexpTestLib.tcl */, F96D443508F272B8004A47F5 /* tcl.hpj.in */, F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */, F96D443A08F272B9004A47F5 /* tclZIC.tcl */, F92D7F100DE777240033A13A /* tsdPerf.tcl */, F96D443B08F272B9004A47F5 /* uniClass.tcl */, F96D443C08F272B9004A47F5 /* uniParse.tcl */, ); path = tools; sourceTree = ""; }; F96D443E08F272B9004A47F5 /* unix */ = { isa = PBXGroup; children = ( F96D444008F272B9004A47F5 /* aclocal.m4 */, F96D444108F272B9004A47F5 /* configure */, F96D444208F272B9004A47F5 /* configure.in */, F96D444308F272B9004A47F5 /* dltest */, F96D444D08F272B9004A47F5 /* install-sh */, F96D444E08F272B9004A47F5 /* installManPage */, F96D444F08F272B9004A47F5 /* ldAix */, F96D445008F272B9004A47F5 /* Makefile.in */, F96D445208F272B9004A47F5 /* README */, F96D445308F272B9004A47F5 /* tcl.m4 */, F974D5790FBE7E9C00BF728B /* tcl.pc.in */, F96D445408F272B9004A47F5 /* tcl.spec */, F96D445508F272B9004A47F5 /* tclAppInit.c */, F96D445608F272B9004A47F5 /* tclConfig.h.in */, F96D445708F272B9004A47F5 /* tclConfig.sh.in */, F96D445808F272B9004A47F5 /* tclLoadAix.c */, F96D445908F272B9004A47F5 /* tclLoadDl.c */, F96D445B08F272B9004A47F5 /* tclLoadDyld.c */, F96D445C08F272B9004A47F5 /* tclLoadNext.c */, F96D445D08F272B9004A47F5 /* tclLoadOSF.c */, F96D445E08F272B9004A47F5 /* tclLoadShl.c */, F96D445F08F272B9004A47F5 /* tclUnixChan.c */, F9FC77B70AB29E9100B7077D /* tclUnixCompat.c */, F96D446008F272B9004A47F5 /* tclUnixEvent.c */, F96D446108F272B9004A47F5 /* tclUnixFCmd.c */, F96D446208F272B9004A47F5 /* tclUnixFile.c */, F96D446308F272B9004A47F5 /* tclUnixInit.c */, F96D446408F272B9004A47F5 /* tclUnixNotfy.c */, F96D446508F272B9004A47F5 /* tclUnixPipe.c */, F96D446608F272B9004A47F5 /* tclUnixPort.h */, F96D446708F272B9004A47F5 /* tclUnixSock.c */, F96D446808F272B9004A47F5 /* tclUnixTest.c */, F96D446908F272B9004A47F5 /* tclUnixThrd.c */, F96D446B08F272B9004A47F5 /* tclUnixTime.c */, F96D446C08F272B9004A47F5 /* tclXtNotify.c */, F96D446D08F272B9004A47F5 /* tclXtTest.c */, ); path = unix; sourceTree = ""; }; F96D444308F272B9004A47F5 /* dltest */ = { isa = PBXGroup; children = ( F96D444408F272B9004A47F5 /* Makefile.in */, F96D444508F272B9004A47F5 /* pkga.c */, F96D444608F272B9004A47F5 /* pkgb.c */, F96D444708F272B9004A47F5 /* pkgc.c */, F96D444808F272B9004A47F5 /* pkgd.c */, F96D444908F272B9004A47F5 /* pkge.c */, F96D444B08F272B9004A47F5 /* pkgua.c */, F96D444C08F272B9004A47F5 /* README */, ); path = dltest; sourceTree = ""; }; F96D446E08F272B9004A47F5 /* win */ = { isa = PBXGroup; children = ( F96D447008F272BA004A47F5 /* aclocal.m4 */, F96D447108F272BA004A47F5 /* buildall.vc.bat */, F96D447208F272BA004A47F5 /* cat.c */, F96D447308F272BA004A47F5 /* coffbase.txt */, F96D447408F272BA004A47F5 /* configure */, F96D447508F272BA004A47F5 /* configure.in */, F96D447608F272BA004A47F5 /* makefile.bc */, F96D447708F272BA004A47F5 /* Makefile.in */, F96D447808F272BA004A47F5 /* makefile.vc */, F96D447908F272BA004A47F5 /* nmakehlp.c */, F96D447A08F272BA004A47F5 /* README */, F96D447C08F272BA004A47F5 /* rules.vc */, F96D447D08F272BA004A47F5 /* stub16.c */, F96D447E08F272BA004A47F5 /* tcl.dsp */, F96D447F08F272BA004A47F5 /* tcl.dsw */, F96D448008F272BA004A47F5 /* tcl.hpj.in */, F96D448108F272BA004A47F5 /* tcl.m4 */, F96D448208F272BA004A47F5 /* tcl.rc */, F96D448308F272BA004A47F5 /* tclAppInit.c */, F96D448408F272BA004A47F5 /* tclConfig.sh.in */, F96D448608F272BA004A47F5 /* tclsh.rc */, F96D448708F272BA004A47F5 /* tclWin32Dll.c */, F96D448808F272BA004A47F5 /* tclWinChan.c */, F96D448908F272BA004A47F5 /* tclWinConsole.c */, F96D448A08F272BA004A47F5 /* tclWinDde.c */, F96D448B08F272BA004A47F5 /* tclWinError.c */, F96D448C08F272BA004A47F5 /* tclWinFCmd.c */, F96D448D08F272BA004A47F5 /* tclWinFile.c */, F96D448E08F272BA004A47F5 /* tclWinInit.c */, F96D448F08F272BA004A47F5 /* tclWinInt.h */, F96D449008F272BA004A47F5 /* tclWinLoad.c */, F96D449108F272BA004A47F5 /* tclWinNotify.c */, F96D449208F272BA004A47F5 /* tclWinPipe.c */, F96D449308F272BA004A47F5 /* tclWinPort.h */, F96D449408F272BA004A47F5 /* tclWinReg.c */, F96D449508F272BA004A47F5 /* tclWinSerial.c */, F96D449608F272BA004A47F5 /* tclWinSock.c */, F96D449708F272BA004A47F5 /* tclWinTest.c */, F96D449808F272BA004A47F5 /* tclWinThrd.c */, F96D449908F272BA004A47F5 /* tclWinThrd.h */, F96D449A08F272BA004A47F5 /* tclWinTime.c */, ); path = win; sourceTree = ""; }; F9ECB1110B26521500A28025 /* platform */ = { isa = PBXGroup; children = ( F9ECB1120B26521500A28025 /* pkgIndex.tcl */, F9ECB1130B26521500A28025 /* platform.tcl */, F9ECB1140B26521500A28025 /* shell.tcl */, ); path = platform; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 8DD76FA90486AB0100D96B5E /* tcltest */ = { isa = PBXNativeTarget; buildConfigurationList = F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */; buildPhases = ( F9A5C5F508F651A2008AE941 /* Configure Tcl */, 8DD76FAB0486AB0100D96B5E /* Sources */, 8DD76FAD0486AB0100D96B5E /* Frameworks */, F95FA74C0B32CE190072E431 /* Build dltest */, ); buildRules = ( ); dependencies = ( ); name = tcltest; productInstallPath = "$(BINDIR)"; productName = tcltest; productReference = 8DD76FB20486AB0100D96B5E /* tcltest */; productType = "com.apple.product-type.tool"; }; F97258A50A86873C00096C78 /* tests */ = { isa = PBXNativeTarget; buildConfigurationList = F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */; buildPhases = ( F97258A40A86873C00096C78 /* Run Testsuite */, ); buildRules = ( ); dependencies = ( F97258D30A868C6F00096C78 /* PBXTargetDependency */, ); name = tests; productName = tests; productType = "com.apple.product-type.bundle"; }; F9E61D16090A3E94002B3151 /* Tcl */ = { isa = PBXNativeTarget; buildConfigurationList = F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */; buildPhases = ( F97AF02F0B665DA900310EA2 /* Build Tcl */, ); buildRules = ( ); dependencies = ( ); name = Tcl; productName = tclsh; productReference = F9A3084B08F2D4CE00BAE1AB /* tclsh */; productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; }; buildConfigurationList = F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */; compatibilityVersion = "Xcode 3.1"; hasScannedForEncodings = 1; mainGroup = 08FB7794FE84155DC02AAC07 /* Tcl */; projectDirPath = ""; projectRoot = ..; targets = ( F9E61D16090A3E94002B3151 /* Tcl */, 8DD76FA90486AB0100D96B5E /* tcltest */, F97258A50A86873C00096C78 /* tests */, ); }; /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ F95FA74C0B32CE190072E431 /* Build dltest */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh", "$(TCL_SRCROOT)/generic/tclStubLib.c", "$(TCL_SRCROOT)/unix/dltest/pkga.c", "$(TCL_SRCROOT)/unix/dltest/pkgb.c", "$(TCL_SRCROOT)/unix/dltest/pkgc.c", "$(TCL_SRCROOT)/unix/dltest/pkgd.c", "$(TCL_SRCROOT)/unix/dltest/pkge.c", "$(TCL_SRCROOT)/unix/dltest/pkgua.c", ); name = "Build dltest"; outputPaths = ( "$(DERIVED_FILE_DIR)/tcl/dltest.marker", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = "## dltest build script phase\n\nrm -f \"${DERIVED_FILE_DIR}/tcl/dltest.marker\"\nmake -C \"${DERIVED_FILE_DIR}/tcl\" dltest.marker\nln -fsh \"${DERIVED_FILE_DIR}/tcl/dltest\" \"${CONFIGURATION_BUILD_DIR}\"\n"; showEnvVarsInLog = 0; }; F97258A40A86873C00096C78 /* Run Testsuite */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Run Testsuite"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = "if [ \"${ACTION:-build}\" == \"build\" ]; then\nif [ -z \"${HOME}\" ]; then export HOME=\"$(echo ~)\"; fi\ncd \"${TARGET_TEMP_DIR}\"; rm -rf \"${DERIVED_FILE_DIR}\"; mkdir -p \"${DERIVED_FILE_DIR}\"\nprintf '%s%s%s%s%s' '\npackage require tcltest 2.2\nnamespace import tcltest::*\nconfigure -testdir [file normalize {' \"${TCL_SRCROOT}\" '/tests}]\nconfigure -tmpdir [file normalize {' \"${DERIVED_FILE_DIR}\" '}]\nconfigure -verbose [concat [configure -verbose] line]\nrunAllTests\n' | \"${TEST_RIG}\"; TEST_RIG_RESULT=$?\n[ ${TEST_RIG_RESULT} -ne 0 ] && echo \"tcltest:0: error: tcltest exited abnormally with code ${TEST_RIG_RESULT}.\"\nexit ${TEST_RIG_RESULT}\nfi"; showEnvVarsInLog = 0; }; F97AF02F0B665DA900310EA2 /* Build Tcl */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${TARGET_TEMP_DIR}/.none", ); name = "Build Tcl"; outputPaths = ( "${TARGET_BUILD_DIR}/${EXECUTABLE_NAME}", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = "if [ -e \"${TARGET_BUILD_DIR}/tclsh\" ]; then\n mv -f \"${TARGET_BUILD_DIR}/tclsh\" \"${TARGET_BUILD_DIR}/tclsh${VERSION}\"\nfi\nexport CC=$(xcrun -find ${GCC} || echo ${GCC}); export LD=${CC}\ngnumake -C \"${TCL_SRCROOT}/macosx\" -j \"$(sysctl -n hw.activecpu)\" \"$(echo \"${ACTION}\" | sed -e s/build// -e s/clean/distclean/ -e s/..\\*/\\&-/)${MAKE_TARGET}\" CFLAGS_WARNING=\"${WARNING_CFLAGS}\" CFLAGS_OPTIMIZE=\"-O${GCC_OPTIMIZATION_LEVEL}\" SYMROOT=\"${BUILT_PRODUCTS_DIR}\" OBJ_DIR=\"${OBJECT_FILE_DIR}\" INSTALL_ROOT=\"${DSTROOT}\" PREFIX=\"${PREFIX}\" BINDIR=\"${BINDIR}\" LIBDIR=\"${FRAMEWORK_INSTALL_PATH}\" MANDIR=\"${MANDIR}\" EXTRA_CONFIGURE_ARGS=\"${CONFIGURE_ARGS}\" ${EXTRA_MAKE_FLAGS}\nresult=$?\nif [ -e \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" ]; then\n mv -f \"${TARGET_BUILD_DIR}/tclsh${VERSION}\" \"${TARGET_BUILD_DIR}/tclsh\"\nfi\nif [ -e \"${BUILT_PRODUCTS_DIR}/tcltest\" ]; then\n\trm -f \"${BUILT_PRODUCTS_DIR}/tcltest\"\nfi\necho \"Done\"\nrm -f \"${SCRIPT_INPUT_FILE_0}\"\nexit ${result}\n"; showEnvVarsInLog = 0; }; F9A5C5F508F651A2008AE941 /* Configure Tcl */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(TCL_SRCROOT)/macosx/configure.ac", "$(TCL_SRCROOT)/unix/configure.in", "$(TCL_SRCROOT)/unix/tcl.m4", "$(TCL_SRCROOT)/unix/aclocal.m4", "$(TCL_SRCROOT)/unix/tclConfig.sh.in", "$(TCL_SRCROOT)/unix/Makefile.in", "$(TCL_SRCROOT)/unix/dltest/Makefile.in", ); name = "Configure Tcl"; outputPaths = ( "$(DERIVED_FILE_DIR)/tcl/tclConfig.sh", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; shellScript = "## tcl configure shell script phase\n\ncd \"${TCL_SRCROOT}\"/macosx &&\nif [ configure.ac -nt configure -o ../unix/configure.in -nt configure -o ../unix/tcl.m4 -nt configure -o ../unix/aclocal.m4 -nt configure ]; then\n echo \"Running autoconf & autoheader in tcl/macosx\"\n rm -rf autom4te.cache\n ${AUTOCONF:-${DEVELOPER_DIR}/usr/bin/autoconf} && ${AUTOHEADER:-${DEVELOPER_DIR}/usr/bin/autoheader} || exit $?\n rm -rf autom4te.cache\nfi\n\ncd \"${DERIVED_FILE_DIR}\" && mkdir -p tcl && cd tcl &&\nif [ \"${TCL_SRCROOT}\"/macosx/configure -nt config.status ]; then\n echo \"Configuring Tcl\"\n CC=$(xcrun -find ${GCC} || echo ${GCC})\n \"${TCL_SRCROOT}\"/macosx/configure --cache-file=../config.cache --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} --mandir=${MANDIR} --includedir=${INCLUDEDIR} --disable-shared CC=${CC} LD=${CC} ${CONFIGURE_ARGS}\nelse\n ./config.status\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 8DD76FAB0486AB0100D96B5E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( F96D456F08F272BB004A47F5 /* regcomp.c in Sources */, F96D457208F272BB004A47F5 /* regerror.c in Sources */, F96D457508F272BB004A47F5 /* regexec.c in Sources */, F96D457608F272BB004A47F5 /* regfree.c in Sources */, F96D457B08F272BB004A47F5 /* tclAlloc.c in Sources */, F96D457C08F272BB004A47F5 /* tclAsync.c in Sources */, F96D457D08F272BB004A47F5 /* tclBasic.c in Sources */, F96D457E08F272BC004A47F5 /* tclBinary.c in Sources */, F96D457F08F272BC004A47F5 /* tclCkalloc.c in Sources */, F96D458008F272BC004A47F5 /* tclClock.c in Sources */, F96D458108F272BC004A47F5 /* tclCmdAH.c in Sources */, F96D458208F272BC004A47F5 /* tclCmdIL.c in Sources */, F96D458308F272BC004A47F5 /* tclCmdMZ.c in Sources */, F96D458408F272BC004A47F5 /* tclCompCmds.c in Sources */, F96D458508F272BC004A47F5 /* tclCompExpr.c in Sources */, F96D458608F272BC004A47F5 /* tclCompile.c in Sources */, F96D458808F272BC004A47F5 /* tclConfig.c in Sources */, F96D458908F272BC004A47F5 /* tclDate.c in Sources */, F96D458B08F272BC004A47F5 /* tclDictObj.c in Sources */, F96D458C08F272BC004A47F5 /* tclEncoding.c in Sources */, F96D458D08F272BC004A47F5 /* tclEnv.c in Sources */, F96D458E08F272BC004A47F5 /* tclEvent.c in Sources */, F96D458F08F272BC004A47F5 /* tclExecute.c in Sources */, F96D459008F272BC004A47F5 /* tclFCmd.c in Sources */, F96D459108F272BC004A47F5 /* tclFileName.c in Sources */, F96D459308F272BC004A47F5 /* tclGet.c in Sources */, F96D459508F272BC004A47F5 /* tclHash.c in Sources */, F96D459608F272BC004A47F5 /* tclHistory.c in Sources */, F96D459708F272BC004A47F5 /* tclIndexObj.c in Sources */, F96D459B08F272BC004A47F5 /* tclInterp.c in Sources */, F96D459D08F272BC004A47F5 /* tclIO.c in Sources */, F96D459F08F272BC004A47F5 /* tclIOCmd.c in Sources */, F96D45A008F272BC004A47F5 /* tclIOGT.c in Sources */, F96D45A108F272BC004A47F5 /* tclIORChan.c in Sources */, F95D77EA0DFD820D00A8BF6F /* tclIORTrans.c in Sources */, F96D45A208F272BC004A47F5 /* tclIOSock.c in Sources */, F96D45A308F272BC004A47F5 /* tclIOUtil.c in Sources */, F96D45A408F272BC004A47F5 /* tclLink.c in Sources */, F96D45A508F272BC004A47F5 /* tclListObj.c in Sources */, F96D45A608F272BC004A47F5 /* tclLiteral.c in Sources */, F96D45A708F272BC004A47F5 /* tclLoad.c in Sources */, F96D45A908F272BC004A47F5 /* tclMain.c in Sources */, F96D45AA08F272BC004A47F5 /* tclNamesp.c in Sources */, F96D45AB08F272BC004A47F5 /* tclNotify.c in Sources */, F96D45AC08F272BC004A47F5 /* tclObj.c in Sources */, F93599B30DF1F75400E04F67 /* tclOO.c in Sources */, F93599B70DF1F76100E04F67 /* tclOOBasic.c in Sources */, F93599B90DF1F76600E04F67 /* tclOOCall.c in Sources */, F93599BC0DF1F77000E04F67 /* tclOODefineCmds.c in Sources */, F93599BE0DF1F77400E04F67 /* tclOOInfo.c in Sources */, F93599C20DF1F78300E04F67 /* tclOOMethod.c in Sources */, F93599C40DF1F78800E04F67 /* tclOOStubInit.c in Sources */, F93599C60DF1F78D00E04F67 /* tclOOStubLib.c in Sources */, F96D45AD08F272BC004A47F5 /* tclPanic.c in Sources */, F96D45AE08F272BC004A47F5 /* tclParse.c in Sources */, F96D45B008F272BC004A47F5 /* tclPathObj.c in Sources */, F96D45B108F272BC004A47F5 /* tclPipe.c in Sources */, F96D45B208F272BC004A47F5 /* tclPkg.c in Sources */, F96D45B308F272BC004A47F5 /* tclPkgConfig.c in Sources */, F96D45B608F272BC004A47F5 /* tclPosixStr.c in Sources */, F96D45B708F272BC004A47F5 /* tclPreserve.c in Sources */, F96D45B808F272BC004A47F5 /* tclProc.c in Sources */, F96D45B908F272BC004A47F5 /* tclRegexp.c in Sources */, F96D45BB08F272BC004A47F5 /* tclResolve.c in Sources */, F96D45BC08F272BC004A47F5 /* tclResult.c in Sources */, F96D45BD08F272BC004A47F5 /* tclScan.c in Sources */, F96D45BE08F272BC004A47F5 /* tclStringObj.c in Sources */, F96D45C308F272BC004A47F5 /* tclStrToD.c in Sources */, F96D45C408F272BC004A47F5 /* tclStubInit.c in Sources */, F96D45C508F272BC004A47F5 /* tclStubLib.c in Sources */, F96D45C608F272BC004A47F5 /* tclTest.c in Sources */, F96D45C708F272BC004A47F5 /* tclTestObj.c in Sources */, F96D45C808F272BC004A47F5 /* tclTestProcBodyObj.c in Sources */, F96D45C908F272BC004A47F5 /* tclThread.c in Sources */, F96D45CA08F272BC004A47F5 /* tclThreadAlloc.c in Sources */, F96D45CB08F272BC004A47F5 /* tclThreadJoin.c in Sources */, F96D45CC08F272BC004A47F5 /* tclThreadStorage.c in Sources */, F96D45CD08F272BC004A47F5 /* tclThreadTest.c in Sources */, F96D45CE08F272BC004A47F5 /* tclTimer.c in Sources */, F96D45D008F272BC004A47F5 /* tclTomMathInterface.c in Sources */, F96D45D108F272BC004A47F5 /* tclTrace.c in Sources */, F96D45D308F272BC004A47F5 /* tclUtf.c in Sources */, F96D45D408F272BC004A47F5 /* tclUtil.c in Sources */, F96D45D508F272BC004A47F5 /* tclVar.c in Sources */, F96437CA0EF0D4B2003F468E /* tclZlib.c in Sources */, F96D48E208F272C3004A47F5 /* bn_fast_s_mp_mul_digs.c in Sources */, F96D48E408F272C3004A47F5 /* bn_fast_s_mp_sqr.c in Sources */, F96D48E708F272C3004A47F5 /* bn_mp_add.c in Sources */, F96D48E808F272C3004A47F5 /* bn_mp_add_d.c in Sources */, F9E61D2B090A48A4002B3151 /* bn_mp_and.c in Sources */, F96D48EB08F272C3004A47F5 /* bn_mp_clamp.c in Sources */, F96D48EC08F272C3004A47F5 /* bn_mp_clear.c in Sources */, F96D48ED08F272C3004A47F5 /* bn_mp_clear_multi.c in Sources */, F96D48EE08F272C3004A47F5 /* bn_mp_cmp.c in Sources */, F9E61D28090A481F002B3151 /* bn_mp_cmp_d.c in Sources */, F96D48F008F272C3004A47F5 /* bn_mp_cmp_mag.c in Sources */, F96D48F208F272C3004A47F5 /* bn_mp_cnt_lsb.c in Sources */, F96D48F208F272C3004A47F5 /* bn_mp_copy.c in Sources */, F96D48F308F272C3004A47F5 /* bn_mp_count_bits.c in Sources */, F96D48F408F272C3004A47F5 /* bn_mp_div.c in Sources */, F96D48F508F272C3004A47F5 /* bn_mp_div_2.c in Sources */, F96D48F608F272C3004A47F5 /* bn_mp_div_2d.c in Sources */, F96D48F708F272C3004A47F5 /* bn_mp_div_3.c in Sources */, F96D48F808F272C3004A47F5 /* bn_mp_div_d.c in Sources */, F96D48FC08F272C3004A47F5 /* bn_mp_exch.c in Sources */, F9E61D2C090A48AC002B3151 /* bn_mp_expt_d.c in Sources */, F96D490508F272C3004A47F5 /* bn_mp_grow.c in Sources */, F96D490608F272C3004A47F5 /* bn_mp_init.c in Sources */, F96D490708F272C3004A47F5 /* bn_mp_init_copy.c in Sources */, F96D490808F272C3004A47F5 /* bn_mp_init_multi.c in Sources */, F96D490908F272C3004A47F5 /* bn_mp_init_set.c in Sources */, F96D490B08F272C3004A47F5 /* bn_mp_init_size.c in Sources */, F96D491008F272C3004A47F5 /* bn_mp_karatsuba_mul.c in Sources */, F96D491108F272C3004A47F5 /* bn_mp_karatsuba_sqr.c in Sources */, F96D491308F272C3004A47F5 /* bn_mp_lshd.c in Sources */, F96D491408F272C3004A47F5 /* bn_mp_mod.c in Sources */, F96D491508F272C3004A47F5 /* bn_mp_mod_2d.c in Sources */, F96D491A08F272C3004A47F5 /* bn_mp_mul.c in Sources */, F96D491B08F272C3004A47F5 /* bn_mp_mul_2.c in Sources */, F96D491C08F272C3004A47F5 /* bn_mp_mul_2d.c in Sources */, F96D491D08F272C3004A47F5 /* bn_mp_mul_d.c in Sources */, F9E61D29090A486C002B3151 /* bn_mp_neg.c in Sources */, F9E61D2E090A48BF002B3151 /* bn_mp_or.c in Sources */, F96D492908F272C3004A47F5 /* bn_mp_radix_size.c in Sources */, F96D492A08F272C3004A47F5 /* bn_mp_radix_smap.c in Sources */, F96D492C08F272C3004A47F5 /* bn_mp_read_radix.c in Sources */, F96D493708F272C3004A47F5 /* bn_mp_rshd.c in Sources */, F96D493808F272C3004A47F5 /* bn_mp_set.c in Sources */, F9E61D2F090A48C7002B3151 /* bn_mp_shrink.c in Sources */, F96D493C08F272C3004A47F5 /* bn_mp_sqr.c in Sources */, F9E61D2A090A4891002B3151 /* bn_mp_sqrt.c in Sources */, F96D493F08F272C3004A47F5 /* bn_mp_sub.c in Sources */, F96D494008F272C3004A47F5 /* bn_mp_sub_d.c in Sources */, F9E61D30090A48E2002B3151 /* bn_mp_to_unsigned_bin_n.c in Sources */, F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */, F96D494608F272C3004A47F5 /* bn_mp_toom_mul.c in Sources */, F96D494708F272C3004A47F5 /* bn_mp_toom_sqr.c in Sources */, F96D494908F272C3004A47F5 /* bn_mp_toradix_n.c in Sources */, F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */, F9E61D2D090A48BB002B3151 /* bn_mp_xor.c in Sources */, F96D494C08F272C3004A47F5 /* bn_mp_zero.c in Sources */, F96D494E08F272C3004A47F5 /* bn_reverse.c in Sources */, F96D494F08F272C3004A47F5 /* bn_s_mp_add.c in Sources */, F96D495108F272C3004A47F5 /* bn_s_mp_mul_digs.c in Sources */, F96D495308F272C3004A47F5 /* bn_s_mp_sqr.c in Sources */, F96D495408F272C3004A47F5 /* bn_s_mp_sub.c in Sources */, F96D495508F272C3004A47F5 /* bncore.c in Sources */, F96D49A908F272C4004A47F5 /* tclMacOSXBundle.c in Sources */, F96D49AD08F272C4004A47F5 /* tclMacOSXFCmd.c in Sources */, F96D49AE08F272C4004A47F5 /* tclMacOSXNotify.c in Sources */, F90509300913A72400327603 /* tclAppInit.c in Sources */, F96D4AC608F272C9004A47F5 /* tclLoadDyld.c in Sources */, F96D4ACA08F272C9004A47F5 /* tclUnixChan.c in Sources */, F9FC77B80AB29E9100B7077D /* tclUnixCompat.c in Sources */, F96D4ACB08F272C9004A47F5 /* tclUnixEvent.c in Sources */, F96D4ACC08F272C9004A47F5 /* tclUnixFCmd.c in Sources */, F96D4ACD08F272C9004A47F5 /* tclUnixFile.c in Sources */, F96D4ACE08F272C9004A47F5 /* tclUnixInit.c in Sources */, F96D4ACF08F272C9004A47F5 /* tclUnixNotfy.c in Sources */, F96D4AD008F272C9004A47F5 /* tclUnixPipe.c in Sources */, F96D4AD208F272CA004A47F5 /* tclUnixSock.c in Sources */, F96D4AD308F272CA004A47F5 /* tclUnixTest.c in Sources */, F96D4AD408F272CA004A47F5 /* tclUnixThrd.c in Sources */, F96D4AD608F272CA004A47F5 /* tclUnixTime.c in Sources */, F9F4415E0C8BAE6F00BCCD67 /* tclDTrace.d in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ F97258D30A868C6F00096C78 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 8DD76FA90486AB0100D96B5E /* tcltest */; targetProxy = F97258D20A868C6F00096C78 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ F91BCC4F093152310042A6BF /* ReleaseUniversal */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = ReleaseUniversal; }; F91BCC50093152310042A6BF /* ReleaseUniversal */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = ReleaseUniversal; }; F91BCC51093152310042A6BF /* ReleaseUniversal */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.5; PREBINDING = NO; }; name = ReleaseUniversal; }; F93084370BB93D2800CD0B9E /* DebugMemCompile */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugMemCompile; }; F93084380BB93D2800CD0B9E /* DebugMemCompile */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugMemCompile; }; F93084390BB93D2800CD0B9E /* DebugMemCompile */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugMemCompile; }; F930843A0BB93D2800CD0B9E /* DebugMemCompile */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-symbols=all"; CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = DebugMemCompile; }; F9359B250DF212DA00E04F67 /* DebugGCov */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; GCC_GENERATE_TEST_COVERAGE_FILES = YES; GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS)", "-lgcov", ); PREBINDING = NO; }; name = DebugGCov; }; F9359B260DF212DA00E04F67 /* DebugGCov */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugGCov; }; F9359B270DF212DA00E04F67 /* DebugGCov */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugGCov; }; F9359B280DF212DA00E04F67 /* DebugGCov */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugGCov; }; F95CC8AC09158F3100EA5ACE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = Debug; }; F95CC8AD09158F3100EA5ACE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = Release; }; F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugNoFixAndContinue; }; F95CC8B109158F3100EA5ACE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)"; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "__private_extern__=extern", "$(GCC_PREPROCESSOR_DEFINITIONS)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; PRODUCT_NAME = tcltest; }; name = Debug; }; F95CC8B209158F3100EA5ACE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = Release; }; F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugNoFixAndContinue; }; F95CC8B609158F3100EA5ACE /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = Debug; }; F95CC8B709158F3100EA5ACE /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = Release; }; F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = DebugNoFixAndContinue; }; F97258A90A86873D00096C78 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = Debug; }; F97258AA0A86873D00096C78 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = Release; }; F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugNoFixAndContinue; }; F97258AC0A86873D00096C78 /* ReleaseUniversal */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = ReleaseUniversal; }; F97AED1B0B660B2100310EA2 /* Debug64bit */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = Debug64bit; }; F97AED1C0B660B2100310EA2 /* Debug64bit */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = Debug64bit; }; F97AED1D0B660B2100310EA2 /* Debug64bit */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = Debug64bit; }; F97AED1E0B660B2100310EA2 /* Debug64bit */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = "$(NATIVE_ARCH_64_BIT)"; CONFIGURE_ARGS = "--enable-64bit $(CONFIGURE_ARGS)"; CPPFLAGS = "-arch $(NATIVE_ARCH_64_BIT) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.5; PREBINDING = NO; }; name = Debug64bit; }; F987512F0DE7B57E00B1C9EC /* DebugNoCF */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-corefoundation"; CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = DebugNoCF; }; F98751300DE7B57E00B1C9EC /* DebugNoCF */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugNoCF; }; F98751310DE7B57E00B1C9EC /* DebugNoCF */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugNoCF; }; F98751320DE7B57E00B1C9EC /* DebugNoCF */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugNoCF; }; F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads --disable-corefoundation"; CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = DebugNoCFUnthreaded; }; F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugNoCFUnthreaded; }; F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugNoCFUnthreaded; }; F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugNoCFUnthreaded; }; F9988AB10D814C6500B6B03B /* Debug gcc40 */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; GCC_VERSION = 4.0; MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = "Debug gcc40"; }; F9988AB20D814C6500B6B03B /* Debug gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = "Debug gcc40"; }; F9988AB30D814C6500B6B03B /* Debug gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)"; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "__private_extern__=extern", "$(GCC_PREPROCESSOR_DEFINITIONS)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; PRODUCT_NAME = tcltest; }; name = "Debug gcc40"; }; F9988AB40D814C6500B6B03B /* Debug gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = "Debug gcc40"; }; F9988AB50D814C7500B6B03B /* Debug llvm-gcc */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; GCC = "llvm-gcc"; GCC_VERSION = com.apple.compilers.llvmgcc42; MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = "Debug llvm-gcc"; }; F9988AB60D814C7500B6B03B /* Debug llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = "Debug llvm-gcc"; }; F9988AB70D814C7500B6B03B /* Debug llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)"; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "__private_extern__=extern", "$(GCC_PREPROCESSOR_DEFINITIONS)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; PRODUCT_NAME = tcltest; }; name = "Debug llvm-gcc"; }; F9988AB80D814C7500B6B03B /* Debug llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = "Debug llvm-gcc"; }; F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)"; GCC_VERSION = 4.0; MACOSX_DEPLOYMENT_TARGET = 10.5; PREBINDING = NO; }; name = "ReleaseUniversal gcc40"; }; F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = "ReleaseUniversal gcc40"; }; F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = "ReleaseUniversal gcc40"; }; F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = "ReleaseUniversal gcc40"; }; F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)"; DEBUG_INFORMATION_FORMAT = dwarf; GCC = "llvm-gcc"; GCC_OPTIMIZATION_LEVEL = 4; GCC_VERSION = com.apple.compilers.llvmgcc42; MACOSX_DEPLOYMENT_TARGET = 10.5; PREBINDING = NO; }; name = "ReleaseUniversal llvm-gcc"; }; F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = "ReleaseUniversal llvm-gcc"; }; F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = "ReleaseUniversal llvm-gcc"; }; F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = "ReleaseUniversal llvm-gcc"; }; F99EE73B0BE835310060D4AF /* DebugUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugUnthreaded; }; F99EE73C0BE835310060D4AF /* DebugLeaks */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = DebugLeaks; }; F99EE73D0BE835310060D4AF /* DebugUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugUnthreaded; }; F99EE73E0BE835310060D4AF /* DebugLeaks */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = DebugLeaks; }; F99EE73F0BE835310060D4AF /* DebugUnthreaded */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugUnthreaded; }; F99EE7400BE835310060D4AF /* DebugLeaks */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = DebugLeaks; }; F99EE7410BE835310060D4AF /* DebugUnthreaded */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --disable-threads"; CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = DebugUnthreaded; }; F99EE7420BE835310060D4AF /* DebugLeaks */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */; buildSettings = { ARCHS = ( "$(NATIVE_ARCH_64_BIT)", "$(NATIVE_ARCH_32_BIT)", ); CPPFLAGS = "-arch $(CURRENT_ARCH) $(CPPFLAGS)"; GCC_PREPROCESSOR_DEFINITIONS = ( PURIFY, "$(GCC_PREPROCESSOR_DEFINITIONS)", ); MACOSX_DEPLOYMENT_TARGET = 10.5; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; }; name = DebugLeaks; }; F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tclsh; SKIP_INSTALL = NO; }; name = ReleaseUniversal10.5SDK; }; F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = tcltest; }; name = ReleaseUniversal10.5SDK; }; F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; PRODUCT_NAME = tests; TCLTEST_OPTIONS = ""; TCL_LIBRARY = "$(TCL_SRCROOT)/library"; TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest"; }; name = ReleaseUniversal10.5SDK; }; F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = { isa = XCBuildConfiguration; baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CFLAGS = "-arch i386 -arch x86_64 -arch ppc $(CFLAGS)"; CPPFLAGS = "-isysroot $(SDKROOT) $(CPPFLAGS)"; MACOSX_DEPLOYMENT_TARGET = 10.5; PREBINDING = NO; SDKROOT = macosx10.5; }; name = ReleaseUniversal10.5SDK; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ F95CC8AB09158F3100EA5ACE /* Build configuration list for PBXNativeTarget "Tcl" */ = { isa = XCConfigurationList; buildConfigurations = ( F95CC8AC09158F3100EA5ACE /* Debug */, F9988AB60D814C7500B6B03B /* Debug llvm-gcc */, F9988AB20D814C6500B6B03B /* Debug gcc40 */, F95CC8AE09158F3100EA5ACE /* DebugNoFixAndContinue */, F99EE73B0BE835310060D4AF /* DebugUnthreaded */, F98751300DE7B57E00B1C9EC /* DebugNoCF */, F98751340DE7B5A200B1C9EC /* DebugNoCFUnthreaded */, F93084370BB93D2800CD0B9E /* DebugMemCompile */, F99EE73C0BE835310060D4AF /* DebugLeaks */, F9359B260DF212DA00E04F67 /* DebugGCov */, F97AED1B0B660B2100310EA2 /* Debug64bit */, F95CC8AD09158F3100EA5ACE /* Release */, F91BCC4F093152310042A6BF /* ReleaseUniversal */, F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */, F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */, F9EEED960C2FEFD300396116 /* ReleaseUniversal10.5SDK */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; F95CC8B009158F3100EA5ACE /* Build configuration list for PBXNativeTarget "tcltest" */ = { isa = XCConfigurationList; buildConfigurations = ( F95CC8B109158F3100EA5ACE /* Debug */, F9988AB70D814C7500B6B03B /* Debug llvm-gcc */, F9988AB30D814C6500B6B03B /* Debug gcc40 */, F95CC8B309158F3100EA5ACE /* DebugNoFixAndContinue */, F99EE73D0BE835310060D4AF /* DebugUnthreaded */, F98751310DE7B57E00B1C9EC /* DebugNoCF */, F98751350DE7B5A200B1C9EC /* DebugNoCFUnthreaded */, F93084380BB93D2800CD0B9E /* DebugMemCompile */, F99EE73E0BE835310060D4AF /* DebugLeaks */, F9359B270DF212DA00E04F67 /* DebugGCov */, F97AED1C0B660B2100310EA2 /* Debug64bit */, F95CC8B209158F3100EA5ACE /* Release */, F91BCC50093152310042A6BF /* ReleaseUniversal */, F9988BB70D81587400B6B03B /* ReleaseUniversal llvm-gcc */, F9988BB30D81586D00B6B03B /* ReleaseUniversal gcc40 */, F9EEED970C2FEFD300396116 /* ReleaseUniversal10.5SDK */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; F95CC8B509158F3100EA5ACE /* Build configuration list for PBXProject "Tcl" */ = { isa = XCConfigurationList; buildConfigurations = ( F95CC8B609158F3100EA5ACE /* Debug */, F9988AB50D814C7500B6B03B /* Debug llvm-gcc */, F9988AB10D814C6500B6B03B /* Debug gcc40 */, F95CC8B809158F3100EA5ACE /* DebugNoFixAndContinue */, F99EE7410BE835310060D4AF /* DebugUnthreaded */, F987512F0DE7B57E00B1C9EC /* DebugNoCF */, F98751330DE7B5A200B1C9EC /* DebugNoCFUnthreaded */, F930843A0BB93D2800CD0B9E /* DebugMemCompile */, F99EE7420BE835310060D4AF /* DebugLeaks */, F9359B250DF212DA00E04F67 /* DebugGCov */, F97AED1E0B660B2100310EA2 /* Debug64bit */, F95CC8B709158F3100EA5ACE /* Release */, F91BCC51093152310042A6BF /* ReleaseUniversal */, F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */, F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */, F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; F97258A80A86873D00096C78 /* Build configuration list for PBXNativeTarget "tests" */ = { isa = XCConfigurationList; buildConfigurations = ( F97258A90A86873D00096C78 /* Debug */, F9988AB80D814C7500B6B03B /* Debug llvm-gcc */, F9988AB40D814C6500B6B03B /* Debug gcc40 */, F97258AB0A86873D00096C78 /* DebugNoFixAndContinue */, F99EE73F0BE835310060D4AF /* DebugUnthreaded */, F98751320DE7B57E00B1C9EC /* DebugNoCF */, F98751360DE7B5A200B1C9EC /* DebugNoCFUnthreaded */, F93084390BB93D2800CD0B9E /* DebugMemCompile */, F99EE7400BE835310060D4AF /* DebugLeaks */, F9359B280DF212DA00E04F67 /* DebugGCov */, F97AED1D0B660B2100310EA2 /* Debug64bit */, F97258AA0A86873D00096C78 /* Release */, F97258AC0A86873D00096C78 /* ReleaseUniversal */, F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */, F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */, F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; /* End XCConfigurationList section */ }; rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; } tcl8.6.5/macosx/Tcl.xcode/default.pbxuser0000644000175000017500000001322212663653132017737 0ustar sergeisergei// !$*UTF8*$! { 08FB7793FE84155DC02AAC07 /* Project object */ = { activeBuildConfigurationName = Debug; activeExecutable = F9E61D1C090A4282002B3151 /* tclsh */; activeTarget = F9E61D16090A3E94002B3151 /* Tcl */; codeSenseManager = F944EB9D08F798180049FDD4 /* Code sense */; executables = ( F9E61D1C090A4282002B3151 /* tclsh */, F944EB8F08F798100049FDD4 /* tcltest */, ); perUserDictionary = { com.apple.ide.smrt.PBXUserSmartGroupsKey.Rev10 = <040b73747265616d747970656481e8038401408484840e4e534d757461626c654172726179008484074e534172726179008484084e534f626a65637400858401690192848484134e534d757461626c6544696374696f6e6172790084840c4e5344696374696f6e6172790095960792848484084e53537472696e67019584012b046e616d658692849a9a14496d706c656d656e746174696f6e2046696c65738692849a9a146162736f6c75746550617468546f42756e646c658692849a9a008692849a9a195042585472616e7369656e744c6f636174696f6e4174546f708692849a9a06626f74746f6d8692849a9a03636c7a8692849a9a1550425846696c656e616d65536d61727447726f75708692849a9a0b6465736372697074696f6e8692849a9a103c6e6f206465736372697074696f6e3e8692849a9a0b707265666572656e63657386928497960892849a9a07666e6d617463688692849a9a008692849a9a05696d6167658692849a9a0b536d617274466f6c6465728692849a9a04726f6f748692849a9a093c50524f4a4543543e8692849a9a0572656765788692849a9a065c2e286329248692849a9a097265637572736976658692848484084e534e756d626572008484074e5356616c7565009584012a849696018692849a9a0669734c656166869284b09db296008692849a9a0763616e536176658692af92849a9a1250425850726f6a65637453636f70654b65798692849a9a03594553868692849a9a08676c6f62616c49448692849a9a18314343304541343030343335304546393030343434313042868686>; }; sourceControlManager = F944EB9C08F798180049FDD4 /* Source Control */; userBuildSettings = { SYMROOT = "${SRCROOT}/../../build/tcl"; TCL_SRCROOT = "${SRCROOT}/../../tcl"; }; }; 8DD76FA90486AB0100D96B5E /* tcltest */ = { activeExec = 0; executables = ( F944EB8F08F798100049FDD4 /* tcltest */, ); }; F944EB8F08F798100049FDD4 /* tcltest */ = { isa = PBXExecutable; activeArgIndices = ( NO, NO, NO, ); argumentStrings = ( "${TCL_SRCROOT}/tests/all.tcl", "-singleproc 1", "-verbose \"bet\"", ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; displayName = "Executable Runner"; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; "PBXLSLaunchAction-1" = { PBXLSLaunchAction = 1; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXGDB_LaunchConfig; displayName = GDB; identifier = com.apple.Xcode.launch.GDBMI_Config; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 0; environmentEntries = ( { active = YES; name = TCL_LIBRARY; value = "${TCL_SRCROOT}/library"; }, { active = YES; name = TCLLIBPATH; value = /Library/Tcl; }, { active = NO; name = DYLD_PRINT_LIBRARIES; }, { active = NO; name = MallocBadFreeAbort; value = 1; }, { active = NO; name = MallocLogFile; value = /tmp/malloc.log; }, { active = NO; name = MallocStackLogging; value = 1; }, { active = NO; name = MallocStackLoggingNoCompact; value = 1; }, { active = NO; name = MallocPreScribble; value = 1; }, { active = NO; name = MallocScribble; value = 1; }, ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = tcltest; sourceDirectories = ( ); }; F944EB9C08F798180049FDD4 /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { CVSToolPath = /usr/bin/cvs; CVSUseSSH = NO; SubversionToolPath = /usr/bin/svn; repositoryNamesForRoots = { .. = ""; }; }; scmType = scm.cvs; }; F944EB9D08F798180049FDD4 /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; F97258A50A86873C00096C78 /* tests */ = { activeExec = 0; }; F9E61D16090A3E94002B3151 /* Tcl */ = { activeExec = 0; executables = ( F9E61D1C090A4282002B3151 /* tclsh */, ); }; F9E61D1C090A4282002B3151 /* tclsh */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 1; configStateDict = { "PBXLSLaunchAction-0" = { PBXLSLaunchAction = 0; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXLSRunLaunchConfig; displayName = "Executable Runner"; identifier = com.apple.Xcode.launch.runConfig; remoteHostInfo = ""; startActionInfo = ""; }; "PBXLSLaunchAction-1" = { PBXLSLaunchAction = 1; PBXLSLaunchStartAction = 1; PBXLSLaunchStdioStyle = 2; PBXLSLaunchStyle = 0; class = PBXGDB_LaunchConfig; displayName = GDB; identifier = com.apple.Xcode.launch.GDBMI_Config; remoteHostInfo = ""; startActionInfo = ""; }; }; customDataFormattersEnabled = 1; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = _debug; enableDebugStr = 0; environmentEntries = ( { active = NO; name = DYLD_PRINT_LIBRARIES; }, ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = tclsh; sourceDirectories = ( ); }; } tcl8.6.5/macosx/Tcl-Info.plist.in0000644000175000017500000000236312663653210016154 0ustar sergeisergei CFBundleDevelopmentRegion English CFBundleExecutable @TCL_LIB_FILE@ CFBundleGetInfoString Tcl @TCL_VERSION@@TCL_PATCH_LEVEL@, Copyright © 1987-@TCL_YEAR@ Tcl Core Team, Copyright © 2001-@TCL_YEAR@ Daniel A. Steffen, Copyright © 2001-2009 Apple Inc., Copyright © 2001-2002 Jim Ingham & Ian Reid CFBundleIdentifier com.tcltk.tcllibrary CFBundleInfoDictionaryVersion 6.0 CFBundleName Tcl @TCL_VERSION@ CFBundlePackageType FMWK CFBundleShortVersionString @TCL_VERSION@@TCL_PATCH_LEVEL@ CFBundleSignature Tcl CFBundleVersion @TCL_VERSION@@TCL_PATCH_LEVEL@ tcl8.6.5/macosx/tclMacOSXNotify.c0000644000175000017500000015253012663660066016222 0ustar sergeisergei/* * tclMacOSXNotify.c -- * * This file contains the implementation of a merged CFRunLoop/select() * based notifier, which is the lowest-level part of the Tcl event loop. * This file works together with generic/tclNotify.c. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2005-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #ifdef HAVE_COREFOUNDATION /* Traditional unix select-based notifier is * in tclUnixNotfy.c */ #include #include /* #define TCL_MAC_DEBUG_NOTIFIER 1 */ /* * We use the Darwin-native spinlock API rather than pthread mutexes for * notifier locking: this radically simplifies the implementation and lowers * overhead. Note that these are not pure spinlocks, they employ various * strategies to back off and relinquish the processor, making them immune to * most priority-inversion livelocks (c.f. 'man 3 OSSpinLockLock' and Darwin * sources: xnu/osfmk/{ppc,i386}/commpage/spinlocks.s). */ #if defined(HAVE_LIBKERN_OSATOMIC_H) && defined(HAVE_OSSPINLOCKLOCK) /* * Use OSSpinLock API where available (Tiger or later). */ #include #if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040 /* * Support for weakly importing spinlock API. */ #define WEAK_IMPORT_SPINLOCKLOCK #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 #define VOLATILE volatile #else #define VOLATILE #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 */ #ifndef bool #define bool int #endif extern void OSSpinLockLock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; extern void OSSpinLockUnlock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; extern bool OSSpinLockTry(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; extern void _spin_lock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; extern void _spin_unlock(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; extern bool _spin_lock_try(VOLATILE OSSpinLock *lock) WEAK_IMPORT_ATTRIBUTE; static void (* lockLock)(VOLATILE OSSpinLock *lock) = NULL; static void (* lockUnlock)(VOLATILE OSSpinLock *lock) = NULL; static bool (* lockTry)(VOLATILE OSSpinLock *lock) = NULL; #undef VOLATILE static pthread_once_t spinLockLockInitControl = PTHREAD_ONCE_INIT; static void SpinLockLockInit(void) { lockLock = OSSpinLockLock != NULL ? OSSpinLockLock : _spin_lock; lockUnlock = OSSpinLockUnlock != NULL ? OSSpinLockUnlock : _spin_unlock; lockTry = OSSpinLockTry != NULL ? OSSpinLockTry : _spin_lock_try; if (lockLock == NULL || lockUnlock == NULL) { Tcl_Panic("SpinLockLockInit: no spinlock API available"); } } #define SpinLockLock(p) lockLock(p) #define SpinLockUnlock(p) lockUnlock(p) #define SpinLockTry(p) lockTry(p) #else #define SpinLockLock(p) OSSpinLockLock(p) #define SpinLockUnlock(p) OSSpinLockUnlock(p) #define SpinLockTry(p) OSSpinLockTry(p) #endif /* HAVE_WEAK_IMPORT */ #define SPINLOCK_INIT OS_SPINLOCK_INIT #else /* * Otherwise, use commpage spinlock SPI directly. */ typedef uint32_t OSSpinLock; extern void _spin_lock(OSSpinLock *lock); extern void _spin_unlock(OSSpinLock *lock); extern int _spin_lock_try(OSSpinLock *lock); #define SpinLockLock(p) _spin_lock(p) #define SpinLockUnlock(p) _spin_unlock(p) #define SpinLockTry(p) _spin_lock_try(p) #define SPINLOCK_INIT 0 #endif /* HAVE_LIBKERN_OSATOMIC_H && HAVE_OSSPINLOCKLOCK */ /* * These spinlocks lock access to the global notifier state. */ static OSSpinLock notifierInitLock = SPINLOCK_INIT; static OSSpinLock notifierLock = SPINLOCK_INIT; /* * Macros abstracting notifier locking/unlocking */ #define LOCK_NOTIFIER_INIT SpinLockLock(¬ifierInitLock) #define UNLOCK_NOTIFIER_INIT SpinLockUnlock(¬ifierInitLock) #define LOCK_NOTIFIER SpinLockLock(¬ifierLock) #define UNLOCK_NOTIFIER SpinLockUnlock(¬ifierLock) #define LOCK_NOTIFIER_TSD SpinLockLock(&tsdPtr->tsdLock) #define UNLOCK_NOTIFIER_TSD SpinLockUnlock(&tsdPtr->tsdLock) #ifdef TCL_MAC_DEBUG_NOTIFIER #define TclMacOSXNotifierDbgMsg(m, ...) \ do { \ fprintf(notifierLog?notifierLog:stderr, "tclMacOSXNotify.c:%d: " \ "%s() pid %5d thread %10p: " m "\n", __LINE__, __func__, \ getpid(), pthread_self(), ##__VA_ARGS__); \ fflush(notifierLog?notifierLog:stderr); \ } while (0) /* * Debug version of SpinLockLock that logs the time spent waiting for the lock */ #define SpinLockLockDbg(p) \ if (!SpinLockTry(p)) { \ Tcl_WideInt s = TclpGetWideClicks(), e; \ \ SpinLockLock(p); \ e = TclpGetWideClicks(); \ TclMacOSXNotifierDbgMsg("waited on %s for %8.0f ns", \ #p, TclpWideClicksToNanoseconds(e-s)); \ } #undef LOCK_NOTIFIER_INIT #define LOCK_NOTIFIER_INIT SpinLockLockDbg(¬ifierInitLock) #undef LOCK_NOTIFIER #define LOCK_NOTIFIER SpinLockLockDbg(¬ifierLock) #undef LOCK_NOTIFIER_TSD #define LOCK_NOTIFIER_TSD SpinLockLockDbg(&tsdPtr->tsdLock) #include static FILE *notifierLog = NULL; #ifndef NOTIFIER_LOG #define NOTIFIER_LOG "/tmp/tclMacOSXNotify.log" #endif #define OPEN_NOTIFIER_LOG \ if (!notifierLog) { \ notifierLog = fopen(NOTIFIER_LOG, "a"); \ /*TclMacOSXNotifierDbgMsg("open log"); \ *asl_set_filter(NULL, \ * ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); \ *asl_add_log_file(NULL, fileno(notifierLog));*/ \ } #define CLOSE_NOTIFIER_LOG \ if (notifierLog) { \ /*asl_remove_log_file(NULL, fileno(notifierLog)); \ *TclMacOSXNotifierDbgMsg("close log");*/ \ fclose(notifierLog); \ notifierLog = NULL; \ } #define ENABLE_ASL \ if (notifierLog) { \ /*tsdPtr->asl = asl_open(NULL, "com.apple.console", \ * ASL_OPT_NO_REMOTE); \ *asl_set_filter(tsdPtr->asl, \ * ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG)); \ *asl_add_log_file(tsdPtr->asl, fileno(notifierLog));*/ \ } #define DISABLE_ASL \ /*if (tsdPtr->asl) { \ * if (notifierLog) { \ * asl_remove_log_file(tsdPtr->asl, fileno(notifierLog)); \ * } \ * asl_close(tsdPtr->asl); \ *}*/ #define ASLCLIENT_DECL /*aslclient asl*/ #else #define TclMacOSXNotifierDbgMsg(m, ...) #define OPEN_NOTIFIER_LOG #define CLOSE_NOTIFIER_LOG #define ENABLE_ASL #define DISABLE_ASL #define ASLCLIENT_DECL #endif /* TCL_MAC_DEBUG_NOTIFIER */ /* * This structure is used to keep track of the notifier info for a registered * file. */ typedef struct FileHandler { int fd; int mask; /* Mask of desired events: TCL_READABLE, * etc. */ int readyMask; /* Mask of events that have been seen since * the last time file handlers were invoked * for this file. */ Tcl_FileProc *proc; /* Function to call, in the style of * Tcl_CreateFileHandler. */ ClientData clientData; /* Argument to pass to proc. */ struct FileHandler *nextPtr;/* Next in list of all files we care about. */ } FileHandler; /* * The following structure is what is added to the Tcl event queue when file * handlers are ready to fire. */ typedef struct FileHandlerEvent { Tcl_Event header; /* Information that is standard for all * events. */ int fd; /* File descriptor that is ready. Used to find * the FileHandler structure for the file * (can't point directly to the FileHandler * structure because it could go away while * the event is queued). */ } FileHandlerEvent; /* * The following structure contains a set of select() masks to track readable, * writable, and exceptional conditions. */ typedef struct SelectMasks { fd_set readable; fd_set writable; fd_set exceptional; } SelectMasks; /* * The following static structure contains the state information for the * select based implementation of the Tcl notifier. One of these structures is * created for each thread that is using the notifier. */ typedef struct ThreadSpecificData { FileHandler *firstFileHandlerPtr; /* Pointer to head of file handler list. */ int polled; /* True if the notifier thread has polled for * this thread. */ int sleeping; /* True if runloop is inside Tcl_Sleep. */ int runLoopSourcePerformed; /* True after the runLoopSource callack was * performed. */ int runLoopRunning; /* True if this thread's Tcl runLoop is * running. */ int runLoopNestingLevel; /* Level of nested runLoop invocations. */ int runLoopServicingEvents; /* True if this thread's runLoop is servicing * Tcl events. */ /* Must hold the notifierLock before accessing the following fields: */ /* Start notifierLock section */ int onList; /* True if this thread is on the * waitingList */ struct ThreadSpecificData *nextPtr, *prevPtr; /* All threads that are currently waiting on * an event have their ThreadSpecificData * structure on a doubly-linked listed formed * from these pointers. */ /* End notifierLock section */ OSSpinLock tsdLock; /* Must hold this lock before acessing the * following fields from more than one * thread. */ /* Start tsdLock section */ SelectMasks checkMasks; /* This structure is used to build up the * masks to be used in the next call to * select. Bits are set in response to calls * to Tcl_CreateFileHandler. */ SelectMasks readyMasks; /* This array reflects the readable/writable * conditions that were found to exist by the * last call to select. */ int numFdBits; /* Number of valid bits in checkMasks (one * more than highest fd for which * Tcl_WatchFile has been called). */ int polling; /* True if this thread is polling for * events. */ CFRunLoopRef runLoop; /* This thread's CFRunLoop, needs to be woken * up whenever the runLoopSource is * signaled. */ CFRunLoopSourceRef runLoopSource; /* Any other thread alerts a notifier that an * event is ready to be processed by signaling * this CFRunLoopSource. */ CFRunLoopObserverRef runLoopObserver, runLoopObserverTcl; /* Adds/removes this thread from waitingList * when the CFRunLoop starts/stops. */ CFRunLoopTimerRef runLoopTimer; /* Wakes up CFRunLoop after given timeout when * running embedded. */ /* End tsdLock section */ CFTimeInterval waitTime; /* runLoopTimer wait time when running * embedded. */ ASLCLIENT_DECL; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * The following static indicates the number of threads that have initialized * notifiers. * * You must hold the notifierInitLock before accessing this variable. */ static int notifierCount = 0; /* * The following variable points to the head of a doubly-linked list of * ThreadSpecificData structures for all threads that are currently waiting on * an event. * * You must hold the notifierLock before accessing this list. */ static ThreadSpecificData *waitingListPtr = NULL; /* * The notifier thread spends all its time in select() waiting for a file * descriptor associated with one of the threads on the waitingListPtr list to * do something interesting. But if the contents of the waitingListPtr list * ever changes, we need to wake up and restart the select() system call. You * can wake up the notifier thread by writing a single byte to the file * descriptor defined below. This file descriptor is the input-end of a pipe * and the notifier thread is listening for data on the output-end of the same * pipe. Hence writing to this file descriptor will cause the select() system * call to return and wake up the notifier thread. * * You must hold the notifierLock lock before writing to the pipe. */ static int triggerPipe = -1; static int receivePipe = -1; /* Output end of triggerPipe */ /* * The following static indicates if the notifier thread is running. * * You must hold the notifierInitLock before accessing this variable. */ static int notifierThreadRunning; /* * This is the thread ID of the notifier thread that does select. Only valid * when notifierThreadRunning is non-zero. * * You must hold the notifierInitLock before accessing this variable. */ static pthread_t notifierThread; /* * Custom runloop mode for running with only the runloop source for the * notifier thread. */ #ifndef TCL_EVENTS_ONLY_RUN_LOOP_MODE #define TCL_EVENTS_ONLY_RUN_LOOP_MODE "com.tcltk.tclEventsOnlyRunLoopMode" #endif #ifdef __CONSTANT_CFSTRINGS__ #define tclEventsOnlyRunLoopMode CFSTR(TCL_EVENTS_ONLY_RUN_LOOP_MODE) #else static CFStringRef tclEventsOnlyRunLoopMode = NULL; #endif /* * CFTimeInterval to wait forever. */ #define CF_TIMEINTERVAL_FOREVER 5.05e8 /* * Static routines defined in this file. */ static void StartNotifierThread(void); static void NotifierThreadProc(ClientData clientData) __attribute__ ((__noreturn__)); static int FileHandlerEventProc(Tcl_Event *evPtr, int flags); static void TimerWakeUp(CFRunLoopTimerRef timer, void *info); static void QueueFileEvents(void *info); static void UpdateWaitingListAndServiceEvents( CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info); static int OnOffWaitingList(ThreadSpecificData *tsdPtr, int onList, int signalNotifier); #ifdef HAVE_PTHREAD_ATFORK static int atForkInit = 0; static void AtForkPrepare(void); static void AtForkParent(void); static void AtForkChild(void); #if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040 /* Support for weakly importing pthread_atfork. */ #define WEAK_IMPORT_PTHREAD_ATFORK extern int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) WEAK_IMPORT_ATTRIBUTE; #define MayUsePthreadAtfork() (pthread_atfork != NULL) #else #define MayUsePthreadAtfork() (1) #endif /* HAVE_WEAK_IMPORT */ /* * On Darwin 9 and later, it is not possible to call CoreFoundation after * a fork. */ #if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || \ MAC_OS_X_VERSION_MIN_REQUIRED < 1050 MODULE_SCOPE long tclMacOSXDarwinRelease; #define noCFafterFork (tclMacOSXDarwinRelease >= 9) #else /* MAC_OS_X_VERSION_MIN_REQUIRED */ #define noCFafterFork 1 #endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #endif /* HAVE_PTHREAD_ATFORK */ /* *---------------------------------------------------------------------- * * Tcl_InitNotifier -- * * Initializes the platform specific notifier state. * * Results: * Returns a handle to the notifier state for this thread. * * Side effects: * None. * *---------------------------------------------------------------------- */ ClientData Tcl_InitNotifier(void) { ThreadSpecificData *tsdPtr; if (tclNotifierHooks.initNotifierProc) { return tclNotifierHooks.initNotifierProc(); } 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"); } #endif #ifndef __CONSTANT_CFSTRINGS__ if (!tclEventsOnlyRunLoopMode) { tclEventsOnlyRunLoopMode = CFSTR(TCL_EVENTS_ONLY_RUN_LOOP_MODE); } #endif /* * Initialize CFRunLoopSource and add it to CFRunLoop of this thread. */ if (!tsdPtr->runLoop) { CFRunLoopRef runLoop = CFRunLoopGetCurrent(); CFRunLoopSourceRef runLoopSource; CFRunLoopSourceContext runLoopSourceContext; CFRunLoopObserverContext runLoopObserverContext; CFRunLoopObserverRef runLoopObserver, runLoopObserverTcl; bzero(&runLoopSourceContext, sizeof(CFRunLoopSourceContext)); runLoopSourceContext.info = tsdPtr; runLoopSourceContext.perform = QueueFileEvents; runLoopSource = CFRunLoopSourceCreate(NULL, LONG_MIN, &runLoopSourceContext); if (!runLoopSource) { Tcl_Panic("Tcl_InitNotifier: could not create CFRunLoopSource"); } CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopCommonModes); CFRunLoopAddSource(runLoop, runLoopSource, tclEventsOnlyRunLoopMode); bzero(&runLoopObserverContext, sizeof(CFRunLoopObserverContext)); runLoopObserverContext.info = tsdPtr; runLoopObserver = CFRunLoopObserverCreate(NULL, kCFRunLoopEntry|kCFRunLoopExit|kCFRunLoopBeforeWaiting, TRUE, LONG_MIN, UpdateWaitingListAndServiceEvents, &runLoopObserverContext); if (!runLoopObserver) { Tcl_Panic("Tcl_InitNotifier: could not create " "CFRunLoopObserver"); } CFRunLoopAddObserver(runLoop, runLoopObserver, kCFRunLoopCommonModes); /* * Create a second CFRunLoopObserver with the same callback as above * for the tclEventsOnlyRunLoopMode to ensure that the callback can be * re-entered via Tcl_ServiceAll() in the kCFRunLoopBeforeWaiting case * (CFRunLoop prevents observer callback re-entry of a given observer * instance). */ runLoopObserverTcl = CFRunLoopObserverCreate(NULL, kCFRunLoopEntry|kCFRunLoopExit|kCFRunLoopBeforeWaiting, TRUE, LONG_MIN, UpdateWaitingListAndServiceEvents, &runLoopObserverContext); if (!runLoopObserverTcl) { Tcl_Panic("Tcl_InitNotifier: could not create " "CFRunLoopObserver"); } CFRunLoopAddObserver(runLoop, runLoopObserverTcl, tclEventsOnlyRunLoopMode); tsdPtr->runLoop = runLoop; tsdPtr->runLoopSource = runLoopSource; tsdPtr->runLoopObserver = runLoopObserver; tsdPtr->runLoopObserverTcl = runLoopObserverTcl; tsdPtr->runLoopTimer = NULL; tsdPtr->waitTime = CF_TIMEINTERVAL_FOREVER; tsdPtr->tsdLock = SPINLOCK_INIT; } LOCK_NOTIFIER_INIT; #ifdef HAVE_PTHREAD_ATFORK /* * Install pthread_atfork handlers to reinitialize the notifier in the * child of a fork. */ if (MayUsePthreadAtfork() && !atForkInit) { int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild); if (result) { Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed"); } atForkInit = 1; } #endif /* HAVE_PTHREAD_ATFORK */ if (notifierCount == 0) { int fds[2], status; /* * Initialize trigger pipe. */ if (pipe(fds) != 0) { Tcl_Panic("Tcl_InitNotifier: 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"); } 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"); } receivePipe = fds[0]; triggerPipe = fds[1]; /* * Create notifier thread lazily in Tcl_WaitForEvent() to avoid * interfering with fork() followed immediately by execve() (we cannot * execve() when more than one thread is present). */ notifierThreadRunning = 0; OPEN_NOTIFIER_LOG; } ENABLE_ASL; notifierCount++; UNLOCK_NOTIFIER_INIT; return tsdPtr; } /* *---------------------------------------------------------------------- * * TclMacOSXNotifierAddRunLoopMode -- * * Add the tcl notifier RunLoop source, observer and timer (if any) * to the given RunLoop mode. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclMacOSXNotifierAddRunLoopMode( const void *runLoopMode) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); CFStringRef mode = (CFStringRef) runLoopMode; if (tsdPtr->runLoop) { CFRunLoopAddSource(tsdPtr->runLoop, tsdPtr->runLoopSource, mode); CFRunLoopAddObserver(tsdPtr->runLoop, tsdPtr->runLoopObserver, mode); if (tsdPtr->runLoopTimer) { CFRunLoopAddTimer(tsdPtr->runLoop, tsdPtr->runLoopTimer, mode); } } } /* *---------------------------------------------------------------------- * * StartNotifierThread -- * * Start notifier thread if necessary. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void StartNotifierThread(void) { LOCK_NOTIFIER_INIT; if (!notifierCount) { Tcl_Panic("StartNotifierThread: notifier not initialized"); } if (!notifierThreadRunning) { int result; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setstacksize(&attr, 60 * 1024); result = pthread_create(¬ifierThread, &attr, (void * (*)(void *))NotifierThreadProc, NULL); pthread_attr_destroy(&attr); if (result) { Tcl_Panic("StartNotifierThread: unable to start notifier thread"); } notifierThreadRunning = 1; } UNLOCK_NOTIFIER_INIT; } /* *---------------------------------------------------------------------- * * Tcl_FinalizeNotifier -- * * This function is called to cleanup the notifier state before a thread * is terminated. * * Results: * None. * * Side effects: * May terminate the background notifier thread if this is the last * notifier instance. * *---------------------------------------------------------------------- */ void Tcl_FinalizeNotifier( ClientData clientData) /* Not used. */ { ThreadSpecificData *tsdPtr; if (tclNotifierHooks.finalizeNotifierProc) { tclNotifierHooks.finalizeNotifierProc(clientData); return; } tsdPtr = TCL_TSD_INIT(&dataKey); LOCK_NOTIFIER_INIT; notifierCount--; DISABLE_ASL; /* * 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) { if (triggerPipe != -1) { /* * Send "q" message to the notifier thread so that it will * terminate. The notifier will return from its call to select() * and notice that a "q" message has arrived, it will then close * its side of the pipe and terminate its thread. Note the we can * not just close the pipe and check for EOF in the notifier * thread because if a background child process was created with * exec, select() would not register the EOF on the pipe until the * child processes had terminated. [Bug: 4139] [Bug 1222872] */ write(triggerPipe, "q", 1); close(triggerPipe); if (notifierThreadRunning) { int result = pthread_join(notifierThread, NULL); if (result) { Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier " "thread"); } notifierThreadRunning = 0; } close(receivePipe); triggerPipe = -1; } CLOSE_NOTIFIER_LOG; } UNLOCK_NOTIFIER_INIT; LOCK_NOTIFIER_TSD; /* For concurrency with Tcl_AlertNotifier */ if (tsdPtr->runLoop) { tsdPtr->runLoop = NULL; /* * Remove runLoopSource, runLoopObserver and runLoopTimer from all * CFRunLoops. */ CFRunLoopSourceInvalidate(tsdPtr->runLoopSource); CFRelease(tsdPtr->runLoopSource); tsdPtr->runLoopSource = NULL; CFRunLoopObserverInvalidate(tsdPtr->runLoopObserver); CFRelease(tsdPtr->runLoopObserver); tsdPtr->runLoopObserver = NULL; CFRunLoopObserverInvalidate(tsdPtr->runLoopObserverTcl); CFRelease(tsdPtr->runLoopObserverTcl); tsdPtr->runLoopObserverTcl = NULL; if (tsdPtr->runLoopTimer) { CFRunLoopTimerInvalidate(tsdPtr->runLoopTimer); CFRelease(tsdPtr->runLoopTimer); tsdPtr->runLoopTimer = NULL; } } UNLOCK_NOTIFIER_TSD; } /* *---------------------------------------------------------------------- * * 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 on a * given notifier after Tcl_FinalizeNotifier is called for that notifier. * * Results: * None. * * Side effects: * Signals the notifier condition variable for the specified notifier. * *---------------------------------------------------------------------- */ void Tcl_AlertNotifier( ClientData clientData) { ThreadSpecificData *tsdPtr = clientData; if (tclNotifierHooks.alertNotifierProc) { tclNotifierHooks.alertNotifierProc(clientData); return; } LOCK_NOTIFIER_TSD; if (tsdPtr->runLoop) { CFRunLoopSourceSignal(tsdPtr->runLoopSource); CFRunLoopWakeUp(tsdPtr->runLoop); } UNLOCK_NOTIFIER_TSD; } /* *---------------------------------------------------------------------- * * Tcl_SetTimer -- * * This function sets the current notifier timer value. * * Results: * None. * * Side effects: * Replaces any previous timer. * *---------------------------------------------------------------------- */ void Tcl_SetTimer( 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) { return; } if (timePtr) { Tcl_Time vTime = *timePtr; if (vTime.sec != 0 || vTime.usec != 0) { tclScaleTimeProcPtr(&vTime, tclTimeClientData); waitTime = vTime.sec + 1.0e-6 * vTime.usec; } else { waitTime = 0; } } else { waitTime = CF_TIMEINTERVAL_FOREVER; } tsdPtr->waitTime = waitTime; CFRunLoopTimerSetNextFireDate(runLoopTimer, CFAbsoluteTimeGetCurrent() + waitTime); } /* *---------------------------------------------------------------------- * * TimerWakeUp -- * * CFRunLoopTimer callback. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void TimerWakeUp( CFRunLoopTimerRef timer, void *info) { } /* *---------------------------------------------------------------------- * * Tcl_ServiceModeHook -- * * This function is invoked whenever the service mode changes. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_ServiceModeHook( int mode) /* Either TCL_SERVICE_ALL, or * TCL_SERVICE_NONE. */ { ThreadSpecificData *tsdPtr; if (tclNotifierHooks.serviceModeHookProc) { tclNotifierHooks.serviceModeHookProc(mode); return; } tsdPtr = TCL_TSD_INIT(&dataKey); if (mode == TCL_SERVICE_ALL && !tsdPtr->runLoopTimer) { if (!tsdPtr->runLoop) { Tcl_Panic("Tcl_ServiceModeHook: Notifier not initialized"); } tsdPtr->runLoopTimer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + CF_TIMEINTERVAL_FOREVER, CF_TIMEINTERVAL_FOREVER, 0, 0, TimerWakeUp, NULL); if (tsdPtr->runLoopTimer) { CFRunLoopAddTimer(tsdPtr->runLoop, tsdPtr->runLoopTimer, kCFRunLoopCommonModes); StartNotifierThread(); } } } /* *---------------------------------------------------------------------- * * Tcl_CreateFileHandler -- * * This function registers a file handler with the select notifier. * * Results: * None. * * Side effects: * Creates a new file handler structure. * *---------------------------------------------------------------------- */ 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. */ { ThreadSpecificData *tsdPtr; FileHandler *filePtr; if (tclNotifierHooks.createFileHandlerProc) { tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData); return; } tsdPtr = TCL_TSD_INIT(&dataKey); for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; filePtr = filePtr->nextPtr) { if (filePtr->fd == fd) { break; } } if (filePtr == NULL) { filePtr = 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. */ LOCK_NOTIFIER_TSD; 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.exceptional); } else { FD_CLR(fd, &tsdPtr->checkMasks.exceptional); } if (tsdPtr->numFdBits <= fd) { tsdPtr->numFdBits = fd+1; } UNLOCK_NOTIFIER_TSD; } /* *---------------------------------------------------------------------- * * Tcl_DeleteFileHandler -- * * Cancel a previously-arranged callback arrangement for a file. * * Results: * None. * * Side effects: * If a callback was previously registered on file, remove it. * *---------------------------------------------------------------------- */ void Tcl_DeleteFileHandler( 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; /* * 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; } } /* * Find current max fd. */ if (fd+1 == tsdPtr->numFdBits) { 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.exceptional)) { numFdBits = i+1; break; } } } LOCK_NOTIFIER_TSD; if (numFdBits != -1) { tsdPtr->numFdBits = numFdBits; } /* * 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.exceptional); } UNLOCK_NOTIFIER_TSD; /* * Clean up information in the callback record. */ if (prevPtr == NULL) { tsdPtr->firstFileHandlerPtr = filePtr->nextPtr; } else { prevPtr->nextPtr = filePtr->nextPtr; } ckfree(filePtr); } /* *---------------------------------------------------------------------- * * FileHandlerEventProc -- * * This function is called by Tcl_ServiceEvent when a file event reaches * the front of the event queue. This function is responsible for * actually handling the event by invoking the callback for the file * handler. * * Results: * Returns 1 if the event was handled, meaning it should be removed from * the queue. Returns 0 if the event was not handled, meaning it should * stay on the queue. The only time the event isn't handled is if the * TCL_FILE_EVENTS flag bit isn't set. * * Side effects: * Whatever the file handler's callback function does. * *---------------------------------------------------------------------- */ static int FileHandlerEventProc( Tcl_Event *evPtr, /* Event to service. */ int flags) /* Flags that indicate what events to handle, * such as TCL_FILE_EVENTS. */ { int mask; FileHandler *filePtr; FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr; ThreadSpecificData *tsdPtr; if (!(flags & TCL_FILE_EVENTS)) { return 0; } /* * Search through the file handlers to find the one whose handle matches * the event. We do this rather than keeping a pointer to the file handler * directly in the event, so that the handler can be deleted while the * event is queued without leaving a dangling pointer. */ tsdPtr = TCL_TSD_INIT(&dataKey); for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; filePtr = filePtr->nextPtr) { if (filePtr->fd != fileEvPtr->fd) { continue; } /* * The code is tricky for two reasons: * 1. The file handler's desired events could have changed since the * time when the event was queued, so AND the ready mask with the * desired mask. * 2. The file could have been closed and re-opened since the time * when the event was queued. This is why the ready mask is stored * in the file handler rather than the queued event: it will be * zeroed when a new file handler is created for the newly opened * file. */ mask = filePtr->readyMask & filePtr->mask; filePtr->readyMask = 0; if (mask != 0) { LOCK_NOTIFIER_TSD; if (mask & TCL_READABLE) { FD_CLR(filePtr->fd, &tsdPtr->readyMasks.readable); } if (mask & TCL_WRITABLE) { FD_CLR(filePtr->fd, &tsdPtr->readyMasks.writable); } if (mask & TCL_EXCEPTION) { FD_CLR(filePtr->fd, &tsdPtr->readyMasks.exceptional); } UNLOCK_NOTIFIER_TSD; filePtr->proc(filePtr->clientData, mask); } break; } return 1; } /* *---------------------------------------------------------------------- * * Tcl_WaitForEvent -- * * This function is called by Tcl_DoOneEvent to wait for new events on * the message queue. If the block time is 0, then Tcl_WaitForEvent just * polls without blocking. * * Results: * Returns 0 if a tcl event or timeout ocurred and 1 if a non-tcl * CFRunLoop source was processed. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_WaitForEvent( const Tcl_Time *timePtr) /* Maximum block time, or NULL. */ { int result, polling, runLoopRunning; CFTimeInterval waitTime; SInt32 runLoopStatus; ThreadSpecificData *tsdPtr; if (tclNotifierHooks.waitForEventProc) { return tclNotifierHooks.waitForEventProc(timePtr); } result = -1; polling = 0; waitTime = CF_TIMEINTERVAL_FOREVER; tsdPtr = TCL_TSD_INIT(&dataKey); if (!tsdPtr->runLoop) { Tcl_Panic("Tcl_WaitForEvent: Notifier not initialized"); } if (timePtr) { Tcl_Time vTime = *timePtr; /* * 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 (vTime.sec != 0 || vTime.usec != 0) { tclScaleTimeProcPtr(&vTime, tclTimeClientData); waitTime = vTime.sec + 1.0e-6 * vTime.usec; } else { /* * Polling: 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. */ polling = 1; } } StartNotifierThread(); LOCK_NOTIFIER_TSD; tsdPtr->polling = polling; UNLOCK_NOTIFIER_TSD; tsdPtr->runLoopSourcePerformed = 0; /* * If the Tcl runloop is already running (e.g. if Tcl_WaitForEvent was * called recursively) or is servicing events via the runloop observer, * re-run it in a custom runloop mode containing only the source for the * notifier thread, otherwise wakeups from other sources added to the * common runloop modes might get lost or 3rd party event handlers might * get called when they do not expect to be. */ runLoopRunning = tsdPtr->runLoopRunning; tsdPtr->runLoopRunning = 1; runLoopStatus = CFRunLoopRunInMode(tsdPtr->runLoopServicingEvents || runLoopRunning ? tclEventsOnlyRunLoopMode : kCFRunLoopDefaultMode, waitTime, TRUE); tsdPtr->runLoopRunning = runLoopRunning; LOCK_NOTIFIER_TSD; tsdPtr->polling = 0; UNLOCK_NOTIFIER_TSD; switch (runLoopStatus) { case kCFRunLoopRunFinished: Tcl_Panic("Tcl_WaitForEvent: CFRunLoop finished"); break; case kCFRunLoopRunTimedOut: QueueFileEvents(tsdPtr); result = 0; break; case kCFRunLoopRunStopped: case kCFRunLoopRunHandledSource: result = tsdPtr->runLoopSourcePerformed ? 0 : 1; break; } return result; } /* *---------------------------------------------------------------------- * * QueueFileEvents -- * * CFRunLoopSource callback for queueing file events. * * Results: * None. * * Side effects: * Queues file events that are detected by the select. * *---------------------------------------------------------------------- */ static void QueueFileEvents( void *info) { SelectMasks readyMasks; FileHandler *filePtr; ThreadSpecificData *tsdPtr = info; /* * Queue all detected file events. */ LOCK_NOTIFIER_TSD; FD_COPY(&tsdPtr->readyMasks.readable, &readyMasks.readable); FD_COPY(&tsdPtr->readyMasks.writable, &readyMasks.writable); FD_COPY(&tsdPtr->readyMasks.exceptional, &readyMasks.exceptional); FD_ZERO(&tsdPtr->readyMasks.readable); FD_ZERO(&tsdPtr->readyMasks.writable); FD_ZERO(&tsdPtr->readyMasks.exceptional); UNLOCK_NOTIFIER_TSD; tsdPtr->runLoopSourcePerformed = 1; for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL); filePtr = filePtr->nextPtr) { int mask = 0; if (FD_ISSET(filePtr->fd, &readyMasks.readable)) { mask |= TCL_READABLE; } if (FD_ISSET(filePtr->fd, &readyMasks.writable)) { mask |= TCL_WRITABLE; } if (FD_ISSET(filePtr->fd, &readyMasks.exceptional)) { mask |= TCL_EXCEPTION; } 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 = ckalloc(sizeof(FileHandlerEvent)); fileEvPtr->header.proc = FileHandlerEventProc; fileEvPtr->fd = filePtr->fd; Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); } filePtr->readyMask = mask; } } /* *---------------------------------------------------------------------- * * UpdateWaitingListAndServiceEvents -- * * CFRunLoopObserver callback for updating waitingList and * servicing Tcl events. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void UpdateWaitingListAndServiceEvents( CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) { ThreadSpecificData *tsdPtr = info; if (tsdPtr->sleeping) { return; } switch (activity) { case kCFRunLoopEntry: tsdPtr->runLoopNestingLevel++; if (tsdPtr->numFdBits > 0 || tsdPtr->polling) { LOCK_NOTIFIER; if (!OnOffWaitingList(tsdPtr, 1, 1) && tsdPtr->polling) { write(triggerPipe, "", 1); } UNLOCK_NOTIFIER; } break; case kCFRunLoopExit: if (tsdPtr->runLoopNestingLevel == 1) { LOCK_NOTIFIER; OnOffWaitingList(tsdPtr, 0, 1); UNLOCK_NOTIFIER; } tsdPtr->runLoopNestingLevel--; break; case kCFRunLoopBeforeWaiting: if (tsdPtr->runLoopTimer && !tsdPtr->runLoopServicingEvents && (tsdPtr->runLoopNestingLevel > 1 || !tsdPtr->runLoopRunning)) { tsdPtr->runLoopServicingEvents = 1; /* This call seems to simply force event processing through and prevents hangups that have long been observed with Tk-Cocoa. */ Tcl_ServiceAll(); tsdPtr->runLoopServicingEvents = 0; } break; default: break; } } /* *---------------------------------------------------------------------- * * OnOffWaitingList -- * * Add/remove the specified thread to/from the global waitingList and * optionally signal the notifier. * * !!! Requires notifierLock to be held !!! * * Results: * Boolean indicating whether the waitingList was changed. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int OnOffWaitingList( ThreadSpecificData *tsdPtr, int onList, int signalNotifier) { int changeWaitingList; #ifdef TCL_MAC_DEBUG_NOTIFIER if (SpinLockTry(¬ifierLock)) { Tcl_Panic("OnOffWaitingList: notifierLock unlocked"); } #endif changeWaitingList = (!onList ^ !tsdPtr->onList); if (changeWaitingList) { if (onList) { tsdPtr->nextPtr = waitingListPtr; if (waitingListPtr) { waitingListPtr->prevPtr = tsdPtr; } tsdPtr->prevPtr = NULL; waitingListPtr = tsdPtr; tsdPtr->onList = 1; } else { 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 (signalNotifier) { write(triggerPipe, "", 1); } } return changeWaitingList; } /* *---------------------------------------------------------------------- * * Tcl_Sleep -- * * Delay execution for the specified number of milliseconds. * * Results: * None. * * Side effects: * Time passes. * *---------------------------------------------------------------------- */ void Tcl_Sleep( int ms) /* Number of milliseconds to sleep. */ { Tcl_Time vdelay; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (ms <= 0) { return; } /* * TIP #233: Scale from virtual time to real-time. */ vdelay.sec = ms / 1000; vdelay.usec = (ms % 1000) * 1000; tclScaleTimeProcPtr(&vdelay, tclTimeClientData); if (tsdPtr->runLoop) { CFTimeInterval waitTime; CFRunLoopTimerRef runLoopTimer = tsdPtr->runLoopTimer; CFAbsoluteTime nextTimerFire = 0, waitEnd, now; SInt32 runLoopStatus; waitTime = vdelay.sec + 1.0e-6 * vdelay.usec; now = CFAbsoluteTimeGetCurrent(); waitEnd = now + waitTime; if (runLoopTimer) { nextTimerFire = CFRunLoopTimerGetNextFireDate(runLoopTimer); if (nextTimerFire < waitEnd) { CFRunLoopTimerSetNextFireDate(runLoopTimer, now + CF_TIMEINTERVAL_FOREVER); } else { runLoopTimer = NULL; } } tsdPtr->sleeping = 1; do { runLoopStatus = CFRunLoopRunInMode(kCFRunLoopDefaultMode, waitTime, FALSE); switch (runLoopStatus) { case kCFRunLoopRunFinished: Tcl_Panic("Tcl_Sleep: CFRunLoop finished"); break; case kCFRunLoopRunStopped: TclMacOSXNotifierDbgMsg("CFRunLoop stopped"); waitTime = waitEnd - CFAbsoluteTimeGetCurrent(); break; case kCFRunLoopRunTimedOut: waitTime = 0; break; } } while (waitTime > 0); tsdPtr->sleeping = 0; if (runLoopTimer) { CFRunLoopTimerSetNextFireDate(runLoopTimer, nextTimerFire); } } else { struct timespec waitTime; waitTime.tv_sec = vdelay.sec; waitTime.tv_nsec = vdelay.usec * 1000; while (nanosleep(&waitTime, &waitTime)); } } /* *---------------------------------------------------------------------- * * TclUnixWaitForFile -- * * This function waits synchronously for a file to become readable or * writable, with an optional timeout. * * Results: * The return value is an OR'ed combination of TCL_READABLE, * TCL_WRITABLE, and TCL_EXCEPTION, indicating the conditions that are * present on file at the time of the return. This function will not * return until either "timeout" milliseconds have elapsed or at least * one of the conditions given by mask has occurred for file (a return * value of 0 means that a timeout occurred). No normal events will be * serviced during the execution of this function. * * Side effects: * Time passes. * *---------------------------------------------------------------------- */ int TclUnixWaitForFile( int fd, /* Handle for file on which to wait. */ int mask, /* What to wait for: OR'ed combination of * TCL_READABLE, TCL_WRITABLE, and * TCL_EXCEPTION. */ int timeout) /* Maximum amount of time to wait for one of * the conditions in mask to occur, in * milliseconds. A value of 0 means don't wait * at all, and a value of -1 means wait * forever. */ { Tcl_Time abortTime = {0, 0}, now; /* silence gcc 4 warning */ struct timeval blockTime, *timeoutPtr; int numFound, result = 0; fd_set readableMask; fd_set writableMask; fd_set exceptionalMask; #define SET_BITS(var, bits) ((var) |= (bits)) #define CLEAR_BITS(var, bits) ((var) &= ~(bits)) #ifndef _DARWIN_C_SOURCE /* * Sanity check fd. */ if (fd >= FD_SETSIZE) { Tcl_Panic("TclUnixWaitForFile can't handle file id %d", fd); /* must never get here, or select masks overrun will occur below */ } #endif /* * If there is a non-zero finite timeout, compute the time when we give * up. */ if (timeout > 0) { Tcl_GetTime(&now); abortTime.sec = now.sec + timeout/1000; abortTime.usec = now.usec + (timeout%1000)*1000; if (abortTime.usec >= 1000000) { abortTime.usec -= 1000000; abortTime.sec += 1; } timeoutPtr = &blockTime; } else if (timeout == 0) { timeoutPtr = &blockTime; blockTime.tv_sec = 0; blockTime.tv_usec = 0; } else { timeoutPtr = NULL; } /* * Initialize the select masks. */ FD_ZERO(&readableMask); FD_ZERO(&writableMask); FD_ZERO(&exceptionalMask); /* * Loop in a mini-event loop of our own, waiting for either the file to * become ready or a timeout to occur. */ while (1) { if (timeout > 0) { blockTime.tv_sec = abortTime.sec - now.sec; blockTime.tv_usec = abortTime.usec - now.usec; if (blockTime.tv_usec < 0) { blockTime.tv_sec -= 1; blockTime.tv_usec += 1000000; } if (blockTime.tv_sec < 0) { blockTime.tv_sec = 0; blockTime.tv_usec = 0; } } /* * Setup the select masks for the fd. */ if (mask & TCL_READABLE) { FD_SET(fd, &readableMask); } if (mask & TCL_WRITABLE) { FD_SET(fd, &writableMask); } if (mask & TCL_EXCEPTION) { FD_SET(fd, &exceptionalMask); } /* * Wait for the event or a timeout. */ numFound = select(fd + 1, &readableMask, &writableMask, &exceptionalMask, timeoutPtr); if (numFound == 1) { if (FD_ISSET(fd, &readableMask)) { SET_BITS(result, TCL_READABLE); } if (FD_ISSET(fd, &writableMask)) { SET_BITS(result, TCL_WRITABLE); } if (FD_ISSET(fd, &exceptionalMask)) { SET_BITS(result, TCL_EXCEPTION); } result &= mask; if (result) { break; } } if (timeout == 0) { break; } if (timeout < 0) { continue; } /* * The select returned early, so we need to recompute the timeout. */ Tcl_GetTime(&now); if ((abortTime.sec < now.sec) || (abortTime.sec==now.sec && abortTime.usec<=now.usec)) { break; } } return result; } /* *---------------------------------------------------------------------- * * NotifierThreadProc -- * * This routine is the initial (and only) function executed by the * special notifier thread. Its job is to wait for file descriptors to * become readable or writable or to have an exception condition and then * to notify other threads who are interested in this information by * signalling a condition variable. Other threads can signal this * notifier thread of a change in their interests by writing a single * 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. * * Side effects: * The trigger pipe used to signal the notifier thread is created when * the notifier thread first starts. * *---------------------------------------------------------------------- */ static void NotifierThreadProc( ClientData clientData) /* Not used. */ { ThreadSpecificData *tsdPtr; fd_set readableMask, writableMask, exceptionalMask; int i, numFdBits = 0, polling; struct timeval poll = {0., 0.}, *timePtr; char buf[2]; /* * Look for file events and report them to interested threads. */ while (1) { FD_ZERO(&readableMask); FD_ZERO(&writableMask); FD_ZERO(&exceptionalMask); /* * Compute the logical OR of the select masks from all the waiting * notifiers. */ timePtr = NULL; LOCK_NOTIFIER; for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { LOCK_NOTIFIER_TSD; for (i = tsdPtr->numFdBits-1; i >= 0; --i) { if (FD_ISSET(i, &tsdPtr->checkMasks.readable)) { FD_SET(i, &readableMask); } if (FD_ISSET(i, &tsdPtr->checkMasks.writable)) { FD_SET(i, &writableMask); } if (FD_ISSET(i, &tsdPtr->checkMasks.exceptional)) { FD_SET(i, &exceptionalMask); } } if (tsdPtr->numFdBits > numFdBits) { numFdBits = tsdPtr->numFdBits; } polling = tsdPtr->polling; UNLOCK_NOTIFIER_TSD; if ((tsdPtr->polled = polling)) { timePtr = &poll; } } UNLOCK_NOTIFIER; /* * Set up the select mask to include the receive pipe. */ if (receivePipe >= numFdBits) { numFdBits = receivePipe + 1; } FD_SET(receivePipe, &readableMask); if (select(numFdBits, &readableMask, &writableMask, &exceptionalMask, timePtr) == -1) { /* * Try again immediately on an error. */ continue; } /* * Alert any threads that are waiting on a ready file descriptor. */ LOCK_NOTIFIER; for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { int found = 0; SelectMasks readyMasks, checkMasks; LOCK_NOTIFIER_TSD; FD_COPY(&tsdPtr->checkMasks.readable, &checkMasks.readable); FD_COPY(&tsdPtr->checkMasks.writable, &checkMasks.writable); FD_COPY(&tsdPtr->checkMasks.exceptional, &checkMasks.exceptional); UNLOCK_NOTIFIER_TSD; found = tsdPtr->polled; FD_ZERO(&readyMasks.readable); FD_ZERO(&readyMasks.writable); FD_ZERO(&readyMasks.exceptional); for (i = tsdPtr->numFdBits-1; i >= 0; --i) { if (FD_ISSET(i, &checkMasks.readable) && FD_ISSET(i, &readableMask)) { FD_SET(i, &readyMasks.readable); found = 1; } if (FD_ISSET(i, &checkMasks.writable) && FD_ISSET(i, &writableMask)) { FD_SET(i, &readyMasks.writable); found = 1; } if (FD_ISSET(i, &checkMasks.exceptional) && FD_ISSET(i, &exceptionalMask)) { FD_SET(i, &readyMasks.exceptional); found = 1; } } if (found) { /* * Remove the ThreadSpecificData structure of this thread from * the waiting list. This prevents us from spinning * continuously on select until the other threads runs and * services the file event. */ OnOffWaitingList(tsdPtr, 0, 0); LOCK_NOTIFIER_TSD; FD_COPY(&readyMasks.readable, &tsdPtr->readyMasks.readable); FD_COPY(&readyMasks.writable, &tsdPtr->readyMasks.writable); FD_COPY(&readyMasks.exceptional, &tsdPtr->readyMasks.exceptional); UNLOCK_NOTIFIER_TSD; tsdPtr->polled = 0; if (tsdPtr->runLoop) { CFRunLoopSourceSignal(tsdPtr->runLoopSource); CFRunLoopWakeUp(tsdPtr->runLoop); } } } UNLOCK_NOTIFIER; /* * Consume the next byte from the notifier pipe if the pipe was * readable. Note that there may be multiple bytes pending, but to * avoid a race condition we only read one at a time. */ if (FD_ISSET(receivePipe, &readableMask)) { i = read(receivePipe, buf, 1); if ((i == 0) || ((i == 1) && (buf[0] == 'q'))) { /* * Someone closed the write end of the pipe or sent us a Quit * message [Bug: 4139] and then closed the write end of the * pipe so we need to shut down the notifier thread. */ break; } } } pthread_exit(0); } #ifdef HAVE_PTHREAD_ATFORK /* *---------------------------------------------------------------------- * * AtForkPrepare -- * * Lock the notifier in preparation for a fork. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void AtForkPrepare(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); LOCK_NOTIFIER_INIT; LOCK_NOTIFIER; LOCK_NOTIFIER_TSD; } /* *---------------------------------------------------------------------- * * AtForkParent -- * * Unlock the notifier in the parent after a fork. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void AtForkParent(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); UNLOCK_NOTIFIER_TSD; UNLOCK_NOTIFIER; UNLOCK_NOTIFIER_INIT; } /* *---------------------------------------------------------------------- * * AtForkChild -- * * Unlock and reinstall the notifier in the child after a fork. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void AtForkChild(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); UNLOCK_NOTIFIER_TSD; UNLOCK_NOTIFIER; UNLOCK_NOTIFIER_INIT; if (tsdPtr->runLoop) { tsdPtr->runLoop = NULL; if (!noCFafterFork) { CFRunLoopSourceInvalidate(tsdPtr->runLoopSource); CFRelease(tsdPtr->runLoopSource); if (tsdPtr->runLoopTimer) { CFRunLoopTimerInvalidate(tsdPtr->runLoopTimer); CFRelease(tsdPtr->runLoopTimer); } } tsdPtr->runLoopSource = NULL; tsdPtr->runLoopTimer = NULL; } if (notifierCount > 0) { notifierCount = 1; notifierThreadRunning = 0; /* * Assume that the return value of Tcl_InitNotifier in the child will * be identical to the one stored as clientData in tclNotify.c's * ThreadSpecificData by the parent's TclInitNotifier, so discard the * return value here. This assumption may require the fork() to be * executed in the main thread of the parent, otherwise * Tcl_AlertNotifier may break in the child. */ if (!noCFafterFork) { Tcl_InitNotifier(); } } } #endif /* HAVE_PTHREAD_ATFORK */ #else /* HAVE_COREFOUNDATION */ void TclMacOSXNotifierAddRunLoopMode( const void *runLoopMode) { Tcl_Panic("TclMacOSXNotifierAddRunLoopMode: " "Tcl not built with CoreFoundation support"); } #endif /* HAVE_COREFOUNDATION */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/macosx/Tcl-Common.xcconfig0000644000175000017500000000301712663653210016546 0ustar sergeisergei// // Tcl-Common.xcconfig -- // // This file contains the Xcode build settings comon to all // project configurations in Tcl.xcodeproj. // // Copyright (c) 2007-2008 Daniel A. Steffen // // See the file "license.terms" for information on usage and redistribution // of this file, and for a DISCLAIMER OF ALL WARRANTIES. HEADER_SEARCH_PATHS = "$(DERIVED_FILE_DIR)/tcl" $(HEADER_SEARCH_PATHS) OTHER_LDFLAGS = -headerpad_max_install_names -sectcreate __TEXT __info_plist "$(DERIVED_FILE_DIR)/tcl/Tclsh-Info.plist" $(OTHER_LDFLAGS) INSTALL_PATH = $(BINDIR) INSTALL_MODE_FLAG = go-w,a+rX GCC_PREFIX_HEADER = $(DERIVED_FILE_DIR)/tcl/tclConfig.h GCC_GENERATE_DEBUGGING_SYMBOLS = YES GCC_NO_COMMON_BLOCKS = YES GCC_DYNAMIC_NO_PIC = YES GCC_VERSION = 4.2 GCC = gcc-$(GCC_VERSION) WARNING_CFLAGS = -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-value -Winit-self -Wpointer-arith -Wcast-align -Wdisabled-optimization -Winline $(WARNING_CFLAGS) BINDIR = $(PREFIX)/bin CFLAGS = $(CFLAGS) CPPFLAGS = -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) $(CPPFLAGS) FRAMEWORK_INSTALL_PATH = /Library/Frameworks INCLUDEDIR = $(PREFIX)/include LIBDIR = $(PREFIX)/lib MANDIR = $(PREFIX)/man PER_ARCH_CFLAGS_ppc = -mcpu=G3 -mtune=G4 $(PER_ARCH_CFLAGS_ppc) PER_ARCH_CFLAGS_ppc64 = -mcpu=G5 -mpowerpc64 $(PER_ARCH_CFLAGS_ppc64) PREFIX = /usr/local TCL_CONFIGURE_ARGS = --enable-threads --enable-dtrace TCL_LIBRARY = $(LIBDIR)/tcl$(VERSION) TCL_PACKAGE_PATH = "$(LIBDIR)" TCL_DEFS = HAVE_TCL_CONFIG_H VERSION = 8.6 tcl8.6.5/macosx/README0000644000175000017500000002015312663660066013743 0ustar sergeisergeiTcl Mac OS X README ------------------- This is the README file for the Mac OS X/Darwin version of Tcl. 1. Where to go for support -------------------------- - The tcl-mac mailing list on sourceforge is the best place to ask questions specific to Tcl & Tk on Mac OS X: http://lists.sourceforge.net/lists/listinfo/tcl-mac (this page also has a link to searchable archives of the list, please check them before asking on the list, many questions have already been answered). - For general Tcl/Tk questions, the newsgroup comp.lang.tcl is your best bet: http://groups.google.com/group/comp.lang.tcl/ - The Tcl'ers Wiki also has many pages dealing with Tcl & Tk on Mac OS X, see http://wiki.tcl.tk/_/ref?N=3753 http://wiki.tcl.tk/_/ref?N=8361 - Please report bugs with Tcl on Mac OS X to the tracker: http://core.tcl.tk/tcl/reportlist 2. Using Tcl on Mac OS X ------------------------ - At a minimum, Mac OS X 10.3 is required to run Tcl. - Unless weak-linking is used, Tcl built on Mac OS X 10.x will not run on 10.y with y < x; on the other hand Tcl built on 10.y will always run on 10.x with y <= x (but without any of the fixes and optimizations that would be available in a binary built on 10.x). Weak-linking is available on OS X 10.2 or later, it additionally allows Tcl built on 10.x to run on any 10.y with x > y >= z (for a chosen z >= 2). - Tcl extensions can be installed in any of: $HOME/Library/Tcl /Library/Tcl /System/Library/Tcl $HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks (searched in that order). Given a potential package directory $pkg, Tcl on OSX checks for the file $pkg/Resources/Scripts/pkgIndex.tcl as well as the usual $pkg/pkgIndex.tcl. This allows building extensions as frameworks with all script files contained in the Resources/Scripts directory of the framework. - [load]able binary extensions can linked as either ordinary shared libraries (.dylib) or as MachO bundles (since 8.4.10/8.5a3); bundles have the advantage that they are [load]ed more efficiently from a tcl VFS (no temporary copy to the native filesystem required), and prior to Mac OS X 10.5, only bundles can be [unload]ed. - The 'deploy' target of macosx/GNUmakefile installs the html manpages into the standard documentation location in the Tcl framework: Tcl.framework/Resources/Documentation/Reference/Tcl No nroff manpages are installed by default by the GNUmakefile. - The Tcl framework can be installed in any of the system's standard framework directories: $HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks 3. Building Tcl on Mac OS X --------------------------- - At least Mac OS X 10.3 is required to build Tcl. Apple's Xcode Developer Tools need to be installed (only the most recent version matching your OS release is supported), the Xcode installer is available on Mac OS X install media or may be present in /Applications/Installers on Macs that came with OS X preinstalled. The most recent version can always be downloaded from the ADC website http://connect.apple.com (free ADC membership required). - Tcl is most easily built as a Mac OS X framework via GNUmakefile in tcl/macosx (see below for details), but can also be built with the standard unix configure and make buildsystem in tcl/unix as on any other unix platform (indeed, the GNUmakefile is just a wrapper around the unix buildsystem). The Mac OS X specific configure flags are --enable-framework and --disable-corefoundation (which disables CF and notably reverts to the standard select based notifier). - It is also possible to build with the Xcode IDE via the projects in tcl/macosx, take care to use the project matching your DevTools and OS version: Tcl.xcode: for Xcode 3.1 on 10.5 Tcl.xcodeproj: for Xcode 3.2 on 10.6 These have the following targets: Tcl: calls through to tcl/macosx/GNUMakefile. tcltest: static build of tcltest for debugging. tests: build tcltest target and run tcl testsuite. The following build configurations are available: Debug: debug build for the active architecture, with Fix & Continue enabled. Debug clang: use clang compiler. Debug llvm-gcc: use llvm-gcc compiler. Debug gcc40: use gcc 4.0 compiler. DebugNoFixAndContinue: disable Fix & Continue. DebugUnthreaded: disable threading. DebugNoCF: disable corefoundation. DebugNoCFUnthreaded: disable corefoundation an threading. DebugMemCompile: enable memory and bytecode debugging. DebugLeaks: define PURIFY. DebugGCov: enable generation of gcov data files. Debug64bit: configure with --enable-64bit (requires building on a 64bit capable processor). Release: release build for the active architecture. ReleaseUniversal: 32/64-bit universal build. ReleaseUniversal clang: use clang compiler. ReleaseUniversal llvm-gcc: use llvm-gcc compiler. ReleaseUniversal gcc40: use gcc 4.0 compiler. ReleaseUniversal10.5SDK: build against the 10.5 SDK (with 10.5 deployment target). Note that the non-SDK configurations have their deployment target set to 10.5 (Tcl.xcode) resp. 10.6 (Tcl.xcodeproj). The Xcode projects refer to the toplevel tcl source directory via the TCL_SRCROOT user build setting, by default this is set to the project-relative path '../../tcl', if your tcl source directory is named differently, e.g. '../../tcl8.6', you need to manually change the TCL_SRCROOT setting by editing your ${USER}.pbxuser file (located inside the Tcl.xcodeproj bundle directory) with a text editor. - To build universal binaries outside of the Xcode IDE, set CFLAGS as follows: export CFLAGS="-arch i386 -arch x86_64 -arch ppc" This requires Mac OS X 10.4 and Xcode 2.4 (or Xcode 2.2 if -arch x86_64 is omitted, but _not_ Xcode 2.1) and will work on any architecture (on PowerPC Tiger you need to add "-isysroot /Developer/SDKs/MacOSX10.4u.sdk"). Note that configure requires CFLAGS to contain a least one architecture that can be run on the build machine (i.e. ppc on G3/G4, ppc or ppc64 on G5, ppc or i386 on Core and ppc, i386 or x86_64 on Core2/Xeon). Universal builds of Tcl TEA extensions are also possible with CFLAGS set as above, they will be [load]able by universal as well as thin binaries of Tcl. - To enable weak-linking, set the MACOSX_DEPLOYMENT_TARGET environment variable to the minimal OS version the binaries should be able to run on, e.g: export MACOSX_DEPLOYMENT_TARGET=10.4 This requires at least gcc 3.1; with gcc 4 or later, set/add to CFLAGS instead: export CFLAGS="-mmacosx-version-min=10.4" Support for weak-linking was added with 8.4.14/8.5a5. Detailed Instructions for building with macosx/GNUmakefile ---------------------------------------------------------- - Unpack the Tcl source release archive. - The following instructions assume the Tcl source tree is named "tcl${ver}", (where ${ver} is a shell variable containing the Tcl version number e.g. '8.6'). Setup this shell variable as follows: ver="8.6" If you are building from CVS, omit this step (CVS source tree names usually do not contain a version number). - Setup environment variables as desired, e.g. for a universal build on 10.5: CFLAGS="-arch i386 -arch x86_64 -arch ppc -mmacosx-version-min=10.5" export CFLAGS - Change to the directory containing the Tcl source tree and build: make -C tcl${ver}/macosx - Install Tcl onto the root volume (admin password required): sudo make -C tcl${ver}/macosx install if you don't have an admin password, you can install into your home directory instead by passing an INSTALL_ROOT argument to make: make -C tcl${ver}/macosx install INSTALL_ROOT="${HOME}/" - The default GNUmakefile targets will build _both_ debug and optimized versions of the Tcl framework with the standard convention of naming the debug library Tcl.framework/Tcl_debug. This allows switching to the debug libraries at runtime by setting export DYLD_IMAGE_SUFFIX=_debug (c.f. man dyld for more details) If you only want to build and install the debug or optimized build, use the 'develop' or 'deploy' target variants of the GNUmakefile, respectively. For example, to build and install only the optimized versions: make -C tcl${ver}/macosx deploy sudo make -C tcl${ver}/macosx install-deploy tcl8.6.5/libtommath/0000755000175000017500000000000012665173607013732 5ustar sergeisergeitcl8.6.5/libtommath/bn_mp_toom_sqr.c0000644000175000017500000001224312663653207017113 0ustar sergeisergei#include #ifdef BN_MP_TOOM_SQR_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* squaring using Toom-Cook 3-way algorithm */ int mp_toom_sqr(mp_int *a, mp_int *b) { mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2; int res, B; /* init temps */ if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) { return res; } /* B */ B = a->used / 3; /* a = a2 * B**2 + a1 * B + a0 */ if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { goto ERR; } if ((res = mp_copy(a, &a1)) != MP_OKAY) { goto ERR; } mp_rshd(&a1, B); mp_mod_2d(&a1, DIGIT_BIT * B, &a1); if ((res = mp_copy(a, &a2)) != MP_OKAY) { goto ERR; } mp_rshd(&a2, B*2); /* w0 = a0*a0 */ if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) { goto ERR; } /* w4 = a2 * a2 */ if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) { goto ERR; } /* w1 = (a2 + 2(a1 + 2a0))**2 */ if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) { goto ERR; } /* w3 = (a0 + 2(a1 + 2a2))**2 */ if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) { goto ERR; } /* w2 = (a2 + a1 + a0)**2 */ if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) { goto ERR; } /* now solve the matrix 0 0 0 0 1 1 2 4 8 16 1 1 1 1 1 16 8 4 2 1 1 0 0 0 0 using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication. */ /* r1 - r4 */ if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { goto ERR; } /* r3 - r0 */ if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { goto ERR; } /* r1/2 */ if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { goto ERR; } /* r3/2 */ if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { goto ERR; } /* r2 - r0 - r4 */ if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { goto ERR; } if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { goto ERR; } /* r1 - r2 */ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { goto ERR; } /* r3 - r2 */ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { goto ERR; } /* r1 - 8r0 */ if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { goto ERR; } /* r3 - 8r4 */ if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { goto ERR; } /* 3r2 - r1 - r3 */ if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { goto ERR; } if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { goto ERR; } if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { goto ERR; } /* r1 - r2 */ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { goto ERR; } /* r3 - r2 */ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { goto ERR; } /* r1/3 */ if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { goto ERR; } /* r3/3 */ if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { goto ERR; } /* at this point shift W[n] by B*n */ if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { goto ERR; } if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { goto ERR; } if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { goto ERR; } if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) { goto ERR; } ERR: mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL); return res; } #endif tcl8.6.5/libtommath/bn_mp_clear.c0000644000175000017500000000172112663653207016335 0ustar sergeisergei#include #ifdef BN_MP_CLEAR_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* clear one (frees) */ void mp_clear (mp_int * a) { int i; /* only do anything if a hasn't been freed previously */ if (a->dp != NULL) { /* first zero the digits */ for (i = 0; i < a->used; i++) { a->dp[i] = 0; } /* free ram */ XFREE(a->dp); /* reset members to make debugging easier */ a->dp = NULL; a->alloc = a->used = 0; a->sign = MP_ZPOS; } } #endif tcl8.6.5/libtommath/bn_mp_init_size.c0000644000175000017500000000206112663653207017242 0ustar sergeisergei#include #ifdef BN_MP_INIT_SIZE_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* init an mp_init for a given size */ int mp_init_size (mp_int * a, int size) { int x; /* pad size so there are always extra digits */ size += (MP_PREC * 2) - (size % MP_PREC); /* alloc mem */ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size); if (a->dp == NULL) { return MP_MEM; } /* set the members */ a->used = 0; a->alloc = size; a->sign = MP_ZPOS; /* zero the digits */ for (x = 0; x < size; x++) { a->dp[x] = 0; } return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_div_2d.c0000644000175000017500000000413012663653207016413 0ustar sergeisergei#include #ifdef BN_MP_DIV_2D_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* shift right by a certain bit count (store quotient in c, optional remainder in d) */ int mp_div_2d (const mp_int * a, int b, mp_int * c, mp_int * d) { mp_digit D, r, rr; int x, res; mp_int t; /* if the shift count is <= 0 then we do no work */ if (b <= 0) { res = mp_copy (a, c); if (d != NULL) { mp_zero (d); } return res; } if ((res = mp_init (&t)) != MP_OKAY) { return res; } /* get the remainder */ if (d != NULL) { if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { mp_clear (&t); return res; } } /* copy */ if ((res = mp_copy (a, c)) != MP_OKAY) { mp_clear (&t); return res; } /* shift by as many digits in the bit count */ if (b >= (int)DIGIT_BIT) { mp_rshd (c, b / DIGIT_BIT); } /* shift any bit count < DIGIT_BIT */ D = (mp_digit) (b % DIGIT_BIT); if (D != 0) { register mp_digit *tmpc, mask, shift; /* mask */ mask = (((mp_digit)1) << D) - 1; /* shift for lsb */ shift = DIGIT_BIT - D; /* alias */ tmpc = c->dp + (c->used - 1); /* carry */ r = 0; for (x = c->used - 1; x >= 0; x--) { /* get the lower bits of this word in a temp */ rr = *tmpc & mask; /* shift the current word and mix in the carry bits from the previous word */ *tmpc = (*tmpc >> D) | (r << shift); --tmpc; /* set the carry to the carry bits of the current word found above */ r = rr; } } mp_clamp (c); if (d != NULL) { mp_exch (&t, d); } mp_clear (&t); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_shrink.c0000644000175000017500000000161012663653207016542 0ustar sergeisergei#include #ifdef BN_MP_SHRINK_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* shrink a bignum */ int mp_shrink (mp_int * a) { mp_digit *tmp; int used = 1; if(a->used > 0) used = a->used; if (a->alloc != used) { if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * used)) == NULL) { return MP_MEM; } a->dp = tmp; a->alloc = used; } return MP_OKAY; } #endif tcl8.6.5/libtommath/tommath_superclass.h0000644000175000017500000000421412663653210020010 0ustar sergeisergei/* super class file for PK algos */ /* default ... include all MPI */ #define LTM_ALL /* RSA only (does not support DH/DSA/ECC) */ /* #define SC_RSA_1 */ /* For reference.... On an Athlon64 optimizing for speed... LTM's mpi.o with all functions [striped] is 142KiB in size. */ /* Works for RSA only, mpi.o is 68KiB */ #ifdef SC_RSA_1 #define BN_MP_SHRINK_C #define BN_MP_LCM_C #define BN_MP_PRIME_RANDOM_EX_C #define BN_MP_INVMOD_C #define BN_MP_GCD_C #define BN_MP_MOD_C #define BN_MP_MULMOD_C #define BN_MP_ADDMOD_C #define BN_MP_EXPTMOD_C #define BN_MP_SET_INT_C #define BN_MP_INIT_MULTI_C #define BN_MP_CLEAR_MULTI_C #define BN_MP_UNSIGNED_BIN_SIZE_C #define BN_MP_TO_UNSIGNED_BIN_C #define BN_MP_MOD_D_C #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C #define BN_REVERSE_C #define BN_PRIME_TAB_C /* other modifiers */ #define BN_MP_DIV_SMALL /* Slower division, not critical */ /* here we are on the last pass so we turn things off. The functions classes are still there * but we remove them specifically from the build. This also invokes tweaks in functions * like removing support for even moduli, etc... */ #ifdef LTM_LAST #undef BN_MP_TOOM_MUL_C #undef BN_MP_TOOM_SQR_C #undef BN_MP_KARATSUBA_MUL_C #undef BN_MP_KARATSUBA_SQR_C #undef BN_MP_REDUCE_C #undef BN_MP_REDUCE_SETUP_C #undef BN_MP_DR_IS_MODULUS_C #undef BN_MP_DR_SETUP_C #undef BN_MP_DR_REDUCE_C #undef BN_MP_REDUCE_IS_2K_C #undef BN_MP_REDUCE_2K_SETUP_C #undef BN_MP_REDUCE_2K_C #undef BN_S_MP_EXPTMOD_C #undef BN_MP_DIV_3_C #undef BN_S_MP_MUL_HIGH_DIGS_C #undef BN_FAST_S_MP_MUL_HIGH_DIGS_C #undef BN_FAST_MP_INVMOD_C /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without * trouble. */ #undef BN_S_MP_MUL_DIGS_C #undef BN_S_MP_SQR_C #undef BN_MP_MONTGOMERY_REDUCE_C #endif #endif tcl8.6.5/libtommath/bn_mp_karatsuba_mul.c0000644000175000017500000001123512663653207020102 0ustar sergeisergei#include #ifdef BN_MP_KARATSUBA_MUL_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* c = |a| * |b| using Karatsuba Multiplication using * three half size multiplications * * Let B represent the radix [e.g. 2**DIGIT_BIT] and * let n represent half of the number of digits in * the min(a,b) * * a = a1 * B**n + a0 * b = b1 * B**n + b0 * * Then, a * b => a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0 * * Note that a1b1 and a0b0 are used twice and only need to be * computed once. So in total three half size (half # of * digit) multiplications are performed, a0b0, a1b1 and * (a1+b1)(a0+b0) * * Note that a multiplication of half the digits requires * 1/4th the number of single precision multiplications so in * total after one call 25% of the single precision multiplications * are saved. Note also that the call to mp_mul can end up back * in this function if the a0, a1, b0, or b1 are above the threshold. * This is known as divide-and-conquer and leads to the famous * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than * the standard O(N**2) that the baseline/comba methods use. * Generally though the overhead of this method doesn't pay off * until a certain size (N ~ 80) is reached. */ int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c) { mp_int x0, x1, y0, y1, t1, x0y0, x1y1; int B, err; /* default the return code to an error */ err = MP_MEM; /* min # of digits */ B = MIN (a->used, b->used); /* now divide in two */ B = B >> 1; /* init copy all the temps */ if (mp_init_size (&x0, B) != MP_OKAY) goto ERR; if (mp_init_size (&x1, a->used - B) != MP_OKAY) goto X0; if (mp_init_size (&y0, B) != MP_OKAY) goto X1; if (mp_init_size (&y1, b->used - B) != MP_OKAY) goto Y0; /* init temps */ if (mp_init_size (&t1, B * 2) != MP_OKAY) goto Y1; if (mp_init_size (&x0y0, B * 2) != MP_OKAY) goto T1; if (mp_init_size (&x1y1, B * 2) != MP_OKAY) goto X0Y0; /* now shift the digits */ x0.used = y0.used = B; x1.used = a->used - B; y1.used = b->used - B; { register int x; register mp_digit *tmpa, *tmpb, *tmpx, *tmpy; /* we copy the digits directly instead of using higher level functions * since we also need to shift the digits */ tmpa = a->dp; tmpb = b->dp; tmpx = x0.dp; tmpy = y0.dp; for (x = 0; x < B; x++) { *tmpx++ = *tmpa++; *tmpy++ = *tmpb++; } tmpx = x1.dp; for (x = B; x < a->used; x++) { *tmpx++ = *tmpa++; } tmpy = y1.dp; for (x = B; x < b->used; x++) { *tmpy++ = *tmpb++; } } /* only need to clamp the lower words since by definition the * upper words x1/y1 must have a known number of digits */ mp_clamp (&x0); mp_clamp (&y0); /* now calc the products x0y0 and x1y1 */ /* after this x0 is no longer required, free temp [x0==t2]! */ if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY) goto X1Y1; /* x0y0 = x0*y0 */ if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY) goto X1Y1; /* x1y1 = x1*y1 */ /* now calc x1+x0 and y1+y0 */ if (s_mp_add (&x1, &x0, &t1) != MP_OKAY) goto X1Y1; /* t1 = x1 - x0 */ if (s_mp_add (&y1, &y0, &x0) != MP_OKAY) goto X1Y1; /* t2 = y1 - y0 */ if (mp_mul (&t1, &x0, &t1) != MP_OKAY) goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */ /* add x0y0 */ if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY) goto X1Y1; /* t2 = x0y0 + x1y1 */ if (s_mp_sub (&t1, &x0, &t1) != MP_OKAY) goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */ /* shift by B */ if (mp_lshd (&t1, B) != MP_OKAY) goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))< #ifdef BN_S_MP_SQR_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ int s_mp_sqr (mp_int * a, mp_int * b) { mp_int t; int res, ix, iy, pa; mp_word r; mp_digit u, tmpx, *tmpt; pa = a->used; if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { return res; } /* default used is maximum possible size */ t.used = 2*pa + 1; for (ix = 0; ix < pa; ix++) { /* first calculate the digit at 2*ix */ /* calculate double precision result */ r = ((mp_word) t.dp[2*ix]) + ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); /* store lower part in result */ t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK)); /* get the carry */ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); /* left hand side of A[ix] * A[iy] */ tmpx = a->dp[ix]; /* alias for where to store the results */ tmpt = t.dp + (2*ix + 1); for (iy = ix + 1; iy < pa; iy++) { /* first calculate the product */ r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); /* now calculate the double precision result, note we use * addition instead of *2 since it's easier to optimize */ r = ((mp_word) *tmpt) + r + r + ((mp_word) u); /* store lower part */ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* get carry */ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); } /* propagate upwards */ while (u != ((mp_digit) 0)) { r = ((mp_word) *tmpt) + ((mp_word) u); *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); } } mp_clamp (&t); mp_exch (&t, b); mp_clear (&t); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_cmp.c0000644000175000017500000000173012663653207016026 0ustar sergeisergei#include #ifdef BN_MP_CMP_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* compare two ints (signed)*/ int mp_cmp (const mp_int * a, const mp_int * b) { /* compare based on sign */ if (a->sign != b->sign) { if (a->sign == MP_NEG) { return MP_LT; } else { return MP_GT; } } /* compare digits */ if (a->sign == MP_NEG) { /* if negative compare opposite direction */ return mp_cmp_mag(b, a); } else { return mp_cmp_mag(a, b); } } #endif tcl8.6.5/libtommath/bn_mp_exch.c0000644000175000017500000000137612663653207016204 0ustar sergeisergei#include #ifdef BN_MP_EXCH_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* swap the elements of two integers, for cases where you can't simply swap the * mp_int pointers around */ void mp_exch (mp_int * a, mp_int * b) { mp_int t; t = *a; *a = *b; *b = t; } #endif tcl8.6.5/libtommath/bn_mp_neg.c0000644000175000017500000000156012663653207016021 0ustar sergeisergei#include #ifdef BN_MP_NEG_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* b = -a */ int mp_neg (const mp_int * a, mp_int * b) { int res; if (a != b) { if ((res = mp_copy (a, b)) != MP_OKAY) { return res; } } if (mp_iszero(b) != MP_YES) { b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; } else { b->sign = MP_ZPOS; } return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_init.c0000644000175000017500000000204212663653207016207 0ustar sergeisergei#include #ifdef BN_MP_INIT_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* init a new mp_int */ int mp_init (mp_int * a) { int i; /* allocate memory required and clear it */ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC); if (a->dp == NULL) { return MP_MEM; } /* set the digits to zero */ for (i = 0; i < MP_PREC; i++) { a->dp[i] = 0; } /* set the used to zero, allocated digits to the default precision * and sign to positive */ a->used = 0; a->alloc = MP_PREC; a->sign = MP_ZPOS; return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_mul.c0000644000175000017500000000326412663653207016050 0ustar sergeisergei#include #ifdef BN_MP_MUL_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* high level multiplication (handles sign) */ int mp_mul (mp_int * a, mp_int * b, mp_int * c) { int res, neg; neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; /* use Toom-Cook? */ #ifdef BN_MP_TOOM_MUL_C if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) { res = mp_toom_mul(a, b, c); } else #endif #ifdef BN_MP_KARATSUBA_MUL_C /* use Karatsuba? */ if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { res = mp_karatsuba_mul (a, b, c); } else #endif { /* can we use the fast multiplier? * * The fast multiplier can be used if the output will * have less than MP_WARRAY digits and the number of * digits won't affect carry propagation */ int digs = a->used + b->used + 1; #ifdef BN_FAST_S_MP_MUL_DIGS_C if ((digs < MP_WARRAY) && MIN(a->used, b->used) <= (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { res = fast_s_mp_mul_digs (a, b, c, digs); } else #endif #ifdef BN_S_MP_MUL_DIGS_C res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */ #else res = MP_VAL; #endif } c->sign = (c->used > 0) ? neg : MP_ZPOS; return res; } #endif tcl8.6.5/libtommath/bn_mp_sub_d.c0000644000175000017500000000376612663653207016356 0ustar sergeisergei#include #ifdef BN_MP_SUB_D_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* single digit subtraction */ int mp_sub_d (mp_int * a, mp_digit b, mp_int * c) { mp_digit *tmpa, *tmpc, mu; int res, ix, oldused; /* grow c as required */ if (c->alloc < a->used + 1) { if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { return res; } } /* if a is negative just do an unsigned * addition [with fudged signs] */ if (a->sign == MP_NEG) { a->sign = MP_ZPOS; res = mp_add_d(a, b, c); a->sign = c->sign = MP_NEG; /* clamp */ mp_clamp(c); return res; } /* setup regs */ oldused = c->used; tmpa = a->dp; tmpc = c->dp; /* if a <= b simply fix the single digit */ if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) { if (a->used == 1) { *tmpc++ = b - *tmpa; } else { *tmpc++ = b; } ix = 1; /* negative/1digit */ c->sign = MP_NEG; c->used = 1; } else { /* positive/size */ c->sign = MP_ZPOS; c->used = a->used; /* subtract first digit */ *tmpc = *tmpa++ - b; mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); *tmpc++ &= MP_MASK; /* handle rest of the digits */ for (ix = 1; ix < a->used; ix++) { *tmpc = *tmpa++ - mu; mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); *tmpc++ &= MP_MASK; } } /* zero excess digits */ while (ix++ < oldused) { *tmpc++ = 0; } mp_clamp(c); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_sqr.c0000644000175000017500000000241512663653207016055 0ustar sergeisergei#include #ifdef BN_MP_SQR_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* computes b = a*a */ int mp_sqr (mp_int * a, mp_int * b) { int res; #ifdef BN_MP_TOOM_SQR_C /* use Toom-Cook? */ if (a->used >= TOOM_SQR_CUTOFF) { res = mp_toom_sqr(a, b); /* Karatsuba? */ } else #endif #ifdef BN_MP_KARATSUBA_SQR_C if (a->used >= KARATSUBA_SQR_CUTOFF) { res = mp_karatsuba_sqr (a, b); } else #endif { #ifdef BN_FAST_S_MP_SQR_C /* can we use the fast comba multiplier? */ if ((a->used * 2 + 1) < MP_WARRAY && a->used < (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { res = fast_s_mp_sqr (a, b); } else #endif #ifdef BN_S_MP_SQR_C res = s_mp_sqr (a, b); #else res = MP_VAL; #endif } b->sign = MP_ZPOS; return res; } #endif tcl8.6.5/libtommath/bn_s_mp_mul_digs.c0000644000175000017500000000453712663653210017376 0ustar sergeisergei#include #ifdef BN_S_MP_MUL_DIGS_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* multiplies |a| * |b| and only computes upto digs digits of result * HAC pp. 595, Algorithm 14.12 Modified so you can control how * many digits of output are created. */ int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { mp_int t; int res, pa, pb, ix, iy; mp_digit u; mp_word r; mp_digit tmpx, *tmpt, *tmpy; /* can we use the fast multiplier? */ if (((digs) < MP_WARRAY) && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { return fast_s_mp_mul_digs (a, b, c, digs); } if ((res = mp_init_size (&t, digs)) != MP_OKAY) { return res; } t.used = digs; /* compute the digits of the product directly */ pa = a->used; for (ix = 0; ix < pa; ix++) { /* set the carry to zero */ u = 0; /* limit ourselves to making digs digits of output */ pb = MIN (b->used, digs - ix); /* setup some aliases */ /* copy of the digit from a used within the nested loop */ tmpx = a->dp[ix]; /* an alias for the destination shifted ix places */ tmpt = t.dp + ix; /* an alias for the digits of b */ tmpy = b->dp; /* compute the columns of the output and propagate the carry */ for (iy = 0; iy < pb; iy++) { /* compute the column as a mp_word */ r = ((mp_word)*tmpt) + ((mp_word)tmpx) * ((mp_word)*tmpy++) + ((mp_word) u); /* the new column is the lower part of the result */ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* get the carry word from the result */ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); } /* set carry if it is placed below digs */ if (ix + iy < digs) { *tmpt = u; } } mp_clamp (&t); mp_exch (&t, c); mp_clear (&t); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_init_set_int.c0000644000175000017500000000137012663653207017737 0ustar sergeisergei#include #ifdef BN_MP_INIT_SET_INT_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* initialize and set a digit */ int mp_init_set_int (mp_int * a, unsigned long b) { int err; if ((err = mp_init(a)) != MP_OKAY) { return err; } return mp_set_int(a, b); } #endif tcl8.6.5/libtommath/bn_mp_add.c0000644000175000017500000000250412663653207015777 0ustar sergeisergei#include #ifdef BN_MP_ADD_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* high level addition (handles signs) */ int mp_add (mp_int * a, mp_int * b, mp_int * c) { int sa, sb, res; /* get sign of both inputs */ sa = a->sign; sb = b->sign; /* handle two cases, not four */ if (sa == sb) { /* both positive or both negative */ /* add their magnitudes, copy the sign */ c->sign = sa; res = s_mp_add (a, b, c); } else { /* one positive, the other negative */ /* subtract the one with the greater magnitude from */ /* the one of the lesser magnitude. The result gets */ /* the sign of the one with the greater magnitude. */ if (mp_cmp_mag (a, b) == MP_LT) { c->sign = sb; res = s_mp_sub (b, a, c); } else { c->sign = sa; res = s_mp_sub (a, b, c); } } return res; } #endif tcl8.6.5/libtommath/bn_mp_copy.c0000644000175000017500000000245412663653207016225 0ustar sergeisergei#include #ifdef BN_MP_COPY_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* copy, b = a */ int mp_copy (const mp_int * a, mp_int * b) { int res, n; /* if dst == src do nothing */ if (a == b) { return MP_OKAY; } /* grow dest */ if (b->alloc < a->used) { if ((res = mp_grow (b, a->used)) != MP_OKAY) { return res; } } /* zero b and copy the parameters over */ { register mp_digit *tmpa, *tmpb; /* pointer aliases */ /* source */ tmpa = a->dp; /* destination */ tmpb = b->dp; /* copy all the digits */ for (n = 0; n < a->used; n++) { *tmpb++ = *tmpa++; } /* clear high digits */ for (; n < b->used; n++) { *tmpb++ = 0; } } /* copy used count and sign */ b->used = a->used; b->sign = a->sign; return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_div_2.c0000644000175000017500000000270612663653207016256 0ustar sergeisergei#include #ifdef BN_MP_DIV_2_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* b = a/2 */ int mp_div_2(mp_int * a, mp_int * b) { int x, res, oldused; /* copy */ if (b->alloc < a->used) { if ((res = mp_grow (b, a->used)) != MP_OKAY) { return res; } } oldused = b->used; b->used = a->used; { register mp_digit r, rr, *tmpa, *tmpb; /* source alias */ tmpa = a->dp + b->used - 1; /* dest alias */ tmpb = b->dp + b->used - 1; /* carry */ r = 0; for (x = b->used - 1; x >= 0; x--) { /* get the carry for the next iteration */ rr = *tmpa & 1; /* shift the current digit, add in carry and store */ *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); /* forward carry to next iteration */ r = rr; } /* zero excess digits */ tmpb = b->dp + b->used; for (x = b->used; x < oldused; x++) { *tmpb++ = 0; } } b->sign = a->sign; mp_clamp (b); return MP_OKAY; } #endif tcl8.6.5/libtommath/tommath_class.h0000644000175000017500000005065612663653210016744 0ustar sergeisergei#if !(defined(LTM1) && defined(LTM2) && defined(LTM3)) #if defined(LTM2) #define LTM3 #endif #if defined(LTM1) #define LTM2 #endif #define LTM1 #if defined(LTM_ALL) #define BN_ERROR_C #define BN_FAST_MP_INVMOD_C #define BN_FAST_MP_MONTGOMERY_REDUCE_C #define BN_FAST_S_MP_MUL_DIGS_C #define BN_FAST_S_MP_MUL_HIGH_DIGS_C #define BN_FAST_S_MP_SQR_C #define BN_MP_2EXPT_C #define BN_MP_ABS_C #define BN_MP_ADD_C #define BN_MP_ADD_D_C #define BN_MP_ADDMOD_C #define BN_MP_AND_C #define BN_MP_CLAMP_C #define BN_MP_CLEAR_C #define BN_MP_CLEAR_MULTI_C #define BN_MP_CMP_C #define BN_MP_CMP_D_C #define BN_MP_CMP_MAG_C #define BN_MP_CNT_LSB_C #define BN_MP_COPY_C #define BN_MP_COUNT_BITS_C #define BN_MP_DIV_C #define BN_MP_DIV_2_C #define BN_MP_DIV_2D_C #define BN_MP_DIV_3_C #define BN_MP_DIV_D_C #define BN_MP_DR_IS_MODULUS_C #define BN_MP_DR_REDUCE_C #define BN_MP_DR_SETUP_C #define BN_MP_EXCH_C #define BN_MP_EXPT_D_C #define BN_MP_EXPTMOD_C #define BN_MP_EXPTMOD_FAST_C #define BN_MP_EXTEUCLID_C #define BN_MP_FREAD_C #define BN_MP_FWRITE_C #define BN_MP_GCD_C #define BN_MP_GET_INT_C #define BN_MP_GROW_C #define BN_MP_INIT_C #define BN_MP_INIT_COPY_C #define BN_MP_INIT_MULTI_C #define BN_MP_INIT_SET_C #define BN_MP_INIT_SET_INT_C #define BN_MP_INIT_SIZE_C #define BN_MP_INVMOD_C #define BN_MP_INVMOD_SLOW_C #define BN_MP_IS_SQUARE_C #define BN_MP_JACOBI_C #define BN_MP_KARATSUBA_MUL_C #define BN_MP_KARATSUBA_SQR_C #define BN_MP_LCM_C #define BN_MP_LSHD_C #define BN_MP_MOD_C #define BN_MP_MOD_2D_C #define BN_MP_MOD_D_C #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C #define BN_MP_MONTGOMERY_REDUCE_C #define BN_MP_MONTGOMERY_SETUP_C #define BN_MP_MUL_C #define BN_MP_MUL_2_C #define BN_MP_MUL_2D_C #define BN_MP_MUL_D_C #define BN_MP_MULMOD_C #define BN_MP_N_ROOT_C #define BN_MP_NEG_C #define BN_MP_OR_C #define BN_MP_PRIME_FERMAT_C #define BN_MP_PRIME_IS_DIVISIBLE_C #define BN_MP_PRIME_IS_PRIME_C #define BN_MP_PRIME_MILLER_RABIN_C #define BN_MP_PRIME_NEXT_PRIME_C #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C #define BN_MP_PRIME_RANDOM_EX_C #define BN_MP_RADIX_SIZE_C #define BN_MP_RADIX_SMAP_C #define BN_MP_RAND_C #define BN_MP_READ_RADIX_C #define BN_MP_READ_SIGNED_BIN_C #define BN_MP_READ_UNSIGNED_BIN_C #define BN_MP_REDUCE_C #define BN_MP_REDUCE_2K_C #define BN_MP_REDUCE_2K_L_C #define BN_MP_REDUCE_2K_SETUP_C #define BN_MP_REDUCE_2K_SETUP_L_C #define BN_MP_REDUCE_IS_2K_C #define BN_MP_REDUCE_IS_2K_L_C #define BN_MP_REDUCE_SETUP_C #define BN_MP_RSHD_C #define BN_MP_SET_C #define BN_MP_SET_INT_C #define BN_MP_SHRINK_C #define BN_MP_SIGNED_BIN_SIZE_C #define BN_MP_SQR_C #define BN_MP_SQRMOD_C #define BN_MP_SQRT_C #define BN_MP_SUB_C #define BN_MP_SUB_D_C #define BN_MP_SUBMOD_C #define BN_MP_TO_SIGNED_BIN_C #define BN_MP_TO_SIGNED_BIN_N_C #define BN_MP_TO_UNSIGNED_BIN_C #define BN_MP_TO_UNSIGNED_BIN_N_C #define BN_MP_TOOM_MUL_C #define BN_MP_TOOM_SQR_C #define BN_MP_TORADIX_C #define BN_MP_TORADIX_N_C #define BN_MP_UNSIGNED_BIN_SIZE_C #define BN_MP_XOR_C #define BN_MP_ZERO_C #define BN_PRIME_TAB_C #define BN_REVERSE_C #define BN_S_MP_ADD_C #define BN_S_MP_EXPTMOD_C #define BN_S_MP_MUL_DIGS_C #define BN_S_MP_MUL_HIGH_DIGS_C #define BN_S_MP_SQR_C #define BN_S_MP_SUB_C #define BNCORE_C #endif #if defined(BN_ERROR_C) #define BN_MP_ERROR_TO_STRING_C #endif #if defined(BN_FAST_MP_INVMOD_C) #define BN_MP_ISEVEN_C #define BN_MP_INIT_MULTI_C #define BN_MP_COPY_C #define BN_MP_MOD_C #define BN_MP_SET_C #define BN_MP_DIV_2_C #define BN_MP_ISODD_C #define BN_MP_SUB_C #define BN_MP_CMP_C #define BN_MP_ISZERO_C #define BN_MP_CMP_D_C #define BN_MP_ADD_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_MULTI_C #endif #if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C) #define BN_MP_GROW_C #define BN_MP_RSHD_C #define BN_MP_CLAMP_C #define BN_MP_CMP_MAG_C #define BN_S_MP_SUB_C #endif #if defined(BN_FAST_S_MP_MUL_DIGS_C) #define BN_MP_GROW_C #define BN_MP_CLAMP_C #endif #if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) #define BN_MP_GROW_C #define BN_MP_CLAMP_C #endif #if defined(BN_FAST_S_MP_SQR_C) #define BN_MP_GROW_C #define BN_MP_CLAMP_C #endif #if defined(BN_MP_2EXPT_C) #define BN_MP_ZERO_C #define BN_MP_GROW_C #endif #if defined(BN_MP_ABS_C) #define BN_MP_COPY_C #endif #if defined(BN_MP_ADD_C) #define BN_S_MP_ADD_C #define BN_MP_CMP_MAG_C #define BN_S_MP_SUB_C #endif #if defined(BN_MP_ADD_D_C) #define BN_MP_GROW_C #define BN_MP_SUB_D_C #define BN_MP_CLAMP_C #endif #if defined(BN_MP_ADDMOD_C) #define BN_MP_INIT_C #define BN_MP_ADD_C #define BN_MP_CLEAR_C #define BN_MP_MOD_C #endif #if defined(BN_MP_AND_C) #define BN_MP_INIT_COPY_C #define BN_MP_CLAMP_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_CLAMP_C) #endif #if defined(BN_MP_CLEAR_C) #endif #if defined(BN_MP_CLEAR_MULTI_C) #define BN_MP_CLEAR_C #endif #if defined(BN_MP_CMP_C) #define BN_MP_CMP_MAG_C #endif #if defined(BN_MP_CMP_D_C) #endif #if defined(BN_MP_CMP_MAG_C) #endif #if defined(BN_MP_CNT_LSB_C) #define BN_MP_ISZERO_C #endif #if defined(BN_MP_COPY_C) #define BN_MP_GROW_C #endif #if defined(BN_MP_COUNT_BITS_C) #endif #if defined(BN_MP_DIV_C) #define BN_MP_ISZERO_C #define BN_MP_CMP_MAG_C #define BN_MP_COPY_C #define BN_MP_ZERO_C #define BN_MP_INIT_MULTI_C #define BN_MP_SET_C #define BN_MP_COUNT_BITS_C #define BN_MP_ABS_C #define BN_MP_MUL_2D_C #define BN_MP_CMP_C #define BN_MP_SUB_C #define BN_MP_ADD_C #define BN_MP_DIV_2D_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_MULTI_C #define BN_MP_INIT_SIZE_C #define BN_MP_INIT_C #define BN_MP_INIT_COPY_C #define BN_MP_LSHD_C #define BN_MP_RSHD_C #define BN_MP_MUL_D_C #define BN_MP_CLAMP_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_DIV_2_C) #define BN_MP_GROW_C #define BN_MP_CLAMP_C #endif #if defined(BN_MP_DIV_2D_C) #define BN_MP_COPY_C #define BN_MP_ZERO_C #define BN_MP_INIT_C #define BN_MP_MOD_2D_C #define BN_MP_CLEAR_C #define BN_MP_RSHD_C #define BN_MP_CLAMP_C #define BN_MP_EXCH_C #endif #if defined(BN_MP_DIV_3_C) #define BN_MP_INIT_SIZE_C #define BN_MP_CLAMP_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_DIV_D_C) #define BN_MP_ISZERO_C #define BN_MP_COPY_C #define BN_MP_DIV_2D_C #define BN_MP_DIV_3_C #define BN_MP_INIT_SIZE_C #define BN_MP_CLAMP_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_DR_IS_MODULUS_C) #endif #if defined(BN_MP_DR_REDUCE_C) #define BN_MP_GROW_C #define BN_MP_CLAMP_C #define BN_MP_CMP_MAG_C #define BN_S_MP_SUB_C #endif #if defined(BN_MP_DR_SETUP_C) #endif #if defined(BN_MP_EXCH_C) #endif #if defined(BN_MP_EXPT_D_C) #define BN_MP_INIT_COPY_C #define BN_MP_SET_C #define BN_MP_SQR_C #define BN_MP_CLEAR_C #define BN_MP_MUL_C #endif #if defined(BN_MP_EXPTMOD_C) #define BN_MP_INIT_C #define BN_MP_INVMOD_C #define BN_MP_CLEAR_C #define BN_MP_ABS_C #define BN_MP_CLEAR_MULTI_C #define BN_MP_REDUCE_IS_2K_L_C #define BN_S_MP_EXPTMOD_C #define BN_MP_DR_IS_MODULUS_C #define BN_MP_REDUCE_IS_2K_C #define BN_MP_ISODD_C #define BN_MP_EXPTMOD_FAST_C #endif #if defined(BN_MP_EXPTMOD_FAST_C) #define BN_MP_COUNT_BITS_C #define BN_MP_INIT_C #define BN_MP_CLEAR_C #define BN_MP_MONTGOMERY_SETUP_C #define BN_FAST_MP_MONTGOMERY_REDUCE_C #define BN_MP_MONTGOMERY_REDUCE_C #define BN_MP_DR_SETUP_C #define BN_MP_DR_REDUCE_C #define BN_MP_REDUCE_2K_SETUP_C #define BN_MP_REDUCE_2K_C #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C #define BN_MP_MULMOD_C #define BN_MP_SET_C #define BN_MP_MOD_C #define BN_MP_COPY_C #define BN_MP_SQR_C #define BN_MP_MUL_C #define BN_MP_EXCH_C #endif #if defined(BN_MP_EXTEUCLID_C) #define BN_MP_INIT_MULTI_C #define BN_MP_SET_C #define BN_MP_COPY_C #define BN_MP_ISZERO_C #define BN_MP_DIV_C #define BN_MP_MUL_C #define BN_MP_SUB_C #define BN_MP_NEG_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_MULTI_C #endif #if defined(BN_MP_FREAD_C) #define BN_MP_ZERO_C #define BN_MP_S_RMAP_C #define BN_MP_MUL_D_C #define BN_MP_ADD_D_C #define BN_MP_CMP_D_C #endif #if defined(BN_MP_FWRITE_C) #define BN_MP_RADIX_SIZE_C #define BN_MP_TORADIX_C #endif #if defined(BN_MP_GCD_C) #define BN_MP_ISZERO_C #define BN_MP_ABS_C #define BN_MP_ZERO_C #define BN_MP_INIT_COPY_C #define BN_MP_CNT_LSB_C #define BN_MP_DIV_2D_C #define BN_MP_CMP_MAG_C #define BN_MP_EXCH_C #define BN_S_MP_SUB_C #define BN_MP_MUL_2D_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_GET_INT_C) #endif #if defined(BN_MP_GROW_C) #endif #if defined(BN_MP_INIT_C) #endif #if defined(BN_MP_INIT_COPY_C) #define BN_MP_COPY_C #endif #if defined(BN_MP_INIT_MULTI_C) #define BN_MP_ERR_C #define BN_MP_INIT_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_INIT_SET_C) #define BN_MP_INIT_C #define BN_MP_SET_C #endif #if defined(BN_MP_INIT_SET_INT_C) #define BN_MP_INIT_C #define BN_MP_SET_INT_C #endif #if defined(BN_MP_INIT_SIZE_C) #define BN_MP_INIT_C #endif #if defined(BN_MP_INVMOD_C) #define BN_MP_ISZERO_C #define BN_MP_ISODD_C #define BN_FAST_MP_INVMOD_C #define BN_MP_INVMOD_SLOW_C #endif #if defined(BN_MP_INVMOD_SLOW_C) #define BN_MP_ISZERO_C #define BN_MP_INIT_MULTI_C #define BN_MP_MOD_C #define BN_MP_COPY_C #define BN_MP_ISEVEN_C #define BN_MP_SET_C #define BN_MP_DIV_2_C #define BN_MP_ISODD_C #define BN_MP_ADD_C #define BN_MP_SUB_C #define BN_MP_CMP_C #define BN_MP_CMP_D_C #define BN_MP_CMP_MAG_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_MULTI_C #endif #if defined(BN_MP_IS_SQUARE_C) #define BN_MP_MOD_D_C #define BN_MP_INIT_SET_INT_C #define BN_MP_MOD_C #define BN_MP_GET_INT_C #define BN_MP_SQRT_C #define BN_MP_SQR_C #define BN_MP_CMP_MAG_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_JACOBI_C) #define BN_MP_CMP_D_C #define BN_MP_ISZERO_C #define BN_MP_INIT_COPY_C #define BN_MP_CNT_LSB_C #define BN_MP_DIV_2D_C #define BN_MP_MOD_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_KARATSUBA_MUL_C) #define BN_MP_MUL_C #define BN_MP_INIT_SIZE_C #define BN_MP_CLAMP_C #define BN_MP_SUB_C #define BN_MP_ADD_C #define BN_MP_LSHD_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_KARATSUBA_SQR_C) #define BN_MP_INIT_SIZE_C #define BN_MP_CLAMP_C #define BN_MP_SQR_C #define BN_MP_SUB_C #define BN_S_MP_ADD_C #define BN_MP_LSHD_C #define BN_MP_ADD_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_LCM_C) #define BN_MP_INIT_MULTI_C #define BN_MP_GCD_C #define BN_MP_CMP_MAG_C #define BN_MP_DIV_C #define BN_MP_MUL_C #define BN_MP_CLEAR_MULTI_C #endif #if defined(BN_MP_LSHD_C) #define BN_MP_GROW_C #define BN_MP_RSHD_C #endif #if defined(BN_MP_MOD_C) #define BN_MP_INIT_C #define BN_MP_DIV_C #define BN_MP_CLEAR_C #define BN_MP_ADD_C #define BN_MP_EXCH_C #endif #if defined(BN_MP_MOD_2D_C) #define BN_MP_ZERO_C #define BN_MP_COPY_C #define BN_MP_CLAMP_C #endif #if defined(BN_MP_MOD_D_C) #define BN_MP_DIV_D_C #endif #if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C) #define BN_MP_COUNT_BITS_C #define BN_MP_2EXPT_C #define BN_MP_SET_C #define BN_MP_MUL_2_C #define BN_MP_CMP_MAG_C #define BN_S_MP_SUB_C #endif #if defined(BN_MP_MONTGOMERY_REDUCE_C) #define BN_FAST_MP_MONTGOMERY_REDUCE_C #define BN_MP_GROW_C #define BN_MP_CLAMP_C #define BN_MP_RSHD_C #define BN_MP_CMP_MAG_C #define BN_S_MP_SUB_C #endif #if defined(BN_MP_MONTGOMERY_SETUP_C) #endif #if defined(BN_MP_MUL_C) #define BN_MP_TOOM_MUL_C #define BN_MP_KARATSUBA_MUL_C #define BN_FAST_S_MP_MUL_DIGS_C #define BN_S_MP_MUL_C #define BN_S_MP_MUL_DIGS_C #endif #if defined(BN_MP_MUL_2_C) #define BN_MP_GROW_C #endif #if defined(BN_MP_MUL_2D_C) #define BN_MP_COPY_C #define BN_MP_GROW_C #define BN_MP_LSHD_C #define BN_MP_CLAMP_C #endif #if defined(BN_MP_MUL_D_C) #define BN_MP_GROW_C #define BN_MP_CLAMP_C #endif #if defined(BN_MP_MULMOD_C) #define BN_MP_INIT_C #define BN_MP_MUL_C #define BN_MP_CLEAR_C #define BN_MP_MOD_C #endif #if defined(BN_MP_N_ROOT_C) #define BN_MP_INIT_C #define BN_MP_SET_C #define BN_MP_COPY_C #define BN_MP_EXPT_D_C #define BN_MP_MUL_C #define BN_MP_SUB_C #define BN_MP_MUL_D_C #define BN_MP_DIV_C #define BN_MP_CMP_C #define BN_MP_SUB_D_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_NEG_C) #define BN_MP_COPY_C #define BN_MP_ISZERO_C #endif #if defined(BN_MP_OR_C) #define BN_MP_INIT_COPY_C #define BN_MP_CLAMP_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_PRIME_FERMAT_C) #define BN_MP_CMP_D_C #define BN_MP_INIT_C #define BN_MP_EXPTMOD_C #define BN_MP_CMP_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_PRIME_IS_DIVISIBLE_C) #define BN_MP_MOD_D_C #endif #if defined(BN_MP_PRIME_IS_PRIME_C) #define BN_MP_CMP_D_C #define BN_MP_PRIME_IS_DIVISIBLE_C #define BN_MP_INIT_C #define BN_MP_SET_C #define BN_MP_PRIME_MILLER_RABIN_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_PRIME_MILLER_RABIN_C) #define BN_MP_CMP_D_C #define BN_MP_INIT_COPY_C #define BN_MP_SUB_D_C #define BN_MP_CNT_LSB_C #define BN_MP_DIV_2D_C #define BN_MP_EXPTMOD_C #define BN_MP_CMP_C #define BN_MP_SQRMOD_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_PRIME_NEXT_PRIME_C) #define BN_MP_CMP_D_C #define BN_MP_SET_C #define BN_MP_SUB_D_C #define BN_MP_ISEVEN_C #define BN_MP_MOD_D_C #define BN_MP_INIT_C #define BN_MP_ADD_D_C #define BN_MP_PRIME_MILLER_RABIN_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C) #endif #if defined(BN_MP_PRIME_RANDOM_EX_C) #define BN_MP_READ_UNSIGNED_BIN_C #define BN_MP_PRIME_IS_PRIME_C #define BN_MP_SUB_D_C #define BN_MP_DIV_2_C #define BN_MP_MUL_2_C #define BN_MP_ADD_D_C #endif #if defined(BN_MP_RADIX_SIZE_C) #define BN_MP_COUNT_BITS_C #define BN_MP_INIT_COPY_C #define BN_MP_ISZERO_C #define BN_MP_DIV_D_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_RADIX_SMAP_C) #define BN_MP_S_RMAP_C #endif #if defined(BN_MP_RAND_C) #define BN_MP_ZERO_C #define BN_MP_ADD_D_C #define BN_MP_LSHD_C #endif #if defined(BN_MP_READ_RADIX_C) #define BN_MP_ZERO_C #define BN_MP_S_RMAP_C #define BN_MP_RADIX_SMAP_C #define BN_MP_MUL_D_C #define BN_MP_ADD_D_C #define BN_MP_ISZERO_C #endif #if defined(BN_MP_READ_SIGNED_BIN_C) #define BN_MP_READ_UNSIGNED_BIN_C #endif #if defined(BN_MP_READ_UNSIGNED_BIN_C) #define BN_MP_GROW_C #define BN_MP_ZERO_C #define BN_MP_MUL_2D_C #define BN_MP_CLAMP_C #endif #if defined(BN_MP_REDUCE_C) #define BN_MP_REDUCE_SETUP_C #define BN_MP_INIT_COPY_C #define BN_MP_RSHD_C #define BN_MP_MUL_C #define BN_S_MP_MUL_HIGH_DIGS_C #define BN_FAST_S_MP_MUL_HIGH_DIGS_C #define BN_MP_MOD_2D_C #define BN_S_MP_MUL_DIGS_C #define BN_MP_SUB_C #define BN_MP_CMP_D_C #define BN_MP_SET_C #define BN_MP_LSHD_C #define BN_MP_ADD_C #define BN_MP_CMP_C #define BN_S_MP_SUB_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_REDUCE_2K_C) #define BN_MP_INIT_C #define BN_MP_COUNT_BITS_C #define BN_MP_DIV_2D_C #define BN_MP_MUL_D_C #define BN_S_MP_ADD_C #define BN_MP_CMP_MAG_C #define BN_S_MP_SUB_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_REDUCE_2K_L_C) #define BN_MP_INIT_C #define BN_MP_COUNT_BITS_C #define BN_MP_DIV_2D_C #define BN_MP_MUL_C #define BN_S_MP_ADD_C #define BN_MP_CMP_MAG_C #define BN_S_MP_SUB_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_REDUCE_2K_SETUP_C) #define BN_MP_INIT_C #define BN_MP_COUNT_BITS_C #define BN_MP_2EXPT_C #define BN_MP_CLEAR_C #define BN_S_MP_SUB_C #endif #if defined(BN_MP_REDUCE_2K_SETUP_L_C) #define BN_MP_INIT_C #define BN_MP_2EXPT_C #define BN_MP_COUNT_BITS_C #define BN_S_MP_SUB_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_REDUCE_IS_2K_C) #define BN_MP_REDUCE_2K_C #define BN_MP_COUNT_BITS_C #endif #if defined(BN_MP_REDUCE_IS_2K_L_C) #endif #if defined(BN_MP_REDUCE_SETUP_C) #define BN_MP_2EXPT_C #define BN_MP_DIV_C #endif #if defined(BN_MP_RSHD_C) #define BN_MP_ZERO_C #endif #if defined(BN_MP_SET_C) #define BN_MP_ZERO_C #endif #if defined(BN_MP_SET_INT_C) #define BN_MP_ZERO_C #define BN_MP_MUL_2D_C #define BN_MP_CLAMP_C #endif #if defined(BN_MP_SHRINK_C) #endif #if defined(BN_MP_SIGNED_BIN_SIZE_C) #define BN_MP_UNSIGNED_BIN_SIZE_C #endif #if defined(BN_MP_SQR_C) #define BN_MP_TOOM_SQR_C #define BN_MP_KARATSUBA_SQR_C #define BN_FAST_S_MP_SQR_C #define BN_S_MP_SQR_C #endif #if defined(BN_MP_SQRMOD_C) #define BN_MP_INIT_C #define BN_MP_SQR_C #define BN_MP_CLEAR_C #define BN_MP_MOD_C #endif #if defined(BN_MP_SQRT_C) #define BN_MP_N_ROOT_C #define BN_MP_ISZERO_C #define BN_MP_ZERO_C #define BN_MP_INIT_COPY_C #define BN_MP_RSHD_C #define BN_MP_DIV_C #define BN_MP_ADD_C #define BN_MP_DIV_2_C #define BN_MP_CMP_MAG_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_SUB_C) #define BN_S_MP_ADD_C #define BN_MP_CMP_MAG_C #define BN_S_MP_SUB_C #endif #if defined(BN_MP_SUB_D_C) #define BN_MP_GROW_C #define BN_MP_ADD_D_C #define BN_MP_CLAMP_C #endif #if defined(BN_MP_SUBMOD_C) #define BN_MP_INIT_C #define BN_MP_SUB_C #define BN_MP_CLEAR_C #define BN_MP_MOD_C #endif #if defined(BN_MP_TO_SIGNED_BIN_C) #define BN_MP_TO_UNSIGNED_BIN_C #endif #if defined(BN_MP_TO_SIGNED_BIN_N_C) #define BN_MP_SIGNED_BIN_SIZE_C #define BN_MP_TO_SIGNED_BIN_C #endif #if defined(BN_MP_TO_UNSIGNED_BIN_C) #define BN_MP_INIT_COPY_C #define BN_MP_ISZERO_C #define BN_MP_DIV_2D_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_TO_UNSIGNED_BIN_N_C) #define BN_MP_UNSIGNED_BIN_SIZE_C #define BN_MP_TO_UNSIGNED_BIN_C #endif #if defined(BN_MP_TOOM_MUL_C) #define BN_MP_INIT_MULTI_C #define BN_MP_MOD_2D_C #define BN_MP_COPY_C #define BN_MP_RSHD_C #define BN_MP_MUL_C #define BN_MP_MUL_2_C #define BN_MP_ADD_C #define BN_MP_SUB_C #define BN_MP_DIV_2_C #define BN_MP_MUL_2D_C #define BN_MP_MUL_D_C #define BN_MP_DIV_3_C #define BN_MP_LSHD_C #define BN_MP_CLEAR_MULTI_C #endif #if defined(BN_MP_TOOM_SQR_C) #define BN_MP_INIT_MULTI_C #define BN_MP_MOD_2D_C #define BN_MP_COPY_C #define BN_MP_RSHD_C #define BN_MP_SQR_C #define BN_MP_MUL_2_C #define BN_MP_ADD_C #define BN_MP_SUB_C #define BN_MP_DIV_2_C #define BN_MP_MUL_2D_C #define BN_MP_MUL_D_C #define BN_MP_DIV_3_C #define BN_MP_LSHD_C #define BN_MP_CLEAR_MULTI_C #endif #if defined(BN_MP_TORADIX_C) #define BN_MP_ISZERO_C #define BN_MP_INIT_COPY_C #define BN_MP_DIV_D_C #define BN_MP_CLEAR_C #define BN_MP_S_RMAP_C #endif #if defined(BN_MP_TORADIX_N_C) #define BN_MP_ISZERO_C #define BN_MP_INIT_COPY_C #define BN_MP_DIV_D_C #define BN_MP_CLEAR_C #define BN_MP_S_RMAP_C #endif #if defined(BN_MP_UNSIGNED_BIN_SIZE_C) #define BN_MP_COUNT_BITS_C #endif #if defined(BN_MP_XOR_C) #define BN_MP_INIT_COPY_C #define BN_MP_CLAMP_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_C #endif #if defined(BN_MP_ZERO_C) #endif #if defined(BN_PRIME_TAB_C) #endif #if defined(BN_REVERSE_C) #endif #if defined(BN_S_MP_ADD_C) #define BN_MP_GROW_C #define BN_MP_CLAMP_C #endif #if defined(BN_S_MP_EXPTMOD_C) #define BN_MP_COUNT_BITS_C #define BN_MP_INIT_C #define BN_MP_CLEAR_C #define BN_MP_REDUCE_SETUP_C #define BN_MP_REDUCE_C #define BN_MP_REDUCE_2K_SETUP_L_C #define BN_MP_REDUCE_2K_L_C #define BN_MP_MOD_C #define BN_MP_COPY_C #define BN_MP_SQR_C #define BN_MP_MUL_C #define BN_MP_SET_C #define BN_MP_EXCH_C #endif #if defined(BN_S_MP_MUL_DIGS_C) #define BN_FAST_S_MP_MUL_DIGS_C #define BN_MP_INIT_SIZE_C #define BN_MP_CLAMP_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_C #endif #if defined(BN_S_MP_MUL_HIGH_DIGS_C) #define BN_FAST_S_MP_MUL_HIGH_DIGS_C #define BN_MP_INIT_SIZE_C #define BN_MP_CLAMP_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_C #endif #if defined(BN_S_MP_SQR_C) #define BN_MP_INIT_SIZE_C #define BN_MP_CLAMP_C #define BN_MP_EXCH_C #define BN_MP_CLEAR_C #endif #if defined(BN_S_MP_SUB_C) #define BN_MP_GROW_C #define BN_MP_CLAMP_C #endif #if defined(BNCORE_C) #endif #ifdef LTM3 #define LTM_LAST #endif #include #include #else #define LTM_LAST #endif tcl8.6.5/libtommath/bn_mp_to_unsigned_bin.c0000644000175000017500000000215312663653207020415 0ustar sergeisergei#include #ifdef BN_MP_TO_UNSIGNED_BIN_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* store in unsigned [big endian] format */ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) { int x, res; mp_int t; if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } x = 0; while (mp_iszero (&t) == 0) { #ifndef MP_8BIT b[x++] = (unsigned char) (t.dp[0] & 255); #else b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); #endif if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { mp_clear (&t); return res; } } bn_reverse (b, x); mp_clear (&t); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_mod_2d.c0000644000175000017500000000253412663653207016416 0ustar sergeisergei#include #ifdef BN_MP_MOD_2D_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* calc a value mod 2**b */ int mp_mod_2d (const mp_int * a, int b, mp_int * c) { int x, res; /* if b is <= 0 then zero the int */ if (b <= 0) { mp_zero (c); return MP_OKAY; } /* if the modulus is larger than the value than return */ if (b >= (int) (a->used * DIGIT_BIT)) { res = mp_copy (a, c); return res; } /* copy */ if ((res = mp_copy (a, c)) != MP_OKAY) { return res; } /* zero digits above the last digit of the modulus */ for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { c->dp[x] = 0; } /* clear the digit that is not completely outside/inside the modulus */ c->dp[b / DIGIT_BIT] &= (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); mp_clamp (c); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_cnt_lsb.c0000644000175000017500000000223612663653257016702 0ustar sergeisergei#include #ifdef BN_MP_CNT_LSB_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ static const int lnz[16] = { 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 }; /* Counts the number of lsbs which are zero before the first zero bit */ int mp_cnt_lsb(const mp_int *a) { int x; mp_digit q, qq; /* easy out */ if (mp_iszero(a) == 1) { return 0; } /* scan lower digits until non-zero */ for (x = 0; x < a->used && a->dp[x] == 0; x++); q = a->dp[x]; x *= DIGIT_BIT; /* now scan this digit until a 1 is found */ if ((q & 1) == 0) { do { qq = q & 15; x += lnz[qq]; q >>= 4; } while (qq == 0); } return x; } #endif tcl8.6.5/libtommath/bn_mp_sqrt.c0000644000175000017500000000602512663653207016242 0ustar sergeisergei#include #ifdef BN_MP_SQRT_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ #ifndef NO_FLOATING_POINT #include #endif /* this function is less generic than mp_n_root, simpler and faster */ int mp_sqrt(mp_int *arg, mp_int *ret) { int res; mp_int t1,t2; int i, j, k; #ifndef NO_FLOATING_POINT volatile double d; mp_digit dig; #endif /* must be positive */ if (arg->sign == MP_NEG) { return MP_VAL; } /* easy out */ if (mp_iszero(arg) == MP_YES) { mp_zero(ret); return MP_OKAY; } i = (arg->used / 2) - 1; j = 2 * i; if ((res = mp_init_size(&t1, i+2)) != MP_OKAY) { return res; } if ((res = mp_init(&t2)) != MP_OKAY) { goto E2; } for (k = 0; k < i; ++k) { t1.dp[k] = (mp_digit) 0; } #ifndef NO_FLOATING_POINT /* Estimate the square root using the hardware floating point unit. */ d = 0.0; for (k = arg->used-1; k >= j; --k) { d = ldexp(d, DIGIT_BIT) + (double) (arg->dp[k]); } /* * At this point, d is the nearest floating point number to the most * significant 1 or 2 mp_digits of arg. Extract its square root. */ d = sqrt(d); /* dig is the most significant mp_digit of the square root */ dig = (mp_digit) ldexp(d, -DIGIT_BIT); /* * If the most significant digit is nonzero, find the next digit down * by subtracting DIGIT_BIT times thie most significant digit. * Subtract one from the result so that our initial estimate is always * low. */ if (dig) { t1.used = i+2; d -= ldexp((double) dig, DIGIT_BIT); if (d >= 1.0) { t1.dp[i+1] = dig; t1.dp[i] = ((mp_digit) d) - 1; } else { t1.dp[i+1] = dig-1; t1.dp[i] = MP_DIGIT_MAX; } } else { t1.used = i+1; t1.dp[i] = ((mp_digit) d) - 1; } #else /* Estimate the square root as having 1 in the most significant place. */ t1.used = i + 2; t1.dp[i+1] = (mp_digit) 1; t1.dp[i] = (mp_digit) 0; #endif /* t1 > 0 */ if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { goto E1; } if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { goto E1; } if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { goto E1; } /* And now t1 > sqrt(arg) */ do { if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { goto E1; } if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { goto E1; } if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { goto E1; } /* t1 >= sqrt(arg) >= t2 at this point */ } while (mp_cmp_mag(&t1,&t2) == MP_GT); mp_exch(&t1,ret); E1: mp_clear(&t2); E2: mp_clear(&t1); return res; } #endif tcl8.6.5/libtommath/bn_mp_radix_size.c0000644000175000017500000000344412663653207017414 0ustar sergeisergei#include #ifdef BN_MP_RADIX_SIZE_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* returns size of ASCII reprensentation */ int mp_radix_size (mp_int * a, int radix, int *size) { int res, digs; mp_int t; mp_digit d; *size = 0; /* special case for binary */ if (radix == 2) { *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; return MP_OKAY; } /* make sure the radix is in range */ if (radix < 2 || radix > 64) { return MP_VAL; } if (mp_iszero(a) == MP_YES) { *size = 2; return MP_OKAY; } /* digs is the digit count */ digs = 0; /* if it's negative add one for the sign */ if (a->sign == MP_NEG) { ++digs; } /* init a copy of the input */ if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } /* force temp to positive */ t.sign = MP_ZPOS; /* fetch out all of the digits */ while (mp_iszero (&t) == MP_NO) { if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { mp_clear (&t); return res; } ++digs; } mp_clear (&t); /* * return digs + 1, the 1 is for the NULL byte that would be required. * mp_toradix_n requires a minimum of 3 bytes, so never report less than * that. */ if ( digs >= 2 ) { *size = digs + 1; } else { *size = 3; } return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_div.c0000644000175000017500000001544112663653207016035 0ustar sergeisergei#include #ifdef BN_MP_DIV_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ #ifdef BN_MP_DIV_SMALL /* slower bit-bang division... also smaller */ int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) { mp_int ta, tb, tq, q; int res, n, n2; /* is divisor zero ? */ if (mp_iszero (b) == 1) { return MP_VAL; } /* if a < b then q=0, r = a */ if (mp_cmp_mag (a, b) == MP_LT) { if (d != NULL) { res = mp_copy (a, d); } else { res = MP_OKAY; } if (c != NULL) { mp_zero (c); } return res; } /* init our temps */ if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) { return res; } mp_set(&tq, 1); n = mp_count_bits(a) - mp_count_bits(b); if (((res = mp_abs(a, &ta)) != MP_OKAY) || ((res = mp_abs(b, &tb)) != MP_OKAY) || ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) || ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) { goto LBL_ERR; } while (n-- >= 0) { if (mp_cmp(&tb, &ta) != MP_GT) { if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) || ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) { goto LBL_ERR; } } if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) || ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) { goto LBL_ERR; } } /* now q == quotient and ta == remainder */ n = a->sign; n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG); if (c != NULL) { mp_exch(c, &q); c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2; } if (d != NULL) { mp_exch(d, &ta); d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n; } LBL_ERR: mp_clear_multi(&ta, &tb, &tq, &q, NULL); return res; } #else /* integer signed division. * c*b + d == a [e.g. a/b, c=quotient, d=remainder] * HAC pp.598 Algorithm 14.20 * * Note that the description in HAC is horribly * incomplete. For example, it doesn't consider * the case where digits are removed from 'x' in * the inner loop. It also doesn't consider the * case that y has fewer than three digits, etc.. * * The overall algorithm is as described as * 14.20 from HAC but fixed to treat these cases. */ int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { mp_int q, x, y, t1, t2; int res, n, t, i, norm, neg; /* is divisor zero ? */ if (mp_iszero (b) == 1) { return MP_VAL; } /* if a < b then q=0, r = a */ if (mp_cmp_mag (a, b) == MP_LT) { if (d != NULL) { res = mp_copy (a, d); } else { res = MP_OKAY; } if (c != NULL) { mp_zero (c); } return res; } if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { return res; } q.used = a->used + 2; if ((res = mp_init (&t1)) != MP_OKAY) { goto LBL_Q; } if ((res = mp_init (&t2)) != MP_OKAY) { goto LBL_T1; } if ((res = mp_init_copy (&x, a)) != MP_OKAY) { goto LBL_T2; } if ((res = mp_init_copy (&y, b)) != MP_OKAY) { goto LBL_X; } /* fix the sign */ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; x.sign = y.sign = MP_ZPOS; /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ norm = mp_count_bits(&y) % DIGIT_BIT; if (norm < (int)(DIGIT_BIT-1)) { norm = (DIGIT_BIT-1) - norm; if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { goto LBL_Y; } } else { norm = 0; } /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ n = x.used - 1; t = y.used - 1; /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */ goto LBL_Y; } while (mp_cmp (&x, &y) != MP_LT) { ++(q.dp[n - t]); if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { goto LBL_Y; } } /* reset y by shifting it back down */ mp_rshd (&y, n - t); /* step 3. for i from n down to (t + 1) */ for (i = n; i >= (t + 1); i--) { if (i > x.used) { continue; } /* step 3.1 if xi == yt then set q{i-t-1} to b-1, * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ if (x.dp[i] == y.dp[t]) { q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1); } else { mp_word tmp; tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); tmp |= ((mp_word) x.dp[i - 1]); tmp /= ((mp_word) y.dp[t]); if (tmp > (mp_word) MP_MASK) tmp = MP_MASK; q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); } /* while (q{i-t-1} * (yt * b + y{t-1})) > xi * b**2 + xi-1 * b + xi-2 do q{i-t-1} -= 1; */ q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; do { q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; /* find left hand */ mp_zero (&t1); t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; t1.dp[1] = y.dp[t]; t1.used = 2; if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { goto LBL_Y; } /* find right hand */ t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; t2.dp[2] = x.dp[i]; t2.used = 3; } while (mp_cmp_mag(&t1, &t2) == MP_GT); /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { goto LBL_Y; } /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ if (x.sign == MP_NEG) { if ((res = mp_copy (&y, &t1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { goto LBL_Y; } q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; } } /* now q is the quotient and x is the remainder * [which we have to normalize] */ /* get sign before writing to c */ x.sign = x.used == 0 ? MP_ZPOS : a->sign; if (c != NULL) { mp_clamp (&q); mp_exch (&q, c); c->sign = neg; } if (d != NULL) { mp_div_2d (&x, norm, &x, NULL); mp_exch (&x, d); } res = MP_OKAY; LBL_Y:mp_clear (&y); LBL_X:mp_clear (&x); LBL_T2:mp_clear (&t2); LBL_T1:mp_clear (&t1); LBL_Q:mp_clear (&q); return res; } #endif #endif tcl8.6.5/libtommath/bn_mp_xor.c0000644000175000017500000000206112663653210016047 0ustar sergeisergei#include #ifdef BN_MP_XOR_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* XOR two ints together */ int mp_xor (mp_int * a, mp_int * b, mp_int * c) { int res, ix, px; mp_int t, *x; if (a->used > b->used) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } px = b->used; x = b; } else { if ((res = mp_init_copy (&t, b)) != MP_OKAY) { return res; } px = a->used; x = a; } for (ix = 0; ix < px; ix++) { t.dp[ix] ^= x->dp[ix]; } mp_clamp (&t); mp_exch (c, &t); mp_clear (&t); return MP_OKAY; } #endif tcl8.6.5/libtommath/bncore.c0000644000175000017500000000231612663653210015337 0ustar sergeisergei#include #ifdef BNCORE_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* Known optimal configurations CPU /Compiler /MUL CUTOFF/SQR CUTOFF ------------------------------------------------------------- Intel P4 Northwood /GCC v3.4.1 / 88/ 128/LTM 0.32 ;-) AMD Athlon64 /GCC v3.4.4 / 80/ 120/LTM 0.35 */ int KARATSUBA_MUL_CUTOFF = 80, /* Min. number of digits before Karatsuba multiplication is used. */ KARATSUBA_SQR_CUTOFF = 120, /* Min. number of digits before Karatsuba squaring is used. */ TOOM_MUL_CUTOFF = 350, /* no optimal values of these are known yet so set em high */ TOOM_SQR_CUTOFF = 400; #endif tcl8.6.5/libtommath/bn_mp_or.c0000644000175000017500000000205512663653207015670 0ustar sergeisergei#include #ifdef BN_MP_OR_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* OR two ints together */ int mp_or (mp_int * a, mp_int * b, mp_int * c) { int res, ix, px; mp_int t, *x; if (a->used > b->used) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } px = b->used; x = b; } else { if ((res = mp_init_copy (&t, b)) != MP_OKAY) { return res; } px = a->used; x = a; } for (ix = 0; ix < px; ix++) { t.dp[ix] |= x->dp[ix]; } mp_clamp (&t); mp_exch (c, &t); mp_clear (&t); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_add_d.c0000644000175000017500000000452412663653207016306 0ustar sergeisergei#include #ifdef BN_MP_ADD_D_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* single digit addition */ int mp_add_d (mp_int * a, mp_digit b, mp_int * c) { int res, ix, oldused; mp_digit *tmpa, *tmpc, mu; /* grow c as required */ if (c->alloc < a->used + 1) { if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { return res; } } /* if a is negative and |a| >= b, call c = |a| - b */ if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) { /* temporarily fix sign of a */ a->sign = MP_ZPOS; /* c = |a| - b */ res = mp_sub_d(a, b, c); /* fix signs */ a->sign = MP_NEG; c->sign = (c->used) ? MP_NEG : MP_ZPOS; /* clamp */ mp_clamp(c); return res; } /* old number of used digits in c */ oldused = c->used; /* sign always positive */ c->sign = MP_ZPOS; /* source alias */ tmpa = a->dp; /* destination alias */ tmpc = c->dp; /* if a is positive */ if (a->sign == MP_ZPOS) { /* add digit, after this we're propagating * the carry. */ *tmpc = *tmpa++ + b; mu = *tmpc >> DIGIT_BIT; *tmpc++ &= MP_MASK; /* now handle rest of the digits */ for (ix = 1; ix < a->used; ix++) { *tmpc = *tmpa++ + mu; mu = *tmpc >> DIGIT_BIT; *tmpc++ &= MP_MASK; } /* set final carry */ ix++; *tmpc++ = mu; /* setup size */ c->used = a->used + 1; } else { /* a was negative and |a| < b */ c->used = 1; /* the result is a single digit */ if (a->used == 1) { *tmpc++ = b - a->dp[0]; } else { *tmpc++ = b; } /* setup count so the clearing of oldused * can fall through correctly */ ix = 1; } /* now zero to oldused */ while (ix++ < oldused) { *tmpc++ = 0; } mp_clamp(c); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_s_mp_add.c0000644000175000017500000000444712663653210016323 0ustar sergeisergei#include #ifdef BN_S_MP_ADD_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* low level addition, based on HAC pp.594, Algorithm 14.7 */ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) { mp_int *x; int olduse, res, min, max; /* find sizes, we let |a| <= |b| which means we have to sort * them. "x" will point to the input with the most digits */ if (a->used > b->used) { min = b->used; max = a->used; x = a; } else { min = a->used; max = b->used; x = b; } /* init result */ if (c->alloc < max + 1) { if ((res = mp_grow (c, max + 1)) != MP_OKAY) { return res; } } /* get old used digit count and set new one */ olduse = c->used; c->used = max + 1; { register mp_digit u, *tmpa, *tmpb, *tmpc; register int i; /* alias for digit pointers */ /* first input */ tmpa = a->dp; /* second input */ tmpb = b->dp; /* destination */ tmpc = c->dp; /* zero the carry */ u = 0; for (i = 0; i < min; i++) { /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ *tmpc = *tmpa++ + *tmpb++ + u; /* U = carry bit of T[i] */ u = *tmpc >> ((mp_digit)DIGIT_BIT); /* take away carry bit from T[i] */ *tmpc++ &= MP_MASK; } /* now copy higher words if any, that is in A+B * if A or B has more digits add those in */ if (min != max) { for (; i < max; i++) { /* T[i] = X[i] + U */ *tmpc = x->dp[i] + u; /* U = carry bit of T[i] */ u = *tmpc >> ((mp_digit)DIGIT_BIT); /* take away carry bit from T[i] */ *tmpc++ &= MP_MASK; } } /* add carry */ *tmpc++ = u; /* clear digits above oldused */ for (i = c->used; i < olduse; i++) { *tmpc++ = 0; } } mp_clamp (c); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_init_copy.c0000644000175000017500000000136712663653207017252 0ustar sergeisergei#include #ifdef BN_MP_INIT_COPY_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* creates "a" then copies b into it */ int mp_init_copy (mp_int * a, mp_int * b) { int res; if ((res = mp_init (a)) != MP_OKAY) { return res; } return mp_copy (b, a); } #endif tcl8.6.5/libtommath/bn_mp_and.c0000644000175000017500000000224212663653207016010 0ustar sergeisergei#include #ifdef BN_MP_AND_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* AND two ints together */ int mp_and (mp_int * a, mp_int * b, mp_int * c) { int res, ix, px; mp_int t, *x; if (a->used > b->used) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } px = b->used; x = b; } else { if ((res = mp_init_copy (&t, b)) != MP_OKAY) { return res; } px = a->used; x = a; } for (ix = 0; ix < px; ix++) { t.dp[ix] &= x->dp[ix]; } /* zero digits above the last from the smallest mp_int */ for (; ix < t.used; ix++) { t.dp[ix] = 0; } mp_clamp (&t); mp_exch (c, &t); mp_clear (&t); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_mul_d.c0000644000175000017500000000334212663653207016350 0ustar sergeisergei#include #ifdef BN_MP_MUL_D_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* multiply by a digit */ int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) { mp_digit u, *tmpa, *tmpc; mp_word r; int ix, res, olduse; /* make sure c is big enough to hold a*b */ if (c->alloc < a->used + 1) { if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) { return res; } } /* get the original destinations used count */ olduse = c->used; /* set the sign */ c->sign = a->sign; /* alias for a->dp [source] */ tmpa = a->dp; /* alias for c->dp [dest] */ tmpc = c->dp; /* zero carry */ u = 0; /* compute columns */ for (ix = 0; ix < a->used; ix++) { /* compute product and carry sum for this term */ r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b); /* mask off higher bits to get a single digit */ *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* send carry into next iteration */ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); } /* store final carry [if any] and increment ix offset */ *tmpc++ = u; ++ix; /* now zero digits above the top */ while (ix++ < olduse) { *tmpc++ = 0; } /* set used count */ c->used = a->used + 1; mp_clamp(c); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_unsigned_bin_size.c0000644000175000017500000000136112663653210020737 0ustar sergeisergei#include #ifdef BN_MP_UNSIGNED_BIN_SIZE_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* get the size for an unsigned equivalent */ int mp_unsigned_bin_size (mp_int * a) { int size = mp_count_bits (a); return (size / 8 + ((size & 7) != 0 ? 1 : 0)); } #endif tcl8.6.5/libtommath/tommath.h0000644000175000017500000004141012663653210015543 0ustar sergeisergei/* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ #ifndef BN_H_ #define BN_H_ #include #include #include #include #include #include #ifndef MIN # define MIN(x,y) ((x)<(y)?(x):(y)) #endif #ifndef MAX # define MAX(x,y) ((x)>(y)?(x):(y)) #endif #ifdef __cplusplus extern "C" { /* C++ compilers don't like assigning void * to mp_digit * */ #define OPT_CAST(x) (x *) #else /* C on the other hand doesn't care */ #define OPT_CAST(x) #endif /* detect 64-bit mode if possible */ #if defined(__x86_64__) # if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT)) # define MP_64BIT # endif #endif /* some default configurations. * * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits * * At the very least a mp_digit must be able to hold 7 bits * [any size beyond that is ok provided it doesn't overflow the data type] */ #ifdef MP_8BIT typedef unsigned char mp_digit; typedef unsigned short mp_word; #elif defined(MP_16BIT) typedef unsigned short mp_digit; typedef unsigned long mp_word; #elif defined(MP_64BIT) /* for GCC only on supported platforms */ #ifndef CRYPT typedef unsigned long long ulong64; typedef signed long long long64; #endif typedef unsigned long mp_digit; typedef unsigned long mp_word __attribute__ ((mode(TI))); # define DIGIT_BIT 60 #else /* this is the default case, 28-bit digits */ /* this is to make porting into LibTomCrypt easier :-) */ #ifndef CRYPT # if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 ulong64; typedef signed __int64 long64; # else typedef unsigned long long ulong64; typedef signed long long long64; # endif #endif typedef unsigned long mp_digit; typedef ulong64 mp_word; #ifdef MP_31BIT /* this is an extension that uses 31-bit digits */ # define DIGIT_BIT 31 #else /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */ # define DIGIT_BIT 28 # define MP_28BIT #endif #endif /* define heap macros */ #ifndef CRYPT /* default to libc stuff */ # ifndef XMALLOC # define XMALLOC malloc # define XFREE free # define XREALLOC realloc # define XCALLOC calloc # else /* prototypes for our heap functions */ extern void *XMALLOC(size_t n); extern void *XREALLOC(void *p, size_t n); extern void *XCALLOC(size_t n, size_t s); extern void XFREE(void *p); # endif #endif /* otherwise the bits per digit is calculated automatically from the size of a mp_digit */ #ifndef DIGIT_BIT # define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */ #endif #define MP_DIGIT_BIT DIGIT_BIT #define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) #define MP_DIGIT_MAX MP_MASK /* equalities */ #define MP_LT -1 /* less than */ #define MP_EQ 0 /* equal to */ #define MP_GT 1 /* greater than */ #define MP_ZPOS 0 /* positive integer */ #define MP_NEG 1 /* negative */ #define MP_OKAY 0 /* ok result */ #define MP_MEM -2 /* out of mem */ #define MP_VAL -3 /* invalid input */ #define MP_RANGE MP_VAL #define MP_YES 1 /* yes response */ #define MP_NO 0 /* no response */ /* Primality generation flags */ #define LTM_PRIME_BBS 0x0001 /* BBS style prime */ #define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ #define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ typedef int mp_err; /* you'll have to tune these... */ extern int KARATSUBA_MUL_CUTOFF, KARATSUBA_SQR_CUTOFF, TOOM_MUL_CUTOFF, TOOM_SQR_CUTOFF; /* define this to use lower memory usage routines (exptmods mostly) */ /* #define MP_LOW_MEM */ /* default precision */ #ifndef MP_PREC # ifndef MP_LOW_MEM # define MP_PREC 32 /* default digits of precision */ # else # define MP_PREC 8 /* default digits of precision */ # endif #endif /* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ #define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) /* the infamous mp_int structure */ typedef struct { int used, alloc, sign; mp_digit *dp; } mp_int; /* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */ typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); #define USED(m) ((m)->used) #define DIGIT(m,k) ((m)->dp[(k)]) #define SIGN(m) ((m)->sign) /* error code to char* string */ char *mp_error_to_string(int code); /* ---> init and deinit bignum functions <--- */ /* init a bignum */ int mp_init(mp_int *a); /* free a bignum */ void mp_clear(mp_int *a); /* init a null terminated series of arguments */ int mp_init_multi(mp_int *mp, ...); /* clear a null terminated series of arguments */ void mp_clear_multi(mp_int *mp, ...); /* exchange two ints */ void mp_exch(mp_int *a, mp_int *b); /* shrink ram required for a bignum */ int mp_shrink(mp_int *a); /* grow an int to a given size */ int mp_grow(mp_int *a, int size); /* init to a given number of digits */ int mp_init_size(mp_int *a, int size); /* ---> Basic Manipulations <--- */ #define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) #define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) #define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) /* set to zero */ void mp_zero(mp_int *a); /* set to a digit */ void mp_set(mp_int *a, mp_digit b); /* set a 32-bit const */ int mp_set_int(mp_int *a, unsigned long b); /* get a 32-bit value */ unsigned long mp_get_int(mp_int * a); /* initialize and set a digit */ int mp_init_set (mp_int * a, mp_digit b); /* initialize and set 32-bit value */ int mp_init_set_int (mp_int * a, unsigned long b); /* copy, b = a */ int mp_copy(const mp_int *a, mp_int *b); /* inits and copies, a = b */ int mp_init_copy(mp_int *a, mp_int *b); /* trim unused digits */ void mp_clamp(mp_int *a); /* ---> digit manipulation <--- */ /* right shift by "b" digits */ void mp_rshd(mp_int *a, int b); /* left shift by "b" digits */ int mp_lshd(mp_int *a, int b); /* c = a / 2**b */ int mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d); /* b = a/2 */ int mp_div_2(mp_int *a, mp_int *b); /* c = a * 2**b */ int mp_mul_2d(const mp_int *a, int b, mp_int *c); /* b = a*2 */ int mp_mul_2(mp_int *a, mp_int *b); /* c = a mod 2**d */ int mp_mod_2d(const mp_int *a, int b, mp_int *c); /* computes a = 2**b */ int mp_2expt(mp_int *a, int b); /* Counts the number of lsbs which are zero before the first zero bit */ int mp_cnt_lsb(mp_int *a); /* I Love Earth! */ /* makes a pseudo-random int of a given size */ int mp_rand(mp_int *a, int digits); /* ---> binary operations <--- */ /* c = a XOR b */ int mp_xor(mp_int *a, mp_int *b, mp_int *c); /* c = a OR b */ int mp_or(mp_int *a, mp_int *b, mp_int *c); /* c = a AND b */ int mp_and(mp_int *a, mp_int *b, mp_int *c); /* ---> Basic arithmetic <--- */ /* b = -a */ int mp_neg(const mp_int *a, mp_int *b); /* b = |a| */ int mp_abs(mp_int *a, mp_int *b); /* compare a to b */ int mp_cmp(const mp_int *a, const mp_int *b); /* compare |a| to |b| */ int mp_cmp_mag(const mp_int *a, const mp_int *b); /* c = a + b */ int mp_add(mp_int *a, mp_int *b, mp_int *c); /* c = a - b */ int mp_sub(mp_int *a, mp_int *b, mp_int *c); /* c = a * b */ int mp_mul(mp_int *a, mp_int *b, mp_int *c); /* b = a*a */ int mp_sqr(mp_int *a, mp_int *b); /* a/b => cb + d == a */ int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d); /* c = a mod b, 0 <= c < b */ int mp_mod(mp_int *a, mp_int *b, mp_int *c); /* ---> single digit functions <--- */ /* compare against a single digit */ int mp_cmp_d(const mp_int *a, mp_digit b); /* c = a + b */ int mp_add_d(mp_int *a, mp_digit b, mp_int *c); /* c = a - b */ int mp_sub_d(mp_int *a, mp_digit b, mp_int *c); /* c = a * b */ int mp_mul_d(mp_int *a, mp_digit b, mp_int *c); /* a/b => cb + d == a */ int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d); /* a/3 => 3c + d == a */ int mp_div_3(mp_int *a, mp_int *c, mp_digit *d); /* c = a**b */ int mp_expt_d(mp_int *a, mp_digit b, mp_int *c); /* c = a mod b, 0 <= c < b */ int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c); /* ---> number theory <--- */ /* d = a + b (mod c) */ int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); /* d = a - b (mod c) */ int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); /* d = a * b (mod c) */ int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); /* c = a * a (mod b) */ int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c); /* c = 1/a (mod b) */ int mp_invmod(mp_int *a, mp_int *b, mp_int *c); /* c = (a, b) */ int mp_gcd(mp_int *a, mp_int *b, mp_int *c); /* produces value such that U1*a + U2*b = U3 */ int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3); /* c = [a, b] or (a*b)/(a, b) */ int mp_lcm(mp_int *a, mp_int *b, mp_int *c); /* finds one of the b'th root of a, such that |c|**b <= |a| * * returns error if a < 0 and b is even */ int mp_n_root(mp_int *a, mp_digit b, mp_int *c); /* special sqrt algo */ int mp_sqrt(mp_int *arg, mp_int *ret); /* is number a square? */ int mp_is_square(mp_int *arg, int *ret); /* computes the jacobi c = (a | n) (or Legendre if b is prime) */ int mp_jacobi(mp_int *a, mp_int *n, int *c); /* used to setup the Barrett reduction for a given modulus b */ int mp_reduce_setup(mp_int *a, mp_int *b); /* Barrett Reduction, computes a (mod b) with a precomputed value c * * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code]. */ int mp_reduce(mp_int *a, mp_int *b, mp_int *c); /* setups the montgomery reduction */ int mp_montgomery_setup(mp_int *a, mp_digit *mp); /* computes a = B**n mod b without division or multiplication useful for * normalizing numbers in a Montgomery system. */ int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); /* computes x/R == x (mod N) via Montgomery Reduction */ int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); /* returns 1 if a is a valid DR modulus */ int mp_dr_is_modulus(mp_int *a); /* sets the value of "d" required for mp_dr_reduce */ void mp_dr_setup(mp_int *a, mp_digit *d); /* reduces a modulo b using the Diminished Radix method */ int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp); /* returns true if a can be reduced with mp_reduce_2k */ int mp_reduce_is_2k(mp_int *a); /* determines k value for 2k reduction */ int mp_reduce_2k_setup(mp_int *a, mp_digit *d); /* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d); /* returns true if a can be reduced with mp_reduce_2k_l */ int mp_reduce_is_2k_l(mp_int *a); /* determines k value for 2k reduction */ int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); /* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); /* d = a**b (mod c) */ int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); /* ---> Primes <--- */ /* number of primes */ #ifdef MP_8BIT # define PRIME_SIZE 31 #else # define PRIME_SIZE 256 #endif /* table of first PRIME_SIZE primes */ extern const mp_digit ltm_prime_tab[]; /* result=1 if a is divisible by one of the first PRIME_SIZE primes */ int mp_prime_is_divisible(mp_int *a, int *result); /* performs one Fermat test of "a" using base "b". * Sets result to 0 if composite or 1 if probable prime */ int mp_prime_fermat(mp_int *a, mp_int *b, int *result); /* performs one Miller-Rabin test of "a" using base "b". * Sets result to 0 if composite or 1 if probable prime */ int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result); /* This gives [for a given bit size] the number of trials required * such that Miller-Rabin gives a prob of failure lower than 2^-96 */ int mp_prime_rabin_miller_trials(int size); /* performs t rounds of Miller-Rabin on "a" using the first * t prime bases. Also performs an initial sieve of trial * division. Determines if "a" is prime with probability * of error no more than (1/4)**t. * * Sets result to 1 if probably prime, 0 otherwise */ int mp_prime_is_prime(mp_int *a, int t, int *result); /* finds the next prime after the number "a" using "t" trials * of Miller-Rabin. * * bbs_style = 1 means the prime must be congruent to 3 mod 4 */ int mp_prime_next_prime(mp_int *a, int t, int bbs_style); /* makes a truly random prime of a given size (bytes), * call with bbs = 1 if you want it to be congruent to 3 mod 4 * * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself * so it can be NULL * * The prime generated will be larger than 2^(8*size). */ #define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat) /* makes a truly random prime of a given size (bits), * * Flags are as follows: * * LTM_PRIME_BBS - make prime congruent to 3 mod 4 * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero * LTM_PRIME_2MSB_ON - make the 2nd highest bit one * * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself * so it can be NULL * */ int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat); /* ---> radix conversion <--- */ int mp_count_bits(const mp_int *a); int mp_unsigned_bin_size(mp_int *a); int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c); int mp_to_unsigned_bin(mp_int *a, unsigned char *b); int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen); int mp_signed_bin_size(mp_int *a); int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c); int mp_to_signed_bin(mp_int *a, unsigned char *b); int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen); int mp_read_radix(mp_int *a, const char *str, int radix); int mp_toradix(mp_int *a, char *str, int radix); int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen); int mp_radix_size(mp_int *a, int radix, int *size); int mp_fread(mp_int *a, int radix, FILE *stream); int mp_fwrite(mp_int *a, int radix, FILE *stream); #define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len)) #define mp_raw_size(mp) mp_signed_bin_size(mp) #define mp_toraw(mp, str) mp_to_signed_bin((mp), (str)) #define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len)) #define mp_mag_size(mp) mp_unsigned_bin_size(mp) #define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) #define mp_tobinary(M, S) mp_toradix((M), (S), 2) #define mp_tooctal(M, S) mp_toradix((M), (S), 8) #define mp_todecimal(M, S) mp_toradix((M), (S), 10) #define mp_tohex(M, S) mp_toradix((M), (S), 16) /* lowlevel functions, do not call! */ int s_mp_add(mp_int *a, mp_int *b, mp_int *c); int s_mp_sub(mp_int *a, mp_int *b, mp_int *c); #define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs); int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs); int fast_s_mp_sqr(mp_int *a, mp_int *b); int s_mp_sqr(mp_int *a, mp_int *b); int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c); int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c); int mp_karatsuba_sqr(mp_int *a, mp_int *b); int mp_toom_sqr(mp_int *a, mp_int *b); int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c); int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c); int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode); int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int mode); void bn_reverse(unsigned char *s, int len); extern const char *mp_s_rmap; #ifdef __cplusplus } #endif #endif tcl8.6.5/libtommath/bn_mp_grow.c0000644000175000017500000000266212663653207016232 0ustar sergeisergei#include #ifdef BN_MP_GROW_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* grow as required */ int mp_grow (mp_int * a, int size) { int i; mp_digit *tmp; /* if the alloc size is smaller alloc more ram */ if (a->alloc < size) { /* ensure there are always at least MP_PREC digits extra on top */ size += (MP_PREC * 2) - (size % MP_PREC); /* reallocate the array a->dp * * We store the return in a temporary variable * in case the operation failed we don't want * to overwrite the dp member of a. */ tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size); if (tmp == NULL) { /* reallocation failed but "a" is still valid [can be freed] */ return MP_MEM; } /* reallocation succeeded so set a->dp */ a->dp = tmp; /* zero excess digits */ i = a->alloc; a->alloc = size; for (; i < a->alloc; i++) { a->dp[i] = 0; } } return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_sub.c0000644000175000017500000000310312663653207016034 0ustar sergeisergei#include #ifdef BN_MP_SUB_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* high level subtraction (handles signs) */ int mp_sub (mp_int * a, mp_int * b, mp_int * c) { int sa, sb, res; sa = a->sign; sb = b->sign; if (sa != sb) { /* subtract a negative from a positive, OR */ /* subtract a positive from a negative. */ /* In either case, ADD their magnitudes, */ /* and use the sign of the first number. */ c->sign = sa; res = s_mp_add (a, b, c); } else { /* subtract a positive from a positive, OR */ /* subtract a negative from a negative. */ /* First, take the difference between their */ /* magnitudes, then... */ if (mp_cmp_mag (a, b) != MP_LT) { /* Copy the sign from the first */ c->sign = sa; /* The first has a larger or equal magnitude */ res = s_mp_sub (a, b, c); } else { /* The result has the *opposite* sign from */ /* the first number. */ c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS; /* The second has a larger magnitude */ res = s_mp_sub (b, a, c); } } return res; } #endif tcl8.6.5/libtommath/bn_fast_s_mp_mul_digs.c0000644000175000017500000000522412663653207020413 0ustar sergeisergei#include #ifdef BN_FAST_S_MP_MUL_DIGS_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* Fast (comba) multiplier * * This is the fast column-array [comba] multiplier. It is * designed to compute the columns of the product first * then handle the carries afterwards. This has the effect * of making the nested loops that compute the columns very * simple and schedulable on super-scalar processors. * * This has been modified to produce a variable number of * digits of output so if say only a half-product is required * you don't have to compute the upper half (a feature * required for fast Barrett reduction). * * Based on Algorithm 14.12 on pp.595 of HAC. * */ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { int olduse, res, pa, ix, iz; mp_digit W[MP_WARRAY]; register mp_word _W; /* grow the destination as required */ if (c->alloc < digs) { if ((res = mp_grow (c, digs)) != MP_OKAY) { return res; } } /* number of output digits to produce */ pa = MIN(digs, a->used + b->used); /* clear the carry */ _W = 0; for (ix = 0; ix < pa; ix++) { int tx, ty; int iy; mp_digit *tmpx, *tmpy; /* get offsets into the two bignums */ ty = MIN(b->used-1, ix); tx = ix - ty; /* setup temp aliases */ tmpx = a->dp + tx; tmpy = b->dp + ty; /* this is the number of times the loop will iterrate, essentially while (tx++ < a->used && ty-- >= 0) { ... } */ iy = MIN(a->used-tx, ty+1); /* execute loop */ for (iz = 0; iz < iy; ++iz) { _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); } /* store term */ W[ix] = ((mp_digit)_W) & MP_MASK; /* make next carry */ _W = _W >> ((mp_word)DIGIT_BIT); } /* setup dest */ olduse = c->used; c->used = pa; { register mp_digit *tmpc; tmpc = c->dp; for (ix = 0; ix < pa+1; ix++) { /* now extract the previous digit [below the carry] */ *tmpc++ = W[ix]; } /* clear unused digits [that existed in the old copy of c] */ for (; ix < olduse; ix++) { *tmpc++ = 0; } } mp_clamp (c); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_div_3.c0000644000175000017500000000332512663653207016255 0ustar sergeisergei#include #ifdef BN_MP_DIV_3_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* divide by three (based on routine from MPI and the GMP manual) */ int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) { mp_int q; mp_word w, t; mp_digit b; int res, ix; /* b = 2**DIGIT_BIT / 3 */ b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3); if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { return res; } q.used = a->used; q.sign = a->sign; w = 0; for (ix = a->used - 1; ix >= 0; ix--) { w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); if (w >= 3) { /* multiply w by [1/3] */ t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT); /* now subtract 3 * [w/3] from w, to get the remainder */ w -= t+t+t; /* fixup the remainder as required since * the optimization is not exact. */ while (w >= 3) { t += 1; w -= 3; } } else { t = 0; } q.dp[ix] = (mp_digit)t; } /* [optional] store the remainder */ if (d != NULL) { *d = (mp_digit)w; } /* [optional] store the quotient */ if (c != NULL) { mp_clamp(&q); mp_exch(&q, c); } mp_clear(&q); return res; } #endif tcl8.6.5/libtommath/bn_mp_div_d.c0000644000175000017500000000434112663653207016335 0ustar sergeisergei#include #ifdef BN_MP_DIV_D_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ static int s_is_power_of_two(mp_digit b, int *p) { int x; /* quick out - if (b & (b-1)) isn't zero, b isn't a power of two */ if ((b==0) || (b & (b-1))) { return 0; } for (x = 1; x < DIGIT_BIT; x++) { if (b == (((mp_digit)1)<dp[0] & ((((mp_digit)1)<used)) != MP_OKAY) { return res; } q.used = a->used; q.sign = a->sign; w = 0; for (ix = a->used - 1; ix >= 0; ix--) { w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); if (w >= b) { t = (mp_digit)(w / b); w -= ((mp_word)t) * ((mp_word)b); } else { t = 0; } q.dp[ix] = (mp_digit)t; } if (d != NULL) { *d = (mp_digit)w; } if (c != NULL) { mp_clamp(&q); mp_exch(&q, c); } mp_clear(&q); return res; } #endif tcl8.6.5/libtommath/bn_mp_count_bits.c0000644000175000017500000000172612663653207017425 0ustar sergeisergei#include #ifdef BN_MP_COUNT_BITS_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* returns the number of bits in an int */ int mp_count_bits (const mp_int * a) { int r; mp_digit q; /* shortcut */ if (a->used == 0) { return 0; } /* get number of digits and add that */ r = (a->used - 1) * DIGIT_BIT; /* take the last digit and count the bits in it */ q = a->dp[a->used - 1]; while (q > ((mp_digit) 0)) { ++r; q >>= ((mp_digit) 1); } return r; } #endif tcl8.6.5/libtommath/bn_mp_clear_multi.c0000644000175000017500000000147212663653207017552 0ustar sergeisergei#include #ifdef BN_MP_CLEAR_MULTI_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ #include void mp_clear_multi(mp_int *mp, ...) { mp_int* next_mp = mp; va_list args; va_start(args, mp); while (next_mp != NULL) { mp_clear(next_mp); next_mp = va_arg(args, mp_int*); } va_end(args); } #endif tcl8.6.5/libtommath/bn_mp_to_unsigned_bin_n.c0000644000175000017500000000154212663653207020733 0ustar sergeisergei#include #ifdef BN_MP_TO_UNSIGNED_BIN_N_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* store in unsigned [big endian] format */ int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen) { if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) { return MP_VAL; } *outlen = mp_unsigned_bin_size(a); return mp_to_unsigned_bin(a, b); } #endif tcl8.6.5/libtommath/bn_mp_set.c0000644000175000017500000000130312663653207016036 0ustar sergeisergei#include #ifdef BN_MP_SET_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* set to a digit */ void mp_set (mp_int * a, mp_digit b) { mp_zero (a); a->dp[0] = b & MP_MASK; a->used = (a->dp[0] != 0) ? 1 : 0; } #endif tcl8.6.5/libtommath/bn_mp_init_multi.c0000644000175000017500000000324612663653207017430 0ustar sergeisergei#include #ifdef BN_MP_INIT_MULTI_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ #include int mp_init_multi(mp_int *mp, ...) { mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ int n = 0; /* Number of ok inits */ mp_int* cur_arg = mp; va_list args; va_start(args, mp); /* init args to next argument from caller */ while (cur_arg != NULL) { if (mp_init(cur_arg) != MP_OKAY) { /* Oops - error! Back-track and mp_clear what we already succeeded in init-ing, then return error. */ va_list clean_args; /* end the current list */ va_end(args); /* now start cleaning up */ cur_arg = mp; va_start(clean_args, mp); while (n--) { mp_clear(cur_arg); cur_arg = va_arg(clean_args, mp_int*); } va_end(clean_args); res = MP_MEM; break; } n++; cur_arg = va_arg(args, mp_int*); } va_end(args); return res; /* Assumed ok, if error flagged above. */ } #endif tcl8.6.5/libtommath/bn_mp_rshd.c0000644000175000017500000000303212663653207016204 0ustar sergeisergei#include #ifdef BN_MP_RSHD_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* shift right a certain amount of digits */ void mp_rshd (mp_int * a, int b) { int x; /* if b <= 0 then ignore it */ if (b <= 0) { return; } /* if b > used then simply zero it and return */ if (a->used <= b) { mp_zero (a); return; } { register mp_digit *bottom, *top; /* shift the digits down */ /* bottom */ bottom = a->dp; /* top [offset into digits] */ top = a->dp + b; /* this is implemented as a sliding window where * the window is b-digits long and digits from * the top of the window are copied to the bottom * * e.g. b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> /\ | ----> \-------------------/ ----> */ for (x = 0; x < (a->used - b); x++) { *bottom++ = *top++; } /* zero the top digits */ for (; x < a->used; x++) { *bottom++ = 0; } } /* remove excess digits */ a->used -= b; } #endif tcl8.6.5/libtommath/bn_s_mp_sub.c0000644000175000017500000000412012663653210016350 0ustar sergeisergei#include #ifdef BN_S_MP_SUB_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) { int olduse, res, min, max; /* find sizes */ min = b->used; max = a->used; /* init result */ if (c->alloc < max) { if ((res = mp_grow (c, max)) != MP_OKAY) { return res; } } olduse = c->used; c->used = max; { register mp_digit u, *tmpa, *tmpb, *tmpc; register int i; /* alias for digit pointers */ tmpa = a->dp; tmpb = b->dp; tmpc = c->dp; /* set carry to zero */ u = 0; for (i = 0; i < min; i++) { /* T[i] = A[i] - B[i] - U */ *tmpc = *tmpa++ - *tmpb++ - u; /* U = carry bit of T[i] * Note this saves performing an AND operation since * if a carry does occur it will propagate all the way to the * MSB. As a result a single shift is enough to get the carry */ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); /* Clear carry from T[i] */ *tmpc++ &= MP_MASK; } /* now copy higher words if any, e.g. if A has more digits than B */ for (; i < max; i++) { /* T[i] = A[i] - U */ *tmpc = *tmpa++ - u; /* U = carry bit of T[i] */ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); /* Clear carry from T[i] */ *tmpc++ &= MP_MASK; } /* clear digits above used (since we may not have grown result above) */ for (i = c->used; i < olduse; i++) { *tmpc++ = 0; } } mp_clamp (c); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_lshd.c0000644000175000017500000000277112663653207016207 0ustar sergeisergei#include #ifdef BN_MP_LSHD_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* shift left a certain amount of digits */ int mp_lshd (mp_int * a, int b) { int x, res; /* if its less than zero return */ if (b <= 0) { return MP_OKAY; } /* grow to fit the new digits */ if (a->alloc < a->used + b) { if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { return res; } } { register mp_digit *top, *bottom; /* increment the used by the shift amount then copy upwards */ a->used += b; /* top */ top = a->dp + a->used - 1; /* base */ bottom = a->dp + a->used - 1 - b; /* much like mp_rshd this is implemented using a sliding window * except the window goes the otherway around. Copying from * the bottom to the top. see bn_mp_rshd.c for more info. */ for (x = a->used - 1; x >= b; x--) { *top-- = *bottom--; } /* zero the lower digits */ top = a->dp; for (x = 0; x < b; x++) { *top++ = 0; } } return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_toradix_n.c0000644000175000017500000000367512663653207017250 0ustar sergeisergei#include #ifdef BN_MP_TORADIX_N_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* stores a bignum as a ASCII string in a given radix (2..64) * * Stores upto maxlen-1 chars and always a NULL byte */ int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen) { int res, digs; mp_int t; mp_digit d; char *_s = str; /* check range of the maxlen, radix */ if (maxlen < 2 || radix < 2 || radix > 64) { return MP_VAL; } /* quick out if its zero */ if (mp_iszero(a) == MP_YES) { *str++ = '0'; *str = '\0'; return MP_OKAY; } if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } /* if it is negative output a - */ if (t.sign == MP_NEG) { /* we have to reverse our digits later... but not the - sign!! */ ++_s; /* store the flag and mark the number as positive */ *str++ = '-'; t.sign = MP_ZPOS; /* subtract a char */ --maxlen; } digs = 0; while (mp_iszero (&t) == 0) { if (--maxlen < 1) { /* no more room */ break; } if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { mp_clear (&t); return res; } *str++ = mp_s_rmap[d]; ++digs; } /* reverse the digits of the string. In this case _s points * to the first digit [exluding the sign] of the number */ bn_reverse ((unsigned char *)_s, digs); /* append a NULL so the string is properly terminated */ *str = '\0'; mp_clear (&t); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_reverse.c0000644000175000017500000000146412663653210016224 0ustar sergeisergei#include #ifdef BN_REVERSE_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* reverse an array, used for radix code */ void bn_reverse (unsigned char *s, int len) { int ix, iy; unsigned char t; ix = 0; iy = len - 1; while (ix < iy) { t = s[ix]; s[ix] = s[iy]; s[iy] = t; ++ix; --iy; } } #endif tcl8.6.5/libtommath/bn_mp_mul_2.c0000644000175000017500000000347712663653207016277 0ustar sergeisergei#include #ifdef BN_MP_MUL_2_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* b = a*2 */ int mp_mul_2(mp_int * a, mp_int * b) { int x, res, oldused; /* grow to accomodate result */ if (b->alloc < a->used + 1) { if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { return res; } } oldused = b->used; b->used = a->used; { register mp_digit r, rr, *tmpa, *tmpb; /* alias for source */ tmpa = a->dp; /* alias for dest */ tmpb = b->dp; /* carry */ r = 0; for (x = 0; x < a->used; x++) { /* get what will be the *next* carry bit from the * MSB of the current digit */ rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); /* now shift up this digit, add in the carry [from the previous] */ *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK; /* copy the carry that would be from the source * digit into the next iteration */ r = rr; } /* new leading digit? */ if (r != 0) { /* add a MSB which is always 1 at this point */ *tmpb = 1; ++(b->used); } /* now zero any excess digits on the destination * that we didn't write to */ tmpb = b->dp + b->used; for (x = b->used; x < oldused; x++) { *tmpb++ = 0; } } b->sign = a->sign; return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_mod.c0000644000175000017500000000171612663653207016032 0ustar sergeisergei#include #ifdef BN_MP_MOD_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* c = a mod b, 0 <= c < b */ int mp_mod (mp_int * a, mp_int * b, mp_int * c) { mp_int t; int res; if ((res = mp_init (&t)) != MP_OKAY) { return res; } if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { mp_clear (&t); return res; } if (t.sign != b->sign) { res = mp_add (b, &t, c); } else { res = MP_OKAY; mp_exch (&t, c); } mp_clear (&t); return res; } #endif tcl8.6.5/libtommath/bn_mp_clamp.c0000644000175000017500000000204312663653207016341 0ustar sergeisergei#include #ifdef BN_MP_CLAMP_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* trim unused digits * * This is used to ensure that leading zero digits are * trimed and the leading "used" digit will be non-zero * Typically very fast. Also fixes the sign if there * are no more leading digits */ void mp_clamp (mp_int * a) { /* decrease used while the most significant digit is * zero. */ while (a->used > 0 && a->dp[a->used - 1] == 0) { --(a->used); } /* reset the sign flag if used == 0 */ if (a->used == 0) { a->sign = MP_ZPOS; } } #endif tcl8.6.5/libtommath/bn_mp_radix_smap.c0000644000175000017500000000127712663653207017404 0ustar sergeisergei#include #ifdef BN_MP_RADIX_SMAP_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* chars used in radix conversions */ const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; #endif tcl8.6.5/libtommath/bn_mp_set_int.c0000644000175000017500000000212412663653207016712 0ustar sergeisergei#include #ifdef BN_MP_SET_INT_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* set a 32-bit const */ int mp_set_int (mp_int * a, unsigned long b) { int x, res; mp_zero (a); /* set four bits at a time */ for (x = 0; x < 8; x++) { /* shift the number up four bits */ if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { return res; } /* OR in the top four bits of the source */ a->dp[0] |= (b >> 28) & 15; /* shift the source up to the next four bits */ b <<= 4; /* ensure that digits are not clamped off */ a->used += 1; } mp_clamp (a); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_expt_d.c0000644000175000017500000000237412663653207016537 0ustar sergeisergei#include #ifdef BN_MP_EXPT_D_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* calculate c = a**b using a square-multiply algorithm */ int mp_expt_d (mp_int * a, mp_digit b, mp_int * c) { int res, x; mp_int g; if ((res = mp_init_copy (&g, a)) != MP_OKAY) { return res; } /* set initial result */ mp_set (c, 1); for (x = 0; x < (int) DIGIT_BIT; x++) { /* square */ if ((res = mp_sqr (c, c)) != MP_OKAY) { mp_clear (&g); return res; } /* if the bit is set multiply */ if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) { if ((res = mp_mul (c, &g, c)) != MP_OKAY) { mp_clear (&g); return res; } } /* shift to next bit */ b <<= 1; } mp_clear (&g); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_read_radix.c0000644000175000017500000000405512663653207017354 0ustar sergeisergei#include #ifdef BN_MP_READ_RADIX_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* read a string [ASCII] in a given radix */ int mp_read_radix (mp_int * a, const char *str, int radix) { int y, res, neg; char ch; /* zero the digit bignum */ mp_zero(a); /* make sure the radix is ok */ if (radix < 2 || radix > 64) { return MP_VAL; } /* if the leading digit is a * minus set the sign to negative. */ if (*str == '-') { ++str; neg = MP_NEG; } else { neg = MP_ZPOS; } /* set the integer to the default of zero */ mp_zero (a); /* process each digit of the string */ while (*str) { /* if the radix < 36 the conversion is case insensitive * this allows numbers like 1AB and 1ab to represent the same value * [e.g. in hex] */ ch = (char) ((radix < 36) ? toupper ((unsigned char) *str) : *str); for (y = 0; y < 64; y++) { if (ch == mp_s_rmap[y]) { break; } } /* if the char was found in the map * and is less than the given radix add it * to the number, otherwise exit the loop. */ if (y < radix) { if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { return res; } if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { return res; } } else { break; } ++str; } /* if an illegal character was found, fail. */ if ( *str != '\0' ) { mp_zero( a ); return MP_VAL; } /* set the sign only if a != 0 */ if (mp_iszero(a) != 1) { a->sign = neg; } return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_toom_mul.c0000644000175000017500000001555612663653207017115 0ustar sergeisergei#include #ifdef BN_MP_TOOM_MUL_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* multiplication using the Toom-Cook 3-way algorithm * * Much more complicated than Karatsuba but has a lower * asymptotic running time of O(N**1.464). This algorithm is * only particularly useful on VERY large inputs * (we're talking 1000s of digits here...). */ int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) { mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2; int res, B; /* init temps */ if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &b0, &b1, &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) { return res; } /* B */ B = MIN(a->used, b->used) / 3; /* a = a2 * B**2 + a1 * B + a0 */ if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { goto ERR; } if ((res = mp_copy(a, &a1)) != MP_OKAY) { goto ERR; } mp_rshd(&a1, B); mp_mod_2d(&a1, DIGIT_BIT * B, &a1); if ((res = mp_copy(a, &a2)) != MP_OKAY) { goto ERR; } mp_rshd(&a2, B*2); /* b = b2 * B**2 + b1 * B + b0 */ if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) { goto ERR; } if ((res = mp_copy(b, &b1)) != MP_OKAY) { goto ERR; } mp_rshd(&b1, B); mp_mod_2d(&b1, DIGIT_BIT * B, &b1); if ((res = mp_copy(b, &b2)) != MP_OKAY) { goto ERR; } mp_rshd(&b2, B*2); /* w0 = a0*b0 */ if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) { goto ERR; } /* w4 = a2 * b2 */ if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) { goto ERR; } /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */ if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { goto ERR; } if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) { goto ERR; } if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) { goto ERR; } /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */ if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { goto ERR; } if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { goto ERR; } if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) { goto ERR; } /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */ if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { goto ERR; } if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) { goto ERR; } /* now solve the matrix 0 0 0 0 1 1 2 4 8 16 1 1 1 1 1 16 8 4 2 1 1 0 0 0 0 using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication */ /* r1 - r4 */ if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { goto ERR; } /* r3 - r0 */ if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { goto ERR; } /* r1/2 */ if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { goto ERR; } /* r3/2 */ if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { goto ERR; } /* r2 - r0 - r4 */ if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { goto ERR; } if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { goto ERR; } /* r1 - r2 */ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { goto ERR; } /* r3 - r2 */ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { goto ERR; } /* r1 - 8r0 */ if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { goto ERR; } /* r3 - 8r4 */ if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { goto ERR; } /* 3r2 - r1 - r3 */ if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { goto ERR; } if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { goto ERR; } if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { goto ERR; } /* r1 - r2 */ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { goto ERR; } /* r3 - r2 */ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { goto ERR; } /* r1/3 */ if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { goto ERR; } /* r3/3 */ if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { goto ERR; } /* at this point shift W[n] by B*n */ if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { goto ERR; } if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { goto ERR; } if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { goto ERR; } if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { goto ERR; } if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) { goto ERR; } ERR: mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &b0, &b1, &b2, &tmp1, &tmp2, NULL); return res; } #endif tcl8.6.5/libtommath/bn_mp_mul_2d.c0000644000175000017500000000357312663653207016440 0ustar sergeisergei#include #ifdef BN_MP_MUL_2D_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* shift left by a certain bit count */ int mp_mul_2d (const mp_int * a, int b, mp_int * c) { mp_digit d; int res; /* copy */ if (a != c) { if ((res = mp_copy (a, c)) != MP_OKAY) { return res; } } if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) { if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) { return res; } } /* shift by as many digits in the bit count */ if (b >= (int)DIGIT_BIT) { if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { return res; } } /* shift any bit count < DIGIT_BIT */ d = (mp_digit) (b % DIGIT_BIT); if (d != 0) { register mp_digit *tmpc, shift, mask, r, rr; register int x; /* bitmask for carries */ mask = (((mp_digit)1) << d) - 1; /* shift for msbs */ shift = DIGIT_BIT - d; /* alias */ tmpc = c->dp; /* carry */ r = 0; for (x = 0; x < c->used; x++) { /* get the higher bits of the current word */ rr = (*tmpc >> shift) & mask; /* shift the current word and OR in the carry */ *tmpc = ((*tmpc << d) | r) & MP_MASK; ++tmpc; /* set the carry to the carry bits of the current word */ r = rr; } /* set final carry */ if (r != 0) { c->dp[(c->used)++] = r; } } mp_clamp (c); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_cmp_d.c0000644000175000017500000000167512663653207016341 0ustar sergeisergei#include #ifdef BN_MP_CMP_D_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* compare a digit */ int mp_cmp_d(const mp_int * a, mp_digit b) { /* compare based on sign */ if (a->sign == MP_NEG) { return MP_LT; } /* compare based on magnitude */ if (a->used > 1) { return MP_GT; } /* compare the only digit of a to b */ if (a->dp[0] > b) { return MP_GT; } else if (a->dp[0] < b) { return MP_LT; } else { return MP_EQ; } } #endif tcl8.6.5/libtommath/bn_mp_init_set.c0000644000175000017500000000135612663653207017071 0ustar sergeisergei#include #ifdef BN_MP_INIT_SET_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* initialize and set a digit */ int mp_init_set (mp_int * a, mp_digit b) { int err; if ((err = mp_init(a)) != MP_OKAY) { return err; } mp_set(a, b); return err; } #endif tcl8.6.5/libtommath/bn_mp_karatsuba_sqr.c0000644000175000017500000000562512663653207020120 0ustar sergeisergei#include #ifdef BN_MP_KARATSUBA_SQR_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* Karatsuba squaring, computes b = a*a using three * half size squarings * * See comments of karatsuba_mul for details. It * is essentially the same algorithm but merely * tuned to perform recursive squarings. */ int mp_karatsuba_sqr (mp_int * a, mp_int * b) { mp_int x0, x1, t1, t2, x0x0, x1x1; int B, err; err = MP_MEM; /* min # of digits */ B = a->used; /* now divide in two */ B = B >> 1; /* init copy all the temps */ if (mp_init_size (&x0, B) != MP_OKAY) goto ERR; if (mp_init_size (&x1, a->used - B) != MP_OKAY) goto X0; /* init temps */ if (mp_init_size (&t1, a->used * 2) != MP_OKAY) goto X1; if (mp_init_size (&t2, a->used * 2) != MP_OKAY) goto T1; if (mp_init_size (&x0x0, B * 2) != MP_OKAY) goto T2; if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY) goto X0X0; { register int x; register mp_digit *dst, *src; src = a->dp; /* now shift the digits */ dst = x0.dp; for (x = 0; x < B; x++) { *dst++ = *src++; } dst = x1.dp; for (x = B; x < a->used; x++) { *dst++ = *src++; } } x0.used = B; x1.used = a->used - B; mp_clamp (&x0); /* now calc the products x0*x0 and x1*x1 */ if (mp_sqr (&x0, &x0x0) != MP_OKAY) goto X1X1; /* x0x0 = x0*x0 */ if (mp_sqr (&x1, &x1x1) != MP_OKAY) goto X1X1; /* x1x1 = x1*x1 */ /* now calc (x1+x0)**2 */ if (s_mp_add (&x1, &x0, &t1) != MP_OKAY) goto X1X1; /* t1 = x1 - x0 */ if (mp_sqr (&t1, &t1) != MP_OKAY) goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */ /* add x0y0 */ if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY) goto X1X1; /* t2 = x0x0 + x1x1 */ if (s_mp_sub (&t1, &t2, &t1) != MP_OKAY) goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */ /* shift by B */ if (mp_lshd (&t1, B) != MP_OKAY) goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))< #ifdef BN_MP_ZERO_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* set to zero */ void mp_zero (mp_int * a) { int n; mp_digit *tmp; a->sign = MP_ZPOS; a->used = 0; tmp = a->dp; for (n = 0; n < a->alloc; n++) { *tmp++ = 0; } } #endif tcl8.6.5/libtommath/bn_fast_s_mp_sqr.c0000644000175000017500000000542712663653207017422 0ustar sergeisergei#include #ifdef BN_FAST_S_MP_SQR_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* the jist of squaring... * you do like mult except the offset of the tmpx [one that * starts closer to zero] can't equal the offset of tmpy. * So basically you set up iy like before then you min it with * (ty-tx) so that it never happens. You double all those * you add in the inner loop After that loop you do the squares and add them in. */ int fast_s_mp_sqr (mp_int * a, mp_int * b) { int olduse, res, pa, ix, iz; mp_digit W[MP_WARRAY], *tmpx; mp_word W1; /* grow the destination as required */ pa = a->used + a->used; if (b->alloc < pa) { if ((res = mp_grow (b, pa)) != MP_OKAY) { return res; } } /* number of output digits to produce */ W1 = 0; for (ix = 0; ix < pa; ix++) { int tx, ty, iy; mp_word _W; mp_digit *tmpy; /* clear counter */ _W = 0; /* get offsets into the two bignums */ ty = MIN(a->used-1, ix); tx = ix - ty; /* setup temp aliases */ tmpx = a->dp + tx; tmpy = a->dp + ty; /* this is the number of times the loop will iterrate, essentially while (tx++ < a->used && ty-- >= 0) { ... } */ iy = MIN(a->used-tx, ty+1); /* now for squaring tx can never equal ty * we halve the distance since they approach at a rate of 2x * and we have to round because odd cases need to be executed */ iy = MIN(iy, (ty-tx+1)>>1); /* execute loop */ for (iz = 0; iz < iy; iz++) { _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); } /* double the inner product and add carry */ _W = _W + _W + W1; /* even columns have the square term in them */ if ((ix&1) == 0) { _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]); } /* store it */ W[ix] = (mp_digit)(_W & MP_MASK); /* make next carry */ W1 = _W >> ((mp_word)DIGIT_BIT); } /* setup dest */ olduse = b->used; b->used = a->used+a->used; { mp_digit *tmpb; tmpb = b->dp; for (ix = 0; ix < pa; ix++) { *tmpb++ = W[ix] & MP_MASK; } /* clear unused digits [that existed in the old copy of c] */ for (; ix < olduse; ix++) { *tmpb++ = 0; } } mp_clamp (b); return MP_OKAY; } #endif tcl8.6.5/libtommath/bn_mp_cmp_mag.c0000644000175000017500000000222512663653207016652 0ustar sergeisergei#include #ifdef BN_MP_CMP_MAG_C /* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ /* compare maginitude of two ints (unsigned) */ int mp_cmp_mag (const mp_int * a, const mp_int * b) { int n; mp_digit *tmpa, *tmpb; /* compare based on # of non-zero digits */ if (a->used > b->used) { return MP_GT; } if (a->used < b->used) { return MP_LT; } /* alias for a */ tmpa = a->dp + (a->used - 1); /* alias for b */ tmpb = b->dp + (a->used - 1); /* compare based on digits */ for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { if (*tmpa > *tmpb) { return MP_GT; } if (*tmpa < *tmpb) { return MP_LT; } } return MP_EQ; } #endif tcl8.6.5/ChangeLog.20030000644000175000017500000037661512663660064013745 0ustar sergeisergei2003-12-25 Mo DeJong * win/tclWin32Dll.c (DllMain): Add HAVE_NO_SEH blocks in place of __try and __except statements to support gcc builds. This is needed after David's changes on 2003-12-21. [Patch 858493] 2003-12-23 David Gravereaux * generic/tclAlloc.c: All uses of 'panic' (the macro) changed to * generic/tclBasic.c: 'Tcl_Panic' (the function). The #define of * generic/tclBinary.c: panic in tcl.h clearly states it is deprecated * generic/tclCkalloc.c: in the comments. [Patch 865264] * generic/tclCmdAH.c: * generic/tclCmdIL.c: * generic/tclCmdMZ.c: * generic/tclCompCmds.c: * generic/tclCompExpr.c: * generic/tclCompile.c: * generic/tclConfig.c: * generic/tclDictObj.c: * generic/tclEncoding.c: * generic/tclEvent.c: * generic/tclExecute.c: * generic/tclHash.c: * generic/tclInterp.c: * generic/tclIO.c: * generic/tclIOCmd.c: * generic/tclIOUtil.c: * generic/tclListObj.c: * generic/tclLiteral.c: * generic/tclNamesp.c: * generic/tclObj.c: * generic/tclParse.c: * generic/tclPathObj.c: * generic/tclPkg.c: * generic/tclPreserve.c: * generic/tclProc.c: * generic/tclStringObj.c: * generic/tclTest.c: * generic/tclThreadAlloc.c: * generic/tclTimer.c: * generic/tclTrace.c: * generic/tclVar.c: * mac/tclMacChan.c: * mac/tclMacOSA.c: * mac/tclMacResource.c: * mac/tclMacSock.c * mac/tclMacThrd.c: * unix/tclUnixChan.c: * unix/tclUnixNotfy.c: * unix/tclUnixThrd.c: * unix/tclXtNotify.c: * win/tclWin32Dll.c: * win/tclWinChan.c: * win/tclWinFCmd.c: * win/tclWinNotify.c: * win/tclWinPipe.c: * win/tclWinSock.c: * win/tclWinThrd.c: * generic/tclInt.h: Deprecated use of Tcl_Ckalloc changed to Tcl_Alloc in the TclAllocObjStorage macro. 2003-12-22 David Gravereaux * win/nmakehlp.c: * win/rules.vc: New feature for extensions that use rules.vc. Now reads header files for version strings. No more hard coding TCL_VERSION = 8.5 and having to edit it when you swap cores. * win/makefile.vc: VERSION macro now set by reading tcl.h for it. * generic/tcl.h: Removed note that makefile.vc needs to have a version number changed. 2003-12-21 David Gravereaux * win/tclWin32Dll.c: Structured Exception Handling added around Tcl_Finalize called from DllMain's DLL_PROCESS_DETACH. We can't be 100% assured that Tcl is being unloaded by the OS in a stable condition and we need to protect the exit handlers should the stack be in a hosed state. AT&T style assembly for SEH under MinGW has not been added yet. This is a first part change for [Patch 858493] 2003-12-17 Daniel Steffen * generic/tclBinary.c (DeleteScanNumberCache): fixed crashing bug when numeric scan-value cache contains NULL value. 2003-12-17 Vince Darley * generic/tclCmdAH.c: * unix/tclUnixFile.c: * win/tclWinFCmd.c: * tests/fCmd.test: * tests/fileSystem.test: * doc/file.n: final fix to support for relative links and its implications on normalization and other parts of the filesystem code. Fixes [Bug 859251] and some Windows problems with recursive file delete/copy and symbolic links. 2003-12-17 Vince Darley * generic/tclPathObj.c: * tests/fileSystem.test: fix and tests for [Bug 860402] in new file normalization code. 2003-12-17 Zoran Vasiljevic * generic/tclIOUtil.c: fixed 2 memory (object) leaks. [Bug 839519] * generic/tclPathObj.c: fixed Tcl_FSGetTranslatedPath to always return properly refcounted path object. [Bug 861515] 2003-12-16 Vince Darley * tests/fCmd.test: marking fCmd-9.14.2, as nonPortable, since on Solaris one can change the name of the current directory with 'file rename'. * doc/FileSystem.3: clarified documentation on ownership of return objects/strings of some Tcl_FS* calls. 2003-12-16 Donal K. Fellows * generic/tclThreadAlloc.c (binfo): Made variable file-local. 2003-12-15 David Gravereaux * win/tcl.rc: * win/tclsh.rc: Slight modification to the STRINGIFY macro to support Borland's rc tool. * win/tclWinFile.c (TclpUtime) : utimbuf struct not a problem with Borland. * win/tclWinTime.c (TclpGetDate) : Borland's localtime() has a slight behavioral difference. From Helmut Giese [Patch 758097]. 2003-12-14 David Gravereaux * generic/tclInt.decls: commented-out entry for TclpCheckStackSpace, removing it from the Stubs table. It's already declared in tclInt.h and labeled as a function that is not to be exported. Regened tables. 2003-12-14 Donal K. Fellows * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): TIP#75 Implementation * tests/switch.test: Can now get submatch information when using * doc/switch.n: -regexp matching in [switch]. 2003-12-14 Vince Darley * generic/tclPathObj.c: complete rewrite of generic file normalization code to cope with links followed by '..'. [Bug 849514], and parts of [Bug 859251] 2003-12-12 David Gravereaux * win/tclWinChan.c: Win32's SetFilePointer() takes LONGs not DWORDs (a signed/unsigned mismatch). Redid local vars to avoid all casting except where truly required. 2003-12-12 Vince Darley * generic/tclCmdAH.c: fix to normalization of non-existent user name ('file normalize ~nobody') [Bug 858937] * doc/file.n: clarify behaviour of 'file link' when the target is not an absolute path. * doc/filename.n: correct documentation to say that Windows Tcl does handle '~user', for recent Windows releases, and clarified distinction between MacOS 'classic' and MacOS X. * doc/glob.n: clarification of glob's behaviour when returning filenames starting with a '~'. * tests/fileSystem.test: * tests/fileName.test: new tests added for the normalization problem above and other recentlt reported issues. * win/tclWinFile.c: corrected unclear comments * unix/tclUnixFile.c: allow creation of relative links. [Bug 833713] 2003-12-11 David Gravereaux * win/tclWinSock.c (SocketThreadExitHandler) : added a TerminateThread fallback just in case the socket handler thread is really in a paused state. This can happen when Tcl is being unloaded by the OS from an exception handler. See MSDN docs on DllMain, it states this behavior. 2003-12-09 Jeff Hobbs * unix/configure: * unix/tcl.m4: updated OpenBSD build configuration based on [Patch #775246] (cassoff) 2003-12-09 Donal K. Fellows * unix/tclUnixPort.h: #ifdef'd out declarations of errno which are * tools/man2tcl.c: known to cause problems with recent glibc. [Bug 852369] 2003-12-09 Vince Darley * win/tclWinFile.c: fix to NT file permissions code [Bug 855923] * tests/winFile.test: added tests for NT file permissions - patch and test scripts supplied by Benny. * tests/winFCmd.test: fixed one test for when not running in C:/ 2003-12-02 Donal K. Fellows * generic/tclBinary.c (DeleteScanNumberCache, ScanNumber): Made the numeric scan-value cache have proper references to the objects within it so strange patterns of writes won't cause references to freed objects. Thanks to Paul Obermeir for the report. [Bug 851747] 2003-12-01 Miguel Sofer * doc/lset.n: fix typo [Bug 852224] 2003-11-24 Don Porter * generic/tclParse.c: Corrected faulty check for trailing white space in {expand} parsing. Thanks Andreas Leitgeb. [Bug 848262] * tests/parse.test: New tests for the bug. 2003-11-24 Vince Darley * generic/tclPathObj.c: fix to [Bug 845778] - Infinite recursion on [cd] (Windows only bug), for which new tests have just been added. 2003-11-21 Don Porter * tests/winFCmd.test (winFCmd-16.10,11): Merged new tests from core-8-4-branch. 2003-11-20 Miguel Sofer * generic/tclVar.c: fix flag bit collision between LOOKUP_FOR_UPVAR and TCL_PARSE_PART1 (deprecated) [Bug 835020] 2003-11-19 Don Porter * tests/compile.test (compile-16.22.0): Improved test for the recent fix for Bug 845412. 2003-11-19 Donal K. Fellows * generic/tclCompile.c (TclCompileScript): Added a guard for the expansion code so that long non-expanding commands don't get expansion infrastructure inserted in them, especially when that infrastructure isn't initialised. [Bug 845412] 2003-11-18 David Gravereaux * contrib/djgpp/Makefile: Changes from Victor Wagner * contrib/djgpp/langinfo.c (new): for better * contrib/djgpp/langinfo.h (new): DJGPP support. * unix/tclUnixInit.c: . * unix/tclUnixChan.c: . * unix/tclUnixFCmd.c: . 2003-11-17 Don Porter * tests/reg.test: Added tests for [Bugs 230589, 504785, 505048, 840258] recently fixed by 2003-11-15 commit to regcomp.c by Pavel Goran. His notes on the fix: This bug results from an error in code that splits states into "progress" and "no-progress" ones. This error causes an interesting situation with the pre-collected single-linked list of states to be splitted: many items were added to the list, but only several of them are accessible from the list beginning, since the "tmp" member of struct state (which is used here to hold a pointer to the next list item) gets overwritten, which results in a "looped" chain. As a result, not all of states are splitted, and one state is splitted two times, causing incorrect "no-progress" flag values. 2003-11-16 Donal K. Fellows * generic/tclExecute.c (TclExecuteByteCode): Make sure that Tcl_AsyncInvoke is called regularly when processing bytecodes. * generic/tclTest.c (AsyncThreadProc, TestasyncCmd): Extended testing harness to send an asynchronous marking without relying on UNIX signals. * tests/async.test (async-4.*): Tests to check that async events are handled by the bytecode core. [Bug 746722] 2003-11-15 Donal K. Fellows * generic/tclTest.c (TestHashSystemHashCmd): Removed 'const' modifier from hash type structure; it should be const and the hash code assumes it behaves like const, but that's not how the API is defined. Like this, we are following in the same footsteps as Tcl_RegisterObjType() which has the same conditions on its argument. Stops VC++5.2 warning. [Bug 842511] 2003-11-14 Donal K. Fellows * generic/tclHash.c (Tcl_DeleteHashTable,Tcl_HashStats,RebuildTable): * generic/tclTest.c (TestHashSystemHashCmd): TIP#138 implementation, * tests/misc.test: plus a new chunk of stuff to test the hash functions more thoroughly in the test suite. [Patch 731356, modified] * doc/Tcl.n: Updated Tcl version number and changebars. 2003-11-14 Don Porter * doc/ParseCmd.3: Implementation of TIP 157. Adds recognition * doc/Tcl.n: of the new leading {expand} syntax on words. * generic/tcl.h: Parses such words as the new Tcl_Token type * generic/tclBasic.c: TCL_TOKEN_EXPAND_WORD. Updated Tcl_EvalEx and * generic/tclCompile.c: the bytecode compiler/execution engine to * generic/tclCompile.h: recognize the new token type. New opcodes * generic/tclExecute.c: INST_LIST_VERIFY and INST_INVOKE_EXP and a new * generic/tclParse.c: operand type OPERAND_ULIST1 are defined. Docs * generic/tclTest.c: and tests are included. * tests/basic.test: * tests/compile.test: * tests/parse.test: * library/auto.tcl: Replaced several [eval]s used to perform * library/package.tcl: argument expansion with the new syntax. In the * library/safe.tcl: test files lindex.test and lset.test, replaced * tests/cmdInfo.test: use of [eval] to force direct string * tests/encoding.test: evaluation with use of [testevalex] which more * tests/execute.test: directly and robustly serves the same purpose. * tests/fCmd.test: * tests/http.test: * tests/init.test: * tests/interp.test: * tests/io.test: * tests/ioUtil.test: * tests/iogt.test: * tests/lindex.test: * tests/lset.test: * tests/namespace-old.test: * tests/namespace.test: * tests/pkg.test: * tests/pkgMkIndex.test: * tests/proc.test: * tests/reg.test: * tests/trace.test: * tests/upvar.test: * tests/winConsole.test: * tests/winFCmd.test: 2003-11-12 Jeff Hobbs * tests/cmdMZ.test (cmdMZ-1.4): change to nonPortable as more systems are using permissions caching, and this isn't really a Tcl controlled issue. 2003-11-11 Jeff Hobbs * unix/configure: * unix/tcl.m4: improve AIX --enable-64bit handling remove -D__NO_STRING_INLINES -D__NO_MATH_INLINES from CFLAGS_OPTIMIZE on Linux. Make default opt -O2 (was -O). 2003-11-11 David Gravereaux * contrib/djgpp/Makefile: Suggested changes from vitus@45.free.net (Victor Wagner) * unix/tclUnixPort.h: added socklen_t typedef for DJGPP 2003-11-10 Don Porter * unix/tclUnixInit.c (TclpInitLibraryPath): * win/tclWinInit.c (TclpInitLibraryPath): Fix for [Bug 832657] that should not run afoul of startup constraints. * library/dde/pkgIndex.tcl: Added safeguards so that registry and * library/reg/pkgIndex.tcl: dde packages are not offered on * win/tclWinDde.c: non-Windows platforms. Bumped to * win/tclWinReg.c: registry 1.1.3 and dde 1.3. * win/Makefile.in: * win/configure.in: * win/makefile.bc: * win/makefile.vc: * win/configure: autoconf (2.57) 2003-11-10 Donal K. Fellows * tests/cmdIL.test: Stopped cmdIL-5.5 from stomping over the test command, and updated the tests to use some tcltest2 features in relation to cleanup. [Bug 838384] 2003-11-10 Vince Darley * generic/tclCmdAH.c: * tests/fCmd.test: fix to misleading error message in 'file link'. [Bug 836208] 2003-11-07 Vince Darley * generic/tclIOUtil.c: fix to compiler warning/error with some compilers. [Bug 835918] 2003-11-07 Daniel Steffen * macosx/Makefile: optimized builds define NDEBUG to turn off ThreadAlloc range checking. 2003-11-05 Don Porter * tests/unixInit.test (unixInit-2.10): New test to expose [Bug 832657] failure of TclpInitLibraryPath() to properly handle .. in the path of the executable. 2003-11-04 Daniel Steffen * macosx/Makefile: added 'test' target. 2003-11-03 Vince Darley * generic/tclIOUtil.c * generic/tclInt.h: added comments and re-arranged code to clarify distinction between Tcl_LoadHandle, ClientData for 'load'ed code, and point out limitations of the design introduced with Tcl 8.4. * unix/tclUnixFile.c: fix to memory leak * generic/tclCmdIL.c: removed warning on Windows. 2003-11-01 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LrepeatObjCmd): Check for sensible list lengths and allow for soft failure of the memory subsystem in the [lconcat] command [Bug 829027]. Uses direct list creation to avoid extra copies when working near the limit of available memory. Also reorganized to encourage optimizing compilers to optimize heavily. * generic/tclListObj.c (TclNewListObjDirect): New list constructor that does not copy the array of objects. Useful for creating potentially very large lists or where you are about to throw away the array argument which is being used in its entirety. 2003-10-28 Miguel Sofer * generic/tclExecute.c (NEXT_INST macros): replaced macro variable "result" by "resultHandling" to avoid confusion. 2003-10-23 Andreas Kupries * unix/tclUnixChan.c (Tcl_MakeFileChannel): Applied [Patch 813606] fixing [Bug 813087]. Detection of sockets was off for Mac OS X which implements pipes as local sockets. The new code ensures that only IP sockets are detected as such. * win/tclWinSock.c (TcpWatchProc): Watch for FD_CLOSE too when asked for writable events by the generic layer. (SocketEventProc): Generate a writable event too when a close is detected. Together the changes fix [Bug 599468]. 2003-10-23 Vince Darley * tests/resource.test: * mac/tclMacResource.c: fix to resource freeing problem in 'resource' command reported by Bernard Desgraupes. * doc/FileSystem.3: updated documentation for 'glob' fix on 2003-10-13 below 2003-10-22 Donal K. Fellows * generic/tclCmdAH.c (Tcl_FileObjCmd): Changed FILE_ prefix to FCMD_ to stop symbol/#def clashes on Cygwin/Mingw32 on NT. [Bug 822528] 2003-10-21 Daniel Steffen * tools/tcltk-man2html.tcl: fixed incorrect html generated for .IP/.TP lists, now use
    ...
    ...

    ...
    ...
    instead of illegal

    ...
    ...

    ...
    ...
    . Added skipping of directives directly after .TP to avoid them being used as item descriptions, e.g. .TP\n.VS in clock.n. 2003-10-21 Andreas Kupries * win/tclWinPipe.c (BuildCommandLine): Applied the patch coming with [Bug 805605] to the code, fixing the incorrect use of ispace noted by Ronald Dauster . 2003-10-20 Kevin B. Kenny * doc/msgcat.n: * library/msgcat/msgcat.tcl (mclocale,mcload): * tools/tcl.wse.in: * unix/Makefile.in: Implementation of TIP#156, add a "root locale" * win/makefile.bc: to the 'msgcat' package. Advanced msgcat * win/Makefile.in: version number to 1.4 * win/Makefile.vc: 2003-10-15 Donal K. Fellows * generic/tclCmdIL.c (SortInfo,etc): Reorganized so that SortInfo carries an array of integer indices instead of a Tcl list. This nips shimmering problems in the bud and simplifies SelectObjFromSublist at the cost of making setup slightly more complex. [Bug 823768] 2003-10-14 David Gravereaux * win/tclAppInit.c (sigHandler): Punt gracefully if exitToken has already been destroyed. 2003-10-14 Vince Darley * generic/tclCmdMZ.c: * tests/regexp.test: fix to [Bug 823524] in regsub; added three new tests. 2003-10-14 Don Porter * generic/tclBasic.c (TclAppendObjToErrorInfo): New internal routine that appends a Tcl_Obj to the errorInfo, saving the caller the trouble of extracting the string rep. * generic/tclStringObj.c (TclAppendLimitedToObj): New internal routine that supports truncated appends with optional ellipsis marking. This single routine supports UTF-8-safe truncated appends needed in several places throughout the Tcl source code, mostly for error and stack messages. Clean fix for [Bug 760872]. * generic/tclInt.h: Declarations for new internal routines. * generic/tclCmdMZ.c: Updated callers to use the new routines. * generic/tclCompExpr.c: * generic/tclCompile.c: * generic/tclExecute.c: * generic/tclIOUtil.c: * generic/tclNamesp.c: * generic/tclObj.c: * generic/tclParseExpr.c: * generic/tclProc.c: * generic/tclStringObj.c: * mac/tclMacResource.c: * library/init.tcl: Updated ::errorInfo cleanup in [unknown] to reflect slight modifications to Tcl_LogCommandInfo(). Corrects failing init-4.* tests. 2003-10-14 Donal K. Fellows TIP#127 IMPLEMENTATION FROM JOE MICHAEL SCHLENKER * generic/tclCmdIL.c (SelectObjFromSublist): Element selection engine. * generic/tclCmdIL.c (Tcl_LsearchObjCmd, Tcl_LsortObjCmd): * tests/lsearch.test: Set up and use of element selection engine, * tests/cmdIL.test: plus tests and documentation. * doc/lsearch.n: Based on [Patch 693836] * doc/lsort.n: 2003-10-13 Vince Darley * generic/tcl.h: * generic/tclFileName.c: * generic/tclIOUtil.c: * generic/tclPathObj.c: * generic/tclTest.c: * mac/tclMacFile.c: * tests/fileName.test: better tests for [Bug 813273] * unix/tclUnixFCmd.c: * unix/tclUnixFile.c: * win/tclWin32Dll.c: * win/tclWinFCmd.c: * win/tclWinFile.c: * win/tclFileInt.h: Fixed [Bug 800106] in which 'glob' was incapable of merging the results of a directory listing (real or virtual) and any virtual filesystem mountpoints in that directory (the latter were ignored). This meant boundaries between different filesystems were not seamless (e.g. 'glob */*' across a filesystem boundary was wrong). Added new entry to Tcl_GlobTypeData in a totally backwards compatible way. To allow listing of mounts, registered filesystems must support the 'TCL_GLOB_TYPE_MOUNT' flag. If this is not supported (e.g. in tclvfs 1.2) then mounts will simply not be listed for that filesystem. Fixed [Bug 749876] 'file writable/readable/etc' (NativeAccess) using correct permission checking code for Windows NT/2000/XP where more complex user-based security/access priveleges are available, particularly on shared volumes. The performance impact of this extra checking will need further investigation. Note: Win 95,98,ME have no support for this. Also made better use of normalized rather than translated paths in the platform specific code. 2003-10-12 Jeff Hobbs * unix/tclUnixTest.c (TestalarmCmd): don't bother checking return value of alarm. [Bug #664755] (english) 2003-10-09 Pat Thoyts * win/makefile.vc: Applied patches for bug #801467 by Joe Mistachkin * win/tclAppInit.c: to fix incompatible TCL_MEM_DEBUG handling in * generic/tclObj.c: Win32 VC builds. 2003-10-08 Don Porter * generic/tclBasic.c: Save and restore the iPtr->flag bits that control the state of errorCode and errorInfo management when calling "leave" execution traces, so that all error information of the traced command is still available whether traced or not. [Bug 760947] Thanks to Yahalom Emet. 2003-10-08 Donal K. Fellows * generic/tclTest.c (TestNumUtfCharsCmd): Command to allow finer access to Tcl_NumUtfChars for testing. * generic/tclUtf.c (Tcl_NumUtfChars): Corrected string length determining when the length parameter is negative; the terminator is a zero byte, not (necessarily) a \u0000 character. [Bug 769812] 2003-10-07 Don Porter * tests/cmdAH.test: * tests/exec.test: Corrected temporary file management * tests/fileSystem.test: issues uncovered by -debug 1 test * tests/io.test: operations. Also backported some * tests/ioCmd.test: other fixes from the HEAD. * tests/main.test: * tests/pid.test: [Bugs 675605, 675655, 675659] * tests/socket.test: * tests/source.test: * tests/fCmd.test: Run tests with the [temporaryDirectory] as the current directory, so that tests can depend on ability to write files. [Bug 575837] * doc/OpenFileChnl.3: Updated Tcl_Tell and Tcl_Seek documentation to reflect that they now return Tcl_WideInt (TIP 72). [Bug 787537] * tests/io.test: Corrected several tests that failed when paths * tests/ioCmd.test: included regexp-special chars. [Bug 775394] 2003-10-06 Jeff Hobbs * win/configure: * win/tcl.m4: removed incorrect checks for existence of optimization. TCL_CFG_OPTIMIZED is now defined whenever the user does not build with --enable-symbols. 2003-10-06 Don Porter * tests/regexp.test: Matched [makeFile] with [removeFile]. * tests/regexpComp.test: [Bug 675652] * tests/fCmd.test (fCmd-8.2): Test only that tilde-substitution happens, not for any particular result. [Bug 685991] * unix/tcl.m4 (SC_PATH_TCLCONFIG): Corrected search path so that alpha and beta releases of Tcl are not favored. [Bug 608698] * tests/reg.test: Corrected duplicate test names. * tests/resource.test: [Bugs 710370, 710358] * tests/dict.test: * tests/dict.test: Updated [package require tcltest] lines to * tests/fileSystem.test: indiciate that these test files * tests/lrepeat.test: use features of tcltest 2. [Bug 706114] * tests/notify.test: * tests/parseExpr.test: * tests/unixNotfy.test: * tests/winDde.test: 2003-10-04 Miguel Sofer * generic/tclExecute.c (TEBC): * tests/execute.test (execute-8.2): fix for [Bug 816641] - faulty execution and catch stack management. 2003-10-03 Don Porter * generic/tclBasic.c: Fixed error in ref count management of command * generic/tclCmdMZ.c: and execution traces that caused access to freed memory in trace-32.1. [Bug 811483] 2003-10-02 Don Porter * generic/tclTrace.c: Corrected comingling of introspection results of [trace info command] and [trace info execution]. [Bug 807243] Thanks to Mark Saye. 2003-10-01 Daniel Steffen * macosx/Makefile: fixed redo prebinding bug when DESTDIR="". * mac/tclMacResource.c: fixed possible NULL dereference (bdesgraupes). 2003-09-29 Vince Darley * generic/tclPathObj.c: * tests/fileName.test: fix to inconsistent handling of backslash path separators on Windows in 'file join' [Bug 813273] 2003-09-29 Donal K. Fellows * generic/tclPathObj.c (TclNativePathInFilesystem,TclFSGetPathType): * generic/tclIOUtil.c (TclNativeDupInternalRep,TclGetPathType): Rename to make sure function names won't interfere with other non-Tcl code (reported by George Staplin) TIP#121 IMPLEMENTATION FROM JOE MISTACHKIN * generic/tclEvent.c (Tcl_SetExitProc,Tcl_Exit): Implementation of application exit handler scheme. * generic/tcl.decls (Tcl_SetExitProc): Public declaration. * doc/Exit.3: Documentation of new API function. TIP#112 IMPLEMENTATION * generic/tclNamesp.c: Core of implementation. * generic/tclInt.h (Namespace,TclInvalidateNsCmdLookup): Add command list epoch counter and list of ensembles to namespace structure, and define a macro to ease update of the epoch counter. * generic/tclBasic.c (Tcl_CreateObjCommand,etc.): Update epoch counter when list of commands in a namespace changes. * generic/tclObj.c (TclInitObjSubsystem): Register ensemble subcommand type. * tests/namespace.test (42.1-47.6): Tests. * doc/namespace.n: Documentation. * library/http/http.tcl (geturl): Correctly check the type of boolean-valued options. [Bug 811170] * unix/tcl.m4 (SC_ENABLE_FRAMEWORK): Added note to make it clearer that this is an OSX feature, not a general Unix feature. [Bug 619440] 2003-09-28 David Gravereaux * win/tclWinPipe.c: The windows port of expect can call TclWinAddProcess before any of the other pipe functions. Added a missing PipeInit() call to make sure the initialization happens. 2003-09-25 Daniel Steffen * macosx/Makefile: ensure SYMROOT exists if OBJROOT is overridden on command line. Replaced explict use of /usr/bin by ${BINDIR}. 2003-09-24 Vince Darley * library/package.tcl (tcl::MacPkgUnknown, tcl::MacOSXPkgUnknown): Minor performance tweaks to reduce the number of [file] invocations. Meant to improve startup times, at least a little bit. (The generic equivalent patch was applied on 2003-02-21). 2003-09-24 Vince Darley * trace.test: removed 'knownBug' from a test which doesn't illustrate a bug, just a bad test. 2003-09-23 Miguel Sofer * generic/tclExecute.c: * generic/tclInt.h: changed the evaluation-stack addressing mode, from array-style to pointer-style; the catch stack and evaluation stack are now contiguous in memory. [Patch 457449] 2003-09-23 Don Porter * tests/trace.test (trace-31,32-*): Added tests for [Bug 807243] and [Bug 811483]. * library/init.tcl (auto_load, auto_import): Expanded Eric Melski's 2000-01-28 fix for [Bug 218871] to all potentially troubled uses of [info commands] on input data, where glob-special characters could cause problems. 2003-09-20 Donal K. Fellows * tests/expr.test (expr-23.4): Prevented accidental wrapping round of exponential operation; it isn't portable, and not what I intended to test either. [Bug 808244] 2003-09-19 Miguel Sofer * generic/tclExecute.c: adding (DE)CACHE_STACK_INFO() pairs to protect all calls that may cause traces on ::errorInfo or ::errorCode to corrupt the stack. [Bug 804681] 2003-09-17 Vince Darley * tclPathObj.c: fix to test-suite problem introduced by the bug fix below. No problem in ordinary code, just test suite code which manually adjusts tclPlatform. [Bug 808247] 2003-09-16 Vince Darley * doc/filename.n: documentation of Windows-specific feature as discussed in [Bug 541989] * generic/tclPathObj.c: fix for normalization of volume-relative paths [Bug 767834] * tests/winFCmd.test: new tests for both of the above. * tests/cmdAH.test: fix for AFS problem in test suite [Bug 748960] 2003-09-13 Donal K. Fellows TIP#123 IMPLEMENTATION BASED ON WORK BY ARJEN MARKUS * generic/tclCompile.h (INST_EXPON): Implementation of * generic/tclCompile.c (tclInstructionTable): exponential operator. * generic/tclCompExpr.c (operatorTable): * generic/tclParseExpr.c (ParseExponentialExpr, GetLexeme): * generic/tclExecute.c (TclExecuteByteCode, ExponWide, ExponLong): (IllegalExprOperandType): * tests/expr.test: * tests/compExpr-old.test: * doc/expr.n: 2003-09-10 Don Porter * library/opt/optparse.tcl: Latest revisions caused [OptGuessType] to guess "int" instead of "string" for empty strings. Missed the required "-strict" option to [string is]. Thanks to Revar Desmera. [Bug 803968] 2003-09-08 David Gravereaux * win/tclWinLoad.c (TclpDlopen): Changed the error message for ERROR_PROC_NOT_FOUND to be a bit more helpful in giving us clues. "can't find specified procedure" means a function in the import table, for implicit loading, couldn't be resolved and that's why the load failed. 2003-09-04 Don Porter * doc/Tcl_Main.3: * doc/FileSystem.3: Implementation of * doc/source.n: TIPs 137/151. Adds a * doc/tclsh.1: -encoding option to * generic/tcl.decls: the [source] command * generic/tclCmdMZ.c (Tcl_SourceObjCmd): and a new C routine, * generic/tclIOUtil.c (Tcl_FSEvalFileEx): Tcl_FSEvalFileEx(), * generic/tclMain.c (Tcl_Main): that provides C access * mac/tclMacResource.c (Tcl_MacSourceObjCmd): to the same function. * tests/cmdMZ.test: Also adds command line * tests/main.test: option handling in Tcl_Main() so that tclsh * tests/source.test: and other apps built on Tcl_Main() respect a -encoding command line option before a script filename. Docs and tests updated as well. [Patch 742683] This is a ***POTENTIAL INCOMPATIBILITY*** only for those C programs that embed Tcl, build on Tcl_Main(), and make use of Tcl_Main's former ability to pass a leading "-encoding" option to interactive shell operations. * generic/tclInt.decls: Added internal stub * generic/tclMain.c (Tcl*StartupScript*): table entries for two new functions Tcl_SetStartupScript() and Tcl_GetStartupScript() that set/get the path and encoding for the startup script to be evaluated by either Tcl_Main() or Tk_Main(). Given public names in anticipation of their exposure by a followup TIP. * generic/tclDecls.h: make genstubs * generic/tclIntDecls.h: * generic/tclStubInit.c: 2003-09-04 Don Porter * doc/SplitList.3: Implementation of TIP 148. Fixes [Bug 489537]. * generic/tcl.h: Updated Tcl_ConvertCountedElement() to quote * generic/tclUtil.c: the leading "#" character of all list elements unless the TCL_DONT_QUOTE_HASH flag is passed in. * generic/tclDictObj.c: Updated Tcl_ConvertCountedElement() callers * generic/tclListObj.c: to pass in the TCL_DONT_QUOTE_HASH flags * generic/tclResult.c: when appropriate. 2003-08-31 Don Porter * doc/return.n: Updated [return] docs to cover new TIP 90 features. * doc/break.n: Added SEE ALSO references to return.n * doc/continue.n: 2003-09-01 Donal K. Fellows * doc/Namespace.3: Basic documentation for the TIP#139 functions. This will need improving, but the basic bits are there at least. 2003-08-31 Don Porter * doc/catch.n: Updated [catch] docs to cover new TIP 90 features. 2003-08-29 Don Porter * generic/tclCmdAH.c: Corrected bug in TIP 90 implementation where * tests/cmdMZ.test: the default -errorcode NONE value was not copied into the return options dictionary. This correction modified one test result. 2003-08-27 David Gravereaux * compat/strftime.c (_fmt): Removed syst array intializer that couldn't take variables within it under the watcom compiler: 'Initializers must be constant'. I believe Borland has this strictness as well. VC++ must be non-standard about this. Changed Win32 platform #ifdef from 'WIN32' to '__WIN32__' as this is the correct one to use across the Tcl sources. Even though we do force it in tcl.h, the true parent one is __WIN32__. Added missing CONST'ification usage to match prototype listed in tclInt.decls. * win/tclWinPort.h: Added a block for OpenWatcom adjustments that fixes 1) the same issue Mo did for MinGW lack of missing LPFN_* typedefs in their WINE derived and 2) The need to be strict about how the char type needs to be signed by default. * win/tclWinSock.c: Added OpenWatcom to the commentary about the #ifdef HAVE_NO_LPFN_DECLS block. * win/tclWinTime.c: Changed use of '_timezone' to 'timezone' as this difference is already adjusted for in tclWinPort.h. Removed unreferenced posixEpoch file-scope global. * win/tclWinFile.c (WinReadLinkDirectory): Fix for 'Initializers must be constant' with the driveSpec array using OpenWatcom. 2003-08-27 Don Porter * generic/tclUtil.c: Corrected [Bug 411825] and other bugs in TclNeedSpace() where non-breaking space (\u00A0) and backslash-escaped spaces were handled incorrectly. * tests/util.test: Added new tests util-8.[2-6]. 2003-08-26 David Gravereaux * generic/tcl.h: Added some support for the LCC-Win32 compiler. Unfortunetly, this compiler has a bug in its preprocessor and can't build Tcl even with this minor patch. Also added some support for the OpenWatcom compiler. A new win/makefile.wc to follow soon. 2003-08-25 Donal K. Fellows * tools/genStubs.tcl (genStubs::makeDecl): A more subtle way of generating stubbed declarations allows us to have declarations of a function in multiple interfaces simultaneously. * generic/tcl.decls: Duplicated some namespace declarations from tclInt.decls here, as mandated by TIP #139. This is OK since the declarations match and will end up using the declarations in the public code from now on because of #include ordering. Keeping the old declarations in tclInt.decls; there's no need to gratuitously break compatability for those extensions which are already clients of the namespace code. 2003-08-23 Zoran Vasiljevic * generic/tclIOUtil.c: merged fixes for thread-unsafe handling of filesystem records [Bug 753315]. This also fixed the [Bug 788780] * generic/tclPathObj.c: merged fixes for thread-unsafe handling of filesystem records. [Bug 753315] * generic/tclFileSystem.h: merged fixes for thread-unsafe handling of filesystem records. [Bug 753315] 2003-08-19 Pat Thoyts * win/tclWinSerial.c (SerialErrorStr): Fixed a syntax error created in the previous code cleanup. 2003-08-19 Donal K. Fellows * win/tclWinSerial.c: Adjusted commenting and spacing usage to follow the principles of the Style Guide better. 2003-08-18 Mo DeJong * win/configure: Regen. * win/tcl.m4 (SC_ENABLE_SYMBOLS): Use test instead of -eq, which does not work. [Bug 781109] 2003-08-13 Chengye Mao * win/tclWinPipe.c: fixed a bug in BuildCommandLine. This bug built a command line with a missing space between tclpipe.dll and the following arguments. It caused error in Windows 98 when exec command.com (e.g. dir). [Bug 789040] 2003-08-11 Donal K. Fellows TIP #136 IMPLEMENTATION from Simon Geard * generic/tclCmdIL.c (Tcl_LrepeatObjCmd): Adapted version of Simon's * doc/lrepeat.n: patch, updated to the HEAD * tests/lrepeat.test: and matching the core style. * generic/tclBasic.c (buildIntCmds): Splice into core. * generic/tclInt.h: * doc/list.n: Cross-reference. 2003-08-06 Jeff Hobbs * win/tclWinInit.c: recognize amd64 and ia32_on_win64 cpus. 2003-08-06 Don Porter * library/msgcat/msgcat.tcl: Added escape so that non-Windows * library/msgcat/pkgIndex.tcl: platforms do not try to use the registry package. This can save a costly and pointless package search. Bumped to 1.3.1. Thanks to Dave Bodenstab. [Bug 781609] 2003-08-05 Miguel Sofer * generic/tclExecute.c (INST_INVOKE, INST_EVAL, INST_PUSH_RESULT): added a Tcl_ResetResult(interp) at each point where the interp's result is pushed onto the stack, to avoid keeping an extra reference that may cause costly Tcl_Obj duplication. Detected by Franco Violi, analyzed by Peter Spjuth and Donal Fellows. [Bug 781585] 2003-07-28 Vince Darley * doc/FileSystem.3: * doc/Translate.3: better documentation of Tcl_TranslateFileName and related functions. [Bug 775220] 2003-07-24 Mo DeJong * generic/tcl.h: Revert change made on 2003-07-21 since it made the sizeof(Tcl_Obj) different for regular vs mem debug builds. * generic/tclInt.h: Define TclDecrRefCount in terms of Tcl_DbDecrRefCount which removes one layer of inderection. * generic/tclObj.c (TclDbInitNewObj, Tcl_DbIncrRefCount, (Tcl_DbDecrRefCount, Tcl_DbIsShared): Define ThreadSpecificData that contains a hashtable. The table is used to ensure that a Tcl_Obj is only acted upon in the thread that allocated it. This checking code is enabled only when mem debug and threads are enabled. 2003-07-24 Don Porter * tests/async.test: Added several tests that demonstrate [Bug * tests/basic.test: 489537], Tcl's longstanding failure to * tests/dict.test: properly quote any leading '#' character when * tests/dstring.test: generating the string rep of a list so that * tests/list.test: the comment-power of that character is hidden * tests/parse.test: from any [eval], in order to satisfy the * tests/util.test: documentation that [list] does [eval]-safe quoting. 2003-07-24 Reinhard Max * library/package.tcl: Fixed a typo that broke pkg_mkIndex -verbose. * tests/pkgMkIndex.test: Added a test for [pkg_mkIndex -verbose]. * ChangeLog.2002 (new file): * ChangeLog: broke changes from 2002 into ChangeLog.2002 to reduce size of the main ChangeLog. 2003-07-23 Daniel Steffen * unix/Makefile.in: changes to html-tcl & html-tk targets for compatibility with non-gnu makes. * unix/Makefile.in: added macosx/README to dist target. 2003-07-23 Pat Thoyts * win/tclWinReg.c (OpenSubKey): Fixed bug 775976 which causes the registry set command to fail when built with VC7. * library/reg/pkgIndex.tcl: Incremented the version to 1.1.2. 2003-07-21 Mo DeJong Check that the thread incrementing or decrementing the ref count of a Tcl_Obj is the thread that originally allocated the thread. This fail fast behavior will catch programming errors that allow a single Tcl_Obj to be accessed from multiple threads. * generic/tcl.h (Tcl_Obj): Add allocThread member to Tcl_Obj. This member records the thread id the Tcl_Obj was allocated. It is used to check that any future ref count incr or decr is done from the same thread that allocated the Tcl_Obj. This member is defined only when threads and mem debug are enabled. * generic/tclInt.h (TclNewObj, TclDbNewObj, TclDecrRefCount): Define TclNewObj and TclDbNewObj using TclDbInitNewObj when mem debug is enabled. This fixes a problem where TclNewObj calls did not work the same as TclDbNewObj when mem debug was enabled. * generic/tclObj.c (TclDbInitNewObj, Tcl_DbIncrRefCount, (Tcl_DbDecrRefCount): Add new helper to init Tcl_Obj members when mem debug is enabled. Init the allocThread member in TclDbInitNewObj and check it in Tcl_DbIncrRefCount and Tcl_DbDecrRefCount to make sure a Tcl_Obj allocated in one thread is not being acted upon in another thread. 2003-07-21 Vince Darley * test/cmdAH.test: ensure certain tests run in local filesystem. [Bug 748960] 2003-07-18 Daniel Steffen * macosx/Makefile: added option to allow installing manpages in addition to default html help. 2003-07-18 Donal K. Fellows * doc/Utf.3: Tightened up documentation of Tcl_UtfNext and Tcl_UtfPrev to better match the behaviour. [Bug 769895] 2003-07-18 Jeff Hobbs * library/http/pkgIndex.tcl: upped to http v2.4.4 * library/http/http.tcl: add support for user:pass info in URL. * tests/http.test: [Bug 759888] (shiobara) 2003-07-18 Don Porter * doc/tcltest.n: Restored the [Eval] proc to replace * library/tcltest/tcltest.tcl: the [::puts] command when either the -output or -error option for [test] is in use, in order to capture data written to the output or error channels for comparison against what is expected. This is easier to document and agrees better with most user expectations than the previous attempt to replace [puts] only in the caller's namespace. Documentation made more precise on the subject. [Bug 706359] * doc/AddErrInfo.3: Improved consistency of documentation by * doc/CrtTrace.3: using "null" everywhere to refer to the * doc/Encoding.3: character '\0', and using "NULL" everywhere * doc/Eval.3: to refer to the value of a pointer that points * doc/GetIndex.3: to nowhere. Also dropped references to ASCII * doc/Hash.3: that are no longer true, and standardized on * doc/LinkVar.3: the hyphenated spelling of "null-terminated". * doc/Macintosh.3: * doc/OpenFileChnl.3: * doc/SetVar.3: * doc/StringObj.3: * doc/Utf.3: * doc/CrtSlave.3 (Tcl_MakeSafe): Removed warning about possible deprecation (no TIP on that). 2003-07-17 Daniel Steffen * unix/tclUnixFCmd.c: fix for compilation errors on platforms where configure detects non-functional chflags(). [Bug 748946] * macosx/Makefile: Rewrote buildsystem for Mac OS X framework build to be purely make driven; in order to become independent of Apple's closed-source IDE and build tool. The changes are intended to be transparent to the Makefile user, all existing make targets and cmd line variable overrides should continue to work. Changed build to only include tcl specific html help in Tcl.framework, the tk specific html help is now included in Tk.framework. Added var to allow overriding of tclsh used during html help building (Landon Fuller). * macosx/Tcl.pbproj/project.pbxproj: * macosx/Tcl.pbproj/jingham.pbxuser: Changed to purely call through to the make driven buildsystem; Tcl.framework is no longer assembled by ProjectBuilder. Set default SYMROOT in target options to simplify setting up PB (manually setting common build folder for tcl & tk no longer needed). * tools/tcltk-man2html.tcl: Added options to allow building only the tcl or tk html help files; the default behaviour with none of the new options is to build both, as before. * unix/Makefile.in: Added targets for building only the tcl or tk help * macosx/README (new): Tcl specific excerpts of tk/macosx/README. * generic/tcl.h: Updated reminder comment about editing macosx/Tcl.pbproj/project.pbxproj when version number changes. 2003-07-16 Mumit Khan * generic/tclPathObj.c (SetFsPathFromAny): Add Cygwin specific code to convert POSIX filename to native format. * generic/tclFileName.c (Tcl_TranslateFileName): And remove from here. (TclDoGlob): Adjust for cygwin and append / for dirs instead of \ * win/tclWinFile.c (TclpObjChdir): Use chdir on Cygwin. [Patch 679315] 2003-07-16 Jeff Hobbs * library/safe.tcl (FileInAccessPath): normalize paths before comparison. [Bug 759607] (myers) * unix/tclUnixNotfy.c (NotifierThreadProc): correct size of found and word vars from int to long. [Bug 767578] (hgo) * generic/tcl.h: Add recognition of -DTCL_UTF_MAX=6 on the make * generic/regcustom.h: line to support UCS-4 mode. No config arg at this time, as it is not the recommended build mode. * generic/tclPreserve.c: In Result and Preserve'd routines, do not * generic/tclUtil.c: assume that ckfree == free, as that is not * generic/tclResult.c: always true. [Bug 756791] (fuller) 2003-07-16 Donal K. Fellows * doc/CrtSlave.3 (Tcl_MakeSafe): Updated documentation to strongly discourage use. IMHO code outside the core that uses this function is a bug... [Bug 655300] 2003-07-16 Don Porter * generic/tclFileName.c (Tcl_GlobObjCmd): [Bug 771840] * generic/tclPathObj.c (Tcl_FSConvertToPathType):[Bug 771947] * unix/tclUnixFCmd.c (GetModeFromPermString): [Bug 771949] Silence compiler warnings about unreached lines. * library/tcltest/tcltest.tcl (ProcessFlags): Corrected broken call * library/tcltest/pkgIndex.tcl: to [lrange]. Bumped to version 2.2.4. [Bug 772333] 2003-07-15 Mo DeJong * unix/dltest/pkga.c (Pkga_EqObjCmd): Fix typo that was causing a crash in load.test. 2003-07-15 Donal K. Fellows * doc/array.n: Make sure docs are synched with the 8.4 release. 2003-07-15 Don Porter * doc/http.n: Updated SYNOPSIS to match actual syntax of commands. [Bug 756112] * unix/dltest/pkga.c: Updated to not use Tcl_UtfNcmp and counted strings instead of strcmp (not defined in any #include'd header) and presumed NULL-terminated strings. * generic/tclCompCmds.c (TclCompileIfCmd): Prior fix of Bug 711371 on 2003-04-07 introduced a buffer overflow. Corrected. [Bug 771613] 2003-07-15 Kevin B. Kenny * win/rules.vc: Added a missing $(OPTDEFINES) which broke the build if STATS=memdbg was specified. 2003-07-15 Donal K. Fellows * generic/tclCmdIL.c (SortCompare): Cleared up confusing error message. [Bug 771539] 2003-07-11 Donal K. Fellows * tests/binary.test (binary-46.*): Tests to help enforce the current behaviour. * doc/binary.n: Documented that [binary format a] and [binary scan a] do encoding conversion by dropping high bytes, unlike the rest of the core. [Bug 735364] 2003-07-11 Don Porter * library/package.tcl: Corrected [pkg_mkIndex] bug reported on comp.lang.tcl. The indexer was searching for newly indexed packages instead of newly provided packages. 2003-07-08 Vince Darley * tests/winFCmd.test: fix for five tests under win98 [Bug 767679] 2003-07-07 Jeff Hobbs * doc/array.n: add examples from Welton 2003-06-23 Vince Darley * doc/file.n: clarification of 'file tail' behaviour [Bug 737977] 2003-07-04 Donal K. Fellows * doc/expr.n: Tighten up the wording of some operations. [Bug 758488] * tests/cmdAH.test: Made tests of [file mtime] work better on FAT filesystems. [Patch 760768] Also a little general cleanup. * generic/tclCmdMZ.c (Tcl_StringObjCmd): Made [string map] accept dictionaries for maps. This is much trickier than it looks, since map entry ordering is significant. [Bug 759936] * generic/tclVar.c (Tcl_ArrayObjCmd, TclArraySet): Made [array get] and [array set] work with dictionaries, producing them and consuming them. Note that for compatability reasons, you will never get a dict from feeding a string literal to [array set] since that alters the trace behaviour of "multi-key" sets. [Bug 759935] 2003-06-23 Vince Darley * generic/tclTrace.c: fix to Window debug build compilation error. 2003-06-27 Don Porter * tests/init.test: Added [cleanupTests] to report results of tests * tests/pkg.test: that run in slave interps. [Bugs 761334,761344] * tests/http.test: Used more reliable path to find httpd script. 2003-06-25 Don Porter * tests/init.test: Added tests init-4.6.* to illustrate [Bug 760872] 2003-06-25 Donal K. Fellows * generic/tclTrace.c: New file, factoring out of virtually all the various trace-related things from tclBasic.c and tclCmdMZ.c with the goal of making this a separate maintenance area. 2003-06-25 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_CONFIG_CFLAGS): Add -ieee when compiling with cc and add -mieee when compiling with gcc under OSF1-V5 "Tru64" systems. [Bug 748957] 2003-06-24 Donal K. Fellows * doc/encoding.n: Corrected the docs to say that [source] uses the system encoding, which it always did anyway (since 8.1) [Bug 742100] 2003-06-24 Donal K. Fellows * generic/tclHash.c (Tcl_HashStats): Prevented occurrence of division-by-zero problems. [Bug 759749] 2003-06-24 Mo DeJong * unix/tclUnixPort.h: #undef inet_ntoa before #define to avoid compiler warning under freebsd. [Bug 745844] 2003-06-23 Pat Thoyts * doc/dde.n: Committed TIP #135 which changes the * win/tclWinDde.c: -exact option to -force. Also cleaned a * tests/winDde.test: bug in the tests. * library/dde/pkgIndex.tcl: Incremented version to 1.2.5 * doc/dde.n: Committed TIP #120 which provides the * win/tclWinDde.c: dde package for safe interpreters. * tests/winDde.test: Incremented package version to 1.2.4 * library/dde/pkgIndex.tcl: 2003-06-23 Vince Darley * generic/tclFCmd.c: fix to bad error message when trying to do 'file copy foo ""'. [Bug 756951] * tests/fCmd.test: added two new tests for the bug. * win/tclWinFile.c: * win/tclWin32Dll.c: recommitted some filesystem globbing speed-ups, but disabled some on the older Win 95/98/ME where they don't seem to work. * doc/FileSystem.3: documentation fix [Bug 720634] 2003-06-18 Miguel Sofer * generic/tclNamesp.c (Tcl_Export): removed erroneous comments. [Bug 756744] 2003-06-17 Vince Darley * win/makefile.vc: fixes to check-in below so compilation now works again on Windows. * generic/tclCmdMZ.c: * tests/regexp.test: fixing of bugs related to regexp and regsub matching of empty strings. Addition of a number of new tests. [Bug 755335] 2003-06-16 Andreas Kupries * win/Makefile.in: Haven't heard back from David for a week. Now * win/configure: committing the remaining changes. * win/configure.in: Note: In active contact with Helmut Giese about * win/makefile.vc: the borland relatedchanges. This part will see * win/rules.vc: future updates. * win/tcl.m4: * win/makefile.bc: 2003-06-10 Andreas Kupries * generic/tclConfig.c (ASSOC_KEY): Changed the key to "tclPackageAboutDict" (tcl prefix) to make collisions with the keys of other packages more unlikely. 2003-06-10 Miguel Sofer * generic/tclBasic.c: * generic/tclExecute.c: let TclExecuteObjvInternal call TclInterpReady instead of relying on its callers to do so; fix for the part of [Bug 495830] that is new in 8.4. * tests/interp.test: Added tests 18.9 (knownbug) and 18.10 2003-06-09 Andreas Kupries * generic/tcl.decls: Ported the changes from the * generic/tcl.h: 'tip-59-implementation' branch into the CVS * generic/tclBasic.c: head. Regenerated stub table. Regenerated the * generic/tclInt.h: configure's scripts, with help from Joe English. * generic/tclDecls.h: * generic/tclStubInit.c: * generic/tclConfig.c: * generic/tclPkgConfig.c: * unix/Makefile.in: * unix/configure.in: The changes in the windows section are not yet * unix/tcl.m4: committed, they await feedback from David * unix/mkLinks: Gravereaux. * doc/RegConfig.3: * mac/tclMacPkgConfig.c: * tests/config.test: 2003-06-09 Don Porter * string.test (string-4.15): Added test for [string first] bug reported in Tcl 8.3, where test for all-single-byte-encoded strings was not reliable. 2003-06-04 Joe Mistachkin * tools/man2help.tcl: Added duplicate help section checking and * tools/index.tcl: corrected a comment typo for the getTopics proc in index.tcl. [Bug 748700] 2003-06-02 Vince Darley * win/tclWinFCmd.c: * tests/fCmd.test: fix to [Bug #747575] in which a bad error message is given when trying to rename a busy directory to one with the same prefix, but not the same name. Added three new tests. 2003-05-23 D. Richard Hipp * win/tclWinTime.c: Add tests to detect and avoid a division by zero in the windows precision timer calibration logic. 2003-05-23 Don Porter * generic/tclObj.c (tclCmdNameType): Converted internal rep management of the cmdName Tcl_ObjType the opposite way, to always use the twoPtrValue instead of always using the otherValuePtr. Previous fix on 2003-05-12 broke several extensions that wanted to poke around with the twoPtrValue.ptr2 value of a cmdName Tcl_Obj, like TclBlend and e4graph. [Bug 726018] Thanks to George Petasis for the bug report and Jacob Levy for testing assistance. 2003-05-23 Mo DeJong * unix/mkLinks: Set the var S to "" at the top of the file to avoid error when user has set S to something. [Tk Bug 739833] 2003-05-22 Daniel Steffen * macosx/Tcl.pbproj/project.pbxproj: added missing references to new source files tclPathObj.c and tclMacOSXFCmd.c. * macosx/tclMacOSXBundle.c: fixed a problem that caused only the first call to Tcl_MacOSXOpenVersionedBundleResources() for a given bundle identifier to succeed. This caused the tcl runtime library not to be found in all interps created after the inital one. 2003-05-19 Kevin B. Kenny * unix/tclUnixTime.c: Corrected a bug in conversion of non-ASCII chars in the format string. 2003-05-19 Daniel Steffen * macosx/Tcl.pbproj/project.pbxproj: changed tclConfig.sh location in versioned framework subdirectories to be identical to location in framework toplevel; fixed stub library symbolic links to be tcl version specific. * unix/tclUnixTime.c: fixed typo. 2003-05-18 Kevin Kenny * compat/strftime.c: Modified TclpStrftime to return its result in * generic/tclClock.c: UTF-8 encoding, and removed the conversion from * mac/tclMacTime.c: system encoding to UTF-8 from [clock format]. * unix/tclUnixTime.c: Needed to avoid double conversion of the * win/tclWinTime.c: timezone name on Windows systems. [Bug 624408] 2003-05-16 Pat Thoyts * library/dde/pkgIndex.tcl: Applied TIP #130 which provides for * tests/winDde.test: unique dde server names. Added some more * win/tclWinDde.c: tests. Fixes [Bug 219293] * doc/dde.n: Updated documentation re TIP #130. * tests/winDde.test: Applied patch for [Bug 738929] by KKB and changed to new-style tests. 2003-05-16 Kevin B. Kenny * unix/Makefile.in: Removed one excess source file tclDToA.c 2003-05-16 Daniel Steffen * macosx/Tcl.pbproj/project.pbxproj: updated copyright year. 2003-05-15 Kevin B. Kenny * generic/tclGetDate.y: added further hackery to the yacc * generic/tclDate.c: post-processing to arrange for the code to set * unix/Makefile.in: up exit handlers to free the stacks. [Bug 736425] 2003-05-15 Jeff Hobbs * win/tclWinFile.c (TclpMatchInDirectory): revert glob code to r1.44 as 2003-04-11 optimizations broke Windows98 glob'ing. * doc/socket.n: nroff font handling correction * library/encoding/gb2312-raw.enc (new): This is the original gb2312.enc renamed to allow for it to still be used. This is needed by Tk (unix) because X fonts with gb2312* charsets really do want the original gb2312 encoding. [Bug 557030] 2003-05-14 Donal K. Fellows * generic/tclCmdAH.c (Tcl_FormatObjCmd): Stop unwarranted demotion of wide values to longs by formatting of int values. [Bug 699060] 2003-05-14 Jeff Hobbs * library/encoding/gb2312.enc: copy euc-cn.enc over original gb2312.enc. gb2312.enc appeared to not work as expected, and most uses of gb2312 really mean euc-cn (which may be the cause of the problem). [Bug 557030] 2003-05-14 Daniel Steffen Implementation of TIP 118: * generic/tclFCmd.c (TclFileAttrsCmd): return the list of attributes that can be retrieved without error for a given file, instead of aborting the whole command when any error occurs. * unix/tclUnixFCmd.c: added support for new file attributes and for copying Mac OS X file attributes & resource fork during [file copy]. * generic/tclInt.decls: added declarations of new external commands needed by new file attributes support in tclUnixFCmd.c. * macosx/tclMacOSXFCmd.c (new): Mac OS X specific implementation of new file attributes and of attribute & resource fork copying. * mac/tclMacFCmd.c: added implementation of -rsrclength attribute & fixes to other attributes for consistency with OSX implementation. * mac/tclMacResource.c: fixes to OSType handling. * doc/file.n: documentation of [file attributes] changes. * unix/configure.in: check for APIs needed by new file attributes. * unix/Makefile.in: * unix/tcl.m4: added new platform specifc tclMacOSXFCmd.c source. * unix/configure: * generic/tclStubInit.c: * generic/tclIntPlatDecls.h: regen. * tools/genStubs.tcl: fixes to completely broken code trying to prevent overlap of "aqua", "macosx", "x11" and "unix" stub entries. * tests/unixFCmd.test: added tests of -readonly attribute. * tests/macOSXFCmd.test (new): tests of macosx file attributes and of preservation of attributes & resource fork during [file copy]. * tests/macFCmd.test: restore -readonly attribute of test dir, as otherwise its removal can fail on unices supporting -readonly. 2003-05-13 David Gravereaux * generic/tclEnv.c: Another putenv() copy behavior problem repaired when compiling on windows and using microsoft's runtime. [Bug 736421] 2003-05-13 Jeff Hobbs * generic/tclIOUtil.c: ensure cd is thread-safe. [Bug 710642] (vasiljevic) 2003-05-13 Donal K. Fellows * generic/tclEvent.c (Tcl_Finalize): Removed unused variable to reduce compiler warnings. [Bug 664745] 2003-05-13 Joe Mistachkin * generic/tcl.decls: Changed Tcl_JoinThread parameter name from * generic/tclDecls.h: "id" to "threadId". [Bug 732477] * unix/tclUnixThrd.c: * win/tclWinThrd.c: * mac/tclMacThrd.c: 2003-05-13 Daniel Steffen * generic/tcl.decls: * macosx/tclMacOSXBundle.c: added extended version of the Tcl_MacOSXOpenBundleResources() API taking an extra version number argument: Tcl_MacOSXOpenVersionedBundleResources(). This is needed to be able to access bundle resources in versioned frameworks such as Tcl and Tk, otherwise if multiple versions were installed, only the latest version's resources could be accessed. [Bug 736774] * unix/tclUnixInit.c (Tcl_MacOSXGetLibraryPath): use new versioned bundle resource API to get tcl runtime library for TCL_VERSION. [Bug 736774] * generic/tclPlatDecls.h: * generic/tclStubInit.c: regen. * unix/tclUnixPort.h: worked around the issue of realpath() not being thread-safe on Mac OS X by defining NO_REALPATH for threaded builds on Mac OS X. [Bug 711232] 2003-05-12 Donal K. Fellows * tests/cmdAH.test: General clean-up of tests so that all tcltest-specific commands are protected by constraints and all platforms see the same number of tests. [Bug 736431] 2003-05-12 Don Porter * generic/tclInterp.c: (AliasObjCmd): Added refCounting of the words * tests/interp.test (interp-33.1): of the target of an interp alias during its execution. Also added test. [Bug 730244] * generic/tclBasic.c (TclInvokeObjectCommand): objv[argc] is no longer set to NULL (Tcl_CreateObjCommand docs already say that it should not be accessed). * tests/cmdMZ.test: Forgot to import [temporaryDirectory]. * generic/tclObj.c (tclCmdNameType): Corrected variable use of the otherValuePtr or the twoPtrValue.ptr1 fields to store a (ResolvedCmdName *) as the internal rep. [Bug 726018] * doc/Eval.3: Corrected prototype for Tcl_GlobalEvalObj [Bug 727622]. 2003-05-12 Miguel Sofer * generic/tclVar.c (TclObjLookupVar): [Bug 735335] temporary fix, disabling usage of tclNsVarNameType. * tests/var.test (var-15.1): test for [Bug 735335] 2003-05-10 Jeff Hobbs * win/tclWinSerial.c (SerialCloseProc): correct mem leak on closing a Windows serial port [Bug 718002] (schroedter) * generic/tclCmdMZ.c (Tcl_StringObjCmd): prevent string repeat crash when overflow sizes were given (throws error). [Bug 714106] 2003-05-09 Joe Mistachkin * generic/tclThreadAlloc.c (TclFreeAllocCache): Fixed memory leak caused by treating cachePtr as a TLS index. [Bug 731754] * win/tclAppInit.c (Tcl_AppInit): Fixed memory leaks caused by not freeing the memory allocated by setargv and the async handler created by Tcl_AppInit. An exit handler has been created that takes care of both leaks. In addition, Tcl_AppInit now uses ckalloc instead of Tcl_Alloc to allow for easier leak tracking and to be more consistent with the rest of the Tcl core. [Bugs 733156, 733221] * tools/encoding/txt2enc.c (main): Fixed memory leak caused by failing to free the memory used by the toUnicode array of strings [Bug 733221] 2003-05-09 Miguel Sofer * generic/tclCompile.c (TclCompileScript): * tests/compile.test (compile-3.5): corrected wrong test and behaviour in the earlier fix for [Bug 705406]; Don Porter reported this as [Bug 735055], and provided the solution. 2003-05-09 Donal K. Fellows * generic/tclCmdMZ.c (Tcl_ReturnObjCmd): The array of strings passed to Tcl_GetIndexFromObj must be NULL terminated. [Bug 735186] Thanks to Joe Mistachkin for spotting this. 2003-05-07 Donal K. Fellows * doc/trace.n: Fixed very strange language in the documentation for 'trace add execution'. [Bug 729821] * generic/tclCmdMZ.c (Tcl_TraceObjCmd): Made error message for 'trace info' more consistent with documentation. [Bug 706961] * generic/tclDictObj.c (DictInfoCmd): Fixed memory leak caused by confusion about string ownership. [Bug 731706] 2003-05-05 Don Porter * generic/tclBasic.c: Implementation of TIP 90, which * generic/tclCmdAH.c: extends the [catch] and [return] * generic/tclCompCmds.c: commands to enable creation of a * generic/tclExecute.c: proc that is a replacement for * generic/tclInt.h: [return]. [Patch 531640] * generic/tclProc.c: * generic/tclResult.c: * tests/cmdAH.test: * tests/cmdMZ.test: * tests/error.test: * tests/proc-old.test: * library/tcltest/tcltest.tcl: The -returnCodes option to [test] failed to recognize the symbolic name "ok" for return code 0. 2003-05-05 Donal K. Fellows * generic/tclBasic.c (Tcl_HideCommand): Fixed error message for grammar and spelling. 2003-04-28 Donal K. Fellows * generic/tclDictObj.c (DictIncrCmd): Updated to reflect the behaviour with wide increments of the normal [incr] command. * generic/tclInt.decls: Added TclIncrWideVar2 to internal stub table and cleaned up. * tests/incr.test (incr-3.*): * generic/tclVar.c (TclIncrWideVar2, TclPtrIncrWideVar): * generic/tclExecute.c (TclExecuteByteCode): * generic/tclCmdIL.c (Tcl_IncrObjCmd): Make [incr] work when trying to increment by wide values. [Bug 728838] * generic/tclCompCmds.c (TclCompileSwitchCmd): Default mode of operation of [switch] is exact matching. [Bug 727563] 2003-04-25 Don Porter * generic/tclBasic.c: Tcl_EvalObjv() failed to honor the TCL_EVAL_GLOBAL flag when resolving command names. Tcl_EvalEx passed a string rep including leading whitespace and comments to TclEvalObjvInternal(). 2003-04-25 Andreas Kupries * win/tclWinThrd.c: Applied SF patch #727271. This patch changes the code to catch any errors returned by the windows functions handling TLS ASAP instead of waiting to get some mysterious crash later on due to bogus pointers. Patch provided by Joe Mistachkin. This is a stop-gap measure to deal with the low number of ?TLS slots provided by some of the variants of Windows (60-80). 2003-04-24 Vince Darley * generic/tclFileName.c: fix to bug reported privately by Jeff where, for example, 'glob -path {[tcl]} *' gets confused by the leading special character (which is escaped internally), and instead lists files in '/'. Bug only occurs on Windows where '\' is also a directory separator. * tests/fileName.test: added test for the above bug. 2003-04-22 Andreas Kupries * The changes below fix SF bugs [593810], and [718045]. * generic/tclIO.c (Tcl_CutChannel, Tcl_SpliceChannel): Invoke TclpCutSockChannel and TclpSpliceSockChannel. * generic/tclInt.h: Declare TclpCutSockChannel and TclpSpliceSockChannel. * unix/tclUnixSock.c (TclpCutSockChannel, TclpSpliceSockChannel): Dummy functions, on unix the sockets are _not_ handled specially. * mac/tclMacSock.c (TclpCutSockChannel, TclpSpliceSockChannel): * win/tclWinSock.c (TclpCutSockChannel, TclpSpliceSockChannel): New functions to handle socket specific cut/splice operations: auto-init of socket system for thread on splice, management of the module internal per-thread list of sockets, management of association of sockets with HWNDs for event notification. * win/tclWinSock.c (NewSocketInfo): Extended initialization assignments to cover all items of the structure. During debugging of the new code mentioned above I found that two fileds could contain bogus data. * win/tclWinFile.c: Added #undef HAVE_NO_FINDEX_ENUMS before definition because when compiling in debug mode the compiler complains about a redefinition, and this warning is also treated as an error. 2003-04-21 Don Porter * library/tcltest/tcltest.tcl: When the return code of a test does not meet expectations, report that as the reason for test failure, and do not attempt to check the test result for correctness. [Bug 725253] 2003-04-18 Jeff Hobbs * win/tclWinInt.h (VER_PLATFORM_WIN32_CE): conditionally define. * win/tclWinInit.c: recognize Windows CE as a Win platform. This just recognizes CE - full support will come later. * win/configure: regen * win/configure.in (SHELL): force it to /bin/sh as autoconf 2.5x uses /bin/bash, which can fail to find exes in the path (ie: lib). * generic/tclExecute.c (ExprCallMathFunc): remove incorrect extraneous cast from Tcl_WideAsDouble. 2003-04-18 Donal K. Fellows * doc/open.n: Moved serial port options from [fconfigure] to * doc/fconfigure.n: [open] as it is up to the creator of a channel to describe the channel's special config options. [Bug 679010] 2003-04-16 Don Porter * generic/tcl.h: Made changes so that the "wideInt" Tcl_ObjType * generic/tclObj.c: is defined on all platforms, even those where * generic/tclPort.h: TCL_WIDE_INT_IS_LONG is defined. Also made the Tcl_Value struct have a wideValue field on all platforms. This is a ***POTENTIAL INCOMPATIBILITY*** for TCL_WIDE_INT_IS_LONG platforms because that struct changes size. This is the same TIP 72 incompatibility that was seen on other platforms at the 8.4.0 release, when this change should have happened as well. [Bug 713562] * generic/tclInt.h: New internal macros TclGetWide() and TclGetLongFromWide() to deal with both forms of the "wideInt" Tcl_ObjType, so that conditional TCL_WIDE_INT_IS_LONG code is confined to the header file. * generic/tclCmdAH.c: Replaced most coding that was conditional * generic/tclCmdIL.c: on TCL_WIDE_INT_IS_LONG with code that * generic/tclExecute.c: works across platforms, sometimes using * generic/tclTest.c: the new macros above to do it. * generic/tclUtil.c: * generic/tclVar.c: 2003-04-17 Donal K. Fellows * doc/socket.n: Added a paragraph to remind people to specify their encodings when using sockets. [Bug 630621] 2003-04-16 Donal K. Fellows * doc/CrtMathFnc.3: Functions also have to deal with wide ints, but this was not documented. [Bug 709720] 2003-04-16 Vince Darley * generic/tclPathObj.c: removed undesired 'static' for function which is now shared (previously it was duplicated). 2003-04-15 Joe English * doc/namespace.n: added example section "SCOPED SCRIPTS", supplied by Kevin Kenny. [Bug 219183] 2003-04-15 Kevin Kenny * makefile.vc: Updated makefile.vc to conform with Mo DeJong's changes to Makefile.in and tclWinPipe.c on 2003-04-14. Now passes TCL_PIPE_DLL in place of TCL_DBGX. * win/tclWinTime.c: Corrected use of types to make compilation compatible with VC++5. 2003-04-15 Vince Darley * generic/tclIOUtil.c: finished check-in from yesterday, removing duplicate function definition. 2003-04-14 Don Porter * generic/tclClock.c: Corrected compiler warnings. * generic/tclTest.c: 2003-04-14 Mo DeJong * win/Makefile.in: Don't define TCL_DBGX symbol for every compile. Instead, define TCL_PIPE_DLL only when compiling tclWinPipe.c. This will break other build systems, so they will need to remove the TCL_DBGX define and replace it with a define for TCL_PIPE_DLL. * win/tclWinPipe.c (TclpCreateProcess): Remove PREFIX_IDENT and DEBUG_IDENT from top of file. Use TCL_PIPE_DLL passed in from build env instead of trying to construct the dll name from already defined symbols. This approach is more flexible and better in the long run. 2003-04-14 Kevin Kenny * win/tclWinFile.c: added conditionals to restore compilation on VC++6, which was broken by recent changes. 2003-04-14 Vince Darley * generic/tclIOUtil.c: * generic/tclPathObj.c: * generic/tclFileSystem.h: overlooked one function which was duplicated, so this is now shared between modules. * win/tclWinFile.c: allow this file to compile with VC++ 5.2 again since Mingw build fixes broke that. 2003-04-13 Mo DeJong * win/configure: Regen. * win/configure.in: Add check for FINDEX_INFO_LEVELS from winbase.h, known to be a problem in VC++ 5.2. Define HAVE_NO_FINDEX_ENUMS if the define does not exist. * win/tclWinFile.c: Put declarations for FINDEX_INFO_LEVELS and FINDEX_SEARCH_OPS inside a check for HAVE_NO_FINDEX_ENUMS so that these are not declared twice. This fixes the Mingw build. * win/tclWinTime.c: Rework the init of timeInfo so that the number or initializers matches the declaration. This was broken under Mingw. Add cast to avoid compile warning when calling the AccumulateSample function. 2003-04-12 Jeff Hobbs * win/Makefile.in (GENERIC_OBJS): add missing tclPathObj.c 2003-04-12 Kevin Kenny * doc/clock.n: * generic/tclClock.c (Tcl_ClockObjCmd): * tests/clock.test: Implementation of TIP #124. Also renumbered test cases to avoid duplicates. [Bug 710310] * tests/winTime.test: * win/tclWinTest.c (TestwinclockCmd, TestwinsleepCmd): * win/tclWinTime.c (Tcl_WinTime, UpdateTimeEachSecond, (ResetCounterSamples, AccumulateSample, SAMPLES, TimeInfo): Made substantial changes to the phase-locked loop (replaced an IIR filter with an FIR one) in a quest for improved loop stability (Bug not logged at SF, but cited in private communication from Jeff Hobbs). 2003-04-11 Don Porter * generic/tclCmdMZ.c (Tcl_StringObjCmd,STR_IS_INT): Corrected inconsistent results of [string is integer] observed on systems where sizeof(long) != sizeof(int). [Bug 718878] * tests/string.test: Added tests for Bug 718878. * doc/string.n: Clarified that [string is integer] accepts 32-bit integers. 2003-04-11 Andreas Kupries * generic/tclIO.c (UpdateInterest): When dropping interest in TCL_READABLE now dropping interest in TCL_EXCEPTION too. This fixes a bug where Expect detects eof on a file prematurely on solaris 2.6 and higher. A much more complete explanation is in the code itself (40 lines of comments for a one-line change :) 2003-04-11 Vince Darley * tests/cmdAH.test: fix test suite problem if /home is a symlink. [Bug 703264] * generic/tclIOUtil.c: fix bad error message with 'cd ""'. [Bug 704917] * win/tclWinFile.c, win/tclWin32Dll.c: * win/tclWinInt.h: allow Tcl to differentiate between reparse points which are symlinks and mounted volumes, and correctly handle the latter. This involves some elaborate code to find the actual drive letter (if possible) corresponding to a mounted volume. [Bug 697862] * tests/fileSystem.test: add constraints to stop tests running in ordinary tcl interpreter. [Bug 705675] * generic/tclIOUtil.c: * generic/tclPathObj.c: (new file) * generic/tclFileSystem.h: (new file) * win/makefile.vc: Split path object handling out of the virtual filesystem layer, into tclPathObj.c. This refactoring cleans up the internal filesystem code, and will make any future optimisations and forthcoming better thread-safety much easier. * generic/tclTest.c: * tests/reg.test: added some 'knownBug' tests for problems in Tcl's regexp code with the TCL_REG_CAN_MATCH flag (see Bug 703709). Code too impenetrable to fix right now, but a fix is needed for tip113 to work correctly. * tests/fCmd.test * win/tclWinFile.c: added some filesystem optimisation to the 'glob' implementation, and some new tests. * generic/tclCmdMZ.c: fix typo in comment * tests/winFile.test: * tests/ioUtil.test: * tests/unixFCmd.test: renumbered tests with duplicate numbers. [Bug 710361] 2003-04-10 Donal K. Fellows * doc/binary.n: Fixed typo in [binary format w] desc. [Bug 718543] 2003-04-08 Donal K. Fellows * generic/tclCmdAH.c (Tcl_ErrorObjCmd): Strings are only empty if they have zero length, not if their first byte is zero, so fix test guarding Tcl_AddObjErrorInfo to take this into account. [Bug reported by Don Porter; no bug-id.] 2003-04-07 Don Porter * generic/tclCompCmds.c (TclCompileIfCmd): Corrected string limits of arguments interpolated in error messages. [Bug 711371] * generic/tclCmdMZ.c (TraceExecutionProc): Added missing Tcl_DiscardResult() call to avoid memory leak. 2003-04-07 Donal K. Fellows * generic/tclDictObj.c (Tcl_DictObjCmd): Stopped compilers from moaning about switch fall-through. [Bug 716327] (DictFilterCmd): Yet more warning killing, this time reported by Miguel Sofer by private chat. 2003-04-07 Donal K. Fellows * tests/dict.test (dict-2.6): * generic/tclDictObj.c (Tcl_NewDictObj, Tcl_DbNewDictObj): Oops! Failed to fully initialise the Dict structure. (DictIncrCmd): Moved valueAlreadyInDictionary label to stop compiler complaints. [Bug 715751] * generic/tclDictObj.c (DictIncrCmd): Followed style in the rest of the core by commenting out wide-specific operations on platforms where wides are longs, and used longs more thoroughly than ints through [dict incr] anyway to forestall further bugs. * generic/tclObj.c: Made sure there's always a tclWideIntType implementation available, not that it is always useful. [Bug 713562] 2003-04-05 Donal K. Fellows * generic/tclDictObj.c: Removed commented out notes on declarations to be moved to elsewhere in the Tcl core. * generic/tclInt.h: Final stages of plumbing in. * generic/tclBasic.c: * generic/tclObj.c (TclInitObjSubsystem): * unix/Makefile.in, win/Makefile.in, win/makefile.[bv]c: Build support. * generic/tcl.decls: Added dict public API to stubs table. * generic/tcl.h (Tcl_DictSearch): Added declaration of structure to allow user code to iterate over dictionaries. * doc/DictObj.3: New files containing dictionary implementation * doc/dict.n: documentation and tests as as mandated by TIP * generic/tclDictObj.c: #111. * tests/dict.test: 2003-04-03 Mo DeJong * unix/configure: * unix/tcl.m4 (SC_CONFIG_CFLAGS): Don't set TCL_LIBS if it is already set to support use of TCL_LIBS var from tclConfig.sh in the Tk configure script. 2003-04-03 Mo DeJong * unix/Makefile.in: Don't subst MATH_LIBS, LIBS, and DL_LIBS separately. Instead, just subst TCL_LIBS since it includes the others. * unix/configure: Regen. * unix/tcl.m4 (SC_CONFIG_CFLAGS, SC_TCL_LINK_LIBS): Set and subst TCL_LIBS in SC_CONFIG_CFLAGS instead of SC_TCL_LINK_LIBS. Don't subst MATH_LIBS since it is now covered by TCL_LIBS. * unix/tclConfig.sh.in: Use TCL_LIBS instead of DL_LIBS, LIBS, and MATH_LIBS. * unix/dltest/Makefile.in: Ditto. 2003-04-03 Don Porter * generic/tclCompCmds.c (TclCompileReturnCmd): Now that [return] compiles to INST_RETURN, it is safe to compile even outside a proc. 2003-04-02 Mo DeJong * win/configure: Regen. * win/configure.in: Set stub lib flag based on new LIBFLAGSUFFIX variable. * win/tcl.m4 (SC_CONFIG_CFLAGS): Set new LIBFLAGSUFFIX that works like LIBSUFFIX, it is used when creating library names. The previous implementation would generate -ltclstub85 instead of -ltclstub85s when configured with --disable-shared. 2003-04-02 Don Porter * generic/tclParse.c (TclSubstTokens): Moved declaration of utfCharBytes to beginning of procedure so that it does not go out of scope (get free()d) while append is still pointing to it. [Bugs 703167, 713754] 2003-04-01 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_CONFIG_CFLAGS): Check for inet_ntoa in -lbind inside the BeOS block since doing it later broke the build under SuSE 7.3. [Bug 713128] 2003-04-01 Don Porter * tests/README: Direct [source] of *.test files is no longer recommended. The tests/*.test files should only be evaluated under the control of the [runAllTests] command in tests/all.tcl. * generic/tclExecute.c (INST_RETURN): Bytecompiled [return] failed to reset iPtr->returnCode, causing tests parse-18.17 and parse-18.21 to fail strangely. * tests/parse.test (parse-18.21): Corrected now functioning test. Added further coverage tests. 2003-03-31 Don Porter * tests/parse.test (parse-18.*): Coverage tests for the new implementation of Tcl_SubstObj(). Note that tests parse-18.17 and parse-18.21 demonstrate some bugs left to fix in the current code. 2003-03-27 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_CONFIG_CFLAGS): Use -Wl,--export-dynamic instead of -rdynamic for LDFLAGS. The -rdynamic is not documented so it seems better to pass the --export-dynamic flag to the linker. [Patch 573395] 2003-03-27 Miguel Sofer * tests/encoding.test: * tests/proc-old.test: * tests/set-old.test: Altered test numers to eliminate duplicates, [Bugs 710313, 710320, 710352] 2003-03-27 Donal K. Fellows * tests/parseOld.test: Altered test numers to eliminate duplicates. * tests/parse.test: [Bugs 710365, 710369] * tests/expr-old.test: * tests/expr.test: * tests/utf.test: Altered test numers to eliminate duplicates. * tests/trace.test: [Bugs 710322, 710327, 710349, 710363] * tests/lsearch.test: * tests/list.test: * tests/info.test: * tests/incr-old.test: * tests/if-old.test: * tests/format.test: * tests/foreach.test: 2003-03-26 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_CONFIG_CFLAGS, SC_TCL_LINK_LIBS): Add BeOS system to SC_CONFIG_CFLAGS. Check for inet_ntoa in -lbind, needed for BeOS. 2003-03-26 Don Porter * doc/tcltest.n: * library/tcltest/tcltest.tcl: Added reporting during [configure -debug 1] operations to warn about multiple uses of the same test name. [FRQ 576693] * tests/msgcat.test (msgcat-2.2.1): changed test name to avoid duplication. [Bug 710356] * unix/dltest/pkg?.c: Changed all Tcl_InitStubs calls to pass argument exact = 0, so that rebuilds are not required when Tcl bumps to a new version. [Bug 701926] 2003-03-24 Miguel Sofer * generic/tclVar.c: * tests/var.test: fixing ObjMakeUpvar's lookup algorithm for the created local variable. [Bug 631741] (Chris Darroch) and [Bug 696893] (David Hilker) 2003-03-24 Pat Thoyts * library/dde/pkgIndex.tcl: bumped version to 1.2.2 in tclWinDde.c, now adding here too. 2003-03-22 Kevin Kenny * library/dde/pkgIndex.tcl: * library/reg/pkgIndex.tcl: Fixed a bug where [package require dde] or [package require registry] attempted to load the release version of the DLL into a debug build. [Bug 708218] Thanks to Joe Mistachkin for the patch. * win/makefile.vc: Added quoting around the script name in the 'test' target; Joe Mistachkin insists that he has a configuration that fails to launch tcltest without it, and it appears harmless otherwise. 2003-03-22 Pat Thoyts * win/tclWinDde.c: Make dde services conform the the documentation such that giving only a topic name really returns all services with that topic. [Bug 219155] Prevent hangup caused by dde server applications failing to process messages. [Bug 707822] * tests/winDde.test: Corrected labels and added a test for search by topic name. 2003-03-20 Don Porter * generic/tclInt.h (tclOriginalNotifier): * generic/tclStubInit.c (tclOriginalNotifier): * mac/tclMacNotify.c (Tcl_SetTimer,Tcl_WaitForEvent): * unix/tclUnixNotfy.c (Tcl_SetTimer,Tcl_WaitForEvent, (Tcl_CreateFileHandler,Tcl_DeleteFileHandler): * win/tclWinNotify.c (Tcl_SetTimer,Tcl_WaitForEvent): Some linkers apparently use a different representation for a pointer to a function within the same compilation unit and a pointer to a function in a different compilation unit. This causes checks like those in the original notifier procedures to fall into infinite loops. The fix is to store pointers to the original notifier procedures in a struct defined in the same compilation unit as the stubs tables, and compare against those values. [Bug 707174] * generic/tclInt.h: Removed definition of ParseValue struct that is no longer used. 2003-03-19 Miguel Sofer * generic/tclCompile.c: * tests/compile.test: bad command count on TCL_OUT_LINE_COMPILE. [Bug 705406] (Don Porter) 2003-03-19 Don Porter * library/auto.tcl: Replaced [regexp] and [regsub] with * library/history.tcl: [string map] where possible. Thanks * library/ldAout.tcl: to David Welton. [Bugs 667456,667558] * library/safe.tcl: Bumped to http 2.4.3, opt 0.4.5, and * library/http/http.tcl: tcltest 2.2.3. * library/http/pkgIndex.tcl: * library/opt/optparse.tcl: * library/opt/pkgIndex.tcl: * library/tcltest/tcltest.tcl: * library/tcltest/pkgIndex.tcl: * tools/genStubs.tcl: * tools/tcltk-man2html.tcl: * unix/mkLinks.tcl: * doc/Eval.3 (Tcl_EvalObjEx): Corrected CONST and * doc/ParseCmd.3 (Tcl_EvalTokensStandard): return type errors in documentation. [Bug 683994] * generic/tclCompCmds.c (TclCompileReturnCmd): Alternative fix for * generic/tclCompile.c (INST_RETURN): [Bug 633204] that uses a new * generic/tclCompile.h (INST_RETURN): bytecode INST_RETURN to * generic/tclExecute.c (INST_RETURN): properly bytecode the [return] command to something that returns TCL_RETURN. 2003-03-18 Mo DeJong * win/configure: Regen. * win/configure.in: Don't run the AC_CYGWIN macro since it uses AC_CANONICAL_HOST under autoconf 2.5X. Just check to see if __CYGWIN__ is defined by the compiler and set the ac_cv_cygwin variable based on that. [Bug 705912] 2003-03-18 Kevin Kenny * tests/registry.test: Changed the conditionals to avoid an abort if [testlocale] is missing, as when running the test in tclsh rather than tcltest. [Bug 705677] 2003-03-18 Daniel Steffen * tools/tcltk-man2html.tcl: added support for building 'make html' from inside distribution directories named with 8.x.x version numbers. tcltk-man2html now uses the latest tcl8.x.x resp. tk8.x.x directories found inside its --srcdir argument. 2003-03-17 Mo DeJong * tests/format.test: Renumber tests, a bunch of tests all had the same id. 2003-03-17 Donal K. Fellows * doc/lsearch.n: Altered documentation of -ascii options so * doc/lsort.n: they don't specify that they operate on ASCII strings, which they never did anyway. [Bug 703807] 2003-03-14 Donal K. Fellows * generic/tclCmdAH.c (Tcl_FormatObjCmd): Only add the modifier that indicates we've got a wide int when we're formatting in an integer style. Stops some libc's from going mad. [Bug 702622] Also tidied whitespace. 2003-03-13 Mo DeJong * win/tcl.m4 (SC_WITH_TCL): Port version number fix that was made in tk instead of tcl sources. 2003-03-13 Mo DeJong Require autoconf 2.57 or newer, see TIP 34 for a detailed explanation of why this is good. This will no doubt break the build on some platforms, let the flaming begin. * tools/configure: Regen with autoconf 2.57. * tools/configure.in: Require autoconf 2.57. * unix/configure: Regen with autoconf 2.57. * unix/configure.in: Require autoconf 2.57. Apply AC_LIBOBJ changes from patch 529884. * unix/tcl.m4: Ditto. * win/configure: Regen with autoconf 2.57. * win/configure.in: Require autoconf 2.57. Don't subst LIBOBJS since this happens by default, this avoids an autoconf error. 2003-03-12 Don Porter * generic/tclBasic.c (Tcl_EvalTokensStandard): * generic/tclCmdMZ.c (Tcl_SubstObj): * generic/tclCompCmds.c (TclCompileSwitchCmd): * generic/tclCompExpr.c (CompileSubExpr): * generic/tclCompile.c (TclSetByteCodeFromAny,TclCompileScript, (TclCompileTokens,TclCompileCmdWord): * generic/tclCompile.h (TclCompileScript): * generic/tclExecute.c (TclCompEvalObj): * generic/tclInt.h (Interp,TCL_BRACKET_TERM,TclSubstTokens): * generic/tclParse.c (ParseTokens,Tcl_SubstObj,TclSubstTokens): * tests/subst.test (2.4, 8.7, 8.8, 11.4, 11.5): Substantial refactoring of Tcl_SubstObj to make use of the same parsing and substitution procedures as normal script evaluation. Tcl_SubstObj() moved to tclParse.c. New routine TclSubstTokens() created in tclParse.c which implements all substantial functioning of Tcl_EvalTokensStandard(). TclCompileScript() loses its "nested" argument, the Tcl_Interp struct loses its termOffset field and the TCL_BRACKET_TERM flag in the evalFlags field, all of which were only used (indirectly) by Tcl_SubstObj(). Tests subst-8.7,8.8,11.4,11.5 modified to accomodate the only behavior change: reporting of parse errors now takes precedence over [return] and [continue] exceptions. All other behavior should remain compatible. [RFE 536831,684982] [Bug 685106] * generic/tcl.h: Removed TCL_PREFIX_IDENT and TCL_DEBUG_IDENT * win/tclWinPipe.c: from tcl.h -- they are not part of Tcl's public interface. Put them in win/tclWinPipe.c where they are used. * generic/tclInterp.c (Tcl_InterpObjCmd): Corrected and added * tests/interp.test (interp-2.13): test for option parsing beyond objc for [interp create --]. Thanks to Marco Maggi. [Bug 702383] 2003-03-11 Kevin Kenny * win/makefile.vc: Added two missing uses of $(DBGX) so that tclpip8x.dll loads without panicking on Win9x. 2003-03-09 Kevin Kenny * generic/tclTest.c (TestChannelCmd): Removed an unused local variable that caused compilation problems on some platforms. 2003-03-08 Don Porter * doc/tcltest.n: Added missing "-body" to example. Thanks to Helmut Giese. [Bug 700011] 2003-03-07 Mo DeJong * tests/io.test: * tests/ioCmd.test: Define a fcopy constraint and add it to the constraint list of any test that depends on the fcopy command. This is only useful to Jacl which does not support fcopy. 2003-03-07 Mo DeJong * tests/encoding.test: Name temp files *.tcltestout instead of *.out so that when they are removed later, we don't accidently toast any files named *.out that the user has created in the build directory. 2003-03-07 Donal K. Fellows * generic/tclCmdAH.c (Tcl_FileObjCmd): Fix the setting of a file's mtime and atime on 64-bit platforms. [Bug 698146] 2003-03-06 Mo DeJong * tests/io.test: Doh! Undo accidental commenting out of a couple of tests. 2003-03-06 Mo DeJong * tests/io.test: Define a fileevent constraint and add it to the constraint list of any test that depends on the fileevent command. This is only useful to Jacl which does not support fileevent. 2003-03-06 Mo DeJong * tests/io.test: Define an openpipe constraint and add it to the constraint list of any test that creates a pipe using the open command. This is only useful to Jacl which does not support pipes. 2003-03-06 Don Porter * generic/TclUtf.c (Tcl_UniCharNcasecmp): Corrected failure to * tests/utf.test (utf-25.*): properly compare Unicode strings of different case in a case insensitive manner. [Bug 699042] 2003-03-06 Kevin Kenny * generic/tclCompCmds.c (TclCompileSwitchCmd): Replaced a non-portable 'bzero' with a portable 'memset'. [Bug 698442] 2003-03-06 Mo DeJong * generic/tclIO.c (Tcl_Seek, Tcl_OutputBuffered): If there is data buffered in the statePtr->curOutPtr member then set the BUFFER_READY flag in Tcl_Seek. This is needed so that the next call to FlushChannel will write any buffered bytes before doing the seek. The existing code would set the BUFFER_READY flag inside the Tcl_OutputBuffered function. This was a programming error made when Tcl_OutputBuffered was originally created in CVS revision 1.35. The setting of the BUFFER_READY flag should not have been included in the Tcl_OutputBuffered function. * generic/tclTest.c (TestChannelCmd): Use the Tcl_InputBuffered and Tcl_OutputBuffered util methods to query the amount of buffered input and output. 2003-03-06 Mo DeJong * generic/tclIO.c (Tcl_Flush): Compare the nextAdded member of the ChannelBuffer to the nextRemoved member to determine if any output has been buffered. The previous check against the value 0 seems to have just been a coding error. See other methods like Tcl_OutputBuffered for examples where nextAdded is compared to nextRemoved to find the number of bytes buffered. 2003-03-06 Mo DeJong * generic/tclIO.c (Tcl_GetsObj): Check that the eol pointer has not gone past the end of the string when in auto translation mode and the INPUT_SAW_CR flag is set. The previous code worked because the end of string value \0 was being compared to \n, this patch just skips that pointless check. 2003-03-06 Mo DeJong * generic/tclIO.c (WriteBytes, WriteChars, Tcl_GetsObj, ReadBytes): Rework calls to TranslateOutputEOL to make it clear that a boolean value is being returned. Add some comments in an effort to make the code more clear. This patch makes no functional changes. 2003-03-06 Mo DeJong * generic/tclIO.c (Tcl_SetChannelOption): Invoke the Tcl_SetChannelBufferSize method as a result of changing the -buffersize option to fconfigure. The previous implementation used some inlined code that reset the buffer size to the default size instead of ignoring the request as implemented in Tcl_SetChannelBufferSize. * tests/io.test: Update test case so that it actually checks the implementation of Tcl_SetChannelBufferSize. 2003-03-05 David Gravereaux * win/rules.vc: updated default tcl version to 8.5. 2003-03-05 Donal K. Fellows * generic/tclCompCmds.c (TclCompileSwitchCmd): First attempt at a bytecode-compiled switch command. It only handles the most common case of switching, but that should be enough for this to speed up a lot of people's code. It is expected that the speed gains come from two things: better handling of the switch itself, and integrated compilation of the arms instead of embedding separate bytecode sequences (i.e. better local variable handling.) * tests/switch.test (switch-10.*): Tests of both uncompiled and compiled switch behaviour. [Patch #644819] * generic/tclCompile.h (TclFixupForwardJumpToHere): Additional macro to make the most common kind of jump fixup a bit easier. 2003-03-04 Don Porter * README: Bumped version number of * generic/tcl.h: Tcl to 8.5a0. * library/init.tcl: * mac/README: * macosx/Tcl.pbproj/project.pbxproj: * tests/basic.test: * tools/configure.in: * tools/tcl.hpj.in: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/README: * win/README.binary: * win/configure.in: * win/makefile.bc: * win/makefile.vc: * win/tcl.m4: * tools/configure: autoconf * unix/configure: * win/configure: 2003-03-03 Jeff Hobbs *** 8.4.2 TAGGED FOR RELEASE *** 2003-03-03 Daniel Steffen Mac OS Classic specific fixes: * generic/tclIOUtil.c (TclNewFSPathObj): on TCL_PLATFORM_MAC, skip potential directory separator at the beginning of addStrRep. * mac/tclMacChan.c (OpenFileChannel, CommonWatch): followup fixes to cut and splice implementation for file channels. * mac/tclMacFile.c (TclpUtime): pass native path to utime(). * mac/tclMacFile.c (TclpObjLink): correctly implemented creation of alias files via new static proc CreateAliasFile(). * mac/tclMacPort.h: define S_ISLNK macro to fix stat'ing of links. * mac/tclMacUtil.c (FSpLocationFromPathAlias): fix to enable stat'ing of broken links. 2003-03-03 Kevin Kenny * win/Makefile.vc: corrected bug introduced by 'g' for debug builds. 2003-03-03 Don Porter * library/dde/pkgIndex.tcl: dde bumped to version 1.2.1 for * win/tclWinDde.c: bundled release with Tcl 8.4.2 * library/reg/pkgIndex.tcl: registry bumped to version 1.1.1 for * win/tclWinReg.c: bundled release with Tcl 8.4.2 * library/opt/pkgIndex.tcl: updated package index to version 0.4.4 2003-02-28 Jeff Hobbs * win/configure: * win/configure.in: check for 'g' for debug build type, not 'd'. * win/rules.vc (DBGX): correct to use 'g' for nmake win makefile to match the cygwin makefile for debug builds. [Bug 635107] 2003-02-28 Vince Darley * doc/file.n: subcommand is 'file volumes' not 'file volume' 2003-02-27 Jeff Hobbs * generic/tclIOUtil.c (MakeFsPathFromRelative): removed dead code check of typePtr (darley). * tests/winTime.test: added note about PCI hardware dependency issues with high performance clock. 2003-02-27 Donal K. Fellows * tests/lsearch.test (lsearch-10.7): * generic/tclCmdIL.c (Tcl_LsearchObjCmd): Stopped -start option from causing an option when used with an empty list. [Bug 694232] 2003-02-26 Chengye Mao * win/tclWinInit.c: fixed a bug in TclpSetVariables by initializing dwUserNameLen with the sizeof(szUserName) before calling GetUserName. Don't know if this bug has been recorded: it caused crash in starting Tcl or wish in Windows. 2003-02-26 Jeff Hobbs * generic/tclCmdMZ.c (TraceCommandProc): Fix mem leak when deleting a command that had trace on it. [Bug 693564] (sofer) 2003-02-25 Don Porter * doc/pkgMkIndex.n: Modified [pkg_mkIndex] to use -nocase matching * library/package.tcl: of -load patterns, to better accomodate common user errors due to confusion between [package names] names and [info loaded] names. 2003-02-25 Andreas Kupries * tests/pid.test: See below [Bug 678412]. * tests/io.test: Made more robust against spaces in paths [Bug 678400] 2003-02-25 Miguel Sofer * tests/execute.test: cleaning up testobj's at the end, to avoid leak warning by valgrind. 2003-02-22 Zoran Vasiljevic * generic/tclEvent.c (Tcl_FinalizeThread): Fix [Bug 571002] 2003-02-21 Donal K. Fellows * tests/binary.test (binary-44.[34]): * generic/tclBinary.c (ScanNumber): Fixed problem with unwanted sign-bit propagation when scanning wide ints. [Bug 690774] 2003-02-21 Daniel Steffen * mac/tclMacChan.c (TclpCutFileChannel, TclpSpliceFileChannel): Implemented missing cut and splice procs for file channels. 2003-02-21 Don Porter * library/package.tcl (tclPkgUnknown): Minor performance tweaks to reduce the number of [file] invocations. Meant to improve startup times, at least a little bit. [Patch 687906] 2003-02-20 Daniel Steffen * unix/tcl.m4: * unix/tclUnixPipe.c: (macosx) use vfork() instead of fork() to create new processes, as recommended by Apple (vfork can be up to 100 times faster thank fork on macosx). * unix/configure: regen. 2003-02-20 Jeff Hobbs * generic/tclEncoding.c (LoadTableEncoding): * library/encoding/cp932.enc: Correct jis round-trip encoding * library/encoding/euc-jp.enc: by adding 'R' type to .enc files. * library/encoding/iso2022-jp.enc: [Patch 689341] (koboyasi, taguchi) * library/encoding/jis0208.enc: * library/encoding/shiftjis.enc: * tests/encoding.test: * unix/tclUnixChan.c (Tcl_MakeTcpClientChannel): add MakeTcpClientChannelMode that takes actual mode flags to avoid hang on OS X (may be OS X bug, but patch works x-plat). [Bug 689835] (steffen) 2003-02-20 Donal K. Fellows * doc/regsub.n: Typo fix [Bug 688943] 2003-02-19 Jeff Hobbs * unix/tclUnixThrd.c (TclpReaddir): * unix/tclUnixPort.h: update to Bug 689100 patch to ensure that there is a defined value of MAXNAMLEN (aka NAME_MAX in POSIX) and that we have some buffer allocated. 2003-02-19 Daniel Steffen * generic/tclStringObj.c: restored Tcl_SetObjLength() side-effect of always invalidating unicode rep (if the obj has a string rep). Added hasUnicode flag to String struct, allows decoupling of validity of unicode rep from buffer size allocated to it (improves memory allocation efficiency). [Bugs 686782, 671138, 635200] * macosx/Tcl.pbproj/project.pbxproj: * macosx/Makefile: reworked embedded build to no longer require relinking but to use install_name_tool instead to change the install_names for embedded frameworks. [Bug 644510] * macosx/Tcl.pbproj/project.pbxproj: preserve mod dates when running 'make install' to build framework (avoids bogus rebuilds of dependent frameworks because tcl headers appear changed). * tests/ioCmd.test (iocmd-1.8): fix failure when system encoding is utf-8: use iso8859-1 encoding explicitly. 2003-02-18 Miguel Sofer * generic/tclCompile.c (TclCompileExprWords): remove unused variable "range" [Bug 664743] * generic/tclExecute.c (ExprSrandFunc): remove unused variable "result" [Bug 664743] * generic/tclStringObj.c (UpdateStringOfString): remove unused variable "length" [Bug 664751] * tests/execute.test (execute-7.30): fix for [Bug 664775] 2003-02-18 Andreas Kupries * unix/tcl.m4: [Bug #651811] Added definition of _XOPEN_SOURCE and linkage of 'xnet' library to HP 11 branch. This kills a lot of socket-related failures in the testsuite when Tcl was compiled in 64 bit mode (both PA-RISC 2.0W, and IA 64). * unix/configure: Regenerated. 2003-02-18 Jeff Hobbs * generic/tclIO.c (HaveVersion): correctly decl static * unix/tclUnixThrd.c (TclpReaddir): reduce size of name string in tsd to NAME_MAX instead of PATH_MAX. [Bug 689100] (waters) 2003-02-18 Mo DeJong * unix/configure: Regen. * unix/tcl.m4 (SC_ENABLE_THREADS): Make sure -lpthread gets passed on the link line when checking for the pthread_attr_setstacksize symbol. 2003-02-18 Vince Darley * generic/tclTest.c: cleanup of new 'simplefs' test code, and better documentation. 2003-02-17 Miguel Sofer * generic/tclBasic.c (TclRenameCommand): fixing error in previous commit. 2003-02-17 Jeff Hobbs * generic/tclExecute.c (TclExecuteByteCode INST_STR_MATCH): * generic/tclCmdMZ.c (Tcl_StringObjCmd STR_MATCH): * generic/tclUtf.c (TclUniCharMatch): * generic/tclInt.decls: add private TclUniCharMatch function that * generic/tclIntDecls.h: does string match on counted unicode * generic/tclStubInit.c: strings. Tcl_UniCharCaseMatch has the failing * tests/string.test: that it can't handle strings or patterns with * tests/stringComp.test: embedded NULLs. Added tests that actually try strings/pats with NULLs. TclUniCharMatch should be TIPed and made public in the next minor version rev. 2003-02-17 Miguel Sofer * generic/tclBasic.c (TclRenameCommand): 'oldFullName' object was not being freed on all function exits, causing a memory leak. [Bug 684756] 2003-02-17 Mo DeJong * generic/tclIO.c (Tcl_GetsObj): Minor change so that eol is only assigned at the top of the TCL_TRANSLATE_AUTO case block. The other cases assign eol so this does not change any functionality. 2003-02-17 Kevin Kenny * tests/notify.test: Removed Windows line terminators. [Bug 687913]. 2003-02-15 Miguel Sofer * generic/tclBasic.c (Tcl_EvalEx): * generic/tclCompExpr.c (CompileSubExpr): * generic/tclCompile.c (TclCompileScript): * generic/tclParse.c (Tcl_ParseCommand, ParseTokens): * generic/tclParseExpr.c (ParsePrimaryExpr): * tests/basic.test (47.1): * tests/main.test (3.4): * tests/misc.test (1.2): * tests/parse.test (6.18): * tests/parseExpr.test (15.35): * tests/subst.test (8.6): Don Porter's fix for bad parsing of nested scripts. [Bug 681841] 2003-02-15 Kevin Kenny * tests/notify.test (new-file): * generic/tclTest.c (TclTest_Init, EventtestObjCmd, EventtestProc, (EventTestDeleteProc): * generic/tclNotify.c (Tcl_DeleteEvents): Fixed Tcl_DeleteEvents not to get a pointer smash when deleting the last event in the queue. Added test code in 'tcltest' and a new file of test cases 'notify.test' to exercise this functionality; several of the new test cases fail for the original code and pass for the corrected code. [Bug 673714] * unix/tclUnixTest.c (TestfilehandlerCmd): Corrected a couple of typos in error messages. [Bug 596027] 2003-02-14 Jeff Hobbs * README: Bumped to version 8.4.2. * generic/tcl.h: * tools/tcl.wse.in: * unix/configure: * unix/configure.in: * unix/tcl.m4: * unix/tcl.spec: * win/README.binary: * win/configure: * win/configure.in: * macosx/Tcl.pbproj/project.pbxproj: * generic/tclStringObj.c (Tcl_GetCharLength): perf tweak * unix/tcl.m4: correct HP-UX ia64 --enable-64bit build flags 2003-02-14 Kevin Kenny * win/tclWinTime.c: Added code to test and compensate for forward leaps of the performance counter. See the MSDN Knowledge Base article Q274323 for the hardware problem that makes this necessary on certain machines. * tests/winTime.test: Revised winTime-2.1 - it had a tolerance of thousands of seconds, rather than milliseconds. (What's six orders of magnitude among friends?) Both the above changes are triggered by a problem reported at: http://aspn.activestate.com/ASPN/Mail/Message/ActiveTcl/1536811 although the developers find it difficult to believe that it accounts for the observed behavior and suspect a fault in the RTC chip. 2003-02-13 Kevin Kenny * win/tclWinInit.c: Added conversion from the system encoding to tcl_platform(user), so that it works with non-ASCII7 user names. [Bug 685926] * doc/tclsh.1: Added language to describe the handling of the end-of-file character \u001a embedded in a script file. [Bug 685485] 2003-02-11 Vince Darley * tests/fileName.test: * unix/tclUnixFile.c: fix for [Bug 685445] when using 'glob -l' on broken symbolic links. Added two new tests for this bug. 2003-02-11 Kevin Kenny * tests/http.test: Corrected a problem where http-4.14 would fail when run in an environment with a proxy server. Replaced references to scriptics.com by tcl.tk. 2003-02-11 Jeff Hobbs * tests/lsearch.test: * generic/tclCmdIL.c (Tcl_LsearchObjCmd): protect against the case that lsearch -regepx list and pattern objects are equal. * tests/stringObj.test: * generic/tclStringObj.c (Tcl_GetCharLength): correct ascii char opt of 2002-11-11 to not stop early on \x00. [Bug 684699] * tests.parse.test: remove excess EOF whitespace * generic/tclParse.c (CommandComplete): more paranoid check to break on (p >= end) instead of just (p == end). 2003-02-11 Miguel Sofer * generic/tclParse.c (CommandComplete): * tests/parse.test: fix for [Bug 684744], by Don Porter. 2003-02-11 Jeff Hobbs * generic/tclIOUtil.c (Tcl_FSJoinPath, Tcl_FSGetNormalizedPath): (UpdateStringOfFsPath): revert the cwdLen == 0 check and instead follow a different code path in Tcl_FSJoinPath. (Tcl_FSConvertToPathType, Tcl_FSGetNormalizedPath): (Tcl_FSGetFileSystemForPath): Update string rep of path objects before freeing the internal object. (darley) * tests/fileSystem.test: added test 8.3 * generic/tclIOUtil.c (Tcl_FSGetNormalizedPath): (UpdateStringOfFsPath): handle the cwdLen == 0 case * unix/tclUnixFile.c (TclpMatchInDirectory): simplify the hidden file match check. 2003-02-10 Mo DeJong * win/configure: * win/configure.in: Generate error when attempting to build under Cygwin. The Cygwin port of Tcl/Tk does not build and people are filing bug reports under the mistaken impression that someone is actually maintaining the Cygwin port. A post to comp.lang.tcl asking someone to volunteer as an area maintainer has generated no results. Closing bugs 680840, 630199, and 634772 and marking as "Won't fix". 2003-02-10 Donal K. Fellows * doc/append.n: Return value was not documented. [Bug 683188] 2003-02-10 Vince Darley * doc/FileSystem.3: * generic/tclIOUtil.c: * generic/tclInt.h: * tests/fileSystem.test: * unix/tclUnixFCmd.c: * unix/tclUnixFile.c: * win/tclWinFile.c: further filesystem optimization, applying [Patch 682500]. In particular, these code examples are faster now: foreach f $flist { if {[file exists $f]} {file stat $f arr;...}} foreach f [glob -dir $dir *] { # action and/or recursion on $f } cd $dir foreach f [glob *] { # action and/or recursion on $f } cd .. * generic/tclTest.c: Fix for [Bug 683181] where test suite left files in 'tmp'. 2003-02-08 Jeff Hobbs * library/safe.tcl: code cleanup of eval and string comp use. 2003-02-07 Vince Darley * win/tclWinFCmd.c: cleanup long lines * win/tclWinFile.c: sped up pure 'glob' by a factor of 2.5 ('foreach f [glob *] { file exists $f }' is still slow) * tests/fileSystem.text: * tests/fileName.test: added new tests to ensure correct behaviour in optimized filesystem code. 2003-02-07 Vince Darley * generic/tclTest.c: * tests/fileSystem.text: fixed test 7.2 to avoid a possible crash, and not change the pwd. * tests/http.text: added comment to test 4.15, that it may fail if you use a proxy server. 2003-02-06 Mo DeJong * generic/tclCompCmds.c (TclCompileIncrCmd): * tests/incr.test: Don't include the text "(increment expression)" in the errorInfo generated by the compiled version of the incr command since it does not match the message generated by the non-compiled version of incr. It is also not possible to match this error output under Jacl, which does not support a compiler. 2003-02-06 Mo DeJong * generic/tclExecute.c (TclExecuteByteCode): When an error is encountered reading the increment value during a compiled call to incr, add a "(reading increment)" error string to the errorInfo variable. This makes the errorInfo variable set by the compiled incr command match the value set by the non-compiled version. * tests/incr-old.test: Change errorInfo result for the compiled incr command case to match the modified implementation. * tests/incr.test: Add tests to make sure the compiled and non-compiled errorInfo messages are the same. 2003-02-06 Don Porter * library/tcltest/tcltest.tcl: Filename arguments to [outputChannel] and [errorChannel] (also -outfile and -errfile) were [open]ed but never [closed]. Also, [cleanupTests] could remove output or error files. [Bug 676978]. * library/tcltest/pkgIndex.tcl: Bumped to version 2.2.2. 2003-02-05 Mo DeJong * tests/interp.test: * tests/set-old.test: Run test cases that depend on hash order through lsort so that the tests also pass under Jacl. Does not change test results under Tcl. 2003-02-04 Vince Darley * generic/tclIOUtil.c: * generic/tclEvent.c: * generic/tclInt.h: * mac/tclMacFCmd.c: * unix/tclUnixFCmd.c: * win/tclWin32Dll.c: * win/tclWinFCmd.c: * win/tclWinInit.c: * win/tclWinInt.h: * tests/fileSystem.test: fix to finalization/unloading/encoding issues to make filesystem much less dependent on encodings for its cleanup, and therefore allow it to be finalized later in the exit process. This fixes fileSystem.test-7.1. Also fixed one more bug in setting of modification dates of files which have undergone cross-platform copies. [Patch 676271] * tests/basic.test: * tests/exec.test: * tests/fileName.test: * tests/io.test: fixed some test failures when tests are run from a directory containing spaces. * tests/fileSystem.test: * generic/tclTest.c: added regression test for the modification date setting of cross-platform file copies. 2003-02-03 Kevin Kenny * generic/tclBasic.c: Changed [trace add command] so that 'rename' callbacks get fully qualified names of the command. [Bug 651271]. ***POTENTIAL INCOMPATIBILITY*** * tests/trace.test: Modified the test cases for [trace add command] to expect fully qualified names on the 'rename' callbacks. Added a case for renaming a proc within a namespace. * doc/trace.n: Added language about use of fully qualified names in trace callbacks. 2003-02-01 Kevin Kenny * generic/tclCompCmds.c: Removed an unused variable that caused compiler warnings on SGI. [Bug 664379] * generic/tclLoad.c: Changed the code so that if Tcl_StaticPackage is called to report the same package as being loaded in two interps, it shows up in [info loaded {}] in both of them (previously, it didn't appear in the static package list in the second). * tests/load.test Added regression test for the above bug. [Bug 670042] * generic/tclClock.c: Fixed a bug that incorrectly allowed [clock clicks {}] and [clock clicks -] to be accepted as if they were [clock clicks -milliseconds]. * tests/clock.test: Added regression tests for the above bug. [Bug 675356] * tests/unixNotfy.test: Added cleanup of working files. [Bug 675609] * doc/Tcl.n: Added headings to the eleven paragraphs, to improve formatting in the tools that attempt to extract tables of contents from the manual pages. [Bug 627455] * generic/tclClock.c: Expanded mutex protection around the setting of env(TZ) and the thread-unsafe call to tzset(). [Bug 656660] 2003-01-31 Don Porter * tests/tcltest.test: Cleaned up management of file/directory creation/deletion to improve "-debug 1" output. [Bug 675614] The utility [slave] command failed to properly [list]-quote a constructed [open] command, causing failure when the pathname contained whitespace. [Bug 678415] * tests/main.test: Stopped main.test from deleting existing file. Test suite should not delete files that already exist. [Bug 675660] 2003-01-28 Don Porter * tests/main.test: Constrain tests that do not work on Windows. [Bug 674387] 2003-01-28 Vince Darley * generic/tclIOUtil.c: fix to setting modification date in TclCrossFilesystemCopy. Also added 'panic' in Tcl_FSGetFileSystemForPath under illegal calling circumstances which lead to hard-to-track-down bugs. * generic/tclTest.c: added test suite code to allow exercising a vfs-crash-on-exit bug in Tcl's finalization caused by the encodings being cleaned up before unloading occurs. * tests/fileSystem.test: added new 'knownBug' test 7.1 to demonstrate the crash on exit. 2003-01-28 Mo DeJong * generic/tcl.h: Add TCL_PREFIX_IDENT and TCL_DEBUG_IDENT, used only by TclpCreateProcess. * unix/Makefile.in: Define TCL_DBGX. * win/Makefile.in: Define TCL_DBGX. * win/tclWinPipe.c (TclpCreateProcess): Check that the Tcl pipe dll actually exists in the Tcl bin directory and panic if it is not found. Incorporate TCL_DBGX into the Tcl pipe dll name. This fixes a really mysterious error that would show up when exec'ing a 16 bit application under Win95 or Win98 when Tcl was compiled with symbols. The error seemed to indicate that the executable could not be found, but it was actually the Tcl pipe dll that could not be found. 2003-01-26 Mo DeJong * win/README: Update msys+mingw URL to release 6. This version bundles gcc 3. 2003-01-26 Mo DeJong * win/configure: Regen. * win/configure.in: Add test that checks to see if the compiler can cast to a union type. * win/tclWinTime.c: Squelch compiler warning about union initializer by casting to union type when compiling with gcc. 2003-01-25 Mo DeJong * generic/tclIO.c (Tcl_CutChannel, Tcl_SpliceChannel): Invoke TclpCutFileChannel and TclpSpliceFileChannel. * generic/tclInt.h: Declare TclpCutFileChannel and TclpSpliceFileChannel. * unix/tclUnixChan.c (FileCloseProc, TclpOpenFileChannel, (Tcl_MakeFileChannel, TclpCutFileChannel, TclpSpliceFileChannel): Implement thread load data cut and splice for file channels. This avoids an invalid memory ref when compiled with -DDEPRECATED. * win/tclWinChan.c (FileCloseProc, TclpCutFileChannel, (TclpSpliceFileChannel): Implement thread load data cut and splice for file channels. This avoids an invalid memory ref that was showing up in the thread extension. 2003-01-25 Mo DeJong * win/tclWin32Dll.c (TclpCheckStackSpace, squelch_warnings): * win/tclWinChan.c (Tcl_MakeFileChannel, squelch_warnings): * win/tclWinFCmd.c (DoRenameFile, DoCopyFile, squelch_warnings): Re-implement inline ASM SEH handlers for gcc. The esp and ebp registers are now saved on the stack instead of in global variables so that the code is thread safe. Add additional checks when TCL_MEM_DEBUG is defined to be sure the values were recovered from the stack properly. Remove squelch_warnings functions and add a dummy call in the handler methods to squelch compiler warnings. 2003-01-25 Mo DeJong * win/configure: * win/configure.in: Define HAVE_ALLOCA_GCC_INLINE when we detect that no alloca function is found in malloc.h and we are compiling with GCC. Remove HAVE_NO_ALLOC_DECL define. * win/tclWin32Dll.c (TclpCheckStackSpace): Don't define alloca as a cdecl function. Doing this caused a tricky runtime bug because the _alloca function expects the size argument to be passed in a register and not on the stack. To fix this problem, we use inline ASM when compiling with gcc to invoke _alloca with the size argument loaded into a register. 2003-01-24 Jeff Hobbs * win/tclWinDde.c (Dde_Init): clarified use of tsdPtr. (DdeServerProc): better refcount handling of returnPackagePtr. * generic/tclEvent.c (Tcl_Finalize): revert finalize change on 2002-12-04 to correct the issue with extensions that have TSD needing to finalize that before they are unloaded. This issue needs further clarification. * tests/unixFCmd.test: only do groups check on unix 2003-01-24 Vince Darley * generic/tclStringObj.c: proper fixes for Tcl_SetObjLength and Tcl_AttemptSetObjectLength dealing with string objects with both pure-unicode and normal internal representations. Previous fix didn't handle all cases correctly. * generic/tclIO.c: Add 'Tcl_GetString()' to ensure the object has a valid 'objPtr->bytes' field before manipulating it directly. This fixes [Bug 635200] and [Bug 671138], but may reduce performance of Unicode string handling in some cases. A further patch will be applied to address this, once the code is known to be correct. 2003-01-24 Mo DeJong * win/configure: Regen. * win/configure.in: Add test to see if alloca is undefined in malloc.h. * win/tclWin32Dll.c (TclpCheckStackSpace): Rework the SEH exception handler logic to avoid using the stack since alloca will modify the stack. This was causing a nasty bug that would set the exception handler to 0 because it tried to pop the previous exception handler off the top of the stack. 2003-01-23 Donal K. Fellows * doc/lset.n: Fixed fault in return values from lset in documentation examples [SF Bug #658463] and tidied up a bit at the same time. 2003-01-21 Joe English * doc/namespace.n (namespace inscope): Clarified documentation [Patch 670110] 2003-01-21 Mo DeJong * win/configure: Regen. * win/tcl.m4 (SC_CONFIG_CFLAGS): Set SHLIB_SUFFIX so that TCL_SHLIB_SUFFIX will be set to a useful value in the generated tclConfig.sh. Set SHLIB_LD_LIBS to "" or '${LIBS}' based on the --enable-shared flag. This matches the UNIX implementation. 2003-01-18 Jeff Hobbs * generic/tclCkalloc.c: change %ud to %u as appropriate. 2003-01-17 Mo DeJong * win/tclWinDde.c (DdeServerProc): Deallocate the Tcl_Obj returned by ExecuteRemoteObject if it was not saved in a connection object. 2003-01-17 Mo DeJong * generic/tcl.h: Revert earlier change that defined TCL_WIDE_INT_TYPE as long long and TCL_LL_MODIFIER as L when compiling with mingw. This change ended up causing some test case failures when compiling with mingw. * generic/tclObj.c (UpdateStringOfWideInt): Describe the warning generated by mingw and why it needs to be ignored so that someone is not tempted to "fix" this problem again in the future. 2003-01-16 Vince Darley * generic/tclStringObj.c: Tcl_SetObjLength fix for when the object has a unicode string rep. [Bug 635200] * tests/stringObj.test: removed 'knownBug' constraint from test 14.1 now that this bug is fixed. * generic/tclInt.h: * generic/tclBasic.c: * generic/tclCmdMZ.z: * tests/trace.test: execution and command tracing bug fixes and cleanup. In particular fixed [Bug 655645], [Bug 615043], [Bug 571385] - fixed some subtle cleanup problems with tracing. This required replacing Tcl_Preserve/Tcl_Release with a more robust refCount approach. Solves at least one known crash caused by memory corruption. - fixed some confusion in the code between new style traces (Tcl 8.4) and the very limited 'Tcl_CreateTrace' which existed before. - made behaviour consistent with documentation (several tests even contradicted the documentation before). - fixed some minor error message details - added a number of new tests 2003-01-16 Jeff Hobbs * win/tclWinSerial.c (SerialOutputProc): add casts for bytesWritten to allow strict compilation (no warnings). * tests/winDde.test: * win/tclWinDde.c (Tcl_DdeObjCmd): Prevent crash when empty service name is passed to 'dde eval' and goto errorNoResult in request and poke error cases to free up any allocated data. 2003-01-16 Mo DeJong * win/tclWin32Dll.c (squelch_warnings): Squelch compiler warnings from SEH ASM code. * win/tclWinChan.c (squelch_warnings): Squelch compiler warnings from SEH ASM code. * win/tclWinDde.c: Add casts to avoid compiler warnings. Pass pointer to DWORD instead of int to avoid compiler warnings. * win/tclWinFCmd.c (squelch_warnings): Add casts and fixup decls to avoid compiler warnings. Squelch compiler warnings from SEH ASM code. * win/tclWinFile.c: Add casts and fixup decls to avoid compiler warnings. Remove unused variable. * win/tclWinNotify.c: Declare as DWORD instead of int to avoid compiler warning. * win/tclWinReg.c: Add casts to avoid compiler warning. Fix assignment in if expression bug. * win/tclWinSerial.c: Add casts to avoid compiler warnings. Remove unused variable. * win/tclWinSock.c: Add casts and fixup decls to avoid compiler warnings. 2003-01-14 Jeff Hobbs * generic/tclClock.c (FormatClock): corrected typo that incorrectly conditionally defined savedTZEnv and savedTimeZone. 2003-01-13 Mo DeJong Fix mingw build problems and compiler warnings. * generic/tcl.h: Add if defined(__MINGW32__) check to code that sets the TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER. * generic/tclClock.c (FormatClock): Don't define savedTimeZone and savedTZEnv if we are not going to use them. * generic/tclEnv.c: Add cast to avoid warning. * win/tclWinChan.c: Use DWORD instead of int to avoid compiler warning * win/tclWinThrd.c: Only define allocLock, allocLockPtr, and dataKey when TCL_THREADS is defined. This avoid a compiler warning about unused variables. 2003-01-12 Mo DeJong * win/README: Update msys + mingw URL, the new release includes the released 1.0.8 version of msys which includes a number of bug fixes. 2003-01-12 Mo DeJong * win/configure: Regen. * win/tcl.m4 (SC_CONFIG_CFLAGS): Pull in addition of shell32.lib to LIBS_GUI that was added to the Tk tcl.m4 but never made it back into the Tcl version. 2003-01-12 Mo DeJong * generic/tcl.h: Skip Tcl's define of CHAR, SHORT, and LONG when HAVE_WINNT_IGNORE_VOID is defined. This avoids a bunch of compiler warnings when building with Cygwin or Mingw. * win/configure: Regen. * win/configure.in: Define HAVE_WINNT_IGNORE_VOID when we detect a winnt.h that still defines CHAR, SHORT, and LONG when VOID has already been defined. * win/tcl.m4 (SC_LOAD_TCLCONFIG): Subst the TCL_DEFS loaded from tclConfig.sh so that Tcl defines can make it into the Tk Makefile. 2003-01-12 Mo DeJong * win/configure: Regen. * win/configure.in: Check for typedefs like LPFN_ACCEPT in winsock2.h and define HAVE_NO_LPFN_DECLS if not found. * win/tclWinSock.c: Define LPFN_* typedefs if HAVE_NO_LPFN_DECLS is defined. This fixes the build under Mingw and Cygwin, it was broken by the changes made on 2002-11-26. 2003-01-10 Vince Darley * generic/tclIOUtil.c: * win/tclWinInt.h: * win/tclWinInit.c: fix to new WinTcl crash on exit with vfs, introduced on 2002-12-06. Encodings must be cleaned up after the filesystem. * win/makefile.vc: fix to minor VC++ 5.2 syntax problem 2003-01-09 Don Porter * generic/tclCompCmds.c (TclCompileReturnCmd): Corrected off-by-one problem with recent commit. [Bug 633204] 2003-01-09 Vince Darley * generic/tclFileName.c: remove unused variable 'macSpecialCase' [Bug 664749] * generic/tclIOUtil.c: * generic/tclInt.h: * unix/tclUnixFile.c: * mac/tclMacFile.c: * win/tclWinFile.c: * win/tclWinInt.h: * win/tclWin32Dll.c: * tests/cmdAH.test: fix to non-ascii chars in paths when setting mtime and atime through 'file (a|m)time $path $time'. [Bug 634151] 2003-01-08 Don Porter * generic/tclExecute.c (TclExprFloatError): Use the IS_NAN macro for greater clarity of code. 2003-01-07 Don Porter * generic/tclCompCmds.c (TclCompileReturnCmd): * tests/compile.test: Corrects failure of bytecompiled [catch {return}] to have result TCL_RETURN (not TCL_OK) [Bug 633204]. This patch is a workaround for 8.4.X. A new opcode INST_RETURN is a better long term solution for 8.5 and later. 2003-01-04 David Gravereaux * win/makefile.vc: * win/rules.vc: Fixed INSTALLDIR macro problem that blanked itself by accident causing the install target to put the tree at the root of the drive built on. Whoops.. Renamed the 'linkexten' option to be 'staticpkg'. Added 'thrdalloc' to allow the switching _on_ of the thread allocator. Under testing, I found it not to be benificial under windows for the purpose of the application I was using it for. It was more important for this app that resources for tcl threads be returned to the system rather than saved/moved to the global recycler. Be extra clean or extra fast for the default threaded build? Let's move to clean and allow it to be switched on for users who find it benificial for their use of threads. ****************************************************************** *** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002" *** *** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" *** *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" *** *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" *** ****************************************************************** tcl8.6.5/ChangeLog.20080000644000175000017500000042176112663653206013743 0ustar sergeisergei2008-12-31 Don Porter * unix/Makefile.in: Set TCLLIBPATH in SHELL_ENV so that targets like `make shell` have access to builds of bundled packages. 2008-12-28 Donal K. Fellows * generic/tclZlib.c (Tcl_ZlibStreamPut): Plug a memory leak. 2008-12-27 Donal K. Fellows * generic/tclZlib.c (ZlibStreamCmd): Fix compilation consistency. [Bug * generic/tcl.decls: 2470237] * generic/tclZlib.c (Tcl_ZlibStreamGet): Corrected the semantics of this function to be useful to the PNG implementation. If the argument object is empty, this gives the previous semantics. (Tcl_ZlibStreamChecksum): Corrected name to be less misleading; it only produced Adler-32 checksums when the stream was processing the right type of compressed data format. (Tcl_ZlibAdler32, Tcl_ZlibCRC32): Corrected types so that they work naturally with the results of Tcl_GetByteArrayFromObj(). *** POTENTIAL INCOMPATIBILITY *** for all above changes, but very unlikely to be difficult for anyone to deal with. 2008-12-26 Donal K. Fellows * generic/tcl.decls: Tidy up the commenting style, adding markers for each of the big release points under TCT stewardship and noting the general purpose of each TIP that added C API. Overall effect is to make this file much more informative to read without having to spend effort correlating with TIPs and ChangeLogs. 2008-12-23 Jan Nijtmans * win/Makefile.in: Fix build of zlib objects with msvc * win/tcl.m4: * win/configure: autoconf-2.59 2008-12-23 Donal K. Fellows * win/Makefile.in: Handle file extensions correctly. [Bug 2459725] 2008-12-22 Pat Thoyts *** 8.6b1 TAGGED FOR RELEASE *** * win/makefile.vc: Ensure pkgs directories are suitable and quote the paths. [Bug 2458395] 2008-12-22 Joe Mistachkin * tools/man2help2.tcl: Added support for "\(mi" nroff macro. [Bug 2330040] 2008-12-22 Pat Thoyts * win/makefile.vc: Support the pkgs tree in the NMAKE builds. 2008-12-21 Daniel Steffen * unix/Makefile.in: Fix broken build of bundled packages when path to build dir contains spaces by switching to relative paths to toplevel build dir. * unix/configure.in: Preserve configure environment variables for sub-configures of bundled packages; reuse configure cache file for sub-configures. * unix/configure: autoconf-2.59 2008-12-21 Donal K. Fellows * doc/TclZlib.3: Fix minor typo. [Bug 2455165] 2008-12-20 Kevin B. Kenny * win/Makefile.in: Renamed the static library libtcl86s.a to * win/configure.in: have a name distinct from the import library libtcl86.a. This renaming dodges an ancient bug in the Makefile revealed by the last commit where the $(TCL_LIB_FILE) rule can fire to try to build the static library in a --enable-shared build (and create a static library that subsequently fails to link). Revised the zlib objects so that they are built directly into the build dir, without building an intermediate static library. *** POTENTIAL INCOMPATIBILITY *** for embedders who link to the static library, but I couldn't figure out how to sort this out any other way. * win/configure: Autoconf 2.59 2008-12-20 Donal K. Fellows * win/Makefile.in: Minor updates to make building work better with msys on Windows. (Apparently the gcc used doesn't like a / at the end of a -I argument...) 2008-12-20 Don Porter * changes: Updates for 8.6b1 release. 2008-12-20 Daniel Steffen * unix/Makefile.in: Make package install directory of bundled * unix/configure.in: packages configurable via PACKAGE_DIR makefile variable (set to platform-specific default). * unix/Makefile.in (*-packages): Ensure toplevel targets fail if sub-make/configure fails; fix quoting when builddir path contains spaces. * macosx/GNUmakefile: Add install-packages to install targets. * unix/configure: autoconf-2.59 2008-12-19 Don Porter * doc/NRE.3: Formatting errors found by `make html` * doc/Tcl_Main.3: * doc/zlib.n: * tests/chanio.test: Add missing [removeFile] cleanups. * tests/io.test: Add missing [close $f] to io-73.2. * unix/Makefile.in: Update `make dist' target to include the files from the compat/zlib directory as well as all the bundled packages found under the pkgs directory, according to their individual `make dist' targets. Change includes breaking a `configure-packages' target out of the `packages` target. * README: Bump version number to 8.6b1 * generic/tcl.h: * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf-2.59 * win/configure: 2008-12-19 Jan Nijtmans * generic/tclInt.decls: CONSTify TclGetLoadedPackages second param * generic/tclLoad.c * generic/tclIntDecls.h (regenerated) 2008-12-19 Kevin Kenny * generic/tclExecute.c: Fix compile warnings when --enable-symbols=all * win/configure.in: * win/Makefile.in: Added build of packages in the 'pkgs/' directory. * win/configure: Autoconf 2.59 2008-12-19 Pat Thoyts * win/makefile.vc: Added build of compat/zlib 2008-12-18 Andreas Kupries * generic/tclIO.c (Tcl_CloseEx, CloseWrite, CloseChannelPart) (ChanCloseHalf): Rewrite the half-close to properly flush the channel, like is done for a full close, going through FlushChannel, and using the flag BG_FLUSH_SCHEDULED (async flush during close). New functions CloseWrite, CloseChannelPart, new flag CHANNEL_CLOSEDWRITE. * tests/chanio.test (chanio-28.[67]): Reactivated these tests. Replaced tclsh -> [interpreter] to get correct executable for the pipe process, and added after cancel to kill the fail timers when we are done. Removed the explicits calls to [flush], now that [close] handles this correctly. 2008-12-18 Don Porter * tests/chanio.test: Replaced [chan event] handlers that returned TCL_RETURN return code, with more conventional ones that return TCL_OK to suppress otherwise strange writes of outdated $::errorInfo values to stderr. [Bug 2444274] * generic/tclExecute.c: Disabled apparently faulty assertion. [Bug 2415422] 2008-12-18 Donal K. Fellows * unix/configure.in, unix/Makefile.in: Autoconf wizardry. * compat/zlib/*: Import of zlib 1.2.3. The license is directly compatible with Tcl's. This import omits the obsolete and contributed parts (i.e. selected directories) and the supplied examples. * generic/tclZlib.c: First implementation of the compressing and * doc/zlib.n: decompressing channel transformations. * tests/zlib.test (zlib-8.*): 2008-12-18 Jan Nijtmans * generic/tcl.decls: VOID -> void * generic/tclInt.decls: * compat/dlfcn.h: * generic/tclDecls.h: (regenerated) * generic/tclIntDecls.h: 2008-12-18 Alexandre Ferrieux TIP #332 IMPLEMENTATION - Half-Close for Bidirectional Channels * doc/close.n, generic/tclIO.c, generic/tclIOCmd.c: * unix/tclUnixChan.c, unix/tclUnixPipe.c, win/tclWinSock.c: * generic/tcl.decls, generic/tclDecls.h, generic/tclStubInit.c: * tests/chan.test, tests/chanio.test, tests/ioCmd.test: 2008-12-17 Donal K. Fellows * doc/SetChanErr.3: General improvements in nroff rendering and some corrections to language issues. 2008-12-17 Jan Nijtmans * generic/tclResult.c: Move variable "length" inside if() * generic/tclStringObj.c: Don't use ckfree((void *)...) but * generic/tclVar.c: ckfree((char *)...) * generic/tclZlib.c * generic/tclBasic.c 2008-12-17 Donal K. Fellows * tests/namespace.test (namespace-28.1): Make tests not * tests/namespace-old.test (namespace-old-9.5): dependent on the global namespace's particular imports. [Bug 2433936] 2008-12-17 Don Porter * unix/Makefile.in: Modify the distclean-packages target so that empty build directories are deleted. * unix/Makefile.in: Add build support for collections of TEA * unix/configure.in: packages found under the pkgs directory. [Patch 1163406]. Still needs porting to Windows. * unix/configure: autoconf-2.59 2008-12-17 Donal K. Fellows * generic/tcl.h, generic/tclZlib.c: Removed undocumented flag. 2008-12-16 Jan Nijtmans * generic/tclThreadTest.c: Eliminate -Wwrite-strings warnings in --enable-threads build. * generic/tclExecute.c: Use TclNewLiteralStringObj() * unix/tclUnixFCmd.c: Use TclNewLiteralStringObj() * win/tclWinFCmd.c: Use TclNewLiteralStringObj() 2008-12-16 Donal K. Fellows TIP #329 IMPLEMENTATION * tests/error.test: Tests for the new commands. * doc/throw.n, doc/try.n: Documentation of the new commands. * library/init.tcl (throw, try): Implementation of commands documented in TIP. This implementation is in Tcl and is a stop-gap until higher-performance ones can be written. 2008-12-16 Don Porter * generic/tcl.h: Add TIP 338 routines to stub table. * generic/tcl.decls: [Bug 2431338] * generic/tclDecls.h: make genstubs * generic/tclStubInit.c: 2008-12-15 Donal K. Fellows * generic/tclExecute.c (TEBC:INST_DICT_GET): Make sure that the result is empty when generating an error message. [Bug 2431847] 2008-12-15 Alexandre Ferrieux * generic/tclBinary.c: Redefine non-strict decoding to ignore only * doc/binary.n: whitespace. [Bug 2380293] * tests/binary.test: 2008-12-15 Don Porter * doc/AddErrInfo.3: Documented Tcl_(Set|Get)ErrorLine (TIP 336). * doc/CrtCommand.3: Various other documentation updates to * doc/CrtInterp.3: reflect the lack of access to Tcl_Interp * doc/Interp.3: fields by default. * doc/SetResult.3: * doc/tcl.decls: TIP #338 IMPLEMENTATION * doc/AppInit.c: Made routines Tcl_SetStartupScript and * doc/Tcl_Main.3: Tcl_GetStartupScript public. Removed all * generic/tcl.h: internal stub access to Tcl*Startup* routines, * generic/tclInt.decls: and removed their implementations. Their * generic/tclMain.c: function can now be completely performed with the new public interface. *** POTENTIAL INCOMPATIBILITY for callers of the internal Tcl*Startup* routines. *** * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclDecls.h: 2008-12-14 Donal K. Fellows * tests/zlib.test: Added constraint so that tests don't fail where they cannot work due to zlib support being missing. * unix/configure.in, win/configure.in: Improve the autodetection code. * win/tcl.m4 (SC_CONFIG_CFLAGS): Remove the assumption of the presence of zlib library on Windows. * win/makefile.vc, win/makefile.bc: Add support for building tclZlib.o but only in stubbed-out mode for now. 2008-12-13 Donal K. Fellows * doc/TclZlib.3: Basic documentation of the C-level API. * doc/zlib.n: Substantially improve documentation of Tcl-level API. * generic/tclZlib.c (ZlibCmd): Flesh out the argument parsing for the command to integrate with channels. 2008-12-12 Jan Nijtmans * generic/tclZlib.c (Tcl_ZlibInflate): Change PATH_MAX to MAXPATHLEN, since MSVC doesn't have PATH_MAX. * doc/clock.n: Document new DST fallback rules. * library/clock.tcl (ProcessPosixTimeZone): Fix time change in Eastern Europe (not 3:00 but 4:00 local time). [Bug 2207436] 2008-12-12 Donal K. Fellows * generic/tclZlib.c, unix/configure.in: Added stubs to use when the version of zlib is not capable enough, and automagic to detect when that is the case. [Bug 2421265] 2008-12-12 Alexandre Ferrieux * unix/tclUnixNotfy.c: Fix missing CLOEXEC on internal pipes [2417695] * unix/tclUnixPipe.c: Fix missing CLOEXEC on [chan pipe] fds. 2008-12-12 Donal K. Fellows * generic/tclZlib.c (Tcl_ZlibDeflate): Add a bit of extra space for the gzip header. [Bug 2419061] (Tcl_ZlibInflate): Ensure that gzip header extraction is done correctly. 2008-12-12 Kevin Kenny TIP #322 IMPLEMENTATION * doc/NRE.3 (new file): Added documentation of the published API for Non-Recursive Evaluation (NRE). 2008-12-11 Jan Nijtmans * generic/tclZlib.c: Eliminate warning: different 'const' qualifiers with msvc compiler. A few more 'const' optimizations. * win/tcl.m4: Fix Windows build (msvc) for TIP #234 implementation * win/Makefile.in: * win/configure: 2008-12-11 Andreas Kupries * generic/tclIO.c (SetChannelFromAny and related): Modified the * tests/io.test: internal representation of the tclChannelType to contain not only the ChannelState pointer, but also a reference to the interpreter it was made in. Invalidate and recompute the internal representation when it is used in a different interpreter, like cmdName intrep's. Added testcase. [Bug 2407783] 2008-12-11 Donal K. Fellows * generic/tclZlib.c (ConvertError): Factor out code to turn zlib errors into Tcl errors. * doc/zlib.n: Added a start at the documentation. Still very rough. 2008-12-11 Jan Nijtmans * win/Makefile.in: Fix Windows build (mingw) for TIP #234 implementation (additionally, first make sure that zlib is available, and rename the standard zdll.lib to libz.a, but at least this works so far). 2008-12-11 Donal K. Fellows * tests/zlib.test: Start of test suite for zlib command. 2008-12-11 Jan Nijtmans * library/clock.tcl (ProcessPosixTimeZone): Fallback to European time zone DST rules, when the timezone is between 0 and -12. [Bug 2207436] * tests/clock.test (clock-52.[23]): Test cases for [Bug 2207436] 2008-12-11 Donal K. Fellows TIP #234 IMPLEMENTATION * generic/tclZlib.c: A very preliminary hack at an interface to the zlib library, based on code from Pascal Scheffers. WARNING! The C API may be subect to change without much warning! USE AT YOUR OWN RISK! 2008-12-10 Kevin B. Kenny * library/tzdata/*: Update from Olson's tzdata2008i. 2008-12-10 Alexandre Ferrieux TIP #343 IMPLEMENTATION - A Binary Specifier for [format/scan] * doc/format.n * doc/scan.n * generic/tclInt.h * generic/tclScan.c * generic/tclStrToD.c * generic/tclStringObj.c * tests/format.test * tests/scan.test 2008-12-10 Donal K. Fellows TIP #341 IMPLEMENTATION * generic/tclDictObj.c (DictFilterCmd): Made key and value filtering * tests/dict.test, doc/dict.n: accept arbitrary numbers of glob arguments. 2008-12-09 Jan Nijtmans * generic/tclInt.decls: Restore source and binary compatibility for TIP #337 implementation. (When it is _that_ simple, there is no excuse not to do it! :-)) * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: 2008-12-09 Don Porter TIP #337 IMPLEMENTATION * doc/BackgdErr.3: Converted internal routine * doc/interp.n: TclBackgroundException() into public routine * generic/tcl.decls: Tcl_BackgroundException(). * generic/tclEvent.c: * generic/tclInt.decls: * generic/tclDecls.h: make genstubs * generic/tclIntDecls.h: * generic/tclStubInit.c: * generic/tclIO.c: Update callers. * generic/tclIOCmd.c: * generic/tclInterp.c: * generic/tclTimer.c: *** POTENTIAL INCOMPATIBILITY only for extensions using the converted internal routine *** 2008-12-09 Donal K. Fellows * generic/tclIO.c (ChanClose,ChanRead,...): Factored out some of the code to connect to channel drivers that was common in multiple locations so as to make code more readable. 2008-12-06 Donal K. Fellows * generic/tclCmdAH.c (FileTempfileCmd): Force temporary files to be created in the native filesystem. Attempting to provide a template that puts it elsewhere will result in the directory part of the template being ignored. Partial address of [Bug 2388866] concerns. 2008-12-05 Donal K. Fellows TIP #335 IMPLEMENTATION * generic/tclBasic.c (Tcl_InterpActive): Added function for working * doc/CrtInterp.3: out if an interp is in use. TIP #307 IMPLEMENTATION * generic/tclResult.c (Tcl_TransferResult): Renamed function from * generic/tcl.decls: TclTransferResult. Added * doc/SetResult.3: to public stubs table. 2008-12-04 Don Porter * generic/tclPathObj.c (Tcl_FSGetNormalizedPath): Added another flag value TCLPATH_NEEDNORM to mark those intreps which need more complete normalization attention for correct results. [Bug 2385549] 2008-12-03 Donal K. Fellows * win/tclWinPipe.c (TclpOpenTemporaryFile): Avoid an infinite loop due to GetTempFileName/CreateFile interaction. [Bug 2380318] 2008-12-03 Don Porter * generic/tclFileName.c (DoGlob): One of the Tcl_FSMatchInDirectory calls did not have its return code checked. This caused error messages returned by some Tcl_Filesystem drivers to be swallowed. 2008-12-02 Don Porter TIP #336 IMPLEMENTATION * generic/tcl.decls: New routines Tcl_(Get|Set)ErrorLine. * generic/tcl.h: Dropped default access to interp->errorLine. * generic/tclCmdAH.c: Restore it with -DUSE_INTERP_ERRORLINE. * generic/tclCmdMZ.c: Updated callers. * generic/tclDictObj.c: * generic/tclIOUtil.c: * generic/tclNamesp.c: * generic/tclOOBasic.c: * generic/tclOODefinedCmds.c: * generic/tclOOMethod.c: * generic/tclProc.c: * generic/tclResult.c: *** POTENTIAL INCOMPATIBILITY for C code directly using the interp->errorLine field *** * generic/tclDecls.h: make genstubs * generic/tclStubInit.c: 2008-12-02 Andreas Kupries * generic/tclIO.c (TclFinalizeIOSubsystem): Replaced Alexandre Ferrieux's first patch for [Bug 2270477] with a gentler version, also supplied by him. 2008-12-01 Don Porter * generic/tclParse.c: Coding standards fixups. 2008-12-01 Donal K. Fellows * tests/cmdAH.test (cmdAH-32.6): Test was not portable; depended on a C API function not universally available. [Bug 2371623] 2008-11-30 Kevin B. Kenny * library/clock.tcl (format, ParseClockScanFormat): Added a [string map] to get rid of namespace delimiters before caching a scan or format procedure. [Bug 2362156] * tests/clock.test (clock-64.[12]): Added test cases for the bug that was tickled by a namespace delimiter inside a format string. 2008-11-29 Donal K. Fellows TIP #210 IMPLEMENTATION * generic/tclCmdAH.c (FileTempfileCmd): * unix/tclUnixFCmd.c (TclpOpenTemporaryFile, DefaultTempDir): * win/tclWinPipe.c (TclpOpenTemporaryFile): * doc/file.n, tests/cmdAH.test: Implementation of [file tempfile]. I do not claim that this is a brilliant implementation, especially on Windows, but it covers the main points. * generic/tclThreadStorage.c: General revisions to make code clearer and more like the style used in the rest of the core. Includes adding more comments and explanation of what is going on. Reduce the amount of locking required. 2008-11-27 Alexandre Ferrieux * generic/tcl.h: Alternate fix for [Bug 2251175]: missing * generic/tclCompile.c: backslash substitution on expanded literals. * generic/tclParse.c: * generic/tclTest.c: * tests/parse.test: 2008-11-26 Jan Nijtmans * generic/tclIndexObj.c: Eliminate warning: unused variable * generic/tclTest.c: A few more (harmless) Tcl_SetResult eliminations. 2008-11-26 Kevin B. Kenny * library/tclIndex: Removed reference to no-longer-extant procedure 'tclLdAout'. * doc/library.n: Corrected mention of 'auto_exec' to 'auto_execok'. [Patch 2114900] thanks to Stuart Cassoff 2008-11-25 Jan Nijtmans * generic/tclIndexObj.c: Eliminate 3 calls to Tcl_SetResult, as * generic/tclIO.c: examples how it should have been done. * generic/tclTestObj.c: purpose: contribute in the TIP #340 discussion. 2008-11-25 Andreas Kupries * generic/tclIO.c (TclFinalizeIOSubsystem): Applied Alexandre Ferrieux's patch for [Bug 2270477] to prevent infinite looping during finalization of channels not bound to interpreters. 2008-11-25 Jan Nijtmans * generic/tclTest.c: Don't assume that Tcl_SetResult sets interp->result, especially not in a DString test, in preparation for TIP #340 2008-11-24 Donal K. Fellows * tools/tcltk-man2html.tcl: Improvements to tackle tricky aspects of cross references and new entities to map. [Bug 2330040] 2008-11-19 Jan Nijtmans * generic/tclThreadTest.c: Convert Tcl_SetResult(......, TCL_DYNAMIC) to Tcl_SetResult(......, TCL_VOLATILE), in preparation for TIP #340 2008-11-17 Jan Nijtmans * generic/tcl.decls: Fix signature and implementation of * generic/tclDecls.h: Tcl_HashStats, such that it conforms to the * generic/tclHash.c: documentation. [Bug 2308236] * generic/tclVar.c: * doc/Hash.3: * generic/tclDictObj.c: Convert Tcl_SetResult call to Tcl_SetObjResult. 2008-11-17 Alexandre Ferrieux * tests/for.test: Check for uncompiled-for-continue [Bug 2186888] fixed earlier. * generic/tcl.h: Fix [Bug 2251175]: missing backslash * generic/tclCompCmds.c: substitution on expanded literals. * generic/tclCompile.c * generic/tclParse.c * generic/tclTest.c * tests/compile.test * tests/parse.test 2008-11-16 Jan Nijtmans * generic/tclTest.c: Replace two times Tcl_SetResult with Tcl_SetObjResult, a little simplification in preparation for the TIP #340 patch. 2008-11-13 Jan Nijtmans * generic/tclInt.h: Rename static function FSUnloadTempFile to * generic/tclIOUtil.c: TclFSUnloadTempFile, needed in tclLoad.c * generic/tclLoad.c: Fixed [Bug 2269431]: Load of shared objects leaves temporary files on windows. 2008-11-12 Pat Thoyts * tests/registry.test: Use HKCU to avoid requiring admin access for registry testing on Vista/Server2008 2008-11-11 Jan Nijtmans * generic/tclNamesp.c: Eliminate warning: passing arg 4 of Tcl_SplitList from incompatible pointer type. * win/tcl.m4: Reverted change from 2008-11-06 (was under the impression that "-Wno-implicit-int" added an extra warning) * win/configure: (regenerated) * unix/tcl.m4: Use -O2 as gcc optimization compiler flag, and get rid of -Wno-implicit-int for UNIX. * unix/configure: (regenerated) 2008-11-10 Andreas Kupries * doc/platform_shell.n: Fixed [Bug 2255235], reported by Ulrich * library/platform/pkgIndex.tcl: Ring . * library/platform/shell.tcl: Updated the LOCATE command in the * library/tm.tcl: package 'platform::shell' to handle the new form * unix/Makefile.in: of 'provide' commands generated by tm.tcl. Bumped * win/Makefile.in: package to version 1.1.4. Added cross-references to the relevant parts of the code to avoid future desynchronization. 2008-11-07 Pat Thoyts * generic/tclInt.h: Applied [Patch 2215022] from Duoas to clean up * generic/tclBinary.c: the binary ensemble initiailization code. * generic/tclNamesp.c: Extends the TclMakeEnsemble to do * doc/ByteArrObj.3: sub-ensembles from tables. 2008-11-06 Jan Nijtmans * win/tcl.m4: Add "-Wno-implicit-int" flag for gcc, as on UNIX * win/configure: (regenerated) * generic/tclIO.c: Eliminate an 'array index out of bounds' warning on HP-UX. 2008-11-04 Jeff Hobbs * generic/tclPort.h: Remove the ../win/ header dir as the build system already has it, and it confuses builds when used with private headers installed. 2008-11-01 Donal K. Fellows * generic/tclOO.h (TCLOO_VERSION): Bump version of TclOO. 2008-10-31 Donal K. Fellows * generic/tclOOBasic.c (TclOONRUpcatch): Reworked the code that does * generic/tclOO.c (InitFoundation): class constructor handling so that it is more robust and runs the constructor call in the context of the caller of the class's constructor method. Needed because the previously used code did not work at all after applying the fix below; no Tcl existing command could reliably do what was needed any more. * generic/tclOODefineCmds.c (GetClassInOuterContext): Rework and factor out the code to resolve class names in definitions so that classes are resolved from the perspective of the caller of the [oo::define] command, rather than from the oo::define namespace! This makes much code simpler by reducing how often fully-qualified names are required (previously always in practice, so no back-compat issues exist). [Bug 2200824] 2008-10-28 Jan Nijtmans * generic/tclCompile.h: CONSTify TclDTraceInfo * generic/tclBasic.c: * generic/tclProc.c: * generic/tclEnv.c: Eliminate some -Wwrite-strings warnings * generic/tclLink.c: 2008-10-27 Don Porter * generic/tclEncoding.c: Use "iso8859-1" and not "identity" as the default and original [encoding system] value. Since "iso8859-1" is built in to the C source code for Tcl now, there's no availability issue, and it has the good feature of "identity" that we must have ("bytes in" == "bytes out") without the bad feature of "identity" ("broken as designed") that makes us want to abandon it. [RFE 2008609] *** POTENTIAL INCOMPATIBILITY for older releases of Tclkit and any other code expecting a particular value for Tcl's default system encoding *** 2008-10-24 Pat Thoyts * library/http/http.tcl: Fixed a failure to read SHOUTcast streams with the new 2.7 package. Introduced a new intial state as the first response may not be HTTP*. 2008-10-23 Miguel Sofer * generic/tclCmdAH.c (ForNextCallback): handle TCL_CONTINUE in the for body. [Bug 2186888] 2008-10-22 Jan Nijtmans * generic/tcl.h: CONST -> const and white-spacing * generic/tclCompile.h: * generic/tclEncoding.c: * generic/tclStubInit.c: * generic/tclStubLib.c: * generic/tcl.decls * generic/tclInt.decls * generic/tclTomMath.decls * generic/tclDecls.h: (regenerated) * generic/tclIntDecls.h: (regenerated) * generic/tclIntPlatDecls.h: (regenerated) * generic/tclOODecls.h: (regenerated) * generic/tclOOIntDecls.h: (regenerated) * generic/tclPlatDecls.h: (regenerated) * generic/tclTomMathDecls.h: (regenerated) * generic/tclIntDecls.h: (regenerated) * tools/genStubs.tcl: CONST -> const and white-spacing 2008-10-19 Don Porter * generic/tclProc.c: Reset -level and -code values to defaults after they are used. [Bug 2152286] 2008-10-19 Donal K. Fellows * generic/tclBasic.c (TclInfoCoroutineCmd): Added code to make this check for being invoked in a syntactically correct way. * doc/info.n: Added documentation of [info coroutine]. * doc/prefix.n: Improved the documentation by fixing formatting, adding good-practice recommendations and cross-references, etc. 2008-10-17 Jan Nijtmans * generic/tclOO.decls: CONST -> const. * generic/tclOODecls.h: (regenerated) * generic/tclOOIntDecls.h: (regenerated) 2008-10-17 Andreas Kupries * generic/tclIORTrans.c (DeleteReflectedTransformMap): Removed debug output in C++ comment. 2008-10-17 Don Porter * generic/tclCompile.h: Declare the internal tclInstructionTable to * generic/tclExecute.c: simply be "const", not CONST86. * generic/tclCmdAH.c: whitespace. * generic/tclCmdIL.c: Uninitialized variable warning. * generic/tclTest.c: const correctness warning. 2008-10-17 Donal K. Fellows * doc/*: Many very small formatting fixes. * doc/{glob,http,if}.n: More substantial reformatting for clarity. * doc/split.n: Remove mention of defunct c.l.t.announce 2008-10-16 Jan Nijtmans * generic/regc_locale.c: Add "const" to many internal const tables. * generic/tclClock.c: No functional or API change. * generic/tclCmdIL.c * generic/tclConfig.c * generic/tclDate.c * generic/tclEncoding.c * generic/tclEvent.c * generic/tclExecute.c * generic/tclFileName.c * generic/tclGetDate.y * generic/tclInterp.c * generic/tclIO.c * generic/tclIOCmd.c * generic/tclIORChan.c * generic/tclIORTrans.c * generic/tclLoad.c * generic/tclObj.c * generic/tclOOBasic.c * generic/tclOOCall.c * generic/tclOOInfo.c * generic/tclPathObj.c * generic/tclPkg.c * generic/tclResult.c * generic/tclStringObj.c * generic/tclTest.c * generic/tclTestObj.c * generic/tclThreadTest.c * generic/tclTimer.c * generic/tclTrace.c * macosx/tclMacOSXFCmd.c * win/cat.c * win/tclWinInit.c * win/tclWinTest.c 2008-10-16 Don Porter * library/init.tcl: Revised [unknown] so that it carefully preserves the state of the ::errorInfo and ::errorCode variables at the start of auto-loading and restores that state before the autoloaded command is evaluated. [Bug 2140628] 2008-10-15 Jan Nijtmans * generic/tclInt.h: Add "const" to many internal const tables, so * generic/tclBinary.c: those will be put by the C-compiler in the * generic/tclCompile.c: TEXT segment in stead of the DATA segment. * generic/tclDictObj.c: This makes those tables sharable in shared * generic/tclHash.c: libraries. * generic/tclListObj.c: * generic/tclNamesp.c: * generic/tclObj.c: * generic/tclProc.c: * generic/tclRegexp.c: * generic/tclStringObj.c: * generic/tclUtil.c: * generic/tclVar.c: 2008-10-14 Jan Nijtmans * generic/tclCmdAH.c: Fix minor compiler warnings when compiling * generic/tclCmdMZ.c: with -Wwrite-strings. * generic/tclIndexObj.c: * generic/tclProc.c: * generic/tclStubLib.c: * generic/tclUtil.c: * win/tclWinChan.c: * win/tclWinDde.c: * win/tclWinInit.c: * win/tclWinReg.c: * win/tclWinSerial.c: 2008-10-14 Donal K. Fellows * doc/binary.n: Formatting fix. 2008-10-14 Don Porter * README: Bump version number to 8.6a4 * generic/tcl.h: * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf-2.59 * win/configure: * generic/tclExecute.c: Fix compile warnings when --enable-symbols=all * generic/tclCmdIL.c: Fix write to unallocated memory whenever [lrepeat] returns an empty list. 2008-10-14 Donal K. Fellows * doc/chan.n, doc/fconfigure.n: Added even more emphatic text to direct people to the correct manual pages for specific channel types, suitable for the hard-of-reading. Following discussion on tcl-core. 2008-10-13 Pat Thoyts * win/tclWinThrd.c (TclpThreadCreate): We need to initialize the thread id variable to 0 as on 64 bit windows this is a pointer sized field while windows only fills it with a 32 bit value. The result is an inability to join the threads as the ids cannot be matched. * generic/tclTest.c (TestNRELevels): Set array to the right size. 2008-10-13 Donal K. Fellows * generic/tclOOInfo.c (InfoClassDestrCmd): Handle error case. * generic/tclOOInt.h: Added macro magic to make things work with Objective C. [Bug 2163447] 2008-10-12 Miguel Sofer * generic/tclCompile.c: Fix bug in srcDelta encoding within ByteCodes. The bug can only be triggered under conditions that cannot happen in Tcl, but were met during development of L. Thanks go to Robert Netzer for diagnosis and fix. 2008-10-10 Don Porter *** 8.6a3 TAGGED FOR RELEASE *** * changes: Updates for 8.6a3 release. 2008-10-10 Donal K. Fellows * generic/tclOODefineCmds.c (TclOODefineUnexportObjCmd) (TclOODefineExportObjCmd): Corrected export/unexport record synthesis. [Bug 2155658] 2008-10-08 Jan Nijtmans * unix/tclUnixChan.c: Fix minor compiler warning. * unix/tcl.m4: Fix for [Bug 2073255] * unix/configure: Regenerated 2008-10-08 Miguel Sofer * generic/tclBasic (TclInfoCoroutineCmd): * tests/unsupported.test: Arrange for [info coroutine] to return {} when a coroutine is running but the resume command has been deleted. [Bug 2153080] 2008-10-08 Don Porter * generic/tclTrace.c: Corrected handling of errors returned by variable traces so that the errorInfo value contains the original error message. [Bug 2151707] * generic/tclVar.c: Revised implementation of TclObjVarErrMsg so that error message construction does not disturb an existing iPtr->errorInfo that may be in progress. 2008-10-07 Donal K. Fellows * doc/binary.n: Added better documentation of the [binary encode] and [binary decode] subcommands. 2008-10-07 Miguel Sofer TIP #327,#328 IMPLEMENTATIONS * generic/tclBasic.c: Move [tailcall], [coroutine] and * generic/tclCmdIL.c: [yield] out of ::tcl::unsupported * tclInt.h: * tests/info.test: and into global scope: TIPs #327 * tests/unsupported.test: and #328 2008-10-07 Donal K. Fellows * doc/chan.n, doc/transchan.n: Documented the channel transformation API of TIP #230. 2008-10-06 Pat Thoyts * tests/winFCmd.test: Fixed some erroneous tests on Vista+. * generic/tclFCmd.c: Fix constness for msvc of last commit 2008-10-06 Joe Mistachkin * tools/man2tcl.c: Added missing line from patch by Harald Oehlmann. [Bug 1934200] 2008-10-05 Jan Nijtmans * doc/FileSystem.3: CONSTified Tcl_FSFileAttrStringsProc * generic/tclFCmd.c: and tclpFileAttrStrings. This allows * generic/tclIOUtil.c: FileSystems to report their attributes * generic/tclTest.c: as const strings, without worrying that * unix/tclUnixFCmd.c: Tcl modifies them (which Tcl should not * win/tclWinFCmd.c: do anyway, but the API didn't indicate that) * generic/tcl.decls * generic/tclDecls.h: regenerated * generic/tcl.h: Make sure that if CONST84 is defined as empty, CONST86 should be defined as empty as well (unless overridden). This change complies with TIP #27 *** POTENTIAL INCOMPATIBILITY *** 2008-10-05 Kevin B, Kenny * libtommath/bn_mp_sqrt.c (bn_mp_sqrt): Handle the case where a * tests/expr.test (expr-47.13): number's square root is between n< * generic/tclInt.decls: CONSTified the AuxDataType argument * generic/tclCompCmds.c: of TclCreateAuxData and * generic/tclCompile.c: TclRegisterAuxDataType and the return * generic/tclCompile.h: values of TclGetAuxDataType and * generic/tclExecute.c: TclGetInstructionTable * generic/tclIntDecls.h: regenerated This change complies with TIP #27 (even though it only involves internal function, so this is not even necessary). 2008-10-05 Donal K. Fellows * generic/tclIndexObj.c (TclInitPrefixCmd): Make the [tcl::prefix] into an exported command. [Bug 2144595] 2008-10-04 Donal K. Fellows * generic/tclCmdIL.c (InfoFrameCmd): Improved hygiene of result * generic/tclRegexp.c (TclRegAbout): handling. 2008-10-04 Jan Nijtmans * generic/tclLoad.c: Make sure that any library which doesn't have an unloadproc is only really unloaded when no library code is executed yet. [Bug 2059262] 2008-10-04 Donal K. Fellows * generic/tclOOInfo.c (GetClassFromObj): Factor out the code to parse a Tcl_Obj and get a class. Also make result handling hygienic. * generic/tclOOBasic.c (TclOOSelfObjCmd): Better hygiene of results, and stop allocating quite so much memory by sharing special "method" names. 2008-10-04 Jan Nijtmans * doc/ChnlStack.3: CONSTified the typePtr argument * doc/CrtChannel.3: of Tcl_CreateChannel and Tcl_StackChannel * generic/tcl.decls: and the return value of Tcl_GetChannelType * generic/tcl.h * generic/tclIO.h * generic/tclIO.c * generic/tclDecls.h: regenerated This change complies with TIP #27. * doc/Hash.3: CONSTified the typePtr argument * generic/tcl.decls: of Tcl_InitCustomHashTable. * generic/tcl.h * generic/tclHash.c * generic/tclDecls.h: regenerated This change complies with TIP #27. * doc/RegConfig.3: CONSTified the configuration argument * generic/tcl.decls: of Tcl_RegisterConfig. * generic/tcl.h * generic/tclConfig.c * generic/tclPkgConfig.c * generic/tclDecls.h: regenerated This change complies with TIP #27. * doc/GetIndex.3: CONSTified the tablePtr argument * generic/tcl.decls: of Tcl_GetIndexFromObj. * generic/tclIndexObj.c * generic/tclDecls.h: regenerated This change complies with TIP #27. 2008-10-03 Miguel Sofer * tests/stack.test: * unix/tclUnixTest.c: Removed test command teststacklimit and the corresponding constraint: it is not needed with NRE 2008-10-03 Donal K. Fellows TIP #195 IMPLEMENTATION * generic/tclIndexObj.c (TclGetIndexFromObjList, PrefixMatchObjCmd) * doc/prefix.n, tests/string.test: Added [tcl::prefix] command for working with prefixes of strings at the Tcl level. [Patch 1040206] TIP #265 IMPLEMENTATION * generic/tclIndexObj.c (Tcl_ParseArgsObjv, PrintUsage): * generic/tcl.h (Tcl_ArgvInfo): Added function for simple parsing of * doc/ParseArgs.3 (new file): optional arguments to commands. Still needs tests and the like. [FRQ 1446696] Note that some of the type signatures are changed a bit from the proposed implementation so that they better reflect codified good practice for argument order. 2008-10-02 Andreas Kupries * tests/info.test (info-23.3): Updated output of the test to handle the NRE-enabled eval and the proper propagation of location information through it. [Bug 2017632] * doc/info.n: Rephrased the documentation of 'info frame' for positive numbers as level argument. [Bug 2134049] * tests/info.test (info-22.8): Made pattern for file containing tcltest less specific to accept both .tcl and .tm variants of the file during matching. [Bug 2129828] 2008-10-02 Don Porter TIP #330 IMPLEMENTATION * generic/tcl.h: Remove the "result" and "freeProc" fields * generic/tclBasic.c: from the default public declaration of the * generic/tclResult.c: Tcl_Interp struct. Code should no longer * generic/tclStubLib.c: be accessing these fields. Access can be * generic/tclTest.c: restored by defining USE_INTERP_RESULT, but * generic/tclUtil.c: that should only be a temporary migration aid. *** POTENTIAL INCOMPATIBILITY *** 2008-10-02 Joe Mistachkin * doc/info.n: Fix unmatched font change. * doc/tclvars.n: Fix unmatched font change. * doc/variable.n: Fix unmatched font change. * tools/man2help2.tcl: Integrated patch from Harald Oehlmann. [Bug 1934272] * tools/man2tcl.c: Increase MAX_LINE_SIZE to fix "Too long line" error. * win/buildall.vc.bat: Prefer the HtmlHelp target over the WinHelp target. [Bug 2072891] * win/makefile.vc: Fix the HtmlHelp and WinHelp targets to not be mutually exclusive. 2008-09-29 Don Porter TIP #323 IMPLEMENTATION (partial) * doc/glob.n: Revise [glob] to accept zero patterns. * generic/tclFileName.c: * tests fileName.test: * doc/linsert.n: Revise [linsert] to accept zero elements. * generic/tclCmdIL.c: * tests/linsert.test: 2008-09-29 Donal K. Fellows TIP #326 IMPLEMENTATION * generic/tclCmdIL.c (Tcl_LsortObjCmd): Added -stride option to carry * doc/lsort.n, tests/cmdIL.test: out sorting of lists where the elements are grouped. Adapted from [Patch 2082681] TIP #313 IMPLEMENTATION * generic/tclCmdIL.c (Tcl_LsearchObjCmd): Added -bisect option to * doc/lsearch.n, tests/lsearch.test: allow the finding of the place to insert an element in a sorted list when that element is not already there. [Patch 1894241] TIP #318 IMPLEMENTATION * generic/tclCmdMZ.c (StringTrimCmd,StringTrimLCmd,StringTrimRCmd): Update the default set of trimmed characters to include some from the larger UNICODE space. Factor out the default trim set into a macro so that it is easier to keep them in synch. 2008-09-28 Donal K. Fellows TIP #314 IMPLEMENTATION * generic/tclCompCmds.c (TclCompileEnsemble) * generic/tclNamesp.c (NamespaceEnsembleCmd) (Tcl_SetEnsembleParameterList, Tcl_GetEnsembleParameterList) (NsEnsembleImplementationCmdNR): * generic/tcl.decls, doc/Ensemble.3, doc/namespace.n * tests/namespace.test: Allow the handling of a (fixed) number of formal parameters between an ensemble's command and subcommand at invokation time. [Patch 1901783] 2008-09-28 Miguel Sofer * generic/tclBasic.c: Fix the numLevels computations on * generic/tclInt.h: coroutine yield/resume * tests/unsupported.test: 2008-09-27 Donal K. Fellows * generic/tclFileName.c (Tcl_GetBlock*FromStat): Made this work acceptably when working with OSes that don't support reporting the block size from the stat() call. [Bug 2130726] * generic/tclCmdIL.c (Tcl_LrepeatObjCmd): Improve the handling of the case where the combination of number of elements and repeat count causes the resulting list to be too large. [Bug 2130992] 2008-09-26 Don Porter TIP #323 IMPLEMENTATION (partial) * doc/lrepeat.n: Revise [lrepeat] to accept both zero * generic/tclCmdIL.c: repetitions and zero elements to be repeated. * tests/lrepeat.test: * doc/object.n: Revise standard oo method [my variable] to * generic/tclOOBasic.c: accept zero variable names. * tests/oo.test: * doc/tm.n: Revise [tcl::tm::path add] and * library/tm.tcl: [tcl::tm::path remove] to accept zero paths. * tests/tm.test: * doc/namespace.n: Revise [namespace upvar] to accept zero * generic/tclNamesp.c: variable names. * tests/upvar.test: * doc/lassign.n: Revise [lassign] to accept zero variable names. * generic/tclCmdIL.c: * tests/cmdIL.test: 2008-09-26 Donal K. Fellows * generic/tclOO.h (TCLOO_VERSION): Bump the version. 2008-09-25 Don Porter TIP #323 IMPLEMENTATION (partial) * doc/global.n: Revise [global] to accept zero variable names. * doc/variable.n: Revise [variable] likewise. * generic/tclVar.c: * tests/proc-old.test: * tests/var.test: * doc/global.n: Correct false claim about [info locals]. 2008-09-25 Donal K. Fellows TIP #315 IMPLEMENTATION * tests/platform.test: Update tests to expect revised results * tests/safe.test: corresponding to the TIP 315 change. * unix/tclUnixInit.c, win/tclWinInit.c (TclpSetVariables): * doc/tclvars.n (tcl_platform): Define what character is used for separating PATH-like lists. Forms part of the tcl_platform array. * generic/tclOOCall.c (InitCallChain, IsStillValid): * tests/oo.test (oo-25.2): Revise call chain cache management so that it takes into account class-wide caching correctly. [Bug 2120903] 2008-09-24 Don Porter TIP #323 IMPLEMENTATION (partial) * doc/file.n: Revise [file delete] and [file mkdir] to * generic/tclCmdAH.c: accept zero "pathname" arguments (the * generic/tclFCmd.c: no-op case). * tests/cmdAH.test: * tests/fCmd.test: 2008-09-24 Donal K. Fellows * generic/tclOOMethod.c (DBPRINT): Remove obsolete debugging macro. [Bug 2124814] TIP #316 IMPLEMENTATION * generic/tcl.decls, generic/tclFileName.c (Tcl_GetSizeFromStat, etc): * doc/FileSystem.3: Added reader functions for Tcl_StatBuf. 2008-09-23 Donal K. Fellows * doc/Method.3: Corrected documentation. [Patch 2082450] * doc/lreverse.n, mathop.n, regexp.n, regsub.n: Make sure that the initial line of the manpage includes nothing that chokes old versions of man. [Bug 2118123] 2008-09-22 Donal K. Fellows TIP #320 IMPLEMENTATION * generic/tclOODefineCmds.c (TclOODefineVariablesObjCmd): * generic/tclOOInfo.c (InfoObjectVariablesCmd, InfoClassVariablesCmd): * generic/tclOOMethod.c (TclOOSetupVariableResolver, etc): * doc/define.n, doc/ooInfo.n, benchmarks/cps.tcl: * tests/oo.test (oo-26.*): Allow the declaration of the common variables used in methods of a class or object. These are then mapped in using a variable resolver. This makes many class declarations much simpler overall, encourages good usage of variable names, and also boosts speed a bit. * generic/tclOOMethod.c (TclOOGetMethodBody): Factor out the code to get the body of a procedure-like method. Reduces the amount of "poking inside the abstraction" that is done by the introspection code. 2008-09-22 Alexandre Ferrieux * doc/chan.n: Clean up paragraph order. 2008-09-18 Miguel Sofer * generic/tclExecute.c (NEXT_INST_F): * generic/tclInt.h (TCL_CT_ASSERT): New compile-time assertions, adapted from www.pixelbeat.org/programming/gcc/static_assert.html 2008-09-17 Don Porter * generic/tclInt.h: Correct the TclGetLongFromObj, TclGetIntFromObj, and TclGetIntForIndexM macros so that they retrieve the longValue field from the internalRep instead of casting the otherValuePtr field to type long. 2008-09-17 Miguel Sofer * library/init.tcl: Export min and max commands from the mathfunc namespace. [Bug 2116053] 2008-09-16 Joe Mistachkin * generic/tclParse.c: Move TclResetCancellation to be called on returning to level 0, as opposed to it being called on starting a substitution at level 0. 2008-09-16 Miguel Sofer * generic/tclBasic.c: Move TclResetCancellation to be called on returning to level 0, as opposed to it being called on starting a command at level 0. Add a call on returning via Tcl_EvalObjEx to fix [Bug 2114165]. 2008-09-10 Donal K. Fellows * doc/binary.n: Added partial documentation of [binary encode] and [binary decode]. * tests/binary.test,cmdAH.test,cmdIL.test,cmdMZ.test,fileSystem.test: More use of tcltest2 to simplify the tests as exposed to people. * tests/compile.test (compile-18.*): Added *some* tests of the disassmbler, though not of its output format. 2008-09-10 Miguel Sofer * tests/nre.test: Add missing constraints; enable test of foreach recursion. * generic/tclBasic.c: * generic/tclCompile.h: * generic/tclExecute.c (INST_EVAL_STK): Wrong numLevels when evaling a canonical list. [Bug 2102930] 2008-09-10 Donal K. Fellows * generic/tclListObj.c (Tcl_ListObjGetElements): Make this list->dict transformation - encountered when using [foreach] with dicts - not as expensive as it was before. Spotted by Kieran Elby and reported on tcl-core. 2008-09-08 Donal K. Fellows * tests/append.test, appendComp.test, cmdAH.test: Use the powers of tcltest2 to make these files simpler. 2008-09-07 Miguel Sofer * generic/tclCompile.c (TclCompileTokens): * generic/tclExecute.c (CompileExprObj): Fix a perf bug (found by Alex Ferrieux) where some variables in the LVT where not being accessed by index. Fix missing localCache management in compiled expressions found while analyzing the bug. 2008-09-07 Miguel Sofer * doc/namespace.n: Fix [Bug 2098441] 2008-09-04 Miguel Sofer * generic/tclTrace.test (TraceVarProc): * generic/unsupported.test: Insure that unset traces are run even when the coroutine is unwinding. [Bug 2093947] * generic/tclExecute.c (CACHE_STACK_INFO): * tests/unsupported.test: Restore execEnv's bottomPtr. [Bug 2093188] 2008-09-02 Don Porter * generic/tcl.h: Stripped "callers" of the _ANSI_ARGS_ macro * compat/dirent2.h: to support a TCL_NO_DEPRECATED build. * compat/dlfcn.h: * unix/tclUnixPort.h: * generic/tcl.h: Removed the conditional #define of _ANSI_ARGS_ that would support pre-prototype C compilers. Since _ANSI_ARGS_ is no longer used in tclDecls.h, it's clear no one compiling against Tcl 8.5 headers is making use of a -DNO_PROTOTYPES configuration. 2008-09-02 Donal K. Fellows * tests/socket.test: Rewrote so as to use tcltest2 better. 2008-09-01 Miguel Sofer * generic/tclCmdAH.c: NRE-enabling [eval]; eval scripts are now * generic/tclOOBasic.c: bytecompiled. Adapted recursion limit tests * tests/interp.test: that were relying on eval not being * tests/nre.test: compiled. Part of the [Bug 2017632] project. * tests/unsupported.test: 2008-09-01 Donal K. Fellows * generic/tclOOMethod.c (InvokeProcedureMethod): * generic/tclOO.c (ObjectRenamedTrace): Arrange for only methods that involve callbacks into the Tcl interpreter to be skipped when the interpreter is being torn down. Allows the semantics of destructors in a dying interpreter to be more useful when they're implemented in C. 2008-08-29 Donal K. Fellows * unix/Makefile.in: Ensure that all TclOO headers get installed. * win/Makefile.in: [Bug 2082299] * win/makefile.bc: * win/makefile.vc: 2008-08-28 Don Porter * README: Bump version number to 8.6a3 * generic/tcl.h: * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf-2.59 * win/configure: 2008-08-27 Donal K. Fellows * doc/tclvars.n, doc/library.n: Ensured that these two manual pages properly cross-reference each other. Issue reported on Tcler's Chat. 2008-08-26 Miguel Sofer * generic/tclBasic.c (InfoCoroutine): * tests/unsupported.test: New command that returns the FQN of the currently executing coroutine. Lives as infoCoroutine under unsupported, but is designed to become a subcommand of [info] 2008-08-23 Miguel Sofer * generic/tclBasic.c (NRInterpCoroutine): Store the caller's eePtr, stop assuming the coroutine is invoked from the same execEnv where it was created. 2008-08-24 Donal K. Fellows * generic/tclCmdAH.c (TclNRForeachCmd): Converted the [foreach] command to have an NRE-aware non-compiled implementation. Part of the [Bug 2017632] project. Also restructured the code so as to manage its temporary memory more efficiently. 2008-08-23 Miguel Sofer * generic/tclBasic.c: Removed unused var; fixed function pointer * generic/tclOOInt.h: declarations (why did gcc start complaining * generic/tclOOMethod.c: all of a sudden?) * generic/tclProc.c: 2008-08-23 Donal K. Fellows * generic/tclInt.h (EnsembleImplMap): Added extra field to make it * generic/tclNamesp.c (TclMakeEnsemble): easier to build non-recursive ensembles in the core. * generic/tclDictObj.c (DictForNRCmd): Converted the [dict for] command to have an NRE-aware non-compiled implementation. Part of the [Bug 2017632] project. 2008-08-22 Miguel Sofer * generic/tclBasic.c: * generic/tclExecute.c: Set special errocodes: COROUTINE_BUSY, COROUTINE_CANT_YIELD, COROUTINE_ILLEGAL_YIELD. 2008-08-22 Don Porter *** 8.6a2 TAGGED FOR RELEASE *** * changes: Updates for 8.6a2 release. * generic/tcl.h: Drop use of USE_COMPAT85_CONST. That added indirection without value. Use -DCONST86="" to engage source compat support for code written for 8.5 headers. * generic/tclUtil.c (TclReToGlob): Added missing set of the *exactPtr value to really fix [Bug 2065115]. Also avoid possible DString overflow. * tests/regexpComp.test: Correct duplicate test names. 2008-08-21 Miguel Sofer * generic/tclBasic.c: Previous fix, now done right. * generic/tclCmdIL.c: * generic/tclInt.h: * tests/unsupported.test: 2008-08-21 Jeff Hobbs * tests/regexp.test, tests/regexpComp.test: Correct re2glob ***= * generic/tclUtil.c (TclReToGlob): translation from exact to anywhere-in-string match. [Bug 2065115] 2008-08-21 Don Porter * generic/tcl.h: Reduced the use of CONST86 and eliminated * generic/tcl.decls: the use of CONST86_RETURN to support source code compatibility with Tcl 8.5 on those public routines passing (Tcl_Filesystem *), (Tcl_Timer *), and (Tcl_Objtype *) values which have been const-ified. What remains is the minimum configurability needed to support code written for pre-8.6 headers via the new -DUSE_COMPAT85_CONST compiler directive. *** POTENTIAL INCOMPATIBILITY *** * generic/tclDecls.h: make genstubs 2008-08-21 Miguel Sofer * generic/tclBasic.c: Fix the cmdFrame level count in * generic/tclCmdIL.c: coroutines. Fix small bug on coroutine * generic/tclInt.h: rewind. 2008-08-21 Donal K. Fellows * generic/tclProc.c (Tcl_DisassembleObjCmd): Added ability to disassemble TclOO methods. The code to do this is very ugly. 2008-08-21 Pat Thoyts * generic/tclOOMethod.c: Added casts to make MSVC happy * generic/tclBasic.c: 2008-08-20 Donal K. Fellows * generic/tclOO.c (AllocObject): Suppress compilation of commands in the namespace allocated for each object. * generic/tclOOMethod.c (PushMethodCallFrame): Restore some of the hackery that makes calling methods of classes fast. Fixes performance problem introduced by the fix of [Bug 2037727]. * generic/tclCompile.c (TclCompileScript): Allow the suppression of * generic/tclInt.h (NS_SUPPRESS_COMPILATION): compilation of commands * generic/tclNamesp.c (Tcl_CreateNamespace): from a namespace or its children. 2008-08-20 Daniel Steffen * generic/tclTest.c (TestconcatobjCmd): Fix use of internal-only TclInvalidateStringRep macro. [Bug 2057479] 2008-08-17 Miguel Sofer * generic/tclBasic.c: Implementation of [coroutine] and [yield] * generic/tclCmdAH.c: commands (in tcl::unsupported). * generic/tclCompile.h: * generic/tclExecute.c: * generic/tclInt.h: * tests/unsupported.test: * generic/tclTest.c (TestconcatobjCmd): * generic/tclUtil.c (Tcl_ConcatObj): * tests/util.test (util-4.7): Fix [Bug 1447328]; the original "fix" turned Tcl_ConcatObj() into a hairy monster. This was exposed by [Bug 2055782]. Additionally, Tcl_ConcatObj could corrupt its input under certain conditions! *** NASTY BUG FIXED *** 2008-08-16 Miguel Sofer * generic/tclExecute.c: Better cmdFrame management 2008-08-14 Don Porter * tests/fileName.test: Revise new tests for portability to case insensitive filesystems. 2008-08-14 Daniel Steffen * generic/tclBasic.c (TclNREvalObjv, Tcl_NRCallObjProc): * generic/tclProc.c (TclNRInterpProcCore, InterpProcNR2): DTrace probes for NRE. [Bug 2017160] * generic/tclBasic.c (TclDTraceInfo): Add two extra arguments to * generic/tclCompile.h: DTrace 'info' probes for tclOO * generic/tclDTrace.d: method & class/object info. * generic/tclCompile.h: Add support for debug logging of DTrace * generic/tclBasic.c: 'proc', 'cmd' and 'inst' probes (does _not_ require a platform with DTrace). * generic/tclCmdIL.c (TclInfoFrame): Check fPtr->line before dereferencing as line info may not exists when TclInfoFrame() is called from a DTrace probe. * tests/fCmd.test (fCmd-6.23): Made result matching robust when test workdir and /tmp are not on same FS. * unix/tclUnixThrd.c: Remove unused TclpThreadGetStackSize() * generic/tclInt.h: and related ifdefs and autoconf tests. * unix/tclUnixPort.h: [Bug 2017264] (jenglish) * unix/tcl.m4: * unix/Makefile.in: Ensure Makefile shell is /bin/bash for * unix/configure.in (SunOS): DTrace-enabled build on Solaris. (followup to 2008-06-12) [Bug 2016584] * unix/tcl.m4 (SC_PATH_X): Check for libX11.dylib in addition to libX11.so et al. * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 2008-08-13 Miguel Sofer * tests/nre.test: Added test for large {*}-expansion effects 2008-08-13 Don Porter * generic/tclFileName.c: Fix for errors handling -types {} * tests/fileName.test: option to [glob]. [Bug 1750300] Thanks to Matthias Kraft and George Peter Staplin. 2008-08-12 Jeff Hobbs * generic/tclOOInfo.c (InfoObjectDefnCmd, InfoObjectMixinsCmd): Fix # args displayed. [Bug 2048676] 2008-08-08 Don Porter * generic/tclOOMethod.c (PushMethodCallFrame): Added missing check for bytecode validity. [Bug 2037727] * generic/tclProc.c (TclProcCompileProc): On recompile of a proc, clear away any entries on the CompiledLocal list from the previous compile. This will prevent compile of temporary variables in the proc body from growing the localCache arbitrarily large. * README: Bump version number to 8.6a2 * generic/tcl.h: * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf-2.59 * win/configure: * changes: Updates for 8.6a2 release. 2008-08-11 Pat Thoyts * library/http/http.tcl: Remove 8.5 requirement. * library/http/pkgIndex.tcl: * unix/Makefile.in: * win/Makefile.in: * win/makefile.vc: 2008-08-11 Andreas Kupries * library/tm.tcl: Added a 'package provide' command to the generated ifneeded scripts of Tcl Modules, for early detection of conflicts between the version specified through the file name and a 'provide' command in the module implementation, if any. Note that this change also now allows Tcl Modules to not provide a 'provide' command at all, and declaring their version only through their filename. * generic/tclProc.c (Tcl_ProcObjCmd): Fixed memory leak triggered by * tests/proc.test: procbody::test::proc. See [Bug 2043636]. Added a test case demonstrating the leak before the fix. Fixed a few spelling errors in test descriptions as well. 2008-08-11 Don Porter * library/http/http.tcl: Bump http version to 2.7.1 to account * library/http/pkgIndex.tcl: for [Bug 2046486] bug fix. This * unix/Makefile.in: release of http now requires a * win/Makefile.in: dependency on Tcl 8.5 to be able to * win/makefile.bc: use the unsigned formats in the * win/makefile.vc: [binary scan] command. 2008-08-11 Pat Thoyts * library/http/http.tcl: CRC field from zlib data should be treated as unsigned for 64bit support. [Bug 2046846] 2008-08-10 Miguel Sofer * generic/tclProc.c: Completely removed ProcCompileProc, which was a fix for [Bug 1482718]. This is not needed at least since varReform, where the local variable data at runtime is read from the CallFrame and/or the LocalCache. 2008-08-09 Miguel Sofer * generic/tclBasic.c: Slight cleanup * generic/tclCompile.h: * generic/tclExecute.c: 2008-08-09 Daniel Steffen * generic/tclExecute.c: Fix warnings. * generic/tclOOMethod.c (PushMethodCallFrame): Fix uninitialized efi name field. * tests/lrange.test (lrange-1.17): Add test cleanup; whitespace. 2008-08-08 Don Porter * changes: Updates for 8.6a2 release. 2008-08-08 Kevin Kenny * library/tzdata/CET: * library/tzdata/MET: * library/tzdata/Africa/Casablanca: * library/tzdata/America/Eirunepe: * library/tzdata/America/Rio_Branco: * library/tzdata/America/Santarem: * library/tzdata/America/Argentina/San_Luis: * library/tzdata/Asia/Karachi: * library/tzdata/Europe/Belgrade: * library/tzdata/Europe/Berlin: * library/tzdata/Europe/Budapest: * library/tzdata/Europe/Sofia: * library/tzdata/Indian/Mauritius: Olson's tzdata2008e. 2008-08-07 Miguel Sofer * generic/tclBasic.c: Fix tailcalls falling out of tebc into * generic/tclExecute.c: Tcl_EvalEx. [Bug 2017946] * generic/tclInt.h: 2008-08-06 Don Porter * generic/tclOO.c: Revised TclOO's check for an interp being deleted during handling of object command deletion. The old code was relying on documented features of command delete traces that do not in fact work. [Bug 2039178] * tests/oo.test (oo-26.*): Added tests that demonstrate failure of TclOO to check for various kinds of invalid bytecode during method dispatch. [Bug 2037727] 2008-08-06 Miguel Sofer * generic/tclVar.c (TclLookupSimpleVar): Fix bug that the core could not trigger before TclOO: the number of locals was being read from the Proc, which can under some circumstance be out of sync with the localCache's. Found by dgp while investigating [Bug 2037727]. * library/init.tcl (::unknown): Removed the [namespace inscope] hack that was maintained for Itcl *** POTENTIAL INCOMPATIBILITY *** for Itcl Itcl users will need a new release with Itcl's [Patch 2040295], or else load the tiny script in that patch by themselves (rewrite ::unknown). Note that it is a script-only patch. 2008-08-05 Joe English * unix/tclUnixChan.c: Streamline async connect logic [Patch 1994512] 2008-08-05 Miguel Sofer * generic/tclExecute.c: Fix for [Bug 2038069] by dgp. * tests/execute.test: 2008-08-04 Miguel Sofer * tests/nre.test: Added tests for [if], [while] and [for]. A test for [foreach] has been added and marked as knownbug, awaiting for it to be NR-enabled. * generic/tclBasic.c: Made atProcExit commands run * generic/tclCompile.h: unconditionally, streamlined * generic/tclExecute.c: atProcExit/tailcall processing in TEBC. * generic/tclProc.c: * tests/unsupported.test: 2008-08-04 Don Porter * generic/tclExecute.c: Stopped faulty double-logging of errors to * tests/execute.test: stack trace when a compile epoch bump triggers fallback to direct evaluation of commands in a compiled script. [Bug 2037338] 2008-08-03 Miguel Sofer * generic/tclBasic.c: New unsupported command atProcExit that * generic/tclCompile.h: shares the implementation with tailcall. * generic/tclExecute.c: Fixed a segfault in tailcalls. Tests added. * generic/tclInt.h: * generic/tclInterp.c: * generic/tclNamesp.c: * tests/unsupported.test: 2008-08-02 Miguel Sofer * tests/NRE.test (removed): Migrated tests to standard locations, * tests/nre.test (new): separating core functionality from the * tests/unsupported.test (new): experimental commands. 2008-08-01 Jeff Hobbs * doc/Exit.3: Do not call Tcl_Finalize implicitly * generic/tclEvent.c: on DLL_PROCESS_DETACH as it may lead * win/tclWin32Dll.c (DllMain): to issues and the user should be explicitly calling Tcl_Finalize before unloading regardless. Clarify the docs to note the explicit need in embedded use. 2008-08-01 Don Porter * generic/tclBasic.c: Revised timing of the CmdFrame stack * tests/info.test: management in TclEvalEx so that the CmdFrame will still be on the stack at the time Tcl_LogCommandInfo is called to append another level of -errorinfo information. Sets the stage to add file and line data to the stack trace. Added test to check that [info frame] functioning remains unchanged by the revision. 2008-07-31 Miguel Sofer * tests/NRE.test: Replaced all deep-recursing tests by shallower tests that actually measure the C-stack depth. This makes them bearable again (even under memdebug) and avoid crashing on failure. * generic/tclBasic.c: NR-enabling [catch], [if] and [for] and * generic/tclCmdAH.c: [while] (the script, not the tests) * generic/tclCmdIL.c: * generic/tclCmdMZ.c: * generic/tclInt.h: * tests/NRE.test: * generic/tclBasic.c: Moved the few remaining defs from tclNRE.h to * generic/tclDictObj.c: tclInt.h, eliminated inclusion of tclNRE.h * generic/tclExecute.c: everywhere. * generic/tclInt.h: * generic/tclInterp.c: * generic/tclNRE.h (removed): * generic/tclNamesp.c: * generic/tclOOBasic.c: * generic/tclOOInt.h: * generic/tclProc.c: * generic/tclTest.c: * unix/Makefile.in: 2008-07-30 Miguel Sofer * generic/tclBasic.c: Improved tailcalls. * generic/tclCompile.h: * generic/tclExecute.c: * generic/tclTest.c: * tests/NRE.test: * generic/tclBasic.c (TclNREvalObjEx): New comments and code reorg to clarify what is happening. * generic/tclBasic.c: Guard against the value of iPtr->evalFlags changing between the times where TEOV and TEOV_exception run. Thanks dgp for catching this. 2008-07-29 Miguel Sofer * tests/NRE.test: New tests that went MIA in the NRE revamping * generic/tclBasic.c: Clean up * generic/tclNRE.h: * generic/tclExecute.c: * generic/tclBasic.c: Made use of the thread's alloc cache stored in * generic/tclInt.h: the ekeko at interp creation to avoid hitting * generic/tclNRE.h: the TSD each time an NRE callback is pushed or * generic/tclThreadAlloc.c: pulled; the approach is suitably general to extend to every other obj allocation where an interp is know; this is left for some other time, requires a lot of grunt work. * generic/tclExecute.c: Fix [Bug 2030670] that cause TclStackRealloc to panic on rare corner cases. Thx ajpasadyn for diagnose and patch. * generic/tcl.decls: Completely revamped NRE implementation, with * generic/tclBasic.c: (almost) unchanged API. * generic/tclCompile.h: * generic/tclExecute.c: TEBC will require a bit of a facelift, but * generic/tclInt.decls: TEOV at least looks great now. There are new * generic/tclInt.h: tests (incomplete!) to verify that execution * generic/tclInterp.c: is indeed in the same TEBC instance, at the * generic/tclNRE.h: same level in all stacks involved. Tailcalls * generic/tclNamesp.c: are still a bit leaky, still deserving to be * generic/tclOOBasic.c: in tcl::unsupported. * generic/tclOOMethod.c: * generic/tclProc.c: Uninit'd var warnings in TEBC with -O2, no * generic/tclTest.c: warnings otherwise. 2008-07-28 Jan Nijtmans * doc/FileSystem.3: CONSTified many functions using * generic/tcl.decls: Tcl_FileSystem which all are supposed * generic/tclDecls.h: to be a constant, but this was not * generic/tclFileSystem.h: reflected in the API: Tcl_FSData, * generic/tclIOUtil.c: Tcl_FSGetInternalRep, Tcl_FSRegister, * generic/tclPathObj.c: Tcl_FSNewNativePath, Tcl_FSUnregister, * generic/tclTest.c: Tcl_FSGetFileSystemForPath ... This change complies with TIP #27. ***POTENTIAL INCOMPATIBILITY*** 2008-07-28 Andreas Kupries * generic/tclBasic.c: Added missing ref count when creating an empty string as path (TclEvalEx). In 8.4 the missing code caused panics in the testsuite. It doesn't in 8.5. I am guessing that the code path with the missing the incr-refcount is not invoked any longer. Because the bug in itself is certainly the same. 2008-07-27 Donal K. Fellows * generic/tclOOMethod.c (PushMethodCallFrame): Remove hack that should have gone when this code was merged into Tcl. 2008-07-27 Jan Nijtmans * doc/Object.3: CONSTified 3 functions using Tcl_ObjType * doc/ObjectType.3: which all are supposed to be a constant, but * generic/tcl.decls: this was not reflected in the API: * generic/tcl.h: Tcl_RegisterObjType, Tcl_ConvertToType, * generic/tclDecls.h: Tcl_GetObjType * generic/tclObj.c: Introduced a CONST86_RETURN, so extensions * generic/tclCompCmds.c: which use Tcl_ObjType directly can be * generic/tclOOMethod.c: modified to compile against both Tcl 8.5 and * generic/tclTestobj.c: Tcl 8.6. tclDecls.h regenerated This change complies with TIP #27. ***POTENTIAL INCOMPATIBILITY*** 2008-07-25 Andreas Kupries * test/info.test: More work on singleTestInterp usability. [1605269] * tests/info.test: Tests 38.* added, exactly testing the tracking of location for uplevel scripts. Resolved merge conflict on info-37.0, switched !singleTestInterp constraint to glob matching instead. Ditto info-22.8, removed constraint, more glob matching, and reduced the depth of the stack we check. More is coming, right now I want to commit the bug fixes. * tests/oo.test: Updated oo-22.1 for expanded location tracking. * generic/tclCompile.c (TclInitCompileEnv): Reorganized the initialization of the #280 location information to match the flow in TclEvalObjEx to get more absolute contexts. * generic/tclBasic.c (TclEvalObjEx): Added missing cleanup of extended location information. 2008-07-25 Daniel Steffen * tests/info.test (info-37.0): Add !singleTestInterp constraint; (info-22.8, info-23.0): switch to glob matching to avoid sensitivity to tcltest.tcl line number changes, remove knownBug constraint, fix expected result. [Bug 1605269] 2008-07-24 Jan Nijtmans * doc/Notifier.3: CONSTified 4 functions in the Notifier which * doc/Thread.3: all have a Tcl_Time* in it which is supposed * generic/tcl.decls: to be a constant, but this was not reflected * generic/tcl.h: reflected in the API: * generic/tclDecls.h: Tcl_SetTimer, Tcl_WaitForEvent, * generic/tclNotify.c: Tcl_ConditionWait, Tcl_SetMaxBlockTime * macosx/tclMacOSXNotify.c: * generic/tclThread.c: Introduced a CONST86, so extensions which have * unix/tclUnixNotfy.c: have their own Notifier (are there any?) can * unix/tclUnixThrd.c: can be modified to compile against both Tcl * win/tclWinNotify.c: Tcl 8.5 and Tcl 8.6 * win/tclWinThrd.c: Regenerated tclDecls.h with "make stubs". This change complies with TIP #27 ***POTENTIAL INCOMPATIBILITY*** 2008-07-23 Alexandre Ferrieux * tests/lrange.test: Added relative speed test to check for lrange in-place optimization committed 2008-06-30. * tests/binary.test: Added relative speed test to check for pure byte array CONCAT1 optimization committed 2008-06-30. 2008-07-23 Andreas Kupries * tests/info.test: Reordered the tests to have monotonously increasing numbers. * generic/tclBasic.c: Modified TclArgumentGet to reject pure lists * generic/tclCmdIL.c: immediately, without search. Reworked setup of * generic/tclCompile.c: eoFramePtr, doesn't need the line information, * tests/info.test: more sensible to have everything on line 1 when eval'ing a pure list. Updated the users of the line information to special case this based on the frame type (i.e. TCL_LOCATION_EVAL_LIST). Added a testcase demonstrating the new behaviour. 2008-07-23 Miguel Sofer * generic/tclBasic.c (GetCommandSource): Added comment with explanation and warning for waintainers. 2008-07-22 Andreas Kupries * generic/tclCompile.c: Made the new TclEnterCmdWordIndex static, and * generic/tclCompile.h: ansified. * generic/tclBasic.c: Ansified the new functions. Added missing function comments. * generic/tclBasic.c: Reworked the handling of bytecode literals for * generic/tclCompile.c: #280 to fix the abysmal performance for deep * generic/tclCompile.h: recursion, replaced the linear search through * generic/tclExecute.c: the whole stack with another hashtable and * generic/tclInt.h: simplified the data structure used by the compiler by using an array instead of a hashtable. Incidentially this also fixes the memory leak reported via [Bug 2024937]. 2008-07-22 Miguel Sofer * generic/tclBasic.c: Added numLevels field to CommandFrame, let * generic/tclExecute.c: GetCommandSource use it. This solves [Bug * generic/tclInt.h: 2017146]. Thx dgp for the analysis. 2008-07-21 Andreas Kupries * generic/tclBasic.c: Extended the existing TIP #280 system (info * generic/tclCmdAH.c: frame), added the ability to track the absolute * generic/tclCompCmds.c: location of literal procedure arguments, and * generic/tclCompile.c: making this information available to uplevel * generic/tclCompile.h: eval, and siblings. This allows proper * generic/tclInterp.c: tracking of absolute location through custom * generic/tclInt.h: (Tcl-coded) control structures based on uplevel, * generic/tclNamesp.c: etc. * generic/tclProc.c: * tests/info.test: 2008-07-21 Jan Nijtmans * generic/*.c: Fix [2021443] inconsistant "wrong # args" messages * win/tclWinReg.c * win/tclWinTest.c * tests/*.test 2008-07-21 Alexandre Ferrieux TIP #304 IMPLEMENTATION * generic/tcl.decls: Public API * generic/tclIOCmds.c: Generic part * unix/tclUnixPipe.c: OS part * win/tclWinPipe.c: OS part * tests/chan.test: [chan pipe] tests * tests/ioCmd.test: Modernized checks * tests/ioTrans.test: 2008-07-21 Pat Thoyts * generic/tclFCmd.c: Inodes on windows are unreliable. [Bug 2015723] * tests/winFCmd.test: test rename with inode collision 2008-07-21 Miguel Sofer * generic/tcl.decls: Changed the implementation of * generic/tclBasic.c: [namespace import]; removed * generic/tclDecls.h: Tcl_NRObjProc, replaced with * generic/tclExecute.c: Tcl_NRCmdSwap (proposed public * generic/tclInt.h: NRE API). This should fix * generic/tclNRE.h: [Bug 582506]. * generic/tclNamesp.c: * generic/tclStubInit.c: * generic/tclBasic.c: NRE: enabled calling NR commands * generic/tclExecute.c: from the callbacks. Completely * generic/tclInt.h: redone tailcall implementation * generic/tclNRE.h: using the new feature. [Bug 2021489] * generic/tclProc.c: * tests/NRE.test: 2008-07-20 Kevin B. Kenny * tests/fileName.test: Repaired the failing test fileName-15.7 from dkf's commit earlier today. 2008-07-20 Donal K. Fellows * generic/tclDictObj.c (SetDictFromAny): Make the list->dict transformation a bit more efficient; modern dicts are ordered and so we can round-trip through lists without needing the string rep at all. * generic/tclListObj.c (SetListFromAny): Make the dict->list transformation not lossy of internal representations and hence more efficient. [Bug 2008248] (ajpasadyn) but using a more efficient patch. * tests/fileName.test: Revise to reduce the obscurity of tests. In particular, all tests should now produce informative messages on failure and the quantity of [catch]-based obscurity is now greatly reduced; non-erroring is now checked for directly. 2008-07-19 Donal K. Fellows * tests/env.test: Add LANG to the list of variables that are not touched by the environment variable tests, so that subprocesses can get their system encoding correct. * tests/exec.test, tests/env.test: Rewrite so that non-ASCII characters are not used in the final comparison. Part of fixing [Bug 1513659]. 2008-07-18 Miguel Sofer * generic/tclBasic.c: Optimization: replace calls to * generic/tclDictObj.c: Tcl_NRAddCallback with the macro * generic/tclExecute.c: TclNRAddCallback. * generic/tclInterp.c: * generic/tclNRE.h: * generic/tclNamesp.c: * generic/tclOO.c: * generic/tclOOBasic.c: * generic/tclOOCall.c: * generic/tclOOInt.h: * generic/tclOOMethod.c: * generic/tclProc.c: 2008-07-18 Donal K. Fellows * generic/tclOO.c (TclNRNewObjectInstance, FinalizeAlloc): * generic/tclOOBasic.c (TclOO_Class_Create, TclOO_Class_CreateNs) (TclOO_Class_New, FinalizeConstruction, AddConstructionFinalizer): NRE-enablement of the class construction methods. 2008-07-18 Miguel Sofer * tests/NRE.test: Added basic tests for deep TclOO calls * generic/tcl.decls: Change the public api prefix from * generic/tcl.h: TclNR_foo to Tcl_NRfoo * generic/tclBasic.c: * generic/tclDecls.h: * generic/tclDictObj.c: * generic/tclExecute.c: * generic/tclInterp.c: * generic/tclNRE.h: * generic/tclNamesp.c: * generic/tclOO.c: * generic/tclOOBasic.c: * generic/tclOOCall.c: * generic/tclOOMethod.c: * generic/tclProc.c: * generic/tclStubInit.c: 2008-07-18 Donal K. Fellows * generic/tclOOBasic.c (TclOO_Object_Eval, FinalizeEval): NRE-enable the oo::object.eval method. 2008-07-18 Miguel Sofer * generic/tclDictObj.c (DictWithCmd, DictUpdateCmd): Fix refcounting bugs that caused crashes [Bug 2017857]. * generic/tclBasic.c (TclNREvalObjEx): Streamline the management of the command frame (opt). 2008-07-17 Donal K. Fellows * generic/tclDictObj.c (DictWithCmd, FinalizeDictWith): Split the implementation of [dict with] so that it works with NRE. (DictUpdateCmd, FinalizeDictUpdate): Similarly for the non-compiled version of [dict update]. 2008-07-16 George Peter Staplin * win/tclWinThrd.c: Test for TLS_OUT_OF_INDEXES to make certain that thread key creation is successful. 2008-07-16 Donal K. Fellows * generic/tclOO.c, generic/tclOOInt.h, generic/tclOOBasic.c: * generic/tclOOCall.c, generic/tclOOMethod.c: NRE-enable the TclOO implementation in Tcl. No change to public APIs, except that method implementations can now be NRE-aware if they choose (which normal methods and forwards are). On the other hand, callers of TclOOInvokeObject (which is only in the internal stub table) will need to deal with the fact that it's only safe to call inside an NRE-aware context. ***POTENTIAL INCOMPATIBILITY*** 2008-07-15 Miguel Sofer * tests/NRE.test: Better constraint for testing the existence of * tests/stack.test: teststacklimit, to insure that the test suite runs under tclsh. * generic/tclParse.c: Fixing incomplete reversion of "fix" for [Bug 2017583], missing TclResetCancellation call. 2008-07-15 Donal K. Fellows * generic/tclBasic.c (Tcl_CancelEval): Fix blunder. [Bug 2018603] * doc/DictObj.3: Fix error in example. [Bug 2016740] * generic/tclNamesp.c (EnsembleUnknownCallback): Factor out some of the more complex parts of the ensemble code to make it easier to understand and hence to permit tighter compilation of code on the critical path. 2008-07-14 Miguel Sofer * generic/tclParse.c: Reverting the "fix" for [Bug 2017583], numLevel * tests/parse.test: management and TclInterpReady check seems to be necessary after all. 2008-07-14 Donal K. Fellows * generic/tclProc.c (TclNRApplyObjCmd, TclObjInterpProcCore): * generic/tclBasic.c (TclNR_AddCallback, TclEvalObjv_NR2): * generic/tclNRE.h (TEOV_callback): Change the callback storage type to use an array, so guaranteeing correct inter-member spacing and memory layout. 2008-07-14 Miguel Sofer * generic/tclExecute.c: Remove unneeded TclInterpReady calls * generic/tclParse.c: * generic/tclBasic.c.: Embedded Tcl_Canceled() calls into * generic/tclExecute.c: TclInterpReady(). * generic/tclParse.c: * generic/tclVar.c: Fix error message * generic/tclParse.c: Remove unnecessary numLevel management * tests/parse.test: [Bug 2017583] * generic/tclBasic.c.: NRE left too many calls to * generic/tclExecute.c: TclResetCancellation lying around: it * generic/tclProc.c: only needs to be called prior to any iPtr->numLevels++. Thanks mistachkin. * generic/tclBasic.c: TclResetCancellation() calls were misplaced (merge mishap); stray //. Thanks patthoyts. * generic/tclInt.h: The new macros TclSmallAlloc and TclSmallFree were badly defined under mem debugging [Bug 2017240] (thx das) 2008-07-13 Miguel Sofer NRE implementation [Patch 2017110] * generic/tcl.decls: The NRE infrastructure * generic/tcl.h: * generic/tclBasic.c: * generic/tclCmdAH.c: * generic/tclCompile.h: * generic/tclDecls.h: * generic/tclExecute.c: * generic/tclHistory.c: * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclNRE.h: * generic/tclStubInit.c: * unix/Makefile.in: * generic/tclInterp.c: NRE-enabling: procs, lambdas, uplevel, * generic/tclNamesp.c: same-interp aliases, ensembles, imports * generic/tclProc.c: and namespace_eval. * generic/tclTestProcBodyObj.c: New NRE specific tests (few, but * tests/NRE.test: note that the thing is actually tested by the whole testsuite. * tests/interp.test: Fixed numLevel counting. * tests/parse.test: * tests/stack.test: * unix/configure: Removing support for the hacky nonportable * unix/configure.in: stack check: it is not needed anymore, Tcl * unix/tclConfig.h.in: is very thrifty on the C stack. * unix/tclUnixInit.c: * unix/tclUnixTest.c: * win/tclWin32Dll.c: 2008-07-08 Don Porter * generic/tclGet.c: Corrected out of date comments and removed * generic/tclInt.decls: internal routine TclGetLong() that's no longer used. If an extension is using this from the internal stubs table, it can shift to the public routine Tcl_GetLongFromObj() or can request addition of a public Tcl_GetLong(). ***POTENTIAL INCOMPATIBILITY*** * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: 2008-07-08 Donal K. Fellows * doc/CrtInterp.3: Tighten up the descriptions of behaviour to make this page easier to read for a "Tcl 8.6" audience. 2008-07-07 Andreas Kupries * generic/tclCmdIL.c (InfoFrameCmd): Fixed unsafe idiom of setting the interp result found by Don Porter. 2008-07-07 Donal K. Fellows * doc/regexp.n, doc/regsub.n: Correct examples. [Bug 1982642] 2008-07-06 Donal K. Fellows * doc/lindex.n: Improve examples. 2008-07-03 Andreas Kupries * generic/tclIORChan.c (InvokeTclMethod): Fixed the memory leak reported in [Bug 1987821]. Thanks to Miguel for the report and Don Porter for tracking the cause down. 2008-07-03 Don Porter * library/package.tcl: Removed [file readable] testing from [tclPkgUnknown] and friends. We find out soon enough whether a file is readable when we try to [source] it, and not testing before allows us to workaround the bugs on some common filesystems where [file readable] lies to us. [Patch 1969717] 2008-07-01 Donal K. Fellows * generic/regc_nfa.c (duptraverse): Impose a maximum stack depth on the single most recursive part of the RE engine. The actual maximum may need tuning, but that needs a system with a small stack to carry out. [Bug 1905562] * tests/string.test: Eliminate non-ASCII characters from the actual test script. [Bug 2006884] 2008-06-30 Donal K. Fellows * doc/ObjectType.3: Clean up typedef formatting. 2008-06-30 Don Porter * doc/ObjectType.3: Updated documentation of the Tcl_ObjType struct to match expectations of Tcl 8.5. [Bug 1917650] 2008-06-30 Alexandre Ferrieux * generic/tclCmdIL.c: Lrange cleanup and in-place optimization. [Patch 1890831] * generic/tclExecute.c: Avoid useless String conversion for CONCAT1 of pure byte arrays. [Patch 1953758] 2008-06-29 Donal K. Fellows * doc/*.1, doc/*.3, doc/*.n: Many small updates, purging out of date change bars and cleaning up the formatting of typedefs. Added a few missing bits of documentation in the process. 2008-06-29 Don Porter * generic/tclPathObj.c: Plug memory leak in [Bug 1999176] fix. Thanks to Rolf Ade for detecting. 2008-06-29 Donal K. Fellows * doc/interp.n: Corrected order of subcommands. [Bug 2004256] Removed obsolete (i.e. 8.5) .VS/.VE pairs. * doc/object.n (EXAMPLES): Fix incorrect usage of oo::define to be done with oo::objdefine instead. [Bug 2004480] 2008-06-28 Don Porter * generic/tclPathObj.c: Plug memory leak in [Bug 1972879] fix. Thanks to Rolf Ade for detecting and Dan Steffen for the fix. [Bug 2004654] 2008-06-26 Andreas Kupries * unix/Makefile.in: Followup to my change of 2008-06-25, make code generated by the Makefile and put into the installed tm.tcl conditional on interpreter safeness as well. Thanks to Daniel Steffen for reminding me of that code. 2008-06-25 Don Porter *** 8.6a1 TAGGED FOR RELEASE *** * changes: Updates for 8.6a1 release. * generic/tclOO.h: Bump to TclOO 0.5. 2008-06-25 Andreas Kupries * library/tm.tcl: Modified the handling of Tcl Modules and of the * library/safe.tcl: Safe Base to interact nicely with each other, * library/init.tcl: enabling requiring Tcl Modules in safe * tests/safe.test: interpreters. [Bug 1999119] 2008-06-25 Pat Thoyts * win/rules.vc: Fix versions of dde and registry dlls * win/makefile.vc: Fix problem building with staticpkg option 2008-06-24 Don Porter * generic/tclPathObj.c: Fixed some internals management in the "path" Tcl_ObjType for the empty string value. Problem led to a crash in the command [glob -dir {} a]. [Bug 1999176] 2008-06-24 Pat Thoyts * doc/fileevent.n: Fix examples and comment on eof use. [Bug 1995063] 2008-06-23 Don Porter * generic/tclPathObj.c: Fixed bug in Tcl_GetTranslatedPath() when operating on the "Special path" variant of the "path" Tcl_ObjType intrep. A full normalization was getting done, in particular, coercing relative paths to absolute, contrary to what the function of producing the "translated path" is supposed to do. [Bug 1972879] 2008-06-20 Don Porter * changes: Updates for 8.6a1 release. * generic/tclInterp.c: Fixed completely boneheaded mistake that * tests/interp.test: [interp bgerror $slave] and [$slave bgerror] would always act like [interp bgerror {}]. [Bug 1999035] * tests/chanio.test: Corrected flawed tests revealed by a -debug 1 * tests/cmdAH.test: -singleproc 1 test suite run. * tests/event.test: * tests/interp.test: * tests/io.test: * tests/ioTrans.test: * tests/namespace.test: * tests/encoding.test: Make failing tests pass again. [Bug 1972867] 2008-06-19 Donal K. Fellows * generic/tclOO.c (Tcl_ObjectContextInvokeNext): Corrected 'next' (at * tests/oo.test (oo-7.8): end of a call chain) to make it * doc/next.n: consistent with the TIP. [Bug 1998244] * generic/tclOOCall.c (AddSimpleClassChainToCallContext): Make sure * tests/oo.test (oo-14.8): that class mixins are processed in the documented order. [Bug 1998221] 2008-06-19 Don Porter * changes: Updates for 8.6a1 release. * README: Bump version number to 8.6a1 * generic/tcl.h: * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf-2.59 * win/configure: 2008-06-17 Andreas Kupries * generic/tclClock.c (ClockConvertlocaltoutcObjCmd): Removed left over debug output. 2008-06-17 Andreas Kupries * doc/tm.n: Followup to changelog entry 2008-03-18 regarding ::tcl::tm::Defaults. Updated the documentation to not only mention the new (underscored) form of environment variable names, but make it the encouraged form as well. [Bug 1914604] 2008-06-17 Kevin Kenny * generic/tclClock.c (ConvertLocalToUTC): * tests/clock.test (clock-63.1): Fixed a bug where the internal ConvertLocalToUTC command segfaulted if passed a dictionary without the 'localSeconds' key. To the best of my knowledge, the bug was not observable in the [clock] command itself. 2008-06-16 Andreas Kupries * generic/tclCmdIL.c (TclInfoFrame): Moved the code looking up the * tests/info.test: information for key 'proc' out of the TCL_LOCATION_BC branch to after the switch, this is common to all frame types. Updated the testsuite to match. This was exposed by the 2008-06-08 commit (Miguel), switching uplevel from direct eval to compilation. [Bug 1987851] 2008-06-16 Andreas Kupries * tests/ioTrans.test (iortrans-11.*): Fixed same issue as for iortrans.tf-11.*, cleanup of temp file, making this a followup to the entry on 2008-06-10 by myself. 2008-06-13 David Gravereaux * win/rules.vc: SYMBOLS macro is now being set to zero when $(OPTS) is not available. * win/makefile.vc: The Stubs source files (tclStubLib.c and tclOOStubLib.c) should not be compiled with the -GL flag. 2008-06-13 Joe Mistachkin TIP #285 IMPLEMENTATION * doc/Eval.3: Added documentation for the Tcl_CancelEval and Tcl_Canceled functions and the TCL_CANCEL_UNWIND flag bit. * doc/after.n: Corrected the spelling of 'canceled' in the documentation. * doc/interp.n: Added documentation for [interp cancel]. * generic/tcl.decls: Added the Tcl_CancelEval and Tcl_Canceled functions to the stubs table. * generic/tcl.h: Added the TCL_CANCEL_UNWIND flag bit. * generic/tclBasic.c: The bulk of the script cancellation functionality is defined here. Added code to initialize and manage the script cancellation hash table in a thread-safe manner. Reset script cancellation flags prior to increasing the nesting level (if the nesting level is currently zero) and always cooperatively check for script cancellation near the start of TclEvalObjvInternal and after invoking async handlers. * generic/tclDecls.h: Regenerated. * generic/tclEvent.c: Call TclFinalizeEvaluation during finalization to cleanup the script cancellation hash table. During [vwait], always cooperatively check for script cancellation. Corrected the spelling of 'canceled' in comments to be consistent with the documentation. * generic/tclExecute.c: Reset script cancellation flags prior to increasing the nesting level (if the nesting level is currently zero) and always cooperatively check for script cancellation after invoking async handlers. Prevent [catch] from catching script cancellation when the TCL_CANCEL_UNWIND flag is set (similar to the manner used by TIP 143 when a limit has been exceeded). * generic/tclInt.decls: Added TclResetCancellation to the internal stubs table. * generic/tclInt.h: Added asyncCancel and asyncCancelMsg fields to the private Interp structure. Added private interp flag value CANCELED to help control script cancellation. * generic/tclIntDecls.h: Regenerated. * generic/tclInterp.c (Tcl_InterpObjCmd): Added [interp cancel] subcommand. * generic/tclNotify.c (Tcl_DeleteEventSource): Corrected the spelling of 'canceled' in comments to be consistent with the documentation. * generic/tclParse.c: Reset script cancellation flags prior to * generic/tclProc.c: increasing the nesting level (if the nesting level is currently zero) and cooperatively check for script cancellation prior to evaluating commands. * generic/tclStubInit.c: Regenerated. * generic/tclThreadTest.c (Tcl_ThreadObjCmd): Added script cancellation support ([testthread cancel]). Modified [testthread id] to allow querying of the 'main' thread ID. Corrected comments to reflect the actual command syntax. Made [testthread wait] cooperatively check for script cancellation. Added [testthread event] to allow for processing one pending event without blocking. * generic/tclTimer.c: Delay for a maximum of 500 milliseconds prior to checking for async handlers and script cancellation. * tests/cmdAH.test: Changed [interp c] to [interp create]. * tests/interp.test: Added and fixed tests for [interp cancel]. * tests/thread.test: Added tests for script cancellation via [testthread cancel]. * tools/man2help2.tcl: Fixed problems with WinHelp target (see * tools/man2tcl.c: [Bug 1934200], [Bug 1934265], and [Bug 1934272]). * win/makefile.vc: Added 'pdbs' option for Windows build rules to * win/rules.vc: allow for non-debug builds with full symbols. * win/tcl.hpj.in: Corrected version for WinHelp target. * win/tclWinNotify.c: Used SleepEx and WaitForSingleObjectEx on * win/tclWinThrd.c: Windows because they are alertable. 2008-06-12 Daniel Steffen * unix/Makefile.in: Add complete deps on tclDTrace.h. * generic/tclOO.c: Use TclOOStubs hooks field to retrieve * generic/tclOODecls.h: TclOOIntStubs pointer. [Bug 1980953] * generic/tclOOIntDecls.h: * generic/tclOOStubInit.c: * generic/tclOOStubLib.c: * generic/tclIORTrans.c: Fix signed <-> unsigned cast warnings. * unix/Makefile.in: Clean generated tclDTrace.h file. * unix/configure.in (SunOS): Fix static DTrace-enabled build. * unix/tcl.m4 (SunOS-5.11): Fix 64bit amd64 support with gcc & Sun cc. * unix/configure: autoconf-2.59 * macosx/Tcl.xcodeproj/project.pbxproj: Add tclIORTrans.c; updates and cleanup for Xcode 3.1/Leopard. * macosx/Tcl.xcode/project.pbxproj: Sync Tcl.xcodeproj changes. * macosx/README: Document new build configs. 2008-06-10 Joe English * generic/tclEncoding.c(UtfToUtfProc): Avoid unwanted sign extension when converting incomplete UTF-8 sequences. See [Bug 1908443] for details. 2008-06-10 Andreas Kupries * tests/ioTrans.test (iortrans.tf-6.1): Fixed the [Bug 1988552], reported by Kevin. Have to close the channel before removal of the file. Fixed same bug in test 'iortrans.tf-11.0', after fixing missing cleanup of the file in 'iortrans.tf-11.*'. Lastly fixed the names of the threaded tests 'iortrans-8.*' to the correct 'iortrans.tf-8.*'. 2008-06-09 Andreas Kupries * generic/tclIORTrans.c (ReflectInput): Fixed a bug triggered by Pat Thoyts . Reset the EOF flag after draining the Tcl level into the result buffer, to make sure that the result buffer will be drained as well by repeated calls to ReflectInput should it contain more than one buffer-full of data. Without that reset the higher I/O system will not call on ReflectInput anymore due to the assumed EOF, thus losing the data which did not fit in the buffer of the call which caused the eof and drain. 2008-06-09 Donal K. Fellows * generic/tclOOCall.c (TclOOGetSortedMethodList): Plug memory leak that occurred when all methods were hidden. [Bug 1987817] 2008-06-08 Miguel Sofer * generic/tclBasic.c: Compilation of uplevel scripts, allow * generic/tclCompCmds.c: non-body compiled scripts to access the * generic/tclCompile.c: LVT (but not to extend it) and enable the * generic/tclCompile.h: canonical list opt to sidestep the * generic/tclExecute.c: compiler. [Patch 1973096] * generic/tclProc.c: * tests/uplevel.test: 2008-06-06 Andreas Kupries TIP #230 IMPLEMENTATION * generic/tclIOCmd.c: Integration of transform commands into 'chan' ensemble. * generic/tclInt.h: Definitions of the transform commands. * generic/tclIORTrans.c: Implementation of the reflection transforms. * tests/chan.test: Tests updated for new sub-commands of 'chan'. * tests/ioCmd.test: Tests updated for new sub-commands of 'chan'. * tests/ioTrans.test: Whole new set of tests for the reflection transform. * unix/Makefile.in: Integration of new files into build rules. * win/Makefile.in: Integration of new files into build rules. * win/makefile.vc: Integration of new files into build rules. NOTE: The file 'tclIORTrans.c' has a lot of code in common with the file 'tclIORChan.c', as that made it much easier to develop the reference implementation as a separate module. Now that the transforms have been committed the one thing left to do is to go over both modules and see which of the common parts we can factor out and share. 2008-06-04 Pat Thoyts * generic/tclBinary.c: TIP #317 implementation * tests/binary.test: 2008-06-02 Kevin B. Kenny * generic/tclOO.c (ReleaseClassContents): Fix the one remaining valgrind complaint about oo.test, caused by failing to protect the Object as well as the Class corresponding to a subclass being deleted and hence getting a freed-memory read when attempting to delete the class command. [Bug 1981001] 2008-06-01 Donal K. Fellows * generic/tclOOMethod.c (Tcl_NewMethod): Complete the fix of [Bug 1981001], previous fix was incomplete though helpful in telling me where to look. 2008-06-01 Joe Mistachkin * win/Makefile.in: Add tclOO genstubs to Windows makefiles and remove * win/makefile.vc: -DBUILD_tcloo because it is no longer required. 2008-06-01 Kevin B. Kenny * generic/tclOODecls.h: Added the swizzling of DLLEXPORT and * generic/tclOOIntDecls.h: DLLIMPORT needed to make EXTERN work. * generic/tclDictObj.c: Added missing initializers to the ensemble map to silence a compiler warning. Thanks to George Peter Staplin for the report. * generic/tclOOMethod.c: Fix a bug where the refcount of a method was reset if the method was redefined while there was an active invocation. [Bug 1981001] 2008-06-01 Donal K. Fellows * generic/tclOO.decls, unix/Makefile.in (genstubs): Make generation of stub tables correct. * generic/tclOO{Decls.h,IntDecls.h,StubInit.c,StubLib.c}: Fixes to make the generation work correctly, removing subtle differences between output of different versions of stub generator. 2008-06-01 Daniel Steffen * generic/tclOOStubLib.c: Ensure use of tcl stubs; include in * unix/Makefile.in: stub lib; disable broken tclOO genstubs * generic/tclOO.c: Make tclOO stubs tables 'static const' * generic/tclOODecls.h: and stub table pointers MODULE_SCOPE * generic/tclOOIntDecls.h: (change generated files manually * generic/tclOOStubInit.c: pending genstubs support for tclOO). * generic/tclOOStubLib.c: * generic/tclOO.c: Fix warnings for 'int<->ptr * generic/tclOOCall.c: conversion' and 'signed vs unsigned * generic/tclOOMethod.c: comparison'. * tests/msgcat.test: Fix for ::tcl::mac::locale with @modifier. * tools/tsdPerf.tcl: Use [info sharedlibextension] * unix/tclConfig.h.in: autoheader-2.59 * macosx/Tcl.xcodeproj/project.pbxproj: Add new tclOO files; add debug * macosx/README: configs with corefoundation disabled and with gcov; update to Xcode 3.1. 2008-05-31 Donal K. Fellows * generic/tclOO.c (InitFoundation): Correct reference counting for strings used when creating the constructor for classes. * generic/tclOOMethod.c (TclOODelMethodRef): Correct fencepost error in reference counting of method implementation structures. * tests/oo.test (oo-0.5): Added a test to detect a memory leak problem relating to disposal of the core object system. TIP#257 IMPLEMENTATION * generic/tclBasic.c, generic/tclOOInt.h: Correct declarations. * win/Makefile.in, win/makefile.bc, win/makefile.vc: Build support for Win32, from Joe Mistachkin. [Patch 1980861] * generic/tclOO*, doc/*, tests/oo.test: Port of implementation of TclOO to sit directly inside Tcl. Note that this is incomplete (e.g. no build support yet for Windows). 2008-05-26 Jeff Hobbs * tests/io.test (io-53.9): Need to close chan before removing file. 2008-05-26 Donal K. Fellows * win/makefile.bc: Remove deprecated winhelp target. * win/Makefile.in, win/makefile.vc: It didn't work correctly anyway. 2008-05-23 Andreas Kupries * win/tclWinChan.c (FileWideSeekProc): Accepted a patch by Alexandre Ferrieux to fix the [Bug 1965787]. 'tell' now works for locations > 2 GB as well instead of going negative. * generic/tclIO.c (Tcl_SetChannelBufferSize): Accepted a patch by * tests/io.test: Alexandre Ferrieux * tests/chanio.test: to fix the [Bug 1969953]. Buffersize outside of the supported range are now clipped to nearest boundary instead of ignored. 2008-05-22 Don Porter * generic/tclNamesp.c (Tcl_LogCommandInfo): Restored ability to handle the argument value length = -1. Thanks to Chris Darroch for discovering the bug and providing the fix. [Bug 1968245] 2008-05-21 Don Porter * generic/tclParse.c (ParseComment): The new TclParseAllWhiteSpace * tests/parse.test (parse-15.60): routine has no mechanism to return the "incomplete" status of "\\\n" so calling this routine anywhere that can be reached within a Tcl_ParseCommand() call is a mistake. In particular, ParseComment() must not use it. [Bug 1968882] 2008-05-20 Donal K. Fellows * generic/tclNamesp.c (Tcl_SetNamespaceUnknownHandler): Corrected odd logic for handling installation of namespace unknown handlers which could lead too very strange things happening in the error case. 2008-05-16 Miguel Sofer * generic/tclCompile.c: Fix crash with tcl_traceExec. Found and fixed by Alexander Pasadyn. [Bug 1964803] 2008-05-15 Pat Thoyts * win/makefile.vc: We should use the thread allocator for threaded * win/rules.vc: builds. Added 'tclalloc' option to disable. 2008-05-09 George Peter Staplin * tools/tsdPerf.c: A loadable Tcl extension for testing TSD performance. * tools/tsdPerf.tcl: A simplistic tool that uses the thread extension and tsdPerf.so to get some performance metrics by, simulating, simple TSD contention. 2008-05-09 George Peter Staplin * generic/tcl.h: Make Tcl_ThreadDataKey a void *. * generic/tclInt.h: Change around some function names and add some new per-platform declarations for thread-specific data functions. * generic/tclThread.c: Make use of of the new function names that no longer have a Tclp prefix. * generic/tclThreadStorage.c: Replace the core thread-specific data (TSD) mechanism with an array offset solution that eliminates the hash tables, and only uses one slot of native TSD. Many thanks to Kevin B. Kenny for his help with this. * unix/tclUnixThrd.c: Add platform-specific TSD functions for use by * win/tclWinThrd.c: tclThreadStorage.c. 2008-05-09 Kevin B. Kenny * tests/dict.test (dict-19.2): Corrected a bug where the test was changed to use [apply] instead of a temporary proc, but the cleanup script still attempted to delete the temporary proc. 2008-05-07 Donal K. Fellows * generic/tclCompCmds.c (TclCompileDictAppendCmd): Fix silly off-by one error that caused a crash every time a compiled 'dict append' with more than one argument was used. Found by Colin McCormack. 2008-05-02 Pat Thoyts * generic/tclBasic.c: Converted the [binary] command into an * generic/tclBinary.c: ensemble. * generic/tclInt.h: * test/binary.test: Updated the error tests for ensemble errors. * generic/tclFileName.c: Reverted accidental commit of TIP 316 APIs. 2008-04-27 Donal K. Fellows * */*.c: A large tranche of getting rid of pre-C89-isms; if your compiler doesn't support things like proper function declarations, 'void' and 'const', borrow a proper one when building Tcl. (The header files allow building things that link against Tcl with really ancient compilers still; the requirement is just when building Tcl itself.) 2008-04-26 Zoran Vasiljevic * generic/tclAsync.c: Tcl_AsyncDelete(): panic if attempt to locate handler token fails. Happens when some other thread attempts to delete somebody else's token. Also, panic early if we find out the wrong thread attempting to delete the async handler (common trap). As, only the one that created the handler is allowed to delete it. 2008-04-24 Andreas Kupries * tests/ioCmd.test: Extended testsuite for reflected channel implementation. Added test cases about how it handles if the rug is pulled out from under a channel (= killing threads, interpreters containing the tcl command for a channel, and channel sitting in a different interpreter/thread.) * generic/tclIORChan.c: Fixed the bugs exposed by the new testcases, redone most of the cleanup and exit handling. 2008-04-21 Don Porter * generic/tclIOUtil.c: Removed all code delimited by * generic/tclTest.c: USE_OBSOLETE_FS_HOOKS, completing * tests/ioCmd.test: the deprecation path for these * tests/ioUtil.test (removed): obsolete interfaces. (Code was active in Tcl 8.4, present but enabled only by customized compile switch in Tcl 8.5, and now completely gone for Tcl 8.6). Also removed all tests relevant only to the removed interfaces. 2008-04-19 George Peter Staplin * doc/Ensemble.3: Fix a typo: s/defiend/defined/ Thanks to hat0 for spotting this. 2008-04-16 Daniel Steffen * generic/tclInt.h: Make stubs tables 'static const' and * generic/tclStubInit.c: export only module-scope pointers to * generic/tclStubLib.c: the main stubs tables (for package * tools/genStubs.tcl: initialization). [Patch 1938497] * generic/tclBasic.c (Tcl_CreateInterp): * generic/tclTomMathInterface.c (TclTommath_Init): * generic/tclInt.h: Revise Tcl_SetNotifier() to use a * generic/tclNotify.c: module-scope hooks table instead of * generic/tclStubInit.c: runtime stubs-table modification; * macosx/tclMacOSXNotify.c: ensure all hookable notifier functions * win/tclWinNotify.c: check for hooks; remove hook checks in * unix/tclUnixNotfy.c: notifier API callers. [Patch 1938497] 2008-04-15 Andreas Kupries * generic/tclIO.c (CopyData): Applied another patch by Alexandre * io.test (io-53.8a): Ferrieux , * chanio.test (chan-io-53.8a): to shift EOF handling to the async part of the command if a callback is specified, should the channel be at EOF already when fcopy is called. Testcase by myself. 2008-04-15 Daniel Steffen * unix/Makefile.in: Adjust tclDTrace.h dependencies for removal of tclStubLib.o from TCL_OBJS. [Bug 1942795] 2008-04-14 Kevin B. Kenny * unix/tclUnixTime.c (NativeGetTime): Removed obsolete use of 'struct timezone' in the call to 'gettimeofday'. [Bug 1942197] * tests/clock.test (clock-33.5, clock-33.5a, clock-33.8, clock-33.8a): Added comments to the test that it can fail on a heavily loaded system. 2008-04-10 Andreas Kupries * generic/tclIOCmd.c (Tcl_FcopyObjCmd): Keeping check for negative values, changed to not be an error, but behave like the special value -1 (copy all, default). * tests/iocmd.test (iocmd-15.{12,13}): Removed. * tests/io.test (io-52.5{,a,b}): Reverted last change, added * tests/chanio.test (chan-io-52.5{,a,b}): comment regarding the meaning of -1, added two more testcases for other negative values, and input wrapped to negative. 2008-04-09 Donal K. Fellows * tests/{fCmd,unixFCmd,winFCmd,winFile}.test: Tidying up of the test suite to make better use of tcltest2 and be clearer about what is being tested. * win/Makefile.in (html): Added target for doing convenient documentation builds, mirroring the one from unix/Makefile. 2008-04-09 Andreas Kupries * tests/chanio.test (chan-io-52.5): Removed '-size -1' from test, * tests/io.test (io-52.5): does not seem to have any bearing, and was an illegal value. Test case is not affected by the value of -size, test flag restoration and that evrything was properly copied. * generic/tclIOCmd.c (Tcl_FcopyObjCmd): Added checking of -size value * tests/ioCmd.test (iocmd-15.{13,14}): to reject negative values, and values overflowing 32-bit signed. Basic patch by Alexandre Ferrieux , with modifications from me to separate overflow from true negative value. Extended testsuite. [Bug 1557855] 2008-04-09 Daniel Steffen * tests/chanio.test (chan-io-53.8,53.9,53.10): Fix typo & quoting for * tests/io.test (io-53.8,53.9,53.10): spaces in builddir path 2008-04-08 Miguel Sofer * generic/tclExecute.c: Added comments to the alignment macros used in GrowEvaluationStack() and friends. 2008-04-08 Daniel Steffen * tools/genStubs.tcl: Revert erroneous 2008-04-02 change marking *StubsPtr as EXTERN instead of extern. * generic/tclDecls.h: make genstubs * generic/tclIntDecls.h: * generic/tclIntPlatDecls.h: * generic/tclPlatDecls.h: * generic/tclTomMathDecls.h: 2008-04-07 Andreas Kupries * tests/io.test (io-53.10): Testcase for bi-directional fcopy. * tests/chanio.test: * generic/tclIO.c: Additional changes to data structures for fcopy and * generic/tclIO.h: channels to perform proper cleanup in case of a channel having two background copy operations running as is now possible. * generic/tclIO.c (BUSY_STATE, CheckChannelErrors, TclCopyChannel): New macro, and the places using it. This change allows for bi-directional fcopy on channels. Thanks to Alexandre Ferrieux for the patch. [Bug 1350564] 2008-04-07 Reinhard Max * generic/tclStringObj.c (Tcl_AppendFormatToObj): Fix [format {% d}] so that it behaves the same way as in 8.4 and as C's printf(). * tests/format.test: Add a test for '% d' and '%+d'. 2008-04-05 Kevin B. Kenny * win/tclWinFile.c: (WinSymLinkDirectory): Fixed a problem that Tcl was creating an NTFS junction point (IO_REPARSE_TAG_MOUNT_POINT) but filling in the union member for a Vista symbolic link. We had gotten away with this error because the union member (SymbolicLinkReparseBuffer) was misdefined in this file and in the 'winnt.h' in early versions of MinGW. MinGW 3.4.2 has the correct definition of SymbolicLinkReparseBuffer, exposing the mismatch, and making tests cmdAH-19.4.1, fCmd-28.*, and filename-11.* fail. * tests/chanio.test (chan-io-53.9): * tests/io.test (io-53.9): Made test cleanup robust against the possibility of slow process shutdown on Windows. * win/tcl.m4: Added -D_CRT_SECURE_NO_DEPRECATE and -DCRT_NONSTDC_NO_DEPRECATE to the MSVC compilation flags so that the compilation doesn't barf on perfectly reasonable Posix system calls. * win/configure: Manually patched (don't have the right autoconf to hand). 2008-04-04 Andreas Kupries * tests/io.test (io-53.9): Added testcase for [Bug 780533], based * tests/chanio.test: on Alexandre's test script. Also fixed problem with timer in preceding test, was not canceled properly in the ok case 2008-04-04 Andreas Kupries * generic/tclIORChan.c (ReflectOutput): Allow zero return from write when input was zero-length anyway. Otherwise keept it an error, and separate the message from 'written too much'. * tests/ioCmd.test (iocmd-24.6): Testcase updated for changed message. * generic/tclIORChan.c (ReflectClose): Added missing removal of the now closed channel from the reflection map. Before we could crash the system by invoking 'chan postevent' on a closed reflected channel, dereferencing the dangling pointer in the map. * tests/ioCmd.test (iocmd-31.8): Testcase for the above. 2008-04-03 Andreas Kupries * generic/tclIO.c (CopyData): Applied patch [Bug 1932639] to * tests/io.test: prevent fcopy from calling -command synchronously * tests/chanio.test: the first time. Thanks to Alexandre Ferrieux for report and patch. 2008-04-02 Daniel Steffen * generic/tcl.decls: Remove 'export' declarations of symbols now only in libtclstub and no longer in libtcl. * generic/tclStubLib.c: Make symbols in libtclstub.a MODULE_SCOPE to * tools/genStubs.tcl: avoid exporting them from libraries that link with -ltclstub; constify tcl*StubsPtr and stub table hook pointers. [Bug 1819422] * generic/tclDecls.h: make genstubs * generic/tclIntDecls.h: * generic/tclIntPlatDecls.h: * generic/tclPlatDecls.h: * generic/tclStubInit.c: * generic/tclTomMathDecls.h: 2008-04-02 Andreas Kupries * generic/tclIO.c (CopyData): Applied patch for fcopy problem [Bug 780533], with many thanks to Alexandre Ferrieux for tracking it down and providing a solution. Still have to convert his test script into a proper test case. 2008-04-01 Andreas Kupries * generic/tclStrToD.c: Applied patch for [Bug 1839067] (fp rounding * unix/tcl.m4: setup on solaris x86, native cc), provided by Michael Schlenker. 2008-04-01 Don Porter * generic/tclStubLib.c: Removed needless #ifdef complexity. * generic/tclStubLib.c (Tcl_InitStubs): Added missing error message. * generic/tclPkg.c (Tcl_PkgInitStubsCheck): * README: Bump version number to 8.6a0 * generic/tcl.h: * library/init.tcl: * macosx/Tcl-Common.xcconfig: * macosx/Tcl.pbproj/default.pbxuser: * macosx/Tcl.pbproj/project.pbxproj: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/README: * win/configure.in: * win/makefile.bc: * win/tcl.m4: * unix/configure: autoconf-2.59 * win/configure: * generic/tclBasic.c: Revised stubs-generation tool and interp * tools/genStubs.tcl: creation so that "tclStubsPtr" is not present * unix/Makefile.in: in libtcl.so, but is present only in * win/Makefile.in: libtclstub.a. This tightens up the rules for * win/makefile.bc: users of the stubs interfaces. [Bug 1819422] * win/makefile.vc: * generic/tclDecls.h: make genstubs * generic/tclIntDecls.h: * generic/tclIntPlatDecls.h: * generic/tclPlatDecls.h: * generic/tclTomMathDecls.h: 2008-03-30 Kevin Kenny * generic/tclInt.h (TclIsNaN): * unix/configure.in: Added code to the configurator to check for a standard isnan() macro and use it if one is found. This change avoids bugs where the test of ((d) != (d)) is optimized away by an overaggressive compiler. [Bug 1783544] * generic/tclObj.c: Added missing #include needed to locate isnan() after the above change. * unix/configure: autoconf-2.61 * tests/mathop.test (mathop-25.9, mathop-25.14): Modified tests to deal with (slightly buggy) math libraries in which pow() returns an incorrectly rounded result. [Bug 1808174] 2008-03-26 Don Porter *** 8.5.2 TAGGED FOR RELEASE *** * generic/tcl.h: Bump to 8.5.2 for release. * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf-2.59 * win/configure: * changes: Updated for 8.5.2 release. 2008-03-28 Donal K. Fellows * tests/fCmd.test: Substantial rewrite to use many more tcltest features. Great reduction in quantity of [catch] gymnastics. Several buggy tests fixed, including one where the result of the previous test was being checked! 2008-03-27 Kevin B. Kenny * library/tzdata/America/Marigot: * library/tztata/America/St_Barthelemy: * library/tzdata/America/Argentina/San_Luis: * library/tzdata/Asia/Ho_Chi_Minh: * library/tzdata/Asia/Kolkata: (new files) * library/tzdata/America/Caracas: * library/tzdata/America/Havana: * library/tzdata/America/Santiago: * library/tzdata/America/Argentina/Buenos_Aires: * library/tzdata/America/Argentina/Catamarca: * library/tzdata/America/Argentina/Cordoba: * library/tzdata/America/Argentina/Jujuy: * library/tzdata/America/Argentina/La_Rioja: * library/tzdata/America/Argentina/Mendoza: * library/tzdata/America/Argentina/Rio_Gallegos: * library/tzdata/America/Argentina/San_Juan: * library/tzdata/America/Argentina/Tucuman: * library/tzdata/America/Argentina/Ushuaia: * library/tzdata/Asia/Baghdad: * library/tzdata/Asia/Calcutta: * library/tzdata/Asia/Damascus: * library/tzdata/Asia/Saigon: * library/tzdata/Pacific/Easter: Changes up to and including Olson's tzdata2008b. 2008-03-27 Daniel Steffen * unix/tcl.m4 (SunOS-5.1x): Fix 64bit support for Sun cc. [Bug 1921166] * unix/configure: autoconf-2.59 2008-03-26 Don Porter * changes: Updated for 8.5.2 release. 2008-03-24 Pat Thoyts * generic/tclBinary.c: [Bug 1923966] - crash in binary format * tests/binary.test: Added tests for the above crash condition. 2008-03-21 Donal K. Fellows * doc/switch.n: Clarified documentation in respect of two-argument invokation. [Bug 1899962] * tests/switch.test: Added more tests of regexp-mode compilation of the [switch] command. [Bug 1854435] 2008-03-20 Donal K. Fellows * generic/tcl.h, generic/tclThreadAlloc.c: Tidied up the declarations of Tcl_GetMemoryInfo so that it is always defined. Will panic when called against a Tcl that was previously built without it at all, which is OK because that also indicates a serious mismatch between memory configuration options. 2008-03-19 Donal K. Fellows * generic/tcl.h, generic/tclThreadAlloc.c (Tcl_GetMemoryInfo): Make sure this function is available when direct linking. [Bug 1868171] * tests/reg.test (reg-33.14): Marked nonPortable because some environments have small default stack sizes. [Bug 1905562] 2008-03-18 Andreas Kupries * library/tm.tcl (::tcl::tm::UnknownHandler): Changed 'source' to 'source -encoding utf-8'. This fixes a portability problem of Tcl Modules pointed out by Don Porter. By using plain 'source' we were at the mercy of 'encoding system', making modules less portable than they could be. The exact scenario: A writes a TM in some weird encoding which is A's system encoding, distributes it, and somewhere else it cannot be read/used because the system encoding is different. Forcing the use of utf-8 makes the module portable. ***INCOMPATIBILITY*** for all Tcl Modules already written in non-utf-8 compatible encodings. 2008-03-18 Don Porter * generic/tclExecute.c: Patch from Miguel Sofer to correct the alignment of memory allocated by GrowEvaluationStack(). [Bug 1914503] 2008-03-18 Andreas Kupries * library/tm.tcl (::tcl::tm::Defaults): Modified handling of environment variables. Solution slightly different than proposed in the report. Using the underscored form TCLX_y_TM_PATH even if TCLX.y_TM_PATH exists. Also using a loop to cut prevent code replication. [Bug 1914604] 2008-03-16 Donal K. Fellows * generic/tclCompCmds.c (TclCompileDictForCmd): Correct the handling of stack space calculation (the jump pattern used was confusing the simple-minded code doing the calculations). [Bug 1903325] * doc/lreplace.n: Clarified documentation of what happens with negative indices. [Bug 1905809] Added example, tidied up formatting. 2008-03-14 Don Porter * generic/tclBasic.c (OldMathFuncProc): Same workaround protection from bad TclStackAlloc() alignment. Thanks George Peter Staplin. * generic/tclCmdIL.c (Tcl_LsortObjCmd): Use ckalloc() to allocate SortElement arrays instead of TclStackAlloc() which isn't getting alignment right. Workaround for [Bug 1914503]. 2008-03-14 Reinhard Max * generic/tclTest.c: Ignore the return value of write() when we are * unix/tclUnixPipe.c: about to exit anyways. 2008-03-13 Daniel Steffen * unix/configure.in: Use backslash-quoting instead of double-quoting * unix/tcl.m4: for lib paths in tclConfig.sh. [Bug 1913622] * unix/configure: autoconf-2.59 2008-03-13 Don Porter * changes: Updated for 8.5.2 release. * generic/tclStrToD.c: Resolve identifier conflict over "pow10" with libm in Cygwin and DJGPP. Thanks to Gordon Schumacher and Philip Moore. [Patch 1800636] 2008-03-12 Daniel Steffen * macosx/Tcl.xcodeproj/project.pbxproj: Add support for Xcode 3.1 * macosx/Tcl.xcodeproj/default.pbxuser: CODE_SIGN_IDENTITY and * macosx/Tcl-Common.xcconfig: 'xcodebuild install'. 2008-03-12 Andreas Kupries * doc/info.n: Replaced {expand} with {*}. 2008-03-12 Jeff Hobbs * unix/Makefile.in (install-libraries): Bump http to 2.7 * win/Makefile.in (install-libraries): Added -myaddr option to allow * library/http/http.tcl (http::geturl): control of selected socket * library/http/pkgIndex.tcl: interface. [Bug 559898] * doc/http.n, tests/http.test: Added -keepalive and -protocol 1.1 with chunked transfer encoding support. [Bug 1063703, 1470377, 219225] (default keepalive is 0) Added ability to override Host in -headers. [Bug 928154] Added -strict option to control URL validation on per-call basis. [Bug 1560506] 2008-03-11 Jeff Hobbs * library/http/http.tcl (http::geturl): Add -method option to support * tests/http.test (http-3.1): http PUT and DELETE requests. * doc/http.n: [Bug 1599901, 862554] * library/http/http.tcl: Whitespace changes, code cleanup. Allow http to be re-sourced without overwriting http state. 2008-03-11 Daniel Steffen * generic/tclEncoding.c (LoadEscapeEncoding): Avoid leaking escape sub-encodings, fixes encoding-11.1 failing after iso2022-jp loaded. [Bug 1893053] * macosx/tclMacOSXNotify.c: Avoid using CoreFoundation after fork() on Darwin 9 even when TclpCreateProcess() uses vfork(). * macosx/Tcl.xcodeproj/project.pbxproj: Add support for Xcode 3.1 and * macosx/Tcl.xcodeproj/default.pbxuser: configs for building with * macosx/Tcl-Common.xcconfig: gcc-4.2 and llvm-gcc-4.2. * unix/tclUnixPort.h: Workaround vfork() problems in llvm-gcc-4.2.1 -O4 build. * unix/tclUnixPort.h: Move MODULE_SCOPE compat define to top. [Bug 1911102] * macosx/GNUmakefile: Fix quoting to allow paths * macosx/Tcl-Common.xcconfig: to ${builddir} and * unix/Makefile.in: ${INSTALL_ROOT} to contain * unix/configure.in: spaces. * unix/install-sh: * unix/tcl.m4: * tests/ioCmd.test: * unix/configure: autoconf-2.59 * unix/Makefile.in (install-strip): Strip non-global symbols from dynamic library. * unix/tclUnixNotfy.c: Fix warning. * tests/exec.test (exec-9.7): Reduce timing sensitivity * tests/socket.test (socket-2.11): (esp. on multi-proc machines). * tests/fCmd.test (fCmd-9.4): Skip on Darwin 9 (xfail). 2008-03-11 Miguel Sofer * generic/tclVar.c (TclDeleteNamespaceVars): * tests/var.test (var-8.2): Unset traces on vars should be called with a FQ named during namespace deletion. This was causing infinite loops when unset traces recreated the var, as reported by Julian Noble. [Bug 1911919] 2008-03-10 Don Porter * changes: Updated for 8.5.2 release. * doc/http.n: Revised to indicate that [package require http 2.5.5] is needed to get all the documented commands ([http::meta]). * generic/tclEvent.c (TclDefaultBgErrorHandlerObjCmd): Added error * tests/event.test (event-5.*): checking to protect against callers passing invalid return options dictionaries. [Bug 1901113] * generic/tclBasic.c (ExprAbsFunc): Revised so that the abs() * tests/expr.test: function and the [::tcl::mathfunc::abs] command do not return the value of -0, or equivalent values with more alarming string reps like -1e-350. [Bug 1893815] 2008-03-07 Andreas Kupries * generic/tclResult.c (ReleaseKeys): Workaround for [Bug 1904907]. Reset the return option keys to NULL to allow full re-initialization by GetKeys(). This introduces a memory leak for the key objects, but gets us around a crash in the finalization of reflected channels when handling returns, either at compile- or runtime. In both cases we access the keys after they have been released by their thread exit handler. A proper fix is entangled with the untangling of the finalization ordering and attendant issues. For now we choose the lesser evil. 2008-03-07 Don Porter * generic/tclExecute.c (Tcl_ExprObj): Revised expression bytecode compiling so that bytecodes invalid due to changing context or due to the difference between expressions and scripts are not reused. [Bug 1899164] * generic/tclCmdAH.c: Revised direct evaluation implementation of [expr] so that [expr $e] caches compiled bytecodes for the expression as the intrep of $e. * tests/execute.test (execute-6.*): More tests checking that script bytecode is invalidated in the right situations. 2008-03-07 Donal K. Fellows * win/configure.in: Add AC_HEADER_STDC to support msys/win64. 2008-03-06 Donal K. Fellows * doc/namespace.n: Minor tidying up. [Bug 1909019] 2008-03-04 Don Porter * tests/execute.test (6.3,4): Added tests for [Bug 1899164]. 2008-03-03 Reinhard Max * unix/tclUnixChan.c: Fix mark and space parity on Linux, which uses CMSPAR instead of PAREXT. 2008-03-02 Miguel Sofer * generic/tclNamesp.c (GetNamespaceFromObj): * tests/interp.test (interp-28.2): Spoil the intrep of an nsNameType obj when the reference crosses interpreter boundaries. 2008-02-29 Don Porter * generic/tclResult.c (Tcl_SetReturnOptions): Revised the refcount management of Tcl_SetReturnOptions to become that of a conventional Consumer routine. Thanks to Peter Spjuth for pointing out the difficulties calling Tcl_SetReturnOptions with non-0-count value for options. * generic/tclExecute.c (INST_RETURN_STK): Revised the one caller within Tcl itself which passes a non-0-count value to Tcl_SetReturnOptions(). * generic/tclBasic.c (Tcl_AppendObjToErrorInfo): Revised the refcount management of Tcl_AppendObjToErrorInfo to become that of a conventional Consumer routine. This preserves the ease of use for the overwhelming common callers who pass in a 0-count value, but makes the proper call with a non-0-count value less surprising. * generic/tclEvent.c (TclDefaultBgErrorHandlerObjCmd): Revised the one caller within Tcl itself which passes a non-0-count value to Tcl_AppendObjToErrorInfo(). 2008-02-28 Joe English * unix/tclPort.h, unix/tclCompat.h, unix/tclUnixChan.h: Reduce scope of and #includes. [Patch 1903339] 2008-02-28 Joe English * unix/tclUnixChan.c, unix/tclUnixNotfy.c, unix/tclUnixPipe.c: Consolidate all code conditionalized on -DUSE_FIONBIO into one place. * unix/tclUnixPort.h, unix/tclUnixCompat.c: New routine TclUnixSetBlockingMode(). [Patch 1903339] 2008-02-28 Don Porter * generic/tclBasic.c (TclEvalObjvInternal): Plug memory leak when an enter trace deletes or changes the command, prompting a reparsing. Don't let the second pass lose commandPtr value allocated during the first pass. * generic/tclCompExpr.c (ParseExpr): Plug memory leak in error message generation. * generic/tclStringObj.c (Tcl_AppendFormatToObj): [format %llx $big] leaked an mp_int. * generic/tclCompCmds.c (TclCompileReturnCmd): The 2007-10-18 commit to optimize compiled [return -level 0 $x] [RFE 1794073] introduced a memory leak of the return options dictionary. Fixing that. 2008-02-27 Pat Thoyts * library/http/http.tcl: [Bug 705956] - fix inverted logic when cleaning up socket error in geturl. 2008-02-27 Kevin B. Kenny * doc/clock.n: Corrected minor indentation gaffe in the penultimate paragraph. [Bug 1898025] * generic/tclClock.c (ParseClockFormatArgs): Changed to check that the clock value is in the range of a 64-bit integer. [Bug 1862555] * library/clock.tcl (::tcl::clock::format, ::tcl::clock::scan, (::tcl::clock::add, ::tcl::clock::LocalizeFormat): Fixed bugs in caching of localized strings that caused weird results when localized date/time formats were used. [Bug 1902423] * tests/clock.test (clock-61.*, clock-62.1): Regression tests for [Bug 1862555] and [Bug 1902423]. 2008-02-26 Joe English * generic/tclIOUtil.c, unix/tclUnixPort.h, unix/tclUnixChan.c: Remove dead/unused portability-related #defines and unused conditional code. See [Patch 1901828] for discussion. 2008-02-26 Joe English * generic/tclIORChan.c (enum MethodName), * generic/tclCompExpr.c (enum Marks): More stray trailing ","s 2008-02-26 Joe English * unix/configure.in(socklen_t test): Define socklen_t as "int" if missing, not "unsigned". Use AC_TRY_COMPILE instead of AC_EGREP_HEADER. * unix/configure: regenerated. 2008-02-26 Joe English * generic/tclCompile.h: Remove stray trailing "," from enum InstOperandType definition (C99ism). 2008-02-26 Jeff Hobbs * generic/tclUtil.c (TclReToGlob): Fix the handling of the last star * tests/regexpComp.test: possibly being escaped in determining right anchor. [Bug 1902436] 2008-02-26 Pat Thoyts * library/http/pkgIndex.tcl: Set version 2.5.5 * library/http/http.tcl: It is better to do the [eof] check after trying to read from the socket. No clashes found in testing. Added http::meta command to access the http headers. [Bug 1868845] 2008-02-22 Pat Thoyts * library/http/pkgIndex.tcl: Set version 2.5.4 * library/http/http.tcl: Always check that the state array exists in the http::status command. [Bug 1818565] 2008-02-13 Don Porter * generic/tcl.h: Bump version number to 8.5.2b1 to distinguish * library/init.tcl: CVS development snapshots from the 8.5.1 and * unix/configure.in: 8.5.2 releases. * unix/tcl.spec: * win/configure.in: * README * unix/configure: autoconf (2.59) * win/configure: 2008-02-12 Donal K. Fellows * generic/tclCompCmds.c (TclCompileSwitchCmd): Corrected logic for * tests/switch.test (switch-10.15): handling -nocase compilation; the -exact -nocase option cannot be compiled currently. [Bug 1891827] * unix/README: Documented missing configure flags. [Bug 1799011] 2008-02-06 Kevin B. Kenny * doc/clock.n (%N): Corrected an error in the explanation of the %N format group. * generic/tclClock.c (ClockParseformatargsObjCmd): * library/clock.tcl (::tcl::clock::format): * tests/clock.test (clock-1.0, clock-1.4): Performance enhancements in [clock format] (moving the analysis of $args into C code, holding on to Tcl_Objs with resolved command names, [lassign] in place of [foreach], avoiding [namespace which] for command resolution). 2008-02-04 Don Porter *** 8.5.1 TAGGED FOR RELEASE *** * changes: Updated for 8.5.1 release. * generic/tcl.h: Bump to 8.5.1 for release. * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf-2.59 * win/configure: 2008-02-04 Miguel Sofer * generic/tclExecute.c (INST_CONCAT1): Fix optimisation for in-place concatenation (was going over String type) 2008-02-02 Daniel Steffen * unix/configure.in (Darwin): Correct Info.plist year substitution in non-framework builds. * unix/configure: autoconf-2.59 2008-01-30 Miguel Sofer * generic/tclInterp.c (Tcl_GetAlias): Fix for [Bug 1882373], thanks go to an00na. 2008-01-30 Donal K. Fellows * tools/tcltk-man2html.tcl: Reworked manual page scraper to do a proper job of handling references to Ttk options. [Tk Bug 1876493] 2008-01-29 Donal K. Fellows * doc/man.macros (SO, SE): Adjusted macros so that it is possible for Ttk to have its "standard options" on a manual page that is not called "options". [Tk Bug 1876493] 2008-01-25 Don Porter * changes: Updated for 8.5.1 release. 2008-01-23 Don Porter * generic/tclInt.h: New macro TclGrowParseTokenArray() to * generic/tclCompCmds.c: simplify code that might need to grow * generic/tclCompExpr.c: an array of Tcl_Tokens in the parsePtr * generic/tclParse.c: field of a Tcl_Parse. Replaces the TclExpandTokenArray() routine via replacing: int needed = parsePtr->numTokens + growth; while (needed > parsePtr->tokensAvailable) { TclExpandTokenArray(parsePtr); } with: TclGrowParseTokenArray(parsePtr, growth); This revision merged over from dgp-refactor branch. * generic/tclCompile.h: Demote TclCompEvalObj() from internal stubs to * generic/tclInt.decls: a MODULE_SCOPE routine declared in tclCompile.h. * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: 2008-01-22 Don Porter * generic/tclTimer.c (AfterProc): Replace Tcl_EvalEx() with Tcl_EvalObjEx() to evaluate [after] callbacks. Part of trend to favor compiled execution over direct evaluation. 2008-01-22 Miguel Sofer * generic/tclCmdIl.c (Tcl_LreverseObjCmd): * tests/cmdIL.test (cmdIL-7.7): Fix crash on reversing an empty list. [Bug 1876793] 2008-01-20 Jeff Hobbs * unix/README: Minor typo fixes [Bug 1853072] * generic/tclIO.c (TclGetsObjBinary): Operate on topmost channel. [Bug 1869405] (Ficicchia) 2008-01-17 Don Porter * generic/tclCompExpr.c: Revision to preserve parsed intreps of numeric and boolean literals when compiling expressions with (optimize == 1). 2008-01-15 Miguel Sofer * generic/tclCompExpr.c: Add an 'optimize' argument to * generic/tclCompile.c: TclCompileExpr() to profit from better * generic/tclCompile.h: literal management according to usage. * generic/tclExecute.c: * generic/tclCompExpr.c: Fix literal leak in exprs [Bug 1869989] (dgp) * generic/tclExecute.c: * tests/compExpr.test: * doc/proc.n: Changed wording for access to non-local variables; added mention to [namespace upvar]. Lame attempt at dealing with documentation. [Bug 1872708] 2008-01-15 Miguel Sofer * generic/tclBasic.c: Replacing 'operator' by 'op' in the def of * generic/tclCompExpr.c: struct TclOpCmdClientData to accommodate C++ * generic/tclCompile.h: compilers. [Bug 1855644] 2008-01-13 Jeff Hobbs * win/tclWinSerial.c (SerialCloseProc, TclWinOpenSerialChannel): Use critical section for read & write side. [Bug 1353846] (newman) 2008-01-11 Miguel Sofer * unix/tclUnixThrd.c (TclpThreadGetStackSize): Restore stack checking functionality in freebsd. [Bug 1850424] * unix/tclUnixThrd.c (TclpThreadGetStackSize): Fix for crash in freebsd. [Bug 1860425] 2008-01-10 Don Porter * generic/tclStringObj.c (Tcl_AppendFormatToObj): Correct failure to * tests/format.test: account for big.used == 0 corner case in the %ll(idox) format directives. [Bug 1867855] 2008-01-09 George Peter Staplin * doc/vwait.n: Add a missing be to fix a typo. 2008-01-04 Jeff Hobbs * tools/tcltk-man2html.tcl (make-man-pages): Make man page title use more specific info on lhs to improve tabbed browser view titles. 2008-01-02 Donal K. Fellows * doc/binary.n: Fixed documentation bug reported on tcl-core, and reordered documentation to discourage people from using the hex formatter that is hardly ever useful. 2008-01-02 Don Porter * generic/tcl.h: Bump version number to 8.5.1b1 to distinguish * library/init.tcl: CVS development snapshots from the 8.5.0 and * unix/configure.in: 8.5.1 releases. * unix/tcl.spec: * win/configure.in: * README * unix/configure: autoconf (2.59) * win/configure: ****************************************************************** *** CHANGELOG ENTRIES FOR 2006-2007 IN "ChangeLog.2007" *** *** CHANGELOG ENTRIES FOR 2005 IN "ChangeLog.2005" *** *** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2004" *** *** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003" *** *** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002" *** *** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" *** *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" *** *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" *** ****************************************************************** tcl8.6.5/generic/0000755000175000017500000000000012665173607013206 5ustar sergeisergeitcl8.6.5/generic/tclStrToD.c0000644000175000017500000040410312663660065015233 0ustar sergeisergei/* * tclStrToD.c -- * * This file contains a collection of procedures for managing conversions * to/from floating-point in Tcl. They include TclParseNumber, which * parses numbers from strings; TclDoubleDigits, which formats numbers * into strings of digits, and procedures for interconversion among * 'double' and 'mp_int' types. * * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tommath.h" #include /* * Define KILL_OCTAL to suppress interpretation of numbers with leading zero * as octal. (Ceterum censeo: numeros octonarios delendos esse.) */ #undef KILL_OCTAL /* * This code supports (at least hypothetically), IBM, Cray, VAX and IEEE-754 * floating point; of these, only IEEE-754 can represent NaN. IEEE-754 can be * uniquely determined by radix and by the widths of significand and exponent. */ #if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024) # define IEEE_FLOATING_POINT #endif /* * Rounding controls. (Thanks a lot, Intel!) */ #ifdef __i386 /* * gcc on x86 needs access to rounding controls, because of a questionable * feature where it retains intermediate results as IEEE 'long double' values * somewhat unpredictably. It is tempting to include fpu_control.h, but that * file exists only on Linux; it is missing on Cygwin and MinGW. Most gcc-isms * and ix86-isms are factored out here. */ #if defined(__GNUC__) typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__))); #define _FPU_GETCW(cw) __asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw)) #define _FPU_SETCW(cw) __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw)) # define FPU_IEEE_ROUNDING 0x027f # define ADJUST_FPU_CONTROL_WORD #define TCL_IEEE_DOUBLE_ROUNDING \ fpu_control_t roundTo53Bits = FPU_IEEE_ROUNDING; \ fpu_control_t oldRoundingMode; \ _FPU_GETCW(oldRoundingMode); \ _FPU_SETCW(roundTo53Bits) #define TCL_DEFAULT_DOUBLE_ROUNDING \ _FPU_SETCW(oldRoundingMode) /* * Sun ProC needs sunmath for rounding control on x86 like gcc above. */ #elif defined(__sun) #include #define TCL_IEEE_DOUBLE_ROUNDING \ ieee_flags("set","precision","double",NULL) #define TCL_DEFAULT_DOUBLE_ROUNDING \ ieee_flags("clear","precision",NULL,NULL) /* * Other platforms are assumed to always operate in full IEEE mode, so we make * the macros to go in and out of that mode do nothing. */ #else /* !__GNUC__ && !__sun */ #define TCL_IEEE_DOUBLE_ROUNDING ((void) 0) #define TCL_DEFAULT_DOUBLE_ROUNDING ((void) 0) #endif #else /* !__i386 */ #define TCL_IEEE_DOUBLE_ROUNDING ((void) 0) #define TCL_DEFAULT_DOUBLE_ROUNDING ((void) 0) #endif /* * MIPS floating-point units need special settings in control registers to use * gradual underflow as we expect. This fix is for the MIPSpro compiler. */ #if defined(__sgi) && defined(_COMPILER_VERSION) #include #endif /* * HP's PA_RISC architecture uses 7ff4000000000000 to represent a quiet NaN. * Everyone else uses 7ff8000000000000. (Why, HP, why?) */ #ifdef __hppa # define NAN_START 0x7ff4 # define NAN_MASK (((Tcl_WideUInt) 1) << 50) #else # define NAN_START 0x7ff8 # define NAN_MASK (((Tcl_WideUInt) 1) << 51) #endif /* * Constants used by this file (most of which are only ever calculated at * runtime). */ /* Magic constants */ #define LOG10_2 0.3010299956639812 #define TWO_OVER_3LOG10 0.28952965460216784 #define LOG10_3HALVES_PLUS_FUDGE 0.1760912590558 /* * Definitions of the parts of an IEEE754-format floating point number. */ #define SIGN_BIT 0x80000000 /* Mask for the sign bit in the first word of * a double. */ #define EXP_MASK 0x7ff00000 /* Mask for the exponent field in the first * word of a double. */ #define EXP_SHIFT 20 /* Shift count to make the exponent an * integer. */ #define HIDDEN_BIT (((Tcl_WideUInt) 0x00100000) << 32) /* Hidden 1 bit for the significand. */ #define HI_ORDER_SIG_MASK 0x000fffff /* Mask for the high-order part of the * significand in the first word of a * double. */ #define SIG_MASK (((Tcl_WideUInt) HI_ORDER_SIG_MASK << 32) \ | 0xffffffff) /* Mask for the 52-bit significand. */ #define FP_PRECISION 53 /* Number of bits of significand plus the * hidden bit. */ #define EXPONENT_BIAS 0x3ff /* Bias of the exponent 0. */ /* * Derived quantities. */ #define TEN_PMAX 22 /* floor(FP_PRECISION*log(2)/log(5)) */ #define QUICK_MAX 14 /* floor((FP_PRECISION-1)*log(2)/log(10))-1 */ #define BLETCH 0x10 /* Highest power of two that is greater than * DBL_MAX_10_EXP, divided by 16. */ #define DIGIT_GROUP 8 /* floor(DIGIT_BIT*log(2)/log(10)) */ /* * Union used to dismantle floating point numbers. */ typedef union Double { struct { #ifdef WORDS_BIGENDIAN int word0; int word1; #else int word1; int word0; #endif } w; double d; Tcl_WideUInt q; } Double; static int maxpow10_wide; /* The powers of ten that can be represented * exactly as wide integers. */ static Tcl_WideUInt *pow10_wide; #define MAXPOW 22 static double pow10vals[MAXPOW+1]; /* The powers of ten that can be represented * exactly as IEEE754 doubles. */ static int mmaxpow; /* Largest power of ten that can be * represented exactly in a 'double'. */ static int log10_DIGIT_MAX; /* The number of decimal digits that fit in an * mp_digit. */ static int log2FLT_RADIX; /* Logarithm of the floating point radix. */ static int mantBits; /* Number of bits in a double's significand */ static mp_int pow5[9]; /* Table of powers of 5**(2**n), up to * 5**256 */ static double tiny = 0.0; /* The smallest representable double. */ static int maxDigits; /* The maximum number of digits to the left of * the decimal point of a double. */ static int minDigits; /* The maximum number of digits to the right * of the decimal point in a double. */ static const double pow_10_2_n[] = { /* Inexact higher powers of ten. */ 1.0, 100.0, 10000.0, 1.0e+8, 1.0e+16, 1.0e+32, 1.0e+64, 1.0e+128, 1.0e+256 }; static int n770_fp; /* Flag is 1 on Nokia N770 floating point. * Nokia's floating point has the words * reversed: if big-endian is 7654 3210, * and little-endian is 0123 4567, * then Nokia's FP is 4567 0123; * little-endian within the 32-bit words but * big-endian between them. */ /* * Table of powers of 5 that are small enough to fit in an mp_digit. */ static const mp_digit dpow5[13] = { 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, 48828125, 244140625 }; /* * Table of powers: pow5_13[n] = 5**(13*2**(n+1)) */ static mp_int pow5_13[5]; /* Table of powers: 5**13, 5**26, 5**52, * 5**104, 5**208 */ static const double tens[] = { 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22 }; static const int itens [] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 }; static const double bigtens[] = { 1e016, 1e032, 1e064, 1e128, 1e256 }; #define N_BIGTENS 5 static const int log2pow5[27] = { 01, 3, 5, 7, 10, 12, 14, 17, 19, 21, 24, 26, 28, 31, 33, 35, 38, 40, 42, 45, 47, 49, 52, 54, 56, 59, 61 }; #define N_LOG2POW5 27 static const Tcl_WideUInt wuipow5[27] = { (Tcl_WideUInt) 1, /* 5**0 */ (Tcl_WideUInt) 5, (Tcl_WideUInt) 25, (Tcl_WideUInt) 125, (Tcl_WideUInt) 625, (Tcl_WideUInt) 3125, /* 5**5 */ (Tcl_WideUInt) 3125*5, (Tcl_WideUInt) 3125*25, (Tcl_WideUInt) 3125*125, (Tcl_WideUInt) 3125*625, (Tcl_WideUInt) 3125*3125, /* 5**10 */ (Tcl_WideUInt) 3125*3125*5, (Tcl_WideUInt) 3125*3125*25, (Tcl_WideUInt) 3125*3125*125, (Tcl_WideUInt) 3125*3125*625, (Tcl_WideUInt) 3125*3125*3125, /* 5**15 */ (Tcl_WideUInt) 3125*3125*3125*5, (Tcl_WideUInt) 3125*3125*3125*25, (Tcl_WideUInt) 3125*3125*3125*125, (Tcl_WideUInt) 3125*3125*3125*625, (Tcl_WideUInt) 3125*3125*3125*3125, /* 5**20 */ (Tcl_WideUInt) 3125*3125*3125*3125*5, (Tcl_WideUInt) 3125*3125*3125*3125*25, (Tcl_WideUInt) 3125*3125*3125*3125*125, (Tcl_WideUInt) 3125*3125*3125*3125*625, (Tcl_WideUInt) 3125*3125*3125*3125*3125, /* 5**25 */ (Tcl_WideUInt) 3125*3125*3125*3125*3125*5 /* 5**26 */ }; /* * Static functions defined in this file. */ static int AccumulateDecimalDigit(unsigned, int, Tcl_WideUInt *, mp_int *, int); static double MakeHighPrecisionDouble(int signum, mp_int *significand, int nSigDigs, int exponent); static double MakeLowPrecisionDouble(int signum, Tcl_WideUInt significand, int nSigDigs, int exponent); #ifdef IEEE_FLOATING_POINT static double MakeNaN(int signum, Tcl_WideUInt tag); #endif static double RefineApproximation(double approx, mp_int *exactSignificand, int exponent); static void MulPow5(mp_int *, unsigned, mp_int *); static int NormalizeRightward(Tcl_WideUInt *); static int RequiredPrecision(Tcl_WideUInt); static void DoubleToExpAndSig(double, Tcl_WideUInt *, int *, int *); static void TakeAbsoluteValue(Double *, int *); static char * FormatInfAndNaN(Double *, int *, char **); static char * FormatZero(int *, char **); static int ApproximateLog10(Tcl_WideUInt, int, int); static int BetterLog10(double, int, int *); static void ComputeScale(int, int, int *, int *, int *, int *); static void SetPrecisionLimits(int, int, int *, int *, int *, int *); static char * BumpUp(char *, char *, int *); static int AdjustRange(double *, int); static char * ShorteningQuickFormat(double, int, int, double, char *, int *); static char * StrictQuickFormat(double, int, int, double, char *, int *); static char * QuickConversion(double, int, int, int, int, int, int, int *, char **); static void CastOutPowersOf2(int *, int *, int *); static char * ShorteningInt64Conversion(Double *, int, Tcl_WideUInt, int, int, int, int, int, int, int, int, int, int, int, int *, char **); static char * StrictInt64Conversion(Double *, int, Tcl_WideUInt, int, int, int, int, int, int, int, int, int *, char **); static int ShouldBankerRoundUpPowD(mp_int *, int, int); static int ShouldBankerRoundUpToNextPowD(mp_int *, mp_int *, int, int, int, mp_int *); static char * ShorteningBignumConversionPowD(Double *dPtr, int convType, Tcl_WideUInt bw, int b2, int b5, int m2plus, int m2minus, int m5, int sd, int k, int len, int ilim, int ilim1, int *decpt, char **endPtr); static char * StrictBignumConversionPowD(Double *dPtr, int convType, Tcl_WideUInt bw, int b2, int b5, int sd, int k, int len, int ilim, int ilim1, int *decpt, char **endPtr); static int ShouldBankerRoundUp(mp_int *, mp_int *, int); static int ShouldBankerRoundUpToNext(mp_int *, mp_int *, mp_int *, int, int, mp_int *); static char * ShorteningBignumConversion(Double *dPtr, int convType, Tcl_WideUInt bw, int b2, int m2plus, int m2minus, int s2, int s5, int k, int len, int ilim, int ilim1, int *decpt, char **endPtr); static char * StrictBignumConversion(Double *dPtr, int convType, Tcl_WideUInt bw, int b2, int s2, int s5, int k, int len, int ilim, int ilim1, int *decpt, char **endPtr); static double BignumToBiasedFrExp(const mp_int *big, int *machexp); static double Pow10TimesFrExp(int exponent, double fraction, int *machexp); static double SafeLdExp(double fraction, int exponent); #ifdef IEEE_FLOATING_POINT static Tcl_WideUInt Nokia770Twiddle(Tcl_WideUInt w); #endif /* *---------------------------------------------------------------------- * * TclParseNumber -- * * Scans bytes, interpreted as characters in Tcl's internal encoding, and * parses the longest prefix that is the string representation of a * number in a format recognized by Tcl. * * The arguments bytes, numBytes, and objPtr are the inputs which * determine the string to be parsed. If bytes is non-NULL, it points to * the first byte to be scanned. If bytes is NULL, then objPtr must be * non-NULL, and the string representation of objPtr will be scanned * (generated first, if necessary). The numBytes argument determines the * number of bytes to be scanned. If numBytes is negative, the first NUL * byte encountered will terminate the scan. If numBytes is non-negative, * then no more than numBytes bytes will be scanned. * * The argument flags is an input that controls the numeric formats * recognized by the parser. The flag bits are: * * - TCL_PARSE_INTEGER_ONLY: accept only integer values; reject * strings that denote floating point values (or accept only the * leading portion of them that are integer values). * - TCL_PARSE_SCAN_PREFIXES: ignore the prefixes 0b and 0o that are * not part of the [scan] command's vocabulary. Use only in * combination with TCL_PARSE_INTEGER_ONLY. * - TCL_PARSE_OCTAL_ONLY: parse only in the octal format, whether * or not a prefix is present that would lead to octal parsing. * Use only in combination with TCL_PARSE_INTEGER_ONLY. * - TCL_PARSE_HEXADECIMAL_ONLY: parse only in the hexadecimal format, * whether or not a prefix is present that would lead to * hexadecimal parsing. Use only in combination with * TCL_PARSE_INTEGER_ONLY. * - TCL_PARSE_DECIMAL_ONLY: parse only in the decimal format, no * matter whether a 0 prefix would normally force a different * base. * - TCL_PARSE_NO_WHITESPACE: reject any leading/trailing whitespace * * The arguments interp and expected are inputs that control error * message generation. If interp is NULL, no error message will be * generated. If interp is non-NULL, then expected must also be non-NULL. * When TCL_ERROR is returned, an error message will be left in the * result of interp, and the expected argument will appear in the error * message as the thing TclParseNumber expected, but failed to find in * the string. * * The arguments objPtr and endPtrPtr as well as the return code are the * outputs. * * When the parser cannot find any prefix of the string that matches a * format it is looking for, TCL_ERROR is returned and an error message * may be generated and returned as described above. The contents of * objPtr will not be changed. If endPtrPtr is non-NULL, a pointer to the * character in the string that terminated the scan will be written to * *endPtrPtr. * * When the parser determines that the entire string matches a format it * is looking for, TCL_OK is returned, and if objPtr is non-NULL, then * the internal rep and Tcl_ObjType of objPtr are set to the "canonical" * numeric value that matches the scanned string. If endPtrPtr is not * NULL, a pointer to the end of the string will be written to *endPtrPtr * (that is, either bytes+numBytes or a pointer to a terminating NUL * byte). * * When the parser determines that a partial string matches a format it * is looking for, the value of endPtrPtr determines what happens: * * - If endPtrPtr is NULL, then TCL_ERROR is returned, with error message * generation as above. * * - If endPtrPtr is non-NULL, then TCL_OK is returned and objPtr * internals are set as above. Also, a pointer to the first * character following the parsed numeric string is written to * *endPtrPtr. * * In some cases where the string being scanned is the string rep of * objPtr, this routine can leave objPtr in an inconsistent state where * its string rep and its internal rep do not agree. In these cases the * internal rep will be in agreement with only some substring of the * string rep. This might happen if the caller passes in a non-NULL bytes * value that points somewhere into the string rep. It might happen if * the caller passes in a numBytes value that limits the scan to only a * prefix of the string rep. Or it might happen if a non-NULL value of * endPtrPtr permits a TCL_OK return from only a partial string match. It * is the responsibility of the caller to detect and correct such * inconsistencies when they can and do arise. * * Results: * Returns a standard Tcl result. * * Side effects: * The string representaton of objPtr may be generated. * * The internal representation and Tcl_ObjType of objPtr may be changed. * This may involve allocation and/or freeing of memory. * *---------------------------------------------------------------------- */ int TclParseNumber( Tcl_Interp *interp, /* Used for error reporting. May be NULL. */ Tcl_Obj *objPtr, /* Object to receive the internal rep. */ const char *expected, /* Description of the type of number the * caller expects to be able to parse * ("integer", "boolean value", etc.). */ const char *bytes, /* Pointer to the start of the string to * scan. */ int numBytes, /* Maximum number of bytes to scan, see * above. */ const char **endPtrPtr, /* Place to store pointer to the character * that terminated the scan. */ int flags) /* Flags governing the parse. */ { enum State { INITIAL, SIGNUM, ZERO, ZERO_X, ZERO_O, ZERO_B, BINARY, HEXADECIMAL, OCTAL, BAD_OCTAL, DECIMAL, LEADING_RADIX_POINT, FRACTION, EXPONENT_START, EXPONENT_SIGNUM, EXPONENT, sI, sIN, sINF, sINFI, sINFIN, sINFINI, sINFINIT, sINFINITY #ifdef IEEE_FLOATING_POINT , sN, sNA, sNAN, sNANPAREN, sNANHEX, sNANFINISH #endif } state = INITIAL; enum State acceptState = INITIAL; int signum = 0; /* Sign of the number being parsed. */ Tcl_WideUInt significandWide = 0; /* Significand of the number being parsed (if * no overflow). */ mp_int significandBig; /* Significand of the number being parsed (if * it overflows significandWide). */ int significandOverflow = 0;/* Flag==1 iff significandBig is used. */ Tcl_WideUInt octalSignificandWide = 0; /* Significand of an octal number; needed * because we don't know whether a number with * a leading zero is octal or decimal until * we've scanned forward to a '.' or 'e'. */ mp_int octalSignificandBig; /* Significand of octal number once * octalSignificandWide overflows. */ int octalSignificandOverflow = 0; /* Flag==1 if octalSignificandBig is used. */ int numSigDigs = 0; /* Number of significant digits in the decimal * significand. */ int numTrailZeros = 0; /* Number of trailing zeroes at the current * point in the parse. */ int numDigitsAfterDp = 0; /* Number of digits scanned after the decimal * point. */ int exponentSignum = 0; /* Signum of the exponent of a floating point * number. */ long exponent = 0; /* Exponent of a floating point number. */ const char *p; /* Pointer to next character to scan. */ size_t len; /* Number of characters remaining after p. */ const char *acceptPoint; /* Pointer to position after last character in * an acceptable number. */ size_t acceptLen; /* Number of characters following that * point. */ int status = TCL_OK; /* Status to return to caller. */ char d = 0; /* Last hexadecimal digit scanned; initialized * to avoid a compiler warning. */ int shift = 0; /* Amount to shift when accumulating binary */ int explicitOctal = 0; #define ALL_BITS (~(Tcl_WideUInt)0) #define MOST_BITS (ALL_BITS >> 1) /* * Initialize bytes to start of the object's string rep if the caller * didn't pass anything else. */ if (bytes == NULL) { bytes = TclGetString(objPtr); } p = bytes; len = numBytes; acceptPoint = p; acceptLen = len; while (1) { char c = len ? *p : '\0'; switch (state) { case INITIAL: /* * Initial state. Acceptable characters are +, -, digits, period, * I, N, and whitespace. */ if (TclIsSpaceProc(c)) { if (flags & TCL_PARSE_NO_WHITESPACE) { goto endgame; } break; } else if (c == '+') { state = SIGNUM; break; } else if (c == '-') { signum = 1; state = SIGNUM; break; } /* FALLTHROUGH */ case SIGNUM: /* * Scanned a leading + or -. Acceptable characters are digits, * period, I, and N. */ if (c == '0') { if (flags & TCL_PARSE_DECIMAL_ONLY) { state = DECIMAL; } else { state = ZERO; } break; } else if (flags & TCL_PARSE_HEXADECIMAL_ONLY) { goto zerox; } else if (flags & TCL_PARSE_BINARY_ONLY) { goto zerob; } else if (flags & TCL_PARSE_OCTAL_ONLY) { goto zeroo; } else if (isdigit(UCHAR(c))) { significandWide = c - '0'; numSigDigs = 1; state = DECIMAL; break; } else if (flags & TCL_PARSE_INTEGER_ONLY) { goto endgame; } else if (c == '.') { state = LEADING_RADIX_POINT; break; } else if (c == 'I' || c == 'i') { state = sI; break; #ifdef IEEE_FLOATING_POINT } else if (c == 'N' || c == 'n') { state = sN; break; #endif } goto endgame; case ZERO: /* * Scanned a leading zero (perhaps with a + or -). Acceptable * inputs are digits, period, X, b, and E. If 8 or 9 is * encountered, the number can't be octal. This state and the * OCTAL state differ only in whether they recognize 'X' and 'b'. */ acceptState = state; acceptPoint = p; acceptLen = len; if (c == 'x' || c == 'X') { state = ZERO_X; break; } if (flags & TCL_PARSE_HEXADECIMAL_ONLY) { goto zerox; } if (flags & TCL_PARSE_SCAN_PREFIXES) { goto zeroo; } if (c == 'b' || c == 'B') { state = ZERO_B; break; } if (flags & TCL_PARSE_BINARY_ONLY) { goto zerob; } if (c == 'o' || c == 'O') { explicitOctal = 1; state = ZERO_O; break; } #ifdef KILL_OCTAL goto decimal; #endif /* FALLTHROUGH */ case OCTAL: /* * Scanned an optional + or -, followed by a string of octal * digits. Acceptable inputs are more digits, period, or E. If 8 * or 9 is encountered, commit to floating point. */ acceptState = state; acceptPoint = p; acceptLen = len; /* FALLTHROUGH */ case ZERO_O: zeroo: if (c == '0') { numTrailZeros++; state = OCTAL; break; } else if (c >= '1' && c <= '7') { if (objPtr != NULL) { shift = 3 * (numTrailZeros + 1); significandOverflow = AccumulateDecimalDigit( (unsigned)(c-'0'), numTrailZeros, &significandWide, &significandBig, significandOverflow); if (!octalSignificandOverflow) { /* * Shifting by more bits than are in the value being * shifted is at least de facto nonportable. Check for * too large shifts first. */ if ((octalSignificandWide != 0) && (((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt)) || (octalSignificandWide > (~(Tcl_WideUInt)0 >> shift)))) { octalSignificandOverflow = 1; TclBNInitBignumFromWideUInt(&octalSignificandBig, octalSignificandWide); } } if (!octalSignificandOverflow) { octalSignificandWide = (octalSignificandWide << shift) + (c - '0'); } else { mp_mul_2d(&octalSignificandBig, shift, &octalSignificandBig); mp_add_d(&octalSignificandBig, (mp_digit)(c - '0'), &octalSignificandBig); } } if (numSigDigs != 0) { numSigDigs += numTrailZeros+1; } else { numSigDigs = 1; } numTrailZeros = 0; state = OCTAL; break; } /* FALLTHROUGH */ case BAD_OCTAL: if (explicitOctal) { /* * No forgiveness for bad digits in explicitly octal numbers. */ goto endgame; } if (flags & TCL_PARSE_INTEGER_ONLY) { /* * No seeking floating point when parsing only integer. */ goto endgame; } #ifndef KILL_OCTAL /* * Scanned a number with a leading zero that contains an 8, 9, * radix point or E. This is an invalid octal number, but might * still be floating point. */ if (c == '0') { numTrailZeros++; state = BAD_OCTAL; break; } else if (isdigit(UCHAR(c))) { if (objPtr != NULL) { significandOverflow = AccumulateDecimalDigit( (unsigned)(c-'0'), numTrailZeros, &significandWide, &significandBig, significandOverflow); } if (numSigDigs != 0) { numSigDigs += (numTrailZeros + 1); } else { numSigDigs = 1; } numTrailZeros = 0; state = BAD_OCTAL; break; } else if (c == '.') { state = FRACTION; break; } else if (c == 'E' || c == 'e') { state = EXPONENT_START; break; } #endif goto endgame; /* * Scanned 0x. If state is HEXADECIMAL, scanned at least one * character following the 0x. The only acceptable inputs are * hexadecimal digits. */ case HEXADECIMAL: acceptState = state; acceptPoint = p; acceptLen = len; /* FALLTHROUGH */ case ZERO_X: zerox: if (c == '0') { numTrailZeros++; state = HEXADECIMAL; break; } else if (isdigit(UCHAR(c))) { d = (c-'0'); } else if (c >= 'A' && c <= 'F') { d = (c-'A'+10); } else if (c >= 'a' && c <= 'f') { d = (c-'a'+10); } else { goto endgame; } if (objPtr != NULL) { shift = 4 * (numTrailZeros + 1); if (!significandOverflow) { /* * Shifting by more bits than are in the value being * shifted is at least de facto nonportable. Check for too * large shifts first. */ if (significandWide != 0 && ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (~(Tcl_WideUInt)0 >> shift))) { significandOverflow = 1; TclBNInitBignumFromWideUInt(&significandBig, significandWide); } } if (!significandOverflow) { significandWide = (significandWide << shift) + d; } else { mp_mul_2d(&significandBig, shift, &significandBig); mp_add_d(&significandBig, (mp_digit) d, &significandBig); } } numTrailZeros = 0; state = HEXADECIMAL; break; case BINARY: acceptState = state; acceptPoint = p; acceptLen = len; case ZERO_B: zerob: if (c == '0') { numTrailZeros++; state = BINARY; break; } else if (c != '1') { goto endgame; } if (objPtr != NULL) { shift = numTrailZeros + 1; if (!significandOverflow) { /* * Shifting by more bits than are in the value being * shifted is at least de facto nonportable. Check for too * large shifts first. */ if (significandWide != 0 && ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (~(Tcl_WideUInt)0 >> shift))) { significandOverflow = 1; TclBNInitBignumFromWideUInt(&significandBig, significandWide); } } if (!significandOverflow) { significandWide = (significandWide << shift) + 1; } else { mp_mul_2d(&significandBig, shift, &significandBig); mp_add_d(&significandBig, (mp_digit) 1, &significandBig); } } numTrailZeros = 0; state = BINARY; break; case DECIMAL: /* * Scanned an optional + or - followed by a string of decimal * digits. */ #ifdef KILL_OCTAL decimal: #endif acceptState = state; acceptPoint = p; acceptLen = len; if (c == '0') { numTrailZeros++; state = DECIMAL; break; } else if (isdigit(UCHAR(c))) { if (objPtr != NULL) { significandOverflow = AccumulateDecimalDigit( (unsigned)(c - '0'), numTrailZeros, &significandWide, &significandBig, significandOverflow); } numSigDigs += numTrailZeros+1; numTrailZeros = 0; state = DECIMAL; break; } else if (flags & TCL_PARSE_INTEGER_ONLY) { goto endgame; } else if (c == '.') { state = FRACTION; break; } else if (c == 'E' || c == 'e') { state = EXPONENT_START; break; } goto endgame; /* * Found a decimal point. If no digits have yet been scanned, E is * not allowed; otherwise, it introduces the exponent. If at least * one digit has been found, we have a possible complete number. */ case FRACTION: acceptState = state; acceptPoint = p; acceptLen = len; if (c == 'E' || c=='e') { state = EXPONENT_START; break; } /* FALLTHROUGH */ case LEADING_RADIX_POINT: if (c == '0') { numDigitsAfterDp++; numTrailZeros++; state = FRACTION; break; } else if (isdigit(UCHAR(c))) { numDigitsAfterDp++; if (objPtr != NULL) { significandOverflow = AccumulateDecimalDigit( (unsigned)(c-'0'), numTrailZeros, &significandWide, &significandBig, significandOverflow); } if (numSigDigs != 0) { numSigDigs += numTrailZeros+1; } else { numSigDigs = 1; } numTrailZeros = 0; state = FRACTION; break; } goto endgame; case EXPONENT_START: /* * Scanned the E at the start of an exponent. Make sure a legal * character follows before using the C library strtol routine, * which allows whitespace. */ if (c == '+') { state = EXPONENT_SIGNUM; break; } else if (c == '-') { exponentSignum = 1; state = EXPONENT_SIGNUM; break; } /* FALLTHROUGH */ case EXPONENT_SIGNUM: /* * Found the E at the start of the exponent, followed by a sign * character. */ if (isdigit(UCHAR(c))) { exponent = c - '0'; state = EXPONENT; break; } goto endgame; case EXPONENT: /* * Found an exponent with at least one digit. Accumulate it, * making sure to hard-pin it to LONG_MAX on overflow. */ acceptState = state; acceptPoint = p; acceptLen = len; if (isdigit(UCHAR(c))) { if (exponent < (LONG_MAX - 9) / 10) { exponent = 10 * exponent + (c - '0'); } else { exponent = LONG_MAX; } state = EXPONENT; break; } goto endgame; /* * Parse out INFINITY by simply spelling it out. INF is accepted * as an abbreviation; other prefices are not. */ case sI: if (c == 'n' || c == 'N') { state = sIN; break; } goto endgame; case sIN: if (c == 'f' || c == 'F') { state = sINF; break; } goto endgame; case sINF: acceptState = state; acceptPoint = p; acceptLen = len; if (c == 'i' || c == 'I') { state = sINFI; break; } goto endgame; case sINFI: if (c == 'n' || c == 'N') { state = sINFIN; break; } goto endgame; case sINFIN: if (c == 'i' || c == 'I') { state = sINFINI; break; } goto endgame; case sINFINI: if (c == 't' || c == 'T') { state = sINFINIT; break; } goto endgame; case sINFINIT: if (c == 'y' || c == 'Y') { state = sINFINITY; break; } goto endgame; /* * Parse NaN's. */ #ifdef IEEE_FLOATING_POINT case sN: if (c == 'a' || c == 'A') { state = sNA; break; } goto endgame; case sNA: if (c == 'n' || c == 'N') { state = sNAN; break; } goto endgame; case sNAN: acceptState = state; acceptPoint = p; acceptLen = len; if (c == '(') { state = sNANPAREN; break; } goto endgame; /* * Parse NaN(hexdigits) */ case sNANHEX: if (c == ')') { state = sNANFINISH; break; } /* FALLTHROUGH */ case sNANPAREN: if (TclIsSpaceProc(c)) { break; } if (numSigDigs < 13) { if (c >= '0' && c <= '9') { d = c - '0'; } else if (c >= 'a' && c <= 'f') { d = 10 + c - 'a'; } else if (c >= 'A' && c <= 'F') { d = 10 + c - 'A'; } else { goto endgame; } numSigDigs++; significandWide = (significandWide << 4) + d; state = sNANHEX; break; } goto endgame; case sNANFINISH: #endif case sINFINITY: acceptState = state; acceptPoint = p; acceptLen = len; goto endgame; } p++; len--; } endgame: if (acceptState == INITIAL) { /* * No numeric string at all found. */ status = TCL_ERROR; if (endPtrPtr != NULL) { *endPtrPtr = p; } } else { /* * Back up to the last accepting state in the lexer. */ p = acceptPoint; len = acceptLen; if (!(flags & TCL_PARSE_NO_WHITESPACE)) { /* * Accept trailing whitespace. */ while (len != 0 && TclIsSpaceProc(*p)) { p++; len--; } } if (endPtrPtr == NULL) { if ((len != 0) && ((numBytes > 0) || (*p != '\0'))) { status = TCL_ERROR; } } else { *endPtrPtr = p; } } /* * Generate and store the appropriate internal rep. */ if (status == TCL_OK && objPtr != NULL) { TclFreeIntRep(objPtr); switch (acceptState) { case SIGNUM: case BAD_OCTAL: case ZERO_X: case ZERO_O: case ZERO_B: case LEADING_RADIX_POINT: case EXPONENT_START: case EXPONENT_SIGNUM: case sI: case sIN: case sINFI: case sINFIN: case sINFINI: case sINFINIT: #ifdef IEEE_FLOATING_POINT case sN: case sNA: case sNANPAREN: case sNANHEX: Tcl_Panic("TclParseNumber: bad acceptState %d parsing '%s'", acceptState, bytes); #endif case BINARY: shift = numTrailZeros; if (!significandOverflow && significandWide != 0 && ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; TclBNInitBignumFromWideUInt(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { significandWide <<= shift; } else { mp_mul_2d(&significandBig, shift, &significandBig); } } goto returnInteger; case HEXADECIMAL: /* * Returning a hex integer. Final scaling step. */ shift = 4 * numTrailZeros; if (!significandOverflow && significandWide !=0 && ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || significandWide > (MOST_BITS + signum) >> shift)) { significandOverflow = 1; TclBNInitBignumFromWideUInt(&significandBig, significandWide); } if (shift) { if (!significandOverflow) { significandWide <<= shift; } else { mp_mul_2d(&significandBig, shift, &significandBig); } } goto returnInteger; case OCTAL: /* * Returning an octal integer. Final scaling step. */ shift = 3 * numTrailZeros; if (!octalSignificandOverflow && octalSignificandWide != 0 && ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) || octalSignificandWide > (MOST_BITS + signum) >> shift)) { octalSignificandOverflow = 1; TclBNInitBignumFromWideUInt(&octalSignificandBig, octalSignificandWide); } if (shift) { if (!octalSignificandOverflow) { octalSignificandWide <<= shift; } else { mp_mul_2d(&octalSignificandBig, shift, &octalSignificandBig); } } if (!octalSignificandOverflow) { if (octalSignificandWide > (Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) { #ifndef TCL_WIDE_INT_IS_LONG if (octalSignificandWide <= (MOST_BITS + signum)) { objPtr->typePtr = &tclWideIntType; if (signum) { objPtr->internalRep.wideValue = - (Tcl_WideInt) octalSignificandWide; } else { objPtr->internalRep.wideValue = (Tcl_WideInt) octalSignificandWide; } break; } #endif TclBNInitBignumFromWideUInt(&octalSignificandBig, octalSignificandWide); octalSignificandOverflow = 1; } else { objPtr->typePtr = &tclIntType; if (signum) { objPtr->internalRep.longValue = - (long) octalSignificandWide; } else { objPtr->internalRep.longValue = (long) octalSignificandWide; } } } if (octalSignificandOverflow) { if (signum) { mp_neg(&octalSignificandBig, &octalSignificandBig); } TclSetBignumIntRep(objPtr, &octalSignificandBig); } break; case ZERO: case DECIMAL: significandOverflow = AccumulateDecimalDigit(0, numTrailZeros-1, &significandWide, &significandBig, significandOverflow); if (!significandOverflow && (significandWide > MOST_BITS+signum)){ significandOverflow = 1; TclBNInitBignumFromWideUInt(&significandBig, significandWide); } returnInteger: if (!significandOverflow) { if (significandWide > (Tcl_WideUInt)(((~(unsigned long)0) >> 1) + signum)) { #ifndef TCL_WIDE_INT_IS_LONG if (significandWide <= MOST_BITS+signum) { objPtr->typePtr = &tclWideIntType; if (signum) { objPtr->internalRep.wideValue = - (Tcl_WideInt) significandWide; } else { objPtr->internalRep.wideValue = (Tcl_WideInt) significandWide; } break; } #endif TclBNInitBignumFromWideUInt(&significandBig, significandWide); significandOverflow = 1; } else { objPtr->typePtr = &tclIntType; if (signum) { objPtr->internalRep.longValue = - (long) significandWide; } else { objPtr->internalRep.longValue = (long) significandWide; } } } if (significandOverflow) { if (signum) { mp_neg(&significandBig, &significandBig); } TclSetBignumIntRep(objPtr, &significandBig); } break; case FRACTION: case EXPONENT: /* * Here, we're parsing a floating-point number. 'significandWide' * or 'significandBig' contains the exact significand, according * to whether 'significandOverflow' is set. The desired floating * point value is significand * 10**k, where * k = numTrailZeros+exponent-numDigitsAfterDp. */ objPtr->typePtr = &tclDoubleType; if (exponentSignum) { exponent = -exponent; } if (!significandOverflow) { objPtr->internalRep.doubleValue = MakeLowPrecisionDouble( signum, significandWide, numSigDigs, numTrailZeros + exponent - numDigitsAfterDp); } else { objPtr->internalRep.doubleValue = MakeHighPrecisionDouble( signum, &significandBig, numSigDigs, numTrailZeros + exponent - numDigitsAfterDp); } break; case sINF: case sINFINITY: if (signum) { objPtr->internalRep.doubleValue = -HUGE_VAL; } else { objPtr->internalRep.doubleValue = HUGE_VAL; } objPtr->typePtr = &tclDoubleType; break; #ifdef IEEE_FLOATING_POINT case sNAN: case sNANFINISH: objPtr->internalRep.doubleValue = MakeNaN(signum,significandWide); objPtr->typePtr = &tclDoubleType; break; #endif case INITIAL: /* This case only to silence compiler warning. */ Tcl_Panic("TclParseNumber: state INITIAL can't happen here"); } } /* * Format an error message when an invalid number is encountered. */ if (status != TCL_OK) { if (interp != NULL) { Tcl_Obj *msg = Tcl_ObjPrintf("expected %s but got \"", expected); Tcl_AppendLimitedToObj(msg, bytes, numBytes, 50, ""); Tcl_AppendToObj(msg, "\"", -1); if (state == BAD_OCTAL) { Tcl_AppendToObj(msg, " (looks like invalid octal number)", -1); } Tcl_SetObjResult(interp, msg); Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL); } } /* * Free memory. */ if (octalSignificandOverflow) { mp_clear(&octalSignificandBig); } if (significandOverflow) { mp_clear(&significandBig); } return status; } /* *---------------------------------------------------------------------- * * AccumulateDecimalDigit -- * * Consume a decimal digit in a number being scanned. * * Results: * Returns 1 if the number has overflowed to a bignum, 0 if it still fits * in a wide integer. * * Side effects: * Updates either the wide or bignum representation. * *---------------------------------------------------------------------- */ static int AccumulateDecimalDigit( unsigned digit, /* Digit being scanned. */ int numZeros, /* Count of zero digits preceding the digit * being scanned. */ Tcl_WideUInt *wideRepPtr, /* Representation of the partial number as a * wide integer. */ mp_int *bignumRepPtr, /* Representation of the partial number as a * bignum. */ int bignumFlag) /* Flag == 1 if the number overflowed previous * to this digit. */ { int i, n; Tcl_WideUInt w; /* * Try wide multiplication first. */ if (!bignumFlag) { w = *wideRepPtr; if (w == 0) { /* * There's no need to multiply if the multiplicand is zero. */ *wideRepPtr = digit; return 0; } else if (numZeros >= maxpow10_wide || w > ((~(Tcl_WideUInt)0)-digit)/pow10_wide[numZeros+1]) { /* * Wide multiplication will overflow. Expand the number to a * bignum and fall through into the bignum case. */ TclBNInitBignumFromWideUInt(bignumRepPtr, w); } else { /* * Wide multiplication. */ *wideRepPtr = w * pow10_wide[numZeros+1] + digit; return 0; } } /* * Bignum multiplication. */ if (numZeros < log10_DIGIT_MAX) { /* * Up to about 8 zeros - single digit multiplication. */ mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[numZeros+1], bignumRepPtr); mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr); } else { /* * More than single digit multiplication. Multiply by the appropriate * small powers of 5, and then shift. Large strings of zeroes are * eaten 256 at a time; this is less efficient than it could be, but * seems implausible. We presume that DIGIT_BIT is at least 27. The * first multiplication, by up to 10**7, is done with a one-DIGIT * multiply (this presumes that DIGIT_BIT >= 24). */ n = numZeros + 1; mp_mul_d(bignumRepPtr, (mp_digit) pow10_wide[n&0x7], bignumRepPtr); for (i=3; i<=7; ++i) { if (n & (1 << i)) { mp_mul(bignumRepPtr, pow5+i, bignumRepPtr); } } while (n >= 256) { mp_mul(bignumRepPtr, pow5+8, bignumRepPtr); n -= 256; } mp_mul_2d(bignumRepPtr, (int)(numZeros+1)&~0x7, bignumRepPtr); mp_add_d(bignumRepPtr, (mp_digit) digit, bignumRepPtr); } return 1; } /* *---------------------------------------------------------------------- * * MakeLowPrecisionDouble -- * * Makes the double precision number, signum*significand*10**exponent. * * Results: * Returns the constructed number. * * Common cases, where there are few enough digits that the number can be * represented with at most roundoff, are handled specially here. If the * number requires more than one rounded operation to compute, the code * promotes the significand to a bignum and calls MakeHighPrecisionDouble * to do it instead. * *---------------------------------------------------------------------- */ static double MakeLowPrecisionDouble( int signum, /* 1 if the number is negative, 0 otherwise */ Tcl_WideUInt significand, /* Significand of the number. */ int numSigDigs, /* Number of digits in the significand. */ int exponent) /* Power of ten. */ { double retval; /* Value of the number. */ mp_int significandBig; /* Significand expressed as a bignum. */ /* * With gcc on x86, the floating point rounding mode is double-extended. * This causes the result of double-precision calculations to be rounded * twice: once to the precision of double-extended and then again to the * precision of double. Double-rounding introduces gratuitous errors of 1 * ulp, so we need to change rounding mode to 53-bits. */ TCL_IEEE_DOUBLE_ROUNDING; /* * Test for the easy cases. */ if (numSigDigs <= QUICK_MAX) { if (exponent >= 0) { if (exponent <= mmaxpow) { /* * The significand is an exact integer, and so is * 10**exponent. The product will be correct to within 1/2 ulp * without special handling. */ retval = (double) ((Tcl_WideInt)significand * pow10vals[exponent]); goto returnValue; } else { int diff = QUICK_MAX - numSigDigs; if (exponent-diff <= mmaxpow) { /* * 10**exponent is not an exact integer, but * 10**(exponent-diff) is exact, and so is * significand*10**diff, so we can still compute the value * with only one roundoff. */ volatile double factor = (double) ((Tcl_WideInt)significand * pow10vals[diff]); retval = factor * pow10vals[exponent-diff]; goto returnValue; } } } else { if (exponent >= -mmaxpow) { /* * 10**-exponent is an exact integer, and so is the * significand. Compute the result by one division, again with * only one rounding. */ retval = (double) ((Tcl_WideInt)significand / pow10vals[-exponent]); goto returnValue; } } } /* * All the easy cases have failed. Promote ths significand to bignum and * call MakeHighPrecisionDouble to do it the hard way. */ TclBNInitBignumFromWideUInt(&significandBig, significand); retval = MakeHighPrecisionDouble(0, &significandBig, numSigDigs, exponent); mp_clear(&significandBig); /* * Come here to return the computed value. */ returnValue: if (signum) { retval = -retval; } /* * On gcc on x86, restore the floating point mode word. */ TCL_DEFAULT_DOUBLE_ROUNDING; return retval; } /* *---------------------------------------------------------------------- * * MakeHighPrecisionDouble -- * * Makes the double precision number, signum*significand*10**exponent. * * Results: * Returns the constructed number. * * MakeHighPrecisionDouble is used when arbitrary-precision arithmetic is * needed to ensure correct rounding. It begins by calculating a * low-precision approximation to the desired number, and then refines * the answer in high precision. * *---------------------------------------------------------------------- */ static double MakeHighPrecisionDouble( int signum, /* 1=negative, 0=nonnegative. */ mp_int *significand, /* Exact significand of the number. */ int numSigDigs, /* Number of significant digits. */ int exponent) /* Power of 10 by which to multiply. */ { double retval; int machexp; /* Machine exponent of a power of 10. */ /* * With gcc on x86, the floating point rounding mode is double-extended. * This causes the result of double-precision calculations to be rounded * twice: once to the precision of double-extended and then again to the * precision of double. Double-rounding introduces gratuitous errors of 1 * ulp, so we need to change rounding mode to 53-bits. */ TCL_IEEE_DOUBLE_ROUNDING; /* * Quick checks for over/underflow. */ if (numSigDigs+exponent-1 > maxDigits) { retval = HUGE_VAL; goto returnValue; } if (numSigDigs+exponent-1 < minDigits) { retval = 0; goto returnValue; } /* * Develop a first approximation to the significand. It is tempting simply * to force bignum to double, but that will overflow on input numbers like * 1.[string repeat 0 1000]1; while this is a not terribly likely * scenario, we still have to deal with it. Use fraction and exponent * instead. Once we have the significand, multiply by 10**exponent. Test * for overflow. Convert back to a double, and test for underflow. */ retval = BignumToBiasedFrExp(significand, &machexp); retval = Pow10TimesFrExp(exponent, retval, &machexp); if (machexp > DBL_MAX_EXP*log2FLT_RADIX) { retval = HUGE_VAL; goto returnValue; } retval = SafeLdExp(retval, machexp); if (tiny == 0.0) { tiny = SafeLdExp(1.0, DBL_MIN_EXP * log2FLT_RADIX - mantBits); } if (retval < tiny) { retval = tiny; } /* * Refine the result twice. (The second refinement should be necessary * only if the best approximation is a power of 2 minus 1/2 ulp). */ retval = RefineApproximation(retval, significand, exponent); retval = RefineApproximation(retval, significand, exponent); /* * Come here to return the computed value. */ returnValue: if (signum) { retval = -retval; } /* * On gcc on x86, restore the floating point mode word. */ TCL_DEFAULT_DOUBLE_ROUNDING; return retval; } /* *---------------------------------------------------------------------- * * MakeNaN -- * * Makes a "Not a Number" given a set of bits to put in the tag bits * * Note that a signalling NaN is never returned. * *---------------------------------------------------------------------- */ #ifdef IEEE_FLOATING_POINT static double MakeNaN( int signum, /* Sign bit (1=negative, 0=nonnegative. */ Tcl_WideUInt tags) /* Tag bits to put in the NaN. */ { union { Tcl_WideUInt iv; double dv; } theNaN; theNaN.iv = tags; theNaN.iv &= (((Tcl_WideUInt) 1) << 51) - 1; if (signum) { theNaN.iv |= ((Tcl_WideUInt) (0x8000 | NAN_START)) << 48; } else { theNaN.iv |= ((Tcl_WideUInt) NAN_START) << 48; } if (n770_fp) { theNaN.iv = Nokia770Twiddle(theNaN.iv); } return theNaN.dv; } #endif /* *---------------------------------------------------------------------- * * RefineApproximation -- * * Given a poor approximation to a floating point number, returns a * better one. (The better approximation is correct to within 1 ulp, and * is entirely correct if the poor approximation is correct to 1 ulp.) * * Results: * Returns the improved result. * *---------------------------------------------------------------------- */ static double RefineApproximation( double approxResult, /* Approximate result of conversion. */ mp_int *exactSignificand, /* Integer significand. */ int exponent) /* Power of 10 to multiply by significand. */ { int M2, M5; /* Powers of 2 and of 5 needed to put the * decimal and binary numbers over a common * denominator. */ double significand; /* Sigificand of the binary number. */ int binExponent; /* Exponent of the binary number. */ int msb; /* Most significant bit position of an * intermediate result. */ int nDigits; /* Number of mp_digit's in an intermediate * result. */ mp_int twoMv; /* Approx binary value expressed as an exact * integer scaled by the multiplier 2M. */ mp_int twoMd; /* Exact decimal value expressed as an exact * integer scaled by the multiplier 2M. */ int scale; /* Scale factor for M. */ int multiplier; /* Power of two to scale M. */ double num, den; /* Numerator and denominator of the correction * term. */ double quot; /* Correction term. */ double minincr; /* Lower bound on the absolute value of the * correction term. */ int roundToEven = 0; /* Flag == TRUE if we need to invoke * "round to even" functionality */ double rteSignificand; /* Significand of the round-to-even result */ int rteExponent; /* Exponent of the round-to-even result */ Tcl_WideInt rteSigWide; /* Wide integer version of the significand * for testing evenness */ int i; /* * The first approximation is always low. If we find that it's HUGE_VAL, * we're done. */ if (approxResult == HUGE_VAL) { return approxResult; } /* * Find a common denominator for the decimal and binary fractions. The * common denominator will be 2**M2 + 5**M5. */ significand = frexp(approxResult, &binExponent); i = mantBits - binExponent; if (i < 0) { M2 = 0; } else { M2 = i; } if (exponent > 0) { M5 = 0; } else { M5 = -exponent; if (M5 - 1 > M2) { M2 = M5 - 1; } } /* * The floating point number is significand*2**binExponent. Compute the * large integer significand*2**(binExponent+M2+1). The 2**-1 bit of the * significand (the most significant) corresponds to the * 2**(binExponent+M2 + 1) bit of 2*M2*v. Allocate enough digits to hold * that quantity, then convert the significand to a large integer, scaled * appropriately. Then multiply by the appropriate power of 5. */ msb = binExponent + M2; /* 1008 */ nDigits = msb / DIGIT_BIT + 1; mp_init_size(&twoMv, nDigits); i = (msb % DIGIT_BIT + 1); twoMv.used = nDigits; significand *= SafeLdExp(1.0, i); while (--nDigits >= 0) { twoMv.dp[nDigits] = (mp_digit) significand; significand -= (mp_digit) significand; significand = SafeLdExp(significand, DIGIT_BIT); } for (i = 0; i <= 8; ++i) { if (M5 & (1 << i)) { mp_mul(&twoMv, pow5+i, &twoMv); } } /* * Collect the decimal significand as a high precision integer. The least * significant bit corresponds to bit M2+exponent+1 so it will need to be * shifted left by that many bits after being multiplied by * 5**(M5+exponent). */ mp_init_copy(&twoMd, exactSignificand); for (i=0; i<=8; ++i) { if ((M5 + exponent) & (1 << i)) { mp_mul(&twoMd, pow5+i, &twoMd); } } mp_mul_2d(&twoMd, M2+exponent+1, &twoMd); mp_sub(&twoMd, &twoMv, &twoMd); /* * The result, 2Mv-2Md, needs to be divided by 2M to yield a correction * term. Because 2M may well overflow a double, we need to scale the * denominator by a factor of 2**binExponent-mantBits. */ scale = binExponent - mantBits - 1; mp_set(&twoMv, 1); for (i=0; i<=8; ++i) { if (M5 & (1 << i)) { mp_mul(&twoMv, pow5+i, &twoMv); } } multiplier = M2 + scale + 1; if (multiplier > 0) { mp_mul_2d(&twoMv, multiplier, &twoMv); } else if (multiplier < 0) { mp_div_2d(&twoMv, -multiplier, &twoMv, NULL); } switch (mp_cmp_mag(&twoMd, &twoMv)) { case MP_LT: /* * If the result is less than unity, the error is less than 1/2 unit in * the last place, so there's no correction to make. */ mp_clear(&twoMd); mp_clear(&twoMv); return approxResult; case MP_EQ: /* * If the result is exactly unity, we need to round to even. */ roundToEven = 1; break; case MP_GT: break; } if (roundToEven) { rteSignificand = frexp(approxResult, &rteExponent); rteSigWide = (Tcl_WideInt) ldexp(rteSignificand, FP_PRECISION); if ((rteSigWide & 1) == 0) { mp_clear(&twoMd); mp_clear(&twoMv); return approxResult; } } /* * Convert the numerator and denominator of the corrector term accurately * to floating point numbers. */ num = TclBignumToDouble(&twoMd); den = TclBignumToDouble(&twoMv); quot = SafeLdExp(num/den, scale); minincr = SafeLdExp(1.0, binExponent-mantBits); if (quot<0. && quot>-minincr) { quot = -minincr; } else if (quot>0. && quot>= 1; ++r; } if (p != result) { mp_copy(p, result); } } /* *---------------------------------------------------------------------- * * NormalizeRightward -- * * Shifts a number rightward until it is odd (that is, until the least * significant bit is nonzero. * * Results: * Returns the number of bit positions by which the number was shifted. * * Side effects: * Shifts the number in place; *wPtr is replaced by the shifted number. * *---------------------------------------------------------------------- */ inline static int NormalizeRightward( Tcl_WideUInt *wPtr) /* INOUT: Number to shift. */ { int rv = 0; Tcl_WideUInt w = *wPtr; if (!(w & (Tcl_WideUInt) 0xffffffff)) { w >>= 32; rv += 32; } if (!(w & (Tcl_WideUInt) 0xffff)) { w >>= 16; rv += 16; } if (!(w & (Tcl_WideUInt) 0xff)) { w >>= 8; rv += 8; } if (!(w & (Tcl_WideUInt) 0xf)) { w >>= 4; rv += 4; } if (!(w & 0x3)) { w >>= 2; rv += 2; } if (!(w & 0x1)) { w >>= 1; ++rv; } *wPtr = w; return rv; } /* *---------------------------------------------------------------------- * * RequiredPrecision -- * * Determines the number of bits needed to hold an intger. * * Results: * Returns the position of the most significant bit (0 - 63). Returns 0 * if the number is zero. * *---------------------------------------------------------------------- */ static int RequiredPrecision( Tcl_WideUInt w) /* Number to interrogate. */ { int rv; unsigned long wi; if (w & ((Tcl_WideUInt) 0xffffffff << 32)) { wi = (unsigned long) (w >> 32); rv = 32; } else { wi = (unsigned long) w; rv = 0; } if (wi & 0xffff0000) { wi >>= 16; rv += 16; } if (wi & 0xff00) { wi >>= 8; rv += 8; } if (wi & 0xf0) { wi >>= 4; rv += 4; } if (wi & 0xc) { wi >>= 2; rv += 2; } if (wi & 0x2) { wi >>= 1; ++rv; } if (wi & 0x1) { ++rv; } return rv; } /* *---------------------------------------------------------------------- * * DoubleToExpAndSig -- * * Separates a 'double' into exponent and significand. * * Side effects: * Stores the significand in '*significand' and the exponent in '*expon' * so that dv == significand * 2.0**expon, and significand is odd. Also * stores the position of the leftmost 1-bit in 'significand' in 'bits'. * *---------------------------------------------------------------------- */ inline static void DoubleToExpAndSig( double dv, /* Number to convert. */ Tcl_WideUInt *significand, /* OUTPUT: Significand of the number. */ int *expon, /* OUTPUT: Exponent to multiply the number * by. */ int *bits) /* OUTPUT: Number of significant bits. */ { Double d; /* Number being converted. */ Tcl_WideUInt z; /* Significand under construction. */ int de; /* Exponent of the number. */ int k; /* Bit count. */ d.d = dv; /* * Extract exponent and significand. */ de = (d.w.word0 & EXP_MASK) >> EXP_SHIFT; z = d.q & SIG_MASK; if (de != 0) { z |= HIDDEN_BIT; k = NormalizeRightward(&z); *bits = FP_PRECISION - k; *expon = k + (de - EXPONENT_BIAS) - (FP_PRECISION-1); } else { k = NormalizeRightward(&z); *expon = k + (de - EXPONENT_BIAS) - (FP_PRECISION-1) + 1; *bits = RequiredPrecision(z); } *significand = z; } /* *---------------------------------------------------------------------- * * TakeAbsoluteValue -- * * Takes the absolute value of a 'double' including 0, Inf and NaN * * Side effects: * The 'double' in *d is replaced with its absolute value. The signum is * stored in 'sign': 1 for negative, 0 for nonnegative. * *---------------------------------------------------------------------- */ inline static void TakeAbsoluteValue( Double *d, /* Number to replace with absolute value. */ int *sign) /* Place to put the signum. */ { if (d->w.word0 & SIGN_BIT) { *sign = 1; d->w.word0 &= ~SIGN_BIT; } else { *sign = 0; } } /* *---------------------------------------------------------------------- * * FormatInfAndNaN -- * * Bailout for formatting infinities and Not-A-Number. * * Results: * Returns one of the strings 'Infinity' and 'NaN'. The string returned * must be freed by the caller using 'ckfree'. * * Side effects: * Stores 9999 in *decpt, and sets '*endPtr' to designate the terminating * NUL byte of the string if 'endPtr' is not NULL. * *---------------------------------------------------------------------- */ inline static char * FormatInfAndNaN( Double *d, /* Exceptional number to format. */ int *decpt, /* Decimal point to set to a bogus value. */ char **endPtr) /* Pointer to the end of the formatted data */ { char *retval; *decpt = 9999; if (!(d->w.word1) && !(d->w.word0 & HI_ORDER_SIG_MASK)) { retval = ckalloc(9); strcpy(retval, "Infinity"); if (endPtr) { *endPtr = retval + 8; } } else { retval = ckalloc(4); strcpy(retval, "NaN"); if (endPtr) { *endPtr = retval + 3; } } return retval; } /* *---------------------------------------------------------------------- * * FormatZero -- * * Bailout to format a zero floating-point number. * * Results: * Returns the constant string "0" * * Side effects: * Stores 1 in '*decpt' and puts a pointer to the NUL byte terminating * the string in '*endPtr' if 'endPtr' is not NULL. * *---------------------------------------------------------------------- */ inline static char * FormatZero( int *decpt, /* Location of the decimal point. */ char **endPtr) /* Pointer to the end of the formatted data */ { char *retval = ckalloc(2); strcpy(retval, "0"); if (endPtr) { *endPtr = retval+1; } *decpt = 0; return retval; } /* *---------------------------------------------------------------------- * * ApproximateLog10 -- * * Computes a two-term Taylor series approximation to the common log of a * number, and computes the number's binary log. * * Results: * Return an approximation to floor(log10(bw*2**be)) that is either exact * or 1 too high. * *---------------------------------------------------------------------- */ inline static int ApproximateLog10( Tcl_WideUInt bw, /* Integer significand of the number. */ int be, /* Power of two to scale bw. */ int bbits) /* Number of bits of precision in bw. */ { int i; /* Log base 2 of the number. */ int k; /* Floor(Log base 10 of the number) */ double ds; /* Mantissa of the number. */ Double d2; /* * Compute i and d2 such that d = d2*2**i, and 1 < d2 < 2. * Compute an approximation to log10(d), * log10(d) ~ log10(2) * i + log10(1.5) * + (significand-1.5)/(1.5 * log(10)) */ d2.q = bw << (FP_PRECISION - bbits) & SIG_MASK; d2.w.word0 |= (EXPONENT_BIAS) << EXP_SHIFT; i = be + bbits - 1; ds = (d2.d - 1.5) * TWO_OVER_3LOG10 + LOG10_3HALVES_PLUS_FUDGE + LOG10_2 * i; k = (int) ds; if (k > ds) { --k; } return k; } /* *---------------------------------------------------------------------- * * BetterLog10 -- * * Improves the result of ApproximateLog10 for numbers in the range * 1 .. 10**(TEN_PMAX)-1 * * Side effects: * Sets k_check to 0 if the new result is known to be exact, and to 1 if * it may still be one too high. * * Results: * Returns the improved approximation to log10(d). * *---------------------------------------------------------------------- */ inline static int BetterLog10( double d, /* Original number to format. */ int k, /* Characteristic(Log base 10) of the * number. */ int *k_check) /* Flag == 1 if k is inexact. */ { /* * Performance hack. If k is in the range 0..TEN_PMAX, then we can use a * powers-of-ten table to check it. */ if (k >= 0 && k <= TEN_PMAX) { if (d < tens[k]) { k--; } *k_check = 0; } else { *k_check = 1; } return k; } /* *---------------------------------------------------------------------- * * ComputeScale -- * * Prepares to format a floating-point number as decimal. * * Parameters: * floor(log10*x) is k (or possibly k-1). floor(log2(x) is i. The * significand of x requires bbits bits to represent. * * Results: * Determines integers b2, b5, s2, s5 so that sig*2**b2*5**b5/2**s2*2**s5 * exactly represents the value of the x/10**k. This value will lie in * the range [1 .. 10), and allows for computing successive digits by * multiplying sig%10 by 10. * *---------------------------------------------------------------------- */ inline static void ComputeScale( int be, /* Exponent part of number: d = bw * 2**be. */ int k, /* Characteristic of log10(number). */ int *b2, /* OUTPUT: Power of 2 in the numerator. */ int *b5, /* OUTPUT: Power of 5 in the numerator. */ int *s2, /* OUTPUT: Power of 2 in the denominator. */ int *s5) /* OUTPUT: Power of 5 in the denominator. */ { /* * Scale numerator and denominator powers of 2 so that the input binary * number is the ratio of integers. */ if (be <= 0) { *b2 = 0; *s2 = -be; } else { *b2 = be; *s2 = 0; } /* * Scale numerator and denominator so that the output decimal number is * the ratio of integers. */ if (k >= 0) { *b5 = 0; *s5 = k; *s2 += k; } else { *b2 -= k; *b5 = -k; *s5 = 0; } } /* *---------------------------------------------------------------------- * * SetPrecisionLimits -- * * Determines how many digits of significance should be computed (and, * hence, how much memory need be allocated) for formatting a floating * point number. * * Given that 'k' is floor(log10(x)): * if 'shortest' format is used, there will be at most 18 digits in the * result. * if 'F' format is used, there will be at most 'ndigits' + k + 1 digits * if 'E' format is used, there will be exactly 'ndigits' digits. * * Side effects: * Adjusts '*ndigitsPtr' to have a valid value. Stores the maximum memory * allocation needed in *iPtr. Sets '*iLimPtr' to the limiting number of * digits to convert if k has been guessed correctly, and '*iLim1Ptr' to * the limiting number of digits to convert if k has been guessed to be * one too high. * *---------------------------------------------------------------------- */ inline static void SetPrecisionLimits( int convType, /* Type of conversion: TCL_DD_SHORTEST, * TCL_DD_STEELE0, TCL_DD_E_FMT, * TCL_DD_F_FMT. */ int k, /* Floor(log10(number to convert)) */ int *ndigitsPtr, /* IN/OUT: Number of digits requested (will be * adjusted if needed). */ int *iPtr, /* OUT: Maximum number of digits to return. */ int *iLimPtr, /* OUT: Number of digits of significance if * the bignum method is used.*/ int *iLim1Ptr) /* OUT: Number of digits of significance if * the quick method is used. */ { switch (convType) { case TCL_DD_SHORTEST0: case TCL_DD_STEELE0: *iLimPtr = *iLim1Ptr = -1; *iPtr = 18; *ndigitsPtr = 0; break; case TCL_DD_E_FORMAT: if (*ndigitsPtr <= 0) { *ndigitsPtr = 1; } *iLimPtr = *iLim1Ptr = *iPtr = *ndigitsPtr; break; case TCL_DD_F_FORMAT: *iPtr = *ndigitsPtr + k + 1; *iLimPtr = *iPtr; *iLim1Ptr = *iPtr - 1; if (*iPtr <= 0) { *iPtr = 1; } break; default: *iPtr = -1; *iLimPtr = -1; *iLim1Ptr = -1; Tcl_Panic("impossible conversion type in TclDoubleDigits"); } } /* *---------------------------------------------------------------------- * * BumpUp -- * * Increases a string of digits ending in a series of nines to designate * the next higher number. xxxxb9999... -> xxxx(b+1)0000... * * Results: * Returns a pointer to the end of the adjusted string. * * Side effects: * In the case that the string consists solely of '999999', sets it to * "1" and moves the decimal point (*kPtr) one place to the right. * *---------------------------------------------------------------------- */ inline static char * BumpUp( char *s, /* Cursor pointing one past the end of the * string. */ char *retval, /* Start of the string of digits. */ int *kPtr) /* Position of the decimal point. */ { while (*--s == '9') { if (s == retval) { ++(*kPtr); *s = '1'; return s+1; } } ++*s; ++s; return s; } /* *---------------------------------------------------------------------- * * AdjustRange -- * * Rescales a 'double' in preparation for formatting it using the 'quick' * double-to-string method. * * Results: * Returns the precision that has been lost in the prescaling as a count * of units in the least significant place. * *---------------------------------------------------------------------- */ inline static int AdjustRange( double *dPtr, /* INOUT: Number to adjust. */ int k) /* IN: floor(log10(d)) */ { int ieps; /* Number of roundoff errors that have * accumulated. */ double d = *dPtr; /* Number to adjust. */ double ds; int i, j, j1; ieps = 2; if (k > 0) { /* * The number must be reduced to bring it into range. */ ds = tens[k & 0xf]; j = k >> 4; if (j & BLETCH) { j &= (BLETCH-1); d /= bigtens[N_BIGTENS - 1]; ieps++; } i = 0; for (; j != 0; j>>=1) { if (j & 1) { ds *= bigtens[i]; ++ieps; } ++i; } d /= ds; } else if ((j1 = -k) != 0) { /* * The number must be increased to bring it into range. */ d *= tens[j1 & 0xf]; i = 0; for (j = j1>>4; j; j>>=1) { if (j & 1) { ieps++; d *= bigtens[i]; } ++i; } } *dPtr = d; return ieps; } /* *---------------------------------------------------------------------- * * ShorteningQuickFormat -- * * Returns a 'quick' format of a double precision number to a string of * digits, preferring a shorter string of digits if the shorter string is * still within 1/2 ulp of the number. * * Results: * Returns the string of digits. Returns NULL if the 'quick' method fails * and the bignum method must be used. * * Side effects: * Stores the position of the decimal point at '*kPtr'. * *---------------------------------------------------------------------- */ inline static char * ShorteningQuickFormat( double d, /* Number to convert. */ int k, /* floor(log10(d)) */ int ilim, /* Number of significant digits to return. */ double eps, /* Estimated roundoff error. */ char *retval, /* Buffer to receive the digit string. */ int *kPtr) /* Pointer to stash the position of the * decimal point. */ { char *s = retval; /* Cursor in the return value. */ int digit; /* Current digit. */ int i; eps = 0.5 / tens[ilim-1] - eps; i = 0; for (;;) { /* * Convert a digit. */ digit = (int) d; d -= digit; *s++ = '0' + digit; /* * Truncate the conversion if the string of digits is within 1/2 ulp * of the actual value. */ if (d < eps) { *kPtr = k; return s; } if ((1. - d) < eps) { *kPtr = k; return BumpUp(s, retval, kPtr); } /* * Bail out if the conversion fails to converge to a sufficiently * precise value. */ if (++i >= ilim) { return NULL; } /* * Bring the next digit to the integer part. */ eps *= 10; d *= 10.0; } } /* *---------------------------------------------------------------------- * * StrictQuickFormat -- * * Convert a double precision number of a string of a precise number of * digits, using the 'quick' double precision method. * * Results: * Returns the digit string, or NULL if the bignum method must be used to * do the formatting. * * Side effects: * Stores the position of the decimal point in '*kPtr'. * *---------------------------------------------------------------------- */ inline static char * StrictQuickFormat( double d, /* Number to convert. */ int k, /* floor(log10(d)) */ int ilim, /* Number of significant digits to return. */ double eps, /* Estimated roundoff error. */ char *retval, /* Start of the digit string. */ int *kPtr) /* Pointer to stash the position of the * decimal point. */ { char *s = retval; /* Cursor in the return value. */ int digit; /* Current digit of the answer. */ int i; eps *= tens[ilim-1]; i = 1; for (;;) { /* * Extract a digit. */ digit = (int) d; d -= digit; if (d == 0.0) { ilim = i; } *s++ = '0' + digit; /* * When the given digit count is reached, handle trailing strings of 0 * and 9. */ if (i == ilim) { if (d > 0.5 + eps) { *kPtr = k; return BumpUp(s, retval, kPtr); } else if (d < 0.5 - eps) { while (*--s == '0') { /* do nothing */ } s++; *kPtr = k; return s; } else { return NULL; } } /* * Advance to the next digit. */ ++i; d *= 10.0; } } /* *---------------------------------------------------------------------- * * QuickConversion -- * * Converts a floating point number the 'quick' way, when only a limited * number of digits is required and floating point arithmetic can * therefore be used for the intermediate results. * * Results: * Returns the converted string, or NULL if the bignum method must be * used. * *---------------------------------------------------------------------- */ inline static char * QuickConversion( double e, /* Number to format. */ int k, /* floor(log10(d)), approximately. */ int k_check, /* 0 if k is exact, 1 if it may be too high */ int flags, /* Flags passed to dtoa: * TCL_DD_SHORTEN_FLAG */ int len, /* Length of the return value. */ int ilim, /* Number of digits to store. */ int ilim1, /* Number of digits to store if we misguessed * k. */ int *decpt, /* OUTPUT: Location of the decimal point. */ char **endPtr) /* OUTPUT: Pointer to the terminal null * byte. */ { int ieps; /* Number of 1-ulp roundoff errors that have * accumulated in the calculation. */ Double eps; /* Estimated roundoff error. */ char *retval; /* Returned string. */ char *end; /* Pointer to the terminal null byte in the * returned string. */ volatile double d; /* Workaround for a bug in mingw gcc 3.4.5 */ /* * Bring d into the range [1 .. 10). */ ieps = AdjustRange(&e, k); d = e; /* * If the guessed value of k didn't get d into range, adjust it by one. If * that leaves us outside the range in which quick format is accurate, * bail out. */ if (k_check && d < 1. && ilim > 0) { if (ilim1 < 0) { return NULL; } ilim = ilim1; --k; d *= 10.0; ++ieps; } /* * Compute estimated roundoff error. */ eps.d = ieps * d + 7.; eps.w.word0 -= (FP_PRECISION-1) << EXP_SHIFT; /* * Handle the peculiar case where the result has no significant digits. */ retval = ckalloc(len + 1); if (ilim == 0) { d -= 5.; if (d > eps.d) { *retval = '1'; *decpt = k; return retval; } else if (d < -eps.d) { *decpt = k; return retval; } else { ckfree(retval); return NULL; } } /* * Format the digit string. */ if (flags & TCL_DD_SHORTEN_FLAG) { end = ShorteningQuickFormat(d, k, ilim, eps.d, retval, decpt); } else { end = StrictQuickFormat(d, k, ilim, eps.d, retval, decpt); } if (end == NULL) { ckfree(retval); return NULL; } *end = '\0'; if (endPtr != NULL) { *endPtr = end; } return retval; } /* *---------------------------------------------------------------------- * * CastOutPowersOf2 -- * * Adjust the factors 'b2', 'm2', and 's2' to cast out common powers of 2 * from numerator and denominator in preparation for the 'bignum' method * of floating point conversion. * *---------------------------------------------------------------------- */ inline static void CastOutPowersOf2( int *b2, /* Power of 2 to multiply the significand. */ int *m2, /* Power of 2 to multiply 1/2 ulp. */ int *s2) /* Power of 2 to multiply the common * denominator. */ { int i; if (*m2 > 0 && *s2 > 0) { /* Find the smallest power of 2 in the * numerator. */ if (*m2 < *s2) { /* Find the lowest common denominator. */ i = *m2; } else { i = *s2; } *b2 -= i; /* Reduce to lowest terms. */ *m2 -= i; *s2 -= i; } } /* *---------------------------------------------------------------------- * * ShorteningInt64Conversion -- * * Converts a double-precision number to the shortest string of digits * that reconverts exactly to the given number, or to 'ilim' digits if * that will yield a shorter result. The numerator and denominator in * David Gay's conversion algorithm are known to fit in Tcl_WideUInt, * giving considerably faster arithmetic than mp_int's. * * Results: * Returns the string of significant decimal digits, in newly allocated * memory * * Side effects: * Stores the location of the decimal point in '*decpt' and the location * of the terminal null byte in '*endPtr'. * *---------------------------------------------------------------------- */ inline static char * ShorteningInt64Conversion( Double *dPtr, /* Original number to convert. */ int convType, /* Type of conversion (shortest, Steele, * E format, F format). */ Tcl_WideUInt bw, /* Integer significand. */ int b2, int b5, /* Scale factor for the significand in the * numerator. */ int m2plus, int m2minus, int m5, /* Scale factors for 1/2 ulp in the numerator * (will be different if bw == 1. */ int s2, int s5, /* Scale factors for the denominator. */ int k, /* Number of output digits before the decimal * point. */ int len, /* Number of digits to allocate. */ int ilim, /* Number of digits to convert if b >= s */ int ilim1, /* Number of digits to convert if b < s */ int *decpt, /* OUTPUT: Position of the decimal point. */ char **endPtr) /* OUTPUT: Position of the terminal '\0' at * the end of the returned string. */ { char *retval = ckalloc(len + 1); /* Output buffer. */ Tcl_WideUInt b = (bw * wuipow5[b5]) << b2; /* Numerator of the fraction being * converted. */ Tcl_WideUInt S = wuipow5[s5] << s2; /* Denominator of the fraction being * converted. */ Tcl_WideUInt mplus, mminus; /* Ranges for testing whether the result is * within roundoff of being exact. */ int digit; /* Current output digit. */ char *s = retval; /* Cursor in the output buffer. */ int i; /* Current position in the output buffer. */ /* * Adjust if the logarithm was guessed wrong. */ if (b < S) { b = 10 * b; ++m2plus; ++m2minus; ++m5; ilim = ilim1; --k; } /* * Compute roundoff ranges. */ mplus = wuipow5[m5] << m2plus; mminus = wuipow5[m5] << m2minus; /* * Loop through the digits. */ i = 1; for (;;) { digit = (int)(b / S); if (digit > 10) { Tcl_Panic("wrong digit!"); } b = b % S; /* * Does the current digit put us on the low side of the exact value * but within within roundoff of being exact? */ if (b < mplus || (b == mplus && convType != TCL_DD_STEELE0 && (dPtr->w.word1 & 1) == 0)) { /* * Make sure we shouldn't be rounding *up* instead, in case the * next number above is closer. */ if (2 * b > S || (2 * b == S && (digit & 1) != 0)) { ++digit; if (digit == 10) { *s++ = '9'; s = BumpUp(s, retval, &k); break; } } /* * Stash the current digit. */ *s++ = '0' + digit; break; } /* * Does one plus the current digit put us within roundoff of the * number? */ if (b > S - mminus || (b == S - mminus && convType != TCL_DD_STEELE0 && (dPtr->w.word1 & 1) == 0)) { if (digit == 9) { *s++ = '9'; s = BumpUp(s, retval, &k); break; } ++digit; *s++ = '0' + digit; break; } /* * Have we converted all the requested digits? */ *s++ = '0' + digit; if (i == ilim) { if (2*b > S || (2*b == S && (digit & 1) != 0)) { s = BumpUp(s, retval, &k); } break; } /* * Advance to the next digit. */ b = 10 * b; mplus = 10 * mplus; mminus = 10 * mminus; ++i; } /* * Endgame - store the location of the decimal point and the end of the * string. */ *s = '\0'; *decpt = k; if (endPtr) { *endPtr = s; } return retval; } /* *---------------------------------------------------------------------- * * StrictInt64Conversion -- * * Converts a double-precision number to a fixed-length string of 'ilim' * digits that reconverts exactly to the given number. ('ilim' should be * replaced with 'ilim1' in the case where log10(d) has been * overestimated). The numerator and denominator in David Gay's * conversion algorithm are known to fit in Tcl_WideUInt, giving * considerably faster arithmetic than mp_int's. * * Results: * Returns the string of significant decimal digits, in newly allocated * memory * * Side effects: * Stores the location of the decimal point in '*decpt' and the location * of the terminal null byte in '*endPtr'. * *---------------------------------------------------------------------- */ inline static char * StrictInt64Conversion( Double *dPtr, /* Original number to convert. */ int convType, /* Type of conversion (shortest, Steele, * E format, F format). */ Tcl_WideUInt bw, /* Integer significand. */ int b2, int b5, /* Scale factor for the significand in the * numerator. */ int s2, int s5, /* Scale factors for the denominator. */ int k, /* Number of output digits before the decimal * point. */ int len, /* Number of digits to allocate. */ int ilim, /* Number of digits to convert if b >= s */ int ilim1, /* Number of digits to convert if b < s */ int *decpt, /* OUTPUT: Position of the decimal point. */ char **endPtr) /* OUTPUT: Position of the terminal '\0' at * the end of the returned string. */ { char *retval = ckalloc(len + 1); /* Output buffer. */ Tcl_WideUInt b = (bw * wuipow5[b5]) << b2; /* Numerator of the fraction being * converted. */ Tcl_WideUInt S = wuipow5[s5] << s2; /* Denominator of the fraction being * converted. */ int digit; /* Current output digit. */ char *s = retval; /* Cursor in the output buffer. */ int i; /* Current position in the output buffer. */ /* * Adjust if the logarithm was guessed wrong. */ if (b < S) { b = 10 * b; ilim = ilim1; --k; } /* * Loop through the digits. */ i = 1; for (;;) { digit = (int)(b / S); if (digit > 10) { Tcl_Panic("wrong digit!"); } b = b % S; /* * Have we converted all the requested digits? */ *s++ = '0' + digit; if (i == ilim) { if (2*b > S || (2*b == S && (digit & 1) != 0)) { s = BumpUp(s, retval, &k); } else { while (*--s == '0') { /* do nothing */ } ++s; } break; } /* * Advance to the next digit. */ b = 10 * b; ++i; } /* * Endgame - store the location of the decimal point and the end of the * string. */ *s = '\0'; *decpt = k; if (endPtr) { *endPtr = s; } return retval; } /* *---------------------------------------------------------------------- * * ShouldBankerRoundUpPowD -- * * Test whether bankers' rounding should round a digit up. Assumption is * made that the denominator of the fraction being tested is a power of * 2**DIGIT_BIT. * * Results: * Returns 1 iff the fraction is more than 1/2, or if the fraction is * exactly 1/2 and the digit is odd. * *---------------------------------------------------------------------- */ inline static int ShouldBankerRoundUpPowD( mp_int *b, /* Numerator of the fraction. */ int sd, /* Denominator is 2**(sd*DIGIT_BIT). */ int isodd) /* 1 if the digit is odd, 0 if even. */ { int i; static const mp_digit topbit = 1 << (DIGIT_BIT - 1); if (b->used < sd || (b->dp[sd-1] & topbit) == 0) { return 0; } if (b->dp[sd-1] != topbit) { return 1; } for (i = sd-2; i >= 0; --i) { if (b->dp[i] != 0) { return 1; } } return isodd; } /* *---------------------------------------------------------------------- * * ShouldBankerRoundUpToNextPowD -- * * Tests whether bankers' rounding will round down in the "denominator is * a power of 2**MP_DIGIT" case. * * Results: * Returns 1 if the rounding will be performed - which increases the * digit by one - and 0 otherwise. * *---------------------------------------------------------------------- */ inline static int ShouldBankerRoundUpToNextPowD( mp_int *b, /* Numerator of the fraction. */ mp_int *m, /* Numerator of the rounding tolerance. */ int sd, /* Common denominator is 2**(sd*DIGIT_BIT). */ int convType, /* Conversion type: STEELE defeats * round-to-even (not sure why one wants to do * this; I copied it from Gay). FIXME */ int isodd, /* 1 if the integer significand is odd. */ mp_int *temp) /* Work area for the calculation. */ { int i; /* * Compare B and S-m - which is the same as comparing B+m and S - which we * do by computing b+m and doing a bitwhack compare against * 2**(DIGIT_BIT*sd) */ mp_add(b, m, temp); if (temp->used <= sd) { /* Too few digits to be > s */ return 0; } if (temp->used > sd+1 || temp->dp[sd] > 1) { /* >= 2s */ return 1; } for (i = sd-1; i >= 0; --i) { /* Check for ==s */ if (temp->dp[i] != 0) { /* > s */ return 1; } } if (convType == TCL_DD_STEELE0) { /* Biased rounding. */ return 0; } return isodd; } /* *---------------------------------------------------------------------- * * ShorteningBignumConversionPowD -- * * Converts a double-precision number to the shortest string of digits * that reconverts exactly to the given number, or to 'ilim' digits if * that will yield a shorter result. The denominator in David Gay's * conversion algorithm is known to be a power of 2**DIGIT_BIT, and hence * the division in the main loop may be replaced by a digit shift and * mask. * * Results: * Returns the string of significant decimal digits, in newly allocated * memory * * Side effects: * Stores the location of the decimal point in '*decpt' and the location * of the terminal null byte in '*endPtr'. * *---------------------------------------------------------------------- */ inline static char * ShorteningBignumConversionPowD( Double *dPtr, /* Original number to convert. */ int convType, /* Type of conversion (shortest, Steele, * E format, F format). */ Tcl_WideUInt bw, /* Integer significand. */ int b2, int b5, /* Scale factor for the significand in the * numerator. */ int m2plus, int m2minus, int m5, /* Scale factors for 1/2 ulp in the numerator * (will be different if bw == 1). */ int sd, /* Scale factor for the denominator. */ int k, /* Number of output digits before the decimal * point. */ int len, /* Number of digits to allocate. */ int ilim, /* Number of digits to convert if b >= s */ int ilim1, /* Number of digits to convert if b < s */ int *decpt, /* OUTPUT: Position of the decimal point. */ char **endPtr) /* OUTPUT: Position of the terminal '\0' at * the end of the returned string. */ { char *retval = ckalloc(len + 1); /* Output buffer. */ mp_int b; /* Numerator of the fraction being * converted. */ mp_int mplus, mminus; /* Bounds for roundoff. */ mp_digit digit; /* Current output digit. */ char *s = retval; /* Cursor in the output buffer. */ int i; /* Index in the output buffer. */ mp_int temp; int r1; /* * b = bw * 2**b2 * 5**b5 * mminus = 5**m5 */ TclBNInitBignumFromWideUInt(&b, bw); mp_init_set_int(&mminus, 1); MulPow5(&b, b5, &b); mp_mul_2d(&b, b2, &b); /* * Adjust if the logarithm was guessed wrong. */ if (b.used <= sd) { mp_mul_d(&b, 10, &b); ++m2plus; ++m2minus; ++m5; ilim = ilim1; --k; } /* * mminus = 5**m5 * 2**m2minus * mplus = 5**m5 * 2**m2plus */ mp_mul_2d(&mminus, m2minus, &mminus); MulPow5(&mminus, m5, &mminus); if (m2plus > m2minus) { mp_init_copy(&mplus, &mminus); mp_mul_2d(&mplus, m2plus-m2minus, &mplus); } mp_init(&temp); /* * Loop through the digits. Do division and mod by s == 2**(sd*DIGIT_BIT) * by mp_digit extraction. */ i = 0; for (;;) { if (b.used <= sd) { digit = 0; } else { digit = b.dp[sd]; if (b.used > sd+1 || digit >= 10) { Tcl_Panic("wrong digit!"); } --b.used; mp_clamp(&b); } /* * Does the current digit put us on the low side of the exact value * but within within roundoff of being exact? */ r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus); if (r1 == MP_LT || (r1 == MP_EQ && convType != TCL_DD_STEELE0 && (dPtr->w.word1 & 1) == 0)) { /* * Make sure we shouldn't be rounding *up* instead, in case the * next number above is closer. */ if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) { ++digit; if (digit == 10) { *s++ = '9'; s = BumpUp(s, retval, &k); break; } } /* * Stash the last digit. */ *s++ = '0' + digit; break; } /* * Does one plus the current digit put us within roundoff of the * number? */ if (ShouldBankerRoundUpToNextPowD(&b, &mminus, sd, convType, dPtr->w.word1 & 1, &temp)) { if (digit == 9) { *s++ = '9'; s = BumpUp(s, retval, &k); break; } ++digit; *s++ = '0' + digit; break; } /* * Have we converted all the requested digits? */ *s++ = '0' + digit; if (i == ilim) { if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) { s = BumpUp(s, retval, &k); } break; } /* * Advance to the next digit. */ mp_mul_d(&b, 10, &b); mp_mul_d(&mminus, 10, &mminus); if (m2plus > m2minus) { mp_mul_2d(&mminus, m2plus-m2minus, &mplus); } ++i; } /* * Endgame - store the location of the decimal point and the end of the * string. */ if (m2plus > m2minus) { mp_clear(&mplus); } mp_clear_multi(&b, &mminus, &temp, NULL); *s = '\0'; *decpt = k; if (endPtr) { *endPtr = s; } return retval; } /* *---------------------------------------------------------------------- * * StrictBignumConversionPowD -- * * Converts a double-precision number to a fixed-lengt string of 'ilim' * digits (or 'ilim1' if log10(d) has been overestimated). The * denominator in David Gay's conversion algorithm is known to be a power * of 2**DIGIT_BIT, and hence the division in the main loop may be * replaced by a digit shift and mask. * * Results: * Returns the string of significant decimal digits, in newly allocated * memory. * * Side effects: * Stores the location of the decimal point in '*decpt' and the location * of the terminal null byte in '*endPtr'. * *---------------------------------------------------------------------- */ inline static char * StrictBignumConversionPowD( Double *dPtr, /* Original number to convert. */ int convType, /* Type of conversion (shortest, Steele, * E format, F format). */ Tcl_WideUInt bw, /* Integer significand. */ int b2, int b5, /* Scale factor for the significand in the * numerator. */ int sd, /* Scale factor for the denominator. */ int k, /* Number of output digits before the decimal * point. */ int len, /* Number of digits to allocate. */ int ilim, /* Number of digits to convert if b >= s */ int ilim1, /* Number of digits to convert if b < s */ int *decpt, /* OUTPUT: Position of the decimal point. */ char **endPtr) /* OUTPUT: Position of the terminal '\0' at * the end of the returned string. */ { char *retval = ckalloc(len + 1); /* Output buffer. */ mp_int b; /* Numerator of the fraction being * converted. */ mp_digit digit; /* Current output digit. */ char *s = retval; /* Cursor in the output buffer. */ int i; /* Index in the output buffer. */ mp_int temp; /* * b = bw * 2**b2 * 5**b5 */ TclBNInitBignumFromWideUInt(&b, bw); MulPow5(&b, b5, &b); mp_mul_2d(&b, b2, &b); /* * Adjust if the logarithm was guessed wrong. */ if (b.used <= sd) { mp_mul_d(&b, 10, &b); ilim = ilim1; --k; } mp_init(&temp); /* * Loop through the digits. Do division and mod by s == 2**(sd*DIGIT_BIT) * by mp_digit extraction. */ i = 1; for (;;) { if (b.used <= sd) { digit = 0; } else { digit = b.dp[sd]; if (b.used > sd+1 || digit >= 10) { Tcl_Panic("wrong digit!"); } --b.used; mp_clamp(&b); } /* * Have we converted all the requested digits? */ *s++ = '0' + digit; if (i == ilim) { if (ShouldBankerRoundUpPowD(&b, sd, digit&1)) { s = BumpUp(s, retval, &k); } while (*--s == '0') { /* do nothing */ } ++s; break; } /* * Advance to the next digit. */ mp_mul_d(&b, 10, &b); ++i; } /* * Endgame - store the location of the decimal point and the end of the * string. */ mp_clear_multi(&b, &temp, NULL); *s = '\0'; *decpt = k; if (endPtr) { *endPtr = s; } return retval; } /* *---------------------------------------------------------------------- * * ShouldBankerRoundUp -- * * Tests whether a digit should be rounded up or down when finishing * bignum-based floating point conversion. * * Results: * Returns 1 if the number needs to be rounded up, 0 otherwise. * *---------------------------------------------------------------------- */ inline static int ShouldBankerRoundUp( mp_int *twor, /* 2x the remainder from thd division that * produced the last digit. */ mp_int *S, /* Denominator. */ int isodd) /* Flag == 1 if the last digit is odd. */ { int r = mp_cmp_mag(twor, S); switch (r) { case MP_LT: return 0; case MP_EQ: return isodd; case MP_GT: return 1; } Tcl_Panic("in ShouldBankerRoundUp, trichotomy fails!"); return 0; } /* *---------------------------------------------------------------------- * * ShouldBankerRoundUpToNext -- * * Tests whether the remainder is great enough to force rounding to the * next higher digit. * * Results: * Returns 1 if the number should be rounded up, 0 otherwise. * *---------------------------------------------------------------------- */ inline static int ShouldBankerRoundUpToNext( mp_int *b, /* Remainder from the division that produced * the last digit. */ mp_int *m, /* Numerator of the rounding tolerance. */ mp_int *S, /* Denominator. */ int convType, /* Conversion type: STEELE0 defeats * round-to-even. (Not sure why one would want * this; I coped it from Gay). FIXME */ int isodd, /* 1 if the integer significand is odd. */ mp_int *temp) /* Work area needed for the calculation. */ { int r; /* * Compare b and S-m: this is the same as comparing B+m and S. */ mp_add(b, m, temp); r = mp_cmp_mag(temp, S); switch(r) { case MP_LT: return 0; case MP_EQ: if (convType == TCL_DD_STEELE0) { return 0; } else { return isodd; } case MP_GT: return 1; } Tcl_Panic("in ShouldBankerRoundUpToNext, trichotomy fails!"); return 0; } /* *---------------------------------------------------------------------- * * ShorteningBignumConversion -- * * Convert a floating point number to a variable-length digit string * using the multiprecision method. * * Results: * Returns the string of digits. * * Side effects: * Stores the position of the decimal point in *decpt. Stores a pointer * to the end of the number in *endPtr. * *---------------------------------------------------------------------- */ inline static char * ShorteningBignumConversion( Double *dPtr, /* Original number being converted. */ int convType, /* Conversion type. */ Tcl_WideUInt bw, /* Integer significand and exponent. */ int b2, /* Scale factor for the significand. */ int m2plus, int m2minus, /* Scale factors for 1/2 ulp in numerator. */ int s2, int s5, /* Scale factors for denominator. */ int k, /* Guessed position of the decimal point. */ int len, /* Size of the digit buffer to allocate. */ int ilim, /* Number of digits to convert if b >= s */ int ilim1, /* Number of digits to convert if b < s */ int *decpt, /* OUTPUT: Position of the decimal point. */ char **endPtr) /* OUTPUT: Pointer to the end of the number */ { char *retval = ckalloc(len+1); /* Buffer of digits to return. */ char *s = retval; /* Cursor in the return value. */ mp_int b; /* Numerator of the result. */ mp_int mminus; /* 1/2 ulp below the result. */ mp_int mplus; /* 1/2 ulp above the result. */ mp_int S; /* Denominator of the result. */ mp_int dig; /* Current digit of the result. */ int digit; /* Current digit of the result. */ mp_int temp; /* Work area. */ int minit = 1; /* Fudge factor for when we misguess k. */ int i; int r1; /* * b = bw * 2**b2 * 5**b5 * S = 2**s2 * 5*s5 */ TclBNInitBignumFromWideUInt(&b, bw); mp_mul_2d(&b, b2, &b); mp_init_set_int(&S, 1); MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); /* * Handle the case where we guess the position of the decimal point wrong. */ if (mp_cmp_mag(&b, &S) == MP_LT) { mp_mul_d(&b, 10, &b); minit = 10; ilim =ilim1; --k; } /* * mminus = 2**m2minus * 5**m5 */ mp_init_set_int(&mminus, minit); mp_mul_2d(&mminus, m2minus, &mminus); if (m2plus > m2minus) { mp_init_copy(&mplus, &mminus); mp_mul_2d(&mplus, m2plus-m2minus, &mplus); } mp_init(&temp); /* * Loop through the digits. */ mp_init(&dig); i = 1; for (;;) { mp_div(&b, &S, &dig, &b); if (dig.used > 1 || dig.dp[0] >= 10) { Tcl_Panic("wrong digit!"); } digit = dig.dp[0]; /* * Does the current digit leave us with a remainder small enough to * round to it? */ r1 = mp_cmp_mag(&b, (m2plus > m2minus)? &mplus : &mminus); if (r1 == MP_LT || (r1 == MP_EQ && convType != TCL_DD_STEELE0 && (dPtr->w.word1 & 1) == 0)) { mp_mul_2d(&b, 1, &b); if (ShouldBankerRoundUp(&b, &S, digit&1)) { ++digit; if (digit == 10) { *s++ = '9'; s = BumpUp(s, retval, &k); break; } } *s++ = '0' + digit; break; } /* * Does the current digit leave us with a remainder large enough to * commit to rounding up to the next higher digit? */ if (ShouldBankerRoundUpToNext(&b, &mminus, &S, convType, dPtr->w.word1 & 1, &temp)) { ++digit; if (digit == 10) { *s++ = '9'; s = BumpUp(s, retval, &k); break; } *s++ = '0' + digit; break; } /* * Have we converted all the requested digits? */ *s++ = '0' + digit; if (i == ilim) { mp_mul_2d(&b, 1, &b); if (ShouldBankerRoundUp(&b, &S, digit&1)) { s = BumpUp(s, retval, &k); } break; } /* * Advance to the next digit. */ if (s5 > 0) { /* * Can possibly shorten the denominator. */ mp_mul_2d(&b, 1, &b); mp_mul_2d(&mminus, 1, &mminus); if (m2plus > m2minus) { mp_mul_2d(&mplus, 1, &mplus); } mp_div_d(&S, 5, &S, NULL); --s5; /* * IDEA: It might possibly be a win to fall back to int64 * arithmetic here if S < 2**64/10. But it's a win only for * a fairly narrow range of magnitudes so perhaps not worth * bothering. We already know that we shorten the * denominator by at least 1 mp_digit, perhaps 2, as we do * the conversion for 17 digits of significance. * Possible savings: * 10**26 1 trip through loop before fallback possible * 10**27 1 trip * 10**28 2 trips * 10**29 3 trips * 10**30 4 trips * 10**31 5 trips * 10**32 6 trips * 10**33 7 trips * 10**34 8 trips * 10**35 9 trips * 10**36 10 trips * 10**37 11 trips * 10**38 12 trips * 10**39 13 trips * 10**40 14 trips * 10**41 15 trips * 10**42 16 trips * thereafter no gain. */ } else { mp_mul_d(&b, 10, &b); mp_mul_d(&mminus, 10, &mminus); if (m2plus > m2minus) { mp_mul_2d(&mplus, 10, &mplus); } } ++i; } /* * Endgame - store the location of the decimal point and the end of the * string. */ if (m2plus > m2minus) { mp_clear(&mplus); } mp_clear_multi(&b, &mminus, &temp, &dig, &S, NULL); *s = '\0'; *decpt = k; if (endPtr) { *endPtr = s; } return retval; } /* *---------------------------------------------------------------------- * * StrictBignumConversion -- * * Convert a floating point number to a fixed-length digit string using * the multiprecision method. * * Results: * Returns the string of digits. * * Side effects: * Stores the position of the decimal point in *decpt. Stores a pointer * to the end of the number in *endPtr. * *---------------------------------------------------------------------- */ inline static char * StrictBignumConversion( Double *dPtr, /* Original number being converted. */ int convType, /* Conversion type. */ Tcl_WideUInt bw, /* Integer significand and exponent. */ int b2, /* Scale factor for the significand. */ int s2, int s5, /* Scale factors for denominator. */ int k, /* Guessed position of the decimal point. */ int len, /* Size of the digit buffer to allocate. */ int ilim, /* Number of digits to convert if b >= s */ int ilim1, /* Number of digits to convert if b < s */ int *decpt, /* OUTPUT: Position of the decimal point. */ char **endPtr) /* OUTPUT: Pointer to the end of the number */ { char *retval = ckalloc(len+1); /* Buffer of digits to return. */ char *s = retval; /* Cursor in the return value. */ mp_int b; /* Numerator of the result. */ mp_int S; /* Denominator of the result. */ mp_int dig; /* Current digit of the result. */ int digit; /* Current digit of the result. */ mp_int temp; /* Work area. */ int g; /* Size of the current digit ground. */ int i, j; /* * b = bw * 2**b2 * 5**b5 * S = 2**s2 * 5*s5 */ mp_init_multi(&temp, &dig, NULL); TclBNInitBignumFromWideUInt(&b, bw); mp_mul_2d(&b, b2, &b); mp_init_set_int(&S, 1); MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); /* * Handle the case where we guess the position of the decimal point wrong. */ if (mp_cmp_mag(&b, &S) == MP_LT) { mp_mul_d(&b, 10, &b); ilim =ilim1; --k; } /* * Convert the leading digit. */ i = 0; mp_div(&b, &S, &dig, &b); if (dig.used > 1 || dig.dp[0] >= 10) { Tcl_Panic("wrong digit!"); } digit = dig.dp[0]; /* * Is a single digit all that was requested? */ *s++ = '0' + digit; if (++i >= ilim) { mp_mul_2d(&b, 1, &b); if (ShouldBankerRoundUp(&b, &S, digit&1)) { s = BumpUp(s, retval, &k); } } else { for (;;) { /* * Shift by a group of digits. */ g = ilim - i; if (g > DIGIT_GROUP) { g = DIGIT_GROUP; } if (s5 >= g) { mp_div_d(&S, dpow5[g], &S, NULL); s5 -= g; } else if (s5 > 0) { mp_div_d(&S, dpow5[s5], &S, NULL); mp_mul_d(&b, dpow5[g - s5], &b); s5 = 0; } else { mp_mul_d(&b, dpow5[g], &b); } mp_mul_2d(&b, g, &b); /* * As with the shortening bignum conversion, it's possible at this * point that we will have reduced the denominator to less than * 2**64/10, at which point it would be possible to fall back to * to int64 arithmetic. But the potential payoff is tremendously * less - unless we're working in F format - because we know that * three groups of digits will always suffice for %#.17e, the * longest format that doesn't introduce empty precision. * * Extract the next group of digits. */ mp_div(&b, &S, &dig, &b); if (dig.used > 1) { Tcl_Panic("wrong digit!"); } digit = dig.dp[0]; for (j = g-1; j >= 0; --j) { int t = itens[j]; *s++ = digit / t + '0'; digit %= t; } i += g; /* * Have we converted all the requested digits? */ if (i == ilim) { mp_mul_2d(&b, 1, &b); if (ShouldBankerRoundUp(&b, &S, digit&1)) { s = BumpUp(s, retval, &k); } break; } } } while (*--s == '0') { /* do nothing */ } ++s; /* * Endgame - store the location of the decimal point and the end of the * string. */ mp_clear_multi(&b, &S, &temp, &dig, NULL); *s = '\0'; *decpt = k; if (endPtr) { *endPtr = s; } return retval; } /* *---------------------------------------------------------------------- * * TclDoubleDigits -- * * Core of Tcl's conversion of double-precision floating point numbers to * decimal. * * Results: * Returns a newly-allocated string of digits. * * Side effects: * Sets *decpt to the index of the character in the string before the * place that the decimal point should go. If 'endPtr' is not NULL, sets * endPtr to point to the terminating '\0' byte of the string. Sets *sign * to 1 if a minus sign should be printed with the number, or 0 if a plus * sign (or no sign) should appear. * * This function is a service routine that produces the string of digits for * floating-point-to-decimal conversion. It can do a number of things * according to the 'flags' argument. Valid values for 'flags' include: * TCL_DD_SHORTEST - This is the default for floating point conversion if * ::tcl_precision is 0. It constructs the shortest string of * digits that will reconvert to the given number when scanned. * For floating point numbers that are exactly between two * decimal numbers, it resolves using the 'round to even' rule. * With this value, the 'ndigits' parameter is ignored. * TCL_DD_STEELE - This value is not recommended and may be removed in * the future. It follows the conversion algorithm outlined in * "How to Print Floating-Point Numbers Accurately" by Guy * L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, * pp. 112-126]. This rule has the effect of rendering 1e23 as * 9.9999999999999999e22 - which is a 'better' approximation in * the sense that it will reconvert correctly even if a * subsequent input conversion is 'round up' or 'round down' * rather than 'round to nearest', but is surprising otherwise. * TCL_DD_E_FORMAT - This value is used to prepare numbers for %e format * conversion (or for default floating->string if tcl_precision * is not 0). It constructs a string of at most 'ndigits' digits, * choosing the one that is closest to the given number (and * resolving ties with 'round to even'). It is allowed to return * fewer than 'ndigits' if the number converts exactly; if the * TCL_DD_E_FORMAT|TCL_DD_SHORTEN_FLAG is supplied instead, it * also returns fewer digits if the shorter string will still * reconvert without loss to the given input number. In any case, * strings of trailing zeroes are suppressed. * TCL_DD_F_FORMAT - This value is used to prepare numbers for %f format * conversion. It requests that conversion proceed until * 'ndigits' digits after the decimal point have been converted. * It is possible for this format to result in a zero-length * string if the number is sufficiently small. Again, it is * permissible for TCL_DD_F_FORMAT to return fewer digits for a * number that converts exactly, and changing the argument to * TCL_DD_F_FORMAT|TCL_DD_SHORTEN_FLAG will allow the routine * also to return fewer digits if the shorter string will still * reconvert without loss to the given input number. Strings of * trailing zeroes are suppressed. * * To any of these flags may be OR'ed TCL_DD_NO_QUICK; this flag requires * all calculations to be done in exact arithmetic. Normally, E and F * format with fewer than about 14 digits will be done with a quick * floating point approximation and fall back on the exact arithmetic * only if the input number is close enough to the midpoint between two * decimal strings that more precision is needed to resolve which string * is correct. * * The value stored in the 'decpt' argument on return may be negative * (indicating that the decimal point falls to the left of the string) or * greater than the length of the string. In addition, the value -9999 is used * as a sentinel to indicate that the string is one of the special values * "Infinity" and "NaN", and that no decimal point should be inserted. * *---------------------------------------------------------------------- */ char * TclDoubleDigits( double dv, /* Number to convert. */ int ndigits, /* Number of digits requested. */ int flags, /* Conversion flags. */ int *decpt, /* OUTPUT: Position of the decimal point. */ int *sign, /* OUTPUT: 1 if the result is negative. */ char **endPtr) /* OUTPUT: If not NULL, receives a pointer to * one character beyond the end of the * returned string. */ { int convType = (flags & TCL_DD_CONVERSION_TYPE_MASK); /* Type of conversion being performed: * TCL_DD_SHORTEST0, TCL_DD_STEELE0, * TCL_DD_E_FORMAT, or TCL_DD_F_FORMAT. */ Double d; /* Union for deconstructing doubles. */ Tcl_WideUInt bw; /* Integer significand. */ int be; /* Power of 2 by which b must be multiplied */ int bbits; /* Number of bits needed to represent b. */ int denorm; /* Flag == 1 iff the input number was * denormalized. */ int k; /* Estimate of floor(log10(d)). */ int k_check; /* Flag == 1 if d is near enough to a power of * ten that k must be checked. */ int b2, b5, s2, s5; /* Powers of 2 and 5 in the numerator and * denominator of intermediate results. */ int ilim = -1, ilim1 = -1; /* Number of digits to convert, and number to * convert if log10(d) has been * overestimated. */ char *retval; /* Return value from this function. */ int i = -1; /* * Put the input number into a union for bit-whacking. */ d.d = dv; /* * Handle the cases of negative numbers (by taking the absolute value: * this includes -Inf and -NaN!), infinity, Not a Number, and zero. */ TakeAbsoluteValue(&d, sign); if ((d.w.word0 & EXP_MASK) == EXP_MASK) { return FormatInfAndNaN(&d, decpt, endPtr); } if (d.d == 0.0) { return FormatZero(decpt, endPtr); } /* * Unpack the floating point into a wide integer and an exponent. * Determine the number of bits that the big integer requires, and compute * a quick approximation (which may be one too high) of ceil(log10(d.d)). */ denorm = ((d.w.word0 & EXP_MASK) == 0); DoubleToExpAndSig(d.d, &bw, &be, &bbits); k = ApproximateLog10(bw, be, bbits); k = BetterLog10(d.d, k, &k_check); /* At this point, we have: * d is the number to convert. * bw are significand and exponent: d == bw*2**be, * bbits is the length of bw: 2**bbits-1 <= bw < 2**bbits * k is either ceil(log10(d)) or ceil(log10(d))+1. k_check is 0 if we * know that k is exactly ceil(log10(d)) and 1 if we need to check. * We want a rational number * r = b * 10**(1-k) = bw * 2**b2 * 5**b5 / (2**s2 / 5**s5), * with b2, b5, s2, s5 >= 0. Note that the most significant decimal * digit is floor(r) and that successive digits can be obtained by * setting r <- 10*floor(r) (or b <= 10 * (b % S)). Find appropriate * b2, b5, s2, s5. */ ComputeScale(be, k, &b2, &b5, &s2, &s5); /* * Correct an incorrect caller-supplied 'ndigits'. Also determine: * i = The maximum number of decimal digits that will be returned in the * formatted string. This is k + 1 + ndigits for F format, 18 for * shortest and Steele, and ndigits for E format. * ilim = The number of significant digits to convert if k has been * guessed correctly. This is -1 for shortest and Steele (which * stop when all significance has been lost), 'ndigits' for E * format, and 'k + 1 + ndigits' for F format. * ilim1 = The minimum number of significant digits to convert if k has * been guessed 1 too high. This, too, is -1 for shortest and * Steele, and 'ndigits' for E format, but it's 'ndigits-1' for F * format. */ SetPrecisionLimits(convType, k, &ndigits, &i, &ilim, &ilim1); /* * Try to do low-precision conversion in floating point rather than * resorting to expensive multiprecision arithmetic. */ if (ilim >= 0 && ilim <= QUICK_MAX && !(flags & TCL_DD_NO_QUICK)) { retval = QuickConversion(d.d, k, k_check, flags, i, ilim, ilim1, decpt, endPtr); if (retval != NULL) { return retval; } } /* * For shortening conversions, determine the upper and lower bounds for * the remainder at which we can stop. * m+ = (2**m2plus * 5**m5) / (2**s2 * 5**s5) is the limit on the high * side, and * m- = (2**m2minus * 5**m5) / (2**s2 * 5**s5) is the limit on the low * side. * We may need to increase s2 to put m2plus, m2minus, b2 over a common * denominator. */ if (flags & TCL_DD_SHORTEN_FLAG) { int m2minus = b2; int m2plus; int m5 = b5; int len = i; /* * Find the quantity i so that (2**i*5**b5)/(2**s2*5**s5) is 1/2 unit * in the least significant place of the floating point number. */ if (denorm) { i = be + EXPONENT_BIAS + (FP_PRECISION-1); } else { i = 1 + FP_PRECISION - bbits; } b2 += i; s2 += i; /* * Reduce the fractions to lowest terms, since the above calculation * may have left excess powers of 2 in numerator and denominator. */ CastOutPowersOf2(&b2, &m2minus, &s2); /* * In the special case where bw==1, the nearest floating point number * to it on the low side is 1/4 ulp below it. Adjust accordingly. */ m2plus = m2minus; if (!denorm && bw == 1) { ++b2; ++s2; ++m2plus; } if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] <= 64) { /* * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit word, * then all our intermediate calculations can be done using exact * 64-bit arithmetic with no need for expensive multiprecision * operations. (This will be true for all numbers in the range * [1.0e-3 .. 1.0e+24]). */ return ShorteningInt64Conversion(&d, convType, bw, b2, b5, m2plus, m2minus, m5, s2, s5, k, len, ilim, ilim1, decpt, endPtr); } else if (s5 == 0) { /* * The denominator is a power of 2, so we can replace division by * digit shifts. First we round up s2 to a multiple of DIGIT_BIT, * and adjust m2 and b2 accordingly. Then we launch into a version * of the comparison that's specialized for the 'power of mp_digit * in the denominator' case. */ if (s2 % DIGIT_BIT != 0) { int delta = DIGIT_BIT - (s2 % DIGIT_BIT); b2 += delta; m2plus += delta; m2minus += delta; s2 += delta; } return ShorteningBignumConversionPowD(&d, convType, bw, b2, b5, m2plus, m2minus, m5, s2/DIGIT_BIT, k, len, ilim, ilim1, decpt, endPtr); } else { /* * Alas, there's no helpful special case; use full-up bignum * arithmetic for the conversion. */ return ShorteningBignumConversion(&d, convType, bw, b2, m2plus, m2minus, s2, s5, k, len, ilim, ilim1, decpt, endPtr); } } else { /* * Non-shortening conversion. */ int len = i; /* * Reduce numerator and denominator to lowest terms. */ if (b2 >= s2 && s2 > 0) { b2 -= s2; s2 = 0; } else if (s2 >= b2 && b2 > 0) { s2 -= b2; b2 = 0; } if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] <= 64) { /* * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit word, * then all our intermediate calculations can be done using exact * 64-bit arithmetic with no need for expensive multiprecision * operations. */ return StrictInt64Conversion(&d, convType, bw, b2, b5, s2, s5, k, len, ilim, ilim1, decpt, endPtr); } else if (s5 == 0) { /* * The denominator is a power of 2, so we can replace division by * digit shifts. First we round up s2 to a multiple of DIGIT_BIT, * and adjust m2 and b2 accordingly. Then we launch into a version * of the comparison that's specialized for the 'power of mp_digit * in the denominator' case. */ if (s2 % DIGIT_BIT != 0) { int delta = DIGIT_BIT - (s2 % DIGIT_BIT); b2 += delta; s2 += delta; } return StrictBignumConversionPowD(&d, convType, bw, b2, b5, s2/DIGIT_BIT, k, len, ilim, ilim1, decpt, endPtr); } else { /* * There are no helpful special cases, but at least we know in * advance how many digits we will convert. We can run the * conversion in steps of DIGIT_GROUP digits, so as to have many * fewer mp_int divisions. */ return StrictBignumConversion(&d, convType, bw, b2, s2, s5, k, len, ilim, ilim1, decpt, endPtr); } } } /* *---------------------------------------------------------------------- * * TclInitDoubleConversion -- * * Initializes constants that are needed for conversions to and from * 'double' * * Results: * None. * * Side effects: * The log base 2 of the floating point radix, the number of bits in a * double mantissa, and a table of the powers of five and ten are * computed and stored. * *---------------------------------------------------------------------- */ void TclInitDoubleConversion(void) { int i; int x; Tcl_WideUInt u; double d; #ifdef IEEE_FLOATING_POINT union { double dv; Tcl_WideUInt iv; } bitwhack; #endif #if defined(__sgi) && defined(_COMPILER_VERSION) union fpc_csr mipsCR; mipsCR.fc_word = get_fpc_csr(); mipsCR.fc_struct.flush = 0; set_fpc_csr(mipsCR.fc_word); #endif /* * Initialize table of powers of 10 expressed as wide integers. */ maxpow10_wide = (int) floor(sizeof(Tcl_WideUInt) * CHAR_BIT * log(2.) / log(10.)); pow10_wide = ckalloc((maxpow10_wide + 1) * sizeof(Tcl_WideUInt)); u = 1; for (i = 0; i < maxpow10_wide; ++i) { pow10_wide[i] = u; u *= 10; } pow10_wide[i] = u; /* * Determine how many bits of precision a double has, and how many decimal * digits that represents. */ if (frexp((double) FLT_RADIX, &log2FLT_RADIX) != 0.5) { Tcl_Panic("This code doesn't work on a decimal machine!"); } log2FLT_RADIX--; mantBits = DBL_MANT_DIG * log2FLT_RADIX; d = 1.0; /* * Initialize a table of powers of ten that can be exactly represented in * a double. */ x = (int) (DBL_MANT_DIG * log((double) FLT_RADIX) / log(5.0)); if (x < MAXPOW) { mmaxpow = x; } else { mmaxpow = MAXPOW; } for (i=0 ; i<=mmaxpow ; ++i) { pow10vals[i] = d; d *= 10.0; } /* * Initialize a table of large powers of five. */ for (i=0; i<9; ++i) { mp_init(pow5 + i); } mp_set(pow5, 5); for (i=0; i<8; ++i) { mp_sqr(pow5+i, pow5+i+1); } mp_init_set_int(pow5_13, 1220703125); for (i = 1; i < 5; ++i) { mp_init(pow5_13 + i); mp_sqr(pow5_13 + i - 1, pow5_13 + i); } /* * Determine the number of decimal digits to the left and right of the * decimal point in the largest and smallest double, the smallest double * that differs from zero, and the number of mp_digits needed to represent * the significand of a double. */ maxDigits = (int) ((DBL_MAX_EXP * log((double) FLT_RADIX) + 0.5 * log(10.)) / log(10.)); minDigits = (int) floor((DBL_MIN_EXP - DBL_MANT_DIG) * log((double) FLT_RADIX) / log(10.)); log10_DIGIT_MAX = (int) floor(DIGIT_BIT * log(2.) / log(10.)); /* * Nokia 770's software-emulated floating point is "middle endian": the * bytes within a 32-bit word are little-endian (like the native * integers), but the two words of a 'double' are presented most * significant word first. */ #ifdef IEEE_FLOATING_POINT bitwhack.dv = 1.000000238418579; /* 3ff0 0000 4000 0000 */ if ((bitwhack.iv >> 32) == 0x3ff00000) { n770_fp = 0; } else if ((bitwhack.iv & 0xffffffff) == 0x3ff00000) { n770_fp = 1; } else { Tcl_Panic("unknown floating point word order on this machine"); } #endif } /* *---------------------------------------------------------------------- * * TclFinalizeDoubleConversion -- * * Cleans up this file on exit. * * Results: * None * * Side effects: * Memory allocated by TclInitDoubleConversion is freed. * *---------------------------------------------------------------------- */ void TclFinalizeDoubleConversion(void) { int i; ckfree(pow10_wide); for (i=0; i<9; ++i) { mp_clear(pow5 + i); } for (i=0; i < 5; ++i) { mp_clear(pow5_13 + i); } } /* *---------------------------------------------------------------------- * * Tcl_InitBignumFromDouble -- * * Extracts the integer part of a double and converts it to an arbitrary * precision integer. * * Results: * None. * * Side effects: * Initializes the bignum supplied, and stores the converted number in * it. * *---------------------------------------------------------------------- */ int Tcl_InitBignumFromDouble( Tcl_Interp *interp, /* For error message. */ double d, /* Number to convert. */ mp_int *b) /* Place to store the result. */ { double fract; int expt; /* * Infinite values can't convert to bignum. */ if (TclIsInfinite(d)) { if (interp != NULL) { const char *s = "integer value too large to represent"; Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1)); Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL); } return TCL_ERROR; } fract = frexp(d,&expt); if (expt <= 0) { mp_init(b); mp_zero(b); } else { Tcl_WideInt w = (Tcl_WideInt) ldexp(fract, mantBits); int shift = expt - mantBits; TclBNInitBignumFromWideInt(b, w); if (shift < 0) { mp_div_2d(b, -shift, b, NULL); } else if (shift > 0) { mp_mul_2d(b, shift, b); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclBignumToDouble -- * * Convert an arbitrary-precision integer to a native floating point * number. * * Results: * Returns the converted number. Sets errno to ERANGE if the number is * too large to convert. * *---------------------------------------------------------------------- */ double TclBignumToDouble( const mp_int *a) /* Integer to convert. */ { mp_int b; int bits, shift, i, lsb; double r; /* * We need a 'mantBits'-bit significand. Determine what shift will * give us that. */ bits = mp_count_bits(a); if (bits > DBL_MAX_EXP*log2FLT_RADIX) { errno = ERANGE; if (a->sign == MP_ZPOS) { return HUGE_VAL; } else { return -HUGE_VAL; } } shift = mantBits - bits; /* * If shift > 0, shift the significand left by the requisite number of * bits. If shift == 0, the significand is already exactly 'mantBits' * in length. If shift < 0, we will need to shift the significand right * by the requisite number of bits, and round it. If the '1-shift' * least significant bits are 0, but the 'shift'th bit is nonzero, * then the significand lies exactly between two values and must be * 'rounded to even'. */ mp_init(&b); if (shift == 0) { mp_copy(a, &b); } else if (shift > 0) { mp_mul_2d(a, shift, &b); } else if (shift < 0) { lsb = mp_cnt_lsb(a); if (lsb == -1-shift) { /* * Round to even */ mp_div_2d(a, -shift, &b, NULL); if (mp_isodd(&b)) { if (b.sign == MP_ZPOS) { mp_add_d(&b, 1, &b); } else { mp_sub_d(&b, 1, &b); } } } else { /* * Ordinary rounding */ mp_div_2d(a, -1-shift, &b, NULL); if (b.sign == MP_ZPOS) { mp_add_d(&b, 1, &b); } else { mp_sub_d(&b, 1, &b); } mp_div_2d(&b, 1, &b, NULL); } } /* * Accumulate the result, one mp_digit at a time. */ r = 0.0; for (i=b.used-1 ; i>=0 ; --i) { r = ldexp(r, DIGIT_BIT) + b.dp[i]; } mp_clear(&b); /* * Scale the result to the correct number of bits. */ r = ldexp(r, bits - mantBits); /* * Return the result with the appropriate sign. */ if (a->sign == MP_ZPOS) { return r; } else { return -r; } } /* *---------------------------------------------------------------------- * * TclCeil -- * * Computes the smallest floating point number that is at least the * mp_int argument. * * Results: * Returns the floating point number. * *---------------------------------------------------------------------- */ double TclCeil( const mp_int *a) /* Integer to convert. */ { double r = 0.0; mp_int b; mp_init(&b); if (mp_cmp_d(a, 0) == MP_LT) { mp_neg(a, &b); r = -TclFloor(&b); } else { int bits = mp_count_bits(a); if (bits > DBL_MAX_EXP*log2FLT_RADIX) { r = HUGE_VAL; } else { int i, exact = 1, shift = mantBits - bits; if (shift > 0) { mp_mul_2d(a, shift, &b); } else if (shift < 0) { mp_int d; mp_init(&d); mp_div_2d(a, -shift, &b, &d); exact = mp_iszero(&d); mp_clear(&d); } else { mp_copy(a, &b); } if (!exact) { mp_add_d(&b, 1, &b); } for (i=b.used-1 ; i>=0 ; --i) { r = ldexp(r, DIGIT_BIT) + b.dp[i]; } r = ldexp(r, bits - mantBits); } } mp_clear(&b); return r; } /* *---------------------------------------------------------------------- * * TclFloor -- * * Computes the largest floating point number less than or equal to the * mp_int argument. * * Results: * Returns the floating point value. * *---------------------------------------------------------------------- */ double TclFloor( const mp_int *a) /* Integer to convert. */ { double r = 0.0; mp_int b; mp_init(&b); if (mp_cmp_d(a, 0) == MP_LT) { mp_neg(a, &b); r = -TclCeil(&b); } else { int bits = mp_count_bits(a); if (bits > DBL_MAX_EXP*log2FLT_RADIX) { r = DBL_MAX; } else { int i, shift = mantBits - bits; if (shift > 0) { mp_mul_2d(a, shift, &b); } else if (shift < 0) { mp_div_2d(a, -shift, &b, NULL); } else { mp_copy(a, &b); } for (i=b.used-1 ; i>=0 ; --i) { r = ldexp(r, DIGIT_BIT) + b.dp[i]; } r = ldexp(r, bits - mantBits); } } mp_clear(&b); return r; } /* *---------------------------------------------------------------------- * * BignumToBiasedFrExp -- * * Convert an arbitrary-precision integer to a native floating point * number in the range [0.5,1) times a power of two. NOTE: Intentionally * converts to a number that's a few ulp too small, so that * RefineApproximation will not overflow near the high end of the * machine's arithmetic range. * * Results: * Returns the converted number. * * Side effects: * Stores the exponent of two in 'machexp'. * *---------------------------------------------------------------------- */ static double BignumToBiasedFrExp( const mp_int *a, /* Integer to convert. */ int *machexp) /* Power of two. */ { mp_int b; int bits; int shift; int i; double r; /* * Determine how many bits we need, and extract that many from the input. * Round to nearest unit in the last place. */ bits = mp_count_bits(a); shift = mantBits - 2 - bits; mp_init(&b); if (shift > 0) { mp_mul_2d(a, shift, &b); } else if (shift < 0) { mp_div_2d(a, -shift, &b, NULL); } else { mp_copy(a, &b); } /* * Accumulate the result, one mp_digit at a time. */ r = 0.0; for (i=b.used-1; i>=0; --i) { r = ldexp(r, DIGIT_BIT) + b.dp[i]; } mp_clear(&b); /* * Return the result with the appropriate sign. */ *machexp = bits - mantBits + 2; return ((a->sign == MP_ZPOS) ? r : -r); } /* *---------------------------------------------------------------------- * * Pow10TimesFrExp -- * * Multiply a power of ten by a number expressed as fraction and * exponent. * * Results: * Returns the significand of the result. * * Side effects: * Overwrites the 'machexp' parameter with the exponent of the result. * * Assumes that 'exponent' is such that 10**exponent would be a double, even * though 'fraction*10**(machexp+exponent)' might overflow. * *---------------------------------------------------------------------- */ static double Pow10TimesFrExp( int exponent, /* Power of 10 to multiply by. */ double fraction, /* Significand of multiplicand. */ int *machexp) /* On input, exponent of multiplicand. On * output, exponent of result. */ { int i, j; int expt = *machexp; double retval = fraction; if (exponent > 0) { /* * Multiply by 10**exponent. */ retval = frexp(retval * pow10vals[exponent&0xf], &j); expt += j; for (i=4; i<9; ++i) { if (exponent & (1<> 32) & 0xffffffff) | (w << 32)); } #endif /* *---------------------------------------------------------------------- * * TclNokia770Doubles -- * * Transpose the two words of a number for Nokia 770 floating point * handling. * *---------------------------------------------------------------------- */ int TclNokia770Doubles(void) { return n770_fp; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclRegexp.h0000644000175000017500000000320412663653207015310 0ustar sergeisergei/* * tclRegexp.h -- * * This file contains definitions used internally by Henry Spencer's * regular expression code. * * Copyright (c) 1998 by Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLREGEXP #define _TCLREGEXP #include "regex.h" /* * The TclRegexp structure encapsulates a compiled regex_t, the flags that * were used to compile it, and an array of pointers that are used to indicate * subexpressions after a call to Tcl_RegExpExec. Note that the string and * objPtr are mutually exclusive. These values are needed by Tcl_RegExpRange * in order to return pointers into the original string. */ typedef struct TclRegexp { int flags; /* Regexp compile flags. */ regex_t re; /* Compiled re, includes number of * subexpressions. */ const char *string; /* Last string passed to Tcl_RegExpExec. */ Tcl_Obj *objPtr; /* Last object passed to Tcl_RegExpExecObj. */ Tcl_Obj *globObjPtr; /* Glob pattern rep of RE or NULL if none. */ regmatch_t *matches; /* Array of indices into the Tcl_UniChar * representation of the last string matched * with this regexp to indicate the location * of subexpressions. */ rm_detail_t details; /* Detailed information on match (currently * used only for REG_EXPECT). */ int refCount; /* Count of number of references to this * compiled regexp. */ } TclRegexp; #endif /* _TCLREGEXP */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclTestObj.c0000644000175000017500000012274112663660065015433 0ustar sergeisergei/* * tclTestObj.c -- * * This file contains C command functions for the additional Tcl commands * that are used for testing implementations of the Tcl object types. * These commands are not normally included in Tcl applications; they're * only used for testing. * * Copyright (c) 1995-1998 Sun Microsystems, Inc. * Copyright (c) 1999 by Scriptics Corporation. * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef USE_TCL_STUBS # define USE_TCL_STUBS #endif #include "tclInt.h" #include "tommath.h" /* * Forward declarations for functions defined later in this file: */ static int CheckIfVarUnset(Tcl_Interp *interp, Tcl_Obj **varPtr, int varIndex); static int GetVariableIndex(Tcl_Interp *interp, const char *string, int *indexPtr); static void SetVarToObj(Tcl_Obj **varPtr, int varIndex, Tcl_Obj *objPtr); static int TestbignumobjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestbooleanobjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestdoubleobjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestindexobjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestintobjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestlistobjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestobjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TeststringobjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); typedef struct TestString { int numChars; int allocated; int maxChars; Tcl_UniChar unicode[2]; } TestString; #define VARPTR_KEY "TCLOBJTEST_VARPTR" #define NUMBER_OF_OBJECT_VARS 20 static void VarPtrDeleteProc(ClientData clientData, Tcl_Interp *interp) { register int i; Tcl_Obj **varPtr = (Tcl_Obj **) clientData; for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) { if (varPtr[i]) Tcl_DecrRefCount(varPtr[i]); } Tcl_DeleteAssocData(interp, VARPTR_KEY); ckfree(varPtr); } static Tcl_Obj **GetVarPtr(Tcl_Interp *interp) { Tcl_InterpDeleteProc *proc; return (Tcl_Obj **) Tcl_GetAssocData(interp, VARPTR_KEY, &proc); } /* *---------------------------------------------------------------------- * * TclObjTest_Init -- * * This function creates additional commands that are used to test the * Tcl object support. * * Results: * Returns a standard Tcl completion code, and leaves an error * message in the interp's result if an error occurs. * * Side effects: * Creates and registers several new testing commands. * *---------------------------------------------------------------------- */ int TclObjTest_Init( Tcl_Interp *interp) { register int i; /* * An array of Tcl_Obj pointers used in the commands that operate on or get * the values of Tcl object-valued variables. varPtr[i] is the i-th variable's * Tcl_Obj *. */ Tcl_Obj **varPtr; varPtr = (Tcl_Obj **) ckalloc(NUMBER_OF_OBJECT_VARS *sizeof(varPtr[0])); if (!varPtr) { return TCL_ERROR; } Tcl_SetAssocData(interp, VARPTR_KEY, VarPtrDeleteProc, varPtr); for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) { varPtr[i] = NULL; } Tcl_CreateObjCommand(interp, "testbignumobj", TestbignumobjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testbooleanobj", TestbooleanobjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testdoubleobj", TestdoubleobjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testintobj", TestintobjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testindexobj", TestindexobjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testlistobj", TestlistobjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testobj", TestobjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "teststringobj", TeststringobjCmd, NULL, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestbignumobjCmd -- * * This function implmenets the "testbignumobj" command. It is used * to exercise the bignum Tcl object type implementation. * * Results: * Returns a standard Tcl object result. * * Side effects: * Creates and frees bignum objects; converts objects to have bignum * type. * *---------------------------------------------------------------------- */ static int TestbignumobjCmd( ClientData clientData, /* unused */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Argument count */ Tcl_Obj *const objv[]) /* Argument vector */ { const char *const subcmds[] = { "set", "get", "mult10", "div10", NULL }; enum options { BIGNUM_SET, BIGNUM_GET, BIGNUM_MULT10, BIGNUM_DIV10 }; int index, varIndex; const char *string; mp_int bignumValue, newValue; Tcl_Obj **varPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } string = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, string, &varIndex) != TCL_OK) { return TCL_ERROR; } varPtr = GetVarPtr(interp); switch (index) { case BIGNUM_SET: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "var value"); return TCL_ERROR; } string = Tcl_GetString(objv[3]); if (mp_init(&bignumValue) != MP_OKAY) { Tcl_SetObjResult(interp, Tcl_NewStringObj("error in mp_init", -1)); return TCL_ERROR; } if (mp_read_radix(&bignumValue, string, 10) != MP_OKAY) { mp_clear(&bignumValue); Tcl_SetObjResult(interp, Tcl_NewStringObj("error in mp_read_radix", -1)); return TCL_ERROR; } /* * If the object currently bound to the variable with index varIndex * has ref count 1 (i.e. the object is unshared) we can modify that * object directly. Otherwise, if RC>1 (i.e. the object is shared), * we must create a new object to modify/set and decrement the old * formerly-shared object's ref count. This is "copy on write". */ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetBignumObj(varPtr[varIndex], &bignumValue); } else { SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&bignumValue)); } break; case BIGNUM_GET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } break; case BIGNUM_MULT10: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } if (Tcl_GetBignumFromObj(interp, varPtr[varIndex], &bignumValue) != TCL_OK) { return TCL_ERROR; } if (mp_init(&newValue) != MP_OKAY || (mp_mul_d(&bignumValue, 10, &newValue) != MP_OKAY)) { mp_clear(&bignumValue); mp_clear(&newValue); Tcl_SetObjResult(interp, Tcl_NewStringObj("error in mp_mul_d", -1)); return TCL_ERROR; } mp_clear(&bignumValue); if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetBignumObj(varPtr[varIndex], &newValue); } else { SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&newValue)); } break; case BIGNUM_DIV10: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } if (Tcl_GetBignumFromObj(interp, varPtr[varIndex], &bignumValue) != TCL_OK) { return TCL_ERROR; } if (mp_init(&newValue) != MP_OKAY || (mp_div_d(&bignumValue, 10, &newValue, NULL) != MP_OKAY)) { mp_clear(&bignumValue); mp_clear(&newValue); Tcl_SetObjResult(interp, Tcl_NewStringObj("error in mp_div_d", -1)); return TCL_ERROR; } mp_clear(&bignumValue); if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetBignumObj(varPtr[varIndex], &newValue); } else { SetVarToObj(varPtr, varIndex, Tcl_NewBignumObj(&newValue)); } } Tcl_SetObjResult(interp, varPtr[varIndex]); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestbooleanobjCmd -- * * This function implements the "testbooleanobj" command. It is used to * test the boolean Tcl object type implementation. * * Results: * A standard Tcl object result. * * Side effects: * Creates and frees boolean objects, and also converts objects to * have boolean type. * *---------------------------------------------------------------------- */ static int TestbooleanobjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int varIndex, boolValue; const char *index, *subCmd; Tcl_Obj **varPtr; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } varPtr = GetVarPtr(interp); subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "set") == 0) { if (objc != 4) { goto wrongNumArgs; } if (Tcl_GetBooleanFromObj(interp, objv[3], &boolValue) != TCL_OK) { return TCL_ERROR; } /* * If the object currently bound to the variable with index varIndex * has ref count 1 (i.e. the object is unshared) we can modify that * object directly. Otherwise, if RC>1 (i.e. the object is shared), * we must create a new object to modify/set and decrement the old * formerly-shared object's ref count. This is "copy on write". */ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetBooleanObj(varPtr[varIndex], boolValue); } else { SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(boolValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "get") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "not") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, varPtr[varIndex], &boolValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetBooleanObj(varPtr[varIndex], !boolValue); } else { SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(!boolValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", Tcl_GetString(objv[1]), "\": must be set, get, or not", NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TestdoubleobjCmd -- * * This function implements the "testdoubleobj" command. It is used to * test the double-precision floating point Tcl object type * implementation. * * Results: * A standard Tcl object result. * * Side effects: * Creates and frees double objects, and also converts objects to * have double type. * *---------------------------------------------------------------------- */ static int TestdoubleobjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int varIndex; double doubleValue; const char *index, *subCmd, *string; Tcl_Obj **varPtr; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } varPtr = GetVarPtr(interp); index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "set") == 0) { if (objc != 4) { goto wrongNumArgs; } string = Tcl_GetString(objv[3]); if (Tcl_GetDouble(interp, string, &doubleValue) != TCL_OK) { return TCL_ERROR; } /* * If the object currently bound to the variable with index varIndex * has ref count 1 (i.e. the object is unshared) we can modify that * object directly. Otherwise, if RC>1 (i.e. the object is shared), we * must create a new object to modify/set and decrement the old * formerly-shared object's ref count. This is "copy on write". */ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetDoubleObj(varPtr[varIndex], doubleValue); } else { SetVarToObj(varPtr, varIndex, Tcl_NewDoubleObj(doubleValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "get") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "mult10") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } if (Tcl_GetDoubleFromObj(interp, varPtr[varIndex], &doubleValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetDoubleObj(varPtr[varIndex], doubleValue * 10.0); } else { SetVarToObj(varPtr, varIndex, Tcl_NewDoubleObj(doubleValue * 10.0)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "div10") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } if (Tcl_GetDoubleFromObj(interp, varPtr[varIndex], &doubleValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetDoubleObj(varPtr[varIndex], doubleValue / 10.0); } else { SetVarToObj(varPtr, varIndex, Tcl_NewDoubleObj(doubleValue / 10.0)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", Tcl_GetString(objv[1]), "\": must be set, get, mult10, or div10", NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TestindexobjCmd -- * * This function implements the "testindexobj" command. It is used to * test the index Tcl object type implementation. * * Results: * A standard Tcl object result. * * Side effects: * Creates and frees int objects, and also converts objects to * have int type. * *---------------------------------------------------------------------- */ static int TestindexobjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int allowAbbrev, index, index2, setError, i, result; const char **argv; static const char *const tablePtr[] = {"a", "b", "check", NULL}; /* * Keep this structure declaration in sync with tclIndexObj.c */ struct IndexRep { void *tablePtr; /* Pointer to the table of strings. */ int offset; /* Offset between table entries. */ int index; /* Selected index into table. */ }; struct IndexRep *indexRep; if ((objc == 3) && (strcmp(Tcl_GetString(objv[1]), "check") == 0)) { /* * This code checks to be sure that the results of Tcl_GetIndexFromObj * are properly cached in the object and returned on subsequent * lookups. */ if (Tcl_GetIntFromObj(interp, objv[2], &index2) != TCL_OK) { return TCL_ERROR; } Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index); indexRep = objv[1]->internalRep.twoPtrValue.ptr1; indexRep->index = index2; result = Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index); if (result == TCL_OK) { Tcl_SetIntObj(Tcl_GetObjResult(interp), index); } return result; } if (objc < 5) { Tcl_AppendToObj(Tcl_GetObjResult(interp), "wrong # args", -1); return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, objv[1], &setError) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, objv[2], &allowAbbrev) != TCL_OK) { return TCL_ERROR; } argv = ckalloc((objc-3) * sizeof(char *)); for (i = 4; i < objc; i++) { argv[i-4] = Tcl_GetString(objv[i]); } argv[objc-4] = NULL; /* * Tcl_GetIndexFromObj assumes that the table is statically-allocated so * that its address is different for each index object. If we accidently * allocate a table at the same address as that cached in the index * object, clear out the object's cached state. */ if (objv[3]->typePtr != NULL && !strcmp("index", objv[3]->typePtr->name)) { indexRep = objv[3]->internalRep.twoPtrValue.ptr1; if (indexRep->tablePtr == (void *) argv) { TclFreeIntRep(objv[3]); } } result = Tcl_GetIndexFromObj((setError? interp : NULL), objv[3], argv, "token", (allowAbbrev? 0 : TCL_EXACT), &index); ckfree(argv); if (result == TCL_OK) { Tcl_SetIntObj(Tcl_GetObjResult(interp), index); } return result; } /* *---------------------------------------------------------------------- * * TestintobjCmd -- * * This function implements the "testintobj" command. It is used to * test the int Tcl object type implementation. * * Results: * A standard Tcl object result. * * Side effects: * Creates and frees int objects, and also converts objects to * have int type. * *---------------------------------------------------------------------- */ static int TestintobjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int intValue, varIndex, i; long longValue; const char *index, *subCmd, *string; Tcl_Obj **varPtr; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } varPtr = GetVarPtr(interp); index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "set") == 0) { if (objc != 4) { goto wrongNumArgs; } string = Tcl_GetString(objv[3]); if (Tcl_GetInt(interp, string, &i) != TCL_OK) { return TCL_ERROR; } intValue = i; /* * If the object currently bound to the variable with index varIndex * has ref count 1 (i.e. the object is unshared) we can modify that * object directly. Otherwise, if RC>1 (i.e. the object is shared), we * must create a new object to modify/set and decrement the old * formerly-shared object's ref count. This is "copy on write". */ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetIntObj(varPtr[varIndex], intValue); } else { SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "set2") == 0) { /* doesn't set result */ if (objc != 4) { goto wrongNumArgs; } string = Tcl_GetString(objv[3]); if (Tcl_GetInt(interp, string, &i) != TCL_OK) { return TCL_ERROR; } intValue = i; if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetIntObj(varPtr[varIndex], intValue); } else { SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue)); } } else if (strcmp(subCmd, "setlong") == 0) { if (objc != 4) { goto wrongNumArgs; } string = Tcl_GetString(objv[3]); if (Tcl_GetInt(interp, string, &i) != TCL_OK) { return TCL_ERROR; } intValue = i; if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetLongObj(varPtr[varIndex], intValue); } else { SetVarToObj(varPtr, varIndex, Tcl_NewLongObj(intValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "setmaxlong") == 0) { long maxLong = LONG_MAX; if (objc != 3) { goto wrongNumArgs; } if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetLongObj(varPtr[varIndex], maxLong); } else { SetVarToObj(varPtr, varIndex, Tcl_NewLongObj(maxLong)); } } else if (strcmp(subCmd, "ismaxlong") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } if (Tcl_GetLongFromObj(interp, varPtr[varIndex], &longValue) != TCL_OK) { return TCL_ERROR; } Tcl_AppendToObj(Tcl_GetObjResult(interp), ((longValue == LONG_MAX)? "1" : "0"), -1); } else if (strcmp(subCmd, "get") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "get2") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } string = Tcl_GetString(varPtr[varIndex]); Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1); } else if (strcmp(subCmd, "inttoobigtest") == 0) { /* * If long ints have more bits than ints on this platform, verify that * Tcl_GetIntFromObj returns an error if the long int held in an * integer object's internal representation is too large to fit in an * int. */ if (objc != 3) { goto wrongNumArgs; } #if (INT_MAX == LONG_MAX) /* int is same size as long int */ Tcl_AppendToObj(Tcl_GetObjResult(interp), "1", -1); #else if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetLongObj(varPtr[varIndex], LONG_MAX); } else { SetVarToObj(varPtr, varIndex, Tcl_NewLongObj(LONG_MAX)); } if (Tcl_GetIntFromObj(interp, varPtr[varIndex], &i) != TCL_OK) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "1", -1); return TCL_OK; } Tcl_AppendToObj(Tcl_GetObjResult(interp), "0", -1); #endif } else if (strcmp(subCmd, "mult10") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, varPtr[varIndex], &intValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetIntObj(varPtr[varIndex], intValue * 10); } else { SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue * 10)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "div10") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, varPtr[varIndex], &intValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetIntObj(varPtr[varIndex], intValue / 10); } else { SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue / 10)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", Tcl_GetString(objv[1]), "\": must be set, get, get2, mult10, or div10", NULL); return TCL_ERROR; } return TCL_OK; } /* *----------------------------------------------------------------------------- * * TestlistobjCmd -- * * This function implements the 'testlistobj' command. It is used to * test a few possible corner cases in list object manipulation from * C code that cannot occur at the Tcl level. * * Results: * A standard Tcl object result. * * Side effects: * Creates, manipulates and frees list objects. * *----------------------------------------------------------------------------- */ static int TestlistobjCmd( ClientData clientData, /* Not used */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Number of arguments */ Tcl_Obj *const objv[]) /* Argument objects */ { /* Subcommands supported by this command */ const char* subcommands[] = { "set", "get", "replace" }; enum listobjCmdIndex { LISTOBJ_SET, LISTOBJ_GET, LISTOBJ_REPLACE }; const char* index; /* Argument giving the variable number */ int varIndex; /* Variable number converted to binary */ int cmdIndex; /* Ordinal number of the subcommand */ int first; /* First index in the list */ int count; /* Count of elements in a list */ Tcl_Obj **varPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg...?"); return TCL_ERROR; } varPtr = GetVarPtr(interp); index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "command", 0, &cmdIndex) != TCL_OK) { return TCL_ERROR; } switch(cmdIndex) { case LISTOBJ_SET: if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetListObj(varPtr[varIndex], objc-3, objv+3); } else { SetVarToObj(varPtr, varIndex, Tcl_NewListObj(objc-3, objv+3)); } Tcl_SetObjResult(interp, varPtr[varIndex]); break; case LISTOBJ_GET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); break; case LISTOBJ_REPLACE: if (objc < 5) { Tcl_WrongNumArgs(interp, 2, objv, "varIndex start count ?element...?"); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[3], &first) != TCL_OK || Tcl_GetIntFromObj(interp, objv[4], &count) != TCL_OK) { return TCL_ERROR; } if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } Tcl_ResetResult(interp); return Tcl_ListObjReplace(interp, varPtr[varIndex], first, count, objc-5, objv+5); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TestobjCmd -- * * This function implements the "testobj" command. It is used to test * the type-independent portions of the Tcl object type implementation. * * Results: * A standard Tcl object result. * * Side effects: * Creates and frees objects. * *---------------------------------------------------------------------- */ static int TestobjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int varIndex, destIndex, i; const char *index, *subCmd, *string; const Tcl_ObjType *targetType; Tcl_Obj **varPtr; if (objc < 2) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } varPtr = GetVarPtr(interp); subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "assign") == 0) { if (objc != 4) { goto wrongNumArgs; } index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } string = Tcl_GetString(objv[3]); if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) { return TCL_ERROR; } SetVarToObj(varPtr, destIndex, varPtr[varIndex]); Tcl_SetObjResult(interp, varPtr[destIndex]); } else if (strcmp(subCmd, "bug3598580") == 0) { Tcl_Obj *listObjPtr, *elemObjPtr; if (objc != 2) { goto wrongNumArgs; } elemObjPtr = Tcl_NewIntObj(123); listObjPtr = Tcl_NewListObj(1, &elemObjPtr); /* Replace the single list element through itself, nonsense but legal. */ Tcl_ListObjReplace(interp, listObjPtr, 0, 1, 1, &elemObjPtr); Tcl_SetObjResult(interp, listObjPtr); return TCL_OK; } else if (strcmp(subCmd, "convert") == 0) { const char *typeName; if (objc != 4) { goto wrongNumArgs; } index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } typeName = Tcl_GetString(objv[3]); if ((targetType = Tcl_GetObjType(typeName)) == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no type ", typeName, " found", NULL); return TCL_ERROR; } if (Tcl_ConvertToType(interp, varPtr[varIndex], targetType) != TCL_OK) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "duplicate") == 0) { if (objc != 4) { goto wrongNumArgs; } index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } string = Tcl_GetString(objv[3]); if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) { return TCL_ERROR; } SetVarToObj(varPtr, destIndex, Tcl_DuplicateObj(varPtr[varIndex])); Tcl_SetObjResult(interp, varPtr[destIndex]); } else if (strcmp(subCmd, "freeallvars") == 0) { if (objc != 2) { goto wrongNumArgs; } for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) { if (varPtr[i] != NULL) { Tcl_DecrRefCount(varPtr[i]); varPtr[i] = NULL; } } } else if (strcmp(subCmd, "invalidateStringRep") == 0) { if (objc != 3) { goto wrongNumArgs; } index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } Tcl_InvalidateStringRep(varPtr[varIndex]); Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "newobj") == 0) { if (objc != 3) { goto wrongNumArgs; } index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } SetVarToObj(varPtr, varIndex, Tcl_NewObj()); Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "objtype") == 0) { const char *typeName; /* * Return an object containing the name of the argument's type of * internal rep. If none exists, return "none". */ if (objc != 3) { goto wrongNumArgs; } if (objv[2]->typePtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1)); } else { typeName = objv[2]->typePtr->name; Tcl_SetObjResult(interp, Tcl_NewStringObj(typeName, -1)); } } else if (strcmp(subCmd, "refcount") == 0) { if (objc != 3) { goto wrongNumArgs; } index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(varPtr[varIndex]->refCount)); } else if (strcmp(subCmd, "type") == 0) { if (objc != 3) { goto wrongNumArgs; } index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } if (varPtr[varIndex]->typePtr == NULL) { /* a string! */ Tcl_AppendToObj(Tcl_GetObjResult(interp), "string", -1); } else { Tcl_AppendToObj(Tcl_GetObjResult(interp), varPtr[varIndex]->typePtr->name, -1); } } else if (strcmp(subCmd, "types") == 0) { if (objc != 2) { goto wrongNumArgs; } if (Tcl_AppendAllObjTypes(interp, Tcl_GetObjResult(interp)) != TCL_OK) { return TCL_ERROR; } } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", Tcl_GetString(objv[1]), "\": must be assign, convert, duplicate, freeallvars, " "newobj, objcount, objtype, refcount, type, or types", NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TeststringobjCmd -- * * This function implements the "teststringobj" command. It is used to * test the string Tcl object type implementation. * * Results: * A standard Tcl object result. * * Side effects: * Creates and frees string objects, and also converts objects to * have string type. * *---------------------------------------------------------------------- */ static int TeststringobjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_UniChar *unicode; int varIndex, option, i, length; #define MAX_STRINGS 11 const char *index, *string, *strings[MAX_STRINGS+1]; TestString *strPtr; Tcl_Obj **varPtr; static const char *const options[] = { "append", "appendstrings", "get", "get2", "length", "length2", "set", "set2", "setlength", "maxchars", "getunicode", "appendself", "appendself2", NULL }; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } varPtr = GetVarPtr(interp); index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &option) != TCL_OK) { return TCL_ERROR; } switch (option) { case 0: /* append */ if (objc != 5) { goto wrongNumArgs; } if (Tcl_GetIntFromObj(interp, objv[4], &length) != TCL_OK) { return TCL_ERROR; } if (varPtr[varIndex] == NULL) { SetVarToObj(varPtr, varIndex, Tcl_NewObj()); } /* * If the object bound to variable "varIndex" is shared, we must * "copy on write" and append to a copy of the object. */ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } string = Tcl_GetString(objv[3]); Tcl_AppendToObj(varPtr[varIndex], string, length); Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 1: /* appendstrings */ if (objc > (MAX_STRINGS+3)) { goto wrongNumArgs; } if (varPtr[varIndex] == NULL) { SetVarToObj(varPtr, varIndex, Tcl_NewObj()); } /* * If the object bound to variable "varIndex" is shared, we must * "copy on write" and append to a copy of the object. */ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } for (i = 3; i < objc; i++) { strings[i-3] = Tcl_GetString(objv[i]); } for ( ; i < 12 + 3; i++) { strings[i - 3] = NULL; } Tcl_AppendStringsToObj(varPtr[varIndex], strings[0], strings[1], strings[2], strings[3], strings[4], strings[5], strings[6], strings[7], strings[8], strings[9], strings[10], strings[11]); Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 2: /* get */ if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 3: /* get2 */ if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr, varIndex)) { return TCL_ERROR; } string = Tcl_GetString(varPtr[varIndex]); Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1); break; case 4: /* length */ if (objc != 3) { goto wrongNumArgs; } Tcl_SetIntObj(Tcl_GetObjResult(interp), (varPtr[varIndex] != NULL) ? varPtr[varIndex]->length : -1); break; case 5: /* length2 */ if (objc != 3) { goto wrongNumArgs; } if (varPtr[varIndex] != NULL) { Tcl_ConvertToType(NULL, varPtr[varIndex], Tcl_GetObjType("string")); strPtr = varPtr[varIndex]->internalRep.twoPtrValue.ptr1; length = (int) strPtr->allocated; } else { length = -1; } Tcl_SetIntObj(Tcl_GetObjResult(interp), length); break; case 6: /* set */ if (objc != 4) { goto wrongNumArgs; } /* * If the object currently bound to the variable with index * varIndex has ref count 1 (i.e. the object is unshared) we can * modify that object directly. Otherwise, if RC>1 (i.e. the * object is shared), we must create a new object to modify/set * and decrement the old formerly-shared object's ref count. This * is "copy on write". */ string = Tcl_GetStringFromObj(objv[3], &length); if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetStringObj(varPtr[varIndex], string, length); } else { SetVarToObj(varPtr, varIndex, Tcl_NewStringObj(string, length)); } Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 7: /* set2 */ if (objc != 4) { goto wrongNumArgs; } SetVarToObj(varPtr, varIndex, objv[3]); break; case 8: /* setlength */ if (objc != 4) { goto wrongNumArgs; } if (Tcl_GetIntFromObj(interp, objv[3], &length) != TCL_OK) { return TCL_ERROR; } if (varPtr[varIndex] != NULL) { Tcl_SetObjLength(varPtr[varIndex], length); } break; case 9: /* maxchars */ if (objc != 3) { goto wrongNumArgs; } if (varPtr[varIndex] != NULL) { Tcl_ConvertToType(NULL, varPtr[varIndex], Tcl_GetObjType("string")); strPtr = varPtr[varIndex]->internalRep.twoPtrValue.ptr1; length = strPtr->maxChars; } else { length = -1; } Tcl_SetIntObj(Tcl_GetObjResult(interp), length); break; case 10: /* getunicode */ if (objc != 3) { goto wrongNumArgs; } Tcl_GetUnicodeFromObj(varPtr[varIndex], NULL); break; case 11: /* appendself */ if (objc != 4) { goto wrongNumArgs; } if (varPtr[varIndex] == NULL) { SetVarToObj(varPtr, varIndex, Tcl_NewObj()); } /* * If the object bound to variable "varIndex" is shared, we must * "copy on write" and append to a copy of the object. */ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } string = Tcl_GetStringFromObj(varPtr[varIndex], &length); if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) { return TCL_ERROR; } if ((i < 0) || (i > length)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "index value out of range", -1)); return TCL_ERROR; } Tcl_AppendToObj(varPtr[varIndex], string + i, length - i); Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 12: /* appendself2 */ if (objc != 4) { goto wrongNumArgs; } if (varPtr[varIndex] == NULL) { SetVarToObj(varPtr, varIndex, Tcl_NewObj()); } /* * If the object bound to variable "varIndex" is shared, we must * "copy on write" and append to a copy of the object. */ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varPtr, varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } unicode = Tcl_GetUnicodeFromObj(varPtr[varIndex], &length); if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) { return TCL_ERROR; } if ((i < 0) || (i > length)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "index value out of range", -1)); return TCL_ERROR; } Tcl_AppendUnicodeToObj(varPtr[varIndex], unicode + i, length - i); Tcl_SetObjResult(interp, varPtr[varIndex]); break; } return TCL_OK; } /* *---------------------------------------------------------------------- * * SetVarToObj -- * * Utility routine to assign a Tcl_Obj* to a test variable. The * Tcl_Obj* can be NULL. * * Results: * None. * * Side effects: * This routine handles ref counting details for assignment: i.e. the old * value's ref count must be decremented (if not NULL) and the new one * incremented (also if not NULL). * *---------------------------------------------------------------------- */ static void SetVarToObj( Tcl_Obj **varPtr, int varIndex, /* Designates the assignment variable. */ Tcl_Obj *objPtr) /* Points to object to assign to var. */ { if (varPtr[varIndex] != NULL) { Tcl_DecrRefCount(varPtr[varIndex]); } varPtr[varIndex] = objPtr; if (objPtr != NULL) { Tcl_IncrRefCount(objPtr); } } /* *---------------------------------------------------------------------- * * GetVariableIndex -- * * Utility routine to get a test variable index from the command line. * * Results: * A standard Tcl object result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int GetVariableIndex( Tcl_Interp *interp, /* Interpreter for error reporting. */ const char *string, /* String containing a variable index * specified as a nonnegative number less than * NUMBER_OF_OBJECT_VARS. */ int *indexPtr) /* Place to store converted result. */ { int index; if (Tcl_GetInt(interp, string, &index) != TCL_OK) { return TCL_ERROR; } if (index < 0 || index >= NUMBER_OF_OBJECT_VARS) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "bad variable index", -1); return TCL_ERROR; } *indexPtr = index; return TCL_OK; } /* *---------------------------------------------------------------------- * * CheckIfVarUnset -- * * Utility function that checks whether a test variable is readable: * i.e., that varPtr[varIndex] is non-NULL. * * Results: * 1 if the test variable is unset (NULL); 0 otherwise. * * Side effects: * Sets the interpreter result to an error message if the variable is * unset (NULL). * *---------------------------------------------------------------------- */ static int CheckIfVarUnset( Tcl_Interp *interp, /* Interpreter for error reporting. */ Tcl_Obj ** varPtr, int varIndex) /* Index of the test variable to check. */ { if (varPtr[varIndex] == NULL) { char buf[32 + TCL_INTEGER_SPACE]; sprintf(buf, "variable %d is unset (NULL)", varIndex); Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); return 1; } return 0; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclCompCmdsSZ.c0000644000175000017500000036214712663660065016051 0ustar sergeisergei/* * tclCompCmdsSZ.c -- * * This file contains compilation procedures that compile various Tcl * commands (beginning with the letters 's' through 'z', except for * [upvar] and [variable]) into a sequence of instructions ("bytecodes"). * Also includes the operator command compilers. * * Copyright (c) 1997-1998 Sun Microsystems, Inc. * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2002 ActiveState Corporation. * Copyright (c) 2004-2010 by Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" #include "tclStringTrim.h" /* * Prototypes for procedures defined later in this file: */ static ClientData DupJumptableInfo(ClientData clientData); static void FreeJumptableInfo(ClientData clientData); static void PrintJumptableInfo(ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); static void DisassembleJumptableInfo(ClientData clientData, Tcl_Obj *dictObj, ByteCode *codePtr, unsigned int pcOffset); static int CompileAssociativeBinaryOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, const char *identity, int instruction, CompileEnv *envPtr); static int CompileComparisonOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, int instruction, CompileEnv *envPtr); static int CompileStrictlyBinaryOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, int instruction, CompileEnv *envPtr); static int CompileUnaryOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, int instruction, CompileEnv *envPtr); static void IssueSwitchChainedTests(Tcl_Interp *interp, CompileEnv *envPtr, int mode, int noCase, int valueIndex, int numWords, Tcl_Token **bodyToken, int *bodyLines, int **bodyNext); static void IssueSwitchJumpTable(Tcl_Interp *interp, CompileEnv *envPtr, int valueIndex, int numWords, Tcl_Token **bodyToken, int *bodyLines, int **bodyContLines); static int IssueTryClausesInstructions(Tcl_Interp *interp, CompileEnv *envPtr, Tcl_Token *bodyToken, int numHandlers, int *matchCodes, Tcl_Obj **matchClauses, int *resultVarIndices, int *optionVarIndices, Tcl_Token **handlerTokens); static int IssueTryClausesFinallyInstructions(Tcl_Interp *interp, CompileEnv *envPtr, Tcl_Token *bodyToken, int numHandlers, int *matchCodes, Tcl_Obj **matchClauses, int *resultVarIndices, int *optionVarIndices, Tcl_Token **handlerTokens, Tcl_Token *finallyToken); static int IssueTryFinallyInstructions(Tcl_Interp *interp, CompileEnv *envPtr, Tcl_Token *bodyToken, Tcl_Token *finallyToken); /* * The structures below define the AuxData types defined in this file. */ const AuxDataType tclJumptableInfoType = { "JumptableInfo", /* name */ DupJumptableInfo, /* dupProc */ FreeJumptableInfo, /* freeProc */ PrintJumptableInfo, /* printProc */ DisassembleJumptableInfo /* disassembleProc */ }; /* * Shorthand macros for instruction issuing. */ #define OP(name) TclEmitOpcode(INST_##name, envPtr) #define OP1(name,val) TclEmitInstInt1(INST_##name,(val),envPtr) #define OP4(name,val) TclEmitInstInt4(INST_##name,(val),envPtr) #define OP14(name,val1,val2) \ TclEmitInstInt1(INST_##name,(val1),envPtr);TclEmitInt4((val2),envPtr) #define OP44(name,val1,val2) \ TclEmitInstInt4(INST_##name,(val1),envPtr);TclEmitInt4((val2),envPtr) #define PUSH(str) \ PushStringLiteral(envPtr, str) #define JUMP4(name,var) \ (var) = CurrentOffset(envPtr);TclEmitInstInt4(INST_##name##4,0,envPtr) #define FIXJUMP4(var) \ TclStoreInt4AtPtr(CurrentOffset(envPtr)-(var),envPtr->codeStart+(var)+1) #define JUMP1(name,var) \ (var) = CurrentOffset(envPtr);TclEmitInstInt1(INST_##name##1,0,envPtr) #define FIXJUMP1(var) \ TclStoreInt1AtPtr(CurrentOffset(envPtr)-(var),envPtr->codeStart+(var)+1) #define LOAD(idx) \ if ((idx)<256) {OP1(LOAD_SCALAR1,(idx));} else {OP4(LOAD_SCALAR4,(idx));} #define STORE(idx) \ if ((idx)<256) {OP1(STORE_SCALAR1,(idx));} else {OP4(STORE_SCALAR4,(idx));} #define INVOKE(name) \ TclEmitInvoke(envPtr,INST_##name) #define INDEX_END (-2) /* *---------------------------------------------------------------------- * * GetIndexFromToken -- * * Parse a token and get the encoded version of the index (as understood * by TEBC), assuming it is at all knowable at compile time. Only handles * indices that are integers or 'end' or 'end-integer'. * * Returns: * TCL_OK if parsing succeeded, and TCL_ERROR if it failed. * * Side effects: * Sets *index to the index value if successful. * *---------------------------------------------------------------------- */ static inline int GetIndexFromToken( Tcl_Token *tokenPtr, int *index) { Tcl_Obj *tmpObj = Tcl_NewObj(); int result, idx; if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) { Tcl_DecrRefCount(tmpObj); return TCL_ERROR; } result = TclGetIntFromObj(NULL, tmpObj, &idx); if (result == TCL_OK) { if (idx < 0) { result = TCL_ERROR; } } else { result = TclGetIntForIndexM(NULL, tmpObj, INDEX_END, &idx); if (result == TCL_OK && idx > INDEX_END) { result = TCL_ERROR; } } Tcl_DecrRefCount(tmpObj); if (result == TCL_OK) { *index = idx; } return result; } /* *---------------------------------------------------------------------- * * TclCompileSetCmd -- * * Procedure called to compile the "set" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "set" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileSetCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *varTokenPtr, *valueTokenPtr; int isAssignment, isScalar, localIndex, numWords; DefineLineInformation; /* TIP #280 */ numWords = parsePtr->numWords; if ((numWords != 2) && (numWords != 3)) { return TCL_ERROR; } isAssignment = (numWords == 3); /* * Decide if we can use a frame slot for the var/array name or if we need * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarNameWord(interp, varTokenPtr, envPtr, 0, &localIndex, &isScalar, 1); /* * If we are doing an assignment, push the new value. */ if (isAssignment) { valueTokenPtr = TokenAfter(varTokenPtr); CompileWord(envPtr, valueTokenPtr, interp, 2); } /* * Emit instructions to set/get the variable. */ if (isScalar) { if (localIndex < 0) { TclEmitOpcode((isAssignment? INST_STORE_STK : INST_LOAD_STK), envPtr); } else if (localIndex <= 255) { TclEmitInstInt1((isAssignment? INST_STORE_SCALAR1 : INST_LOAD_SCALAR1), localIndex, envPtr); } else { TclEmitInstInt4((isAssignment? INST_STORE_SCALAR4 : INST_LOAD_SCALAR4), localIndex, envPtr); } } else { if (localIndex < 0) { TclEmitOpcode((isAssignment? INST_STORE_ARRAY_STK : INST_LOAD_ARRAY_STK), envPtr); } else if (localIndex <= 255) { TclEmitInstInt1((isAssignment? INST_STORE_ARRAY1 : INST_LOAD_ARRAY1), localIndex, envPtr); } else { TclEmitInstInt4((isAssignment? INST_STORE_ARRAY4 : INST_LOAD_ARRAY4), localIndex, envPtr); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileString*Cmd -- * * Procedures called to compile various subcommands of the "string" * command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "string" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileStringCatCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { int i, numWords = parsePtr->numWords, numArgs; Tcl_Token *wordTokenPtr; Tcl_Obj *obj, *folded; DefineLineInformation; /* TIP #280 */ /* Trivial case, no arg */ if (numWords<2) { PushStringLiteral(envPtr, ""); return TCL_OK; } /* General case: issue CONCAT1's (by chunks of 254 if needed), folding contiguous constants along the way */ numArgs = 0; folded = NULL; wordTokenPtr = TokenAfter(parsePtr->tokenPtr); for (i = 1; i < numWords; i++) { obj = Tcl_NewObj(); if (TclWordKnownAtCompileTime(wordTokenPtr, obj)) { if (folded) { Tcl_AppendObjToObj(folded, obj); Tcl_DecrRefCount(obj); } else { folded = obj; } } else { Tcl_DecrRefCount(obj); if (folded) { int len; const char *bytes = Tcl_GetStringFromObj(folded, &len); PushLiteral(envPtr, bytes, len); Tcl_DecrRefCount(folded); folded = NULL; numArgs ++; } CompileWord(envPtr, wordTokenPtr, interp, i); numArgs ++; if (numArgs >= 254) { /* 254 to take care of the possible +1 of "folded" above */ TclEmitInstInt1(INST_STR_CONCAT1, numArgs, envPtr); numArgs = 1; /* concat pushes 1 obj, the result */ } } wordTokenPtr = TokenAfter(wordTokenPtr); } if (folded) { int len; const char *bytes = Tcl_GetStringFromObj(folded, &len); PushLiteral(envPtr, bytes, len); Tcl_DecrRefCount(folded); folded = NULL; numArgs ++; } if (numArgs > 1) { TclEmitInstInt1(INST_STR_CONCAT1, numArgs, envPtr); } return TCL_OK; } int TclCompileStringCmpCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; /* * We don't support any flags; the bytecode isn't that sophisticated. */ if (parsePtr->numWords != 3) { return TCL_ERROR; } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); TclEmitOpcode(INST_STR_CMP, envPtr); return TCL_OK; } int TclCompileStringEqualCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; /* * We don't support any flags; the bytecode isn't that sophisticated. */ if (parsePtr->numWords != 3) { return TCL_ERROR; } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); TclEmitOpcode(INST_STR_EQ, envPtr); return TCL_OK; } int TclCompileStringFirstCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; /* * We don't support any flags; the bytecode isn't that sophisticated. */ if (parsePtr->numWords != 3) { return TCL_ERROR; } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); OP(STR_FIND); return TCL_OK; } int TclCompileStringLastCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; /* * We don't support any flags; the bytecode isn't that sophisticated. */ if (parsePtr->numWords != 3) { return TCL_ERROR; } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); OP(STR_FIND_LAST); return TCL_OK; } int TclCompileStringIndexCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; if (parsePtr->numWords != 3) { return TCL_ERROR; } /* * Push the two operands onto the stack and then the index operation. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); TclEmitOpcode(INST_STR_INDEX, envPtr); return TCL_OK; } int TclCompileStringIsCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); static const char *const isClasses[] = { "alnum", "alpha", "ascii", "control", "boolean", "digit", "double", "entier", "false", "graph", "integer", "list", "lower", "print", "punct", "space", "true", "upper", "wideinteger", "wordchar", "xdigit", NULL }; enum isClasses { STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL, STR_IS_BOOL, STR_IS_DIGIT, STR_IS_DOUBLE, STR_IS_ENTIER, STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT, STR_IS_LIST, STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT, STR_IS_SPACE, STR_IS_TRUE, STR_IS_UPPER, STR_IS_WIDE, STR_IS_WORD, STR_IS_XDIGIT }; int t, range, allowEmpty = 0, end; InstStringClassType strClassType; Tcl_Obj *isClass; if (parsePtr->numWords < 3 || parsePtr->numWords > 6) { return TCL_ERROR; } isClass = Tcl_NewObj(); if (!TclWordKnownAtCompileTime(tokenPtr, isClass)) { Tcl_DecrRefCount(isClass); return TCL_ERROR; } else if (Tcl_GetIndexFromObj(interp, isClass, isClasses, "class", 0, &t) != TCL_OK) { Tcl_DecrRefCount(isClass); TclCompileSyntaxError(interp, envPtr); return TCL_OK; } Tcl_DecrRefCount(isClass); #define GotLiteral(tokenPtr, word) \ ((tokenPtr)->type == TCL_TOKEN_SIMPLE_WORD && \ (tokenPtr)[1].size > 1 && \ (tokenPtr)[1].start[0] == word[0] && \ strncmp((tokenPtr)[1].start, (word), (tokenPtr)[1].size) == 0) /* * Cannot handle the -failindex option at all, and that's the only legal * way to have more than 4 arguments. */ if (parsePtr->numWords != 3 && parsePtr->numWords != 4) { return TCL_ERROR; } tokenPtr = TokenAfter(tokenPtr); if (parsePtr->numWords == 3) { allowEmpty = 1; } else { if (!GotLiteral(tokenPtr, "-strict")) { return TCL_ERROR; } tokenPtr = TokenAfter(tokenPtr); } #undef GotLiteral /* * Compile the code. There are several main classes of check here. * 1. Character classes * 2. Booleans * 3. Integers * 4. Floats * 5. Lists */ CompileWord(envPtr, tokenPtr, interp, parsePtr->numWords-1); switch ((enum isClasses) t) { case STR_IS_ALNUM: strClassType = STR_CLASS_ALNUM; goto compileStrClass; case STR_IS_ALPHA: strClassType = STR_CLASS_ALPHA; goto compileStrClass; case STR_IS_ASCII: strClassType = STR_CLASS_ASCII; goto compileStrClass; case STR_IS_CONTROL: strClassType = STR_CLASS_CONTROL; goto compileStrClass; case STR_IS_DIGIT: strClassType = STR_CLASS_DIGIT; goto compileStrClass; case STR_IS_GRAPH: strClassType = STR_CLASS_GRAPH; goto compileStrClass; case STR_IS_LOWER: strClassType = STR_CLASS_LOWER; goto compileStrClass; case STR_IS_PRINT: strClassType = STR_CLASS_PRINT; goto compileStrClass; case STR_IS_PUNCT: strClassType = STR_CLASS_PUNCT; goto compileStrClass; case STR_IS_SPACE: strClassType = STR_CLASS_SPACE; goto compileStrClass; case STR_IS_UPPER: strClassType = STR_CLASS_UPPER; goto compileStrClass; case STR_IS_WORD: strClassType = STR_CLASS_WORD; goto compileStrClass; case STR_IS_XDIGIT: strClassType = STR_CLASS_XDIGIT; compileStrClass: if (allowEmpty) { OP1( STR_CLASS, strClassType); } else { int over, over2; OP( DUP); OP1( STR_CLASS, strClassType); JUMP1( JUMP_TRUE, over); OP( POP); PUSH( "0"); JUMP1( JUMP, over2); FIXJUMP1(over); PUSH( ""); OP( STR_NEQ); FIXJUMP1(over2); } return TCL_OK; case STR_IS_BOOL: case STR_IS_FALSE: case STR_IS_TRUE: OP( TRY_CVT_TO_BOOLEAN); switch (t) { int over, over2; case STR_IS_BOOL: if (allowEmpty) { JUMP1( JUMP_TRUE, over); PUSH( ""); OP( STR_EQ); JUMP1( JUMP, over2); FIXJUMP1(over); OP( POP); PUSH( "1"); FIXJUMP1(over2); } else { OP4( REVERSE, 2); OP( POP); } return TCL_OK; case STR_IS_TRUE: JUMP1( JUMP_TRUE, over); if (allowEmpty) { PUSH( ""); OP( STR_EQ); } else { OP( POP); PUSH( "0"); } FIXJUMP1( over); OP( LNOT); OP( LNOT); return TCL_OK; case STR_IS_FALSE: JUMP1( JUMP_TRUE, over); if (allowEmpty) { PUSH( ""); OP( STR_NEQ); } else { OP( POP); PUSH( "1"); } FIXJUMP1( over); OP( LNOT); return TCL_OK; } case STR_IS_DOUBLE: { int satisfied, isEmpty; if (allowEmpty) { OP( DUP); PUSH( ""); OP( STR_EQ); JUMP1( JUMP_TRUE, isEmpty); OP( NUM_TYPE); JUMP1( JUMP_TRUE, satisfied); PUSH( "0"); JUMP1( JUMP, end); FIXJUMP1( isEmpty); OP( POP); FIXJUMP1( satisfied); } else { OP( NUM_TYPE); JUMP1( JUMP_TRUE, satisfied); PUSH( "0"); JUMP1( JUMP, end); TclAdjustStackDepth(-1, envPtr); FIXJUMP1( satisfied); } PUSH( "1"); FIXJUMP1( end); return TCL_OK; } case STR_IS_INT: case STR_IS_WIDE: case STR_IS_ENTIER: if (allowEmpty) { int testNumType; OP( DUP); OP( NUM_TYPE); OP( DUP); JUMP1( JUMP_TRUE, testNumType); OP( POP); PUSH( ""); OP( STR_EQ); JUMP1( JUMP, end); TclAdjustStackDepth(1, envPtr); FIXJUMP1( testNumType); OP4( REVERSE, 2); OP( POP); } else { OP( NUM_TYPE); OP( DUP); JUMP1( JUMP_FALSE, end); } switch (t) { case STR_IS_INT: PUSH( "1"); OP( EQ); break; case STR_IS_WIDE: PUSH( "2"); OP( LE); break; case STR_IS_ENTIER: PUSH( "3"); OP( LE); break; } FIXJUMP1( end); return TCL_OK; case STR_IS_LIST: range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); OP4( BEGIN_CATCH4, range); ExceptionRangeStarts(envPtr, range); OP( DUP); OP( LIST_LENGTH); OP( POP); ExceptionRangeEnds(envPtr, range); ExceptionRangeTarget(envPtr, range, catchOffset); OP( POP); OP( PUSH_RETURN_CODE); OP( END_CATCH); OP( LNOT); return TCL_OK; } return TclCompileBasicMin0ArgCmd(interp, parsePtr, cmdPtr, envPtr); } int TclCompileStringMatchCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; int i, length, exactMatch = 0, nocase = 0; const char *str; if (parsePtr->numWords < 3 || parsePtr->numWords > 4) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); /* * Check if we have a -nocase flag. */ if (parsePtr->numWords == 4) { if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } str = tokenPtr[1].start; length = tokenPtr[1].size; if ((length <= 1) || strncmp(str, "-nocase", (size_t) length)) { /* * Fail at run time, not in compilation. */ return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } nocase = 1; tokenPtr = TokenAfter(tokenPtr); } /* * Push the strings to match against each other. */ for (i = 0; i < 2; i++) { if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { str = tokenPtr[1].start; length = tokenPtr[1].size; if (!nocase && (i == 0)) { /* * Trivial matches can be done by 'string equal'. If -nocase * was specified, we can't do this because INST_STR_EQ has no * support for nocase. */ Tcl_Obj *copy = Tcl_NewStringObj(str, length); Tcl_IncrRefCount(copy); exactMatch = TclMatchIsTrivial(TclGetString(copy)); TclDecrRefCount(copy); } PushLiteral(envPtr, str, length); } else { SetLineInformation(i+1+nocase); CompileTokens(envPtr, tokenPtr, interp); } tokenPtr = TokenAfter(tokenPtr); } /* * Push the matcher. */ if (exactMatch) { TclEmitOpcode(INST_STR_EQ, envPtr); } else { TclEmitInstInt1(INST_STR_MATCH, nocase, envPtr); } return TCL_OK; } int TclCompileStringLenCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; Tcl_Obj *objPtr; if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); TclNewObj(objPtr); if (TclWordKnownAtCompileTime(tokenPtr, objPtr)) { /* * Here someone is asking for the length of a static string (or * something with backslashes). Just push the actual character (not * byte) length. */ char buf[TCL_INTEGER_SPACE]; int len = Tcl_GetCharLength(objPtr); len = sprintf(buf, "%d", len); PushLiteral(envPtr, buf, len); } else { SetLineInformation(1); CompileTokens(envPtr, tokenPtr, interp); TclEmitOpcode(INST_STR_LEN, envPtr); } TclDecrRefCount(objPtr); return TCL_OK; } int TclCompileStringMapCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *mapTokenPtr, *stringTokenPtr; Tcl_Obj *mapObj, **objv; char *bytes; int len; /* * We only handle the case: * * string map {foo bar} $thing * * That is, a literal two-element list (doesn't need to be brace-quoted, * but does need to be compile-time knowable) and any old argument (the * thing to map). */ if (parsePtr->numWords != 3) { return TCL_ERROR; } mapTokenPtr = TokenAfter(parsePtr->tokenPtr); stringTokenPtr = TokenAfter(mapTokenPtr); mapObj = Tcl_NewObj(); Tcl_IncrRefCount(mapObj); if (!TclWordKnownAtCompileTime(mapTokenPtr, mapObj)) { Tcl_DecrRefCount(mapObj); return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } else if (Tcl_ListObjGetElements(NULL, mapObj, &len, &objv) != TCL_OK) { Tcl_DecrRefCount(mapObj); return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } else if (len != 2) { Tcl_DecrRefCount(mapObj); return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Now issue the opcodes. Note that in the case that we know that the * first word is an empty word, we don't issue the map at all. That is the * correct semantics for mapping. */ bytes = Tcl_GetStringFromObj(objv[0], &len); if (len == 0) { CompileWord(envPtr, stringTokenPtr, interp, 2); } else { PushLiteral(envPtr, bytes, len); bytes = Tcl_GetStringFromObj(objv[1], &len); PushLiteral(envPtr, bytes, len); CompileWord(envPtr, stringTokenPtr, interp, 2); OP(STR_MAP); } Tcl_DecrRefCount(mapObj); return TCL_OK; } int TclCompileStringRangeCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *stringTokenPtr, *fromTokenPtr, *toTokenPtr; int idx1, idx2; if (parsePtr->numWords != 4) { return TCL_ERROR; } stringTokenPtr = TokenAfter(parsePtr->tokenPtr); fromTokenPtr = TokenAfter(stringTokenPtr); toTokenPtr = TokenAfter(fromTokenPtr); /* * Parse the two indices. */ if (GetIndexFromToken(fromTokenPtr, &idx1) != TCL_OK) { goto nonConstantIndices; } if (GetIndexFromToken(toTokenPtr, &idx2) != TCL_OK) { goto nonConstantIndices; } /* * Push the operand onto the stack and then the substring operation. */ CompileWord(envPtr, stringTokenPtr, interp, 1); OP44( STR_RANGE_IMM, idx1, idx2); return TCL_OK; /* * Push the operands onto the stack and then the substring operation. */ nonConstantIndices: CompileWord(envPtr, stringTokenPtr, interp, 1); CompileWord(envPtr, fromTokenPtr, interp, 2); CompileWord(envPtr, toTokenPtr, interp, 3); OP( STR_RANGE); return TCL_OK; } int TclCompileStringReplaceCmd( Tcl_Interp *interp, /* Tcl interpreter for context. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the * command. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds the resulting instructions. */ { Tcl_Token *tokenPtr, *valueTokenPtr, *replacementTokenPtr = NULL; DefineLineInformation; /* TIP #280 */ int idx1, idx2; if (parsePtr->numWords < 4 || parsePtr->numWords > 5) { return TCL_ERROR; } valueTokenPtr = TokenAfter(parsePtr->tokenPtr); if (parsePtr->numWords == 5) { tokenPtr = TokenAfter(valueTokenPtr); tokenPtr = TokenAfter(tokenPtr); replacementTokenPtr = TokenAfter(tokenPtr); } /* * Parse the indices. Will only compile special cases if both are * constants and not an _integer_ less than zero (since we reserve * negative indices here for end-relative indexing) or an end-based index * greater than 'end' itself. */ tokenPtr = TokenAfter(valueTokenPtr); if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) { goto genericReplace; } tokenPtr = TokenAfter(tokenPtr); if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) { goto genericReplace; } /* * We handle these replacements specially: first character (where * idx1=idx2=0) and last character (where idx1=idx2=INDEX_END). Anything * else and the semantics get rather screwy. */ if (idx1 == 0 && idx2 == 0) { int notEq, end; /* * Just working with the first character. */ CompileWord(envPtr, valueTokenPtr, interp, 1); if (replacementTokenPtr == NULL) { /* Drop first */ OP44( STR_RANGE_IMM, 1, INDEX_END); return TCL_OK; } /* Replace first */ CompileWord(envPtr, replacementTokenPtr, interp, 4); OP4( OVER, 1); PUSH( ""); OP( STR_EQ); JUMP1( JUMP_FALSE, notEq); OP( POP); JUMP1( JUMP, end); FIXJUMP1(notEq); TclAdjustStackDepth(1, envPtr); OP4( REVERSE, 2); OP44( STR_RANGE_IMM, 1, INDEX_END); OP1( STR_CONCAT1, 2); FIXJUMP1(end); return TCL_OK; } else if (idx1 == INDEX_END && idx2 == INDEX_END) { int notEq, end; /* * Just working with the last character. */ CompileWord(envPtr, valueTokenPtr, interp, 1); if (replacementTokenPtr == NULL) { /* Drop last */ OP44( STR_RANGE_IMM, 0, INDEX_END-1); return TCL_OK; } /* Replace last */ CompileWord(envPtr, replacementTokenPtr, interp, 4); OP4( OVER, 1); PUSH( ""); OP( STR_EQ); JUMP1( JUMP_FALSE, notEq); OP( POP); JUMP1( JUMP, end); FIXJUMP1(notEq); TclAdjustStackDepth(1, envPtr); OP4( REVERSE, 2); OP44( STR_RANGE_IMM, 0, INDEX_END-1); OP4( REVERSE, 2); OP1( STR_CONCAT1, 2); FIXJUMP1(end); return TCL_OK; } else { /* * Need to process indices at runtime. This could be because the * indices are not constants, or because we need to resolve them to * absolute indices to work out if a replacement is going to happen. * In any case, to runtime it is. */ genericReplace: CompileWord(envPtr, valueTokenPtr, interp, 1); tokenPtr = TokenAfter(valueTokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 3); if (replacementTokenPtr != NULL) { CompileWord(envPtr, replacementTokenPtr, interp, 4); } else { PUSH( ""); } OP( STR_REPLACE); return TCL_OK; } } int TclCompileStringTrimLCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; if (parsePtr->numWords != 2 && parsePtr->numWords != 3) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); if (parsePtr->numWords == 3) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); } else { PushLiteral(envPtr, tclDefaultTrimSet, strlen(tclDefaultTrimSet)); } OP( STR_TRIM_LEFT); return TCL_OK; } int TclCompileStringTrimRCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; if (parsePtr->numWords != 2 && parsePtr->numWords != 3) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); if (parsePtr->numWords == 3) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); } else { PushLiteral(envPtr, tclDefaultTrimSet, strlen(tclDefaultTrimSet)); } OP( STR_TRIM_RIGHT); return TCL_OK; } int TclCompileStringTrimCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; if (parsePtr->numWords != 2 && parsePtr->numWords != 3) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); if (parsePtr->numWords == 3) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); } else { PushLiteral(envPtr, tclDefaultTrimSet, strlen(tclDefaultTrimSet)); } OP( STR_TRIM); return TCL_OK; } int TclCompileStringToUpperCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; if (parsePtr->numWords != 2) { return TclCompileBasic1To3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); OP( STR_UPPER); return TCL_OK; } int TclCompileStringToLowerCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; if (parsePtr->numWords != 2) { return TclCompileBasic1To3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); OP( STR_LOWER); return TCL_OK; } int TclCompileStringToTitleCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; if (parsePtr->numWords != 2) { return TclCompileBasic1To3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); OP( STR_TITLE); return TCL_OK; } /* * Support definitions for the [string is] compilation. */ static int UniCharIsAscii( int character) { return (character >= 0) && (character < 0x80); } static int UniCharIsHexDigit( int character) { return (character >= 0) && (character < 0x80) && isxdigit(character); } StringClassDesc const tclStringClassTable[] = { {"alnum", Tcl_UniCharIsAlnum}, {"alpha", Tcl_UniCharIsAlpha}, {"ascii", UniCharIsAscii}, {"control", Tcl_UniCharIsControl}, {"digit", Tcl_UniCharIsDigit}, {"graph", Tcl_UniCharIsGraph}, {"lower", Tcl_UniCharIsLower}, {"print", Tcl_UniCharIsPrint}, {"punct", Tcl_UniCharIsPunct}, {"space", Tcl_UniCharIsSpace}, {"upper", Tcl_UniCharIsUpper}, {"word", Tcl_UniCharIsWordChar}, {"xdigit", UniCharIsHexDigit}, {NULL, NULL} }; /* *---------------------------------------------------------------------- * * TclCompileSubstCmd -- * * Procedure called to compile the "subst" command. * * Results: * Returns TCL_OK for successful compile, or TCL_ERROR to defer * evaluation to runtime (either when it is too complex to get the * semantics right, or when we know for sure that it is an error but need * the error to happen at the right time). * * Side effects: * Instructions are added to envPtr to execute the "subst" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileSubstCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { int numArgs = parsePtr->numWords - 1; int numOpts = numArgs - 1; int objc, flags = TCL_SUBST_ALL; Tcl_Obj **objv/*, *toSubst = NULL*/; Tcl_Token *wordTokenPtr = TokenAfter(parsePtr->tokenPtr); int code = TCL_ERROR; DefineLineInformation; /* TIP #280 */ if (numArgs == 0) { return TCL_ERROR; } objv = TclStackAlloc(interp, /*numArgs*/ numOpts * sizeof(Tcl_Obj *)); for (objc = 0; objc < /*numArgs*/ numOpts; objc++) { objv[objc] = Tcl_NewObj(); Tcl_IncrRefCount(objv[objc]); if (!TclWordKnownAtCompileTime(wordTokenPtr, objv[objc])) { objc++; goto cleanup; } wordTokenPtr = TokenAfter(wordTokenPtr); } /* if (TclSubstOptions(NULL, numOpts, objv, &flags) == TCL_OK) { toSubst = objv[numOpts]; Tcl_IncrRefCount(toSubst); } */ /* TODO: Figure out expansion to cover WordKnownAtCompileTime * The difficulty is that WKACT makes a copy, and if TclSubstParse * below parses the copy of the original source string, some deep * parts of the compile machinery get upset. They want all pointers * stored in Tcl_Tokens to point back to the same original string. */ if (wordTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { code = TclSubstOptions(NULL, numOpts, objv, &flags); } cleanup: while (--objc >= 0) { TclDecrRefCount(objv[objc]); } TclStackFree(interp, objv); if (/*toSubst == NULL*/ code != TCL_OK) { return TCL_ERROR; } SetLineInformation(numArgs); TclSubstCompile(interp, wordTokenPtr[1].start, wordTokenPtr[1].size, flags, mapPtr->loc[eclIndex].line[numArgs], envPtr); /* TclDecrRefCount(toSubst);*/ return TCL_OK; } void TclSubstCompile( Tcl_Interp *interp, const char *bytes, int numBytes, int flags, int line, CompileEnv *envPtr) { Tcl_Token *endTokenPtr, *tokenPtr; int breakOffset = 0, count = 0, bline = line; Tcl_Parse parse; Tcl_InterpState state = NULL; TclSubstParse(interp, bytes, numBytes, flags, &parse, &state); if (state != NULL) { Tcl_ResetResult(interp); } /* * Tricky point! If the first token does not result in a *guaranteed* push * of a Tcl_Obj on the stack, we must push an empty object. Otherwise it * is possible to get to an INST_STR_CONCAT1 or INST_DONE without enough * values on the stack, resulting in a crash. Thanks to Joe Mistachkin for * identifying a script that could trigger this case. */ tokenPtr = parse.tokenPtr; if (tokenPtr->type != TCL_TOKEN_TEXT && tokenPtr->type != TCL_TOKEN_BS) { PUSH(""); count++; } for (endTokenPtr = tokenPtr + parse.numTokens; tokenPtr < endTokenPtr; tokenPtr = TokenAfter(tokenPtr)) { int length, literal, catchRange, breakJump; char buf[TCL_UTF_MAX]; JumpFixup startFixup, okFixup, returnFixup, breakFixup; JumpFixup continueFixup, otherFixup, endFixup; switch (tokenPtr->type) { case TCL_TOKEN_TEXT: literal = TclRegisterNewLiteral(envPtr, tokenPtr->start, tokenPtr->size); TclEmitPush(literal, envPtr); TclAdvanceLines(&bline, tokenPtr->start, tokenPtr->start + tokenPtr->size); count++; continue; case TCL_TOKEN_BS: length = TclParseBackslash(tokenPtr->start, tokenPtr->size, NULL, buf); literal = TclRegisterNewLiteral(envPtr, buf, length); TclEmitPush(literal, envPtr); count++; continue; case TCL_TOKEN_VARIABLE: /* * Check for simple variable access; see if we can only generate * TCL_OK or TCL_ERROR from the substituted variable read; if so, * there is no need to generate elaborate exception-management * code. Note that the first component of TCL_TOKEN_VARIABLE is * always TCL_TOKEN_TEXT... */ if (tokenPtr->numComponents > 1) { int i, foundCommand = 0; for (i=2 ; i<=tokenPtr->numComponents ; i++) { if (tokenPtr[i].type == TCL_TOKEN_COMMAND) { foundCommand = 1; break; } } if (foundCommand) { break; } } envPtr->line = bline; TclCompileVarSubst(interp, tokenPtr, envPtr); bline = envPtr->line; count++; continue; } while (count > 255) { OP1( STR_CONCAT1, 255); count -= 254; } if (count > 1) { OP1( STR_CONCAT1, count); count = 1; } if (breakOffset == 0) { /* Jump to the start (jump over the jump to end) */ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &startFixup); /* Jump to the end (all BREAKs land here) */ breakOffset = CurrentOffset(envPtr); TclEmitInstInt4(INST_JUMP4, 0, envPtr); /* Start */ if (TclFixupForwardJumpToHere(envPtr, &startFixup, 127)) { Tcl_Panic("TclCompileSubstCmd: bad start jump distance %d", (int) (CurrentOffset(envPtr) - startFixup.codeOffset)); } } envPtr->line = bline; catchRange = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); OP4( BEGIN_CATCH4, catchRange); ExceptionRangeStarts(envPtr, catchRange); switch (tokenPtr->type) { case TCL_TOKEN_COMMAND: TclCompileScript(interp, tokenPtr->start+1, tokenPtr->size-2, envPtr); count++; break; case TCL_TOKEN_VARIABLE: TclCompileVarSubst(interp, tokenPtr, envPtr); count++; break; default: Tcl_Panic("unexpected token type in TclCompileSubstCmd: %d", tokenPtr->type); } ExceptionRangeEnds(envPtr, catchRange); /* Substitution produced TCL_OK */ OP( END_CATCH); TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &okFixup); TclAdjustStackDepth(-1, envPtr); /* Exceptional return codes processed here */ ExceptionRangeTarget(envPtr, catchRange, catchOffset); OP( PUSH_RETURN_OPTIONS); OP( PUSH_RESULT); OP( PUSH_RETURN_CODE); OP( END_CATCH); OP( RETURN_CODE_BRANCH); /* ERROR -> reraise it; NB: can't require BREAK/CONTINUE handling */ OP( RETURN_STK); OP( NOP); /* RETURN */ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &returnFixup); /* BREAK */ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &breakFixup); /* CONTINUE */ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &continueFixup); /* OTHER */ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &otherFixup); TclAdjustStackDepth(1, envPtr); /* BREAK destination */ if (TclFixupForwardJumpToHere(envPtr, &breakFixup, 127)) { Tcl_Panic("TclCompileSubstCmd: bad break jump distance %d", (int) (CurrentOffset(envPtr) - breakFixup.codeOffset)); } OP( POP); OP( POP); breakJump = CurrentOffset(envPtr) - breakOffset; if (breakJump > 127) { OP4(JUMP4, -breakJump); } else { OP1(JUMP1, -breakJump); } TclAdjustStackDepth(2, envPtr); /* CONTINUE destination */ if (TclFixupForwardJumpToHere(envPtr, &continueFixup, 127)) { Tcl_Panic("TclCompileSubstCmd: bad continue jump distance %d", (int) (CurrentOffset(envPtr) - continueFixup.codeOffset)); } OP( POP); OP( POP); TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &endFixup); TclAdjustStackDepth(2, envPtr); /* RETURN + other destination */ if (TclFixupForwardJumpToHere(envPtr, &returnFixup, 127)) { Tcl_Panic("TclCompileSubstCmd: bad return jump distance %d", (int) (CurrentOffset(envPtr) - returnFixup.codeOffset)); } if (TclFixupForwardJumpToHere(envPtr, &otherFixup, 127)) { Tcl_Panic("TclCompileSubstCmd: bad other jump distance %d", (int) (CurrentOffset(envPtr) - otherFixup.codeOffset)); } /* * Pull the result to top of stack, discard options dict. */ OP4( REVERSE, 2); OP( POP); /* OK destination */ if (TclFixupForwardJumpToHere(envPtr, &okFixup, 127)) { Tcl_Panic("TclCompileSubstCmd: bad ok jump distance %d", (int) (CurrentOffset(envPtr) - okFixup.codeOffset)); } if (count > 1) { OP1(STR_CONCAT1, count); count = 1; } /* CONTINUE jump to here */ if (TclFixupForwardJumpToHere(envPtr, &endFixup, 127)) { Tcl_Panic("TclCompileSubstCmd: bad end jump distance %d", (int) (CurrentOffset(envPtr) - endFixup.codeOffset)); } bline = envPtr->line; } while (count > 255) { OP1( STR_CONCAT1, 255); count -= 254; } if (count > 1) { OP1( STR_CONCAT1, count); } Tcl_FreeParse(&parse); if (state != NULL) { Tcl_RestoreInterpState(interp, state); TclCompileSyntaxError(interp, envPtr); TclAdjustStackDepth(-1, envPtr); } /* Final target of the multi-jump from all BREAKs */ if (breakOffset > 0) { TclUpdateInstInt4AtPc(INST_JUMP4, CurrentOffset(envPtr) - breakOffset, envPtr->codeStart + breakOffset); } } /* *---------------------------------------------------------------------- * * TclCompileSwitchCmd -- * * Procedure called to compile the "switch" command. * * Results: * Returns TCL_OK for successful compile, or TCL_ERROR to defer * evaluation to runtime (either when it is too complex to get the * semantics right, or when we know for sure that it is an error but need * the error to happen at the right time). * * Side effects: * Instructions are added to envPtr to execute the "switch" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileSwitchCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; /* Pointer to tokens in command. */ int numWords; /* Number of words in command. */ Tcl_Token *valueTokenPtr; /* Token for the value to switch on. */ enum {Switch_Exact, Switch_Glob, Switch_Regexp} mode; /* What kind of switch are we doing? */ Tcl_Token *bodyTokenArray; /* Array of real pattern list items. */ Tcl_Token **bodyToken; /* Array of pointers to pattern list items. */ int *bodyLines; /* Array of line numbers for body list * items. */ int **bodyContLines; /* Array of continuation line info. */ int noCase; /* Has the -nocase flag been given? */ int foundMode = 0; /* Have we seen a mode flag yet? */ int i, valueIndex; int result = TCL_ERROR; DefineLineInformation; /* TIP #280 */ int *clNext = envPtr->clNext; /* * Only handle the following versions: * switch ?--? word {pattern body ...} * switch -exact ?--? word {pattern body ...} * switch -glob ?--? word {pattern body ...} * switch -regexp ?--? word {pattern body ...} * switch -- word simpleWordPattern simpleWordBody ... * switch -exact -- word simpleWordPattern simpleWordBody ... * switch -glob -- word simpleWordPattern simpleWordBody ... * switch -regexp -- word simpleWordPattern simpleWordBody ... * When the mode is -glob, can also handle a -nocase flag. * * First off, we don't care how the command's word was generated; we're * compiling it anyway! So skip it... */ tokenPtr = TokenAfter(parsePtr->tokenPtr); valueIndex = 1; numWords = parsePtr->numWords-1; /* * Check for options. */ noCase = 0; mode = Switch_Exact; if (numWords == 2) { /* * There's just the switch value and the bodies list. In that case, we * can skip all option parsing and move on to consider switch values * and the body list. */ goto finishedOptionParse; } /* * There must be at least one option, --, because without that there is no * way to statically avoid the problems you get from strings-to-be-matched * that start with a - (the interpreted code falls apart if it encounters * them, so we punt if we *might* encounter them as that is the easiest * way of emulating the behaviour). */ for (; numWords>=3 ; tokenPtr=TokenAfter(tokenPtr),numWords--) { register unsigned size = tokenPtr[1].size; register const char *chrs = tokenPtr[1].start; /* * We only process literal options, and we assume that -e, -g and -n * are unique prefixes of -exact, -glob and -nocase respectively (true * at time of writing). Note that -exact and -glob may only be given * at most once or we bail out (error case). */ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD || size < 2) { return TCL_ERROR; } if ((size <= 6) && !memcmp(chrs, "-exact", size)) { if (foundMode) { return TCL_ERROR; } mode = Switch_Exact; foundMode = 1; valueIndex++; continue; } else if ((size <= 5) && !memcmp(chrs, "-glob", size)) { if (foundMode) { return TCL_ERROR; } mode = Switch_Glob; foundMode = 1; valueIndex++; continue; } else if ((size <= 7) && !memcmp(chrs, "-regexp", size)) { if (foundMode) { return TCL_ERROR; } mode = Switch_Regexp; foundMode = 1; valueIndex++; continue; } else if ((size <= 7) && !memcmp(chrs, "-nocase", size)) { noCase = 1; valueIndex++; continue; } else if ((size == 2) && !memcmp(chrs, "--", 2)) { valueIndex++; break; } /* * The switch command has many flags we cannot compile at all (e.g. * all the RE-related ones) which we must have encountered. Either * that or we have run off the end. The action here is the same: punt * to interpreted version. */ return TCL_ERROR; } if (numWords < 3) { return TCL_ERROR; } tokenPtr = TokenAfter(tokenPtr); numWords--; if (noCase && (mode == Switch_Exact)) { /* * Can't compile this case; no opcode for case-insensitive equality! */ return TCL_ERROR; } /* * The value to test against is going to always get pushed on the stack. * But not yet; we need to verify that the rest of the command is * compilable too. */ finishedOptionParse: valueTokenPtr = tokenPtr; /* For valueIndex, see previous loop. */ tokenPtr = TokenAfter(tokenPtr); numWords--; /* * Build an array of tokens for the matcher terms and script bodies. Note * that in the case of the quoted bodies, this is tricky as we cannot use * copies of the string from the input token for the generated tokens (it * causes a crash during exception handling). When multiple tokens are * available at this point, this is pretty easy. */ if (numWords == 1) { const char *bytes; int maxLen, numBytes; int bline; /* TIP #280: line of the pattern/action list, * and start of list for when tracking the * location. This list comes immediately after * the value we switch on. */ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TCL_ERROR; } bytes = tokenPtr[1].start; numBytes = tokenPtr[1].size; /* Allocate enough space to work in. */ maxLen = TclMaxListLength(bytes, numBytes, NULL); if (maxLen < 2) { return TCL_ERROR; } bodyTokenArray = ckalloc(sizeof(Tcl_Token) * maxLen); bodyToken = ckalloc(sizeof(Tcl_Token *) * maxLen); bodyLines = ckalloc(sizeof(int) * maxLen); bodyContLines = ckalloc(sizeof(int*) * maxLen); bline = mapPtr->loc[eclIndex].line[valueIndex+1]; numWords = 0; while (numBytes > 0) { const char *prevBytes = bytes; int literal; if (TCL_OK != TclFindElement(NULL, bytes, numBytes, &(bodyTokenArray[numWords].start), &bytes, &(bodyTokenArray[numWords].size), &literal) || !literal) { goto abort; } bodyTokenArray[numWords].type = TCL_TOKEN_TEXT; bodyTokenArray[numWords].numComponents = 0; bodyToken[numWords] = bodyTokenArray + numWords; /* * TIP #280: Now determine the line the list element starts on * (there is no need to do it earlier, due to the possibility of * aborting, see above). */ TclAdvanceLines(&bline, prevBytes, bodyTokenArray[numWords].start); TclAdvanceContinuations(&bline, &clNext, bodyTokenArray[numWords].start - envPtr->source); bodyLines[numWords] = bline; bodyContLines[numWords] = clNext; TclAdvanceLines(&bline, bodyTokenArray[numWords].start, bytes); TclAdvanceContinuations(&bline, &clNext, bytes - envPtr->source); numBytes -= (bytes - prevBytes); numWords++; } if (numWords % 2) { abort: ckfree((char *) bodyToken); ckfree((char *) bodyTokenArray); ckfree((char *) bodyLines); ckfree((char *) bodyContLines); return TCL_ERROR; } } else if (numWords % 2 || numWords == 0) { /* * Odd number of words (>1) available, or no words at all available. * Both are error cases, so punt and let the interpreted-version * generate the error message. Note that the second case probably * should get caught earlier, but it's easy to check here again anyway * because it'd cause a nasty crash otherwise. */ return TCL_ERROR; } else { /* * Multi-word definition of patterns & actions. */ bodyToken = ckalloc(sizeof(Tcl_Token *) * numWords); bodyLines = ckalloc(sizeof(int) * numWords); bodyContLines = ckalloc(sizeof(int*) * numWords); bodyTokenArray = NULL; for (i=0 ; itype != TCL_TOKEN_SIMPLE_WORD) { goto freeTemporaries; } bodyToken[i] = tokenPtr+1; /* * TIP #280: Copy line information from regular cmd info. */ bodyLines[i] = mapPtr->loc[eclIndex].line[valueIndex+1+i]; bodyContLines[i] = mapPtr->loc[eclIndex].next[valueIndex+1+i]; tokenPtr = TokenAfter(tokenPtr); } } /* * Fall back to interpreted if the last body is a continuation (it's * illegal, but this makes the error happen at the right time). */ if (bodyToken[numWords-1]->size == 1 && bodyToken[numWords-1]->start[0] == '-') { goto freeTemporaries; } /* * Now we commit to generating code; the parsing stage per se is done. * Check if we can generate a jump table, since if so that's faster than * doing an explicit compare with each body. Note that we're definitely * over-conservative with determining whether we can do the jump table, * but it handles the most common case well enough. */ /* Both methods push the value to match against onto the stack. */ CompileWord(envPtr, valueTokenPtr, interp, valueIndex); if (mode == Switch_Exact) { IssueSwitchJumpTable(interp, envPtr, valueIndex, numWords, bodyToken, bodyLines, bodyContLines); } else { IssueSwitchChainedTests(interp, envPtr, mode, noCase, valueIndex, numWords, bodyToken, bodyLines, bodyContLines); } result = TCL_OK; /* * Clean up all our temporary space and return. */ freeTemporaries: ckfree(bodyToken); ckfree(bodyLines); ckfree(bodyContLines); if (bodyTokenArray != NULL) { ckfree(bodyTokenArray); } return result; } /* *---------------------------------------------------------------------- * * IssueSwitchChainedTests -- * * Generate instructions for a [switch] command that is to be compiled * into a sequence of tests. This is the generic handle-everything mode * that inherently has performance that is (on average) linear in the * number of tests. It is the only mode that can handle -glob and -regexp * matches, or anything that is case-insensitive. It does not handle the * wild-and-wooly end of regexp matching (i.e., capture of match results) * so that's when we spill to the interpreted version. * *---------------------------------------------------------------------- */ static void IssueSwitchChainedTests( Tcl_Interp *interp, /* Context for compiling script bodies. */ CompileEnv *envPtr, /* Holds resulting instructions. */ int mode, /* Exact, Glob or Regexp */ int noCase, /* Case-insensitivity flag. */ int valueIndex, /* The value to match against. */ int numBodyTokens, /* Number of tokens describing things the * switch can match against and bodies to * execute when the match succeeds. */ Tcl_Token **bodyToken, /* Array of pointers to pattern list items. */ int *bodyLines, /* Array of line numbers for body list * items. */ int **bodyContLines) /* Array of continuation line info. */ { enum {Switch_Exact, Switch_Glob, Switch_Regexp}; int foundDefault; /* Flag to indicate whether a "default" clause * is present. */ JumpFixup *fixupArray; /* Array of forward-jump fixup records. */ int *fixupTargetArray; /* Array of places for fixups to point at. */ int fixupCount; /* Number of places to fix up. */ int contFixIndex; /* Where the first of the jumps due to a group * of continuation bodies starts, or -1 if * there aren't any. */ int contFixCount; /* Number of continuation bodies pointing to * the current (or next) real body. */ int nextArmFixupIndex; int simple, exact; /* For extracting the type of regexp. */ int i; /* * Generate a test for each arm. */ contFixIndex = -1; contFixCount = 0; fixupArray = TclStackAlloc(interp, sizeof(JumpFixup) * numBodyTokens); fixupTargetArray = TclStackAlloc(interp, sizeof(int) * numBodyTokens); memset(fixupTargetArray, 0, numBodyTokens * sizeof(int)); fixupCount = 0; foundDefault = 0; for (i=0 ; isize != 7 || memcmp(bodyToken[numBodyTokens-2]->start, "default", 7)) { /* * Generate the test for the arm. */ switch (mode) { case Switch_Exact: OP( DUP); TclCompileTokens(interp, bodyToken[i], 1, envPtr); OP( STR_EQ); break; case Switch_Glob: TclCompileTokens(interp, bodyToken[i], 1, envPtr); OP4( OVER, 1); OP1( STR_MATCH, noCase); break; case Switch_Regexp: simple = exact = 0; /* * Keep in sync with TclCompileRegexpCmd. */ if (bodyToken[i]->type == TCL_TOKEN_TEXT) { Tcl_DString ds; if (bodyToken[i]->size == 0) { /* * The semantics of regexps are that they always match * when the RE == "". */ PUSH("1"); break; } /* * Attempt to convert pattern to glob. If successful, push * the converted pattern. */ if (TclReToGlob(NULL, bodyToken[i]->start, bodyToken[i]->size, &ds, &exact, NULL) == TCL_OK){ simple = 1; PushLiteral(envPtr, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); Tcl_DStringFree(&ds); } } if (!simple) { TclCompileTokens(interp, bodyToken[i], 1, envPtr); } OP4( OVER, 1); if (!simple) { /* * Pass correct RE compile flags. We use only Int1 * (8-bit), but that handles all the flags we want to * pass. Don't use TCL_REG_NOSUB as we may have backrefs * or capture vars. */ int cflags = TCL_REG_ADVANCED | (noCase ? TCL_REG_NOCASE : 0); OP1(REGEXP, cflags); } else if (exact && !noCase) { OP( STR_EQ); } else { OP1(STR_MATCH, noCase); } break; default: Tcl_Panic("unknown switch mode: %d", mode); } /* * In a fall-through case, we will jump on _true_ to the place * where the body starts (generated later, with guarantee of this * ensured earlier; the final body is never a fall-through). */ if (bodyToken[i+1]->size==1 && bodyToken[i+1]->start[0]=='-') { if (contFixIndex == -1) { contFixIndex = fixupCount; contFixCount = 0; } TclEmitForwardJump(envPtr, TCL_TRUE_JUMP, &fixupArray[contFixIndex+contFixCount]); fixupCount++; contFixCount++; continue; } TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &fixupArray[fixupCount]); nextArmFixupIndex = fixupCount; fixupCount++; } else { /* * Got a default clause; set a flag to inhibit the generation of * the jump after the body and the cleanup of the intermediate * value that we are switching against. * * Note that default clauses (which are always terminal clauses) * cannot be fall-through clauses as well, since the last clause * is never a fall-through clause (which we have already * verified). */ foundDefault = 1; } /* * Generate the body for the arm. This is guaranteed not to be a * fall-through case, but it might have preceding fall-through cases, * so we must process those first. */ if (contFixIndex != -1) { int j; for (j=0 ; jline = bodyLines[i+1]; /* TIP #280 */ envPtr->clNext = bodyContLines[i+1]; /* TIP #280 */ TclCompileCmdWord(interp, bodyToken[i+1], 1, envPtr); if (!foundDefault) { TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &fixupArray[fixupCount]); fixupCount++; fixupTargetArray[nextArmFixupIndex] = CurrentOffset(envPtr); } } /* * Discard the value we are matching against unless we've had a default * clause (in which case it will already be gone due to the code at the * start of processing an arm, guaranteed) and make the result of the * command an empty string. */ if (!foundDefault) { OP( POP); PUSH(""); } /* * Do jump fixups for arms that were executed. First, fill in the jumps of * all jumps that don't point elsewhere to point to here. */ for (i=0 ; icodeNext-envPtr->codeStart; } } /* * Now scan backwards over all the jumps (all of which are forward jumps) * doing each one. When we do one and there is a size changes, we must * scan back over all the previous ones and see if they need adjusting * before proceeding with further jump fixups (the interleaved nature of * all the jumps makes this impossible to do without nested loops). */ for (i=fixupCount-1 ; i>=0 ; i--) { if (TclFixupForwardJump(envPtr, &fixupArray[i], fixupTargetArray[i] - fixupArray[i].codeOffset, 127)) { int j; for (j=i-1 ; j>=0 ; j--) { if (fixupTargetArray[j] > fixupArray[i].codeOffset) { fixupTargetArray[j] += 3; } } } } TclStackFree(interp, fixupTargetArray); TclStackFree(interp, fixupArray); } /* *---------------------------------------------------------------------- * * IssueSwitchJumpTable -- * * Generate instructions for a [switch] command that is to be compiled * into a jump table. This only handles the case where case-sensitive, * exact matching is used, but this is actually the most common case in * real code. * *---------------------------------------------------------------------- */ static void IssueSwitchJumpTable( Tcl_Interp *interp, /* Context for compiling script bodies. */ CompileEnv *envPtr, /* Holds resulting instructions. */ int valueIndex, /* The value to match against. */ int numBodyTokens, /* Number of tokens describing things the * switch can match against and bodies to * execute when the match succeeds. */ Tcl_Token **bodyToken, /* Array of pointers to pattern list items. */ int *bodyLines, /* Array of line numbers for body list * items. */ int **bodyContLines) /* Array of continuation line info. */ { JumptableInfo *jtPtr; int infoIndex, isNew, *finalFixups, numRealBodies = 0, jumpLocation; int mustGenerate, foundDefault, jumpToDefault, i; Tcl_DString buffer; Tcl_HashEntry *hPtr; /* * Compile the switch by using a jump table, which is basically a * hashtable that maps from literal values to match against to the offset * (relative to the INST_JUMP_TABLE instruction) to jump to. The jump * table itself is independent of any invokation of the bytecode, and as * such is stored in an auxData block. * * Start by allocating the jump table itself, plus some workspace. */ jtPtr = ckalloc(sizeof(JumptableInfo)); Tcl_InitHashTable(&jtPtr->hashTable, TCL_STRING_KEYS); infoIndex = TclCreateAuxData(jtPtr, &tclJumptableInfoType, envPtr); finalFixups = TclStackAlloc(interp, sizeof(int) * (numBodyTokens/2)); foundDefault = 0; mustGenerate = 1; /* * Next, issue the instruction to do the jump, together with what we want * to do if things do not work out (jump to either the default clause or * the "default" default, which just sets the result to empty). Note that * we will come back and rewrite the jump's offset parameter when we know * what it should be, and that all jumps we issue are of the wide kind * because that makes the code much easier to debug! */ jumpLocation = CurrentOffset(envPtr); OP4( JUMP_TABLE, infoIndex); jumpToDefault = CurrentOffset(envPtr); OP4( JUMP4, 0); for (i=0 ; isize != 7 || memcmp(bodyToken[numBodyTokens-2]->start, "default", 7)) { /* * This is not a default clause, so insert the current location as * a target in the jump table (assuming it isn't already there, * which would indicate that this clause is probably masked by an * earlier one). Note that we use a Tcl_DString here simply * because the hash API does not let us specify the string length. */ Tcl_DStringInit(&buffer); TclDStringAppendToken(&buffer, bodyToken[i]); hPtr = Tcl_CreateHashEntry(&jtPtr->hashTable, Tcl_DStringValue(&buffer), &isNew); if (isNew) { /* * First time we've encountered this match clause, so it must * point to here. */ Tcl_SetHashValue(hPtr, CurrentOffset(envPtr) - jumpLocation); } Tcl_DStringFree(&buffer); } else { /* * This is a default clause, so patch up the fallthrough from the * INST_JUMP_TABLE instruction to here. */ foundDefault = 1; isNew = 1; TclStoreInt4AtPtr(CurrentOffset(envPtr)-jumpToDefault, envPtr->codeStart+jumpToDefault+1); } /* * Now, for each arm we must deal with the body of the clause. * * If this is a continuation body (never true of a final clause, * whether default or not) we're done because the next jump target * will also point here, so we advance to the next clause. */ if (bodyToken[i+1]->size == 1 && bodyToken[i+1]->start[0] == '-') { mustGenerate = 1; continue; } /* * Also skip this arm if its only match clause is masked. (We could * probably be more aggressive about this, but that would be much more * difficult to get right.) */ if (!isNew && !mustGenerate) { continue; } mustGenerate = 0; /* * Compile the body of the arm. */ envPtr->line = bodyLines[i+1]; /* TIP #280 */ envPtr->clNext = bodyContLines[i+1]; /* TIP #280 */ TclCompileCmdWord(interp, bodyToken[i+1], 1, envPtr); /* * Compile a jump in to the end of the command if this body is * anything other than a user-supplied default arm (to either skip * over the remaining bodies or the code that generates an empty * result). */ if (i+2 < numBodyTokens || !foundDefault) { finalFixups[numRealBodies++] = CurrentOffset(envPtr); /* * Easier by far to issue this jump as a fixed-width jump, since * otherwise we'd need to do a lot more (and more awkward) * rewriting when we fixed this all up. */ OP4( JUMP4, 0); TclAdjustStackDepth(-1, envPtr); } } /* * We're at the end. If we've not already done so through the processing * of a user-supplied default clause, add in a "default" default clause * now. */ if (!foundDefault) { TclStoreInt4AtPtr(CurrentOffset(envPtr)-jumpToDefault, envPtr->codeStart+jumpToDefault+1); PUSH(""); } /* * No more instructions to be issued; everything that needs to jump to the * end of the command is fixed up at this point. */ for (i=0 ; icodeStart+finalFixups[i]+1); } /* * Clean up all our temporary space and return. */ TclStackFree(interp, finalFixups); } /* *---------------------------------------------------------------------- * * DupJumptableInfo, FreeJumptableInfo -- * * Functions to duplicate, release and print a jump-table created for use * with the INST_JUMP_TABLE instruction. * * Results: * DupJumptableInfo: a copy of the jump-table * FreeJumptableInfo: none * PrintJumptableInfo: none * DisassembleJumptableInfo: none * * Side effects: * DupJumptableInfo: allocates memory * FreeJumptableInfo: releases memory * PrintJumptableInfo: none * DisassembleJumptableInfo: none * *---------------------------------------------------------------------- */ static ClientData DupJumptableInfo( ClientData clientData) { JumptableInfo *jtPtr = clientData; JumptableInfo *newJtPtr = ckalloc(sizeof(JumptableInfo)); Tcl_HashEntry *hPtr, *newHPtr; Tcl_HashSearch search; int isNew; Tcl_InitHashTable(&newJtPtr->hashTable, TCL_STRING_KEYS); hPtr = Tcl_FirstHashEntry(&jtPtr->hashTable, &search); while (hPtr != NULL) { newHPtr = Tcl_CreateHashEntry(&newJtPtr->hashTable, Tcl_GetHashKey(&jtPtr->hashTable, hPtr), &isNew); Tcl_SetHashValue(newHPtr, Tcl_GetHashValue(hPtr)); } return newJtPtr; } static void FreeJumptableInfo( ClientData clientData) { JumptableInfo *jtPtr = clientData; Tcl_DeleteHashTable(&jtPtr->hashTable); ckfree(jtPtr); } static void PrintJumptableInfo( ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset) { register JumptableInfo *jtPtr = clientData; Tcl_HashEntry *hPtr; Tcl_HashSearch search; const char *keyPtr; int offset, i = 0; hPtr = Tcl_FirstHashEntry(&jtPtr->hashTable, &search); for (; hPtr ; hPtr = Tcl_NextHashEntry(&search)) { keyPtr = Tcl_GetHashKey(&jtPtr->hashTable, hPtr); offset = PTR2INT(Tcl_GetHashValue(hPtr)); if (i++) { Tcl_AppendToObj(appendObj, ", ", -1); if (i%4==0) { Tcl_AppendToObj(appendObj, "\n\t\t", -1); } } Tcl_AppendPrintfToObj(appendObj, "\"%s\"->pc %d", keyPtr, pcOffset + offset); } } static void DisassembleJumptableInfo( ClientData clientData, Tcl_Obj *dictObj, ByteCode *codePtr, unsigned int pcOffset) { register JumptableInfo *jtPtr = clientData; Tcl_Obj *mapping = Tcl_NewObj(); Tcl_HashEntry *hPtr; Tcl_HashSearch search; const char *keyPtr; int offset; hPtr = Tcl_FirstHashEntry(&jtPtr->hashTable, &search); for (; hPtr ; hPtr = Tcl_NextHashEntry(&search)) { keyPtr = Tcl_GetHashKey(&jtPtr->hashTable, hPtr); offset = PTR2INT(Tcl_GetHashValue(hPtr)); Tcl_DictObjPut(NULL, mapping, Tcl_NewStringObj(keyPtr, -1), Tcl_NewIntObj(offset)); } Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("mapping", -1), mapping); } /* *---------------------------------------------------------------------- * * TclCompileTailcallCmd -- * * Procedure called to compile the "tailcall" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "tailcall" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileTailcallCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; int i; if (parsePtr->numWords < 2 || parsePtr->numWords > 256 || envPtr->procPtr == NULL) { return TCL_ERROR; } /* make room for the nsObjPtr */ /* TODO: Doesn't this have to be a known value? */ CompileWord(envPtr, tokenPtr, interp, 0); for (i=1 ; inumWords ; i++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i); } TclEmitInstInt1( INST_TAILCALL, parsePtr->numWords, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileThrowCmd -- * * Procedure called to compile the "throw" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "throw" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileThrowCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ int numWords = parsePtr->numWords; Tcl_Token *codeToken, *msgToken; Tcl_Obj *objPtr; int codeKnown, codeIsList, codeIsValid, len; if (numWords != 3) { return TCL_ERROR; } codeToken = TokenAfter(parsePtr->tokenPtr); msgToken = TokenAfter(codeToken); TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); codeKnown = TclWordKnownAtCompileTime(codeToken, objPtr); /* * First we must emit the code to substitute the arguments. This * must come first in case substitution raises errors. */ if (!codeKnown) { CompileWord(envPtr, codeToken, interp, 1); PUSH( "-errorcode"); } CompileWord(envPtr, msgToken, interp, 2); codeIsList = codeKnown && (TCL_OK == Tcl_ListObjLength(interp, objPtr, &len)); codeIsValid = codeIsList && (len != 0); if (codeIsValid) { Tcl_Obj *errPtr, *dictPtr; TclNewLiteralStringObj(errPtr, "-errorcode"); TclNewObj(dictPtr); Tcl_DictObjPut(NULL, dictPtr, errPtr, objPtr); TclEmitPush(TclAddLiteralObj(envPtr, dictPtr, NULL), envPtr); } TclDecrRefCount(objPtr); /* * Simpler bytecodes when we detect invalid arguments at compile time. */ if (codeKnown && !codeIsValid) { OP( POP); if (codeIsList) { /* Must be an empty list */ goto issueErrorForEmptyCode; } TclCompileSyntaxError(interp, envPtr); return TCL_OK; } if (!codeKnown) { /* * Argument validity checking has to be done by bytecode at * run time. */ OP4( REVERSE, 3); OP( DUP); OP( LIST_LENGTH); OP1( JUMP_FALSE1, 16); OP4( LIST, 2); OP44( RETURN_IMM, TCL_ERROR, 0); TclAdjustStackDepth(2, envPtr); OP( POP); OP( POP); OP( POP); issueErrorForEmptyCode: PUSH( "type must be non-empty list"); PUSH( "-errorcode {TCL OPERATION THROW BADEXCEPTION}"); } OP44( RETURN_IMM, TCL_ERROR, 0); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileTryCmd -- * * Procedure called to compile the "try" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "try" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileTryCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { int numWords = parsePtr->numWords, numHandlers, result = TCL_ERROR; Tcl_Token *bodyToken, *finallyToken, *tokenPtr; Tcl_Token **handlerTokens = NULL; Tcl_Obj **matchClauses = NULL; int *matchCodes=NULL, *resultVarIndices=NULL, *optionVarIndices=NULL; int i; if (numWords < 2) { return TCL_ERROR; } bodyToken = TokenAfter(parsePtr->tokenPtr); if (numWords == 2) { /* * No handlers or finally; do nothing beyond evaluating the body. */ DefineLineInformation; /* TIP #280 */ BODY(bodyToken, 1); return TCL_OK; } numWords -= 2; tokenPtr = TokenAfter(bodyToken); /* * Extract information about what handlers there are. */ numHandlers = numWords >> 2; numWords -= numHandlers * 4; if (numHandlers > 0) { handlerTokens = TclStackAlloc(interp, sizeof(Tcl_Token*)*numHandlers); matchClauses = TclStackAlloc(interp, sizeof(Tcl_Obj *) * numHandlers); memset(matchClauses, 0, sizeof(Tcl_Obj *) * numHandlers); matchCodes = TclStackAlloc(interp, sizeof(int) * numHandlers); resultVarIndices = TclStackAlloc(interp, sizeof(int) * numHandlers); optionVarIndices = TclStackAlloc(interp, sizeof(int) * numHandlers); for (i=0 ; itype != TCL_TOKEN_SIMPLE_WORD) { goto failedToCompile; } if (tokenPtr[1].size == 4 && !strncmp(tokenPtr[1].start, "trap", 4)) { /* * Parse the list of errorCode words to match against. */ matchCodes[i] = TCL_ERROR; tokenPtr = TokenAfter(tokenPtr); TclNewObj(tmpObj); Tcl_IncrRefCount(tmpObj); if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj) || Tcl_ListObjLength(NULL, tmpObj, &objc) != TCL_OK || (objc == 0)) { TclDecrRefCount(tmpObj); goto failedToCompile; } Tcl_ListObjReplace(NULL, tmpObj, 0, 0, 0, NULL); matchClauses[i] = tmpObj; } else if (tokenPtr[1].size == 2 && !strncmp(tokenPtr[1].start, "on", 2)) { int code; /* * Parse the result code to look for. */ tokenPtr = TokenAfter(tokenPtr); TclNewObj(tmpObj); Tcl_IncrRefCount(tmpObj); if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) { TclDecrRefCount(tmpObj); goto failedToCompile; } if (TCL_ERROR == TclGetCompletionCodeFromObj(NULL, tmpObj, &code)) { TclDecrRefCount(tmpObj); goto failedToCompile; } matchCodes[i] = code; TclDecrRefCount(tmpObj); } else { goto failedToCompile; } /* * Parse the variable binding. */ tokenPtr = TokenAfter(tokenPtr); TclNewObj(tmpObj); Tcl_IncrRefCount(tmpObj); if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) { TclDecrRefCount(tmpObj); goto failedToCompile; } if (Tcl_ListObjGetElements(NULL, tmpObj, &objc, &objv) != TCL_OK || (objc > 2)) { TclDecrRefCount(tmpObj); goto failedToCompile; } if (objc > 0) { int len; const char *varname = Tcl_GetStringFromObj(objv[0], &len); resultVarIndices[i] = LocalScalar(varname, len, envPtr); if (resultVarIndices[i] < 0) { TclDecrRefCount(tmpObj); goto failedToCompile; } } else { resultVarIndices[i] = -1; } if (objc == 2) { int len; const char *varname = Tcl_GetStringFromObj(objv[1], &len); optionVarIndices[i] = LocalScalar(varname, len, envPtr); if (optionVarIndices[i] < 0) { TclDecrRefCount(tmpObj); goto failedToCompile; } } else { optionVarIndices[i] = -1; } TclDecrRefCount(tmpObj); /* * Extract the body for this handler. */ tokenPtr = TokenAfter(tokenPtr); if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { goto failedToCompile; } if (tokenPtr[1].size == 1 && tokenPtr[1].start[0] == '-') { handlerTokens[i] = NULL; } else { handlerTokens[i] = tokenPtr; } tokenPtr = TokenAfter(tokenPtr); } if (handlerTokens[numHandlers-1] == NULL) { goto failedToCompile; } } /* * Parse the finally clause */ if (numWords == 0) { finallyToken = NULL; } else if (numWords == 2) { if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD || tokenPtr[1].size != 7 || strncmp(tokenPtr[1].start, "finally", 7)) { goto failedToCompile; } finallyToken = TokenAfter(tokenPtr); } else { goto failedToCompile; } /* * Issue the bytecode. */ if (!finallyToken) { result = IssueTryClausesInstructions(interp, envPtr, bodyToken, numHandlers, matchCodes, matchClauses, resultVarIndices, optionVarIndices, handlerTokens); } else if (numHandlers == 0) { result = IssueTryFinallyInstructions(interp, envPtr, bodyToken, finallyToken); } else { result = IssueTryClausesFinallyInstructions(interp, envPtr, bodyToken, numHandlers, matchCodes, matchClauses, resultVarIndices, optionVarIndices, handlerTokens, finallyToken); } /* * Delete any temporary state and finish off. */ failedToCompile: if (numHandlers > 0) { for (i=0 ; i= 0) { LOAD( resultVar); STORE( resultVars[i]); OP( POP); if (optionVars[i] >= 0) { LOAD( optionsVar); STORE( optionVars[i]); OP( POP); } } if (!handlerTokens[i]) { forwardsNeedFixing = 1; JUMP4( JUMP, forwardsToFix[i]); TclAdjustStackDepth(1, envPtr); } else { int dontChangeOptions; forwardsToFix[i] = -1; if (forwardsNeedFixing) { forwardsNeedFixing = 0; for (j=0 ; j= 0 || handlerTokens[i]) { range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); OP4( BEGIN_CATCH4, range); ExceptionRangeStarts(envPtr, range); } if (resultVars[i] >= 0) { LOAD( resultVar); STORE( resultVars[i]); OP( POP); if (optionVars[i] >= 0) { LOAD( optionsVar); STORE( optionVars[i]); OP( POP); } if (!handlerTokens[i]) { /* * No handler. Will not be the last handler (that is a * condition that is checked by the caller). Chain to the next * one. */ ExceptionRangeEnds(envPtr, range); OP( END_CATCH); forwardsNeedFixing = 1; JUMP4( JUMP, forwardsToFix[i]); goto finishTrapCatchHandling; } } else if (!handlerTokens[i]) { /* * No handler. Will not be the last handler (that condition is * checked by the caller). Chain to the next one. */ forwardsNeedFixing = 1; JUMP4( JUMP, forwardsToFix[i]); goto endOfThisArm; } /* * Got a handler. Make sure that any pending patch-up actions from * previous unprocessed handlers are dealt with now that we know where * they are to jump to. */ if (forwardsNeedFixing) { forwardsNeedFixing = 0; OP1( JUMP1, 7); for (j=0 ; jtokenPtr ; inumWords ; i++) { Tcl_Obj *leadingWord = Tcl_NewObj(); varTokenPtr = TokenAfter(varTokenPtr); if (!TclWordKnownAtCompileTime(varTokenPtr, leadingWord)) { TclDecrRefCount(leadingWord); /* * We can tolerate non-trivial substitutions in the first variable * to be unset. If a '--' or '-nocomplain' was present, anything * goes in that one place! (All subsequent variable names must be * constants since we don't want to have to push them all first.) */ if (varCount == 0) { if (haveFlags) { continue; } /* * In fact, we're OK as long as we're the first argument *and* * we provably don't start with a '-'. If that is true, then * even if everything else is varying, we still can't be a * flag. Otherwise we'll spill to runtime to place a limit on * the trickiness. */ if (varTokenPtr->type == TCL_TOKEN_WORD && varTokenPtr[1].type == TCL_TOKEN_TEXT && varTokenPtr[1].size > 0 && varTokenPtr[1].start[0] != '-') { continue; } } return TCL_ERROR; } if (varCount == 0) { const char *bytes; int len; bytes = Tcl_GetStringFromObj(leadingWord, &len); if (i == 1 && len == 11 && !strncmp("-nocomplain", bytes, 11)) { flags = 0; haveFlags++; } else if (i == (2 - flags) && len == 2 && !strncmp("--", bytes, 2)) { haveFlags++; } else { varCount++; } } else { varCount++; } TclDecrRefCount(leadingWord); } /* * Issue instructions to unset each of the named variables. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); for (i=0; inumWords ; i++) { /* * Decide if we can use a frame slot for the var/array name or if we * need to emit code to compute and push the name at runtime. We use a * frame slot (entry in the array of local vars) if we are compiling a * procedure body and if the name is simple text that does not include * namespace qualifiers. */ PushVarNameWord(interp, varTokenPtr, envPtr, 0, &localIndex, &isScalar, i); /* * Emit instructions to unset the variable. */ if (isScalar) { if (localIndex < 0) { OP1( UNSET_STK, flags); } else { OP14( UNSET_SCALAR, flags, localIndex); } } else { if (localIndex < 0) { OP1( UNSET_ARRAY_STK, flags); } else { OP14( UNSET_ARRAY, flags, localIndex); } } varTokenPtr = TokenAfter(varTokenPtr); } PUSH(""); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileWhileCmd -- * * Procedure called to compile the "while" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "while" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileWhileCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *testTokenPtr, *bodyTokenPtr; JumpFixup jumpEvalCondFixup; int testCodeOffset, bodyCodeOffset, jumpDist, range, code, boolVal; int loopMayEnd = 1; /* This is set to 0 if it is recognized as an * infinite loop. */ Tcl_Obj *boolObj; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 3) { return TCL_ERROR; } /* * If the test expression requires substitutions, don't compile the while * command inline. E.g., the expression might cause the loop to never * execute or execute forever, as in "while "$x < 5" {}". * * Bail out also if the body expression requires substitutions in order to * insure correct behaviour [Bug 219166] */ testTokenPtr = TokenAfter(parsePtr->tokenPtr); bodyTokenPtr = TokenAfter(testTokenPtr); if ((testTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) || (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD)) { return TCL_ERROR; } /* * Find out if the condition is a constant. */ boolObj = Tcl_NewStringObj(testTokenPtr[1].start, testTokenPtr[1].size); Tcl_IncrRefCount(boolObj); code = Tcl_GetBooleanFromObj(NULL, boolObj, &boolVal); TclDecrRefCount(boolObj); if (code == TCL_OK) { if (boolVal) { /* * It is an infinite loop; flag it so that we generate a more * efficient body. */ loopMayEnd = 0; } else { /* * This is an empty loop: "while 0 {...}" or such. Compile no * bytecodes. */ goto pushResult; } } /* * Create a ExceptionRange record for the loop body. This is used to * implement break and continue. */ range = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); /* * Jump to the evaluation of the condition. This code uses the "loop * rotation" optimisation (which eliminates one branch from the loop). * "while cond body" produces then: * goto A * B: body : bodyCodeOffset * A: cond -> result : testCodeOffset, continueOffset * if (result) goto B * * The infinite loop "while 1 body" produces: * B: body : all three offsets here * goto B */ if (loopMayEnd) { TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpEvalCondFixup); testCodeOffset = 0; /* Avoid compiler warning. */ } else { /* * Make sure that the first command in the body is preceded by an * INST_START_CMD, and hence counted properly. [Bug 1752146] */ envPtr->atCmdStart &= ~1; testCodeOffset = CurrentOffset(envPtr); } /* * Compile the loop body. */ bodyCodeOffset = ExceptionRangeStarts(envPtr, range); if (!loopMayEnd) { envPtr->exceptArrayPtr[range].continueOffset = testCodeOffset; envPtr->exceptArrayPtr[range].codeOffset = bodyCodeOffset; } BODY(bodyTokenPtr, 2); ExceptionRangeEnds(envPtr, range); OP( POP); /* * Compile the test expression then emit the conditional jump that * terminates the while. We already know it's a simple word. */ if (loopMayEnd) { testCodeOffset = CurrentOffset(envPtr); jumpDist = testCodeOffset - jumpEvalCondFixup.codeOffset; if (TclFixupForwardJump(envPtr, &jumpEvalCondFixup, jumpDist, 127)) { bodyCodeOffset += 3; testCodeOffset += 3; } SetLineInformation(1); TclCompileExprWords(interp, testTokenPtr, 1, envPtr); jumpDist = CurrentOffset(envPtr) - bodyCodeOffset; if (jumpDist > 127) { TclEmitInstInt4(INST_JUMP_TRUE4, -jumpDist, envPtr); } else { TclEmitInstInt1(INST_JUMP_TRUE1, -jumpDist, envPtr); } } else { jumpDist = CurrentOffset(envPtr) - bodyCodeOffset; if (jumpDist > 127) { TclEmitInstInt4(INST_JUMP4, -jumpDist, envPtr); } else { TclEmitInstInt1(INST_JUMP1, -jumpDist, envPtr); } } /* * Set the loop's body, continue and break offsets. */ envPtr->exceptArrayPtr[range].continueOffset = testCodeOffset; envPtr->exceptArrayPtr[range].codeOffset = bodyCodeOffset; ExceptionRangeTarget(envPtr, range, breakOffset); TclFinalizeLoopExceptionRange(envPtr, range); /* * The while command's result is an empty string. */ pushResult: PUSH(""); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileYieldCmd -- * * Procedure called to compile the "yield" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "yield" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileYieldCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { if (parsePtr->numWords < 1 || parsePtr->numWords > 2) { return TCL_ERROR; } if (parsePtr->numWords == 1) { PUSH(""); } else { DefineLineInformation; /* TIP #280 */ Tcl_Token *valueTokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, valueTokenPtr, interp, 1); } OP( YIELD); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileYieldToCmd -- * * Procedure called to compile the "yieldto" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "yieldto" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileYieldToCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); int i; if (parsePtr->numWords < 2) { return TCL_ERROR; } OP( NS_CURRENT); for (i = 1 ; i < parsePtr->numWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } OP4( LIST, i); OP( YIELD_TO_INVOKE); return TCL_OK; } /* *---------------------------------------------------------------------- * * CompileUnaryOpCmd -- * * Utility routine to compile the unary operator commands. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the compiled command at * runtime. * *---------------------------------------------------------------------- */ static int CompileUnaryOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, int instruction, CompileEnv *envPtr) { Tcl_Token *tokenPtr; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); TclEmitOpcode(instruction, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * CompileAssociativeBinaryOpCmd -- * * Utility routine to compile the binary operator commands that accept an * arbitrary number of arguments, and that are associative operations. * Because of the associativity, we may combine operations from right to * left, saving us any effort of re-ordering the arguments on the stack * after substitutions are completed. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the compiled command at * runtime. * *---------------------------------------------------------------------- */ static int CompileAssociativeBinaryOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, const char *identity, int instruction, CompileEnv *envPtr) { Tcl_Token *tokenPtr = parsePtr->tokenPtr; DefineLineInformation; /* TIP #280 */ int words; /* TODO: Consider support for compiling expanded args. */ for (words=1 ; wordsnumWords ; words++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, words); } if (parsePtr->numWords <= 2) { PushLiteral(envPtr, identity, -1); words++; } if (words > 3) { /* * Reverse order of arguments to get precise agreement with [expr] in * calcuations, including roundoff errors. */ OP4( REVERSE, words-1); } while (--words > 1) { TclEmitOpcode(instruction, envPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * CompileStrictlyBinaryOpCmd -- * * Utility routine to compile the binary operator commands, that strictly * accept exactly two arguments. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the compiled command at * runtime. * *---------------------------------------------------------------------- */ static int CompileStrictlyBinaryOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, int instruction, CompileEnv *envPtr) { if (parsePtr->numWords != 3) { return TCL_ERROR; } return CompileAssociativeBinaryOpCmd(interp, parsePtr, NULL, instruction, envPtr); } /* *---------------------------------------------------------------------- * * CompileComparisonOpCmd -- * * Utility routine to compile the n-ary comparison operator commands. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the compiled command at * runtime. * *---------------------------------------------------------------------- */ static int CompileComparisonOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, int instruction, CompileEnv *envPtr) { Tcl_Token *tokenPtr; DefineLineInformation; /* TIP #280 */ /* TODO: Consider support for compiling expanded args. */ if (parsePtr->numWords < 3) { PUSH("1"); } else if (parsePtr->numWords == 3) { tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); TclEmitOpcode(instruction, envPtr); } else if (envPtr->procPtr == NULL) { /* * No local variable space! */ return TCL_ERROR; } else { int tmpIndex = AnonymousLocal(envPtr); int words; tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); STORE(tmpIndex); TclEmitOpcode(instruction, envPtr); for (words=3 ; wordsnumWords ;) { LOAD(tmpIndex); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, words); if (++words < parsePtr->numWords) { STORE(tmpIndex); } TclEmitOpcode(instruction, envPtr); } for (; words>3 ; words--) { OP( BITAND); } /* * Drop the value from the temp variable; retaining that reference * might be expensive elsewhere. */ OP14( UNSET_SCALAR, 0, tmpIndex); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompile*OpCmd -- * * Procedures called to compile the corresponding "::tcl::mathop::*" * commands. These are all wrappers around the utility operator command * compiler functions, except for the compilers for subtraction and * division, which are special. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the compiled command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileInvertOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileUnaryOpCmd(interp, parsePtr, INST_BITNOT, envPtr); } int TclCompileNotOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileUnaryOpCmd(interp, parsePtr, INST_LNOT, envPtr); } int TclCompileAddOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileAssociativeBinaryOpCmd(interp, parsePtr, "0", INST_ADD, envPtr); } int TclCompileMulOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileAssociativeBinaryOpCmd(interp, parsePtr, "1", INST_MULT, envPtr); } int TclCompileAndOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileAssociativeBinaryOpCmd(interp, parsePtr, "-1", INST_BITAND, envPtr); } int TclCompileOrOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileAssociativeBinaryOpCmd(interp, parsePtr, "0", INST_BITOR, envPtr); } int TclCompileXorOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileAssociativeBinaryOpCmd(interp, parsePtr, "0", INST_BITXOR, envPtr); } int TclCompilePowOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { /* * This one has its own implementation because the ** operator is the only * one with right associativity. */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; DefineLineInformation; /* TIP #280 */ int words; for (words=1 ; wordsnumWords ; words++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, words); } if (parsePtr->numWords <= 2) { PUSH("1"); words++; } while (--words > 1) { TclEmitOpcode(INST_EXPON, envPtr); } return TCL_OK; } int TclCompileLshiftOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_LSHIFT, envPtr); } int TclCompileRshiftOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_RSHIFT, envPtr); } int TclCompileModOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_MOD, envPtr); } int TclCompileNeqOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_NEQ, envPtr); } int TclCompileStrneqOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_STR_NEQ, envPtr); } int TclCompileInOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_LIST_IN, envPtr); } int TclCompileNiOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileStrictlyBinaryOpCmd(interp, parsePtr, INST_LIST_NOT_IN, envPtr); } int TclCompileLessOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_LT, envPtr); } int TclCompileLeqOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_LE, envPtr); } int TclCompileGreaterOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_GT, envPtr); } int TclCompileGeqOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_GE, envPtr); } int TclCompileEqOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_EQ, envPtr); } int TclCompileStreqOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_STR_EQ, envPtr); } int TclCompileMinusOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { Tcl_Token *tokenPtr = parsePtr->tokenPtr; DefineLineInformation; /* TIP #280 */ int words; /* TODO: Consider support for compiling expanded args. */ if (parsePtr->numWords == 1) { /* * Fallback to direct eval to report syntax error. */ return TCL_ERROR; } for (words=1 ; wordsnumWords ; words++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, words); } if (words == 2) { TclEmitOpcode(INST_UMINUS, envPtr); return TCL_OK; } if (words == 3) { TclEmitOpcode(INST_SUB, envPtr); return TCL_OK; } /* * Reverse order of arguments to get precise agreement with [expr] in * calcuations, including roundoff errors. */ TclEmitInstInt4(INST_REVERSE, words-1, envPtr); while (--words > 1) { TclEmitInstInt4(INST_REVERSE, 2, envPtr); TclEmitOpcode(INST_SUB, envPtr); } return TCL_OK; } int TclCompileDivOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { Tcl_Token *tokenPtr = parsePtr->tokenPtr; DefineLineInformation; /* TIP #280 */ int words; /* TODO: Consider support for compiling expanded args. */ if (parsePtr->numWords == 1) { /* * Fallback to direct eval to report syntax error. */ return TCL_ERROR; } if (parsePtr->numWords == 2) { PUSH("1.0"); } for (words=1 ; wordsnumWords ; words++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, words); } if (words <= 3) { TclEmitOpcode(INST_DIV, envPtr); return TCL_OK; } /* * Reverse order of arguments to get precise agreement with [expr] in * calcuations, including roundoff errors. */ TclEmitInstInt4(INST_REVERSE, words-1, envPtr); while (--words > 1) { TclEmitInstInt4(INST_REVERSE, 2, envPtr); TclEmitOpcode(INST_DIV, envPtr); } return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclProc.c0000644000175000017500000023522312663660065014764 0ustar sergeisergei/* * tclProc.c -- * * This file contains routines that implement Tcl procedures, including * the "proc" and "uplevel" commands. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 2004-2006 Miguel Sofer * Copyright (c) 2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" /* * Variables that are part of the [apply] command implementation and which * have to be passed to the other side of the NRE call. */ typedef struct { int isRootEnsemble; Command cmd; ExtraFrameInfo efi; } ApplyExtraData; /* * Prototypes for static functions in this file */ static void DupLambdaInternalRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); static void FreeLambdaInternalRep(Tcl_Obj *objPtr); static int InitArgsAndLocals(Tcl_Interp *interp, Tcl_Obj *procNameObj, int skip); static void InitResolvedLocals(Tcl_Interp *interp, ByteCode *codePtr, Var *defPtr, Namespace *nsPtr); static void InitLocalCache(Proc *procPtr); static void ProcBodyDup(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr); static void ProcBodyFree(Tcl_Obj *objPtr); static int ProcWrongNumArgs(Tcl_Interp *interp, int skip); static void MakeProcError(Tcl_Interp *interp, Tcl_Obj *procNameObj); static void MakeLambdaError(Tcl_Interp *interp, Tcl_Obj *procNameObj); static int SetLambdaFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static Tcl_NRPostProc ApplyNR2; static Tcl_NRPostProc InterpProcNR2; static Tcl_NRPostProc Uplevel_Callback; /* * The ProcBodyObjType type */ const Tcl_ObjType tclProcBodyType = { "procbody", /* name for this type */ ProcBodyFree, /* FreeInternalRep function */ ProcBodyDup, /* DupInternalRep function */ NULL, /* UpdateString function; Tcl_GetString and * Tcl_GetStringFromObj should panic * instead. */ NULL /* SetFromAny function; Tcl_ConvertToType * should panic instead. */ }; /* * The [upvar]/[uplevel] level reference type. Uses the twoPtrValue field, * encoding the type of level reference in ptr and the actual parsed out * offset in ptr2. * * Uses the default behaviour throughout, and never disposes of the string * rep; it's just a cache type. */ static const Tcl_ObjType levelReferenceType = { "levelReference", NULL, NULL, NULL, NULL }; /* * The type of lambdas. Note that every lambda will *always* have a string * representation. * * Internally, ptr1 is a pointer to a Proc instance that is not bound to a * command name, and ptr2 is a pointer to the namespace that the Proc instance * will execute within. IF YOU CHANGE THIS, CHECK IN tclDisassemble.c TOO. */ const Tcl_ObjType tclLambdaType = { "lambdaExpr", /* name */ FreeLambdaInternalRep, /* freeIntRepProc */ DupLambdaInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ SetLambdaFromAny /* setFromAnyProc */ }; /* *---------------------------------------------------------------------- * * Tcl_ProcObjCmd -- * * This object-based function is invoked to process the "proc" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result value. * * Side effects: * A new procedure gets created. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ProcObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register Interp *iPtr = (Interp *) interp; Proc *procPtr; const char *fullName; const char *procName, *procArgs, *procBody; Namespace *nsPtr, *altNsPtr, *cxtNsPtr; Tcl_Command cmd; Tcl_DString ds; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "name args body"); return TCL_ERROR; } /* * Determine the namespace where the procedure should reside. Unless the * command name includes namespace qualifiers, this will be the current * namespace. */ fullName = TclGetString(objv[1]); TclGetNamespaceForQualName(interp, fullName, NULL, 0, &nsPtr, &altNsPtr, &cxtNsPtr, &procName); if (nsPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create procedure \"%s\": unknown namespace", fullName)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL); return TCL_ERROR; } if (procName == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create procedure \"%s\": bad procedure name", fullName)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL); return TCL_ERROR; } if ((nsPtr != iPtr->globalNsPtr) && (procName != NULL) && (procName[0] == ':')) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create procedure \"%s\" in non-global namespace with" " name starting with \":\"", procName)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL); return TCL_ERROR; } /* * Create the data structure to represent the procedure. */ if (TclCreateProc(interp, nsPtr, procName, objv[2], objv[3], &procPtr) != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (creating proc \""); Tcl_AddErrorInfo(interp, procName); Tcl_AddErrorInfo(interp, "\")"); return TCL_ERROR; } /* * Now create a command for the procedure. This will initially be in the * current namespace unless the procedure's name included namespace * qualifiers. To create the new command in the right namespace, we * generate a fully qualified name for it. */ Tcl_DStringInit(&ds); if (nsPtr != iPtr->globalNsPtr) { Tcl_DStringAppend(&ds, nsPtr->fullName, -1); TclDStringAppendLiteral(&ds, "::"); } Tcl_DStringAppend(&ds, procName, -1); cmd = Tcl_NRCreateCommand(interp, Tcl_DStringValue(&ds), TclObjInterpProc, TclNRInterpProc, procPtr, TclProcDeleteProc); Tcl_DStringFree(&ds); /* * Now initialize the new procedure's cmdPtr field. This will be used * later when the procedure is called to determine what namespace the * procedure will run in. This will be different than the current * namespace if the proc was renamed into a different namespace. */ procPtr->cmdPtr = (Command *) cmd; /* * TIP #280: Remember the line the procedure body is starting on. In a * bytecode context we ask the engine to provide us with the necessary * information. This is for the initialization of the byte code compiler * when the body is used for the first time. * * This code is nearly identical to the #280 code in SetLambdaFromAny, see * this file. The differences are the different index of the body in the * line array of the context, and the lambda code requires some special * processing. Find a way to factor the common elements into a single * function. */ if (iPtr->cmdFramePtr) { CmdFrame *contextPtr = TclStackAlloc(interp, sizeof(CmdFrame)); *contextPtr = *iPtr->cmdFramePtr; if (contextPtr->type == TCL_LOCATION_BC) { /* * Retrieve source information from the bytecode, if possible. If * the information is retrieved successfully, context.type will be * TCL_LOCATION_SOURCE and the reference held by * context.data.eval.path will be counted. */ TclGetSrcInfoForPc(contextPtr); } else if (contextPtr->type == TCL_LOCATION_SOURCE) { /* * The copy into 'context' up above has created another reference * to 'context.data.eval.path'; account for it. */ Tcl_IncrRefCount(contextPtr->data.eval.path); } if (contextPtr->type == TCL_LOCATION_SOURCE) { /* * We can account for source location within a proc only if the * proc body was not created by substitution. */ if (contextPtr->line && (contextPtr->nline >= 4) && (contextPtr->line[3] >= 0)) { int isNew; Tcl_HashEntry *hePtr; CmdFrame *cfPtr = ckalloc(sizeof(CmdFrame)); cfPtr->level = -1; cfPtr->type = contextPtr->type; cfPtr->line = ckalloc(sizeof(int)); cfPtr->line[0] = contextPtr->line[3]; cfPtr->nline = 1; cfPtr->framePtr = NULL; cfPtr->nextPtr = NULL; cfPtr->data.eval.path = contextPtr->data.eval.path; Tcl_IncrRefCount(cfPtr->data.eval.path); cfPtr->cmd = NULL; cfPtr->len = 0; hePtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr, procPtr, &isNew); if (!isNew) { /* * Get the old command frame and release it. See also * TclProcCleanupProc in this file. Currently it seems as * if only the procbodytest::proc command of the testsuite * is able to trigger this situation. */ CmdFrame *cfOldPtr = Tcl_GetHashValue(hePtr); if (cfOldPtr->type == TCL_LOCATION_SOURCE) { Tcl_DecrRefCount(cfOldPtr->data.eval.path); cfOldPtr->data.eval.path = NULL; } ckfree(cfOldPtr->line); cfOldPtr->line = NULL; ckfree(cfOldPtr); } Tcl_SetHashValue(hePtr, cfPtr); } /* * 'contextPtr' is going out of scope; account for the reference * that it's holding to the path name. */ Tcl_DecrRefCount(contextPtr->data.eval.path); contextPtr->data.eval.path = NULL; } TclStackFree(interp, contextPtr); } /* * Optimize for no-op procs: if the body is not precompiled (like a TclPro * procbody), and the argument list is just "args" and the body is empty, * define a compileProc to compile a no-op. * * Notes: * - cannot be done for any argument list without having different * compiled/not-compiled behaviour in the "wrong argument #" case, or * making this code much more complicated. In any case, it doesn't * seem to make a lot of sense to verify the number of arguments we * are about to ignore ... * - could be enhanced to handle also non-empty bodies that contain only * comments; however, parsing the body will slow down the compilation * of all procs whose argument list is just _args_ */ if (objv[3]->typePtr == &tclProcBodyType) { goto done; } procArgs = TclGetString(objv[2]); while (*procArgs == ' ') { procArgs++; } if ((procArgs[0] == 'a') && (strncmp(procArgs, "args", 4) == 0)) { int numBytes; procArgs +=4; while (*procArgs != '\0') { if (*procArgs != ' ') { goto done; } procArgs++; } /* * The argument list is just "args"; check the body */ procBody = Tcl_GetStringFromObj(objv[3], &numBytes); if (TclParseAllWhiteSpace(procBody, numBytes) < numBytes) { goto done; } /* * The body is just spaces: link the compileProc */ ((Command *) cmd)->compileProc = TclCompileNoOp; } done: return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCreateProc -- * * Creates the data associated with a Tcl procedure definition. This * function knows how to handle two types of body objects: strings and * procbody. Strings are the traditional (and common) value for bodies, * procbody are values created by extensions that have loaded a * previously compiled script. * * Results: * Returns TCL_OK on success, along with a pointer to a Tcl procedure * definition in procPtrPtr where the cmdPtr field is not initialised. * This definition should be freed by calling TclProcCleanupProc() when * it is no longer needed. Returns TCL_ERROR if anything goes wrong. * * Side effects: * If anything goes wrong, this function returns an error message in the * interpreter. * *---------------------------------------------------------------------- */ int TclCreateProc( Tcl_Interp *interp, /* Interpreter containing proc. */ Namespace *nsPtr, /* Namespace containing this proc. */ const char *procName, /* Unqualified name of this proc. */ Tcl_Obj *argsPtr, /* Description of arguments. */ Tcl_Obj *bodyPtr, /* Command body. */ Proc **procPtrPtr) /* Returns: pointer to proc data. */ { Interp *iPtr = (Interp *) interp; const char **argArray = NULL; register Proc *procPtr; int i, length, result, numArgs; const char *args, *bytes, *p; register CompiledLocal *localPtr = NULL; Tcl_Obj *defPtr; int precompiled = 0; if (bodyPtr->typePtr == &tclProcBodyType) { /* * Because the body is a TclProProcBody, the actual body is already * compiled, and it is not shared with anyone else, so it's OK not to * unshare it (as a matter of fact, it is bad to unshare it, because * there may be no source code). * * We don't create and initialize a Proc structure for the procedure; * rather, we use what is in the body object. We increment the ref * count of the Proc struct since the command (soon to be created) * will be holding a reference to it. */ procPtr = bodyPtr->internalRep.twoPtrValue.ptr1; procPtr->iPtr = iPtr; procPtr->refCount++; precompiled = 1; } else { /* * If the procedure's body object is shared because its string value * is identical to, e.g., the body of another procedure, we must * create a private copy for this procedure to use. Such sharing of * procedure bodies is rare but can cause problems. A procedure body * is compiled in a context that includes the number of "slots" * allocated by the compiler for local variables. There is a local * variable slot for each formal parameter (the * "procPtr->numCompiledLocals = numArgs" assignment below). This * means that the same code can not be shared by two procedures that * have a different number of arguments, even if their bodies are * identical. Note that we don't use Tcl_DuplicateObj since we would * not want any bytecode internal representation. */ if (Tcl_IsShared(bodyPtr)) { Tcl_Obj *sharedBodyPtr = bodyPtr; bytes = TclGetStringFromObj(bodyPtr, &length); bodyPtr = Tcl_NewStringObj(bytes, length); /* * TIP #280. * Ensure that the continuation line data for the original body is * not lost and applies to the new body as well. */ TclContinuationsCopy(bodyPtr, sharedBodyPtr); } /* * Create and initialize a Proc structure for the procedure. We * increment the ref count of the procedure's body object since there * will be a reference to it in the Proc structure. */ Tcl_IncrRefCount(bodyPtr); procPtr = ckalloc(sizeof(Proc)); procPtr->iPtr = iPtr; procPtr->refCount = 1; procPtr->bodyPtr = bodyPtr; procPtr->numArgs = 0; /* Actual argument count is set below. */ procPtr->numCompiledLocals = 0; procPtr->firstLocalPtr = NULL; procPtr->lastLocalPtr = NULL; } /* * Break up the argument list into argument specifiers, then process each * argument specifier. If the body is precompiled, processing is limited * to checking that the parsed argument is consistent with the one stored * in the Proc. * * THIS FAILS IF THE ARG LIST OBJECT'S STRING REP CONTAINS NULS. */ args = TclGetStringFromObj(argsPtr, &length); result = Tcl_SplitList(interp, args, &numArgs, &argArray); if (result != TCL_OK) { goto procError; } if (precompiled) { if (numArgs > procPtr->numArgs) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "procedure \"%s\": arg list contains %d entries, " "precompiled header expects %d", procName, numArgs, procPtr->numArgs)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", "BYTECODELIES", NULL); goto procError; } localPtr = procPtr->firstLocalPtr; } else { procPtr->numArgs = numArgs; procPtr->numCompiledLocals = numArgs; } for (i = 0; i < numArgs; i++) { int fieldCount, nameLength, valueLength; const char **fieldValues; /* * Now divide the specifier up into name and default. */ result = Tcl_SplitList(interp, argArray[i], &fieldCount, &fieldValues); if (result != TCL_OK) { goto procError; } if (fieldCount > 2) { ckfree(fieldValues); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "too many fields in argument specifier \"%s\"", argArray[i])); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", "FORMALARGUMENTFORMAT", NULL); goto procError; } if ((fieldCount == 0) || (*fieldValues[0] == 0)) { ckfree(fieldValues); Tcl_SetObjResult(interp, Tcl_NewStringObj( "argument with no name", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", "FORMALARGUMENTFORMAT", NULL); goto procError; } nameLength = strlen(fieldValues[0]); if (fieldCount == 2) { valueLength = strlen(fieldValues[1]); } else { valueLength = 0; } /* * Check that the formal parameter name is a scalar. */ p = fieldValues[0]; while (*p != '\0') { if (*p == '(') { const char *q = p; do { q++; } while (*q != '\0'); q--; if (*q == ')') { /* We have an array element. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "formal parameter \"%s\" is an array element", fieldValues[0])); ckfree(fieldValues); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", "FORMALARGUMENTFORMAT", NULL); goto procError; } } else if ((*p == ':') && (*(p+1) == ':')) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "formal parameter \"%s\" is not a simple name", fieldValues[0])); ckfree(fieldValues); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", "FORMALARGUMENTFORMAT", NULL); goto procError; } p++; } if (precompiled) { /* * Compare the parsed argument with the stored one. Note that the * only flag value that makes sense at this point is VAR_ARGUMENT * (its value was kept the same as pre VarReform to simplify * tbcload's processing of older byetcodes). * * The only other flag vlaue that is important to retrieve from * precompiled procs is VAR_TEMPORARY (also unchanged). It is * needed later when retrieving the variable names. */ if ((localPtr->nameLength != nameLength) || (strcmp(localPtr->name, fieldValues[0])) || (localPtr->frameIndex != i) || !(localPtr->flags & VAR_ARGUMENT) || (localPtr->defValuePtr == NULL && fieldCount == 2) || (localPtr->defValuePtr != NULL && fieldCount != 2)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "procedure \"%s\": formal parameter %d is " "inconsistent with precompiled body", procName, i)); ckfree(fieldValues); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", "BYTECODELIES", NULL); goto procError; } /* * Compare the default value if any. */ if (localPtr->defValuePtr != NULL) { int tmpLength; const char *tmpPtr = TclGetStringFromObj(localPtr->defValuePtr, &tmpLength); if ((valueLength != tmpLength) || strncmp(fieldValues[1], tmpPtr, (size_t) tmpLength)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "procedure \"%s\": formal parameter \"%s\" has " "default value inconsistent with precompiled body", procName, fieldValues[0])); ckfree(fieldValues); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", "BYTECODELIES", NULL); goto procError; } } if ((i == numArgs - 1) && (localPtr->nameLength == 4) && (localPtr->name[0] == 'a') && (strcmp(localPtr->name, "args") == 0)) { localPtr->flags |= VAR_IS_ARGS; } localPtr = localPtr->nextPtr; } else { /* * Allocate an entry in the runtime procedure frame's array of * local variables for the argument. */ localPtr = ckalloc(TclOffset(CompiledLocal, name) + nameLength+1); if (procPtr->firstLocalPtr == NULL) { procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr; } else { procPtr->lastLocalPtr->nextPtr = localPtr; procPtr->lastLocalPtr = localPtr; } localPtr->nextPtr = NULL; localPtr->nameLength = nameLength; localPtr->frameIndex = i; localPtr->flags = VAR_ARGUMENT; localPtr->resolveInfo = NULL; if (fieldCount == 2) { localPtr->defValuePtr = Tcl_NewStringObj(fieldValues[1], valueLength); Tcl_IncrRefCount(localPtr->defValuePtr); } else { localPtr->defValuePtr = NULL; } memcpy(localPtr->name, fieldValues[0], nameLength + 1); if ((i == numArgs - 1) && (localPtr->nameLength == 4) && (localPtr->name[0] == 'a') && (strcmp(localPtr->name, "args") == 0)) { localPtr->flags |= VAR_IS_ARGS; } } ckfree(fieldValues); } *procPtrPtr = procPtr; ckfree(argArray); return TCL_OK; procError: if (precompiled) { procPtr->refCount--; } else { Tcl_DecrRefCount(bodyPtr); while (procPtr->firstLocalPtr != NULL) { localPtr = procPtr->firstLocalPtr; procPtr->firstLocalPtr = localPtr->nextPtr; defPtr = localPtr->defValuePtr; if (defPtr != NULL) { Tcl_DecrRefCount(defPtr); } ckfree(localPtr); } ckfree(procPtr); } if (argArray != NULL) { ckfree(argArray); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclGetFrame -- * * Given a description of a procedure frame, such as the first argument * to an "uplevel" or "upvar" command, locate the call frame for the * appropriate level of procedure. * * Results: * The return value is -1 if an error occurred in finding the frame (in * this case an error message is left in the interp's result). 1 is * returned if string was either a number or a number preceded by "#" and * it specified a valid frame. 0 is returned if string isn't one of the * two things above (in this case, the lookup acts as if string were * "1"). The variable pointed to by framePtrPtr is filled in with the * address of the desired frame (unless an error occurs, in which case it * isn't modified). * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclGetFrame( Tcl_Interp *interp, /* Interpreter in which to find frame. */ const char *name, /* String describing frame. */ CallFrame **framePtrPtr) /* Store pointer to frame here (or NULL if * global frame indicated). */ { register Interp *iPtr = (Interp *) interp; int curLevel, level, result; CallFrame *framePtr; /* * Parse string to figure out which level number to go to. */ result = 1; curLevel = iPtr->varFramePtr->level; if (*name== '#') { if (Tcl_GetInt(interp, name+1, &level) != TCL_OK || level < 0) { goto levelError; } } else if (isdigit(UCHAR(*name))) { /* INTL: digit */ if (Tcl_GetInt(interp, name, &level) != TCL_OK) { goto levelError; } level = curLevel - level; } else { level = curLevel - 1; result = 0; } /* * Figure out which frame to use, and return it to the caller. */ for (framePtr = iPtr->varFramePtr; framePtr != NULL; framePtr = framePtr->callerVarPtr) { if (framePtr->level == level) { break; } } if (framePtr == NULL) { goto levelError; } *framePtrPtr = framePtr; return result; levelError: Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad level \"%s\"", name)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "STACKLEVEL", NULL); return -1; } /* *---------------------------------------------------------------------- * * TclObjGetFrame -- * * Given a description of a procedure frame, such as the first argument * to an "uplevel" or "upvar" command, locate the call frame for the * appropriate level of procedure. * * Results: * The return value is -1 if an error occurred in finding the frame (in * this case an error message is left in the interp's result). 1 is * returned if objPtr was either a number or a number preceded by "#" and * it specified a valid frame. 0 is returned if objPtr isn't one of the * two things above (in this case, the lookup acts as if objPtr were * "1"). The variable pointed to by framePtrPtr is filled in with the * address of the desired frame (unless an error occurs, in which case it * isn't modified). * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclObjGetFrame( Tcl_Interp *interp, /* Interpreter in which to find frame. */ Tcl_Obj *objPtr, /* Object describing frame. */ CallFrame **framePtrPtr) /* Store pointer to frame here (or NULL if * global frame indicated). */ { register Interp *iPtr = (Interp *) interp; int curLevel, level, result; CallFrame *framePtr; const char *name; /* * Parse object to figure out which level number to go to. */ result = 1; curLevel = iPtr->varFramePtr->level; if (objPtr == NULL) { name = "1"; goto haveLevel1; } name = TclGetString(objPtr); if (objPtr->typePtr == &levelReferenceType) { if (objPtr->internalRep.twoPtrValue.ptr1) { level = curLevel - PTR2INT(objPtr->internalRep.twoPtrValue.ptr2); } else { level = PTR2INT(objPtr->internalRep.twoPtrValue.ptr2); } if (level < 0) { goto levelError; } /* TODO: Consider skipping the typePtr checks */ } else if (objPtr->typePtr == &tclIntType #ifndef TCL_WIDE_INT_IS_LONG || objPtr->typePtr == &tclWideIntType #endif ) { if (TclGetIntFromObj(NULL, objPtr, &level) != TCL_OK || level < 0) { goto levelError; } level = curLevel - level; } else if (*name == '#') { if (Tcl_GetInt(interp, name+1, &level) != TCL_OK || level < 0) { goto levelError; } /* * Cache for future reference. */ TclFreeIntRep(objPtr); objPtr->typePtr = &levelReferenceType; objPtr->internalRep.twoPtrValue.ptr1 = (void *) 0; objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(level); } else if (isdigit(UCHAR(*name))) { /* INTL: digit */ if (Tcl_GetInt(interp, name, &level) != TCL_OK) { return -1; } /* * Cache for future reference. */ TclFreeIntRep(objPtr); objPtr->typePtr = &levelReferenceType; objPtr->internalRep.twoPtrValue.ptr1 = (void *) 1; objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(level); level = curLevel - level; } else { /* * Don't cache as the object *isn't* a level reference (might even be * NULL...) */ haveLevel1: level = curLevel - 1; result = 0; } /* * Figure out which frame to use, and return it to the caller. */ for (framePtr = iPtr->varFramePtr; framePtr != NULL; framePtr = framePtr->callerVarPtr) { if (framePtr->level == level) { break; } } if (framePtr == NULL) { goto levelError; } *framePtrPtr = framePtr; return result; levelError: Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad level \"%s\"", name)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "STACKLEVEL", NULL); return -1; } /* *---------------------------------------------------------------------- * * Tcl_UplevelObjCmd -- * * This object function is invoked to process the "uplevel" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl object result value. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int Uplevel_Callback( ClientData data[], Tcl_Interp *interp, int result) { CallFrame *savedVarFramePtr = data[0]; if (result == TCL_ERROR) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"uplevel\" body line %d)", Tcl_GetErrorLine(interp))); } /* * Restore the variable frame, and return. */ ((Interp *)interp)->varFramePtr = savedVarFramePtr; return result; } /* ARGSUSED */ int Tcl_UplevelObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRUplevelObjCmd, dummy, objc, objv); } int TclNRUplevelObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register Interp *iPtr = (Interp *) interp; CmdFrame *invoker = NULL; int word = 0; int result; CallFrame *savedVarFramePtr, *framePtr; Tcl_Obj *objPtr; if (objc < 2) { uplevelSyntax: Tcl_WrongNumArgs(interp, 1, objv, "?level? command ?arg ...?"); return TCL_ERROR; } /* * Find the level to use for executing the command. */ result = TclObjGetFrame(interp, objv[1], &framePtr); if (result == -1) { return TCL_ERROR; } objc -= result + 1; if (objc == 0) { goto uplevelSyntax; } objv += result + 1; /* * Modify the interpreter state to execute in the given frame. */ savedVarFramePtr = iPtr->varFramePtr; iPtr->varFramePtr = framePtr; /* * Execute the residual arguments as a command. */ if (objc == 1) { /* * TIP #280. Make actual argument location available to eval'd script */ TclArgumentGet(interp, objv[0], &invoker, &word); objPtr = objv[0]; } else { /* * More than one argument: concatenate them together with spaces * between, then evaluate the result. Tcl_EvalObjEx will delete the * object when it decrements its refcount after eval'ing it. */ objPtr = Tcl_ConcatObj(objc, objv); } TclNRAddCallback(interp, Uplevel_Callback, savedVarFramePtr, NULL, NULL, NULL); return TclNREvalObjEx(interp, objPtr, 0, invoker, word); } /* *---------------------------------------------------------------------- * * TclFindProc -- * * Given the name of a procedure, return a pointer to the record * describing the procedure. The procedure will be looked up using the * usual rules: first in the current namespace and then in the global * namespace. * * Results: * NULL is returned if the name doesn't correspond to any procedure. * Otherwise, the return value is a pointer to the procedure's record. If * the name is found but refers to an imported command that points to a * "real" procedure defined in another namespace, a pointer to that * "real" procedure's structure is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ Proc * TclFindProc( Interp *iPtr, /* Interpreter in which to look. */ const char *procName) /* Name of desired procedure. */ { Tcl_Command cmd; Command *cmdPtr; cmd = Tcl_FindCommand((Tcl_Interp *) iPtr, procName, NULL, /*flags*/ 0); if (cmd == (Tcl_Command) NULL) { return NULL; } cmdPtr = (Command *) cmd; return TclIsProc(cmdPtr); } /* *---------------------------------------------------------------------- * * TclIsProc -- * * Tells whether a command is a Tcl procedure or not. * * Results: * If the given command is actually a Tcl procedure, the return value is * the address of the record describing the procedure. Otherwise the * return value is 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ Proc * TclIsProc( Command *cmdPtr) /* Command to test. */ { Tcl_Command origCmd = TclGetOriginalCommand((Tcl_Command) cmdPtr); if (origCmd != NULL) { cmdPtr = (Command *) origCmd; } if (cmdPtr->deleteProc == TclProcDeleteProc) { return cmdPtr->objClientData; } return NULL; } static int ProcWrongNumArgs( Tcl_Interp *interp, int skip) { CallFrame *framePtr = ((Interp *)interp)->varFramePtr; register Proc *procPtr = framePtr->procPtr; register Var *defPtr; int localCt = procPtr->numCompiledLocals, numArgs, i; Tcl_Obj **desiredObjs; const char *final = NULL; /* * Build up desired argument list for Tcl_WrongNumArgs */ numArgs = framePtr->procPtr->numArgs; desiredObjs = TclStackAlloc(interp, (int) sizeof(Tcl_Obj *) * (numArgs+1)); if (framePtr->isProcCallFrame & FRAME_IS_LAMBDA) { desiredObjs[0] = Tcl_NewStringObj("lambdaExpr", -1); } else { ((Interp *) interp)->ensembleRewrite.numInsertedObjs -= skip - 1; #ifdef AVOID_HACKS_FOR_ITCL desiredObjs[0] = framePtr->objv[skip-1]; #else desiredObjs[0] = Tcl_NewListObj(skip, framePtr->objv); #endif /* AVOID_HACKS_FOR_ITCL */ } Tcl_IncrRefCount(desiredObjs[0]); defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt); for (i=1 ; i<=numArgs ; i++, defPtr++) { Tcl_Obj *argObj; Tcl_Obj *namePtr = localName(framePtr, i-1); if (defPtr->value.objPtr != NULL) { TclNewObj(argObj); Tcl_AppendStringsToObj(argObj, "?", TclGetString(namePtr), "?", NULL); } else if (defPtr->flags & VAR_IS_ARGS) { numArgs--; final = "?arg ...?"; break; } else { argObj = namePtr; Tcl_IncrRefCount(namePtr); } desiredObjs[i] = argObj; } Tcl_ResetResult(interp); Tcl_WrongNumArgs(interp, numArgs+1, desiredObjs, final); for (i=0 ; i<=numArgs ; i++) { Tcl_DecrRefCount(desiredObjs[i]); } TclStackFree(interp, desiredObjs); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclInitCompiledLocals -- * * This routine is invoked in order to initialize the compiled locals * table for a new call frame. * * DEPRECATED: functionality has been inlined elsewhere; this function * remains to insure binary compatibility with Itcl. * * Results: * None. * * Side effects: * May invoke various name resolvers in order to determine which * variables are being referenced at runtime. * *---------------------------------------------------------------------- */ void TclInitCompiledLocals( Tcl_Interp *interp, /* Current interpreter. */ CallFrame *framePtr, /* Call frame to initialize. */ Namespace *nsPtr) /* Pointer to current namespace. */ { Var *varPtr = framePtr->compiledLocals; Tcl_Obj *bodyPtr; ByteCode *codePtr; bodyPtr = framePtr->procPtr->bodyPtr; if (bodyPtr->typePtr != &tclByteCodeType) { Tcl_Panic("body object for proc attached to frame is not a byte code type"); } codePtr = bodyPtr->internalRep.twoPtrValue.ptr1; if (framePtr->numCompiledLocals) { if (!codePtr->localCachePtr) { InitLocalCache(framePtr->procPtr) ; } framePtr->localCachePtr = codePtr->localCachePtr; framePtr->localCachePtr->refCount++; } InitResolvedLocals(interp, codePtr, varPtr, nsPtr); } /* *---------------------------------------------------------------------- * * InitResolvedLocals -- * * This routine is invoked in order to initialize the compiled locals * table for a new call frame. * * Results: * None. * * Side effects: * May invoke various name resolvers in order to determine which * variables are being referenced at runtime. * *---------------------------------------------------------------------- */ static void InitResolvedLocals( Tcl_Interp *interp, /* Current interpreter. */ ByteCode *codePtr, Var *varPtr, Namespace *nsPtr) /* Pointer to current namespace. */ { Interp *iPtr = (Interp *) interp; int haveResolvers = (nsPtr->compiledVarResProc || iPtr->resolverPtr); CompiledLocal *firstLocalPtr, *localPtr; int varNum; Tcl_ResolvedVarInfo *resVarInfo; /* * Find the localPtr corresponding to varPtr */ varNum = varPtr - iPtr->framePtr->compiledLocals; localPtr = iPtr->framePtr->procPtr->firstLocalPtr; while (varNum--) { localPtr = localPtr->nextPtr; } if (!(haveResolvers && (codePtr->flags & TCL_BYTECODE_RESOLVE_VARS))) { goto doInitResolvedLocals; } /* * This is the first run after a recompile, or else the resolver epoch * has changed: update the resolver cache. */ firstLocalPtr = localPtr; for (; localPtr != NULL; localPtr = localPtr->nextPtr) { if (localPtr->resolveInfo) { if (localPtr->resolveInfo->deleteProc) { localPtr->resolveInfo->deleteProc(localPtr->resolveInfo); } else { ckfree(localPtr->resolveInfo); } localPtr->resolveInfo = NULL; } localPtr->flags &= ~VAR_RESOLVED; if (haveResolvers && !(localPtr->flags & (VAR_ARGUMENT|VAR_TEMPORARY))) { ResolverScheme *resPtr = iPtr->resolverPtr; Tcl_ResolvedVarInfo *vinfo; int result; if (nsPtr->compiledVarResProc) { result = nsPtr->compiledVarResProc(nsPtr->interp, localPtr->name, localPtr->nameLength, (Tcl_Namespace *) nsPtr, &vinfo); } else { result = TCL_CONTINUE; } while ((result == TCL_CONTINUE) && resPtr) { if (resPtr->compiledVarResProc) { result = resPtr->compiledVarResProc(nsPtr->interp, localPtr->name, localPtr->nameLength, (Tcl_Namespace *) nsPtr, &vinfo); } resPtr = resPtr->nextPtr; } if (result == TCL_OK) { localPtr->resolveInfo = vinfo; localPtr->flags |= VAR_RESOLVED; } } } localPtr = firstLocalPtr; codePtr->flags &= ~TCL_BYTECODE_RESOLVE_VARS; /* * Initialize the array of local variables stored in the call frame. Some * variables may have special resolution rules. In that case, we call * their "resolver" procs to get our hands on the variable, and we make * the compiled local a link to the real variable. */ doInitResolvedLocals: for (; localPtr != NULL; varPtr++, localPtr = localPtr->nextPtr) { varPtr->flags = 0; varPtr->value.objPtr = NULL; /* * Now invoke the resolvers to determine the exact variables that * should be used. */ resVarInfo = localPtr->resolveInfo; if (resVarInfo && resVarInfo->fetchProc) { register Var *resolvedVarPtr = (Var *) resVarInfo->fetchProc(interp, resVarInfo); if (resolvedVarPtr) { if (TclIsVarInHash(resolvedVarPtr)) { VarHashRefCount(resolvedVarPtr)++; } varPtr->flags = VAR_LINK; varPtr->value.linkPtr = resolvedVarPtr; } } } } void TclFreeLocalCache( Tcl_Interp *interp, LocalCache *localCachePtr) { int i; Tcl_Obj **namePtrPtr = &localCachePtr->varName0; for (i = 0; i < localCachePtr->numVars; i++, namePtrPtr++) { register Tcl_Obj *objPtr = *namePtrPtr; if (objPtr) { /* TclReleaseLiteral calls Tcl_DecrRefCount for us */ TclReleaseLiteral(interp, objPtr); } } ckfree(localCachePtr); } static void InitLocalCache( Proc *procPtr) { Interp *iPtr = procPtr->iPtr; ByteCode *codePtr = procPtr->bodyPtr->internalRep.twoPtrValue.ptr1; int localCt = procPtr->numCompiledLocals; int numArgs = procPtr->numArgs, i = 0; Tcl_Obj **namePtr; Var *varPtr; LocalCache *localCachePtr; CompiledLocal *localPtr; int new; /* * Cache the names and initial values of local variables; store the * cache in both the framePtr for this execution and in the codePtr * for future calls. */ localCachePtr = ckalloc(sizeof(LocalCache) + (localCt - 1) * sizeof(Tcl_Obj *) + numArgs * sizeof(Var)); namePtr = &localCachePtr->varName0; varPtr = (Var *) (namePtr + localCt); localPtr = procPtr->firstLocalPtr; while (localPtr) { if (TclIsVarTemporary(localPtr)) { *namePtr = NULL; } else { *namePtr = TclCreateLiteral(iPtr, localPtr->name, localPtr->nameLength, /* hash */ (unsigned int) -1, &new, /* nsPtr */ NULL, 0, NULL); Tcl_IncrRefCount(*namePtr); } if (i < numArgs) { varPtr->flags = (localPtr->flags & VAR_IS_ARGS); varPtr->value.objPtr = localPtr->defValuePtr; varPtr++; i++; } namePtr++; localPtr = localPtr->nextPtr; } codePtr->localCachePtr = localCachePtr; localCachePtr->refCount = 1; localCachePtr->numVars = localCt; } /* *---------------------------------------------------------------------- * * InitArgsAndLocals -- * * This routine is invoked in order to initialize the arguments and other * compiled locals table for a new call frame. * * Results: * A standard Tcl result. * * Side effects: * Allocates memory on the stack for the compiled local variables, the * caller is responsible for freeing them. Initialises all variables. May * invoke various name resolvers in order to determine which variables * are being referenced at runtime. * *---------------------------------------------------------------------- */ static int InitArgsAndLocals( register Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ Tcl_Obj *procNameObj, /* Procedure name for error reporting. */ int skip) /* Number of initial arguments to be skipped, * i.e., words in the "command name". */ { CallFrame *framePtr = ((Interp *)interp)->varFramePtr; register Proc *procPtr = framePtr->procPtr; ByteCode *codePtr = procPtr->bodyPtr->internalRep.twoPtrValue.ptr1; register Var *varPtr, *defPtr; int localCt = procPtr->numCompiledLocals, numArgs, argCt, i, imax; Tcl_Obj *const *argObjs; /* * Make sure that the local cache of variable names and initial values has * been initialised properly . */ if (localCt) { if (!codePtr->localCachePtr) { InitLocalCache(procPtr) ; } framePtr->localCachePtr = codePtr->localCachePtr; framePtr->localCachePtr->refCount++; defPtr = (Var *) (&framePtr->localCachePtr->varName0 + localCt); } else { defPtr = NULL; } /* * Create the "compiledLocals" array. Make sure it is large enough to hold * all the procedure's compiled local variables, including its formal * parameters. */ varPtr = TclStackAlloc(interp, (int)(localCt * sizeof(Var))); framePtr->compiledLocals = varPtr; framePtr->numCompiledLocals = localCt; /* * Match and assign the call's actual parameters to the procedure's formal * arguments. The formal arguments are described by the first numArgs * entries in both the Proc structure's local variable list and the call * frame's local variable array. */ numArgs = procPtr->numArgs; argCt = framePtr->objc - skip; /* Set it to the number of args to the * procedure. */ argObjs = framePtr->objv + skip; if (numArgs == 0) { if (argCt) { goto incorrectArgs; } else { goto correctArgs; } } imax = ((argCt < numArgs-1) ? argCt : numArgs-1); for (i = 0; i < imax; i++, varPtr++, defPtr ? defPtr++ : defPtr) { /* * "Normal" arguments; last formal is special, depends on it being * 'args'. */ Tcl_Obj *objPtr = argObjs[i]; varPtr->flags = 0; varPtr->value.objPtr = objPtr; Tcl_IncrRefCount(objPtr); /* Local var is a reference. */ } for (; i < numArgs-1; i++, varPtr++, defPtr ? defPtr++ : defPtr) { /* * This loop is entered if argCt < (numArgs-1). Set default values; * last formal is special. */ Tcl_Obj *objPtr = defPtr ? defPtr->value.objPtr : NULL; if (!objPtr) { goto incorrectArgs; } varPtr->flags = 0; varPtr->value.objPtr = objPtr; Tcl_IncrRefCount(objPtr); /* Local var reference. */ } /* * When we get here, the last formal argument remains to be defined: * defPtr and varPtr point to the last argument to be initialized. */ varPtr->flags = 0; if (defPtr && defPtr->flags & VAR_IS_ARGS) { Tcl_Obj *listPtr = Tcl_NewListObj(argCt-i, argObjs+i); varPtr->value.objPtr = listPtr; Tcl_IncrRefCount(listPtr); /* Local var is a reference. */ } else if (argCt == numArgs) { Tcl_Obj *objPtr = argObjs[i]; varPtr->value.objPtr = objPtr; Tcl_IncrRefCount(objPtr); /* Local var is a reference. */ } else if ((argCt < numArgs) && defPtr && defPtr->value.objPtr) { Tcl_Obj *objPtr = defPtr->value.objPtr; varPtr->value.objPtr = objPtr; Tcl_IncrRefCount(objPtr); /* Local var is a reference. */ } else { goto incorrectArgs; } varPtr++; /* * Initialise and resolve the remaining compiledLocals. In the absence of * resolvers, they are undefined local vars: (flags=0, value=NULL). */ correctArgs: if (numArgs < localCt) { if (!framePtr->nsPtr->compiledVarResProc && !((Interp *)interp)->resolverPtr) { memset(varPtr, 0, (localCt - numArgs)*sizeof(Var)); } else { InitResolvedLocals(interp, codePtr, varPtr, framePtr->nsPtr); } } return TCL_OK; /* * Initialise all compiled locals to avoid problems at DeleteLocalVars. */ incorrectArgs: memset(varPtr, 0, ((framePtr->compiledLocals + localCt)-varPtr) * sizeof(Var)); return ProcWrongNumArgs(interp, skip); } /* *---------------------------------------------------------------------- * * TclPushProcCallFrame -- * * Compiles a proc body if necessary, then pushes a CallFrame suitable * for executing it. * * Results: * A standard Tcl object result value. * * Side effects: * The proc's body may be recompiled. A CallFrame is pushed, it will have * to be popped by the caller. * *---------------------------------------------------------------------- */ int TclPushProcCallFrame( ClientData clientData, /* Record describing procedure to be * interpreted. */ register Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ int objc, /* Count of number of arguments to this * procedure. */ Tcl_Obj *const objv[], /* Argument value objects. */ int isLambda) /* 1 if this is a call by ApplyObjCmd: it * needs special rules for error msg */ { Proc *procPtr = clientData; Namespace *nsPtr = procPtr->cmdPtr->nsPtr; CallFrame *framePtr, **framePtrPtr; int result; ByteCode *codePtr; /* * If necessary (i.e. if we haven't got a suitable compilation already * cached) compile the procedure's body. The compiler will allocate frame * slots for the procedure's non-argument local variables. Note that * compiling the body might increase procPtr->numCompiledLocals if new * local variables are found while compiling. */ if (procPtr->bodyPtr->typePtr == &tclByteCodeType) { Interp *iPtr = (Interp *) interp; /* * When we've got bytecode, this is the check for validity. That is, * the bytecode must be for the right interpreter (no cross-leaks!), * the code must be from the current epoch (so subcommand compilation * is up-to-date), the namespace must match (so variable handling * is right) and the resolverEpoch must match (so that new shadowed * commands and/or resolver changes are considered). */ codePtr = procPtr->bodyPtr->internalRep.twoPtrValue.ptr1; if (((Interp *) *codePtr->interpHandle != iPtr) || (codePtr->compileEpoch != iPtr->compileEpoch) || (codePtr->nsPtr != nsPtr) || (codePtr->nsEpoch != nsPtr->resolverEpoch)) { goto doCompilation; } } else { doCompilation: result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr, (isLambda ? "body of lambda term" : "body of proc"), TclGetString(objv[isLambda])); if (result != TCL_OK) { return result; } } /* * Set up and push a new call frame for the new procedure invocation. * This call frame will execute in the proc's namespace, which might be * different than the current namespace. The proc's namespace is that of * its command, which can change if the command is renamed from one * namespace to another. */ framePtrPtr = &framePtr; (void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr, (Tcl_Namespace *) nsPtr, (isLambda? (FRAME_IS_PROC|FRAME_IS_LAMBDA) : FRAME_IS_PROC)); framePtr->objc = objc; framePtr->objv = objv; framePtr->procPtr = procPtr; return TCL_OK; } /* *---------------------------------------------------------------------- * * TclObjInterpProc -- * * When a Tcl procedure gets invoked during bytecode evaluation, this * object-based routine gets invoked to interpret the procedure. * * Results: * A standard Tcl object result value. * * Side effects: * Depends on the commands in the procedure. * *---------------------------------------------------------------------- */ int TclObjInterpProc( ClientData clientData, /* Record describing procedure to be * interpreted. */ register Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ int objc, /* Count of number of arguments to this * procedure. */ Tcl_Obj *const objv[]) /* Argument value objects. */ { /* * Not used much in the core; external interface for iTcl */ return Tcl_NRCallObjProc(interp, TclNRInterpProc, clientData, objc, objv); } int TclNRInterpProc( ClientData clientData, /* Record describing procedure to be * interpreted. */ register Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ int objc, /* Count of number of arguments to this * procedure. */ Tcl_Obj *const objv[]) /* Argument value objects. */ { int result = TclPushProcCallFrame(clientData, interp, objc, objv, /*isLambda*/ 0); if (result != TCL_OK) { return TCL_ERROR; } return TclNRInterpProcCore(interp, objv[0], 1, &MakeProcError); } /* *---------------------------------------------------------------------- * * TclNRInterpProcCore -- * * When a Tcl procedure, lambda term or anything else that works like a * procedure gets invoked during bytecode evaluation, this object-based * routine gets invoked to interpret the body. * * Results: * A standard Tcl object result value. * * Side effects: * Nearly anything; depends on the commands in the procedure body. * *---------------------------------------------------------------------- */ int TclNRInterpProcCore( register Tcl_Interp *interp,/* Interpreter in which procedure was * invoked. */ Tcl_Obj *procNameObj, /* Procedure name for error reporting. */ int skip, /* Number of initial arguments to be skipped, * i.e., words in the "command name". */ ProcErrorProc *errorProc) /* How to convert results from the script into * results of the overall procedure. */ { Interp *iPtr = (Interp *) interp; register Proc *procPtr = iPtr->varFramePtr->procPtr; int result; CallFrame *freePtr; ByteCode *codePtr; result = InitArgsAndLocals(interp, procNameObj, skip); if (result != TCL_OK) { freePtr = iPtr->framePtr; Tcl_PopCallFrame(interp); /* Pop but do not free. */ TclStackFree(interp, freePtr->compiledLocals); /* Free compiledLocals. */ TclStackFree(interp, freePtr); /* Free CallFrame. */ return TCL_ERROR; } #if defined(TCL_COMPILE_DEBUG) if (tclTraceExec >= 1) { register CallFrame *framePtr = iPtr->varFramePtr; register int i; if (framePtr->isProcCallFrame & FRAME_IS_LAMBDA) { fprintf(stdout, "Calling lambda "); } else { fprintf(stdout, "Calling proc "); } for (i = 0; i < framePtr->objc; i++) { TclPrintObject(stdout, framePtr->objv[i], 15); fprintf(stdout, " "); } fprintf(stdout, "\n"); fflush(stdout); } #endif /*TCL_COMPILE_DEBUG*/ #ifdef USE_DTRACE if (TCL_DTRACE_PROC_ARGS_ENABLED()) { int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; const char *a[10]; int i; for (i = 0 ; i < 10 ; i++) { a[i] = (l < iPtr->varFramePtr->objc ? TclGetString(iPtr->varFramePtr->objv[l]) : NULL); l++; } TCL_DTRACE_PROC_ARGS(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]); } if (TCL_DTRACE_PROC_INFO_ENABLED() && iPtr->cmdFramePtr) { Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr); const char *a[6]; int i[2]; TclDTraceInfo(info, a, i); TCL_DTRACE_PROC_INFO(a[0], a[1], a[2], a[3], i[0], i[1], a[4], a[5]); TclDecrRefCount(info); } if (TCL_DTRACE_PROC_ENTRY_ENABLED()) { int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; TCL_DTRACE_PROC_ENTRY(l < iPtr->varFramePtr->objc ? TclGetString(iPtr->varFramePtr->objv[l]) : NULL, iPtr->varFramePtr->objc - l - 1, (Tcl_Obj **)(iPtr->varFramePtr->objv + l + 1)); } if (TCL_DTRACE_PROC_ENTRY_ENABLED()) { int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; TCL_DTRACE_PROC_ENTRY(l < iPtr->varFramePtr->objc ? TclGetString(iPtr->varFramePtr->objv[l]) : NULL, iPtr->varFramePtr->objc - l - 1, (Tcl_Obj **)(iPtr->varFramePtr->objv + l + 1)); } #endif /* USE_DTRACE */ /* * Invoke the commands in the procedure's body. */ procPtr->refCount++; codePtr = procPtr->bodyPtr->internalRep.twoPtrValue.ptr1; TclNRAddCallback(interp, InterpProcNR2, procNameObj, errorProc, NULL, NULL); return TclNRExecuteByteCode(interp, codePtr); } static int InterpProcNR2( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Proc *procPtr = iPtr->varFramePtr->procPtr; CallFrame *freePtr; Tcl_Obj *procNameObj = data[0]; ProcErrorProc *errorProc = (ProcErrorProc *)data[1]; if (TCL_DTRACE_PROC_RETURN_ENABLED()) { int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; TCL_DTRACE_PROC_RETURN(l < iPtr->varFramePtr->objc ? TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result); } if (procPtr->refCount-- <= 1) { TclProcCleanupProc(procPtr); } /* * Free the stack-allocated compiled locals and CallFrame. It is important * to pop the call frame without freeing it first: the compiledLocals * cannot be freed before the frame is popped, as the local variables must * be deleted. But the compiledLocals must be freed first, as they were * allocated later on the stack. */ if (result != TCL_OK) { goto process; } done: if (TCL_DTRACE_PROC_RESULT_ENABLED()) { int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0; Tcl_Obj *r = Tcl_GetObjResult(interp); TCL_DTRACE_PROC_RESULT(l < iPtr->varFramePtr->objc ? TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result, TclGetString(r), r); } freePtr = iPtr->framePtr; Tcl_PopCallFrame(interp); /* Pop but do not free. */ TclStackFree(interp, freePtr->compiledLocals); /* Free compiledLocals. */ TclStackFree(interp, freePtr); /* Free CallFrame. */ return result; /* * Process any non-TCL_OK result code. */ process: switch (result) { case TCL_RETURN: /* * If it is a 'return', do the TIP#90 processing now. */ result = TclUpdateReturnInfo((Interp *) interp); break; case TCL_CONTINUE: case TCL_BREAK: /* * It's an error to get to this point from a 'break' or 'continue', so * transform to an error now. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invoked \"%s\" outside of a loop", ((result == TCL_BREAK) ? "break" : "continue"))); Tcl_SetErrorCode(interp, "TCL", "RESULT", "UNEXPECTED", NULL); result = TCL_ERROR; /* * Fall through to the TCL_ERROR handling code. */ case TCL_ERROR: /* * Now it _must_ be an error, so we need to log it as such. This means * filling out the error trace. Luckily, we just hand this off to the * function handed to us as an argument. */ errorProc(interp, procNameObj); } goto done; } /* *---------------------------------------------------------------------- * * TclProcCompileProc -- * * Called just before a procedure is executed to compile the body to byte * codes. If the type of the body is not "byte code" or if the compile * conditions have changed (namespace context, epoch counters, etc.) then * the body is recompiled. Otherwise, this function does nothing. * * Results: * None. * * Side effects: * May change the internal representation of the body object to compiled * code. * *---------------------------------------------------------------------- */ int TclProcCompileProc( Tcl_Interp *interp, /* Interpreter containing procedure. */ Proc *procPtr, /* Data associated with procedure. */ Tcl_Obj *bodyPtr, /* Body of proc. (Usually procPtr->bodyPtr, * but could be any code fragment compiled in * the context of this procedure.) */ Namespace *nsPtr, /* Namespace containing procedure. */ const char *description, /* string describing this body of code. */ const char *procName) /* Name of this procedure. */ { Interp *iPtr = (Interp *) interp; Tcl_CallFrame *framePtr; ByteCode *codePtr = bodyPtr->internalRep.twoPtrValue.ptr1; /* * If necessary, compile the procedure's body. The compiler will allocate * frame slots for the procedure's non-argument local variables. If the * ByteCode already exists, make sure it hasn't been invalidated by * someone redefining a core command (this might make the compiled code * wrong). Also, if the code was compiled in/for a different interpreter, * we recompile it. Note that compiling the body might increase * procPtr->numCompiledLocals if new local variables are found while * compiling. * * Precompiled procedure bodies, however, are immutable and therefore they * are not recompiled, even if things have changed. */ if (bodyPtr->typePtr == &tclByteCodeType) { if (((Interp *) *codePtr->interpHandle == iPtr) && (codePtr->compileEpoch == iPtr->compileEpoch) && (codePtr->nsPtr == nsPtr) && (codePtr->nsEpoch == nsPtr->resolverEpoch)) { return TCL_OK; } if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) { if ((Interp *) *codePtr->interpHandle != iPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "a precompiled script jumped interps", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC", "CROSSINTERPBYTECODE", NULL); return TCL_ERROR; } codePtr->compileEpoch = iPtr->compileEpoch; codePtr->nsPtr = nsPtr; } else { TclFreeIntRep(bodyPtr); } } if (bodyPtr->typePtr != &tclByteCodeType) { Tcl_HashEntry *hePtr; #ifdef TCL_COMPILE_DEBUG if (tclTraceCompile >= 1) { /* * Display a line summarizing the top level command we are about * to compile. */ Tcl_Obj *message; TclNewLiteralStringObj(message, "Compiling "); Tcl_IncrRefCount(message); Tcl_AppendStringsToObj(message, description, " \"", NULL); Tcl_AppendLimitedToObj(message, procName, -1, 50, NULL); fprintf(stdout, "%s\"\n", TclGetString(message)); Tcl_DecrRefCount(message); } #endif /* * Plug the current procPtr into the interpreter and coerce the code * body to byte codes. The interpreter needs to know which proc it's * compiling so that it can access its list of compiled locals. * * TRICKY NOTE: Be careful to push a call frame with the proper * namespace context, so that the byte codes are compiled in the * appropriate class context. */ iPtr->compiledProcPtr = procPtr; if (procPtr->numCompiledLocals > procPtr->numArgs) { CompiledLocal *clPtr = procPtr->firstLocalPtr; CompiledLocal *lastPtr = NULL; int i, numArgs = procPtr->numArgs; for (i = 0; i < numArgs; i++) { lastPtr = clPtr; clPtr = clPtr->nextPtr; } if (lastPtr) { lastPtr->nextPtr = NULL; } else { procPtr->firstLocalPtr = NULL; } procPtr->lastLocalPtr = lastPtr; while (clPtr) { CompiledLocal *toFree = clPtr; clPtr = clPtr->nextPtr; if (toFree->resolveInfo) { if (toFree->resolveInfo->deleteProc) { toFree->resolveInfo->deleteProc(toFree->resolveInfo); } else { ckfree(toFree->resolveInfo); } } ckfree(toFree); } procPtr->numCompiledLocals = procPtr->numArgs; } (void) TclPushStackFrame(interp, &framePtr, (Tcl_Namespace *) nsPtr, /* isProcCallFrame */ 0); /* * TIP #280: We get the invoking context from the cmdFrame which * was saved by 'Tcl_ProcObjCmd' (using linePBodyPtr). */ hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, (char *) procPtr); /* * Constructed saved frame has body as word 0. See Tcl_ProcObjCmd. */ iPtr->invokeWord = 0; iPtr->invokeCmdFramePtr = (hePtr ? Tcl_GetHashValue(hePtr) : NULL); TclSetByteCodeFromAny(interp, bodyPtr, NULL, NULL); iPtr->invokeCmdFramePtr = NULL; TclPopStackFrame(interp); } else if (codePtr->nsEpoch != nsPtr->resolverEpoch) { /* * The resolver epoch has changed, but we only need to invalidate the * resolver cache. */ codePtr->nsEpoch = nsPtr->resolverEpoch; codePtr->flags |= TCL_BYTECODE_RESOLVE_VARS; } return TCL_OK; } /* *---------------------------------------------------------------------- * * MakeProcError -- * * Function called by TclObjInterpProc to create the stack information * upon an error from a procedure. * * Results: * The interpreter's error info trace is set to a value that supplements * the error code. * * Side effects: * none. * *---------------------------------------------------------------------- */ static void MakeProcError( Tcl_Interp *interp, /* The interpreter in which the procedure was * called. */ Tcl_Obj *procNameObj) /* Name of the procedure. Used for error * messages and trace information. */ { int overflow, limit = 60, nameLen; const char *procName = Tcl_GetStringFromObj(procNameObj, &nameLen); overflow = (nameLen > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (procedure \"%.*s%s\" line %d)", (overflow ? limit : nameLen), procName, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } /* *---------------------------------------------------------------------- * * TclProcDeleteProc -- * * This function is invoked just before a command procedure is removed * from an interpreter. Its job is to release all the resources allocated * to the procedure. * * Results: * None. * * Side effects: * Memory gets freed, unless the procedure is actively being executed. * In this case the cleanup is delayed until the last call to the current * procedure completes. * *---------------------------------------------------------------------- */ void TclProcDeleteProc( ClientData clientData) /* Procedure to be deleted. */ { Proc *procPtr = clientData; if (procPtr->refCount-- <= 1) { TclProcCleanupProc(procPtr); } } /* *---------------------------------------------------------------------- * * TclProcCleanupProc -- * * This function does all the real work of freeing up a Proc structure. * It's called only when the structure's reference count becomes zero. * * Results: * None. * * Side effects: * Memory gets freed. * *---------------------------------------------------------------------- */ void TclProcCleanupProc( register Proc *procPtr) /* Procedure to be deleted. */ { register CompiledLocal *localPtr; Tcl_Obj *bodyPtr = procPtr->bodyPtr; Tcl_Obj *defPtr; Tcl_ResolvedVarInfo *resVarInfo; Tcl_HashEntry *hePtr = NULL; CmdFrame *cfPtr = NULL; Interp *iPtr = procPtr->iPtr; if (bodyPtr != NULL) { Tcl_DecrRefCount(bodyPtr); } for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; ) { CompiledLocal *nextPtr = localPtr->nextPtr; resVarInfo = localPtr->resolveInfo; if (resVarInfo) { if (resVarInfo->deleteProc) { resVarInfo->deleteProc(resVarInfo); } else { ckfree(resVarInfo); } } if (localPtr->defValuePtr != NULL) { defPtr = localPtr->defValuePtr; Tcl_DecrRefCount(defPtr); } ckfree(localPtr); localPtr = nextPtr; } ckfree(procPtr); /* * TIP #280: Release the location data associated with this Proc * structure, if any. The interpreter may not exist (For example for * procbody structures created by tbcload. */ if (iPtr == NULL) { return; } hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, (char *) procPtr); if (!hePtr) { return; } cfPtr = Tcl_GetHashValue(hePtr); if (cfPtr) { if (cfPtr->type == TCL_LOCATION_SOURCE) { Tcl_DecrRefCount(cfPtr->data.eval.path); cfPtr->data.eval.path = NULL; } ckfree(cfPtr->line); cfPtr->line = NULL; ckfree(cfPtr); } Tcl_DeleteHashEntry(hePtr); } /* *---------------------------------------------------------------------- * * TclUpdateReturnInfo -- * * This function is called when procedures return, and at other points * where the TCL_RETURN code is used. It examines the returnLevel and * returnCode to determine the real return status. * * Results: * The return value is the true completion code to use for the procedure * or script, instead of TCL_RETURN. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclUpdateReturnInfo( Interp *iPtr) /* Interpreter for which TCL_RETURN exception * is being processed. */ { int code = TCL_RETURN; iPtr->returnLevel--; if (iPtr->returnLevel < 0) { Tcl_Panic("TclUpdateReturnInfo: negative return level"); } if (iPtr->returnLevel == 0) { /* * Now we've reached the level to return the requested -code. * Since iPtr->returnLevel and iPtr->returnCode have completed * their task, we now reset them to default values so that any * bare "return TCL_RETURN" that may follow will work [Bug 2152286]. */ code = iPtr->returnCode; iPtr->returnLevel = 1; iPtr->returnCode = TCL_OK; if (code == TCL_ERROR) { iPtr->flags |= ERR_LEGACY_COPY; } } return code; } /* *---------------------------------------------------------------------- * * TclGetObjInterpProc -- * * Returns a pointer to the TclObjInterpProc function; this is different * from the value obtained from the TclObjInterpProc reference on systems * like Windows where import and export versions of a function exported * by a DLL exist. * * Results: * Returns the internal address of the TclObjInterpProc function. * * Side effects: * None. * *---------------------------------------------------------------------- */ TclObjCmdProcType TclGetObjInterpProc(void) { return (TclObjCmdProcType) TclObjInterpProc; } /* *---------------------------------------------------------------------- * * TclNewProcBodyObj -- * * Creates a new object, of type "procbody", whose internal * representation is the given Proc struct. The newly created object's * reference count is 0. * * Results: * Returns a pointer to a newly allocated Tcl_Obj, NULL on error. * * Side effects: * The reference count in the ByteCode attached to the Proc is bumped up * by one, since the internal rep stores a pointer to it. * *---------------------------------------------------------------------- */ Tcl_Obj * TclNewProcBodyObj( Proc *procPtr) /* the Proc struct to store as the internal * representation. */ { Tcl_Obj *objPtr; if (!procPtr) { return NULL; } TclNewObj(objPtr); if (objPtr) { objPtr->typePtr = &tclProcBodyType; objPtr->internalRep.twoPtrValue.ptr1 = procPtr; procPtr->refCount++; } return objPtr; } /* *---------------------------------------------------------------------- * * ProcBodyDup -- * * Tcl_ObjType's Dup function for the proc body object. Bumps the * reference count on the Proc stored in the internal representation. * * Results: * None. * * Side effects: * Sets up the object in dupPtr to be a duplicate of the one in srcPtr. * *---------------------------------------------------------------------- */ static void ProcBodyDup( Tcl_Obj *srcPtr, /* Object to copy. */ Tcl_Obj *dupPtr) /* Target object for the duplication. */ { Proc *procPtr = srcPtr->internalRep.twoPtrValue.ptr1; dupPtr->typePtr = &tclProcBodyType; dupPtr->internalRep.twoPtrValue.ptr1 = procPtr; procPtr->refCount++; } /* *---------------------------------------------------------------------- * * ProcBodyFree -- * * Tcl_ObjType's Free function for the proc body object. The reference * count on its Proc struct is decreased by 1; if the count reaches 0, * the proc is freed. * * Results: * None. * * Side effects: * If the reference count on the Proc struct reaches 0, the struct is * freed. * *---------------------------------------------------------------------- */ static void ProcBodyFree( Tcl_Obj *objPtr) /* The object to clean up. */ { Proc *procPtr = objPtr->internalRep.twoPtrValue.ptr1; if (procPtr->refCount-- <= 1) { TclProcCleanupProc(procPtr); } } /* *---------------------------------------------------------------------- * * DupLambdaInternalRep, FreeLambdaInternalRep, SetLambdaFromAny -- * * How to manage the internal representations of lambda term objects. * Syntactically they look like a two- or three-element list, where the * first element is the formal arguments, the second is the the body, and * the (optional) third is the namespace to execute the lambda term * within (the global namespace is assumed if it is absent). * *---------------------------------------------------------------------- */ static void DupLambdaInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ register Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { Proc *procPtr = srcPtr->internalRep.twoPtrValue.ptr1; Tcl_Obj *nsObjPtr = srcPtr->internalRep.twoPtrValue.ptr2; copyPtr->internalRep.twoPtrValue.ptr1 = procPtr; copyPtr->internalRep.twoPtrValue.ptr2 = nsObjPtr; procPtr->refCount++; Tcl_IncrRefCount(nsObjPtr); copyPtr->typePtr = &tclLambdaType; } static void FreeLambdaInternalRep( register Tcl_Obj *objPtr) /* CmdName object with internal representation * to free. */ { Proc *procPtr = objPtr->internalRep.twoPtrValue.ptr1; Tcl_Obj *nsObjPtr = objPtr->internalRep.twoPtrValue.ptr2; if (procPtr->refCount-- == 1) { TclProcCleanupProc(procPtr); } TclDecrRefCount(nsObjPtr); objPtr->typePtr = NULL; } static int SetLambdaFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr) /* The object to convert. */ { Interp *iPtr = (Interp *) interp; const char *name; Tcl_Obj *argsPtr, *bodyPtr, *nsObjPtr, **objv; int isNew, objc, result; CmdFrame *cfPtr = NULL; Proc *procPtr; if (interp == NULL) { return TCL_ERROR; } /* * Convert objPtr to list type first; if it cannot be converted, or if its * length is not 2, then it cannot be converted to tclLambdaType. */ result = TclListObjGetElements(NULL, objPtr, &objc, &objv); if ((result != TCL_OK) || ((objc != 2) && (objc != 3))) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't interpret \"%s\" as a lambda expression", Tcl_GetString(objPtr))); Tcl_SetErrorCode(interp, "TCL", "VALUE", "LAMBDA", NULL); return TCL_ERROR; } argsPtr = objv[0]; bodyPtr = objv[1]; /* * Create and initialize the Proc struct. The cmdPtr field is set to NULL * to signal that this is an anonymous function. */ name = TclGetString(objPtr); if (TclCreateProc(interp, /*ignored nsPtr*/ NULL, name, argsPtr, bodyPtr, &procPtr) != TCL_OK) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (parsing lambda expression \"%s\")", name)); return TCL_ERROR; } /* * CAREFUL: TclCreateProc returns refCount==1! [Bug 1578454] * procPtr->refCount = 1; */ procPtr->cmdPtr = NULL; /* * TIP #280: Remember the line the apply body is starting on. In a Byte * code context we ask the engine to provide us with the necessary * information. This is for the initialization of the byte code compiler * when the body is used for the first time. * * NOTE: The body is the second word in the 'objPtr'. Its location, * accessible through 'context.line[1]' (see below) is therefore only the * first approximation of the actual line the body is on. We have to use * the string rep of the 'objPtr' to determine the exact line. This is * available already through 'name'. Use 'TclListLines', see 'switch' * (tclCmdMZ.c). * * This code is nearly identical to the #280 code in Tcl_ProcObjCmd, see * this file. The differences are the different index of the body in the * line array of the context, and the special processing mentioned in the * previous paragraph to track into the list. Find a way to factor the * common elements into a single function. */ if (iPtr->cmdFramePtr) { CmdFrame *contextPtr = TclStackAlloc(interp, sizeof(CmdFrame)); *contextPtr = *iPtr->cmdFramePtr; if (contextPtr->type == TCL_LOCATION_BC) { /* * Retrieve the source context from the bytecode. This call * accounts for the reference to the source file, if any, held in * 'context.data.eval.path'. */ TclGetSrcInfoForPc(contextPtr); } else if (contextPtr->type == TCL_LOCATION_SOURCE) { /* * We created a new reference to the source file path name when we * created 'context' above. Account for the reference. */ Tcl_IncrRefCount(contextPtr->data.eval.path); } if (contextPtr->type == TCL_LOCATION_SOURCE) { /* * We can record source location within a lambda only if the body * was not created by substitution. */ if (contextPtr->line && (contextPtr->nline >= 2) && (contextPtr->line[1] >= 0)) { int buf[2]; /* * Move from approximation (line of list cmd word) to actual * location (line of 2nd list element). */ cfPtr = ckalloc(sizeof(CmdFrame)); TclListLines(objPtr, contextPtr->line[1], 2, buf, NULL); cfPtr->level = -1; cfPtr->type = contextPtr->type; cfPtr->line = ckalloc(sizeof(int)); cfPtr->line[0] = buf[1]; cfPtr->nline = 1; cfPtr->framePtr = NULL; cfPtr->nextPtr = NULL; cfPtr->data.eval.path = contextPtr->data.eval.path; Tcl_IncrRefCount(cfPtr->data.eval.path); cfPtr->cmd = NULL; cfPtr->len = 0; } /* * 'contextPtr' is going out of scope. Release the reference that * it's holding to the source file path */ Tcl_DecrRefCount(contextPtr->data.eval.path); } TclStackFree(interp, contextPtr); } Tcl_SetHashValue(Tcl_CreateHashEntry(iPtr->linePBodyPtr, procPtr, &isNew), cfPtr); /* * Set the namespace for this lambda: given by objv[2] understood as a * global reference, or else global per default. */ if (objc == 2) { TclNewLiteralStringObj(nsObjPtr, "::"); } else { const char *nsName = TclGetString(objv[2]); if ((*nsName != ':') || (*(nsName+1) != ':')) { TclNewLiteralStringObj(nsObjPtr, "::"); Tcl_AppendObjToObj(nsObjPtr, objv[2]); } else { nsObjPtr = objv[2]; } } Tcl_IncrRefCount(nsObjPtr); /* * Free the list internalrep of objPtr - this will free argsPtr, but * bodyPtr retains a reference from the Proc structure. Then finish the * conversion to tclLambdaType. */ TclFreeIntRep(objPtr); objPtr->internalRep.twoPtrValue.ptr1 = procPtr; objPtr->internalRep.twoPtrValue.ptr2 = nsObjPtr; objPtr->typePtr = &tclLambdaType; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ApplyObjCmd -- * * This object-based function is invoked to process the "apply" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result value. * * Side effects: * Depends on the content of the lambda term (i.e., objv[1]). * *---------------------------------------------------------------------- */ int Tcl_ApplyObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRApplyObjCmd, dummy, objc, objv); } int TclNRApplyObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; Proc *procPtr = NULL; Tcl_Obj *lambdaPtr, *nsObjPtr; int result, isRootEnsemble; Tcl_Namespace *nsPtr; ApplyExtraData *extraPtr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "lambdaExpr ?arg ...?"); return TCL_ERROR; } /* * Set lambdaPtr, convert it to tclLambdaType in the current interp if * necessary. */ lambdaPtr = objv[1]; if (lambdaPtr->typePtr == &tclLambdaType) { procPtr = lambdaPtr->internalRep.twoPtrValue.ptr1; } #define JOE_EXTENSION 0 /* * Note: this code is NOT FUNCTIONAL due to the NR implementation; DO NOT * ENABLE! Leaving here as reminder to (a) TIP the suggestion, and (b) adapt * the code. (MS) */ #if JOE_EXTENSION else { /* * Joe English's suggestion to allow cmdNames to function as lambdas. */ Tcl_Obj *elemPtr; int numElem; if ((lambdaPtr->typePtr == &tclCmdNameType) || (TclListObjGetElements(interp, lambdaPtr, &numElem, &elemPtr) == TCL_OK && numElem == 1)) { return Tcl_EvalObjv(interp, objc-1, objv+1, 0); } } #endif if ((procPtr == NULL) || (procPtr->iPtr != iPtr)) { result = SetLambdaFromAny(interp, lambdaPtr); if (result != TCL_OK) { return result; } procPtr = lambdaPtr->internalRep.twoPtrValue.ptr1; } /* * Find the namespace where this lambda should run, and push a call frame * for that namespace. Note that TclObjInterpProc() will pop it. */ nsObjPtr = lambdaPtr->internalRep.twoPtrValue.ptr2; result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); if (result != TCL_OK) { return TCL_ERROR; } extraPtr = TclStackAlloc(interp, sizeof(ApplyExtraData)); memset(&extraPtr->cmd, 0, sizeof(Command)); procPtr->cmdPtr = &extraPtr->cmd; extraPtr->cmd.nsPtr = (Namespace *) nsPtr; /* * TIP#280 (semi-)HACK! * * Using cmd.clientData to tell [info frame] how to render the lambdaPtr. * The InfoFrameCmd will detect this case by testing cmd.hPtr for NULL. * This condition holds here because of the memset() above, and nowhere * else (in the core). Regular commands always have a valid hPtr, and * lambda's never. */ extraPtr->efi.length = 1; extraPtr->efi.fields[0].name = "lambda"; extraPtr->efi.fields[0].proc = NULL; extraPtr->efi.fields[0].clientData = lambdaPtr; extraPtr->cmd.clientData = &extraPtr->efi; isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL); if (isRootEnsemble) { iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = 1; iPtr->ensembleRewrite.numInsertedObjs = 0; } else { iPtr->ensembleRewrite.numInsertedObjs -= 1; } extraPtr->isRootEnsemble = isRootEnsemble; result = TclPushProcCallFrame(procPtr, interp, objc, objv, 1); if (result == TCL_OK) { TclNRAddCallback(interp, ApplyNR2, extraPtr, NULL, NULL, NULL); result = TclNRInterpProcCore(interp, objv[1], 2, &MakeLambdaError); } return result; } static int ApplyNR2( ClientData data[], Tcl_Interp *interp, int result) { ApplyExtraData *extraPtr = data[0]; if (extraPtr->isRootEnsemble) { ((Interp *) interp)->ensembleRewrite.sourceObjs = NULL; } TclStackFree(interp, extraPtr); return result; } /* *---------------------------------------------------------------------- * * MakeLambdaError -- * * Function called by TclObjInterpProc to create the stack information * upon an error from a lambda term. * * Results: * The interpreter's error info trace is set to a value that supplements * the error code. * * Side effects: * none. * *---------------------------------------------------------------------- */ static void MakeLambdaError( Tcl_Interp *interp, /* The interpreter in which the procedure was * called. */ Tcl_Obj *procNameObj) /* Name of the procedure. Used for error * messages and trace information. */ { int overflow, limit = 60, nameLen; const char *procName = Tcl_GetStringFromObj(procNameObj, &nameLen); overflow = (nameLen > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (lambda term \"%.*s%s\" line %d)", (overflow ? limit : nameLen), procName, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclResult.c0000644000175000017500000013261212663660065015335 0ustar sergeisergei/* * tclResult.c -- * * This file contains code to manage the interpreter result. * * Copyright (c) 1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Indices of the standard return options dictionary keys. */ enum returnKeys { KEY_CODE, KEY_ERRORCODE, KEY_ERRORINFO, KEY_ERRORLINE, KEY_LEVEL, KEY_OPTIONS, KEY_ERRORSTACK, KEY_LAST }; /* * Function prototypes for local functions in this file: */ static Tcl_Obj ** GetKeys(void); static void ReleaseKeys(ClientData clientData); static void ResetObjResult(Interp *iPtr); static void SetupAppendBuffer(Interp *iPtr, int newSpace); /* * This structure is used to take a snapshot of the interpreter state in * Tcl_SaveInterpState. You can snapshot the state, execute a command, and * then back up to the result or the error that was previously in progress. */ typedef struct InterpState { int status; /* return code status */ int flags; /* Each remaining field saves the */ int returnLevel; /* corresponding field of the Interp */ int returnCode; /* struct. These fields taken together are */ Tcl_Obj *errorInfo; /* the "state" of the interp. */ Tcl_Obj *errorCode; Tcl_Obj *returnOpts; Tcl_Obj *objResult; Tcl_Obj *errorStack; int resetErrorStack; } InterpState; /* *---------------------------------------------------------------------- * * Tcl_SaveInterpState -- * * Fills a token with a snapshot of the current state of the interpreter. * The snapshot can be restored at any point by TclRestoreInterpState. * * The token returned must be eventally passed to one of the routines * TclRestoreInterpState or TclDiscardInterpState, or there will be a * memory leak. * * Results: * Returns a token representing the interp state. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_InterpState Tcl_SaveInterpState( Tcl_Interp *interp, /* Interpreter's state to be saved */ int status) /* status code for current operation */ { Interp *iPtr = (Interp *) interp; InterpState *statePtr = ckalloc(sizeof(InterpState)); statePtr->status = status; statePtr->flags = iPtr->flags & ERR_ALREADY_LOGGED; statePtr->returnLevel = iPtr->returnLevel; statePtr->returnCode = iPtr->returnCode; statePtr->errorInfo = iPtr->errorInfo; statePtr->errorStack = iPtr->errorStack; statePtr->resetErrorStack = iPtr->resetErrorStack; if (statePtr->errorInfo) { Tcl_IncrRefCount(statePtr->errorInfo); } statePtr->errorCode = iPtr->errorCode; if (statePtr->errorCode) { Tcl_IncrRefCount(statePtr->errorCode); } statePtr->returnOpts = iPtr->returnOpts; if (statePtr->returnOpts) { Tcl_IncrRefCount(statePtr->returnOpts); } if (statePtr->errorStack) { Tcl_IncrRefCount(statePtr->errorStack); } statePtr->objResult = Tcl_GetObjResult(interp); Tcl_IncrRefCount(statePtr->objResult); return (Tcl_InterpState) statePtr; } /* *---------------------------------------------------------------------- * * Tcl_RestoreInterpState -- * * Accepts an interp and a token previously returned by * Tcl_SaveInterpState. Restore the state of the interp to what it was at * the time of the Tcl_SaveInterpState call. * * Results: * Returns the status value originally passed in to Tcl_SaveInterpState. * * Side effects: * Restores the interp state and frees memory held by token. * *---------------------------------------------------------------------- */ int Tcl_RestoreInterpState( Tcl_Interp *interp, /* Interpreter's state to be restored. */ Tcl_InterpState state) /* Saved interpreter state. */ { Interp *iPtr = (Interp *) interp; InterpState *statePtr = (InterpState *) state; int status = statePtr->status; iPtr->flags &= ~ERR_ALREADY_LOGGED; iPtr->flags |= (statePtr->flags & ERR_ALREADY_LOGGED); iPtr->returnLevel = statePtr->returnLevel; iPtr->returnCode = statePtr->returnCode; iPtr->resetErrorStack = statePtr->resetErrorStack; if (iPtr->errorInfo) { Tcl_DecrRefCount(iPtr->errorInfo); } iPtr->errorInfo = statePtr->errorInfo; if (iPtr->errorInfo) { Tcl_IncrRefCount(iPtr->errorInfo); } if (iPtr->errorCode) { Tcl_DecrRefCount(iPtr->errorCode); } iPtr->errorCode = statePtr->errorCode; if (iPtr->errorCode) { Tcl_IncrRefCount(iPtr->errorCode); } if (iPtr->errorStack) { Tcl_DecrRefCount(iPtr->errorStack); } iPtr->errorStack = statePtr->errorStack; if (iPtr->errorStack) { Tcl_IncrRefCount(iPtr->errorStack); } if (iPtr->returnOpts) { Tcl_DecrRefCount(iPtr->returnOpts); } iPtr->returnOpts = statePtr->returnOpts; if (iPtr->returnOpts) { Tcl_IncrRefCount(iPtr->returnOpts); } Tcl_SetObjResult(interp, statePtr->objResult); Tcl_DiscardInterpState(state); return status; } /* *---------------------------------------------------------------------- * * Tcl_DiscardInterpState -- * * Accepts a token previously returned by Tcl_SaveInterpState. Frees the * memory it uses. * * Results: * None. * * Side effects: * Frees memory. * *---------------------------------------------------------------------- */ void Tcl_DiscardInterpState( Tcl_InterpState state) /* saved interpreter state */ { InterpState *statePtr = (InterpState *) state; if (statePtr->errorInfo) { Tcl_DecrRefCount(statePtr->errorInfo); } if (statePtr->errorCode) { Tcl_DecrRefCount(statePtr->errorCode); } if (statePtr->returnOpts) { Tcl_DecrRefCount(statePtr->returnOpts); } if (statePtr->errorStack) { Tcl_DecrRefCount(statePtr->errorStack); } Tcl_DecrRefCount(statePtr->objResult); ckfree(statePtr); } /* *---------------------------------------------------------------------- * * Tcl_SaveResult -- * * Takes a snapshot of the current result state of the interpreter. The * snapshot can be restored at any point by Tcl_RestoreResult. Note that * this routine does not preserve the errorCode, errorInfo, or flags * fields so it should not be used if an error is in progress. * * Once a snapshot is saved, it must be restored by calling * Tcl_RestoreResult, or discarded by calling Tcl_DiscardResult. * * Results: * None. * * Side effects: * Resets the interpreter result. * *---------------------------------------------------------------------- */ #undef Tcl_SaveResult void Tcl_SaveResult( Tcl_Interp *interp, /* Interpreter to save. */ Tcl_SavedResult *statePtr) /* Pointer to state structure. */ { Interp *iPtr = (Interp *) interp; /* * Move the result object into the save state. Note that we don't need to * change its refcount because we're moving it, not adding a new * reference. Put an empty object into the interpreter. */ statePtr->objResultPtr = iPtr->objResultPtr; iPtr->objResultPtr = Tcl_NewObj(); Tcl_IncrRefCount(iPtr->objResultPtr); /* * Save the string result. */ statePtr->freeProc = iPtr->freeProc; if (iPtr->result == iPtr->resultSpace) { /* * Copy the static string data out of the interp buffer. */ statePtr->result = statePtr->resultSpace; strcpy(statePtr->result, iPtr->result); statePtr->appendResult = NULL; } else if (iPtr->result == iPtr->appendResult) { /* * Move the append buffer out of the interp. */ statePtr->appendResult = iPtr->appendResult; statePtr->appendAvl = iPtr->appendAvl; statePtr->appendUsed = iPtr->appendUsed; statePtr->result = statePtr->appendResult; iPtr->appendResult = NULL; iPtr->appendAvl = 0; iPtr->appendUsed = 0; } else { /* * Move the dynamic or static string out of the interpreter. */ statePtr->result = iPtr->result; statePtr->appendResult = NULL; } iPtr->result = iPtr->resultSpace; iPtr->resultSpace[0] = 0; iPtr->freeProc = 0; } /* *---------------------------------------------------------------------- * * Tcl_RestoreResult -- * * Restores the state of the interpreter to a snapshot taken by * Tcl_SaveResult. After this call, the token for the interpreter state * is no longer valid. * * Results: * None. * * Side effects: * Restores the interpreter result. * *---------------------------------------------------------------------- */ #undef Tcl_RestoreResult void Tcl_RestoreResult( Tcl_Interp *interp, /* Interpreter being restored. */ Tcl_SavedResult *statePtr) /* State returned by Tcl_SaveResult. */ { Interp *iPtr = (Interp *) interp; Tcl_ResetResult(interp); /* * Restore the string result. */ iPtr->freeProc = statePtr->freeProc; if (statePtr->result == statePtr->resultSpace) { /* * Copy the static string data into the interp buffer. */ iPtr->result = iPtr->resultSpace; strcpy(iPtr->result, statePtr->result); } else if (statePtr->result == statePtr->appendResult) { /* * Move the append buffer back into the interp. */ if (iPtr->appendResult != NULL) { ckfree(iPtr->appendResult); } iPtr->appendResult = statePtr->appendResult; iPtr->appendAvl = statePtr->appendAvl; iPtr->appendUsed = statePtr->appendUsed; iPtr->result = iPtr->appendResult; } else { /* * Move the dynamic or static string back into the interpreter. */ iPtr->result = statePtr->result; } /* * Restore the object result. */ Tcl_DecrRefCount(iPtr->objResultPtr); iPtr->objResultPtr = statePtr->objResultPtr; } /* *---------------------------------------------------------------------- * * Tcl_DiscardResult -- * * Frees the memory associated with an interpreter snapshot taken by * Tcl_SaveResult. If the snapshot is not restored, this function must be * called to discard it, or the memory will be lost. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ #undef Tcl_DiscardResult void Tcl_DiscardResult( Tcl_SavedResult *statePtr) /* State returned by Tcl_SaveResult. */ { TclDecrRefCount(statePtr->objResultPtr); if (statePtr->result == statePtr->appendResult) { ckfree(statePtr->appendResult); } else if (statePtr->freeProc == TCL_DYNAMIC) { ckfree(statePtr->result); } else if (statePtr->freeProc) { statePtr->freeProc(statePtr->result); } } /* *---------------------------------------------------------------------- * * Tcl_SetResult -- * * Arrange for "result" to be the Tcl return value. * * Results: * None. * * Side effects: * interp->result is left pointing either to "result" or to a copy of it. * Also, the object result is reset. * *---------------------------------------------------------------------- */ void Tcl_SetResult( Tcl_Interp *interp, /* Interpreter with which to associate the * return value. */ register char *result, /* Value to be returned. If NULL, the result * is set to an empty string. */ Tcl_FreeProc *freeProc) /* Gives information about the string: * TCL_STATIC, TCL_VOLATILE, or the address of * a Tcl_FreeProc such as free. */ { Interp *iPtr = (Interp *) interp; register Tcl_FreeProc *oldFreeProc = iPtr->freeProc; char *oldResult = iPtr->result; if (result == NULL) { iPtr->resultSpace[0] = 0; iPtr->result = iPtr->resultSpace; iPtr->freeProc = 0; } else if (freeProc == TCL_VOLATILE) { int length = strlen(result); if (length > TCL_RESULT_SIZE) { iPtr->result = ckalloc(length + 1); iPtr->freeProc = TCL_DYNAMIC; } else { iPtr->result = iPtr->resultSpace; iPtr->freeProc = 0; } memcpy(iPtr->result, result, (unsigned) length+1); } else { iPtr->result = (char *) result; iPtr->freeProc = freeProc; } /* * If the old result was dynamically-allocated, free it up. Do it here, * rather than at the beginning, in case the new result value was part of * the old result value. */ if (oldFreeProc != 0) { if (oldFreeProc == TCL_DYNAMIC) { ckfree(oldResult); } else { oldFreeProc(oldResult); } } /* * Reset the object result since we just set the string result. */ ResetObjResult(iPtr); } /* *---------------------------------------------------------------------- * * Tcl_GetStringResult -- * * Returns an interpreter's result value as a string. * * Results: * The interpreter's result as a string. * * Side effects: * If the string result is empty, the object result is moved to the * string result, then the object result is reset. * *---------------------------------------------------------------------- */ const char * Tcl_GetStringResult( register Tcl_Interp *interp)/* Interpreter whose result to return. */ { /* * If the string result is empty, move the object result to the string * result, then reset the object result. */ Interp *iPtr = (Interp *) interp; if (*(iPtr->result) == 0) { Tcl_SetResult(interp, TclGetString(Tcl_GetObjResult(interp)), TCL_VOLATILE); } return iPtr->result; } /* *---------------------------------------------------------------------- * * Tcl_SetObjResult -- * * Arrange for objPtr to be an interpreter's result value. * * Results: * None. * * Side effects: * interp->objResultPtr is left pointing to the object referenced by * objPtr. The object's reference count is incremented since there is now * a new reference to it. The reference count for any old objResultPtr * value is decremented. Also, the string result is reset. * *---------------------------------------------------------------------- */ void Tcl_SetObjResult( Tcl_Interp *interp, /* Interpreter with which to associate the * return object value. */ register Tcl_Obj *objPtr) /* Tcl object to be returned. If NULL, the obj * result is made an empty string object. */ { register Interp *iPtr = (Interp *) interp; register Tcl_Obj *oldObjResult = iPtr->objResultPtr; iPtr->objResultPtr = objPtr; Tcl_IncrRefCount(objPtr); /* since interp result is a reference */ /* * We wait until the end to release the old object result, in case we are * setting the result to itself. */ TclDecrRefCount(oldObjResult); /* * Reset the string result since we just set the result object. */ if (iPtr->freeProc != NULL) { if (iPtr->freeProc == TCL_DYNAMIC) { ckfree(iPtr->result); } else { iPtr->freeProc(iPtr->result); } iPtr->freeProc = 0; } iPtr->result = iPtr->resultSpace; iPtr->resultSpace[0] = 0; } /* *---------------------------------------------------------------------- * * Tcl_GetObjResult -- * * Returns an interpreter's result value as a Tcl object. The object's * reference count is not modified; the caller must do that if it needs * to hold on to a long-term reference to it. * * Results: * The interpreter's result as an object. * * Side effects: * If the interpreter has a non-empty string result, the result object is * either empty or stale because some function set interp->result * directly. If so, the string result is moved to the result object then * the string result is reset. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_GetObjResult( Tcl_Interp *interp) /* Interpreter whose result to return. */ { register Interp *iPtr = (Interp *) interp; Tcl_Obj *objResultPtr; int length; /* * If the string result is non-empty, move the string result to the object * result, then reset the string result. */ if (iPtr->result[0] != 0) { ResetObjResult(iPtr); objResultPtr = iPtr->objResultPtr; length = strlen(iPtr->result); TclInitStringRep(objResultPtr, iPtr->result, length); if (iPtr->freeProc != NULL) { if (iPtr->freeProc == TCL_DYNAMIC) { ckfree(iPtr->result); } else { iPtr->freeProc(iPtr->result); } iPtr->freeProc = 0; } iPtr->result = iPtr->resultSpace; iPtr->result[0] = 0; } return iPtr->objResultPtr; } /* *---------------------------------------------------------------------- * * Tcl_AppendResultVA -- * * Append a variable number of strings onto the interpreter's result. * * Results: * None. * * Side effects: * The result of the interpreter given by the first argument is extended * by the strings in the va_list (up to a terminating NULL argument). * * If the string result is non-empty, the object result forced to be a * duplicate of it first. There will be a string result afterwards. * *---------------------------------------------------------------------- */ void Tcl_AppendResultVA( Tcl_Interp *interp, /* Interpreter with which to associate the * return value. */ va_list argList) /* Variable argument list. */ { Tcl_Obj *objPtr = Tcl_GetObjResult(interp); if (Tcl_IsShared(objPtr)) { objPtr = Tcl_DuplicateObj(objPtr); } Tcl_AppendStringsToObjVA(objPtr, argList); Tcl_SetObjResult(interp, objPtr); /* * Strictly we should call Tcl_GetStringResult(interp) here to make sure * that interp->result is correct according to the old contract, but that * makes the performance of much code (e.g. in Tk) absolutely awful. So we * leave it out; code that really wants interp->result can just insert the * calls to Tcl_GetStringResult() itself. [Patch 1041072 discussion] */ #ifdef USE_INTERP_RESULT /* * Ensure that the interp->result is legal so old Tcl 7.* code still * works. There's still embarrasingly much of it about... */ (void) Tcl_GetStringResult(interp); #endif /* USE_INTERP_RESULT */ } /* *---------------------------------------------------------------------- * * Tcl_AppendResult -- * * Append a variable number of strings onto the interpreter's result. * * Results: * None. * * Side effects: * The result of the interpreter given by the first argument is extended * by the strings given by the second and following arguments (up to a * terminating NULL argument). * * If the string result is non-empty, the object result forced to be a * duplicate of it first. There will be a string result afterwards. * *---------------------------------------------------------------------- */ void Tcl_AppendResult( Tcl_Interp *interp, ...) { va_list argList; va_start(argList, interp); Tcl_AppendResultVA(interp, argList); va_end(argList); } /* *---------------------------------------------------------------------- * * Tcl_AppendElement -- * * Convert a string to a valid Tcl list element and append it to the * result (which is ostensibly a list). * * Results: * None. * * Side effects: * The result in the interpreter given by the first argument is extended * with a list element converted from string. A separator space is added * before the converted list element unless the current result is empty, * contains the single character "{", or ends in " {". * * If the string result is empty, the object result is moved to the * string result, then the object result is reset. * *---------------------------------------------------------------------- */ void Tcl_AppendElement( Tcl_Interp *interp, /* Interpreter whose result is to be * extended. */ const char *element) /* String to convert to list element and add * to result. */ { Interp *iPtr = (Interp *) interp; char *dst; int size; int flags; /* * If the string result is empty, move the object result to the string * result, then reset the object result. */ (void) Tcl_GetStringResult(interp); /* * See how much space is needed, and grow the append buffer if needed to * accommodate the list element. */ size = Tcl_ScanElement(element, &flags) + 1; if ((iPtr->result != iPtr->appendResult) || (iPtr->appendResult[iPtr->appendUsed] != 0) || ((size + iPtr->appendUsed) >= iPtr->appendAvl)) { SetupAppendBuffer(iPtr, size+iPtr->appendUsed); } /* * Convert the string into a list element and copy it to the buffer that's * forming, with a space separator if needed. */ dst = iPtr->appendResult + iPtr->appendUsed; if (TclNeedSpace(iPtr->appendResult, dst)) { iPtr->appendUsed++; *dst = ' '; dst++; /* * If we need a space to separate this element from preceding stuff, * then this element will not lead a list, and need not have it's * leading '#' quoted. */ flags |= TCL_DONT_QUOTE_HASH; } iPtr->appendUsed += Tcl_ConvertElement(element, dst, flags); } /* *---------------------------------------------------------------------- * * SetupAppendBuffer -- * * This function makes sure that there is an append buffer properly * initialized, if necessary, from the interpreter's result, and that it * has at least enough room to accommodate newSpace new bytes of * information. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void SetupAppendBuffer( Interp *iPtr, /* Interpreter whose result is being set up. */ int newSpace) /* Make sure that at least this many bytes of * new information may be added. */ { int totalSpace; /* * Make the append buffer larger, if that's necessary, then copy the * result into the append buffer and make the append buffer the official * Tcl result. */ if (iPtr->result != iPtr->appendResult) { /* * If an oversized buffer was used recently, then free it up so we go * back to a smaller buffer. This avoids tying up memory forever after * a large operation. */ if (iPtr->appendAvl > 500) { ckfree(iPtr->appendResult); iPtr->appendResult = NULL; iPtr->appendAvl = 0; } iPtr->appendUsed = strlen(iPtr->result); } else if (iPtr->result[iPtr->appendUsed] != 0) { /* * Most likely someone has modified a result created by * Tcl_AppendResult et al. so that it has a different size. Just * recompute the size. */ iPtr->appendUsed = strlen(iPtr->result); } totalSpace = newSpace + iPtr->appendUsed; if (totalSpace >= iPtr->appendAvl) { char *new; if (totalSpace < 100) { totalSpace = 200; } else { totalSpace *= 2; } new = ckalloc(totalSpace); strcpy(new, iPtr->result); if (iPtr->appendResult != NULL) { ckfree(iPtr->appendResult); } iPtr->appendResult = new; iPtr->appendAvl = totalSpace; } else if (iPtr->result != iPtr->appendResult) { strcpy(iPtr->appendResult, iPtr->result); } Tcl_FreeResult((Tcl_Interp *) iPtr); iPtr->result = iPtr->appendResult; } /* *---------------------------------------------------------------------- * * Tcl_FreeResult -- * * This function frees up the memory associated with an interpreter's * string result. It also resets the interpreter's result object. * Tcl_FreeResult is most commonly used when a function is about to * replace one result value with another. * * Results: * None. * * Side effects: * Frees the memory associated with interp's string result and sets * interp->freeProc to zero, but does not change interp->result or clear * error state. Resets interp's result object to an unshared empty * object. * *---------------------------------------------------------------------- */ void Tcl_FreeResult( register Tcl_Interp *interp)/* Interpreter for which to free result. */ { register Interp *iPtr = (Interp *) interp; if (iPtr->freeProc != NULL) { if (iPtr->freeProc == TCL_DYNAMIC) { ckfree(iPtr->result); } else { iPtr->freeProc(iPtr->result); } iPtr->freeProc = 0; } ResetObjResult(iPtr); } /* *---------------------------------------------------------------------- * * Tcl_ResetResult -- * * This function resets both the interpreter's string and object results. * * Results: * None. * * Side effects: * It resets the result object to an unshared empty object. It then * restores the interpreter's string result area to its default * initialized state, freeing up any memory that may have been allocated. * It also clears any error information for the interpreter. * *---------------------------------------------------------------------- */ void Tcl_ResetResult( register Tcl_Interp *interp)/* Interpreter for which to clear result. */ { register Interp *iPtr = (Interp *) interp; ResetObjResult(iPtr); if (iPtr->freeProc != NULL) { if (iPtr->freeProc == TCL_DYNAMIC) { ckfree(iPtr->result); } else { iPtr->freeProc(iPtr->result); } iPtr->freeProc = 0; } iPtr->result = iPtr->resultSpace; iPtr->resultSpace[0] = 0; if (iPtr->errorCode) { /* Legacy support */ if (iPtr->flags & ERR_LEGACY_COPY) { Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL, iPtr->errorCode, TCL_GLOBAL_ONLY); } Tcl_DecrRefCount(iPtr->errorCode); iPtr->errorCode = NULL; } if (iPtr->errorInfo) { /* Legacy support */ if (iPtr->flags & ERR_LEGACY_COPY) { Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL, iPtr->errorInfo, TCL_GLOBAL_ONLY); } Tcl_DecrRefCount(iPtr->errorInfo); iPtr->errorInfo = NULL; } iPtr->resetErrorStack = 1; iPtr->returnLevel = 1; iPtr->returnCode = TCL_OK; if (iPtr->returnOpts) { Tcl_DecrRefCount(iPtr->returnOpts); iPtr->returnOpts = NULL; } iPtr->flags &= ~(ERR_ALREADY_LOGGED | ERR_LEGACY_COPY); } /* *---------------------------------------------------------------------- * * ResetObjResult -- * * Function used to reset an interpreter's Tcl result object. * * Results: * None. * * Side effects: * Resets the interpreter's result object to an unshared empty string * object with ref count one. It does not clear any error information in * the interpreter. * *---------------------------------------------------------------------- */ static void ResetObjResult( register Interp *iPtr) /* Points to the interpreter whose result * object should be reset. */ { register Tcl_Obj *objResultPtr = iPtr->objResultPtr; if (Tcl_IsShared(objResultPtr)) { TclDecrRefCount(objResultPtr); TclNewObj(objResultPtr); Tcl_IncrRefCount(objResultPtr); iPtr->objResultPtr = objResultPtr; } else { if (objResultPtr->bytes != tclEmptyStringRep) { if (objResultPtr->bytes) { ckfree(objResultPtr->bytes); } objResultPtr->bytes = tclEmptyStringRep; objResultPtr->length = 0; } TclFreeIntRep(objResultPtr); } } /* *---------------------------------------------------------------------- * * Tcl_SetErrorCodeVA -- * * This function is called to record machine-readable information about * an error that is about to be returned. * * Results: * None. * * Side effects: * The errorCode field of the interp is modified to hold all of the * arguments to this function, in a list form with each argument becoming * one element of the list. * *---------------------------------------------------------------------- */ void Tcl_SetErrorCodeVA( Tcl_Interp *interp, /* Interpreter in which to set errorCode */ va_list argList) /* Variable argument list. */ { Tcl_Obj *errorObj = Tcl_NewObj(); /* * Scan through the arguments one at a time, appending them to the * errorCode field as list elements. */ while (1) { char *elem = va_arg(argList, char *); if (elem == NULL) { break; } Tcl_ListObjAppendElement(NULL, errorObj, Tcl_NewStringObj(elem, -1)); } Tcl_SetObjErrorCode(interp, errorObj); } /* *---------------------------------------------------------------------- * * Tcl_SetErrorCode -- * * This function is called to record machine-readable information about * an error that is about to be returned. * * Results: * None. * * Side effects: * The errorCode field of the interp is modified to hold all of the * arguments to this function, in a list form with each argument becoming * one element of the list. * *---------------------------------------------------------------------- */ void Tcl_SetErrorCode( Tcl_Interp *interp, ...) { va_list argList; /* * Scan through the arguments one at a time, appending them to the * errorCode field as list elements. */ va_start(argList, interp); Tcl_SetErrorCodeVA(interp, argList); va_end(argList); } /* *---------------------------------------------------------------------- * * Tcl_SetObjErrorCode -- * * This function is called to record machine-readable information about * an error that is about to be returned. The caller should build a list * object up and pass it to this routine. * * Results: * None. * * Side effects: * The errorCode field of the interp is set to the new value. * *---------------------------------------------------------------------- */ void Tcl_SetObjErrorCode( Tcl_Interp *interp, Tcl_Obj *errorObjPtr) { Interp *iPtr = (Interp *) interp; if (iPtr->errorCode) { Tcl_DecrRefCount(iPtr->errorCode); } iPtr->errorCode = errorObjPtr; Tcl_IncrRefCount(iPtr->errorCode); } /* *---------------------------------------------------------------------- * * Tcl_GetErrorLine -- * * Returns the line number associated with the current error. * *---------------------------------------------------------------------- */ #undef Tcl_GetErrorLine int Tcl_GetErrorLine( Tcl_Interp *interp) { return ((Interp *) interp)->errorLine; } /* *---------------------------------------------------------------------- * * Tcl_SetErrorLine -- * * Sets the line number associated with the current error. * *---------------------------------------------------------------------- */ #undef Tcl_SetErrorLine void Tcl_SetErrorLine( Tcl_Interp *interp, int value) { ((Interp *) interp)->errorLine = value; } /* *---------------------------------------------------------------------- * * GetKeys -- * * Returns a Tcl_Obj * array of the standard keys used in the return * options dictionary. * * Broadly sharing one copy of these key values helps with both memory * efficiency and dictionary lookup times. * * Results: * A Tcl_Obj * array. * * Side effects: * First time called in a thread, creates the keys (allocating memory) * and arranges for their cleanup at thread exit. * *---------------------------------------------------------------------- */ static Tcl_Obj ** GetKeys(void) { static Tcl_ThreadDataKey returnKeysKey; Tcl_Obj **keys = Tcl_GetThreadData(&returnKeysKey, (int) (KEY_LAST * sizeof(Tcl_Obj *))); if (keys[0] == NULL) { /* * First call in this thread, create the keys... */ int i; TclNewLiteralStringObj(keys[KEY_CODE], "-code"); TclNewLiteralStringObj(keys[KEY_ERRORCODE], "-errorcode"); TclNewLiteralStringObj(keys[KEY_ERRORINFO], "-errorinfo"); TclNewLiteralStringObj(keys[KEY_ERRORLINE], "-errorline"); TclNewLiteralStringObj(keys[KEY_ERRORSTACK],"-errorstack"); TclNewLiteralStringObj(keys[KEY_LEVEL], "-level"); TclNewLiteralStringObj(keys[KEY_OPTIONS], "-options"); for (i = KEY_CODE; i < KEY_LAST; i++) { Tcl_IncrRefCount(keys[i]); } /* * ... and arrange for their clenaup. */ Tcl_CreateThreadExitHandler(ReleaseKeys, keys); } return keys; } /* *---------------------------------------------------------------------- * * ReleaseKeys -- * * Called as a thread exit handler to cleanup return options dictionary * keys. * * Results: * None. * * Side effects: * Frees memory. * *---------------------------------------------------------------------- */ static void ReleaseKeys( ClientData clientData) { Tcl_Obj **keys = clientData; int i; for (i = KEY_CODE; i < KEY_LAST; i++) { Tcl_DecrRefCount(keys[i]); keys[i] = NULL; } } /* *---------------------------------------------------------------------- * * TclProcessReturn -- * * Does the work of the [return] command based on the code, level, and * returnOpts arguments. Note that the code argument must agree with the * -code entry in returnOpts and the level argument must agree with the * -level entry in returnOpts, as is the case for values returned from * TclMergeReturnOptions. * * Results: * Returns the return code the [return] command should return. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclProcessReturn( Tcl_Interp *interp, int code, int level, Tcl_Obj *returnOpts) { Interp *iPtr = (Interp *) interp; Tcl_Obj *valuePtr; Tcl_Obj **keys = GetKeys(); /* * Store the merged return options. */ if (iPtr->returnOpts != returnOpts) { if (iPtr->returnOpts) { Tcl_DecrRefCount(iPtr->returnOpts); } iPtr->returnOpts = returnOpts; Tcl_IncrRefCount(iPtr->returnOpts); } if (code == TCL_ERROR) { if (iPtr->errorInfo) { Tcl_DecrRefCount(iPtr->errorInfo); iPtr->errorInfo = NULL; } Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO], &valuePtr); if (valuePtr != NULL) { int infoLen; (void) TclGetStringFromObj(valuePtr, &infoLen); if (infoLen) { iPtr->errorInfo = valuePtr; Tcl_IncrRefCount(iPtr->errorInfo); iPtr->flags |= ERR_ALREADY_LOGGED; } } Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORSTACK], &valuePtr); if (valuePtr != NULL) { int len, valueObjc; Tcl_Obj **valueObjv; if (Tcl_IsShared(iPtr->errorStack)) { Tcl_Obj *newObj; newObj = Tcl_DuplicateObj(iPtr->errorStack); Tcl_DecrRefCount(iPtr->errorStack); Tcl_IncrRefCount(newObj); iPtr->errorStack = newObj; } /* * List extraction done after duplication to avoid moving the rug * if someone does [return -errorstack [info errorstack]] */ if (Tcl_ListObjGetElements(interp, valuePtr, &valueObjc, &valueObjv) == TCL_ERROR) { return TCL_ERROR; } iPtr->resetErrorStack = 0; Tcl_ListObjLength(interp, iPtr->errorStack, &len); /* * Reset while keeping the list intrep as much as possible. */ Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, valueObjc, valueObjv); } Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE], &valuePtr); if (valuePtr != NULL) { Tcl_SetObjErrorCode(interp, valuePtr); } else { Tcl_SetErrorCode(interp, "NONE", NULL); } Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE], &valuePtr); if (valuePtr != NULL) { TclGetIntFromObj(NULL, valuePtr, &iPtr->errorLine); } } if (level != 0) { iPtr->returnLevel = level; iPtr->returnCode = code; return TCL_RETURN; } if (code == TCL_ERROR) { iPtr->flags |= ERR_LEGACY_COPY; } return code; } /* *---------------------------------------------------------------------- * * TclMergeReturnOptions -- * * Parses, checks, and stores the options to the [return] command. * * Results: * Returns TCL_ERROR if any of the option values are invalid. Otherwise, * returns TCL_OK, and writes the returnOpts, code, and level values to * the pointers provided. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclMergeReturnOptions( Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[], /* Argument objects. */ Tcl_Obj **optionsPtrPtr, /* If not NULL, points to space for a (Tcl_Obj * *) where the pointer to the merged return * options dictionary should be written. */ int *codePtr, /* If not NULL, points to space where the * -code value should be written. */ int *levelPtr) /* If not NULL, points to space where the * -level value should be written. */ { int code = TCL_OK; int level = 1; Tcl_Obj *valuePtr; Tcl_Obj *returnOpts = Tcl_NewObj(); Tcl_Obj **keys = GetKeys(); for (; objc > 1; objv += 2, objc -= 2) { int optLen; const char *opt = TclGetStringFromObj(objv[0], &optLen); int compareLen; const char *compare = TclGetStringFromObj(keys[KEY_OPTIONS], &compareLen); if ((optLen == compareLen) && (memcmp(opt, compare, optLen) == 0)) { Tcl_DictSearch search; int done = 0; Tcl_Obj *keyPtr; Tcl_Obj *dict = objv[1]; nestedOptions: if (TCL_ERROR == Tcl_DictObjFirst(NULL, dict, &search, &keyPtr, &valuePtr, &done)) { /* * Value is not a legal dictionary. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad %s value: expected dictionary but got \"%s\"", compare, TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_OPTIONS", NULL); goto error; } while (!done) { Tcl_DictObjPut(NULL, returnOpts, keyPtr, valuePtr); Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done); } Tcl_DictObjGet(NULL, returnOpts, keys[KEY_OPTIONS], &valuePtr); if (valuePtr != NULL) { dict = valuePtr; Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_OPTIONS]); goto nestedOptions; } } else { Tcl_DictObjPut(NULL, returnOpts, objv[0], objv[1]); } } /* * Check for bogus -code value. */ Tcl_DictObjGet(NULL, returnOpts, keys[KEY_CODE], &valuePtr); if (valuePtr != NULL) { if (TclGetCompletionCodeFromObj(interp, valuePtr, &code) == TCL_ERROR) { goto error; } Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_CODE]); } /* * Check for bogus -level value. */ Tcl_DictObjGet(NULL, returnOpts, keys[KEY_LEVEL], &valuePtr); if (valuePtr != NULL) { if ((TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &level)) || (level < 0)) { /* * Value is not a legal level. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad -level value: expected non-negative integer but got" " \"%s\"", TclGetString(valuePtr))); Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_LEVEL", NULL); goto error; } Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_LEVEL]); } /* * Check for bogus -errorcode value. */ Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORCODE], &valuePtr); if (valuePtr != NULL) { int length; if (TCL_ERROR == Tcl_ListObjLength(NULL, valuePtr, &length )) { /* * Value is not a list, which is illegal for -errorcode. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad -errorcode value: expected a list but got \"%s\"", TclGetString(valuePtr))); Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_ERRORCODE", NULL); goto error; } } /* * Check for bogus -errorstack value. */ Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORSTACK], &valuePtr); if (valuePtr != NULL) { int length; if (TCL_ERROR == Tcl_ListObjLength(NULL, valuePtr, &length )) { /* * Value is not a list, which is illegal for -errorstack. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad -errorstack value: expected a list but got \"%s\"", TclGetString(valuePtr))); Tcl_SetErrorCode(interp, "TCL", "RESULT", "NONLIST_ERRORSTACK", NULL); goto error; } if (length % 2) { /* * Errorstack must always be an even-sized list */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "forbidden odd-sized list for -errorstack: \"%s\"", TclGetString(valuePtr))); Tcl_SetErrorCode(interp, "TCL", "RESULT", "ODDSIZEDLIST_ERRORSTACK", NULL); goto error; } } /* * Convert [return -code return -level X] to [return -code ok -level X+1] */ if (code == TCL_RETURN) { level++; code = TCL_OK; } if (codePtr != NULL) { *codePtr = code; } if (levelPtr != NULL) { *levelPtr = level; } if (optionsPtrPtr == NULL) { /* * Not passing back the options (?!), so clean them up. */ Tcl_DecrRefCount(returnOpts); } else { *optionsPtrPtr = returnOpts; } return TCL_OK; error: Tcl_DecrRefCount(returnOpts); return TCL_ERROR; } /* *------------------------------------------------------------------------- * * Tcl_GetReturnOptions -- * * Packs up the interp state into a dictionary of return options. * * Results: * A dictionary of return options. * * Side effects: * None. * *------------------------------------------------------------------------- */ Tcl_Obj * Tcl_GetReturnOptions( Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_Obj *options; Tcl_Obj **keys = GetKeys(); if (iPtr->returnOpts) { options = Tcl_DuplicateObj(iPtr->returnOpts); } else { options = Tcl_NewObj(); } if (result == TCL_RETURN) { Tcl_DictObjPut(NULL, options, keys[KEY_CODE], Tcl_NewIntObj(iPtr->returnCode)); Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL], Tcl_NewIntObj(iPtr->returnLevel)); } else { Tcl_DictObjPut(NULL, options, keys[KEY_CODE], Tcl_NewIntObj(result)); Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL], Tcl_NewIntObj(0)); } if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, ""); Tcl_DictObjPut(NULL, options, keys[KEY_ERRORSTACK], iPtr->errorStack); } if (iPtr->errorCode) { Tcl_DictObjPut(NULL, options, keys[KEY_ERRORCODE], iPtr->errorCode); } if (iPtr->errorInfo) { Tcl_DictObjPut(NULL, options, keys[KEY_ERRORINFO], iPtr->errorInfo); Tcl_DictObjPut(NULL, options, keys[KEY_ERRORLINE], Tcl_NewIntObj(iPtr->errorLine)); } return options; } /* *------------------------------------------------------------------------- * * TclNoErrorStack -- * * Removes the -errorstack entry from an options dict to avoid reference * cycles. * * Results: * The (unshared) argument options dict, modified in -place. * *------------------------------------------------------------------------- */ Tcl_Obj * TclNoErrorStack( Tcl_Interp *interp, Tcl_Obj *options) { Tcl_Obj **keys = GetKeys(); Tcl_DictObjRemove(interp, options, keys[KEY_ERRORSTACK]); return options; } /* *------------------------------------------------------------------------- * * Tcl_SetReturnOptions -- * * Accepts an interp and a dictionary of return options, and sets the * return options of the interp to match the dictionary. * * Results: * A standard status code. Usually TCL_OK, but TCL_ERROR if an invalid * option value was found in the dictionary. If a -level value of 0 is in * the dictionary, then the -code value in the dictionary will be * returned (TCL_OK default). * * Side effects: * Sets the state of the interp. * *------------------------------------------------------------------------- */ int Tcl_SetReturnOptions( Tcl_Interp *interp, Tcl_Obj *options) { int objc, level, code; Tcl_Obj **objv, *mergedOpts; Tcl_IncrRefCount(options); if (TCL_ERROR == TclListObjGetElements(interp, options, &objc, &objv) || (objc % 2)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected dict but got \"%s\"", TclGetString(options))); Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_OPTIONS", NULL); code = TCL_ERROR; } else if (TCL_ERROR == TclMergeReturnOptions(interp, objc, objv, &mergedOpts, &code, &level)) { code = TCL_ERROR; } else { code = TclProcessReturn(interp, code, level, mergedOpts); } Tcl_DecrRefCount(options); return code; } /* *------------------------------------------------------------------------- * * Tcl_TransferResult -- * * Copy the result (and error information) from one interp to another. * Used when one interp has caused another interp to evaluate a script * and then wants to transfer the results back to itself. * * This routine copies the string reps of the result and error * information. It does not simply increment the refcounts of the result * and error information objects themselves. It is not legal to exchange * objects between interps, because an object may be kept alive by one * interp, but have an internal rep that is only valid while some other * interp is alive. * * Results: * The target interp's result is set to a copy of the source interp's * result. The source's errorInfo field may be transferred to the * target's errorInfo field, and the source's errorCode field may be * transferred to the target's errorCode field. * * Side effects: * None. * *------------------------------------------------------------------------- */ void Tcl_TransferResult( Tcl_Interp *sourceInterp, /* Interp whose result and error information * should be moved to the target interp. * After moving result, this interp's result * is reset. */ int result, /* TCL_OK if just the result should be copied, * TCL_ERROR if both the result and error * information should be copied. */ Tcl_Interp *targetInterp) /* Interp where result and error information * should be stored. If source and target are * the same, nothing is done. */ { Interp *tiPtr = (Interp *) targetInterp; Interp *siPtr = (Interp *) sourceInterp; if (sourceInterp == targetInterp) { return; } if (result == TCL_OK && siPtr->returnOpts == NULL) { /* * Special optimization for the common case of normal command return * code and no explicit return options. */ if (tiPtr->returnOpts) { Tcl_DecrRefCount(tiPtr->returnOpts); tiPtr->returnOpts = NULL; } } else { Tcl_SetReturnOptions(targetInterp, Tcl_GetReturnOptions(sourceInterp, result)); tiPtr->flags &= ~(ERR_ALREADY_LOGGED); } Tcl_SetObjResult(targetInterp, Tcl_GetObjResult(sourceInterp)); Tcl_ResetResult(sourceInterp); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * indent-tabs-mode: nil * End: */ tcl8.6.5/generic/tclOOMethod.c0000644000175000017500000014625412663660065015544 0ustar sergeisergei/* * tclOOMethod.c -- * * This file contains code to create and manage methods. * * Copyright (c) 2005-2011 by Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tclInt.h" #include "tclOOInt.h" #include "tclCompile.h" /* * Structure used to help delay computing names of objects or classes for * [info frame] until needed, making invokation faster in the normal case. */ struct PNI { Tcl_Interp *interp; /* Interpreter in which to compute the name of * a method. */ Tcl_Method method; /* Method to compute the name of. */ }; /* * Structure used to contain all the information needed about a call frame * used in a procedure-like method. */ typedef struct { CallFrame *framePtr; /* Reference to the call frame itself (it's * actually allocated on the Tcl stack). */ ProcErrorProc *errProc; /* The error handler for the body. */ Tcl_Obj *nameObj; /* The "name" of the command. */ Command cmd; /* The command structure. Mostly bogus. */ ExtraFrameInfo efi; /* Extra information used for [info frame]. */ Command *oldCmdPtr; /* Saved cmdPtr so that we can be safe after a * recursive call returns. */ struct PNI pni; /* Specialist information used in the efi * field for this type of call. */ } PMFrameData; /* * Structure used to pass information about variable resolution to the * on-the-ground resolvers used when working with resolved compiled variables. */ typedef struct { Tcl_ResolvedVarInfo info; /* "Type" information so that the compiled * variable can be linked to the namespace * variable at the right time. */ Tcl_Obj *variableObj; /* The name of the variable. */ Tcl_Var cachedObjectVar; /* TODO: When to flush this cache? Can class * variables be cached? */ } OOResVarInfo; /* * Function declarations for things defined in this file. */ static Tcl_Obj ** InitEnsembleRewrite(Tcl_Interp *interp, int objc, Tcl_Obj *const *objv, int toRewrite, int rewriteLength, Tcl_Obj *const *rewriteObjs, int *lengthPtr); static int InvokeProcedureMethod(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int FinalizeForwardCall(ClientData data[], Tcl_Interp *interp, int result); static int FinalizePMCall(ClientData data[], Tcl_Interp *interp, int result); static int PushMethodCallFrame(Tcl_Interp *interp, CallContext *contextPtr, ProcedureMethod *pmPtr, int objc, Tcl_Obj *const *objv, PMFrameData *fdPtr); static void DeleteProcedureMethodRecord(ProcedureMethod *pmPtr); static void DeleteProcedureMethod(ClientData clientData); static int CloneProcedureMethod(Tcl_Interp *interp, ClientData clientData, ClientData *newClientData); static void MethodErrorHandler(Tcl_Interp *interp, Tcl_Obj *procNameObj); static void ConstructorErrorHandler(Tcl_Interp *interp, Tcl_Obj *procNameObj); static void DestructorErrorHandler(Tcl_Interp *interp, Tcl_Obj *procNameObj); static Tcl_Obj * RenderDeclarerName(ClientData clientData); static int InvokeForwardMethod(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static void DeleteForwardMethod(ClientData clientData); static int CloneForwardMethod(Tcl_Interp *interp, ClientData clientData, ClientData *newClientData); static int ProcedureMethodVarResolver(Tcl_Interp *interp, const char *varName, Tcl_Namespace *contextNs, int flags, Tcl_Var *varPtr); static int ProcedureMethodCompiledVarResolver(Tcl_Interp *interp, const char *varName, int length, Tcl_Namespace *contextNs, Tcl_ResolvedVarInfo **rPtrPtr); /* * The types of methods defined by the core OO system. */ static const Tcl_MethodType procMethodType = { TCL_OO_METHOD_VERSION_CURRENT, "method", InvokeProcedureMethod, DeleteProcedureMethod, CloneProcedureMethod }; static const Tcl_MethodType fwdMethodType = { TCL_OO_METHOD_VERSION_CURRENT, "forward", InvokeForwardMethod, DeleteForwardMethod, CloneForwardMethod }; /* * Helper macros (derived from things private to tclVar.c) */ #define TclVarTable(contextNs) \ ((Tcl_HashTable *) (&((Namespace *) (contextNs))->varTable)) #define TclVarHashGetValue(hPtr) \ ((Tcl_Var) ((char *)hPtr - TclOffset(VarInHash, entry))) /* * ---------------------------------------------------------------------- * * Tcl_NewInstanceMethod -- * * Attach a method to an object instance. * * ---------------------------------------------------------------------- */ Tcl_Method Tcl_NewInstanceMethod( Tcl_Interp *interp, /* Unused? */ Tcl_Object object, /* The object that has the method attached to * it. */ Tcl_Obj *nameObj, /* The name of the method. May be NULL; if so, * up to caller to manage storage (e.g., when * it is a constructor or destructor). */ int flags, /* Whether this is a public method. */ const Tcl_MethodType *typePtr, /* The type of method this is, which defines * how to invoke, delete and clone the * method. */ ClientData clientData) /* Some data associated with the particular * method to be created. */ { register Object *oPtr = (Object *) object; register Method *mPtr; Tcl_HashEntry *hPtr; int isNew; if (nameObj == NULL) { mPtr = ckalloc(sizeof(Method)); mPtr->namePtr = NULL; mPtr->refCount = 1; goto populate; } if (!oPtr->methodsPtr) { oPtr->methodsPtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitObjHashTable(oPtr->methodsPtr); oPtr->flags &= ~USE_CLASS_CACHE; } hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *) nameObj, &isNew); if (isNew) { mPtr = ckalloc(sizeof(Method)); mPtr->namePtr = nameObj; mPtr->refCount = 1; Tcl_IncrRefCount(nameObj); Tcl_SetHashValue(hPtr, mPtr); } else { mPtr = Tcl_GetHashValue(hPtr); if (mPtr->typePtr != NULL && mPtr->typePtr->deleteProc != NULL) { mPtr->typePtr->deleteProc(mPtr->clientData); } } populate: mPtr->typePtr = typePtr; mPtr->clientData = clientData; mPtr->flags = 0; mPtr->declaringObjectPtr = oPtr; mPtr->declaringClassPtr = NULL; if (flags) { mPtr->flags |= flags & (PUBLIC_METHOD | PRIVATE_METHOD); } oPtr->epoch++; return (Tcl_Method) mPtr; } /* * ---------------------------------------------------------------------- * * Tcl_NewMethod -- * * Attach a method to a class. * * ---------------------------------------------------------------------- */ Tcl_Method Tcl_NewMethod( Tcl_Interp *interp, /* The interpreter containing the class. */ Tcl_Class cls, /* The class to attach the method to. */ Tcl_Obj *nameObj, /* The name of the object. May be NULL (e.g., * for constructors or destructors); if so, up * to caller to manage storage. */ int flags, /* Whether this is a public method. */ const Tcl_MethodType *typePtr, /* The type of method this is, which defines * how to invoke, delete and clone the * method. */ ClientData clientData) /* Some data associated with the particular * method to be created. */ { register Class *clsPtr = (Class *) cls; register Method *mPtr; Tcl_HashEntry *hPtr; int isNew; if (nameObj == NULL) { mPtr = ckalloc(sizeof(Method)); mPtr->namePtr = NULL; mPtr->refCount = 1; goto populate; } hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char *)nameObj,&isNew); if (isNew) { mPtr = ckalloc(sizeof(Method)); mPtr->refCount = 1; mPtr->namePtr = nameObj; Tcl_IncrRefCount(nameObj); Tcl_SetHashValue(hPtr, mPtr); } else { mPtr = Tcl_GetHashValue(hPtr); if (mPtr->typePtr != NULL && mPtr->typePtr->deleteProc != NULL) { mPtr->typePtr->deleteProc(mPtr->clientData); } } populate: clsPtr->thisPtr->fPtr->epoch++; mPtr->typePtr = typePtr; mPtr->clientData = clientData; mPtr->flags = 0; mPtr->declaringObjectPtr = NULL; mPtr->declaringClassPtr = clsPtr; if (flags) { mPtr->flags |= flags & (PUBLIC_METHOD | PRIVATE_METHOD); } return (Tcl_Method) mPtr; } /* * ---------------------------------------------------------------------- * * TclOODelMethodRef -- * * How to delete a method. * * ---------------------------------------------------------------------- */ void TclOODelMethodRef( Method *mPtr) { if ((mPtr != NULL) && (mPtr->refCount-- <= 1)) { if (mPtr->typePtr != NULL && mPtr->typePtr->deleteProc != NULL) { mPtr->typePtr->deleteProc(mPtr->clientData); } if (mPtr->namePtr != NULL) { Tcl_DecrRefCount(mPtr->namePtr); } ckfree(mPtr); } } /* * ---------------------------------------------------------------------- * * TclOONewBasicMethod -- * * Helper that makes it cleaner to create very simple methods during * basic system initialization. Not suitable for general use. * * ---------------------------------------------------------------------- */ void TclOONewBasicMethod( Tcl_Interp *interp, Class *clsPtr, /* Class to attach the method to. */ const DeclaredClassMethod *dcm) /* Name of the method, whether it is public, * and the function to implement it. */ { Tcl_Obj *namePtr = Tcl_NewStringObj(dcm->name, -1); Tcl_IncrRefCount(namePtr); Tcl_NewMethod(interp, (Tcl_Class) clsPtr, namePtr, (dcm->isPublic ? PUBLIC_METHOD : 0), &dcm->definition, NULL); Tcl_DecrRefCount(namePtr); } /* * ---------------------------------------------------------------------- * * TclOONewProcInstanceMethod -- * * Create a new procedure-like method for an object. * * ---------------------------------------------------------------------- */ Method * TclOONewProcInstanceMethod( Tcl_Interp *interp, /* The interpreter containing the object. */ Object *oPtr, /* The object to modify. */ int flags, /* Whether this is a public method. */ Tcl_Obj *nameObj, /* The name of the method, which must not be * NULL. */ Tcl_Obj *argsObj, /* The formal argument list for the method, * which must not be NULL. */ Tcl_Obj *bodyObj, /* The body of the method, which must not be * NULL. */ ProcedureMethod **pmPtrPtr) /* Place to write pointer to procedure method * structure to allow for deeper tuning of the * structure's contents. NULL if caller is not * interested. */ { int argsLen; register ProcedureMethod *pmPtr; Tcl_Method method; if (Tcl_ListObjLength(interp, argsObj, &argsLen) != TCL_OK) { return NULL; } pmPtr = ckalloc(sizeof(ProcedureMethod)); memset(pmPtr, 0, sizeof(ProcedureMethod)); pmPtr->version = TCLOO_PROCEDURE_METHOD_VERSION; pmPtr->flags = flags & USE_DECLARER_NS; pmPtr->refCount = 1; method = TclOOMakeProcInstanceMethod(interp, oPtr, flags, nameObj, argsObj, bodyObj, &procMethodType, pmPtr, &pmPtr->procPtr); if (method == NULL) { ckfree(pmPtr); } else if (pmPtrPtr != NULL) { *pmPtrPtr = pmPtr; } return (Method *) method; } /* * ---------------------------------------------------------------------- * * TclOONewProcMethod -- * * Create a new procedure-like method for a class. * * ---------------------------------------------------------------------- */ Method * TclOONewProcMethod( Tcl_Interp *interp, /* The interpreter containing the class. */ Class *clsPtr, /* The class to modify. */ int flags, /* Whether this is a public method. */ Tcl_Obj *nameObj, /* The name of the method, which may be NULL; * if so, up to caller to manage storage * (e.g., because it is a constructor or * destructor). */ Tcl_Obj *argsObj, /* The formal argument list for the method, * which may be NULL; if so, it is equivalent * to an empty list. */ Tcl_Obj *bodyObj, /* The body of the method, which must not be * NULL. */ ProcedureMethod **pmPtrPtr) /* Place to write pointer to procedure method * structure to allow for deeper tuning of the * structure's contents. NULL if caller is not * interested. */ { int argsLen; /* -1 => delete argsObj before exit */ register ProcedureMethod *pmPtr; const char *procName; Tcl_Method method; if (argsObj == NULL) { argsLen = -1; argsObj = Tcl_NewObj(); Tcl_IncrRefCount(argsObj); procName = ""; } else if (Tcl_ListObjLength(interp, argsObj, &argsLen) != TCL_OK) { return NULL; } else { procName = (nameObj==NULL ? "" : TclGetString(nameObj)); } pmPtr = ckalloc(sizeof(ProcedureMethod)); memset(pmPtr, 0, sizeof(ProcedureMethod)); pmPtr->version = TCLOO_PROCEDURE_METHOD_VERSION; pmPtr->flags = flags & USE_DECLARER_NS; pmPtr->refCount = 1; method = TclOOMakeProcMethod(interp, clsPtr, flags, nameObj, procName, argsObj, bodyObj, &procMethodType, pmPtr, &pmPtr->procPtr); if (argsLen == -1) { Tcl_DecrRefCount(argsObj); } if (method == NULL) { ckfree(pmPtr); } else if (pmPtrPtr != NULL) { *pmPtrPtr = pmPtr; } return (Method *) method; } /* * ---------------------------------------------------------------------- * * TclOOMakeProcInstanceMethod -- * * The guts of the code to make a procedure-like method for an object. * Split apart so that it is easier for other extensions to reuse (in * particular, it frees them from having to pry so deeply into Tcl's * guts). * * ---------------------------------------------------------------------- */ Tcl_Method TclOOMakeProcInstanceMethod( Tcl_Interp *interp, /* The interpreter containing the object. */ Object *oPtr, /* The object to modify. */ int flags, /* Whether this is a public method. */ Tcl_Obj *nameObj, /* The name of the method, which _must not_ be * NULL. */ Tcl_Obj *argsObj, /* The formal argument list for the method, * which _must not_ be NULL. */ Tcl_Obj *bodyObj, /* The body of the method, which _must not_ be * NULL. */ const Tcl_MethodType *typePtr, /* The type of the method to create. */ ClientData clientData, /* The per-method type-specific data. */ Proc **procPtrPtr) /* A pointer to the variable in which to write * the procedure record reference. Presumably * inside the structure indicated by the * pointer in clientData. */ { Interp *iPtr = (Interp *) interp; Proc *procPtr; if (TclCreateProc(interp, NULL, TclGetString(nameObj), argsObj, bodyObj, procPtrPtr) != TCL_OK) { return NULL; } procPtr = *procPtrPtr; procPtr->cmdPtr = NULL; if (iPtr->cmdFramePtr) { CmdFrame context = *iPtr->cmdFramePtr; if (context.type == TCL_LOCATION_BC) { /* * Retrieve source information from the bytecode, if possible. If * the information is retrieved successfully, context.type will be * TCL_LOCATION_SOURCE and the reference held by * context.data.eval.path will be counted. */ TclGetSrcInfoForPc(&context); } else if (context.type == TCL_LOCATION_SOURCE) { /* * The copy into 'context' up above has created another reference * to 'context.data.eval.path'; account for it. */ Tcl_IncrRefCount(context.data.eval.path); } if (context.type == TCL_LOCATION_SOURCE) { /* * We can account for source location within a proc only if the * proc body was not created by substitution. * (FIXME: check that this is sane and correct!) */ if (context.line && (context.nline >= 4) && (context.line[3] >= 0)) { int isNew; CmdFrame *cfPtr = ckalloc(sizeof(CmdFrame)); Tcl_HashEntry *hPtr; cfPtr->level = -1; cfPtr->type = context.type; cfPtr->line = ckalloc(sizeof(int)); cfPtr->line[0] = context.line[3]; cfPtr->nline = 1; cfPtr->framePtr = NULL; cfPtr->nextPtr = NULL; cfPtr->data.eval.path = context.data.eval.path; Tcl_IncrRefCount(cfPtr->data.eval.path); cfPtr->cmd = NULL; cfPtr->len = 0; hPtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr, (char *) procPtr, &isNew); Tcl_SetHashValue(hPtr, cfPtr); } /* * 'context' is going out of scope; account for the reference that * it's holding to the path name. */ Tcl_DecrRefCount(context.data.eval.path); context.data.eval.path = NULL; } } return Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, nameObj, flags, typePtr, clientData); } /* * ---------------------------------------------------------------------- * * TclOOMakeProcMethod -- * * The guts of the code to make a procedure-like method for a class. * Split apart so that it is easier for other extensions to reuse (in * particular, it frees them from having to pry so deeply into Tcl's * guts). * * ---------------------------------------------------------------------- */ Tcl_Method TclOOMakeProcMethod( Tcl_Interp *interp, /* The interpreter containing the class. */ Class *clsPtr, /* The class to modify. */ int flags, /* Whether this is a public method. */ Tcl_Obj *nameObj, /* The name of the method, which may be NULL; * if so, up to caller to manage storage * (e.g., because it is a constructor or * destructor). */ const char *namePtr, /* The name of the method as a string, which * _must not_ be NULL. */ Tcl_Obj *argsObj, /* The formal argument list for the method, * which _must not_ be NULL. */ Tcl_Obj *bodyObj, /* The body of the method, which _must not_ be * NULL. */ const Tcl_MethodType *typePtr, /* The type of the method to create. */ ClientData clientData, /* The per-method type-specific data. */ Proc **procPtrPtr) /* A pointer to the variable in which to write * the procedure record reference. Presumably * inside the structure indicated by the * pointer in clientData. */ { Interp *iPtr = (Interp *) interp; Proc *procPtr; if (TclCreateProc(interp, NULL, namePtr, argsObj, bodyObj, procPtrPtr) != TCL_OK) { return NULL; } procPtr = *procPtrPtr; procPtr->cmdPtr = NULL; if (iPtr->cmdFramePtr) { CmdFrame context = *iPtr->cmdFramePtr; if (context.type == TCL_LOCATION_BC) { /* * Retrieve source information from the bytecode, if possible. If * the information is retrieved successfully, context.type will be * TCL_LOCATION_SOURCE and the reference held by * context.data.eval.path will be counted. */ TclGetSrcInfoForPc(&context); } else if (context.type == TCL_LOCATION_SOURCE) { /* * The copy into 'context' up above has created another reference * to 'context.data.eval.path'; account for it. */ Tcl_IncrRefCount(context.data.eval.path); } if (context.type == TCL_LOCATION_SOURCE) { /* * We can account for source location within a proc only if the * proc body was not created by substitution. * (FIXME: check that this is sane and correct!) */ if (context.line && (context.nline >= 4) && (context.line[3] >= 0)) { int isNew; CmdFrame *cfPtr = ckalloc(sizeof(CmdFrame)); Tcl_HashEntry *hPtr; cfPtr->level = -1; cfPtr->type = context.type; cfPtr->line = ckalloc(sizeof(int)); cfPtr->line[0] = context.line[3]; cfPtr->nline = 1; cfPtr->framePtr = NULL; cfPtr->nextPtr = NULL; cfPtr->data.eval.path = context.data.eval.path; Tcl_IncrRefCount(cfPtr->data.eval.path); cfPtr->cmd = NULL; cfPtr->len = 0; hPtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr, (char *) procPtr, &isNew); Tcl_SetHashValue(hPtr, cfPtr); } /* * 'context' is going out of scope; account for the reference that * it's holding to the path name. */ Tcl_DecrRefCount(context.data.eval.path); context.data.eval.path = NULL; } } return Tcl_NewMethod(interp, (Tcl_Class) clsPtr, nameObj, flags, typePtr, clientData); } /* * ---------------------------------------------------------------------- * * InvokeProcedureMethod, PushMethodCallFrame -- * * How to invoke a procedure-like method. * * ---------------------------------------------------------------------- */ static int InvokeProcedureMethod( ClientData clientData, /* Pointer to some per-method context. */ Tcl_Interp *interp, Tcl_ObjectContext context, /* The method calling context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* Arguments as actually seen. */ { ProcedureMethod *pmPtr = clientData; int result; PMFrameData *fdPtr; /* Important data that has to have a lifetime * matched by this function (or rather, by the * call frame's lifetime). */ /* * If the interpreter was deleted, we just skip to the next thing in the * chain. */ if (Tcl_InterpDeleted(interp)) { return TclNRObjectContextInvokeNext(interp, context, objc, objv, Tcl_ObjectContextSkippedArgs(context)); } /* * Allocate the special frame data. */ fdPtr = TclStackAlloc(interp, sizeof(PMFrameData)); /* * Create a call frame for this method. */ result = PushMethodCallFrame(interp, (CallContext *) context, pmPtr, objc, objv, fdPtr); if (result != TCL_OK) { TclStackFree(interp, fdPtr); return result; } pmPtr->refCount++; /* * Give the pre-call callback a chance to do some setup and, possibly, * veto the call. */ if (pmPtr->preCallProc != NULL) { int isFinished; result = pmPtr->preCallProc(pmPtr->clientData, interp, context, (Tcl_CallFrame *) fdPtr->framePtr, &isFinished); if (isFinished || result != TCL_OK) { /* * Restore the old cmdPtr so that a subsequent use of [info frame] * won't crash on us. [Bug 3001438] */ pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr; Tcl_PopCallFrame(interp); TclStackFree(interp, fdPtr->framePtr); if (pmPtr->refCount-- <= 1) { DeleteProcedureMethodRecord(pmPtr); } TclStackFree(interp, fdPtr); return result; } } /* * Now invoke the body of the method. */ TclNRAddCallback(interp, FinalizePMCall, pmPtr, context, fdPtr, NULL); return TclNRInterpProcCore(interp, fdPtr->nameObj, Tcl_ObjectContextSkippedArgs(context), fdPtr->errProc); } static int FinalizePMCall( ClientData data[], Tcl_Interp *interp, int result) { ProcedureMethod *pmPtr = data[0]; Tcl_ObjectContext context = data[1]; PMFrameData *fdPtr = data[2]; /* * Give the post-call callback a chance to do some cleanup. Note that at * this point the call frame itself is invalid; it's already been popped. */ if (pmPtr->postCallProc) { result = pmPtr->postCallProc(pmPtr->clientData, interp, context, Tcl_GetObjectNamespace(Tcl_ObjectContextObject(context)), result); } /* * Restore the old cmdPtr so that a subsequent use of [info frame] won't * crash on us. [Bug 3001438] */ pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr; /* * Scrap the special frame data now that we're done with it. Note that we * are inlining DeleteProcedureMethod() here; this location is highly * sensitive when it comes to performance! */ if (pmPtr->refCount-- <= 1) { DeleteProcedureMethodRecord(pmPtr); } TclStackFree(interp, fdPtr); return result; } static int PushMethodCallFrame( Tcl_Interp *interp, /* Current interpreter. */ CallContext *contextPtr, /* Current method call context. */ ProcedureMethod *pmPtr, /* Information about this procedure-like * method. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv, /* Array of arguments. */ PMFrameData *fdPtr) /* Place to store information about the call * frame. */ { Namespace *nsPtr = (Namespace *) contextPtr->oPtr->namespacePtr; register int result; const char *namePtr; CallFrame **framePtrPtr = &fdPtr->framePtr; /* * Compute basic information on the basis of the type of method it is. */ if (contextPtr->callPtr->flags & CONSTRUCTOR) { namePtr = ""; fdPtr->nameObj = contextPtr->oPtr->fPtr->constructorName; fdPtr->errProc = ConstructorErrorHandler; } else if (contextPtr->callPtr->flags & DESTRUCTOR) { namePtr = ""; fdPtr->nameObj = contextPtr->oPtr->fPtr->destructorName; fdPtr->errProc = DestructorErrorHandler; } else { fdPtr->nameObj = Tcl_MethodName( Tcl_ObjectContextMethod((Tcl_ObjectContext) contextPtr)); namePtr = TclGetString(fdPtr->nameObj); fdPtr->errProc = MethodErrorHandler; } if (pmPtr->errProc != NULL) { fdPtr->errProc = pmPtr->errProc; } /* * Magic to enable things like [incr Tcl], which wants methods to run in * their class's namespace. */ if (pmPtr->flags & USE_DECLARER_NS) { register Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; if (mPtr->declaringClassPtr != NULL) { nsPtr = (Namespace *) mPtr->declaringClassPtr->thisPtr->namespacePtr; } else { nsPtr = (Namespace *) mPtr->declaringObjectPtr->namespacePtr; } } /* * Save the old cmdPtr so that when this recursive call returns, we can * restore it. To do otherwise causes crashes in [info frame] after we * return from a recursive call. [Bug 3001438] */ fdPtr->oldCmdPtr = pmPtr->procPtr->cmdPtr; /* * Compile the body. This operation may fail. */ fdPtr->efi.length = 2; memset(&fdPtr->cmd, 0, sizeof(Command)); fdPtr->cmd.nsPtr = nsPtr; fdPtr->cmd.clientData = &fdPtr->efi; pmPtr->procPtr->cmdPtr = &fdPtr->cmd; /* * [Bug 2037727] Always call TclProcCompileProc so that we check not only * that we have bytecode, but also that it remains valid. Note that we set * the namespace of the code here directly; this is a hack, but the * alternative is *so* slow... */ if (pmPtr->procPtr->bodyPtr->typePtr == &tclByteCodeType) { ByteCode *codePtr = pmPtr->procPtr->bodyPtr->internalRep.twoPtrValue.ptr1; codePtr->nsPtr = nsPtr; } result = TclProcCompileProc(interp, pmPtr->procPtr, pmPtr->procPtr->bodyPtr, nsPtr, "body of method", namePtr); if (result != TCL_OK) { goto failureReturn; } /* * Make the stack frame and fill it out with information about this call. * This operation may fail. */ (void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr, (Tcl_Namespace *) nsPtr, FRAME_IS_PROC|FRAME_IS_METHOD); fdPtr->framePtr->clientData = contextPtr; fdPtr->framePtr->objc = objc; fdPtr->framePtr->objv = objv; fdPtr->framePtr->procPtr = pmPtr->procPtr; /* * Finish filling out the extra frame info so that [info frame] works. */ fdPtr->efi.fields[0].name = "method"; fdPtr->efi.fields[0].proc = NULL; fdPtr->efi.fields[0].clientData = fdPtr->nameObj; if (pmPtr->gfivProc != NULL) { fdPtr->efi.fields[1].name = ""; fdPtr->efi.fields[1].proc = pmPtr->gfivProc; fdPtr->efi.fields[1].clientData = pmPtr; } else { register Tcl_Method method = Tcl_ObjectContextMethod((Tcl_ObjectContext) contextPtr); if (Tcl_MethodDeclarerObject(method) != NULL) { fdPtr->efi.fields[1].name = "object"; } else { fdPtr->efi.fields[1].name = "class"; } fdPtr->efi.fields[1].proc = RenderDeclarerName; fdPtr->efi.fields[1].clientData = &fdPtr->pni; fdPtr->pni.interp = interp; fdPtr->pni.method = method; } return TCL_OK; /* * Restore the old cmdPtr so that a subsequent use of [info frame] won't * crash on us. [Bug 3001438] */ failureReturn: pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr; return result; } /* * ---------------------------------------------------------------------- * * TclOOSetupVariableResolver, etc. -- * * Variable resolution engine used to connect declared variables to local * variables used in methods. The compiled variable resolver is more * important, but both are needed as it is possible to have a variable * that is only referred to in ways that aren't compilable and we can't * force LVT presence. [TIP #320] * * ---------------------------------------------------------------------- */ void TclOOSetupVariableResolver( Tcl_Namespace *nsPtr) { Tcl_ResolverInfo info; Tcl_GetNamespaceResolvers(nsPtr, &info); if (info.compiledVarResProc == NULL) { Tcl_SetNamespaceResolvers(nsPtr, NULL, ProcedureMethodVarResolver, ProcedureMethodCompiledVarResolver); } } static int ProcedureMethodVarResolver( Tcl_Interp *interp, const char *varName, Tcl_Namespace *contextNs, int flags, Tcl_Var *varPtr) { int result; Tcl_ResolvedVarInfo *rPtr = NULL; result = ProcedureMethodCompiledVarResolver(interp, varName, strlen(varName), contextNs, &rPtr); if (result != TCL_OK) { return result; } *varPtr = rPtr->fetchProc(interp, rPtr); /* * Must not retain reference to resolved information. [Bug 3105999] */ if (rPtr != NULL) { rPtr->deleteProc(rPtr); } return (*varPtr? TCL_OK : TCL_CONTINUE); } static Tcl_Var ProcedureMethodCompiledVarConnect( Tcl_Interp *interp, Tcl_ResolvedVarInfo *rPtr) { OOResVarInfo *infoPtr = (OOResVarInfo *) rPtr; Interp *iPtr = (Interp *) interp; CallFrame *framePtr = iPtr->varFramePtr; CallContext *contextPtr; Tcl_Obj *variableObj; Tcl_HashEntry *hPtr; int i, isNew, cacheIt, varLen, len; const char *match, *varName; /* * Check that the variable is being requested in a context that is also a * method call; if not (i.e. we're evaluating in the object's namespace or * in a procedure of that namespace) then we do nothing. */ if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) { return NULL; } contextPtr = framePtr->clientData; /* * If we've done the work before (in a comparable context) then reuse that * rather than performing resolution ourselves. */ if (infoPtr->cachedObjectVar) { return infoPtr->cachedObjectVar; } /* * Check if the variable is one we want to resolve at all (i.e. whether it * is in the list provided by the user). If not, we mustn't do anything * either. */ varName = TclGetStringFromObj(infoPtr->variableObj, &varLen); if (contextPtr->callPtr->chain[contextPtr->index] .mPtr->declaringClassPtr != NULL) { FOREACH(variableObj, contextPtr->callPtr->chain[contextPtr->index] .mPtr->declaringClassPtr->variables) { match = TclGetStringFromObj(variableObj, &len); if ((len == varLen) && !memcmp(match, varName, len)) { cacheIt = 0; goto gotMatch; } } } else { FOREACH(variableObj, contextPtr->oPtr->variables) { match = TclGetStringFromObj(variableObj, &len); if ((len == varLen) && !memcmp(match, varName, len)) { cacheIt = 1; goto gotMatch; } } } return NULL; /* * It is a variable we want to resolve, so resolve it. */ gotMatch: hPtr = Tcl_CreateHashEntry(TclVarTable(contextPtr->oPtr->namespacePtr), (char *) variableObj, &isNew); if (isNew) { TclSetVarNamespaceVar((Var *) TclVarHashGetValue(hPtr)); } if (cacheIt) { infoPtr->cachedObjectVar = TclVarHashGetValue(hPtr); /* * We must keep a reference to the variable so everything will * continue to work correctly even if it is unset; being unset does * not end the life of the variable at this level. [Bug 3185009] */ VarHashRefCount(infoPtr->cachedObjectVar)++; } return TclVarHashGetValue(hPtr); } static void ProcedureMethodCompiledVarDelete( Tcl_ResolvedVarInfo *rPtr) { OOResVarInfo *infoPtr = (OOResVarInfo *) rPtr; /* * Release the reference to the variable if we were holding it. */ if (infoPtr->cachedObjectVar) { VarHashRefCount(infoPtr->cachedObjectVar)--; TclCleanupVar((Var *) infoPtr->cachedObjectVar, NULL); } Tcl_DecrRefCount(infoPtr->variableObj); ckfree(infoPtr); } static int ProcedureMethodCompiledVarResolver( Tcl_Interp *interp, const char *varName, int length, Tcl_Namespace *contextNs, Tcl_ResolvedVarInfo **rPtrPtr) { OOResVarInfo *infoPtr; Tcl_Obj *variableObj = Tcl_NewStringObj(varName, length); /* * Do not create resolvers for cases that contain namespace separators or * which look like array accesses. Both will lead us astray. */ if (strstr(Tcl_GetString(variableObj), "::") != NULL || Tcl_StringMatch(Tcl_GetString(variableObj), "*(*)")) { Tcl_DecrRefCount(variableObj); return TCL_CONTINUE; } infoPtr = ckalloc(sizeof(OOResVarInfo)); infoPtr->info.fetchProc = ProcedureMethodCompiledVarConnect; infoPtr->info.deleteProc = ProcedureMethodCompiledVarDelete; infoPtr->cachedObjectVar = NULL; infoPtr->variableObj = variableObj; Tcl_IncrRefCount(variableObj); *rPtrPtr = &infoPtr->info; return TCL_OK; } /* * ---------------------------------------------------------------------- * * RenderDeclarerName -- * * Returns the name of the entity (object or class) which declared a * method. Used for producing information for [info frame] in such a way * that the expensive part of this (generating the object or class name * itself) isn't done until it is needed. * * ---------------------------------------------------------------------- */ static Tcl_Obj * RenderDeclarerName( ClientData clientData) { struct PNI *pni = clientData; Tcl_Object object = Tcl_MethodDeclarerObject(pni->method); if (object == NULL) { object = Tcl_GetClassAsObject(Tcl_MethodDeclarerClass(pni->method)); } return TclOOObjectName(pni->interp, (Object *) object); } /* * ---------------------------------------------------------------------- * * MethodErrorHandler, ConstructorErrorHandler, DestructorErrorHandler -- * * How to fill in the stack trace correctly upon error in various forms * of procedure-like methods. LIMIT is how long the inserted strings in * the error traces should get before being converted to have ellipses, * and ELLIPSIFY is a macro to do the conversion (with the help of a * %.*s%s format field). Note that ELLIPSIFY is only safe for use in * suitable formatting contexts. * * ---------------------------------------------------------------------- */ #define LIMIT 60 #define ELLIPSIFY(str,len) \ ((len) > LIMIT ? LIMIT : (len)), (str), ((len) > LIMIT ? "..." : "") static void MethodErrorHandler( Tcl_Interp *interp, Tcl_Obj *methodNameObj) { int nameLen, objectNameLen; CallContext *contextPtr = ((Interp *) interp)->varFramePtr->clientData; Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; const char *objectName, *kindName, *methodName = Tcl_GetStringFromObj(mPtr->namePtr, &nameLen); Object *declarerPtr; if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; kindName = "object"; } else { if (mPtr->declaringClassPtr == NULL) { Tcl_Panic("method not declared in class or object"); } declarerPtr = mPtr->declaringClassPtr->thisPtr; kindName = "class"; } objectName = Tcl_GetStringFromObj(TclOOObjectName(interp, declarerPtr), &objectNameLen); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (%s \"%.*s%s\" method \"%.*s%s\" line %d)", kindName, ELLIPSIFY(objectName, objectNameLen), ELLIPSIFY(methodName, nameLen), Tcl_GetErrorLine(interp))); } static void ConstructorErrorHandler( Tcl_Interp *interp, Tcl_Obj *methodNameObj) { CallContext *contextPtr = ((Interp *) interp)->varFramePtr->clientData; Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; Object *declarerPtr; const char *objectName, *kindName; int objectNameLen; if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; kindName = "object"; } else { if (mPtr->declaringClassPtr == NULL) { Tcl_Panic("method not declared in class or object"); } declarerPtr = mPtr->declaringClassPtr->thisPtr; kindName = "class"; } objectName = Tcl_GetStringFromObj(TclOOObjectName(interp, declarerPtr), &objectNameLen); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (%s \"%.*s%s\" constructor line %d)", kindName, ELLIPSIFY(objectName, objectNameLen), Tcl_GetErrorLine(interp))); } static void DestructorErrorHandler( Tcl_Interp *interp, Tcl_Obj *methodNameObj) { CallContext *contextPtr = ((Interp *) interp)->varFramePtr->clientData; Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; Object *declarerPtr; const char *objectName, *kindName; int objectNameLen; if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; kindName = "object"; } else { if (mPtr->declaringClassPtr == NULL) { Tcl_Panic("method not declared in class or object"); } declarerPtr = mPtr->declaringClassPtr->thisPtr; kindName = "class"; } objectName = Tcl_GetStringFromObj(TclOOObjectName(interp, declarerPtr), &objectNameLen); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (%s \"%.*s%s\" destructor line %d)", kindName, ELLIPSIFY(objectName, objectNameLen), Tcl_GetErrorLine(interp))); } /* * ---------------------------------------------------------------------- * * DeleteProcedureMethod, CloneProcedureMethod -- * * How to delete and clone procedure-like methods. * * ---------------------------------------------------------------------- */ static void DeleteProcedureMethodRecord( ProcedureMethod *pmPtr) { TclProcDeleteProc(pmPtr->procPtr); if (pmPtr->deleteClientdataProc) { pmPtr->deleteClientdataProc(pmPtr->clientData); } ckfree(pmPtr); } static void DeleteProcedureMethod( ClientData clientData) { register ProcedureMethod *pmPtr = clientData; if (pmPtr->refCount-- <= 1) { DeleteProcedureMethodRecord(pmPtr); } } static int CloneProcedureMethod( Tcl_Interp *interp, ClientData clientData, ClientData *newClientData) { ProcedureMethod *pmPtr = clientData; ProcedureMethod *pm2Ptr; Tcl_Obj *bodyObj, *argsObj; CompiledLocal *localPtr; /* * Copy the argument list. */ argsObj = Tcl_NewObj(); for (localPtr=pmPtr->procPtr->firstLocalPtr; localPtr!=NULL; localPtr=localPtr->nextPtr) { if (TclIsVarArgument(localPtr)) { Tcl_Obj *argObj = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, argObj, Tcl_NewStringObj(localPtr->name, -1)); if (localPtr->defValuePtr != NULL) { Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr); } Tcl_ListObjAppendElement(NULL, argsObj, argObj); } } /* * Must strip the internal representation in order to ensure that any * bound references to instance variables are removed. [Bug 3609693] */ bodyObj = Tcl_DuplicateObj(pmPtr->procPtr->bodyPtr); TclFreeIntRep(bodyObj); /* * Create the actual copy of the method record, manufacturing a new proc * record. */ pm2Ptr = ckalloc(sizeof(ProcedureMethod)); memcpy(pm2Ptr, pmPtr, sizeof(ProcedureMethod)); pm2Ptr->refCount = 1; Tcl_IncrRefCount(argsObj); Tcl_IncrRefCount(bodyObj); if (TclCreateProc(interp, NULL, "", argsObj, bodyObj, &pm2Ptr->procPtr) != TCL_OK) { Tcl_DecrRefCount(argsObj); Tcl_DecrRefCount(bodyObj); ckfree(pm2Ptr); return TCL_ERROR; } Tcl_DecrRefCount(argsObj); Tcl_DecrRefCount(bodyObj); if (pmPtr->cloneClientdataProc) { pm2Ptr->clientData = pmPtr->cloneClientdataProc(pmPtr->clientData); } *newClientData = pm2Ptr; return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOONewForwardInstanceMethod -- * * Create a forwarded method for an object. * * ---------------------------------------------------------------------- */ Method * TclOONewForwardInstanceMethod( Tcl_Interp *interp, /* Interpreter for error reporting. */ Object *oPtr, /* The object to attach the method to. */ int flags, /* Whether the method is public or not. */ Tcl_Obj *nameObj, /* The name of the method. */ Tcl_Obj *prefixObj) /* List of arguments that form the command * prefix to forward to. */ { int prefixLen; register ForwardMethod *fmPtr; if (Tcl_ListObjLength(interp, prefixObj, &prefixLen) != TCL_OK) { return NULL; } if (prefixLen < 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "method forward prefix must be non-empty", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_FORWARD", NULL); return NULL; } fmPtr = ckalloc(sizeof(ForwardMethod)); fmPtr->prefixObj = prefixObj; Tcl_IncrRefCount(prefixObj); return (Method *) Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, nameObj, flags, &fwdMethodType, fmPtr); } /* * ---------------------------------------------------------------------- * * TclOONewForwardMethod -- * * Create a new forwarded method for a class. * * ---------------------------------------------------------------------- */ Method * TclOONewForwardMethod( Tcl_Interp *interp, /* Interpreter for error reporting. */ Class *clsPtr, /* The class to attach the method to. */ int flags, /* Whether the method is public or not. */ Tcl_Obj *nameObj, /* The name of the method. */ Tcl_Obj *prefixObj) /* List of arguments that form the command * prefix to forward to. */ { int prefixLen; register ForwardMethod *fmPtr; if (Tcl_ListObjLength(interp, prefixObj, &prefixLen) != TCL_OK) { return NULL; } if (prefixLen < 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "method forward prefix must be non-empty", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_FORWARD", NULL); return NULL; } fmPtr = ckalloc(sizeof(ForwardMethod)); fmPtr->prefixObj = prefixObj; Tcl_IncrRefCount(prefixObj); return (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr, nameObj, flags, &fwdMethodType, fmPtr); } /* * ---------------------------------------------------------------------- * * InvokeForwardMethod -- * * How to invoke a forwarded method. Works by doing some ensemble-like * command rearranging and then invokes some other Tcl command. * * ---------------------------------------------------------------------- */ static int InvokeForwardMethod( ClientData clientData, /* Pointer to some per-method context. */ Tcl_Interp *interp, Tcl_ObjectContext context, /* The method calling context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* Arguments as actually seen. */ { CallContext *contextPtr = (CallContext *) context; ForwardMethod *fmPtr = clientData; Tcl_Obj **argObjs, **prefixObjs; int numPrefixes, len, skip = contextPtr->skip; /* * Build the real list of arguments to use. Note that we know that the * prefixObj field of the ForwardMethod structure holds a reference to a * non-empty list, so there's a whole class of failures ("not a list") we * can ignore here. */ Tcl_ListObjGetElements(NULL, fmPtr->prefixObj, &numPrefixes, &prefixObjs); argObjs = InitEnsembleRewrite(interp, objc, objv, skip, numPrefixes, prefixObjs, &len); Tcl_NRAddCallback(interp, FinalizeForwardCall, argObjs, NULL, NULL, NULL); ((Interp *)interp)->lookupNsPtr = (Namespace *) contextPtr->oPtr->namespacePtr; return TclNREvalObjv(interp, len, argObjs, TCL_EVAL_NOERR, NULL); } static int FinalizeForwardCall( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj **argObjs = data[0]; TclStackFree(interp, argObjs); return result; } /* * ---------------------------------------------------------------------- * * DeleteForwardMethod, CloneForwardMethod -- * * How to delete and clone forwarded methods. * * ---------------------------------------------------------------------- */ static void DeleteForwardMethod( ClientData clientData) { ForwardMethod *fmPtr = clientData; Tcl_DecrRefCount(fmPtr->prefixObj); ckfree(fmPtr); } static int CloneForwardMethod( Tcl_Interp *interp, ClientData clientData, ClientData *newClientData) { ForwardMethod *fmPtr = clientData; ForwardMethod *fm2Ptr = ckalloc(sizeof(ForwardMethod)); fm2Ptr->prefixObj = fmPtr->prefixObj; Tcl_IncrRefCount(fm2Ptr->prefixObj); *newClientData = fm2Ptr; return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOOGetProcFromMethod, TclOOGetFwdFromMethod -- * * Utility functions used for procedure-like and forwarding method * introspection. * * ---------------------------------------------------------------------- */ Proc * TclOOGetProcFromMethod( Method *mPtr) { if (mPtr->typePtr == &procMethodType) { ProcedureMethod *pmPtr = mPtr->clientData; return pmPtr->procPtr; } return NULL; } Tcl_Obj * TclOOGetMethodBody( Method *mPtr) { if (mPtr->typePtr == &procMethodType) { ProcedureMethod *pmPtr = mPtr->clientData; if (pmPtr->procPtr->bodyPtr->bytes == NULL) { (void) Tcl_GetString(pmPtr->procPtr->bodyPtr); } return pmPtr->procPtr->bodyPtr; } return NULL; } Tcl_Obj * TclOOGetFwdFromMethod( Method *mPtr) { if (mPtr->typePtr == &fwdMethodType) { ForwardMethod *fwPtr = mPtr->clientData; return fwPtr->prefixObj; } return NULL; } /* * ---------------------------------------------------------------------- * * InitEnsembleRewrite -- * * Utility function that wraps up a lot of the complexity involved in * doing ensemble-like command forwarding. Here is a picture of memory * management plan: * * <-----------------objc----------------------> * objv: |=============|===============================| * <-toRewrite-> | * \ * <-rewriteLength-> \ * rewriteObjs: |=================| \ * | | * V V * argObjs: |=================|===============================| * <------------------*lengthPtr-------------------> * * ---------------------------------------------------------------------- */ static Tcl_Obj ** InitEnsembleRewrite( Tcl_Interp *interp, /* Place to log the rewrite info. */ int objc, /* Number of real arguments. */ Tcl_Obj *const *objv, /* The real arguments. */ int toRewrite, /* Number of real arguments to replace. */ int rewriteLength, /* Number of arguments to insert instead. */ Tcl_Obj *const *rewriteObjs,/* Arguments to insert instead. */ int *lengthPtr) /* Where to write the resulting length of the * array of rewritten arguments. */ { Interp *iPtr = (Interp *) interp; int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL); Tcl_Obj **argObjs; unsigned len = rewriteLength + objc - toRewrite; argObjs = TclStackAlloc(interp, sizeof(Tcl_Obj *) * len); memcpy(argObjs, rewriteObjs, rewriteLength * sizeof(Tcl_Obj *)); memcpy(argObjs + rewriteLength, objv + toRewrite, sizeof(Tcl_Obj *) * (objc - toRewrite)); /* * Now plumb this into the core ensemble rewrite logging system so that * Tcl_WrongNumArgs() can rewrite its result appropriately. The rules for * how to store the rewrite rules get complex solely because of the case * where an ensemble rewrites itself out of the picture; when that * happens, the quality of the error message rewrite falls drastically * (and unavoidably). */ if (isRootEnsemble) { iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = toRewrite; iPtr->ensembleRewrite.numInsertedObjs = rewriteLength; } else { int numIns = iPtr->ensembleRewrite.numInsertedObjs; if (numIns < toRewrite) { iPtr->ensembleRewrite.numRemovedObjs += toRewrite - numIns; iPtr->ensembleRewrite.numInsertedObjs += rewriteLength - 1; } else { iPtr->ensembleRewrite.numInsertedObjs += rewriteLength - toRewrite; } } *lengthPtr = len; return argObjs; } /* * ---------------------------------------------------------------------- * * assorted trivial 'getter' functions * * ---------------------------------------------------------------------- */ Tcl_Object Tcl_MethodDeclarerObject( Tcl_Method method) { return (Tcl_Object) ((Method *) method)->declaringObjectPtr; } Tcl_Class Tcl_MethodDeclarerClass( Tcl_Method method) { return (Tcl_Class) ((Method *) method)->declaringClassPtr; } Tcl_Obj * Tcl_MethodName( Tcl_Method method) { return ((Method *) method)->namePtr; } int Tcl_MethodIsType( Tcl_Method method, const Tcl_MethodType *typePtr, ClientData *clientDataPtr) { Method *mPtr = (Method *) method; if (mPtr->typePtr == typePtr) { if (clientDataPtr != NULL) { *clientDataPtr = mPtr->clientData; } return 1; } return 0; } int Tcl_MethodIsPublic( Tcl_Method method) { return (((Method *)method)->flags & PUBLIC_METHOD) ? 1 : 0; } /* * Extended method construction for itcl-ng. */ Tcl_Method TclOONewProcInstanceMethodEx( Tcl_Interp *interp, /* The interpreter containing the object. */ Tcl_Object oPtr, /* The object to modify. */ TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, ClientData clientData, Tcl_Obj *nameObj, /* The name of the method, which must not be * NULL. */ Tcl_Obj *argsObj, /* The formal argument list for the method, * which must not be NULL. */ Tcl_Obj *bodyObj, /* The body of the method, which must not be * NULL. */ int flags, /* Whether this is a public method. */ void **internalTokenPtr) /* If non-NULL, points to a variable that gets * the reference to the ProcedureMethod * structure. */ { ProcedureMethod *pmPtr; Tcl_Method method = (Tcl_Method) TclOONewProcInstanceMethod(interp, (Object *) oPtr, flags, nameObj, argsObj, bodyObj, &pmPtr); if (method == NULL) { return NULL; } pmPtr->flags = flags & USE_DECLARER_NS; pmPtr->preCallProc = preCallPtr; pmPtr->postCallProc = postCallPtr; pmPtr->errProc = errProc; pmPtr->clientData = clientData; if (internalTokenPtr != NULL) { *internalTokenPtr = pmPtr; } return method; } Tcl_Method TclOONewProcMethodEx( Tcl_Interp *interp, /* The interpreter containing the class. */ Tcl_Class clsPtr, /* The class to modify. */ TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, ClientData clientData, Tcl_Obj *nameObj, /* The name of the method, which may be NULL; * if so, up to caller to manage storage * (e.g., because it is a constructor or * destructor). */ Tcl_Obj *argsObj, /* The formal argument list for the method, * which may be NULL; if so, it is equivalent * to an empty list. */ Tcl_Obj *bodyObj, /* The body of the method, which must not be * NULL. */ int flags, /* Whether this is a public method. */ void **internalTokenPtr) /* If non-NULL, points to a variable that gets * the reference to the ProcedureMethod * structure. */ { ProcedureMethod *pmPtr; Tcl_Method method = (Tcl_Method) TclOONewProcMethod(interp, (Class *) clsPtr, flags, nameObj, argsObj, bodyObj, &pmPtr); if (method == NULL) { return NULL; } pmPtr->flags = flags & USE_DECLARER_NS; pmPtr->preCallProc = preCallPtr; pmPtr->postCallProc = postCallPtr; pmPtr->errProc = errProc; pmPtr->clientData = clientData; if (internalTokenPtr != NULL) { *internalTokenPtr = pmPtr; } return method; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclClock.c0000644000175000017500000015163712663660065015122 0ustar sergeisergei/* * tclClock.c -- * * Contains the time and date related commands. This code is derived from * the time and date facilities of TclX, by Mark Diekhans and Karl * Lehenbauer. * * Copyright 1991-1995 Karl Lehenbauer and Mark Diekhans. * Copyright (c) 1995 Sun Microsystems, Inc. * Copyright (c) 2004 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Windows has mktime. The configurators do not check. */ #ifdef _WIN32 #define HAVE_MKTIME 1 #endif /* * Constants */ #define JULIAN_DAY_POSIX_EPOCH 2440588 #define SECONDS_PER_DAY 86400 #define JULIAN_SEC_POSIX_EPOCH (((Tcl_WideInt) JULIAN_DAY_POSIX_EPOCH) \ * SECONDS_PER_DAY) #define FOUR_CENTURIES 146097 /* days */ #define JDAY_1_JAN_1_CE_JULIAN 1721424 #define JDAY_1_JAN_1_CE_GREGORIAN 1721426 #define ONE_CENTURY_GREGORIAN 36524 /* days */ #define FOUR_YEARS 1461 /* days */ #define ONE_YEAR 365 /* days */ /* * Table of the days in each month, leap and common years */ static const int hath[2][12] = { {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; static const int daysInPriorMonths[2][13] = { {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366} }; /* * Enumeration of the string literals used in [clock] */ typedef enum ClockLiteral { LIT__NIL, LIT__DEFAULT_FORMAT, LIT_BCE, LIT_C, LIT_CANNOT_USE_GMT_AND_TIMEZONE, LIT_CE, LIT_DAYOFMONTH, LIT_DAYOFWEEK, LIT_DAYOFYEAR, LIT_ERA, LIT_GMT, LIT_GREGORIAN, LIT_INTEGER_VALUE_TOO_LARGE, LIT_ISO8601WEEK, LIT_ISO8601YEAR, LIT_JULIANDAY, LIT_LOCALSECONDS, LIT_MONTH, LIT_SECONDS, LIT_TZNAME, LIT_TZOFFSET, LIT_YEAR, LIT__END } ClockLiteral; static const char *const literals[] = { "", "%a %b %d %H:%M:%S %Z %Y", "BCE", "C", "cannot use -gmt and -timezone in same call", "CE", "dayOfMonth", "dayOfWeek", "dayOfYear", "era", ":GMT", "gregorian", "integer value too large to represent", "iso8601Week", "iso8601Year", "julianDay", "localSeconds", "month", "seconds", "tzName", "tzOffset", "year" }; /* * Structure containing the client data for [clock] */ typedef struct ClockClientData { int refCount; /* Number of live references. */ Tcl_Obj **literals; /* Pool of object literals. */ } ClockClientData; /* * Structure containing the fields used in [clock format] and [clock scan] */ typedef struct TclDateFields { Tcl_WideInt seconds; /* Time expressed in seconds from the Posix * epoch */ Tcl_WideInt localSeconds; /* Local time expressed in nominal seconds * from the Posix epoch */ int tzOffset; /* Time zone offset in seconds east of * Greenwich */ Tcl_Obj *tzName; /* Time zone name */ int julianDay; /* Julian Day Number in local time zone */ enum {BCE=1, CE=0} era; /* Era */ int gregorian; /* Flag == 1 if the date is Gregorian */ int year; /* Year of the era */ int dayOfYear; /* Day of the year (1 January == 1) */ int month; /* Month number */ int dayOfMonth; /* Day of the month */ int iso8601Year; /* ISO8601 week-based year */ int iso8601Week; /* ISO8601 week number */ int dayOfWeek; /* Day of the week */ } TclDateFields; static const char *const eras[] = { "CE", "BCE", NULL }; /* * Thread specific data block holding a 'struct tm' for the 'gmtime' and * 'localtime' library calls. */ static Tcl_ThreadDataKey tmKey; /* * Mutex protecting 'gmtime', 'localtime' and 'mktime' calls and the statics * in the date parsing code. */ TCL_DECLARE_MUTEX(clockMutex) /* * Function prototypes for local procedures in this file: */ static int ConvertUTCToLocal(Tcl_Interp *, TclDateFields *, Tcl_Obj *, int); static int ConvertUTCToLocalUsingTable(Tcl_Interp *, TclDateFields *, int, Tcl_Obj *const[]); static int ConvertUTCToLocalUsingC(Tcl_Interp *, TclDateFields *, int); static int ConvertLocalToUTC(Tcl_Interp *, TclDateFields *, Tcl_Obj *, int); static int ConvertLocalToUTCUsingTable(Tcl_Interp *, TclDateFields *, int, Tcl_Obj *const[]); static int ConvertLocalToUTCUsingC(Tcl_Interp *, TclDateFields *, int); static Tcl_Obj * LookupLastTransition(Tcl_Interp *, Tcl_WideInt, int, Tcl_Obj *const *); static void GetYearWeekDay(TclDateFields *, int); static void GetGregorianEraYearDay(TclDateFields *, int); static void GetMonthDay(TclDateFields *); static void GetJulianDayFromEraYearWeekDay(TclDateFields *, int); static void GetJulianDayFromEraYearMonthDay(TclDateFields *, int); static int IsGregorianLeapYear(TclDateFields *); static int WeekdayOnOrBefore(int, int); static int ClockClicksObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ClockConvertlocaltoutcObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ClockGetdatefieldsObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ClockGetjuliandayfromerayearmonthdayObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ClockGetjuliandayfromerayearweekdayObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ClockGetenvObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ClockMicrosecondsObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ClockMillisecondsObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ClockParseformatargsObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ClockSecondsObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static struct tm * ThreadSafeLocalTime(const time_t *); static void TzsetIfNecessary(void); static void ClockDeleteCmdProc(ClientData); /* * Structure containing description of "native" clock commands to create. */ struct ClockCommand { const char *name; /* The tail of the command name. The full name * is "::tcl::clock::". When NULL marks * the end of the table. */ Tcl_ObjCmdProc *objCmdProc; /* Function that implements the command. This * will always have the ClockClientData sent * to it, but may well ignore this data. */ }; static const struct ClockCommand clockCommands[] = { { "clicks", ClockClicksObjCmd }, { "getenv", ClockGetenvObjCmd }, { "microseconds", ClockMicrosecondsObjCmd }, { "milliseconds", ClockMillisecondsObjCmd }, { "seconds", ClockSecondsObjCmd }, { "Oldscan", TclClockOldscanObjCmd }, { "ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd }, { "GetDateFields", ClockGetdatefieldsObjCmd }, { "GetJulianDayFromEraYearMonthDay", ClockGetjuliandayfromerayearmonthdayObjCmd }, { "GetJulianDayFromEraYearWeekDay", ClockGetjuliandayfromerayearweekdayObjCmd }, { "ParseFormatArgs", ClockParseformatargsObjCmd }, { NULL, NULL } }; /* *---------------------------------------------------------------------- * * TclClockInit -- * * Registers the 'clock' subcommands with the Tcl interpreter and * initializes its client data (which consists mostly of constant * Tcl_Obj's that it is too much trouble to keep recreating). * * Results: * None. * * Side effects: * Installs the commands and creates the client data * *---------------------------------------------------------------------- */ void TclClockInit( Tcl_Interp *interp) /* Tcl interpreter */ { const struct ClockCommand *clockCmdPtr; char cmdName[50]; /* Buffer large enough to hold the string *::tcl::clock::GetJulianDayFromEraYearMonthDay * plus a terminating NUL. */ ClockClientData *data; int i; /* * Safe interps get [::clock] as alias to a master, so do not need their * own copies of the support routines. */ if (Tcl_IsSafe(interp)) { return; } /* * Create the client data, which is a refcounted literal pool. */ data = ckalloc(sizeof(ClockClientData)); data->refCount = 0; data->literals = ckalloc(LIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < LIT__END; ++i) { data->literals[i] = Tcl_NewStringObj(literals[i], -1); Tcl_IncrRefCount(data->literals[i]); } /* * Install the commands. */ #define TCL_CLOCK_PREFIX_LEN 14 /* == strlen("::tcl::clock::") */ memcpy(cmdName, "::tcl::clock::", TCL_CLOCK_PREFIX_LEN); for (clockCmdPtr=clockCommands ; clockCmdPtr->name!=NULL ; clockCmdPtr++) { strcpy(cmdName + TCL_CLOCK_PREFIX_LEN, clockCmdPtr->name); data->refCount++; Tcl_CreateObjCommand(interp, cmdName, clockCmdPtr->objCmdProc, data, ClockDeleteCmdProc); } } /* *---------------------------------------------------------------------- * * ClockConvertlocaltoutcObjCmd -- * * Tcl command that converts a UTC time to a local time by whatever means * is available. * * Usage: * ::tcl::clock::ConvertUTCToLocal dictionary tzdata changeover * * Parameters: * dict - Dictionary containing a 'localSeconds' entry. * tzdata - Time zone data * changeover - Julian Day of the adoption of the Gregorian calendar. * * Results: * Returns a standard Tcl result. * * Side effects: * On success, sets the interpreter result to the given dictionary * augmented with a 'seconds' field giving the UTC time. On failure, * leaves an error message in the interpreter result. * *---------------------------------------------------------------------- */ static int ClockConvertlocaltoutcObjCmd( ClientData clientData, /* Client data */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ { ClockClientData *data = clientData; Tcl_Obj *const *literals = data->literals; Tcl_Obj *secondsObj; Tcl_Obj *dict; int changeover; TclDateFields fields; int created = 0; int status; /* * Check params and convert time. */ if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "dict tzdata changeover"); return TCL_ERROR; } dict = objv[1]; if (Tcl_DictObjGet(interp, dict, literals[LIT_LOCALSECONDS], &secondsObj)!= TCL_OK) { return TCL_ERROR; } if (secondsObj == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("key \"localseconds\" not " "found in dictionary", -1)); return TCL_ERROR; } if ((Tcl_GetWideIntFromObj(interp, secondsObj, &fields.localSeconds) != TCL_OK) || (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK) || ConvertLocalToUTC(interp, &fields, objv[2], changeover)) { return TCL_ERROR; } /* * Copy-on-write; set the 'seconds' field in the dictionary and place the * modified dictionary in the interpreter result. */ if (Tcl_IsShared(dict)) { dict = Tcl_DuplicateObj(dict); created = 1; Tcl_IncrRefCount(dict); } status = Tcl_DictObjPut(interp, dict, literals[LIT_SECONDS], Tcl_NewWideIntObj(fields.seconds)); if (status == TCL_OK) { Tcl_SetObjResult(interp, dict); } if (created) { Tcl_DecrRefCount(dict); } return status; } /* *---------------------------------------------------------------------- * * ClockGetdatefieldsObjCmd -- * * Tcl command that determines the values that [clock format] will use in * formatting a date, and populates a dictionary with them. * * Usage: * ::tcl::clock::GetDateFields seconds tzdata changeover * * Parameters: * seconds - Time expressed in seconds from the Posix epoch. * tzdata - Time zone data of the time zone in which time is to be * expressed. * changeover - Julian Day Number at which the current locale adopted * the Gregorian calendar * * Results: * Returns a dictonary populated with the fields: * seconds - Seconds from the Posix epoch * localSeconds - Nominal seconds from the Posix epoch in the * local time zone. * tzOffset - Time zone offset in seconds east of Greenwich * tzName - Time zone name * julianDay - Julian Day Number in the local time zone * *---------------------------------------------------------------------- */ int ClockGetdatefieldsObjCmd( ClientData clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ { TclDateFields fields; Tcl_Obj *dict; ClockClientData *data = clientData; Tcl_Obj *const *literals = data->literals; int changeover; /* * Check params. */ if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "seconds tzdata changeover"); return TCL_ERROR; } if (Tcl_GetWideIntFromObj(interp, objv[1], &fields.seconds) != TCL_OK || TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK) { return TCL_ERROR; } /* * fields.seconds could be an unsigned number that overflowed. Make sure * that it isn't. */ if (objv[1]->typePtr == &tclBignumType) { Tcl_SetObjResult(interp, literals[LIT_INTEGER_VALUE_TOO_LARGE]); return TCL_ERROR; } /* * Convert UTC time to local. */ if (ConvertUTCToLocal(interp, &fields, objv[2], changeover) != TCL_OK) { return TCL_ERROR; } /* * Extract Julian day. */ fields.julianDay = (int) ((fields.localSeconds + JULIAN_SEC_POSIX_EPOCH) / SECONDS_PER_DAY); /* * Convert to Julian or Gregorian calendar. */ GetGregorianEraYearDay(&fields, changeover); GetMonthDay(&fields); GetYearWeekDay(&fields, changeover); dict = Tcl_NewDictObj(); Tcl_DictObjPut(NULL, dict, literals[LIT_LOCALSECONDS], Tcl_NewWideIntObj(fields.localSeconds)); Tcl_DictObjPut(NULL, dict, literals[LIT_SECONDS], Tcl_NewWideIntObj(fields.seconds)); Tcl_DictObjPut(NULL, dict, literals[LIT_TZNAME], fields.tzName); Tcl_DecrRefCount(fields.tzName); Tcl_DictObjPut(NULL, dict, literals[LIT_TZOFFSET], Tcl_NewIntObj(fields.tzOffset)); Tcl_DictObjPut(NULL, dict, literals[LIT_JULIANDAY], Tcl_NewIntObj(fields.julianDay)); Tcl_DictObjPut(NULL, dict, literals[LIT_GREGORIAN], Tcl_NewIntObj(fields.gregorian)); Tcl_DictObjPut(NULL, dict, literals[LIT_ERA], literals[fields.era ? LIT_BCE : LIT_CE]); Tcl_DictObjPut(NULL, dict, literals[LIT_YEAR], Tcl_NewIntObj(fields.year)); Tcl_DictObjPut(NULL, dict, literals[LIT_DAYOFYEAR], Tcl_NewIntObj(fields.dayOfYear)); Tcl_DictObjPut(NULL, dict, literals[LIT_MONTH], Tcl_NewIntObj(fields.month)); Tcl_DictObjPut(NULL, dict, literals[LIT_DAYOFMONTH], Tcl_NewIntObj(fields.dayOfMonth)); Tcl_DictObjPut(NULL, dict, literals[LIT_ISO8601YEAR], Tcl_NewIntObj(fields.iso8601Year)); Tcl_DictObjPut(NULL, dict, literals[LIT_ISO8601WEEK], Tcl_NewIntObj(fields.iso8601Week)); Tcl_DictObjPut(NULL, dict, literals[LIT_DAYOFWEEK], Tcl_NewIntObj(fields.dayOfWeek)); Tcl_SetObjResult(interp, dict); return TCL_OK; } /* *---------------------------------------------------------------------- * * ClockGetjuliandayfromerayearmonthdayObjCmd -- * * Tcl command that converts a time from era-year-month-day to a Julian * Day Number. * * Parameters: * dict - Dictionary that contains 'era', 'year', 'month' and * 'dayOfMonth' keys. * changeover - Julian Day of changeover to the Gregorian calendar * * Results: * Result is either TCL_OK, with the interpreter result being the * dictionary augmented with a 'julianDay' key, or TCL_ERROR, * with the result being an error message. * *---------------------------------------------------------------------- */ static int FetchEraField( Tcl_Interp *interp, Tcl_Obj *dict, Tcl_Obj *key, int *storePtr) { Tcl_Obj *value = NULL; if (Tcl_DictObjGet(interp, dict, key, &value) != TCL_OK) { return TCL_ERROR; } if (value == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "expected key(s) not found in dictionary", -1)); return TCL_ERROR; } return Tcl_GetIndexFromObj(interp, value, eras, "era", TCL_EXACT, storePtr); } static int FetchIntField( Tcl_Interp *interp, Tcl_Obj *dict, Tcl_Obj *key, int *storePtr) { Tcl_Obj *value = NULL; if (Tcl_DictObjGet(interp, dict, key, &value) != TCL_OK) { return TCL_ERROR; } if (value == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "expected key(s) not found in dictionary", -1)); return TCL_ERROR; } return TclGetIntFromObj(interp, value, storePtr); } static int ClockGetjuliandayfromerayearmonthdayObjCmd( ClientData clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ { TclDateFields fields; Tcl_Obj *dict; ClockClientData *data = clientData; Tcl_Obj *const *literals = data->literals; int changeover; int copied = 0; int status; int era = 0; /* * Check params. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "dict changeover"); return TCL_ERROR; } dict = objv[1]; if (FetchEraField(interp, dict, literals[LIT_ERA], &era) != TCL_OK || FetchIntField(interp, dict, literals[LIT_YEAR], &fields.year) != TCL_OK || FetchIntField(interp, dict, literals[LIT_MONTH], &fields.month) != TCL_OK || FetchIntField(interp, dict, literals[LIT_DAYOFMONTH], &fields.dayOfMonth) != TCL_OK || TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) { return TCL_ERROR; } fields.era = era; /* * Get Julian day. */ GetJulianDayFromEraYearMonthDay(&fields, changeover); /* * Store Julian day in the dictionary - copy on write. */ if (Tcl_IsShared(dict)) { dict = Tcl_DuplicateObj(dict); Tcl_IncrRefCount(dict); copied = 1; } status = Tcl_DictObjPut(interp, dict, literals[LIT_JULIANDAY], Tcl_NewIntObj(fields.julianDay)); if (status == TCL_OK) { Tcl_SetObjResult(interp, dict); } if (copied) { Tcl_DecrRefCount(dict); } return status; } /* *---------------------------------------------------------------------- * * ClockGetjuliandayfromerayearweekdayObjCmd -- * * Tcl command that converts a time from the ISO calendar to a Julian Day * Number. * * Parameters: * dict - Dictionary that contains 'era', 'iso8601Year', 'iso8601Week' * and 'dayOfWeek' keys. * changeover - Julian Day of changeover to the Gregorian calendar * * Results: * Result is either TCL_OK, with the interpreter result being the * dictionary augmented with a 'julianDay' key, or TCL_ERROR, with the * result being an error message. * *---------------------------------------------------------------------- */ static int ClockGetjuliandayfromerayearweekdayObjCmd( ClientData clientData, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ { TclDateFields fields; Tcl_Obj *dict; ClockClientData *data = clientData; Tcl_Obj *const *literals = data->literals; int changeover; int copied = 0; int status; int era = 0; /* * Check params. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "dict changeover"); return TCL_ERROR; } dict = objv[1]; if (FetchEraField(interp, dict, literals[LIT_ERA], &era) != TCL_OK || FetchIntField(interp, dict, literals[LIT_ISO8601YEAR], &fields.iso8601Year) != TCL_OK || FetchIntField(interp, dict, literals[LIT_ISO8601WEEK], &fields.iso8601Week) != TCL_OK || FetchIntField(interp, dict, literals[LIT_DAYOFWEEK], &fields.dayOfWeek) != TCL_OK || TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) { return TCL_ERROR; } fields.era = era; /* * Get Julian day. */ GetJulianDayFromEraYearWeekDay(&fields, changeover); /* * Store Julian day in the dictionary - copy on write. */ if (Tcl_IsShared(dict)) { dict = Tcl_DuplicateObj(dict); Tcl_IncrRefCount(dict); copied = 1; } status = Tcl_DictObjPut(interp, dict, literals[LIT_JULIANDAY], Tcl_NewIntObj(fields.julianDay)); if (status == TCL_OK) { Tcl_SetObjResult(interp, dict); } if (copied) { Tcl_DecrRefCount(dict); } return status; } /* *---------------------------------------------------------------------- * * ConvertLocalToUTC -- * * Converts a time (in a TclDateFields structure) from the local wall * clock to UTC. * * Results: * Returns a standard Tcl result. * * Side effects: * Populates the 'seconds' field if successful; stores an error message * in the interpreter result on failure. * *---------------------------------------------------------------------- */ static int ConvertLocalToUTC( Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Fields of the time */ Tcl_Obj *tzdata, /* Time zone data */ int changeover) /* Julian Day of the Gregorian transition */ { int rowc; /* Number of rows in tzdata */ Tcl_Obj **rowv; /* Pointers to the rows */ /* * Unpack the tz data. */ if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK) { return TCL_ERROR; } /* * Special case: If the time zone is :localtime, the tzdata will be empty. * Use 'mktime' to convert the time to local */ if (rowc == 0) { return ConvertLocalToUTCUsingC(interp, fields, changeover); } else { return ConvertLocalToUTCUsingTable(interp, fields, rowc, rowv); } } /* *---------------------------------------------------------------------- * * ConvertLocalToUTCUsingTable -- * * Converts a time (in a TclDateFields structure) from local time in a * given time zone to UTC. * * Results: * Returns a standard Tcl result. * * Side effects: * Stores an error message in the interpreter if an error occurs; if * successful, stores the 'seconds' field in 'fields. * *---------------------------------------------------------------------- */ static int ConvertLocalToUTCUsingTable( Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Time to convert, with 'seconds' filled in */ int rowc, /* Number of points at which time changes */ Tcl_Obj *const rowv[]) /* Points at which time changes */ { Tcl_Obj *row; int cellc; Tcl_Obj **cellv; int have[8]; int nHave = 0; int i; int found; /* * Perform an initial lookup assuming that local == UTC, and locate the * last time conversion prior to that time. Get the offset from that row, * and look up again. Continue until we find an offset that we found * before. This definition, rather than "the same offset" ensures that we * don't enter an endless loop, as would otherwise happen when trying to * convert a non-existent time such as 02:30 during the US Spring Daylight * Saving Time transition. */ found = 0; fields->tzOffset = 0; fields->seconds = fields->localSeconds; while (!found) { row = LookupLastTransition(interp, fields->seconds, rowc, rowv); if ((row == NULL) || TclListObjGetElements(interp, row, &cellc, &cellv) != TCL_OK || TclGetIntFromObj(interp, cellv[1], &fields->tzOffset) != TCL_OK) { return TCL_ERROR; } found = 0; for (i = 0; !found && i < nHave; ++i) { if (have[i] == fields->tzOffset) { found = 1; break; } } if (!found) { if (nHave == 8) { Tcl_Panic("loop in ConvertLocalToUTCUsingTable"); } have[nHave++] = fields->tzOffset; } fields->seconds = fields->localSeconds - fields->tzOffset; } fields->tzOffset = have[i]; fields->seconds = fields->localSeconds - fields->tzOffset; return TCL_OK; } /* *---------------------------------------------------------------------- * * ConvertLocalToUTCUsingC -- * * Converts a time from local wall clock to UTC when the local time zone * cannot be determined. Uses 'mktime' to do the job. * * Results: * Returns a standard Tcl result. * * Side effects: * Stores an error message in the interpreter if an error occurs; if * successful, stores the 'seconds' field in 'fields. * *---------------------------------------------------------------------- */ static int ConvertLocalToUTCUsingC( Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Time to convert, with 'seconds' filled in */ int changeover) /* Julian Day of the Gregorian transition */ { struct tm timeVal; int localErrno; int secondOfDay; Tcl_WideInt jsec; /* * Convert the given time to a date. */ jsec = fields->localSeconds + JULIAN_SEC_POSIX_EPOCH; fields->julianDay = (int) (jsec / SECONDS_PER_DAY); secondOfDay = (int)(jsec % SECONDS_PER_DAY); if (secondOfDay < 0) { secondOfDay += SECONDS_PER_DAY; fields->julianDay--; } GetGregorianEraYearDay(fields, changeover); GetMonthDay(fields); /* * Convert the date/time to a 'struct tm'. */ timeVal.tm_year = fields->year - 1900; timeVal.tm_mon = fields->month - 1; timeVal.tm_mday = fields->dayOfMonth; timeVal.tm_hour = (secondOfDay / 3600) % 24; timeVal.tm_min = (secondOfDay / 60) % 60; timeVal.tm_sec = secondOfDay % 60; timeVal.tm_isdst = -1; timeVal.tm_wday = -1; timeVal.tm_yday = -1; /* * Get local time. It is rumored that mktime is not thread safe on some * platforms, so seize a mutex before attempting this. */ TzsetIfNecessary(); Tcl_MutexLock(&clockMutex); errno = 0; fields->seconds = (Tcl_WideInt) mktime(&timeVal); localErrno = errno; Tcl_MutexUnlock(&clockMutex); /* * If conversion fails, report an error. */ if (localErrno != 0 || (fields->seconds == -1 && timeVal.tm_yday == -1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "time value too large/small to represent", -1)); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * ConvertUTCToLocal -- * * Converts a time (in a TclDateFields structure) from UTC to local time. * * Results: * Returns a standard Tcl result. * * Side effects: * Populates the 'tzName' and 'tzOffset' fields. * *---------------------------------------------------------------------- */ static int ConvertUTCToLocal( Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Fields of the time */ Tcl_Obj *tzdata, /* Time zone data */ int changeover) /* Julian Day of the Gregorian transition */ { int rowc; /* Number of rows in tzdata */ Tcl_Obj **rowv; /* Pointers to the rows */ /* * Unpack the tz data. */ if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK) { return TCL_ERROR; } /* * Special case: If the time zone is :localtime, the tzdata will be empty. * Use 'localtime' to convert the time to local */ if (rowc == 0) { return ConvertUTCToLocalUsingC(interp, fields, changeover); } else { return ConvertUTCToLocalUsingTable(interp, fields, rowc, rowv); } } /* *---------------------------------------------------------------------- * * ConvertUTCToLocalUsingTable -- * * Converts UTC to local time, given a table of transition points * * Results: * Returns a standard Tcl result * * Side effects: * On success, fills fields->tzName, fields->tzOffset and * fields->localSeconds. On failure, places an error message in the * interpreter result. * *---------------------------------------------------------------------- */ static int ConvertUTCToLocalUsingTable( Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Fields of the date */ int rowc, /* Number of rows in the conversion table * (>= 1) */ Tcl_Obj *const rowv[]) /* Rows of the conversion table */ { Tcl_Obj *row; /* Row containing the current information */ int cellc; /* Count of cells in the row (must be 4) */ Tcl_Obj **cellv; /* Pointers to the cells */ /* * Look up the nearest transition time. */ row = LookupLastTransition(interp, fields->seconds, rowc, rowv); if (row == NULL || TclListObjGetElements(interp, row, &cellc, &cellv) != TCL_OK || TclGetIntFromObj(interp, cellv[1], &fields->tzOffset) != TCL_OK) { return TCL_ERROR; } /* * Convert the time. */ fields->tzName = cellv[3]; Tcl_IncrRefCount(fields->tzName); fields->localSeconds = fields->seconds + fields->tzOffset; return TCL_OK; } /* *---------------------------------------------------------------------- * * ConvertUTCToLocalUsingC -- * * Converts UTC to localtime in cases where the local time zone is not * determinable, using the C 'localtime' function to do it. * * Results: * Returns a standard Tcl result. * * Side effects: * On success, fills fields->tzName, fields->tzOffset and * fields->localSeconds. On failure, places an error message in the * interpreter result. * *---------------------------------------------------------------------- */ static int ConvertUTCToLocalUsingC( Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Time to convert, with 'seconds' filled in */ int changeover) /* Julian Day of the Gregorian transition */ { time_t tock; struct tm *timeVal; /* Time after conversion */ int diff; /* Time zone diff local-Greenwich */ char buffer[8]; /* Buffer for time zone name */ /* * Use 'localtime' to determine local year, month, day, time of day. */ tock = (time_t) fields->seconds; if ((Tcl_WideInt) tock != fields->seconds) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "number too large to represent as a Posix time", -1)); Tcl_SetErrorCode(interp, "CLOCK", "argTooLarge", NULL); return TCL_ERROR; } TzsetIfNecessary(); timeVal = ThreadSafeLocalTime(&tock); if (timeVal == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "localtime failed (clock value may be too " "large/small to represent)", -1)); Tcl_SetErrorCode(interp, "CLOCK", "localtimeFailed", NULL); return TCL_ERROR; } /* * Fill in the date in 'fields' and use it to derive Julian Day. */ fields->era = CE; fields->year = timeVal->tm_year + 1900; fields->month = timeVal->tm_mon + 1; fields->dayOfMonth = timeVal->tm_mday; GetJulianDayFromEraYearMonthDay(fields, changeover); /* * Convert that value to seconds. */ fields->localSeconds = (((fields->julianDay * (Tcl_WideInt) 24 + timeVal->tm_hour) * 60 + timeVal->tm_min) * 60 + timeVal->tm_sec) - JULIAN_SEC_POSIX_EPOCH; /* * Determine a time zone offset and name; just use +hhmm for the name. */ diff = (int) (fields->localSeconds - fields->seconds); fields->tzOffset = diff; if (diff < 0) { *buffer = '-'; diff = -diff; } else { *buffer = '+'; } sprintf(buffer+1, "%02d", diff / 3600); diff %= 3600; sprintf(buffer+3, "%02d", diff / 60); diff %= 60; if (diff > 0) { sprintf(buffer+5, "%02d", diff); } fields->tzName = Tcl_NewStringObj(buffer, -1); Tcl_IncrRefCount(fields->tzName); return TCL_OK; } /* *---------------------------------------------------------------------- * * LookupLastTransition -- * * Given a UTC time and a tzdata array, looks up the last transition on * or before the given time. * * Results: * Returns a pointer to the row, or NULL if an error occurs. * *---------------------------------------------------------------------- */ static Tcl_Obj * LookupLastTransition( Tcl_Interp *interp, /* Interpreter for error messages */ Tcl_WideInt tick, /* Time from the epoch */ int rowc, /* Number of rows of tzdata */ Tcl_Obj *const *rowv) /* Rows in tzdata */ { int l; int u; Tcl_Obj *compObj; Tcl_WideInt compVal; /* * Examine the first row to make sure we're in bounds. */ if (Tcl_ListObjIndex(interp, rowv[0], 0, &compObj) != TCL_OK || Tcl_GetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) { return NULL; } /* * Bizarre case - first row doesn't begin at MIN_WIDE_INT. Return it * anyway. */ if (tick < compVal) { return rowv[0]; } /* * Binary-search to find the transition. */ l = 0; u = rowc-1; while (l < u) { int m = (l + u + 1) / 2; if (Tcl_ListObjIndex(interp, rowv[m], 0, &compObj) != TCL_OK || Tcl_GetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) { return NULL; } if (tick >= compVal) { l = m; } else { u = m-1; } } return rowv[l]; } /* *---------------------------------------------------------------------- * * GetYearWeekDay -- * * Given a date with Julian Calendar Day, compute the year, week, and day * in the ISO8601 calendar. * * Results: * None. * * Side effects: * Stores 'iso8601Year', 'iso8601Week' and 'dayOfWeek' in the date * fields. * *---------------------------------------------------------------------- */ static void GetYearWeekDay( TclDateFields *fields, /* Date to convert, must have 'julianDay' */ int changeover) /* Julian Day Number of the Gregorian * transition */ { TclDateFields temp; int dayOfFiscalYear; /* * Find the given date, minus three days, plus one year. That date's * iso8601 year is an upper bound on the ISO8601 year of the given date. */ temp.julianDay = fields->julianDay - 3; GetGregorianEraYearDay(&temp, changeover); if (temp.era == BCE) { temp.iso8601Year = temp.year - 1; } else { temp.iso8601Year = temp.year + 1; } temp.iso8601Week = 1; temp.dayOfWeek = 1; GetJulianDayFromEraYearWeekDay(&temp, changeover); /* * temp.julianDay is now the start of an ISO8601 year, either the one * corresponding to the given date, or the one after. If we guessed high, * move one year earlier */ if (fields->julianDay < temp.julianDay) { if (temp.era == BCE) { temp.iso8601Year += 1; } else { temp.iso8601Year -= 1; } GetJulianDayFromEraYearWeekDay(&temp, changeover); } fields->iso8601Year = temp.iso8601Year; dayOfFiscalYear = fields->julianDay - temp.julianDay; fields->iso8601Week = (dayOfFiscalYear / 7) + 1; fields->dayOfWeek = (dayOfFiscalYear + 1) % 7; if (fields->dayOfWeek < 1) { fields->dayOfWeek += 7; } } /* *---------------------------------------------------------------------- * * GetGregorianEraYearDay -- * * Given a Julian Day Number, extracts the year and day of the year and * puts them into TclDateFields, along with the era (BCE or CE) and a * flag indicating whether the date is Gregorian or Julian. * * Results: * None. * * Side effects: * Stores 'era', 'gregorian', 'year', and 'dayOfYear'. * *---------------------------------------------------------------------- */ static void GetGregorianEraYearDay( TclDateFields *fields, /* Date fields containing 'julianDay' */ int changeover) /* Gregorian transition date */ { int jday = fields->julianDay; int day; int year; int n; if (jday >= changeover) { /* * Gregorian calendar. */ fields->gregorian = 1; year = 1; /* * n = Number of 400-year cycles since 1 January, 1 CE in the * proleptic Gregorian calendar. day = remaining days. */ day = jday - JDAY_1_JAN_1_CE_GREGORIAN; n = day / FOUR_CENTURIES; day %= FOUR_CENTURIES; if (day < 0) { day += FOUR_CENTURIES; n--; } year += 400 * n; /* * n = number of centuries since the start of (year); * day = remaining days */ n = day / ONE_CENTURY_GREGORIAN; day %= ONE_CENTURY_GREGORIAN; if (n > 3) { /* * 31 December in the last year of a 400-year cycle. */ n = 3; day += ONE_CENTURY_GREGORIAN; } year += 100 * n; } else { /* * Julian calendar. */ fields->gregorian = 0; year = 1; day = jday - JDAY_1_JAN_1_CE_JULIAN; } /* * n = number of 4-year cycles; days = remaining days. */ n = day / FOUR_YEARS; day %= FOUR_YEARS; if (day < 0) { day += FOUR_YEARS; n--; } year += 4 * n; /* * n = number of years; days = remaining days. */ n = day / ONE_YEAR; day %= ONE_YEAR; if (n > 3) { /* * 31 December of a leap year. */ n = 3; day += 365; } year += n; /* * store era/year/day back into fields. */ if (year <= 0) { fields->era = BCE; fields->year = 1 - year; } else { fields->era = CE; fields->year = year; } fields->dayOfYear = day + 1; } /* *---------------------------------------------------------------------- * * GetMonthDay -- * * Given a date as year and day-of-year, find month and day. * * Results: * None. * * Side effects: * Stores 'month' and 'dayOfMonth' in the 'fields' structure. * *---------------------------------------------------------------------- */ static void GetMonthDay( TclDateFields *fields) /* Date to convert */ { int day = fields->dayOfYear; int month; const int *h = hath[IsGregorianLeapYear(fields)]; for (month = 0; month < 12 && day > h[month]; ++month) { day -= h[month]; } fields->month = month+1; fields->dayOfMonth = day; } /* *---------------------------------------------------------------------- * * GetJulianDayFromEraYearWeekDay -- * * Given a TclDateFields structure containing era, ISO8601 year, ISO8601 * week, and day of week, computes the Julian Day Number. * * Results: * None. * * Side effects: * Stores 'julianDay' in the fields. * *---------------------------------------------------------------------- */ static void GetJulianDayFromEraYearWeekDay( TclDateFields *fields, /* Date to convert */ int changeover) /* Julian Day Number of the Gregorian * transition */ { int firstMonday; /* Julian day number of week 1, day 1 in the * given year */ TclDateFields firstWeek; /* * Find January 4 in the ISO8601 year, which will always be in week 1. */ firstWeek.era = fields->era; firstWeek.year = fields->iso8601Year; firstWeek.month = 1; firstWeek.dayOfMonth = 4; GetJulianDayFromEraYearMonthDay(&firstWeek, changeover); /* * Find Monday of week 1. */ firstMonday = WeekdayOnOrBefore(1, firstWeek.julianDay); /* * Advance to the given week and day. */ fields->julianDay = firstMonday + 7 * (fields->iso8601Week - 1) + fields->dayOfWeek - 1; } /* *---------------------------------------------------------------------- * * GetJulianDayFromEraYearMonthDay -- * * Given era, year, month, and dayOfMonth (in TclDateFields), and the * Gregorian transition date, computes the Julian Day Number. * * Results: * None. * * Side effects: * Stores day number in 'julianDay' * *---------------------------------------------------------------------- */ static void GetJulianDayFromEraYearMonthDay( TclDateFields *fields, /* Date to convert */ int changeover) /* Gregorian transition date as a Julian Day */ { int year, ym1, month, mm1, q, r, ym1o4, ym1o100, ym1o400; if (fields->era == BCE) { year = 1 - fields->year; } else { year = fields->year; } /* * Reduce month modulo 12. */ month = fields->month; mm1 = month - 1; q = mm1 / 12; r = (mm1 % 12); if (r < 0) { r += 12; q -= 1; } year += q; month = r + 1; ym1 = year - 1; /* * Adjust the year after reducing the month. */ fields->gregorian = 1; if (year < 1) { fields->era = BCE; fields->year = 1-year; } else { fields->era = CE; fields->year = year; } /* * Try an initial conversion in the Gregorian calendar. */ ym1o4 = ym1 / 4; if (ym1 % 4 < 0) { ym1o4--; } ym1o100 = ym1 / 100; if (ym1 % 100 < 0) { ym1o100--; } ym1o400 = ym1 / 400; if (ym1 % 400 < 0) { ym1o400--; } fields->julianDay = JDAY_1_JAN_1_CE_GREGORIAN - 1 + fields->dayOfMonth + daysInPriorMonths[IsGregorianLeapYear(fields)][month - 1] + (ONE_YEAR * ym1) + ym1o4 - ym1o100 + ym1o400; /* * If the resulting date is before the Gregorian changeover, convert in * the Julian calendar instead. */ if (fields->julianDay < changeover) { fields->gregorian = 0; fields->julianDay = JDAY_1_JAN_1_CE_JULIAN - 1 + fields->dayOfMonth + daysInPriorMonths[year%4 == 0][month - 1] + (365 * ym1) + ym1o4; } } /* *---------------------------------------------------------------------- * * IsGregorianLeapYear -- * * Tests whether a given year is a leap year, in either Julian or * Gregorian calendar. * * Results: * Returns 1 for a leap year, 0 otherwise. * *---------------------------------------------------------------------- */ static int IsGregorianLeapYear( TclDateFields *fields) /* Date to test */ { int year; if (fields->era == BCE) { year = 1 - fields->year; } else { year = fields->year; } if (year%4 != 0) { return 0; } else if (!(fields->gregorian)) { return 1; } else if (year%400 == 0) { return 1; } else if (year%100 == 0) { return 0; } else { return 1; } } /* *---------------------------------------------------------------------- * * WeekdayOnOrBefore -- * * Finds the Julian Day Number of a given day of the week that falls on * or before a given date, expressed as Julian Day Number. * * Results: * Returns the Julian Day Number * *---------------------------------------------------------------------- */ static int WeekdayOnOrBefore( int dayOfWeek, /* Day of week; Sunday == 0 or 7 */ int julianDay) /* Reference date */ { int k = (dayOfWeek + 6) % 7; if (k < 0) { k += 7; } return julianDay - ((julianDay - k) % 7); } /* *---------------------------------------------------------------------- * * ClockGetenvObjCmd -- * * Tcl command that reads an environment variable from the system * * Usage: * ::tcl::clock::getEnv NAME * * Parameters: * NAME - Name of the environment variable desired * * Results: * Returns a standard Tcl result. Returns an error if the variable does * not exist, with a message left in the interpreter. Returns TCL_OK and * the value of the variable if the variable does exist, * *---------------------------------------------------------------------- */ int ClockGetenvObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { const char *varName; const char *varValue; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } varName = TclGetString(objv[1]); varValue = getenv(varName); if (varValue == NULL) { varValue = ""; } Tcl_SetObjResult(interp, Tcl_NewStringObj(varValue, -1)); return TCL_OK; } /* *---------------------------------------------------------------------- * * ThreadSafeLocalTime -- * * Wrapper around the 'localtime' library function to make it thread * safe. * * Results: * Returns a pointer to a 'struct tm' in thread-specific data. * * Side effects: * Invokes localtime or localtime_r as appropriate. * *---------------------------------------------------------------------- */ static struct tm * ThreadSafeLocalTime( const time_t *timePtr) /* Pointer to the number of seconds since the * local system's epoch */ { /* * Get a thread-local buffer to hold the returned time. */ struct tm *tmPtr = Tcl_GetThreadData(&tmKey, (int) sizeof(struct tm)); #ifdef HAVE_LOCALTIME_R localtime_r(timePtr, tmPtr); #else struct tm *sysTmPtr; Tcl_MutexLock(&clockMutex); sysTmPtr = localtime(timePtr); if (sysTmPtr == NULL) { Tcl_MutexUnlock(&clockMutex); return NULL; } memcpy(tmPtr, localtime(timePtr), sizeof(struct tm)); Tcl_MutexUnlock(&clockMutex); #endif return tmPtr; } /*---------------------------------------------------------------------- * * ClockClicksObjCmd -- * * Returns a high-resolution counter. * * Results: * Returns a standard Tcl result. * * Side effects: * None. * * This function implements the 'clock clicks' Tcl command. Refer to the user * documentation for details on what it does. * *---------------------------------------------------------------------- */ int ClockClicksObjCmd( ClientData clientData, /* Client data is unused */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter values */ { static const char *const clicksSwitches[] = { "-milliseconds", "-microseconds", NULL }; enum ClicksSwitch { CLICKS_MILLIS, CLICKS_MICROS, CLICKS_NATIVE }; int index = CLICKS_NATIVE; Tcl_Time now; Tcl_WideInt clicks = 0; switch (objc) { case 1: break; case 2: if (Tcl_GetIndexFromObj(interp, objv[1], clicksSwitches, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } break; default: Tcl_WrongNumArgs(interp, 1, objv, "?-switch?"); return TCL_ERROR; } switch (index) { case CLICKS_MILLIS: Tcl_GetTime(&now); clicks = (Tcl_WideInt) now.sec * 1000 + now.usec / 1000; break; case CLICKS_NATIVE: #ifdef TCL_WIDE_CLICKS clicks = TclpGetWideClicks(); #else clicks = (Tcl_WideInt) TclpGetClicks(); #endif break; case CLICKS_MICROS: Tcl_GetTime(&now); clicks = ((Tcl_WideInt) now.sec * 1000000) + now.usec; break; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj(clicks)); return TCL_OK; } /*---------------------------------------------------------------------- * * ClockMillisecondsObjCmd - * * Returns a count of milliseconds since the epoch. * * Results: * Returns a standard Tcl result. * * Side effects: * None. * * This function implements the 'clock milliseconds' Tcl command. Refer to the * user documentation for details on what it does. * *---------------------------------------------------------------------- */ int ClockMillisecondsObjCmd( ClientData clientData, /* Client data is unused */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter values */ { Tcl_Time now; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } Tcl_GetTime(&now); Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) now.sec * 1000 + now.usec / 1000)); return TCL_OK; } /*---------------------------------------------------------------------- * * ClockMicrosecondsObjCmd - * * Returns a count of microseconds since the epoch. * * Results: * Returns a standard Tcl result. * * Side effects: * None. * * This function implements the 'clock microseconds' Tcl command. Refer to the * user documentation for details on what it does. * *---------------------------------------------------------------------- */ int ClockMicrosecondsObjCmd( ClientData clientData, /* Client data is unused */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter values */ { Tcl_Time now; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } Tcl_GetTime(&now); Tcl_SetObjResult(interp, Tcl_NewWideIntObj( ((Tcl_WideInt) now.sec * 1000000) + now.usec)); return TCL_OK; } /* *----------------------------------------------------------------------------- * * ClockParseformatargsObjCmd -- * * Parses the arguments for [clock format]. * * Results: * Returns a standard Tcl result, whose value is a four-element list * comprising the time format, the locale, and the timezone. * * This function exists because the loop that parses the [clock format] * options is a known performance "hot spot", and is implemented in an effort * to speed that particular code up. * *----------------------------------------------------------------------------- */ static int ClockParseformatargsObjCmd( ClientData clientData, /* Client data containing literal pool */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const objv[]) /* Parameter vector */ { ClockClientData *dataPtr = clientData; Tcl_Obj **litPtr = dataPtr->literals; Tcl_Obj *results[3]; /* Format, locale and timezone */ #define formatObj results[0] #define localeObj results[1] #define timezoneObj results[2] int gmtFlag = 0; static const char *const options[] = { /* Command line options expected */ "-format", "-gmt", "-locale", "-timezone", NULL }; enum optionInd { CLOCK_FORMAT_FORMAT, CLOCK_FORMAT_GMT, CLOCK_FORMAT_LOCALE, CLOCK_FORMAT_TIMEZONE }; int optionIndex; /* Index of an option. */ int saw = 0; /* Flag == 1 if option was seen already. */ Tcl_WideInt clockVal; /* Clock value - just used to parse. */ int i; /* * Args consist of a time followed by keyword-value pairs. */ if (objc < 2 || (objc % 2) != 0) { Tcl_WrongNumArgs(interp, 0, objv, "clock format clockval ?-format string? " "?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?"); Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", NULL); return TCL_ERROR; } /* * Extract values for the keywords. */ formatObj = litPtr[LIT__DEFAULT_FORMAT]; localeObj = litPtr[LIT_C]; timezoneObj = litPtr[LIT__NIL]; for (i = 2; i < objc; i+=2) { if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &optionIndex) != TCL_OK) { Tcl_SetErrorCode(interp, "CLOCK", "badOption", Tcl_GetString(objv[i]), NULL); return TCL_ERROR; } switch (optionIndex) { case CLOCK_FORMAT_FORMAT: formatObj = objv[i+1]; break; case CLOCK_FORMAT_GMT: if (Tcl_GetBooleanFromObj(interp, objv[i+1], &gmtFlag) != TCL_OK){ return TCL_ERROR; } break; case CLOCK_FORMAT_LOCALE: localeObj = objv[i+1]; break; case CLOCK_FORMAT_TIMEZONE: timezoneObj = objv[i+1]; break; } saw |= 1 << optionIndex; } /* * Check options. */ if (Tcl_GetWideIntFromObj(interp, objv[1], &clockVal) != TCL_OK) { return TCL_ERROR; } if ((saw & (1 << CLOCK_FORMAT_GMT)) && (saw & (1 << CLOCK_FORMAT_TIMEZONE))) { Tcl_SetObjResult(interp, litPtr[LIT_CANNOT_USE_GMT_AND_TIMEZONE]); Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", NULL); return TCL_ERROR; } if (gmtFlag) { timezoneObj = litPtr[LIT_GMT]; } /* * Return options as a list. */ Tcl_SetObjResult(interp, Tcl_NewListObj(3, results)); return TCL_OK; #undef timezoneObj #undef localeObj #undef formatObj } /*---------------------------------------------------------------------- * * ClockSecondsObjCmd - * * Returns a count of microseconds since the epoch. * * Results: * Returns a standard Tcl result. * * Side effects: * None. * * This function implements the 'clock seconds' Tcl command. Refer to the user * documentation for details on what it does. * *---------------------------------------------------------------------- */ int ClockSecondsObjCmd( ClientData clientData, /* Client data is unused */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter values */ { Tcl_Time now; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } Tcl_GetTime(&now); Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) now.sec)); return TCL_OK; } /* *---------------------------------------------------------------------- * * TzsetIfNecessary -- * * Calls the tzset() library function if the contents of the TZ * environment variable has changed. * * Results: * None. * * Side effects: * Calls tzset. * *---------------------------------------------------------------------- */ static void TzsetIfNecessary(void) { static char* tzWas = INT2PTR(-1); /* Previous value of TZ, protected by * clockMutex. */ const char *tzIsNow; /* Current value of TZ */ Tcl_MutexLock(&clockMutex); tzIsNow = getenv("TZ"); if (tzIsNow != NULL && (tzWas == NULL || tzWas == INT2PTR(-1) || strcmp(tzIsNow, tzWas) != 0)) { tzset(); if (tzWas != NULL && tzWas != INT2PTR(-1)) { ckfree(tzWas); } tzWas = ckalloc(strlen(tzIsNow) + 1); strcpy(tzWas, tzIsNow); } else if (tzIsNow == NULL && tzWas != NULL) { tzset(); if (tzWas != INT2PTR(-1)) ckfree(tzWas); tzWas = NULL; } Tcl_MutexUnlock(&clockMutex); } /* *---------------------------------------------------------------------- * * ClockDeleteCmdProc -- * * Remove a reference to the clock client data, and clean up memory * when it's all gone. * * Results: * None. * *---------------------------------------------------------------------- */ static void ClockDeleteCmdProc( ClientData clientData) /* Opaque pointer to the client data */ { ClockClientData *data = clientData; int i; data->refCount--; if (data->refCount == 0) { for (i = 0; i < LIT__END; ++i) { Tcl_DecrRefCount(data->literals[i]); } ckfree(data->literals); ckfree(data); } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclUtf.c0000644000175000017500000013553712663660065014626 0ustar sergeisergei/* * tclUtf.c -- * * Routines for manipulating UTF-8 strings. * * Copyright (c) 1997-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Include the static character classification tables and macros. */ #include "tclUniData.c" /* * The following macros are used for fast character category tests. The x_BITS * values are shifted right by the category value to determine whether the * given category is included in the set. */ #define ALPHA_BITS ((1 << UPPERCASE_LETTER) | (1 << LOWERCASE_LETTER) \ | (1 << TITLECASE_LETTER) | (1 << MODIFIER_LETTER) | (1< 3 4,4,4,4,4,4,4,4, #else 1,1,1,1,1,1,1,1, #endif #if TCL_UTF_MAX > 4 5,5,5,5, #else 1,1,1,1, #endif #if TCL_UTF_MAX > 5 6,6,6,6 #else 1,1,1,1 #endif }; /* * Functions used only in this module. */ static int UtfCount(int ch); /* *--------------------------------------------------------------------------- * * UtfCount -- * * Find the number of bytes in the Utf character "ch". * * Results: * The return values is the number of bytes in the Utf character "ch". * * Side effects: * None. * *--------------------------------------------------------------------------- */ INLINE static int UtfCount( int ch) /* The Tcl_UniChar whose size is returned. */ { if ((ch > 0) && (ch < UNICODE_SELF)) { return 1; } if (ch <= 0x7FF) { return 2; } #if TCL_UTF_MAX > 3 if ((ch > 0xFFFF) && (ch <= 0x10FFFF)) { return 4; } #endif return 3; } /* *--------------------------------------------------------------------------- * * Tcl_UniCharToUtf -- * * Store the given Tcl_UniChar as a sequence of UTF-8 bytes in the * provided buffer. Equivalent to Plan 9 runetochar(). * * Results: * The return values is the number of bytes in the buffer that were * consumed. * * Side effects: * None. * *--------------------------------------------------------------------------- */ INLINE int Tcl_UniCharToUtf( int ch, /* The Tcl_UniChar to be stored in the * buffer. */ char *buf) /* Buffer in which the UTF-8 representation of * the Tcl_UniChar is stored. Buffer must be * large enough to hold the UTF-8 character * (at most TCL_UTF_MAX bytes). */ { if ((ch > 0) && (ch < UNICODE_SELF)) { buf[0] = (char) ch; return 1; } if (ch >= 0) { if (ch <= 0x7FF) { buf[1] = (char) ((ch | 0x80) & 0xBF); buf[0] = (char) ((ch >> 6) | 0xC0); return 2; } if (ch <= 0xFFFF) { #if TCL_UTF_MAX == 4 if ((ch & 0xF800) == 0xD800) { if (ch & 0x0400) { /* Low surrogate */ buf[3] = (char) ((ch | 0x80) & 0xBF); buf[2] |= (char) (((ch >> 6) | 0x80) & 0x8F); return 4; } else { /* High surrogate */ ch += 0x40; buf[2] = (char) (((ch << 4) | 0x80) & 0xB0); buf[1] = (char) (((ch >> 2) | 0x80) & 0xBF); buf[0] = (char) (((ch >> 8) | 0xF0) & 0xF7); return 0; } } #endif three: buf[2] = (char) ((ch | 0x80) & 0xBF); buf[1] = (char) (((ch >> 6) | 0x80) & 0xBF); buf[0] = (char) ((ch >> 12) | 0xE0); return 3; } #if TCL_UTF_MAX > 3 if (ch <= 0x10FFFF) { buf[3] = (char) ((ch | 0x80) & 0xBF); buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF); buf[1] = (char) (((ch >> 12) | 0x80) & 0xBF); buf[0] = (char) ((ch >> 18) | 0xF0); return 4; } #endif } ch = 0xFFFD; goto three; } /* *--------------------------------------------------------------------------- * * Tcl_UniCharToUtfDString -- * * Convert the given Unicode string to UTF-8. * * Results: * The return value is a pointer to the UTF-8 representation of the * Unicode string. Storage for the return value is appended to the end of * dsPtr. * * Side effects: * None. * *--------------------------------------------------------------------------- */ char * Tcl_UniCharToUtfDString( const Tcl_UniChar *uniStr, /* Unicode string to convert to UTF-8. */ int uniLength, /* Length of Unicode string in Tcl_UniChars * (must be >= 0). */ Tcl_DString *dsPtr) /* UTF-8 representation of string is appended * to this previously initialized DString. */ { const Tcl_UniChar *w, *wEnd; char *p, *string; int oldLength; /* * UTF-8 string length in bytes will be <= Unicode string length * * TCL_UTF_MAX. */ oldLength = Tcl_DStringLength(dsPtr); Tcl_DStringSetLength(dsPtr, (oldLength + uniLength + 1) * TCL_UTF_MAX); string = Tcl_DStringValue(dsPtr) + oldLength; p = string; wEnd = uniStr + uniLength; for (w = uniStr; w < wEnd; ) { p += Tcl_UniCharToUtf(*w, p); w++; } Tcl_DStringSetLength(dsPtr, oldLength + (p - string)); return string; } /* *--------------------------------------------------------------------------- * * Tcl_UtfToUniChar -- * * Extract the Tcl_UniChar represented by the UTF-8 string. Bad UTF-8 * sequences are converted to valid Tcl_UniChars and processing * continues. Equivalent to Plan 9 chartorune(). * * The caller must ensure that the source buffer is long enough that this * routine does not run off the end and dereference non-existent memory * looking for trail bytes. If the source buffer is known to be '\0' * terminated, this cannot happen. Otherwise, the caller should call * Tcl_UtfCharComplete() before calling this routine to ensure that * enough bytes remain in the string. * * Results: * *chPtr is filled with the Tcl_UniChar, and the return value is the * number of bytes from the UTF-8 string that were consumed. * * Side effects: * None. * *--------------------------------------------------------------------------- */ int Tcl_UtfToUniChar( register const char *src, /* The UTF-8 string. */ register Tcl_UniChar *chPtr)/* Filled with the Tcl_UniChar represented by * the UTF-8 string. */ { register int byte; /* * Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones. */ byte = *((unsigned char *) src); if (byte < 0xC0) { /* * Handles properly formed UTF-8 characters between 0x01 and 0x7F. * Also treats \0 and naked trail bytes 0x80 to 0xBF as valid * characters representing themselves. */ *chPtr = (Tcl_UniChar) byte; return 1; } else if (byte < 0xE0) { if ((src[1] & 0xC0) == 0x80) { /* * Two-byte-character lead-byte followed by a trail-byte. */ *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (src[1] & 0x3F)); return 2; } /* * A two-byte-character lead-byte not followed by trail-byte * represents itself. */ *chPtr = (Tcl_UniChar) byte; return 1; } else if (byte < 0xF0) { if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80)) { /* * Three-byte-character lead byte followed by two trail bytes. */ *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) | ((src[1] & 0x3F) << 6) | (src[2] & 0x3F)); return 3; } /* * A three-byte-character lead-byte not followed by two trail-bytes * represents itself. */ *chPtr = (Tcl_UniChar) byte; return 1; } #if TCL_UTF_MAX > 3 { int ch, total, trail; total = totalBytes[byte]; trail = total - 1; if (trail > 0) { ch = byte & (0x3F >> trail); do { src++; if ((*src & 0xC0) != 0x80) { *chPtr = byte; return 1; } ch <<= 6; ch |= (*src & 0x3F); trail--; } while (trail > 0); *chPtr = ch; return total; } } #endif *chPtr = (Tcl_UniChar) byte; return 1; } /* *--------------------------------------------------------------------------- * * Tcl_UtfToUniCharDString -- * * Convert the UTF-8 string to Unicode. * * Results: * The return value is a pointer to the Unicode representation of the * UTF-8 string. Storage for the return value is appended to the end of * dsPtr. The Unicode string is terminated with a Unicode NULL character. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_UniChar * Tcl_UtfToUniCharDString( const char *src, /* UTF-8 string to convert to Unicode. */ int length, /* Length of UTF-8 string in bytes, or -1 for * strlen(). */ Tcl_DString *dsPtr) /* Unicode representation of string is * appended to this previously initialized * DString. */ { Tcl_UniChar *w, *wString; const char *p, *end; int oldLength; if (length < 0) { length = strlen(src); } /* * Unicode string length in Tcl_UniChars will be <= UTF-8 string length in * bytes. */ oldLength = Tcl_DStringLength(dsPtr); /* TODO: fix overreach! */ Tcl_DStringSetLength(dsPtr, (int) ((oldLength + length + 1) * sizeof(Tcl_UniChar))); wString = (Tcl_UniChar *) (Tcl_DStringValue(dsPtr) + oldLength); w = wString; end = src + length; for (p = src; p < end; ) { p += TclUtfToUniChar(p, w); w++; } *w = '\0'; Tcl_DStringSetLength(dsPtr, (oldLength + ((char *) w - (char *) wString))); return wString; } /* *--------------------------------------------------------------------------- * * Tcl_UtfCharComplete -- * * Determine if the UTF-8 string of the given length is long enough to be * decoded by Tcl_UtfToUniChar(). This does not ensure that the UTF-8 * string is properly formed. Equivalent to Plan 9 fullrune(). * * Results: * The return value is 0 if the string is not long enough, non-zero * otherwise. * * Side effects: * None. * *--------------------------------------------------------------------------- */ int Tcl_UtfCharComplete( const char *src, /* String to check if first few bytes contain * a complete UTF-8 character. */ int length) /* Length of above string in bytes. */ { int ch; ch = *((unsigned char *) src); return length >= totalBytes[ch]; } /* *--------------------------------------------------------------------------- * * Tcl_NumUtfChars -- * * Returns the number of characters (not bytes) in the UTF-8 string, not * including the terminating NULL byte. This is equivalent to Plan 9 * utflen() and utfnlen(). * * Results: * As above. * * Side effects: * None. * *--------------------------------------------------------------------------- */ int Tcl_NumUtfChars( register const char *src, /* The UTF-8 string to measure. */ int length) /* The length of the string in bytes, or -1 * for strlen(string). */ { Tcl_UniChar ch; register Tcl_UniChar *chPtr = &ch; register int i; /* * The separate implementations are faster. * * Since this is a time-sensitive function, we also do the check for the * single-byte char case specially. */ i = 0; if (length < 0) { while (*src != '\0') { src += TclUtfToUniChar(src, chPtr); i++; } } else { register int n; while (length > 0) { if (UCHAR(*src) < 0xC0) { length--; src++; } else { n = Tcl_UtfToUniChar(src, chPtr); length -= n; src += n; } i++; } } return i; } /* *--------------------------------------------------------------------------- * * Tcl_UtfFindFirst -- * * Returns a pointer to the first occurance of the given Tcl_UniChar in * the NULL-terminated UTF-8 string. The NULL terminator is considered * part of the UTF-8 string. Equivalent to Plan 9 utfrune(). * * Results: * As above. If the Tcl_UniChar does not exist in the given string, the * return value is NULL. * * Side effects: * None. * *--------------------------------------------------------------------------- */ const char * Tcl_UtfFindFirst( const char *src, /* The UTF-8 string to be searched. */ int ch) /* The Tcl_UniChar to search for. */ { int len; Tcl_UniChar find; while (1) { len = TclUtfToUniChar(src, &find); if (find == ch) { return src; } if (*src == '\0') { return NULL; } src += len; } } /* *--------------------------------------------------------------------------- * * Tcl_UtfFindLast -- * * Returns a pointer to the last occurance of the given Tcl_UniChar in * the NULL-terminated UTF-8 string. The NULL terminator is considered * part of the UTF-8 string. Equivalent to Plan 9 utfrrune(). * * Results: * As above. If the Tcl_UniChar does not exist in the given string, the * return value is NULL. * * Side effects: * None. * *--------------------------------------------------------------------------- */ const char * Tcl_UtfFindLast( const char *src, /* The UTF-8 string to be searched. */ int ch) /* The Tcl_UniChar to search for. */ { int len; Tcl_UniChar find; const char *last; last = NULL; while (1) { len = TclUtfToUniChar(src, &find); if (find == ch) { last = src; } if (*src == '\0') { break; } src += len; } return last; } /* *--------------------------------------------------------------------------- * * Tcl_UtfNext -- * * Given a pointer to some current location in a UTF-8 string, move * forward one character. The caller must ensure that they are not asking * for the next character after the last character in the string. * * Results: * The return value is the pointer to the next character in the UTF-8 * string. * * Side effects: * None. * *--------------------------------------------------------------------------- */ const char * Tcl_UtfNext( const char *src) /* The current location in the string. */ { Tcl_UniChar ch; return src + TclUtfToUniChar(src, &ch); } /* *--------------------------------------------------------------------------- * * Tcl_UtfPrev -- * * Given a pointer to some current location in a UTF-8 string, move * backwards one character. This works correctly when the pointer is in * the middle of a UTF-8 character. * * Results: * The return value is a pointer to the previous character in the UTF-8 * string. If the current location was already at the beginning of the * string, the return value will also be a pointer to the beginning of * the string. * * Side effects: * None. * *--------------------------------------------------------------------------- */ const char * Tcl_UtfPrev( const char *src, /* The current location in the string. */ const char *start) /* Pointer to the beginning of the string, to * avoid going backwards too far. */ { const char *look; int i, byte; src--; look = src; for (i = 0; i < TCL_UTF_MAX; i++) { if (look < start) { if (src < start) { src = start; } break; } byte = *((unsigned char *) look); if (byte < 0x80) { break; } if (byte >= 0xC0) { return look; } look--; } return src; } /* *--------------------------------------------------------------------------- * * Tcl_UniCharAtIndex -- * * Returns the Unicode character represented at the specified character * (not byte) position in the UTF-8 string. * * Results: * As above. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_UniChar Tcl_UniCharAtIndex( register const char *src, /* The UTF-8 string to dereference. */ register int index) /* The position of the desired character. */ { Tcl_UniChar ch = 0; while (index >= 0) { index--; src += TclUtfToUniChar(src, &ch); } return ch; } /* *--------------------------------------------------------------------------- * * Tcl_UtfAtIndex -- * * Returns a pointer to the specified character (not byte) position in * the UTF-8 string. * * Results: * As above. * * Side effects: * None. * *--------------------------------------------------------------------------- */ const char * Tcl_UtfAtIndex( register const char *src, /* The UTF-8 string. */ register int index) /* The position of the desired character. */ { Tcl_UniChar ch; while (index > 0) { index--; src += TclUtfToUniChar(src, &ch); } return src; } /* *--------------------------------------------------------------------------- * * Tcl_UtfBackslash -- * * Figure out how to handle a backslash sequence. * * Results: * Stores the bytes represented by the backslash sequence in dst and * returns the number of bytes written to dst. At most TCL_UTF_MAX bytes * are written to dst; dst must have been large enough to accept those * bytes. If readPtr isn't NULL then it is filled in with a count of the * number of bytes in the backslash sequence. * * Side effects: * The maximum number of bytes it takes to represent a Unicode character * in UTF-8 is guaranteed to be less than the number of bytes used to * express the backslash sequence that represents that Unicode character. * If the target buffer into which the caller is going to store the bytes * that represent the Unicode character is at least as large as the * source buffer from which the backslashed sequence was extracted, no * buffer overruns should occur. * *--------------------------------------------------------------------------- */ int Tcl_UtfBackslash( const char *src, /* Points to the backslash character of a * backslash sequence. */ int *readPtr, /* Fill in with number of characters read from * src, unless NULL. */ char *dst) /* Filled with the bytes represented by the * backslash sequence. */ { #define LINE_LENGTH 128 int numRead; int result; result = TclParseBackslash(src, LINE_LENGTH, &numRead, dst); if (numRead == LINE_LENGTH) { /* * We ate a whole line. Pay the price of a strlen() */ result = TclParseBackslash(src, (int)strlen(src), &numRead, dst); } if (readPtr != NULL) { *readPtr = numRead; } return result; } /* *---------------------------------------------------------------------- * * Tcl_UtfToUpper -- * * Convert lowercase characters to uppercase characters in a UTF string * in place. The conversion may shrink the UTF string. * * Results: * Returns the number of bytes in the resulting string excluding the * trailing null. * * Side effects: * Writes a terminating null after the last converted character. * *---------------------------------------------------------------------- */ int Tcl_UtfToUpper( char *str) /* String to convert in place. */ { Tcl_UniChar ch, upChar; char *src, *dst; int bytes; /* * Iterate over the string until we hit the terminating null. */ src = dst = str; while (*src) { bytes = TclUtfToUniChar(src, &ch); upChar = Tcl_UniCharToUpper(ch); /* * To keep badly formed Utf strings from getting inflated by the * conversion (thereby causing a segfault), only copy the upper case * char to dst if its size is <= the original char. */ if (bytes < UtfCount(upChar)) { memcpy(dst, src, (size_t) bytes); dst += bytes; } else { dst += Tcl_UniCharToUtf(upChar, dst); } src += bytes; } *dst = '\0'; return (dst - str); } /* *---------------------------------------------------------------------- * * Tcl_UtfToLower -- * * Convert uppercase characters to lowercase characters in a UTF string * in place. The conversion may shrink the UTF string. * * Results: * Returns the number of bytes in the resulting string excluding the * trailing null. * * Side effects: * Writes a terminating null after the last converted character. * *---------------------------------------------------------------------- */ int Tcl_UtfToLower( char *str) /* String to convert in place. */ { Tcl_UniChar ch, lowChar; char *src, *dst; int bytes; /* * Iterate over the string until we hit the terminating null. */ src = dst = str; while (*src) { bytes = TclUtfToUniChar(src, &ch); lowChar = Tcl_UniCharToLower(ch); /* * To keep badly formed Utf strings from getting inflated by the * conversion (thereby causing a segfault), only copy the lower case * char to dst if its size is <= the original char. */ if (bytes < UtfCount(lowChar)) { memcpy(dst, src, (size_t) bytes); dst += bytes; } else { dst += Tcl_UniCharToUtf(lowChar, dst); } src += bytes; } *dst = '\0'; return (dst - str); } /* *---------------------------------------------------------------------- * * Tcl_UtfToTitle -- * * Changes the first character of a UTF string to title case or uppercase * and the rest of the string to lowercase. The conversion happens in * place and may shrink the UTF string. * * Results: * Returns the number of bytes in the resulting string excluding the * trailing null. * * Side effects: * Writes a terminating null after the last converted character. * *---------------------------------------------------------------------- */ int Tcl_UtfToTitle( char *str) /* String to convert in place. */ { Tcl_UniChar ch, titleChar, lowChar; char *src, *dst; int bytes; /* * Capitalize the first character and then lowercase the rest of the * characters until we get to a null. */ src = dst = str; if (*src) { bytes = TclUtfToUniChar(src, &ch); titleChar = Tcl_UniCharToTitle(ch); if (bytes < UtfCount(titleChar)) { memcpy(dst, src, (size_t) bytes); dst += bytes; } else { dst += Tcl_UniCharToUtf(titleChar, dst); } src += bytes; } while (*src) { bytes = TclUtfToUniChar(src, &ch); lowChar = Tcl_UniCharToLower(ch); if (bytes < UtfCount(lowChar)) { memcpy(dst, src, (size_t) bytes); dst += bytes; } else { dst += Tcl_UniCharToUtf(lowChar, dst); } src += bytes; } *dst = '\0'; return (dst - str); } /* *---------------------------------------------------------------------- * * TclpUtfNcmp2 -- * * Compare at most numBytes bytes of utf-8 strings cs and ct. Both cs and * ct are assumed to be at least numBytes bytes long. * * Results: * Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclpUtfNcmp2( const char *cs, /* UTF string to compare to ct. */ const char *ct, /* UTF string cs is compared to. */ unsigned long numBytes) /* Number of *bytes* to compare. */ { /* * We can't simply call 'memcmp(cs, ct, numBytes);' because we need to * check for Tcl's \xC0\x80 non-utf-8 null encoding. Otherwise utf-8 lexes * fine in the strcmp manner. */ register int result = 0; for ( ; numBytes != 0; numBytes--, cs++, ct++) { if (*cs != *ct) { result = UCHAR(*cs) - UCHAR(*ct); break; } } if (numBytes && ((UCHAR(*cs) == 0xC0) || (UCHAR(*ct) == 0xC0))) { unsigned char c1, c2; c1 = ((UCHAR(*cs) == 0xC0) && (UCHAR(cs[1]) == 0x80)) ? 0 : UCHAR(*cs); c2 = ((UCHAR(*ct) == 0xC0) && (UCHAR(ct[1]) == 0x80)) ? 0 : UCHAR(*ct); result = (c1 - c2); } return result; } /* *---------------------------------------------------------------------- * * Tcl_UtfNcmp -- * * Compare at most numChars UTF chars of string cs to string ct. Both cs * and ct are assumed to be at least numChars UTF chars long. * * Results: * Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UtfNcmp( const char *cs, /* UTF string to compare to ct. */ const char *ct, /* UTF string cs is compared to. */ unsigned long numChars) /* Number of UTF chars to compare. */ { Tcl_UniChar ch1, ch2; /* * Cannot use 'memcmp(cs, ct, n);' as byte representation of \u0000 (the * pair of bytes 0xc0,0x80) is larger than byte representation of \u0001 * (the byte 0x01.) */ while (numChars-- > 0) { /* * n must be interpreted as chars, not bytes. This should be called * only when both strings are of at least n chars long (no need for \0 * check) */ cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); if (ch1 != ch2) { return (ch1 - ch2); } } return 0; } /* *---------------------------------------------------------------------- * * Tcl_UtfNcasecmp -- * * Compare at most numChars UTF chars of string cs to string ct case * insensitive. Both cs and ct are assumed to be at least numChars UTF * chars long. * * Results: * Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UtfNcasecmp( const char *cs, /* UTF string to compare to ct. */ const char *ct, /* UTF string cs is compared to. */ unsigned long numChars) /* Number of UTF chars to compare. */ { Tcl_UniChar ch1, ch2; while (numChars-- > 0) { /* * n must be interpreted as chars, not bytes. * This should be called only when both strings are of * at least n chars long (no need for \0 check) */ cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); if (ch1 != ch2) { ch1 = Tcl_UniCharToLower(ch1); ch2 = Tcl_UniCharToLower(ch2); if (ch1 != ch2) { return (ch1 - ch2); } } } return 0; } /* *---------------------------------------------------------------------- * * Tcl_UtfNcasecmp -- * * Compare UTF chars of string cs to string ct case insensitively. * Replacement for strcasecmp in Tcl core, in places where UTF-8 should * be handled. * * Results: * Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclUtfCasecmp( const char *cs, /* UTF string to compare to ct. */ const char *ct) /* UTF string cs is compared to. */ { while (*cs && *ct) { Tcl_UniChar ch1, ch2; cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); if (ch1 != ch2) { ch1 = Tcl_UniCharToLower(ch1); ch2 = Tcl_UniCharToLower(ch2); if (ch1 != ch2) { return ch1 - ch2; } } } return UCHAR(*cs) - UCHAR(*ct); } /* *---------------------------------------------------------------------- * * Tcl_UniCharToUpper -- * * Compute the uppercase equivalent of the given Unicode character. * * Results: * Returns the uppercase Unicode character. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_UniChar Tcl_UniCharToUpper( int ch) /* Unicode character to convert. */ { int info = GetUniCharInfo(ch); if (GetCaseType(info) & 0x04) { ch -= GetDelta(info); } return (Tcl_UniChar) ch; } /* *---------------------------------------------------------------------- * * Tcl_UniCharToLower -- * * Compute the lowercase equivalent of the given Unicode character. * * Results: * Returns the lowercase Unicode character. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_UniChar Tcl_UniCharToLower( int ch) /* Unicode character to convert. */ { int info = GetUniCharInfo(ch); if (GetCaseType(info) & 0x02) { ch += GetDelta(info); } return (Tcl_UniChar) ch; } /* *---------------------------------------------------------------------- * * Tcl_UniCharToTitle -- * * Compute the titlecase equivalent of the given Unicode character. * * Results: * Returns the titlecase Unicode character. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_UniChar Tcl_UniCharToTitle( int ch) /* Unicode character to convert. */ { int info = GetUniCharInfo(ch); int mode = GetCaseType(info); if (mode & 0x1) { /* * Subtract or add one depending on the original case. */ ch += ((mode & 0x4) ? -1 : 1); } else if (mode == 0x4) { ch -= GetDelta(info); } return (Tcl_UniChar) ch; } /* *---------------------------------------------------------------------- * * Tcl_UniCharLen -- * * Find the length of a UniChar string. The str input must be null * terminated. * * Results: * Returns the length of str in UniChars (not bytes). * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharLen( const Tcl_UniChar *uniStr) /* Unicode string to find length of. */ { int len = 0; while (*uniStr != '\0') { len++; uniStr++; } return len; } /* *---------------------------------------------------------------------- * * Tcl_UniCharNcmp -- * * Compare at most numChars unichars of string ucs to string uct. * Both ucs and uct are assumed to be at least numChars unichars long. * * Results: * Return <0 if ucs < uct, 0 if ucs == uct, or >0 if ucs > uct. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharNcmp( const Tcl_UniChar *ucs, /* Unicode string to compare to uct. */ const Tcl_UniChar *uct, /* Unicode string ucs is compared to. */ unsigned long numChars) /* Number of unichars to compare. */ { #ifdef WORDS_BIGENDIAN /* * We are definitely on a big-endian machine; memcmp() is safe */ return memcmp(ucs, uct, numChars*sizeof(Tcl_UniChar)); #else /* !WORDS_BIGENDIAN */ /* * We can't simply call memcmp() because that is not lexically correct. */ for ( ; numChars != 0; ucs++, uct++, numChars--) { if (*ucs != *uct) { return (*ucs - *uct); } } return 0; #endif /* WORDS_BIGENDIAN */ } /* *---------------------------------------------------------------------- * * Tcl_UniCharNcasecmp -- * * Compare at most numChars unichars of string ucs to string uct case * insensitive. Both ucs and uct are assumed to be at least numChars * unichars long. * * Results: * Return <0 if ucs < uct, 0 if ucs == uct, or >0 if ucs > uct. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharNcasecmp( const Tcl_UniChar *ucs, /* Unicode string to compare to uct. */ const Tcl_UniChar *uct, /* Unicode string ucs is compared to. */ unsigned long numChars) /* Number of unichars to compare. */ { for ( ; numChars != 0; numChars--, ucs++, uct++) { if (*ucs != *uct) { Tcl_UniChar lcs = Tcl_UniCharToLower(*ucs); Tcl_UniChar lct = Tcl_UniCharToLower(*uct); if (lcs != lct) { return (lcs - lct); } } } return 0; } /* *---------------------------------------------------------------------- * * Tcl_UniCharIsAlnum -- * * Test if a character is an alphanumeric Unicode character. * * Results: * Returns 1 if character is alphanumeric. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharIsAlnum( int ch) /* Unicode character to test. */ { #if TCL_UTF_MAX > 3 if (UNICODE_OUT_OF_RANGE(ch)) { return 0; } #endif return (((ALPHA_BITS | DIGIT_BITS) >> GetCategory(ch)) & 1); } /* *---------------------------------------------------------------------- * * Tcl_UniCharIsAlpha -- * * Test if a character is an alphabetic Unicode character. * * Results: * Returns 1 if character is alphabetic. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharIsAlpha( int ch) /* Unicode character to test. */ { #if TCL_UTF_MAX > 3 if (UNICODE_OUT_OF_RANGE(ch)) { return 0; } #endif return ((ALPHA_BITS >> GetCategory(ch)) & 1); } /* *---------------------------------------------------------------------- * * Tcl_UniCharIsControl -- * * Test if a character is a Unicode control character. * * Results: * Returns non-zero if character is a control. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharIsControl( int ch) /* Unicode character to test. */ { #if TCL_UTF_MAX > 3 if (UNICODE_OUT_OF_RANGE(ch)) { ch &= 0x1fffff; if ((ch == 0xe0001) || ((ch >= 0xe0020) && (ch <= 0xe007f))) { return 1; } if ((ch >= 0xf0000) && ((ch & 0xffff) <= 0xfffd)) { return 1; } return 0; } #endif return ((CONTROL_BITS >> GetCategory(ch)) & 1); } /* *---------------------------------------------------------------------- * * Tcl_UniCharIsDigit -- * * Test if a character is a numeric Unicode character. * * Results: * Returns non-zero if character is a digit. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharIsDigit( int ch) /* Unicode character to test. */ { #if TCL_UTF_MAX > 3 if (UNICODE_OUT_OF_RANGE(ch)) { return 0; } #endif return (GetCategory(ch) == DECIMAL_DIGIT_NUMBER); } /* *---------------------------------------------------------------------- * * Tcl_UniCharIsGraph -- * * Test if a character is any Unicode print character except space. * * Results: * Returns non-zero if character is printable, but not space. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharIsGraph( int ch) /* Unicode character to test. */ { #if TCL_UTF_MAX > 3 if (UNICODE_OUT_OF_RANGE(ch)) { ch &= 0x1fffff; return (ch >= 0xe0100) && (ch <= 0xe01ef); } #endif return ((GRAPH_BITS >> GetCategory(ch)) & 1); } /* *---------------------------------------------------------------------- * * Tcl_UniCharIsLower -- * * Test if a character is a lowercase Unicode character. * * Results: * Returns non-zero if character is lowercase. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharIsLower( int ch) /* Unicode character to test. */ { #if TCL_UTF_MAX > 3 if (UNICODE_OUT_OF_RANGE(ch)) { return 0; } #endif return (GetCategory(ch) == LOWERCASE_LETTER); } /* *---------------------------------------------------------------------- * * Tcl_UniCharIsPrint -- * * Test if a character is a Unicode print character. * * Results: * Returns non-zero if character is printable. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharIsPrint( int ch) /* Unicode character to test. */ { #if TCL_UTF_MAX > 3 if (UNICODE_OUT_OF_RANGE(ch)) { ch &= 0x1fffff; return (ch >= 0xe0100) && (ch <= 0xe01ef); } #endif return (((GRAPH_BITS|SPACE_BITS) >> GetCategory(ch)) & 1); } /* *---------------------------------------------------------------------- * * Tcl_UniCharIsPunct -- * * Test if a character is a Unicode punctuation character. * * Results: * Returns non-zero if character is punct. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharIsPunct( int ch) /* Unicode character to test. */ { #if TCL_UTF_MAX > 3 if (UNICODE_OUT_OF_RANGE(ch)) { return 0; } #endif return ((PUNCT_BITS >> GetCategory(ch)) & 1); } /* *---------------------------------------------------------------------- * * Tcl_UniCharIsSpace -- * * Test if a character is a whitespace Unicode character. * * Results: * Returns non-zero if character is a space. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharIsSpace( int ch) /* Unicode character to test. */ { #if TCL_UTF_MAX > 3 /* Ignore upper 11 bits. */ ch &= 0x1fffff; #else /* Ignore upper 16 bits. */ ch &= 0xffff; #endif /* * If the character is within the first 127 characters, just use the * standard C function, otherwise consult the Unicode table. */ if (ch < 0x80) { return TclIsSpaceProc((char) ch); #if TCL_UTF_MAX > 3 } else if (UNICODE_OUT_OF_RANGE(ch)) { return 0; #endif } else if (ch == 0x0085 || ch == 0x180e || ch == 0x200b || ch == 0x202f || ch == 0x2060 || ch == 0xfeff) { return 1; } else { return ((SPACE_BITS >> GetCategory(ch)) & 1); } } /* *---------------------------------------------------------------------- * * Tcl_UniCharIsUpper -- * * Test if a character is a uppercase Unicode character. * * Results: * Returns non-zero if character is uppercase. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharIsUpper( int ch) /* Unicode character to test. */ { #if TCL_UTF_MAX > 3 if (UNICODE_OUT_OF_RANGE(ch)) { return 0; } #endif return (GetCategory(ch) == UPPERCASE_LETTER); } /* *---------------------------------------------------------------------- * * Tcl_UniCharIsWordChar -- * * Test if a character is alphanumeric or a connector punctuation mark. * * Results: * Returns 1 if character is a word character. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharIsWordChar( int ch) /* Unicode character to test. */ { #if TCL_UTF_MAX > 3 if (UNICODE_OUT_OF_RANGE(ch)) { return 0; } #endif return ((WORD_BITS >> GetCategory(ch)) & 1); } /* *---------------------------------------------------------------------- * * Tcl_UniCharCaseMatch -- * * See if a particular Unicode string matches a particular pattern. * Allows case insensitivity. This is the Unicode equivalent of the char* * Tcl_StringCaseMatch. The UniChar strings must be NULL-terminated. * This has no provision for counted UniChar strings, thus should not be * used where NULLs are expected in the UniChar string. Use * TclUniCharMatch where possible. * * Results: * The return value is 1 if string matches pattern, and 0 otherwise. The * matching operation permits the following special characters in the * pattern: *?\[] (see the manual entry for details on what these mean). * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_UniCharCaseMatch( const Tcl_UniChar *uniStr, /* Unicode String. */ const Tcl_UniChar *uniPattern, /* Pattern, which may contain special * characters. */ int nocase) /* 0 for case sensitive, 1 for insensitive */ { Tcl_UniChar ch1, p; while (1) { p = *uniPattern; /* * See if we're at the end of both the pattern and the string. If so, * we succeeded. If we're at the end of the pattern but not at the end * of the string, we failed. */ if (p == 0) { return (*uniStr == 0); } if ((*uniStr == 0) && (p != '*')) { return 0; } /* * Check for a "*" as the next pattern character. It matches any * substring. We handle this by skipping all the characters up to the * next matching one in the pattern, and then calling ourselves * recursively for each postfix of string, until either we match or we * reach the end of the string. */ if (p == '*') { /* * Skip all successive *'s in the pattern */ while (*(++uniPattern) == '*') { /* empty body */ } p = *uniPattern; if (p == 0) { return 1; } if (nocase) { p = Tcl_UniCharToLower(p); } while (1) { /* * Optimization for matching - cruise through the string * quickly if the next char in the pattern isn't a special * character */ if ((p != '[') && (p != '?') && (p != '\\')) { if (nocase) { while (*uniStr && (p != *uniStr) && (p != Tcl_UniCharToLower(*uniStr))) { uniStr++; } } else { while (*uniStr && (p != *uniStr)) { uniStr++; } } } if (Tcl_UniCharCaseMatch(uniStr, uniPattern, nocase)) { return 1; } if (*uniStr == 0) { return 0; } uniStr++; } } /* * Check for a "?" as the next pattern character. It matches any * single character. */ if (p == '?') { uniPattern++; uniStr++; continue; } /* * Check for a "[" as the next pattern character. It is followed by a * list of characters that are acceptable, or by a range (two * characters separated by "-"). */ if (p == '[') { Tcl_UniChar startChar, endChar; uniPattern++; ch1 = (nocase ? Tcl_UniCharToLower(*uniStr) : *uniStr); uniStr++; while (1) { if ((*uniPattern == ']') || (*uniPattern == 0)) { return 0; } startChar = (nocase ? Tcl_UniCharToLower(*uniPattern) : *uniPattern); uniPattern++; if (*uniPattern == '-') { uniPattern++; if (*uniPattern == 0) { return 0; } endChar = (nocase ? Tcl_UniCharToLower(*uniPattern) : *uniPattern); uniPattern++; if (((startChar <= ch1) && (ch1 <= endChar)) || ((endChar <= ch1) && (ch1 <= startChar))) { /* * Matches ranges of form [a-z] or [z-a]. */ break; } } else if (startChar == ch1) { break; } } while (*uniPattern != ']') { if (*uniPattern == 0) { uniPattern--; break; } uniPattern++; } uniPattern++; continue; } /* * If the next pattern character is '\', just strip off the '\' so we * do exact matching on the character that follows. */ if (p == '\\') { if (*(++uniPattern) == '\0') { return 0; } } /* * There's no special character. Just make sure that the next bytes of * each string match. */ if (nocase) { if (Tcl_UniCharToLower(*uniStr) != Tcl_UniCharToLower(*uniPattern)) { return 0; } } else if (*uniStr != *uniPattern) { return 0; } uniStr++; uniPattern++; } } /* *---------------------------------------------------------------------- * * TclUniCharMatch -- * * See if a particular Unicode string matches a particular pattern. * Allows case insensitivity. This is the Unicode equivalent of the char* * Tcl_StringCaseMatch. This variant of Tcl_UniCharCaseMatch uses counted * Strings, so embedded NULLs are allowed. * * Results: * The return value is 1 if string matches pattern, and 0 otherwise. The * matching operation permits the following special characters in the * pattern: *?\[] (see the manual entry for details on what these mean). * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclUniCharMatch( const Tcl_UniChar *string, /* Unicode String. */ int strLen, /* Length of String */ const Tcl_UniChar *pattern, /* Pattern, which may contain special * characters. */ int ptnLen, /* Length of Pattern */ int nocase) /* 0 for case sensitive, 1 for insensitive */ { const Tcl_UniChar *stringEnd, *patternEnd; Tcl_UniChar p; stringEnd = string + strLen; patternEnd = pattern + ptnLen; while (1) { /* * See if we're at the end of both the pattern and the string. If so, * we succeeded. If we're at the end of the pattern but not at the end * of the string, we failed. */ if (pattern == patternEnd) { return (string == stringEnd); } p = *pattern; if ((string == stringEnd) && (p != '*')) { return 0; } /* * Check for a "*" as the next pattern character. It matches any * substring. We handle this by skipping all the characters up to the * next matching one in the pattern, and then calling ourselves * recursively for each postfix of string, until either we match or we * reach the end of the string. */ if (p == '*') { /* * Skip all successive *'s in the pattern. */ while (*(++pattern) == '*') { /* empty body */ } if (pattern == patternEnd) { return 1; } p = *pattern; if (nocase) { p = Tcl_UniCharToLower(p); } while (1) { /* * Optimization for matching - cruise through the string * quickly if the next char in the pattern isn't a special * character. */ if ((p != '[') && (p != '?') && (p != '\\')) { if (nocase) { while ((string < stringEnd) && (p != *string) && (p != Tcl_UniCharToLower(*string))) { string++; } } else { while ((string < stringEnd) && (p != *string)) { string++; } } } if (TclUniCharMatch(string, stringEnd - string, pattern, patternEnd - pattern, nocase)) { return 1; } if (string == stringEnd) { return 0; } string++; } } /* * Check for a "?" as the next pattern character. It matches any * single character. */ if (p == '?') { pattern++; string++; continue; } /* * Check for a "[" as the next pattern character. It is followed by a * list of characters that are acceptable, or by a range (two * characters separated by "-"). */ if (p == '[') { Tcl_UniChar ch1, startChar, endChar; pattern++; ch1 = (nocase ? Tcl_UniCharToLower(*string) : *string); string++; while (1) { if ((*pattern == ']') || (pattern == patternEnd)) { return 0; } startChar = (nocase ? Tcl_UniCharToLower(*pattern) : *pattern); pattern++; if (*pattern == '-') { pattern++; if (pattern == patternEnd) { return 0; } endChar = (nocase ? Tcl_UniCharToLower(*pattern) : *pattern); pattern++; if (((startChar <= ch1) && (ch1 <= endChar)) || ((endChar <= ch1) && (ch1 <= startChar))) { /* * Matches ranges of form [a-z] or [z-a]. */ break; } } else if (startChar == ch1) { break; } } while (*pattern != ']') { if (pattern == patternEnd) { pattern--; break; } pattern++; } pattern++; continue; } /* * If the next pattern character is '\', just strip off the '\' so we * do exact matching on the character that follows. */ if (p == '\\') { if (++pattern == patternEnd) { return 0; } } /* * There's no special character. Just make sure that the next bytes of * each string match. */ if (nocase) { if (Tcl_UniCharToLower(*string) != Tcl_UniCharToLower(*pattern)) { return 0; } } else if (*string != *pattern) { return 0; } string++; pattern++; } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclCompCmds.c0000644000175000017500000030521712663670157015572 0ustar sergeisergei/* * tclCompCmds.c -- * * This file contains compilation procedures that compile various Tcl * commands into a sequence of instructions ("bytecodes"). * * Copyright (c) 1997-1998 Sun Microsystems, Inc. * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2002 ActiveState Corporation. * Copyright (c) 2004-2013 by Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" #include /* * Prototypes for procedures defined later in this file: */ static ClientData DupDictUpdateInfo(ClientData clientData); static void FreeDictUpdateInfo(ClientData clientData); static void PrintDictUpdateInfo(ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); static void DisassembleDictUpdateInfo(ClientData clientData, Tcl_Obj *dictObj, ByteCode *codePtr, unsigned int pcOffset); static ClientData DupForeachInfo(ClientData clientData); static void FreeForeachInfo(ClientData clientData); static void PrintForeachInfo(ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); static void DisassembleForeachInfo(ClientData clientData, Tcl_Obj *dictObj, ByteCode *codePtr, unsigned int pcOffset); static void PrintNewForeachInfo(ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); static void DisassembleNewForeachInfo(ClientData clientData, Tcl_Obj *dictObj, ByteCode *codePtr, unsigned int pcOffset); static int CompileEachloopCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, CompileEnv *envPtr, int collect); static int CompileDictEachCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr, int collect); /* * The structures below define the AuxData types defined in this file. */ static const AuxDataType foreachInfoType = { "ForeachInfo", /* name */ DupForeachInfo, /* dupProc */ FreeForeachInfo, /* freeProc */ PrintForeachInfo, /* printProc */ DisassembleForeachInfo /* disassembleProc */ }; static const AuxDataType newForeachInfoType = { "NewForeachInfo", /* name */ DupForeachInfo, /* dupProc */ FreeForeachInfo, /* freeProc */ PrintNewForeachInfo, /* printProc */ DisassembleNewForeachInfo /* disassembleProc */ }; static const AuxDataType dictUpdateInfoType = { "DictUpdateInfo", /* name */ DupDictUpdateInfo, /* dupProc */ FreeDictUpdateInfo, /* freeProc */ PrintDictUpdateInfo, /* printProc */ DisassembleDictUpdateInfo /* disassembleProc */ }; /* *---------------------------------------------------------------------- * * TclGetAuxDataType -- * * This procedure looks up an Auxdata type by name. * * Results: * If an AuxData type with name matching "typeName" is found, a pointer * to its AuxDataType structure is returned; otherwise, NULL is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ const AuxDataType * TclGetAuxDataType( const char *typeName) /* Name of AuxData type to look up. */ { if (!strcmp(typeName, foreachInfoType.name)) { return &foreachInfoType; } else if (!strcmp(typeName, newForeachInfoType.name)) { return &newForeachInfoType; } else if (!strcmp(typeName, dictUpdateInfoType.name)) { return &dictUpdateInfoType; } else if (!strcmp(typeName, tclJumptableInfoType.name)) { return &tclJumptableInfoType; } return NULL; } /* *---------------------------------------------------------------------- * * TclCompileAppendCmd -- * * Procedure called to compile the "append" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "append" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileAppendCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *varTokenPtr, *valueTokenPtr; int isScalar, localIndex, numWords, i; DefineLineInformation; /* TIP #280 */ /* TODO: Consider support for compiling expanded args. */ numWords = parsePtr->numWords; if (numWords == 1) { return TCL_ERROR; } else if (numWords == 2) { /* * append varName == set varName */ return TclCompileSetCmd(interp, parsePtr, cmdPtr, envPtr); } else if (numWords > 3) { /* * APPEND instructions currently only handle one value, but we can * handle some multi-value cases by stringing them together. */ goto appendMultiple; } /* * Decide if we can use a frame slot for the var/array name or if we need * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarNameWord(interp, varTokenPtr, envPtr, 0, &localIndex, &isScalar, 1); /* * We are doing an assignment, otherwise TclCompileSetCmd was called, so * push the new value. This will need to be extended to push a value for * each argument. */ valueTokenPtr = TokenAfter(varTokenPtr); CompileWord(envPtr, valueTokenPtr, interp, 2); /* * Emit instructions to set/get the variable. */ if (isScalar) { if (localIndex < 0) { TclEmitOpcode(INST_APPEND_STK, envPtr); } else { Emit14Inst(INST_APPEND_SCALAR, localIndex, envPtr); } } else { if (localIndex < 0) { TclEmitOpcode(INST_APPEND_ARRAY_STK, envPtr); } else { Emit14Inst(INST_APPEND_ARRAY, localIndex, envPtr); } } return TCL_OK; appendMultiple: /* * Can only handle the case where we are appending to a local scalar when * there are multiple values to append. Fortunately, this is common. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); localIndex = LocalScalarFromToken(varTokenPtr, envPtr); if (localIndex < 0) { return TCL_ERROR; } /* * Definitely appending to a local scalar; generate the words and append * them. */ valueTokenPtr = TokenAfter(varTokenPtr); for (i = 2 ; i < numWords ; i++) { CompileWord(envPtr, valueTokenPtr, interp, i); valueTokenPtr = TokenAfter(valueTokenPtr); } TclEmitInstInt4( INST_REVERSE, numWords-2, envPtr); for (i = 2 ; i < numWords ;) { Emit14Inst( INST_APPEND_SCALAR, localIndex, envPtr); if (++i < numWords) { TclEmitOpcode(INST_POP, envPtr); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileArray*Cmd -- * * Functions called to compile "array" sucommands. * * Results: * All return TCL_OK for a successful compile, and TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "array" subcommand at * runtime. * *---------------------------------------------------------------------- */ int TclCompileArrayExistsCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; int isScalar, localIndex; if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarNameWord(interp, tokenPtr, envPtr, TCL_NO_ELEMENT, &localIndex, &isScalar, 1); if (!isScalar) { return TCL_ERROR; } if (localIndex >= 0) { TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr); } else { TclEmitOpcode( INST_ARRAY_EXISTS_STK, envPtr); } return TCL_OK; } int TclCompileArraySetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varTokenPtr, *dataTokenPtr; int isScalar, localIndex, code = TCL_OK; int isDataLiteral, isDataValid, isDataEven, len; int keyVar, valVar, infoIndex; int fwd, offsetBack, offsetFwd; Tcl_Obj *literalObj; ForeachInfo *infoPtr; if (parsePtr->numWords != 3) { return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); dataTokenPtr = TokenAfter(varTokenPtr); literalObj = Tcl_NewObj(); isDataLiteral = TclWordKnownAtCompileTime(dataTokenPtr, literalObj); isDataValid = (isDataLiteral && Tcl_ListObjLength(NULL, literalObj, &len) == TCL_OK); isDataEven = (isDataValid && (len & 1) == 0); /* * Special case: literal odd-length argument is always an error. */ if (isDataValid && !isDataEven) { PushStringLiteral(envPtr, "list must have an even number of elements"); PushStringLiteral(envPtr, "-errorcode {TCL ARGUMENT FORMAT}"); TclEmitInstInt4(INST_RETURN_IMM, TCL_ERROR, envPtr); TclEmitInt4( 0, envPtr); goto done; } /* * Except for the special "ensure array" case below, when we're not in * a proc, we cannot do a better compile than generic. */ if ((varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) || (envPtr->procPtr == NULL && !(isDataEven && len == 0))) { code = TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr); goto done; } PushVarNameWord(interp, varTokenPtr, envPtr, TCL_NO_ELEMENT, &localIndex, &isScalar, 1); if (!isScalar) { code = TCL_ERROR; goto done; } /* * Special case: literal empty value argument is just an "ensure array" * operation. */ if (isDataEven && len == 0) { if (localIndex >= 0) { TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr); TclEmitInstInt1(INST_JUMP_TRUE1, 7, envPtr); TclEmitInstInt4(INST_ARRAY_MAKE_IMM, localIndex, envPtr); } else { TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_ARRAY_EXISTS_STK, envPtr); TclEmitInstInt1(INST_JUMP_TRUE1, 5, envPtr); TclEmitOpcode( INST_ARRAY_MAKE_STK, envPtr); TclEmitInstInt1(INST_JUMP1, 3, envPtr); /* Each branch decrements stack depth, but we only take one. */ TclAdjustStackDepth(1, envPtr); TclEmitOpcode( INST_POP, envPtr); } PushStringLiteral(envPtr, ""); goto done; } if (localIndex < 0) { /* * a non-local variable: upvar from a local one! This consumes the * variable name that was left at stacktop. */ localIndex = TclFindCompiledLocal(varTokenPtr->start, varTokenPtr->size, 1, envPtr); PushStringLiteral(envPtr, "0"); TclEmitInstInt4(INST_REVERSE, 2, envPtr); TclEmitInstInt4(INST_UPVAR, localIndex, envPtr); TclEmitOpcode(INST_POP, envPtr); } /* * Prepare for the internal foreach. */ keyVar = AnonymousLocal(envPtr); valVar = AnonymousLocal(envPtr); infoPtr = ckalloc(sizeof(ForeachInfo)); infoPtr->numLists = 1; infoPtr->varLists[0] = ckalloc(sizeof(ForeachVarList) + sizeof(int)); infoPtr->varLists[0]->numVars = 2; infoPtr->varLists[0]->varIndexes[0] = keyVar; infoPtr->varLists[0]->varIndexes[1] = valVar; infoIndex = TclCreateAuxData(infoPtr, &newForeachInfoType, envPtr); /* * Start issuing instructions to write to the array. */ CompileWord(envPtr, dataTokenPtr, interp, 2); if (!isDataLiteral || !isDataValid) { /* * Only need this safety check if we're handling a non-literal or list * containing an invalid literal; with valid list literals, we've * already checked (worth it because literals are a very common * use-case with [array set]). */ TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_LIST_LENGTH, envPtr); PushStringLiteral(envPtr, "1"); TclEmitOpcode( INST_BITAND, envPtr); offsetFwd = CurrentOffset(envPtr); TclEmitInstInt1(INST_JUMP_FALSE1, 0, envPtr); PushStringLiteral(envPtr, "list must have an even number of elements"); PushStringLiteral(envPtr, "-errorcode {TCL ARGUMENT FORMAT}"); TclEmitInstInt4(INST_RETURN_IMM, TCL_ERROR, envPtr); TclEmitInt4( 0, envPtr); TclAdjustStackDepth(-1, envPtr); fwd = CurrentOffset(envPtr) - offsetFwd; TclStoreInt1AtPtr(fwd, envPtr->codeStart+offsetFwd+1); } TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr); TclEmitInstInt1(INST_JUMP_TRUE1, 7, envPtr); TclEmitInstInt4(INST_ARRAY_MAKE_IMM, localIndex, envPtr); TclEmitInstInt4(INST_FOREACH_START, infoIndex, envPtr); offsetBack = CurrentOffset(envPtr); Emit14Inst( INST_LOAD_SCALAR, keyVar, envPtr); Emit14Inst( INST_LOAD_SCALAR, valVar, envPtr); Emit14Inst( INST_STORE_ARRAY, localIndex, envPtr); TclEmitOpcode( INST_POP, envPtr); infoPtr->loopCtTemp = offsetBack - CurrentOffset(envPtr); /*misuse */ TclEmitOpcode( INST_FOREACH_STEP, envPtr); TclEmitOpcode( INST_FOREACH_END, envPtr); TclAdjustStackDepth(-3, envPtr); PushStringLiteral(envPtr, ""); done: Tcl_DecrRefCount(literalObj); return code; } int TclCompileArrayUnsetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); int isScalar, localIndex; if (parsePtr->numWords != 2) { return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } PushVarNameWord(interp, tokenPtr, envPtr, TCL_NO_ELEMENT, &localIndex, &isScalar, 1); if (!isScalar) { return TCL_ERROR; } if (localIndex >= 0) { TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr); TclEmitInstInt1(INST_JUMP_FALSE1, 8, envPtr); TclEmitInstInt1(INST_UNSET_SCALAR, 1, envPtr); TclEmitInt4( localIndex, envPtr); } else { TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_ARRAY_EXISTS_STK, envPtr); TclEmitInstInt1(INST_JUMP_FALSE1, 6, envPtr); TclEmitInstInt1(INST_UNSET_STK, 1, envPtr); TclEmitInstInt1(INST_JUMP1, 3, envPtr); /* Each branch decrements stack depth, but we only take one. */ TclAdjustStackDepth(1, envPtr); TclEmitOpcode( INST_POP, envPtr); } PushStringLiteral(envPtr, ""); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileBreakCmd -- * * Procedure called to compile the "break" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "break" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileBreakCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { ExceptionRange *rangePtr; ExceptionAux *auxPtr; if (parsePtr->numWords != 1) { return TCL_ERROR; } /* * Find the innermost exception range that contains this command. */ rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_BREAK, &auxPtr); if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) { /* * Found the target! No need for a nasty INST_BREAK here. */ TclCleanupStackForBreakContinue(envPtr, auxPtr); TclAddLoopBreakFixup(envPtr, auxPtr); } else { /* * Emit a real break. */ TclEmitOpcode(INST_BREAK, envPtr); } TclAdjustStackDepth(1, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileCatchCmd -- * * Procedure called to compile the "catch" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "catch" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileCatchCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { JumpFixup jumpFixup; Tcl_Token *cmdTokenPtr, *resultNameTokenPtr, *optsNameTokenPtr; int resultIndex, optsIndex, range, dropScript = 0; DefineLineInformation; /* TIP #280 */ int depth = TclGetStackDepth(envPtr); /* * If syntax does not match what we expect for [catch], do not compile. * Let runtime checks determine if syntax has changed. */ if ((parsePtr->numWords < 2) || (parsePtr->numWords > 4)) { return TCL_ERROR; } /* * If variables were specified and the catch command is at global level * (not in a procedure), don't compile it inline: the payoff is too small. */ if ((parsePtr->numWords >= 3) && !EnvHasLVT(envPtr)) { return TCL_ERROR; } /* * Make sure the variable names, if any, have no substitutions and just * refer to local scalars. */ resultIndex = optsIndex = -1; cmdTokenPtr = TokenAfter(parsePtr->tokenPtr); if (parsePtr->numWords >= 3) { resultNameTokenPtr = TokenAfter(cmdTokenPtr); /* DGP */ resultIndex = LocalScalarFromToken(resultNameTokenPtr, envPtr); if (resultIndex < 0) { return TCL_ERROR; } /* DKF */ if (parsePtr->numWords == 4) { optsNameTokenPtr = TokenAfter(resultNameTokenPtr); optsIndex = LocalScalarFromToken(optsNameTokenPtr, envPtr); if (optsIndex < 0) { return TCL_ERROR; } } } /* * We will compile the catch command. Declare the exception range that it * uses. * * If the body is a simple word, compile a BEGIN_CATCH instruction, * followed by the instructions to eval the body. * Otherwise, compile instructions to substitute the body text before * starting the catch, then BEGIN_CATCH, and then EVAL_STK to evaluate the * substituted body. * Care has to be taken to make sure that substitution happens outside the * catch range so that errors in the substitution are not caught. * [Bug 219184] * The reason for duplicating the script is that EVAL_STK would otherwise * begin by undeflowing the stack below the mark set by BEGIN_CATCH4. */ range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); if (cmdTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { TclEmitInstInt4( INST_BEGIN_CATCH4, range, envPtr); ExceptionRangeStarts(envPtr, range); BODY(cmdTokenPtr, 1); } else { SetLineInformation(1); CompileTokens(envPtr, cmdTokenPtr, interp); TclEmitInstInt4( INST_BEGIN_CATCH4, range, envPtr); ExceptionRangeStarts(envPtr, range); TclEmitOpcode( INST_DUP, envPtr); TclEmitInvoke(envPtr, INST_EVAL_STK); /* drop the script */ dropScript = 1; TclEmitInstInt4( INST_REVERSE, 2, envPtr); TclEmitOpcode( INST_POP, envPtr); } ExceptionRangeEnds(envPtr, range); /* * Emit the "no errors" epilogue: push "0" (TCL_OK) as the catch result, * and jump around the "error case" code. */ TclCheckStackDepth(depth+1, envPtr); PushStringLiteral(envPtr, "0"); TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); /* * Emit the "error case" epilogue. Push the interpreter result and the * return code. */ ExceptionRangeTarget(envPtr, range, catchOffset); TclSetStackDepth(depth + dropScript, envPtr); if (dropScript) { TclEmitOpcode( INST_POP, envPtr); } /* Stack at this point is empty */ TclEmitOpcode( INST_PUSH_RESULT, envPtr); TclEmitOpcode( INST_PUSH_RETURN_CODE, envPtr); /* Stack at this point on both branches: result returnCode */ if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) { Tcl_Panic("TclCompileCatchCmd: bad jump distance %d", (int)(CurrentOffset(envPtr) - jumpFixup.codeOffset)); } /* * Push the return options if the caller wants them. This needs to happen * before INST_END_CATCH */ if (optsIndex != -1) { TclEmitOpcode( INST_PUSH_RETURN_OPTIONS, envPtr); } /* * End the catch */ TclEmitOpcode( INST_END_CATCH, envPtr); /* * Save the result and return options if the caller wants them. This needs * to happen after INST_END_CATCH (compile-3.6/7). */ if (optsIndex != -1) { Emit14Inst( INST_STORE_SCALAR, optsIndex, envPtr); TclEmitOpcode( INST_POP, envPtr); } /* * At this point, the top of the stack is inconveniently ordered: * result returnCode * Reverse the stack to store the result. */ TclEmitInstInt4( INST_REVERSE, 2, envPtr); if (resultIndex != -1) { Emit14Inst( INST_STORE_SCALAR, resultIndex, envPtr); } TclEmitOpcode( INST_POP, envPtr); TclCheckStackDepth(depth+1, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileConcatCmd -- * * Procedure called to compile the "concat" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "concat" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileConcatCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Obj *objPtr, *listObj; Tcl_Token *tokenPtr; int i; /* TODO: Consider compiling expansion case. */ if (parsePtr->numWords == 1) { /* * [concat] without arguments just pushes an empty object. */ PushStringLiteral(envPtr, ""); return TCL_OK; } /* * Test if all arguments are compile-time known. If they are, we can * implement with a simple push. */ listObj = Tcl_NewObj(); for (i = 1, tokenPtr = parsePtr->tokenPtr; i < parsePtr->numWords; i++) { tokenPtr = TokenAfter(tokenPtr); objPtr = Tcl_NewObj(); if (!TclWordKnownAtCompileTime(tokenPtr, objPtr)) { Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(listObj); listObj = NULL; break; } (void) Tcl_ListObjAppendElement(NULL, listObj, objPtr); } if (listObj != NULL) { Tcl_Obj **objs; const char *bytes; int len; Tcl_ListObjGetElements(NULL, listObj, &len, &objs); objPtr = Tcl_ConcatObj(len, objs); Tcl_DecrRefCount(listObj); bytes = Tcl_GetStringFromObj(objPtr, &len); PushLiteral(envPtr, bytes, len); Tcl_DecrRefCount(objPtr); return TCL_OK; } /* * General case: runtime concat. */ for (i = 1, tokenPtr = parsePtr->tokenPtr; i < parsePtr->numWords; i++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i); } TclEmitInstInt4( INST_CONCAT_STK, i-1, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileContinueCmd -- * * Procedure called to compile the "continue" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "continue" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileContinueCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { ExceptionRange *rangePtr; ExceptionAux *auxPtr; /* * There should be no argument after the "continue". */ if (parsePtr->numWords != 1) { return TCL_ERROR; } /* * See if we can find a valid continueOffset (i.e., not -1) in the * innermost containing exception range. */ rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_CONTINUE, &auxPtr); if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) { /* * Found the target! No need for a nasty INST_CONTINUE here. */ TclCleanupStackForBreakContinue(envPtr, auxPtr); TclAddLoopContinueFixup(envPtr, auxPtr); } else { /* * Emit a real continue. */ TclEmitOpcode(INST_CONTINUE, envPtr); } TclAdjustStackDepth(1, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileDict*Cmd -- * * Functions called to compile "dict" sucommands. * * Results: * All return TCL_OK for a successful compile, and TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "dict" subcommand at * runtime. * *---------------------------------------------------------------------- */ int TclCompileDictSetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; int i, dictVarIndex; DefineLineInformation; /* TIP #280 */ Tcl_Token *varTokenPtr; /* * There must be at least one argument after the command. */ if (parsePtr->numWords < 4) { return TCL_ERROR; } /* * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); dictVarIndex = LocalScalarFromToken(varTokenPtr, envPtr); if (dictVarIndex < 0) { return TCL_ERROR; } /* * Remaining words (key path and value to set) can be handled normally. */ tokenPtr = TokenAfter(varTokenPtr); for (i=2 ; i< parsePtr->numWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } /* * Now emit the instruction to do the dict manipulation. */ TclEmitInstInt4( INST_DICT_SET, parsePtr->numWords-3, envPtr); TclEmitInt4( dictVarIndex, envPtr); TclAdjustStackDepth(-1, envPtr); return TCL_OK; } int TclCompileDictIncrCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varTokenPtr, *keyTokenPtr; int dictVarIndex, incrAmount; /* * There must be at least two arguments after the command. */ if (parsePtr->numWords < 3 || parsePtr->numWords > 4) { return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); keyTokenPtr = TokenAfter(varTokenPtr); /* * Parse the increment amount, if present. */ if (parsePtr->numWords == 4) { const char *word; int numBytes, code; Tcl_Token *incrTokenPtr; Tcl_Obj *intObj; incrTokenPtr = TokenAfter(keyTokenPtr); if (incrTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasic2Or3ArgCmd(interp, parsePtr,cmdPtr, envPtr); } word = incrTokenPtr[1].start; numBytes = incrTokenPtr[1].size; intObj = Tcl_NewStringObj(word, numBytes); Tcl_IncrRefCount(intObj); code = TclGetIntFromObj(NULL, intObj, &incrAmount); TclDecrRefCount(intObj); if (code != TCL_OK) { return TclCompileBasic2Or3ArgCmd(interp, parsePtr,cmdPtr, envPtr); } } else { incrAmount = 1; } /* * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ dictVarIndex = LocalScalarFromToken(varTokenPtr, envPtr); if (dictVarIndex < 0) { return TclCompileBasic2Or3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Emit the key and the code to actually do the increment. */ CompileWord(envPtr, keyTokenPtr, interp, 2); TclEmitInstInt4( INST_DICT_INCR_IMM, incrAmount, envPtr); TclEmitInt4( dictVarIndex, envPtr); return TCL_OK; } int TclCompileDictGetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; int i; DefineLineInformation; /* TIP #280 */ /* * There must be at least two arguments after the command (the single-arg * case is legal, but too special and magic for us to deal with here). */ /* TODO: Consider support for compiling expanded args. */ if (parsePtr->numWords < 3) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); /* * Only compile this because we need INST_DICT_GET anyway. */ for (i=1 ; inumWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } TclEmitInstInt4(INST_DICT_GET, parsePtr->numWords-2, envPtr); TclAdjustStackDepth(-1, envPtr); return TCL_OK; } int TclCompileDictExistsCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; int i; DefineLineInformation; /* TIP #280 */ /* * There must be at least two arguments after the command (the single-arg * case is legal, but too special and magic for us to deal with here). */ /* TODO: Consider support for compiling expanded args. */ if (parsePtr->numWords < 3) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); /* * Now we do the code generation. */ for (i=1 ; inumWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } TclEmitInstInt4(INST_DICT_EXISTS, parsePtr->numWords-2, envPtr); TclAdjustStackDepth(-1, envPtr); return TCL_OK; } int TclCompileDictUnsetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; DefineLineInformation; /* TIP #280 */ int i, dictVarIndex; /* * There must be at least one argument after the variable name for us to * compile to bytecode. */ /* TODO: Consider support for compiling expanded args. */ if (parsePtr->numWords < 3) { return TCL_ERROR; } /* * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); dictVarIndex = LocalScalarFromToken(tokenPtr, envPtr); if (dictVarIndex < 0) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Remaining words (the key path) can be handled normally. */ for (i=2 ; inumWords ; i++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i); } /* * Now emit the instruction to do the dict manipulation. */ TclEmitInstInt4( INST_DICT_UNSET, parsePtr->numWords-2, envPtr); TclEmitInt4( dictVarIndex, envPtr); return TCL_OK; } int TclCompileDictCreateCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ int worker; /* Temp var for building the value in. */ Tcl_Token *tokenPtr; Tcl_Obj *keyObj, *valueObj, *dictObj; const char *bytes; int i, len; if ((parsePtr->numWords & 1) == 0) { return TCL_ERROR; } /* * See if we can build the value at compile time... */ tokenPtr = TokenAfter(parsePtr->tokenPtr); dictObj = Tcl_NewObj(); Tcl_IncrRefCount(dictObj); for (i=1 ; inumWords ; i+=2) { keyObj = Tcl_NewObj(); Tcl_IncrRefCount(keyObj); if (!TclWordKnownAtCompileTime(tokenPtr, keyObj)) { Tcl_DecrRefCount(keyObj); Tcl_DecrRefCount(dictObj); goto nonConstant; } tokenPtr = TokenAfter(tokenPtr); valueObj = Tcl_NewObj(); Tcl_IncrRefCount(valueObj); if (!TclWordKnownAtCompileTime(tokenPtr, valueObj)) { Tcl_DecrRefCount(keyObj); Tcl_DecrRefCount(valueObj); Tcl_DecrRefCount(dictObj); goto nonConstant; } tokenPtr = TokenAfter(tokenPtr); Tcl_DictObjPut(NULL, dictObj, keyObj, valueObj); Tcl_DecrRefCount(keyObj); Tcl_DecrRefCount(valueObj); } /* * We did! Excellent. The "verifyDict" is to do type forcing. */ bytes = Tcl_GetStringFromObj(dictObj, &len); PushLiteral(envPtr, bytes, len); TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_DICT_VERIFY, envPtr); Tcl_DecrRefCount(dictObj); return TCL_OK; /* * Otherwise, we've got to issue runtime code to do the building, which we * do by [dict set]ting into an unnamed local variable. This requires that * we are in a context with an LVT. */ nonConstant: worker = AnonymousLocal(envPtr); if (worker < 0) { return TclCompileBasicMin0ArgCmd(interp, parsePtr, cmdPtr, envPtr); } PushStringLiteral(envPtr, ""); Emit14Inst( INST_STORE_SCALAR, worker, envPtr); TclEmitOpcode( INST_POP, envPtr); tokenPtr = TokenAfter(parsePtr->tokenPtr); for (i=1 ; inumWords ; i+=2) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i+1); tokenPtr = TokenAfter(tokenPtr); TclEmitInstInt4( INST_DICT_SET, 1, envPtr); TclEmitInt4( worker, envPtr); TclAdjustStackDepth(-1, envPtr); TclEmitOpcode( INST_POP, envPtr); } Emit14Inst( INST_LOAD_SCALAR, worker, envPtr); TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr); TclEmitInt4( worker, envPtr); return TCL_OK; } int TclCompileDictMergeCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; int i, workerIndex, infoIndex, outLoop; /* * Deal with some special edge cases. Note that in the case with one * argument, the only thing to do is to verify the dict-ness. */ /* TODO: Consider support for compiling expanded args. (less likely) */ if (parsePtr->numWords < 2) { PushStringLiteral(envPtr, ""); return TCL_OK; } else if (parsePtr->numWords == 2) { tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_DICT_VERIFY, envPtr); return TCL_OK; } /* * There's real merging work to do. * * Allocate some working space. This means we'll only ever compile this * command when there's an LVT present. */ workerIndex = AnonymousLocal(envPtr); if (workerIndex < 0) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } infoIndex = AnonymousLocal(envPtr); /* * Get the first dictionary and verify that it is so. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_DICT_VERIFY, envPtr); Emit14Inst( INST_STORE_SCALAR, workerIndex, envPtr); TclEmitOpcode( INST_POP, envPtr); /* * For each of the remaining dictionaries... */ outLoop = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); TclEmitInstInt4( INST_BEGIN_CATCH4, outLoop, envPtr); ExceptionRangeStarts(envPtr, outLoop); for (i=2 ; inumWords ; i++) { /* * Get the dictionary, and merge its pairs into the first dict (using * a small loop). */ tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i); TclEmitInstInt4( INST_DICT_FIRST, infoIndex, envPtr); TclEmitInstInt1( INST_JUMP_TRUE1, 24, envPtr); TclEmitInstInt4( INST_REVERSE, 2, envPtr); TclEmitInstInt4( INST_DICT_SET, 1, envPtr); TclEmitInt4( workerIndex, envPtr); TclAdjustStackDepth(-1, envPtr); TclEmitOpcode( INST_POP, envPtr); TclEmitInstInt4( INST_DICT_NEXT, infoIndex, envPtr); TclEmitInstInt1( INST_JUMP_FALSE1, -20, envPtr); TclEmitOpcode( INST_POP, envPtr); TclEmitOpcode( INST_POP, envPtr); TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr); TclEmitInt4( infoIndex, envPtr); } ExceptionRangeEnds(envPtr, outLoop); TclEmitOpcode( INST_END_CATCH, envPtr); /* * Clean up any state left over. */ Emit14Inst( INST_LOAD_SCALAR, workerIndex, envPtr); TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr); TclEmitInt4( workerIndex, envPtr); TclEmitInstInt1( INST_JUMP1, 18, envPtr); /* * If an exception happens when starting to iterate over the second (and * subsequent) dicts. This is strictly not necessary, but it is nice. */ TclAdjustStackDepth(-1, envPtr); ExceptionRangeTarget(envPtr, outLoop, catchOffset); TclEmitOpcode( INST_PUSH_RETURN_OPTIONS, envPtr); TclEmitOpcode( INST_PUSH_RESULT, envPtr); TclEmitOpcode( INST_END_CATCH, envPtr); TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr); TclEmitInt4( workerIndex, envPtr); TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr); TclEmitInt4( infoIndex, envPtr); TclEmitOpcode( INST_RETURN_STK, envPtr); return TCL_OK; } int TclCompileDictForCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { return CompileDictEachCmd(interp, parsePtr, cmdPtr, envPtr, TCL_EACH_KEEP_NONE); } int TclCompileDictMapCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { return CompileDictEachCmd(interp, parsePtr, cmdPtr, envPtr, TCL_EACH_COLLECT); } int CompileDictEachCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr, /* Holds resulting instructions. */ int collect) /* Flag == TCL_EACH_COLLECT to collect and * construct a new dictionary with the loop * body result. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varsTokenPtr, *dictTokenPtr, *bodyTokenPtr; int keyVarIndex, valueVarIndex, nameChars, loopRange, catchRange; int infoIndex, jumpDisplacement, bodyTargetOffset, emptyTargetOffset; int numVars, endTargetOffset; int collectVar = -1; /* Index of temp var holding the result * dict. */ const char **argv; Tcl_DString buffer; /* * There must be three arguments after the command. */ if (parsePtr->numWords != 4) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } varsTokenPtr = TokenAfter(parsePtr->tokenPtr); dictTokenPtr = TokenAfter(varsTokenPtr); bodyTokenPtr = TokenAfter(dictTokenPtr); if (varsTokenPtr->type != TCL_TOKEN_SIMPLE_WORD || bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Create temporary variable to capture return values from loop body when * we're collecting results. */ if (collect == TCL_EACH_COLLECT) { collectVar = AnonymousLocal(envPtr); if (collectVar < 0) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } } /* * Check we've got a pair of variables and that they are local variables. * Then extract their indices in the LVT. */ Tcl_DStringInit(&buffer); TclDStringAppendToken(&buffer, &varsTokenPtr[1]); if (Tcl_SplitList(NULL, Tcl_DStringValue(&buffer), &numVars, &argv) != TCL_OK) { Tcl_DStringFree(&buffer); return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } Tcl_DStringFree(&buffer); if (numVars != 2) { ckfree(argv); return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } nameChars = strlen(argv[0]); keyVarIndex = LocalScalar(argv[0], nameChars, envPtr); nameChars = strlen(argv[1]); valueVarIndex = LocalScalar(argv[1], nameChars, envPtr); ckfree(argv); if ((keyVarIndex < 0) || (valueVarIndex < 0)) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Allocate a temporary variable to store the iterator reference. The * variable will contain a Tcl_DictSearch reference which will be * allocated by INST_DICT_FIRST and disposed when the variable is unset * (at which point it should also have been finished with). */ infoIndex = AnonymousLocal(envPtr); if (infoIndex < 0) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Preparation complete; issue instructions. Note that this code issues * fixed-sized jumps. That simplifies things a lot! * * First up, initialize the accumulator dictionary if needed. */ if (collect == TCL_EACH_COLLECT) { PushStringLiteral(envPtr, ""); Emit14Inst( INST_STORE_SCALAR, collectVar, envPtr); TclEmitOpcode( INST_POP, envPtr); } /* * Get the dictionary and start the iteration. No catching of errors at * this point. */ CompileWord(envPtr, dictTokenPtr, interp, 2); /* * Now we catch errors from here on so that we can finalize the search * started by Tcl_DictObjFirst above. */ catchRange = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); TclEmitInstInt4( INST_BEGIN_CATCH4, catchRange, envPtr); ExceptionRangeStarts(envPtr, catchRange); TclEmitInstInt4( INST_DICT_FIRST, infoIndex, envPtr); emptyTargetOffset = CurrentOffset(envPtr); TclEmitInstInt4( INST_JUMP_TRUE4, 0, envPtr); /* * Inside the iteration, write the loop variables. */ bodyTargetOffset = CurrentOffset(envPtr); Emit14Inst( INST_STORE_SCALAR, keyVarIndex, envPtr); TclEmitOpcode( INST_POP, envPtr); Emit14Inst( INST_STORE_SCALAR, valueVarIndex, envPtr); TclEmitOpcode( INST_POP, envPtr); /* * Set up the loop exception targets. */ loopRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); ExceptionRangeStarts(envPtr, loopRange); /* * Compile the loop body itself. It should be stack-neutral. */ BODY(bodyTokenPtr, 3); if (collect == TCL_EACH_COLLECT) { Emit14Inst( INST_LOAD_SCALAR, keyVarIndex, envPtr); TclEmitInstInt4(INST_OVER, 1, envPtr); TclEmitInstInt4(INST_DICT_SET, 1, envPtr); TclEmitInt4( collectVar, envPtr); TclAdjustStackDepth(-1, envPtr); TclEmitOpcode( INST_POP, envPtr); } TclEmitOpcode( INST_POP, envPtr); /* * Both exception target ranges (error and loop) end here. */ ExceptionRangeEnds(envPtr, loopRange); ExceptionRangeEnds(envPtr, catchRange); /* * Continue (or just normally process) by getting the next pair of items * from the dictionary and jumping back to the code to write them into * variables if there is another pair. */ ExceptionRangeTarget(envPtr, loopRange, continueOffset); TclEmitInstInt4( INST_DICT_NEXT, infoIndex, envPtr); jumpDisplacement = bodyTargetOffset - CurrentOffset(envPtr); TclEmitInstInt4( INST_JUMP_FALSE4, jumpDisplacement, envPtr); endTargetOffset = CurrentOffset(envPtr); TclEmitInstInt1( INST_JUMP1, 0, envPtr); /* * Error handler "finally" clause, which force-terminates the iteration * and rethrows the error. */ TclAdjustStackDepth(-1, envPtr); ExceptionRangeTarget(envPtr, catchRange, catchOffset); TclEmitOpcode( INST_PUSH_RETURN_OPTIONS, envPtr); TclEmitOpcode( INST_PUSH_RESULT, envPtr); TclEmitOpcode( INST_END_CATCH, envPtr); TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr); TclEmitInt4( infoIndex, envPtr); if (collect == TCL_EACH_COLLECT) { TclEmitInstInt1(INST_UNSET_SCALAR, 0, envPtr); TclEmitInt4( collectVar, envPtr); } TclEmitOpcode( INST_RETURN_STK, envPtr); /* * Otherwise we're done (the jump after the DICT_FIRST points here) and we * need to pop the bogus key/value pair (pushed to keep stack calculations * easy!) Note that we skip the END_CATCH. [Bug 1382528] */ jumpDisplacement = CurrentOffset(envPtr) - emptyTargetOffset; TclUpdateInstInt4AtPc(INST_JUMP_TRUE4, jumpDisplacement, envPtr->codeStart + emptyTargetOffset); jumpDisplacement = CurrentOffset(envPtr) - endTargetOffset; TclUpdateInstInt1AtPc(INST_JUMP1, jumpDisplacement, envPtr->codeStart + endTargetOffset); TclEmitOpcode( INST_POP, envPtr); TclEmitOpcode( INST_POP, envPtr); ExceptionRangeTarget(envPtr, loopRange, breakOffset); TclFinalizeLoopExceptionRange(envPtr, loopRange); TclEmitOpcode( INST_END_CATCH, envPtr); /* * Final stage of the command (normal case) is that we push an empty * object (or push the accumulator as the result object). This is done * last to promote peephole optimization when it's dropped immediately. */ TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr); TclEmitInt4( infoIndex, envPtr); if (collect == TCL_EACH_COLLECT) { Emit14Inst( INST_LOAD_SCALAR, collectVar, envPtr); TclEmitInstInt1(INST_UNSET_SCALAR, 0, envPtr); TclEmitInt4( collectVar, envPtr); } else { PushStringLiteral(envPtr, ""); } return TCL_OK; } int TclCompileDictUpdateCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ int i, dictIndex, numVars, range, infoIndex; Tcl_Token **keyTokenPtrs, *dictVarTokenPtr, *bodyTokenPtr, *tokenPtr; DictUpdateInfo *duiPtr; JumpFixup jumpFixup; /* * There must be at least one argument after the command. */ if (parsePtr->numWords < 5) { return TCL_ERROR; } /* * Parse the command. Expect the following: * dict update ? ...? */ if ((parsePtr->numWords - 1) & 1) { return TCL_ERROR; } numVars = (parsePtr->numWords - 3) / 2; /* * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ dictVarTokenPtr = TokenAfter(parsePtr->tokenPtr); dictIndex = LocalScalarFromToken(dictVarTokenPtr, envPtr); if (dictIndex < 0) { goto issueFallback; } /* * Assemble the instruction metadata. This is complex enough that it is * represented as auxData; it holds an ordered list of variable indices * that are to be used. */ duiPtr = ckalloc(sizeof(DictUpdateInfo) + sizeof(int) * (numVars - 1)); duiPtr->length = numVars; keyTokenPtrs = TclStackAlloc(interp, sizeof(Tcl_Token *) * numVars); tokenPtr = TokenAfter(dictVarTokenPtr); for (i=0 ; ivarIndices[i] = LocalScalarFromToken(tokenPtr, envPtr); if (duiPtr->varIndices[i] < 0) { goto failedUpdateInfoAssembly; } tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { goto failedUpdateInfoAssembly; } bodyTokenPtr = tokenPtr; /* * The list of variables to bind is stored in auxiliary data so that it * can't be snagged by literal sharing and forced to shimmer dangerously. */ infoIndex = TclCreateAuxData(duiPtr, &dictUpdateInfoType, envPtr); for (i=0 ; inumWords - 1); ExceptionRangeEnds(envPtr, range); /* * Normal termination code: the stack has the key list below the result of * the body evaluation: swap them and finish the update code. */ TclEmitOpcode( INST_END_CATCH, envPtr); TclEmitInstInt4( INST_REVERSE, 2, envPtr); TclEmitInstInt4( INST_DICT_UPDATE_END, dictIndex, envPtr); TclEmitInt4( infoIndex, envPtr); /* * Jump around the exceptional termination code. */ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); /* * Termination code for non-ok returns: stash the result and return * options in the stack, bring up the key list, finish the update code, * and finally return with the catched return data */ ExceptionRangeTarget(envPtr, range, catchOffset); TclEmitOpcode( INST_PUSH_RESULT, envPtr); TclEmitOpcode( INST_PUSH_RETURN_OPTIONS, envPtr); TclEmitOpcode( INST_END_CATCH, envPtr); TclEmitInstInt4( INST_REVERSE, 3, envPtr); TclEmitInstInt4( INST_DICT_UPDATE_END, dictIndex, envPtr); TclEmitInt4( infoIndex, envPtr); TclEmitInvoke(envPtr,INST_RETURN_STK); if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) { Tcl_Panic("TclCompileDictCmd(update): bad jump distance %d", (int) (CurrentOffset(envPtr) - jumpFixup.codeOffset)); } TclStackFree(interp, keyTokenPtrs); return TCL_OK; /* * Clean up after a failure to create the DictUpdateInfo structure. */ failedUpdateInfoAssembly: ckfree(duiPtr); TclStackFree(interp, keyTokenPtrs); issueFallback: return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } int TclCompileDictAppendCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; int i, dictVarIndex; /* * There must be at least two argument after the command. And we impose an * (arbirary) safe limit; anyone exceeding it should stop worrying about * speed quite so much. ;-) */ /* TODO: Consider support for compiling expanded args. */ if (parsePtr->numWords<4 || parsePtr->numWords>100) { return TCL_ERROR; } /* * Get the index of the local variable that we will be working with. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); dictVarIndex = LocalScalarFromToken(tokenPtr, envPtr); if (dictVarIndex < 0) { return TclCompileBasicMin2ArgCmd(interp, parsePtr,cmdPtr, envPtr); } /* * Produce the string to concatenate onto the dictionary entry. */ tokenPtr = TokenAfter(tokenPtr); for (i=2 ; inumWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } if (parsePtr->numWords > 4) { TclEmitInstInt1(INST_STR_CONCAT1, parsePtr->numWords-3, envPtr); } /* * Do the concatenation. */ TclEmitInstInt4(INST_DICT_APPEND, dictVarIndex, envPtr); return TCL_OK; } int TclCompileDictLappendCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varTokenPtr, *keyTokenPtr, *valueTokenPtr; int dictVarIndex; /* * There must be three arguments after the command. */ /* TODO: Consider support for compiling expanded args. */ /* Probably not. Why is INST_DICT_LAPPEND limited to one value? */ if (parsePtr->numWords != 4) { return TCL_ERROR; } /* * Parse the arguments. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); keyTokenPtr = TokenAfter(varTokenPtr); valueTokenPtr = TokenAfter(keyTokenPtr); dictVarIndex = LocalScalarFromToken(varTokenPtr, envPtr); if (dictVarIndex < 0) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Issue the implementation. */ CompileWord(envPtr, keyTokenPtr, interp, 2); CompileWord(envPtr, valueTokenPtr, interp, 3); TclEmitInstInt4( INST_DICT_LAPPEND, dictVarIndex, envPtr); return TCL_OK; } int TclCompileDictWithCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ int i, range, varNameTmp = -1, pathTmp = -1, keysTmp, gotPath; int dictVar, bodyIsEmpty = 1; Tcl_Token *varTokenPtr, *tokenPtr; JumpFixup jumpFixup; const char *ptr, *end; /* * There must be at least one argument after the command. */ /* TODO: Consider support for compiling expanded args. */ if (parsePtr->numWords < 3) { return TCL_ERROR; } /* * Parse the command (trivially). Expect the following: * dict with ? ...? */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); tokenPtr = TokenAfter(varTokenPtr); for (i=3 ; inumWords ; i++) { tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Test if the last word is an empty script; if so, we can compile it in * all cases, but if it is non-empty we need local variable table entries * to hold the temporary variables (used to keep stack usage simple). */ for (ptr=tokenPtr[1].start,end=ptr+tokenPtr[1].size ; ptr!=end ; ptr++) { if (*ptr!=' ' && *ptr!='\t' && *ptr!='\n' && *ptr!='\r') { if (envPtr->procPtr == NULL) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } bodyIsEmpty = 0; break; } } /* * Determine if we're manipulating a dict in a simple local variable. */ gotPath = (parsePtr->numWords > 3); dictVar = LocalScalarFromToken(varTokenPtr, envPtr); /* * Special case: an empty body means we definitely have no need to issue * try-finally style code or to allocate local variable table entries for * storing temporaries. Still need to do both INST_DICT_EXPAND and * INST_DICT_RECOMBINE_* though, because we can't determine if we're free * of traces. */ if (bodyIsEmpty) { if (dictVar >= 0) { if (gotPath) { /* * Case: Path into dict in LVT with empty body. */ tokenPtr = TokenAfter(varTokenPtr); for (i=2 ; inumWords-1 ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } TclEmitInstInt4(INST_LIST, parsePtr->numWords-3,envPtr); Emit14Inst( INST_LOAD_SCALAR, dictVar, envPtr); TclEmitInstInt4(INST_OVER, 1, envPtr); TclEmitOpcode( INST_DICT_EXPAND, envPtr); TclEmitInstInt4(INST_DICT_RECOMBINE_IMM, dictVar, envPtr); } else { /* * Case: Direct dict in LVT with empty body. */ PushStringLiteral(envPtr, ""); Emit14Inst( INST_LOAD_SCALAR, dictVar, envPtr); PushStringLiteral(envPtr, ""); TclEmitOpcode( INST_DICT_EXPAND, envPtr); TclEmitInstInt4(INST_DICT_RECOMBINE_IMM, dictVar, envPtr); } } else { if (gotPath) { /* * Case: Path into dict in non-simple var with empty body. */ tokenPtr = varTokenPtr; for (i=1 ; inumWords-1 ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } TclEmitInstInt4(INST_LIST, parsePtr->numWords-3,envPtr); TclEmitInstInt4(INST_OVER, 1, envPtr); TclEmitOpcode( INST_LOAD_STK, envPtr); TclEmitInstInt4(INST_OVER, 1, envPtr); TclEmitOpcode( INST_DICT_EXPAND, envPtr); TclEmitOpcode( INST_DICT_RECOMBINE_STK, envPtr); } else { /* * Case: Direct dict in non-simple var with empty body. */ CompileWord(envPtr, varTokenPtr, interp, 1); TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_LOAD_STK, envPtr); PushStringLiteral(envPtr, ""); TclEmitOpcode( INST_DICT_EXPAND, envPtr); PushStringLiteral(envPtr, ""); TclEmitInstInt4(INST_REVERSE, 2, envPtr); TclEmitOpcode( INST_DICT_RECOMBINE_STK, envPtr); } } PushStringLiteral(envPtr, ""); return TCL_OK; } /* * OK, we have a non-trivial body. This means that the focus is on * generating a try-finally structure where the INST_DICT_RECOMBINE_* goes * in the 'finally' clause. * * Start by allocating local (unnamed, untraced) working variables. */ if (dictVar == -1) { varNameTmp = AnonymousLocal(envPtr); } if (gotPath) { pathTmp = AnonymousLocal(envPtr); } keysTmp = AnonymousLocal(envPtr); /* * Issue instructions. First, the part to expand the dictionary. */ if (dictVar == -1) { CompileWord(envPtr, varTokenPtr, interp, 1); Emit14Inst( INST_STORE_SCALAR, varNameTmp, envPtr); } tokenPtr = TokenAfter(varTokenPtr); if (gotPath) { for (i=2 ; inumWords-1 ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } TclEmitInstInt4( INST_LIST, parsePtr->numWords-3,envPtr); Emit14Inst( INST_STORE_SCALAR, pathTmp, envPtr); TclEmitOpcode( INST_POP, envPtr); } if (dictVar == -1) { TclEmitOpcode( INST_LOAD_STK, envPtr); } else { Emit14Inst( INST_LOAD_SCALAR, dictVar, envPtr); } if (gotPath) { Emit14Inst( INST_LOAD_SCALAR, pathTmp, envPtr); } else { PushStringLiteral(envPtr, ""); } TclEmitOpcode( INST_DICT_EXPAND, envPtr); Emit14Inst( INST_STORE_SCALAR, keysTmp, envPtr); TclEmitOpcode( INST_POP, envPtr); /* * Now the body of the [dict with]. */ range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); TclEmitInstInt4( INST_BEGIN_CATCH4, range, envPtr); ExceptionRangeStarts(envPtr, range); BODY(tokenPtr, parsePtr->numWords - 1); ExceptionRangeEnds(envPtr, range); /* * Now fold the results back into the dictionary in the OK case. */ TclEmitOpcode( INST_END_CATCH, envPtr); if (dictVar == -1) { Emit14Inst( INST_LOAD_SCALAR, varNameTmp, envPtr); } if (gotPath) { Emit14Inst( INST_LOAD_SCALAR, pathTmp, envPtr); } else { PushStringLiteral(envPtr, ""); } Emit14Inst( INST_LOAD_SCALAR, keysTmp, envPtr); if (dictVar == -1) { TclEmitOpcode( INST_DICT_RECOMBINE_STK, envPtr); } else { TclEmitInstInt4( INST_DICT_RECOMBINE_IMM, dictVar, envPtr); } TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); /* * Now fold the results back into the dictionary in the exception case. */ TclAdjustStackDepth(-1, envPtr); ExceptionRangeTarget(envPtr, range, catchOffset); TclEmitOpcode( INST_PUSH_RETURN_OPTIONS, envPtr); TclEmitOpcode( INST_PUSH_RESULT, envPtr); TclEmitOpcode( INST_END_CATCH, envPtr); if (dictVar == -1) { Emit14Inst( INST_LOAD_SCALAR, varNameTmp, envPtr); } if (parsePtr->numWords > 3) { Emit14Inst( INST_LOAD_SCALAR, pathTmp, envPtr); } else { PushStringLiteral(envPtr, ""); } Emit14Inst( INST_LOAD_SCALAR, keysTmp, envPtr); if (dictVar == -1) { TclEmitOpcode( INST_DICT_RECOMBINE_STK, envPtr); } else { TclEmitInstInt4( INST_DICT_RECOMBINE_IMM, dictVar, envPtr); } TclEmitInvoke(envPtr, INST_RETURN_STK); /* * Prepare for the start of the next command. */ if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) { Tcl_Panic("TclCompileDictCmd(update): bad jump distance %d", (int) (CurrentOffset(envPtr) - jumpFixup.codeOffset)); } return TCL_OK; } /* *---------------------------------------------------------------------- * * DupDictUpdateInfo, FreeDictUpdateInfo -- * * Functions to duplicate, release and print the aux data created for use * with the INST_DICT_UPDATE_START and INST_DICT_UPDATE_END instructions. * * Results: * DupDictUpdateInfo: a copy of the auxiliary data * FreeDictUpdateInfo: none * PrintDictUpdateInfo: none * DisassembleDictUpdateInfo: none * * Side effects: * DupDictUpdateInfo: allocates memory * FreeDictUpdateInfo: releases memory * PrintDictUpdateInfo: none * DisassembleDictUpdateInfo: none * *---------------------------------------------------------------------- */ static ClientData DupDictUpdateInfo( ClientData clientData) { DictUpdateInfo *dui1Ptr, *dui2Ptr; unsigned len; dui1Ptr = clientData; len = sizeof(DictUpdateInfo) + sizeof(int) * (dui1Ptr->length - 1); dui2Ptr = ckalloc(len); memcpy(dui2Ptr, dui1Ptr, len); return dui2Ptr; } static void FreeDictUpdateInfo( ClientData clientData) { ckfree(clientData); } static void PrintDictUpdateInfo( ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset) { DictUpdateInfo *duiPtr = clientData; int i; for (i=0 ; ilength ; i++) { if (i) { Tcl_AppendToObj(appendObj, ", ", -1); } Tcl_AppendPrintfToObj(appendObj, "%%v%u", duiPtr->varIndices[i]); } } static void DisassembleDictUpdateInfo( ClientData clientData, Tcl_Obj *dictObj, ByteCode *codePtr, unsigned int pcOffset) { DictUpdateInfo *duiPtr = clientData; int i; Tcl_Obj *variables = Tcl_NewObj(); for (i=0 ; ilength ; i++) { Tcl_ListObjAppendElement(NULL, variables, Tcl_NewIntObj(duiPtr->varIndices[i])); } Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("variables", -1), variables); } /* *---------------------------------------------------------------------- * * TclCompileErrorCmd -- * * Procedure called to compile the "error" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "error" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileErrorCmd( Tcl_Interp *interp, /* Used for context. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * General syntax: [error message ?errorInfo? ?errorCode?] */ Tcl_Token *tokenPtr; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords < 2 || parsePtr->numWords > 4) { return TCL_ERROR; } /* * Handle the message. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); /* * Construct the options. Note that -code and -level are not here. */ if (parsePtr->numWords == 2) { PushStringLiteral(envPtr, ""); } else { PushStringLiteral(envPtr, "-errorinfo"); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 2); if (parsePtr->numWords == 3) { TclEmitInstInt4( INST_LIST, 2, envPtr); } else { PushStringLiteral(envPtr, "-errorcode"); tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, 3); TclEmitInstInt4( INST_LIST, 4, envPtr); } } /* * Issue the error via 'returnImm error 0'. */ TclEmitInstInt4( INST_RETURN_IMM, TCL_ERROR, envPtr); TclEmitInt4( 0, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileExprCmd -- * * Procedure called to compile the "expr" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "expr" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileExprCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *firstWordPtr; if (parsePtr->numWords == 1) { return TCL_ERROR; } /* * TIP #280: Use the per-word line information of the current command. */ envPtr->line = envPtr->extCmdMapPtr->loc[ envPtr->extCmdMapPtr->nuloc-1].line[1]; firstWordPtr = TokenAfter(parsePtr->tokenPtr); TclCompileExprWords(interp, firstWordPtr, parsePtr->numWords-1, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileForCmd -- * * Procedure called to compile the "for" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "for" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileForCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *startTokenPtr, *testTokenPtr, *nextTokenPtr, *bodyTokenPtr; JumpFixup jumpEvalCondFixup; int bodyCodeOffset, nextCodeOffset, jumpDist; int bodyRange, nextRange; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 5) { return TCL_ERROR; } /* * If the test expression requires substitutions, don't compile the for * command inline. E.g., the expression might cause the loop to never * execute or execute forever, as in "for {} "$x > 5" {incr x} {}". */ startTokenPtr = TokenAfter(parsePtr->tokenPtr); testTokenPtr = TokenAfter(startTokenPtr); if (testTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TCL_ERROR; } /* * Bail out also if the body or the next expression require substitutions * in order to insure correct behaviour [Bug 219166] */ nextTokenPtr = TokenAfter(testTokenPtr); bodyTokenPtr = TokenAfter(nextTokenPtr); if ((nextTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) || (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD)) { return TCL_ERROR; } /* * Inline compile the initial command. */ BODY(startTokenPtr, 1); TclEmitOpcode(INST_POP, envPtr); /* * Jump to the evaluation of the condition. This code uses the "loop * rotation" optimisation (which eliminates one branch from the loop). * "for start cond next body" produces then: * start * goto A * B: body : bodyCodeOffset * next : nextCodeOffset, continueOffset * A: cond -> result : testCodeOffset * if (result) goto B */ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpEvalCondFixup); /* * Compile the loop body. */ bodyRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); bodyCodeOffset = ExceptionRangeStarts(envPtr, bodyRange); BODY(bodyTokenPtr, 4); ExceptionRangeEnds(envPtr, bodyRange); TclEmitOpcode(INST_POP, envPtr); /* * Compile the "next" subcommand. Note that this exception range will not * have a continueOffset (other than -1) connected to it; it won't trap * TCL_CONTINUE but rather just TCL_BREAK. */ nextRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); envPtr->exceptAuxArrayPtr[nextRange].supportsContinue = 0; nextCodeOffset = ExceptionRangeStarts(envPtr, nextRange); BODY(nextTokenPtr, 3); ExceptionRangeEnds(envPtr, nextRange); TclEmitOpcode(INST_POP, envPtr); /* * Compile the test expression then emit the conditional jump that * terminates the for. */ if (TclFixupForwardJumpToHere(envPtr, &jumpEvalCondFixup, 127)) { bodyCodeOffset += 3; nextCodeOffset += 3; } SetLineInformation(2); TclCompileExprWords(interp, testTokenPtr, 1, envPtr); jumpDist = CurrentOffset(envPtr) - bodyCodeOffset; if (jumpDist > 127) { TclEmitInstInt4(INST_JUMP_TRUE4, -jumpDist, envPtr); } else { TclEmitInstInt1(INST_JUMP_TRUE1, -jumpDist, envPtr); } /* * Fix the starting points of the exception ranges (may have moved due to * jump type modification) and set where the exceptions target. */ envPtr->exceptArrayPtr[bodyRange].codeOffset = bodyCodeOffset; envPtr->exceptArrayPtr[bodyRange].continueOffset = nextCodeOffset; envPtr->exceptArrayPtr[nextRange].codeOffset = nextCodeOffset; ExceptionRangeTarget(envPtr, bodyRange, breakOffset); ExceptionRangeTarget(envPtr, nextRange, breakOffset); TclFinalizeLoopExceptionRange(envPtr, bodyRange); TclFinalizeLoopExceptionRange(envPtr, nextRange); /* * The for command's result is an empty string. */ PushStringLiteral(envPtr, ""); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileForeachCmd -- * * Procedure called to compile the "foreach" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "foreach" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileForeachCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { return CompileEachloopCmd(interp, parsePtr, cmdPtr, envPtr, TCL_EACH_KEEP_NONE); } /* *---------------------------------------------------------------------- * * TclCompileLmapCmd -- * * Procedure called to compile the "lmap" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "lmap" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileLmapCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { return CompileEachloopCmd(interp, parsePtr, cmdPtr, envPtr, TCL_EACH_COLLECT); } /* *---------------------------------------------------------------------- * * CompileEachloopCmd -- * * Procedure called to compile the "foreach" and "lmap" commands. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "foreach" command at * runtime. * *---------------------------------------------------------------------- */ static int CompileEachloopCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr, /* Holds resulting instructions. */ int collect) /* Select collecting or accumulating mode * (TCL_EACH_*) */ { Proc *procPtr = envPtr->procPtr; ForeachInfo *infoPtr=NULL; /* Points to the structure describing this * foreach command. Stored in a AuxData * record in the ByteCode. */ Tcl_Token *tokenPtr, *bodyTokenPtr; int jumpBackOffset, infoIndex, range; int numWords, numLists, i, j, code = TCL_OK; Tcl_Obj *varListObj = NULL; DefineLineInformation; /* TIP #280 */ /* * If the foreach command isn't in a procedure, don't compile it inline: * the payoff is too small. */ if (procPtr == NULL) { return TCL_ERROR; } numWords = parsePtr->numWords; if ((numWords < 4) || (numWords%2 != 0)) { return TCL_ERROR; } /* * Bail out if the body requires substitutions in order to insure correct * behaviour. [Bug 219166] */ for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++) { tokenPtr = TokenAfter(tokenPtr); } bodyTokenPtr = tokenPtr; if (bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TCL_ERROR; } /* * Create and initialize the ForeachInfo and ForeachVarList data * structures describing this command. Then create a AuxData record * pointing to the ForeachInfo structure. */ numLists = (numWords - 2)/2; infoPtr = ckalloc(sizeof(ForeachInfo) + (numLists - 1) * sizeof(ForeachVarList *)); infoPtr->numLists = 0; /* Count this up as we go */ /* * Parse each var list into sequence of var names. Don't * compile the foreach inline if any var name needs substitutions or isn't * a scalar, or if any var list needs substitutions. */ varListObj = Tcl_NewObj(); for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++, tokenPtr = TokenAfter(tokenPtr)) { ForeachVarList *varListPtr; int numVars; if (i%2 != 1) { continue; } /* * If the variable list is empty, we can enter an infinite loop when * the interpreted version would not. Take care to ensure this does * not happen. [Bug 1671138] */ if (!TclWordKnownAtCompileTime(tokenPtr, varListObj) || TCL_OK != Tcl_ListObjLength(NULL, varListObj, &numVars) || numVars == 0) { code = TCL_ERROR; goto done; } varListPtr = ckalloc(sizeof(ForeachVarList) + (numVars - 1) * sizeof(int)); varListPtr->numVars = numVars; infoPtr->varLists[i/2] = varListPtr; infoPtr->numLists++; for (j = 0; j < numVars; j++) { Tcl_Obj *varNameObj; const char *bytes; int numBytes, varIndex; Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj); bytes = Tcl_GetStringFromObj(varNameObj, &numBytes); varIndex = LocalScalar(bytes, numBytes, envPtr); if (varIndex < 0) { code = TCL_ERROR; goto done; } varListPtr->varIndexes[j] = varIndex; } Tcl_SetObjLength(varListObj, 0); } /* * We will compile the foreach command. */ infoIndex = TclCreateAuxData(infoPtr, &newForeachInfoType, envPtr); /* * Create the collecting object, unshared. */ if (collect == TCL_EACH_COLLECT) { TclEmitInstInt4(INST_LIST, 0, envPtr); } /* * Evaluate each value list and leave it on stack. */ for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++, tokenPtr = TokenAfter(tokenPtr)) { if ((i%2 == 0) && (i > 0)) { CompileWord(envPtr, tokenPtr, interp, i); } } TclEmitInstInt4(INST_FOREACH_START, infoIndex, envPtr); /* * Inline compile the loop body. */ range = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); ExceptionRangeStarts(envPtr, range); BODY(bodyTokenPtr, numWords - 1); ExceptionRangeEnds(envPtr, range); if (collect == TCL_EACH_COLLECT) { TclEmitOpcode(INST_LMAP_COLLECT, envPtr); } else { TclEmitOpcode( INST_POP, envPtr); } /* * Bottom of loop code: assign each loop variable and check whether * to terminate the loop. Set the loop's break target. */ ExceptionRangeTarget(envPtr, range, continueOffset); TclEmitOpcode(INST_FOREACH_STEP, envPtr); ExceptionRangeTarget(envPtr, range, breakOffset); TclFinalizeLoopExceptionRange(envPtr, range); TclEmitOpcode(INST_FOREACH_END, envPtr); TclAdjustStackDepth(-(numLists+2), envPtr); /* * Set the jumpback distance from INST_FOREACH_STEP to the start of the * body's code. Misuse loopCtTemp for storing the jump size. */ jumpBackOffset = envPtr->exceptArrayPtr[range].continueOffset - envPtr->exceptArrayPtr[range].codeOffset; infoPtr->loopCtTemp = -jumpBackOffset; /* * The command's result is an empty string if not collecting. If * collecting, it is automatically left on stack after FOREACH_END. */ if (collect != TCL_EACH_COLLECT) { PushStringLiteral(envPtr, ""); } done: if (code == TCL_ERROR) { FreeForeachInfo(infoPtr); } Tcl_DecrRefCount(varListObj); return code; } /* *---------------------------------------------------------------------- * * DupForeachInfo -- * * This procedure duplicates a ForeachInfo structure created as auxiliary * data during the compilation of a foreach command. * * Results: * A pointer to a newly allocated copy of the existing ForeachInfo * structure is returned. * * Side effects: * Storage for the copied ForeachInfo record is allocated. If the * original ForeachInfo structure pointed to any ForeachVarList records, * these structures are also copied and pointers to them are stored in * the new ForeachInfo record. * *---------------------------------------------------------------------- */ static ClientData DupForeachInfo( ClientData clientData) /* The foreach command's compilation auxiliary * data to duplicate. */ { register ForeachInfo *srcPtr = clientData; ForeachInfo *dupPtr; register ForeachVarList *srcListPtr, *dupListPtr; int numVars, i, j, numLists = srcPtr->numLists; dupPtr = ckalloc(sizeof(ForeachInfo) + numLists * sizeof(ForeachVarList *)); dupPtr->numLists = numLists; dupPtr->firstValueTemp = srcPtr->firstValueTemp; dupPtr->loopCtTemp = srcPtr->loopCtTemp; for (i = 0; i < numLists; i++) { srcListPtr = srcPtr->varLists[i]; numVars = srcListPtr->numVars; dupListPtr = ckalloc(sizeof(ForeachVarList) + numVars * sizeof(int)); dupListPtr->numVars = numVars; for (j = 0; j < numVars; j++) { dupListPtr->varIndexes[j] = srcListPtr->varIndexes[j]; } dupPtr->varLists[i] = dupListPtr; } return dupPtr; } /* *---------------------------------------------------------------------- * * FreeForeachInfo -- * * Procedure to free a ForeachInfo structure created as auxiliary data * during the compilation of a foreach command. * * Results: * None. * * Side effects: * Storage for the ForeachInfo structure pointed to by the ClientData * argument is freed as is any ForeachVarList record pointed to by the * ForeachInfo structure. * *---------------------------------------------------------------------- */ static void FreeForeachInfo( ClientData clientData) /* The foreach command's compilation auxiliary * data to free. */ { register ForeachInfo *infoPtr = clientData; register ForeachVarList *listPtr; int numLists = infoPtr->numLists; register int i; for (i = 0; i < numLists; i++) { listPtr = infoPtr->varLists[i]; ckfree(listPtr); } ckfree(infoPtr); } /* *---------------------------------------------------------------------- * * PrintForeachInfo, DisassembleForeachInfo -- * * Functions to write a human-readable or script-readablerepresentation * of a ForeachInfo structure to a Tcl_Obj for debugging. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void PrintForeachInfo( ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset) { register ForeachInfo *infoPtr = clientData; register ForeachVarList *varsPtr; int i, j; Tcl_AppendToObj(appendObj, "data=[", -1); for (i=0 ; inumLists ; i++) { if (i) { Tcl_AppendToObj(appendObj, ", ", -1); } Tcl_AppendPrintfToObj(appendObj, "%%v%u", (unsigned) (infoPtr->firstValueTemp + i)); } Tcl_AppendPrintfToObj(appendObj, "], loop=%%v%u", (unsigned) infoPtr->loopCtTemp); for (i=0 ; inumLists ; i++) { if (i) { Tcl_AppendToObj(appendObj, ",", -1); } Tcl_AppendPrintfToObj(appendObj, "\n\t\t it%%v%u\t[", (unsigned) (infoPtr->firstValueTemp + i)); varsPtr = infoPtr->varLists[i]; for (j=0 ; jnumVars ; j++) { if (j) { Tcl_AppendToObj(appendObj, ", ", -1); } Tcl_AppendPrintfToObj(appendObj, "%%v%u", (unsigned) varsPtr->varIndexes[j]); } Tcl_AppendToObj(appendObj, "]", -1); } } static void PrintNewForeachInfo( ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset) { register ForeachInfo *infoPtr = clientData; register ForeachVarList *varsPtr; int i, j; Tcl_AppendPrintfToObj(appendObj, "jumpOffset=%+d, vars=", infoPtr->loopCtTemp); for (i=0 ; inumLists ; i++) { if (i) { Tcl_AppendToObj(appendObj, ",", -1); } Tcl_AppendToObj(appendObj, "[", -1); varsPtr = infoPtr->varLists[i]; for (j=0 ; jnumVars ; j++) { if (j) { Tcl_AppendToObj(appendObj, ",", -1); } Tcl_AppendPrintfToObj(appendObj, "%%v%u", (unsigned) varsPtr->varIndexes[j]); } Tcl_AppendToObj(appendObj, "]", -1); } } static void DisassembleForeachInfo( ClientData clientData, Tcl_Obj *dictObj, ByteCode *codePtr, unsigned int pcOffset) { register ForeachInfo *infoPtr = clientData; register ForeachVarList *varsPtr; int i, j; Tcl_Obj *objPtr, *innerPtr; /* * Data stores. */ objPtr = Tcl_NewObj(); for (i=0 ; inumLists ; i++) { Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(infoPtr->firstValueTemp + i)); } Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("data", -1), objPtr); /* * Loop counter. */ Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("loop", -1), Tcl_NewIntObj(infoPtr->loopCtTemp)); /* * Assignment targets. */ objPtr = Tcl_NewObj(); for (i=0 ; inumLists ; i++) { innerPtr = Tcl_NewObj(); varsPtr = infoPtr->varLists[i]; for (j=0 ; jnumVars ; j++) { Tcl_ListObjAppendElement(NULL, innerPtr, Tcl_NewIntObj(varsPtr->varIndexes[j])); } Tcl_ListObjAppendElement(NULL, objPtr, innerPtr); } Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("assign", -1), objPtr); } static void DisassembleNewForeachInfo( ClientData clientData, Tcl_Obj *dictObj, ByteCode *codePtr, unsigned int pcOffset) { register ForeachInfo *infoPtr = clientData; register ForeachVarList *varsPtr; int i, j; Tcl_Obj *objPtr, *innerPtr; /* * Jump offset. */ Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("jumpOffset", -1), Tcl_NewIntObj(infoPtr->loopCtTemp)); /* * Assignment targets. */ objPtr = Tcl_NewObj(); for (i=0 ; inumLists ; i++) { innerPtr = Tcl_NewObj(); varsPtr = infoPtr->varLists[i]; for (j=0 ; jnumVars ; j++) { Tcl_ListObjAppendElement(NULL, innerPtr, Tcl_NewIntObj(varsPtr->varIndexes[j])); } Tcl_ListObjAppendElement(NULL, objPtr, innerPtr); } Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("assign", -1), objPtr); } /* *---------------------------------------------------------------------- * * TclCompileFormatCmd -- * * Procedure called to compile the "format" command. Handles cases that * can be done as constants or simple string concatenation only. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "format" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileFormatCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; Tcl_Obj **objv, *formatObj, *tmpObj; char *bytes, *start; int i, j, len; /* * Don't handle any guaranteed-error cases. */ if (parsePtr->numWords < 2) { return TCL_ERROR; } /* * Check if the argument words are all compile-time-known literals; that's * a case we can handle by compiling to a constant. */ formatObj = Tcl_NewObj(); Tcl_IncrRefCount(formatObj); tokenPtr = TokenAfter(tokenPtr); if (!TclWordKnownAtCompileTime(tokenPtr, formatObj)) { Tcl_DecrRefCount(formatObj); return TCL_ERROR; } objv = ckalloc((parsePtr->numWords-2) * sizeof(Tcl_Obj *)); for (i=0 ; i+2 < parsePtr->numWords ; i++) { tokenPtr = TokenAfter(tokenPtr); objv[i] = Tcl_NewObj(); Tcl_IncrRefCount(objv[i]); if (!TclWordKnownAtCompileTime(tokenPtr, objv[i])) { goto checkForStringConcatCase; } } /* * Everything is a literal, so the result is constant too (or an error if * the format is broken). Do the format now. */ tmpObj = Tcl_Format(interp, Tcl_GetString(formatObj), parsePtr->numWords-2, objv); for (; --i>=0 ;) { Tcl_DecrRefCount(objv[i]); } ckfree(objv); Tcl_DecrRefCount(formatObj); if (tmpObj == NULL) { TclCompileSyntaxError(interp, envPtr); return TCL_OK; } /* * Not an error, always a constant result, so just push the result as a * literal. Job done. */ bytes = Tcl_GetStringFromObj(tmpObj, &len); PushLiteral(envPtr, bytes, len); Tcl_DecrRefCount(tmpObj); return TCL_OK; checkForStringConcatCase: /* * See if we can generate a sequence of things to concatenate. This * requires that all the % sequences be %s or %%, as everything else is * sufficiently complex that we don't bother. * * First, get the state of the system relatively sensible (cleaning up * after our attempt to spot a literal). */ for (; i>=0 ; i--) { Tcl_DecrRefCount(objv[i]); } ckfree(objv); tokenPtr = TokenAfter(parsePtr->tokenPtr); tokenPtr = TokenAfter(tokenPtr); i = 0; /* * Now scan through and check for non-%s and non-%% substitutions. */ for (bytes = Tcl_GetString(formatObj) ; *bytes ; bytes++) { if (*bytes == '%') { bytes++; if (*bytes == 's') { i++; continue; } else if (*bytes == '%') { continue; } Tcl_DecrRefCount(formatObj); return TCL_ERROR; } } /* * Check if the number of things to concatenate will fit in a byte. */ if (i+2 != parsePtr->numWords || i > 125) { Tcl_DecrRefCount(formatObj); return TCL_ERROR; } /* * Generate the pushes of the things to concatenate, a sequence of * literals and compiled tokens (of which at least one is non-literal or * we'd have the case in the first half of this function) which we will * concatenate. */ i = 0; /* The count of things to concat. */ j = 2; /* The index into the argument tokens, for * TIP#280 handling. */ start = Tcl_GetString(formatObj); /* The start of the currently-scanned literal * in the format string. */ tmpObj = Tcl_NewObj(); /* The buffer used to accumulate the literal * being built. */ for (bytes = start ; *bytes ; bytes++) { if (*bytes == '%') { Tcl_AppendToObj(tmpObj, start, bytes - start); if (*++bytes == '%') { Tcl_AppendToObj(tmpObj, "%", 1); } else { char *b = Tcl_GetStringFromObj(tmpObj, &len); /* * If there is a non-empty literal from the format string, * push it and reset. */ if (len > 0) { PushLiteral(envPtr, b, len); Tcl_DecrRefCount(tmpObj); tmpObj = Tcl_NewObj(); i++; } /* * Push the code to produce the string that would be * substituted with %s, except we'll be concatenating * directly. */ CompileWord(envPtr, tokenPtr, interp, j); tokenPtr = TokenAfter(tokenPtr); j++; i++; } start = bytes + 1; } } /* * Handle the case of a trailing literal. */ Tcl_AppendToObj(tmpObj, start, bytes - start); bytes = Tcl_GetStringFromObj(tmpObj, &len); if (len > 0) { PushLiteral(envPtr, bytes, len); i++; } Tcl_DecrRefCount(tmpObj); Tcl_DecrRefCount(formatObj); if (i > 1) { /* * Do the concatenation, which produces the result. */ TclEmitInstInt1(INST_STR_CONCAT1, i, envPtr); } else { /* * EVIL HACK! Force there to be a string representation in the case * where there's just a "%s" in the format; case covered by the test * format-20.1 (and it is horrible...) */ TclEmitOpcode(INST_DUP, envPtr); PushStringLiteral(envPtr, ""); TclEmitOpcode(INST_STR_EQ, envPtr); TclEmitOpcode(INST_POP, envPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclLocalScalarFromToken -- * * Get the index into the table of compiled locals that corresponds * to a local scalar variable name. * * Results: * Returns the non-negative integer index value into the table of * compiled locals corresponding to a local scalar variable name. * If the arguments passed in do not identify a local scalar variable * then return -1. * * Side effects: * May add an entery into the table of compiled locals. * *---------------------------------------------------------------------- */ int TclLocalScalarFromToken( Tcl_Token *tokenPtr, CompileEnv *envPtr) { int isScalar, index; TclPushVarName(NULL, tokenPtr, envPtr, TCL_NO_ELEMENT, &index, &isScalar); if (!isScalar) { index = -1; } return index; } int TclLocalScalar( const char *bytes, int numBytes, CompileEnv *envPtr) { Tcl_Token token[2] = {{TCL_TOKEN_SIMPLE_WORD, NULL, 0, 1}, {TCL_TOKEN_TEXT, NULL, 0, 0}}; token[1].start = bytes; token[1].size = numBytes; return TclLocalScalarFromToken(token, envPtr); } /* *---------------------------------------------------------------------- * * TclPushVarName -- * * Procedure used in the compiling where pushing a variable name is * necessary (append, lappend, set). * * Results: * The values written to *localIndexPtr and *isScalarPtr signal to * the caller what the instructions emitted by this routine will do: * * *isScalarPtr (*localIndexPtr < 0) * 1 1 Push the varname on the stack. (Stack +1) * 1 0 *localIndexPtr is the index of the compiled * local for this varname. No instructions * emitted. (Stack +0) * 0 1 Push part1 and part2 names of array element * on the stack. (Stack +2) * 0 0 *localIndexPtr is the index of the compiled * local for this array. Element name is pushed * on the stack. (Stack +1) * * Side effects: * Instructions are added to envPtr. * *---------------------------------------------------------------------- */ void TclPushVarName( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Token *varTokenPtr, /* Points to a variable token. */ CompileEnv *envPtr, /* Holds resulting instructions. */ int flags, /* TCL_NO_LARGE_INDEX | TCL_NO_ELEMENT. */ int *localIndexPtr, /* Must not be NULL. */ int *isScalarPtr) /* Must not be NULL. */ { register const char *p; const char *name, *elName; register int i, n; Tcl_Token *elemTokenPtr = NULL; int nameChars, elNameChars, simpleVarName, localIndex; int elemTokenCount = 0, allocedTokens = 0, removedParen = 0; /* * Decide if we can use a frame slot for the var/array name or if we need * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ simpleVarName = 0; name = elName = NULL; nameChars = elNameChars = 0; localIndex = -1; if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { /* * A simple variable name. Divide it up into "name" and "elName" * strings. If it is not a local variable, look it up at runtime. */ simpleVarName = 1; name = varTokenPtr[1].start; nameChars = varTokenPtr[1].size; if (name[nameChars-1] == ')') { /* * last char is ')' => potential array reference. */ for (i=0,p=name ; itype = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; elemTokenPtr->size = elNameChars; elemTokenPtr->numComponents = 0; elemTokenCount = 1; } } } else if (interp && ((n = varTokenPtr->numComponents) > 1) && (varTokenPtr[1].type == TCL_TOKEN_TEXT) && (varTokenPtr[n].type == TCL_TOKEN_TEXT) && (varTokenPtr[n].start[varTokenPtr[n].size - 1] == ')')) { /* * Check for parentheses inside first token. */ simpleVarName = 0; for (i = 0, p = varTokenPtr[1].start; i < varTokenPtr[1].size; i++, p++) { if (*p == '(') { simpleVarName = 1; break; } } if (simpleVarName) { int remainingChars; /* * Check the last token: if it is just ')', do not count it. * Otherwise, remove the ')' and flag so that it is restored at * the end. */ if (varTokenPtr[n].size == 1) { n--; } else { varTokenPtr[n].size--; removedParen = n; } name = varTokenPtr[1].start; nameChars = p - varTokenPtr[1].start; elName = p + 1; remainingChars = (varTokenPtr[2].start - p) - 1; elNameChars = (varTokenPtr[n].start-p) + varTokenPtr[n].size - 1; if (!(flags & TCL_NO_ELEMENT)) { if (remainingChars) { /* * Make a first token with the extra characters in the first * token. */ elemTokenPtr = TclStackAlloc(interp, n * sizeof(Tcl_Token)); allocedTokens = 1; elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; elemTokenPtr->size = remainingChars; elemTokenPtr->numComponents = 0; elemTokenCount = n; /* * Copy the remaining tokens. */ memcpy(elemTokenPtr+1, varTokenPtr+2, (n-1) * sizeof(Tcl_Token)); } else { /* * Use the already available tokens. */ elemTokenPtr = &varTokenPtr[2]; elemTokenCount = n - 1; } } } } if (simpleVarName) { /* * See whether name has any namespace separators (::'s). */ int hasNsQualifiers = 0; for (i = 0, p = name; i < nameChars; i++, p++) { if ((*p == ':') && ((i+1) < nameChars) && (*(p+1) == ':')) { hasNsQualifiers = 1; break; } } /* * Look up the var name's index in the array of local vars in the proc * frame. If retrieving the var's value and it doesn't already exist, * push its name and look it up at runtime. */ if (!hasNsQualifiers) { localIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr); if ((flags & TCL_NO_LARGE_INDEX) && (localIndex > 255)) { /* * We'll push the name. */ localIndex = -1; } } if (interp && localIndex < 0) { PushLiteral(envPtr, name, nameChars); } /* * Compile the element script, if any, and only if not inhibited. [Bug * 3600328] */ if (elName != NULL && !(flags & TCL_NO_ELEMENT)) { if (elNameChars) { TclCompileTokens(interp, elemTokenPtr, elemTokenCount, envPtr); } else { PushStringLiteral(envPtr, ""); } } } else if (interp) { /* * The var name isn't simple: compile and push it. */ CompileTokens(envPtr, varTokenPtr, interp); } if (removedParen) { varTokenPtr[removedParen].size++; } if (allocedTokens) { TclStackFree(interp, elemTokenPtr); } *localIndexPtr = localIndex; *isScalarPtr = (elName == NULL); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclTomMathInterface.c0000644000175000017500000001460112663660065017246 0ustar sergeisergei/* *---------------------------------------------------------------------- * * tclTomMathInterface.c -- * * This file contains procedures that are used as a 'glue' layer between * Tcl and libtommath. * * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tommath.h" MODULE_SCOPE const TclTomMathStubs tclTomMathStubs; /* *---------------------------------------------------------------------- * * TclTommath_Init -- * * Initializes the TclTomMath 'package', which exists as a * placeholder so that the package data can be used to hold * a stub table pointer. * * Results: * Returns a standard Tcl result. * * Side effects: * Installs the stub table for tommath. * *---------------------------------------------------------------------- */ int TclTommath_Init( Tcl_Interp *interp) /* Tcl interpreter */ { /* TIP #268: Full patchlevel instead of just major.minor */ if (Tcl_PkgProvideEx(interp, "tcl::tommath", TCL_PATCH_LEVEL, &tclTomMathStubs) != TCL_OK) { return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclBN_epoch -- * * Return the epoch number of the TclTomMath stubs table * * Results: * Returns an arbitrary integer that does not decrease with * release. Stubs tables with different epochs are incompatible. * *---------------------------------------------------------------------- */ int TclBN_epoch(void) { return TCLTOMMATH_EPOCH; } /* *---------------------------------------------------------------------- * * TclBN_revision -- * * Returns the revision level of the TclTomMath stubs table * * Results: * Returns an arbitrary integer that increases with revisions. * If a client requires a given epoch and revision, any Stubs table * with the same epoch and an equal or higher revision satisfies * the request. * *---------------------------------------------------------------------- */ int TclBN_revision(void) { return TCLTOMMATH_REVISION; } #if 0 /* *---------------------------------------------------------------------- * * TclBNAlloc -- * * Allocate memory for libtommath. * * Results: * Returns a pointer to the allocated block. * * This procedure is a wrapper around Tcl_Alloc, needed because of a * mismatched type signature between Tcl_Alloc and malloc. * *---------------------------------------------------------------------- */ extern void * TclBNAlloc( size_t x) { return (void *) ckalloc((unsigned int) x); } /* *---------------------------------------------------------------------- * * TclBNRealloc -- * * Change the size of an allocated block of memory in libtommath * * Results: * Returns a pointer to the allocated block. * * This procedure is a wrapper around Tcl_Realloc, needed because of a * mismatched type signature between Tcl_Realloc and realloc. * *---------------------------------------------------------------------- */ void * TclBNRealloc( void *p, size_t s) { return (void *) ckrealloc((char *) p, (unsigned int) s); } /* *---------------------------------------------------------------------- * * TclBNFree -- * * Free allocated memory in libtommath. * * Results: * None. * * Side effects: * Memory is freed. * * This function is simply a wrapper around Tcl_Free, needed in libtommath * because of a type mismatch between free and Tcl_Free. * *---------------------------------------------------------------------- */ extern void TclBNFree( void *p) { ckree((char *) p); } #endif /* *---------------------------------------------------------------------- * * TclBNInitBignumFromLong -- * * Allocate and initialize a 'bignum' from a native 'long'. * * Results: * None. * * Side effects: * The 'bignum' is constructed. * *---------------------------------------------------------------------- */ extern void TclBNInitBignumFromLong( mp_int *a, long initVal) { int status; unsigned long v; mp_digit *p; /* * Allocate enough memory to hold the largest possible long */ status = mp_init_size(a, (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1) / DIGIT_BIT); if (status != MP_OKAY) { Tcl_Panic("initialization failure in TclBNInitBignumFromLong"); } /* * Convert arg to sign and magnitude. */ if (initVal < 0) { a->sign = MP_NEG; v = -initVal; } else { a->sign = MP_ZPOS; v = initVal; } /* * Store the magnitude in the bignum. */ p = a->dp; while (v) { *p++ = (mp_digit) (v & MP_MASK); v >>= MP_DIGIT_BIT; } a->used = p - a->dp; } /* *---------------------------------------------------------------------- * * TclBNInitBignumFromWideInt -- * * Allocate and initialize a 'bignum' from a Tcl_WideInt * * Results: * None. * * Side effects: * The 'bignum' is constructed. * *---------------------------------------------------------------------- */ extern void TclBNInitBignumFromWideInt( mp_int *a, /* Bignum to initialize */ Tcl_WideInt v) /* Initial value */ { if (v < (Tcl_WideInt)0) { TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)(-v)); mp_neg(a, a); } else { TclBNInitBignumFromWideUInt(a, (Tcl_WideUInt)v); } } /* *---------------------------------------------------------------------- * * TclBNInitBignumFromWideUInt -- * * Allocate and initialize a 'bignum' from a Tcl_WideUInt * * Results: * None. * * Side effects: * The 'bignum' is constructed. * *---------------------------------------------------------------------- */ extern void TclBNInitBignumFromWideUInt( mp_int *a, /* Bignum to initialize */ Tcl_WideUInt v) /* Initial value */ { int status; mp_digit *p; /* * Allocate enough memory to hold the largest possible Tcl_WideUInt. */ status = mp_init_size(a, (CHAR_BIT * sizeof(Tcl_WideUInt) + DIGIT_BIT - 1) / DIGIT_BIT); if (status != MP_OKAY) { Tcl_Panic("initialization failure in TclBNInitBignumFromWideUInt"); } a->sign = MP_ZPOS; /* * Store the magnitude in the bignum. */ p = a->dp; while (v) { *p++ = (mp_digit) (v & MP_MASK); v >>= MP_DIGIT_BIT; } a->used = p - a->dp; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclIntPlatDecls.h0000644000175000017500000005116612665173571016421 0ustar sergeisergei/* * tclIntPlatDecls.h -- * * This file contains the declarations for all platform dependent * unsupported functions that are exported by the Tcl library. These * interfaces are not guaranteed to remain the same between * versions. Use at your own risk. * * Copyright (c) 1998-1999 by Scriptics Corporation. * All rights reserved. */ #ifndef _TCLINTPLATDECLS #define _TCLINTPLATDECLS #ifdef _WIN32 # define Tcl_DirEntry void # define DIR void #endif #undef TCL_STORAGE_CLASS #ifdef BUILD_tcl # define TCL_STORAGE_CLASS DLLEXPORT #else # ifdef USE_TCL_STUBS # define TCL_STORAGE_CLASS # else # define TCL_STORAGE_CLASS DLLIMPORT # endif #endif /* * WARNING: This file is automatically generated by the tools/genStubs.tcl * script. Any modifications to the function declarations below should be made * in the generic/tclInt.decls script. */ /* !BEGIN!: Do not edit below this line. */ #ifdef __cplusplus extern "C" { #endif /* * Exported function declarations: */ #if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */ /* 0 */ EXTERN void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan); /* 1 */ EXTERN int TclpCloseFile(TclFile file); /* 2 */ EXTERN Tcl_Channel TclpCreateCommandChannel(TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 3 */ EXTERN int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe); /* 4 */ EXTERN int TclpCreateProcess(Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* Slot 5 is reserved */ /* 6 */ EXTERN TclFile TclpMakeFile(Tcl_Channel channel, int direction); /* 7 */ EXTERN TclFile TclpOpenFile(const char *fname, int mode); /* 8 */ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout); /* 9 */ EXTERN TclFile TclpCreateTempFile(const char *contents); /* 10 */ EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir); /* 11 */ EXTERN struct tm * TclpLocaltime_unix(const time_t *clock); /* 12 */ EXTERN struct tm * TclpGmtime_unix(const time_t *clock); /* 13 */ EXTERN char * TclpInetNtoa(struct in_addr addr); /* 14 */ EXTERN int TclUnixCopyFile(const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* Slot 15 is reserved */ /* Slot 16 is reserved */ /* Slot 17 is reserved */ /* Slot 18 is reserved */ /* Slot 19 is reserved */ /* Slot 20 is reserved */ /* Slot 21 is reserved */ /* Slot 22 is reserved */ /* Slot 23 is reserved */ /* Slot 24 is reserved */ /* Slot 25 is reserved */ /* Slot 26 is reserved */ /* Slot 27 is reserved */ /* Slot 28 is reserved */ /* 29 */ EXTERN int TclWinCPUID(unsigned int index, unsigned int *regs); /* 30 */ EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); #endif /* UNIX */ #if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ /* 0 */ EXTERN void TclWinConvertError(DWORD errCode); /* 1 */ EXTERN void TclWinConvertWSAError(DWORD errCode); /* 2 */ EXTERN struct servent * TclWinGetServByName(const char *nm, const char *proto); /* 3 */ EXTERN int TclWinGetSockOpt(SOCKET s, int level, int optname, char *optval, int *optlen); /* 4 */ EXTERN HINSTANCE TclWinGetTclInstance(void); /* 5 */ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout); /* 6 */ EXTERN unsigned short TclWinNToHS(unsigned short ns); /* 7 */ EXTERN int TclWinSetSockOpt(SOCKET s, int level, int optname, const char *optval, int optlen); /* 8 */ EXTERN int TclpGetPid(Tcl_Pid pid); /* 9 */ EXTERN int TclWinGetPlatformId(void); /* 10 */ EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir); /* 11 */ EXTERN void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan); /* 12 */ EXTERN int TclpCloseFile(TclFile file); /* 13 */ EXTERN Tcl_Channel TclpCreateCommandChannel(TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 14 */ EXTERN int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe); /* 15 */ EXTERN int TclpCreateProcess(Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 16 */ EXTERN int TclpIsAtty(int fd); /* 17 */ EXTERN int TclUnixCopyFile(const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 18 */ EXTERN TclFile TclpMakeFile(Tcl_Channel channel, int direction); /* 19 */ EXTERN TclFile TclpOpenFile(const char *fname, int mode); /* 20 */ EXTERN void TclWinAddProcess(HANDLE hProcess, DWORD id); /* 21 */ EXTERN char * TclpInetNtoa(struct in_addr addr); /* 22 */ EXTERN TclFile TclpCreateTempFile(const char *contents); /* Slot 23 is reserved */ /* 24 */ EXTERN char * TclWinNoBackslash(char *path); /* Slot 25 is reserved */ /* 26 */ EXTERN void TclWinSetInterfaces(int wide); /* 27 */ EXTERN void TclWinFlushDirtyChannels(void); /* 28 */ EXTERN void TclWinResetInterfaces(void); /* 29 */ EXTERN int TclWinCPUID(unsigned int index, unsigned int *regs); /* 30 */ EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ /* 0 */ EXTERN void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan); /* 1 */ EXTERN int TclpCloseFile(TclFile file); /* 2 */ EXTERN Tcl_Channel TclpCreateCommandChannel(TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 3 */ EXTERN int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe); /* 4 */ EXTERN int TclpCreateProcess(Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* Slot 5 is reserved */ /* 6 */ EXTERN TclFile TclpMakeFile(Tcl_Channel channel, int direction); /* 7 */ EXTERN TclFile TclpOpenFile(const char *fname, int mode); /* 8 */ EXTERN int TclUnixWaitForFile(int fd, int mask, int timeout); /* 9 */ EXTERN TclFile TclpCreateTempFile(const char *contents); /* 10 */ EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir); /* 11 */ EXTERN struct tm * TclpLocaltime_unix(const time_t *clock); /* 12 */ EXTERN struct tm * TclpGmtime_unix(const time_t *clock); /* 13 */ EXTERN char * TclpInetNtoa(struct in_addr addr); /* 14 */ EXTERN int TclUnixCopyFile(const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 15 */ EXTERN int TclMacOSXGetFileAttribute(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); /* 16 */ EXTERN int TclMacOSXSetFileAttribute(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj *attributePtr); /* 17 */ EXTERN int TclMacOSXCopyFileAttributes(const char *src, const char *dst, const Tcl_StatBuf *statBufPtr); /* 18 */ EXTERN int TclMacOSXMatchType(Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types); /* 19 */ EXTERN void TclMacOSXNotifierAddRunLoopMode( const void *runLoopMode); /* Slot 20 is reserved */ /* Slot 21 is reserved */ /* Slot 22 is reserved */ /* Slot 23 is reserved */ /* Slot 24 is reserved */ /* Slot 25 is reserved */ /* Slot 26 is reserved */ /* Slot 27 is reserved */ /* Slot 28 is reserved */ /* 29 */ EXTERN int TclWinCPUID(unsigned int index, unsigned int *regs); /* 30 */ EXTERN int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); #endif /* MACOSX */ typedef struct TclIntPlatStubs { int magic; void *hooks; #if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 0 */ int (*tclpCloseFile) (TclFile file); /* 1 */ Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 2 */ int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 3 */ int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 4 */ void (*reserved5)(void); TclFile (*tclpMakeFile) (Tcl_Channel channel, int direction); /* 6 */ TclFile (*tclpOpenFile) (const char *fname, int mode); /* 7 */ int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */ TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */ Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */ struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */ struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */ char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */ void (*reserved15)(void); void (*reserved16)(void); void (*reserved17)(void); void (*reserved18)(void); void (*reserved19)(void); void (*reserved20)(void); void (*reserved21)(void); void (*reserved22)(void); void (*reserved23)(void); void (*reserved24)(void); void (*reserved25)(void); void (*reserved26)(void); void (*reserved27)(void); void (*reserved28)(void); int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */ int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */ #endif /* UNIX */ #if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ void (*tclWinConvertError) (DWORD errCode); /* 0 */ void (*tclWinConvertWSAError) (DWORD errCode); /* 1 */ struct servent * (*tclWinGetServByName) (const char *nm, const char *proto); /* 2 */ int (*tclWinGetSockOpt) (SOCKET s, int level, int optname, char *optval, int *optlen); /* 3 */ HINSTANCE (*tclWinGetTclInstance) (void); /* 4 */ int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 5 */ unsigned short (*tclWinNToHS) (unsigned short ns); /* 6 */ int (*tclWinSetSockOpt) (SOCKET s, int level, int optname, const char *optval, int optlen); /* 7 */ int (*tclpGetPid) (Tcl_Pid pid); /* 8 */ int (*tclWinGetPlatformId) (void); /* 9 */ Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 11 */ int (*tclpCloseFile) (TclFile file); /* 12 */ Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 13 */ int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 14 */ int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 15 */ int (*tclpIsAtty) (int fd); /* 16 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 17 */ TclFile (*tclpMakeFile) (Tcl_Channel channel, int direction); /* 18 */ TclFile (*tclpOpenFile) (const char *fname, int mode); /* 19 */ void (*tclWinAddProcess) (HANDLE hProcess, DWORD id); /* 20 */ char * (*tclpInetNtoa) (struct in_addr addr); /* 21 */ TclFile (*tclpCreateTempFile) (const char *contents); /* 22 */ void (*reserved23)(void); char * (*tclWinNoBackslash) (char *path); /* 24 */ void (*reserved25)(void); void (*tclWinSetInterfaces) (int wide); /* 26 */ void (*tclWinFlushDirtyChannels) (void); /* 27 */ void (*tclWinResetInterfaces) (void); /* 28 */ int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */ int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 0 */ int (*tclpCloseFile) (TclFile file); /* 1 */ Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 2 */ int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 3 */ int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 4 */ void (*reserved5)(void); TclFile (*tclpMakeFile) (Tcl_Channel channel, int direction); /* 6 */ TclFile (*tclpOpenFile) (const char *fname, int mode); /* 7 */ int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */ TclFile (*tclpCreateTempFile) (const char *contents); /* 9 */ Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */ struct tm * (*tclpLocaltime_unix) (const time_t *clock); /* 11 */ struct tm * (*tclpGmtime_unix) (const time_t *clock); /* 12 */ char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */ int (*tclMacOSXGetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); /* 15 */ int (*tclMacOSXSetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj *attributePtr); /* 16 */ int (*tclMacOSXCopyFileAttributes) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr); /* 17 */ int (*tclMacOSXMatchType) (Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types); /* 18 */ void (*tclMacOSXNotifierAddRunLoopMode) (const void *runLoopMode); /* 19 */ void (*reserved20)(void); void (*reserved21)(void); void (*reserved22)(void); void (*reserved23)(void); void (*reserved24)(void); void (*reserved25)(void); void (*reserved26)(void); void (*reserved27)(void); void (*reserved28)(void); int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */ int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */ #endif /* MACOSX */ } TclIntPlatStubs; extern const TclIntPlatStubs *tclIntPlatStubsPtr; #ifdef __cplusplus } #endif #if defined(USE_TCL_STUBS) /* * Inline function declarations: */ #if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */ #define TclGetAndDetachPids \ (tclIntPlatStubsPtr->tclGetAndDetachPids) /* 0 */ #define TclpCloseFile \ (tclIntPlatStubsPtr->tclpCloseFile) /* 1 */ #define TclpCreateCommandChannel \ (tclIntPlatStubsPtr->tclpCreateCommandChannel) /* 2 */ #define TclpCreatePipe \ (tclIntPlatStubsPtr->tclpCreatePipe) /* 3 */ #define TclpCreateProcess \ (tclIntPlatStubsPtr->tclpCreateProcess) /* 4 */ /* Slot 5 is reserved */ #define TclpMakeFile \ (tclIntPlatStubsPtr->tclpMakeFile) /* 6 */ #define TclpOpenFile \ (tclIntPlatStubsPtr->tclpOpenFile) /* 7 */ #define TclUnixWaitForFile \ (tclIntPlatStubsPtr->tclUnixWaitForFile) /* 8 */ #define TclpCreateTempFile \ (tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */ #define TclpReaddir \ (tclIntPlatStubsPtr->tclpReaddir) /* 10 */ #define TclpLocaltime_unix \ (tclIntPlatStubsPtr->tclpLocaltime_unix) /* 11 */ #define TclpGmtime_unix \ (tclIntPlatStubsPtr->tclpGmtime_unix) /* 12 */ #define TclpInetNtoa \ (tclIntPlatStubsPtr->tclpInetNtoa) /* 13 */ #define TclUnixCopyFile \ (tclIntPlatStubsPtr->tclUnixCopyFile) /* 14 */ /* Slot 15 is reserved */ /* Slot 16 is reserved */ /* Slot 17 is reserved */ /* Slot 18 is reserved */ /* Slot 19 is reserved */ /* Slot 20 is reserved */ /* Slot 21 is reserved */ /* Slot 22 is reserved */ /* Slot 23 is reserved */ /* Slot 24 is reserved */ /* Slot 25 is reserved */ /* Slot 26 is reserved */ /* Slot 27 is reserved */ /* Slot 28 is reserved */ #define TclWinCPUID \ (tclIntPlatStubsPtr->tclWinCPUID) /* 29 */ #define TclUnixOpenTemporaryFile \ (tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */ #endif /* UNIX */ #if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ #define TclWinConvertError \ (tclIntPlatStubsPtr->tclWinConvertError) /* 0 */ #define TclWinConvertWSAError \ (tclIntPlatStubsPtr->tclWinConvertWSAError) /* 1 */ #define TclWinGetServByName \ (tclIntPlatStubsPtr->tclWinGetServByName) /* 2 */ #define TclWinGetSockOpt \ (tclIntPlatStubsPtr->tclWinGetSockOpt) /* 3 */ #define TclWinGetTclInstance \ (tclIntPlatStubsPtr->tclWinGetTclInstance) /* 4 */ #define TclUnixWaitForFile \ (tclIntPlatStubsPtr->tclUnixWaitForFile) /* 5 */ #define TclWinNToHS \ (tclIntPlatStubsPtr->tclWinNToHS) /* 6 */ #define TclWinSetSockOpt \ (tclIntPlatStubsPtr->tclWinSetSockOpt) /* 7 */ #define TclpGetPid \ (tclIntPlatStubsPtr->tclpGetPid) /* 8 */ #define TclWinGetPlatformId \ (tclIntPlatStubsPtr->tclWinGetPlatformId) /* 9 */ #define TclpReaddir \ (tclIntPlatStubsPtr->tclpReaddir) /* 10 */ #define TclGetAndDetachPids \ (tclIntPlatStubsPtr->tclGetAndDetachPids) /* 11 */ #define TclpCloseFile \ (tclIntPlatStubsPtr->tclpCloseFile) /* 12 */ #define TclpCreateCommandChannel \ (tclIntPlatStubsPtr->tclpCreateCommandChannel) /* 13 */ #define TclpCreatePipe \ (tclIntPlatStubsPtr->tclpCreatePipe) /* 14 */ #define TclpCreateProcess \ (tclIntPlatStubsPtr->tclpCreateProcess) /* 15 */ #define TclpIsAtty \ (tclIntPlatStubsPtr->tclpIsAtty) /* 16 */ #define TclUnixCopyFile \ (tclIntPlatStubsPtr->tclUnixCopyFile) /* 17 */ #define TclpMakeFile \ (tclIntPlatStubsPtr->tclpMakeFile) /* 18 */ #define TclpOpenFile \ (tclIntPlatStubsPtr->tclpOpenFile) /* 19 */ #define TclWinAddProcess \ (tclIntPlatStubsPtr->tclWinAddProcess) /* 20 */ #define TclpInetNtoa \ (tclIntPlatStubsPtr->tclpInetNtoa) /* 21 */ #define TclpCreateTempFile \ (tclIntPlatStubsPtr->tclpCreateTempFile) /* 22 */ /* Slot 23 is reserved */ #define TclWinNoBackslash \ (tclIntPlatStubsPtr->tclWinNoBackslash) /* 24 */ /* Slot 25 is reserved */ #define TclWinSetInterfaces \ (tclIntPlatStubsPtr->tclWinSetInterfaces) /* 26 */ #define TclWinFlushDirtyChannels \ (tclIntPlatStubsPtr->tclWinFlushDirtyChannels) /* 27 */ #define TclWinResetInterfaces \ (tclIntPlatStubsPtr->tclWinResetInterfaces) /* 28 */ #define TclWinCPUID \ (tclIntPlatStubsPtr->tclWinCPUID) /* 29 */ #define TclUnixOpenTemporaryFile \ (tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ #define TclGetAndDetachPids \ (tclIntPlatStubsPtr->tclGetAndDetachPids) /* 0 */ #define TclpCloseFile \ (tclIntPlatStubsPtr->tclpCloseFile) /* 1 */ #define TclpCreateCommandChannel \ (tclIntPlatStubsPtr->tclpCreateCommandChannel) /* 2 */ #define TclpCreatePipe \ (tclIntPlatStubsPtr->tclpCreatePipe) /* 3 */ #define TclpCreateProcess \ (tclIntPlatStubsPtr->tclpCreateProcess) /* 4 */ /* Slot 5 is reserved */ #define TclpMakeFile \ (tclIntPlatStubsPtr->tclpMakeFile) /* 6 */ #define TclpOpenFile \ (tclIntPlatStubsPtr->tclpOpenFile) /* 7 */ #define TclUnixWaitForFile \ (tclIntPlatStubsPtr->tclUnixWaitForFile) /* 8 */ #define TclpCreateTempFile \ (tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */ #define TclpReaddir \ (tclIntPlatStubsPtr->tclpReaddir) /* 10 */ #define TclpLocaltime_unix \ (tclIntPlatStubsPtr->tclpLocaltime_unix) /* 11 */ #define TclpGmtime_unix \ (tclIntPlatStubsPtr->tclpGmtime_unix) /* 12 */ #define TclpInetNtoa \ (tclIntPlatStubsPtr->tclpInetNtoa) /* 13 */ #define TclUnixCopyFile \ (tclIntPlatStubsPtr->tclUnixCopyFile) /* 14 */ #define TclMacOSXGetFileAttribute \ (tclIntPlatStubsPtr->tclMacOSXGetFileAttribute) /* 15 */ #define TclMacOSXSetFileAttribute \ (tclIntPlatStubsPtr->tclMacOSXSetFileAttribute) /* 16 */ #define TclMacOSXCopyFileAttributes \ (tclIntPlatStubsPtr->tclMacOSXCopyFileAttributes) /* 17 */ #define TclMacOSXMatchType \ (tclIntPlatStubsPtr->tclMacOSXMatchType) /* 18 */ #define TclMacOSXNotifierAddRunLoopMode \ (tclIntPlatStubsPtr->tclMacOSXNotifierAddRunLoopMode) /* 19 */ /* Slot 20 is reserved */ /* Slot 21 is reserved */ /* Slot 22 is reserved */ /* Slot 23 is reserved */ /* Slot 24 is reserved */ /* Slot 25 is reserved */ /* Slot 26 is reserved */ /* Slot 27 is reserved */ /* Slot 28 is reserved */ #define TclWinCPUID \ (tclIntPlatStubsPtr->tclWinCPUID) /* 29 */ #define TclUnixOpenTemporaryFile \ (tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */ #endif /* MACOSX */ #endif /* defined(USE_TCL_STUBS) */ /* !END!: Do not edit above this line. */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT #undef TclpLocaltime_unix #undef TclpGmtime_unix #undef TclWinConvertWSAError #define TclWinConvertWSAError TclWinConvertError #undef TclpInetNtoa #define TclpInetNtoa inet_ntoa #if defined(_WIN32) # undef TclWinNToHS # undef TclWinGetServByName # undef TclWinGetSockOpt # undef TclWinSetSockOpt # define TclWinNToHS ntohs # define TclWinGetServByName getservbyname # define TclWinGetSockOpt getsockopt # define TclWinSetSockOpt setsockopt #else # undef TclpGetPid # define TclpGetPid(pid) ((unsigned long) (pid)) #endif #endif /* _TCLINTPLATDECLS */ tcl8.6.5/generic/tclCkalloc.c0000644000175000017500000010015612663660065015425 0ustar sergeisergei/* * tclCkalloc.c -- * * Interface to malloc and free that provides support for debugging * problems involving overwritten, double freeing memory and loss of * memory. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * This code contributed by Karl Lehenbauer and Mark Diekhans */ #include "tclInt.h" #define FALSE 0 #define TRUE 1 #undef Tcl_Alloc #undef Tcl_Free #undef Tcl_Realloc #undef Tcl_AttemptAlloc #undef Tcl_AttemptRealloc #ifdef TCL_MEM_DEBUG /* * One of the following structures is allocated each time the * "memory tag" command is invoked, to hold the current tag. */ typedef struct MemTag { int refCount; /* Number of mem_headers referencing this * tag. */ char string[1]; /* Actual size of string will be as large as * needed for actual tag. This must be the * last field in the structure. */ } MemTag; #define TAG_SIZE(bytesInString) ((unsigned) ((TclOffset(MemTag, string) + 1) + bytesInString)) static MemTag *curTagPtr = NULL;/* Tag to use in all future mem_headers (set * by "memory tag" command). */ /* * One of the following structures is allocated just before each dynamically * allocated chunk of memory, both to record information about the chunk and * to help detect chunk under-runs. */ #define LOW_GUARD_SIZE (8 + (32 - (sizeof(long) + sizeof(int)))%8) struct mem_header { struct mem_header *flink; struct mem_header *blink; MemTag *tagPtr; /* Tag from "memory tag" command; may be * NULL. */ const char *file; long length; int line; unsigned char low_guard[LOW_GUARD_SIZE]; /* Aligns body on 8-byte boundary, plus * provides at least 8 additional guard bytes * to detect underruns. */ char body[1]; /* First byte of client's space. Actual size * of this field will be larger than one. */ }; static struct mem_header *allocHead = NULL; /* List of allocated structures */ #define GUARD_VALUE 0141 /* * The following macro determines the amount of guard space *above* each chunk * of memory. */ #define HIGH_GUARD_SIZE 8 /* * The following macro computes the offset of the "body" field within * mem_header. It is used to get back to the header pointer from the body * pointer that's used by clients. */ #define BODY_OFFSET \ ((size_t) (&((struct mem_header *) 0)->body)) static int total_mallocs = 0; static int total_frees = 0; static size_t current_bytes_malloced = 0; static size_t maximum_bytes_malloced = 0; static int current_malloc_packets = 0; static int maximum_malloc_packets = 0; static int break_on_malloc = 0; static int trace_on_at_malloc = 0; static int alloc_tracing = FALSE; static int init_malloced_bodies = TRUE; #ifdef MEM_VALIDATE static int validate_memory = TRUE; #else static int validate_memory = FALSE; #endif /* * The following variable indicates to TclFinalizeMemorySubsystem() that it * should dump out the state of memory before exiting. If the value is * non-NULL, it gives the name of the file in which to dump memory usage * information. */ char *tclMemDumpFileName = NULL; static char *onExitMemDumpFileName = NULL; static char dumpFile[100]; /* Records where to dump memory allocation * information. */ /* * Mutex to serialize allocations. This is a low-level mutex that must be * explicitly initialized. This is necessary because the self initializing * mutexes use ckalloc... */ static Tcl_Mutex *ckallocMutexPtr; static int ckallocInit = 0; /* * Prototypes for procedures defined in this file: */ static int CheckmemCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[]); static int MemoryCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[]); static void ValidateMemory(struct mem_header *memHeaderP, const char *file, int line, int nukeGuards); /* *---------------------------------------------------------------------- * * TclInitDbCkalloc -- * * Initialize the locks used by the allocator. This is only appropriate * to call in a single threaded environment, such as during * TclInitSubsystems. * *---------------------------------------------------------------------- */ void TclInitDbCkalloc(void) { if (!ckallocInit) { ckallocInit = 1; ckallocMutexPtr = Tcl_GetAllocMutex(); #ifndef TCL_THREADS /* Silence compiler warning */ (void)ckallocMutexPtr; #endif } } /* *---------------------------------------------------------------------- * * TclDumpMemoryInfo -- * * Display the global memory management statistics. * *---------------------------------------------------------------------- */ int TclDumpMemoryInfo( ClientData clientData, int flags) { char buf[1024]; if (clientData == NULL) { return 0; } sprintf(buf, "total mallocs %10d\n" "total frees %10d\n" "current packets allocated %10d\n" "current bytes allocated %10lu\n" "maximum packets allocated %10d\n" "maximum bytes allocated %10lu\n", total_mallocs, total_frees, current_malloc_packets, (unsigned long)current_bytes_malloced, maximum_malloc_packets, (unsigned long)maximum_bytes_malloced); if (flags == 0) { fprintf((FILE *)clientData, "%s", buf); } else { /* Assume objPtr to append to */ Tcl_AppendToObj((Tcl_Obj *) clientData, buf, -1); } return 1; } /* *---------------------------------------------------------------------- * * ValidateMemory -- * * Validate memory guard zones for a particular chunk of allocated * memory. * * Results: * None. * * Side effects: * Prints validation information about the allocated memory to stderr. * *---------------------------------------------------------------------- */ static void ValidateMemory( struct mem_header *memHeaderP, /* Memory chunk to validate */ const char *file, /* File containing the call to * Tcl_ValidateAllMemory */ int line, /* Line number of call to * Tcl_ValidateAllMemory */ int nukeGuards) /* If non-zero, indicates that the memory * guards are to be reset to 0 after they have * been printed */ { unsigned char *hiPtr; size_t idx; int guard_failed = FALSE; int byte; for (idx = 0; idx < LOW_GUARD_SIZE; idx++) { byte = *(memHeaderP->low_guard + idx); if (byte != GUARD_VALUE) { guard_failed = TRUE; fflush(stdout); byte &= 0xff; fprintf(stderr, "low guard byte %d is 0x%x \t%c\n", (int)idx, byte, (isprint(UCHAR(byte)) ? byte : ' ')); /* INTL: bytes */ } } if (guard_failed) { TclDumpMemoryInfo((ClientData) stderr, 0); fprintf(stderr, "low guard failed at %lx, %s %d\n", (long unsigned) memHeaderP->body, file, line); fflush(stderr); /* In case name pointer is bad. */ fprintf(stderr, "%ld bytes allocated at (%s %d)\n", memHeaderP->length, memHeaderP->file, memHeaderP->line); Tcl_Panic("Memory validation failure"); } hiPtr = (unsigned char *)memHeaderP->body + memHeaderP->length; for (idx = 0; idx < HIGH_GUARD_SIZE; idx++) { byte = *(hiPtr + idx); if (byte != GUARD_VALUE) { guard_failed = TRUE; fflush(stdout); byte &= 0xff; fprintf(stderr, "hi guard byte %d is 0x%x \t%c\n", (int)idx, byte, (isprint(UCHAR(byte)) ? byte : ' ')); /* INTL: bytes */ } } if (guard_failed) { TclDumpMemoryInfo((ClientData) stderr, 0); fprintf(stderr, "high guard failed at %lx, %s %d\n", (long unsigned) memHeaderP->body, file, line); fflush(stderr); /* In case name pointer is bad. */ fprintf(stderr, "%ld bytes allocated at (%s %d)\n", memHeaderP->length, memHeaderP->file, memHeaderP->line); Tcl_Panic("Memory validation failure"); } if (nukeGuards) { memset(memHeaderP->low_guard, 0, LOW_GUARD_SIZE); memset(hiPtr, 0, HIGH_GUARD_SIZE); } } /* *---------------------------------------------------------------------- * * Tcl_ValidateAllMemory -- * * Validate memory guard regions for all allocated memory. * * Results: * None. * * Side effects: * Displays memory validation information to stderr. * *---------------------------------------------------------------------- */ void Tcl_ValidateAllMemory( const char *file, /* File from which Tcl_ValidateAllMemory was * called. */ int line) /* Line number of call to * Tcl_ValidateAllMemory */ { struct mem_header *memScanP; if (!ckallocInit) { TclInitDbCkalloc(); } Tcl_MutexLock(ckallocMutexPtr); for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) { ValidateMemory(memScanP, file, line, FALSE); } Tcl_MutexUnlock(ckallocMutexPtr); } /* *---------------------------------------------------------------------- * * Tcl_DumpActiveMemory -- * * Displays all allocated memory to a file; if no filename is given, * information will be written to stderr. * * Results: * Return TCL_ERROR if an error accessing the file occurs, `errno' will * have the file error number left in it. * *---------------------------------------------------------------------- */ int Tcl_DumpActiveMemory( const char *fileName) /* Name of the file to write info to */ { FILE *fileP; struct mem_header *memScanP; char *address; if (fileName == NULL) { fileP = stderr; } else { fileP = fopen(fileName, "w"); if (fileP == NULL) { return TCL_ERROR; } } Tcl_MutexLock(ckallocMutexPtr); for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) { address = &memScanP->body[0]; fprintf(fileP, "%8lx - %8lx %7ld @ %s %d %s", (long unsigned) address, (long unsigned) address + memScanP->length - 1, memScanP->length, memScanP->file, memScanP->line, (memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string); (void) fputc('\n', fileP); } Tcl_MutexUnlock(ckallocMutexPtr); if (fileP != stderr) { fclose(fileP); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_DbCkalloc - debugging ckalloc * * Allocate the requested amount of space plus some extra for guard bands * at both ends of the request, plus a size, panicing if there isn't * enough space, then write in the guard bands and return the address of * the space in the middle that the user asked for. * * The second and third arguments are file and line, these contain the * filename and line number corresponding to the caller. These are sent * by the ckalloc macro; it uses the preprocessor autodefines __FILE__ * and __LINE__. * *---------------------------------------------------------------------- */ char * Tcl_DbCkalloc( unsigned int size, const char *file, int line) { struct mem_header *result = NULL; if (validate_memory) { Tcl_ValidateAllMemory(file, line); } /* Don't let size argument to TclpAlloc overflow */ if (size <= UINT_MAX - HIGH_GUARD_SIZE -sizeof(struct mem_header)) { result = (struct mem_header *) TclpAlloc((unsigned)size + sizeof(struct mem_header) + HIGH_GUARD_SIZE); } if (result == NULL) { fflush(stdout); TclDumpMemoryInfo((ClientData) stderr, 0); Tcl_Panic("unable to alloc %u bytes, %s line %d", size, file, line); } /* * Fill in guard zones and size. Also initialize the contents of the block * with bogus bytes to detect uses of initialized data. Link into * allocated list. */ if (init_malloced_bodies) { memset(result, GUARD_VALUE, size + sizeof(struct mem_header) + HIGH_GUARD_SIZE); } else { memset(result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE); memset(result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE); } if (!ckallocInit) { TclInitDbCkalloc(); } Tcl_MutexLock(ckallocMutexPtr); result->length = size; result->tagPtr = curTagPtr; if (curTagPtr != NULL) { curTagPtr->refCount++; } result->file = file; result->line = line; result->flink = allocHead; result->blink = NULL; if (allocHead != NULL) { allocHead->blink = result; } allocHead = result; total_mallocs++; if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) { (void) fflush(stdout); fprintf(stderr, "reached malloc trace enable point (%d)\n", total_mallocs); fflush(stderr); alloc_tracing = TRUE; trace_on_at_malloc = 0; } if (alloc_tracing) { fprintf(stderr,"ckalloc %lx %u %s %d\n", (long unsigned int) result->body, size, file, line); } if (break_on_malloc && (total_mallocs >= break_on_malloc)) { break_on_malloc = 0; (void) fflush(stdout); Tcl_Panic("reached malloc break limit (%d)", total_mallocs); } current_malloc_packets++; if (current_malloc_packets > maximum_malloc_packets) { maximum_malloc_packets = current_malloc_packets; } current_bytes_malloced += size; if (current_bytes_malloced > maximum_bytes_malloced) { maximum_bytes_malloced = current_bytes_malloced; } Tcl_MutexUnlock(ckallocMutexPtr); return result->body; } char * Tcl_AttemptDbCkalloc( unsigned int size, const char *file, int line) { struct mem_header *result = NULL; if (validate_memory) { Tcl_ValidateAllMemory(file, line); } /* Don't let size argument to TclpAlloc overflow */ if (size <= UINT_MAX - HIGH_GUARD_SIZE - sizeof(struct mem_header)) { result = (struct mem_header *) TclpAlloc((unsigned)size + sizeof(struct mem_header) + HIGH_GUARD_SIZE); } if (result == NULL) { fflush(stdout); TclDumpMemoryInfo((ClientData) stderr, 0); return NULL; } /* * Fill in guard zones and size. Also initialize the contents of the block * with bogus bytes to detect uses of initialized data. Link into * allocated list. */ if (init_malloced_bodies) { memset(result, GUARD_VALUE, size + sizeof(struct mem_header) + HIGH_GUARD_SIZE); } else { memset(result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE); memset(result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE); } if (!ckallocInit) { TclInitDbCkalloc(); } Tcl_MutexLock(ckallocMutexPtr); result->length = size; result->tagPtr = curTagPtr; if (curTagPtr != NULL) { curTagPtr->refCount++; } result->file = file; result->line = line; result->flink = allocHead; result->blink = NULL; if (allocHead != NULL) { allocHead->blink = result; } allocHead = result; total_mallocs++; if (trace_on_at_malloc && (total_mallocs >= trace_on_at_malloc)) { (void) fflush(stdout); fprintf(stderr, "reached malloc trace enable point (%d)\n", total_mallocs); fflush(stderr); alloc_tracing = TRUE; trace_on_at_malloc = 0; } if (alloc_tracing) { fprintf(stderr,"ckalloc %lx %u %s %d\n", (long unsigned int) result->body, size, file, line); } if (break_on_malloc && (total_mallocs >= break_on_malloc)) { break_on_malloc = 0; (void) fflush(stdout); Tcl_Panic("reached malloc break limit (%d)", total_mallocs); } current_malloc_packets++; if (current_malloc_packets > maximum_malloc_packets) { maximum_malloc_packets = current_malloc_packets; } current_bytes_malloced += size; if (current_bytes_malloced > maximum_bytes_malloced) { maximum_bytes_malloced = current_bytes_malloced; } Tcl_MutexUnlock(ckallocMutexPtr); return result->body; } /* *---------------------------------------------------------------------- * * Tcl_DbCkfree - debugging ckfree * * Verify that the low and high guards are intact, and if so then free * the buffer else Tcl_Panic. * * The guards are erased after being checked to catch duplicate frees. * * The second and third arguments are file and line, these contain the * filename and line number corresponding to the caller. These are sent * by the ckfree macro; it uses the preprocessor autodefines __FILE__ and * __LINE__. * *---------------------------------------------------------------------- */ void Tcl_DbCkfree( char *ptr, const char *file, int line) { struct mem_header *memp; if (ptr == NULL) { return; } /* * The following cast is *very* tricky. Must convert the pointer to an * integer before doing arithmetic on it, because otherwise the arithmetic * will be done differently (and incorrectly) on word-addressed machines * such as Crays (will subtract only bytes, even though BODY_OFFSET is in * words on these machines). */ memp = (struct mem_header *) (((size_t) ptr) - BODY_OFFSET); if (alloc_tracing) { fprintf(stderr, "ckfree %lx %ld %s %d\n", (long unsigned int) memp->body, memp->length, file, line); } if (validate_memory) { Tcl_ValidateAllMemory(file, line); } Tcl_MutexLock(ckallocMutexPtr); ValidateMemory(memp, file, line, TRUE); if (init_malloced_bodies) { memset(ptr, GUARD_VALUE, (size_t) memp->length); } total_frees++; current_malloc_packets--; current_bytes_malloced -= memp->length; if (memp->tagPtr != NULL) { memp->tagPtr->refCount--; if ((memp->tagPtr->refCount == 0) && (curTagPtr != memp->tagPtr)) { TclpFree((char *) memp->tagPtr); } } /* * Delink from allocated list */ if (memp->flink != NULL) { memp->flink->blink = memp->blink; } if (memp->blink != NULL) { memp->blink->flink = memp->flink; } if (allocHead == memp) { allocHead = memp->flink; } TclpFree((char *) memp); Tcl_MutexUnlock(ckallocMutexPtr); } /* *-------------------------------------------------------------------- * * Tcl_DbCkrealloc - debugging ckrealloc * * Reallocate a chunk of memory by allocating a new one of the right * size, copying the old data to the new location, and then freeing the * old memory space, using all the memory checking features of this * package. * *-------------------------------------------------------------------- */ char * Tcl_DbCkrealloc( char *ptr, unsigned int size, const char *file, int line) { char *newPtr; unsigned int copySize; struct mem_header *memp; if (ptr == NULL) { return Tcl_DbCkalloc(size, file, line); } /* * See comment from Tcl_DbCkfree before you change the following line. */ memp = (struct mem_header *) (((size_t) ptr) - BODY_OFFSET); copySize = size; if (copySize > (unsigned int) memp->length) { copySize = memp->length; } newPtr = Tcl_DbCkalloc(size, file, line); memcpy(newPtr, ptr, (size_t) copySize); Tcl_DbCkfree(ptr, file, line); return newPtr; } char * Tcl_AttemptDbCkrealloc( char *ptr, unsigned int size, const char *file, int line) { char *newPtr; unsigned int copySize; struct mem_header *memp; if (ptr == NULL) { return Tcl_AttemptDbCkalloc(size, file, line); } /* * See comment from Tcl_DbCkfree before you change the following line. */ memp = (struct mem_header *) (((size_t) ptr) - BODY_OFFSET); copySize = size; if (copySize > (unsigned int) memp->length) { copySize = memp->length; } newPtr = Tcl_AttemptDbCkalloc(size, file, line); if (newPtr == NULL) { return NULL; } memcpy(newPtr, ptr, (size_t) copySize); Tcl_DbCkfree(ptr, file, line); return newPtr; } /* *---------------------------------------------------------------------- * * Tcl_Alloc, et al. -- * * These functions are defined in terms of the debugging versions when * TCL_MEM_DEBUG is set. * * Results: * Same as the debug versions. * * Side effects: * Same as the debug versions. * *---------------------------------------------------------------------- */ char * Tcl_Alloc( unsigned int size) { return Tcl_DbCkalloc(size, "unknown", 0); } char * Tcl_AttemptAlloc( unsigned int size) { return Tcl_AttemptDbCkalloc(size, "unknown", 0); } void Tcl_Free( char *ptr) { Tcl_DbCkfree(ptr, "unknown", 0); } char * Tcl_Realloc( char *ptr, unsigned int size) { return Tcl_DbCkrealloc(ptr, size, "unknown", 0); } char * Tcl_AttemptRealloc( char *ptr, unsigned int size) { return Tcl_AttemptDbCkrealloc(ptr, size, "unknown", 0); } /* *---------------------------------------------------------------------- * * MemoryCmd -- * * Implements the Tcl "memory" command, which provides Tcl-level control * of Tcl memory debugging information. * memory active $file * memory break_on_malloc $count * memory info * memory init on|off * memory onexit $file * memory tag $string * memory trace on|off * memory trace_on_at_malloc $count * memory validate on|off * * Results: * Standard TCL results. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int MemoryCmd( ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[]) { const char *fileName; FILE *fileP; Tcl_DString buffer; int result; size_t len; if (argc < 2) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: should be \"%s option [args..]\"", argv[0])); return TCL_ERROR; } if (strcmp(argv[1], "active") == 0 || strcmp(argv[1], "display") == 0) { if (argc != 3) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: should be \"%s %s file\"", argv[0], argv[1])); return TCL_ERROR; } fileName = Tcl_TranslateFileName(interp, argv[2], &buffer); if (fileName == NULL) { return TCL_ERROR; } result = Tcl_DumpActiveMemory(fileName); Tcl_DStringFree(&buffer); if (result != TCL_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("error accessing %s: %s", argv[2], Tcl_PosixError(interp))); return TCL_ERROR; } return TCL_OK; } if (strcmp(argv[1],"break_on_malloc") == 0) { if (argc != 3) { goto argError; } if (Tcl_GetInt(interp, argv[2], &break_on_malloc) != TCL_OK) { return TCL_ERROR; } return TCL_OK; } if (strcmp(argv[1],"info") == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%-25s %10d\n%-25s %10d\n%-25s %10d\n%-25s %10lu\n%-25s %10d\n%-25s %10lu\n", "total mallocs", total_mallocs, "total frees", total_frees, "current packets allocated", current_malloc_packets, "current bytes allocated", (unsigned long)current_bytes_malloced, "maximum packets allocated", maximum_malloc_packets, "maximum bytes allocated", (unsigned long)maximum_bytes_malloced)); return TCL_OK; } if (strcmp(argv[1], "init") == 0) { if (argc != 3) { goto bad_suboption; } init_malloced_bodies = (strcmp(argv[2],"on") == 0); return TCL_OK; } if (strcmp(argv[1], "objs") == 0) { if (argc != 3) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: should be \"%s objs file\"", argv[0])); return TCL_ERROR; } fileName = Tcl_TranslateFileName(interp, argv[2], &buffer); if (fileName == NULL) { return TCL_ERROR; } fileP = fopen(fileName, "w"); if (fileP == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "cannot open output file: %s", Tcl_PosixError(interp))); return TCL_ERROR; } TclDbDumpActiveObjects(fileP); fclose(fileP); Tcl_DStringFree(&buffer); return TCL_OK; } if (strcmp(argv[1],"onexit") == 0) { if (argc != 3) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: should be \"%s onexit file\"", argv[0])); return TCL_ERROR; } fileName = Tcl_TranslateFileName(interp, argv[2], &buffer); if (fileName == NULL) { return TCL_ERROR; } onExitMemDumpFileName = dumpFile; strcpy(onExitMemDumpFileName,fileName); Tcl_DStringFree(&buffer); return TCL_OK; } if (strcmp(argv[1],"tag") == 0) { if (argc != 3) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: should be \"%s tag string\"", argv[0])); return TCL_ERROR; } if ((curTagPtr != NULL) && (curTagPtr->refCount == 0)) { TclpFree((char *) curTagPtr); } len = strlen(argv[2]); curTagPtr = (MemTag *) TclpAlloc(TAG_SIZE(len)); curTagPtr->refCount = 0; memcpy(curTagPtr->string, argv[2], len + 1); return TCL_OK; } if (strcmp(argv[1],"trace") == 0) { if (argc != 3) { goto bad_suboption; } alloc_tracing = (strcmp(argv[2],"on") == 0); return TCL_OK; } if (strcmp(argv[1],"trace_on_at_malloc") == 0) { if (argc != 3) { goto argError; } if (Tcl_GetInt(interp, argv[2], &trace_on_at_malloc) != TCL_OK) { return TCL_ERROR; } return TCL_OK; } if (strcmp(argv[1],"validate") == 0) { if (argc != 3) { goto bad_suboption; } validate_memory = (strcmp(argv[2],"on") == 0); return TCL_OK; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\": should be active, break_on_malloc, info, " "init, objs, onexit, tag, trace, trace_on_at_malloc, or validate", argv[1])); return TCL_ERROR; argError: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: should be \"%s %s count\"", argv[0], argv[1])); return TCL_ERROR; bad_suboption: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: should be \"%s %s on|off\"", argv[0], argv[1])); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * CheckmemCmd -- * * This is the command procedure for the "checkmem" command, which causes * the application to exit after printing information about memory usage * to the file passed to this command as its first argument. * * Results: * Returns a standard Tcl completion code. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int CheckmemCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Interpreter for evaluation. */ int argc, /* Number of arguments. */ const char *argv[]) /* String values of arguments. */ { if (argc != 2) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: should be \"%s fileName\"", argv[0])); return TCL_ERROR; } tclMemDumpFileName = dumpFile; strcpy(tclMemDumpFileName, argv[1]); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_InitMemory -- * * Create the "memory" and "checkmem" commands in the given interpreter. * * Results: * None. * * Side effects: * New commands are added to the interpreter. * *---------------------------------------------------------------------- */ void Tcl_InitMemory( Tcl_Interp *interp) /* Interpreter in which commands should be * added */ { TclInitDbCkalloc(); Tcl_CreateCommand(interp, "memory", MemoryCmd, NULL, NULL); Tcl_CreateCommand(interp, "checkmem", CheckmemCmd, NULL, NULL); } #else /* TCL_MEM_DEBUG */ /* This is the !TCL_MEM_DEBUG case */ #undef Tcl_InitMemory #undef Tcl_DumpActiveMemory #undef Tcl_ValidateAllMemory /* *---------------------------------------------------------------------- * * Tcl_Alloc -- * * Interface to TclpAlloc when TCL_MEM_DEBUG is disabled. It does check * that memory was actually allocated. * *---------------------------------------------------------------------- */ char * Tcl_Alloc( unsigned int size) { char *result; result = TclpAlloc(size); /* * Most systems will not alloc(0), instead bumping it to one so that NULL * isn't returned. Some systems (AIX, Tru64) will alloc(0) by returning * NULL, so we have to check that the NULL we get is not in response to * alloc(0). * * The ANSI spec actually says that systems either return NULL *or* a * special pointer on failure, but we only check for NULL */ if ((result == NULL) && size) { Tcl_Panic("unable to alloc %u bytes", size); } return result; } char * Tcl_DbCkalloc( unsigned int size, const char *file, int line) { char *result; result = (char *) TclpAlloc(size); if ((result == NULL) && size) { fflush(stdout); Tcl_Panic("unable to alloc %u bytes, %s line %d", size, file, line); } return result; } /* *---------------------------------------------------------------------- * * Tcl_AttemptAlloc -- * * Interface to TclpAlloc when TCL_MEM_DEBUG is disabled. It does not * check that memory was actually allocated. * *---------------------------------------------------------------------- */ char * Tcl_AttemptAlloc( unsigned int size) { char *result; result = TclpAlloc(size); return result; } char * Tcl_AttemptDbCkalloc( unsigned int size, const char *file, int line) { char *result; result = (char *) TclpAlloc(size); return result; } /* *---------------------------------------------------------------------- * * Tcl_Realloc -- * * Interface to TclpRealloc when TCL_MEM_DEBUG is disabled. It does check * that memory was actually allocated. * *---------------------------------------------------------------------- */ char * Tcl_Realloc( char *ptr, unsigned int size) { char *result; result = TclpRealloc(ptr, size); if ((result == NULL) && size) { Tcl_Panic("unable to realloc %u bytes", size); } return result; } char * Tcl_DbCkrealloc( char *ptr, unsigned int size, const char *file, int line) { char *result; result = (char *) TclpRealloc(ptr, size); if ((result == NULL) && size) { fflush(stdout); Tcl_Panic("unable to realloc %u bytes, %s line %d", size, file, line); } return result; } /* *---------------------------------------------------------------------- * * Tcl_AttemptRealloc -- * * Interface to TclpRealloc when TCL_MEM_DEBUG is disabled. It does not * check that memory was actually allocated. * *---------------------------------------------------------------------- */ char * Tcl_AttemptRealloc( char *ptr, unsigned int size) { char *result; result = TclpRealloc(ptr, size); return result; } char * Tcl_AttemptDbCkrealloc( char *ptr, unsigned int size, const char *file, int line) { char *result; result = (char *) TclpRealloc(ptr, size); return result; } /* *---------------------------------------------------------------------- * * Tcl_Free -- * * Interface to TclpFree when TCL_MEM_DEBUG is disabled. Done here rather * in the macro to keep some modules from being compiled with * TCL_MEM_DEBUG enabled and some with it disabled. * *---------------------------------------------------------------------- */ void Tcl_Free( char *ptr) { TclpFree(ptr); } void Tcl_DbCkfree( char *ptr, const char *file, int line) { TclpFree(ptr); } /* *---------------------------------------------------------------------- * * Tcl_InitMemory -- * * Dummy initialization for memory command, which is only available if * TCL_MEM_DEBUG is on. * *---------------------------------------------------------------------- */ /* ARGSUSED */ void Tcl_InitMemory( Tcl_Interp *interp) { } int Tcl_DumpActiveMemory( const char *fileName) { return TCL_OK; } void Tcl_ValidateAllMemory( const char *file, int line) { } int TclDumpMemoryInfo( ClientData clientData, int flags) { return 1; } #endif /* TCL_MEM_DEBUG */ /* *--------------------------------------------------------------------------- * * TclFinalizeMemorySubsystem -- * * This procedure is called to finalize all the structures that are used * by the memory allocator on a per-process basis. * * Results: * None. * * Side effects: * This subsystem is self-initializing, since memory can be allocated * before Tcl is formally initialized. After this call, this subsystem * has been reset to its initial state and is usable again. * *--------------------------------------------------------------------------- */ void TclFinalizeMemorySubsystem(void) { #ifdef TCL_MEM_DEBUG if (tclMemDumpFileName != NULL) { Tcl_DumpActiveMemory(tclMemDumpFileName); } else if (onExitMemDumpFileName != NULL) { Tcl_DumpActiveMemory(onExitMemDumpFileName); } Tcl_MutexLock(ckallocMutexPtr); if (curTagPtr != NULL) { TclpFree((char *) curTagPtr); curTagPtr = NULL; } allocHead = NULL; Tcl_MutexUnlock(ckallocMutexPtr); #endif #if USE_TCLALLOC TclFinalizeAllocSubsystem(); #endif } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * indent-tabs-mode: nil * End: */ tcl8.6.5/generic/tclPort.h0000644000175000017500000000203512663660065015003 0ustar sergeisergei/* * tclPort.h -- * * This header file handles porting issues that occur because * of differences between systems. It reads in platform specific * portability files. * * Copyright (c) 1994-1995 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLPORT #define _TCLPORT #ifdef HAVE_TCL_CONFIG_H #include "tclConfig.h" #endif #if defined(_WIN32) # include "tclWinPort.h" #else # include "tclUnixPort.h" #endif #include "tcl.h" #if !defined(LLONG_MIN) # ifdef TCL_WIDE_INT_IS_LONG # define LLONG_MIN LONG_MIN # else # ifdef LLONG_BIT # define LLONG_MIN ((Tcl_WideInt)(Tcl_LongAsWide(1)<<(LLONG_BIT-1))) # else /* Assume we're on a system with a 64-bit 'long long' type */ # define LLONG_MIN ((Tcl_WideInt)(Tcl_LongAsWide(1)<<63)) # endif # endif /* Assume that if LLONG_MIN is undefined, then so is LLONG_MAX */ # define LLONG_MAX (~LLONG_MIN) #endif #endif /* _TCLPORT */ tcl8.6.5/generic/tclTest.c0000644000175000017500000062325312663660065015004 0ustar sergeisergei/* * tclTest.c -- * * This file contains C command functions for a bunch of additional Tcl * commands that are used for testing out Tcl's C interfaces. These * commands are not normally included in Tcl applications; they're only * used for testing. * * Copyright (c) 1993-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-2000 Ajuba Solutions. * Copyright (c) 2003 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #undef STATIC_BUILD #ifndef USE_TCL_STUBS # define USE_TCL_STUBS #endif #include "tclInt.h" #include "tclOO.h" #include /* * Required for Testregexp*Cmd */ #include "tclRegexp.h" /* * Required for TestlocaleCmd */ #include /* * Required for the TestChannelCmd and TestChannelEventCmd */ #include "tclIO.h" /* * Declare external functions used in Windows tests. */ /* * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the * Tcltest_Init declaration is in the source file itself, which is only * accessed when we are building a library. */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLEXPORT EXTERN int Tcltest_Init(Tcl_Interp *interp); EXTERN int Tcltest_SafeInit(Tcl_Interp *interp); /* * Dynamic string shared by TestdcallCmd and DelCallbackProc; used to collect * the results of the various deletion callbacks. */ static Tcl_DString delString; static Tcl_Interp *delInterp; /* * One of the following structures exists for each asynchronous handler * created by the "testasync" command". */ typedef struct TestAsyncHandler { int id; /* Identifier for this handler. */ Tcl_AsyncHandler handler; /* Tcl's token for the handler. */ char *command; /* Command to invoke when the handler is * invoked. */ struct TestAsyncHandler *nextPtr; /* Next is list of handlers. */ } TestAsyncHandler; TCL_DECLARE_MUTEX(asyncTestMutex) static TestAsyncHandler *firstHandler = NULL; /* * The dynamic string below is used by the "testdstring" command to test the * dynamic string facilities. */ static Tcl_DString dstring; /* * The command trace below is used by the "testcmdtraceCmd" command to test * the command tracing facilities. */ static Tcl_Trace cmdTrace; /* * One of the following structures exists for each command created by * TestdelCmd: */ typedef struct DelCmd { Tcl_Interp *interp; /* Interpreter in which command exists. */ char *deleteCmd; /* Script to execute when command is deleted. * Malloc'ed. */ } DelCmd; /* * The following is used to keep track of an encoding that invokes a Tcl * command. */ typedef struct TclEncoding { Tcl_Interp *interp; char *toUtfCmd; char *fromUtfCmd; } TclEncoding; /* * The counter below is used to determine if the TestsaveresultFree routine * was called for a result. */ static int freeCount; /* * Boolean flag used by the "testsetmainloop" and "testexitmainloop" commands. */ static int exitMainLoop = 0; /* * Event structure used in testing the event queue management procedures. */ typedef struct TestEvent { Tcl_Event header; /* Header common to all events */ Tcl_Interp *interp; /* Interpreter that will handle the event */ Tcl_Obj *command; /* Command to evaluate when the event occurs */ Tcl_Obj *tag; /* Tag for this event used to delete it */ } TestEvent; /* * Simple detach/attach facility for testchannel cut|splice. Allow testing of * channel transfer in core testsuite. */ typedef struct TestChannel { Tcl_Channel chan; /* Detached channel */ struct TestChannel *nextPtr;/* Next in detached channel pool */ } TestChannel; static TestChannel *firstDetached; /* * Forward declarations for procedures defined later in this file: */ static int AsyncHandlerProc(ClientData clientData, Tcl_Interp *interp, int code); #ifdef TCL_THREADS static Tcl_ThreadCreateType AsyncThreadProc(ClientData); #endif static void CleanupTestSetassocdataTests( ClientData clientData, Tcl_Interp *interp); static void CmdDelProc1(ClientData clientData); static void CmdDelProc2(ClientData clientData); static int CmdProc1(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static int CmdProc2(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static void CmdTraceDeleteProc( ClientData clientData, Tcl_Interp *interp, int level, char *command, Tcl_CmdProc *cmdProc, ClientData cmdClientData, int argc, const char *argv[]); static void CmdTraceProc(ClientData clientData, Tcl_Interp *interp, int level, char *command, Tcl_CmdProc *cmdProc, ClientData cmdClientData, int argc, const char *argv[]); static int CreatedCommandProc( ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static int CreatedCommandProc2( ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static void DelCallbackProc(ClientData clientData, Tcl_Interp *interp); static int DelCmdProc(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static void DelDeleteProc(ClientData clientData); static void EncodingFreeProc(ClientData clientData); static int EncodingToUtfProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static int EncodingFromUtfProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static void ExitProcEven(ClientData clientData); static void ExitProcOdd(ClientData clientData); static int GetTimesObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void MainLoop(void); static int NoopCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static int NoopObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ObjTraceProc(ClientData clientData, Tcl_Interp *interp, int level, const char *command, Tcl_Command commandToken, int objc, Tcl_Obj *const objv[]); static void ObjTraceDeleteProc(ClientData clientData); static void PrintParse(Tcl_Interp *interp, Tcl_Parse *parsePtr); static void SpecialFree(char *blockPtr); static int StaticInitProc(Tcl_Interp *interp); static int TestasyncCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestbytestringObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestcmdinfoCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestcmdtokenCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestcmdtraceCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestconcatobjCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestcreatecommandCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestdcallCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestdelCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestdelassocdataCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestdoubledigitsObjCmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj* const objv[]); static int TestdstringCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestencodingObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestevalexObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestevalobjvObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TesteventObjCmd(ClientData unused, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]); static int TesteventProc(Tcl_Event *event, int flags); static int TesteventDeleteProc(Tcl_Event *event, ClientData clientData); static int TestexithandlerCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestexprlongCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestexprlongobjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestexprdoubleCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestexprdoubleobjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestexprparserObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestexprstringCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestfileCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestfilelinkCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestfeventCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestgetassocdataCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestgetintCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestgetplatformCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestgetvarfullnameCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestinterpdeleteCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestlinkCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestlocaleCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestMathFunc(ClientData clientData, Tcl_Interp *interp, Tcl_Value *args, Tcl_Value *resultPtr); static int TestMathFunc2(ClientData clientData, Tcl_Interp *interp, Tcl_Value *args, Tcl_Value *resultPtr); static int TestmainthreadCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestsetmainloopCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestexitmainloopCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestpanicCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestparseargsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestparserObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestparsevarObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestparsevarnameObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestregexpObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestreturnObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void TestregexpXflags(const char *string, int length, int *cflagsPtr, int *eflagsPtr); #ifndef TCL_NO_DEPRECATED static int TestsaveresultCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void TestsaveresultFree(char *blockPtr); #endif /* TCL_NO_DEPRECATED */ static int TestsetassocdataCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestsetCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int Testset2Cmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestseterrorcodeCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestsetobjerrorcodeCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestsetplatformCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TeststaticpkgCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TesttranslatefilenameCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestupvarCmd(ClientData dummy, Tcl_Interp *interp, int argc, const char **argv); static int TestWrongNumArgsObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestGetIndexFromObjStructObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestChannelCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static int TestChannelEventCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); static int TestFilesystemObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestSimpleFilesystemObjCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void TestReport(const char *cmd, Tcl_Obj *arg1, Tcl_Obj *arg2); static Tcl_Obj * TestReportGetNativePath(Tcl_Obj *pathPtr); static Tcl_FSStatProc TestReportStat; static Tcl_FSAccessProc TestReportAccess; static Tcl_FSOpenFileChannelProc TestReportOpenFileChannel; static Tcl_FSMatchInDirectoryProc TestReportMatchInDirectory; static Tcl_FSChdirProc TestReportChdir; static Tcl_FSLstatProc TestReportLstat; static Tcl_FSCopyFileProc TestReportCopyFile; static Tcl_FSDeleteFileProc TestReportDeleteFile; static Tcl_FSRenameFileProc TestReportRenameFile; static Tcl_FSCreateDirectoryProc TestReportCreateDirectory; static Tcl_FSCopyDirectoryProc TestReportCopyDirectory; static Tcl_FSRemoveDirectoryProc TestReportRemoveDirectory; static int TestReportLoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); static Tcl_FSLinkProc TestReportLink; static Tcl_FSFileAttrStringsProc TestReportFileAttrStrings; static Tcl_FSFileAttrsGetProc TestReportFileAttrsGet; static Tcl_FSFileAttrsSetProc TestReportFileAttrsSet; static Tcl_FSUtimeProc TestReportUtime; static Tcl_FSNormalizePathProc TestReportNormalizePath; static Tcl_FSPathInFilesystemProc TestReportInFilesystem; static Tcl_FSFreeInternalRepProc TestReportFreeInternalRep; static Tcl_FSDupInternalRepProc TestReportDupInternalRep; static Tcl_FSStatProc SimpleStat; static Tcl_FSAccessProc SimpleAccess; static Tcl_FSOpenFileChannelProc SimpleOpenFileChannel; static Tcl_FSListVolumesProc SimpleListVolumes; static Tcl_FSPathInFilesystemProc SimplePathInFilesystem; static Tcl_Obj * SimpleRedirect(Tcl_Obj *pathPtr); static Tcl_FSMatchInDirectoryProc SimpleMatchInDirectory; static int TestNumUtfCharsCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestHashSystemHashCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NREUnwind_callback(ClientData data[], Tcl_Interp *interp, int result); static int TestNREUnwind(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestNRELevels(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TestInterpResolverCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); #if defined(HAVE_CPUID) || defined(_WIN32) static int TestcpuidCmd(ClientData dummy, Tcl_Interp* interp, int objc, Tcl_Obj *const objv[]); #endif static const Tcl_Filesystem testReportingFilesystem = { "reporting", sizeof(Tcl_Filesystem), TCL_FILESYSTEM_VERSION_1, TestReportInFilesystem, /* path in */ TestReportDupInternalRep, TestReportFreeInternalRep, NULL, /* native to norm */ NULL, /* convert to native */ TestReportNormalizePath, NULL, /* path type */ NULL, /* separator */ TestReportStat, TestReportAccess, TestReportOpenFileChannel, TestReportMatchInDirectory, TestReportUtime, TestReportLink, NULL /* list volumes */, TestReportFileAttrStrings, TestReportFileAttrsGet, TestReportFileAttrsSet, TestReportCreateDirectory, TestReportRemoveDirectory, TestReportDeleteFile, TestReportCopyFile, TestReportRenameFile, TestReportCopyDirectory, TestReportLstat, (Tcl_FSLoadFileProc *) TestReportLoadFile, NULL /* cwd */, TestReportChdir }; static const Tcl_Filesystem simpleFilesystem = { "simple", sizeof(Tcl_Filesystem), TCL_FILESYSTEM_VERSION_1, SimplePathInFilesystem, NULL, NULL, /* No internal to normalized, since we don't create any * pure 'internal' Tcl_Obj path representations */ NULL, /* No create native rep function, since we don't use it * or 'Tcl_FSNewNativePath' */ NULL, /* Normalize path isn't needed - we assume paths only have * one representation */ NULL, NULL, NULL, SimpleStat, SimpleAccess, SimpleOpenFileChannel, SimpleMatchInDirectory, NULL, /* We choose not to support symbolic links inside our vfs's */ NULL, SimpleListVolumes, NULL, NULL, NULL, NULL, NULL, NULL, /* No copy file - fallback will occur at Tcl level */ NULL, /* No rename file - fallback will occur at Tcl level */ NULL, /* No copy directory - fallback will occur at Tcl level */ NULL, /* Use stat for lstat */ NULL, /* No load - fallback on core implementation */ NULL, /* We don't need a getcwd or chdir - fallback on Tcl's versions */ NULL, NULL }; /* *---------------------------------------------------------------------- * * Tcltest_Init -- * * This procedure performs application-specific initialization. Most * applications, especially those that incorporate additional packages, * will have their own version of this procedure. * * Results: * Returns a standard Tcl completion code, and leaves an error message in * the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- */ int Tcltest_Init( Tcl_Interp *interp) /* Interpreter for application. */ { #ifndef TCL_NO_DEPRECATED Tcl_ValueType t3ArgTypes[2]; #endif /* TCL_NO_DEPRECATED */ Tcl_Obj *listPtr; Tcl_Obj **objv; int objc, index; static const char *const specialOptions[] = { "-appinitprocerror", "-appinitprocdeleteinterp", "-appinitprocclosestderr", "-appinitprocsetrcfile", NULL }; if (Tcl_InitStubs(interp, "8.5", 0) == NULL) { return TCL_ERROR; } if (Tcl_TomMath_InitStubs(interp, "8.5") == NULL) { return TCL_ERROR; } if (Tcl_OOInitStubs(interp) == NULL) { return TCL_ERROR; } /* TIP #268: Full patchlevel instead of just major.minor */ if (Tcl_PkgProvide(interp, "Tcltest", TCL_PATCH_LEVEL) == TCL_ERROR) { return TCL_ERROR; } /* * Create additional commands and math functions for testing Tcl. */ Tcl_CreateObjCommand(interp, "gettimes", GetTimesObjCmd, NULL, NULL); Tcl_CreateCommand(interp, "noop", NoopCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "noop", NoopObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testbytestring", TestbytestringObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testwrongnumargs", TestWrongNumArgsObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testfilesystem", TestFilesystemObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testsimplefilesystem", TestSimpleFilesystemObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testgetindexfromobjstruct", TestGetIndexFromObjStructObjCmd, NULL, NULL); Tcl_CreateCommand(interp, "testasync", TestasyncCmd, NULL, NULL); Tcl_CreateCommand(interp, "testchannel", TestChannelCmd, NULL, NULL); Tcl_CreateCommand(interp, "testchannelevent", TestChannelEventCmd, NULL, NULL); Tcl_CreateCommand(interp, "testcmdtoken", TestcmdtokenCmd, NULL, NULL); Tcl_CreateCommand(interp, "testcmdinfo", TestcmdinfoCmd, NULL, NULL); Tcl_CreateCommand(interp, "testcmdtrace", TestcmdtraceCmd, NULL, NULL); Tcl_CreateCommand(interp, "testconcatobj", TestconcatobjCmd, NULL, NULL); Tcl_CreateCommand(interp, "testcreatecommand", TestcreatecommandCmd, NULL, NULL); Tcl_CreateCommand(interp, "testdcall", TestdcallCmd, NULL, NULL); Tcl_CreateCommand(interp, "testdel", TestdelCmd, NULL, NULL); Tcl_CreateCommand(interp, "testdelassocdata", TestdelassocdataCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testdoubledigits", TestdoubledigitsObjCmd, NULL, NULL); Tcl_DStringInit(&dstring); Tcl_CreateCommand(interp, "testdstring", TestdstringCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testencoding", TestencodingObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testevalex", TestevalexObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testevalobjv", TestevalobjvObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testevent", TesteventObjCmd, NULL, NULL); Tcl_CreateCommand(interp, "testexithandler", TestexithandlerCmd, NULL, NULL); Tcl_CreateCommand(interp, "testexprlong", TestexprlongCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testexprlongobj", TestexprlongobjCmd, NULL, NULL); Tcl_CreateCommand(interp, "testexprdouble", TestexprdoubleCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testexprdoubleobj", TestexprdoubleobjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testexprparser", TestexprparserObjCmd, NULL, NULL); Tcl_CreateCommand(interp, "testexprstring", TestexprstringCmd, NULL, NULL); Tcl_CreateCommand(interp, "testfevent", TestfeventCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testfilelink", TestfilelinkCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testfile", TestfileCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testhashsystemhash", TestHashSystemHashCmd, NULL, NULL); Tcl_CreateCommand(interp, "testgetassocdata", TestgetassocdataCmd, NULL, NULL); Tcl_CreateCommand(interp, "testgetint", TestgetintCmd, NULL, NULL); Tcl_CreateCommand(interp, "testgetplatform", TestgetplatformCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testgetvarfullname", TestgetvarfullnameCmd, NULL, NULL); Tcl_CreateCommand(interp, "testinterpdelete", TestinterpdeleteCmd, NULL, NULL); Tcl_CreateCommand(interp, "testlink", TestlinkCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testlocale", TestlocaleCmd, NULL, NULL); Tcl_CreateCommand(interp, "testpanic", TestpanicCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testparseargs", TestparseargsCmd,NULL,NULL); Tcl_CreateObjCommand(interp, "testparser", TestparserObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testparsevar", TestparsevarObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testparsevarname", TestparsevarnameObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testregexp", TestregexpObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testreturn", TestreturnObjCmd, NULL, NULL); #ifndef TCL_NO_DEPRECATED Tcl_CreateObjCommand(interp, "testsaveresult", TestsaveresultCmd, NULL, NULL); #endif /* TCL_NO_DEPRECATED */ Tcl_CreateCommand(interp, "testsetassocdata", TestsetassocdataCmd, NULL, NULL); Tcl_CreateCommand(interp, "testsetnoerr", TestsetCmd, NULL, NULL); Tcl_CreateCommand(interp, "testseterr", TestsetCmd, (ClientData) TCL_LEAVE_ERR_MSG, NULL); Tcl_CreateCommand(interp, "testset2", Testset2Cmd, (ClientData) TCL_LEAVE_ERR_MSG, NULL); Tcl_CreateCommand(interp, "testseterrorcode", TestseterrorcodeCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testsetobjerrorcode", TestsetobjerrorcodeCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testnumutfchars", TestNumUtfCharsCmd, NULL, NULL); Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd, NULL, NULL); Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd, NULL, NULL); Tcl_CreateCommand(interp, "testtranslatefilename", TesttranslatefilenameCmd, NULL, NULL); Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, NULL, NULL); #ifndef TCL_NO_DEPRECATED Tcl_CreateMathFunc(interp, "T1", 0, NULL, TestMathFunc, (ClientData) 123); Tcl_CreateMathFunc(interp, "T2", 0, NULL, TestMathFunc, (ClientData) 345); #endif /* TCL_NO_DEPRECATED */ Tcl_CreateCommand(interp, "testmainthread", TestmainthreadCmd, NULL, NULL); Tcl_CreateCommand(interp, "testsetmainloop", TestsetmainloopCmd, NULL, NULL); Tcl_CreateCommand(interp, "testexitmainloop", TestexitmainloopCmd, NULL, NULL); #if defined(HAVE_CPUID) || defined(_WIN32) Tcl_CreateObjCommand(interp, "testcpuid", TestcpuidCmd, (ClientData) 0, NULL); #endif #ifndef TCL_NO_DEPRECATED t3ArgTypes[0] = TCL_EITHER; t3ArgTypes[1] = TCL_EITHER; Tcl_CreateMathFunc(interp, "T3", 2, t3ArgTypes, TestMathFunc2, NULL); #endif /* TCL_NO_DEPRECATED */ Tcl_CreateObjCommand(interp, "testnreunwind", TestNREUnwind, NULL, NULL); Tcl_CreateObjCommand(interp, "testnrelevels", TestNRELevels, NULL, NULL); Tcl_CreateObjCommand(interp, "testinterpresolver", TestInterpResolverCmd, NULL, NULL); if (TclObjTest_Init(interp) != TCL_OK) { return TCL_ERROR; } if (Procbodytest_Init(interp) != TCL_OK) { return TCL_ERROR; } #ifdef TCL_THREADS if (TclThread_Init(interp) != TCL_OK) { return TCL_ERROR; } #endif /* * Check for special options used in ../tests/main.test */ listPtr = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY); if (listPtr != NULL) { if (Tcl_ListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) { return TCL_ERROR; } if (objc && (Tcl_GetIndexFromObj(NULL, objv[0], specialOptions, NULL, TCL_EXACT, &index) == TCL_OK)) { switch (index) { case 0: return TCL_ERROR; case 1: Tcl_DeleteInterp(interp); return TCL_ERROR; case 2: { int mode; Tcl_UnregisterChannel(interp, Tcl_GetChannel(interp, "stderr", &mode)); return TCL_ERROR; } case 3: if (objc-1) { Tcl_SetVar2Ex(interp, "tcl_rcFileName", NULL, objv[1], TCL_GLOBAL_ONLY); } return TCL_ERROR; } } } /* * And finally add any platform specific test commands. */ return TclplatformtestInit(interp); } /* *---------------------------------------------------------------------- * * Tcltest_SafeInit -- * * This procedure performs application-specific initialization. Most * applications, especially those that incorporate additional packages, * will have their own version of this procedure. * * Results: * Returns a standard Tcl completion code, and leaves an error message in * the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- */ int Tcltest_SafeInit( Tcl_Interp *interp) /* Interpreter for application. */ { if (Tcl_InitStubs(interp, "8.5", 0) == NULL) { return TCL_ERROR; } return Procbodytest_SafeInit(interp); } /* *---------------------------------------------------------------------- * * TestasyncCmd -- * * This procedure implements the "testasync" command. It is used * to test the asynchronous handler facilities of Tcl. * * Results: * A standard Tcl result. * * Side effects: * Creates, deletes, and invokes handlers. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestasyncCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { TestAsyncHandler *asyncPtr, *prevPtr; int id, code; static int nextId = 1; if (argc < 2) { wrongNumArgs: Tcl_SetResult(interp, "wrong # args", TCL_STATIC); return TCL_ERROR; } if (strcmp(argv[1], "create") == 0) { if (argc != 3) { goto wrongNumArgs; } asyncPtr = ckalloc(sizeof(TestAsyncHandler)); asyncPtr->command = ckalloc(strlen(argv[2]) + 1); strcpy(asyncPtr->command, argv[2]); Tcl_MutexLock(&asyncTestMutex); asyncPtr->id = nextId; nextId++; asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc, INT2PTR(asyncPtr->id)); asyncPtr->nextPtr = firstHandler; firstHandler = asyncPtr; Tcl_MutexUnlock(&asyncTestMutex); Tcl_SetObjResult(interp, Tcl_NewIntObj(asyncPtr->id)); } else if (strcmp(argv[1], "delete") == 0) { if (argc == 2) { Tcl_MutexLock(&asyncTestMutex); while (firstHandler != NULL) { asyncPtr = firstHandler; firstHandler = asyncPtr->nextPtr; Tcl_AsyncDelete(asyncPtr->handler); ckfree(asyncPtr->command); ckfree(asyncPtr); } Tcl_MutexUnlock(&asyncTestMutex); return TCL_OK; } if (argc != 3) { goto wrongNumArgs; } if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) { return TCL_ERROR; } Tcl_MutexLock(&asyncTestMutex); for (prevPtr = NULL, asyncPtr = firstHandler; asyncPtr != NULL; prevPtr = asyncPtr, asyncPtr = asyncPtr->nextPtr) { if (asyncPtr->id != id) { continue; } if (prevPtr == NULL) { firstHandler = asyncPtr->nextPtr; } else { prevPtr->nextPtr = asyncPtr->nextPtr; } Tcl_AsyncDelete(asyncPtr->handler); ckfree(asyncPtr->command); ckfree(asyncPtr); break; } Tcl_MutexUnlock(&asyncTestMutex); } else if (strcmp(argv[1], "mark") == 0) { if (argc != 5) { goto wrongNumArgs; } if ((Tcl_GetInt(interp, argv[2], &id) != TCL_OK) || (Tcl_GetInt(interp, argv[4], &code) != TCL_OK)) { return TCL_ERROR; } Tcl_MutexLock(&asyncTestMutex); for (asyncPtr = firstHandler; asyncPtr != NULL; asyncPtr = asyncPtr->nextPtr) { if (asyncPtr->id == id) { Tcl_AsyncMark(asyncPtr->handler); break; } } Tcl_SetObjResult(interp, Tcl_NewStringObj(argv[3], -1)); Tcl_MutexUnlock(&asyncTestMutex); return code; #ifdef TCL_THREADS } else if (strcmp(argv[1], "marklater") == 0) { if (argc != 3) { goto wrongNumArgs; } if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) { return TCL_ERROR; } Tcl_MutexLock(&asyncTestMutex); for (asyncPtr = firstHandler; asyncPtr != NULL; asyncPtr = asyncPtr->nextPtr) { if (asyncPtr->id == id) { Tcl_ThreadId threadID; if (Tcl_CreateThread(&threadID, AsyncThreadProc, INT2PTR(id), TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS) != TCL_OK) { Tcl_SetResult(interp, "can't create thread", TCL_STATIC); Tcl_MutexUnlock(&asyncTestMutex); return TCL_ERROR; } break; } } Tcl_MutexUnlock(&asyncTestMutex); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create, delete, int, mark, or marklater", NULL); return TCL_ERROR; #else /* !TCL_THREADS */ } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create, delete, int, or mark", NULL); return TCL_ERROR; #endif } return TCL_OK; } static int AsyncHandlerProc( ClientData clientData, /* If of TestAsyncHandler structure. * in global list. */ Tcl_Interp *interp, /* Interpreter in which command was * executed, or NULL. */ int code) /* Current return code from command. */ { TestAsyncHandler *asyncPtr; int id = PTR2INT(clientData); const char *listArgv[4], *cmd; char string[TCL_INTEGER_SPACE]; Tcl_MutexLock(&asyncTestMutex); for (asyncPtr = firstHandler; asyncPtr != NULL; asyncPtr = asyncPtr->nextPtr) { if (asyncPtr->id == id) break; } Tcl_MutexUnlock(&asyncTestMutex); if (!asyncPtr) { /* Woops - this one was deleted between the AsyncMark and now */ return TCL_OK; } TclFormatInt(string, code); listArgv[0] = asyncPtr->command; listArgv[1] = Tcl_GetString(Tcl_GetObjResult(interp)); listArgv[2] = string; listArgv[3] = NULL; cmd = Tcl_Merge(3, listArgv); if (interp != NULL) { code = Tcl_EvalEx(interp, cmd, -1, 0); } else { /* * this should not happen, but by definition of how async handlers are * invoked, it's possible. Better error checking is needed here. */ } ckfree(cmd); return code; } /* *---------------------------------------------------------------------- * * AsyncThreadProc -- * * Delivers an asynchronous event to a handler in another thread. * * Results: * None. * * Side effects: * Invokes Tcl_AsyncMark on the handler * *---------------------------------------------------------------------- */ #ifdef TCL_THREADS static Tcl_ThreadCreateType AsyncThreadProc( ClientData clientData) /* Parameter is the id of a * TestAsyncHandler, defined above. */ { TestAsyncHandler *asyncPtr; int id = PTR2INT(clientData); Tcl_Sleep(1); Tcl_MutexLock(&asyncTestMutex); for (asyncPtr = firstHandler; asyncPtr != NULL; asyncPtr = asyncPtr->nextPtr) { if (asyncPtr->id == id) { Tcl_AsyncMark(asyncPtr->handler); break; } } Tcl_MutexUnlock(&asyncTestMutex); Tcl_ExitThread(TCL_OK); TCL_THREAD_CREATE_RETURN; } #endif /* *---------------------------------------------------------------------- * * TestcmdinfoCmd -- * * This procedure implements the "testcmdinfo" command. It is used to * test Tcl_GetCommandInfo, Tcl_SetCommandInfo, and command creation and * deletion. * * Results: * A standard Tcl result. * * Side effects: * Creates and deletes various commands and modifies their data. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestcmdinfoCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { Tcl_CmdInfo info; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option cmdName\"", NULL); return TCL_ERROR; } if (strcmp(argv[1], "create") == 0) { Tcl_CreateCommand(interp, argv[2], CmdProc1, (ClientData) "original", CmdDelProc1); } else if (strcmp(argv[1], "delete") == 0) { Tcl_DStringInit(&delString); Tcl_DeleteCommand(interp, argv[2]); Tcl_DStringResult(interp, &delString); } else if (strcmp(argv[1], "get") == 0) { if (Tcl_GetCommandInfo(interp, argv[2], &info) ==0) { Tcl_SetResult(interp, "??", TCL_STATIC); return TCL_OK; } if (info.proc == CmdProc1) { Tcl_AppendResult(interp, "CmdProc1", " ", (char *) info.clientData, NULL); } else if (info.proc == CmdProc2) { Tcl_AppendResult(interp, "CmdProc2", " ", (char *) info.clientData, NULL); } else { Tcl_AppendResult(interp, "unknown", NULL); } if (info.deleteProc == CmdDelProc1) { Tcl_AppendResult(interp, " CmdDelProc1", " ", (char *) info.deleteData, NULL); } else if (info.deleteProc == CmdDelProc2) { Tcl_AppendResult(interp, " CmdDelProc2", " ", (char *) info.deleteData, NULL); } else { Tcl_AppendResult(interp, " unknown", NULL); } Tcl_AppendResult(interp, " ", info.namespacePtr->fullName, NULL); if (info.isNativeObjectProc) { Tcl_AppendResult(interp, " nativeObjectProc", NULL); } else { Tcl_AppendResult(interp, " stringProc", NULL); } } else if (strcmp(argv[1], "modify") == 0) { info.proc = CmdProc2; info.clientData = (ClientData) "new_command_data"; info.objProc = NULL; info.objClientData = NULL; info.deleteProc = CmdDelProc2; info.deleteData = (ClientData) "new_delete_data"; if (Tcl_SetCommandInfo(interp, argv[2], &info) == 0) { Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); } else { Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); } } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create, delete, get, or modify", NULL); return TCL_ERROR; } return TCL_OK; } /*ARGSUSED*/ static int CmdProc1( ClientData clientData, /* String to return. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { Tcl_AppendResult(interp, "CmdProc1 ", (char *) clientData, NULL); return TCL_OK; } /*ARGSUSED*/ static int CmdProc2( ClientData clientData, /* String to return. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { Tcl_AppendResult(interp, "CmdProc2 ", (char *) clientData, NULL); return TCL_OK; } static void CmdDelProc1( ClientData clientData) /* String to save. */ { Tcl_DStringInit(&delString); Tcl_DStringAppend(&delString, "CmdDelProc1 ", -1); Tcl_DStringAppend(&delString, (char *) clientData, -1); } static void CmdDelProc2( ClientData clientData) /* String to save. */ { Tcl_DStringInit(&delString); Tcl_DStringAppend(&delString, "CmdDelProc2 ", -1); Tcl_DStringAppend(&delString, (char *) clientData, -1); } /* *---------------------------------------------------------------------- * * TestcmdtokenCmd -- * * This procedure implements the "testcmdtoken" command. It is used to * test Tcl_Command tokens and procedures such as Tcl_GetCommandFullName. * * Results: * A standard Tcl result. * * Side effects: * Creates and deletes various commands and modifies their data. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestcmdtokenCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { Tcl_Command token; int *l; char buf[30]; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option arg\"", NULL); return TCL_ERROR; } if (strcmp(argv[1], "create") == 0) { token = Tcl_CreateCommand(interp, argv[2], CmdProc1, (ClientData) "original", NULL); sprintf(buf, "%p", (void *)token); Tcl_SetResult(interp, buf, TCL_VOLATILE); } else if (strcmp(argv[1], "name") == 0) { Tcl_Obj *objPtr; if (sscanf(argv[2], "%p", &l) != 1) { Tcl_AppendResult(interp, "bad command token \"", argv[2], "\"", NULL); return TCL_ERROR; } objPtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, (Tcl_Command) l, objPtr); Tcl_AppendElement(interp, Tcl_GetCommandName(interp, (Tcl_Command) l)); Tcl_AppendElement(interp, Tcl_GetString(objPtr)); Tcl_DecrRefCount(objPtr); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create or name", NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TestcmdtraceCmd -- * * This procedure implements the "testcmdtrace" command. It is used * to test Tcl_CreateTrace and Tcl_DeleteTrace. * * Results: * A standard Tcl result. * * Side effects: * Creates and deletes a command trace, and tests the invocation of * a procedure by the command trace. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestcmdtraceCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { Tcl_DString buffer; int result; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option script\"", NULL); return TCL_ERROR; } if (strcmp(argv[1], "tracetest") == 0) { Tcl_DStringInit(&buffer); cmdTrace = Tcl_CreateTrace(interp, 50000, CmdTraceProc, &buffer); result = Tcl_EvalEx(interp, argv[2], -1, 0); if (result == TCL_OK) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL); } Tcl_DeleteTrace(interp, cmdTrace); Tcl_DStringFree(&buffer); } else if (strcmp(argv[1], "deletetest") == 0) { /* * Create a command trace then eval a script to check whether it is * called. Note that this trace procedure removes itself as a further * check of the robustness of the trace proc calling code in * TclNRExecuteByteCode. */ cmdTrace = Tcl_CreateTrace(interp, 50000, CmdTraceDeleteProc, NULL); Tcl_EvalEx(interp, argv[2], -1, 0); } else if (strcmp(argv[1], "leveltest") == 0) { Interp *iPtr = (Interp *) interp; Tcl_DStringInit(&buffer); cmdTrace = Tcl_CreateTrace(interp, iPtr->numLevels + 4, CmdTraceProc, &buffer); result = Tcl_EvalEx(interp, argv[2], -1, 0); if (result == TCL_OK) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL); } Tcl_DeleteTrace(interp, cmdTrace); Tcl_DStringFree(&buffer); } else if (strcmp(argv[1], "resulttest") == 0) { /* Create an object-based trace, then eval a script. This is used * to test return codes other than TCL_OK from the trace engine. */ static int deleteCalled; deleteCalled = 0; cmdTrace = Tcl_CreateObjTrace(interp, 50000, TCL_ALLOW_INLINE_COMPILATION, ObjTraceProc, (ClientData) &deleteCalled, ObjTraceDeleteProc); result = Tcl_Eval(interp, argv[2]); Tcl_DeleteTrace(interp, cmdTrace); if (!deleteCalled) { Tcl_SetResult(interp, "Delete wasn't called", TCL_STATIC); return TCL_ERROR; } else { return result; } } else if (strcmp(argv[1], "doubletest") == 0) { Tcl_Trace t1, t2; Tcl_DStringInit(&buffer); t1 = Tcl_CreateTrace(interp, 1, CmdTraceProc, &buffer); t2 = Tcl_CreateTrace(interp, 50000, CmdTraceProc, &buffer); result = Tcl_Eval(interp, argv[2]); if (result == TCL_OK) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL); } Tcl_DeleteTrace(interp, t2); Tcl_DeleteTrace(interp, t1); Tcl_DStringFree(&buffer); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be tracetest, deletetest, doubletest or resulttest", NULL); return TCL_ERROR; } return TCL_OK; } static void CmdTraceProc( ClientData clientData, /* Pointer to buffer in which the * command and arguments are appended. * Accumulates test result. */ Tcl_Interp *interp, /* Current interpreter. */ int level, /* Current trace level. */ char *command, /* The command being traced (after * substitutions). */ Tcl_CmdProc *cmdProc, /* Points to command's command procedure. */ ClientData cmdClientData, /* Client data associated with command * procedure. */ int argc, /* Number of arguments. */ const char *argv[]) /* Argument strings. */ { Tcl_DString *bufPtr = (Tcl_DString *) clientData; int i; Tcl_DStringAppendElement(bufPtr, command); Tcl_DStringStartSublist(bufPtr); for (i = 0; i < argc; i++) { Tcl_DStringAppendElement(bufPtr, argv[i]); } Tcl_DStringEndSublist(bufPtr); } static void CmdTraceDeleteProc( ClientData clientData, /* Unused. */ Tcl_Interp *interp, /* Current interpreter. */ int level, /* Current trace level. */ char *command, /* The command being traced (after * substitutions). */ Tcl_CmdProc *cmdProc, /* Points to command's command procedure. */ ClientData cmdClientData, /* Client data associated with command * procedure. */ int argc, /* Number of arguments. */ const char *argv[]) /* Argument strings. */ { /* * Remove ourselves to test whether calling Tcl_DeleteTrace within a trace * callback causes the for loop in TclNRExecuteByteCode that calls traces to * reference freed memory. */ Tcl_DeleteTrace(interp, cmdTrace); } static int ObjTraceProc( ClientData clientData, /* unused */ Tcl_Interp *interp, /* Tcl interpreter */ int level, /* Execution level */ const char *command, /* Command being executed */ Tcl_Command token, /* Command information */ int objc, /* Parameter count */ Tcl_Obj *const objv[]) /* Parameter list */ { const char *word = Tcl_GetString(objv[0]); if (!strcmp(word, "Error")) { Tcl_SetObjResult(interp, Tcl_NewStringObj(command, -1)); return TCL_ERROR; } else if (!strcmp(word, "Break")) { return TCL_BREAK; } else if (!strcmp(word, "Continue")) { return TCL_CONTINUE; } else if (!strcmp(word, "Return")) { return TCL_RETURN; } else if (!strcmp(word, "OtherStatus")) { return 6; } else { return TCL_OK; } } static void ObjTraceDeleteProc( ClientData clientData) { int *intPtr = (int *) clientData; *intPtr = 1; /* Record that the trace was deleted */ } /* *---------------------------------------------------------------------- * * TestcreatecommandCmd -- * * This procedure implements the "testcreatecommand" command. It is used * to test that the Tcl_CreateCommand creates a new command in the * namespace specified as part of its name, if any. It also checks that * the namespace code ignore single ":"s in the middle or end of a * command name. * * Results: * A standard Tcl result. * * Side effects: * Creates and deletes two commands ("test_ns_basic::createdcommand" * and "value:at:"). * *---------------------------------------------------------------------- */ static int TestcreatecommandCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { if (argc != 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option\"", NULL); return TCL_ERROR; } if (strcmp(argv[1], "create") == 0) { Tcl_CreateCommand(interp, "test_ns_basic::createdcommand", CreatedCommandProc, NULL, NULL); } else if (strcmp(argv[1], "delete") == 0) { Tcl_DeleteCommand(interp, "test_ns_basic::createdcommand"); } else if (strcmp(argv[1], "create2") == 0) { Tcl_CreateCommand(interp, "value:at:", CreatedCommandProc2, NULL, NULL); } else if (strcmp(argv[1], "delete2") == 0) { Tcl_DeleteCommand(interp, "value:at:"); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create, delete, create2, or delete2", NULL); return TCL_ERROR; } return TCL_OK; } static int CreatedCommandProc( ClientData clientData, /* String to return. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { Tcl_CmdInfo info; int found; found = Tcl_GetCommandInfo(interp, "test_ns_basic::createdcommand", &info); if (!found) { Tcl_AppendResult(interp, "CreatedCommandProc could not get command info for test_ns_basic::createdcommand", NULL); return TCL_ERROR; } Tcl_AppendResult(interp, "CreatedCommandProc in ", info.namespacePtr->fullName, NULL); return TCL_OK; } static int CreatedCommandProc2( ClientData clientData, /* String to return. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { Tcl_CmdInfo info; int found; found = Tcl_GetCommandInfo(interp, "value:at:", &info); if (!found) { Tcl_AppendResult(interp, "CreatedCommandProc2 could not get command info for test_ns_basic::createdcommand", NULL); return TCL_ERROR; } Tcl_AppendResult(interp, "CreatedCommandProc2 in ", info.namespacePtr->fullName, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestdcallCmd -- * * This procedure implements the "testdcall" command. It is used * to test Tcl_CallWhenDeleted. * * Results: * A standard Tcl result. * * Side effects: * Creates and deletes interpreters. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestdcallCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { int i, id; delInterp = Tcl_CreateInterp(); Tcl_DStringInit(&delString); for (i = 1; i < argc; i++) { if (Tcl_GetInt(interp, argv[i], &id) != TCL_OK) { return TCL_ERROR; } if (id < 0) { Tcl_DontCallWhenDeleted(delInterp, DelCallbackProc, (ClientData) INT2PTR(-id)); } else { Tcl_CallWhenDeleted(delInterp, DelCallbackProc, (ClientData) INT2PTR(id)); } } Tcl_DeleteInterp(delInterp); Tcl_DStringResult(interp, &delString); return TCL_OK; } /* * The deletion callback used by TestdcallCmd: */ static void DelCallbackProc( ClientData clientData, /* Numerical value to append to delString. */ Tcl_Interp *interp) /* Interpreter being deleted. */ { int id = PTR2INT(clientData); char buffer[TCL_INTEGER_SPACE]; TclFormatInt(buffer, id); Tcl_DStringAppendElement(&delString, buffer); if (interp != delInterp) { Tcl_DStringAppendElement(&delString, "bogus interpreter argument!"); } } /* *---------------------------------------------------------------------- * * TestdelCmd -- * * This procedure implements the "testdel" command. It is used * to test calling of command deletion callbacks. * * Results: * A standard Tcl result. * * Side effects: * Creates a command. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestdelCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { DelCmd *dPtr; Tcl_Interp *slave; if (argc != 4) { Tcl_SetResult(interp, "wrong # args", TCL_STATIC); return TCL_ERROR; } slave = Tcl_GetSlave(interp, argv[1]); if (slave == NULL) { return TCL_ERROR; } dPtr = ckalloc(sizeof(DelCmd)); dPtr->interp = interp; dPtr->deleteCmd = ckalloc(strlen(argv[3]) + 1); strcpy(dPtr->deleteCmd, argv[3]); Tcl_CreateCommand(slave, argv[2], DelCmdProc, (ClientData) dPtr, DelDeleteProc); return TCL_OK; } static int DelCmdProc( ClientData clientData, /* String result to return. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { DelCmd *dPtr = (DelCmd *) clientData; Tcl_AppendResult(interp, dPtr->deleteCmd, NULL); ckfree(dPtr->deleteCmd); ckfree(dPtr); return TCL_OK; } static void DelDeleteProc( ClientData clientData) /* String command to evaluate. */ { DelCmd *dPtr = clientData; Tcl_Eval(dPtr->interp, dPtr->deleteCmd); Tcl_ResetResult(dPtr->interp); ckfree(dPtr->deleteCmd); ckfree(dPtr); } /* *---------------------------------------------------------------------- * * TestdelassocdataCmd -- * * This procedure implements the "testdelassocdata" command. It is used * to test Tcl_DeleteAssocData. * * Results: * A standard Tcl result. * * Side effects: * Deletes an association between a key and associated data from an * interpreter. * *---------------------------------------------------------------------- */ static int TestdelassocdataCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " data_key\"", NULL); return TCL_ERROR; } Tcl_DeleteAssocData(interp, argv[1]); return TCL_OK; } /* *----------------------------------------------------------------------------- * * TestdoubledigitsCmd -- * * This procedure implements the 'testdoubledigits' command. It is * used to test the low-level floating-point formatting primitives * in Tcl. * * Usage: * testdoubledigits fpval ndigits type ?shorten" * * Parameters: * fpval - Floating-point value to format. * ndigits - Digit count to request from Tcl_DoubleDigits * type - One of 'shortest', 'Steele', 'e', 'f' * shorten - Indicates that the 'shorten' flag should be passed in. * *----------------------------------------------------------------------------- */ static int TestdoubledigitsObjCmd(ClientData unused, /* NULL */ Tcl_Interp* interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj* const objv[]) /* Parameter vector */ { static const char* options[] = { "shortest", "Steele", "e", "f", NULL }; static const int types[] = { TCL_DD_SHORTEST, TCL_DD_STEELE, TCL_DD_E_FORMAT, TCL_DD_F_FORMAT }; const Tcl_ObjType* doubleType; double d; int status; int ndigits; int type; int decpt; int signum; char* str; char* endPtr; Tcl_Obj* strObj; Tcl_Obj* retval; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 1, objv, "fpval ndigits type ?shorten?"); return TCL_ERROR; } status = Tcl_GetDoubleFromObj(interp, objv[1], &d); if (status != TCL_OK) { doubleType = Tcl_GetObjType("double"); if (objv[1]->typePtr == doubleType || TclIsNaN(objv[1]->internalRep.doubleValue)) { status = TCL_OK; memcpy(&d, &(objv[1]->internalRep.doubleValue), sizeof(double)); } } if (status != TCL_OK || Tcl_GetIntFromObj(interp, objv[2], &ndigits) != TCL_OK || Tcl_GetIndexFromObj(interp, objv[3], options, "conversion type", TCL_EXACT, &type) != TCL_OK) { fprintf(stderr, "bad value? %g\n", d); return TCL_ERROR; } type = types[type]; if (objc > 4) { if (strcmp(Tcl_GetString(objv[4]), "shorten")) { Tcl_SetObjResult(interp, Tcl_NewStringObj("bad flag", -1)); return TCL_ERROR; } type |= TCL_DD_SHORTEN_FLAG; } str = TclDoubleDigits(d, ndigits, type, &decpt, &signum, &endPtr); strObj = Tcl_NewStringObj(str, endPtr-str); ckfree(str); retval = Tcl_NewListObj(1, &strObj); Tcl_ListObjAppendElement(NULL, retval, Tcl_NewIntObj(decpt)); strObj = Tcl_NewStringObj(signum ? "-" : "+", 1); Tcl_ListObjAppendElement(NULL, retval, strObj); Tcl_SetObjResult(interp, retval); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestdstringCmd -- * * This procedure implements the "testdstring" command. It is used * to test the dynamic string facilities of Tcl. * * Results: * A standard Tcl result. * * Side effects: * Creates, deletes, and invokes handlers. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestdstringCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { int count; if (argc < 2) { wrongNumArgs: Tcl_SetResult(interp, "wrong # args", TCL_STATIC); return TCL_ERROR; } if (strcmp(argv[1], "append") == 0) { if (argc != 4) { goto wrongNumArgs; } if (Tcl_GetInt(interp, argv[3], &count) != TCL_OK) { return TCL_ERROR; } Tcl_DStringAppend(&dstring, argv[2], count); } else if (strcmp(argv[1], "element") == 0) { if (argc != 3) { goto wrongNumArgs; } Tcl_DStringAppendElement(&dstring, argv[2]); } else if (strcmp(argv[1], "end") == 0) { if (argc != 2) { goto wrongNumArgs; } Tcl_DStringEndSublist(&dstring); } else if (strcmp(argv[1], "free") == 0) { if (argc != 2) { goto wrongNumArgs; } Tcl_DStringFree(&dstring); } else if (strcmp(argv[1], "get") == 0) { if (argc != 2) { goto wrongNumArgs; } Tcl_SetResult(interp, Tcl_DStringValue(&dstring), TCL_VOLATILE); } else if (strcmp(argv[1], "gresult") == 0) { if (argc != 3) { goto wrongNumArgs; } if (strcmp(argv[2], "staticsmall") == 0) { Tcl_SetResult(interp, "short", TCL_STATIC); } else if (strcmp(argv[2], "staticlarge") == 0) { Tcl_SetResult(interp, "first0 first1 first2 first3 first4 first5 first6 first7 first8 first9\nsecond0 second1 second2 second3 second4 second5 second6 second7 second8 second9\nthird0 third1 third2 third3 third4 third5 third6 third7 third8 third9\nfourth0 fourth1 fourth2 fourth3 fourth4 fourth5 fourth6 fourth7 fourth8 fourth9\nfifth0 fifth1 fifth2 fifth3 fifth4 fifth5 fifth6 fifth7 fifth8 fifth9\nsixth0 sixth1 sixth2 sixth3 sixth4 sixth5 sixth6 sixth7 sixth8 sixth9\nseventh0 seventh1 seventh2 seventh3 seventh4 seventh5 seventh6 seventh7 seventh8 seventh9\n", TCL_STATIC); } else if (strcmp(argv[2], "free") == 0) { char *s = ckalloc(100); strcpy(s, "This is a malloc-ed string"); Tcl_SetResult(interp, s, TCL_DYNAMIC); } else if (strcmp(argv[2], "special") == 0) { char *s = (char*)ckalloc(100) + 16; strcpy(s, "This is a specially-allocated string"); Tcl_SetResult(interp, s, SpecialFree); } else { Tcl_AppendResult(interp, "bad gresult option \"", argv[2], "\": must be staticsmall, staticlarge, free, or special", NULL); return TCL_ERROR; } Tcl_DStringGetResult(interp, &dstring); } else if (strcmp(argv[1], "length") == 0) { if (argc != 2) { goto wrongNumArgs; } Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_DStringLength(&dstring))); } else if (strcmp(argv[1], "result") == 0) { if (argc != 2) { goto wrongNumArgs; } Tcl_DStringResult(interp, &dstring); } else if (strcmp(argv[1], "trunc") == 0) { if (argc != 3) { goto wrongNumArgs; } if (Tcl_GetInt(interp, argv[2], &count) != TCL_OK) { return TCL_ERROR; } Tcl_DStringSetLength(&dstring, count); } else if (strcmp(argv[1], "start") == 0) { if (argc != 2) { goto wrongNumArgs; } Tcl_DStringStartSublist(&dstring); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be append, element, end, free, get, length, " "result, trunc, or start", NULL); return TCL_ERROR; } return TCL_OK; } /* * The procedure below is used as a special freeProc to test how well * Tcl_DStringGetResult handles freeProc's other than free. */ static void SpecialFree(blockPtr) char *blockPtr; /* Block to free. */ { ckfree(blockPtr - 16); } /* *---------------------------------------------------------------------- * * TestencodingCmd -- * * This procedure implements the "testencoding" command. It is used * to test the encoding package. * * Results: * A standard Tcl result. * * Side effects: * Load encodings. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestencodingObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Encoding encoding; int index, length; const char *string; TclEncoding *encodingPtr; static const char *const optionStrings[] = { "create", "delete", NULL }; enum options { ENC_CREATE, ENC_DELETE }; if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { case ENC_CREATE: { Tcl_EncodingType type; if (objc != 5) { return TCL_ERROR; } encodingPtr = ckalloc(sizeof(TclEncoding)); encodingPtr->interp = interp; string = Tcl_GetStringFromObj(objv[3], &length); encodingPtr->toUtfCmd = ckalloc(length + 1); memcpy(encodingPtr->toUtfCmd, string, (unsigned) length + 1); string = Tcl_GetStringFromObj(objv[4], &length); encodingPtr->fromUtfCmd = ckalloc(length + 1); memcpy(encodingPtr->fromUtfCmd, string, (unsigned) (length + 1)); string = Tcl_GetStringFromObj(objv[2], &length); type.encodingName = string; type.toUtfProc = EncodingToUtfProc; type.fromUtfProc = EncodingFromUtfProc; type.freeProc = EncodingFreeProc; type.clientData = (ClientData) encodingPtr; type.nullSize = 1; Tcl_CreateEncoding(&type); break; } case ENC_DELETE: if (objc != 3) { return TCL_ERROR; } encoding = Tcl_GetEncoding(NULL, Tcl_GetString(objv[2])); Tcl_FreeEncoding(encoding); Tcl_FreeEncoding(encoding); break; } return TCL_OK; } static int EncodingToUtfProc( ClientData clientData, /* TclEncoding structure. */ const char *src, /* Source string in specified encoding. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ Tcl_EncodingState *statePtr,/* Current state. */ char *dst, /* Output buffer. */ int dstLen, /* The maximum length of output buffer. */ int *srcReadPtr, /* Filled with number of bytes read. */ int *dstWrotePtr, /* Filled with number of bytes stored. */ int *dstCharsPtr) /* Filled with number of chars stored. */ { int len; TclEncoding *encodingPtr; encodingPtr = (TclEncoding *) clientData; Tcl_EvalEx(encodingPtr->interp,encodingPtr->toUtfCmd,-1,TCL_EVAL_GLOBAL); len = strlen(Tcl_GetStringResult(encodingPtr->interp)); if (len > dstLen) { len = dstLen; } memcpy(dst, Tcl_GetStringResult(encodingPtr->interp), (unsigned) len); Tcl_ResetResult(encodingPtr->interp); *srcReadPtr = srcLen; *dstWrotePtr = len; *dstCharsPtr = len; return TCL_OK; } static int EncodingFromUtfProc( ClientData clientData, /* TclEncoding structure. */ const char *src, /* Source string in specified encoding. */ int srcLen, /* Source string length in bytes. */ int flags, /* Conversion control flags. */ Tcl_EncodingState *statePtr,/* Current state. */ char *dst, /* Output buffer. */ int dstLen, /* The maximum length of output buffer. */ int *srcReadPtr, /* Filled with number of bytes read. */ int *dstWrotePtr, /* Filled with number of bytes stored. */ int *dstCharsPtr) /* Filled with number of chars stored. */ { int len; TclEncoding *encodingPtr; encodingPtr = (TclEncoding *) clientData; Tcl_EvalEx(encodingPtr->interp, encodingPtr->fromUtfCmd,-1,TCL_EVAL_GLOBAL); len = strlen(Tcl_GetStringResult(encodingPtr->interp)); if (len > dstLen) { len = dstLen; } memcpy(dst, Tcl_GetStringResult(encodingPtr->interp), (unsigned) len); Tcl_ResetResult(encodingPtr->interp); *srcReadPtr = srcLen; *dstWrotePtr = len; *dstCharsPtr = len; return TCL_OK; } static void EncodingFreeProc( ClientData clientData) /* ClientData associated with type. */ { TclEncoding *encodingPtr = clientData; ckfree(encodingPtr->toUtfCmd); ckfree(encodingPtr->fromUtfCmd); ckfree(encodingPtr); } /* *---------------------------------------------------------------------- * * TestevalexObjCmd -- * * This procedure implements the "testevalex" command. It is * used to test Tcl_EvalEx. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestevalexObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int length, flags; const char *script; flags = 0; if (objc == 3) { const char *global = Tcl_GetStringFromObj(objv[2], &length); if (strcmp(global, "global") != 0) { Tcl_AppendResult(interp, "bad value \"", global, "\": must be global", NULL); return TCL_ERROR; } flags = TCL_EVAL_GLOBAL; } else if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "script ?global?"); return TCL_ERROR; } script = Tcl_GetStringFromObj(objv[1], &length); return Tcl_EvalEx(interp, script, length, flags); } /* *---------------------------------------------------------------------- * * TestevalobjvObjCmd -- * * This procedure implements the "testevalobjv" command. It is * used to test Tcl_EvalObjv. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestevalobjvObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int evalGlobal; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "global word ?word ...?"); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[1], &evalGlobal) != TCL_OK) { return TCL_ERROR; } return Tcl_EvalObjv(interp, objc-2, objv+2, (evalGlobal) ? TCL_EVAL_GLOBAL : 0); } /* *---------------------------------------------------------------------- * * TesteventObjCmd -- * * This procedure implements a 'testevent' command. The command * is used to test event queue management. * * The command takes two forms: * - testevent queue name position script * Queues an event at the given position in the queue, and * associates a given name with it (the same name may be * associated with multiple events). When the event comes * to the head of the queue, executes the given script at * global level in the current interp. The position may be * one of 'head', 'tail' or 'mark'. * - testevent delete name * Deletes any events associated with the given name from * the queue. * * Return value: * Returns a standard Tcl result. * * Side effects: * Manipulates the event queue as directed. * *---------------------------------------------------------------------- */ static int TesteventObjCmd( ClientData unused, /* Not used */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const objv[]) /* Parameter vector */ { static const char *const subcommands[] = { /* Possible subcommands */ "queue", "delete", NULL }; int subCmdIndex; /* Index of the chosen subcommand */ static const char *const positions[] = { /* Possible queue positions */ "head", "tail", "mark", NULL }; int posIndex; /* Index of the chosen position */ static const Tcl_QueuePosition posNum[] = { /* Interpretation of the chosen position */ TCL_QUEUE_HEAD, TCL_QUEUE_TAIL, TCL_QUEUE_MARK }; TestEvent *ev; /* Event to be queued */ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "subcommand", TCL_EXACT, &subCmdIndex) != TCL_OK) { return TCL_ERROR; } switch (subCmdIndex) { case 0: /* queue */ if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "name position script"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], positions, "position specifier", TCL_EXACT, &posIndex) != TCL_OK) { return TCL_ERROR; } ev = ckalloc(sizeof(TestEvent)); ev->header.proc = TesteventProc; ev->header.nextPtr = NULL; ev->interp = interp; ev->command = objv[4]; Tcl_IncrRefCount(ev->command); ev->tag = objv[2]; Tcl_IncrRefCount(ev->tag); Tcl_QueueEvent((Tcl_Event *) ev, posNum[posIndex]); break; case 1: /* delete */ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "name"); return TCL_ERROR; } Tcl_DeleteEvents(TesteventDeleteProc, objv[2]); break; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TesteventProc -- * * Delivers a test event to the Tcl interpreter as part of event * queue testing. * * Results: * Returns 1 if the event has been serviced, 0 otherwise. * * Side effects: * Evaluates the event's callback script, so has whatever side effects * the callback has. The return value of the callback script becomes the * return value of this function. If the callback script reports an * error, it is reported as a background error. * *---------------------------------------------------------------------- */ static int TesteventProc( Tcl_Event *event, /* Event to deliver */ int flags) /* Current flags for Tcl_ServiceEvent */ { TestEvent *ev = (TestEvent *) event; Tcl_Interp *interp = ev->interp; Tcl_Obj *command = ev->command; int result = Tcl_EvalObjEx(interp, command, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); int retval; if (result != TCL_OK) { Tcl_AddErrorInfo(interp, " (command bound to \"testevent\" callback)"); Tcl_BackgroundError(interp); return 1; /* Avoid looping on errors */ } if (Tcl_GetBooleanFromObj(interp, Tcl_GetObjResult(interp), &retval) != TCL_OK) { Tcl_AddErrorInfo(interp, " (return value from \"testevent\" callback)"); Tcl_BackgroundError(interp); return 1; } if (retval) { Tcl_DecrRefCount(ev->tag); Tcl_DecrRefCount(ev->command); } return retval; } /* *---------------------------------------------------------------------- * * TesteventDeleteProc -- * * Removes some set of events from the queue. * * This procedure is used as part of testing event queue management. * * Results: * Returns 1 if a given event should be deleted, 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TesteventDeleteProc( Tcl_Event *event, /* Event to examine */ ClientData clientData) /* Tcl_Obj containing the name of the event(s) * to remove */ { TestEvent *ev; /* Event to examine */ const char *evNameStr; Tcl_Obj *targetName; /* Name of the event(s) to delete */ const char *targetNameStr; if (event->proc != TesteventProc) { return 0; } targetName = (Tcl_Obj *) clientData; targetNameStr = (char *) Tcl_GetString(targetName); ev = (TestEvent *) event; evNameStr = Tcl_GetString(ev->tag); if (strcmp(evNameStr, targetNameStr) == 0) { Tcl_DecrRefCount(ev->tag); Tcl_DecrRefCount(ev->command); return 1; } else { return 0; } } /* *---------------------------------------------------------------------- * * TestexithandlerCmd -- * * This procedure implements the "testexithandler" command. It is * used to test Tcl_CreateExitHandler and Tcl_DeleteExitHandler. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestexithandlerCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { int value; if (argc != 3) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " create|delete value\"", NULL); return TCL_ERROR; } if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) { return TCL_ERROR; } if (strcmp(argv[1], "create") == 0) { Tcl_CreateExitHandler((value & 1) ? ExitProcOdd : ExitProcEven, (ClientData) INT2PTR(value)); } else if (strcmp(argv[1], "delete") == 0) { Tcl_DeleteExitHandler((value & 1) ? ExitProcOdd : ExitProcEven, (ClientData) INT2PTR(value)); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be create or delete", NULL); return TCL_ERROR; } return TCL_OK; } static void ExitProcOdd( ClientData clientData) /* Integer value to print. */ { char buf[16 + TCL_INTEGER_SPACE]; size_t len; sprintf(buf, "odd %d\n", PTR2INT(clientData)); len = strlen(buf); if (len != (size_t) write(1, buf, len)) { Tcl_Panic("ExitProcOdd: unable to write to stdout"); } } static void ExitProcEven( ClientData clientData) /* Integer value to print. */ { char buf[16 + TCL_INTEGER_SPACE]; size_t len; sprintf(buf, "even %d\n", PTR2INT(clientData)); len = strlen(buf); if (len != (size_t) write(1, buf, len)) { Tcl_Panic("ExitProcEven: unable to write to stdout"); } } /* *---------------------------------------------------------------------- * * TestexprlongCmd -- * * This procedure verifies that Tcl_ExprLong does not modify the * interpreter result if there is no error. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestexprlongCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { long exprResult; char buf[4 + TCL_INTEGER_SPACE]; int result; if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " expression\"", NULL); return TCL_ERROR; } Tcl_SetResult(interp, "This is a result", TCL_STATIC); result = Tcl_ExprLong(interp, argv[1], &exprResult); if (result != TCL_OK) { return result; } sprintf(buf, ": %ld", exprResult); Tcl_AppendResult(interp, buf, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestexprlongobjCmd -- * * This procedure verifies that Tcl_ExprLongObj does not modify the * interpreter result if there is no error. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestexprlongobjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* Argument objects. */ { long exprResult; char buf[4 + TCL_INTEGER_SPACE]; int result; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "expression"); return TCL_ERROR; } Tcl_SetResult(interp, "This is a result", TCL_STATIC); result = Tcl_ExprLongObj(interp, objv[1], &exprResult); if (result != TCL_OK) { return result; } sprintf(buf, ": %ld", exprResult); Tcl_AppendResult(interp, buf, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestexprdoubleCmd -- * * This procedure verifies that Tcl_ExprDouble does not modify the * interpreter result if there is no error. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestexprdoubleCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { double exprResult; char buf[4 + TCL_DOUBLE_SPACE]; int result; if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " expression\"", NULL); return TCL_ERROR; } Tcl_SetResult(interp, "This is a result", TCL_STATIC); result = Tcl_ExprDouble(interp, argv[1], &exprResult); if (result != TCL_OK) { return result; } strcpy(buf, ": "); Tcl_PrintDouble(interp, exprResult, buf+2); Tcl_AppendResult(interp, buf, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestexprdoubleobjCmd -- * * This procedure verifies that Tcl_ExprLongObj does not modify the * interpreter result if there is no error. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestexprdoubleobjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* Argument objects. */ { double exprResult; char buf[4 + TCL_DOUBLE_SPACE]; int result; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "expression"); return TCL_ERROR; } Tcl_SetResult(interp, "This is a result", TCL_STATIC); result = Tcl_ExprDoubleObj(interp, objv[1], &exprResult); if (result != TCL_OK) { return result; } strcpy(buf, ": "); Tcl_PrintDouble(interp, exprResult, buf+2); Tcl_AppendResult(interp, buf, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestexprstringCmd -- * * This procedure tests the basic operation of Tcl_ExprString. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestexprstringCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " expression\"", NULL); return TCL_ERROR; } return Tcl_ExprString(interp, argv[1]); } /* *---------------------------------------------------------------------- * * TestfilelinkCmd -- * * This procedure implements the "testfilelink" command. It is used to * test the effects of creating and manipulating filesystem links in Tcl. * * Results: * A standard Tcl result. * * Side effects: * May create a link on disk. * *---------------------------------------------------------------------- */ static int TestfilelinkCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { Tcl_Obj *contents; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "source ?target?"); return TCL_ERROR; } if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) { return TCL_ERROR; } if (objc == 3) { /* Create link from source to target */ contents = Tcl_FSLink(objv[1], objv[2], TCL_CREATE_SYMBOLIC_LINK|TCL_CREATE_HARD_LINK); if (contents == NULL) { Tcl_AppendResult(interp, "could not create link from \"", Tcl_GetString(objv[1]), "\" to \"", Tcl_GetString(objv[2]), "\": ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } } else { /* Read link */ contents = Tcl_FSLink(objv[1], NULL, 0); if (contents == NULL) { Tcl_AppendResult(interp, "could not read link \"", Tcl_GetString(objv[1]), "\": ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } } Tcl_SetObjResult(interp, contents); if (objc == 2) { /* * If we are creating a link, this will actually just * be objv[3], and we don't own it */ Tcl_DecrRefCount(contents); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TestgetassocdataCmd -- * * This procedure implements the "testgetassocdata" command. It is * used to test Tcl_GetAssocData. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestgetassocdataCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { char *res; if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " data_key\"", NULL); return TCL_ERROR; } res = (char *) Tcl_GetAssocData(interp, argv[1], NULL); if (res != NULL) { Tcl_AppendResult(interp, res, NULL); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TestgetplatformCmd -- * * This procedure implements the "testgetplatform" command. It is * used to retrievel the value of the tclPlatform global variable. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestgetplatformCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { static const char *const platformStrings[] = { "unix", "mac", "windows" }; TclPlatformType *platform; platform = TclGetPlatform(); if (argc != 1) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], NULL); return TCL_ERROR; } Tcl_AppendResult(interp, platformStrings[*platform], NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestinterpdeleteCmd -- * * This procedure tests the code in tclInterp.c that deals with * interpreter deletion. It deletes a user-specified interpreter * from the hierarchy, and subsequent code checks integrity. * * Results: * A standard Tcl result. * * Side effects: * Deletes one or more interpreters. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestinterpdeleteCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { Tcl_Interp *slaveToDelete; if (argc != 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " path\"", NULL); return TCL_ERROR; } slaveToDelete = Tcl_GetSlave(interp, argv[1]); if (slaveToDelete == NULL) { return TCL_ERROR; } Tcl_DeleteInterp(slaveToDelete); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestlinkCmd -- * * This procedure implements the "testlink" command. It is used * to test Tcl_LinkVar and related library procedures. * * Results: * A standard Tcl result. * * Side effects: * Creates and deletes various variable links, plus returns * values of the linked variables. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestlinkCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { static int intVar = 43; static int boolVar = 4; static double realVar = 1.23; static Tcl_WideInt wideVar = Tcl_LongAsWide(79); static char *stringVar = NULL; static char charVar = '@'; static unsigned char ucharVar = 130; static short shortVar = 3000; static unsigned short ushortVar = 60000; static unsigned int uintVar = 0xbeeffeed; static long longVar = 123456789L; static unsigned long ulongVar = 3456789012UL; static float floatVar = 4.5; static Tcl_WideUInt uwideVar = (Tcl_WideUInt) Tcl_LongAsWide(123); static int created = 0; char buffer[2*TCL_DOUBLE_SPACE]; int writable, flag; Tcl_Obj *tmp; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option ?arg arg arg arg arg arg arg arg arg arg arg arg" " arg arg?\"", NULL); return TCL_ERROR; } if (strcmp(argv[1], "create") == 0) { if (argc != 16) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " intRO realRO boolRO stringRO wideRO charRO ucharRO shortRO" " ushortRO uintRO longRO ulongRO floatRO uwideRO\"", NULL); return TCL_ERROR; } if (created) { Tcl_UnlinkVar(interp, "int"); Tcl_UnlinkVar(interp, "real"); Tcl_UnlinkVar(interp, "bool"); Tcl_UnlinkVar(interp, "string"); Tcl_UnlinkVar(interp, "wide"); Tcl_UnlinkVar(interp, "char"); Tcl_UnlinkVar(interp, "uchar"); Tcl_UnlinkVar(interp, "short"); Tcl_UnlinkVar(interp, "ushort"); Tcl_UnlinkVar(interp, "uint"); Tcl_UnlinkVar(interp, "long"); Tcl_UnlinkVar(interp, "ulong"); Tcl_UnlinkVar(interp, "float"); Tcl_UnlinkVar(interp, "uwide"); } created = 1; if (Tcl_GetBoolean(interp, argv[2], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "int", (char *) &intVar, TCL_LINK_INT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[3], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "real", (char *) &realVar, TCL_LINK_DOUBLE | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[4], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "bool", (char *) &boolVar, TCL_LINK_BOOLEAN | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[5], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "string", (char *) &stringVar, TCL_LINK_STRING | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[6], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "wide", (char *) &wideVar, TCL_LINK_WIDE_INT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[7], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "char", (char *) &charVar, TCL_LINK_CHAR | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[8], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "uchar", (char *) &ucharVar, TCL_LINK_UCHAR | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[9], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "short", (char *) &shortVar, TCL_LINK_SHORT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[10], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "ushort", (char *) &ushortVar, TCL_LINK_USHORT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[11], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "uint", (char *) &uintVar, TCL_LINK_UINT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[12], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "long", (char *) &longVar, TCL_LINK_LONG | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[13], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "ulong", (char *) &ulongVar, TCL_LINK_ULONG | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[14], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "float", (char *) &floatVar, TCL_LINK_FLOAT | flag) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBoolean(interp, argv[15], &writable) != TCL_OK) { return TCL_ERROR; } flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY; if (Tcl_LinkVar(interp, "uwide", (char *) &uwideVar, TCL_LINK_WIDE_UINT | flag) != TCL_OK) { return TCL_ERROR; } } else if (strcmp(argv[1], "delete") == 0) { Tcl_UnlinkVar(interp, "int"); Tcl_UnlinkVar(interp, "real"); Tcl_UnlinkVar(interp, "bool"); Tcl_UnlinkVar(interp, "string"); Tcl_UnlinkVar(interp, "wide"); Tcl_UnlinkVar(interp, "char"); Tcl_UnlinkVar(interp, "uchar"); Tcl_UnlinkVar(interp, "short"); Tcl_UnlinkVar(interp, "ushort"); Tcl_UnlinkVar(interp, "uint"); Tcl_UnlinkVar(interp, "long"); Tcl_UnlinkVar(interp, "ulong"); Tcl_UnlinkVar(interp, "float"); Tcl_UnlinkVar(interp, "uwide"); created = 0; } else if (strcmp(argv[1], "get") == 0) { TclFormatInt(buffer, intVar); Tcl_AppendElement(interp, buffer); Tcl_PrintDouble(NULL, realVar, buffer); Tcl_AppendElement(interp, buffer); TclFormatInt(buffer, boolVar); Tcl_AppendElement(interp, buffer); Tcl_AppendElement(interp, (stringVar == NULL) ? "-" : stringVar); /* * Wide ints only have an object-based interface. */ tmp = Tcl_NewWideIntObj(wideVar); Tcl_AppendElement(interp, Tcl_GetString(tmp)); Tcl_DecrRefCount(tmp); TclFormatInt(buffer, (int) charVar); Tcl_AppendElement(interp, buffer); TclFormatInt(buffer, (int) ucharVar); Tcl_AppendElement(interp, buffer); TclFormatInt(buffer, (int) shortVar); Tcl_AppendElement(interp, buffer); TclFormatInt(buffer, (int) ushortVar); Tcl_AppendElement(interp, buffer); TclFormatInt(buffer, (int) uintVar); Tcl_AppendElement(interp, buffer); tmp = Tcl_NewLongObj(longVar); Tcl_AppendElement(interp, Tcl_GetString(tmp)); Tcl_DecrRefCount(tmp); tmp = Tcl_NewLongObj((long)ulongVar); Tcl_AppendElement(interp, Tcl_GetString(tmp)); Tcl_DecrRefCount(tmp); Tcl_PrintDouble(NULL, (double)floatVar, buffer); Tcl_AppendElement(interp, buffer); tmp = Tcl_NewWideIntObj((Tcl_WideInt)uwideVar); Tcl_AppendElement(interp, Tcl_GetString(tmp)); Tcl_DecrRefCount(tmp); } else if (strcmp(argv[1], "set") == 0) { int v; if (argc != 16) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " intValue realValue boolValue stringValue wideValue" " charValue ucharValue shortValue ushortValue uintValue" " longValue ulongValue floatValue uwideValue\"", NULL); return TCL_ERROR; } if (argv[2][0] != 0) { if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) { return TCL_ERROR; } } if (argv[3][0] != 0) { if (Tcl_GetDouble(interp, argv[3], &realVar) != TCL_OK) { return TCL_ERROR; } } if (argv[4][0] != 0) { if (Tcl_GetInt(interp, argv[4], &boolVar) != TCL_OK) { return TCL_ERROR; } } if (argv[5][0] != 0) { if (stringVar != NULL) { ckfree(stringVar); } if (strcmp(argv[5], "-") == 0) { stringVar = NULL; } else { stringVar = ckalloc(strlen(argv[5]) + 1); strcpy(stringVar, argv[5]); } } if (argv[6][0] != 0) { tmp = Tcl_NewStringObj(argv[6], -1); if (Tcl_GetWideIntFromObj(interp, tmp, &wideVar) != TCL_OK) { Tcl_DecrRefCount(tmp); return TCL_ERROR; } Tcl_DecrRefCount(tmp); } if (argv[7][0]) { if (Tcl_GetInt(interp, argv[7], &v) != TCL_OK) { return TCL_ERROR; } charVar = (char) v; } if (argv[8][0]) { if (Tcl_GetInt(interp, argv[8], &v) != TCL_OK) { return TCL_ERROR; } ucharVar = (unsigned char) v; } if (argv[9][0]) { if (Tcl_GetInt(interp, argv[9], &v) != TCL_OK) { return TCL_ERROR; } shortVar = (short) v; } if (argv[10][0]) { if (Tcl_GetInt(interp, argv[10], &v) != TCL_OK) { return TCL_ERROR; } ushortVar = (unsigned short) v; } if (argv[11][0]) { if (Tcl_GetInt(interp, argv[11], &v) != TCL_OK) { return TCL_ERROR; } uintVar = (unsigned int) v; } if (argv[12][0]) { if (Tcl_GetInt(interp, argv[12], &v) != TCL_OK) { return TCL_ERROR; } longVar = (long) v; } if (argv[13][0]) { if (Tcl_GetInt(interp, argv[13], &v) != TCL_OK) { return TCL_ERROR; } ulongVar = (unsigned long) v; } if (argv[14][0]) { double d; if (Tcl_GetDouble(interp, argv[14], &d) != TCL_OK) { return TCL_ERROR; } floatVar = (float) d; } if (argv[15][0]) { Tcl_WideInt w; tmp = Tcl_NewStringObj(argv[15], -1); if (Tcl_GetWideIntFromObj(interp, tmp, &w) != TCL_OK) { Tcl_DecrRefCount(tmp); return TCL_ERROR; } Tcl_DecrRefCount(tmp); uwideVar = (Tcl_WideUInt) w; } } else if (strcmp(argv[1], "update") == 0) { int v; if (argc != 16) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ", argv[1], " intValue realValue boolValue stringValue wideValue" " charValue ucharValue shortValue ushortValue uintValue" " longValue ulongValue floatValue uwideValue\"", NULL); return TCL_ERROR; } if (argv[2][0] != 0) { if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) { return TCL_ERROR; } Tcl_UpdateLinkedVar(interp, "int"); } if (argv[3][0] != 0) { if (Tcl_GetDouble(interp, argv[3], &realVar) != TCL_OK) { return TCL_ERROR; } Tcl_UpdateLinkedVar(interp, "real"); } if (argv[4][0] != 0) { if (Tcl_GetInt(interp, argv[4], &boolVar) != TCL_OK) { return TCL_ERROR; } Tcl_UpdateLinkedVar(interp, "bool"); } if (argv[5][0] != 0) { if (stringVar != NULL) { ckfree(stringVar); } if (strcmp(argv[5], "-") == 0) { stringVar = NULL; } else { stringVar = ckalloc(strlen(argv[5]) + 1); strcpy(stringVar, argv[5]); } Tcl_UpdateLinkedVar(interp, "string"); } if (argv[6][0] != 0) { tmp = Tcl_NewStringObj(argv[6], -1); if (Tcl_GetWideIntFromObj(interp, tmp, &wideVar) != TCL_OK) { Tcl_DecrRefCount(tmp); return TCL_ERROR; } Tcl_DecrRefCount(tmp); Tcl_UpdateLinkedVar(interp, "wide"); } if (argv[7][0]) { if (Tcl_GetInt(interp, argv[7], &v) != TCL_OK) { return TCL_ERROR; } charVar = (char) v; Tcl_UpdateLinkedVar(interp, "char"); } if (argv[8][0]) { if (Tcl_GetInt(interp, argv[8], &v) != TCL_OK) { return TCL_ERROR; } ucharVar = (unsigned char) v; Tcl_UpdateLinkedVar(interp, "uchar"); } if (argv[9][0]) { if (Tcl_GetInt(interp, argv[9], &v) != TCL_OK) { return TCL_ERROR; } shortVar = (short) v; Tcl_UpdateLinkedVar(interp, "short"); } if (argv[10][0]) { if (Tcl_GetInt(interp, argv[10], &v) != TCL_OK) { return TCL_ERROR; } ushortVar = (unsigned short) v; Tcl_UpdateLinkedVar(interp, "ushort"); } if (argv[11][0]) { if (Tcl_GetInt(interp, argv[11], &v) != TCL_OK) { return TCL_ERROR; } uintVar = (unsigned int) v; Tcl_UpdateLinkedVar(interp, "uint"); } if (argv[12][0]) { if (Tcl_GetInt(interp, argv[12], &v) != TCL_OK) { return TCL_ERROR; } longVar = (long) v; Tcl_UpdateLinkedVar(interp, "long"); } if (argv[13][0]) { if (Tcl_GetInt(interp, argv[13], &v) != TCL_OK) { return TCL_ERROR; } ulongVar = (unsigned long) v; Tcl_UpdateLinkedVar(interp, "ulong"); } if (argv[14][0]) { double d; if (Tcl_GetDouble(interp, argv[14], &d) != TCL_OK) { return TCL_ERROR; } floatVar = (float) d; Tcl_UpdateLinkedVar(interp, "float"); } if (argv[15][0]) { Tcl_WideInt w; tmp = Tcl_NewStringObj(argv[15], -1); if (Tcl_GetWideIntFromObj(interp, tmp, &w) != TCL_OK) { Tcl_DecrRefCount(tmp); return TCL_ERROR; } Tcl_DecrRefCount(tmp); uwideVar = (Tcl_WideUInt) w; Tcl_UpdateLinkedVar(interp, "uwide"); } } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": should be create, delete, get, set, or update", NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TestlocaleCmd -- * * This procedure implements the "testlocale" command. It is used * to test the effects of setting different locales in Tcl. * * Results: * A standard Tcl result. * * Side effects: * Modifies the current C locale. * *---------------------------------------------------------------------- */ static int TestlocaleCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { int index; const char *locale; static const char *const optionStrings[] = { "ctype", "numeric", "time", "collate", "monetary", "all", NULL }; static const int lcTypes[] = { LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_ALL }; /* * LC_CTYPE, etc. correspond to the indices for the strings. */ if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "category ?locale?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (objc == 3) { locale = Tcl_GetString(objv[2]); } else { locale = NULL; } locale = setlocale(lcTypes[index], locale); if (locale) { Tcl_SetStringObj(Tcl_GetObjResult(interp), locale, -1); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TestMathFunc -- * * This is a user-defined math procedure to test out math procedures * with no arguments. * * Results: * A normal Tcl completion code. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestMathFunc( ClientData clientData, /* Integer value to return. */ Tcl_Interp *interp, /* Not used. */ Tcl_Value *args, /* Not used. */ Tcl_Value *resultPtr) /* Where to store result. */ { resultPtr->type = TCL_INT; resultPtr->intValue = PTR2INT(clientData); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestMathFunc2 -- * * This is a user-defined math procedure to test out math procedures * that do have arguments, in this case 2. * * Results: * A normal Tcl completion code. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestMathFunc2( ClientData clientData, /* Integer value to return. */ Tcl_Interp *interp, /* Used to report errors. */ Tcl_Value *args, /* Points to an array of two Tcl_Value structs * for the two arguments. */ Tcl_Value *resultPtr) /* Where to store the result. */ { int result = TCL_OK; /* * Return the maximum of the two arguments with the correct type. */ if (args[0].type == TCL_INT) { int i0 = args[0].intValue; if (args[1].type == TCL_INT) { int i1 = args[1].intValue; resultPtr->type = TCL_INT; resultPtr->intValue = ((i0 > i1)? i0 : i1); } else if (args[1].type == TCL_DOUBLE) { double d0 = i0; double d1 = args[1].doubleValue; resultPtr->type = TCL_DOUBLE; resultPtr->doubleValue = ((d0 > d1)? d0 : d1); } else if (args[1].type == TCL_WIDE_INT) { Tcl_WideInt w0 = Tcl_LongAsWide(i0); Tcl_WideInt w1 = args[1].wideValue; resultPtr->type = TCL_WIDE_INT; resultPtr->wideValue = ((w0 > w1)? w0 : w1); } else { Tcl_SetResult(interp, "T3: wrong type for arg 2", TCL_STATIC); result = TCL_ERROR; } } else if (args[0].type == TCL_DOUBLE) { double d0 = args[0].doubleValue; if (args[1].type == TCL_INT) { double d1 = args[1].intValue; resultPtr->type = TCL_DOUBLE; resultPtr->doubleValue = ((d0 > d1)? d0 : d1); } else if (args[1].type == TCL_DOUBLE) { double d1 = args[1].doubleValue; resultPtr->type = TCL_DOUBLE; resultPtr->doubleValue = ((d0 > d1)? d0 : d1); } else if (args[1].type == TCL_WIDE_INT) { double d1 = Tcl_WideAsDouble(args[1].wideValue); resultPtr->type = TCL_DOUBLE; resultPtr->doubleValue = ((d0 > d1)? d0 : d1); } else { Tcl_SetResult(interp, "T3: wrong type for arg 2", TCL_STATIC); result = TCL_ERROR; } } else if (args[0].type == TCL_WIDE_INT) { Tcl_WideInt w0 = args[0].wideValue; if (args[1].type == TCL_INT) { Tcl_WideInt w1 = Tcl_LongAsWide(args[1].intValue); resultPtr->type = TCL_WIDE_INT; resultPtr->wideValue = ((w0 > w1)? w0 : w1); } else if (args[1].type == TCL_DOUBLE) { double d0 = Tcl_WideAsDouble(w0); double d1 = args[1].doubleValue; resultPtr->type = TCL_DOUBLE; resultPtr->doubleValue = ((d0 > d1)? d0 : d1); } else if (args[1].type == TCL_WIDE_INT) { Tcl_WideInt w1 = args[1].wideValue; resultPtr->type = TCL_WIDE_INT; resultPtr->wideValue = ((w0 > w1)? w0 : w1); } else { Tcl_SetResult(interp, "T3: wrong type for arg 2", TCL_STATIC); result = TCL_ERROR; } } else { Tcl_SetResult(interp, "T3: wrong type for arg 1", TCL_STATIC); result = TCL_ERROR; } return result; } /* *---------------------------------------------------------------------- * * CleanupTestSetassocdataTests -- * * This function is called when an interpreter is deleted to clean * up any data left over from running the testsetassocdata command. * * Results: * None. * * Side effects: * Releases storage. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static void CleanupTestSetassocdataTests( ClientData clientData, /* Data to be released. */ Tcl_Interp *interp) /* Interpreter being deleted. */ { ckfree(clientData); } /* *---------------------------------------------------------------------- * * TestparserObjCmd -- * * This procedure implements the "testparser" command. It is * used for testing the new Tcl script parser in Tcl 8.1. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestparserObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { const char *script; int length, dummy; Tcl_Parse parse; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "script length"); return TCL_ERROR; } script = Tcl_GetStringFromObj(objv[1], &dummy); if (Tcl_GetIntFromObj(interp, objv[2], &length)) { return TCL_ERROR; } if (length == 0) { length = dummy; } if (Tcl_ParseCommand(interp, script, length, 0, &parse) != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (remainder of script: \""); Tcl_AddErrorInfo(interp, parse.term); Tcl_AddErrorInfo(interp, "\")"); return TCL_ERROR; } /* * The parse completed successfully. Just print out the contents * of the parse structure into the interpreter's result. */ PrintParse(interp, &parse); Tcl_FreeParse(&parse); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestexprparserObjCmd -- * * This procedure implements the "testexprparser" command. It is * used for testing the new Tcl expression parser in Tcl 8.1. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestexprparserObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { const char *script; int length, dummy; Tcl_Parse parse; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "expr length"); return TCL_ERROR; } script = Tcl_GetStringFromObj(objv[1], &dummy); if (Tcl_GetIntFromObj(interp, objv[2], &length)) { return TCL_ERROR; } if (length == 0) { length = dummy; } parse.commentStart = NULL; parse.commentSize = 0; parse.commandStart = NULL; parse.commandSize = 0; if (Tcl_ParseExpr(interp, script, length, &parse) != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (remainder of expr: \""); Tcl_AddErrorInfo(interp, parse.term); Tcl_AddErrorInfo(interp, "\")"); return TCL_ERROR; } /* * The parse completed successfully. Just print out the contents * of the parse structure into the interpreter's result. */ PrintParse(interp, &parse); Tcl_FreeParse(&parse); return TCL_OK; } /* *---------------------------------------------------------------------- * * PrintParse -- * * This procedure prints out the contents of a Tcl_Parse structure * in the result of an interpreter. * * Results: * Interp's result is set to a prettily formatted version of the * contents of parsePtr. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void PrintParse( Tcl_Interp *interp, /* Interpreter whose result is to be set to * the contents of a parse structure. */ Tcl_Parse *parsePtr) /* Parse structure to print out. */ { Tcl_Obj *objPtr; const char *typeString; Tcl_Token *tokenPtr; int i; objPtr = Tcl_GetObjResult(interp); if (parsePtr->commentSize > 0) { Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(parsePtr->commentStart, parsePtr->commentSize)); } else { Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj("-", 1)); } Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(parsePtr->commandStart, parsePtr->commandSize)); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(parsePtr->numWords)); for (i = 0; i < parsePtr->numTokens; i++) { tokenPtr = &parsePtr->tokenPtr[i]; switch (tokenPtr->type) { case TCL_TOKEN_EXPAND_WORD: typeString = "expand"; break; case TCL_TOKEN_WORD: typeString = "word"; break; case TCL_TOKEN_SIMPLE_WORD: typeString = "simple"; break; case TCL_TOKEN_TEXT: typeString = "text"; break; case TCL_TOKEN_BS: typeString = "backslash"; break; case TCL_TOKEN_COMMAND: typeString = "command"; break; case TCL_TOKEN_VARIABLE: typeString = "variable"; break; case TCL_TOKEN_SUB_EXPR: typeString = "subexpr"; break; case TCL_TOKEN_OPERATOR: typeString = "operator"; break; default: typeString = "??"; break; } Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(typeString, -1)); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(tokenPtr->start, tokenPtr->size)); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(tokenPtr->numComponents)); } Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(parsePtr->commandStart + parsePtr->commandSize, -1)); } /* *---------------------------------------------------------------------- * * TestparsevarObjCmd -- * * This procedure implements the "testparsevar" command. It is * used for testing Tcl_ParseVar. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestparsevarObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { const char *value, *name, *termPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "varName"); return TCL_ERROR; } name = Tcl_GetString(objv[1]); value = Tcl_ParseVar(interp, name, &termPtr); if (value == NULL) { return TCL_ERROR; } Tcl_AppendElement(interp, value); Tcl_AppendElement(interp, termPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestparsevarnameObjCmd -- * * This procedure implements the "testparsevarname" command. It is * used for testing the new Tcl script parser in Tcl 8.1. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestparsevarnameObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { const char *script; int append, length, dummy; Tcl_Parse parse; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "script length append"); return TCL_ERROR; } script = Tcl_GetStringFromObj(objv[1], &dummy); if (Tcl_GetIntFromObj(interp, objv[2], &length)) { return TCL_ERROR; } if (length == 0) { length = dummy; } if (Tcl_GetIntFromObj(interp, objv[3], &append)) { return TCL_ERROR; } if (Tcl_ParseVarName(interp, script, length, &parse, append) != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (remainder of script: \""); Tcl_AddErrorInfo(interp, parse.term); Tcl_AddErrorInfo(interp, "\")"); return TCL_ERROR; } /* * The parse completed successfully. Just print out the contents * of the parse structure into the interpreter's result. */ parse.commentSize = 0; parse.commandStart = script + parse.tokenPtr->size; parse.commandSize = 0; PrintParse(interp, &parse); Tcl_FreeParse(&parse); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestregexpObjCmd -- * * This procedure implements the "testregexp" command. It is used to give * a direct interface for regexp flags. It's identical to * Tcl_RegexpObjCmd except for the -xflags option, and the consequences * thereof (including the REG_EXPECT kludge). * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestregexpObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int i, ii, indices, stringLength, match, about; int hasxflags, cflags, eflags; Tcl_RegExp regExpr; const char *string; Tcl_Obj *objPtr; Tcl_RegExpInfo info; static const char *const options[] = { "-indices", "-nocase", "-about", "-expanded", "-line", "-linestop", "-lineanchor", "-xflags", "--", NULL }; enum options { REGEXP_INDICES, REGEXP_NOCASE, REGEXP_ABOUT, REGEXP_EXPANDED, REGEXP_MULTI, REGEXP_NOCROSS, REGEXP_NEWL, REGEXP_XFLAGS, REGEXP_LAST }; indices = 0; about = 0; cflags = REG_ADVANCED; eflags = 0; hasxflags = 0; for (i = 1; i < objc; i++) { const char *name; int index; name = Tcl_GetString(objv[i]); if (name[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { case REGEXP_INDICES: indices = 1; break; case REGEXP_NOCASE: cflags |= REG_ICASE; break; case REGEXP_ABOUT: about = 1; break; case REGEXP_EXPANDED: cflags |= REG_EXPANDED; break; case REGEXP_MULTI: cflags |= REG_NEWLINE; break; case REGEXP_NOCROSS: cflags |= REG_NLSTOP; break; case REGEXP_NEWL: cflags |= REG_NLANCH; break; case REGEXP_XFLAGS: hasxflags = 1; break; case REGEXP_LAST: i++; goto endOfForLoop; } } endOfForLoop: if (objc - i < hasxflags + 2 - about) { Tcl_WrongNumArgs(interp, 1, objv, "?-switch ...? exp string ?matchVar? ?subMatchVar ...?"); return TCL_ERROR; } objc -= i; objv += i; if (hasxflags) { string = Tcl_GetStringFromObj(objv[0], &stringLength); TestregexpXflags(string, stringLength, &cflags, &eflags); objc--; objv++; } regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags); if (regExpr == NULL) { return TCL_ERROR; } if (about) { if (TclRegAbout(interp, regExpr) < 0) { return TCL_ERROR; } return TCL_OK; } objPtr = objv[1]; match = Tcl_RegExpExecObj(interp, regExpr, objPtr, 0 /* offset */, objc-2 /* nmatches */, eflags); if (match < 0) { return TCL_ERROR; } if (match == 0) { /* * Set the interpreter's object result to an integer object w/ * value 0. */ Tcl_SetIntObj(Tcl_GetObjResult(interp), 0); if (objc > 2 && (cflags®_EXPECT) && indices) { const char *varName; const char *value; int start, end; char resinfo[TCL_INTEGER_SPACE * 2]; varName = Tcl_GetString(objv[2]); TclRegExpRangeUniChar(regExpr, -1, &start, &end); sprintf(resinfo, "%d %d", start, end-1); value = Tcl_SetVar(interp, varName, resinfo, 0); if (value == NULL) { Tcl_AppendResult(interp, "couldn't set variable \"", varName, "\"", NULL); return TCL_ERROR; } } else if (cflags & TCL_REG_CANMATCH) { const char *varName; const char *value; char resinfo[TCL_INTEGER_SPACE * 2]; Tcl_RegExpGetInfo(regExpr, &info); varName = Tcl_GetString(objv[2]); sprintf(resinfo, "%ld", info.extendStart); value = Tcl_SetVar(interp, varName, resinfo, 0); if (value == NULL) { Tcl_AppendResult(interp, "couldn't set variable \"", varName, "\"", NULL); return TCL_ERROR; } } return TCL_OK; } /* * If additional variable names have been specified, return * index information in those variables. */ objc -= 2; objv += 2; Tcl_RegExpGetInfo(regExpr, &info); for (i = 0; i < objc; i++) { int start, end; Tcl_Obj *newPtr, *varPtr, *valuePtr; varPtr = objv[i]; ii = ((cflags®_EXPECT) && i == objc-1) ? -1 : i; if (indices) { Tcl_Obj *objs[2]; if (ii == -1) { TclRegExpRangeUniChar(regExpr, ii, &start, &end); } else if (ii > info.nsubs) { start = -1; end = -1; } else { start = info.matches[ii].start; end = info.matches[ii].end; } /* * Adjust index so it refers to the last character in the match * instead of the first character after the match. */ if (end >= 0) { end--; } objs[0] = Tcl_NewLongObj(start); objs[1] = Tcl_NewLongObj(end); newPtr = Tcl_NewListObj(2, objs); } else { if (ii == -1) { TclRegExpRangeUniChar(regExpr, ii, &start, &end); newPtr = Tcl_GetRange(objPtr, start, end); } else if (ii > info.nsubs) { newPtr = Tcl_NewObj(); } else { newPtr = Tcl_GetRange(objPtr, info.matches[ii].start, info.matches[ii].end - 1); } } valuePtr = Tcl_ObjSetVar2(interp, varPtr, NULL, newPtr, TCL_LEAVE_ERR_MSG); if (valuePtr == NULL) { return TCL_ERROR; } } /* * Set the interpreter's object result to an integer object w/ value 1. */ Tcl_SetIntObj(Tcl_GetObjResult(interp), 1); return TCL_OK; } /* *--------------------------------------------------------------------------- * * TestregexpXflags -- * * Parse a string of extended regexp flag letters, for testing. * * Results: * No return value (you're on your own for errors here). * * Side effects: * Modifies *cflagsPtr, a regcomp flags word, and *eflagsPtr, a * regexec flags word, as appropriate. * *---------------------------------------------------------------------- */ static void TestregexpXflags( const char *string, /* The string of flags. */ int length, /* The length of the string in bytes. */ int *cflagsPtr, /* compile flags word */ int *eflagsPtr) /* exec flags word */ { int i, cflags, eflags; cflags = *cflagsPtr; eflags = *eflagsPtr; for (i = 0; i < length; i++) { switch (string[i]) { case 'a': cflags |= REG_ADVF; break; case 'b': cflags &= ~REG_ADVANCED; break; case 'c': cflags |= TCL_REG_CANMATCH; break; case 'e': cflags &= ~REG_ADVANCED; cflags |= REG_EXTENDED; break; case 'q': cflags &= ~REG_ADVANCED; cflags |= REG_QUOTE; break; case 'o': /* o for opaque */ cflags |= REG_NOSUB; break; case 's': /* s for start */ cflags |= REG_BOSONLY; break; case '+': cflags |= REG_FAKE; break; case ',': cflags |= REG_PROGRESS; break; case '.': cflags |= REG_DUMP; break; case ':': eflags |= REG_MTRACE; break; case ';': eflags |= REG_FTRACE; break; case '^': eflags |= REG_NOTBOL; break; case '$': eflags |= REG_NOTEOL; break; case 't': cflags |= REG_EXPECT; break; case '%': eflags |= REG_SMALL; break; } } *cflagsPtr = cflags; *eflagsPtr = eflags; } /* *---------------------------------------------------------------------- * * TestreturnObjCmd -- * * This procedure implements the "testreturn" command. It is * used to verify that a * return TCL_RETURN; * has same behavior as * return Tcl_SetReturnOptions(interp, Tcl_NewObj()); * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestreturnObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return TCL_RETURN; } /* *---------------------------------------------------------------------- * * TestsetassocdataCmd -- * * This procedure implements the "testsetassocdata" command. It is used * to test Tcl_SetAssocData. * * Results: * A standard Tcl result. * * Side effects: * Modifies or creates an association between a key and associated * data for this interpreter. * *---------------------------------------------------------------------- */ static int TestsetassocdataCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { char *buf, *oldData; Tcl_InterpDeleteProc *procPtr; if (argc != 3) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " data_key data_item\"", NULL); return TCL_ERROR; } buf = ckalloc(strlen(argv[2]) + 1); strcpy(buf, argv[2]); /* * If we previously associated a malloced value with the variable, * free it before associating a new value. */ oldData = (char *) Tcl_GetAssocData(interp, argv[1], &procPtr); if ((oldData != NULL) && (procPtr == CleanupTestSetassocdataTests)) { ckfree(oldData); } Tcl_SetAssocData(interp, argv[1], CleanupTestSetassocdataTests, (ClientData) buf); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestsetplatformCmd -- * * This procedure implements the "testsetplatform" command. It is * used to change the tclPlatform global variable so all file * name conversions can be tested on a single platform. * * Results: * A standard Tcl result. * * Side effects: * Sets the tclPlatform global variable. * *---------------------------------------------------------------------- */ static int TestsetplatformCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { size_t length; TclPlatformType *platform; platform = TclGetPlatform(); if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " platform\"", NULL); return TCL_ERROR; } length = strlen(argv[1]); if (strncmp(argv[1], "unix", length) == 0) { *platform = TCL_PLATFORM_UNIX; } else if (strncmp(argv[1], "windows", length) == 0) { *platform = TCL_PLATFORM_WINDOWS; } else { Tcl_AppendResult(interp, "unsupported platform: should be one of " "unix, or windows", NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TeststaticpkgCmd -- * * This procedure implements the "teststaticpkg" command. * It is used to test the procedure Tcl_StaticPackage. * * Results: * A standard Tcl result. * * Side effects: * When the packge given by argv[1] is loaded into an interpeter, * variable "x" in that interpreter is set to "loaded". * *---------------------------------------------------------------------- */ static int TeststaticpkgCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { int safe, loaded; if (argc != 4) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " pkgName safe loaded\"", NULL); return TCL_ERROR; } if (Tcl_GetInt(interp, argv[2], &safe) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetInt(interp, argv[3], &loaded) != TCL_OK) { return TCL_ERROR; } tclStubsPtr->tcl_StaticPackage((loaded) ? interp : NULL, argv[1], StaticInitProc, (safe) ? StaticInitProc : NULL); return TCL_OK; } static int StaticInitProc( Tcl_Interp *interp) /* Interpreter in which package is supposedly * being loaded. */ { Tcl_SetVar(interp, "x", "loaded", TCL_GLOBAL_ONLY); return TCL_OK; } /* *---------------------------------------------------------------------- * * TesttranslatefilenameCmd -- * * This procedure implements the "testtranslatefilename" command. * It is used to test the Tcl_TranslateFileName command. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TesttranslatefilenameCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { Tcl_DString buffer; const char *result; if (argc != 2) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " path\"", NULL); return TCL_ERROR; } result = Tcl_TranslateFileName(interp, argv[1], &buffer); if (result == NULL) { return TCL_ERROR; } Tcl_AppendResult(interp, result, NULL); Tcl_DStringFree(&buffer); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestupvarCmd -- * * This procedure implements the "testupvar2" command. It is used * to test Tcl_UpVar and Tcl_UpVar2. * * Results: * A standard Tcl result. * * Side effects: * Creates or modifies an "upvar" reference. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestupvarCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { int flags = 0; if ((argc != 5) && (argc != 6)) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " level name ?name2? dest global\"", NULL); return TCL_ERROR; } if (argc == 5) { if (strcmp(argv[4], "global") == 0) { flags = TCL_GLOBAL_ONLY; } else if (strcmp(argv[4], "namespace") == 0) { flags = TCL_NAMESPACE_ONLY; } return Tcl_UpVar(interp, argv[1], argv[2], argv[3], flags); } else { if (strcmp(argv[5], "global") == 0) { flags = TCL_GLOBAL_ONLY; } else if (strcmp(argv[5], "namespace") == 0) { flags = TCL_NAMESPACE_ONLY; } return Tcl_UpVar2(interp, argv[1], argv[2], (argv[3][0] == 0) ? NULL : argv[3], argv[4], flags); } } /* *---------------------------------------------------------------------- * * TestseterrorcodeCmd -- * * This procedure implements the "testseterrorcodeCmd". This tests up to * five elements passed to the Tcl_SetErrorCode command. * * Results: * A standard Tcl result. Always returns TCL_ERROR so that * the error code can be tested. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestseterrorcodeCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { if (argc > 6) { Tcl_SetResult(interp, "too many args", TCL_STATIC); return TCL_ERROR; } switch (argc) { case 1: Tcl_SetErrorCode(interp, "NONE", NULL); break; case 2: Tcl_SetErrorCode(interp, argv[1], NULL); break; case 3: Tcl_SetErrorCode(interp, argv[1], argv[2], NULL); break; case 4: Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], NULL); break; case 5: Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4], NULL); break; case 6: Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4], argv[5], NULL); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TestsetobjerrorcodeCmd -- * * This procedure implements the "testsetobjerrorcodeCmd". * This tests the Tcl_SetObjErrorCode function. * * Results: * A standard Tcl result. Always returns TCL_ERROR so that * the error code can be tested. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestsetobjerrorcodeCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { Tcl_SetObjErrorCode(interp, Tcl_ConcatObj(objc - 1, objv + 1)); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TestfeventCmd -- * * This procedure implements the "testfevent" command. It is * used for testing the "fileevent" command. * * Results: * A standard Tcl result. * * Side effects: * Creates and deletes interpreters. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestfeventCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { static Tcl_Interp *interp2 = NULL; int code; Tcl_Channel chan; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option ?arg ...?", NULL); return TCL_ERROR; } if (strcmp(argv[1], "cmd") == 0) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " cmd script", NULL); return TCL_ERROR; } if (interp2 != NULL) { code = Tcl_EvalEx(interp2, argv[2], -1, TCL_EVAL_GLOBAL); Tcl_SetObjResult(interp, Tcl_GetObjResult(interp2)); return code; } else { Tcl_AppendResult(interp, "called \"testfevent code\" before \"testfevent create\"", NULL); return TCL_ERROR; } } else if (strcmp(argv[1], "create") == 0) { if (interp2 != NULL) { Tcl_DeleteInterp(interp2); } interp2 = Tcl_CreateInterp(); return Tcl_Init(interp2); } else if (strcmp(argv[1], "delete") == 0) { if (interp2 != NULL) { Tcl_DeleteInterp(interp2); } interp2 = NULL; } else if (strcmp(argv[1], "share") == 0) { if (interp2 != NULL) { chan = Tcl_GetChannel(interp, argv[2], NULL); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } Tcl_RegisterChannel(interp2, chan); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TestpanicCmd -- * * Calls the panic routine. * * Results: * Always returns TCL_OK. * * Side effects: * May exit application. * *---------------------------------------------------------------------- */ static int TestpanicCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { const char *argString; /* * Put the arguments into a var args structure * Append all of the arguments together separated by spaces */ argString = Tcl_Merge(argc-1, argv+1); Tcl_Panic("%s", argString); ckfree(argString); return TCL_OK; } static int TestfileCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ Tcl_Obj *const argv[]) /* The argument objects. */ { int force, i, j, result; Tcl_Obj *error = NULL; const char *subcmd; if (argc < 3) { return TCL_ERROR; } force = 0; i = 2; if (strcmp(Tcl_GetString(argv[2]), "-force") == 0) { force = 1; i = 3; } if (argc - i > 2) { return TCL_ERROR; } for (j = i; j < argc; j++) { if (Tcl_FSGetNormalizedPath(interp, argv[j]) == NULL) { return TCL_ERROR; } } subcmd = Tcl_GetString(argv[1]); if (strcmp(subcmd, "mv") == 0) { result = TclpObjRenameFile(argv[i], argv[i + 1]); } else if (strcmp(subcmd, "cp") == 0) { result = TclpObjCopyFile(argv[i], argv[i + 1]); } else if (strcmp(subcmd, "rm") == 0) { result = TclpObjDeleteFile(argv[i]); } else if (strcmp(subcmd, "mkdir") == 0) { result = TclpObjCreateDirectory(argv[i]); } else if (strcmp(subcmd, "cpdir") == 0) { result = TclpObjCopyDirectory(argv[i], argv[i + 1], &error); } else if (strcmp(subcmd, "rmdir") == 0) { result = TclpObjRemoveDirectory(argv[i], force, &error); } else { result = TCL_ERROR; goto end; } if (result != TCL_OK) { if (error != NULL) { if (Tcl_GetString(error)[0] != '\0') { Tcl_AppendResult(interp, Tcl_GetString(error), " ", NULL); } Tcl_DecrRefCount(error); } Tcl_AppendResult(interp, Tcl_ErrnoId(), NULL); } end: return result; } /* *---------------------------------------------------------------------- * * TestgetvarfullnameCmd -- * * Implements the "testgetvarfullname" cmd that is used when testing * the Tcl_GetVariableFullName procedure. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestgetvarfullnameCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { const char *name, *arg; int flags = 0; Tcl_Namespace *namespacePtr; Tcl_CallFrame *framePtr; Tcl_Var variable; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "name scope"); return TCL_ERROR; } name = Tcl_GetString(objv[1]); arg = Tcl_GetString(objv[2]); if (strcmp(arg, "global") == 0) { flags = TCL_GLOBAL_ONLY; } else if (strcmp(arg, "namespace") == 0) { flags = TCL_NAMESPACE_ONLY; } /* * This command, like any other created with Tcl_Create[Obj]Command, runs * in the global namespace. As a "namespace-aware" command that needs to * run in a particular namespace, it must activate that namespace itself. */ if (flags == TCL_NAMESPACE_ONLY) { namespacePtr = Tcl_FindNamespace(interp, "::test_ns_var", NULL, TCL_LEAVE_ERR_MSG); if (namespacePtr == NULL) { return TCL_ERROR; } (void) TclPushStackFrame(interp, &framePtr, namespacePtr, /*isProcCallFrame*/ 0); } variable = Tcl_FindNamespaceVar(interp, name, NULL, (flags | TCL_LEAVE_ERR_MSG)); if (flags == TCL_NAMESPACE_ONLY) { TclPopStackFrame(interp); } if (variable == (Tcl_Var) NULL) { return TCL_ERROR; } Tcl_GetVariableFullName(interp, variable, Tcl_GetObjResult(interp)); return TCL_OK; } /* *---------------------------------------------------------------------- * * GetTimesObjCmd -- * * This procedure implements the "gettimes" command. It is used for * computing the time needed for various basic operations such as reading * variables, allocating memory, sprintf, converting variables, etc. * * Results: * A standard Tcl result. * * Side effects: * Allocates and frees memory, sets a variable "a" in the interpreter. * *---------------------------------------------------------------------- */ static int GetTimesObjCmd( ClientData unused, /* Unused. */ Tcl_Interp *interp, /* The current interpreter. */ int notused1, /* Number of arguments. */ Tcl_Obj *const notused2[]) /* The argument objects. */ { Interp *iPtr = (Interp *) interp; int i, n; double timePer; Tcl_Time start, stop; Tcl_Obj *objPtr, **objv; const char *s; char newString[TCL_INTEGER_SPACE]; /* alloc & free 100000 times */ fprintf(stderr, "alloc & free 100000 6 word items\n"); Tcl_GetTime(&start); for (i = 0; i < 100000; i++) { objPtr = ckalloc(sizeof(Tcl_Obj)); ckfree(objPtr); } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per alloc+free\n", timePer/100000); /* alloc 5000 times */ fprintf(stderr, "alloc 5000 6 word items\n"); objv = ckalloc(5000 * sizeof(Tcl_Obj *)); Tcl_GetTime(&start); for (i = 0; i < 5000; i++) { objv[i] = ckalloc(sizeof(Tcl_Obj)); } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per alloc\n", timePer/5000); /* free 5000 times */ fprintf(stderr, "free 5000 6 word items\n"); Tcl_GetTime(&start); for (i = 0; i < 5000; i++) { ckfree(objv[i]); } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per free\n", timePer/5000); /* Tcl_NewObj 5000 times */ fprintf(stderr, "Tcl_NewObj 5000 times\n"); Tcl_GetTime(&start); for (i = 0; i < 5000; i++) { objv[i] = Tcl_NewObj(); } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per Tcl_NewObj\n", timePer/5000); /* Tcl_DecrRefCount 5000 times */ fprintf(stderr, "Tcl_DecrRefCount 5000 times\n"); Tcl_GetTime(&start); for (i = 0; i < 5000; i++) { objPtr = objv[i]; Tcl_DecrRefCount(objPtr); } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per Tcl_DecrRefCount\n", timePer/5000); ckfree(objv); /* TclGetString 100000 times */ fprintf(stderr, "TclGetStringFromObj of \"12345\" 100000 times\n"); objPtr = Tcl_NewStringObj("12345", -1); Tcl_GetTime(&start); for (i = 0; i < 100000; i++) { (void) TclGetString(objPtr); } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per TclGetStringFromObj of \"12345\"\n", timePer/100000); /* Tcl_GetIntFromObj 100000 times */ fprintf(stderr, "Tcl_GetIntFromObj of \"12345\" 100000 times\n"); Tcl_GetTime(&start); for (i = 0; i < 100000; i++) { if (Tcl_GetIntFromObj(interp, objPtr, &n) != TCL_OK) { return TCL_ERROR; } } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per Tcl_GetIntFromObj of \"12345\"\n", timePer/100000); Tcl_DecrRefCount(objPtr); /* Tcl_GetInt 100000 times */ fprintf(stderr, "Tcl_GetInt of \"12345\" 100000 times\n"); Tcl_GetTime(&start); for (i = 0; i < 100000; i++) { if (Tcl_GetInt(interp, "12345", &n) != TCL_OK) { return TCL_ERROR; } } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per Tcl_GetInt of \"12345\"\n", timePer/100000); /* sprintf 100000 times */ fprintf(stderr, "sprintf of 12345 100000 times\n"); Tcl_GetTime(&start); for (i = 0; i < 100000; i++) { sprintf(newString, "%d", 12345); } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per sprintf of 12345\n", timePer/100000); /* hashtable lookup 100000 times */ fprintf(stderr, "hashtable lookup of \"gettimes\" 100000 times\n"); Tcl_GetTime(&start); for (i = 0; i < 100000; i++) { (void) Tcl_FindHashEntry(&iPtr->globalNsPtr->cmdTable, "gettimes"); } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per hashtable lookup of \"gettimes\"\n", timePer/100000); /* Tcl_SetVar 100000 times */ fprintf(stderr, "Tcl_SetVar of \"12345\" 100000 times\n"); Tcl_GetTime(&start); for (i = 0; i < 100000; i++) { s = Tcl_SetVar(interp, "a", "12345", TCL_LEAVE_ERR_MSG); if (s == NULL) { return TCL_ERROR; } } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per Tcl_SetVar of a to \"12345\"\n", timePer/100000); /* Tcl_GetVar 100000 times */ fprintf(stderr, "Tcl_GetVar of a==\"12345\" 100000 times\n"); Tcl_GetTime(&start); for (i = 0; i < 100000; i++) { s = Tcl_GetVar(interp, "a", TCL_LEAVE_ERR_MSG); if (s == NULL) { return TCL_ERROR; } } Tcl_GetTime(&stop); timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec); fprintf(stderr, " %.3f usec per Tcl_GetVar of a==\"12345\"\n", timePer/100000); Tcl_ResetResult(interp); return TCL_OK; } /* *---------------------------------------------------------------------- * * NoopCmd -- * * This procedure is just used to time the overhead involved in * parsing and invoking a command. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int NoopCmd( ClientData unused, /* Unused. */ Tcl_Interp *interp, /* The current interpreter. */ int argc, /* The number of arguments. */ const char **argv) /* The argument strings. */ { return TCL_OK; } /* *---------------------------------------------------------------------- * * NoopObjCmd -- * * This object-based procedure is just used to time the overhead * involved in parsing and invoking a command. * * Results: * Returns the TCL_OK result code. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int NoopObjCmd( ClientData unused, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { return TCL_OK; } /* *---------------------------------------------------------------------- * * TestbytestringObjCmd -- * * This object-based procedure constructs a string which can * possibly contain invalid UTF-8 bytes. * * Results: * Returns the TCL_OK result code. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestbytestringObjCmd( ClientData unused, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { int n; const char *p; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "bytearray"); return TCL_ERROR; } p = (const char *)Tcl_GetByteArrayFromObj(objv[1], &n); Tcl_SetObjResult(interp, Tcl_NewStringObj(p, n)); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestsetCmd -- * * Implements the "testset{err,noerr}" cmds that are used when testing * Tcl_Set/GetVar C Api with/without TCL_LEAVE_ERR_MSG flag * * Results: * A standard Tcl result. * * Side effects: * Variables may be set. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestsetCmd( ClientData data, /* Additional flags for Get/SetVar2. */ register Tcl_Interp *interp,/* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { int flags = PTR2INT(data); const char *value; if (argc == 2) { Tcl_SetResult(interp, "before get", TCL_STATIC); value = Tcl_GetVar2(interp, argv[1], NULL, flags); if (value == NULL) { return TCL_ERROR; } Tcl_AppendElement(interp, value); return TCL_OK; } else if (argc == 3) { Tcl_SetResult(interp, "before set", TCL_STATIC); value = Tcl_SetVar2(interp, argv[1], NULL, argv[2], flags); if (value == NULL) { return TCL_ERROR; } Tcl_AppendElement(interp, value); return TCL_OK; } else { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " varName ?newValue?\"", NULL); return TCL_ERROR; } } static int Testset2Cmd( ClientData data, /* Additional flags for Get/SetVar2. */ register Tcl_Interp *interp,/* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { int flags = PTR2INT(data); const char *value; if (argc == 3) { Tcl_SetResult(interp, "before get", TCL_STATIC); value = Tcl_GetVar2(interp, argv[1], argv[2], flags); if (value == NULL) { return TCL_ERROR; } Tcl_AppendElement(interp, value); return TCL_OK; } else if (argc == 4) { Tcl_SetResult(interp, "before set", TCL_STATIC); value = Tcl_SetVar2(interp, argv[1], argv[2], argv[3], flags); if (value == NULL) { return TCL_ERROR; } Tcl_AppendElement(interp, value); return TCL_OK; } else { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " varName elemName ?newValue?\"", NULL); return TCL_ERROR; } } #ifndef TCL_NO_DEPRECATED /* *---------------------------------------------------------------------- * * TestsaveresultCmd -- * * Implements the "testsaveresult" cmd that is used when testing the * Tcl_SaveResult, Tcl_RestoreResult, and Tcl_DiscardResult interfaces. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestsaveresultCmd( ClientData dummy, /* Not used. */ register Tcl_Interp *interp,/* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { Interp* iPtr = (Interp*) interp; int discard, result, index; Tcl_SavedResult state; Tcl_Obj *objPtr; static const char *const optionStrings[] = { "append", "dynamic", "free", "object", "small", NULL }; enum options { RESULT_APPEND, RESULT_DYNAMIC, RESULT_FREE, RESULT_OBJECT, RESULT_SMALL }; /* * Parse arguments */ if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "type script discard"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, objv[3], &discard) != TCL_OK) { return TCL_ERROR; } objPtr = NULL; /* Lint. */ switch ((enum options) index) { case RESULT_SMALL: Tcl_SetResult(interp, "small result", TCL_VOLATILE); break; case RESULT_APPEND: Tcl_AppendResult(interp, "append result", NULL); break; case RESULT_FREE: { char *buf = ckalloc(200); strcpy(buf, "free result"); Tcl_SetResult(interp, buf, TCL_DYNAMIC); break; } case RESULT_DYNAMIC: Tcl_SetResult(interp, (char *)"dynamic result", TestsaveresultFree); break; case RESULT_OBJECT: objPtr = Tcl_NewStringObj("object result", -1); Tcl_SetObjResult(interp, objPtr); break; } freeCount = 0; Tcl_SaveResult(interp, &state); if (((enum options) index) == RESULT_OBJECT) { result = Tcl_EvalObjEx(interp, objv[2], 0); } else { result = Tcl_Eval(interp, Tcl_GetString(objv[2])); } if (discard) { Tcl_DiscardResult(&state); } else { Tcl_RestoreResult(interp, &state); result = TCL_OK; } switch ((enum options) index) { case RESULT_DYNAMIC: { int present = iPtr->freeProc == TestsaveresultFree; int called = freeCount; Tcl_AppendElement(interp, called ? "called" : "notCalled"); Tcl_AppendElement(interp, present ? "present" : "missing"); break; } case RESULT_OBJECT: Tcl_AppendElement(interp, Tcl_GetObjResult(interp) == objPtr ? "same" : "different"); break; default: break; } return result; } /* *---------------------------------------------------------------------- * * TestsaveresultFree -- * * Special purpose freeProc used by TestsaveresultCmd. * * Results: * None. * * Side effects: * Increments the freeCount. * *---------------------------------------------------------------------- */ static void TestsaveresultFree( char *blockPtr) { freeCount++; } #endif /* TCL_NO_DEPRECATED */ /* *---------------------------------------------------------------------- * * TestmainthreadCmd -- * * Implements the "testmainthread" cmd that is used to test the * 'Tcl_GetCurrentThread' API. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestmainthreadCmd( ClientData dummy, /* Not used. */ register Tcl_Interp *interp,/* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { if (argc == 1) { Tcl_Obj *idObj = Tcl_NewLongObj((long)(size_t)Tcl_GetCurrentThread()); Tcl_SetObjResult(interp, idObj); return TCL_OK; } else { Tcl_SetResult(interp, "wrong # args", TCL_STATIC); return TCL_ERROR; } } /* *---------------------------------------------------------------------- * * MainLoop -- * * A main loop set by TestsetmainloopCmd below. * * Results: * None. * * Side effects: * Event handlers could do anything. * *---------------------------------------------------------------------- */ static void MainLoop(void) { while (!exitMainLoop) { Tcl_DoOneEvent(0); } fprintf(stdout,"Exit MainLoop\n"); fflush(stdout); } /* *---------------------------------------------------------------------- * * TestsetmainloopCmd -- * * Implements the "testsetmainloop" cmd that is used to test the * 'Tcl_SetMainLoop' API. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestsetmainloopCmd( ClientData dummy, /* Not used. */ register Tcl_Interp *interp,/* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { exitMainLoop = 0; Tcl_SetMainLoop(MainLoop); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestexitmainloopCmd -- * * Implements the "testexitmainloop" cmd that is used to test the * 'Tcl_SetMainLoop' API. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestexitmainloopCmd( ClientData dummy, /* Not used. */ register Tcl_Interp *interp,/* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { exitMainLoop = 1; return TCL_OK; } /* *---------------------------------------------------------------------- * * TestChannelCmd -- * * Implements the Tcl "testchannel" debugging command and its * subcommands. This is part of the testing environment. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestChannelCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Interpreter for result. */ int argc, /* Count of additional args. */ const char **argv) /* Additional arg strings. */ { const char *cmdName; /* Sub command. */ Tcl_HashTable *hTblPtr; /* Hash table of channels. */ Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ Channel *chanPtr; /* The actual channel. */ ChannelState *statePtr; /* state info for channel */ Tcl_Channel chan; /* The opaque type. */ size_t len; /* Length of subcommand string. */ int IOQueued; /* How much IO is queued inside channel? */ char buf[TCL_INTEGER_SPACE];/* For sprintf. */ int mode; /* rw mode of the channel */ if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " subcommand ?additional args..?\"", NULL); return TCL_ERROR; } cmdName = argv[1]; len = strlen(cmdName); chanPtr = NULL; if (argc > 2) { if ((cmdName[0] == 's') && (strncmp(cmdName, "splice", len) == 0)) { /* For splice access the pool of detached channels. * Locate channel, remove from the list. */ TestChannel **nextPtrPtr, *curPtr; chan = (Tcl_Channel) NULL; for (nextPtrPtr = &firstDetached, curPtr = firstDetached; curPtr != NULL; nextPtrPtr = &(curPtr->nextPtr), curPtr = curPtr->nextPtr) { if (strcmp(argv[2], Tcl_GetChannelName(curPtr->chan)) == 0) { *nextPtrPtr = curPtr->nextPtr; curPtr->nextPtr = NULL; chan = curPtr->chan; ckfree(curPtr); break; } } } else { chan = Tcl_GetChannel(interp, argv[2], &mode); } if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } chanPtr = (Channel *) chan; statePtr = chanPtr->state; chanPtr = statePtr->topChanPtr; chan = (Tcl_Channel) chanPtr; } else { /* lint */ statePtr = NULL; chan = NULL; } if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerror", len) == 0)) { Tcl_Obj *msg = Tcl_NewStringObj(argv[3],-1); Tcl_IncrRefCount(msg); Tcl_SetChannelError(chan, msg); Tcl_DecrRefCount(msg); Tcl_GetChannelError(chan, &msg); Tcl_SetObjResult(interp, msg); Tcl_DecrRefCount(msg); return TCL_OK; } if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerrorinterp", len) == 0)) { Tcl_Obj *msg = Tcl_NewStringObj(argv[3],-1); Tcl_IncrRefCount(msg); Tcl_SetChannelErrorInterp(interp, msg); Tcl_DecrRefCount(msg); Tcl_GetChannelErrorInterp(interp, &msg); Tcl_SetObjResult(interp, msg); Tcl_DecrRefCount(msg); return TCL_OK; } /* * "cut" is actually more a simplified detach facility as provided by the * Thread package. Without the safeguards of a regular command (no * checking that the command is truly cut'able, no mutexes for * thread-safety). Its complementary command is "splice", see below. */ if ((cmdName[0] == 'c') && (strncmp(cmdName, "cut", len) == 0)) { TestChannel *det; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " cut channelName\"", NULL); return TCL_ERROR; } Tcl_RegisterChannel(NULL, chan); /* prevent closing */ Tcl_UnregisterChannel(interp, chan); Tcl_CutChannel(chan); /* Remember the channel in the pool of detached channels */ det = ckalloc(sizeof(TestChannel)); det->chan = chan; det->nextPtr = firstDetached; firstDetached = det; return TCL_OK; } if ((cmdName[0] == 'c') && (strncmp(cmdName, "clearchannelhandlers", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " clearchannelhandlers channelName\"", NULL); return TCL_ERROR; } Tcl_ClearChannelHandlers(chan); return TCL_OK; } if ((cmdName[0] == 'i') && (strncmp(cmdName, "info", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " info channelName\"", NULL); return TCL_ERROR; } Tcl_AppendElement(interp, argv[2]); Tcl_AppendElement(interp, Tcl_ChannelName(chanPtr->typePtr)); if (statePtr->flags & TCL_READABLE) { Tcl_AppendElement(interp, "read"); } else { Tcl_AppendElement(interp, ""); } if (statePtr->flags & TCL_WRITABLE) { Tcl_AppendElement(interp, "write"); } else { Tcl_AppendElement(interp, ""); } if (statePtr->flags & CHANNEL_NONBLOCKING) { Tcl_AppendElement(interp, "nonblocking"); } else { Tcl_AppendElement(interp, "blocking"); } if (statePtr->flags & CHANNEL_LINEBUFFERED) { Tcl_AppendElement(interp, "line"); } else if (statePtr->flags & CHANNEL_UNBUFFERED) { Tcl_AppendElement(interp, "none"); } else { Tcl_AppendElement(interp, "full"); } if (statePtr->flags & BG_FLUSH_SCHEDULED) { Tcl_AppendElement(interp, "async_flush"); } else { Tcl_AppendElement(interp, ""); } if (statePtr->flags & CHANNEL_EOF) { Tcl_AppendElement(interp, "eof"); } else { Tcl_AppendElement(interp, ""); } if (statePtr->flags & CHANNEL_BLOCKED) { Tcl_AppendElement(interp, "blocked"); } else { Tcl_AppendElement(interp, "unblocked"); } if (statePtr->inputTranslation == TCL_TRANSLATE_AUTO) { Tcl_AppendElement(interp, "auto"); if (statePtr->flags & INPUT_SAW_CR) { Tcl_AppendElement(interp, "saw_cr"); } else { Tcl_AppendElement(interp, ""); } } else if (statePtr->inputTranslation == TCL_TRANSLATE_LF) { Tcl_AppendElement(interp, "lf"); Tcl_AppendElement(interp, ""); } else if (statePtr->inputTranslation == TCL_TRANSLATE_CR) { Tcl_AppendElement(interp, "cr"); Tcl_AppendElement(interp, ""); } else if (statePtr->inputTranslation == TCL_TRANSLATE_CRLF) { Tcl_AppendElement(interp, "crlf"); if (statePtr->flags & INPUT_SAW_CR) { Tcl_AppendElement(interp, "queued_cr"); } else { Tcl_AppendElement(interp, ""); } } if (statePtr->outputTranslation == TCL_TRANSLATE_AUTO) { Tcl_AppendElement(interp, "auto"); } else if (statePtr->outputTranslation == TCL_TRANSLATE_LF) { Tcl_AppendElement(interp, "lf"); } else if (statePtr->outputTranslation == TCL_TRANSLATE_CR) { Tcl_AppendElement(interp, "cr"); } else if (statePtr->outputTranslation == TCL_TRANSLATE_CRLF) { Tcl_AppendElement(interp, "crlf"); } IOQueued = Tcl_InputBuffered(chan); TclFormatInt(buf, IOQueued); Tcl_AppendElement(interp, buf); IOQueued = Tcl_OutputBuffered(chan); TclFormatInt(buf, IOQueued); Tcl_AppendElement(interp, buf); TclFormatInt(buf, (int)Tcl_Tell(chan)); Tcl_AppendElement(interp, buf); TclFormatInt(buf, statePtr->refCount); Tcl_AppendElement(interp, buf); return TCL_OK; } if ((cmdName[0] == 'i') && (strncmp(cmdName, "inputbuffered", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "channel name required", NULL); return TCL_ERROR; } IOQueued = Tcl_InputBuffered(chan); TclFormatInt(buf, IOQueued); Tcl_AppendResult(interp, buf, NULL); return TCL_OK; } if ((cmdName[0] == 'i') && (strncmp(cmdName, "isshared", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "channel name required", NULL); return TCL_ERROR; } TclFormatInt(buf, Tcl_IsChannelShared(chan)); Tcl_AppendResult(interp, buf, NULL); return TCL_OK; } if ((cmdName[0] == 'i') && (strncmp(cmdName, "isstandard", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "channel name required", NULL); return TCL_ERROR; } TclFormatInt(buf, Tcl_IsStandardChannel(chan)); Tcl_AppendResult(interp, buf, NULL); return TCL_OK; } if ((cmdName[0] == 'm') && (strncmp(cmdName, "mode", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "channel name required", NULL); return TCL_ERROR; } if (statePtr->flags & TCL_READABLE) { Tcl_AppendElement(interp, "read"); } else { Tcl_AppendElement(interp, ""); } if (statePtr->flags & TCL_WRITABLE) { Tcl_AppendElement(interp, "write"); } else { Tcl_AppendElement(interp, ""); } return TCL_OK; } if ((cmdName[0] == 'm') && (strncmp(cmdName, "mthread", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "channel name required", NULL); return TCL_ERROR; } TclFormatInt(buf, (size_t) Tcl_GetChannelThread(chan)); Tcl_AppendResult(interp, buf, NULL); return TCL_OK; } if ((cmdName[0] == 'n') && (strncmp(cmdName, "name", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "channel name required", NULL); return TCL_ERROR; } Tcl_AppendResult(interp, statePtr->channelName, NULL); return TCL_OK; } if ((cmdName[0] == 'o') && (strncmp(cmdName, "open", len) == 0)) { hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL); if (hTblPtr == NULL) { return TCL_OK; } for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr)); } return TCL_OK; } if ((cmdName[0] == 'o') && (strncmp(cmdName, "outputbuffered", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "channel name required", NULL); return TCL_ERROR; } IOQueued = Tcl_OutputBuffered(chan); TclFormatInt(buf, IOQueued); Tcl_AppendResult(interp, buf, NULL); return TCL_OK; } if ((cmdName[0] == 'q') && (strncmp(cmdName, "queuedcr", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "channel name required", NULL); return TCL_ERROR; } Tcl_AppendResult(interp, (statePtr->flags & INPUT_SAW_CR) ? "1" : "0", NULL); return TCL_OK; } if ((cmdName[0] == 'r') && (strncmp(cmdName, "readable", len) == 0)) { hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL); if (hTblPtr == NULL) { return TCL_OK; } for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { chanPtr = (Channel *) Tcl_GetHashValue(hPtr); statePtr = chanPtr->state; if (statePtr->flags & TCL_READABLE) { Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr)); } } return TCL_OK; } if ((cmdName[0] == 'r') && (strncmp(cmdName, "refcount", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "channel name required", NULL); return TCL_ERROR; } TclFormatInt(buf, statePtr->refCount); Tcl_AppendResult(interp, buf, NULL); return TCL_OK; } /* * "splice" is actually more a simplified attach facility as provided by * the Thread package. Without the safeguards of a regular command (no * checking that the command is truly cut'able, no mutexes for * thread-safety). Its complementary command is "cut", see above. */ if ((cmdName[0] == 's') && (strncmp(cmdName, "splice", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "channel name required", NULL); return TCL_ERROR; } Tcl_SpliceChannel(chan); Tcl_RegisterChannel(interp, chan); Tcl_UnregisterChannel(NULL, chan); return TCL_OK; } if ((cmdName[0] == 't') && (strncmp(cmdName, "type", len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "channel name required", NULL); return TCL_ERROR; } Tcl_AppendResult(interp, Tcl_ChannelName(chanPtr->typePtr), NULL); return TCL_OK; } if ((cmdName[0] == 'w') && (strncmp(cmdName, "writable", len) == 0)) { hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL); if (hTblPtr == NULL) { return TCL_OK; } for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { chanPtr = (Channel *) Tcl_GetHashValue(hPtr); statePtr = chanPtr->state; if (statePtr->flags & TCL_WRITABLE) { Tcl_AppendElement(interp, Tcl_GetHashKey(hTblPtr, hPtr)); } } return TCL_OK; } if ((cmdName[0] == 't') && (strncmp(cmdName, "transform", len) == 0)) { /* * Syntax: transform channel -command command */ if (argc != 5) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " transform channelId -command cmd\"", NULL); return TCL_ERROR; } if (strcmp(argv[3], "-command") != 0) { Tcl_AppendResult(interp, "bad argument \"", argv[3], "\": should be \"-command\"", NULL); return TCL_ERROR; } return TclChannelTransform(interp, chan, Tcl_NewStringObj(argv[4], -1)); } if ((cmdName[0] == 'u') && (strncmp(cmdName, "unstack", len) == 0)) { /* * Syntax: unstack channel */ if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " unstack channel\"", NULL); return TCL_ERROR; } return Tcl_UnstackChannel(interp, chan); } Tcl_AppendResult(interp, "bad option \"", cmdName, "\": should be " "cut, clearchannelhandlers, info, isshared, mode, open, " "readable, splice, writable, transform, unstack", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TestChannelEventCmd -- * * This procedure implements the "testchannelevent" command. It is used * to test the Tcl channel event mechanism. * * Results: * A standard Tcl result. * * Side effects: * Creates, deletes and returns channel event handlers. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int TestChannelEventCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { Tcl_Obj *resultListPtr; Channel *chanPtr; ChannelState *statePtr; /* state info for channel */ EventScriptRecord *esPtr, *prevEsPtr, *nextEsPtr; const char *cmd; int index, i, mask, len; if ((argc < 3) || (argc > 5)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " channelName cmd ?arg1? ?arg2?\"", NULL); return TCL_ERROR; } chanPtr = (Channel *) Tcl_GetChannel(interp, argv[1], NULL); if (chanPtr == NULL) { return TCL_ERROR; } statePtr = chanPtr->state; cmd = argv[2]; len = strlen(cmd); if ((cmd[0] == 'a') && (strncmp(cmd, "add", (unsigned) len) == 0)) { if (argc != 5) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " channelName add eventSpec script\"", NULL); return TCL_ERROR; } if (strcmp(argv[3], "readable") == 0) { mask = TCL_READABLE; } else if (strcmp(argv[3], "writable") == 0) { mask = TCL_WRITABLE; } else if (strcmp(argv[3], "none") == 0) { mask = 0; } else { Tcl_AppendResult(interp, "bad event name \"", argv[3], "\": must be readable, writable, or none", NULL); return TCL_ERROR; } esPtr = ckalloc(sizeof(EventScriptRecord)); esPtr->nextPtr = statePtr->scriptRecordPtr; statePtr->scriptRecordPtr = esPtr; esPtr->chanPtr = chanPtr; esPtr->interp = interp; esPtr->mask = mask; esPtr->scriptPtr = Tcl_NewStringObj(argv[4], -1); Tcl_IncrRefCount(esPtr->scriptPtr); Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask, TclChannelEventScriptInvoker, (ClientData) esPtr); return TCL_OK; } if ((cmd[0] == 'd') && (strncmp(cmd, "delete", (unsigned) len) == 0)) { if (argc != 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " channelName delete index\"", NULL); return TCL_ERROR; } if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) { return TCL_ERROR; } if (index < 0) { Tcl_AppendResult(interp, "bad event index: ", argv[3], ": must be nonnegative", NULL); return TCL_ERROR; } for (i = 0, esPtr = statePtr->scriptRecordPtr; (i < index) && (esPtr != NULL); i++, esPtr = esPtr->nextPtr) { /* Empty loop body. */ } if (esPtr == NULL) { Tcl_AppendResult(interp, "bad event index ", argv[3], ": out of range", NULL); return TCL_ERROR; } if (esPtr == statePtr->scriptRecordPtr) { statePtr->scriptRecordPtr = esPtr->nextPtr; } else { for (prevEsPtr = statePtr->scriptRecordPtr; (prevEsPtr != NULL) && (prevEsPtr->nextPtr != esPtr); prevEsPtr = prevEsPtr->nextPtr) { /* Empty loop body. */ } if (prevEsPtr == NULL) { Tcl_Panic("TestChannelEventCmd: damaged event script list"); } prevEsPtr->nextPtr = esPtr->nextPtr; } Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, TclChannelEventScriptInvoker, (ClientData) esPtr); Tcl_DecrRefCount(esPtr->scriptPtr); ckfree(esPtr); return TCL_OK; } if ((cmd[0] == 'l') && (strncmp(cmd, "list", (unsigned) len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " channelName list\"", NULL); return TCL_ERROR; } resultListPtr = Tcl_GetObjResult(interp); for (esPtr = statePtr->scriptRecordPtr; esPtr != NULL; esPtr = esPtr->nextPtr) { if (esPtr->mask) { Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj( (esPtr->mask == TCL_READABLE) ? "readable" : "writable", -1)); } else { Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj("none", -1)); } Tcl_ListObjAppendElement(interp, resultListPtr, esPtr->scriptPtr); } Tcl_SetObjResult(interp, resultListPtr); return TCL_OK; } if ((cmd[0] == 'r') && (strncmp(cmd, "removeall", (unsigned) len) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " channelName removeall\"", NULL); return TCL_ERROR; } for (esPtr = statePtr->scriptRecordPtr; esPtr != NULL; esPtr = nextEsPtr) { nextEsPtr = esPtr->nextPtr; Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, TclChannelEventScriptInvoker, (ClientData) esPtr); Tcl_DecrRefCount(esPtr->scriptPtr); ckfree(esPtr); } statePtr->scriptRecordPtr = NULL; return TCL_OK; } if ((cmd[0] == 's') && (strncmp(cmd, "set", (unsigned) len) == 0)) { if (argc != 5) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " channelName delete index event\"", NULL); return TCL_ERROR; } if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) { return TCL_ERROR; } if (index < 0) { Tcl_AppendResult(interp, "bad event index: ", argv[3], ": must be nonnegative", NULL); return TCL_ERROR; } for (i = 0, esPtr = statePtr->scriptRecordPtr; (i < index) && (esPtr != NULL); i++, esPtr = esPtr->nextPtr) { /* Empty loop body. */ } if (esPtr == NULL) { Tcl_AppendResult(interp, "bad event index ", argv[3], ": out of range", NULL); return TCL_ERROR; } if (strcmp(argv[4], "readable") == 0) { mask = TCL_READABLE; } else if (strcmp(argv[4], "writable") == 0) { mask = TCL_WRITABLE; } else if (strcmp(argv[4], "none") == 0) { mask = 0; } else { Tcl_AppendResult(interp, "bad event name \"", argv[4], "\": must be readable, writable, or none", NULL); return TCL_ERROR; } esPtr->mask = mask; Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask, TclChannelEventScriptInvoker, (ClientData) esPtr); return TCL_OK; } Tcl_AppendResult(interp, "bad command ", cmd, ", must be one of " "add, delete, list, set, or removeall", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TestWrongNumArgsObjCmd -- * * Test the Tcl_WrongNumArgs function. * * Results: * Standard Tcl result. * * Side effects: * Sets interpreter result. * *---------------------------------------------------------------------- */ static int TestWrongNumArgsObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int i, length; const char *msg; if (objc < 3) { /* * Don't use Tcl_WrongNumArgs here, as that is the function * we want to test! */ Tcl_SetResult(interp, "insufficient arguments", TCL_STATIC); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[1], &i) != TCL_OK) { return TCL_ERROR; } msg = Tcl_GetStringFromObj(objv[2], &length); if (length == 0) { msg = NULL; } if (i > objc - 3) { /* * Asked for more arguments than were given. */ Tcl_SetResult(interp, "insufficient arguments", TCL_STATIC); return TCL_ERROR; } Tcl_WrongNumArgs(interp, i, &(objv[3]), msg); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestGetIndexFromObjStructObjCmd -- * * Test the Tcl_GetIndexFromObjStruct function. * * Results: * Standard Tcl result. * * Side effects: * Sets interpreter result. * *---------------------------------------------------------------------- */ static int TestGetIndexFromObjStructObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *const ary[] = { "a", "b", "c", "d", "e", "f", NULL, NULL }; int idx,target; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "argument targetvalue"); return TCL_ERROR; } if (Tcl_GetIndexFromObjStruct(interp, objv[1], ary, 2*sizeof(char *), "dummy", 0, &idx) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[2], &target) != TCL_OK) { return TCL_ERROR; } if (idx != target) { char buffer[64]; sprintf(buffer, "%d", idx); Tcl_AppendResult(interp, "index value comparison failed: got ", buffer, NULL); sprintf(buffer, "%d", target); Tcl_AppendResult(interp, " when ", buffer, " expected", NULL); return TCL_ERROR; } Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestFilesystemObjCmd -- * * This procedure implements the "testfilesystem" command. It is used to * test Tcl_FSRegister, Tcl_FSUnregister, and can be used to test that * the pluggable filesystem works. * * Results: * A standard Tcl result. * * Side effects: * Inserts or removes a filesystem from Tcl's stack. * *---------------------------------------------------------------------- */ static int TestFilesystemObjCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int res, boolVal; const char *msg; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "boolean"); return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, objv[1], &boolVal) != TCL_OK) { return TCL_ERROR; } if (boolVal) { res = Tcl_FSRegister((ClientData)interp, &testReportingFilesystem); msg = (res == TCL_OK) ? "registered" : "failed"; } else { res = Tcl_FSUnregister(&testReportingFilesystem); msg = (res == TCL_OK) ? "unregistered" : "failed"; } Tcl_SetObjResult(interp, Tcl_NewStringObj(msg , -1)); return res; } static int TestReportInFilesystem( Tcl_Obj *pathPtr, ClientData *clientDataPtr) { static Tcl_Obj *lastPathPtr = NULL; Tcl_Obj *newPathPtr; if (pathPtr == lastPathPtr) { /* Reject all files second time around */ return -1; } /* Try to claim all files first time around */ newPathPtr = Tcl_DuplicateObj(pathPtr); lastPathPtr = newPathPtr; Tcl_IncrRefCount(newPathPtr); if (Tcl_FSGetFileSystemForPath(newPathPtr) == NULL) { /* Nothing claimed it. Therefore we don't either */ Tcl_DecrRefCount(newPathPtr); lastPathPtr = NULL; return -1; } lastPathPtr = NULL; *clientDataPtr = (ClientData) newPathPtr; return TCL_OK; } /* * Simple helper function to extract the native vfs representation of a path * object, or NULL if no such representation exists. */ static Tcl_Obj * TestReportGetNativePath( Tcl_Obj *pathPtr) { return (Tcl_Obj*) Tcl_FSGetInternalRep(pathPtr, &testReportingFilesystem); } static void TestReportFreeInternalRep( ClientData clientData) { Tcl_Obj *nativeRep = (Tcl_Obj *) clientData; if (nativeRep != NULL) { /* Free the path */ Tcl_DecrRefCount(nativeRep); } } static ClientData TestReportDupInternalRep( ClientData clientData) { Tcl_Obj *original = (Tcl_Obj *) clientData; Tcl_IncrRefCount(original); return clientData; } static void TestReport( const char *cmd, Tcl_Obj *path, Tcl_Obj *arg2) { Tcl_Interp *interp = (Tcl_Interp *) Tcl_FSData(&testReportingFilesystem); if (interp == NULL) { /* This is bad, but not much we can do about it */ } else { /* * No idea why I decided to program this up using the old string-based * API, but there you go. We should convert it to objects. */ Tcl_Obj *savedResult; Tcl_DString ds; Tcl_DStringInit(&ds); Tcl_DStringAppend(&ds, "lappend filesystemReport ", -1); Tcl_DStringStartSublist(&ds); Tcl_DStringAppendElement(&ds, cmd); if (path != NULL) { Tcl_DStringAppendElement(&ds, Tcl_GetString(path)); } if (arg2 != NULL) { Tcl_DStringAppendElement(&ds, Tcl_GetString(arg2)); } Tcl_DStringEndSublist(&ds); savedResult = Tcl_GetObjResult(interp); Tcl_IncrRefCount(savedResult); Tcl_SetObjResult(interp, Tcl_NewObj()); Tcl_Eval(interp, Tcl_DStringValue(&ds)); Tcl_DStringFree(&ds); Tcl_ResetResult(interp); Tcl_SetObjResult(interp, savedResult); Tcl_DecrRefCount(savedResult); } } static int TestReportStat( Tcl_Obj *path, /* Path of file to stat (in current CP). */ Tcl_StatBuf *buf) /* Filled with results of stat call. */ { TestReport("stat", path, NULL); return Tcl_FSStat(TestReportGetNativePath(path), buf); } static int TestReportLstat( Tcl_Obj *path, /* Path of file to stat (in current CP). */ Tcl_StatBuf *buf) /* Filled with results of stat call. */ { TestReport("lstat", path, NULL); return Tcl_FSLstat(TestReportGetNativePath(path), buf); } static int TestReportAccess( Tcl_Obj *path, /* Path of file to access (in current CP). */ int mode) /* Permission setting. */ { TestReport("access", path, NULL); return Tcl_FSAccess(TestReportGetNativePath(path), mode); } static Tcl_Channel TestReportOpenFileChannel( Tcl_Interp *interp, /* Interpreter for error reporting; can be * NULL. */ Tcl_Obj *fileName, /* Name of file to open. */ int mode, /* POSIX open mode. */ int permissions) /* If the open involves creating a file, with * what modes to create it? */ { TestReport("open", fileName, NULL); return TclpOpenFileChannel(interp, TestReportGetNativePath(fileName), mode, permissions); } static int TestReportMatchInDirectory( Tcl_Interp *interp, /* Interpreter for error messages. */ Tcl_Obj *resultPtr, /* Object to lappend results. */ Tcl_Obj *dirPtr, /* Contains path to directory to search. */ const char *pattern, /* Pattern to match against. */ Tcl_GlobTypeData *types) /* Object containing list of acceptable types. * May be NULL. */ { if (types != NULL && types->type & TCL_GLOB_TYPE_MOUNT) { TestReport("matchmounts", dirPtr, NULL); return TCL_OK; } else { TestReport("matchindirectory", dirPtr, NULL); return Tcl_FSMatchInDirectory(interp, resultPtr, TestReportGetNativePath(dirPtr), pattern, types); } } static int TestReportChdir( Tcl_Obj *dirName) { TestReport("chdir", dirName, NULL); return Tcl_FSChdir(TestReportGetNativePath(dirName)); } static int TestReportLoadFile( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Obj *fileName, /* Name of the file containing the desired * code. */ Tcl_LoadHandle *handlePtr, /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr) /* Filled with address of Tcl_FSUnloadFileProc * function which should be used for * this file. */ { TestReport("loadfile", fileName, NULL); return Tcl_FSLoadFile(interp, TestReportGetNativePath(fileName), NULL, NULL, NULL, NULL, handlePtr, unloadProcPtr); } static Tcl_Obj * TestReportLink( Tcl_Obj *path, /* Path of file to readlink or link */ Tcl_Obj *to, /* Path of file to link to, or NULL */ int linkType) { TestReport("link", path, to); return Tcl_FSLink(TestReportGetNativePath(path), to, linkType); } static int TestReportRenameFile( Tcl_Obj *src, /* Pathname of file or dir to be renamed * (UTF-8). */ Tcl_Obj *dst) /* New pathname of file or directory * (UTF-8). */ { TestReport("renamefile", src, dst); return Tcl_FSRenameFile(TestReportGetNativePath(src), TestReportGetNativePath(dst)); } static int TestReportCopyFile( Tcl_Obj *src, /* Pathname of file to be copied (UTF-8). */ Tcl_Obj *dst) /* Pathname of file to copy to (UTF-8). */ { TestReport("copyfile", src, dst); return Tcl_FSCopyFile(TestReportGetNativePath(src), TestReportGetNativePath(dst)); } static int TestReportDeleteFile( Tcl_Obj *path) /* Pathname of file to be removed (UTF-8). */ { TestReport("deletefile", path, NULL); return Tcl_FSDeleteFile(TestReportGetNativePath(path)); } static int TestReportCreateDirectory( Tcl_Obj *path) /* Pathname of directory to create (UTF-8). */ { TestReport("createdirectory", path, NULL); return Tcl_FSCreateDirectory(TestReportGetNativePath(path)); } static int TestReportCopyDirectory( Tcl_Obj *src, /* Pathname of directory to be copied * (UTF-8). */ Tcl_Obj *dst, /* Pathname of target directory (UTF-8). */ Tcl_Obj **errorPtr) /* If non-NULL, to be filled with UTF-8 name * of file causing error. */ { TestReport("copydirectory", src, dst); return Tcl_FSCopyDirectory(TestReportGetNativePath(src), TestReportGetNativePath(dst), errorPtr); } static int TestReportRemoveDirectory( Tcl_Obj *path, /* Pathname of directory to be removed * (UTF-8). */ int recursive, /* If non-zero, removes directories that * are nonempty. Otherwise, will only remove * empty directories. */ Tcl_Obj **errorPtr) /* If non-NULL, to be filled with UTF-8 name * of file causing error. */ { TestReport("removedirectory", path, NULL); return Tcl_FSRemoveDirectory(TestReportGetNativePath(path), recursive, errorPtr); } static const char *const * TestReportFileAttrStrings( Tcl_Obj *fileName, Tcl_Obj **objPtrRef) { TestReport("fileattributestrings", fileName, NULL); return Tcl_FSFileAttrStrings(TestReportGetNativePath(fileName), objPtrRef); } static int TestReportFileAttrsGet( Tcl_Interp *interp, /* The interpreter for error reporting. */ int index, /* index of the attribute command. */ Tcl_Obj *fileName, /* filename we are operating on. */ Tcl_Obj **objPtrRef) /* for output. */ { TestReport("fileattributesget", fileName, NULL); return Tcl_FSFileAttrsGet(interp, index, TestReportGetNativePath(fileName), objPtrRef); } static int TestReportFileAttrsSet( Tcl_Interp *interp, /* The interpreter for error reporting. */ int index, /* index of the attribute command. */ Tcl_Obj *fileName, /* filename we are operating on. */ Tcl_Obj *objPtr) /* for input. */ { TestReport("fileattributesset", fileName, objPtr); return Tcl_FSFileAttrsSet(interp, index, TestReportGetNativePath(fileName), objPtr); } static int TestReportUtime( Tcl_Obj *fileName, struct utimbuf *tval) { TestReport("utime", fileName, NULL); return Tcl_FSUtime(TestReportGetNativePath(fileName), tval); } static int TestReportNormalizePath( Tcl_Interp *interp, Tcl_Obj *pathPtr, int nextCheckpoint) { TestReport("normalizepath", pathPtr, NULL); return nextCheckpoint; } static int SimplePathInFilesystem( Tcl_Obj *pathPtr, ClientData *clientDataPtr) { const char *str = Tcl_GetString(pathPtr); if (strncmp(str, "simplefs:/", 10)) { return -1; } return TCL_OK; } /* * This is a slightly 'hacky' filesystem which is used just to test a few * important features of the vfs code: (1) that you can load a shared library * from a vfs, (2) that when copying files from one fs to another, the 'mtime' * is preserved. (3) that recursive cross-filesystem directory copies have the * correct behaviour with/without -force. * * It treats any file in 'simplefs:/' as a file, which it routes to the * current directory. The real file it uses is whatever follows the trailing * '/' (e.g. 'foo' in 'simplefs:/foo'), and that file exists or not according * to what is in the native pwd. * * Please do not consider this filesystem a model of how things are to be * done. It is quite the opposite! But, it does allow us to test some * important features. */ static int TestSimpleFilesystemObjCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int res, boolVal; const char *msg; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "boolean"); return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, objv[1], &boolVal) != TCL_OK) { return TCL_ERROR; } if (boolVal) { res = Tcl_FSRegister((ClientData)interp, &simpleFilesystem); msg = (res == TCL_OK) ? "registered" : "failed"; } else { res = Tcl_FSUnregister(&simpleFilesystem); msg = (res == TCL_OK) ? "unregistered" : "failed"; } Tcl_SetObjResult(interp, Tcl_NewStringObj(msg , -1)); return res; } /* * Treats a file name 'simplefs:/foo' by using the file 'foo' in the current * (native) directory. */ static Tcl_Obj * SimpleRedirect( Tcl_Obj *pathPtr) /* Name of file to copy. */ { int len; const char *str; Tcl_Obj *origPtr; /* * We assume the same name in the current directory is ok. */ str = Tcl_GetStringFromObj(pathPtr, &len); if (len < 10 || strncmp(str, "simplefs:/", 10)) { /* Probably shouldn't ever reach here */ Tcl_IncrRefCount(pathPtr); return pathPtr; } origPtr = Tcl_NewStringObj(str+10,-1); Tcl_IncrRefCount(origPtr); return origPtr; } static int SimpleMatchInDirectory( Tcl_Interp *interp, /* Interpreter for error * messages. */ Tcl_Obj *resultPtr, /* Object to lappend results. */ Tcl_Obj *dirPtr, /* Contains path to directory to search. */ const char *pattern, /* Pattern to match against. */ Tcl_GlobTypeData *types) /* Object containing list of acceptable types. * May be NULL. */ { int res; Tcl_Obj *origPtr; Tcl_Obj *resPtr; /* We only provide a new volume, therefore no mounts at all */ if (types != NULL && types->type & TCL_GLOB_TYPE_MOUNT) { return TCL_OK; } /* * We assume the same name in the current directory is ok. */ resPtr = Tcl_NewObj(); Tcl_IncrRefCount(resPtr); origPtr = SimpleRedirect(dirPtr); res = Tcl_FSMatchInDirectory(interp, resPtr, origPtr, pattern, types); if (res == TCL_OK) { int gLength, j; Tcl_ListObjLength(NULL, resPtr, &gLength); for (j = 0; j < gLength; j++) { Tcl_Obj *gElt, *nElt; Tcl_ListObjIndex(NULL, resPtr, j, &gElt); nElt = Tcl_NewStringObj("simplefs:/",10); Tcl_AppendObjToObj(nElt, gElt); Tcl_ListObjAppendElement(NULL, resultPtr, nElt); } } Tcl_DecrRefCount(origPtr); Tcl_DecrRefCount(resPtr); return res; } static Tcl_Channel SimpleOpenFileChannel( Tcl_Interp *interp, /* Interpreter for error reporting; can be * NULL. */ Tcl_Obj *pathPtr, /* Name of file to open. */ int mode, /* POSIX open mode. */ int permissions) /* If the open involves creating a file, with * what modes to create it? */ { Tcl_Obj *tempPtr; Tcl_Channel chan; if ((mode != 0) && !(mode & O_RDONLY)) { Tcl_AppendResult(interp, "read-only", NULL); return NULL; } tempPtr = SimpleRedirect(pathPtr); chan = Tcl_FSOpenFileChannel(interp, tempPtr, "r", permissions); Tcl_DecrRefCount(tempPtr); return chan; } static int SimpleAccess( Tcl_Obj *pathPtr, /* Path of file to access (in current CP). */ int mode) /* Permission setting. */ { Tcl_Obj *tempPtr = SimpleRedirect(pathPtr); int res = Tcl_FSAccess(tempPtr, mode); Tcl_DecrRefCount(tempPtr); return res; } static int SimpleStat( Tcl_Obj *pathPtr, /* Path of file to stat (in current CP). */ Tcl_StatBuf *bufPtr) /* Filled with results of stat call. */ { Tcl_Obj *tempPtr = SimpleRedirect(pathPtr); int res = Tcl_FSStat(tempPtr, bufPtr); Tcl_DecrRefCount(tempPtr); return res; } static Tcl_Obj * SimpleListVolumes(void) { /* Add one new volume */ Tcl_Obj *retVal; retVal = Tcl_NewStringObj("simplefs:/", -1); Tcl_IncrRefCount(retVal); return retVal; } /* * Used to check correct string-length determining in Tcl_NumUtfChars */ static int TestNumUtfCharsCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc > 1) { int len = -1; if (objc > 2) { (void) Tcl_GetStringFromObj(objv[1], &len); } len = Tcl_NumUtfChars(Tcl_GetString(objv[1]), len); Tcl_SetObjResult(interp, Tcl_NewIntObj(len)); } return TCL_OK; } #if defined(HAVE_CPUID) || defined(_WIN32) /* *---------------------------------------------------------------------- * * TestcpuidCmd -- * * Retrieves CPU ID information. * * Usage: * testwincpuid * * Parameters: * eax - The value to pass in the EAX register to a CPUID instruction. * * Results: * Returns a four-element list containing the values from the EAX, EBX, * ECX and EDX registers returned from the CPUID instruction. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestcpuidCmd( ClientData dummy, Tcl_Interp* interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const * objv) /* Parameter vector */ { int status, index, i; unsigned int regs[4]; Tcl_Obj *regsObjs[4]; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "eax"); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[1], &index) != TCL_OK) { return TCL_ERROR; } status = TclWinCPUID((unsigned) index, regs); if (status != TCL_OK) { Tcl_SetObjResult(interp, Tcl_NewStringObj("operation not available", -1)); return status; } for (i=0 ; i<4 ; ++i) { regsObjs[i] = Tcl_NewIntObj((int) regs[i]); } Tcl_SetObjResult(interp, Tcl_NewListObj(4, regsObjs)); return TCL_OK; } #endif /* * Used to do basic checks of the TCL_HASH_KEY_SYSTEM_HASH flag */ static int TestHashSystemHashCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { static const Tcl_HashKeyType hkType = { TCL_HASH_KEY_TYPE_VERSION, TCL_HASH_KEY_SYSTEM_HASH, NULL, NULL, NULL, NULL }; Tcl_HashTable hash; Tcl_HashEntry *hPtr; int i, isNew, limit = 100; if (objc>1 && Tcl_GetIntFromObj(interp, objv[1], &limit)!=TCL_OK) { return TCL_ERROR; } Tcl_InitCustomHashTable(&hash, TCL_CUSTOM_TYPE_KEYS, &hkType); if (hash.numEntries != 0) { Tcl_AppendResult(interp, "non-zero initial size", NULL); Tcl_DeleteHashTable(&hash); return TCL_ERROR; } for (i=0 ; iexecEnvPtr->callbackPtr; if (refDepth == NULL) { refDepth = &depth; } depth = (refDepth - &depth); levels[0] = Tcl_NewIntObj(depth); levels[1] = Tcl_NewIntObj(iPtr->numLevels); levels[2] = Tcl_NewIntObj(iPtr->cmdFramePtr->level); levels[3] = Tcl_NewIntObj(iPtr->varFramePtr->level); levels[4] = Tcl_NewIntObj(iPtr->execEnvPtr->execStackPtr->tosPtr - iPtr->execEnvPtr->execStackPtr->stackWords); while (cbPtr) { i++; cbPtr = cbPtr->nextPtr; } levels[5] = Tcl_NewIntObj(i); Tcl_SetObjResult(interp, Tcl_NewListObj(6, levels)); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestconcatobjCmd -- * * This procedure implements the "testconcatobj" command. It is used * to test that Tcl_ConcatObj does indeed return a fresh Tcl_Obj in all * cases and thet it never corrupts its arguments. In other words, that * [Bug 1447328] was fixed properly. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestconcatobjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ const char **argv) /* Argument strings. */ { Tcl_Obj *list1Ptr, *list2Ptr, *emptyPtr, *concatPtr, *tmpPtr; int result = TCL_OK, len; Tcl_Obj *objv[3]; /* * Set the start of the error message as obj result; it will be cleared at * the end if no errors were found. */ Tcl_SetObjResult(interp, Tcl_NewStringObj("Tcl_ConcatObj is unsafe:", -1)); emptyPtr = Tcl_NewObj(); list1Ptr = Tcl_NewStringObj("foo bar sum", -1); Tcl_ListObjLength(NULL, list1Ptr, &len); if (list1Ptr->bytes != NULL) { ckfree(list1Ptr->bytes); list1Ptr->bytes = NULL; } list2Ptr = Tcl_NewStringObj("eeny meeny", -1); Tcl_ListObjLength(NULL, list2Ptr, &len); if (list2Ptr->bytes != NULL) { ckfree(list2Ptr->bytes); list2Ptr->bytes = NULL; } /* * Verify that concat'ing a list obj with one or more empty strings does * return a fresh Tcl_Obj (see also [Bug 2055782]). */ tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[0] = tmpPtr; objv[1] = emptyPtr; concatPtr = Tcl_ConcatObj(2, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (a) concatObj does not have refCount 0", NULL); } if (concatPtr == tmpPtr) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (a) concatObj is not a new obj ", NULL); switch (tmpPtr->refCount) { case 0: Tcl_AppendResult(interp, "(no new refCount)", NULL); break; case 1: Tcl_AppendResult(interp, "(refCount added)", NULL); break; default: Tcl_AppendResult(interp, "(more than one refCount added!)", NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); } tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[0] = tmpPtr; } Tcl_DecrRefCount(concatPtr); Tcl_IncrRefCount(tmpPtr); concatPtr = Tcl_ConcatObj(2, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (b) concatObj does not have refCount 0", NULL); } if (concatPtr == tmpPtr) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (b) concatObj is not a new obj ", NULL); switch (tmpPtr->refCount) { case 0: Tcl_AppendResult(interp, "(refCount removed?)", NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); break; case 1: Tcl_AppendResult(interp, "(no new refCount)", NULL); break; case 2: Tcl_AppendResult(interp, "(refCount added)", NULL); Tcl_DecrRefCount(tmpPtr); break; default: Tcl_AppendResult(interp, "(more than one refCount added!)", NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); } tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[0] = tmpPtr; } Tcl_DecrRefCount(concatPtr); objv[0] = emptyPtr; objv[1] = tmpPtr; objv[2] = emptyPtr; concatPtr = Tcl_ConcatObj(3, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (c) concatObj does not have refCount 0", NULL); } if (concatPtr == tmpPtr) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (c) concatObj is not a new obj ", NULL); switch (tmpPtr->refCount) { case 0: Tcl_AppendResult(interp, "(no new refCount)", NULL); break; case 1: Tcl_AppendResult(interp, "(refCount added)", NULL); break; default: Tcl_AppendResult(interp, "(more than one refCount added!)", NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); } tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[1] = tmpPtr; } Tcl_DecrRefCount(concatPtr); Tcl_IncrRefCount(tmpPtr); concatPtr = Tcl_ConcatObj(3, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (d) concatObj does not have refCount 0", NULL); } if (concatPtr == tmpPtr) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (d) concatObj is not a new obj ", NULL); switch (tmpPtr->refCount) { case 0: Tcl_AppendResult(interp, "(refCount removed?)", NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); break; case 1: Tcl_AppendResult(interp, "(no new refCount)", NULL); break; case 2: Tcl_AppendResult(interp, "(refCount added)", NULL); Tcl_DecrRefCount(tmpPtr); break; default: Tcl_AppendResult(interp, "(more than one refCount added!)", NULL); Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()"); } tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[1] = tmpPtr; } Tcl_DecrRefCount(concatPtr); /* * Verify that an unshared list is not corrupted when concat'ing things to * it. */ objv[0] = tmpPtr; objv[1] = list2Ptr; concatPtr = Tcl_ConcatObj(2, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (e) concatObj does not have refCount 0", NULL); } if (concatPtr == tmpPtr) { int len; result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (e) concatObj is not a new obj ", NULL); (void) Tcl_ListObjLength(NULL, concatPtr, &len); switch (tmpPtr->refCount) { case 3: Tcl_AppendResult(interp, "(failed to concat)", NULL); break; default: Tcl_AppendResult(interp, "(corrupted input!)", NULL); } if (Tcl_IsShared(tmpPtr)) { Tcl_DecrRefCount(tmpPtr); } tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[0] = tmpPtr; } Tcl_DecrRefCount(concatPtr); objv[0] = tmpPtr; objv[1] = list2Ptr; Tcl_IncrRefCount(tmpPtr); concatPtr = Tcl_ConcatObj(2, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (f) concatObj does not have refCount 0", NULL); } if (concatPtr == tmpPtr) { int len; result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (f) concatObj is not a new obj ", NULL); (void) Tcl_ListObjLength(NULL, concatPtr, &len); switch (tmpPtr->refCount) { case 3: Tcl_AppendResult(interp, "(failed to concat)", NULL); break; default: Tcl_AppendResult(interp, "(corrupted input!)", NULL); } if (Tcl_IsShared(tmpPtr)) { Tcl_DecrRefCount(tmpPtr); } tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[0] = tmpPtr; } Tcl_DecrRefCount(concatPtr); objv[0] = tmpPtr; objv[1] = list2Ptr; Tcl_IncrRefCount(tmpPtr); Tcl_IncrRefCount(tmpPtr); concatPtr = Tcl_ConcatObj(2, objv); if (concatPtr->refCount != 0) { result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (g) concatObj does not have refCount 0", NULL); } if (concatPtr == tmpPtr) { int len; result = TCL_ERROR; Tcl_AppendResult(interp, "\n\t* (g) concatObj is not a new obj ", NULL); (void) Tcl_ListObjLength(NULL, concatPtr, &len); switch (tmpPtr->refCount) { case 3: Tcl_AppendResult(interp, "(failed to concat)", NULL); break; default: Tcl_AppendResult(interp, "(corrupted input!)", NULL); } Tcl_DecrRefCount(tmpPtr); if (Tcl_IsShared(tmpPtr)) { Tcl_DecrRefCount(tmpPtr); } tmpPtr = Tcl_DuplicateObj(list1Ptr); objv[0] = tmpPtr; } Tcl_DecrRefCount(concatPtr); /* * Clean everything up. Note that we don't actually know how many * references there are to tmpPtr here; in the no-error case, it should be * five... [Bug 2895367] */ Tcl_DecrRefCount(list1Ptr); Tcl_DecrRefCount(list2Ptr); Tcl_DecrRefCount(emptyPtr); while (tmpPtr->refCount > 1) { Tcl_DecrRefCount(tmpPtr); } Tcl_DecrRefCount(tmpPtr); if (result == TCL_OK) { Tcl_ResetResult(interp); } return result; } /* *---------------------------------------------------------------------- * * TestparseargsCmd -- * * This procedure implements the "testparseargs" command. It is used to * test that Tcl_ParseArgsObjv does indeed return the right number of * arguments. In other words, that [Bug 3413857] was fixed properly. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int TestparseargsCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Arguments. */ { static int foo = 0; int count = objc; Tcl_Obj **remObjv, *result[3]; Tcl_ArgvInfo argTable[] = { {TCL_ARGV_CONSTANT, "-bool", INT2PTR(1), &foo, "booltest", NULL}, TCL_ARGV_AUTO_REST, TCL_ARGV_AUTO_HELP, TCL_ARGV_TABLE_END }; foo = 0; if (Tcl_ParseArgsObjv(interp, argTable, &count, objv, &remObjv)!=TCL_OK) { return TCL_ERROR; } result[0] = Tcl_NewIntObj(foo); result[1] = Tcl_NewIntObj(count); result[2] = Tcl_NewListObj(count, remObjv); Tcl_SetObjResult(interp, Tcl_NewListObj(3, result)); ckfree(remObjv); return TCL_OK; } /** * Test harness for command and variable resolvers. */ static int InterpCmdResolver( Tcl_Interp *interp, const char *name, Tcl_Namespace *context, int flags, Tcl_Command *rPtr) { Interp *iPtr = (Interp *) interp; CallFrame *varFramePtr = iPtr->varFramePtr; Proc *procPtr = (varFramePtr->isProcCallFrame & FRAME_IS_PROC) ? varFramePtr->procPtr : NULL; Namespace *ns2NsPtr = (Namespace *) Tcl_FindNamespace(interp, "::ns2", NULL, 0); if (procPtr && (procPtr->cmdPtr->nsPtr == iPtr->globalNsPtr || (ns2NsPtr && procPtr->cmdPtr->nsPtr == ns2NsPtr))) { const char *callingCmdName = Tcl_GetCommandName(interp, (Tcl_Command) procPtr->cmdPtr); if ((callingCmdName[0] == 'x') && (callingCmdName[1] == '\0') && (name[0] == 'z') && (name[1] == '\0')) { Tcl_Command sourceCmdPtr = Tcl_FindCommand(interp, "y", NULL, TCL_GLOBAL_ONLY); if (sourceCmdPtr != NULL) { *rPtr = sourceCmdPtr; return TCL_OK; } } } return TCL_CONTINUE; } static int InterpVarResolver( Tcl_Interp *interp, const char *name, Tcl_Namespace *context, int flags, Tcl_Var *rPtr) { /* * Don't resolve the variable; use standard rules. */ return TCL_CONTINUE; } typedef struct MyResolvedVarInfo { Tcl_ResolvedVarInfo vInfo; /* This must be the first element. */ Tcl_Var var; Tcl_Obj *nameObj; } MyResolvedVarInfo; static inline void HashVarFree( Tcl_Var var) { if (VarHashRefCount(var) < 2) { ckfree(var); } else { VarHashRefCount(var)--; } } static void MyCompiledVarFree( Tcl_ResolvedVarInfo *vInfoPtr) { MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *) vInfoPtr; Tcl_DecrRefCount(resVarInfo->nameObj); if (resVarInfo->var) { HashVarFree(resVarInfo->var); } ckfree(vInfoPtr); } #define TclVarHashGetValue(hPtr) \ ((Var *) ((char *)hPtr - TclOffset(VarInHash, entry))) static Tcl_Var MyCompiledVarFetch( Tcl_Interp *interp, Tcl_ResolvedVarInfo *vinfoPtr) { MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *) vinfoPtr; Tcl_Var var = resVarInfo->var; int isNewVar; Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hPtr; if (var != NULL) { if (!(((Var *) var)->flags & VAR_DEAD_HASH)) { /* * The cached variable is valid, return it. */ return var; } /* * The variable is not valid anymore. Clean it up. */ HashVarFree(var); } hPtr = Tcl_CreateHashEntry((Tcl_HashTable *) &iPtr->globalNsPtr->varTable, (char *) resVarInfo->nameObj, &isNewVar); if (hPtr) { var = (Tcl_Var) TclVarHashGetValue(hPtr); } else { var = NULL; } resVarInfo->var = var; /* * Increment the reference counter to avoid ckfree() of the variable in * Tcl's FreeVarEntry(); for cleanup, we provide our own HashVarFree(); */ VarHashRefCount(var)++; return var; } static int InterpCompiledVarResolver( Tcl_Interp *interp, const char *name, int length, Tcl_Namespace *context, Tcl_ResolvedVarInfo **rPtr) { if (*name == 'T') { MyResolvedVarInfo *resVarInfo = ckalloc(sizeof(MyResolvedVarInfo)); resVarInfo->vInfo.fetchProc = MyCompiledVarFetch; resVarInfo->vInfo.deleteProc = MyCompiledVarFree; resVarInfo->var = NULL; resVarInfo->nameObj = Tcl_NewStringObj(name, -1); Tcl_IncrRefCount(resVarInfo->nameObj); *rPtr = &resVarInfo->vInfo; return TCL_OK; } return TCL_CONTINUE; } static int TestInterpResolverCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { static const char *const table[] = { "down", "up", NULL }; int idx; #define RESOLVER_KEY "testInterpResolver" if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "up|down"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], table, "operation", TCL_EXACT, &idx) != TCL_OK) { return TCL_ERROR; } switch (idx) { case 1: /* up */ Tcl_AddInterpResolvers(interp, RESOLVER_KEY, InterpCmdResolver, InterpVarResolver, InterpCompiledVarResolver); break; case 0: /*down*/ if (!Tcl_RemoveInterpResolvers(interp, RESOLVER_KEY)) { Tcl_AppendResult(interp, "could not remove the resolver scheme", NULL); return TCL_ERROR; } } return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * indent-tabs-mode: nil * End: */ tcl8.6.5/generic/tclTomMathDecls.h0000644000175000017500000004471412665173571016420 0ustar sergeisergei/* *---------------------------------------------------------------------- * * tclTomMathDecls.h -- * * This file contains the declarations for the 'libtommath' * functions that are exported by the Tcl library. * * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLTOMMATHDECLS #define _TCLTOMMATHDECLS #include "tcl.h" /* * Define the version of the Stubs table that's exported for tommath */ #define TCLTOMMATH_EPOCH 0 #define TCLTOMMATH_REVISION 0 #define Tcl_TomMath_InitStubs(interp,version) \ (TclTomMathInitializeStubs((interp),(version),\ TCLTOMMATH_EPOCH,TCLTOMMATH_REVISION)) /* Define custom memory allocation for libtommath */ /* MODULE_SCOPE void* TclBNAlloc( size_t ); */ #define TclBNAlloc(s) ((void*)ckalloc((size_t)(s))) /* MODULE_SCOPE void* TclBNRealloc( void*, size_t ); */ #define TclBNRealloc(x,s) ((void*)ckrealloc((char*)(x),(size_t)(s))) /* MODULE_SCOPE void TclBNFree( void* ); */ #define TclBNFree(x) (ckfree((char*)(x))) /* MODULE_SCOPE void* TclBNCalloc( size_t, size_t ); */ /* unused - no macro */ #define XMALLOC(x) TclBNAlloc(x) #define XFREE(x) TclBNFree(x) #define XREALLOC(x,n) TclBNRealloc(x,n) #define XCALLOC(n,x) TclBNCalloc(n,x) /* Rename the global symbols in libtommath to avoid linkage conflicts */ #define KARATSUBA_MUL_CUTOFF TclBNKaratsubaMulCutoff #define KARATSUBA_SQR_CUTOFF TclBNKaratsubaSqrCutoff #define TOOM_MUL_CUTOFF TclBNToomMulCutoff #define TOOM_SQR_CUTOFF TclBNToomSqrCutoff #define bn_reverse TclBN_reverse #define fast_s_mp_mul_digs TclBN_fast_s_mp_mul_digs #define fast_s_mp_sqr TclBN_fast_s_mp_sqr #define mp_add TclBN_mp_add #define mp_add_d TclBN_mp_add_d #define mp_and TclBN_mp_and #define mp_clamp TclBN_mp_clamp #define mp_clear TclBN_mp_clear #define mp_clear_multi TclBN_mp_clear_multi #define mp_cmp TclBN_mp_cmp #define mp_cmp_d TclBN_mp_cmp_d #define mp_cmp_mag TclBN_mp_cmp_mag #define mp_cnt_lsb TclBN_mp_cnt_lsb #define mp_copy TclBN_mp_copy #define mp_count_bits TclBN_mp_count_bits #define mp_div TclBN_mp_div #define mp_div_2 TclBN_mp_div_2 #define mp_div_2d TclBN_mp_div_2d #define mp_div_3 TclBN_mp_div_3 #define mp_div_d TclBN_mp_div_d #define mp_exch TclBN_mp_exch #define mp_expt_d TclBN_mp_expt_d #define mp_grow TclBN_mp_grow #define mp_init TclBN_mp_init #define mp_init_copy TclBN_mp_init_copy #define mp_init_multi TclBN_mp_init_multi #define mp_init_set TclBN_mp_init_set #define mp_init_set_int TclBN_mp_init_set_int #define mp_init_size TclBN_mp_init_size #define mp_karatsuba_mul TclBN_mp_karatsuba_mul #define mp_karatsuba_sqr TclBN_mp_karatsuba_sqr #define mp_lshd TclBN_mp_lshd #define mp_mod TclBN_mp_mod #define mp_mod_2d TclBN_mp_mod_2d #define mp_mul TclBN_mp_mul #define mp_mul_2 TclBN_mp_mul_2 #define mp_mul_2d TclBN_mp_mul_2d #define mp_mul_d TclBN_mp_mul_d #define mp_neg TclBN_mp_neg #define mp_or TclBN_mp_or #define mp_radix_size TclBN_mp_radix_size #define mp_read_radix TclBN_mp_read_radix #define mp_rshd TclBN_mp_rshd #define mp_s_rmap TclBNMpSRmap #define mp_set TclBN_mp_set #define mp_set_int TclBN_mp_set_int #define mp_shrink TclBN_mp_shrink #define mp_sqr TclBN_mp_sqr #define mp_sqrt TclBN_mp_sqrt #define mp_sub TclBN_mp_sub #define mp_sub_d TclBN_mp_sub_d #define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin #define mp_to_unsigned_bin_n TclBN_mp_to_unsigned_bin_n #define mp_toom_mul TclBN_mp_toom_mul #define mp_toom_sqr TclBN_mp_toom_sqr #define mp_toradix_n TclBN_mp_toradix_n #define mp_unsigned_bin_size TclBN_mp_unsigned_bin_size #define mp_xor TclBN_mp_xor #define mp_zero TclBN_mp_zero #define s_mp_add TclBN_s_mp_add #define s_mp_mul_digs TclBN_s_mp_mul_digs #define s_mp_sqr TclBN_s_mp_sqr #define s_mp_sub TclBN_s_mp_sub #undef TCL_STORAGE_CLASS #ifdef BUILD_tcl # define TCL_STORAGE_CLASS DLLEXPORT #else # ifdef USE_TCL_STUBS # define TCL_STORAGE_CLASS # else # define TCL_STORAGE_CLASS DLLIMPORT # endif #endif /* * WARNING: This file is automatically generated by the tools/genStubs.tcl * script. Any modifications to the function declarations below should be made * in the generic/tclInt.decls script. */ /* !BEGIN!: Do not edit below this line. */ #ifdef __cplusplus extern "C" { #endif /* * Exported function declarations: */ /* 0 */ EXTERN int TclBN_epoch(void); /* 1 */ EXTERN int TclBN_revision(void); /* 2 */ EXTERN int TclBN_mp_add(mp_int *a, mp_int *b, mp_int *c); /* 3 */ EXTERN int TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c); /* 4 */ EXTERN int TclBN_mp_and(mp_int *a, mp_int *b, mp_int *c); /* 5 */ EXTERN void TclBN_mp_clamp(mp_int *a); /* 6 */ EXTERN void TclBN_mp_clear(mp_int *a); /* 7 */ EXTERN void TclBN_mp_clear_multi(mp_int *a, ...); /* 8 */ EXTERN int TclBN_mp_cmp(const mp_int *a, const mp_int *b); /* 9 */ EXTERN int TclBN_mp_cmp_d(const mp_int *a, mp_digit b); /* 10 */ EXTERN int TclBN_mp_cmp_mag(const mp_int *a, const mp_int *b); /* 11 */ EXTERN int TclBN_mp_copy(const mp_int *a, mp_int *b); /* 12 */ EXTERN int TclBN_mp_count_bits(const mp_int *a); /* 13 */ EXTERN int TclBN_mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r); /* 14 */ EXTERN int TclBN_mp_div_d(mp_int *a, mp_digit b, mp_int *q, mp_digit *r); /* 15 */ EXTERN int TclBN_mp_div_2(mp_int *a, mp_int *q); /* 16 */ EXTERN int TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, mp_int *r); /* 17 */ EXTERN int TclBN_mp_div_3(mp_int *a, mp_int *q, mp_digit *r); /* 18 */ EXTERN void TclBN_mp_exch(mp_int *a, mp_int *b); /* 19 */ EXTERN int TclBN_mp_expt_d(mp_int *a, mp_digit b, mp_int *c); /* 20 */ EXTERN int TclBN_mp_grow(mp_int *a, int size); /* 21 */ EXTERN int TclBN_mp_init(mp_int *a); /* 22 */ EXTERN int TclBN_mp_init_copy(mp_int *a, mp_int *b); /* 23 */ EXTERN int TclBN_mp_init_multi(mp_int *a, ...); /* 24 */ EXTERN int TclBN_mp_init_set(mp_int *a, mp_digit b); /* 25 */ EXTERN int TclBN_mp_init_size(mp_int *a, int size); /* 26 */ EXTERN int TclBN_mp_lshd(mp_int *a, int shift); /* 27 */ EXTERN int TclBN_mp_mod(mp_int *a, mp_int *b, mp_int *r); /* 28 */ EXTERN int TclBN_mp_mod_2d(const mp_int *a, int b, mp_int *r); /* 29 */ EXTERN int TclBN_mp_mul(mp_int *a, mp_int *b, mp_int *p); /* 30 */ EXTERN int TclBN_mp_mul_d(mp_int *a, mp_digit b, mp_int *p); /* 31 */ EXTERN int TclBN_mp_mul_2(mp_int *a, mp_int *p); /* 32 */ EXTERN int TclBN_mp_mul_2d(const mp_int *a, int d, mp_int *p); /* 33 */ EXTERN int TclBN_mp_neg(const mp_int *a, mp_int *b); /* 34 */ EXTERN int TclBN_mp_or(mp_int *a, mp_int *b, mp_int *c); /* 35 */ EXTERN int TclBN_mp_radix_size(mp_int *a, int radix, int *size); /* 36 */ EXTERN int TclBN_mp_read_radix(mp_int *a, const char *str, int radix); /* 37 */ EXTERN void TclBN_mp_rshd(mp_int *a, int shift); /* 38 */ EXTERN int TclBN_mp_shrink(mp_int *a); /* 39 */ EXTERN void TclBN_mp_set(mp_int *a, mp_digit b); /* 40 */ EXTERN int TclBN_mp_sqr(mp_int *a, mp_int *b); /* 41 */ EXTERN int TclBN_mp_sqrt(mp_int *a, mp_int *b); /* 42 */ EXTERN int TclBN_mp_sub(mp_int *a, mp_int *b, mp_int *c); /* 43 */ EXTERN int TclBN_mp_sub_d(mp_int *a, mp_digit b, mp_int *c); /* 44 */ EXTERN int TclBN_mp_to_unsigned_bin(mp_int *a, unsigned char *b); /* 45 */ EXTERN int TclBN_mp_to_unsigned_bin_n(mp_int *a, unsigned char *b, unsigned long *outlen); /* 46 */ EXTERN int TclBN_mp_toradix_n(mp_int *a, char *str, int radix, int maxlen); /* 47 */ EXTERN int TclBN_mp_unsigned_bin_size(mp_int *a); /* 48 */ EXTERN int TclBN_mp_xor(mp_int *a, mp_int *b, mp_int *c); /* 49 */ EXTERN void TclBN_mp_zero(mp_int *a); /* 50 */ EXTERN void TclBN_reverse(unsigned char *s, int len); /* 51 */ EXTERN int TclBN_fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); /* 52 */ EXTERN int TclBN_fast_s_mp_sqr(mp_int *a, mp_int *b); /* 53 */ EXTERN int TclBN_mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c); /* 54 */ EXTERN int TclBN_mp_karatsuba_sqr(mp_int *a, mp_int *b); /* 55 */ EXTERN int TclBN_mp_toom_mul(mp_int *a, mp_int *b, mp_int *c); /* 56 */ EXTERN int TclBN_mp_toom_sqr(mp_int *a, mp_int *b); /* 57 */ EXTERN int TclBN_s_mp_add(mp_int *a, mp_int *b, mp_int *c); /* 58 */ EXTERN int TclBN_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); /* 59 */ EXTERN int TclBN_s_mp_sqr(mp_int *a, mp_int *b); /* 60 */ EXTERN int TclBN_s_mp_sub(mp_int *a, mp_int *b, mp_int *c); /* 61 */ EXTERN int TclBN_mp_init_set_int(mp_int *a, unsigned long i); /* 62 */ EXTERN int TclBN_mp_set_int(mp_int *a, unsigned long i); /* 63 */ EXTERN int TclBN_mp_cnt_lsb(const mp_int *a); /* 64 */ EXTERN void TclBNInitBignumFromLong(mp_int *bignum, long initVal); /* 65 */ EXTERN void TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal); /* 66 */ EXTERN void TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal); typedef struct TclTomMathStubs { int magic; void *hooks; int (*tclBN_epoch) (void); /* 0 */ int (*tclBN_revision) (void); /* 1 */ int (*tclBN_mp_add) (mp_int *a, mp_int *b, mp_int *c); /* 2 */ int (*tclBN_mp_add_d) (mp_int *a, mp_digit b, mp_int *c); /* 3 */ int (*tclBN_mp_and) (mp_int *a, mp_int *b, mp_int *c); /* 4 */ void (*tclBN_mp_clamp) (mp_int *a); /* 5 */ void (*tclBN_mp_clear) (mp_int *a); /* 6 */ void (*tclBN_mp_clear_multi) (mp_int *a, ...); /* 7 */ int (*tclBN_mp_cmp) (const mp_int *a, const mp_int *b); /* 8 */ int (*tclBN_mp_cmp_d) (const mp_int *a, mp_digit b); /* 9 */ int (*tclBN_mp_cmp_mag) (const mp_int *a, const mp_int *b); /* 10 */ int (*tclBN_mp_copy) (const mp_int *a, mp_int *b); /* 11 */ int (*tclBN_mp_count_bits) (const mp_int *a); /* 12 */ int (*tclBN_mp_div) (mp_int *a, mp_int *b, mp_int *q, mp_int *r); /* 13 */ int (*tclBN_mp_div_d) (mp_int *a, mp_digit b, mp_int *q, mp_digit *r); /* 14 */ int (*tclBN_mp_div_2) (mp_int *a, mp_int *q); /* 15 */ int (*tclBN_mp_div_2d) (const mp_int *a, int b, mp_int *q, mp_int *r); /* 16 */ int (*tclBN_mp_div_3) (mp_int *a, mp_int *q, mp_digit *r); /* 17 */ void (*tclBN_mp_exch) (mp_int *a, mp_int *b); /* 18 */ int (*tclBN_mp_expt_d) (mp_int *a, mp_digit b, mp_int *c); /* 19 */ int (*tclBN_mp_grow) (mp_int *a, int size); /* 20 */ int (*tclBN_mp_init) (mp_int *a); /* 21 */ int (*tclBN_mp_init_copy) (mp_int *a, mp_int *b); /* 22 */ int (*tclBN_mp_init_multi) (mp_int *a, ...); /* 23 */ int (*tclBN_mp_init_set) (mp_int *a, mp_digit b); /* 24 */ int (*tclBN_mp_init_size) (mp_int *a, int size); /* 25 */ int (*tclBN_mp_lshd) (mp_int *a, int shift); /* 26 */ int (*tclBN_mp_mod) (mp_int *a, mp_int *b, mp_int *r); /* 27 */ int (*tclBN_mp_mod_2d) (const mp_int *a, int b, mp_int *r); /* 28 */ int (*tclBN_mp_mul) (mp_int *a, mp_int *b, mp_int *p); /* 29 */ int (*tclBN_mp_mul_d) (mp_int *a, mp_digit b, mp_int *p); /* 30 */ int (*tclBN_mp_mul_2) (mp_int *a, mp_int *p); /* 31 */ int (*tclBN_mp_mul_2d) (const mp_int *a, int d, mp_int *p); /* 32 */ int (*tclBN_mp_neg) (const mp_int *a, mp_int *b); /* 33 */ int (*tclBN_mp_or) (mp_int *a, mp_int *b, mp_int *c); /* 34 */ int (*tclBN_mp_radix_size) (mp_int *a, int radix, int *size); /* 35 */ int (*tclBN_mp_read_radix) (mp_int *a, const char *str, int radix); /* 36 */ void (*tclBN_mp_rshd) (mp_int *a, int shift); /* 37 */ int (*tclBN_mp_shrink) (mp_int *a); /* 38 */ void (*tclBN_mp_set) (mp_int *a, mp_digit b); /* 39 */ int (*tclBN_mp_sqr) (mp_int *a, mp_int *b); /* 40 */ int (*tclBN_mp_sqrt) (mp_int *a, mp_int *b); /* 41 */ int (*tclBN_mp_sub) (mp_int *a, mp_int *b, mp_int *c); /* 42 */ int (*tclBN_mp_sub_d) (mp_int *a, mp_digit b, mp_int *c); /* 43 */ int (*tclBN_mp_to_unsigned_bin) (mp_int *a, unsigned char *b); /* 44 */ int (*tclBN_mp_to_unsigned_bin_n) (mp_int *a, unsigned char *b, unsigned long *outlen); /* 45 */ int (*tclBN_mp_toradix_n) (mp_int *a, char *str, int radix, int maxlen); /* 46 */ int (*tclBN_mp_unsigned_bin_size) (mp_int *a); /* 47 */ int (*tclBN_mp_xor) (mp_int *a, mp_int *b, mp_int *c); /* 48 */ void (*tclBN_mp_zero) (mp_int *a); /* 49 */ void (*tclBN_reverse) (unsigned char *s, int len); /* 50 */ int (*tclBN_fast_s_mp_mul_digs) (mp_int *a, mp_int *b, mp_int *c, int digs); /* 51 */ int (*tclBN_fast_s_mp_sqr) (mp_int *a, mp_int *b); /* 52 */ int (*tclBN_mp_karatsuba_mul) (mp_int *a, mp_int *b, mp_int *c); /* 53 */ int (*tclBN_mp_karatsuba_sqr) (mp_int *a, mp_int *b); /* 54 */ int (*tclBN_mp_toom_mul) (mp_int *a, mp_int *b, mp_int *c); /* 55 */ int (*tclBN_mp_toom_sqr) (mp_int *a, mp_int *b); /* 56 */ int (*tclBN_s_mp_add) (mp_int *a, mp_int *b, mp_int *c); /* 57 */ int (*tclBN_s_mp_mul_digs) (mp_int *a, mp_int *b, mp_int *c, int digs); /* 58 */ int (*tclBN_s_mp_sqr) (mp_int *a, mp_int *b); /* 59 */ int (*tclBN_s_mp_sub) (mp_int *a, mp_int *b, mp_int *c); /* 60 */ int (*tclBN_mp_init_set_int) (mp_int *a, unsigned long i); /* 61 */ int (*tclBN_mp_set_int) (mp_int *a, unsigned long i); /* 62 */ int (*tclBN_mp_cnt_lsb) (const mp_int *a); /* 63 */ void (*tclBNInitBignumFromLong) (mp_int *bignum, long initVal); /* 64 */ void (*tclBNInitBignumFromWideInt) (mp_int *bignum, Tcl_WideInt initVal); /* 65 */ void (*tclBNInitBignumFromWideUInt) (mp_int *bignum, Tcl_WideUInt initVal); /* 66 */ } TclTomMathStubs; extern const TclTomMathStubs *tclTomMathStubsPtr; #ifdef __cplusplus } #endif #if defined(USE_TCL_STUBS) /* * Inline function declarations: */ #define TclBN_epoch \ (tclTomMathStubsPtr->tclBN_epoch) /* 0 */ #define TclBN_revision \ (tclTomMathStubsPtr->tclBN_revision) /* 1 */ #define TclBN_mp_add \ (tclTomMathStubsPtr->tclBN_mp_add) /* 2 */ #define TclBN_mp_add_d \ (tclTomMathStubsPtr->tclBN_mp_add_d) /* 3 */ #define TclBN_mp_and \ (tclTomMathStubsPtr->tclBN_mp_and) /* 4 */ #define TclBN_mp_clamp \ (tclTomMathStubsPtr->tclBN_mp_clamp) /* 5 */ #define TclBN_mp_clear \ (tclTomMathStubsPtr->tclBN_mp_clear) /* 6 */ #define TclBN_mp_clear_multi \ (tclTomMathStubsPtr->tclBN_mp_clear_multi) /* 7 */ #define TclBN_mp_cmp \ (tclTomMathStubsPtr->tclBN_mp_cmp) /* 8 */ #define TclBN_mp_cmp_d \ (tclTomMathStubsPtr->tclBN_mp_cmp_d) /* 9 */ #define TclBN_mp_cmp_mag \ (tclTomMathStubsPtr->tclBN_mp_cmp_mag) /* 10 */ #define TclBN_mp_copy \ (tclTomMathStubsPtr->tclBN_mp_copy) /* 11 */ #define TclBN_mp_count_bits \ (tclTomMathStubsPtr->tclBN_mp_count_bits) /* 12 */ #define TclBN_mp_div \ (tclTomMathStubsPtr->tclBN_mp_div) /* 13 */ #define TclBN_mp_div_d \ (tclTomMathStubsPtr->tclBN_mp_div_d) /* 14 */ #define TclBN_mp_div_2 \ (tclTomMathStubsPtr->tclBN_mp_div_2) /* 15 */ #define TclBN_mp_div_2d \ (tclTomMathStubsPtr->tclBN_mp_div_2d) /* 16 */ #define TclBN_mp_div_3 \ (tclTomMathStubsPtr->tclBN_mp_div_3) /* 17 */ #define TclBN_mp_exch \ (tclTomMathStubsPtr->tclBN_mp_exch) /* 18 */ #define TclBN_mp_expt_d \ (tclTomMathStubsPtr->tclBN_mp_expt_d) /* 19 */ #define TclBN_mp_grow \ (tclTomMathStubsPtr->tclBN_mp_grow) /* 20 */ #define TclBN_mp_init \ (tclTomMathStubsPtr->tclBN_mp_init) /* 21 */ #define TclBN_mp_init_copy \ (tclTomMathStubsPtr->tclBN_mp_init_copy) /* 22 */ #define TclBN_mp_init_multi \ (tclTomMathStubsPtr->tclBN_mp_init_multi) /* 23 */ #define TclBN_mp_init_set \ (tclTomMathStubsPtr->tclBN_mp_init_set) /* 24 */ #define TclBN_mp_init_size \ (tclTomMathStubsPtr->tclBN_mp_init_size) /* 25 */ #define TclBN_mp_lshd \ (tclTomMathStubsPtr->tclBN_mp_lshd) /* 26 */ #define TclBN_mp_mod \ (tclTomMathStubsPtr->tclBN_mp_mod) /* 27 */ #define TclBN_mp_mod_2d \ (tclTomMathStubsPtr->tclBN_mp_mod_2d) /* 28 */ #define TclBN_mp_mul \ (tclTomMathStubsPtr->tclBN_mp_mul) /* 29 */ #define TclBN_mp_mul_d \ (tclTomMathStubsPtr->tclBN_mp_mul_d) /* 30 */ #define TclBN_mp_mul_2 \ (tclTomMathStubsPtr->tclBN_mp_mul_2) /* 31 */ #define TclBN_mp_mul_2d \ (tclTomMathStubsPtr->tclBN_mp_mul_2d) /* 32 */ #define TclBN_mp_neg \ (tclTomMathStubsPtr->tclBN_mp_neg) /* 33 */ #define TclBN_mp_or \ (tclTomMathStubsPtr->tclBN_mp_or) /* 34 */ #define TclBN_mp_radix_size \ (tclTomMathStubsPtr->tclBN_mp_radix_size) /* 35 */ #define TclBN_mp_read_radix \ (tclTomMathStubsPtr->tclBN_mp_read_radix) /* 36 */ #define TclBN_mp_rshd \ (tclTomMathStubsPtr->tclBN_mp_rshd) /* 37 */ #define TclBN_mp_shrink \ (tclTomMathStubsPtr->tclBN_mp_shrink) /* 38 */ #define TclBN_mp_set \ (tclTomMathStubsPtr->tclBN_mp_set) /* 39 */ #define TclBN_mp_sqr \ (tclTomMathStubsPtr->tclBN_mp_sqr) /* 40 */ #define TclBN_mp_sqrt \ (tclTomMathStubsPtr->tclBN_mp_sqrt) /* 41 */ #define TclBN_mp_sub \ (tclTomMathStubsPtr->tclBN_mp_sub) /* 42 */ #define TclBN_mp_sub_d \ (tclTomMathStubsPtr->tclBN_mp_sub_d) /* 43 */ #define TclBN_mp_to_unsigned_bin \ (tclTomMathStubsPtr->tclBN_mp_to_unsigned_bin) /* 44 */ #define TclBN_mp_to_unsigned_bin_n \ (tclTomMathStubsPtr->tclBN_mp_to_unsigned_bin_n) /* 45 */ #define TclBN_mp_toradix_n \ (tclTomMathStubsPtr->tclBN_mp_toradix_n) /* 46 */ #define TclBN_mp_unsigned_bin_size \ (tclTomMathStubsPtr->tclBN_mp_unsigned_bin_size) /* 47 */ #define TclBN_mp_xor \ (tclTomMathStubsPtr->tclBN_mp_xor) /* 48 */ #define TclBN_mp_zero \ (tclTomMathStubsPtr->tclBN_mp_zero) /* 49 */ #define TclBN_reverse \ (tclTomMathStubsPtr->tclBN_reverse) /* 50 */ #define TclBN_fast_s_mp_mul_digs \ (tclTomMathStubsPtr->tclBN_fast_s_mp_mul_digs) /* 51 */ #define TclBN_fast_s_mp_sqr \ (tclTomMathStubsPtr->tclBN_fast_s_mp_sqr) /* 52 */ #define TclBN_mp_karatsuba_mul \ (tclTomMathStubsPtr->tclBN_mp_karatsuba_mul) /* 53 */ #define TclBN_mp_karatsuba_sqr \ (tclTomMathStubsPtr->tclBN_mp_karatsuba_sqr) /* 54 */ #define TclBN_mp_toom_mul \ (tclTomMathStubsPtr->tclBN_mp_toom_mul) /* 55 */ #define TclBN_mp_toom_sqr \ (tclTomMathStubsPtr->tclBN_mp_toom_sqr) /* 56 */ #define TclBN_s_mp_add \ (tclTomMathStubsPtr->tclBN_s_mp_add) /* 57 */ #define TclBN_s_mp_mul_digs \ (tclTomMathStubsPtr->tclBN_s_mp_mul_digs) /* 58 */ #define TclBN_s_mp_sqr \ (tclTomMathStubsPtr->tclBN_s_mp_sqr) /* 59 */ #define TclBN_s_mp_sub \ (tclTomMathStubsPtr->tclBN_s_mp_sub) /* 60 */ #define TclBN_mp_init_set_int \ (tclTomMathStubsPtr->tclBN_mp_init_set_int) /* 61 */ #define TclBN_mp_set_int \ (tclTomMathStubsPtr->tclBN_mp_set_int) /* 62 */ #define TclBN_mp_cnt_lsb \ (tclTomMathStubsPtr->tclBN_mp_cnt_lsb) /* 63 */ #define TclBNInitBignumFromLong \ (tclTomMathStubsPtr->tclBNInitBignumFromLong) /* 64 */ #define TclBNInitBignumFromWideInt \ (tclTomMathStubsPtr->tclBNInitBignumFromWideInt) /* 65 */ #define TclBNInitBignumFromWideUInt \ (tclTomMathStubsPtr->tclBNInitBignumFromWideUInt) /* 66 */ #endif /* defined(USE_TCL_STUBS) */ /* !END!: Do not edit above this line. */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT #endif /* _TCLINTDECLS */ tcl8.6.5/generic/tclInt.decls0000644000175000017500000010231612663660065015457 0ustar sergeisergei# tclInt.decls -- # # This file contains the declarations for all unsupported # functions that are exported by the Tcl library. This file # is used to generate the tclIntDecls.h, tclIntPlatDecls.h # and tclStubInit.c files # # Copyright (c) 1998-1999 by Scriptics Corporation. # Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. # Copyright (c) 2007 Daniel A. Steffen # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. library tcl # Define the unsupported generic interfaces. interface tclInt # Declare each of the functions in the unsupported internal Tcl # interface. These interfaces are allowed to changed between versions. # Use at your own risk. Note that the position of functions should not # be changed between versions to avoid gratuitous incompatibilities. # Replaced by Tcl_FSAccess in 8.4: #declare 0 { # int TclAccess(const char *path, int mode) #} #declare 1 { # int TclAccessDeleteProc(TclAccessProc_ *proc) #} #declare 2 { # int TclAccessInsertProc(TclAccessProc_ *proc) #} declare 3 { void TclAllocateFreeObjects(void) } # Replaced by TclpChdir in 8.1: # declare 4 { # int TclChdir(Tcl_Interp *interp, char *dirName) # } declare 5 { int TclCleanupChildren(Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan) } declare 6 { void TclCleanupCommand(Command *cmdPtr) } declare 7 { int TclCopyAndCollapse(int count, const char *src, char *dst) } declare 8 { int TclCopyChannelOld(Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj *cmdPtr) } # TclCreatePipeline unofficially exported for use by BLT. declare 9 { int TclCreatePipeline(Tcl_Interp *interp, int argc, const char **argv, Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, TclFile *errFilePtr) } declare 10 { int TclCreateProc(Tcl_Interp *interp, Namespace *nsPtr, const char *procName, Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Proc **procPtrPtr) } declare 11 { void TclDeleteCompiledLocalVars(Interp *iPtr, CallFrame *framePtr) } declare 12 { void TclDeleteVars(Interp *iPtr, TclVarHashTable *tablePtr) } # Removed in 8.5 #declare 13 { # int TclDoGlob(Tcl_Interp *interp, char *separators, # Tcl_DString *headPtr, char *tail, Tcl_GlobTypeData *types) #} declare 14 { int TclDumpMemoryInfo(ClientData clientData, int flags) } # Removed in 8.1: # declare 15 { # void TclExpandParseValue(ParseValue *pvPtr, int needed) # } declare 16 { void TclExprFloatError(Tcl_Interp *interp, double value) } # Removed in 8.4 #declare 17 { # int TclFileAttrsCmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) #} #declare 18 { # int TclFileCopyCmd(Tcl_Interp *interp, int argc, char **argv) #} #declare 19 { # int TclFileDeleteCmd(Tcl_Interp *interp, int argc, char **argv) #} #declare 20 { # int TclFileMakeDirsCmd(Tcl_Interp *interp, int argc, char **argv) #} #declare 21 { # int TclFileRenameCmd(Tcl_Interp *interp, int argc, char **argv) #} declare 22 { int TclFindElement(Tcl_Interp *interp, const char *listStr, int listLength, const char **elementPtr, const char **nextPtr, int *sizePtr, int *bracePtr) } declare 23 { Proc *TclFindProc(Interp *iPtr, const char *procName) } # Replaced with macro (see tclInt.h) in Tcl 8.5.0, restored in 8.5.10 declare 24 { int TclFormatInt(char *buffer, long n) } declare 25 { void TclFreePackageInfo(Interp *iPtr) } # Removed in 8.1: # declare 26 { # char *TclGetCwd(Tcl_Interp *interp) # } # Removed in 8.5 #declare 27 { # int TclGetDate(char *p, unsigned long now, long zone, # unsigned long *timePtr) #} declare 28 { Tcl_Channel TclpGetDefaultStdChannel(int type) } # Removed in 8.4b2: #declare 29 { # Tcl_Obj *TclGetElementOfIndexedArray(Tcl_Interp *interp, # int localIndex, Tcl_Obj *elemPtr, int flags) #} # Replaced by char *TclGetEnv(const char *name, Tcl_DString *valuePtr) in 8.1: # declare 30 { # char *TclGetEnv(const char *name) # } declare 31 { const char *TclGetExtension(const char *name) } declare 32 { int TclGetFrame(Tcl_Interp *interp, const char *str, CallFrame **framePtrPtr) } # Removed in Tcl 8.5 #declare 33 { # TclCmdProcType TclGetInterpProc(void) #} declare 34 { int TclGetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr) } # Removed in 8.4b2: #declare 35 { # Tcl_Obj *TclGetIndexedScalar(Tcl_Interp *interp, int localIndex, # int flags) #} # Removed in 8.6a2 #declare 36 { # int TclGetLong(Tcl_Interp *interp, const char *str, long *longPtr) #} declare 37 { int TclGetLoadedPackages(Tcl_Interp *interp, const char *targetName) } declare 38 { int TclGetNamespaceForQualName(Tcl_Interp *interp, const char *qualName, Namespace *cxtNsPtr, int flags, Namespace **nsPtrPtr, Namespace **altNsPtrPtr, Namespace **actualCxtPtrPtr, const char **simpleNamePtr) } declare 39 { TclObjCmdProcType TclGetObjInterpProc(void) } declare 40 { int TclGetOpenMode(Tcl_Interp *interp, const char *str, int *seekFlagPtr) } declare 41 { Tcl_Command TclGetOriginalCommand(Tcl_Command command) } declare 42 { CONST86 char *TclpGetUserHome(const char *name, Tcl_DString *bufferPtr) } # Removed in Tcl 8.5a2 #declare 43 { # int TclGlobalInvoke(Tcl_Interp *interp, int argc, CONST84 char **argv, # int flags) #} declare 44 { int TclGuessPackageName(const char *fileName, Tcl_DString *bufPtr) } declare 45 { int TclHideUnsafeCommands(Tcl_Interp *interp) } declare 46 { int TclInExit(void) } # Removed in 8.4b2: #declare 47 { # Tcl_Obj *TclIncrElementOfIndexedArray(Tcl_Interp *interp, # int localIndex, Tcl_Obj *elemPtr, long incrAmount) #} # Removed in 8.4b2: #declare 48 { # Tcl_Obj *TclIncrIndexedScalar(Tcl_Interp *interp, int localIndex, # long incrAmount) #} #declare 49 { # Tcl_Obj *TclIncrVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, # Tcl_Obj *part2Ptr, long incrAmount, int part1NotParsed) #} declare 50 { void TclInitCompiledLocals(Tcl_Interp *interp, CallFrame *framePtr, Namespace *nsPtr) } declare 51 { int TclInterpInit(Tcl_Interp *interp) } # Removed in Tcl 8.5a2 #declare 52 { # int TclInvoke(Tcl_Interp *interp, int argc, CONST84 char **argv, # int flags) #} declare 53 { int TclInvokeObjectCommand(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char **argv) } declare 54 { int TclInvokeStringCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) } declare 55 { Proc *TclIsProc(Command *cmdPtr) } # 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) # } # Signature changed to take a length in 8.1: # declare 57 { # int TclLooksLikeInt(char *p) # } declare 58 { Var *TclLookupVar(Tcl_Interp *interp, const char *part1, const char *part2, int flags, const char *msg, int createPart1, int createPart2, Var **arrayPtrPtr) } # Replaced by Tcl_FSMatchInDirectory in 8.4 #declare 59 { # int TclpMatchFiles(Tcl_Interp *interp, char *separators, # Tcl_DString *dirPtr, char *pattern, char *tail) #} declare 60 { int TclNeedSpace(const char *start, const char *end) } declare 61 { Tcl_Obj *TclNewProcBodyObj(Proc *procPtr) } declare 62 { int TclObjCommandComplete(Tcl_Obj *cmdPtr) } declare 63 { int TclObjInterpProc(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) } declare 64 { int TclObjInvoke(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags) } # Removed in Tcl 8.5a2 #declare 65 { # int TclObjInvokeGlobal(Tcl_Interp *interp, int objc, # Tcl_Obj *const objv[], int flags) #} #declare 66 { # int TclOpenFileChannelDeleteProc(TclOpenFileChannelProc_ *proc) #} #declare 67 { # int TclOpenFileChannelInsertProc(TclOpenFileChannelProc_ *proc) #} # Replaced by Tcl_FSAccess in 8.4: #declare 68 { # int TclpAccess(const char *path, int mode) #} declare 69 { char *TclpAlloc(unsigned int size) } #declare 70 { # int TclpCopyFile(const char *source, const char *dest) #} #declare 71 { # int TclpCopyDirectory(const char *source, const char *dest, # Tcl_DString *errorPtr) #} #declare 72 { # int TclpCreateDirectory(const char *path) #} #declare 73 { # int TclpDeleteFile(const char *path) #} declare 74 { void TclpFree(char *ptr) } declare 75 { unsigned long TclpGetClicks(void) } declare 76 { unsigned long TclpGetSeconds(void) } # deprecated declare 77 { void TclpGetTime(Tcl_Time *time) } # Removed in 8.6: #declare 78 { # int TclpGetTimeZone(unsigned long time) #} # Replaced by Tcl_FSListVolumes in 8.4: #declare 79 { # int TclpListVolumes(Tcl_Interp *interp) #} # Replaced by Tcl_FSOpenFileChannel in 8.4: #declare 80 { # Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp, char *fileName, # char *modeString, int permissions) #} declare 81 { char *TclpRealloc(char *ptr, unsigned int size) } #declare 82 { # int TclpRemoveDirectory(const char *path, int recursive, # Tcl_DString *errorPtr) #} #declare 83 { # int TclpRenameFile(const char *source, const char *dest) #} # Removed in 8.1: # declare 84 { # int TclParseBraces(Tcl_Interp *interp, char *str, char **termPtr, # ParseValue *pvPtr) # } # declare 85 { # int TclParseNestedCmd(Tcl_Interp *interp, char *str, int flags, # char **termPtr, ParseValue *pvPtr) # } # declare 86 { # int TclParseQuotes(Tcl_Interp *interp, char *str, int termChar, # int flags, char **termPtr, ParseValue *pvPtr) # } # declare 87 { # void TclPlatformInit(Tcl_Interp *interp) # } declare 88 { char *TclPrecTraceProc(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags) } declare 89 { int TclPreventAliasLoop(Tcl_Interp *interp, Tcl_Interp *cmdInterp, Tcl_Command cmd) } # Removed in 8.1 (only available if compiled with TCL_COMPILE_DEBUG): # declare 90 { # void TclPrintByteCodeObj(Tcl_Interp *interp, Tcl_Obj *objPtr) # } declare 91 { void TclProcCleanupProc(Proc *procPtr) } declare 92 { int TclProcCompileProc(Tcl_Interp *interp, Proc *procPtr, Tcl_Obj *bodyPtr, Namespace *nsPtr, const char *description, const char *procName) } declare 93 { void TclProcDeleteProc(ClientData clientData) } # Removed in Tcl 8.5: #declare 94 { # int TclProcInterpProc(ClientData clientData, Tcl_Interp *interp, # int argc, const char **argv) #} # Replaced by Tcl_FSStat in 8.4: #declare 95 { # int TclpStat(const char *path, Tcl_StatBuf *buf) #} declare 96 { int TclRenameCommand(Tcl_Interp *interp, const char *oldName, const char *newName) } declare 97 { void TclResetShadowedCmdRefs(Tcl_Interp *interp, Command *newCmdPtr) } declare 98 { int TclServiceIdle(void) } # Removed in 8.4b2: #declare 99 { # Tcl_Obj *TclSetElementOfIndexedArray(Tcl_Interp *interp, int localIndex, # Tcl_Obj *elemPtr, Tcl_Obj *objPtr, int flags) #} # Removed in 8.4b2: #declare 100 { # Tcl_Obj *TclSetIndexedScalar(Tcl_Interp *interp, int localIndex, # Tcl_Obj *objPtr, int flags) #} declare 101 { CONST86 char *TclSetPreInitScript(const char *string) } declare 102 { void TclSetupEnv(Tcl_Interp *interp) } declare 103 { int TclSockGetPort(Tcl_Interp *interp, const char *str, const char *proto, int *portPtr) } declare 104 { int TclSockMinimumBuffersOld(int sock, int size) } # Replaced by Tcl_FSStat in 8.4: #declare 105 { # int TclStat(const char *path, Tcl_StatBuf *buf) #} #declare 106 { # int TclStatDeleteProc(TclStatProc_ *proc) #} #declare 107 { # int TclStatInsertProc(TclStatProc_ *proc) #} declare 108 { void TclTeardownNamespace(Namespace *nsPtr) } declare 109 { int TclUpdateReturnInfo(Interp *iPtr) } declare 110 { int TclSockMinimumBuffers(void *sock, int size) } # Removed in 8.1: # declare 110 { # char *TclWordEnd(char *start, char *lastChar, int nested, int *semiPtr) # } # Procedures used in conjunction with Tcl namespaces. They are # defined here instead of in tcl.decls since they are not stable yet. declare 111 { void Tcl_AddInterpResolvers(Tcl_Interp *interp, const char *name, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc) } declare 112 { int Tcl_AppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *objPtr) } declare 113 { Tcl_Namespace *Tcl_CreateNamespace(Tcl_Interp *interp, const char *name, ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc) } declare 114 { void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr) } declare 115 { int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int resetListFirst) } declare 116 { Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags) } declare 117 { Tcl_Namespace *Tcl_FindNamespace(Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags) } declare 118 { int Tcl_GetInterpResolvers(Tcl_Interp *interp, const char *name, Tcl_ResolverInfo *resInfo) } declare 119 { int Tcl_GetNamespaceResolvers(Tcl_Namespace *namespacePtr, Tcl_ResolverInfo *resInfo) } declare 120 { Tcl_Var Tcl_FindNamespaceVar(Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags) } declare 121 { int Tcl_ForgetImport(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern) } declare 122 { Tcl_Command Tcl_GetCommandFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr) } declare 123 { void Tcl_GetCommandFullName(Tcl_Interp *interp, Tcl_Command command, Tcl_Obj *objPtr) } declare 124 { Tcl_Namespace *Tcl_GetCurrentNamespace(Tcl_Interp *interp) } declare 125 { Tcl_Namespace *Tcl_GetGlobalNamespace(Tcl_Interp *interp) } declare 126 { void Tcl_GetVariableFullName(Tcl_Interp *interp, Tcl_Var variable, Tcl_Obj *objPtr) } declare 127 { int Tcl_Import(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int allowOverwrite) } declare 128 { void Tcl_PopCallFrame(Tcl_Interp *interp) } declare 129 { int Tcl_PushCallFrame(Tcl_Interp *interp, Tcl_CallFrame *framePtr, Tcl_Namespace *nsPtr, int isProcCallFrame) } declare 130 { int Tcl_RemoveInterpResolvers(Tcl_Interp *interp, const char *name) } declare 131 { void Tcl_SetNamespaceResolvers(Tcl_Namespace *namespacePtr, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc) } declare 132 { int TclpHasSockets(Tcl_Interp *interp) } declare 133 { struct tm *TclpGetDate(const time_t *time, int useGMT) } # Removed in 8.5 #declare 134 { # size_t TclpStrftime(char *s, size_t maxsize, const char *format, # const struct tm *t, int useGMT) #} #declare 135 { # int TclpCheckStackSpace(void) #} # Added in 8.1: #declare 137 { # int TclpChdir(const char *dirName) #} declare 138 { CONST84_RETURN char *TclGetEnv(const char *name, Tcl_DString *valuePtr) } #declare 139 { # int TclpLoadFile(Tcl_Interp *interp, char *fileName, char *sym1, # char *sym2, Tcl_PackageInitProc **proc1Ptr, # Tcl_PackageInitProc **proc2Ptr, ClientData *clientDataPtr) #} #declare 140 { # int TclLooksLikeInt(const char *bytes, int length) #} # This is used by TclX, but should otherwise be considered private declare 141 { CONST84_RETURN char *TclpGetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr) } declare 142 { int TclSetByteCodeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr, CompileHookProc *hookProc, ClientData clientData) } declare 143 { int TclAddLiteralObj(struct CompileEnv *envPtr, Tcl_Obj *objPtr, LiteralEntry **litPtrPtr) } declare 144 { void TclHideLiteral(Tcl_Interp *interp, struct CompileEnv *envPtr, int index) } declare 145 { const struct AuxDataType *TclGetAuxDataType(const char *typeName) } declare 146 { TclHandle TclHandleCreate(void *ptr) } declare 147 { void TclHandleFree(TclHandle handle) } declare 148 { TclHandle TclHandlePreserve(TclHandle handle) } declare 149 { void TclHandleRelease(TclHandle handle) } # Added for Tcl 8.2 declare 150 { int TclRegAbout(Tcl_Interp *interp, Tcl_RegExp re) } declare 151 { void TclRegExpRangeUniChar(Tcl_RegExp re, int index, int *startPtr, int *endPtr) } declare 152 { void TclSetLibraryPath(Tcl_Obj *pathPtr) } declare 153 { Tcl_Obj *TclGetLibraryPath(void) } # moved to tclTest.c (static) in 8.3.2/8.4a2 #declare 154 { # int TclTestChannelCmd(ClientData clientData, # Tcl_Interp *interp, int argc, char **argv) #} #declare 155 { # int TclTestChannelEventCmd(ClientData clientData, # Tcl_Interp *interp, int argc, char **argv) #} declare 156 { void TclRegError(Tcl_Interp *interp, const char *msg, int status) } declare 157 { Var *TclVarTraceExists(Tcl_Interp *interp, const char *varName) } # REMOVED (except from stub table) - use public Tcl_SetStartupScript() declare 158 { void TclSetStartupScriptFileName(const char *filename) } # REMOVED (except from stub table) - use public Tcl_GetStartupScript() declare 159 { const char *TclGetStartupScriptFileName(void) } #declare 160 { # int TclpMatchFilesTypes(Tcl_Interp *interp, char *separators, # Tcl_DString *dirPtr, char *pattern, char *tail, # GlobTypeData *types) #} # new in 8.3.2/8.4a2 declare 161 { int TclChannelTransform(Tcl_Interp *interp, Tcl_Channel chan, Tcl_Obj *cmdObjPtr) } declare 162 { void TclChannelEventScriptInvoker(ClientData clientData, int flags) } # ALERT: The result of 'TclGetInstructionTable' is actually a # "const InstructionDesc*" but we do not want to describe this structure in # "tclInt.h". It is described in "tclCompile.h". Use a cast to the # correct type when calling this procedure. declare 163 { const void *TclGetInstructionTable(void) } # ALERT: The argument of 'TclExpandCodeArray' is actually a # "CompileEnv*" but we do not want to describe this structure in # "tclInt.h". It is described in "tclCompile.h". declare 164 { void TclExpandCodeArray(void *envPtr) } # These functions are vfs aware, but are generally only useful internally. declare 165 { void TclpSetInitialEncodings(void) } # New function due to TIP #33 declare 166 { int TclListObjSetElement(Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj *valuePtr) } # VFS-aware versions of Tcl*StartupScriptFileName (158 and 159 above) # REMOVED (except from stub table) - use public Tcl_SetStartupScript() declare 167 { void TclSetStartupScriptPath(Tcl_Obj *pathPtr) } # REMOVED (except from stub table) - use public Tcl_GetStartupScript() declare 168 { Tcl_Obj *TclGetStartupScriptPath(void) } # variant of Tcl_UtfNCmp that takes n as bytes, not chars declare 169 { int TclpUtfNcmp2(const char *s1, const char *s2, unsigned long n) } declare 170 { int TclCheckInterpTraces(Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]) } declare 171 { int TclCheckExecutionTraces(Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]) } declare 172 { int TclInThreadExit(void) } # added for 8.4.2 declare 173 { int TclUniCharMatch(const Tcl_UniChar *string, int strLen, const Tcl_UniChar *pattern, int ptnLen, int flags) } # added for 8.4.3 #declare 174 { # Tcl_Obj *TclIncrWideVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, # Tcl_Obj *part2Ptr, Tcl_WideInt wideIncrAmount, int part1NotParsed) #} # Factoring out of trace code declare 175 { int TclCallVarTraces(Interp *iPtr, Var *arrayPtr, Var *varPtr, const char *part1, const char *part2, int flags, int leaveErrMsg) } declare 176 { void TclCleanupVar(Var *varPtr, Var *arrayPtr) } declare 177 { void TclVarErrMsg(Tcl_Interp *interp, const char *part1, const char *part2, const char *operation, const char *reason) } # TIP 338 made these public - now declared in tcl.h too declare 178 { void Tcl_SetStartupScript(Tcl_Obj *pathPtr, const char *encodingName) } declare 179 { Tcl_Obj *Tcl_GetStartupScript(const char **encodingNamePtr) } # REMOVED # Allocate lists without copying arrays # declare 180 { # Tcl_Obj *TclNewListObjDirect(int objc, Tcl_Obj **objv) # } #declare 181 { # Tcl_Obj *TclDbNewListObjDirect(int objc, Tcl_Obj **objv, # const char *file, int line) #} # TclpGmtime and TclpLocaltime promoted to the generic interface from unix declare 182 { struct tm *TclpLocaltime(const time_t *clock) } declare 183 { struct tm *TclpGmtime(const time_t *clock) } # For the new "Thread Storage" subsystem. ### REMOVED on grounds it should never have been exposed. All these ### functions are now either static in tclThreadStorage.c or ### MODULE_SCOPE. # declare 184 { # void TclThreadStorageLockInit(void) # } # declare 185 { # void TclThreadStorageLock(void) # } # declare 186 { # void TclThreadStorageUnlock(void) # } # declare 187 { # void TclThreadStoragePrint(FILE *outFile, int flags) # } # declare 188 { # Tcl_HashTable *TclThreadStorageGetHashTable(Tcl_ThreadId id) # } # declare 189 { # Tcl_HashTable *TclThreadStorageInit(Tcl_ThreadId id, void *reserved) # } # declare 190 { # void TclThreadStorageDataKeyInit(Tcl_ThreadDataKey *keyPtr) # } # declare 191 { # void *TclThreadStorageDataKeyGet(Tcl_ThreadDataKey *keyPtr) # } # declare 192 { # void TclThreadStorageDataKeySet(Tcl_ThreadDataKey *keyPtr, void *data) # } # declare 193 { # void TclFinalizeThreadStorageThread(Tcl_ThreadId id) # } # declare 194 { # void TclFinalizeThreadStorage(void) # } # declare 195 { # void TclFinalizeThreadStorageData(Tcl_ThreadDataKey *keyPtr) # } # declare 196 { # void TclFinalizeThreadStorageDataKey(Tcl_ThreadDataKey *keyPtr) # } # # Added in tcl8.5a5 for compiler/executor experimentation. # Disabled in Tcl 8.5.1; experiments terminated. :/ # #declare 197 { # int TclCompEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr, # const CmdFrame *invoker, int word) #} declare 198 { int TclObjGetFrame(Tcl_Interp *interp, Tcl_Obj *objPtr, CallFrame **framePtrPtr) } #declare 199 { # int TclMatchIsTrivial(const char *pattern) #} # 200-208 exported for use by the test suite [Bug 1054748] declare 200 { int TclpObjRemoveDirectory(Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr) } declare 201 { int TclpObjCopyDirectory(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr) } declare 202 { int TclpObjCreateDirectory(Tcl_Obj *pathPtr) } declare 203 { int TclpObjDeleteFile(Tcl_Obj *pathPtr) } declare 204 { int TclpObjCopyFile(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr) } declare 205 { int TclpObjRenameFile(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr) } declare 206 { int TclpObjStat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf) } declare 207 { int TclpObjAccess(Tcl_Obj *pathPtr, int mode) } declare 208 { Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions) } # Made public by TIP 258 #declare 209 { # Tcl_Obj *TclGetEncodingSearchPath(void) #} #declare 210 { # int TclSetEncodingSearchPath(Tcl_Obj *searchPath) #} #declare 211 { # const char *TclpGetEncodingNameFromEnvironment(Tcl_DString *bufPtr) #} declare 212 { void TclpFindExecutable(const char *argv0) } declare 213 { Tcl_Obj *TclGetObjNameOfExecutable(void) } declare 214 { void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding) } declare 215 { void *TclStackAlloc(Tcl_Interp *interp, int numBytes) } declare 216 { void TclStackFree(Tcl_Interp *interp, void *freePtr) } declare 217 { int TclPushStackFrame(Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame) } declare 218 { void TclPopStackFrame(Tcl_Interp *interp) } # for use in tclTest.c declare 224 { TclPlatformType *TclGetPlatform(void) } # declare 225 { Tcl_Obj *TclTraceDictPath(Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *const keyv[], int flags) } declare 226 { int TclObjBeingDeleted(Tcl_Obj *objPtr) } declare 227 { void TclSetNsPath(Namespace *nsPtr, int pathLength, Tcl_Namespace *pathAry[]) } # Used to be needed for TclOO-extension; unneeded now that TclOO is in the # core and NRE-enabled # declare 228 { # int TclObjInterpProcCore(register Tcl_Interp *interp, Tcl_Obj *procNameObj, # int skip, ProcErrorProc *errorProc) # } declare 229 { int TclPtrMakeUpvar(Tcl_Interp *interp, Var *otherP1Ptr, const char *myName, int myFlags, int index) } declare 230 { Var *TclObjLookupVar(Tcl_Interp *interp, Tcl_Obj *part1Ptr, const char *part2, int flags, const char *msg, const int createPart1, const int createPart2, Var **arrayPtrPtr) } declare 231 { int TclGetNamespaceFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr) } # Bits and pieces of TIP#280's guts declare 232 { int TclEvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word) } declare 233 { void TclGetSrcInfoForPc(CmdFrame *contextPtr) } # Exports for VarReform compat: Itcl, XOTcl like to peek into our varTables :( declare 234 { Var *TclVarHashCreateVar(TclVarHashTable *tablePtr, const char *key, int *newPtr) } declare 235 { void TclInitVarHashTable(TclVarHashTable *tablePtr, Namespace *nsPtr) } # TIP 337 made this one public declare 236 { void TclBackgroundException(Tcl_Interp *interp, int code) } # TIP #285: Script cancellation support. declare 237 { int TclResetCancellation(Tcl_Interp *interp, int force) } # NRE functions for "rogue" extensions to exploit NRE; they will need to # include NRE.h too. declare 238 { int TclNRInterpProc(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) } declare 239 { int TclNRInterpProcCore(Tcl_Interp *interp, Tcl_Obj *procNameObj, int skip, ProcErrorProc *errorProc) } declare 240 { int TclNRRunCallbacks(Tcl_Interp *interp, int result, struct NRE_callback *rootPtr) } declare 241 { int TclNREvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word) } declare 242 { int TclNREvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags, Command *cmdPtr) } # Tcl_Obj leak detection support. declare 243 { void TclDbDumpActiveObjects(FILE *outFile) } # Functions to make things better for itcl declare 244 { Tcl_HashTable *TclGetNamespaceChildTable(Tcl_Namespace *nsPtr) } declare 245 { Tcl_HashTable *TclGetNamespaceCommandTable(Tcl_Namespace *nsPtr) } declare 246 { int TclInitRewriteEnsemble(Tcl_Interp *interp, int numRemoved, int numInserted, Tcl_Obj *const *objv) } declare 247 { void TclResetRewriteEnsemble(Tcl_Interp *interp, int isRootEnsemble) } declare 248 { int TclCopyChannel(Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr) } declare 249 { char *TclDoubleDigits(double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr) } # TIP #285: Script cancellation support. declare 250 { void TclSetSlaveCancelFlags(Tcl_Interp *interp, int flags, int force) } # Allow extensions for optimization declare 251 { int TclRegisterLiteral(void *envPtr, char *bytes, int length, int flags) } ############################################################################## # Define the platform specific internal Tcl interface. These functions are # only available on the designated platform. interface tclIntPlat ################################ # Windows specific functions declare 0 win { void TclWinConvertError(DWORD errCode) } declare 1 win { void TclWinConvertWSAError(DWORD errCode) } declare 2 win { struct servent *TclWinGetServByName(const char *nm, const char *proto) } declare 3 win { int TclWinGetSockOpt(SOCKET s, int level, int optname, char *optval, int *optlen) } declare 4 win { HINSTANCE TclWinGetTclInstance(void) } # new for 8.4.20+/8.5.12+ Cygwin only declare 5 win { int TclUnixWaitForFile(int fd, int mask, int timeout) } # Removed in 8.1: # declare 5 win { # HINSTANCE TclWinLoadLibrary(char *name) # } declare 6 win { unsigned short TclWinNToHS(unsigned short ns) } declare 7 win { int TclWinSetSockOpt(SOCKET s, int level, int optname, const char *optval, int optlen) } declare 8 win { int TclpGetPid(Tcl_Pid pid) } declare 9 win { int TclWinGetPlatformId(void) } # new for 8.4.20+/8.5.12+ Cygwin only declare 10 win { Tcl_DirEntry *TclpReaddir(DIR *dir) } # Removed in 8.3.1 (for Win32s only) #declare 10 win { # int TclWinSynchSpawn(void *args, int type, void **trans, Tcl_Pid *pidPtr) #} # Pipe channel functions declare 11 win { void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan) } declare 12 win { int TclpCloseFile(TclFile file) } declare 13 win { Tcl_Channel TclpCreateCommandChannel(TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr) } declare 14 win { int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe) } declare 15 win { int TclpCreateProcess(Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr) } # new for 8.4.20+/8.5.12+ Cygwin only declare 16 win { int TclpIsAtty(int fd) } # Signature changed in 8.1: # declare 16 win { # TclFile TclpCreateTempFile(char *contents, Tcl_DString *namePtr) # } # declare 17 win { # char *TclpGetTZName(void) # } # new for 8.5.12+ Cygwin only declare 17 win { int TclUnixCopyFile(const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts) } declare 18 win { TclFile TclpMakeFile(Tcl_Channel channel, int direction) } declare 19 win { TclFile TclpOpenFile(const char *fname, int mode) } declare 20 win { void TclWinAddProcess(HANDLE hProcess, DWORD id) } # new for 8.4.20+/8.5.12+ declare 21 win { char *TclpInetNtoa(struct in_addr addr) } # removed permanently for 8.4 #declare 21 win { # void TclpAsyncMark(Tcl_AsyncHandler async) #} # Added in 8.1: declare 22 win { TclFile TclpCreateTempFile(const char *contents) } # Removed in 8.6: #declare 23 win { # char *TclpGetTZName(int isdst) #} declare 24 win { char *TclWinNoBackslash(char *path) } # replaced by generic TclGetPlatform #declare 25 win { # TclPlatformType *TclWinGetPlatform(void) #} declare 26 win { void TclWinSetInterfaces(int wide) } # Added in Tcl 8.3.3 / 8.4 declare 27 win { void TclWinFlushDirtyChannels(void) } # Added in 8.4.2 declare 28 win { void TclWinResetInterfaces(void) } ################################ # Unix specific functions # Pipe channel functions declare 0 unix { void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan) } declare 1 unix { int TclpCloseFile(TclFile file) } declare 2 unix { Tcl_Channel TclpCreateCommandChannel(TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr) } declare 3 unix { int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe) } declare 4 unix { int TclpCreateProcess(Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr) } # Signature changed in 8.1: # declare 5 unix { # TclFile TclpCreateTempFile(char *contents, Tcl_DString *namePtr) # } declare 6 unix { TclFile TclpMakeFile(Tcl_Channel channel, int direction) } declare 7 unix { TclFile TclpOpenFile(const char *fname, int mode) } declare 8 unix { int TclUnixWaitForFile(int fd, int mask, int timeout) } # Added in 8.1: declare 9 unix { TclFile TclpCreateTempFile(const char *contents) } # Added in 8.4: declare 10 unix { Tcl_DirEntry *TclpReaddir(DIR *dir) } # Slots 11 and 12 are forwarders for functions that were promoted to # generic Stubs declare 11 unix { struct tm *TclpLocaltime_unix(const time_t *clock) } declare 12 unix { struct tm *TclpGmtime_unix(const time_t *clock) } declare 13 unix { char *TclpInetNtoa(struct in_addr addr) } # Added in 8.5: declare 14 unix { int TclUnixCopyFile(const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts) } ################################ # Mac OS X specific functions declare 15 macosx { int TclMacOSXGetFileAttribute(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr) } declare 16 macosx { int TclMacOSXSetFileAttribute(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj *attributePtr) } declare 17 macosx { int TclMacOSXCopyFileAttributes(const char *src, const char *dst, const Tcl_StatBuf *statBufPtr) } declare 18 macosx { int TclMacOSXMatchType(Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types) } declare 19 macosx { void TclMacOSXNotifierAddRunLoopMode(const void *runLoopMode) } declare 29 {win unix} { int TclWinCPUID(unsigned int index, unsigned int *regs) } # Added in 8.6; core of TclpOpenTemporaryFile declare 30 {win unix} { int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj) } # Local Variables: # mode: tcl # End: tcl8.6.5/generic/tclNotify.c0000644000175000017500000007460612663660065015337 0ustar sergeisergei/* * tclNotify.c -- * * This file implements the generic portion of the Tcl notifier. The * notifier is lowest-level part of the event system. It manages an event * queue that holds Tcl_Event structures. The platform specific portion * of the notifier is defined in the tcl*Notify.c files in each platform * directory. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1998 by Scriptics Corporation. * Copyright (c) 2003 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Module-scope struct of notifier hooks that are checked in the default * notifier functions (for overriding via Tcl_SetNotifier). */ Tcl_NotifierProcs tclNotifierHooks = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* * For each event source (created with Tcl_CreateEventSource) there is a * structure of the following type: */ typedef struct EventSource { Tcl_EventSetupProc *setupProc; Tcl_EventCheckProc *checkProc; ClientData clientData; struct EventSource *nextPtr; } EventSource; /* * The following structure keeps track of the state of the notifier on a * per-thread basis. The first three elements keep track of the event queue. * In addition to the first (next to be serviced) and last events in the * queue, we keep track of a "marker" event. This provides a simple priority * mechanism whereby events can be inserted at the front of the queue but * behind all other high-priority events already in the queue (this is used * for things like a sequence of Enter and Leave events generated during a * grab in Tk). These elements are protected by the queueMutex so that any * thread can queue an event on any notifier. Note that all of the values in * this structure will be initialized to 0. */ typedef struct ThreadSpecificData { Tcl_Event *firstEventPtr; /* First pending event, or NULL if none. */ Tcl_Event *lastEventPtr; /* Last pending event, or NULL if none. */ Tcl_Event *markerEventPtr; /* Last high-priority event in queue, or NULL * if none. */ Tcl_Mutex queueMutex; /* Mutex to protect access to the previous * three fields. */ int serviceMode; /* One of TCL_SERVICE_NONE or * TCL_SERVICE_ALL. */ int blockTimeSet; /* 0 means there is no maximum block time: * block forever. */ Tcl_Time blockTime; /* If blockTimeSet is 1, gives the maximum * elapsed time for the next block. */ int inTraversal; /* 1 if Tcl_SetMaxBlockTime is being called * during an event source traversal. */ EventSource *firstEventSourcePtr; /* Pointer to first event source in list of * event sources for this thread. */ Tcl_ThreadId threadId; /* Thread that owns this notifier instance. */ ClientData clientData; /* Opaque handle for platform specific * notifier. */ int initialized; /* 1 if notifier has been initialized. */ struct ThreadSpecificData *nextPtr; /* Next notifier in global list of notifiers. * Access is controlled by the listLock global * mutex. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * Global list of notifiers. Access to this list is controlled by the listLock * mutex. If this becomes a performance bottleneck, this could be replaced * with a hashtable. */ static ThreadSpecificData *firstNotifierPtr = NULL; TCL_DECLARE_MUTEX(listLock) /* * Declarations for routines used only in this file. */ static void QueueEvent(ThreadSpecificData *tsdPtr, Tcl_Event *evPtr, Tcl_QueuePosition position); /* *---------------------------------------------------------------------- * * TclInitNotifier -- * * Initialize the thread local data structures for the notifier * subsystem. * * Results: * None. * * Side effects: * Adds the current thread to the global list of notifiers. * *---------------------------------------------------------------------- */ void TclInitNotifier(void) { ThreadSpecificData *tsdPtr; Tcl_ThreadId threadId = Tcl_GetCurrentThread(); Tcl_MutexLock(&listLock); for (tsdPtr = firstNotifierPtr; tsdPtr && tsdPtr->threadId != threadId; tsdPtr = tsdPtr->nextPtr) { /* Empty loop body. */ } if (NULL == tsdPtr) { /* * Notifier not yet initialized in this thread. */ tsdPtr = TCL_TSD_INIT(&dataKey); tsdPtr->threadId = threadId; tsdPtr->clientData = Tcl_InitNotifier(); tsdPtr->initialized = 1; tsdPtr->nextPtr = firstNotifierPtr; firstNotifierPtr = tsdPtr; } Tcl_MutexUnlock(&listLock); } /* *---------------------------------------------------------------------- * * TclFinalizeNotifier -- * * Finalize the thread local data structures for the notifier subsystem. * * Results: * None. * * Side effects: * Removes the notifier associated with the current thread from the * global notifier list. This is done only if the notifier was * initialized for this thread by call to TclInitNotifier(). This is * always true for threads which have been seeded with an Tcl * interpreter, since the call to Tcl_CreateInterp will, among other * things, call TclInitializeSubsystems() and this one will, in turn, * call the TclInitNotifier() for the thread. For threads created without * the Tcl interpreter, though, nobody is explicitly nor implicitly * calling the TclInitNotifier hence, TclFinalizeNotifier should not be * performed at all. * *---------------------------------------------------------------------- */ void TclFinalizeNotifier(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ThreadSpecificData **prevPtrPtr; Tcl_Event *evPtr, *hold; if (!tsdPtr->initialized) { return; /* Notifier not initialized for the current thread */ } Tcl_MutexLock(&(tsdPtr->queueMutex)); for (evPtr = tsdPtr->firstEventPtr; evPtr != NULL; ) { hold = evPtr; evPtr = evPtr->nextPtr; ckfree(hold); } tsdPtr->firstEventPtr = NULL; tsdPtr->lastEventPtr = NULL; Tcl_MutexUnlock(&(tsdPtr->queueMutex)); Tcl_MutexLock(&listLock); Tcl_FinalizeNotifier(tsdPtr->clientData); Tcl_MutexFinalize(&(tsdPtr->queueMutex)); for (prevPtrPtr = &firstNotifierPtr; *prevPtrPtr != NULL; prevPtrPtr = &((*prevPtrPtr)->nextPtr)) { if (*prevPtrPtr == tsdPtr) { *prevPtrPtr = tsdPtr->nextPtr; break; } } tsdPtr->initialized = 0; Tcl_MutexUnlock(&listLock); } /* *---------------------------------------------------------------------- * * Tcl_SetNotifier -- * * Install a set of alternate functions for use with the notifier. In * particular, this can be used to install the Xt-based notifier for use * with the Browser plugin. * * Results: * None. * * Side effects: * Set the tclNotifierHooks global, which is checked in the default * notifier functions. * *---------------------------------------------------------------------- */ void Tcl_SetNotifier( Tcl_NotifierProcs *notifierProcPtr) { tclNotifierHooks = *notifierProcPtr; } /* *---------------------------------------------------------------------- * * Tcl_CreateEventSource -- * * This function is invoked to create a new source of events. The source * is identified by a function that gets invoked during Tcl_DoOneEvent to * check for events on that source and queue them. * * * Results: * None. * * Side effects: * SetupProc and checkProc will be invoked each time that Tcl_DoOneEvent * runs out of things to do. SetupProc will be invoked before * Tcl_DoOneEvent calls select or whatever else it uses to wait for * events. SetupProc typically calls functions like Tcl_SetMaxBlockTime * to indicate what to wait for. * * CheckProc is called after select or whatever operation was actually * used to wait. It figures out whether anything interesting actually * happened (e.g. by calling Tcl_AsyncReady), and then calls * Tcl_QueueEvent to queue any events that are ready. * * Each of these functions is passed two arguments, e.g. * (*checkProc)(ClientData clientData, int flags)); * ClientData is the same as the clientData argument here, and flags is a * combination of things like TCL_FILE_EVENTS that indicates what events * are of interest: setupProc and checkProc use flags to figure out * whether their events are relevant or not. * *---------------------------------------------------------------------- */ void Tcl_CreateEventSource( Tcl_EventSetupProc *setupProc, /* Function to invoke to figure out what to * wait for. */ Tcl_EventCheckProc *checkProc, /* Function to call after waiting to see what * happened. */ ClientData clientData) /* One-word argument to pass to setupProc and * checkProc. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); EventSource *sourcePtr = ckalloc(sizeof(EventSource)); sourcePtr->setupProc = setupProc; sourcePtr->checkProc = checkProc; sourcePtr->clientData = clientData; sourcePtr->nextPtr = tsdPtr->firstEventSourcePtr; tsdPtr->firstEventSourcePtr = sourcePtr; } /* *---------------------------------------------------------------------- * * Tcl_DeleteEventSource -- * * This function is invoked to delete the source of events given by proc * and clientData. * * Results: * None. * * Side effects: * The given event source is canceled, so its function will never again * be called. If no such source exists, nothing happens. * *---------------------------------------------------------------------- */ void Tcl_DeleteEventSource( Tcl_EventSetupProc *setupProc, /* Function to invoke to figure out what to * wait for. */ Tcl_EventCheckProc *checkProc, /* Function to call after waiting to see what * happened. */ ClientData clientData) /* One-word argument to pass to setupProc and * checkProc. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); EventSource *sourcePtr, *prevPtr; for (sourcePtr = tsdPtr->firstEventSourcePtr, prevPtr = NULL; sourcePtr != NULL; prevPtr = sourcePtr, sourcePtr = sourcePtr->nextPtr) { if ((sourcePtr->setupProc != setupProc) || (sourcePtr->checkProc != checkProc) || (sourcePtr->clientData != clientData)) { continue; } if (prevPtr == NULL) { tsdPtr->firstEventSourcePtr = sourcePtr->nextPtr; } else { prevPtr->nextPtr = sourcePtr->nextPtr; } ckfree(sourcePtr); return; } } /* *---------------------------------------------------------------------- * * Tcl_QueueEvent -- * * Queue an event on the event queue associated with the current thread. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_QueueEvent( Tcl_Event *evPtr, /* Event to add to queue. The storage space * must have been allocated the caller with * malloc (ckalloc), and it becomes the * property of the event queue. It will be * freed after the event has been handled. */ Tcl_QueuePosition position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, * TCL_QUEUE_MARK. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); QueueEvent(tsdPtr, evPtr, position); } /* *---------------------------------------------------------------------- * * Tcl_ThreadQueueEvent -- * * Queue an event on the specified thread's event queue. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_ThreadQueueEvent( Tcl_ThreadId threadId, /* Identifier for thread to use. */ Tcl_Event *evPtr, /* Event to add to queue. The storage space * must have been allocated the caller with * malloc (ckalloc), and it becomes the * property of the event queue. It will be * freed after the event has been handled. */ Tcl_QueuePosition position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, * TCL_QUEUE_MARK. */ { ThreadSpecificData *tsdPtr; /* * Find the notifier associated with the specified thread. */ Tcl_MutexLock(&listLock); for (tsdPtr = firstNotifierPtr; tsdPtr && tsdPtr->threadId != threadId; tsdPtr = tsdPtr->nextPtr) { /* Empty loop body. */ } /* * Queue the event if there was a notifier associated with the thread. */ if (tsdPtr) { QueueEvent(tsdPtr, evPtr, position); } else { ckfree(evPtr); } Tcl_MutexUnlock(&listLock); } /* *---------------------------------------------------------------------- * * QueueEvent -- * * Insert an event into the specified thread's event queue at one of * three positions: the head, the tail, or before a floating marker. * Events inserted before the marker will be processed in first-in- * first-out order, but before any events inserted at the tail of the * queue. Events inserted at the head of the queue will be processed in * last-in-first-out order. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void QueueEvent( ThreadSpecificData *tsdPtr, /* Handle to thread local data that indicates * which event queue to use. */ Tcl_Event *evPtr, /* Event to add to queue. The storage space * must have been allocated the caller with * malloc (ckalloc), and it becomes the * property of the event queue. It will be * freed after the event has been handled. */ Tcl_QueuePosition position) /* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, * TCL_QUEUE_MARK. */ { Tcl_MutexLock(&(tsdPtr->queueMutex)); if (position == TCL_QUEUE_TAIL) { /* * Append the event on the end of the queue. */ evPtr->nextPtr = NULL; if (tsdPtr->firstEventPtr == NULL) { tsdPtr->firstEventPtr = evPtr; } else { tsdPtr->lastEventPtr->nextPtr = evPtr; } tsdPtr->lastEventPtr = evPtr; } else if (position == TCL_QUEUE_HEAD) { /* * Push the event on the head of the queue. */ evPtr->nextPtr = tsdPtr->firstEventPtr; if (tsdPtr->firstEventPtr == NULL) { tsdPtr->lastEventPtr = evPtr; } tsdPtr->firstEventPtr = evPtr; } else if (position == TCL_QUEUE_MARK) { /* * Insert the event after the current marker event and advance the * marker to the new event. */ if (tsdPtr->markerEventPtr == NULL) { evPtr->nextPtr = tsdPtr->firstEventPtr; tsdPtr->firstEventPtr = evPtr; } else { evPtr->nextPtr = tsdPtr->markerEventPtr->nextPtr; tsdPtr->markerEventPtr->nextPtr = evPtr; } tsdPtr->markerEventPtr = evPtr; if (evPtr->nextPtr == NULL) { tsdPtr->lastEventPtr = evPtr; } } Tcl_MutexUnlock(&(tsdPtr->queueMutex)); } /* *---------------------------------------------------------------------- * * Tcl_DeleteEvents -- * * Calls a function for each event in the queue and deletes those for * which the function returns 1. Events for which the function returns 0 * are left in the queue. Operates on the queue associated with the * current thread. * * Results: * None. * * Side effects: * Potentially removes one or more events from the event queue. * *---------------------------------------------------------------------- */ void Tcl_DeleteEvents( Tcl_EventDeleteProc *proc, /* The function to call. */ ClientData clientData) /* The type-specific data. */ { Tcl_Event *evPtr; /* Pointer to the event being examined */ Tcl_Event *prevPtr; /* Pointer to evPtr's predecessor, or NULL if * evPtr designates the first event in the * queue for the thread. */ Tcl_Event *hold; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Tcl_MutexLock(&(tsdPtr->queueMutex)); /* * Walk the queue of events for the thread, applying 'proc' to each to * decide whether to eliminate the event. */ prevPtr = NULL; evPtr = tsdPtr->firstEventPtr; while (evPtr != NULL) { if (proc(evPtr, clientData) == 1) { /* * This event should be deleted. Unlink it. */ if (prevPtr == NULL) { tsdPtr->firstEventPtr = evPtr->nextPtr; } else { prevPtr->nextPtr = evPtr->nextPtr; } /* * Update 'last' and 'marker' events if either has been deleted. */ if (evPtr->nextPtr == NULL) { tsdPtr->lastEventPtr = prevPtr; } if (tsdPtr->markerEventPtr == evPtr) { tsdPtr->markerEventPtr = prevPtr; } /* * Delete the event data structure. */ hold = evPtr; evPtr = evPtr->nextPtr; ckfree(hold); } else { /* * Event is to be retained. */ prevPtr = evPtr; evPtr = evPtr->nextPtr; } } Tcl_MutexUnlock(&(tsdPtr->queueMutex)); } /* *---------------------------------------------------------------------- * * Tcl_ServiceEvent -- * * Process one event from the event queue, or invoke an asynchronous * event handler. Operates on event queue for current thread. * * Results: * The return value is 1 if the function actually found an event to * process. If no processing occurred, then 0 is returned. * * Side effects: * Invokes all of the event handlers for the highest priority event in * the event queue. May collapse some events into a single event or * discard stale events. * *---------------------------------------------------------------------- */ int Tcl_ServiceEvent( int flags) /* Indicates what events should be processed. * May be any combination of TCL_WINDOW_EVENTS * TCL_FILE_EVENTS, TCL_TIMER_EVENTS, or other * flags defined elsewhere. Events not * matching this will be skipped for * processing later. */ { Tcl_Event *evPtr, *prevPtr; Tcl_EventProc *proc; int result; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * Asynchronous event handlers are considered to be the highest priority * events, and so must be invoked before we process events on the event * queue. */ if (Tcl_AsyncReady()) { (void) Tcl_AsyncInvoke(NULL, 0); return 1; } /* * No event flags is equivalent to TCL_ALL_EVENTS. */ if ((flags & TCL_ALL_EVENTS) == 0) { flags |= TCL_ALL_EVENTS; } /* * Loop through all the events in the queue until we find one that can * actually be handled. */ Tcl_MutexLock(&(tsdPtr->queueMutex)); for (evPtr = tsdPtr->firstEventPtr; evPtr != NULL; evPtr = evPtr->nextPtr) { /* * Call the handler for the event. If it actually handles the event * then free the storage for the event. There are two tricky things * here, both stemming from the fact that the event code may be * re-entered while servicing the event: * * 1. Set the "proc" field to NULL. This is a signal to ourselves * that we shouldn't reexecute the handler if the event loop is * re-entered. * 2. When freeing the event, must search the queue again from the * front to find it. This is because the event queue could change * almost arbitrarily while handling the event, so we can't depend * on pointers found now still being valid when the handler * returns. */ proc = evPtr->proc; if (proc == NULL) { continue; } evPtr->proc = NULL; /* * Release the lock before calling the event function. This allows * other threads to post events if we enter a recursive event loop in * this thread. Note that we are making the assumption that if the * proc returns 0, the event is still in the list. */ Tcl_MutexUnlock(&(tsdPtr->queueMutex)); result = proc(evPtr, flags); Tcl_MutexLock(&(tsdPtr->queueMutex)); if (result) { /* * The event was processed, so remove it from the queue. */ if (tsdPtr->firstEventPtr == evPtr) { tsdPtr->firstEventPtr = evPtr->nextPtr; if (evPtr->nextPtr == NULL) { tsdPtr->lastEventPtr = NULL; } if (tsdPtr->markerEventPtr == evPtr) { tsdPtr->markerEventPtr = NULL; } } else { for (prevPtr = tsdPtr->firstEventPtr; prevPtr && prevPtr->nextPtr != evPtr; prevPtr = prevPtr->nextPtr) { /* Empty loop body. */ } if (prevPtr) { prevPtr->nextPtr = evPtr->nextPtr; if (evPtr->nextPtr == NULL) { tsdPtr->lastEventPtr = prevPtr; } if (tsdPtr->markerEventPtr == evPtr) { tsdPtr->markerEventPtr = prevPtr; } } else { evPtr = NULL; } } if (evPtr) { ckfree(evPtr); } Tcl_MutexUnlock(&(tsdPtr->queueMutex)); return 1; } else { /* * The event wasn't actually handled, so we have to restore the * proc field to allow the event to be attempted again. */ evPtr->proc = proc; } } Tcl_MutexUnlock(&(tsdPtr->queueMutex)); return 0; } /* *---------------------------------------------------------------------- * * Tcl_GetServiceMode -- * * This routine returns the current service mode of the notifier. * * Results: * Returns either TCL_SERVICE_ALL or TCL_SERVICE_NONE. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetServiceMode(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); return tsdPtr->serviceMode; } /* *---------------------------------------------------------------------- * * Tcl_SetServiceMode -- * * This routine sets the current service mode of the tsdPtr-> * * Results: * Returns the previous service mode. * * Side effects: * Invokes the notifier service mode hook function. * *---------------------------------------------------------------------- */ int Tcl_SetServiceMode( int mode) /* New service mode: TCL_SERVICE_ALL or * TCL_SERVICE_NONE */ { int oldMode; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); oldMode = tsdPtr->serviceMode; tsdPtr->serviceMode = mode; Tcl_ServiceModeHook(mode); return oldMode; } /* *---------------------------------------------------------------------- * * Tcl_SetMaxBlockTime -- * * This function is invoked by event sources to tell the notifier how * long it may block the next time it blocks. The timePtr argument gives * a maximum time; the actual time may be less if some other event source * requested a smaller time. * * Results: * None. * * Side effects: * May reduce the length of the next sleep in the tsdPtr-> * *---------------------------------------------------------------------- */ void Tcl_SetMaxBlockTime( const Tcl_Time *timePtr) /* Specifies a maximum elapsed time for the * next blocking operation in the event * tsdPtr-> */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!tsdPtr->blockTimeSet || (timePtr->sec < tsdPtr->blockTime.sec) || ((timePtr->sec == tsdPtr->blockTime.sec) && (timePtr->usec < tsdPtr->blockTime.usec))) { tsdPtr->blockTime = *timePtr; tsdPtr->blockTimeSet = 1; } /* * If we are called outside an event source traversal, set the timeout * immediately. */ if (!tsdPtr->inTraversal) { Tcl_SetTimer(&tsdPtr->blockTime); } } /* *---------------------------------------------------------------------- * * Tcl_DoOneEvent -- * * Process a single event of some sort. If there's no work to do, wait * for an event to occur, then process it. * * Results: * The return value is 1 if the function actually found an event to * process. If no processing occurred, then 0 is returned (this can * happen if the TCL_DONT_WAIT flag is set or if there are no event * handlers to wait for in the set specified by flags). * * Side effects: * May delay execution of process while waiting for an event, unless * TCL_DONT_WAIT is set in the flags argument. Event sources are invoked * to check for and queue events. Event handlers may produce arbitrary * side effects. * *---------------------------------------------------------------------- */ int Tcl_DoOneEvent( int flags) /* Miscellaneous flag values: may be any * combination of TCL_DONT_WAIT, * TCL_WINDOW_EVENTS, TCL_FILE_EVENTS, * TCL_TIMER_EVENTS, TCL_IDLE_EVENTS, or * others defined by event sources. */ { int result = 0, oldMode; EventSource *sourcePtr; Tcl_Time *timePtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * The first thing we do is to service any asynchronous event handlers. */ if (Tcl_AsyncReady()) { (void) Tcl_AsyncInvoke(NULL, 0); return 1; } /* * No event flags is equivalent to TCL_ALL_EVENTS. */ if ((flags & TCL_ALL_EVENTS) == 0) { flags |= TCL_ALL_EVENTS; } /* * Set the service mode to none so notifier event routines won't try to * service events recursively. */ oldMode = tsdPtr->serviceMode; tsdPtr->serviceMode = TCL_SERVICE_NONE; /* * The core of this function is an infinite loop, even though we only * service one event. The reason for this is that we may be processing * events that don't do anything inside of Tcl. */ while (1) { /* * If idle events are the only things to service, skip the main part * of the loop and go directly to handle idle events (i.e. don't wait * even if TCL_DONT_WAIT isn't set). */ if ((flags & TCL_ALL_EVENTS) == TCL_IDLE_EVENTS) { flags = TCL_IDLE_EVENTS | TCL_DONT_WAIT; goto idleEvents; } /* * Ask Tcl to service a queued event, if there are any. */ if (Tcl_ServiceEvent(flags)) { result = 1; break; } /* * If TCL_DONT_WAIT is set, be sure to poll rather than blocking, * otherwise reset the block time to infinity. */ if (flags & TCL_DONT_WAIT) { tsdPtr->blockTime.sec = 0; tsdPtr->blockTime.usec = 0; tsdPtr->blockTimeSet = 1; } else { tsdPtr->blockTimeSet = 0; } /* * Set up all the event sources for new events. This will cause the * block time to be updated if necessary. */ tsdPtr->inTraversal = 1; for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->setupProc) { sourcePtr->setupProc(sourcePtr->clientData, flags); } } tsdPtr->inTraversal = 0; if ((flags & TCL_DONT_WAIT) || tsdPtr->blockTimeSet) { timePtr = &tsdPtr->blockTime; } else { timePtr = NULL; } /* * Wait for a new event or a timeout. If Tcl_WaitForEvent returns -1, * we should abort Tcl_DoOneEvent. */ result = Tcl_WaitForEvent(timePtr); if (result < 0) { result = 0; break; } /* * Check all the event sources for new events. */ for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->checkProc) { sourcePtr->checkProc(sourcePtr->clientData, flags); } } /* * Check for events queued by the notifier or event sources. */ if (Tcl_ServiceEvent(flags)) { result = 1; break; } /* * We've tried everything at this point, but nobody we know about had * anything to do. Check for idle events. If none, either quit or go * back to the top and try again. */ idleEvents: if (flags & TCL_IDLE_EVENTS) { if (TclServiceIdle()) { result = 1; break; } } if (flags & TCL_DONT_WAIT) { break; } /* * If Tcl_WaitForEvent has returned 1, indicating that one system * event has been dispatched (and thus that some Tcl code might have * been indirectly executed), we break out of the loop. We do this to * give VwaitCmd for instance a chance to check if that system event * had the side effect of changing the variable (so the vwait can * return and unwind properly). * * NB: We will process idle events if any first, because otherwise we * might never do the idle events if the notifier always gets * system events. */ if (result) { break; } } tsdPtr->serviceMode = oldMode; return result; } /* *---------------------------------------------------------------------- * * Tcl_ServiceAll -- * * This routine checks all of the event sources, processes events that * are on the Tcl event queue, and then calls the any idle handlers. * Platform specific notifier callbacks that generate events should call * this routine before returning to the system in order to ensure that * Tcl gets a chance to process the new events. * * Results: * Returns 1 if an event or idle handler was invoked, else 0. * * Side effects: * Anything that an event or idle handler may do. * *---------------------------------------------------------------------- */ int Tcl_ServiceAll(void) { int result = 0; EventSource *sourcePtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->serviceMode == TCL_SERVICE_NONE) { return result; } /* * We need to turn off event servicing like we to in Tcl_DoOneEvent, to * avoid recursive calls. */ tsdPtr->serviceMode = TCL_SERVICE_NONE; /* * Check async handlers first. */ if (Tcl_AsyncReady()) { (void) Tcl_AsyncInvoke(NULL, 0); } /* * Make a single pass through all event sources, queued events, and idle * handlers. Note that we wait to update the notifier timer until the end * so we can avoid multiple changes. */ tsdPtr->inTraversal = 1; tsdPtr->blockTimeSet = 0; for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->setupProc) { sourcePtr->setupProc(sourcePtr->clientData, TCL_ALL_EVENTS); } } for (sourcePtr = tsdPtr->firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->checkProc) { sourcePtr->checkProc(sourcePtr->clientData, TCL_ALL_EVENTS); } } while (Tcl_ServiceEvent(0)) { result = 1; } if (TclServiceIdle()) { result = 1; } if (!tsdPtr->blockTimeSet) { Tcl_SetTimer(NULL); } else { Tcl_SetTimer(&tsdPtr->blockTime); } tsdPtr->inTraversal = 0; tsdPtr->serviceMode = TCL_SERVICE_ALL; return result; } /* *---------------------------------------------------------------------- * * Tcl_ThreadAlert -- * * This function wakes up the notifier associated with the specified * thread (if there is one). * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_ThreadAlert( Tcl_ThreadId threadId) /* Identifier for thread to use. */ { ThreadSpecificData *tsdPtr; /* * Find the notifier associated with the specified thread. Note that we * need to hold the listLock while calling Tcl_AlertNotifier to avoid a * race condition where the specified thread might destroy its notifier. */ Tcl_MutexLock(&listLock); for (tsdPtr = firstNotifierPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { if (tsdPtr->threadId == threadId) { Tcl_AlertNotifier(tsdPtr->clientData); break; } } Tcl_MutexUnlock(&listLock); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclOOBasic.c0000644000175000017500000010614012663660065015333 0ustar sergeisergei/* * tclOOBasic.c -- * * This file contains implementations of the "simple" commands and * methods from the object-system core. * * Copyright (c) 2005-2013 by Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tclInt.h" #include "tclOOInt.h" static inline Tcl_Object *AddConstructionFinalizer(Tcl_Interp *interp); static Tcl_NRPostProc AfterNRDestructor; static Tcl_NRPostProc DecrRefsPostClassConstructor; static Tcl_NRPostProc FinalizeConstruction; static Tcl_NRPostProc FinalizeEval; static Tcl_NRPostProc NextRestoreFrame; /* * ---------------------------------------------------------------------- * * AddCreateCallback, FinalizeConstruction -- * * Special version of TclNRAddCallback that allows the caller to splice * the object created later on. Always calls FinalizeConstruction, which * converts the object into its name and stores that in the interpreter * result. This is shared by all the construction methods (create, * createWithNamespace, new). * * Note that this is the only code in this file (or, indeed, the whole of * TclOO) that uses NRE internals; it is the only code that does * non-standard poking in the NRE guts. * * ---------------------------------------------------------------------- */ static inline Tcl_Object * AddConstructionFinalizer( Tcl_Interp *interp) { TclNRAddCallback(interp, FinalizeConstruction, NULL, NULL, NULL, NULL); return (Tcl_Object *) &(TOP_CB(interp)->data[0]); } static int FinalizeConstruction( ClientData data[], Tcl_Interp *interp, int result) { Object *oPtr = data[0]; if (result != TCL_OK) { return result; } Tcl_SetObjResult(interp, TclOOObjectName(interp, oPtr)); return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOO_Class_Constructor -- * * Implementation for oo::class constructor. * * ---------------------------------------------------------------------- */ int TclOO_Class_Constructor( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) Tcl_ObjectContextObject(context); Tcl_Obj **invoke; if (objc-1 > Tcl_ObjectContextSkippedArgs(context)) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "?definitionScript?"); return TCL_ERROR; } else if (objc == Tcl_ObjectContextSkippedArgs(context)) { return TCL_OK; } /* * Delegate to [oo::define] to do the work. */ invoke = ckalloc(3 * sizeof(Tcl_Obj *)); invoke[0] = oPtr->fPtr->defineName; invoke[1] = TclOOObjectName(interp, oPtr); invoke[2] = objv[objc-1]; /* * Must add references or errors in configuration script will cause * trouble. */ Tcl_IncrRefCount(invoke[0]); Tcl_IncrRefCount(invoke[1]); Tcl_IncrRefCount(invoke[2]); TclNRAddCallback(interp, DecrRefsPostClassConstructor, invoke, NULL, NULL, NULL); /* * Tricky point: do not want the extra reported level in the Tcl stack * trace, so use TCL_EVAL_NOERR. */ return TclNREvalObjv(interp, 3, invoke, TCL_EVAL_NOERR, NULL); } static int DecrRefsPostClassConstructor( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj **invoke = data[0]; TclDecrRefCount(invoke[0]); TclDecrRefCount(invoke[1]); TclDecrRefCount(invoke[2]); ckfree(invoke); return result; } /* * ---------------------------------------------------------------------- * * TclOO_Class_Create -- * * Implementation for oo::class->create method. * * ---------------------------------------------------------------------- */ int TclOO_Class_Create( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { Object *oPtr = (Object *) Tcl_ObjectContextObject(context); const char *objName; int len; /* * Sanity check; should not be possible to invoke this method on a * non-class. */ if (oPtr->classPtr == NULL) { Tcl_Obj *cmdnameObj = TclOOObjectName(interp, oPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "object \"%s\" is not a class", TclGetString(cmdnameObj))); Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", NULL); return TCL_ERROR; } /* * Check we have the right number of (sensible) arguments. */ if (objc - Tcl_ObjectContextSkippedArgs(context) < 1) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "objectName ?arg ...?"); return TCL_ERROR; } objName = Tcl_GetStringFromObj( objv[Tcl_ObjectContextSkippedArgs(context)], &len); if (len == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "object name must not be empty", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", NULL); return TCL_ERROR; } /* * Make the object and return its name. */ return TclNRNewObjectInstance(interp, (Tcl_Class) oPtr->classPtr, objName, NULL, objc, objv, Tcl_ObjectContextSkippedArgs(context)+1, AddConstructionFinalizer(interp)); } /* * ---------------------------------------------------------------------- * * TclOO_Class_CreateNs -- * * Implementation for oo::class->createWithNamespace method. * * ---------------------------------------------------------------------- */ int TclOO_Class_CreateNs( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { Object *oPtr = (Object *) Tcl_ObjectContextObject(context); const char *objName, *nsName; int len; /* * Sanity check; should not be possible to invoke this method on a * non-class. */ if (oPtr->classPtr == NULL) { Tcl_Obj *cmdnameObj = TclOOObjectName(interp, oPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "object \"%s\" is not a class", TclGetString(cmdnameObj))); Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", NULL); return TCL_ERROR; } /* * Check we have the right number of (sensible) arguments. */ if (objc - Tcl_ObjectContextSkippedArgs(context) < 2) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "objectName namespaceName ?arg ...?"); return TCL_ERROR; } objName = Tcl_GetStringFromObj( objv[Tcl_ObjectContextSkippedArgs(context)], &len); if (len == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "object name must not be empty", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", NULL); return TCL_ERROR; } nsName = Tcl_GetStringFromObj( objv[Tcl_ObjectContextSkippedArgs(context)+1], &len); if (len == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "namespace name must not be empty", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "EMPTY_NAME", NULL); return TCL_ERROR; } /* * Make the object and return its name. */ return TclNRNewObjectInstance(interp, (Tcl_Class) oPtr->classPtr, objName, nsName, objc, objv, Tcl_ObjectContextSkippedArgs(context)+2, AddConstructionFinalizer(interp)); } /* * ---------------------------------------------------------------------- * * TclOO_Class_New -- * * Implementation for oo::class->new method. * * ---------------------------------------------------------------------- */ int TclOO_Class_New( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { Object *oPtr = (Object *) Tcl_ObjectContextObject(context); /* * Sanity check; should not be possible to invoke this method on a * non-class. */ if (oPtr->classPtr == NULL) { Tcl_Obj *cmdnameObj = TclOOObjectName(interp, oPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "object \"%s\" is not a class", TclGetString(cmdnameObj))); Tcl_SetErrorCode(interp, "TCL", "OO", "INSTANTIATE_NONCLASS", NULL); return TCL_ERROR; } /* * Make the object and return its name. */ return TclNRNewObjectInstance(interp, (Tcl_Class) oPtr->classPtr, NULL, NULL, objc, objv, Tcl_ObjectContextSkippedArgs(context), AddConstructionFinalizer(interp)); } /* * ---------------------------------------------------------------------- * * TclOO_Object_Destroy -- * * Implementation for oo::object->destroy method. * * ---------------------------------------------------------------------- */ int TclOO_Object_Destroy( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { Object *oPtr = (Object *) Tcl_ObjectContextObject(context); CallContext *contextPtr; if (objc != Tcl_ObjectContextSkippedArgs(context)) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; } if (!(oPtr->flags & DESTRUCTOR_CALLED)) { oPtr->flags |= DESTRUCTOR_CALLED; contextPtr = TclOOGetCallContext(oPtr, NULL, DESTRUCTOR, NULL); if (contextPtr != NULL) { contextPtr->callPtr->flags |= DESTRUCTOR; contextPtr->skip = 0; TclNRAddCallback(interp, AfterNRDestructor, contextPtr, NULL, NULL, NULL); TclPushTailcallPoint(interp); return TclOOInvokeContext(contextPtr, interp, 0, NULL); } } if (oPtr->command) { Tcl_DeleteCommandFromToken(interp, oPtr->command); } return TCL_OK; } static int AfterNRDestructor( ClientData data[], Tcl_Interp *interp, int result) { CallContext *contextPtr = data[0]; if (contextPtr->oPtr->command) { Tcl_DeleteCommandFromToken(interp, contextPtr->oPtr->command); } TclOODeleteContext(contextPtr); return result; } /* * ---------------------------------------------------------------------- * * TclOO_Object_Eval -- * * Implementation for oo::object->eval method. * * ---------------------------------------------------------------------- */ int TclOO_Object_Eval( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { CallContext *contextPtr = (CallContext *) context; Tcl_Object object = Tcl_ObjectContextObject(context); register const int skip = Tcl_ObjectContextSkippedArgs(context); CallFrame *framePtr, **framePtrPtr = &framePtr; Tcl_Obj *scriptPtr; CmdFrame *invoker; if (objc-1 < skip) { Tcl_WrongNumArgs(interp, skip, objv, "arg ?arg ...?"); return TCL_ERROR; } /* * Make the object's namespace the current namespace and evaluate the * command(s). */ (void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr, Tcl_GetObjectNamespace(object), 0); framePtr->objc = objc; framePtr->objv = objv; /* Reference counts do not need to be * incremented here. */ if (!(contextPtr->callPtr->flags & PUBLIC_METHOD)) { object = NULL; /* Now just for error mesage printing. */ } /* * Work out what script we are actually going to evaluate. * * When there's more than one argument, we concatenate them together with * spaces between, then evaluate the result. Tcl_EvalObjEx will delete the * object when it decrements its refcount after eval'ing it. */ if (objc != skip+1) { scriptPtr = Tcl_ConcatObj(objc-skip, objv+skip); invoker = NULL; } else { scriptPtr = objv[skip]; invoker = ((Interp *) interp)->cmdFramePtr; } /* * Evaluate the script now, with FinalizeEval to do the processing after * the script completes. */ TclNRAddCallback(interp, FinalizeEval, object, NULL, NULL, NULL); return TclNREvalObjEx(interp, scriptPtr, 0, invoker, skip); } static int FinalizeEval( ClientData data[], Tcl_Interp *interp, int result) { if (result == TCL_ERROR) { Object *oPtr = data[0]; const char *namePtr; if (oPtr) { namePtr = TclGetString(TclOOObjectName(interp, oPtr)); } else { namePtr = "my"; } Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (in \"%s eval\" script line %d)", namePtr, Tcl_GetErrorLine(interp))); } /* * Restore the previous "current" namespace. */ TclPopStackFrame(interp); return result; } /* * ---------------------------------------------------------------------- * * TclOO_Object_Unknown -- * * Default unknown method handler method (defined in oo::object). This * just creates a suitable error message. * * ---------------------------------------------------------------------- */ int TclOO_Object_Unknown( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { CallContext *contextPtr = (CallContext *) context; Object *oPtr = contextPtr->oPtr; const char **methodNames; int numMethodNames, i, skip = Tcl_ObjectContextSkippedArgs(context); Tcl_Obj *errorMsg; /* * If no method name, generate an error asking for a method name. (Only by * overriding *this* method can an object handle the absence of a method * name without an error). */ if (objc < skip+1) { Tcl_WrongNumArgs(interp, skip, objv, "method ?arg ...?"); return TCL_ERROR; } /* * Get the list of methods that we want to know about. */ numMethodNames = TclOOGetSortedMethodList(oPtr, contextPtr->callPtr->flags & PUBLIC_METHOD, &methodNames); /* * Special message when there are no visible methods at all. */ if (numMethodNames == 0) { Tcl_Obj *tmpBuf = TclOOObjectName(interp, oPtr); const char *piece; if (contextPtr->callPtr->flags & PUBLIC_METHOD) { piece = "visible methods"; } else { piece = "methods"; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "object \"%s\" has no %s", TclGetString(tmpBuf), piece)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[skip]), NULL); return TCL_ERROR; } errorMsg = Tcl_ObjPrintf("unknown method \"%s\": must be ", TclGetString(objv[skip])); for (i=0 ; ivariable method. * * ---------------------------------------------------------------------- */ int TclOO_Object_LinkVar( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { Interp *iPtr = (Interp *) interp; Tcl_Object object = Tcl_ObjectContextObject(context); Namespace *savedNsPtr; int i; if (objc-Tcl_ObjectContextSkippedArgs(context) < 0) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "?varName ...?"); return TCL_ERROR; } /* * A sanity check. Shouldn't ever happen. (This is all that remains of a * more complex check inherited from [global] after we have applied the * fix for [Bug 2903811]; note that the fix involved *removing* code.) */ if (iPtr->varFramePtr == NULL) { return TCL_OK; } for (i=Tcl_ObjectContextSkippedArgs(context) ; ivarFramePtr->nsPtr; iPtr->varFramePtr->nsPtr = (Namespace *) Tcl_GetObjectNamespace(object); varPtr = TclObjLookupVar(interp, objv[i], NULL, TCL_NAMESPACE_ONLY, "define", 1, 0, &aryPtr); iPtr->varFramePtr->nsPtr = savedNsPtr; if (varPtr == NULL || aryPtr != NULL) { /* * Variable cannot be an element in an array. If aryPtr is not * NULL, it is an element, so throw up an error and return. */ TclVarErrMsg(interp, varName, NULL, "define", "name refers to an element in an array"); Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL); return TCL_ERROR; } /* * Arrange for the lifetime of the variable to be correctly managed. * This is copied out of Tcl_VariableObjCmd... */ if (!TclIsVarNamespaceVar(varPtr)) { TclSetVarNamespaceVar(varPtr); } if (TclPtrMakeUpvar(interp, varPtr, varName, 0, -1) != TCL_OK) { return TCL_ERROR; } } return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOO_Object_VarName -- * * Implementation of the oo::object->varname method. * * ---------------------------------------------------------------------- */ int TclOO_Object_VarName( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* Interpreter in which to create the object; * also used for error reporting. */ Tcl_ObjectContext context, /* The object/call context. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* The actual arguments. */ { Var *varPtr, *aryVar; Tcl_Obj *varNamePtr, *argPtr; const char *arg; if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "varName"); return TCL_ERROR; } argPtr = objv[objc-1]; arg = Tcl_GetString(argPtr); /* * Convert the variable name to fully-qualified form if it wasn't already. * This has to be done prior to lookup because we can run into problems * with resolvers otherwise. [Bug 3603695] * * We still need to do the lookup; the variable could be linked to another * variable and we want the target's name. */ if (arg[0] == ':' && arg[1] == ':') { varNamePtr = argPtr; } else { Tcl_Namespace *namespacePtr = Tcl_GetObjectNamespace(Tcl_ObjectContextObject(context)); varNamePtr = Tcl_NewStringObj(namespacePtr->fullName, -1); Tcl_AppendToObj(varNamePtr, "::", 2); Tcl_AppendObjToObj(varNamePtr, argPtr); } Tcl_IncrRefCount(varNamePtr); varPtr = TclObjLookupVar(interp, varNamePtr, NULL, TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG, "refer to", 1, 1, &aryVar); Tcl_DecrRefCount(varNamePtr); if (varPtr == NULL) { Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", arg, NULL); return TCL_ERROR; } /* * Now that we've pinned down what variable we're really talking about * (including traversing variable links), convert back to a name. */ varNamePtr = Tcl_NewObj(); if (aryVar != NULL) { Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_GetVariableFullName(interp, (Tcl_Var) aryVar, varNamePtr); /* * WARNING! This code pokes inside the implementation of hash tables! */ hPtr = Tcl_FirstHashEntry((Tcl_HashTable *) aryVar->value.tablePtr, &search); while (hPtr != NULL) { if (varPtr == Tcl_GetHashValue(hPtr)) { Tcl_AppendToObj(varNamePtr, "(", -1); Tcl_AppendObjToObj(varNamePtr, hPtr->key.objPtr); Tcl_AppendToObj(varNamePtr, ")", -1); break; } hPtr = Tcl_NextHashEntry(&search); } } else { Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, varNamePtr); } Tcl_SetObjResult(interp, varNamePtr); return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOONextObjCmd, TclOONextToObjCmd -- * * Implementation of the [next] and [nextto] commands. Note that these * commands are only ever to be used inside the body of a procedure-like * method. * * ---------------------------------------------------------------------- */ int TclOONextObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; CallFrame *framePtr = iPtr->varFramePtr; Tcl_ObjectContext context; /* * Start with sanity checks on the calling context to make sure that we * are invoked from a suitable method context. If so, we can safely * retrieve the handle to the object call context. */ if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s may only be called from inside a method", TclGetString(objv[0]))); Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); return TCL_ERROR; } context = framePtr->clientData; /* * Invoke the (advanced) method call context in the caller context. Note * that this is like [uplevel 1] and not [eval]. */ TclNRAddCallback(interp, NextRestoreFrame, framePtr, NULL,NULL,NULL); iPtr->varFramePtr = framePtr->callerVarPtr; return TclNRObjectContextInvokeNext(interp, context, objc, objv, 1); } int TclOONextToObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; CallFrame *framePtr = iPtr->varFramePtr; Class *classPtr; CallContext *contextPtr; int i; Tcl_Object object; const char *methodType; /* * Start with sanity checks on the calling context to make sure that we * are invoked from a suitable method context. If so, we can safely * retrieve the handle to the object call context. */ if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s may only be called from inside a method", TclGetString(objv[0]))); Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); return TCL_ERROR; } contextPtr = framePtr->clientData; /* * Sanity check the arguments; we need the first one to refer to a class. */ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "class ?arg...?"); return TCL_ERROR; } object = Tcl_GetObjectFromObj(interp, objv[1]); if (object == NULL) { return TCL_ERROR; } classPtr = ((Object *)object)->classPtr; if (classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not a class", TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_REQUIRED", NULL); return TCL_ERROR; } /* * Search for an implementation of a method associated with the current * call on the call chain past the point where we currently are. Do not * allow jumping backwards! */ for (i=contextPtr->index+1 ; icallPtr->numChain ; i++) { struct MInvoke *miPtr = contextPtr->callPtr->chain + i; if (!miPtr->isFilter && miPtr->mPtr->declaringClassPtr == classPtr) { /* * Invoke the (advanced) method call context in the caller * context. Note that this is like [uplevel 1] and not [eval]. */ TclNRAddCallback(interp, NextRestoreFrame, framePtr, contextPtr, INT2PTR(contextPtr->index), NULL); contextPtr->index = i-1; iPtr->varFramePtr = framePtr->callerVarPtr; return TclNRObjectContextInvokeNext(interp, (Tcl_ObjectContext) contextPtr, objc, objv, 2); } } /* * Generate an appropriate error message, depending on whether the value * is on the chain but unreachable, or not on the chain at all. */ if (contextPtr->callPtr->flags & CONSTRUCTOR) { methodType = "constructor"; } else if (contextPtr->callPtr->flags & DESTRUCTOR) { methodType = "destructor"; } else { methodType = "method"; } for (i=contextPtr->index ; i>=0 ; i--) { struct MInvoke *miPtr = contextPtr->callPtr->chain + i; if (!miPtr->isFilter && miPtr->mPtr->declaringClassPtr == classPtr) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s implementation by \"%s\" not reachable from here", methodType, TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_REACHABLE", NULL); return TCL_ERROR; } } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s has no non-filter implementation by \"%s\"", methodType, TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", NULL); return TCL_ERROR; } static int NextRestoreFrame( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; CallContext *contextPtr = data[1]; iPtr->varFramePtr = data[0]; if (contextPtr != NULL) { contextPtr->index = PTR2INT(data[2]); } return result; } /* * ---------------------------------------------------------------------- * * TclOOSelfObjCmd -- * * Implementation of the [self] command, which provides introspection of * the call context. * * ---------------------------------------------------------------------- */ int TclOOSelfObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { static const char *const subcmds[] = { "call", "caller", "class", "filter", "method", "namespace", "next", "object", "target", NULL }; enum SelfCmds { SELF_CALL, SELF_CALLER, SELF_CLASS, SELF_FILTER, SELF_METHOD, SELF_NS, SELF_NEXT, SELF_OBJECT, SELF_TARGET }; Interp *iPtr = (Interp *) interp; CallFrame *framePtr = iPtr->varFramePtr; CallContext *contextPtr; Tcl_Obj *result[3]; int index; #define CurrentlyInvoked(contextPtr) \ ((contextPtr)->callPtr->chain[(contextPtr)->index]) /* * Start with sanity checks on the calling context and the method context. */ if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s may only be called from inside a method", TclGetString(objv[0]))); Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); return TCL_ERROR; } contextPtr = framePtr->clientData; /* * Now we do "conventional" argument parsing for a while. Note that no * subcommand takes arguments. */ if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "subcommand"); return TCL_ERROR; } else if (objc == 1) { index = SELF_OBJECT; } else if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "subcommand", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum SelfCmds) index) { case SELF_OBJECT: Tcl_SetObjResult(interp, TclOOObjectName(interp, contextPtr->oPtr)); return TCL_OK; case SELF_NS: Tcl_SetObjResult(interp, Tcl_NewStringObj( contextPtr->oPtr->namespacePtr->fullName,-1)); return TCL_OK; case SELF_CLASS: { Class *clsPtr = CurrentlyInvoked(contextPtr).mPtr->declaringClassPtr; if (clsPtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "method not defined by a class", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, TclOOObjectName(interp, clsPtr->thisPtr)); return TCL_OK; } case SELF_METHOD: if (contextPtr->callPtr->flags & CONSTRUCTOR) { Tcl_SetObjResult(interp, contextPtr->oPtr->fPtr->constructorName); } else if (contextPtr->callPtr->flags & DESTRUCTOR) { Tcl_SetObjResult(interp, contextPtr->oPtr->fPtr->destructorName); } else { Tcl_SetObjResult(interp, CurrentlyInvoked(contextPtr).mPtr->namePtr); } return TCL_OK; case SELF_FILTER: if (!CurrentlyInvoked(contextPtr).isFilter) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "not inside a filtering context", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", NULL); return TCL_ERROR; } else { register struct MInvoke *miPtr = &CurrentlyInvoked(contextPtr); Object *oPtr; const char *type; if (miPtr->filterDeclarer != NULL) { oPtr = miPtr->filterDeclarer->thisPtr; type = "class"; } else { oPtr = contextPtr->oPtr; type = "object"; } result[0] = TclOOObjectName(interp, oPtr); result[1] = Tcl_NewStringObj(type, -1); result[2] = miPtr->mPtr->namePtr; Tcl_SetObjResult(interp, Tcl_NewListObj(3, result)); return TCL_OK; } case SELF_CALLER: if ((framePtr->callerVarPtr == NULL) || !(framePtr->callerVarPtr->isProcCallFrame & FRAME_IS_METHOD)){ Tcl_SetObjResult(interp, Tcl_NewStringObj( "caller is not an object", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); return TCL_ERROR; } else { CallContext *callerPtr = framePtr->callerVarPtr->clientData; Method *mPtr = callerPtr->callPtr->chain[callerPtr->index].mPtr; Object *declarerPtr; if (mPtr->declaringClassPtr != NULL) { declarerPtr = mPtr->declaringClassPtr->thisPtr; } else if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; } else { /* * This should be unreachable code. */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "method without declarer!", -1)); return TCL_ERROR; } result[0] = TclOOObjectName(interp, declarerPtr); result[1] = TclOOObjectName(interp, callerPtr->oPtr); if (callerPtr->callPtr->flags & CONSTRUCTOR) { result[2] = declarerPtr->fPtr->constructorName; } else if (callerPtr->callPtr->flags & DESTRUCTOR) { result[2] = declarerPtr->fPtr->destructorName; } else { result[2] = mPtr->namePtr; } Tcl_SetObjResult(interp, Tcl_NewListObj(3, result)); return TCL_OK; } case SELF_NEXT: if (contextPtr->index < contextPtr->callPtr->numChain-1) { Method *mPtr = contextPtr->callPtr->chain[contextPtr->index+1].mPtr; Object *declarerPtr; if (mPtr->declaringClassPtr != NULL) { declarerPtr = mPtr->declaringClassPtr->thisPtr; } else if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; } else { /* * This should be unreachable code. */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "method without declarer!", -1)); return TCL_ERROR; } result[0] = TclOOObjectName(interp, declarerPtr); if (contextPtr->callPtr->flags & CONSTRUCTOR) { result[1] = declarerPtr->fPtr->constructorName; } else if (contextPtr->callPtr->flags & DESTRUCTOR) { result[1] = declarerPtr->fPtr->destructorName; } else { result[1] = mPtr->namePtr; } Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); } return TCL_OK; case SELF_TARGET: if (!CurrentlyInvoked(contextPtr).isFilter) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "not inside a filtering context", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "UNMATCHED_CONTEXT", NULL); return TCL_ERROR; } else { Method *mPtr; Object *declarerPtr; int i; for (i=contextPtr->index ; icallPtr->numChain ; i++){ if (!contextPtr->callPtr->chain[i].isFilter) { break; } } if (i == contextPtr->callPtr->numChain) { Tcl_Panic("filtering call chain without terminal non-filter"); } mPtr = contextPtr->callPtr->chain[i].mPtr; if (mPtr->declaringClassPtr != NULL) { declarerPtr = mPtr->declaringClassPtr->thisPtr; } else if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; } else { /* * This should be unreachable code. */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "method without declarer!", -1)); return TCL_ERROR; } result[0] = TclOOObjectName(interp, declarerPtr); result[1] = mPtr->namePtr; Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); return TCL_OK; } case SELF_CALL: result[0] = TclOORenderCallChain(interp, contextPtr->callPtr); result[1] = Tcl_NewIntObj(contextPtr->index); Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); return TCL_OK; } return TCL_ERROR; } /* * ---------------------------------------------------------------------- * * CopyObjectCmd -- * * Implementation of the [oo::copy] command, which clones an object (but * not its namespace). Note that no constructors are called during this * process. * * ---------------------------------------------------------------------- */ int TclOOCopyObjectCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Object oPtr, o2Ptr; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "sourceName ?targetName?"); return TCL_ERROR; } oPtr = Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } /* * Create a cloned object of the correct class. Note that constructors are * not called. Also note that we must resolve the object name ourselves * because we do not want to create the object in the current namespace, * but rather in the context of the namespace of the caller of the overall * [oo::define] command. */ if (objc == 2) { o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, NULL, NULL); } else { const char *name; Tcl_DString buffer; name = TclGetString(objv[2]); Tcl_DStringInit(&buffer); if (name[0]!=':' || name[1]!=':') { Interp *iPtr = (Interp *) interp; if (iPtr->varFramePtr != NULL) { Tcl_DStringAppend(&buffer, iPtr->varFramePtr->nsPtr->fullName, -1); } TclDStringAppendLiteral(&buffer, "::"); Tcl_DStringAppend(&buffer, name, -1); name = Tcl_DStringValue(&buffer); } o2Ptr = Tcl_CopyObjectInstance(interp, oPtr, name, NULL); Tcl_DStringFree(&buffer); } if (o2Ptr == NULL) { return TCL_ERROR; } /* * Return the name of the cloned object. */ Tcl_SetObjResult(interp, TclOOObjectName(interp, (Object *) o2Ptr)); return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclIOCmd.c0000644000175000017500000015204212663660065015011 0ustar sergeisergei/* * tclIOCmd.c -- * * Contains the definitions of most of the Tcl commands relating to IO. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Callback structure for accept callback in a TCP server. */ typedef struct AcceptCallback { char *script; /* Script to invoke. */ Tcl_Interp *interp; /* Interpreter in which to run it. */ } AcceptCallback; /* * Thread local storage used to maintain a per-thread stdout channel obj. * It must be per-thread because of std channel limitations. */ typedef struct ThreadSpecificData { int initialized; /* Set to 1 when the module is initialized. */ Tcl_Obj *stdoutObjPtr; /* Cached stdout channel Tcl_Obj */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * Static functions for this file: */ static void FinalizeIOCmdTSD(ClientData clientData); static void AcceptCallbackProc(ClientData callbackData, Tcl_Channel chan, char *address, int port); static int ChanPendingObjCmd(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ChanTruncateObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void RegisterTcpServerInterpCleanup(Tcl_Interp *interp, AcceptCallback *acceptCallbackPtr); static void TcpAcceptCallbacksDeleteProc(ClientData clientData, Tcl_Interp *interp); static void TcpServerCloseProc(ClientData callbackData); static void UnregisterTcpServerInterpCleanupProc( Tcl_Interp *interp, AcceptCallback *acceptCallbackPtr); /* *---------------------------------------------------------------------- * * FinalizeIOCmdTSD -- * * Release the storage associated with the per-thread cache. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void FinalizeIOCmdTSD( ClientData clientData) /* Not used. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->stdoutObjPtr != NULL) { Tcl_DecrRefCount(tsdPtr->stdoutObjPtr); tsdPtr->stdoutObjPtr = NULL; } tsdPtr->initialized = 0; } /* *---------------------------------------------------------------------- * * Tcl_PutsObjCmd -- * * This function is invoked to process the "puts" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Produces output on a channel. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_PutsObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to puts on. */ Tcl_Obj *string; /* String to write. */ Tcl_Obj *chanObjPtr = NULL; /* channel object. */ int newline; /* Add a newline at end? */ int result; /* Result of puts operation. */ int mode; /* Mode in which channel is opened. */ ThreadSpecificData *tsdPtr; switch (objc) { case 2: /* [puts $x] */ string = objv[1]; newline = 1; break; case 3: /* [puts -nonewline $x] or [puts $chan $x] */ if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) { newline = 0; } else { newline = 1; chanObjPtr = objv[1]; } string = objv[2]; break; case 4: /* [puts -nonewline $chan $x] or * [puts $chan $x nonewline] */ newline = 0; if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) { chanObjPtr = objv[2]; string = objv[3]; break; #if TCL_MAJOR_VERSION < 9 } else if (strcmp(TclGetString(objv[3]), "nonewline") == 0) { /* * The code below provides backwards compatibility with an old * form of the command that is no longer recommended or * documented. See also [Bug #3151675]. Will be removed in Tcl 9, * maybe even earlier. */ chanObjPtr = objv[1]; string = objv[2]; break; #endif } /* Fall through */ default: /* [puts] or * [puts some bad number of arguments...] */ Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? ?channelId? string"); return TCL_ERROR; } if (chanObjPtr == NULL) { tsdPtr = TCL_TSD_INIT(&dataKey); if (!tsdPtr->initialized) { tsdPtr->initialized = 1; TclNewLiteralStringObj(tsdPtr->stdoutObjPtr, "stdout"); Tcl_IncrRefCount(tsdPtr->stdoutObjPtr); Tcl_CreateThreadExitHandler(FinalizeIOCmdTSD, NULL); } chanObjPtr = tsdPtr->stdoutObjPtr; } if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) { return TCL_ERROR; } if (!(mode & TCL_WRITABLE)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel \"%s\" wasn't opened for writing", TclGetString(chanObjPtr))); return TCL_ERROR; } TclChannelPreserve(chan); result = Tcl_WriteObj(chan, string); if (result < 0) { goto error; } if (newline != 0) { result = Tcl_WriteChars(chan, "\n", 1); if (result < 0) { goto error; } } TclChannelRelease(chan); return TCL_OK; /* * TIP #219. * Capture error messages put by the driver into the bypass area and put * them into the regular interpreter result. Fall back to the regular * message if nothing was found in the bypass. */ error: if (!TclChanCaughtErrorBypass(interp, chan)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("error writing \"%s\": %s", TclGetString(chanObjPtr), Tcl_PosixError(interp))); } TclChannelRelease(chan); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_FlushObjCmd -- * * This function is called to process the Tcl "flush" command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * May cause output to appear on the specified channel. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_FlushObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *chanObjPtr; Tcl_Channel chan; /* The channel to flush on. */ int mode; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channelId"); return TCL_ERROR; } chanObjPtr = objv[1]; if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) { return TCL_ERROR; } if (!(mode & TCL_WRITABLE)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel \"%s\" wasn't opened for writing", TclGetString(chanObjPtr))); return TCL_ERROR; } TclChannelPreserve(chan); if (Tcl_Flush(chan) != TCL_OK) { /* * TIP #219. * Capture error messages put by the driver into the bypass area and * put them into the regular interpreter result. Fall back to the * regular message if nothing was found in the bypass. */ if (!TclChanCaughtErrorBypass(interp, chan)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error flushing \"%s\": %s", TclGetString(chanObjPtr), Tcl_PosixError(interp))); } TclChannelRelease(chan); return TCL_ERROR; } TclChannelRelease(chan); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetsObjCmd -- * * This function is called to process the Tcl "gets" command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * May consume input from channel. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_GetsObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to read from. */ int lineLen; /* Length of line just read. */ int mode; /* Mode in which channel is opened. */ Tcl_Obj *linePtr, *chanObjPtr; int code = TCL_OK; if ((objc != 2) && (objc != 3)) { Tcl_WrongNumArgs(interp, 1, objv, "channelId ?varName?"); return TCL_ERROR; } chanObjPtr = objv[1]; if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) { return TCL_ERROR; } if (!(mode & TCL_READABLE)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel \"%s\" wasn't opened for reading", TclGetString(chanObjPtr))); return TCL_ERROR; } TclChannelPreserve(chan); linePtr = Tcl_NewObj(); lineLen = Tcl_GetsObj(chan, linePtr); if (lineLen < 0) { if (!Tcl_Eof(chan) && !Tcl_InputBlocked(chan)) { Tcl_DecrRefCount(linePtr); /* * TIP #219. * Capture error messages put by the driver into the bypass area * and put them into the regular interpreter result. Fall back to * the regular message if nothing was found in the bypass. */ if (!TclChanCaughtErrorBypass(interp, chan)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error reading \"%s\": %s", TclGetString(chanObjPtr), Tcl_PosixError(interp))); } code = TCL_ERROR; goto done; } lineLen = -1; } if (objc == 3) { if (Tcl_ObjSetVar2(interp, objv[2], NULL, linePtr, TCL_LEAVE_ERR_MSG) == NULL) { code = TCL_ERROR; goto done; } Tcl_SetObjResult(interp, Tcl_NewIntObj(lineLen)); } else { Tcl_SetObjResult(interp, linePtr); } done: TclChannelRelease(chan); return code; } /* *---------------------------------------------------------------------- * * Tcl_ReadObjCmd -- * * This function is invoked to process the Tcl "read" command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * May consume input from channel. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ReadObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to read from. */ int newline, i; /* Discard newline at end? */ int toRead; /* How many bytes to read? */ int charactersRead; /* How many characters were read? */ int mode; /* Mode in which channel is opened. */ Tcl_Obj *resultPtr, *chanObjPtr; if ((objc != 2) && (objc != 3)) { Interp *iPtr; argerror: iPtr = (Interp *) interp; Tcl_WrongNumArgs(interp, 1, objv, "channelId ?numChars?"); /* * Do not append directly; that makes ensembles using this command as * a subcommand produce the wrong message. */ iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS; Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? channelId"); return TCL_ERROR; } i = 1; newline = 0; if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) { newline = 1; i++; } if (i == objc) { goto argerror; } chanObjPtr = objv[i]; if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) { return TCL_ERROR; } if (!(mode & TCL_READABLE)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel \"%s\" wasn't opened for reading", TclGetString(chanObjPtr))); return TCL_ERROR; } i++; /* Consumed channel name. */ /* * Compute how many bytes to read. */ toRead = -1; if (i < objc) { if ((TclGetIntFromObj(interp, objv[i], &toRead) != TCL_OK) || (toRead < 0)) { #if TCL_MAJOR_VERSION < 9 /* * The code below provides backwards compatibility with an old * form of the command that is no longer recommended or * documented. See also [Bug #3151675]. Will be removed in Tcl 9, * maybe even earlier. */ if (strcmp(TclGetString(objv[i]), "nonewline") != 0) { #endif Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected non-negative integer but got \"%s\"", TclGetString(objv[i]))); Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL); return TCL_ERROR; #if TCL_MAJOR_VERSION < 9 } newline = 1; #endif } } resultPtr = Tcl_NewObj(); Tcl_IncrRefCount(resultPtr); TclChannelPreserve(chan); charactersRead = Tcl_ReadChars(chan, resultPtr, toRead, 0); if (charactersRead < 0) { /* * TIP #219. * Capture error messages put by the driver into the bypass area and * put them into the regular interpreter result. Fall back to the * regular message if nothing was found in the bypass. */ if (!TclChanCaughtErrorBypass(interp, chan)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error reading \"%s\": %s", TclGetString(chanObjPtr), Tcl_PosixError(interp))); } TclChannelRelease(chan); Tcl_DecrRefCount(resultPtr); return TCL_ERROR; } /* * If requested, remove the last newline in the channel if at EOF. */ if ((charactersRead > 0) && (newline != 0)) { const char *result; int length; result = TclGetStringFromObj(resultPtr, &length); if (result[length - 1] == '\n') { Tcl_SetObjLength(resultPtr, length - 1); } } Tcl_SetObjResult(interp, resultPtr); TclChannelRelease(chan); Tcl_DecrRefCount(resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_SeekObjCmd -- * * This function is invoked to process the Tcl "seek" command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Moves the position of the access point on the specified channel. May * flush queued output. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_SeekObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to tell on. */ Tcl_WideInt offset; /* Where to seek? */ int mode; /* How to seek? */ Tcl_WideInt result; /* Of calling Tcl_Seek. */ int optionIndex; static const char *const originOptions[] = { "start", "current", "end", NULL }; static const int modeArray[] = {SEEK_SET, SEEK_CUR, SEEK_END}; if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 1, objv, "channelId offset ?origin?"); return TCL_ERROR; } if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetWideIntFromObj(interp, objv[2], &offset) != TCL_OK) { return TCL_ERROR; } mode = SEEK_SET; if (objc == 4) { if (Tcl_GetIndexFromObj(interp, objv[3], originOptions, "origin", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } mode = modeArray[optionIndex]; } TclChannelPreserve(chan); result = Tcl_Seek(chan, offset, mode); if (result == Tcl_LongAsWide(-1)) { /* * TIP #219. * Capture error messages put by the driver into the bypass area and * put them into the regular interpreter result. Fall back to the * regular message if nothing was found in the bypass. */ if (!TclChanCaughtErrorBypass(interp, chan)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error during seek on \"%s\": %s", TclGetString(objv[1]), Tcl_PosixError(interp))); } TclChannelRelease(chan); return TCL_ERROR; } TclChannelRelease(chan); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_TellObjCmd -- * * This function is invoked to process the Tcl "tell" command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_TellObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to tell on. */ Tcl_WideInt newLoc; int code; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channelId"); return TCL_ERROR; } /* * Try to find a channel with the right name and permissions in the IO * channel table of this interpreter. */ if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) { return TCL_ERROR; } TclChannelPreserve(chan); newLoc = Tcl_Tell(chan); /* * TIP #219. * Capture error messages put by the driver into the bypass area and put * them into the regular interpreter result. */ code = TclChanCaughtErrorBypass(interp, chan); TclChannelRelease(chan); if (code) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj(newLoc)); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_CloseObjCmd -- * * This function is invoked to process the Tcl "close" command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * May discard queued input; may flush queued output. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_CloseObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; /* The channel to close. */ static const char *const dirOptions[] = { "read", "write", NULL }; static const int dirArray[] = {TCL_CLOSE_READ, TCL_CLOSE_WRITE}; if ((objc != 2) && (objc != 3)) { Tcl_WrongNumArgs(interp, 1, objv, "channelId ?direction?"); return TCL_ERROR; } if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) { return TCL_ERROR; } if (objc == 3) { int index, dir; /* * Get direction requested to close, and check syntax. */ if (Tcl_GetIndexFromObj(interp, objv[2], dirOptions, "direction", 0, &index) != TCL_OK) { return TCL_ERROR; } dir = dirArray[index]; /* * Check direction against channel mode. It is an error if we try to * close a direction not supported by the channel (already closed, or * never opened for that direction). */ if (!(dir & Tcl_GetChannelMode(chan))) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "Half-close of %s-side not possible, side not opened" " or already closed", dirOptions[index])); return TCL_ERROR; } /* * Special handling is needed if and only if the channel mode supports * more than the direction to close. Because if the close the last * direction suppported we can and will go through the regular * process. */ if ((Tcl_GetChannelMode(chan) & (TCL_CLOSE_READ|TCL_CLOSE_WRITE)) != dir) { return Tcl_CloseEx(interp, chan, dir); } } if (Tcl_UnregisterChannel(interp, chan) != TCL_OK) { /* * If there is an error message and it ends with a newline, remove the * newline. This is done for command pipeline channels where the error * output from the subprocesses is stored in interp's result. * * NOTE: This is likely to not have any effect on regular error * messages produced by drivers during the closing of a channel, * because the Tcl convention is that such error messages do not have * a terminating newline. */ Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); const char *string; int len; if (Tcl_IsShared(resultPtr)) { resultPtr = Tcl_DuplicateObj(resultPtr); Tcl_SetObjResult(interp, resultPtr); } string = TclGetStringFromObj(resultPtr, &len); if ((len > 0) && (string[len - 1] == '\n')) { Tcl_SetObjLength(resultPtr, len - 1); } return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_FconfigureObjCmd -- * * This function is invoked to process the Tcl "fconfigure" command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * May modify the behavior of an IO channel. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_FconfigureObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *optionName, *valueName; Tcl_Channel chan; /* The channel to set a mode on. */ int i; /* Iterate over arg-value pairs. */ if ((objc < 2) || (((objc % 2) == 1) && (objc != 3))) { Tcl_WrongNumArgs(interp, 1, objv, "channelId ?-option value ...?"); return TCL_ERROR; } if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) { return TCL_ERROR; } if (objc == 2) { Tcl_DString ds; /* DString to hold result of calling * Tcl_GetChannelOption. */ Tcl_DStringInit(&ds); if (Tcl_GetChannelOption(interp, chan, NULL, &ds) != TCL_OK) { Tcl_DStringFree(&ds); return TCL_ERROR; } Tcl_DStringResult(interp, &ds); return TCL_OK; } else if (objc == 3) { Tcl_DString ds; /* DString to hold result of calling * Tcl_GetChannelOption. */ Tcl_DStringInit(&ds); optionName = TclGetString(objv[2]); if (Tcl_GetChannelOption(interp, chan, optionName, &ds) != TCL_OK) { Tcl_DStringFree(&ds); return TCL_ERROR; } Tcl_DStringResult(interp, &ds); return TCL_OK; } for (i = 3; i < objc; i += 2) { optionName = TclGetString(objv[i-1]); valueName = TclGetString(objv[i]); if (Tcl_SetChannelOption(interp, chan, optionName, valueName) != TCL_OK) { return TCL_ERROR; } } return TCL_OK; } /* *--------------------------------------------------------------------------- * * Tcl_EofObjCmd -- * * This function is invoked to process the Tcl "eof" command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Sets interp's result to boolean true or false depending on whether the * specified channel has an EOF condition. * *--------------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_EofObjCmd( ClientData unused, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channelId"); return TCL_ERROR; } if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_Eof(chan))); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ExecObjCmd -- * * This function is invoked to process the "exec" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ExecObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *resultPtr; const char **argv; /* An array for the string arguments. Stored * on the _Tcl_ stack. */ const char *string; Tcl_Channel chan; int argc, background, i, index, keepNewline, result, skip, length; int ignoreStderr; static const char *const options[] = { "-ignorestderr", "-keepnewline", "--", NULL }; enum options { EXEC_IGNORESTDERR, EXEC_KEEPNEWLINE, EXEC_LAST }; /* * Check for any leading option arguments. */ keepNewline = 0; ignoreStderr = 0; for (skip = 1; skip < objc; skip++) { string = TclGetString(objv[skip]); if (string[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[skip], options, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } if (index == EXEC_KEEPNEWLINE) { keepNewline = 1; } else if (index == EXEC_IGNORESTDERR) { ignoreStderr = 1; } else { skip++; break; } } if (objc <= skip) { Tcl_WrongNumArgs(interp, 1, objv, "?-option ...? arg ?arg ...?"); return TCL_ERROR; } /* * See if the command is to be run in background. */ background = 0; string = TclGetString(objv[objc - 1]); if ((string[0] == '&') && (string[1] == '\0')) { objc--; background = 1; } /* * Create the string argument array "argv". Make sure argv is large enough * to hold the argc arguments plus 1 extra for the zero end-of-argv word. */ argc = objc - skip; argv = TclStackAlloc(interp, (unsigned)(argc + 1) * sizeof(char *)); /* * Copy the string conversions of each (post option) object into the * argument vector. */ for (i = 0; i < argc; i++) { argv[i] = TclGetString(objv[i + skip]); } argv[argc] = NULL; chan = Tcl_OpenCommandChannel(interp, argc, argv, (background ? 0 : ignoreStderr ? TCL_STDOUT : TCL_STDOUT|TCL_STDERR)); /* * Free the argv array. */ TclStackFree(interp, (void *) argv); if (chan == NULL) { return TCL_ERROR; } if (background) { /* * Store the list of PIDs from the pipeline in interp's result and * detach the PIDs (instead of waiting for them). */ TclGetAndDetachPids(interp, chan); if (Tcl_Close(interp, chan) != TCL_OK) { return TCL_ERROR; } return TCL_OK; } resultPtr = Tcl_NewObj(); if (Tcl_GetChannelHandle(chan, TCL_READABLE, NULL) == TCL_OK) { if (Tcl_ReadChars(chan, resultPtr, -1, 0) < 0) { /* * TIP #219. * Capture error messages put by the driver into the bypass area * and put them into the regular interpreter result. Fall back to * the regular message if nothing was found in the bypass. */ if (!TclChanCaughtErrorBypass(interp, chan)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error reading output from command: %s", Tcl_PosixError(interp))); Tcl_DecrRefCount(resultPtr); } return TCL_ERROR; } } /* * If the process produced anything on stderr, it will have been returned * in the interpreter result. It needs to be appended to the result * string. */ result = Tcl_Close(interp, chan); Tcl_AppendObjToObj(resultPtr, Tcl_GetObjResult(interp)); /* * If the last character of the result is a newline, then remove the * newline character. */ if (keepNewline == 0) { string = TclGetStringFromObj(resultPtr, &length); if ((length > 0) && (string[length - 1] == '\n')) { Tcl_SetObjLength(resultPtr, length - 1); } } Tcl_SetObjResult(interp, resultPtr); return result; } /* *--------------------------------------------------------------------------- * * Tcl_FblockedObjCmd -- * * This function is invoked to process the Tcl "fblocked" command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Sets interp's result to boolean true or false depending on whether the * preceeding input operation on the channel would have blocked. * *--------------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_FblockedObjCmd( ClientData unused, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; int mode; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channelId"); return TCL_ERROR; } if (TclGetChannelFromObj(interp, objv[1], &chan, &mode, 0) != TCL_OK) { return TCL_ERROR; } if (!(mode & TCL_READABLE)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel \"%s\" wasn't opened for reading", TclGetString(objv[1]))); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_InputBlocked(chan))); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_OpenObjCmd -- * * This function is invoked to process the "open" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_OpenObjCmd( ClientData notUsed, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int pipeline, prot; const char *modeString, *what; Tcl_Channel chan; if ((objc < 2) || (objc > 4)) { Tcl_WrongNumArgs(interp, 1, objv, "fileName ?access? ?permissions?"); return TCL_ERROR; } prot = 0666; if (objc == 2) { modeString = "r"; } else { modeString = TclGetString(objv[2]); if (objc == 4) { const char *permString = TclGetString(objv[3]); int code = TCL_ERROR; int scanned = TclParseAllWhiteSpace(permString, -1); /* * Support legacy octal numbers. */ if ((permString[scanned] == '0') && (permString[scanned+1] >= '0') && (permString[scanned+1] <= '7')) { Tcl_Obj *permObj; TclNewLiteralStringObj(permObj, "0o"); Tcl_AppendToObj(permObj, permString+scanned+1, -1); code = TclGetIntFromObj(NULL, permObj, &prot); Tcl_DecrRefCount(permObj); } if ((code == TCL_ERROR) && TclGetIntFromObj(interp, objv[3], &prot) != TCL_OK) { return TCL_ERROR; } } } pipeline = 0; what = TclGetString(objv[1]); if (what[0] == '|') { pipeline = 1; } /* * Open the file or create a process pipeline. */ if (!pipeline) { chan = Tcl_FSOpenFileChannel(interp, objv[1], modeString, prot); } else { int mode, seekFlag, cmdObjc, binary; const char **cmdArgv; if (Tcl_SplitList(interp, what+1, &cmdObjc, &cmdArgv) != TCL_OK) { return TCL_ERROR; } mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary); if (mode == -1) { chan = NULL; } else { int flags = TCL_STDERR | TCL_ENFORCE_MODE; switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) { case O_RDONLY: flags |= TCL_STDOUT; break; case O_WRONLY: flags |= TCL_STDIN; break; case O_RDWR: flags |= (TCL_STDIN | TCL_STDOUT); break; default: Tcl_Panic("Tcl_OpenCmd: invalid mode value"); break; } chan = Tcl_OpenCommandChannel(interp, cmdObjc, cmdArgv, flags); if (binary && chan) { Tcl_SetChannelOption(interp, chan, "-translation", "binary"); } } ckfree(cmdArgv); } if (chan == NULL) { return TCL_ERROR; } Tcl_RegisterChannel(interp, chan); Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetChannelName(chan), -1)); return TCL_OK; } /* *---------------------------------------------------------------------- * * TcpAcceptCallbacksDeleteProc -- * * Assocdata cleanup routine called when an interpreter is being deleted * to set the interp field of all the accept callback records registered * with the interpreter to NULL. This will prevent the interpreter from * being used in the future to eval accept scripts. * * Results: * None. * * Side effects: * Deallocates memory and sets the interp field of all the accept * callback records to NULL to prevent this interpreter from being used * subsequently to eval accept scripts. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static void TcpAcceptCallbacksDeleteProc( ClientData clientData, /* Data which was passed when the assocdata * was registered. */ Tcl_Interp *interp) /* Interpreter being deleted - not used. */ { Tcl_HashTable *hTblPtr = clientData; Tcl_HashEntry *hPtr; Tcl_HashSearch hSearch; for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { AcceptCallback *acceptCallbackPtr = Tcl_GetHashValue(hPtr); acceptCallbackPtr->interp = NULL; } Tcl_DeleteHashTable(hTblPtr); ckfree(hTblPtr); } /* *---------------------------------------------------------------------- * * RegisterTcpServerInterpCleanup -- * * Registers an accept callback record to have its interp field set to * NULL when the interpreter is deleted. * * Results: * None. * * Side effects: * When, in the future, the interpreter is deleted, the interp field of * the accept callback data structure will be set to NULL. This will * prevent attempts to eval the accept script in a deleted interpreter. * *---------------------------------------------------------------------- */ static void RegisterTcpServerInterpCleanup( Tcl_Interp *interp, /* Interpreter for which we want to be * informed of deletion. */ AcceptCallback *acceptCallbackPtr) /* The accept callback record whose interp * field we want set to NULL when the * interpreter is deleted. */ { Tcl_HashTable *hTblPtr; /* Hash table for accept callback records to * smash when the interpreter will be * deleted. */ Tcl_HashEntry *hPtr; /* Entry for this record. */ int isNew; /* Is the entry new? */ hTblPtr = Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL); if (hTblPtr == NULL) { hTblPtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(hTblPtr, TCL_ONE_WORD_KEYS); Tcl_SetAssocData(interp, "tclTCPAcceptCallbacks", TcpAcceptCallbacksDeleteProc, hTblPtr); } hPtr = Tcl_CreateHashEntry(hTblPtr, acceptCallbackPtr, &isNew); if (!isNew) { Tcl_Panic("RegisterTcpServerCleanup: damaged accept record table"); } Tcl_SetHashValue(hPtr, acceptCallbackPtr); } /* *---------------------------------------------------------------------- * * UnregisterTcpServerInterpCleanupProc -- * * Unregister a previously registered accept callback record. The interp * field of this record will no longer be set to NULL in the future when * the interpreter is deleted. * * Results: * None. * * Side effects: * Prevents the interp field of the accept callback record from being set * to NULL in the future when the interpreter is deleted. * *---------------------------------------------------------------------- */ static void UnregisterTcpServerInterpCleanupProc( Tcl_Interp *interp, /* Interpreter in which the accept callback * record was registered. */ AcceptCallback *acceptCallbackPtr) /* The record for which to delete the * registration. */ { Tcl_HashTable *hTblPtr; Tcl_HashEntry *hPtr; hTblPtr = Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL); if (hTblPtr == NULL) { return; } hPtr = Tcl_FindHashEntry(hTblPtr, (char *) acceptCallbackPtr); if (hPtr != NULL) { Tcl_DeleteHashEntry(hPtr); } } /* *---------------------------------------------------------------------- * * AcceptCallbackProc -- * * This callback is invoked by the TCP channel driver when it accepts a * new connection from a client on a server socket. * * Results: * None. * * Side effects: * Whatever the script does. * *---------------------------------------------------------------------- */ static void AcceptCallbackProc( ClientData callbackData, /* The data stored when the callback was * created in the call to * Tcl_OpenTcpServer. */ Tcl_Channel chan, /* Channel for the newly accepted * connection. */ char *address, /* Address of client that was accepted. */ int port) /* Port of client that was accepted. */ { AcceptCallback *acceptCallbackPtr = callbackData; /* * Check if the callback is still valid; the interpreter may have gone * away, this is signalled by setting the interp field of the callback * data to NULL. */ if (acceptCallbackPtr->interp != NULL) { char portBuf[TCL_INTEGER_SPACE]; char *script = acceptCallbackPtr->script; Tcl_Interp *interp = acceptCallbackPtr->interp; int result; Tcl_Preserve(script); Tcl_Preserve(interp); TclFormatInt(portBuf, port); Tcl_RegisterChannel(interp, chan); /* * Artificially bump the refcount to protect the channel from being * deleted while the script is being evaluated. */ Tcl_RegisterChannel(NULL, chan); result = Tcl_VarEval(interp, script, " ", Tcl_GetChannelName(chan), " ", address, " ", portBuf, NULL); if (result != TCL_OK) { Tcl_BackgroundException(interp, result); Tcl_UnregisterChannel(interp, chan); } /* * Decrement the artificially bumped refcount. After this it is not * safe anymore to use "chan", because it may now be deleted. */ Tcl_UnregisterChannel(NULL, chan); Tcl_Release(interp); Tcl_Release(script); } else { /* * The interpreter has been deleted, so there is no useful way to use * the client socket - just close it. */ Tcl_Close(NULL, chan); } } /* *---------------------------------------------------------------------- * * TcpServerCloseProc -- * * This callback is called when the TCP server channel for which it was * registered is being closed. It informs the interpreter in which the * accept script is evaluated (if that interpreter still exists) that * this channel no longer needs to be informed if the interpreter is * deleted. * * Results: * None. * * Side effects: * In the future, if the interpreter is deleted this channel will no * longer be informed. * *---------------------------------------------------------------------- */ static void TcpServerCloseProc( ClientData callbackData) /* The data passed in the call to * Tcl_CreateCloseHandler. */ { AcceptCallback *acceptCallbackPtr = callbackData; /* The actual data. */ if (acceptCallbackPtr->interp != NULL) { UnregisterTcpServerInterpCleanupProc(acceptCallbackPtr->interp, acceptCallbackPtr); } Tcl_EventuallyFree(acceptCallbackPtr->script, TCL_DYNAMIC); ckfree(acceptCallbackPtr); } /* *---------------------------------------------------------------------- * * Tcl_SocketObjCmd -- * * This function is invoked to process the "socket" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Creates a socket based channel. * *---------------------------------------------------------------------- */ int Tcl_SocketObjCmd( ClientData notUsed, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const socketOptions[] = { "-async", "-myaddr", "-myport", "-server", NULL }; enum socketOptions { SKT_ASYNC, SKT_MYADDR, SKT_MYPORT, SKT_SERVER }; int optionIndex, a, server = 0, port, myport = 0, async = 0; const char *host, *script = NULL, *myaddr = NULL; Tcl_Channel chan; if (TclpHasSockets(interp) != TCL_OK) { return TCL_ERROR; } for (a = 1; a < objc; a++) { const char *arg = Tcl_GetString(objv[a]); if (arg[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[a], socketOptions, "option", TCL_EXACT, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum socketOptions) optionIndex) { case SKT_ASYNC: if (server == 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot set -async option for server sockets", -1)); return TCL_ERROR; } async = 1; break; case SKT_MYADDR: a++; if (a >= objc) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "no argument given for -myaddr option", -1)); return TCL_ERROR; } myaddr = TclGetString(objv[a]); break; case SKT_MYPORT: { const char *myPortName; a++; if (a >= objc) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "no argument given for -myport option", -1)); return TCL_ERROR; } myPortName = TclGetString(objv[a]); if (TclSockGetPort(interp, myPortName, "tcp", &myport) != TCL_OK) { return TCL_ERROR; } break; } case SKT_SERVER: if (async == 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot set -async option for server sockets", -1)); return TCL_ERROR; } server = 1; a++; if (a >= objc) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "no argument given for -server option", -1)); return TCL_ERROR; } script = TclGetString(objv[a]); break; default: Tcl_Panic("Tcl_SocketObjCmd: bad option index to SocketOptions"); } } if (server) { host = myaddr; /* NULL implies INADDR_ANY */ if (myport != 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "option -myport is not valid for servers", -1)); return TCL_ERROR; } } else if (a < objc) { host = TclGetString(objv[a]); a++; } else { Interp *iPtr; wrongNumArgs: iPtr = (Interp *) interp; Tcl_WrongNumArgs(interp, 1, objv, "?-myaddr addr? ?-myport myport? ?-async? host port"); iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS; Tcl_WrongNumArgs(interp, 1, objv, "-server command ?-myaddr addr? port"); return TCL_ERROR; } if (a == objc-1) { if (TclSockGetPort(interp, TclGetString(objv[a]), "tcp", &port) != TCL_OK) { return TCL_ERROR; } } else { goto wrongNumArgs; } if (server) { AcceptCallback *acceptCallbackPtr = ckalloc(sizeof(AcceptCallback)); unsigned len = strlen(script) + 1; char *copyScript = ckalloc(len); memcpy(copyScript, script, len); acceptCallbackPtr->script = copyScript; acceptCallbackPtr->interp = interp; chan = Tcl_OpenTcpServer(interp, port, host, AcceptCallbackProc, acceptCallbackPtr); if (chan == NULL) { ckfree(copyScript); ckfree(acceptCallbackPtr); return TCL_ERROR; } /* * Register with the interpreter to let us know when the interpreter * is deleted (by having the callback set the interp field of the * acceptCallbackPtr's structure to NULL). This is to avoid trying to * eval the script in a deleted interpreter. */ RegisterTcpServerInterpCleanup(interp, acceptCallbackPtr); /* * Register a close callback. This callback will inform the * interpreter (if it still exists) that this channel does not need to * be informed when the interpreter is deleted. */ Tcl_CreateCloseHandler(chan, TcpServerCloseProc, acceptCallbackPtr); } else { chan = Tcl_OpenTcpClient(interp, port, host, myaddr, myport, async); if (chan == NULL) { return TCL_ERROR; } } Tcl_RegisterChannel(interp, chan); Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetChannelName(chan), -1)); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_FcopyObjCmd -- * * This function is invoked to process the "fcopy" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Moves data between two channels and possibly sets up a background copy * handler. * *---------------------------------------------------------------------- */ int Tcl_FcopyObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel inChan, outChan; int mode, i, index; Tcl_WideInt toRead; Tcl_Obj *cmdPtr; static const char *const switches[] = { "-size", "-command", NULL }; enum { FcopySize, FcopyCommand }; if ((objc < 3) || (objc > 7) || (objc == 4) || (objc == 6)) { Tcl_WrongNumArgs(interp, 1, objv, "input output ?-size size? ?-command callback?"); return TCL_ERROR; } /* * Parse the channel arguments and verify that they are readable or * writable, as appropriate. */ if (TclGetChannelFromObj(interp, objv[1], &inChan, &mode, 0) != TCL_OK) { return TCL_ERROR; } if (!(mode & TCL_READABLE)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel \"%s\" wasn't opened for reading", TclGetString(objv[1]))); return TCL_ERROR; } if (TclGetChannelFromObj(interp, objv[2], &outChan, &mode, 0) != TCL_OK) { return TCL_ERROR; } if (!(mode & TCL_WRITABLE)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel \"%s\" wasn't opened for writing", TclGetString(objv[2]))); return TCL_ERROR; } toRead = -1; cmdPtr = NULL; for (i = 3; i < objc; i += 2) { if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case FcopySize: if (Tcl_GetWideIntFromObj(interp, objv[i+1], &toRead) != TCL_OK) { return TCL_ERROR; } if (toRead < 0) { /* * Handle all negative sizes like -1, meaning 'copy all'. By * resetting toRead we avoid changes in the core copying * functions (which explicitly check for -1 and crash on any * other negative value). */ toRead = -1; } break; case FcopyCommand: cmdPtr = objv[i+1]; break; } } return TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr); } /* *--------------------------------------------------------------------------- * * ChanPendingObjCmd -- * * This function is invoked to process the Tcl "chan pending" command * (TIP #287). See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Sets interp's result to the number of bytes of buffered input or * output (depending on whether the first argument is "input" or * "output"), or -1 if the channel wasn't opened for that mode. * *--------------------------------------------------------------------------- */ /* ARGSUSED */ static int ChanPendingObjCmd( ClientData unused, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; int index, mode; static const char *const options[] = {"input", "output", NULL}; enum options {PENDING_INPUT, PENDING_OUTPUT}; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "mode channelId"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "mode", 0, &index) != TCL_OK) { return TCL_ERROR; } if (TclGetChannelFromObj(interp, objv[2], &chan, &mode, 0) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { case PENDING_INPUT: if (!(mode & TCL_READABLE)) { Tcl_SetObjResult(interp, Tcl_NewIntObj(-1)); } else { Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_InputBuffered(chan))); } break; case PENDING_OUTPUT: if (!(mode & TCL_WRITABLE)) { Tcl_SetObjResult(interp, Tcl_NewIntObj(-1)); } else { Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_OutputBuffered(chan))); } break; } return TCL_OK; } /* *---------------------------------------------------------------------- * * ChanTruncateObjCmd -- * * This function is invoked to process the "chan truncate" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Truncates a channel (or rather a file underlying a channel). * *---------------------------------------------------------------------- */ static int ChanTruncateObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel chan; Tcl_WideInt length; if ((objc < 2) || (objc > 3)) { Tcl_WrongNumArgs(interp, 1, objv, "channelId ?length?"); return TCL_ERROR; } if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) { return TCL_ERROR; } if (objc == 3) { /* * User is supplying an explicit length. */ if (Tcl_GetWideIntFromObj(interp, objv[2], &length) != TCL_OK) { return TCL_ERROR; } if (length < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot truncate to negative length of file", -1)); return TCL_ERROR; } } else { /* * User wants to truncate to the current file position. */ length = Tcl_Tell(chan); if (length == Tcl_WideAsLong(-1)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not determine current location in \"%s\": %s", TclGetString(objv[1]), Tcl_PosixError(interp))); return TCL_ERROR; } } if (Tcl_TruncateChannel(chan, length) != TCL_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error during truncate on \"%s\": %s", TclGetString(objv[1]), Tcl_PosixError(interp))); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * ChanPipeObjCmd -- * * This function is invoked to process the "chan pipe" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Creates a pair of Tcl channels wrapping both ends of a new * anonymous pipe. * *---------------------------------------------------------------------- */ static int ChanPipeObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Channel rchan, wchan; const char *channelNames[2]; Tcl_Obj *resultPtr; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, ""); return TCL_ERROR; } if (Tcl_CreatePipe(interp, &rchan, &wchan, 0) != TCL_OK) { return TCL_ERROR; } channelNames[0] = Tcl_GetChannelName(rchan); channelNames[1] = Tcl_GetChannelName(wchan); resultPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(channelNames[0], -1)); Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(channelNames[1], -1)); Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclChannelNamesCmd -- * * This function is invoked to process the "chan names" and "file * channels" Tcl commands. See the user documentation for details on * what they do. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclChannelNamesCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc < 1 || objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?pattern?"); return TCL_ERROR; } return Tcl_GetChannelNamesEx(interp, ((objc == 1) ? NULL : TclGetString(objv[1]))); } /* *---------------------------------------------------------------------- * * TclInitChanCmd -- * * This function is invoked to create the "chan" Tcl command. See the * user documentation for details on what it does. * * Results: * A Tcl command handle. * * Side effects: * None (since nothing is byte-compiled). * *---------------------------------------------------------------------- */ Tcl_Command TclInitChanCmd( Tcl_Interp *interp) { /* * Most commands are plugged directly together, but some are done via * alias-like rewriting; [chan configure] is this way for security reasons * (want overwriting of [fconfigure] to control that nicely), and [chan * names] because the functionality isn't available as a separate command * function at the moment. */ static const EnsembleImplMap initMap[] = { {"blocked", Tcl_FblockedObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"close", Tcl_CloseObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"copy", Tcl_FcopyObjCmd, NULL, NULL, NULL, 0}, {"create", TclChanCreateObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #219 */ {"eof", Tcl_EofObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"event", Tcl_FileEventObjCmd, TclCompileBasic2Or3ArgCmd, NULL, NULL, 0}, {"flush", Tcl_FlushObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"gets", Tcl_GetsObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"names", TclChannelNamesCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"pending", ChanPendingObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #287 */ {"pipe", ChanPipeObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, /* TIP #304 */ {"pop", TclChanPopObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, /* TIP #230 */ {"postevent", TclChanPostEventObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #219 */ {"push", TclChanPushObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #230 */ {"puts", Tcl_PutsObjCmd, NULL, NULL, NULL, 0}, {"read", Tcl_ReadObjCmd, NULL, NULL, NULL, 0}, {"seek", Tcl_SeekObjCmd, TclCompileBasic2Or3ArgCmd, NULL, NULL, 0}, {"tell", Tcl_TellObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"truncate", ChanTruncateObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, /* TIP #208 */ {NULL, NULL, NULL, NULL, NULL, 0} }; static const char *const extras[] = { "configure", "::fconfigure", NULL }; Tcl_Command ensemble; Tcl_Obj *mapObj; int i; ensemble = TclMakeEnsemble(interp, "chan", initMap); Tcl_GetEnsembleMappingDict(NULL, ensemble, &mapObj); for (i=0 ; extras[i] ; i+=2) { /* * Can assume that reference counts are all incremented. */ Tcl_DictObjPut(NULL, mapObj, Tcl_NewStringObj(extras[i], -1), Tcl_NewStringObj(extras[i+1], -1)); } Tcl_SetEnsembleMappingDict(interp, ensemble, mapObj); return ensemble; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclDictObj.c0000644000175000017500000027263612663660065015410 0ustar sergeisergei/* * tclDictObj.c -- * * This file contains functions that implement the Tcl dict object type * and its accessor command. * * Copyright (c) 2002-2010 by Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tommath.h" /* * Forward declaration. */ struct Dict; /* * Prototypes for functions defined later in this file: */ static void DeleteDict(struct Dict *dict); static int DictAppendCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictCreateCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictExistsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictFilterCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictGetCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictIncrCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictInfoCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictKeysCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictLappendCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictMergeCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictRemoveCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictReplaceCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictSetCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictSizeCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictUnsetCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictUpdateCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictValuesCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictWithCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static void DupDictInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static void FreeDictInternalRep(Tcl_Obj *dictPtr); static void InvalidateDictChain(Tcl_Obj *dictObj); static int SetDictFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void UpdateStringOfDict(Tcl_Obj *dictPtr); static Tcl_HashEntry * AllocChainEntry(Tcl_HashTable *tablePtr,void *keyPtr); static inline void InitChainTable(struct Dict *dict); static inline void DeleteChainTable(struct Dict *dict); static inline Tcl_HashEntry *CreateChainEntry(struct Dict *dict, Tcl_Obj *keyPtr, int *newPtr); static inline int DeleteChainEntry(struct Dict *dict, Tcl_Obj *keyPtr); static int FinalizeDictUpdate(ClientData data[], Tcl_Interp *interp, int result); static int FinalizeDictWith(ClientData data[], Tcl_Interp *interp, int result); static int DictForNRCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictMapNRCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int DictForLoopCallback(ClientData data[], Tcl_Interp *interp, int result); static int DictMapLoopCallback(ClientData data[], Tcl_Interp *interp, int result); /* * Table of dict subcommand names and implementations. */ static const EnsembleImplMap implementationMap[] = { {"append", DictAppendCmd, TclCompileDictAppendCmd, NULL, NULL, 0 }, {"create", DictCreateCmd, TclCompileDictCreateCmd, NULL, NULL, 0 }, {"exists", DictExistsCmd, TclCompileDictExistsCmd, NULL, NULL, 0 }, {"filter", DictFilterCmd, NULL, NULL, NULL, 0 }, {"for", NULL, TclCompileDictForCmd, DictForNRCmd, NULL, 0 }, {"get", DictGetCmd, TclCompileDictGetCmd, NULL, NULL, 0 }, {"incr", DictIncrCmd, TclCompileDictIncrCmd, NULL, NULL, 0 }, {"info", DictInfoCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 }, {"keys", DictKeysCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, {"lappend", DictLappendCmd, TclCompileDictLappendCmd, NULL, NULL, 0 }, {"map", NULL, TclCompileDictMapCmd, DictMapNRCmd, NULL, 0 }, {"merge", DictMergeCmd, TclCompileDictMergeCmd, NULL, NULL, 0 }, {"remove", DictRemoveCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0 }, {"replace", DictReplaceCmd, NULL, NULL, NULL, 0 }, {"set", DictSetCmd, TclCompileDictSetCmd, NULL, NULL, 0 }, {"size", DictSizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 }, {"unset", DictUnsetCmd, TclCompileDictUnsetCmd, NULL, NULL, 0 }, {"update", DictUpdateCmd, TclCompileDictUpdateCmd, NULL, NULL, 0 }, {"values", DictValuesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, {"with", DictWithCmd, TclCompileDictWithCmd, NULL, NULL, 0 }, {NULL, NULL, NULL, NULL, NULL, 0} }; /* * Internal representation of the entries in the hash table that backs a * dictionary. */ typedef struct ChainEntry { Tcl_HashEntry entry; struct ChainEntry *prevPtr; struct ChainEntry *nextPtr; } ChainEntry; /* * Internal representation of a dictionary. * * The internal representation of a dictionary object is a hash table (with * Tcl_Objs for both keys and values), a reference count and epoch number for * detecting concurrent modifications of the dictionary, and a pointer to the * parent object (used when invalidating string reps of pathed dictionary * trees) which is NULL in normal use. The fact that hash tables know (with * appropriate initialisation) already about objects makes key management /so/ * much easier! * * Reference counts are used to enable safe iteration across hashes while * allowing the type of the containing object to be modified. */ typedef struct Dict { Tcl_HashTable table; /* Object hash table to store mapping in. */ ChainEntry *entryChainHead; /* Linked list of all entries in the * dictionary. Used for doing traversal of the * entries in the order that they are * created. */ ChainEntry *entryChainTail; /* Other end of linked list of all entries in * the dictionary. Used for doing traversal of * the entries in the order that they are * created. */ int epoch; /* Epoch counter */ int refcount; /* Reference counter (see above) */ Tcl_Obj *chain; /* Linked list used for invalidating the * string representations of updated nested * dictionaries. */ } Dict; /* * Accessor macro for converting between a Tcl_Obj* and a Dict. Note that this * must be assignable as well as readable. */ #define DICT(dictObj) (*((Dict **)&(dictObj)->internalRep.twoPtrValue.ptr1)) /* * The structure below defines the dictionary object type by means of * functions that can be invoked by generic object code. */ const Tcl_ObjType tclDictType = { "dict", FreeDictInternalRep, /* freeIntRepProc */ DupDictInternalRep, /* dupIntRepProc */ UpdateStringOfDict, /* updateStringProc */ SetDictFromAny /* setFromAnyProc */ }; /* * The type of the specially adapted version of the Tcl_Obj*-containing hash * table defined in the tclObj.c code. This version differs in that it * allocates a bit more space in each hash entry in order to hold the pointers * used to keep the hash entries in a linked list. * * Note that this type of hash table is *only* suitable for direct use in * *this* file. Everything else should use the dict iterator API. */ static const Tcl_HashKeyType chainHashType = { TCL_HASH_KEY_TYPE_VERSION, 0, TclHashObjKey, TclCompareObjKeys, AllocChainEntry, TclFreeObjEntry }; /* * Structure used in implementation of 'dict map' to hold the state that gets * passed between parts of the implementation. */ typedef struct { Tcl_Obj *keyVarObj; /* The name of the variable that will have * keys assigned to it. */ Tcl_Obj *valueVarObj; /* The name of the variable that will have * values assigned to it. */ Tcl_DictSearch search; /* The dictionary search structure. */ Tcl_Obj *scriptObj; /* The script to evaluate each time through * the loop. */ Tcl_Obj *accumulatorObj; /* The dictionary used to accumulate the * results. */ } DictMapStorage; /***** START OF FUNCTIONS IMPLEMENTING DICT CORE API *****/ /* *---------------------------------------------------------------------- * * AllocChainEntry -- * * Allocate space for a Tcl_HashEntry containing the Tcl_Obj * key, and * which has a bit of extra space afterwards for storing pointers to the * rest of the chain of entries (the extra pointers are left NULL). * * Results: * The return value is a pointer to the created entry. * * Side effects: * Increments the reference count on the object. * *---------------------------------------------------------------------- */ static Tcl_HashEntry * AllocChainEntry( Tcl_HashTable *tablePtr, void *keyPtr) { Tcl_Obj *objPtr = keyPtr; ChainEntry *cPtr; cPtr = ckalloc(sizeof(ChainEntry)); cPtr->entry.key.objPtr = objPtr; Tcl_IncrRefCount(objPtr); cPtr->entry.clientData = NULL; cPtr->prevPtr = cPtr->nextPtr = NULL; return &cPtr->entry; } /* * Helper functions that disguise most of the details relating to how the * linked list of hash entries is managed. In particular, these manage the * creation of the table and initializing of the chain, the deletion of the * table and chain, the adding of an entry to the chain, and the removal of an * entry from the chain. */ static inline void InitChainTable( Dict *dict) { Tcl_InitCustomHashTable(&dict->table, TCL_CUSTOM_PTR_KEYS, &chainHashType); dict->entryChainHead = dict->entryChainTail = NULL; } static inline void DeleteChainTable( Dict *dict) { ChainEntry *cPtr; for (cPtr=dict->entryChainHead ; cPtr!=NULL ; cPtr=cPtr->nextPtr) { Tcl_Obj *valuePtr = Tcl_GetHashValue(&cPtr->entry); TclDecrRefCount(valuePtr); } Tcl_DeleteHashTable(&dict->table); } static inline Tcl_HashEntry * CreateChainEntry( Dict *dict, Tcl_Obj *keyPtr, int *newPtr) { ChainEntry *cPtr = (ChainEntry *) Tcl_CreateHashEntry(&dict->table, keyPtr, newPtr); /* * If this is a new entry in the hash table, stitch it into the chain. */ if (*newPtr) { cPtr->nextPtr = NULL; if (dict->entryChainHead == NULL) { cPtr->prevPtr = NULL; dict->entryChainHead = cPtr; dict->entryChainTail = cPtr; } else { cPtr->prevPtr = dict->entryChainTail; dict->entryChainTail->nextPtr = cPtr; dict->entryChainTail = cPtr; } } return &cPtr->entry; } static inline int DeleteChainEntry( Dict *dict, Tcl_Obj *keyPtr) { ChainEntry *cPtr = (ChainEntry *) Tcl_FindHashEntry(&dict->table, keyPtr); if (cPtr == NULL) { return 0; } else { Tcl_Obj *valuePtr = Tcl_GetHashValue(&cPtr->entry); TclDecrRefCount(valuePtr); } /* * Unstitch from the chain. */ if (cPtr->nextPtr) { cPtr->nextPtr->prevPtr = cPtr->prevPtr; } else { dict->entryChainTail = cPtr->prevPtr; } if (cPtr->prevPtr) { cPtr->prevPtr->nextPtr = cPtr->nextPtr; } else { dict->entryChainHead = cPtr->nextPtr; } Tcl_DeleteHashEntry(&cPtr->entry); return 1; } /* *---------------------------------------------------------------------- * * DupDictInternalRep -- * * Initialize the internal representation of a dictionary Tcl_Obj to a * copy of the internal representation of an existing dictionary object. * * Results: * None. * * Side effects: * "srcPtr"s dictionary internal rep pointer should not be NULL and we * assume it is not NULL. We set "copyPtr"s internal rep to a pointer to * a newly allocated dictionary rep that, in turn, points to "srcPtr"s * key and value objects. Those objects are not actually copied but are * shared between "srcPtr" and "copyPtr". The ref count of each key and * value object is incremented. * *---------------------------------------------------------------------- */ static void DupDictInternalRep( Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) { Dict *oldDict = DICT(srcPtr); Dict *newDict = ckalloc(sizeof(Dict)); ChainEntry *cPtr; /* * Copy values across from the old hash table. */ InitChainTable(newDict); for (cPtr=oldDict->entryChainHead ; cPtr!=NULL ; cPtr=cPtr->nextPtr) { Tcl_Obj *key = Tcl_GetHashKey(&oldDict->table, &cPtr->entry); Tcl_Obj *valuePtr = Tcl_GetHashValue(&cPtr->entry); int n; Tcl_HashEntry *hPtr = CreateChainEntry(newDict, key, &n); /* * Fill in the contents. */ Tcl_SetHashValue(hPtr, valuePtr); Tcl_IncrRefCount(valuePtr); } /* * Initialise other fields. */ newDict->epoch = 0; newDict->chain = NULL; newDict->refcount = 1; /* * Store in the object. */ DICT(copyPtr) = newDict; copyPtr->internalRep.twoPtrValue.ptr2 = NULL; copyPtr->typePtr = &tclDictType; } /* *---------------------------------------------------------------------- * * FreeDictInternalRep -- * * Deallocate the storage associated with a dictionary object's internal * representation. * * Results: * None * * Side effects: * Frees the memory holding the dictionary's internal hash table unless * it is locked by an iteration going over it. * *---------------------------------------------------------------------- */ static void FreeDictInternalRep( Tcl_Obj *dictPtr) { Dict *dict = DICT(dictPtr); dict->refcount--; if (dict->refcount <= 0) { DeleteDict(dict); } dictPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * DeleteDict -- * * Delete the structure that is used to implement a dictionary's internal * representation. Called when either the dictionary object loses its * internal representation or when the last iteration over the dictionary * completes. * * Results: * None * * Side effects: * Decrements the reference count of all key and value objects in the * dictionary, which may free them. * *---------------------------------------------------------------------- */ static void DeleteDict( Dict *dict) { DeleteChainTable(dict); ckfree(dict); } /* *---------------------------------------------------------------------- * * UpdateStringOfDict -- * * Update the string representation for a dictionary object. Note: This * function does not invalidate an existing old string rep so storage * will be lost if this has not already been done. This code is based on * UpdateStringOfList in tclListObj.c * * Results: * None. * * Side effects: * The object's string is set to a valid string that results from the * dict-to-string conversion. This string will be empty if the dictionary * has no key/value pairs. The dictionary internal representation should * not be NULL and we assume it is not NULL. * *---------------------------------------------------------------------- */ static void UpdateStringOfDict( Tcl_Obj *dictPtr) { #define LOCAL_SIZE 20 int localFlags[LOCAL_SIZE], *flagPtr = NULL; Dict *dict = DICT(dictPtr); ChainEntry *cPtr; Tcl_Obj *keyPtr, *valuePtr; int i, length, bytesNeeded = 0; const char *elem; char *dst; const int maxFlags = UINT_MAX / sizeof(int); /* * This field is the most useful one in the whole hash structure, and it * is not exposed by any API function... */ int numElems = dict->table.numEntries * 2; /* Handle empty list case first, simplifies what follows */ if (numElems == 0) { dictPtr->bytes = tclEmptyStringRep; dictPtr->length = 0; return; } /* * Pass 1: estimate space, gather flags. */ if (numElems <= LOCAL_SIZE) { flagPtr = localFlags; } else if (numElems > maxFlags) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } else { flagPtr = ckalloc(numElems * sizeof(int)); } for (i=0,cPtr=dict->entryChainHead; inextPtr) { /* * Assume that cPtr is never NULL since we know the number of array * elements already. */ flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 ); keyPtr = Tcl_GetHashKey(&dict->table, &cPtr->entry); elem = TclGetStringFromObj(keyPtr, &length); bytesNeeded += TclScanElement(elem, length, flagPtr+i); if (bytesNeeded < 0) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } flagPtr[i+1] = TCL_DONT_QUOTE_HASH; valuePtr = Tcl_GetHashValue(&cPtr->entry); elem = TclGetStringFromObj(valuePtr, &length); bytesNeeded += TclScanElement(elem, length, flagPtr+i+1); if (bytesNeeded < 0) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } } if (bytesNeeded > INT_MAX - numElems + 1) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } bytesNeeded += numElems; /* * Pass 2: copy into string rep buffer. */ dictPtr->length = bytesNeeded - 1; dictPtr->bytes = ckalloc(bytesNeeded); dst = dictPtr->bytes; for (i=0,cPtr=dict->entryChainHead; inextPtr) { flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 ); keyPtr = Tcl_GetHashKey(&dict->table, &cPtr->entry); elem = TclGetStringFromObj(keyPtr, &length); dst += TclConvertElement(elem, length, dst, flagPtr[i]); *dst++ = ' '; flagPtr[i+1] |= TCL_DONT_QUOTE_HASH; valuePtr = Tcl_GetHashValue(&cPtr->entry); elem = TclGetStringFromObj(valuePtr, &length); dst += TclConvertElement(elem, length, dst, flagPtr[i+1]); *dst++ = ' '; } dictPtr->bytes[dictPtr->length] = '\0'; if (flagPtr != localFlags) { ckfree(flagPtr); } } /* *---------------------------------------------------------------------- * * SetDictFromAny -- * * Convert a non-dictionary object into a dictionary object. This code is * very closely related to SetListFromAny in tclListObj.c but does not * actually guarantee that a dictionary object will have a string rep (as * conversions from lists are handled with a special case.) * * Results: * A standard Tcl result. * * Side effects: * If the string can be converted, it loses any old internal * representation that it had and gains a dictionary's internalRep. * *---------------------------------------------------------------------- */ static int SetDictFromAny( Tcl_Interp *interp, Tcl_Obj *objPtr) { Tcl_HashEntry *hPtr; int isNew; Dict *dict = ckalloc(sizeof(Dict)); InitChainTable(dict); /* * Since lists and dictionaries have very closely-related string * representations (i.e. the same parsing code) we can safely special-case * the conversion from lists to dictionaries. */ if (objPtr->typePtr == &tclListType) { int objc, i; Tcl_Obj **objv; /* Cannot fail, we already know the Tcl_ObjType is "list". */ TclListObjGetElements(NULL, objPtr, &objc, &objv); if (objc & 1) { goto missingValue; } for (i=0 ; ibytes = ckalloc((unsigned) elemSize + 1); keyPtr->length = TclCopyAndCollapse(elemSize, elemStart, keyPtr->bytes); } if (TclFindDictElement(interp, nextElem, (limit - nextElem), &elemStart, &nextElem, &elemSize, &literal) != TCL_OK) { TclDecrRefCount(keyPtr); goto errorInFindDictElement; } if (literal) { TclNewStringObj(valuePtr, elemStart, elemSize); } else { /* Avoid double copy */ TclNewObj(valuePtr); valuePtr->bytes = ckalloc((unsigned) elemSize + 1); valuePtr->length = TclCopyAndCollapse(elemSize, elemStart, valuePtr->bytes); } /* Store key and value in the hash table we're building. */ hPtr = CreateChainEntry(dict, keyPtr, &isNew); if (!isNew) { Tcl_Obj *discardedValue = Tcl_GetHashValue(hPtr); TclDecrRefCount(keyPtr); TclDecrRefCount(discardedValue); } Tcl_SetHashValue(hPtr, valuePtr); Tcl_IncrRefCount(valuePtr); /* since hash now holds ref to it */ } } /* * Free the old internalRep before setting the new one. We do this as late * as possible to allow the conversion code, in particular * Tcl_GetStringFromObj, to use that old internalRep. */ TclFreeIntRep(objPtr); dict->epoch = 0; dict->chain = NULL; dict->refcount = 1; DICT(objPtr) = dict; objPtr->internalRep.twoPtrValue.ptr2 = NULL; objPtr->typePtr = &tclDictType; return TCL_OK; missingValue: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing value to go with key", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL); } errorInFindDictElement: DeleteChainTable(dict); ckfree(dict); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclTraceDictPath -- * * Trace through a tree of dictionaries using the array of keys given. If * the flags argument has the DICT_PATH_UPDATE flag is set, a * backward-pointing chain of dictionaries is also built (in the Dict's * chain field) and the chained dictionaries are made into unshared * dictionaries (if they aren't already.) * * Results: * The object at the end of the path, or NULL if there was an error. Note * that this it is an error for an intermediate dictionary on the path to * not exist. If the flags argument has the DICT_PATH_EXISTS set, a * non-existent path gives a DICT_PATH_NON_EXISTENT result. * * Side effects: * If the flags argument is zero or DICT_PATH_EXISTS, there are no side * effects (other than potential conversion of objects to dictionaries.) * If the flags argument is DICT_PATH_UPDATE, the following additional * side effects occur. Shared dictionaries along the path are converted * into unshared objects, and a backward-pointing chain is built using * the chain fields of the dictionaries (for easy invalidation of string * representations using InvalidateDictChain). If the flags argument has * the DICT_PATH_CREATE bits set (and not the DICT_PATH_EXISTS bit), * non-existant keys will be inserted with a value of an empty * dictionary, resulting in the path being built. * *---------------------------------------------------------------------- */ Tcl_Obj * TclTraceDictPath( Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const keyv[], int flags) { Dict *dict, *newDict; int i; if (dictPtr->typePtr != &tclDictType && SetDictFromAny(interp, dictPtr) != TCL_OK) { return NULL; } dict = DICT(dictPtr); if (flags & DICT_PATH_UPDATE) { dict->chain = NULL; } for (i=0 ; itable, keyv[i]); Tcl_Obj *tmpObj; if (hPtr == NULL) { int isNew; /* Dummy */ if (flags & DICT_PATH_EXISTS) { return DICT_PATH_NON_EXISTENT; } if ((flags & DICT_PATH_CREATE) != DICT_PATH_CREATE) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "key \"%s\" not known in dictionary", TclGetString(keyv[i]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT", TclGetString(keyv[i]), NULL); } return NULL; } /* * The next line should always set isNew to 1. */ hPtr = CreateChainEntry(dict, keyv[i], &isNew); tmpObj = Tcl_NewDictObj(); Tcl_IncrRefCount(tmpObj); Tcl_SetHashValue(hPtr, tmpObj); } else { tmpObj = Tcl_GetHashValue(hPtr); if (tmpObj->typePtr != &tclDictType && SetDictFromAny(interp, tmpObj) != TCL_OK) { return NULL; } } newDict = DICT(tmpObj); if (flags & DICT_PATH_UPDATE) { if (Tcl_IsShared(tmpObj)) { TclDecrRefCount(tmpObj); tmpObj = Tcl_DuplicateObj(tmpObj); Tcl_IncrRefCount(tmpObj); Tcl_SetHashValue(hPtr, tmpObj); dict->epoch++; newDict = DICT(tmpObj); } newDict->chain = dictPtr; } dict = newDict; dictPtr = tmpObj; } return dictPtr; } /* *---------------------------------------------------------------------- * * InvalidateDictChain -- * * Go through a dictionary chain (built by an updating invokation of * TclTraceDictPath) and invalidate the string representations of all the * dictionaries on the chain. * * Results: * None * * Side effects: * String reps are invalidated and epoch counters (for detecting illegal * concurrent modifications) are updated through the chain of updated * dictionaries. * *---------------------------------------------------------------------- */ static void InvalidateDictChain( Tcl_Obj *dictObj) { Dict *dict = DICT(dictObj); do { TclInvalidateStringRep(dictObj); dict->epoch++; dictObj = dict->chain; if (dictObj == NULL) { break; } dict->chain = NULL; dict = DICT(dictObj); } while (dict != NULL); } /* *---------------------------------------------------------------------- * * Tcl_DictObjPut -- * * Add a key,value pair to a dictionary, or update the value for a key if * that key already has a mapping in the dictionary. * * Results: * A standard Tcl result. * * Side effects: * The object pointed to by dictPtr is converted to a dictionary if it is * not already one, and any string representation that it has is * invalidated. * *---------------------------------------------------------------------- */ int Tcl_DictObjPut( Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj *valuePtr) { Dict *dict; Tcl_HashEntry *hPtr; int isNew; if (Tcl_IsShared(dictPtr)) { Tcl_Panic("%s called with shared object", "Tcl_DictObjPut"); } if (dictPtr->typePtr != &tclDictType && SetDictFromAny(interp, dictPtr) != TCL_OK) { return TCL_ERROR; } if (dictPtr->bytes != NULL) { TclInvalidateStringRep(dictPtr); } dict = DICT(dictPtr); hPtr = CreateChainEntry(dict, keyPtr, &isNew); Tcl_IncrRefCount(valuePtr); if (!isNew) { Tcl_Obj *oldValuePtr = Tcl_GetHashValue(hPtr); TclDecrRefCount(oldValuePtr); } Tcl_SetHashValue(hPtr, valuePtr); dict->epoch++; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_DictObjGet -- * * Given a key, get its value from the dictionary (or NULL if key is not * found in dictionary.) * * Results: * A standard Tcl result. The variable pointed to by valuePtrPtr is * updated with the value for the key. Note that it is not an error for * the key to have no mapping in the dictionary. * * Side effects: * The object pointed to by dictPtr is converted to a dictionary if it is * not already one. * *---------------------------------------------------------------------- */ int Tcl_DictObjGet( Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr) { Dict *dict; Tcl_HashEntry *hPtr; if (dictPtr->typePtr != &tclDictType && SetDictFromAny(interp, dictPtr) != TCL_OK) { *valuePtrPtr = NULL; return TCL_ERROR; } dict = DICT(dictPtr); hPtr = Tcl_FindHashEntry(&dict->table, keyPtr); if (hPtr == NULL) { *valuePtrPtr = NULL; } else { *valuePtrPtr = Tcl_GetHashValue(hPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_DictObjRemove -- * * Remove the key,value pair with the given key from the dictionary; the * key does not need to be present in the dictionary. * * Results: * A standard Tcl result. * * Side effects: * The object pointed to by dictPtr is converted to a dictionary if it is * not already one, and any string representation that it has is * invalidated. * *---------------------------------------------------------------------- */ int Tcl_DictObjRemove( Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr) { Dict *dict; if (Tcl_IsShared(dictPtr)) { Tcl_Panic("%s called with shared object", "Tcl_DictObjRemove"); } if (dictPtr->typePtr != &tclDictType && SetDictFromAny(interp, dictPtr) != TCL_OK) { return TCL_ERROR; } dict = DICT(dictPtr); if (DeleteChainEntry(dict, keyPtr)) { if (dictPtr->bytes != NULL) { TclInvalidateStringRep(dictPtr); } dict->epoch++; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_DictObjSize -- * * How many key,value pairs are there in the dictionary? * * Results: * A standard Tcl result. Updates the variable pointed to by sizePtr with * the number of key,value pairs in the dictionary. * * Side effects: * The dictPtr object is converted to a dictionary type if it is not a * dictionary already. * *---------------------------------------------------------------------- */ int Tcl_DictObjSize( Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr) { Dict *dict; if (dictPtr->typePtr != &tclDictType && SetDictFromAny(interp, dictPtr) != TCL_OK) { return TCL_ERROR; } dict = DICT(dictPtr); *sizePtr = dict->table.numEntries; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_DictObjFirst -- * * Start a traversal of the dictionary. Caller must supply the search * context, pointers for returning key and value, and a pointer to allow * indication of whether the dictionary has been traversed (i.e. the * dictionary is empty). The order of traversal is undefined. * * Results: * A standard Tcl result. Updates the variables pointed to by keyPtrPtr, * valuePtrPtr and donePtr. Either of keyPtrPtr and valuePtrPtr may be * NULL, in which case the key/value is not made available to the caller. * * Side effects: * The dictPtr object is converted to a dictionary type if it is not a * dictionary already. The search context is initialised if the search * has not finished. The dictionary's internal rep is Tcl_Preserve()d if * the dictionary has at least one element. * *---------------------------------------------------------------------- */ int Tcl_DictObjFirst( Tcl_Interp *interp, /* For error messages, or NULL if no error * messages desired. */ Tcl_Obj *dictPtr, /* Dictionary to traverse. */ Tcl_DictSearch *searchPtr, /* Pointer to a dict search context. */ Tcl_Obj **keyPtrPtr, /* Pointer to a variable to have the first key * written into, or NULL. */ Tcl_Obj **valuePtrPtr, /* Pointer to a variable to have the first * value written into, or NULL.*/ int *donePtr) /* Pointer to a variable which will have a 1 * written into when there are no further * values in the dictionary, or a 0 * otherwise. */ { Dict *dict; ChainEntry *cPtr; if (dictPtr->typePtr != &tclDictType && SetDictFromAny(interp, dictPtr) != TCL_OK) { return TCL_ERROR; } dict = DICT(dictPtr); cPtr = dict->entryChainHead; if (cPtr == NULL) { searchPtr->epoch = -1; *donePtr = 1; } else { *donePtr = 0; searchPtr->dictionaryPtr = (Tcl_Dict) dict; searchPtr->epoch = dict->epoch; searchPtr->next = cPtr->nextPtr; dict->refcount++; if (keyPtrPtr != NULL) { *keyPtrPtr = Tcl_GetHashKey(&dict->table, &cPtr->entry); } if (valuePtrPtr != NULL) { *valuePtrPtr = Tcl_GetHashValue(&cPtr->entry); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_DictObjNext -- * * Continue a traversal of a dictionary previously started with * Tcl_DictObjFirst. This function is safe against concurrent * modification of the underlying object (including type shimmering), * treating such situations as if the search has terminated, though it is * up to the caller to ensure that the object itself is not disposed * until the search has finished. It is _not_ safe against modifications * from other threads. * * Results: * Updates the variables pointed to by keyPtrPtr, valuePtrPtr and * donePtr. Either of keyPtrPtr and valuePtrPtr may be NULL, in which * case the key/value is not made available to the caller. * * Side effects: * Removes a reference to the dictionary's internal rep if the search * terminates. * *---------------------------------------------------------------------- */ void Tcl_DictObjNext( Tcl_DictSearch *searchPtr, /* Pointer to a hash search context. */ Tcl_Obj **keyPtrPtr, /* Pointer to a variable to have the first key * written into, or NULL. */ Tcl_Obj **valuePtrPtr, /* Pointer to a variable to have the first * value written into, or NULL.*/ int *donePtr) /* Pointer to a variable which will have a 1 * written into when there are no further * values in the dictionary, or a 0 * otherwise. */ { ChainEntry *cPtr; /* * If the searh is done; we do no work. */ if (searchPtr->epoch == -1) { *donePtr = 1; return; } /* * Bail out if the dictionary has had any elements added, modified or * removed. This *shouldn't* happen, but... */ if (((Dict *)searchPtr->dictionaryPtr)->epoch != searchPtr->epoch) { Tcl_Panic("concurrent dictionary modification and search"); } cPtr = searchPtr->next; if (cPtr == NULL) { Tcl_DictObjDone(searchPtr); *donePtr = 1; return; } searchPtr->next = cPtr->nextPtr; *donePtr = 0; if (keyPtrPtr != NULL) { *keyPtrPtr = Tcl_GetHashKey( &((Dict *)searchPtr->dictionaryPtr)->table, &cPtr->entry); } if (valuePtrPtr != NULL) { *valuePtrPtr = Tcl_GetHashValue(&cPtr->entry); } } /* *---------------------------------------------------------------------- * * Tcl_DictObjDone -- * * Call this if you want to stop a search before you reach the end of the * dictionary (e.g. because of abnormal termination of the search). It * need not be used if the search reaches its natural end (i.e. if either * Tcl_DictObjFirst or Tcl_DictObjNext sets its donePtr variable to 1). * * Results: * None. * * Side effects: * Removes a reference to the dictionary's internal rep. * *---------------------------------------------------------------------- */ void Tcl_DictObjDone( Tcl_DictSearch *searchPtr) /* Pointer to a hash search context. */ { Dict *dict; if (searchPtr->epoch != -1) { searchPtr->epoch = -1; dict = (Dict *) searchPtr->dictionaryPtr; dict->refcount--; if (dict->refcount <= 0) { DeleteDict(dict); } } } /* *---------------------------------------------------------------------- * * Tcl_DictObjPutKeyList -- * * Add a key...key,value pair to a dictionary tree. The main dictionary * value must not be shared, though sub-dictionaries may be. All * intermediate dictionaries on the path must exist. * * Results: * A standard Tcl result. Note that in the error case, a message is left * in interp unless that is NULL. * * Side effects: * If the dictionary and any of its sub-dictionaries on the path have * string representations, these are invalidated. * *---------------------------------------------------------------------- */ int Tcl_DictObjPutKeyList( Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const keyv[], Tcl_Obj *valuePtr) { Dict *dict; Tcl_HashEntry *hPtr; int isNew; if (Tcl_IsShared(dictPtr)) { Tcl_Panic("%s called with shared object", "Tcl_DictObjPutKeyList"); } if (keyc < 1) { Tcl_Panic("%s called with empty key list", "Tcl_DictObjPutKeyList"); } dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_CREATE); if (dictPtr == NULL) { return TCL_ERROR; } dict = DICT(dictPtr); hPtr = CreateChainEntry(dict, keyv[keyc-1], &isNew); Tcl_IncrRefCount(valuePtr); if (!isNew) { Tcl_Obj *oldValuePtr = Tcl_GetHashValue(hPtr); TclDecrRefCount(oldValuePtr); } Tcl_SetHashValue(hPtr, valuePtr); InvalidateDictChain(dictPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_DictObjRemoveKeyList -- * * Remove a key...key,value pair from a dictionary tree (the value * removed is implicit in the key path). The main dictionary value must * not be shared, though sub-dictionaries may be. It is not an error if * there is no value associated with the given key list, but all * intermediate dictionaries on the key path must exist. * * Results: * A standard Tcl result. Note that in the error case, a message is left * in interp unless that is NULL. * * Side effects: * If the dictionary and any of its sub-dictionaries on the key path have * string representations, these are invalidated. * *---------------------------------------------------------------------- */ int Tcl_DictObjRemoveKeyList( Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const keyv[]) { Dict *dict; if (Tcl_IsShared(dictPtr)) { Tcl_Panic("%s called with shared object", "Tcl_DictObjRemoveKeyList"); } if (keyc < 1) { Tcl_Panic("%s called with empty key list", "Tcl_DictObjRemoveKeyList"); } dictPtr = TclTraceDictPath(interp, dictPtr, keyc-1,keyv, DICT_PATH_UPDATE); if (dictPtr == NULL) { return TCL_ERROR; } dict = DICT(dictPtr); DeleteChainEntry(dict, keyv[keyc-1]); InvalidateDictChain(dictPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_NewDictObj -- * * This function is normally called when not debugging: i.e., when * TCL_MEM_DEBUG is not defined. It creates a new dict object without any * content. * * When TCL_MEM_DEBUG is defined, this function just returns the result * of calling the debugging version Tcl_DbNewDictObj. * * Results: * A new dict object is returned; it has no keys defined in it. The new * object's string representation is left NULL, and the ref count of the * object is 0. * * Side Effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_NewDictObj(void) { #ifdef TCL_MEM_DEBUG return Tcl_DbNewDictObj("unknown", 0); #else /* !TCL_MEM_DEBUG */ Tcl_Obj *dictPtr; Dict *dict; TclNewObj(dictPtr); TclInvalidateStringRep(dictPtr); dict = ckalloc(sizeof(Dict)); InitChainTable(dict); dict->epoch = 0; dict->chain = NULL; dict->refcount = 1; DICT(dictPtr) = dict; dictPtr->internalRep.twoPtrValue.ptr2 = NULL; dictPtr->typePtr = &tclDictType; return dictPtr; #endif } /* *---------------------------------------------------------------------- * * Tcl_DbNewDictObj -- * * This function is normally called when debugging: i.e., when * TCL_MEM_DEBUG is defined. It creates new dict objects. It is the same * as the Tcl_NewDictObj function above except that it calls * Tcl_DbCkalloc directly with the file name and line number from its * caller. This simplifies debugging since then the [memory active] * command will report the correct file name and line number when * reporting objects that haven't been freed. * * When TCL_MEM_DEBUG is not defined, this function just returns the * result of calling Tcl_NewDictObj. * * Results: * A new dict object is returned; it has no keys defined in it. The new * object's string representation is left NULL, and the ref count of the * object is 0. * * Side Effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_DbNewDictObj( const char *file, int line) { #ifdef TCL_MEM_DEBUG Tcl_Obj *dictPtr; Dict *dict; TclDbNewObj(dictPtr, file, line); TclInvalidateStringRep(dictPtr); dict = ckalloc(sizeof(Dict)); InitChainTable(dict); dict->epoch = 0; dict->chain = NULL; dict->refcount = 1; DICT(dictPtr) = dict; dictPtr->internalRep.twoPtrValue.ptr2 = NULL; dictPtr->typePtr = &tclDictType; return dictPtr; #else /* !TCL_MEM_DEBUG */ return Tcl_NewDictObj(); #endif } /***** START OF FUNCTIONS IMPLEMENTING TCL COMMANDS *****/ /* *---------------------------------------------------------------------- * * DictCreateCmd -- * * This function implements the "dict create" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictCreateCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictObj; int i; /* * Must have an even number of arguments; note that number of preceding * arguments (i.e. "dict create" is also even, which makes this much * easier.) */ if ((objc & 1) == 0) { Tcl_WrongNumArgs(interp, 1, objv, "?key value ...?"); return TCL_ERROR; } dictObj = Tcl_NewDictObj(); for (i=1 ; itypePtr != &tclDictType && SetDictFromAny(interp, dictPtr) != TCL_OK) { return TCL_ERROR; } if (Tcl_IsShared(dictPtr)) { dictPtr = Tcl_DuplicateObj(dictPtr); } if (dictPtr->bytes != NULL) { TclInvalidateStringRep(dictPtr); } for (i=2 ; itypePtr != &tclDictType && SetDictFromAny(interp, dictPtr) != TCL_OK) { return TCL_ERROR; } if (Tcl_IsShared(dictPtr)) { dictPtr = Tcl_DuplicateObj(dictPtr); } if (dictPtr->bytes != NULL) { TclInvalidateStringRep(dictPtr); } for (i=2 ; itypePtr != &tclDictType && SetDictFromAny(interp, targetObj) != TCL_OK) { return TCL_ERROR; } if (objc == 2) { /* * Single argument, return it. */ Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } /* * Normal behaviour: combining two (or more) dictionaries. */ if (Tcl_IsShared(targetObj)) { targetObj = Tcl_DuplicateObj(targetObj); allocatedDict = 1; } for (i=2 ; itypePtr != &tclDictType && SetDictFromAny(interp, objv[1]) != TCL_OK) { return TCL_ERROR; } if (objc == 3) { pattern = TclGetString(objv[2]); } listPtr = Tcl_NewListObj(0, NULL); if ((pattern != NULL) && TclMatchIsTrivial(pattern)) { Tcl_Obj *valuePtr = NULL; Tcl_DictObjGet(interp, objv[1], objv[2], &valuePtr); if (valuePtr != NULL) { Tcl_ListObjAppendElement(NULL, listPtr, objv[2]); } } else { Tcl_DictSearch search; Tcl_Obj *keyPtr = NULL; int done = 0; /* * At this point, we know we have a dictionary (or at least something * that can be represented; it could theoretically have shimmered away * when the pattern was fetched, but that shouldn't be damaging) so we * can start the iteration process without checking for failures. */ Tcl_DictObjFirst(NULL, objv[1], &search, &keyPtr, NULL, &done); for (; !done ; Tcl_DictObjNext(&search, &keyPtr, NULL, &done)) { if (!pattern || Tcl_StringMatch(TclGetString(keyPtr), pattern)) { Tcl_ListObjAppendElement(NULL, listPtr, keyPtr); } } Tcl_DictObjDone(&search); } Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * DictValuesCmd -- * * This function implements the "dict values" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictValuesCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *valuePtr = NULL, *listPtr; Tcl_DictSearch search; int done; const char *pattern; if (objc!=2 && objc!=3) { Tcl_WrongNumArgs(interp, 1, objv, "dictionary ?pattern?"); return TCL_ERROR; } if (Tcl_DictObjFirst(interp, objv[1], &search, NULL, &valuePtr, &done) != TCL_OK) { return TCL_ERROR; } if (objc == 3) { pattern = TclGetString(objv[2]); } else { pattern = NULL; } listPtr = Tcl_NewListObj(0, NULL); for (; !done ; Tcl_DictObjNext(&search, NULL, &valuePtr, &done)) { if (pattern==NULL || Tcl_StringMatch(TclGetString(valuePtr),pattern)) { /* * Assume this operation always succeeds. */ Tcl_ListObjAppendElement(interp, listPtr, valuePtr); } } Tcl_DictObjDone(&search); Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * DictSizeCmd -- * * This function implements the "dict size" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictSizeCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int result, size; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "dictionary"); return TCL_ERROR; } result = Tcl_DictObjSize(interp, objv[1], &size); if (result == TCL_OK) { Tcl_SetObjResult(interp, Tcl_NewIntObj(size)); } return result; } /* *---------------------------------------------------------------------- * * DictExistsCmd -- * * This function implements the "dict exists" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictExistsCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *valuePtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "dictionary key ?key ...?"); return TCL_ERROR; } dictPtr = TclTraceDictPath(interp, objv[1], objc-3, objv+2, DICT_PATH_EXISTS); if (dictPtr == NULL || dictPtr == DICT_PATH_NON_EXISTENT || Tcl_DictObjGet(interp, dictPtr, objv[objc-1], &valuePtr) != TCL_OK) { Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); } else { Tcl_SetObjResult(interp, Tcl_NewBooleanObj(valuePtr != NULL)); } return TCL_OK; } /* *---------------------------------------------------------------------- * * DictInfoCmd -- * * This function implements the "dict info" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictInfoCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr; Dict *dict; char *statsStr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "dictionary"); return TCL_ERROR; } dictPtr = objv[1]; if (dictPtr->typePtr != &tclDictType && SetDictFromAny(interp, dictPtr) != TCL_OK) { return TCL_ERROR; } dict = DICT(dictPtr); statsStr = Tcl_HashStats(&dict->table); Tcl_SetObjResult(interp, Tcl_NewStringObj(statsStr, -1)); ckfree(statsStr); return TCL_OK; } /* *---------------------------------------------------------------------- * * DictIncrCmd -- * * This function implements the "dict incr" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictIncrCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int code = TCL_OK; Tcl_Obj *dictPtr, *valuePtr = NULL; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?increment?"); return TCL_ERROR; } dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); if (dictPtr == NULL) { /* * Variable didn't yet exist. Create new dictionary value. */ dictPtr = Tcl_NewDictObj(); } else if (Tcl_DictObjGet(interp, dictPtr, objv[2], &valuePtr) != TCL_OK) { /* * Variable contents are not a dict, report error. */ return TCL_ERROR; } if (Tcl_IsShared(dictPtr)) { /* * A little internals surgery to avoid copying a string rep that will * soon be no good. */ char *saved = dictPtr->bytes; Tcl_Obj *oldPtr = dictPtr; dictPtr->bytes = NULL; dictPtr = Tcl_DuplicateObj(dictPtr); oldPtr->bytes = saved; } if (valuePtr == NULL) { /* * Key not in dictionary. Create new key with increment as value. */ if (objc == 4) { /* * Verify increment is an integer. */ mp_int increment; code = Tcl_GetBignumFromObj(interp, objv[3], &increment); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (reading increment)"); } else { /* * Remember to dispose with the bignum as we're not actually * using it directly. [Bug 2874678] */ mp_clear(&increment); Tcl_DictObjPut(NULL, dictPtr, objv[2], objv[3]); } } else { Tcl_DictObjPut(NULL, dictPtr, objv[2], Tcl_NewIntObj(1)); } } else { /* * Key in dictionary. Increment its value with minimum dup. */ if (Tcl_IsShared(valuePtr)) { valuePtr = Tcl_DuplicateObj(valuePtr); Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr); } if (objc == 4) { code = TclIncrObj(interp, valuePtr, objv[3]); } else { Tcl_Obj *incrPtr = Tcl_NewIntObj(1); Tcl_IncrRefCount(incrPtr); code = TclIncrObj(interp, valuePtr, incrPtr); TclDecrRefCount(incrPtr); } } if (code == TCL_OK) { TclInvalidateStringRep(dictPtr); valuePtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr, TCL_LEAVE_ERR_MSG); if (valuePtr == NULL) { code = TCL_ERROR; } else { Tcl_SetObjResult(interp, valuePtr); } } else if (dictPtr->refCount == 0) { TclDecrRefCount(dictPtr); } return code; } /* *---------------------------------------------------------------------- * * DictLappendCmd -- * * This function implements the "dict lappend" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictLappendCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *valuePtr, *resultPtr; int i, allocatedDict = 0, allocatedValue = 0; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?value ...?"); return TCL_ERROR; } dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); if (dictPtr == NULL) { allocatedDict = 1; dictPtr = Tcl_NewDictObj(); } else if (Tcl_IsShared(dictPtr)) { allocatedDict = 1; dictPtr = Tcl_DuplicateObj(dictPtr); } if (Tcl_DictObjGet(interp, dictPtr, objv[2], &valuePtr) != TCL_OK) { if (allocatedDict) { TclDecrRefCount(dictPtr); } return TCL_ERROR; } if (valuePtr == NULL) { valuePtr = Tcl_NewListObj(objc-3, objv+3); allocatedValue = 1; } else { if (Tcl_IsShared(valuePtr)) { allocatedValue = 1; valuePtr = Tcl_DuplicateObj(valuePtr); } for (i=3 ; ibytes != NULL) { TclInvalidateStringRep(dictPtr); } resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr, TCL_LEAVE_ERR_MSG); if (resultPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * DictAppendCmd -- * * This function implements the "dict append" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictAppendCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *valuePtr, *resultPtr; int i, allocatedDict = 0; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?value ...?"); return TCL_ERROR; } dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); if (dictPtr == NULL) { allocatedDict = 1; dictPtr = Tcl_NewDictObj(); } else if (Tcl_IsShared(dictPtr)) { allocatedDict = 1; dictPtr = Tcl_DuplicateObj(dictPtr); } if (Tcl_DictObjGet(interp, dictPtr, objv[2], &valuePtr) != TCL_OK) { if (allocatedDict) { TclDecrRefCount(dictPtr); } return TCL_ERROR; } if (valuePtr == NULL) { TclNewObj(valuePtr); } else if (Tcl_IsShared(valuePtr)) { valuePtr = Tcl_DuplicateObj(valuePtr); } for (i=3 ; icmdFramePtr, 3); /* * For unwinding everything on error. */ error: TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); Tcl_DictObjDone(searchPtr); TclStackFree(interp, searchPtr); return TCL_ERROR; } static int DictForLoopCallback( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_DictSearch *searchPtr = data[0]; Tcl_Obj *keyVarObj = data[1]; Tcl_Obj *valueVarObj = data[2]; Tcl_Obj *scriptObj = data[3]; Tcl_Obj *keyObj, *valueObj; int done; /* * Process the result from the previous execution of the script body. */ if (result == TCL_CONTINUE) { result = TCL_OK; } else if (result != TCL_OK) { if (result == TCL_BREAK) { Tcl_ResetResult(interp); result = TCL_OK; } else if (result == TCL_ERROR) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"dict for\" body line %d)", Tcl_GetErrorLine(interp))); } goto done; } /* * Get the next mapping from the dictionary. */ Tcl_DictObjNext(searchPtr, &keyObj, &valueObj, &done); if (done) { Tcl_ResetResult(interp); goto done; } /* * Stop the value from getting hit in any way by any traces on the key * variable. */ Tcl_IncrRefCount(valueObj); if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj, TCL_LEAVE_ERR_MSG) == NULL) { TclDecrRefCount(valueObj); result = TCL_ERROR; goto done; } TclDecrRefCount(valueObj); if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj, TCL_LEAVE_ERR_MSG) == NULL) { result = TCL_ERROR; goto done; } /* * Run the script. */ TclNRAddCallback(interp, DictForLoopCallback, searchPtr, keyVarObj, valueVarObj, scriptObj); return TclNREvalObjEx(interp, scriptObj, 0, iPtr->cmdFramePtr, 3); /* * For unwinding everything once the iterating is done. */ done: TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); Tcl_DictObjDone(searchPtr); TclStackFree(interp, searchPtr); return result; } /* *---------------------------------------------------------------------- * * DictMapNRCmd -- * * These functions implement the "dict map" Tcl command. See the user * documentation for details on what it does, and TIP#405 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictMapNRCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; Tcl_Obj **varv, *keyObj, *valueObj; DictMapStorage *storagePtr; int varc, done; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "{keyVarName valueVarName} dictionary script"); return TCL_ERROR; } /* * Parse arguments. */ if (TclListObjGetElements(interp, objv[1], &varc, &varv) != TCL_OK) { return TCL_ERROR; } if (varc != 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must have exactly two variable names", -1)); Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "dict", "map", NULL); return TCL_ERROR; } storagePtr = TclStackAlloc(interp, sizeof(DictMapStorage)); if (Tcl_DictObjFirst(interp, objv[2], &storagePtr->search, &keyObj, &valueObj, &done) != TCL_OK) { TclStackFree(interp, storagePtr); return TCL_ERROR; } if (done) { /* * Note that this exit leaves an empty value in the result (due to * command calling conventions) but that is OK since an empty value is * an empty dictionary. */ TclStackFree(interp, storagePtr); return TCL_OK; } TclNewObj(storagePtr->accumulatorObj); TclListObjGetElements(NULL, objv[1], &varc, &varv); storagePtr->keyVarObj = varv[0]; storagePtr->valueVarObj = varv[1]; storagePtr->scriptObj = objv[3]; /* * Make sure that these objects (which we need throughout the body of the * loop) don't vanish. Note that the dictionary internal rep is locked * internally so that updates, shimmering, etc are not a problem. */ Tcl_IncrRefCount(storagePtr->accumulatorObj); Tcl_IncrRefCount(storagePtr->keyVarObj); Tcl_IncrRefCount(storagePtr->valueVarObj); Tcl_IncrRefCount(storagePtr->scriptObj); /* * Stop the value from getting hit in any way by any traces on the key * variable. */ Tcl_IncrRefCount(valueObj); if (Tcl_ObjSetVar2(interp, storagePtr->keyVarObj, NULL, keyObj, TCL_LEAVE_ERR_MSG) == NULL) { TclDecrRefCount(valueObj); goto error; } if (Tcl_ObjSetVar2(interp, storagePtr->valueVarObj, NULL, valueObj, TCL_LEAVE_ERR_MSG) == NULL) { TclDecrRefCount(valueObj); goto error; } TclDecrRefCount(valueObj); /* * Run the script. */ TclNRAddCallback(interp, DictMapLoopCallback, storagePtr, NULL,NULL,NULL); return TclNREvalObjEx(interp, storagePtr->scriptObj, 0, iPtr->cmdFramePtr, 3); /* * For unwinding everything on error. */ error: TclDecrRefCount(storagePtr->keyVarObj); TclDecrRefCount(storagePtr->valueVarObj); TclDecrRefCount(storagePtr->scriptObj); TclDecrRefCount(storagePtr->accumulatorObj); Tcl_DictObjDone(&storagePtr->search); TclStackFree(interp, storagePtr); return TCL_ERROR; } static int DictMapLoopCallback( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; DictMapStorage *storagePtr = data[0]; Tcl_Obj *keyObj, *valueObj; int done; /* * Process the result from the previous execution of the script body. */ if (result == TCL_CONTINUE) { result = TCL_OK; } else if (result != TCL_OK) { if (result == TCL_BREAK) { Tcl_ResetResult(interp); result = TCL_OK; } else if (result == TCL_ERROR) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"dict map\" body line %d)", Tcl_GetErrorLine(interp))); } goto done; } else { keyObj = Tcl_ObjGetVar2(interp, storagePtr->keyVarObj, NULL, TCL_LEAVE_ERR_MSG); if (keyObj == NULL) { result = TCL_ERROR; goto done; } Tcl_DictObjPut(NULL, storagePtr->accumulatorObj, keyObj, Tcl_GetObjResult(interp)); } /* * Get the next mapping from the dictionary. */ Tcl_DictObjNext(&storagePtr->search, &keyObj, &valueObj, &done); if (done) { Tcl_SetObjResult(interp, storagePtr->accumulatorObj); goto done; } /* * Stop the value from getting hit in any way by any traces on the key * variable. */ Tcl_IncrRefCount(valueObj); if (Tcl_ObjSetVar2(interp, storagePtr->keyVarObj, NULL, keyObj, TCL_LEAVE_ERR_MSG) == NULL) { TclDecrRefCount(valueObj); result = TCL_ERROR; goto done; } if (Tcl_ObjSetVar2(interp, storagePtr->valueVarObj, NULL, valueObj, TCL_LEAVE_ERR_MSG) == NULL) { TclDecrRefCount(valueObj); result = TCL_ERROR; goto done; } TclDecrRefCount(valueObj); /* * Run the script. */ TclNRAddCallback(interp, DictMapLoopCallback, storagePtr, NULL,NULL,NULL); return TclNREvalObjEx(interp, storagePtr->scriptObj, 0, iPtr->cmdFramePtr, 3); /* * For unwinding everything once the iterating is done. */ done: TclDecrRefCount(storagePtr->keyVarObj); TclDecrRefCount(storagePtr->valueVarObj); TclDecrRefCount(storagePtr->scriptObj); TclDecrRefCount(storagePtr->accumulatorObj); Tcl_DictObjDone(&storagePtr->search); TclStackFree(interp, storagePtr); return result; } /* *---------------------------------------------------------------------- * * DictSetCmd -- * * This function implements the "dict set" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictSetCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *resultPtr; int result, allocatedDict = 0; if (objc < 4) { Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?key ...? value"); return TCL_ERROR; } dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); if (dictPtr == NULL) { allocatedDict = 1; dictPtr = Tcl_NewDictObj(); } else if (Tcl_IsShared(dictPtr)) { allocatedDict = 1; dictPtr = Tcl_DuplicateObj(dictPtr); } result = Tcl_DictObjPutKeyList(interp, dictPtr, objc-3, objv+2, objv[objc-1]); if (result != TCL_OK) { if (allocatedDict) { TclDecrRefCount(dictPtr); } return TCL_ERROR; } resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr, TCL_LEAVE_ERR_MSG); if (resultPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * DictUnsetCmd -- * * This function implements the "dict unset" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictUnsetCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tcl_Obj *dictPtr, *resultPtr; int result, allocatedDict = 0; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key ?key ...?"); return TCL_ERROR; } dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); if (dictPtr == NULL) { allocatedDict = 1; dictPtr = Tcl_NewDictObj(); } else if (Tcl_IsShared(dictPtr)) { allocatedDict = 1; dictPtr = Tcl_DuplicateObj(dictPtr); } result = Tcl_DictObjRemoveKeyList(interp, dictPtr, objc-2, objv+2); if (result != TCL_OK) { if (allocatedDict) { TclDecrRefCount(dictPtr); } return TCL_ERROR; } resultPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, dictPtr, TCL_LEAVE_ERR_MSG); if (resultPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * DictFilterCmd -- * * This function implements the "dict filter" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictFilterCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; static const char *const filters[] = { "key", "script", "value", NULL }; enum FilterTypes { FILTER_KEYS, FILTER_SCRIPT, FILTER_VALUES }; Tcl_Obj *scriptObj, *keyVarObj, *valueVarObj; Tcl_Obj **varv, *keyObj = NULL, *valueObj = NULL, *resultObj, *boolObj; Tcl_DictSearch search; int index, varc, done, result, satisfied; const char *pattern; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "dictionary filterType ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], filters, "filterType", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum FilterTypes) index) { case FILTER_KEYS: /* * Create a dictionary whose keys all match a certain pattern. */ if (Tcl_DictObjFirst(interp, objv[1], &search, &keyObj, &valueObj, &done) != TCL_OK) { return TCL_ERROR; } if (objc == 3) { /* * Nothing to match, so return nothing (== empty dictionary). */ Tcl_DictObjDone(&search); return TCL_OK; } else if (objc == 4) { pattern = TclGetString(objv[3]); resultObj = Tcl_NewDictObj(); if (TclMatchIsTrivial(pattern)) { /* * Must release the search lock here to prevent a memory leak * since we are not exhausing the search. [Bug 1705778, leak * K05] */ Tcl_DictObjDone(&search); Tcl_DictObjGet(interp, objv[1], objv[3], &valueObj); if (valueObj != NULL) { Tcl_DictObjPut(NULL, resultObj, objv[3], valueObj); } } else { while (!done) { if (Tcl_StringMatch(TclGetString(keyObj), pattern)) { Tcl_DictObjPut(NULL, resultObj, keyObj, valueObj); } Tcl_DictObjNext(&search, &keyObj, &valueObj, &done); } } } else { /* * Can't optimize this match for trivial globbing: would disturb * order. */ resultObj = Tcl_NewDictObj(); while (!done) { int i; for (i=3 ; icmdFramePtr, 4); switch (result) { case TCL_OK: boolObj = Tcl_GetObjResult(interp); Tcl_IncrRefCount(boolObj); Tcl_ResetResult(interp); if (Tcl_GetBooleanFromObj(interp, boolObj, &satisfied) != TCL_OK) { TclDecrRefCount(boolObj); result = TCL_ERROR; goto abnormalResult; } TclDecrRefCount(boolObj); if (satisfied) { Tcl_DictObjPut(NULL, resultObj, keyObj, valueObj); } break; case TCL_BREAK: /* * Force loop termination by calling Tcl_DictObjDone; this * makes the next Tcl_DictObjNext say there is nothing more to * do. */ Tcl_ResetResult(interp); Tcl_DictObjDone(&search); case TCL_CONTINUE: result = TCL_OK; break; case TCL_ERROR: Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"dict filter\" script line %d)", Tcl_GetErrorLine(interp))); default: goto abnormalResult; } TclDecrRefCount(keyObj); TclDecrRefCount(valueObj); Tcl_DictObjNext(&search, &keyObj, &valueObj, &done); } /* * Stop holding a reference to these objects. */ TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); Tcl_DictObjDone(&search); if (result == TCL_OK) { Tcl_SetObjResult(interp, resultObj); } else { TclDecrRefCount(resultObj); } return result; abnormalResult: Tcl_DictObjDone(&search); TclDecrRefCount(keyObj); TclDecrRefCount(valueObj); TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); TclDecrRefCount(resultObj); return result; } Tcl_Panic("unexpected fallthrough"); /* Control never reaches this point. */ return TCL_ERROR; } /* *---------------------------------------------------------------------- * * DictUpdateCmd -- * * This function implements the "dict update" Tcl command. See the user * documentation for details on what it does, and TIP#212 for the formal * specification. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int DictUpdateCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; Tcl_Obj *dictPtr, *objPtr; int i, dummy; if (objc < 5 || !(objc & 1)) { Tcl_WrongNumArgs(interp, 1, objv, "dictVarName key varName ?key varName ...? script"); return TCL_ERROR; } dictPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG); if (dictPtr == NULL) { return TCL_ERROR; } if (Tcl_DictObjSize(interp, dictPtr, &dummy) != TCL_OK) { return TCL_ERROR; } Tcl_IncrRefCount(dictPtr); for (i=2 ; i+2cmdFramePtr, objc-1); } static int FinalizeDictUpdate( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj *dictPtr, *objPtr, **objv; Tcl_InterpState state; int i, objc; Tcl_Obj *varName = data[0]; Tcl_Obj *argsObj = data[1]; /* * ErrorInfo handling. */ if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (body of \"dict update\")"); } /* * If the dictionary variable doesn't exist, drop everything silently. */ dictPtr = Tcl_ObjGetVar2(interp, varName, NULL, 0); if (dictPtr == NULL) { TclDecrRefCount(varName); TclDecrRefCount(argsObj); return result; } /* * Double-check that it is still a dictionary. */ state = Tcl_SaveInterpState(interp, result); if (Tcl_DictObjSize(interp, dictPtr, &objc) != TCL_OK) { Tcl_DiscardInterpState(state); TclDecrRefCount(varName); TclDecrRefCount(argsObj); return TCL_ERROR; } if (Tcl_IsShared(dictPtr)) { dictPtr = Tcl_DuplicateObj(dictPtr); } /* * Write back the values from the variables, treating failure to read as * an instruction to remove the key. */ Tcl_ListObjGetElements(NULL, argsObj, &objc, &objv); for (i=0 ; i 3) { pathPtr = Tcl_NewListObj(objc-3, objv+2); Tcl_IncrRefCount(pathPtr); } Tcl_IncrRefCount(objv[1]); TclNRAddCallback(interp, FinalizeDictWith, objv[1], keysPtr, pathPtr, NULL); return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1); } static int FinalizeDictWith( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj **pathv; int pathc; Tcl_InterpState state; Tcl_Obj *varName = data[0]; Tcl_Obj *keysPtr = data[1]; Tcl_Obj *pathPtr = data[2]; Var *varPtr, *arrayPtr; if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (body of \"dict with\")"); } /* * Save the result state; TDWF doesn't guarantee to not modify that on * TCL_OK result. */ state = Tcl_SaveInterpState(interp, result); if (pathPtr != NULL) { Tcl_ListObjGetElements(NULL, pathPtr, &pathc, &pathv); } else { pathc = 0; pathv = NULL; } /* * Pack from local variables back into the dictionary. */ varPtr = TclObjLookupVarEx(interp, varName, NULL, TCL_LEAVE_ERR_MSG, "set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { result = TCL_ERROR; } else { result = TclDictWithFinish(interp, varPtr, arrayPtr, varName, NULL, -1, pathc, pathv, keysPtr); } /* * Tidy up and return the real result (unless we had an error). */ TclDecrRefCount(varName); TclDecrRefCount(keysPtr); if (pathPtr != NULL) { TclDecrRefCount(pathPtr); } if (result != TCL_OK) { Tcl_DiscardInterpState(state); return TCL_ERROR; } return Tcl_RestoreInterpState(interp, state); } /* *---------------------------------------------------------------------- * * TclDictWithInit -- * * Part of the core of [dict with]. Pokes into a dictionary and converts * the mappings there into assignments to (presumably) local variables. * Returns a list of all the names that were mapped so that removal of * either the variable or the dictionary entry won't surprise us when we * come to stuffing everything back. * * Result: * List of mapped names, or NULL if there was an error. * * Side effects: * Assigns to variables, so potentially legion due to traces. * *---------------------------------------------------------------------- */ Tcl_Obj * TclDictWithInit( Tcl_Interp *interp, Tcl_Obj *dictPtr, int pathc, Tcl_Obj *const pathv[]) { Tcl_DictSearch s; Tcl_Obj *keyPtr, *valPtr, *keysPtr; int done; if (pathc > 0) { dictPtr = TclTraceDictPath(interp, dictPtr, pathc, pathv, DICT_PATH_READ); if (dictPtr == NULL) { return NULL; } } /* * Go over the list of keys and write each corresponding value to a * variable in the current context with the same name. Also keep a copy of * the keys so we can write back properly later on even if the dictionary * has been structurally modified. */ if (Tcl_DictObjFirst(interp, dictPtr, &s, &keyPtr, &valPtr, &done) != TCL_OK) { return NULL; } TclNewObj(keysPtr); for (; !done ; Tcl_DictObjNext(&s, &keyPtr, &valPtr, &done)) { Tcl_ListObjAppendElement(NULL, keysPtr, keyPtr); if (Tcl_ObjSetVar2(interp, keyPtr, NULL, valPtr, TCL_LEAVE_ERR_MSG) == NULL) { TclDecrRefCount(keysPtr); Tcl_DictObjDone(&s); return NULL; } } return keysPtr; } /* *---------------------------------------------------------------------- * * TclDictWithFinish -- * * Part of the core of [dict with]. Reassembles the piece of the dict (in * varName, location given by pathc/pathv) from the variables named in * the keysPtr argument. NB, does not try to preserve errors or manage * argument lifetimes. * * Result: * TCL_OK if we succeeded, or TCL_ERROR if we failed. * * Side effects: * Assigns to a variable, so potentially legion due to traces. Updates * the dictionary in the named variable. * *---------------------------------------------------------------------- */ int TclDictWithFinish( Tcl_Interp *interp, /* Command interpreter in which variable * exists. Used for state management, traces * and error reporting. */ Var *varPtr, /* Reference to the variable holding the * dictionary. */ Var *arrayPtr, /* Reference to the array containing the * variable, or NULL if the variable is a * scalar. */ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or * the name of a variable. NULL if the 'index' * parameter is >= 0 */ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element * in the array part1. */ int index, /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ int pathc, /* The number of elements in the path into the * dictionary. */ Tcl_Obj *const pathv[], /* The elements of the path to the subdict. */ Tcl_Obj *keysPtr) /* List of keys to be synchronized. This is * the result value from TclDictWithInit. */ { Tcl_Obj *dictPtr, *leafPtr, *valPtr; int i, allocdict, keyc; Tcl_Obj **keyv; /* * If the dictionary variable doesn't exist, drop everything silently. */ dictPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, index); if (dictPtr == NULL) { return TCL_OK; } /* * Double-check that it is still a dictionary. */ if (Tcl_DictObjSize(interp, dictPtr, &i) != TCL_OK) { return TCL_ERROR; } if (Tcl_IsShared(dictPtr)) { dictPtr = Tcl_DuplicateObj(dictPtr); allocdict = 1; } else { allocdict = 0; } if (pathc > 0) { /* * Want to get to the dictionary which we will update; need to do * prepare-for-update de-sharing along the path *but* avoid generating * an error on a non-existant path (we'll treat that the same as a * non-existant variable. Luckily, the de-sharing operation isn't * deeply damaging if we don't go on to update; it's just less than * perfectly efficient (but no memory should be leaked). */ leafPtr = TclTraceDictPath(interp, dictPtr, pathc, pathv, DICT_PATH_EXISTS | DICT_PATH_UPDATE); if (leafPtr == NULL) { if (allocdict) { TclDecrRefCount(dictPtr); } return TCL_ERROR; } if (leafPtr == DICT_PATH_NON_EXISTENT) { if (allocdict) { TclDecrRefCount(dictPtr); } return TCL_OK; } } else { leafPtr = dictPtr; } /* * Now process our updates on the leaf dictionary. */ TclListObjGetElements(NULL, keysPtr, &keyc, &keyv); for (i=0 ; i 0) { InvalidateDictChain(leafPtr); } /* * Write back the outermost dictionary to the variable. */ if (TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, dictPtr, TCL_LEAVE_ERR_MSG, index) == NULL) { if (allocdict) { TclDecrRefCount(dictPtr); } return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclInitDictCmd -- * * This function is create the "dict" Tcl command. See the user * documentation for details on what it does, and TIP#111 for the formal * specification. * * Results: * A Tcl command handle. * * Side effects: * May advance compilation epoch. * *---------------------------------------------------------------------- */ Tcl_Command TclInitDictCmd( Tcl_Interp *interp) { return TclMakeEnsemble(interp, "dict", implementationMap); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclVar.c0000644000175000017500000055766712665172306014632 0ustar sergeisergei/* * tclVar.c -- * * This file contains routines that implement Tcl variables (both scalars * and arrays). * * The implementation of arrays is modelled after an initial * implementation by Mark Diekhans and Karl Lehenbauer. * * Copyright (c) 1987-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2007 Miguel Sofer * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclOOInt.h" /* * Prototypes for the variable hash key methods. */ static Tcl_HashEntry * AllocVarEntry(Tcl_HashTable *tablePtr, void *keyPtr); static void FreeVarEntry(Tcl_HashEntry *hPtr); static int CompareVarKeys(void *keyPtr, Tcl_HashEntry *hPtr); static const Tcl_HashKeyType tclVarHashKeyType = { TCL_HASH_KEY_TYPE_VERSION, /* version */ 0, /* flags */ TclHashObjKey, /* hashKeyProc */ CompareVarKeys, /* compareKeysProc */ AllocVarEntry, /* allocEntryProc */ FreeVarEntry /* freeEntryProc */ }; static inline Var * VarHashCreateVar(TclVarHashTable *tablePtr, Tcl_Obj *key, int *newPtr); static inline Var * VarHashFirstVar(TclVarHashTable *tablePtr, Tcl_HashSearch *searchPtr); static inline Var * VarHashNextVar(Tcl_HashSearch *searchPtr); static inline void CleanupVar(Var *varPtr, Var *arrayPtr); #define VarHashGetValue(hPtr) \ ((Var *) ((char *)hPtr - TclOffset(VarInHash, entry))) /* * NOTE: VarHashCreateVar increments the recount of its key argument. * All callers that will call Tcl_DecrRefCount on that argument must * call Tcl_IncrRefCount on it before passing it in. This requirement * can bubble up to callers of callers .... etc. */ static inline Var * VarHashCreateVar( TclVarHashTable *tablePtr, Tcl_Obj *key, int *newPtr) { Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&tablePtr->table, key, newPtr); if (hPtr) { return VarHashGetValue(hPtr); } else { return NULL; } } #define VarHashFindVar(tablePtr, key) \ VarHashCreateVar((tablePtr), (key), NULL) #define VarHashInvalidateEntry(varPtr) \ ((varPtr)->flags |= VAR_DEAD_HASH) #define VarHashDeleteEntry(varPtr) \ Tcl_DeleteHashEntry(&(((VarInHash *) varPtr)->entry)) #define VarHashFirstEntry(tablePtr, searchPtr) \ Tcl_FirstHashEntry(&(tablePtr)->table, (searchPtr)) #define VarHashNextEntry(searchPtr) \ Tcl_NextHashEntry((searchPtr)) static inline Var * VarHashFirstVar( TclVarHashTable *tablePtr, Tcl_HashSearch *searchPtr) { Tcl_HashEntry *hPtr = VarHashFirstEntry(tablePtr, searchPtr); if (hPtr) { return VarHashGetValue(hPtr); } else { return NULL; } } static inline Var * VarHashNextVar( Tcl_HashSearch *searchPtr) { Tcl_HashEntry *hPtr = VarHashNextEntry(searchPtr); if (hPtr) { return VarHashGetValue(hPtr); } else { return NULL; } } #define VarHashGetKey(varPtr) \ (((VarInHash *)(varPtr))->entry.key.objPtr) #define VarHashDeleteTable(tablePtr) \ Tcl_DeleteHashTable(&(tablePtr)->table) /* * The strings below are used to indicate what went wrong when a variable * access is denied. */ static const char *noSuchVar = "no such variable"; static const char *isArray = "variable is array"; static const char *needArray = "variable isn't array"; static const char *noSuchElement = "no such element in array"; static const char *danglingElement = "upvar refers to element in deleted array"; static const char *danglingVar = "upvar refers to variable in deleted namespace"; static const char *badNamespace = "parent namespace doesn't exist"; static const char *missingName = "missing variable name"; static const char *isArrayElement = "name refers to an element in an array"; /* * A test to see if we are in a call frame that has local variables. This is * true if we are inside a procedure body. */ #define HasLocalVars(framePtr) ((framePtr)->isProcCallFrame & FRAME_IS_PROC) /* * The following structure describes an enumerative search in progress on an * array variable; this are invoked with options to the "array" command. */ typedef struct ArraySearch { int id; /* Integer id used to distinguish among * multiple concurrent searches for the same * array. */ struct Var *varPtr; /* Pointer to array variable that's being * searched. */ Tcl_HashSearch search; /* Info kept by the hash module about progress * through the array. */ Tcl_HashEntry *nextEntry; /* Non-null means this is the next element to * be enumerated (it's leftover from the * Tcl_FirstHashEntry call or from an "array * anymore" command). NULL means must call * Tcl_NextHashEntry to get value to * return. */ struct ArraySearch *nextPtr;/* Next in list of all active searches for * this variable, or NULL if this is the last * one. */ } ArraySearch; /* * Forward references to functions defined later in this file: */ static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *patternPtr, int includeLinks); static void DeleteSearches(Interp *iPtr, Var *arrayVarPtr); static void DeleteArray(Interp *iPtr, Tcl_Obj *arrayNamePtr, Var *varPtr, int flags, int index); static Tcl_Var ObjFindNamespaceVar(Tcl_Interp *interp, Tcl_Obj *namePtr, Tcl_Namespace *contextNsPtr, int flags); static int ObjMakeUpvar(Tcl_Interp *interp, CallFrame *framePtr, Tcl_Obj *otherP1Ptr, const char *otherP2, const int otherFlags, Tcl_Obj *myNamePtr, int myFlags, int index); static ArraySearch * ParseSearchId(Tcl_Interp *interp, const Var *varPtr, Tcl_Obj *varNamePtr, Tcl_Obj *handleObj); static void UnsetVarStruct(Var *varPtr, Var *arrayPtr, Interp *iPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags, int index); static int SetArraySearchObj(Tcl_Interp *interp, Tcl_Obj *objPtr); /* * Functions defined in this file that may be exported in the future for use * by the bytecode compiler and engine or to the public interface. */ MODULE_SCOPE Var * TclLookupSimpleVar(Tcl_Interp *interp, Tcl_Obj *varNamePtr, int flags, const int create, const char **errMsgPtr, int *indexPtr); static Tcl_DupInternalRepProc DupLocalVarName; static Tcl_FreeInternalRepProc FreeLocalVarName; static Tcl_UpdateStringProc PanicOnUpdateVarName; static Tcl_FreeInternalRepProc FreeParsedVarName; static Tcl_DupInternalRepProc DupParsedVarName; static Tcl_UpdateStringProc UpdateParsedVarName; static Tcl_UpdateStringProc PanicOnUpdateVarName; static Tcl_SetFromAnyProc PanicOnSetVarName; /* * Types of Tcl_Objs used to cache variable lookups. * * localVarName - INTERNALREP DEFINITION: * twoPtrValue.ptr1: pointer to name obj in varFramePtr->localCache * or NULL if it is this same obj * twoPtrValue.ptr2: index into locals table * * nsVarName - INTERNALREP DEFINITION: * twoPtrValue.ptr1: pointer to the namespace containing the reference * twoPtrValue.ptr2: pointer to the corresponding Var * * parsedVarName - INTERNALREP DEFINITION: * twoPtrValue.ptr1: pointer to the array name Tcl_Obj, or NULL if it is a * scalar variable * twoPtrValue.ptr2: pointer to the element name string (owned by this * Tcl_Obj), or NULL if it is a scalar variable */ static const Tcl_ObjType localVarNameType = { "localVarName", FreeLocalVarName, DupLocalVarName, PanicOnUpdateVarName, PanicOnSetVarName }; static const Tcl_ObjType tclParsedVarNameType = { "parsedVarName", FreeParsedVarName, DupParsedVarName, UpdateParsedVarName, PanicOnSetVarName }; /* * Type of Tcl_Objs used to speed up array searches. * * INTERNALREP DEFINITION: * twoPtrValue.ptr1: searchIdNumber (cast to pointer) * twoPtrValue.ptr2: variableNameStartInString (cast to pointer) * * Note that the value stored in ptr2 is the offset into the string of the * start of the variable name and not the address of the variable name itself, * as this can be safely copied. */ const Tcl_ObjType tclArraySearchType = { "array search", NULL, NULL, NULL, SetArraySearchObj }; Var * TclVarHashCreateVar( TclVarHashTable *tablePtr, const char *key, int *newPtr) { Tcl_Obj *keyPtr; Var *varPtr; keyPtr = Tcl_NewStringObj(key, -1); Tcl_IncrRefCount(keyPtr); varPtr = VarHashCreateVar(tablePtr, keyPtr, newPtr); Tcl_DecrRefCount(keyPtr); return varPtr; } /* *---------------------------------------------------------------------- * * TclCleanupVar -- * * This function is called when it looks like it may be OK to free up a * variable's storage. If the variable is in a hashtable, its Var * structure and hash table entry will be freed along with those of its * containing array, if any. This function is called, for example, when * a trace on a variable deletes a variable. * * Results: * None. * * Side effects: * If the variable (or its containing array) really is dead and in a * hashtable, then its Var structure, and possibly its hash table entry, * is freed up. * *---------------------------------------------------------------------- */ static inline void CleanupVar( Var *varPtr, /* Pointer to variable that may be a candidate * for being expunged. */ Var *arrayPtr) /* Array that contains the variable, or NULL * if this variable isn't an array element. */ { if (TclIsVarUndefined(varPtr) && TclIsVarInHash(varPtr) && !TclIsVarTraced(varPtr) && (VarHashRefCount(varPtr) == !TclIsVarDeadHash(varPtr))) { if (VarHashRefCount(varPtr) == 0) { ckfree(varPtr); } else { VarHashDeleteEntry(varPtr); } } if (arrayPtr != NULL && TclIsVarUndefined(arrayPtr) && TclIsVarInHash(arrayPtr) && !TclIsVarTraced(arrayPtr) && (VarHashRefCount(arrayPtr) == !TclIsVarDeadHash(arrayPtr))) { if (VarHashRefCount(arrayPtr) == 0) { ckfree(arrayPtr); } else { VarHashDeleteEntry(arrayPtr); } } } void TclCleanupVar( Var *varPtr, /* Pointer to variable that may be a candidate * for being expunged. */ Var *arrayPtr) /* Array that contains the variable, or NULL * if this variable isn't an array element. */ { CleanupVar(varPtr, arrayPtr); } /* *---------------------------------------------------------------------- * * TclLookupVar -- * * This function is used to locate a variable given its name(s). It has * been mostly superseded by TclObjLookupVar, it is now only used by the * trace code. It is kept in tcl8.5 mainly because it is in the internal * stubs table, so that some extension may be calling it. * * Results: * The return value is a pointer to the variable structure indicated by * part1 and part2, or NULL if the variable couldn't be found. If the * variable is found, *arrayPtrPtr is filled in with the address of the * variable structure for the array that contains the variable (or NULL * if the variable is a scalar). If the variable can't be found and * either createPart1 or createPart2 are 1, a new as-yet-undefined * (VAR_UNDEFINED) variable structure is created, entered into a hash * table, and returned. * * If the variable isn't found and creation wasn't specified, or some * other error occurs, NULL is returned and an error message is left in * the interp's result if TCL_LEAVE_ERR_MSG is set in flags. * * Note: it's possible for the variable returned to be VAR_UNDEFINED even * if createPart1 or createPart2 are 1 (these only cause the hash table * entry or array to be created). For example, the variable might be a * global that has been unset but is still referenced by a procedure, or * a variable that has been unset but it only being kept in existence (if * VAR_UNDEFINED) by a trace. * * Side effects: * New hashtable entries may be created if createPart1 or createPart2 * are 1. * *---------------------------------------------------------------------- */ Var * TclLookupVar( Tcl_Interp *interp, /* Interpreter to use for lookup. */ const char *part1, /* If part2 isn't NULL, this is the name of an * array. Otherwise, this is a full variable * name that could include a parenthesized * array element. */ const char *part2, /* Name of element within array, or NULL. */ int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * and TCL_LEAVE_ERR_MSG bits matter. */ const char *msg, /* Verb to use in error messages, e.g. "read" * or "set". Only needed if TCL_LEAVE_ERR_MSG * is set in flags. */ int createPart1, /* If 1, create hash table entry for part 1 of * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ int createPart2, /* If 1, create hash table entry for part 2 of * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var **arrayPtrPtr) /* If the name refers to an element of an * array, *arrayPtrPtr gets filled in with * address of array variable. Otherwise this * is set to NULL. */ { Var *varPtr; Tcl_Obj *part1Ptr = Tcl_NewStringObj(part1, -1); if (createPart1) { Tcl_IncrRefCount(part1Ptr); } varPtr = TclObjLookupVar(interp, part1Ptr, part2, flags, msg, createPart1, createPart2, arrayPtrPtr); TclDecrRefCount(part1Ptr); return varPtr; } /* *---------------------------------------------------------------------- * * TclObjLookupVar, TclObjLookupVarEx -- * * This function is used by virtually all of the variable code to locate * a variable given its name(s). The parsing into array/element * components and (if possible) the lookup results are cached in * part1Ptr, which is converted to one of the varNameTypes. * * Results: * The return value is a pointer to the variable structure indicated by * part1Ptr and part2, or NULL if the variable couldn't be found. If * * the variable is found, *arrayPtrPtr is filled with the address of the * variable structure for the array that contains the variable (or NULL * if the variable is a scalar). If the variable can't be found and * either createPart1 or createPart2 are 1, a new as-yet-undefined * (VAR_UNDEFINED) variable structure is created, entered into a hash * table, and returned. * * If the variable isn't found and creation wasn't specified, or some * other error occurs, NULL is returned and an error message is left in * the interp's result if TCL_LEAVE_ERR_MSG is set in flags. * * Note: it's possible for the variable returned to be VAR_UNDEFINED even * if createPart1 or createPart2 are 1 (these only cause the hash table * entry or array to be created). For example, the variable might be a * global that has been unset but is still referenced by a procedure, or * a variable that has been unset but it only being kept in existence (if * VAR_UNDEFINED) by a trace. * * Side effects: * New hashtable entries may be created if createPart1 or createPart2 * are 1. The object part1Ptr is converted to one of localVarNameType, * tclNsVarNameType or tclParsedVarNameType and caches as much of the * lookup as it can. * When createPart1 is 1, callers must IncrRefCount part1Ptr if they * plan to DecrRefCount it. * *---------------------------------------------------------------------- */ Var * TclObjLookupVar( Tcl_Interp *interp, /* Interpreter to use for lookup. */ register Tcl_Obj *part1Ptr, /* If part2 isn't NULL, this is the name of an * array. Otherwise, this is a full variable * name that could include a parenthesized * array element. */ const char *part2, /* Name of element within array, or NULL. */ int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * and TCL_LEAVE_ERR_MSG bits matter. */ const char *msg, /* Verb to use in error messages, e.g. "read" * or "set". Only needed if TCL_LEAVE_ERR_MSG * is set in flags. */ const int createPart1, /* If 1, create hash table entry for part 1 of * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ const int createPart2, /* If 1, create hash table entry for part 2 of * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var **arrayPtrPtr) /* If the name refers to an element of an * array, *arrayPtrPtr gets filled in with * address of array variable. Otherwise this * is set to NULL. */ { Tcl_Obj *part2Ptr = NULL; Var *resPtr; if (part2) { part2Ptr = Tcl_NewStringObj(part2, -1); if (createPart2) { Tcl_IncrRefCount(part2Ptr); } } resPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, msg, createPart1, createPart2, arrayPtrPtr); if (part2Ptr) { Tcl_DecrRefCount(part2Ptr); } return resPtr; } /* * When createPart1 is 1, callers must IncrRefCount part1Ptr if they * plan to DecrRefCount it. * When createPart2 is 1, callers must IncrRefCount part2Ptr if they * plan to DecrRefCount it. */ Var * TclObjLookupVarEx( Tcl_Interp *interp, /* Interpreter to use for lookup. */ Tcl_Obj *part1Ptr, /* If part2Ptr isn't NULL, this is the name of * an array. Otherwise, this is a full * variable name that could include a * parenthesized array element. */ Tcl_Obj *part2Ptr, /* Name of element within array, or NULL. */ int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * and TCL_LEAVE_ERR_MSG bits matter. */ const char *msg, /* Verb to use in error messages, e.g. "read" * or "set". Only needed if TCL_LEAVE_ERR_MSG * is set in flags. */ const int createPart1, /* If 1, create hash table entry for part 1 of * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ const int createPart2, /* If 1, create hash table entry for part 2 of * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var **arrayPtrPtr) /* If the name refers to an element of an * array, *arrayPtrPtr gets filled in with * address of array variable. Otherwise this * is set to NULL. */ { Interp *iPtr = (Interp *) interp; register Var *varPtr; /* Points to the variable's in-frame Var * structure. */ const char *part1; int index, len1, len2; int parsed = 0; Tcl_Obj *objPtr; const Tcl_ObjType *typePtr = part1Ptr->typePtr; const char *errMsg = NULL; CallFrame *varFramePtr = iPtr->varFramePtr; const char *part2 = part2Ptr? TclGetString(part2Ptr):NULL; char *newPart2 = NULL; *arrayPtrPtr = NULL; if (typePtr == &localVarNameType) { int localIndex; localVarNameTypeHandling: localIndex = PTR2INT(part1Ptr->internalRep.twoPtrValue.ptr2); if (HasLocalVars(varFramePtr) && !(flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY)) && (localIndex < varFramePtr->numCompiledLocals)) { /* * Use the cached index if the names coincide. */ Tcl_Obj *namePtr = part1Ptr->internalRep.twoPtrValue.ptr1; Tcl_Obj *checkNamePtr = localName(iPtr->varFramePtr, localIndex); if ((!namePtr && (checkNamePtr == part1Ptr)) || (namePtr && (checkNamePtr == namePtr))) { varPtr = (Var *) &(varFramePtr->compiledLocals[localIndex]); goto donePart1; } } goto doneParsing; } /* * If part1Ptr is a tclParsedVarNameType, separate it into the pre-parsed * parts. */ if (typePtr == &tclParsedVarNameType) { if (part1Ptr->internalRep.twoPtrValue.ptr1 != NULL) { if (part2Ptr != NULL) { /* * ERROR: part1Ptr is already an array element, cannot specify * a part2. */ if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg, noSuchVar, -1); Tcl_SetErrorCode(interp, "TCL", "VALUE", "VARNAME", NULL); } return NULL; } part2 = newPart2 = part1Ptr->internalRep.twoPtrValue.ptr2; if (newPart2) { part2Ptr = Tcl_NewStringObj(newPart2, -1); if (createPart2) { Tcl_IncrRefCount(part2Ptr); } } part1Ptr = part1Ptr->internalRep.twoPtrValue.ptr1; typePtr = part1Ptr->typePtr; if (typePtr == &localVarNameType) { goto localVarNameTypeHandling; } } parsed = 1; } part1 = TclGetStringFromObj(part1Ptr, &len1); if (!parsed && len1 && (*(part1 + len1 - 1) == ')')) { /* * part1Ptr is possibly an unparsed array element. */ register int i; len2 = -1; for (i = 0; i < len1; i++) { if (*(part1 + i) == '(') { if (part2Ptr != NULL) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg, needArray, -1); Tcl_SetErrorCode(interp, "TCL", "VALUE", "VARNAME", NULL); } return NULL; } /* * part1Ptr points to an array element; first copy the element * name to a new string part2. */ part2 = part1 + i + 1; len2 = len1 - i - 2; len1 = i; newPart2 = ckalloc(len2 + 1); memcpy(newPart2, part2, (unsigned) len2); *(newPart2+len2) = '\0'; part2 = newPart2; part2Ptr = Tcl_NewStringObj(newPart2, -1); if (createPart2) { Tcl_IncrRefCount(part2Ptr); } /* * Free the internal rep of the original part1Ptr, now renamed * objPtr, and set it to tclParsedVarNameType. */ objPtr = part1Ptr; TclFreeIntRep(objPtr); objPtr->typePtr = &tclParsedVarNameType; /* * Define a new string object to hold the new part1Ptr, i.e., * the array name. Set the internal rep of objPtr, reset * typePtr and part1 to contain the references to the array * name. */ TclNewStringObj(part1Ptr, part1, len1); Tcl_IncrRefCount(part1Ptr); objPtr->internalRep.twoPtrValue.ptr1 = part1Ptr; objPtr->internalRep.twoPtrValue.ptr2 = (void *) part2; typePtr = part1Ptr->typePtr; part1 = TclGetString(part1Ptr); break; } } } doneParsing: /* * part1Ptr is not an array element; look it up, and convert it to one of * the cached types if possible. */ TclFreeIntRep(part1Ptr); varPtr = TclLookupSimpleVar(interp, part1Ptr, flags, createPart1, &errMsg, &index); if (varPtr == NULL) { if ((errMsg != NULL) && (flags & TCL_LEAVE_ERR_MSG)) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, msg, errMsg, -1); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", TclGetString(part1Ptr), NULL); } if (newPart2) { Tcl_DecrRefCount(part2Ptr); } return NULL; } /* * Cache the newly found variable if possible. */ if (index >= 0) { /* * An indexed local variable. */ part1Ptr->typePtr = &localVarNameType; if (part1Ptr != localName(iPtr->varFramePtr, index)) { part1Ptr->internalRep.twoPtrValue.ptr1 = localName(iPtr->varFramePtr, index); Tcl_IncrRefCount((Tcl_Obj *) part1Ptr->internalRep.twoPtrValue.ptr1); } else { part1Ptr->internalRep.twoPtrValue.ptr1 = NULL; } part1Ptr->internalRep.twoPtrValue.ptr2 = INT2PTR(index); } else { /* * At least mark part1Ptr as already parsed. */ part1Ptr->typePtr = &tclParsedVarNameType; part1Ptr->internalRep.twoPtrValue.ptr1 = NULL; part1Ptr->internalRep.twoPtrValue.ptr2 = NULL; } donePart1: while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (part2Ptr != NULL) { /* * Array element sought: look it up. */ *arrayPtrPtr = varPtr; varPtr = TclLookupArrayElement(interp, part1Ptr, part2Ptr, flags, msg, createPart1, createPart2, varPtr, -1); if (newPart2) { Tcl_DecrRefCount(part2Ptr); } } return varPtr; } /* * This flag bit should not interfere with TCL_GLOBAL_ONLY, * TCL_NAMESPACE_ONLY, or TCL_LEAVE_ERR_MSG; it signals that the variable * lookup is performed for upvar (or similar) purposes, with slightly * different rules: * - Bug #696893 - variable is either proc-local or in the current * namespace; never follow the second (global) resolution path * - Bug #631741 - do not use special namespace or interp resolvers * * It should also not collide with the (deprecated) TCL_PARSE_PART1 flag * (Bug #835020) */ #define AVOID_RESOLVERS 0x40000 /* *---------------------------------------------------------------------- * * TclLookupSimpleVar -- * * This function is used by to locate a simple variable (i.e., not an * array element) given its name. * * Results: * The return value is a pointer to the variable structure indicated by * varName, or NULL if the variable couldn't be found. If the variable * can't be found and create is 1, a new as-yet-undefined (VAR_UNDEFINED) * variable structure is created, entered into a hash table, and * returned. * * If the current CallFrame corresponds to a proc and the variable found * is one of the compiledLocals, its index is placed in *indexPtr. * Otherwise, *indexPtr will be set to (according to the needs of * TclObjLookupVar): * -1 a global reference * -2 a reference to a namespace variable * -3 a non-cachable reference, i.e., one of: * . non-indexed local var * . a reference of unknown origin; * . resolution by a namespace or interp resolver * * If the variable isn't found and creation wasn't specified, or some * other error occurs, NULL is returned and the corresponding error * message is left in *errMsgPtr. * * Note: it's possible for the variable returned to be VAR_UNDEFINED even * if create is 1 (this only causes the hash table entry to be created). * For example, the variable might be a global that has been unset but is * still referenced by a procedure, or a variable that has been unset but * it only being kept in existence (if VAR_UNDEFINED) by a trace. * * Side effects: * A new hashtable entry may be created if create is 1. * Callers must Incr varNamePtr if they plan to Decr it if create is 1. * *---------------------------------------------------------------------- */ Var * TclLookupSimpleVar( Tcl_Interp *interp, /* Interpreter to use for lookup. */ Tcl_Obj *varNamePtr, /* This is a simple variable name that could * represent a scalar or an array. */ int flags, /* Only TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * AVOID_RESOLVERS and TCL_LEAVE_ERR_MSG bits * matter. */ const int create, /* If 1, create hash table entry for varname, * if it doesn't already exist. If 0, return * error if it doesn't exist. */ const char **errMsgPtr, int *indexPtr) { Interp *iPtr = (Interp *) interp; CallFrame *varFramePtr = iPtr->varFramePtr; /* Points to the procedure call frame whose * variables are currently in use. Same as the * current procedure's frame, if any, unless * an "uplevel" is executing. */ TclVarHashTable *tablePtr; /* Points to the hashtable, if any, in which * to look up the variable. */ Tcl_Var var; /* Used to search for global names. */ Var *varPtr; /* Points to the Var structure returned for * the variable. */ Namespace *varNsPtr, *cxtNsPtr, *dummy1Ptr, *dummy2Ptr; ResolverScheme *resPtr; int isNew, i, result, varLen; const char *varName = TclGetStringFromObj(varNamePtr, &varLen); varPtr = NULL; varNsPtr = NULL; /* Set non-NULL if a nonlocal variable. */ *indexPtr = -3; if (flags & TCL_GLOBAL_ONLY) { cxtNsPtr = iPtr->globalNsPtr; } else { cxtNsPtr = iPtr->varFramePtr->nsPtr; } /* * If this namespace has a variable resolver, then give it first crack at * the variable resolution. It may return a Tcl_Var value, it may signal * to continue onward, or it may signal an error. */ if ((cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL) && !(flags & AVOID_RESOLVERS)) { resPtr = iPtr->resolverPtr; if (cxtNsPtr->varResProc) { result = cxtNsPtr->varResProc(interp, varName, (Tcl_Namespace *) cxtNsPtr, flags, &var); } else { result = TCL_CONTINUE; } while (result == TCL_CONTINUE && resPtr) { if (resPtr->varResProc) { result = resPtr->varResProc(interp, varName, (Tcl_Namespace *) cxtNsPtr, flags, &var); } resPtr = resPtr->nextPtr; } if (result == TCL_OK) { return (Var *) var; } else if (result != TCL_CONTINUE) { return NULL; } } /* * Look up varName. Look it up as either a namespace variable or as a * local variable in a procedure call frame (varFramePtr). Interpret * varName as a namespace variable if: * 1) so requested by a TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY flag, * 2) there is no active frame (we're at the global :: scope), * 3) the active frame was pushed to define the namespace context for a * "namespace eval" or "namespace inscope" command, * 4) the name has namespace qualifiers ("::"s). * Otherwise, if varName is a local variable, search first in the frame's * array of compiler-allocated local variables, then in its hashtable for * runtime-created local variables. * * If create and the variable isn't found, create the variable and, if * necessary, create varFramePtr's local var hashtable. */ if (((flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY)) != 0) || !HasLocalVars(varFramePtr) || (strstr(varName, "::") != NULL)) { const char *tail; int lookGlobal = (flags & TCL_GLOBAL_ONLY) || (cxtNsPtr == iPtr->globalNsPtr) || ((*varName == ':') && (*(varName+1) == ':')); if (lookGlobal) { *indexPtr = -1; flags = (flags | TCL_GLOBAL_ONLY) & ~TCL_NAMESPACE_ONLY; } else { if (flags & AVOID_RESOLVERS) { flags = (flags | TCL_NAMESPACE_ONLY); } if (flags & TCL_NAMESPACE_ONLY) { *indexPtr = -2; } } /* * Don't pass TCL_LEAVE_ERR_MSG, we may yet create the variable, or * otherwise generate our own error! */ varPtr = (Var *) ObjFindNamespaceVar(interp, varNamePtr, (Tcl_Namespace *) cxtNsPtr, (flags | AVOID_RESOLVERS) & ~TCL_LEAVE_ERR_MSG); if (varPtr == NULL) { Tcl_Obj *tailPtr; if (create) { /* Var wasn't found so create it. */ TclGetNamespaceForQualName(interp, varName, cxtNsPtr, flags, &varNsPtr, &dummy1Ptr, &dummy2Ptr, &tail); if (varNsPtr == NULL) { *errMsgPtr = badNamespace; return NULL; } else if (tail == NULL) { *errMsgPtr = missingName; return NULL; } if (tail != varName) { tailPtr = Tcl_NewStringObj(tail, -1); } else { tailPtr = varNamePtr; } varPtr = VarHashCreateVar(&varNsPtr->varTable, tailPtr, &isNew); if (lookGlobal) { /* * The variable was created starting from the global * namespace: a global reference is returned even if it * wasn't explicitly requested. */ *indexPtr = -1; } else { *indexPtr = -2; } } else { /* Var wasn't found and not to create it. */ *errMsgPtr = noSuchVar; return NULL; } } } else { /* Local var: look in frame varFramePtr. */ int localLen, localCt = varFramePtr->numCompiledLocals; Tcl_Obj **objPtrPtr = &varFramePtr->localCachePtr->varName0; const char *localNameStr; for (i=0 ; icompiledLocals[i]; } } } tablePtr = varFramePtr->varTablePtr; if (create) { if (tablePtr == NULL) { tablePtr = ckalloc(sizeof(TclVarHashTable)); TclInitVarHashTable(tablePtr, NULL); varFramePtr->varTablePtr = tablePtr; } varPtr = VarHashCreateVar(tablePtr, varNamePtr, &isNew); } else { varPtr = NULL; if (tablePtr != NULL) { varPtr = VarHashFindVar(tablePtr, varNamePtr); } if (varPtr == NULL) { *errMsgPtr = noSuchVar; } } } return varPtr; } /* *---------------------------------------------------------------------- * * TclLookupArrayElement -- * * This function is used to locate a variable which is in an array's * hashtable given a pointer to the array's Var structure and the * element's name. * * Results: * The return value is a pointer to the variable structure , or NULL if * the variable couldn't be found. * * If arrayPtr points to a variable that isn't an array and createPart1 * is 1, the corresponding variable will be converted to an array. * Otherwise, NULL is returned and an error message is left in the * interp's result if TCL_LEAVE_ERR_MSG is set in flags. * * If the variable is not found and createPart2 is 1, the variable is * created. Otherwise, NULL is returned and an error message is left in * the interp's result if TCL_LEAVE_ERR_MSG is set in flags. * * Note: it's possible for the variable returned to be VAR_UNDEFINED even * if createPart1 or createPart2 are 1 (these only cause the hash table * entry or array to be created). For example, the variable might be a * global that has been unset but is still referenced by a procedure, or * a variable that has been unset but it only being kept in existence (if * VAR_UNDEFINED) by a trace. * * Side effects: * The variable at arrayPtr may be converted to be an array if * createPart1 is 1. A new hashtable entry may be created if createPart2 * is 1. * When createElem is 1, callers must incr elNamePtr if they plan * to decr it. * *---------------------------------------------------------------------- */ Var * TclLookupArrayElement( Tcl_Interp *interp, /* Interpreter to use for lookup. */ Tcl_Obj *arrayNamePtr, /* This is the name of the array, or NULL if * index>= 0. */ Tcl_Obj *elNamePtr, /* Name of element within array. */ const int flags, /* Only TCL_LEAVE_ERR_MSG bit matters. */ const char *msg, /* Verb to use in error messages, e.g. "read" * or "set". Only needed if TCL_LEAVE_ERR_MSG * is set in flags. */ const int createArray, /* If 1, transform arrayName to be an array if * it isn't one yet and the transformation is * possible. If 0, return error if it isn't * already an array. */ const int createElem, /* If 1, create hash table entry for the * element, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var *arrayPtr, /* Pointer to the array's Var structure. */ int index) /* If >=0, the index of the local array. */ { int isNew; Var *varPtr; TclVarHashTable *tablePtr; Namespace *nsPtr; /* * We're dealing with an array element. Make sure the variable is an array * and look up the element (create the element if desired). */ if (TclIsVarUndefined(arrayPtr) && !TclIsVarArrayElement(arrayPtr)) { if (!createArray) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg, noSuchVar, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL); } return NULL; } /* * Make sure we are not resurrecting a namespace variable from a * deleted namespace! */ if (TclIsVarDeadHash(arrayPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg, danglingVar, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL); } return NULL; } TclSetVarArray(arrayPtr); tablePtr = ckalloc(sizeof(TclVarHashTable)); arrayPtr->value.tablePtr = tablePtr; if (TclIsVarInHash(arrayPtr) && TclGetVarNsPtr(arrayPtr)) { nsPtr = TclGetVarNsPtr(arrayPtr); } else { nsPtr = NULL; } TclInitVarHashTable(arrayPtr->value.tablePtr, nsPtr); } else if (!TclIsVarArray(arrayPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg, needArray, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL); } return NULL; } if (createElem) { varPtr = VarHashCreateVar(arrayPtr->value.tablePtr, elNamePtr, &isNew); if (isNew) { if (arrayPtr->flags & VAR_SEARCH_ACTIVE) { DeleteSearches((Interp *) interp, arrayPtr); } TclSetVarArrayElement(varPtr); } } else { varPtr = VarHashFindVar(arrayPtr->value.tablePtr, elNamePtr); if (varPtr == NULL) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg, noSuchElement, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ELEMENT", TclGetString(elNamePtr), NULL); } } } return varPtr; } /* *---------------------------------------------------------------------- * * Tcl_GetVar -- * * Return the value of a Tcl variable as a string. * * Results: * The return value points to the current value of varName as a string. * If the variable is not defined or can't be read because of a clash in * array usage then a NULL pointer is returned and an error message is * left in the interp's result if the TCL_LEAVE_ERR_MSG flag is set. * Note: the return value is only valid up until the next change to the * variable; if you depend on the value lasting longer than that, then * make yourself a private copy. * * Side effects: * None. * *---------------------------------------------------------------------- */ #undef Tcl_GetVar const char * Tcl_GetVar( Tcl_Interp *interp, /* Command interpreter in which varName is to * be looked up. */ const char *varName, /* Name of a variable in interp. */ int flags) /* OR-ed combination of TCL_GLOBAL_ONLY, * TCL_NAMESPACE_ONLY or TCL_LEAVE_ERR_MSG * bits. */ { Tcl_Obj *varNamePtr = Tcl_NewStringObj(varName, -1); Tcl_Obj *resultPtr = Tcl_ObjGetVar2(interp, varNamePtr, NULL, flags); TclDecrRefCount(varNamePtr); if (resultPtr == NULL) { return NULL; } return TclGetString(resultPtr); } /* *---------------------------------------------------------------------- * * Tcl_GetVar2 -- * * Return the value of a Tcl variable as a string, given a two-part name * consisting of array name and element within array. * * Results: * The return value points to the current value of the variable given by * part1 and part2 as a string. If the specified variable doesn't exist, * or if there is a clash in array usage, then NULL is returned and a * message will be left in the interp's result if the TCL_LEAVE_ERR_MSG * flag is set. Note: the return value is only valid up until the next * change to the variable; if you depend on the value lasting longer than * that, then make yourself a private copy. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * Tcl_GetVar2( Tcl_Interp *interp, /* Command interpreter in which variable is to * be looked up. */ const char *part1, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ const char *part2, /* If non-NULL, gives the name of an element * in the array part1. */ int flags) /* OR-ed combination of TCL_GLOBAL_ONLY, * TCL_NAMESPACE_ONLY and TCL_LEAVE_ERR_MSG * * bits. */ { Tcl_Obj *resultPtr; Tcl_Obj *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1); if (part2) { part2Ptr = Tcl_NewStringObj(part2, -1); Tcl_IncrRefCount(part2Ptr); } resultPtr = Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags); Tcl_DecrRefCount(part1Ptr); if (part2Ptr) { Tcl_DecrRefCount(part2Ptr); } if (resultPtr == NULL) { return NULL; } return TclGetString(resultPtr); } /* *---------------------------------------------------------------------- * * Tcl_GetVar2Ex -- * * Return the value of a Tcl variable as a Tcl object, given a two-part * name consisting of array name and element within array. * * Results: * The return value points to the current object value of the variable * given by part1Ptr and part2Ptr. If the specified variable doesn't * exist, or if there is a clash in array usage, then NULL is returned * and a message will be left in the interpreter's result if the * TCL_LEAVE_ERR_MSG flag is set. * * Side effects: * The ref count for the returned object is _not_ incremented to reflect * the returned reference; if you want to keep a reference to the object * you must increment its ref count yourself. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_GetVar2Ex( Tcl_Interp *interp, /* Command interpreter in which variable is to * be looked up. */ const char *part1, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ const char *part2, /* If non-NULL, gives the name of an element * in the array part1. */ int flags) /* OR-ed combination of TCL_GLOBAL_ONLY, and * TCL_LEAVE_ERR_MSG bits. */ { Tcl_Obj *resPtr, *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1); if (part2) { part2Ptr = Tcl_NewStringObj(part2, -1); Tcl_IncrRefCount(part2Ptr); } resPtr = Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags); Tcl_DecrRefCount(part1Ptr); if (part2Ptr) { Tcl_DecrRefCount(part2Ptr); } return resPtr; } /* *---------------------------------------------------------------------- * * Tcl_ObjGetVar2 -- * * Return the value of a Tcl variable as a Tcl object, given a two-part * name consisting of array name and element within array. * * Results: * The return value points to the current object value of the variable * given by part1Ptr and part2Ptr. If the specified variable doesn't * exist, or if there is a clash in array usage, then NULL is returned * and a message will be left in the interpreter's result if the * TCL_LEAVE_ERR_MSG flag is set. * * Side effects: * The ref count for the returned object is _not_ incremented to reflect * the returned reference; if you want to keep a reference to the object * you must increment its ref count yourself. * * Callers must incr part2Ptr if they plan to decr it. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_ObjGetVar2( Tcl_Interp *interp, /* Command interpreter in which variable is to * be looked up. */ register Tcl_Obj *part1Ptr, /* Points to an object holding the name of an * array (if part2 is non-NULL) or the name of * a variable. */ register Tcl_Obj *part2Ptr, /* If non-null, points to an object holding * the name of an element in the array * part1Ptr. */ int flags) /* OR-ed combination of TCL_GLOBAL_ONLY and * TCL_LEAVE_ERR_MSG bits. */ { Var *varPtr, *arrayPtr; /* * Filter to pass through only the flags this interface supports. */ flags &= (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG); varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "read", /*createPart1*/ 0, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { return NULL; } return TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, flags, -1); } /* *---------------------------------------------------------------------- * * TclPtrGetVar -- * * Return the value of a Tcl variable as a Tcl object, given the pointers * to the variable's (and possibly containing array's) VAR structure. * * Results: * The return value points to the current object value of the variable * given by varPtr. If the specified variable doesn't exist, or if there * is a clash in array usage, then NULL is returned and a message will be * left in the interpreter's result if the TCL_LEAVE_ERR_MSG flag is set. * * Side effects: * The ref count for the returned object is _not_ incremented to reflect * the returned reference; if you want to keep a reference to the object * you must increment its ref count yourself. * *---------------------------------------------------------------------- */ Tcl_Obj * TclPtrGetVar( Tcl_Interp *interp, /* Command interpreter in which variable is to * be looked up. */ register Var *varPtr, /* The variable to be read.*/ Var *arrayPtr, /* NULL for scalar variables, pointer to the * containing array otherwise. */ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element * in the array part1. */ const int flags, /* OR-ed combination of TCL_GLOBAL_ONLY, and * TCL_LEAVE_ERR_MSG bits. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { Interp *iPtr = (Interp *) interp; const char *msg; /* * Invoke any read traces that have been set for the variable. */ if ((varPtr->flags & VAR_TRACED_READ) || (arrayPtr && (arrayPtr->flags & VAR_TRACED_READ))) { if (TCL_ERROR == TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr, part2Ptr, (flags & (TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY)) | TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG), index)) { goto errorReturn; } } /* * Return the element if it's an existing scalar variable. */ if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) { return varPtr->value.objPtr; } if (flags & TCL_LEAVE_ERR_MSG) { if (TclIsVarUndefined(varPtr) && arrayPtr && !TclIsVarUndefined(arrayPtr)) { msg = noSuchElement; } else if (TclIsVarArray(varPtr)) { msg = isArray; } else { msg = noSuchVar; } TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "read", msg, index); } /* * An error. If the variable doesn't exist anymore and no-one's using it, * then free up the relevant structures and hash table entries. */ errorReturn: Tcl_SetErrorCode(interp, "TCL", "READ", "VARNAME", NULL); if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, arrayPtr); } return NULL; } /* *---------------------------------------------------------------------- * * Tcl_SetObjCmd -- * * This function is invoked to process the "set" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result value. * * Side effects: * A variable's value may be changed. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_SetObjCmd( ClientData dummy, /* Not used. */ register Tcl_Interp *interp,/* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *varValueObj; if (objc == 2) { varValueObj = Tcl_ObjGetVar2(interp, objv[1], NULL,TCL_LEAVE_ERR_MSG); if (varValueObj == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, varValueObj); return TCL_OK; } else if (objc == 3) { varValueObj = Tcl_ObjSetVar2(interp, objv[1], NULL, objv[2], TCL_LEAVE_ERR_MSG); if (varValueObj == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, varValueObj); return TCL_OK; } else { Tcl_WrongNumArgs(interp, 1, objv, "varName ?newValue?"); return TCL_ERROR; } } /* *---------------------------------------------------------------------- * * Tcl_SetVar -- * * Change the value of a variable. * * Results: * Returns a pointer to the malloc'ed string which is the character * representation of the variable's new value. The caller must not modify * this string. If the write operation was disallowed then NULL is * returned; if the TCL_LEAVE_ERR_MSG flag is set, then an explanatory * message will be left in the interp's result. Note that the returned * string may not be the same as newValue; this is because variable * traces may modify the variable's value. * * Side effects: * If varName is defined as a local or global variable in interp, its * value is changed to newValue. If varName isn't currently defined, then * a new global variable by that name is created. * *---------------------------------------------------------------------- */ #undef Tcl_SetVar const char * Tcl_SetVar( Tcl_Interp *interp, /* Command interpreter in which varName is to * be looked up. */ const char *varName, /* Name of a variable in interp. */ const char *newValue, /* New value for varName. */ int flags) /* Various flags that tell how to set value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, * TCL_LEAVE_ERR_MSG. */ { Tcl_Obj *varValuePtr, *varNamePtr = Tcl_NewStringObj(varName, -1); Tcl_IncrRefCount(varNamePtr); varValuePtr = Tcl_ObjSetVar2(interp, varNamePtr, NULL, Tcl_NewStringObj(newValue, -1), flags); Tcl_DecrRefCount(varNamePtr); if (varValuePtr == NULL) { return NULL; } return TclGetString(varValuePtr); } /* *---------------------------------------------------------------------- * * Tcl_SetVar2 -- * * Given a two-part variable name, which may refer either to a scalar * variable or an element of an array, change the value of the variable. * If the named scalar or array or element doesn't exist then create one. * * Results: * Returns a pointer to the malloc'ed string which is the character * representation of the variable's new value. The caller must not modify * this string. If the write operation was disallowed because an array * was expected but not found (or vice versa), then NULL is returned; if * the TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will be * left in the interp's result. Note that the returned string may not be * the same as newValue; this is because variable traces may modify the * variable's value. * * Side effects: * The value of the given variable is set. If either the array or the * entry didn't exist then a new one is created. * *---------------------------------------------------------------------- */ const char * Tcl_SetVar2( Tcl_Interp *interp, /* Command interpreter in which variable is to * be looked up. */ const char *part1, /* If part2 is NULL, this is name of scalar * variable. Otherwise it is the name of an * array. */ const char *part2, /* Name of an element within an array, or * NULL. */ const char *newValue, /* New value for variable. */ int flags) /* Various flags that tell how to set value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, or * TCL_LEAVE_ERR_MSG. */ { Tcl_Obj *varValuePtr = Tcl_SetVar2Ex(interp, part1, part2, Tcl_NewStringObj(newValue, -1), flags); if (varValuePtr == NULL) { return NULL; } return TclGetString(varValuePtr); } /* *---------------------------------------------------------------------- * * Tcl_SetVar2Ex -- * * Given a two-part variable name, which may refer either to a scalar * variable or an element of an array, change the value of the variable * to a new Tcl object value. If the named scalar or array or element * doesn't exist then create one. * * Results: * Returns a pointer to the Tcl_Obj holding the new value of the * variable. If the write operation was disallowed because an array was * expected but not found (or vice versa), then NULL is returned; if the * TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will be * left in the interpreter's result. Note that the returned object may * not be the same one referenced by newValuePtr; this is because * variable traces may modify the variable's value. * * Side effects: * The value of the given variable is set. If either the array or the * entry didn't exist then a new variable is created. * * The reference count is decremented for any old value of the variable * and incremented for its new value. If the new value for the variable * is not the same one referenced by newValuePtr (perhaps as a result of * a variable trace), then newValuePtr's ref count is left unchanged by * Tcl_SetVar2Ex. newValuePtr's ref count is also left unchanged if we * are appending it as a string value: that is, if "flags" includes * TCL_APPEND_VALUE but not TCL_LIST_ELEMENT. * * The reference count for the returned object is _not_ incremented: if * you want to keep a reference to the object you must increment its ref * count yourself. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_SetVar2Ex( Tcl_Interp *interp, /* Command interpreter in which variable is to * be found. */ const char *part1, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ const char *part2, /* If non-NULL, gives the name of an element * in the array part1. */ Tcl_Obj *newValuePtr, /* New value for variable. */ int flags) /* Various flags that tell how to set value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT or * TCL_LEAVE_ERR_MSG. */ { Tcl_Obj *resPtr, *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1); Tcl_IncrRefCount(part1Ptr); if (part2) { part2Ptr = Tcl_NewStringObj(part2, -1); Tcl_IncrRefCount(part2Ptr); } resPtr = Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, newValuePtr, flags); Tcl_DecrRefCount(part1Ptr); if (part2Ptr) { Tcl_DecrRefCount(part2Ptr); } return resPtr; } /* *---------------------------------------------------------------------- * * Tcl_ObjSetVar2 -- * * This function is the same as Tcl_SetVar2Ex above, except the variable * names are passed in Tcl object instead of strings. * * Results: * Returns a pointer to the Tcl_Obj holding the new value of the * variable. If the write operation was disallowed because an array was * expected but not found (or vice versa), then NULL is returned; if the * TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will be * left in the interpreter's result. Note that the returned object may * not be the same one referenced by newValuePtr; this is because * variable traces may modify the variable's value. * * Side effects: * The value of the given variable is set. If either the array or the * entry didn't exist then a new variable is created. * Callers must Incr part1Ptr if they plan to Decr it. * Callers must Incr part2Ptr if they plan to Decr it. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_ObjSetVar2( Tcl_Interp *interp, /* Command interpreter in which variable is to * be found. */ register Tcl_Obj *part1Ptr, /* Points to an object holding the name of an * array (if part2 is non-NULL) or the name of * a variable. */ register Tcl_Obj *part2Ptr, /* If non-NULL, points to an object holding * the name of an element in the array * part1Ptr. */ Tcl_Obj *newValuePtr, /* New value for variable. */ int flags) /* Various flags that tell how to set value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, or * TCL_LEAVE_ERR_MSG. */ { Var *varPtr, *arrayPtr; /* * Filter to pass through only the flags this interface supports. */ flags &= (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG |TCL_APPEND_VALUE|TCL_LIST_ELEMENT); varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { if (newValuePtr->refCount == 0) { Tcl_DecrRefCount(newValuePtr); } return NULL; } return TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, newValuePtr, flags, -1); } /* *---------------------------------------------------------------------- * * TclPtrSetVar -- * * This function is the same as Tcl_SetVar2Ex above, except that it * requires pointers to the variable's Var structs in addition to the * variable names. * * Results: * Returns a pointer to the Tcl_Obj holding the new value of the * variable. If the write operation was disallowed because an array was * expected but not found (or vice versa), then NULL is returned; if the * TCL_LEAVE_ERR_MSG flag is set, then an explanatory message will be * left in the interpreter's result. Note that the returned object may * not be the same one referenced by newValuePtr; this is because * variable traces may modify the variable's value. * * Side effects: * The value of the given variable is set. If either the array or the * entry didn't exist then a new variable is created. * *---------------------------------------------------------------------- */ Tcl_Obj * TclPtrSetVar( Tcl_Interp *interp, /* Command interpreter in which variable is to * be looked up. */ register Var *varPtr, /* Reference to the variable to set. */ Var *arrayPtr, /* Reference to the array containing the * variable, or NULL if the variable is a * scalar. */ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or * the name of a variable. NULL if the 'index' * parameter is >= 0 */ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element * in the array part1. */ Tcl_Obj *newValuePtr, /* New value for variable. */ const int flags, /* OR-ed combination of TCL_GLOBAL_ONLY, and * TCL_LEAVE_ERR_MSG bits. */ int index) /* Index of local var where part1 is to be * found. */ { Interp *iPtr = (Interp *) interp; Tcl_Obj *oldValuePtr; Tcl_Obj *resultPtr = NULL; int result; int cleanupOnEarlyError = (newValuePtr->refCount == 0); /* * If the variable is in a hashtable and its hPtr field is NULL, then we * may have an upvar to an array element where the array was deleted or an * upvar to a namespace variable whose namespace was deleted. Generate an * error (allowing the variable to be reset would screw up our storage * allocation and is meaningless anyway). */ if (TclIsVarDeadHash(varPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { if (TclIsVarArrayElement(varPtr)) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", danglingElement, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ELEMENT", NULL); } else { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", danglingVar, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", NULL); } } goto earlyError; } /* * It's an error to try to set an array variable itself. */ if (TclIsVarArray(varPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", isArray,index); Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL); } goto earlyError; } /* * Invoke any read traces that have been set for the variable if it is * requested. This was done for INST_LAPPEND_* but that was inconsistent * with the non-bc instruction, and would cause failures trying to * lappend to any non-existing ::env var, which is inconsistent with * documented behavior. [Bug #3057639]. */ if ((flags & TCL_TRACE_READS) && ((varPtr->flags & VAR_TRACED_READ) || (arrayPtr && (arrayPtr->flags & VAR_TRACED_READ)))) { if (TCL_ERROR == TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr, part2Ptr, TCL_TRACE_READS, (flags & TCL_LEAVE_ERR_MSG), index)) { goto earlyError; } } /* * Set the variable's new value. If appending, append the new value to the * variable, either as a list element or as a string. Also, if appending, * then if the variable's old value is unshared we can modify it directly, * otherwise we must create a new copy to modify: this is "copy on write". */ oldValuePtr = varPtr->value.objPtr; if (flags & TCL_LIST_ELEMENT && !(flags & TCL_APPEND_VALUE)) { varPtr->value.objPtr = NULL; } if (flags & (TCL_APPEND_VALUE|TCL_LIST_ELEMENT)) { if (flags & TCL_LIST_ELEMENT) { /* Append list element. */ if (oldValuePtr == NULL) { TclNewObj(oldValuePtr); varPtr->value.objPtr = oldValuePtr; Tcl_IncrRefCount(oldValuePtr); /* Since var is referenced. */ } else if (Tcl_IsShared(oldValuePtr)) { varPtr->value.objPtr = Tcl_DuplicateObj(oldValuePtr); TclDecrRefCount(oldValuePtr); oldValuePtr = varPtr->value.objPtr; Tcl_IncrRefCount(oldValuePtr); /* Since var is referenced. */ } result = Tcl_ListObjAppendElement(interp, oldValuePtr, newValuePtr); if (result != TCL_OK) { goto earlyError; } } else { /* Append string. */ /* * We append newValuePtr's bytes but don't change its ref count. */ if (oldValuePtr == NULL) { varPtr->value.objPtr = newValuePtr; Tcl_IncrRefCount(newValuePtr); } else { if (Tcl_IsShared(oldValuePtr)) { /* Append to copy. */ varPtr->value.objPtr = Tcl_DuplicateObj(oldValuePtr); TclContinuationsCopy(varPtr->value.objPtr, oldValuePtr); TclDecrRefCount(oldValuePtr); oldValuePtr = varPtr->value.objPtr; Tcl_IncrRefCount(oldValuePtr); /* Since var is ref */ } Tcl_AppendObjToObj(oldValuePtr, newValuePtr); if (newValuePtr->refCount == 0) { Tcl_DecrRefCount(newValuePtr); } } } } else if (newValuePtr != oldValuePtr) { /* * In this case we are replacing the value, so we don't need to do * more than swap the objects. */ varPtr->value.objPtr = newValuePtr; Tcl_IncrRefCount(newValuePtr); /* Var is another ref. */ if (oldValuePtr != NULL) { TclDecrRefCount(oldValuePtr); /* Discard old value. */ } } /* * Invoke any write traces for the variable. */ if ((varPtr->flags & VAR_TRACED_WRITE) || (arrayPtr && (arrayPtr->flags & VAR_TRACED_WRITE))) { if (TCL_ERROR == TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr, part2Ptr, (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) | TCL_TRACE_WRITES, (flags & TCL_LEAVE_ERR_MSG), index)) { goto cleanup; } } /* * Return the variable's value unless the variable was changed in some * gross way by a trace (e.g. it was unset and then recreated as an * array). */ if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) { return varPtr->value.objPtr; } /* * A trace changed the value in some gross way. Return an empty string * object. */ resultPtr = iPtr->emptyObjPtr; /* * If the variable doesn't exist anymore and no-one's using it, then free * up the relevant structures and hash table entries. */ cleanup: if (resultPtr == NULL) { Tcl_SetErrorCode(interp, "TCL", "WRITE", "VARNAME", NULL); } if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, arrayPtr); } return resultPtr; earlyError: if (cleanupOnEarlyError) { Tcl_DecrRefCount(newValuePtr); } goto cleanup; } /* *---------------------------------------------------------------------- * * TclIncrObjVar2 -- * * Given a two-part variable name, which may refer either to a scalar * variable or an element of an array, increment the Tcl object value of * the variable by a specified Tcl_Obj increment value. * * Results: * Returns a pointer to the Tcl_Obj holding the new value of the * variable. If the specified variable doesn't exist, or there is a clash * in array usage, or an error occurs while executing variable traces, * then NULL is returned and a message will be left in the interpreter's * result. * * Side effects: * The value of the given variable is incremented by the specified * amount. If either the array or the entry didn't exist then a new * variable is created. The ref count for the returned object is _not_ * incremented to reflect the returned reference; if you want to keep a * reference to the object you must increment its ref count yourself. * Callers must Incr part1Ptr if they plan to Decr it. * Callers must Incr part2Ptr if they plan to Decr it. * *---------------------------------------------------------------------- */ Tcl_Obj * TclIncrObjVar2( Tcl_Interp *interp, /* Command interpreter in which variable is to * be found. */ Tcl_Obj *part1Ptr, /* Points to an object holding the name of an * array (if part2 is non-NULL) or the name of * a variable. */ Tcl_Obj *part2Ptr, /* If non-null, points to an object holding * the name of an element in the array * part1Ptr. */ Tcl_Obj *incrPtr, /* Amount to be added to variable. */ int flags) /* Various flags that tell how to incr value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, * TCL_LEAVE_ERR_MSG. */ { Var *varPtr, *arrayPtr; varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "read", 1, 1, &arrayPtr); if (varPtr == NULL) { Tcl_AddErrorInfo(interp, "\n (reading value of variable to increment)"); return NULL; } return TclPtrIncrObjVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, incrPtr, flags, -1); } /* *---------------------------------------------------------------------- * * TclPtrIncrObjVar -- * * Given the pointers to a variable and possible containing array, * increment the Tcl object value of the variable by a Tcl_Obj increment. * * Results: * Returns a pointer to the Tcl_Obj holding the new value of the * variable. If the specified variable doesn't exist, or there is a clash * in array usage, or an error occurs while executing variable traces, * then NULL is returned and a message will be left in the interpreter's * result. * * Side effects: * The value of the given variable is incremented by the specified * amount. If either the array or the entry didn't exist then a new * variable is created. The ref count for the returned object is _not_ * incremented to reflect the returned reference; if you want to keep a * reference to the object you must increment its ref count yourself. * *---------------------------------------------------------------------- */ Tcl_Obj * TclPtrIncrObjVar( Tcl_Interp *interp, /* Command interpreter in which variable is to * be found. */ Var *varPtr, /* Reference to the variable to set. */ Var *arrayPtr, /* Reference to the array containing the * variable, or NULL if the variable is a * scalar. */ Tcl_Obj *part1Ptr, /* Points to an object holding the name of an * array (if part2 is non-NULL) or the name of * a variable. */ Tcl_Obj *part2Ptr, /* If non-null, points to an object holding * the name of an element in the array * part1Ptr. */ Tcl_Obj *incrPtr, /* Increment value. */ /* TODO: Which of these flag values really make sense? */ const int flags, /* Various flags that tell how to incr value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, * TCL_LEAVE_ERR_MSG. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { register Tcl_Obj *varValuePtr; if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)++; } varValuePtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, flags, index); if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)--; } if (varValuePtr == NULL) { varValuePtr = Tcl_NewIntObj(0); } if (Tcl_IsShared(varValuePtr)) { /* Copy on write */ varValuePtr = Tcl_DuplicateObj(varValuePtr); if (TCL_OK == TclIncrObj(interp, varValuePtr, incrPtr)) { return TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, varValuePtr, flags, index); } else { Tcl_DecrRefCount(varValuePtr); return NULL; } } else { /* Unshared - can Incr in place */ if (TCL_OK == TclIncrObj(interp, varValuePtr, incrPtr)) { /* * This seems dumb to write the incremeted value into the var * after we just adjusted the value in place, but the spec for * [incr] requires that write traces fire, and making this call * is the way to make that happen. */ return TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, varValuePtr, flags, index); } else { return NULL; } } } /* *---------------------------------------------------------------------- * * Tcl_UnsetVar -- * * Delete a variable, so that it may not be accessed anymore. * * Results: * Returns TCL_OK if the variable was successfully deleted, TCL_ERROR if * the variable can't be unset. In the event of an error, if the * TCL_LEAVE_ERR_MSG flag is set then an error message is left in the * interp's result. * * Side effects: * If varName is defined as a local or global variable in interp, it is * deleted. * *---------------------------------------------------------------------- */ #undef Tcl_UnsetVar int Tcl_UnsetVar( Tcl_Interp *interp, /* Command interpreter in which varName is to * be looked up. */ const char *varName, /* Name of a variable in interp. May be either * a scalar name or an array name or an * element in an array. */ int flags) /* OR-ed combination of any of * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY or * TCL_LEAVE_ERR_MSG. */ { int result; Tcl_Obj *varNamePtr; varNamePtr = Tcl_NewStringObj(varName, -1); Tcl_IncrRefCount(varNamePtr); /* * Filter to pass through only the flags this interface supports. */ flags &= (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG); result = TclObjUnsetVar2(interp, varNamePtr, NULL, flags); Tcl_DecrRefCount(varNamePtr); return result; } /* *---------------------------------------------------------------------- * * Tcl_UnsetVar2 -- * * Delete a variable, given a 2-part name. * * Results: * Returns TCL_OK if the variable was successfully deleted, TCL_ERROR if * the variable can't be unset. In the event of an error, if the * TCL_LEAVE_ERR_MSG flag is set then an error message is left in the * interp's result. * * Side effects: * If part1 and part2 indicate a local or global variable in interp, it * is deleted. If part1 is an array name and part2 is NULL, then the * whole array is deleted. * *---------------------------------------------------------------------- */ int Tcl_UnsetVar2( Tcl_Interp *interp, /* Command interpreter in which varName is to * be looked up. */ const char *part1, /* Name of variable or array. */ const char *part2, /* Name of element within array or NULL. */ int flags) /* OR-ed combination of any of * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_LEAVE_ERR_MSG. */ { int result; Tcl_Obj *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1); if (part2) { part2Ptr = Tcl_NewStringObj(part2, -1); } /* * Filter to pass through only the flags this interface supports. */ flags &= (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG); result = TclObjUnsetVar2(interp, part1Ptr, part2Ptr, flags); Tcl_DecrRefCount(part1Ptr); if (part2Ptr) { Tcl_DecrRefCount(part2Ptr); } return result; } /* *---------------------------------------------------------------------- * * TclObjUnsetVar2 -- * * Delete a variable, given a 2-object name. * * Results: * Returns TCL_OK if the variable was successfully deleted, TCL_ERROR if * the variable can't be unset. In the event of an error, if the * TCL_LEAVE_ERR_MSG flag is set then an error message is left in the * interp's result. * * Side effects: * If part1ptr and part2Ptr indicate a local or global variable in * interp, it is deleted. If part1Ptr is an array name and part2Ptr is * NULL, then the whole array is deleted. * *---------------------------------------------------------------------- */ int TclObjUnsetVar2( Tcl_Interp *interp, /* Command interpreter in which varName is to * be looked up. */ Tcl_Obj *part1Ptr, /* Name of variable or array. */ Tcl_Obj *part2Ptr, /* Name of element within array or NULL. */ int flags) /* OR-ed combination of any of * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_LEAVE_ERR_MSG. */ { Var *varPtr, *arrayPtr; varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "unset", /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); if (varPtr == NULL) { return TCL_ERROR; } return TclPtrUnsetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, flags, -1); } /* *---------------------------------------------------------------------- * * TclPtrUnsetVar -- * * Delete a variable, given the pointers to the variable's (and possibly * containing array's) VAR structure. * * Results: * Returns TCL_OK if the variable was successfully deleted, TCL_ERROR if * the variable can't be unset. In the event of an error, if the * TCL_LEAVE_ERR_MSG flag is set then an error message is left in the * interp's result. * * Side effects: * If varPtr and arrayPtr indicate a local or global variable in interp, * it is deleted. If varPtr is an array reference and part2Ptr is NULL, * then the whole array is deleted. * *---------------------------------------------------------------------- */ int TclPtrUnsetVar( Tcl_Interp *interp, /* Command interpreter in which varName is to * be looked up. */ register Var *varPtr, /* The variable to be unset. */ Var *arrayPtr, /* NULL for scalar variables, pointer to the * containing array otherwise. */ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element * in the array part1. */ const int flags, /* OR-ed combination of any of * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_LEAVE_ERR_MSG. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { Interp *iPtr = (Interp *) interp; int result = (TclIsVarUndefined(varPtr)? TCL_ERROR : TCL_OK); /* * Keep the variable alive until we're done with it. We used to * increase/decrease the refCount for each operation, making it hard to * find [Bug 735335] - caused by unsetting the variable whose value was * the variable's name. */ if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)++; } UnsetVarStruct(varPtr, arrayPtr, iPtr, part1Ptr, part2Ptr, flags, index); /* * It's an error to unset an undefined variable. */ if (result != TCL_OK) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "unset", ((arrayPtr == NULL) ? noSuchVar : noSuchElement), index); Tcl_SetErrorCode(interp, "TCL", "UNSET", "VARNAME", NULL); } } /* * Finally, if the variable is truly not in use then free up its Var * structure and remove it from its hash table, if any. The ref count of * its value object, if any, was decremented above. */ if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)--; CleanupVar(varPtr, arrayPtr); } return result; } /* *---------------------------------------------------------------------- * * UnsetVarStruct -- * * Unset and delete a variable. This does the internal work for * TclObjUnsetVar2 and TclDeleteNamespaceVars, which call here for each * variable to be unset and deleted. * * Results: * None. * * Side effects: * If the arguments indicate a local or global variable in iPtr, it is * unset and deleted. * *---------------------------------------------------------------------- */ static void UnsetVarStruct( Var *varPtr, Var *arrayPtr, Interp *iPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags, int index) { Var dummyVar; int traced = TclIsVarTraced(varPtr) || (arrayPtr && (arrayPtr->flags & VAR_TRACED_UNSET)); if (arrayPtr && (arrayPtr->flags & VAR_SEARCH_ACTIVE)) { DeleteSearches(iPtr, arrayPtr); } else if (varPtr->flags & VAR_SEARCH_ACTIVE) { DeleteSearches(iPtr, varPtr); } /* * The code below is tricky, because of the possibility that a trace * function might try to access a variable being deleted. To handle this * situation gracefully, do things in three steps: * 1. Copy the contents of the variable to a dummy variable structure, and * mark the original Var structure as undefined. * 2. Invoke traces and clean up the variable, using the dummy copy. * 3. If at the end of this the original variable is still undefined and * has no outstanding references, then delete it (but it could have * gotten recreated by a trace). */ dummyVar = *varPtr; dummyVar.flags &= ~VAR_ALL_HASH; TclSetVarUndefined(varPtr); /* * Call trace functions for the variable being deleted. Then delete its * traces. Be sure to abort any other traces for the variable that are * still pending. Special tricks: * 1. We need to increment varPtr's refCount around this: TclCallVarTraces * will use dummyVar so it won't increment varPtr's refCount itself. * 2. Turn off the VAR_TRACE_ACTIVE flag in dummyVar: we want to call * unset traces even if other traces are pending. */ if (traced) { VarTrace *tracePtr = NULL; Tcl_HashEntry *tPtr; if (TclIsVarTraced(&dummyVar)) { /* * Transfer any existing traces on var, IF there are unset traces. * Otherwise just delete them. */ int isNew; tPtr = Tcl_FindHashEntry(&iPtr->varTraces, varPtr); tracePtr = Tcl_GetHashValue(tPtr); varPtr->flags &= ~VAR_ALL_TRACES; Tcl_DeleteHashEntry(tPtr); if (dummyVar.flags & VAR_TRACED_UNSET) { tPtr = Tcl_CreateHashEntry(&iPtr->varTraces, &dummyVar, &isNew); Tcl_SetHashValue(tPtr, tracePtr); } } if ((dummyVar.flags & VAR_TRACED_UNSET) || (arrayPtr && (arrayPtr->flags & VAR_TRACED_UNSET))) { dummyVar.flags &= ~VAR_TRACE_ACTIVE; TclObjCallVarTraces(iPtr, arrayPtr, &dummyVar, part1Ptr, part2Ptr, (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) | TCL_TRACE_UNSETS, /* leaveErrMsg */ 0, index); /* * The traces that we just called may have triggered a change in * the set of traces. If so, reload the traces to manipulate. */ tracePtr = NULL; if (TclIsVarTraced(&dummyVar)) { tPtr = Tcl_FindHashEntry(&iPtr->varTraces, &dummyVar); if (tPtr) { tracePtr = Tcl_GetHashValue(tPtr); Tcl_DeleteHashEntry(tPtr); } } } if (tracePtr) { ActiveVarTrace *activePtr; while (tracePtr) { VarTrace *prevPtr = tracePtr; tracePtr = tracePtr->nextPtr; prevPtr->nextPtr = NULL; Tcl_EventuallyFree(prevPtr, TCL_DYNAMIC); } for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL; activePtr = activePtr->nextPtr) { if (activePtr->varPtr == varPtr) { activePtr->nextTracePtr = NULL; } } dummyVar.flags &= ~VAR_ALL_TRACES; } } if (TclIsVarScalar(&dummyVar) && (dummyVar.value.objPtr != NULL)) { /* * Decrement the ref count of the var's value. */ Tcl_Obj *objPtr = dummyVar.value.objPtr; TclDecrRefCount(objPtr); } else if (TclIsVarArray(&dummyVar)) { /* * If the variable is an array, delete all of its elements. This must * be done after calling and deleting the traces on the array, above * (that's the way traces are defined). If the array name is not * present and is required for a trace on some element, it will be * computed at DeleteArray. */ DeleteArray(iPtr, part1Ptr, (Var *) &dummyVar, (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY)) | TCL_TRACE_UNSETS, index); } else if (TclIsVarLink(&dummyVar)) { /* * For global/upvar variables referenced in procedures, decrement the * reference count on the variable referred to, and free the * referenced variable if it's no longer needed. */ Var *linkPtr = dummyVar.value.linkPtr; if (TclIsVarInHash(linkPtr)) { VarHashRefCount(linkPtr)--; CleanupVar(linkPtr, NULL); } } /* * If the variable was a namespace variable, decrement its reference * count. */ TclClearVarNamespaceVar(varPtr); } /* *---------------------------------------------------------------------- * * Tcl_UnsetObjCmd -- * * This object-based function is invoked to process the "unset" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result value. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_UnsetObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register int i, flags = TCL_LEAVE_ERR_MSG; register const char *name; if (objc == 1) { /* * Do nothing if no arguments supplied, so as to match command * documentation. */ return TCL_OK; } /* * Simple, restrictive argument parsing. The only options are -- and * -nocomplain (which must come first and be given exactly to be an * option). */ i = 1; name = TclGetString(objv[i]); if (name[0] == '-') { if (strcmp("-nocomplain", name) == 0) { i++; if (i == objc) { return TCL_OK; } flags = 0; name = TclGetString(objv[i]); } if (strcmp("--", name) == 0) { i++; } } for (; i < objc; i++) { if ((TclObjUnsetVar2(interp, objv[i], NULL, flags) != TCL_OK) && (flags == TCL_LEAVE_ERR_MSG)) { return TCL_ERROR; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_AppendObjCmd -- * * This object-based function is invoked to process the "append" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result value. * * Side effects: * A variable's value may be changed. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_AppendObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Var *varPtr, *arrayPtr; register Tcl_Obj *varValuePtr = NULL; /* Initialized to avoid compiler warning. */ int i; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "varName ?value ...?"); return TCL_ERROR; } if (objc == 2) { varValuePtr = Tcl_ObjGetVar2(interp, objv[1], NULL,TCL_LEAVE_ERR_MSG); if (varValuePtr == NULL) { return TCL_ERROR; } } else { varPtr = TclObjLookupVarEx(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG, "set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { return TCL_ERROR; } for (i=2 ; iemptyObjPtr)) { return TCL_ERROR; } } } Tcl_SetObjResult(interp, varValuePtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_LappendObjCmd -- * * This object-based function is invoked to process the "lappend" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result value. * * Side effects: * A variable's value may be changed. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_LappendObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *varValuePtr, *newValuePtr; int numElems, createdNewObj; Var *varPtr, *arrayPtr; int result; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "varName ?value ...?"); return TCL_ERROR; } if (objc == 2) { newValuePtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0); if (newValuePtr == NULL) { /* * The variable doesn't exist yet. Just create it with an empty * initial value. */ TclNewObj(varValuePtr); newValuePtr = Tcl_ObjSetVar2(interp, objv[1], NULL, varValuePtr, TCL_LEAVE_ERR_MSG); if (newValuePtr == NULL) { return TCL_ERROR; } } else { result = TclListObjLength(interp, newValuePtr, &numElems); if (result != TCL_OK) { return result; } } } else { /* * We have arguments to append. We used to call Tcl_SetVar2 to append * each argument one at a time to ensure that traces were run for each * append step. We now append the arguments all at once because it's * faster. Note that a read trace and a write trace for the variable * will now each only be called once. Also, if the variable's old * value is unshared we modify it directly, otherwise we create a new * copy to modify: this is "copy on write". */ createdNewObj = 0; /* * Protect the variable pointers around the TclPtrGetVar call * to insure that they remain valid even if the variable was undefined * and unused. */ varPtr = TclObjLookupVarEx(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG, "set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { return TCL_ERROR; } if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)++; } if (arrayPtr && TclIsVarInHash(arrayPtr)) { VarHashRefCount(arrayPtr)++; } varValuePtr = TclPtrGetVar(interp, varPtr, arrayPtr, objv[1], NULL, TCL_LEAVE_ERR_MSG, -1); if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)--; } if (arrayPtr && TclIsVarInHash(arrayPtr)) { VarHashRefCount(arrayPtr)--; } if (varValuePtr == NULL) { /* * We couldn't read the old value: either the var doesn't yet * exist or it's an array element. If it's new, we will try to * create it with Tcl_ObjSetVar2 below. */ TclNewObj(varValuePtr); createdNewObj = 1; } else if (Tcl_IsShared(varValuePtr)) { varValuePtr = Tcl_DuplicateObj(varValuePtr); createdNewObj = 1; } result = TclListObjLength(interp, varValuePtr, &numElems); if (result == TCL_OK) { result = Tcl_ListObjReplace(interp, varValuePtr, numElems, 0, (objc-2), (objv+2)); } if (result != TCL_OK) { if (createdNewObj) { TclDecrRefCount(varValuePtr); /* Free unneeded obj. */ } return result; } /* * Now store the list object back into the variable. If there is an * error setting the new value, decrement its ref count if it was new * and we didn't create the variable. */ newValuePtr = TclPtrSetVar(interp, varPtr, arrayPtr, objv[1], NULL, varValuePtr, TCL_LEAVE_ERR_MSG, -1); if (newValuePtr == NULL) { return TCL_ERROR; } } /* * Set the interpreter's object result to refer to the variable's value * object. */ Tcl_SetObjResult(interp, newValuePtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclArraySet -- * * Set the elements of an array. If there are no elements to set, create * an empty array. This routine is used by the Tcl_ArrayObjCmd and by the * TclSetupEnv routine. * * Results: * A standard Tcl result object. * * Side effects: * A variable will be created if one does not already exist. * Callers must Incr arrayNameObj if they pland to Decr it. * *---------------------------------------------------------------------- */ int TclArraySet( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *arrayNameObj, /* The array name. */ Tcl_Obj *arrayElemObj) /* The array elements list or dict. If this is * NULL, create an empty array. */ { Var *varPtr, *arrayPtr; int result, i; varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, /*flags*/ TCL_LEAVE_ERR_MSG, /*msg*/ "set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { return TCL_ERROR; } if (arrayPtr) { CleanupVar(varPtr, arrayPtr); TclObjVarErrMsg(interp, arrayNameObj, NULL, "set", needArray, -1); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", TclGetString(arrayNameObj), NULL); return TCL_ERROR; } if (arrayElemObj == NULL) { goto ensureArray; } /* * Install the contents of the dictionary or list into the array. */ if (arrayElemObj->typePtr == &tclDictType) { Tcl_Obj *keyPtr, *valuePtr; Tcl_DictSearch search; int done; if (Tcl_DictObjSize(interp, arrayElemObj, &done) != TCL_OK) { return TCL_ERROR; } if (done == 0) { /* * Empty, so we'll just force the array to be properly existing * instead. */ goto ensureArray; } /* * Don't need to look at result of Tcl_DictObjFirst as we've just * successfully used a dictionary operation on the same object. */ for (Tcl_DictObjFirst(interp, arrayElemObj, &search, &keyPtr, &valuePtr, &done) ; !done ; Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done)) { /* * At this point, it would be nice if the key was directly usable * by the array. This isn't the case though. */ Var *elemVarPtr = TclLookupArrayElement(interp, arrayNameObj, keyPtr, TCL_LEAVE_ERR_MSG, "set", 1, 1, varPtr, -1); if ((elemVarPtr == NULL) || (TclPtrSetVar(interp, elemVarPtr, varPtr, arrayNameObj, keyPtr, valuePtr, TCL_LEAVE_ERR_MSG, -1) == NULL)) { Tcl_DictObjDone(&search); return TCL_ERROR; } } return TCL_OK; } else { /* * Not a dictionary, so assume (and convert to, for backward- * -compatability reasons) a list. */ int elemLen; Tcl_Obj **elemPtrs, *copyListObj; result = TclListObjGetElements(interp, arrayElemObj, &elemLen, &elemPtrs); if (result != TCL_OK) { return result; } if (elemLen & 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "list must have an even number of elements", -1)); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "FORMAT", NULL); return TCL_ERROR; } if (elemLen == 0) { goto ensureArray; } /* * We needn't worry about traces invalidating arrayPtr: should that be * the case, TclPtrSetVar will return NULL so that we break out of the * loop and return an error. */ copyListObj = TclListObjCopy(NULL, arrayElemObj); for (i=0 ; ivalue.tablePtr = ckalloc(sizeof(TclVarHashTable)); TclInitVarHashTable(varPtr->value.tablePtr, TclGetVarNsPtr(varPtr)); return TCL_OK; } /* *---------------------------------------------------------------------- * * ArrayStartSearchCmd -- * * This object-based function is invoked to process the "array * startsearch" Tcl command. See the user documentation for details on * what it does. * * Results: * A standard Tcl result object. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ArrayStartSearchCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_HashEntry *hPtr; Tcl_Obj *varNameObj; int isNew; ArraySearch *searchPtr; const char *varName; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName"); return TCL_ERROR; } varNameObj = objv[1]; /* * Locate the array variable. */ varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); varName = TclGetString(varNameObj); /* * Special array trace used to keep the env array in sync for array names, * array get, etc. */ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { return TCL_ERROR; } } /* * Verify that it is indeed an array variable. This test comes after the * traces - the variable may actually become an array as an effect of said * traces. */ if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't an array", varName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", varName, NULL); return TCL_ERROR; } /* * Make a new array search with a free name. */ searchPtr = ckalloc(sizeof(ArraySearch)); hPtr = Tcl_CreateHashEntry(&iPtr->varSearches, varPtr, &isNew); if (isNew) { searchPtr->id = 1; varPtr->flags |= VAR_SEARCH_ACTIVE; searchPtr->nextPtr = NULL; } else { searchPtr->id = ((ArraySearch *) Tcl_GetHashValue(hPtr))->id + 1; searchPtr->nextPtr = Tcl_GetHashValue(hPtr); } searchPtr->varPtr = varPtr; searchPtr->nextEntry = VarHashFirstEntry(varPtr->value.tablePtr, &searchPtr->search); Tcl_SetHashValue(hPtr, searchPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf("s-%d-%s", searchPtr->id, varName)); return TCL_OK; } /* *---------------------------------------------------------------------- * * ArrayAnyMoreCmd -- * * This object-based function is invoked to process the "array anymore" * Tcl command. See the user documentation for details on what it does. * * Results: * A standard Tcl result object. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ArrayAnyMoreCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_Obj *varNameObj, *searchObj; int gotValue; ArraySearch *searchPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName searchId"); return TCL_ERROR; } varNameObj = objv[1]; searchObj = objv[2]; /* * Locate the array variable. */ varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); /* * Special array trace used to keep the env array in sync for array names, * array get, etc. */ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { return TCL_ERROR; } } /* * Verify that it is indeed an array variable. This test comes after the * traces - the variable may actually become an array as an effect of said * traces. */ if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't an array", TclGetString(varNameObj))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", TclGetString(varNameObj), NULL); return TCL_ERROR; } /* * Get the search. */ searchPtr = ParseSearchId(interp, varPtr, varNameObj, searchObj); if (searchPtr == NULL) { return TCL_ERROR; } /* * Scan forward to find if there are any further elements in the array * that are defined. */ while (1) { if (searchPtr->nextEntry != NULL) { varPtr = VarHashGetValue(searchPtr->nextEntry); if (!TclIsVarUndefined(varPtr)) { gotValue = 1; break; } } searchPtr->nextEntry = Tcl_NextHashEntry(&searchPtr->search); if (searchPtr->nextEntry == NULL) { gotValue = 0; break; } } Tcl_SetObjResult(interp, iPtr->execEnvPtr->constants[gotValue]); return TCL_OK; } /* *---------------------------------------------------------------------- * * ArrayNextElementCmd -- * * This object-based function is invoked to process the "array * nextelement" Tcl command. See the user documentation for details on * what it does. * * Results: * A standard Tcl result object. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ArrayNextElementCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_Obj *varNameObj, *searchObj; ArraySearch *searchPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName searchId"); return TCL_ERROR; } varNameObj = objv[1]; searchObj = objv[2]; /* * Locate the array variable. */ varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); /* * Special array trace used to keep the env array in sync for array names, * array get, etc. */ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { return TCL_ERROR; } } /* * Verify that it is indeed an array variable. This test comes after the * traces - the variable may actually become an array as an effect of said * traces. */ if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't an array", TclGetString(varNameObj))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", TclGetString(varNameObj), NULL); return TCL_ERROR; } /* * Get the search. */ searchPtr = ParseSearchId(interp, varPtr, varNameObj, searchObj); if (searchPtr == NULL) { return TCL_ERROR; } /* * Get the next element from the search, or the empty string on * exhaustion. Note that the [array anymore] command may well have already * pulled a value from the hash enumeration, so we have to check the cache * there first. */ while (1) { Tcl_HashEntry *hPtr = searchPtr->nextEntry; if (hPtr == NULL) { hPtr = Tcl_NextHashEntry(&searchPtr->search); if (hPtr == NULL) { return TCL_OK; } } else { searchPtr->nextEntry = NULL; } varPtr = VarHashGetValue(hPtr); if (!TclIsVarUndefined(varPtr)) { Tcl_SetObjResult(interp, VarHashGetKey(varPtr)); return TCL_OK; } } } /* *---------------------------------------------------------------------- * * ArrayDoneSearchCmd -- * * This object-based function is invoked to process the "array * donesearch" Tcl command. See the user documentation for details on * what it does. * * Results: * A standard Tcl result object. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ArrayDoneSearchCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_HashEntry *hPtr; Tcl_Obj *varNameObj, *searchObj; ArraySearch *searchPtr, *prevPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName searchId"); return TCL_ERROR; } varNameObj = objv[1]; searchObj = objv[2]; /* * Locate the array variable. */ varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); /* * Special array trace used to keep the env array in sync for array names, * array get, etc. */ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { return TCL_ERROR; } } /* * Verify that it is indeed an array variable. This test comes after the * traces - the variable may actually become an array as an effect of said * traces. */ if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't an array", TclGetString(varNameObj))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", TclGetString(varNameObj), NULL); return TCL_ERROR; } /* * Get the search. */ searchPtr = ParseSearchId(interp, varPtr, varNameObj, searchObj); if (searchPtr == NULL) { return TCL_ERROR; } /* * Unhook the search from the list of searches associated with the * variable. */ hPtr = Tcl_FindHashEntry(&iPtr->varSearches, varPtr); if (searchPtr == Tcl_GetHashValue(hPtr)) { if (searchPtr->nextPtr) { Tcl_SetHashValue(hPtr, searchPtr->nextPtr); } else { varPtr->flags &= ~VAR_SEARCH_ACTIVE; Tcl_DeleteHashEntry(hPtr); } } else { for (prevPtr=Tcl_GetHashValue(hPtr) ;; prevPtr=prevPtr->nextPtr) { if (prevPtr->nextPtr == searchPtr) { prevPtr->nextPtr = searchPtr->nextPtr; break; } } } ckfree(searchPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * ArrayExistsCmd -- * * This object-based function is invoked to process the "array exists" * Tcl command. See the user documentation for details on what it does. * * Results: * A standard Tcl result object. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ArrayExistsCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_Obj *arrayNameObj; int notArray; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName"); return TCL_ERROR; } arrayNameObj = objv[1]; /* * Locate the array variable. */ varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); /* * Special array trace used to keep the env array in sync for array names, * array get, etc. */ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, arrayNameObj, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { return TCL_ERROR; } } /* * Check whether we've actually got an array variable. */ notArray = ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)); Tcl_SetObjResult(interp, iPtr->execEnvPtr->constants[!notArray]); return TCL_OK; } /* *---------------------------------------------------------------------- * * ArrayGetCmd -- * * This object-based function is invoked to process the "array get" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl result object. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ArrayGetCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr, *varPtr2; Tcl_Obj *varNameObj, *nameObj, *valueObj, *nameLstObj, *tmpResObj; Tcl_Obj **nameObjPtr, *patternObj; Tcl_HashSearch search; const char *pattern; int i, count, result; switch (objc) { case 2: varNameObj = objv[1]; patternObj = NULL; break; case 3: varNameObj = objv[1]; patternObj = objv[2]; break; default: Tcl_WrongNumArgs(interp, 1, objv, "arrayName ?pattern?"); return TCL_ERROR; } /* * Locate the array variable. */ varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); /* * Special array trace used to keep the env array in sync for array names, * array get, etc. */ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { return TCL_ERROR; } } /* * Verify that it is indeed an array variable. This test comes after the * traces - the variable may actually become an array as an effect of said * traces. If not an array, it's an empty result. */ if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) { return TCL_OK; } pattern = (patternObj ? TclGetString(patternObj) : NULL); /* * Store the array names in a new object. */ TclNewObj(nameLstObj); Tcl_IncrRefCount(nameLstObj); if ((patternObj != NULL) && TclMatchIsTrivial(pattern)) { varPtr2 = VarHashFindVar(varPtr->value.tablePtr, patternObj); if (varPtr2 == NULL) { goto searchDone; } if (TclIsVarUndefined(varPtr2)) { goto searchDone; } result = Tcl_ListObjAppendElement(interp, nameLstObj, VarHashGetKey(varPtr2)); if (result != TCL_OK) { TclDecrRefCount(nameLstObj); return result; } goto searchDone; } for (varPtr2 = VarHashFirstVar(varPtr->value.tablePtr, &search); varPtr2; varPtr2 = VarHashNextVar(&search)) { if (TclIsVarUndefined(varPtr2)) { continue; } nameObj = VarHashGetKey(varPtr2); if (patternObj && !Tcl_StringMatch(TclGetString(nameObj), pattern)) { continue; /* Element name doesn't match pattern. */ } result = Tcl_ListObjAppendElement(interp, nameLstObj, nameObj); if (result != TCL_OK) { TclDecrRefCount(nameLstObj); return result; } } /* * Make sure the Var structure of the array is not removed by a trace * while we're working. */ searchDone: if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)++; } /* * Get the array values corresponding to each element name. */ TclNewObj(tmpResObj); result = Tcl_ListObjGetElements(interp, nameLstObj, &count, &nameObjPtr); if (result != TCL_OK) { goto errorInArrayGet; } for (i=0 ; i 4)) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName ?mode? ?pattern?"); return TCL_ERROR; } varNameObj = objv[1]; patternObj = (objc > 2 ? objv[objc-1] : NULL); /* * Locate the array variable. */ varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); /* * Special array trace used to keep the env array in sync for array names, * array get, etc. */ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { return TCL_ERROR; } } /* * Finish parsing the arguments. */ if ((objc == 4) && Tcl_GetIndexFromObj(interp, objv[2], options, "option", 0, &mode) != TCL_OK) { return TCL_ERROR; } /* * Verify that it is indeed an array variable. This test comes after the * traces - the variable may actually become an array as an effect of said * traces. If not an array, the result is empty. */ if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) { return TCL_OK; } /* * Check for the trivial cases where we can use a direct lookup. */ TclNewObj(resultObj); if (patternObj) { pattern = TclGetString(patternObj); } if ((mode==OPT_GLOB && patternObj && TclMatchIsTrivial(pattern)) || (mode==OPT_EXACT)) { varPtr2 = VarHashFindVar(varPtr->value.tablePtr, patternObj); if ((varPtr2 != NULL) && !TclIsVarUndefined(varPtr2)) { /* * This can't fail; lappending to an empty object always works. */ Tcl_ListObjAppendElement(NULL, resultObj, VarHashGetKey(varPtr2)); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * Must scan the array to select the elements. */ for (varPtr2=VarHashFirstVar(varPtr->value.tablePtr, &search); varPtr2!=NULL ; varPtr2=VarHashNextVar(&search)) { if (TclIsVarUndefined(varPtr2)) { continue; } nameObj = VarHashGetKey(varPtr2); if (patternObj) { const char *name = TclGetString(nameObj); int matched = 0; switch ((enum options) mode) { case OPT_EXACT: Tcl_Panic("exact matching shouldn't get here"); case OPT_GLOB: matched = Tcl_StringMatch(name, pattern); break; case OPT_REGEXP: matched = Tcl_RegExpMatchObj(interp, nameObj, patternObj); if (matched < 0) { TclDecrRefCount(resultObj); return TCL_ERROR; } break; } if (matched == 0) { continue; } } Tcl_ListObjAppendElement(NULL, resultObj, nameObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclFindArrayPtrElements -- * * Fill out a hash table (which *must* use Tcl_Obj* keys) with an entry * for each existing element of the given array. The provided hash table * is assumed to be initially empty. * * Result: * none * * Side effects: * The keys of the array gain an extra reference. The supplied hash table * has elements added to it. * *---------------------------------------------------------------------- */ void TclFindArrayPtrElements( Var *arrayPtr, Tcl_HashTable *tablePtr) { Var *varPtr; Tcl_HashSearch search; if ((arrayPtr == NULL) || !TclIsVarArray(arrayPtr) || TclIsVarUndefined(arrayPtr)) { return; } for (varPtr=VarHashFirstVar(arrayPtr->value.tablePtr, &search); varPtr!=NULL ; varPtr=VarHashNextVar(&search)) { Tcl_HashEntry *hPtr; Tcl_Obj *nameObj; int dummy; if (TclIsVarUndefined(varPtr)) { continue; } nameObj = VarHashGetKey(varPtr); hPtr = Tcl_CreateHashEntry(tablePtr, (char *) nameObj, &dummy); Tcl_SetHashValue(hPtr, nameObj); } } /* *---------------------------------------------------------------------- * * ArraySetCmd -- * * This object-based function is invoked to process the "array set" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl result object. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ArraySetCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName list"); return TCL_ERROR; } /* * Locate the array variable. */ varPtr = TclObjLookupVarEx(interp, objv[1], NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); /* * Special array trace used to keep the env array in sync for array names, * array get, etc. */ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, objv[1], NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { return TCL_ERROR; } } return TclArraySet(interp, objv[1], objv[2]); } /* *---------------------------------------------------------------------- * * ArraySizeCmd -- * * This object-based function is invoked to process the "array size" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl result object. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ArraySizeCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_Obj *varNameObj; Tcl_HashSearch search; Var *varPtr2; int size = 0; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName"); return TCL_ERROR; } varNameObj = objv[1]; /* * Locate the array variable. */ varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); /* * Special array trace used to keep the env array in sync for array names, * array get, etc. */ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { return TCL_ERROR; } } /* * Verify that it is indeed an array variable. This test comes after the * traces - the variable may actually become an array as an effect of said * traces. We can only iterate over the array if it exists... */ if (varPtr && TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) { /* * Must iterate in order to get chance to check for present but * "undefined" entries. */ for (varPtr2=VarHashFirstVar(varPtr->value.tablePtr, &search); varPtr2!=NULL ; varPtr2=VarHashNextVar(&search)) { if (!TclIsVarUndefined(varPtr2)) { size++; } } } Tcl_SetObjResult(interp, Tcl_NewIntObj(size)); return TCL_OK; } /* *---------------------------------------------------------------------- * * ArrayStatsCmd -- * * This object-based function is invoked to process the "array * statistics" Tcl command. See the user documentation for details on * what it does. * * Results: * A standard Tcl result object. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ArrayStatsCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_Obj *varNameObj; char *stats; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName"); return TCL_ERROR; } varNameObj = objv[1]; /* * Locate the array variable. */ varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); /* * Special array trace used to keep the env array in sync for array names, * array get, etc. */ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { return TCL_ERROR; } } /* * Verify that it is indeed an array variable. This test comes after the * traces - the variable may actually become an array as an effect of said * traces. */ if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't an array", TclGetString(varNameObj))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", TclGetString(varNameObj), NULL); return TCL_ERROR; } stats = Tcl_HashStats((Tcl_HashTable *) varPtr->value.tablePtr); if (stats == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "error reading array statistics", -1)); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewStringObj(stats, -1)); ckfree(stats); return TCL_OK; } /* *---------------------------------------------------------------------- * * ArrayUnsetCmd -- * * This object-based function is invoked to process the "array unset" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl result object. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ArrayUnsetCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr, *varPtr2, *protectedVarPtr; Tcl_Obj *varNameObj, *patternObj, *nameObj; Tcl_HashSearch search; const char *pattern; const int unsetFlags = 0; /* Should this be TCL_LEAVE_ERR_MSG? */ switch (objc) { case 2: varNameObj = objv[1]; patternObj = NULL; break; case 3: varNameObj = objv[1]; patternObj = objv[2]; break; default: Tcl_WrongNumArgs(interp, 1, objv, "arrayName ?pattern?"); return TCL_ERROR; } /* * Locate the array variable */ varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); /* * Special array trace used to keep the env array in sync for array names, * array get, etc. */ if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { return TCL_ERROR; } } /* * Verify that it is indeed an array variable. This test comes after the * traces - the variable may actually become an array as an effect of said * traces. */ if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) { return TCL_OK; } if (!patternObj) { /* * When no pattern is given, just unset the whole array. */ return TclObjUnsetVar2(interp, varNameObj, NULL, 0); } /* * With a trivial pattern, we can just unset. */ pattern = TclGetString(patternObj); if (TclMatchIsTrivial(pattern)) { varPtr2 = VarHashFindVar(varPtr->value.tablePtr, patternObj); if (!varPtr2 || TclIsVarUndefined(varPtr2)) { return TCL_OK; } return TclPtrUnsetVar(interp, varPtr2, varPtr, varNameObj, patternObj, unsetFlags, -1); } /* * Non-trivial case (well, deeply tricky really). We peek inside the hash * iterator in order to allow us to guarantee that the following element * in the array will not be scrubbed until we have dealt with it. This * stops the overall iterator from ending up pointing into deallocated * memory. [Bug 2939073] */ protectedVarPtr = NULL; for (varPtr2=VarHashFirstVar(varPtr->value.tablePtr, &search); varPtr2!=NULL ; varPtr2=VarHashNextVar(&search)) { /* * Drop the extra ref immediately. We don't need to free it at this * point though; we'll be unsetting it if necessary soon. */ if (varPtr2 == protectedVarPtr) { VarHashRefCount(varPtr2)--; } /* * Guard the next (peeked) item in the search chain by incrementing * its refcount. This guarantees that the hash table iterator won't be * dangling on the next time through the loop. */ if (search.nextEntryPtr != NULL) { protectedVarPtr = VarHashGetValue(search.nextEntryPtr); VarHashRefCount(protectedVarPtr)++; } else { protectedVarPtr = NULL; } /* * If the variable is undefined, clean it out as it has been hit by * something else (i.e., an unset trace). */ if (TclIsVarUndefined(varPtr2)) { CleanupVar(varPtr2, varPtr); continue; } nameObj = VarHashGetKey(varPtr2); if (Tcl_StringMatch(TclGetString(nameObj), pattern) && TclPtrUnsetVar(interp, varPtr2, varPtr, varNameObj, nameObj, unsetFlags, -1) != TCL_OK) { /* * If we incremented a refcount, we must decrement it here as we * will not be coming back properly due to the error. */ if (protectedVarPtr) { VarHashRefCount(protectedVarPtr)--; CleanupVar(protectedVarPtr, varPtr); } return TCL_ERROR; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclInitArrayCmd -- * * This creates the ensemble for the "array" command. * * Results: * The handle for the created ensemble. * * Side effects: * Creates a command in the global namespace. * *---------------------------------------------------------------------- */ /* ARGSUSED */ Tcl_Command TclInitArrayCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap arrayImplMap[] = { {"anymore", ArrayAnyMoreCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"donesearch", ArrayDoneSearchCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"exists", ArrayExistsCmd, TclCompileArrayExistsCmd, NULL, NULL, 0}, {"get", ArrayGetCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"names", ArrayNamesCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"nextelement", ArrayNextElementCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"set", ArraySetCmd, TclCompileArraySetCmd, NULL, NULL, 0}, {"size", ArraySizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"startsearch", ArrayStartSearchCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"statistics", ArrayStatsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"unset", ArrayUnsetCmd, TclCompileArrayUnsetCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; return TclMakeEnsemble(interp, "array", arrayImplMap); } /* *---------------------------------------------------------------------- * * ObjMakeUpvar -- * * This function does all of the work of the "global" and "upvar" * commands. * * Results: * A standard Tcl completion code. If an error occurs then an error * message is left in iPtr->result. * * Side effects: * The variable given by myName is linked to the variable in framePtr * given by otherP1 and otherP2, so that references to myName are * redirected to the other variable like a symbolic link. * Callers must Incr myNamePtr if they plan to Decr it. * Callers must Incr otherP1Ptr if they plan to Decr it. * *---------------------------------------------------------------------- */ static int ObjMakeUpvar( Tcl_Interp *interp, /* Interpreter containing variables. Used for * error messages, too. */ CallFrame *framePtr, /* Call frame containing "other" variable. * NULL means use global :: context. */ Tcl_Obj *otherP1Ptr, const char *otherP2, /* Two-part name of variable in framePtr. */ const int otherFlags, /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY: * indicates scope of "other" variable. */ Tcl_Obj *myNamePtr, /* Name of variable which will refer to * otherP1/otherP2. Must be a scalar. */ int myFlags, /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY: * indicates scope of myName. */ int index) /* If the variable to be linked is an indexed * scalar, this is its index. Otherwise, -1 */ { Interp *iPtr = (Interp *) interp; Var *otherPtr, *arrayPtr; CallFrame *varFramePtr; /* * Find "other" in "framePtr". If not looking up other in just the current * namespace, temporarily replace the current var frame pointer in the * interpreter in order to use TclObjLookupVar. */ if (framePtr == NULL) { framePtr = iPtr->rootFramePtr; } varFramePtr = iPtr->varFramePtr; if (!(otherFlags & TCL_NAMESPACE_ONLY)) { iPtr->varFramePtr = framePtr; } otherPtr = TclObjLookupVar(interp, otherP1Ptr, otherP2, (otherFlags | TCL_LEAVE_ERR_MSG), "access", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (!(otherFlags & TCL_NAMESPACE_ONLY)) { iPtr->varFramePtr = varFramePtr; } if (otherPtr == NULL) { return TCL_ERROR; } /* * Check that we are not trying to create a namespace var linked to a * local variable in a procedure. If we allowed this, the local * variable in the shorter-lived procedure frame could go away leaving * the namespace var's reference invalid. */ if (index < 0) { if (!(arrayPtr != NULL ? (TclIsVarInHash(arrayPtr) && TclGetVarNsPtr(arrayPtr)) : (TclIsVarInHash(otherPtr) && TclGetVarNsPtr(otherPtr))) && ((myFlags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY)) || (varFramePtr == NULL) || !HasLocalVars(varFramePtr) || (strstr(TclGetString(myNamePtr), "::") != NULL))) { Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_ObjPrintf( "bad variable name \"%s\": can't create namespace " "variable that refers to procedure variable", TclGetString(myNamePtr))); Tcl_SetErrorCode(interp, "TCL", "UPVAR", "INVERTED", NULL); return TCL_ERROR; } } return TclPtrObjMakeUpvar(interp, otherPtr, myNamePtr, myFlags, index); } /* *---------------------------------------------------------------------- * * TclPtrMakeUpvar -- * * This procedure does all of the work of the "global" and "upvar" * commands. * * Results: * A standard Tcl completion code. If an error occurs then an error * message is left in iPtr->result. * * Side effects: * The variable given by myName is linked to the variable in framePtr * given by otherP1 and otherP2, so that references to myName are * redirected to the other variable like a symbolic link. * *---------------------------------------------------------------------- */ int TclPtrMakeUpvar( Tcl_Interp *interp, /* Interpreter containing variables. Used for * error messages, too. */ Var *otherPtr, /* Pointer to the variable being linked-to. */ const char *myName, /* Name of variable which will refer to * otherP1/otherP2. Must be a scalar. */ int myFlags, /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY: * indicates scope of myName. */ int index) /* If the variable to be linked is an indexed * scalar, this is its index. Otherwise, -1 */ { Tcl_Obj *myNamePtr = NULL; int result; if (myName) { myNamePtr = Tcl_NewStringObj(myName, -1); Tcl_IncrRefCount(myNamePtr); } result = TclPtrObjMakeUpvar(interp, otherPtr, myNamePtr, myFlags, index); if (myNamePtr) { Tcl_DecrRefCount(myNamePtr); } return result; } /* Callers must Incr myNamePtr if they plan to Decr it. */ int TclPtrObjMakeUpvar( Tcl_Interp *interp, /* Interpreter containing variables. Used for * error messages, too. */ Var *otherPtr, /* Pointer to the variable being linked-to. */ Tcl_Obj *myNamePtr, /* Name of variable which will refer to * otherP1/otherP2. Must be a scalar. */ int myFlags, /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY: * indicates scope of myName. */ int index) /* If the variable to be linked is an indexed * scalar, this is its index. Otherwise, -1 */ { Interp *iPtr = (Interp *) interp; CallFrame *varFramePtr = iPtr->varFramePtr; const char *errMsg, *p, *myName; Var *varPtr; if (index >= 0) { if (!HasLocalVars(varFramePtr)) { Tcl_Panic("ObjMakeUpvar called with an index outside from a proc"); } varPtr = (Var *) &(varFramePtr->compiledLocals[index]); myNamePtr = localName(iPtr->varFramePtr, index); myName = myNamePtr? TclGetString(myNamePtr) : NULL; } else { /* * Do not permit the new variable to look like an array reference, as * it will not be reachable in that case [Bug 600812, TIP 184]. The * "definition" of what "looks like an array reference" is consistent * (and must remain consistent) with the code in TclObjLookupVar(). */ myName = TclGetString(myNamePtr); p = strstr(myName, "("); if (p != NULL) { p += strlen(p)-1; if (*p == ')') { /* * myName looks like an array reference. */ Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_ObjPrintf( "bad variable name \"%s\": can't create a scalar " "variable that looks like an array element", myName)); Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL); return TCL_ERROR; } } /* * Lookup and eventually create the new variable. Set the flag bit * AVOID_RESOLVERS to indicate the special resolution rules for upvar * purposes: * - Bug #696893 - variable is either proc-local or in the current * namespace; never follow the second (global) resolution path. * - Bug #631741 - do not use special namespace or interp resolvers. */ varPtr = TclLookupSimpleVar(interp, myNamePtr, myFlags|AVOID_RESOLVERS, /* create */ 1, &errMsg, &index); if (varPtr == NULL) { TclObjVarErrMsg(interp, myNamePtr, NULL, "create", errMsg, -1); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", TclGetString(myNamePtr), NULL); return TCL_ERROR; } } if (varPtr == otherPtr) { Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_NewStringObj( "can't upvar from variable to itself", -1)); Tcl_SetErrorCode(interp, "TCL", "UPVAR", "SELF", NULL); return TCL_ERROR; } if (TclIsVarTraced(varPtr)) { Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_ObjPrintf( "variable \"%s\" has traces: can't use for upvar", myName)); Tcl_SetErrorCode(interp, "TCL", "UPVAR", "TRACED", NULL); return TCL_ERROR; } else if (!TclIsVarUndefined(varPtr)) { Var *linkPtr; /* * The variable already existed. Make sure this variable "varPtr" * isn't the same as "otherPtr" (avoid circular links). Also, if it's * not an upvar then it's an error. If it is an upvar, then just * disconnect it from the thing it currently refers to. */ if (!TclIsVarLink(varPtr)) { Tcl_SetObjResult((Tcl_Interp *) iPtr, Tcl_ObjPrintf( "variable \"%s\" already exists", myName)); Tcl_SetErrorCode(interp, "TCL", "UPVAR", "EXISTS", NULL); return TCL_ERROR; } linkPtr = varPtr->value.linkPtr; if (linkPtr == otherPtr) { return TCL_OK; } if (TclIsVarInHash(linkPtr)) { VarHashRefCount(linkPtr)--; if (TclIsVarUndefined(linkPtr)) { CleanupVar(linkPtr, NULL); } } } TclSetVarLink(varPtr); varPtr->value.linkPtr = otherPtr; if (TclIsVarInHash(otherPtr)) { VarHashRefCount(otherPtr)++; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_UpVar -- * * This function links one variable to another, just like the "upvar" * command. * * Results: * A standard Tcl completion code. If an error occurs then an error * message is left in the interp's result. * * Side effects: * The variable in frameName whose name is given by varName becomes * accessible under the name localNameStr, so that references to * localNameStr are redirected to the other variable like a symbolic * link. * *---------------------------------------------------------------------- */ #undef Tcl_UpVar int Tcl_UpVar( Tcl_Interp *interp, /* Command interpreter in which varName is to * be looked up. */ const char *frameName, /* Name of the frame containing the source * variable, such as "1" or "#0". */ const char *varName, /* Name of a variable in interp to link to. * May be either a scalar name or an element * in an array. */ const char *localNameStr, /* Name of link variable. */ int flags) /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY: * indicates scope of localNameStr. */ { int result; CallFrame *framePtr; Tcl_Obj *varNamePtr, *localNamePtr; if (TclGetFrame(interp, frameName, &framePtr) == -1) { return TCL_ERROR; } varNamePtr = Tcl_NewStringObj(varName, -1); Tcl_IncrRefCount(varNamePtr); localNamePtr = Tcl_NewStringObj(localNameStr, -1); Tcl_IncrRefCount(localNamePtr); result = ObjMakeUpvar(interp, framePtr, varNamePtr, NULL, 0, localNamePtr, flags, -1); Tcl_DecrRefCount(varNamePtr); Tcl_DecrRefCount(localNamePtr); return result; } /* *---------------------------------------------------------------------- * * Tcl_UpVar2 -- * * This function links one variable to another, just like the "upvar" * command. * * Results: * A standard Tcl completion code. If an error occurs then an error * message is left in the interp's result. * * Side effects: * The variable in frameName whose name is given by part1 and part2 * becomes accessible under the name localNameStr, so that references to * localNameStr are redirected to the other variable like a symbolic * link. * *---------------------------------------------------------------------- */ int Tcl_UpVar2( Tcl_Interp *interp, /* Interpreter containing variables. Used for * error messages too. */ const char *frameName, /* Name of the frame containing the source * variable, such as "1" or "#0". */ const char *part1, const char *part2, /* Two parts of source variable name to link * to. */ const char *localNameStr, /* Name of link variable. */ int flags) /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY: * indicates scope of localNameStr. */ { int result; CallFrame *framePtr; Tcl_Obj *part1Ptr, *localNamePtr; if (TclGetFrame(interp, frameName, &framePtr) == -1) { return TCL_ERROR; } part1Ptr = Tcl_NewStringObj(part1, -1); Tcl_IncrRefCount(part1Ptr); localNamePtr = Tcl_NewStringObj(localNameStr, -1); Tcl_IncrRefCount(localNamePtr); result = ObjMakeUpvar(interp, framePtr, part1Ptr, part2, 0, localNamePtr, flags, -1); Tcl_DecrRefCount(part1Ptr); Tcl_DecrRefCount(localNamePtr); return result; } /* *---------------------------------------------------------------------- * * Tcl_GetVariableFullName -- * * Given a Tcl_Var token returned by Tcl_FindNamespaceVar, this function * appends to an object the namespace variable's full name, qualified by * a sequence of parent namespace names. * * Results: * None. * * Side effects: * The variable's fully-qualified name is appended to the string * representation of objPtr. * *---------------------------------------------------------------------- */ void Tcl_GetVariableFullName( Tcl_Interp *interp, /* Interpreter containing the variable. */ Tcl_Var variable, /* Token for the variable returned by a * previous call to Tcl_FindNamespaceVar. */ Tcl_Obj *objPtr) /* Points to the object onto which the * variable's full name is appended. */ { Interp *iPtr = (Interp *) interp; register Var *varPtr = (Var *) variable; Tcl_Obj *namePtr; Namespace *nsPtr; if (!varPtr || TclIsVarArrayElement(varPtr)) { return; } /* * Add the full name of the containing namespace (if any), followed by the * "::" separator, then the variable name. */ nsPtr = TclGetVarNsPtr(varPtr); if (nsPtr) { Tcl_AppendToObj(objPtr, nsPtr->fullName, -1); if (nsPtr != iPtr->globalNsPtr) { Tcl_AppendToObj(objPtr, "::", 2); } } if (TclIsVarInHash(varPtr)) { if (!TclIsVarDeadHash(varPtr)) { namePtr = VarHashGetKey(varPtr); Tcl_AppendObjToObj(objPtr, namePtr); } } else if (iPtr->varFramePtr->procPtr) { int index = varPtr - iPtr->varFramePtr->compiledLocals; if (index >= 0 && index < iPtr->varFramePtr->numCompiledLocals) { namePtr = localName(iPtr->varFramePtr, index); Tcl_AppendObjToObj(objPtr, namePtr); } } } /* *---------------------------------------------------------------------- * * Tcl_GlobalObjCmd -- * * This object-based function is invoked to process the "global" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result value. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_GlobalObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; register Tcl_Obj *objPtr, *tailPtr; const char *varName; register const char *tail; int result, i; /* * If we are not executing inside a Tcl procedure, just return. */ if (!HasLocalVars(iPtr->varFramePtr)) { return TCL_OK; } for (i=1 ; i varName) && ((*tail != ':') || (*(tail-1) != ':'))) { tail--; } if ((*tail == ':') && (tail > varName)) { tail++; } if (tail == varName) { tailPtr = objPtr; } else { tailPtr = Tcl_NewStringObj(tail, -1); Tcl_IncrRefCount(tailPtr); } /* * Link to the variable "varName" in the global :: namespace. */ result = ObjMakeUpvar(interp, NULL, objPtr, NULL, TCL_GLOBAL_ONLY, /*myName*/ tailPtr, /*myFlags*/ 0, -1); if (tail != varName) { Tcl_DecrRefCount(tailPtr); } if (result != TCL_OK) { return result; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_VariableObjCmd -- * * Invoked to implement the "variable" command that creates one or more * global variables. Handles the following syntax: * * variable ?name value...? name ?value? * * One or more variables can be created. The variables are initialized * with the specified values. The value for the last variable is * optional. * * If the variable does not exist, it is created and given the optional * value. If it already exists, it is simply set to the optional value. * Normally, "name" is an unqualified name, so it is created in the * current namespace. If it includes namespace qualifiers, it can be * created in another namespace. * * If the variable command is executed inside a Tcl procedure, it creates * a local variable linked to the newly-created namespace variable. * * Results: * Returns TCL_OK if the variable is found or created. Returns TCL_ERROR * if anything goes wrong. * * Side effects: * If anything goes wrong, this function returns an error message as the * result in the interpreter's result object. * *---------------------------------------------------------------------- */ int Tcl_VariableObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; const char *varName, *tail, *cp; Var *varPtr, *arrayPtr; Tcl_Obj *varValuePtr; int i, result; Tcl_Obj *varNamePtr, *tailPtr; for (i=1 ; ivarFramePtr)) { /* * varName might have a scope qualifier, but the name for the * local "link" variable must be the simple name at the tail. * * Locate tail in one pass: drop any prefix after two *or more* * consecutive ":" characters). */ for (tail=cp=varName ; *cp!='\0' ;) { if (*cp++ == ':') { while (*cp == ':') { tail = ++cp; } } } /* * Create a local link "tail" to the variable "varName" in the * current namespace. */ if (tail == varName) { tailPtr = varNamePtr; } else { tailPtr = Tcl_NewStringObj(tail, -1); Tcl_IncrRefCount(tailPtr); } result = ObjMakeUpvar(interp, NULL, varNamePtr, /*otherP2*/ NULL, /*otherFlags*/ TCL_NAMESPACE_ONLY, /*myName*/ tailPtr, /*myFlags*/ 0, -1); if (tail != varName) { Tcl_DecrRefCount(tailPtr); } if (result != TCL_OK) { return result; } } } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_UpvarObjCmd -- * * This object-based function is invoked to process the "upvar" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result value. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_UpvarObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { CallFrame *framePtr; int result, hasLevel; Tcl_Obj *levelObj; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "?level? otherVar localVar ?otherVar localVar ...?"); return TCL_ERROR; } if (objc & 1) { /* * Even number of arguments, so use the default level of "1" by * passing NULL to TclObjGetFrame. */ levelObj = NULL; hasLevel = 0; } else { /* * Odd number of arguments, so objv[1] must contain the level. */ levelObj = objv[1]; hasLevel = 1; } /* * Find the call frame containing each of the "other variables" to be * linked to. */ result = TclObjGetFrame(interp, levelObj, &framePtr); if (result == -1) { return TCL_ERROR; } if ((result == 0) && hasLevel) { /* * Synthesize an error message since TclObjGetFrame doesn't do this * for this particular case. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad level \"%s\"", TclGetString(levelObj))); Tcl_SetErrorCode(interp, "TCL", "VALUE", "LEVEL", NULL); return TCL_ERROR; } /* * We've now finished with parsing levels; skip to the variable names. */ objc -= hasLevel + 1; objv += hasLevel + 1; /* * Iterate over each (other variable, local variable) pair. Divide the * other variable name into two parts, then call MakeUpvar to do all the * work of linking it to the local variable. */ for (; objc>0 ; objc-=2, objv+=2) { result = ObjMakeUpvar(interp, framePtr, /* othervarName */ objv[0], NULL, 0, /* myVarName */ objv[1], /*flags*/ 0, -1); if (result != TCL_OK) { return TCL_ERROR; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * SetArraySearchObj -- * * This function converts the given tcl object into one that has the * "array search" internal type. * * Results: * TCL_OK if the conversion succeeded, and TCL_ERROR if it failed (when * an error message will be placed in the interpreter's result.) * * Side effects: * Updates the internal type and representation of the object to make * this an array-search object. See the tclArraySearchType declaration * above for details of the internal representation. * *---------------------------------------------------------------------- */ static int SetArraySearchObj( Tcl_Interp *interp, Tcl_Obj *objPtr) { const char *string; char *end; /* Can't be const due to strtoul defn. */ int id; size_t offset; /* * Get the string representation. Make it up-to-date if necessary. */ string = TclGetString(objPtr); /* * Parse the id into the three parts separated by dashes. */ if ((string[0] != 's') || (string[1] != '-')) { goto syntax; } id = strtoul(string+2, &end, 10); if ((end == (string+2)) || (*end != '-')) { goto syntax; } /* * Can't perform value check in this context, so place reference to place * in string to use for the check in the object instead. */ end++; offset = end - string; TclFreeIntRep(objPtr); objPtr->typePtr = &tclArraySearchType; objPtr->internalRep.twoPtrValue.ptr1 = INT2PTR(id); objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(offset); return TCL_OK; syntax: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "illegal search identifier \"%s\"", string)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAYSEARCH", string, NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * ParseSearchId -- * * This function translates from a tcl object to a pointer to an active * array search (if there is one that matches the string). * * Results: * The return value is a pointer to the array search indicated by string, * or NULL if there isn't one. If NULL is returned, the interp's result * contains an error message. * * Side effects: * The tcl object might have its internal type and representation * modified. * *---------------------------------------------------------------------- */ static ArraySearch * ParseSearchId( Tcl_Interp *interp, /* Interpreter containing variable. */ const Var *varPtr, /* Array variable search is for. */ Tcl_Obj *varNamePtr, /* Name of array variable that search is * supposed to be for. */ Tcl_Obj *handleObj) /* Object containing id of search. Must have * form "search-num-var" where "num" is a * decimal number and "var" is a variable * name. */ { Interp *iPtr = (Interp *) interp; register const char *string; register size_t offset; int id; ArraySearch *searchPtr; const char *varName = TclGetString(varNamePtr); /* * Parse the id. */ if ((handleObj->typePtr != &tclArraySearchType) && (SetArraySearchObj(interp, handleObj) != TCL_OK)) { return NULL; } /* * Extract the information out of the Tcl_Obj. */ id = PTR2INT(handleObj->internalRep.twoPtrValue.ptr1); string = TclGetString(handleObj); offset = PTR2INT(handleObj->internalRep.twoPtrValue.ptr2); /* * This test cannot be placed inside the Tcl_Obj machinery, since it is * dependent on the variable context. */ if (strcmp(string+offset, varName) != 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "search identifier \"%s\" isn't for variable \"%s\"", string, varName)); goto badLookup; } /* * Search through the list of active searches on the interpreter to see if * the desired one exists. * * Note that we cannot store the searchPtr directly in the Tcl_Obj as that * would run into trouble when DeleteSearches() was called so we must scan * this list every time. */ if (varPtr->flags & VAR_SEARCH_ACTIVE) { Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&iPtr->varSearches, varPtr); for (searchPtr = Tcl_GetHashValue(hPtr); searchPtr != NULL; searchPtr = searchPtr->nextPtr) { if (searchPtr->id == id) { return searchPtr; } } } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't find search \"%s\"", string)); badLookup: Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAYSEARCH", string, NULL); return NULL; } /* *---------------------------------------------------------------------- * * DeleteSearches -- * * This function is called to free up all of the searches associated * with an array variable. * * Results: * None. * * Side effects: * Memory is released to the storage allocator. * *---------------------------------------------------------------------- */ static void DeleteSearches( Interp *iPtr, register Var *arrayVarPtr) /* Variable whose searches are to be * deleted. */ { ArraySearch *searchPtr, *nextPtr; Tcl_HashEntry *sPtr; if (arrayVarPtr->flags & VAR_SEARCH_ACTIVE) { sPtr = Tcl_FindHashEntry(&iPtr->varSearches, arrayVarPtr); for (searchPtr = Tcl_GetHashValue(sPtr); searchPtr != NULL; searchPtr = nextPtr) { nextPtr = searchPtr->nextPtr; ckfree(searchPtr); } arrayVarPtr->flags &= ~VAR_SEARCH_ACTIVE; Tcl_DeleteHashEntry(sPtr); } } /* *---------------------------------------------------------------------- * * TclDeleteNamespaceVars -- * * This function is called to recycle all the storage space associated * with a namespace's table of variables. * * Results: * None. * * Side effects: * Variables are deleted and trace functions are invoked, if any are * declared. * *---------------------------------------------------------------------- */ void TclDeleteNamespaceVars( Namespace *nsPtr) { TclVarHashTable *tablePtr = &nsPtr->varTable; Tcl_Interp *interp = nsPtr->interp; Interp *iPtr = (Interp *)interp; Tcl_HashSearch search; int flags = 0; Var *varPtr; /* * Determine what flags to pass to the trace callback functions. */ if (nsPtr == iPtr->globalNsPtr) { flags = TCL_GLOBAL_ONLY; } else if (nsPtr == (Namespace *) TclGetCurrentNamespace(interp)) { flags = TCL_NAMESPACE_ONLY; } for (varPtr = VarHashFirstVar(tablePtr, &search); varPtr != NULL; varPtr = VarHashFirstVar(tablePtr, &search)) { Tcl_Obj *objPtr = Tcl_NewObj(); VarHashRefCount(varPtr)++; /* Make sure we get to remove from * hash. */ Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, objPtr); UnsetVarStruct(varPtr, NULL, iPtr, /* part1 */ objPtr, NULL, flags, -1); Tcl_DecrRefCount(objPtr); /* Free no longer needed obj */ /* * Remove the variable from the table and force it undefined in case * an unset trace brought it back from the dead. */ if (TclIsVarTraced(varPtr)) { Tcl_HashEntry *tPtr = Tcl_FindHashEntry(&iPtr->varTraces, varPtr); VarTrace *tracePtr = Tcl_GetHashValue(tPtr); ActiveVarTrace *activePtr; while (tracePtr) { VarTrace *prevPtr = tracePtr; tracePtr = tracePtr->nextPtr; prevPtr->nextPtr = NULL; Tcl_EventuallyFree(prevPtr, TCL_DYNAMIC); } Tcl_DeleteHashEntry(tPtr); varPtr->flags &= ~VAR_ALL_TRACES; for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL; activePtr = activePtr->nextPtr) { if (activePtr->varPtr == varPtr) { activePtr->nextTracePtr = NULL; } } } VarHashRefCount(varPtr)--; VarHashDeleteEntry(varPtr); } VarHashDeleteTable(tablePtr); } /* *---------------------------------------------------------------------- * * TclDeleteVars -- * * This function is called to recycle all the storage space associated * with a table of variables. For this function to work correctly, it * must not be possible for any of the variables in the table to be * accessed from Tcl commands (e.g. from trace functions). * * Results: * None. * * Side effects: * Variables are deleted and trace functions are invoked, if any are * declared. * *---------------------------------------------------------------------- */ void TclDeleteVars( Interp *iPtr, /* Interpreter to which variables belong. */ TclVarHashTable *tablePtr) /* Hash table containing variables to * delete. */ { Tcl_Interp *interp = (Tcl_Interp *) iPtr; Tcl_HashSearch search; register Var *varPtr; int flags; Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp); /* * Determine what flags to pass to the trace callback functions. */ flags = TCL_TRACE_UNSETS; if (tablePtr == &iPtr->globalNsPtr->varTable) { flags |= TCL_GLOBAL_ONLY; } else if (tablePtr == &currNsPtr->varTable) { flags |= TCL_NAMESPACE_ONLY; } for (varPtr = VarHashFirstVar(tablePtr, &search); varPtr != NULL; varPtr = VarHashFirstVar(tablePtr, &search)) { UnsetVarStruct(varPtr, NULL, iPtr, VarHashGetKey(varPtr), NULL, flags, -1); VarHashDeleteEntry(varPtr); } VarHashDeleteTable(tablePtr); } /* *---------------------------------------------------------------------- * * TclDeleteCompiledLocalVars -- * * This function is called to recycle storage space associated with the * compiler-allocated array of local variables in a procedure call frame. * This function resembles TclDeleteVars above except that each variable * is stored in a call frame and not a hash table. For this function to * work correctly, it must not be possible for any of the variable in the * table to be accessed from Tcl commands (e.g. from trace functions). * * Results: * None. * * Side effects: * Variables are deleted and trace functions are invoked, if any are * declared. * *---------------------------------------------------------------------- */ void TclDeleteCompiledLocalVars( Interp *iPtr, /* Interpreter to which variables belong. */ CallFrame *framePtr) /* Procedure call frame containing compiler- * assigned local variables to delete. */ { register Var *varPtr; int numLocals, i; Tcl_Obj **namePtrPtr; numLocals = framePtr->numCompiledLocals; varPtr = framePtr->compiledLocals; namePtrPtr = &localName(framePtr, 0); for (i=0 ; inumCompiledLocals = 0; } /* *---------------------------------------------------------------------- * * DeleteArray -- * * This function is called to free up everything in an array variable. * It's the caller's responsibility to make sure that the array is no * longer accessible before this function is called. * * Results: * None. * * Side effects: * All storage associated with varPtr's array elements is deleted * (including the array's hash table). Deletion trace functions for * array elements are invoked, then deleted. Any pending traces for array * elements are also deleted. * *---------------------------------------------------------------------- */ static void DeleteArray( Interp *iPtr, /* Interpreter containing array. */ Tcl_Obj *arrayNamePtr, /* Name of array (used for trace callbacks), * or NULL if it is to be computed on * demand. */ Var *varPtr, /* Pointer to variable structure. */ int flags, /* Flags to pass to TclCallVarTraces: * TCL_TRACE_UNSETS and sometimes * TCL_NAMESPACE_ONLY or TCL_GLOBAL_ONLY. */ int index) { Tcl_HashSearch search; Tcl_HashEntry *tPtr; register Var *elPtr; ActiveVarTrace *activePtr; Tcl_Obj *objPtr; VarTrace *tracePtr; if (varPtr->flags & VAR_SEARCH_ACTIVE) { DeleteSearches(iPtr, varPtr); } for (elPtr = VarHashFirstVar(varPtr->value.tablePtr, &search); elPtr != NULL; elPtr = VarHashNextVar(&search)) { if (TclIsVarScalar(elPtr) && (elPtr->value.objPtr != NULL)) { objPtr = elPtr->value.objPtr; TclDecrRefCount(objPtr); elPtr->value.objPtr = NULL; } /* * Lie about the validity of the hashtable entry. In this way the * variables will be deleted by VarHashDeleteTable. */ VarHashInvalidateEntry(elPtr); if (TclIsVarTraced(elPtr)) { /* * Compute the array name if it was not supplied. */ if (elPtr->flags & VAR_TRACED_UNSET) { Tcl_Obj *elNamePtr = VarHashGetKey(elPtr); elPtr->flags &= ~VAR_TRACE_ACTIVE; TclObjCallVarTraces(iPtr, NULL, elPtr, arrayNamePtr, elNamePtr, flags,/* leaveErrMsg */ 0, index); } tPtr = Tcl_FindHashEntry(&iPtr->varTraces, elPtr); tracePtr = Tcl_GetHashValue(tPtr); while (tracePtr) { VarTrace *prevPtr = tracePtr; tracePtr = tracePtr->nextPtr; prevPtr->nextPtr = NULL; Tcl_EventuallyFree(prevPtr, TCL_DYNAMIC); } Tcl_DeleteHashEntry(tPtr); elPtr->flags &= ~VAR_ALL_TRACES; for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL; activePtr = activePtr->nextPtr) { if (activePtr->varPtr == elPtr) { activePtr->nextTracePtr = NULL; } } } TclSetVarUndefined(elPtr); /* * Even though array elements are not supposed to be namespace * variables, some combinations of [upvar] and [variable] may create * such beasts - see [Bug 604239]. This is necessary to avoid leaking * the corresponding Var struct, and is otherwise harmless. */ TclClearVarNamespaceVar(elPtr); } VarHashDeleteTable(varPtr->value.tablePtr); ckfree(varPtr->value.tablePtr); } /* *---------------------------------------------------------------------- * * TclObjVarErrMsg -- * * Generate a reasonable error message describing why a variable * operation failed. * * Results: * None. * * Side effects: * The interp's result is set to hold a message identifying the variable * given by part1 and part2 and describing why the variable operation * failed. * *---------------------------------------------------------------------- */ void TclVarErrMsg( Tcl_Interp *interp, /* Interpreter in which to record message. */ const char *part1, const char *part2, /* Variable's two-part name. */ const char *operation, /* String describing operation that failed, * e.g. "read", "set", or "unset". */ const char *reason) /* String describing why operation failed. */ { Tcl_Obj *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1); if (part2) { part2Ptr = Tcl_NewStringObj(part2, -1); } TclObjVarErrMsg(interp, part1Ptr, part2Ptr, operation, reason, -1); Tcl_DecrRefCount(part1Ptr); if (part2Ptr) { Tcl_DecrRefCount(part2Ptr); } } void TclObjVarErrMsg( Tcl_Interp *interp, /* Interpreter in which to record message. */ Tcl_Obj *part1Ptr, /* (may be NULL, if index >= 0) */ Tcl_Obj *part2Ptr, /* Variable's two-part name. */ const char *operation, /* String describing operation that failed, * e.g. "read", "set", or "unset". */ const char *reason, /* String describing why operation failed. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { if (!part1Ptr) { if (index == -1) { Tcl_Panic("invalid part1Ptr and invalid index together"); } part1Ptr = localName(((Interp *)interp)->varFramePtr, index); } Tcl_SetObjResult(interp, Tcl_ObjPrintf("can't %s \"%s%s%s%s\": %s", operation, TclGetString(part1Ptr), (part2Ptr ? "(" : ""), (part2Ptr ? TclGetString(part2Ptr) : ""), (part2Ptr ? ")" : ""), reason)); } /* *---------------------------------------------------------------------- * * Internal functions for variable name object types -- * *---------------------------------------------------------------------- */ /* * Panic functions that should never be called in normal operation. */ static void PanicOnUpdateVarName( Tcl_Obj *objPtr) { Tcl_Panic("%s of type %s should not be called", "updateStringProc", objPtr->typePtr->name); } static int PanicOnSetVarName( Tcl_Interp *interp, Tcl_Obj *objPtr) { Tcl_Panic("%s of type %s should not be called", "setFromAnyProc", objPtr->typePtr->name); return TCL_ERROR; } /* * localVarName - * * INTERNALREP DEFINITION: * twoPtrValue.ptr1: pointer to name obj in varFramePtr->localCache * or NULL if it is this same obj * twoPtrValue.ptr2: index into locals table */ static void FreeLocalVarName( Tcl_Obj *objPtr) { Tcl_Obj *namePtr = objPtr->internalRep.twoPtrValue.ptr1; if (namePtr) { Tcl_DecrRefCount(namePtr); } objPtr->typePtr = NULL; } static void DupLocalVarName( Tcl_Obj *srcPtr, Tcl_Obj *dupPtr) { Tcl_Obj *namePtr = srcPtr->internalRep.twoPtrValue.ptr1; if (!namePtr) { namePtr = srcPtr; } dupPtr->internalRep.twoPtrValue.ptr1 = namePtr; Tcl_IncrRefCount(namePtr); dupPtr->internalRep.twoPtrValue.ptr2 = srcPtr->internalRep.twoPtrValue.ptr2; dupPtr->typePtr = &localVarNameType; } /* * parsedVarName - * * INTERNALREP DEFINITION: * twoPtrValue.ptr1 = pointer to the array name Tcl_Obj (NULL if scalar) * twoPtrValue.ptr2 = pointer to the element name string (owned by this * Tcl_Obj), or NULL if it is a scalar variable */ static void FreeParsedVarName( Tcl_Obj *objPtr) { register Tcl_Obj *arrayPtr = objPtr->internalRep.twoPtrValue.ptr1; register char *elem = objPtr->internalRep.twoPtrValue.ptr2; if (arrayPtr != NULL) { TclDecrRefCount(arrayPtr); ckfree(elem); } objPtr->typePtr = NULL; } static void DupParsedVarName( Tcl_Obj *srcPtr, Tcl_Obj *dupPtr) { register Tcl_Obj *arrayPtr = srcPtr->internalRep.twoPtrValue.ptr1; register char *elem = srcPtr->internalRep.twoPtrValue.ptr2; char *elemCopy; unsigned elemLen; if (arrayPtr != NULL) { Tcl_IncrRefCount(arrayPtr); elemLen = strlen(elem); elemCopy = ckalloc(elemLen + 1); memcpy(elemCopy, elem, elemLen); *(elemCopy + elemLen) = '\0'; elem = elemCopy; } dupPtr->internalRep.twoPtrValue.ptr1 = arrayPtr; dupPtr->internalRep.twoPtrValue.ptr2 = elem; dupPtr->typePtr = &tclParsedVarNameType; } static void UpdateParsedVarName( Tcl_Obj *objPtr) { Tcl_Obj *arrayPtr = objPtr->internalRep.twoPtrValue.ptr1; char *part2 = objPtr->internalRep.twoPtrValue.ptr2; const char *part1; char *p; int len1, len2, totalLen; if (arrayPtr == NULL) { /* * This is a parsed scalar name: what is it doing here? */ Tcl_Panic("scalar parsedVarName without a string rep"); } part1 = TclGetStringFromObj(arrayPtr, &len1); len2 = strlen(part2); totalLen = len1 + len2 + 2; p = ckalloc(totalLen + 1); objPtr->bytes = p; objPtr->length = totalLen; memcpy(p, part1, (unsigned) len1); p += len1; *p++ = '('; memcpy(p, part2, (unsigned) len2); p += len2; *p++ = ')'; *p = '\0'; } /* *---------------------------------------------------------------------- * * Tcl_FindNamespaceVar -- MOVED OVER from tclNamesp.c * * Searches for a namespace variable, a variable not local to a * procedure. The variable can be either a scalar or an array, but may * not be an element of an array. * * Results: * Returns a token for the variable if it is found. Otherwise, if it * can't be found or there is an error, returns NULL and leaves an error * message in the interpreter's result object if "flags" contains * TCL_LEAVE_ERR_MSG. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Var Tcl_FindNamespaceVar( Tcl_Interp *interp, /* The interpreter in which to find the * variable. */ const char *name, /* Variable's name. If it starts with "::", * will be looked up in global namespace. * Else, looked up first in contextNsPtr * (current namespace if contextNsPtr is * NULL), then in global namespace. */ Tcl_Namespace *contextNsPtr,/* Ignored if TCL_GLOBAL_ONLY flag set. * Otherwise, points to namespace in which to * resolve name. If NULL, look up name in the * current namespace. */ int flags) /* An OR'd combination of: AVOID_RESOLVERS, * TCL_GLOBAL_ONLY (look up name only in * global namespace), TCL_NAMESPACE_ONLY (look * up only in contextNsPtr, or the current * namespace if contextNsPtr is NULL), and * TCL_LEAVE_ERR_MSG. If both TCL_GLOBAL_ONLY * and TCL_NAMESPACE_ONLY are given, * TCL_GLOBAL_ONLY is ignored. */ { Tcl_Obj *namePtr = Tcl_NewStringObj(name, -1); Tcl_Var var; var = ObjFindNamespaceVar(interp, namePtr, contextNsPtr, flags); Tcl_DecrRefCount(namePtr); return var; } static Tcl_Var ObjFindNamespaceVar( Tcl_Interp *interp, /* The interpreter in which to find the * variable. */ Tcl_Obj *namePtr, /* Variable's name. If it starts with "::", * will be looked up in global namespace. * Else, looked up first in contextNsPtr * (current namespace if contextNsPtr is * NULL), then in global namespace. */ Tcl_Namespace *contextNsPtr,/* Ignored if TCL_GLOBAL_ONLY flag set. * Otherwise, points to namespace in which to * resolve name. If NULL, look up name in the * current namespace. */ int flags) /* An OR'd combination of: AVOID_RESOLVERS, * TCL_GLOBAL_ONLY (look up name only in * global namespace), TCL_NAMESPACE_ONLY (look * up only in contextNsPtr, or the current * namespace if contextNsPtr is NULL), and * TCL_LEAVE_ERR_MSG. If both TCL_GLOBAL_ONLY * and TCL_NAMESPACE_ONLY are given, * TCL_GLOBAL_ONLY is ignored. */ { Interp *iPtr = (Interp *) interp; ResolverScheme *resPtr; Namespace *nsPtr[2], *cxtNsPtr; const char *simpleName; Var *varPtr; register int search; int result; Tcl_Var var; Tcl_Obj *simpleNamePtr; const char *name = TclGetString(namePtr); /* * If this namespace has a variable resolver, then give it first crack at * the variable resolution. It may return a Tcl_Var value, it may signal * to continue onward, or it may signal an error. */ if ((flags & TCL_GLOBAL_ONLY) != 0) { cxtNsPtr = (Namespace *) TclGetGlobalNamespace(interp); } else if (contextNsPtr != NULL) { cxtNsPtr = (Namespace *) contextNsPtr; } else { cxtNsPtr = (Namespace *) TclGetCurrentNamespace(interp); } if (!(flags & AVOID_RESOLVERS) && (cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL)) { resPtr = iPtr->resolverPtr; if (cxtNsPtr->varResProc) { result = cxtNsPtr->varResProc(interp, name, (Tcl_Namespace *) cxtNsPtr, flags, &var); } else { result = TCL_CONTINUE; } while (result == TCL_CONTINUE && resPtr) { if (resPtr->varResProc) { result = resPtr->varResProc(interp, name, (Tcl_Namespace *) cxtNsPtr, flags, &var); } resPtr = resPtr->nextPtr; } if (result == TCL_OK) { return var; } else if (result != TCL_CONTINUE) { return NULL; } } /* * Find the namespace(s) that contain the variable. */ TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr, flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName); /* * Look for the variable in the variable table of its namespace. Be sure * to check both possible search paths: from the specified namespace * context and from the global namespace. */ varPtr = NULL; if (simpleName != name) { simpleNamePtr = Tcl_NewStringObj(simpleName, -1); } else { simpleNamePtr = namePtr; } for (search = 0; (search < 2) && (varPtr == NULL); search++) { if ((nsPtr[search] != NULL) && (simpleName != NULL)) { varPtr = VarHashFindVar(&nsPtr[search]->varTable, simpleNamePtr); } } if (simpleName != name) { Tcl_DecrRefCount(simpleNamePtr); } if ((varPtr == NULL) && (flags & TCL_LEAVE_ERR_MSG)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown variable \"%s\"", name)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", name, NULL); } return (Tcl_Var) varPtr; } /* *---------------------------------------------------------------------- * * InfoVarsCmd -- (moved over from tclCmdIL.c) * * Called to implement the "info vars" command that returns the list of * variables in the interpreter that match an optional pattern. The * pattern, if any, consists of an optional sequence of namespace names * separated by "::" qualifiers, which is followed by a glob-style * pattern that restricts which variables are returned. Handles the * following syntax: * * info vars ?pattern? * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ int TclInfoVarsCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; const char *varName, *pattern, *simplePattern; Tcl_HashSearch search; Var *varPtr; Namespace *nsPtr; Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp); Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); Tcl_Obj *listPtr, *elemObjPtr, *varNamePtr; int specificNsInPattern = 0;/* Init. to avoid compiler warning. */ Tcl_Obj *simplePatternPtr = NULL; /* * Get the pattern and find the "effective namespace" in which to list * variables. We only use this effective namespace if there's no active * Tcl procedure frame. */ if (objc == 1) { simplePattern = NULL; nsPtr = currNsPtr; specificNsInPattern = 0; } else if (objc == 2) { /* * From the pattern, get the effective namespace and the simple * pattern (no namespace qualifiers or ::'s) at the end. If an error * was found while parsing the pattern, return it. Otherwise, if the * namespace wasn't found, just leave nsPtr NULL: we will return an * empty list since no variables there can be found. */ Namespace *dummy1NsPtr, *dummy2NsPtr; pattern = TclGetString(objv[1]); TclGetNamespaceForQualName(interp, pattern, NULL, /*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern); if (nsPtr != NULL) { /* We successfully found the pattern's ns. */ specificNsInPattern = (strcmp(simplePattern, pattern) != 0); if (simplePattern == pattern) { simplePatternPtr = objv[1]; } else { simplePatternPtr = Tcl_NewStringObj(simplePattern, -1); } Tcl_IncrRefCount(simplePatternPtr); } } else { Tcl_WrongNumArgs(interp, 1, objv, "?pattern?"); return TCL_ERROR; } /* * If the namespace specified in the pattern wasn't found, just return. */ if (nsPtr == NULL) { return TCL_OK; } listPtr = Tcl_NewListObj(0, NULL); if (!HasLocalVars(iPtr->varFramePtr) || specificNsInPattern) { /* * There is no frame pointer, the frame pointer was pushed only to * activate a namespace, or we are in a procedure call frame but a * specific namespace was specified. Create a list containing only the * variables in the effective namespace's variable table. */ if (simplePattern && TclMatchIsTrivial(simplePattern)) { /* * If we can just do hash lookups, that simplifies things a lot. */ varPtr = VarHashFindVar(&nsPtr->varTable, simplePatternPtr); if (varPtr) { if (!TclIsVarUndefined(varPtr) || TclIsVarNamespaceVar(varPtr)) { if (specificNsInPattern) { elemObjPtr = Tcl_NewObj(); Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, elemObjPtr); } else { elemObjPtr = VarHashGetKey(varPtr); } Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); } } else if ((nsPtr != globalNsPtr) && !specificNsInPattern) { varPtr = VarHashFindVar(&globalNsPtr->varTable, simplePatternPtr); if (varPtr) { if (!TclIsVarUndefined(varPtr) || TclIsVarNamespaceVar(varPtr)) { Tcl_ListObjAppendElement(interp, listPtr, VarHashGetKey(varPtr)); } } } } else { /* * Have to scan the tables of variables. */ varPtr = VarHashFirstVar(&nsPtr->varTable, &search); while (varPtr) { if (!TclIsVarUndefined(varPtr) || TclIsVarNamespaceVar(varPtr)) { varNamePtr = VarHashGetKey(varPtr); varName = TclGetString(varNamePtr); if ((simplePattern == NULL) || Tcl_StringMatch(varName, simplePattern)) { if (specificNsInPattern) { elemObjPtr = Tcl_NewObj(); Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, elemObjPtr); } else { elemObjPtr = varNamePtr; } Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); } } varPtr = VarHashNextVar(&search); } /* * If the effective namespace isn't the global :: namespace, and a * specific namespace wasn't requested in the pattern (i.e., the * pattern only specifies variable names), then add in all global * :: variables that match the simple pattern. Of course, add in * only those variables that aren't hidden by a variable in the * effective namespace. */ if ((nsPtr != globalNsPtr) && !specificNsInPattern) { varPtr = VarHashFirstVar(&globalNsPtr->varTable,&search); while (varPtr) { if (!TclIsVarUndefined(varPtr) || TclIsVarNamespaceVar(varPtr)) { varNamePtr = VarHashGetKey(varPtr); varName = TclGetString(varNamePtr); if ((simplePattern == NULL) || Tcl_StringMatch(varName, simplePattern)) { if (VarHashFindVar(&nsPtr->varTable, varNamePtr) == NULL) { Tcl_ListObjAppendElement(interp, listPtr, varNamePtr); } } } varPtr = VarHashNextVar(&search); } } } } else if (iPtr->varFramePtr->procPtr != NULL) { AppendLocals(interp, listPtr, simplePatternPtr, 1); } if (simplePatternPtr) { Tcl_DecrRefCount(simplePatternPtr); } Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * InfoGlobalsCmd -- (moved over from tclCmdIL.c) * * Called to implement the "info globals" command that returns the list * of global variables matching an optional pattern. Handles the * following syntax: * * info globals ?pattern? * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ int TclInfoGlobalsCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *varName, *pattern; Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp); Tcl_HashSearch search; Var *varPtr; Tcl_Obj *listPtr, *varNamePtr, *patternPtr; if (objc == 1) { pattern = NULL; } else if (objc == 2) { pattern = TclGetString(objv[1]); /* * Strip leading global-namespace qualifiers. [Bug 1057461] */ if (pattern[0] == ':' && pattern[1] == ':') { while (*pattern == ':') { pattern++; } } } else { Tcl_WrongNumArgs(interp, 1, objv, "?pattern?"); return TCL_ERROR; } /* * Scan through the global :: namespace's variable table and create a list * of all global variables that match the pattern. */ listPtr = Tcl_NewListObj(0, NULL); if (pattern != NULL && TclMatchIsTrivial(pattern)) { if (pattern == TclGetString(objv[1])) { patternPtr = objv[1]; } else { patternPtr = Tcl_NewStringObj(pattern, -1); } Tcl_IncrRefCount(patternPtr); varPtr = VarHashFindVar(&globalNsPtr->varTable, patternPtr); if (varPtr) { if (!TclIsVarUndefined(varPtr)) { Tcl_ListObjAppendElement(interp, listPtr, VarHashGetKey(varPtr)); } } Tcl_DecrRefCount(patternPtr); } else { for (varPtr = VarHashFirstVar(&globalNsPtr->varTable, &search); varPtr != NULL; varPtr = VarHashNextVar(&search)) { if (TclIsVarUndefined(varPtr)) { continue; } varNamePtr = VarHashGetKey(varPtr); varName = TclGetString(varNamePtr); if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) { Tcl_ListObjAppendElement(interp, listPtr, varNamePtr); } } } Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclInfoLocalsCmd -- (moved over from tclCmdIl.c) * * Called to implement the "info locals" command to return a list of * local variables that match an optional pattern. Handles the following * syntax: * * info locals ?pattern? * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ int TclInfoLocalsCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; Tcl_Obj *patternPtr, *listPtr; if (objc == 1) { patternPtr = NULL; } else if (objc == 2) { patternPtr = objv[1]; } else { Tcl_WrongNumArgs(interp, 1, objv, "?pattern?"); return TCL_ERROR; } if (!HasLocalVars(iPtr->varFramePtr)) { return TCL_OK; } /* * Return a list containing names of first the compiled locals (i.e. the * ones stored in the call frame), then the variables in the local hash * table (if one exists). */ listPtr = Tcl_NewListObj(0, NULL); AppendLocals(interp, listPtr, patternPtr, 0); Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * AppendLocals -- * * Append the local variables for the current frame to the specified list * object. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void AppendLocals( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *listPtr, /* List object to append names to. */ Tcl_Obj *patternPtr, /* Pattern to match against. */ int includeLinks) /* 1 if upvars should be included, else 0. */ { Interp *iPtr = (Interp *) interp; Var *varPtr; int i, localVarCt, added; Tcl_Obj **varNamePtr, *objNamePtr; const char *varName; TclVarHashTable *localVarTablePtr; Tcl_HashSearch search; Tcl_HashTable addedTable; const char *pattern = patternPtr? TclGetString(patternPtr) : NULL; localVarCt = iPtr->varFramePtr->numCompiledLocals; varPtr = iPtr->varFramePtr->compiledLocals; localVarTablePtr = iPtr->varFramePtr->varTablePtr; varNamePtr = &iPtr->varFramePtr->localCachePtr->varName0; if (includeLinks) { Tcl_InitObjHashTable(&addedTable); } for (i = 0; i < localVarCt; i++, varNamePtr++) { /* * Skip nameless (temporary) variables and undefined variables. */ if (*varNamePtr && !TclIsVarUndefined(varPtr) && (includeLinks || !TclIsVarLink(varPtr))) { varName = TclGetString(*varNamePtr); if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) { Tcl_ListObjAppendElement(interp, listPtr, *varNamePtr); if (includeLinks) { Tcl_CreateHashEntry(&addedTable, *varNamePtr, &added); } } } varPtr++; } /* * Do nothing if no local variables. */ if (localVarTablePtr == NULL) { goto objectVars; } /* * Check for the simple and fast case. */ if ((pattern != NULL) && TclMatchIsTrivial(pattern)) { varPtr = VarHashFindVar(localVarTablePtr, patternPtr); if (varPtr != NULL) { if (!TclIsVarUndefined(varPtr) && (includeLinks || !TclIsVarLink(varPtr))) { Tcl_ListObjAppendElement(interp, listPtr, VarHashGetKey(varPtr)); if (includeLinks) { Tcl_CreateHashEntry(&addedTable, VarHashGetKey(varPtr), &added); } } } goto objectVars; } /* * Scan over and process all local variables. */ for (varPtr = VarHashFirstVar(localVarTablePtr, &search); varPtr != NULL; varPtr = VarHashNextVar(&search)) { if (!TclIsVarUndefined(varPtr) && (includeLinks || !TclIsVarLink(varPtr))) { objNamePtr = VarHashGetKey(varPtr); varName = TclGetString(objNamePtr); if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) { Tcl_ListObjAppendElement(interp, listPtr, objNamePtr); if (includeLinks) { Tcl_CreateHashEntry(&addedTable, objNamePtr, &added); } } } } objectVars: if (!includeLinks) { return; } if (iPtr->varFramePtr->isProcCallFrame & FRAME_IS_METHOD) { CallContext *contextPtr = iPtr->varFramePtr->clientData; Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; if (mPtr->declaringObjectPtr) { FOREACH(objNamePtr, mPtr->declaringObjectPtr->variables) { Tcl_CreateHashEntry(&addedTable, objNamePtr, &added); if (added && (!pattern || Tcl_StringMatch(TclGetString(objNamePtr), pattern))) { Tcl_ListObjAppendElement(interp, listPtr, objNamePtr); } } } else { FOREACH(objNamePtr, mPtr->declaringClassPtr->variables) { Tcl_CreateHashEntry(&addedTable, objNamePtr, &added); if (added && (!pattern || Tcl_StringMatch(TclGetString(objNamePtr), pattern))) { Tcl_ListObjAppendElement(interp, listPtr, objNamePtr); } } } } Tcl_DeleteHashTable(&addedTable); } /* * Hash table implementation - first, just copy and adapt the obj key stuff */ void TclInitVarHashTable( TclVarHashTable *tablePtr, Namespace *nsPtr) { Tcl_InitCustomHashTable(&tablePtr->table, TCL_CUSTOM_TYPE_KEYS, &tclVarHashKeyType); tablePtr->nsPtr = nsPtr; } static Tcl_HashEntry * AllocVarEntry( Tcl_HashTable *tablePtr, /* Hash table. */ void *keyPtr) /* Key to store in the hash table entry. */ { Tcl_Obj *objPtr = keyPtr; Tcl_HashEntry *hPtr; Var *varPtr; varPtr = ckalloc(sizeof(VarInHash)); varPtr->flags = VAR_IN_HASHTABLE; varPtr->value.objPtr = NULL; VarHashRefCount(varPtr) = 1; hPtr = &(((VarInHash *) varPtr)->entry); Tcl_SetHashValue(hPtr, varPtr); hPtr->key.objPtr = objPtr; Tcl_IncrRefCount(objPtr); return hPtr; } static void FreeVarEntry( Tcl_HashEntry *hPtr) { Var *varPtr = VarHashGetValue(hPtr); Tcl_Obj *objPtr = hPtr->key.objPtr; if (TclIsVarUndefined(varPtr) && !TclIsVarTraced(varPtr) && (VarHashRefCount(varPtr) == 1)) { ckfree(varPtr); } else { VarHashInvalidateEntry(varPtr); TclSetVarUndefined(varPtr); VarHashRefCount(varPtr)--; } Tcl_DecrRefCount(objPtr); } static int CompareVarKeys( void *keyPtr, /* New key to compare. */ Tcl_HashEntry *hPtr) /* Existing key to compare. */ { Tcl_Obj *objPtr1 = keyPtr; Tcl_Obj *objPtr2 = hPtr->key.objPtr; register const char *p1, *p2; register int l1, l2; /* * If the object pointers are the same then they match. * OPT: this comparison was moved to the caller if (objPtr1 == objPtr2) return 1; */ /* * Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being in a * register. */ p1 = TclGetString(objPtr1); l1 = objPtr1->length; p2 = TclGetString(objPtr2); l2 = objPtr2->length; /* * Only compare string representations of the same length. */ return ((l1 == l2) && !memcmp(p1, p2, l1)); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclAssembly.c0000644000175000017500000040505612663660065015643 0ustar sergeisergei/* * tclAssembly.c -- * * Assembler for Tcl bytecodes. * * This file contains the procedures that convert Tcl Assembly Language (TAL) * to a sequence of bytecode instructions for the Tcl execution engine. * * Copyright (c) 2010 by Ozgur Dogan Ugurlu. * Copyright (c) 2010 by Kevin B. Kenny. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ /*- *- THINGS TO DO: *- More instructions: *- done - alternate exit point (affects stack and exception range checking) *- break and continue - if exception ranges can be sorted out. *- foreach_start4, foreach_step4 *- returnImm, returnStk *- expandStart, expandStkTop, invokeExpanded, expandDrop *- dictFirst, dictNext, dictDone *- dictUpdateStart, dictUpdateEnd *- jumpTable testing *- syntax (?) *- returnCodeBranch *- tclooNext, tclooNextClass */ #include "tclInt.h" #include "tclCompile.h" #include "tclOOInt.h" /* * Structure that represents a range of instructions in the bytecode. */ typedef struct CodeRange { int startOffset; /* Start offset in the bytecode array */ int endOffset; /* End offset in the bytecode array */ } CodeRange; /* * State identified for a basic block's catch context. */ typedef enum BasicBlockCatchState { BBCS_UNKNOWN = 0, /* Catch context has not yet been identified */ BBCS_NONE, /* Block is outside of any catch */ BBCS_INCATCH, /* Block is within a catch context */ BBCS_CAUGHT /* Block is within a catch context and * may be executed after an exception fires */ } BasicBlockCatchState; /* * Structure that defines a basic block - a linear sequence of bytecode * instructions with no jumps in or out (including not changing the * state of any exception range). */ typedef struct BasicBlock { int originalStartOffset; /* Instruction offset before JUMP1s were * substituted with JUMP4's */ int startOffset; /* Instruction offset of the start of the * block */ int startLine; /* Line number in the input script of the * instruction at the start of the block */ int jumpOffset; /* Bytecode offset of the 'jump' instruction * that ends the block, or -1 if there is no * jump. */ int jumpLine; /* Line number in the input script of the * 'jump' instruction that ends the block, or * -1 if there is no jump */ struct BasicBlock* prevPtr; /* Immediate predecessor of this block */ struct BasicBlock* predecessor; /* Predecessor of this block in the spanning * tree */ struct BasicBlock* successor1; /* BasicBlock structure of the following * block: NULL at the end of the bytecode * sequence. */ Tcl_Obj* jumpTarget; /* Jump target label if the jump target is * unresolved */ int initialStackDepth; /* Absolute stack depth on entry */ int minStackDepth; /* Low-water relative stack depth */ int maxStackDepth; /* High-water relative stack depth */ int finalStackDepth; /* Relative stack depth on exit */ enum BasicBlockCatchState catchState; /* State of the block for 'catch' analysis */ int catchDepth; /* Number of nested catches in which the basic * block appears */ struct BasicBlock* enclosingCatch; /* BasicBlock structure of the last startCatch * executed on a path to this block, or NULL * if there is no enclosing catch */ int foreignExceptionBase; /* Base index of foreign exceptions */ int foreignExceptionCount; /* Count of foreign exceptions */ ExceptionRange* foreignExceptions; /* ExceptionRange structures for exception * ranges belonging to embedded scripts and * expressions in this block */ JumptableInfo* jtPtr; /* Jump table at the end of this basic block */ int flags; /* Boolean flags */ } BasicBlock; /* * Flags that pertain to a basic block. */ enum BasicBlockFlags { BB_VISITED = (1 << 0), /* Block has been visited in the current * traversal */ BB_FALLTHRU = (1 << 1), /* Control may pass from this block to a * successor */ BB_JUMP1 = (1 << 2), /* Basic block ends with a 1-byte-offset jump * and may need expansion */ BB_JUMPTABLE = (1 << 3), /* Basic block ends with a jump table */ BB_BEGINCATCH = (1 << 4), /* Block ends with a 'beginCatch' instruction, * marking it as the start of a 'catch' * sequence. The 'jumpTarget' is the exception * exit from the catch block. */ BB_ENDCATCH = (1 << 5) /* Block ends with an 'endCatch' instruction, * unwinding the catch from the exception * stack. */ }; /* * Source instruction type recognized by the assembler. */ typedef enum TalInstType { ASSEM_1BYTE, /* Fixed arity, 1-byte instruction */ ASSEM_BEGIN_CATCH, /* Begin catch: one 4-byte jump offset to be * converted to appropriate exception * ranges */ ASSEM_BOOL, /* One Boolean operand */ ASSEM_BOOL_LVT4, /* One Boolean, one 4-byte LVT ref. */ ASSEM_CONCAT1, /* 1-byte unsigned-integer operand count, must * be strictly positive, consumes N, produces * 1 */ ASSEM_DICT_GET, /* 'dict get' and related - consumes N+1 * operands, produces 1, N > 0 */ ASSEM_DICT_SET, /* specifies key count and LVT index, consumes * N+1 operands, produces 1, N > 0 */ ASSEM_DICT_UNSET, /* specifies key count and LVT index, consumes * N operands, produces 1, N > 0 */ ASSEM_END_CATCH, /* End catch. No args. Exception range popped * from stack and stack pointer restored. */ ASSEM_EVAL, /* 'eval' - evaluate a constant script (by * compiling it in line with the assembly * code! I love Tcl!) */ ASSEM_INDEX, /* 4 byte operand, integer or end-integer */ ASSEM_INVOKE, /* 1- or 4-byte operand count, must be * strictly positive, consumes N, produces * 1. */ ASSEM_JUMP, /* Jump instructions */ ASSEM_JUMP4, /* Jump instructions forcing a 4-byte offset */ ASSEM_JUMPTABLE, /* Jumptable (switch -exact) */ ASSEM_LABEL, /* The assembly directive that defines a * label */ ASSEM_LINDEX_MULTI, /* 4-byte operand count, must be strictly * positive, consumes N, produces 1 */ ASSEM_LIST, /* 4-byte operand count, must be nonnegative, * consumses N, produces 1 */ ASSEM_LSET_FLAT, /* 4-byte operand count, must be >= 3, * consumes N, produces 1 */ ASSEM_LVT, /* One operand that references a local * variable */ ASSEM_LVT1, /* One 1-byte operand that references a local * variable */ ASSEM_LVT1_SINT1, /* One 1-byte operand that references a local * variable, one signed-integer 1-byte * operand */ ASSEM_LVT4, /* One 4-byte operand that references a local * variable */ ASSEM_OVER, /* OVER: 4-byte operand count, consumes N+1, * produces N+2 */ ASSEM_PUSH, /* one literal operand */ ASSEM_REGEXP, /* One Boolean operand, but weird mapping to * call flags */ ASSEM_REVERSE, /* REVERSE: 4-byte operand count, consumes N, * produces N */ ASSEM_SINT1, /* One 1-byte signed-integer operand * (INCR_STK_IMM) */ ASSEM_SINT4_LVT4 /* Signed 4-byte integer operand followed by * LVT entry. Fixed arity */ } TalInstType; /* * Description of an instruction recognized by the assembler. */ typedef struct TalInstDesc { const char *name; /* Name of instruction. */ TalInstType instType; /* The type of instruction */ int tclInstCode; /* Instruction code. For instructions having * 1- and 4-byte variables, tclInstCode is * ((1byte)<<8) || (4byte) */ int operandsConsumed; /* Number of operands consumed by the * operation, or INT_MIN if the operation is * variadic */ int operandsProduced; /* Number of operands produced by the * operation. If negative, the operation has a * net stack effect of -1-operandsProduced */ } TalInstDesc; /* * Structure that holds the state of the assembler while generating code. */ typedef struct AssemblyEnv { CompileEnv* envPtr; /* Compilation environment being used for code * generation */ Tcl_Parse* parsePtr; /* Parse of the current line of source */ Tcl_HashTable labelHash; /* Hash table whose keys are labels and whose * values are 'label' objects storing the code * offsets of the labels. */ int cmdLine; /* Current line number within the assembly * code */ int* clNext; /* Invisible continuation line for * [info frame] */ BasicBlock* head_bb; /* First basic block in the code */ BasicBlock* curr_bb; /* Current basic block */ int maxDepth; /* Maximum stack depth encountered */ int curCatchDepth; /* Current depth of catches */ int maxCatchDepth; /* Maximum depth of catches encountered */ int flags; /* Compilation flags (TCL_EVAL_DIRECT) */ } AssemblyEnv; /* * Static functions defined in this file. */ static void AddBasicBlockRangeToErrorInfo(AssemblyEnv*, BasicBlock*); static BasicBlock * AllocBB(AssemblyEnv*); static int AssembleOneLine(AssemblyEnv* envPtr); static void BBAdjustStackDepth(BasicBlock* bbPtr, int consumed, int produced); static void BBUpdateStackReqs(BasicBlock* bbPtr, int tblIdx, int count); static void BBEmitInstInt1(AssemblyEnv* assemEnvPtr, int tblIdx, int opnd, int count); static void BBEmitInstInt4(AssemblyEnv* assemEnvPtr, int tblIdx, int opnd, int count); static void BBEmitInst1or4(AssemblyEnv* assemEnvPtr, int tblIdx, int param, int count); static void BBEmitOpcode(AssemblyEnv* assemEnvPtr, int tblIdx, int count); static int BuildExceptionRanges(AssemblyEnv* assemEnvPtr); static int CalculateJumpRelocations(AssemblyEnv*, int*); static int CheckForUnclosedCatches(AssemblyEnv*); static int CheckForThrowInWrongContext(AssemblyEnv*); static int CheckNonThrowingBlock(AssemblyEnv*, BasicBlock*); static int BytecodeMightThrow(unsigned char); static int CheckJumpTableLabels(AssemblyEnv*, BasicBlock*); static int CheckNamespaceQualifiers(Tcl_Interp*, const char*, int); static int CheckNonNegative(Tcl_Interp*, int); static int CheckOneByte(Tcl_Interp*, int); static int CheckSignedOneByte(Tcl_Interp*, int); static int CheckStack(AssemblyEnv*); static int CheckStrictlyPositive(Tcl_Interp*, int); static ByteCode * CompileAssembleObj(Tcl_Interp *interp, Tcl_Obj *objPtr); static void CompileEmbeddedScript(AssemblyEnv*, Tcl_Token*, const TalInstDesc*); static int DefineLabel(AssemblyEnv* envPtr, const char* label); static void DeleteMirrorJumpTable(JumptableInfo* jtPtr); static void DupAssembleCodeInternalRep(Tcl_Obj* src, Tcl_Obj* dest); static void FillInJumpOffsets(AssemblyEnv*); static int CreateMirrorJumpTable(AssemblyEnv* assemEnvPtr, Tcl_Obj* jumpTable); static int FindLocalVar(AssemblyEnv* envPtr, Tcl_Token** tokenPtrPtr); static int FinishAssembly(AssemblyEnv*); static void FreeAssembleCodeInternalRep(Tcl_Obj *objPtr); static void FreeAssemblyEnv(AssemblyEnv*); static int GetBooleanOperand(AssemblyEnv*, Tcl_Token**, int*); static int GetListIndexOperand(AssemblyEnv*, Tcl_Token**, int*); static int GetIntegerOperand(AssemblyEnv*, Tcl_Token**, int*); static int GetNextOperand(AssemblyEnv*, Tcl_Token**, Tcl_Obj**); static void LookForFreshCatches(BasicBlock*, BasicBlock**); static void MoveCodeForJumps(AssemblyEnv*, int); static void MoveExceptionRangesToBasicBlock(AssemblyEnv*, int, int); static AssemblyEnv* NewAssemblyEnv(CompileEnv*, int); static int ProcessCatches(AssemblyEnv*); static int ProcessCatchesInBasicBlock(AssemblyEnv*, BasicBlock*, BasicBlock*, enum BasicBlockCatchState, int); static void ResetVisitedBasicBlocks(AssemblyEnv*); static void ResolveJumpTableTargets(AssemblyEnv*, BasicBlock*); static void ReportUndefinedLabel(AssemblyEnv*, BasicBlock*, Tcl_Obj*); static void RestoreEmbeddedExceptionRanges(AssemblyEnv*); static int StackCheckBasicBlock(AssemblyEnv*, BasicBlock *, BasicBlock *, int); static BasicBlock* StartBasicBlock(AssemblyEnv*, int fallthrough, Tcl_Obj* jumpLabel); /* static int AdvanceIp(const unsigned char *pc); */ static int StackCheckBasicBlock(AssemblyEnv*, BasicBlock *, BasicBlock *, int); static int StackCheckExit(AssemblyEnv*); static void StackFreshCatches(AssemblyEnv*, BasicBlock*, int, BasicBlock**, int*); static void SyncStackDepth(AssemblyEnv*); static int TclAssembleCode(CompileEnv* envPtr, const char* code, int codeLen, int flags); static void UnstackExpiredCatches(CompileEnv*, BasicBlock*, int, BasicBlock**, int*); /* * Tcl_ObjType that describes bytecode emitted by the assembler. */ static const Tcl_ObjType assembleCodeType = { "assemblecode", FreeAssembleCodeInternalRep, /* freeIntRepProc */ DupAssembleCodeInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ NULL /* setFromAnyProc */ }; /* * Source instructions recognized in the Tcl Assembly Language (TAL) */ static const TalInstDesc TalInstructionTable[] = { /* PUSH must be first, see the code near the end of TclAssembleCode */ {"push", ASSEM_PUSH, (INST_PUSH1<<8 | INST_PUSH4), 0, 1}, {"add", ASSEM_1BYTE, INST_ADD, 2, 1}, {"append", ASSEM_LVT, (INST_APPEND_SCALAR1<<8 | INST_APPEND_SCALAR4),1, 1}, {"appendArray", ASSEM_LVT, (INST_APPEND_ARRAY1<<8 | INST_APPEND_ARRAY4), 2, 1}, {"appendArrayStk", ASSEM_1BYTE, INST_APPEND_ARRAY_STK, 3, 1}, {"appendStk", ASSEM_1BYTE, INST_APPEND_STK, 2, 1}, {"arrayExistsImm", ASSEM_LVT4, INST_ARRAY_EXISTS_IMM, 0, 1}, {"arrayExistsStk", ASSEM_1BYTE, INST_ARRAY_EXISTS_STK, 1, 1}, {"arrayMakeImm", ASSEM_LVT4, INST_ARRAY_MAKE_IMM, 0, 0}, {"arrayMakeStk", ASSEM_1BYTE, INST_ARRAY_MAKE_STK, 1, 0}, {"beginCatch", ASSEM_BEGIN_CATCH, INST_BEGIN_CATCH4, 0, 0}, {"bitand", ASSEM_1BYTE, INST_BITAND, 2, 1}, {"bitnot", ASSEM_1BYTE, INST_BITNOT, 1, 1}, {"bitor", ASSEM_1BYTE, INST_BITOR, 2, 1}, {"bitxor", ASSEM_1BYTE, INST_BITXOR, 2, 1}, {"concat", ASSEM_CONCAT1, INST_STR_CONCAT1, INT_MIN,1}, {"concatStk", ASSEM_LIST, INST_CONCAT_STK, INT_MIN,1}, {"coroName", ASSEM_1BYTE, INST_COROUTINE_NAME, 0, 1}, {"currentNamespace",ASSEM_1BYTE, INST_NS_CURRENT, 0, 1}, {"dictAppend", ASSEM_LVT4, INST_DICT_APPEND, 2, 1}, {"dictExists", ASSEM_DICT_GET, INST_DICT_EXISTS, INT_MIN,1}, {"dictExpand", ASSEM_1BYTE, INST_DICT_EXPAND, 3, 1}, {"dictGet", ASSEM_DICT_GET, INST_DICT_GET, INT_MIN,1}, {"dictIncrImm", ASSEM_SINT4_LVT4, INST_DICT_INCR_IMM, 1, 1}, {"dictLappend", ASSEM_LVT4, INST_DICT_LAPPEND, 2, 1}, {"dictRecombineStk",ASSEM_1BYTE, INST_DICT_RECOMBINE_STK,3, 0}, {"dictRecombineImm",ASSEM_LVT4, INST_DICT_RECOMBINE_IMM,2, 0}, {"dictSet", ASSEM_DICT_SET, INST_DICT_SET, INT_MIN,1}, {"dictUnset", ASSEM_DICT_UNSET, INST_DICT_UNSET, INT_MIN,1}, {"div", ASSEM_1BYTE, INST_DIV, 2, 1}, {"dup", ASSEM_1BYTE, INST_DUP, 1, 2}, {"endCatch", ASSEM_END_CATCH,INST_END_CATCH, 0, 0}, {"eq", ASSEM_1BYTE, INST_EQ, 2, 1}, {"eval", ASSEM_EVAL, INST_EVAL_STK, 1, 1}, {"evalStk", ASSEM_1BYTE, INST_EVAL_STK, 1, 1}, {"exist", ASSEM_LVT4, INST_EXIST_SCALAR, 0, 1}, {"existArray", ASSEM_LVT4, INST_EXIST_ARRAY, 1, 1}, {"existArrayStk", ASSEM_1BYTE, INST_EXIST_ARRAY_STK, 2, 1}, {"existStk", ASSEM_1BYTE, INST_EXIST_STK, 1, 1}, {"expon", ASSEM_1BYTE, INST_EXPON, 2, 1}, {"expr", ASSEM_EVAL, INST_EXPR_STK, 1, 1}, {"exprStk", ASSEM_1BYTE, INST_EXPR_STK, 1, 1}, {"ge", ASSEM_1BYTE, INST_GE, 2, 1}, {"gt", ASSEM_1BYTE, INST_GT, 2, 1}, {"incr", ASSEM_LVT1, INST_INCR_SCALAR1, 1, 1}, {"incrArray", ASSEM_LVT1, INST_INCR_ARRAY1, 2, 1}, {"incrArrayImm", ASSEM_LVT1_SINT1, INST_INCR_ARRAY1_IMM, 1, 1}, {"incrArrayStk", ASSEM_1BYTE, INST_INCR_ARRAY_STK, 3, 1}, {"incrArrayStkImm", ASSEM_SINT1, INST_INCR_ARRAY_STK_IMM,2, 1}, {"incrImm", ASSEM_LVT1_SINT1, INST_INCR_SCALAR1_IMM, 0, 1}, {"incrStk", ASSEM_1BYTE, INST_INCR_STK, 2, 1}, {"incrStkImm", ASSEM_SINT1, INST_INCR_STK_IMM, 1, 1}, {"infoLevelArgs", ASSEM_1BYTE, INST_INFO_LEVEL_ARGS, 1, 1}, {"infoLevelNumber", ASSEM_1BYTE, INST_INFO_LEVEL_NUM, 0, 1}, {"invokeStk", ASSEM_INVOKE, (INST_INVOKE_STK1 << 8 | INST_INVOKE_STK4), INT_MIN,1}, {"jump", ASSEM_JUMP, INST_JUMP1, 0, 0}, {"jump4", ASSEM_JUMP4, INST_JUMP4, 0, 0}, {"jumpFalse", ASSEM_JUMP, INST_JUMP_FALSE1, 1, 0}, {"jumpFalse4", ASSEM_JUMP4, INST_JUMP_FALSE4, 1, 0}, {"jumpTable", ASSEM_JUMPTABLE,INST_JUMP_TABLE, 1, 0}, {"jumpTrue", ASSEM_JUMP, INST_JUMP_TRUE1, 1, 0}, {"jumpTrue4", ASSEM_JUMP4, INST_JUMP_TRUE4, 1, 0}, {"label", ASSEM_LABEL, 0, 0, 0}, {"land", ASSEM_1BYTE, INST_LAND, 2, 1}, {"lappend", ASSEM_LVT, (INST_LAPPEND_SCALAR1<<8 | INST_LAPPEND_SCALAR4), 1, 1}, {"lappendArray", ASSEM_LVT, (INST_LAPPEND_ARRAY1<<8 | INST_LAPPEND_ARRAY4),2, 1}, {"lappendArrayStk", ASSEM_1BYTE, INST_LAPPEND_ARRAY_STK, 3, 1}, {"lappendList", ASSEM_LVT4, INST_LAPPEND_LIST, 1, 1}, {"lappendListArray",ASSEM_LVT4, INST_LAPPEND_LIST_ARRAY,2, 1}, {"lappendListArrayStk", ASSEM_1BYTE,INST_LAPPEND_LIST_ARRAY_STK, 3, 1}, {"lappendListStk", ASSEM_1BYTE, INST_LAPPEND_LIST_STK, 2, 1}, {"lappendStk", ASSEM_1BYTE, INST_LAPPEND_STK, 2, 1}, {"le", ASSEM_1BYTE, INST_LE, 2, 1}, {"lindexMulti", ASSEM_LINDEX_MULTI, INST_LIST_INDEX_MULTI, INT_MIN,1}, {"list", ASSEM_LIST, INST_LIST, INT_MIN,1}, {"listConcat", ASSEM_1BYTE, INST_LIST_CONCAT, 2, 1}, {"listIn", ASSEM_1BYTE, INST_LIST_IN, 2, 1}, {"listIndex", ASSEM_1BYTE, INST_LIST_INDEX, 2, 1}, {"listIndexImm", ASSEM_INDEX, INST_LIST_INDEX_IMM, 1, 1}, {"listLength", ASSEM_1BYTE, INST_LIST_LENGTH, 1, 1}, {"listNotIn", ASSEM_1BYTE, INST_LIST_NOT_IN, 2, 1}, {"load", ASSEM_LVT, (INST_LOAD_SCALAR1 << 8 | INST_LOAD_SCALAR4), 0, 1}, {"loadArray", ASSEM_LVT, (INST_LOAD_ARRAY1<<8 | INST_LOAD_ARRAY4), 1, 1}, {"loadArrayStk", ASSEM_1BYTE, INST_LOAD_ARRAY_STK, 2, 1}, {"loadStk", ASSEM_1BYTE, INST_LOAD_STK, 1, 1}, {"lor", ASSEM_1BYTE, INST_LOR, 2, 1}, {"lsetFlat", ASSEM_LSET_FLAT,INST_LSET_FLAT, INT_MIN,1}, {"lsetList", ASSEM_1BYTE, INST_LSET_LIST, 3, 1}, {"lshift", ASSEM_1BYTE, INST_LSHIFT, 2, 1}, {"lt", ASSEM_1BYTE, INST_LT, 2, 1}, {"mod", ASSEM_1BYTE, INST_MOD, 2, 1}, {"mult", ASSEM_1BYTE, INST_MULT, 2, 1}, {"neq", ASSEM_1BYTE, INST_NEQ, 2, 1}, {"nop", ASSEM_1BYTE, INST_NOP, 0, 0}, {"not", ASSEM_1BYTE, INST_LNOT, 1, 1}, {"nsupvar", ASSEM_LVT4, INST_NSUPVAR, 2, 1}, {"numericType", ASSEM_1BYTE, INST_NUM_TYPE, 1, 1}, {"originCmd", ASSEM_1BYTE, INST_ORIGIN_COMMAND, 1, 1}, {"over", ASSEM_OVER, INST_OVER, INT_MIN,-1-1}, {"pop", ASSEM_1BYTE, INST_POP, 1, 0}, {"pushReturnCode", ASSEM_1BYTE, INST_PUSH_RETURN_CODE, 0, 1}, {"pushReturnOpts", ASSEM_1BYTE, INST_PUSH_RETURN_OPTIONS, 0, 1}, {"pushResult", ASSEM_1BYTE, INST_PUSH_RESULT, 0, 1}, {"regexp", ASSEM_REGEXP, INST_REGEXP, 2, 1}, {"resolveCmd", ASSEM_1BYTE, INST_RESOLVE_COMMAND, 1, 1}, {"reverse", ASSEM_REVERSE, INST_REVERSE, INT_MIN,-1-0}, {"rshift", ASSEM_1BYTE, INST_RSHIFT, 2, 1}, {"store", ASSEM_LVT, (INST_STORE_SCALAR1<<8 | INST_STORE_SCALAR4), 1, 1}, {"storeArray", ASSEM_LVT, (INST_STORE_ARRAY1<<8 | INST_STORE_ARRAY4), 2, 1}, {"storeArrayStk", ASSEM_1BYTE, INST_STORE_ARRAY_STK, 3, 1}, {"storeStk", ASSEM_1BYTE, INST_STORE_STK, 2, 1}, {"strcaseLower", ASSEM_1BYTE, INST_STR_LOWER, 1, 1}, {"strcaseTitle", ASSEM_1BYTE, INST_STR_TITLE, 1, 1}, {"strcaseUpper", ASSEM_1BYTE, INST_STR_UPPER, 1, 1}, {"strcmp", ASSEM_1BYTE, INST_STR_CMP, 2, 1}, {"strcat", ASSEM_CONCAT1, INST_STR_CONCAT1, INT_MIN,1}, {"streq", ASSEM_1BYTE, INST_STR_EQ, 2, 1}, {"strfind", ASSEM_1BYTE, INST_STR_FIND, 2, 1}, {"strindex", ASSEM_1BYTE, INST_STR_INDEX, 2, 1}, {"strlen", ASSEM_1BYTE, INST_STR_LEN, 1, 1}, {"strmap", ASSEM_1BYTE, INST_STR_MAP, 3, 1}, {"strmatch", ASSEM_BOOL, INST_STR_MATCH, 2, 1}, {"strneq", ASSEM_1BYTE, INST_STR_NEQ, 2, 1}, {"strrange", ASSEM_1BYTE, INST_STR_RANGE, 3, 1}, {"strreplace", ASSEM_1BYTE, INST_STR_REPLACE, 4, 1}, {"strrfind", ASSEM_1BYTE, INST_STR_FIND_LAST, 2, 1}, {"strtrim", ASSEM_1BYTE, INST_STR_TRIM, 2, 1}, {"strtrimLeft", ASSEM_1BYTE, INST_STR_TRIM_LEFT, 2, 1}, {"strtrimRight", ASSEM_1BYTE, INST_STR_TRIM_RIGHT, 2, 1}, {"sub", ASSEM_1BYTE, INST_SUB, 2, 1}, {"tclooClass", ASSEM_1BYTE, INST_TCLOO_CLASS, 1, 1}, {"tclooIsObject", ASSEM_1BYTE, INST_TCLOO_IS_OBJECT, 1, 1}, {"tclooNamespace", ASSEM_1BYTE, INST_TCLOO_NS, 1, 1}, {"tclooSelf", ASSEM_1BYTE, INST_TCLOO_SELF, 0, 1}, {"tryCvtToBoolean", ASSEM_1BYTE, INST_TRY_CVT_TO_BOOLEAN,1, 2}, {"tryCvtToNumeric", ASSEM_1BYTE, INST_TRY_CVT_TO_NUMERIC,1, 1}, {"uminus", ASSEM_1BYTE, INST_UMINUS, 1, 1}, {"unset", ASSEM_BOOL_LVT4,INST_UNSET_SCALAR, 0, 0}, {"unsetArray", ASSEM_BOOL_LVT4,INST_UNSET_ARRAY, 1, 0}, {"unsetArrayStk", ASSEM_BOOL, INST_UNSET_ARRAY_STK, 2, 0}, {"unsetStk", ASSEM_BOOL, INST_UNSET_STK, 1, 0}, {"uplus", ASSEM_1BYTE, INST_UPLUS, 1, 1}, {"upvar", ASSEM_LVT4, INST_UPVAR, 2, 1}, {"variable", ASSEM_LVT4, INST_VARIABLE, 1, 0}, {"verifyDict", ASSEM_1BYTE, INST_DICT_VERIFY, 1, 0}, {"yield", ASSEM_1BYTE, INST_YIELD, 1, 1}, {NULL, 0, 0, 0, 0} }; /* * List of instructions that cannot throw an exception under any * circumstances. These instructions are the ones that are permissible after * an exception is caught but before the corresponding exception range is * popped from the stack. * The instructions must be in ascending order by numeric operation code. */ static const unsigned char NonThrowingByteCodes[] = { INST_PUSH1, INST_PUSH4, INST_POP, INST_DUP, /* 1-4 */ INST_JUMP1, INST_JUMP4, /* 34-35 */ INST_END_CATCH, INST_PUSH_RESULT, INST_PUSH_RETURN_CODE, /* 70-72 */ INST_LIST, /* 79 */ INST_OVER, /* 95 */ INST_PUSH_RETURN_OPTIONS, /* 108 */ INST_REVERSE, /* 126 */ INST_NOP, /* 132 */ INST_STR_MAP, /* 143 */ INST_STR_FIND, /* 144 */ INST_COROUTINE_NAME, /* 149 */ INST_NS_CURRENT, /* 151 */ INST_INFO_LEVEL_NUM, /* 152 */ INST_RESOLVE_COMMAND, /* 154 */ INST_STR_TRIM, INST_STR_TRIM_LEFT, INST_STR_TRIM_RIGHT, /* 166-168 */ INST_CONCAT_STK, /* 169 */ INST_STR_UPPER, INST_STR_LOWER, INST_STR_TITLE, /* 170-172 */ INST_NUM_TYPE /* 180 */ }; /* * Helper macros. */ #if defined(TCL_DEBUG_ASSEMBLY) && defined(__GNUC__) && __GNUC__ > 2 #define DEBUG_PRINT(...) fprintf(stderr, ##__VA_ARGS__);fflush(stderr) #elif defined(__GNUC__) && __GNUC__ > 2 #define DEBUG_PRINT(...) /* nothing */ #else #define DEBUG_PRINT /* nothing */ #endif /* *----------------------------------------------------------------------------- * * BBAdjustStackDepth -- * * When an opcode is emitted, adjusts the stack information in the basic * block to reflect the number of operands produced and consumed. * * Results: * None. * * Side effects: * Updates minimum, maximum and final stack requirements in the basic * block. * *----------------------------------------------------------------------------- */ static void BBAdjustStackDepth( BasicBlock *bbPtr, /* Structure describing the basic block */ int consumed, /* Count of operands consumed by the * operation */ int produced) /* Count of operands produced by the * operation */ { int depth = bbPtr->finalStackDepth; depth -= consumed; if (depth < bbPtr->minStackDepth) { bbPtr->minStackDepth = depth; } depth += produced; if (depth > bbPtr->maxStackDepth) { bbPtr->maxStackDepth = depth; } bbPtr->finalStackDepth = depth; } /* *----------------------------------------------------------------------------- * * BBUpdateStackReqs -- * * Updates the stack requirements of a basic block, given the opcode * being emitted and an operand count. * * Results: * None. * * Side effects: * Updates min, max and final stack requirements in the basic block. * * Notes: * This function must not be called for instructions such as REVERSE and * OVER that are variadic but do not consume all their operands. Instead, * BBAdjustStackDepth should be called directly. * * count should be provided only for variadic operations. For operations * with known arity, count should be 0. * *----------------------------------------------------------------------------- */ static void BBUpdateStackReqs( BasicBlock* bbPtr, /* Structure describing the basic block */ int tblIdx, /* Index in TalInstructionTable of the * operation being assembled */ int count) /* Count of operands for variadic insts */ { int consumed = TalInstructionTable[tblIdx].operandsConsumed; int produced = TalInstructionTable[tblIdx].operandsProduced; if (consumed == INT_MIN) { /* * The instruction is variadic; it consumes 'count' operands. */ consumed = count; } if (produced < 0) { /* * The instruction leaves some of its variadic operands on the stack, * with net stack effect of '-1-produced' */ produced = consumed - produced - 1; } BBAdjustStackDepth(bbPtr, consumed, produced); } /* *----------------------------------------------------------------------------- * * BBEmitOpcode, BBEmitInstInt1, BBEmitInstInt4 -- * * Emit the opcode part of an instruction, or the entirety of an * instruction with a 1- or 4-byte operand, and adjust stack * requirements. * * Results: * None. * * Side effects: * Stores instruction and operand in the operand stream, and adjusts the * stack. * *----------------------------------------------------------------------------- */ static void BBEmitOpcode( AssemblyEnv* assemEnvPtr, /* Assembly environment */ int tblIdx, /* Table index in TalInstructionTable of op */ int count) /* Operand count for variadic ops */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ BasicBlock* bbPtr = assemEnvPtr->curr_bb; /* Current basic block */ int op = TalInstructionTable[tblIdx].tclInstCode & 0xff; /* * If this is the first instruction in a basic block, record its line * number. */ if (bbPtr->startOffset == envPtr->codeNext - envPtr->codeStart) { bbPtr->startLine = assemEnvPtr->cmdLine; } TclEmitInt1(op, envPtr); TclUpdateAtCmdStart(op, envPtr); BBUpdateStackReqs(bbPtr, tblIdx, count); } static void BBEmitInstInt1( AssemblyEnv* assemEnvPtr, /* Assembly environment */ int tblIdx, /* Index in TalInstructionTable of op */ int opnd, /* 1-byte operand */ int count) /* Operand count for variadic ops */ { BBEmitOpcode(assemEnvPtr, tblIdx, count); TclEmitInt1(opnd, assemEnvPtr->envPtr); } static void BBEmitInstInt4( AssemblyEnv* assemEnvPtr, /* Assembly environment */ int tblIdx, /* Index in TalInstructionTable of op */ int opnd, /* 4-byte operand */ int count) /* Operand count for variadic ops */ { BBEmitOpcode(assemEnvPtr, tblIdx, count); TclEmitInt4(opnd, assemEnvPtr->envPtr); } /* *----------------------------------------------------------------------------- * * BBEmitInst1or4 -- * * Emits a 1- or 4-byte operation according to the magnitude of the * operand. * *----------------------------------------------------------------------------- */ static void BBEmitInst1or4( AssemblyEnv* assemEnvPtr, /* Assembly environment */ int tblIdx, /* Index in TalInstructionTable of op */ int param, /* Variable-length parameter */ int count) /* Arity if variadic */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ BasicBlock* bbPtr = assemEnvPtr->curr_bb; /* Current basic block */ int op = TalInstructionTable[tblIdx].tclInstCode; if (param <= 0xff) { op >>= 8; } else { op &= 0xff; } TclEmitInt1(op, envPtr); if (param <= 0xff) { TclEmitInt1(param, envPtr); } else { TclEmitInt4(param, envPtr); } TclUpdateAtCmdStart(op, envPtr); BBUpdateStackReqs(bbPtr, tblIdx, count); } /* *----------------------------------------------------------------------------- * * Tcl_AssembleObjCmd, TclNRAssembleObjCmd -- * * Direct evaluation path for tcl::unsupported::assemble * * Results: * Returns a standard Tcl result. * * Side effects: * Assembles the code in objv[1], and executes it, so side effects * include whatever the code does. * *----------------------------------------------------------------------------- */ int Tcl_AssembleObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { /* * Boilerplate - make sure that there is an NRE trampoline on the C stack * because there needs to be one in place to execute bytecode. */ return Tcl_NRCallObjProc(interp, TclNRAssembleObjCmd, dummy, objc, objv); } int TclNRAssembleObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { ByteCode *codePtr; /* Pointer to the bytecode to execute */ Tcl_Obj* backtrace; /* Object where extra error information is * constructed. */ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "bytecodeList"); return TCL_ERROR; } /* * Assemble the source to bytecode. */ codePtr = CompileAssembleObj(interp, objv[1]); /* * On failure, report error line. */ if (codePtr == NULL) { Tcl_AddErrorInfo(interp, "\n (\""); Tcl_AppendObjToErrorInfo(interp, objv[0]); Tcl_AddErrorInfo(interp, "\" body, line "); backtrace = Tcl_NewIntObj(Tcl_GetErrorLine(interp)); Tcl_AppendObjToErrorInfo(interp, backtrace); Tcl_AddErrorInfo(interp, ")"); return TCL_ERROR; } /* * Use NRE to evaluate the bytecode from the trampoline. */ return TclNRExecuteByteCode(interp, codePtr); } /* *----------------------------------------------------------------------------- * * CompileAssembleObj -- * * Sets up and assembles Tcl bytecode for the direct-execution path in * the Tcl bytecode assembler. * * Results: * Returns a pointer to the assembled code. Returns NULL if the assembly * fails for any reason, with an appropriate error message in the * interpreter. * *----------------------------------------------------------------------------- */ static ByteCode * CompileAssembleObj( Tcl_Interp *interp, /* Tcl interpreter */ Tcl_Obj *objPtr) /* Source code to assemble */ { Interp *iPtr = (Interp *) interp; /* Internals of the interpreter */ CompileEnv compEnv; /* Compilation environment structure */ register ByteCode *codePtr = NULL; /* Bytecode resulting from the assembly */ Namespace* namespacePtr; /* Namespace in which variable and command * names in the bytecode resolve */ int status; /* Status return from Tcl_AssembleCode */ const char* source; /* String representation of the source code */ int sourceLen; /* Length of the source code in bytes */ /* * Get the expression ByteCode from the object. If it exists, make sure it * is valid in the current context. */ if (objPtr->typePtr == &assembleCodeType) { namespacePtr = iPtr->varFramePtr->nsPtr; codePtr = objPtr->internalRep.twoPtrValue.ptr1; if (((Interp *) *codePtr->interpHandle == iPtr) && (codePtr->compileEpoch == iPtr->compileEpoch) && (codePtr->nsPtr == namespacePtr) && (codePtr->nsEpoch == namespacePtr->resolverEpoch) && (codePtr->localCachePtr == iPtr->varFramePtr->localCachePtr)) { return codePtr; } /* * Not valid, so free it and regenerate. */ FreeAssembleCodeInternalRep(objPtr); } /* * Set up the compilation environment, and assemble the code. */ source = TclGetStringFromObj(objPtr, &sourceLen); TclInitCompileEnv(interp, &compEnv, source, sourceLen, NULL, 0); status = TclAssembleCode(&compEnv, source, sourceLen, TCL_EVAL_DIRECT); if (status != TCL_OK) { /* * Assembly failed. Clean up and report the error. */ TclFreeCompileEnv(&compEnv); return NULL; } /* * Add a "done" instruction as the last instruction and change the object * into a ByteCode object. Ownership of the literal objects and aux data * items is given to the ByteCode object. */ TclEmitOpcode(INST_DONE, &compEnv); TclInitByteCodeObj(objPtr, &compEnv); objPtr->typePtr = &assembleCodeType; TclFreeCompileEnv(&compEnv); /* * Record the local variable context to which the bytecode pertains */ codePtr = objPtr->internalRep.twoPtrValue.ptr1; if (iPtr->varFramePtr->localCachePtr) { codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr; codePtr->localCachePtr->refCount++; } /* * Report on what the assembler did. */ #ifdef TCL_COMPILE_DEBUG if (tclTraceCompile >= 2) { TclPrintByteCodeObj(interp, objPtr); fflush(stdout); } #endif /* TCL_COMPILE_DEBUG */ return codePtr; } /* *----------------------------------------------------------------------------- * * TclCompileAssembleCmd -- * * Compilation procedure for the '::tcl::unsupported::assemble' command. * * Results: * Returns a standard Tcl result. * * Side effects: * Puts the result of assembling the code into the bytecode stream in * 'compileEnv'. * * This procedure makes sure that the command has a single arg, which is * constant. If that condition is met, the procedure calls TclAssembleCode to * produce bytecode for the given assembly code, and returns any error * resulting from the assembly. * *----------------------------------------------------------------------------- */ int TclCompileAssembleCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; /* Token in the input script */ int numCommands = envPtr->numCommands; int offset = envPtr->codeNext - envPtr->codeStart; int depth = envPtr->currStackDepth; /* * Make sure that the command has a single arg that is a simple word. */ if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TCL_ERROR; } /* * Compile the code and convert any error from the compilation into * bytecode reporting the error; */ if (TCL_ERROR == TclAssembleCode(envPtr, tokenPtr[1].start, tokenPtr[1].size, TCL_EVAL_DIRECT)) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%.*s\" body, line %d)", parsePtr->tokenPtr->size, parsePtr->tokenPtr->start, Tcl_GetErrorLine(interp))); envPtr->numCommands = numCommands; envPtr->codeNext = envPtr->codeStart + offset; envPtr->currStackDepth = depth; TclCompileSyntaxError(interp, envPtr); } return TCL_OK; } /* *----------------------------------------------------------------------------- * * TclAssembleCode -- * * Take a list of instructions in a Tcl_Obj, and assemble them to Tcl * bytecodes * * Results: * Returns TCL_OK on success, TCL_ERROR on failure. If 'flags' includes * TCL_EVAL_DIRECT, places an error message in the interpreter result. * * Side effects: * Adds byte codes to the compile environment, and updates the * environment's stack depth. * *----------------------------------------------------------------------------- */ static int TclAssembleCode( CompileEnv *envPtr, /* Compilation environment that is to receive * the generated bytecode */ const char* codePtr, /* Assembly-language code to be processed */ int codeLen, /* Length of the code */ int flags) /* OR'ed combination of flags */ { Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ /* * Walk through the assembly script using the Tcl parser. Each 'command' * will be an instruction or assembly directive. */ const char* instPtr = codePtr; /* Where to start looking for a line of code */ const char* nextPtr; /* Pointer to the end of the line of code */ int bytesLeft = codeLen; /* Number of bytes of source code remaining to * be parsed */ int status; /* Tcl status return */ AssemblyEnv* assemEnvPtr = NewAssemblyEnv(envPtr, flags); Tcl_Parse* parsePtr = assemEnvPtr->parsePtr; do { /* * Parse out one command line from the assembly script. */ status = Tcl_ParseCommand(interp, instPtr, bytesLeft, 0, parsePtr); /* * Report errors in the parse. */ if (status != TCL_OK) { if (flags & TCL_EVAL_DIRECT) { Tcl_LogCommandInfo(interp, codePtr, parsePtr->commandStart, parsePtr->term + 1 - parsePtr->commandStart); } FreeAssemblyEnv(assemEnvPtr); return TCL_ERROR; } /* * Advance the pointers around any leading commentary. */ TclAdvanceLines(&assemEnvPtr->cmdLine, instPtr, parsePtr->commandStart); TclAdvanceContinuations(&assemEnvPtr->cmdLine, &assemEnvPtr->clNext, parsePtr->commandStart - envPtr->source); /* * Process the line of code. */ if (parsePtr->numWords > 0) { int instLen = parsePtr->commandSize; /* Length in bytes of the current command */ if (parsePtr->term == parsePtr->commandStart + instLen - 1) { --instLen; } /* * If tracing, show each line assembled as it happens. */ #ifdef TCL_COMPILE_DEBUG if ((tclTraceCompile >= 2) && (envPtr->procPtr == NULL)) { printf(" %4ld Assembling: ", (long)(envPtr->codeNext - envPtr->codeStart)); TclPrintSource(stdout, parsePtr->commandStart, TclMin(instLen, 55)); printf("\n"); } #endif if (AssembleOneLine(assemEnvPtr) != TCL_OK) { if (flags & TCL_EVAL_DIRECT) { Tcl_LogCommandInfo(interp, codePtr, parsePtr->commandStart, instLen); } Tcl_FreeParse(parsePtr); FreeAssemblyEnv(assemEnvPtr); return TCL_ERROR; } } /* * Advance to the next line of code. */ nextPtr = parsePtr->commandStart + parsePtr->commandSize; bytesLeft -= (nextPtr - instPtr); instPtr = nextPtr; TclAdvanceLines(&assemEnvPtr->cmdLine, parsePtr->commandStart, instPtr); TclAdvanceContinuations(&assemEnvPtr->cmdLine, &assemEnvPtr->clNext, instPtr - envPtr->source); Tcl_FreeParse(parsePtr); } while (bytesLeft > 0); /* * Done with parsing the code. */ status = FinishAssembly(assemEnvPtr); FreeAssemblyEnv(assemEnvPtr); return status; } /* *----------------------------------------------------------------------------- * * NewAssemblyEnv -- * * Creates an environment for the assembler to run in. * * Results: * Allocates, initialises and returns an assembler environment * *----------------------------------------------------------------------------- */ static AssemblyEnv* NewAssemblyEnv( CompileEnv* envPtr, /* Compilation environment being used for code * generation*/ int flags) /* Compilation flags (TCL_EVAL_DIRECT) */ { Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ AssemblyEnv* assemEnvPtr = TclStackAlloc(interp, sizeof(AssemblyEnv)); /* Assembler environment under construction */ Tcl_Parse* parsePtr = TclStackAlloc(interp, sizeof(Tcl_Parse)); /* Parse of one line of assembly code */ assemEnvPtr->envPtr = envPtr; assemEnvPtr->parsePtr = parsePtr; assemEnvPtr->cmdLine = 1; assemEnvPtr->clNext = envPtr->clNext; /* * Make the hashtables that store symbol resolution. */ Tcl_InitHashTable(&assemEnvPtr->labelHash, TCL_STRING_KEYS); /* * Start the first basic block. */ assemEnvPtr->curr_bb = NULL; assemEnvPtr->head_bb = AllocBB(assemEnvPtr); assemEnvPtr->curr_bb = assemEnvPtr->head_bb; assemEnvPtr->head_bb->startLine = 1; /* * Stash compilation flags. */ assemEnvPtr->flags = flags; return assemEnvPtr; } /* *----------------------------------------------------------------------------- * * FreeAssemblyEnv -- * * Cleans up the assembler environment when assembly is complete. * *----------------------------------------------------------------------------- */ static void FreeAssemblyEnv( AssemblyEnv* assemEnvPtr) /* Environment to free */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment being used for code * generation */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ BasicBlock* thisBB; /* Pointer to a basic block being deleted */ BasicBlock* nextBB; /* Pointer to a deleted basic block's * successor */ /* * Free all the basic block structures. */ for (thisBB = assemEnvPtr->head_bb; thisBB != NULL; thisBB = nextBB) { if (thisBB->jumpTarget != NULL) { Tcl_DecrRefCount(thisBB->jumpTarget); } if (thisBB->foreignExceptions != NULL) { ckfree(thisBB->foreignExceptions); } nextBB = thisBB->successor1; if (thisBB->jtPtr != NULL) { DeleteMirrorJumpTable(thisBB->jtPtr); thisBB->jtPtr = NULL; } ckfree(thisBB); } /* * Dispose what's left. */ Tcl_DeleteHashTable(&assemEnvPtr->labelHash); TclStackFree(interp, assemEnvPtr->parsePtr); TclStackFree(interp, assemEnvPtr); } /* *----------------------------------------------------------------------------- * * AssembleOneLine -- * * Assembles a single command from an assembly language source. * * Results: * Returns TCL_ERROR with an appropriate error message if the assembly * fails. Returns TCL_OK if the assembly succeeds. Updates the assembly * environment with the state of the assembly. * *----------------------------------------------------------------------------- */ static int AssembleOneLine( AssemblyEnv* assemEnvPtr) /* State of the assembly */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment being used for code * gen */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ Tcl_Parse* parsePtr = assemEnvPtr->parsePtr; /* Parse of the line of code */ Tcl_Token* tokenPtr; /* Current token within the line of code */ Tcl_Obj* instNameObj; /* Name of the instruction */ int tblIdx; /* Index in TalInstructionTable of the * instruction */ enum TalInstType instType; /* Type of the instruction */ Tcl_Obj* operand1Obj = NULL; /* First operand to the instruction */ const char* operand1; /* String rep of the operand */ int operand1Len; /* String length of the operand */ int opnd; /* Integer representation of an operand */ int litIndex; /* Literal pool index of a constant */ int localVar; /* LVT index of a local variable */ int flags; /* Flags for a basic block */ JumptableInfo* jtPtr; /* Pointer to a jumptable */ int infoIndex; /* Index of the jumptable in auxdata */ int status = TCL_ERROR; /* Return value from this function */ /* * Make sure that the instruction name is known at compile time. */ tokenPtr = parsePtr->tokenPtr; if (GetNextOperand(assemEnvPtr, &tokenPtr, &instNameObj) != TCL_OK) { return TCL_ERROR; } /* * Look up the instruction name. */ if (Tcl_GetIndexFromObjStruct(interp, instNameObj, &TalInstructionTable[0].name, sizeof(TalInstDesc), "instruction", TCL_EXACT, &tblIdx) != TCL_OK) { goto cleanup; } /* * Vector on the type of instruction being processed. */ instType = TalInstructionTable[tblIdx].instType; switch (instType) { case ASSEM_PUSH: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "value"); goto cleanup; } if (GetNextOperand(assemEnvPtr, &tokenPtr, &operand1Obj) != TCL_OK) { goto cleanup; } operand1 = Tcl_GetStringFromObj(operand1Obj, &operand1Len); litIndex = TclRegisterNewLiteral(envPtr, operand1, operand1Len); BBEmitInst1or4(assemEnvPtr, tblIdx, litIndex, 0); break; case ASSEM_1BYTE: if (parsePtr->numWords != 1) { Tcl_WrongNumArgs(interp, 1, &instNameObj, ""); goto cleanup; } BBEmitOpcode(assemEnvPtr, tblIdx, 0); break; case ASSEM_BEGIN_CATCH: /* * Emit the BEGIN_CATCH instruction with the code offset of the * exception branch target instead of the exception range index. The * correct index will be generated and inserted later, when catches * are being resolved. */ if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "label"); goto cleanup; } if (GetNextOperand(assemEnvPtr, &tokenPtr, &operand1Obj) != TCL_OK) { goto cleanup; } assemEnvPtr->curr_bb->jumpLine = assemEnvPtr->cmdLine; assemEnvPtr->curr_bb->jumpOffset = envPtr->codeNext-envPtr->codeStart; BBEmitInstInt4(assemEnvPtr, tblIdx, 0, 0); assemEnvPtr->curr_bb->flags |= BB_BEGINCATCH; StartBasicBlock(assemEnvPtr, BB_FALLTHRU, operand1Obj); break; case ASSEM_BOOL: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "boolean"); goto cleanup; } if (GetBooleanOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, 0); break; case ASSEM_BOOL_LVT4: if (parsePtr->numWords != 3) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "boolean varName"); goto cleanup; } if (GetBooleanOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) { goto cleanup; } localVar = FindLocalVar(assemEnvPtr, &tokenPtr); if (localVar < 0) { goto cleanup; } BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, 0); TclEmitInt4(localVar, envPtr); break; case ASSEM_CONCAT1: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "imm8"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckOneByte(interp, opnd) != TCL_OK || CheckStrictlyPositive(interp, opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, opnd); break; case ASSEM_DICT_GET: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckStrictlyPositive(interp, opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd+1); break; case ASSEM_DICT_SET: if (parsePtr->numWords != 3) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count varName"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckStrictlyPositive(interp, opnd) != TCL_OK) { goto cleanup; } localVar = FindLocalVar(assemEnvPtr, &tokenPtr); if (localVar < 0) { goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd+1); TclEmitInt4(localVar, envPtr); break; case ASSEM_DICT_UNSET: if (parsePtr->numWords != 3) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count varName"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckStrictlyPositive(interp, opnd) != TCL_OK) { goto cleanup; } localVar = FindLocalVar(assemEnvPtr, &tokenPtr); if (localVar < 0) { goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd); TclEmitInt4(localVar, envPtr); break; case ASSEM_END_CATCH: if (parsePtr->numWords != 1) { Tcl_WrongNumArgs(interp, 1, &instNameObj, ""); goto cleanup; } assemEnvPtr->curr_bb->flags |= BB_ENDCATCH; BBEmitOpcode(assemEnvPtr, tblIdx, 0); StartBasicBlock(assemEnvPtr, BB_FALLTHRU, NULL); break; case ASSEM_EVAL: /* TODO - Refactor this stuff into a subroutine that takes the inst * code, the message ("script" or "expression") and an evaluator * callback that calls TclCompileScript or TclCompileExpr. */ if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, ((TalInstructionTable[tblIdx].tclInstCode == INST_EVAL_STK) ? "script" : "expression")); goto cleanup; } if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { CompileEmbeddedScript(assemEnvPtr, tokenPtr+1, TalInstructionTable+tblIdx); } else if (GetNextOperand(assemEnvPtr, &tokenPtr, &operand1Obj) != TCL_OK) { goto cleanup; } else { operand1 = Tcl_GetStringFromObj(operand1Obj, &operand1Len); litIndex = TclRegisterNewLiteral(envPtr, operand1, operand1Len); /* * Assumes that PUSH is the first slot! */ BBEmitInst1or4(assemEnvPtr, 0, litIndex, 0); BBEmitOpcode(assemEnvPtr, tblIdx, 0); } break; case ASSEM_INVOKE: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckStrictlyPositive(interp, opnd) != TCL_OK) { goto cleanup; } BBEmitInst1or4(assemEnvPtr, tblIdx, opnd, opnd); break; case ASSEM_JUMP: case ASSEM_JUMP4: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "label"); goto cleanup; } if (GetNextOperand(assemEnvPtr, &tokenPtr, &operand1Obj) != TCL_OK) { goto cleanup; } assemEnvPtr->curr_bb->jumpOffset = envPtr->codeNext-envPtr->codeStart; if (instType == ASSEM_JUMP) { flags = BB_JUMP1; BBEmitInstInt1(assemEnvPtr, tblIdx, 0, 0); } else { flags = 0; BBEmitInstInt4(assemEnvPtr, tblIdx, 0, 0); } /* * Start a new basic block at the instruction following the jump. */ assemEnvPtr->curr_bb->jumpLine = assemEnvPtr->cmdLine; if (TalInstructionTable[tblIdx].operandsConsumed != 0) { flags |= BB_FALLTHRU; } StartBasicBlock(assemEnvPtr, flags, operand1Obj); break; case ASSEM_JUMPTABLE: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "table"); goto cleanup; } if (GetNextOperand(assemEnvPtr, &tokenPtr, &operand1Obj) != TCL_OK) { goto cleanup; } jtPtr = ckalloc(sizeof(JumptableInfo)); Tcl_InitHashTable(&jtPtr->hashTable, TCL_STRING_KEYS); assemEnvPtr->curr_bb->jumpLine = assemEnvPtr->cmdLine; assemEnvPtr->curr_bb->jumpOffset = envPtr->codeNext-envPtr->codeStart; DEBUG_PRINT("bb %p jumpLine %d jumpOffset %d\n", assemEnvPtr->curr_bb, assemEnvPtr->cmdLine, envPtr->codeNext - envPtr->codeStart); infoIndex = TclCreateAuxData(jtPtr, &tclJumptableInfoType, envPtr); DEBUG_PRINT("auxdata index=%d\n", infoIndex); BBEmitInstInt4(assemEnvPtr, tblIdx, infoIndex, 0); if (CreateMirrorJumpTable(assemEnvPtr, operand1Obj) != TCL_OK) { goto cleanup; } StartBasicBlock(assemEnvPtr, BB_JUMPTABLE|BB_FALLTHRU, NULL); break; case ASSEM_LABEL: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "name"); goto cleanup; } if (GetNextOperand(assemEnvPtr, &tokenPtr, &operand1Obj) != TCL_OK) { goto cleanup; } /* * Add the (label_name, address) pair to the hash table. */ if (DefineLabel(assemEnvPtr, Tcl_GetString(operand1Obj)) != TCL_OK) { goto cleanup; } break; case ASSEM_LINDEX_MULTI: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckStrictlyPositive(interp, opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd); break; case ASSEM_LIST: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckNonNegative(interp, opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd); break; case ASSEM_INDEX: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count"); goto cleanup; } if (GetListIndexOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd); break; case ASSEM_LSET_FLAT: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) { goto cleanup; } if (opnd < 2) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj("operand must be >=2", -1)); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND>=2", NULL); } goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd); break; case ASSEM_LVT: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "varname"); goto cleanup; } localVar = FindLocalVar(assemEnvPtr, &tokenPtr); if (localVar < 0) { goto cleanup; } BBEmitInst1or4(assemEnvPtr, tblIdx, localVar, 0); break; case ASSEM_LVT1: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "varname"); goto cleanup; } localVar = FindLocalVar(assemEnvPtr, &tokenPtr); if (localVar < 0 || CheckOneByte(interp, localVar)) { goto cleanup; } BBEmitInstInt1(assemEnvPtr, tblIdx, localVar, 0); break; case ASSEM_LVT1_SINT1: if (parsePtr->numWords != 3) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "varName imm8"); goto cleanup; } localVar = FindLocalVar(assemEnvPtr, &tokenPtr); if (localVar < 0 || CheckOneByte(interp, localVar) || GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckSignedOneByte(interp, opnd)) { goto cleanup; } BBEmitInstInt1(assemEnvPtr, tblIdx, localVar, 0); TclEmitInt1(opnd, envPtr); break; case ASSEM_LVT4: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "varname"); goto cleanup; } localVar = FindLocalVar(assemEnvPtr, &tokenPtr); if (localVar < 0) { goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, localVar, 0); break; case ASSEM_OVER: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckNonNegative(interp, opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd+1); break; case ASSEM_REGEXP: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "boolean"); goto cleanup; } if (GetBooleanOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) { goto cleanup; } { int flags = TCL_REG_ADVANCED | (opnd ? TCL_REG_NOCASE : 0); BBEmitInstInt1(assemEnvPtr, tblIdx, flags, 0); } break; case ASSEM_REVERSE: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckNonNegative(interp, opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd); break; case ASSEM_SINT1: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "imm8"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckSignedOneByte(interp, opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, 0); break; case ASSEM_SINT4_LVT4: if (parsePtr->numWords != 3) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count varName"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) { goto cleanup; } localVar = FindLocalVar(assemEnvPtr, &tokenPtr); if (localVar < 0) { goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, 0); TclEmitInt4(localVar, envPtr); break; default: Tcl_Panic("Instruction \"%s\" could not be found, can't happen\n", Tcl_GetString(instNameObj)); } status = TCL_OK; cleanup: Tcl_DecrRefCount(instNameObj); if (operand1Obj) { Tcl_DecrRefCount(operand1Obj); } return status; } /* *----------------------------------------------------------------------------- * * CompileEmbeddedScript -- * * Compile an embedded 'eval' or 'expr' that appears in assembly code. * * This procedure is called when the 'eval' or 'expr' assembly directive is * encountered, and the argument to the directive is a simple word that * requires no substitution. The appropriate compiler (TclCompileScript or * TclCompileExpr) is invoked recursively, and emits bytecode. * * Before the compiler is invoked, the compilation environment's stack * consumption is reset to zero. Upon return from the compilation, the net * stack effect of the compilation is in the compiler env, and this stack * effect is posted to the assembler environment. The compile environment's * stack consumption is then restored to what it was before (which is actually * the state of the stack on entry to the block of assembly code). * * Any exception ranges pushed by the compilation are copied to the basic * block and removed from the compiler environment. They will be rebuilt at * the end of assembly, when the exception stack depth is actually known. * *----------------------------------------------------------------------------- */ static void CompileEmbeddedScript( AssemblyEnv* assemEnvPtr, /* Assembly environment */ Tcl_Token* tokenPtr, /* Tcl_Token containing the script */ const TalInstDesc* instPtr) /* Instruction that determines whether * the script is 'expr' or 'eval' */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ /* * The expression or script is not only known at compile time, but * actually a "simple word". It can be compiled inline by invoking the * compiler recursively. * * Save away the stack depth and reset it before compiling the script. * We'll record the stack usage of the script in the BasicBlock, and * accumulate it together with the stack usage of the enclosing assembly * code. */ int savedStackDepth = envPtr->currStackDepth; int savedMaxStackDepth = envPtr->maxStackDepth; int savedCodeIndex = envPtr->codeNext - envPtr->codeStart; int savedExceptArrayNext = envPtr->exceptArrayNext; envPtr->currStackDepth = 0; envPtr->maxStackDepth = 0; StartBasicBlock(assemEnvPtr, BB_FALLTHRU, NULL); switch(instPtr->tclInstCode) { case INST_EVAL_STK: TclCompileScript(interp, tokenPtr->start, tokenPtr->size, envPtr); break; case INST_EXPR_STK: TclCompileExpr(interp, tokenPtr->start, tokenPtr->size, envPtr, 1); break; default: Tcl_Panic("no ASSEM_EVAL case for %s (%d), can't happen", instPtr->name, instPtr->tclInstCode); } /* * Roll up the stack usage of the embedded block into the assembler * environment. */ SyncStackDepth(assemEnvPtr); envPtr->currStackDepth = savedStackDepth; envPtr->maxStackDepth = savedMaxStackDepth; /* * Save any exception ranges that were pushed by the compiler; they will * need to be fixed up once the stack depth is known. */ MoveExceptionRangesToBasicBlock(assemEnvPtr, savedCodeIndex, savedExceptArrayNext); /* * Flush the current basic block. */ StartBasicBlock(assemEnvPtr, BB_FALLTHRU, NULL); } /* *----------------------------------------------------------------------------- * * SyncStackDepth -- * * Copies the stack depth from the compile environment to a basic block. * * Side effects: * Current and max stack depth in the current basic block are adjusted. * * This procedure is called on return from invoking the compiler for the * 'eval' and 'expr' operations. It adjusts the stack depth of the current * basic block to reflect the stack required by the just-compiled code. * *----------------------------------------------------------------------------- */ static void SyncStackDepth( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ BasicBlock* curr_bb = assemEnvPtr->curr_bb; /* Current basic block */ int maxStackDepth = curr_bb->finalStackDepth + envPtr->maxStackDepth; /* Max stack depth in the basic block */ if (maxStackDepth > curr_bb->maxStackDepth) { curr_bb->maxStackDepth = maxStackDepth; } curr_bb->finalStackDepth += envPtr->currStackDepth; } /* *----------------------------------------------------------------------------- * * MoveExceptionRangesToBasicBlock -- * * Removes exception ranges that were created by compiling an embedded * script from the CompileEnv, and stores them in the BasicBlock. They * will be reinstalled, at the correct stack depth, after control flow * analysis is complete on the assembly code. * *----------------------------------------------------------------------------- */ static void MoveExceptionRangesToBasicBlock( AssemblyEnv* assemEnvPtr, /* Assembly environment */ int savedCodeIndex, /* Start of the embedded code */ int savedExceptArrayNext) /* Saved index of the end of the exception * range array */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ BasicBlock* curr_bb = assemEnvPtr->curr_bb; /* Current basic block */ int exceptionCount = envPtr->exceptArrayNext - savedExceptArrayNext; /* Number of ranges that must be moved */ int i; if (exceptionCount == 0) { /* Nothing to do */ return; } /* * Save the exception ranges in the basic block. They will be re-added at * the conclusion of assembly; at this time, the INST_BEGIN_CATCH * instructions in the block will be adjusted from whatever range indices * they have [savedExceptArrayNext .. envPtr->exceptArrayNext) to the * indices that the exceptions acquire. The saved exception ranges are * converted to a relative nesting depth. The depth will be recomputed * once flow analysis has determined the actual stack depth of the block. */ DEBUG_PRINT("basic block %p has %d exceptions starting at %d\n", curr_bb, exceptionCount, savedExceptArrayNext); curr_bb->foreignExceptionBase = savedExceptArrayNext; curr_bb->foreignExceptionCount = exceptionCount; curr_bb->foreignExceptions = ckalloc(exceptionCount * sizeof(ExceptionRange)); memcpy(curr_bb->foreignExceptions, envPtr->exceptArrayPtr + savedExceptArrayNext, exceptionCount * sizeof(ExceptionRange)); for (i = 0; i < exceptionCount; ++i) { curr_bb->foreignExceptions[i].nestingLevel -= envPtr->exceptDepth; } envPtr->exceptArrayNext = savedExceptArrayNext; } /* *----------------------------------------------------------------------------- * * CreateMirrorJumpTable -- * * Makes a jump table with comparison values and assembly code labels. * * Results: * Returns a standard Tcl status, with an error message in the * interpreter on error. * * Side effects: * Initializes the jump table pointer in the current basic block to a * JumptableInfo. The keys in the JumptableInfo are the comparison * strings. The values, instead of being jump displacements, are * Tcl_Obj's with the code labels. */ static int CreateMirrorJumpTable( AssemblyEnv* assemEnvPtr, /* Assembly environment */ Tcl_Obj* jumps) /* List of alternating keywords and labels */ { int objc; /* Number of elements in the 'jumps' list */ Tcl_Obj** objv; /* Pointers to the elements in the list */ CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ BasicBlock* bbPtr = assemEnvPtr->curr_bb; /* Current basic block */ JumptableInfo* jtPtr; Tcl_HashTable* jtHashPtr; /* Hashtable in the JumptableInfo */ Tcl_HashEntry* hashEntry; /* Entry for a key in the hashtable */ int isNew; /* Flag==1 if the key is not yet in the * table. */ int i; if (Tcl_ListObjGetElements(interp, jumps, &objc, &objv) != TCL_OK) { return TCL_ERROR; } if (objc % 2 != 0) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "jump table must have an even number of list elements", -1)); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADJUMPTABLE", NULL); } return TCL_ERROR; } /* * Allocate the jumptable. */ jtPtr = ckalloc(sizeof(JumptableInfo)); jtHashPtr = &jtPtr->hashTable; Tcl_InitHashTable(jtHashPtr, TCL_STRING_KEYS); /* * Fill the keys and labels into the table. */ DEBUG_PRINT("jump table {\n"); for (i = 0; i < objc; i+=2) { DEBUG_PRINT(" %s -> %s\n", Tcl_GetString(objv[i]), Tcl_GetString(objv[i+1])); hashEntry = Tcl_CreateHashEntry(jtHashPtr, Tcl_GetString(objv[i]), &isNew); if (!isNew) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "duplicate entry in jump table for \"%s\"", Tcl_GetString(objv[i]))); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "DUPJUMPTABLEENTRY"); DeleteMirrorJumpTable(jtPtr); return TCL_ERROR; } } Tcl_SetHashValue(hashEntry, objv[i+1]); Tcl_IncrRefCount(objv[i+1]); } DEBUG_PRINT("}\n"); /* * Put the mirror jumptable in the basic block struct. */ bbPtr->jtPtr = jtPtr; return TCL_OK; } /* *----------------------------------------------------------------------------- * * DeleteMirrorJumpTable -- * * Cleans up a jump table when the basic block is deleted. * *----------------------------------------------------------------------------- */ static void DeleteMirrorJumpTable( JumptableInfo* jtPtr) { Tcl_HashTable* jtHashPtr = &jtPtr->hashTable; /* Hash table pointer */ Tcl_HashSearch search; /* Hash search control */ Tcl_HashEntry* entry; /* Hash table entry containing a jump label */ Tcl_Obj* label; /* Jump label from the hash table */ for (entry = Tcl_FirstHashEntry(jtHashPtr, &search); entry != NULL; entry = Tcl_NextHashEntry(&search)) { label = Tcl_GetHashValue(entry); Tcl_DecrRefCount(label); Tcl_SetHashValue(entry, NULL); } Tcl_DeleteHashTable(jtHashPtr); ckfree(jtPtr); } /* *----------------------------------------------------------------------------- * * GetNextOperand -- * * Retrieves the next operand in sequence from an assembly instruction, * and makes sure that its value is known at compile time. * * Results: * If successful, returns TCL_OK and leaves a Tcl_Obj with the operand * text in *operandObjPtr. In case of failure, returns TCL_ERROR and * leaves *operandObjPtr untouched. * * Side effects: * Advances *tokenPtrPtr around the token just processed. * *----------------------------------------------------------------------------- */ static int GetNextOperand( AssemblyEnv* assemEnvPtr, /* Assembly environment */ Tcl_Token** tokenPtrPtr, /* INPUT/OUTPUT: Pointer to the token holding * the operand */ Tcl_Obj** operandObjPtr) /* OUTPUT: Tcl object holding the operand text * with \-substitutions done. */ { Tcl_Interp* interp = (Tcl_Interp*) assemEnvPtr->envPtr->iPtr; Tcl_Obj* operandObj = Tcl_NewObj(); if (!TclWordKnownAtCompileTime(*tokenPtrPtr, operandObj)) { Tcl_DecrRefCount(operandObj); if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "assembly code may not contain substitutions", -1)); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NOSUBST", NULL); } return TCL_ERROR; } *tokenPtrPtr = TokenAfter(*tokenPtrPtr); Tcl_IncrRefCount(operandObj); *operandObjPtr = operandObj; return TCL_OK; } /* *----------------------------------------------------------------------------- * * GetBooleanOperand -- * * Retrieves a Boolean operand from the input stream and advances * the token pointer. * * Results: * Returns a standard Tcl result (with an error message in the * interpreter on failure). * * Side effects: * Stores the Boolean value in (*result) and advances (*tokenPtrPtr) * to the next token. * *----------------------------------------------------------------------------- */ static int GetBooleanOperand( AssemblyEnv* assemEnvPtr, /* Assembly environment */ Tcl_Token** tokenPtrPtr, /* Current token from the parser */ int* result) /* OUTPUT: Integer extracted from the token */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ Tcl_Token* tokenPtr = *tokenPtrPtr; /* INOUT: Pointer to the next token in the * source code */ Tcl_Obj* intObj; /* Integer from the source code */ int status; /* Tcl status return */ /* * Extract the next token as a string. */ if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &intObj) != TCL_OK) { return TCL_ERROR; } /* * Convert to an integer, advance to the next token and return. */ status = Tcl_GetBooleanFromObj(interp, intObj, result); Tcl_DecrRefCount(intObj); *tokenPtrPtr = TokenAfter(tokenPtr); return status; } /* *----------------------------------------------------------------------------- * * GetIntegerOperand -- * * Retrieves an integer operand from the input stream and advances the * token pointer. * * Results: * Returns a standard Tcl result (with an error message in the * interpreter on failure). * * Side effects: * Stores the integer value in (*result) and advances (*tokenPtrPtr) to * the next token. * *----------------------------------------------------------------------------- */ static int GetIntegerOperand( AssemblyEnv* assemEnvPtr, /* Assembly environment */ Tcl_Token** tokenPtrPtr, /* Current token from the parser */ int* result) /* OUTPUT: Integer extracted from the token */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ Tcl_Token* tokenPtr = *tokenPtrPtr; /* INOUT: Pointer to the next token in the * source code */ Tcl_Obj* intObj; /* Integer from the source code */ int status; /* Tcl status return */ /* * Extract the next token as a string. */ if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &intObj) != TCL_OK) { return TCL_ERROR; } /* * Convert to an integer, advance to the next token and return. */ status = Tcl_GetIntFromObj(interp, intObj, result); Tcl_DecrRefCount(intObj); *tokenPtrPtr = TokenAfter(tokenPtr); return status; } /* *----------------------------------------------------------------------------- * * GetListIndexOperand -- * * Gets the value of an operand intended to serve as a list index. * * Results: * Returns a standard Tcl result: TCL_OK if the parse is successful and * TCL_ERROR (with an appropriate error message) if the parse fails. * * Side effects: * Stores the list index at '*index'. Values between -1 and 0x7fffffff * have their natural meaning; values between -2 and -0x80000000 * represent 'end-2-N'. * *----------------------------------------------------------------------------- */ static int GetListIndexOperand( AssemblyEnv* assemEnvPtr, /* Assembly environment */ Tcl_Token** tokenPtrPtr, /* Current token from the parser */ int* result) /* OUTPUT: Integer extracted from the token */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ Tcl_Token* tokenPtr = *tokenPtrPtr; /* INOUT: Pointer to the next token in the * source code */ Tcl_Obj* intObj; /* Integer from the source code */ int status; /* Tcl status return */ /* * Extract the next token as a string. */ if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &intObj) != TCL_OK) { return TCL_ERROR; } /* * Convert to an integer, advance to the next token and return. */ status = TclGetIntForIndex(interp, intObj, -2, result); Tcl_DecrRefCount(intObj); *tokenPtrPtr = TokenAfter(tokenPtr); return status; } /* *----------------------------------------------------------------------------- * * FindLocalVar -- * * Gets the name of a local variable from the input stream and advances * the token pointer. * * Results: * Returns the LVT index of the local variable. Returns -1 if the * variable is non-local, not known at compile time, or cannot be * installed in the LVT (leaving an error message in the interpreter * result if necessary). * * Side effects: * Advances the token pointer. May define a new LVT slot if the variable * has not yet been seen and the execution context allows for it. * *----------------------------------------------------------------------------- */ static int FindLocalVar( AssemblyEnv* assemEnvPtr, /* Assembly environment */ Tcl_Token** tokenPtrPtr) { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ Tcl_Token* tokenPtr = *tokenPtrPtr; /* INOUT: Pointer to the next token in the * source code. */ Tcl_Obj* varNameObj; /* Name of the variable */ const char* varNameStr; int varNameLen; int localVar; /* Index of the variable in the LVT */ if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &varNameObj) != TCL_OK) { return -1; } varNameStr = Tcl_GetStringFromObj(varNameObj, &varNameLen); if (CheckNamespaceQualifiers(interp, varNameStr, varNameLen)) { Tcl_DecrRefCount(varNameObj); return -1; } localVar = TclFindCompiledLocal(varNameStr, varNameLen, 1, envPtr); Tcl_DecrRefCount(varNameObj); if (localVar == -1) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot use this instruction to create a variable" " in a non-proc context", -1)); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "LVT", NULL); } return -1; } *tokenPtrPtr = TokenAfter(tokenPtr); return localVar; } /* *----------------------------------------------------------------------------- * * CheckNamespaceQualifiers -- * * Verify that a variable name has no namespace qualifiers before * attempting to install it in the LVT. * * Results: * On success, returns TCL_OK. On failure, returns TCL_ERROR and stores * an error message in the interpreter result. * *----------------------------------------------------------------------------- */ static int CheckNamespaceQualifiers( Tcl_Interp* interp, /* Tcl interpreter for error reporting */ const char* name, /* Variable name to check */ int nameLen) /* Length of the variable */ { const char* p; for (p = name; p+2 < name+nameLen; p++) { if ((*p == ':') && (p[1] == ':')) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "variable \"%s\" is not local", name)); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NONLOCAL", name, NULL); return TCL_ERROR; } } return TCL_OK; } /* *----------------------------------------------------------------------------- * * CheckOneByte -- * * Verify that a constant fits in a single byte in the instruction * stream. * * Results: * On success, returns TCL_OK. On failure, returns TCL_ERROR and stores * an error message in the interpreter result. * * This code is here primarily to verify that instructions like INCR_SCALAR1 * are possible on a given local variable. The fact that there is no * INCR_SCALAR4 is puzzling. * *----------------------------------------------------------------------------- */ static int CheckOneByte( Tcl_Interp* interp, /* Tcl interpreter for error reporting */ int value) /* Value to check */ { Tcl_Obj* result; /* Error message */ if (value < 0 || value > 0xff) { result = Tcl_NewStringObj("operand does not fit in one byte", -1); Tcl_SetObjResult(interp, result); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "1BYTE", NULL); return TCL_ERROR; } return TCL_OK; } /* *----------------------------------------------------------------------------- * * CheckSignedOneByte -- * * Verify that a constant fits in a single signed byte in the instruction * stream. * * Results: * On success, returns TCL_OK. On failure, returns TCL_ERROR and stores * an error message in the interpreter result. * * This code is here primarily to verify that instructions like INCR_SCALAR1 * are possible on a given local variable. The fact that there is no * INCR_SCALAR4 is puzzling. * *----------------------------------------------------------------------------- */ static int CheckSignedOneByte( Tcl_Interp* interp, /* Tcl interpreter for error reporting */ int value) /* Value to check */ { Tcl_Obj* result; /* Error message */ if (value > 0x7f || value < -0x80) { result = Tcl_NewStringObj("operand does not fit in one byte", -1); Tcl_SetObjResult(interp, result); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "1BYTE", NULL); return TCL_ERROR; } return TCL_OK; } /* *----------------------------------------------------------------------------- * * CheckNonNegative -- * * Verify that a constant is nonnegative * * Results: * On success, returns TCL_OK. On failure, returns TCL_ERROR and stores * an error message in the interpreter result. * * This code is here primarily to verify that instructions like INCR_INVOKE * are consuming a positive number of operands * *----------------------------------------------------------------------------- */ static int CheckNonNegative( Tcl_Interp* interp, /* Tcl interpreter for error reporting */ int value) /* Value to check */ { Tcl_Obj* result; /* Error message */ if (value < 0) { result = Tcl_NewStringObj("operand must be nonnegative", -1); Tcl_SetObjResult(interp, result); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NONNEGATIVE", NULL); return TCL_ERROR; } return TCL_OK; } /* *----------------------------------------------------------------------------- * * CheckStrictlyPositive -- * * Verify that a constant is positive * * Results: * On success, returns TCL_OK. On failure, returns TCL_ERROR and * stores an error message in the interpreter result. * * This code is here primarily to verify that instructions like INCR_INVOKE * are consuming a positive number of operands * *----------------------------------------------------------------------------- */ static int CheckStrictlyPositive( Tcl_Interp* interp, /* Tcl interpreter for error reporting */ int value) /* Value to check */ { Tcl_Obj* result; /* Error message */ if (value <= 0) { result = Tcl_NewStringObj("operand must be positive", -1); Tcl_SetObjResult(interp, result); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "POSITIVE", NULL); return TCL_ERROR; } return TCL_OK; } /* *----------------------------------------------------------------------------- * * DefineLabel -- * * Defines a label appearing in the assembly sequence. * * Results: * Returns a standard Tcl result. Returns TCL_OK and an empty result if * the definition succeeds; returns TCL_ERROR and an appropriate message * if a duplicate definition is found. * *----------------------------------------------------------------------------- */ static int DefineLabel( AssemblyEnv* assemEnvPtr, /* Assembly environment */ const char* labelName) /* Label being defined */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ Tcl_HashEntry* entry; /* Label's entry in the symbol table */ int isNew; /* Flag == 1 iff the label was previously * undefined */ /* TODO - This can now be simplified! */ StartBasicBlock(assemEnvPtr, BB_FALLTHRU, NULL); /* * Look up the newly-defined label in the symbol table. */ entry = Tcl_CreateHashEntry(&assemEnvPtr->labelHash, labelName, &isNew); if (!isNew) { /* * This is a duplicate label. */ if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "duplicate definition of label \"%s\"", labelName)); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "DUPLABEL", labelName, NULL); } return TCL_ERROR; } /* * This is the first appearance of the label in the code. */ Tcl_SetHashValue(entry, assemEnvPtr->curr_bb); return TCL_OK; } /* *----------------------------------------------------------------------------- * * StartBasicBlock -- * * Starts a new basic block when a label or jump is encountered. * * Results: * Returns a pointer to the BasicBlock structure of the new * basic block. * *----------------------------------------------------------------------------- */ static BasicBlock* StartBasicBlock( AssemblyEnv* assemEnvPtr, /* Assembly environment */ int flags, /* Flags to apply to the basic block being * closed, if there is one. */ Tcl_Obj* jumpLabel) /* Label of the location that the block jumps * to, or NULL if the block does not jump */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ BasicBlock* newBB; /* BasicBlock structure for the new block */ BasicBlock* currBB = assemEnvPtr->curr_bb; /* * Coalesce zero-length blocks. */ if (currBB->startOffset == envPtr->codeNext - envPtr->codeStart) { currBB->startLine = assemEnvPtr->cmdLine; return currBB; } /* * Make the new basic block. */ newBB = AllocBB(assemEnvPtr); /* * Record the jump target if there is one. */ currBB->jumpTarget = jumpLabel; if (jumpLabel != NULL) { Tcl_IncrRefCount(currBB->jumpTarget); } /* * Record the fallthrough if there is one. */ currBB->flags |= flags; /* * Record the successor block. */ currBB->successor1 = newBB; assemEnvPtr->curr_bb = newBB; return newBB; } /* *----------------------------------------------------------------------------- * * AllocBB -- * * Allocates a new basic block * * Results: * Returns a pointer to the newly allocated block, which is initialized * to contain no code and begin at the current instruction pointer. * *----------------------------------------------------------------------------- */ static BasicBlock * AllocBB( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { CompileEnv* envPtr = assemEnvPtr->envPtr; BasicBlock *bb = ckalloc(sizeof(BasicBlock)); bb->originalStartOffset = bb->startOffset = envPtr->codeNext - envPtr->codeStart; bb->startLine = assemEnvPtr->cmdLine + 1; bb->jumpOffset = -1; bb->jumpLine = -1; bb->prevPtr = assemEnvPtr->curr_bb; bb->predecessor = NULL; bb->successor1 = NULL; bb->jumpTarget = NULL; bb->initialStackDepth = 0; bb->minStackDepth = 0; bb->maxStackDepth = 0; bb->finalStackDepth = 0; bb->catchDepth = 0; bb->enclosingCatch = NULL; bb->foreignExceptionBase = -1; bb->foreignExceptionCount = 0; bb->foreignExceptions = NULL; bb->jtPtr = NULL; bb->flags = 0; return bb; } /* *----------------------------------------------------------------------------- * * FinishAssembly -- * * Postprocessing after all bytecode has been generated for a block of * assembly code. * * Results: * Returns a standard Tcl result, with an error message left in the * interpreter if appropriate. * * Side effects: * The program is checked to see if any undefined labels remain. The * initial stack depth of all the basic blocks in the flow graph is * calculated and saved. The stack balance on exit is computed, checked * and saved. * *----------------------------------------------------------------------------- */ static int FinishAssembly( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { int mustMove; /* Amount by which the code needs to be grown * because of expanding jumps */ /* * Resolve the targets of all jumps and determine whether code needs to be * moved around. */ if (CalculateJumpRelocations(assemEnvPtr, &mustMove)) { return TCL_ERROR; } /* * Move the code if necessary. */ if (mustMove) { MoveCodeForJumps(assemEnvPtr, mustMove); } /* * Resolve jump target labels to bytecode offsets. */ FillInJumpOffsets(assemEnvPtr); /* * Label each basic block with its catch context. Quit on inconsistency. */ if (ProcessCatches(assemEnvPtr) != TCL_OK) { return TCL_ERROR; } /* * Make sure that no block accessible from a catch's error exit that hasn't * popped the exception stack can throw an exception. */ if (CheckForThrowInWrongContext(assemEnvPtr) != TCL_OK) { return TCL_ERROR; } /* * Compute stack balance throughout the program. */ if (CheckStack(assemEnvPtr) != TCL_OK) { return TCL_ERROR; } /* * TODO - Check for unreachable code. Or maybe not; unreachable code is * Mostly Harmless. */ return TCL_OK; } /* *----------------------------------------------------------------------------- * * CalculateJumpRelocations -- * * Calculate any movement that has to be done in the assembly code to * expand JUMP1 instructions to JUMP4 (because they jump more than a * 1-byte range). * * Results: * Returns a standard Tcl result, with an appropriate error message if * anything fails. * * Side effects: * Sets the 'startOffset' pointer in every basic block to the new origin * of the block, and turns off JUMP1 flags on instructions that must be * expanded (and adjusts them to the corresponding JUMP4's). Does *not* * store the jump offsets at this point. * * Sets *mustMove to 1 if and only if at least one instruction changed * size so the code must be moved. * * As a side effect, also checks for undefined labels and reports them. * *----------------------------------------------------------------------------- */ static int CalculateJumpRelocations( AssemblyEnv* assemEnvPtr, /* Assembly environment */ int* mustMove) /* OUTPUT: Number of bytes that have been * added to the code */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ BasicBlock* bbPtr; /* Pointer to a basic block being checked */ Tcl_HashEntry* entry; /* Exit label's entry in the symbol table */ BasicBlock* jumpTarget; /* Basic block where the jump goes */ int motion; /* Amount by which the code has expanded */ int offset; /* Offset in the bytecode from a jump * instruction to its target */ unsigned opcode; /* Opcode in the bytecode being adjusted */ /* * Iterate through basic blocks as long as a change results in code * expansion. */ *mustMove = 0; do { motion = 0; for (bbPtr = assemEnvPtr->head_bb; bbPtr != NULL; bbPtr = bbPtr->successor1) { /* * Advance the basic block start offset by however many bytes we * have inserted in the code up to this point */ bbPtr->startOffset += motion; /* * If the basic block references a label (and hence performs a * jump), find the location of the label. Report an error if the * label is missing. */ if (bbPtr->jumpTarget != NULL) { entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash, Tcl_GetString(bbPtr->jumpTarget)); if (entry == NULL) { ReportUndefinedLabel(assemEnvPtr, bbPtr, bbPtr->jumpTarget); return TCL_ERROR; } /* * If the instruction is a JUMP1, turn it into a JUMP4 if its * target is out of range. */ jumpTarget = Tcl_GetHashValue(entry); if (bbPtr->flags & BB_JUMP1) { offset = jumpTarget->startOffset - (bbPtr->jumpOffset + motion); if (offset < -0x80 || offset > 0x7f) { opcode = TclGetUInt1AtPtr(envPtr->codeStart + bbPtr->jumpOffset); ++opcode; TclStoreInt1AtPtr(opcode, envPtr->codeStart + bbPtr->jumpOffset); motion += 3; bbPtr->flags &= ~BB_JUMP1; } } } /* * If the basic block references a jump table, that doesn't affect * the code locations, but resolve the labels now, and store basic * block pointers in the jumptable hash. */ if (bbPtr->flags & BB_JUMPTABLE) { if (CheckJumpTableLabels(assemEnvPtr, bbPtr) != TCL_OK) { return TCL_ERROR; } } } *mustMove += motion; } while (motion != 0); return TCL_OK; } /* *----------------------------------------------------------------------------- * * CheckJumpTableLabels -- * * Make sure that all the labels in a jump table are defined. * * Results: * Returns TCL_OK if they are, TCL_ERROR if they aren't. * *----------------------------------------------------------------------------- */ static int CheckJumpTableLabels( AssemblyEnv* assemEnvPtr, /* Assembly environment */ BasicBlock* bbPtr) /* Basic block that ends in a jump table */ { Tcl_HashTable* symHash = &bbPtr->jtPtr->hashTable; /* Hash table with the symbols */ Tcl_HashSearch search; /* Hash table iterator */ Tcl_HashEntry* symEntryPtr; /* Hash entry for the symbols */ Tcl_Obj* symbolObj; /* Jump target */ Tcl_HashEntry* valEntryPtr; /* Hash entry for the resolutions */ /* * Look up every jump target in the jump hash. */ DEBUG_PRINT("check jump table labels %p {\n", bbPtr); for (symEntryPtr = Tcl_FirstHashEntry(symHash, &search); symEntryPtr != NULL; symEntryPtr = Tcl_NextHashEntry(&search)) { symbolObj = Tcl_GetHashValue(symEntryPtr); valEntryPtr = Tcl_FindHashEntry(&assemEnvPtr->labelHash, Tcl_GetString(symbolObj)); DEBUG_PRINT(" %s -> %s (%d)\n", (char*) Tcl_GetHashKey(symHash, symEntryPtr), Tcl_GetString(symbolObj), (valEntryPtr != NULL)); if (valEntryPtr == NULL) { ReportUndefinedLabel(assemEnvPtr, bbPtr, symbolObj); return TCL_ERROR; } } DEBUG_PRINT("}\n"); return TCL_OK; } /* *----------------------------------------------------------------------------- * * ReportUndefinedLabel -- * * Report that a basic block refers to an undefined jump label * * Side effects: * Stores an error message, error code, and line number information in * the assembler's Tcl interpreter. * *----------------------------------------------------------------------------- */ static void ReportUndefinedLabel( AssemblyEnv* assemEnvPtr, /* Assembly environment */ BasicBlock* bbPtr, /* Basic block that contains the undefined * label */ Tcl_Obj* jumpTarget) /* Label of a jump target */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "undefined label \"%s\"", Tcl_GetString(jumpTarget))); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NOLABEL", Tcl_GetString(jumpTarget), NULL); Tcl_SetErrorLine(interp, bbPtr->jumpLine); } } /* *----------------------------------------------------------------------------- * * MoveCodeForJumps -- * * Move bytecodes in memory to accommodate JUMP1 instructions that have * expanded to become JUMP4's. * *----------------------------------------------------------------------------- */ static void MoveCodeForJumps( AssemblyEnv* assemEnvPtr, /* Assembler environment */ int mustMove) /* Number of bytes of added code */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ BasicBlock* bbPtr; /* Pointer to a basic block being checked */ int topOffset; /* Bytecode offset of the following basic * block before code motion */ /* * Make sure that there is enough space in the bytecode array to * accommodate the expanded code. */ while (envPtr->codeEnd < envPtr->codeNext + mustMove) { TclExpandCodeArray(envPtr); } /* * Iterate through the bytecodes in reverse order, and move them upward to * their new homes. */ topOffset = envPtr->codeNext - envPtr->codeStart; for (bbPtr = assemEnvPtr->curr_bb; bbPtr != NULL; bbPtr = bbPtr->prevPtr) { DEBUG_PRINT("move code from %d to %d\n", bbPtr->originalStartOffset, bbPtr->startOffset); memmove(envPtr->codeStart + bbPtr->startOffset, envPtr->codeStart + bbPtr->originalStartOffset, topOffset - bbPtr->originalStartOffset); topOffset = bbPtr->originalStartOffset; bbPtr->jumpOffset += (bbPtr->startOffset - bbPtr->originalStartOffset); } envPtr->codeNext += mustMove; } /* *----------------------------------------------------------------------------- * * FillInJumpOffsets -- * * Fill in the final offsets of all jump instructions once bytecode * locations have been completely determined. * *----------------------------------------------------------------------------- */ static void FillInJumpOffsets( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ BasicBlock* bbPtr; /* Pointer to a basic block being checked */ Tcl_HashEntry* entry; /* Hashtable entry for a jump target label */ BasicBlock* jumpTarget; /* Basic block where a jump goes */ int fromOffset; /* Bytecode location of a jump instruction */ int targetOffset; /* Bytecode location of a jump instruction's * target */ for (bbPtr = assemEnvPtr->head_bb; bbPtr != NULL; bbPtr = bbPtr->successor1) { if (bbPtr->jumpTarget != NULL) { entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash, Tcl_GetString(bbPtr->jumpTarget)); jumpTarget = Tcl_GetHashValue(entry); fromOffset = bbPtr->jumpOffset; targetOffset = jumpTarget->startOffset; if (bbPtr->flags & BB_JUMP1) { TclStoreInt1AtPtr(targetOffset - fromOffset, envPtr->codeStart + fromOffset + 1); } else { TclStoreInt4AtPtr(targetOffset - fromOffset, envPtr->codeStart + fromOffset + 1); } } if (bbPtr->flags & BB_JUMPTABLE) { ResolveJumpTableTargets(assemEnvPtr, bbPtr); } } } /* *----------------------------------------------------------------------------- * * ResolveJumpTableTargets -- * * Puts bytecode addresses for the targets of a jumptable into the * table * * Results: * Returns TCL_OK if they are, TCL_ERROR if they aren't. * *----------------------------------------------------------------------------- */ static void ResolveJumpTableTargets( AssemblyEnv* assemEnvPtr, /* Assembly environment */ BasicBlock* bbPtr) /* Basic block that ends in a jump table */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_HashTable* symHash = &bbPtr->jtPtr->hashTable; /* Hash table with the symbols */ Tcl_HashSearch search; /* Hash table iterator */ Tcl_HashEntry* symEntryPtr; /* Hash entry for the symbols */ Tcl_Obj* symbolObj; /* Jump target */ Tcl_HashEntry* valEntryPtr; /* Hash entry for the resolutions */ int auxDataIndex; /* Index of the auxdata */ JumptableInfo* realJumpTablePtr; /* Jump table in the actual code */ Tcl_HashTable* realJumpHashPtr; /* Jump table hash in the actual code */ Tcl_HashEntry* realJumpEntryPtr; /* Entry in the jump table hash in * the actual code */ BasicBlock* jumpTargetBBPtr; /* Basic block that the jump proceeds to */ int junk; auxDataIndex = TclGetInt4AtPtr(envPtr->codeStart + bbPtr->jumpOffset + 1); DEBUG_PRINT("bbPtr = %p jumpOffset = %d auxDataIndex = %d\n", bbPtr, bbPtr->jumpOffset, auxDataIndex); realJumpTablePtr = TclFetchAuxData(envPtr, auxDataIndex); realJumpHashPtr = &realJumpTablePtr->hashTable; /* * Look up every jump target in the jump hash. */ DEBUG_PRINT("resolve jump table {\n"); for (symEntryPtr = Tcl_FirstHashEntry(symHash, &search); symEntryPtr != NULL; symEntryPtr = Tcl_NextHashEntry(&search)) { symbolObj = Tcl_GetHashValue(symEntryPtr); DEBUG_PRINT(" symbol %s\n", Tcl_GetString(symbolObj)); valEntryPtr = Tcl_FindHashEntry(&assemEnvPtr->labelHash, Tcl_GetString(symbolObj)); jumpTargetBBPtr = Tcl_GetHashValue(valEntryPtr); realJumpEntryPtr = Tcl_CreateHashEntry(realJumpHashPtr, Tcl_GetHashKey(symHash, symEntryPtr), &junk); DEBUG_PRINT(" %s -> %s -> bb %p (pc %d) hash entry %p\n", (char*) Tcl_GetHashKey(symHash, symEntryPtr), Tcl_GetString(symbolObj), jumpTargetBBPtr, jumpTargetBBPtr->startOffset, realJumpEntryPtr); Tcl_SetHashValue(realJumpEntryPtr, INT2PTR(jumpTargetBBPtr->startOffset - bbPtr->jumpOffset)); } DEBUG_PRINT("}\n"); } /* *----------------------------------------------------------------------------- * * CheckForThrowInWrongContext -- * * Verify that no beginCatch/endCatch sequence can throw an exception * after an original exception is caught and before its exception context * is removed from the stack. * * Results: * Returns a standard Tcl result. * * Side effects: * Stores an appropriate error message in the interpreter as needed. * *----------------------------------------------------------------------------- */ static int CheckForThrowInWrongContext( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { BasicBlock* blockPtr; /* Current basic block */ /* * Walk through the basic blocks in turn, checking all the ones that have * caught an exception and not disposed of it properly. */ for (blockPtr = assemEnvPtr->head_bb; blockPtr != NULL; blockPtr = blockPtr->successor1) { if (blockPtr->catchState == BBCS_CAUGHT) { /* * Walk through the instructions in the basic block. */ if (CheckNonThrowingBlock(assemEnvPtr, blockPtr) != TCL_OK) { return TCL_ERROR; } } } return TCL_OK; } /* *----------------------------------------------------------------------------- * * CheckNonThrowingBlock -- * * Check that a basic block cannot throw an exception. * * Results: * Returns TCL_ERROR if the block cannot be proven to be nonthrowing. * * Side effects: * Stashes an error message in the interpreter result. * *----------------------------------------------------------------------------- */ static int CheckNonThrowingBlock( AssemblyEnv* assemEnvPtr, /* Assembly environment */ BasicBlock* blockPtr) /* Basic block where exceptions are not * allowed */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ BasicBlock* nextPtr; /* Pointer to the succeeding basic block */ int offset; /* Bytecode offset of the current * instruction */ int bound; /* Bytecode offset following the last * instruction of the block. */ unsigned char opcode; /* Current bytecode instruction */ /* * Determine where in the code array the basic block ends. */ nextPtr = blockPtr->successor1; if (nextPtr == NULL) { bound = envPtr->codeNext - envPtr->codeStart; } else { bound = nextPtr->startOffset; } /* * Walk through the instructions of the block. */ offset = blockPtr->startOffset; while (offset < bound) { /* * Determine whether an instruction is nonthrowing. */ opcode = (envPtr->codeStart)[offset]; if (BytecodeMightThrow(opcode)) { /* * Report an error for a throw in the wrong context. */ if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" instruction may not appear in " "a context where an exception has been " "caught and not disposed of.", tclInstructionTable[opcode].name)); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADTHROW", NULL); AddBasicBlockRangeToErrorInfo(assemEnvPtr, blockPtr); } return TCL_ERROR; } offset += tclInstructionTable[opcode].numBytes; } return TCL_OK; } /* *----------------------------------------------------------------------------- * * BytecodeMightThrow -- * * Tests if a given bytecode instruction might throw an exception. * * Results: * Returns 1 if the bytecode might throw an exception, 0 if the * instruction is known never to throw. * *----------------------------------------------------------------------------- */ static int BytecodeMightThrow( unsigned char opcode) { /* * Binary search on the non-throwing bytecode list. */ int min = 0; int max = sizeof(NonThrowingByteCodes) - 1; int mid; unsigned char c; while (max >= min) { mid = (min + max) / 2; c = NonThrowingByteCodes[mid]; if (opcode < c) { max = mid-1; } else if (opcode > c) { min = mid+1; } else { /* * Opcode is nonthrowing. */ return 0; } } return 1; } /* *----------------------------------------------------------------------------- * * CheckStack -- * * Audit stack usage in a block of assembly code. * * Results: * Returns a standard Tcl result. * * Side effects: * Updates stack depth on entry for all basic blocks in the flowgraph. * Calculates the max stack depth used in the program, and updates the * compilation environment to reflect it. * *----------------------------------------------------------------------------- */ static int CheckStack( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ int maxDepth; /* Maximum stack depth overall */ /* * Checking the head block will check all the other blocks recursively. */ assemEnvPtr->maxDepth = 0; if (StackCheckBasicBlock(assemEnvPtr, assemEnvPtr->head_bb, NULL, 0) == TCL_ERROR) { return TCL_ERROR; } /* * Post the max stack depth back to the compilation environment. */ maxDepth = assemEnvPtr->maxDepth + envPtr->currStackDepth; if (maxDepth > envPtr->maxStackDepth) { envPtr->maxStackDepth = maxDepth; } /* * If the exit is reachable, make sure that the program exits with 1 * operand on the stack. */ if (StackCheckExit(assemEnvPtr) != TCL_OK) { return TCL_ERROR; } /* * Reset the visited state on all basic blocks. */ ResetVisitedBasicBlocks(assemEnvPtr); return TCL_OK; } /* *----------------------------------------------------------------------------- * * StackCheckBasicBlock -- * * Checks stack consumption for a basic block (and recursively for its * successors). * * Results: * Returns a standard Tcl result. * * Side effects: * Updates initial stack depth for the basic block and its successors. * (Final and maximum stack depth are relative to initial, and are not * touched). * * This procedure eventually checks, for the entire flow graph, whether stack * balance is consistent. It is an error for a given basic block to be * reachable along multiple flow paths with different stack depths. * *----------------------------------------------------------------------------- */ static int StackCheckBasicBlock( AssemblyEnv* assemEnvPtr, /* Assembly environment */ BasicBlock* blockPtr, /* Pointer to the basic block being checked */ BasicBlock* predecessor, /* Pointer to the block that passed control to * this one. */ int initialStackDepth) /* Stack depth on entry to the block */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ BasicBlock* jumpTarget; /* Basic block where a jump goes */ int stackDepth; /* Current stack depth */ int maxDepth; /* Maximum stack depth so far */ int result; /* Tcl status return */ Tcl_HashSearch jtSearch; /* Search structure for the jump table */ Tcl_HashEntry* jtEntry; /* Hash entry in the jump table */ Tcl_Obj* targetLabel; /* Target label from the jump table */ Tcl_HashEntry* entry; /* Hash entry in the label table */ if (blockPtr->flags & BB_VISITED) { /* * If the block is already visited, check stack depth for consistency * among the paths that reach it. */ if (blockPtr->initialStackDepth == initialStackDepth) { return TCL_OK; } if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "inconsistent stack depths on two execution paths", -1)); /* * TODO - add execution trace of both paths */ Tcl_SetErrorLine(interp, blockPtr->startLine); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", NULL); } return TCL_ERROR; } /* * If the block is not already visited, set the 'predecessor' link to * indicate how control got to it. Set the initial stack depth to the * current stack depth in the flow of control. */ blockPtr->flags |= BB_VISITED; blockPtr->predecessor = predecessor; blockPtr->initialStackDepth = initialStackDepth; /* * Calculate minimum stack depth, and flag an error if the block * underflows the stack. */ if (initialStackDepth + blockPtr->minStackDepth < 0) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj("stack underflow", -1)); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", NULL); AddBasicBlockRangeToErrorInfo(assemEnvPtr, blockPtr); Tcl_SetErrorLine(interp, blockPtr->startLine); } return TCL_ERROR; } /* * Make sure that the block doesn't try to pop below the stack level of an * enclosing catch. */ if (blockPtr->enclosingCatch != 0 && initialStackDepth + blockPtr->minStackDepth < (blockPtr->enclosingCatch->initialStackDepth + blockPtr->enclosingCatch->finalStackDepth)) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "code pops stack below level of enclosing catch", -1)); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACKINCATCH", -1); AddBasicBlockRangeToErrorInfo(assemEnvPtr, blockPtr); Tcl_SetErrorLine(interp, blockPtr->startLine); } return TCL_ERROR; } /* * Update maximum stgack depth. */ maxDepth = initialStackDepth + blockPtr->maxStackDepth; if (maxDepth > assemEnvPtr->maxDepth) { assemEnvPtr->maxDepth = maxDepth; } /* * Calculate stack depth on exit from the block, and invoke this procedure * recursively to check successor blocks. */ stackDepth = initialStackDepth + blockPtr->finalStackDepth; result = TCL_OK; if (blockPtr->flags & BB_FALLTHRU) { result = StackCheckBasicBlock(assemEnvPtr, blockPtr->successor1, blockPtr, stackDepth); } if (result == TCL_OK && blockPtr->jumpTarget != NULL) { entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash, Tcl_GetString(blockPtr->jumpTarget)); jumpTarget = Tcl_GetHashValue(entry); result = StackCheckBasicBlock(assemEnvPtr, jumpTarget, blockPtr, stackDepth); } /* * All blocks referenced in a jump table are successors. */ if (blockPtr->flags & BB_JUMPTABLE) { for (jtEntry = Tcl_FirstHashEntry(&blockPtr->jtPtr->hashTable, &jtSearch); result == TCL_OK && jtEntry != NULL; jtEntry = Tcl_NextHashEntry(&jtSearch)) { targetLabel = Tcl_GetHashValue(jtEntry); entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash, Tcl_GetString(targetLabel)); jumpTarget = Tcl_GetHashValue(entry); result = StackCheckBasicBlock(assemEnvPtr, jumpTarget, blockPtr, stackDepth); } } return result; } /* *----------------------------------------------------------------------------- * * StackCheckExit -- * * Makes sure that the net stack effect of an entire assembly language * script is to push 1 result. * * Results: * Returns a standard Tcl result, with an error message in the * interpreter result if the stack is wrong. * * Side effects: * If the assembly code had a net stack effect of zero, emits code to the * concluding block to push a null result. In any case, updates the stack * depth in the compile environment to reflect the net effect of the * assembly code. * *----------------------------------------------------------------------------- */ static int StackCheckExit( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ int depth; /* Net stack effect */ int litIndex; /* Index in the literal pool of the empty * string */ BasicBlock* curr_bb = assemEnvPtr->curr_bb; /* Final basic block in the assembly */ /* * Don't perform these checks if execution doesn't reach the exit (either * because of an infinite loop or because the only return is from the * middle. */ if (curr_bb->flags & BB_VISITED) { /* * Exit with no operands; push an empty one. */ depth = curr_bb->finalStackDepth + curr_bb->initialStackDepth; if (depth == 0) { /* * Emit a 'push' of the empty literal. */ litIndex = TclRegisterNewLiteral(envPtr, "", 0); /* * Assumes that 'push' is at slot 0 in TalInstructionTable. */ BBEmitInst1or4(assemEnvPtr, 0, litIndex, 0); ++depth; } /* * Exit with unbalanced stack. */ if (depth != 1) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "stack is unbalanced on exit from the code (depth=%d)", depth)); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADSTACK", NULL); } return TCL_ERROR; } /* * Record stack usage. */ envPtr->currStackDepth += depth; } return TCL_OK; } /* *----------------------------------------------------------------------------- * * ProcessCatches -- * * First pass of 'catch' processing. * * Results: * Returns a standard Tcl result, with an appropriate error message if * the result is TCL_ERROR. * * Side effects: * Labels all basic blocks with their enclosing catches. * *----------------------------------------------------------------------------- */ static int ProcessCatches( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { BasicBlock* blockPtr; /* Pointer to a basic block */ /* * Clear the catch state of all basic blocks. */ for (blockPtr = assemEnvPtr->head_bb; blockPtr != NULL; blockPtr = blockPtr->successor1) { blockPtr->catchState = BBCS_UNKNOWN; blockPtr->enclosingCatch = NULL; } /* * Start the check recursively from the first basic block, which is * outside any exception context */ if (ProcessCatchesInBasicBlock(assemEnvPtr, assemEnvPtr->head_bb, NULL, BBCS_NONE, 0) != TCL_OK) { return TCL_ERROR; } /* * Check for unclosed catch on exit. */ if (CheckForUnclosedCatches(assemEnvPtr) != TCL_OK) { return TCL_ERROR; } /* * Now there's enough information to build the exception ranges. */ if (BuildExceptionRanges(assemEnvPtr) != TCL_OK) { return TCL_ERROR; } /* * Finally, restore any exception ranges from embedded scripts. */ RestoreEmbeddedExceptionRanges(assemEnvPtr); return TCL_OK; } /* *----------------------------------------------------------------------------- * * ProcessCatchesInBasicBlock -- * * First-pass catch processing for one basic block. * * Results: * Returns a standard Tcl result, with error message in the interpreter * result if an error occurs. * * This procedure checks consistency of the exception context through the * assembler program, and records the enclosing 'catch' for every basic block. * *----------------------------------------------------------------------------- */ static int ProcessCatchesInBasicBlock( AssemblyEnv* assemEnvPtr, /* Assembly environment */ BasicBlock* bbPtr, /* Basic block being processed */ BasicBlock* enclosing, /* Start basic block of the enclosing catch */ enum BasicBlockCatchState state, /* BBCS_NONE, BBCS_INCATCH, or BBCS_CAUGHT */ int catchDepth) /* Depth of nesting of catches */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ int result; /* Return value from this procedure */ BasicBlock* fallThruEnclosing; /* Enclosing catch if execution falls thru */ enum BasicBlockCatchState fallThruState; /* Catch state of the successor block */ BasicBlock* jumpEnclosing; /* Enclosing catch if execution goes to jump * target */ enum BasicBlockCatchState jumpState; /* Catch state of the jump target */ int changed = 0; /* Flag == 1 iff successor blocks need to be * checked because the state of this block has * changed. */ BasicBlock* jumpTarget; /* Basic block where a jump goes */ Tcl_HashSearch jtSearch; /* Hash search control for a jumptable */ Tcl_HashEntry* jtEntry; /* Entry in a jumptable */ Tcl_Obj* targetLabel; /* Target label from a jumptable */ Tcl_HashEntry* entry; /* Entry from the label table */ /* * Update the state of the current block, checking for consistency. Set * 'changed' to 1 if the state changes and successor blocks need to be * rechecked. */ if (bbPtr->catchState == BBCS_UNKNOWN) { bbPtr->enclosingCatch = enclosing; } else if (bbPtr->enclosingCatch != enclosing) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "execution reaches an instruction in inconsistent " "exception contexts", -1)); Tcl_SetErrorLine(interp, bbPtr->startLine); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADCATCH", NULL); } return TCL_ERROR; } if (state > bbPtr->catchState) { bbPtr->catchState = state; changed = 1; } /* * If this block has been visited before, and its state hasn't changed, * we're done with it for now. */ if (!changed) { return TCL_OK; } bbPtr->catchDepth = catchDepth; /* * Determine enclosing catch and 'caught' state for the fallthrough and * the jump target. Default for both is the state of the current block. */ fallThruEnclosing = enclosing; fallThruState = state; jumpEnclosing = enclosing; jumpState = state; /* * TODO: Make sure that the test cases include validating that a natural * loop can't include 'beginCatch' or 'endCatch' */ if (bbPtr->flags & BB_BEGINCATCH) { /* * If the block begins a catch, the state for the successor is 'in * catch'. The jump target is the exception exit, and the state of the * jump target is 'caught.' */ fallThruEnclosing = bbPtr; fallThruState = BBCS_INCATCH; jumpEnclosing = bbPtr; jumpState = BBCS_CAUGHT; ++catchDepth; } if (bbPtr->flags & BB_ENDCATCH) { /* * If the block ends a catch, the state for the successor is whatever * the state was on entry to the catch. */ if (enclosing == NULL) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "endCatch without a corresponding beginCatch", -1)); Tcl_SetErrorLine(interp, bbPtr->startLine); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "BADENDCATCH", NULL); } return TCL_ERROR; } fallThruEnclosing = enclosing->enclosingCatch; fallThruState = enclosing->catchState; --catchDepth; } /* * Visit any successor blocks with the appropriate exception context */ result = TCL_OK; if (bbPtr->flags & BB_FALLTHRU) { result = ProcessCatchesInBasicBlock(assemEnvPtr, bbPtr->successor1, fallThruEnclosing, fallThruState, catchDepth); } if (result == TCL_OK && bbPtr->jumpTarget != NULL) { entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash, Tcl_GetString(bbPtr->jumpTarget)); jumpTarget = Tcl_GetHashValue(entry); result = ProcessCatchesInBasicBlock(assemEnvPtr, jumpTarget, jumpEnclosing, jumpState, catchDepth); } /* * All blocks referenced in a jump table are successors. */ if (bbPtr->flags & BB_JUMPTABLE) { for (jtEntry = Tcl_FirstHashEntry(&bbPtr->jtPtr->hashTable,&jtSearch); result == TCL_OK && jtEntry != NULL; jtEntry = Tcl_NextHashEntry(&jtSearch)) { targetLabel = Tcl_GetHashValue(jtEntry); entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash, Tcl_GetString(targetLabel)); jumpTarget = Tcl_GetHashValue(entry); result = ProcessCatchesInBasicBlock(assemEnvPtr, jumpTarget, jumpEnclosing, jumpState, catchDepth); } } return result; } /* *----------------------------------------------------------------------------- * * CheckForUnclosedCatches -- * * Checks that a sequence of assembly code has no unclosed catches on * exit. * * Results: * Returns a standard Tcl result, with an error message for unclosed * catches. * *----------------------------------------------------------------------------- */ static int CheckForUnclosedCatches( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ if (assemEnvPtr->curr_bb->catchState >= BBCS_INCATCH) { if (assemEnvPtr->flags & TCL_EVAL_DIRECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "catch still active on exit from assembly code", -1)); Tcl_SetErrorLine(interp, assemEnvPtr->curr_bb->enclosingCatch->startLine); Tcl_SetErrorCode(interp, "TCL", "ASSEM", "UNCLOSEDCATCH", NULL); } return TCL_ERROR; } return TCL_OK; } /* *----------------------------------------------------------------------------- * * BuildExceptionRanges -- * * Walks through the assembly code and builds exception ranges for the * catches embedded therein. * * Results: * Returns a standard Tcl result with an error message in the interpreter * if anything is unsuccessful. * * Side effects: * Each contiguous block of code with a given catch exit is assigned an * exception range at the appropriate level. * Exception ranges in embedded blocks have their levels corrected and * collated into the table. * Blocks that end with 'beginCatch' are associated with the innermost * exception range of the following block. * *----------------------------------------------------------------------------- */ static int BuildExceptionRanges( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ BasicBlock* bbPtr; /* Current basic block */ BasicBlock* prevPtr = NULL; /* Previous basic block */ int catchDepth = 0; /* Current catch depth */ int maxCatchDepth = 0; /* Maximum catch depth in the program */ BasicBlock** catches; /* Stack of catches in progress */ int* catchIndices; /* Indices of the exception ranges of catches * in progress */ int i; /* * Determine the max catch depth for the entire assembly script * (excluding embedded eval's and expr's, which will be handled later). */ for (bbPtr=assemEnvPtr->head_bb; bbPtr != NULL; bbPtr=bbPtr->successor1) { if (bbPtr->catchDepth > maxCatchDepth) { maxCatchDepth = bbPtr->catchDepth; } } /* * Allocate memory for a stack of active catches. */ catches = ckalloc(maxCatchDepth * sizeof(BasicBlock*)); catchIndices = ckalloc(maxCatchDepth * sizeof(int)); for (i = 0; i < maxCatchDepth; ++i) { catches[i] = NULL; catchIndices[i] = -1; } /* * Walk through the basic blocks and manage exception ranges. */ for (bbPtr=assemEnvPtr->head_bb; bbPtr != NULL; bbPtr=bbPtr->successor1) { UnstackExpiredCatches(envPtr, bbPtr, catchDepth, catches, catchIndices); LookForFreshCatches(bbPtr, catches); StackFreshCatches(assemEnvPtr, bbPtr, catchDepth, catches, catchIndices); /* * If the last block was a 'begin catch', fill in the exception range. */ catchDepth = bbPtr->catchDepth; if (prevPtr != NULL && (prevPtr->flags & BB_BEGINCATCH)) { TclStoreInt4AtPtr(catchIndices[catchDepth-1], envPtr->codeStart + bbPtr->startOffset - 4); } prevPtr = bbPtr; } /* Make sure that all catches are closed */ if (catchDepth != 0) { Tcl_Panic("unclosed catch at end of code in " "tclAssembly.c:BuildExceptionRanges, can't happen"); } /* Free temp storage */ ckfree(catchIndices); ckfree(catches); return TCL_OK; } /* *----------------------------------------------------------------------------- * * UnstackExpiredCatches -- * * Unstacks and closes the exception ranges for any catch contexts that * were active in the previous basic block but are inactive in the * current one. * *----------------------------------------------------------------------------- */ static void UnstackExpiredCatches( CompileEnv* envPtr, /* Compilation environment */ BasicBlock* bbPtr, /* Basic block being processed */ int catchDepth, /* Depth of nesting of catches prior to entry * to this block */ BasicBlock** catches, /* Array of catch contexts */ int* catchIndices) /* Indices of the exception ranges * corresponding to the catch contexts */ { ExceptionRange* range; /* Exception range for a specific catch */ BasicBlock* catch; /* Catch block being examined */ BasicBlockCatchState catchState; /* State of the code relative to the catch * block being examined ("in catch" or * "caught"). */ /* * Unstack any catches that are deeper than the nesting level of the basic * block being entered. */ while (catchDepth > bbPtr->catchDepth) { --catchDepth; range = envPtr->exceptArrayPtr + catchIndices[catchDepth]; range->numCodeBytes = bbPtr->startOffset - range->codeOffset; catches[catchDepth] = NULL; catchIndices[catchDepth] = -1; } /* * Unstack any catches that don't match the basic block being entered, * either because they are no longer part of the context, or because the * context has changed from INCATCH to CAUGHT. */ catchState = bbPtr->catchState; catch = bbPtr->enclosingCatch; while (catchDepth > 0) { --catchDepth; if (catches[catchDepth] != NULL) { if (catches[catchDepth] != catch || catchState >= BBCS_CAUGHT) { range = envPtr->exceptArrayPtr + catchIndices[catchDepth]; range->numCodeBytes = bbPtr->startOffset - range->codeOffset; catches[catchDepth] = NULL; catchIndices[catchDepth] = -1; } catchState = catch->catchState; catch = catch->enclosingCatch; } } } /* *----------------------------------------------------------------------------- * * LookForFreshCatches -- * * Determines whether a basic block being entered needs any exception * ranges that are not already stacked. * * Does not create the ranges: this procedure iterates from the innermost * catch outward, but exception ranges must be created from the outermost * catch inward. * *----------------------------------------------------------------------------- */ static void LookForFreshCatches( BasicBlock* bbPtr, /* Basic block being entered */ BasicBlock** catches) /* Array of catch contexts that are already * entered */ { BasicBlockCatchState catchState; /* State ("in catch" or "caught") of the * current catch. */ BasicBlock* catch; /* Current enclosing catch */ int catchDepth; /* Nesting depth of the current catch */ catchState = bbPtr->catchState; catch = bbPtr->enclosingCatch; catchDepth = bbPtr->catchDepth; while (catchDepth > 0) { --catchDepth; if (catches[catchDepth] != catch && catchState < BBCS_CAUGHT) { catches[catchDepth] = catch; } catchState = catch->catchState; catch = catch->enclosingCatch; } } /* *----------------------------------------------------------------------------- * * StackFreshCatches -- * * Make ExceptionRange records for any catches that are in the basic * block being entered and were not in the previous basic block. * *----------------------------------------------------------------------------- */ static void StackFreshCatches( AssemblyEnv* assemEnvPtr, /* Assembly environment */ BasicBlock* bbPtr, /* Basic block being processed */ int catchDepth, /* Depth of nesting of catches prior to entry * to this block */ BasicBlock** catches, /* Array of catch contexts */ int* catchIndices) /* Indices of the exception ranges * corresponding to the catch contexts */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ ExceptionRange* range; /* Exception range for a specific catch */ BasicBlock* catch; /* Catch block being examined */ BasicBlock* errorExit; /* Error exit from the catch block */ Tcl_HashEntry* entryPtr; catchDepth = 0; /* * Iterate through the enclosing catch blocks from the outside in, * looking for ones that don't have exception ranges (and are uncaught) */ for (catchDepth = 0; catchDepth < bbPtr->catchDepth; ++catchDepth) { if (catchIndices[catchDepth] == -1 && catches[catchDepth] != NULL) { /* * Create an exception range for a block that needs one. */ catch = catches[catchDepth]; catchIndices[catchDepth] = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr); range = envPtr->exceptArrayPtr + catchIndices[catchDepth]; range->nestingLevel = envPtr->exceptDepth + catchDepth; envPtr->maxExceptDepth = TclMax(range->nestingLevel + 1, envPtr->maxExceptDepth); range->codeOffset = bbPtr->startOffset; entryPtr = Tcl_FindHashEntry(&assemEnvPtr->labelHash, Tcl_GetString(catch->jumpTarget)); if (entryPtr == NULL) { Tcl_Panic("undefined label in tclAssembly.c:" "BuildExceptionRanges, can't happen"); } errorExit = Tcl_GetHashValue(entryPtr); range->catchOffset = errorExit->startOffset; } } } /* *----------------------------------------------------------------------------- * * RestoreEmbeddedExceptionRanges -- * * Processes an assembly script, replacing any exception ranges that * were present in embedded code. * *----------------------------------------------------------------------------- */ static void RestoreEmbeddedExceptionRanges( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ BasicBlock* bbPtr; /* Current basic block */ int rangeBase; /* Base of the foreign exception ranges when * they are reinstalled */ int rangeIndex; /* Index of the current foreign exception * range as reinstalled */ ExceptionRange* range; /* Current foreign exception range */ unsigned char opcode; /* Current instruction's opcode */ int catchIndex; /* Index of the exception range to which the * current instruction refers */ int i; /* * Walk the basic blocks looking for exceptions in embedded scripts. */ for (bbPtr = assemEnvPtr->head_bb; bbPtr != NULL; bbPtr = bbPtr->successor1) { if (bbPtr->foreignExceptionCount != 0) { /* * Reinstall the embedded exceptions and track their nesting level */ rangeBase = envPtr->exceptArrayNext; for (i = 0; i < bbPtr->foreignExceptionCount; ++i) { range = bbPtr->foreignExceptions + i; rangeIndex = TclCreateExceptRange(range->type, envPtr); range->nestingLevel += envPtr->exceptDepth + bbPtr->catchDepth; memcpy(envPtr->exceptArrayPtr + rangeIndex, range, sizeof(ExceptionRange)); if (range->nestingLevel >= envPtr->maxExceptDepth) { envPtr->maxExceptDepth = range->nestingLevel + 1; } } /* * Walk through the bytecode of the basic block, and relocate * INST_BEGIN_CATCH4 instructions to the new locations */ i = bbPtr->startOffset; while (i < bbPtr->successor1->startOffset) { opcode = envPtr->codeStart[i]; if (opcode == INST_BEGIN_CATCH4) { catchIndex = TclGetUInt4AtPtr(envPtr->codeStart + i + 1); if (catchIndex >= bbPtr->foreignExceptionBase && catchIndex < (bbPtr->foreignExceptionBase + bbPtr->foreignExceptionCount)) { catchIndex -= bbPtr->foreignExceptionBase; catchIndex += rangeBase; TclStoreInt4AtPtr(catchIndex, envPtr->codeStart+i+1); } } i += tclInstructionTable[opcode].numBytes; } } } } /* *----------------------------------------------------------------------------- * * ResetVisitedBasicBlocks -- * * Turns off the 'visited' flag in all basic blocks at the conclusion * of a pass. * *----------------------------------------------------------------------------- */ static void ResetVisitedBasicBlocks( AssemblyEnv* assemEnvPtr) /* Assembly environment */ { BasicBlock* block; for (block = assemEnvPtr->head_bb; block != NULL; block = block->successor1) { block->flags &= ~BB_VISITED; } } /* *----------------------------------------------------------------------------- * * AddBasicBlockRangeToErrorInfo -- * * Updates the error info of the Tcl interpreter to show a given basic * block in the code. * * This procedure is used to label the callstack with source location * information when reporting an error in stack checking. * *----------------------------------------------------------------------------- */ static void AddBasicBlockRangeToErrorInfo( AssemblyEnv* assemEnvPtr, /* Assembly environment */ BasicBlock* bbPtr) /* Basic block in which the error is found */ { CompileEnv* envPtr = assemEnvPtr->envPtr; /* Compilation environment */ Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ Tcl_Obj* lineNo; /* Line number in the source */ Tcl_AddErrorInfo(interp, "\n in assembly code between lines "); lineNo = Tcl_NewIntObj(bbPtr->startLine); Tcl_IncrRefCount(lineNo); Tcl_AppendObjToErrorInfo(interp, lineNo); Tcl_AddErrorInfo(interp, " and "); if (bbPtr->successor1 != NULL) { Tcl_SetIntObj(lineNo, bbPtr->successor1->startLine); Tcl_AppendObjToErrorInfo(interp, lineNo); } else { Tcl_AddErrorInfo(interp, "end of assembly code"); } Tcl_DecrRefCount(lineNo); } /* *----------------------------------------------------------------------------- * * DupAssembleCodeInternalRep -- * * Part of the Tcl object type implementation for Tcl assembly language * bytecode. We do not copy the bytecode intrep. Instead, we return * without setting copyPtr->typePtr, so the copy is a plain string copy * of the assembly source, and if it is to be used as a compiled * expression, it will need to be reprocessed. * * This makes sense, because with Tcl's copy-on-write practices, the * usual (only?) time Tcl_DuplicateObj() will be called is when the copy * is about to be modified, which would invalidate any copied bytecode * anyway. The only reason it might make sense to copy the bytecode is if * we had some modifying routines that operated directly on the intrep, * as we do for lists and dicts. * * Results: * None. * * Side effects: * None. * *----------------------------------------------------------------------------- */ static void DupAssembleCodeInternalRep( Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) { return; } /* *----------------------------------------------------------------------------- * * FreeAssembleCodeInternalRep -- * * Part of the Tcl object type implementation for Tcl expression * bytecode. Frees the storage allocated to hold the internal rep, unless * ref counts indicate bytecode execution is still in progress. * * Results: * None. * * Side effects: * May free allocated memory. Leaves objPtr untyped. * *----------------------------------------------------------------------------- */ static void FreeAssembleCodeInternalRep( Tcl_Obj *objPtr) { ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1; codePtr->refCount--; if (codePtr->refCount <= 0) { TclCleanupByteCode(codePtr); } objPtr->typePtr = NULL; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclLiteral.c0000644000175000017500000010632512663660065015455 0ustar sergeisergei/* * tclLiteral.c -- * * Implementation of the global and ByteCode-local literal tables used to * manage the Tcl objects created for literal values during compilation * of Tcl scripts. This implementation borrows heavily from the more * general hashtable implementation of Tcl hash tables that appears in * tclHash.c. * * Copyright (c) 1997-1998 Sun Microsystems, Inc. * Copyright (c) 2004 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" /* * When there are this many entries per bucket, on average, rebuild a * literal's hash table to make it larger. */ #define REBUILD_MULTIPLIER 3 /* * Function prototypes for static functions in this file: */ static int AddLocalLiteralEntry(CompileEnv *envPtr, Tcl_Obj *objPtr, int localHash); static void ExpandLocalLiteralArray(CompileEnv *envPtr); static unsigned HashString(const char *string, int length); #ifdef TCL_COMPILE_DEBUG static LiteralEntry * LookupLiteralEntry(Tcl_Interp *interp, Tcl_Obj *objPtr); #endif static void RebuildLiteralTable(LiteralTable *tablePtr); /* *---------------------------------------------------------------------- * * TclInitLiteralTable -- * * This function is called to initialize the fields of a literal table * structure for either an interpreter or a compilation's CompileEnv * structure. * * Results: * None. * * Side effects: * The literal table is made ready for use. * *---------------------------------------------------------------------- */ void TclInitLiteralTable( register LiteralTable *tablePtr) /* Pointer to table structure, which is * supplied by the caller. */ { #if (TCL_SMALL_HASH_TABLE != 4) Tcl_Panic("%s: TCL_SMALL_HASH_TABLE is %d, not 4", "TclInitLiteralTable", TCL_SMALL_HASH_TABLE); #endif tablePtr->buckets = tablePtr->staticBuckets; tablePtr->staticBuckets[0] = tablePtr->staticBuckets[1] = 0; tablePtr->staticBuckets[2] = tablePtr->staticBuckets[3] = 0; tablePtr->numBuckets = TCL_SMALL_HASH_TABLE; tablePtr->numEntries = 0; tablePtr->rebuildSize = TCL_SMALL_HASH_TABLE * REBUILD_MULTIPLIER; tablePtr->mask = 3; } /* *---------------------------------------------------------------------- * * TclDeleteLiteralTable -- * * This function frees up everything associated with a literal table * except for the table's structure itself. It is called when the * interpreter is deleted. * * Results: * None. * * Side effects: * Each literal in the table is released: i.e., its reference count in * the global literal table is decremented and, if it becomes zero, the * literal is freed. In addition, the table's bucket array is freed. * *---------------------------------------------------------------------- */ void TclDeleteLiteralTable( Tcl_Interp *interp, /* Interpreter containing shared literals * referenced by the table to delete. */ LiteralTable *tablePtr) /* Points to the literal table to delete. */ { LiteralEntry *entryPtr, *nextPtr; Tcl_Obj *objPtr; int i; /* * Release remaining literals in the table. Note that releasing a literal * might release other literals, modifying the table, so we restart the * search from the bucket chain we last found an entry. */ #ifdef TCL_COMPILE_DEBUG TclVerifyGlobalLiteralTable((Interp *) interp); #endif /*TCL_COMPILE_DEBUG*/ /* * We used to call TclReleaseLiteral for each literal in the table, which * is rather inefficient as it causes one lookup-by-hash for each * reference to the literal. We now rely at interp-deletion on each * bytecode object to release its references to the literal Tcl_Obj * without requiring that it updates the global table itself, and deal * here only with the table. */ for (i=0 ; inumBuckets ; i++) { entryPtr = tablePtr->buckets[i]; while (entryPtr != NULL) { objPtr = entryPtr->objPtr; TclDecrRefCount(objPtr); nextPtr = entryPtr->nextPtr; ckfree(entryPtr); entryPtr = nextPtr; } } /* * Free up the table's bucket array if it was dynamically allocated. */ if (tablePtr->buckets != tablePtr->staticBuckets) { ckfree(tablePtr->buckets); } } /* *---------------------------------------------------------------------- * * TclCreateLiteral -- * * Find, or if necessary create, an object in the interpreter's literal * table that has a string representation matching the argument * string. If nsPtr!=NULL then only literals stored for the namespace are * considered. * * Results: * The literal object. If it was created in this call *newPtr is set to * 1, else 0. NULL is returned if newPtr==NULL and no literal is found. * * Side effects: * Increments the ref count of the global LiteralEntry since the caller * now holds a reference. If LITERAL_ON_HEAP is set in flags, this * function is given ownership of the string: if an object is created * then its string representation is set directly from string, otherwise * the string is freed. Typically, a caller sets LITERAL_ON_HEAP if * "string" is an already heap-allocated buffer holding the result of * backslash substitutions. * *---------------------------------------------------------------------- */ Tcl_Obj * TclCreateLiteral( Interp *iPtr, char *bytes, /* The start of the string. Note that this is * not a NUL-terminated string. */ int length, /* Number of bytes in the string. */ unsigned hash, /* The string's hash. If -1, it will be * computed here. */ int *newPtr, Namespace *nsPtr, int flags, LiteralEntry **globalPtrPtr) { LiteralTable *globalTablePtr = &iPtr->literalTable; LiteralEntry *globalPtr; int globalHash; Tcl_Obj *objPtr; /* * Is it in the interpreter's global literal table? */ if (hash == (unsigned) -1) { hash = HashString(bytes, length); } globalHash = (hash & globalTablePtr->mask); for (globalPtr=globalTablePtr->buckets[globalHash] ; globalPtr!=NULL; globalPtr = globalPtr->nextPtr) { objPtr = globalPtr->objPtr; if ((globalPtr->nsPtr == nsPtr) && (objPtr->length == length) && ((length == 0) || ((objPtr->bytes[0] == bytes[0]) && (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) { /* * A literal was found: return it */ if (newPtr) { *newPtr = 0; } if (globalPtrPtr) { *globalPtrPtr = globalPtr; } if (flags & LITERAL_ON_HEAP) { ckfree(bytes); } globalPtr->refCount++; return objPtr; } } if (!newPtr) { if (flags & LITERAL_ON_HEAP) { ckfree(bytes); } return NULL; } /* * The literal is new to the interpreter. Add it to the global literal * table. */ TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); if (flags & LITERAL_ON_HEAP) { objPtr->bytes = bytes; objPtr->length = length; } else { TclInitStringRep(objPtr, bytes, length); } #ifdef TCL_COMPILE_DEBUG if (LookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) { Tcl_Panic("%s: literal \"%.*s\" found globally but shouldn't be", "TclRegisterLiteral", (length>60? 60 : length), bytes); } #endif globalPtr = ckalloc(sizeof(LiteralEntry)); globalPtr->objPtr = objPtr; globalPtr->refCount = 1; globalPtr->nsPtr = nsPtr; globalPtr->nextPtr = globalTablePtr->buckets[globalHash]; globalTablePtr->buckets[globalHash] = globalPtr; globalTablePtr->numEntries++; /* * If the global literal table has exceeded a decent size, rebuild it with * more buckets. */ if (globalTablePtr->numEntries >= globalTablePtr->rebuildSize) { RebuildLiteralTable(globalTablePtr); } #ifdef TCL_COMPILE_DEBUG TclVerifyGlobalLiteralTable(iPtr); { LiteralEntry *entryPtr; int found, i; found = 0; for (i=0 ; inumBuckets ; i++) { for (entryPtr=globalTablePtr->buckets[i]; entryPtr!=NULL ; entryPtr=entryPtr->nextPtr) { if ((entryPtr == globalPtr) && (entryPtr->objPtr == objPtr)) { found = 1; } } } if (!found) { Tcl_Panic("%s: literal \"%.*s\" wasn't global", "TclRegisterLiteral", (length>60? 60 : length), bytes); } } #endif /*TCL_COMPILE_DEBUG*/ #ifdef TCL_COMPILE_STATS iPtr->stats.numLiteralsCreated++; iPtr->stats.totalLitStringBytes += (double) (length + 1); iPtr->stats.currentLitStringBytes += (double) (length + 1); iPtr->stats.literalCount[TclLog2(length)]++; #endif /*TCL_COMPILE_STATS*/ if (globalPtrPtr) { *globalPtrPtr = globalPtr; } *newPtr = 1; return objPtr; } /* *---------------------------------------------------------------------- * * TclFetchLiteral -- * * Fetch from a CompileEnv the literal value identified by an index * value, as returned by a prior call to TclRegisterLiteral(). * * Results: * The literal value, or NULL if the index is out of range. * *---------------------------------------------------------------------- */ Tcl_Obj * TclFetchLiteral( CompileEnv *envPtr, /* Points to the CompileEnv from which to * fetch the registered literal value. */ unsigned int index) /* Index of the desired literal, as returned * by prior call to TclRegisterLiteral() */ { if (index >= (unsigned int) envPtr->literalArrayNext) { return NULL; } return envPtr->literalArrayPtr[index].objPtr; } /* *---------------------------------------------------------------------- * * TclRegisterLiteral -- * * Find, or if necessary create, an object in a CompileEnv literal array * that has a string representation matching the argument string. * * Results: * The index in the CompileEnv's literal array that references a shared * literal matching the string. The object is created if necessary. * * Side effects: * To maximize sharing, we look up the string in the interpreter's global * literal table. If not found, we create a new shared literal in the * global table. We then add a reference to the shared literal in the * CompileEnv's literal array. * * If LITERAL_ON_HEAP is set in flags, this function is given ownership * of the string: if an object is created then its string representation * is set directly from string, otherwise the string is freed. Typically, * a caller sets LITERAL_ON_HEAP if "string" is an already heap-allocated * buffer holding the result of backslash substitutions. * *---------------------------------------------------------------------- */ int TclRegisterLiteral( void *ePtr, /* Points to the CompileEnv in whose object * array an object is found or created. */ register char *bytes, /* Points to string for which to find or * create an object in CompileEnv's object * array. */ int length, /* Number of bytes in the string. If < 0, the * string consists of all bytes up to the * first null character. */ int flags) /* If LITERAL_ON_HEAP then the caller already * malloc'd bytes and ownership is passed to * this function. If LITERAL_CMD_NAME then * the literal should not be shared accross * namespaces. */ { CompileEnv *envPtr = ePtr; Interp *iPtr = envPtr->iPtr; LiteralTable *localTablePtr = &envPtr->localLitTable; LiteralEntry *globalPtr, *localPtr; Tcl_Obj *objPtr; unsigned hash; int localHash, objIndex, new; Namespace *nsPtr; if (length < 0) { length = (bytes ? strlen(bytes) : 0); } hash = HashString(bytes, length); /* * Is the literal already in the CompileEnv's local literal array? If so, * just return its index. */ localHash = (hash & localTablePtr->mask); for (localPtr=localTablePtr->buckets[localHash] ; localPtr!=NULL; localPtr = localPtr->nextPtr) { objPtr = localPtr->objPtr; if ((objPtr->length == length) && ((length == 0) || ((objPtr->bytes[0] == bytes[0]) && (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) { if (flags & LITERAL_ON_HEAP) { ckfree(bytes); } objIndex = (localPtr - envPtr->literalArrayPtr); #ifdef TCL_COMPILE_DEBUG TclVerifyLocalLiteralTable(envPtr); #endif /*TCL_COMPILE_DEBUG*/ return objIndex; } } /* * The literal is new to this CompileEnv. If it is a command name, avoid * sharing it accross namespaces, and try not to share it with non-cmd * literals. Note that FQ command names can be shared, so that we register * the namespace as the interp's global NS. */ if (flags & LITERAL_CMD_NAME) { if ((length >= 2) && (bytes[0] == ':') && (bytes[1] == ':')) { nsPtr = iPtr->globalNsPtr; } else { nsPtr = iPtr->varFramePtr->nsPtr; } } else { nsPtr = NULL; } /* * Is it in the interpreter's global literal table? If not, create it. */ objPtr = TclCreateLiteral(iPtr, bytes, length, hash, &new, nsPtr, flags, &globalPtr); objIndex = AddLocalLiteralEntry(envPtr, objPtr, localHash); #ifdef TCL_COMPILE_DEBUG if (globalPtr->refCount < 1) { Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d", "TclRegisterLiteral", (length>60? 60 : length), bytes, globalPtr->refCount); } TclVerifyLocalLiteralTable(envPtr); #endif /*TCL_COMPILE_DEBUG*/ return objIndex; } #ifdef TCL_COMPILE_DEBUG /* *---------------------------------------------------------------------- * * LookupLiteralEntry -- * * Finds the LiteralEntry that corresponds to a literal Tcl object * holding a literal. * * Results: * Returns the matching LiteralEntry if found, otherwise NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ static LiteralEntry * LookupLiteralEntry( Tcl_Interp *interp, /* Interpreter for which objPtr was created to * hold a literal. */ register Tcl_Obj *objPtr) /* Points to a Tcl object holding a literal * that was previously created by a call to * TclRegisterLiteral. */ { Interp *iPtr = (Interp *) interp; LiteralTable *globalTablePtr = &iPtr->literalTable; register LiteralEntry *entryPtr; const char *bytes; int length, globalHash; bytes = TclGetStringFromObj(objPtr, &length); globalHash = (HashString(bytes, length) & globalTablePtr->mask); for (entryPtr=globalTablePtr->buckets[globalHash] ; entryPtr!=NULL; entryPtr=entryPtr->nextPtr) { if (entryPtr->objPtr == objPtr) { return entryPtr; } } return NULL; } #endif /* *---------------------------------------------------------------------- * * TclHideLiteral -- * * Remove a literal entry from the literal hash tables, leaving it in the * literal array so existing references continue to function. This makes * it possible to turn a shared literal into a private literal that * cannot be shared. * * Results: * None. * * Side effects: * Removes the literal from the local hash table and decrements the * global hash entry's reference count. * *---------------------------------------------------------------------- */ void TclHideLiteral( Tcl_Interp *interp, /* Interpreter for which objPtr was created to * hold a literal. */ register CompileEnv *envPtr,/* Points to CompileEnv whose literal array * contains the entry being hidden. */ int index) /* The index of the entry in the literal * array. */ { LiteralEntry **nextPtrPtr, *entryPtr, *lPtr; LiteralTable *localTablePtr = &envPtr->localLitTable; int localHash, length; const char *bytes; Tcl_Obj *newObjPtr; lPtr = &envPtr->literalArrayPtr[index]; /* * To avoid unwanted sharing we need to copy the object and remove it from * the local and global literal tables. It still has a slot in the literal * array so it can be referred to by byte codes, but it will not be * matched by literal searches. */ newObjPtr = Tcl_DuplicateObj(lPtr->objPtr); Tcl_IncrRefCount(newObjPtr); TclReleaseLiteral(interp, lPtr->objPtr); lPtr->objPtr = newObjPtr; bytes = TclGetStringFromObj(newObjPtr, &length); localHash = (HashString(bytes, length) & localTablePtr->mask); nextPtrPtr = &localTablePtr->buckets[localHash]; for (entryPtr=*nextPtrPtr ; entryPtr!=NULL ; entryPtr=*nextPtrPtr) { if (entryPtr == lPtr) { *nextPtrPtr = lPtr->nextPtr; lPtr->nextPtr = NULL; localTablePtr->numEntries--; break; } nextPtrPtr = &entryPtr->nextPtr; } } /* *---------------------------------------------------------------------- * * TclAddLiteralObj -- * * Add a single literal object to the literal array. This function does * not add the literal to the local or global literal tables. The caller * is expected to add the entry to whatever tables are appropriate. * * Results: * The index in the CompileEnv's literal array that references the * literal. Stores the pointer to the new literal entry in the location * referenced by the localPtrPtr argument. * * Side effects: * Expands the literal array if necessary. Increments the refcount on the * literal object. * *---------------------------------------------------------------------- */ int TclAddLiteralObj( register CompileEnv *envPtr,/* Points to CompileEnv in whose literal array * the object is to be inserted. */ Tcl_Obj *objPtr, /* The object to insert into the array. */ LiteralEntry **litPtrPtr) /* The location where the pointer to the new * literal entry should be stored. May be * NULL. */ { register LiteralEntry *lPtr; int objIndex; if (envPtr->literalArrayNext >= envPtr->literalArrayEnd) { ExpandLocalLiteralArray(envPtr); } objIndex = envPtr->literalArrayNext; envPtr->literalArrayNext++; lPtr = &envPtr->literalArrayPtr[objIndex]; lPtr->objPtr = objPtr; Tcl_IncrRefCount(objPtr); lPtr->refCount = -1; /* i.e., unused */ lPtr->nextPtr = NULL; if (litPtrPtr) { *litPtrPtr = lPtr; } return objIndex; } /* *---------------------------------------------------------------------- * * AddLocalLiteralEntry -- * * Insert a new literal into a CompileEnv's local literal array. * * Results: * The index in the CompileEnv's literal array that references the * literal. * * Side effects: * Expands the literal array if necessary. May rebuild the hash bucket * array of the CompileEnv's literal array if it becomes too large. * *---------------------------------------------------------------------- */ static int AddLocalLiteralEntry( register CompileEnv *envPtr,/* Points to CompileEnv in whose literal array * the object is to be inserted. */ Tcl_Obj *objPtr, /* The literal to add to the CompileEnv. */ int localHash) /* Hash value for the literal's string. */ { register LiteralTable *localTablePtr = &envPtr->localLitTable; LiteralEntry *localPtr; int objIndex; objIndex = TclAddLiteralObj(envPtr, objPtr, &localPtr); /* * Add the literal to the local table. */ localPtr->nextPtr = localTablePtr->buckets[localHash]; localTablePtr->buckets[localHash] = localPtr; localTablePtr->numEntries++; /* * If the CompileEnv's local literal table has exceeded a decent size, * rebuild it with more buckets. */ if (localTablePtr->numEntries >= localTablePtr->rebuildSize) { RebuildLiteralTable(localTablePtr); } #ifdef TCL_COMPILE_DEBUG TclVerifyLocalLiteralTable(envPtr); { char *bytes; int length, found, i; found = 0; for (i=0 ; inumBuckets ; i++) { for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL ; localPtr=localPtr->nextPtr) { if (localPtr->objPtr == objPtr) { found = 1; } } } if (!found) { bytes = Tcl_GetStringFromObj(objPtr, &length); Tcl_Panic("%s: literal \"%.*s\" wasn't found locally", "AddLocalLiteralEntry", (length>60? 60 : length), bytes); } } #endif /*TCL_COMPILE_DEBUG*/ return objIndex; } /* *---------------------------------------------------------------------- * * ExpandLocalLiteralArray -- * * Function that uses malloc to allocate more storage for a CompileEnv's * local literal array. * * Results: * None. * * Side effects: * The literal array in *envPtr is reallocated to a new array of double * the size, and if envPtr->mallocedLiteralArray is non-zero the old * array is freed. Entries are copied from the old array to the new one. * The local literal table is updated to refer to the new entries. * *---------------------------------------------------------------------- */ static void ExpandLocalLiteralArray( register CompileEnv *envPtr)/* Points to the CompileEnv whose object array * must be enlarged. */ { /* * The current allocated local literal entries are stored between elements * 0 and (envPtr->literalArrayNext - 1) [inclusive]. */ LiteralTable *localTablePtr = &envPtr->localLitTable; int currElems = envPtr->literalArrayNext; size_t currBytes = (currElems * sizeof(LiteralEntry)); LiteralEntry *currArrayPtr = envPtr->literalArrayPtr; LiteralEntry *newArrayPtr; int i; unsigned int newSize = (currBytes <= UINT_MAX / 2) ? 2*currBytes : UINT_MAX; if (currBytes == newSize) { Tcl_Panic("max size of Tcl literal array (%d literals) exceeded", currElems); } if (envPtr->mallocedLiteralArray) { newArrayPtr = ckrealloc(currArrayPtr, newSize); } else { /* * envPtr->literalArrayPtr isn't a ckalloc'd pointer, so we must * code a ckrealloc equivalent for ourselves. */ newArrayPtr = ckalloc(newSize); memcpy(newArrayPtr, currArrayPtr, currBytes); envPtr->mallocedLiteralArray = 1; } /* * Update the local literal table's bucket array. */ if (currArrayPtr != newArrayPtr) { for (i=0 ; inumBuckets ; i++) { if (localTablePtr->buckets[i] != NULL) { localTablePtr->buckets[i] = newArrayPtr + (localTablePtr->buckets[i] - currArrayPtr); } } } envPtr->literalArrayPtr = newArrayPtr; envPtr->literalArrayEnd = newSize / sizeof(LiteralEntry); } /* *---------------------------------------------------------------------- * * TclReleaseLiteral -- * * This function releases a reference to one of the shared Tcl objects * that hold literals. It is called to release the literals referenced by * a ByteCode that is being destroyed, and it is also called by * TclDeleteLiteralTable. * * Results: * None. * * Side effects: * The reference count for the global LiteralTable entry that corresponds * to the literal is decremented. If no other reference to a global * literal object remains, it is freed. * *---------------------------------------------------------------------- */ void TclReleaseLiteral( Tcl_Interp *interp, /* Interpreter for which objPtr was created to * hold a literal. */ register Tcl_Obj *objPtr) /* Points to a literal object that was * previously created by a call to * TclRegisterLiteral. */ { Interp *iPtr = (Interp *) interp; LiteralTable *globalTablePtr; register LiteralEntry *entryPtr, *prevPtr; const char *bytes; int length, index; if (iPtr == NULL) { goto done; } globalTablePtr = &iPtr->literalTable; bytes = TclGetStringFromObj(objPtr, &length); index = (HashString(bytes, length) & globalTablePtr->mask); /* * Check to see if the object is in the global literal table and remove * this reference. The object may not be in the table if it is a hidden * local literal. */ for (prevPtr=NULL, entryPtr=globalTablePtr->buckets[index]; entryPtr!=NULL ; prevPtr=entryPtr, entryPtr=entryPtr->nextPtr) { if (entryPtr->objPtr == objPtr) { entryPtr->refCount--; /* * If the literal is no longer being used by any ByteCode, delete * the entry then remove the reference corresponding to the global * literal table entry (decrement the ref count of the object). */ if (entryPtr->refCount == 0) { if (prevPtr == NULL) { globalTablePtr->buckets[index] = entryPtr->nextPtr; } else { prevPtr->nextPtr = entryPtr->nextPtr; } ckfree(entryPtr); globalTablePtr->numEntries--; TclDecrRefCount(objPtr); #ifdef TCL_COMPILE_STATS iPtr->stats.currentLitStringBytes -= (double) (length + 1); #endif /*TCL_COMPILE_STATS*/ } break; } } /* * Remove the reference corresponding to the local literal table entry. */ done: Tcl_DecrRefCount(objPtr); } /* *---------------------------------------------------------------------- * * HashString -- * * Compute a one-word summary of a text string, which can be used to * generate a hash index. * * Results: * The return value is a one-word summary of the information in string. * * Side effects: * None. * *---------------------------------------------------------------------- */ static unsigned HashString( register const char *string, /* String for which to compute hash value. */ int length) /* Number of bytes in the string. */ { register unsigned int result = 0; /* * I tried a zillion different hash functions and asked many other people * for advice. Many people had their own favorite functions, all * different, but no-one had much idea why they were good ones. I chose * the one below (multiply by 9 and add new character) because of the * following reasons: * * 1. Multiplying by 10 is perfect for keys that are decimal strings, and * multiplying by 9 is just about as good. * 2. Times-9 is (shift-left-3) plus (old). This means that each * character's bits hang around in the low-order bits of the hash value * for ever, plus they spread fairly rapidly up to the high-order bits * to fill out the hash value. This seems works well both for decimal * and non-decimal strings. * * Note that this function is very weak against malicious strings; it's * very easy to generate multiple keys that have the same hashcode. On the * other hand, that hardly ever actually occurs and this function *is* * very cheap, even by comparison with industry-standard hashes like FNV. * If real strength of hash is required though, use a custom hash based on * Bob Jenkins's lookup3(), but be aware that it's significantly slower. * Tcl scripts tend to not have a big issue in this area, and literals * mostly aren't looked up by name anyway. * * See also HashStringKey in tclHash.c. * See also TclObjHashKey in tclObj.c. * * See [tcl-Feature Request #2958832] */ if (length > 0) { result = UCHAR(*string); while (--length) { result += (result << 3) + UCHAR(*++string); } } return result; } /* *---------------------------------------------------------------------- * * RebuildLiteralTable -- * * This function is invoked when the ratio of entries to hash buckets * becomes too large in a local or global literal table. It allocates a * larger bucket array and moves the entries into the new buckets. * * Results: * None. * * Side effects: * Memory gets reallocated and entries get rehashed into new buckets. * *---------------------------------------------------------------------- */ static void RebuildLiteralTable( register LiteralTable *tablePtr) /* Local or global table to enlarge. */ { LiteralEntry **oldBuckets; register LiteralEntry **oldChainPtr, **newChainPtr; register LiteralEntry *entryPtr; LiteralEntry **bucketPtr; const char *bytes; unsigned int oldSize; int count, index, length; oldSize = tablePtr->numBuckets; oldBuckets = tablePtr->buckets; /* * Allocate and initialize the new bucket array, and set up hashing * constants for new array size. */ if (oldSize > UINT_MAX/(4 * sizeof(LiteralEntry *))) { /* * Memory allocator limitations will not let us create the * next larger table size. Best option is to limp along * with what we have. */ return; } tablePtr->numBuckets *= 4; tablePtr->buckets = ckalloc(tablePtr->numBuckets * sizeof(LiteralEntry*)); for (count=tablePtr->numBuckets, newChainPtr=tablePtr->buckets; count>0 ; count--, newChainPtr++) { *newChainPtr = NULL; } tablePtr->rebuildSize *= 4; tablePtr->mask = (tablePtr->mask << 2) + 3; /* * Rehash all of the existing entries into the new bucket array. */ for (oldChainPtr=oldBuckets ; oldSize>0 ; oldSize--,oldChainPtr++) { for (entryPtr=*oldChainPtr ; entryPtr!=NULL ; entryPtr=*oldChainPtr) { bytes = TclGetStringFromObj(entryPtr->objPtr, &length); index = (HashString(bytes, length) & tablePtr->mask); *oldChainPtr = entryPtr->nextPtr; bucketPtr = &tablePtr->buckets[index]; entryPtr->nextPtr = *bucketPtr; *bucketPtr = entryPtr; } } /* * Free up the old bucket array, if it was dynamically allocated. */ if (oldBuckets != tablePtr->staticBuckets) { ckfree(oldBuckets); } } /* *---------------------------------------------------------------------- * * TclInvalidateCmdLiteral -- * * Invalidate a command literal entry, if present in the literal hash * tables, by resetting its internal representation. This invalidation * leaves it in the literal tables and in existing literal arrays. As a * result, existing references continue to work but we force a fresh * command look-up upon the next use (see, in particular, * TclSetCmdNameObj()). * * Results: * None. * * Side effects: * Resets the internal representation of the CmdName Tcl_Obj * using TclFreeIntRep(). * *---------------------------------------------------------------------- */ void TclInvalidateCmdLiteral( Tcl_Interp *interp, /* Interpreter for which to invalidate a * command literal. */ const char *name, /* Points to the start of the cmd literal * name. */ Namespace *nsPtr) /* The namespace for which to lookup and * invalidate a cmd literal. */ { Interp *iPtr = (Interp *) interp; Tcl_Obj *literalObjPtr = TclCreateLiteral(iPtr, (char *) name, strlen(name), -1, NULL, nsPtr, 0, NULL); if (literalObjPtr != NULL) { if (literalObjPtr->typePtr == &tclCmdNameType) { TclFreeIntRep(literalObjPtr); } /* Balance the refcount effects of TclCreateLiteral() above */ Tcl_IncrRefCount(literalObjPtr); TclReleaseLiteral(interp, literalObjPtr); } } #ifdef TCL_COMPILE_STATS /* *---------------------------------------------------------------------- * * TclLiteralStats -- * * Return statistics describing the layout of the hash table in its hash * buckets. * * Results: * The return value is a malloc-ed string containing information about * tablePtr. It is the caller's responsibility to free this string. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * TclLiteralStats( LiteralTable *tablePtr) /* Table for which to produce stats. */ { #define NUM_COUNTERS 10 int count[NUM_COUNTERS], overflow, i, j; double average, tmp; register LiteralEntry *entryPtr; char *result, *p; /* * Compute a histogram of bucket usage. For each bucket chain i, j is the * number of entries in the chain. */ for (i=0 ; inumBuckets ; i++) { j = 0; for (entryPtr=tablePtr->buckets[i] ; entryPtr!=NULL; entryPtr=entryPtr->nextPtr) { j++; } if (j < NUM_COUNTERS) { count[j]++; } else { overflow++; } tmp = j; average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0; } /* * Print out the histogram and a few other pieces of information. */ result = ckalloc(NUM_COUNTERS*60 + 300); sprintf(result, "%d entries in table, %d buckets\n", tablePtr->numEntries, tablePtr->numBuckets); p = result + strlen(result); for (i=0 ; ilocalLitTable; register LiteralEntry *localPtr; char *bytes; register int i; int length, count; count = 0; for (i=0 ; inumBuckets ; i++) { for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL; localPtr=localPtr->nextPtr) { count++; if (localPtr->refCount != -1) { bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length); Tcl_Panic("%s: local literal \"%.*s\" had bad refCount %d", "TclVerifyLocalLiteralTable", (length>60? 60 : length), bytes, localPtr->refCount); } if (LookupLiteralEntry((Tcl_Interp *) envPtr->iPtr, localPtr->objPtr) == NULL) { bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length); Tcl_Panic("%s: local literal \"%.*s\" is not global", "TclVerifyLocalLiteralTable", (length>60? 60 : length), bytes); } if (localPtr->objPtr->bytes == NULL) { Tcl_Panic("%s: literal has NULL string rep", "TclVerifyLocalLiteralTable"); } } } if (count != localTablePtr->numEntries) { Tcl_Panic("%s: local literal table had %d entries, should be %d", "TclVerifyLocalLiteralTable", count, localTablePtr->numEntries); } } /* *---------------------------------------------------------------------- * * TclVerifyGlobalLiteralTable -- * * Check an interpreter's global literal table literal for consistency. * * Results: * None. * * Side effects: * Tcl_Panic if problems are found. * *---------------------------------------------------------------------- */ void TclVerifyGlobalLiteralTable( Interp *iPtr) /* Points to interpreter whose global literal * table is to be validated. */ { register LiteralTable *globalTablePtr = &iPtr->literalTable; register LiteralEntry *globalPtr; char *bytes; register int i; int length, count; count = 0; for (i=0 ; inumBuckets ; i++) { for (globalPtr=globalTablePtr->buckets[i] ; globalPtr!=NULL; globalPtr=globalPtr->nextPtr) { count++; if (globalPtr->refCount < 1) { bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length); Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d", "TclVerifyGlobalLiteralTable", (length>60? 60 : length), bytes, globalPtr->refCount); } if (globalPtr->objPtr->bytes == NULL) { Tcl_Panic("%s: literal has NULL string rep", "TclVerifyGlobalLiteralTable"); } } } if (count != globalTablePtr->numEntries) { Tcl_Panic("%s: global literal table had %d entries, should be %d", "TclVerifyGlobalLiteralTable", count, globalTablePtr->numEntries); } } #endif /*TCL_COMPILE_DEBUG*/ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclBasic.c0000644000175000017500000077161512664052331015104 0ustar sergeisergei/* * tclBasic.c -- * * Contains the basic facilities for TCL command interpretation, * including interpreter creation and deletion, command creation and * deletion, and command/script execution. * * Copyright (c) 1987-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2007 Daniel A. Steffen * Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved. * Copyright (c) 2008 Miguel Sofer * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclOOInt.h" #include "tclCompile.h" #include "tommath.h" #include #include #define INTERP_STACK_INITIAL_SIZE 2000 #define CORO_STACK_INITIAL_SIZE 200 /* * Determine whether we're using IEEE floating point */ #if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024) # define IEEE_FLOATING_POINT /* Largest odd integer that can be represented exactly in a double */ # define MAX_EXACT 9007199254740991.0 #endif /* * The following structure defines the client data for a math function * registered with Tcl_CreateMathFunc */ typedef struct OldMathFuncData { Tcl_MathProc *proc; /* Handler function */ int numArgs; /* Number of args expected */ Tcl_ValueType *argTypes; /* Types of the args */ ClientData clientData; /* Client data for the handler function */ } OldMathFuncData; /* * This is the script cancellation struct and hash table. The hash table is * used to keep track of the information necessary to process script * cancellation requests, including the original interp, asynchronous handler * tokens (created by Tcl_AsyncCreate), and the clientData and flags arguments * passed to Tcl_CancelEval on a per-interp basis. The cancelLock mutex is * used for protecting calls to Tcl_CancelEval as well as protecting access to * the hash table below. */ typedef struct { Tcl_Interp *interp; /* Interp this struct belongs to. */ Tcl_AsyncHandler async; /* Async handler token for script * cancellation. */ char *result; /* The script cancellation result or NULL for * a default result. */ int length; /* Length of the above error message. */ ClientData clientData; /* Ignored */ int flags; /* Additional flags */ } CancelInfo; static Tcl_HashTable cancelTable; static int cancelTableInitialized = 0; /* 0 means not yet initialized. */ TCL_DECLARE_MUTEX(cancelLock) /* * Declarations for managing contexts for non-recursive coroutines. Contexts * are used to save the evaluation state between NR calls to each coro. */ #define SAVE_CONTEXT(context) \ (context).framePtr = iPtr->framePtr; \ (context).varFramePtr = iPtr->varFramePtr; \ (context).cmdFramePtr = iPtr->cmdFramePtr; \ (context).lineLABCPtr = iPtr->lineLABCPtr #define RESTORE_CONTEXT(context) \ iPtr->framePtr = (context).framePtr; \ iPtr->varFramePtr = (context).varFramePtr; \ iPtr->cmdFramePtr = (context).cmdFramePtr; \ iPtr->lineLABCPtr = (context).lineLABCPtr /* * Static functions in this file: */ static char * CallCommandTraces(Interp *iPtr, Command *cmdPtr, const char *oldName, const char *newName, int flags); static int CancelEvalProc(ClientData clientData, Tcl_Interp *interp, int code); static int CheckDoubleResult(Tcl_Interp *interp, double dResult); static void DeleteCoroutine(ClientData clientData); static void DeleteInterpProc(Tcl_Interp *interp); static void DeleteOpCmdClientData(ClientData clientData); #ifdef USE_DTRACE static Tcl_ObjCmdProc DTraceObjCmd; static Tcl_NRPostProc DTraceCmdReturn; #else # define DTraceCmdReturn NULL #endif /* USE_DTRACE */ static Tcl_ObjCmdProc ExprAbsFunc; static Tcl_ObjCmdProc ExprBinaryFunc; static Tcl_ObjCmdProc ExprBoolFunc; static Tcl_ObjCmdProc ExprCeilFunc; static Tcl_ObjCmdProc ExprDoubleFunc; static Tcl_ObjCmdProc ExprEntierFunc; static Tcl_ObjCmdProc ExprFloorFunc; static Tcl_ObjCmdProc ExprIntFunc; static Tcl_ObjCmdProc ExprIsqrtFunc; static Tcl_ObjCmdProc ExprRandFunc; static Tcl_ObjCmdProc ExprRoundFunc; static Tcl_ObjCmdProc ExprSqrtFunc; static Tcl_ObjCmdProc ExprSrandFunc; static Tcl_ObjCmdProc ExprUnaryFunc; static Tcl_ObjCmdProc ExprWideFunc; static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected, int actual, Tcl_Obj *const *objv); static Tcl_NRPostProc NRCoroutineCallerCallback; static Tcl_NRPostProc NRCoroutineExitCallback; static int NRCommand(ClientData data[], Tcl_Interp *interp, int result); static Tcl_ObjCmdProc OldMathFuncProc; static void OldMathFuncDeleteProc(ClientData clientData); static void ProcessUnexpectedResult(Tcl_Interp *interp, int returnCode); static int RewindCoroutine(CoroutineData *corPtr, int result); static void TEOV_SwitchVarFrame(Tcl_Interp *interp); static void TEOV_PushExceptionHandlers(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); static inline Command * TEOV_LookupCmdFromObj(Tcl_Interp *interp, Tcl_Obj *namePtr, Namespace *lookupNsPtr); static int TEOV_NotFound(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], Namespace *lookupNsPtr); static int TEOV_RunEnterTraces(Tcl_Interp *interp, Command **cmdPtrPtr, Tcl_Obj *commandPtr, int objc, Tcl_Obj *const objv[]); static Tcl_NRPostProc RewindCoroutineCallback; static Tcl_NRPostProc TailcallCleanup; static Tcl_NRPostProc TEOEx_ByteCodeCallback; static Tcl_NRPostProc TEOEx_ListCallback; static Tcl_NRPostProc TEOV_Error; static Tcl_NRPostProc TEOV_Exception; static Tcl_NRPostProc TEOV_NotFoundCallback; static Tcl_NRPostProc TEOV_RestoreVarFrame; static Tcl_NRPostProc TEOV_RunLeaveTraces; static Tcl_NRPostProc EvalObjvCore; static Tcl_NRPostProc Dispatch; static Tcl_ObjCmdProc NRCoroInjectObjCmd; static Tcl_NRPostProc NRPostInvoke; MODULE_SCOPE const TclStubs tclStubs; /* * Magical counts for the number of arguments accepted by a coroutine command * after particular kinds of [yield]. */ #define CORO_ACTIVATE_YIELD PTR2INT(NULL) #define CORO_ACTIVATE_YIELDM PTR2INT(NULL)+1 #define COROUTINE_ARGUMENTS_SINGLE_OPTIONAL (-1) #define COROUTINE_ARGUMENTS_ARBITRARY (-2) /* * The following structure define the commands in the Tcl core. */ typedef struct { const char *name; /* Name of object-based command. */ Tcl_ObjCmdProc *objProc; /* Object-based function for command. */ CompileProc *compileProc; /* Function called to compile command. */ Tcl_ObjCmdProc *nreProc; /* NR-based function for command */ int flags; /* Various flag bits, as defined below. */ } CmdInfo; #define CMD_IS_SAFE 1 /* Whether this command is part of the set of * commands present by default in a safe * interpreter. */ /* CMD_COMPILES_EXPANDED - Whether the compiler for this command can handle * expansion for itself rather than needing the generic layer to take care of * it for it. Defined in tclInt.h. */ /* * The built-in commands, and the functions that implement them: */ static const CmdInfo builtInCmds[] = { /* * Commands in the generic core. */ {"append", Tcl_AppendObjCmd, TclCompileAppendCmd, NULL, CMD_IS_SAFE}, {"apply", Tcl_ApplyObjCmd, NULL, TclNRApplyObjCmd, CMD_IS_SAFE}, {"break", Tcl_BreakObjCmd, TclCompileBreakCmd, NULL, CMD_IS_SAFE}, #ifndef EXCLUDE_OBSOLETE_COMMANDS {"case", Tcl_CaseObjCmd, NULL, NULL, CMD_IS_SAFE}, #endif {"catch", Tcl_CatchObjCmd, TclCompileCatchCmd, TclNRCatchObjCmd, CMD_IS_SAFE}, {"concat", Tcl_ConcatObjCmd, TclCompileConcatCmd, NULL, CMD_IS_SAFE}, {"continue", Tcl_ContinueObjCmd, TclCompileContinueCmd, NULL, CMD_IS_SAFE}, {"coroutine", NULL, NULL, TclNRCoroutineObjCmd, CMD_IS_SAFE}, {"error", Tcl_ErrorObjCmd, TclCompileErrorCmd, NULL, CMD_IS_SAFE}, {"eval", Tcl_EvalObjCmd, NULL, TclNREvalObjCmd, CMD_IS_SAFE}, {"expr", Tcl_ExprObjCmd, TclCompileExprCmd, TclNRExprObjCmd, CMD_IS_SAFE}, {"for", Tcl_ForObjCmd, TclCompileForCmd, TclNRForObjCmd, CMD_IS_SAFE}, {"foreach", Tcl_ForeachObjCmd, TclCompileForeachCmd, TclNRForeachCmd, CMD_IS_SAFE}, {"format", Tcl_FormatObjCmd, TclCompileFormatCmd, NULL, CMD_IS_SAFE}, {"global", Tcl_GlobalObjCmd, TclCompileGlobalCmd, NULL, CMD_IS_SAFE}, {"if", Tcl_IfObjCmd, TclCompileIfCmd, TclNRIfObjCmd, CMD_IS_SAFE}, {"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, NULL, CMD_IS_SAFE}, {"join", Tcl_JoinObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE}, {"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, NULL, CMD_IS_SAFE}, {"lindex", Tcl_LindexObjCmd, TclCompileLindexCmd, NULL, CMD_IS_SAFE}, {"linsert", Tcl_LinsertObjCmd, TclCompileLinsertCmd, NULL, CMD_IS_SAFE}, {"list", Tcl_ListObjCmd, TclCompileListCmd, NULL, CMD_IS_SAFE|CMD_COMPILES_EXPANDED}, {"llength", Tcl_LlengthObjCmd, TclCompileLlengthCmd, NULL, CMD_IS_SAFE}, {"lmap", Tcl_LmapObjCmd, TclCompileLmapCmd, TclNRLmapCmd, CMD_IS_SAFE}, {"lrange", Tcl_LrangeObjCmd, TclCompileLrangeCmd, NULL, CMD_IS_SAFE}, {"lrepeat", Tcl_LrepeatObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lreplace", Tcl_LreplaceObjCmd, TclCompileLreplaceCmd, NULL, CMD_IS_SAFE}, {"lreverse", Tcl_LreverseObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lsearch", Tcl_LsearchObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lset", Tcl_LsetObjCmd, TclCompileLsetCmd, NULL, CMD_IS_SAFE}, {"lsort", Tcl_LsortObjCmd, NULL, NULL, CMD_IS_SAFE}, {"package", Tcl_PackageObjCmd, NULL, NULL, CMD_IS_SAFE}, {"proc", Tcl_ProcObjCmd, NULL, NULL, CMD_IS_SAFE}, {"regexp", Tcl_RegexpObjCmd, TclCompileRegexpCmd, NULL, CMD_IS_SAFE}, {"regsub", Tcl_RegsubObjCmd, TclCompileRegsubCmd, NULL, CMD_IS_SAFE}, {"rename", Tcl_RenameObjCmd, NULL, NULL, CMD_IS_SAFE}, {"return", Tcl_ReturnObjCmd, TclCompileReturnCmd, NULL, CMD_IS_SAFE}, {"scan", Tcl_ScanObjCmd, NULL, NULL, CMD_IS_SAFE}, {"set", Tcl_SetObjCmd, TclCompileSetCmd, NULL, CMD_IS_SAFE}, {"split", Tcl_SplitObjCmd, NULL, NULL, CMD_IS_SAFE}, {"subst", Tcl_SubstObjCmd, TclCompileSubstCmd, TclNRSubstObjCmd, CMD_IS_SAFE}, {"switch", Tcl_SwitchObjCmd, TclCompileSwitchCmd, TclNRSwitchObjCmd, CMD_IS_SAFE}, {"tailcall", NULL, TclCompileTailcallCmd, TclNRTailcallObjCmd, CMD_IS_SAFE}, {"throw", Tcl_ThrowObjCmd, TclCompileThrowCmd, NULL, CMD_IS_SAFE}, {"trace", Tcl_TraceObjCmd, NULL, NULL, CMD_IS_SAFE}, {"try", Tcl_TryObjCmd, TclCompileTryCmd, TclNRTryObjCmd, CMD_IS_SAFE}, {"unset", Tcl_UnsetObjCmd, TclCompileUnsetCmd, NULL, CMD_IS_SAFE}, {"uplevel", Tcl_UplevelObjCmd, NULL, TclNRUplevelObjCmd, CMD_IS_SAFE}, {"upvar", Tcl_UpvarObjCmd, TclCompileUpvarCmd, NULL, CMD_IS_SAFE}, {"variable", Tcl_VariableObjCmd, TclCompileVariableCmd, NULL, CMD_IS_SAFE}, {"while", Tcl_WhileObjCmd, TclCompileWhileCmd, TclNRWhileObjCmd, CMD_IS_SAFE}, {"yield", NULL, TclCompileYieldCmd, TclNRYieldObjCmd, CMD_IS_SAFE}, {"yieldto", NULL, TclCompileYieldToCmd, TclNRYieldToObjCmd, CMD_IS_SAFE}, /* * Commands in the OS-interface. Note that many of these are unsafe. */ {"after", Tcl_AfterObjCmd, NULL, NULL, CMD_IS_SAFE}, {"cd", Tcl_CdObjCmd, NULL, NULL, 0}, {"close", Tcl_CloseObjCmd, NULL, NULL, CMD_IS_SAFE}, {"eof", Tcl_EofObjCmd, NULL, NULL, CMD_IS_SAFE}, {"encoding", Tcl_EncodingObjCmd, NULL, NULL, 0}, {"exec", Tcl_ExecObjCmd, NULL, NULL, 0}, {"exit", Tcl_ExitObjCmd, NULL, NULL, 0}, {"fblocked", Tcl_FblockedObjCmd, NULL, NULL, CMD_IS_SAFE}, {"fconfigure", Tcl_FconfigureObjCmd, NULL, NULL, 0}, {"fcopy", Tcl_FcopyObjCmd, NULL, NULL, CMD_IS_SAFE}, {"fileevent", Tcl_FileEventObjCmd, NULL, NULL, CMD_IS_SAFE}, {"flush", Tcl_FlushObjCmd, NULL, NULL, CMD_IS_SAFE}, {"gets", Tcl_GetsObjCmd, NULL, NULL, CMD_IS_SAFE}, {"glob", Tcl_GlobObjCmd, NULL, NULL, 0}, {"load", Tcl_LoadObjCmd, NULL, NULL, 0}, {"open", Tcl_OpenObjCmd, NULL, NULL, 0}, {"pid", Tcl_PidObjCmd, NULL, NULL, CMD_IS_SAFE}, {"puts", Tcl_PutsObjCmd, NULL, NULL, CMD_IS_SAFE}, {"pwd", Tcl_PwdObjCmd, NULL, NULL, 0}, {"read", Tcl_ReadObjCmd, NULL, NULL, CMD_IS_SAFE}, {"seek", Tcl_SeekObjCmd, NULL, NULL, CMD_IS_SAFE}, {"socket", Tcl_SocketObjCmd, NULL, NULL, 0}, {"source", Tcl_SourceObjCmd, NULL, TclNRSourceObjCmd, 0}, {"tell", Tcl_TellObjCmd, NULL, NULL, CMD_IS_SAFE}, {"time", Tcl_TimeObjCmd, NULL, NULL, CMD_IS_SAFE}, {"unload", Tcl_UnloadObjCmd, NULL, NULL, 0}, {"update", Tcl_UpdateObjCmd, NULL, NULL, CMD_IS_SAFE}, {"vwait", Tcl_VwaitObjCmd, NULL, NULL, CMD_IS_SAFE}, {NULL, NULL, NULL, NULL, 0} }; /* * Math functions. All are safe. */ typedef struct { const char *name; /* Name of the function. The full name is * "::tcl::mathfunc::". */ Tcl_ObjCmdProc *objCmdProc; /* Function that evaluates the function */ ClientData clientData; /* Client data for the function */ } BuiltinFuncDef; static const BuiltinFuncDef BuiltinFuncTable[] = { { "abs", ExprAbsFunc, NULL }, { "acos", ExprUnaryFunc, (ClientData) acos }, { "asin", ExprUnaryFunc, (ClientData) asin }, { "atan", ExprUnaryFunc, (ClientData) atan }, { "atan2", ExprBinaryFunc, (ClientData) atan2 }, { "bool", ExprBoolFunc, NULL }, { "ceil", ExprCeilFunc, NULL }, { "cos", ExprUnaryFunc, (ClientData) cos }, { "cosh", ExprUnaryFunc, (ClientData) cosh }, { "double", ExprDoubleFunc, NULL }, { "entier", ExprEntierFunc, NULL }, { "exp", ExprUnaryFunc, (ClientData) exp }, { "floor", ExprFloorFunc, NULL }, { "fmod", ExprBinaryFunc, (ClientData) fmod }, { "hypot", ExprBinaryFunc, (ClientData) hypot }, { "int", ExprIntFunc, NULL }, { "isqrt", ExprIsqrtFunc, NULL }, { "log", ExprUnaryFunc, (ClientData) log }, { "log10", ExprUnaryFunc, (ClientData) log10 }, { "pow", ExprBinaryFunc, (ClientData) pow }, { "rand", ExprRandFunc, NULL }, { "round", ExprRoundFunc, NULL }, { "sin", ExprUnaryFunc, (ClientData) sin }, { "sinh", ExprUnaryFunc, (ClientData) sinh }, { "sqrt", ExprSqrtFunc, NULL }, { "srand", ExprSrandFunc, NULL }, { "tan", ExprUnaryFunc, (ClientData) tan }, { "tanh", ExprUnaryFunc, (ClientData) tanh }, { "wide", ExprWideFunc, NULL }, { NULL, NULL, NULL } }; /* * TIP#174's math operators. All are safe. */ typedef struct { const char *name; /* Name of object-based command. */ Tcl_ObjCmdProc *objProc; /* Object-based function for command. */ CompileProc *compileProc; /* Function called to compile command. */ union { int numArgs; int identity; } i; const char *expected; /* For error message, what argument(s) * were expected. */ } OpCmdInfo; static const OpCmdInfo mathOpCmds[] = { { "~", TclSingleOpCmd, TclCompileInvertOpCmd, /* numArgs */ {1}, "integer"}, { "!", TclSingleOpCmd, TclCompileNotOpCmd, /* numArgs */ {1}, "boolean"}, { "+", TclVariadicOpCmd, TclCompileAddOpCmd, /* identity */ {0}, NULL}, { "*", TclVariadicOpCmd, TclCompileMulOpCmd, /* identity */ {1}, NULL}, { "&", TclVariadicOpCmd, TclCompileAndOpCmd, /* identity */ {-1}, NULL}, { "|", TclVariadicOpCmd, TclCompileOrOpCmd, /* identity */ {0}, NULL}, { "^", TclVariadicOpCmd, TclCompileXorOpCmd, /* identity */ {0}, NULL}, { "**", TclVariadicOpCmd, TclCompilePowOpCmd, /* identity */ {1}, NULL}, { "<<", TclSingleOpCmd, TclCompileLshiftOpCmd, /* numArgs */ {2}, "integer shift"}, { ">>", TclSingleOpCmd, TclCompileRshiftOpCmd, /* numArgs */ {2}, "integer shift"}, { "%", TclSingleOpCmd, TclCompileModOpCmd, /* numArgs */ {2}, "integer integer"}, { "!=", TclSingleOpCmd, TclCompileNeqOpCmd, /* numArgs */ {2}, "value value"}, { "ne", TclSingleOpCmd, TclCompileStrneqOpCmd, /* numArgs */ {2}, "value value"}, { "in", TclSingleOpCmd, TclCompileInOpCmd, /* numArgs */ {2}, "value list"}, { "ni", TclSingleOpCmd, TclCompileNiOpCmd, /* numArgs */ {2}, "value list"}, { "-", TclNoIdentOpCmd, TclCompileMinusOpCmd, /* unused */ {0}, "value ?value ...?"}, { "/", TclNoIdentOpCmd, TclCompileDivOpCmd, /* unused */ {0}, "value ?value ...?"}, { "<", TclSortingOpCmd, TclCompileLessOpCmd, /* unused */ {0}, NULL}, { "<=", TclSortingOpCmd, TclCompileLeqOpCmd, /* unused */ {0}, NULL}, { ">", TclSortingOpCmd, TclCompileGreaterOpCmd, /* unused */ {0}, NULL}, { ">=", TclSortingOpCmd, TclCompileGeqOpCmd, /* unused */ {0}, NULL}, { "==", TclSortingOpCmd, TclCompileEqOpCmd, /* unused */ {0}, NULL}, { "eq", TclSortingOpCmd, TclCompileStreqOpCmd, /* unused */ {0}, NULL}, { NULL, NULL, NULL, {0}, NULL} }; /* *---------------------------------------------------------------------- * * TclFinalizeEvaluation -- * * Finalizes the script cancellation hash table. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclFinalizeEvaluation(void) { Tcl_MutexLock(&cancelLock); if (cancelTableInitialized == 1) { Tcl_DeleteHashTable(&cancelTable); cancelTableInitialized = 0; } Tcl_MutexUnlock(&cancelLock); } /* *---------------------------------------------------------------------- * * Tcl_CreateInterp -- * * Create a new TCL command interpreter. * * Results: * The return value is a token for the interpreter, which may be used in * calls to functions like Tcl_CreateCmd, Tcl_Eval, or Tcl_DeleteInterp. * * Side effects: * The command interpreter is initialized with the built-in commands and * with the variables documented in tclvars(n). * *---------------------------------------------------------------------- */ Tcl_Interp * Tcl_CreateInterp(void) { Interp *iPtr; Tcl_Interp *interp; Command *cmdPtr; const BuiltinFuncDef *builtinFuncPtr; const OpCmdInfo *opcmdInfoPtr; const CmdInfo *cmdInfoPtr; Tcl_Namespace *mathfuncNSPtr, *mathopNSPtr; Tcl_HashEntry *hPtr; int isNew; CancelInfo *cancelInfo; union { char c[sizeof(short)]; short s; } order; #ifdef TCL_COMPILE_STATS ByteCodeStats *statsPtr; #endif /* TCL_COMPILE_STATS */ char mathFuncName[32]; CallFrame *framePtr; TclInitSubsystems(); /* * Panic if someone updated the CallFrame structure without also updating * the Tcl_CallFrame structure (or vice versa). */ if (sizeof(Tcl_CallFrame) < sizeof(CallFrame)) { /*NOTREACHED*/ Tcl_Panic("Tcl_CallFrame must not be smaller than CallFrame"); } #if defined(_WIN32) && !defined(_WIN64) if (sizeof(time_t) != 4) { /*NOTREACHED*/ Tcl_Panic(" is not compatible with MSVC"); } if ((TclOffset(Tcl_StatBuf,st_atime) != 32) || (TclOffset(Tcl_StatBuf,st_ctime) != 40)) { /*NOTREACHED*/ Tcl_Panic(" is not compatible with MSVC"); } #endif if (cancelTableInitialized == 0) { Tcl_MutexLock(&cancelLock); if (cancelTableInitialized == 0) { Tcl_InitHashTable(&cancelTable, TCL_ONE_WORD_KEYS); cancelTableInitialized = 1; } Tcl_MutexUnlock(&cancelLock); } /* * Initialize support for namespaces and create the global namespace * (whose name is ""; an alias is "::"). This also initializes the Tcl * object type table and other object management code. */ iPtr = ckalloc(sizeof(Interp)); interp = (Tcl_Interp *) iPtr; iPtr->result = iPtr->resultSpace; iPtr->freeProc = NULL; iPtr->errorLine = 0; iPtr->objResultPtr = Tcl_NewObj(); Tcl_IncrRefCount(iPtr->objResultPtr); iPtr->handle = TclHandleCreate(iPtr); iPtr->globalNsPtr = NULL; iPtr->hiddenCmdTablePtr = NULL; iPtr->interpInfo = NULL; TCL_CT_ASSERT(sizeof(iPtr->extra) <= sizeof(Tcl_HashTable)); iPtr->extra.optimizer = TclOptimizeBytecode; iPtr->numLevels = 0; iPtr->maxNestingDepth = MAX_NESTING_DEPTH; iPtr->framePtr = NULL; /* Initialise as soon as :: is available */ iPtr->varFramePtr = NULL; /* Initialise as soon as :: is available */ /* * TIP #280 - Initialize the arrays used to extend the ByteCode and Proc * structures. */ iPtr->cmdFramePtr = NULL; iPtr->linePBodyPtr = ckalloc(sizeof(Tcl_HashTable)); iPtr->lineBCPtr = ckalloc(sizeof(Tcl_HashTable)); iPtr->lineLAPtr = ckalloc(sizeof(Tcl_HashTable)); iPtr->lineLABCPtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(iPtr->linePBodyPtr, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(iPtr->lineBCPtr, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(iPtr->lineLAPtr, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(iPtr->lineLABCPtr, TCL_ONE_WORD_KEYS); iPtr->scriptCLLocPtr = NULL; iPtr->activeVarTracePtr = NULL; iPtr->returnOpts = NULL; iPtr->errorInfo = NULL; TclNewLiteralStringObj(iPtr->eiVar, "::errorInfo"); Tcl_IncrRefCount(iPtr->eiVar); iPtr->errorStack = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(iPtr->errorStack); iPtr->resetErrorStack = 1; TclNewLiteralStringObj(iPtr->upLiteral,"UP"); Tcl_IncrRefCount(iPtr->upLiteral); TclNewLiteralStringObj(iPtr->callLiteral,"CALL"); Tcl_IncrRefCount(iPtr->callLiteral); TclNewLiteralStringObj(iPtr->innerLiteral,"INNER"); Tcl_IncrRefCount(iPtr->innerLiteral); iPtr->innerContext = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(iPtr->innerContext); iPtr->errorCode = NULL; TclNewLiteralStringObj(iPtr->ecVar, "::errorCode"); Tcl_IncrRefCount(iPtr->ecVar); iPtr->returnLevel = 1; iPtr->returnCode = TCL_OK; iPtr->rootFramePtr = NULL; /* Initialise as soon as :: is available */ iPtr->lookupNsPtr = NULL; iPtr->appendResult = NULL; iPtr->appendAvl = 0; iPtr->appendUsed = 0; Tcl_InitHashTable(&iPtr->packageTable, TCL_STRING_KEYS); iPtr->packageUnknown = NULL; /* TIP #268 */ if (getenv("TCL_PKG_PREFER_LATEST") == NULL) { iPtr->packagePrefer = PKG_PREFER_STABLE; } else { iPtr->packagePrefer = PKG_PREFER_LATEST; } iPtr->cmdCount = 0; TclInitLiteralTable(&iPtr->literalTable); iPtr->compileEpoch = 0; iPtr->compiledProcPtr = NULL; iPtr->resolverPtr = NULL; iPtr->evalFlags = 0; iPtr->scriptFile = NULL; iPtr->flags = 0; iPtr->tracePtr = NULL; iPtr->tracesForbiddingInline = 0; iPtr->activeCmdTracePtr = NULL; iPtr->activeInterpTracePtr = NULL; iPtr->assocData = NULL; iPtr->execEnvPtr = NULL; /* Set after namespaces initialized. */ iPtr->emptyObjPtr = Tcl_NewObj(); /* Another empty object. */ Tcl_IncrRefCount(iPtr->emptyObjPtr); iPtr->resultSpace[0] = 0; iPtr->threadId = Tcl_GetCurrentThread(); /* TIP #378 */ #ifdef TCL_INTERP_DEBUG_FRAME iPtr->flags |= INTERP_DEBUG_FRAME; #else if (getenv("TCL_INTERP_DEBUG_FRAME") != NULL) { iPtr->flags |= INTERP_DEBUG_FRAME; } #endif /* * Initialise the tables for variable traces and searches *before* * creating the global ns - so that the trace on errorInfo can be * recorded. */ Tcl_InitHashTable(&iPtr->varTraces, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&iPtr->varSearches, TCL_ONE_WORD_KEYS); iPtr->globalNsPtr = NULL; /* Force creation of global ns below. */ iPtr->globalNsPtr = (Namespace *) Tcl_CreateNamespace(interp, "", NULL, NULL); if (iPtr->globalNsPtr == NULL) { Tcl_Panic("Tcl_CreateInterp: can't create global namespace"); } /* * Initialise the rootCallframe. It cannot be allocated on the stack, as * it has to be in place before TclCreateExecEnv tries to use a variable. */ /* This is needed to satisfy GCC 3.3's strict aliasing rules */ framePtr = ckalloc(sizeof(CallFrame)); (void) Tcl_PushCallFrame(interp, (Tcl_CallFrame *) framePtr, (Tcl_Namespace *) iPtr->globalNsPtr, /*isProcCallFrame*/ 0); framePtr->objc = 0; iPtr->framePtr = framePtr; iPtr->varFramePtr = framePtr; iPtr->rootFramePtr = framePtr; /* * Initialize support for code compilation and execution. We call * TclCreateExecEnv after initializing namespaces since it tries to * reference a Tcl variable (it links to the Tcl "tcl_traceExec" * variable). */ iPtr->execEnvPtr = TclCreateExecEnv(interp, INTERP_STACK_INITIAL_SIZE); /* * TIP #219, Tcl Channel Reflection API support. */ iPtr->chanMsg = NULL; /* * TIP #285, Script cancellation support. */ iPtr->asyncCancelMsg = Tcl_NewObj(); cancelInfo = ckalloc(sizeof(CancelInfo)); cancelInfo->interp = interp; iPtr->asyncCancel = Tcl_AsyncCreate(CancelEvalProc, cancelInfo); cancelInfo->async = iPtr->asyncCancel; cancelInfo->result = NULL; cancelInfo->length = 0; Tcl_MutexLock(&cancelLock); hPtr = Tcl_CreateHashEntry(&cancelTable, iPtr, &isNew); Tcl_SetHashValue(hPtr, cancelInfo); Tcl_MutexUnlock(&cancelLock); /* * Initialize the compilation and execution statistics kept for this * interpreter. */ #ifdef TCL_COMPILE_STATS statsPtr = &iPtr->stats; statsPtr->numExecutions = 0; statsPtr->numCompilations = 0; statsPtr->numByteCodesFreed = 0; memset(statsPtr->instructionCount, 0, sizeof(statsPtr->instructionCount)); statsPtr->totalSrcBytes = 0.0; statsPtr->totalByteCodeBytes = 0.0; statsPtr->currentSrcBytes = 0.0; statsPtr->currentByteCodeBytes = 0.0; memset(statsPtr->srcCount, 0, sizeof(statsPtr->srcCount)); memset(statsPtr->byteCodeCount, 0, sizeof(statsPtr->byteCodeCount)); memset(statsPtr->lifetimeCount, 0, sizeof(statsPtr->lifetimeCount)); statsPtr->currentInstBytes = 0.0; statsPtr->currentLitBytes = 0.0; statsPtr->currentExceptBytes = 0.0; statsPtr->currentAuxBytes = 0.0; statsPtr->currentCmdMapBytes = 0.0; statsPtr->numLiteralsCreated = 0; statsPtr->totalLitStringBytes = 0.0; statsPtr->currentLitStringBytes = 0.0; memset(statsPtr->literalCount, 0, sizeof(statsPtr->literalCount)); #endif /* TCL_COMPILE_STATS */ /* * Initialise the stub table pointer. */ iPtr->stubTable = &tclStubs; /* * Initialize the ensemble error message rewriting support. */ iPtr->ensembleRewrite.sourceObjs = NULL; iPtr->ensembleRewrite.numRemovedObjs = 0; iPtr->ensembleRewrite.numInsertedObjs = 0; /* * TIP#143: Initialise the resource limit support. */ TclInitLimitSupport(interp); /* * Initialise the thread-specific data ekeko. Note that the thread's alloc * cache was already initialised by the call to alloc the interp struct. */ #if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) iPtr->allocCache = TclpGetAllocCache(); #else iPtr->allocCache = NULL; #endif iPtr->pendingObjDataPtr = NULL; iPtr->asyncReadyPtr = TclGetAsyncReadyPtr(); iPtr->deferredCallbacks = NULL; /* * Create the core commands. Do it here, rather than calling * Tcl_CreateCommand, because it's faster (there's no need to check for a * pre-existing command by the same name). If a command has a Tcl_CmdProc * but no Tcl_ObjCmdProc, set the Tcl_ObjCmdProc to * TclInvokeStringCommand. This is an object-based wrapper function that * extracts strings, calls the string function, and creates an object for * the result. Similarly, if a command has a Tcl_ObjCmdProc but no * Tcl_CmdProc, set the Tcl_CmdProc to TclInvokeObjectCommand. */ for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) { if ((cmdInfoPtr->objProc == NULL) && (cmdInfoPtr->compileProc == NULL) && (cmdInfoPtr->nreProc == NULL)) { Tcl_Panic("builtin command with NULL object command proc and a NULL compile proc"); } hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable, cmdInfoPtr->name, &isNew); if (isNew) { cmdPtr = ckalloc(sizeof(Command)); cmdPtr->hPtr = hPtr; cmdPtr->nsPtr = iPtr->globalNsPtr; cmdPtr->refCount = 1; cmdPtr->cmdEpoch = 0; cmdPtr->compileProc = cmdInfoPtr->compileProc; cmdPtr->proc = TclInvokeObjectCommand; cmdPtr->clientData = cmdPtr; cmdPtr->objProc = cmdInfoPtr->objProc; cmdPtr->objClientData = NULL; cmdPtr->deleteProc = NULL; cmdPtr->deleteData = NULL; cmdPtr->flags = 0; if (cmdInfoPtr->flags & CMD_COMPILES_EXPANDED) { cmdPtr->flags |= CMD_COMPILES_EXPANDED; } cmdPtr->importRefPtr = NULL; cmdPtr->tracePtr = NULL; cmdPtr->nreProc = cmdInfoPtr->nreProc; Tcl_SetHashValue(hPtr, cmdPtr); } } /* * Create the "array", "binary", "chan", "dict", "file", "info", * "namespace" and "string" ensembles. Note that all these commands (and * their subcommands that are not present in the global namespace) are * wholly safe *except* for "file". */ TclInitArrayCmd(interp); TclInitBinaryCmd(interp); TclInitChanCmd(interp); TclInitDictCmd(interp); TclInitFileCmd(interp); TclInitInfoCmd(interp); TclInitNamespaceCmd(interp); TclInitStringCmd(interp); TclInitPrefixCmd(interp); /* * Register "clock" subcommands. These *do* go through * Tcl_CreateObjCommand, since they aren't in the global namespace and * involve ensembles. */ TclClockInit(interp); /* * Register the built-in functions. This is empty now that they are * implemented as commands in the ::tcl::mathfunc namespace. */ /* * Register the default [interp bgerror] handler. */ Tcl_CreateObjCommand(interp, "::tcl::Bgerror", TclDefaultBgErrorHandlerObjCmd, NULL, NULL); /* * Create unsupported commands for debugging bytecode and objects. */ Tcl_CreateObjCommand(interp, "::tcl::unsupported::disassemble", Tcl_DisassembleObjCmd, INT2PTR(0), NULL); Tcl_CreateObjCommand(interp, "::tcl::unsupported::getbytecode", Tcl_DisassembleObjCmd, INT2PTR(1), NULL); Tcl_CreateObjCommand(interp, "::tcl::unsupported::representation", Tcl_RepresentationCmd, NULL, NULL); /* Adding the bytecode assembler command */ cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "::tcl::unsupported::assemble", Tcl_AssembleObjCmd, TclNRAssembleObjCmd, NULL, NULL); cmdPtr->compileProc = &TclCompileAssembleCmd; Tcl_NRCreateCommand(interp, "::tcl::unsupported::inject", NULL, NRCoroInjectObjCmd, NULL, NULL); #ifdef USE_DTRACE /* * Register the tcl::dtrace command. */ Tcl_CreateObjCommand(interp, "::tcl::dtrace", DTraceObjCmd, NULL, NULL); #endif /* USE_DTRACE */ /* * Register the builtin math functions. */ mathfuncNSPtr = Tcl_CreateNamespace(interp, "::tcl::mathfunc", NULL,NULL); if (mathfuncNSPtr == NULL) { Tcl_Panic("Can't create math function namespace"); } #define MATH_FUNC_PREFIX_LEN 17 /* == strlen("::tcl::mathfunc::") */ memcpy(mathFuncName, "::tcl::mathfunc::", MATH_FUNC_PREFIX_LEN); for (builtinFuncPtr = BuiltinFuncTable; builtinFuncPtr->name != NULL; builtinFuncPtr++) { strcpy(mathFuncName+MATH_FUNC_PREFIX_LEN, builtinFuncPtr->name); Tcl_CreateObjCommand(interp, mathFuncName, builtinFuncPtr->objCmdProc, builtinFuncPtr->clientData, NULL); Tcl_Export(interp, mathfuncNSPtr, builtinFuncPtr->name, 0); } /* * Register the mathematical "operator" commands. [TIP #174] */ mathopNSPtr = Tcl_CreateNamespace(interp, "::tcl::mathop", NULL, NULL); if (mathopNSPtr == NULL) { Tcl_Panic("can't create math operator namespace"); } Tcl_Export(interp, mathopNSPtr, "*", 1); #define MATH_OP_PREFIX_LEN 15 /* == strlen("::tcl::mathop::") */ memcpy(mathFuncName, "::tcl::mathop::", MATH_OP_PREFIX_LEN); for (opcmdInfoPtr=mathOpCmds ; opcmdInfoPtr->name!=NULL ; opcmdInfoPtr++){ TclOpCmdClientData *occdPtr = ckalloc(sizeof(TclOpCmdClientData)); occdPtr->op = opcmdInfoPtr->name; occdPtr->i.numArgs = opcmdInfoPtr->i.numArgs; occdPtr->expected = opcmdInfoPtr->expected; strcpy(mathFuncName + MATH_OP_PREFIX_LEN, opcmdInfoPtr->name); cmdPtr = (Command *) Tcl_CreateObjCommand(interp, mathFuncName, opcmdInfoPtr->objProc, occdPtr, DeleteOpCmdClientData); if (cmdPtr == NULL) { Tcl_Panic("failed to create math operator %s", opcmdInfoPtr->name); } else if (opcmdInfoPtr->compileProc != NULL) { cmdPtr->compileProc = opcmdInfoPtr->compileProc; } } /* * Do Multiple/Safe Interps Tcl init stuff */ TclInterpInit(interp); TclSetupEnv(interp); /* * TIP #59: Make embedded configuration information available. */ TclInitEmbeddedConfigurationInformation(interp); /* * TIP #440: Declare the name of the script engine to be "Tcl". */ Tcl_SetVar2(interp, "tcl_platform", "engine", "Tcl", TCL_GLOBAL_ONLY); /* * Compute the byte order of this machine. */ order.s = 1; Tcl_SetVar2(interp, "tcl_platform", "byteOrder", ((order.c[0] == 1) ? "littleEndian" : "bigEndian"), TCL_GLOBAL_ONLY); Tcl_SetVar2Ex(interp, "tcl_platform", "wordSize", Tcl_NewLongObj((long) sizeof(long)), TCL_GLOBAL_ONLY); /* TIP #291 */ Tcl_SetVar2Ex(interp, "tcl_platform", "pointerSize", Tcl_NewLongObj((long) sizeof(void *)), TCL_GLOBAL_ONLY); /* * Set up other variables such as tcl_version and tcl_library */ Tcl_SetVar(interp, "tcl_patchLevel", TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY); Tcl_SetVar(interp, "tcl_version", TCL_VERSION, TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, "tcl_precision", NULL, TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, TclPrecTraceProc, NULL); TclpSetVariables(interp); #ifdef TCL_THREADS /* * The existence of the "threaded" element of the tcl_platform array * indicates that this particular Tcl shell has been compiled with threads * turned on. Using "info exists tcl_platform(threaded)" a Tcl script can * introspect on the interpreter level of thread safety. */ Tcl_SetVar2(interp, "tcl_platform", "threaded", "1", TCL_GLOBAL_ONLY); #endif /* * Register Tcl's version number. * TIP #268: Full patchlevel instead of just major.minor */ Tcl_PkgProvideEx(interp, "Tcl", TCL_PATCH_LEVEL, &tclStubs); if (TclTommath_Init(interp) != TCL_OK) { Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp))); } if (TclOOInit(interp) != TCL_OK) { Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp))); } /* * Only build in zlib support if we've successfully detected a library to * compile and link against. */ #ifdef HAVE_ZLIB if (TclZlibInit(interp) != TCL_OK) { Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp))); } #endif TOP_CB(iPtr) = NULL; return interp; } static void DeleteOpCmdClientData( ClientData clientData) { TclOpCmdClientData *occdPtr = clientData; ckfree(occdPtr); } /* *---------------------------------------------------------------------- * * TclHideUnsafeCommands -- * * Hides base commands that are not marked as safe from this interpreter. * * Results: * TCL_OK if it succeeds, TCL_ERROR else. * * Side effects: * Hides functionality in an interpreter. * *---------------------------------------------------------------------- */ int TclHideUnsafeCommands( Tcl_Interp *interp) /* Hide commands in this interpreter. */ { register const CmdInfo *cmdInfoPtr; if (interp == NULL) { return TCL_ERROR; } for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) { if (!(cmdInfoPtr->flags & CMD_IS_SAFE)) { Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name); } } TclMakeFileCommandSafe(interp); /* Ugh! */ return TCL_OK; } /* *-------------------------------------------------------------- * * Tcl_CallWhenDeleted -- * * Arrange for a function to be called before a given interpreter is * deleted. The function is called as soon as Tcl_DeleteInterp is called; * if Tcl_CallWhenDeleted is called on an interpreter that has already * been deleted, the function will be called when the last Tcl_Release is * done on the interpreter. * * Results: * None. * * Side effects: * When Tcl_DeleteInterp is invoked to delete interp, proc will be * invoked. See the manual entry for details. * *-------------------------------------------------------------- */ void Tcl_CallWhenDeleted( Tcl_Interp *interp, /* Interpreter to watch. */ Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about * to be deleted. */ ClientData clientData) /* One-word value to pass to proc. */ { Interp *iPtr = (Interp *) interp; static Tcl_ThreadDataKey assocDataCounterKey; int *assocDataCounterPtr = Tcl_GetThreadData(&assocDataCounterKey, (int)sizeof(int)); int isNew; char buffer[32 + TCL_INTEGER_SPACE]; AssocData *dPtr = ckalloc(sizeof(AssocData)); Tcl_HashEntry *hPtr; sprintf(buffer, "Assoc Data Key #%d", *assocDataCounterPtr); (*assocDataCounterPtr)++; if (iPtr->assocData == NULL) { iPtr->assocData = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS); } hPtr = Tcl_CreateHashEntry(iPtr->assocData, buffer, &isNew); dPtr->proc = proc; dPtr->clientData = clientData; Tcl_SetHashValue(hPtr, dPtr); } /* *-------------------------------------------------------------- * * Tcl_DontCallWhenDeleted -- * * Cancel the arrangement for a function to be called when a given * interpreter is deleted. * * Results: * None. * * Side effects: * If proc and clientData were previously registered as a callback via * Tcl_CallWhenDeleted, they are unregistered. If they weren't previously * registered then nothing happens. * *-------------------------------------------------------------- */ void Tcl_DontCallWhenDeleted( Tcl_Interp *interp, /* Interpreter to watch. */ Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about * to be deleted. */ ClientData clientData) /* One-word value to pass to proc. */ { Interp *iPtr = (Interp *) interp; Tcl_HashTable *hTablePtr; Tcl_HashSearch hSearch; Tcl_HashEntry *hPtr; AssocData *dPtr; hTablePtr = iPtr->assocData; if (hTablePtr == NULL) { return; } for (hPtr = Tcl_FirstHashEntry(hTablePtr, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { dPtr = Tcl_GetHashValue(hPtr); if ((dPtr->proc == proc) && (dPtr->clientData == clientData)) { ckfree(dPtr); Tcl_DeleteHashEntry(hPtr); return; } } } /* *---------------------------------------------------------------------- * * Tcl_SetAssocData -- * * Creates a named association between user-specified data, a delete * function and this interpreter. If the association already exists the * data is overwritten with the new data. The delete function will be * invoked when the interpreter is deleted. * * Results: * None. * * Side effects: * Sets the associated data, creates the association if needed. * *---------------------------------------------------------------------- */ void Tcl_SetAssocData( Tcl_Interp *interp, /* Interpreter to associate with. */ const char *name, /* Name for association. */ Tcl_InterpDeleteProc *proc, /* Proc to call when interpreter is about to * be deleted. */ ClientData clientData) /* One-word value to pass to proc. */ { Interp *iPtr = (Interp *) interp; AssocData *dPtr; Tcl_HashEntry *hPtr; int isNew; if (iPtr->assocData == NULL) { iPtr->assocData = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS); } hPtr = Tcl_CreateHashEntry(iPtr->assocData, name, &isNew); if (isNew == 0) { dPtr = Tcl_GetHashValue(hPtr); } else { dPtr = ckalloc(sizeof(AssocData)); } dPtr->proc = proc; dPtr->clientData = clientData; Tcl_SetHashValue(hPtr, dPtr); } /* *---------------------------------------------------------------------- * * Tcl_DeleteAssocData -- * * Deletes a named association of user-specified data with the specified * interpreter. * * Results: * None. * * Side effects: * Deletes the association. * *---------------------------------------------------------------------- */ void Tcl_DeleteAssocData( Tcl_Interp *interp, /* Interpreter to associate with. */ const char *name) /* Name of association. */ { Interp *iPtr = (Interp *) interp; AssocData *dPtr; Tcl_HashEntry *hPtr; if (iPtr->assocData == NULL) { return; } hPtr = Tcl_FindHashEntry(iPtr->assocData, name); if (hPtr == NULL) { return; } dPtr = Tcl_GetHashValue(hPtr); if (dPtr->proc != NULL) { dPtr->proc(dPtr->clientData, interp); } ckfree(dPtr); Tcl_DeleteHashEntry(hPtr); } /* *---------------------------------------------------------------------- * * Tcl_GetAssocData -- * * Returns the client data associated with this name in the specified * interpreter. * * Results: * The client data in the AssocData record denoted by the named * association, or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ ClientData Tcl_GetAssocData( Tcl_Interp *interp, /* Interpreter associated with. */ const char *name, /* Name of association. */ Tcl_InterpDeleteProc **procPtr) /* Pointer to place to store address of * current deletion callback. */ { Interp *iPtr = (Interp *) interp; AssocData *dPtr; Tcl_HashEntry *hPtr; if (iPtr->assocData == NULL) { return NULL; } hPtr = Tcl_FindHashEntry(iPtr->assocData, name); if (hPtr == NULL) { return NULL; } dPtr = Tcl_GetHashValue(hPtr); if (procPtr != NULL) { *procPtr = dPtr->proc; } return dPtr->clientData; } /* *---------------------------------------------------------------------- * * Tcl_InterpDeleted -- * * Returns nonzero if the interpreter has been deleted with a call to * Tcl_DeleteInterp. * * Results: * Nonzero if the interpreter is deleted, zero otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_InterpDeleted( Tcl_Interp *interp) { return (((Interp *) interp)->flags & DELETED) ? 1 : 0; } /* *---------------------------------------------------------------------- * * Tcl_DeleteInterp -- * * Ensures that the interpreter will be deleted eventually. If there are * no Tcl_Preserve calls in effect for this interpreter, it is deleted * immediately, otherwise the interpreter is deleted when the last * Tcl_Preserve is matched by a call to Tcl_Release. In either case, the * function runs the currently registered deletion callbacks. * * Results: * None. * * Side effects: * The interpreter is marked as deleted. The caller may still use it * safely if there are calls to Tcl_Preserve in effect for the * interpreter, but further calls to Tcl_Eval etc in this interpreter * will fail. * *---------------------------------------------------------------------- */ void Tcl_DeleteInterp( Tcl_Interp *interp) /* Token for command interpreter (returned by * a previous call to Tcl_CreateInterp). */ { Interp *iPtr = (Interp *) interp; /* * If the interpreter has already been marked deleted, just punt. */ if (iPtr->flags & DELETED) { return; } /* * Mark the interpreter as deleted. No further evals will be allowed. * Increase the compileEpoch as a signal to compiled bytecodes. */ iPtr->flags |= DELETED; iPtr->compileEpoch++; /* * Ensure that the interpreter is eventually deleted. */ Tcl_EventuallyFree(interp, (Tcl_FreeProc *) DeleteInterpProc); } /* *---------------------------------------------------------------------- * * DeleteInterpProc -- * * Helper function to delete an interpreter. This function is called when * the last call to Tcl_Preserve on this interpreter is matched by a call * to Tcl_Release. The function cleans up all resources used in the * interpreter and calls all currently registered interpreter deletion * callbacks. * * Results: * None. * * Side effects: * Whatever the interpreter deletion callbacks do. Frees resources used * by the interpreter. * *---------------------------------------------------------------------- */ static void DeleteInterpProc( Tcl_Interp *interp) /* Interpreter to delete. */ { Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_HashTable *hTablePtr; ResolverScheme *resPtr, *nextResPtr; int i; /* * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup, * unless we are exiting. */ if ((iPtr->numLevels > 0) && !TclInExit()) { Tcl_Panic("DeleteInterpProc called with active evals"); } /* * The interpreter should already be marked deleted; otherwise how did we * get here? */ if (!(iPtr->flags & DELETED)) { Tcl_Panic("DeleteInterpProc called on interpreter not marked deleted"); } /* * TIP #219, Tcl Channel Reflection API. Discard a leftover state. */ if (iPtr->chanMsg != NULL) { Tcl_DecrRefCount(iPtr->chanMsg); iPtr->chanMsg = NULL; } /* * TIP #285, Script cancellation support. Delete this interp from the * global hash table of CancelInfo structs. */ Tcl_MutexLock(&cancelLock); hPtr = Tcl_FindHashEntry(&cancelTable, (char *) iPtr); if (hPtr != NULL) { CancelInfo *cancelInfo = Tcl_GetHashValue(hPtr); if (cancelInfo != NULL) { if (cancelInfo->result != NULL) { ckfree(cancelInfo->result); } ckfree(cancelInfo); } Tcl_DeleteHashEntry(hPtr); } if (iPtr->asyncCancel != NULL) { Tcl_AsyncDelete(iPtr->asyncCancel); iPtr->asyncCancel = NULL; } if (iPtr->asyncCancelMsg != NULL) { Tcl_DecrRefCount(iPtr->asyncCancelMsg); iPtr->asyncCancelMsg = NULL; } Tcl_MutexUnlock(&cancelLock); /* * Shut down all limit handler callback scripts that call back into this * interpreter. Then eliminate all limit handlers for this interpreter. */ TclRemoveScriptLimitCallbacks(interp); TclLimitRemoveAllHandlers(interp); /* * Dismantle the namespace here, before we clear the assocData. If any * background errors occur here, they will be deleted below. * * Dismantle the namespace after freeing the iPtr->handle so that each * bytecode releases its literals without caring to update the literal * table, as it will be freed later in this function without further use. */ TclHandleFree(iPtr->handle); TclTeardownNamespace(iPtr->globalNsPtr); /* * Delete all the hidden commands. */ hTablePtr = iPtr->hiddenCmdTablePtr; if (hTablePtr != NULL) { /* * Non-pernicious deletion. The deletion callbacks will not be allowed * to create any new hidden or non-hidden commands. * Tcl_DeleteCommandFromToken will remove the entry from the * hiddenCmdTablePtr. */ hPtr = Tcl_FirstHashEntry(hTablePtr, &search); for (; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Tcl_DeleteCommandFromToken(interp, Tcl_GetHashValue(hPtr)); } Tcl_DeleteHashTable(hTablePtr); ckfree(hTablePtr); } /* * Invoke deletion callbacks; note that a callback can create new * callbacks, so we iterate. */ while (iPtr->assocData != NULL) { AssocData *dPtr; hTablePtr = iPtr->assocData; iPtr->assocData = NULL; for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search); hPtr != NULL; hPtr = Tcl_FirstHashEntry(hTablePtr, &search)) { dPtr = Tcl_GetHashValue(hPtr); Tcl_DeleteHashEntry(hPtr); if (dPtr->proc != NULL) { dPtr->proc(dPtr->clientData, interp); } ckfree(dPtr); } Tcl_DeleteHashTable(hTablePtr); ckfree(hTablePtr); } /* * Pop the root frame pointer and finish deleting the global * namespace. The order is important [Bug 1658572]. */ if ((iPtr->framePtr != iPtr->rootFramePtr) && !TclInExit()) { Tcl_Panic("DeleteInterpProc: popping rootCallFrame with other frames on top"); } Tcl_PopCallFrame(interp); ckfree(iPtr->rootFramePtr); iPtr->rootFramePtr = NULL; Tcl_DeleteNamespace((Tcl_Namespace *) iPtr->globalNsPtr); /* * Free up the result *after* deleting variables, since variable deletion * could have transferred ownership of the result string to Tcl. */ Tcl_FreeResult(interp); iPtr->result = NULL; Tcl_DecrRefCount(iPtr->objResultPtr); iPtr->objResultPtr = NULL; Tcl_DecrRefCount(iPtr->ecVar); if (iPtr->errorCode) { Tcl_DecrRefCount(iPtr->errorCode); iPtr->errorCode = NULL; } Tcl_DecrRefCount(iPtr->eiVar); if (iPtr->errorInfo) { Tcl_DecrRefCount(iPtr->errorInfo); iPtr->errorInfo = NULL; } Tcl_DecrRefCount(iPtr->errorStack); iPtr->errorStack = NULL; Tcl_DecrRefCount(iPtr->upLiteral); Tcl_DecrRefCount(iPtr->callLiteral); Tcl_DecrRefCount(iPtr->innerLiteral); Tcl_DecrRefCount(iPtr->innerContext); if (iPtr->returnOpts) { Tcl_DecrRefCount(iPtr->returnOpts); } if (iPtr->appendResult != NULL) { ckfree(iPtr->appendResult); iPtr->appendResult = NULL; } TclFreePackageInfo(iPtr); while (iPtr->tracePtr != NULL) { Tcl_DeleteTrace((Tcl_Interp *) iPtr, (Tcl_Trace) iPtr->tracePtr); } if (iPtr->execEnvPtr != NULL) { TclDeleteExecEnv(iPtr->execEnvPtr); } if (iPtr->scriptFile) { Tcl_DecrRefCount(iPtr->scriptFile); iPtr->scriptFile = NULL; } Tcl_DecrRefCount(iPtr->emptyObjPtr); iPtr->emptyObjPtr = NULL; resPtr = iPtr->resolverPtr; while (resPtr) { nextResPtr = resPtr->nextPtr; ckfree(resPtr->name); ckfree(resPtr); resPtr = nextResPtr; } /* * Free up literal objects created for scripts compiled by the * interpreter. */ TclDeleteLiteralTable(interp, &iPtr->literalTable); /* * TIP #280 - Release the arrays for ByteCode/Proc extension, and * contents. */ for (hPtr = Tcl_FirstHashEntry(iPtr->linePBodyPtr, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { CmdFrame *cfPtr = Tcl_GetHashValue(hPtr); Proc *procPtr = (Proc *) Tcl_GetHashKey(iPtr->linePBodyPtr, hPtr); procPtr->iPtr = NULL; if (cfPtr) { if (cfPtr->type == TCL_LOCATION_SOURCE) { Tcl_DecrRefCount(cfPtr->data.eval.path); } ckfree(cfPtr->line); ckfree(cfPtr); } Tcl_DeleteHashEntry(hPtr); } Tcl_DeleteHashTable(iPtr->linePBodyPtr); ckfree(iPtr->linePBodyPtr); iPtr->linePBodyPtr = NULL; /* * See also tclCompile.c, TclCleanupByteCode */ for (hPtr = Tcl_FirstHashEntry(iPtr->lineBCPtr, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { ExtCmdLoc *eclPtr = Tcl_GetHashValue(hPtr); if (eclPtr->type == TCL_LOCATION_SOURCE) { Tcl_DecrRefCount(eclPtr->path); } for (i=0; i< eclPtr->nuloc; i++) { ckfree(eclPtr->loc[i].line); } if (eclPtr->loc != NULL) { ckfree(eclPtr->loc); } ckfree(eclPtr); Tcl_DeleteHashEntry(hPtr); } Tcl_DeleteHashTable(iPtr->lineBCPtr); ckfree(iPtr->lineBCPtr); iPtr->lineBCPtr = NULL; /* * Location stack for uplevel/eval/... scripts which were passed through * proc arguments. Actually we track all arguments as we do not and cannot * know which arguments will be used as scripts and which will not. */ if (iPtr->lineLAPtr->numEntries && !TclInExit()) { /* * When the interp goes away we have nothing on the stack, so there * are no arguments, so this table has to be empty. */ Tcl_Panic("Argument location tracking table not empty"); } Tcl_DeleteHashTable(iPtr->lineLAPtr); ckfree((char *) iPtr->lineLAPtr); iPtr->lineLAPtr = NULL; if (iPtr->lineLABCPtr->numEntries && !TclInExit()) { /* * When the interp goes away we have nothing on the stack, so there * are no arguments, so this table has to be empty. */ Tcl_Panic("Argument location tracking table not empty"); } Tcl_DeleteHashTable(iPtr->lineLABCPtr); ckfree(iPtr->lineLABCPtr); iPtr->lineLABCPtr = NULL; /* * Squelch the tables of traces on variables and searches over arrays in * the in the interpreter. */ Tcl_DeleteHashTable(&iPtr->varTraces); Tcl_DeleteHashTable(&iPtr->varSearches); ckfree(iPtr); } /* *--------------------------------------------------------------------------- * * Tcl_HideCommand -- * * Makes a command hidden so that it cannot be invoked from within an * interpreter, only from within an ancestor. * * Results: * A standard Tcl result; also leaves a message in the interp's result if * an error occurs. * * Side effects: * Removes a command from the command table and create an entry into the * hidden command table under the specified token name. * *--------------------------------------------------------------------------- */ int Tcl_HideCommand( Tcl_Interp *interp, /* Interpreter in which to hide command. */ const char *cmdName, /* Name of command to hide. */ const char *hiddenCmdToken) /* Token name of the to-be-hidden command. */ { Interp *iPtr = (Interp *) interp; Tcl_Command cmd; Command *cmdPtr; Tcl_HashTable *hiddenCmdTablePtr; Tcl_HashEntry *hPtr; int isNew; if (iPtr->flags & DELETED) { /* * The interpreter is being deleted. Do not create any new structures, * because it is not safe to modify the interpreter. */ return TCL_ERROR; } /* * Disallow hiding of commands that are currently in a namespace or * renaming (as part of hiding) into a namespace (because the current * implementation with a single global table and the needed uniqueness of * names cause problems with namespaces). * * We don't need to check for "::" in cmdName because the real check is on * the nsPtr below. * * hiddenCmdToken is just a string which is not interpreted in any way. It * may contain :: but the string is not interpreted as a namespace * qualifier command name. Thus, hiding foo::bar to foo::bar and then * trying to expose or invoke ::foo::bar will NOT work; but if the * application always uses the same strings it will get consistent * behaviour. * * But as we currently limit ourselves to the global namespace only for * the source, in order to avoid potential confusion, lets prevent "::" in * the token too. - dl */ if (strstr(hiddenCmdToken, "::") != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot use namespace qualifiers in hidden command" " token (rename)", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "HIDDENTOKEN", NULL); return TCL_ERROR; } /* * Find the command to hide. An error is returned if cmdName can't be * found. Look up the command only from the global namespace. Full path of * the command must be given if using namespaces. */ cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY); if (cmd == (Tcl_Command) NULL) { return TCL_ERROR; } cmdPtr = (Command *) cmd; /* * Check that the command is really in global namespace */ if (cmdPtr->nsPtr != iPtr->globalNsPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can only hide global namespace commands (use rename then hide)", -1)); Tcl_SetErrorCode(interp, "TCL", "HIDE", "NON_GLOBAL", NULL); return TCL_ERROR; } /* * Initialize the hidden command table if necessary. */ hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr; if (hiddenCmdTablePtr == NULL) { hiddenCmdTablePtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(hiddenCmdTablePtr, TCL_STRING_KEYS); iPtr->hiddenCmdTablePtr = hiddenCmdTablePtr; } /* * It is an error to move an exposed command to a hidden command with * hiddenCmdToken if a hidden command with the name hiddenCmdToken already * exists. */ hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &isNew); if (!isNew) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "hidden command named \"%s\" already exists", hiddenCmdToken)); Tcl_SetErrorCode(interp, "TCL", "HIDE", "ALREADY_HIDDEN", NULL); return TCL_ERROR; } /* * NB: This code is currently 'like' a rename to a specialy set apart name * table. Changes here and in TclRenameCommand must be kept in synch until * the common parts are actually factorized out. */ /* * Remove the hash entry for the command from the interpreter command * table. This is like deleting the command, so bump its command epoch; * this invalidates any cached references that point to the command. */ if (cmdPtr->hPtr != NULL) { Tcl_DeleteHashEntry(cmdPtr->hPtr); cmdPtr->hPtr = NULL; cmdPtr->cmdEpoch++; } /* * The list of command exported from the namespace might have changed. * However, we do not need to recompute this just yet; next time we need * the info will be soon enough. */ TclInvalidateNsCmdLookup(cmdPtr->nsPtr); /* * Now link the hash table entry with the command structure. We ensured * above that the nsPtr was right. */ cmdPtr->hPtr = hPtr; Tcl_SetHashValue(hPtr, cmdPtr); /* * If the command being hidden has a compile function, increment the * interpreter's compileEpoch to invalidate its compiled code. This makes * sure that we don't later try to execute old code compiled with * command-specific (i.e., inline) bytecodes for the now-hidden command. * This field is checked in Tcl_EvalObj and ObjInterpProc, and code whose * compilation epoch doesn't match is recompiled. */ if (cmdPtr->compileProc != NULL) { iPtr->compileEpoch++; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ExposeCommand -- * * Makes a previously hidden command callable from inside the interpreter * instead of only by its ancestors. * * Results: * A standard Tcl result. If an error occurs, a message is left in the * interp's result. * * Side effects: * Moves commands from one hash table to another. * *---------------------------------------------------------------------- */ int Tcl_ExposeCommand( Tcl_Interp *interp, /* Interpreter in which to make command * callable. */ const char *hiddenCmdToken, /* Name of hidden command. */ const char *cmdName) /* Name of to-be-exposed command. */ { Interp *iPtr = (Interp *) interp; Command *cmdPtr; Namespace *nsPtr; Tcl_HashEntry *hPtr; Tcl_HashTable *hiddenCmdTablePtr; int isNew; if (iPtr->flags & DELETED) { /* * The interpreter is being deleted. Do not create any new structures, * because it is not safe to modify the interpreter. */ return TCL_ERROR; } /* * Check that we have a regular name for the command (that the user is not * trying to do an expose and a rename (to another namespace) at the same * time). */ if (strstr(cmdName, "::") != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot expose to a namespace (use expose to toplevel, then rename)", -1)); Tcl_SetErrorCode(interp, "TCL", "EXPOSE", "NON_GLOBAL", NULL); return TCL_ERROR; } /* * Get the command from the hidden command table: */ hPtr = NULL; hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr; if (hiddenCmdTablePtr != NULL) { hPtr = Tcl_FindHashEntry(hiddenCmdTablePtr, hiddenCmdToken); } if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown hidden command \"%s\"", hiddenCmdToken)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "HIDDENTOKEN", hiddenCmdToken, NULL); return TCL_ERROR; } cmdPtr = Tcl_GetHashValue(hPtr); /* * Check that we have a true global namespace command (enforced by * Tcl_HideCommand but let's double check. (If it was not, we would not * really know how to handle it). */ if (cmdPtr->nsPtr != iPtr->globalNsPtr) { /* * This case is theoritically impossible, we might rather Tcl_Panic * than 'nicely' erroring out ? */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "trying to expose a non-global command namespace command", -1)); return TCL_ERROR; } /* * This is the global table. */ nsPtr = cmdPtr->nsPtr; /* * It is an error to overwrite an existing exposed command as a result of * exposing a previously hidden command. */ hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &isNew); if (!isNew) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "exposed command \"%s\" already exists", cmdName)); Tcl_SetErrorCode(interp, "TCL", "EXPOSE", "COMMAND_EXISTS", NULL); return TCL_ERROR; } /* * Command resolvers (per-interp, per-namespace) might have resolved to a * command for the given namespace scope with this command not being * registered with the namespace's command table. During BC compilation, * the so-resolved command turns into a CmdName literal. Without * invalidating a possible CmdName literal here explicitly, such literals * keep being reused while pointing to overhauled commands. */ TclInvalidateCmdLiteral(interp, cmdName, nsPtr); /* * The list of command exported from the namespace might have changed. * However, we do not need to recompute this just yet; next time we need * the info will be soon enough. */ TclInvalidateNsCmdLookup(nsPtr); /* * Remove the hash entry for the command from the interpreter hidden * command table. */ if (cmdPtr->hPtr != NULL) { Tcl_DeleteHashEntry(cmdPtr->hPtr); cmdPtr->hPtr = NULL; } /* * Now link the hash table entry with the command structure. This is like * creating a new command, so deal with any shadowing of commands in the * global namespace. */ cmdPtr->hPtr = hPtr; Tcl_SetHashValue(hPtr, cmdPtr); /* * Not needed as we are only in the global namespace (but would be needed * again if we supported namespace command hiding) * * TclResetShadowedCmdRefs(interp, cmdPtr); */ /* * If the command being exposed has a compile function, increment * interpreter's compileEpoch to invalidate its compiled code. This makes * sure that we don't later try to execute old code compiled assuming the * command is hidden. This field is checked in Tcl_EvalObj and * ObjInterpProc, and code whose compilation epoch doesn't match is * recompiled. */ if (cmdPtr->compileProc != NULL) { iPtr->compileEpoch++; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_CreateCommand -- * * Define a new command in a command table. * * Results: * The return value is a token for the command, which can be used in * future calls to Tcl_GetCommandName. * * Side effects: * If a command named cmdName already exists for interp, it is deleted. * In the future, when cmdName is seen as the name of a command by * Tcl_Eval, proc will be called. To support the bytecode interpreter, * the command is created with a wrapper Tcl_ObjCmdProc * (TclInvokeStringCommand) that eventially calls proc. When the command * is deleted from the table, deleteProc will be called. See the manual * entry for details on the calling sequence. * *---------------------------------------------------------------------- */ Tcl_Command Tcl_CreateCommand( Tcl_Interp *interp, /* Token for command interpreter returned by a * previous call to Tcl_CreateInterp. */ const char *cmdName, /* Name of command. If it contains namespace * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_CmdProc *proc, /* Function to associate with cmdName. */ ClientData clientData, /* Arbitrary value passed to string proc. */ Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ { Interp *iPtr = (Interp *) interp; ImportRef *oldRefPtr = NULL; Namespace *nsPtr, *dummy1, *dummy2; Command *cmdPtr, *refCmdPtr; Tcl_HashEntry *hPtr; const char *tail; int isNew; ImportedCmdData *dataPtr; if (iPtr->flags & DELETED) { /* * The interpreter is being deleted. Don't create any new commands; * it's not safe to muck with the interpreter anymore. */ return (Tcl_Command) NULL; } /* * Determine where the command should reside. If its name contains * namespace qualifiers, we put it in the specified namespace; otherwise, * we always put it in the global namespace. */ if (strstr(cmdName, "::") != NULL) { TclGetNamespaceForQualName(interp, cmdName, NULL, TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail); if ((nsPtr == NULL) || (tail == NULL)) { return (Tcl_Command) NULL; } } else { nsPtr = iPtr->globalNsPtr; tail = cmdName; } hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew); if (!isNew) { /* * Command already exists. Delete the old one. Be careful to preserve * any existing import links so we can restore them down below. That * way, you can redefine a command and its import status will remain * intact. */ cmdPtr = Tcl_GetHashValue(hPtr); cmdPtr->refCount++; if (cmdPtr->importRefPtr) { cmdPtr->flags |= CMD_REDEF_IN_PROGRESS; } Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr); if (cmdPtr->flags & CMD_REDEF_IN_PROGRESS) { oldRefPtr = cmdPtr->importRefPtr; cmdPtr->importRefPtr = NULL; } TclCleanupCommandMacro(cmdPtr); hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew); if (!isNew) { /* * If the deletion callback recreated the command, just throw away * the new command (if we try to delete it again, we could get * stuck in an infinite loop). */ ckfree(Tcl_GetHashValue(hPtr)); } } else { /* * Command resolvers (per-interp, per-namespace) might have resolved * to a command for the given namespace scope with this command not * being registered with the namespace's command table. During BC * compilation, the so-resolved command turns into a CmdName literal. * Without invalidating a possible CmdName literal here explicitly, * such literals keep being reused while pointing to overhauled * commands. */ TclInvalidateCmdLiteral(interp, tail, nsPtr); /* * The list of command exported from the namespace might have changed. * However, we do not need to recompute this just yet; next time we * need the info will be soon enough. */ TclInvalidateNsCmdLookup(nsPtr); TclInvalidateNsPath(nsPtr); } cmdPtr = ckalloc(sizeof(Command)); Tcl_SetHashValue(hPtr, cmdPtr); cmdPtr->hPtr = hPtr; cmdPtr->nsPtr = nsPtr; cmdPtr->refCount = 1; cmdPtr->cmdEpoch = 0; cmdPtr->compileProc = NULL; cmdPtr->objProc = TclInvokeStringCommand; cmdPtr->objClientData = cmdPtr; cmdPtr->proc = proc; cmdPtr->clientData = clientData; cmdPtr->deleteProc = deleteProc; cmdPtr->deleteData = clientData; cmdPtr->flags = 0; cmdPtr->importRefPtr = NULL; cmdPtr->tracePtr = NULL; cmdPtr->nreProc = NULL; /* * Plug in any existing import references found above. Be sure to update * all of these references to point to the new command. */ if (oldRefPtr != NULL) { cmdPtr->importRefPtr = oldRefPtr; while (oldRefPtr != NULL) { refCmdPtr = oldRefPtr->importedCmdPtr; dataPtr = refCmdPtr->objClientData; dataPtr->realCmdPtr = cmdPtr; oldRefPtr = oldRefPtr->nextPtr; } } /* * We just created a command, so in its namespace and all of its parent * namespaces, it may shadow global commands with the same name. If any * shadowed commands are found, invalidate all cached command references * in the affected namespaces. */ TclResetShadowedCmdRefs(interp, cmdPtr); return (Tcl_Command) cmdPtr; } /* *---------------------------------------------------------------------- * * Tcl_CreateObjCommand -- * * Define a new object-based command in a command table. * * Results: * The return value is a token for the command, which can be used in * future calls to Tcl_GetCommandName. * * Side effects: * If a command named "cmdName" already exists for interp, it is * first deleted. Then the new command is created from the arguments. * [***] (See below for exception). * * In the future, during bytecode evaluation when "cmdName" is seen as * the name of a command by Tcl_EvalObj or Tcl_Eval, the object-based * Tcl_ObjCmdProc proc will be called. When the command is deleted from * the table, deleteProc will be called. See the manual entry for details * on the calling sequence. * *---------------------------------------------------------------------- */ Tcl_Command Tcl_CreateObjCommand( Tcl_Interp *interp, /* Token for command interpreter (returned by * previous call to Tcl_CreateInterp). */ const char *cmdName, /* Name of command. If it contains namespace * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_ObjCmdProc *proc, /* Object-based function to associate with * name. */ ClientData clientData, /* Arbitrary value to pass to object * function. */ Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ { Interp *iPtr = (Interp *) interp; ImportRef *oldRefPtr = NULL; Namespace *nsPtr, *dummy1, *dummy2; Command *cmdPtr, *refCmdPtr; Tcl_HashEntry *hPtr; const char *tail; int isNew; ImportedCmdData *dataPtr; if (iPtr->flags & DELETED) { /* * The interpreter is being deleted. Don't create any new commands; * it's not safe to muck with the interpreter anymore. */ return (Tcl_Command) NULL; } /* * Determine where the command should reside. If its name contains * namespace qualifiers, we put it in the specified namespace; otherwise, * we always put it in the global namespace. */ if (strstr(cmdName, "::") != NULL) { TclGetNamespaceForQualName(interp, cmdName, NULL, TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail); if ((nsPtr == NULL) || (tail == NULL)) { return (Tcl_Command) NULL; } } else { nsPtr = iPtr->globalNsPtr; tail = cmdName; } hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew); TclInvalidateNsPath(nsPtr); if (!isNew) { cmdPtr = Tcl_GetHashValue(hPtr); /* Command already exists. */ /* * [***] This is wrong. See Tcl Bug a16752c252. * However, this buggy behavior is kept under particular * circumstances to accommodate deployed binaries of the * "tclcompiler" program. http://sourceforge.net/projects/tclpro/ * that crash if the bug is fixed. */ if (cmdPtr->objProc == TclInvokeStringCommand && cmdPtr->clientData == clientData && cmdPtr->deleteData == clientData && cmdPtr->deleteProc == deleteProc) { cmdPtr->objProc = proc; cmdPtr->objClientData = clientData; return (Tcl_Command) cmdPtr; } /* * Otherwise, we delete the old command. Be careful to preserve any * existing import links so we can restore them down below. That way, * you can redefine a command and its import status will remain * intact. */ cmdPtr->refCount++; if (cmdPtr->importRefPtr) { cmdPtr->flags |= CMD_REDEF_IN_PROGRESS; } Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr); if (cmdPtr->flags & CMD_REDEF_IN_PROGRESS) { oldRefPtr = cmdPtr->importRefPtr; cmdPtr->importRefPtr = NULL; } TclCleanupCommandMacro(cmdPtr); hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew); if (!isNew) { /* * If the deletion callback recreated the command, just throw away * the new command (if we try to delete it again, we could get * stuck in an infinite loop). */ ckfree(Tcl_GetHashValue(hPtr)); } } else { /* * Command resolvers (per-interp, per-namespace) might have resolved * to a command for the given namespace scope with this command not * being registered with the namespace's command table. During BC * compilation, the so-resolved command turns into a CmdName literal. * Without invalidating a possible CmdName literal here explicitly, * such literals keep being reused while pointing to overhauled * commands. */ TclInvalidateCmdLiteral(interp, tail, nsPtr); /* * The list of command exported from the namespace might have changed. * However, we do not need to recompute this just yet; next time we * need the info will be soon enough. */ TclInvalidateNsCmdLookup(nsPtr); } cmdPtr = ckalloc(sizeof(Command)); Tcl_SetHashValue(hPtr, cmdPtr); cmdPtr->hPtr = hPtr; cmdPtr->nsPtr = nsPtr; cmdPtr->refCount = 1; cmdPtr->cmdEpoch = 0; cmdPtr->compileProc = NULL; cmdPtr->objProc = proc; cmdPtr->objClientData = clientData; cmdPtr->proc = TclInvokeObjectCommand; cmdPtr->clientData = cmdPtr; cmdPtr->deleteProc = deleteProc; cmdPtr->deleteData = clientData; cmdPtr->flags = 0; cmdPtr->importRefPtr = NULL; cmdPtr->tracePtr = NULL; cmdPtr->nreProc = NULL; /* * Plug in any existing import references found above. Be sure to update * all of these references to point to the new command. */ if (oldRefPtr != NULL) { cmdPtr->importRefPtr = oldRefPtr; while (oldRefPtr != NULL) { refCmdPtr = oldRefPtr->importedCmdPtr; dataPtr = refCmdPtr->objClientData; dataPtr->realCmdPtr = cmdPtr; oldRefPtr = oldRefPtr->nextPtr; } } /* * We just created a command, so in its namespace and all of its parent * namespaces, it may shadow global commands with the same name. If any * shadowed commands are found, invalidate all cached command references * in the affected namespaces. */ TclResetShadowedCmdRefs(interp, cmdPtr); return (Tcl_Command) cmdPtr; } /* *---------------------------------------------------------------------- * * TclInvokeStringCommand -- * * "Wrapper" Tcl_ObjCmdProc used to call an existing string-based * Tcl_CmdProc if no object-based function exists for a command. A * pointer to this function is stored as the Tcl_ObjCmdProc in a Command * structure. It simply turns around and calls the string Tcl_CmdProc in * the Command structure. * * Results: * A standard Tcl object result value. * * Side effects: * Besides those side effects of the called Tcl_CmdProc, * TclInvokeStringCommand allocates and frees storage. * *---------------------------------------------------------------------- */ int TclInvokeStringCommand( ClientData clientData, /* Points to command's Command structure. */ Tcl_Interp *interp, /* Current interpreter. */ register int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Command *cmdPtr = clientData; int i, result; const char **argv = TclStackAlloc(interp, (unsigned)(objc + 1) * sizeof(char *)); for (i = 0; i < objc; i++) { argv[i] = Tcl_GetString(objv[i]); } argv[objc] = 0; /* * Invoke the command's string-based Tcl_CmdProc. */ result = cmdPtr->proc(cmdPtr->clientData, interp, objc, argv); TclStackFree(interp, (void *) argv); return result; } /* *---------------------------------------------------------------------- * * TclInvokeObjectCommand -- * * "Wrapper" Tcl_CmdProc used to call an existing object-based * Tcl_ObjCmdProc if no string-based function exists for a command. A * pointer to this function is stored as the Tcl_CmdProc in a Command * structure. It simply turns around and calls the object Tcl_ObjCmdProc * in the Command structure. * * Results: * A standard Tcl string result value. * * Side effects: * Besides those side effects of the called Tcl_ObjCmdProc, * TclInvokeObjectCommand allocates and frees storage. * *---------------------------------------------------------------------- */ int TclInvokeObjectCommand( ClientData clientData, /* Points to command's Command structure. */ Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ register const char **argv) /* Argument strings. */ { Command *cmdPtr = clientData; Tcl_Obj *objPtr; int i, length, result; Tcl_Obj **objv = TclStackAlloc(interp, (unsigned)(argc * sizeof(Tcl_Obj *))); for (i = 0; i < argc; i++) { length = strlen(argv[i]); TclNewStringObj(objPtr, argv[i], length); Tcl_IncrRefCount(objPtr); objv[i] = objPtr; } /* * Invoke the command's object-based Tcl_ObjCmdProc. */ if (cmdPtr->objProc != NULL) { result = cmdPtr->objProc(cmdPtr->objClientData, interp, argc, objv); } else { result = Tcl_NRCallObjProc(interp, cmdPtr->nreProc, cmdPtr->objClientData, argc, objv); } /* * Move the interpreter's object result to the string result, then reset * the object result. */ (void) Tcl_GetStringResult(interp); /* * Decrement the ref counts for the argument objects created above, then * free the objv array if malloc'ed storage was used. */ for (i = 0; i < argc; i++) { objPtr = objv[i]; Tcl_DecrRefCount(objPtr); } TclStackFree(interp, objv); return result; } /* *---------------------------------------------------------------------- * * TclRenameCommand -- * * Called to give an existing Tcl command a different name. Both the old * command name and the new command name can have "::" namespace * qualifiers. If the new command has a different namespace context, the * command will be moved to that namespace and will execute in the * context of that new namespace. * * If the new command name is NULL or the null string, the command is * deleted. * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * If anything goes wrong, an error message is returned in the * interpreter's result object. * *---------------------------------------------------------------------- */ int TclRenameCommand( Tcl_Interp *interp, /* Current interpreter. */ const char *oldName, /* Existing command name. */ const char *newName) /* New command name. */ { Interp *iPtr = (Interp *) interp; const char *newTail; Namespace *cmdNsPtr, *newNsPtr, *dummy1, *dummy2; Tcl_Command cmd; Command *cmdPtr; Tcl_HashEntry *hPtr, *oldHPtr; int isNew, result; Tcl_Obj *oldFullName; Tcl_DString newFullName; /* * Find the existing command. An error is returned if cmdName can't be * found. */ cmd = Tcl_FindCommand(interp, oldName, NULL, /*flags*/ 0); cmdPtr = (Command *) cmd; if (cmdPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't %s \"%s\": command doesn't exist", ((newName == NULL)||(*newName == '\0'))? "delete":"rename", oldName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", oldName, NULL); return TCL_ERROR; } cmdNsPtr = cmdPtr->nsPtr; oldFullName = Tcl_NewObj(); Tcl_IncrRefCount(oldFullName); Tcl_GetCommandFullName(interp, cmd, oldFullName); /* * If the new command name is NULL or empty, delete the command. Do this * with Tcl_DeleteCommandFromToken, since we already have the command. */ if ((newName == NULL) || (*newName == '\0')) { Tcl_DeleteCommandFromToken(interp, cmd); result = TCL_OK; goto done; } /* * Make sure that the destination command does not already exist. The * rename operation is like creating a command, so we should automatically * create the containing namespaces just like Tcl_CreateCommand would. */ TclGetNamespaceForQualName(interp, newName, NULL, TCL_CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail); if ((newNsPtr == NULL) || (newTail == NULL)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't rename to \"%s\": bad command name", newName)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL); result = TCL_ERROR; goto done; } if (Tcl_FindHashEntry(&newNsPtr->cmdTable, newTail) != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't rename to \"%s\": command already exists", newName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "RENAME", "TARGET_EXISTS", NULL); result = TCL_ERROR; goto done; } /* * Warning: any changes done in the code here are likely to be needed in * Tcl_HideCommand code too (until the common parts are extracted out). * - dl */ /* * Put the command in the new namespace so we can check for an alias loop. * Since we are adding a new command to a namespace, we must handle any * shadowing of the global commands that this might create. */ oldHPtr = cmdPtr->hPtr; hPtr = Tcl_CreateHashEntry(&newNsPtr->cmdTable, newTail, &isNew); Tcl_SetHashValue(hPtr, cmdPtr); cmdPtr->hPtr = hPtr; cmdPtr->nsPtr = newNsPtr; TclResetShadowedCmdRefs(interp, cmdPtr); /* * Now check for an alias loop. If we detect one, put everything back the * way it was and report the error. */ result = TclPreventAliasLoop(interp, interp, (Tcl_Command) cmdPtr); if (result != TCL_OK) { Tcl_DeleteHashEntry(cmdPtr->hPtr); cmdPtr->hPtr = oldHPtr; cmdPtr->nsPtr = cmdNsPtr; goto done; } /* * The list of command exported from the namespace might have changed. * However, we do not need to recompute this just yet; next time we need * the info will be soon enough. These might refer to the same variable, * but that's no big deal. */ TclInvalidateNsCmdLookup(cmdNsPtr); TclInvalidateNsCmdLookup(cmdPtr->nsPtr); /* * Command resolvers (per-interp, per-namespace) might have resolved to a * command for the given namespace scope with this command not being * registered with the namespace's command table. During BC compilation, * the so-resolved command turns into a CmdName literal. Without * invalidating a possible CmdName literal here explicitly, such literals * keep being reused while pointing to overhauled commands. */ TclInvalidateCmdLiteral(interp, newTail, cmdPtr->nsPtr); /* * Script for rename traces can delete the command "oldName". Therefore * increment the reference count for cmdPtr so that it's Command structure * is freed only towards the end of this function by calling * TclCleanupCommand. * * The trace function needs to get a fully qualified name for old and new * commands [Tcl bug #651271], or else there's no way for the trace * function to get the namespace from which the old command is being * renamed! */ Tcl_DStringInit(&newFullName); Tcl_DStringAppend(&newFullName, newNsPtr->fullName, -1); if (newNsPtr != iPtr->globalNsPtr) { TclDStringAppendLiteral(&newFullName, "::"); } Tcl_DStringAppend(&newFullName, newTail, -1); cmdPtr->refCount++; CallCommandTraces(iPtr, cmdPtr, Tcl_GetString(oldFullName), Tcl_DStringValue(&newFullName), TCL_TRACE_RENAME); Tcl_DStringFree(&newFullName); /* * The new command name is okay, so remove the command from its current * namespace. This is like deleting the command, so bump the cmdEpoch to * invalidate any cached references to the command. */ Tcl_DeleteHashEntry(oldHPtr); cmdPtr->cmdEpoch++; /* * If the command being renamed has a compile function, increment the * interpreter's compileEpoch to invalidate its compiled code. This makes * sure that we don't later try to execute old code compiled for the * now-renamed command. */ if (cmdPtr->compileProc != NULL) { iPtr->compileEpoch++; } /* * Now free the Command structure, if the "oldName" command has been * deleted by invocation of rename traces. */ TclCleanupCommandMacro(cmdPtr); result = TCL_OK; done: TclDecrRefCount(oldFullName); return result; } /* *---------------------------------------------------------------------- * * Tcl_SetCommandInfo -- * * Modifies various information about a Tcl command. Note that this * function will not change a command's namespace; use TclRenameCommand * to do that. Also, the isNativeObjectProc member of *infoPtr is * ignored. * * Results: * If cmdName exists in interp, then the information at *infoPtr is * stored with the command in place of the current information and 1 is * returned. If the command doesn't exist then 0 is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_SetCommandInfo( Tcl_Interp *interp, /* Interpreter in which to look for * command. */ const char *cmdName, /* Name of desired command. */ const Tcl_CmdInfo *infoPtr) /* Where to find information to store in the * command. */ { Tcl_Command cmd; cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0); return Tcl_SetCommandInfoFromToken(cmd, infoPtr); } /* *---------------------------------------------------------------------- * * Tcl_SetCommandInfoFromToken -- * * Modifies various information about a Tcl command. Note that this * function will not change a command's namespace; use TclRenameCommand * to do that. Also, the isNativeObjectProc member of *infoPtr is * ignored. * * Results: * If cmdName exists in interp, then the information at *infoPtr is * stored with the command in place of the current information and 1 is * returned. If the command doesn't exist then 0 is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_SetCommandInfoFromToken( Tcl_Command cmd, const Tcl_CmdInfo *infoPtr) { Command *cmdPtr; /* Internal representation of the command */ if (cmd == NULL) { return 0; } /* * The isNativeObjectProc and nsPtr members of *infoPtr are ignored. */ cmdPtr = (Command *) cmd; cmdPtr->proc = infoPtr->proc; cmdPtr->clientData = infoPtr->clientData; if (infoPtr->objProc == NULL) { cmdPtr->objProc = TclInvokeStringCommand; cmdPtr->objClientData = cmdPtr; cmdPtr->nreProc = NULL; } else { if (infoPtr->objProc != cmdPtr->objProc) { cmdPtr->nreProc = NULL; cmdPtr->objProc = infoPtr->objProc; } cmdPtr->objClientData = infoPtr->objClientData; } cmdPtr->deleteProc = infoPtr->deleteProc; cmdPtr->deleteData = infoPtr->deleteData; return 1; } /* *---------------------------------------------------------------------- * * Tcl_GetCommandInfo -- * * Returns various information about a Tcl command. * * Results: * If cmdName exists in interp, then *infoPtr is modified to hold * information about cmdName and 1 is returned. If the command doesn't * exist then 0 is returned and *infoPtr isn't modified. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetCommandInfo( Tcl_Interp *interp, /* Interpreter in which to look for * command. */ const char *cmdName, /* Name of desired command. */ Tcl_CmdInfo *infoPtr) /* Where to store information about * command. */ { Tcl_Command cmd; cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0); return Tcl_GetCommandInfoFromToken(cmd, infoPtr); } /* *---------------------------------------------------------------------- * * Tcl_GetCommandInfoFromToken -- * * Returns various information about a Tcl command. * * Results: * Copies information from the command identified by 'cmd' into a * caller-supplied structure and returns 1. If the 'cmd' is NULL, leaves * the structure untouched and returns 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetCommandInfoFromToken( Tcl_Command cmd, Tcl_CmdInfo *infoPtr) { Command *cmdPtr; /* Internal representation of the command */ if (cmd == NULL) { return 0; } /* * Set isNativeObjectProc 1 if objProc was registered by a call to * Tcl_CreateObjCommand. Otherwise set it to 0. */ cmdPtr = (Command *) cmd; infoPtr->isNativeObjectProc = (cmdPtr->objProc != TclInvokeStringCommand); infoPtr->objProc = cmdPtr->objProc; infoPtr->objClientData = cmdPtr->objClientData; infoPtr->proc = cmdPtr->proc; infoPtr->clientData = cmdPtr->clientData; infoPtr->deleteProc = cmdPtr->deleteProc; infoPtr->deleteData = cmdPtr->deleteData; infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr; return 1; } /* *---------------------------------------------------------------------- * * Tcl_GetCommandName -- * * Given a token returned by Tcl_CreateCommand, this function returns the * current name of the command (which may have changed due to renaming). * * Results: * The return value is the name of the given command. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * Tcl_GetCommandName( Tcl_Interp *interp, /* Interpreter containing the command. */ Tcl_Command command) /* Token for command returned by a previous * call to Tcl_CreateCommand. The command must * not have been deleted. */ { Command *cmdPtr = (Command *) command; if ((cmdPtr == NULL) || (cmdPtr->hPtr == NULL)) { /* * This should only happen if command was "created" after the * interpreter began to be deleted, so there isn't really any command. * Just return an empty string. */ return ""; } return Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr); } /* *---------------------------------------------------------------------- * * Tcl_GetCommandFullName -- * * Given a token returned by, e.g., Tcl_CreateCommand or Tcl_FindCommand, * this function appends to an object the command's full name, qualified * by a sequence of parent namespace names. The command's fully-qualified * name may have changed due to renaming. * * Results: * None. * * Side effects: * The command's fully-qualified name is appended to the string * representation of objPtr. * *---------------------------------------------------------------------- */ void Tcl_GetCommandFullName( Tcl_Interp *interp, /* Interpreter containing the command. */ Tcl_Command command, /* Token for command returned by a previous * call to Tcl_CreateCommand. The command must * not have been deleted. */ Tcl_Obj *objPtr) /* Points to the object onto which the * command's full name is appended. */ { Interp *iPtr = (Interp *) interp; register Command *cmdPtr = (Command *) command; char *name; /* * Add the full name of the containing namespace, followed by the "::" * separator, and the command name. */ if (cmdPtr != NULL) { if (cmdPtr->nsPtr != NULL) { Tcl_AppendToObj(objPtr, cmdPtr->nsPtr->fullName, -1); if (cmdPtr->nsPtr != iPtr->globalNsPtr) { Tcl_AppendToObj(objPtr, "::", 2); } } if (cmdPtr->hPtr != NULL) { name = Tcl_GetHashKey(cmdPtr->hPtr->tablePtr, cmdPtr->hPtr); Tcl_AppendToObj(objPtr, name, -1); } } } /* *---------------------------------------------------------------------- * * Tcl_DeleteCommand -- * * Remove the given command from the given interpreter. * * Results: * 0 is returned if the command was deleted successfully. -1 is returned * if there didn't exist a command by that name. * * Side effects: * cmdName will no longer be recognized as a valid command for interp. * *---------------------------------------------------------------------- */ int Tcl_DeleteCommand( Tcl_Interp *interp, /* Token for command interpreter (returned by * a previous Tcl_CreateInterp call). */ const char *cmdName) /* Name of command to remove. */ { Tcl_Command cmd; /* * Find the desired command and delete it. */ cmd = Tcl_FindCommand(interp, cmdName, NULL, /*flags*/ 0); if (cmd == NULL) { return -1; } return Tcl_DeleteCommandFromToken(interp, cmd); } /* *---------------------------------------------------------------------- * * Tcl_DeleteCommandFromToken -- * * Removes the given command from the given interpreter. This function * resembles Tcl_DeleteCommand, but takes a Tcl_Command token instead of * a command name for efficiency. * * Results: * 0 is returned if the command was deleted successfully. -1 is returned * if there didn't exist a command by that name. * * Side effects: * The command specified by "cmd" will no longer be recognized as a valid * command for "interp". * *---------------------------------------------------------------------- */ int Tcl_DeleteCommandFromToken( Tcl_Interp *interp, /* Token for command interpreter returned by a * previous call to Tcl_CreateInterp. */ Tcl_Command cmd) /* Token for command to delete. */ { Interp *iPtr = (Interp *) interp; Command *cmdPtr = (Command *) cmd; ImportRef *refPtr, *nextRefPtr; Tcl_Command importCmd; /* * Bump the command epoch counter. This will invalidate all cached * references that point to this command. */ cmdPtr->cmdEpoch++; /* * The code here is tricky. We can't delete the hash table entry before * invoking the deletion callback because there are cases where the * deletion callback needs to invoke the command (e.g. object systems such * as OTcl). However, this means that the callback could try to delete or * rename the command. The deleted flag allows us to detect these cases * and skip nested deletes. */ if (cmdPtr->flags & CMD_IS_DELETED) { /* * Another deletion is already in progress. Remove the hash table * entry now, but don't invoke a callback or free the command * structure. Take care to only remove the hash entry if it has not * already been removed; otherwise if we manage to hit this function * three times, everything goes up in smoke. [Bug 1220058] */ if (cmdPtr->hPtr != NULL) { Tcl_DeleteHashEntry(cmdPtr->hPtr); cmdPtr->hPtr = NULL; } return 0; } /* * We must delete this command, even though both traces and delete procs * may try to avoid this (renaming the command etc). Also traces and * delete procs may try to delete the command themsevles. This flag * declares that a delete is in progress and that recursive deletes should * be ignored. */ cmdPtr->flags |= CMD_IS_DELETED; /* * Call trace functions for the command being deleted. Then delete its * traces. */ if (cmdPtr->tracePtr != NULL) { CommandTrace *tracePtr; CallCommandTraces(iPtr,cmdPtr,NULL,NULL,TCL_TRACE_DELETE); /* * Now delete these traces. */ tracePtr = cmdPtr->tracePtr; while (tracePtr != NULL) { CommandTrace *nextPtr = tracePtr->nextPtr; if (tracePtr->refCount-- <= 1) { ckfree(tracePtr); } tracePtr = nextPtr; } cmdPtr->tracePtr = NULL; } /* * The list of command exported from the namespace might have changed. * However, we do not need to recompute this just yet; next time we need * the info will be soon enough. */ TclInvalidateNsCmdLookup(cmdPtr->nsPtr); /* * If the command being deleted has a compile function, increment the * interpreter's compileEpoch to invalidate its compiled code. This makes * sure that we don't later try to execute old code compiled with * command-specific (i.e., inline) bytecodes for the now-deleted command. * This field is checked in Tcl_EvalObj and ObjInterpProc, and code whose * compilation epoch doesn't match is recompiled. */ if (cmdPtr->compileProc != NULL) { iPtr->compileEpoch++; } if (cmdPtr->deleteProc != NULL) { /* * Delete the command's client data. If this was an imported command * created when a command was imported into a namespace, this client * data will be a pointer to a ImportedCmdData structure describing * the "real" command that this imported command refers to. * * If you are getting a crash during the call to deleteProc and * cmdPtr->deleteProc is a pointer to the function free(), the most * likely cause is that your extension allocated memory for the * clientData argument to Tcl_CreateObjCommand with the ckalloc() * macro and you are now trying to deallocate this memory with free() * instead of ckfree(). You should pass a pointer to your own method * that calls ckfree(). */ cmdPtr->deleteProc(cmdPtr->deleteData); } /* * If this command was imported into other namespaces, then imported * commands were created that refer back to this command. Delete these * imported commands now. */ if (!(cmdPtr->flags & CMD_REDEF_IN_PROGRESS)) { for (refPtr = cmdPtr->importRefPtr; refPtr != NULL; refPtr = nextRefPtr) { nextRefPtr = refPtr->nextPtr; importCmd = (Tcl_Command) refPtr->importedCmdPtr; Tcl_DeleteCommandFromToken(interp, importCmd); } } /* * Don't use hPtr to delete the hash entry here, because it's possible * that the deletion callback renamed the command. Instead, use * cmdPtr->hptr, and make sure that no-one else has already deleted the * hash entry. */ if (cmdPtr->hPtr != NULL) { Tcl_DeleteHashEntry(cmdPtr->hPtr); cmdPtr->hPtr = NULL; } /* * A number of tests for particular kinds of commands are done by checking * whether the objProc field holds a known value. Set the field to NULL so * that such tests won't have false positives when applied to deleted * commands. */ cmdPtr->objProc = NULL; /* * Now free the Command structure, unless there is another reference to it * from a CmdName Tcl object in some ByteCode code sequence. In that case, * delay the cleanup until all references are either discarded (when a * ByteCode is freed) or replaced by a new reference (when a cached * CmdName Command reference is found to be invalid and * TclNRExecuteByteCode looks up the command in the command hashtable). */ TclCleanupCommandMacro(cmdPtr); return 0; } /* *---------------------------------------------------------------------- * * CallCommandTraces -- * * Abstraction of the code to call traces on a command. * * Results: * Currently always NULL. * * Side effects: * Anything; this may recursively evaluate scripts and code exists to do * just that. * *---------------------------------------------------------------------- */ static char * CallCommandTraces( Interp *iPtr, /* Interpreter containing command. */ Command *cmdPtr, /* Command whose traces are to be invoked. */ const char *oldName, /* Command's old name, or NULL if we must get * the name from cmdPtr */ const char *newName, /* Command's new name, or NULL if the command * is not being renamed */ int flags) /* Flags indicating the type of traces to * trigger, either TCL_TRACE_DELETE or * TCL_TRACE_RENAME. */ { register CommandTrace *tracePtr; ActiveCommandTrace active; char *result; Tcl_Obj *oldNamePtr = NULL; Tcl_InterpState state = NULL; if (cmdPtr->flags & CMD_TRACE_ACTIVE) { /* * While a rename trace is active, we will not process any more rename * traces; while a delete trace is active we will never reach here - * because Tcl_DeleteCommandFromToken checks for the condition * (cmdPtr->flags & CMD_IS_DELETED) and returns immediately when a * command deletion is in progress. For all other traces, delete * traces will not be invoked but a call to TraceCommandProc will * ensure that tracePtr->clientData is freed whenever the command * "oldName" is deleted. */ if (cmdPtr->flags & TCL_TRACE_RENAME) { flags &= ~TCL_TRACE_RENAME; } if (flags == 0) { return NULL; } } cmdPtr->flags |= CMD_TRACE_ACTIVE; cmdPtr->refCount++; result = NULL; active.nextPtr = iPtr->activeCmdTracePtr; active.reverseScan = 0; iPtr->activeCmdTracePtr = &active; if (flags & TCL_TRACE_DELETE) { flags |= TCL_TRACE_DESTROYED; } active.cmdPtr = cmdPtr; Tcl_Preserve(iPtr); for (tracePtr = cmdPtr->tracePtr; tracePtr != NULL; tracePtr = active.nextTracePtr) { active.nextTracePtr = tracePtr->nextPtr; if (!(tracePtr->flags & flags)) { continue; } cmdPtr->flags |= tracePtr->flags; if (oldName == NULL) { TclNewObj(oldNamePtr); Tcl_IncrRefCount(oldNamePtr); Tcl_GetCommandFullName((Tcl_Interp *) iPtr, (Tcl_Command) cmdPtr, oldNamePtr); oldName = TclGetString(oldNamePtr); } tracePtr->refCount++; if (state == NULL) { state = Tcl_SaveInterpState((Tcl_Interp *) iPtr, TCL_OK); } tracePtr->traceProc(tracePtr->clientData, (Tcl_Interp *) iPtr, oldName, newName, flags); cmdPtr->flags &= ~tracePtr->flags; if (tracePtr->refCount-- <= 1) { ckfree(tracePtr); } } if (state) { Tcl_RestoreInterpState((Tcl_Interp *) iPtr, state); } /* * If a new object was created to hold the full oldName, free it now. */ if (oldNamePtr != NULL) { TclDecrRefCount(oldNamePtr); } /* * Restore the variable's flags, remove the record of our active traces, * and then return. */ cmdPtr->flags &= ~CMD_TRACE_ACTIVE; cmdPtr->refCount--; iPtr->activeCmdTracePtr = active.nextPtr; Tcl_Release(iPtr); return result; } /* *---------------------------------------------------------------------- * * CancelEvalProc -- * * Marks this interpreter as being canceled. This causes current * executions to be unwound as the interpreter enters a state where it * refuses to execute more commands or handle [catch] or [try], yet the * interpreter is still able to execute further commands after the * cancelation is cleared (unlike if it is deleted). * * Results: * The value given for the code argument. * * Side effects: * Transfers a message from the cancelation message to the interpreter. * *---------------------------------------------------------------------- */ static int CancelEvalProc( ClientData clientData, /* Interp to cancel the script in progress. */ Tcl_Interp *interp, /* Ignored */ int code) /* Current return code from command. */ { CancelInfo *cancelInfo = clientData; Interp *iPtr; if (cancelInfo != NULL) { Tcl_MutexLock(&cancelLock); iPtr = (Interp *) cancelInfo->interp; if (iPtr != NULL) { /* * Setting the CANCELED flag will cause the script in progress to * be canceled as soon as possible. The core honors this flag at * all the necessary places to ensure script cancellation is * responsive. Extensions can check for this flag by calling * Tcl_Canceled and checking if TCL_ERROR is returned or they can * choose to ignore the script cancellation flag and the * associated functionality altogether. Currently, the only other * flag we care about here is the TCL_CANCEL_UNWIND flag (from * Tcl_CancelEval). We do not want to simply combine all the flags * from original Tcl_CancelEval call with the interp flags here * just in case the caller passed flags that might cause behaviour * unrelated to script cancellation. */ TclSetCancelFlags(iPtr, cancelInfo->flags | CANCELED); /* * Now, we must set the script cancellation flags on all the slave * interpreters belonging to this one. */ TclSetSlaveCancelFlags((Tcl_Interp *) iPtr, cancelInfo->flags | CANCELED, 0); /* * Create the result object now so that Tcl_Canceled can avoid * locking the cancelLock mutex. */ if (cancelInfo->result != NULL) { Tcl_SetStringObj(iPtr->asyncCancelMsg, cancelInfo->result, cancelInfo->length); } else { Tcl_SetObjLength(iPtr->asyncCancelMsg, 0); } } Tcl_MutexUnlock(&cancelLock); } return code; } /* *---------------------------------------------------------------------- * * TclCleanupCommand -- * * This function frees up a Command structure unless it is still * referenced from an interpreter's command hashtable or from a CmdName * Tcl object representing the name of a command in a ByteCode * instruction sequence. * * Results: * None. * * Side effects: * Memory gets freed unless a reference to the Command structure still * exists. In that case the cleanup is delayed until the command is * deleted or when the last ByteCode referring to it is freed. * *---------------------------------------------------------------------- */ void TclCleanupCommand( register Command *cmdPtr) /* Points to the Command structure to * be freed. */ { cmdPtr->refCount--; if (cmdPtr->refCount <= 0) { ckfree(cmdPtr); } } /* *---------------------------------------------------------------------- * * Tcl_CreateMathFunc -- * * Creates a new math function for expressions in a given interpreter. * * Results: * None. * * Side effects: * The Tcl function defined by "name" is created or redefined. If the * function already exists then its definition is replaced; this includes * the builtin functions. Redefining a builtin function forces all * existing code to be invalidated since that code may be compiled using * an instruction specific to the replaced function. In addition, * redefioning a non-builtin function will force existing code to be * invalidated if the number of arguments has changed. * *---------------------------------------------------------------------- */ void Tcl_CreateMathFunc( Tcl_Interp *interp, /* Interpreter in which function is to be * available. */ const char *name, /* Name of function (e.g. "sin"). */ int numArgs, /* Nnumber of arguments required by * function. */ Tcl_ValueType *argTypes, /* Array of types acceptable for each * argument. */ Tcl_MathProc *proc, /* C function that implements the math * function. */ ClientData clientData) /* Additional value to pass to the * function. */ { Tcl_DString bigName; OldMathFuncData *data = ckalloc(sizeof(OldMathFuncData)); data->proc = proc; data->numArgs = numArgs; data->argTypes = ckalloc(numArgs * sizeof(Tcl_ValueType)); memcpy(data->argTypes, argTypes, numArgs * sizeof(Tcl_ValueType)); data->clientData = clientData; Tcl_DStringInit(&bigName); TclDStringAppendLiteral(&bigName, "::tcl::mathfunc::"); Tcl_DStringAppend(&bigName, name, -1); Tcl_CreateObjCommand(interp, Tcl_DStringValue(&bigName), OldMathFuncProc, data, OldMathFuncDeleteProc); Tcl_DStringFree(&bigName); } /* *---------------------------------------------------------------------- * * OldMathFuncProc -- * * Dispatch to a math function created with Tcl_CreateMathFunc * * Results: * Returns a standard Tcl result. * * Side effects: * Whatever the math function does. * *---------------------------------------------------------------------- */ static int OldMathFuncProc( ClientData clientData, /* Ponter to OldMathFuncData describing the * function being called */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ { Tcl_Obj *valuePtr; OldMathFuncData *dataPtr = clientData; Tcl_Value funcResult, *args; int result; int j, k; double d; /* * Check argument count. */ if (objc != dataPtr->numArgs + 1) { MathFuncWrongNumArgs(interp, dataPtr->numArgs+1, objc, objv); return TCL_ERROR; } /* * Convert arguments from Tcl_Obj's to Tcl_Value's. */ args = ckalloc(dataPtr->numArgs * sizeof(Tcl_Value)); for (j = 1, k = 0; j < objc; ++j, ++k) { /* TODO: Convert to TclGetNumberFromObj? */ valuePtr = objv[j]; result = Tcl_GetDoubleFromObj(NULL, valuePtr, &d); #ifdef ACCEPT_NAN if ((result != TCL_OK) && (valuePtr->typePtr == &tclDoubleType)) { d = valuePtr->internalRep.doubleValue; result = TCL_OK; } #endif if (result != TCL_OK) { /* * We have a non-numeric argument. */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "argument to math function didn't have numeric value", -1)); TclCheckBadOctal(interp, Tcl_GetString(valuePtr)); ckfree(args); return TCL_ERROR; } /* * Copy the object's numeric value to the argument record, converting * it if necessary. * * NOTE: no bignum support; use the new mathfunc interface for that. */ args[k].type = dataPtr->argTypes[k]; switch (args[k].type) { case TCL_EITHER: if (Tcl_GetLongFromObj(NULL, valuePtr, &args[k].intValue) == TCL_OK) { args[k].type = TCL_INT; break; } if (Tcl_GetWideIntFromObj(interp, valuePtr, &args[k].wideValue) == TCL_OK) { args[k].type = TCL_WIDE_INT; break; } args[k].type = TCL_DOUBLE; /* FALLTHROUGH */ case TCL_DOUBLE: args[k].doubleValue = d; break; case TCL_INT: if (ExprIntFunc(NULL, interp, 2, &objv[j-1]) != TCL_OK) { ckfree(args); return TCL_ERROR; } valuePtr = Tcl_GetObjResult(interp); Tcl_GetLongFromObj(NULL, valuePtr, &args[k].intValue); Tcl_ResetResult(interp); break; case TCL_WIDE_INT: if (ExprWideFunc(NULL, interp, 2, &objv[j-1]) != TCL_OK) { ckfree(args); return TCL_ERROR; } valuePtr = Tcl_GetObjResult(interp); Tcl_GetWideIntFromObj(NULL, valuePtr, &args[k].wideValue); Tcl_ResetResult(interp); break; } } /* * Call the function. */ errno = 0; result = dataPtr->proc(dataPtr->clientData, interp, args, &funcResult); ckfree(args); if (result != TCL_OK) { return result; } /* * Return the result of the call. */ if (funcResult.type == TCL_INT) { TclNewLongObj(valuePtr, funcResult.intValue); } else if (funcResult.type == TCL_WIDE_INT) { valuePtr = Tcl_NewWideIntObj(funcResult.wideValue); } else { return CheckDoubleResult(interp, funcResult.doubleValue); } Tcl_SetObjResult(interp, valuePtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * OldMathFuncDeleteProc -- * * Cleans up after deleting a math function registered with * Tcl_CreateMathFunc * * Results: * None. * * Side effects: * Frees allocated memory. * *---------------------------------------------------------------------- */ static void OldMathFuncDeleteProc( ClientData clientData) { OldMathFuncData *dataPtr = clientData; ckfree(dataPtr->argTypes); ckfree(dataPtr); } /* *---------------------------------------------------------------------- * * Tcl_GetMathFuncInfo -- * * Discovers how a particular math function was created in a given * interpreter. * * Results: * TCL_OK if it succeeds, TCL_ERROR else (leaving an error message in the * interpreter result if that happens.) * * Side effects: * If this function succeeds, the variables pointed to by the numArgsPtr * and argTypePtr arguments will be updated to detail the arguments * allowed by the function. The variable pointed to by the procPtr * argument will be set to NULL if the function is a builtin function, * and will be set to the address of the C function used to implement the * math function otherwise (in which case the variable pointed to by the * clientDataPtr argument will also be updated.) * *---------------------------------------------------------------------- */ int Tcl_GetMathFuncInfo( Tcl_Interp *interp, const char *name, int *numArgsPtr, Tcl_ValueType **argTypesPtr, Tcl_MathProc **procPtr, ClientData *clientDataPtr) { Tcl_Obj *cmdNameObj; Command *cmdPtr; /* * Get the command that implements the math function. */ TclNewLiteralStringObj(cmdNameObj, "tcl::mathfunc::"); Tcl_AppendToObj(cmdNameObj, name, -1); Tcl_IncrRefCount(cmdNameObj); cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdNameObj); Tcl_DecrRefCount(cmdNameObj); /* * Report unknown functions. */ if (cmdPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown math function \"%s\"", name)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "MATHFUNC", name, NULL); *numArgsPtr = -1; *argTypesPtr = NULL; *procPtr = NULL; *clientDataPtr = NULL; return TCL_ERROR; } /* * Retrieve function info for user defined functions; return dummy * information for builtins. */ if (cmdPtr->objProc == &OldMathFuncProc) { OldMathFuncData *dataPtr = cmdPtr->clientData; *procPtr = dataPtr->proc; *numArgsPtr = dataPtr->numArgs; *argTypesPtr = dataPtr->argTypes; *clientDataPtr = dataPtr->clientData; } else { *procPtr = NULL; *numArgsPtr = -1; *argTypesPtr = NULL; *procPtr = NULL; *clientDataPtr = NULL; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ListMathFuncs -- * * Produces a list of all the math functions defined in a given * interpreter. * * Results: * A pointer to a Tcl_Obj structure with a reference count of zero, or * NULL in the case of an error (in which case a suitable error message * will be left in the interpreter result.) * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_ListMathFuncs( Tcl_Interp *interp, const char *pattern) { Tcl_Obj *script = Tcl_NewStringObj("::info functions ", -1); Tcl_Obj *result; Tcl_InterpState state; if (pattern) { Tcl_Obj *patternObj = Tcl_NewStringObj(pattern, -1); Tcl_Obj *arg = Tcl_NewListObj(1, &patternObj); Tcl_AppendObjToObj(script, arg); Tcl_DecrRefCount(arg); /* Should tear down patternObj too */ } state = Tcl_SaveInterpState(interp, TCL_OK); Tcl_IncrRefCount(script); if (TCL_OK == Tcl_EvalObjEx(interp, script, 0)) { result = Tcl_DuplicateObj(Tcl_GetObjResult(interp)); } else { result = Tcl_NewObj(); } Tcl_DecrRefCount(script); Tcl_RestoreInterpState(interp, state); return result; } /* *---------------------------------------------------------------------- * * TclInterpReady -- * * Check if an interpreter is ready to eval commands or scripts, i.e., if * it was not deleted and if the nesting level is not too high. * * Results: * The return value is TCL_OK if it the interpreter is ready, TCL_ERROR * otherwise. * * Side effects: * The interpreters object and string results are cleared. * *---------------------------------------------------------------------- */ int TclInterpReady( Tcl_Interp *interp) { register Interp *iPtr = (Interp *) interp; /* * Reset both the interpreter's string and object results and clear out * any previous error information. */ Tcl_ResetResult(interp); /* * If the interpreter has been deleted, return an error. */ if (iPtr->flags & DELETED) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to call eval in deleted interpreter", -1)); Tcl_SetErrorCode(interp, "TCL", "IDELETE", "attempt to call eval in deleted interpreter", NULL); return TCL_ERROR; } if (iPtr->execEnvPtr->rewind) { return TCL_ERROR; } /* * Make sure the script being evaluated (if any) has not been canceled. */ if (TclCanceled(iPtr) && (TCL_OK != Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG))) { return TCL_ERROR; } /* * Check depth of nested calls to Tcl_Eval: if this gets too large, it's * probably because of an infinite loop somewhere. */ if (((iPtr->numLevels) <= iPtr->maxNestingDepth)) { return TCL_OK; } Tcl_SetObjResult(interp, Tcl_NewStringObj( "too many nested evaluations (infinite loop?)", -1)); Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclResetCancellation -- * * Reset the script cancellation flags if the nesting level * (iPtr->numLevels) for the interp is zero or argument force is * non-zero. * * Results: * A standard Tcl result. * * Side effects: * The script cancellation flags for the interp may be reset. * *---------------------------------------------------------------------- */ int TclResetCancellation( Tcl_Interp *interp, int force) { register Interp *iPtr = (Interp *) interp; if (iPtr == NULL) { return TCL_ERROR; } if (force || (iPtr->numLevels == 0)) { TclUnsetCancelFlags(iPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_Canceled -- * * Check if the script in progress has been canceled, i.e., * Tcl_CancelEval was called for this interpreter or any of its master * interpreters. * * Results: * The return value is TCL_OK if the script evaluation has not been * canceled, TCL_ERROR otherwise. * * If "flags" contains TCL_LEAVE_ERR_MSG, an error message is returned in * the interpreter's result object. Otherwise, the interpreter's result * object is left unchanged. If "flags" contains TCL_CANCEL_UNWIND, * TCL_ERROR will only be returned if the script evaluation is being * completely unwound. * * Side effects: * The CANCELED flag for the interp will be reset if it is set. * *---------------------------------------------------------------------- */ int Tcl_Canceled( Tcl_Interp *interp, int flags) { register Interp *iPtr = (Interp *) interp; /* * Has the current script in progress for this interpreter been canceled * or is the stack being unwound due to the previous script cancellation? */ if (!TclCanceled(iPtr)) { return TCL_OK; } /* * The CANCELED flag is a one-shot flag that is reset immediately upon * being detected; however, if the TCL_CANCEL_UNWIND flag is set we will * continue to report that the script in progress has been canceled * thereby allowing the evaluation stack for the interp to be fully * unwound. */ iPtr->flags &= ~CANCELED; /* * The CANCELED flag was detected and reset; however, if the caller * specified the TCL_CANCEL_UNWIND flag, we only return TCL_ERROR * (indicating that the script in progress has been canceled) if the * evaluation stack for the interp is being fully unwound. */ if ((flags & TCL_CANCEL_UNWIND) && !(iPtr->flags & TCL_CANCEL_UNWIND)) { return TCL_OK; } /* * If the TCL_LEAVE_ERR_MSG flags bit is set, place an error in the * interp's result; otherwise, we leave it alone. */ if (flags & TCL_LEAVE_ERR_MSG) { const char *id, *message = NULL; int length; /* * Setup errorCode variables so that we can differentiate between * being canceled and unwound. */ if (iPtr->asyncCancelMsg != NULL) { message = Tcl_GetStringFromObj(iPtr->asyncCancelMsg, &length); } else { length = 0; } if (iPtr->flags & TCL_CANCEL_UNWIND) { id = "IUNWIND"; if (length == 0) { message = "eval unwound"; } } else { id = "ICANCEL"; if (length == 0) { message = "eval canceled"; } } Tcl_SetObjResult(interp, Tcl_NewStringObj(message, -1)); Tcl_SetErrorCode(interp, "TCL", "CANCEL", id, message, NULL); } /* * Return TCL_ERROR to the caller (not necessarily just the Tcl core * itself) that indicates further processing of the script or command in * progress should halt gracefully and as soon as possible. */ return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_CancelEval -- * * This function schedules the cancellation of the current script in the * given interpreter. * * Results: * The return value is a standard Tcl completion code such as TCL_OK or * TCL_ERROR. Since the interp may belong to a different thread, no error * message can be left in the interp's result. * * Side effects: * The script in progress in the specified interpreter will be canceled * with TCL_ERROR after asynchronous handlers are invoked at the next * Tcl_Canceled check. * *---------------------------------------------------------------------- */ int Tcl_CancelEval( Tcl_Interp *interp, /* Interpreter in which to cancel the * script. */ Tcl_Obj *resultObjPtr, /* The script cancellation error message or * NULL for a default error message. */ ClientData clientData, /* Passed to CancelEvalProc. */ int flags) /* Collection of OR-ed bits that control * the cancellation of the script. Only * TCL_CANCEL_UNWIND is currently * supported. */ { Tcl_HashEntry *hPtr; CancelInfo *cancelInfo; int code = TCL_ERROR; const char *result; if (interp == NULL) { return TCL_ERROR; } Tcl_MutexLock(&cancelLock); if (cancelTableInitialized != 1) { /* * No CancelInfo hash table (Tcl_CreateInterp has never been called?) */ goto done; } hPtr = Tcl_FindHashEntry(&cancelTable, (char *) interp); if (hPtr == NULL) { /* * No CancelInfo record for this interpreter. */ goto done; } cancelInfo = Tcl_GetHashValue(hPtr); /* * Populate information needed by the interpreter thread to fulfill the * cancellation request. Currently, clientData is ignored. If the * TCL_CANCEL_UNWIND flags bit is set, the script in progress is not * allowed to catch the script cancellation because the evaluation stack * for the interp is completely unwound. */ if (resultObjPtr != NULL) { result = Tcl_GetStringFromObj(resultObjPtr, &cancelInfo->length); cancelInfo->result = ckrealloc(cancelInfo->result,cancelInfo->length); memcpy(cancelInfo->result, result, (size_t) cancelInfo->length); TclDecrRefCount(resultObjPtr); /* Discard their result object. */ } else { cancelInfo->result = NULL; cancelInfo->length = 0; } cancelInfo->clientData = clientData; cancelInfo->flags = flags; Tcl_AsyncMark(cancelInfo->async); code = TCL_OK; done: Tcl_MutexUnlock(&cancelLock); return code; } /* *---------------------------------------------------------------------- * * Tcl_InterpActive -- * * Returns non-zero if the specified interpreter is in use, i.e. if there * is an evaluation currently active in the interpreter. * * Results: * See above. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_InterpActive( Tcl_Interp *interp) { return ((Interp *) interp)->numLevels > 0; } /* *---------------------------------------------------------------------- * * Tcl_EvalObjv -- * * This function evaluates a Tcl command that has already been parsed * into words, with one Tcl_Obj holding each word. * * Results: * The return value is a standard Tcl completion code such as TCL_OK or * TCL_ERROR. A result or error message is left in interp's result. * * Side effects: * Always pushes a callback. Other side effects depend on the command. * *---------------------------------------------------------------------- */ int Tcl_EvalObjv( Tcl_Interp *interp, /* Interpreter in which to evaluate the * command. Also used for error reporting. */ int objc, /* Number of words in command. */ Tcl_Obj *const objv[], /* An array of pointers to objects that are * the words that make up the command. */ int flags) /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL, TCL_EVAL_INVOKE and * TCL_EVAL_NOERR are currently supported. */ { int result; NRE_callback *rootPtr = TOP_CB(interp); result = TclNREvalObjv(interp, objc, objv, flags, NULL); return TclNRRunCallbacks(interp, result, rootPtr); } int TclNREvalObjv( Tcl_Interp *interp, /* Interpreter in which to evaluate the * command. Also used for error reporting. */ int objc, /* Number of words in command. */ Tcl_Obj *const objv[], /* An array of pointers to objects that are * the words that make up the command. */ int flags, /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL, TCL_EVAL_INVOKE and * TCL_EVAL_NOERR are currently supported. */ Command *cmdPtr) /* NULL if the Command is to be looked up * here, otherwise the pointer to the * requested Command struct to be invoked. */ { Interp *iPtr = (Interp *) interp; /* * data[1] stores a marker for use by tailcalls; it will be set to 1 by * command redirectors (imports, alias, ensembles) so that tailcall skips * this callback (that marks the end of the target command) and goes back * to the end of the source command. */ if (iPtr->deferredCallbacks) { iPtr->deferredCallbacks = NULL; } else { TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL); } iPtr->numLevels++; TclNRAddCallback(interp, EvalObjvCore, cmdPtr, INT2PTR(flags), INT2PTR(objc), objv); return TCL_OK; } static int EvalObjvCore( ClientData data[], Tcl_Interp *interp, int result) { Command *cmdPtr = NULL, *preCmdPtr = data[0]; int flags = PTR2INT(data[1]); int objc = PTR2INT(data[2]); Tcl_Obj **objv = data[3]; Interp *iPtr = (Interp *) interp; Namespace *lookupNsPtr = NULL; int enterTracesDone = 0; /* * Push records for task to be done on return, in INVERSE order. First, if * needed, the exception handlers (as they should happen last). */ if (!(flags & TCL_EVAL_NOERR)) { TEOV_PushExceptionHandlers(interp, objc, objv, flags); } if (TCL_OK != TclInterpReady(interp)) { return TCL_ERROR; } if (objc == 0) { return TCL_OK; } if (TclLimitExceeded(iPtr->limit)) { return TCL_ERROR; } /* * Configure evaluation context to match the requested flags. */ if (iPtr->lookupNsPtr) { /* * Capture the namespace we should do command name resolution in, as * instructed by our caller sneaking it in to us in a private interp * field. Clear that field right away so we cannot possibly have its * use leak where it should not. The sneaky message pass is done. * * Use of this mechanism overrides the TCL_EVAL_GLOBAL flag. * TODO: Is that a bug? */ lookupNsPtr = iPtr->lookupNsPtr; iPtr->lookupNsPtr = NULL; } else if (flags & TCL_EVAL_INVOKE) { lookupNsPtr = iPtr->globalNsPtr; } else { /* * TCL_EVAL_INVOKE was not set: clear rewrite rules */ iPtr->ensembleRewrite.sourceObjs = NULL; if (flags & TCL_EVAL_GLOBAL) { TEOV_SwitchVarFrame(interp); lookupNsPtr = iPtr->globalNsPtr; } } /* * Lookup the Command to dispatch. */ reresolve: assert(cmdPtr == NULL); if (preCmdPtr) { /* Caller gave it to us */ if (!(preCmdPtr->flags & CMD_IS_DELETED)) { /* So long as it exists, use it. */ cmdPtr = preCmdPtr; } else if (flags & TCL_EVAL_NORESOLVE) { /* * When it's been deleted, and we're told not to attempt * resolving it ourselves, all we can do is raise an error. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "attempt to invoke a deleted command")); Tcl_SetErrorCode(interp, "TCL", "EVAL", "DELETEDCOMMAND", NULL); return TCL_ERROR; } } if (cmdPtr == NULL) { cmdPtr = TEOV_LookupCmdFromObj(interp, objv[0], lookupNsPtr); if (!cmdPtr) { return TEOV_NotFound(interp, objc, objv, lookupNsPtr); } } if (enterTracesDone || iPtr->tracePtr || (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) { Tcl_Obj *commandPtr = TclGetSourceFromFrame( flags & TCL_EVAL_SOURCE_IN_FRAME ? iPtr->cmdFramePtr : NULL, objc, objv); Tcl_IncrRefCount(commandPtr); if (!enterTracesDone) { int code = TEOV_RunEnterTraces(interp, &cmdPtr, commandPtr, objc, objv); /* * Send any exception from enter traces back as an exception * raised by the traced command. * TODO: Is this a bug? Letting an execution trace BREAK or * CONTINUE or RETURN in the place of the traced command? * Would either converting all exceptions to TCL_ERROR, or * just swallowing them be better? (Swallowing them has the * problem of permanently hiding program errors.) */ if (code != TCL_OK) { Tcl_DecrRefCount(commandPtr); return code; } /* * If the enter traces made the resolved cmdPtr unusable, go * back and resolve again, but next time don't run enter * traces again. */ if (cmdPtr == NULL) { enterTracesDone = 1; Tcl_DecrRefCount(commandPtr); goto reresolve; } } /* * Schedule leave traces. Raise the refCount on the resolved * cmdPtr, so that when it passes to the leave traces we know * it's still valid. */ cmdPtr->refCount++; TclNRAddCallback(interp, TEOV_RunLeaveTraces, INT2PTR(objc), commandPtr, cmdPtr, objv); } TclNRAddCallback(interp, Dispatch, cmdPtr->nreProc ? cmdPtr->nreProc : cmdPtr->objProc, cmdPtr->objClientData, INT2PTR(objc), objv); return TCL_OK; } static int Dispatch( ClientData data[], Tcl_Interp *interp, int result) { Tcl_ObjCmdProc *objProc = data[0]; ClientData clientData = data[1]; int objc = PTR2INT(data[2]); Tcl_Obj **objv = data[3]; Interp *iPtr = (Interp *) interp; #ifdef USE_DTRACE if (TCL_DTRACE_CMD_ARGS_ENABLED()) { const char *a[10]; int i = 0; while (i < 10) { a[i] = i < objc ? TclGetString(objv[i]) : NULL; i++; } TCL_DTRACE_CMD_ARGS(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]); } if (TCL_DTRACE_CMD_INFO_ENABLED() && iPtr->cmdFramePtr) { Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr); const char *a[6]; int i[2]; TclDTraceInfo(info, a, i); TCL_DTRACE_CMD_INFO(a[0], a[1], a[2], a[3], i[0], i[1], a[4], a[5]); TclDecrRefCount(info); } if ((TCL_DTRACE_CMD_RETURN_ENABLED() || TCL_DTRACE_CMD_RESULT_ENABLED()) && objc) { TclNRAddCallback(interp, DTraceCmdReturn, objv[0], NULL, NULL, NULL); } if (TCL_DTRACE_CMD_ENTRY_ENABLED() && objc) { TCL_DTRACE_CMD_ENTRY(TclGetString(objv[0]), objc - 1, (Tcl_Obj **)(objv + 1)); } #endif /* USE_DTRACE */ iPtr->cmdCount++; return objProc(clientData, interp, objc, objv); } int TclNRRunCallbacks( Tcl_Interp *interp, int result, struct NRE_callback *rootPtr) /* All callbacks down to rootPtr not inclusive * are to be run. */ { Interp *iPtr = (Interp *) interp; NRE_callback *callbackPtr; Tcl_NRPostProc *procPtr; /* * If the interpreter has a non-empty string result, the result object is * either empty or stale because some function set interp->result * directly. If so, move the string result to the result object, then * reset the string result. * * This only needs to be done for the first item in the list: all other * are for NR function calls, and those are Tcl_Obj based. */ if (*(iPtr->result) != 0) { (void) Tcl_GetObjResult(interp); } while (TOP_CB(interp) != rootPtr) { callbackPtr = TOP_CB(interp); procPtr = callbackPtr->procPtr; TOP_CB(interp) = callbackPtr->nextPtr; result = procPtr(callbackPtr->data, interp, result); TCLNR_FREE(interp, callbackPtr); } return result; } static int NRCommand( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; iPtr->numLevels--; /* * If there is a tailcall, schedule it next */ if (data[1] && (data[1] != INT2PTR(1))) { TclNRAddCallback(interp, TclNRTailcallEval, data[1], NULL, NULL, NULL); } /* OPT ?? * Do not interrupt a series of cleanups with async or limit checks: * just check at the end? */ if (TclAsyncReady(iPtr)) { result = Tcl_AsyncInvoke(interp, result); } if ((result == TCL_OK) && TclCanceled(iPtr)) { result = Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG); } if (result == TCL_OK && TclLimitReady(iPtr->limit)) { result = Tcl_LimitCheck(interp); } return result; } /* *---------------------------------------------------------------------- * * TEOV_Exception - * TEOV_LookupCmdFromObj - * TEOV_RunEnterTraces - * TEOV_RunLeaveTraces - * TEOV_NotFound - * * These are helper functions for Tcl_EvalObjv. * *---------------------------------------------------------------------- */ static void TEOV_PushExceptionHandlers( Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags) { Interp *iPtr = (Interp *) interp; /* * If any error processing is necessary, push the appropriate records. * Note that we have to push them in the inverse order: first the one that * has to run last. */ if (!(flags & TCL_EVAL_INVOKE)) { /* * Error messages */ TclNRAddCallback(interp, TEOV_Error, INT2PTR(objc), (ClientData) objv, NULL, NULL); } if (iPtr->numLevels == 1) { /* * No CONTINUE or BREAK at level 0, manage RETURN */ TclNRAddCallback(interp, TEOV_Exception, INT2PTR(iPtr->evalFlags), NULL, NULL, NULL); } } static void TEOV_SwitchVarFrame( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; /* * Change the varFrame to be the rootVarFrame, and push a record to * restore things at the end. */ TclNRAddCallback(interp, TEOV_RestoreVarFrame, iPtr->varFramePtr, NULL, NULL, NULL); iPtr->varFramePtr = iPtr->rootFramePtr; } static int TEOV_RestoreVarFrame( ClientData data[], Tcl_Interp *interp, int result) { ((Interp *) interp)->varFramePtr = data[0]; return result; } static int TEOV_Exception( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; int allowExceptions = (PTR2INT(data[0]) & TCL_ALLOW_EXCEPTIONS); if (result != TCL_OK) { if (result == TCL_RETURN) { result = TclUpdateReturnInfo(iPtr); } if ((result != TCL_ERROR) && !allowExceptions) { ProcessUnexpectedResult(interp, result); result = TCL_ERROR; } } /* * We are returning to level 0, so should process TclResetCancellation. As * numLevels has not *yet* been decreased, do not call it: do the thing * here directly. */ TclUnsetCancelFlags(iPtr); return result; } static int TEOV_Error( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_Obj *listPtr; const char *cmdString; int cmdLen; int objc = PTR2INT(data[0]); Tcl_Obj **objv = data[1]; if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)){ /* * If there was an error, a command string will be needed for the * error log: get it out of the itemPtr. The details depend on the * type. */ listPtr = Tcl_NewListObj(objc, objv); cmdString = Tcl_GetStringFromObj(listPtr, &cmdLen); Tcl_LogCommandInfo(interp, cmdString, cmdString, cmdLen); Tcl_DecrRefCount(listPtr); } iPtr->flags &= ~ERR_ALREADY_LOGGED; return result; } static int TEOV_NotFound( Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], Namespace *lookupNsPtr) { Command * cmdPtr; Interp *iPtr = (Interp *) interp; int i, newObjc, handlerObjc; Tcl_Obj **newObjv, **handlerObjv; CallFrame *varFramePtr = iPtr->varFramePtr; Namespace *currNsPtr = NULL;/* Used to check for and invoke any registered * unknown command handler for the current * namespace (TIP 181). */ Namespace *savedNsPtr = NULL; currNsPtr = varFramePtr->nsPtr; if ((currNsPtr == NULL) || (currNsPtr->unknownHandlerPtr == NULL)) { currNsPtr = iPtr->globalNsPtr; if (currNsPtr == NULL) { Tcl_Panic("Tcl_EvalObjv: NULL global namespace pointer"); } } /* * Check to see if the resolution namespace has lost its unknown handler. * If so, reset it to "::unknown". */ if (currNsPtr->unknownHandlerPtr == NULL) { TclNewLiteralStringObj(currNsPtr->unknownHandlerPtr, "::unknown"); Tcl_IncrRefCount(currNsPtr->unknownHandlerPtr); } /* * Get the list of words for the unknown handler and allocate enough space * to hold both the handler prefix and all words of the command invokation * itself. */ Tcl_ListObjGetElements(NULL, currNsPtr->unknownHandlerPtr, &handlerObjc, &handlerObjv); newObjc = objc + handlerObjc; newObjv = TclStackAlloc(interp, (int) sizeof(Tcl_Obj *) * newObjc); /* * Copy command prefix from unknown handler and add on the real command's * full argument list. Note that we only use memcpy() once because we have * to increment the reference count of all the handler arguments anyway. */ for (i = 0; i < handlerObjc; ++i) { newObjv[i] = handlerObjv[i]; Tcl_IncrRefCount(newObjv[i]); } memcpy(newObjv+handlerObjc, objv, sizeof(Tcl_Obj *) * (unsigned)objc); /* * Look up and invoke the handler (by recursive call to this function). If * there is no handler at all, instead of doing the recursive call we just * generate a generic error message; it would be an infinite-recursion * nightmare otherwise. * * In this case we worry a bit less about recursion for now, and call the * "blocking" interface. */ cmdPtr = TEOV_LookupCmdFromObj(interp, newObjv[0], lookupNsPtr); if (cmdPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid command name \"%s\"", TclGetString(objv[0]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", TclGetString(objv[0]), NULL); /* * Release any resources we locked and allocated during the handler * call. */ for (i = 0; i < handlerObjc; ++i) { Tcl_DecrRefCount(newObjv[i]); } TclStackFree(interp, newObjv); return TCL_ERROR; } if (lookupNsPtr) { savedNsPtr = varFramePtr->nsPtr; varFramePtr->nsPtr = lookupNsPtr; } TclSkipTailcall(interp); TclNRAddCallback(interp, TEOV_NotFoundCallback, INT2PTR(handlerObjc), newObjv, savedNsPtr, NULL); return TclNREvalObjv(interp, newObjc, newObjv, TCL_EVAL_NOERR, NULL); } static int TEOV_NotFoundCallback( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; int objc = PTR2INT(data[0]); Tcl_Obj **objv = data[1]; Namespace *savedNsPtr = data[2]; int i; if (savedNsPtr) { iPtr->varFramePtr->nsPtr = savedNsPtr; } /* * Release any resources we locked and allocated during the handler call. */ for (i = 0; i < objc; ++i) { Tcl_DecrRefCount(objv[i]); } TclStackFree(interp, objv); return result; } static int TEOV_RunEnterTraces( Tcl_Interp *interp, Command **cmdPtrPtr, Tcl_Obj *commandPtr, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; Command *cmdPtr = *cmdPtrPtr; int newEpoch, cmdEpoch = cmdPtr->cmdEpoch; int length, traceCode = TCL_OK; const char *command = Tcl_GetStringFromObj(commandPtr, &length); /* * Call trace functions. * Execute any command or execution traces. Note that we bump up the * command's reference count for the duration of the calling of the * traces so that the structure doesn't go away underneath our feet. */ cmdPtr->refCount++; if (iPtr->tracePtr) { traceCode = TclCheckInterpTraces(interp, command, length, cmdPtr, TCL_OK, TCL_TRACE_ENTER_EXEC, objc, objv); } if ((cmdPtr->flags & CMD_HAS_EXEC_TRACES) && (traceCode == TCL_OK)) { traceCode = TclCheckExecutionTraces(interp, command, length, cmdPtr, TCL_OK, TCL_TRACE_ENTER_EXEC, objc, objv); } newEpoch = cmdPtr->cmdEpoch; TclCleanupCommandMacro(cmdPtr); if (traceCode != TCL_OK) { if (traceCode == TCL_ERROR) { Tcl_Obj *info; TclNewLiteralStringObj(info, "\n (enter trace on \""); Tcl_AppendLimitedToObj(info, command, length, 55, "..."); Tcl_AppendToObj(info, "\")", 2); Tcl_AppendObjToErrorInfo(interp, info); iPtr->flags |= ERR_ALREADY_LOGGED; } return traceCode; } if (cmdEpoch != newEpoch) { *cmdPtrPtr = NULL; } return TCL_OK; } static int TEOV_RunLeaveTraces( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; int traceCode = TCL_OK; int objc = PTR2INT(data[0]); Tcl_Obj *commandPtr = data[1]; Command *cmdPtr = data[2]; Tcl_Obj **objv = data[3]; int length; const char *command = Tcl_GetStringFromObj(commandPtr, &length); if (!(cmdPtr->flags & CMD_IS_DELETED)) { if (cmdPtr->flags & CMD_HAS_EXEC_TRACES){ traceCode = TclCheckExecutionTraces(interp, command, length, cmdPtr, result, TCL_TRACE_LEAVE_EXEC, objc, objv); } if (iPtr->tracePtr != NULL && traceCode == TCL_OK) { traceCode = TclCheckInterpTraces(interp, command, length, cmdPtr, result, TCL_TRACE_LEAVE_EXEC, objc, objv); } } /* * As cmdPtr is set, TclNRRunCallbacks is about to reduce the numlevels. * Prevent that by resetting the cmdPtr field and dealing right here with * cmdPtr->refCount. */ TclCleanupCommandMacro(cmdPtr); if (traceCode != TCL_OK) { if (traceCode == TCL_ERROR) { Tcl_Obj *info; TclNewLiteralStringObj(info, "\n (leave trace on \""); Tcl_AppendLimitedToObj(info, command, length, 55, "..."); Tcl_AppendToObj(info, "\")", 2); Tcl_AppendObjToErrorInfo(interp, info); iPtr->flags |= ERR_ALREADY_LOGGED; } result = traceCode; } Tcl_DecrRefCount(commandPtr); return result; } static inline Command * TEOV_LookupCmdFromObj( Tcl_Interp *interp, Tcl_Obj *namePtr, Namespace *lookupNsPtr) { Interp *iPtr = (Interp *) interp; Command *cmdPtr; Namespace *savedNsPtr = iPtr->varFramePtr->nsPtr; if (lookupNsPtr) { iPtr->varFramePtr->nsPtr = lookupNsPtr; } cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, namePtr); iPtr->varFramePtr->nsPtr = savedNsPtr; return cmdPtr; } /* *---------------------------------------------------------------------- * * Tcl_EvalTokensStandard -- * * Given an array of tokens parsed from a Tcl command (e.g., the tokens * that make up a word or the index for an array variable) this function * evaluates the tokens and concatenates their values to form a single * result value. * * Results: * The return value is a standard Tcl completion code such as TCL_OK or * TCL_ERROR. A result or error message is left in interp's result. * * Side effects: * Depends on the array of tokens being evaled. * *---------------------------------------------------------------------- */ int Tcl_EvalTokensStandard( Tcl_Interp *interp, /* Interpreter in which to lookup variables, * execute nested commands, and report * errors. */ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to * evaluate and concatenate. */ int count) /* Number of tokens to consider at tokenPtr. * Must be at least 1. */ { return TclSubstTokens(interp, tokenPtr, count, /* numLeftPtr */ NULL, 1, NULL, NULL); } /* *---------------------------------------------------------------------- * * Tcl_EvalTokens -- * * Given an array of tokens parsed from a Tcl command (e.g., the tokens * that make up a word or the index for an array variable) this function * evaluates the tokens and concatenates their values to form a single * result value. * * Results: * The return value is a pointer to a newly allocated Tcl_Obj containing * the value of the array of tokens. The reference count of the returned * object has been incremented. If an error occurs in evaluating the * tokens then a NULL value is returned and an error message is left in * interp's result. * * Side effects: * A new object is allocated to hold the result. * *---------------------------------------------------------------------- * * This uses a non-standard return convention; its use is now deprecated. It * is a wrapper for the new function Tcl_EvalTokensStandard, and is not used * in the core any longer. It is only kept for backward compatibility. */ Tcl_Obj * Tcl_EvalTokens( Tcl_Interp *interp, /* Interpreter in which to lookup variables, * execute nested commands, and report * errors. */ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to * evaluate and concatenate. */ int count) /* Number of tokens to consider at tokenPtr. * Must be at least 1. */ { Tcl_Obj *resPtr; if (Tcl_EvalTokensStandard(interp, tokenPtr, count) != TCL_OK) { return NULL; } resPtr = Tcl_GetObjResult(interp); Tcl_IncrRefCount(resPtr); Tcl_ResetResult(interp); return resPtr; } /* *---------------------------------------------------------------------- * * Tcl_EvalEx, TclEvalEx -- * * This function evaluates a Tcl script without using the compiler or * byte-code interpreter. It just parses the script, creates values for * each word of each command, then calls EvalObjv to execute each * command. * * Results: * The return value is a standard Tcl completion code such as TCL_OK or * TCL_ERROR. A result or error message is left in interp's result. * * Side effects: * Depends on the script. * * TIP #280 : Keep public API, internally extended API. *---------------------------------------------------------------------- */ int Tcl_EvalEx( Tcl_Interp *interp, /* Interpreter in which to evaluate the * script. Also used for error reporting. */ const char *script, /* First character of script to evaluate. */ int numBytes, /* Number of bytes in script. If < 0, the * script consists of all bytes up to the * first null character. */ int flags) /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL is currently supported. */ { return TclEvalEx(interp, script, numBytes, flags, 1, NULL, script); } int TclEvalEx( Tcl_Interp *interp, /* Interpreter in which to evaluate the * script. Also used for error reporting. */ const char *script, /* First character of script to evaluate. */ int numBytes, /* Number of bytes in script. If < 0, the * script consists of all bytes up to the * first NUL character. */ int flags, /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL is currently supported. */ int line, /* The line the script starts on. */ int *clNextOuter, /* Information about an outer context for */ const char *outerScript) /* continuation line data. This is set only in * TclSubstTokens(), to properly handle * [...]-nested commands. The 'outerScript' * refers to the most-outer script containing * the embedded command, which is refered to * by 'script'. The 'clNextOuter' refers to * the current entry in the table of * continuation lines in this "master script", * and the character offsets are relative to * the 'outerScript' as well. * * If outerScript == script, then this call is * for the outer-most script/command. See * Tcl_EvalEx() and TclEvalObjEx() for places * generating arguments for which this is * true. */ { Interp *iPtr = (Interp *) interp; const char *p, *next; const unsigned int minObjs = 20; Tcl_Obj **objv, **objvSpace; int *expand, *lines, *lineSpace; Tcl_Token *tokenPtr; int commandLength, bytesLeft, expandRequested, code = TCL_OK; CallFrame *savedVarFramePtr;/* Saves old copy of iPtr->varFramePtr in case * TCL_EVAL_GLOBAL was set. */ int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS); int gotParse = 0; unsigned int i, objectsUsed = 0; /* These variables keep track of how much * state has been allocated while evaluating * the script, so that it can be freed * properly if an error occurs. */ Tcl_Parse *parsePtr = TclStackAlloc(interp, sizeof(Tcl_Parse)); CmdFrame *eeFramePtr = TclStackAlloc(interp, sizeof(CmdFrame)); Tcl_Obj **stackObjArray = TclStackAlloc(interp, minObjs * sizeof(Tcl_Obj *)); int *expandStack = TclStackAlloc(interp, minObjs * sizeof(int)); int *linesStack = TclStackAlloc(interp, minObjs * sizeof(int)); /* TIP #280 Structures for tracking of command * locations. */ int *clNext = NULL; /* Pointer for the tracking of invisible * continuation lines. Initialized only if the * caller gave us a table of locations to * track, via scriptCLLocPtr. It always refers * to the table entry holding the location of * the next invisible continuation line to * look for, while parsing the script. */ if (iPtr->scriptCLLocPtr) { if (clNextOuter) { clNext = clNextOuter; } else { clNext = &iPtr->scriptCLLocPtr->loc[0]; } } if (numBytes < 0) { numBytes = strlen(script); } Tcl_ResetResult(interp); savedVarFramePtr = iPtr->varFramePtr; if (flags & TCL_EVAL_GLOBAL) { iPtr->varFramePtr = iPtr->rootFramePtr; } /* * Each iteration through the following loop parses the next command from * the script and then executes it. */ objv = objvSpace = stackObjArray; lines = lineSpace = linesStack; expand = expandStack; p = script; bytesLeft = numBytes; /* * TIP #280 Initialize tracking. Do not push on the frame stack yet. * * We open a new context, either for a sourced script, or 'eval'. * For sourced files we always have a path object, even if nothing was * specified in the interp itself. That makes code using it simpler as * NULL checks can be left out. Sourced file without path in the * 'scriptFile' is possible during Tcl initialization. */ eeFramePtr->level = iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level + 1 : 1; eeFramePtr->framePtr = iPtr->framePtr; eeFramePtr->nextPtr = iPtr->cmdFramePtr; eeFramePtr->nline = 0; eeFramePtr->line = NULL; eeFramePtr->cmdObj = NULL; iPtr->cmdFramePtr = eeFramePtr; if (iPtr->evalFlags & TCL_EVAL_FILE) { /* * Set up for a sourced file. */ eeFramePtr->type = TCL_LOCATION_SOURCE; if (iPtr->scriptFile) { /* * Normalization here, to have the correct pwd. Should have * negligible impact on performance, as the norm should have been * done already by the 'source' invoking us, and it caches the * result. */ Tcl_Obj *norm = Tcl_FSGetNormalizedPath(interp, iPtr->scriptFile); if (norm == NULL) { /* * Error message in the interp result. */ code = TCL_ERROR; goto error; } eeFramePtr->data.eval.path = norm; } else { TclNewLiteralStringObj(eeFramePtr->data.eval.path, ""); } Tcl_IncrRefCount(eeFramePtr->data.eval.path); } else { /* * Set up for plain eval. */ eeFramePtr->type = TCL_LOCATION_EVAL; eeFramePtr->data.eval.path = NULL; } iPtr->evalFlags = 0; do { if (Tcl_ParseCommand(interp, p, bytesLeft, 0, parsePtr) != TCL_OK) { code = TCL_ERROR; Tcl_LogCommandInfo(interp, script, parsePtr->commandStart, parsePtr->term + 1 - parsePtr->commandStart); goto posterror; } /* * TIP #280 Track lines. The parser may have skipped text till it * found the command we are now at. We have to count the lines in this * block, and do not forget invisible continuation lines. */ TclAdvanceLines(&line, p, parsePtr->commandStart); TclAdvanceContinuations(&line, &clNext, parsePtr->commandStart - outerScript); gotParse = 1; if (parsePtr->numWords > 0) { /* * TIP #280. Track lines within the words of the current * command. We use a separate pointer into the table of * continuation line locations to not lose our position for the * per-command parsing. */ int wordLine = line; const char *wordStart = parsePtr->commandStart; int *wordCLNext = clNext; unsigned int objectsNeeded = 0; unsigned int numWords = parsePtr->numWords; /* * Generate an array of objects for the words of the command. */ if (numWords > minObjs) { expand = ckalloc(numWords * sizeof(int)); objvSpace = ckalloc(numWords * sizeof(Tcl_Obj *)); lineSpace = ckalloc(numWords * sizeof(int)); } expandRequested = 0; objv = objvSpace; lines = lineSpace; iPtr->cmdFramePtr = eeFramePtr->nextPtr; for (objectsUsed = 0, tokenPtr = parsePtr->tokenPtr; objectsUsed < numWords; objectsUsed++, tokenPtr += tokenPtr->numComponents+1) { /* * TIP #280. Track lines to current word. Save the information * on a per-word basis, signaling dynamic words as needed. * Make the information available to the recursively called * evaluator as well, including the type of context (source * vs. eval). */ TclAdvanceLines(&wordLine, wordStart, tokenPtr->start); TclAdvanceContinuations(&wordLine, &wordCLNext, tokenPtr->start - outerScript); wordStart = tokenPtr->start; lines[objectsUsed] = TclWordKnownAtCompileTime(tokenPtr, NULL) ? wordLine : -1; if (eeFramePtr->type == TCL_LOCATION_SOURCE) { iPtr->evalFlags |= TCL_EVAL_FILE; } code = TclSubstTokens(interp, tokenPtr+1, tokenPtr->numComponents, NULL, wordLine, wordCLNext, outerScript); iPtr->evalFlags = 0; if (code != TCL_OK) { break; } objv[objectsUsed] = Tcl_GetObjResult(interp); Tcl_IncrRefCount(objv[objectsUsed]); if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) { int numElements; code = TclListObjLength(interp, objv[objectsUsed], &numElements); if (code == TCL_ERROR) { /* * Attempt to expand a non-list. */ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (expanding word %d)", objectsUsed)); Tcl_DecrRefCount(objv[objectsUsed]); break; } expandRequested = 1; expand[objectsUsed] = 1; objectsNeeded += (numElements ? numElements : 1); } else { expand[objectsUsed] = 0; objectsNeeded++; } if (wordCLNext) { TclContinuationsEnterDerived(objv[objectsUsed], wordStart - outerScript, wordCLNext); } } /* for loop */ iPtr->cmdFramePtr = eeFramePtr; if (code != TCL_OK) { goto error; } if (expandRequested) { /* * Some word expansion was requested. Check for objv resize. */ Tcl_Obj **copy = objvSpace; int *lcopy = lineSpace; int wordIdx = numWords; int objIdx = objectsNeeded - 1; if ((numWords > minObjs) || (objectsNeeded > minObjs)) { objv = objvSpace = ckalloc(objectsNeeded * sizeof(Tcl_Obj *)); lines = lineSpace = ckalloc(objectsNeeded * sizeof(int)); } objectsUsed = 0; while (wordIdx--) { if (expand[wordIdx]) { int numElements; Tcl_Obj **elements, *temp = copy[wordIdx]; Tcl_ListObjGetElements(NULL, temp, &numElements, &elements); objectsUsed += numElements; while (numElements--) { lines[objIdx] = -1; objv[objIdx--] = elements[numElements]; Tcl_IncrRefCount(elements[numElements]); } Tcl_DecrRefCount(temp); } else { lines[objIdx] = lcopy[wordIdx]; objv[objIdx--] = copy[wordIdx]; objectsUsed++; } } objv += objIdx+1; if (copy != stackObjArray) { ckfree(copy); } if (lcopy != linesStack) { ckfree(lcopy); } } /* * Execute the command and free the objects for its words. * * TIP #280: Remember the command itself for 'info frame'. We * shorten the visible command by one char to exclude the * termination character, if necessary. Here is where we put our * frame on the stack of frames too. _After_ the nested commands * have been executed. */ eeFramePtr->cmd = parsePtr->commandStart; eeFramePtr->len = parsePtr->commandSize; if (parsePtr->term == parsePtr->commandStart + parsePtr->commandSize - 1) { eeFramePtr->len--; } eeFramePtr->nline = objectsUsed; eeFramePtr->line = lines; TclArgumentEnter(interp, objv, objectsUsed, eeFramePtr); code = Tcl_EvalObjv(interp, objectsUsed, objv, TCL_EVAL_NOERR | TCL_EVAL_SOURCE_IN_FRAME); TclArgumentRelease(interp, objv, objectsUsed); eeFramePtr->line = NULL; eeFramePtr->nline = 0; if (eeFramePtr->cmdObj) { Tcl_DecrRefCount(eeFramePtr->cmdObj); eeFramePtr->cmdObj = NULL; } if (code != TCL_OK) { goto error; } for (i = 0; i < objectsUsed; i++) { Tcl_DecrRefCount(objv[i]); } objectsUsed = 0; if (objvSpace != stackObjArray) { ckfree(objvSpace); objvSpace = stackObjArray; ckfree(lineSpace); lineSpace = linesStack; } /* * Free expand separately since objvSpace could have been * reallocated above. */ if (expand != expandStack) { ckfree(expand); expand = expandStack; } } /* * Advance to the next command in the script. * * TIP #280 Track Lines. Now we track how many lines were in the * executed command. */ next = parsePtr->commandStart + parsePtr->commandSize; bytesLeft -= next - p; p = next; TclAdvanceLines(&line, parsePtr->commandStart, p); Tcl_FreeParse(parsePtr); gotParse = 0; } while (bytesLeft > 0); iPtr->varFramePtr = savedVarFramePtr; code = TCL_OK; goto cleanup_return; error: /* * Generate and log various pieces of error information. */ if (iPtr->numLevels == 0) { if (code == TCL_RETURN) { code = TclUpdateReturnInfo(iPtr); } if ((code != TCL_OK) && (code != TCL_ERROR) && !allowExceptions) { ProcessUnexpectedResult(interp, code); code = TCL_ERROR; } } if ((code == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { commandLength = parsePtr->commandSize; if (parsePtr->term == parsePtr->commandStart + commandLength - 1) { /* * The terminator character (such as ; or ]) of the command where * the error occurred is the last character in the parsed command. * Reduce the length by one so that the error message doesn't * include the terminator character. */ commandLength -= 1; } Tcl_LogCommandInfo(interp, script, parsePtr->commandStart, commandLength); } posterror: iPtr->flags &= ~ERR_ALREADY_LOGGED; /* * Then free resources that had been allocated to the command. */ for (i = 0; i < objectsUsed; i++) { Tcl_DecrRefCount(objv[i]); } if (gotParse) { Tcl_FreeParse(parsePtr); } if (objvSpace != stackObjArray) { ckfree(objvSpace); ckfree(lineSpace); } if (expand != expandStack) { ckfree(expand); } iPtr->varFramePtr = savedVarFramePtr; cleanup_return: /* * TIP #280. Release the local CmdFrame, and its contents. */ iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr; if (eeFramePtr->type == TCL_LOCATION_SOURCE) { Tcl_DecrRefCount(eeFramePtr->data.eval.path); } TclStackFree(interp, linesStack); TclStackFree(interp, expandStack); TclStackFree(interp, stackObjArray); TclStackFree(interp, eeFramePtr); TclStackFree(interp, parsePtr); return code; } /* *---------------------------------------------------------------------- * * TclAdvanceLines -- * * This function is a helper which counts the number of lines in a block * of text and advances an external counter. * * Results: * None. * * Side effects: * The specified counter is advanced per the number of lines found. * * TIP #280 *---------------------------------------------------------------------- */ void TclAdvanceLines( int *line, const char *start, const char *end) { register const char *p; for (p = start; p < end; p++) { if (*p == '\n') { (*line)++; } } } /* *---------------------------------------------------------------------- * * TclAdvanceContinuations -- * * This procedure is a helper which counts the number of continuation * lines (CL) in a block of text using a table of CL locations and * advances an external counter, and the pointer into the table. * * Results: * None. * * Side effects: * The specified counter is advanced per the number of continuation lines * found. * * TIP #280 *---------------------------------------------------------------------- */ void TclAdvanceContinuations( int *line, int **clNextPtrPtr, int loc) { /* * Track the invisible continuation lines embedded in a script, if any. * Here they are just spaces (already). They were removed by * TclSubstTokens via TclParseBackslash. * * *clNextPtrPtr <=> We have continuation lines to track. * **clNextPtrPtr >= 0 <=> We are not beyond the last possible location. * loc >= **clNextPtrPtr <=> We stepped beyond the current cont. line. */ while (*clNextPtrPtr && (**clNextPtrPtr >= 0) && (loc >= **clNextPtrPtr)) { /* * We just stepped over an invisible continuation line. Adjust the * line counter and step to the table entry holding the location of * the next continuation line to track. */ (*line)++; (*clNextPtrPtr)++; } } /* *---------------------------------------------------------------------- * Note: The whole data structure access for argument location tracking is * hidden behind these three functions. The only parts open are the lineLAPtr * field in the Interp structure. The CFWord definition is internal to here. * Should make it easier to redo the data structures if we find something more * space/time efficient. */ /* *---------------------------------------------------------------------- * * TclArgumentEnter -- * * This procedure is a helper for the TIP #280 uplevel extension. It * enters location references for the arguments of a command to be * invoked. Only the first entry has the actual data, further entries * simply count the usage up. * * Results: * None. * * Side effects: * May allocate memory. * * TIP #280 *---------------------------------------------------------------------- */ void TclArgumentEnter( Tcl_Interp *interp, Tcl_Obj **objv, int objc, CmdFrame *cfPtr) { Interp *iPtr = (Interp *) interp; int new, i; Tcl_HashEntry *hPtr; CFWord *cfwPtr; for (i = 1; i < objc; i++) { /* * Ignore argument words without line information (= dynamic). If they * are variables they may have location information associated with * that, either through globally recorded 'set' invokations, or * literals in bytecode. Eitehr way there is no need to record * something here. */ if (cfPtr->line[i] < 0) { continue; } hPtr = Tcl_CreateHashEntry(iPtr->lineLAPtr, objv[i], &new); if (new) { /* * The word is not on the stack yet, remember the current location * and initialize references. */ cfwPtr = ckalloc(sizeof(CFWord)); cfwPtr->framePtr = cfPtr; cfwPtr->word = i; cfwPtr->refCount = 1; Tcl_SetHashValue(hPtr, cfwPtr); } else { /* * The word is already on the stack, its current location is not * relevant. Just remember the reference to prevent early removal. */ cfwPtr = Tcl_GetHashValue(hPtr); cfwPtr->refCount++; } } } /* *---------------------------------------------------------------------- * * TclArgumentRelease -- * * This procedure is a helper for the TIP #280 uplevel extension. It * removes the location references for the arguments of a command just * done. Usage is counted down, the data is removed only when no user is * left over. * * Results: * None. * * Side effects: * May release memory. * * TIP #280 *---------------------------------------------------------------------- */ void TclArgumentRelease( Tcl_Interp *interp, Tcl_Obj **objv, int objc) { Interp *iPtr = (Interp *) interp; int i; for (i = 1; i < objc; i++) { CFWord *cfwPtr; Tcl_HashEntry *hPtr = Tcl_FindHashEntry(iPtr->lineLAPtr, (char *) objv[i]); if (!hPtr) { continue; } cfwPtr = Tcl_GetHashValue(hPtr); cfwPtr->refCount--; if (cfwPtr->refCount > 0) { continue; } ckfree(cfwPtr); Tcl_DeleteHashEntry(hPtr); } } /* *---------------------------------------------------------------------- * * TclArgumentBCEnter -- * * This procedure is a helper for the TIP #280 uplevel extension. It * enters location references for the literal arguments of commands in * bytecode about to be invoked. Only the first entry has the actual * data, further entries simply count the usage up. * * Results: * None. * * Side effects: * May allocate memory. * * TIP #280 *---------------------------------------------------------------------- */ void TclArgumentBCEnter( Tcl_Interp *interp, Tcl_Obj *objv[], int objc, void *codePtr, CmdFrame *cfPtr, int cmd, int pc) { ExtCmdLoc *eclPtr; int word; ECL *ePtr; CFWordBC *lastPtr = NULL; Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr, (char *) codePtr); if (!hePtr) { return; } eclPtr = Tcl_GetHashValue(hePtr); ePtr = &eclPtr->loc[cmd]; /* * ePtr->nline is the number of words originally parsed. * * objc is the number of elements getting invoked. * * If they are not the same, we arrived here by compiling an * ensemble dispatch. Ensemble subcommands that lead to script * evaluation are not supposed to get compiled, because a command * such as [info level] in the script can expose some of the dispatch * shenanigans. This means that we don't have to tend to the * housekeeping, and can escape now. */ if (ePtr->nline != objc) { return; } /* * Having disposed of the ensemble cases, we can state... * A few truths ... * (1) ePtr->nline == objc * (2) (ePtr->line[word] < 0) => !literal, for all words * (3) (word == 0) => !literal * * Item (2) is why we can use objv to get the literals, and do not * have to save them at compile time. */ for (word = 1; word < objc; word++) { if (ePtr->line[word] >= 0) { int isnew; Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(iPtr->lineLABCPtr, objv[word], &isnew); CFWordBC *cfwPtr = ckalloc(sizeof(CFWordBC)); cfwPtr->framePtr = cfPtr; cfwPtr->obj = objv[word]; cfwPtr->pc = pc; cfwPtr->word = word; cfwPtr->nextPtr = lastPtr; lastPtr = cfwPtr; if (isnew) { /* * The word is not on the stack yet, remember the current * location and initialize references. */ cfwPtr->prevPtr = NULL; } else { /* * The object is already on the stack, however it may have * a different location now (literal sharing may map * multiple location to a single Tcl_Obj*. Save the old * information in the new structure. */ cfwPtr->prevPtr = Tcl_GetHashValue(hPtr); } Tcl_SetHashValue(hPtr, cfwPtr); } } /* for */ cfPtr->litarg = lastPtr; } /* *---------------------------------------------------------------------- * * TclArgumentBCRelease -- * * This procedure is a helper for the TIP #280 uplevel extension. It * removes the location references for the literal arguments of commands * in bytecode just done. Usage is counted down, the data is removed only * when no user is left over. * * Results: * None. * * Side effects: * May release memory. * * TIP #280 *---------------------------------------------------------------------- */ void TclArgumentBCRelease( Tcl_Interp *interp, CmdFrame *cfPtr) { Interp *iPtr = (Interp *) interp; CFWordBC *cfwPtr = (CFWordBC *) cfPtr->litarg; while (cfwPtr) { CFWordBC *nextPtr = cfwPtr->nextPtr; Tcl_HashEntry *hPtr = Tcl_FindHashEntry(iPtr->lineLABCPtr, (char *) cfwPtr->obj); CFWordBC *xPtr = Tcl_GetHashValue(hPtr); if (xPtr != cfwPtr) { Tcl_Panic("TclArgumentBC Enter/Release Mismatch"); } if (cfwPtr->prevPtr) { Tcl_SetHashValue(hPtr, cfwPtr->prevPtr); } else { Tcl_DeleteHashEntry(hPtr); } ckfree(cfwPtr); cfwPtr = nextPtr; } cfPtr->litarg = NULL; } /* *---------------------------------------------------------------------- * * TclArgumentGet -- * * This procedure is a helper for the TIP #280 uplevel extension. It * finds the location references for a Tcl_Obj, if any. * * Results: * None. * * Side effects: * Writes found location information into the result arguments. * * TIP #280 *---------------------------------------------------------------------- */ void TclArgumentGet( Tcl_Interp *interp, Tcl_Obj *obj, CmdFrame **cfPtrPtr, int *wordPtr) { Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hPtr; CmdFrame *framePtr; /* * An object which either has no string rep or else is a canonical list is * guaranteed to have been generated dynamically: bail out, this cannot * have a usable absolute location. _Do not touch_ the information the set * up by the caller. It knows better than us. */ if ((obj->bytes == NULL) || TclListObjIsCanonical(obj)) { return; } /* * First look for location information recorded in the argument * stack. That is nearest. */ hPtr = Tcl_FindHashEntry(iPtr->lineLAPtr, (char *) obj); if (hPtr) { CFWord *cfwPtr = Tcl_GetHashValue(hPtr); *wordPtr = cfwPtr->word; *cfPtrPtr = cfwPtr->framePtr; return; } /* * Check if the Tcl_Obj has location information as a bytecode literal, in * that stack. */ hPtr = Tcl_FindHashEntry(iPtr->lineLABCPtr, (char *) obj); if (hPtr) { CFWordBC *cfwPtr = Tcl_GetHashValue(hPtr); framePtr = cfwPtr->framePtr; framePtr->data.tebc.pc = (char *) (((ByteCode *) framePtr->data.tebc.codePtr)->codeStart + cfwPtr->pc); *cfPtrPtr = cfwPtr->framePtr; *wordPtr = cfwPtr->word; return; } } /* *---------------------------------------------------------------------- * * Tcl_Eval -- * * Execute a Tcl command in a string. This function executes the script * directly, rather than compiling it to bytecodes. Before the arrival of * the bytecode compiler in Tcl 8.0 Tcl_Eval was the main function used * for executing Tcl commands, but nowadays it isn't used much. * * Results: * The return value is one of the return codes defined in tcl.h (such as * TCL_OK), and interp's result contains a value to supplement the return * code. The value of the result will persist only until the next call to * Tcl_Eval or Tcl_EvalObj: you must copy it or lose it! * * Side effects: * Can be almost arbitrary, depending on the commands in the script. * *---------------------------------------------------------------------- */ #undef Tcl_Eval int Tcl_Eval( Tcl_Interp *interp, /* Token for command interpreter (returned by * previous call to Tcl_CreateInterp). */ const char *script) /* Pointer to TCL command to execute. */ { int code = Tcl_EvalEx(interp, script, -1, 0); /* * For backwards compatibility with old C code that predates the object * system in Tcl 8.0, we have to mirror the object result back into the * string result (some callers may expect it there). */ (void) Tcl_GetStringResult(interp); return code; } /* *---------------------------------------------------------------------- * * Tcl_EvalObj, Tcl_GlobalEvalObj -- * * These functions are deprecated but we keep them around for backwards * compatibility reasons. * * Results: * See the functions they call. * * Side effects: * See the functions they call. * *---------------------------------------------------------------------- */ #undef Tcl_EvalObj int Tcl_EvalObj( Tcl_Interp *interp, Tcl_Obj *objPtr) { return Tcl_EvalObjEx(interp, objPtr, 0); } #undef Tcl_GlobalEvalObj int Tcl_GlobalEvalObj( Tcl_Interp *interp, Tcl_Obj *objPtr) { return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL); } /* *---------------------------------------------------------------------- * * Tcl_EvalObjEx, TclEvalObjEx -- * * Execute Tcl commands stored in a Tcl object. These commands are * compiled into bytecodes if necessary, unless TCL_EVAL_DIRECT is * specified. * * If the flag TCL_EVAL_DIRECT is passed in, the value of invoker * must be NULL. Support for non-NULL invokers in that mode has * been removed since it was unused and untested. Failure to * follow this limitation will lead to an assertion panic. * * Results: * The return value is one of the return codes defined in tcl.h (such as * TCL_OK), and the interpreter's result contains a value to supplement * the return code. * * Side effects: * The object is converted, if necessary, to a ByteCode object that holds * the bytecode instructions for the commands. Executing the commands * will almost certainly have side effects that depend on those commands. * * TIP #280 : Keep public API, internally extended API. *---------------------------------------------------------------------- */ int Tcl_EvalObjEx( Tcl_Interp *interp, /* Token for command interpreter (returned by * a previous call to Tcl_CreateInterp). */ register Tcl_Obj *objPtr, /* Pointer to object containing commands to * execute. */ int flags) /* Collection of OR-ed bits that control the * evaluation of the script. Supported values * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */ { return TclEvalObjEx(interp, objPtr, flags, NULL, 0); } int TclEvalObjEx( Tcl_Interp *interp, /* Token for command interpreter (returned by * a previous call to Tcl_CreateInterp). */ register Tcl_Obj *objPtr, /* Pointer to object containing commands to * execute. */ int flags, /* Collection of OR-ed bits that control the * evaluation of the script. Supported values * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */ const CmdFrame *invoker, /* Frame of the command doing the eval. */ int word) /* Index of the word which is in objPtr. */ { int result = TCL_OK; NRE_callback *rootPtr = TOP_CB(interp); result = TclNREvalObjEx(interp, objPtr, flags, invoker, word); return TclNRRunCallbacks(interp, result, rootPtr); } int TclNREvalObjEx( Tcl_Interp *interp, /* Token for command interpreter (returned by * a previous call to Tcl_CreateInterp). */ register Tcl_Obj *objPtr, /* Pointer to object containing commands to * execute. */ int flags, /* Collection of OR-ed bits that control the * evaluation of the script. Supported values * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */ const CmdFrame *invoker, /* Frame of the command doing the eval. */ int word) /* Index of the word which is in objPtr. */ { Interp *iPtr = (Interp *) interp; int result; /* * This function consists of three independent blocks for: direct * evaluation of canonical lists, compilation and bytecode execution and * finally direct evaluation. Precisely one of these blocks will be run. */ if (TclListObjIsCanonical(objPtr)) { CmdFrame *eoFramePtr = NULL; int objc; Tcl_Obj *listPtr, **objv; /* * Canonical List Optimization: In this case, we * can safely use Tcl_EvalObjv instead and get an appreciable * improvement in execution speed. This is because it allows us to * avoid a setFromAny step that would just pack everything into a * string and back out again. * * This also preserves any associations between list elements and * location information for such elements. */ /* * Shimmer protection! Always pass an unshared obj. The caller could * incr the refCount of objPtr AFTER calling us! To be completely safe * we always make a copy. The callback takes care od the refCounts for * both listPtr and objPtr. * * TODO: Create a test to demo this need, or eliminate it. * FIXME OPT: preserve just the internal rep? */ Tcl_IncrRefCount(objPtr); listPtr = TclListObjCopy(interp, objPtr); Tcl_IncrRefCount(listPtr); if (word != INT_MIN) { /* * TIP #280 Structures for tracking lines. As we know that this is * dynamic execution we ignore the invoker, even if known. * * TIP #280. We do _not_ compute all the line numbers for the * words in the command. For the eval of a pure list the most * sensible choice is to put all words on line 1. Given that we * neither need memory for them nor compute anything. 'line' is * left NULL. The two places using this information (TclInfoFrame, * and TclInitCompileEnv), are special-cased to use the proper * line number directly instead of accessing the 'line' array. * * Note that we use (word==INTMIN) to signal that no command frame * should be pushed, as needed by alias and ensemble redirections. */ eoFramePtr = TclStackAlloc(interp, sizeof(CmdFrame)); eoFramePtr->nline = 0; eoFramePtr->line = NULL; eoFramePtr->type = TCL_LOCATION_EVAL; eoFramePtr->level = (iPtr->cmdFramePtr == NULL? 1 : iPtr->cmdFramePtr->level + 1); eoFramePtr->framePtr = iPtr->framePtr; eoFramePtr->nextPtr = iPtr->cmdFramePtr; eoFramePtr->cmdObj = objPtr; eoFramePtr->cmd = NULL; eoFramePtr->len = 0; eoFramePtr->data.eval.path = NULL; iPtr->cmdFramePtr = eoFramePtr; flags |= TCL_EVAL_SOURCE_IN_FRAME; } TclMarkTailcall(interp); TclNRAddCallback(interp, TEOEx_ListCallback, listPtr, eoFramePtr, objPtr, NULL); ListObjGetElements(listPtr, objc, objv); return TclNREvalObjv(interp, objc, objv, flags, NULL); } if (!(flags & TCL_EVAL_DIRECT)) { /* * Let the compiler/engine subsystem do the evaluation. * * TIP #280 The invoker provides us with the context for the script. * We transfer this to the byte code compiler. */ int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS); ByteCode *codePtr; CallFrame *savedVarFramePtr = NULL; /* Saves old copy of * iPtr->varFramePtr in case * TCL_EVAL_GLOBAL was set. */ if (TclInterpReady(interp) != TCL_OK) { return TCL_ERROR; } if (flags & TCL_EVAL_GLOBAL) { savedVarFramePtr = iPtr->varFramePtr; iPtr->varFramePtr = iPtr->rootFramePtr; } Tcl_IncrRefCount(objPtr); codePtr = TclCompileObj(interp, objPtr, invoker, word); TclNRAddCallback(interp, TEOEx_ByteCodeCallback, savedVarFramePtr, objPtr, INT2PTR(allowExceptions), NULL); return TclNRExecuteByteCode(interp, codePtr); } { /* * We're not supposed to use the compiler or byte-code * interpreter. Let Tcl_EvalEx evaluate the command directly (and * probably more slowly). */ const char *script; int numSrcBytes; /* * Now we check if we have data about invisible continuation lines for * the script, and make it available to the direct script parser and * evaluator we are about to call, if so. * * It may be possible that the script Tcl_Obj* can be free'd while the * evaluator is using it, leading to the release of the associated * ContLineLoc structure as well. To ensure that the latter doesn't * happen we set a lock on it. We release this lock later in this * function, after the evaluator is done. The relevant "lineCLPtr" * hashtable is managed in the file "tclObj.c". * * Another important action is to save (and later restore) the * continuation line information of the caller, in case we are * executing nested commands in the eval/direct path. */ ContLineLoc *saveCLLocPtr = iPtr->scriptCLLocPtr; assert(invoker == NULL); iPtr->scriptCLLocPtr = TclContinuationsGet(objPtr); Tcl_IncrRefCount(objPtr); script = Tcl_GetStringFromObj(objPtr, &numSrcBytes); result = Tcl_EvalEx(interp, script, numSrcBytes, flags); TclDecrRefCount(objPtr); iPtr->scriptCLLocPtr = saveCLLocPtr; return result; } } static int TEOEx_ByteCodeCallback( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; CallFrame *savedVarFramePtr = data[0]; Tcl_Obj *objPtr = data[1]; int allowExceptions = PTR2INT(data[2]); if (iPtr->numLevels == 0) { if (result == TCL_RETURN) { result = TclUpdateReturnInfo(iPtr); } if ((result != TCL_OK) && (result != TCL_ERROR) && !allowExceptions) { const char *script; int numSrcBytes; ProcessUnexpectedResult(interp, result); result = TCL_ERROR; script = Tcl_GetStringFromObj(objPtr, &numSrcBytes); Tcl_LogCommandInfo(interp, script, script, numSrcBytes); } /* * We are returning to level 0, so should call TclResetCancellation. * Let us just unset the flags inline. */ TclUnsetCancelFlags(iPtr); } iPtr->evalFlags = 0; /* * Restore the callFrame if this was a TCL_EVAL_GLOBAL. */ if (savedVarFramePtr) { iPtr->varFramePtr = savedVarFramePtr; } TclDecrRefCount(objPtr); return result; } static int TEOEx_ListCallback( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_Obj *listPtr = data[0]; CmdFrame *eoFramePtr = data[1]; Tcl_Obj *objPtr = data[2]; /* * Remove the cmdFrame */ if (eoFramePtr) { iPtr->cmdFramePtr = eoFramePtr->nextPtr; TclStackFree(interp, eoFramePtr); } TclDecrRefCount(objPtr); TclDecrRefCount(listPtr); return result; } /* *---------------------------------------------------------------------- * * ProcessUnexpectedResult -- * * Function called by Tcl_EvalObj to set the interpreter's result value * to an appropriate error message when the code it evaluates returns an * unexpected result code (not TCL_OK and not TCL_ERROR) to the topmost * evaluation level. * * Results: * None. * * Side effects: * The interpreter result is set to an error message appropriate to the * result code. * *---------------------------------------------------------------------- */ static void ProcessUnexpectedResult( Tcl_Interp *interp, /* The interpreter in which the unexpected * result code was returned. */ int returnCode) /* The unexpected result code. */ { char buf[TCL_INTEGER_SPACE]; Tcl_ResetResult(interp); if (returnCode == TCL_BREAK) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "invoked \"break\" outside of a loop", -1)); } else if (returnCode == TCL_CONTINUE) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "invoked \"continue\" outside of a loop", -1)); } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "command returned bad code: %d", returnCode)); } sprintf(buf, "%d", returnCode); Tcl_SetErrorCode(interp, "TCL", "UNEXPECTED_RESULT_CODE", buf, NULL); } /* *--------------------------------------------------------------------------- * * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean -- * * Functions to evaluate an expression and return its value in a * particular form. * * Results: * Each of the functions below returns a standard Tcl result. If an error * occurs then an error message is left in the interp's result. Otherwise * the value of the expression, in the appropriate form, is stored at * *ptr. If the expression had a result that was incompatible with the * desired form then an error is returned. * * Side effects: * None. * *--------------------------------------------------------------------------- */ int Tcl_ExprLong( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ const char *exprstring, /* Expression to evaluate. */ long *ptr) /* Where to store result. */ { register Tcl_Obj *exprPtr; int result = TCL_OK; if (*exprstring == '\0') { /* * Legacy compatibility - return 0 for the zero-length string. */ *ptr = 0; } else { exprPtr = Tcl_NewStringObj(exprstring, -1); Tcl_IncrRefCount(exprPtr); result = Tcl_ExprLongObj(interp, exprPtr, ptr); Tcl_DecrRefCount(exprPtr); if (result != TCL_OK) { (void) Tcl_GetStringResult(interp); } } return result; } int Tcl_ExprDouble( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ const char *exprstring, /* Expression to evaluate. */ double *ptr) /* Where to store result. */ { register Tcl_Obj *exprPtr; int result = TCL_OK; if (*exprstring == '\0') { /* * Legacy compatibility - return 0 for the zero-length string. */ *ptr = 0.0; } else { exprPtr = Tcl_NewStringObj(exprstring, -1); Tcl_IncrRefCount(exprPtr); result = Tcl_ExprDoubleObj(interp, exprPtr, ptr); Tcl_DecrRefCount(exprPtr); /* Discard the expression object. */ if (result != TCL_OK) { (void) Tcl_GetStringResult(interp); } } return result; } int Tcl_ExprBoolean( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ const char *exprstring, /* Expression to evaluate. */ int *ptr) /* Where to store 0/1 result. */ { if (*exprstring == '\0') { /* * An empty string. Just set the result boolean to 0 (false). */ *ptr = 0; return TCL_OK; } else { int result; Tcl_Obj *exprPtr = Tcl_NewStringObj(exprstring, -1); Tcl_IncrRefCount(exprPtr); result = Tcl_ExprBooleanObj(interp, exprPtr, ptr); Tcl_DecrRefCount(exprPtr); if (result != TCL_OK) { /* * Move the interpreter's object result to the string result, then * reset the object result. */ (void) Tcl_GetStringResult(interp); } return result; } } /* *-------------------------------------------------------------- * * Tcl_ExprLongObj, Tcl_ExprDoubleObj, Tcl_ExprBooleanObj -- * * Functions to evaluate an expression in an object and return its value * in a particular form. * * Results: * Each of the functions below returns a standard Tcl result object. If * an error occurs then an error message is left in the interpreter's * result. Otherwise the value of the expression, in the appropriate * form, is stored at *ptr. If the expression had a result that was * incompatible with the desired form then an error is returned. * * Side effects: * None. * *-------------------------------------------------------------- */ int Tcl_ExprLongObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ register Tcl_Obj *objPtr, /* Expression to evaluate. */ long *ptr) /* Where to store long result. */ { Tcl_Obj *resultPtr; int result, type; double d; ClientData internalPtr; result = Tcl_ExprObj(interp, objPtr, &resultPtr); if (result != TCL_OK) { return TCL_ERROR; } if (TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type)!=TCL_OK) { return TCL_ERROR; } switch (type) { case TCL_NUMBER_DOUBLE: { mp_int big; d = *((const double *) internalPtr); Tcl_DecrRefCount(resultPtr); if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) { return TCL_ERROR; } resultPtr = Tcl_NewBignumObj(&big); /* FALLTHROUGH */ } case TCL_NUMBER_LONG: case TCL_NUMBER_WIDE: case TCL_NUMBER_BIG: result = TclGetLongFromObj(interp, resultPtr, ptr); break; case TCL_NUMBER_NAN: Tcl_GetDoubleFromObj(interp, resultPtr, &d); result = TCL_ERROR; } Tcl_DecrRefCount(resultPtr);/* Discard the result object. */ return result; } int Tcl_ExprDoubleObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ register Tcl_Obj *objPtr, /* Expression to evaluate. */ double *ptr) /* Where to store double result. */ { Tcl_Obj *resultPtr; int result, type; ClientData internalPtr; result = Tcl_ExprObj(interp, objPtr, &resultPtr); if (result != TCL_OK) { return TCL_ERROR; } result = TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type); if (result == TCL_OK) { switch (type) { case TCL_NUMBER_NAN: #ifndef ACCEPT_NAN result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr); break; #endif case TCL_NUMBER_DOUBLE: *ptr = *((const double *) internalPtr); result = TCL_OK; break; default: result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr); } } Tcl_DecrRefCount(resultPtr);/* Discard the result object. */ return result; } int Tcl_ExprBooleanObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ register Tcl_Obj *objPtr, /* Expression to evaluate. */ int *ptr) /* Where to store 0/1 result. */ { Tcl_Obj *resultPtr; int result; result = Tcl_ExprObj(interp, objPtr, &resultPtr); if (result == TCL_OK) { result = Tcl_GetBooleanFromObj(interp, resultPtr, ptr); Tcl_DecrRefCount(resultPtr); /* Discard the result object. */ } return result; } /* *---------------------------------------------------------------------- * * TclObjInvokeNamespace -- * * Object version: Invokes a Tcl command, given an objv/objc, from either * the exposed or hidden set of commands in the given interpreter. * * NOTE: The command is invoked in the global stack frame of the * interpreter or namespace, thus it cannot see any current state on the * stack of that interpreter. * * Results: * A standard Tcl result. * * Side effects: * Whatever the command does. * *---------------------------------------------------------------------- */ int TclObjInvokeNamespace( Tcl_Interp *interp, /* Interpreter in which command is to be * invoked. */ int objc, /* Count of arguments. */ Tcl_Obj *const objv[], /* Argument objects; objv[0] points to the * name of the command to invoke. */ Tcl_Namespace *nsPtr, /* The namespace to use. */ int flags) /* Combination of flags controlling the call: * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN, * or TCL_INVOKE_NO_TRACEBACK. */ { int result; Tcl_CallFrame *framePtr; /* * Make the specified namespace the current namespace and invoke the * command. */ (void) TclPushStackFrame(interp, &framePtr, nsPtr, /*isProcFrame*/0); result = TclObjInvoke(interp, objc, objv, flags); TclPopStackFrame(interp); return result; } /* *---------------------------------------------------------------------- * * TclObjInvoke -- * * Invokes a Tcl command, given an objv/objc, from either the exposed or * the hidden sets of commands in the given interpreter. * * Results: * A standard Tcl object result. * * Side effects: * Whatever the command does. * *---------------------------------------------------------------------- */ int TclObjInvoke( Tcl_Interp *interp, /* Interpreter in which command is to be * invoked. */ int objc, /* Count of arguments. */ Tcl_Obj *const objv[], /* Argument objects; objv[0] points to the * name of the command to invoke. */ int flags) /* Combination of flags controlling the call: * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN, * or TCL_INVOKE_NO_TRACEBACK. */ { if (interp == NULL) { return TCL_ERROR; } if ((objc < 1) || (objv == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "illegal argument vector", -1)); return TCL_ERROR; } if ((flags & TCL_INVOKE_HIDDEN) == 0) { Tcl_Panic("TclObjInvoke: called without TCL_INVOKE_HIDDEN"); } return Tcl_NRCallObjProc(interp, TclNRInvoke, NULL, objc, objv); } int TclNRInvoke( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { register Interp *iPtr = (Interp *) interp; Tcl_HashTable *hTblPtr; /* Table of hidden commands. */ const char *cmdName; /* Name of the command from objv[0]. */ Tcl_HashEntry *hPtr = NULL; Command *cmdPtr; cmdName = TclGetString(objv[0]); hTblPtr = iPtr->hiddenCmdTablePtr; if (hTblPtr != NULL) { hPtr = Tcl_FindHashEntry(hTblPtr, cmdName); } if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid hidden command name \"%s\"", cmdName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "HIDDENTOKEN", cmdName, NULL); return TCL_ERROR; } cmdPtr = Tcl_GetHashValue(hPtr); /* Avoid the exception-handling brain damage when numLevels == 0 . */ iPtr->numLevels++; Tcl_NRAddCallback(interp, NRPostInvoke, NULL, NULL, NULL, NULL); /* * Normal command resolution of objv[0] isn't going to find cmdPtr. * That's the whole point of **hidden** commands. So tell the * Eval core machinery not to even try (and risk finding something wrong). */ return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NORESOLVE, cmdPtr); } static int NRPostInvoke( ClientData clientData[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *)interp; iPtr->numLevels--; return result; } /* *--------------------------------------------------------------------------- * * Tcl_ExprString -- * * Evaluate an expression in a string and return its value in string * form. * * Results: * A standard Tcl result. If the result is TCL_OK, then the interp's * result is set to the string value of the expression. If the result is * TCL_ERROR, then the interp's result contains an error message. * * Side effects: * A Tcl object is allocated to hold a copy of the expression string. * This expression object is passed to Tcl_ExprObj and then deallocated. * *--------------------------------------------------------------------------- */ int Tcl_ExprString( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ const char *expr) /* Expression to evaluate. */ { int code = TCL_OK; if (expr[0] == '\0') { /* * An empty string. Just set the interpreter's result to 0. */ Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); } else { Tcl_Obj *resultPtr, *exprObj = Tcl_NewStringObj(expr, -1); Tcl_IncrRefCount(exprObj); code = Tcl_ExprObj(interp, exprObj, &resultPtr); Tcl_DecrRefCount(exprObj); if (code == TCL_OK) { Tcl_SetObjResult(interp, resultPtr); Tcl_DecrRefCount(resultPtr); } } /* * Force the string rep of the interp result. */ (void) Tcl_GetStringResult(interp); return code; } /* *---------------------------------------------------------------------- * * Tcl_AppendObjToErrorInfo -- * * Add a Tcl_Obj value to the errorInfo field that describes the current * error. * * Results: * None. * * Side effects: * The value of the Tcl_obj is appended to the errorInfo field. If we are * just starting to log an error, errorInfo is initialized from the error * message in the interpreter's result. * *---------------------------------------------------------------------- */ #undef Tcl_AddObjErrorInfo void Tcl_AppendObjToErrorInfo( Tcl_Interp *interp, /* Interpreter to which error information * pertains. */ Tcl_Obj *objPtr) /* Message to record. */ { int length; const char *message = TclGetStringFromObj(objPtr, &length); Tcl_IncrRefCount(objPtr); Tcl_AddObjErrorInfo(interp, message, length); Tcl_DecrRefCount(objPtr); } /* *---------------------------------------------------------------------- * * Tcl_AddErrorInfo -- * * Add information to the errorInfo field that describes the current * error. * * Results: * None. * * Side effects: * The contents of message are appended to the errorInfo field. If we are * just starting to log an error, errorInfo is initialized from the error * message in the interpreter's result. * *---------------------------------------------------------------------- */ #undef Tcl_AddErrorInfo void Tcl_AddErrorInfo( Tcl_Interp *interp, /* Interpreter to which error information * pertains. */ const char *message) /* Message to record. */ { Tcl_AddObjErrorInfo(interp, message, -1); } /* *---------------------------------------------------------------------- * * Tcl_AddObjErrorInfo -- * * Add information to the errorInfo field that describes the current * error. This routine differs from Tcl_AddErrorInfo by taking a byte * pointer and length. * * Results: * None. * * Side effects: * "length" bytes from "message" are appended to the errorInfo field. If * "length" is negative, use bytes up to the first NULL byte. If we are * just starting to log an error, errorInfo is initialized from the error * message in the interpreter's result. * *---------------------------------------------------------------------- */ void Tcl_AddObjErrorInfo( Tcl_Interp *interp, /* Interpreter to which error information * pertains. */ const char *message, /* Points to the first byte of an array of * bytes of the message. */ int length) /* The number of bytes in the message. If < 0, * then append all bytes up to a NULL byte. */ { register Interp *iPtr = (Interp *) interp; /* * If we are just starting to log an error, errorInfo is initialized from * the error message in the interpreter's result. */ iPtr->flags |= ERR_LEGACY_COPY; if (iPtr->errorInfo == NULL) { if (iPtr->result[0] != 0) { /* * The interp's string result is set, apparently by some extension * making a deprecated direct write to it. That extension may * expect interp->result to continue to be set, so we'll take * special pains to avoid clearing it, until we drop support for * interp->result completely. */ iPtr->errorInfo = Tcl_NewStringObj(iPtr->result, -1); } else { iPtr->errorInfo = iPtr->objResultPtr; } Tcl_IncrRefCount(iPtr->errorInfo); if (!iPtr->errorCode) { Tcl_SetErrorCode(interp, "NONE", NULL); } } /* * Now append "message" to the end of errorInfo. */ if (length != 0) { if (Tcl_IsShared(iPtr->errorInfo)) { Tcl_DecrRefCount(iPtr->errorInfo); iPtr->errorInfo = Tcl_DuplicateObj(iPtr->errorInfo); Tcl_IncrRefCount(iPtr->errorInfo); } Tcl_AppendToObj(iPtr->errorInfo, message, length); } } /* *--------------------------------------------------------------------------- * * Tcl_VarEvalVA -- * * Given a variable number of string arguments, concatenate them all * together and execute the result as a Tcl command. * * Results: * A standard Tcl return result. An error message or other result may be * left in the interp's result. * * Side effects: * Depends on what was done by the command. * *--------------------------------------------------------------------------- */ int Tcl_VarEvalVA( Tcl_Interp *interp, /* Interpreter in which to evaluate command */ va_list argList) /* Variable argument list. */ { Tcl_DString buf; char *string; int result; /* * Copy the strings one after the other into a single larger string. Use * stack-allocated space for small commands, but if the command gets too * large than call ckalloc to create the space. */ Tcl_DStringInit(&buf); while (1) { string = va_arg(argList, char *); if (string == NULL) { break; } Tcl_DStringAppend(&buf, string, -1); } result = Tcl_Eval(interp, Tcl_DStringValue(&buf)); Tcl_DStringFree(&buf); return result; } /* *---------------------------------------------------------------------- * * Tcl_VarEval -- * * Given a variable number of string arguments, concatenate them all * together and execute the result as a Tcl command. * * Results: * A standard Tcl return result. An error message or other result may be * left in interp->result. * * Side effects: * Depends on what was done by the command. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_VarEval( Tcl_Interp *interp, ...) { va_list argList; int result; va_start(argList, interp); result = Tcl_VarEvalVA(interp, argList); va_end(argList); return result; } /* *---------------------------------------------------------------------- * * Tcl_GlobalEval -- * * Evaluate a command at global level in an interpreter. * * Results: * A standard Tcl result is returned, and the interp's result is modified * accordingly. * * Side effects: * The command string is executed in interp, and the execution is carried * out in the variable context of global level (no functions active), * just as if an "uplevel #0" command were being executed. * *---------------------------------------------------------------------- */ #undef Tcl_GlobalEval int Tcl_GlobalEval( Tcl_Interp *interp, /* Interpreter in which to evaluate * command. */ const char *command) /* Command to evaluate. */ { register Interp *iPtr = (Interp *) interp; int result; CallFrame *savedVarFramePtr; savedVarFramePtr = iPtr->varFramePtr; iPtr->varFramePtr = iPtr->rootFramePtr; result = Tcl_Eval(interp, command); iPtr->varFramePtr = savedVarFramePtr; return result; } /* *---------------------------------------------------------------------- * * Tcl_SetRecursionLimit -- * * Set the maximum number of recursive calls that may be active for an * interpreter at once. * * Results: * The return value is the old limit on nesting for interp. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_SetRecursionLimit( Tcl_Interp *interp, /* Interpreter whose nesting limit is to be * set. */ int depth) /* New value for maximimum depth. */ { Interp *iPtr = (Interp *) interp; int old; old = iPtr->maxNestingDepth; if (depth > 0) { iPtr->maxNestingDepth = depth; } return old; } /* *---------------------------------------------------------------------- * * Tcl_AllowExceptions -- * * Sets a flag in an interpreter so that exceptions can occur in the next * call to Tcl_Eval without them being turned into errors. * * Results: * None. * * Side effects: * The TCL_ALLOW_EXCEPTIONS flag gets set in the interpreter's evalFlags * structure. See the reference documentation for more details. * *---------------------------------------------------------------------- */ void Tcl_AllowExceptions( Tcl_Interp *interp) /* Interpreter in which to set flag. */ { Interp *iPtr = (Interp *) interp; iPtr->evalFlags |= TCL_ALLOW_EXCEPTIONS; } /* *---------------------------------------------------------------------- * * Tcl_GetVersion -- * * Get the Tcl major, minor, and patchlevel version numbers and the * release type. A patch is a release type TCL_FINAL_RELEASE with a * patchLevel > 0. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_GetVersion( int *majorV, int *minorV, int *patchLevelV, int *type) { if (majorV != NULL) { *majorV = TCL_MAJOR_VERSION; } if (minorV != NULL) { *minorV = TCL_MINOR_VERSION; } if (patchLevelV != NULL) { *patchLevelV = TCL_RELEASE_SERIAL; } if (type != NULL) { *type = TCL_RELEASE_LEVEL; } } /* *---------------------------------------------------------------------- * * Math Functions -- * * This page contains the functions that implement all of the built-in * math functions for expressions. * * Results: * Each function returns TCL_OK if it succeeds and pushes an Tcl object * holding the result. If it fails it returns TCL_ERROR and leaves an * error message in the interpreter's result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ExprCeilFunc( ClientData clientData, /* Ignored */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter list. */ { int code; double d; mp_int big; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d); #ifdef ACCEPT_NAN if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } #endif if (code != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK) { Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclCeil(&big))); mp_clear(&big); } else { Tcl_SetObjResult(interp, Tcl_NewDoubleObj(ceil(d))); } return TCL_OK; } static int ExprFloorFunc( ClientData clientData, /* Ignored */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter list. */ { int code; double d; mp_int big; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d); #ifdef ACCEPT_NAN if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } #endif if (code != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK) { Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclFloor(&big))); mp_clear(&big); } else { Tcl_SetObjResult(interp, Tcl_NewDoubleObj(floor(d))); } return TCL_OK; } static int ExprIsqrtFunc( ClientData clientData, /* Ignored */ Tcl_Interp *interp, /* The interpreter in which to execute. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter list. */ { ClientData ptr; int type; double d; Tcl_WideInt w; mp_int big; int exact = 0; /* Flag ==1 if the argument can be represented * in a double as an exact integer. */ /* * Check syntax. */ if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } /* * Make sure that the arg is a number. */ if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } switch (type) { case TCL_NUMBER_NAN: Tcl_GetDoubleFromObj(interp, objv[1], &d); return TCL_ERROR; case TCL_NUMBER_DOUBLE: d = *((const double *) ptr); if (d < 0) { goto negarg; } #ifdef IEEE_FLOATING_POINT if (d <= MAX_EXACT) { exact = 1; } #endif if (!exact) { if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) { return TCL_ERROR; } } break; case TCL_NUMBER_BIG: if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) { return TCL_ERROR; } if (SIGN(&big) == MP_NEG) { mp_clear(&big); goto negarg; } break; default: if (Tcl_GetWideIntFromObj(interp, objv[1], &w) != TCL_OK) { return TCL_ERROR; } if (w < 0) { goto negarg; } d = (double) w; #ifdef IEEE_FLOATING_POINT if (d < MAX_EXACT) { exact = 1; } #endif if (!exact) { Tcl_GetBignumFromObj(interp, objv[1], &big); } break; } if (exact) { Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) sqrt(d))); } else { mp_int root; mp_init(&root); mp_sqrt(&big, &root); mp_clear(&big); Tcl_SetObjResult(interp, Tcl_NewBignumObj(&root)); } return TCL_OK; negarg: Tcl_SetObjResult(interp, Tcl_NewStringObj( "square root of negative argument", -1)); Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", "domain error: argument not in valid range", NULL); return TCL_ERROR; } static int ExprSqrtFunc( ClientData clientData, /* Ignored */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter list. */ { int code; double d; mp_int big; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d); #ifdef ACCEPT_NAN if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } #endif if (code != TCL_OK) { return TCL_ERROR; } if ((d >= 0.0) && TclIsInfinite(d) && (Tcl_GetBignumFromObj(NULL, objv[1], &big) == TCL_OK)) { mp_int root; mp_init(&root); mp_sqrt(&big, &root); mp_clear(&big); Tcl_SetObjResult(interp, Tcl_NewDoubleObj(TclBignumToDouble(&root))); mp_clear(&root); } else { Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sqrt(d))); } return TCL_OK; } static int ExprUnaryFunc( ClientData clientData, /* Contains the address of a function that * takes one double argument and returns a * double result. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { int code; double d; double (*func)(double) = (double (*)(double)) clientData; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d); #ifdef ACCEPT_NAN if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) { d = objv[1]->internalRep.doubleValue; Tcl_ResetResult(interp); code = TCL_OK; } #endif if (code != TCL_OK) { return TCL_ERROR; } errno = 0; return CheckDoubleResult(interp, func(d)); } static int CheckDoubleResult( Tcl_Interp *interp, double dResult) { #ifndef ACCEPT_NAN if (TclIsNaN(dResult)) { TclExprFloatError(interp, dResult); return TCL_ERROR; } #endif if ((errno == ERANGE) && ((dResult == 0.0) || TclIsInfinite(dResult))) { /* * When ERANGE signals under/overflow, just accept 0.0 or +/-Inf */ } else if (errno != 0) { /* * Report other errno values as errors. */ TclExprFloatError(interp, dResult); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult)); return TCL_OK; } static int ExprBinaryFunc( ClientData clientData, /* Contains the address of a function that * takes two double arguments and returns a * double result. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Parameter vector. */ { int code; double d1, d2; double (*func)(double, double) = (double (*)(double, double)) clientData; if (objc != 3) { MathFuncWrongNumArgs(interp, 3, objc, objv); return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d1); #ifdef ACCEPT_NAN if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) { d1 = objv[1]->internalRep.doubleValue; Tcl_ResetResult(interp); code = TCL_OK; } #endif if (code != TCL_OK) { return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[2], &d2); #ifdef ACCEPT_NAN if ((code != TCL_OK) && (objv[2]->typePtr == &tclDoubleType)) { d2 = objv[2]->internalRep.doubleValue; Tcl_ResetResult(interp); code = TCL_OK; } #endif if (code != TCL_OK) { return TCL_ERROR; } errno = 0; return CheckDoubleResult(interp, func(d1, d2)); } static int ExprAbsFunc( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Parameter vector. */ { ClientData ptr; int type; mp_int big; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_LONG) { long l = *((const long *) ptr); if (l > (long)0) { goto unChanged; } else if (l == (long)0) { const char *string = objv[1]->bytes; if (string) { while (*string != '0') { if (*string == '-') { Tcl_SetObjResult(interp, Tcl_NewLongObj(0)); return TCL_OK; } string++; } } goto unChanged; } else if (l == LONG_MIN) { TclBNInitBignumFromLong(&big, l); goto tooLarge; } Tcl_SetObjResult(interp, Tcl_NewLongObj(-l)); return TCL_OK; } if (type == TCL_NUMBER_DOUBLE) { double d = *((const double *) ptr); static const double poszero = 0.0; /* * We need to distinguish here between positive 0.0 and negative -0.0. * [Bug 2954959] */ if (d == -0.0) { if (!memcmp(&d, &poszero, sizeof(double))) { goto unChanged; } } else if (d > -0.0) { goto unChanged; } Tcl_SetObjResult(interp, Tcl_NewDoubleObj(-d)); return TCL_OK; } #ifndef TCL_WIDE_INT_IS_LONG if (type == TCL_NUMBER_WIDE) { Tcl_WideInt w = *((const Tcl_WideInt *) ptr); if (w >= (Tcl_WideInt)0) { goto unChanged; } if (w == LLONG_MIN) { TclBNInitBignumFromWideInt(&big, w); goto tooLarge; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w)); return TCL_OK; } #endif if (type == TCL_NUMBER_BIG) { if (mp_cmp_d((const mp_int *) ptr, 0) == MP_LT) { Tcl_GetBignumFromObj(NULL, objv[1], &big); tooLarge: mp_neg(&big, &big); Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big)); } else { unChanged: Tcl_SetObjResult(interp, objv[1]); } return TCL_OK; } if (type == TCL_NUMBER_NAN) { #ifdef ACCEPT_NAN Tcl_SetObjResult(interp, objv[1]); return TCL_OK; #else double d; Tcl_GetDoubleFromObj(interp, objv[1], &d); return TCL_ERROR; #endif } return TCL_OK; } static int ExprBoolFunc( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter vector. */ { int value; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, objv[1], &value) != TCL_OK) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value)); return TCL_OK; } static int ExprDoubleFunc( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter vector. */ { double dResult; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetDoubleFromObj(interp, objv[1], &dResult) != TCL_OK) { #ifdef ACCEPT_NAN if (objv[1]->typePtr == &tclDoubleType) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } #endif return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult)); return TCL_OK; } static int ExprEntierFunc( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter vector. */ { double d; int type; ClientData ptr; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_DOUBLE) { d = *((const double *) ptr); if ((d >= (double)LONG_MAX) || (d <= (double)LONG_MIN)) { mp_int big; if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) { /* Infinity */ return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big)); return TCL_OK; } else { long result = (long) d; Tcl_SetObjResult(interp, Tcl_NewLongObj(result)); return TCL_OK; } } if (type != TCL_NUMBER_NAN) { /* * All integers are already of integer type. */ Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } /* * Get the error message for NaN. */ Tcl_GetDoubleFromObj(interp, objv[1], &d); return TCL_ERROR; } static int ExprIntFunc( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter vector. */ { long iResult; Tcl_Obj *objPtr; if (ExprEntierFunc(NULL, interp, objc, objv) != TCL_OK) { return TCL_ERROR; } objPtr = Tcl_GetObjResult(interp); if (TclGetLongFromObj(NULL, objPtr, &iResult) != TCL_OK) { /* * Truncate the bignum; keep only bits in long range. */ mp_int big; Tcl_GetBignumFromObj(NULL, objPtr, &big); mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big); objPtr = Tcl_NewBignumObj(&big); Tcl_IncrRefCount(objPtr); TclGetLongFromObj(NULL, objPtr, &iResult); Tcl_DecrRefCount(objPtr); } Tcl_SetObjResult(interp, Tcl_NewLongObj(iResult)); return TCL_OK; } static int ExprWideFunc( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter vector. */ { Tcl_WideInt wResult; Tcl_Obj *objPtr; if (ExprEntierFunc(NULL, interp, objc, objv) != TCL_OK) { return TCL_ERROR; } objPtr = Tcl_GetObjResult(interp); if (Tcl_GetWideIntFromObj(NULL, objPtr, &wResult) != TCL_OK) { /* * Truncate the bignum; keep only bits in wide int range. */ mp_int big; Tcl_GetBignumFromObj(NULL, objPtr, &big); mp_mod_2d(&big, (int) CHAR_BIT * sizeof(Tcl_WideInt), &big); objPtr = Tcl_NewBignumObj(&big); Tcl_IncrRefCount(objPtr); Tcl_GetWideIntFromObj(NULL, objPtr, &wResult); Tcl_DecrRefCount(objPtr); } Tcl_SetObjResult(interp, Tcl_NewWideIntObj(wResult)); return TCL_OK; } static int ExprRandFunc( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter vector. */ { Interp *iPtr = (Interp *) interp; double dResult; long tmp; /* Algorithm assumes at least 32 bits. Only * long guarantees that. See below. */ Tcl_Obj *oResult; if (objc != 1) { MathFuncWrongNumArgs(interp, 1, objc, objv); return TCL_ERROR; } if (!(iPtr->flags & RAND_SEED_INITIALIZED)) { iPtr->flags |= RAND_SEED_INITIALIZED; /* * Take into consideration the thread this interp is running in order * to insure different seeds in different threads (bug #416643) */ iPtr->randSeed = TclpGetClicks() + (PTR2INT(Tcl_GetCurrentThread())<<12); /* * Make sure 1 <= randSeed <= (2^31) - 2. See below. */ iPtr->randSeed &= (unsigned long) 0x7fffffff; if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) { iPtr->randSeed ^= 123459876; } } /* * Generate the random number using the linear congruential generator * defined by the following recurrence: * seed = ( IA * seed ) mod IM * where IA is 16807 and IM is (2^31) - 1. The recurrence maps a seed in * the range [1, IM - 1] to a new seed in that same range. The recurrence * maps IM to 0, and maps 0 back to 0, so those two values must not be * allowed as initial values of seed. * * In order to avoid potential problems with integer overflow, the * recurrence is implemented in terms of additional constants IQ and IR * such that * IM = IA*IQ + IR * None of the operations in the implementation overflows a 32-bit signed * integer, and the C type long is guaranteed to be at least 32 bits wide. * * For more details on how this algorithm works, refer to the following * papers: * * S.K. Park & K.W. Miller, "Random number generators: good ones are hard * to find," Comm ACM 31(10):1192-1201, Oct 1988 * * W.H. Press & S.A. Teukolsky, "Portable random number generators," * Computers in Physics 6(5):522-524, Sep/Oct 1992. */ #define RAND_IA 16807 #define RAND_IM 2147483647 #define RAND_IQ 127773 #define RAND_IR 2836 #define RAND_MASK 123459876 tmp = iPtr->randSeed/RAND_IQ; iPtr->randSeed = RAND_IA*(iPtr->randSeed - tmp*RAND_IQ) - RAND_IR*tmp; if (iPtr->randSeed < 0) { iPtr->randSeed += RAND_IM; } /* * Since the recurrence keeps seed values in the range [1, RAND_IM - 1], * dividing by RAND_IM yields a double in the range (0, 1). */ dResult = iPtr->randSeed * (1.0/RAND_IM); /* * Push a Tcl object with the result. */ TclNewDoubleObj(oResult, dResult); Tcl_SetObjResult(interp, oResult); return TCL_OK; } static int ExprRoundFunc( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Parameter vector. */ { double d; ClientData ptr; int type; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_DOUBLE) { double fractPart, intPart; long max = LONG_MAX, min = LONG_MIN; fractPart = modf(*((const double *) ptr), &intPart); if (fractPart <= -0.5) { min++; } else if (fractPart >= 0.5) { max--; } if ((intPart >= (double)max) || (intPart <= (double)min)) { mp_int big; if (Tcl_InitBignumFromDouble(interp, intPart, &big) != TCL_OK) { /* Infinity */ return TCL_ERROR; } if (fractPart <= -0.5) { mp_sub_d(&big, 1, &big); } else if (fractPart >= 0.5) { mp_add_d(&big, 1, &big); } Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big)); return TCL_OK; } else { long result = (long)intPart; if (fractPart <= -0.5) { result--; } else if (fractPart >= 0.5) { result++; } Tcl_SetObjResult(interp, Tcl_NewLongObj(result)); return TCL_OK; } } if (type != TCL_NUMBER_NAN) { /* * All integers are already rounded */ Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } /* * Get the error message for NaN. */ Tcl_GetDoubleFromObj(interp, objv[1], &d); return TCL_ERROR; } static int ExprSrandFunc( ClientData clientData, /* Ignored. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Parameter vector. */ { Interp *iPtr = (Interp *) interp; long i = 0; /* Initialized to avoid compiler warning. */ /* * Convert argument and use it to reset the seed. */ if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetLongFromObj(NULL, objv[1], &i) != TCL_OK) { Tcl_Obj *objPtr; mp_int big; if (Tcl_GetBignumFromObj(interp, objv[1], &big) != TCL_OK) { /* TODO: more ::errorInfo here? or in caller? */ return TCL_ERROR; } mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big); objPtr = Tcl_NewBignumObj(&big); Tcl_IncrRefCount(objPtr); TclGetLongFromObj(NULL, objPtr, &i); Tcl_DecrRefCount(objPtr); } /* * Reset the seed. Make sure 1 <= randSeed <= 2^31 - 2. See comments in * ExprRandFunc for more details. */ iPtr->flags |= RAND_SEED_INITIALIZED; iPtr->randSeed = i; iPtr->randSeed &= (unsigned long) 0x7fffffff; if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) { iPtr->randSeed ^= 123459876; } /* * To avoid duplicating the random number generation code we simply clean * up our state and call the real random number function. That function * will always succeed. */ return ExprRandFunc(clientData, interp, 1, objv); } /* *---------------------------------------------------------------------- * * MathFuncWrongNumArgs -- * * Generate an error message when a math function presents the wrong * number of arguments. * * Results: * None. * * Side effects: * An error message is stored in the interpreter result. * *---------------------------------------------------------------------- */ static void MathFuncWrongNumArgs( Tcl_Interp *interp, /* Tcl interpreter */ int expected, /* Formal parameter count. */ int found, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter vector. */ { const char *name = Tcl_GetString(objv[0]); const char *tail = name + strlen(name); while (tail > name+1) { tail--; if (*tail == ':' && tail[-1] == ':') { name = tail+1; break; } } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "too %s arguments for math function \"%s\"", (found < expected ? "few" : "many"), name)); Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); } #ifdef USE_DTRACE /* *---------------------------------------------------------------------- * * DTraceObjCmd -- * * This function is invoked to process the "::tcl::dtrace" Tcl command. * * Results: * A standard Tcl object result. * * Side effects: * The 'tcl-probe' DTrace probe is triggered (if it is enabled). * *---------------------------------------------------------------------- */ static int DTraceObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (TCL_DTRACE_TCL_PROBE_ENABLED()) { char *a[10]; int i = 0; while (i++ < 10) { a[i-1] = i < objc ? TclGetString(objv[i]) : NULL; } TCL_DTRACE_TCL_PROBE(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclDTraceInfo -- * * Extract information from a TIP280 dict for use by DTrace probes. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclDTraceInfo( Tcl_Obj *info, const char **args, int *argsi) { static Tcl_Obj *keys[10] = { NULL }; Tcl_Obj **k = keys, *val; int i = 0; if (!*k) { #define kini(s) TclNewLiteralStringObj(keys[i], s); i++ kini("cmd"); kini("type"); kini("proc"); kini("file"); kini("method"); kini("class"); kini("lambda"); kini("object"); kini("line"); kini("level"); #undef kini } for (i = 0; i < 6; i++) { Tcl_DictObjGet(NULL, info, *k++, &val); args[i] = val ? TclGetString(val) : NULL; } /* no "proc" -> use "lambda" */ if (!args[2]) { Tcl_DictObjGet(NULL, info, *k, &val); args[2] = val ? TclGetString(val) : NULL; } k++; /* no "class" -> use "object" */ if (!args[5]) { Tcl_DictObjGet(NULL, info, *k, &val); args[5] = val ? TclGetString(val) : NULL; } k++; for (i = 0; i < 2; i++) { Tcl_DictObjGet(NULL, info, *k++, &val); if (val) { TclGetIntFromObj(NULL, val, &argsi[i]); } else { argsi[i] = 0; } } } /* *---------------------------------------------------------------------- * * DTraceCmdReturn -- * * NR callback for DTrace command return probes. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int DTraceCmdReturn( ClientData data[], Tcl_Interp *interp, int result) { char *cmdName = TclGetString((Tcl_Obj *) data[0]); if (TCL_DTRACE_CMD_RETURN_ENABLED()) { TCL_DTRACE_CMD_RETURN(cmdName, result); } if (TCL_DTRACE_CMD_RESULT_ENABLED()) { Tcl_Obj *r = Tcl_GetObjResult(interp); TCL_DTRACE_CMD_RESULT(cmdName, result, TclGetString(r), r); } return result; } TCL_DTRACE_DEBUG_LOG() #endif /* USE_DTRACE */ /* *---------------------------------------------------------------------- * * Tcl_NRCallObjProc -- * * This function calls an objProc directly while managing things properly * if it happens to be an NR objProc. It is meant to be used by extenders * that provide an NR implementation of a command, as this function * permits a trivial coding of the non-NR objProc. * * Results: * The return value is a standard Tcl completion code such as TCL_OK or * TCL_ERROR. A result or error message is left in interp's result. * * Side effects: * Depends on the objProc. * *---------------------------------------------------------------------- */ int Tcl_NRCallObjProc( Tcl_Interp *interp, Tcl_ObjCmdProc *objProc, ClientData clientData, int objc, Tcl_Obj *const objv[]) { NRE_callback *rootPtr = TOP_CB(interp); TclNRAddCallback(interp, Dispatch, objProc, clientData, INT2PTR(objc), objv); return TclNRRunCallbacks(interp, TCL_OK, rootPtr); } /* *---------------------------------------------------------------------- * * Tcl_NRCreateCommand -- * * Define a new NRE-enabled object-based command in a command table. * * Results: * The return value is a token for the command, which can be used in * future calls to Tcl_GetCommandName. * * Side effects: * If no command named "cmdName" already exists for interp, one is * created. Otherwise, if a command does exist, then if the object-based * Tcl_ObjCmdProc is TclInvokeStringCommand, we assume Tcl_CreateCommand * was called previously for the same command and just set its * Tcl_ObjCmdProc to the argument "proc"; otherwise, we delete the old * command. * * In the future, during bytecode evaluation when "cmdName" is seen as * the name of a command by Tcl_EvalObj or Tcl_Eval, the object-based * Tcl_ObjCmdProc proc will be called. When the command is deleted from * the table, deleteProc will be called. See the manual entry for details * on the calling sequence. * *---------------------------------------------------------------------- */ Tcl_Command Tcl_NRCreateCommand( Tcl_Interp *interp, /* Token for command interpreter (returned by * previous call to Tcl_CreateInterp). */ const char *cmdName, /* Name of command. If it contains namespace * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_ObjCmdProc *proc, /* Object-based function to associate with * name, provides direct access for direct * calls. */ Tcl_ObjCmdProc *nreProc, /* Object-based function to associate with * name, provides NR implementation */ ClientData clientData, /* Arbitrary value to pass to object * function. */ Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ { Command *cmdPtr = (Command *) Tcl_CreateObjCommand(interp,cmdName,proc,clientData,deleteProc); cmdPtr->nreProc = nreProc; return (Tcl_Command) cmdPtr; } /**************************************************************************** * Stuff for the public api ****************************************************************************/ int Tcl_NREvalObj( Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) { return TclNREvalObjEx(interp, objPtr, flags, NULL, INT_MIN); } int Tcl_NREvalObjv( Tcl_Interp *interp, /* Interpreter in which to evaluate the * command. Also used for error reporting. */ int objc, /* Number of words in command. */ Tcl_Obj *const objv[], /* An array of pointers to objects that are * the words that make up the command. */ int flags) /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL, TCL_EVAL_INVOKE and * TCL_EVAL_NOERR are currently supported. */ { return TclNREvalObjv(interp, objc, objv, flags, NULL); } int Tcl_NRCmdSwap( Tcl_Interp *interp, Tcl_Command cmd, int objc, Tcl_Obj *const objv[], int flags) { return TclNREvalObjv(interp, objc, objv, flags|TCL_EVAL_NOERR, (Command *) cmd); } /***************************************************************************** * Tailcall related code ***************************************************************************** * * The steps of the tailcall dance are as follows: * * 1. when [tailcall] is invoked, it stores the corresponding callback in * the current CallFrame and returns TCL_RETURN * 2. when the CallFrame is popped, it calls TclSetTailcall to store the * callback in the proper NRCommand callback - the spot where the command * that pushed the CallFrame is completely cleaned up * 3. when the NRCommand callback runs, it schedules the tailcall callback * to run immediately after it returns * * One delicate point is to properly define the NRCommand where the tailcall * will execute. There are functions whose purpose is to help define the * precise spot: * TclMarkTailcall: if the NEXT command to be pushed tailcalls, execution * should continue right here * TclSkipTailcall: if the NEXT command to be pushed tailcalls, execution * should continue after the CURRENT command is fully returned ("skip * the next command: we are redirecting to it, tailcalls should run * after WE return") * TclPushTailcallPoint: the search for a tailcalling spot cannot traverse * this point. This is special for OO, as some of the oo constructs * that behave like commands may not push an NRCommand callback. */ void TclMarkTailcall( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; if (iPtr->deferredCallbacks == NULL) { TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL); iPtr->deferredCallbacks = TOP_CB(interp); } } void TclSkipTailcall( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; TclMarkTailcall(interp); iPtr->deferredCallbacks->data[1] = INT2PTR(1); } void TclPushTailcallPoint( Tcl_Interp *interp) { TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL); ((Interp *) interp)->numLevels++; } /* *---------------------------------------------------------------------- * * TclSetTailcall -- * * Splice a tailcall command in the proper spot of the NRE callback * stack, so that it runs at the right time. * *---------------------------------------------------------------------- */ void TclSetTailcall( Tcl_Interp *interp, Tcl_Obj *listPtr) { /* * Find the splicing spot: right before the NRCommand of the thing * being tailcalled. Note that we skip NRCommands marked by a 1 in data[1] * (used by command redirectors). */ NRE_callback *runPtr; for (runPtr = TOP_CB(interp); runPtr; runPtr = runPtr->nextPtr) { if (((runPtr->procPtr) == NRCommand) && !runPtr->data[1]) { break; } } if (!runPtr) { Tcl_Panic("tailcall cannot find the right splicing spot: should not happen!"); } runPtr->data[1] = listPtr; } /* *---------------------------------------------------------------------- * * TclNRTailcallObjCmd -- * * Prepare the tailcall as a list and store it in the current * varFrame. When the frame is later popped the tailcall will be spliced * at the proper place. * * Results: * The first NRCommand callback that is not marked to be skipped is * updated so that its data[1] field contains the tailcall list. * *---------------------------------------------------------------------- */ int TclNRTailcallObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; if (objc < 1) { Tcl_WrongNumArgs(interp, 1, objv, "?command? ?arg ...?"); return TCL_ERROR; } if (!(iPtr->varFramePtr->isProcCallFrame & 1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "tailcall can only be called from a proc, lambda or method", -1)); Tcl_SetErrorCode(interp, "TCL", "TAILCALL", "ILLEGAL", NULL); return TCL_ERROR; } /* * Invocation without args just clears a scheduled tailcall; invocation * with an argument replaces any previously scheduled tailcall. */ if (iPtr->varFramePtr->tailcallPtr) { Tcl_DecrRefCount(iPtr->varFramePtr->tailcallPtr); iPtr->varFramePtr->tailcallPtr = NULL; } /* * Create the callback to actually evaluate the tailcalled * command, then set it in the varFrame so that PopCallFrame can use it * at the proper time. */ if (objc > 1) { Tcl_Obj *listPtr, *nsObjPtr; Tcl_Namespace *nsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr; Tcl_Namespace *ns1Ptr; /* The tailcall data is in a Tcl list: the first element is the * namespace, the rest the command to be tailcalled. */ listPtr = Tcl_NewListObj(objc, objv); nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1); if ((TCL_OK != TclGetNamespaceFromObj(interp, nsObjPtr, &ns1Ptr)) || (nsPtr != ns1Ptr)) { Tcl_Panic("Tailcall failed to find the proper namespace"); } TclListObjSetElement(interp, listPtr, 0, nsObjPtr); iPtr->varFramePtr->tailcallPtr = listPtr; } return TCL_RETURN; } /* *---------------------------------------------------------------------- * * TclNRTailcallEval -- * * This NREcallback actually causes the tailcall to be evaluated. * *---------------------------------------------------------------------- */ int TclNRTailcallEval( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_Obj *listPtr = data[0], *nsObjPtr; Tcl_Namespace *nsPtr; int objc; Tcl_Obj **objv; Tcl_ListObjGetElements(interp, listPtr, &objc, &objv); nsObjPtr = objv[0]; if (result == TCL_OK) { result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); } if (result != TCL_OK) { /* * Tailcall execution was preempted, eg by an intervening catch or by * a now-gone namespace: cleanup and return. */ TailcallCleanup(data, interp, result); return result; } /* * Perform the tailcall */ TclMarkTailcall(interp); TclNRAddCallback(interp, TailcallCleanup, listPtr, NULL, NULL,NULL); iPtr->lookupNsPtr = (Namespace *) nsPtr; return TclNREvalObjv(interp, objc-1, objv+1, 0, NULL); } static int TailcallCleanup( ClientData data[], Tcl_Interp *interp, int result) { Tcl_DecrRefCount((Tcl_Obj *) data[0]); return result; } void Tcl_NRAddCallback( Tcl_Interp *interp, Tcl_NRPostProc *postProcPtr, ClientData data0, ClientData data1, ClientData data2, ClientData data3) { if (!(postProcPtr)) { Tcl_Panic("Adding a callback without an objProc?!"); } TclNRAddCallback(interp, postProcPtr, data0, data1, data2, data3); } /* *---------------------------------------------------------------------- * * TclNRCoroutineObjCmd -- (and friends) * * This object-based function is invoked to process the "coroutine" Tcl * command. It is heavily based on "apply". * * Results: * A standard Tcl object result value. * * Side effects: * A new procedure gets created. * * ** FIRST EXPERIMENTAL IMPLEMENTATION ** * * It is fairly amateurish and not up to our standards - mainly in terms of * error messages and [info] interaction. Just to test the infrastructure in * teov and tebc. *---------------------------------------------------------------------- */ #define iPtr ((Interp *) interp) int TclNRYieldObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?returnValue?"); return TCL_ERROR; } if (!corPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "yield can only be called in a coroutine", -1)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", NULL); return TCL_ERROR; } if (objc == 2) { Tcl_SetObjResult(interp, objv[1]); } NRE_ASSERT(!COR_IS_SUSPENDED(corPtr)); TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr, clientData, NULL, NULL); return TCL_OK; } int TclNRYieldToObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; Tcl_Obj *listPtr, *nsObjPtr; Tcl_Namespace *nsPtr = TclGetCurrentNamespace(interp); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "command ?arg ...?"); return TCL_ERROR; } if (!corPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "yieldto can only be called in a coroutine", -1)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", NULL); return TCL_ERROR; } if (((Namespace *) nsPtr)->flags & NS_DYING) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "yieldto called in deleted namespace", -1)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "YIELDTO_IN_DELETED", NULL); return TCL_ERROR; } /* * Add the tailcall in the caller env, then just yield. * * This is essentially code from TclNRTailcallObjCmd */ listPtr = Tcl_NewListObj(objc, objv); nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1); TclListObjSetElement(interp, listPtr, 0, nsObjPtr); /* * Add the callback in the caller's env, then instruct TEBC to yield. */ iPtr->execEnvPtr = corPtr->callerEEPtr; TclSetTailcall(interp, listPtr); iPtr->execEnvPtr = corPtr->eePtr; return TclNRYieldObjCmd(INT2PTR(CORO_ACTIVATE_YIELDM), interp, 1, objv); } static int RewindCoroutineCallback( ClientData data[], Tcl_Interp *interp, int result) { return Tcl_RestoreInterpState(interp, data[0]); } static int RewindCoroutine( CoroutineData *corPtr, int result) { Tcl_Interp *interp = corPtr->eePtr->interp; Tcl_InterpState state = Tcl_SaveInterpState(interp, result); NRE_ASSERT(COR_IS_SUSPENDED(corPtr)); NRE_ASSERT(corPtr->eePtr != NULL); NRE_ASSERT(corPtr->eePtr != iPtr->execEnvPtr); corPtr->eePtr->rewind = 1; TclNRAddCallback(interp, RewindCoroutineCallback, state, NULL, NULL, NULL); return TclNRInterpCoroutine(corPtr, interp, 0, NULL); } static void DeleteCoroutine( ClientData clientData) { CoroutineData *corPtr = clientData; Tcl_Interp *interp = corPtr->eePtr->interp; NRE_callback *rootPtr = TOP_CB(interp); if (COR_IS_SUSPENDED(corPtr)) { TclNRRunCallbacks(interp, RewindCoroutine(corPtr,TCL_OK), rootPtr); } } static int NRCoroutineCallerCallback( ClientData data[], Tcl_Interp *interp, int result) { CoroutineData *corPtr = data[0]; Command *cmdPtr = corPtr->cmdPtr; /* * This is the last callback in the caller execEnv, right before switching * to the coroutine's */ NRE_ASSERT(iPtr->execEnvPtr == corPtr->callerEEPtr); if (!corPtr->eePtr) { /* * The execEnv was wound down but not deleted for our sake. We finish * the job here. The caller context has already been restored. */ NRE_ASSERT(iPtr->varFramePtr == corPtr->caller.varFramePtr); NRE_ASSERT(iPtr->framePtr == corPtr->caller.framePtr); NRE_ASSERT(iPtr->cmdFramePtr == corPtr->caller.cmdFramePtr); ckfree(corPtr); return result; } NRE_ASSERT(COR_IS_SUSPENDED(corPtr)); SAVE_CONTEXT(corPtr->running); RESTORE_CONTEXT(corPtr->caller); if (cmdPtr->flags & CMD_IS_DELETED) { /* * The command was deleted while it was running: wind down the * execEnv, this will do the complete cleanup. RewindCoroutine will * restore both the caller's context and interp state. */ return RewindCoroutine(corPtr, result); } return result; } static int NRCoroutineExitCallback( ClientData data[], Tcl_Interp *interp, int result) { CoroutineData *corPtr = data[0]; Command *cmdPtr = corPtr->cmdPtr; /* * This runs at the bottom of the Coroutine's execEnv: it will be executed * when the coroutine returns or is wound down, but not when it yields. It * deletes the coroutine and restores the caller's environment. */ NRE_ASSERT(interp == corPtr->eePtr->interp); NRE_ASSERT(TOP_CB(interp) == NULL); NRE_ASSERT(iPtr->execEnvPtr == corPtr->eePtr); NRE_ASSERT(!COR_IS_SUSPENDED(corPtr)); NRE_ASSERT((corPtr->callerEEPtr->callbackPtr->procPtr == NRCoroutineCallerCallback)); cmdPtr->deleteProc = NULL; Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr); TclCleanupCommandMacro(cmdPtr); corPtr->eePtr->corPtr = NULL; TclDeleteExecEnv(corPtr->eePtr); corPtr->eePtr = NULL; corPtr->stackLevel = NULL; /* * #280. * Drop the coroutine-owned copy of the lineLABCPtr hashtable for literal * command arguments in bytecode. */ Tcl_DeleteHashTable(corPtr->lineLABCPtr); ckfree(corPtr->lineLABCPtr); corPtr->lineLABCPtr = NULL; RESTORE_CONTEXT(corPtr->caller); iPtr->execEnvPtr = corPtr->callerEEPtr; iPtr->numLevels++; return result; } /* *---------------------------------------------------------------------- * * TclNRCoroutineActivateCallback -- * * This is the workhorse for coroutines: it implements both yield and * resume. * * It is important that both be implemented in the same callback: the * detection of the impossibility to suspend due to a busy C-stack relies * on the precise position of a local variable in the stack. We do not * want the compiler to play tricks on us, either by moving things around * or inlining. * *---------------------------------------------------------------------- */ int TclNRCoroutineActivateCallback( ClientData data[], Tcl_Interp *interp, int result) { CoroutineData *corPtr = data[0]; int type = PTR2INT(data[1]); int numLevels, unused; int *stackLevel = &unused; if (!corPtr->stackLevel) { /* * -- Coroutine is suspended -- * Push the callback to restore the caller's context on yield or * return. */ TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr, NULL, NULL, NULL); /* * Record the stackLevel at which the resume is happening, then swap * the interp's environment to make it suitable to run this coroutine. */ corPtr->stackLevel = stackLevel; numLevels = corPtr->auxNumLevels; corPtr->auxNumLevels = iPtr->numLevels; SAVE_CONTEXT(corPtr->caller); corPtr->callerEEPtr = iPtr->execEnvPtr; RESTORE_CONTEXT(corPtr->running); iPtr->execEnvPtr = corPtr->eePtr; iPtr->numLevels += numLevels; } else { /* * Coroutine is active: yield */ if (corPtr->stackLevel != stackLevel) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot yield: C stack busy", -1)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "CANT_YIELD", NULL); return TCL_ERROR; } if (type == CORO_ACTIVATE_YIELD) { corPtr->nargs = COROUTINE_ARGUMENTS_SINGLE_OPTIONAL; } else if (type == CORO_ACTIVATE_YIELDM) { corPtr->nargs = COROUTINE_ARGUMENTS_ARBITRARY; } else { Tcl_Panic("Yield received an option which is not implemented"); } corPtr->stackLevel = NULL; numLevels = iPtr->numLevels; iPtr->numLevels = corPtr->auxNumLevels; corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels; iPtr->execEnvPtr = corPtr->callerEEPtr; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NRCoroInjectObjCmd -- * * Implementation of [::tcl::unsupported::inject] command. * *---------------------------------------------------------------------- */ static int NRCoroInjectObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Command *cmdPtr; CoroutineData *corPtr; ExecEnv *savedEEPtr = iPtr->execEnvPtr; /* * Usage more or less like tailcall: * inject coroName cmd ?arg1 arg2 ...? */ if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?"); return TCL_ERROR; } cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[1]); if ((!cmdPtr) || (cmdPtr->nreProc != TclNRInterpCoroutine)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can only inject a command into a coroutine", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COROUTINE", TclGetString(objv[1]), NULL); return TCL_ERROR; } corPtr = cmdPtr->objClientData; if (!COR_IS_SUSPENDED(corPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can only inject a command into a suspended coroutine", -1)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", NULL); return TCL_ERROR; } /* * Add the callback to the coro's execEnv, so that it is the first thing * to happen when the coro is resumed. */ iPtr->execEnvPtr = corPtr->eePtr; TclNREvalObjEx(interp, Tcl_NewListObj(objc-2, objv+2), 0, NULL, INT_MIN); iPtr->execEnvPtr = savedEEPtr; return TCL_OK; } int TclNRInterpCoroutine( ClientData clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { CoroutineData *corPtr = clientData; if (!COR_IS_SUSPENDED(corPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "coroutine \"%s\" is already running", Tcl_GetString(objv[0]))); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BUSY", NULL); return TCL_ERROR; } /* * Parse all the arguments to work out what to feed as the result of the * [yield]. TRICKY POINT: objc==0 happens here! It occurs when a coroutine * is deleted! */ switch (corPtr->nargs) { case COROUTINE_ARGUMENTS_SINGLE_OPTIONAL: if (objc == 2) { Tcl_SetObjResult(interp, objv[1]); } else if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?arg?"); return TCL_ERROR; } break; default: if (corPtr->nargs != objc-1) { Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong coro nargs; how did we get here? " "not implemented!", -1)); Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); return TCL_ERROR; } /* fallthrough */ case COROUTINE_ARGUMENTS_ARBITRARY: if (objc > 1) { Tcl_SetObjResult(interp, Tcl_NewListObj(objc-1, objv+1)); } break; } TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr, NULL, NULL, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclNRCoroutineObjCmd -- * * Implementation of [coroutine] command; see documentation for * description of what this does. * *---------------------------------------------------------------------- */ int TclNRCoroutineObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Command *cmdPtr; CoroutineData *corPtr; const char *fullName, *procName; Namespace *nsPtr, *altNsPtr, *cxtNsPtr; Tcl_DString ds; Namespace *lookupNsPtr = iPtr->varFramePtr->nsPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "name cmd ?arg ...?"); return TCL_ERROR; } /* * FIXME: this is copy/pasted from Tcl_ProcObjCommand. Should have * something in tclUtil.c to find the FQ name. */ fullName = TclGetString(objv[1]); TclGetNamespaceForQualName(interp, fullName, NULL, 0, &nsPtr, &altNsPtr, &cxtNsPtr, &procName); if (nsPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create procedure \"%s\": unknown namespace", fullName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", NULL); return TCL_ERROR; } if (procName == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create procedure \"%s\": bad procedure name", fullName)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", fullName, NULL); return TCL_ERROR; } if ((nsPtr != iPtr->globalNsPtr) && (procName != NULL) && (procName[0] == ':')) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create procedure \"%s\" in non-global namespace with" " name starting with \":\"", procName)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", procName, NULL); return TCL_ERROR; } /* * We ARE creating the coroutine command: allocate the corresponding * struct and create the corresponding command. */ corPtr = ckalloc(sizeof(CoroutineData)); Tcl_DStringInit(&ds); if (nsPtr != iPtr->globalNsPtr) { Tcl_DStringAppend(&ds, nsPtr->fullName, -1); TclDStringAppendLiteral(&ds, "::"); } Tcl_DStringAppend(&ds, procName, -1); cmdPtr = (Command *) Tcl_NRCreateCommand(interp, Tcl_DStringValue(&ds), /*objProc*/ NULL, TclNRInterpCoroutine, corPtr, DeleteCoroutine); Tcl_DStringFree(&ds); corPtr->cmdPtr = cmdPtr; cmdPtr->refCount++; /* * #280. * Provide the new coroutine with its own copy of the lineLABCPtr * hashtable for literal command arguments in bytecode. Note that that * CFWordBC chains are not duplicated, only the entrypoints to them. This * means that in the presence of coroutines each chain is potentially a * tree. Like the chain -> tree conversion of the CmdFrame stack. */ { Tcl_HashSearch hSearch; Tcl_HashEntry *hePtr; corPtr->lineLABCPtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(corPtr->lineLABCPtr, TCL_ONE_WORD_KEYS); for (hePtr = Tcl_FirstHashEntry(iPtr->lineLABCPtr,&hSearch); hePtr; hePtr = Tcl_NextHashEntry(&hSearch)) { int isNew; Tcl_HashEntry *newPtr = Tcl_CreateHashEntry(corPtr->lineLABCPtr, Tcl_GetHashKey(iPtr->lineLABCPtr, hePtr), &isNew); Tcl_SetHashValue(newPtr, Tcl_GetHashValue(hePtr)); } } /* * Create the base context. */ corPtr->running.framePtr = iPtr->rootFramePtr; corPtr->running.varFramePtr = iPtr->rootFramePtr; corPtr->running.cmdFramePtr = NULL; corPtr->running.lineLABCPtr = corPtr->lineLABCPtr; corPtr->stackLevel = NULL; corPtr->auxNumLevels = 0; /* * Create the coro's execEnv, switch to it to push the exit and coro * command callbacks, then switch back. */ corPtr->eePtr = TclCreateExecEnv(interp, CORO_STACK_INITIAL_SIZE); corPtr->callerEEPtr = iPtr->execEnvPtr; corPtr->eePtr->corPtr = corPtr; SAVE_CONTEXT(corPtr->caller); corPtr->callerEEPtr = iPtr->execEnvPtr; RESTORE_CONTEXT(corPtr->running); iPtr->execEnvPtr = corPtr->eePtr; TclNRAddCallback(interp, NRCoroutineExitCallback, corPtr, NULL, NULL, NULL); /* insure that the command is looked up in the correct namespace */ iPtr->lookupNsPtr = lookupNsPtr; Tcl_NREvalObj(interp, Tcl_NewListObj(objc-2, objv+2), 0); iPtr->numLevels--; SAVE_CONTEXT(corPtr->running); RESTORE_CONTEXT(corPtr->caller); iPtr->execEnvPtr = corPtr->callerEEPtr; /* * Now just resume the coroutine. */ TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr, NULL, NULL, NULL); return TCL_OK; } /* * This is used in the [info] ensemble */ int TclInfoCoroutineCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } if (corPtr && !(corPtr->cmdPtr->flags & CMD_IS_DELETED)) { Tcl_Obj *namePtr; TclNewObj(namePtr); Tcl_GetCommandFullName(interp, (Tcl_Command) corPtr->cmdPtr, namePtr); Tcl_SetObjResult(interp, namePtr); } return TCL_OK; } #undef iPtr /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * indent-tabs-mode: nil * End: */ tcl8.6.5/generic/tclRegexp.c0000644000175000017500000007501112663660065015310 0ustar sergeisergei/* * tclRegexp.c -- * * This file contains the public interfaces to the Tcl regular expression * mechanism. * * Copyright (c) 1998 by Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclRegexp.h" /* *---------------------------------------------------------------------- * The routines in this file use Henry Spencer's regular expression package * contained in the following additional source files: * * regc_color.c regc_cvec.c regc_lex.c * regc_nfa.c regcomp.c regcustom.h * rege_dfa.c regerror.c regerrs.h * regex.h regexec.c regfree.c * regfronts.c regguts.h * * Copyright (c) 1998 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *** NOTE: this code has been altered slightly for use in Tcl: *** * *** 1. Names have been changed, e.g. from re_comp to *** * *** TclRegComp, to avoid clashes with other *** * *** regexp implementations used by applications. *** */ /* * Thread local storage used to maintain a per-thread cache of compiled * regular expressions. */ #define NUM_REGEXPS 30 typedef struct ThreadSpecificData { int initialized; /* Set to 1 when the module is initialized. */ char *patterns[NUM_REGEXPS];/* Strings corresponding to compiled regular * expression patterns. NULL means that this * slot isn't used. Malloc-ed. */ int patLengths[NUM_REGEXPS];/* Number of non-null characters in * corresponding entry in patterns. -1 means * entry isn't used. */ struct TclRegexp *regexps[NUM_REGEXPS]; /* Compiled forms of above strings. Also * malloc-ed, or NULL if not in use yet. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * Declarations for functions used only in this file. */ static TclRegexp * CompileRegexp(Tcl_Interp *interp, const char *pattern, int length, int flags); static void DupRegexpInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static void FinalizeRegexp(ClientData clientData); static void FreeRegexp(TclRegexp *regexpPtr); static void FreeRegexpInternalRep(Tcl_Obj *objPtr); static int RegExpExecUniChar(Tcl_Interp *interp, Tcl_RegExp re, const Tcl_UniChar *uniString, int numChars, int nmatches, int flags); static int SetRegexpFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); /* * The regular expression Tcl object type. This serves as a cache of the * compiled form of the regular expression. */ const Tcl_ObjType tclRegexpType = { "regexp", /* name */ FreeRegexpInternalRep, /* freeIntRepProc */ DupRegexpInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ SetRegexpFromAny /* setFromAnyProc */ }; /* *---------------------------------------------------------------------- * * Tcl_RegExpCompile -- * * Compile a regular expression into a form suitable for fast matching. * This function is DEPRECATED in favor of the object version of the * command. * * Results: * The return value is a pointer to the compiled form of string, suitable * for passing to Tcl_RegExpExec. This compiled form is only valid up * until the next call to this function, so don't keep these around for a * long time! If an error occurred while compiling the pattern, then NULL * is returned and an error message is left in the interp's result. * * Side effects: * Updates the cache of compiled regexps. * *---------------------------------------------------------------------- */ Tcl_RegExp Tcl_RegExpCompile( Tcl_Interp *interp, /* For use in error reporting and to access * the interp regexp cache. */ const char *pattern) /* String for which to produce compiled * regular expression. */ { return (Tcl_RegExp) CompileRegexp(interp, pattern, (int) strlen(pattern), REG_ADVANCED); } /* *---------------------------------------------------------------------- * * Tcl_RegExpExec -- * * Execute the regular expression matcher using a compiled form of a * regular expression and save information about any match that is found. * * Results: * If an error occurs during the matching operation then -1 is returned * and the interp's result contains an error message. Otherwise the * return value is 1 if a matching range is found and 0 if there is no * matching range. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_RegExpExec( Tcl_Interp *interp, /* Interpreter to use for error reporting. */ Tcl_RegExp re, /* Compiled regular expression; must have been * returned by previous call to * Tcl_GetRegExpFromObj. */ const char *text, /* Text against which to match re. */ const char *start) /* If text is part of a larger string, this * identifies beginning of larger string, so * that "^" won't match. */ { int flags, result, numChars; TclRegexp *regexp = (TclRegexp *) re; Tcl_DString ds; const Tcl_UniChar *ustr; /* * If the starting point is offset from the beginning of the buffer, then * we need to tell the regexp engine not to match "^". */ if (text > start) { flags = REG_NOTBOL; } else { flags = 0; } /* * Remember the string for use by Tcl_RegExpRange(). */ regexp->string = text; regexp->objPtr = NULL; /* * Convert the string to Unicode and perform the match. */ Tcl_DStringInit(&ds); ustr = Tcl_UtfToUniCharDString(text, -1, &ds); numChars = Tcl_DStringLength(&ds) / sizeof(Tcl_UniChar); result = RegExpExecUniChar(interp, re, ustr, numChars, -1 /* nmatches */, flags); Tcl_DStringFree(&ds); return result; } /* *--------------------------------------------------------------------------- * * Tcl_RegExpRange -- * * Returns pointers describing the range of a regular expression match, * or one of the subranges within the match. * * Results: * The variables at *startPtr and *endPtr are modified to hold the * addresses of the endpoints of the range given by index. If the * specified range doesn't exist then NULLs are returned. * * Side effects: * None. * *--------------------------------------------------------------------------- */ void Tcl_RegExpRange( Tcl_RegExp re, /* Compiled regular expression that has been * passed to Tcl_RegExpExec. */ int index, /* 0 means give the range of the entire match, * > 0 means give the range of a matching * subrange. */ const char **startPtr, /* Store address of first character in * (sub-)range here. */ const char **endPtr) /* Store address of character just after last * in (sub-)range here. */ { TclRegexp *regexpPtr = (TclRegexp *) re; const char *string; if ((size_t) index > regexpPtr->re.re_nsub) { *startPtr = *endPtr = NULL; } else if (regexpPtr->matches[index].rm_so < 0) { *startPtr = *endPtr = NULL; } else { if (regexpPtr->objPtr) { string = TclGetString(regexpPtr->objPtr); } else { string = regexpPtr->string; } *startPtr = Tcl_UtfAtIndex(string, regexpPtr->matches[index].rm_so); *endPtr = Tcl_UtfAtIndex(string, regexpPtr->matches[index].rm_eo); } } /* *--------------------------------------------------------------------------- * * RegExpExecUniChar -- * * Execute the regular expression matcher using a compiled form of a * regular expression and save information about any match that is found. * * Results: * If an error occurs during the matching operation then -1 is returned * and an error message is left in interp's result. Otherwise the return * value is 1 if a matching range was found or 0 if there was no matching * range. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int RegExpExecUniChar( Tcl_Interp *interp, /* Interpreter to use for error reporting. */ Tcl_RegExp re, /* Compiled regular expression; returned by a * previous call to Tcl_GetRegExpFromObj */ const Tcl_UniChar *wString, /* String against which to match re. */ int numChars, /* Length of Tcl_UniChar string (must be * >=0). */ int nmatches, /* How many subexpression matches (counting * the whole match as subexpression 0) are of * interest. -1 means "don't know". */ int flags) /* Regular expression flags. */ { int status; TclRegexp *regexpPtr = (TclRegexp *) re; size_t last = regexpPtr->re.re_nsub + 1; size_t nm = last; if (nmatches >= 0 && (size_t) nmatches < nm) { nm = (size_t) nmatches; } status = TclReExec(®expPtr->re, wString, (size_t) numChars, ®expPtr->details, nm, regexpPtr->matches, flags); /* * Check for errors. */ if (status != REG_OKAY) { if (status == REG_NOMATCH) { return 0; } if (interp != NULL) { TclRegError(interp, "error while matching regular expression: ", status); } return -1; } return 1; } /* *--------------------------------------------------------------------------- * * TclRegExpRangeUniChar -- * * Returns pointers describing the range of a regular expression match, * or one of the subranges within the match, or the hypothetical range * represented by the rm_extend field of the rm_detail_t. * * Results: * The variables at *startPtr and *endPtr are modified to hold the * offsets of the endpoints of the range given by index. If the specified * range doesn't exist then -1s are supplied. * * Side effects: * None. * *--------------------------------------------------------------------------- */ void TclRegExpRangeUniChar( Tcl_RegExp re, /* Compiled regular expression that has been * passed to Tcl_RegExpExec. */ int index, /* 0 means give the range of the entire match, * > 0 means give the range of a matching * subrange, -1 means the range of the * rm_extend field. */ int *startPtr, /* Store address of first character in * (sub-)range here. */ int *endPtr) /* Store address of character just after last * in (sub-)range here. */ { TclRegexp *regexpPtr = (TclRegexp *) re; if ((regexpPtr->flags®_EXPECT) && index == -1) { *startPtr = regexpPtr->details.rm_extend.rm_so; *endPtr = regexpPtr->details.rm_extend.rm_eo; } else if ((size_t) index > regexpPtr->re.re_nsub) { *startPtr = -1; *endPtr = -1; } else { *startPtr = regexpPtr->matches[index].rm_so; *endPtr = regexpPtr->matches[index].rm_eo; } } /* *---------------------------------------------------------------------- * * Tcl_RegExpMatch -- * * See if a string matches a regular expression. * * Results: * If an error occurs during the matching operation then -1 is returned * and the interp's result contains an error message. Otherwise the * return value is 1 if "text" matches "pattern" and 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_RegExpMatch( Tcl_Interp *interp, /* Used for error reporting. May be NULL. */ const char *text, /* Text to search for pattern matches. */ const char *pattern) /* Regular expression to match against text. */ { Tcl_RegExp re = Tcl_RegExpCompile(interp, pattern); if (re == NULL) { return -1; } return Tcl_RegExpExec(interp, re, text, text); } /* *---------------------------------------------------------------------- * * Tcl_RegExpExecObj -- * * Execute a precompiled regexp against the given object. * * Results: * If an error occurs during the matching operation then -1 is returned * and the interp's result contains an error message. Otherwise the * return value is 1 if "string" matches "pattern" and 0 otherwise. * * Side effects: * Converts the object to a Unicode object. * *---------------------------------------------------------------------- */ int Tcl_RegExpExecObj( Tcl_Interp *interp, /* Interpreter to use for error reporting. */ Tcl_RegExp re, /* Compiled regular expression; must have been * returned by previous call to * Tcl_GetRegExpFromObj. */ Tcl_Obj *textObj, /* Text against which to match re. */ int offset, /* Character index that marks where matching * should begin. */ int nmatches, /* How many subexpression matches (counting * the whole match as subexpression 0) are of * interest. -1 means all of them. */ int flags) /* Regular expression execution flags. */ { TclRegexp *regexpPtr = (TclRegexp *) re; Tcl_UniChar *udata; int length; int reflags = regexpPtr->flags; #define TCL_REG_GLOBOK_FLAGS \ (TCL_REG_ADVANCED | TCL_REG_NOSUB | TCL_REG_NOCASE) /* * Take advantage of the equivalent glob pattern, if one exists. * This is possible based only on the right mix of incoming flags (0) * and regexp compile flags. */ if ((offset == 0) && (nmatches == 0) && (flags == 0) && !(reflags & ~TCL_REG_GLOBOK_FLAGS) && (regexpPtr->globObjPtr != NULL)) { int nocase = (reflags & TCL_REG_NOCASE) ? TCL_MATCH_NOCASE : 0; /* * Pass to TclStringMatchObj for obj-specific handling. * XXX: Currently doesn't take advantage of exact-ness that * XXX: TclReToGlob tells us about */ return TclStringMatchObj(textObj, regexpPtr->globObjPtr, nocase); } /* * Save the target object so we can extract strings from it later. */ regexpPtr->string = NULL; regexpPtr->objPtr = textObj; udata = Tcl_GetUnicodeFromObj(textObj, &length); if (offset > length) { offset = length; } udata += offset; length -= offset; return RegExpExecUniChar(interp, re, udata, length, nmatches, flags); } /* *---------------------------------------------------------------------- * * Tcl_RegExpMatchObj -- * * See if an object matches a regular expression. * * Results: * If an error occurs during the matching operation then -1 is returned * and the interp's result contains an error message. Otherwise the * return value is 1 if "text" matches "pattern" and 0 otherwise. * * Side effects: * Changes the internal rep of the pattern and string objects. * *---------------------------------------------------------------------- */ int Tcl_RegExpMatchObj( Tcl_Interp *interp, /* Used for error reporting. May be NULL. */ Tcl_Obj *textObj, /* Object containing the String to search. */ Tcl_Obj *patternObj) /* Regular expression to match against * string. */ { Tcl_RegExp re; re = Tcl_GetRegExpFromObj(interp, patternObj, TCL_REG_ADVANCED | TCL_REG_NOSUB); if (re == NULL) { return -1; } return Tcl_RegExpExecObj(interp, re, textObj, 0 /* offset */, 0 /* nmatches */, 0 /* flags */); } /* *---------------------------------------------------------------------- * * Tcl_RegExpGetInfo -- * * Retrieve information about the current match. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_RegExpGetInfo( Tcl_RegExp regexp, /* Pattern from which to get subexpressions. */ Tcl_RegExpInfo *infoPtr) /* Match information is stored here. */ { TclRegexp *regexpPtr = (TclRegexp *) regexp; infoPtr->nsubs = regexpPtr->re.re_nsub; infoPtr->matches = (Tcl_RegExpIndices *) regexpPtr->matches; infoPtr->extendStart = regexpPtr->details.rm_extend.rm_so; } /* *---------------------------------------------------------------------- * * Tcl_GetRegExpFromObj -- * * Compile a regular expression into a form suitable for fast matching. * This function caches the result in a Tcl_Obj. * * Results: * The return value is a pointer to the compiled form of string, suitable * for passing to Tcl_RegExpExec. If an error occurred while compiling * the pattern, then NULL is returned and an error message is left in the * interp's result. * * Side effects: * Updates the native rep of the Tcl_Obj. * *---------------------------------------------------------------------- */ Tcl_RegExp Tcl_GetRegExpFromObj( Tcl_Interp *interp, /* For use in error reporting, and to access * the interp regexp cache. */ Tcl_Obj *objPtr, /* Object whose string rep contains regular * expression pattern. Internal rep will be * changed to compiled form of this regular * expression. */ int flags) /* Regular expression compilation flags. */ { int length; TclRegexp *regexpPtr; const char *pattern; /* * This is OK because we only actually interpret this value properly as a * TclRegexp* when the type is tclRegexpType. */ regexpPtr = objPtr->internalRep.twoPtrValue.ptr1; if ((objPtr->typePtr != &tclRegexpType) || (regexpPtr->flags != flags)) { pattern = TclGetStringFromObj(objPtr, &length); regexpPtr = CompileRegexp(interp, pattern, length, flags); if (regexpPtr == NULL) { return NULL; } /* * Add a reference to the regexp so it will persist even if it is * pushed out of the current thread's regexp cache. This reference * will be removed when the object's internal rep is freed. */ regexpPtr->refCount++; /* * Free the old representation and set our type. */ TclFreeIntRep(objPtr); objPtr->internalRep.twoPtrValue.ptr1 = regexpPtr; objPtr->typePtr = &tclRegexpType; } return (Tcl_RegExp) regexpPtr; } /* *---------------------------------------------------------------------- * * TclRegAbout -- * * Return information about a compiled regular expression. * * Results: * The return value is -1 for failure, 0 for success, although at the * moment there's nothing that could fail. On success, a list is left in * the interp's result: first element is the subexpression count, second * is a list of re_info bit names. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclRegAbout( Tcl_Interp *interp, /* For use in variable assignment. */ Tcl_RegExp re) /* The compiled regular expression. */ { TclRegexp *regexpPtr = (TclRegexp *) re; struct infoname { int bit; const char *text; }; static const struct infoname infonames[] = { {REG_UBACKREF, "REG_UBACKREF"}, {REG_ULOOKAHEAD, "REG_ULOOKAHEAD"}, {REG_UBOUNDS, "REG_UBOUNDS"}, {REG_UBRACES, "REG_UBRACES"}, {REG_UBSALNUM, "REG_UBSALNUM"}, {REG_UPBOTCH, "REG_UPBOTCH"}, {REG_UBBS, "REG_UBBS"}, {REG_UNONPOSIX, "REG_UNONPOSIX"}, {REG_UUNSPEC, "REG_UUNSPEC"}, {REG_UUNPORT, "REG_UUNPORT"}, {REG_ULOCALE, "REG_ULOCALE"}, {REG_UEMPTYMATCH, "REG_UEMPTYMATCH"}, {REG_UIMPOSSIBLE, "REG_UIMPOSSIBLE"}, {REG_USHORTEST, "REG_USHORTEST"}, {0, NULL} }; const struct infoname *inf; Tcl_Obj *infoObj, *resultObj; /* * The reset here guarantees that the interpreter result is empty and * unshared. This means that we can use Tcl_ListObjAppendElement on the * result object quite safely. */ Tcl_ResetResult(interp); /* * Assume that there will never be more than INT_MAX subexpressions. This * is a pretty reasonable assumption; the RE engine doesn't scale _that_ * well and Tcl has other limits that constrain things as well... */ resultObj = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewIntObj((int) regexpPtr->re.re_nsub)); /* * Now append a list of all the bit-flags set for the RE. */ TclNewObj(infoObj); for (inf=infonames ; inf->bit != 0 ; inf++) { if (regexpPtr->re.re_info & inf->bit) { Tcl_ListObjAppendElement(NULL, infoObj, Tcl_NewStringObj(inf->text, -1)); } } Tcl_ListObjAppendElement(NULL, resultObj, infoObj); Tcl_SetObjResult(interp, resultObj); return 0; } /* *---------------------------------------------------------------------- * * TclRegError -- * * Generate an error message based on the regexp status code. * * Results: * Places an error in the interpreter. * * Side effects: * Sets errorCode as well. * *---------------------------------------------------------------------- */ void TclRegError( Tcl_Interp *interp, /* Interpreter for error reporting. */ const char *msg, /* Message to prepend to error. */ int status) /* Status code to report. */ { char buf[100]; /* ample in practice */ char cbuf[TCL_INTEGER_SPACE]; size_t n; const char *p; Tcl_ResetResult(interp); n = TclReError(status, NULL, buf, sizeof(buf)); p = (n > sizeof(buf)) ? "..." : ""; Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s%s%s", msg, buf, p)); sprintf(cbuf, "%d", status); (void) TclReError(REG_ITOA, NULL, cbuf, sizeof(cbuf)); Tcl_SetErrorCode(interp, "REGEXP", cbuf, buf, NULL); } /* *---------------------------------------------------------------------- * * FreeRegexpInternalRep -- * * Deallocate the storage associated with a regexp object's internal * representation. * * Results: * None. * * Side effects: * Frees the compiled regular expression. * *---------------------------------------------------------------------- */ static void FreeRegexpInternalRep( Tcl_Obj *objPtr) /* Regexp object with internal rep to free. */ { TclRegexp *regexpRepPtr = objPtr->internalRep.twoPtrValue.ptr1; /* * If this is the last reference to the regexp, free it. */ if (regexpRepPtr->refCount-- <= 1) { FreeRegexp(regexpRepPtr); } objPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * DupRegexpInternalRep -- * * We copy the reference to the compiled regexp and bump its reference * count. * * Results: * None. * * Side effects: * Increments the reference count of the regexp. * *---------------------------------------------------------------------- */ static void DupRegexpInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { TclRegexp *regexpPtr = srcPtr->internalRep.twoPtrValue.ptr1; regexpPtr->refCount++; copyPtr->internalRep.twoPtrValue.ptr1 = srcPtr->internalRep.twoPtrValue.ptr1; copyPtr->typePtr = &tclRegexpType; } /* *---------------------------------------------------------------------- * * SetRegexpFromAny -- * * Attempt to generate a compiled regular expression for the Tcl object * "objPtr". * * Results: * The return value is TCL_OK or TCL_ERROR. If an error occurs during * conversion, an error message is left in the interpreter's result * unless "interp" is NULL. * * Side effects: * If no error occurs, a regular expression is stored as "objPtr"s * internal representation. * *---------------------------------------------------------------------- */ static int SetRegexpFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr) /* The object to convert. */ { if (Tcl_GetRegExpFromObj(interp, objPtr, REG_ADVANCED) == NULL) { return TCL_ERROR; } return TCL_OK; } /* *--------------------------------------------------------------------------- * * CompileRegexp -- * * Attempt to compile the given regexp pattern. If the compiled regular * expression can be found in the per-thread cache, it will be used * instead of compiling a new copy. * * Results: * The return value is a pointer to a newly allocated TclRegexp that * represents the compiled pattern, or NULL if the pattern could not be * compiled. If NULL is returned, an error message is left in the * interp's result. * * Side effects: * The thread-local regexp cache is updated and a new TclRegexp may be * allocated. * *---------------------------------------------------------------------- */ static TclRegexp * CompileRegexp( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ const char *string, /* The regexp to compile (UTF-8). */ int length, /* The length of the string in bytes. */ int flags) /* Compilation flags. */ { TclRegexp *regexpPtr; const Tcl_UniChar *uniString; int numChars, status, i, exact; Tcl_DString stringBuf; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!tsdPtr->initialized) { tsdPtr->initialized = 1; Tcl_CreateThreadExitHandler(FinalizeRegexp, NULL); } /* * This routine maintains a second-level regular expression cache in * addition to the per-object regexp cache. The per-thread cache is needed * to handle the case where for various reasons the object is lost between * invocations of the regexp command, but the literal pattern is the same. */ /* * Check the per-thread compiled regexp cache. We can only reuse a regexp * if it has the same pattern and the same flags. */ for (i = 0; (i < NUM_REGEXPS) && (tsdPtr->patterns[i] != NULL); i++) { if ((length == tsdPtr->patLengths[i]) && (tsdPtr->regexps[i]->flags == flags) && (strcmp(string, tsdPtr->patterns[i]) == 0)) { /* * Move the matched pattern to the first slot in the cache and * shift the other patterns down one position. */ if (i != 0) { int j; char *cachedString; cachedString = tsdPtr->patterns[i]; regexpPtr = tsdPtr->regexps[i]; for (j = i-1; j >= 0; j--) { tsdPtr->patterns[j+1] = tsdPtr->patterns[j]; tsdPtr->patLengths[j+1] = tsdPtr->patLengths[j]; tsdPtr->regexps[j+1] = tsdPtr->regexps[j]; } tsdPtr->patterns[0] = cachedString; tsdPtr->patLengths[0] = length; tsdPtr->regexps[0] = regexpPtr; } return tsdPtr->regexps[0]; } } /* * This is a new expression, so compile it and add it to the cache. */ regexpPtr = ckalloc(sizeof(TclRegexp)); regexpPtr->objPtr = NULL; regexpPtr->string = NULL; regexpPtr->details.rm_extend.rm_so = -1; regexpPtr->details.rm_extend.rm_eo = -1; /* * Get the up-to-date string representation and map to unicode. */ Tcl_DStringInit(&stringBuf); uniString = Tcl_UtfToUniCharDString(string, length, &stringBuf); numChars = Tcl_DStringLength(&stringBuf) / sizeof(Tcl_UniChar); /* * Compile the string and check for errors. */ regexpPtr->flags = flags; status = TclReComp(®expPtr->re, uniString, (size_t) numChars, flags); Tcl_DStringFree(&stringBuf); if (status != REG_OKAY) { /* * Clean up and report errors in the interpreter, if possible. */ ckfree(regexpPtr); if (interp) { TclRegError(interp, "couldn't compile regular expression pattern: ", status); } return NULL; } /* * Convert RE to a glob pattern equivalent, if any, and cache it. If this * is not possible, then globObjPtr will be NULL. This is used by * Tcl_RegExpExecObj to optionally do a fast match (avoids RE engine). */ if (TclReToGlob(NULL, string, length, &stringBuf, &exact, NULL) == TCL_OK) { regexpPtr->globObjPtr = TclDStringToObj(&stringBuf); Tcl_IncrRefCount(regexpPtr->globObjPtr); } else { regexpPtr->globObjPtr = NULL; } /* * Allocate enough space for all of the subexpressions, plus one extra for * the entire pattern. */ regexpPtr->matches = ckalloc(sizeof(regmatch_t) * (regexpPtr->re.re_nsub + 1)); /* * Initialize the refcount to one initially, since it is in the cache. */ regexpPtr->refCount = 1; /* * Free the last regexp, if necessary, and make room at the head of the * list for the new regexp. */ if (tsdPtr->patterns[NUM_REGEXPS-1] != NULL) { TclRegexp *oldRegexpPtr = tsdPtr->regexps[NUM_REGEXPS-1]; if (oldRegexpPtr->refCount-- <= 1) { FreeRegexp(oldRegexpPtr); } ckfree(tsdPtr->patterns[NUM_REGEXPS-1]); } for (i = NUM_REGEXPS - 2; i >= 0; i--) { tsdPtr->patterns[i+1] = tsdPtr->patterns[i]; tsdPtr->patLengths[i+1] = tsdPtr->patLengths[i]; tsdPtr->regexps[i+1] = tsdPtr->regexps[i]; } tsdPtr->patterns[0] = ckalloc(length + 1); memcpy(tsdPtr->patterns[0], string, (unsigned) length + 1); tsdPtr->patLengths[0] = length; tsdPtr->regexps[0] = regexpPtr; return regexpPtr; } /* *---------------------------------------------------------------------- * * FreeRegexp -- * * Release the storage associated with a TclRegexp. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void FreeRegexp( TclRegexp *regexpPtr) /* Compiled regular expression to free. */ { TclReFree(®expPtr->re); if (regexpPtr->globObjPtr) { TclDecrRefCount(regexpPtr->globObjPtr); } if (regexpPtr->matches) { ckfree(regexpPtr->matches); } ckfree(regexpPtr); } /* *---------------------------------------------------------------------- * * FinalizeRegexp -- * * Release the storage associated with the per-thread regexp cache. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void FinalizeRegexp( ClientData clientData) /* Not used. */ { int i; TclRegexp *regexpPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); for (i = 0; (i < NUM_REGEXPS) && (tsdPtr->patterns[i] != NULL); i++) { regexpPtr = tsdPtr->regexps[i]; if (regexpPtr->refCount-- <= 1) { FreeRegexp(regexpPtr); } ckfree(tsdPtr->patterns[i]); tsdPtr->patterns[i] = NULL; } /* * We may find ourselves reinitialized if another finalization routine * invokes regexps. */ tsdPtr->initialized = 0; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclLink.c0000644000175000017500000004624612663660065014763 0ustar sergeisergei/* * tclLink.c -- * * This file implements linked variables (a C variable that is tied to a * Tcl variable). The idea of linked variables was first suggested by * Andreas Stolcke and this implementation is based heavily on a * prototype implementation provided by him. * * Copyright (c) 1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * For each linked variable there is a data structure of the following type, * which describes the link and is the clientData for the trace set on the Tcl * variable. */ typedef struct Link { Tcl_Interp *interp; /* Interpreter containing Tcl variable. */ Tcl_Obj *varName; /* Name of variable (must be global). This is * needed during trace callbacks, since the * actual variable may be aliased at that time * via upvar. */ char *addr; /* Location of C variable. */ int type; /* Type of link (TCL_LINK_INT, etc.). */ union { char c; unsigned char uc; int i; unsigned int ui; short s; unsigned short us; long l; unsigned long ul; Tcl_WideInt w; Tcl_WideUInt uw; float f; double d; } lastValue; /* Last known value of C variable; used to * avoid string conversions. */ int flags; /* Miscellaneous one-bit values; see below for * definitions. */ } Link; /* * Definitions for flag bits: * LINK_READ_ONLY - 1 means errors should be generated if Tcl * script attempts to write variable. * LINK_BEING_UPDATED - 1 means that a call to Tcl_UpdateLinkedVar is * in progress for this variable, so trace * callbacks on the variable should be ignored. */ #define LINK_READ_ONLY 1 #define LINK_BEING_UPDATED 2 /* * Forward references to functions defined later in this file: */ static char * LinkTraceProc(ClientData clientData,Tcl_Interp *interp, const char *name1, const char *name2, int flags); static Tcl_Obj * ObjValue(Link *linkPtr); /* * Convenience macro for accessing the value of the C variable pointed to by a * link. Note that this macro produces something that may be regarded as an * lvalue or rvalue; it may be assigned to as well as read. Also note that * this macro assumes the name of the variable being accessed (linkPtr); this * is not strictly a good thing, but it keeps the code much shorter and * cleaner. */ #define LinkedVar(type) (*(type *) linkPtr->addr) /* *---------------------------------------------------------------------- * * Tcl_LinkVar -- * * Link a C variable to a Tcl variable so that changes to either one * causes the other to change. * * Results: * The return value is TCL_OK if everything went well or TCL_ERROR if an * error occurred (the interp's result is also set after errors). * * Side effects: * The value at *addr is linked to the Tcl variable "varName", using * "type" to convert between string values for Tcl and binary values for * *addr. * *---------------------------------------------------------------------- */ int Tcl_LinkVar( Tcl_Interp *interp, /* Interpreter in which varName exists. */ const char *varName, /* Name of a global variable in interp. */ char *addr, /* Address of a C variable to be linked to * varName. */ int type) /* Type of C variable: TCL_LINK_INT, etc. Also * may have TCL_LINK_READ_ONLY OR'ed in. */ { Tcl_Obj *objPtr; Link *linkPtr; int code; linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL, TCL_GLOBAL_ONLY, LinkTraceProc, (ClientData) NULL); if (linkPtr != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "variable '%s' is already linked", varName)); return TCL_ERROR; } linkPtr = ckalloc(sizeof(Link)); linkPtr->interp = interp; linkPtr->varName = Tcl_NewStringObj(varName, -1); Tcl_IncrRefCount(linkPtr->varName); linkPtr->addr = addr; linkPtr->type = type & ~TCL_LINK_READ_ONLY; if (type & TCL_LINK_READ_ONLY) { linkPtr->flags = LINK_READ_ONLY; } else { linkPtr->flags = 0; } objPtr = ObjValue(linkPtr); if (Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, objPtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { Tcl_DecrRefCount(linkPtr->varName); ckfree(linkPtr); return TCL_ERROR; } code = Tcl_TraceVar2(interp, varName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, LinkTraceProc, linkPtr); if (code != TCL_OK) { Tcl_DecrRefCount(linkPtr->varName); ckfree(linkPtr); } return code; } /* *---------------------------------------------------------------------- * * Tcl_UnlinkVar -- * * Destroy the link between a Tcl variable and a C variable. * * Results: * None. * * Side effects: * If "varName" was previously linked to a C variable, the link is broken * to make the variable independent. If there was no previous link for * "varName" then nothing happens. * *---------------------------------------------------------------------- */ void Tcl_UnlinkVar( Tcl_Interp *interp, /* Interpreter containing variable to unlink */ const char *varName) /* Global variable in interp to unlink. */ { Link *linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL, TCL_GLOBAL_ONLY, LinkTraceProc, NULL); if (linkPtr == NULL) { return; } Tcl_UntraceVar2(interp, varName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, LinkTraceProc, linkPtr); Tcl_DecrRefCount(linkPtr->varName); ckfree(linkPtr); } /* *---------------------------------------------------------------------- * * Tcl_UpdateLinkedVar -- * * This function is invoked after a linked variable has been changed by C * code. It updates the Tcl variable so that traces on the variable will * trigger. * * Results: * None. * * Side effects: * The Tcl variable "varName" is updated from its C value, causing traces * on the variable to trigger. * *---------------------------------------------------------------------- */ void Tcl_UpdateLinkedVar( Tcl_Interp *interp, /* Interpreter containing variable. */ const char *varName) /* Name of global variable that is linked. */ { Link *linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL, TCL_GLOBAL_ONLY, LinkTraceProc, NULL); int savedFlag; if (linkPtr == NULL) { return; } savedFlag = linkPtr->flags & LINK_BEING_UPDATED; linkPtr->flags |= LINK_BEING_UPDATED; Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); /* * Callback may have unlinked the variable. [Bug 1740631] */ linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL, TCL_GLOBAL_ONLY, LinkTraceProc, NULL); if (linkPtr != NULL) { linkPtr->flags = (linkPtr->flags & ~LINK_BEING_UPDATED) | savedFlag; } } /* *---------------------------------------------------------------------- * * LinkTraceProc -- * * This function is invoked when a linked Tcl variable is read, written, * or unset from Tcl. It's responsible for keeping the C variable in sync * with the Tcl variable. * * Results: * If all goes well, NULL is returned; otherwise an error message is * returned. * * Side effects: * The C variable may be updated to make it consistent with the Tcl * variable, or the Tcl variable may be overwritten to reject a * modification. * *---------------------------------------------------------------------- */ static char * LinkTraceProc( ClientData clientData, /* Contains information about the link. */ Tcl_Interp *interp, /* Interpreter containing Tcl variable. */ const char *name1, /* First part of variable name. */ const char *name2, /* Second part of variable name. */ int flags) /* Miscellaneous additional information. */ { Link *linkPtr = clientData; int changed, valueLength; const char *value; char **pp; Tcl_Obj *valueObj; int valueInt; Tcl_WideInt valueWide; double valueDouble; /* * If the variable is being unset, then just re-create it (with a trace) * unless the whole interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { if (Tcl_InterpDeleted(interp)) { Tcl_DecrRefCount(linkPtr->varName); ckfree(linkPtr); } else if (flags & TCL_TRACE_DESTROYED) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); Tcl_TraceVar2(interp, Tcl_GetString(linkPtr->varName), NULL, TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES |TCL_TRACE_UNSETS, LinkTraceProc, linkPtr); } return NULL; } /* * If we were invoked because of a call to Tcl_UpdateLinkedVar, then don't * do anything at all. In particular, we don't want to get upset that the * variable is being modified, even if it is supposed to be read-only. */ if (linkPtr->flags & LINK_BEING_UPDATED) { return NULL; } /* * For read accesses, update the Tcl variable if the C variable has * changed since the last time we updated the Tcl variable. */ if (flags & TCL_TRACE_READS) { switch (linkPtr->type) { case TCL_LINK_INT: case TCL_LINK_BOOLEAN: changed = (LinkedVar(int) != linkPtr->lastValue.i); break; case TCL_LINK_DOUBLE: changed = (LinkedVar(double) != linkPtr->lastValue.d); break; case TCL_LINK_WIDE_INT: changed = (LinkedVar(Tcl_WideInt) != linkPtr->lastValue.w); break; case TCL_LINK_WIDE_UINT: changed = (LinkedVar(Tcl_WideUInt) != linkPtr->lastValue.uw); break; case TCL_LINK_CHAR: changed = (LinkedVar(char) != linkPtr->lastValue.c); break; case TCL_LINK_UCHAR: changed = (LinkedVar(unsigned char) != linkPtr->lastValue.uc); break; case TCL_LINK_SHORT: changed = (LinkedVar(short) != linkPtr->lastValue.s); break; case TCL_LINK_USHORT: changed = (LinkedVar(unsigned short) != linkPtr->lastValue.us); break; case TCL_LINK_UINT: changed = (LinkedVar(unsigned int) != linkPtr->lastValue.ui); break; case TCL_LINK_LONG: changed = (LinkedVar(long) != linkPtr->lastValue.l); break; case TCL_LINK_ULONG: changed = (LinkedVar(unsigned long) != linkPtr->lastValue.ul); break; case TCL_LINK_FLOAT: changed = (LinkedVar(float) != linkPtr->lastValue.f); break; case TCL_LINK_STRING: changed = 1; break; default: return (char *) "internal error: bad linked variable type"; } if (changed) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); } return NULL; } /* * For writes, first make sure that the variable is writable. Then convert * the Tcl value to C if possible. If the variable isn't writable or can't * be converted, then restore the varaible's old value and return an * error. Another tricky thing: we have to save and restore the interp's * result, since the variable access could occur when the result has been * partially set. */ if (linkPtr->flags & LINK_READ_ONLY) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "linked variable is read-only"; } valueObj = Tcl_ObjGetVar2(interp, linkPtr->varName,NULL, TCL_GLOBAL_ONLY); if (valueObj == NULL) { /* * This shouldn't ever happen. */ return (char *) "internal error: linked variable couldn't be read"; } switch (linkPtr->type) { case TCL_LINK_INT: if (Tcl_GetIntFromObj(NULL, valueObj, &linkPtr->lastValue.i) != TCL_OK) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have integer value"; } LinkedVar(int) = linkPtr->lastValue.i; break; case TCL_LINK_WIDE_INT: if (Tcl_GetWideIntFromObj(NULL, valueObj, &linkPtr->lastValue.w) != TCL_OK) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have integer value"; } LinkedVar(Tcl_WideInt) = linkPtr->lastValue.w; break; case TCL_LINK_DOUBLE: if (Tcl_GetDoubleFromObj(NULL, valueObj, &linkPtr->lastValue.d) != TCL_OK) { #ifdef ACCEPT_NAN if (valueObj->typePtr != &tclDoubleType) { #endif Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have real value"; #ifdef ACCEPT_NAN } linkPtr->lastValue.d = valueObj->internalRep.doubleValue; #endif } LinkedVar(double) = linkPtr->lastValue.d; break; case TCL_LINK_BOOLEAN: if (Tcl_GetBooleanFromObj(NULL, valueObj, &linkPtr->lastValue.i) != TCL_OK) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have boolean value"; } LinkedVar(int) = linkPtr->lastValue.i; break; case TCL_LINK_CHAR: if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK || valueInt < SCHAR_MIN || valueInt > SCHAR_MAX) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have char value"; } linkPtr->lastValue.c = (char)valueInt; LinkedVar(char) = linkPtr->lastValue.c; break; case TCL_LINK_UCHAR: if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK || valueInt < 0 || valueInt > UCHAR_MAX) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have unsigned char value"; } linkPtr->lastValue.uc = (unsigned char) valueInt; LinkedVar(unsigned char) = linkPtr->lastValue.uc; break; case TCL_LINK_SHORT: if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK || valueInt < SHRT_MIN || valueInt > SHRT_MAX) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have short value"; } linkPtr->lastValue.s = (short)valueInt; LinkedVar(short) = linkPtr->lastValue.s; break; case TCL_LINK_USHORT: if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK || valueInt < 0 || valueInt > USHRT_MAX) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have unsigned short value"; } linkPtr->lastValue.us = (unsigned short)valueInt; LinkedVar(unsigned short) = linkPtr->lastValue.us; break; case TCL_LINK_UINT: if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK || valueWide < 0 || valueWide > UINT_MAX) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have unsigned int value"; } linkPtr->lastValue.ui = (unsigned int)valueWide; LinkedVar(unsigned int) = linkPtr->lastValue.ui; break; case TCL_LINK_LONG: if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK || valueWide < LONG_MIN || valueWide > LONG_MAX) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have long value"; } linkPtr->lastValue.l = (long)valueWide; LinkedVar(long) = linkPtr->lastValue.l; break; case TCL_LINK_ULONG: if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK || valueWide < 0 || (Tcl_WideUInt) valueWide > ULONG_MAX) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have unsigned long value"; } linkPtr->lastValue.ul = (unsigned long)valueWide; LinkedVar(unsigned long) = linkPtr->lastValue.ul; break; case TCL_LINK_WIDE_UINT: /* * FIXME: represent as a bignum. */ if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have unsigned wide int value"; } linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide; LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw; break; case TCL_LINK_FLOAT: if (Tcl_GetDoubleFromObj(interp, valueObj, &valueDouble) != TCL_OK || valueDouble < -FLT_MAX || valueDouble > FLT_MAX) { Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), TCL_GLOBAL_ONLY); return (char *) "variable must have float value"; } linkPtr->lastValue.f = (float)valueDouble; LinkedVar(float) = linkPtr->lastValue.f; break; case TCL_LINK_STRING: value = Tcl_GetStringFromObj(valueObj, &valueLength); valueLength++; pp = (char **) linkPtr->addr; *pp = ckrealloc(*pp, valueLength); memcpy(*pp, value, (unsigned) valueLength); break; default: return (char *) "internal error: bad linked variable type"; } return NULL; } /* *---------------------------------------------------------------------- * * ObjValue -- * * Converts the value of a C variable to a Tcl_Obj* for use in a Tcl * variable to which it is linked. * * Results: * The return value is a pointer to a Tcl_Obj that represents the value * of the C variable given by linkPtr. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Tcl_Obj * ObjValue( Link *linkPtr) /* Structure describing linked variable. */ { char *p; Tcl_Obj *resultObj; switch (linkPtr->type) { case TCL_LINK_INT: linkPtr->lastValue.i = LinkedVar(int); return Tcl_NewIntObj(linkPtr->lastValue.i); case TCL_LINK_WIDE_INT: linkPtr->lastValue.w = LinkedVar(Tcl_WideInt); return Tcl_NewWideIntObj(linkPtr->lastValue.w); case TCL_LINK_DOUBLE: linkPtr->lastValue.d = LinkedVar(double); return Tcl_NewDoubleObj(linkPtr->lastValue.d); case TCL_LINK_BOOLEAN: linkPtr->lastValue.i = LinkedVar(int); return Tcl_NewBooleanObj(linkPtr->lastValue.i != 0); case TCL_LINK_CHAR: linkPtr->lastValue.c = LinkedVar(char); return Tcl_NewIntObj(linkPtr->lastValue.c); case TCL_LINK_UCHAR: linkPtr->lastValue.uc = LinkedVar(unsigned char); return Tcl_NewIntObj(linkPtr->lastValue.uc); case TCL_LINK_SHORT: linkPtr->lastValue.s = LinkedVar(short); return Tcl_NewIntObj(linkPtr->lastValue.s); case TCL_LINK_USHORT: linkPtr->lastValue.us = LinkedVar(unsigned short); return Tcl_NewIntObj(linkPtr->lastValue.us); case TCL_LINK_UINT: linkPtr->lastValue.ui = LinkedVar(unsigned int); return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ui); case TCL_LINK_LONG: linkPtr->lastValue.l = LinkedVar(long); return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.l); case TCL_LINK_ULONG: linkPtr->lastValue.ul = LinkedVar(unsigned long); return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ul); case TCL_LINK_FLOAT: linkPtr->lastValue.f = LinkedVar(float); return Tcl_NewDoubleObj(linkPtr->lastValue.f); case TCL_LINK_WIDE_UINT: linkPtr->lastValue.uw = LinkedVar(Tcl_WideUInt); /* * FIXME: represent as a bignum. */ return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.uw); case TCL_LINK_STRING: p = LinkedVar(char *); if (p == NULL) { TclNewLiteralStringObj(resultObj, "NULL"); return resultObj; } return Tcl_NewStringObj(p, -1); /* * This code only gets executed if the link type is unknown (shouldn't * ever happen). */ default: TclNewLiteralStringObj(resultObj, "??"); return resultObj; } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclCmdMZ.c0000644000175000017500000037147212663660065015042 0ustar sergeisergei/* * tclCmdMZ.c -- * * This file contains the top-level command routines for most of the Tcl * built-in commands whose names begin with the letters M to Z. It * contains only commands in the generic core (i.e. those that don't * depend much upon UNIX facilities). * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-2000 Scriptics Corporation. * Copyright (c) 2002 ActiveState Corporation. * Copyright (c) 2003-2009 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclRegexp.h" #include "tclStringTrim.h" static inline Tcl_Obj * During(Tcl_Interp *interp, int resultCode, Tcl_Obj *oldOptions, Tcl_Obj *errorInfo); static int SwitchPostProc(ClientData data[], Tcl_Interp *interp, int result); static int TryPostBody(ClientData data[], Tcl_Interp *interp, int result); static int TryPostFinal(ClientData data[], Tcl_Interp *interp, int result); static int TryPostHandler(ClientData data[], Tcl_Interp *interp, int result); static int UniCharIsAscii(int character); static int UniCharIsHexDigit(int character); /* * Default set of characters to trim in [string trim] and friends. This is a * UTF-8 literal string containing all Unicode space characters [TIP #413] */ const char tclDefaultTrimSet[] = "\x09\x0a\x0b\x0c\x0d " /* ASCII */ "\xc0\x80" /* nul (U+0000) */ "\xc2\x85" /* next line (U+0085) */ "\xc2\xa0" /* non-breaking space (U+00a0) */ "\xe1\x9a\x80" /* ogham space mark (U+1680) */ "\xe1\xa0\x8e" /* mongolian vowel separator (U+180e) */ "\xe2\x80\x80" /* en quad (U+2000) */ "\xe2\x80\x81" /* em quad (U+2001) */ "\xe2\x80\x82" /* en space (U+2002) */ "\xe2\x80\x83" /* em space (U+2003) */ "\xe2\x80\x84" /* three-per-em space (U+2004) */ "\xe2\x80\x85" /* four-per-em space (U+2005) */ "\xe2\x80\x86" /* six-per-em space (U+2006) */ "\xe2\x80\x87" /* figure space (U+2007) */ "\xe2\x80\x88" /* punctuation space (U+2008) */ "\xe2\x80\x89" /* thin space (U+2009) */ "\xe2\x80\x8a" /* hair space (U+200a) */ "\xe2\x80\x8b" /* zero width space (U+200b) */ "\xe2\x80\xa8" /* line separator (U+2028) */ "\xe2\x80\xa9" /* paragraph separator (U+2029) */ "\xe2\x80\xaf" /* narrow no-break space (U+202f) */ "\xe2\x81\x9f" /* medium mathematical space (U+205f) */ "\xe2\x81\xa0" /* word joiner (U+2060) */ "\xe3\x80\x80" /* ideographic space (U+3000) */ "\xef\xbb\xbf" /* zero width no-break space (U+feff) */ ; /* *---------------------------------------------------------------------- * * Tcl_PwdObjCmd -- * * This procedure is invoked to process the "pwd" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_PwdObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *retVal; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } retVal = Tcl_FSGetCwd(interp); if (retVal == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, retVal); Tcl_DecrRefCount(retVal); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_RegexpObjCmd -- * * This procedure is invoked to process the "regexp" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_RegexpObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int i, indices, match, about, offset, all, doinline, numMatchesSaved; int cflags, eflags, stringLength, matchLength; Tcl_RegExp regExpr; Tcl_Obj *objPtr, *startIndex = NULL, *resultPtr = NULL; Tcl_RegExpInfo info; static const char *const options[] = { "-all", "-about", "-indices", "-inline", "-expanded", "-line", "-linestop", "-lineanchor", "-nocase", "-start", "--", NULL }; enum options { REGEXP_ALL, REGEXP_ABOUT, REGEXP_INDICES, REGEXP_INLINE, REGEXP_EXPANDED,REGEXP_LINE, REGEXP_LINESTOP,REGEXP_LINEANCHOR, REGEXP_NOCASE, REGEXP_START, REGEXP_LAST }; indices = 0; about = 0; cflags = TCL_REG_ADVANCED; offset = 0; all = 0; doinline = 0; for (i = 1; i < objc; i++) { const char *name; int index; name = TclGetString(objv[i]); if (name[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", TCL_EXACT, &index) != TCL_OK) { goto optionError; } switch ((enum options) index) { case REGEXP_ALL: all = 1; break; case REGEXP_INDICES: indices = 1; break; case REGEXP_INLINE: doinline = 1; break; case REGEXP_NOCASE: cflags |= TCL_REG_NOCASE; break; case REGEXP_ABOUT: about = 1; break; case REGEXP_EXPANDED: cflags |= TCL_REG_EXPANDED; break; case REGEXP_LINE: cflags |= TCL_REG_NEWLINE; break; case REGEXP_LINESTOP: cflags |= TCL_REG_NLSTOP; break; case REGEXP_LINEANCHOR: cflags |= TCL_REG_NLANCH; break; case REGEXP_START: { int temp; if (++i >= objc) { goto endOfForLoop; } if (TclGetIntForIndexM(interp, objv[i], 0, &temp) != TCL_OK) { goto optionError; } if (startIndex) { Tcl_DecrRefCount(startIndex); } startIndex = objv[i]; Tcl_IncrRefCount(startIndex); break; } case REGEXP_LAST: i++; goto endOfForLoop; } } endOfForLoop: if ((objc - i) < (2 - about)) { Tcl_WrongNumArgs(interp, 1, objv, "?-option ...? exp string ?matchVar? ?subMatchVar ...?"); goto optionError; } objc -= i; objv += i; /* * Check if the user requested -inline, but specified match variables; a * no-no. */ if (doinline && ((objc - 2) != 0)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "regexp match variables not allowed when using -inline", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "REGEXP", "MIX_VAR_INLINE", NULL); goto optionError; } /* * Handle the odd about case separately. */ if (about) { regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags); if ((regExpr == NULL) || (TclRegAbout(interp, regExpr) < 0)) { optionError: if (startIndex) { Tcl_DecrRefCount(startIndex); } return TCL_ERROR; } return TCL_OK; } /* * Get the length of the string that we are matching against so we can do * the termination test for -all matches. Do this before getting the * regexp to avoid shimmering problems. */ objPtr = objv[1]; stringLength = Tcl_GetCharLength(objPtr); if (startIndex) { TclGetIntForIndexM(NULL, startIndex, stringLength, &offset); Tcl_DecrRefCount(startIndex); if (offset < 0) { offset = 0; } } regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags); if (regExpr == NULL) { return TCL_ERROR; } objc -= 2; objv += 2; if (doinline) { /* * Save all the subexpressions, as we will return them as a list */ numMatchesSaved = -1; } else { /* * Save only enough subexpressions for matches we want to keep, expect * in the case of -all, where we need to keep at least one to know * where to move the offset. */ numMatchesSaved = (objc == 0) ? all : objc; } /* * The following loop is to handle multiple matches within the same source * string; each iteration handles one match. If "-all" hasn't been * specified then the loop body only gets executed once. We terminate the * loop when the starting offset is past the end of the string. */ while (1) { /* * Pass either 0 or TCL_REG_NOTBOL in the eflags. Passing * TCL_REG_NOTBOL indicates that the character at offset should not be * considered the start of the line. If for example the pattern {^} is * passed and -start is positive, then the pattern will not match the * start of the string unless the previous character is a newline. */ if (offset == 0) { eflags = 0; } else if (offset > stringLength) { eflags = TCL_REG_NOTBOL; } else if (Tcl_GetUniChar(objPtr, offset-1) == (Tcl_UniChar)'\n') { eflags = 0; } else { eflags = TCL_REG_NOTBOL; } match = Tcl_RegExpExecObj(interp, regExpr, objPtr, offset, numMatchesSaved, eflags); if (match < 0) { return TCL_ERROR; } if (match == 0) { /* * We want to set the value of the intepreter result only when * this is the first time through the loop. */ if (all <= 1) { /* * If inlining, the interpreter's object result remains an * empty list, otherwise set it to an integer object w/ value * 0. */ if (!doinline) { Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); } return TCL_OK; } break; } /* * If additional variable names have been specified, return index * information in those variables. */ Tcl_RegExpGetInfo(regExpr, &info); if (doinline) { /* * It's the number of substitutions, plus one for the matchVar at * index 0 */ objc = info.nsubs + 1; if (all <= 1) { resultPtr = Tcl_NewObj(); } } for (i = 0; i < objc; i++) { Tcl_Obj *newPtr; if (indices) { int start, end; Tcl_Obj *objs[2]; /* * Only adjust the match area if there was a match for that * area. (Scriptics Bug 4391/SF Bug #219232) */ if (i <= info.nsubs && info.matches[i].start >= 0) { start = offset + info.matches[i].start; end = offset + info.matches[i].end; /* * Adjust index so it refers to the last character in the * match instead of the first character after the match. */ if (end >= offset) { end--; } } else { start = -1; end = -1; } objs[0] = Tcl_NewLongObj(start); objs[1] = Tcl_NewLongObj(end); newPtr = Tcl_NewListObj(2, objs); } else { if (i <= info.nsubs) { newPtr = Tcl_GetRange(objPtr, offset + info.matches[i].start, offset + info.matches[i].end - 1); } else { newPtr = Tcl_NewObj(); } } if (doinline) { if (Tcl_ListObjAppendElement(interp, resultPtr, newPtr) != TCL_OK) { Tcl_DecrRefCount(newPtr); Tcl_DecrRefCount(resultPtr); return TCL_ERROR; } } else { if (Tcl_ObjSetVar2(interp, objv[i], NULL, newPtr, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } } } if (all == 0) { break; } /* * Adjust the offset to the character just after the last one in the * matchVar and increment all to count how many times we are making a * match. We always increment the offset by at least one to prevent * endless looping (as in the case: regexp -all {a*} a). Otherwise, * when we match the NULL string at the end of the input string, we * will loop indefinately (because the length of the match is 0, so * offset never changes). */ matchLength = (info.matches[0].end - info.matches[0].start); offset += info.matches[0].end; /* * A match of length zero could happen for {^} {$} or {.*} and in * these cases we always want to bump the index up one. */ if (matchLength == 0) { offset++; } all++; if (offset >= stringLength) { break; } } /* * Set the interpreter's object result to an integer object with value 1 * if -all wasn't specified, otherwise it's all-1 (the number of times * through the while - 1). */ if (doinline) { Tcl_SetObjResult(interp, resultPtr); } else { Tcl_SetObjResult(interp, Tcl_NewIntObj(all ? all-1 : 1)); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_RegsubObjCmd -- * * This procedure is invoked to process the "regsub" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_RegsubObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int idx, result, cflags, all, wlen, wsublen, numMatches, offset; int start, end, subStart, subEnd, match; Tcl_RegExp regExpr; Tcl_RegExpInfo info; Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL; Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend; static const char *const options[] = { "-all", "-nocase", "-expanded", "-line", "-linestop", "-lineanchor", "-start", "--", NULL }; enum options { REGSUB_ALL, REGSUB_NOCASE, REGSUB_EXPANDED, REGSUB_LINE, REGSUB_LINESTOP, REGSUB_LINEANCHOR, REGSUB_START, REGSUB_LAST }; cflags = TCL_REG_ADVANCED; all = 0; offset = 0; resultPtr = NULL; for (idx = 1; idx < objc; idx++) { const char *name; int index; name = TclGetString(objv[idx]); if (name[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[idx], options, "option", TCL_EXACT, &index) != TCL_OK) { goto optionError; } switch ((enum options) index) { case REGSUB_ALL: all = 1; break; case REGSUB_NOCASE: cflags |= TCL_REG_NOCASE; break; case REGSUB_EXPANDED: cflags |= TCL_REG_EXPANDED; break; case REGSUB_LINE: cflags |= TCL_REG_NEWLINE; break; case REGSUB_LINESTOP: cflags |= TCL_REG_NLSTOP; break; case REGSUB_LINEANCHOR: cflags |= TCL_REG_NLANCH; break; case REGSUB_START: { int temp; if (++idx >= objc) { goto endOfForLoop; } if (TclGetIntForIndexM(interp, objv[idx], 0, &temp) != TCL_OK) { goto optionError; } if (startIndex) { Tcl_DecrRefCount(startIndex); } startIndex = objv[idx]; Tcl_IncrRefCount(startIndex); break; } case REGSUB_LAST: idx++; goto endOfForLoop; } } endOfForLoop: if (objc-idx < 3 || objc-idx > 4) { Tcl_WrongNumArgs(interp, 1, objv, "?-option ...? exp string subSpec ?varName?"); optionError: if (startIndex) { Tcl_DecrRefCount(startIndex); } return TCL_ERROR; } objc -= idx; objv += idx; if (startIndex) { int stringLength = Tcl_GetCharLength(objv[1]); TclGetIntForIndexM(NULL, startIndex, stringLength, &offset); Tcl_DecrRefCount(startIndex); if (offset < 0) { offset = 0; } } if (all && (offset == 0) && (strpbrk(TclGetString(objv[2]), "&\\") == NULL) && (strpbrk(TclGetString(objv[0]), "*+?{}()[].\\|^$") == NULL)) { /* * This is a simple one pair string map situation. We make use of a * slightly modified version of the one pair STR_MAP code. */ int slen, nocase; int (*strCmpFn)(const Tcl_UniChar*,const Tcl_UniChar*,unsigned long); Tcl_UniChar *p, wsrclc; numMatches = 0; nocase = (cflags & TCL_REG_NOCASE); strCmpFn = nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp; wsrc = Tcl_GetUnicodeFromObj(objv[0], &slen); wstring = Tcl_GetUnicodeFromObj(objv[1], &wlen); wsubspec = Tcl_GetUnicodeFromObj(objv[2], &wsublen); wend = wstring + wlen - (slen ? slen - 1 : 0); result = TCL_OK; if (slen == 0) { /* * regsub behavior for "" matches between each character. 'string * map' skips the "" case. */ if (wstring < wend) { resultPtr = Tcl_NewUnicodeObj(wstring, 0); Tcl_IncrRefCount(resultPtr); for (; wstring < wend; wstring++) { Tcl_AppendUnicodeToObj(resultPtr, wsubspec, wsublen); Tcl_AppendUnicodeToObj(resultPtr, wstring, 1); numMatches++; } wlen = 0; } } else { wsrclc = Tcl_UniCharToLower(*wsrc); for (p = wfirstChar = wstring; wstring < wend; wstring++) { if ((*wstring == *wsrc || (nocase && Tcl_UniCharToLower(*wstring)==wsrclc)) && (slen==1 || (strCmpFn(wstring, wsrc, (unsigned long) slen) == 0))) { if (numMatches == 0) { resultPtr = Tcl_NewUnicodeObj(wstring, 0); Tcl_IncrRefCount(resultPtr); } if (p != wstring) { Tcl_AppendUnicodeToObj(resultPtr, p, wstring - p); p = wstring + slen; } else { p += slen; } wstring = p - 1; Tcl_AppendUnicodeToObj(resultPtr, wsubspec, wsublen); numMatches++; } } if (numMatches) { wlen = wfirstChar + wlen - p; wstring = p; } } objPtr = NULL; subPtr = NULL; goto regsubDone; } regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags); if (regExpr == NULL) { return TCL_ERROR; } /* * Make sure to avoid problems where the objects are shared. This can * cause RegExpObj <> UnicodeObj shimmering that causes data corruption. * [Bug #461322] */ if (objv[1] == objv[0]) { objPtr = Tcl_DuplicateObj(objv[1]); } else { objPtr = objv[1]; } wstring = Tcl_GetUnicodeFromObj(objPtr, &wlen); if (objv[2] == objv[0]) { subPtr = Tcl_DuplicateObj(objv[2]); } else { subPtr = objv[2]; } wsubspec = Tcl_GetUnicodeFromObj(subPtr, &wsublen); result = TCL_OK; /* * The following loop is to handle multiple matches within the same source * string; each iteration handles one match and its corresponding * substitution. If "-all" hasn't been specified then the loop body only * gets executed once. We must use 'offset <= wlen' in particular for the * case where the regexp pattern can match the empty string - this is * useful when doing, say, 'regsub -- ^ $str ...' when $str might be * empty. */ numMatches = 0; for ( ; offset <= wlen; ) { /* * The flags argument is set if string is part of a larger string, so * that "^" won't match. */ match = Tcl_RegExpExecObj(interp, regExpr, objPtr, offset, 10 /* matches */, ((offset > 0 && (wstring[offset-1] != (Tcl_UniChar)'\n')) ? TCL_REG_NOTBOL : 0)); if (match < 0) { result = TCL_ERROR; goto done; } if (match == 0) { break; } if (numMatches == 0) { resultPtr = Tcl_NewUnicodeObj(wstring, 0); Tcl_IncrRefCount(resultPtr); if (offset > 0) { /* * Copy the initial portion of the string in if an offset was * specified. */ Tcl_AppendUnicodeToObj(resultPtr, wstring, offset); } } numMatches++; /* * Copy the portion of the source string before the match to the * result variable. */ Tcl_RegExpGetInfo(regExpr, &info); start = info.matches[0].start; end = info.matches[0].end; Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, start); /* * Append the subSpec argument to the variable, making appropriate * substitutions. This code is a bit hairy because of the backslash * conventions and because the code saves up ranges of characters in * subSpec to reduce the number of calls to Tcl_SetVar. */ wsrc = wfirstChar = wsubspec; wend = wsubspec + wsublen; for (ch = *wsrc; wsrc != wend; wsrc++, ch = *wsrc) { if (ch == '&') { idx = 0; } else if (ch == '\\') { ch = wsrc[1]; if ((ch >= '0') && (ch <= '9')) { idx = ch - '0'; } else if ((ch == '\\') || (ch == '&')) { *wsrc = ch; Tcl_AppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar + 1); *wsrc = '\\'; wfirstChar = wsrc + 2; wsrc++; continue; } else { continue; } } else { continue; } if (wfirstChar != wsrc) { Tcl_AppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar); } if (idx <= info.nsubs) { subStart = info.matches[idx].start; subEnd = info.matches[idx].end; if ((subStart >= 0) && (subEnd >= 0)) { Tcl_AppendUnicodeToObj(resultPtr, wstring + offset + subStart, subEnd - subStart); } } if (*wsrc == '\\') { wsrc++; } wfirstChar = wsrc + 1; } if (wfirstChar != wsrc) { Tcl_AppendUnicodeToObj(resultPtr, wfirstChar, wsrc - wfirstChar); } if (end == 0) { /* * Always consume at least one character of the input string in * order to prevent infinite loops. */ if (offset < wlen) { Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1); } offset++; } else { offset += end; if (start == end) { /* * We matched an empty string, which means we must go forward * one more step so we don't match again at the same spot. */ if (offset < wlen) { Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1); } offset++; } } if (!all) { break; } } /* * Copy the portion of the source string after the last match to the * result variable. */ regsubDone: if (numMatches == 0) { /* * On zero matches, just ignore the offset, since it shouldn't matter * to us in this case, and the user may have skewed it. */ resultPtr = objv[1]; Tcl_IncrRefCount(resultPtr); } else if (offset < wlen) { Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, wlen - offset); } if (objc == 4) { if (Tcl_ObjSetVar2(interp, objv[3], NULL, resultPtr, TCL_LEAVE_ERR_MSG) == NULL) { result = TCL_ERROR; } else { /* * Set the interpreter's object result to an integer object * holding the number of matches. */ Tcl_SetObjResult(interp, Tcl_NewIntObj(numMatches)); } } else { /* * No varname supplied, so just return the modified string. */ Tcl_SetObjResult(interp, resultPtr); } done: if (objPtr && (objv[1] == objv[0])) { Tcl_DecrRefCount(objPtr); } if (subPtr && (objv[2] == objv[0])) { Tcl_DecrRefCount(subPtr); } if (resultPtr) { Tcl_DecrRefCount(resultPtr); } return result; } /* *---------------------------------------------------------------------- * * Tcl_RenameObjCmd -- * * This procedure is invoked to process the "rename" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_RenameObjCmd( ClientData dummy, /* Arbitrary value passed to the command. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *oldName, *newName; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "oldName newName"); return TCL_ERROR; } oldName = TclGetString(objv[1]); newName = TclGetString(objv[2]); return TclRenameCommand(interp, oldName, newName); } /* *---------------------------------------------------------------------- * * Tcl_ReturnObjCmd -- * * This object-based procedure is invoked to process the "return" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_ReturnObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int code, level; Tcl_Obj *returnOpts; /* * General syntax: [return ?-option value ...? ?result?] * An even number of words means an explicit result argument is present. */ int explicitResult = (0 == (objc % 2)); int numOptionWords = objc - 1 - explicitResult; if (TCL_ERROR == TclMergeReturnOptions(interp, numOptionWords, objv+1, &returnOpts, &code, &level)) { return TCL_ERROR; } code = TclProcessReturn(interp, code, level, returnOpts); if (explicitResult) { Tcl_SetObjResult(interp, objv[objc-1]); } return code; } /* *---------------------------------------------------------------------- * * Tcl_SourceObjCmd -- * * This procedure is invoked to process the "source" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_SourceObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRSourceObjCmd, dummy, objc, objv); } int TclNRSourceObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *encodingName = NULL; Tcl_Obj *fileName; if (objc != 2 && objc !=4) { Tcl_WrongNumArgs(interp, 1, objv, "?-encoding name? fileName"); return TCL_ERROR; } fileName = objv[objc-1]; if (objc == 4) { static const char *const options[] = { "-encoding", NULL }; int index; if (TCL_ERROR == Tcl_GetIndexFromObj(interp, objv[1], options, "option", TCL_EXACT, &index)) { return TCL_ERROR; } encodingName = TclGetString(objv[2]); } return TclNREvalFile(interp, fileName, encodingName); } /* *---------------------------------------------------------------------- * * Tcl_SplitObjCmd -- * * This procedure is invoked to process the "split" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_SplitObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_UniChar ch; int len; const char *splitChars; const char *stringPtr; const char *end; int splitCharLen, stringLen; Tcl_Obj *listPtr, *objPtr; if (objc == 2) { splitChars = " \n\t\r"; splitCharLen = 4; } else if (objc == 3) { splitChars = TclGetStringFromObj(objv[2], &splitCharLen); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?splitChars?"); return TCL_ERROR; } stringPtr = TclGetStringFromObj(objv[1], &stringLen); end = stringPtr + stringLen; listPtr = Tcl_NewObj(); if (stringLen == 0) { /* * Do nothing. */ } else if (splitCharLen == 0) { Tcl_HashTable charReuseTable; Tcl_HashEntry *hPtr; int isNew; /* * Handle the special case of splitting on every character. * * Uses a hash table to ensure that each kind of character has only * one Tcl_Obj instance (multiply-referenced) in the final list. This * is a *major* win when splitting on a long string (especially in the * megabyte range!) - DKF */ Tcl_InitHashTable(&charReuseTable, TCL_ONE_WORD_KEYS); for ( ; stringPtr < end; stringPtr += len) { len = TclUtfToUniChar(stringPtr, &ch); /* * Assume Tcl_UniChar is an integral type... */ hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR((int) ch), &isNew); if (isNew) { TclNewStringObj(objPtr, stringPtr, len); /* * Don't need to fiddle with refcount... */ Tcl_SetHashValue(hPtr, objPtr); } else { objPtr = Tcl_GetHashValue(hPtr); } Tcl_ListObjAppendElement(NULL, listPtr, objPtr); } Tcl_DeleteHashTable(&charReuseTable); } else if (splitCharLen == 1) { char *p; /* * Handle the special case of splitting on a single character. This is * only true for the one-char ASCII case, as one unicode char is > 1 * byte in length. */ while (*stringPtr && (p=strchr(stringPtr,(int)*splitChars)) != NULL) { objPtr = Tcl_NewStringObj(stringPtr, p - stringPtr); Tcl_ListObjAppendElement(NULL, listPtr, objPtr); stringPtr = p + 1; } TclNewStringObj(objPtr, stringPtr, end - stringPtr); Tcl_ListObjAppendElement(NULL, listPtr, objPtr); } else { const char *element, *p, *splitEnd; int splitLen; Tcl_UniChar splitChar; /* * Normal case: split on any of a given set of characters. Discard * instances of the split characters. */ splitEnd = splitChars + splitCharLen; for (element = stringPtr; stringPtr < end; stringPtr += len) { len = TclUtfToUniChar(stringPtr, &ch); for (p = splitChars; p < splitEnd; p += splitLen) { splitLen = TclUtfToUniChar(p, &splitChar); if (ch == splitChar) { TclNewStringObj(objPtr, element, stringPtr - element); Tcl_ListObjAppendElement(NULL, listPtr, objPtr); element = stringPtr + len; break; } } } TclNewStringObj(objPtr, element, stringPtr - element); Tcl_ListObjAppendElement(NULL, listPtr, objPtr); } Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringFirstCmd -- * * This procedure is invoked to process the "string first" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringFirstCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_UniChar *needleStr, *haystackStr; int match, start, needleLen, haystackLen; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "needleString haystackString ?startIndex?"); return TCL_ERROR; } /* * We are searching haystackStr for the sequence needleStr. */ match = -1; start = 0; haystackLen = -1; needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); if (objc == 4) { /* * If a startIndex is specified, we will need to fast forward to that * point in the string before we think about a match. */ if (TclGetIntForIndexM(interp, objv[3], haystackLen-1, &start) != TCL_OK){ return TCL_ERROR; } /* * Reread to prevent shimmering problems. */ needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); if (start >= haystackLen) { goto str_first_done; } else if (start > 0) { haystackStr += start; haystackLen -= start; } else if (start < 0) { /* * Invalid start index mapped to string start; Bug #423581 */ start = 0; } } /* * If the length of the needle is more than the length of the haystack, it * cannot be contained in there so we can avoid searching. [Bug 2960021] */ if (needleLen > 0 && needleLen <= haystackLen) { register Tcl_UniChar *p, *end; end = haystackStr + haystackLen - needleLen + 1; for (p = haystackStr; p < end; p++) { /* * Scan forward to find the first character. */ if ((*p == *needleStr) && (TclUniCharNcmp(needleStr, p, (unsigned long) needleLen) == 0)) { match = p - haystackStr; break; } } } /* * Compute the character index of the matching string by counting the * number of characters before the match. */ if ((match != -1) && (objc == 4)) { match += start; } str_first_done: Tcl_SetObjResult(interp, Tcl_NewIntObj(match)); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringLastCmd -- * * This procedure is invoked to process the "string last" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringLastCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_UniChar *needleStr, *haystackStr, *p; int match, start, needleLen, haystackLen; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "needleString haystackString ?startIndex?"); return TCL_ERROR; } /* * We are searching haystackString for the sequence needleString. */ match = -1; start = 0; haystackLen = -1; needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); if (objc == 4) { /* * If a startIndex is specified, we will need to restrict the string * range to that char index in the string */ if (TclGetIntForIndexM(interp, objv[3], haystackLen-1, &start) != TCL_OK){ return TCL_ERROR; } /* * Reread to prevent shimmering problems. */ needleStr = Tcl_GetUnicodeFromObj(objv[1], &needleLen); haystackStr = Tcl_GetUnicodeFromObj(objv[2], &haystackLen); if (start < 0) { goto str_last_done; } else if (start < haystackLen) { p = haystackStr + start + 1 - needleLen; } else { p = haystackStr + haystackLen - needleLen; } } else { p = haystackStr + haystackLen - needleLen; } /* * If the length of the needle is more than the length of the haystack, it * cannot be contained in there so we can avoid searching. [Bug 2960021] */ if (needleLen > 0 && needleLen <= haystackLen) { for (; p >= haystackStr; p--) { /* * Scan backwards to find the first character. */ if ((*p == *needleStr) && !memcmp(needleStr, p, sizeof(Tcl_UniChar) * (size_t)needleLen)) { match = p - haystackStr; break; } } } str_last_done: Tcl_SetObjResult(interp, Tcl_NewIntObj(match)); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringIndexCmd -- * * This procedure is invoked to process the "string index" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringIndexCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int length, index; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "string charIndex"); return TCL_ERROR; } /* * Get the char length to calulate what 'end' means. */ length = Tcl_GetCharLength(objv[1]); if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK) { return TCL_ERROR; } if ((index >= 0) && (index < length)) { Tcl_UniChar ch = Tcl_GetUniChar(objv[1], index); /* * If we have a ByteArray object, we're careful to generate a new * bytearray for a result. */ if (TclIsPureByteArray(objv[1])) { unsigned char uch = (unsigned char) ch; Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(&uch, 1)); } else { char buf[TCL_UTF_MAX]; length = Tcl_UniCharToUtf(ch, buf); Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, length)); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * StringIsCmd -- * * This procedure is invoked to process the "string is" Tcl command. See * the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringIsCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1, *end, *stop; Tcl_UniChar ch; int (*chcomp)(int) = NULL; /* The UniChar comparison function. */ int i, failat = 0, result = 1, strict = 0, index, length1, length2; Tcl_Obj *objPtr, *failVarObj = NULL; Tcl_WideInt w; static const char *const isClasses[] = { "alnum", "alpha", "ascii", "control", "boolean", "digit", "double", "entier", "false", "graph", "integer", "list", "lower", "print", "punct", "space", "true", "upper", "wideinteger", "wordchar", "xdigit", NULL }; enum isClasses { STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL, STR_IS_BOOL, STR_IS_DIGIT, STR_IS_DOUBLE, STR_IS_ENTIER, STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT, STR_IS_LIST, STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT, STR_IS_SPACE, STR_IS_TRUE, STR_IS_UPPER, STR_IS_WIDE, STR_IS_WORD, STR_IS_XDIGIT }; static const char *const isOptions[] = { "-strict", "-failindex", NULL }; enum isOptions { OPT_STRICT, OPT_FAILIDX }; if (objc < 3 || objc > 6) { Tcl_WrongNumArgs(interp, 1, objv, "class ?-strict? ?-failindex var? str"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], isClasses, "class", 0, &index) != TCL_OK) { return TCL_ERROR; } if (objc != 3) { for (i = 2; i < objc-1; i++) { int idx2; if (Tcl_GetIndexFromObj(interp, objv[i], isOptions, "option", 0, &idx2) != TCL_OK) { return TCL_ERROR; } switch ((enum isOptions) idx2) { case OPT_STRICT: strict = 1; break; case OPT_FAILIDX: if (i+1 >= objc-1) { Tcl_WrongNumArgs(interp, 2, objv, "?-strict? ?-failindex var? str"); return TCL_ERROR; } failVarObj = objv[++i]; break; } } } /* * We get the objPtr so that we can short-cut for some classes by checking * the object type (int and double), but we need the string otherwise, * because we don't want any conversion of type occuring (as, for example, * Tcl_Get*FromObj would do). */ objPtr = objv[objc-1]; /* * When entering here, result == 1 and failat == 0. */ switch ((enum isClasses) index) { case STR_IS_ALNUM: chcomp = Tcl_UniCharIsAlnum; break; case STR_IS_ALPHA: chcomp = Tcl_UniCharIsAlpha; break; case STR_IS_ASCII: chcomp = UniCharIsAscii; break; case STR_IS_BOOL: case STR_IS_TRUE: case STR_IS_FALSE: if ((objPtr->typePtr != &tclBooleanType) && (TCL_OK != TclSetBooleanFromAny(NULL, objPtr))) { if (strict) { result = 0; } else { string1 = TclGetStringFromObj(objPtr, &length1); result = length1 == 0; } } else if (((index == STR_IS_TRUE) && objPtr->internalRep.longValue == 0) || ((index == STR_IS_FALSE) && objPtr->internalRep.longValue != 0)) { result = 0; } break; case STR_IS_CONTROL: chcomp = Tcl_UniCharIsControl; break; case STR_IS_DIGIT: chcomp = Tcl_UniCharIsDigit; break; case STR_IS_DOUBLE: { /* TODO */ if ((objPtr->typePtr == &tclDoubleType) || (objPtr->typePtr == &tclIntType) || #ifndef TCL_WIDE_INT_IS_LONG (objPtr->typePtr == &tclWideIntType) || #endif (objPtr->typePtr == &tclBignumType)) { break; } string1 = TclGetStringFromObj(objPtr, &length1); if (length1 == 0) { if (strict) { result = 0; } goto str_is_done; } end = string1 + length1; if (TclParseNumber(NULL, objPtr, NULL, NULL, -1, (const char **) &stop, 0) != TCL_OK) { result = 0; failat = 0; } else { failat = stop - string1; if (stop < end) { result = 0; TclFreeIntRep(objPtr); } } break; } case STR_IS_GRAPH: chcomp = Tcl_UniCharIsGraph; break; case STR_IS_INT: if (TCL_OK == TclGetIntFromObj(NULL, objPtr, &i)) { break; } goto failedIntParse; case STR_IS_ENTIER: if ((objPtr->typePtr == &tclIntType) || #ifndef TCL_WIDE_INT_IS_LONG (objPtr->typePtr == &tclWideIntType) || #endif (objPtr->typePtr == &tclBignumType)) { break; } string1 = TclGetStringFromObj(objPtr, &length1); if (length1 == 0) { if (strict) { result = 0; } goto str_is_done; } end = string1 + length1; if (TclParseNumber(NULL, objPtr, NULL, NULL, -1, (const char **) &stop, TCL_PARSE_INTEGER_ONLY) == TCL_OK) { if (stop == end) { /* * Entire string parses as an integer. */ break; } else { /* * Some prefix parsed as an integer, but not the whole string, * so return failure index as the point where parsing stopped. * Clear out the internal rep, since keeping it would leave * *objPtr in an inconsistent state. */ result = 0; failat = stop - string1; TclFreeIntRep(objPtr); } } else { /* * No prefix is a valid integer. Fail at beginning. */ result = 0; failat = 0; } break; case STR_IS_WIDE: if (TCL_OK == Tcl_GetWideIntFromObj(NULL, objPtr, &w)) { break; } failedIntParse: string1 = TclGetStringFromObj(objPtr, &length1); if (length1 == 0) { if (strict) { result = 0; } goto str_is_done; } result = 0; if (failVarObj == NULL) { /* * Don't bother computing the failure point if we're not going to * return it. */ break; } end = string1 + length1; if (TclParseNumber(NULL, objPtr, NULL, NULL, -1, (const char **) &stop, TCL_PARSE_INTEGER_ONLY) == TCL_OK) { if (stop == end) { /* * Entire string parses as an integer, but rejected by * Tcl_Get(Wide)IntFromObj() so we must have overflowed the * target type, and our convention is to return failure at * index -1 in that situation. */ failat = -1; } else { /* * Some prefix parsed as an integer, but not the whole string, * so return failure index as the point where parsing stopped. * Clear out the internal rep, since keeping it would leave * *objPtr in an inconsistent state. */ failat = stop - string1; TclFreeIntRep(objPtr); } } else { /* * No prefix is a valid integer. Fail at beginning. */ failat = 0; } break; case STR_IS_LIST: /* * We ignore the strictness here, since empty strings are always * well-formed lists. */ if (TCL_OK == TclListObjLength(NULL, objPtr, &length2)) { break; } if (failVarObj != NULL) { /* * Need to figure out where the list parsing failed, which is * fairly expensive. This is adapted from the core of * SetListFromAny(). */ const char *elemStart, *nextElem; int lenRemain, elemSize; register const char *p; string1 = TclGetStringFromObj(objPtr, &length1); end = string1 + length1; failat = -1; for (p=string1, lenRemain=length1; lenRemain > 0; p=nextElem, lenRemain=end-nextElem) { if (TCL_ERROR == TclFindElement(NULL, p, lenRemain, &elemStart, &nextElem, &elemSize, NULL)) { Tcl_Obj *tmpStr; /* * This is the simplest way of getting the number of * characters parsed. Note that this is not the same as * the number of bytes when parsing strings with non-ASCII * characters in them. * * Skip leading spaces first. This is only really an issue * if it is the first "element" that has the failure. */ while (TclIsSpaceProc(*p)) { p++; } TclNewStringObj(tmpStr, string1, p-string1); failat = Tcl_GetCharLength(tmpStr); TclDecrRefCount(tmpStr); break; } } } result = 0; break; case STR_IS_LOWER: chcomp = Tcl_UniCharIsLower; break; case STR_IS_PRINT: chcomp = Tcl_UniCharIsPrint; break; case STR_IS_PUNCT: chcomp = Tcl_UniCharIsPunct; break; case STR_IS_SPACE: chcomp = Tcl_UniCharIsSpace; break; case STR_IS_UPPER: chcomp = Tcl_UniCharIsUpper; break; case STR_IS_WORD: chcomp = Tcl_UniCharIsWordChar; break; case STR_IS_XDIGIT: chcomp = UniCharIsHexDigit; break; } if (chcomp != NULL) { string1 = TclGetStringFromObj(objPtr, &length1); if (length1 == 0) { if (strict) { result = 0; } goto str_is_done; } end = string1 + length1; for (; string1 < end; string1 += length2, failat++) { length2 = TclUtfToUniChar(string1, &ch); if (!chcomp(ch)) { result = 0; break; } } } /* * Only set the failVarObj when we will return 0 and we have indicated a * valid fail index (>= 0). */ str_is_done: if ((result == 0) && (failVarObj != NULL) && Tcl_ObjSetVar2(interp, failVarObj, NULL, Tcl_NewIntObj(failat), TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int UniCharIsAscii( int character) { return (character >= 0) && (character < 0x80); } static int UniCharIsHexDigit( int character) { return (character >= 0) && (character < 0x80) && isxdigit(character); } /* *---------------------------------------------------------------------- * * StringMapCmd -- * * This procedure is invoked to process the "string map" Tcl command. See * the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringMapCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int length1, length2, mapElemc, index; int nocase = 0, mapWithDict = 0, copySource = 0; Tcl_Obj **mapElemv, *sourceObj, *resultPtr; Tcl_UniChar *ustring1, *ustring2, *p, *end; int (*strCmpFn)(const Tcl_UniChar*, const Tcl_UniChar*, unsigned long); if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "?-nocase? charMap string"); return TCL_ERROR; } if (objc == 4) { const char *string = TclGetStringFromObj(objv[1], &length2); if ((length2 > 1) && strncmp(string, "-nocase", (size_t) length2) == 0) { nocase = 1; } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\": must be -nocase", string)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", string, NULL); return TCL_ERROR; } } /* * This test is tricky, but has to be that way or you get other strange * inconsistencies (see test string-10.20 for illustration why!) */ if (objv[objc-2]->typePtr == &tclDictType && objv[objc-2]->bytes == NULL){ int i, done; Tcl_DictSearch search; /* * We know the type exactly, so all dict operations will succeed for * sure. This shortens this code quite a bit. */ Tcl_DictObjSize(interp, objv[objc-2], &mapElemc); if (mapElemc == 0) { /* * Empty charMap, just return whatever string was given. */ Tcl_SetObjResult(interp, objv[objc-1]); return TCL_OK; } mapElemc *= 2; mapWithDict = 1; /* * Copy the dictionary out into an array; that's the easiest way to * adapt this code... */ mapElemv = TclStackAlloc(interp, sizeof(Tcl_Obj *) * mapElemc); Tcl_DictObjFirst(interp, objv[objc-2], &search, mapElemv+0, mapElemv+1, &done); for (i=2 ; i30% faster on * larger strings. */ int mapLen; Tcl_UniChar *mapString, u2lc; ustring2 = Tcl_GetUnicodeFromObj(mapElemv[0], &length2); p = ustring1; if ((length2 > length1) || (length2 == 0)) { /* * Match string is either longer than input or empty. */ ustring1 = end; } else { mapString = Tcl_GetUnicodeFromObj(mapElemv[1], &mapLen); u2lc = (nocase ? Tcl_UniCharToLower(*ustring2) : 0); for (; ustring1 < end; ustring1++) { if (((*ustring1 == *ustring2) || (nocase&&Tcl_UniCharToLower(*ustring1)==u2lc)) && (length2==1 || strCmpFn(ustring1, ustring2, (unsigned long) length2) == 0)) { if (p != ustring1) { Tcl_AppendUnicodeToObj(resultPtr, p, ustring1-p); p = ustring1 + length2; } else { p += length2; } ustring1 = p - 1; Tcl_AppendUnicodeToObj(resultPtr, mapString, mapLen); } } } } else { Tcl_UniChar **mapStrings, *u2lc = NULL; int *mapLens; /* * Precompute pointers to the unicode string and length. This saves us * repeated function calls later, significantly speeding up the * algorithm. We only need the lowercase first char in the nocase * case. */ mapStrings = TclStackAlloc(interp, mapElemc*2*sizeof(Tcl_UniChar *)); mapLens = TclStackAlloc(interp, mapElemc * 2 * sizeof(int)); if (nocase) { u2lc = TclStackAlloc(interp, mapElemc * sizeof(Tcl_UniChar)); } for (index = 0; index < mapElemc; index++) { mapStrings[index] = Tcl_GetUnicodeFromObj(mapElemv[index], mapLens+index); if (nocase && ((index % 2) == 0)) { u2lc[index/2] = Tcl_UniCharToLower(*mapStrings[index]); } } for (p = ustring1; ustring1 < end; ustring1++) { for (index = 0; index < mapElemc; index += 2) { /* * Get the key string to match on. */ ustring2 = mapStrings[index]; length2 = mapLens[index]; if ((length2 > 0) && ((*ustring1 == *ustring2) || (nocase && (Tcl_UniCharToLower(*ustring1) == u2lc[index/2]))) && /* Restrict max compare length. */ (end-ustring1 >= length2) && ((length2 == 1) || !strCmpFn(ustring2, ustring1, (unsigned) length2))) { if (p != ustring1) { /* * Put the skipped chars onto the result first. */ Tcl_AppendUnicodeToObj(resultPtr, p, ustring1-p); p = ustring1 + length2; } else { p += length2; } /* * Adjust len to be full length of matched string. */ ustring1 = p - 1; /* * Append the map value to the unicode string. */ Tcl_AppendUnicodeToObj(resultPtr, mapStrings[index+1], mapLens[index+1]); break; } } } if (nocase) { TclStackFree(interp, u2lc); } TclStackFree(interp, mapLens); TclStackFree(interp, mapStrings); } if (p != ustring1) { /* * Put the rest of the unmapped chars onto result. */ Tcl_AppendUnicodeToObj(resultPtr, p, ustring1 - p); } Tcl_SetObjResult(interp, resultPtr); done: if (mapWithDict) { TclStackFree(interp, mapElemv); } if (copySource) { Tcl_DecrRefCount(sourceObj); } return TCL_OK; } /* *---------------------------------------------------------------------- * * StringMatchCmd -- * * This procedure is invoked to process the "string match" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringMatchCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int nocase = 0; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "?-nocase? pattern string"); return TCL_ERROR; } if (objc == 4) { int length; const char *string = TclGetStringFromObj(objv[1], &length); if ((length > 1) && strncmp(string, "-nocase", (size_t) length) == 0) { nocase = TCL_MATCH_NOCASE; } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\": must be -nocase", string)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", string, NULL); return TCL_ERROR; } } Tcl_SetObjResult(interp, Tcl_NewBooleanObj( TclStringMatchObj(objv[objc-1], objv[objc-2], nocase))); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringRangeCmd -- * * This procedure is invoked to process the "string range" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringRangeCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int length, first, last; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "string first last"); return TCL_ERROR; } /* * Get the length in actual characters; Then reduce it by one because * 'end' refers to the last character, not one past it. */ length = Tcl_GetCharLength(objv[1]) - 1; if (TclGetIntForIndexM(interp, objv[2], length, &first) != TCL_OK || TclGetIntForIndexM(interp, objv[3], length, &last) != TCL_OK) { return TCL_ERROR; } if (first < 0) { first = 0; } if (last >= length) { last = length; } if (last >= first) { Tcl_SetObjResult(interp, Tcl_GetRange(objv[1], first, last)); } return TCL_OK; } /* *---------------------------------------------------------------------- * * StringReptCmd -- * * This procedure is invoked to process the "string repeat" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringReptCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1; char *string2; int count, index, length1, length2; Tcl_Obj *resultPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "string count"); return TCL_ERROR; } if (TclGetIntFromObj(interp, objv[2], &count) != TCL_OK) { return TCL_ERROR; } /* * Check for cases that allow us to skip copying stuff. */ if (count == 1) { Tcl_SetObjResult(interp, objv[1]); goto done; } else if (count < 1) { goto done; } string1 = TclGetStringFromObj(objv[1], &length1); if (length1 <= 0) { goto done; } /* * Only build up a string that has data. Instead of building it up with * repeated appends, we just allocate the necessary space once and copy * the string value in. * * We have to worry about overflow [Bugs 714106, 2561746]. * At this point we know 1 <= length1 <= INT_MAX and 2 <= count <= INT_MAX. * We need to keep 2 <= length2 <= INT_MAX. */ if (count > INT_MAX/length1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "result exceeds max size for a Tcl value (%d bytes)", INT_MAX)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); return TCL_ERROR; } length2 = length1 * count; /* * Include space for the NUL. */ string2 = attemptckalloc((unsigned) length2 + 1); if (string2 == NULL) { /* * Alloc failed. Note that in this case we try to do an error message * since this is a case that's most likely when the alloc is large and * that's easy to do with this API. Note that if we fail allocating a * short string, this will likely keel over too (and fatally). */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "string size overflow, out of memory allocating %u bytes", length2 + 1)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); return TCL_ERROR; } for (index = 0; index < count; index++) { memcpy(string2 + (length1 * index), string1, (size_t) length1); } string2[length2] = '\0'; /* * We have to directly assign this instead of using Tcl_SetStringObj (and * indirectly TclInitStringRep) because that makes another copy of the * data. */ TclNewObj(resultPtr); resultPtr->bytes = string2; resultPtr->length = length2; Tcl_SetObjResult(interp, resultPtr); done: return TCL_OK; } /* *---------------------------------------------------------------------- * * StringRplcCmd -- * * This procedure is invoked to process the "string replace" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringRplcCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_UniChar *ustring; int first, last, length; if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 1, objv, "string first last ?string?"); return TCL_ERROR; } ustring = Tcl_GetUnicodeFromObj(objv[1], &length); length--; if (TclGetIntForIndexM(interp, objv[2], length, &first) != TCL_OK || TclGetIntForIndexM(interp, objv[3], length, &last) != TCL_OK){ return TCL_ERROR; } if ((last < first) || (last < 0) || (first > length)) { Tcl_SetObjResult(interp, objv[1]); } else { Tcl_Obj *resultPtr; ustring = Tcl_GetUnicodeFromObj(objv[1], &length); length--; if (first < 0) { first = 0; } resultPtr = Tcl_NewUnicodeObj(ustring, first); if (objc == 5) { Tcl_AppendObjToObj(resultPtr, objv[4]); } if (last < length) { Tcl_AppendUnicodeToObj(resultPtr, ustring + last + 1, length - last); } Tcl_SetObjResult(interp, resultPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * StringRevCmd -- * * This procedure is invoked to process the "string reverse" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringRevCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "string"); return TCL_ERROR; } Tcl_SetObjResult(interp, TclStringObjReverse(objv[1])); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringStartCmd -- * * This procedure is invoked to process the "string wordstart" Tcl * command. See the user documentation for details on what it does. Note * that this command only functions correctly on properly formed Tcl UTF * strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringStartCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_UniChar ch; const char *p, *string; int cur, index, length, numChars; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "string index"); return TCL_ERROR; } string = TclGetStringFromObj(objv[1], &length); numChars = Tcl_NumUtfChars(string, length); if (TclGetIntForIndexM(interp, objv[2], numChars-1, &index) != TCL_OK) { return TCL_ERROR; } string = TclGetStringFromObj(objv[1], &length); if (index >= numChars) { index = numChars - 1; } cur = 0; if (index > 0) { p = Tcl_UtfAtIndex(string, index); for (cur = index; cur >= 0; cur--) { TclUtfToUniChar(p, &ch); if (!Tcl_UniCharIsWordChar(ch)) { break; } p = Tcl_UtfPrev(p, string); } if (cur != index) { cur += 1; } } Tcl_SetObjResult(interp, Tcl_NewIntObj(cur)); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringEndCmd -- * * This procedure is invoked to process the "string wordend" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringEndCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_UniChar ch; const char *p, *end, *string; int cur, index, length, numChars; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "string index"); return TCL_ERROR; } string = TclGetStringFromObj(objv[1], &length); numChars = Tcl_NumUtfChars(string, length); if (TclGetIntForIndexM(interp, objv[2], numChars-1, &index) != TCL_OK) { return TCL_ERROR; } string = TclGetStringFromObj(objv[1], &length); if (index < 0) { index = 0; } if (index < numChars) { p = Tcl_UtfAtIndex(string, index); end = string+length; for (cur = index; p < end; cur++) { p += TclUtfToUniChar(p, &ch); if (!Tcl_UniCharIsWordChar(ch)) { break; } } if (cur == index) { cur++; } } else { cur = numChars; } Tcl_SetObjResult(interp, Tcl_NewIntObj(cur)); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringEqualCmd -- * * This procedure is invoked to process the "string equal" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringEqualCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { /* * Remember to keep code here in some sync with the byte-compiled versions * in tclExecute.c (INST_STR_EQ, INST_STR_NEQ and INST_STR_CMP as well as * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...). */ const char *string1, *string2; int length1, length2, i, match, length, nocase = 0, reqlength = -1; typedef int (*strCmpFn_t)(const char *, const char *, unsigned int); strCmpFn_t strCmpFn; if (objc < 3 || objc > 6) { str_cmp_args: Tcl_WrongNumArgs(interp, 1, objv, "?-nocase? ?-length int? string1 string2"); return TCL_ERROR; } for (i = 1; i < objc-2; i++) { string2 = TclGetStringFromObj(objv[i], &length2); if ((length2 > 1) && !strncmp(string2, "-nocase", (size_t)length2)) { nocase = 1; } else if ((length2 > 1) && !strncmp(string2, "-length", (size_t)length2)) { if (i+1 >= objc-2) { goto str_cmp_args; } i++; if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) { return TCL_ERROR; } } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\": must be -nocase or -length", string2)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", string2, NULL); return TCL_ERROR; } } /* * From now on, we only access the two objects at the end of the argument * array. */ objv += objc-2; if ((reqlength == 0) || (objv[0] == objv[1])) { /* * Always match at 0 chars of if it is the same obj. */ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); return TCL_OK; } if (!nocase && TclIsPureByteArray(objv[0]) && TclIsPureByteArray(objv[1])) { /* * Use binary versions of comparisons since that won't cause undue * type conversions and it is much faster. Only do this if we're * case-sensitive (which is all that really makes sense with byte * arrays anyway, and we have no memcasecmp() for some reason... :^) */ string1 = (char *) Tcl_GetByteArrayFromObj(objv[0], &length1); string2 = (char *) Tcl_GetByteArrayFromObj(objv[1], &length2); strCmpFn = (strCmpFn_t) memcmp; } else if ((objv[0]->typePtr == &tclStringType) && (objv[1]->typePtr == &tclStringType)) { /* * Do a unicode-specific comparison if both of the args are of String * type. In benchmark testing this proved the most efficient check * between the unicode and string comparison operations. */ string1 = (char *) Tcl_GetUnicodeFromObj(objv[0], &length1); string2 = (char *) Tcl_GetUnicodeFromObj(objv[1], &length2); strCmpFn = (strCmpFn_t) (nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp); } else { /* * As a catch-all we will work with UTF-8. We cannot use memcmp() as * that is unsafe with any string containing NUL (\xC0\x80 in Tcl's * utf rep). We can use the more efficient TclpUtfNcmp2 if we are * case-sensitive and no specific length was requested. */ string1 = (char *) TclGetStringFromObj(objv[0], &length1); string2 = (char *) TclGetStringFromObj(objv[1], &length2); if ((reqlength < 0) && !nocase) { strCmpFn = (strCmpFn_t) TclpUtfNcmp2; } else { length1 = Tcl_NumUtfChars(string1, length1); length2 = Tcl_NumUtfChars(string2, length2); strCmpFn = (strCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp); } } if ((reqlength < 0) && (length1 != length2)) { match = 1; /* This will be reversed below. */ } else { length = (length1 < length2) ? length1 : length2; if (reqlength > 0 && reqlength < length) { length = reqlength; } else if (reqlength < 0) { /* * The requested length is negative, so we ignore it by setting it * to length + 1 so we correct the match var. */ reqlength = length + 1; } match = strCmpFn(string1, string2, (unsigned) length); if ((match == 0) && (reqlength > length)) { match = length1 - length2; } } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match ? 0 : 1)); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringCmpCmd -- * * This procedure is invoked to process the "string compare" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringCmpCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { /* * Remember to keep code here in some sync with the byte-compiled versions * in tclExecute.c (INST_STR_EQ, INST_STR_NEQ and INST_STR_CMP as well as * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...). */ const char *string1, *string2; int length1, length2, i, match, length, nocase = 0, reqlength = -1; typedef int (*strCmpFn_t)(const char *, const char *, unsigned int); strCmpFn_t strCmpFn; if (objc < 3 || objc > 6) { str_cmp_args: Tcl_WrongNumArgs(interp, 1, objv, "?-nocase? ?-length int? string1 string2"); return TCL_ERROR; } for (i = 1; i < objc-2; i++) { string2 = TclGetStringFromObj(objv[i], &length2); if ((length2 > 1) && !strncmp(string2, "-nocase", (size_t)length2)) { nocase = 1; } else if ((length2 > 1) && !strncmp(string2, "-length", (size_t)length2)) { if (i+1 >= objc-2) { goto str_cmp_args; } i++; if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) { return TCL_ERROR; } } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\": must be -nocase or -length", string2)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", string2, NULL); return TCL_ERROR; } } /* * From now on, we only access the two objects at the end of the argument * array. */ objv += objc-2; if ((reqlength == 0) || (objv[0] == objv[1])) { /* * Always match at 0 chars of if it is the same obj. */ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); return TCL_OK; } if (!nocase && TclIsPureByteArray(objv[0]) && TclIsPureByteArray(objv[1])) { /* * Use binary versions of comparisons since that won't cause undue * type conversions and it is much faster. Only do this if we're * case-sensitive (which is all that really makes sense with byte * arrays anyway, and we have no memcasecmp() for some reason... :^) */ string1 = (char *) Tcl_GetByteArrayFromObj(objv[0], &length1); string2 = (char *) Tcl_GetByteArrayFromObj(objv[1], &length2); strCmpFn = (strCmpFn_t) memcmp; } else if ((objv[0]->typePtr == &tclStringType) && (objv[1]->typePtr == &tclStringType)) { /* * Do a unicode-specific comparison if both of the args are of String * type. In benchmark testing this proved the most efficient check * between the unicode and string comparison operations. */ string1 = (char *) Tcl_GetUnicodeFromObj(objv[0], &length1); string2 = (char *) Tcl_GetUnicodeFromObj(objv[1], &length2); strCmpFn = (strCmpFn_t) (nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp); } else { /* * As a catch-all we will work with UTF-8. We cannot use memcmp() as * that is unsafe with any string containing NUL (\xC0\x80 in Tcl's * utf rep). We can use the more efficient TclpUtfNcmp2 if we are * case-sensitive and no specific length was requested. */ string1 = (char *) TclGetStringFromObj(objv[0], &length1); string2 = (char *) TclGetStringFromObj(objv[1], &length2); if ((reqlength < 0) && !nocase) { strCmpFn = (strCmpFn_t) TclpUtfNcmp2; } else { length1 = Tcl_NumUtfChars(string1, length1); length2 = Tcl_NumUtfChars(string2, length2); strCmpFn = (strCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp); } } length = (length1 < length2) ? length1 : length2; if (reqlength > 0 && reqlength < length) { length = reqlength; } else if (reqlength < 0) { /* * The requested length is negative, so we ignore it by setting it to * length + 1 so we correct the match var. */ reqlength = length + 1; } match = strCmpFn(string1, string2, (unsigned) length); if ((match == 0) && (reqlength > length)) { match = length1 - length2; } Tcl_SetObjResult(interp, Tcl_NewIntObj((match > 0) ? 1 : (match < 0) ? -1 : 0)); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringCatCmd -- * * This procedure is invoked to process the "string cat" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringCatCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int i; Tcl_Obj *objResultPtr; if (objc < 2) { /* * If there are no args, the result is an empty object. * Just leave the preset empty interp result. */ return TCL_OK; } if (objc == 2) { /* * Other trivial case, single arg, just return it. */ Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } objResultPtr = objv[1]; if (Tcl_IsShared(objResultPtr)) { objResultPtr = Tcl_DuplicateObj(objResultPtr); } for(i = 2;i < objc;i++) { Tcl_AppendObjToObj(objResultPtr, objv[i]); } Tcl_SetObjResult(interp, objResultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringBytesCmd -- * * This procedure is invoked to process the "string bytelength" Tcl * command. See the user documentation for details on what it does. Note * that this command only functions correctly on properly formed Tcl UTF * strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringBytesCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int length; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "string"); return TCL_ERROR; } (void) TclGetStringFromObj(objv[1], &length); Tcl_SetObjResult(interp, Tcl_NewIntObj(length)); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringLenCmd -- * * This procedure is invoked to process the "string length" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringLenCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "string"); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_GetCharLength(objv[1]))); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringLowerCmd -- * * This procedure is invoked to process the "string tolower" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringLowerCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int length1, length2; const char *string1; char *string2; if (objc < 2 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?"); return TCL_ERROR; } string1 = TclGetStringFromObj(objv[1], &length1); if (objc == 2) { Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1); length1 = Tcl_UtfToLower(TclGetString(resultPtr)); Tcl_SetObjLength(resultPtr, length1); Tcl_SetObjResult(interp, resultPtr); } else { int first, last; const char *start, *end; Tcl_Obj *resultPtr; length1 = Tcl_NumUtfChars(string1, length1) - 1; if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) { return TCL_ERROR; } if (first < 0) { first = 0; } last = first; if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1, &last) != TCL_OK)) { return TCL_ERROR; } if (last >= length1) { last = length1; } if (last < first) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } string1 = TclGetStringFromObj(objv[1], &length1); start = Tcl_UtfAtIndex(string1, first); end = Tcl_UtfAtIndex(start, last - first + 1); resultPtr = Tcl_NewStringObj(string1, end - string1); string2 = TclGetString(resultPtr) + (start - string1); length2 = Tcl_UtfToLower(string2); Tcl_SetObjLength(resultPtr, length2 + (start - string1)); Tcl_AppendToObj(resultPtr, end, -1); Tcl_SetObjResult(interp, resultPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * StringUpperCmd -- * * This procedure is invoked to process the "string toupper" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringUpperCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int length1, length2; const char *string1; char *string2; if (objc < 2 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?"); return TCL_ERROR; } string1 = TclGetStringFromObj(objv[1], &length1); if (objc == 2) { Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1); length1 = Tcl_UtfToUpper(TclGetString(resultPtr)); Tcl_SetObjLength(resultPtr, length1); Tcl_SetObjResult(interp, resultPtr); } else { int first, last; const char *start, *end; Tcl_Obj *resultPtr; length1 = Tcl_NumUtfChars(string1, length1) - 1; if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) { return TCL_ERROR; } if (first < 0) { first = 0; } last = first; if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1, &last) != TCL_OK)) { return TCL_ERROR; } if (last >= length1) { last = length1; } if (last < first) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } string1 = TclGetStringFromObj(objv[1], &length1); start = Tcl_UtfAtIndex(string1, first); end = Tcl_UtfAtIndex(start, last - first + 1); resultPtr = Tcl_NewStringObj(string1, end - string1); string2 = TclGetString(resultPtr) + (start - string1); length2 = Tcl_UtfToUpper(string2); Tcl_SetObjLength(resultPtr, length2 + (start - string1)); Tcl_AppendToObj(resultPtr, end, -1); Tcl_SetObjResult(interp, resultPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * StringTitleCmd -- * * This procedure is invoked to process the "string totitle" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringTitleCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int length1, length2; const char *string1; char *string2; if (objc < 2 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "string ?first? ?last?"); return TCL_ERROR; } string1 = TclGetStringFromObj(objv[1], &length1); if (objc == 2) { Tcl_Obj *resultPtr = Tcl_NewStringObj(string1, length1); length1 = Tcl_UtfToTitle(TclGetString(resultPtr)); Tcl_SetObjLength(resultPtr, length1); Tcl_SetObjResult(interp, resultPtr); } else { int first, last; const char *start, *end; Tcl_Obj *resultPtr; length1 = Tcl_NumUtfChars(string1, length1) - 1; if (TclGetIntForIndexM(interp,objv[2],length1, &first) != TCL_OK) { return TCL_ERROR; } if (first < 0) { first = 0; } last = first; if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1, &last) != TCL_OK)) { return TCL_ERROR; } if (last >= length1) { last = length1; } if (last < first) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } string1 = TclGetStringFromObj(objv[1], &length1); start = Tcl_UtfAtIndex(string1, first); end = Tcl_UtfAtIndex(start, last - first + 1); resultPtr = Tcl_NewStringObj(string1, end - string1); string2 = TclGetString(resultPtr) + (start - string1); length2 = Tcl_UtfToTitle(string2); Tcl_SetObjLength(resultPtr, length2 + (start - string1)); Tcl_AppendToObj(resultPtr, end, -1); Tcl_SetObjResult(interp, resultPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * StringTrimCmd -- * * This procedure is invoked to process the "string trim" Tcl command. * See the user documentation for details on what it does. Note that this * command only functions correctly on properly formed Tcl UTF strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringTrimCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1, *string2; int triml, trimr, length1, length2; if (objc == 3) { string2 = TclGetStringFromObj(objv[2], &length2); } else if (objc == 2) { string2 = tclDefaultTrimSet; length2 = strlen(tclDefaultTrimSet); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?"); return TCL_ERROR; } string1 = TclGetStringFromObj(objv[1], &length1); triml = TclTrimLeft(string1, length1, string2, length2); trimr = TclTrimRight(string1 + triml, length1 - triml, string2, length2); Tcl_SetObjResult(interp, Tcl_NewStringObj(string1 + triml, length1 - triml - trimr)); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringTrimLCmd -- * * This procedure is invoked to process the "string trimleft" Tcl * command. See the user documentation for details on what it does. Note * that this command only functions correctly on properly formed Tcl UTF * strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringTrimLCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1, *string2; int trim, length1, length2; if (objc == 3) { string2 = TclGetStringFromObj(objv[2], &length2); } else if (objc == 2) { string2 = tclDefaultTrimSet; length2 = strlen(tclDefaultTrimSet); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?"); return TCL_ERROR; } string1 = TclGetStringFromObj(objv[1], &length1); trim = TclTrimLeft(string1, length1, string2, length2); Tcl_SetObjResult(interp, Tcl_NewStringObj(string1+trim, length1-trim)); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringTrimRCmd -- * * This procedure is invoked to process the "string trimright" Tcl * command. See the user documentation for details on what it does. Note * that this command only functions correctly on properly formed Tcl UTF * strings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int StringTrimRCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *string1, *string2; int trim, length1, length2; if (objc == 3) { string2 = TclGetStringFromObj(objv[2], &length2); } else if (objc == 2) { string2 = tclDefaultTrimSet; length2 = strlen(tclDefaultTrimSet); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?chars?"); return TCL_ERROR; } string1 = TclGetStringFromObj(objv[1], &length1); trim = TclTrimRight(string1, length1, string2, length2); Tcl_SetObjResult(interp, Tcl_NewStringObj(string1, length1-trim)); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclInitStringCmd -- * * This procedure creates the "string" Tcl command. See the user * documentation for details on what it does. Note that this command only * functions correctly on properly formed Tcl UTF strings. * * Also note that the primary methods here (equal, compare, match, ...) * have bytecode equivalents. You will find the code for those in * tclExecute.c. The code here will only be used in the non-bc case (like * in an 'eval'). * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ Tcl_Command TclInitStringCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap stringImplMap[] = { {"bytelength", StringBytesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"cat", StringCatCmd, TclCompileStringCatCmd, NULL, NULL, 0}, {"compare", StringCmpCmd, TclCompileStringCmpCmd, NULL, NULL, 0}, {"equal", StringEqualCmd, TclCompileStringEqualCmd, NULL, NULL, 0}, {"first", StringFirstCmd, TclCompileStringFirstCmd, NULL, NULL, 0}, {"index", StringIndexCmd, TclCompileStringIndexCmd, NULL, NULL, 0}, {"is", StringIsCmd, TclCompileStringIsCmd, NULL, NULL, 0}, {"last", StringLastCmd, TclCompileStringLastCmd, NULL, NULL, 0}, {"length", StringLenCmd, TclCompileStringLenCmd, NULL, NULL, 0}, {"map", StringMapCmd, TclCompileStringMapCmd, NULL, NULL, 0}, {"match", StringMatchCmd, TclCompileStringMatchCmd, NULL, NULL, 0}, {"range", StringRangeCmd, TclCompileStringRangeCmd, NULL, NULL, 0}, {"repeat", StringReptCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"replace", StringRplcCmd, TclCompileStringReplaceCmd, NULL, NULL, 0}, {"reverse", StringRevCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"tolower", StringLowerCmd, TclCompileStringToLowerCmd, NULL, NULL, 0}, {"toupper", StringUpperCmd, TclCompileStringToUpperCmd, NULL, NULL, 0}, {"totitle", StringTitleCmd, TclCompileStringToTitleCmd, NULL, NULL, 0}, {"trim", StringTrimCmd, TclCompileStringTrimCmd, NULL, NULL, 0}, {"trimleft", StringTrimLCmd, TclCompileStringTrimLCmd, NULL, NULL, 0}, {"trimright", StringTrimRCmd, TclCompileStringTrimRCmd, NULL, NULL, 0}, {"wordend", StringEndCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"wordstart", StringStartCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; return TclMakeEnsemble(interp, "string", stringImplMap); } /* *---------------------------------------------------------------------- * * Tcl_SubstObjCmd -- * * This procedure is invoked to process the "subst" Tcl command. See the * user documentation for details on what it does. This command relies on * Tcl_SubstObj() for its implementation. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int TclSubstOptions( Tcl_Interp *interp, int numOpts, Tcl_Obj *const opts[], int *flagPtr) { static const char *const substOptions[] = { "-nobackslashes", "-nocommands", "-novariables", NULL }; enum { SUBST_NOBACKSLASHES, SUBST_NOCOMMANDS, SUBST_NOVARS }; int i, flags = TCL_SUBST_ALL; for (i = 0; i < numOpts; i++) { int optionIndex; if (Tcl_GetIndexFromObj(interp, opts[i], substOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch (optionIndex) { case SUBST_NOBACKSLASHES: flags &= ~TCL_SUBST_BACKSLASHES; break; case SUBST_NOCOMMANDS: flags &= ~TCL_SUBST_COMMANDS; break; case SUBST_NOVARS: flags &= ~TCL_SUBST_VARIABLES; break; default: Tcl_Panic("Tcl_SubstObjCmd: bad option index to SubstOptions"); } } *flagPtr = flags; return TCL_OK; } int Tcl_SubstObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRSubstObjCmd, dummy, objc, objv); } int TclNRSubstObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int flags; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "?-nobackslashes? ?-nocommands? ?-novariables? string"); return TCL_ERROR; } if (TclSubstOptions(interp, objc-2, objv+1, &flags) != TCL_OK) { return TCL_ERROR; } return Tcl_NRSubstObj(interp, objv[objc-1], flags); } /* *---------------------------------------------------------------------- * * Tcl_SwitchObjCmd -- * * This object-based procedure is invoked to process the "switch" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_SwitchObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRSwitchObjCmd, dummy, objc, objv); } int TclNRSwitchObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int i,j, index, mode, foundmode, splitObjs, numMatchesSaved; int noCase, patternLength; const char *pattern; Tcl_Obj *stringObj, *indexVarObj, *matchVarObj; Tcl_Obj *const *savedObjv = objv; Tcl_RegExp regExpr = NULL; Interp *iPtr = (Interp *) interp; int pc = 0; int bidx = 0; /* Index of body argument. */ Tcl_Obj *blist = NULL; /* List obj which is the body */ CmdFrame *ctxPtr; /* Copy of the topmost cmdframe, to allow us * to mess with the line information */ /* * If you add options that make -e and -g not unique prefixes of -exact or * -glob, you *must* fix TclCompileSwitchCmd's option parser as well. */ static const char *const options[] = { "-exact", "-glob", "-indexvar", "-matchvar", "-nocase", "-regexp", "--", NULL }; enum options { OPT_EXACT, OPT_GLOB, OPT_INDEXV, OPT_MATCHV, OPT_NOCASE, OPT_REGEXP, OPT_LAST }; typedef int (*strCmpFn_t)(const char *, const char *); strCmpFn_t strCmpFn = strcmp; mode = OPT_EXACT; foundmode = 0; indexVarObj = NULL; matchVarObj = NULL; numMatchesSaved = 0; noCase = 0; for (i = 1; i < objc-2; i++) { if (TclGetString(objv[i])[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { /* * General options. */ case OPT_LAST: i++; goto finishedOptions; case OPT_NOCASE: strCmpFn = TclUtfCasecmp; noCase = 1; break; /* * Handle the different switch mode options. */ default: if (foundmode) { /* * Mode already set via -exact, -glob, or -regexp. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\": %s option already found", TclGetString(objv[i]), options[mode])); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", "DOUBLEOPT", NULL); return TCL_ERROR; } foundmode = 1; mode = index; break; /* * Check for TIP#75 options specifying the variables to write * regexp information into. */ case OPT_INDEXV: i++; if (i >= objc-2) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "missing variable name argument to %s option", "-indexvar")); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", "NOVAR", NULL); return TCL_ERROR; } indexVarObj = objv[i]; numMatchesSaved = -1; break; case OPT_MATCHV: i++; if (i >= objc-2) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "missing variable name argument to %s option", "-matchvar")); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", "NOVAR", NULL); return TCL_ERROR; } matchVarObj = objv[i]; numMatchesSaved = -1; break; } } finishedOptions: if (objc - i < 2) { Tcl_WrongNumArgs(interp, 1, objv, "?-option ...? string ?pattern body ...? ?default body?"); return TCL_ERROR; } if (indexVarObj != NULL && mode != OPT_REGEXP) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s option requires -regexp option", "-indexvar")); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", "MODERESTRICTION", NULL); return TCL_ERROR; } if (matchVarObj != NULL && mode != OPT_REGEXP) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s option requires -regexp option", "-matchvar")); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", "MODERESTRICTION", NULL); return TCL_ERROR; } stringObj = objv[i]; objc -= i + 1; objv += i + 1; bidx = i + 1; /* First after the match string. */ /* * If all of the pattern/command pairs are lumped into a single argument, * split them out again. * * TIP #280: Determine the lines the words in the list start at, based on * the same data for the list word itself. The cmdFramePtr line * information is manipulated directly. */ splitObjs = 0; if (objc == 1) { Tcl_Obj **listv; blist = objv[0]; if (TclListObjGetElements(interp, objv[0], &objc, &listv) != TCL_OK){ return TCL_ERROR; } /* * Ensure that the list is non-empty. */ if (objc < 1) { Tcl_WrongNumArgs(interp, 1, savedObjv, "?-option ...? string {?pattern body ...? ?default body?}"); return TCL_ERROR; } objv = listv; splitObjs = 1; } /* * Complain if there is an odd number of words in the list of patterns and * bodies. */ if (objc % 2) { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewStringObj( "extra switch pattern with no body", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "SWITCH", "BADARM", NULL); /* * Check if this can be due to a badly placed comment in the switch * block. * * The following is an heuristic to detect the infamous "comment in * switch" error: just check if a pattern begins with '#'. */ if (splitObjs) { for (i=0 ; i 0) { rangeObjAry[0] = Tcl_NewLongObj(info.matches[j].start); rangeObjAry[1] = Tcl_NewLongObj(info.matches[j].end-1); } else { rangeObjAry[0] = rangeObjAry[1] = Tcl_NewIntObj(-1); } /* * Never fails; the object is always clean at this point. */ Tcl_ListObjAppendElement(NULL, indicesObj, Tcl_NewListObj(2, rangeObjAry)); } if (matchVarObj != NULL) { Tcl_Obj *substringObj; substringObj = Tcl_GetRange(stringObj, info.matches[j].start, info.matches[j].end-1); /* * Never fails; the object is always clean at this point. */ Tcl_ListObjAppendElement(NULL, matchesObj, substringObj); } } if (indexVarObj != NULL) { if (Tcl_ObjSetVar2(interp, indexVarObj, NULL, indicesObj, TCL_LEAVE_ERR_MSG) == NULL) { /* * Careful! Check to see if we have allocated the list of * matched strings; if so (but there was an error assigning * the indices list) we have a potential memory leak because * the match list has not been written to a variable. Except * that we'll clean that up right now. */ if (matchesObj != NULL) { Tcl_DecrRefCount(matchesObj); } return TCL_ERROR; } } if (matchVarObj != NULL) { if (Tcl_ObjSetVar2(interp, matchVarObj, NULL, matchesObj, TCL_LEAVE_ERR_MSG) == NULL) { /* * Unlike above, if indicesObj is non-NULL at this point, it * will have been written to a variable already and will hence * not be leaked. */ return TCL_ERROR; } } } /* * We've got a match. Find a body to execute, skipping bodies that are * "-". */ matchFound: ctxPtr = TclStackAlloc(interp, sizeof(CmdFrame)); *ctxPtr = *iPtr->cmdFramePtr; if (splitObjs) { /* * We have to perform the GetSrc and other type dependent handling of * the frame here because we are munging with the line numbers, * something the other commands like if, etc. are not doing. Them are * fine with simply passing the CmdFrame through and having the * special handling done in 'info frame', or the bc compiler */ if (ctxPtr->type == TCL_LOCATION_BC) { /* * Type BC => ctxPtr->data.eval.path is not used. * ctxPtr->data.tebc.codePtr is used instead. */ TclGetSrcInfoForPc(ctxPtr); pc = 1; /* * The line information in the cmdFrame is now a copy we do not * own. */ } if (ctxPtr->type == TCL_LOCATION_SOURCE && ctxPtr->line[bidx] >= 0) { int bline = ctxPtr->line[bidx]; ctxPtr->line = ckalloc(objc * sizeof(int)); ctxPtr->nline = objc; TclListLines(blist, bline, objc, ctxPtr->line, objv); } else { /* * This is either a dynamic code word, when all elements are * relative to themselves, or something else less expected and * where we have no information. The result is the same in both * cases; tell the code to come that it doesn't know where it is, * which triggers reversion to the old behavior. */ int k; ctxPtr->line = ckalloc(objc * sizeof(int)); ctxPtr->nline = objc; for (k=0; k < objc; k++) { ctxPtr->line[k] = -1; } } } for (j = i + 1; ; j += 2) { if (j >= objc) { /* * This shouldn't happen since we've checked that the last body is * not a continuation... */ Tcl_Panic("fall-out when searching for body to match pattern"); } if (strcmp(TclGetString(objv[j]), "-") != 0) { break; } } /* * TIP #280: Make invoking context available to switch branch. */ Tcl_NRAddCallback(interp, SwitchPostProc, INT2PTR(splitObjs), ctxPtr, INT2PTR(pc), (ClientData) pattern); return TclNREvalObjEx(interp, objv[j], 0, ctxPtr, splitObjs ? j : bidx+j); } static int SwitchPostProc( ClientData data[], /* Data passed from Tcl_NRAddCallback above */ Tcl_Interp *interp, /* Tcl interpreter */ int result) /* Result to return*/ { /* Unpack the preserved data */ int splitObjs = PTR2INT(data[0]); CmdFrame *ctxPtr = data[1]; int pc = PTR2INT(data[2]); const char *pattern = data[3]; int patternLength = strlen(pattern); /* * Clean up TIP 280 context information */ if (splitObjs) { ckfree(ctxPtr->line); if (pc && (ctxPtr->type == TCL_LOCATION_SOURCE)) { /* * Death of SrcInfo reference. */ Tcl_DecrRefCount(ctxPtr->data.eval.path); } } /* * Generate an error message if necessary. */ if (result == TCL_ERROR) { int limit = 50; int overflow = (patternLength > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%.*s%s\" arm line %d)", (overflow ? limit : patternLength), pattern, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } TclStackFree(interp, ctxPtr); return result; } /* *---------------------------------------------------------------------- * * Tcl_ThrowObjCmd -- * * This procedure is invoked to process the "throw" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ThrowObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *options; int len; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "type message"); return TCL_ERROR; } /* * The type must be a list of at least length 1. */ if (Tcl_ListObjLength(interp, objv[1], &len) != TCL_OK) { return TCL_ERROR; } else if (len < 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "type must be non-empty list", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "THROW", "BADEXCEPTION", NULL); return TCL_ERROR; } /* * Now prepare the result options dictionary. We use the list API as it is * slightly more convenient. */ TclNewLiteralStringObj(options, "-code error -level 0 -errorcode"); Tcl_ListObjAppendElement(NULL, options, objv[1]); /* * We're ready to go. Fire things into the low-level result machinery. */ Tcl_SetObjResult(interp, objv[2]); return Tcl_SetReturnOptions(interp, options); } /* *---------------------------------------------------------------------- * * Tcl_TimeObjCmd -- * * This object-based procedure is invoked to process the "time" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_TimeObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register Tcl_Obj *objPtr; Tcl_Obj *objs[4]; register int i, result; int count; double totalMicroSec; #ifndef TCL_WIDE_CLICKS Tcl_Time start, stop; #else Tcl_WideInt start, stop; #endif if (objc == 2) { count = 1; } else if (objc == 3) { result = TclGetIntFromObj(interp, objv[2], &count); if (result != TCL_OK) { return result; } } else { Tcl_WrongNumArgs(interp, 1, objv, "command ?count?"); return TCL_ERROR; } objPtr = objv[1]; i = count; #ifndef TCL_WIDE_CLICKS Tcl_GetTime(&start); #else start = TclpGetWideClicks(); #endif while (i-- > 0) { result = Tcl_EvalObjEx(interp, objPtr, 0); if (result != TCL_OK) { return result; } } #ifndef TCL_WIDE_CLICKS Tcl_GetTime(&stop); totalMicroSec = ((double) (stop.sec - start.sec)) * 1.0e6 + (stop.usec - start.usec); #else stop = TclpGetWideClicks(); totalMicroSec = ((double) TclpWideClicksToNanoseconds(stop - start))/1.0e3; #endif if (count <= 1) { /* * Use int obj since we know time is not fractional. [Bug 1202178] */ objs[0] = Tcl_NewIntObj((count <= 0) ? 0 : (int) totalMicroSec); } else { objs[0] = Tcl_NewDoubleObj(totalMicroSec/count); } /* * Construct the result as a list because many programs have always parsed * as such (extracting the first element, typically). */ TclNewLiteralStringObj(objs[1], "microseconds"); TclNewLiteralStringObj(objs[2], "per"); TclNewLiteralStringObj(objs[3], "iteration"); Tcl_SetObjResult(interp, Tcl_NewListObj(4, objs)); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_TryObjCmd, TclNRTryObjCmd -- * * This procedure is invoked to process the "try" Tcl command. See the * user documentation (or TIP #329) for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_TryObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRTryObjCmd, dummy, objc, objv); } int TclNRTryObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *bodyObj, *handlersObj, *finallyObj = NULL; int i, bodyShared, haveHandlers, dummy, code; static const char *const handlerNames[] = { "finally", "on", "trap", NULL }; enum Handlers { TryFinally, TryOn, TryTrap }; /* * Parse the arguments. The handlers are passed to subsequent callbacks as * a Tcl_Obj list of the 5-tuples like (type, returnCode, errorCodePrefix, * bindVariables, script), and the finally script is just passed as it is. */ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "body ?handler ...? ?finally script?"); return TCL_ERROR; } bodyObj = objv[1]; handlersObj = Tcl_NewObj(); bodyShared = 0; haveHandlers = 0; for (i=2 ; i objc-4) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "wrong # args to on clause: must be \"... on code" " variableList script\"", -1)); Tcl_DecrRefCount(handlersObj); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "ON", "ARGUMENT", NULL); return TCL_ERROR; } if (TclGetCompletionCodeFromObj(interp, objv[i+1], &code) != TCL_OK) { Tcl_DecrRefCount(handlersObj); return TCL_ERROR; } info[2] = NULL; goto commonHandler; case TryTrap: /* trap pattern variableList script */ if (i > objc-4) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "wrong # args to trap clause: " "must be \"... trap pattern variableList script\"", -1)); Tcl_DecrRefCount(handlersObj); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "TRAP", "ARGUMENT", NULL); return TCL_ERROR; } code = 1; if (Tcl_ListObjLength(NULL, objv[i+1], &dummy) != TCL_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad prefix '%s': must be a list", Tcl_GetString(objv[i+1]))); Tcl_DecrRefCount(handlersObj); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "TRAP", "EXNFORMAT", NULL); return TCL_ERROR; } info[2] = objv[i+1]; commonHandler: if (Tcl_ListObjLength(interp, objv[i+2], &dummy) != TCL_OK) { Tcl_DecrRefCount(handlersObj); return TCL_ERROR; } info[0] = objv[i]; /* type */ TclNewIntObj(info[1], code); /* returnCode */ if (info[2] == NULL) { /* errorCodePrefix */ TclNewObj(info[2]); } info[3] = objv[i+2]; /* bindVariables */ info[4] = objv[i+3]; /* script */ bodyShared = !strcmp(TclGetString(objv[i+3]), "-"); Tcl_ListObjAppendElement(NULL, handlersObj, Tcl_NewListObj(5, info)); haveHandlers = 1; i += 3; break; } } if (bodyShared) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "last non-finally clause must not have a body of \"-\"", -1)); Tcl_DecrRefCount(handlersObj); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRY", "BADFALLTHROUGH", NULL); return TCL_ERROR; } if (!haveHandlers) { Tcl_DecrRefCount(handlersObj); handlersObj = NULL; } /* * Execute the body. */ Tcl_NRAddCallback(interp, TryPostBody, handlersObj, finallyObj, (ClientData)objv, INT2PTR(objc)); return TclNREvalObjEx(interp, bodyObj, 0, ((Interp *) interp)->cmdFramePtr, 1); } /* *---------------------------------------------------------------------- * * During -- * * This helper function patches together the updates to the interpreter's * return options that are needed when things fail during the processing * of a handler or finally script for the [try] command. * * Returns: * The new option dictionary. * *---------------------------------------------------------------------- */ static inline Tcl_Obj * During( Tcl_Interp *interp, int resultCode, /* The result code from the just-evaluated * script. */ Tcl_Obj *oldOptions, /* The old option dictionary. */ Tcl_Obj *errorInfo) /* An object to append to the errorinfo and * release, or NULL if nothing is to be added. * Designed to be used with Tcl_ObjPrintf. */ { Tcl_Obj *during, *options; if (errorInfo != NULL) { Tcl_AppendObjToErrorInfo(interp, errorInfo); } options = Tcl_GetReturnOptions(interp, resultCode); TclNewLiteralStringObj(during, "-during"); Tcl_IncrRefCount(during); Tcl_DictObjPut(interp, options, during, oldOptions); Tcl_DecrRefCount(during); Tcl_IncrRefCount(options); Tcl_DecrRefCount(oldOptions); return options; } /* *---------------------------------------------------------------------- * * TryPostBody -- * * Callback to handle the outcome of the execution of the body of a 'try' * command. * *---------------------------------------------------------------------- */ static int TryPostBody( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj *resultObj, *options, *handlersObj, *finallyObj, *cmdObj, **objv; int i, dummy, code, objc; int numHandlers = 0; handlersObj = data[0]; finallyObj = data[1]; objv = data[2]; objc = PTR2INT(data[3]); cmdObj = objv[0]; /* * Check for limits/rewinding, which override normal trapping behaviour. */ if (((Interp*) interp)->execEnvPtr->rewind || Tcl_LimitExceeded(interp)) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%s\" body line %d)", TclGetString(cmdObj), Tcl_GetErrorLine(interp))); if (handlersObj != NULL) { Tcl_DecrRefCount(handlersObj); } return TCL_ERROR; } /* * Basic processing of the outcome of the script, including adding of * errorinfo trace. */ if (result == TCL_ERROR) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%s\" body line %d)", TclGetString(cmdObj), Tcl_GetErrorLine(interp))); } resultObj = Tcl_GetObjResult(interp); Tcl_IncrRefCount(resultObj); options = Tcl_GetReturnOptions(interp, result); Tcl_IncrRefCount(options); Tcl_ResetResult(interp); /* * Handle the results. */ if (handlersObj != NULL) { int found = 0; Tcl_Obj **handlers, **info; Tcl_ListObjGetElements(NULL, handlersObj, &numHandlers, &handlers); for (i=0 ; i 0) { Tcl_Obj *varName; Tcl_ListObjIndex(NULL, info[3], 0, &varName); if (Tcl_ObjSetVar2(interp, varName, NULL, resultObj, TCL_LEAVE_ERR_MSG) == NULL) { Tcl_DecrRefCount(resultObj); goto handlerFailed; } Tcl_DecrRefCount(resultObj); if (dummy > 1) { Tcl_ListObjIndex(NULL, info[3], 1, &varName); if (Tcl_ObjSetVar2(interp, varName, NULL, options, TCL_LEAVE_ERR_MSG) == NULL) { goto handlerFailed; } } } else { /* * Dispose of the result to prevent a memleak. [Bug 2910044] */ Tcl_DecrRefCount(resultObj); } /* * Evaluate the handler body and process the outcome. Note that we * need to keep the kind of handler for debugging purposes, and in * any case anything we want from info[] must be extracted right * now because the info[] array is about to become invalid. There * is very little refcount handling here however, since we know * that the objects that we still want to refer to now were input * arguments to [try] and so are still on the Tcl value stack. */ handlerBodyObj = info[4]; Tcl_NRAddCallback(interp, TryPostHandler, objv, options, info[0], INT2PTR((finallyObj == NULL) ? 0 : objc - 1)); Tcl_DecrRefCount(handlersObj); return TclNREvalObjEx(interp, handlerBodyObj, 0, ((Interp *) interp)->cmdFramePtr, 4*i + 5); handlerFailed: resultObj = Tcl_GetObjResult(interp); Tcl_IncrRefCount(resultObj); options = During(interp, result, options, NULL); break; didNotMatch: continue; } /* * No handler matched; get rid of the list of handlers. */ Tcl_DecrRefCount(handlersObj); } /* * Process the finally clause. */ if (finallyObj != NULL) { Tcl_NRAddCallback(interp, TryPostFinal, resultObj, options, cmdObj, NULL); return TclNREvalObjEx(interp, finallyObj, 0, ((Interp *) interp)->cmdFramePtr, objc - 1); } /* * Install the correct result/options into the interpreter and clean up * any temporary storage. */ result = Tcl_SetReturnOptions(interp, options); Tcl_DecrRefCount(options); Tcl_SetObjResult(interp, resultObj); Tcl_DecrRefCount(resultObj); return result; } /* *---------------------------------------------------------------------- * * TryPostHandler -- * * Callback to handle the outcome of the execution of a handler of a * 'try' command. * *---------------------------------------------------------------------- */ static int TryPostHandler( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj *resultObj, *cmdObj, *options, *handlerKindObj, **objv; Tcl_Obj *finallyObj; int finally; objv = data[0]; options = data[1]; handlerKindObj = data[2]; finally = PTR2INT(data[3]); cmdObj = objv[0]; finallyObj = finally ? objv[finally] : 0; /* * Check for limits/rewinding, which override normal trapping behaviour. */ if (((Interp*) interp)->execEnvPtr->rewind || Tcl_LimitExceeded(interp)) { options = During(interp, result, options, Tcl_ObjPrintf( "\n (\"%s ... %s\" handler line %d)", TclGetString(cmdObj), TclGetString(handlerKindObj), Tcl_GetErrorLine(interp))); Tcl_DecrRefCount(options); return TCL_ERROR; } /* * The handler result completely substitutes for the result of the body. */ resultObj = Tcl_GetObjResult(interp); Tcl_IncrRefCount(resultObj); if (result == TCL_ERROR) { options = During(interp, result, options, Tcl_ObjPrintf( "\n (\"%s ... %s\" handler line %d)", TclGetString(cmdObj), TclGetString(handlerKindObj), Tcl_GetErrorLine(interp))); } else { Tcl_DecrRefCount(options); options = Tcl_GetReturnOptions(interp, result); Tcl_IncrRefCount(options); } /* * Process the finally clause if it is present. */ if (finallyObj != NULL) { Interp *iPtr = (Interp *) interp; Tcl_NRAddCallback(interp, TryPostFinal, resultObj, options, cmdObj, NULL); /* The 'finally' script is always the last argument word. */ return TclNREvalObjEx(interp, finallyObj, 0, iPtr->cmdFramePtr, finally); } /* * Install the correct result/options into the interpreter and clean up * any temporary storage. */ result = Tcl_SetReturnOptions(interp, options); Tcl_DecrRefCount(options); Tcl_SetObjResult(interp, resultObj); Tcl_DecrRefCount(resultObj); return result; } /* *---------------------------------------------------------------------- * * TryPostFinal -- * * Callback to handle the outcome of the execution of the finally script * of a 'try' command. * *---------------------------------------------------------------------- */ static int TryPostFinal( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj *resultObj, *options, *cmdObj; resultObj = data[0]; options = data[1]; cmdObj = data[2]; /* * If the result wasn't OK, we need to adjust the result options. */ if (result != TCL_OK) { Tcl_DecrRefCount(resultObj); resultObj = NULL; if (result == TCL_ERROR) { options = During(interp, result, options, Tcl_ObjPrintf( "\n (\"%s ... finally\" body line %d)", TclGetString(cmdObj), Tcl_GetErrorLine(interp))); } else { Tcl_Obj *origOptions = options; options = Tcl_GetReturnOptions(interp, result); Tcl_IncrRefCount(options); Tcl_DecrRefCount(origOptions); } } /* * Install the correct result/options into the interpreter and clean up * any temporary storage. */ result = Tcl_SetReturnOptions(interp, options); Tcl_DecrRefCount(options); if (resultObj != NULL) { Tcl_SetObjResult(interp, resultObj); Tcl_DecrRefCount(resultObj); } return result; } /* *---------------------------------------------------------------------- * * Tcl_WhileObjCmd -- * * This procedure is invoked to process the "while" Tcl command. See the * user documentation for details on what it does. * * With the bytecode compiler, this procedure is only called when a * command name is computed at runtime, and is "while" or the name to * which "while" was renamed: e.g., "set z while; $z {$i<100} {}" * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_WhileObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRWhileObjCmd, dummy, objc, objv); } int TclNRWhileObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { ForIterData *iterPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "test command"); return TCL_ERROR; } /* * We reuse [for]'s callback, passing a NULL for the 'next' script. */ TclSmallAllocEx(interp, sizeof(ForIterData), iterPtr); iterPtr->cond = objv[1]; iterPtr->body = objv[2]; iterPtr->next = NULL; iterPtr->msg = "\n (\"while\" body line %d)"; iterPtr->word = 2; TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclListLines -- * * ??? * * Results: * Filled in array of line numbers? * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclListLines( Tcl_Obj *listObj, /* Pointer to obj holding a string with list * structure. Assumed to be valid. Assumed to * contain n elements. */ int line, /* Line the list as a whole starts on. */ int n, /* #elements in lines */ int *lines, /* Array of line numbers, to fill. */ Tcl_Obj *const *elems) /* The list elems as Tcl_Obj*, in need of * derived continuation data */ { const char *listStr = Tcl_GetString(listObj); const char *listHead = listStr; int i, length = strlen(listStr); const char *element = NULL, *next = NULL; ContLineLoc *clLocPtr = TclContinuationsGet(listObj); int *clNext = (clLocPtr ? &clLocPtr->loc[0] : NULL); for (i = 0; i < n; i++) { TclFindElement(NULL, listStr, length, &element, &next, NULL, NULL); TclAdvanceLines(&line, listStr, element); /* Leading whitespace */ TclAdvanceContinuations(&line, &clNext, element - listHead); if (elems && clNext) { TclContinuationsEnterDerived(elems[i], element-listHead, clNext); } lines[i] = line; length -= (next - listStr); TclAdvanceLines(&line, element, next); /* Element */ listStr = next; if (*element == 0) { /* ASSERT i == n */ break; } } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclPkg.c0000644000175000017500000015036612663660065014606 0ustar sergeisergei/* * tclPkg.c -- * * This file implements package and version control for Tcl via the * "package" command and a few C APIs. * * Copyright (c) 1996 Sun Microsystems, Inc. * Copyright (c) 2006 Andreas Kupries * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * TIP #268. * Heavily rewritten to handle the extend version numbers, and extended * package requirements. */ #include "tclInt.h" /* * Each invocation of the "package ifneeded" command creates a structure of * the following type, which is used to load the package into the interpreter * if it is requested with a "package require" command. */ typedef struct PkgAvail { char *version; /* Version string; malloc'ed. */ char *script; /* Script to invoke to provide this version of * the package. Malloc'ed and protected by * Tcl_Preserve and Tcl_Release. */ struct PkgAvail *nextPtr; /* Next in list of available versions of the * same package. */ } PkgAvail; /* * For each package that is known in any way to an interpreter, there is one * record of the following type. These records are stored in the * "packageTable" hash table in the interpreter, keyed by package name such as * "Tk" (no version number). */ typedef struct Package { char *version; /* Version that has been supplied in this * interpreter via "package provide" * (malloc'ed). NULL means the package doesn't * exist in this interpreter yet. */ PkgAvail *availPtr; /* First in list of all available versions of * this package. */ const void *clientData; /* Client data. */ } Package; /* * Prototypes for functions defined in this file: */ static int CheckVersionAndConvert(Tcl_Interp *interp, const char *string, char **internal, int *stable); static int CompareVersions(char *v1i, char *v2i, int *isMajorPtr); static int CheckRequirement(Tcl_Interp *interp, const char *string); static int CheckAllRequirements(Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]); static int RequirementSatisfied(char *havei, const char *req); static int SomeRequirementSatisfied(char *havei, int reqc, Tcl_Obj *const reqv[]); static void AddRequirementsToResult(Tcl_Interp *interp, int reqc, Tcl_Obj *const reqv[]); static void AddRequirementsToDString(Tcl_DString *dstring, int reqc, Tcl_Obj *const reqv[]); static Package * FindPackage(Tcl_Interp *interp, const char *name); static const char * PkgRequireCore(Tcl_Interp *interp, const char *name, int reqc, Tcl_Obj *const reqv[], void *clientDataPtr); /* * Helper macros. */ #define DupBlock(v,s,len) \ ((v) = ckalloc(len), memcpy((v),(s),(len))) #define DupString(v,s) \ do { \ unsigned local__len = (unsigned) (strlen(s) + 1); \ DupBlock((v),(s),local__len); \ } while (0) /* *---------------------------------------------------------------------- * * Tcl_PkgProvide / Tcl_PkgProvideEx -- * * This function is invoked to declare that a particular version of a * particular package is now present in an interpreter. There must not be * any other version of this package already provided in the interpreter. * * Results: * Normally returns TCL_OK; if there is already another version of the * package loaded then TCL_ERROR is returned and an error message is left * in the interp's result. * * Side effects: * The interpreter remembers that this package is available, so that no * other version of the package may be provided for the interpreter. * *---------------------------------------------------------------------- */ #undef Tcl_PkgProvide int Tcl_PkgProvide( Tcl_Interp *interp, /* Interpreter in which package is now * available. */ const char *name, /* Name of package. */ const char *version) /* Version string for package. */ { return Tcl_PkgProvideEx(interp, name, version, NULL); } int Tcl_PkgProvideEx( Tcl_Interp *interp, /* Interpreter in which package is now * available. */ const char *name, /* Name of package. */ const char *version, /* Version string for package. */ const void *clientData) /* clientdata for this package (normally used * for C callback function table) */ { Package *pkgPtr; char *pvi, *vi; int res; pkgPtr = FindPackage(interp, name); if (pkgPtr->version == NULL) { DupString(pkgPtr->version, version); pkgPtr->clientData = clientData; return TCL_OK; } if (CheckVersionAndConvert(interp, pkgPtr->version, &pvi, NULL) != TCL_OK) { return TCL_ERROR; } else if (CheckVersionAndConvert(interp, version, &vi, NULL) != TCL_OK) { ckfree(pvi); return TCL_ERROR; } res = CompareVersions(pvi, vi, NULL); ckfree(pvi); ckfree(vi); if (res == 0) { if (clientData != NULL) { pkgPtr->clientData = clientData; } return TCL_OK; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "conflicting versions provided for package \"%s\": %s, then %s", name, pkgPtr->version, version)); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_PkgRequire / Tcl_PkgRequireEx / Tcl_PkgRequireProc -- * * This function is called by code that depends on a particular version * of a particular package. If the package is not already provided in the * interpreter, this function invokes a Tcl script to provide it. If the * package is already provided, this function makes sure that the * caller's needs don't conflict with the version that is present. * * Results: * If successful, returns the version string for the currently provided * version of the package, which may be different from the "version" * argument. If the caller's requirements cannot be met (e.g. the version * requested conflicts with a currently provided version, or the required * version cannot be found, or the script to provide the required version * generates an error), NULL is returned and an error message is left in * the interp's result. * * Side effects: * The script from some previous "package ifneeded" command may be * invoked to provide the package. * *---------------------------------------------------------------------- */ #undef Tcl_PkgRequire const char * Tcl_PkgRequire( Tcl_Interp *interp, /* Interpreter in which package is now * available. */ const char *name, /* Name of desired package. */ const char *version, /* Version string for desired version; NULL * means use the latest version available. */ int exact) /* Non-zero means that only the particular * version given is acceptable. Zero means use * the latest compatible version. */ { return Tcl_PkgRequireEx(interp, name, version, exact, NULL); } const char * Tcl_PkgRequireEx( Tcl_Interp *interp, /* Interpreter in which package is now * available. */ const char *name, /* Name of desired package. */ const char *version, /* Version string for desired version; NULL * means use the latest version available. */ int exact, /* Non-zero means that only the particular * version given is acceptable. Zero means use * the latest compatible version. */ void *clientDataPtr) /* Used to return the client data for this * package. If it is NULL then the client data * is not returned. This is unchanged if this * call fails for any reason. */ { Tcl_Obj *ov; const char *result = NULL; /* * If an attempt is being made to load this into a standalone executable * on a platform where backlinking is not supported then this must be a * shared version of Tcl (Otherwise the load would have failed). Detect * this situation by checking that this library has been correctly * initialised. If it has not been then return immediately as nothing will * work. */ if (tclEmptyStringRep == NULL) { /* * OK, so what's going on here? * * First, what are we doing? We are performing a check on behalf of * one particular caller, Tcl_InitStubs(). When a package is stub- * enabled, it is statically linked to libtclstub.a, which contains a * copy of Tcl_InitStubs(). When a stub-enabled package is loaded, its * *_Init() function is supposed to call Tcl_InitStubs() before * calling any other functions in the Tcl library. The first Tcl * function called by Tcl_InitStubs() through the stub table is * Tcl_PkgRequireEx(), so this code right here is the first code that * is part of the original Tcl library in the executable that gets * executed on behalf of a newly loaded stub-enabled package. * * One easy error for the developer/builder of a stub-enabled package * to make is to forget to define USE_TCL_STUBS when compiling the * package. When that happens, the package will contain symbols that * are references to the Tcl library, rather than function pointers * referencing the stub table. On platforms that lack backlinking, * those unresolved references may cause the loading of the package to * also load a second copy of the Tcl library, leading to all kinds of * trouble. We would like to catch that error and report a useful * message back to the user. That's what we're doing. * * Second, how does this work? If we reach this point, then the global * variable tclEmptyStringRep has the value NULL. Compare that with * the definition of tclEmptyStringRep near the top of the file * generic/tclObj.c. It clearly should not have the value NULL; it * should point to the char tclEmptyString. If we see it having the * value NULL, then somehow we are seeing a Tcl library that isn't * completely initialized, and that's an indicator for the error * condition described above. (Further explanation is welcome.) * * Third, so what do we do about it? This situation indicates the * package we just loaded wasn't properly compiled to be stub-enabled, * yet it thinks it is stub-enabled (it called Tcl_InitStubs()). We * want to report that the package just loaded is broken, so we want * to place an error message in the interpreter result and return NULL * to indicate failure to Tcl_InitStubs() so that it will also fail. * (Further explanation why we don't want to Tcl_Panic() is welcome. * After all, two Tcl libraries can't be a good thing!) * * Trouble is that's going to be tricky. We're now using a Tcl library * that's not fully initialized. In particular, it doesn't have a * proper value for tclEmptyStringRep. The Tcl_Obj system heavily * depends on the value of tclEmptyStringRep and all of Tcl depends * (increasingly) on the Tcl_Obj system, we need to correct that flaw * before making the calls to set the interpreter result to the error * message. That's the only flaw corrected; other problems with * initialization of the Tcl library are not remedied, so be very * careful about adding any other calls here without checking how they * behave when initialization is incomplete. */ tclEmptyStringRep = &tclEmptyString; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "Cannot load package \"%s\" in standalone executable:" " This package is not compiled with stub support", name)); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNSTUBBED", NULL); return NULL; } /* * Translate between old and new API, and defer to the new function. */ if (version == NULL) { result = PkgRequireCore(interp, name, 0, NULL, clientDataPtr); } else { if (exact && TCL_OK != CheckVersionAndConvert(interp, version, NULL, NULL)) { return NULL; } ov = Tcl_NewStringObj(version, -1); if (exact) { Tcl_AppendStringsToObj(ov, "-", version, NULL); } Tcl_IncrRefCount(ov); result = PkgRequireCore(interp, name, 1, &ov, clientDataPtr); TclDecrRefCount(ov); } return result; } int Tcl_PkgRequireProc( Tcl_Interp *interp, /* Interpreter in which package is now * available. */ const char *name, /* Name of desired package. */ int reqc, /* Requirements constraining the desired * version. */ Tcl_Obj *const reqv[], /* 0 means to use the latest version * available. */ void *clientDataPtr) { const char *result = PkgRequireCore(interp, name, reqc, reqv, clientDataPtr); if (result == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1)); return TCL_OK; } static const char * PkgRequireCore( Tcl_Interp *interp, /* Interpreter in which package is now * available. */ const char *name, /* Name of desired package. */ int reqc, /* Requirements constraining the desired * version. */ Tcl_Obj *const reqv[], /* 0 means to use the latest version * available. */ void *clientDataPtr) { Interp *iPtr = (Interp *) interp; Package *pkgPtr; PkgAvail *availPtr, *bestPtr, *bestStablePtr; char *availVersion, *bestVersion; /* Internal rep. of versions */ int availStable, code, satisfies, pass; char *script, *pkgVersionI; Tcl_DString command; if (TCL_OK != CheckAllRequirements(interp, reqc, reqv)) { return NULL; } /* * It can take up to three passes to find the package: one pass to run the * "package unknown" script, one to run the "package ifneeded" script for * a specific version, and a final pass to lookup the package loaded by * the "package ifneeded" script. */ for (pass=1 ;; pass++) { pkgPtr = FindPackage(interp, name); if (pkgPtr->version != NULL) { break; } /* * Check whether we're already attempting to load some version of this * package (circular dependency detection). */ if (pkgPtr->clientData != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "circular package dependency:" " attempt to provide %s %s requires %s", name, (char *) pkgPtr->clientData, name)); AddRequirementsToResult(interp, reqc, reqv); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "CIRCULARITY", NULL); return NULL; } /* * The package isn't yet present. Search the list of available * versions and invoke the script for the best available version. We * are actually locating the best, and the best stable version. One of * them is then chosen based on the selection mode. */ bestPtr = NULL; bestStablePtr = NULL; bestVersion = NULL; for (availPtr = pkgPtr->availPtr; availPtr != NULL; availPtr = availPtr->nextPtr) { if (CheckVersionAndConvert(interp, availPtr->version, &availVersion, &availStable) != TCL_OK) { /* * The provided version number has invalid syntax. This * should not happen. This should have been caught by the * 'package ifneeded' registering the package. */ continue; } if (bestPtr != NULL) { int res = CompareVersions(availVersion, bestVersion, NULL); /* * Note: Use internal reps! */ if (res <= 0) { /* * The version of the package sought is not as good as the * currently selected version. Ignore it. */ ckfree(availVersion); availVersion = NULL; continue; } } /* * We have found a version which is better than our max. */ if (reqc > 0) { /* Check satisfaction of requirements. */ satisfies = SomeRequirementSatisfied(availVersion, reqc, reqv); if (!satisfies) { ckfree(availVersion); availVersion = NULL; continue; } } bestPtr = availPtr; if (bestVersion != NULL) { ckfree(bestVersion); } bestVersion = availVersion; /* * If this new best version is stable then it also has to be * better than the max stable version found so far. */ if (availStable) { bestStablePtr = availPtr; } } if (bestVersion != NULL) { ckfree(bestVersion); } /* * Now choose a version among the two best. For 'latest' we simply * take (actually keep) the best. For 'stable' we take the best * stable, if there is any, or the best if there is nothing stable. */ if ((iPtr->packagePrefer == PKG_PREFER_STABLE) && (bestStablePtr != NULL)) { bestPtr = bestStablePtr; } if (bestPtr != NULL) { /* * We found an ifneeded script for the package. Be careful while * executing it: this could cause reentrancy, so (a) protect the * script itself from deletion and (b) don't assume that bestPtr * will still exist when the script completes. */ char *versionToProvide = bestPtr->version; script = bestPtr->script; pkgPtr->clientData = versionToProvide; Tcl_Preserve(script); Tcl_Preserve(versionToProvide); code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL); Tcl_Release(script); pkgPtr = FindPackage(interp, name); if (code == TCL_OK) { Tcl_ResetResult(interp); if (pkgPtr->version == NULL) { code = TCL_ERROR; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "attempt to provide package %s %s failed:" " no version of package %s provided", name, versionToProvide, name)); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNPROVIDED", NULL); } else { char *pvi, *vi; if (CheckVersionAndConvert(interp, pkgPtr->version, &pvi, NULL) != TCL_OK) { code = TCL_ERROR; } else if (CheckVersionAndConvert(interp, versionToProvide, &vi, NULL) != TCL_OK) { ckfree(pvi); code = TCL_ERROR; } else { int res = CompareVersions(pvi, vi, NULL); ckfree(pvi); ckfree(vi); if (res != 0) { code = TCL_ERROR; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "attempt to provide package %s %s failed:" " package %s %s provided instead", name, versionToProvide, name, pkgPtr->version)); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "WRONGPROVIDE", NULL); } } } } else if (code != TCL_ERROR) { Tcl_Obj *codePtr = Tcl_NewIntObj(code); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "attempt to provide package %s %s failed:" " bad return code: %s", name, versionToProvide, TclGetString(codePtr))); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); TclDecrRefCount(codePtr); code = TCL_ERROR; } if (code == TCL_ERROR) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"package ifneeded %s %s\" script)", name, versionToProvide)); } Tcl_Release(versionToProvide); if (code != TCL_OK) { /* * Take a non-TCL_OK code from the script as an indication the * package wasn't loaded properly, so the package system * should not remember an improper load. * * This is consistent with our returning NULL. If we're not * willing to tell our caller we got a particular version, we * shouldn't store that version for telling future callers * either. */ if (pkgPtr->version != NULL) { ckfree(pkgPtr->version); pkgPtr->version = NULL; } pkgPtr->clientData = NULL; return NULL; } break; } /* * The package is not in the database. If there is a "package unknown" * command, invoke it (but only on the first pass; after that, we * should not get here in the first place). */ if (pass > 1) { break; } script = ((Interp *) interp)->packageUnknown; if (script != NULL) { Tcl_DStringInit(&command); Tcl_DStringAppend(&command, script, -1); Tcl_DStringAppendElement(&command, name); AddRequirementsToDString(&command, reqc, reqv); code = Tcl_EvalEx(interp, Tcl_DStringValue(&command), Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); Tcl_DStringFree(&command); if ((code != TCL_OK) && (code != TCL_ERROR)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad return code: %d", code)); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "BADRESULT", NULL); code = TCL_ERROR; } if (code == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (\"package unknown\" script)"); return NULL; } Tcl_ResetResult(interp); } } if (pkgPtr->version == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't find package %s", name)); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "UNFOUND", NULL); AddRequirementsToResult(interp, reqc, reqv); return NULL; } /* * At this point we know that the package is present. Make sure that the * provided version meets the current requirements. */ if (reqc != 0) { CheckVersionAndConvert(interp, pkgPtr->version, &pkgVersionI, NULL); satisfies = SomeRequirementSatisfied(pkgVersionI, reqc, reqv); ckfree(pkgVersionI); if (!satisfies) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "version conflict for package \"%s\": have %s, need", name, pkgPtr->version)); Tcl_SetErrorCode(interp, "TCL", "PACKAGE", "VERSIONCONFLICT", NULL); AddRequirementsToResult(interp, reqc, reqv); return NULL; } } if (clientDataPtr) { const void **ptr = (const void **) clientDataPtr; *ptr = pkgPtr->clientData; } return pkgPtr->version; } /* *---------------------------------------------------------------------- * * Tcl_PkgPresent / Tcl_PkgPresentEx -- * * Checks to see whether the specified package is present. If it is not * then no additional action is taken. * * Results: * If successful, returns the version string for the currently provided * version of the package, which may be different from the "version" * argument. If the caller's requirements cannot be met (e.g. the version * requested conflicts with a currently provided version), NULL is * returned and an error message is left in interp->result. * * Side effects: * None. * *---------------------------------------------------------------------- */ #undef Tcl_PkgPresent const char * Tcl_PkgPresent( Tcl_Interp *interp, /* Interpreter in which package is now * available. */ const char *name, /* Name of desired package. */ const char *version, /* Version string for desired version; NULL * means use the latest version available. */ int exact) /* Non-zero means that only the particular * version given is acceptable. Zero means use * the latest compatible version. */ { return Tcl_PkgPresentEx(interp, name, version, exact, NULL); } const char * Tcl_PkgPresentEx( Tcl_Interp *interp, /* Interpreter in which package is now * available. */ const char *name, /* Name of desired package. */ const char *version, /* Version string for desired version; NULL * means use the latest version available. */ int exact, /* Non-zero means that only the particular * version given is acceptable. Zero means use * the latest compatible version. */ void *clientDataPtr) /* Used to return the client data for this * package. If it is NULL then the client data * is not returned. This is unchanged if this * call fails for any reason. */ { Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hPtr; Package *pkgPtr; hPtr = Tcl_FindHashEntry(&iPtr->packageTable, name); if (hPtr) { pkgPtr = Tcl_GetHashValue(hPtr); if (pkgPtr->version != NULL) { /* * At this point we know that the package is present. Make sure * that the provided version meets the current requirement by * calling Tcl_PkgRequireEx() to check for us. */ const char *foundVersion = Tcl_PkgRequireEx(interp, name, version, exact, clientDataPtr); if (foundVersion == NULL) { Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name, NULL); } return foundVersion; } } if (version != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "package %s %s is not present", name, version)); } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "package %s is not present", name)); } Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name, NULL); return NULL; } /* *---------------------------------------------------------------------- * * Tcl_PackageObjCmd -- * * This function is invoked to process the "package" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_PackageObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const pkgOptions[] = { "forget", "ifneeded", "names", "prefer", "present", "provide", "require", "unknown", "vcompare", "versions", "vsatisfies", NULL }; enum pkgOptions { PKG_FORGET, PKG_IFNEEDED, PKG_NAMES, PKG_PREFER, PKG_PRESENT, PKG_PROVIDE, PKG_REQUIRE, PKG_UNKNOWN, PKG_VCOMPARE, PKG_VERSIONS, PKG_VSATISFIES }; Interp *iPtr = (Interp *) interp; int optionIndex, exact, i, satisfies; PkgAvail *availPtr, *prevPtr; Package *pkgPtr; Tcl_HashEntry *hPtr; Tcl_HashSearch search; Tcl_HashTable *tablePtr; const char *version; const char *argv2, *argv3, *argv4; char *iva = NULL, *ivb = NULL; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], pkgOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum pkgOptions) optionIndex) { case PKG_FORGET: { const char *keyString; for (i = 2; i < objc; i++) { keyString = TclGetString(objv[i]); hPtr = Tcl_FindHashEntry(&iPtr->packageTable, keyString); if (hPtr == NULL) { continue; } pkgPtr = Tcl_GetHashValue(hPtr); Tcl_DeleteHashEntry(hPtr); if (pkgPtr->version != NULL) { ckfree(pkgPtr->version); } while (pkgPtr->availPtr != NULL) { availPtr = pkgPtr->availPtr; pkgPtr->availPtr = availPtr->nextPtr; Tcl_EventuallyFree(availPtr->version, TCL_DYNAMIC); Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC); ckfree(availPtr); } ckfree(pkgPtr); } break; } case PKG_IFNEEDED: { int length, res; char *argv3i, *avi; if ((objc != 4) && (objc != 5)) { Tcl_WrongNumArgs(interp, 2, objv, "package version ?script?"); return TCL_ERROR; } argv3 = TclGetString(objv[3]); if (CheckVersionAndConvert(interp, argv3, &argv3i, NULL) != TCL_OK) { return TCL_ERROR; } argv2 = TclGetString(objv[2]); if (objc == 4) { hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2); if (hPtr == NULL) { ckfree(argv3i); return TCL_OK; } pkgPtr = Tcl_GetHashValue(hPtr); } else { pkgPtr = FindPackage(interp, argv2); } argv3 = Tcl_GetStringFromObj(objv[3], &length); for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL; prevPtr = availPtr, availPtr = availPtr->nextPtr) { if (CheckVersionAndConvert(interp, availPtr->version, &avi, NULL) != TCL_OK) { ckfree(argv3i); return TCL_ERROR; } res = CompareVersions(avi, argv3i, NULL); ckfree(avi); if (res == 0){ if (objc == 4) { ckfree(argv3i); Tcl_SetObjResult(interp, Tcl_NewStringObj(availPtr->script, -1)); return TCL_OK; } Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC); break; } } ckfree(argv3i); if (objc == 4) { return TCL_OK; } if (availPtr == NULL) { availPtr = ckalloc(sizeof(PkgAvail)); DupBlock(availPtr->version, argv3, (unsigned) length + 1); if (prevPtr == NULL) { availPtr->nextPtr = pkgPtr->availPtr; pkgPtr->availPtr = availPtr; } else { availPtr->nextPtr = prevPtr->nextPtr; prevPtr->nextPtr = availPtr; } } argv4 = Tcl_GetStringFromObj(objv[4], &length); DupBlock(availPtr->script, argv4, (unsigned) length + 1); break; } case PKG_NAMES: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } else { Tcl_Obj *resultObj; resultObj = Tcl_NewObj(); tablePtr = &iPtr->packageTable; for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { pkgPtr = Tcl_GetHashValue(hPtr); if ((pkgPtr->version != NULL) || (pkgPtr->availPtr != NULL)) { Tcl_ListObjAppendElement(NULL,resultObj, Tcl_NewStringObj( Tcl_GetHashKey(tablePtr, hPtr), -1)); } } Tcl_SetObjResult(interp, resultObj); } break; case PKG_PRESENT: { const char *name; if (objc < 3) { goto require; } argv2 = TclGetString(objv[2]); if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) { if (objc != 5) { goto requireSyntax; } exact = 1; name = TclGetString(objv[3]); } else { exact = 0; name = argv2; } hPtr = Tcl_FindHashEntry(&iPtr->packageTable, name); if (hPtr != NULL) { pkgPtr = Tcl_GetHashValue(hPtr); if (pkgPtr->version != NULL) { goto require; } } version = NULL; if (exact) { version = TclGetString(objv[4]); if (CheckVersionAndConvert(interp, version, NULL, NULL) != TCL_OK) { return TCL_ERROR; } } else { if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) { return TCL_ERROR; } if ((objc > 3) && (CheckVersionAndConvert(interp, TclGetString(objv[3]), NULL, NULL) == TCL_OK)) { version = TclGetString(objv[3]); } } Tcl_PkgPresentEx(interp, name, version, exact, NULL); return TCL_ERROR; break; } case PKG_PROVIDE: if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 2, objv, "package ?version?"); return TCL_ERROR; } argv2 = TclGetString(objv[2]); if (objc == 3) { hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2); if (hPtr != NULL) { pkgPtr = Tcl_GetHashValue(hPtr); if (pkgPtr->version != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(pkgPtr->version, -1)); } } return TCL_OK; } argv3 = TclGetString(objv[3]); if (CheckVersionAndConvert(interp, argv3, NULL, NULL) != TCL_OK) { return TCL_ERROR; } return Tcl_PkgProvideEx(interp, argv2, argv3, NULL); case PKG_REQUIRE: require: if (objc < 3) { requireSyntax: Tcl_WrongNumArgs(interp, 2, objv, "?-exact? package ?requirement ...?"); return TCL_ERROR; } version = NULL; argv2 = TclGetString(objv[2]); if ((argv2[0] == '-') && (strcmp(argv2, "-exact") == 0)) { Tcl_Obj *ov; int res; if (objc != 5) { goto requireSyntax; } version = TclGetString(objv[4]); if (CheckVersionAndConvert(interp, version, NULL, NULL) != TCL_OK) { return TCL_ERROR; } /* * Create a new-style requirement for the exact version. */ ov = Tcl_NewStringObj(version, -1); Tcl_AppendStringsToObj(ov, "-", version, NULL); version = NULL; argv3 = TclGetString(objv[3]); Tcl_IncrRefCount(ov); res = Tcl_PkgRequireProc(interp, argv3, 1, &ov, NULL); TclDecrRefCount(ov); return res; } else { if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) { return TCL_ERROR; } return Tcl_PkgRequireProc(interp, argv2, objc-3, objv+3, NULL); } break; case PKG_UNKNOWN: { int length; if (objc == 2) { if (iPtr->packageUnknown != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(iPtr->packageUnknown, -1)); } } else if (objc == 3) { if (iPtr->packageUnknown != NULL) { ckfree(iPtr->packageUnknown); } argv2 = Tcl_GetStringFromObj(objv[2], &length); if (argv2[0] == 0) { iPtr->packageUnknown = NULL; } else { DupBlock(iPtr->packageUnknown, argv2, (unsigned) length+1); } } else { Tcl_WrongNumArgs(interp, 2, objv, "?command?"); return TCL_ERROR; } break; } case PKG_PREFER: { static const char *const pkgPreferOptions[] = { "latest", "stable", NULL }; /* * See tclInt.h for the enum, just before Interp. */ if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?latest|stable?"); return TCL_ERROR; } else if (objc == 3) { /* * Seting the value. */ int newPref; if (Tcl_GetIndexFromObj(interp, objv[2], pkgPreferOptions, "preference", 0, &newPref) != TCL_OK) { return TCL_ERROR; } if (newPref < iPtr->packagePrefer) { iPtr->packagePrefer = newPref; } } /* * Always return current value. */ Tcl_SetObjResult(interp, Tcl_NewStringObj(pkgPreferOptions[iPtr->packagePrefer], -1)); break; } case PKG_VCOMPARE: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "version1 version2"); return TCL_ERROR; } argv3 = TclGetString(objv[3]); argv2 = TclGetString(objv[2]); if (CheckVersionAndConvert(interp, argv2, &iva, NULL) != TCL_OK || CheckVersionAndConvert(interp, argv3, &ivb, NULL) != TCL_OK) { if (iva != NULL) { ckfree(iva); } /* * ivb cannot be set in this branch. */ return TCL_ERROR; } /* * Comparison is done on the internal representation. */ Tcl_SetObjResult(interp, Tcl_NewIntObj(CompareVersions(iva, ivb, NULL))); ckfree(iva); ckfree(ivb); break; case PKG_VERSIONS: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "package"); return TCL_ERROR; } else { Tcl_Obj *resultObj = Tcl_NewObj(); argv2 = TclGetString(objv[2]); hPtr = Tcl_FindHashEntry(&iPtr->packageTable, argv2); if (hPtr != NULL) { pkgPtr = Tcl_GetHashValue(hPtr); for (availPtr = pkgPtr->availPtr; availPtr != NULL; availPtr = availPtr->nextPtr) { Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(availPtr->version, -1)); } } Tcl_SetObjResult(interp, resultObj); } break; case PKG_VSATISFIES: { char *argv2i = NULL; if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, "version ?requirement ...?"); return TCL_ERROR; } argv2 = TclGetString(objv[2]); if (CheckVersionAndConvert(interp, argv2, &argv2i, NULL) != TCL_OK) { return TCL_ERROR; } else if (CheckAllRequirements(interp, objc-3, objv+3) != TCL_OK) { ckfree(argv2i); return TCL_ERROR; } satisfies = SomeRequirementSatisfied(argv2i, objc-3, objv+3); ckfree(argv2i); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(satisfies)); break; } default: Tcl_Panic("Tcl_PackageObjCmd: bad option index to pkgOptions"); } return TCL_OK; } /* *---------------------------------------------------------------------- * * FindPackage -- * * This function finds the Package record for a particular package in a * particular interpreter, creating a record if one doesn't already * exist. * * Results: * The return value is a pointer to the Package record for the package. * * Side effects: * A new Package record may be created. * *---------------------------------------------------------------------- */ static Package * FindPackage( Tcl_Interp *interp, /* Interpreter to use for package lookup. */ const char *name) /* Name of package to fine. */ { Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hPtr; int isNew; Package *pkgPtr; hPtr = Tcl_CreateHashEntry(&iPtr->packageTable, name, &isNew); if (isNew) { pkgPtr = ckalloc(sizeof(Package)); pkgPtr->version = NULL; pkgPtr->availPtr = NULL; pkgPtr->clientData = NULL; Tcl_SetHashValue(hPtr, pkgPtr); } else { pkgPtr = Tcl_GetHashValue(hPtr); } return pkgPtr; } /* *---------------------------------------------------------------------- * * TclFreePackageInfo -- * * This function is called during interpreter deletion to free all of the * package-related information for the interpreter. * * Results: * None. * * Side effects: * Memory is freed. * *---------------------------------------------------------------------- */ void TclFreePackageInfo( Interp *iPtr) /* Interpereter that is being deleted. */ { Package *pkgPtr; Tcl_HashSearch search; Tcl_HashEntry *hPtr; PkgAvail *availPtr; for (hPtr = Tcl_FirstHashEntry(&iPtr->packageTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { pkgPtr = Tcl_GetHashValue(hPtr); if (pkgPtr->version != NULL) { ckfree(pkgPtr->version); } while (pkgPtr->availPtr != NULL) { availPtr = pkgPtr->availPtr; pkgPtr->availPtr = availPtr->nextPtr; Tcl_EventuallyFree(availPtr->version, TCL_DYNAMIC); Tcl_EventuallyFree(availPtr->script, TCL_DYNAMIC); ckfree(availPtr); } ckfree(pkgPtr); } Tcl_DeleteHashTable(&iPtr->packageTable); if (iPtr->packageUnknown != NULL) { ckfree(iPtr->packageUnknown); } } /* *---------------------------------------------------------------------- * * CheckVersionAndConvert -- * * This function checks to see whether a version number has valid syntax. * It also generates a semi-internal representation (string rep of a list * of numbers). * * Results: * If string is a properly formed version number the TCL_OK is returned. * Otherwise TCL_ERROR is returned and an error message is left in the * interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int CheckVersionAndConvert( Tcl_Interp *interp, /* Used for error reporting. */ const char *string, /* Supposedly a version number, which is * groups of decimal digits separated by * dots. */ char **internal, /* Internal normalized representation */ int *stable) /* Flag: Version is (un)stable. */ { const char *p = string; char prevChar; int hasunstable = 0; /* * 4* assuming that each char is a separator (a,b become ' -x '). * 4+ to have spce for an additional -2 at the end */ char *ibuf = ckalloc(4 + 4*strlen(string)); char *ip = ibuf; /* * Basic rules * (1) First character has to be a digit. * (2) All other characters have to be a digit or '.' * (3) Two '.'s may not follow each other. * * TIP 268, Modified rules * (1) s.a. * (2) All other characters have to be a digit, 'a', 'b', or '.' * (3) s.a. * (4) Only one of 'a' or 'b' may occur. * (5) Neither 'a', nor 'b' may occur before or after a '.' */ if (!isdigit(UCHAR(*p))) { /* INTL: digit */ goto error; } *ip++ = *p; for (prevChar = *p, p++; *p != 0; p++) { if (!isdigit(UCHAR(*p)) && /* INTL: digit */ ((*p!='.' && *p!='a' && *p!='b') || ((hasunstable && (*p=='a' || *p=='b')) || ((prevChar=='a' || prevChar=='b' || prevChar=='.') && (*p=='.')) || ((*p=='a' || *p=='b' || *p=='.') && prevChar=='.')))) { goto error; } if (*p == 'a' || *p == 'b') { hasunstable = 1; } /* * Translation to the internal rep. Regular version chars are copied * as is. The separators are translated to numerics. The new separator * for all parts is space. */ if (*p == '.') { *ip++ = ' '; *ip++ = '0'; *ip++ = ' '; } else if (*p == 'a') { *ip++ = ' '; *ip++ = '-'; *ip++ = '2'; *ip++ = ' '; } else if (*p == 'b') { *ip++ = ' '; *ip++ = '-'; *ip++ = '1'; *ip++ = ' '; } else { *ip++ = *p; } prevChar = *p; } if (prevChar!='.' && prevChar!='a' && prevChar!='b') { *ip = '\0'; if (internal != NULL) { *internal = ibuf; } else { ckfree(ibuf); } if (stable != NULL) { *stable = !hasunstable; } return TCL_OK; } error: ckfree(ibuf); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected version number but got \"%s\"", string)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "VERSION", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * CompareVersions -- * * This function compares two version numbers (in internal rep). * * Results: * The return value is -1 if v1 is less than v2, 0 if the two version * numbers are the same, and 1 if v1 is greater than v2. If *satPtr is * non-NULL, the word it points to is filled in with 1 if v2 >= v1 and * both numbers have the same major number or 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int CompareVersions( char *v1, char *v2, /* Versions strings, of form 2.1.3 (any number * of version numbers). */ int *isMajorPtr) /* If non-null, the word pointed to is filled * in with a 0/1 value. 1 means that the * difference occured in the first element. */ { int thisIsMajor, res, flip; char *s1, *e1, *s2, *e2, o1, o2; /* * Each iteration of the following loop processes one number from each * string, terminated by a " " (space). If those numbers don't match then * the comparison is over; otherwise, we loop back for the next number. * * TIP 268. * This is identical the function 'ComparePkgVersion', but using the new * space separator as used by the internal rep of version numbers. The * special separators 'a' and 'b' have already been dealt with in * 'CheckVersionAndConvert', they were translated into numbers as well. * This keeps the comparison sane. Otherwise we would have to compare * numerics, the separators, and also deal with the special case of * end-of-string compared to separators. The semi-list rep we get here is * much easier to handle, as it is still regular. * * Rewritten to not compute a numeric value for the extracted version * number, but do string comparison. Skip any leading zeros for that to * work. This change breaks through the 32bit-limit on version numbers. */ thisIsMajor = 1; s1 = v1; s2 = v2; while (1) { /* * Parse one decimal number from the front of each string. Skip * leading zeros. Terminate found number for upcoming string-wise * comparison, if needed. */ while ((*s1 != 0) && (*s1 == '0')) { s1++; } while ((*s2 != 0) && (*s2 == '0')) { s2++; } /* * s1, s2 now point to the beginnings of the numbers to compare. Test * for their signs first, as shortcut to the result (different signs), * or determines if result has to be flipped (both negative). If there * is no shortcut we have to insert terminators later to limit the * strcmp. */ if ((*s1 == '-') && (*s2 != '-')) { /* s1 < 0, s2 >= 0 => s1 < s2 */ res = -1; break; } if ((*s1 != '-') && (*s2 == '-')) { /* s1 >= 0, s2 < 0 => s1 > s2 */ res = 1; break; } if ((*s1 == '-') && (*s2 == '-')) { /* a < b => -a > -b, etc. */ s1++; s2++; flip = 1; } else { flip = 0; } /* * The string comparison is needed, so now we determine where the * numbers end. */ e1 = s1; while ((*e1 != 0) && (*e1 != ' ')) { e1++; } e2 = s2; while ((*e2 != 0) && (*e2 != ' ')) { e2++; } /* * s1 .. e1 and s2 .. e2 now bracket the numbers to compare. Insert * terminators, compare, and restore actual contents. First however * another shortcut. Compare lengths. Shorter string is smaller * number! Thus we strcmp only strings of identical length. */ if ((e1-s1) < (e2-s2)) { res = -1; } else if ((e2-s2) < (e1-s1)) { res = 1; } else { o1 = *e1; *e1 = '\0'; o2 = *e2; *e2 = '\0'; res = strcmp(s1, s2); res = (res < 0) ? -1 : (res ? 1 : 0); *e1 = o1; *e2 = o2; } /* * Stop comparing segments when a difference has been found. Here we * may have to flip the result to account for signs. */ if (res != 0) { if (flip) { res = -res; } break; } /* * Go on to the next version number if the current numbers match. * However stop processing if the end of both numbers has been * reached. */ s1 = e1; s2 = e2; if (*s1 != 0) { s1++; } else if (*s2 == 0) { /* * s1, s2 both at the end => identical */ res = 0; break; } if (*s2 != 0) { s2++; } thisIsMajor = 0; } if (isMajorPtr != NULL) { *isMajorPtr = thisIsMajor; } return res; } /* *---------------------------------------------------------------------- * * CheckAllRequirements -- * * This function checks to see whether all requirements in a set have * valid syntax. * * Results: * TCL_OK is returned if all requirements are valid. Otherwise TCL_ERROR * is returned and an error message is left in the interp's result. * * Side effects: * May modify the interpreter result. * *---------------------------------------------------------------------- */ static int CheckAllRequirements( Tcl_Interp *interp, int reqc, /* Requirements to check. */ Tcl_Obj *const reqv[]) { int i; for (i = 0; i < reqc; i++) { if ((CheckRequirement(interp, TclGetString(reqv[i])) != TCL_OK)) { return TCL_ERROR; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * CheckRequirement -- * * This function checks to see whether a requirement has valid syntax. * * Results: * If string is a properly formed requirement then TCL_OK is returned. * Otherwise TCL_ERROR is returned and an error message is left in the * interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int CheckRequirement( Tcl_Interp *interp, /* Used for error reporting. */ const char *string) /* Supposedly a requirement. */ { /* * Syntax of requirement = version * = version-version * = version- */ char *dash = NULL, *buf; dash = strchr(string, '-'); if (dash == NULL) { /* * No dash found, has to be a simple version. */ return CheckVersionAndConvert(interp, string, NULL, NULL); } if (strchr(dash+1, '-') != NULL) { /* * More dashes found after the first. This is wrong. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected versionMin-versionMax but got \"%s\"", string)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "VERSIONRANGE", NULL); return TCL_ERROR; } /* * Exactly one dash is present. Copy the string, split at the location of * dash and check that both parts are versions. Note that the max part can * be empty. Also note that the string allocated with strdup() must be * freed with free() and not ckfree(). */ DupString(buf, string); dash = buf + (dash - string); *dash = '\0'; /* buf now <=> min part */ dash++; /* dash now <=> max part */ if ((CheckVersionAndConvert(interp, buf, NULL, NULL) != TCL_OK) || ((*dash != '\0') && (CheckVersionAndConvert(interp, dash, NULL, NULL) != TCL_OK))) { ckfree(buf); return TCL_ERROR; } ckfree(buf); return TCL_OK; } /* *---------------------------------------------------------------------- * * AddRequirementsToResult -- * * This function accumulates requirements in the interpreter result. * * Results: * None. * * Side effects: * The interpreter result is extended. * *---------------------------------------------------------------------- */ static void AddRequirementsToResult( Tcl_Interp *interp, int reqc, /* Requirements constraining the desired * version. */ Tcl_Obj *const reqv[]) /* 0 means to use the latest version * available. */ { Tcl_Obj *result = Tcl_GetObjResult(interp); int i, length; for (i = 0; i < reqc; i++) { const char *v = Tcl_GetStringFromObj(reqv[i], &length); if ((length & 0x1) && (v[length/2] == '-') && (strncmp(v, v+((length+1)/2), length/2) == 0)) { Tcl_AppendPrintfToObj(result, " exactly %s", v+((length+1)/2)); } else { Tcl_AppendPrintfToObj(result, " %s", v); } } } /* *---------------------------------------------------------------------- * * AddRequirementsToDString -- * * This function accumulates requirements in a DString. * * Results: * None. * * Side effects: * The DString argument is extended. * *---------------------------------------------------------------------- */ static void AddRequirementsToDString( Tcl_DString *dsPtr, int reqc, /* Requirements constraining the desired * version. */ Tcl_Obj *const reqv[]) /* 0 means to use the latest version * available. */ { int i; if (reqc > 0) { for (i = 0; i < reqc; i++) { TclDStringAppendLiteral(dsPtr, " "); TclDStringAppendObj(dsPtr, reqv[i]); } } else { TclDStringAppendLiteral(dsPtr, " 0-"); } } /* *---------------------------------------------------------------------- * * SomeRequirementSatisfied -- * * This function checks to see whether a version satisfies at least one * of a set of requirements. * * Results: * If the requirements are satisfied 1 is returned. Otherwise 0 is * returned. The function assumes that all pieces have valid syntax. And * is allowed to make that assumption. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int SomeRequirementSatisfied( char *availVersionI, /* Candidate version to check against the * requirements. */ int reqc, /* Requirements constraining the desired * version. */ Tcl_Obj *const reqv[]) /* 0 means to use the latest version * available. */ { int i; for (i = 0; i < reqc; i++) { if (RequirementSatisfied(availVersionI, TclGetString(reqv[i]))) { return 1; } } return 0; } /* *---------------------------------------------------------------------- * * RequirementSatisfied -- * * This function checks to see whether a version satisfies a requirement. * * Results: * If the requirement is satisfied 1 is returned. Otherwise 0 is * returned. The function assumes that all pieces have valid syntax, and * is allowed to make that assumption. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int RequirementSatisfied( char *havei, /* Version string, of candidate package we * have. */ const char *req) /* Requirement string the candidate has to * satisfy. */ { /* * The have candidate is already in internal rep. */ int satisfied, res; char *dash = NULL, *buf, *min, *max; dash = strchr(req, '-'); if (dash == NULL) { /* * No dash found, is a simple version, fallback to regular check. The * 'CheckVersionAndConvert' cannot fail. We pad the requirement with * 'a0', i.e '-2' before doing the comparison to properly accept * unstables as well. */ char *reqi = NULL; int thisIsMajor; CheckVersionAndConvert(NULL, req, &reqi, NULL); strcat(reqi, " -2"); res = CompareVersions(havei, reqi, &thisIsMajor); satisfied = (res == 0) || ((res == 1) && !thisIsMajor); ckfree(reqi); return satisfied; } /* * Exactly one dash is present (Assumption of valid syntax). Copy the req, * split at the location of dash and check that both parts are versions. * Note that the max part can be empty. */ DupString(buf, req); dash = buf + (dash - req); *dash = '\0'; /* buf now <=> min part */ dash++; /* dash now <=> max part */ if (*dash == '\0') { /* * We have a min, but no max. For the comparison we generate the * internal rep, padded with 'a0' i.e. '-2'. */ CheckVersionAndConvert(NULL, buf, &min, NULL); strcat(min, " -2"); satisfied = (CompareVersions(havei, min, NULL) >= 0); ckfree(min); ckfree(buf); return satisfied; } /* * We have both min and max, and generate their internal reps. When * identical we compare as is, otherwise we pad with 'a0' to ove the range * a bit. */ CheckVersionAndConvert(NULL, buf, &min, NULL); CheckVersionAndConvert(NULL, dash, &max, NULL); if (CompareVersions(min, max, NULL) == 0) { satisfied = (CompareVersions(min, havei, NULL) == 0); } else { strcat(min, " -2"); strcat(max, " -2"); satisfied = ((CompareVersions(min, havei, NULL) <= 0) && (CompareVersions(havei, max, NULL) < 0)); } ckfree(min); ckfree(max); ckfree(buf); return satisfied; } /* *---------------------------------------------------------------------- * * Tcl_PkgInitStubsCheck -- * * This is a replacement routine for Tcl_InitStubs() that is called * from code where -DUSE_TCL_STUBS has not been enabled. * * Results: * Returns the version of a conforming stubs table, or NULL, if * the table version doesn't satisfy the requested requirements, * according to historical practice. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * Tcl_PkgInitStubsCheck( Tcl_Interp *interp, const char * version, int exact) { const char *actualVersion = Tcl_PkgPresent(interp, "Tcl", version, 0); if (exact && actualVersion) { const char *p = version; int count = 0; while (*p) { count += !isdigit(UCHAR(*p++)); } if (count == 1) { if (0 != strncmp(version, actualVersion, strlen(version))) { /* Construct error message */ Tcl_PkgPresent(interp, "Tcl", version, 1); return NULL; } } else { return Tcl_PkgPresent(interp, "Tcl", version, 1); } } return actualVersion; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclOOIntDecls.h0000644000175000017500000001606012665173571016030 0ustar sergeisergei/* * This file is (mostly) automatically generated from tclOO.decls. */ #ifndef _TCLOOINTDECLS #define _TCLOOINTDECLS /* !BEGIN!: Do not edit below this line. */ #ifdef __cplusplus extern "C" { #endif /* * Exported function declarations: */ /* 0 */ TCLAPI Tcl_Object TclOOGetDefineCmdContext(Tcl_Interp *interp); /* 1 */ TCLAPI Tcl_Method TclOOMakeProcInstanceMethod(Tcl_Interp *interp, Object *oPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, const Tcl_MethodType *typePtr, ClientData clientData, Proc **procPtrPtr); /* 2 */ TCLAPI Tcl_Method TclOOMakeProcMethod(Tcl_Interp *interp, Class *clsPtr, int flags, Tcl_Obj *nameObj, const char *namePtr, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, const Tcl_MethodType *typePtr, ClientData clientData, Proc **procPtrPtr); /* 3 */ TCLAPI Method * TclOONewProcInstanceMethod(Tcl_Interp *interp, Object *oPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr); /* 4 */ TCLAPI Method * TclOONewProcMethod(Tcl_Interp *interp, Class *clsPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr); /* 5 */ TCLAPI int TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv, int publicOnly, Class *startCls); /* 6 */ TCLAPI int TclOOIsReachable(Class *targetPtr, Class *startPtr); /* 7 */ TCLAPI Method * TclOONewForwardMethod(Tcl_Interp *interp, Class *clsPtr, int isPublic, Tcl_Obj *nameObj, Tcl_Obj *prefixObj); /* 8 */ TCLAPI Method * TclOONewForwardInstanceMethod(Tcl_Interp *interp, Object *oPtr, int isPublic, Tcl_Obj *nameObj, Tcl_Obj *prefixObj); /* 9 */ TCLAPI Tcl_Method TclOONewProcInstanceMethodEx(Tcl_Interp *interp, Tcl_Object oPtr, TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, ClientData clientData, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags, void **internalTokenPtr); /* 10 */ TCLAPI Tcl_Method TclOONewProcMethodEx(Tcl_Interp *interp, Tcl_Class clsPtr, TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, ClientData clientData, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags, void **internalTokenPtr); /* 11 */ TCLAPI int TclOOInvokeObject(Tcl_Interp *interp, Tcl_Object object, Tcl_Class startCls, int publicPrivate, int objc, Tcl_Obj *const *objv); /* 12 */ TCLAPI void TclOOObjectSetFilters(Object *oPtr, int numFilters, Tcl_Obj *const *filters); /* 13 */ TCLAPI void TclOOClassSetFilters(Tcl_Interp *interp, Class *classPtr, int numFilters, Tcl_Obj *const *filters); /* 14 */ TCLAPI void TclOOObjectSetMixins(Object *oPtr, int numMixins, Class *const *mixins); /* 15 */ TCLAPI void TclOOClassSetMixins(Tcl_Interp *interp, Class *classPtr, int numMixins, Class *const *mixins); typedef struct TclOOIntStubs { int magic; void *hooks; Tcl_Object (*tclOOGetDefineCmdContext) (Tcl_Interp *interp); /* 0 */ Tcl_Method (*tclOOMakeProcInstanceMethod) (Tcl_Interp *interp, Object *oPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, const Tcl_MethodType *typePtr, ClientData clientData, Proc **procPtrPtr); /* 1 */ Tcl_Method (*tclOOMakeProcMethod) (Tcl_Interp *interp, Class *clsPtr, int flags, Tcl_Obj *nameObj, const char *namePtr, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, const Tcl_MethodType *typePtr, ClientData clientData, Proc **procPtrPtr); /* 2 */ Method * (*tclOONewProcInstanceMethod) (Tcl_Interp *interp, Object *oPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr); /* 3 */ Method * (*tclOONewProcMethod) (Tcl_Interp *interp, Class *clsPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr); /* 4 */ int (*tclOOObjectCmdCore) (Object *oPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv, int publicOnly, Class *startCls); /* 5 */ int (*tclOOIsReachable) (Class *targetPtr, Class *startPtr); /* 6 */ Method * (*tclOONewForwardMethod) (Tcl_Interp *interp, Class *clsPtr, int isPublic, Tcl_Obj *nameObj, Tcl_Obj *prefixObj); /* 7 */ Method * (*tclOONewForwardInstanceMethod) (Tcl_Interp *interp, Object *oPtr, int isPublic, Tcl_Obj *nameObj, Tcl_Obj *prefixObj); /* 8 */ Tcl_Method (*tclOONewProcInstanceMethodEx) (Tcl_Interp *interp, Tcl_Object oPtr, TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, ClientData clientData, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags, void **internalTokenPtr); /* 9 */ Tcl_Method (*tclOONewProcMethodEx) (Tcl_Interp *interp, Tcl_Class clsPtr, TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, ClientData clientData, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags, void **internalTokenPtr); /* 10 */ int (*tclOOInvokeObject) (Tcl_Interp *interp, Tcl_Object object, Tcl_Class startCls, int publicPrivate, int objc, Tcl_Obj *const *objv); /* 11 */ void (*tclOOObjectSetFilters) (Object *oPtr, int numFilters, Tcl_Obj *const *filters); /* 12 */ void (*tclOOClassSetFilters) (Tcl_Interp *interp, Class *classPtr, int numFilters, Tcl_Obj *const *filters); /* 13 */ void (*tclOOObjectSetMixins) (Object *oPtr, int numMixins, Class *const *mixins); /* 14 */ void (*tclOOClassSetMixins) (Tcl_Interp *interp, Class *classPtr, int numMixins, Class *const *mixins); /* 15 */ } TclOOIntStubs; extern const TclOOIntStubs *tclOOIntStubsPtr; #ifdef __cplusplus } #endif #if defined(USE_TCLOO_STUBS) /* * Inline function declarations: */ #define TclOOGetDefineCmdContext \ (tclOOIntStubsPtr->tclOOGetDefineCmdContext) /* 0 */ #define TclOOMakeProcInstanceMethod \ (tclOOIntStubsPtr->tclOOMakeProcInstanceMethod) /* 1 */ #define TclOOMakeProcMethod \ (tclOOIntStubsPtr->tclOOMakeProcMethod) /* 2 */ #define TclOONewProcInstanceMethod \ (tclOOIntStubsPtr->tclOONewProcInstanceMethod) /* 3 */ #define TclOONewProcMethod \ (tclOOIntStubsPtr->tclOONewProcMethod) /* 4 */ #define TclOOObjectCmdCore \ (tclOOIntStubsPtr->tclOOObjectCmdCore) /* 5 */ #define TclOOIsReachable \ (tclOOIntStubsPtr->tclOOIsReachable) /* 6 */ #define TclOONewForwardMethod \ (tclOOIntStubsPtr->tclOONewForwardMethod) /* 7 */ #define TclOONewForwardInstanceMethod \ (tclOOIntStubsPtr->tclOONewForwardInstanceMethod) /* 8 */ #define TclOONewProcInstanceMethodEx \ (tclOOIntStubsPtr->tclOONewProcInstanceMethodEx) /* 9 */ #define TclOONewProcMethodEx \ (tclOOIntStubsPtr->tclOONewProcMethodEx) /* 10 */ #define TclOOInvokeObject \ (tclOOIntStubsPtr->tclOOInvokeObject) /* 11 */ #define TclOOObjectSetFilters \ (tclOOIntStubsPtr->tclOOObjectSetFilters) /* 12 */ #define TclOOClassSetFilters \ (tclOOIntStubsPtr->tclOOClassSetFilters) /* 13 */ #define TclOOObjectSetMixins \ (tclOOIntStubsPtr->tclOOObjectSetMixins) /* 14 */ #define TclOOClassSetMixins \ (tclOOIntStubsPtr->tclOOClassSetMixins) /* 15 */ #endif /* defined(USE_TCLOO_STUBS) */ /* !END!: Do not edit above this line. */ #endif /* _TCLOOINTDECLS */ tcl8.6.5/generic/regc_lex.c0000644000175000017500000006176712663660065015160 0ustar sergeisergei/* * lexical analyzer * This file is #included by regcomp.c. * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* scanning macros (know about v) */ #define ATEOS() (v->now >= v->stop) #define HAVE(n) (v->stop - v->now >= (n)) #define NEXT1(c) (!ATEOS() && *v->now == CHR(c)) #define NEXT2(a,b) (HAVE(2) && *v->now == CHR(a) && *(v->now+1) == CHR(b)) #define NEXT3(a,b,c) \ (HAVE(3) && *v->now == CHR(a) && \ *(v->now+1) == CHR(b) && \ *(v->now+2) == CHR(c)) #define SET(c) (v->nexttype = (c)) #define SETV(c, n) (v->nexttype = (c), v->nextvalue = (n)) #define RET(c) return (SET(c), 1) #define RETV(c, n) return (SETV(c, n), 1) #define FAILW(e) return (ERR(e), 0) /* ERR does SET(EOS) */ #define LASTTYPE(t) (v->lasttype == (t)) /* lexical contexts */ #define L_ERE 1 /* mainline ERE/ARE */ #define L_BRE 2 /* mainline BRE */ #define L_Q 3 /* REG_QUOTE */ #define L_EBND 4 /* ERE/ARE bound */ #define L_BBND 5 /* BRE bound */ #define L_BRACK 6 /* brackets */ #define L_CEL 7 /* collating element */ #define L_ECL 8 /* equivalence class */ #define L_CCL 9 /* character class */ #define INTOCON(c) (v->lexcon = (c)) #define INCON(con) (v->lexcon == (con)) /* construct pointer past end of chr array */ #define ENDOF(array) ((array) + sizeof(array)/sizeof(chr)) /* - lexstart - set up lexical stuff, scan leading options ^ static void lexstart(struct vars *); */ static void lexstart( struct vars *v) { prefixes(v); /* may turn on new type bits etc. */ NOERR(); if (v->cflags®_QUOTE) { assert(!(v->cflags&(REG_ADVANCED|REG_EXPANDED|REG_NEWLINE))); INTOCON(L_Q); } else if (v->cflags®_EXTENDED) { assert(!(v->cflags®_QUOTE)); INTOCON(L_ERE); } else { assert(!(v->cflags&(REG_QUOTE|REG_ADVF))); INTOCON(L_BRE); } v->nexttype = EMPTY; /* remember we were at the start */ next(v); /* set up the first token */ } /* - prefixes - implement various special prefixes ^ static void prefixes(struct vars *); */ static void prefixes( struct vars *v) { /* * Literal string doesn't get any of this stuff. */ if (v->cflags®_QUOTE) { return; } /* * Initial "***" gets special things. */ if (HAVE(4) && NEXT3('*', '*', '*')) { switch (*(v->now + 3)) { case CHR('?'): /* "***?" error, msg shows version */ ERR(REG_BADPAT); return; /* proceed no further */ break; case CHR('='): /* "***=" shifts to literal string */ NOTE(REG_UNONPOSIX); v->cflags |= REG_QUOTE; v->cflags &= ~(REG_ADVANCED|REG_EXPANDED|REG_NEWLINE); v->now += 4; return; /* and there can be no more prefixes */ break; case CHR(':'): /* "***:" shifts to AREs */ NOTE(REG_UNONPOSIX); v->cflags |= REG_ADVANCED; v->now += 4; break; default: /* otherwise *** is just an error */ ERR(REG_BADRPT); return; break; } } /* * BREs and EREs don't get embedded options. */ if ((v->cflags®_ADVANCED) != REG_ADVANCED) { return; } /* * Embedded options (AREs only). */ if (HAVE(3) && NEXT2('(', '?') && iscalpha(*(v->now + 2))) { NOTE(REG_UNONPOSIX); v->now += 2; for (; !ATEOS() && iscalpha(*v->now); v->now++) { switch (*v->now) { case CHR('b'): /* BREs (but why???) */ v->cflags &= ~(REG_ADVANCED|REG_QUOTE); break; case CHR('c'): /* case sensitive */ v->cflags &= ~REG_ICASE; break; case CHR('e'): /* plain EREs */ v->cflags |= REG_EXTENDED; v->cflags &= ~(REG_ADVF|REG_QUOTE); break; case CHR('i'): /* case insensitive */ v->cflags |= REG_ICASE; break; case CHR('m'): /* Perloid synonym for n */ case CHR('n'): /* \n affects ^ $ . [^ */ v->cflags |= REG_NEWLINE; break; case CHR('p'): /* ~Perl, \n affects . [^ */ v->cflags |= REG_NLSTOP; v->cflags &= ~REG_NLANCH; break; case CHR('q'): /* literal string */ v->cflags |= REG_QUOTE; v->cflags &= ~REG_ADVANCED; break; case CHR('s'): /* single line, \n ordinary */ v->cflags &= ~REG_NEWLINE; break; case CHR('t'): /* tight syntax */ v->cflags &= ~REG_EXPANDED; break; case CHR('w'): /* weird, \n affects ^ $ only */ v->cflags &= ~REG_NLSTOP; v->cflags |= REG_NLANCH; break; case CHR('x'): /* expanded syntax */ v->cflags |= REG_EXPANDED; break; default: ERR(REG_BADOPT); return; } } if (!NEXT1(')')) { ERR(REG_BADOPT); return; } v->now++; if (v->cflags®_QUOTE) { v->cflags &= ~(REG_EXPANDED|REG_NEWLINE); } } } /* - lexnest - "call a subroutine", interpolating string at the lexical level * Note, this is not a very general facility. There are a number of * implicit assumptions about what sorts of strings can be subroutines. ^ static void lexnest(struct vars *, const chr *, const chr *); */ static void lexnest( struct vars *v, const chr *beginp, /* start of interpolation */ const chr *endp) /* one past end of interpolation */ { assert(v->savenow == NULL); /* only one level of nesting */ v->savenow = v->now; v->savestop = v->stop; v->now = beginp; v->stop = endp; } /* * string constants to interpolate as expansions of things like \d */ static const chr backd[] = { /* \d */ CHR('['), CHR('['), CHR(':'), CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'), CHR(':'), CHR(']'), CHR(']') }; static const chr backD[] = { /* \D */ CHR('['), CHR('^'), CHR('['), CHR(':'), CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'), CHR(':'), CHR(']'), CHR(']') }; static const chr brbackd[] = { /* \d within brackets */ CHR('['), CHR(':'), CHR('d'), CHR('i'), CHR('g'), CHR('i'), CHR('t'), CHR(':'), CHR(']') }; static const chr backs[] = { /* \s */ CHR('['), CHR('['), CHR(':'), CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'), CHR(':'), CHR(']'), CHR(']') }; static const chr backS[] = { /* \S */ CHR('['), CHR('^'), CHR('['), CHR(':'), CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'), CHR(':'), CHR(']'), CHR(']') }; static const chr brbacks[] = { /* \s within brackets */ CHR('['), CHR(':'), CHR('s'), CHR('p'), CHR('a'), CHR('c'), CHR('e'), CHR(':'), CHR(']') }; static const chr backw[] = { /* \w */ CHR('['), CHR('['), CHR(':'), CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'), CHR(':'), CHR(']'), CHR('_'), CHR(']') }; static const chr backW[] = { /* \W */ CHR('['), CHR('^'), CHR('['), CHR(':'), CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'), CHR(':'), CHR(']'), CHR('_'), CHR(']') }; static const chr brbackw[] = { /* \w within brackets */ CHR('['), CHR(':'), CHR('a'), CHR('l'), CHR('n'), CHR('u'), CHR('m'), CHR(':'), CHR(']'), CHR('_') }; /* - lexword - interpolate a bracket expression for word characters * Possibly ought to inquire whether there is a "word" character class. ^ static void lexword(struct vars *); */ static void lexword( struct vars *v) { lexnest(v, backw, ENDOF(backw)); } /* - next - get next token ^ static int next(struct vars *); */ static int /* 1 normal, 0 failure */ next( struct vars *v) { chr c; /* * Errors yield an infinite sequence of failures. */ if (ISERR()) { return 0; /* the error has set nexttype to EOS */ } /* * Remember flavor of last token. */ v->lasttype = v->nexttype; /* * REG_BOSONLY */ if (v->nexttype == EMPTY && (v->cflags®_BOSONLY)) { /* at start of a REG_BOSONLY RE */ RETV(SBEGIN, 0); /* same as \A */ } /* * If we're nested and we've hit end, return to outer level. */ if (v->savenow != NULL && ATEOS()) { v->now = v->savenow; v->stop = v->savestop; v->savenow = v->savestop = NULL; } /* * Skip white space etc. if appropriate (not in literal or []) */ if (v->cflags®_EXPANDED) { switch (v->lexcon) { case L_ERE: case L_BRE: case L_EBND: case L_BBND: skip(v); break; } } /* * Handle EOS, depending on context. */ if (ATEOS()) { switch (v->lexcon) { case L_ERE: case L_BRE: case L_Q: RET(EOS); break; case L_EBND: case L_BBND: FAILW(REG_EBRACE); break; case L_BRACK: case L_CEL: case L_ECL: case L_CCL: FAILW(REG_EBRACK); break; } assert(NOTREACHED); } /* * Okay, time to actually get a character. */ c = *v->now++; /* * Deal with the easy contexts, punt EREs to code below. */ switch (v->lexcon) { case L_BRE: /* punt BREs to separate function */ return brenext(v, c); break; case L_ERE: /* see below */ break; case L_Q: /* literal strings are easy */ RETV(PLAIN, c); break; case L_BBND: /* bounds are fairly simple */ case L_EBND: switch (c) { case CHR('0'): case CHR('1'): case CHR('2'): case CHR('3'): case CHR('4'): case CHR('5'): case CHR('6'): case CHR('7'): case CHR('8'): case CHR('9'): RETV(DIGIT, (chr)DIGITVAL(c)); break; case CHR(','): RET(','); break; case CHR('}'): /* ERE bound ends with } */ if (INCON(L_EBND)) { INTOCON(L_ERE); if ((v->cflags®_ADVF) && NEXT1('?')) { v->now++; NOTE(REG_UNONPOSIX); RETV('}', 0); } RETV('}', 1); } else { FAILW(REG_BADBR); } break; case CHR('\\'): /* BRE bound ends with \} */ if (INCON(L_BBND) && NEXT1('}')) { v->now++; INTOCON(L_BRE); RET('}'); } else { FAILW(REG_BADBR); } break; default: FAILW(REG_BADBR); break; } assert(NOTREACHED); break; case L_BRACK: /* brackets are not too hard */ switch (c) { case CHR(']'): if (LASTTYPE('[')) { RETV(PLAIN, c); } else { INTOCON((v->cflags®_EXTENDED) ? L_ERE : L_BRE); RET(']'); } break; case CHR('\\'): NOTE(REG_UBBS); if (!(v->cflags®_ADVF)) { RETV(PLAIN, c); } NOTE(REG_UNONPOSIX); if (ATEOS()) { FAILW(REG_EESCAPE); } (DISCARD)lexescape(v); switch (v->nexttype) { /* not all escapes okay here */ case PLAIN: return 1; break; case CCLASS: switch (v->nextvalue) { case 'd': lexnest(v, brbackd, ENDOF(brbackd)); break; case 's': lexnest(v, brbacks, ENDOF(brbacks)); break; case 'w': lexnest(v, brbackw, ENDOF(brbackw)); break; default: FAILW(REG_EESCAPE); break; } /* * lexnest() done, back up and try again. */ v->nexttype = v->lasttype; return next(v); break; } /* * Not one of the acceptable escapes. */ FAILW(REG_EESCAPE); break; case CHR('-'): if (LASTTYPE('[') || NEXT1(']')) { RETV(PLAIN, c); } else { RETV(RANGE, c); } break; case CHR('['): if (ATEOS()) { FAILW(REG_EBRACK); } switch (*v->now++) { case CHR('.'): INTOCON(L_CEL); /* * Might or might not be locale-specific. */ RET(COLLEL); break; case CHR('='): INTOCON(L_ECL); NOTE(REG_ULOCALE); RET(ECLASS); break; case CHR(':'): INTOCON(L_CCL); NOTE(REG_ULOCALE); RET(CCLASS); break; default: /* oops */ v->now--; RETV(PLAIN, c); break; } assert(NOTREACHED); break; default: RETV(PLAIN, c); break; } assert(NOTREACHED); break; case L_CEL: /* collating elements are easy */ if (c == CHR('.') && NEXT1(']')) { v->now++; INTOCON(L_BRACK); RETV(END, '.'); } else { RETV(PLAIN, c); } break; case L_ECL: /* ditto equivalence classes */ if (c == CHR('=') && NEXT1(']')) { v->now++; INTOCON(L_BRACK); RETV(END, '='); } else { RETV(PLAIN, c); } break; case L_CCL: /* ditto character classes */ if (c == CHR(':') && NEXT1(']')) { v->now++; INTOCON(L_BRACK); RETV(END, ':'); } else { RETV(PLAIN, c); } break; default: assert(NOTREACHED); break; } /* * That got rid of everything except EREs and AREs. */ assert(INCON(L_ERE)); /* * Deal with EREs and AREs, except for backslashes. */ switch (c) { case CHR('|'): RET('|'); break; case CHR('*'): if ((v->cflags®_ADVF) && NEXT1('?')) { v->now++; NOTE(REG_UNONPOSIX); RETV('*', 0); } RETV('*', 1); break; case CHR('+'): if ((v->cflags®_ADVF) && NEXT1('?')) { v->now++; NOTE(REG_UNONPOSIX); RETV('+', 0); } RETV('+', 1); break; case CHR('?'): if ((v->cflags®_ADVF) && NEXT1('?')) { v->now++; NOTE(REG_UNONPOSIX); RETV('?', 0); } RETV('?', 1); break; case CHR('{'): /* bounds start or plain character */ if (v->cflags®_EXPANDED) { skip(v); } if (ATEOS() || !iscdigit(*v->now)) { NOTE(REG_UBRACES); NOTE(REG_UUNSPEC); RETV(PLAIN, c); } else { NOTE(REG_UBOUNDS); INTOCON(L_EBND); RET('{'); } assert(NOTREACHED); break; case CHR('('): /* parenthesis, or advanced extension */ if ((v->cflags®_ADVF) && NEXT1('?')) { NOTE(REG_UNONPOSIX); v->now++; switch (*v->now++) { case CHR(':'): /* non-capturing paren */ RETV('(', 0); break; case CHR('#'): /* comment */ while (!ATEOS() && *v->now != CHR(')')) { v->now++; } if (!ATEOS()) { v->now++; } assert(v->nexttype == v->lasttype); return next(v); break; case CHR('='): /* positive lookahead */ NOTE(REG_ULOOKAHEAD); RETV(LACON, 1); break; case CHR('!'): /* negative lookahead */ NOTE(REG_ULOOKAHEAD); RETV(LACON, 0); break; default: FAILW(REG_BADRPT); break; } assert(NOTREACHED); } if (v->cflags®_NOSUB) { RETV('(', 0); /* all parens non-capturing */ } else { RETV('(', 1); } break; case CHR(')'): if (LASTTYPE('(')) { NOTE(REG_UUNSPEC); } RETV(')', c); break; case CHR('['): /* easy except for [[:<:]] and [[:>:]] */ if (HAVE(6) && *(v->now+0) == CHR('[') && *(v->now+1) == CHR(':') && (*(v->now+2) == CHR('<') || *(v->now+2) == CHR('>')) && *(v->now+3) == CHR(':') && *(v->now+4) == CHR(']') && *(v->now+5) == CHR(']')) { c = *(v->now+2); v->now += 6; NOTE(REG_UNONPOSIX); RET((c == CHR('<')) ? '<' : '>'); } INTOCON(L_BRACK); if (NEXT1('^')) { v->now++; RETV('[', 0); } RETV('[', 1); break; case CHR('.'): RET('.'); break; case CHR('^'): RET('^'); break; case CHR('$'): RET('$'); break; case CHR('\\'): /* mostly punt backslashes to code below */ if (ATEOS()) { FAILW(REG_EESCAPE); } break; default: /* ordinary character */ RETV(PLAIN, c); break; } /* * ERE/ARE backslash handling; backslash already eaten. */ assert(!ATEOS()); if (!(v->cflags®_ADVF)) {/* only AREs have non-trivial escapes */ if (iscalnum(*v->now)) { NOTE(REG_UBSALNUM); NOTE(REG_UUNSPEC); } RETV(PLAIN, *v->now++); } (DISCARD)lexescape(v); if (ISERR()) { FAILW(REG_EESCAPE); } if (v->nexttype == CCLASS) {/* fudge at lexical level */ switch (v->nextvalue) { case 'd': lexnest(v, backd, ENDOF(backd)); break; case 'D': lexnest(v, backD, ENDOF(backD)); break; case 's': lexnest(v, backs, ENDOF(backs)); break; case 'S': lexnest(v, backS, ENDOF(backS)); break; case 'w': lexnest(v, backw, ENDOF(backw)); break; case 'W': lexnest(v, backW, ENDOF(backW)); break; default: assert(NOTREACHED); FAILW(REG_ASSERT); break; } /* lexnest done, back up and try again */ v->nexttype = v->lasttype; return next(v); } /* * Otherwise, lexescape has already done the work. */ return !ISERR(); } /* - lexescape - parse an ARE backslash escape (backslash already eaten) * Note slightly nonstandard use of the CCLASS type code. ^ static int lexescape(struct vars *); */ static int /* not actually used, but convenient for RETV */ lexescape( struct vars *v) { chr c; int i; static const chr alert[] = { CHR('a'), CHR('l'), CHR('e'), CHR('r'), CHR('t') }; static const chr esc[] = { CHR('E'), CHR('S'), CHR('C') }; const chr *save; assert(v->cflags®_ADVF); assert(!ATEOS()); c = *v->now++; if (!iscalnum(c)) { RETV(PLAIN, c); } NOTE(REG_UNONPOSIX); switch (c) { case CHR('a'): RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\007'))); break; case CHR('A'): RETV(SBEGIN, 0); break; case CHR('b'): RETV(PLAIN, CHR('\b')); break; case CHR('B'): RETV(PLAIN, CHR('\\')); break; case CHR('c'): NOTE(REG_UUNPORT); if (ATEOS()) { FAILW(REG_EESCAPE); } RETV(PLAIN, (chr)(*v->now++ & 037)); break; case CHR('d'): NOTE(REG_ULOCALE); RETV(CCLASS, 'd'); break; case CHR('D'): NOTE(REG_ULOCALE); RETV(CCLASS, 'D'); break; case CHR('e'): NOTE(REG_UUNPORT); RETV(PLAIN, chrnamed(v, esc, ENDOF(esc), CHR('\033'))); break; case CHR('f'): RETV(PLAIN, CHR('\f')); break; case CHR('m'): RET('<'); break; case CHR('M'): RET('>'); break; case CHR('n'): RETV(PLAIN, CHR('\n')); break; case CHR('r'): RETV(PLAIN, CHR('\r')); break; case CHR('s'): NOTE(REG_ULOCALE); RETV(CCLASS, 's'); break; case CHR('S'): NOTE(REG_ULOCALE); RETV(CCLASS, 'S'); break; case CHR('t'): RETV(PLAIN, CHR('\t')); break; case CHR('u'): c = (uchr) lexdigits(v, 16, 1, 4); if (ISERR()) { FAILW(REG_EESCAPE); } RETV(PLAIN, c); break; case CHR('U'): i = lexdigits(v, 16, 1, 8); if (ISERR()) { FAILW(REG_EESCAPE); } if (i > 0xFFFF) { /* TODO: output a Surrogate pair */ i = 0xFFFD; } RETV(PLAIN, (uchr) i); break; case CHR('v'): RETV(PLAIN, CHR('\v')); break; case CHR('w'): NOTE(REG_ULOCALE); RETV(CCLASS, 'w'); break; case CHR('W'): NOTE(REG_ULOCALE); RETV(CCLASS, 'W'); break; case CHR('x'): NOTE(REG_UUNPORT); c = (uchr) lexdigits(v, 16, 1, 2); if (ISERR()) { FAILW(REG_EESCAPE); } RETV(PLAIN, c); break; case CHR('y'): NOTE(REG_ULOCALE); RETV(WBDRY, 0); break; case CHR('Y'): NOTE(REG_ULOCALE); RETV(NWBDRY, 0); break; case CHR('Z'): RETV(SEND, 0); break; case CHR('1'): case CHR('2'): case CHR('3'): case CHR('4'): case CHR('5'): case CHR('6'): case CHR('7'): case CHR('8'): case CHR('9'): save = v->now; v->now--; /* put first digit back */ c = (uchr) lexdigits(v, 10, 1, 255); /* REs >255 long outside spec */ if (ISERR()) { FAILW(REG_EESCAPE); } /* * Ugly heuristic (first test is "exactly 1 digit?") */ if (v->now - save == 0 || ((int) c > 0 && (int)c <= v->nsubexp)) { NOTE(REG_UBACKREF); RETV(BACKREF, (chr)c); } /* * Oops, doesn't look like it's a backref after all... */ v->now = save; /* * And fall through into octal number. */ case CHR('0'): NOTE(REG_UUNPORT); v->now--; /* put first digit back */ c = (uchr) lexdigits(v, 8, 1, 3); if (ISERR()) { FAILW(REG_EESCAPE); } if (c > 0xff) { /* out of range, so we handled one digit too much */ v->now--; c >>= 3; } RETV(PLAIN, c); break; default: assert(iscalpha(c)); FAILW(REG_EESCAPE); /* unknown alphabetic escape */ break; } assert(NOTREACHED); } /* - lexdigits - slurp up digits and return chr value ^ static int lexdigits(struct vars *, int, int, int); */ static int /* chr value; errors signalled via ERR */ lexdigits( struct vars *v, int base, int minlen, int maxlen) { int n; int len; chr c; int d; const uchr ub = (uchr) base; n = 0; for (len = 0; len < maxlen && !ATEOS(); len++) { if (n > 0x10fff) { /* Stop when continuing would otherwise overflow */ break; } c = *v->now++; switch (c) { case CHR('0'): case CHR('1'): case CHR('2'): case CHR('3'): case CHR('4'): case CHR('5'): case CHR('6'): case CHR('7'): case CHR('8'): case CHR('9'): d = DIGITVAL(c); break; case CHR('a'): case CHR('A'): d = 10; break; case CHR('b'): case CHR('B'): d = 11; break; case CHR('c'): case CHR('C'): d = 12; break; case CHR('d'): case CHR('D'): d = 13; break; case CHR('e'): case CHR('E'): d = 14; break; case CHR('f'): case CHR('F'): d = 15; break; default: v->now--; /* oops, not a digit at all */ d = -1; break; } if (d >= base) { /* not a plausible digit */ v->now--; d = -1; } if (d < 0) { break; /* NOTE BREAK OUT */ } n = n*ub + (uchr)d; } if (len < minlen) { ERR(REG_EESCAPE); } return n; } /* - brenext - get next BRE token * This is much like EREs except for all the stupid backslashes and the * context-dependency of some things. ^ static int brenext(struct vars *, pchr); */ static int /* 1 normal, 0 failure */ brenext( struct vars *v, pchr pc) { chr c = (chr)pc; switch (c) { case CHR('*'): if (LASTTYPE(EMPTY) || LASTTYPE('(') || LASTTYPE('^')) { RETV(PLAIN, c); } RET('*'); break; case CHR('['): if (HAVE(6) && *(v->now+0) == CHR('[') && *(v->now+1) == CHR(':') && (*(v->now+2) == CHR('<') || *(v->now+2) == CHR('>')) && *(v->now+3) == CHR(':') && *(v->now+4) == CHR(']') && *(v->now+5) == CHR(']')) { c = *(v->now+2); v->now += 6; NOTE(REG_UNONPOSIX); RET((c == CHR('<')) ? '<' : '>'); } INTOCON(L_BRACK); if (NEXT1('^')) { v->now++; RETV('[', 0); } RETV('[', 1); break; case CHR('.'): RET('.'); break; case CHR('^'): if (LASTTYPE(EMPTY)) { RET('^'); } if (LASTTYPE('(')) { NOTE(REG_UUNSPEC); RET('^'); } RETV(PLAIN, c); break; case CHR('$'): if (v->cflags®_EXPANDED) { skip(v); } if (ATEOS()) { RET('$'); } if (NEXT2('\\', ')')) { NOTE(REG_UUNSPEC); RET('$'); } RETV(PLAIN, c); break; case CHR('\\'): break; /* see below */ default: RETV(PLAIN, c); break; } assert(c == CHR('\\')); if (ATEOS()) { FAILW(REG_EESCAPE); } c = *v->now++; switch (c) { case CHR('{'): INTOCON(L_BBND); NOTE(REG_UBOUNDS); RET('{'); break; case CHR('('): RETV('(', 1); break; case CHR(')'): RETV(')', c); break; case CHR('<'): NOTE(REG_UNONPOSIX); RET('<'); break; case CHR('>'): NOTE(REG_UNONPOSIX); RET('>'); break; case CHR('1'): case CHR('2'): case CHR('3'): case CHR('4'): case CHR('5'): case CHR('6'): case CHR('7'): case CHR('8'): case CHR('9'): NOTE(REG_UBACKREF); RETV(BACKREF, (chr)DIGITVAL(c)); break; default: if (iscalnum(c)) { NOTE(REG_UBSALNUM); NOTE(REG_UUNSPEC); } RETV(PLAIN, c); break; } assert(NOTREACHED); } /* - skip - skip white space and comments in expanded form ^ static void skip(struct vars *); */ static void skip( struct vars *v) { const chr *start = v->now; assert(v->cflags®_EXPANDED); for (;;) { while (!ATEOS() && iscspace(*v->now)) { v->now++; } if (ATEOS() || *v->now != CHR('#')) { break; /* NOTE BREAK OUT */ } assert(NEXT1('#')); while (!ATEOS() && *v->now != CHR('\n')) { v->now++; } /* * Leave the newline to be picked up by the iscspace loop. */ } if (v->now != start) { NOTE(REG_UNONPOSIX); } } /* - newline - return the chr for a newline * This helps confine use of CHR to this source file. ^ static chr newline(NOPARMS); */ static chr newline(void) { return CHR('\n'); } /* - chrnamed - return the chr known by a given (chr string) name * The code is a bit clumsy, but this routine gets only such specialized * use that it hardly matters. ^ static chr chrnamed(struct vars *, const chr *, const chr *, pchr); */ static chr chrnamed( struct vars *v, const chr *startp, /* start of name */ const chr *endp, /* just past end of name */ pchr lastresort) /* what to return if name lookup fails */ { celt c; int errsave; int e; struct cvec *cv; errsave = v->err; v->err = 0; c = element(v, startp, endp); e = v->err; v->err = errsave; if (e != 0) { return (chr)lastresort; } cv = range(v, c, c, 0); if (cv->nchrs == 0) { return (chr)lastresort; } return cv->chrs[0]; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclHistory.c0000644000175000017500000001311312663660065015512 0ustar sergeisergei/* * tclHistory.c -- * * This module and the Tcl library file history.tcl together implement * Tcl command history. Tcl_RecordAndEval(Obj) can be called to record * commands ("events") before they are executed. Commands defined in * history.tcl may be used to perform history substitutions. * * Copyright (c) 1990-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Type of the assocData structure used to hold the reference to the [history * add] subcommand, used in Tcl_RecordAndEvalObj. */ typedef struct { Tcl_Obj *historyObj; /* == "::history" */ Tcl_Obj *addObj; /* == "add" */ } HistoryObjs; #define HISTORY_OBJS_KEY "::tcl::HistoryObjs" /* * Static functions in this file. */ static Tcl_InterpDeleteProc DeleteHistoryObjs; /* *---------------------------------------------------------------------- * * Tcl_RecordAndEval -- * * This procedure adds its command argument to the current list of * recorded events and then executes the command by calling Tcl_Eval. * * Results: * The return value is a standard Tcl return value, the result of * executing cmd. * * Side effects: * The command is recorded and executed. * *---------------------------------------------------------------------- */ int Tcl_RecordAndEval( Tcl_Interp *interp, /* Token for interpreter in which command will * be executed. */ const char *cmd, /* Command to record. */ int flags) /* Additional flags. TCL_NO_EVAL means only * record: don't execute command. * TCL_EVAL_GLOBAL means use Tcl_GlobalEval * instead of Tcl_Eval. */ { register Tcl_Obj *cmdPtr; int length = strlen(cmd); int result; if (length > 0) { /* * Call Tcl_RecordAndEvalObj to do the actual work. */ cmdPtr = Tcl_NewStringObj(cmd, length); Tcl_IncrRefCount(cmdPtr); result = Tcl_RecordAndEvalObj(interp, cmdPtr, flags); /* * Move the interpreter's object result to the string result, then * reset the object result. */ (void) Tcl_GetStringResult(interp); /* * Discard the Tcl object created to hold the command. */ Tcl_DecrRefCount(cmdPtr); } else { /* * An empty string. Just reset the interpreter's result. */ Tcl_ResetResult(interp); result = TCL_OK; } return result; } /* *---------------------------------------------------------------------- * * Tcl_RecordAndEvalObj -- * * This procedure adds the command held in its argument object to the * current list of recorded events and then executes the command by * calling Tcl_EvalObj. * * Results: * The return value is a standard Tcl return value, the result of * executing the command. * * Side effects: * The command is recorded and executed. * *---------------------------------------------------------------------- */ int Tcl_RecordAndEvalObj( Tcl_Interp *interp, /* Token for interpreter in which command will * be executed. */ Tcl_Obj *cmdPtr, /* Points to object holding the command to * record and execute. */ int flags) /* Additional flags. TCL_NO_EVAL means record * only: don't execute the command. * TCL_EVAL_GLOBAL means evaluate the script * in global variable context instead of the * current procedure. */ { int result, call = 1; Tcl_CmdInfo info; HistoryObjs *histObjsPtr = Tcl_GetAssocData(interp, HISTORY_OBJS_KEY, NULL); /* * Create the references to the [::history add] command if necessary. */ if (histObjsPtr == NULL) { histObjsPtr = ckalloc(sizeof(HistoryObjs)); TclNewLiteralStringObj(histObjsPtr->historyObj, "::history"); TclNewLiteralStringObj(histObjsPtr->addObj, "add"); Tcl_IncrRefCount(histObjsPtr->historyObj); Tcl_IncrRefCount(histObjsPtr->addObj); Tcl_SetAssocData(interp, HISTORY_OBJS_KEY, DeleteHistoryObjs, histObjsPtr); } /* * Do not call [history] if it has been replaced by an empty proc */ result = Tcl_GetCommandInfo(interp, "::history", &info); if (result && (info.deleteProc == TclProcDeleteProc)) { Proc *procPtr = (Proc *) info.objClientData; call = (procPtr->cmdPtr->compileProc != TclCompileNoOp); } if (call) { Tcl_Obj *list[3]; /* * Do recording by eval'ing a tcl history command: history add $cmd. */ list[0] = histObjsPtr->historyObj; list[1] = histObjsPtr->addObj; list[2] = cmdPtr; Tcl_IncrRefCount(cmdPtr); (void) Tcl_EvalObjv(interp, 3, list, TCL_EVAL_GLOBAL); Tcl_DecrRefCount(cmdPtr); /* * One possible failure mode above: exceeding a resource limit. */ if (Tcl_LimitExceeded(interp)) { return TCL_ERROR; } } /* * Execute the command. */ result = TCL_OK; if (!(flags & TCL_NO_EVAL)) { result = Tcl_EvalObjEx(interp, cmdPtr, flags & TCL_EVAL_GLOBAL); } return result; } /* *---------------------------------------------------------------------- * * DeleteHistoryObjs -- * * Called to delete the references to the constant words used when adding * to the history. * * Results: * None. * * Side effects: * The constant words may be deleted. * *---------------------------------------------------------------------- */ static void DeleteHistoryObjs( ClientData clientData, Tcl_Interp *interp) { register HistoryObjs *histObjsPtr = clientData; TclDecrRefCount(histObjsPtr->historyObj); TclDecrRefCount(histObjsPtr->addObj); ckfree(histObjsPtr); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclOOCall.c0000644000175000017500000012613712663660065015175 0ustar sergeisergei/* * tclOOCall.c -- * * This file contains the method call chain management code for the * object-system core. * * Copyright (c) 2005-2012 by Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tclInt.h" #include "tclOOInt.h" /* * Structure containing a CallContext and any other values needed only during * the construction of the CallContext. */ struct ChainBuilder { CallChain *callChainPtr; /* The call chain being built. */ int filterLength; /* Number of entries in the call chain that * are due to processing filters and not the * main call chain. */ Object *oPtr; /* The object that we are building the chain * for. */ }; /* * Extra flags used for call chain management. */ #define DEFINITE_PROTECTED 0x100000 #define DEFINITE_PUBLIC 0x200000 #define KNOWN_STATE (DEFINITE_PROTECTED | DEFINITE_PUBLIC) #define SPECIAL (CONSTRUCTOR | DESTRUCTOR | FORCE_UNKNOWN) #define BUILDING_MIXINS 0x400000 #define TRAVERSED_MIXIN 0x800000 #define OBJECT_MIXIN 0x1000000 #define MIXIN_CONSISTENT(flags) \ (((flags) & OBJECT_MIXIN) || \ !((flags) & BUILDING_MIXINS) == !((flags) & TRAVERSED_MIXIN)) /* * Function declarations for things defined in this file. */ static void AddClassFiltersToCallContext(Object *const oPtr, Class *clsPtr, struct ChainBuilder *const cbPtr, Tcl_HashTable *const doneFilters, int flags); static void AddClassMethodNames(Class *clsPtr, const int flags, Tcl_HashTable *const namesPtr); static inline void AddMethodToCallChain(Method *const mPtr, struct ChainBuilder *const cbPtr, Tcl_HashTable *const doneFilters, Class *const filterDecl, int flags); static inline void AddSimpleChainToCallContext(Object *const oPtr, Tcl_Obj *const methodNameObj, struct ChainBuilder *const cbPtr, Tcl_HashTable *const doneFilters, int flags, Class *const filterDecl); static void AddSimpleClassChainToCallContext(Class *classPtr, Tcl_Obj *const methodNameObj, struct ChainBuilder *const cbPtr, Tcl_HashTable *const doneFilters, int flags, Class *const filterDecl); static int CmpStr(const void *ptr1, const void *ptr2); static void DupMethodNameRep(Tcl_Obj *srcPtr, Tcl_Obj *dstPtr); static int FinalizeMethodRefs(ClientData data[], Tcl_Interp *interp, int result); static void FreeMethodNameRep(Tcl_Obj *objPtr); static inline int IsStillValid(CallChain *callPtr, Object *oPtr, int flags, int reuseMask); static int ResetFilterFlags(ClientData data[], Tcl_Interp *interp, int result); static int SetFilterFlags(ClientData data[], Tcl_Interp *interp, int result); static inline void StashCallChain(Tcl_Obj *objPtr, CallChain *callPtr); /* * Object type used to manage type caches attached to method names. */ static const Tcl_ObjType methodNameType = { "TclOO method name", FreeMethodNameRep, DupMethodNameRep, NULL, NULL }; /* * ---------------------------------------------------------------------- * * TclOODeleteContext -- * * Destroys a method call-chain context, which should not be in use. * * ---------------------------------------------------------------------- */ void TclOODeleteContext( CallContext *contextPtr) { register Object *oPtr = contextPtr->oPtr; TclOODeleteChain(contextPtr->callPtr); if (oPtr != NULL) { TclStackFree(oPtr->fPtr->interp, contextPtr); DelRef(oPtr); } } /* * ---------------------------------------------------------------------- * * TclOODeleteChainCache -- * * Destroy the cache of method call-chains. * * ---------------------------------------------------------------------- */ void TclOODeleteChainCache( Tcl_HashTable *tablePtr) { FOREACH_HASH_DECLS; CallChain *callPtr; FOREACH_HASH_VALUE(callPtr, tablePtr) { if (callPtr) { TclOODeleteChain(callPtr); } } Tcl_DeleteHashTable(tablePtr); ckfree(tablePtr); } /* * ---------------------------------------------------------------------- * * TclOODeleteChain -- * * Destroys a method call-chain. * * ---------------------------------------------------------------------- */ void TclOODeleteChain( CallChain *callPtr) { if (callPtr == NULL || callPtr->refCount-- > 1) { return; } if (callPtr->chain != callPtr->staticChain) { ckfree(callPtr->chain); } ckfree(callPtr); } /* * ---------------------------------------------------------------------- * * TclOOStashContext -- * * Saves a reference to a method call context in a Tcl_Obj's internal * representation. * * ---------------------------------------------------------------------- */ static inline void StashCallChain( Tcl_Obj *objPtr, CallChain *callPtr) { callPtr->refCount++; TclFreeIntRep(objPtr); objPtr->typePtr = &methodNameType; objPtr->internalRep.twoPtrValue.ptr1 = callPtr; } void TclOOStashContext( Tcl_Obj *objPtr, CallContext *contextPtr) { StashCallChain(objPtr, contextPtr->callPtr); } /* * ---------------------------------------------------------------------- * * DupMethodNameRep, FreeMethodNameRep -- * * Functions to implement the required parts of the Tcl_Obj guts needed * for caching of method contexts in Tcl_Objs. * * ---------------------------------------------------------------------- */ static void DupMethodNameRep( Tcl_Obj *srcPtr, Tcl_Obj *dstPtr) { register CallChain *callPtr = srcPtr->internalRep.twoPtrValue.ptr1; dstPtr->typePtr = &methodNameType; dstPtr->internalRep.twoPtrValue.ptr1 = callPtr; callPtr->refCount++; } static void FreeMethodNameRep( Tcl_Obj *objPtr) { register CallChain *callPtr = objPtr->internalRep.twoPtrValue.ptr1; TclOODeleteChain(callPtr); objPtr->typePtr = NULL; } /* * ---------------------------------------------------------------------- * * TclOOInvokeContext -- * * Invokes a single step along a method call-chain context. Note that the * invokation of a step along the chain can cause further steps along the * chain to be invoked. Note that this function is written to be as light * in stack usage as possible. * * ---------------------------------------------------------------------- */ int TclOOInvokeContext( ClientData clientData, /* The method call context. */ Tcl_Interp *interp, /* Interpreter for error reporting, and many * other sorts of context handling (e.g., * commands, variables) depending on method * implementation. */ int objc, /* The number of arguments. */ Tcl_Obj *const objv[]) /* The arguments as actually seen. */ { register CallContext *const contextPtr = clientData; Method *const mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; const int isFilter = contextPtr->callPtr->chain[contextPtr->index].isFilter; /* * If this is the first step along the chain, we preserve the method * entries in the chain so that they do not get deleted out from under our * feet. */ if (contextPtr->index == 0) { int i; for (i=0 ; icallPtr->numChain ; i++) { AddRef(contextPtr->callPtr->chain[i].mPtr); } /* * Ensure that the method name itself is part of the arguments when * we're doing unknown processing. */ if (contextPtr->callPtr->flags & OO_UNKNOWN_METHOD) { contextPtr->skip--; } /* * Add a callback to ensure that method references are dropped once * this call is finished. */ TclNRAddCallback(interp, FinalizeMethodRefs, contextPtr, NULL, NULL, NULL); } /* * Save whether we were in a filter and set up whether we are now. */ if (contextPtr->oPtr->flags & FILTER_HANDLING) { TclNRAddCallback(interp, SetFilterFlags, contextPtr, NULL,NULL,NULL); } else { TclNRAddCallback(interp, ResetFilterFlags,contextPtr,NULL,NULL,NULL); } if (isFilter || contextPtr->callPtr->flags & FILTER_HANDLING) { contextPtr->oPtr->flags |= FILTER_HANDLING; } else { contextPtr->oPtr->flags &= ~FILTER_HANDLING; } /* * Run the method implementation. */ return mPtr->typePtr->callProc(mPtr->clientData, interp, (Tcl_ObjectContext) contextPtr, objc, objv); } static int SetFilterFlags( ClientData data[], Tcl_Interp *interp, int result) { CallContext *contextPtr = data[0]; contextPtr->oPtr->flags |= FILTER_HANDLING; return result; } static int ResetFilterFlags( ClientData data[], Tcl_Interp *interp, int result) { CallContext *contextPtr = data[0]; contextPtr->oPtr->flags &= ~FILTER_HANDLING; return result; } static int FinalizeMethodRefs( ClientData data[], Tcl_Interp *interp, int result) { CallContext *contextPtr = data[0]; int i; for (i=0 ; icallPtr->numChain ; i++) { TclOODelMethodRef(contextPtr->callPtr->chain[i].mPtr); } return result; } /* * ---------------------------------------------------------------------- * * TclOOGetSortedMethodList, TclOOGetSortedClassMethodList -- * * Discovers the list of method names supported by an object or class. * * ---------------------------------------------------------------------- */ int TclOOGetSortedMethodList( Object *oPtr, /* The object to get the method names for. */ int flags, /* Whether we just want the public method * names. */ const char ***stringsPtr) /* Where to write a pointer to the array of * strings to. */ { Tcl_HashTable names; /* Tcl_Obj* method name to "wanted in list" * mapping. */ FOREACH_HASH_DECLS; int i; Class *mixinPtr; Tcl_Obj *namePtr; Method *mPtr; int isWantedIn; void *isWanted; Tcl_InitObjHashTable(&names); /* * Name the bits used in the names table values. */ #define IN_LIST 1 #define NO_IMPLEMENTATION 2 /* * Process method names due to the object. */ if (oPtr->methodsPtr) { FOREACH_HASH(namePtr, mPtr, oPtr->methodsPtr) { int isNew; if ((mPtr->flags & PRIVATE_METHOD) && !(flags & PRIVATE_METHOD)) { continue; } hPtr = Tcl_CreateHashEntry(&names, (char *) namePtr, &isNew); if (isNew) { isWantedIn = ((!(flags & PUBLIC_METHOD) || mPtr->flags & PUBLIC_METHOD) ? IN_LIST : 0); isWantedIn |= (mPtr->typePtr == NULL ? NO_IMPLEMENTATION : 0); Tcl_SetHashValue(hPtr, INT2PTR(isWantedIn)); } } } /* * Process method names due to private methods on the object's class. */ if (flags & PRIVATE_METHOD) { FOREACH_HASH(namePtr, mPtr, &oPtr->selfCls->classMethods) { if (mPtr->flags & PRIVATE_METHOD) { int isNew; hPtr = Tcl_CreateHashEntry(&names, (char *) namePtr, &isNew); if (isNew) { isWantedIn = IN_LIST; if (mPtr->typePtr == NULL) { isWantedIn |= NO_IMPLEMENTATION; } Tcl_SetHashValue(hPtr, INT2PTR(isWantedIn)); } else if (mPtr->typePtr != NULL) { isWantedIn = PTR2INT(Tcl_GetHashValue(hPtr)); if (isWantedIn & NO_IMPLEMENTATION) { isWantedIn &= ~NO_IMPLEMENTATION; Tcl_SetHashValue(hPtr, INT2PTR(isWantedIn)); } } } } } /* * Process (normal) method names from the class hierarchy and the mixin * hierarchy. */ AddClassMethodNames(oPtr->selfCls, flags, &names); FOREACH(mixinPtr, oPtr->mixins) { AddClassMethodNames(mixinPtr, flags|TRAVERSED_MIXIN, &names); } /* * See how many (visible) method names there are. If none, we do not (and * should not) try to sort the list of them. */ i = 0; if (names.numEntries != 0) { const char **strings; /* * We need to build the list of methods to sort. We will be using * qsort() for this, because it is very unlikely that the list will be * heavily sorted when it is long enough to matter. */ strings = ckalloc(sizeof(char *) * names.numEntries); FOREACH_HASH(namePtr, isWanted, &names) { if (!(flags & PUBLIC_METHOD) || (PTR2INT(isWanted) & IN_LIST)) { if (PTR2INT(isWanted) & NO_IMPLEMENTATION) { continue; } strings[i++] = TclGetString(namePtr); } } /* * Note that 'i' may well be less than names.numEntries when we are * dealing with public method names. */ if (i > 0) { if (i > 1) { qsort((void *) strings, (unsigned) i, sizeof(char *), CmpStr); } *stringsPtr = strings; } else { ckfree(strings); } } Tcl_DeleteHashTable(&names); return i; } int TclOOGetSortedClassMethodList( Class *clsPtr, /* The class to get the method names for. */ int flags, /* Whether we just want the public method * names. */ const char ***stringsPtr) /* Where to write a pointer to the array of * strings to. */ { Tcl_HashTable names; /* Tcl_Obj* method name to "wanted in list" * mapping. */ FOREACH_HASH_DECLS; int i; Tcl_Obj *namePtr; void *isWanted; Tcl_InitObjHashTable(&names); /* * Process method names from the class hierarchy and the mixin hierarchy. */ AddClassMethodNames(clsPtr, flags, &names); /* * See how many (visible) method names there are. If none, we do not (and * should not) try to sort the list of them. */ i = 0; if (names.numEntries != 0) { const char **strings; /* * We need to build the list of methods to sort. We will be using * qsort() for this, because it is very unlikely that the list will be * heavily sorted when it is long enough to matter. */ strings = ckalloc(sizeof(char *) * names.numEntries); FOREACH_HASH(namePtr, isWanted, &names) { if (!(flags & PUBLIC_METHOD) || (PTR2INT(isWanted) & IN_LIST)) { if (PTR2INT(isWanted) & NO_IMPLEMENTATION) { continue; } strings[i++] = TclGetString(namePtr); } } /* * Note that 'i' may well be less than names.numEntries when we are * dealing with public method names. */ if (i > 0) { if (i > 1) { qsort((void *) strings, (unsigned) i, sizeof(char *), CmpStr); } *stringsPtr = strings; } else { ckfree(strings); } } Tcl_DeleteHashTable(&names); return i; } /* Comparator for GetSortedMethodList */ static int CmpStr( const void *ptr1, const void *ptr2) { const char **strPtr1 = (const char **) ptr1; const char **strPtr2 = (const char **) ptr2; return TclpUtfNcmp2(*strPtr1, *strPtr2, strlen(*strPtr1)+1); } /* * ---------------------------------------------------------------------- * * AddClassMethodNames -- * * Adds the method names defined by a class (or its superclasses) to the * collection being built. The collection is built in a hash table to * ensure that duplicates are excluded. Helper for GetSortedMethodList(). * * ---------------------------------------------------------------------- */ static void AddClassMethodNames( Class *clsPtr, /* Class to get method names from. */ const int flags, /* Whether we are interested in just the * public method names. */ Tcl_HashTable *const namesPtr) /* Reference to the hash table to put the * information in. The hash table maps the * Tcl_Obj * method name to an integral value * describing whether the method is wanted. * This ensures that public/private override * semantics are handled correctly.*/ { /* * Scope all declarations so that the compiler can stand a good chance of * making the recursive step highly efficient. We also hand-implement the * tail-recursive case using a while loop; C compilers typically cannot do * tail-recursion optimization usefully. */ if (clsPtr->mixins.num != 0) { Class *mixinPtr; int i; /* TODO: Beware of infinite loops! */ FOREACH(mixinPtr, clsPtr->mixins) { AddClassMethodNames(mixinPtr, flags|TRAVERSED_MIXIN, namesPtr); } } while (1) { FOREACH_HASH_DECLS; Tcl_Obj *namePtr; Method *mPtr; FOREACH_HASH(namePtr, mPtr, &clsPtr->classMethods) { int isNew; hPtr = Tcl_CreateHashEntry(namesPtr, (char *) namePtr, &isNew); if (isNew) { int isWanted = (!(flags & PUBLIC_METHOD) || (mPtr->flags & PUBLIC_METHOD)) ? IN_LIST : 0; Tcl_SetHashValue(hPtr, INT2PTR(isWanted)); } else if ((PTR2INT(Tcl_GetHashValue(hPtr)) & NO_IMPLEMENTATION) && mPtr->typePtr != NULL) { int isWanted = PTR2INT(Tcl_GetHashValue(hPtr)); isWanted &= ~NO_IMPLEMENTATION; Tcl_SetHashValue(hPtr, INT2PTR(isWanted)); } } if (clsPtr->superclasses.num != 1) { break; } clsPtr = clsPtr->superclasses.list[0]; } if (clsPtr->superclasses.num != 0) { Class *superPtr; int i; FOREACH(superPtr, clsPtr->superclasses) { AddClassMethodNames(superPtr, flags, namesPtr); } } } /* * ---------------------------------------------------------------------- * * AddSimpleChainToCallContext -- * * The core of the call-chain construction engine, this handles calling a * particular method on a particular object. Note that filters and * unknown handling are already handled by the logic that uses this * function. * * ---------------------------------------------------------------------- */ static inline void AddSimpleChainToCallContext( Object *const oPtr, /* Object to add call chain entries for. */ Tcl_Obj *const methodNameObj, /* Name of method to add the call chain * entries for. */ struct ChainBuilder *const cbPtr, /* Where to add the call chain entries. */ Tcl_HashTable *const doneFilters, /* Where to record what call chain entries * have been processed. */ int flags, /* What sort of call chain are we building. */ Class *const filterDecl) /* The class that declared the filter. If * NULL, either the filter was declared by the * object or this isn't a filter. */ { int i; if (!(flags & (KNOWN_STATE | SPECIAL)) && oPtr->methodsPtr) { Tcl_HashEntry *hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) methodNameObj); if (hPtr != NULL) { Method *mPtr = Tcl_GetHashValue(hPtr); if (flags & PUBLIC_METHOD) { if (!(mPtr->flags & PUBLIC_METHOD)) { return; } else { flags |= DEFINITE_PUBLIC; } } else { flags |= DEFINITE_PROTECTED; } } } if (!(flags & SPECIAL)) { Tcl_HashEntry *hPtr; Class *mixinPtr; FOREACH(mixinPtr, oPtr->mixins) { AddSimpleClassChainToCallContext(mixinPtr, methodNameObj, cbPtr, doneFilters, flags|TRAVERSED_MIXIN, filterDecl); } if (oPtr->methodsPtr) { hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char*) methodNameObj); if (hPtr != NULL) { AddMethodToCallChain(Tcl_GetHashValue(hPtr), cbPtr, doneFilters, filterDecl, flags); } } } AddSimpleClassChainToCallContext(oPtr->selfCls, methodNameObj, cbPtr, doneFilters, flags, filterDecl); } /* * ---------------------------------------------------------------------- * * AddMethodToCallChain -- * * Utility method that manages the adding of a particular method * implementation to a call-chain. * * ---------------------------------------------------------------------- */ static inline void AddMethodToCallChain( Method *const mPtr, /* Actual method implementation to add to call * chain (or NULL, a no-op). */ struct ChainBuilder *const cbPtr, /* The call chain to add the method * implementation to. */ Tcl_HashTable *const doneFilters, /* Where to record what filters have been * processed. If NULL, not processing filters. * Note that this function does not update * this hashtable. */ Class *const filterDecl, /* The class that declared the filter. If * NULL, either the filter was declared by the * object or this isn't a filter. */ int flags) /* Used to check if we're mixin-consistent * only. Mixin-consistent means that either * we're looking to add things from a mixin * and we have passed a mixin, or we're not * looking to add things from a mixin and have * not passed a mixin. */ { register CallChain *callPtr = cbPtr->callChainPtr; int i; /* * Return if this is just an entry used to record whether this is a public * method. If so, there's nothing real to call and so nothing to add to * the call chain. * * This is also where we enforce mixin-consistency. */ if (mPtr == NULL || mPtr->typePtr == NULL || !MIXIN_CONSISTENT(flags)) { return; } /* * Enforce real private method handling here. We will skip adding this * method IF * 1) we are not allowing private methods, AND * 2) this is a private method, AND * 3) this is a class method, AND * 4) this method was not declared by the class of the current object. * * This does mean that only classes really handle private methods. This * should be sufficient for [incr Tcl] support though. */ if (!(callPtr->flags & PRIVATE_METHOD) && (mPtr->flags & PRIVATE_METHOD) && (mPtr->declaringClassPtr != NULL) && (mPtr->declaringClassPtr != cbPtr->oPtr->selfCls)) { return; } /* * First test whether the method is already in the call chain. Skip over * any leading filters. */ for (i=cbPtr->filterLength ; inumChain ; i++) { if (callPtr->chain[i].mPtr == mPtr && callPtr->chain[i].isFilter == (doneFilters != NULL)) { /* * Call chain semantics states that methods come as *late* in the * call chain as possible. This is done by copying down the * following methods. Note that this does not change the number of * method invokations in the call chain; it just rearranges them. */ Class *declCls = callPtr->chain[i].filterDeclarer; for (; i+1numChain ; i++) { callPtr->chain[i] = callPtr->chain[i+1]; } callPtr->chain[i].mPtr = mPtr; callPtr->chain[i].isFilter = (doneFilters != NULL); callPtr->chain[i].filterDeclarer = declCls; return; } } /* * Need to really add the method. This is made a bit more complex by the * fact that we are using some "static" space initially, and only start * realloc-ing if the chain gets long. */ if (callPtr->numChain == CALL_CHAIN_STATIC_SIZE) { callPtr->chain = ckalloc(sizeof(struct MInvoke) * (callPtr->numChain+1)); memcpy(callPtr->chain, callPtr->staticChain, sizeof(struct MInvoke) * callPtr->numChain); } else if (callPtr->numChain > CALL_CHAIN_STATIC_SIZE) { callPtr->chain = ckrealloc(callPtr->chain, sizeof(struct MInvoke) * (callPtr->numChain + 1)); } callPtr->chain[i].mPtr = mPtr; callPtr->chain[i].isFilter = (doneFilters != NULL); callPtr->chain[i].filterDeclarer = filterDecl; callPtr->numChain++; } /* * ---------------------------------------------------------------------- * * InitCallChain -- * Encoding of the policy of how to set up a call chain. Doesn't populate * the chain with the method implementation data. * * ---------------------------------------------------------------------- */ static inline void InitCallChain( CallChain *callPtr, Object *oPtr, int flags) { callPtr->flags = flags & (PUBLIC_METHOD | PRIVATE_METHOD | SPECIAL | FILTER_HANDLING); if (oPtr->flags & USE_CLASS_CACHE) { oPtr = oPtr->selfCls->thisPtr; callPtr->flags |= USE_CLASS_CACHE; } callPtr->epoch = oPtr->fPtr->epoch; callPtr->objectCreationEpoch = oPtr->creationEpoch; callPtr->objectEpoch = oPtr->epoch; callPtr->refCount = 1; callPtr->numChain = 0; callPtr->chain = callPtr->staticChain; } /* * ---------------------------------------------------------------------- * * IsStillValid -- * Calculates whether the given call chain can be used for executing a * method for the given object. The condition on a chain from a cached * location being reusable is: * - Refers to the same object (same creation epoch), and * - Still across the same class structure (same global epoch), and * - Still across the same object strucutre (same local epoch), and * - No public/private/filter magic leakage (same flags, modulo the fact * that a public chain will satisfy a non-public call). * * ---------------------------------------------------------------------- */ static inline int IsStillValid( CallChain *callPtr, Object *oPtr, int flags, int mask) { if ((oPtr->flags & USE_CLASS_CACHE)) { oPtr = oPtr->selfCls->thisPtr; flags |= USE_CLASS_CACHE; } return ((callPtr->objectCreationEpoch == oPtr->creationEpoch) && (callPtr->epoch == oPtr->fPtr->epoch) && (callPtr->objectEpoch == oPtr->epoch) && ((callPtr->flags & mask) == (flags & mask))); } /* * ---------------------------------------------------------------------- * * TclOOGetCallContext -- * * Responsible for constructing the call context, an ordered list of all * method implementations to be called as part of a method invokation. * This method is central to the whole operation of the OO system. * * ---------------------------------------------------------------------- */ CallContext * TclOOGetCallContext( Object *oPtr, /* The object to get the context for. */ Tcl_Obj *methodNameObj, /* The name of the method to get the context * for. NULL when getting a constructor or * destructor chain. */ int flags, /* What sort of context are we looking for. * Only the bits PUBLIC_METHOD, CONSTRUCTOR, * PRIVATE_METHOD, DESTRUCTOR and * FILTER_HANDLING are useful. */ Tcl_Obj *cacheInThisObj) /* What object to cache in, or NULL if it is * to be in the same object as the * methodNameObj. */ { CallContext *contextPtr; CallChain *callPtr; struct ChainBuilder cb; int i, count, doFilters; Tcl_HashEntry *hPtr; Tcl_HashTable doneFilters; if (cacheInThisObj == NULL) { cacheInThisObj = methodNameObj; } if (flags&(SPECIAL|FILTER_HANDLING) || (oPtr->flags&FILTER_HANDLING)) { hPtr = NULL; doFilters = 0; /* * Check if we have a cached valid constructor or destructor. */ if (flags & CONSTRUCTOR) { callPtr = oPtr->selfCls->constructorChainPtr; if ((callPtr != NULL) && (callPtr->objectEpoch == oPtr->selfCls->thisPtr->epoch) && (callPtr->epoch == oPtr->fPtr->epoch)) { callPtr->refCount++; goto returnContext; } } else if (flags & DESTRUCTOR) { callPtr = oPtr->selfCls->destructorChainPtr; if ((oPtr->mixins.num == 0) && (callPtr != NULL) && (callPtr->objectEpoch == oPtr->selfCls->thisPtr->epoch) && (callPtr->epoch == oPtr->fPtr->epoch)) { callPtr->refCount++; goto returnContext; } } } else { /* * Check if we can get the chain out of the Tcl_Obj method name or out * of the cache. This is made a bit more complex by the fact that * there are multiple different layers of cache (in the Tcl_Obj, in * the object, and in the class). */ const int reuseMask = ((flags & PUBLIC_METHOD) ? ~0 : ~PUBLIC_METHOD); if (cacheInThisObj->typePtr == &methodNameType) { callPtr = cacheInThisObj->internalRep.twoPtrValue.ptr1; if (IsStillValid(callPtr, oPtr, flags, reuseMask)) { callPtr->refCount++; goto returnContext; } FreeMethodNameRep(cacheInThisObj); } if (oPtr->flags & USE_CLASS_CACHE) { if (oPtr->selfCls->classChainCache != NULL) { hPtr = Tcl_FindHashEntry(oPtr->selfCls->classChainCache, (char *) methodNameObj); } else { hPtr = NULL; } } else { if (oPtr->chainCache != NULL) { hPtr = Tcl_FindHashEntry(oPtr->chainCache, (char *) methodNameObj); } else { hPtr = NULL; } } if (hPtr != NULL && Tcl_GetHashValue(hPtr) != NULL) { callPtr = Tcl_GetHashValue(hPtr); if (IsStillValid(callPtr, oPtr, flags, reuseMask)) { callPtr->refCount++; goto returnContext; } Tcl_SetHashValue(hPtr, NULL); TclOODeleteChain(callPtr); } doFilters = 1; } callPtr = ckalloc(sizeof(CallChain)); InitCallChain(callPtr, oPtr, flags); cb.callChainPtr = callPtr; cb.filterLength = 0; cb.oPtr = oPtr; /* * If we're working with a forced use of unknown, do that now. */ if (flags & FORCE_UNKNOWN) { AddSimpleChainToCallContext(oPtr, oPtr->fPtr->unknownMethodNameObj, &cb, NULL, BUILDING_MIXINS, NULL); AddSimpleChainToCallContext(oPtr, oPtr->fPtr->unknownMethodNameObj, &cb, NULL, 0, NULL); callPtr->flags |= OO_UNKNOWN_METHOD; callPtr->epoch = -1; if (callPtr->numChain == 0) { TclOODeleteChain(callPtr); return NULL; } goto returnContext; } /* * Add all defined filters (if any, and if we're going to be processing * them; they're not processed for constructors, destructors or when we're * in the middle of processing a filter). */ if (doFilters) { Tcl_Obj *filterObj; Class *mixinPtr; doFilters = 1; Tcl_InitObjHashTable(&doneFilters); FOREACH(mixinPtr, oPtr->mixins) { AddClassFiltersToCallContext(oPtr, mixinPtr, &cb, &doneFilters, TRAVERSED_MIXIN|BUILDING_MIXINS|OBJECT_MIXIN); AddClassFiltersToCallContext(oPtr, mixinPtr, &cb, &doneFilters, OBJECT_MIXIN); } FOREACH(filterObj, oPtr->filters) { AddSimpleChainToCallContext(oPtr, filterObj, &cb, &doneFilters, BUILDING_MIXINS, NULL); AddSimpleChainToCallContext(oPtr, filterObj, &cb, &doneFilters, 0, NULL); } AddClassFiltersToCallContext(oPtr, oPtr->selfCls, &cb, &doneFilters, BUILDING_MIXINS); AddClassFiltersToCallContext(oPtr, oPtr->selfCls, &cb, &doneFilters, 0); Tcl_DeleteHashTable(&doneFilters); } count = cb.filterLength = callPtr->numChain; /* * Add the actual method implementations. We have to do this twice to * handle class mixins right. */ AddSimpleChainToCallContext(oPtr, methodNameObj, &cb, NULL, flags|BUILDING_MIXINS, NULL); AddSimpleChainToCallContext(oPtr, methodNameObj, &cb, NULL, flags, NULL); /* * Check to see if the method has no implementation. If so, we probably * need to add in a call to the unknown method. Otherwise, set up the * cacheing of the method implementation (if relevant). */ if (count == callPtr->numChain) { /* * Method does not actually exist. If we're dealing with constructors * or destructors, this isn't a problem. */ if (flags & SPECIAL) { TclOODeleteChain(callPtr); return NULL; } AddSimpleChainToCallContext(oPtr, oPtr->fPtr->unknownMethodNameObj, &cb, NULL, BUILDING_MIXINS, NULL); AddSimpleChainToCallContext(oPtr, oPtr->fPtr->unknownMethodNameObj, &cb, NULL, 0, NULL); callPtr->flags |= OO_UNKNOWN_METHOD; callPtr->epoch = -1; if (count == callPtr->numChain) { TclOODeleteChain(callPtr); return NULL; } } else if (doFilters) { if (hPtr == NULL) { if (oPtr->flags & USE_CLASS_CACHE) { if (oPtr->selfCls->classChainCache == NULL) { oPtr->selfCls->classChainCache = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitObjHashTable(oPtr->selfCls->classChainCache); } hPtr = Tcl_CreateHashEntry(oPtr->selfCls->classChainCache, (char *) methodNameObj, &i); } else { if (oPtr->chainCache == NULL) { oPtr->chainCache = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitObjHashTable(oPtr->chainCache); } hPtr = Tcl_CreateHashEntry(oPtr->chainCache, (char *) methodNameObj, &i); } } callPtr->refCount++; Tcl_SetHashValue(hPtr, callPtr); StashCallChain(cacheInThisObj, callPtr); } else if (flags & CONSTRUCTOR) { if (oPtr->selfCls->constructorChainPtr) { TclOODeleteChain(oPtr->selfCls->constructorChainPtr); } oPtr->selfCls->constructorChainPtr = callPtr; callPtr->refCount++; } else if ((flags & DESTRUCTOR) && oPtr->mixins.num == 0) { if (oPtr->selfCls->destructorChainPtr) { TclOODeleteChain(oPtr->selfCls->destructorChainPtr); } oPtr->selfCls->destructorChainPtr = callPtr; callPtr->refCount++; } returnContext: contextPtr = TclStackAlloc(oPtr->fPtr->interp, sizeof(CallContext)); contextPtr->oPtr = oPtr; AddRef(oPtr); contextPtr->callPtr = callPtr; contextPtr->skip = 2; contextPtr->index = 0; return contextPtr; } /* * ---------------------------------------------------------------------- * * TclOOGetStereotypeCallChain -- * * Construct a call-chain for a method that would be used by a * stereotypical instance of the given class (i.e., where the object has * no definitions special to itself). * * ---------------------------------------------------------------------- */ CallChain * TclOOGetStereotypeCallChain( Class *clsPtr, /* The object to get the context for. */ Tcl_Obj *methodNameObj, /* The name of the method to get the context * for. NULL when getting a constructor or * destructor chain. */ int flags) /* What sort of context are we looking for. * Only the bits PUBLIC_METHOD, CONSTRUCTOR, * PRIVATE_METHOD, DESTRUCTOR and * FILTER_HANDLING are useful. */ { CallChain *callPtr; struct ChainBuilder cb; int i, count; Foundation *fPtr = clsPtr->thisPtr->fPtr; Tcl_HashEntry *hPtr; Tcl_HashTable doneFilters; Object obj; /* * Synthesize a temporary stereotypical object so that we can use existing * machinery to produce the stereotypical call chain. */ memset(&obj, 0, sizeof(Object)); obj.fPtr = fPtr; obj.selfCls = clsPtr; obj.refCount = 1; obj.flags = USE_CLASS_CACHE; /* * Check if we can get the chain out of the Tcl_Obj method name or out of * the cache. This is made a bit more complex by the fact that there are * multiple different layers of cache (in the Tcl_Obj, in the object, and * in the class). */ if (clsPtr->classChainCache != NULL) { hPtr = Tcl_FindHashEntry(clsPtr->classChainCache, (char *) methodNameObj); if (hPtr != NULL && Tcl_GetHashValue(hPtr) != NULL) { const int reuseMask = ((flags & PUBLIC_METHOD) ? ~0 : ~PUBLIC_METHOD); callPtr = Tcl_GetHashValue(hPtr); if (IsStillValid(callPtr, &obj, flags, reuseMask)) { callPtr->refCount++; return callPtr; } Tcl_SetHashValue(hPtr, NULL); TclOODeleteChain(callPtr); } } else { hPtr = NULL; } callPtr = ckalloc(sizeof(CallChain)); memset(callPtr, 0, sizeof(CallChain)); callPtr->flags = flags & (PUBLIC_METHOD|PRIVATE_METHOD|FILTER_HANDLING); callPtr->epoch = fPtr->epoch; callPtr->objectCreationEpoch = fPtr->tsdPtr->nsCount; callPtr->objectEpoch = clsPtr->thisPtr->epoch; callPtr->refCount = 1; callPtr->chain = callPtr->staticChain; cb.callChainPtr = callPtr; cb.filterLength = 0; cb.oPtr = &obj; /* * Add all defined filters (if any, and if we're going to be processing * them; they're not processed for constructors, destructors or when we're * in the middle of processing a filter). */ Tcl_InitObjHashTable(&doneFilters); AddClassFiltersToCallContext(&obj, clsPtr, &cb, &doneFilters, BUILDING_MIXINS); AddClassFiltersToCallContext(&obj, clsPtr, &cb, &doneFilters, 0); Tcl_DeleteHashTable(&doneFilters); count = cb.filterLength = callPtr->numChain; /* * Add the actual method implementations. */ AddSimpleChainToCallContext(&obj, methodNameObj, &cb, NULL, flags|BUILDING_MIXINS, NULL); AddSimpleChainToCallContext(&obj, methodNameObj, &cb, NULL, flags, NULL); /* * Check to see if the method has no implementation. If so, we probably * need to add in a call to the unknown method. Otherwise, set up the * cacheing of the method implementation (if relevant). */ if (count == callPtr->numChain) { AddSimpleChainToCallContext(&obj, fPtr->unknownMethodNameObj, &cb, NULL, BUILDING_MIXINS, NULL); AddSimpleChainToCallContext(&obj, fPtr->unknownMethodNameObj, &cb, NULL, 0, NULL); callPtr->flags |= OO_UNKNOWN_METHOD; callPtr->epoch = -1; if (count == callPtr->numChain) { TclOODeleteChain(callPtr); return NULL; } } else { if (hPtr == NULL) { if (clsPtr->classChainCache == NULL) { clsPtr->classChainCache = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitObjHashTable(clsPtr->classChainCache); } hPtr = Tcl_CreateHashEntry(clsPtr->classChainCache, (char *) methodNameObj, &i); } callPtr->refCount++; Tcl_SetHashValue(hPtr, callPtr); StashCallChain(methodNameObj, callPtr); } return callPtr; } /* * ---------------------------------------------------------------------- * * AddClassFiltersToCallContext -- * * Logic to make extracting all the filters from the class context much * easier. * * ---------------------------------------------------------------------- */ static void AddClassFiltersToCallContext( Object *const oPtr, /* Object that the filters operate on. */ Class *clsPtr, /* Class to get the filters from. */ struct ChainBuilder *const cbPtr, /* Context to fill with call chain entries. */ Tcl_HashTable *const doneFilters, /* Where to record what filters have been * processed. Keys are objects, values are * ignored. */ int flags) /* Whether we've gone along a mixin link * yet. */ { int i, clearedFlags = flags & ~(TRAVERSED_MIXIN|OBJECT_MIXIN|BUILDING_MIXINS); Class *superPtr, *mixinPtr; Tcl_Obj *filterObj; tailRecurse: if (clsPtr == NULL) { return; } /* * Add all the filters defined by classes mixed into the main class * hierarchy. */ FOREACH(mixinPtr, clsPtr->mixins) { AddClassFiltersToCallContext(oPtr, mixinPtr, cbPtr, doneFilters, flags|TRAVERSED_MIXIN); } /* * Add all the class filters from the current class. Note that the filters * are added starting at the object root, as this allows the object to * override how filters work to extend their behaviour. */ if (MIXIN_CONSISTENT(flags)) { FOREACH(filterObj, clsPtr->filters) { int isNew; (void) Tcl_CreateHashEntry(doneFilters, (char *) filterObj, &isNew); if (isNew) { AddSimpleChainToCallContext(oPtr, filterObj, cbPtr, doneFilters, clearedFlags|BUILDING_MIXINS, clsPtr); AddSimpleChainToCallContext(oPtr, filterObj, cbPtr, doneFilters, clearedFlags, clsPtr); } } } /* * Now process the recursive case. Notice the tail-call optimization. */ switch (clsPtr->superclasses.num) { case 1: clsPtr = clsPtr->superclasses.list[0]; goto tailRecurse; default: FOREACH(superPtr, clsPtr->superclasses) { AddClassFiltersToCallContext(oPtr, superPtr, cbPtr, doneFilters, flags); } case 0: return; } } /* * ---------------------------------------------------------------------- * * AddSimpleClassChainToCallContext -- * * Construct a call-chain from a class hierarchy. * * ---------------------------------------------------------------------- */ static void AddSimpleClassChainToCallContext( Class *classPtr, /* Class to add the call chain entries for. */ Tcl_Obj *const methodNameObj, /* Name of method to add the call chain * entries for. */ struct ChainBuilder *const cbPtr, /* Where to add the call chain entries. */ Tcl_HashTable *const doneFilters, /* Where to record what call chain entries * have been processed. */ int flags, /* What sort of call chain are we building. */ Class *const filterDecl) /* The class that declared the filter. If * NULL, either the filter was declared by the * object or this isn't a filter. */ { int i; Class *superPtr; /* * We hard-code the tail-recursive form. It's by far the most common case * *and* it is much more gentle on the stack. * * Note that mixins must be processed before the main class hierarchy. * [Bug 1998221] */ tailRecurse: FOREACH(superPtr, classPtr->mixins) { AddSimpleClassChainToCallContext(superPtr, methodNameObj, cbPtr, doneFilters, flags|TRAVERSED_MIXIN, filterDecl); } if (flags & CONSTRUCTOR) { AddMethodToCallChain(classPtr->constructorPtr, cbPtr, doneFilters, filterDecl, flags); } else if (flags & DESTRUCTOR) { AddMethodToCallChain(classPtr->destructorPtr, cbPtr, doneFilters, filterDecl, flags); } else { Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&classPtr->classMethods, (char *) methodNameObj); if (hPtr != NULL) { register Method *mPtr = Tcl_GetHashValue(hPtr); if (!(flags & KNOWN_STATE)) { if (flags & PUBLIC_METHOD) { if (mPtr->flags & PUBLIC_METHOD) { flags |= DEFINITE_PUBLIC; } else { return; } } else { flags |= DEFINITE_PROTECTED; } } AddMethodToCallChain(mPtr, cbPtr, doneFilters, filterDecl, flags); } } switch (classPtr->superclasses.num) { case 1: classPtr = classPtr->superclasses.list[0]; goto tailRecurse; default: FOREACH(superPtr, classPtr->superclasses) { AddSimpleClassChainToCallContext(superPtr, methodNameObj, cbPtr, doneFilters, flags, filterDecl); } case 0: return; } } /* * ---------------------------------------------------------------------- * * TclOORenderCallChain -- * * Create a description of a call chain. Used in [info object call], * [info class call], and [self call]. * * ---------------------------------------------------------------------- */ Tcl_Obj * TclOORenderCallChain( Tcl_Interp *interp, CallChain *callPtr) { Tcl_Obj *filterLiteral, *methodLiteral, *objectLiteral; Tcl_Obj *resultObj, *descObjs[4], **objv; Foundation *fPtr = TclOOGetFoundation(interp); int i; /* * Allocate the literals (potentially) used in our description. */ filterLiteral = Tcl_NewStringObj("filter", -1); Tcl_IncrRefCount(filterLiteral); methodLiteral = Tcl_NewStringObj("method", -1); Tcl_IncrRefCount(methodLiteral); objectLiteral = Tcl_NewStringObj("object", -1); Tcl_IncrRefCount(objectLiteral); /* * Do the actual construction of the descriptions. They consist of a list * of triples that describe the details of how a method is understood. For * each triple, the first word is the type of invokation ("method" is * normal, "unknown" is special because it adds the method name as an * extra argument when handled by some method types, and "filter" is * special because it's a filter method). The second word is the name of * the method in question (which differs for "unknown" and "filter" types) * and the third word is the full name of the class that declares the * method (or "object" if it is declared on the instance). */ objv = TclStackAlloc(interp, callPtr->numChain * sizeof(Tcl_Obj *)); for (i=0 ; inumChain ; i++) { struct MInvoke *miPtr = &callPtr->chain[i]; descObjs[0] = miPtr->isFilter ? filterLiteral : callPtr->flags & OO_UNKNOWN_METHOD ? fPtr->unknownMethodNameObj : methodLiteral; descObjs[1] = callPtr->flags & CONSTRUCTOR ? fPtr->constructorName : callPtr->flags & DESTRUCTOR ? fPtr->destructorName : miPtr->mPtr->namePtr; descObjs[2] = miPtr->mPtr->declaringClassPtr ? Tcl_GetObjectName(interp, (Tcl_Object) miPtr->mPtr->declaringClassPtr->thisPtr) : objectLiteral; descObjs[3] = Tcl_NewStringObj(miPtr->mPtr->typePtr->name, -1); objv[i] = Tcl_NewListObj(4, descObjs); } /* * Drop the local references to the literals; if they're actually used, * they'll live on the description itself. */ Tcl_DecrRefCount(filterLiteral); Tcl_DecrRefCount(methodLiteral); Tcl_DecrRefCount(objectLiteral); /* * Finish building the description and return it. */ resultObj = Tcl_NewListObj(callPtr->numChain, objv); TclStackFree(interp, objv); return resultObj; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/regc_color.c0000644000175000017500000004501212663660065015467 0ustar sergeisergei/* * colorings of characters * This file is #included by regcomp.c. * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Note that there are some incestuous relationships between this code and NFA * arc maintenance, which perhaps ought to be cleaned up sometime. */ #define CISERR() VISERR(cm->v) #define CERR(e) VERR(cm->v, (e)) /* - initcm - set up new colormap ^ static void initcm(struct vars *, struct colormap *); */ static void initcm( struct vars *v, struct colormap *cm) { int i; int j; union tree *t; union tree *nextt; struct colordesc *cd; cm->magic = CMMAGIC; cm->v = v; cm->ncds = NINLINECDS; cm->cd = cm->cdspace; cm->max = 0; cm->free = 0; cd = cm->cd; /* cm->cd[WHITE] */ cd->sub = NOSUB; cd->arcs = NULL; cd->flags = 0; cd->nchrs = CHR_MAX - CHR_MIN + 1; /* * Upper levels of tree. */ for (t=&cm->tree[0], j=NBYTS-1 ; j>0 ; t=nextt, j--) { nextt = t + 1; for (i=BYTTAB-1 ; i>=0 ; i--) { t->tptr[i] = nextt; } } /* * Bottom level is solid white. */ t = &cm->tree[NBYTS-1]; for (i=BYTTAB-1 ; i>=0 ; i--) { t->tcolor[i] = WHITE; } cd->block = t; } /* - freecm - free dynamically-allocated things in a colormap ^ static void freecm(struct colormap *); */ static void freecm( struct colormap *cm) { size_t i; union tree *cb; cm->magic = 0; if (NBYTS > 1) { cmtreefree(cm, cm->tree, 0); } for (i=1 ; i<=cm->max ; i++) { /* skip WHITE */ if (!UNUSEDCOLOR(&cm->cd[i])) { cb = cm->cd[i].block; if (cb != NULL) { FREE(cb); } } } if (cm->cd != cm->cdspace) { FREE(cm->cd); } } /* - cmtreefree - free a non-terminal part of a colormap tree ^ static void cmtreefree(struct colormap *, union tree *, int); */ static void cmtreefree( struct colormap *cm, union tree *tree, int level) /* level number (top == 0) of this block */ { int i; union tree *t; union tree *fillt = &cm->tree[level+1]; union tree *cb; assert(level < NBYTS-1); /* this level has pointers */ for (i=BYTTAB-1 ; i>=0 ; i--) { t = tree->tptr[i]; assert(t != NULL); if (t != fillt) { if (level < NBYTS-2) { /* more pointer blocks below */ cmtreefree(cm, t, level+1); FREE(t); } else { /* color block below */ cb = cm->cd[t->tcolor[0]].block; if (t != cb) { /* not a solid block */ FREE(t); } } } } } /* - setcolor - set the color of a character in a colormap ^ static color setcolor(struct colormap *, pchr, pcolor); */ static color /* previous color */ setcolor( struct colormap *cm, pchr c, pcolor co) { uchr uc = c; int shift; int level; int b; int bottom; union tree *t; union tree *newt; union tree *fillt; union tree *lastt; union tree *cb; color prev; assert(cm->magic == CMMAGIC); if (CISERR() || co == COLORLESS) { return COLORLESS; } t = cm->tree; for (level=0, shift=BYTBITS*(NBYTS-1) ; shift>0; level++, shift-=BYTBITS){ b = (uc >> shift) & BYTMASK; lastt = t; t = lastt->tptr[b]; assert(t != NULL); fillt = &cm->tree[level+1]; bottom = (shift <= BYTBITS) ? 1 : 0; cb = (bottom) ? cm->cd[t->tcolor[0]].block : fillt; if (t == fillt || t == cb) { /* must allocate a new block */ newt = (union tree *) MALLOC((bottom) ? sizeof(struct colors) : sizeof(struct ptrs)); if (newt == NULL) { CERR(REG_ESPACE); return COLORLESS; } if (bottom) { memcpy(newt->tcolor, t->tcolor, BYTTAB*sizeof(color)); } else { memcpy(newt->tptr, t->tptr, BYTTAB*sizeof(union tree *)); } t = newt; lastt->tptr[b] = t; } } b = uc & BYTMASK; prev = t->tcolor[b]; t->tcolor[b] = (color) co; return prev; } /* - maxcolor - report largest color number in use ^ static color maxcolor(struct colormap *); */ static color maxcolor( struct colormap *cm) { if (CISERR()) { return COLORLESS; } return (color) cm->max; } /* - newcolor - find a new color (must be subject of setcolor at once) * Beware: may relocate the colordescs. ^ static color newcolor(struct colormap *); */ static color /* COLORLESS for error */ newcolor( struct colormap *cm) { struct colordesc *cd; size_t n; if (CISERR()) { return COLORLESS; } if (cm->free != 0) { assert(cm->free > 0); assert((size_t) cm->free < cm->ncds); cd = &cm->cd[cm->free]; assert(UNUSEDCOLOR(cd)); assert(cd->arcs == NULL); cm->free = cd->sub; } else if (cm->max < cm->ncds - 1) { cm->max++; cd = &cm->cd[cm->max]; } else { struct colordesc *newCd; /* * Oops, must allocate more. */ if (cm->max == MAX_COLOR) { CERR(REG_ECOLORS); return COLORLESS; /* too many colors */ } n = cm->ncds * 2; if (n > MAX_COLOR + 1) { n = MAX_COLOR + 1; } if (cm->cd == cm->cdspace) { newCd = (struct colordesc *) MALLOC(n * sizeof(struct colordesc)); if (newCd != NULL) { memcpy(newCd, cm->cdspace, cm->ncds * sizeof(struct colordesc)); } } else { newCd = (struct colordesc *) REALLOC(cm->cd, n * sizeof(struct colordesc)); } if (newCd == NULL) { CERR(REG_ESPACE); return COLORLESS; } cm->cd = newCd; cm->ncds = n; assert(cm->max < cm->ncds - 1); cm->max++; cd = &cm->cd[cm->max]; } cd->nchrs = 0; cd->sub = NOSUB; cd->arcs = NULL; cd->flags = 0; cd->block = NULL; return (color) (cd - cm->cd); } /* - freecolor - free a color (must have no arcs or subcolor) ^ static void freecolor(struct colormap *, pcolor); */ static void freecolor( struct colormap *cm, pcolor co) { struct colordesc *cd = &cm->cd[co]; color pco, nco; /* for freelist scan */ assert(co >= 0); if (co == WHITE) { return; } assert(cd->arcs == NULL); assert(cd->sub == NOSUB); assert(cd->nchrs == 0); cd->flags = FREECOL; if (cd->block != NULL) { FREE(cd->block); cd->block = NULL; /* just paranoia */ } if ((size_t) co == cm->max) { while (cm->max > WHITE && UNUSEDCOLOR(&cm->cd[cm->max])) { cm->max--; } assert(cm->free >= 0); while ((size_t) cm->free > cm->max) { cm->free = cm->cd[cm->free].sub; } if (cm->free > 0) { assert((size_t)cm->free < cm->max); pco = cm->free; nco = cm->cd[pco].sub; while (nco > 0) { if ((size_t) nco > cm->max) { /* * Take this one out of freelist. */ nco = cm->cd[nco].sub; cm->cd[pco].sub = nco; } else { assert((size_t)nco < cm->max); pco = nco; nco = cm->cd[pco].sub; } } } } else { cd->sub = cm->free; cm->free = (color) (cd - cm->cd); } } /* - pseudocolor - allocate a false color, to be managed by other means ^ static color pseudocolor(struct colormap *); */ static color pseudocolor( struct colormap *cm) { color co; co = newcolor(cm); if (CISERR()) { return COLORLESS; } cm->cd[co].nchrs = 1; cm->cd[co].flags = PSEUDO; return co; } /* - subcolor - allocate a new subcolor (if necessary) to this chr ^ static color subcolor(struct colormap *, pchr c); */ static color subcolor( struct colormap *cm, pchr c) { color co; /* current color of c */ color sco; /* new subcolor */ co = GETCOLOR(cm, c); sco = newsub(cm, co); if (CISERR()) { return COLORLESS; } assert(sco != COLORLESS); if (co == sco) { /* already in an open subcolor */ return co; /* rest is redundant */ } cm->cd[co].nchrs--; cm->cd[sco].nchrs++; setcolor(cm, c, sco); return sco; } /* - newsub - allocate a new subcolor (if necessary) for a color ^ static color newsub(struct colormap *, pcolor); */ static color newsub( struct colormap *cm, pcolor co) { color sco; /* new subcolor */ sco = cm->cd[co].sub; if (sco == NOSUB) { /* color has no open subcolor */ if (cm->cd[co].nchrs == 1) { /* optimization */ return co; } sco = newcolor(cm); /* must create subcolor */ if (sco == COLORLESS) { assert(CISERR()); return COLORLESS; } cm->cd[co].sub = sco; cm->cd[sco].sub = sco; /* open subcolor points to self */ } assert(sco != NOSUB); return sco; } /* - subrange - allocate new subcolors to this range of chrs, fill in arcs ^ static void subrange(struct vars *, pchr, pchr, struct state *, ^ struct state *); */ static void subrange( struct vars *v, pchr from, pchr to, struct state *lp, struct state *rp) { uchr uf; int i; assert(from <= to); /* * First, align "from" on a tree-block boundary */ uf = (uchr) from; i = (int) (((uf + BYTTAB - 1) & (uchr) ~BYTMASK) - uf); for (; from<=to && i>0; i--, from++) { newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp); } if (from > to) { /* didn't reach a boundary */ return; } /* * Deal with whole blocks. */ for (; to-from>=BYTTAB ; from+=BYTTAB) { subblock(v, from, lp, rp); } /* * Clean up any remaining partial table. */ for (; from<=to ; from++) { newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp); } } /* - subblock - allocate new subcolors for one tree block of chrs, fill in arcs ^ static void subblock(struct vars *, pchr, struct state *, struct state *); */ static void subblock( struct vars *v, pchr start, /* first of BYTTAB chrs */ struct state *lp, struct state *rp) { uchr uc = start; struct colormap *cm = v->cm; int shift; int level; int i; int b; union tree *t; union tree *cb; union tree *fillt; union tree *lastt; int previ; int ndone; color co; color sco; assert((uc % BYTTAB) == 0); /* * Find its color block, making new pointer blocks as needed. */ t = cm->tree; fillt = NULL; for (level=0, shift=BYTBITS*(NBYTS-1); shift>0; level++, shift-=BYTBITS) { b = (uc >> shift) & BYTMASK; lastt = t; t = lastt->tptr[b]; assert(t != NULL); fillt = &cm->tree[level+1]; if (t == fillt && shift > BYTBITS) { /* need new ptr block */ t = (union tree *) MALLOC(sizeof(struct ptrs)); if (t == NULL) { CERR(REG_ESPACE); return; } memcpy(t->tptr, fillt->tptr, BYTTAB*sizeof(union tree *)); lastt->tptr[b] = t; } } /* * Special cases: fill block or solid block. */ co = t->tcolor[0]; cb = cm->cd[co].block; if (t == fillt || t == cb) { /* * Either way, we want a subcolor solid block. */ sco = newsub(cm, co); t = cm->cd[sco].block; if (t == NULL) { /* must set it up */ t = (union tree *) MALLOC(sizeof(struct colors)); if (t == NULL) { CERR(REG_ESPACE); return; } for (i=0 ; itcolor[i] = sco; } cm->cd[sco].block = t; } /* * Find loop must have run at least once. */ lastt->tptr[b] = t; newarc(v->nfa, PLAIN, sco, lp, rp); cm->cd[co].nchrs -= BYTTAB; cm->cd[sco].nchrs += BYTTAB; return; } /* * General case, a mixed block to be altered. */ i = 0; while (i < BYTTAB) { co = t->tcolor[i]; sco = newsub(cm, co); newarc(v->nfa, PLAIN, sco, lp, rp); previ = i; do { t->tcolor[i++] = sco; } while (i < BYTTAB && t->tcolor[i] == co); ndone = i - previ; cm->cd[co].nchrs -= ndone; cm->cd[sco].nchrs += ndone; } } /* - okcolors - promote subcolors to full colors ^ static void okcolors(struct nfa *, struct colormap *); */ static void okcolors( struct nfa *nfa, struct colormap *cm) { struct colordesc *cd; struct colordesc *end = CDEND(cm); struct colordesc *scd; struct arc *a; color co; color sco; for (cd=cm->cd, co=0 ; cdsub; if (UNUSEDCOLOR(cd) || sco == NOSUB) { /* * Has no subcolor, no further action. */ } else if (sco == co) { /* * Is subcolor, let parent deal with it. */ } else if (cd->nchrs == 0) { /* * Parent empty, its arcs change color to subcolor. */ cd->sub = NOSUB; scd = &cm->cd[sco]; assert(scd->nchrs > 0); assert(scd->sub == sco); scd->sub = NOSUB; while ((a = cd->arcs) != NULL) { assert(a->co == co); uncolorchain(cm, a); a->co = sco; colorchain(cm, a); } freecolor(cm, co); } else { /* * Parent's arcs must gain parallel subcolor arcs. */ cd->sub = NOSUB; scd = &cm->cd[sco]; assert(scd->nchrs > 0); assert(scd->sub == sco); scd->sub = NOSUB; for (a=cd->arcs ; a!=NULL ; a=a->colorchain) { assert(a->co == co); newarc(nfa, a->type, sco, a->from, a->to); } } } } /* - colorchain - add this arc to the color chain of its color ^ static void colorchain(struct colormap *, struct arc *); */ static void colorchain( struct colormap *cm, struct arc *a) { struct colordesc *cd = &cm->cd[a->co]; if (cd->arcs != NULL) { cd->arcs->colorchainRev = a; } a->colorchain = cd->arcs; a->colorchainRev = NULL; cd->arcs = a; } /* - uncolorchain - delete this arc from the color chain of its color ^ static void uncolorchain(struct colormap *, struct arc *); */ static void uncolorchain( struct colormap *cm, struct arc *a) { struct colordesc *cd = &cm->cd[a->co]; struct arc *aa = a->colorchainRev; if (aa == NULL) { assert(cd->arcs == a); cd->arcs = a->colorchain; } else { assert(aa->colorchain == a); aa->colorchain = a->colorchain; } if (a->colorchain != NULL) { a->colorchain->colorchainRev = aa; } a->colorchain = NULL; /* paranoia */ a->colorchainRev = NULL; } /* - rainbow - add arcs of all full colors (but one) between specified states ^ static void rainbow(struct nfa *, struct colormap *, int, pcolor, ^ struct state *, struct state *); */ static void rainbow( struct nfa *nfa, struct colormap *cm, int type, pcolor but, /* COLORLESS if no exceptions */ struct state *from, struct state *to) { struct colordesc *cd; struct colordesc *end = CDEND(cm); color co; for (cd=cm->cd, co=0 ; cdsub != co) && (co != but) && !(cd->flags&PSEUDO)) { newarc(nfa, type, co, from, to); } } } /* - colorcomplement - add arcs of complementary colors * The calling sequence ought to be reconciled with cloneouts(). ^ static void colorcomplement(struct nfa *, struct colormap *, int, ^ struct state *, struct state *, struct state *); */ static void colorcomplement( struct nfa *nfa, struct colormap *cm, int type, struct state *of, /* complements of this guy's PLAIN outarcs */ struct state *from, struct state *to) { struct colordesc *cd; struct colordesc *end = CDEND(cm); color co; assert(of != from); for (cd=cm->cd, co=0 ; cdflags&PSEUDO)) { if (findarc(of, PLAIN, co) == NULL) { newarc(nfa, type, co, from, to); } } } } #ifdef REG_DEBUG /* ^ #ifdef REG_DEBUG */ /* - dumpcolors - debugging output ^ static void dumpcolors(struct colormap *, FILE *); */ static void dumpcolors( struct colormap *cm, FILE *f) { struct colordesc *cd; struct colordesc *end; color co; chr c; char *has; fprintf(f, "max %ld\n", (long) cm->max); if (NBYTS > 1) { fillcheck(cm, cm->tree, 0, f); } end = CDEND(cm); for (cd=cm->cd+1, co=1 ; cdnchrs > 0); has = (cd->block != NULL) ? "#" : ""; if (cd->flags&PSEUDO) { fprintf(f, "#%2ld%s(ps): ", (long) co, has); } else { fprintf(f, "#%2ld%s(%2d): ", (long) co, has, cd->nchrs); } /* * Unfortunately, it's hard to do this next bit more efficiently. * * Spencer's original coding has the loop iterating from CHR_MIN * to CHR_MAX, but that's utterly unusable for 32-bit chr, or * even 16-bit. For debugging purposes it seems fine to print * only chr codes up to 1000 or so. */ for (c=CHR_MIN ; c<1000 ; c++) { if (GETCOLOR(cm, c) == co) { dumpchr(c, f); } } fprintf(f, "\n"); } } } /* - fillcheck - check proper filling of a tree ^ static void fillcheck(struct colormap *, union tree *, int, FILE *); */ static void fillcheck( struct colormap *cm, union tree *tree, int level, /* level number (top == 0) of this block */ FILE *f) { int i; union tree *t; union tree *fillt = &cm->tree[level+1]; assert(level < NBYTS-1); /* this level has pointers */ for (i=BYTTAB-1 ; i>=0 ; i--) { t = tree->tptr[i]; if (t == NULL) { fprintf(f, "NULL found in filled tree!\n"); } else if (t == fillt) { /* empty body */ } else if (level < NBYTS-2) { /* more pointer blocks below */ fillcheck(cm, t, level+1, f); } } } /* - dumpchr - print a chr * Kind of char-centric but works well enough for debug use. ^ static void dumpchr(pchr, FILE *); */ static void dumpchr( pchr c, FILE *f) { if (c == '\\') { fprintf(f, "\\\\"); } else if (c > ' ' && c <= '~') { putc((char) c, f); } else { fprintf(f, "\\u%04lx", (long) c); } } /* ^ #endif */ #endif /* ifdef REG_DEBUG */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/regerrs.h0000644000175000017500000000225612663660065015032 0ustar sergeisergei{ REG_OKAY, "REG_OKAY", "no errors detected" }, { REG_NOMATCH, "REG_NOMATCH", "failed to match" }, { REG_BADPAT, "REG_BADPAT", "invalid regexp (reg version 0.8)" }, { REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element" }, { REG_ECTYPE, "REG_ECTYPE", "invalid character class" }, { REG_EESCAPE, "REG_EESCAPE", "invalid escape \\ sequence" }, { REG_ESUBREG, "REG_ESUBREG", "invalid backreference number" }, { REG_EBRACK, "REG_EBRACK", "brackets [] not balanced" }, { REG_EPAREN, "REG_EPAREN", "parentheses () not balanced" }, { REG_EBRACE, "REG_EBRACE", "braces {} not balanced" }, { REG_BADBR, "REG_BADBR", "invalid repetition count(s)" }, { REG_ERANGE, "REG_ERANGE", "invalid character range" }, { REG_ESPACE, "REG_ESPACE", "out of memory" }, { REG_BADRPT, "REG_BADRPT", "quantifier operand invalid" }, { REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug" }, { REG_INVARG, "REG_INVARG", "invalid argument to regex function" }, { REG_MIXED, "REG_MIXED", "character widths of regex and string differ" }, { REG_BADOPT, "REG_BADOPT", "invalid embedded option" }, { REG_ETOOBIG, "REG_ETOOBIG", "regular expression is too complex" }, { REG_ECOLORS, "REG_ECOLORS", "too many colors" }, tcl8.6.5/generic/regcustom.h0000644000175000017500000001136412663660065015371 0ustar sergeisergei/* * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms - with or without * modification - are permitted for any purpose, provided that redistributions * in source form retain this entire copyright notice and indicate the origin * and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Headers if any. */ #include "regex.h" /* * Overrides for regguts.h definitions, if any. */ #define FUNCPTR(name, args) (*name)args #define MALLOC(n) VS(attemptckalloc(n)) #define FREE(p) ckfree(VS(p)) #define REALLOC(p,n) VS(attemptckrealloc(VS(p),n)) /* * Do not insert extras between the "begin" and "end" lines - this chunk is * automatically extracted to be fitted into regex.h. */ /* --- begin --- */ /* Ensure certain things don't sneak in from system headers. */ #ifdef __REG_WIDE_T #undef __REG_WIDE_T #endif #ifdef __REG_WIDE_COMPILE #undef __REG_WIDE_COMPILE #endif #ifdef __REG_WIDE_EXEC #undef __REG_WIDE_EXEC #endif #ifdef __REG_REGOFF_T #undef __REG_REGOFF_T #endif #ifdef __REG_NOFRONT #undef __REG_NOFRONT #endif #ifdef __REG_NOCHAR #undef __REG_NOCHAR #endif /* Interface types */ #define __REG_WIDE_T Tcl_UniChar #define __REG_REGOFF_T long /* Not really right, but good enough... */ /* Names and declarations */ #define __REG_WIDE_COMPILE TclReComp #define __REG_WIDE_EXEC TclReExec #define __REG_NOFRONT /* Don't want regcomp() and regexec() */ #define __REG_NOCHAR /* Or the char versions */ #define regfree TclReFree #define regerror TclReError /* --- end --- */ /* * Internal character type and related. */ typedef Tcl_UniChar chr; /* The type itself. */ typedef int pchr; /* What it promotes to. */ typedef unsigned uchr; /* Unsigned type that will hold a chr. */ typedef int celt; /* Type to hold chr, or NOCELT */ #define NOCELT (-1) /* Celt value which is not valid chr */ #define CHR(c) (UCHAR(c)) /* Turn char literal into chr literal */ #define DIGITVAL(c) ((c)-'0') /* Turn chr digit into its value */ #if TCL_UTF_MAX > 4 #define CHRBITS 32 /* Bits in a chr; must not use sizeof */ #define CHR_MIN 0x00000000 /* Smallest and largest chr; the value */ #define CHR_MAX 0xffffffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */ #else #define CHRBITS 16 /* Bits in a chr; must not use sizeof */ #define CHR_MIN 0x0000 /* Smallest and largest chr; the value */ #define CHR_MAX 0xffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */ #endif /* * Functions operating on chr. */ #define iscalnum(x) Tcl_UniCharIsAlnum(x) #define iscalpha(x) Tcl_UniCharIsAlpha(x) #define iscdigit(x) Tcl_UniCharIsDigit(x) #define iscspace(x) Tcl_UniCharIsSpace(x) /* * Name the external functions. */ #define compile TclReComp #define exec TclReExec /* & Enable/disable debugging code (by whether REG_DEBUG is defined or not). */ #if 0 /* No debug unless requested by makefile. */ #define REG_DEBUG /* */ #endif /* * Method of allocating a local workspace. We used a thread-specific data * space to store this because the regular expression engine is never * reentered from the same thread; it doesn't make any callbacks. */ #if 1 #define AllocVars(vPtr) \ static Tcl_ThreadDataKey varsKey; \ register struct vars *vPtr = (struct vars *) \ Tcl_GetThreadData(&varsKey, sizeof(struct vars)) #else /* * This strategy for allocating workspace is "more proper" in some sense, but * quite a bit slower. Using TSD (as above) leads to code that is quite a bit * faster in practice (measured!) */ #define AllocVars(vPtr) \ register struct vars *vPtr = (struct vars *) MALLOC(sizeof(struct vars)) #define FreeVars(vPtr) \ FREE(vPtr) #endif /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclGet.c0000644000175000017500000000773012663660065014600 0ustar sergeisergei/* * tclGet.c -- * * This file contains functions to convert strings into other forms, like * integers or floating-point numbers or booleans, doing syntax checking * along the way. * * Copyright (c) 1990-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* *---------------------------------------------------------------------- * * Tcl_GetInt -- * * Given a string, produce the corresponding integer value. * * Results: * The return value is normally TCL_OK; in this case *intPtr will be set * to the integer value equivalent to src. If src is improperly formed * then TCL_ERROR is returned and an error message will be left in the * interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetInt( Tcl_Interp *interp, /* Interpreter to use for error reporting. */ const char *src, /* String containing a (possibly signed) * integer in a form acceptable to * Tcl_GetIntFromObj(). */ int *intPtr) /* Place to store converted result. */ { Tcl_Obj obj; int code; obj.refCount = 1; obj.bytes = (char *) src; obj.length = strlen(src); obj.typePtr = NULL; code = Tcl_GetIntFromObj(interp, &obj, intPtr); if (obj.refCount > 1) { Tcl_Panic("invalid sharing of Tcl_Obj on C stack"); } TclFreeIntRep(&obj); return code; } /* *---------------------------------------------------------------------- * * Tcl_GetDouble -- * * Given a string, produce the corresponding double-precision * floating-point value. * * Results: * The return value is normally TCL_OK; in this case *doublePtr will be * set to the double-precision value equivalent to src. If src is * improperly formed then TCL_ERROR is returned and an error message will * be left in the interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetDouble( Tcl_Interp *interp, /* Interpreter used for error reporting. */ const char *src, /* String containing a floating-point number * in a form acceptable to * Tcl_GetDoubleFromObj(). */ double *doublePtr) /* Place to store converted result. */ { Tcl_Obj obj; int code; obj.refCount = 1; obj.bytes = (char *) src; obj.length = strlen(src); obj.typePtr = NULL; code = Tcl_GetDoubleFromObj(interp, &obj, doublePtr); if (obj.refCount > 1) { Tcl_Panic("invalid sharing of Tcl_Obj on C stack"); } TclFreeIntRep(&obj); return code; } /* *---------------------------------------------------------------------- * * Tcl_GetBoolean -- * * Given a string, return a 0/1 boolean value corresponding to the * string. * * Results: * The return value is normally TCL_OK; in this case *boolPtr will be set * to the 0/1 value equivalent to src. If src is improperly formed then * TCL_ERROR is returned and an error message will be left in the * interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetBoolean( Tcl_Interp *interp, /* Interpreter used for error reporting. */ const char *src, /* String containing one of the boolean values * 1, 0, true, false, yes, no, on, off. */ int *boolPtr) /* Place to store converted result, which will * be 0 or 1. */ { Tcl_Obj obj; int code; obj.refCount = 1; obj.bytes = (char *) src; obj.length = strlen(src); obj.typePtr = NULL; code = TclSetBooleanFromAny(interp, &obj); if (obj.refCount > 1) { Tcl_Panic("invalid sharing of Tcl_Obj on C stack"); } if (code == TCL_OK) { *boolPtr = obj.internalRep.longValue; } return code; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclOptimize.c0000644000175000017500000002641212663660065015657 0ustar sergeisergei/* * tclOptimize.c -- * * This file contains the bytecode optimizer. * * Copyright (c) 2013 by Donal Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" #include /* * Forward declarations. */ static void AdvanceJumps(CompileEnv *envPtr); static void ConvertZeroEffectToNOP(CompileEnv *envPtr); static void LocateTargetAddresses(CompileEnv *envPtr, Tcl_HashTable *tablePtr); static void TrimUnreachable(CompileEnv *envPtr); /* * Helper macros. */ #define DefineTargetAddress(tablePtr, address) \ ((void) Tcl_CreateHashEntry((tablePtr), (void *) (address), &isNew)) #define IsTargetAddress(tablePtr, address) \ (Tcl_FindHashEntry((tablePtr), (void *) (address)) != NULL) #define AddrLength(address) \ (tclInstructionTable[*(unsigned char *)(address)].numBytes) #define InstLength(instruction) \ (tclInstructionTable[(unsigned char)(instruction)].numBytes) /* * ---------------------------------------------------------------------- * * LocateTargetAddresses -- * * Populate a hash table with places that we need to be careful around * because they're the targets of various kinds of jumps and other * non-local behavior. * * ---------------------------------------------------------------------- */ static void LocateTargetAddresses( CompileEnv *envPtr, Tcl_HashTable *tablePtr) { unsigned char *currentInstPtr, *targetInstPtr; int isNew, i; Tcl_HashEntry *hPtr; Tcl_HashSearch hSearch; Tcl_InitHashTable(tablePtr, TCL_ONE_WORD_KEYS); /* * The starts of commands represent target addresses. */ for (i=0 ; inumCommands ; i++) { DefineTargetAddress(tablePtr, envPtr->codeStart + envPtr->cmdMapPtr[i].codeOffset); } /* * Find places where we should be careful about replacing instructions * because they are the targets of various types of jumps. */ for (currentInstPtr = envPtr->codeStart ; currentInstPtr < envPtr->codeNext ; currentInstPtr += AddrLength(currentInstPtr)) { switch (*currentInstPtr) { case INST_JUMP1: case INST_JUMP_TRUE1: case INST_JUMP_FALSE1: targetInstPtr = currentInstPtr+TclGetInt1AtPtr(currentInstPtr+1); goto storeTarget; case INST_JUMP4: case INST_JUMP_TRUE4: case INST_JUMP_FALSE4: case INST_START_CMD: targetInstPtr = currentInstPtr+TclGetInt4AtPtr(currentInstPtr+1); goto storeTarget; case INST_BEGIN_CATCH4: targetInstPtr = envPtr->codeStart + envPtr->exceptArrayPtr[ TclGetUInt4AtPtr(currentInstPtr+1)].codeOffset; storeTarget: DefineTargetAddress(tablePtr, targetInstPtr); break; case INST_JUMP_TABLE: hPtr = Tcl_FirstHashEntry( &JUMPTABLEINFO(envPtr, currentInstPtr+1)->hashTable, &hSearch); for (; hPtr ; hPtr = Tcl_NextHashEntry(&hSearch)) { targetInstPtr = currentInstPtr + PTR2INT(Tcl_GetHashValue(hPtr)); DefineTargetAddress(tablePtr, targetInstPtr); } break; case INST_RETURN_CODE_BRANCH: for (i=TCL_ERROR ; iexceptArrayNext ; i++) { ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[i]; if (rangePtr->type == CATCH_EXCEPTION_RANGE) { targetInstPtr = envPtr->codeStart + rangePtr->catchOffset; DefineTargetAddress(tablePtr, targetInstPtr); } else { targetInstPtr = envPtr->codeStart + rangePtr->breakOffset; DefineTargetAddress(tablePtr, targetInstPtr); if (rangePtr->continueOffset >= 0) { targetInstPtr = envPtr->codeStart + rangePtr->continueOffset; DefineTargetAddress(tablePtr, targetInstPtr); } } } } /* * ---------------------------------------------------------------------- * * TrimUnreachable -- * * Converts code that provably can't be executed into NOPs and reduces * the overall reported length of the bytecode where that is possible. * * ---------------------------------------------------------------------- */ static void TrimUnreachable( CompileEnv *envPtr) { unsigned char *currentInstPtr; Tcl_HashTable targets; LocateTargetAddresses(envPtr, &targets); for (currentInstPtr = envPtr->codeStart ; currentInstPtr < envPtr->codeNext-1 ; currentInstPtr += AddrLength(currentInstPtr)) { int clear = 0; if (*currentInstPtr != INST_DONE) { continue; } while (!IsTargetAddress(&targets, currentInstPtr + 1 + clear)) { clear += AddrLength(currentInstPtr + 1 + clear); } if (currentInstPtr + 1 + clear == envPtr->codeNext) { envPtr->codeNext -= clear; } else { while (clear --> 0) { *(currentInstPtr + 1 + clear) = INST_NOP; } } } Tcl_DeleteHashTable(&targets); } /* * ---------------------------------------------------------------------- * * ConvertZeroEffectToNOP -- * * Replace PUSH/POP sequences (when non-hazardous) with NOPs. Also * replace PUSH empty/STR_CONCAT and TRY_CVT_NUMERIC (when followed by an * operation that guarantees the check for arithmeticity) and eliminate * LNOT when we can invert the following JUMP condition. * * ---------------------------------------------------------------------- */ static void ConvertZeroEffectToNOP( CompileEnv *envPtr) { unsigned char *currentInstPtr; int size; Tcl_HashTable targets; LocateTargetAddresses(envPtr, &targets); for (currentInstPtr = envPtr->codeStart ; currentInstPtr < envPtr->codeNext ; currentInstPtr += size) { int blank = 0, i, nextInst; size = AddrLength(currentInstPtr); while ((currentInstPtr + size < envPtr->codeNext) && *(currentInstPtr+size) == INST_NOP) { if (IsTargetAddress(&targets, currentInstPtr + size)) { break; } size += InstLength(INST_NOP); } if (IsTargetAddress(&targets, currentInstPtr + size)) { continue; } nextInst = *(currentInstPtr + size); switch (*currentInstPtr) { case INST_PUSH1: if (nextInst == INST_POP) { blank = size + InstLength(nextInst); } else if (nextInst == INST_STR_CONCAT1 && TclGetUInt1AtPtr(currentInstPtr + size + 1) == 2) { Tcl_Obj *litPtr = TclFetchLiteral(envPtr, TclGetUInt1AtPtr(currentInstPtr + 1)); int numBytes; (void) Tcl_GetStringFromObj(litPtr, &numBytes); if (numBytes == 0) { blank = size + InstLength(nextInst); } } break; case INST_PUSH4: if (nextInst == INST_POP) { blank = size + 1; } else if (nextInst == INST_STR_CONCAT1 && TclGetUInt1AtPtr(currentInstPtr + size + 1) == 2) { Tcl_Obj *litPtr = TclFetchLiteral(envPtr, TclGetUInt4AtPtr(currentInstPtr + 1)); int numBytes; (void) Tcl_GetStringFromObj(litPtr, &numBytes); if (numBytes == 0) { blank = size + InstLength(nextInst); } } break; case INST_LNOT: switch (nextInst) { case INST_JUMP_TRUE1: blank = size; *(currentInstPtr + size) = INST_JUMP_FALSE1; break; case INST_JUMP_FALSE1: blank = size; *(currentInstPtr + size) = INST_JUMP_TRUE1; break; case INST_JUMP_TRUE4: blank = size; *(currentInstPtr + size) = INST_JUMP_FALSE4; break; case INST_JUMP_FALSE4: blank = size; *(currentInstPtr + size) = INST_JUMP_TRUE4; break; } break; case INST_TRY_CVT_TO_NUMERIC: switch (nextInst) { case INST_JUMP_TRUE1: case INST_JUMP_TRUE4: case INST_JUMP_FALSE1: case INST_JUMP_FALSE4: case INST_INCR_SCALAR1: case INST_INCR_ARRAY1: case INST_INCR_ARRAY_STK: case INST_INCR_SCALAR_STK: case INST_INCR_STK: case INST_LOR: case INST_LAND: case INST_EQ: case INST_NEQ: case INST_LT: case INST_LE: case INST_GT: case INST_GE: case INST_MOD: case INST_LSHIFT: case INST_RSHIFT: case INST_BITOR: case INST_BITXOR: case INST_BITAND: case INST_EXPON: case INST_ADD: case INST_SUB: case INST_DIV: case INST_MULT: case INST_LNOT: case INST_BITNOT: case INST_UMINUS: case INST_UPLUS: case INST_TRY_CVT_TO_NUMERIC: blank = size; break; } break; } if (blank > 0) { for (i=0 ; icodeStart ; currentInstPtr < envPtr->codeNext-1 ; currentInstPtr += AddrLength(currentInstPtr)) { int offset, delta, isNew; switch (*currentInstPtr) { case INST_JUMP1: case INST_JUMP_TRUE1: case INST_JUMP_FALSE1: offset = TclGetInt1AtPtr(currentInstPtr + 1); Tcl_InitHashTable(&jumps, TCL_ONE_WORD_KEYS); for (delta=0 ; offset+delta != 0 ;) { if (offset + delta < -128 || offset + delta > 127) { break; } Tcl_CreateHashEntry(&jumps, INT2PTR(offset), &isNew); if (!isNew) { offset = TclGetInt1AtPtr(currentInstPtr + 1); break; } offset += delta; switch (*(currentInstPtr + offset)) { case INST_NOP: delta = InstLength(INST_NOP); continue; case INST_JUMP1: delta = TclGetInt1AtPtr(currentInstPtr + offset + 1); continue; case INST_JUMP4: delta = TclGetInt4AtPtr(currentInstPtr + offset + 1); continue; } break; } Tcl_DeleteHashTable(&jumps); TclStoreInt1AtPtr(offset, currentInstPtr + 1); continue; case INST_JUMP4: case INST_JUMP_TRUE4: case INST_JUMP_FALSE4: Tcl_InitHashTable(&jumps, TCL_ONE_WORD_KEYS); Tcl_CreateHashEntry(&jumps, INT2PTR(0), &isNew); for (offset = TclGetInt4AtPtr(currentInstPtr + 1); offset!=0 ;) { Tcl_CreateHashEntry(&jumps, INT2PTR(offset), &isNew); if (!isNew) { offset = TclGetInt4AtPtr(currentInstPtr + 1); break; } switch (*(currentInstPtr + offset)) { case INST_NOP: offset += InstLength(INST_NOP); continue; case INST_JUMP1: offset += TclGetInt1AtPtr(currentInstPtr + offset + 1); continue; case INST_JUMP4: offset += TclGetInt4AtPtr(currentInstPtr + offset + 1); continue; } break; } Tcl_DeleteHashTable(&jumps); TclStoreInt4AtPtr(offset, currentInstPtr + 1); continue; } } } /* * ---------------------------------------------------------------------- * * TclOptimizeBytecode -- * * A very simple peephole optimizer for bytecode. * * ---------------------------------------------------------------------- */ void TclOptimizeBytecode( void *envPtr) { ConvertZeroEffectToNOP(envPtr); AdvanceJumps(envPtr); TrimUnreachable(envPtr); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * End: */ tcl8.6.5/generic/regfronts.c0000644000175000017500000000470312663653131015360 0ustar sergeisergei/* * regcomp and regexec - front ends to re_ routines * * Mostly for implementation of backward-compatibility kludges. Note that * these routines exist ONLY in char versions. * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "regguts.h" /* - regcomp - compile regular expression */ int regcomp( regex_t *re, const char *str, int flags) { size_t len; int f = flags; if (f®_PEND) { len = re->re_endp - str; f &= ~REG_PEND; } else { len = strlen(str); } return re_comp(re, str, len, f); } /* - regexec - execute regular expression */ int regexec( regex_t *re, const char *str, size_t nmatch, regmatch_t pmatch[], int flags) { const char *start; size_t len; int f = flags; if (f & REG_STARTEND) { start = str + pmatch[0].rm_so; len = pmatch[0].rm_eo - pmatch[0].rm_so; f &= ~REG_STARTEND; } else { start = str; len = strlen(str); } return re_exec(re, start, len, nmatch, pmatch, f); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/regc_cvec.c0000644000175000017500000000765512663660065015304 0ustar sergeisergei/* * Utility functions for handling cvecs * This file is #included by regcomp.c. * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Notes: * Only (selected) functions in _this_ file should treat chr* as non-constant. */ /* - newcvec - allocate a new cvec ^ static struct cvec *newcvec(int, int); */ static struct cvec * newcvec( int nchrs, /* to hold this many chrs... */ int nranges) /* ... and this many ranges... */ { size_t nc = (size_t)nchrs + (size_t)nranges*2; size_t n = sizeof(struct cvec) + nc*sizeof(chr); struct cvec *cv = (struct cvec *) MALLOC(n); if (cv == NULL) { return NULL; } cv->chrspace = nchrs; cv->chrs = (chr *)(((char *)cv)+sizeof(struct cvec)); cv->ranges = cv->chrs + nchrs; cv->rangespace = nranges; return clearcvec(cv); } /* - clearcvec - clear a possibly-new cvec * Returns pointer as convenience. ^ static struct cvec *clearcvec(struct cvec *); */ static struct cvec * clearcvec( struct cvec *cv) /* character vector */ { assert(cv != NULL); cv->nchrs = 0; cv->nranges = 0; return cv; } /* - addchr - add a chr to a cvec ^ static void addchr(struct cvec *, pchr); */ static void addchr( struct cvec *cv, /* character vector */ pchr c) /* character to add */ { assert(cv->nchrs < cv->chrspace); cv->chrs[cv->nchrs++] = (chr)c; } /* - addrange - add a range to a cvec ^ static void addrange(struct cvec *, pchr, pchr); */ static void addrange( struct cvec *cv, /* character vector */ pchr from, /* first character of range */ pchr to) /* last character of range */ { assert(cv->nranges < cv->rangespace); cv->ranges[cv->nranges*2] = (chr)from; cv->ranges[cv->nranges*2 + 1] = (chr)to; cv->nranges++; } /* - getcvec - get a cvec, remembering it as v->cv ^ static struct cvec *getcvec(struct vars *, int, int); */ static struct cvec * getcvec( struct vars *v, /* context */ int nchrs, /* to hold this many chrs... */ int nranges) /* ... and this many ranges... */ { if ((v->cv != NULL) && (nchrs <= v->cv->chrspace) && (nranges <= v->cv->rangespace)) { return clearcvec(v->cv); } if (v->cv != NULL) { freecvec(v->cv); } v->cv = newcvec(nchrs, nranges); if (v->cv == NULL) { ERR(REG_ESPACE); } return v->cv; } /* - freecvec - free a cvec ^ static void freecvec(struct cvec *); */ static void freecvec( struct cvec *cv) /* character vector */ { FREE(cv); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclOODefineCmds.c0000644000175000017500000021576112663660065016325 0ustar sergeisergei/* * tclOODefineCmds.c -- * * This file contains the implementation of the ::oo::define command, * part of the object-system core (NB: not Tcl_Obj, but ::oo). * * Copyright (c) 2006-2013 by Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tclInt.h" #include "tclOOInt.h" /* * The maximum length of fully-qualified object name to use in an errorinfo * message. Longer than this will be curtailed. */ #define OBJNAME_LENGTH_IN_ERRORINFO_LIMIT 30 /* * Some things that make it easier to declare a slot. */ struct DeclaredSlot { const char *name; const Tcl_MethodType getterType; const Tcl_MethodType setterType; }; #define SLOT(name,getter,setter) \ {"::oo::" name, \ {TCL_OO_METHOD_VERSION_CURRENT, "core method: " name " Getter", \ getter, NULL, NULL}, \ {TCL_OO_METHOD_VERSION_CURRENT, "core method: " name " Setter", \ setter, NULL, NULL}} /* * Forward declarations. */ static inline void BumpGlobalEpoch(Tcl_Interp *interp, Class *classPtr); static Tcl_Command FindCommand(Tcl_Interp *interp, Tcl_Obj *stringObj, Tcl_Namespace *const namespacePtr); static void GenerateErrorInfo(Tcl_Interp *interp, Object *oPtr, Tcl_Obj *savedNameObj, const char *typeOfSubject); static inline Class * GetClassInOuterContext(Tcl_Interp *interp, Tcl_Obj *className, const char *errMsg); static inline int InitDefineContext(Tcl_Interp *interp, Tcl_Namespace *namespacePtr, Object *oPtr, int objc, Tcl_Obj *const objv[]); static inline void RecomputeClassCacheFlag(Object *oPtr); static int RenameDeleteMethod(Tcl_Interp *interp, Object *oPtr, int useClass, Tcl_Obj *const fromPtr, Tcl_Obj *const toPtr); static int ClassFilterGet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassFilterSet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassMixinGet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassMixinSet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassSuperGet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassSuperSet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassVarsGet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ClassVarsSet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ObjFilterGet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ObjFilterSet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ObjMixinGet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ObjMixinSet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ObjVarsGet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); static int ObjVarsSet(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); /* * Now define the slots used in declarations. */ static const struct DeclaredSlot slots[] = { SLOT("define::filter", ClassFilterGet, ClassFilterSet), SLOT("define::mixin", ClassMixinGet, ClassMixinSet), SLOT("define::superclass", ClassSuperGet, ClassSuperSet), SLOT("define::variable", ClassVarsGet, ClassVarsSet), SLOT("objdefine::filter", ObjFilterGet, ObjFilterSet), SLOT("objdefine::mixin", ObjMixinGet, ObjMixinSet), SLOT("objdefine::variable", ObjVarsGet, ObjVarsSet), {NULL, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}} }; /* * ---------------------------------------------------------------------- * * BumpGlobalEpoch -- * Utility that ensures that call chains that are invalid will get thrown * away at an appropriate time. Note that exactly which epoch gets * advanced will depend on exactly what the class is tangled up in; in * the worst case, the simplest option is to advance the global epoch, * causing *everything* to be thrown away on next usage. * * ---------------------------------------------------------------------- */ static inline void BumpGlobalEpoch( Tcl_Interp *interp, Class *classPtr) { if (classPtr != NULL && classPtr->subclasses.num == 0 && classPtr->instances.num == 0 && classPtr->mixinSubs.num == 0) { /* * If a class has no subclasses or instances, and is not mixed into * anything, a change to its structure does not require us to * invalidate any call chains. Note that we still bump our object's * epoch if it has any mixins; the relation between a class and its * representative object is special. But it won't hurt. */ if (classPtr->thisPtr->mixins.num > 0) { classPtr->thisPtr->epoch++; } return; } /* * Either there's no class (?!) or we're reconfiguring something that is * in use. Force regeneration of call chains. */ TclOOGetFoundation(interp)->epoch++; } /* * ---------------------------------------------------------------------- * * RecomputeClassCacheFlag -- * Determine whether the object is prototypical of its class, and hence * able to use the class's method chain cache. * * ---------------------------------------------------------------------- */ static inline void RecomputeClassCacheFlag( Object *oPtr) { if ((oPtr->methodsPtr == NULL || oPtr->methodsPtr->numEntries == 0) && (oPtr->mixins.num == 0) && (oPtr->filters.num == 0)) { oPtr->flags |= USE_CLASS_CACHE; } else { oPtr->flags &= ~USE_CLASS_CACHE; } } /* * ---------------------------------------------------------------------- * * TclOOObjectSetFilters -- * Install a list of filter method names into an object. * * ---------------------------------------------------------------------- */ void TclOOObjectSetFilters( Object *oPtr, int numFilters, Tcl_Obj *const *filters) { int i; if (oPtr->filters.num) { Tcl_Obj *filterObj; FOREACH(filterObj, oPtr->filters) { Tcl_DecrRefCount(filterObj); } } if (numFilters == 0) { /* * No list of filters was supplied, so we're deleting filters. */ ckfree(oPtr->filters.list); oPtr->filters.list = NULL; oPtr->filters.num = 0; RecomputeClassCacheFlag(oPtr); } else { /* * We've got a list of filters, so we're creating filters. */ Tcl_Obj **filtersList; int size = sizeof(Tcl_Obj *) * numFilters; /* should be size_t */ if (oPtr->filters.num == 0) { filtersList = ckalloc(size); } else { filtersList = ckrealloc(oPtr->filters.list, size); } for (i=0 ; ifilters.list = filtersList; oPtr->filters.num = numFilters; oPtr->flags &= ~USE_CLASS_CACHE; } oPtr->epoch++; /* Only this object can be affected. */ } /* * ---------------------------------------------------------------------- * * TclOOClassSetFilters -- * Install a list of filter method names into a class. * * ---------------------------------------------------------------------- */ void TclOOClassSetFilters( Tcl_Interp *interp, Class *classPtr, int numFilters, Tcl_Obj *const *filters) { int i; if (classPtr->filters.num) { Tcl_Obj *filterObj; FOREACH(filterObj, classPtr->filters) { Tcl_DecrRefCount(filterObj); } } if (numFilters == 0) { /* * No list of filters was supplied, so we're deleting filters. */ ckfree(classPtr->filters.list); classPtr->filters.list = NULL; classPtr->filters.num = 0; } else { /* * We've got a list of filters, so we're creating filters. */ Tcl_Obj **filtersList; int size = sizeof(Tcl_Obj *) * numFilters; /* should be size_t */ if (classPtr->filters.num == 0) { filtersList = ckalloc(size); } else { filtersList = ckrealloc(classPtr->filters.list, size); } for (i=0 ; ifilters.list = filtersList; classPtr->filters.num = numFilters; } /* * There may be many objects affected, so bump the global epoch. */ BumpGlobalEpoch(interp, classPtr); } /* * ---------------------------------------------------------------------- * * TclOOObjectSetMixins -- * Install a list of mixin classes into an object. * * ---------------------------------------------------------------------- */ void TclOOObjectSetMixins( Object *oPtr, int numMixins, Class *const *mixins) { Class *mixinPtr; int i; if (numMixins == 0) { if (oPtr->mixins.num != 0) { FOREACH(mixinPtr, oPtr->mixins) { if (mixinPtr) { TclOORemoveFromInstances(oPtr, mixinPtr); } } ckfree(oPtr->mixins.list); oPtr->mixins.num = 0; } RecomputeClassCacheFlag(oPtr); } else { if (oPtr->mixins.num != 0) { FOREACH(mixinPtr, oPtr->mixins) { if (mixinPtr && mixinPtr != oPtr->selfCls) { TclOORemoveFromInstances(oPtr, mixinPtr); } } oPtr->mixins.list = ckrealloc(oPtr->mixins.list, sizeof(Class *) * numMixins); } else { oPtr->mixins.list = ckalloc(sizeof(Class *) * numMixins); oPtr->flags &= ~USE_CLASS_CACHE; } oPtr->mixins.num = numMixins; memcpy(oPtr->mixins.list, mixins, sizeof(Class *) * numMixins); FOREACH(mixinPtr, oPtr->mixins) { if (mixinPtr != oPtr->selfCls) { TclOOAddToInstances(oPtr, mixinPtr); } } } oPtr->epoch++; } /* * ---------------------------------------------------------------------- * * TclOOClassSetMixins -- * Install a list of mixin classes into a class. * * ---------------------------------------------------------------------- */ void TclOOClassSetMixins( Tcl_Interp *interp, Class *classPtr, int numMixins, Class *const *mixins) { Class *mixinPtr; int i; if (numMixins == 0) { if (classPtr->mixins.num != 0) { FOREACH(mixinPtr, classPtr->mixins) { TclOORemoveFromMixinSubs(classPtr, mixinPtr); } ckfree(classPtr->mixins.list); classPtr->mixins.num = 0; } } else { if (classPtr->mixins.num != 0) { FOREACH(mixinPtr, classPtr->mixins) { TclOORemoveFromMixinSubs(classPtr, mixinPtr); } classPtr->mixins.list = ckrealloc(classPtr->mixins.list, sizeof(Class *) * numMixins); } else { classPtr->mixins.list = ckalloc(sizeof(Class *) * numMixins); } classPtr->mixins.num = numMixins; memcpy(classPtr->mixins.list, mixins, sizeof(Class *) * numMixins); FOREACH(mixinPtr, classPtr->mixins) { TclOOAddToMixinSubs(classPtr, mixinPtr); } } BumpGlobalEpoch(interp, classPtr); } /* * ---------------------------------------------------------------------- * * RenameDeleteMethod -- * Core of the code to rename and delete methods. * * ---------------------------------------------------------------------- */ static int RenameDeleteMethod( Tcl_Interp *interp, Object *oPtr, int useClass, Tcl_Obj *const fromPtr, Tcl_Obj *const toPtr) { Tcl_HashEntry *hPtr, *newHPtr = NULL; Method *mPtr; int isNew; if (!useClass) { if (!oPtr->methodsPtr) { noSuchMethod: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "method %s does not exist", TclGetString(fromPtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(fromPtr), NULL); return TCL_ERROR; } hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) fromPtr); if (hPtr == NULL) { goto noSuchMethod; } if (toPtr) { newHPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *) toPtr, &isNew); if (hPtr == newHPtr) { renameToSelf: Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot rename method to itself", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_TO_SELF", NULL); return TCL_ERROR; } else if (!isNew) { renameToExisting: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "method called %s already exists", TclGetString(toPtr))); Tcl_SetErrorCode(interp, "TCL", "OO", "RENAME_OVER", NULL); return TCL_ERROR; } } } else { hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods, (char *) fromPtr); if (hPtr == NULL) { goto noSuchMethod; } if (toPtr) { newHPtr = Tcl_CreateHashEntry(&oPtr->classPtr->classMethods, (char *) toPtr, &isNew); if (hPtr == newHPtr) { goto renameToSelf; } else if (!isNew) { goto renameToExisting; } } } /* * Complete the splicing by changing the method's name. */ mPtr = Tcl_GetHashValue(hPtr); if (toPtr) { Tcl_IncrRefCount(toPtr); Tcl_DecrRefCount(mPtr->namePtr); mPtr->namePtr = toPtr; Tcl_SetHashValue(newHPtr, mPtr); } else { if (!useClass) { RecomputeClassCacheFlag(oPtr); } TclOODelMethodRef(mPtr); } Tcl_DeleteHashEntry(hPtr); return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOOUnknownDefinition -- * Handles what happens when an unknown command is encountered during the * processing of a definition script. Works by finding a command in the * operating definition namespace that the requested command is a unique * prefix of. * * ---------------------------------------------------------------------- */ int TclOOUnknownDefinition( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Namespace *nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); Tcl_HashSearch search; Tcl_HashEntry *hPtr; int soughtLen; const char *soughtStr, *matchedStr = NULL; if (objc < 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad call of unknown handler", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_UNKNOWN", NULL); return TCL_ERROR; } if (TclOOGetDefineCmdContext(interp) == NULL) { return TCL_ERROR; } soughtStr = Tcl_GetStringFromObj(objv[1], &soughtLen); if (soughtLen == 0) { goto noMatch; } hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); while (hPtr != NULL) { const char *nameStr = Tcl_GetHashKey(&nsPtr->cmdTable, hPtr); if (strncmp(soughtStr, nameStr, soughtLen) == 0) { if (matchedStr != NULL) { goto noMatch; } matchedStr = nameStr; } hPtr = Tcl_NextHashEntry(&search); } if (matchedStr != NULL) { /* * Got one match, and only one match! */ Tcl_Obj **newObjv = TclStackAlloc(interp, sizeof(Tcl_Obj*)*(objc-1)); int result; newObjv[0] = Tcl_NewStringObj(matchedStr, -1); Tcl_IncrRefCount(newObjv[0]); if (objc > 2) { memcpy(newObjv+1, objv+2, sizeof(Tcl_Obj *) * (objc-2)); } result = Tcl_EvalObjv(interp, objc-1, newObjv, 0); Tcl_DecrRefCount(newObjv[0]); TclStackFree(interp, newObjv); return result; } noMatch: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid command name \"%s\"", soughtStr)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", soughtStr, NULL); return TCL_ERROR; } /* * ---------------------------------------------------------------------- * * FindCommand -- * Specialized version of Tcl_FindCommand that handles command prefixes * and disallows namespace magic. * * ---------------------------------------------------------------------- */ static Tcl_Command FindCommand( Tcl_Interp *interp, Tcl_Obj *stringObj, Tcl_Namespace *const namespacePtr) { int length; const char *nameStr, *string = Tcl_GetStringFromObj(stringObj, &length); register Namespace *const nsPtr = (Namespace *) namespacePtr; FOREACH_HASH_DECLS; Tcl_Command cmd, cmd2; /* * If someone is playing games, we stop playing right now. */ if (string[0] == '\0' || strstr(string, "::") != NULL) { return NULL; } /* * Do the exact lookup first. */ cmd = Tcl_FindCommand(interp, string, namespacePtr, TCL_NAMESPACE_ONLY); if (cmd != NULL) { return cmd; } /* * Bother, need to perform an approximate match. Iterate across the hash * table of commands in the namespace. */ FOREACH_HASH(nameStr, cmd2, &nsPtr->cmdTable) { if (strncmp(string, nameStr, length) == 0) { if (cmd != NULL) { return NULL; } cmd = cmd2; } } /* * Either we found one thing or we found nothing. Either way, return it. */ return cmd; } /* * ---------------------------------------------------------------------- * * InitDefineContext -- * Does the magic incantations necessary to push the special stack frame * used when processing object definitions. It is up to the caller to * dispose of the frame (with TclPopStackFrame) when finished. * * ---------------------------------------------------------------------- */ static inline int InitDefineContext( Tcl_Interp *interp, Tcl_Namespace *namespacePtr, Object *oPtr, int objc, Tcl_Obj *const objv[]) { CallFrame *framePtr, **framePtrPtr = &framePtr; if (namespacePtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot process definitions; support namespace deleted", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } /* framePtrPtr is needed to satisfy GCC 3.3's strict aliasing rules */ (void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr, namespacePtr, FRAME_IS_OO_DEFINE); framePtr->clientData = oPtr; framePtr->objc = objc; framePtr->objv = objv; /* Reference counts do not need to be * incremented here. */ return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOOGetDefineCmdContext -- * Extracts the magic token from the current stack frame, or returns NULL * (and leaves an error message) otherwise. * * ---------------------------------------------------------------------- */ Tcl_Object TclOOGetDefineCmdContext( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; Tcl_Object object; if ((iPtr->varFramePtr == NULL) || (iPtr->varFramePtr->isProcCallFrame != FRAME_IS_OO_DEFINE)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "this command may only be called from within the context of" " an ::oo::define or ::oo::objdefine command", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return NULL; } object = iPtr->varFramePtr->clientData; if (Tcl_ObjectDeleted(object)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "this command cannot be called when the object has been" " deleted", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return NULL; } return object; } /* * ---------------------------------------------------------------------- * * GetClassInOuterContext -- * Wrapper round Tcl_GetObjectFromObj to perform the lookup in the * context that called oo::define (or equivalent). Note that this may * have to go up multiple levels to get the level that we started doing * definitions at. * * ---------------------------------------------------------------------- */ static inline Class * GetClassInOuterContext( Tcl_Interp *interp, Tcl_Obj *className, const char *errMsg) { Interp *iPtr = (Interp *) interp; Object *oPtr; CallFrame *savedFramePtr = iPtr->varFramePtr; while (iPtr->varFramePtr->isProcCallFrame == FRAME_IS_OO_DEFINE) { if (iPtr->varFramePtr->callerVarPtr == NULL) { Tcl_Panic("getting outer context when already in global context"); } iPtr->varFramePtr = iPtr->varFramePtr->callerVarPtr; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, className); iPtr->varFramePtr = savedFramePtr; if (oPtr == NULL) { return NULL; } if (oPtr->classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS", TclGetString(className), NULL); return NULL; } return oPtr->classPtr; } /* * ---------------------------------------------------------------------- * * GenerateErrorInfo -- * Factored out code to generate part of the error trace messages. * * ---------------------------------------------------------------------- */ static void GenerateErrorInfo( Tcl_Interp *interp, /* Where to store the error info trace. */ Object *oPtr, /* What object (or class) was being configured * when the error occurred? */ Tcl_Obj *savedNameObj, /* Name of object saved from before script was * evaluated, which is needed if the object * goes away part way through execution. OTOH, * if the object isn't deleted then its * current name (post-execution) has to be * used. This matters, because the object * could have been renamed... */ const char *typeOfSubject) /* Part of the message, saying whether it was * an object, class or class-as-object that * was being configured. */ { int length; Tcl_Obj *realNameObj = Tcl_ObjectDeleted((Tcl_Object) oPtr) ? savedNameObj : TclOOObjectName(interp, oPtr); const char *objName = Tcl_GetStringFromObj(realNameObj, &length); int limit = OBJNAME_LENGTH_IN_ERRORINFO_LIMIT; int overflow = (length > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (in definition script for %s \"%.*s%s\" line %d)", typeOfSubject, (overflow ? limit : length), objName, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } /* * ---------------------------------------------------------------------- * * TclOODefineObjCmd -- * Implementation of the "oo::define" command. Works by effectively doing * the same as 'namespace eval', but with extra magic applied so that the * object to be modified is known to the commands in the target * namespace. Also does ensemble-like tricks with dispatch so that error * messages are clearer. * * ---------------------------------------------------------------------- */ int TclOODefineObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Foundation *fPtr = TclOOGetFoundation(interp); int result; Object *oPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "className arg ?arg ...?"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } if (oPtr->classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s does not refer to a class",TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS", TclGetString(objv[1]), NULL); return TCL_ERROR; } /* * Make the oo::define namespace the current namespace and evaluate the * command(s). */ if (InitDefineContext(interp, fPtr->defineNs, oPtr, objc,objv) != TCL_OK){ return TCL_ERROR; } AddRef(oPtr); if (objc == 3) { Tcl_Obj *objNameObj = TclOOObjectName(interp, oPtr); Tcl_IncrRefCount(objNameObj); result = TclEvalObjEx(interp, objv[2], 0, ((Interp *)interp)->cmdFramePtr, 2); if (result == TCL_ERROR) { GenerateErrorInfo(interp, oPtr, objNameObj, "class"); } TclDecrRefCount(objNameObj); } else { Tcl_Obj *objPtr, *obj2Ptr, **objs; Interp *iPtr = (Interp *) interp; Tcl_Command cmd; int dummy; /* * More than one argument: fire them through the ensemble processing * engine so that everything appears to be good and proper in error * messages. Note that we cannot just concatenate and send through * Tcl_EvalObjEx, as that doesn't do ensemble processing, and we * cannot go through Tcl_EvalObjv without the extra work to pre-find * the command, as that finds command names in the wrong namespace at * the moment. Ugly! */ if (iPtr->ensembleRewrite.sourceObjs == NULL) { iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = 3; iPtr->ensembleRewrite.numInsertedObjs = 1; } else { int ni = iPtr->ensembleRewrite.numInsertedObjs; if (ni < 3) { iPtr->ensembleRewrite.numRemovedObjs += 3 - ni; } else { iPtr->ensembleRewrite.numInsertedObjs -= 2; } } /* * Build the list of arguments using a Tcl_Obj as a workspace. See * comments above for why these contortions are necessary. */ objPtr = Tcl_NewObj(); obj2Ptr = Tcl_NewObj(); cmd = FindCommand(interp, objv[2], fPtr->defineNs); if (cmd == NULL) { /* punt this case! */ Tcl_AppendObjToObj(obj2Ptr, objv[2]); } else { Tcl_GetCommandFullName(interp, cmd, obj2Ptr); } Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr); /* TODO: overflow? */ Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc-3, objv+3); Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs); result = Tcl_EvalObjv(interp, objc-2, objs, TCL_EVAL_INVOKE); Tcl_DecrRefCount(objPtr); } DelRef(oPtr); /* * Restore the previous "current" namespace. */ TclPopStackFrame(interp); return result; } /* * ---------------------------------------------------------------------- * * TclOOObjDefObjCmd -- * Implementation of the "oo::objdefine" command. Works by effectively * doing the same as 'namespace eval', but with extra magic applied so * that the object to be modified is known to the commands in the target * namespace. Also does ensemble-like tricks with dispatch so that error * messages are clearer. * * ---------------------------------------------------------------------- */ int TclOOObjDefObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Foundation *fPtr = TclOOGetFoundation(interp); int result; Object *oPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "objectName arg ?arg ...?"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } /* * Make the oo::objdefine namespace the current namespace and evaluate the * command(s). */ if (InitDefineContext(interp, fPtr->objdefNs, oPtr, objc,objv) != TCL_OK){ return TCL_ERROR; } AddRef(oPtr); if (objc == 3) { Tcl_Obj *objNameObj = TclOOObjectName(interp, oPtr); Tcl_IncrRefCount(objNameObj); result = TclEvalObjEx(interp, objv[2], 0, ((Interp *)interp)->cmdFramePtr, 2); if (result == TCL_ERROR) { GenerateErrorInfo(interp, oPtr, objNameObj, "object"); } TclDecrRefCount(objNameObj); } else { Tcl_Obj *objPtr, *obj2Ptr, **objs; Interp *iPtr = (Interp *) interp; Tcl_Command cmd; int dummy; /* * More than one argument: fire them through the ensemble processing * engine so that everything appears to be good and proper in error * messages. Note that we cannot just concatenate and send through * Tcl_EvalObjEx, as that doesn't do ensemble processing, and we * cannot go through Tcl_EvalObjv without the extra work to pre-find * the command, as that finds command names in the wrong namespace at * the moment. Ugly! */ if (iPtr->ensembleRewrite.sourceObjs == NULL) { iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = 3; iPtr->ensembleRewrite.numInsertedObjs = 1; } else { int ni = iPtr->ensembleRewrite.numInsertedObjs; if (ni < 3) { iPtr->ensembleRewrite.numRemovedObjs += 3 - ni; } else { iPtr->ensembleRewrite.numInsertedObjs -= 2; } } /* * Build the list of arguments using a Tcl_Obj as a workspace. See * comments above for why these contortions are necessary. */ objPtr = Tcl_NewObj(); obj2Ptr = Tcl_NewObj(); cmd = FindCommand(interp, objv[2], fPtr->objdefNs); if (cmd == NULL) { /* punt this case! */ Tcl_AppendObjToObj(obj2Ptr, objv[2]); } else { Tcl_GetCommandFullName(interp, cmd, obj2Ptr); } Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr); /* TODO: overflow? */ Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc-3, objv+3); Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs); result = Tcl_EvalObjv(interp, objc-2, objs, TCL_EVAL_INVOKE); Tcl_DecrRefCount(objPtr); } DelRef(oPtr); /* * Restore the previous "current" namespace. */ TclPopStackFrame(interp); return result; } /* * ---------------------------------------------------------------------- * * TclOODefineSelfObjCmd -- * Implementation of the "self" subcommand of the "oo::define" command. * Works by effectively doing the same as 'namespace eval', but with * extra magic applied so that the object to be modified is known to the * commands in the target namespace. Also does ensemble-like tricks with * dispatch so that error messages are clearer. * * ---------------------------------------------------------------------- */ int TclOODefineSelfObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Foundation *fPtr = TclOOGetFoundation(interp); int result; Object *oPtr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "arg ?arg ...?"); return TCL_ERROR; } oPtr = (Object *) TclOOGetDefineCmdContext(interp); if (oPtr == NULL) { return TCL_ERROR; } /* * Make the oo::objdefine namespace the current namespace and evaluate the * command(s). */ if (InitDefineContext(interp, fPtr->objdefNs, oPtr, objc,objv) != TCL_OK){ return TCL_ERROR; } AddRef(oPtr); if (objc == 2) { Tcl_Obj *objNameObj = TclOOObjectName(interp, oPtr); Tcl_IncrRefCount(objNameObj); result = TclEvalObjEx(interp, objv[1], 0, ((Interp *)interp)->cmdFramePtr, 2); if (result == TCL_ERROR) { GenerateErrorInfo(interp, oPtr, objNameObj, "class object"); } TclDecrRefCount(objNameObj); } else { Tcl_Obj *objPtr, *obj2Ptr, **objs; Interp *iPtr = (Interp *) interp; Tcl_Command cmd; int dummy; /* * More than one argument: fire them through the ensemble processing * engine so that everything appears to be good and proper in error * messages. Note that we cannot just concatenate and send through * Tcl_EvalObjEx, as that doesn't do ensemble processing, and we * cannot go through Tcl_EvalObjv without the extra work to pre-find * the command, as that finds command names in the wrong namespace at * the moment. Ugly! */ if (iPtr->ensembleRewrite.sourceObjs == NULL) { iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = 2; iPtr->ensembleRewrite.numInsertedObjs = 1; } else { int ni = iPtr->ensembleRewrite.numInsertedObjs; if (ni < 2) { iPtr->ensembleRewrite.numRemovedObjs += 2 - ni; } else { iPtr->ensembleRewrite.numInsertedObjs -= 1; } } /* * Build the list of arguments using a Tcl_Obj as a workspace. See * comments above for why these contortions are necessary. */ objPtr = Tcl_NewObj(); obj2Ptr = Tcl_NewObj(); cmd = FindCommand(interp, objv[1], fPtr->objdefNs); if (cmd == NULL) { /* punt this case! */ Tcl_AppendObjToObj(obj2Ptr, objv[1]); } else { Tcl_GetCommandFullName(interp, cmd, obj2Ptr); } Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr); /* TODO: overflow? */ Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc-2, objv+2); Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs); result = Tcl_EvalObjv(interp, objc-1, objs, TCL_EVAL_INVOKE); Tcl_DecrRefCount(objPtr); } DelRef(oPtr); /* * Restore the previous "current" namespace. */ TclPopStackFrame(interp); return result; } /* * ---------------------------------------------------------------------- * * TclOODefineClassObjCmd -- * Implementation of the "class" subcommand of the "oo::objdefine" * command. * * ---------------------------------------------------------------------- */ int TclOODefineClassObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Object *oPtr; Class *clsPtr; Foundation *fPtr = TclOOGetFoundation(interp); /* * Parse the context to get the object to operate on. */ oPtr = (Object *) TclOOGetDefineCmdContext(interp); if (oPtr == NULL) { return TCL_ERROR; } if (oPtr->flags & ROOT_OBJECT) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may not modify the class of the root object class", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } if (oPtr->flags & ROOT_CLASS) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may not modify the class of the class of classes", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } /* * Parse the argument to get the class to set the object's class to. */ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "className"); return TCL_ERROR; } clsPtr = GetClassInOuterContext(interp, objv[1], "the class of an object must be a class"); if (clsPtr == NULL) { return TCL_ERROR; } /* * Apply semantic checks. In particular, classes and non-classes are not * interchangable (too complicated to do the conversion!) so we must * produce an error if any attempt is made to swap from one to the other. */ if ((oPtr->classPtr==NULL) == TclOOIsReachable(fPtr->classCls, clsPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "may not change a %sclass object into a %sclass object", (oPtr->classPtr==NULL ? "non-" : ""), (oPtr->classPtr==NULL ? "" : "non-"))); Tcl_SetErrorCode(interp, "TCL", "OO", "TRANSMUTATION", NULL); return TCL_ERROR; } /* * Set the object's class. */ if (oPtr->selfCls != clsPtr) { TclOORemoveFromInstances(oPtr, oPtr->selfCls); oPtr->selfCls = clsPtr; TclOOAddToInstances(oPtr, oPtr->selfCls); if (!(clsPtr->thisPtr->flags & OBJECT_DELETED)) { oPtr->flags &= ~CLASS_GONE; } if (oPtr->classPtr != NULL) { BumpGlobalEpoch(interp, oPtr->classPtr); } else { oPtr->epoch++; } } return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOODefineConstructorObjCmd -- * Implementation of the "constructor" subcommand of the "oo::define" * command. * * ---------------------------------------------------------------------- */ int TclOODefineConstructorObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Object *oPtr; Class *clsPtr; Tcl_Method method; int bodyLength; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arguments body"); return TCL_ERROR; } /* * Extract and validate the context, which is the class that we wish to * modify. */ oPtr = (Object *) TclOOGetDefineCmdContext(interp); if (oPtr == NULL) { return TCL_ERROR; } clsPtr = oPtr->classPtr; Tcl_GetStringFromObj(objv[2], &bodyLength); if (bodyLength > 0) { /* * Create the method structure. */ method = (Tcl_Method) TclOONewProcMethod(interp, clsPtr, PUBLIC_METHOD, NULL, objv[1], objv[2], NULL); if (method == NULL) { return TCL_ERROR; } } else { /* * Delete the constructor method record and set the field in the * class record to NULL. */ method = NULL; } /* * Place the method structure in the class record. Note that we might not * immediately delete the constructor as this might be being done during * execution of the constructor itself. */ Tcl_ClassSetConstructor(interp, (Tcl_Class) clsPtr, method); return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOODefineDeleteMethodObjCmd -- * Implementation of the "deletemethod" subcommand of the "oo::define" * and "oo::objdefine" commands. * * ---------------------------------------------------------------------- */ int TclOODefineDeleteMethodObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstanceDeleteMethod = (clientData != NULL); Object *oPtr; int i; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "name ?name ...?"); return TCL_ERROR; } oPtr = (Object *) TclOOGetDefineCmdContext(interp); if (oPtr == NULL) { return TCL_ERROR; } if (!isInstanceDeleteMethod && !oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } for (i=1 ; iepoch++; } else { BumpGlobalEpoch(interp, oPtr->classPtr); } return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOODefineDestructorObjCmd -- * Implementation of the "destructor" subcommand of the "oo::define" * command. * * ---------------------------------------------------------------------- */ int TclOODefineDestructorObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Object *oPtr; Class *clsPtr; Tcl_Method method; int bodyLength; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "body"); return TCL_ERROR; } oPtr = (Object *) TclOOGetDefineCmdContext(interp); if (oPtr == NULL) { return TCL_ERROR; } clsPtr = oPtr->classPtr; Tcl_GetStringFromObj(objv[1], &bodyLength); if (bodyLength > 0) { /* * Create the method structure. */ method = (Tcl_Method) TclOONewProcMethod(interp, clsPtr, PUBLIC_METHOD, NULL, NULL, objv[1], NULL); if (method == NULL) { return TCL_ERROR; } } else { /* * Delete the destructor method record and set the field in the class * record to NULL. */ method = NULL; } /* * Place the method structure in the class record. Note that we might not * immediately delete the destructor as this might be being done during * execution of the destructor itself. Also note that setting a * destructor during a destructor is fairly dumb anyway. */ Tcl_ClassSetDestructor(interp, (Tcl_Class) clsPtr, method); return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOODefineExportObjCmd -- * Implementation of the "export" subcommand of the "oo::define" and * "oo::objdefine" commands. * * ---------------------------------------------------------------------- */ int TclOODefineExportObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstanceExport = (clientData != NULL); Object *oPtr; Method *mPtr; Tcl_HashEntry *hPtr; Class *clsPtr; int i, isNew, changed = 0; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "name ?name ...?"); return TCL_ERROR; } oPtr = (Object *) TclOOGetDefineCmdContext(interp); if (oPtr == NULL) { return TCL_ERROR; } clsPtr = oPtr->classPtr; if (!isInstanceExport && !clsPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } for (i=1 ; imethodsPtr) { oPtr->methodsPtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitObjHashTable(oPtr->methodsPtr); oPtr->flags &= ~USE_CLASS_CACHE; } hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *) objv[i], &isNew); } else { hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char*) objv[i], &isNew); } if (isNew) { mPtr = ckalloc(sizeof(Method)); memset(mPtr, 0, sizeof(Method)); mPtr->refCount = 1; mPtr->namePtr = objv[i]; Tcl_IncrRefCount(objv[i]); Tcl_SetHashValue(hPtr, mPtr); } else { mPtr = Tcl_GetHashValue(hPtr); } if (isNew || !(mPtr->flags & PUBLIC_METHOD)) { mPtr->flags |= PUBLIC_METHOD; changed = 1; } } /* * Bump the right epoch if we actually changed anything. */ if (changed) { if (isInstanceExport) { oPtr->epoch++; } else { BumpGlobalEpoch(interp, clsPtr); } } return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOODefineForwardObjCmd -- * Implementation of the "forward" subcommand of the "oo::define" and * "oo::objdefine" commands. * * ---------------------------------------------------------------------- */ int TclOODefineForwardObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstanceForward = (clientData != NULL); Object *oPtr; Method *mPtr; int isPublic; Tcl_Obj *prefixObj; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "name cmdName ?arg ...?"); return TCL_ERROR; } oPtr = (Object *) TclOOGetDefineCmdContext(interp); if (oPtr == NULL) { return TCL_ERROR; } if (!isInstanceForward && !oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } isPublic = Tcl_StringMatch(TclGetString(objv[1]), "[a-z]*") ? PUBLIC_METHOD : 0; /* * Create the method structure. */ prefixObj = Tcl_NewListObj(objc-2, objv+2); if (isInstanceForward) { mPtr = TclOONewForwardInstanceMethod(interp, oPtr, isPublic, objv[1], prefixObj); } else { mPtr = TclOONewForwardMethod(interp, oPtr->classPtr, isPublic, objv[1], prefixObj); } if (mPtr == NULL) { Tcl_DecrRefCount(prefixObj); return TCL_ERROR; } return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOODefineMethodObjCmd -- * Implementation of the "method" subcommand of the "oo::define" and * "oo::objdefine" commands. * * ---------------------------------------------------------------------- */ int TclOODefineMethodObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstanceMethod = (clientData != NULL); Object *oPtr; int isPublic; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "name args body"); return TCL_ERROR; } oPtr = (Object *) TclOOGetDefineCmdContext(interp); if (oPtr == NULL) { return TCL_ERROR; } if (!isInstanceMethod && !oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } isPublic = Tcl_StringMatch(TclGetString(objv[1]), "[a-z]*") ? PUBLIC_METHOD : 0; /* * Create the method by using the right back-end API. */ if (isInstanceMethod) { if (TclOONewProcInstanceMethod(interp, oPtr, isPublic, objv[1], objv[2], objv[3], NULL) == NULL) { return TCL_ERROR; } } else { if (TclOONewProcMethod(interp, oPtr->classPtr, isPublic, objv[1], objv[2], objv[3], NULL) == NULL) { return TCL_ERROR; } } return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOODefineMixinObjCmd -- * Implementation of the "mixin" subcommand of the "oo::define" and * "oo::objdefine" commands. * * ---------------------------------------------------------------------- */ int TclOODefineMixinObjCmd( ClientData clientData, Tcl_Interp *interp, const int objc, Tcl_Obj *const *objv) { int isInstanceMixin = (clientData != NULL); Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Class **mixins; int i; if (oPtr == NULL) { return TCL_ERROR; } if (!isInstanceMixin && !oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } mixins = TclStackAlloc(interp, sizeof(Class *) * (objc-1)); for (i=1 ; iclassPtr, clsPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may not mix a class into itself", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", NULL); goto freeAndError; } mixins[i-1] = clsPtr; } if (isInstanceMixin) { TclOOObjectSetMixins(oPtr, objc-1, mixins); } else { TclOOClassSetMixins(interp, oPtr->classPtr, objc-1, mixins); } TclStackFree(interp, mixins); return TCL_OK; freeAndError: TclStackFree(interp, mixins); return TCL_ERROR; } /* * ---------------------------------------------------------------------- * * TclOODefineRenameMethodObjCmd -- * Implementation of the "renamemethod" subcommand of the "oo::define" * and "oo::objdefine" commands. * * ---------------------------------------------------------------------- */ int TclOODefineRenameMethodObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstanceRenameMethod = (clientData != NULL); Object *oPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "oldName newName"); return TCL_ERROR; } oPtr = (Object *) TclOOGetDefineCmdContext(interp); if (oPtr == NULL) { return TCL_ERROR; } if (!isInstanceRenameMethod && !oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } /* * Delete the method entry from the appropriate hash table, and transfer * the thing it points to to its new entry. To do this, we first need to * get the entries from the appropriate hash tables (this can generate a * range of errors...) */ if (RenameDeleteMethod(interp, oPtr, !isInstanceRenameMethod, objv[1], objv[2]) != TCL_OK) { return TCL_ERROR; } if (isInstanceRenameMethod) { oPtr->epoch++; } else { BumpGlobalEpoch(interp, oPtr->classPtr); } return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOODefineUnexportObjCmd -- * Implementation of the "unexport" subcommand of the "oo::define" and * "oo::objdefine" commands. * * ---------------------------------------------------------------------- */ int TclOODefineUnexportObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { int isInstanceUnexport = (clientData != NULL); Object *oPtr; Method *mPtr; Tcl_HashEntry *hPtr; Class *clsPtr; int i, isNew, changed = 0; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "name ?name ...?"); return TCL_ERROR; } oPtr = (Object *) TclOOGetDefineCmdContext(interp); if (oPtr == NULL) { return TCL_ERROR; } clsPtr = oPtr->classPtr; if (!isInstanceUnexport && !clsPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } for (i=1 ; imethodsPtr) { oPtr->methodsPtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitObjHashTable(oPtr->methodsPtr); oPtr->flags &= ~USE_CLASS_CACHE; } hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *) objv[i], &isNew); } else { hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char*) objv[i], &isNew); } if (isNew) { mPtr = ckalloc(sizeof(Method)); memset(mPtr, 0, sizeof(Method)); mPtr->refCount = 1; mPtr->namePtr = objv[i]; Tcl_IncrRefCount(objv[i]); Tcl_SetHashValue(hPtr, mPtr); } else { mPtr = Tcl_GetHashValue(hPtr); } if (isNew || mPtr->flags & PUBLIC_METHOD) { mPtr->flags &= ~PUBLIC_METHOD; changed = 1; } } /* * Bump the right epoch if we actually changed anything. */ if (changed) { if (isInstanceUnexport) { oPtr->epoch++; } else { BumpGlobalEpoch(interp, clsPtr); } } return TCL_OK; } /* * ---------------------------------------------------------------------- * * Tcl_ClassSetConstructor, Tcl_ClassSetDestructor -- * How to install a constructor or destructor into a class; API to call * from C. * * ---------------------------------------------------------------------- */ void Tcl_ClassSetConstructor( Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method) { Class *clsPtr = (Class *) clazz; if (method != (Tcl_Method) clsPtr->constructorPtr) { TclOODelMethodRef(clsPtr->constructorPtr); clsPtr->constructorPtr = (Method *) method; /* * Remember to invalidate the cached constructor chain for this class. * [Bug 2531577] */ if (clsPtr->constructorChainPtr) { TclOODeleteChain(clsPtr->constructorChainPtr); clsPtr->constructorChainPtr = NULL; } BumpGlobalEpoch(interp, clsPtr); } } void Tcl_ClassSetDestructor( Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method) { Class *clsPtr = (Class *) clazz; if (method != (Tcl_Method) clsPtr->destructorPtr) { TclOODelMethodRef(clsPtr->destructorPtr); clsPtr->destructorPtr = (Method *) method; if (clsPtr->destructorChainPtr) { TclOODeleteChain(clsPtr->destructorChainPtr); clsPtr->destructorChainPtr = NULL; } BumpGlobalEpoch(interp, clsPtr); } } /* * ---------------------------------------------------------------------- * * TclOODefineSlots -- * Create the "::oo::Slot" class and its standard instances. Class * definition is empty at the stage (added by scripting). * * ---------------------------------------------------------------------- */ int TclOODefineSlots( Foundation *fPtr) { const struct DeclaredSlot *slotInfoPtr; Tcl_Obj *getName = Tcl_NewStringObj("Get", -1); Tcl_Obj *setName = Tcl_NewStringObj("Set", -1); Class *slotCls; slotCls = ((Object *) Tcl_NewObjectInstance(fPtr->interp, (Tcl_Class) fPtr->classCls, "::oo::Slot", NULL, -1, NULL, 0))->classPtr; if (slotCls == NULL) { return TCL_ERROR; } Tcl_IncrRefCount(getName); Tcl_IncrRefCount(setName); for (slotInfoPtr = slots ; slotInfoPtr->name ; slotInfoPtr++) { Tcl_Object slotObject = Tcl_NewObjectInstance(fPtr->interp, (Tcl_Class) slotCls, slotInfoPtr->name, NULL,-1,NULL,0); if (slotObject == NULL) { continue; } Tcl_NewInstanceMethod(fPtr->interp, slotObject, getName, 0, &slotInfoPtr->getterType, NULL); Tcl_NewInstanceMethod(fPtr->interp, slotObject, setName, 0, &slotInfoPtr->setterType, NULL); } Tcl_DecrRefCount(getName); Tcl_DecrRefCount(setName); return TCL_OK; } /* * ---------------------------------------------------------------------- * * ClassFilterGet, ClassFilterSet -- * Implementation of the "filter" slot accessors of the "oo::define" * command. * * ---------------------------------------------------------------------- */ static int ClassFilterGet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj, *filterObj; int i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; } if (oPtr == NULL) { return TCL_ERROR; } else if (!oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(filterObj, oPtr->classPtr->filters) { Tcl_ListObjAppendElement(NULL, resultObj, filterObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } static int ClassFilterSet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); int filterc; Tcl_Obj **filterv; if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "filterList"); return TCL_ERROR; } objv += Tcl_ObjectContextSkippedArgs(context); if (oPtr == NULL) { return TCL_ERROR; } else if (!oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } else if (Tcl_ListObjGetElements(interp, objv[0], &filterc, &filterv) != TCL_OK) { return TCL_ERROR; } TclOOClassSetFilters(interp, oPtr->classPtr, filterc, filterv); return TCL_OK; } /* * ---------------------------------------------------------------------- * * ClassMixinGet, ClassMixinSet -- * Implementation of the "mixin" slot accessors of the "oo::define" * command. * * ---------------------------------------------------------------------- */ static int ClassMixinGet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj; Class *mixinPtr; int i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; } if (oPtr == NULL) { return TCL_ERROR; } else if (!oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(mixinPtr, oPtr->classPtr->mixins) { Tcl_ListObjAppendElement(NULL, resultObj, TclOOObjectName(interp, mixinPtr->thisPtr)); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } static int ClassMixinSet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); int mixinc, i; Tcl_Obj **mixinv; Class **mixins; if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "mixinList"); return TCL_ERROR; } objv += Tcl_ObjectContextSkippedArgs(context); if (oPtr == NULL) { return TCL_ERROR; } else if (!oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } else if (Tcl_ListObjGetElements(interp, objv[0], &mixinc, &mixinv) != TCL_OK) { return TCL_ERROR; } mixins = TclStackAlloc(interp, sizeof(Class *) * mixinc); for (i=0 ; iclassPtr, mixins[i])) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may not mix a class into itself", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", NULL); goto freeAndError; } } TclOOClassSetMixins(interp, oPtr->classPtr, mixinc, mixins); TclStackFree(interp, mixins); return TCL_OK; freeAndError: TclStackFree(interp, mixins); return TCL_ERROR; } /* * ---------------------------------------------------------------------- * * ClassSuperGet, ClassSuperSet -- * Implementation of the "superclass" slot accessors of the "oo::define" * command. * * ---------------------------------------------------------------------- */ static int ClassSuperGet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj; Class *superPtr; int i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; } if (oPtr == NULL) { return TCL_ERROR; } else if (!oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(superPtr, oPtr->classPtr->superclasses) { Tcl_ListObjAppendElement(NULL, resultObj, TclOOObjectName(interp, superPtr->thisPtr)); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } static int ClassSuperSet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); int superc, i, j; Tcl_Obj **superv; Class **superclasses, *superPtr; if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "superclassList"); return TCL_ERROR; } objv += Tcl_ObjectContextSkippedArgs(context); if (oPtr == NULL) { return TCL_ERROR; } else if (!oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } else if (oPtr == oPtr->fPtr->objectCls->thisPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may not modify the superclass of the root object", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } else if (Tcl_ListObjGetElements(interp, objv[0], &superc, &superv) != TCL_OK) { return TCL_ERROR; } /* * Allocate some working space. */ superclasses = (Class **) ckalloc(sizeof(Class *) * superc); /* * Parse the arguments to get the class to use as superclasses. * * Note that zero classes is special, as it is equivalent to just the * class of objects. [Bug 9d61624b3d] */ if (superc == 0) { superclasses = ckrealloc(superclasses, sizeof(Class *)); superclasses[0] = oPtr->fPtr->objectCls; superc = 1; if (TclOOIsReachable(oPtr->fPtr->classCls, oPtr->classPtr)) { superclasses[0] = oPtr->fPtr->classCls; } } else { for (i=0 ; iclassPtr, superclasses[i])) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to form circular dependency graph", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", NULL); failedAfterAlloc: ckfree((char *) superclasses); return TCL_ERROR; } } } /* * Install the list of superclasses into the class. Note that this also * involves splicing the class out of the superclasses' subclass list that * it used to be a member of and splicing it into the new superclasses' * subclass list. */ if (oPtr->classPtr->superclasses.num != 0) { FOREACH(superPtr, oPtr->classPtr->superclasses) { TclOORemoveFromSubclasses(oPtr->classPtr, superPtr); } ckfree((char *) oPtr->classPtr->superclasses.list); } oPtr->classPtr->superclasses.list = superclasses; oPtr->classPtr->superclasses.num = superc; FOREACH(superPtr, oPtr->classPtr->superclasses) { TclOOAddToSubclasses(oPtr->classPtr, superPtr); } BumpGlobalEpoch(interp, oPtr->classPtr); return TCL_OK; } /* * ---------------------------------------------------------------------- * * ClassVarsGet, ClassVarsSet -- * Implementation of the "variable" slot accessors of the "oo::define" * command. * * ---------------------------------------------------------------------- */ static int ClassVarsGet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj, *variableObj; int i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; } if (oPtr == NULL) { return TCL_ERROR; } else if (!oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(variableObj, oPtr->classPtr->variables) { Tcl_ListObjAppendElement(NULL, resultObj, variableObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } static int ClassVarsSet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); int varc; Tcl_Obj **varv, *variableObj; int i; if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "filterList"); return TCL_ERROR; } objv += Tcl_ObjectContextSkippedArgs(context); if (oPtr == NULL) { return TCL_ERROR; } else if (!oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } else if (Tcl_ListObjGetElements(interp, objv[0], &varc, &varv) != TCL_OK) { return TCL_ERROR; } for (i=0 ; iclassPtr->variables) { Tcl_DecrRefCount(variableObj); } if (i != varc) { if (varc == 0) { ckfree((char *) oPtr->classPtr->variables.list); } else if (i) { oPtr->classPtr->variables.list = (Tcl_Obj **) ckrealloc((char *) oPtr->classPtr->variables.list, sizeof(Tcl_Obj *) * varc); } else { oPtr->classPtr->variables.list = (Tcl_Obj **) ckalloc(sizeof(Tcl_Obj *) * varc); } } oPtr->classPtr->variables.num = 0; if (varc > 0) { int created, n; Tcl_HashTable uniqueTable; Tcl_InitObjHashTable(&uniqueTable); for (i=n=0 ; iclassPtr->variables.list[n++] = varv[i]; } else { Tcl_DecrRefCount(varv[i]); } } oPtr->classPtr->variables.num = n; /* * Shouldn't be necessary, but maintain num/list invariant. */ oPtr->classPtr->variables.list = (Tcl_Obj **) ckrealloc((char *) oPtr->classPtr->variables.list, sizeof(Tcl_Obj *) * n); Tcl_DeleteHashTable(&uniqueTable); } return TCL_OK; } /* * ---------------------------------------------------------------------- * * ObjectFilterGet, ObjectFilterSet -- * Implementation of the "filter" slot accessors of the "oo::objdefine" * command. * * ---------------------------------------------------------------------- */ static int ObjFilterGet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj, *filterObj; int i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; } else if (oPtr == NULL) { return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(filterObj, oPtr->filters) { Tcl_ListObjAppendElement(NULL, resultObj, filterObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } static int ObjFilterSet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); int filterc; Tcl_Obj **filterv; if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "filterList"); return TCL_ERROR; } else if (oPtr == NULL) { return TCL_ERROR; } objv += Tcl_ObjectContextSkippedArgs(context); if (Tcl_ListObjGetElements(interp, objv[0], &filterc, &filterv) != TCL_OK) { return TCL_ERROR; } TclOOObjectSetFilters(oPtr, filterc, filterv); return TCL_OK; } /* * ---------------------------------------------------------------------- * * ObjectMixinGet, ObjectMixinSet -- * Implementation of the "mixin" slot accessors of the "oo::objdefine" * command. * * ---------------------------------------------------------------------- */ static int ObjMixinGet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); Tcl_Obj *resultObj; Class *mixinPtr; int i; if (Tcl_ObjectContextSkippedArgs(context) != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, NULL); return TCL_ERROR; } else if (oPtr == NULL) { return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(mixinPtr, oPtr->mixins) { if (mixinPtr) { Tcl_ListObjAppendElement(NULL, resultObj, TclOOObjectName(interp, mixinPtr->thisPtr)); } } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } static int ObjMixinSet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); int mixinc; Tcl_Obj **mixinv; Class **mixins; int i; if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "mixinList"); return TCL_ERROR; } else if (oPtr == NULL) { return TCL_ERROR; } objv += Tcl_ObjectContextSkippedArgs(context); if (Tcl_ListObjGetElements(interp, objv[0], &mixinc, &mixinv) != TCL_OK) { return TCL_ERROR; } mixins = TclStackAlloc(interp, sizeof(Class *) * mixinc); for (i=0 ; ivariables) { Tcl_ListObjAppendElement(NULL, resultObj, variableObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } static int ObjVarsSet( ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv) { Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp); int varc, i; Tcl_Obj **varv, *variableObj; if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) { Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv, "variableList"); return TCL_ERROR; } else if (oPtr == NULL) { return TCL_ERROR; } objv += Tcl_ObjectContextSkippedArgs(context); if (Tcl_ListObjGetElements(interp, objv[0], &varc, &varv) != TCL_OK) { return TCL_ERROR; } for (i=0 ; ivariables) { Tcl_DecrRefCount(variableObj); } if (i != varc) { if (varc == 0) { ckfree((char *) oPtr->variables.list); } else if (i) { oPtr->variables.list = (Tcl_Obj **) ckrealloc((char *) oPtr->variables.list, sizeof(Tcl_Obj *) * varc); } else { oPtr->variables.list = (Tcl_Obj **) ckalloc(sizeof(Tcl_Obj *) * varc); } } oPtr->variables.num = 0; if (varc > 0) { int created, n; Tcl_HashTable uniqueTable; Tcl_InitObjHashTable(&uniqueTable); for (i=n=0 ; ivariables.list[n++] = varv[i]; } else { Tcl_DecrRefCount(varv[i]); } } oPtr->variables.num = n; /* * Shouldn't be necessary, but maintain num/list invariant. */ oPtr->variables.list = (Tcl_Obj **) ckrealloc((char *) oPtr->variables.list, sizeof(Tcl_Obj *) * n); Tcl_DeleteHashTable(&uniqueTable); } return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/rege_dfa.c0000644000175000017500000004607312663660065015115 0ustar sergeisergei/* * DFA routines * This file is #included by regexec.c. * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation * of software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* - longest - longest-preferred matching engine ^ static chr *longest(struct vars *, struct dfa *, chr *, chr *, int *); */ static chr * /* endpoint, or NULL */ longest( struct vars *const v, /* used only for debug and exec flags */ struct dfa *const d, chr *const start, /* where the match should start */ chr *const stop, /* match must end at or before here */ int *const hitstopp) /* record whether hit v->stop, if non-NULL */ { chr *cp; chr *realstop = (stop == v->stop) ? stop : stop + 1; color co; struct sset *css, *ss; chr *post; int i; struct colormap *cm = d->cm; /* * Initialize. */ css = initialize(v, d, start); cp = start; if (hitstopp != NULL) { *hitstopp = 0; } /* * Startup. */ FDEBUG(("+++ startup +++\n")); if (cp == v->start) { co = d->cnfa->bos[(v->eflags®_NOTBOL) ? 0 : 1]; FDEBUG(("color %ld\n", (long)co)); } else { co = GETCOLOR(cm, *(cp - 1)); FDEBUG(("char %c, color %ld\n", (char)*(cp-1), (long)co)); } css = miss(v, d, css, co, cp, start); if (css == NULL) { return NULL; } css->lastseen = cp; /* * Main loop. */ if (v->eflags®_FTRACE) { while (cp < realstop) { FDEBUG(("+++ at c%d +++\n", (int) (css - d->ssets))); co = GETCOLOR(cm, *cp); FDEBUG(("char %c, color %ld\n", (char)*cp, (long)co)); ss = css->outs[co]; if (ss == NULL) { ss = miss(v, d, css, co, cp+1, start); if (ss == NULL) { break; /* NOTE BREAK OUT */ } } cp++; ss->lastseen = cp; css = ss; } } else { while (cp < realstop) { co = GETCOLOR(cm, *cp); ss = css->outs[co]; if (ss == NULL) { ss = miss(v, d, css, co, cp+1, start); if (ss == NULL) { break; /* NOTE BREAK OUT */ } } cp++; ss->lastseen = cp; css = ss; } } /* * Shutdown. */ FDEBUG(("+++ shutdown at c%d +++\n", (int) (css - d->ssets))); if (cp == v->stop && stop == v->stop) { if (hitstopp != NULL) { *hitstopp = 1; } co = d->cnfa->eos[(v->eflags®_NOTEOL) ? 0 : 1]; FDEBUG(("color %ld\n", (long)co)); ss = miss(v, d, css, co, cp, start); /* * Special case: match ended at eol? */ if (ss != NULL && (ss->flags&POSTSTATE)) { return cp; } else if (ss != NULL) { ss->lastseen = cp; /* to be tidy */ } } /* * Find last match, if any. */ post = d->lastpost; for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--) { if ((ss->flags&POSTSTATE) && (post != ss->lastseen) && (post == NULL || post < ss->lastseen)) { post = ss->lastseen; } } if (post != NULL) { /* found one */ return post - 1; } return NULL; } /* - shortest - shortest-preferred matching engine ^ static chr *shortest(struct vars *, struct dfa *, chr *, chr *, chr *, ^ chr **, int *); */ static chr * /* endpoint, or NULL */ shortest( struct vars *const v, struct dfa *const d, chr *const start, /* where the match should start */ chr *const min, /* match must end at or after here */ chr *const max, /* match must end at or before here */ chr **const coldp, /* store coldstart pointer here, if nonNULL */ int *const hitstopp) /* record whether hit v->stop, if non-NULL */ { chr *cp; chr *realmin = (min == v->stop) ? min : min + 1; chr *realmax = (max == v->stop) ? max : max + 1; color co; struct sset *css, *ss; struct colormap *cm = d->cm; /* * Initialize. */ css = initialize(v, d, start); cp = start; if (hitstopp != NULL) { *hitstopp = 0; } /* * Startup. */ FDEBUG(("--- startup ---\n")); if (cp == v->start) { co = d->cnfa->bos[(v->eflags®_NOTBOL) ? 0 : 1]; FDEBUG(("color %ld\n", (long)co)); } else { co = GETCOLOR(cm, *(cp - 1)); FDEBUG(("char %c, color %ld\n", (char)*(cp-1), (long)co)); } css = miss(v, d, css, co, cp, start); if (css == NULL) { return NULL; } css->lastseen = cp; ss = css; /* * Main loop. */ if (v->eflags®_FTRACE) { while (cp < realmax) { FDEBUG(("--- at c%d ---\n", (int) (css - d->ssets))); co = GETCOLOR(cm, *cp); FDEBUG(("char %c, color %ld\n", (char)*cp, (long)co)); ss = css->outs[co]; if (ss == NULL) { ss = miss(v, d, css, co, cp+1, start); if (ss == NULL) { break; /* NOTE BREAK OUT */ } } cp++; ss->lastseen = cp; css = ss; if ((ss->flags&POSTSTATE) && cp >= realmin) { break; /* NOTE BREAK OUT */ } } } else { while (cp < realmax) { co = GETCOLOR(cm, *cp); ss = css->outs[co]; if (ss == NULL) { ss = miss(v, d, css, co, cp+1, start); if (ss == NULL) { break; /* NOTE BREAK OUT */ } } cp++; ss->lastseen = cp; css = ss; if ((ss->flags&POSTSTATE) && cp >= realmin) { break; /* NOTE BREAK OUT */ } } } if (ss == NULL) { return NULL; } if (coldp != NULL) { /* report last no-progress state set, if any */ *coldp = lastCold(v, d); } if ((ss->flags&POSTSTATE) && cp > min) { assert(cp >= realmin); cp--; } else if (cp == v->stop && max == v->stop) { co = d->cnfa->eos[(v->eflags®_NOTEOL) ? 0 : 1]; FDEBUG(("color %ld\n", (long)co)); ss = miss(v, d, css, co, cp, start); /* * Match might have ended at eol. */ if ((ss == NULL || !(ss->flags&POSTSTATE)) && hitstopp != NULL) { *hitstopp = 1; } } if (ss == NULL || !(ss->flags&POSTSTATE)) { return NULL; } return cp; } /* - lastCold - determine last point at which no progress had been made ^ static chr *lastCold(struct vars *, struct dfa *); */ static chr * /* endpoint, or NULL */ lastCold( struct vars *const v, struct dfa *const d) { struct sset *ss; chr *nopr = d->lastnopr; int i; if (nopr == NULL) { nopr = v->start; } for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--) { if ((ss->flags&NOPROGRESS) && nopr < ss->lastseen) { nopr = ss->lastseen; } } return nopr; } /* - newDFA - set up a fresh DFA ^ static struct dfa *newDFA(struct vars *, struct cnfa *, ^ struct colormap *, struct smalldfa *); */ static struct dfa * newDFA( struct vars *const v, struct cnfa *const cnfa, struct colormap *const cm, struct smalldfa *sml) /* preallocated space, may be NULL */ { struct dfa *d; size_t nss = cnfa->nstates * 2; int wordsper = (cnfa->nstates + UBITS - 1) / UBITS; struct smalldfa *smallwas = sml; assert(cnfa != NULL && cnfa->nstates != 0); if (nss <= FEWSTATES && cnfa->ncolors <= FEWCOLORS) { assert(wordsper == 1); if (sml == NULL) { sml = (struct smalldfa *) MALLOC(sizeof(struct smalldfa)); if (sml == NULL) { ERR(REG_ESPACE); return NULL; } } d = &sml->dfa; d->ssets = sml->ssets; d->statesarea = sml->statesarea; d->work = &d->statesarea[nss]; d->outsarea = sml->outsarea; d->incarea = sml->incarea; d->cptsmalloced = 0; d->mallocarea = (smallwas == NULL) ? (char *)sml : NULL; } else { d = (struct dfa *) MALLOC(sizeof(struct dfa)); if (d == NULL) { ERR(REG_ESPACE); return NULL; } d->ssets = (struct sset *) MALLOC(nss * sizeof(struct sset)); d->statesarea = (unsigned *) MALLOC((nss+WORK) * wordsper * sizeof(unsigned)); d->work = &d->statesarea[nss * wordsper]; d->outsarea = (struct sset **) MALLOC(nss * cnfa->ncolors * sizeof(struct sset *)); d->incarea = (struct arcp *) MALLOC(nss * cnfa->ncolors * sizeof(struct arcp)); d->cptsmalloced = 1; d->mallocarea = (char *)d; if (d->ssets == NULL || d->statesarea == NULL || d->outsarea == NULL || d->incarea == NULL) { freeDFA(d); ERR(REG_ESPACE); return NULL; } } d->nssets = (v->eflags®_SMALL) ? 7 : nss; d->nssused = 0; d->nstates = cnfa->nstates; d->ncolors = cnfa->ncolors; d->wordsper = wordsper; d->cnfa = cnfa; d->cm = cm; d->lastpost = NULL; d->lastnopr = NULL; d->search = d->ssets; /* * Initialization of sset fields is done as needed. */ return d; } /* - freeDFA - free a DFA ^ static void freeDFA(struct dfa *); */ static void freeDFA( struct dfa *const d) { if (d->cptsmalloced) { if (d->ssets != NULL) { FREE(d->ssets); } if (d->statesarea != NULL) { FREE(d->statesarea); } if (d->outsarea != NULL) { FREE(d->outsarea); } if (d->incarea != NULL) { FREE(d->incarea); } } if (d->mallocarea != NULL) { FREE(d->mallocarea); } } /* - hash - construct a hash code for a bitvector * There are probably better ways, but they're more expensive. ^ static unsigned hash(unsigned *, int); */ static unsigned hash( unsigned *const uv, const int n) { int i; unsigned h; h = 0; for (i = 0; i < n; i++) { h ^= uv[i]; } return h; } /* - initialize - hand-craft a cache entry for startup, otherwise get ready ^ static struct sset *initialize(struct vars *, struct dfa *, chr *); */ static struct sset * initialize( struct vars *const v, /* used only for debug flags */ struct dfa *const d, chr *const start) { struct sset *ss; int i; /* * Is previous one still there? */ if (d->nssused > 0 && (d->ssets[0].flags&STARTER)) { ss = &d->ssets[0]; } else { /* no, must (re)build it */ ss = getVacantSS(v, d, start, start); for (i = 0; i < d->wordsper; i++) { ss->states[i] = 0; } BSET(ss->states, d->cnfa->pre); ss->hash = HASH(ss->states, d->wordsper); assert(d->cnfa->pre != d->cnfa->post); ss->flags = STARTER|LOCKED|NOPROGRESS; /* * lastseen dealt with below */ } for (i = 0; i < d->nssused; i++) { d->ssets[i].lastseen = NULL; } ss->lastseen = start; /* maybe untrue, but harmless */ d->lastpost = NULL; d->lastnopr = NULL; return ss; } /* - miss - handle a cache miss ^ static struct sset *miss(struct vars *, struct dfa *, struct sset *, ^ pcolor, chr *, chr *); */ static struct sset * /* NULL if goes to empty set */ miss( struct vars *const v, /* used only for debug flags */ struct dfa *const d, struct sset *const css, const pcolor co, chr *const cp, /* next chr */ chr *const start) /* where the attempt got started */ { struct cnfa *cnfa = d->cnfa; unsigned h; struct carc *ca; struct sset *p; int i, isPost, noProgress, gotState, doLAConstraints, sawLAConstraints; /* * For convenience, we can be called even if it might not be a miss. */ if (css->outs[co] != NULL) { FDEBUG(("hit\n")); return css->outs[co]; } FDEBUG(("miss\n")); /* * First, what set of states would we end up in? */ for (i = 0; i < d->wordsper; i++) { d->work[i] = 0; } isPost = 0; noProgress = 1; gotState = 0; for (i = 0; i < d->nstates; i++) { if (ISBSET(css->states, i)) { for (ca = cnfa->states[i]; ca->co != COLORLESS; ca++) { if (ca->co == co) { BSET(d->work, ca->to); gotState = 1; if (ca->to == cnfa->post) { isPost = 1; } if (!(cnfa->stflags[ca->to] & CNFA_NOPROGRESS)) { noProgress = 0; } FDEBUG(("%d -> %d\n", i, ca->to)); } } } } doLAConstraints = (gotState ? (cnfa->flags&HASLACONS) : 0); sawLAConstraints = 0; while (doLAConstraints) { /* transitive closure */ doLAConstraints = 0; for (i = 0; i < d->nstates; i++) { if (ISBSET(d->work, i)) { for (ca = cnfa->states[i]; ca->co != COLORLESS; ca++) { if (ca->co < cnfa->ncolors) { continue; /* NOTE CONTINUE */ } sawLAConstraints = 1; if (ISBSET(d->work, ca->to)) { continue; /* NOTE CONTINUE */ } if (!checkLAConstraint(v, cnfa, cp, ca->co)) { continue; /* NOTE CONTINUE */ } BSET(d->work, ca->to); doLAConstraints = 1; if (ca->to == cnfa->post) { isPost = 1; } if (!(cnfa->stflags[ca->to] & CNFA_NOPROGRESS)) { noProgress = 0; } FDEBUG(("%d :> %d\n", i, ca->to)); } } } } if (!gotState) { return NULL; } h = HASH(d->work, d->wordsper); /* * Next, is that in the cache? */ for (p = d->ssets, i = d->nssused; i > 0; p++, i--) { if (HIT(h, d->work, p, d->wordsper)) { FDEBUG(("cached c%d\n", (int) (p - d->ssets))); break; /* NOTE BREAK OUT */ } } if (i == 0) { /* nope, need a new cache entry */ p = getVacantSS(v, d, cp, start); assert(p != css); for (i = 0; i < d->wordsper; i++) { p->states[i] = d->work[i]; } p->hash = h; p->flags = (isPost ? POSTSTATE : 0); if (noProgress) { p->flags |= NOPROGRESS; } /* * lastseen to be dealt with by caller */ } if (!sawLAConstraints) { /* lookahead conds. always cache miss */ FDEBUG(("c%d[%d]->c%d\n", (int) (css - d->ssets), co, (int) (p - d->ssets))); css->outs[co] = p; css->inchain[co] = p->ins; p->ins.ss = css; p->ins.co = (color) co; } return p; } /* - checkLAConstraint - lookahead-constraint checker for miss() ^ static int checkLAConstraint(struct vars *, struct cnfa *, chr *, pcolor); */ static int /* predicate: constraint satisfied? */ checkLAConstraint( struct vars *const v, struct cnfa *const pcnfa, /* parent cnfa */ chr *const cp, const pcolor co) /* "color" of the lookahead constraint */ { int n; struct subre *sub; struct dfa *d; struct smalldfa sd; chr *end; n = co - pcnfa->ncolors; assert(n < v->g->nlacons && v->g->lacons != NULL); FDEBUG(("=== testing lacon %d\n", n)); sub = &v->g->lacons[n]; d = newDFA(v, &sub->cnfa, &v->g->cmap, &sd); if (d == NULL) { ERR(REG_ESPACE); return 0; } end = longest(v, d, cp, v->stop, NULL); freeDFA(d); FDEBUG(("=== lacon %d match %d\n", n, (end != NULL))); return (sub->subno) ? (end != NULL) : (end == NULL); } /* - getVacantSS - get a vacant state set * This routine clears out the inarcs and outarcs, but does not otherwise * clear the innards of the state set -- that's up to the caller. ^ static struct sset *getVacantSS(struct vars *, struct dfa *, chr *, chr *); */ static struct sset * getVacantSS( struct vars *const v, /* used only for debug flags */ struct dfa *const d, chr *const cp, chr *const start) { int i; struct sset *ss, *p; struct arcp ap, lastap = {NULL, 0}; /* silence gcc 4 warning */ color co; ss = pickNextSS(v, d, cp, start); assert(!(ss->flags&LOCKED)); /* * Clear out its inarcs, including self-referential ones. */ ap = ss->ins; while ((p = ap.ss) != NULL) { co = ap.co; FDEBUG(("zapping c%d's %ld outarc\n", (int) (p - d->ssets), (long)co)); p->outs[co] = NULL; ap = p->inchain[co]; p->inchain[co].ss = NULL; /* paranoia */ } ss->ins.ss = NULL; /* * Take it off the inarc chains of the ssets reached by its outarcs. */ for (i = 0; i < d->ncolors; i++) { p = ss->outs[i]; assert(p != ss); /* not self-referential */ if (p == NULL) { continue; /* NOTE CONTINUE */ } FDEBUG(("del outarc %d from c%d's in chn\n", i, (int) (p - d->ssets))); if (p->ins.ss == ss && p->ins.co == i) { p->ins = ss->inchain[i]; } else { assert(p->ins.ss != NULL); for (ap = p->ins; ap.ss != NULL && !(ap.ss == ss && ap.co == i); ap = ap.ss->inchain[ap.co]) { lastap = ap; } assert(ap.ss != NULL); lastap.ss->inchain[lastap.co] = ss->inchain[i]; } ss->outs[i] = NULL; ss->inchain[i].ss = NULL; } /* * If ss was a success state, may need to remember location. */ if ((ss->flags&POSTSTATE) && ss->lastseen != d->lastpost && (d->lastpost == NULL || d->lastpost < ss->lastseen)) { d->lastpost = ss->lastseen; } /* * Likewise for a no-progress state. */ if ((ss->flags&NOPROGRESS) && ss->lastseen != d->lastnopr && (d->lastnopr == NULL || d->lastnopr < ss->lastseen)) { d->lastnopr = ss->lastseen; } return ss; } /* - pickNextSS - pick the next stateset to be used ^ static struct sset *pickNextSS(struct vars *, struct dfa *, chr *, chr *); */ static struct sset * pickNextSS( struct vars *const v, /* used only for debug flags */ struct dfa *const d, chr *const cp, chr *const start) { int i; struct sset *ss, *end; chr *ancient; /* * Shortcut for cases where cache isn't full. */ if (d->nssused < d->nssets) { i = d->nssused; d->nssused++; ss = &d->ssets[i]; FDEBUG(("new c%d\n", i)); /* * Set up innards. */ ss->states = &d->statesarea[i * d->wordsper]; ss->flags = 0; ss->ins.ss = NULL; ss->ins.co = WHITE; /* give it some value */ ss->outs = &d->outsarea[i * d->ncolors]; ss->inchain = &d->incarea[i * d->ncolors]; for (i = 0; i < d->ncolors; i++) { ss->outs[i] = NULL; ss->inchain[i].ss = NULL; } return ss; } /* * Look for oldest, or old enough anyway. */ if (cp - start > d->nssets*2/3) { /* oldest 33% are expendable */ ancient = cp - d->nssets*2/3; } else { ancient = start; } for (ss = d->search, end = &d->ssets[d->nssets]; ss < end; ss++) { if ((ss->lastseen == NULL || ss->lastseen < ancient) && !(ss->flags&LOCKED)) { d->search = ss + 1; FDEBUG(("replacing c%d\n", (int) (ss - d->ssets))); return ss; } } for (ss = d->ssets, end = d->search; ss < end; ss++) { if ((ss->lastseen == NULL || ss->lastseen < ancient) && !(ss->flags&LOCKED)) { d->search = ss + 1; FDEBUG(("replacing c%d\n", (int) (ss - d->ssets))); return ss; } } /* * Nobody's old enough?!? -- something's really wrong. */ FDEBUG(("can't find victim to replace!\n")); assert(NOTREACHED); ERR(REG_ASSERT); return d->ssets; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclStringObj.c0000644000175000017500000023552412663660065015766 0ustar sergeisergei/* * tclStringObj.c -- * * This file contains functions that implement string operations on Tcl * objects. Some string operations work with UTF strings and others * require Unicode format. Functions that require knowledge of the width * of each character, such as indexing, operate on Unicode data. * * A Unicode string is an internationalized string. Conceptually, a * Unicode string is an array of 16-bit quantities organized as a * sequence of properly formed UTF-8 characters. There is a one-to-one * map between Unicode and UTF characters. Because Unicode characters * have a fixed width, operations such as indexing operate on Unicode * data. The String object is optimized for the case where each UTF char * in a string is only one byte. In this case, we store the value of * numChars, but we don't store the Unicode data (unless Tcl_GetUnicode * is explicitly called). * * The String object type stores one or both formats. The default * behavior is to store UTF. Once Unicode is calculated by a function, it * is stored in the internal rep for future access (without an additional * O(n) cost). * * To allow many appends to be done to an object without constantly * reallocating the space for the string or Unicode representation, we * allocate double the space for the string or Unicode and use the * internal representation to keep track of how much space is used vs. * allocated. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tommath.h" /* * Set COMPAT to 1 to restore the shimmering patterns to those of Tcl 8.5. * This is an escape hatch in case the changes have some unexpected unwelcome * impact on performance. If things go well, this mechanism can go away when * post-8.6 development begins. */ #define COMPAT 0 /* * Prototypes for functions defined later in this file: */ static void AppendPrintfToObjVA(Tcl_Obj *objPtr, const char *format, va_list argList); static void AppendUnicodeToUnicodeRep(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int appendNumChars); static void AppendUnicodeToUtfRep(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int numChars); static void AppendUtfToUnicodeRep(Tcl_Obj *objPtr, const char *bytes, int numBytes); static void AppendUtfToUtfRep(Tcl_Obj *objPtr, const char *bytes, int numBytes); static void DupStringInternalRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); static int ExtendStringRepWithUnicode(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int numChars); static void ExtendUnicodeRepWithString(Tcl_Obj *objPtr, const char *bytes, int numBytes, int numAppendChars); static void FillUnicodeRep(Tcl_Obj *objPtr); static void FreeStringInternalRep(Tcl_Obj *objPtr); static void GrowStringBuffer(Tcl_Obj *objPtr, int needed, int flag); static void GrowUnicodeBuffer(Tcl_Obj *objPtr, int needed); static int SetStringFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void SetUnicodeObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int numChars); static int UnicodeLength(const Tcl_UniChar *unicode); static void UpdateStringOfString(Tcl_Obj *objPtr); /* * The structure below defines the string Tcl object type by means of * functions that can be invoked by generic object code. */ const Tcl_ObjType tclStringType = { "string", /* name */ FreeStringInternalRep, /* freeIntRepPro */ DupStringInternalRep, /* dupIntRepProc */ UpdateStringOfString, /* updateStringProc */ SetStringFromAny /* setFromAnyProc */ }; /* * The following structure is the internal rep for a String object. It keeps * track of how much memory has been used and how much has been allocated for * the Unicode and UTF string to enable growing and shrinking of the UTF and * Unicode reps of the String object with fewer mallocs. To optimize string * length and indexing operations, this structure also stores the number of * characters (same of UTF and Unicode!) once that value has been computed. * * Under normal configurations, what Tcl calls "Unicode" is actually UTF-16 * restricted to the Basic Multilingual Plane (i.e. U+00000 to U+0FFFF). This * can be officially modified by altering the definition of Tcl_UniChar in * tcl.h, but do not do that unless you are sure what you're doing! */ typedef struct String { int numChars; /* The number of chars in the string. -1 means * this value has not been calculated. >= 0 * means that there is a valid Unicode rep, or * that the number of UTF bytes == the number * of chars. */ int allocated; /* The amount of space actually allocated for * the UTF string (minus 1 byte for the * termination char). */ int maxChars; /* Max number of chars that can fit in the * space allocated for the unicode array. */ int hasUnicode; /* Boolean determining whether the string has * a Unicode representation. */ Tcl_UniChar unicode[1]; /* The array of Unicode chars. The actual size * of this field depends on the 'maxChars' * field above. */ } String; #define STRING_MAXCHARS \ (int)(((size_t)UINT_MAX - sizeof(String))/sizeof(Tcl_UniChar)) #define STRING_SIZE(numChars) \ (sizeof(String) + ((numChars) * sizeof(Tcl_UniChar))) #define stringCheckLimits(numChars) \ if ((numChars) < 0 || (numChars) > STRING_MAXCHARS) { \ Tcl_Panic("max length for a Tcl unicode value (%d chars) exceeded", \ STRING_MAXCHARS); \ } #define stringAttemptAlloc(numChars) \ (String *) attemptckalloc((unsigned) STRING_SIZE(numChars) ) #define stringAlloc(numChars) \ (String *) ckalloc((unsigned) STRING_SIZE(numChars) ) #define stringRealloc(ptr, numChars) \ (String *) ckrealloc((ptr), (unsigned) STRING_SIZE(numChars) ) #define stringAttemptRealloc(ptr, numChars) \ (String *) attemptckrealloc((ptr), (unsigned) STRING_SIZE(numChars) ) #define GET_STRING(objPtr) \ ((String *) (objPtr)->internalRep.twoPtrValue.ptr1) #define SET_STRING(objPtr, stringPtr) \ ((objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (stringPtr)) /* * TCL STRING GROWTH ALGORITHM * * When growing strings (during an append, for example), the following growth * algorithm is used: * * Attempt to allocate 2 * (originalLength + appendLength) * On failure: * attempt to allocate originalLength + 2*appendLength + TCL_MIN_GROWTH * * This algorithm allows very good performance, as it rapidly increases the * memory allocated for a given string, which minimizes the number of * reallocations that must be performed. However, using only the doubling * algorithm can lead to a significant waste of memory. In particular, it may * fail even when there is sufficient memory available to complete the append * request (but there is not 2*totalLength memory available). So when the * doubling fails (because there is not enough memory available), the * algorithm requests a smaller amount of memory, which is still enough to * cover the request, but which hopefully will be less than the total * available memory. * * The addition of TCL_MIN_GROWTH allows for efficient handling of very * small appends. Without this extra slush factor, a sequence of several small * appends would cause several memory allocations. As long as * TCL_MIN_GROWTH is a reasonable size, we can avoid that behavior. * * The growth algorithm can be tuned by adjusting the following parameters: * * TCL_MIN_GROWTH Additional space, in bytes, to allocate when * the double allocation has failed. Default is * 1024 (1 kilobyte). See tclInt.h. */ #ifndef TCL_MIN_UNICHAR_GROWTH #define TCL_MIN_UNICHAR_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_UniChar) #endif static void GrowStringBuffer( Tcl_Obj *objPtr, int needed, int flag) { /* * Pre-conditions: * objPtr->typePtr == &tclStringType * needed > stringPtr->allocated * flag || objPtr->bytes != NULL */ String *stringPtr = GET_STRING(objPtr); char *ptr = NULL; int attempt; if (objPtr->bytes == tclEmptyStringRep) { objPtr->bytes = NULL; } if (flag == 0 || stringPtr->allocated > 0) { attempt = 2 * needed; if (attempt >= 0) { ptr = attemptckrealloc(objPtr->bytes, attempt + 1); } if (ptr == NULL) { /* * Take care computing the amount of modest growth to avoid * overflow into invalid argument values for attempt. */ unsigned int limit = INT_MAX - needed; unsigned int extra = needed - objPtr->length + TCL_MIN_GROWTH; int growth = (int) ((extra > limit) ? limit : extra); attempt = needed + growth; ptr = attemptckrealloc(objPtr->bytes, attempt + 1); } } if (ptr == NULL) { /* * First allocation - just big enough; or last chance fallback. */ attempt = needed; ptr = ckrealloc(objPtr->bytes, attempt + 1); } objPtr->bytes = ptr; stringPtr->allocated = attempt; } static void GrowUnicodeBuffer( Tcl_Obj *objPtr, int needed) { /* * Pre-conditions: * objPtr->typePtr == &tclStringType * needed > stringPtr->maxChars * needed < STRING_MAXCHARS */ String *ptr = NULL, *stringPtr = GET_STRING(objPtr); int attempt; if (stringPtr->maxChars > 0) { /* * Subsequent appends - apply the growth algorithm. */ attempt = 2 * needed; if (attempt >= 0 && attempt <= STRING_MAXCHARS) { ptr = stringAttemptRealloc(stringPtr, attempt); } if (ptr == NULL) { /* * Take care computing the amount of modest growth to avoid * overflow into invalid argument values for attempt. */ unsigned int limit = STRING_MAXCHARS - needed; unsigned int extra = needed - stringPtr->numChars + TCL_MIN_UNICHAR_GROWTH; int growth = (int) ((extra > limit) ? limit : extra); attempt = needed + growth; ptr = stringAttemptRealloc(stringPtr, attempt); } } if (ptr == NULL) { /* * First allocation - just big enough; or last chance fallback. */ attempt = needed; ptr = stringRealloc(stringPtr, attempt); } stringPtr = ptr; stringPtr->maxChars = attempt; SET_STRING(objPtr, stringPtr); } /* *---------------------------------------------------------------------- * * Tcl_NewStringObj -- * * This function is normally called when not debugging: i.e., when * TCL_MEM_DEBUG is not defined. It creates a new string object and * initializes it from the byte pointer and length arguments. * * When TCL_MEM_DEBUG is defined, this function just returns the result * of calling the debugging version Tcl_DbNewStringObj. * * Results: * A newly created string object is returned that has ref count zero. * * Side effects: * The new object's internal string representation will be set to a copy * of the length bytes starting at "bytes". If "length" is negative, use * bytes up to the first NUL byte; i.e., assume "bytes" points to a * C-style NUL-terminated string. The object's type is set to NULL. An * extra NUL is added to the end of the new object's byte array. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG #undef Tcl_NewStringObj Tcl_Obj * Tcl_NewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ int length) /* The number of bytes to copy from "bytes" * when initializing the new object. If * negative, use bytes up to the first NUL * byte. */ { return Tcl_DbNewStringObj(bytes, length, "unknown", 0); } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_NewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ int length) /* The number of bytes to copy from "bytes" * when initializing the new object. If * negative, use bytes up to the first NUL * byte. */ { Tcl_Obj *objPtr; if (length < 0) { length = (bytes? strlen(bytes) : 0); } TclNewStringObj(objPtr, bytes, length); return objPtr; } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_DbNewStringObj -- * * This function is normally called when debugging: i.e., when * TCL_MEM_DEBUG is defined. It creates new string objects. It is the * same as the Tcl_NewStringObj function above except that it calls * Tcl_DbCkalloc directly with the file name and line number from its * caller. This simplifies debugging since then the [memory active] * command will report the correct file name and line number when * reporting objects that haven't been freed. * * When TCL_MEM_DEBUG is not defined, this function just returns the * result of calling Tcl_NewStringObj. * * Results: * A newly created string object is returned that has ref count zero. * * Side effects: * The new object's internal string representation will be set to a copy * of the length bytes starting at "bytes". If "length" is negative, use * bytes up to the first NUL byte; i.e., assume "bytes" points to a * C-style NUL-terminated string. The object's type is set to NULL. An * extra NUL is added to the end of the new object's byte array. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_DbNewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ int length, /* The number of bytes to copy from "bytes" * when initializing the new object. If * negative, use bytes up to the first NUL * byte. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { Tcl_Obj *objPtr; if (length < 0) { length = (bytes? strlen(bytes) : 0); } TclDbNewObj(objPtr, file, line); TclInitStringRep(objPtr, bytes, length); return objPtr; } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_DbNewStringObj( const char *bytes, /* Points to the first of the length bytes * used to initialize the new object. */ int length, /* The number of bytes to copy from "bytes" * when initializing the new object. If * negative, use bytes up to the first NUL * byte. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { return Tcl_NewStringObj(bytes, length); } #endif /* TCL_MEM_DEBUG */ /* *--------------------------------------------------------------------------- * * Tcl_NewUnicodeObj -- * * This function is creates a new String object and initializes it from * the given Unicode String. If the Utf String is the same size as the * Unicode string, don't duplicate the data. * * Results: * The newly created object is returned. This object will have no initial * string representation. The returned object has a ref count of 0. * * Side effects: * Memory allocated for new object and copy of Unicode argument. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_NewUnicodeObj( const Tcl_UniChar *unicode, /* The unicode string used to initialize the * new object. */ int numChars) /* Number of characters in the unicode * string. */ { Tcl_Obj *objPtr; TclNewObj(objPtr); SetUnicodeObj(objPtr, unicode, numChars); return objPtr; } /* *---------------------------------------------------------------------- * * Tcl_GetCharLength -- * * Get the length of the Unicode string from the Tcl object. * * Results: * Pointer to unicode string representing the unicode object. * * Side effects: * Frees old internal rep. Allocates memory for new "String" internal * rep. * *---------------------------------------------------------------------- */ int Tcl_GetCharLength( Tcl_Obj *objPtr) /* The String object to get the num chars * of. */ { String *stringPtr; int numChars; /* * Optimize the case where we're really dealing with a bytearray object * without string representation; we don't need to convert to a string to * perform the get-length operation. */ if (TclIsPureByteArray(objPtr)) { int length; (void) Tcl_GetByteArrayFromObj(objPtr, &length); return length; } /* * OK, need to work with the object as a string. */ SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); numChars = stringPtr->numChars; /* * If numChars is unknown, compute it. */ if (numChars == -1) { TclNumUtfChars(numChars, objPtr->bytes, objPtr->length); stringPtr->numChars = numChars; #if COMPAT if (numChars < objPtr->length) { /* * Since we've just computed the number of chars, and not all UTF * chars are 1-byte long, go ahead and populate the unicode * string. */ FillUnicodeRep(objPtr); } #endif } return numChars; } /* *---------------------------------------------------------------------- * * Tcl_GetUniChar -- * * Get the index'th Unicode character from the String object. The index * is assumed to be in the appropriate range. * * Results: * Returns the index'th Unicode character in the Object. * * Side effects: * Fills unichar with the index'th Unicode character. * *---------------------------------------------------------------------- */ Tcl_UniChar Tcl_GetUniChar( Tcl_Obj *objPtr, /* The object to get the Unicode charater * from. */ int index) /* Get the index'th Unicode character. */ { String *stringPtr; /* * Optimize the case where we're really dealing with a bytearray object * without string representation; we don't need to convert to a string to * perform the indexing operation. */ if (TclIsPureByteArray(objPtr)) { unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, NULL); return (Tcl_UniChar) bytes[index]; } /* * OK, need to work with the object as a string. */ SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); if (stringPtr->hasUnicode == 0) { /* * If numChars is unknown, compute it. */ if (stringPtr->numChars == -1) { TclNumUtfChars(stringPtr->numChars, objPtr->bytes, objPtr->length); } if (stringPtr->numChars == objPtr->length) { return (Tcl_UniChar) objPtr->bytes[index]; } FillUnicodeRep(objPtr); stringPtr = GET_STRING(objPtr); } return stringPtr->unicode[index]; } /* *---------------------------------------------------------------------- * * Tcl_GetUnicode -- * * Get the Unicode form of the String object. If the object is not * already a String object, it will be converted to one. If the String * object does not have a Unicode rep, then one is create from the UTF * string format. * * Results: * Returns a pointer to the object's internal Unicode string. * * Side effects: * Converts the object to have the String internal rep. * *---------------------------------------------------------------------- */ Tcl_UniChar * Tcl_GetUnicode( Tcl_Obj *objPtr) /* The object to find the unicode string * for. */ { return Tcl_GetUnicodeFromObj(objPtr, NULL); } /* *---------------------------------------------------------------------- * * Tcl_GetUnicodeFromObj -- * * Get the Unicode form of the String object with length. If the object * is not already a String object, it will be converted to one. If the * String object does not have a Unicode rep, then one is create from the * UTF string format. * * Results: * Returns a pointer to the object's internal Unicode string. * * Side effects: * Converts the object to have the String internal rep. * *---------------------------------------------------------------------- */ Tcl_UniChar * Tcl_GetUnicodeFromObj( Tcl_Obj *objPtr, /* The object to find the unicode string * for. */ int *lengthPtr) /* If non-NULL, the location where the string * rep's unichar length should be stored. If * NULL, no length is stored. */ { String *stringPtr; SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); if (stringPtr->hasUnicode == 0) { FillUnicodeRep(objPtr); stringPtr = GET_STRING(objPtr); } if (lengthPtr != NULL) { *lengthPtr = stringPtr->numChars; } return stringPtr->unicode; } /* *---------------------------------------------------------------------- * * Tcl_GetRange -- * * Create a Tcl Object that contains the chars between first and last of * the object indicated by "objPtr". If the object is not already a * String object, convert it to one. The first and last indices are * assumed to be in the appropriate range. * * Results: * Returns a new Tcl Object of the String type. * * Side effects: * Changes the internal rep of "objPtr" to the String type. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_GetRange( Tcl_Obj *objPtr, /* The Tcl object to find the range of. */ int first, /* First index of the range. */ int last) /* Last index of the range. */ { Tcl_Obj *newObjPtr; /* The Tcl object to find the range of. */ String *stringPtr; /* * Optimize the case where we're really dealing with a bytearray object * without string representation; we don't need to convert to a string to * perform the substring operation. */ if (TclIsPureByteArray(objPtr)) { unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, NULL); return Tcl_NewByteArrayObj(bytes+first, last-first+1); } /* * OK, need to work with the object as a string. */ SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); if (stringPtr->hasUnicode == 0) { /* * If numChars is unknown, compute it. */ if (stringPtr->numChars == -1) { TclNumUtfChars(stringPtr->numChars, objPtr->bytes, objPtr->length); } if (stringPtr->numChars == objPtr->length) { newObjPtr = Tcl_NewStringObj(objPtr->bytes + first, last-first+1); /* * Since we know the char length of the result, store it. */ SetStringFromAny(NULL, newObjPtr); stringPtr = GET_STRING(newObjPtr); stringPtr->numChars = newObjPtr->length; return newObjPtr; } FillUnicodeRep(objPtr); stringPtr = GET_STRING(objPtr); } return Tcl_NewUnicodeObj(stringPtr->unicode + first, last-first+1); } /* *---------------------------------------------------------------------- * * Tcl_SetStringObj -- * * Modify an object to hold a string that is a copy of the bytes * indicated by the byte pointer and length arguments. * * Results: * None. * * Side effects: * The object's string representation will be set to a copy of the * "length" bytes starting at "bytes". If "length" is negative, use bytes * up to the first NUL byte; i.e., assume "bytes" points to a C-style * NUL-terminated string. The object's old string and internal * representations are freed and the object's type is set NULL. * *---------------------------------------------------------------------- */ void Tcl_SetStringObj( Tcl_Obj *objPtr, /* Object whose internal rep to init. */ const char *bytes, /* Points to the first of the length bytes * used to initialize the object. */ int length) /* The number of bytes to copy from "bytes" * when initializing the object. If negative, * use bytes up to the first NUL byte.*/ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetStringObj"); } /* * Set the type to NULL and free any internal rep for the old type. */ TclFreeIntRep(objPtr); /* * Free any old string rep, then set the string rep to a copy of the * length bytes starting at "bytes". */ TclInvalidateStringRep(objPtr); if (length < 0) { length = (bytes? strlen(bytes) : 0); } TclInitStringRep(objPtr, bytes, length); } /* *---------------------------------------------------------------------- * * Tcl_SetObjLength -- * * This function changes the length of the string representation of an * object. * * Results: * None. * * Side effects: * If the size of objPtr's string representation is greater than length, * then it is reduced to length and a new terminating null byte is stored * in the strength. If the length of the string representation is greater * than length, the storage space is reallocated to the given length; a * null byte is stored at the end, but other bytes past the end of the * original string representation are undefined. The object's internal * representation is changed to "expendable string". * *---------------------------------------------------------------------- */ void Tcl_SetObjLength( Tcl_Obj *objPtr, /* Pointer to object. This object must not * currently be shared. */ int length) /* Number of bytes desired for string * representation of object, not including * terminating null byte. */ { String *stringPtr; if (length < 0) { /* * Setting to a negative length is nonsense. This is probably the * result of overflowing the signed integer range. */ Tcl_Panic("Tcl_SetObjLength: negative length requested: " "%d (integer overflow?)", length); } if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetObjLength"); } if (objPtr->bytes && objPtr->length == length) { return; } SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); if (objPtr->bytes != NULL) { /* * Change length of an existing string rep. */ if (length > stringPtr->allocated) { /* * Need to enlarge the buffer. */ if (objPtr->bytes == tclEmptyStringRep) { objPtr->bytes = ckalloc(length + 1); } else { objPtr->bytes = ckrealloc(objPtr->bytes, length + 1); } stringPtr->allocated = length; } objPtr->length = length; objPtr->bytes[length] = 0; /* * Invalidate the unicode data. */ stringPtr->numChars = -1; stringPtr->hasUnicode = 0; } else { /* * Changing length of pure unicode string. */ stringCheckLimits(length); if (length > stringPtr->maxChars) { stringPtr = stringRealloc(stringPtr, length); SET_STRING(objPtr, stringPtr); stringPtr->maxChars = length; } /* * Mark the new end of the unicode string */ stringPtr->numChars = length; stringPtr->unicode[length] = 0; stringPtr->hasUnicode = 1; /* * Can only get here when objPtr->bytes == NULL. No need to invalidate * the string rep. */ } } /* *---------------------------------------------------------------------- * * Tcl_AttemptSetObjLength -- * * This function changes the length of the string representation of an * object. It uses the attempt* (non-panic'ing) memory allocators. * * Results: * 1 if the requested memory was allocated, 0 otherwise. * * Side effects: * If the size of objPtr's string representation is greater than length, * then it is reduced to length and a new terminating null byte is stored * in the strength. If the length of the string representation is greater * than length, the storage space is reallocated to the given length; a * null byte is stored at the end, but other bytes past the end of the * original string representation are undefined. The object's internal * representation is changed to "expendable string". * *---------------------------------------------------------------------- */ int Tcl_AttemptSetObjLength( Tcl_Obj *objPtr, /* Pointer to object. This object must not * currently be shared. */ int length) /* Number of bytes desired for string * representation of object, not including * terminating null byte. */ { String *stringPtr; if (length < 0) { /* * Setting to a negative length is nonsense. This is probably the * result of overflowing the signed integer range. */ return 0; } if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_AttemptSetObjLength"); } if (objPtr->bytes && objPtr->length == length) { return 1; } SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); if (objPtr->bytes != NULL) { /* * Change length of an existing string rep. */ if (length > stringPtr->allocated) { /* * Need to enlarge the buffer. */ char *newBytes; if (objPtr->bytes == tclEmptyStringRep) { newBytes = attemptckalloc(length + 1); } else { newBytes = attemptckrealloc(objPtr->bytes, length + 1); } if (newBytes == NULL) { return 0; } objPtr->bytes = newBytes; stringPtr->allocated = length; } objPtr->length = length; objPtr->bytes[length] = 0; /* * Invalidate the unicode data. */ stringPtr->numChars = -1; stringPtr->hasUnicode = 0; } else { /* * Changing length of pure unicode string. */ if (length > STRING_MAXCHARS) { return 0; } if (length > stringPtr->maxChars) { stringPtr = stringAttemptRealloc(stringPtr, length); if (stringPtr == NULL) { return 0; } SET_STRING(objPtr, stringPtr); stringPtr->maxChars = length; } /* * Mark the new end of the unicode string. */ stringPtr->unicode[length] = 0; stringPtr->numChars = length; stringPtr->hasUnicode = 1; /* * Can only get here when objPtr->bytes == NULL. No need to invalidate * the string rep. */ } return 1; } /* *--------------------------------------------------------------------------- * * Tcl_SetUnicodeObj -- * * Modify an object to hold the Unicode string indicated by "unicode". * * Results: * None. * * Side effects: * Memory allocated for new "String" internal rep. * *--------------------------------------------------------------------------- */ void Tcl_SetUnicodeObj( Tcl_Obj *objPtr, /* The object to set the string of. */ const Tcl_UniChar *unicode, /* The unicode string used to initialize the * object. */ int numChars) /* Number of characters in the unicode * string. */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetUnicodeObj"); } TclFreeIntRep(objPtr); SetUnicodeObj(objPtr, unicode, numChars); } static int UnicodeLength( const Tcl_UniChar *unicode) { int numChars = 0; if (unicode) { while (numChars >= 0 && unicode[numChars] != 0) { numChars++; } } stringCheckLimits(numChars); return numChars; } static void SetUnicodeObj( Tcl_Obj *objPtr, /* The object to set the string of. */ const Tcl_UniChar *unicode, /* The unicode string used to initialize the * object. */ int numChars) /* Number of characters in the unicode * string. */ { String *stringPtr; if (numChars < 0) { numChars = UnicodeLength(unicode); } /* * Allocate enough space for the String structure + Unicode string. */ stringCheckLimits(numChars); stringPtr = stringAlloc(numChars); SET_STRING(objPtr, stringPtr); objPtr->typePtr = &tclStringType; stringPtr->maxChars = numChars; memcpy(stringPtr->unicode, unicode, numChars * sizeof(Tcl_UniChar)); stringPtr->unicode[numChars] = 0; stringPtr->numChars = numChars; stringPtr->hasUnicode = 1; TclInvalidateStringRep(objPtr); stringPtr->allocated = 0; } /* *---------------------------------------------------------------------- * * Tcl_AppendLimitedToObj -- * * This function appends a limited number of bytes from a sequence of * bytes to an object, marking any limitation with an ellipsis. * * Results: * None. * * Side effects: * The bytes at *bytes are appended to the string representation of * objPtr. * *---------------------------------------------------------------------- */ void Tcl_AppendLimitedToObj( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* Points to the bytes to append to the * object. */ int length, /* The number of bytes available to be * appended from "bytes". If < 0, then all * bytes up to a NUL byte are available. */ int limit, /* The maximum number of bytes to append to * the object. */ const char *ellipsis) /* Ellipsis marker string, appended to the * object to indicate not all available bytes * at "bytes" were appended. */ { String *stringPtr; int toCopy = 0; if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_AppendLimitedToObj"); } if (length < 0) { length = (bytes ? strlen(bytes) : 0); } if (length == 0) { return; } if (length <= limit) { toCopy = length; } else { if (ellipsis == NULL) { ellipsis = "..."; } toCopy = (bytes == NULL) ? limit : Tcl_UtfPrev(bytes+limit+1-strlen(ellipsis), bytes) - bytes; } /* * If objPtr has a valid Unicode rep, then append the Unicode conversion * of "bytes" to the objPtr's Unicode rep, otherwise append "bytes" to * objPtr's string rep. */ SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); if (stringPtr->hasUnicode && stringPtr->numChars > 0) { AppendUtfToUnicodeRep(objPtr, bytes, toCopy); } else { AppendUtfToUtfRep(objPtr, bytes, toCopy); } if (length <= limit) { return; } stringPtr = GET_STRING(objPtr); if (stringPtr->hasUnicode && stringPtr->numChars > 0) { AppendUtfToUnicodeRep(objPtr, ellipsis, strlen(ellipsis)); } else { AppendUtfToUtfRep(objPtr, ellipsis, strlen(ellipsis)); } } /* *---------------------------------------------------------------------- * * Tcl_AppendToObj -- * * This function appends a sequence of bytes to an object. * * Results: * None. * * Side effects: * The bytes at *bytes are appended to the string representation of * objPtr. * *---------------------------------------------------------------------- */ void Tcl_AppendToObj( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* Points to the bytes to append to the * object. */ int length) /* The number of bytes to append from "bytes". * If < 0, then append all bytes up to NUL * byte. */ { Tcl_AppendLimitedToObj(objPtr, bytes, length, INT_MAX, NULL); } /* *---------------------------------------------------------------------- * * Tcl_AppendUnicodeToObj -- * * This function appends a Unicode string to an object in the most * efficient manner possible. Length must be >= 0. * * Results: * None. * * Side effects: * Invalidates the string rep and creates a new Unicode string. * *---------------------------------------------------------------------- */ void Tcl_AppendUnicodeToObj( Tcl_Obj *objPtr, /* Points to the object to append to. */ const Tcl_UniChar *unicode, /* The unicode string to append to the * object. */ int length) /* Number of chars in "unicode". */ { String *stringPtr; if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_AppendUnicodeToObj"); } if (length == 0) { return; } SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); /* * If objPtr has a valid Unicode rep, then append the "unicode" to the * objPtr's Unicode rep, otherwise the UTF conversion of "unicode" to * objPtr's string rep. */ if (stringPtr->hasUnicode #if COMPAT && stringPtr->numChars > 0 #endif ) { AppendUnicodeToUnicodeRep(objPtr, unicode, length); } else { AppendUnicodeToUtfRep(objPtr, unicode, length); } } /* *---------------------------------------------------------------------- * * Tcl_AppendObjToObj -- * * This function appends the string rep of one object to another. * "objPtr" cannot be a shared object. * * Results: * None. * * Side effects: * The string rep of appendObjPtr is appended to the string * representation of objPtr. * *---------------------------------------------------------------------- */ void Tcl_AppendObjToObj( Tcl_Obj *objPtr, /* Points to the object to append to. */ Tcl_Obj *appendObjPtr) /* Object to append. */ { String *stringPtr; int length, numChars, appendNumChars = -1; const char *bytes; /* * Special case: second object is standard-empty is fast case. We know * that appending nothing to anything leaves that starting anything... */ if (appendObjPtr->bytes == tclEmptyStringRep) { return; } /* * Handle append of one bytearray object to another as a special case. * Note that we only do this when the objects don't have string reps; if * it did, then appending the byte arrays together could well lose * information; this is a special-case optimization only. */ if ((TclIsPureByteArray(objPtr) || objPtr->bytes == tclEmptyStringRep) && TclIsPureByteArray(appendObjPtr)) { /* * You might expect the code here to be * * bytes = Tcl_GetByteArrayFromObj(appendObjPtr, &length); * TclAppendBytesToByteArray(objPtr, bytes, length); * * and essentially all of the time that would be fine. However, * it would run into trouble in the case where objPtr and * appendObjPtr point to the same thing. That may never be a * good idea. It seems to violate Copy On Write, and we don't * have any tests for the situation, since making any Tcl commands * that call Tcl_AppendObjToObj() do that appears impossible * (They honor Copy On Write!). For the sake of extensions that * go off into that realm, though, here's a more complex approach * that can handle all the cases. */ /* Get lengths */ int lengthSrc; (void) Tcl_GetByteArrayFromObj(objPtr, &length); (void) Tcl_GetByteArrayFromObj(appendObjPtr, &lengthSrc); /* Grow buffer enough for the append */ TclAppendBytesToByteArray(objPtr, NULL, lengthSrc); /* Reset objPtr back to the original value */ Tcl_SetByteArrayLength(objPtr, length); /* * Now do the append knowing that buffer growth cannot cause * any trouble. */ TclAppendBytesToByteArray(objPtr, Tcl_GetByteArrayFromObj(appendObjPtr, NULL), lengthSrc); return; } /* * Must append as strings. */ SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); /* * If objPtr has a valid Unicode rep, then get a Unicode string from * appendObjPtr and append it. */ if (stringPtr->hasUnicode #if COMPAT && stringPtr->numChars > 0 #endif ) { /* * If appendObjPtr is not of the "String" type, don't convert it. */ if (appendObjPtr->typePtr == &tclStringType) { Tcl_UniChar *unicode = Tcl_GetUnicodeFromObj(appendObjPtr, &numChars); AppendUnicodeToUnicodeRep(objPtr, unicode, numChars); } else { bytes = TclGetStringFromObj(appendObjPtr, &length); AppendUtfToUnicodeRep(objPtr, bytes, length); } return; } /* * Append to objPtr's UTF string rep. If we know the number of characters * in both objects before appending, then set the combined number of * characters in the final (appended-to) object. */ bytes = TclGetStringFromObj(appendObjPtr, &length); numChars = stringPtr->numChars; if ((numChars >= 0) && (appendObjPtr->typePtr == &tclStringType)) { String *appendStringPtr = GET_STRING(appendObjPtr); appendNumChars = appendStringPtr->numChars; } AppendUtfToUtfRep(objPtr, bytes, length); if (numChars >= 0 && appendNumChars >= 0 #if COMPAT && appendNumChars == length #endif ) { stringPtr->numChars = numChars + appendNumChars; } } /* *---------------------------------------------------------------------- * * AppendUnicodeToUnicodeRep -- * * This function appends the contents of "unicode" to the Unicode rep of * "objPtr". objPtr must already have a valid Unicode rep. * * Results: * None. * * Side effects: * objPtr's internal rep is reallocated. * *---------------------------------------------------------------------- */ static void AppendUnicodeToUnicodeRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const Tcl_UniChar *unicode, /* String to append. */ int appendNumChars) /* Number of chars of "unicode" to append. */ { String *stringPtr; int numChars; if (appendNumChars < 0) { appendNumChars = UnicodeLength(unicode); } if (appendNumChars == 0) { return; } SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); /* * If not enough space has been allocated for the unicode rep, reallocate * the internal rep object with additional space. First try to double the * required allocation; if that fails, try a more modest increase. See the * "TCL STRING GROWTH ALGORITHM" comment at the top of this file for an * explanation of this growth algorithm. */ numChars = stringPtr->numChars + appendNumChars; stringCheckLimits(numChars); if (numChars > stringPtr->maxChars) { int offset = -1; /* * Protect against case where unicode points into the existing * stringPtr->unicode array. Force it to follow any relocations due to * the reallocs below. */ if (unicode && unicode >= stringPtr->unicode && unicode <= stringPtr->unicode + stringPtr->maxChars) { offset = unicode - stringPtr->unicode; } GrowUnicodeBuffer(objPtr, numChars); stringPtr = GET_STRING(objPtr); /* * Relocate unicode if needed; see above. */ if (offset >= 0) { unicode = stringPtr->unicode + offset; } } /* * Copy the new string onto the end of the old string, then add the * trailing null. */ if (unicode) { memmove(stringPtr->unicode + stringPtr->numChars, unicode, appendNumChars * sizeof(Tcl_UniChar)); } stringPtr->unicode[numChars] = 0; stringPtr->numChars = numChars; stringPtr->allocated = 0; TclInvalidateStringRep(objPtr); } /* *---------------------------------------------------------------------- * * AppendUnicodeToUtfRep -- * * This function converts the contents of "unicode" to UTF and appends * the UTF to the string rep of "objPtr". * * Results: * None. * * Side effects: * objPtr's internal rep is reallocated. * *---------------------------------------------------------------------- */ static void AppendUnicodeToUtfRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const Tcl_UniChar *unicode, /* String to convert to UTF. */ int numChars) /* Number of chars of "unicode" to convert. */ { String *stringPtr = GET_STRING(objPtr); numChars = ExtendStringRepWithUnicode(objPtr, unicode, numChars); if (stringPtr->numChars != -1) { stringPtr->numChars += numChars; } #if COMPAT /* * Invalidate the unicode rep. */ stringPtr->hasUnicode = 0; #endif } /* *---------------------------------------------------------------------- * * AppendUtfToUnicodeRep -- * * This function converts the contents of "bytes" to Unicode and appends * the Unicode to the Unicode rep of "objPtr". objPtr must already have a * valid Unicode rep. numBytes must be non-negative. * * Results: * None. * * Side effects: * objPtr's internal rep is reallocated. * *---------------------------------------------------------------------- */ static void AppendUtfToUnicodeRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* String to convert to Unicode. */ int numBytes) /* Number of bytes of "bytes" to convert. */ { String *stringPtr; if (numBytes == 0) { return; } ExtendUnicodeRepWithString(objPtr, bytes, numBytes, -1); TclInvalidateStringRep(objPtr); stringPtr = GET_STRING(objPtr); stringPtr->allocated = 0; } /* *---------------------------------------------------------------------- * * AppendUtfToUtfRep -- * * This function appends "numBytes" bytes of "bytes" to the UTF string * rep of "objPtr". objPtr must already have a valid String rep. * numBytes must be non-negative. * * Results: * None. * * Side effects: * objPtr's internal rep is reallocated. * *---------------------------------------------------------------------- */ static void AppendUtfToUtfRep( Tcl_Obj *objPtr, /* Points to the object to append to. */ const char *bytes, /* String to append. */ int numBytes) /* Number of bytes of "bytes" to append. */ { String *stringPtr; int newLength, oldLength; if (numBytes == 0) { return; } /* * Copy the new string onto the end of the old string, then add the * trailing null. */ if (objPtr->bytes == NULL) { objPtr->length = 0; } oldLength = objPtr->length; newLength = numBytes + oldLength; if (newLength < 0) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } stringPtr = GET_STRING(objPtr); if (newLength > stringPtr->allocated) { int offset = -1; /* * Protect against case where unicode points into the existing * stringPtr->unicode array. Force it to follow any relocations due to * the reallocs below. */ if (bytes && bytes >= objPtr->bytes && bytes <= objPtr->bytes + objPtr->length) { offset = bytes - objPtr->bytes; } /* * TODO: consider passing flag=1: no overalloc on first append. This * would make test stringObj-8.1 fail. */ GrowStringBuffer(objPtr, newLength, 0); /* * Relocate bytes if needed; see above. */ if (offset >= 0) { bytes = objPtr->bytes + offset; } } /* * Invalidate the unicode data. */ stringPtr->numChars = -1; stringPtr->hasUnicode = 0; if (bytes) { memmove(objPtr->bytes + oldLength, bytes, numBytes); } objPtr->bytes[newLength] = 0; objPtr->length = newLength; } /* *---------------------------------------------------------------------- * * Tcl_AppendStringsToObjVA -- * * This function appends one or more null-terminated strings to an * object. * * Results: * None. * * Side effects: * The contents of all the string arguments are appended to the string * representation of objPtr. * *---------------------------------------------------------------------- */ void Tcl_AppendStringsToObjVA( Tcl_Obj *objPtr, /* Points to the object to append to. */ va_list argList) /* Variable argument list. */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_AppendStringsToObj"); } while (1) { const char *bytes = va_arg(argList, char *); if (bytes == NULL) { break; } Tcl_AppendToObj(objPtr, bytes, -1); } } /* *---------------------------------------------------------------------- * * Tcl_AppendStringsToObj -- * * This function appends one or more null-terminated strings to an * object. * * Results: * None. * * Side effects: * The contents of all the string arguments are appended to the string * representation of objPtr. * *---------------------------------------------------------------------- */ void Tcl_AppendStringsToObj( Tcl_Obj *objPtr, ...) { va_list argList; va_start(argList, objPtr); Tcl_AppendStringsToObjVA(objPtr, argList); va_end(argList); } /* *---------------------------------------------------------------------- * * Tcl_AppendFormatToObj -- * * This function appends a list of Tcl_Obj's to a Tcl_Obj according to * the formatting instructions embedded in the format string. The * formatting instructions are inspired by sprintf(). Returns TCL_OK when * successful. If there's an error in the arguments, TCL_ERROR is * returned, and an error message is written to the interp, if non-NULL. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_AppendFormatToObj( Tcl_Interp *interp, Tcl_Obj *appendObj, const char *format, int objc, Tcl_Obj *const objv[]) { const char *span = format, *msg, *errCode; int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0; int originalLength, limit; static const char *mixedXPG = "cannot mix \"%\" and \"%n$\" conversion specifiers"; static const char *const badIndex[2] = { "not enough arguments for all format specifiers", "\"%n$\" argument index out of range" }; static const char *overflow = "max size for a Tcl value exceeded"; if (Tcl_IsShared(appendObj)) { Tcl_Panic("%s called with shared object", "Tcl_AppendFormatToObj"); } TclGetStringFromObj(appendObj, &originalLength); limit = INT_MAX - originalLength; /* * Format string is NUL-terminated. */ while (*format != '\0') { char *end; int gotMinus, gotHash, gotZero, gotSpace, gotPlus, sawFlag; int width, gotPrecision, precision, useShort, useWide, useBig; int newXpg, numChars, allocSegment = 0, segmentLimit, segmentNumBytes; Tcl_Obj *segment; Tcl_UniChar ch; int step = Tcl_UtfToUniChar(format, &ch); format += step; if (ch != '%') { numBytes += step; continue; } if (numBytes) { if (numBytes > limit) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } Tcl_AppendToObj(appendObj, span, numBytes); limit -= numBytes; numBytes = 0; } /* * Saw a % : process the format specifier. * * Step 0. Handle special case of escaped format marker (i.e., %%). */ step = Tcl_UtfToUniChar(format, &ch); if (ch == '%') { span = format; numBytes = step; format += step; continue; } /* * Step 1. XPG3 position specifier */ newXpg = 0; if (isdigit(UCHAR(ch))) { int position = strtoul(format, &end, 10); if (*end == '$') { newXpg = 1; objIndex = position - 1; format = end + 1; step = Tcl_UtfToUniChar(format, &ch); } } if (newXpg) { if (gotSequential) { msg = mixedXPG; errCode = "MIXEDSPECTYPES"; goto errorMsg; } gotXpg = 1; } else { if (gotXpg) { msg = mixedXPG; errCode = "MIXEDSPECTYPES"; goto errorMsg; } gotSequential = 1; } if ((objIndex < 0) || (objIndex >= objc)) { msg = badIndex[gotXpg]; errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH"; goto errorMsg; } /* * Step 2. Set of flags. */ gotMinus = gotHash = gotZero = gotSpace = gotPlus = 0; sawFlag = 1; do { switch (ch) { case '-': gotMinus = 1; break; case '#': gotHash = 1; break; case '0': gotZero = 1; break; case ' ': gotSpace = 1; break; case '+': gotPlus = 1; break; default: sawFlag = 0; } if (sawFlag) { format += step; step = Tcl_UtfToUniChar(format, &ch); } } while (sawFlag); /* * Step 3. Minimum field width. */ width = 0; if (isdigit(UCHAR(ch))) { width = strtoul(format, &end, 10); format = end; step = Tcl_UtfToUniChar(format, &ch); } else if (ch == '*') { if (objIndex >= objc - 1) { msg = badIndex[gotXpg]; errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH"; goto errorMsg; } if (TclGetIntFromObj(interp, objv[objIndex], &width) != TCL_OK) { goto error; } if (width < 0) { width = -width; gotMinus = 1; } objIndex++; format += step; step = Tcl_UtfToUniChar(format, &ch); } if (width > limit) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } /* * Step 4. Precision. */ gotPrecision = precision = 0; if (ch == '.') { gotPrecision = 1; format += step; step = Tcl_UtfToUniChar(format, &ch); } if (isdigit(UCHAR(ch))) { precision = strtoul(format, &end, 10); format = end; step = Tcl_UtfToUniChar(format, &ch); } else if (ch == '*') { if (objIndex >= objc - 1) { msg = badIndex[gotXpg]; errCode = gotXpg ? "INDEXRANGE" : "FIELDVARMISMATCH"; goto errorMsg; } if (TclGetIntFromObj(interp, objv[objIndex], &precision) != TCL_OK) { goto error; } /* * TODO: Check this truncation logic. */ if (precision < 0) { precision = 0; } objIndex++; format += step; step = Tcl_UtfToUniChar(format, &ch); } /* * Step 5. Length modifier. */ useShort = useWide = useBig = 0; if (ch == 'h') { useShort = 1; format += step; step = Tcl_UtfToUniChar(format, &ch); } else if (ch == 'l') { format += step; step = Tcl_UtfToUniChar(format, &ch); if (ch == 'l') { useBig = 1; format += step; step = Tcl_UtfToUniChar(format, &ch); #ifndef TCL_WIDE_INT_IS_LONG } else { useWide = 1; #endif } } format += step; span = format; /* * Step 6. The actual conversion character. */ segment = objv[objIndex]; numChars = -1; if (ch == 'i') { ch = 'd'; } switch (ch) { case '\0': msg = "format string ended in middle of field specifier"; errCode = "INCOMPLETE"; goto errorMsg; case 's': if (gotPrecision) { numChars = Tcl_GetCharLength(segment); if (precision < numChars) { segment = Tcl_GetRange(segment, 0, precision - 1); numChars = precision; Tcl_IncrRefCount(segment); allocSegment = 1; } } break; case 'c': { char buf[TCL_UTF_MAX]; int code, length; if (TclGetIntFromObj(interp, segment, &code) != TCL_OK) { goto error; } length = Tcl_UniCharToUtf(code, buf); segment = Tcl_NewStringObj(buf, length); Tcl_IncrRefCount(segment); allocSegment = 1; break; } case 'u': if (useBig) { msg = "unsigned bignum format is invalid"; errCode = "BADUNSIGNED"; goto errorMsg; } case 'd': case 'o': case 'x': case 'X': case 'b': { short s = 0; /* Silence compiler warning; only defined and * used when useShort is true. */ long l; Tcl_WideInt w; mp_int big; int toAppend, isNegative = 0; if (useBig) { if (Tcl_GetBignumFromObj(interp, segment, &big) != TCL_OK) { goto error; } isNegative = (mp_cmp_d(&big, 0) == MP_LT); } else if (useWide) { if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) { Tcl_Obj *objPtr; if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) { goto error; } mp_mod_2d(&big, (int) CHAR_BIT*sizeof(Tcl_WideInt), &big); objPtr = Tcl_NewBignumObj(&big); Tcl_IncrRefCount(objPtr); Tcl_GetWideIntFromObj(NULL, objPtr, &w); Tcl_DecrRefCount(objPtr); } isNegative = (w < (Tcl_WideInt) 0); } else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) { if (Tcl_GetWideIntFromObj(NULL, segment, &w) != TCL_OK) { Tcl_Obj *objPtr; if (Tcl_GetBignumFromObj(interp,segment,&big) != TCL_OK) { goto error; } mp_mod_2d(&big, (int) CHAR_BIT * sizeof(long), &big); objPtr = Tcl_NewBignumObj(&big); Tcl_IncrRefCount(objPtr); TclGetLongFromObj(NULL, objPtr, &l); Tcl_DecrRefCount(objPtr); } else { l = Tcl_WideAsLong(w); } if (useShort) { s = (short) l; isNegative = (s < (short) 0); } else { isNegative = (l < (long) 0); } } else if (useShort) { s = (short) l; isNegative = (s < (short) 0); } else { isNegative = (l < (long) 0); } segment = Tcl_NewObj(); allocSegment = 1; segmentLimit = INT_MAX; Tcl_IncrRefCount(segment); if ((isNegative || gotPlus || gotSpace) && (useBig || ch=='d')) { Tcl_AppendToObj(segment, (isNegative ? "-" : gotPlus ? "+" : " "), 1); segmentLimit -= 1; } if (gotHash) { switch (ch) { case 'o': Tcl_AppendToObj(segment, "0", 1); segmentLimit -= 1; precision--; break; case 'x': case 'X': Tcl_AppendToObj(segment, "0x", 2); segmentLimit -= 2; break; case 'b': Tcl_AppendToObj(segment, "0b", 2); segmentLimit -= 2; break; } } switch (ch) { case 'd': { int length; Tcl_Obj *pure; const char *bytes; if (useShort) { pure = Tcl_NewIntObj((int) s); } else if (useWide) { pure = Tcl_NewWideIntObj(w); } else if (useBig) { pure = Tcl_NewBignumObj(&big); } else { pure = Tcl_NewLongObj(l); } Tcl_IncrRefCount(pure); bytes = TclGetStringFromObj(pure, &length); /* * Already did the sign above. */ if (*bytes == '-') { length--; bytes++; } toAppend = length; /* * Canonical decimal string reps for integers are composed * entirely of one-byte encoded characters, so "length" is the * number of chars. */ if (gotPrecision) { if (length < precision) { segmentLimit -= precision - length; } while (length < precision) { Tcl_AppendToObj(segment, "0", 1); length++; } gotZero = 0; } if (gotZero) { length += Tcl_GetCharLength(segment); if (length < width) { segmentLimit -= width - length; } while (length < width) { Tcl_AppendToObj(segment, "0", 1); length++; } } if (toAppend > segmentLimit) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } Tcl_AppendToObj(segment, bytes, toAppend); Tcl_DecrRefCount(pure); break; } case 'u': case 'o': case 'x': case 'X': case 'b': { Tcl_WideUInt bits = (Tcl_WideUInt) 0; Tcl_WideInt numDigits = (Tcl_WideInt) 0; int length, numBits = 4, base = 16, index = 0, shift = 0; Tcl_Obj *pure; char *bytes; if (ch == 'u') { base = 10; } else if (ch == 'o') { base = 8; numBits = 3; } else if (ch == 'b') { base = 2; numBits = 1; } if (useShort) { unsigned short us = (unsigned short) s; bits = (Tcl_WideUInt) us; while (us) { numDigits++; us /= base; } } else if (useWide) { Tcl_WideUInt uw = (Tcl_WideUInt) w; bits = uw; while (uw) { numDigits++; uw /= base; } } else if (useBig && big.used) { int leftover = (big.used * DIGIT_BIT) % numBits; mp_digit mask = (~(mp_digit)0) << (DIGIT_BIT-leftover); numDigits = 1 + (((Tcl_WideInt) big.used * DIGIT_BIT) / numBits); while ((mask & big.dp[big.used-1]) == 0) { numDigits--; mask >>= numBits; } if (numDigits > INT_MAX) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } } else if (!useBig) { unsigned long ul = (unsigned long) l; bits = (Tcl_WideUInt) ul; while (ul) { numDigits++; ul /= base; } } /* * Need to be sure zero becomes "0", not "". */ if ((numDigits == 0) && !((ch == 'o') && gotHash)) { numDigits = 1; } pure = Tcl_NewObj(); Tcl_SetObjLength(pure, (int) numDigits); bytes = TclGetString(pure); toAppend = length = (int) numDigits; while (numDigits--) { int digitOffset; if (useBig && big.used) { if (index < big.used && (size_t) shift < CHAR_BIT*sizeof(Tcl_WideUInt) - DIGIT_BIT) { bits |= ((Tcl_WideUInt) big.dp[index++]) << shift; shift += DIGIT_BIT; } shift -= numBits; } digitOffset = (int) (bits % base); if (digitOffset > 9) { bytes[numDigits] = 'a' + digitOffset - 10; } else { bytes[numDigits] = '0' + digitOffset; } bits /= base; } if (useBig) { mp_clear(&big); } if (gotPrecision) { if (length < precision) { segmentLimit -= precision - length; } while (length < precision) { Tcl_AppendToObj(segment, "0", 1); length++; } gotZero = 0; } if (gotZero) { length += Tcl_GetCharLength(segment); if (length < width) { segmentLimit -= width - length; } while (length < width) { Tcl_AppendToObj(segment, "0", 1); length++; } } if (toAppend > segmentLimit) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } Tcl_AppendObjToObj(segment, pure); Tcl_DecrRefCount(pure); break; } } break; } case 'e': case 'E': case 'f': case 'g': case 'G': { #define MAX_FLOAT_SIZE 320 char spec[2*TCL_INTEGER_SPACE + 9], *p = spec; double d; int length = MAX_FLOAT_SIZE; char *bytes; if (Tcl_GetDoubleFromObj(interp, segment, &d) != TCL_OK) { /* TODO: Figure out ACCEPT_NAN here */ goto error; } *p++ = '%'; if (gotMinus) { *p++ = '-'; } if (gotHash) { *p++ = '#'; } if (gotZero) { *p++ = '0'; } if (gotSpace) { *p++ = ' '; } if (gotPlus) { *p++ = '+'; } if (width) { p += sprintf(p, "%d", width); if (width > length) { length = width; } } if (gotPrecision) { *p++ = '.'; p += sprintf(p, "%d", precision); if (precision > INT_MAX - length) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } length += precision; } /* * Don't pass length modifiers! */ *p++ = (char) ch; *p = '\0'; segment = Tcl_NewObj(); allocSegment = 1; if (!Tcl_AttemptSetObjLength(segment, length)) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } bytes = TclGetString(segment); if (!Tcl_AttemptSetObjLength(segment, sprintf(bytes, spec, d))) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } break; } default: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad field specifier \"%c\"", ch)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", NULL); } goto error; } switch (ch) { case 'E': case 'G': case 'X': { Tcl_SetObjLength(segment, Tcl_UtfToUpper(TclGetString(segment))); } } if (width>0 && numChars<0) { numChars = Tcl_GetCharLength(segment); } if (!gotMinus && width>0) { if (numChars < width) { limit -= width - numChars; } while (numChars < width) { Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1); numChars++; } } Tcl_GetStringFromObj(segment, &segmentNumBytes); if (segmentNumBytes > limit) { if (allocSegment) { Tcl_DecrRefCount(segment); } msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } Tcl_AppendObjToObj(appendObj, segment); limit -= segmentNumBytes; if (allocSegment) { Tcl_DecrRefCount(segment); } if (width > 0) { if (numChars < width) { limit -= width-numChars; } while (numChars < width) { Tcl_AppendToObj(appendObj, (gotZero ? "0" : " "), 1); numChars++; } } objIndex += gotSequential; } if (numBytes) { if (numBytes > limit) { msg = overflow; errCode = "OVERFLOW"; goto errorMsg; } Tcl_AppendToObj(appendObj, span, numBytes); limit -= numBytes; numBytes = 0; } return TCL_OK; errorMsg: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", errCode, NULL); } error: Tcl_SetObjLength(appendObj, originalLength); return TCL_ERROR; } /* *--------------------------------------------------------------------------- * * Tcl_Format-- * * Results: * A refcount zero Tcl_Obj. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_Format( Tcl_Interp *interp, const char *format, int objc, Tcl_Obj *const objv[]) { int result; Tcl_Obj *objPtr = Tcl_NewObj(); result = Tcl_AppendFormatToObj(interp, objPtr, format, objc, objv); if (result != TCL_OK) { Tcl_DecrRefCount(objPtr); return NULL; } return objPtr; } /* *--------------------------------------------------------------------------- * * AppendPrintfToObjVA -- * * Results: * * Side effects: * *--------------------------------------------------------------------------- */ static void AppendPrintfToObjVA( Tcl_Obj *objPtr, const char *format, va_list argList) { int code, objc; Tcl_Obj **objv, *list = Tcl_NewObj(); const char *p; p = format; Tcl_IncrRefCount(list); while (*p != '\0') { int size = 0, seekingConversion = 1, gotPrecision = 0; int lastNum = -1; if (*p++ != '%') { continue; } if (*p == '%') { p++; continue; } do { switch (*p) { case '\0': seekingConversion = 0; break; case 's': { const char *q, *end, *bytes = va_arg(argList, char *); seekingConversion = 0; /* * The buffer to copy characters from starts at bytes and ends * at either the first NUL byte, or after lastNum bytes, when * caller has indicated a limit. */ end = bytes; while ((!gotPrecision || lastNum--) && (*end != '\0')) { end++; } /* * Within that buffer, we trim both ends if needed so that we * copy only whole characters, and avoid copying any partial * multi-byte characters. */ q = Tcl_UtfPrev(end, bytes); if (!Tcl_UtfCharComplete(q, (int)(end - q))) { end = q; } q = bytes + TCL_UTF_MAX; while ((bytes < end) && (bytes < q) && ((*bytes & 0xC0) == 0x80)) { bytes++; } Tcl_ListObjAppendElement(NULL, list, Tcl_NewStringObj(bytes , (int)(end - bytes))); break; } case 'c': case 'i': case 'u': case 'd': case 'o': case 'x': case 'X': seekingConversion = 0; switch (size) { case -1: case 0: Tcl_ListObjAppendElement(NULL, list, Tcl_NewLongObj( (long) va_arg(argList, int))); break; case 1: Tcl_ListObjAppendElement(NULL, list, Tcl_NewLongObj( va_arg(argList, long))); break; } break; case 'e': case 'E': case 'f': case 'g': case 'G': Tcl_ListObjAppendElement(NULL, list, Tcl_NewDoubleObj( va_arg(argList, double))); seekingConversion = 0; break; case '*': lastNum = (int) va_arg(argList, int); Tcl_ListObjAppendElement(NULL, list, Tcl_NewIntObj(lastNum)); p++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { char *end; lastNum = (int) strtoul(p, &end, 10); p = end; break; } case '.': gotPrecision = 1; p++; break; /* TODO: support for wide (and bignum?) arguments */ case 'l': size = 1; p++; break; case 'h': size = -1; default: p++; } } while (seekingConversion); } TclListObjGetElements(NULL, list, &objc, &objv); code = Tcl_AppendFormatToObj(NULL, objPtr, format, objc, objv); if (code != TCL_OK) { Tcl_AppendPrintfToObj(objPtr, "Unable to format \"%s\" with supplied arguments: %s", format, Tcl_GetString(list)); } Tcl_DecrRefCount(list); } /* *--------------------------------------------------------------------------- * * Tcl_AppendPrintfToObj -- * * Results: * A standard Tcl result. * * Side effects: * None. * *--------------------------------------------------------------------------- */ void Tcl_AppendPrintfToObj( Tcl_Obj *objPtr, const char *format, ...) { va_list argList; va_start(argList, format); AppendPrintfToObjVA(objPtr, format, argList); va_end(argList); } /* *--------------------------------------------------------------------------- * * Tcl_ObjPrintf -- * * Results: * A refcount zero Tcl_Obj. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_ObjPrintf( const char *format, ...) { va_list argList; Tcl_Obj *objPtr = Tcl_NewObj(); va_start(argList, format); AppendPrintfToObjVA(objPtr, format, argList); va_end(argList); return objPtr; } /* *--------------------------------------------------------------------------- * * TclGetStringStorage -- * * Returns the string storage space of a Tcl_Obj. * * Results: * The pointer value objPtr->bytes is returned and the number of bytes * allocated there is written to *sizePtr (if known). * * Side effects: * May set objPtr->bytes. * *--------------------------------------------------------------------------- */ char * TclGetStringStorage( Tcl_Obj *objPtr, unsigned int *sizePtr) { String *stringPtr; if (objPtr->typePtr != &tclStringType || objPtr->bytes == NULL) { return TclGetStringFromObj(objPtr, (int *)sizePtr); } stringPtr = GET_STRING(objPtr); *sizePtr = stringPtr->allocated; return objPtr->bytes; } /* *--------------------------------------------------------------------------- * * TclStringObjReverse -- * * Implements the [string reverse] operation. * * Results: * An unshared Tcl value which is the [string reverse] of the argument * supplied. When sharing rules permit, the returned value might be the * argument with modifications done in place. * * Side effects: * May allocate a new Tcl_Obj. * *--------------------------------------------------------------------------- */ static void ReverseBytes( unsigned char *to, /* Copy bytes into here... */ unsigned char *from, /* ...from here... */ int count) /* Until this many are copied, */ /* reversing as you go. */ { unsigned char *src = from + count; if (to == from) { /* Reversing in place */ while (--src > to) { unsigned char c = *src; *src = *to; *to++ = c; } } else { while (--src >= from) { *to++ = *src; } } } Tcl_Obj * TclStringObjReverse( Tcl_Obj *objPtr) { String *stringPtr; Tcl_UniChar ch; if (TclIsPureByteArray(objPtr)) { int numBytes; unsigned char *from = Tcl_GetByteArrayFromObj(objPtr, &numBytes); if (Tcl_IsShared(objPtr)) { objPtr = Tcl_NewByteArrayObj(NULL, numBytes); } ReverseBytes(Tcl_GetByteArrayFromObj(objPtr, NULL), from, numBytes); return objPtr; } SetStringFromAny(NULL, objPtr); stringPtr = GET_STRING(objPtr); if (stringPtr->hasUnicode) { Tcl_UniChar *from = Tcl_GetUnicode(objPtr); Tcl_UniChar *src = from + stringPtr->numChars; if (Tcl_IsShared(objPtr)) { Tcl_UniChar *to; /* * Create a non-empty, pure unicode value, so we can coax * Tcl_SetObjLength into growing the unicode rep buffer. */ ch = 0; objPtr = Tcl_NewUnicodeObj(&ch, 1); Tcl_SetObjLength(objPtr, stringPtr->numChars); to = Tcl_GetUnicode(objPtr); while (--src >= from) { *to++ = *src; } } else { /* Reversing in place */ while (--src > from) { ch = *src; *src = *from; *from++ = ch; } } } if (objPtr->bytes) { int numChars = stringPtr->numChars; int numBytes = objPtr->length; char *to, *from = objPtr->bytes; if (Tcl_IsShared(objPtr)) { objPtr = Tcl_NewObj(); Tcl_SetObjLength(objPtr, numBytes); } to = objPtr->bytes; if (numChars < numBytes) { /* * Either numChars == -1 and we don't know how many chars are * represented by objPtr->bytes and we need Pass 1 just in case, * or numChars >= 0 and we know we have fewer chars than bytes, * so we know there's a multibyte character needing Pass 1. * * Pass 1. Reverse the bytes of each multi-byte character. */ int charCount = 0; int bytesLeft = numBytes; while (bytesLeft) { /* * NOTE: We know that the from buffer is NUL-terminated. * It's part of the contract for objPtr->bytes values. * Thus, we can skip calling Tcl_UtfCharComplete() here. */ int bytesInChar = Tcl_UtfToUniChar(from, &ch); ReverseBytes((unsigned char *)to, (unsigned char *)from, bytesInChar); to += bytesInChar; from += bytesInChar; bytesLeft -= bytesInChar; charCount++; } from = to = objPtr->bytes; stringPtr->numChars = charCount; } /* Pass 2. Reverse all the bytes. */ ReverseBytes((unsigned char *)to, (unsigned char *)from, numBytes); } return objPtr; } /* *--------------------------------------------------------------------------- * * FillUnicodeRep -- * * Populate the Unicode internal rep with the Unicode form of its string * rep. The object must alread have a "String" internal rep. * * Results: * None. * * Side effects: * Reallocates the String internal rep. * *--------------------------------------------------------------------------- */ static void FillUnicodeRep( Tcl_Obj *objPtr) /* The object in which to fill the unicode * rep. */ { String *stringPtr = GET_STRING(objPtr); ExtendUnicodeRepWithString(objPtr, objPtr->bytes, objPtr->length, stringPtr->numChars); } static void ExtendUnicodeRepWithString( Tcl_Obj *objPtr, const char *bytes, int numBytes, int numAppendChars) { String *stringPtr = GET_STRING(objPtr); int needed, numOrigChars = 0; Tcl_UniChar *dst; if (stringPtr->hasUnicode) { numOrigChars = stringPtr->numChars; } if (numAppendChars == -1) { TclNumUtfChars(numAppendChars, bytes, numBytes); } needed = numOrigChars + numAppendChars; stringCheckLimits(needed); if (needed > stringPtr->maxChars) { GrowUnicodeBuffer(objPtr, needed); stringPtr = GET_STRING(objPtr); } stringPtr->hasUnicode = 1; if (bytes) { stringPtr->numChars = needed; } else { numAppendChars = 0; } for (dst=stringPtr->unicode + numOrigChars; numAppendChars-- > 0; dst++) { bytes += TclUtfToUniChar(bytes, dst); } *dst = 0; } /* *---------------------------------------------------------------------- * * DupStringInternalRep -- * * Initialize the internal representation of a new Tcl_Obj to a copy of * the internal representation of an existing string object. * * Results: * None. * * Side effects: * copyPtr's internal rep is set to a copy of srcPtr's internal * representation. * *---------------------------------------------------------------------- */ static void DupStringInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. Must have * an internal rep of type "String". */ Tcl_Obj *copyPtr) /* Object with internal rep to set. Must not * currently have an internal rep.*/ { String *srcStringPtr = GET_STRING(srcPtr); String *copyStringPtr = NULL; #if COMPAT==0 if (srcStringPtr->numChars == -1) { /* * The String struct in the source value holds zero useful data. Don't * bother copying it. Don't even bother allocating space in which to * copy it. Just let the copy be untyped. */ return; } if (srcStringPtr->hasUnicode) { int copyMaxChars; if (srcStringPtr->maxChars / 2 >= srcStringPtr->numChars) { copyMaxChars = 2 * srcStringPtr->numChars; } else { copyMaxChars = srcStringPtr->maxChars; } copyStringPtr = stringAttemptAlloc(copyMaxChars); if (copyStringPtr == NULL) { copyMaxChars = srcStringPtr->numChars; copyStringPtr = stringAlloc(copyMaxChars); } copyStringPtr->maxChars = copyMaxChars; memcpy(copyStringPtr->unicode, srcStringPtr->unicode, srcStringPtr->numChars * sizeof(Tcl_UniChar)); copyStringPtr->unicode[srcStringPtr->numChars] = 0; } else { copyStringPtr = stringAlloc(0); copyStringPtr->maxChars = 0; copyStringPtr->unicode[0] = 0; } copyStringPtr->hasUnicode = srcStringPtr->hasUnicode; copyStringPtr->numChars = srcStringPtr->numChars; /* * Tricky point: the string value was copied by generic object management * code, so it doesn't contain any extra bytes that might exist in the * source object. */ copyStringPtr->allocated = copyPtr->bytes ? copyPtr->length : 0; #else /* COMPAT!=0 */ /* * If the src obj is a string of 1-byte Utf chars, then copy the string * rep of the source object and create an "empty" Unicode internal rep for * the new object. Otherwise, copy Unicode internal rep, and invalidate * the string rep of the new object. */ if (srcStringPtr->hasUnicode && srcStringPtr->numChars > 0) { /* * Copy the full allocation for the Unicode buffer. */ copyStringPtr = stringAlloc(srcStringPtr->maxChars); copyStringPtr->maxChars = srcStringPtr->maxChars; memcpy(copyStringPtr->unicode, srcStringPtr->unicode, srcStringPtr->numChars * sizeof(Tcl_UniChar)); copyStringPtr->unicode[srcStringPtr->numChars] = 0; copyStringPtr->allocated = 0; } else { copyStringPtr = stringAlloc(0); copyStringPtr->unicode[0] = 0; copyStringPtr->maxChars = 0; /* * Tricky point: the string value was copied by generic object * management code, so it doesn't contain any extra bytes that might * exist in the source object. */ copyStringPtr->allocated = copyPtr->length; } copyStringPtr->numChars = srcStringPtr->numChars; copyStringPtr->hasUnicode = srcStringPtr->hasUnicode; #endif /* COMPAT==0 */ SET_STRING(copyPtr, copyStringPtr); copyPtr->typePtr = &tclStringType; } /* *---------------------------------------------------------------------- * * SetStringFromAny -- * * Create an internal representation of type "String" for an object. * * Results: * This operation always succeeds and returns TCL_OK. * * Side effects: * Any old internal reputation for objPtr is freed and the internal * representation is set to "String". * *---------------------------------------------------------------------- */ static int SetStringFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr) /* The object to convert. */ { if (objPtr->typePtr != &tclStringType) { String *stringPtr = stringAlloc(0); /* * Convert whatever we have into an untyped value. Just A String. */ (void) TclGetString(objPtr); TclFreeIntRep(objPtr); /* * Create a basic String intrep that just points to the UTF-8 string * already in place at objPtr->bytes. */ stringPtr->numChars = -1; stringPtr->allocated = objPtr->length; stringPtr->maxChars = 0; stringPtr->hasUnicode = 0; SET_STRING(objPtr, stringPtr); objPtr->typePtr = &tclStringType; } return TCL_OK; } /* *---------------------------------------------------------------------- * * UpdateStringOfString -- * * Update the string representation for an object whose internal * representation is "String". * * Results: * None. * * Side effects: * The object's string may be set by converting its Unicode represention * to UTF format. * *---------------------------------------------------------------------- */ static void UpdateStringOfString( Tcl_Obj *objPtr) /* Object with string rep to update. */ { String *stringPtr = GET_STRING(objPtr); if (stringPtr->numChars == 0) { TclInitStringRep(objPtr, tclEmptyStringRep, 0); } else { (void) ExtendStringRepWithUnicode(objPtr, stringPtr->unicode, stringPtr->numChars); } } static int ExtendStringRepWithUnicode( Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int numChars) { /* * Pre-condition: this is the "string" Tcl_ObjType. */ int i, origLength, size = 0; char *dst, buf[TCL_UTF_MAX]; String *stringPtr = GET_STRING(objPtr); if (numChars < 0) { numChars = UnicodeLength(unicode); } if (numChars == 0) { return 0; } if (objPtr->bytes == NULL) { objPtr->length = 0; } size = origLength = objPtr->length; /* * Quick cheap check in case we have more than enough room. */ if (numChars <= (INT_MAX - size)/TCL_UTF_MAX && stringPtr->allocated >= size + numChars * TCL_UTF_MAX) { goto copyBytes; } for (i = 0; i < numChars && size >= 0; i++) { size += Tcl_UniCharToUtf((int) unicode[i], buf); } if (size < 0) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } /* * Grow space if needed. */ if (size > stringPtr->allocated) { GrowStringBuffer(objPtr, size, 1); } copyBytes: dst = objPtr->bytes + origLength; for (i = 0; i < numChars; i++) { dst += Tcl_UniCharToUtf((int) unicode[i], dst); } *dst = '\0'; objPtr->length = dst - objPtr->bytes; return numChars; } /* *---------------------------------------------------------------------- * * FreeStringInternalRep -- * * Deallocate the storage associated with a String data object's internal * representation. * * Results: * None. * * Side effects: * Frees memory. * *---------------------------------------------------------------------- */ static void FreeStringInternalRep( Tcl_Obj *objPtr) /* Object with internal rep to free. */ { ckfree(GET_STRING(objPtr)); objPtr->typePtr = NULL; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclEvent.c0000644000175000017500000012455712663660065015151 0ustar sergeisergei/* * tclEvent.c -- * * This file implements some general event related interfaces including * background errors, exit handlers, and the "vwait" and "update" command * functions. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 2004 by Zoran Vasiljevic. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * The data structure below is used to report background errors. One such * structure is allocated for each error; it holds information about the * interpreter and the error until an idle handler command can be invoked. */ typedef struct BgError { Tcl_Obj *errorMsg; /* Copy of the error message (the interp's * result when the error occurred). */ Tcl_Obj *returnOpts; /* Active return options when the error * occurred */ struct BgError *nextPtr; /* Next in list of all pending error reports * for this interpreter, or NULL for end of * list. */ } BgError; /* * One of the structures below is associated with the "tclBgError" assoc data * for each interpreter. It keeps track of the head and tail of the list of * pending background errors for the interpreter. */ typedef struct ErrAssocData { Tcl_Interp *interp; /* Interpreter in which error occurred. */ Tcl_Obj *cmdPrefix; /* First word(s) of the handler command */ BgError *firstBgPtr; /* First in list of all background errors * waiting to be processed for this * interpreter (NULL if none). */ BgError *lastBgPtr; /* Last in list of all background errors * waiting to be processed for this * interpreter (NULL if none). */ } ErrAssocData; /* * For each exit handler created with a call to Tcl_Create(Late)ExitHandler * there is a structure of the following type: */ typedef struct ExitHandler { Tcl_ExitProc *proc; /* Function to call when process exits. */ ClientData clientData; /* One word of information to pass to proc. */ struct ExitHandler *nextPtr;/* Next in list of all exit handlers for this * application, or NULL for end of list. */ } ExitHandler; /* * There is both per-process and per-thread exit handlers. The first list is * controlled by a mutex. The other is in thread local storage. */ static ExitHandler *firstExitPtr = NULL; /* First in list of all exit handlers for * application. */ static ExitHandler *firstLateExitPtr = NULL; /* First in list of all late exit handlers for * application. */ TCL_DECLARE_MUTEX(exitMutex) /* * This variable is set to 1 when Tcl_Exit is called. The variable is checked * by TclInExit() to allow different behavior for exit-time processing, e.g., * in closing of files and pipes. */ static int inExit = 0; static int subsystemsInitialized = 0; /* * This variable contains the application wide exit handler. It will be called * by Tcl_Exit instead of the C-runtime exit if this variable is set to a * non-NULL value. */ static TCL_NORETURN1 Tcl_ExitProc *appExitPtr = NULL; typedef struct ThreadSpecificData { ExitHandler *firstExitPtr; /* First in list of all exit handlers for this * thread. */ int inExit; /* True when this thread is exiting. This is * used as a hack to decide to close the * standard channels. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; #ifdef TCL_THREADS typedef struct { Tcl_ThreadCreateProc *proc; /* Main() function of the thread */ ClientData clientData; /* The one argument to Main() */ } ThreadClientData; static Tcl_ThreadCreateType NewThreadProc(ClientData clientData); #endif /* TCL_THREADS */ /* * Prototypes for functions referenced only in this file: */ static void BgErrorDeleteProc(ClientData clientData, Tcl_Interp *interp); static void HandleBgErrors(ClientData clientData); static char * VwaitVarProc(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); static void InvokeExitHandlers(void); static void FinalizeThread(int quick); /* *---------------------------------------------------------------------- * * Tcl_BackgroundError -- * * This function is invoked to handle errors that occur in Tcl commands * that are invoked in "background" (e.g. from event or timer bindings). * * Results: * None. * * Side effects: * A handler command is invoked later as an idle handler to process the * error, passing it the interp result and return options. * *---------------------------------------------------------------------- */ void Tcl_BackgroundError( Tcl_Interp *interp) /* Interpreter in which an error has * occurred. */ { Tcl_BackgroundException(interp, TCL_ERROR); } void Tcl_BackgroundException( Tcl_Interp *interp, /* Interpreter in which an exception has * occurred. */ int code) /* The exception code value */ { BgError *errPtr; ErrAssocData *assocPtr; if (code == TCL_OK) { return; } errPtr = ckalloc(sizeof(BgError)); errPtr->errorMsg = Tcl_GetObjResult(interp); Tcl_IncrRefCount(errPtr->errorMsg); errPtr->returnOpts = Tcl_GetReturnOptions(interp, code); Tcl_IncrRefCount(errPtr->returnOpts); errPtr->nextPtr = NULL; (void) TclGetBgErrorHandler(interp); assocPtr = Tcl_GetAssocData(interp, "tclBgError", NULL); if (assocPtr->firstBgPtr == NULL) { assocPtr->firstBgPtr = errPtr; Tcl_DoWhenIdle(HandleBgErrors, assocPtr); } else { assocPtr->lastBgPtr->nextPtr = errPtr; } assocPtr->lastBgPtr = errPtr; Tcl_ResetResult(interp); } /* *---------------------------------------------------------------------- * * HandleBgErrors -- * * This function is invoked as an idle handler to process all of the * accumulated background errors. * * Results: * None. * * Side effects: * Depends on what actions the handler command takes for the errors. * *---------------------------------------------------------------------- */ static void HandleBgErrors( ClientData clientData) /* Pointer to ErrAssocData structure. */ { ErrAssocData *assocPtr = clientData; Tcl_Interp *interp = assocPtr->interp; BgError *errPtr; /* * Not bothering to save/restore the interp state. Assume that any code * that has interp state it needs to keep will make its own * Tcl_SaveInterpState call before calling something like Tcl_DoOneEvent() * that could lead us here. */ Tcl_Preserve(assocPtr); Tcl_Preserve(interp); while (assocPtr->firstBgPtr != NULL) { int code, prefixObjc; Tcl_Obj **prefixObjv, **tempObjv; /* * Note we copy the handler command prefix each pass through, so we do * support one handler setting another handler. */ Tcl_Obj *copyObj = TclListObjCopy(NULL, assocPtr->cmdPrefix); errPtr = assocPtr->firstBgPtr; Tcl_ListObjGetElements(NULL, copyObj, &prefixObjc, &prefixObjv); tempObjv = ckalloc((prefixObjc+2) * sizeof(Tcl_Obj *)); memcpy(tempObjv, prefixObjv, prefixObjc*sizeof(Tcl_Obj *)); tempObjv[prefixObjc] = errPtr->errorMsg; tempObjv[prefixObjc+1] = errPtr->returnOpts; Tcl_AllowExceptions(interp); code = Tcl_EvalObjv(interp, prefixObjc+2, tempObjv, TCL_EVAL_GLOBAL); /* * Discard the command and the information about the error report. */ Tcl_DecrRefCount(copyObj); Tcl_DecrRefCount(errPtr->errorMsg); Tcl_DecrRefCount(errPtr->returnOpts); assocPtr->firstBgPtr = errPtr->nextPtr; ckfree(errPtr); ckfree(tempObjv); if (code == TCL_BREAK) { /* * Break means cancel any remaining error reports for this * interpreter. */ while (assocPtr->firstBgPtr != NULL) { errPtr = assocPtr->firstBgPtr; assocPtr->firstBgPtr = errPtr->nextPtr; Tcl_DecrRefCount(errPtr->errorMsg); Tcl_DecrRefCount(errPtr->returnOpts); ckfree(errPtr); } } else if ((code == TCL_ERROR) && !Tcl_IsSafe(interp)) { Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR); if (errChannel != NULL) { Tcl_Obj *options = Tcl_GetReturnOptions(interp, code); Tcl_Obj *keyPtr, *valuePtr = NULL; TclNewLiteralStringObj(keyPtr, "-errorinfo"); Tcl_IncrRefCount(keyPtr); Tcl_DictObjGet(NULL, options, keyPtr, &valuePtr); Tcl_DecrRefCount(keyPtr); Tcl_WriteChars(errChannel, "error in background error handler:\n", -1); if (valuePtr) { Tcl_WriteObj(errChannel, valuePtr); } else { Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)); } Tcl_WriteChars(errChannel, "\n", 1); Tcl_Flush(errChannel); Tcl_DecrRefCount(options); } } } assocPtr->lastBgPtr = NULL; Tcl_Release(interp); Tcl_Release(assocPtr); } /* *---------------------------------------------------------------------- * * TclDefaultBgErrorHandlerObjCmd -- * * This function is invoked to process the "::tcl::Bgerror" Tcl command. * It is the default handler command registered with [interp bgerror] for * the sake of compatibility with older Tcl releases. * * Results: * A standard Tcl object result. * * Side effects: * Depends on what actions the "bgerror" command takes for the errors. * *---------------------------------------------------------------------- */ int TclDefaultBgErrorHandlerObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *keyPtr, *valuePtr; Tcl_Obj *tempObjv[2]; int result, code, level; Tcl_InterpState saved; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "msg options"); return TCL_ERROR; } /* * Check for a valid return options dictionary. */ TclNewLiteralStringObj(keyPtr, "-level"); Tcl_IncrRefCount(keyPtr); result = Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr); Tcl_DecrRefCount(keyPtr); if (result != TCL_OK || valuePtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing return option \"-level\"", -1)); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, valuePtr, &level) == TCL_ERROR) { return TCL_ERROR; } TclNewLiteralStringObj(keyPtr, "-code"); Tcl_IncrRefCount(keyPtr); result = Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr); Tcl_DecrRefCount(keyPtr); if (result != TCL_OK || valuePtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing return option \"-code\"", -1)); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, valuePtr, &code) == TCL_ERROR) { return TCL_ERROR; } if (level != 0) { /* * We're handling a TCL_RETURN exception. */ code = TCL_RETURN; } if (code == TCL_OK) { /* * Somehow we got to exception handling with no exception. (Pass * TCL_OK to Tcl_BackgroundException()?) Just return without doing * anything. */ return TCL_OK; } /* * Construct the bgerror command. */ TclNewLiteralStringObj(tempObjv[0], "bgerror"); Tcl_IncrRefCount(tempObjv[0]); /* * Determine error message argument. Check the return options in case * a non-error exception brought us here. */ switch (code) { case TCL_ERROR: tempObjv[1] = objv[1]; break; case TCL_BREAK: TclNewLiteralStringObj(tempObjv[1], "invoked \"break\" outside of a loop"); break; case TCL_CONTINUE: TclNewLiteralStringObj(tempObjv[1], "invoked \"continue\" outside of a loop"); break; default: tempObjv[1] = Tcl_ObjPrintf("command returned bad code: %d", code); break; } Tcl_IncrRefCount(tempObjv[1]); if (code != TCL_ERROR) { Tcl_SetObjResult(interp, tempObjv[1]); } TclNewLiteralStringObj(keyPtr, "-errorcode"); Tcl_IncrRefCount(keyPtr); result = Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr); Tcl_DecrRefCount(keyPtr); if (result == TCL_OK && valuePtr != NULL) { Tcl_SetObjErrorCode(interp, valuePtr); } TclNewLiteralStringObj(keyPtr, "-errorinfo"); Tcl_IncrRefCount(keyPtr); result = Tcl_DictObjGet(NULL, objv[2], keyPtr, &valuePtr); Tcl_DecrRefCount(keyPtr); if (result == TCL_OK && valuePtr != NULL) { Tcl_AppendObjToErrorInfo(interp, valuePtr); } if (code == TCL_ERROR) { Tcl_SetObjResult(interp, tempObjv[1]); } /* * Save interpreter state so we can restore it if multiple handler * attempts are needed. */ saved = Tcl_SaveInterpState(interp, code); /* * Invoke the bgerror command. */ Tcl_AllowExceptions(interp); code = Tcl_EvalObjv(interp, 2, tempObjv, TCL_EVAL_GLOBAL); if (code == TCL_ERROR) { /* * If the interpreter is safe, we look for a hidden command named * "bgerror" and call that with the error information. Otherwise, * simply ignore the error. The rationale is that this could be an * error caused by a malicious applet trying to cause an infinite * barrage of error messages. The hidden "bgerror" command can be used * by a security policy to interpose on such attacks and e.g. kill the * applet after a few attempts. */ if (Tcl_IsSafe(interp)) { Tcl_RestoreInterpState(interp, saved); TclObjInvoke(interp, 2, tempObjv, TCL_INVOKE_HIDDEN); } else { Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR); if (errChannel != NULL) { Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); Tcl_IncrRefCount(resultPtr); if (Tcl_FindCommand(interp, "bgerror", NULL, TCL_GLOBAL_ONLY) == NULL) { Tcl_RestoreInterpState(interp, saved); Tcl_WriteObj(errChannel, Tcl_GetVar2Ex(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY)); Tcl_WriteChars(errChannel, "\n", -1); } else { Tcl_DiscardInterpState(saved); Tcl_WriteChars(errChannel, "bgerror failed to handle background error.\n",-1); Tcl_WriteChars(errChannel, " Original error: ", -1); Tcl_WriteObj(errChannel, tempObjv[1]); Tcl_WriteChars(errChannel, "\n", -1); Tcl_WriteChars(errChannel, " Error in bgerror: ", -1); Tcl_WriteObj(errChannel, resultPtr); Tcl_WriteChars(errChannel, "\n", -1); } Tcl_DecrRefCount(resultPtr); Tcl_Flush(errChannel); } else { Tcl_DiscardInterpState(saved); } } code = TCL_OK; } else { Tcl_DiscardInterpState(saved); } Tcl_DecrRefCount(tempObjv[0]); Tcl_DecrRefCount(tempObjv[1]); Tcl_ResetResult(interp); return code; } /* *---------------------------------------------------------------------- * * TclSetBgErrorHandler -- * * This function sets the command prefix to be used to handle background * errors in interp. * * Results: * None. * * Side effects: * Error handler is registered. * *---------------------------------------------------------------------- */ void TclSetBgErrorHandler( Tcl_Interp *interp, Tcl_Obj *cmdPrefix) { ErrAssocData *assocPtr = Tcl_GetAssocData(interp, "tclBgError", NULL); if (cmdPrefix == NULL) { Tcl_Panic("TclSetBgErrorHandler: NULL cmdPrefix argument"); } if (assocPtr == NULL) { /* * First access: initialize. */ assocPtr = ckalloc(sizeof(ErrAssocData)); assocPtr->interp = interp; assocPtr->cmdPrefix = NULL; assocPtr->firstBgPtr = NULL; assocPtr->lastBgPtr = NULL; Tcl_SetAssocData(interp, "tclBgError", BgErrorDeleteProc, assocPtr); } if (assocPtr->cmdPrefix) { Tcl_DecrRefCount(assocPtr->cmdPrefix); } assocPtr->cmdPrefix = cmdPrefix; Tcl_IncrRefCount(assocPtr->cmdPrefix); } /* *---------------------------------------------------------------------- * * TclGetBgErrorHandler -- * * This function retrieves the command prefix currently used to handle * background errors in interp. * * Results: * A (Tcl_Obj *) to a list of words (command prefix). * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * TclGetBgErrorHandler( Tcl_Interp *interp) { ErrAssocData *assocPtr = Tcl_GetAssocData(interp, "tclBgError", NULL); if (assocPtr == NULL) { Tcl_Obj *bgerrorObj; TclNewLiteralStringObj(bgerrorObj, "::tcl::Bgerror"); TclSetBgErrorHandler(interp, bgerrorObj); assocPtr = Tcl_GetAssocData(interp, "tclBgError", NULL); } return assocPtr->cmdPrefix; } /* *---------------------------------------------------------------------- * * BgErrorDeleteProc -- * * This function is associated with the "tclBgError" assoc data for an * interpreter; it is invoked when the interpreter is deleted in order to * free the information assoicated with any pending error reports. * * Results: * None. * * Side effects: * Background error information is freed: if there were any pending error * reports, they are canceled. * *---------------------------------------------------------------------- */ static void BgErrorDeleteProc( ClientData clientData, /* Pointer to ErrAssocData structure. */ Tcl_Interp *interp) /* Interpreter being deleted. */ { ErrAssocData *assocPtr = clientData; BgError *errPtr; while (assocPtr->firstBgPtr != NULL) { errPtr = assocPtr->firstBgPtr; assocPtr->firstBgPtr = errPtr->nextPtr; Tcl_DecrRefCount(errPtr->errorMsg); Tcl_DecrRefCount(errPtr->returnOpts); ckfree(errPtr); } Tcl_CancelIdleCall(HandleBgErrors, assocPtr); Tcl_DecrRefCount(assocPtr->cmdPrefix); Tcl_EventuallyFree(assocPtr, TCL_DYNAMIC); } /* *---------------------------------------------------------------------- * * Tcl_CreateExitHandler -- * * Arrange for a given function to be invoked just before the application * exits. * * Results: * None. * * Side effects: * Proc will be invoked with clientData as argument when the application * exits. * *---------------------------------------------------------------------- */ void Tcl_CreateExitHandler( Tcl_ExitProc *proc, /* Function to invoke. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { ExitHandler *exitPtr = ckalloc(sizeof(ExitHandler)); exitPtr->proc = proc; exitPtr->clientData = clientData; Tcl_MutexLock(&exitMutex); exitPtr->nextPtr = firstExitPtr; firstExitPtr = exitPtr; Tcl_MutexUnlock(&exitMutex); } /* *---------------------------------------------------------------------- * * TclCreateLateExitHandler -- * * Arrange for a given function to be invoked after all pre-thread * cleanups. * * Results: * None. * * Side effects: * Proc will be invoked with clientData as argument when the application * exits. * *---------------------------------------------------------------------- */ void TclCreateLateExitHandler( Tcl_ExitProc *proc, /* Function to invoke. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { ExitHandler *exitPtr = ckalloc(sizeof(ExitHandler)); exitPtr->proc = proc; exitPtr->clientData = clientData; Tcl_MutexLock(&exitMutex); exitPtr->nextPtr = firstLateExitPtr; firstLateExitPtr = exitPtr; Tcl_MutexUnlock(&exitMutex); } /* *---------------------------------------------------------------------- * * Tcl_DeleteExitHandler -- * * This function cancels an existing exit handler matching proc and * clientData, if such a handler exits. * * Results: * None. * * Side effects: * If there is an exit handler corresponding to proc and clientData then * it is canceled; if no such handler exists then nothing happens. * *---------------------------------------------------------------------- */ void Tcl_DeleteExitHandler( Tcl_ExitProc *proc, /* Function that was previously registered. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { ExitHandler *exitPtr, *prevPtr; Tcl_MutexLock(&exitMutex); for (prevPtr = NULL, exitPtr = firstExitPtr; exitPtr != NULL; prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) { if ((exitPtr->proc == proc) && (exitPtr->clientData == clientData)) { if (prevPtr == NULL) { firstExitPtr = exitPtr->nextPtr; } else { prevPtr->nextPtr = exitPtr->nextPtr; } ckfree(exitPtr); break; } } Tcl_MutexUnlock(&exitMutex); return; } /* *---------------------------------------------------------------------- * * TclDeleteLateExitHandler -- * * This function cancels an existing late exit handler matching proc and * clientData, if such a handler exits. * * Results: * None. * * Side effects: * If there is a late exit handler corresponding to proc and clientData * then it is canceled; if no such handler exists then nothing happens. * *---------------------------------------------------------------------- */ void TclDeleteLateExitHandler( Tcl_ExitProc *proc, /* Function that was previously registered. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { ExitHandler *exitPtr, *prevPtr; Tcl_MutexLock(&exitMutex); for (prevPtr = NULL, exitPtr = firstLateExitPtr; exitPtr != NULL; prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) { if ((exitPtr->proc == proc) && (exitPtr->clientData == clientData)) { if (prevPtr == NULL) { firstLateExitPtr = exitPtr->nextPtr; } else { prevPtr->nextPtr = exitPtr->nextPtr; } ckfree(exitPtr); break; } } Tcl_MutexUnlock(&exitMutex); return; } /* *---------------------------------------------------------------------- * * Tcl_CreateThreadExitHandler -- * * Arrange for a given function to be invoked just before the current * thread exits. * * Results: * None. * * Side effects: * Proc will be invoked with clientData as argument when the application * exits. * *---------------------------------------------------------------------- */ void Tcl_CreateThreadExitHandler( Tcl_ExitProc *proc, /* Function to invoke. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { ExitHandler *exitPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); exitPtr = ckalloc(sizeof(ExitHandler)); exitPtr->proc = proc; exitPtr->clientData = clientData; exitPtr->nextPtr = tsdPtr->firstExitPtr; tsdPtr->firstExitPtr = exitPtr; } /* *---------------------------------------------------------------------- * * Tcl_DeleteThreadExitHandler -- * * This function cancels an existing exit handler matching proc and * clientData, if such a handler exits. * * Results: * None. * * Side effects: * If there is an exit handler corresponding to proc and clientData then * it is canceled; if no such handler exists then nothing happens. * *---------------------------------------------------------------------- */ void Tcl_DeleteThreadExitHandler( Tcl_ExitProc *proc, /* Function that was previously registered. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { ExitHandler *exitPtr, *prevPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); for (prevPtr = NULL, exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL; prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) { if ((exitPtr->proc == proc) && (exitPtr->clientData == clientData)) { if (prevPtr == NULL) { tsdPtr->firstExitPtr = exitPtr->nextPtr; } else { prevPtr->nextPtr = exitPtr->nextPtr; } ckfree(exitPtr); return; } } } /* *---------------------------------------------------------------------- * * Tcl_SetExitProc -- * * This function sets the application wide exit handler that will be * called by Tcl_Exit in place of the C-runtime exit. If the application * wide exit handler is NULL, the C-runtime exit will be used instead. * * Results: * The previously set application wide exit handler. * * Side effects: * Sets the application wide exit handler to the specified value. * *---------------------------------------------------------------------- */ Tcl_ExitProc * Tcl_SetExitProc( TCL_NORETURN1 Tcl_ExitProc *proc) /* New exit handler for app or NULL */ { Tcl_ExitProc *prevExitProc; /* * Swap the old exit proc for the new one, saving the old one for our * return value. */ Tcl_MutexLock(&exitMutex); prevExitProc = appExitPtr; appExitPtr = proc; Tcl_MutexUnlock(&exitMutex); return prevExitProc; } /* *---------------------------------------------------------------------- * * InvokeExitHandlers -- * * Call the registered exit handlers. * * Results: * None. * * Side effects: * The exit handlers are invoked, and the ExitHandler struct is * freed. * *---------------------------------------------------------------------- */ static void InvokeExitHandlers(void) { ExitHandler *exitPtr; Tcl_MutexLock(&exitMutex); inExit = 1; for (exitPtr = firstExitPtr; exitPtr != NULL; exitPtr = firstExitPtr) { /* * Be careful to remove the handler from the list before invoking its * callback. This protects us against double-freeing if the callback * should call Tcl_DeleteExitHandler on itself. */ firstExitPtr = exitPtr->nextPtr; Tcl_MutexUnlock(&exitMutex); exitPtr->proc(exitPtr->clientData); ckfree(exitPtr); Tcl_MutexLock(&exitMutex); } firstExitPtr = NULL; Tcl_MutexUnlock(&exitMutex); } /* *---------------------------------------------------------------------- * * Tcl_Exit -- * * This function is called to terminate the application. * * Results: * None. * * Side effects: * All existing exit handlers are invoked, then the application ends. * *---------------------------------------------------------------------- */ TCL_NORETURN void Tcl_Exit( int status) /* Exit status for application; typically 0 * for normal return, 1 for error return. */ { TCL_NORETURN1 Tcl_ExitProc *currentAppExitPtr; Tcl_MutexLock(&exitMutex); currentAppExitPtr = appExitPtr; Tcl_MutexUnlock(&exitMutex); if (currentAppExitPtr) { /* * Warning: this code SHOULD NOT return, as there is code that depends * on Tcl_Exit never returning. In fact, we will Tcl_Panic if anyone * returns, so critical is this dependcy. */ currentAppExitPtr(INT2PTR(status)); Tcl_Panic("AppExitProc returned unexpectedly"); } else { if (TclFullFinalizationRequested()) { /* * Thorough finalization for Valgrind et al. */ Tcl_Finalize(); } else { /* * Fast and deterministic exit (default behavior) */ InvokeExitHandlers(); /* * Ensure the thread-specific data is initialised as it is used in * Tcl_FinalizeThread() */ (void) TCL_TSD_INIT(&dataKey); /* * Now finalize the calling thread only (others are not safely * reachable). Among other things, this triggers a flush of the * Tcl_Channels that may have data enqueued. */ FinalizeThread(/* quick */ 1); } TclpExit(status); Tcl_Panic("OS exit failed!"); } } /* *------------------------------------------------------------------------- * * TclInitSubsystems -- * * Initialize various subsytems in Tcl. This should be called the first * time an interp is created, or before any of the subsystems are used. * This function ensures an order for the initialization of subsystems: * * 1. that cannot be initialized in lazy order because they are mutually * dependent. * * 2. so that they can be finalized in a known order w/o causing the * subsequent re-initialization of a subsystem in the act of shutting * down another. * * Results: * None. * * Side effects: * Varied, see the respective initialization routines. * *------------------------------------------------------------------------- */ void TclInitSubsystems(void) { if (inExit != 0) { Tcl_Panic("TclInitSubsystems called while exiting"); } if (subsystemsInitialized == 0) { /* * Double check inside the mutex. There are definitly calls back into * this routine from some of the functions below. */ TclpInitLock(); if (subsystemsInitialized == 0) { /* * Initialize locks used by the memory allocators before anything * interesting happens so we can use the allocators in the * implementation of self-initializing locks. */ TclInitThreadStorage(); /* Creates master hash table for * thread local storage */ #if USE_TCLALLOC TclInitAlloc(); /* Process wide mutex init */ #endif #ifdef TCL_MEM_DEBUG TclInitDbCkalloc(); /* Process wide mutex init */ #endif TclpInitPlatform(); /* Creates signal handler(s) */ TclInitDoubleConversion(); /* Initializes constants for * converting to/from double. */ TclInitObjSubsystem(); /* Register obj types, create * mutexes. */ TclInitIOSubsystem(); /* Inits a tsd key (noop). */ TclInitEncodingSubsystem(); /* Process wide encoding init. */ TclpSetInterfaces(); TclInitNamespaceSubsystem();/* Register ns obj type (mutexed). */ subsystemsInitialized = 1; } TclpInitUnlock(); } TclInitNotifier(); } /* *---------------------------------------------------------------------- * * Tcl_Finalize -- * * Shut down Tcl. First calls registered exit handlers, then carefully * shuts down various subsystems. Should be invoked by user before the * Tcl shared library is being unloaded in an embedded context. * * Results: * None. * * Side effects: * Varied, see the respective finalization routines. * *---------------------------------------------------------------------- */ void Tcl_Finalize(void) { ExitHandler *exitPtr; /* * Invoke exit handlers first. */ InvokeExitHandlers(); TclpInitLock(); if (subsystemsInitialized == 0) { goto alreadyFinalized; } subsystemsInitialized = 0; /* * Ensure the thread-specific data is initialised as it is used in * Tcl_FinalizeThread() */ (void) TCL_TSD_INIT(&dataKey); /* * Clean up after the current thread now, after exit handlers. In * particular, the testexithandler command sets up something that writes * to standard output, which gets closed. Note that there is no * thread-local storage or IO subsystem after this call. */ Tcl_FinalizeThread(); /* * Now invoke late (process-wide) exit handlers. */ Tcl_MutexLock(&exitMutex); for (exitPtr = firstLateExitPtr; exitPtr != NULL; exitPtr = firstLateExitPtr) { /* * Be careful to remove the handler from the list before invoking its * callback. This protects us against double-freeing if the callback * should call Tcl_DeleteLateExitHandler on itself. */ firstLateExitPtr = exitPtr->nextPtr; Tcl_MutexUnlock(&exitMutex); exitPtr->proc(exitPtr->clientData); ckfree(exitPtr); Tcl_MutexLock(&exitMutex); } firstLateExitPtr = NULL; Tcl_MutexUnlock(&exitMutex); /* * Now finalize the Tcl execution environment. Note that this must be done * after the exit handlers, because there are order dependencies. */ TclFinalizeEvaluation(); TclFinalizeExecution(); TclFinalizeEnvironment(); /* * Finalizing the filesystem must come after anything which might * conceivably interact with the 'Tcl_FS' API. */ TclFinalizeFilesystem(); /* * Undo all Tcl_ObjType registrations, and reset the master list of free * Tcl_Obj's. After this returns, no more Tcl_Obj's should be allocated or * freed. * * Note in particular that TclFinalizeObjects() must follow * TclFinalizeFilesystem() because TclFinalizeFilesystem free's the * Tcl_Obj that holds the path of the current working directory. */ TclFinalizeObjects(); /* * We must be sure the encoding finalization doesn't need to examine the * filesystem in any way. Since it only needs to clean up internal data * structures, this is fine. */ TclFinalizeEncodingSubsystem(); /* * Repeat finalization of the thread local storage once more. Although * this step is already done by the Tcl_FinalizeThread call above, series * of events happening afterwards may re-initialize TSD slots. Those need * to be finalized again, otherwise we're leaking memory chunks. Very * important to note is that things happening afterwards should not * reference anything which may re-initialize TSD's. This includes freeing * Tcl_Objs's, among other things. * * This fixes the Tcl Bug #990552. */ TclFinalizeThreadData(/* quick */ 0); /* * Now we can free constants for conversions to/from double. */ TclFinalizeDoubleConversion(); /* * There have been several bugs in the past that cause exit handlers to be * established during Tcl_Finalize processing. Such exit handlers leave * malloc'ed memory, and Tcl_FinalizeMemorySubsystem or * Tcl_FinalizeThreadAlloc will result in a corrupted heap. The result can * be a mysterious crash on process exit. Check here that nobody's done * this. */ if (firstExitPtr != NULL) { Tcl_Panic("exit handlers were created during Tcl_Finalize"); } TclFinalizePreserve(); /* * Free synchronization objects. There really should only be one thread * alive at this moment. */ TclFinalizeSynchronization(); /* * Close down the thread-specific object allocator. */ #if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) TclFinalizeThreadAlloc(); #endif /* * We defer unloading of packages until very late to avoid memory access * issues. Both exit callbacks and synchronization variables may be stored * in packages. * * Note that TclFinalizeLoad unloads packages in the reverse of the order * they were loaded in (i.e. last to be loaded is the first to be * unloaded). This can be important for correct unloading when * dependencies exist. * * Once load has been finalized, we will have deleted any temporary copies * of shared libraries and can therefore reset the filesystem to its * original state. */ TclFinalizeLoad(); TclResetFilesystem(); /* * At this point, there should no longer be any ckalloc'ed memory. */ TclFinalizeMemorySubsystem(); alreadyFinalized: TclFinalizeLock(); } /* *---------------------------------------------------------------------- * * Tcl_FinalizeThread -- * * Runs the exit handlers to allow Tcl to clean up its state about a * particular thread. * * Results: * None. * * Side effects: * Varied, see the respective finalization routines. * *---------------------------------------------------------------------- */ void Tcl_FinalizeThread(void) { FinalizeThread(/* quick */ 0); } void FinalizeThread( int quick) { ExitHandler *exitPtr; ThreadSpecificData *tsdPtr; /* * We use TclThreadDataKeyGet here, rather than Tcl_GetThreadData, because * we don't want to initialize the data block if it hasn't been * initialized already. */ tsdPtr = TclThreadDataKeyGet(&dataKey); if (tsdPtr != NULL) { tsdPtr->inExit = 1; for (exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL; exitPtr = tsdPtr->firstExitPtr) { /* * Be careful to remove the handler from the list before invoking * its callback. This protects us against double-freeing if the * callback should call Tcl_DeleteThreadExitHandler on itself. */ tsdPtr->firstExitPtr = exitPtr->nextPtr; exitPtr->proc(exitPtr->clientData); ckfree(exitPtr); } TclFinalizeIOSubsystem(); TclFinalizeNotifier(); TclFinalizeAsync(); TclFinalizeThreadObjects(); } /* * Blow away all thread local storage blocks. * * Note that Tcl API allows creation of threads which do not use any Tcl * interp or other Tcl subsytems. Those threads might, however, use thread * local storage, so we must unconditionally finalize it. * * Fix [Bug #571002] */ TclFinalizeThreadData(quick); } /* *---------------------------------------------------------------------- * * TclInExit -- * * Determines if we are in the middle of exit-time cleanup. * * Results: * If we are in the middle of exiting, 1, otherwise 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclInExit(void) { return inExit; } /* *---------------------------------------------------------------------- * * TclInThreadExit -- * * Determines if we are in the middle of thread exit-time cleanup. * * Results: * If we are in the middle of exiting this thread, 1, otherwise 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclInThreadExit(void) { ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); if (tsdPtr == NULL) { return 0; } return tsdPtr->inExit; } /* *---------------------------------------------------------------------- * * Tcl_VwaitObjCmd -- * * This function is invoked to process the "vwait" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_VwaitObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int done, foundEvent; const char *nameString; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } nameString = Tcl_GetString(objv[1]); if (Tcl_TraceVar2(interp, nameString, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, VwaitVarProc, &done) != TCL_OK) { return TCL_ERROR; }; done = 0; foundEvent = 1; while (!done && foundEvent) { foundEvent = Tcl_DoOneEvent(TCL_ALL_EVENTS); if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) { break; } if (Tcl_LimitExceeded(interp)) { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewStringObj("limit exceeded", -1)); break; } } Tcl_UntraceVar2(interp, nameString, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, VwaitVarProc, &done); if (!foundEvent) { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't wait for variable \"%s\": would wait forever", nameString)); Tcl_SetErrorCode(interp, "TCL", "EVENT", "NO_SOURCES", NULL); return TCL_ERROR; } if (!done) { /* * The interpreter's result was already set to the right error message * prior to exiting the loop above. */ return TCL_ERROR; } /* * Clear out the interpreter's result, since it may have been set by event * handlers. */ Tcl_ResetResult(interp); return TCL_OK; } /* ARGSUSED */ static char * VwaitVarProc( ClientData clientData, /* Pointer to integer to set to 1. */ Tcl_Interp *interp, /* Interpreter containing variable. */ const char *name1, /* Name of variable. */ const char *name2, /* Second part of variable name. */ int flags) /* Information about what happened. */ { int *donePtr = clientData; *donePtr = 1; return NULL; } /* *---------------------------------------------------------------------- * * Tcl_UpdateObjCmd -- * * This function is invoked to process the "update" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_UpdateObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int optionIndex; int flags = 0; /* Initialized to avoid compiler warning. */ static const char *const updateOptions[] = {"idletasks", NULL}; enum updateOptions {OPT_IDLETASKS}; if (objc == 1) { flags = TCL_ALL_EVENTS|TCL_DONT_WAIT; } else if (objc == 2) { if (Tcl_GetIndexFromObj(interp, objv[1], updateOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum updateOptions) optionIndex) { case OPT_IDLETASKS: flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT; break; default: Tcl_Panic("Tcl_UpdateObjCmd: bad option index to UpdateOptions"); } } else { Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?"); return TCL_ERROR; } while (Tcl_DoOneEvent(flags) != 0) { if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) { return TCL_ERROR; } if (Tcl_LimitExceeded(interp)) { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewStringObj("limit exceeded", -1)); return TCL_ERROR; } } /* * Must clear the interpreter's result because event handlers could have * executed commands. */ Tcl_ResetResult(interp); return TCL_OK; } #ifdef TCL_THREADS /* *---------------------------------------------------------------------- * * NewThreadProc -- * * Bootstrap function of a new Tcl thread. * * Results: * None. * * Side Effects: * Initializes Tcl notifier for the current thread. * *---------------------------------------------------------------------- */ static Tcl_ThreadCreateType NewThreadProc( ClientData clientData) { ThreadClientData *cdPtr = clientData; ClientData threadClientData; Tcl_ThreadCreateProc *threadProc; threadProc = cdPtr->proc; threadClientData = cdPtr->clientData; ckfree(clientData); /* Allocated in Tcl_CreateThread() */ threadProc(threadClientData); TCL_THREAD_CREATE_RETURN; } #endif /* *---------------------------------------------------------------------- * * Tcl_CreateThread -- * * This function creates a new thread. This actually belongs to the * tclThread.c file but since we use some private data structures local * to this file, it is placed here. * * Results: * TCL_OK if the thread could be created. The thread ID is returned in a * parameter. * * Side effects: * A new thread is created. * *---------------------------------------------------------------------- */ int Tcl_CreateThread( Tcl_ThreadId *idPtr, /* Return, the ID of the thread */ Tcl_ThreadCreateProc *proc, /* Main() function of the thread */ ClientData clientData, /* The one argument to Main() */ int stackSize, /* Size of stack for the new thread */ int flags) /* Flags controlling behaviour of the new * thread. */ { #ifdef TCL_THREADS ThreadClientData *cdPtr = ckalloc(sizeof(ThreadClientData)); int result; cdPtr->proc = proc; cdPtr->clientData = clientData; result = TclpThreadCreate(idPtr, NewThreadProc, cdPtr, stackSize, flags); if (result != TCL_OK) { ckfree(cdPtr); } return result; #else return TCL_ERROR; #endif /* TCL_THREADS */ } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclOO.h0000644000175000017500000001027212665113557014377 0ustar sergeisergei/* * tclOO.h -- * * This file contains the public API definitions and some of the function * declarations for the object-system (NB: not Tcl_Obj, but ::oo). * * Copyright (c) 2006-2010 by Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef TCLOO_H_INCLUDED #define TCLOO_H_INCLUDED /* * Be careful when it comes to versioning; need to make sure that the * standalone TclOO version matches. Also make sure that this matches the * version in the files: * * tests/oo.test * tests/ooNext2.test * unix/tclooConfig.sh * win/tclooConfig.sh */ #define TCLOO_VERSION "1.0.4" #define TCLOO_PATCHLEVEL TCLOO_VERSION #include "tcl.h" /* * For C++ compilers, use extern "C" */ #ifdef __cplusplus extern "C" { #endif extern const char *TclOOInitializeStubs( Tcl_Interp *, const char *version); #define Tcl_OOInitStubs(interp) \ TclOOInitializeStubs((interp), TCLOO_VERSION) #ifndef USE_TCL_STUBS # define TclOOInitializeStubs(interp, version) (TCLOO_PATCHLEVEL) #endif /* * These are opaque types. */ typedef struct Tcl_Class_ *Tcl_Class; typedef struct Tcl_Method_ *Tcl_Method; typedef struct Tcl_Object_ *Tcl_Object; typedef struct Tcl_ObjectContext_ *Tcl_ObjectContext; /* * Public datatypes for callbacks and structures used in the TIP#257 (OO) * implementation. These are used to implement custom types of method calls * and to allow the attachment of arbitrary data to objects and classes. */ typedef int (Tcl_MethodCallProc)(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext objectContext, int objc, Tcl_Obj *const *objv); typedef void (Tcl_MethodDeleteProc)(ClientData clientData); typedef int (Tcl_CloneProc)(Tcl_Interp *interp, ClientData oldClientData, ClientData *newClientData); typedef void (Tcl_ObjectMetadataDeleteProc)(ClientData clientData); typedef int (Tcl_ObjectMapMethodNameProc)(Tcl_Interp *interp, Tcl_Object object, Tcl_Class *startClsPtr, Tcl_Obj *methodNameObj); /* * The type of a method implementation. This describes how to call the method * implementation, how to delete it (when the object or class is deleted) and * how to create a clone of it (when the object or class is copied). */ typedef struct { int version; /* Structure version field. Always to be equal * to TCL_OO_METHOD_VERSION_CURRENT in * declarations. */ const char *name; /* Name of this type of method, mostly for * debugging purposes. */ Tcl_MethodCallProc *callProc; /* How to invoke this method. */ Tcl_MethodDeleteProc *deleteProc; /* How to delete this method's type-specific * data, or NULL if the type-specific data * does not need deleting. */ Tcl_CloneProc *cloneProc; /* How to copy this method's type-specific * data, or NULL if the type-specific data can * be copied directly. */ } Tcl_MethodType; /* * The correct value for the version field of the Tcl_MethodType structure. * This allows new versions of the structure to be introduced without breaking * binary compatability. */ #define TCL_OO_METHOD_VERSION_CURRENT 1 /* * The type of some object (or class) metadata. This describes how to delete * the metadata (when the object or class is deleted) and how to create a * clone of it (when the object or class is copied). */ typedef struct { int version; /* Structure version field. Always to be equal * to TCL_OO_METADATA_VERSION_CURRENT in * declarations. */ const char *name; Tcl_ObjectMetadataDeleteProc *deleteProc; /* How to delete the metadata. This must not * be NULL. */ Tcl_CloneProc *cloneProc; /* How to copy the metadata, or NULL if the * type-specific data can be copied * directly. */ } Tcl_ObjectMetadataType; /* * The correct value for the version field of the Tcl_ObjectMetadataType * structure. This allows new versions of the structure to be introduced * without breaking binary compatability. */ #define TCL_OO_METADATA_VERSION_CURRENT 1 /* * Include all the public API, generated from tclOO.decls. */ #include "tclOODecls.h" #ifdef __cplusplus } #endif #endif /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclOOStubInit.c0000644000175000017500000000430312665173571016054 0ustar sergeisergei/* * This file is (mostly) automatically generated from tclOO.decls. * It is compiled and linked in with the tclOO package proper. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tclOOInt.h" MODULE_SCOPE const TclOOStubs tclOOStubs; #ifdef __GNUC__ #pragma GCC dependency "tclOO.decls" #endif /* !BEGIN!: Do not edit below this line. */ static const TclOOIntStubs tclOOIntStubs = { TCL_STUB_MAGIC, 0, TclOOGetDefineCmdContext, /* 0 */ TclOOMakeProcInstanceMethod, /* 1 */ TclOOMakeProcMethod, /* 2 */ TclOONewProcInstanceMethod, /* 3 */ TclOONewProcMethod, /* 4 */ TclOOObjectCmdCore, /* 5 */ TclOOIsReachable, /* 6 */ TclOONewForwardMethod, /* 7 */ TclOONewForwardInstanceMethod, /* 8 */ TclOONewProcInstanceMethodEx, /* 9 */ TclOONewProcMethodEx, /* 10 */ TclOOInvokeObject, /* 11 */ TclOOObjectSetFilters, /* 12 */ TclOOClassSetFilters, /* 13 */ TclOOObjectSetMixins, /* 14 */ TclOOClassSetMixins, /* 15 */ }; static const TclOOStubHooks tclOOStubHooks = { &tclOOIntStubs }; const TclOOStubs tclOOStubs = { TCL_STUB_MAGIC, &tclOOStubHooks, Tcl_CopyObjectInstance, /* 0 */ Tcl_GetClassAsObject, /* 1 */ Tcl_GetObjectAsClass, /* 2 */ Tcl_GetObjectCommand, /* 3 */ Tcl_GetObjectFromObj, /* 4 */ Tcl_GetObjectNamespace, /* 5 */ Tcl_MethodDeclarerClass, /* 6 */ Tcl_MethodDeclarerObject, /* 7 */ Tcl_MethodIsPublic, /* 8 */ Tcl_MethodIsType, /* 9 */ Tcl_MethodName, /* 10 */ Tcl_NewInstanceMethod, /* 11 */ Tcl_NewMethod, /* 12 */ Tcl_NewObjectInstance, /* 13 */ Tcl_ObjectDeleted, /* 14 */ Tcl_ObjectContextIsFiltering, /* 15 */ Tcl_ObjectContextMethod, /* 16 */ Tcl_ObjectContextObject, /* 17 */ Tcl_ObjectContextSkippedArgs, /* 18 */ Tcl_ClassGetMetadata, /* 19 */ Tcl_ClassSetMetadata, /* 20 */ Tcl_ObjectGetMetadata, /* 21 */ Tcl_ObjectSetMetadata, /* 22 */ Tcl_ObjectContextInvokeNext, /* 23 */ Tcl_ObjectGetMethodNameMapper, /* 24 */ Tcl_ObjectSetMethodNameMapper, /* 25 */ Tcl_ClassSetConstructor, /* 26 */ Tcl_ClassSetDestructor, /* 27 */ Tcl_GetObjectName, /* 28 */ }; /* !END!: Do not edit above this line. */ tcl8.6.5/generic/tclTomMathStubLib.c0000644000175000017500000000425012663660065016711 0ustar sergeisergei/* * tclTomMathStubLib.c -- * * Stub object that will be statically linked into extensions that want * to access Tcl. * * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 1998 Paul Duffin. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" MODULE_SCOPE const TclTomMathStubs *tclTomMathStubsPtr; const TclTomMathStubs *tclTomMathStubsPtr = NULL; /* *---------------------------------------------------------------------- * * TclTomMathInitStubs -- * * Initializes the Stubs table for Tcl's subset of libtommath * * Results: * Returns a standard Tcl result. * * This procedure should not be called directly, but rather through * the TclTomMath_InitStubs macro, to insure that the Stubs table * matches the header files used in compilation. * *---------------------------------------------------------------------- */ MODULE_SCOPE const char * TclTomMathInitializeStubs( Tcl_Interp *interp, /* Tcl interpreter */ const char *version, /* Tcl version needed */ int epoch, /* Stubs table epoch from the header files */ int revision) /* Stubs table revision number from the * header files */ { int exact = 0; const char *packageName = "tcl::tommath"; const char *errMsg = NULL; TclTomMathStubs *stubsPtr = NULL; const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, exact, &stubsPtr); if (actualVersion == NULL) { return NULL; } if (stubsPtr == NULL) { errMsg = "missing stub table pointer"; } else if(stubsPtr->tclBN_epoch() != epoch) { errMsg = "epoch number mismatch"; } else if(stubsPtr->tclBN_revision() != revision) { errMsg = "requires a later revision"; } else { tclTomMathStubsPtr = stubsPtr; return actualVersion; } tclStubsPtr->tcl_ResetResult(interp); tclStubsPtr->tcl_AppendResult(interp, "Error loading ", packageName, " (requested version ", version, ", actual version ", actualVersion, "): ", errMsg, NULL); return NULL; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclUniData.c0000644000175000017500000032461512663660065015412 0ustar sergeisergei/* * tclUniData.c -- * * Declarations of Unicode character information tables. This file is * automatically generated by the tools/uniParse.tcl script. Do not * modify this file by hand. * * Copyright (c) 1998 by Scriptics Corporation. * All rights reserved. */ /* * A 16-bit Unicode character is split into two parts in order to index * into the following tables. The lower OFFSET_BITS comprise an offset * into a page of characters. The upper bits comprise the page number. */ #define OFFSET_BITS 5 /* * The pageMap is indexed by page number and returns an alternate page number * that identifies a unique page of characters. Many Unicode characters map * to the same alternate page number. */ static const unsigned short pageMap[] = { 0, 32, 64, 96, 0, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 224, 480, 512, 544, 576, 608, 640, 672, 704, 704, 736, 768, 800, 832, 864, 896, 928, 960, 992, 224, 1024, 224, 1056, 224, 224, 1088, 1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1344, 1344, 1440, 1472, 1504, 1536, 1568, 1344, 1344, 1600, 1632, 1664, 1696, 1728, 1760, 1792, 1792, 1824, 1792, 1856, 1888, 1920, 1952, 1984, 2016, 2048, 2080, 2112, 2144, 2176, 2208, 2240, 2272, 2304, 2336, 2368, 2400, 2432, 2464, 2496, 2528, 2560, 2592, 2624, 2656, 2688, 2720, 2752, 2784, 2816, 2848, 2880, 2784, 2912, 2944, 2976, 3008, 3040, 3072, 3104, 3136, 3168, 3200, 1792, 3232, 3264, 3296, 1792, 3328, 3360, 3392, 3424, 3456, 3488, 3520, 1792, 1344, 3552, 3584, 3616, 3648, 3680, 3712, 3744, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 3776, 1344, 3808, 3840, 3872, 1344, 3904, 1344, 3936, 3968, 4000, 4032, 4032, 4064, 4096, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 4128, 4160, 1344, 1344, 4192, 4224, 4256, 4288, 4320, 1344, 4352, 4384, 4416, 4448, 1344, 4480, 4512, 1344, 4544, 1344, 4576, 4608, 4640, 4672, 4704, 1344, 4736, 4768, 4800, 4832, 1344, 4864, 4896, 4928, 4960, 1792, 1792, 4992, 5024, 5056, 5088, 5120, 5152, 1344, 5184, 1344, 5216, 5248, 5280, 1792, 1792, 5312, 5344, 5376, 5408, 5440, 5472, 5504, 5440, 704, 5536, 224, 224, 224, 224, 5568, 224, 224, 224, 5600, 5632, 5664, 5696, 5728, 5760, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112, 6144, 6176, 6208, 6240, 6272, 6304, 6336, 6368, 6368, 6368, 6368, 6368, 6368, 6368, 6368, 6400, 6432, 4800, 6464, 6496, 6528, 6560, 6592, 4800, 6624, 6656, 6688, 6720, 6752, 6784, 6816, 4800, 4800, 4800, 4800, 4800, 6848, 6880, 6912, 4800, 4800, 4800, 6944, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 6976, 7008, 4800, 7040, 7072, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 6368, 6368, 6368, 6368, 7104, 6368, 7136, 7168, 6368, 6368, 6368, 6368, 6368, 6368, 6368, 6368, 4800, 7200, 7232, 7264, 7296, 7328, 7360, 7392, 7424, 7456, 7488, 7520, 224, 224, 224, 7552, 7584, 7616, 1344, 7648, 7680, 7712, 7712, 704, 7744, 7776, 7808, 1792, 7840, 4800, 4800, 7872, 4800, 4800, 4800, 4800, 4800, 4800, 7904, 7936, 7968, 8000, 3136, 1344, 8032, 4096, 1344, 8064, 8096, 8128, 1344, 1344, 8160, 8192, 4800, 8224, 8256, 8288, 8320, 4800, 8288, 8352, 4800, 8256, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 4576, 4800, 4800, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 4576, 1792, 8384, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 8416, 4800, 8448, 5280, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 8480, 8512, 224, 8544, 8576, 1344, 1344, 8608, 8640, 8672, 224, 8704, 8736, 8768, 1792, 8800, 8832, 8864, 1344, 8896, 8928, 8960, 8992, 9024, 1632, 9056, 9088, 9120, 1888, 9152, 9184, 9216, 1344, 9248, 9280, 9312, 1344, 9344, 9376, 9408, 9440, 9472, 9504, 9536, 9568, 9568, 1344, 9600, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 9632, 9664, 9696, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9728, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 9760, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 9792, 1344, 1344, 9824, 1792, 9856, 9888, 9920, 1344, 1344, 9952, 9984, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 10016, 10048, 1344, 10080, 1344, 10112, 10144, 10176, 10208, 10240, 10272, 1344, 1344, 1344, 10304, 10336, 64, 10368, 10400, 10432, 4608, 10464, 10496 #if TCL_UTF_MAX > 3 ,10528, 10560, 10592, 1792, 1344, 1344, 1344, 8192, 10624, 10656, 10688, 10720, 10752, 10784, 10816, 10848, 1792, 1792, 1792, 1792, 9120, 1344, 10880, 10912, 1344, 10944, 10976, 11008, 11040, 1344, 11072, 1792, 11104, 11136, 11168, 1344, 11200, 11232, 1792, 1792, 1344, 11264, 1344, 11296, 1792, 1792, 1792, 1792, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 7680, 4576, 10112, 1792, 1792, 1792, 1792, 11328, 11360, 11392, 11424, 4608, 11456, 1792, 11488, 11520, 11552, 1792, 1792, 1344, 11584, 11616, 6688, 11648, 11680, 11712, 11744, 11776, 1792, 11808, 11840, 1344, 11872, 11904, 11936, 11968, 12000, 1792, 1792, 1344, 1344, 12032, 1792, 12064, 12096, 12128, 12160, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 12192, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 12224, 12256, 12288, 12320, 5120, 12352, 12384, 12416, 12448, 12480, 12512, 12544, 5120, 12576, 12608, 12640, 12672, 12704, 1792, 1792, 12736, 12768, 12800, 12832, 12864, 2304, 12896, 12928, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1344, 12960, 12992, 1792, 1792, 1792, 1792, 1792, 1344, 13024, 13056, 1792, 1344, 13088, 13120, 1792, 1344, 13152, 11232, 1792, 13184, 13216, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 13248, 13280, 13312, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1344, 13344, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 9824, 1792, 1792, 1792, 10688, 10688, 10688, 13376, 1344, 1344, 1344, 1344, 1344, 1344, 13408, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 13440, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 13472, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 13344, 4608, 13504, 1792, 1792, 10048, 13536, 1344, 13568, 13600, 13632, 13664, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1344, 1344, 13696, 13728, 13760, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 13792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1344, 1344, 1344, 13824, 13856, 13888, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 7904, 4800, 13920, 4800, 13952, 13984, 14016, 4800, 14048, 4800, 4800, 14080, 1792, 1792, 1792, 1792, 1792, 4800, 4800, 14112, 14144, 1792, 1792, 1792, 1792, 14176, 14208, 14240, 14272, 14304, 14336, 14368, 14400, 14432, 14464, 14496, 14528, 14560, 14176, 14208, 14592, 14272, 14624, 14656, 14688, 14400, 14720, 14752, 14784, 14816, 14848, 14880, 14912, 14944, 14976, 15008, 15040, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 704, 15072, 704, 15104, 15136, 15168, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1344, 1344, 1344, 1344, 1344, 1344, 15200, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 15232, 15264, 15296, 15328, 15360, 15392, 1792, 15424, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 4800, 15456, 4800, 4800, 7872, 15488, 15520, 7904, 15552, 15584, 4800, 15456, 15616, 1792, 1792, 15648, 15680, 15616, 15712, 1792, 1792, 1792, 1792, 1792, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 15744, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 7840, 4800, 15776, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 4800, 15808, 15840, 4800, 4800, 4800, 7872, 4800, 4800, 15872, 1792, 15456, 4800, 15904, 4800, 15936, 15968, 1792, 1792, 16000, 1792, 1792, 1792, 16032, 1792, 10784, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 7680, 1792, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 11200, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 13792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 11200 #endif /* TCL_UTF_MAX > 3 */ }; /* * The groupMap is indexed by combining the alternate page number with * the page offset and returns a group number that identifies a unique * set of character attributes. */ static const unsigned char groupMap[] = { 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, 3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 7, 7, 7, 3, 3, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 5, 3, 6, 11, 12, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 5, 7, 6, 7, 1, 2, 3, 4, 4, 4, 4, 14, 3, 11, 14, 15, 16, 7, 17, 14, 11, 14, 7, 18, 18, 11, 19, 3, 3, 11, 18, 15, 20, 18, 18, 18, 3, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 7, 10, 10, 10, 10, 10, 10, 10, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 13, 13, 13, 13, 13, 13, 13, 22, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 25, 26, 23, 24, 23, 24, 23, 24, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 27, 23, 24, 23, 24, 23, 24, 28, 29, 30, 23, 24, 23, 24, 31, 23, 24, 32, 32, 23, 24, 21, 33, 34, 35, 23, 24, 32, 36, 37, 38, 39, 23, 24, 40, 21, 38, 41, 42, 43, 23, 24, 23, 24, 23, 24, 44, 23, 24, 44, 21, 21, 23, 24, 44, 23, 24, 45, 45, 23, 24, 23, 24, 46, 23, 24, 21, 15, 23, 24, 21, 47, 15, 15, 15, 15, 48, 49, 50, 48, 49, 50, 48, 49, 50, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 51, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 21, 48, 49, 50, 23, 24, 52, 53, 23, 24, 23, 24, 23, 24, 23, 24, 54, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 21, 21, 21, 21, 21, 21, 55, 23, 24, 56, 57, 58, 58, 23, 24, 59, 60, 61, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 62, 63, 64, 65, 66, 21, 67, 67, 21, 68, 21, 69, 70, 21, 21, 21, 67, 71, 21, 72, 21, 73, 74, 21, 75, 76, 21, 77, 78, 21, 21, 76, 21, 79, 80, 21, 21, 81, 21, 21, 21, 21, 21, 21, 21, 82, 21, 21, 83, 21, 21, 83, 21, 21, 21, 84, 83, 85, 86, 86, 87, 21, 21, 21, 21, 21, 88, 21, 15, 21, 21, 21, 21, 21, 21, 21, 21, 89, 90, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 11, 11, 11, 11, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 91, 91, 91, 91, 91, 11, 11, 11, 11, 11, 11, 11, 91, 11, 91, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 23, 24, 23, 24, 91, 11, 23, 24, 0, 0, 91, 42, 42, 42, 3, 94, 0, 0, 0, 0, 11, 11, 95, 3, 96, 96, 96, 0, 97, 0, 98, 98, 21, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 99, 100, 100, 100, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 101, 13, 13, 13, 13, 13, 13, 13, 13, 13, 102, 103, 103, 104, 105, 106, 107, 107, 107, 108, 109, 110, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 111, 112, 113, 114, 115, 116, 7, 23, 24, 117, 23, 24, 21, 54, 54, 54, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 23, 24, 14, 92, 92, 92, 92, 92, 119, 119, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 120, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 121, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 0, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 0, 0, 91, 3, 3, 3, 3, 3, 3, 0, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 21, 0, 3, 8, 0, 0, 14, 14, 4, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 8, 92, 3, 92, 92, 3, 92, 92, 3, 92, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 7, 7, 7, 3, 3, 4, 3, 3, 14, 14, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 17, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 15, 92, 92, 92, 92, 92, 92, 92, 17, 14, 92, 92, 92, 92, 92, 92, 91, 91, 92, 92, 14, 92, 92, 92, 92, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 14, 14, 15, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 17, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 91, 14, 3, 3, 3, 91, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 92, 92, 92, 91, 92, 92, 92, 92, 92, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 0, 0, 3, 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, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 92, 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 124, 124, 92, 124, 124, 15, 92, 92, 92, 92, 92, 92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 0, 0, 15, 15, 15, 15, 0, 0, 92, 15, 124, 124, 124, 92, 92, 92, 92, 0, 0, 124, 124, 0, 0, 124, 124, 92, 15, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 15, 15, 0, 15, 15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 4, 4, 18, 18, 18, 18, 18, 18, 14, 4, 0, 0, 0, 0, 0, 92, 92, 124, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 0, 15, 15, 0, 0, 92, 0, 124, 124, 124, 92, 92, 0, 0, 0, 0, 92, 92, 0, 0, 92, 92, 92, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 15, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 92, 92, 15, 15, 15, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 92, 15, 124, 124, 124, 92, 92, 92, 92, 92, 0, 92, 92, 124, 0, 124, 124, 92, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 4, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 92, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 92, 15, 124, 92, 124, 92, 92, 92, 92, 0, 0, 124, 124, 0, 0, 124, 124, 92, 0, 0, 0, 0, 0, 0, 0, 0, 92, 124, 0, 0, 0, 0, 15, 15, 0, 15, 15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 15, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 0, 15, 15, 0, 15, 0, 15, 15, 0, 0, 0, 15, 15, 0, 0, 0, 15, 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 124, 124, 92, 124, 124, 0, 0, 0, 124, 124, 124, 0, 124, 124, 124, 92, 0, 0, 15, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 14, 14, 14, 14, 14, 14, 4, 14, 0, 0, 0, 0, 0, 92, 124, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 92, 92, 92, 124, 124, 124, 124, 0, 92, 92, 92, 0, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 92, 92, 0, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 14, 0, 92, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 92, 15, 124, 92, 124, 124, 124, 124, 124, 0, 92, 124, 124, 0, 124, 124, 92, 92, 0, 0, 0, 0, 0, 0, 0, 124, 124, 0, 0, 0, 0, 0, 0, 0, 15, 0, 15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 124, 124, 124, 92, 92, 92, 92, 0, 124, 124, 124, 0, 124, 124, 124, 92, 15, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, 0, 0, 0, 14, 15, 15, 15, 15, 15, 15, 0, 0, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 92, 0, 0, 0, 0, 124, 124, 124, 92, 92, 92, 0, 92, 0, 124, 124, 124, 124, 124, 124, 124, 124, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 124, 124, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 15, 15, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 4, 15, 15, 15, 15, 15, 15, 91, 92, 92, 92, 92, 92, 92, 92, 92, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 0, 0, 0, 0, 0, 15, 15, 0, 15, 0, 0, 15, 15, 0, 15, 0, 0, 15, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 0, 15, 0, 0, 15, 15, 0, 15, 15, 15, 15, 92, 15, 15, 92, 92, 92, 92, 92, 92, 0, 92, 92, 15, 0, 0, 15, 15, 15, 15, 15, 0, 91, 0, 92, 92, 92, 92, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 15, 15, 15, 15, 15, 14, 14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 14, 3, 14, 14, 14, 92, 92, 14, 14, 14, 14, 14, 14, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 92, 14, 92, 14, 92, 5, 6, 5, 6, 124, 124, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, 3, 92, 92, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 14, 14, 14, 14, 14, 14, 14, 14, 92, 14, 14, 14, 14, 14, 14, 0, 14, 14, 3, 3, 3, 3, 3, 14, 14, 14, 14, 3, 3, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, 92, 124, 92, 92, 124, 124, 92, 92, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 124, 124, 92, 92, 15, 15, 15, 15, 92, 92, 92, 15, 124, 124, 124, 15, 15, 124, 124, 124, 124, 124, 124, 124, 15, 15, 15, 92, 92, 92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 124, 92, 92, 124, 124, 124, 124, 124, 124, 92, 15, 124, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 124, 124, 124, 92, 14, 14, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 0, 125, 0, 0, 0, 0, 0, 125, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 92, 92, 92, 3, 3, 3, 3, 3, 3, 3, 3, 3, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 104, 104, 104, 104, 104, 104, 0, 0, 110, 110, 110, 110, 110, 110, 0, 0, 8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 5, 6, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 3, 127, 127, 127, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 124, 92, 92, 92, 92, 92, 92, 92, 124, 124, 124, 124, 124, 124, 124, 124, 92, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 3, 3, 91, 3, 3, 3, 4, 15, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 8, 3, 3, 3, 3, 92, 92, 92, 17, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 92, 92, 92, 124, 124, 124, 124, 92, 92, 124, 124, 124, 0, 0, 0, 0, 124, 124, 92, 124, 124, 124, 124, 124, 124, 92, 92, 92, 0, 0, 0, 0, 14, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 124, 124, 92, 0, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 92, 124, 92, 92, 92, 92, 92, 92, 92, 0, 92, 124, 92, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 124, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 92, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 91, 3, 3, 3, 3, 3, 3, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 119, 0, 92, 92, 92, 92, 124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 92, 92, 92, 92, 92, 124, 92, 124, 124, 124, 124, 124, 92, 124, 124, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 3, 3, 3, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 92, 92, 92, 92, 92, 92, 92, 92, 92, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 92, 92, 124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 92, 92, 92, 92, 124, 124, 92, 92, 124, 92, 92, 92, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 92, 92, 124, 124, 124, 92, 124, 92, 92, 92, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 15, 15, 15, 15, 124, 124, 124, 124, 124, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 92, 92, 0, 0, 0, 3, 3, 3, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 91, 91, 91, 91, 91, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 3, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, 92, 92, 15, 15, 15, 15, 92, 15, 15, 15, 15, 124, 124, 92, 15, 15, 0, 92, 92, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 91, 128, 21, 21, 21, 129, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 91, 91, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 21, 21, 21, 21, 21, 130, 21, 21, 131, 21, 132, 132, 132, 132, 132, 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 0, 0, 133, 133, 133, 133, 133, 133, 0, 0, 132, 132, 132, 132, 132, 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 0, 0, 133, 133, 133, 133, 133, 133, 0, 0, 21, 132, 21, 132, 21, 132, 21, 132, 0, 133, 0, 133, 0, 133, 0, 133, 132, 132, 132, 132, 132, 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, 133, 134, 134, 135, 135, 135, 135, 136, 136, 137, 137, 138, 138, 139, 139, 0, 0, 132, 132, 132, 132, 132, 132, 132, 132, 140, 140, 140, 140, 140, 140, 140, 140, 132, 132, 132, 132, 132, 132, 132, 132, 140, 140, 140, 140, 140, 140, 140, 140, 132, 132, 132, 132, 132, 132, 132, 132, 140, 140, 140, 140, 140, 140, 140, 140, 132, 132, 21, 141, 21, 0, 21, 21, 133, 133, 142, 142, 143, 11, 144, 11, 11, 11, 21, 141, 21, 0, 21, 21, 145, 145, 145, 145, 143, 11, 11, 11, 132, 132, 21, 21, 0, 0, 21, 21, 133, 133, 146, 146, 0, 11, 11, 11, 132, 132, 21, 21, 21, 113, 21, 21, 133, 133, 147, 147, 117, 11, 11, 11, 0, 0, 21, 141, 21, 0, 21, 21, 148, 148, 149, 149, 143, 11, 11, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 17, 8, 8, 8, 8, 8, 8, 3, 3, 16, 20, 5, 16, 16, 20, 5, 16, 3, 3, 3, 3, 3, 3, 3, 3, 150, 151, 17, 17, 17, 17, 17, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 16, 20, 3, 3, 3, 3, 12, 12, 3, 3, 3, 7, 5, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 12, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 91, 0, 0, 18, 18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 91, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 0, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 119, 119, 119, 119, 92, 119, 119, 119, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 107, 14, 14, 14, 14, 107, 14, 14, 21, 107, 107, 107, 21, 21, 107, 107, 107, 21, 14, 107, 14, 14, 7, 107, 107, 107, 107, 107, 14, 14, 14, 14, 14, 14, 107, 14, 152, 14, 107, 14, 153, 154, 107, 107, 14, 21, 107, 107, 155, 107, 21, 15, 15, 15, 15, 21, 14, 14, 21, 21, 107, 107, 7, 7, 7, 7, 7, 107, 21, 21, 21, 21, 14, 7, 14, 14, 156, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 127, 127, 127, 23, 24, 127, 127, 127, 127, 18, 14, 14, 0, 0, 0, 0, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 7, 7, 14, 14, 14, 14, 7, 14, 14, 7, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 14, 14, 7, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 14, 14, 14, 14, 14, 14, 14, 5, 6, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 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, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 0, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 0, 23, 24, 161, 162, 163, 164, 165, 23, 24, 23, 24, 23, 24, 166, 167, 168, 169, 21, 23, 24, 21, 23, 24, 21, 21, 21, 21, 21, 91, 91, 170, 170, 23, 24, 23, 24, 21, 14, 14, 14, 14, 14, 14, 23, 24, 23, 24, 92, 92, 92, 23, 24, 0, 0, 0, 0, 0, 3, 3, 3, 3, 18, 3, 3, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 0, 171, 0, 0, 0, 0, 0, 171, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 91, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 3, 3, 16, 20, 16, 20, 3, 3, 3, 16, 20, 3, 16, 20, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 3, 3, 8, 3, 16, 20, 3, 3, 16, 20, 5, 6, 5, 6, 5, 6, 5, 6, 3, 3, 3, 3, 3, 91, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 8, 3, 5, 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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 2, 3, 3, 3, 14, 91, 15, 127, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 14, 14, 5, 6, 5, 6, 5, 6, 5, 6, 8, 5, 6, 6, 14, 127, 127, 127, 127, 127, 127, 127, 127, 127, 92, 92, 92, 92, 124, 124, 8, 91, 91, 91, 91, 91, 14, 14, 127, 127, 127, 91, 15, 3, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 92, 92, 11, 11, 91, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 91, 91, 91, 15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 14, 14, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 15, 92, 119, 119, 119, 3, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 91, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 91, 91, 92, 92, 15, 15, 15, 15, 15, 15, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 92, 92, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 91, 91, 91, 91, 91, 91, 91, 91, 91, 11, 11, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 21, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 91, 21, 21, 21, 21, 21, 21, 21, 21, 23, 24, 23, 24, 172, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 91, 11, 11, 23, 24, 173, 21, 15, 23, 24, 23, 24, 21, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 174, 175, 176, 177, 0, 0, 178, 179, 180, 181, 23, 24, 23, 24, 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, 0, 0, 15, 91, 91, 21, 15, 15, 15, 15, 15, 15, 15, 92, 15, 15, 15, 92, 15, 15, 15, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 92, 92, 124, 14, 14, 14, 14, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 14, 14, 4, 14, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 124, 124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 15, 15, 15, 15, 15, 15, 3, 3, 3, 15, 3, 15, 0, 0, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 124, 92, 92, 92, 92, 124, 124, 92, 124, 124, 124, 124, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 91, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 15, 15, 15, 15, 15, 92, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 124, 124, 92, 92, 124, 124, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 14, 14, 14, 15, 124, 92, 124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 15, 92, 92, 92, 15, 15, 92, 92, 15, 15, 15, 15, 15, 92, 92, 15, 92, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 91, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 92, 92, 124, 124, 3, 3, 15, 91, 91, 124, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 182, 21, 21, 21, 21, 21, 21, 21, 11, 91, 91, 91, 91, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 15, 15, 15, 124, 124, 92, 124, 124, 92, 124, 124, 3, 124, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 4, 14, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 3, 3, 3, 3, 3, 3, 5, 6, 3, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 8, 8, 12, 12, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 3, 3, 5, 6, 3, 3, 3, 3, 12, 12, 12, 3, 3, 3, 0, 3, 3, 3, 3, 8, 5, 6, 5, 6, 5, 6, 3, 3, 3, 7, 8, 7, 7, 7, 0, 3, 4, 3, 3, 0, 0, 0, 0, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 17, 0, 3, 3, 3, 4, 3, 3, 3, 5, 6, 3, 7, 3, 8, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 7, 7, 7, 3, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 5, 7, 6, 7, 5, 6, 3, 5, 6, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 91, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 0, 0, 0, 4, 4, 7, 11, 14, 4, 4, 0, 14, 7, 7, 7, 7, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 14, 14, 0, 0 #if TCL_UTF_MAX > 3 ,15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 3, 3, 3, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 92, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 15, 15, 15, 15, 15, 15, 15, 15, 127, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 3, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 3, 127, 127, 127, 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 0, 0, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 3, 18, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 18, 18, 18, 18, 18, 18, 0, 0, 0, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 18, 18, 15, 15, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 15, 92, 92, 92, 0, 92, 92, 0, 0, 0, 0, 0, 92, 92, 92, 92, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 92, 92, 92, 0, 0, 0, 0, 92, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 18, 18, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 0, 0, 0, 0, 18, 18, 18, 18, 18, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 124, 92, 124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, 92, 124, 124, 92, 92, 3, 3, 17, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 92, 92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, 92, 92, 92, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 15, 15, 15, 15, 3, 3, 3, 3, 3, 92, 92, 92, 3, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 3, 15, 3, 3, 3, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, 124, 124, 92, 124, 92, 92, 3, 3, 3, 3, 3, 3, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 92, 92, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 124, 124, 124, 0, 0, 124, 124, 0, 0, 124, 124, 124, 0, 0, 15, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 124, 124, 0, 0, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 124, 92, 124, 124, 124, 124, 92, 92, 124, 92, 92, 15, 15, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, 92, 0, 0, 124, 124, 124, 124, 92, 92, 124, 92, 92, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 92, 92, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 92, 124, 92, 92, 3, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 92, 124, 124, 92, 92, 92, 92, 92, 92, 124, 92, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 92, 92, 92, 124, 124, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 3, 3, 3, 14, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 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, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 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, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 92, 92, 92, 92, 92, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 3, 3, 3, 3, 3, 14, 14, 14, 14, 91, 91, 91, 91, 3, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 18, 18, 18, 18, 18, 18, 18, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 15, 15, 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, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 14, 92, 92, 3, 17, 17, 17, 17, 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, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 124, 124, 92, 92, 92, 14, 14, 14, 124, 124, 124, 124, 124, 124, 17, 17, 17, 17, 17, 17, 17, 17, 92, 92, 92, 92, 92, 92, 92, 92, 14, 14, 92, 92, 92, 92, 92, 92, 92, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 92, 92, 92, 92, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 92, 92, 92, 14, 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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 0, 107, 107, 0, 0, 107, 0, 0, 107, 107, 0, 0, 107, 107, 107, 107, 0, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 0, 21, 0, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 0, 107, 107, 107, 107, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 0, 107, 107, 107, 107, 107, 107, 107, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 0, 107, 107, 107, 107, 0, 107, 107, 107, 107, 107, 0, 107, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, 21, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 14, 14, 14, 14, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 14, 14, 14, 14, 14, 14, 14, 14, 92, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 92, 14, 14, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 0, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 0, 15, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 15, 0, 15, 0, 15, 15, 15, 0, 15, 15, 0, 15, 0, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 15, 0, 15, 0, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, 11, 11, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 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, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 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 #endif /* TCL_UTF_MAX > 3 */ }; /* * Each group represents a unique set of character attributes. The attributes * are encoded into a 32-bit value as follows: * * Bits 0-4 Character category: see the constants listed below. * * Bits 5-7 Case delta type: 000 = identity * 010 = add delta for lower * 011 = add delta for lower, add 1 for title * 100 = subtract delta for title/upper * 101 = sub delta for upper, sub 1 for title * 110 = sub delta for upper, add delta for lower * * Bits 8-31 Case delta: delta for case conversions. This should be the * highest field so we can easily sign extend. */ static const int groups[] = { 0, 15, 12, 25, 27, 21, 22, 26, 20, 9, 8257, 28, 19, 8322, 29, 5, 23, 16, 11, -190078, 24, 2, -30846, 321, 386, -50879, 59522, -30911, 76930, -49790, 53825, 52801, 52545, 20289, 51777, 52033, 53057, -24702, 54081, 53569, -41598, 54593, -33150, 54849, 55873, 55617, 56129, -14206, 609, 451, 674, 20354, -24767, -14271, -33215, 2763585, -41663, 2762817, -2768510, -49855, 17729, 18241, -2760318, -2759550, -2760062, 53890, 52866, 52610, 51842, 52098, -10833534, -10832510, 53122, -10823550, -10830718, 53634, 54146, -2750078, -10829950, -2751614, 54658, 54914, -2745982, 55938, -10824062, 17794, 55682, 18306, 56194, -10818686, -10817918, 4, 6, -21370, 29761, 9793, 9537, 16449, 16193, 9858, 9602, 8066, 16514, 16258, 2113, 16002, 14722, 1, 12162, 13954, 2178, 22146, 20610, -1662, 29826, -15295, 24706, -1727, 20545, 7, 3905, 3970, 12353, 12418, 8, 1859649, 9949249, 10, -9044862, -976254, 15234, -1949375, -1918, -1983, -18814, -21886, -25470, -32638, -28542, -32126, -1981, -2174, -18879, -2237, 1844610, -21951, -25535, -28607, -32703, -32191, 13, 14, -1924287, -2145983, -2115007, 7233, 7298, 4170, 4234, 6749, 6813, -2750143, -976319, -2746047, 2763650, 2762882, -2759615, -2751679, -2760383, -2760127, -2768575, 1859714, -9044927, -10823615, -10830783, -10833599, -10832575, -10830015, -10817983, -10824127, -10818751, 237633, 237698, 9949314, 18, 17, 10305, 10370 }; #if TCL_UTF_MAX > 3 # define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1fffff) >= 0x2fa20) #else # define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1f0000) != 0) #endif /* * The following constants are used to determine the category of a * Unicode character. */ enum { UNASSIGNED, UPPERCASE_LETTER, LOWERCASE_LETTER, TITLECASE_LETTER, MODIFIER_LETTER, OTHER_LETTER, NON_SPACING_MARK, ENCLOSING_MARK, COMBINING_SPACING_MARK, DECIMAL_DIGIT_NUMBER, LETTER_NUMBER, OTHER_NUMBER, SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, PRIVATE_USE, SURROGATE, CONNECTOR_PUNCTUATION, DASH_PUNCTUATION, OPEN_PUNCTUATION, CLOSE_PUNCTUATION, INITIAL_QUOTE_PUNCTUATION, FINAL_QUOTE_PUNCTUATION, OTHER_PUNCTUATION, MATH_SYMBOL, CURRENCY_SYMBOL, MODIFIER_SYMBOL, OTHER_SYMBOL }; /* * The following macros extract the fields of the character info. The * GetDelta() macro is complicated because we can't rely on the C compiler * to do sign extension on right shifts. */ #define GetCaseType(info) (((info) & 0xe0) >> 5) #define GetCategory(ch) (GetUniCharInfo(ch) & 0x1f) #define GetDelta(info) ((info) >> 8) /* * This macro extracts the information about a character from the * Unicode character tables. */ #if TCL_UTF_MAX > 3 # define GetUniCharInfo(ch) (groups[groupMap[pageMap[((ch) & 0x1fffff) >> OFFSET_BITS] | ((ch) & ((1 << OFFSET_BITS)-1))]]) #else # define GetUniCharInfo(ch) (groups[groupMap[pageMap[((ch) & 0xffff) >> OFFSET_BITS] | ((ch) & ((1 << OFFSET_BITS)-1))]]) #endif tcl8.6.5/generic/tclStubInit.c0000644000175000017500000012250612665173571015624 0ustar sergeisergei/* * tclStubInit.c -- * * This file contains the initializers for the Tcl stub vectors. * * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tommath.h" #ifdef __GNUC__ #pragma GCC dependency "tcl.decls" #pragma GCC dependency "tclInt.decls" #pragma GCC dependency "tclTomMath.decls" #endif /* * Remove macros that will interfere with the definitions below. */ #undef Tcl_Alloc #undef Tcl_Free #undef Tcl_Realloc #undef Tcl_NewBooleanObj #undef Tcl_NewByteArrayObj #undef Tcl_NewDoubleObj #undef Tcl_NewIntObj #undef Tcl_NewListObj #undef Tcl_NewLongObj #undef Tcl_NewObj #undef Tcl_NewStringObj #undef Tcl_DumpActiveMemory #undef Tcl_ValidateAllMemory #undef Tcl_FindHashEntry #undef Tcl_CreateHashEntry #undef Tcl_Panic #undef Tcl_FindExecutable #undef TclpGetPid #undef TclSockMinimumBuffers #define TclBackgroundException Tcl_BackgroundException #undef Tcl_SetIntObj #undef TclpInetNtoa #undef TclWinGetServByName #undef TclWinGetSockOpt #undef TclWinSetSockOpt /* See bug 510001: TclSockMinimumBuffers needs plat imp */ #ifdef _WIN64 # define TclSockMinimumBuffersOld 0 #else #define TclSockMinimumBuffersOld sockMinimumBuffersOld static int TclSockMinimumBuffersOld(int sock, int size) { return TclSockMinimumBuffers(INT2PTR(sock), size); } #endif #define TclSetStartupScriptPath setStartupScriptPath static void TclSetStartupScriptPath(Tcl_Obj *path) { Tcl_SetStartupScript(path, NULL); } #define TclGetStartupScriptPath getStartupScriptPath static Tcl_Obj *TclGetStartupScriptPath(void) { return Tcl_GetStartupScript(NULL); } #define TclSetStartupScriptFileName setStartupScriptFileName static void TclSetStartupScriptFileName( const char *fileName) { Tcl_SetStartupScript(Tcl_NewStringObj(fileName,-1), NULL); } #define TclGetStartupScriptFileName getStartupScriptFileName static const char *TclGetStartupScriptFileName(void) { Tcl_Obj *path = Tcl_GetStartupScript(NULL); if (path == NULL) { return NULL; } return Tcl_GetString(path); } #if defined(_WIN32) || defined(__CYGWIN__) #undef TclWinNToHS #define TclWinNToHS winNToHS static unsigned short TclWinNToHS(unsigned short ns) { return ntohs(ns); } #endif #ifdef _WIN32 # define TclUnixWaitForFile 0 # define TclUnixCopyFile 0 # define TclUnixOpenTemporaryFile 0 # define TclpReaddir 0 # define TclpIsAtty 0 #elif defined(__CYGWIN__) # define TclpIsAtty TclPlatIsAtty # define TclWinSetInterfaces (void (*) (int)) doNothing # define TclWinAddProcess (void (*) (void *, unsigned int)) doNothing # define TclWinFlushDirtyChannels doNothing # define TclWinResetInterfaces doNothing static Tcl_Encoding winTCharEncoding; static int TclpIsAtty(int fd) { return isatty(fd); } #define TclWinGetPlatformId winGetPlatformId static int TclWinGetPlatformId() { /* Don't bother to determine the real platform on cygwin, * because VER_PLATFORM_WIN32_NT is the only supported platform */ return 2; /* VER_PLATFORM_WIN32_NT */; } void *TclWinGetTclInstance() { void *hInstance = NULL; GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const char *)&winTCharEncoding, &hInstance); return hInstance; } #define TclWinSetSockOpt winSetSockOpt static int TclWinSetSockOpt(SOCKET s, int level, int optname, const char *optval, int optlen) { return setsockopt((int) s, level, optname, optval, optlen); } #define TclWinGetSockOpt winGetSockOpt static int TclWinGetSockOpt(SOCKET s, int level, int optname, char *optval, int *optlen) { return getsockopt((int) s, level, optname, optval, optlen); } #define TclWinGetServByName winGetServByName static struct servent * TclWinGetServByName(const char *name, const char *proto) { return getservbyname(name, proto); } #define TclWinNoBackslash winNoBackslash static char * TclWinNoBackslash(char *path) { char *p; for (p = path; *p != '\0'; p++) { if (*p == '\\') { *p = '/'; } } return path; } int TclpGetPid(Tcl_Pid pid) { return (int) (size_t) pid; } static void doNothing(void) { /* dummy implementation, no need to do anything */ } char * Tcl_WinUtfToTChar( const char *string, int len, Tcl_DString *dsPtr) { if (!winTCharEncoding) { winTCharEncoding = Tcl_GetEncoding(0, "unicode"); } return Tcl_UtfToExternalDString(winTCharEncoding, string, len, dsPtr); } char * Tcl_WinTCharToUtf( const char *string, int len, Tcl_DString *dsPtr) { if (!winTCharEncoding) { winTCharEncoding = Tcl_GetEncoding(0, "unicode"); } return Tcl_ExternalToUtfDString(winTCharEncoding, string, len, dsPtr); } #if defined(TCL_WIDE_INT_IS_LONG) /* On Cygwin64, long is 64-bit while on Win64 long is 32-bit. Therefore * we have to make sure that all stub entries on Cygwin64 follow the Win64 * signature. Tcl 9 must find a better solution, but that cannot be done * without introducing a binary incompatibility. */ #define Tcl_DbNewLongObj ((Tcl_Obj*(*)(long,const char*,int))dbNewLongObj) static Tcl_Obj *dbNewLongObj( int intValue, const char *file, int line ) { #ifdef TCL_MEM_DEBUG register Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); objPtr->bytes = NULL; objPtr->internalRep.longValue = (long) intValue; objPtr->typePtr = &tclIntType; return objPtr; #else return Tcl_NewIntObj(intValue); #endif } #define Tcl_GetLongFromObj (int(*)(Tcl_Interp*,Tcl_Obj*,long*))Tcl_GetIntFromObj #define Tcl_NewLongObj (Tcl_Obj*(*)(long))Tcl_NewIntObj #define Tcl_SetLongObj (void(*)(Tcl_Obj*,long))Tcl_SetIntObj static int exprInt(Tcl_Interp *interp, const char *expr, int *ptr){ long longValue; int result = Tcl_ExprLong(interp, expr, &longValue); if (result == TCL_OK) { if ((longValue >= -(long)(UINT_MAX)) && (longValue <= (long)(UINT_MAX))) { *ptr = (int)longValue; } else { Tcl_SetObjResult(interp, Tcl_NewStringObj( "integer value too large to represent as non-long integer", -1)); result = TCL_ERROR; } } return result; } #define Tcl_ExprLong (int(*)(Tcl_Interp*,const char*,long*))exprInt static int exprIntObj(Tcl_Interp *interp, Tcl_Obj*expr, int *ptr){ long longValue; int result = Tcl_ExprLongObj(interp, expr, &longValue); if (result == TCL_OK) { if ((longValue >= -(long)(UINT_MAX)) && (longValue <= (long)(UINT_MAX))) { *ptr = (int)longValue; } else { Tcl_SetObjResult(interp, Tcl_NewStringObj( "integer value too large to represent as non-long integer", -1)); result = TCL_ERROR; } } return result; } #define Tcl_ExprLongObj (int(*)(Tcl_Interp*,Tcl_Obj*,long*))exprIntObj static int uniCharNcmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsigned int n){ return Tcl_UniCharNcmp(ucs, uct, (unsigned long)n); } #define Tcl_UniCharNcmp (int(*)(const Tcl_UniChar*,const Tcl_UniChar*,unsigned long))uniCharNcmp static int utfNcmp(const char *s1, const char *s2, unsigned int n){ return Tcl_UtfNcmp(s1, s2, (unsigned long)n); } #define Tcl_UtfNcmp (int(*)(const char*,const char*,unsigned long))utfNcmp static int utfNcasecmp(const char *s1, const char *s2, unsigned int n){ return Tcl_UtfNcasecmp(s1, s2, (unsigned long)n); } #define Tcl_UtfNcasecmp (int(*)(const char*,const char*,unsigned long))utfNcasecmp static int uniCharNcasecmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsigned int n){ return Tcl_UniCharNcasecmp(ucs, uct, (unsigned long)n); } #define Tcl_UniCharNcasecmp (int(*)(const Tcl_UniChar*,const Tcl_UniChar*,unsigned long))uniCharNcasecmp static int formatInt(char *buffer, int n){ return TclFormatInt(buffer, (long)n); } #define TclFormatInt (int(*)(char *, long))formatInt #endif #else /* UNIX and MAC */ # define TclpLocaltime_unix TclpLocaltime # define TclpGmtime_unix TclpGmtime #endif /* * WARNING: The contents of this file is automatically generated by the * tools/genStubs.tcl script. Any modifications to the function declarations * below should be made in the generic/tcl.decls script. */ MODULE_SCOPE const TclStubs tclStubs; MODULE_SCOPE const TclTomMathStubs tclTomMathStubs; /* !BEGIN!: Do not edit below this line. */ static const TclIntStubs tclIntStubs = { TCL_STUB_MAGIC, 0, 0, /* 0 */ 0, /* 1 */ 0, /* 2 */ TclAllocateFreeObjects, /* 3 */ 0, /* 4 */ TclCleanupChildren, /* 5 */ TclCleanupCommand, /* 6 */ TclCopyAndCollapse, /* 7 */ TclCopyChannelOld, /* 8 */ TclCreatePipeline, /* 9 */ TclCreateProc, /* 10 */ TclDeleteCompiledLocalVars, /* 11 */ TclDeleteVars, /* 12 */ 0, /* 13 */ TclDumpMemoryInfo, /* 14 */ 0, /* 15 */ TclExprFloatError, /* 16 */ 0, /* 17 */ 0, /* 18 */ 0, /* 19 */ 0, /* 20 */ 0, /* 21 */ TclFindElement, /* 22 */ TclFindProc, /* 23 */ TclFormatInt, /* 24 */ TclFreePackageInfo, /* 25 */ 0, /* 26 */ 0, /* 27 */ TclpGetDefaultStdChannel, /* 28 */ 0, /* 29 */ 0, /* 30 */ TclGetExtension, /* 31 */ TclGetFrame, /* 32 */ 0, /* 33 */ TclGetIntForIndex, /* 34 */ 0, /* 35 */ 0, /* 36 */ TclGetLoadedPackages, /* 37 */ TclGetNamespaceForQualName, /* 38 */ TclGetObjInterpProc, /* 39 */ TclGetOpenMode, /* 40 */ TclGetOriginalCommand, /* 41 */ TclpGetUserHome, /* 42 */ 0, /* 43 */ TclGuessPackageName, /* 44 */ TclHideUnsafeCommands, /* 45 */ TclInExit, /* 46 */ 0, /* 47 */ 0, /* 48 */ 0, /* 49 */ TclInitCompiledLocals, /* 50 */ TclInterpInit, /* 51 */ 0, /* 52 */ TclInvokeObjectCommand, /* 53 */ TclInvokeStringCommand, /* 54 */ TclIsProc, /* 55 */ 0, /* 56 */ 0, /* 57 */ TclLookupVar, /* 58 */ 0, /* 59 */ TclNeedSpace, /* 60 */ TclNewProcBodyObj, /* 61 */ TclObjCommandComplete, /* 62 */ TclObjInterpProc, /* 63 */ TclObjInvoke, /* 64 */ 0, /* 65 */ 0, /* 66 */ 0, /* 67 */ 0, /* 68 */ TclpAlloc, /* 69 */ 0, /* 70 */ 0, /* 71 */ 0, /* 72 */ 0, /* 73 */ TclpFree, /* 74 */ TclpGetClicks, /* 75 */ TclpGetSeconds, /* 76 */ TclpGetTime, /* 77 */ 0, /* 78 */ 0, /* 79 */ 0, /* 80 */ TclpRealloc, /* 81 */ 0, /* 82 */ 0, /* 83 */ 0, /* 84 */ 0, /* 85 */ 0, /* 86 */ 0, /* 87 */ TclPrecTraceProc, /* 88 */ TclPreventAliasLoop, /* 89 */ 0, /* 90 */ TclProcCleanupProc, /* 91 */ TclProcCompileProc, /* 92 */ TclProcDeleteProc, /* 93 */ 0, /* 94 */ 0, /* 95 */ TclRenameCommand, /* 96 */ TclResetShadowedCmdRefs, /* 97 */ TclServiceIdle, /* 98 */ 0, /* 99 */ 0, /* 100 */ TclSetPreInitScript, /* 101 */ TclSetupEnv, /* 102 */ TclSockGetPort, /* 103 */ TclSockMinimumBuffersOld, /* 104 */ 0, /* 105 */ 0, /* 106 */ 0, /* 107 */ TclTeardownNamespace, /* 108 */ TclUpdateReturnInfo, /* 109 */ TclSockMinimumBuffers, /* 110 */ Tcl_AddInterpResolvers, /* 111 */ Tcl_AppendExportList, /* 112 */ Tcl_CreateNamespace, /* 113 */ Tcl_DeleteNamespace, /* 114 */ Tcl_Export, /* 115 */ Tcl_FindCommand, /* 116 */ Tcl_FindNamespace, /* 117 */ Tcl_GetInterpResolvers, /* 118 */ Tcl_GetNamespaceResolvers, /* 119 */ Tcl_FindNamespaceVar, /* 120 */ Tcl_ForgetImport, /* 121 */ Tcl_GetCommandFromObj, /* 122 */ Tcl_GetCommandFullName, /* 123 */ Tcl_GetCurrentNamespace, /* 124 */ Tcl_GetGlobalNamespace, /* 125 */ Tcl_GetVariableFullName, /* 126 */ Tcl_Import, /* 127 */ Tcl_PopCallFrame, /* 128 */ Tcl_PushCallFrame, /* 129 */ Tcl_RemoveInterpResolvers, /* 130 */ Tcl_SetNamespaceResolvers, /* 131 */ TclpHasSockets, /* 132 */ TclpGetDate, /* 133 */ 0, /* 134 */ 0, /* 135 */ 0, /* 136 */ 0, /* 137 */ TclGetEnv, /* 138 */ 0, /* 139 */ 0, /* 140 */ TclpGetCwd, /* 141 */ TclSetByteCodeFromAny, /* 142 */ TclAddLiteralObj, /* 143 */ TclHideLiteral, /* 144 */ TclGetAuxDataType, /* 145 */ TclHandleCreate, /* 146 */ TclHandleFree, /* 147 */ TclHandlePreserve, /* 148 */ TclHandleRelease, /* 149 */ TclRegAbout, /* 150 */ TclRegExpRangeUniChar, /* 151 */ TclSetLibraryPath, /* 152 */ TclGetLibraryPath, /* 153 */ 0, /* 154 */ 0, /* 155 */ TclRegError, /* 156 */ TclVarTraceExists, /* 157 */ TclSetStartupScriptFileName, /* 158 */ TclGetStartupScriptFileName, /* 159 */ 0, /* 160 */ TclChannelTransform, /* 161 */ TclChannelEventScriptInvoker, /* 162 */ TclGetInstructionTable, /* 163 */ TclExpandCodeArray, /* 164 */ TclpSetInitialEncodings, /* 165 */ TclListObjSetElement, /* 166 */ TclSetStartupScriptPath, /* 167 */ TclGetStartupScriptPath, /* 168 */ TclpUtfNcmp2, /* 169 */ TclCheckInterpTraces, /* 170 */ TclCheckExecutionTraces, /* 171 */ TclInThreadExit, /* 172 */ TclUniCharMatch, /* 173 */ 0, /* 174 */ TclCallVarTraces, /* 175 */ TclCleanupVar, /* 176 */ TclVarErrMsg, /* 177 */ Tcl_SetStartupScript, /* 178 */ Tcl_GetStartupScript, /* 179 */ 0, /* 180 */ 0, /* 181 */ TclpLocaltime, /* 182 */ TclpGmtime, /* 183 */ 0, /* 184 */ 0, /* 185 */ 0, /* 186 */ 0, /* 187 */ 0, /* 188 */ 0, /* 189 */ 0, /* 190 */ 0, /* 191 */ 0, /* 192 */ 0, /* 193 */ 0, /* 194 */ 0, /* 195 */ 0, /* 196 */ 0, /* 197 */ TclObjGetFrame, /* 198 */ 0, /* 199 */ TclpObjRemoveDirectory, /* 200 */ TclpObjCopyDirectory, /* 201 */ TclpObjCreateDirectory, /* 202 */ TclpObjDeleteFile, /* 203 */ TclpObjCopyFile, /* 204 */ TclpObjRenameFile, /* 205 */ TclpObjStat, /* 206 */ TclpObjAccess, /* 207 */ TclpOpenFileChannel, /* 208 */ 0, /* 209 */ 0, /* 210 */ 0, /* 211 */ TclpFindExecutable, /* 212 */ TclGetObjNameOfExecutable, /* 213 */ TclSetObjNameOfExecutable, /* 214 */ TclStackAlloc, /* 215 */ TclStackFree, /* 216 */ TclPushStackFrame, /* 217 */ TclPopStackFrame, /* 218 */ 0, /* 219 */ 0, /* 220 */ 0, /* 221 */ 0, /* 222 */ 0, /* 223 */ TclGetPlatform, /* 224 */ TclTraceDictPath, /* 225 */ TclObjBeingDeleted, /* 226 */ TclSetNsPath, /* 227 */ 0, /* 228 */ TclPtrMakeUpvar, /* 229 */ TclObjLookupVar, /* 230 */ TclGetNamespaceFromObj, /* 231 */ TclEvalObjEx, /* 232 */ TclGetSrcInfoForPc, /* 233 */ TclVarHashCreateVar, /* 234 */ TclInitVarHashTable, /* 235 */ TclBackgroundException, /* 236 */ TclResetCancellation, /* 237 */ TclNRInterpProc, /* 238 */ TclNRInterpProcCore, /* 239 */ TclNRRunCallbacks, /* 240 */ TclNREvalObjEx, /* 241 */ TclNREvalObjv, /* 242 */ TclDbDumpActiveObjects, /* 243 */ TclGetNamespaceChildTable, /* 244 */ TclGetNamespaceCommandTable, /* 245 */ TclInitRewriteEnsemble, /* 246 */ TclResetRewriteEnsemble, /* 247 */ TclCopyChannel, /* 248 */ TclDoubleDigits, /* 249 */ TclSetSlaveCancelFlags, /* 250 */ TclRegisterLiteral, /* 251 */ }; static const TclIntPlatStubs tclIntPlatStubs = { TCL_STUB_MAGIC, 0, #if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */ TclGetAndDetachPids, /* 0 */ TclpCloseFile, /* 1 */ TclpCreateCommandChannel, /* 2 */ TclpCreatePipe, /* 3 */ TclpCreateProcess, /* 4 */ 0, /* 5 */ TclpMakeFile, /* 6 */ TclpOpenFile, /* 7 */ TclUnixWaitForFile, /* 8 */ TclpCreateTempFile, /* 9 */ TclpReaddir, /* 10 */ TclpLocaltime_unix, /* 11 */ TclpGmtime_unix, /* 12 */ TclpInetNtoa, /* 13 */ TclUnixCopyFile, /* 14 */ 0, /* 15 */ 0, /* 16 */ 0, /* 17 */ 0, /* 18 */ 0, /* 19 */ 0, /* 20 */ 0, /* 21 */ 0, /* 22 */ 0, /* 23 */ 0, /* 24 */ 0, /* 25 */ 0, /* 26 */ 0, /* 27 */ 0, /* 28 */ TclWinCPUID, /* 29 */ TclUnixOpenTemporaryFile, /* 30 */ #endif /* UNIX */ #if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ TclWinConvertError, /* 0 */ TclWinConvertWSAError, /* 1 */ TclWinGetServByName, /* 2 */ TclWinGetSockOpt, /* 3 */ TclWinGetTclInstance, /* 4 */ TclUnixWaitForFile, /* 5 */ TclWinNToHS, /* 6 */ TclWinSetSockOpt, /* 7 */ TclpGetPid, /* 8 */ TclWinGetPlatformId, /* 9 */ TclpReaddir, /* 10 */ TclGetAndDetachPids, /* 11 */ TclpCloseFile, /* 12 */ TclpCreateCommandChannel, /* 13 */ TclpCreatePipe, /* 14 */ TclpCreateProcess, /* 15 */ TclpIsAtty, /* 16 */ TclUnixCopyFile, /* 17 */ TclpMakeFile, /* 18 */ TclpOpenFile, /* 19 */ TclWinAddProcess, /* 20 */ TclpInetNtoa, /* 21 */ TclpCreateTempFile, /* 22 */ 0, /* 23 */ TclWinNoBackslash, /* 24 */ 0, /* 25 */ TclWinSetInterfaces, /* 26 */ TclWinFlushDirtyChannels, /* 27 */ TclWinResetInterfaces, /* 28 */ TclWinCPUID, /* 29 */ TclUnixOpenTemporaryFile, /* 30 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ TclGetAndDetachPids, /* 0 */ TclpCloseFile, /* 1 */ TclpCreateCommandChannel, /* 2 */ TclpCreatePipe, /* 3 */ TclpCreateProcess, /* 4 */ 0, /* 5 */ TclpMakeFile, /* 6 */ TclpOpenFile, /* 7 */ TclUnixWaitForFile, /* 8 */ TclpCreateTempFile, /* 9 */ TclpReaddir, /* 10 */ TclpLocaltime_unix, /* 11 */ TclpGmtime_unix, /* 12 */ TclpInetNtoa, /* 13 */ TclUnixCopyFile, /* 14 */ TclMacOSXGetFileAttribute, /* 15 */ TclMacOSXSetFileAttribute, /* 16 */ TclMacOSXCopyFileAttributes, /* 17 */ TclMacOSXMatchType, /* 18 */ TclMacOSXNotifierAddRunLoopMode, /* 19 */ 0, /* 20 */ 0, /* 21 */ 0, /* 22 */ 0, /* 23 */ 0, /* 24 */ 0, /* 25 */ 0, /* 26 */ 0, /* 27 */ 0, /* 28 */ TclWinCPUID, /* 29 */ TclUnixOpenTemporaryFile, /* 30 */ #endif /* MACOSX */ }; static const TclPlatStubs tclPlatStubs = { TCL_STUB_MAGIC, 0, #if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ Tcl_WinUtfToTChar, /* 0 */ Tcl_WinTCharToUtf, /* 1 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ Tcl_MacOSXOpenBundleResources, /* 0 */ Tcl_MacOSXOpenVersionedBundleResources, /* 1 */ #endif /* MACOSX */ }; const TclTomMathStubs tclTomMathStubs = { TCL_STUB_MAGIC, 0, TclBN_epoch, /* 0 */ TclBN_revision, /* 1 */ TclBN_mp_add, /* 2 */ TclBN_mp_add_d, /* 3 */ TclBN_mp_and, /* 4 */ TclBN_mp_clamp, /* 5 */ TclBN_mp_clear, /* 6 */ TclBN_mp_clear_multi, /* 7 */ TclBN_mp_cmp, /* 8 */ TclBN_mp_cmp_d, /* 9 */ TclBN_mp_cmp_mag, /* 10 */ TclBN_mp_copy, /* 11 */ TclBN_mp_count_bits, /* 12 */ TclBN_mp_div, /* 13 */ TclBN_mp_div_d, /* 14 */ TclBN_mp_div_2, /* 15 */ TclBN_mp_div_2d, /* 16 */ TclBN_mp_div_3, /* 17 */ TclBN_mp_exch, /* 18 */ TclBN_mp_expt_d, /* 19 */ TclBN_mp_grow, /* 20 */ TclBN_mp_init, /* 21 */ TclBN_mp_init_copy, /* 22 */ TclBN_mp_init_multi, /* 23 */ TclBN_mp_init_set, /* 24 */ TclBN_mp_init_size, /* 25 */ TclBN_mp_lshd, /* 26 */ TclBN_mp_mod, /* 27 */ TclBN_mp_mod_2d, /* 28 */ TclBN_mp_mul, /* 29 */ TclBN_mp_mul_d, /* 30 */ TclBN_mp_mul_2, /* 31 */ TclBN_mp_mul_2d, /* 32 */ TclBN_mp_neg, /* 33 */ TclBN_mp_or, /* 34 */ TclBN_mp_radix_size, /* 35 */ TclBN_mp_read_radix, /* 36 */ TclBN_mp_rshd, /* 37 */ TclBN_mp_shrink, /* 38 */ TclBN_mp_set, /* 39 */ TclBN_mp_sqr, /* 40 */ TclBN_mp_sqrt, /* 41 */ TclBN_mp_sub, /* 42 */ TclBN_mp_sub_d, /* 43 */ TclBN_mp_to_unsigned_bin, /* 44 */ TclBN_mp_to_unsigned_bin_n, /* 45 */ TclBN_mp_toradix_n, /* 46 */ TclBN_mp_unsigned_bin_size, /* 47 */ TclBN_mp_xor, /* 48 */ TclBN_mp_zero, /* 49 */ TclBN_reverse, /* 50 */ TclBN_fast_s_mp_mul_digs, /* 51 */ TclBN_fast_s_mp_sqr, /* 52 */ TclBN_mp_karatsuba_mul, /* 53 */ TclBN_mp_karatsuba_sqr, /* 54 */ TclBN_mp_toom_mul, /* 55 */ TclBN_mp_toom_sqr, /* 56 */ TclBN_s_mp_add, /* 57 */ TclBN_s_mp_mul_digs, /* 58 */ TclBN_s_mp_sqr, /* 59 */ TclBN_s_mp_sub, /* 60 */ TclBN_mp_init_set_int, /* 61 */ TclBN_mp_set_int, /* 62 */ TclBN_mp_cnt_lsb, /* 63 */ TclBNInitBignumFromLong, /* 64 */ TclBNInitBignumFromWideInt, /* 65 */ TclBNInitBignumFromWideUInt, /* 66 */ }; static const TclStubHooks tclStubHooks = { &tclPlatStubs, &tclIntStubs, &tclIntPlatStubs }; const TclStubs tclStubs = { TCL_STUB_MAGIC, &tclStubHooks, Tcl_PkgProvideEx, /* 0 */ Tcl_PkgRequireEx, /* 1 */ Tcl_Panic, /* 2 */ Tcl_Alloc, /* 3 */ Tcl_Free, /* 4 */ Tcl_Realloc, /* 5 */ Tcl_DbCkalloc, /* 6 */ Tcl_DbCkfree, /* 7 */ Tcl_DbCkrealloc, /* 8 */ #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ Tcl_CreateFileHandler, /* 9 */ #endif /* UNIX */ #if defined(_WIN32) /* WIN */ 0, /* 9 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ Tcl_CreateFileHandler, /* 9 */ #endif /* MACOSX */ #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ Tcl_DeleteFileHandler, /* 10 */ #endif /* UNIX */ #if defined(_WIN32) /* WIN */ 0, /* 10 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ Tcl_DeleteFileHandler, /* 10 */ #endif /* MACOSX */ Tcl_SetTimer, /* 11 */ Tcl_Sleep, /* 12 */ Tcl_WaitForEvent, /* 13 */ Tcl_AppendAllObjTypes, /* 14 */ Tcl_AppendStringsToObj, /* 15 */ Tcl_AppendToObj, /* 16 */ Tcl_ConcatObj, /* 17 */ Tcl_ConvertToType, /* 18 */ Tcl_DbDecrRefCount, /* 19 */ Tcl_DbIncrRefCount, /* 20 */ Tcl_DbIsShared, /* 21 */ Tcl_DbNewBooleanObj, /* 22 */ Tcl_DbNewByteArrayObj, /* 23 */ Tcl_DbNewDoubleObj, /* 24 */ Tcl_DbNewListObj, /* 25 */ Tcl_DbNewLongObj, /* 26 */ Tcl_DbNewObj, /* 27 */ Tcl_DbNewStringObj, /* 28 */ Tcl_DuplicateObj, /* 29 */ TclFreeObj, /* 30 */ Tcl_GetBoolean, /* 31 */ Tcl_GetBooleanFromObj, /* 32 */ Tcl_GetByteArrayFromObj, /* 33 */ Tcl_GetDouble, /* 34 */ Tcl_GetDoubleFromObj, /* 35 */ Tcl_GetIndexFromObj, /* 36 */ Tcl_GetInt, /* 37 */ Tcl_GetIntFromObj, /* 38 */ Tcl_GetLongFromObj, /* 39 */ Tcl_GetObjType, /* 40 */ Tcl_GetStringFromObj, /* 41 */ Tcl_InvalidateStringRep, /* 42 */ Tcl_ListObjAppendList, /* 43 */ Tcl_ListObjAppendElement, /* 44 */ Tcl_ListObjGetElements, /* 45 */ Tcl_ListObjIndex, /* 46 */ Tcl_ListObjLength, /* 47 */ Tcl_ListObjReplace, /* 48 */ Tcl_NewBooleanObj, /* 49 */ Tcl_NewByteArrayObj, /* 50 */ Tcl_NewDoubleObj, /* 51 */ Tcl_NewIntObj, /* 52 */ Tcl_NewListObj, /* 53 */ Tcl_NewLongObj, /* 54 */ Tcl_NewObj, /* 55 */ Tcl_NewStringObj, /* 56 */ Tcl_SetBooleanObj, /* 57 */ Tcl_SetByteArrayLength, /* 58 */ Tcl_SetByteArrayObj, /* 59 */ Tcl_SetDoubleObj, /* 60 */ Tcl_SetIntObj, /* 61 */ Tcl_SetListObj, /* 62 */ Tcl_SetLongObj, /* 63 */ Tcl_SetObjLength, /* 64 */ Tcl_SetStringObj, /* 65 */ Tcl_AddErrorInfo, /* 66 */ Tcl_AddObjErrorInfo, /* 67 */ Tcl_AllowExceptions, /* 68 */ Tcl_AppendElement, /* 69 */ Tcl_AppendResult, /* 70 */ Tcl_AsyncCreate, /* 71 */ Tcl_AsyncDelete, /* 72 */ Tcl_AsyncInvoke, /* 73 */ Tcl_AsyncMark, /* 74 */ Tcl_AsyncReady, /* 75 */ Tcl_BackgroundError, /* 76 */ Tcl_Backslash, /* 77 */ Tcl_BadChannelOption, /* 78 */ Tcl_CallWhenDeleted, /* 79 */ Tcl_CancelIdleCall, /* 80 */ Tcl_Close, /* 81 */ Tcl_CommandComplete, /* 82 */ Tcl_Concat, /* 83 */ Tcl_ConvertElement, /* 84 */ Tcl_ConvertCountedElement, /* 85 */ Tcl_CreateAlias, /* 86 */ Tcl_CreateAliasObj, /* 87 */ Tcl_CreateChannel, /* 88 */ Tcl_CreateChannelHandler, /* 89 */ Tcl_CreateCloseHandler, /* 90 */ Tcl_CreateCommand, /* 91 */ Tcl_CreateEventSource, /* 92 */ Tcl_CreateExitHandler, /* 93 */ Tcl_CreateInterp, /* 94 */ Tcl_CreateMathFunc, /* 95 */ Tcl_CreateObjCommand, /* 96 */ Tcl_CreateSlave, /* 97 */ Tcl_CreateTimerHandler, /* 98 */ Tcl_CreateTrace, /* 99 */ Tcl_DeleteAssocData, /* 100 */ Tcl_DeleteChannelHandler, /* 101 */ Tcl_DeleteCloseHandler, /* 102 */ Tcl_DeleteCommand, /* 103 */ Tcl_DeleteCommandFromToken, /* 104 */ Tcl_DeleteEvents, /* 105 */ Tcl_DeleteEventSource, /* 106 */ Tcl_DeleteExitHandler, /* 107 */ Tcl_DeleteHashEntry, /* 108 */ Tcl_DeleteHashTable, /* 109 */ Tcl_DeleteInterp, /* 110 */ Tcl_DetachPids, /* 111 */ Tcl_DeleteTimerHandler, /* 112 */ Tcl_DeleteTrace, /* 113 */ Tcl_DontCallWhenDeleted, /* 114 */ Tcl_DoOneEvent, /* 115 */ Tcl_DoWhenIdle, /* 116 */ Tcl_DStringAppend, /* 117 */ Tcl_DStringAppendElement, /* 118 */ Tcl_DStringEndSublist, /* 119 */ Tcl_DStringFree, /* 120 */ Tcl_DStringGetResult, /* 121 */ Tcl_DStringInit, /* 122 */ Tcl_DStringResult, /* 123 */ Tcl_DStringSetLength, /* 124 */ Tcl_DStringStartSublist, /* 125 */ Tcl_Eof, /* 126 */ Tcl_ErrnoId, /* 127 */ Tcl_ErrnoMsg, /* 128 */ Tcl_Eval, /* 129 */ Tcl_EvalFile, /* 130 */ Tcl_EvalObj, /* 131 */ Tcl_EventuallyFree, /* 132 */ Tcl_Exit, /* 133 */ Tcl_ExposeCommand, /* 134 */ Tcl_ExprBoolean, /* 135 */ Tcl_ExprBooleanObj, /* 136 */ Tcl_ExprDouble, /* 137 */ Tcl_ExprDoubleObj, /* 138 */ Tcl_ExprLong, /* 139 */ Tcl_ExprLongObj, /* 140 */ Tcl_ExprObj, /* 141 */ Tcl_ExprString, /* 142 */ Tcl_Finalize, /* 143 */ Tcl_FindExecutable, /* 144 */ Tcl_FirstHashEntry, /* 145 */ Tcl_Flush, /* 146 */ Tcl_FreeResult, /* 147 */ Tcl_GetAlias, /* 148 */ Tcl_GetAliasObj, /* 149 */ Tcl_GetAssocData, /* 150 */ Tcl_GetChannel, /* 151 */ Tcl_GetChannelBufferSize, /* 152 */ Tcl_GetChannelHandle, /* 153 */ Tcl_GetChannelInstanceData, /* 154 */ Tcl_GetChannelMode, /* 155 */ Tcl_GetChannelName, /* 156 */ Tcl_GetChannelOption, /* 157 */ Tcl_GetChannelType, /* 158 */ Tcl_GetCommandInfo, /* 159 */ Tcl_GetCommandName, /* 160 */ Tcl_GetErrno, /* 161 */ Tcl_GetHostName, /* 162 */ Tcl_GetInterpPath, /* 163 */ Tcl_GetMaster, /* 164 */ Tcl_GetNameOfExecutable, /* 165 */ Tcl_GetObjResult, /* 166 */ #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ Tcl_GetOpenFile, /* 167 */ #endif /* UNIX */ #if defined(_WIN32) /* WIN */ 0, /* 167 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ Tcl_GetOpenFile, /* 167 */ #endif /* MACOSX */ Tcl_GetPathType, /* 168 */ Tcl_Gets, /* 169 */ Tcl_GetsObj, /* 170 */ Tcl_GetServiceMode, /* 171 */ Tcl_GetSlave, /* 172 */ Tcl_GetStdChannel, /* 173 */ Tcl_GetStringResult, /* 174 */ Tcl_GetVar, /* 175 */ Tcl_GetVar2, /* 176 */ Tcl_GlobalEval, /* 177 */ Tcl_GlobalEvalObj, /* 178 */ Tcl_HideCommand, /* 179 */ Tcl_Init, /* 180 */ Tcl_InitHashTable, /* 181 */ Tcl_InputBlocked, /* 182 */ Tcl_InputBuffered, /* 183 */ Tcl_InterpDeleted, /* 184 */ Tcl_IsSafe, /* 185 */ Tcl_JoinPath, /* 186 */ Tcl_LinkVar, /* 187 */ 0, /* 188 */ Tcl_MakeFileChannel, /* 189 */ Tcl_MakeSafe, /* 190 */ Tcl_MakeTcpClientChannel, /* 191 */ Tcl_Merge, /* 192 */ Tcl_NextHashEntry, /* 193 */ Tcl_NotifyChannel, /* 194 */ Tcl_ObjGetVar2, /* 195 */ Tcl_ObjSetVar2, /* 196 */ Tcl_OpenCommandChannel, /* 197 */ Tcl_OpenFileChannel, /* 198 */ Tcl_OpenTcpClient, /* 199 */ Tcl_OpenTcpServer, /* 200 */ Tcl_Preserve, /* 201 */ Tcl_PrintDouble, /* 202 */ Tcl_PutEnv, /* 203 */ Tcl_PosixError, /* 204 */ Tcl_QueueEvent, /* 205 */ Tcl_Read, /* 206 */ Tcl_ReapDetachedProcs, /* 207 */ Tcl_RecordAndEval, /* 208 */ Tcl_RecordAndEvalObj, /* 209 */ Tcl_RegisterChannel, /* 210 */ Tcl_RegisterObjType, /* 211 */ Tcl_RegExpCompile, /* 212 */ Tcl_RegExpExec, /* 213 */ Tcl_RegExpMatch, /* 214 */ Tcl_RegExpRange, /* 215 */ Tcl_Release, /* 216 */ Tcl_ResetResult, /* 217 */ Tcl_ScanElement, /* 218 */ Tcl_ScanCountedElement, /* 219 */ Tcl_SeekOld, /* 220 */ Tcl_ServiceAll, /* 221 */ Tcl_ServiceEvent, /* 222 */ Tcl_SetAssocData, /* 223 */ Tcl_SetChannelBufferSize, /* 224 */ Tcl_SetChannelOption, /* 225 */ Tcl_SetCommandInfo, /* 226 */ Tcl_SetErrno, /* 227 */ Tcl_SetErrorCode, /* 228 */ Tcl_SetMaxBlockTime, /* 229 */ Tcl_SetPanicProc, /* 230 */ Tcl_SetRecursionLimit, /* 231 */ Tcl_SetResult, /* 232 */ Tcl_SetServiceMode, /* 233 */ Tcl_SetObjErrorCode, /* 234 */ Tcl_SetObjResult, /* 235 */ Tcl_SetStdChannel, /* 236 */ Tcl_SetVar, /* 237 */ Tcl_SetVar2, /* 238 */ Tcl_SignalId, /* 239 */ Tcl_SignalMsg, /* 240 */ Tcl_SourceRCFile, /* 241 */ Tcl_SplitList, /* 242 */ Tcl_SplitPath, /* 243 */ Tcl_StaticPackage, /* 244 */ Tcl_StringMatch, /* 245 */ Tcl_TellOld, /* 246 */ Tcl_TraceVar, /* 247 */ Tcl_TraceVar2, /* 248 */ Tcl_TranslateFileName, /* 249 */ Tcl_Ungets, /* 250 */ Tcl_UnlinkVar, /* 251 */ Tcl_UnregisterChannel, /* 252 */ Tcl_UnsetVar, /* 253 */ Tcl_UnsetVar2, /* 254 */ Tcl_UntraceVar, /* 255 */ Tcl_UntraceVar2, /* 256 */ Tcl_UpdateLinkedVar, /* 257 */ Tcl_UpVar, /* 258 */ Tcl_UpVar2, /* 259 */ Tcl_VarEval, /* 260 */ Tcl_VarTraceInfo, /* 261 */ Tcl_VarTraceInfo2, /* 262 */ Tcl_Write, /* 263 */ Tcl_WrongNumArgs, /* 264 */ Tcl_DumpActiveMemory, /* 265 */ Tcl_ValidateAllMemory, /* 266 */ Tcl_AppendResultVA, /* 267 */ Tcl_AppendStringsToObjVA, /* 268 */ Tcl_HashStats, /* 269 */ Tcl_ParseVar, /* 270 */ Tcl_PkgPresent, /* 271 */ Tcl_PkgPresentEx, /* 272 */ Tcl_PkgProvide, /* 273 */ Tcl_PkgRequire, /* 274 */ Tcl_SetErrorCodeVA, /* 275 */ Tcl_VarEvalVA, /* 276 */ Tcl_WaitPid, /* 277 */ Tcl_PanicVA, /* 278 */ Tcl_GetVersion, /* 279 */ Tcl_InitMemory, /* 280 */ Tcl_StackChannel, /* 281 */ Tcl_UnstackChannel, /* 282 */ Tcl_GetStackedChannel, /* 283 */ Tcl_SetMainLoop, /* 284 */ 0, /* 285 */ Tcl_AppendObjToObj, /* 286 */ Tcl_CreateEncoding, /* 287 */ Tcl_CreateThreadExitHandler, /* 288 */ Tcl_DeleteThreadExitHandler, /* 289 */ Tcl_DiscardResult, /* 290 */ Tcl_EvalEx, /* 291 */ Tcl_EvalObjv, /* 292 */ Tcl_EvalObjEx, /* 293 */ Tcl_ExitThread, /* 294 */ Tcl_ExternalToUtf, /* 295 */ Tcl_ExternalToUtfDString, /* 296 */ Tcl_FinalizeThread, /* 297 */ Tcl_FinalizeNotifier, /* 298 */ Tcl_FreeEncoding, /* 299 */ Tcl_GetCurrentThread, /* 300 */ Tcl_GetEncoding, /* 301 */ Tcl_GetEncodingName, /* 302 */ Tcl_GetEncodingNames, /* 303 */ Tcl_GetIndexFromObjStruct, /* 304 */ Tcl_GetThreadData, /* 305 */ Tcl_GetVar2Ex, /* 306 */ Tcl_InitNotifier, /* 307 */ Tcl_MutexLock, /* 308 */ Tcl_MutexUnlock, /* 309 */ Tcl_ConditionNotify, /* 310 */ Tcl_ConditionWait, /* 311 */ Tcl_NumUtfChars, /* 312 */ Tcl_ReadChars, /* 313 */ Tcl_RestoreResult, /* 314 */ Tcl_SaveResult, /* 315 */ Tcl_SetSystemEncoding, /* 316 */ Tcl_SetVar2Ex, /* 317 */ Tcl_ThreadAlert, /* 318 */ Tcl_ThreadQueueEvent, /* 319 */ Tcl_UniCharAtIndex, /* 320 */ Tcl_UniCharToLower, /* 321 */ Tcl_UniCharToTitle, /* 322 */ Tcl_UniCharToUpper, /* 323 */ Tcl_UniCharToUtf, /* 324 */ Tcl_UtfAtIndex, /* 325 */ Tcl_UtfCharComplete, /* 326 */ Tcl_UtfBackslash, /* 327 */ Tcl_UtfFindFirst, /* 328 */ Tcl_UtfFindLast, /* 329 */ Tcl_UtfNext, /* 330 */ Tcl_UtfPrev, /* 331 */ Tcl_UtfToExternal, /* 332 */ Tcl_UtfToExternalDString, /* 333 */ Tcl_UtfToLower, /* 334 */ Tcl_UtfToTitle, /* 335 */ Tcl_UtfToUniChar, /* 336 */ Tcl_UtfToUpper, /* 337 */ Tcl_WriteChars, /* 338 */ Tcl_WriteObj, /* 339 */ Tcl_GetString, /* 340 */ Tcl_GetDefaultEncodingDir, /* 341 */ Tcl_SetDefaultEncodingDir, /* 342 */ Tcl_AlertNotifier, /* 343 */ Tcl_ServiceModeHook, /* 344 */ Tcl_UniCharIsAlnum, /* 345 */ Tcl_UniCharIsAlpha, /* 346 */ Tcl_UniCharIsDigit, /* 347 */ Tcl_UniCharIsLower, /* 348 */ Tcl_UniCharIsSpace, /* 349 */ Tcl_UniCharIsUpper, /* 350 */ Tcl_UniCharIsWordChar, /* 351 */ Tcl_UniCharLen, /* 352 */ Tcl_UniCharNcmp, /* 353 */ Tcl_UniCharToUtfDString, /* 354 */ Tcl_UtfToUniCharDString, /* 355 */ Tcl_GetRegExpFromObj, /* 356 */ Tcl_EvalTokens, /* 357 */ Tcl_FreeParse, /* 358 */ Tcl_LogCommandInfo, /* 359 */ Tcl_ParseBraces, /* 360 */ Tcl_ParseCommand, /* 361 */ Tcl_ParseExpr, /* 362 */ Tcl_ParseQuotedString, /* 363 */ Tcl_ParseVarName, /* 364 */ Tcl_GetCwd, /* 365 */ Tcl_Chdir, /* 366 */ Tcl_Access, /* 367 */ Tcl_Stat, /* 368 */ Tcl_UtfNcmp, /* 369 */ Tcl_UtfNcasecmp, /* 370 */ Tcl_StringCaseMatch, /* 371 */ Tcl_UniCharIsControl, /* 372 */ Tcl_UniCharIsGraph, /* 373 */ Tcl_UniCharIsPrint, /* 374 */ Tcl_UniCharIsPunct, /* 375 */ Tcl_RegExpExecObj, /* 376 */ Tcl_RegExpGetInfo, /* 377 */ Tcl_NewUnicodeObj, /* 378 */ Tcl_SetUnicodeObj, /* 379 */ Tcl_GetCharLength, /* 380 */ Tcl_GetUniChar, /* 381 */ Tcl_GetUnicode, /* 382 */ Tcl_GetRange, /* 383 */ Tcl_AppendUnicodeToObj, /* 384 */ Tcl_RegExpMatchObj, /* 385 */ Tcl_SetNotifier, /* 386 */ Tcl_GetAllocMutex, /* 387 */ Tcl_GetChannelNames, /* 388 */ Tcl_GetChannelNamesEx, /* 389 */ Tcl_ProcObjCmd, /* 390 */ Tcl_ConditionFinalize, /* 391 */ Tcl_MutexFinalize, /* 392 */ Tcl_CreateThread, /* 393 */ Tcl_ReadRaw, /* 394 */ Tcl_WriteRaw, /* 395 */ Tcl_GetTopChannel, /* 396 */ Tcl_ChannelBuffered, /* 397 */ Tcl_ChannelName, /* 398 */ Tcl_ChannelVersion, /* 399 */ Tcl_ChannelBlockModeProc, /* 400 */ Tcl_ChannelCloseProc, /* 401 */ Tcl_ChannelClose2Proc, /* 402 */ Tcl_ChannelInputProc, /* 403 */ Tcl_ChannelOutputProc, /* 404 */ Tcl_ChannelSeekProc, /* 405 */ Tcl_ChannelSetOptionProc, /* 406 */ Tcl_ChannelGetOptionProc, /* 407 */ Tcl_ChannelWatchProc, /* 408 */ Tcl_ChannelGetHandleProc, /* 409 */ Tcl_ChannelFlushProc, /* 410 */ Tcl_ChannelHandlerProc, /* 411 */ Tcl_JoinThread, /* 412 */ Tcl_IsChannelShared, /* 413 */ Tcl_IsChannelRegistered, /* 414 */ Tcl_CutChannel, /* 415 */ Tcl_SpliceChannel, /* 416 */ Tcl_ClearChannelHandlers, /* 417 */ Tcl_IsChannelExisting, /* 418 */ Tcl_UniCharNcasecmp, /* 419 */ Tcl_UniCharCaseMatch, /* 420 */ Tcl_FindHashEntry, /* 421 */ Tcl_CreateHashEntry, /* 422 */ Tcl_InitCustomHashTable, /* 423 */ Tcl_InitObjHashTable, /* 424 */ Tcl_CommandTraceInfo, /* 425 */ Tcl_TraceCommand, /* 426 */ Tcl_UntraceCommand, /* 427 */ Tcl_AttemptAlloc, /* 428 */ Tcl_AttemptDbCkalloc, /* 429 */ Tcl_AttemptRealloc, /* 430 */ Tcl_AttemptDbCkrealloc, /* 431 */ Tcl_AttemptSetObjLength, /* 432 */ Tcl_GetChannelThread, /* 433 */ Tcl_GetUnicodeFromObj, /* 434 */ Tcl_GetMathFuncInfo, /* 435 */ Tcl_ListMathFuncs, /* 436 */ Tcl_SubstObj, /* 437 */ Tcl_DetachChannel, /* 438 */ Tcl_IsStandardChannel, /* 439 */ Tcl_FSCopyFile, /* 440 */ Tcl_FSCopyDirectory, /* 441 */ Tcl_FSCreateDirectory, /* 442 */ Tcl_FSDeleteFile, /* 443 */ Tcl_FSLoadFile, /* 444 */ Tcl_FSMatchInDirectory, /* 445 */ Tcl_FSLink, /* 446 */ Tcl_FSRemoveDirectory, /* 447 */ Tcl_FSRenameFile, /* 448 */ Tcl_FSLstat, /* 449 */ Tcl_FSUtime, /* 450 */ Tcl_FSFileAttrsGet, /* 451 */ Tcl_FSFileAttrsSet, /* 452 */ Tcl_FSFileAttrStrings, /* 453 */ Tcl_FSStat, /* 454 */ Tcl_FSAccess, /* 455 */ Tcl_FSOpenFileChannel, /* 456 */ Tcl_FSGetCwd, /* 457 */ Tcl_FSChdir, /* 458 */ Tcl_FSConvertToPathType, /* 459 */ Tcl_FSJoinPath, /* 460 */ Tcl_FSSplitPath, /* 461 */ Tcl_FSEqualPaths, /* 462 */ Tcl_FSGetNormalizedPath, /* 463 */ Tcl_FSJoinToPath, /* 464 */ Tcl_FSGetInternalRep, /* 465 */ Tcl_FSGetTranslatedPath, /* 466 */ Tcl_FSEvalFile, /* 467 */ Tcl_FSNewNativePath, /* 468 */ Tcl_FSGetNativePath, /* 469 */ Tcl_FSFileSystemInfo, /* 470 */ Tcl_FSPathSeparator, /* 471 */ Tcl_FSListVolumes, /* 472 */ Tcl_FSRegister, /* 473 */ Tcl_FSUnregister, /* 474 */ Tcl_FSData, /* 475 */ Tcl_FSGetTranslatedStringPath, /* 476 */ Tcl_FSGetFileSystemForPath, /* 477 */ Tcl_FSGetPathType, /* 478 */ Tcl_OutputBuffered, /* 479 */ Tcl_FSMountsChanged, /* 480 */ Tcl_EvalTokensStandard, /* 481 */ Tcl_GetTime, /* 482 */ Tcl_CreateObjTrace, /* 483 */ Tcl_GetCommandInfoFromToken, /* 484 */ Tcl_SetCommandInfoFromToken, /* 485 */ Tcl_DbNewWideIntObj, /* 486 */ Tcl_GetWideIntFromObj, /* 487 */ Tcl_NewWideIntObj, /* 488 */ Tcl_SetWideIntObj, /* 489 */ Tcl_AllocStatBuf, /* 490 */ Tcl_Seek, /* 491 */ Tcl_Tell, /* 492 */ Tcl_ChannelWideSeekProc, /* 493 */ Tcl_DictObjPut, /* 494 */ Tcl_DictObjGet, /* 495 */ Tcl_DictObjRemove, /* 496 */ Tcl_DictObjSize, /* 497 */ Tcl_DictObjFirst, /* 498 */ Tcl_DictObjNext, /* 499 */ Tcl_DictObjDone, /* 500 */ Tcl_DictObjPutKeyList, /* 501 */ Tcl_DictObjRemoveKeyList, /* 502 */ Tcl_NewDictObj, /* 503 */ Tcl_DbNewDictObj, /* 504 */ Tcl_RegisterConfig, /* 505 */ Tcl_CreateNamespace, /* 506 */ Tcl_DeleteNamespace, /* 507 */ Tcl_AppendExportList, /* 508 */ Tcl_Export, /* 509 */ Tcl_Import, /* 510 */ Tcl_ForgetImport, /* 511 */ Tcl_GetCurrentNamespace, /* 512 */ Tcl_GetGlobalNamespace, /* 513 */ Tcl_FindNamespace, /* 514 */ Tcl_FindCommand, /* 515 */ Tcl_GetCommandFromObj, /* 516 */ Tcl_GetCommandFullName, /* 517 */ Tcl_FSEvalFileEx, /* 518 */ Tcl_SetExitProc, /* 519 */ Tcl_LimitAddHandler, /* 520 */ Tcl_LimitRemoveHandler, /* 521 */ Tcl_LimitReady, /* 522 */ Tcl_LimitCheck, /* 523 */ Tcl_LimitExceeded, /* 524 */ Tcl_LimitSetCommands, /* 525 */ Tcl_LimitSetTime, /* 526 */ Tcl_LimitSetGranularity, /* 527 */ Tcl_LimitTypeEnabled, /* 528 */ Tcl_LimitTypeExceeded, /* 529 */ Tcl_LimitTypeSet, /* 530 */ Tcl_LimitTypeReset, /* 531 */ Tcl_LimitGetCommands, /* 532 */ Tcl_LimitGetTime, /* 533 */ Tcl_LimitGetGranularity, /* 534 */ Tcl_SaveInterpState, /* 535 */ Tcl_RestoreInterpState, /* 536 */ Tcl_DiscardInterpState, /* 537 */ Tcl_SetReturnOptions, /* 538 */ Tcl_GetReturnOptions, /* 539 */ Tcl_IsEnsemble, /* 540 */ Tcl_CreateEnsemble, /* 541 */ Tcl_FindEnsemble, /* 542 */ Tcl_SetEnsembleSubcommandList, /* 543 */ Tcl_SetEnsembleMappingDict, /* 544 */ Tcl_SetEnsembleUnknownHandler, /* 545 */ Tcl_SetEnsembleFlags, /* 546 */ Tcl_GetEnsembleSubcommandList, /* 547 */ Tcl_GetEnsembleMappingDict, /* 548 */ Tcl_GetEnsembleUnknownHandler, /* 549 */ Tcl_GetEnsembleFlags, /* 550 */ Tcl_GetEnsembleNamespace, /* 551 */ Tcl_SetTimeProc, /* 552 */ Tcl_QueryTimeProc, /* 553 */ Tcl_ChannelThreadActionProc, /* 554 */ Tcl_NewBignumObj, /* 555 */ Tcl_DbNewBignumObj, /* 556 */ Tcl_SetBignumObj, /* 557 */ Tcl_GetBignumFromObj, /* 558 */ Tcl_TakeBignumFromObj, /* 559 */ Tcl_TruncateChannel, /* 560 */ Tcl_ChannelTruncateProc, /* 561 */ Tcl_SetChannelErrorInterp, /* 562 */ Tcl_GetChannelErrorInterp, /* 563 */ Tcl_SetChannelError, /* 564 */ Tcl_GetChannelError, /* 565 */ Tcl_InitBignumFromDouble, /* 566 */ Tcl_GetNamespaceUnknownHandler, /* 567 */ Tcl_SetNamespaceUnknownHandler, /* 568 */ Tcl_GetEncodingFromObj, /* 569 */ Tcl_GetEncodingSearchPath, /* 570 */ Tcl_SetEncodingSearchPath, /* 571 */ Tcl_GetEncodingNameFromEnvironment, /* 572 */ Tcl_PkgRequireProc, /* 573 */ Tcl_AppendObjToErrorInfo, /* 574 */ Tcl_AppendLimitedToObj, /* 575 */ Tcl_Format, /* 576 */ Tcl_AppendFormatToObj, /* 577 */ Tcl_ObjPrintf, /* 578 */ Tcl_AppendPrintfToObj, /* 579 */ Tcl_CancelEval, /* 580 */ Tcl_Canceled, /* 581 */ Tcl_CreatePipe, /* 582 */ Tcl_NRCreateCommand, /* 583 */ Tcl_NREvalObj, /* 584 */ Tcl_NREvalObjv, /* 585 */ Tcl_NRCmdSwap, /* 586 */ Tcl_NRAddCallback, /* 587 */ Tcl_NRCallObjProc, /* 588 */ Tcl_GetFSDeviceFromStat, /* 589 */ Tcl_GetFSInodeFromStat, /* 590 */ Tcl_GetModeFromStat, /* 591 */ Tcl_GetLinkCountFromStat, /* 592 */ Tcl_GetUserIdFromStat, /* 593 */ Tcl_GetGroupIdFromStat, /* 594 */ Tcl_GetDeviceTypeFromStat, /* 595 */ Tcl_GetAccessTimeFromStat, /* 596 */ Tcl_GetModificationTimeFromStat, /* 597 */ Tcl_GetChangeTimeFromStat, /* 598 */ Tcl_GetSizeFromStat, /* 599 */ Tcl_GetBlocksFromStat, /* 600 */ Tcl_GetBlockSizeFromStat, /* 601 */ Tcl_SetEnsembleParameterList, /* 602 */ Tcl_GetEnsembleParameterList, /* 603 */ Tcl_ParseArgsObjv, /* 604 */ Tcl_GetErrorLine, /* 605 */ Tcl_SetErrorLine, /* 606 */ Tcl_TransferResult, /* 607 */ Tcl_InterpActive, /* 608 */ Tcl_BackgroundException, /* 609 */ Tcl_ZlibDeflate, /* 610 */ Tcl_ZlibInflate, /* 611 */ Tcl_ZlibCRC32, /* 612 */ Tcl_ZlibAdler32, /* 613 */ Tcl_ZlibStreamInit, /* 614 */ Tcl_ZlibStreamGetCommandName, /* 615 */ Tcl_ZlibStreamEof, /* 616 */ Tcl_ZlibStreamChecksum, /* 617 */ Tcl_ZlibStreamPut, /* 618 */ Tcl_ZlibStreamGet, /* 619 */ Tcl_ZlibStreamClose, /* 620 */ Tcl_ZlibStreamReset, /* 621 */ Tcl_SetStartupScript, /* 622 */ Tcl_GetStartupScript, /* 623 */ Tcl_CloseEx, /* 624 */ Tcl_NRExprObj, /* 625 */ Tcl_NRSubstObj, /* 626 */ Tcl_LoadFile, /* 627 */ Tcl_FindSymbol, /* 628 */ Tcl_FSUnloadFile, /* 629 */ Tcl_ZlibStreamSetCompressionDictionary, /* 630 */ }; /* !END!: Do not edit above this line. */ tcl8.6.5/generic/tclAlloc.c0000644000175000017500000004264412663660065015116 0ustar sergeisergei/* * tclAlloc.c -- * * This is a very fast storage allocator. It allocates blocks of a small * number of different sizes, and keeps free lists of each size. Blocks * that don't exactly fit are passed up to the next larger size. Blocks * over a certain size are directly allocated from the system. * * Copyright (c) 1983 Regents of the University of California. * Copyright (c) 1996-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ /* * Windows and Unix use an alternative allocator when building with threads * that has significantly reduced lock contention. */ #include "tclInt.h" #if !defined(TCL_THREADS) || !defined(USE_THREAD_ALLOC) #if USE_TCLALLOC /* * We should really make use of AC_CHECK_TYPE(caddr_t) here, but it can wait * until Tcl uses config.h properly. */ #if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__) typedef unsigned long caddr_t; #endif /* * The overhead on a block is at least 8 bytes. When free, this space contains * a pointer to the next free block, and the bottom two bits must be zero. * When in use, the first byte is set to MAGIC, and the second byte is the * size index. The remaining bytes are for alignment. If range checking is * enabled then a second word holds the size of the requested block, less 1, * rounded up to a multiple of sizeof(RMAGIC). The order of elements is * critical: ov.magic must overlay the low order bits of ov.next, and ov.magic * can not be a valid ov.next bit pattern. */ union overhead { union overhead *next; /* when free */ unsigned char padding[TCL_ALLOCALIGN]; /* align struct to TCL_ALLOCALIGN bytes */ struct { unsigned char magic0; /* magic number */ unsigned char index; /* bucket # */ unsigned char unused; /* unused */ unsigned char magic1; /* other magic number */ #ifndef NDEBUG unsigned short rmagic; /* range magic number */ unsigned long size; /* actual block size */ unsigned short unused2; /* padding to 8-byte align */ #endif } ovu; #define overMagic0 ovu.magic0 #define overMagic1 ovu.magic1 #define bucketIndex ovu.index #define rangeCheckMagic ovu.rmagic #define realBlockSize ovu.size }; #define MAGIC 0xef /* magic # on accounting info */ #define RMAGIC 0x5555 /* magic # on range info */ #ifndef NDEBUG #define RSLOP sizeof(unsigned short) #else #define RSLOP 0 #endif #define OVERHEAD (sizeof(union overhead) + RSLOP) /* * Macro to make it easier to refer to the end-of-block guard magic. */ #define BLOCK_END(overPtr) \ (*(unsigned short *)((caddr_t)((overPtr) + 1) + (overPtr)->realBlockSize)) /* * nextf[i] is the pointer to the next free block of size 2^(i+3). The * smallest allocatable block is MINBLOCK bytes. The overhead information * precedes the data area returned to the user. */ #define MINBLOCK ((sizeof(union overhead) + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1)) #define NBUCKETS (13 - (MINBLOCK >> 4)) #define MAXMALLOC (1<<(NBUCKETS+2)) static union overhead *nextf[NBUCKETS]; /* * The following structure is used to keep track of all system memory * currently owned by Tcl. When finalizing, all this memory will be returned * to the system. */ struct block { struct block *nextPtr; /* Linked list. */ struct block *prevPtr; /* Linked list for big blocks, ensures 8-byte * alignment for suballocated blocks. */ }; static struct block *blockList; /* Tracks the suballocated blocks. */ static struct block bigBlocks={ /* Big blocks aren't suballocated. */ &bigBlocks, &bigBlocks }; /* * The allocator is protected by a special mutex that must be explicitly * initialized. Futhermore, because Tcl_Alloc may be used before anything else * in Tcl, we make this module self-initializing after all with the allocInit * variable. */ #ifdef TCL_THREADS static Tcl_Mutex *allocMutexPtr; #endif static int allocInit = 0; #ifdef MSTATS /* * numMallocs[i] is the difference between the number of mallocs and frees for * a given block size. */ static unsigned int numMallocs[NBUCKETS+1]; #endif #if !defined(NDEBUG) #define ASSERT(p) if (!(p)) Tcl_Panic(# p) #define RANGE_ASSERT(p) if (!(p)) Tcl_Panic(# p) #else #define ASSERT(p) #define RANGE_ASSERT(p) #endif /* * Prototypes for functions used only in this file. */ static void MoreCore(int bucket); /* *------------------------------------------------------------------------- * * TclInitAlloc -- * * Initialize the memory system. * * Results: * None. * * Side effects: * Initialize the mutex used to serialize allocations. * *------------------------------------------------------------------------- */ void TclInitAlloc(void) { if (!allocInit) { allocInit = 1; #ifdef TCL_THREADS allocMutexPtr = Tcl_GetAllocMutex(); #endif } } /* *------------------------------------------------------------------------- * * TclFinalizeAllocSubsystem -- * * Release all resources being used by this subsystem, including * aggressively freeing all memory allocated by TclpAlloc() that has not * yet been released with TclpFree(). * * After this function is called, all memory allocated with TclpAlloc() * should be considered unusable. * * Results: * None. * * Side effects: * This subsystem is self-initializing, since memory can be allocated * before Tcl is formally initialized. After this call, this subsystem * has been reset to its initial state and is usable again. * *------------------------------------------------------------------------- */ void TclFinalizeAllocSubsystem(void) { unsigned int i; struct block *blockPtr, *nextPtr; Tcl_MutexLock(allocMutexPtr); for (blockPtr = blockList; blockPtr != NULL; blockPtr = nextPtr) { nextPtr = blockPtr->nextPtr; TclpSysFree(blockPtr); } blockList = NULL; for (blockPtr = bigBlocks.nextPtr; blockPtr != &bigBlocks; ) { nextPtr = blockPtr->nextPtr; TclpSysFree(blockPtr); blockPtr = nextPtr; } bigBlocks.nextPtr = &bigBlocks; bigBlocks.prevPtr = &bigBlocks; for (i=0 ; i= MAXMALLOC - OVERHEAD) { if (numBytes <= UINT_MAX - OVERHEAD -sizeof(struct block)) { bigBlockPtr = (struct block *) TclpSysAlloc((unsigned) (sizeof(struct block) + OVERHEAD + numBytes), 0); } if (bigBlockPtr == NULL) { Tcl_MutexUnlock(allocMutexPtr); return NULL; } bigBlockPtr->nextPtr = bigBlocks.nextPtr; bigBlocks.nextPtr = bigBlockPtr; bigBlockPtr->prevPtr = &bigBlocks; bigBlockPtr->nextPtr->prevPtr = bigBlockPtr; overPtr = (union overhead *) (bigBlockPtr + 1); overPtr->overMagic0 = overPtr->overMagic1 = MAGIC; overPtr->bucketIndex = 0xff; #ifdef MSTATS numMallocs[NBUCKETS]++; #endif #ifndef NDEBUG /* * Record allocated size of block and bound space with magic numbers. */ overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1); overPtr->rangeCheckMagic = RMAGIC; BLOCK_END(overPtr) = RMAGIC; #endif Tcl_MutexUnlock(allocMutexPtr); return (void *)(overPtr+1); } /* * Convert amount of memory requested into closest block size stored in * hash buckets which satisfies request. Account for space used per block * for accounting. */ amount = MINBLOCK; /* size of first bucket */ bucket = MINBLOCK >> 4; while (numBytes + OVERHEAD > amount) { amount <<= 1; if (amount == 0) { Tcl_MutexUnlock(allocMutexPtr); return NULL; } bucket++; } ASSERT(bucket < NBUCKETS); /* * If nothing in hash bucket right now, request more memory from the * system. */ if ((overPtr = nextf[bucket]) == NULL) { MoreCore(bucket); if ((overPtr = nextf[bucket]) == NULL) { Tcl_MutexUnlock(allocMutexPtr); return NULL; } } /* * Remove from linked list */ nextf[bucket] = overPtr->next; overPtr->overMagic0 = overPtr->overMagic1 = MAGIC; overPtr->bucketIndex = (unsigned char) bucket; #ifdef MSTATS numMallocs[bucket]++; #endif #ifndef NDEBUG /* * Record allocated size of block and bound space with magic numbers. */ overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1); overPtr->rangeCheckMagic = RMAGIC; BLOCK_END(overPtr) = RMAGIC; #endif Tcl_MutexUnlock(allocMutexPtr); return ((char *)(overPtr + 1)); } /* *---------------------------------------------------------------------- * * MoreCore -- * * Allocate more memory to the indicated bucket. * * Assumes Mutex is already held. * * Results: * None. * * Side effects: * Attempts to get more memory from the system. * *---------------------------------------------------------------------- */ static void MoreCore( int bucket) /* What bucket to allocat to. */ { register union overhead *overPtr; register long size; /* size of desired block */ long amount; /* amount to allocate */ int numBlocks; /* how many blocks we get */ struct block *blockPtr; /* * sbrk_size <= 0 only for big, FLUFFY, requests (about 2^30 bytes on a * VAX, I think) or for a negative arg. */ size = 1 << (bucket + 3); ASSERT(size > 0); amount = MAXMALLOC; numBlocks = amount / size; ASSERT(numBlocks*size == amount); blockPtr = (struct block *) TclpSysAlloc((unsigned) (sizeof(struct block) + amount), 1); /* no more room! */ if (blockPtr == NULL) { return; } blockPtr->nextPtr = blockList; blockList = blockPtr; overPtr = (union overhead *) (blockPtr + 1); /* * Add new memory allocated to that on free list for this hash bucket. */ nextf[bucket] = overPtr; while (--numBlocks > 0) { overPtr->next = (union overhead *)((caddr_t)overPtr + size); overPtr = (union overhead *)((caddr_t)overPtr + size); } overPtr->next = NULL; } /* *---------------------------------------------------------------------- * * TclpFree -- * * Free memory. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclpFree( char *oldPtr) /* Pointer to memory to free. */ { register long size; register union overhead *overPtr; struct block *bigBlockPtr; if (oldPtr == NULL) { return; } Tcl_MutexLock(allocMutexPtr); overPtr = (union overhead *)((caddr_t)oldPtr - sizeof(union overhead)); ASSERT(overPtr->overMagic0 == MAGIC); /* make sure it was in use */ ASSERT(overPtr->overMagic1 == MAGIC); if (overPtr->overMagic0 != MAGIC || overPtr->overMagic1 != MAGIC) { Tcl_MutexUnlock(allocMutexPtr); return; } RANGE_ASSERT(overPtr->rangeCheckMagic == RMAGIC); RANGE_ASSERT(BLOCK_END(overPtr) == RMAGIC); size = overPtr->bucketIndex; if (size == 0xff) { #ifdef MSTATS numMallocs[NBUCKETS]--; #endif bigBlockPtr = (struct block *) overPtr - 1; bigBlockPtr->prevPtr->nextPtr = bigBlockPtr->nextPtr; bigBlockPtr->nextPtr->prevPtr = bigBlockPtr->prevPtr; TclpSysFree(bigBlockPtr); Tcl_MutexUnlock(allocMutexPtr); return; } ASSERT(size < NBUCKETS); overPtr->next = nextf[size]; /* also clobbers overMagic */ nextf[size] = overPtr; #ifdef MSTATS numMallocs[size]--; #endif Tcl_MutexUnlock(allocMutexPtr); } /* *---------------------------------------------------------------------- * * TclpRealloc -- * * Reallocate memory. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * TclpRealloc( char *oldPtr, /* Pointer to alloced block. */ unsigned int numBytes) /* New size of memory. */ { int i; union overhead *overPtr; struct block *bigBlockPtr; int expensive; unsigned long maxSize; if (oldPtr == NULL) { return TclpAlloc(numBytes); } Tcl_MutexLock(allocMutexPtr); overPtr = (union overhead *)((caddr_t)oldPtr - sizeof(union overhead)); ASSERT(overPtr->overMagic0 == MAGIC); /* make sure it was in use */ ASSERT(overPtr->overMagic1 == MAGIC); if (overPtr->overMagic0 != MAGIC || overPtr->overMagic1 != MAGIC) { Tcl_MutexUnlock(allocMutexPtr); return NULL; } RANGE_ASSERT(overPtr->rangeCheckMagic == RMAGIC); RANGE_ASSERT(BLOCK_END(overPtr) == RMAGIC); i = overPtr->bucketIndex; /* * If the block isn't in a bin, just realloc it. */ if (i == 0xff) { struct block *prevPtr, *nextPtr; bigBlockPtr = (struct block *) overPtr - 1; prevPtr = bigBlockPtr->prevPtr; nextPtr = bigBlockPtr->nextPtr; bigBlockPtr = (struct block *) TclpSysRealloc(bigBlockPtr, sizeof(struct block) + OVERHEAD + numBytes); if (bigBlockPtr == NULL) { Tcl_MutexUnlock(allocMutexPtr); return NULL; } if (prevPtr->nextPtr != bigBlockPtr) { /* * If the block has moved, splice the new block into the list * where the old block used to be. */ prevPtr->nextPtr = bigBlockPtr; nextPtr->prevPtr = bigBlockPtr; } overPtr = (union overhead *) (bigBlockPtr + 1); #ifdef MSTATS numMallocs[NBUCKETS]++; #endif #ifndef NDEBUG /* * Record allocated size of block and update magic number bounds. */ overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1); BLOCK_END(overPtr) = RMAGIC; #endif Tcl_MutexUnlock(allocMutexPtr); return (char *)(overPtr+1); } maxSize = 1 << (i+3); expensive = 0; if (numBytes+OVERHEAD > maxSize) { expensive = 1; } else if (i>0 && numBytes+OVERHEAD < maxSize/2) { expensive = 1; } if (expensive) { void *newPtr; Tcl_MutexUnlock(allocMutexPtr); newPtr = TclpAlloc(numBytes); if (newPtr == NULL) { return NULL; } maxSize -= OVERHEAD; if (maxSize < numBytes) { numBytes = maxSize; } memcpy(newPtr, oldPtr, (size_t) numBytes); TclpFree(oldPtr); return newPtr; } /* * Ok, we don't have to copy, it fits as-is */ #ifndef NDEBUG overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1); BLOCK_END(overPtr) = RMAGIC; #endif Tcl_MutexUnlock(allocMutexPtr); return(oldPtr); } /* *---------------------------------------------------------------------- * * mstats -- * * Prints two lines of numbers, one showing the length of the free list * for each size category, the second showing the number of mallocs - * frees for each size category. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef MSTATS void mstats( char *s) /* Where to write info. */ { register int i, j; register union overhead *overPtr; int totalFree = 0, totalUsed = 0; Tcl_MutexLock(allocMutexPtr); fprintf(stderr, "Memory allocation statistics %s\nTclpFree:\t", s); for (i = 0; i < NBUCKETS; i++) { for (j=0, overPtr=nextf[i]; overPtr; overPtr=overPtr->next, j++) { fprintf(stderr, " %d", j); } totalFree += j * (1 << (i + 3)); } fprintf(stderr, "\nused:\t"); for (i = 0; i < NBUCKETS; i++) { fprintf(stderr, " %d", numMallocs[i]); totalUsed += numMallocs[i] * (1 << (i + 3)); } fprintf(stderr, "\n\tTotal small in use: %d, total free: %d\n", totalUsed, totalFree); fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %d\n", MAXMALLOC, numMallocs[NBUCKETS]); Tcl_MutexUnlock(allocMutexPtr); } #endif #else /* !USE_TCLALLOC */ /* *---------------------------------------------------------------------- * * TclpAlloc -- * * Allocate more memory. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * TclpAlloc( unsigned int numBytes) /* Number of bytes to allocate. */ { return (char *) malloc(numBytes); } /* *---------------------------------------------------------------------- * * TclpFree -- * * Free memory. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclpFree( char *oldPtr) /* Pointer to memory to free. */ { free(oldPtr); return; } /* *---------------------------------------------------------------------- * * TclpRealloc -- * * Reallocate memory. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * TclpRealloc( char *oldPtr, /* Pointer to alloced block. */ unsigned int numBytes) /* New size of memory. */ { return (char *) realloc(oldPtr, numBytes); } #endif /* !USE_TCLALLOC */ #endif /* !TCL_THREADS */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclCompile.c0000644000175000017500000043652012664052331015444 0ustar sergeisergei/* * tclCompile.c -- * * This file contains procedures that compile Tcl commands or parts of * commands (like quoted strings or nested sub-commands) into a sequence * of instructions ("bytecodes"). * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" #include /* * Variable that controls whether compilation tracing is enabled and, if so, * what level of tracing is desired: * 0: no compilation tracing * 1: summarize compilation of top level cmds and proc bodies * 2: display all instructions of each ByteCode compiled * This variable is linked to the Tcl variable "tcl_traceCompile". */ #ifdef TCL_COMPILE_DEBUG int tclTraceCompile = 0; static int traceInitialized = 0; #endif /* * A table describing the Tcl bytecode instructions. Entries in this table * must correspond to the instruction opcode definitions in tclCompile.h. The * names "op1" and "op4" refer to an instruction's one or four byte first * operand. Similarly, "stktop" and "stknext" refer to the topmost and next to * topmost stack elements. * * Note that the load, store, and incr instructions do not distinguish local * from global variables; the bytecode interpreter at runtime uses the * existence of a procedure call frame to distinguish these. */ InstructionDesc const tclInstructionTable[] = { /* Name Bytes stackEffect #Opnds Operand types */ {"done", 1, -1, 0, {OPERAND_NONE}}, /* Finish ByteCode execution and return stktop (top stack item) */ {"push1", 2, +1, 1, {OPERAND_LIT1}}, /* Push object at ByteCode objArray[op1] */ {"push4", 5, +1, 1, {OPERAND_LIT4}}, /* Push object at ByteCode objArray[op4] */ {"pop", 1, -1, 0, {OPERAND_NONE}}, /* Pop the topmost stack object */ {"dup", 1, +1, 0, {OPERAND_NONE}}, /* Duplicate the topmost stack object and push the result */ {"strcat", 2, INT_MIN, 1, {OPERAND_UINT1}}, /* Concatenate the top op1 items and push result */ {"invokeStk1", 2, INT_MIN, 1, {OPERAND_UINT1}}, /* Invoke command named objv[0]; = */ {"invokeStk4", 5, INT_MIN, 1, {OPERAND_UINT4}}, /* Invoke command named objv[0]; = */ {"evalStk", 1, 0, 0, {OPERAND_NONE}}, /* Evaluate command in stktop using Tcl_EvalObj. */ {"exprStk", 1, 0, 0, {OPERAND_NONE}}, /* Execute expression in stktop using Tcl_ExprStringObj. */ {"loadScalar1", 2, 1, 1, {OPERAND_LVT1}}, /* Load scalar variable at index op1 <= 255 in call frame */ {"loadScalar4", 5, 1, 1, {OPERAND_LVT4}}, /* Load scalar variable at index op1 >= 256 in call frame */ {"loadScalarStk", 1, 0, 0, {OPERAND_NONE}}, /* Load scalar variable; scalar's name is stktop */ {"loadArray1", 2, 0, 1, {OPERAND_LVT1}}, /* Load array element; array at slot op1<=255, element is stktop */ {"loadArray4", 5, 0, 1, {OPERAND_LVT4}}, /* Load array element; array at slot op1 > 255, element is stktop */ {"loadArrayStk", 1, -1, 0, {OPERAND_NONE}}, /* Load array element; element is stktop, array name is stknext */ {"loadStk", 1, 0, 0, {OPERAND_NONE}}, /* Load general variable; unparsed variable name is stktop */ {"storeScalar1", 2, 0, 1, {OPERAND_LVT1}}, /* Store scalar variable at op1<=255 in frame; value is stktop */ {"storeScalar4", 5, 0, 1, {OPERAND_LVT4}}, /* Store scalar variable at op1 > 255 in frame; value is stktop */ {"storeScalarStk", 1, -1, 0, {OPERAND_NONE}}, /* Store scalar; value is stktop, scalar name is stknext */ {"storeArray1", 2, -1, 1, {OPERAND_LVT1}}, /* Store array element; array at op1<=255, value is top then elem */ {"storeArray4", 5, -1, 1, {OPERAND_LVT4}}, /* Store array element; array at op1>=256, value is top then elem */ {"storeArrayStk", 1, -2, 0, {OPERAND_NONE}}, /* Store array element; value is stktop, then elem, array names */ {"storeStk", 1, -1, 0, {OPERAND_NONE}}, /* Store general variable; value is stktop, then unparsed name */ {"incrScalar1", 2, 0, 1, {OPERAND_LVT1}}, /* Incr scalar at index op1<=255 in frame; incr amount is stktop */ {"incrScalarStk", 1, -1, 0, {OPERAND_NONE}}, /* Incr scalar; incr amount is stktop, scalar's name is stknext */ {"incrArray1", 2, -1, 1, {OPERAND_LVT1}}, /* Incr array elem; arr at slot op1<=255, amount is top then elem */ {"incrArrayStk", 1, -2, 0, {OPERAND_NONE}}, /* Incr array element; amount is top then elem then array names */ {"incrStk", 1, -1, 0, {OPERAND_NONE}}, /* Incr general variable; amount is stktop then unparsed var name */ {"incrScalar1Imm", 3, +1, 2, {OPERAND_LVT1, OPERAND_INT1}}, /* Incr scalar at slot op1 <= 255; amount is 2nd operand byte */ {"incrScalarStkImm", 2, 0, 1, {OPERAND_INT1}}, /* Incr scalar; scalar name is stktop; incr amount is op1 */ {"incrArray1Imm", 3, 0, 2, {OPERAND_LVT1, OPERAND_INT1}}, /* Incr array elem; array at slot op1 <= 255, elem is stktop, * amount is 2nd operand byte */ {"incrArrayStkImm", 2, -1, 1, {OPERAND_INT1}}, /* Incr array element; elem is top then array name, amount is op1 */ {"incrStkImm", 2, 0, 1, {OPERAND_INT1}}, /* Incr general variable; unparsed name is top, amount is op1 */ {"jump1", 2, 0, 1, {OPERAND_OFFSET1}}, /* Jump relative to (pc + op1) */ {"jump4", 5, 0, 1, {OPERAND_OFFSET4}}, /* Jump relative to (pc + op4) */ {"jumpTrue1", 2, -1, 1, {OPERAND_OFFSET1}}, /* Jump relative to (pc + op1) if stktop expr object is true */ {"jumpTrue4", 5, -1, 1, {OPERAND_OFFSET4}}, /* Jump relative to (pc + op4) if stktop expr object is true */ {"jumpFalse1", 2, -1, 1, {OPERAND_OFFSET1}}, /* Jump relative to (pc + op1) if stktop expr object is false */ {"jumpFalse4", 5, -1, 1, {OPERAND_OFFSET4}}, /* Jump relative to (pc + op4) if stktop expr object is false */ {"lor", 1, -1, 0, {OPERAND_NONE}}, /* Logical or: push (stknext || stktop) */ {"land", 1, -1, 0, {OPERAND_NONE}}, /* Logical and: push (stknext && stktop) */ {"bitor", 1, -1, 0, {OPERAND_NONE}}, /* Bitwise or: push (stknext | stktop) */ {"bitxor", 1, -1, 0, {OPERAND_NONE}}, /* Bitwise xor push (stknext ^ stktop) */ {"bitand", 1, -1, 0, {OPERAND_NONE}}, /* Bitwise and: push (stknext & stktop) */ {"eq", 1, -1, 0, {OPERAND_NONE}}, /* Equal: push (stknext == stktop) */ {"neq", 1, -1, 0, {OPERAND_NONE}}, /* Not equal: push (stknext != stktop) */ {"lt", 1, -1, 0, {OPERAND_NONE}}, /* Less: push (stknext < stktop) */ {"gt", 1, -1, 0, {OPERAND_NONE}}, /* Greater: push (stknext > stktop) */ {"le", 1, -1, 0, {OPERAND_NONE}}, /* Less or equal: push (stknext <= stktop) */ {"ge", 1, -1, 0, {OPERAND_NONE}}, /* Greater or equal: push (stknext >= stktop) */ {"lshift", 1, -1, 0, {OPERAND_NONE}}, /* Left shift: push (stknext << stktop) */ {"rshift", 1, -1, 0, {OPERAND_NONE}}, /* Right shift: push (stknext >> stktop) */ {"add", 1, -1, 0, {OPERAND_NONE}}, /* Add: push (stknext + stktop) */ {"sub", 1, -1, 0, {OPERAND_NONE}}, /* Sub: push (stkext - stktop) */ {"mult", 1, -1, 0, {OPERAND_NONE}}, /* Multiply: push (stknext * stktop) */ {"div", 1, -1, 0, {OPERAND_NONE}}, /* Divide: push (stknext / stktop) */ {"mod", 1, -1, 0, {OPERAND_NONE}}, /* Mod: push (stknext % stktop) */ {"uplus", 1, 0, 0, {OPERAND_NONE}}, /* Unary plus: push +stktop */ {"uminus", 1, 0, 0, {OPERAND_NONE}}, /* Unary minus: push -stktop */ {"bitnot", 1, 0, 0, {OPERAND_NONE}}, /* Bitwise not: push ~stktop */ {"not", 1, 0, 0, {OPERAND_NONE}}, /* Logical not: push !stktop */ {"callBuiltinFunc1", 2, 1, 1, {OPERAND_UINT1}}, /* Call builtin math function with index op1; any args are on stk */ {"callFunc1", 2, INT_MIN, 1, {OPERAND_UINT1}}, /* Call non-builtin func objv[0]; = */ {"tryCvtToNumeric", 1, 0, 0, {OPERAND_NONE}}, /* Try converting stktop to first int then double if possible. */ {"break", 1, 0, 0, {OPERAND_NONE}}, /* Abort closest enclosing loop; if none, return TCL_BREAK code. */ {"continue", 1, 0, 0, {OPERAND_NONE}}, /* Skip to next iteration of closest enclosing loop; if none, return * TCL_CONTINUE code. */ {"foreach_start4", 5, 0, 1, {OPERAND_AUX4}}, /* Initialize execution of a foreach loop. Operand is aux data index * of the ForeachInfo structure for the foreach command. */ {"foreach_step4", 5, +1, 1, {OPERAND_AUX4}}, /* "Step" or begin next iteration of foreach loop. Push 0 if to * terminate loop, else push 1. */ {"beginCatch4", 5, 0, 1, {OPERAND_UINT4}}, /* Record start of catch with the operand's exception index. Push the * current stack depth onto a special catch stack. */ {"endCatch", 1, 0, 0, {OPERAND_NONE}}, /* End of last catch. Pop the bytecode interpreter's catch stack. */ {"pushResult", 1, +1, 0, {OPERAND_NONE}}, /* Push the interpreter's object result onto the stack. */ {"pushReturnCode", 1, +1, 0, {OPERAND_NONE}}, /* Push interpreter's return code (e.g. TCL_OK or TCL_ERROR) as a new * object onto the stack. */ {"streq", 1, -1, 0, {OPERAND_NONE}}, /* Str Equal: push (stknext eq stktop) */ {"strneq", 1, -1, 0, {OPERAND_NONE}}, /* Str !Equal: push (stknext neq stktop) */ {"strcmp", 1, -1, 0, {OPERAND_NONE}}, /* Str Compare: push (stknext cmp stktop) */ {"strlen", 1, 0, 0, {OPERAND_NONE}}, /* Str Length: push (strlen stktop) */ {"strindex", 1, -1, 0, {OPERAND_NONE}}, /* Str Index: push (strindex stknext stktop) */ {"strmatch", 2, -1, 1, {OPERAND_INT1}}, /* Str Match: push (strmatch stknext stktop) opnd == nocase */ {"list", 5, INT_MIN, 1, {OPERAND_UINT4}}, /* List: push (stk1 stk2 ... stktop) */ {"listIndex", 1, -1, 0, {OPERAND_NONE}}, /* List Index: push (listindex stknext stktop) */ {"listLength", 1, 0, 0, {OPERAND_NONE}}, /* List Len: push (listlength stktop) */ {"appendScalar1", 2, 0, 1, {OPERAND_LVT1}}, /* Append scalar variable at op1<=255 in frame; value is stktop */ {"appendScalar4", 5, 0, 1, {OPERAND_LVT4}}, /* Append scalar variable at op1 > 255 in frame; value is stktop */ {"appendArray1", 2, -1, 1, {OPERAND_LVT1}}, /* Append array element; array at op1<=255, value is top then elem */ {"appendArray4", 5, -1, 1, {OPERAND_LVT4}}, /* Append array element; array at op1>=256, value is top then elem */ {"appendArrayStk", 1, -2, 0, {OPERAND_NONE}}, /* Append array element; value is stktop, then elem, array names */ {"appendStk", 1, -1, 0, {OPERAND_NONE}}, /* Append general variable; value is stktop, then unparsed name */ {"lappendScalar1", 2, 0, 1, {OPERAND_LVT1}}, /* Lappend scalar variable at op1<=255 in frame; value is stktop */ {"lappendScalar4", 5, 0, 1, {OPERAND_LVT4}}, /* Lappend scalar variable at op1 > 255 in frame; value is stktop */ {"lappendArray1", 2, -1, 1, {OPERAND_LVT1}}, /* Lappend array element; array at op1<=255, value is top then elem */ {"lappendArray4", 5, -1, 1, {OPERAND_LVT4}}, /* Lappend array element; array at op1>=256, value is top then elem */ {"lappendArrayStk", 1, -2, 0, {OPERAND_NONE}}, /* Lappend array element; value is stktop, then elem, array names */ {"lappendStk", 1, -1, 0, {OPERAND_NONE}}, /* Lappend general variable; value is stktop, then unparsed name */ {"lindexMulti", 5, INT_MIN, 1, {OPERAND_UINT4}}, /* Lindex with generalized args, operand is number of stacked objs * used: (operand-1) entries from stktop are the indices; then list to * process. */ {"over", 5, +1, 1, {OPERAND_UINT4}}, /* Duplicate the arg-th element from top of stack (TOS=0) */ {"lsetList", 1, -2, 0, {OPERAND_NONE}}, /* Four-arg version of 'lset'. stktop is old value; next is new * element value, next is the index list; pushes new value */ {"lsetFlat", 5, INT_MIN, 1, {OPERAND_UINT4}}, /* Three- or >=5-arg version of 'lset', operand is number of stacked * objs: stktop is old value, next is new element value, next come * (operand-2) indices; pushes the new value. */ {"returnImm", 9, -1, 2, {OPERAND_INT4, OPERAND_UINT4}}, /* Compiled [return], code, level are operands; options and result * are on the stack. */ {"expon", 1, -1, 0, {OPERAND_NONE}}, /* Binary exponentiation operator: push (stknext ** stktop) */ /* * NOTE: the stack effects of expandStkTop and invokeExpanded are wrong - * but it cannot be done right at compile time, the stack effect is only * known at run time. The value for invokeExpanded is estimated better at * compile time. * See the comments further down in this file, where INST_INVOKE_EXPANDED * is emitted. */ {"expandStart", 1, 0, 0, {OPERAND_NONE}}, /* Start of command with {*} (expanded) arguments */ {"expandStkTop", 5, 0, 1, {OPERAND_UINT4}}, /* Expand the list at stacktop: push its elements on the stack */ {"invokeExpanded", 1, 0, 0, {OPERAND_NONE}}, /* Invoke the command marked by the last 'expandStart' */ {"listIndexImm", 5, 0, 1, {OPERAND_IDX4}}, /* List Index: push (lindex stktop op4) */ {"listRangeImm", 9, 0, 2, {OPERAND_IDX4, OPERAND_IDX4}}, /* List Range: push (lrange stktop op4 op4) */ {"startCommand", 9, 0, 2, {OPERAND_OFFSET4, OPERAND_UINT4}}, /* Start of bytecoded command: op is the length of the cmd's code, op2 * is number of commands here */ {"listIn", 1, -1, 0, {OPERAND_NONE}}, /* List containment: push [lsearch stktop stknext]>=0) */ {"listNotIn", 1, -1, 0, {OPERAND_NONE}}, /* List negated containment: push [lsearch stktop stknext]<0) */ {"pushReturnOpts", 1, +1, 0, {OPERAND_NONE}}, /* Push the interpreter's return option dictionary as an object on the * stack. */ {"returnStk", 1, -1, 0, {OPERAND_NONE}}, /* Compiled [return]; options and result are on the stack, code and * level are in the options. */ {"dictGet", 5, INT_MIN, 1, {OPERAND_UINT4}}, /* The top op4 words (min 1) are a key path into the dictionary just * below the keys on the stack, and all those values are replaced by * the value read out of that key-path (like [dict get]). * Stack: ... dict key1 ... keyN => ... value */ {"dictSet", 9, INT_MIN, 2, {OPERAND_UINT4, OPERAND_LVT4}}, /* Update a dictionary value such that the keys are a path pointing to * the value. op4#1 = numKeys, op4#2 = LVTindex * Stack: ... key1 ... keyN value => ... newDict */ {"dictUnset", 9, INT_MIN, 2, {OPERAND_UINT4, OPERAND_LVT4}}, /* Update a dictionary value such that the keys are not a path pointing * to any value. op4#1 = numKeys, op4#2 = LVTindex * Stack: ... key1 ... keyN => ... newDict */ {"dictIncrImm", 9, 0, 2, {OPERAND_INT4, OPERAND_LVT4}}, /* Update a dictionary value such that the value pointed to by key is * incremented by some value (or set to it if the key isn't in the * dictionary at all). op4#1 = incrAmount, op4#2 = LVTindex * Stack: ... key => ... newDict */ {"dictAppend", 5, -1, 1, {OPERAND_LVT4}}, /* Update a dictionary value such that the value pointed to by key has * some value string-concatenated onto it. op4 = LVTindex * Stack: ... key valueToAppend => ... newDict */ {"dictLappend", 5, -1, 1, {OPERAND_LVT4}}, /* Update a dictionary value such that the value pointed to by key has * some value list-appended onto it. op4 = LVTindex * Stack: ... key valueToAppend => ... newDict */ {"dictFirst", 5, +2, 1, {OPERAND_LVT4}}, /* Begin iterating over the dictionary, using the local scalar * indicated by op4 to hold the iterator state. The local scalar * should not refer to a named variable as the value is not wholly * managed correctly. * Stack: ... dict => ... value key doneBool */ {"dictNext", 5, +3, 1, {OPERAND_LVT4}}, /* Get the next iteration from the iterator in op4's local scalar. * Stack: ... => ... value key doneBool */ {"dictDone", 5, 0, 1, {OPERAND_LVT4}}, /* Terminate the iterator in op4's local scalar. Use unsetScalar * instead (with 0 for flags). */ {"dictUpdateStart", 9, 0, 2, {OPERAND_LVT4, OPERAND_AUX4}}, /* Create the variables (described in the aux data referred to by the * second immediate argument) to mirror the state of the dictionary in * the variable referred to by the first immediate argument. The list * of keys (top of the stack, not popped) must be the same length as * the list of variables. * Stack: ... keyList => ... keyList */ {"dictUpdateEnd", 9, -1, 2, {OPERAND_LVT4, OPERAND_AUX4}}, /* Reflect the state of local variables (described in the aux data * referred to by the second immediate argument) back to the state of * the dictionary in the variable referred to by the first immediate * argument. The list of keys (popped from the stack) must be the same * length as the list of variables. * Stack: ... keyList => ... */ {"jumpTable", 5, -1, 1, {OPERAND_AUX4}}, /* Jump according to the jump-table (in AuxData as indicated by the * operand) and the argument popped from the list. Always executes the * next instruction if no match against the table's entries was found. * Stack: ... value => ... * Note that the jump table contains offsets relative to the PC when * it points to this instruction; the code is relocatable. */ {"upvar", 5, -1, 1, {OPERAND_LVT4}}, /* finds level and otherName in stack, links to local variable at * index op1. Leaves the level on stack. */ {"nsupvar", 5, -1, 1, {OPERAND_LVT4}}, /* finds namespace and otherName in stack, links to local variable at * index op1. Leaves the namespace on stack. */ {"variable", 5, -1, 1, {OPERAND_LVT4}}, /* finds namespace and otherName in stack, links to local variable at * index op1. Leaves the namespace on stack. */ {"syntax", 9, -1, 2, {OPERAND_INT4, OPERAND_UINT4}}, /* Compiled bytecodes to signal syntax error. Equivalent to returnImm * except for the ERR_ALREADY_LOGGED flag in the interpreter. */ {"reverse", 5, 0, 1, {OPERAND_UINT4}}, /* Reverse the order of the arg elements at the top of stack */ {"regexp", 2, -1, 1, {OPERAND_INT1}}, /* Regexp: push (regexp stknext stktop) opnd == nocase */ {"existScalar", 5, 1, 1, {OPERAND_LVT4}}, /* Test if scalar variable at index op1 in call frame exists */ {"existArray", 5, 0, 1, {OPERAND_LVT4}}, /* Test if array element exists; array at slot op1, element is * stktop */ {"existArrayStk", 1, -1, 0, {OPERAND_NONE}}, /* Test if array element exists; element is stktop, array name is * stknext */ {"existStk", 1, 0, 0, {OPERAND_NONE}}, /* Test if general variable exists; unparsed variable name is stktop*/ {"nop", 1, 0, 0, {OPERAND_NONE}}, /* Do nothing */ {"returnCodeBranch", 1, -1, 0, {OPERAND_NONE}}, /* Jump to next instruction based on the return code on top of stack * ERROR: +1; RETURN: +3; BREAK: +5; CONTINUE: +7; * Other non-OK: +9 */ {"unsetScalar", 6, 0, 2, {OPERAND_UINT1, OPERAND_LVT4}}, /* Make scalar variable at index op2 in call frame cease to exist; * op1 is 1 for errors on problems, 0 otherwise */ {"unsetArray", 6, -1, 2, {OPERAND_UINT1, OPERAND_LVT4}}, /* Make array element cease to exist; array at slot op2, element is * stktop; op1 is 1 for errors on problems, 0 otherwise */ {"unsetArrayStk", 2, -2, 1, {OPERAND_UINT1}}, /* Make array element cease to exist; element is stktop, array name is * stknext; op1 is 1 for errors on problems, 0 otherwise */ {"unsetStk", 2, -1, 1, {OPERAND_UINT1}}, /* Make general variable cease to exist; unparsed variable name is * stktop; op1 is 1 for errors on problems, 0 otherwise */ {"dictExpand", 1, -1, 0, {OPERAND_NONE}}, /* Probe into a dict and extract it (or a subdict of it) into * variables with matched names. Produces list of keys bound as * result. Part of [dict with]. * Stack: ... dict path => ... keyList */ {"dictRecombineStk", 1, -3, 0, {OPERAND_NONE}}, /* Map variable contents back into a dictionary in a variable. Part of * [dict with]. * Stack: ... dictVarName path keyList => ... */ {"dictRecombineImm", 5, -2, 1, {OPERAND_LVT4}}, /* Map variable contents back into a dictionary in the local variable * indicated by the LVT index. Part of [dict with]. * Stack: ... path keyList => ... */ {"dictExists", 5, INT_MIN, 1, {OPERAND_UINT4}}, /* The top op4 words (min 1) are a key path into the dictionary just * below the keys on the stack, and all those values are replaced by a * boolean indicating whether it is possible to read out a value from * that key-path (like [dict exists]). * Stack: ... dict key1 ... keyN => ... boolean */ {"verifyDict", 1, -1, 0, {OPERAND_NONE}}, /* Verifies that the word on the top of the stack is a dictionary, * popping it if it is and throwing an error if it is not. * Stack: ... value => ... */ {"strmap", 1, -2, 0, {OPERAND_NONE}}, /* Simplified version of [string map] that only applies one change * string, and only case-sensitively. * Stack: ... from to string => ... changedString */ {"strfind", 1, -1, 0, {OPERAND_NONE}}, /* Find the first index of a needle string in a haystack string, * producing the index (integer) or -1 if nothing found. * Stack: ... needle haystack => ... index */ {"strrfind", 1, -1, 0, {OPERAND_NONE}}, /* Find the last index of a needle string in a haystack string, * producing the index (integer) or -1 if nothing found. * Stack: ... needle haystack => ... index */ {"strrangeImm", 9, 0, 2, {OPERAND_IDX4, OPERAND_IDX4}}, /* String Range: push (string range stktop op4 op4) */ {"strrange", 1, -2, 0, {OPERAND_NONE}}, /* String Range with non-constant arguments. * Stack: ... string idxA idxB => ... substring */ {"yield", 1, 0, 0, {OPERAND_NONE}}, /* Makes the current coroutine yield the value at the top of the * stack, and places the response back on top of the stack when it * resumes. * Stack: ... valueToYield => ... resumeValue */ {"coroName", 1, +1, 0, {OPERAND_NONE}}, /* Push the name of the interpreter's current coroutine as an object * on the stack. */ {"tailcall", 2, INT_MIN, 1, {OPERAND_UINT1}}, /* Do a tailcall with the opnd items on the stack as the thing to * tailcall to; opnd must be greater than 0 for the semantics to work * right. */ {"currentNamespace", 1, +1, 0, {OPERAND_NONE}}, /* Push the name of the interpreter's current namespace as an object * on the stack. */ {"infoLevelNumber", 1, +1, 0, {OPERAND_NONE}}, /* Push the stack depth (i.e., [info level]) of the interpreter as an * object on the stack. */ {"infoLevelArgs", 1, 0, 0, {OPERAND_NONE}}, /* Push the argument words to a stack depth (i.e., [info level ]) * of the interpreter as an object on the stack. * Stack: ... depth => ... argList */ {"resolveCmd", 1, 0, 0, {OPERAND_NONE}}, /* Resolves the command named on the top of the stack to its fully * qualified version, or produces the empty string if no such command * exists. Never generates errors. * Stack: ... cmdName => ... fullCmdName */ {"tclooSelf", 1, +1, 0, {OPERAND_NONE}}, /* Push the identity of the current TclOO object (i.e., the name of * its current public access command) on the stack. */ {"tclooClass", 1, 0, 0, {OPERAND_NONE}}, /* Push the class of the TclOO object named at the top of the stack * onto the stack. * Stack: ... object => ... class */ {"tclooNamespace", 1, 0, 0, {OPERAND_NONE}}, /* Push the namespace of the TclOO object named at the top of the * stack onto the stack. * Stack: ... object => ... namespace */ {"tclooIsObject", 1, 0, 0, {OPERAND_NONE}}, /* Push whether the value named at the top of the stack is a TclOO * object (i.e., a boolean). Can corrupt the interpreter result * despite not throwing, so not safe for use in a post-exception * context. * Stack: ... value => ... boolean */ {"arrayExistsStk", 1, 0, 0, {OPERAND_NONE}}, /* Looks up the element on the top of the stack and tests whether it * is an array. Pushes a boolean describing whether this is the * case. Also runs the whole-array trace on the named variable, so can * throw anything. * Stack: ... varName => ... boolean */ {"arrayExistsImm", 5, +1, 1, {OPERAND_LVT4}}, /* Looks up the variable indexed by opnd and tests whether it is an * array. Pushes a boolean describing whether this is the case. Also * runs the whole-array trace on the named variable, so can throw * anything. * Stack: ... => ... boolean */ {"arrayMakeStk", 1, -1, 0, {OPERAND_NONE}}, /* Forces the element on the top of the stack to be the name of an * array. * Stack: ... varName => ... */ {"arrayMakeImm", 5, 0, 1, {OPERAND_LVT4}}, /* Forces the variable indexed by opnd to be an array. Does not touch * the stack. */ {"invokeReplace", 6, INT_MIN, 2, {OPERAND_UINT4,OPERAND_UINT1}}, /* Invoke command named objv[0], replacing the first two words with * the word at the top of the stack; * = */ {"listConcat", 1, -1, 0, {OPERAND_NONE}}, /* Concatenates the two lists at the top of the stack into a single * list and pushes that resulting list onto the stack. * Stack: ... list1 list2 => ... [lconcat list1 list2] */ {"expandDrop", 1, 0, 0, {OPERAND_NONE}}, /* Drops an element from the auxiliary stack, popping stack elements * until the matching stack depth is reached. */ /* New foreach implementation */ {"foreach_start", 5, +2, 1, {OPERAND_AUX4}}, /* Initialize execution of a foreach loop. Operand is aux data index * of the ForeachInfo structure for the foreach command. It pushes 2 * elements which hold runtime params for foreach_step, they are later * dropped by foreach_end together with the value lists. NOTE that the * iterator-tracker and info reference must not be passed to bytecodes * that handle normal Tcl values. NOTE that this instruction jumps to * the foreach_step instruction paired with it; the stack info below * is only nominal. * Stack: ... listObjs... => ... listObjs... iterTracker info */ {"foreach_step", 1, 0, 0, {OPERAND_NONE}}, /* "Step" or begin next iteration of foreach loop. Assigns to foreach * iteration variables. May jump to straight after the foreach_start * that pushed the iterTracker and info values. MUST be followed * immediately by a foreach_end. * Stack: ... listObjs... iterTracker info => * ... listObjs... iterTracker info */ {"foreach_end", 1, 0, 0, {OPERAND_NONE}}, /* Clean up a foreach loop by dropping the info value, the tracker * value and the lists that were being iterated over. * Stack: ... listObjs... iterTracker info => ... */ {"lmap_collect", 1, -1, 0, {OPERAND_NONE}}, /* Appends the value at the top of the stack to the list located on * the stack the "other side" of the foreach-related values. * Stack: ... collector listObjs... iterTracker info value => * ... collector listObjs... iterTracker info */ {"strtrim", 1, -1, 0, {OPERAND_NONE}}, /* [string trim] core: removes the characters (designated by the value * at the top of the stack) from both ends of the string and pushes * the resulting string. * Stack: ... string charset => ... trimmedString */ {"strtrimLeft", 1, -1, 0, {OPERAND_NONE}}, /* [string trimleft] core: removes the characters (designated by the * value at the top of the stack) from the left of the string and * pushes the resulting string. * Stack: ... string charset => ... trimmedString */ {"strtrimRight", 1, -1, 0, {OPERAND_NONE}}, /* [string trimright] core: removes the characters (designated by the * value at the top of the stack) from the right of the string and * pushes the resulting string. * Stack: ... string charset => ... trimmedString */ {"concatStk", 5, INT_MIN, 1, {OPERAND_UINT4}}, /* Wrapper round Tcl_ConcatObj(), used for [concat] and [eval]. opnd * is number of values to concatenate. * Operation: push concat(stk1 stk2 ... stktop) */ {"strcaseUpper", 1, 0, 0, {OPERAND_NONE}}, /* [string toupper] core: converts whole string to upper case using * the default (extended "C" locale) rules. * Stack: ... string => ... newString */ {"strcaseLower", 1, 0, 0, {OPERAND_NONE}}, /* [string tolower] core: converts whole string to upper case using * the default (extended "C" locale) rules. * Stack: ... string => ... newString */ {"strcaseTitle", 1, 0, 0, {OPERAND_NONE}}, /* [string totitle] core: converts whole string to upper case using * the default (extended "C" locale) rules. * Stack: ... string => ... newString */ {"strreplace", 1, -3, 0, {OPERAND_NONE}}, /* [string replace] core: replaces a non-empty range of one string * with the contents of another. * Stack: ... string fromIdx toIdx replacement => ... newString */ {"originCmd", 1, 0, 0, {OPERAND_NONE}}, /* Reports which command was the origin (via namespace import chain) * of the command named on the top of the stack. * Stack: ... cmdName => ... fullOriginalCmdName */ {"tclooNext", 2, INT_MIN, 1, {OPERAND_UINT1}}, /* Call the next item on the TclOO call chain, passing opnd arguments * (min 1, max 255, *includes* "next"). The result of the invoked * method implementation will be pushed on the stack in place of the * arguments (similar to invokeStk). * Stack: ... "next" arg2 arg3 -- argN => ... result */ {"tclooNextClass", 2, INT_MIN, 1, {OPERAND_UINT1}}, /* Call the following item on the TclOO call chain defined by class * className, passing opnd arguments (min 2, max 255, *includes* * "nextto" and the class name). The result of the invoked method * implementation will be pushed on the stack in place of the * arguments (similar to invokeStk). * Stack: ... "nextto" className arg3 arg4 -- argN => ... result */ {"yieldToInvoke", 1, 0, 0, {OPERAND_NONE}}, /* Makes the current coroutine yield the value at the top of the * stack, invoking the given command/args with resolution in the given * namespace (all packed into a list), and places the list of values * that are the response back on top of the stack when it resumes. * Stack: ... [list ns cmd arg1 ... argN] => ... resumeList */ {"numericType", 1, 0, 0, {OPERAND_NONE}}, /* Pushes the numeric type code of the word at the top of the stack. * Stack: ... value => ... typeCode */ {"tryCvtToBoolean", 1, +1, 0, {OPERAND_NONE}}, /* Try converting stktop to boolean if possible. No errors. * Stack: ... value => ... value isStrictBool */ {"strclass", 2, 0, 1, {OPERAND_SCLS1}}, /* See if all the characters of the given string are a member of the * specified (by opnd) character class. Note that an empty string will * satisfy the class check (standard definition of "all"). * Stack: ... stringValue => ... boolean */ {"lappendList", 5, 0, 1, {OPERAND_LVT4}}, /* Lappend list to scalar variable at op4 in frame. * Stack: ... list => ... listVarContents */ {"lappendListArray", 5, -1, 1, {OPERAND_LVT4}}, /* Lappend list to array element; array at op4. * Stack: ... elem list => ... listVarContents */ {"lappendListArrayStk", 1, -2, 0, {OPERAND_NONE}}, /* Lappend list to array element. * Stack: ... arrayName elem list => ... listVarContents */ {"lappendListStk", 1, -1, 0, {OPERAND_NONE}}, /* Lappend list to general variable. * Stack: ... varName list => ... listVarContents */ {NULL, 0, 0, 0, {OPERAND_NONE}} }; /* * Prototypes for procedures defined later in this file: */ static ByteCode * CompileSubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); static void DupByteCodeInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static unsigned char * EncodeCmdLocMap(CompileEnv *envPtr, ByteCode *codePtr, unsigned char *startPtr); static void EnterCmdExtentData(CompileEnv *envPtr, int cmdNumber, int numSrcBytes, int numCodeBytes); static void EnterCmdStartData(CompileEnv *envPtr, int cmdNumber, int srcOffset, int codeOffset); static void FreeByteCodeInternalRep(Tcl_Obj *objPtr); static void FreeSubstCodeInternalRep(Tcl_Obj *objPtr); static int GetCmdLocEncodingSize(CompileEnv *envPtr); static int IsCompactibleCompileEnv(Tcl_Interp *interp, CompileEnv *envPtr); #ifdef TCL_COMPILE_STATS static void RecordByteCodeStats(ByteCode *codePtr); #endif /* TCL_COMPILE_STATS */ static int SetByteCodeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void StartExpanding(CompileEnv *envPtr); /* * TIP #280: Helper for building the per-word line information of all compiled * commands. */ static void EnterCmdWordData(ExtCmdLoc *eclPtr, int srcOffset, Tcl_Token *tokenPtr, const char *cmd, int len, int numWords, int line, int *clNext, int **lines, CompileEnv *envPtr); static void ReleaseCmdWordData(ExtCmdLoc *eclPtr); /* * The structure below defines the bytecode Tcl object type by means of * procedures that can be invoked by generic object code. */ const Tcl_ObjType tclByteCodeType = { "bytecode", /* name */ FreeByteCodeInternalRep, /* freeIntRepProc */ DupByteCodeInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ SetByteCodeFromAny /* setFromAnyProc */ }; /* * The structure below defines a bytecode Tcl object type to hold the * compiled bytecode for the [subst]itution of Tcl values. */ static const Tcl_ObjType substCodeType = { "substcode", /* name */ FreeSubstCodeInternalRep, /* freeIntRepProc */ DupByteCodeInternalRep, /* dupIntRepProc - shared with bytecode */ NULL, /* updateStringProc */ NULL, /* setFromAnyProc */ }; /* * Helper macros. */ #define TclIncrUInt4AtPtr(ptr, delta) \ TclStoreInt4AtPtr(TclGetUInt4AtPtr(ptr)+(delta), (ptr)); /* *---------------------------------------------------------------------- * * TclSetByteCodeFromAny -- * * Part of the bytecode Tcl object type implementation. Attempts to * generate an byte code internal form for the Tcl object "objPtr" by * compiling its string representation. This function also takes a hook * procedure that will be invoked to perform any needed post processing * on the compilation results before generating byte codes. interp is * compilation context and may not be NULL. * * Results: * The return value is a standard Tcl object result. If an error occurs * during compilation, an error message is left in the interpreter's * result. * * Side effects: * Frees the old internal representation. If no error occurs, then the * compiled code is stored as "objPtr"s bytecode representation. Also, if * debugging, initializes the "tcl_traceCompile" Tcl variable used to * trace compilations. * *---------------------------------------------------------------------- */ int TclSetByteCodeFromAny( Tcl_Interp *interp, /* The interpreter for which the code is being * compiled. Must not be NULL. */ Tcl_Obj *objPtr, /* The object to make a ByteCode object. */ CompileHookProc *hookProc, /* Procedure to invoke after compilation. */ ClientData clientData) /* Hook procedure private data. */ { Interp *iPtr = (Interp *) interp; CompileEnv compEnv; /* Compilation environment structure allocated * in frame. */ int length, result = TCL_OK; const char *stringPtr; Proc *procPtr = iPtr->compiledProcPtr; ContLineLoc *clLocPtr; #ifdef TCL_COMPILE_DEBUG if (!traceInitialized) { if (Tcl_LinkVar(interp, "tcl_traceCompile", (char *) &tclTraceCompile, TCL_LINK_INT) != TCL_OK) { Tcl_Panic("SetByteCodeFromAny: unable to create link for tcl_traceCompile variable"); } traceInitialized = 1; } #endif stringPtr = TclGetStringFromObj(objPtr, &length); /* * TIP #280: Pick up the CmdFrame in which the BC compiler was invoked and * use to initialize the tracking in the compiler. This information was * stored by TclCompEvalObj and ProcCompileProc. */ TclInitCompileEnv(interp, &compEnv, stringPtr, length, iPtr->invokeCmdFramePtr, iPtr->invokeWord); /* * Now we check if we have data about invisible continuation lines for the * script, and make it available to the compile environment, if so. * * It is not clear if the script Tcl_Obj* can be free'd while the compiler * is using it, leading to the release of the associated ContLineLoc * structure as well. To ensure that the latter doesn't happen we set a * lock on it. We release this lock in the function TclFreeCompileEnv(), * found in this file. The "lineCLPtr" hashtable is managed in the file * "tclObj.c". */ clLocPtr = TclContinuationsGet(objPtr); if (clLocPtr) { compEnv.clNext = &clLocPtr->loc[0]; } TclCompileScript(interp, stringPtr, length, &compEnv); /* * Successful compilation. Add a "done" instruction at the end. */ TclEmitOpcode(INST_DONE, &compEnv); /* * Check for optimizations! * * Test if the generated code is free of most hazards; if so, recompile * but with generation of INST_START_CMD disabled. This produces somewhat * faster code in some cases, and more compact code in more. */ if (Tcl_GetMaster(interp) == NULL && !Tcl_LimitTypeEnabled(interp, TCL_LIMIT_COMMANDS|TCL_LIMIT_TIME) && IsCompactibleCompileEnv(interp, &compEnv)) { TclFreeCompileEnv(&compEnv); iPtr->compiledProcPtr = procPtr; TclInitCompileEnv(interp, &compEnv, stringPtr, length, iPtr->invokeCmdFramePtr, iPtr->invokeWord); if (clLocPtr) { compEnv.clNext = &clLocPtr->loc[0]; } compEnv.atCmdStart = 2; /* The disabling magic. */ TclCompileScript(interp, stringPtr, length, &compEnv); assert (compEnv.atCmdStart > 1); TclEmitOpcode(INST_DONE, &compEnv); assert (compEnv.atCmdStart > 1); } /* * Apply some peephole optimizations that can cross specific/generic * instruction generator boundaries. */ if (iPtr->extra.optimizer) { (iPtr->extra.optimizer)(&compEnv); } /* * Invoke the compilation hook procedure if one exists. */ if (hookProc) { result = hookProc(interp, &compEnv, clientData); } /* * Change the object into a ByteCode object. Ownership of the literal * objects and aux data items is given to the ByteCode object. */ #ifdef TCL_COMPILE_DEBUG TclVerifyLocalLiteralTable(&compEnv); #endif /*TCL_COMPILE_DEBUG*/ if (result == TCL_OK) { TclInitByteCodeObj(objPtr, &compEnv); #ifdef TCL_COMPILE_DEBUG if (tclTraceCompile >= 2) { TclPrintByteCodeObj(interp, objPtr); fflush(stdout); } #endif /* TCL_COMPILE_DEBUG */ } TclFreeCompileEnv(&compEnv); return result; } /* *----------------------------------------------------------------------- * * SetByteCodeFromAny -- * * Part of the bytecode Tcl object type implementation. Attempts to * generate an byte code internal form for the Tcl object "objPtr" by * compiling its string representation. * * Results: * The return value is a standard Tcl object result. If an error occurs * during compilation, an error message is left in the interpreter's * result unless "interp" is NULL. * * Side effects: * Frees the old internal representation. If no error occurs, then the * compiled code is stored as "objPtr"s bytecode representation. Also, if * debugging, initializes the "tcl_traceCompile" Tcl variable used to * trace compilations. * *---------------------------------------------------------------------- */ static int SetByteCodeFromAny( Tcl_Interp *interp, /* The interpreter for which the code is being * compiled. Must not be NULL. */ Tcl_Obj *objPtr) /* The object to make a ByteCode object. */ { if (interp == NULL) { return TCL_ERROR; } return TclSetByteCodeFromAny(interp, objPtr, NULL, NULL); } /* *---------------------------------------------------------------------- * * DupByteCodeInternalRep -- * * Part of the bytecode Tcl object type implementation. However, it does * not copy the internal representation of a bytecode Tcl_Obj, but * instead leaves the new object untyped (with a NULL type pointer). * Code will be compiled for the new object only if necessary. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void DupByteCodeInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { return; } /* *---------------------------------------------------------------------- * * FreeByteCodeInternalRep -- * * Part of the bytecode Tcl object type implementation. Frees the storage * associated with a bytecode object's internal representation unless its * code is actively being executed. * * Results: * None. * * Side effects: * The bytecode object's internal rep is marked invalid and its code gets * freed unless the code is actively being executed. In that case the * cleanup is delayed until the last execution of the code completes. * *---------------------------------------------------------------------- */ static void FreeByteCodeInternalRep( register Tcl_Obj *objPtr) /* Object whose internal rep to free. */ { register ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1; objPtr->typePtr = NULL; if (codePtr->refCount-- <= 1) { TclCleanupByteCode(codePtr); } } /* *---------------------------------------------------------------------- * * TclCleanupByteCode -- * * This procedure does all the real work of freeing up a bytecode * object's ByteCode structure. It's called only when the structure's * reference count becomes zero. * * Results: * None. * * Side effects: * Frees objPtr's bytecode internal representation and sets its type NULL * Also releases its literals and frees its auxiliary data items. * *---------------------------------------------------------------------- */ void TclCleanupByteCode( register ByteCode *codePtr) /* Points to the ByteCode to free. */ { Tcl_Interp *interp = (Tcl_Interp *) *codePtr->interpHandle; Interp *iPtr = (Interp *) interp; int numLitObjects = codePtr->numLitObjects; int numAuxDataItems = codePtr->numAuxDataItems; register Tcl_Obj **objArrayPtr, *objPtr; register const AuxData *auxDataPtr; int i; #ifdef TCL_COMPILE_STATS if (interp != NULL) { ByteCodeStats *statsPtr; Tcl_Time destroyTime; int lifetimeSec, lifetimeMicroSec, log2; statsPtr = &iPtr->stats; statsPtr->numByteCodesFreed++; statsPtr->currentSrcBytes -= (double) codePtr->numSrcBytes; statsPtr->currentByteCodeBytes -= (double) codePtr->structureSize; statsPtr->currentInstBytes -= (double) codePtr->numCodeBytes; statsPtr->currentLitBytes -= (double) codePtr->numLitObjects * sizeof(Tcl_Obj *); statsPtr->currentExceptBytes -= (double) codePtr->numExceptRanges * sizeof(ExceptionRange); statsPtr->currentAuxBytes -= (double) codePtr->numAuxDataItems * sizeof(AuxData); statsPtr->currentCmdMapBytes -= (double) codePtr->numCmdLocBytes; Tcl_GetTime(&destroyTime); lifetimeSec = destroyTime.sec - codePtr->createTime.sec; if (lifetimeSec > 2000) { /* avoid overflow */ lifetimeSec = 2000; } lifetimeMicroSec = 1000000 * lifetimeSec + (destroyTime.usec - codePtr->createTime.usec); log2 = TclLog2(lifetimeMicroSec); if (log2 > 31) { log2 = 31; } statsPtr->lifetimeCount[log2]++; } #endif /* TCL_COMPILE_STATS */ /* * A single heap object holds the ByteCode structure and its code, object, * command location, and auxiliary data arrays. This means we only need to * 1) decrement the ref counts of the LiteralEntry's in its literal array, * 2) call the free procs for the auxiliary data items, 3) free the * localCache if it is unused, and finally 4) free the ByteCode * structure's heap object. * * The case for TCL_BYTECODE_PRECOMPILED (precompiled ByteCodes, like * those generated from tbcload) is special, as they doesn't make use of * the global literal table. They instead maintain private references to * their literals which must be decremented. * * In order to insure a proper and efficient cleanup of the literal array * when it contains non-shared literals [Bug 983660], we also distinguish * the case of an interpreter being deleted (signaled by interp == NULL). * Also, as the interp deletion will remove the global literal table * anyway, we avoid the extra cost of updating it for each literal being * released. */ if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) { objArrayPtr = codePtr->objArrayPtr; for (i = 0; i < numLitObjects; i++) { objPtr = *objArrayPtr; if (objPtr) { Tcl_DecrRefCount(objPtr); } objArrayPtr++; } codePtr->numLitObjects = 0; } else { objArrayPtr = codePtr->objArrayPtr; while (numLitObjects--) { /* TclReleaseLiteral calls Tcl_DecrRefCount() for us */ TclReleaseLiteral(interp, *objArrayPtr++); } } auxDataPtr = codePtr->auxDataArrayPtr; for (i = 0; i < numAuxDataItems; i++) { if (auxDataPtr->type->freeProc != NULL) { auxDataPtr->type->freeProc(auxDataPtr->clientData); } auxDataPtr++; } /* * TIP #280. Release the location data associated with this byte code * structure, if any. NOTE: The interp we belong to may be gone already, * and the data with it. * * See also tclBasic.c, DeleteInterpProc */ if (iPtr) { Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr, (char *) codePtr); if (hePtr) { ReleaseCmdWordData(Tcl_GetHashValue(hePtr)); Tcl_DeleteHashEntry(hePtr); } } if (codePtr->localCachePtr && (--codePtr->localCachePtr->refCount == 0)) { TclFreeLocalCache(interp, codePtr->localCachePtr); } TclHandleRelease(codePtr->interpHandle); ckfree(codePtr); } /* * --------------------------------------------------------------------- * * IsCompactibleCompileEnv -- * * Checks to see if we may apply some basic compaction optimizations to a * piece of bytecode. Idempotent. * * --------------------------------------------------------------------- */ static int IsCompactibleCompileEnv( Tcl_Interp *interp, CompileEnv *envPtr) { unsigned char *pc; int size; /* * Special: procedures in the '::tcl' namespace (or its children) are * considered to be well-behaved and so can have compaction applied even * if it would otherwise be invalid. */ if (envPtr->procPtr != NULL && envPtr->procPtr->cmdPtr != NULL && envPtr->procPtr->cmdPtr->nsPtr != NULL) { Namespace *nsPtr = envPtr->procPtr->cmdPtr->nsPtr; if (strcmp(nsPtr->fullName, "::tcl") == 0 || strncmp(nsPtr->fullName, "::tcl::", 7) == 0) { return 1; } } /* * Go through and ensure that no operation involved can cause a desired * change of bytecode sequence during running. This comes down to ensuring * that there are no mapped variables (due to traces) or calls to external * commands (traces, [uplevel] trickery). This is actually a very * conservative check; it turns down a lot of code that is OK in practice. */ for (pc = envPtr->codeStart ; pc < envPtr->codeNext ; pc += size) { switch (*pc) { /* Invokes */ case INST_INVOKE_STK1: case INST_INVOKE_STK4: case INST_INVOKE_EXPANDED: case INST_INVOKE_REPLACE: return 0; /* Runtime evals */ case INST_EVAL_STK: case INST_EXPR_STK: case INST_YIELD: return 0; /* Upvars */ case INST_UPVAR: case INST_NSUPVAR: case INST_VARIABLE: return 0; default: size = tclInstructionTable[*pc].numBytes; assert (size > 0); break; } } return 1; } /* *---------------------------------------------------------------------- * * Tcl_SubstObj -- * * This function performs the substitutions specified on the given string * as described in the user documentation for the "subst" Tcl command. * * Results: * A Tcl_Obj* containing the substituted string, or NULL to indicate that * an error occurred. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_SubstObj( Tcl_Interp *interp, /* Interpreter in which substitution occurs */ Tcl_Obj *objPtr, /* The value to be substituted. */ int flags) /* What substitutions to do. */ { NRE_callback *rootPtr = TOP_CB(interp); if (TclNRRunCallbacks(interp, Tcl_NRSubstObj(interp, objPtr, flags), rootPtr) != TCL_OK) { return NULL; } return Tcl_GetObjResult(interp); } /* *---------------------------------------------------------------------- * * Tcl_NRSubstObj -- * * Request substitution of a Tcl value by the NR stack. * * Results: * Returns TCL_OK. * * Side effects: * Compiles objPtr into bytecode that performs the substitutions as * governed by flags and places callbacks on the NR stack to execute * the bytecode and store the result in the interp. * *---------------------------------------------------------------------- */ int Tcl_NRSubstObj( Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) { ByteCode *codePtr = CompileSubstObj(interp, objPtr, flags); /* TODO: Confirm we do not need this. */ /* Tcl_ResetResult(interp); */ return TclNRExecuteByteCode(interp, codePtr); } /* *---------------------------------------------------------------------- * * CompileSubstObj -- * * Compile a Tcl value into ByteCode implementing its substitution, as * governed by flags. * * Results: * A (ByteCode *) is returned pointing to the resulting ByteCode. * The caller must manage its refCount and arrange for a call to * TclCleanupByteCode() when the last reference disappears. * * Side effects: * The Tcl_ObjType of objPtr is changed to the "substcode" type, and the * ByteCode and governing flags value are kept in the internal rep for * faster operations the next time CompileSubstObj is called on the same * value. * *---------------------------------------------------------------------- */ static ByteCode * CompileSubstObj( Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) { Interp *iPtr = (Interp *) interp; ByteCode *codePtr = NULL; if (objPtr->typePtr == &substCodeType) { Namespace *nsPtr = iPtr->varFramePtr->nsPtr; codePtr = objPtr->internalRep.twoPtrValue.ptr1; if (flags != PTR2INT(objPtr->internalRep.twoPtrValue.ptr2) || ((Interp *) *codePtr->interpHandle != iPtr) || (codePtr->compileEpoch != iPtr->compileEpoch) || (codePtr->nsPtr != nsPtr) || (codePtr->nsEpoch != nsPtr->resolverEpoch) || (codePtr->localCachePtr != iPtr->varFramePtr->localCachePtr)) { FreeSubstCodeInternalRep(objPtr); } } if (objPtr->typePtr != &substCodeType) { CompileEnv compEnv; int numBytes; const char *bytes = Tcl_GetStringFromObj(objPtr, &numBytes); /* TODO: Check for more TIP 280 */ TclInitCompileEnv(interp, &compEnv, bytes, numBytes, NULL, 0); TclSubstCompile(interp, bytes, numBytes, flags, 1, &compEnv); TclEmitOpcode(INST_DONE, &compEnv); TclInitByteCodeObj(objPtr, &compEnv); objPtr->typePtr = &substCodeType; TclFreeCompileEnv(&compEnv); codePtr = objPtr->internalRep.twoPtrValue.ptr1; objPtr->internalRep.twoPtrValue.ptr1 = codePtr; objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(flags); if (iPtr->varFramePtr->localCachePtr) { codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr; codePtr->localCachePtr->refCount++; } #ifdef TCL_COMPILE_DEBUG if (tclTraceCompile >= 2) { TclPrintByteCodeObj(interp, objPtr); fflush(stdout); } #endif /* TCL_COMPILE_DEBUG */ } return codePtr; } /* *---------------------------------------------------------------------- * * FreeSubstCodeInternalRep -- * * Part of the substcode Tcl object type implementation. Frees the * storage associated with a substcode object's internal representation * unless its code is actively being executed. * * Results: * None. * * Side effects: * The substcode object's internal rep is marked invalid and its code * gets freed unless the code is actively being executed. In that case * the cleanup is delayed until the last execution of the code completes. * *---------------------------------------------------------------------- */ static void FreeSubstCodeInternalRep( register Tcl_Obj *objPtr) /* Object whose internal rep to free. */ { register ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1; objPtr->typePtr = NULL; if (codePtr->refCount-- <= 1) { TclCleanupByteCode(codePtr); } } static void ReleaseCmdWordData( ExtCmdLoc *eclPtr) { int i; if (eclPtr->type == TCL_LOCATION_SOURCE) { Tcl_DecrRefCount(eclPtr->path); } for (i=0 ; inuloc ; i++) { ckfree((char *) eclPtr->loc[i].line); } if (eclPtr->loc != NULL) { ckfree((char *) eclPtr->loc); } ckfree((char *) eclPtr); } /* *---------------------------------------------------------------------- * * TclInitCompileEnv -- * * Initializes a CompileEnv compilation environment structure for the * compilation of a string in an interpreter. * * Results: * None. * * Side effects: * The CompileEnv structure is initialized. * *---------------------------------------------------------------------- */ void TclInitCompileEnv( Tcl_Interp *interp, /* The interpreter for which a CompileEnv * structure is initialized. */ register CompileEnv *envPtr,/* Points to the CompileEnv structure to * initialize. */ const char *stringPtr, /* The source string to be compiled. */ int numBytes, /* Number of bytes in source string. */ const CmdFrame *invoker, /* Location context invoking the bcc */ int word) /* Index of the word in that context getting * compiled */ { Interp *iPtr = (Interp *) interp; assert(tclInstructionTable[LAST_INST_OPCODE+1].name == NULL); envPtr->iPtr = iPtr; envPtr->source = stringPtr; envPtr->numSrcBytes = numBytes; envPtr->procPtr = iPtr->compiledProcPtr; iPtr->compiledProcPtr = NULL; envPtr->numCommands = 0; envPtr->exceptDepth = 0; envPtr->maxExceptDepth = 0; envPtr->maxStackDepth = 0; envPtr->currStackDepth = 0; TclInitLiteralTable(&envPtr->localLitTable); envPtr->codeStart = envPtr->staticCodeSpace; envPtr->codeNext = envPtr->codeStart; envPtr->codeEnd = envPtr->codeStart + COMPILEENV_INIT_CODE_BYTES; envPtr->mallocedCodeArray = 0; envPtr->literalArrayPtr = envPtr->staticLiteralSpace; envPtr->literalArrayNext = 0; envPtr->literalArrayEnd = COMPILEENV_INIT_NUM_OBJECTS; envPtr->mallocedLiteralArray = 0; envPtr->exceptArrayPtr = envPtr->staticExceptArraySpace; envPtr->exceptAuxArrayPtr = envPtr->staticExAuxArraySpace; envPtr->exceptArrayNext = 0; envPtr->exceptArrayEnd = COMPILEENV_INIT_EXCEPT_RANGES; envPtr->mallocedExceptArray = 0; envPtr->cmdMapPtr = envPtr->staticCmdMapSpace; envPtr->cmdMapEnd = COMPILEENV_INIT_CMD_MAP_SIZE; envPtr->mallocedCmdMap = 0; envPtr->atCmdStart = 1; envPtr->expandCount = 0; /* * TIP #280: Set up the extended command location information, based on * the context invoking the byte code compiler. This structure is used to * keep the per-word line information for all compiled commands. * * See also tclBasic.c, TclEvalObjEx, for the equivalent code in the * non-compiling evaluator */ envPtr->extCmdMapPtr = ckalloc(sizeof(ExtCmdLoc)); envPtr->extCmdMapPtr->loc = NULL; envPtr->extCmdMapPtr->nloc = 0; envPtr->extCmdMapPtr->nuloc = 0; envPtr->extCmdMapPtr->path = NULL; if (invoker == NULL) { /* * Initialize the compiler for relative counting in case of a * dynamic context. */ envPtr->line = 1; if (iPtr->evalFlags & TCL_EVAL_FILE) { iPtr->evalFlags &= ~TCL_EVAL_FILE; envPtr->extCmdMapPtr->type = TCL_LOCATION_SOURCE; if (iPtr->scriptFile) { /* * Normalization here, to have the correct pwd. Should have * negligible impact on performance, as the norm should have * been done already by the 'source' invoking us, and it * caches the result. */ Tcl_Obj *norm = Tcl_FSGetNormalizedPath(interp, iPtr->scriptFile); if (norm == NULL) { /* * Error message in the interp result. No place to put it. * And no place to serve the error itself to either. Fake * a path, empty string. */ TclNewLiteralStringObj(envPtr->extCmdMapPtr->path, ""); } else { envPtr->extCmdMapPtr->path = norm; } } else { TclNewLiteralStringObj(envPtr->extCmdMapPtr->path, ""); } Tcl_IncrRefCount(envPtr->extCmdMapPtr->path); } else { envPtr->extCmdMapPtr->type = (envPtr->procPtr ? TCL_LOCATION_PROC : TCL_LOCATION_BC); } } else { /* * Initialize the compiler using the context, making counting absolute * to that context. Note that the context can be byte code execution. * In that case we have to fill out the missing pieces (line, path, * ...) which may make change the type as well. */ CmdFrame *ctxPtr = TclStackAlloc(interp, sizeof(CmdFrame)); int pc = 0; *ctxPtr = *invoker; if (invoker->type == TCL_LOCATION_BC) { /* * Note: Type BC => ctx.data.eval.path is not used. * ctx.data.tebc.codePtr is used instead. */ TclGetSrcInfoForPc(ctxPtr); pc = 1; } if ((ctxPtr->nline <= word) || (ctxPtr->line[word] < 0)) { /* * Word is not a literal, relative counting. */ envPtr->line = 1; envPtr->extCmdMapPtr->type = (envPtr->procPtr ? TCL_LOCATION_PROC : TCL_LOCATION_BC); if (pc && (ctxPtr->type == TCL_LOCATION_SOURCE)) { /* * The reference made by 'TclGetSrcInfoForPc' is dead. */ Tcl_DecrRefCount(ctxPtr->data.eval.path); } } else { envPtr->line = ctxPtr->line[word]; envPtr->extCmdMapPtr->type = ctxPtr->type; if (ctxPtr->type == TCL_LOCATION_SOURCE) { envPtr->extCmdMapPtr->path = ctxPtr->data.eval.path; if (pc) { /* * The reference 'TclGetSrcInfoForPc' made is transfered. */ ctxPtr->data.eval.path = NULL; } else { /* * We have a new reference here. */ Tcl_IncrRefCount(envPtr->extCmdMapPtr->path); } } } TclStackFree(interp, ctxPtr); } envPtr->extCmdMapPtr->start = envPtr->line; /* * Initialize the data about invisible continuation lines as empty, i.e. * not used. The caller (TclSetByteCodeFromAny) will set this up, if such * data is available. */ envPtr->clNext = NULL; envPtr->auxDataArrayPtr = envPtr->staticAuxDataArraySpace; envPtr->auxDataArrayNext = 0; envPtr->auxDataArrayEnd = COMPILEENV_INIT_AUX_DATA_SIZE; envPtr->mallocedAuxDataArray = 0; } /* *---------------------------------------------------------------------- * * TclFreeCompileEnv -- * * Free the storage allocated in a CompileEnv compilation environment * structure. * * Results: * None. * * Side effects: * Allocated storage in the CompileEnv structure is freed. Note that its * local literal table is not deleted and its literal objects are not * released. In addition, storage referenced by its auxiliary data items * is not freed. This is done so that, when compilation is successful, * "ownership" of these objects and aux data items is handed over to the * corresponding ByteCode structure. * *---------------------------------------------------------------------- */ void TclFreeCompileEnv( register CompileEnv *envPtr)/* Points to the CompileEnv structure. */ { if (envPtr->localLitTable.buckets != envPtr->localLitTable.staticBuckets){ ckfree(envPtr->localLitTable.buckets); envPtr->localLitTable.buckets = envPtr->localLitTable.staticBuckets; } if (envPtr->iPtr) { /* * We never converted to Bytecode, so free the things we would * have transferred to it. */ int i; LiteralEntry *entryPtr = envPtr->literalArrayPtr; AuxData *auxDataPtr = envPtr->auxDataArrayPtr; for (i = 0; i < envPtr->literalArrayNext; i++) { TclReleaseLiteral((Tcl_Interp *)envPtr->iPtr, entryPtr->objPtr); entryPtr++; } #ifdef TCL_COMPILE_DEBUG TclVerifyGlobalLiteralTable(envPtr->iPtr); #endif /*TCL_COMPILE_DEBUG*/ for (i = 0; i < envPtr->auxDataArrayNext; i++) { if (auxDataPtr->type->freeProc != NULL) { auxDataPtr->type->freeProc(auxDataPtr->clientData); } auxDataPtr++; } } if (envPtr->mallocedCodeArray) { ckfree(envPtr->codeStart); } if (envPtr->mallocedLiteralArray) { ckfree(envPtr->literalArrayPtr); } if (envPtr->mallocedExceptArray) { ckfree(envPtr->exceptArrayPtr); ckfree(envPtr->exceptAuxArrayPtr); } if (envPtr->mallocedCmdMap) { ckfree(envPtr->cmdMapPtr); } if (envPtr->mallocedAuxDataArray) { ckfree(envPtr->auxDataArrayPtr); } if (envPtr->extCmdMapPtr) { ReleaseCmdWordData(envPtr->extCmdMapPtr); envPtr->extCmdMapPtr = NULL; } } /* *---------------------------------------------------------------------- * * TclWordKnownAtCompileTime -- * * Test whether the value of a token is completely known at compile time. * * Results: * Returns true if the tokenPtr argument points to a word value that is * completely known at compile time. Generally, values that are known at * compile time can be compiled to their values, while values that cannot * be known until substitution at runtime must be compiled to bytecode * instructions that perform that substitution. For several commands, * whether or not arguments are known at compile time determine whether * it is worthwhile to compile at all. * * Side effects: * When returning true, appends the known value of the word to the * unshared Tcl_Obj (*valuePtr), unless valuePtr is NULL. * *---------------------------------------------------------------------- */ int TclWordKnownAtCompileTime( Tcl_Token *tokenPtr, /* Points to Tcl_Token we should check */ Tcl_Obj *valuePtr) /* If not NULL, points to an unshared Tcl_Obj * to which we should append the known value * of the word. */ { int numComponents = tokenPtr->numComponents; Tcl_Obj *tempPtr = NULL; if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { if (valuePtr != NULL) { Tcl_AppendToObj(valuePtr, tokenPtr[1].start, tokenPtr[1].size); } return 1; } if (tokenPtr->type != TCL_TOKEN_WORD) { return 0; } tokenPtr++; if (valuePtr != NULL) { tempPtr = Tcl_NewObj(); Tcl_IncrRefCount(tempPtr); } while (numComponents--) { switch (tokenPtr->type) { case TCL_TOKEN_TEXT: if (tempPtr != NULL) { Tcl_AppendToObj(tempPtr, tokenPtr->start, tokenPtr->size); } break; case TCL_TOKEN_BS: if (tempPtr != NULL) { char utfBuf[TCL_UTF_MAX]; int length = TclParseBackslash(tokenPtr->start, tokenPtr->size, NULL, utfBuf); Tcl_AppendToObj(tempPtr, utfBuf, length); } break; default: if (tempPtr != NULL) { Tcl_DecrRefCount(tempPtr); } return 0; } tokenPtr++; } if (valuePtr != NULL) { Tcl_AppendObjToObj(valuePtr, tempPtr); Tcl_DecrRefCount(tempPtr); } return 1; } /* *---------------------------------------------------------------------- * * TclCompileScript -- * * Compile a Tcl script in a string. * * Results: * The return value is TCL_OK on a successful compilation and TCL_ERROR * on failure. If TCL_ERROR is returned, then the interpreter's result * contains an error message. * * Side effects: * Adds instructions to envPtr to evaluate the script at runtime. * *---------------------------------------------------------------------- */ static int ExpandRequested( Tcl_Token *tokenPtr, int numWords) { /* Determine whether any words of the command require expansion */ while (numWords--) { if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) { return 1; } tokenPtr = TokenAfter(tokenPtr); } return 0; } static void CompileCmdLiteral( Tcl_Interp *interp, Tcl_Obj *cmdObj, CompileEnv *envPtr) { int numBytes; const char *bytes = Tcl_GetStringFromObj(cmdObj, &numBytes); int cmdLitIdx = TclRegisterNewCmdLiteral(envPtr, bytes, numBytes); Command *cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdObj); if (cmdPtr) { TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLitIdx), cmdPtr); } TclEmitPush(cmdLitIdx, envPtr); } void TclCompileInvocation( Tcl_Interp *interp, Tcl_Token *tokenPtr, Tcl_Obj *cmdObj, int numWords, CompileEnv *envPtr) { int wordIdx = 0, depth = TclGetStackDepth(envPtr); DefineLineInformation; if (cmdObj) { CompileCmdLiteral(interp, cmdObj, envPtr); wordIdx = 1; tokenPtr = TokenAfter(tokenPtr); } for (; wordIdx < numWords; wordIdx++, tokenPtr = TokenAfter(tokenPtr)) { int objIdx; SetLineInformation(wordIdx); if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { CompileTokens(envPtr, tokenPtr, interp); continue; } objIdx = TclRegisterNewLiteral(envPtr, tokenPtr[1].start, tokenPtr[1].size); if (envPtr->clNext) { TclContinuationsEnterDerived(TclFetchLiteral(envPtr, objIdx), tokenPtr[1].start - envPtr->source, envPtr->clNext); } TclEmitPush(objIdx, envPtr); } if (wordIdx <= 255) { TclEmitInvoke(envPtr, INST_INVOKE_STK1, wordIdx); } else { TclEmitInvoke(envPtr, INST_INVOKE_STK4, wordIdx); } TclCheckStackDepth(depth+1, envPtr); } static void CompileExpanded( Tcl_Interp *interp, Tcl_Token *tokenPtr, Tcl_Obj *cmdObj, int numWords, CompileEnv *envPtr) { int wordIdx = 0; DefineLineInformation; int depth = TclGetStackDepth(envPtr); StartExpanding(envPtr); if (cmdObj) { CompileCmdLiteral(interp, cmdObj, envPtr); wordIdx = 1; tokenPtr = TokenAfter(tokenPtr); } for (; wordIdx < numWords; wordIdx++, tokenPtr = TokenAfter(tokenPtr)) { int objIdx; SetLineInformation(wordIdx); if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { CompileTokens(envPtr, tokenPtr, interp); if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) { TclEmitInstInt4(INST_EXPAND_STKTOP, envPtr->currStackDepth, envPtr); } continue; } objIdx = TclRegisterNewLiteral(envPtr, tokenPtr[1].start, tokenPtr[1].size); if (envPtr->clNext) { TclContinuationsEnterDerived(TclFetchLiteral(envPtr, objIdx), tokenPtr[1].start - envPtr->source, envPtr->clNext); } TclEmitPush(objIdx, envPtr); } /* * The stack depth during argument expansion can only be managed at * runtime, as the number of elements in the expanded lists is not known * at compile time. We adjust here the stack depth estimate so that it is * correct after the command with expanded arguments returns. * * The end effect of this command's invocation is that all the words of * the command are popped from the stack, and the result is pushed: the * stack top changes by (1-wordIdx). * * Note that the estimates are not correct while the command is being * prepared and run, INST_EXPAND_STKTOP is not stack-neutral in general. */ TclEmitInvoke(envPtr, INST_INVOKE_EXPANDED, wordIdx); TclCheckStackDepth(depth+1, envPtr); } static int CompileCmdCompileProc( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, CompileEnv *envPtr) { int unwind = 0, incrOffset = -1; DefineLineInformation; int depth = TclGetStackDepth(envPtr); /* * Emit of the INST_START_CMD instruction is controlled by the value of * envPtr->atCmdStart: * * atCmdStart == 2 : We are not using the INST_START_CMD instruction. * atCmdStart == 1 : INST_START_CMD was the last instruction emitted. * : We do not need to emit another. Instead we * : increment the number of cmds started at it (except * : for the special case at the start of a script.) * atCmdStart == 0 : The last instruction was something else. We need * : to emit INST_START_CMD here. */ switch (envPtr->atCmdStart) { case 0: unwind = tclInstructionTable[INST_START_CMD].numBytes; TclEmitInstInt4(INST_START_CMD, 0, envPtr); incrOffset = envPtr->codeNext - envPtr->codeStart; TclEmitInt4(0, envPtr); break; case 1: if (envPtr->codeNext > envPtr->codeStart) { incrOffset = envPtr->codeNext - 4 - envPtr->codeStart; } break; case 2: /* Nothing to do */ ; } if (TCL_OK == TclAttemptCompileProc(interp, parsePtr, 1, cmdPtr, envPtr)) { if (incrOffset >= 0) { /* * We successfully compiled a command. Increment the number of * commands that start at the currently active INST_START_CMD. */ unsigned char *incrPtr = envPtr->codeStart + incrOffset; unsigned char *startPtr = incrPtr - 5; TclIncrUInt4AtPtr(incrPtr, 1); if (unwind) { /* We started the INST_START_CMD. Record the code length. */ TclStoreInt4AtPtr(envPtr->codeNext - startPtr, startPtr + 1); } } TclCheckStackDepth(depth+1, envPtr); return TCL_OK; } envPtr->codeNext -= unwind; /* Unwind INST_START_CMD */ /* * Throw out any line information generated by the failed compile attempt. */ while (mapPtr->nuloc - 1 > eclIndex) { mapPtr->nuloc--; ckfree(mapPtr->loc[mapPtr->nuloc].line); mapPtr->loc[mapPtr->nuloc].line = NULL; } /* * Reset the index of next command. Toss out any from failed nested * partial compiles. */ envPtr->numCommands = mapPtr->nuloc; return TCL_ERROR; } static int CompileCommandTokens( Tcl_Interp *interp, Tcl_Parse *parsePtr, CompileEnv *envPtr) { Interp *iPtr = (Interp *) interp; Tcl_Token *tokenPtr = parsePtr->tokenPtr; ExtCmdLoc *eclPtr = envPtr->extCmdMapPtr; Tcl_Obj *cmdObj = Tcl_NewObj(); Command *cmdPtr = NULL; int code = TCL_ERROR; int cmdKnown, expand = -1; int *wlines, wlineat; int cmdLine = envPtr->line; int *clNext = envPtr->clNext; int cmdIdx = envPtr->numCommands; int startCodeOffset = envPtr->codeNext - envPtr->codeStart; int depth = TclGetStackDepth(envPtr); assert (parsePtr->numWords > 0); /* Pre-Compile */ envPtr->numCommands++; EnterCmdStartData(envPtr, cmdIdx, parsePtr->commandStart - envPtr->source, startCodeOffset); /* * TIP #280. Scan the words and compute the extended location information. * The map first contain full per-word line information for use by the * compiler. This is later replaced by a reduced form which signals * non-literal words, stored in 'wlines'. */ EnterCmdWordData(eclPtr, parsePtr->commandStart - envPtr->source, parsePtr->tokenPtr, parsePtr->commandStart, parsePtr->commandSize, parsePtr->numWords, cmdLine, clNext, &wlines, envPtr); wlineat = eclPtr->nuloc - 1; envPtr->line = eclPtr->loc[wlineat].line[0]; envPtr->clNext = eclPtr->loc[wlineat].next[0]; /* Do we know the command word? */ Tcl_IncrRefCount(cmdObj); tokenPtr = parsePtr->tokenPtr; cmdKnown = TclWordKnownAtCompileTime(tokenPtr, cmdObj); /* Is this a command we should (try to) compile with a compileProc ? */ if (cmdKnown && !(iPtr->flags & DONT_COMPILE_CMDS_INLINE)) { cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdObj); if (cmdPtr) { /* * Found a command. Test the ways we can be told not to attempt * to compile it. */ if ((cmdPtr->compileProc == NULL) || (cmdPtr->nsPtr->flags & NS_SUPPRESS_COMPILATION) || (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) { cmdPtr = NULL; } } if (cmdPtr && !(cmdPtr->flags & CMD_COMPILES_EXPANDED)) { expand = ExpandRequested(parsePtr->tokenPtr, parsePtr->numWords); if (expand) { /* We need to expand, but compileProc cannot. */ cmdPtr = NULL; } } } /* If cmdPtr != NULL, we will try to call cmdPtr->compileProc */ if (cmdPtr) { code = CompileCmdCompileProc(interp, parsePtr, cmdPtr, envPtr); } if (code == TCL_ERROR) { if (expand < 0) { expand = ExpandRequested(parsePtr->tokenPtr, parsePtr->numWords); } if (expand) { CompileExpanded(interp, parsePtr->tokenPtr, cmdKnown ? cmdObj : NULL, parsePtr->numWords, envPtr); } else { TclCompileInvocation(interp, parsePtr->tokenPtr, cmdKnown ? cmdObj : NULL, parsePtr->numWords, envPtr); } } Tcl_DecrRefCount(cmdObj); TclEmitOpcode(INST_POP, envPtr); EnterCmdExtentData(envPtr, cmdIdx, parsePtr->term - parsePtr->commandStart, (envPtr->codeNext-envPtr->codeStart) - startCodeOffset); /* * TIP #280: Free full form of per-word line data and insert the reduced * form now */ envPtr->line = cmdLine; envPtr->clNext = clNext; ckfree(eclPtr->loc[wlineat].line); ckfree(eclPtr->loc[wlineat].next); eclPtr->loc[wlineat].line = wlines; eclPtr->loc[wlineat].next = NULL; TclCheckStackDepth(depth, envPtr); return cmdIdx; } void TclCompileScript( Tcl_Interp *interp, /* Used for error and status reporting. Also * serves as context for finding and compiling * commands. May not be NULL. */ const char *script, /* The source script to compile. */ int numBytes, /* Number of bytes in script. If < 0, the * script consists of all bytes up to the * first null character. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { int lastCmdIdx = -1; /* Index into envPtr->cmdMapPtr of the last * command this routine compiles into bytecode. * Initial value of -1 indicates this routine * has not yet generated any bytecode. */ const char *p = script; /* Where we are in our compile. */ int depth = TclGetStackDepth(envPtr); if (envPtr->iPtr == NULL) { Tcl_Panic("TclCompileScript() called on uninitialized CompileEnv"); } /* Each iteration compiles one command from the script. */ while (numBytes > 0) { Tcl_Parse parse; const char *next; if (TCL_OK != Tcl_ParseCommand(interp, p, numBytes, 0, &parse)) { /* * Compile bytecodes to report the parse error at runtime. */ Tcl_LogCommandInfo(interp, script, parse.commandStart, parse.term + 1 - parse.commandStart); TclCompileSyntaxError(interp, envPtr); return; } #ifdef TCL_COMPILE_DEBUG /* * If tracing, print a line for each top level command compiled. * TODO: Suppress when numWords == 0 ? */ if ((tclTraceCompile >= 1) && (envPtr->procPtr == NULL)) { int commandLength = parse.term - parse.commandStart; fprintf(stdout, " Compiling: "); TclPrintSource(stdout, parse.commandStart, TclMin(commandLength, 55)); fprintf(stdout, "\n"); } #endif /* * TIP #280: Count newlines before the command start. * (See test info-30.33). */ TclAdvanceLines(&envPtr->line, p, parse.commandStart); TclAdvanceContinuations(&envPtr->line, &envPtr->clNext, parse.commandStart - envPtr->source); /* * Advance parser to the next command in the script. */ next = parse.commandStart + parse.commandSize; numBytes -= next - p; p = next; if (parse.numWords == 0) { /* * The "command" parsed has no words. In this case we can skip * the rest of the loop body. With no words, clearly * CompileCommandTokens() has nothing to do. Since the parser * aggressively sucks up leading comment and white space, * including newlines, parse.commandStart must be pointing at * either the end of script, or a command-terminating semi-colon. * In either case, the TclAdvance*() calls have nothing to do. * Finally, when no words are parsed, no tokens have been * allocated at parse.tokenPtr so there's also nothing for * Tcl_FreeParse() to do. * * The advantage of this shortcut is that CompileCommandTokens() * can be written with an assumption that parse.numWords > 0, with * the implication the CCT() always generates bytecode. */ continue; } lastCmdIdx = CompileCommandTokens(interp, &parse, envPtr); /* * TIP #280: Track lines in the just compiled command. */ TclAdvanceLines(&envPtr->line, parse.commandStart, p); TclAdvanceContinuations(&envPtr->line, &envPtr->clNext, p - envPtr->source); Tcl_FreeParse(&parse); } if (lastCmdIdx == -1) { /* * Compiling the script yielded no bytecode. The script must be all * whitespace, comments, and empty commands. Such scripts are defined * to successfully produce the empty string result, so we emit the * simple bytecode that makes that happen. */ PushStringLiteral(envPtr, ""); } else { /* * We compiled at least one command to bytecode. The routine * CompileCommandTokens() follows the bytecode of each compiled * command with an INST_POP, so that stack balance is maintained when * several commands are in sequence. (The result of each command is * thrown away before moving on to the next command). For the last * command compiled, we need to undo that INST_POP so that the result * of the last command becomes the result of the script. The code * here removes that trailing INST_POP. */ envPtr->cmdMapPtr[lastCmdIdx].numCodeBytes--; envPtr->codeNext--; envPtr->currStackDepth++; } TclCheckStackDepth(depth+1, envPtr); } /* *---------------------------------------------------------------------- * * TclCompileTokens -- * * Given an array of tokens parsed from a Tcl command (e.g., the tokens * that make up a word) this procedure emits instructions to evaluate the * tokens and concatenate their values to form a single result value on * the interpreter's runtime evaluation stack. * * Results: * The return value is a standard Tcl result. If an error occurs, an * error message is left in the interpreter's result. * * Side effects: * Instructions are added to envPtr to push and evaluate the tokens at * runtime. * *---------------------------------------------------------------------- */ void TclCompileVarSubst( Tcl_Interp *interp, Tcl_Token *tokenPtr, CompileEnv *envPtr) { const char *p, *name = tokenPtr[1].start; int nameBytes = tokenPtr[1].size; int i, localVar, localVarName = 1; /* * Determine how the variable name should be handled: if it contains any * namespace qualifiers it is not a local variable (localVarName=-1); if * it looks like an array element and the token has a single component, it * should not be created here [Bug 569438] (localVarName=0); otherwise, * the local variable can safely be created (localVarName=1). */ for (i = 0, p = name; i < nameBytes; i++, p++) { if ((*p == ':') && (i < nameBytes-1) && (*(p+1) == ':')) { localVarName = -1; break; } else if ((*p == '(') && (tokenPtr->numComponents == 1) && (*(name + nameBytes - 1) == ')')) { localVarName = 0; break; } } /* * Either push the variable's name, or find its index in the array * of local variables in a procedure frame. */ localVar = -1; if (localVarName != -1) { localVar = TclFindCompiledLocal(name, nameBytes, localVarName, envPtr); } if (localVar < 0) { PushLiteral(envPtr, name, nameBytes); } /* * Emit instructions to load the variable. */ TclAdvanceLines(&envPtr->line, tokenPtr[1].start, tokenPtr[1].start + tokenPtr[1].size); if (tokenPtr->numComponents == 1) { if (localVar < 0) { TclEmitOpcode(INST_LOAD_STK, envPtr); } else if (localVar <= 255) { TclEmitInstInt1(INST_LOAD_SCALAR1, localVar, envPtr); } else { TclEmitInstInt4(INST_LOAD_SCALAR4, localVar, envPtr); } } else { TclCompileTokens(interp, tokenPtr+2, tokenPtr->numComponents-1, envPtr); if (localVar < 0) { TclEmitOpcode(INST_LOAD_ARRAY_STK, envPtr); } else if (localVar <= 255) { TclEmitInstInt1(INST_LOAD_ARRAY1, localVar, envPtr); } else { TclEmitInstInt4(INST_LOAD_ARRAY4, localVar, envPtr); } } } void TclCompileTokens( Tcl_Interp *interp, /* Used for error and status reporting. */ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to * compile. */ int count, /* Number of tokens to consider at tokenPtr. * Must be at least 1. */ CompileEnv *envPtr) /* Holds the resulting instructions. */ { Tcl_DString textBuffer; /* Holds concatenated chars from adjacent * TCL_TOKEN_TEXT, TCL_TOKEN_BS tokens. */ char buffer[TCL_UTF_MAX]; int i, numObjsToConcat, length, adjust; unsigned char *entryCodeNext = envPtr->codeNext; #define NUM_STATIC_POS 20 int isLiteral, maxNumCL, numCL; int *clPosition = NULL; int depth = TclGetStackDepth(envPtr); /* * For the handling of continuation lines in literals we first check if * this is actually a literal. For if not we can forego the additional * processing. Otherwise we pre-allocate a small table to store the * locations of all continuation lines we find in this literal, if any. * The table is extended if needed. * * Note: Different to the equivalent code in function 'TclSubstTokens()' * (see file "tclParse.c") we do not seem to need the 'adjust' variable. * We also do not seem to need code which merges continuation line * information of multiple words which concat'd at runtime. Either that or * I have not managed to find a test case for these two possibilities yet. * It might be a difference between compile- versus run-time processing. */ numCL = 0; maxNumCL = 0; isLiteral = 1; for (i=0 ; i < count; i++) { if ((tokenPtr[i].type != TCL_TOKEN_TEXT) && (tokenPtr[i].type != TCL_TOKEN_BS)) { isLiteral = 0; break; } } if (isLiteral) { maxNumCL = NUM_STATIC_POS; clPosition = ckalloc(maxNumCL * sizeof(int)); } adjust = 0; Tcl_DStringInit(&textBuffer); numObjsToConcat = 0; for ( ; count > 0; count--, tokenPtr++) { switch (tokenPtr->type) { case TCL_TOKEN_TEXT: TclDStringAppendToken(&textBuffer, tokenPtr); TclAdvanceLines(&envPtr->line, tokenPtr->start, tokenPtr->start + tokenPtr->size); break; case TCL_TOKEN_BS: length = TclParseBackslash(tokenPtr->start, tokenPtr->size, NULL, buffer); Tcl_DStringAppend(&textBuffer, buffer, length); /* * If the backslash sequence we found is in a literal, and * represented a continuation line, we compute and store its * location (as char offset to the beginning of the _result_ * script). We may have to extend the table of locations. * * Note that the continuation line information is relevant even if * the word we are processing is not a literal, as it can affect * nested commands. See the branch for TCL_TOKEN_COMMAND below, * where the adjustment we are tracking here is taken into * account. The good thing is that we do not need a table of * everything, just the number of lines we have to add as * correction. */ if ((length == 1) && (buffer[0] == ' ') && (tokenPtr->start[1] == '\n')) { if (isLiteral) { int clPos = Tcl_DStringLength(&textBuffer); if (numCL >= maxNumCL) { maxNumCL *= 2; clPosition = ckrealloc(clPosition, maxNumCL * sizeof(int)); } clPosition[numCL] = clPos; numCL ++; } adjust++; } break; case TCL_TOKEN_COMMAND: /* * Push any accumulated chars appearing before the command. */ if (Tcl_DStringLength(&textBuffer) > 0) { int literal = TclRegisterDStringLiteral(envPtr, &textBuffer); TclEmitPush(literal, envPtr); numObjsToConcat++; Tcl_DStringFree(&textBuffer); if (numCL) { TclContinuationsEnter(TclFetchLiteral(envPtr, literal), numCL, clPosition); } numCL = 0; } envPtr->line += adjust; TclCompileScript(interp, tokenPtr->start+1, tokenPtr->size-2, envPtr); envPtr->line -= adjust; numObjsToConcat++; break; case TCL_TOKEN_VARIABLE: /* * Push any accumulated chars appearing before the $. */ if (Tcl_DStringLength(&textBuffer) > 0) { int literal; literal = TclRegisterDStringLiteral(envPtr, &textBuffer); TclEmitPush(literal, envPtr); numObjsToConcat++; Tcl_DStringFree(&textBuffer); } TclCompileVarSubst(interp, tokenPtr, envPtr); numObjsToConcat++; count -= tokenPtr->numComponents; tokenPtr += tokenPtr->numComponents; break; default: Tcl_Panic("Unexpected token type in TclCompileTokens: %d; %.*s", tokenPtr->type, tokenPtr->size, tokenPtr->start); } } /* * Push any accumulated characters appearing at the end. */ if (Tcl_DStringLength(&textBuffer) > 0) { int literal = TclRegisterDStringLiteral(envPtr, &textBuffer); TclEmitPush(literal, envPtr); numObjsToConcat++; if (numCL) { TclContinuationsEnter(TclFetchLiteral(envPtr, literal), numCL, clPosition); } numCL = 0; } /* * If necessary, concatenate the parts of the word. */ while (numObjsToConcat > 255) { TclEmitInstInt1(INST_STR_CONCAT1, 255, envPtr); numObjsToConcat -= 254; /* concat pushes 1 obj, the result */ } if (numObjsToConcat > 1) { TclEmitInstInt1(INST_STR_CONCAT1, numObjsToConcat, envPtr); } /* * If the tokens yielded no instructions, push an empty string. */ if (envPtr->codeNext == entryCodeNext) { PushStringLiteral(envPtr, ""); } Tcl_DStringFree(&textBuffer); /* * Release the temp table we used to collect the locations of continuation * lines, if any. */ if (maxNumCL) { ckfree(clPosition); } TclCheckStackDepth(depth+1, envPtr); } /* *---------------------------------------------------------------------- * * TclCompileCmdWord -- * * Given an array of parse tokens for a word containing one or more Tcl * commands, emit inline instructions to execute them. This procedure * differs from TclCompileTokens in that a simple word such as a loop * body enclosed in braces is not just pushed as a string, but is itself * parsed into tokens and compiled. * * Results: * The return value is a standard Tcl result. If an error occurs, an * error message is left in the interpreter's result. * * Side effects: * Instructions are added to envPtr to execute the tokens at runtime. * *---------------------------------------------------------------------- */ void TclCompileCmdWord( Tcl_Interp *interp, /* Used for error and status reporting. */ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens for * a command word to compile inline. */ int count, /* Number of tokens to consider at tokenPtr. * Must be at least 1. */ CompileEnv *envPtr) /* Holds the resulting instructions. */ { if ((count == 1) && (tokenPtr->type == TCL_TOKEN_TEXT)) { /* * Handle the common case: if there is a single text token, compile it * into an inline sequence of instructions. */ TclCompileScript(interp, tokenPtr->start, tokenPtr->size, envPtr); } else { /* * Multiple tokens or the single token involves substitutions. Emit * instructions to invoke the eval command procedure at runtime on the * result of evaluating the tokens. */ TclCompileTokens(interp, tokenPtr, count, envPtr); TclEmitInvoke(envPtr, INST_EVAL_STK); } } /* *---------------------------------------------------------------------- * * TclCompileExprWords -- * * Given an array of parse tokens representing one or more words that * contain a Tcl expression, emit inline instructions to execute the * expression. This procedure differs from TclCompileExpr in that it * supports Tcl's two-level substitution semantics for expressions that * appear as command words. * * Results: * The return value is a standard Tcl result. If an error occurs, an * error message is left in the interpreter's result. * * Side effects: * Instructions are added to envPtr to execute the expression. * *---------------------------------------------------------------------- */ void TclCompileExprWords( Tcl_Interp *interp, /* Used for error and status reporting. */ Tcl_Token *tokenPtr, /* Points to first in an array of word tokens * tokens for the expression to compile * inline. */ int numWords, /* Number of word tokens starting at tokenPtr. * Must be at least 1. Each word token * contains one or more subtokens. */ CompileEnv *envPtr) /* Holds the resulting instructions. */ { Tcl_Token *wordPtr; int i, concatItems; /* * If the expression is a single word that doesn't require substitutions, * just compile its string into inline instructions. */ if ((numWords == 1) && (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD)) { TclCompileExpr(interp, tokenPtr[1].start,tokenPtr[1].size, envPtr, 1); return; } /* * Emit code to call the expr command proc at runtime. Concatenate the * (already substituted once) expr tokens with a space between each. */ wordPtr = tokenPtr; for (i = 0; i < numWords; i++) { CompileTokens(envPtr, wordPtr, interp); if (i < (numWords - 1)) { PushStringLiteral(envPtr, " "); } wordPtr += wordPtr->numComponents + 1; } concatItems = 2*numWords - 1; while (concatItems > 255) { TclEmitInstInt1(INST_STR_CONCAT1, 255, envPtr); concatItems -= 254; } if (concatItems > 1) { TclEmitInstInt1(INST_STR_CONCAT1, concatItems, envPtr); } TclEmitOpcode(INST_EXPR_STK, envPtr); } /* *---------------------------------------------------------------------- * * TclCompileNoOp -- * * Function called to compile no-op's * * Results: * The return value is TCL_OK, indicating successful compilation. * * Side effects: * Instructions are added to envPtr to execute a no-op at runtime. No * result is pushed onto the stack: the compiler has to take care of this * itself if the last compiled command is a NoOp. * *---------------------------------------------------------------------- */ int TclCompileNoOp( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; int i; tokenPtr = parsePtr->tokenPtr; for (i = 1; i < parsePtr->numWords; i++) { tokenPtr = tokenPtr + tokenPtr->numComponents + 1; if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { CompileTokens(envPtr, tokenPtr, interp); TclEmitOpcode(INST_POP, envPtr); } } PushStringLiteral(envPtr, ""); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclInitByteCodeObj -- * * Create a ByteCode structure and initialize it from a CompileEnv * compilation environment structure. The ByteCode structure is smaller * and contains just that information needed to execute the bytecode * instructions resulting from compiling a Tcl script. The resulting * structure is placed in the specified object. * * Results: * A newly constructed ByteCode object is stored in the internal * representation of the objPtr. * * Side effects: * A single heap object is allocated to hold the new ByteCode structure * and its code, object, command location, and aux data arrays. Note that * "ownership" (i.e., the pointers to) the Tcl objects and aux data items * will be handed over to the new ByteCode structure from the CompileEnv * structure. * *---------------------------------------------------------------------- */ void TclInitByteCodeObj( Tcl_Obj *objPtr, /* Points object that should be initialized, * and whose string rep contains the source * code. */ register CompileEnv *envPtr)/* Points to the CompileEnv structure from * which to create a ByteCode structure. */ { register ByteCode *codePtr; size_t codeBytes, objArrayBytes, exceptArrayBytes, cmdLocBytes; size_t auxDataArrayBytes, structureSize; register unsigned char *p; #ifdef TCL_COMPILE_DEBUG unsigned char *nextPtr; #endif int numLitObjects = envPtr->literalArrayNext; Namespace *namespacePtr; int i, isNew; Interp *iPtr; if (envPtr->iPtr == NULL) { Tcl_Panic("TclInitByteCodeObj() called on uninitialized CompileEnv"); } iPtr = envPtr->iPtr; codeBytes = envPtr->codeNext - envPtr->codeStart; objArrayBytes = envPtr->literalArrayNext * sizeof(Tcl_Obj *); exceptArrayBytes = envPtr->exceptArrayNext * sizeof(ExceptionRange); auxDataArrayBytes = envPtr->auxDataArrayNext * sizeof(AuxData); cmdLocBytes = GetCmdLocEncodingSize(envPtr); /* * Compute the total number of bytes needed for this bytecode. */ structureSize = sizeof(ByteCode); structureSize += TCL_ALIGN(codeBytes); /* align object array */ structureSize += TCL_ALIGN(objArrayBytes); /* align exc range arr */ structureSize += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */ structureSize += auxDataArrayBytes; structureSize += cmdLocBytes; if (envPtr->iPtr->varFramePtr != NULL) { namespacePtr = envPtr->iPtr->varFramePtr->nsPtr; } else { namespacePtr = envPtr->iPtr->globalNsPtr; } p = ckalloc(structureSize); codePtr = (ByteCode *) p; codePtr->interpHandle = TclHandlePreserve(iPtr->handle); codePtr->compileEpoch = iPtr->compileEpoch; codePtr->nsPtr = namespacePtr; codePtr->nsEpoch = namespacePtr->resolverEpoch; codePtr->refCount = 1; if (namespacePtr->compiledVarResProc || iPtr->resolverPtr) { codePtr->flags = TCL_BYTECODE_RESOLVE_VARS; } else { codePtr->flags = 0; } codePtr->source = envPtr->source; codePtr->procPtr = envPtr->procPtr; codePtr->numCommands = envPtr->numCommands; codePtr->numSrcBytes = envPtr->numSrcBytes; codePtr->numCodeBytes = codeBytes; codePtr->numLitObjects = numLitObjects; codePtr->numExceptRanges = envPtr->exceptArrayNext; codePtr->numAuxDataItems = envPtr->auxDataArrayNext; codePtr->numCmdLocBytes = cmdLocBytes; codePtr->maxExceptDepth = envPtr->maxExceptDepth; codePtr->maxStackDepth = envPtr->maxStackDepth; p += sizeof(ByteCode); codePtr->codeStart = p; memcpy(p, envPtr->codeStart, (size_t) codeBytes); p += TCL_ALIGN(codeBytes); /* align object array */ codePtr->objArrayPtr = (Tcl_Obj **) p; for (i = 0; i < numLitObjects; i++) { Tcl_Obj *fetched = TclFetchLiteral(envPtr, i); if (objPtr == fetched) { /* * Prevent circular reference where the bytecode intrep of * a value contains a literal which is that same value. * If this is allowed to happen, refcount decrements may not * reach zero, and memory may leak. Bugs 467523, 3357771 * * NOTE: [Bugs 3392070, 3389764] We make a copy based completely * on the string value, and do not call Tcl_DuplicateObj() so we * can be sure we do not have any lingering cycles hiding in * the intrep. */ int numBytes; const char *bytes = Tcl_GetStringFromObj(objPtr, &numBytes); codePtr->objArrayPtr[i] = Tcl_NewStringObj(bytes, numBytes); Tcl_IncrRefCount(codePtr->objArrayPtr[i]); TclReleaseLiteral((Tcl_Interp *)iPtr, objPtr); } else { codePtr->objArrayPtr[i] = fetched; } } p += TCL_ALIGN(objArrayBytes); /* align exception range array */ if (exceptArrayBytes > 0) { codePtr->exceptArrayPtr = (ExceptionRange *) p; memcpy(p, envPtr->exceptArrayPtr, (size_t) exceptArrayBytes); } else { codePtr->exceptArrayPtr = NULL; } p += TCL_ALIGN(exceptArrayBytes); /* align AuxData array */ if (auxDataArrayBytes > 0) { codePtr->auxDataArrayPtr = (AuxData *) p; memcpy(p, envPtr->auxDataArrayPtr, (size_t) auxDataArrayBytes); } else { codePtr->auxDataArrayPtr = NULL; } p += auxDataArrayBytes; #ifndef TCL_COMPILE_DEBUG EncodeCmdLocMap(envPtr, codePtr, (unsigned char *) p); #else nextPtr = EncodeCmdLocMap(envPtr, codePtr, (unsigned char *) p); if (((size_t)(nextPtr - p)) != cmdLocBytes) { Tcl_Panic("TclInitByteCodeObj: encoded cmd location bytes %lu != expected size %lu", (unsigned long)(nextPtr - p), (unsigned long)cmdLocBytes); } #endif /* * Record various compilation-related statistics about the new ByteCode * structure. Don't include overhead for statistics-related fields. */ #ifdef TCL_COMPILE_STATS codePtr->structureSize = structureSize - (sizeof(size_t) + sizeof(Tcl_Time)); Tcl_GetTime(&codePtr->createTime); RecordByteCodeStats(codePtr); #endif /* TCL_COMPILE_STATS */ /* * Free the old internal rep then convert the object to a bytecode object * by making its internal rep point to the just compiled ByteCode. */ TclFreeIntRep(objPtr); objPtr->internalRep.twoPtrValue.ptr1 = codePtr; objPtr->typePtr = &tclByteCodeType; /* * TIP #280. Associate the extended per-word line information with the * byte code object (internal rep), for use with the bc compiler. */ Tcl_SetHashValue(Tcl_CreateHashEntry(iPtr->lineBCPtr, codePtr, &isNew), envPtr->extCmdMapPtr); envPtr->extCmdMapPtr = NULL; /* We've used up the CompileEnv. Mark as uninitialized. */ envPtr->iPtr = NULL; codePtr->localCachePtr = NULL; } /* *---------------------------------------------------------------------- * * TclFindCompiledLocal -- * * This procedure is called at compile time to look up and optionally * allocate an entry ("slot") for a variable in a procedure's array of * local variables. If the variable's name is NULL, a new temporary * variable is always created. (Such temporary variables can only be * referenced using their slot index.) * * Results: * If create is 0 and the name is non-NULL, then if the variable is * found, the index of its entry in the procedure's array of local * variables is returned; otherwise -1 is returned. If name is NULL, the * index of a new temporary variable is returned. Finally, if create is 1 * and name is non-NULL, the index of a new entry is returned. * * Side effects: * Creates and registers a new local variable if create is 1 and the * variable is unknown, or if the name is NULL. * *---------------------------------------------------------------------- */ int TclFindCompiledLocal( register const char *name, /* Points to first character of the name of a * scalar or array variable. If NULL, a * temporary var should be created. */ int nameBytes, /* Number of bytes in the name. */ int create, /* If 1, allocate a local frame entry for the * variable if it is new. */ CompileEnv *envPtr) /* Points to the current compile environment*/ { register CompiledLocal *localPtr; int localVar = -1; register int i; Proc *procPtr; /* * If not creating a temporary, does a local variable of the specified * name already exist? */ procPtr = envPtr->procPtr; if (procPtr == NULL) { /* * Compiling a non-body script: give it read access to the LVT in the * current localCache */ LocalCache *cachePtr = envPtr->iPtr->varFramePtr->localCachePtr; const char *localName; Tcl_Obj **varNamePtr; int len; if (!cachePtr || !name) { return -1; } varNamePtr = &cachePtr->varName0; for (i=0; i < cachePtr->numVars; varNamePtr++, i++) { if (*varNamePtr) { localName = Tcl_GetStringFromObj(*varNamePtr, &len); if ((len == nameBytes) && !strncmp(name, localName, len)) { return i; } } } return -1; } if (name != NULL) { int localCt = procPtr->numCompiledLocals; localPtr = procPtr->firstLocalPtr; for (i = 0; i < localCt; i++) { if (!TclIsVarTemporary(localPtr)) { char *localName = localPtr->name; if ((nameBytes == localPtr->nameLength) && (strncmp(name,localName,(unsigned)nameBytes) == 0)) { return i; } } localPtr = localPtr->nextPtr; } } /* * Create a new variable if appropriate. */ if (create || (name == NULL)) { localVar = procPtr->numCompiledLocals; localPtr = ckalloc(TclOffset(CompiledLocal, name) + nameBytes + 1); if (procPtr->firstLocalPtr == NULL) { procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr; } else { procPtr->lastLocalPtr->nextPtr = localPtr; procPtr->lastLocalPtr = localPtr; } localPtr->nextPtr = NULL; localPtr->nameLength = nameBytes; localPtr->frameIndex = localVar; localPtr->flags = 0; if (name == NULL) { localPtr->flags |= VAR_TEMPORARY; } localPtr->defValuePtr = NULL; localPtr->resolveInfo = NULL; if (name != NULL) { memcpy(localPtr->name, name, (size_t) nameBytes); } localPtr->name[nameBytes] = '\0'; procPtr->numCompiledLocals++; } return localVar; } /* *---------------------------------------------------------------------- * * TclExpandCodeArray -- * * Procedure that uses malloc to allocate more storage for a CompileEnv's * code array. * * Results: * None. * * Side effects: * The byte code array in *envPtr is reallocated to a new array of double * the size, and if envPtr->mallocedCodeArray is non-zero the old array * is freed. Byte codes are copied from the old array to the new one. * *---------------------------------------------------------------------- */ void TclExpandCodeArray( void *envArgPtr) /* Points to the CompileEnv whose code array * must be enlarged. */ { CompileEnv *envPtr = envArgPtr; /* The CompileEnv containing the code array to * be doubled in size. */ /* * envPtr->codeNext is equal to envPtr->codeEnd. The currently defined * code bytes are stored between envPtr->codeStart and envPtr->codeNext-1 * [inclusive]. */ size_t currBytes = envPtr->codeNext - envPtr->codeStart; size_t newBytes = 2 * (envPtr->codeEnd - envPtr->codeStart); if (envPtr->mallocedCodeArray) { envPtr->codeStart = ckrealloc(envPtr->codeStart, newBytes); } else { /* * envPtr->codeStart isn't a ckalloc'd pointer, so we must code a * ckrealloc equivalent for ourselves. */ unsigned char *newPtr = ckalloc(newBytes); memcpy(newPtr, envPtr->codeStart, currBytes); envPtr->codeStart = newPtr; envPtr->mallocedCodeArray = 1; } envPtr->codeNext = envPtr->codeStart + currBytes; envPtr->codeEnd = envPtr->codeStart + newBytes; } /* *---------------------------------------------------------------------- * * EnterCmdStartData -- * * Registers the starting source and bytecode location of a command. This * information is used at runtime to map between instruction pc and * source locations. * * Results: * None. * * Side effects: * Inserts source and code location information into the compilation * environment envPtr for the command at index cmdIndex. The compilation * environment's CmdLocation array is grown if necessary. * *---------------------------------------------------------------------- */ static void EnterCmdStartData( CompileEnv *envPtr, /* Points to the compilation environment * structure in which to enter command * location information. */ int cmdIndex, /* Index of the command whose start data is * being set. */ int srcOffset, /* Offset of first char of the command. */ int codeOffset) /* Offset of first byte of command code. */ { CmdLocation *cmdLocPtr; if ((cmdIndex < 0) || (cmdIndex >= envPtr->numCommands)) { Tcl_Panic("EnterCmdStartData: bad command index %d", cmdIndex); } if (cmdIndex >= envPtr->cmdMapEnd) { /* * Expand the command location array by allocating more storage from * the heap. The currently allocated CmdLocation entries are stored * from cmdMapPtr[0] up to cmdMapPtr[envPtr->cmdMapEnd] (inclusive). */ size_t currElems = envPtr->cmdMapEnd; size_t newElems = 2 * currElems; size_t currBytes = currElems * sizeof(CmdLocation); size_t newBytes = newElems * sizeof(CmdLocation); if (envPtr->mallocedCmdMap) { envPtr->cmdMapPtr = ckrealloc(envPtr->cmdMapPtr, newBytes); } else { /* * envPtr->cmdMapPtr isn't a ckalloc'd pointer, so we must code a * ckrealloc equivalent for ourselves. */ CmdLocation *newPtr = ckalloc(newBytes); memcpy(newPtr, envPtr->cmdMapPtr, currBytes); envPtr->cmdMapPtr = newPtr; envPtr->mallocedCmdMap = 1; } envPtr->cmdMapEnd = newElems; } if (cmdIndex > 0) { if (codeOffset < envPtr->cmdMapPtr[cmdIndex-1].codeOffset) { Tcl_Panic("EnterCmdStartData: cmd map not sorted by code offset"); } } cmdLocPtr = &envPtr->cmdMapPtr[cmdIndex]; cmdLocPtr->codeOffset = codeOffset; cmdLocPtr->srcOffset = srcOffset; cmdLocPtr->numSrcBytes = -1; cmdLocPtr->numCodeBytes = -1; } /* *---------------------------------------------------------------------- * * EnterCmdExtentData -- * * Registers the source and bytecode length for a command. This * information is used at runtime to map between instruction pc and * source locations. * * Results: * None. * * Side effects: * Inserts source and code length information into the compilation * environment envPtr for the command at index cmdIndex. Starting source * and bytecode information for the command must already have been * registered. * *---------------------------------------------------------------------- */ static void EnterCmdExtentData( CompileEnv *envPtr, /* Points to the compilation environment * structure in which to enter command * location information. */ int cmdIndex, /* Index of the command whose source and code * length data is being set. */ int numSrcBytes, /* Number of command source chars. */ int numCodeBytes) /* Offset of last byte of command code. */ { CmdLocation *cmdLocPtr; if ((cmdIndex < 0) || (cmdIndex >= envPtr->numCommands)) { Tcl_Panic("EnterCmdExtentData: bad command index %d", cmdIndex); } if (cmdIndex > envPtr->cmdMapEnd) { Tcl_Panic("EnterCmdExtentData: missing start data for command %d", cmdIndex); } cmdLocPtr = &envPtr->cmdMapPtr[cmdIndex]; cmdLocPtr->numSrcBytes = numSrcBytes; cmdLocPtr->numCodeBytes = numCodeBytes; } /* *---------------------------------------------------------------------- * TIP #280 * * EnterCmdWordData -- * * Registers the lines for the words of a command. This information is * used at runtime by 'info frame'. * * Results: * None. * * Side effects: * Inserts word location information into the compilation environment * envPtr for the command at index cmdIndex. The compilation * environment's ExtCmdLoc.ECL array is grown if necessary. * *---------------------------------------------------------------------- */ static void EnterCmdWordData( ExtCmdLoc *eclPtr, /* Points to the map environment structure in * which to enter command location * information. */ int srcOffset, /* Offset of first char of the command. */ Tcl_Token *tokenPtr, const char *cmd, int len, int numWords, int line, int *clNext, int **wlines, CompileEnv *envPtr) { ECL *ePtr; const char *last; int wordIdx, wordLine, *wwlines, *wordNext; if (eclPtr->nuloc >= eclPtr->nloc) { /* * Expand the ECL array by allocating more storage from the heap. The * currently allocated ECL entries are stored from eclPtr->loc[0] up * to eclPtr->loc[eclPtr->nuloc-1] (inclusive). */ size_t currElems = eclPtr->nloc; size_t newElems = (currElems ? 2*currElems : 1); size_t newBytes = newElems * sizeof(ECL); eclPtr->loc = ckrealloc(eclPtr->loc, newBytes); eclPtr->nloc = newElems; } ePtr = &eclPtr->loc[eclPtr->nuloc]; ePtr->srcOffset = srcOffset; ePtr->line = ckalloc(numWords * sizeof(int)); ePtr->next = ckalloc(numWords * sizeof(int *)); ePtr->nline = numWords; wwlines = ckalloc(numWords * sizeof(int)); last = cmd; wordLine = line; wordNext = clNext; for (wordIdx=0 ; wordIdxnumComponents + 1) { TclAdvanceLines(&wordLine, last, tokenPtr->start); TclAdvanceContinuations(&wordLine, &wordNext, tokenPtr->start - envPtr->source); wwlines[wordIdx] = (TclWordKnownAtCompileTime(tokenPtr, NULL) ? wordLine : -1); ePtr->line[wordIdx] = wordLine; ePtr->next[wordIdx] = wordNext; last = tokenPtr->start; } *wlines = wwlines; eclPtr->nuloc ++; } /* *---------------------------------------------------------------------- * * TclCreateExceptRange -- * * Procedure that allocates and initializes a new ExceptionRange * structure of the specified kind in a CompileEnv. * * Results: * Returns the index for the newly created ExceptionRange. * * Side effects: * If there is not enough room in the CompileEnv's ExceptionRange array, * the array in expanded: a new array of double the size is allocated, if * envPtr->mallocedExceptArray is non-zero the old array is freed, and * ExceptionRange entries are copied from the old array to the new one. * *---------------------------------------------------------------------- */ int TclCreateExceptRange( ExceptionRangeType type, /* The kind of ExceptionRange desired. */ register CompileEnv *envPtr)/* Points to CompileEnv for which to create a * new ExceptionRange structure. */ { register ExceptionRange *rangePtr; register ExceptionAux *auxPtr; int index = envPtr->exceptArrayNext; if (index >= envPtr->exceptArrayEnd) { /* * Expand the ExceptionRange array. The currently allocated entries * are stored between elements 0 and (envPtr->exceptArrayNext - 1) * [inclusive]. */ size_t currBytes = envPtr->exceptArrayNext * sizeof(ExceptionRange); size_t currBytes2 = envPtr->exceptArrayNext * sizeof(ExceptionAux); int newElems = 2*envPtr->exceptArrayEnd; size_t newBytes = newElems * sizeof(ExceptionRange); size_t newBytes2 = newElems * sizeof(ExceptionAux); if (envPtr->mallocedExceptArray) { envPtr->exceptArrayPtr = ckrealloc(envPtr->exceptArrayPtr, newBytes); envPtr->exceptAuxArrayPtr = ckrealloc(envPtr->exceptAuxArrayPtr, newBytes2); } else { /* * envPtr->exceptArrayPtr isn't a ckalloc'd pointer, so we must * code a ckrealloc equivalent for ourselves. */ ExceptionRange *newPtr = ckalloc(newBytes); ExceptionAux *newPtr2 = ckalloc(newBytes2); memcpy(newPtr, envPtr->exceptArrayPtr, currBytes); memcpy(newPtr2, envPtr->exceptAuxArrayPtr, currBytes2); envPtr->exceptArrayPtr = newPtr; envPtr->exceptAuxArrayPtr = newPtr2; envPtr->mallocedExceptArray = 1; } envPtr->exceptArrayEnd = newElems; } envPtr->exceptArrayNext++; rangePtr = &envPtr->exceptArrayPtr[index]; rangePtr->type = type; rangePtr->nestingLevel = envPtr->exceptDepth; rangePtr->codeOffset = -1; rangePtr->numCodeBytes = -1; rangePtr->breakOffset = -1; rangePtr->continueOffset = -1; rangePtr->catchOffset = -1; auxPtr = &envPtr->exceptAuxArrayPtr[index]; auxPtr->supportsContinue = 1; auxPtr->stackDepth = envPtr->currStackDepth; auxPtr->expandTarget = envPtr->expandCount; auxPtr->expandTargetDepth = -1; auxPtr->numBreakTargets = 0; auxPtr->breakTargets = NULL; auxPtr->allocBreakTargets = 0; auxPtr->numContinueTargets = 0; auxPtr->continueTargets = NULL; auxPtr->allocContinueTargets = 0; return index; } /* * --------------------------------------------------------------------- * * TclGetInnermostExceptionRange -- * * Returns the innermost exception range that covers the current code * creation point, and (optionally) the stack depth that is expected at * that point. Relies on the fact that the range has a numCodeBytes = -1 * when it is being populated and that inner ranges come after outer * ranges. * * --------------------------------------------------------------------- */ ExceptionRange * TclGetInnermostExceptionRange( CompileEnv *envPtr, int returnCode, ExceptionAux **auxPtrPtr) { int exnIdx = -1, i; for (i=0 ; iexceptArrayNext ; i++) { ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[i]; if (CurrentOffset(envPtr) >= rangePtr->codeOffset && (rangePtr->numCodeBytes == -1 || CurrentOffset(envPtr) < rangePtr->codeOffset+rangePtr->numCodeBytes) && (returnCode != TCL_CONTINUE || envPtr->exceptAuxArrayPtr[i].supportsContinue)) { exnIdx = i; } } if (exnIdx == -1) { return NULL; } if (auxPtrPtr) { *auxPtrPtr = &envPtr->exceptAuxArrayPtr[exnIdx]; } return &envPtr->exceptArrayPtr[exnIdx]; } /* * --------------------------------------------------------------------- * * TclAddLoopBreakFixup, TclAddLoopContinueFixup -- * * Adds a place that wants to break/continue to the loop exception range * tracking that will be fixed up once the loop can be finalized. These * functions will generate an INST_JUMP4 that will be fixed up during the * loop finalization. * * --------------------------------------------------------------------- */ void TclAddLoopBreakFixup( CompileEnv *envPtr, ExceptionAux *auxPtr) { int range = auxPtr - envPtr->exceptAuxArrayPtr; if (envPtr->exceptArrayPtr[range].type != LOOP_EXCEPTION_RANGE) { Tcl_Panic("trying to add 'break' fixup to full exception range"); } if (++auxPtr->numBreakTargets > auxPtr->allocBreakTargets) { auxPtr->allocBreakTargets *= 2; auxPtr->allocBreakTargets += 2; if (auxPtr->breakTargets) { auxPtr->breakTargets = ckrealloc(auxPtr->breakTargets, sizeof(int) * auxPtr->allocBreakTargets); } else { auxPtr->breakTargets = ckalloc(sizeof(int) * auxPtr->allocBreakTargets); } } auxPtr->breakTargets[auxPtr->numBreakTargets - 1] = CurrentOffset(envPtr); TclEmitInstInt4(INST_JUMP4, 0, envPtr); } void TclAddLoopContinueFixup( CompileEnv *envPtr, ExceptionAux *auxPtr) { int range = auxPtr - envPtr->exceptAuxArrayPtr; if (envPtr->exceptArrayPtr[range].type != LOOP_EXCEPTION_RANGE) { Tcl_Panic("trying to add 'continue' fixup to full exception range"); } if (++auxPtr->numContinueTargets > auxPtr->allocContinueTargets) { auxPtr->allocContinueTargets *= 2; auxPtr->allocContinueTargets += 2; if (auxPtr->continueTargets) { auxPtr->continueTargets = ckrealloc(auxPtr->continueTargets, sizeof(int) * auxPtr->allocContinueTargets); } else { auxPtr->continueTargets = ckalloc(sizeof(int) * auxPtr->allocContinueTargets); } } auxPtr->continueTargets[auxPtr->numContinueTargets - 1] = CurrentOffset(envPtr); TclEmitInstInt4(INST_JUMP4, 0, envPtr); } /* * --------------------------------------------------------------------- * * TclCleanupStackForBreakContinue -- * * Ditch the extra elements from the auxiliary stack and the main stack. * How to do this exactly depends on whether there are any elements on * the auxiliary stack to pop. * * --------------------------------------------------------------------- */ void TclCleanupStackForBreakContinue( CompileEnv *envPtr, ExceptionAux *auxPtr) { int savedStackDepth = envPtr->currStackDepth; int toPop = envPtr->expandCount - auxPtr->expandTarget; if (toPop > 0) { while (toPop --> 0) { TclEmitOpcode(INST_EXPAND_DROP, envPtr); } TclAdjustStackDepth(auxPtr->expandTargetDepth - envPtr->currStackDepth, envPtr); envPtr->currStackDepth = auxPtr->expandTargetDepth; } toPop = envPtr->currStackDepth - auxPtr->stackDepth; while (toPop --> 0) { TclEmitOpcode(INST_POP, envPtr); } envPtr->currStackDepth = savedStackDepth; } /* * --------------------------------------------------------------------- * * StartExpanding -- * * Pushes an INST_EXPAND_START and does some additional housekeeping so * that the [break] and [continue] compilers can use an exception-free * issue to discard it. * * --------------------------------------------------------------------- */ static void StartExpanding( CompileEnv *envPtr) { int i; TclEmitOpcode(INST_EXPAND_START, envPtr); /* * Update inner exception ranges with information about the environment * where this expansion started. */ for (i=0 ; iexceptArrayNext ; i++) { ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[i]; ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[i]; /* * Ignore loops unless they're still being built. */ if (rangePtr->codeOffset > CurrentOffset(envPtr)) { continue; } if (rangePtr->numCodeBytes != -1) { continue; } /* * Adequate condition: further out loops and further in exceptions * don't actually need this information. */ if (auxPtr->expandTarget == envPtr->expandCount) { auxPtr->expandTargetDepth = envPtr->currStackDepth; } } /* * There's now one more expansion being processed on the auxiliary stack. */ envPtr->expandCount++; } /* * --------------------------------------------------------------------- * * TclFinalizeLoopExceptionRange -- * * Finalizes a loop exception range, binding the registered [break] and * [continue] implementations so that they jump to the correct place. * Note that this must only be called after *all* the exception range * target offsets have been set. * * --------------------------------------------------------------------- */ void TclFinalizeLoopExceptionRange( CompileEnv *envPtr, int range) { ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[range]; ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[range]; int i, offset; unsigned char *site; if (rangePtr->type != LOOP_EXCEPTION_RANGE) { Tcl_Panic("trying to finalize a loop exception range"); } /* * Do the jump fixups. Note that these are always issued as INST_JUMP4 so * there is no need to fuss around with updating code offsets. */ for (i=0 ; inumBreakTargets ; i++) { site = envPtr->codeStart + auxPtr->breakTargets[i]; offset = rangePtr->breakOffset - auxPtr->breakTargets[i]; TclUpdateInstInt4AtPc(INST_JUMP4, offset, site); } for (i=0 ; inumContinueTargets ; i++) { site = envPtr->codeStart + auxPtr->continueTargets[i]; if (rangePtr->continueOffset == -1) { int j; /* * WTF? Can't bind, so revert to an INST_CONTINUE. Not enough * space to do anything else. */ *site = INST_CONTINUE; for (j=0 ; j<4 ; j++) { *++site = INST_NOP; } } else { offset = rangePtr->continueOffset - auxPtr->continueTargets[i]; TclUpdateInstInt4AtPc(INST_JUMP4, offset, site); } } /* * Drop the arrays we were holding the only reference to. */ if (auxPtr->breakTargets) { ckfree(auxPtr->breakTargets); auxPtr->breakTargets = NULL; auxPtr->numBreakTargets = 0; } if (auxPtr->continueTargets) { ckfree(auxPtr->continueTargets); auxPtr->continueTargets = NULL; auxPtr->numContinueTargets = 0; } } /* *---------------------------------------------------------------------- * * TclCreateAuxData -- * * Procedure that allocates and initializes a new AuxData structure in a * CompileEnv's array of compilation auxiliary data records. These * AuxData records hold information created during compilation by * CompileProcs and used by instructions during execution. * * Results: * Returns the index for the newly created AuxData structure. * * Side effects: * If there is not enough room in the CompileEnv's AuxData array, the * AuxData array in expanded: a new array of double the size is * allocated, if envPtr->mallocedAuxDataArray is non-zero the old array * is freed, and AuxData entries are copied from the old array to the new * one. * *---------------------------------------------------------------------- */ int TclCreateAuxData( ClientData clientData, /* The compilation auxiliary data to store in * the new aux data record. */ const AuxDataType *typePtr, /* Pointer to the type to attach to this * AuxData */ register CompileEnv *envPtr)/* Points to the CompileEnv for which a new * aux data structure is to be allocated. */ { int index; /* Index for the new AuxData structure. */ register AuxData *auxDataPtr; /* Points to the new AuxData structure */ index = envPtr->auxDataArrayNext; if (index >= envPtr->auxDataArrayEnd) { /* * Expand the AuxData array. The currently allocated entries are * stored between elements 0 and (envPtr->auxDataArrayNext - 1) * [inclusive]. */ size_t currBytes = envPtr->auxDataArrayNext * sizeof(AuxData); int newElems = 2*envPtr->auxDataArrayEnd; size_t newBytes = newElems * sizeof(AuxData); if (envPtr->mallocedAuxDataArray) { envPtr->auxDataArrayPtr = ckrealloc(envPtr->auxDataArrayPtr, newBytes); } else { /* * envPtr->auxDataArrayPtr isn't a ckalloc'd pointer, so we must * code a ckrealloc equivalent for ourselves. */ AuxData *newPtr = ckalloc(newBytes); memcpy(newPtr, envPtr->auxDataArrayPtr, currBytes); envPtr->auxDataArrayPtr = newPtr; envPtr->mallocedAuxDataArray = 1; } envPtr->auxDataArrayEnd = newElems; } envPtr->auxDataArrayNext++; auxDataPtr = &envPtr->auxDataArrayPtr[index]; auxDataPtr->clientData = clientData; auxDataPtr->type = typePtr; return index; } /* *---------------------------------------------------------------------- * * TclInitJumpFixupArray -- * * Initializes a JumpFixupArray structure to hold some number of jump * fixup entries. * * Results: * None. * * Side effects: * The JumpFixupArray structure is initialized. * *---------------------------------------------------------------------- */ void TclInitJumpFixupArray( register JumpFixupArray *fixupArrayPtr) /* Points to the JumpFixupArray structure to * initialize. */ { fixupArrayPtr->fixup = fixupArrayPtr->staticFixupSpace; fixupArrayPtr->next = 0; fixupArrayPtr->end = JUMPFIXUP_INIT_ENTRIES - 1; fixupArrayPtr->mallocedArray = 0; } /* *---------------------------------------------------------------------- * * TclExpandJumpFixupArray -- * * Procedure that uses malloc to allocate more storage for a jump fixup * array. * * Results: * None. * * Side effects: * The jump fixup array in *fixupArrayPtr is reallocated to a new array * of double the size, and if fixupArrayPtr->mallocedArray is non-zero * the old array is freed. Jump fixup structures are copied from the old * array to the new one. * *---------------------------------------------------------------------- */ void TclExpandJumpFixupArray( register JumpFixupArray *fixupArrayPtr) /* Points to the JumpFixupArray structure to * enlarge. */ { /* * The currently allocated jump fixup entries are stored from fixup[0] up * to fixup[fixupArrayPtr->fixupNext] (*not* inclusive). We assume * fixupArrayPtr->fixupNext is equal to fixupArrayPtr->fixupEnd. */ size_t currBytes = fixupArrayPtr->next * sizeof(JumpFixup); int newElems = 2*(fixupArrayPtr->end + 1); size_t newBytes = newElems * sizeof(JumpFixup); if (fixupArrayPtr->mallocedArray) { fixupArrayPtr->fixup = ckrealloc(fixupArrayPtr->fixup, newBytes); } else { /* * fixupArrayPtr->fixup isn't a ckalloc'd pointer, so we must code a * ckrealloc equivalent for ourselves. */ JumpFixup *newPtr = ckalloc(newBytes); memcpy(newPtr, fixupArrayPtr->fixup, currBytes); fixupArrayPtr->fixup = newPtr; fixupArrayPtr->mallocedArray = 1; } fixupArrayPtr->end = newElems; } /* *---------------------------------------------------------------------- * * TclFreeJumpFixupArray -- * * Free any storage allocated in a jump fixup array structure. * * Results: * None. * * Side effects: * Allocated storage in the JumpFixupArray structure is freed. * *---------------------------------------------------------------------- */ void TclFreeJumpFixupArray( register JumpFixupArray *fixupArrayPtr) /* Points to the JumpFixupArray structure to * free. */ { if (fixupArrayPtr->mallocedArray) { ckfree(fixupArrayPtr->fixup); } } /* *---------------------------------------------------------------------- * * TclEmitForwardJump -- * * Procedure to emit a two-byte forward jump of kind "jumpType". Since * the jump may later have to be grown to five bytes if the jump target * is more than, say, 127 bytes away, this procedure also initializes a * JumpFixup record with information about the jump. * * Results: * None. * * Side effects: * The JumpFixup record pointed to by "jumpFixupPtr" is initialized with * information needed later if the jump is to be grown. Also, a two byte * jump of the designated type is emitted at the current point in the * bytecode stream. * *---------------------------------------------------------------------- */ void TclEmitForwardJump( CompileEnv *envPtr, /* Points to the CompileEnv structure that * holds the resulting instruction. */ TclJumpType jumpType, /* Indicates the kind of jump: if true or * false or unconditional. */ JumpFixup *jumpFixupPtr) /* Points to the JumpFixup structure to * initialize with information about this * forward jump. */ { /* * Initialize the JumpFixup structure: * - codeOffset is offset of first byte of jump below * - cmdIndex is index of the command after the current one * - exceptIndex is the index of the first ExceptionRange after the * current one. */ jumpFixupPtr->jumpType = jumpType; jumpFixupPtr->codeOffset = envPtr->codeNext - envPtr->codeStart; jumpFixupPtr->cmdIndex = envPtr->numCommands; jumpFixupPtr->exceptIndex = envPtr->exceptArrayNext; switch (jumpType) { case TCL_UNCONDITIONAL_JUMP: TclEmitInstInt1(INST_JUMP1, 0, envPtr); break; case TCL_TRUE_JUMP: TclEmitInstInt1(INST_JUMP_TRUE1, 0, envPtr); break; default: TclEmitInstInt1(INST_JUMP_FALSE1, 0, envPtr); break; } } /* *---------------------------------------------------------------------- * * TclFixupForwardJump -- * * Procedure that updates a previously-emitted forward jump to jump a * specified number of bytes, "jumpDist". If necessary, the jump is grown * from two to five bytes; this is done if the jump distance is greater * than "distThreshold" (normally 127 bytes). The jump is described by a * JumpFixup record previously initialized by TclEmitForwardJump. * * Results: * 1 if the jump was grown and subsequent instructions had to be moved; * otherwise 0. This result is returned to allow callers to update any * additional code offsets they may hold. * * Side effects: * The jump may be grown and subsequent instructions moved. If this * happens, the code offsets for any commands and any ExceptionRange * records between the jump and the current code address will be updated * to reflect the moved code. Also, the bytecode instruction array in the * CompileEnv structure may be grown and reallocated. * *---------------------------------------------------------------------- */ int TclFixupForwardJump( CompileEnv *envPtr, /* Points to the CompileEnv structure that * holds the resulting instruction. */ JumpFixup *jumpFixupPtr, /* Points to the JumpFixup structure that * describes the forward jump. */ int jumpDist, /* Jump distance to set in jump instr. */ int distThreshold) /* Maximum distance before the two byte jump * is grown to five bytes. */ { unsigned char *jumpPc, *p; int firstCmd, lastCmd, firstRange, lastRange, k; unsigned numBytes; if (jumpDist <= distThreshold) { jumpPc = envPtr->codeStart + jumpFixupPtr->codeOffset; switch (jumpFixupPtr->jumpType) { case TCL_UNCONDITIONAL_JUMP: TclUpdateInstInt1AtPc(INST_JUMP1, jumpDist, jumpPc); break; case TCL_TRUE_JUMP: TclUpdateInstInt1AtPc(INST_JUMP_TRUE1, jumpDist, jumpPc); break; default: TclUpdateInstInt1AtPc(INST_JUMP_FALSE1, jumpDist, jumpPc); break; } return 0; } /* * We must grow the jump then move subsequent instructions down. Note that * if we expand the space for generated instructions, code addresses might * change; be careful about updating any of these addresses held in * variables. */ if ((envPtr->codeNext + 3) > envPtr->codeEnd) { TclExpandCodeArray(envPtr); } jumpPc = envPtr->codeStart + jumpFixupPtr->codeOffset; numBytes = envPtr->codeNext-jumpPc-2; p = jumpPc+2; memmove(p+3, p, numBytes); envPtr->codeNext += 3; jumpDist += 3; switch (jumpFixupPtr->jumpType) { case TCL_UNCONDITIONAL_JUMP: TclUpdateInstInt4AtPc(INST_JUMP4, jumpDist, jumpPc); break; case TCL_TRUE_JUMP: TclUpdateInstInt4AtPc(INST_JUMP_TRUE4, jumpDist, jumpPc); break; default: TclUpdateInstInt4AtPc(INST_JUMP_FALSE4, jumpDist, jumpPc); break; } /* * Adjust the code offsets for any commands and any ExceptionRange records * between the jump and the current code address. */ firstCmd = jumpFixupPtr->cmdIndex; lastCmd = envPtr->numCommands - 1; if (firstCmd < lastCmd) { for (k = firstCmd; k <= lastCmd; k++) { envPtr->cmdMapPtr[k].codeOffset += 3; } } firstRange = jumpFixupPtr->exceptIndex; lastRange = envPtr->exceptArrayNext - 1; for (k = firstRange; k <= lastRange; k++) { ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[k]; rangePtr->codeOffset += 3; switch (rangePtr->type) { case LOOP_EXCEPTION_RANGE: rangePtr->breakOffset += 3; if (rangePtr->continueOffset != -1) { rangePtr->continueOffset += 3; } break; case CATCH_EXCEPTION_RANGE: rangePtr->catchOffset += 3; break; default: Tcl_Panic("TclFixupForwardJump: bad ExceptionRange type %d", rangePtr->type); } } for (k = 0 ; k < envPtr->exceptArrayNext ; k++) { ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[k]; int i; for (i=0 ; inumBreakTargets ; i++) { if (jumpFixupPtr->codeOffset < auxPtr->breakTargets[i]) { auxPtr->breakTargets[i] += 3; } } for (i=0 ; inumContinueTargets ; i++) { if (jumpFixupPtr->codeOffset < auxPtr->continueTargets[i]) { auxPtr->continueTargets[i] += 3; } } } return 1; /* the jump was grown */ } /* *---------------------------------------------------------------------- * * TclEmitInvoke -- * * Emit one of the invoke-related instructions, wrapping it if necessary * in code that ensures that any break or continue operation passing * through it gets the stack unwinding correct, converting it into an * internal jump if in an appropriate context. * * Results: * None * * Side effects: * Issues the jump with all correct stack management. May create another * loop exception range; pointers to ExceptionRange and ExceptionAux * structures should not be held across this call. * *---------------------------------------------------------------------- */ void TclEmitInvoke( CompileEnv *envPtr, int opcode, ...) { va_list argList; ExceptionRange *rangePtr; ExceptionAux *auxBreakPtr, *auxContinuePtr; int arg1, arg2, wordCount = 0, expandCount = 0; int loopRange = 0, breakRange = 0, continueRange = 0; int cleanup, depth = TclGetStackDepth(envPtr); /* * Parse the arguments. */ va_start(argList, opcode); switch (opcode) { case INST_INVOKE_STK1: wordCount = arg1 = cleanup = va_arg(argList, int); arg2 = 0; break; case INST_INVOKE_STK4: wordCount = arg1 = cleanup = va_arg(argList, int); arg2 = 0; break; case INST_INVOKE_REPLACE: arg1 = va_arg(argList, int); arg2 = va_arg(argList, int); wordCount = arg1 + arg2 - 1; cleanup = arg1 + 1; break; default: Tcl_Panic("unexpected opcode"); case INST_EVAL_STK: wordCount = cleanup = 1; arg1 = arg2 = 0; break; case INST_RETURN_STK: wordCount = cleanup = 2; arg1 = arg2 = 0; break; case INST_INVOKE_EXPANDED: wordCount = arg1 = cleanup = va_arg(argList, int); arg2 = 0; expandCount = 1; break; } va_end(argList); /* * Determine if we need to handle break and continue exceptions with a * special handling exception range (so that we can correctly unwind the * stack). * * These must be done separately; they can be different (especially for * calls from inside a [for] increment clause). */ rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_CONTINUE, &auxContinuePtr); if (rangePtr == NULL || rangePtr->type != LOOP_EXCEPTION_RANGE) { auxContinuePtr = NULL; } else if (auxContinuePtr->stackDepth == envPtr->currStackDepth-wordCount && auxContinuePtr->expandTarget == envPtr->expandCount-expandCount) { auxContinuePtr = NULL; } else { continueRange = auxContinuePtr - envPtr->exceptAuxArrayPtr; } rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_BREAK, &auxBreakPtr); if (rangePtr == NULL || rangePtr->type != LOOP_EXCEPTION_RANGE) { auxBreakPtr = NULL; } else if (auxContinuePtr == NULL && auxBreakPtr->stackDepth == envPtr->currStackDepth-wordCount && auxBreakPtr->expandTarget == envPtr->expandCount-expandCount) { auxBreakPtr = NULL; } else { breakRange = auxBreakPtr - envPtr->exceptAuxArrayPtr; } if (auxBreakPtr != NULL || auxContinuePtr != NULL) { loopRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); ExceptionRangeStarts(envPtr, loopRange); } /* * Issue the invoke itself. */ switch (opcode) { case INST_INVOKE_STK1: TclEmitInstInt1(INST_INVOKE_STK1, arg1, envPtr); break; case INST_INVOKE_STK4: TclEmitInstInt4(INST_INVOKE_STK4, arg1, envPtr); break; case INST_INVOKE_EXPANDED: TclEmitOpcode(INST_INVOKE_EXPANDED, envPtr); envPtr->expandCount--; TclAdjustStackDepth(1 - arg1, envPtr); break; case INST_EVAL_STK: TclEmitOpcode(INST_EVAL_STK, envPtr); break; case INST_RETURN_STK: TclEmitOpcode(INST_RETURN_STK, envPtr); break; case INST_INVOKE_REPLACE: TclEmitInstInt4(INST_INVOKE_REPLACE, arg1, envPtr); TclEmitInt1(arg2, envPtr); TclAdjustStackDepth(-1, envPtr); /* Correction to stack depth calcs */ break; } /* * If we're generating a special wrapper exception range, we need to * finish that up now. */ if (auxBreakPtr != NULL || auxContinuePtr != NULL) { int savedStackDepth = envPtr->currStackDepth; int savedExpandCount = envPtr->expandCount; JumpFixup nonTrapFixup; if (auxBreakPtr != NULL) { auxBreakPtr = envPtr->exceptAuxArrayPtr + breakRange; } if (auxContinuePtr != NULL) { auxContinuePtr = envPtr->exceptAuxArrayPtr + continueRange; } ExceptionRangeEnds(envPtr, loopRange); TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &nonTrapFixup); /* * Careful! When generating these stack unwinding sequences, the depth * of stack in the cases where they are taken is not the same as if * the exception is not taken. */ if (auxBreakPtr != NULL) { TclAdjustStackDepth(-1, envPtr); ExceptionRangeTarget(envPtr, loopRange, breakOffset); TclCleanupStackForBreakContinue(envPtr, auxBreakPtr); TclAddLoopBreakFixup(envPtr, auxBreakPtr); TclAdjustStackDepth(1, envPtr); envPtr->currStackDepth = savedStackDepth; envPtr->expandCount = savedExpandCount; } if (auxContinuePtr != NULL) { TclAdjustStackDepth(-1, envPtr); ExceptionRangeTarget(envPtr, loopRange, continueOffset); TclCleanupStackForBreakContinue(envPtr, auxContinuePtr); TclAddLoopContinueFixup(envPtr, auxContinuePtr); TclAdjustStackDepth(1, envPtr); envPtr->currStackDepth = savedStackDepth; envPtr->expandCount = savedExpandCount; } TclFinalizeLoopExceptionRange(envPtr, loopRange); TclFixupForwardJumpToHere(envPtr, &nonTrapFixup, 127); } TclCheckStackDepth(depth+1-cleanup, envPtr); } /* *---------------------------------------------------------------------- * * TclGetInstructionTable -- * * Returns a pointer to the table describing Tcl bytecode instructions. * This procedure is defined so that clients can access the pointer from * outside the TCL DLLs. * * Results: * Returns a pointer to the global instruction table, same as the * expression (&tclInstructionTable[0]). * * Side effects: * None. * *---------------------------------------------------------------------- */ const void * /* == InstructionDesc* == */ TclGetInstructionTable(void) { return &tclInstructionTable[0]; } /* *---------------------------------------------------------------------- * * GetCmdLocEncodingSize -- * * Computes the total number of bytes needed to encode the command * location information for some compiled code. * * Results: * The byte count needed to encode the compiled location information. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int GetCmdLocEncodingSize( CompileEnv *envPtr) /* Points to compilation environment structure * containing the CmdLocation structure to * encode. */ { register CmdLocation *mapPtr = envPtr->cmdMapPtr; int numCmds = envPtr->numCommands; int codeDelta, codeLen, srcDelta, srcLen; int codeDeltaNext, codeLengthNext, srcDeltaNext, srcLengthNext; /* The offsets in their respective byte * sequences where the next encoded offset or * length should go. */ int prevCodeOffset, prevSrcOffset, i; codeDeltaNext = codeLengthNext = srcDeltaNext = srcLengthNext = 0; prevCodeOffset = prevSrcOffset = 0; for (i = 0; i < numCmds; i++) { codeDelta = mapPtr[i].codeOffset - prevCodeOffset; if (codeDelta < 0) { Tcl_Panic("GetCmdLocEncodingSize: bad code offset"); } else if (codeDelta <= 127) { codeDeltaNext++; } else { codeDeltaNext += 5; /* 1 byte for 0xFF, 4 for positive delta */ } prevCodeOffset = mapPtr[i].codeOffset; codeLen = mapPtr[i].numCodeBytes; if (codeLen < 0) { Tcl_Panic("GetCmdLocEncodingSize: bad code length"); } else if (codeLen <= 127) { codeLengthNext++; } else { codeLengthNext += 5;/* 1 byte for 0xFF, 4 for length */ } srcDelta = mapPtr[i].srcOffset - prevSrcOffset; if ((-127 <= srcDelta) && (srcDelta <= 127) && (srcDelta != -1)) { srcDeltaNext++; } else { srcDeltaNext += 5; /* 1 byte for 0xFF, 4 for delta */ } prevSrcOffset = mapPtr[i].srcOffset; srcLen = mapPtr[i].numSrcBytes; if (srcLen < 0) { Tcl_Panic("GetCmdLocEncodingSize: bad source length"); } else if (srcLen <= 127) { srcLengthNext++; } else { srcLengthNext += 5; /* 1 byte for 0xFF, 4 for length */ } } return (codeDeltaNext + codeLengthNext + srcDeltaNext + srcLengthNext); } /* *---------------------------------------------------------------------- * * EncodeCmdLocMap -- * * Encode the command location information for some compiled code into a * ByteCode structure. The encoded command location map is stored as * three adjacent byte sequences. * * Results: * Pointer to the first byte after the encoded command location * information. * * Side effects: * The encoded information is stored into the block of memory headed by * codePtr. Also records pointers to the start of the four byte sequences * in fields in codePtr's ByteCode header structure. * *---------------------------------------------------------------------- */ static unsigned char * EncodeCmdLocMap( CompileEnv *envPtr, /* Points to compilation environment structure * containing the CmdLocation structure to * encode. */ ByteCode *codePtr, /* ByteCode in which to encode envPtr's * command location information. */ unsigned char *startPtr) /* Points to the first byte in codePtr's * memory block where the location information * is to be stored. */ { register CmdLocation *mapPtr = envPtr->cmdMapPtr; int numCmds = envPtr->numCommands; register unsigned char *p = startPtr; int codeDelta, codeLen, srcDelta, srcLen, prevOffset; register int i; /* * Encode the code offset for each command as a sequence of deltas. */ codePtr->codeDeltaStart = p; prevOffset = 0; for (i = 0; i < numCmds; i++) { codeDelta = mapPtr[i].codeOffset - prevOffset; if (codeDelta < 0) { Tcl_Panic("EncodeCmdLocMap: bad code offset"); } else if (codeDelta <= 127) { TclStoreInt1AtPtr(codeDelta, p); p++; } else { TclStoreInt1AtPtr(0xFF, p); p++; TclStoreInt4AtPtr(codeDelta, p); p += 4; } prevOffset = mapPtr[i].codeOffset; } /* * Encode the code length for each command. */ codePtr->codeLengthStart = p; for (i = 0; i < numCmds; i++) { codeLen = mapPtr[i].numCodeBytes; if (codeLen < 0) { Tcl_Panic("EncodeCmdLocMap: bad code length"); } else if (codeLen <= 127) { TclStoreInt1AtPtr(codeLen, p); p++; } else { TclStoreInt1AtPtr(0xFF, p); p++; TclStoreInt4AtPtr(codeLen, p); p += 4; } } /* * Encode the source offset for each command as a sequence of deltas. */ codePtr->srcDeltaStart = p; prevOffset = 0; for (i = 0; i < numCmds; i++) { srcDelta = mapPtr[i].srcOffset - prevOffset; if ((-127 <= srcDelta) && (srcDelta <= 127) && (srcDelta != -1)) { TclStoreInt1AtPtr(srcDelta, p); p++; } else { TclStoreInt1AtPtr(0xFF, p); p++; TclStoreInt4AtPtr(srcDelta, p); p += 4; } prevOffset = mapPtr[i].srcOffset; } /* * Encode the source length for each command. */ codePtr->srcLengthStart = p; for (i = 0; i < numCmds; i++) { srcLen = mapPtr[i].numSrcBytes; if (srcLen < 0) { Tcl_Panic("EncodeCmdLocMap: bad source length"); } else if (srcLen <= 127) { TclStoreInt1AtPtr(srcLen, p); p++; } else { TclStoreInt1AtPtr(0xFF, p); p++; TclStoreInt4AtPtr(srcLen, p); p += 4; } } return p; } #ifdef TCL_COMPILE_STATS /* *---------------------------------------------------------------------- * * RecordByteCodeStats -- * * Accumulates various compilation-related statistics for each newly * compiled ByteCode. Called by the TclInitByteCodeObj when Tcl is * compiled with the -DTCL_COMPILE_STATS flag * * Results: * None. * * Side effects: * Accumulates aggregate code-related statistics in the interpreter's * ByteCodeStats structure. Records statistics specific to a ByteCode in * its ByteCode structure. * *---------------------------------------------------------------------- */ void RecordByteCodeStats( ByteCode *codePtr) /* Points to ByteCode structure with info * to add to accumulated statistics. */ { Interp *iPtr = (Interp *) *codePtr->interpHandle; register ByteCodeStats *statsPtr; if (iPtr == NULL) { /* Avoid segfaulting in case we're called in a deleted interp */ return; } statsPtr = &(iPtr->stats); statsPtr->numCompilations++; statsPtr->totalSrcBytes += (double) codePtr->numSrcBytes; statsPtr->totalByteCodeBytes += (double) codePtr->structureSize; statsPtr->currentSrcBytes += (double) codePtr->numSrcBytes; statsPtr->currentByteCodeBytes += (double) codePtr->structureSize; statsPtr->srcCount[TclLog2(codePtr->numSrcBytes)]++; statsPtr->byteCodeCount[TclLog2((int) codePtr->structureSize)]++; statsPtr->currentInstBytes += (double) codePtr->numCodeBytes; statsPtr->currentLitBytes += (double) codePtr->numLitObjects * sizeof(Tcl_Obj *); statsPtr->currentExceptBytes += (double) codePtr->numExceptRanges * sizeof(ExceptionRange); statsPtr->currentAuxBytes += (double) codePtr->numAuxDataItems * sizeof(AuxData); statsPtr->currentCmdMapBytes += (double) codePtr->numCmdLocBytes; } #endif /* TCL_COMPILE_STATS */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * End: */ tcl8.6.5/generic/tclPreserve.c0000644000175000017500000003146112663660065015652 0ustar sergeisergei/* * tclPreserve.c -- * * This file contains a collection of functions that are used to make * sure that widget records and other data structures aren't reallocated * when there are nested functions that depend on their existence. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * The following data structure is used to keep track of all the Tcl_Preserve * calls that are still in effect. It grows as needed to accommodate any * number of calls in effect. */ typedef struct { ClientData clientData; /* Address of preserved block. */ int refCount; /* Number of Tcl_Preserve calls in effect for * block. */ int mustFree; /* Non-zero means Tcl_EventuallyFree was * called while a Tcl_Preserve call was in * effect, so the structure must be freed when * refCount becomes zero. */ Tcl_FreeProc *freeProc; /* Function to call to free. */ } Reference; /* * Global data structures used to hold the list of preserved data references. * These variables are protected by "preserveMutex". */ static Reference *refArray = NULL; /* First in array of references. */ static int spaceAvl = 0; /* Total number of structures available at * *firstRefPtr. */ static int inUse = 0; /* Count of structures currently in use in * refArray. */ TCL_DECLARE_MUTEX(preserveMutex)/* To protect the above statics */ #define INITIAL_SIZE 2 /* Initial number of reference slots to make */ /* * The following data structure is used to keep track of whether an arbitrary * block of memory has been deleted. This is used by the TclHandle code to * avoid the more time-expensive algorithm of Tcl_Preserve(). This mechanism * is mainly used when we have lots of references to a few big, expensive * objects that we don't want to live any longer than necessary. */ typedef struct HandleStruct { void *ptr; /* Pointer to the memory block being tracked. * This field will become NULL when the memory * block is deleted. This field must be the * first in the structure. */ #ifdef TCL_MEM_DEBUG void *ptr2; /* Backup copy of the above pointer used to * ensure that the contents of the handle are * not changed by anyone else. */ #endif int refCount; /* Number of TclHandlePreserve() calls in * effect on this handle. */ } HandleStruct; /* *---------------------------------------------------------------------- * * TclFinalizePreserve -- * * Called during exit processing to clean up the reference array. * * Results: * None. * * Side effects: * Frees the storage of the reference array. * *---------------------------------------------------------------------- */ /* ARGSUSED */ void TclFinalizePreserve(void) { Tcl_MutexLock(&preserveMutex); if (spaceAvl != 0) { ckfree(refArray); refArray = NULL; inUse = 0; spaceAvl = 0; } Tcl_MutexUnlock(&preserveMutex); } /* *---------------------------------------------------------------------- * * Tcl_Preserve -- * * This function is used by a function to declare its interest in a * particular block of memory, so that the block will not be reallocated * until a matching call to Tcl_Release has been made. * * Results: * None. * * Side effects: * Information is retained so that the block of memory will not be freed * until at least the matching call to Tcl_Release. * *---------------------------------------------------------------------- */ void Tcl_Preserve( ClientData clientData) /* Pointer to malloc'ed block of memory. */ { Reference *refPtr; int i; /* * See if there is already a reference for this pointer. If so, just * increment its reference count. */ Tcl_MutexLock(&preserveMutex); for (i=0, refPtr=refArray ; iclientData == clientData) { refPtr->refCount++; Tcl_MutexUnlock(&preserveMutex); return; } } /* * Make a reference array if it doesn't already exist, or make it bigger * if it is full. */ if (inUse == spaceAvl) { spaceAvl = spaceAvl ? 2*spaceAvl : INITIAL_SIZE; refArray = ckrealloc(refArray, spaceAvl * sizeof(Reference)); } /* * Make a new entry for the new reference. */ refPtr = &refArray[inUse]; refPtr->clientData = clientData; refPtr->refCount = 1; refPtr->mustFree = 0; refPtr->freeProc = TCL_STATIC; inUse += 1; Tcl_MutexUnlock(&preserveMutex); } /* *---------------------------------------------------------------------- * * Tcl_Release -- * * This function is called to cancel a previous call to Tcl_Preserve, * thereby allowing a block of memory to be freed (if no one else cares * about it). * * Results: * None. * * Side effects: * If Tcl_EventuallyFree has been called for clientData, and if no other * call to Tcl_Preserve is still in effect, the block of memory is freed. * *---------------------------------------------------------------------- */ void Tcl_Release( ClientData clientData) /* Pointer to malloc'ed block of memory. */ { Reference *refPtr; int i; Tcl_MutexLock(&preserveMutex); for (i=0, refPtr=refArray ; iclientData != clientData) { continue; } if (--refPtr->refCount != 0) { Tcl_MutexUnlock(&preserveMutex); return; } /* * Must remove information from the slot before calling freeProc to * avoid reentrancy problems if the freeProc calls Tcl_Preserve on the * same clientData. Copy down the last reference in the array to * overwrite the current slot. */ freeProc = refPtr->freeProc; mustFree = refPtr->mustFree; inUse--; if (i < inUse) { refArray[i] = refArray[inUse]; } /* * Now committed to disposing the data. But first, we've patched up * all the global data structures so we should release the mutex now. * Only then should we dabble around with potentially-slow memory * managers... */ Tcl_MutexUnlock(&preserveMutex); if (mustFree) { if (freeProc == TCL_DYNAMIC) { ckfree(clientData); } else { freeProc(clientData); } } return; } Tcl_MutexUnlock(&preserveMutex); /* * Reference not found. This is a bug in the caller. */ Tcl_Panic("Tcl_Release couldn't find reference for %p", clientData); } /* *---------------------------------------------------------------------- * * Tcl_EventuallyFree -- * * Free up a block of memory, unless a call to Tcl_Preserve is in effect * for that block. In this case, defer the free until all calls to * Tcl_Preserve have been undone by matching calls to Tcl_Release. * * Results: * None. * * Side effects: * Ptr may be released by calling free(). * *---------------------------------------------------------------------- */ void Tcl_EventuallyFree( ClientData clientData, /* Pointer to malloc'ed block of memory. */ Tcl_FreeProc *freeProc) /* Function to actually do free. */ { Reference *refPtr; int i; /* * See if there is a reference for this pointer. If so, set its "mustFree" * flag (the flag had better not be set already!). */ Tcl_MutexLock(&preserveMutex); for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) { if (refPtr->clientData != clientData) { continue; } if (refPtr->mustFree) { Tcl_Panic("Tcl_EventuallyFree called twice for %p", clientData); } refPtr->mustFree = 1; refPtr->freeProc = freeProc; Tcl_MutexUnlock(&preserveMutex); return; } Tcl_MutexUnlock(&preserveMutex); /* * No reference for this block. Free it now. */ if (freeProc == TCL_DYNAMIC) { ckfree(clientData); } else { freeProc(clientData); } } /* *--------------------------------------------------------------------------- * * TclHandleCreate -- * * Allocate a handle that contains enough information to determine if an * arbitrary malloc'd block has been deleted. This is used to avoid the * more time-expensive algorithm of Tcl_Preserve(). * * Results: * The return value is a TclHandle that refers to the given malloc'd * block. Doubly dereferencing the returned handle will give back the * pointer to the block, or will give NULL if the block has been deleted. * * Side effects: * The caller must keep track of this handle (generally by storing it in * a field in the malloc'd block) and call TclHandleFree() on this handle * when the block is deleted. Everything else that wishes to keep track * of whether the malloc'd block has been deleted should use calls to * TclHandlePreserve() and TclHandleRelease() on the associated handle. * *--------------------------------------------------------------------------- */ TclHandle TclHandleCreate( void *ptr) /* Pointer to an arbitrary block of memory to * be tracked for deletion. Must not be * NULL. */ { HandleStruct *handlePtr = ckalloc(sizeof(HandleStruct)); handlePtr->ptr = ptr; #ifdef TCL_MEM_DEBUG handlePtr->ptr2 = ptr; #endif handlePtr->refCount = 0; return (TclHandle) handlePtr; } /* *--------------------------------------------------------------------------- * * TclHandleFree -- * * Called when the arbitrary malloc'd block associated with the handle is * being deleted. Modifies the handle so that doubly dereferencing it * will give NULL. This informs any user of the handle that the block of * memory formerly referenced by the handle has been freed. * * Results: * None. * * Side effects: * If nothing is referring to the handle, the handle will be reclaimed. * *--------------------------------------------------------------------------- */ void TclHandleFree( TclHandle handle) /* Previously created handle associated with a * malloc'd block that is being deleted. The * handle is modified so that doubly * dereferencing it will give NULL. */ { HandleStruct *handlePtr; handlePtr = (HandleStruct *) handle; #ifdef TCL_MEM_DEBUG if (handlePtr->refCount == 0x61616161) { Tcl_Panic("using previously disposed TclHandle %p", handlePtr); } if (handlePtr->ptr2 != handlePtr->ptr) { Tcl_Panic("someone has changed the block referenced by the handle %p\nfrom %p to %p", handlePtr, handlePtr->ptr2, handlePtr->ptr); } #endif handlePtr->ptr = NULL; if (handlePtr->refCount == 0) { ckfree(handlePtr); } } /* *--------------------------------------------------------------------------- * * TclHandlePreserve -- * * Declare an interest in the arbitrary malloc'd block associated with * the handle. * * Results: * The return value is the handle argument, with its ref count * incremented. * * Side effects: * For each call to TclHandlePreserve(), there should be a matching call * to TclHandleRelease() when the caller is no longer interested in the * malloc'd block associated with the handle. * *--------------------------------------------------------------------------- */ TclHandle TclHandlePreserve( TclHandle handle) /* Declare an interest in the block of memory * referenced by this handle. */ { HandleStruct *handlePtr; handlePtr = (HandleStruct *) handle; #ifdef TCL_MEM_DEBUG if (handlePtr->refCount == 0x61616161) { Tcl_Panic("using previously disposed TclHandle %p", handlePtr); } if ((handlePtr->ptr != NULL) && (handlePtr->ptr != handlePtr->ptr2)) { Tcl_Panic("someone has changed the block referenced by the handle %p\nfrom %p to %p", handlePtr, handlePtr->ptr2, handlePtr->ptr); } #endif handlePtr->refCount++; return handle; } /* *--------------------------------------------------------------------------- * * TclHandleRelease -- * * This function is called to release an interest in the malloc'd block * associated with the handle. * * Results: * None. * * Side effects: * The ref count of the handle is decremented. If the malloc'd block has * been freed and if no one is using the handle any more, the handle will * be reclaimed. * *--------------------------------------------------------------------------- */ void TclHandleRelease( TclHandle handle) /* Unregister interest in the block of memory * referenced by this handle. */ { HandleStruct *handlePtr; handlePtr = (HandleStruct *) handle; #ifdef TCL_MEM_DEBUG if (handlePtr->refCount == 0x61616161) { Tcl_Panic("using previously disposed TclHandle %p", handlePtr); } if ((handlePtr->ptr != NULL) && (handlePtr->ptr != handlePtr->ptr2)) { Tcl_Panic("someone has changed the block referenced by the handle %p\nfrom %p to %p", handlePtr, handlePtr->ptr2, handlePtr->ptr); } #endif if ((--handlePtr->refCount == 0) && (handlePtr->ptr == NULL)) { ckfree(handlePtr); } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclStubLib.c0000644000175000017500000000605012663660065015417 0ustar sergeisergei/* * tclStubLib.c -- * * Stub object that will be statically linked into extensions that want * to access Tcl. * * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 1998 Paul Duffin. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" MODULE_SCOPE const TclStubs *tclStubsPtr; MODULE_SCOPE const TclPlatStubs *tclPlatStubsPtr; MODULE_SCOPE const TclIntStubs *tclIntStubsPtr; MODULE_SCOPE const TclIntPlatStubs *tclIntPlatStubsPtr; const TclStubs *tclStubsPtr = NULL; const TclPlatStubs *tclPlatStubsPtr = NULL; const TclIntStubs *tclIntStubsPtr = NULL; const TclIntPlatStubs *tclIntPlatStubsPtr = NULL; /* * Use our own isDigit to avoid linking to libc on windows */ static int isDigit(const int c) { return (c >= '0' && c <= '9'); } /* *---------------------------------------------------------------------- * * Tcl_InitStubs -- * * Tries to initialise the stub table pointers and ensures that the * correct version of Tcl is loaded. * * Results: * The actual version of Tcl that satisfies the request, or NULL to * indicate that an error occurred. * * Side effects: * Sets the stub table pointers. * *---------------------------------------------------------------------- */ #undef Tcl_InitStubs MODULE_SCOPE const char * Tcl_InitStubs( Tcl_Interp *interp, const char *version, int exact) { Interp *iPtr = (Interp *) interp; const char *actualVersion = NULL; ClientData pkgData = NULL; const TclStubs *stubsPtr = iPtr->stubTable; /* * We can't optimize this check by caching tclStubsPtr because that * prevents apps from being able to load/unload Tcl dynamically multiple * times. [Bug 615304] */ if (!stubsPtr || (stubsPtr->magic != TCL_STUB_MAGIC)) { iPtr->result = "interpreter uses an incompatible stubs mechanism"; iPtr->freeProc = TCL_STATIC; return NULL; } actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData); if (actualVersion == NULL) { return NULL; } if (exact) { const char *p = version; int count = 0; while (*p) { count += !isDigit(*p++); } if (count == 1) { const char *q = actualVersion; p = version; while (*p && (*p == *q)) { p++; q++; } if (*p || isDigit(*q)) { /* Construct error message */ stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); return NULL; } } else { actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); if (actualVersion == NULL) { return NULL; } } } tclStubsPtr = (TclStubs *)pkgData; if (tclStubsPtr->hooks) { tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs; tclIntStubsPtr = tclStubsPtr->hooks->tclIntStubs; tclIntPlatStubsPtr = tclStubsPtr->hooks->tclIntPlatStubs; } else { tclPlatStubsPtr = NULL; tclIntStubsPtr = NULL; tclIntPlatStubsPtr = NULL; } return actualVersion; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclConfig.c0000644000175000017500000002517712663660065015273 0ustar sergeisergei/* * tclConfig.c -- * * This file provides the facilities which allow Tcl and other packages * to embed configuration information into their binary libraries. * * Copyright (c) 2002 Andreas Kupries * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Internal structure to hold embedded configuration information. * * Our structure is a two-level dictionary associated with the 'interp'. The * first level is keyed with the package name and maps to the dictionary for * that package. The package dictionary is keyed with metadata keys and maps * to the metadata value for that key. This is package specific. The metadata * values are in UTF-8, converted from the external representation given to us * by the caller. */ #define ASSOC_KEY "tclPackageAboutDict" /* * A ClientData struct for the QueryConfig command. Store the three bits * of data we need; the package name for which we store a config dict, * the (Tcl_Interp *) in which it is stored, and the encoding. */ typedef struct QCCD { Tcl_Obj *pkg; Tcl_Interp *interp; char *encoding; } QCCD; /* * Static functions in this file: */ static int QueryConfigObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, struct Tcl_Obj *const *objv); static void QueryConfigDelete(ClientData clientData); static Tcl_Obj * GetConfigDict(Tcl_Interp *interp); static void ConfigDictDeleteProc(ClientData clientData, Tcl_Interp *interp); /* *---------------------------------------------------------------------- * * Tcl_RegisterConfig -- * * See TIP#59 for details on what this function does. * * Results: * None. * * Side effects: * Creates namespace and cfg query command in it as per TIP #59. * *---------------------------------------------------------------------- */ void Tcl_RegisterConfig( Tcl_Interp *interp, /* Interpreter the configuration command is * registered in. */ const char *pkgName, /* Name of the package registering the * embedded configuration. ASCII, thus in * UTF-8 too. */ const Tcl_Config *configuration, /* Embedded configuration. */ const char *valEncoding) /* Name of the encoding used to store the * configuration values, ASCII, thus UTF-8. */ { Tcl_Obj *pDB, *pkgDict; Tcl_DString cmdName; const Tcl_Config *cfg; QCCD *cdPtr = ckalloc(sizeof(QCCD)); cdPtr->interp = interp; if (valEncoding) { cdPtr->encoding = ckalloc(strlen(valEncoding)+1); strcpy(cdPtr->encoding, valEncoding); } else { cdPtr->encoding = NULL; } cdPtr->pkg = Tcl_NewStringObj(pkgName, -1); /* * Phase I: Adding the provided information to the internal database of * package meta data. * * Phase II: Create a command for querying this database, specific to the * package registering its configuration. This is the approved interface * in TIP 59. In the future a more general interface should be done, as * follow-up to TIP 59. Simply because our database is now general across * packages, and not a structure tied to one package. * * Note, the created command will have a reference through its clientdata. */ Tcl_IncrRefCount(cdPtr->pkg); /* * For venc == NULL aka bogus encoding we skip the step setting up the * dictionaries visible at Tcl level. I.e. they are not filled */ pDB = GetConfigDict(interp); /* * Retrieve package specific configuration... */ if (Tcl_DictObjGet(interp, pDB, cdPtr->pkg, &pkgDict) != TCL_OK || (pkgDict == NULL)) { pkgDict = Tcl_NewDictObj(); } else if (Tcl_IsShared(pkgDict)) { pkgDict = Tcl_DuplicateObj(pkgDict); } /* * Extend the package configuration... * We cannot assume that the encodings are initialized, therefore * store the value as-is in a byte array. See Bug [9b2e636361]. */ for (cfg=configuration ; cfg->key!=NULL && cfg->key[0]!='\0' ; cfg++) { Tcl_DictObjPut(interp, pkgDict, Tcl_NewStringObj(cfg->key, -1), Tcl_NewByteArrayObj((unsigned char *)cfg->value, strlen(cfg->value))); } /* * Write the changes back into the overall database. */ Tcl_DictObjPut(interp, pDB, cdPtr->pkg, pkgDict); /* * Now create the interface command for retrieval of the package * information. */ Tcl_DStringInit(&cmdName); TclDStringAppendLiteral(&cmdName, "::"); Tcl_DStringAppend(&cmdName, pkgName, -1); /* * The incomplete command name is the name of the namespace to place it * in. */ if (Tcl_FindNamespace(interp, Tcl_DStringValue(&cmdName), NULL, TCL_GLOBAL_ONLY) == NULL) { if (Tcl_CreateNamespace(interp, Tcl_DStringValue(&cmdName), NULL, NULL) == NULL) { Tcl_Panic("%s.\n%s: %s", Tcl_GetStringResult(interp), "Tcl_RegisterConfig", "Unable to create namespace for package configuration."); } } TclDStringAppendLiteral(&cmdName, "::pkgconfig"); if (Tcl_CreateObjCommand(interp, Tcl_DStringValue(&cmdName), QueryConfigObjCmd, cdPtr, QueryConfigDelete) == NULL) { Tcl_Panic("%s: %s", "Tcl_RegisterConfig", "Unable to create query command for package configuration"); } Tcl_DStringFree(&cmdName); } /* *---------------------------------------------------------------------- * * QueryConfigObjCmd -- * * Implementation of "::::pkgconfig", the command to query * configuration information embedded into a binary library. * * Results: * A standard tcl result. * * Side effects: * See the manual for what this command does. * *---------------------------------------------------------------------- */ static int QueryConfigObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, struct Tcl_Obj *const *objv) { QCCD *cdPtr = clientData; Tcl_Obj *pkgName = cdPtr->pkg; Tcl_Obj *pDB, *pkgDict, *val, *listPtr; int n, index; static const char *const subcmdStrings[] = { "get", "list", NULL }; enum subcmds { CFG_GET, CFG_LIST }; Tcl_DString conv; Tcl_Encoding venc = NULL; const char *value; if ((objc < 2) || (objc > 3)) { Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], subcmdStrings, "subcommand", 0, &index) != TCL_OK) { return TCL_ERROR; } pDB = GetConfigDict(interp); if (Tcl_DictObjGet(interp, pDB, pkgName, &pkgDict) != TCL_OK || pkgDict == NULL) { /* * Maybe a Tcl_Panic is better, because the package data has to be * present. */ Tcl_SetObjResult(interp, Tcl_NewStringObj("package not known", -1)); Tcl_SetErrorCode(interp, "TCL", "FATAL", "PKGCFG_BASE", Tcl_GetString(pkgName), NULL); return TCL_ERROR; } switch ((enum subcmds) index) { case CFG_GET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "key"); return TCL_ERROR; } if (Tcl_DictObjGet(interp, pkgDict, objv[2], &val) != TCL_OK || val == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("key not known", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONFIG", Tcl_GetString(objv[2]), NULL); return TCL_ERROR; } if (cdPtr->encoding) { venc = Tcl_GetEncoding(interp, cdPtr->encoding); if (!venc) { return TCL_ERROR; } } /* * Value is stored as-is in a byte array, see Bug [9b2e636361], * so we have to decode it first. */ value = (const char *) Tcl_GetByteArrayFromObj(val, &n); value = Tcl_ExternalToUtfDString(venc, value, n, &conv); Tcl_SetObjResult(interp, Tcl_NewStringObj(value, Tcl_DStringLength(&conv))); Tcl_DStringFree(&conv); return TCL_OK; case CFG_LIST: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } Tcl_DictObjSize(interp, pkgDict, &n); listPtr = Tcl_NewListObj(n, NULL); if (!listPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "insufficient memory to create list", -1)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); return TCL_ERROR; } if (n) { Tcl_DictSearch s; Tcl_Obj *key; int done; for (Tcl_DictObjFirst(interp, pkgDict, &s, &key, NULL, &done); !done; Tcl_DictObjNext(&s, &key, NULL, &done)) { Tcl_ListObjAppendElement(NULL, listPtr, key); } } Tcl_SetObjResult(interp, listPtr); return TCL_OK; default: Tcl_Panic("QueryConfigObjCmd: Unknown subcommand to 'pkgconfig'. This can't happen"); break; } return TCL_ERROR; } /* *------------------------------------------------------------------------- * * QueryConfigDelete -- * * Command delete function. Cleans up after the configuration query * command when it is deleted by the user or during finalization. * * Results: * None. * * Side effects: * Deallocates all non-transient memory allocated by Tcl_RegisterConfig. * *------------------------------------------------------------------------- */ static void QueryConfigDelete( ClientData clientData) { QCCD *cdPtr = clientData; Tcl_Obj *pkgName = cdPtr->pkg; Tcl_Obj *pDB = GetConfigDict(cdPtr->interp); Tcl_DictObjRemove(NULL, pDB, pkgName); Tcl_DecrRefCount(pkgName); if (cdPtr->encoding) { ckfree((char *)cdPtr->encoding); } ckfree((char *)cdPtr); } /* *------------------------------------------------------------------------- * * GetConfigDict -- * * Retrieve the package metadata database from the interpreter. * Initializes it, if not present yet. * * Results: * A Tcl_Obj reference * * Side effects: * May allocate a Tcl_Obj. * *------------------------------------------------------------------------- */ static Tcl_Obj * GetConfigDict( Tcl_Interp *interp) { Tcl_Obj *pDB = Tcl_GetAssocData(interp, ASSOC_KEY, NULL); if (pDB == NULL) { pDB = Tcl_NewDictObj(); Tcl_IncrRefCount(pDB); Tcl_SetAssocData(interp, ASSOC_KEY, ConfigDictDeleteProc, pDB); } return pDB; } /* *---------------------------------------------------------------------- * * ConfigDictDeleteProc -- * * This function is associated with the "Package About dict" assoc data * for an interpreter; it is invoked when the interpreter is deleted in * order to free the information associated with any pending error * reports. * * Results: * None. * * Side effects: * The package metadata database is freed. * *---------------------------------------------------------------------- */ static void ConfigDictDeleteProc( ClientData clientData, /* Pointer to Tcl_Obj. */ Tcl_Interp *interp) /* Interpreter being deleted. */ { Tcl_Obj *pDB = clientData; Tcl_DecrRefCount(pDB); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclTomMath.decls0000644000175000017500000001270712663660065016302 0ustar sergeisergei# tclTomMath.decls -- # # This file contains the declarations for the functions in 'libtommath' # that are contained within the Tcl library. This file is used to # generate the 'tclTomMathDecls.h' and 'tclStubInit.c' files. # # If you edit this file, advance the revision number (and the epoch # if the new stubs are not backward compatible) in tclTomMathDecls.h # # Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. library tcl # Define the unsupported generic interfaces. interface tclTomMath # hooks {tclTomMathInt} scspec EXTERN # Declare each of the functions in the Tcl tommath interface declare 0 { int TclBN_epoch(void) } declare 1 { int TclBN_revision(void) } declare 2 { int TclBN_mp_add(mp_int *a, mp_int *b, mp_int *c) } declare 3 { int TclBN_mp_add_d(mp_int *a, mp_digit b, mp_int *c) } declare 4 { int TclBN_mp_and(mp_int *a, mp_int *b, mp_int *c) } declare 5 { void TclBN_mp_clamp(mp_int *a) } declare 6 { void TclBN_mp_clear(mp_int *a) } declare 7 { void TclBN_mp_clear_multi(mp_int *a, ...) } declare 8 { int TclBN_mp_cmp(const mp_int *a, const mp_int *b) } declare 9 { int TclBN_mp_cmp_d(const mp_int *a, mp_digit b) } declare 10 { int TclBN_mp_cmp_mag(const mp_int *a, const mp_int *b) } declare 11 { int TclBN_mp_copy(const mp_int *a, mp_int *b) } declare 12 { int TclBN_mp_count_bits(const mp_int *a) } declare 13 { int TclBN_mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r) } declare 14 { int TclBN_mp_div_d(mp_int *a, mp_digit b, mp_int *q, mp_digit *r) } declare 15 { int TclBN_mp_div_2(mp_int *a, mp_int *q) } declare 16 { int TclBN_mp_div_2d(const mp_int *a, int b, mp_int *q, mp_int *r) } declare 17 { int TclBN_mp_div_3(mp_int *a, mp_int *q, mp_digit *r) } declare 18 { void TclBN_mp_exch(mp_int *a, mp_int *b) } declare 19 { int TclBN_mp_expt_d(mp_int *a, mp_digit b, mp_int *c) } declare 20 { int TclBN_mp_grow(mp_int *a, int size) } declare 21 { int TclBN_mp_init(mp_int *a) } declare 22 { int TclBN_mp_init_copy(mp_int *a, mp_int *b) } declare 23 { int TclBN_mp_init_multi(mp_int *a, ...) } declare 24 { int TclBN_mp_init_set(mp_int *a, mp_digit b) } declare 25 { int TclBN_mp_init_size(mp_int *a, int size) } declare 26 { int TclBN_mp_lshd(mp_int *a, int shift) } declare 27 { int TclBN_mp_mod(mp_int *a, mp_int *b, mp_int *r) } declare 28 { int TclBN_mp_mod_2d(const mp_int *a, int b, mp_int *r) } declare 29 { int TclBN_mp_mul(mp_int *a, mp_int *b, mp_int *p) } declare 30 { int TclBN_mp_mul_d(mp_int *a, mp_digit b, mp_int *p) } declare 31 { int TclBN_mp_mul_2(mp_int *a, mp_int *p) } declare 32 { int TclBN_mp_mul_2d(const mp_int *a, int d, mp_int *p) } declare 33 { int TclBN_mp_neg(const mp_int *a, mp_int *b) } declare 34 { int TclBN_mp_or(mp_int *a, mp_int *b, mp_int *c) } declare 35 { int TclBN_mp_radix_size(mp_int *a, int radix, int *size) } declare 36 { int TclBN_mp_read_radix(mp_int *a, const char *str, int radix) } declare 37 { void TclBN_mp_rshd(mp_int *a, int shift) } declare 38 { int TclBN_mp_shrink(mp_int *a) } declare 39 { void TclBN_mp_set(mp_int *a, mp_digit b) } declare 40 { int TclBN_mp_sqr(mp_int *a, mp_int *b) } declare 41 { int TclBN_mp_sqrt(mp_int *a, mp_int *b) } declare 42 { int TclBN_mp_sub(mp_int *a, mp_int *b, mp_int *c) } declare 43 { int TclBN_mp_sub_d(mp_int *a, mp_digit b, mp_int *c) } declare 44 { int TclBN_mp_to_unsigned_bin(mp_int *a, unsigned char *b) } declare 45 { int TclBN_mp_to_unsigned_bin_n(mp_int *a, unsigned char *b, unsigned long *outlen) } declare 46 { int TclBN_mp_toradix_n(mp_int *a, char *str, int radix, int maxlen) } declare 47 { int TclBN_mp_unsigned_bin_size(mp_int *a) } declare 48 { int TclBN_mp_xor(mp_int *a, mp_int *b, mp_int *c) } declare 49 { void TclBN_mp_zero(mp_int *a) } # internal routines to libtommath - should not be called but must be # exported to accommodate the "tommath" extension declare 50 { void TclBN_reverse(unsigned char *s, int len) } declare 51 { int TclBN_fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs) } declare 52 { int TclBN_fast_s_mp_sqr(mp_int *a, mp_int *b) } declare 53 { int TclBN_mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c) } declare 54 { int TclBN_mp_karatsuba_sqr(mp_int *a, mp_int *b) } declare 55 { int TclBN_mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) } declare 56 { int TclBN_mp_toom_sqr(mp_int *a, mp_int *b) } declare 57 { int TclBN_s_mp_add(mp_int *a, mp_int *b, mp_int *c) } declare 58 { int TclBN_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs) } declare 59 { int TclBN_s_mp_sqr(mp_int *a, mp_int *b) } declare 60 { int TclBN_s_mp_sub(mp_int *a, mp_int *b, mp_int *c) } declare 61 { int TclBN_mp_init_set_int(mp_int *a, unsigned long i) } declare 62 { int TclBN_mp_set_int(mp_int *a, unsigned long i) } declare 63 { int TclBN_mp_cnt_lsb(const mp_int *a) } # Formerly internal API to allow initialisation of bignums without knowing the # typedefs of how a bignum works internally. declare 64 { void TclBNInitBignumFromLong(mp_int *bignum, long initVal) } declare 65 { void TclBNInitBignumFromWideInt(mp_int *bignum, Tcl_WideInt initVal) } declare 66 { void TclBNInitBignumFromWideUInt(mp_int *bignum, Tcl_WideUInt initVal) } # Local Variables: # mode: tcl # End: tcl8.6.5/generic/tclTomMathInt.h0000644000175000017500000000010712663660065016101 0ustar sergeisergei#include "tclInt.h" #include "tclTomMath.h" #include "tommath_class.h" tcl8.6.5/generic/tclPosixStr.c0000644000175000017500000007305612663660065015660 0ustar sergeisergei/* * tclPosixStr.c -- * * This file contains procedures that generate strings corresponding to * various POSIX-related codes, such as errno and signals. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-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. */ #include "tclInt.h" /* *---------------------------------------------------------------------- * * Tcl_ErrnoId -- * * Return a textual identifier for the current errno value. * * Results: * This procedure returns a machine-readable textual identifier that * corresponds to the current errno value (e.g. "EPERM"). The identifier * is the same as the #define name in errno.h. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * Tcl_ErrnoId(void) { switch (errno) { #if defined(E2BIG) && (!defined(EOVERFLOW) || (E2BIG != EOVERFLOW)) case E2BIG: return "E2BIG"; #endif #ifdef EACCES case EACCES: return "EACCES"; #endif #ifdef EADDRINUSE case EADDRINUSE: return "EADDRINUSE"; #endif #ifdef EADDRNOTAVAIL case EADDRNOTAVAIL: return "EADDRNOTAVAIL"; #endif #ifdef EADV case EADV: return "EADV"; #endif #ifdef EAFNOSUPPORT case EAFNOSUPPORT: return "EAFNOSUPPORT"; #endif #ifdef EAGAIN case EAGAIN: return "EAGAIN"; #endif #ifdef EALIGN case EALIGN: return "EALIGN"; #endif #if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY)) case EALREADY: return "EALREADY"; #endif #ifdef EBADE case EBADE: return "EBADE"; #endif #ifdef EBADF case EBADF: return "EBADF"; #endif #ifdef EBADFD case EBADFD: return "EBADFD"; #endif #ifdef EBADMSG case EBADMSG: return "EBADMSG"; #endif #ifdef ECANCELED case ECANCELED: return "ECANCELED"; #endif #ifdef EBADR case EBADR: return "EBADR"; #endif #ifdef EBADRPC case EBADRPC: return "EBADRPC"; #endif #ifdef EBADRQC case EBADRQC: return "EBADRQC"; #endif #ifdef EBADSLT case EBADSLT: return "EBADSLT"; #endif #ifdef EBFONT case EBFONT: return "EBFONT"; #endif #ifdef EBUSY case EBUSY: return "EBUSY"; #endif #ifdef ECHILD case ECHILD: return "ECHILD"; #endif #ifdef ECHRNG case ECHRNG: return "ECHRNG"; #endif #ifdef ECOMM case ECOMM: return "ECOMM"; #endif #ifdef ECONNABORTED case ECONNABORTED: return "ECONNABORTED"; #endif #ifdef ECONNREFUSED case ECONNREFUSED: return "ECONNREFUSED"; #endif #ifdef ECONNRESET case ECONNRESET: return "ECONNRESET"; #endif #if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK)) case EDEADLK: return "EDEADLK"; #endif #if defined(EDEADLOCK) && (!defined(EDEADLK) || (EDEADLOCK != EDEADLK)) case EDEADLOCK: return "EDEADLOCK"; #endif #ifdef EDESTADDRREQ case EDESTADDRREQ: return "EDESTADDRREQ"; #endif #ifdef EDIRTY case EDIRTY: return "EDIRTY"; #endif #ifdef EDOM case EDOM: return "EDOM"; #endif #ifdef EDOTDOT case EDOTDOT: return "EDOTDOT"; #endif #ifdef EDQUOT case EDQUOT: return "EDQUOT"; #endif #ifdef EDUPPKG case EDUPPKG: return "EDUPPKG"; #endif #ifdef EEXIST case EEXIST: return "EEXIST"; #endif #ifdef EFAULT case EFAULT: return "EFAULT"; #endif #ifdef EFBIG case EFBIG: return "EFBIG"; #endif #ifdef EHOSTDOWN case EHOSTDOWN: return "EHOSTDOWN"; #endif #ifdef EHOSTUNREACH case EHOSTUNREACH: return "EHOSTUNREACH"; #endif #if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS)) case EIDRM: return "EIDRM"; #endif #ifdef EINIT case EINIT: return "EINIT"; #endif #ifdef EINPROGRESS case EINPROGRESS: return "EINPROGRESS"; #endif #ifdef EINTR case EINTR: return "EINTR"; #endif #ifdef EINVAL case EINVAL: return "EINVAL"; #endif #ifdef EIO case EIO: return "EIO"; #endif #ifdef EISCONN case EISCONN: return "EISCONN"; #endif #ifdef EISDIR case EISDIR: return "EISDIR"; #endif #ifdef EISNAME case EISNAM: return "EISNAM"; #endif #ifdef ELBIN case ELBIN: return "ELBIN"; #endif #ifdef EL2HLT case EL2HLT: return "EL2HLT"; #endif #ifdef EL2NSYNC case EL2NSYNC: return "EL2NSYNC"; #endif #ifdef EL3HLT case EL3HLT: return "EL3HLT"; #endif #ifdef EL3RST case EL3RST: return "EL3RST"; #endif #ifdef ELIBACC case ELIBACC: return "ELIBACC"; #endif #ifdef ELIBBAD case ELIBBAD: return "ELIBBAD"; #endif #ifdef ELIBEXEC case ELIBEXEC: return "ELIBEXEC"; #endif #if defined(ELIBMAX) && (!defined(ECANCELED) || (ELIBMAX != ECANCELED)) case ELIBMAX: return "ELIBMAX"; #endif #ifdef ELIBSCN case ELIBSCN: return "ELIBSCN"; #endif #ifdef ELNRNG case ELNRNG: return "ELNRNG"; #endif #if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT)) case ELOOP: return "ELOOP"; #endif #ifdef EMFILE case EMFILE: return "EMFILE"; #endif #ifdef EMLINK case EMLINK: return "EMLINK"; #endif #ifdef EMSGSIZE case EMSGSIZE: return "EMSGSIZE"; #endif #ifdef EMULTIHOP case EMULTIHOP: return "EMULTIHOP"; #endif #ifdef ENAMETOOLONG case ENAMETOOLONG: return "ENAMETOOLONG"; #endif #ifdef ENAVAIL case ENAVAIL: return "ENAVAIL"; #endif #ifdef ENET case ENET: return "ENET"; #endif #ifdef ENETDOWN case ENETDOWN: return "ENETDOWN"; #endif #ifdef ENETRESET case ENETRESET: return "ENETRESET"; #endif #ifdef ENETUNREACH case ENETUNREACH: return "ENETUNREACH"; #endif #ifdef ENFILE case ENFILE: return "ENFILE"; #endif #ifdef ENOANO case ENOANO: return "ENOANO"; #endif #if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR)) case ENOBUFS: return "ENOBUFS"; #endif #ifdef ENOCSI case ENOCSI: return "ENOCSI"; #endif #if defined(ENODATA) && (!defined(ECONNREFUSED) || (ENODATA != ECONNREFUSED)) case ENODATA: return "ENODATA"; #endif #ifdef ENODEV case ENODEV: return "ENODEV"; #endif #ifdef ENOENT case ENOENT: return "ENOENT"; #endif #ifdef ENOEXEC case ENOEXEC: return "ENOEXEC"; #endif #ifdef ENOLCK case ENOLCK: return "ENOLCK"; #endif #ifdef ENOLINK case ENOLINK: return "ENOLINK"; #endif #ifdef ENOMEM case ENOMEM: return "ENOMEM"; #endif #ifdef ENOMSG case ENOMSG: return "ENOMSG"; #endif #ifdef ENONET case ENONET: return "ENONET"; #endif #ifdef ENOPKG case ENOPKG: return "ENOPKG"; #endif #ifdef ENOPROTOOPT case ENOPROTOOPT: return "ENOPROTOOPT"; #endif #ifdef ENOSPC case ENOSPC: return "ENOSPC"; #endif #if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR)) case ENOSR: return "ENOSR"; #endif #if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR)) case ENOSTR: return "ENOSTR"; #endif #ifdef ENOSYM case ENOSYM: return "ENOSYM"; #endif #ifdef ENOSYS case ENOSYS: return "ENOSYS"; #endif #ifdef ENOTBLK case ENOTBLK: return "ENOTBLK"; #endif #ifdef ENOTCONN case ENOTCONN: return "ENOTCONN"; #endif #ifdef ENOTRECOVERABLE case ENOTRECOVERABLE: return "ENOTRECOVERABLE"; #endif #ifdef ENOTDIR case ENOTDIR: return "ENOTDIR"; #endif #if defined(ENOTEMPTY) && (!defined(EEXIST) || (ENOTEMPTY != EEXIST)) case ENOTEMPTY: return "ENOTEMPTY"; #endif #ifdef ENOTNAM case ENOTNAM: return "ENOTNAM"; #endif #ifdef ENOTSOCK case ENOTSOCK: return "ENOTSOCK"; #endif #ifdef ENOTSUP case ENOTSUP: return "ENOTSUP"; #endif #ifdef ENOTTY case ENOTTY: return "ENOTTY"; #endif #ifdef ENOTUNIQ case ENOTUNIQ: return "ENOTUNIQ"; #endif #ifdef ENXIO case ENXIO: return "ENXIO"; #endif #if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP)) case EOPNOTSUPP: return "EOPNOTSUPP"; #endif #ifdef EOTHER case EOTHER: return "EOTHER"; #endif #if defined(EOVERFLOW) && (!defined(EFBIG) || (EOVERFLOW != EFBIG)) && (!defined(EINVAL) || (EOVERFLOW != EINVAL)) case EOVERFLOW: return "EOVERFLOW"; #endif #ifdef EOWNERDEAD case EOWNERDEAD: return "EOWNERDEAD"; #endif #ifdef EPERM case EPERM: return "EPERM"; #endif #if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT)) case EPFNOSUPPORT: return "EPFNOSUPPORT"; #endif #ifdef EPIPE case EPIPE: return "EPIPE"; #endif #ifdef EPROCLIM case EPROCLIM: return "EPROCLIM"; #endif #ifdef EPROCUNAVAIL case EPROCUNAVAIL: return "EPROCUNAVAIL"; #endif #ifdef EPROGMISMATCH case EPROGMISMATCH: return "EPROGMISMATCH"; #endif #ifdef EPROGUNAVAIL case EPROGUNAVAIL: return "EPROGUNAVAIL"; #endif #ifdef EPROTO case EPROTO: return "EPROTO"; #endif #ifdef EPROTONOSUPPORT case EPROTONOSUPPORT: return "EPROTONOSUPPORT"; #endif #ifdef EPROTOTYPE case EPROTOTYPE: return "EPROTOTYPE"; #endif #ifdef ERANGE case ERANGE: return "ERANGE"; #endif #if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED)) case EREFUSED: return "EREFUSED"; #endif #ifdef EREMCHG case EREMCHG: return "EREMCHG"; #endif #ifdef EREMDEV case EREMDEV: return "EREMDEV"; #endif #ifdef EREMOTE case EREMOTE: return "EREMOTE"; #endif #ifdef EREMOTEIO case EREMOTEIO: return "EREMOTEIO"; #endif #ifdef EREMOTERELEASE case EREMOTERELEASE: return "EREMOTERELEASE"; #endif #ifdef EROFS case EROFS: return "EROFS"; #endif #ifdef ERPCMISMATCH case ERPCMISMATCH: return "ERPCMISMATCH"; #endif #ifdef ERREMOTE case ERREMOTE: return "ERREMOTE"; #endif #ifdef ESHUTDOWN case ESHUTDOWN: return "ESHUTDOWN"; #endif #ifdef ESOCKTNOSUPPORT case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT"; #endif #ifdef ESPIPE case ESPIPE: return "ESPIPE"; #endif #ifdef ESRCH case ESRCH: return "ESRCH"; #endif #ifdef ESRMNT case ESRMNT: return "ESRMNT"; #endif #ifdef ESTALE case ESTALE: return "ESTALE"; #endif #ifdef ESUCCESS case ESUCCESS: return "ESUCCESS"; #endif #if defined(ETIME) && (!defined(ELOOP) || (ETIME != ELOOP)) case ETIME: return "ETIME"; #endif #if defined(ETIMEDOUT) && (!defined(ENOSTR) || (ETIMEDOUT != ENOSTR)) case ETIMEDOUT: return "ETIMEDOUT"; #endif #ifdef ETOOMANYREFS case ETOOMANYREFS: return "ETOOMANYREFS"; #endif #ifdef ETXTBSY case ETXTBSY: return "ETXTBSY"; #endif #ifdef EUCLEAN case EUCLEAN: return "EUCLEAN"; #endif #ifdef EUNATCH case EUNATCH: return "EUNATCH"; #endif #ifdef EUSERS case EUSERS: return "EUSERS"; #endif #ifdef EVERSION case EVERSION: return "EVERSION"; #endif #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) case EWOULDBLOCK: return "EWOULDBLOCK"; #endif #ifdef EXDEV case EXDEV: return "EXDEV"; #endif #ifdef EXFULL case EXFULL: return "EXFULL"; #endif } return "unknown error"; } /* *---------------------------------------------------------------------- * * Tcl_ErrnoMsg -- * * Return a human-readable message corresponding to a given errno value. * * Results: * The return value is the standard POSIX error message for errno. This * procedure is used instead of strerror because strerror returns * slightly different values on different machines (e.g. different * capitalizations), which cause problems for things such as regression * tests. This procedure provides messages for most standard errors, then * it calls strerror for things it doesn't understand. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * Tcl_ErrnoMsg( int err) /* Error number (such as in errno variable). */ { switch (err) { #if defined(E2BIG) && (!defined(EOVERFLOW) || (E2BIG != EOVERFLOW)) case E2BIG: return "argument list too long"; #endif #ifdef EACCES case EACCES: return "permission denied"; #endif #ifdef EADDRINUSE case EADDRINUSE: return "address already in use"; #endif #ifdef EADDRNOTAVAIL case EADDRNOTAVAIL: return "cannot assign requested address"; #endif #ifdef EADV case EADV: return "advertise error"; #endif #ifdef EAFNOSUPPORT case EAFNOSUPPORT: return "address family not supported by protocol"; #endif #ifdef EAGAIN case EAGAIN: return "resource temporarily unavailable"; #endif #ifdef EALIGN case EALIGN: return "EALIGN"; #endif #if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY)) case EALREADY: return "operation already in progress"; #endif #ifdef EBADE case EBADE: return "bad exchange descriptor"; #endif #ifdef EBADF case EBADF: return "bad file number"; #endif #ifdef EBADFD case EBADFD: return "file descriptor in bad state"; #endif #ifdef EBADMSG case EBADMSG: return "not a data message"; #endif #ifdef ECANCELED case ECANCELED: return "operation canceled"; #endif #ifdef EBADR case EBADR: return "bad request descriptor"; #endif #ifdef EBADRPC case EBADRPC: return "RPC structure is bad"; #endif #ifdef EBADRQC case EBADRQC: return "bad request code"; #endif #ifdef EBADSLT case EBADSLT: return "invalid slot"; #endif #ifdef EBFONT case EBFONT: return "bad font file format"; #endif #ifdef EBUSY case EBUSY: return "file busy"; #endif #ifdef ECHILD case ECHILD: return "no children"; #endif #ifdef ECHRNG case ECHRNG: return "channel number out of range"; #endif #ifdef ECOMM case ECOMM: return "communication error on send"; #endif #ifdef ECONNABORTED case ECONNABORTED: return "software caused connection abort"; #endif #ifdef ECONNREFUSED case ECONNREFUSED: return "connection refused"; #endif #ifdef ECONNRESET case ECONNRESET: return "connection reset by peer"; #endif #if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK)) case EDEADLK: return "resource deadlock avoided"; #endif #if defined(EDEADLOCK) && (!defined(EDEADLK) || (EDEADLOCK != EDEADLK)) case EDEADLOCK: return "resource deadlock avoided"; #endif #ifdef EDESTADDRREQ case EDESTADDRREQ: return "destination address required"; #endif #ifdef EDIRTY case EDIRTY: return "mounting a dirty fs w/o force"; #endif #ifdef EDOM case EDOM: return "math argument out of range"; #endif #ifdef EDOTDOT case EDOTDOT: return "cross mount point"; #endif #ifdef EDQUOT case EDQUOT: return "disk quota exceeded"; #endif #ifdef EDUPPKG case EDUPPKG: return "duplicate package name"; #endif #ifdef EEXIST case EEXIST: return "file already exists"; #endif #ifdef EFAULT case EFAULT: return "bad address in system call argument"; #endif #ifdef EFBIG case EFBIG: return "file too large"; #endif #ifdef EHOSTDOWN case EHOSTDOWN: return "host is down"; #endif #ifdef EHOSTUNREACH case EHOSTUNREACH: return "host is unreachable"; #endif #if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS)) case EIDRM: return "identifier removed"; #endif #ifdef EINIT case EINIT: return "initialization error"; #endif #ifdef EINPROGRESS case EINPROGRESS: return "operation now in progress"; #endif #ifdef EINTR case EINTR: return "interrupted system call"; #endif #ifdef EINVAL case EINVAL: return "invalid argument"; #endif #ifdef EIO case EIO: return "I/O error"; #endif #ifdef EISCONN case EISCONN: return "socket is already connected"; #endif #ifdef EISDIR case EISDIR: return "illegal operation on a directory"; #endif #ifdef EISNAME case EISNAM: return "is a name file"; #endif #ifdef ELBIN case ELBIN: return "ELBIN"; #endif #ifdef EL2HLT case EL2HLT: return "level 2 halted"; #endif #ifdef EL2NSYNC case EL2NSYNC: return "level 2 not synchronized"; #endif #ifdef EL3HLT case EL3HLT: return "level 3 halted"; #endif #ifdef EL3RST case EL3RST: return "level 3 reset"; #endif #ifdef ELIBACC case ELIBACC: return "cannot access a needed shared library"; #endif #ifdef ELIBBAD case ELIBBAD: return "accessing a corrupted shared library"; #endif #ifdef ELIBEXEC case ELIBEXEC: return "cannot exec a shared library directly"; #endif #if defined(ELIBMAX) && (!defined(ECANCELED) || (ELIBMAX != ECANCELED)) case ELIBMAX: return "attempting to link in more shared libraries than system limit"; #endif #ifdef ELIBSCN case ELIBSCN: return ".lib section in a.out corrupted"; #endif #ifdef ELNRNG case ELNRNG: return "link number out of range"; #endif #if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT)) case ELOOP: return "too many levels of symbolic links"; #endif #ifdef EMFILE case EMFILE: return "too many open files"; #endif #ifdef EMLINK case EMLINK: return "too many links"; #endif #ifdef EMSGSIZE case EMSGSIZE: return "message too long"; #endif #ifdef EMULTIHOP case EMULTIHOP: return "multihop attempted"; #endif #ifdef ENAMETOOLONG case ENAMETOOLONG: return "file name too long"; #endif #ifdef ENAVAIL case ENAVAIL: return "not available"; #endif #ifdef ENET case ENET: return "ENET"; #endif #ifdef ENETDOWN case ENETDOWN: return "network is down"; #endif #ifdef ENETRESET case ENETRESET: return "network dropped connection on reset"; #endif #ifdef ENETUNREACH case ENETUNREACH: return "network is unreachable"; #endif #ifdef ENFILE case ENFILE: return "file table overflow"; #endif #ifdef ENOANO case ENOANO: return "anode table overflow"; #endif #if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR)) case ENOBUFS: return "no buffer space available"; #endif #ifdef ENOCSI case ENOCSI: return "no CSI structure available"; #endif #if defined(ENODATA) && (!defined(ECONNREFUSED) || (ENODATA != ECONNREFUSED)) case ENODATA: return "no data available"; #endif #ifdef ENODEV case ENODEV: return "no such device"; #endif #ifdef ENOENT case ENOENT: return "no such file or directory"; #endif #ifdef ENOEXEC case ENOEXEC: return "exec format error"; #endif #ifdef ENOLCK case ENOLCK: return "no locks available"; #endif #ifdef ENOLINK case ENOLINK: return "link has been severed"; #endif #ifdef ENOMEM case ENOMEM: return "not enough memory"; #endif #ifdef ENOMSG case ENOMSG: return "no message of desired type"; #endif #ifdef ENONET case ENONET: return "machine is not on the network"; #endif #ifdef ENOPKG case ENOPKG: return "package not installed"; #endif #ifdef ENOPROTOOPT case ENOPROTOOPT: return "bad protocol option"; #endif #ifdef ENOSPC case ENOSPC: return "no space left on device"; #endif #if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR)) case ENOSR: return "out of stream resources"; #endif #if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR)) case ENOSTR: return "not a stream device"; #endif #ifdef ENOSYM case ENOSYM: return "unresolved symbol name"; #endif #ifdef ENOSYS case ENOSYS: return "function not implemented"; #endif #ifdef ENOTBLK case ENOTBLK: return "block device required"; #endif #ifdef ENOTCONN case ENOTCONN: return "socket is not connected"; #endif #ifdef ENOTRECOVERABLE case ENOTRECOVERABLE: return "state not recoverable"; #endif #ifdef ENOTDIR case ENOTDIR: return "not a directory"; #endif #if defined(ENOTEMPTY) && (!defined(EEXIST) || (ENOTEMPTY != EEXIST)) case ENOTEMPTY: return "directory not empty"; #endif #ifdef ENOTNAM case ENOTNAM: return "not a name file"; #endif #ifdef ENOTSOCK case ENOTSOCK: return "socket operation on non-socket"; #endif #ifdef ENOTSUP case ENOTSUP: return "operation not supported"; #endif #ifdef ENOTTY case ENOTTY: return "inappropriate device for ioctl"; #endif #ifdef ENOTUNIQ case ENOTUNIQ: return "name not unique on network"; #endif #ifdef ENXIO case ENXIO: return "no such device or address"; #endif #if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP)) case EOPNOTSUPP: return "operation not supported on socket"; #endif #ifdef EOTHER case EOTHER: return "other error"; #endif #if defined(EOVERFLOW) && (!defined(EFBIG) || (EOVERFLOW != EFBIG)) && (!defined(EINVAL) || (EOVERFLOW != EINVAL)) case EOVERFLOW: return "file too big"; #endif #ifdef EOWNERDEAD case EOWNERDEAD: return "owner died"; #endif #ifdef EPERM case EPERM: return "not owner"; #endif #if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT)) case EPFNOSUPPORT: return "protocol family not supported"; #endif #ifdef EPIPE case EPIPE: return "broken pipe"; #endif #ifdef EPROCLIM case EPROCLIM: return "too many processes"; #endif #ifdef EPROCUNAVAIL case EPROCUNAVAIL: return "bad procedure for program"; #endif #ifdef EPROGMISMATCH case EPROGMISMATCH: return "program version wrong"; #endif #ifdef EPROGUNAVAIL case EPROGUNAVAIL: return "RPC program not available"; #endif #ifdef EPROTO case EPROTO: return "protocol error"; #endif #ifdef EPROTONOSUPPORT case EPROTONOSUPPORT: return "protocol not supported"; #endif #ifdef EPROTOTYPE case EPROTOTYPE: return "protocol wrong type for socket"; #endif #ifdef ERANGE case ERANGE: return "math result unrepresentable"; #endif #if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED)) case EREFUSED: return "EREFUSED"; #endif #ifdef EREMCHG case EREMCHG: return "remote address changed"; #endif #ifdef EREMDEV case EREMDEV: return "remote device"; #endif #ifdef EREMOTE case EREMOTE: return "pathname hit remote file system"; #endif #ifdef EREMOTEIO case EREMOTEIO: return "remote i/o error"; #endif #ifdef EREMOTERELEASE case EREMOTERELEASE: return "EREMOTERELEASE"; #endif #ifdef EROFS case EROFS: return "read-only file system"; #endif #ifdef ERPCMISMATCH case ERPCMISMATCH: return "RPC version is wrong"; #endif #ifdef ERREMOTE case ERREMOTE: return "object is remote"; #endif #ifdef ESHUTDOWN case ESHUTDOWN: return "cannot send after socket shutdown"; #endif #ifdef ESOCKTNOSUPPORT case ESOCKTNOSUPPORT: return "socket type not supported"; #endif #ifdef ESPIPE case ESPIPE: return "invalid seek"; #endif #ifdef ESRCH case ESRCH: return "no such process"; #endif #ifdef ESRMNT case ESRMNT: return "srmount error"; #endif #ifdef ESTALE case ESTALE: return "stale remote file handle"; #endif #ifdef ESUCCESS case ESUCCESS: return "Error 0"; #endif #if defined(ETIME) && (!defined(ELOOP) || (ETIME != ELOOP)) case ETIME: return "timer expired"; #endif #if defined(ETIMEDOUT) && (!defined(ENOSTR) || (ETIMEDOUT != ENOSTR)) case ETIMEDOUT: return "connection timed out"; #endif #ifdef ETOOMANYREFS case ETOOMANYREFS: return "too many references: cannot splice"; #endif #ifdef ETXTBSY case ETXTBSY: return "text file or pseudo-device busy"; #endif #ifdef EUCLEAN case EUCLEAN: return "structure needs cleaning"; #endif #ifdef EUNATCH case EUNATCH: return "protocol driver not attached"; #endif #ifdef EUSERS case EUSERS: return "too many users"; #endif #ifdef EVERSION case EVERSION: return "version mismatch"; #endif #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) case EWOULDBLOCK: return "operation would block"; #endif #ifdef EXDEV case EXDEV: return "cross-domain link"; #endif #ifdef EXFULL case EXFULL: return "message tables full"; #endif default: #ifdef NO_STRERROR return "unknown POSIX error"; #else return strerror(err); #endif } } /* *---------------------------------------------------------------------- * * Tcl_SignalId -- * * Return a textual identifier for a signal number. * * Results: * This procedure returns a machine-readable textual identifier that * corresponds to sig. The identifier is the same as the #define name in * signal.h. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * Tcl_SignalId( int sig) /* Number of signal. */ { switch (sig) { #ifdef SIGABRT case SIGABRT: return "SIGABRT"; #endif #ifdef SIGALRM case SIGALRM: return "SIGALRM"; #endif #ifdef SIGBUS case SIGBUS: return "SIGBUS"; #endif #ifdef SIGCHLD case SIGCHLD: return "SIGCHLD"; #endif #if defined(SIGCLD) && (!defined(SIGCHLD) || (SIGCLD != SIGCHLD)) case SIGCLD: return "SIGCLD"; #endif #ifdef SIGCONT case SIGCONT: return "SIGCONT"; #endif #if defined(SIGEMT) && (!defined(SIGXCPU) || (SIGEMT != SIGXCPU)) case SIGEMT: return "SIGEMT"; #endif #ifdef SIGFPE case SIGFPE: return "SIGFPE"; #endif #ifdef SIGHUP case SIGHUP: return "SIGHUP"; #endif #ifdef SIGILL case SIGILL: return "SIGILL"; #endif #ifdef SIGINT case SIGINT: return "SIGINT"; #endif #ifdef SIGIO case SIGIO: return "SIGIO"; #endif #if defined(SIGIOT) && (!defined(SIGABRT) || (SIGIOT != SIGABRT)) case SIGIOT: return "SIGIOT"; #endif #ifdef SIGKILL case SIGKILL: return "SIGKILL"; #endif #if defined(SIGLOST) && (!defined(SIGIOT) || (SIGLOST != SIGIOT)) && (!defined(SIGURG) || (SIGLOST != SIGURG)) && (!defined(SIGPROF) || (SIGLOST != SIGPROF)) && (!defined(SIGIO) || (SIGLOST != SIGIO)) case SIGLOST: return "SIGLOST"; #endif #ifdef SIGPIPE case SIGPIPE: return "SIGPIPE"; #endif #if defined(SIGPOLL) && (!defined(SIGIO) || (SIGPOLL != SIGIO)) case SIGPOLL: return "SIGPOLL"; #endif #ifdef SIGPROF case SIGPROF: return "SIGPROF"; #endif #if defined(SIGPWR) && (!defined(SIGXFSZ) || (SIGPWR != SIGXFSZ)) && (!defined(SIGLOST) || (SIGPWR != SIGLOST)) case SIGPWR: return "SIGPWR"; #endif #ifdef SIGQUIT case SIGQUIT: return "SIGQUIT"; #endif #if defined(SIGSEGV) && (!defined(SIGBUS) || (SIGSEGV != SIGBUS)) case SIGSEGV: return "SIGSEGV"; #endif #ifdef SIGSTOP case SIGSTOP: return "SIGSTOP"; #endif #ifdef SIGSYS case SIGSYS: return "SIGSYS"; #endif #ifdef SIGTERM case SIGTERM: return "SIGTERM"; #endif #ifdef SIGTRAP case SIGTRAP: return "SIGTRAP"; #endif #ifdef SIGTSTP case SIGTSTP: return "SIGTSTP"; #endif #ifdef SIGTTIN case SIGTTIN: return "SIGTTIN"; #endif #ifdef SIGTTOU case SIGTTOU: return "SIGTTOU"; #endif #if defined(SIGURG) && (!defined(SIGIO) || (SIGURG != SIGIO)) case SIGURG: return "SIGURG"; #endif #if defined(SIGUSR1) && (!defined(SIGIO) || (SIGUSR1 != SIGIO)) case SIGUSR1: return "SIGUSR1"; #endif #if defined(SIGUSR2) && (!defined(SIGURG) || (SIGUSR2 != SIGURG)) case SIGUSR2: return "SIGUSR2"; #endif #ifdef SIGVTALRM case SIGVTALRM: return "SIGVTALRM"; #endif #ifdef SIGWINCH case SIGWINCH: return "SIGWINCH"; #endif #ifdef SIGXCPU case SIGXCPU: return "SIGXCPU"; #endif #ifdef SIGXFSZ case SIGXFSZ: return "SIGXFSZ"; #endif #if defined(SIGINFO) && (!defined(SIGPWR) || (SIGINFO != SIGPWR)) case SIGINFO: return "SIGINFO"; #endif } return "unknown signal"; } /* *---------------------------------------------------------------------- * * Tcl_SignalMsg -- * * Return a human-readable message describing a signal. * * Results: * This procedure returns a string describing sig that should make sense * to a human. It may not be easy for a machine to parse. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * Tcl_SignalMsg( int sig) /* Number of signal. */ { switch (sig) { #ifdef SIGABRT case SIGABRT: return "SIGABRT"; #endif #ifdef SIGALRM case SIGALRM: return "alarm clock"; #endif #ifdef SIGBUS case SIGBUS: return "bus error"; #endif #ifdef SIGCHLD case SIGCHLD: return "child status changed"; #endif #if defined(SIGCLD) && (!defined(SIGCHLD) || (SIGCLD != SIGCHLD)) case SIGCLD: return "child status changed"; #endif #ifdef SIGCONT case SIGCONT: return "continue after stop"; #endif #if defined(SIGEMT) && (!defined(SIGXCPU) || (SIGEMT != SIGXCPU)) case SIGEMT: return "EMT instruction"; #endif #ifdef SIGFPE case SIGFPE: return "floating-point exception"; #endif #ifdef SIGHUP case SIGHUP: return "hangup"; #endif #ifdef SIGILL case SIGILL: return "illegal instruction"; #endif #ifdef SIGINT case SIGINT: return "interrupt"; #endif #ifdef SIGIO case SIGIO: return "input/output possible on file"; #endif #if defined(SIGIOT) && (!defined(SIGABRT) || (SIGABRT != SIGIOT)) case SIGIOT: return "IOT instruction"; #endif #ifdef SIGKILL case SIGKILL: return "kill signal"; #endif #if defined(SIGLOST) && (!defined(SIGIOT) || (SIGLOST != SIGIOT)) && (!defined(SIGURG) || (SIGLOST != SIGURG)) && (!defined(SIGPROF) || (SIGLOST != SIGPROF)) && (!defined(SIGIO) || (SIGLOST != SIGIO)) case SIGLOST: return "resource lost"; #endif #ifdef SIGPIPE case SIGPIPE: return "write on pipe with no readers"; #endif #if defined(SIGPOLL) && (!defined(SIGIO) || (SIGPOLL != SIGIO)) case SIGPOLL: return "input/output possible on file"; #endif #ifdef SIGPROF case SIGPROF: return "profiling alarm"; #endif #if defined(SIGPWR) && (!defined(SIGXFSZ) || (SIGPWR != SIGXFSZ)) && (!defined(SIGLOST) || (SIGPWR != SIGLOST)) case SIGPWR: return "power-fail restart"; #endif #ifdef SIGQUIT case SIGQUIT: return "quit signal"; #endif #if defined(SIGSEGV) && (!defined(SIGBUS) || (SIGSEGV != SIGBUS)) case SIGSEGV: return "segmentation violation"; #endif #ifdef SIGSTOP case SIGSTOP: return "stop"; #endif #ifdef SIGSYS case SIGSYS: return "bad argument to system call"; #endif #ifdef SIGTERM case SIGTERM: return "software termination signal"; #endif #ifdef SIGTRAP case SIGTRAP: return "trace trap"; #endif #ifdef SIGTSTP case SIGTSTP: return "stop signal from tty"; #endif #ifdef SIGTTIN case SIGTTIN: return "background tty read"; #endif #ifdef SIGTTOU case SIGTTOU: return "background tty write"; #endif #if defined(SIGURG) && (!defined(SIGIO) || (SIGURG != SIGIO)) case SIGURG: return "urgent I/O condition"; #endif #if defined(SIGUSR1) && (!defined(SIGIO) || (SIGUSR1 != SIGIO)) case SIGUSR1: return "user-defined signal 1"; #endif #if defined(SIGUSR2) && (!defined(SIGURG) || (SIGUSR2 != SIGURG)) case SIGUSR2: return "user-defined signal 2"; #endif #ifdef SIGVTALRM case SIGVTALRM: return "virtual time alarm"; #endif #ifdef SIGWINCH case SIGWINCH: return "window changed"; #endif #ifdef SIGXCPU case SIGXCPU: return "exceeded CPU time limit"; #endif #ifdef SIGXFSZ case SIGXFSZ: return "exceeded file size limit"; #endif #if defined(SIGINFO) && (!defined(SIGPWR) || (SIGINFO != SIGPWR)) case SIGINFO: return "information request"; #endif } return "unknown signal"; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclPkgConfig.c0000644000175000017500000000650112663660065015723 0ustar sergeisergei/* * tclPkgConfig.c -- * * This file contains the configuration information to embed into the tcl * binary library. * * Copyright (c) 2002 Andreas Kupries * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ /* Note, the definitions in this module are influenced by the following C * preprocessor macros: * * OSCMa = shortcut for "old style configuration macro activates" * NSCMdt = shortcut for "new style configuration macro declares that" * * - TCL_THREADS OSCMa compilation as threaded core. * - TCL_MEM_DEBUG OSCMa memory debugging. * - TCL_COMPILE_DEBUG OSCMa debugging of bytecode compiler. * - TCL_COMPILE_STATS OSCMa bytecode compiler statistics. * * - TCL_CFG_DO64BIT NSCMdt tcl is compiled for a 64bit system. * - NDEBUG NSCMdt tcl is compiled with symbol info off. * - TCL_CFG_OPTIMIZED NSCMdt tcl is compiled with cc optimizations on * - TCL_CFG_PROFILED NSCMdt tcl is compiled with profiling info. * * - CFG_RUNTIME_* Paths to various stuff at runtime. * - CFG_INSTALL_* Paths to various stuff at installation time. * * - TCL_CFGVAL_ENCODING string containing the encoding used for the * configuration values. */ #include "tclInt.h" /* * Use C preprocessor statements to define the various values for the embedded * configuration information. */ #ifdef TCL_THREADS # define CFG_THREADED "1" #else # define CFG_THREADED "0" #endif #ifdef TCL_MEM_DEBUG # define CFG_MEMDEBUG "1" #else # define CFG_MEMDEBUG "0" #endif #ifdef TCL_COMPILE_DEBUG # define CFG_COMPILE_DEBUG "1" #else # define CFG_COMPILE_DEBUG "0" #endif #ifdef TCL_COMPILE_STATS # define CFG_COMPILE_STATS "1" #else # define CFG_COMPILE_STATS "0" #endif #ifdef TCL_CFG_DO64BIT # define CFG_64 "1" #else # define CFG_64 "0" #endif #ifndef NDEBUG # define CFG_DEBUG "1" #else # define CFG_DEBUG "0" #endif #ifdef TCL_CFG_OPTIMIZED # define CFG_OPTIMIZED "1" #else # define CFG_OPTIMIZED "0" #endif #ifdef TCL_CFG_PROFILED # define CFG_PROFILED "1" #else # define CFG_PROFILED "0" #endif static Tcl_Config const cfg[] = { {"debug", CFG_DEBUG}, {"threaded", CFG_THREADED}, {"profiled", CFG_PROFILED}, {"64bit", CFG_64}, {"optimized", CFG_OPTIMIZED}, {"mem_debug", CFG_MEMDEBUG}, {"compile_debug", CFG_COMPILE_DEBUG}, {"compile_stats", CFG_COMPILE_STATS}, /* Runtime paths to various stuff */ {"libdir,runtime", CFG_RUNTIME_LIBDIR}, {"bindir,runtime", CFG_RUNTIME_BINDIR}, {"scriptdir,runtime", CFG_RUNTIME_SCRDIR}, {"includedir,runtime", CFG_RUNTIME_INCDIR}, {"docdir,runtime", CFG_RUNTIME_DOCDIR}, /* Installation paths to various stuff */ {"libdir,install", CFG_INSTALL_LIBDIR}, {"bindir,install", CFG_INSTALL_BINDIR}, {"scriptdir,install", CFG_INSTALL_SCRDIR}, {"includedir,install", CFG_INSTALL_INCDIR}, {"docdir,install", CFG_INSTALL_DOCDIR}, /* Last entry, closes the array */ {NULL, NULL} }; void TclInitEmbeddedConfigurationInformation( Tcl_Interp *interp) /* Interpreter the configuration command is * registered in. */ { Tcl_RegisterConfig(interp, "tcl", cfg, TCL_CFGVAL_ENCODING); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclTrace.c0000644000175000017500000027503512663660065015124 0ustar sergeisergei/* * tclTrace.c -- * * This file contains code to handle most trace management. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-2000 Scriptics Corporation. * Copyright (c) 2002 ActiveState Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Structures used to hold information about variable traces: */ typedef struct { int flags; /* Operations for which Tcl command is to be * invoked. */ size_t length; /* Number of non-NUL chars. in command. */ char command[1]; /* Space for Tcl command to invoke. Actual * size will be as large as necessary to hold * command. This field must be the last in the * structure, so that it can be larger than 1 * byte. */ } TraceVarInfo; typedef struct { VarTrace traceInfo; TraceVarInfo traceCmdInfo; } CombinedTraceVarInfo; /* * Structure used to hold information about command traces: */ typedef struct { int flags; /* Operations for which Tcl command is to be * invoked. */ size_t length; /* Number of non-NUL chars. in command. */ Tcl_Trace stepTrace; /* Used for execution traces, when tracing * inside the given command */ int startLevel; /* Used for bookkeeping with step execution * traces, store the level at which the step * trace was invoked */ char *startCmd; /* Used for bookkeeping with step execution * traces, store the command name which * invoked step trace */ int curFlags; /* Trace flags for the current command */ int curCode; /* Return code for the current command */ int refCount; /* Used to ensure this structure is not * deleted too early. Keeps track of how many * pieces of code have a pointer to this * structure. */ char command[1]; /* Space for Tcl command to invoke. Actual * size will be as large as necessary to hold * command. This field must be the last in the * structure, so that it can be larger than 1 * byte. */ } TraceCommandInfo; /* * Used by command execution traces. Note that we assume in the code that * TCL_TRACE_ENTER_DURING_EXEC == 4 * TCL_TRACE_ENTER_EXEC and that * TCL_TRACE_LEAVE_DURING_EXEC == 4 * TCL_TRACE_LEAVE_EXEC. * * TCL_TRACE_ENTER_DURING_EXEC - Trace each command inside the command * currently being traced, before execution. * TCL_TRACE_LEAVE_DURING_EXEC - Trace each command inside the command * currently being traced, after execution. * TCL_TRACE_ANY_EXEC - OR'd combination of all EXEC flags. * TCL_TRACE_EXEC_IN_PROGRESS - The callback function on this trace is * currently executing. Therefore we don't let * further traces execute. * TCL_TRACE_EXEC_DIRECT - This execution trace is triggered directly * by the command being traced, not because of * an internal trace. * The flags 'TCL_TRACE_DESTROYED' and 'TCL_INTERP_DESTROYED' may also be used * in command execution traces. */ #define TCL_TRACE_ENTER_DURING_EXEC 4 #define TCL_TRACE_LEAVE_DURING_EXEC 8 #define TCL_TRACE_ANY_EXEC 15 #define TCL_TRACE_EXEC_IN_PROGRESS 0x10 #define TCL_TRACE_EXEC_DIRECT 0x20 /* * Forward declarations for functions defined in this file: */ typedef int (Tcl_TraceTypeObjCmd)(Tcl_Interp *interp, int optionIndex, int objc, Tcl_Obj *const objv[]); static Tcl_TraceTypeObjCmd TraceVariableObjCmd; static Tcl_TraceTypeObjCmd TraceCommandObjCmd; static Tcl_TraceTypeObjCmd TraceExecutionObjCmd; /* * Each subcommand has a number of 'types' to which it can apply. Currently * 'execution', 'command' and 'variable' are the only types supported. These * three arrays MUST be kept in sync! In the future we may provide an API to * add to the list of supported trace types. */ static const char *const traceTypeOptions[] = { "execution", "command", "variable", NULL }; static Tcl_TraceTypeObjCmd *const traceSubCmds[] = { TraceExecutionObjCmd, TraceCommandObjCmd, TraceVariableObjCmd }; /* * Declarations for local functions to this file: */ static int CallTraceFunction(Tcl_Interp *interp, Trace *tracePtr, Command *cmdPtr, const char *command, int numChars, int objc, Tcl_Obj *const objv[]); static char * TraceVarProc(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); static void TraceCommandProc(ClientData clientData, Tcl_Interp *interp, const char *oldName, const char *newName, int flags); static Tcl_CmdObjTraceProc TraceExecutionProc; static int StringTraceProc(ClientData clientData, Tcl_Interp *interp, int level, const char *command, Tcl_Command commandInfo, int objc, Tcl_Obj *const objv[]); static void StringTraceDeleteProc(ClientData clientData); static void DisposeTraceResult(int flags, char *result); static int TraceVarEx(Tcl_Interp *interp, const char *part1, const char *part2, register VarTrace *tracePtr); /* * The following structure holds the client data for string-based * trace procs */ typedef struct StringTraceData { ClientData clientData; /* Client data from Tcl_CreateTrace */ Tcl_CmdTraceProc *proc; /* Trace function from Tcl_CreateTrace */ } StringTraceData; /* * Convenience macros for iterating over the list of traces. Note that each of * these *must* be treated as a command, and *must* have a block following it. */ #define FOREACH_VAR_TRACE(interp, name, clientData) \ (clientData) = NULL; \ while (((clientData) = Tcl_VarTraceInfo2((interp), (name), NULL, \ 0, TraceVarProc, (clientData))) != NULL) #define FOREACH_COMMAND_TRACE(interp, name, clientData) \ (clientData) = NULL; \ while ((clientData = Tcl_CommandTraceInfo(interp, name, 0, \ TraceCommandProc, clientData)) != NULL) /* *---------------------------------------------------------------------- * * Tcl_TraceObjCmd -- * * This function is invoked to process the "trace" Tcl command. See the * user documentation for details on what it does. * * Standard syntax as of Tcl 8.4 is: * trace {add|info|remove} {command|variable} name ops cmd * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_TraceObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int optionIndex; const char *name; const char *flagOps, *p; /* Main sub commands to 'trace' */ static const char *const traceOptions[] = { "add", "info", "remove", #ifndef TCL_REMOVE_OBSOLETE_TRACES "variable", "vdelete", "vinfo", #endif NULL }; /* 'OLD' options are pre-Tcl-8.4 style */ enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE, #ifndef TCL_REMOVE_OBSOLETE_TRACES TRACE_OLD_VARIABLE, TRACE_OLD_VDELETE, TRACE_OLD_VINFO #endif }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], traceOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum traceOptions) optionIndex) { case TRACE_ADD: case TRACE_REMOVE: { /* * All sub commands of trace add/remove must take at least one more * argument. Beyond that we let the subcommand itself control the * argument structure. */ int typeIndex; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "type ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], traceTypeOptions, "option", 0, &typeIndex) != TCL_OK) { return TCL_ERROR; } return traceSubCmds[typeIndex](interp, optionIndex, objc, objv); } case TRACE_INFO: { /* * All sub commands of trace info must take exactly two more arguments * which name the type of thing being traced and the name of the thing * being traced. */ int typeIndex; if (objc < 3) { /* * Delegate other complaints to the type-specific code which can * give a better error message. */ Tcl_WrongNumArgs(interp, 2, objv, "type name"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], traceTypeOptions, "option", 0, &typeIndex) != TCL_OK) { return TCL_ERROR; } return traceSubCmds[typeIndex](interp, optionIndex, objc, objv); break; } #ifndef TCL_REMOVE_OBSOLETE_TRACES case TRACE_OLD_VARIABLE: case TRACE_OLD_VDELETE: { Tcl_Obj *copyObjv[6]; Tcl_Obj *opsList; int code, numFlags; if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "name ops command"); return TCL_ERROR; } opsList = Tcl_NewObj(); Tcl_IncrRefCount(opsList); flagOps = Tcl_GetStringFromObj(objv[3], &numFlags); if (numFlags == 0) { Tcl_DecrRefCount(opsList); goto badVarOps; } for (p = flagOps; *p != 0; p++) { Tcl_Obj *opObj; if (*p == 'r') { TclNewLiteralStringObj(opObj, "read"); } else if (*p == 'w') { TclNewLiteralStringObj(opObj, "write"); } else if (*p == 'u') { TclNewLiteralStringObj(opObj, "unset"); } else if (*p == 'a') { TclNewLiteralStringObj(opObj, "array"); } else { Tcl_DecrRefCount(opsList); goto badVarOps; } Tcl_ListObjAppendElement(NULL, opsList, opObj); } copyObjv[0] = NULL; memcpy(copyObjv+1, objv, objc*sizeof(Tcl_Obj *)); copyObjv[4] = opsList; if (optionIndex == TRACE_OLD_VARIABLE) { code = traceSubCmds[2](interp, TRACE_ADD, objc+1, copyObjv); } else { code = traceSubCmds[2](interp, TRACE_REMOVE, objc+1, copyObjv); } Tcl_DecrRefCount(opsList); return code; } case TRACE_OLD_VINFO: { ClientData clientData; char ops[5]; Tcl_Obj *resultListPtr, *pairObjPtr, *elemObjPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "name"); return TCL_ERROR; } resultListPtr = Tcl_NewObj(); name = Tcl_GetString(objv[2]); FOREACH_VAR_TRACE(interp, name, clientData) { TraceVarInfo *tvarPtr = clientData; char *q = ops; pairObjPtr = Tcl_NewListObj(0, NULL); if (tvarPtr->flags & TCL_TRACE_READS) { *q = 'r'; q++; } if (tvarPtr->flags & TCL_TRACE_WRITES) { *q = 'w'; q++; } if (tvarPtr->flags & TCL_TRACE_UNSETS) { *q = 'u'; q++; } if (tvarPtr->flags & TCL_TRACE_ARRAY) { *q = 'a'; q++; } *q = '\0'; /* * Build a pair (2-item list) with the ops string as the first obj * element and the tvarPtr->command string as the second obj * element. Append the pair (as an element) to the end of the * result object list. */ elemObjPtr = Tcl_NewStringObj(ops, -1); Tcl_ListObjAppendElement(NULL, pairObjPtr, elemObjPtr); elemObjPtr = Tcl_NewStringObj(tvarPtr->command, -1); Tcl_ListObjAppendElement(NULL, pairObjPtr, elemObjPtr); Tcl_ListObjAppendElement(interp, resultListPtr, pairObjPtr); } Tcl_SetObjResult(interp, resultListPtr); break; } #endif /* TCL_REMOVE_OBSOLETE_TRACES */ } return TCL_OK; badVarOps: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad operations \"%s\": should be one or more of rwua", flagOps)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "BADOPS", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TraceExecutionObjCmd -- * * Helper function for Tcl_TraceObjCmd; implements the [trace * {add|remove|info} execution ...] subcommands. See the user * documentation for details on what these do. * * Results: * Standard Tcl result. * * Side effects: * Depends on the operation (add, remove, or info) being performed; may * add or remove command traces on a command. * *---------------------------------------------------------------------- */ static int TraceExecutionObjCmd( Tcl_Interp *interp, /* Current interpreter. */ int optionIndex, /* Add, info or remove */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int commandLength, index; const char *name, *command; size_t length; enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE }; static const char *const opStrings[] = { "enter", "leave", "enterstep", "leavestep", NULL }; enum operations { TRACE_EXEC_ENTER, TRACE_EXEC_LEAVE, TRACE_EXEC_ENTER_STEP, TRACE_EXEC_LEAVE_STEP }; switch ((enum traceOptions) optionIndex) { case TRACE_ADD: case TRACE_REMOVE: { int flags = 0; int i, listLen, result; Tcl_Obj **elemPtrs; if (objc != 6) { Tcl_WrongNumArgs(interp, 3, objv, "name opList command"); return TCL_ERROR; } /* * Make sure the ops argument is a list object; get its length and a * pointer to its array of element pointers. */ result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs); if (result != TCL_OK) { return result; } if (listLen == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad operation list \"\": must be one or more of" " enter, leave, enterstep, or leavestep", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "NOOPS", NULL); return TCL_ERROR; } for (i = 0; i < listLen; i++) { if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings, "operation", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum operations) index) { case TRACE_EXEC_ENTER: flags |= TCL_TRACE_ENTER_EXEC; break; case TRACE_EXEC_LEAVE: flags |= TCL_TRACE_LEAVE_EXEC; break; case TRACE_EXEC_ENTER_STEP: flags |= TCL_TRACE_ENTER_DURING_EXEC; break; case TRACE_EXEC_LEAVE_STEP: flags |= TCL_TRACE_LEAVE_DURING_EXEC; break; } } command = Tcl_GetStringFromObj(objv[5], &commandLength); length = (size_t) commandLength; if ((enum traceOptions) optionIndex == TRACE_ADD) { TraceCommandInfo *tcmdPtr = ckalloc( TclOffset(TraceCommandInfo, command) + 1 + length); tcmdPtr->flags = flags; tcmdPtr->stepTrace = NULL; tcmdPtr->startLevel = 0; tcmdPtr->startCmd = NULL; tcmdPtr->length = length; tcmdPtr->refCount = 1; flags |= TCL_TRACE_DELETE; if (flags & (TCL_TRACE_ENTER_DURING_EXEC | TCL_TRACE_LEAVE_DURING_EXEC)) { flags |= (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC); } memcpy(tcmdPtr->command, command, length+1); name = Tcl_GetString(objv[3]); if (Tcl_TraceCommand(interp, name, flags, TraceCommandProc, tcmdPtr) != TCL_OK) { ckfree(tcmdPtr); return TCL_ERROR; } } else { /* * Search through all of our traces on this command to see if * there's one with the given command. If so, then delete the * first one that matches. */ ClientData clientData; /* * First ensure the name given is valid. */ name = Tcl_GetString(objv[3]); if (Tcl_FindCommand(interp,name,NULL,TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } FOREACH_COMMAND_TRACE(interp, name, clientData) { TraceCommandInfo *tcmdPtr = clientData; /* * In checking the 'flags' field we must remove any extraneous * flags which may have been temporarily added by various * pieces of the trace mechanism. */ if ((tcmdPtr->length == length) && ((tcmdPtr->flags & (TCL_TRACE_ANY_EXEC | TCL_TRACE_RENAME | TCL_TRACE_DELETE)) == flags) && (strncmp(command, tcmdPtr->command, (size_t) length) == 0)) { flags |= TCL_TRACE_DELETE; if (flags & (TCL_TRACE_ENTER_DURING_EXEC | TCL_TRACE_LEAVE_DURING_EXEC)) { flags |= (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC); } Tcl_UntraceCommand(interp, name, flags, TraceCommandProc, clientData); if (tcmdPtr->stepTrace != NULL) { /* * We need to remove the interpreter-wide trace which * we created to allow 'step' traces. */ Tcl_DeleteTrace(interp, tcmdPtr->stepTrace); tcmdPtr->stepTrace = NULL; if (tcmdPtr->startCmd != NULL) { ckfree(tcmdPtr->startCmd); } } if (tcmdPtr->flags & TCL_TRACE_EXEC_IN_PROGRESS) { /* * Postpone deletion. */ tcmdPtr->flags = 0; } if (tcmdPtr->refCount-- <= 1) { ckfree(tcmdPtr); } break; } } } break; } case TRACE_INFO: { ClientData clientData; Tcl_Obj *resultListPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "name"); return TCL_ERROR; } name = Tcl_GetString(objv[3]); /* * First ensure the name given is valid. */ if (Tcl_FindCommand(interp, name, NULL, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } resultListPtr = Tcl_NewListObj(0, NULL); FOREACH_COMMAND_TRACE(interp, name, clientData) { int numOps = 0; Tcl_Obj *opObj, *eachTraceObjPtr, *elemObjPtr; TraceCommandInfo *tcmdPtr = clientData; /* * Build a list with the ops list as the first obj element and the * tcmdPtr->command string as the second obj element. Append this * list (as an element) to the end of the result object list. */ elemObjPtr = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(elemObjPtr); if (tcmdPtr->flags & TCL_TRACE_ENTER_EXEC) { TclNewLiteralStringObj(opObj, "enter"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj); } if (tcmdPtr->flags & TCL_TRACE_LEAVE_EXEC) { TclNewLiteralStringObj(opObj, "leave"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj); } if (tcmdPtr->flags & TCL_TRACE_ENTER_DURING_EXEC) { TclNewLiteralStringObj(opObj, "enterstep"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj); } if (tcmdPtr->flags & TCL_TRACE_LEAVE_DURING_EXEC) { TclNewLiteralStringObj(opObj, "leavestep"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj); } Tcl_ListObjLength(NULL, elemObjPtr, &numOps); if (0 == numOps) { Tcl_DecrRefCount(elemObjPtr); continue; } eachTraceObjPtr = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr); Tcl_DecrRefCount(elemObjPtr); elemObjPtr = NULL; Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, Tcl_NewStringObj(tcmdPtr->command, -1)); Tcl_ListObjAppendElement(interp, resultListPtr, eachTraceObjPtr); } Tcl_SetObjResult(interp, resultListPtr); break; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TraceCommandObjCmd -- * * Helper function for Tcl_TraceObjCmd; implements the [trace * {add|info|remove} command ...] subcommands. See the user documentation * for details on what these do. * * Results: * Standard Tcl result. * * Side effects: * Depends on the operation (add, remove, or info) being performed; may * add or remove command traces on a command. * *---------------------------------------------------------------------- */ static int TraceCommandObjCmd( Tcl_Interp *interp, /* Current interpreter. */ int optionIndex, /* Add, info or remove */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int commandLength, index; const char *name, *command; size_t length; enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE }; static const char *const opStrings[] = { "delete", "rename", NULL }; enum operations { TRACE_CMD_DELETE, TRACE_CMD_RENAME }; switch ((enum traceOptions) optionIndex) { case TRACE_ADD: case TRACE_REMOVE: { int flags = 0; int i, listLen, result; Tcl_Obj **elemPtrs; if (objc != 6) { Tcl_WrongNumArgs(interp, 3, objv, "name opList command"); return TCL_ERROR; } /* * Make sure the ops argument is a list object; get its length and a * pointer to its array of element pointers. */ result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs); if (result != TCL_OK) { return result; } if (listLen == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad operation list \"\": must be one or more of" " delete or rename", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "NOOPS", NULL); return TCL_ERROR; } for (i = 0; i < listLen; i++) { if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings, "operation", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum operations) index) { case TRACE_CMD_RENAME: flags |= TCL_TRACE_RENAME; break; case TRACE_CMD_DELETE: flags |= TCL_TRACE_DELETE; break; } } command = Tcl_GetStringFromObj(objv[5], &commandLength); length = (size_t) commandLength; if ((enum traceOptions) optionIndex == TRACE_ADD) { TraceCommandInfo *tcmdPtr = ckalloc( TclOffset(TraceCommandInfo, command) + 1 + length); tcmdPtr->flags = flags; tcmdPtr->stepTrace = NULL; tcmdPtr->startLevel = 0; tcmdPtr->startCmd = NULL; tcmdPtr->length = length; tcmdPtr->refCount = 1; flags |= TCL_TRACE_DELETE; memcpy(tcmdPtr->command, command, length+1); name = Tcl_GetString(objv[3]); if (Tcl_TraceCommand(interp, name, flags, TraceCommandProc, tcmdPtr) != TCL_OK) { ckfree(tcmdPtr); return TCL_ERROR; } } else { /* * Search through all of our traces on this command to see if * there's one with the given command. If so, then delete the * first one that matches. */ ClientData clientData; /* * First ensure the name given is valid. */ name = Tcl_GetString(objv[3]); if (Tcl_FindCommand(interp,name,NULL,TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } FOREACH_COMMAND_TRACE(interp, name, clientData) { TraceCommandInfo *tcmdPtr = clientData; if ((tcmdPtr->length == length) && (tcmdPtr->flags == flags) && (strncmp(command, tcmdPtr->command, (size_t) length) == 0)) { Tcl_UntraceCommand(interp, name, flags | TCL_TRACE_DELETE, TraceCommandProc, clientData); tcmdPtr->flags |= TCL_TRACE_DESTROYED; if (tcmdPtr->refCount-- <= 1) { ckfree(tcmdPtr); } break; } } } break; } case TRACE_INFO: { ClientData clientData; Tcl_Obj *resultListPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "name"); return TCL_ERROR; } /* * First ensure the name given is valid. */ name = Tcl_GetString(objv[3]); if (Tcl_FindCommand(interp, name, NULL, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } resultListPtr = Tcl_NewListObj(0, NULL); FOREACH_COMMAND_TRACE(interp, name, clientData) { int numOps = 0; Tcl_Obj *opObj, *eachTraceObjPtr, *elemObjPtr; TraceCommandInfo *tcmdPtr = clientData; /* * Build a list with the ops list as the first obj element and the * tcmdPtr->command string as the second obj element. Append this * list (as an element) to the end of the result object list. */ elemObjPtr = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(elemObjPtr); if (tcmdPtr->flags & TCL_TRACE_RENAME) { TclNewLiteralStringObj(opObj, "rename"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj); } if (tcmdPtr->flags & TCL_TRACE_DELETE) { TclNewLiteralStringObj(opObj, "delete"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObj); } Tcl_ListObjLength(NULL, elemObjPtr, &numOps); if (0 == numOps) { Tcl_DecrRefCount(elemObjPtr); continue; } eachTraceObjPtr = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr); Tcl_DecrRefCount(elemObjPtr); elemObjPtr = Tcl_NewStringObj(tcmdPtr->command, -1); Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr); Tcl_ListObjAppendElement(interp, resultListPtr, eachTraceObjPtr); } Tcl_SetObjResult(interp, resultListPtr); break; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TraceVariableObjCmd -- * * Helper function for Tcl_TraceObjCmd; implements the [trace * {add|info|remove} variable ...] subcommands. See the user * documentation for details on what these do. * * Results: * Standard Tcl result. * * Side effects: * Depends on the operation (add, remove, or info) being performed; may * add or remove variable traces on a variable. * *---------------------------------------------------------------------- */ static int TraceVariableObjCmd( Tcl_Interp *interp, /* Current interpreter. */ int optionIndex, /* Add, info or remove */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int commandLength, index; const char *name, *command; size_t length; ClientData clientData; enum traceOptions { TRACE_ADD, TRACE_INFO, TRACE_REMOVE }; static const char *const opStrings[] = { "array", "read", "unset", "write", NULL }; enum operations { TRACE_VAR_ARRAY, TRACE_VAR_READ, TRACE_VAR_UNSET, TRACE_VAR_WRITE }; switch ((enum traceOptions) optionIndex) { case TRACE_ADD: case TRACE_REMOVE: { int flags = 0; int i, listLen, result; Tcl_Obj **elemPtrs; if (objc != 6) { Tcl_WrongNumArgs(interp, 3, objv, "name opList command"); return TCL_ERROR; } /* * Make sure the ops argument is a list object; get its length and a * pointer to its array of element pointers. */ result = Tcl_ListObjGetElements(interp, objv[4], &listLen, &elemPtrs); if (result != TCL_OK) { return result; } if (listLen == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad operation list \"\": must be one or more of" " array, read, unset, or write", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "TRACE", "NOOPS", NULL); return TCL_ERROR; } for (i = 0; i < listLen ; i++) { if (Tcl_GetIndexFromObj(interp, elemPtrs[i], opStrings, "operation", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum operations) index) { case TRACE_VAR_ARRAY: flags |= TCL_TRACE_ARRAY; break; case TRACE_VAR_READ: flags |= TCL_TRACE_READS; break; case TRACE_VAR_UNSET: flags |= TCL_TRACE_UNSETS; break; case TRACE_VAR_WRITE: flags |= TCL_TRACE_WRITES; break; } } command = Tcl_GetStringFromObj(objv[5], &commandLength); length = (size_t) commandLength; if ((enum traceOptions) optionIndex == TRACE_ADD) { CombinedTraceVarInfo *ctvarPtr = ckalloc( TclOffset(CombinedTraceVarInfo, traceCmdInfo.command) + 1 + length); ctvarPtr->traceCmdInfo.flags = flags; if (objv[0] == NULL) { ctvarPtr->traceCmdInfo.flags |= TCL_TRACE_OLD_STYLE; } ctvarPtr->traceCmdInfo.length = length; flags |= TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT; memcpy(ctvarPtr->traceCmdInfo.command, command, length+1); ctvarPtr->traceInfo.traceProc = TraceVarProc; ctvarPtr->traceInfo.clientData = &ctvarPtr->traceCmdInfo; ctvarPtr->traceInfo.flags = flags; name = Tcl_GetString(objv[3]); if (TraceVarEx(interp, name, NULL, (VarTrace *) ctvarPtr) != TCL_OK) { ckfree(ctvarPtr); return TCL_ERROR; } } else { /* * Search through all of our traces on this variable to see if * there's one with the given command. If so, then delete the * first one that matches. */ name = Tcl_GetString(objv[3]); FOREACH_VAR_TRACE(interp, name, clientData) { TraceVarInfo *tvarPtr = clientData; if ((tvarPtr->length == length) && ((tvarPtr->flags & ~TCL_TRACE_OLD_STYLE)==flags) && (strncmp(command, tvarPtr->command, (size_t) length) == 0)) { Tcl_UntraceVar2(interp, name, NULL, flags | TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT, TraceVarProc, clientData); break; } } } break; } case TRACE_INFO: { Tcl_Obj *resultListPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 3, objv, "name"); return TCL_ERROR; } resultListPtr = Tcl_NewObj(); name = Tcl_GetString(objv[3]); FOREACH_VAR_TRACE(interp, name, clientData) { Tcl_Obj *opObjPtr, *eachTraceObjPtr, *elemObjPtr; TraceVarInfo *tvarPtr = clientData; /* * Build a list with the ops list as the first obj element and the * tcmdPtr->command string as the second obj element. Append this * list (as an element) to the end of the result object list. */ elemObjPtr = Tcl_NewListObj(0, NULL); if (tvarPtr->flags & TCL_TRACE_ARRAY) { TclNewLiteralStringObj(opObjPtr, "array"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObjPtr); } if (tvarPtr->flags & TCL_TRACE_READS) { TclNewLiteralStringObj(opObjPtr, "read"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObjPtr); } if (tvarPtr->flags & TCL_TRACE_WRITES) { TclNewLiteralStringObj(opObjPtr, "write"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObjPtr); } if (tvarPtr->flags & TCL_TRACE_UNSETS) { TclNewLiteralStringObj(opObjPtr, "unset"); Tcl_ListObjAppendElement(NULL, elemObjPtr, opObjPtr); } eachTraceObjPtr = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr); elemObjPtr = Tcl_NewStringObj(tvarPtr->command, -1); Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr); Tcl_ListObjAppendElement(interp, resultListPtr, eachTraceObjPtr); } Tcl_SetObjResult(interp, resultListPtr); break; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_CommandTraceInfo -- * * Return the clientData value associated with a trace on a command. * This function can also be used to step through all of the traces on a * particular command that have the same trace function. * * Results: * The return value is the clientData value associated with a trace on * the given command. Information will only be returned for a trace with * proc as trace function. If the clientData argument is NULL then the * first such trace is returned; otherwise, the next relevant one after * the one given by clientData will be returned. If the command doesn't * exist then an error message is left in the interpreter and NULL is * returned. Also, if there are no (more) traces for the given command, * NULL is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ ClientData Tcl_CommandTraceInfo( Tcl_Interp *interp, /* Interpreter containing command. */ const char *cmdName, /* Name of command. */ int flags, /* OR-ed combo or TCL_GLOBAL_ONLY, * TCL_NAMESPACE_ONLY (can be 0). */ Tcl_CommandTraceProc *proc, /* Function assocated with trace. */ ClientData prevClientData) /* If non-NULL, gives last value returned by * this function, so this call will return the * next trace after that one. If NULL, this * call will return the first trace. */ { Command *cmdPtr; register CommandTrace *tracePtr; cmdPtr = (Command *) Tcl_FindCommand(interp, cmdName, NULL, TCL_LEAVE_ERR_MSG); if (cmdPtr == NULL) { return NULL; } /* * Find the relevant trace, if any, and return its clientData. */ tracePtr = cmdPtr->tracePtr; if (prevClientData != NULL) { for (; tracePtr!=NULL ; tracePtr=tracePtr->nextPtr) { if ((tracePtr->clientData == prevClientData) && (tracePtr->traceProc == proc)) { tracePtr = tracePtr->nextPtr; break; } } } for (; tracePtr!=NULL ; tracePtr=tracePtr->nextPtr) { if (tracePtr->traceProc == proc) { return tracePtr->clientData; } } return NULL; } /* *---------------------------------------------------------------------- * * Tcl_TraceCommand -- * * Arrange for rename/deletes to a command to cause a function to be * invoked, which can monitor the operations. * * Also optionally arrange for execution of that command to cause a * function to be invoked. * * Results: * A standard Tcl return value. * * Side effects: * A trace is set up on the command given by cmdName, such that future * changes to the command will be intermediated by proc. See the manual * entry for complete details on the calling sequence for proc. * *---------------------------------------------------------------------- */ int Tcl_TraceCommand( Tcl_Interp *interp, /* Interpreter in which command is to be * traced. */ const char *cmdName, /* Name of command. */ int flags, /* OR-ed collection of bits, including any of * TCL_TRACE_RENAME, TCL_TRACE_DELETE, and any * of the TRACE_*_EXEC flags */ Tcl_CommandTraceProc *proc, /* Function to call when specified ops are * invoked upon cmdName. */ ClientData clientData) /* Arbitrary argument to pass to proc. */ { Command *cmdPtr; register CommandTrace *tracePtr; cmdPtr = (Command *) Tcl_FindCommand(interp, cmdName, NULL, TCL_LEAVE_ERR_MSG); if (cmdPtr == NULL) { return TCL_ERROR; } /* * Set up trace information. */ tracePtr = ckalloc(sizeof(CommandTrace)); tracePtr->traceProc = proc; tracePtr->clientData = clientData; tracePtr->flags = flags & (TCL_TRACE_RENAME | TCL_TRACE_DELETE | TCL_TRACE_ANY_EXEC); tracePtr->nextPtr = cmdPtr->tracePtr; tracePtr->refCount = 1; cmdPtr->tracePtr = tracePtr; if (tracePtr->flags & TCL_TRACE_ANY_EXEC) { /* * Bug 3484621: up the interp's epoch if this is a BC'ed command */ if ((cmdPtr->compileProc != NULL) && !(cmdPtr->flags & CMD_HAS_EXEC_TRACES)){ Interp *iPtr = (Interp *) interp; iPtr->compileEpoch++; } cmdPtr->flags |= CMD_HAS_EXEC_TRACES; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_UntraceCommand -- * * Remove a previously-created trace for a command. * * Results: * None. * * Side effects: * If there exists a trace for the command given by cmdName with the * given flags, proc, and clientData, then that trace is removed. * *---------------------------------------------------------------------- */ void Tcl_UntraceCommand( Tcl_Interp *interp, /* Interpreter containing command. */ const char *cmdName, /* Name of command. */ int flags, /* OR-ed collection of bits, including any of * TCL_TRACE_RENAME, TCL_TRACE_DELETE, and any * of the TRACE_*_EXEC flags */ Tcl_CommandTraceProc *proc, /* Function assocated with trace. */ ClientData clientData) /* Arbitrary argument to pass to proc. */ { register CommandTrace *tracePtr; CommandTrace *prevPtr; Command *cmdPtr; Interp *iPtr = (Interp *) interp; ActiveCommandTrace *activePtr; int hasExecTraces = 0; cmdPtr = (Command *) Tcl_FindCommand(interp, cmdName, NULL, TCL_LEAVE_ERR_MSG); if (cmdPtr == NULL) { return; } flags &= (TCL_TRACE_RENAME | TCL_TRACE_DELETE | TCL_TRACE_ANY_EXEC); for (tracePtr = cmdPtr->tracePtr, prevPtr = NULL; ; prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) { if (tracePtr == NULL) { return; } if ((tracePtr->traceProc == proc) && ((tracePtr->flags & (TCL_TRACE_RENAME | TCL_TRACE_DELETE | TCL_TRACE_ANY_EXEC)) == flags) && (tracePtr->clientData == clientData)) { if (tracePtr->flags & TCL_TRACE_ANY_EXEC) { hasExecTraces = 1; } break; } } /* * The code below makes it possible to delete traces while traces are * active: it makes sure that the deleted trace won't be processed by * CallCommandTraces. */ for (activePtr = iPtr->activeCmdTracePtr; activePtr != NULL; activePtr = activePtr->nextPtr) { if (activePtr->nextTracePtr == tracePtr) { if (activePtr->reverseScan) { activePtr->nextTracePtr = prevPtr; } else { activePtr->nextTracePtr = tracePtr->nextPtr; } } } if (prevPtr == NULL) { cmdPtr->tracePtr = tracePtr->nextPtr; } else { prevPtr->nextPtr = tracePtr->nextPtr; } tracePtr->flags = 0; if (tracePtr->refCount-- <= 1) { ckfree(tracePtr); } if (hasExecTraces) { for (tracePtr = cmdPtr->tracePtr, prevPtr = NULL; tracePtr != NULL ; prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) { if (tracePtr->flags & TCL_TRACE_ANY_EXEC) { return; } } /* * None of the remaining traces on this command are execution traces. * We therefore remove this flag: */ cmdPtr->flags &= ~CMD_HAS_EXEC_TRACES; /* * Bug 3484621: up the interp's epoch if this is a BC'ed command */ if (cmdPtr->compileProc != NULL) { Interp *iPtr = (Interp *) interp; iPtr->compileEpoch++; } } } /* *---------------------------------------------------------------------- * * TraceCommandProc -- * * This function is called to handle command changes that have been * traced using the "trace" command, when using the 'rename' or 'delete' * options. * * Results: * None. * * Side effects: * Depends on the command associated with the trace. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static void TraceCommandProc( ClientData clientData, /* Information about the command trace. */ Tcl_Interp *interp, /* Interpreter containing command. */ const char *oldName, /* Name of command being changed. */ const char *newName, /* New name of command. Empty string or NULL * means command is being deleted (renamed to * ""). */ int flags) /* OR-ed bits giving operation and other * information. */ { TraceCommandInfo *tcmdPtr = clientData; int code; Tcl_DString cmd; tcmdPtr->refCount++; if ((tcmdPtr->flags & flags) && !Tcl_InterpDeleted(interp) && !Tcl_LimitExceeded(interp)) { /* * Generate a command to execute by appending list elements for the * old and new command name and the operation. */ Tcl_DStringInit(&cmd); Tcl_DStringAppend(&cmd, tcmdPtr->command, (int) tcmdPtr->length); Tcl_DStringAppendElement(&cmd, oldName); Tcl_DStringAppendElement(&cmd, (newName ? newName : "")); if (flags & TCL_TRACE_RENAME) { TclDStringAppendLiteral(&cmd, " rename"); } else if (flags & TCL_TRACE_DELETE) { TclDStringAppendLiteral(&cmd, " delete"); } /* * Execute the command. We discard any object result the command * returns. * * Add the TCL_TRACE_DESTROYED flag to tcmdPtr to indicate to other * areas that this will be destroyed by us, otherwise a double-free * might occur depending on what the eval does. */ if (flags & TCL_TRACE_DESTROYED) { tcmdPtr->flags |= TCL_TRACE_DESTROYED; } code = Tcl_EvalEx(interp, Tcl_DStringValue(&cmd), Tcl_DStringLength(&cmd), 0); if (code != TCL_OK) { /* We ignore errors in these traced commands */ /*** QUESTION: Use Tcl_BackgroundException(interp, code); instead? ***/ } Tcl_DStringFree(&cmd); } /* * We delete when the trace was destroyed or if this is a delete trace, * because command deletes are unconditional, so the trace must go away. */ if (flags & (TCL_TRACE_DESTROYED | TCL_TRACE_DELETE)) { int untraceFlags = tcmdPtr->flags; Tcl_InterpState state; if (tcmdPtr->stepTrace != NULL) { Tcl_DeleteTrace(interp, tcmdPtr->stepTrace); tcmdPtr->stepTrace = NULL; if (tcmdPtr->startCmd != NULL) { ckfree(tcmdPtr->startCmd); } } if (tcmdPtr->flags & TCL_TRACE_EXEC_IN_PROGRESS) { /* * Postpone deletion, until exec trace returns. */ tcmdPtr->flags = 0; } /* * We need to construct the same flags for Tcl_UntraceCommand as were * passed to Tcl_TraceCommand. Reproduce the processing of [trace add * execution/command]. Be careful to keep this code in sync with that. */ if (untraceFlags & TCL_TRACE_ANY_EXEC) { untraceFlags |= TCL_TRACE_DELETE; if (untraceFlags & (TCL_TRACE_ENTER_DURING_EXEC | TCL_TRACE_LEAVE_DURING_EXEC)) { untraceFlags |= (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC); } } else if (untraceFlags & TCL_TRACE_RENAME) { untraceFlags |= TCL_TRACE_DELETE; } /* * Remove the trace since TCL_TRACE_DESTROYED tells us to, or the * command we're tracing has just gone away. Then decrement the * clientData refCount that was set up by trace creation. * * Note that we save the (return) state of the interpreter to prevent * bizarre error messages. */ state = Tcl_SaveInterpState(interp, TCL_OK); Tcl_UntraceCommand(interp, oldName, untraceFlags, TraceCommandProc, clientData); Tcl_RestoreInterpState(interp, state); tcmdPtr->refCount--; } if (tcmdPtr->refCount-- <= 1) { ckfree(tcmdPtr); } } /* *---------------------------------------------------------------------- * * TclCheckExecutionTraces -- * * Checks on all current command execution traces, and invokes functions * which have been registered. This function can be used by other code * which performs execution to unify the tracing system, so that * execution traces will function for that other code. * * For instance extensions like [incr Tcl] which use their own execution * technique can make use of Tcl's tracing. * * This function is called by 'TclEvalObjvInternal' * * Results: * The return value is a standard Tcl completion code such as TCL_OK or * TCL_ERROR, etc. * * Side effects: * Those side effects made by any trace functions called. * *---------------------------------------------------------------------- */ int TclCheckExecutionTraces( Tcl_Interp *interp, /* The current interpreter. */ const char *command, /* Pointer to beginning of the current command * string. */ int numChars, /* The number of characters in 'command' which * are part of the command string. */ Command *cmdPtr, /* Points to command's Command struct. */ int code, /* The current result code. */ int traceFlags, /* Current tracing situation. */ int objc, /* Number of arguments for the command. */ Tcl_Obj *const objv[]) /* Pointers to Tcl_Obj of each argument. */ { Interp *iPtr = (Interp *) interp; CommandTrace *tracePtr, *lastTracePtr; ActiveCommandTrace active; int curLevel; int traceCode = TCL_OK; Tcl_InterpState state = NULL; if (cmdPtr->tracePtr == NULL) { return traceCode; } curLevel = iPtr->varFramePtr->level; active.nextPtr = iPtr->activeCmdTracePtr; iPtr->activeCmdTracePtr = &active; active.cmdPtr = cmdPtr; lastTracePtr = NULL; for (tracePtr = cmdPtr->tracePtr; (traceCode == TCL_OK) && (tracePtr != NULL); tracePtr = active.nextTracePtr) { if (traceFlags & TCL_TRACE_LEAVE_EXEC) { /* * Execute the trace command in order of creation for "leave". */ active.reverseScan = 1; active.nextTracePtr = NULL; tracePtr = cmdPtr->tracePtr; while (tracePtr->nextPtr != lastTracePtr) { active.nextTracePtr = tracePtr; tracePtr = tracePtr->nextPtr; } } else { active.reverseScan = 0; active.nextTracePtr = tracePtr->nextPtr; } if (tracePtr->traceProc == TraceCommandProc) { TraceCommandInfo *tcmdPtr = tracePtr->clientData; if (tcmdPtr->flags != 0) { tcmdPtr->curFlags = traceFlags | TCL_TRACE_EXEC_DIRECT; tcmdPtr->curCode = code; tcmdPtr->refCount++; if (state == NULL) { state = Tcl_SaveInterpState(interp, code); } traceCode = TraceExecutionProc(tcmdPtr, interp, curLevel, command, (Tcl_Command) cmdPtr, objc, objv); if (tcmdPtr->refCount-- <= 1) { ckfree(tcmdPtr); } } } if (active.nextTracePtr) { lastTracePtr = active.nextTracePtr->nextPtr; } } iPtr->activeCmdTracePtr = active.nextPtr; if (state) { if (traceCode == TCL_OK) { (void) Tcl_RestoreInterpState(interp, state); } else { Tcl_DiscardInterpState(state); } } return traceCode; } /* *---------------------------------------------------------------------- * * TclCheckInterpTraces -- * * Checks on all current traces, and invokes functions which have been * registered. This function can be used by other code which performs * execution to unify the tracing system. For instance extensions like * [incr Tcl] which use their own execution technique can make use of * Tcl's tracing. * * This function is called by 'TclEvalObjvInternal' * * Results: * The return value is a standard Tcl completion code such as TCL_OK or * TCL_ERROR, etc. * * Side effects: * Those side effects made by any trace functions called. * *---------------------------------------------------------------------- */ int TclCheckInterpTraces( Tcl_Interp *interp, /* The current interpreter. */ const char *command, /* Pointer to beginning of the current command * string. */ int numChars, /* The number of characters in 'command' which * are part of the command string. */ Command *cmdPtr, /* Points to command's Command struct. */ int code, /* The current result code. */ int traceFlags, /* Current tracing situation. */ int objc, /* Number of arguments for the command. */ Tcl_Obj *const objv[]) /* Pointers to Tcl_Obj of each argument. */ { Interp *iPtr = (Interp *) interp; Trace *tracePtr, *lastTracePtr; ActiveInterpTrace active; int curLevel; int traceCode = TCL_OK; Tcl_InterpState state = NULL; if ((iPtr->tracePtr == NULL) || (iPtr->flags & INTERP_TRACE_IN_PROGRESS)) { return(traceCode); } curLevel = iPtr->numLevels; active.nextPtr = iPtr->activeInterpTracePtr; iPtr->activeInterpTracePtr = &active; lastTracePtr = NULL; for (tracePtr = iPtr->tracePtr; (traceCode == TCL_OK) && (tracePtr != NULL); tracePtr = active.nextTracePtr) { if (traceFlags & TCL_TRACE_ENTER_EXEC) { /* * Execute the trace command in reverse order of creation for * "enterstep" operation. The order is changed for "enterstep" * instead of for "leavestep" as was done in * TclCheckExecutionTraces because for step traces, * Tcl_CreateObjTrace creates one more linked list of traces which * results in one more reversal of trace invocation. */ active.reverseScan = 1; active.nextTracePtr = NULL; tracePtr = iPtr->tracePtr; while (tracePtr->nextPtr != lastTracePtr) { active.nextTracePtr = tracePtr; tracePtr = tracePtr->nextPtr; } if (active.nextTracePtr) { lastTracePtr = active.nextTracePtr->nextPtr; } } else { active.reverseScan = 0; active.nextTracePtr = tracePtr->nextPtr; } if (tracePtr->level > 0 && curLevel > tracePtr->level) { continue; } if (!(tracePtr->flags & TCL_TRACE_EXEC_IN_PROGRESS)) { /* * The proc invoked might delete the traced command which which * might try to free tracePtr. We want to use tracePtr until the * end of this if section, so we use Tcl_Preserve() and * Tcl_Release() to be sure it is not freed while we still need * it. */ Tcl_Preserve(tracePtr); tracePtr->flags |= TCL_TRACE_EXEC_IN_PROGRESS; if (state == NULL) { state = Tcl_SaveInterpState(interp, code); } if (tracePtr->flags & (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC)) { /* * New style trace. */ if (tracePtr->flags & traceFlags) { if (tracePtr->proc == TraceExecutionProc) { TraceCommandInfo *tcmdPtr = tracePtr->clientData; tcmdPtr->curFlags = traceFlags; tcmdPtr->curCode = code; } traceCode = tracePtr->proc(tracePtr->clientData, interp, curLevel, command, (Tcl_Command) cmdPtr, objc, objv); } } else { /* * Old-style trace. */ if (traceFlags & TCL_TRACE_ENTER_EXEC) { /* * Old-style interpreter-wide traces only trigger before * the command is executed. */ traceCode = CallTraceFunction(interp, tracePtr, cmdPtr, command, numChars, objc, objv); } } tracePtr->flags &= ~TCL_TRACE_EXEC_IN_PROGRESS; Tcl_Release(tracePtr); } } iPtr->activeInterpTracePtr = active.nextPtr; if (state) { if (traceCode == TCL_OK) { Tcl_RestoreInterpState(interp, state); } else { Tcl_DiscardInterpState(state); } } return traceCode; } /* *---------------------------------------------------------------------- * * CallTraceFunction -- * * Invokes a trace function registered with an interpreter. These * functions trace command execution. Currently this trace function is * called with the address of the string-based Tcl_CmdProc for the * command, not the Tcl_ObjCmdProc. * * Results: * None. * * Side effects: * Those side effects made by the trace function. * *---------------------------------------------------------------------- */ static int CallTraceFunction( Tcl_Interp *interp, /* The current interpreter. */ register Trace *tracePtr, /* Describes the trace function to call. */ Command *cmdPtr, /* Points to command's Command struct. */ const char *command, /* Points to the first character of the * command's source before substitutions. */ int numChars, /* The number of characters in the command's * source. */ register int objc, /* Number of arguments for the command. */ Tcl_Obj *const objv[]) /* Pointers to Tcl_Obj of each argument. */ { Interp *iPtr = (Interp *) interp; char *commandCopy; int traceCode; /* * Copy the command characters into a new string. */ commandCopy = TclStackAlloc(interp, (unsigned) numChars + 1); memcpy(commandCopy, command, (size_t) numChars); commandCopy[numChars] = '\0'; /* * Call the trace function then free allocated storage. */ traceCode = tracePtr->proc(tracePtr->clientData, (Tcl_Interp *) iPtr, iPtr->numLevels, commandCopy, (Tcl_Command) cmdPtr, objc, objv); TclStackFree(interp, commandCopy); return traceCode; } /* *---------------------------------------------------------------------- * * CommandObjTraceDeleted -- * * Ensure the trace is correctly deleted by decrementing its refCount and * only deleting if no other references exist. * * Results: * None. * * Side effects: * May release memory. * *---------------------------------------------------------------------- */ static void CommandObjTraceDeleted( ClientData clientData) { TraceCommandInfo *tcmdPtr = clientData; if (tcmdPtr->refCount-- <= 1) { ckfree(tcmdPtr); } } /* *---------------------------------------------------------------------- * * TraceExecutionProc -- * * This function is invoked whenever code relevant to a 'trace execution' * command is executed. It is called in one of two ways in Tcl's core: * * (i) by the TclCheckExecutionTraces, when an execution trace has been * triggered. * (ii) by TclCheckInterpTraces, when a prior execution trace has created * a trace of the internals of a procedure, passing in this function as * the one to be called. * * Results: * The return value is a standard Tcl completion code such as TCL_OK or * TCL_ERROR, etc. * * Side effects: * May invoke an arbitrary Tcl procedure, and may create or delete an * interpreter-wide trace. * *---------------------------------------------------------------------- */ static int TraceExecutionProc( ClientData clientData, Tcl_Interp *interp, int level, const char *command, Tcl_Command cmdInfo, int objc, struct Tcl_Obj *const objv[]) { int call = 0; Interp *iPtr = (Interp *) interp; TraceCommandInfo *tcmdPtr = clientData; int flags = tcmdPtr->curFlags; int code = tcmdPtr->curCode; int traceCode = TCL_OK; if (tcmdPtr->flags & TCL_TRACE_EXEC_IN_PROGRESS) { /* * Inside any kind of execution trace callback, we do not allow any * further execution trace callbacks to be called for the same trace. */ return traceCode; } if (!Tcl_InterpDeleted(interp) && !Tcl_LimitExceeded(interp)) { /* * Check whether the current call is going to eval arbitrary Tcl code * with a generated trace, or whether we are only going to setup * interpreter-wide traces to implement the 'step' traces. This latter * situation can happen if we create a command trace without either * before or after operations, but with either of the step operations. */ if (flags & TCL_TRACE_EXEC_DIRECT) { call = flags & tcmdPtr->flags & (TCL_TRACE_ENTER_EXEC | TCL_TRACE_LEAVE_EXEC); } else { call = 1; } /* * First, if we have returned back to the level at which we created an * interpreter trace for enterstep and/or leavestep execution traces, * we remove it here. */ if ((flags & TCL_TRACE_LEAVE_EXEC) && (tcmdPtr->stepTrace != NULL) && (level == tcmdPtr->startLevel) && (strcmp(command, tcmdPtr->startCmd) == 0)) { Tcl_DeleteTrace(interp, tcmdPtr->stepTrace); tcmdPtr->stepTrace = NULL; if (tcmdPtr->startCmd != NULL) { ckfree(tcmdPtr->startCmd); } } /* * Second, create the tcl callback, if required. */ if (call) { Tcl_DString cmd, sub; int i, saveInterpFlags; Tcl_DStringInit(&cmd); Tcl_DStringAppend(&cmd, tcmdPtr->command, (int)tcmdPtr->length); /* * Append command with arguments. */ Tcl_DStringInit(&sub); for (i = 0; i < objc; i++) { Tcl_DStringAppendElement(&sub, Tcl_GetString(objv[i])); } Tcl_DStringAppendElement(&cmd, Tcl_DStringValue(&sub)); Tcl_DStringFree(&sub); if (flags & TCL_TRACE_ENTER_EXEC) { /* * Append trace operation. */ if (flags & TCL_TRACE_EXEC_DIRECT) { Tcl_DStringAppendElement(&cmd, "enter"); } else { Tcl_DStringAppendElement(&cmd, "enterstep"); } } else if (flags & TCL_TRACE_LEAVE_EXEC) { Tcl_Obj *resultCode; const char *resultCodeStr; /* * Append result code. */ resultCode = Tcl_NewIntObj(code); resultCodeStr = Tcl_GetString(resultCode); Tcl_DStringAppendElement(&cmd, resultCodeStr); Tcl_DecrRefCount(resultCode); /* * Append result string. */ Tcl_DStringAppendElement(&cmd, Tcl_GetStringResult(interp)); /* * Append trace operation. */ if (flags & TCL_TRACE_EXEC_DIRECT) { Tcl_DStringAppendElement(&cmd, "leave"); } else { Tcl_DStringAppendElement(&cmd, "leavestep"); } } else { Tcl_Panic("TraceExecutionProc: bad flag combination"); } /* * Execute the command. We discard any object result the command * returns. */ saveInterpFlags = iPtr->flags; iPtr->flags |= INTERP_TRACE_IN_PROGRESS; tcmdPtr->flags |= TCL_TRACE_EXEC_IN_PROGRESS; tcmdPtr->refCount++; /* * This line can have quite arbitrary side-effects, including * deleting the trace, the command being traced, or even the * interpreter. */ traceCode = Tcl_EvalEx(interp, Tcl_DStringValue(&cmd), Tcl_DStringLength(&cmd), 0); tcmdPtr->flags &= ~TCL_TRACE_EXEC_IN_PROGRESS; /* * Restore the interp tracing flag to prevent cmd traces from * affecting interp traces. */ iPtr->flags = saveInterpFlags; if (tcmdPtr->flags == 0) { flags |= TCL_TRACE_DESTROYED; } Tcl_DStringFree(&cmd); } /* * Third, if there are any step execution traces for this proc, we * register an interpreter trace to invoke enterstep and/or leavestep * traces. We also need to save the current stack level and the proc * string in startLevel and startCmd so that we can delete this * interpreter trace when it reaches the end of this proc. */ if ((flags & TCL_TRACE_ENTER_EXEC) && (tcmdPtr->stepTrace == NULL) && (tcmdPtr->flags & (TCL_TRACE_ENTER_DURING_EXEC | TCL_TRACE_LEAVE_DURING_EXEC))) { register unsigned len = strlen(command) + 1; tcmdPtr->startLevel = level; tcmdPtr->startCmd = ckalloc(len); memcpy(tcmdPtr->startCmd, command, len); tcmdPtr->refCount++; tcmdPtr->stepTrace = Tcl_CreateObjTrace(interp, 0, (tcmdPtr->flags & TCL_TRACE_ANY_EXEC) >> 2, TraceExecutionProc, tcmdPtr, CommandObjTraceDeleted); } } if (flags & TCL_TRACE_DESTROYED) { if (tcmdPtr->stepTrace != NULL) { Tcl_DeleteTrace(interp, tcmdPtr->stepTrace); tcmdPtr->stepTrace = NULL; if (tcmdPtr->startCmd != NULL) { ckfree(tcmdPtr->startCmd); } } } if (call) { if (tcmdPtr->refCount-- <= 1) { ckfree(tcmdPtr); } } return traceCode; } /* *---------------------------------------------------------------------- * * TraceVarProc -- * * This function is called to handle variable accesses that have been * traced using the "trace" command. * * Results: * Normally returns NULL. If the trace command returns an error, then * this function returns an error string. * * Side effects: * Depends on the command associated with the trace. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static char * TraceVarProc( ClientData clientData, /* Information about the variable trace. */ Tcl_Interp *interp, /* Interpreter containing variable. */ const char *name1, /* Name of variable or array. */ const char *name2, /* Name of element within array; NULL means * scalar variable is being referenced. */ int flags) /* OR-ed bits giving operation and other * information. */ { TraceVarInfo *tvarPtr = clientData; char *result; int code, destroy = 0; Tcl_DString cmd; int rewind = ((Interp *)interp)->execEnvPtr->rewind; /* * We might call Tcl_Eval() below, and that might evaluate [trace vdelete] * which might try to free tvarPtr. We want to use tvarPtr until the end * of this function, so we use Tcl_Preserve() and Tcl_Release() to be sure * it is not freed while we still need it. */ result = NULL; if ((tvarPtr->flags & flags) && !Tcl_InterpDeleted(interp) && !Tcl_LimitExceeded(interp)) { if (tvarPtr->length != (size_t) 0) { /* * Generate a command to execute by appending list elements for * the two variable names and the operation. */ Tcl_DStringInit(&cmd); Tcl_DStringAppend(&cmd, tvarPtr->command, (int) tvarPtr->length); Tcl_DStringAppendElement(&cmd, name1); Tcl_DStringAppendElement(&cmd, (name2 ? name2 : "")); #ifndef TCL_REMOVE_OBSOLETE_TRACES if (tvarPtr->flags & TCL_TRACE_OLD_STYLE) { if (flags & TCL_TRACE_ARRAY) { TclDStringAppendLiteral(&cmd, " a"); } else if (flags & TCL_TRACE_READS) { TclDStringAppendLiteral(&cmd, " r"); } else if (flags & TCL_TRACE_WRITES) { TclDStringAppendLiteral(&cmd, " w"); } else if (flags & TCL_TRACE_UNSETS) { TclDStringAppendLiteral(&cmd, " u"); } } else { #endif if (flags & TCL_TRACE_ARRAY) { TclDStringAppendLiteral(&cmd, " array"); } else if (flags & TCL_TRACE_READS) { TclDStringAppendLiteral(&cmd, " read"); } else if (flags & TCL_TRACE_WRITES) { TclDStringAppendLiteral(&cmd, " write"); } else if (flags & TCL_TRACE_UNSETS) { TclDStringAppendLiteral(&cmd, " unset"); } #ifndef TCL_REMOVE_OBSOLETE_TRACES } #endif /* * Execute the command. We discard any object result the command * returns. * * Add the TCL_TRACE_DESTROYED flag to tvarPtr to indicate to * other areas that this will be destroyed by us, otherwise a * double-free might occur depending on what the eval does. */ if ((flags & TCL_TRACE_DESTROYED) && !(tvarPtr->flags & TCL_TRACE_DESTROYED)) { destroy = 1; tvarPtr->flags |= TCL_TRACE_DESTROYED; } /* * Make sure that unset traces are rune even if the execEnv is * rewinding (coroutine deletion, [Bug 2093947] */ if (rewind && (flags & TCL_TRACE_UNSETS)) { ((Interp *)interp)->execEnvPtr->rewind = 0; } code = Tcl_EvalEx(interp, Tcl_DStringValue(&cmd), Tcl_DStringLength(&cmd), 0); if (rewind) { ((Interp *)interp)->execEnvPtr->rewind = rewind; } if (code != TCL_OK) { /* copy error msg to result */ Tcl_Obj *errMsgObj = Tcl_GetObjResult(interp); Tcl_IncrRefCount(errMsgObj); result = (char *) errMsgObj; } Tcl_DStringFree(&cmd); } } if (destroy && result != NULL) { register Tcl_Obj *errMsgObj = (Tcl_Obj *) result; Tcl_DecrRefCount(errMsgObj); result = NULL; } return result; } /* *---------------------------------------------------------------------- * * Tcl_CreateObjTrace -- * * Arrange for a function to be called to trace command execution. * * Results: * The return value is a token for the trace, which may be passed to * Tcl_DeleteTrace to eliminate the trace. * * Side effects: * From now on, proc will be called just before a command function is * called to execute a Tcl command. Calls to proc will have the following * form: * * void proc(ClientData clientData, * Tcl_Interp * interp, * int level, * const char * command, * Tcl_Command commandInfo, * int objc, * Tcl_Obj *const objv[]); * * The 'clientData' and 'interp' arguments to 'proc' will be the same as * the arguments to Tcl_CreateObjTrace. The 'level' argument gives the * nesting depth of command interpretation within the interpreter. The * 'command' argument is the ASCII text of the command being evaluated - * before any substitutions are performed. The 'commandInfo' argument * gives a handle to the command procedure that will be evaluated. The * 'objc' and 'objv' parameters give the parameter vector that will be * passed to the command procedure. Proc does not return a value. * * It is permissible for 'proc' to call Tcl_SetCommandTokenInfo to change * the command procedure or client data for the command being evaluated, * and these changes will take effect with the current evaluation. * * The 'level' argument specifies the maximum nesting level of calls to * be traced. If the execution depth of the interpreter exceeds 'level', * the trace callback is not executed. * * The 'flags' argument is either zero or the value, * TCL_ALLOW_INLINE_COMPILATION. If the TCL_ALLOW_INLINE_COMPILATION flag * is not present, the bytecode compiler will not generate inline code * for Tcl's built-in commands. This behavior will have a significant * impact on performance, but will ensure that all command evaluations * are traced. If the TCL_ALLOW_INLINE_COMPILATION flag is present, the * bytecode compiler will have its normal behavior of compiling in-line * code for some of Tcl's built-in commands. In this case, the tracing * will be imprecise - in-line code will not be traced - but run-time * performance will be improved. The latter behavior is desired for many * applications such as profiling of run time. * * When the trace is deleted, the 'delProc' function will be invoked, * passing it the original client data. * *---------------------------------------------------------------------- */ Tcl_Trace Tcl_CreateObjTrace( Tcl_Interp *interp, /* Tcl interpreter */ int level, /* Maximum nesting level */ int flags, /* Flags, see above */ Tcl_CmdObjTraceProc *proc, /* Trace callback */ ClientData clientData, /* Client data for the callback */ Tcl_CmdObjTraceDeleteProc *delProc) /* Function to call when trace is deleted */ { register Trace *tracePtr; register Interp *iPtr = (Interp *) interp; /* * Test if this trace allows inline compilation of commands. */ if (!(flags & TCL_ALLOW_INLINE_COMPILATION)) { if (iPtr->tracesForbiddingInline == 0) { /* * When the first trace forbidding inline compilation is created, * invalidate existing compiled code for this interpreter and * arrange (by setting the DONT_COMPILE_CMDS_INLINE flag) that * when compiling new code, no commands will be compiled inline * (i.e., into an inline sequence of instructions). We do this * because commands that were compiled inline will never result in * a command trace being called. */ iPtr->compileEpoch++; iPtr->flags |= DONT_COMPILE_CMDS_INLINE; } iPtr->tracesForbiddingInline++; } tracePtr = ckalloc(sizeof(Trace)); tracePtr->level = level; tracePtr->proc = proc; tracePtr->clientData = clientData; tracePtr->delProc = delProc; tracePtr->nextPtr = iPtr->tracePtr; tracePtr->flags = flags; iPtr->tracePtr = tracePtr; return (Tcl_Trace) tracePtr; } /* *---------------------------------------------------------------------- * * Tcl_CreateTrace -- * * Arrange for a function to be called to trace command execution. * * Results: * The return value is a token for the trace, which may be passed to * Tcl_DeleteTrace to eliminate the trace. * * Side effects: * From now on, proc will be called just before a command procedure is * called to execute a Tcl command. Calls to proc will have the following * form: * * void * proc(clientData, interp, level, command, cmdProc, cmdClientData, * argc, argv) * ClientData clientData; * Tcl_Interp *interp; * int level; * char *command; * int (*cmdProc)(); * ClientData cmdClientData; * int argc; * char **argv; * { * } * * The clientData and interp arguments to proc will be the same as the * corresponding arguments to this function. Level gives the nesting * level of command interpretation for this interpreter (0 corresponds to * top level). Command gives the ASCII text of the raw command, cmdProc * and cmdClientData give the function that will be called to process the * command and the ClientData value it will receive, and argc and argv * give the arguments to the command, after any argument parsing and * substitution. Proc does not return a value. * *---------------------------------------------------------------------- */ Tcl_Trace Tcl_CreateTrace( Tcl_Interp *interp, /* Interpreter in which to create trace. */ int level, /* Only call proc for commands at nesting * level<=argument level (1=>top level). */ Tcl_CmdTraceProc *proc, /* Function to call before executing each * command. */ ClientData clientData) /* Arbitrary value word to pass to proc. */ { StringTraceData *data = ckalloc(sizeof(StringTraceData)); data->clientData = clientData; data->proc = proc; return Tcl_CreateObjTrace(interp, level, 0, StringTraceProc, data, StringTraceDeleteProc); } /* *---------------------------------------------------------------------- * * StringTraceProc -- * * Invoke a string-based trace function from an object-based callback. * * Results: * None. * * Side effects: * Whatever the string-based trace function does. * *---------------------------------------------------------------------- */ static int StringTraceProc( ClientData clientData, Tcl_Interp *interp, int level, const char *command, Tcl_Command commandInfo, int objc, Tcl_Obj *const *objv) { StringTraceData *data = clientData; Command *cmdPtr = (Command *) commandInfo; const char **argv; /* Args to pass to string trace proc */ int i; /* * This is a bit messy because we have to emulate the old trace interface, * which uses strings for everything. */ argv = (const char **) TclStackAlloc(interp, (unsigned) ((objc + 1) * sizeof(const char *))); for (i = 0; i < objc; i++) { argv[i] = Tcl_GetString(objv[i]); } argv[objc] = 0; /* * Invoke the command function. Note that we cast away const-ness on two * parameters for compatibility with legacy code; the code MUST NOT modify * either command or argv. */ data->proc(data->clientData, interp, level, (char *) command, cmdPtr->proc, cmdPtr->clientData, objc, argv); TclStackFree(interp, (void *) argv); return TCL_OK; } /* *---------------------------------------------------------------------- * * StringTraceDeleteProc -- * * Clean up memory when a string-based trace is deleted. * * Results: * None. * * Side effects: * Allocated memory is returned to the system. * *---------------------------------------------------------------------- */ static void StringTraceDeleteProc( ClientData clientData) { ckfree(clientData); } /* *---------------------------------------------------------------------- * * Tcl_DeleteTrace -- * * Remove a trace. * * Results: * None. * * Side effects: * From now on there will be no more calls to the function given in * trace. * *---------------------------------------------------------------------- */ void Tcl_DeleteTrace( Tcl_Interp *interp, /* Interpreter that contains trace. */ Tcl_Trace trace) /* Token for trace (returned previously by * Tcl_CreateTrace). */ { Interp *iPtr = (Interp *) interp; Trace *prevPtr, *tracePtr = (Trace *) trace; register Trace **tracePtr2 = &iPtr->tracePtr; ActiveInterpTrace *activePtr; /* * Locate the trace entry in the interpreter's trace list, and remove it * from the list. */ prevPtr = NULL; while (*tracePtr2 != NULL && *tracePtr2 != tracePtr) { prevPtr = *tracePtr2; tracePtr2 = &prevPtr->nextPtr; } if (*tracePtr2 == NULL) { return; } *tracePtr2 = (*tracePtr2)->nextPtr; /* * The code below makes it possible to delete traces while traces are * active: it makes sure that the deleted trace won't be processed by * TclCheckInterpTraces. */ for (activePtr = iPtr->activeInterpTracePtr; activePtr != NULL; activePtr = activePtr->nextPtr) { if (activePtr->nextTracePtr == tracePtr) { if (activePtr->reverseScan) { activePtr->nextTracePtr = prevPtr; } else { activePtr->nextTracePtr = tracePtr->nextPtr; } } } /* * If the trace forbids bytecode compilation, change the interpreter's * state. If bytecode compilation is now permitted, flag the fact and * advance the compilation epoch so that procs will be recompiled to take * advantage of it. */ if (!(tracePtr->flags & TCL_ALLOW_INLINE_COMPILATION)) { iPtr->tracesForbiddingInline--; if (iPtr->tracesForbiddingInline == 0) { iPtr->flags &= ~DONT_COMPILE_CMDS_INLINE; iPtr->compileEpoch++; } } /* * Execute any delete callback. */ if (tracePtr->delProc != NULL) { tracePtr->delProc(tracePtr->clientData); } /* * Delete the trace object. */ Tcl_EventuallyFree((char *) tracePtr, TCL_DYNAMIC); } /* *---------------------------------------------------------------------- * * TclTraceVarExists -- * * This is called from info exists. We need to trigger read and/or array * traces because they may end up creating a variable that doesn't * currently exist. * * Results: * A pointer to the Var structure, or NULL. * * Side effects: * May fill in error messages in the interp. * *---------------------------------------------------------------------- */ Var * TclVarTraceExists( Tcl_Interp *interp, /* The interpreter */ const char *varName) /* The variable name */ { Var *varPtr, *arrayPtr; /* * The choice of "create" flag values is delicate here, and matches the * semantics of GetVar. Things are still not perfect, however, because if * you do "info exists x" you get a varPtr and therefore trigger traces. * However, if you do "info exists x(i)", then you only get a varPtr if x * is already known to be an array. Otherwise you get NULL, and no trace * is triggered. This matches Tcl 7.6 semantics. */ varPtr = TclLookupVar(interp, varName, NULL, 0, "access", /*createPart1*/ 0, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { return NULL; } if ((varPtr->flags & VAR_TRACED_READ) || (arrayPtr && (arrayPtr->flags & VAR_TRACED_READ))) { TclCallVarTraces((Interp *) interp, arrayPtr, varPtr, varName, NULL, TCL_TRACE_READS, /* leaveErrMsg */ 0); } /* * If the variable doesn't exist anymore and no-one's using it, then free * up the relevant structures and hash table entries. */ if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, arrayPtr); return NULL; } return varPtr; } /* *---------------------------------------------------------------------- * * TclCallVarTraces -- * * This function is invoked to find and invoke relevant trace functions * associated with a particular operation on a variable. This function * invokes traces both on the variable and on its containing array (where * relevant). * * Results: * Returns TCL_OK to indicate normal operation. Returns TCL_ERROR if * invocation of a trace function indicated an error. When TCL_ERROR is * returned and leaveErrMsg is true, then the errorInfo field of iPtr has * information about the error placed in it. * * Side effects: * Almost anything can happen, depending on trace; this function itself * doesn't have any side effects. * *---------------------------------------------------------------------- */ int TclObjCallVarTraces( Interp *iPtr, /* Interpreter containing variable. */ register Var *arrayPtr, /* Pointer to array variable that contains the * variable, or NULL if the variable isn't an * element of an array. */ Var *varPtr, /* Variable whose traces are to be invoked. */ Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, /* Variable's two-part name. */ int flags, /* Flags passed to trace functions: indicates * what's happening to variable, plus maybe * TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY */ int leaveErrMsg, /* If true, and one of the traces indicates an * error, then leave an error message and * stack trace information in *iPTr. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { const char *part1, *part2; if (!part1Ptr) { part1Ptr = localName(iPtr->varFramePtr, index); } if (!part1Ptr) { Tcl_Panic("Cannot trace a variable with no name"); } part1 = TclGetString(part1Ptr); part2 = part2Ptr? TclGetString(part2Ptr) : NULL; return TclCallVarTraces(iPtr, arrayPtr, varPtr, part1, part2, flags, leaveErrMsg); } int TclCallVarTraces( Interp *iPtr, /* Interpreter containing variable. */ register Var *arrayPtr, /* Pointer to array variable that contains the * variable, or NULL if the variable isn't an * element of an array. */ Var *varPtr, /* Variable whose traces are to be invoked. */ const char *part1, const char *part2, /* Variable's two-part name. */ int flags, /* Flags passed to trace functions: indicates * what's happening to variable, plus maybe * TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY */ int leaveErrMsg) /* If true, and one of the traces indicates an * error, then leave an error message and * stack trace information in *iPTr. */ { register VarTrace *tracePtr; ActiveVarTrace active; char *result; const char *openParen, *p; Tcl_DString nameCopy; int copiedName; int code = TCL_OK; int disposeFlags = 0; Tcl_InterpState state = NULL; Tcl_HashEntry *hPtr; int traceflags = flags & VAR_ALL_TRACES; /* * If there are already similar trace functions active for the variable, * don't call them again. */ if (TclIsVarTraceActive(varPtr)) { return code; } TclSetVarTraceActive(varPtr); if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)++; } if (arrayPtr && TclIsVarInHash(arrayPtr)) { VarHashRefCount(arrayPtr)++; } /* * If the variable name hasn't been parsed into array name and element, do * it here. If there really is an array element, make a copy of the * original name so that NULLs can be inserted into it to separate the * names (can't modify the name string in place, because the string might * get used by the callbacks we invoke). */ copiedName = 0; if (part2 == NULL) { for (p = part1; *p ; p++) { if (*p == '(') { openParen = p; do { p++; } while (*p != '\0'); p--; if (*p == ')') { int offset = (openParen - part1); char *newPart1; Tcl_DStringInit(&nameCopy); Tcl_DStringAppend(&nameCopy, part1, p-part1); newPart1 = Tcl_DStringValue(&nameCopy); newPart1[offset] = 0; part1 = newPart1; part2 = newPart1 + offset + 1; copiedName = 1; } break; } } } /* * Ignore any caller-provided TCL_INTERP_DESTROYED flag. Only we can * set it correctly. */ flags &= ~TCL_INTERP_DESTROYED; /* * Invoke traces on the array containing the variable, if relevant. */ result = NULL; active.nextPtr = iPtr->activeVarTracePtr; iPtr->activeVarTracePtr = &active; Tcl_Preserve(iPtr); if (arrayPtr && !TclIsVarTraceActive(arrayPtr) && (arrayPtr->flags & traceflags)) { hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) arrayPtr); active.varPtr = arrayPtr; for (tracePtr = Tcl_GetHashValue(hPtr); tracePtr != NULL; tracePtr = active.nextTracePtr) { active.nextTracePtr = tracePtr->nextPtr; if (!(tracePtr->flags & flags)) { continue; } Tcl_Preserve(tracePtr); if (state == NULL) { state = Tcl_SaveInterpState((Tcl_Interp *) iPtr, code); } if (Tcl_InterpDeleted((Tcl_Interp *) iPtr)) { flags |= TCL_INTERP_DESTROYED; } result = tracePtr->traceProc(tracePtr->clientData, (Tcl_Interp *) iPtr, part1, part2, flags); if (result != NULL) { if (flags & TCL_TRACE_UNSETS) { /* * Ignore errors in unset traces. */ DisposeTraceResult(tracePtr->flags, result); } else { disposeFlags = tracePtr->flags; code = TCL_ERROR; } } Tcl_Release(tracePtr); if (code == TCL_ERROR) { goto done; } } } /* * Invoke traces on the variable itself. */ if (flags & TCL_TRACE_UNSETS) { flags |= TCL_TRACE_DESTROYED; } active.varPtr = varPtr; if (varPtr->flags & traceflags) { hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr); for (tracePtr = Tcl_GetHashValue(hPtr); tracePtr != NULL; tracePtr = active.nextTracePtr) { active.nextTracePtr = tracePtr->nextPtr; if (!(tracePtr->flags & flags)) { continue; } Tcl_Preserve(tracePtr); if (state == NULL) { state = Tcl_SaveInterpState((Tcl_Interp *) iPtr, code); } if (Tcl_InterpDeleted((Tcl_Interp *) iPtr)) { flags |= TCL_INTERP_DESTROYED; } result = tracePtr->traceProc(tracePtr->clientData, (Tcl_Interp *) iPtr, part1, part2, flags); if (result != NULL) { if (flags & TCL_TRACE_UNSETS) { /* * Ignore errors in unset traces. */ DisposeTraceResult(tracePtr->flags, result); } else { disposeFlags = tracePtr->flags; code = TCL_ERROR; } } Tcl_Release(tracePtr); if (code == TCL_ERROR) { goto done; } } } /* * Restore the variable's flags, remove the record of our active traces, * and then return. */ done: if (code == TCL_ERROR) { if (leaveErrMsg) { const char *verb = ""; const char *type = ""; switch (flags&(TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_ARRAY)) { case TCL_TRACE_READS: verb = "read"; type = verb; break; case TCL_TRACE_WRITES: verb = "set"; type = "write"; break; case TCL_TRACE_ARRAY: verb = "trace array"; type = "array"; break; } if (disposeFlags & TCL_TRACE_RESULT_OBJECT) { Tcl_SetObjResult((Tcl_Interp *)iPtr, (Tcl_Obj *) result); } else { Tcl_SetObjResult((Tcl_Interp *)iPtr, Tcl_NewStringObj(result, -1)); } Tcl_AddErrorInfo((Tcl_Interp *)iPtr, ""); Tcl_AppendObjToErrorInfo((Tcl_Interp *)iPtr, Tcl_ObjPrintf( "\n (%s trace on \"%s%s%s%s\")", type, part1, (part2 ? "(" : ""), (part2 ? part2 : ""), (part2 ? ")" : "") )); if (disposeFlags & TCL_TRACE_RESULT_OBJECT) { TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb, Tcl_GetString((Tcl_Obj *) result)); } else { TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb, result); } iPtr->flags &= ~(ERR_ALREADY_LOGGED); Tcl_DiscardInterpState(state); } else { Tcl_RestoreInterpState((Tcl_Interp *) iPtr, state); } DisposeTraceResult(disposeFlags,result); } else if (state) { if (code == TCL_OK) { code = Tcl_RestoreInterpState((Tcl_Interp *) iPtr, state); } else { Tcl_DiscardInterpState(state); } } if (arrayPtr && TclIsVarInHash(arrayPtr)) { VarHashRefCount(arrayPtr)--; } if (copiedName) { Tcl_DStringFree(&nameCopy); } TclClearVarTraceActive(varPtr); if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)--; } iPtr->activeVarTracePtr = active.nextPtr; Tcl_Release(iPtr); return code; } /* *---------------------------------------------------------------------- * * DisposeTraceResult-- * * This function is called to dispose of the result returned from a trace * function. The disposal method appropriate to the type of result is * determined by flags. * * Results: * None. * * Side effects: * The memory allocated for the trace result may be freed. * *---------------------------------------------------------------------- */ static void DisposeTraceResult( int flags, /* Indicates type of result to determine * proper disposal method. */ char *result) /* The result returned from a trace function * to be disposed. */ { if (flags & TCL_TRACE_RESULT_DYNAMIC) { ckfree(result); } else if (flags & TCL_TRACE_RESULT_OBJECT) { Tcl_DecrRefCount((Tcl_Obj *) result); } } /* *---------------------------------------------------------------------- * * Tcl_UntraceVar -- * * Remove a previously-created trace for a variable. * * Results: * None. * * Side effects: * If there exists a trace for the variable given by varName with the * given flags, proc, and clientData, then that trace is removed. * *---------------------------------------------------------------------- */ #undef Tcl_UntraceVar void Tcl_UntraceVar( Tcl_Interp *interp, /* Interpreter containing variable. */ const char *varName, /* Name of variable; may end with "(index)" to * signify an array reference. */ int flags, /* OR-ed collection of bits describing current * trace, including any of TCL_TRACE_READS, * TCL_TRACE_WRITES, TCL_TRACE_UNSETS, * TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY. */ Tcl_VarTraceProc *proc, /* Function assocated with trace. */ ClientData clientData) /* Arbitrary argument to pass to proc. */ { Tcl_UntraceVar2(interp, varName, NULL, flags, proc, clientData); } /* *---------------------------------------------------------------------- * * Tcl_UntraceVar2 -- * * Remove a previously-created trace for a variable. * * Results: * None. * * Side effects: * If there exists a trace for the variable given by part1 and part2 with * the given flags, proc, and clientData, then that trace is removed. * *---------------------------------------------------------------------- */ void Tcl_UntraceVar2( Tcl_Interp *interp, /* Interpreter containing variable. */ const char *part1, /* Name of variable or array. */ const char *part2, /* Name of element within array; NULL means * trace applies to scalar variable or array * as-a-whole. */ int flags, /* OR-ed collection of bits describing current * trace, including any of TCL_TRACE_READS, * TCL_TRACE_WRITES, TCL_TRACE_UNSETS, * TCL_GLOBAL_ONLY, and TCL_NAMESPACE_ONLY. */ Tcl_VarTraceProc *proc, /* Function assocated with trace. */ ClientData clientData) /* Arbitrary argument to pass to proc. */ { register VarTrace *tracePtr; VarTrace *prevPtr, *nextPtr; Var *varPtr, *arrayPtr; Interp *iPtr = (Interp *) interp; ActiveVarTrace *activePtr; int flagMask, allFlags = 0; Tcl_HashEntry *hPtr; /* * Set up a mask to mask out the parts of the flags that we are not * interested in now. */ flagMask = TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY; varPtr = TclLookupVar(interp, part1, part2, flags & flagMask, /*msg*/ NULL, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); if (varPtr == NULL || !(varPtr->flags & VAR_ALL_TRACES & flags)) { return; } /* * Set up a mask to mask out the parts of the flags that we are not * interested in now. */ flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS | TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT; #ifndef TCL_REMOVE_OBSOLETE_TRACES flagMask |= TCL_TRACE_OLD_STYLE; #endif flags &= flagMask; hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr); for (tracePtr = Tcl_GetHashValue(hPtr), prevPtr = NULL; ; prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) { if (tracePtr == NULL) { goto updateFlags; } if ((tracePtr->traceProc == proc) && (tracePtr->flags == flags) && (tracePtr->clientData == clientData)) { break; } allFlags |= tracePtr->flags; } /* * The code below makes it possible to delete traces while traces are * active: it makes sure that the deleted trace won't be processed by * TclCallVarTraces. * * Caveat (Bug 3062331): When an unset trace handler on a variable * tries to delete a different unset trace handler on the same variable, * the results may be surprising. When variable unset traces fire, the * traced variable is already gone. So the TclLookupVar() call above * will not find that variable, and not finding it will never reach here * to perform the deletion. This means callers of Tcl_UntraceVar*() * attempting to delete unset traces from within the handler of another * unset trace have to account for the possibility that their call to * Tcl_UntraceVar*() is a no-op. */ for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL; activePtr = activePtr->nextPtr) { if (activePtr->nextTracePtr == tracePtr) { activePtr->nextTracePtr = tracePtr->nextPtr; } } nextPtr = tracePtr->nextPtr; if (prevPtr == NULL) { if (nextPtr) { Tcl_SetHashValue(hPtr, nextPtr); } else { Tcl_DeleteHashEntry(hPtr); } } else { prevPtr->nextPtr = nextPtr; } tracePtr->nextPtr = NULL; Tcl_EventuallyFree(tracePtr, TCL_DYNAMIC); for (tracePtr = nextPtr; tracePtr != NULL; tracePtr = tracePtr->nextPtr) { allFlags |= tracePtr->flags; } updateFlags: varPtr->flags &= ~VAR_ALL_TRACES; if (allFlags & VAR_ALL_TRACES) { varPtr->flags |= (allFlags & VAR_ALL_TRACES); } else if (TclIsVarUndefined(varPtr)) { /* * If this is the last trace on the variable, and the variable is * unset and unused, then free up the variable. */ TclCleanupVar(varPtr, NULL); } } /* *---------------------------------------------------------------------- * * Tcl_VarTraceInfo -- * * Return the clientData value associated with a trace on a variable. * This function can also be used to step through all of the traces on a * particular variable that have the same trace function. * * Results: * The return value is the clientData value associated with a trace on * the given variable. Information will only be returned for a trace with * proc as trace function. If the clientData argument is NULL then the * first such trace is returned; otherwise, the next relevant one after * the one given by clientData will be returned. If the variable doesn't * exist, or if there are no (more) traces for it, then NULL is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ #undef Tcl_VarTraceInfo ClientData Tcl_VarTraceInfo( Tcl_Interp *interp, /* Interpreter containing variable. */ const char *varName, /* Name of variable; may end with "(index)" to * signify an array reference. */ int flags, /* OR-ed combo or TCL_GLOBAL_ONLY, * TCL_NAMESPACE_ONLY (can be 0). */ Tcl_VarTraceProc *proc, /* Function assocated with trace. */ ClientData prevClientData) /* If non-NULL, gives last value returned by * this function, so this call will return the * next trace after that one. If NULL, this * call will return the first trace. */ { return Tcl_VarTraceInfo2(interp, varName, NULL, flags, proc, prevClientData); } /* *---------------------------------------------------------------------- * * Tcl_VarTraceInfo2 -- * * Same as Tcl_VarTraceInfo, except takes name in two pieces instead of * one. * * Results: * Same as Tcl_VarTraceInfo. * * Side effects: * None. * *---------------------------------------------------------------------- */ ClientData Tcl_VarTraceInfo2( Tcl_Interp *interp, /* Interpreter containing variable. */ const char *part1, /* Name of variable or array. */ const char *part2, /* Name of element within array; NULL means * trace applies to scalar variable or array * as-a-whole. */ int flags, /* OR-ed combination of TCL_GLOBAL_ONLY, * TCL_NAMESPACE_ONLY. */ Tcl_VarTraceProc *proc, /* Function assocated with trace. */ ClientData prevClientData) /* If non-NULL, gives last value returned by * this function, so this call will return the * next trace after that one. If NULL, this * call will return the first trace. */ { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_HashEntry *hPtr; varPtr = TclLookupVar(interp, part1, part2, flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY), /*msg*/ NULL, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); if (varPtr == NULL) { return NULL; } /* * Find the relevant trace, if any, and return its clientData. */ hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr); if (hPtr) { register VarTrace *tracePtr = Tcl_GetHashValue(hPtr); if (prevClientData != NULL) { for (; tracePtr != NULL; tracePtr = tracePtr->nextPtr) { if ((tracePtr->clientData == prevClientData) && (tracePtr->traceProc == proc)) { tracePtr = tracePtr->nextPtr; break; } } } for (; tracePtr != NULL ; tracePtr = tracePtr->nextPtr) { if (tracePtr->traceProc == proc) { return tracePtr->clientData; } } } return NULL; } /* *---------------------------------------------------------------------- * * Tcl_TraceVar -- * * Arrange for reads and/or writes to a variable to cause a function to * be invoked, which can monitor the operations and/or change their * actions. * * Results: * A standard Tcl return value. * * Side effects: * A trace is set up on the variable given by varName, such that future * references to the variable will be intermediated by proc. See the * manual entry for complete details on the calling sequence for proc. * The variable's flags are updated. * *---------------------------------------------------------------------- */ #undef Tcl_TraceVar int Tcl_TraceVar( Tcl_Interp *interp, /* Interpreter in which variable is to be * traced. */ const char *varName, /* Name of variable; may end with "(index)" to * signify an array reference. */ int flags, /* OR-ed collection of bits, including any of * TCL_TRACE_READS, TCL_TRACE_WRITES, * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY, and * TCL_NAMESPACE_ONLY. */ Tcl_VarTraceProc *proc, /* Function to call when specified ops are * invoked upon varName. */ ClientData clientData) /* Arbitrary argument to pass to proc. */ { return Tcl_TraceVar2(interp, varName, NULL, flags, proc, clientData); } /* *---------------------------------------------------------------------- * * Tcl_TraceVar2 -- * * Arrange for reads and/or writes to a variable to cause a function to * be invoked, which can monitor the operations and/or change their * actions. * * Results: * A standard Tcl return value. * * Side effects: * A trace is set up on the variable given by part1 and part2, such that * future references to the variable will be intermediated by proc. See * the manual entry for complete details on the calling sequence for * proc. The variable's flags are updated. * *---------------------------------------------------------------------- */ int Tcl_TraceVar2( Tcl_Interp *interp, /* Interpreter in which variable is to be * traced. */ const char *part1, /* Name of scalar variable or array. */ const char *part2, /* Name of element within array; NULL means * trace applies to scalar variable or array * as-a-whole. */ int flags, /* OR-ed collection of bits, including any of * TCL_TRACE_READS, TCL_TRACE_WRITES, * TCL_TRACE_UNSETS, TCL_GLOBAL_ONLY, and * TCL_NAMESPACE_ONLY. */ Tcl_VarTraceProc *proc, /* Function to call when specified ops are * invoked upon varName. */ ClientData clientData) /* Arbitrary argument to pass to proc. */ { register VarTrace *tracePtr; int result; tracePtr = ckalloc(sizeof(VarTrace)); tracePtr->traceProc = proc; tracePtr->clientData = clientData; tracePtr->flags = flags; result = TraceVarEx(interp, part1, part2, tracePtr); if (result != TCL_OK) { ckfree(tracePtr); } return result; } /* *---------------------------------------------------------------------- * * TraceVarEx -- * * Arrange for reads and/or writes to a variable to cause a function to * be invoked, which can monitor the operations and/or change their * actions. * * Results: * A standard Tcl return value. * * Side effects: * A trace is set up on the variable given by part1 and part2, such that * future references to the variable will be intermediated by the * traceProc listed in tracePtr. See the manual entry for complete * details on the calling sequence for proc. * *---------------------------------------------------------------------- */ static int TraceVarEx( Tcl_Interp *interp, /* Interpreter in which variable is to be * traced. */ const char *part1, /* Name of scalar variable or array. */ const char *part2, /* Name of element within array; NULL means * trace applies to scalar variable or array * as-a-whole. */ register VarTrace *tracePtr)/* Structure containing flags, traceProc and * clientData fields. Others should be left * blank. Will be ckfree()d (eventually) if * this function returns TCL_OK, and up to * caller to free if this function returns * TCL_ERROR. */ { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; int flagMask, isNew; Tcl_HashEntry *hPtr; /* * We strip 'flags' down to just the parts which are relevant to * TclLookupVar, to avoid conflicts between trace flags and internal * namespace flags such as 'TCL_FIND_ONLY_NS'. This can now occur since we * have trace flags with values 0x1000 and higher. */ flagMask = TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY; varPtr = TclLookupVar(interp, part1, part2, (tracePtr->flags & flagMask) | TCL_LEAVE_ERR_MSG, "trace", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { return TCL_ERROR; } /* * Check for a nonsense flag combination. Note that this is a Tcl_Panic() * because there should be no code path that ever sets both flags. */ if ((tracePtr->flags & TCL_TRACE_RESULT_DYNAMIC) && (tracePtr->flags & TCL_TRACE_RESULT_OBJECT)) { Tcl_Panic("bad result flag combination"); } /* * Set up trace information. */ flagMask = TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS | TCL_TRACE_ARRAY | TCL_TRACE_RESULT_DYNAMIC | TCL_TRACE_RESULT_OBJECT; #ifndef TCL_REMOVE_OBSOLETE_TRACES flagMask |= TCL_TRACE_OLD_STYLE; #endif tracePtr->flags = tracePtr->flags & flagMask; hPtr = Tcl_CreateHashEntry(&iPtr->varTraces, varPtr, &isNew); if (isNew) { tracePtr->nextPtr = NULL; } else { tracePtr->nextPtr = Tcl_GetHashValue(hPtr); } Tcl_SetHashValue(hPtr, tracePtr); /* * Mark the variable as traced so we know to call them. */ varPtr->flags |= (tracePtr->flags & VAR_ALL_TRACES); return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclEncoding.c0000644000175000017500000031534212663660065015610 0ustar sergeisergei/* * tclEncoding.c -- * * Contains the implementation of the encoding conversion package. * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" typedef size_t (LengthProc)(const char *src); /* * The following data structure represents an encoding, which describes how to * convert between various character sets and UTF-8. */ typedef struct Encoding { char *name; /* Name of encoding. Malloced because (1) hash * table entry that owns this encoding may be * freed prior to this encoding being freed, * (2) string passed in the Tcl_EncodingType * structure may not be persistent. */ Tcl_EncodingConvertProc *toUtfProc; /* Function to convert from external encoding * into UTF-8. */ Tcl_EncodingConvertProc *fromUtfProc; /* Function to convert from UTF-8 into * external encoding. */ Tcl_EncodingFreeProc *freeProc; /* If non-NULL, function to call when this * encoding is deleted. */ int nullSize; /* Number of 0x00 bytes that signify * end-of-string in this encoding. This number * is used to determine the source string * length when the srcLen argument is * negative. This number can be 1 or 2. */ ClientData clientData; /* Arbitrary value associated with encoding * type. Passed to conversion functions. */ LengthProc *lengthProc; /* Function to compute length of * null-terminated strings in this encoding. * If nullSize is 1, this is strlen; if * nullSize is 2, this is a function that * returns the number of bytes in a 0x0000 * terminated string. */ int refCount; /* Number of uses of this structure. */ Tcl_HashEntry *hPtr; /* Hash table entry that owns this encoding. */ } Encoding; /* * The following structure is the clientData for a dynamically-loaded, * table-driven encoding created by LoadTableEncoding(). It maps between * Unicode and a single-byte, double-byte, or multibyte (1 or 2 bytes only) * encoding. */ typedef struct TableEncodingData { int fallback; /* Character (in this encoding) to substitute * when this encoding cannot represent a UTF-8 * character. */ char prefixBytes[256]; /* If a byte in the input stream is a lead * byte for a 2-byte sequence, the * corresponding entry in this array is 1, * otherwise it is 0. */ unsigned short **toUnicode; /* Two dimensional sparse matrix to map * characters from the encoding to Unicode. * Each element of the toUnicode array points * to an array of 256 shorts. If there is no * corresponding character in Unicode, the * value in the matrix is 0x0000. * malloc'd. */ unsigned short **fromUnicode; /* Two dimensional sparse matrix to map * characters from Unicode to the encoding. * Each element of the fromUnicode array * points to an array of 256 shorts. If there * is no corresponding character the encoding, * the value in the matrix is 0x0000. * malloc'd. */ } TableEncodingData; /* * The following structures is the clientData for a dynamically-loaded, * escape-driven encoding that is itself comprised of other simpler encodings. * An example is "iso-2022-jp", which uses escape sequences to switch between * ascii, jis0208, jis0212, gb2312, and ksc5601. Note that "escape-driven" * does not necessarily mean that the ESCAPE character is the character used * for switching character sets. */ typedef struct EscapeSubTable { unsigned sequenceLen; /* Length of following string. */ char sequence[16]; /* Escape code that marks this encoding. */ char name[32]; /* Name for encoding. */ Encoding *encodingPtr; /* Encoding loaded using above name, or NULL * if this sub-encoding has not been needed * yet. */ } EscapeSubTable; typedef struct EscapeEncodingData { int fallback; /* Character (in this encoding) to substitute * when this encoding cannot represent a UTF-8 * character. */ unsigned initLen; /* Length of following string. */ char init[16]; /* String to emit or expect before first char * in conversion. */ unsigned finalLen; /* Length of following string. */ char final[16]; /* String to emit or expect after last char in * conversion. */ char prefixBytes[256]; /* If a byte in the input stream is the first * character of one of the escape sequences in * the following array, the corresponding * entry in this array is 1, otherwise it is * 0. */ int numSubTables; /* Length of following array. */ EscapeSubTable subTables[1];/* Information about each EscapeSubTable used * by this encoding type. The actual size will * be as large as necessary to hold all * EscapeSubTables. */ } EscapeEncodingData; /* * Constants used when loading an encoding file to identify the type of the * file. */ #define ENCODING_SINGLEBYTE 0 #define ENCODING_DOUBLEBYTE 1 #define ENCODING_MULTIBYTE 2 #define ENCODING_ESCAPE 3 /* * A list of directories in which Tcl should look for *.enc files. This list * is shared by all threads. Access is governed by a mutex lock. */ static TclInitProcessGlobalValueProc InitializeEncodingSearchPath; static ProcessGlobalValue encodingSearchPath = { 0, 0, NULL, NULL, InitializeEncodingSearchPath, NULL, NULL }; /* * A map from encoding names to the directories in which their data files have * been seen. The string value of the map is shared by all threads. Access to * the shared string is governed by a mutex lock. */ static ProcessGlobalValue encodingFileMap = { 0, 0, NULL, NULL, NULL, NULL, NULL }; /* * A list of directories making up the "library path". Historically this * search path has served many uses, but the only one remaining is a base for * the encodingSearchPath above. If the application does not explicitly set * the encodingSearchPath, then it will be initialized by appending /encoding * to each directory in this "libraryPath". */ static ProcessGlobalValue libraryPath = { 0, 0, NULL, NULL, TclpInitLibraryPath, NULL, NULL }; static int encodingsInitialized = 0; /* * Hash table that keeps track of all loaded Encodings. Keys are the string * names that represent the encoding, values are (Encoding *). */ static Tcl_HashTable encodingTable; TCL_DECLARE_MUTEX(encodingMutex) /* * The following are used to hold the default and current system encodings. * If NULL is passed to one of the conversion routines, the current setting of * the system encoding will be used to perform the conversion. */ static Tcl_Encoding defaultEncoding = NULL; static Tcl_Encoding systemEncoding = NULL; Tcl_Encoding tclIdentityEncoding = NULL; /* * The following variable is used in the sparse matrix code for a * TableEncoding to represent a page in the table that has no entries. */ static unsigned short emptyPage[256]; /* * Functions used only in this module. */ static int BinaryProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static void DupEncodingIntRep(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr); static void EscapeFreeProc(ClientData clientData); static int EscapeFromUtfProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static int EscapeToUtfProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static void FillEncodingFileMap(void); static void FreeEncoding(Tcl_Encoding encoding); static void FreeEncodingIntRep(Tcl_Obj *objPtr); static Encoding * GetTableEncoding(EscapeEncodingData *dataPtr, int state); static Tcl_Encoding LoadEncodingFile(Tcl_Interp *interp, const char *name); static Tcl_Encoding LoadTableEncoding(const char *name, int type, Tcl_Channel chan); static Tcl_Encoding LoadEscapeEncoding(const char *name, Tcl_Channel chan); static Tcl_Channel OpenEncodingFileChannel(Tcl_Interp *interp, const char *name); static void TableFreeProc(ClientData clientData); static int TableFromUtfProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static int TableToUtfProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static size_t unilen(const char *src); static int UnicodeToUtfProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static int UtfToUnicodeProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); 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 int UtfIntToUtfExtProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static int UtfExtToUtfIntProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static int Iso88591FromUtfProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); static int Iso88591ToUtfProc(ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); /* * A Tcl_ObjType for holding a cached Tcl_Encoding in the twoPtrValue.ptr1 field * of the intrep. This should help the lifetime of encodings be more useful. * See concerns raised in [Bug 1077262]. */ static const Tcl_ObjType encodingType = { "encoding", FreeEncodingIntRep, DupEncodingIntRep, NULL, NULL }; /* *---------------------------------------------------------------------- * * Tcl_GetEncodingFromObj -- * * Writes to (*encodingPtr) the Tcl_Encoding value of (*objPtr), if * possible, and returns TCL_OK. If no such encoding exists, TCL_ERROR is * returned, and if interp is non-NULL, an error message is written * there. * * Results: * Standard Tcl return code. * * Side effects: * Caches the Tcl_Encoding value as the internal rep of (*objPtr). * *---------------------------------------------------------------------- */ int Tcl_GetEncodingFromObj( Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr) { const char *name = Tcl_GetString(objPtr); if (objPtr->typePtr != &encodingType) { Tcl_Encoding encoding = Tcl_GetEncoding(interp, name); if (encoding == NULL) { return TCL_ERROR; } TclFreeIntRep(objPtr); objPtr->internalRep.twoPtrValue.ptr1 = encoding; objPtr->typePtr = &encodingType; } *encodingPtr = Tcl_GetEncoding(NULL, name); return TCL_OK; } /* *---------------------------------------------------------------------- * * FreeEncodingIntRep -- * * The Tcl_FreeInternalRepProc for the "encoding" Tcl_ObjType. * *---------------------------------------------------------------------- */ static void FreeEncodingIntRep( Tcl_Obj *objPtr) { Tcl_FreeEncoding(objPtr->internalRep.twoPtrValue.ptr1); objPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * DupEncodingIntRep -- * * The Tcl_DupInternalRepProc for the "encoding" Tcl_ObjType. * *---------------------------------------------------------------------- */ static void DupEncodingIntRep( Tcl_Obj *srcPtr, Tcl_Obj *dupPtr) { dupPtr->internalRep.twoPtrValue.ptr1 = Tcl_GetEncoding(NULL, srcPtr->bytes); } /* *---------------------------------------------------------------------- * * Tcl_GetEncodingSearchPath -- * * Keeps the per-thread copy of the encoding search path current with * changes to the global copy. * * Results: * Returns a "list" (Tcl_Obj *) that contains the encoding search path. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_GetEncodingSearchPath(void) { return TclGetProcessGlobalValue(&encodingSearchPath); } /* *---------------------------------------------------------------------- * * Tcl_SetEncodingSearchPath -- * * Keeps the per-thread copy of the encoding search path current with * changes to the global copy. * *---------------------------------------------------------------------- */ int Tcl_SetEncodingSearchPath( Tcl_Obj *searchPath) { int dummy; if (TCL_ERROR == Tcl_ListObjLength(NULL, searchPath, &dummy)) { return TCL_ERROR; } TclSetProcessGlobalValue(&encodingSearchPath, searchPath, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclGetLibraryPath -- * * Keeps the per-thread copy of the library path current with changes to * the global copy. * * Results: * Returns a "list" (Tcl_Obj *) that contains the library path. * *---------------------------------------------------------------------- */ Tcl_Obj * TclGetLibraryPath(void) { return TclGetProcessGlobalValue(&libraryPath); } /* *---------------------------------------------------------------------- * * TclSetLibraryPath -- * * Keeps the per-thread copy of the library path current with changes to * the global copy. * * NOTE: this routine returns void, so there's no way to report the error * that searchPath is not a valid list. In that case, this routine will * silently do nothing. * *---------------------------------------------------------------------- */ void TclSetLibraryPath( Tcl_Obj *path) { int dummy; if (TCL_ERROR == Tcl_ListObjLength(NULL, path, &dummy)) { return; } TclSetProcessGlobalValue(&libraryPath, path, NULL); } /* *--------------------------------------------------------------------------- * * FillEncodingFileMap -- * * Called to bring the encoding file map in sync with the current value * of the encoding search path. * * Scan the directories on the encoding search path, find the *.enc * files, and store the found pathnames in a map associated with the * encoding name. * * In particular, if $dir is on the encoding search path, and the file * $dir/foo.enc is found, then store a "foo" -> $dir entry in the map. * Later, any need for the "foo" encoding will quickly * be able to * construct the $dir/foo.enc pathname for reading the encoding data. * * Results: * None. * * Side effects: * Entries are added to the encoding file map. * *--------------------------------------------------------------------------- */ static void FillEncodingFileMap(void) { int i, numDirs = 0; Tcl_Obj *map, *searchPath; searchPath = Tcl_GetEncodingSearchPath(); Tcl_IncrRefCount(searchPath); Tcl_ListObjLength(NULL, searchPath, &numDirs); map = Tcl_NewDictObj(); Tcl_IncrRefCount(map); for (i = numDirs-1; i >= 0; i--) { /* * Iterate backwards through the search path so as we overwrite * entries found, we favor files earlier on the search path. */ int j, numFiles; Tcl_Obj *directory, *matchFileList = Tcl_NewObj(); Tcl_Obj **filev; Tcl_GlobTypeData readableFiles = { TCL_GLOB_TYPE_FILE, TCL_GLOB_PERM_R, NULL, NULL }; Tcl_ListObjIndex(NULL, searchPath, i, &directory); Tcl_IncrRefCount(directory); Tcl_IncrRefCount(matchFileList); Tcl_FSMatchInDirectory(NULL, matchFileList, directory, "*.enc", &readableFiles); Tcl_ListObjGetElements(NULL, matchFileList, &numFiles, &filev); for (j=0; jfallback = '?'; size = 256*(sizeof(unsigned short *) + sizeof(unsigned short)); dataPtr->toUnicode = ckalloc(size); memset(dataPtr->toUnicode, 0, size); dataPtr->fromUnicode = ckalloc(size); memset(dataPtr->fromUnicode, 0, size); dataPtr->toUnicode[0] = (unsigned short *) (dataPtr->toUnicode + 256); dataPtr->fromUnicode[0] = (unsigned short *) (dataPtr->fromUnicode + 256); for (i=1 ; i<256 ; i++) { dataPtr->toUnicode[i] = emptyPage; dataPtr->fromUnicode[i] = emptyPage; } for (i=0 ; i<256 ; i++) { dataPtr->toUnicode[0][i] = i; dataPtr->fromUnicode[0][i] = i; } type.encodingName = "iso8859-1"; type.toUtfProc = Iso88591ToUtfProc; type.fromUtfProc = Iso88591FromUtfProc; type.freeProc = TableFreeProc; type.nullSize = 1; type.clientData = dataPtr; defaultEncoding = Tcl_CreateEncoding(&type); systemEncoding = Tcl_GetEncoding(NULL, type.encodingName); encodingsInitialized = 1; } /* *---------------------------------------------------------------------- * * TclFinalizeEncodingSubsystem -- * * Release the state associated with the encoding subsystem. * * Results: * None. * * Side effects: * Frees all of the encodings. * *---------------------------------------------------------------------- */ void TclFinalizeEncodingSubsystem(void) { Tcl_HashSearch search; Tcl_HashEntry *hPtr; Tcl_MutexLock(&encodingMutex); encodingsInitialized = 0; FreeEncoding(systemEncoding); systemEncoding = NULL; defaultEncoding = NULL; FreeEncoding(tclIdentityEncoding); tclIdentityEncoding = NULL; hPtr = Tcl_FirstHashEntry(&encodingTable, &search); while (hPtr != NULL) { /* * Call FreeEncoding instead of doing it directly to handle refcounts * like escape encodings use. [Bug 524674] Make sure to call * Tcl_FirstHashEntry repeatedly so that all encodings are eventually * cleaned up. */ FreeEncoding(Tcl_GetHashValue(hPtr)); hPtr = Tcl_FirstHashEntry(&encodingTable, &search); } Tcl_DeleteHashTable(&encodingTable); Tcl_MutexUnlock(&encodingMutex); } /* *------------------------------------------------------------------------- * * Tcl_GetDefaultEncodingDir -- * * Legacy public interface to retrieve first directory in the encoding * searchPath. * * Results: * The directory pathname, as a string, or NULL for an empty encoding * search path. * * Side effects: * None. * *------------------------------------------------------------------------- */ const char * Tcl_GetDefaultEncodingDir(void) { int numDirs; Tcl_Obj *first, *searchPath = Tcl_GetEncodingSearchPath(); Tcl_ListObjLength(NULL, searchPath, &numDirs); if (numDirs == 0) { return NULL; } Tcl_ListObjIndex(NULL, searchPath, 0, &first); return Tcl_GetString(first); } /* *------------------------------------------------------------------------- * * Tcl_SetDefaultEncodingDir -- * * Legacy public interface to set the first directory in the encoding * search path. * * Results: * None. * * Side effects: * Modifies the encoding search path. * *------------------------------------------------------------------------- */ void Tcl_SetDefaultEncodingDir( const char *path) { Tcl_Obj *searchPath = Tcl_GetEncodingSearchPath(); Tcl_Obj *directory = Tcl_NewStringObj(path, -1); searchPath = Tcl_DuplicateObj(searchPath); Tcl_ListObjReplace(NULL, searchPath, 0, 0, 1, &directory); Tcl_SetEncodingSearchPath(searchPath); } /* *------------------------------------------------------------------------- * * Tcl_GetEncoding -- * * Given the name of a encoding, find the corresponding Tcl_Encoding * token. If the encoding did not already exist, Tcl attempts to * dynamically load an encoding by that name. * * Results: * Returns a token that represents the encoding. If the name didn't refer * to any known or loadable encoding, NULL is returned. If NULL was * returned, an error message is left in interp's result object, unless * interp was NULL. * * Side effects: * The new encoding type is entered into a table visible to all * interpreters, keyed off the encoding's name. For each call to this * function, there should eventually be a call to Tcl_FreeEncoding, so * that the database can be cleaned up when encodings aren't needed * anymore. * *------------------------------------------------------------------------- */ Tcl_Encoding Tcl_GetEncoding( Tcl_Interp *interp, /* Interp for error reporting, if not NULL. */ const char *name) /* The name of the desired encoding. */ { Tcl_HashEntry *hPtr; Encoding *encodingPtr; Tcl_MutexLock(&encodingMutex); if (name == NULL) { encodingPtr = (Encoding *) systemEncoding; encodingPtr->refCount++; Tcl_MutexUnlock(&encodingMutex); return systemEncoding; } hPtr = Tcl_FindHashEntry(&encodingTable, name); if (hPtr != NULL) { encodingPtr = Tcl_GetHashValue(hPtr); encodingPtr->refCount++; Tcl_MutexUnlock(&encodingMutex); return (Tcl_Encoding) encodingPtr; } Tcl_MutexUnlock(&encodingMutex); return LoadEncodingFile(interp, name); } /* *--------------------------------------------------------------------------- * * Tcl_FreeEncoding -- * * This function is called to release an encoding allocated by * Tcl_CreateEncoding() or Tcl_GetEncoding(). * * Results: * None. * * Side effects: * The reference count associated with the encoding is decremented and * the encoding may be deleted if nothing is using it anymore. * *--------------------------------------------------------------------------- */ void Tcl_FreeEncoding( Tcl_Encoding encoding) { Tcl_MutexLock(&encodingMutex); FreeEncoding(encoding); Tcl_MutexUnlock(&encodingMutex); } /* *---------------------------------------------------------------------- * * FreeEncoding -- * * This function is called to release an encoding by functions that * already have the encodingMutex. * * Results: * None. * * Side effects: * The reference count associated with the encoding is decremented and * the encoding may be deleted if nothing is using it anymore. * *---------------------------------------------------------------------- */ static void FreeEncoding( Tcl_Encoding encoding) { Encoding *encodingPtr = (Encoding *) encoding; if (encodingPtr == NULL) { return; } if (encodingPtr->refCount<=0) { Tcl_Panic("FreeEncoding: refcount problem !!!"); } encodingPtr->refCount--; if (encodingPtr->refCount == 0) { if (encodingPtr->freeProc != NULL) { encodingPtr->freeProc(encodingPtr->clientData); } if (encodingPtr->hPtr != NULL) { Tcl_DeleteHashEntry(encodingPtr->hPtr); } ckfree(encodingPtr->name); ckfree(encodingPtr); } } /* *------------------------------------------------------------------------- * * Tcl_GetEncodingName -- * * Given an encoding, return the name that was used to constuct the * encoding. * * Results: * The name of the encoding. * * Side effects: * None. * *--------------------------------------------------------------------------- */ const char * Tcl_GetEncodingName( Tcl_Encoding encoding) /* The encoding whose name to fetch. */ { if (encoding == NULL) { encoding = systemEncoding; } return ((Encoding *) encoding)->name; } /* *------------------------------------------------------------------------- * * Tcl_GetEncodingNames -- * * Get the list of all known encodings, including the ones stored as * files on disk in the encoding path. * * Results: * Modifies interp's result object to hold a list of all the available * encodings. * * Side effects: * None. * *------------------------------------------------------------------------- */ void Tcl_GetEncodingNames( Tcl_Interp *interp) /* Interp to hold result. */ { Tcl_HashTable table; Tcl_HashSearch search; Tcl_HashEntry *hPtr; Tcl_Obj *map, *name, *result = Tcl_NewObj(); Tcl_DictSearch mapSearch; int dummy, done = 0; Tcl_InitObjHashTable(&table); /* * Copy encoding names from loaded encoding table to table. */ Tcl_MutexLock(&encodingMutex); for (hPtr = Tcl_FirstHashEntry(&encodingTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Encoding *encodingPtr = Tcl_GetHashValue(hPtr); Tcl_CreateHashEntry(&table, Tcl_NewStringObj(encodingPtr->name, -1), &dummy); } Tcl_MutexUnlock(&encodingMutex); FillEncodingFileMap(); map = TclGetProcessGlobalValue(&encodingFileMap); /* * Copy encoding names from encoding file map to table. */ Tcl_DictObjFirst(NULL, map, &mapSearch, &name, NULL, &done); for (; !done; Tcl_DictObjNext(&mapSearch, &name, NULL, &done)) { Tcl_CreateHashEntry(&table, name, &dummy); } /* * Pull all encoding names from table into the result list. */ for (hPtr = Tcl_FirstHashEntry(&table, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Tcl_ListObjAppendElement(NULL, result, (Tcl_Obj *) Tcl_GetHashKey(&table, hPtr)); } Tcl_SetObjResult(interp, result); Tcl_DeleteHashTable(&table); } /* *------------------------------------------------------------------------ * * Tcl_SetSystemEncoding -- * * Sets the default encoding that should be used whenever the user passes * a NULL value in to one of the conversion routines. If the supplied * name is NULL, the system encoding is reset to the default system * encoding. * * Results: * The return value is TCL_OK if the system encoding was successfully set * to the encoding specified by name, TCL_ERROR otherwise. If TCL_ERROR * is returned, an error message is left in interp's result object, * unless interp was NULL. * * Side effects: * The reference count of the new system encoding is incremented. The * reference count of the old system encoding is decremented and it may * be freed. * *------------------------------------------------------------------------ */ int Tcl_SetSystemEncoding( Tcl_Interp *interp, /* Interp for error reporting, if not NULL. */ const char *name) /* The name of the desired encoding, or NULL/"" * to reset to default encoding. */ { Tcl_Encoding encoding; Encoding *encodingPtr; if (!name || !*name) { Tcl_MutexLock(&encodingMutex); encoding = defaultEncoding; encodingPtr = (Encoding *) encoding; encodingPtr->refCount++; Tcl_MutexUnlock(&encodingMutex); } else { encoding = Tcl_GetEncoding(interp, name); if (encoding == NULL) { return TCL_ERROR; } } Tcl_MutexLock(&encodingMutex); FreeEncoding(systemEncoding); systemEncoding = encoding; Tcl_MutexUnlock(&encodingMutex); return TCL_OK; } /* *--------------------------------------------------------------------------- * * Tcl_CreateEncoding -- * * This function is called to define a new encoding and the functions * that are used to convert between the specified encoding and Unicode. * * Results: * Returns a token that represents the encoding. If an encoding with the * same name already existed, the old encoding token remains valid and * continues to behave as it used to, and will eventually be garbage * collected when the last reference to it goes away. Any subsequent * calls to Tcl_GetEncoding with the specified name will retrieve the * most recent encoding token. * * Side effects: * The new encoding type is entered into a table visible to all * interpreters, keyed off the encoding's name. For each call to this * function, there should eventually be a call to Tcl_FreeEncoding, so * that the database can be cleaned up when encodings aren't needed * anymore. * *--------------------------------------------------------------------------- */ Tcl_Encoding Tcl_CreateEncoding( const Tcl_EncodingType *typePtr) /* The encoding type. */ { Tcl_HashEntry *hPtr; int isNew; Encoding *encodingPtr; char *name; Tcl_MutexLock(&encodingMutex); hPtr = Tcl_CreateHashEntry(&encodingTable, typePtr->encodingName, &isNew); if (isNew == 0) { /* * Remove old encoding from hash table, but don't delete it until last * reference goes away. */ encodingPtr = Tcl_GetHashValue(hPtr); encodingPtr->hPtr = NULL; } name = ckalloc(strlen(typePtr->encodingName) + 1); encodingPtr = ckalloc(sizeof(Encoding)); encodingPtr->name = strcpy(name, typePtr->encodingName); encodingPtr->toUtfProc = typePtr->toUtfProc; encodingPtr->fromUtfProc = typePtr->fromUtfProc; encodingPtr->freeProc = typePtr->freeProc; encodingPtr->nullSize = typePtr->nullSize; encodingPtr->clientData = typePtr->clientData; if (typePtr->nullSize == 1) { encodingPtr->lengthProc = (LengthProc *) strlen; } else { encodingPtr->lengthProc = (LengthProc *) unilen; } encodingPtr->refCount = 1; encodingPtr->hPtr = hPtr; Tcl_SetHashValue(hPtr, encodingPtr); Tcl_MutexUnlock(&encodingMutex); return (Tcl_Encoding) encodingPtr; } /* *------------------------------------------------------------------------- * * Tcl_ExternalToUtfDString -- * * Convert a source buffer from the specified encoding into UTF-8. If any * of the bytes in the source buffer are invalid or cannot be represented * in the target encoding, a default fallback character will be * substituted. * * Results: * The converted bytes are stored in the DString, which is then NULL * terminated. The return value is a pointer to the value stored in the * DString. * * Side effects: * None. * *------------------------------------------------------------------------- */ char * Tcl_ExternalToUtfDString( Tcl_Encoding encoding, /* The encoding for the source string, or NULL * for the default system encoding. */ const char *src, /* Source string in specified encoding. */ int srcLen, /* Source string length in bytes, or < 0 for * encoding-specific string length. */ Tcl_DString *dstPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { char *dst; Tcl_EncodingState state; const Encoding *encodingPtr; int flags, dstLen, result, soFar, srcRead, dstWrote, dstChars; Tcl_DStringInit(dstPtr); dst = Tcl_DStringValue(dstPtr); dstLen = dstPtr->spaceAvl - 1; if (encoding == NULL) { encoding = systemEncoding; } encodingPtr = (Encoding *) encoding; if (src == NULL) { srcLen = 0; } else if (srcLen < 0) { srcLen = encodingPtr->lengthProc(src); } flags = TCL_ENCODING_START | TCL_ENCODING_END; while (1) { result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen, flags, &state, dst, dstLen, &srcRead, &dstWrote, &dstChars); soFar = dst + dstWrote - Tcl_DStringValue(dstPtr); 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); } Tcl_DStringSetLength(dstPtr, 2 * Tcl_DStringLength(dstPtr) + 1); dst = Tcl_DStringValue(dstPtr) + soFar; dstLen = Tcl_DStringLength(dstPtr) - soFar - 1; } } /* *------------------------------------------------------------------------- * * Tcl_ExternalToUtf -- * * Convert a source buffer from the specified encoding into UTF-8. * * Results: * The return value is one of TCL_OK, TCL_CONVERT_MULTIBYTE, * TCL_CONVERT_SYNTAX, TCL_CONVERT_UNKNOWN, or TCL_CONVERT_NOSPACE, as * documented in tcl.h. * * Side effects: * The converted bytes are stored in the output buffer. * *------------------------------------------------------------------------- */ int Tcl_ExternalToUtf( Tcl_Interp *interp, /* Interp for error return, if not NULL. */ Tcl_Encoding encoding, /* The encoding for the source string, or NULL * for the default system encoding. */ const char *src, /* Source string in specified encoding. */ int srcLen, /* Source string length in bytes, or < 0 for * encoding-specific string length. */ 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. */ { const Encoding *encodingPtr; int result, srcRead, dstWrote, dstChars = 0; int noTerminate = flags & TCL_ENCODING_NO_TERMINATE; int charLimited = (flags & TCL_ENCODING_CHAR_LIMIT) && dstCharsPtr; int maxChars = INT_MAX; Tcl_EncodingState state; if (encoding == NULL) { encoding = systemEncoding; } encodingPtr = (Encoding *) encoding; if (src == NULL) { srcLen = 0; } else if (srcLen < 0) { srcLen = encodingPtr->lengthProc(src); } if (statePtr == NULL) { flags |= TCL_ENCODING_START | TCL_ENCODING_END; statePtr = &state; } if (srcReadPtr == NULL) { srcReadPtr = &srcRead; } if (dstWrotePtr == NULL) { dstWrotePtr = &dstWrote; } if (dstCharsPtr == NULL) { dstCharsPtr = &dstChars; flags &= ~TCL_ENCODING_CHAR_LIMIT; } else if (charLimited) { maxChars = *dstCharsPtr; } 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 * the actual \0 at the end of the destination buffer, we need to * append it manually. First make room for it... */ dstLen--; } do { int savedFlags = flags; Tcl_EncodingState savedState = *statePtr; result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr); if (*dstCharsPtr <= maxChars) { break; } dstLen = Tcl_UtfAtIndex(dst, maxChars) - 1 - dst + TCL_UTF_MAX; flags = savedFlags; *statePtr = savedState; } while (1); if (!noTerminate) { /* ...and then append it */ dst[*dstWrotePtr] = '\0'; } return result; } /* *------------------------------------------------------------------------- * * Tcl_UtfToExternalDString -- * * Convert a source buffer from UTF-8 into the specified encoding. If any * of the bytes in the source buffer are invalid or cannot be represented * in the target encoding, a default fallback character will be * substituted. * * Results: * The converted bytes are stored in the DString, which is then NULL * terminated in an encoding-specific manner. The return value is a * pointer to the value stored in the DString. * * Side effects: * None. * *------------------------------------------------------------------------- */ char * Tcl_UtfToExternalDString( Tcl_Encoding encoding, /* The encoding for the converted string, or * NULL for the default system encoding. */ const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes, or < 0 for * strlen(). */ Tcl_DString *dstPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { char *dst; Tcl_EncodingState state; const Encoding *encodingPtr; int flags, dstLen, result, soFar, srcRead, dstWrote, dstChars; Tcl_DStringInit(dstPtr); dst = Tcl_DStringValue(dstPtr); dstLen = dstPtr->spaceAvl - 1; if (encoding == NULL) { encoding = systemEncoding; } encodingPtr = (Encoding *) encoding; if (src == NULL) { srcLen = 0; } else if (srcLen < 0) { srcLen = strlen(src); } flags = TCL_ENCODING_START | TCL_ENCODING_END; while (1) { result = encodingPtr->fromUtfProc(encodingPtr->clientData, src, srcLen, flags, &state, dst, dstLen, &srcRead, &dstWrote, &dstChars); soFar = dst + dstWrote - Tcl_DStringValue(dstPtr); if (result != TCL_CONVERT_NOSPACE) { if (encodingPtr->nullSize == 2) { Tcl_DStringSetLength(dstPtr, soFar + 1); } 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); } Tcl_DStringSetLength(dstPtr, 2 * Tcl_DStringLength(dstPtr) + 1); dst = Tcl_DStringValue(dstPtr) + soFar; dstLen = Tcl_DStringLength(dstPtr) - soFar - 1; } } /* *------------------------------------------------------------------------- * * Tcl_UtfToExternal -- * * Convert a buffer from UTF-8 into the specified encoding. * * Results: * The return value is one of TCL_OK, TCL_CONVERT_MULTIBYTE, * TCL_CONVERT_SYNTAX, TCL_CONVERT_UNKNOWN, or TCL_CONVERT_NOSPACE, as * documented in tcl.h. * * Side effects: * The converted bytes are stored in the output buffer. * *------------------------------------------------------------------------- */ int Tcl_UtfToExternal( Tcl_Interp *interp, /* Interp for error return, if not NULL. */ Tcl_Encoding encoding, /* The encoding for the converted string, or * NULL for the default system encoding. */ const char *src, /* Source string in UTF-8. */ int srcLen, /* Source string length in bytes, or < 0 for * strlen(). */ 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. */ { const Encoding *encodingPtr; int result, srcRead, dstWrote, dstChars; Tcl_EncodingState state; if (encoding == NULL) { encoding = systemEncoding; } encodingPtr = (Encoding *) encoding; if (src == NULL) { srcLen = 0; } else if (srcLen < 0) { srcLen = strlen(src); } if (statePtr == NULL) { flags |= TCL_ENCODING_START | TCL_ENCODING_END; statePtr = &state; } if (srcReadPtr == NULL) { srcReadPtr = &srcRead; } if (dstWrotePtr == NULL) { dstWrotePtr = &dstWrote; } if (dstCharsPtr == NULL) { dstCharsPtr = &dstChars; } dstLen -= encodingPtr->nullSize; result = encodingPtr->fromUtfProc(encodingPtr->clientData, src, srcLen, flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr, dstCharsPtr); if (encodingPtr->nullSize == 2) { dst[*dstWrotePtr + 1] = '\0'; } dst[*dstWrotePtr] = '\0'; return result; } /* *--------------------------------------------------------------------------- * * Tcl_FindExecutable -- * * This function computes the absolute path name of the current * application, given its argv[0] value. * * Results: * None. * * Side effects: * The absolute pathname for the application is computed and stored to be * returned later by [info nameofexecutable]. * *--------------------------------------------------------------------------- */ #undef Tcl_FindExecutable void Tcl_FindExecutable( const char *argv0) /* The value of the application's argv[0] * (native). */ { TclInitSubsystems(); TclpSetInitialEncodings(); TclpFindExecutable(argv0); } /* *--------------------------------------------------------------------------- * * OpenEncodingFileChannel -- * * Open the file believed to hold data for the encoding, "name". * * Results: * Returns the readable Tcl_Channel from opening the file, or NULL if the * file could not be successfully opened. If NULL was returned, an error * message is left in interp's result object, unless interp was NULL. * * Side effects: * Channel may be opened. Information about the filesystem may be cached * to speed later calls. * *--------------------------------------------------------------------------- */ static Tcl_Channel OpenEncodingFileChannel( Tcl_Interp *interp, /* Interp for error reporting, if not NULL. */ const char *name) /* The name of the encoding file on disk and * also the name for new encoding. */ { Tcl_Obj *nameObj = Tcl_NewStringObj(name, -1); Tcl_Obj *fileNameObj = Tcl_DuplicateObj(nameObj); Tcl_Obj *searchPath = Tcl_DuplicateObj(Tcl_GetEncodingSearchPath()); Tcl_Obj *map = TclGetProcessGlobalValue(&encodingFileMap); Tcl_Obj **dir, *path, *directory = NULL; Tcl_Channel chan = NULL; int i, numDirs; Tcl_ListObjGetElements(NULL, searchPath, &numDirs, &dir); Tcl_IncrRefCount(nameObj); Tcl_AppendToObj(fileNameObj, ".enc", -1); Tcl_IncrRefCount(fileNameObj); Tcl_DictObjGet(NULL, map, nameObj, &directory); /* * Check that any cached directory is still on the encoding search path. */ if (NULL != directory) { int verified = 0; for (i=0; i 256) { numPages = 256; } memset(used, 0, sizeof(used)); #undef PAGESIZE #define PAGESIZE (256 * sizeof(unsigned short)) dataPtr = ckalloc(sizeof(TableEncodingData)); memset(dataPtr, 0, sizeof(TableEncodingData)); dataPtr->fallback = fallback; /* * Read the table that maps characters to Unicode. Performs a single * malloc to get the memory for the array and all the pages needed by the * array. */ size = 256 * sizeof(unsigned short *) + numPages * PAGESIZE; dataPtr->toUnicode = ckalloc(size); memset(dataPtr->toUnicode, 0, size); pageMemPtr = (unsigned short *) (dataPtr->toUnicode + 256); TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); for (i = 0; i < numPages; i++) { int ch; const char *p; Tcl_ReadChars(chan, objPtr, 3 + 16 * (16 * 4 + 1), 0); p = Tcl_GetString(objPtr); hi = (staticHex[UCHAR(p[0])] << 4) + staticHex[UCHAR(p[1])]; dataPtr->toUnicode[hi] = pageMemPtr; p += 2; for (lo = 0; lo < 256; lo++) { if ((lo & 0x0f) == 0) { p++; } ch = (staticHex[UCHAR(p[0])] << 12) + (staticHex[UCHAR(p[1])] << 8) + (staticHex[UCHAR(p[2])] << 4) + staticHex[UCHAR(p[3])]; if (ch != 0) { used[ch >> 8] = 1; } *pageMemPtr = (unsigned short) ch; pageMemPtr++; p += 4; } } TclDecrRefCount(objPtr); if (type == ENCODING_DOUBLEBYTE) { memset(dataPtr->prefixBytes, 1, sizeof(dataPtr->prefixBytes)); } else { for (hi = 1; hi < 256; hi++) { if (dataPtr->toUnicode[hi] != NULL) { dataPtr->prefixBytes[hi] = 1; } } } /* * Invert toUnicode array to produce the fromUnicode array. Performs a * single malloc to get the memory for the array and all the pages needed * by the array. While reading in the toUnicode array, we remembered what * pages that would be needed for the fromUnicode array. */ if (symbol) { used[0] = 1; } numPages = 0; for (hi = 0; hi < 256; hi++) { if (used[hi]) { numPages++; } } size = 256 * sizeof(unsigned short *) + numPages * PAGESIZE; dataPtr->fromUnicode = ckalloc(size); memset(dataPtr->fromUnicode, 0, size); pageMemPtr = (unsigned short *) (dataPtr->fromUnicode + 256); for (hi = 0; hi < 256; hi++) { if (dataPtr->toUnicode[hi] == NULL) { dataPtr->toUnicode[hi] = emptyPage; continue; } for (lo = 0; lo < 256; lo++) { int ch = dataPtr->toUnicode[hi][lo]; if (ch != 0) { page = dataPtr->fromUnicode[ch >> 8]; if (page == NULL) { page = pageMemPtr; pageMemPtr += 256; dataPtr->fromUnicode[ch >> 8] = page; } page[ch & 0xff] = (unsigned short) ((hi << 8) + lo); } } } if (type == ENCODING_MULTIBYTE) { /* * If multibyte encodings don't have a backslash character, define * one. Otherwise, on Windows, native file names won't work because * the backslash in the file name will map to the unknown character * (question mark) when converting from UTF-8 to external encoding. */ if (dataPtr->fromUnicode[0] != NULL) { if (dataPtr->fromUnicode[0]['\\'] == '\0') { dataPtr->fromUnicode[0]['\\'] = '\\'; } } } if (symbol) { /* * Make a special symbol encoding that not only maps the symbol * characters from their Unicode code points down into page 0, but * also ensure that the characters on page 0 map to themselves. This * is so that a symbol font can be used to display a simple string * like "abcd" and have alpha, beta, chi, delta show up, rather than * have "unknown" chars show up because strictly speaking the symbol * font doesn't have glyphs for those low ASCII chars. */ page = dataPtr->fromUnicode[0]; if (page == NULL) { page = pageMemPtr; dataPtr->fromUnicode[0] = page; } for (lo = 0; lo < 256; lo++) { if (dataPtr->toUnicode[0][lo] != 0) { page[lo] = (unsigned short) lo; } } } for (hi = 0; hi < 256; hi++) { if (dataPtr->fromUnicode[hi] == NULL) { dataPtr->fromUnicode[hi] = emptyPage; } } /* * For trailing 'R'everse encoding, see [Patch 689341] */ Tcl_DStringInit(&lineString); /* * Skip leading empty lines. */ while ((len = Tcl_Gets(chan, &lineString)) == 0) { /* empty body */ } if (len < 0) { goto doneParse; } /* * Require that it starts with an 'R'. */ line = Tcl_DStringValue(&lineString); if (line[0] != 'R') { goto doneParse; } /* * Read lines from the encoding until EOF. */ for (TclDStringClear(&lineString); (len = Tcl_Gets(chan, &lineString)) >= 0; TclDStringClear(&lineString)) { const unsigned char *p; int to, from; /* * Skip short lines. */ if (len < 5) { continue; } /* * Parse the line as a sequence of hex digits. */ p = (const unsigned char *) Tcl_DStringValue(&lineString); to = (staticHex[p[0]] << 12) + (staticHex[p[1]] << 8) + (staticHex[p[2]] << 4) + staticHex[p[3]]; if (to == 0) { continue; } for (p += 5, len -= 5; len >= 0 && *p; p += 5, len -= 5) { from = (staticHex[p[0]] << 12) + (staticHex[p[1]] << 8) + (staticHex[p[2]] << 4) + staticHex[p[3]]; if (from == 0) { continue; } dataPtr->fromUnicode[from >> 8][from & 0xff] = to; } } doneParse: Tcl_DStringFree(&lineString); /* * Package everything into an encoding structure. */ encType.encodingName = name; encType.toUtfProc = TableToUtfProc; encType.fromUtfProc = TableFromUtfProc; encType.freeProc = TableFreeProc; encType.nullSize = (type == ENCODING_DOUBLEBYTE) ? 2 : 1; encType.clientData = dataPtr; return Tcl_CreateEncoding(&encType); } /* *------------------------------------------------------------------------- * * LoadEscapeEncoding -- * * Helper function for LoadEncodingTable(). Loads a state machine that * converts between Unicode and some other encoding. * * File contains text data that describes the escape sequences that are * used to choose an encoding and the associated names for the * sub-encodings. * * Results: * The return value is the new encoding, or NULL if the encoding could * not be created (because the file contained invalid data). * * Side effects: * None. * *------------------------------------------------------------------------- */ static Tcl_Encoding LoadEscapeEncoding( const char *name, /* Name for new encoding. */ Tcl_Channel chan) /* File containing new encoding. */ { int i; unsigned size; Tcl_DString escapeData; char init[16], final[16]; EscapeEncodingData *dataPtr; Tcl_EncodingType type; init[0] = '\0'; final[0] = '\0'; Tcl_DStringInit(&escapeData); while (1) { int argc; const char **argv; char *line; Tcl_DString lineString; Tcl_DStringInit(&lineString); if (Tcl_Gets(chan, &lineString) < 0) { break; } line = Tcl_DStringValue(&lineString); if (Tcl_SplitList(NULL, line, &argc, &argv) != TCL_OK) { Tcl_DStringFree(&lineString); continue; } if (argc >= 2) { if (strcmp(argv[0], "name") == 0) { /* do nothing */ } else if (strcmp(argv[0], "init") == 0) { strncpy(init, argv[1], sizeof(init)); init[sizeof(init) - 1] = '\0'; } else if (strcmp(argv[0], "final") == 0) { strncpy(final, argv[1], sizeof(final)); final[sizeof(final) - 1] = '\0'; } else { EscapeSubTable est; Encoding *e; strncpy(est.sequence, argv[1], sizeof(est.sequence)); est.sequence[sizeof(est.sequence) - 1] = '\0'; est.sequenceLen = strlen(est.sequence); strncpy(est.name, argv[0], sizeof(est.name)); est.name[sizeof(est.name) - 1] = '\0'; /* * To avoid infinite recursion in [encoding system iso2022-*] */ e = (Encoding *) Tcl_GetEncoding(NULL, est.name); if ((e != NULL) && (e->toUtfProc != TableToUtfProc) && (e->toUtfProc != Iso88591ToUtfProc)) { Tcl_FreeEncoding((Tcl_Encoding) e); e = NULL; } est.encodingPtr = e; Tcl_DStringAppend(&escapeData, (char *) &est, sizeof(est)); } } ckfree(argv); Tcl_DStringFree(&lineString); } size = sizeof(EscapeEncodingData) - sizeof(EscapeSubTable) + Tcl_DStringLength(&escapeData); dataPtr = ckalloc(size); dataPtr->initLen = strlen(init); memcpy(dataPtr->init, init, (unsigned) dataPtr->initLen + 1); dataPtr->finalLen = strlen(final); memcpy(dataPtr->final, final, (unsigned) dataPtr->finalLen + 1); dataPtr->numSubTables = Tcl_DStringLength(&escapeData) / sizeof(EscapeSubTable); memcpy(dataPtr->subTables, Tcl_DStringValue(&escapeData), (size_t) Tcl_DStringLength(&escapeData)); Tcl_DStringFree(&escapeData); memset(dataPtr->prefixBytes, 0, sizeof(dataPtr->prefixBytes)); for (i = 0; i < dataPtr->numSubTables; i++) { dataPtr->prefixBytes[UCHAR(dataPtr->subTables[i].sequence[0])] = 1; } if (dataPtr->init[0] != '\0') { dataPtr->prefixBytes[UCHAR(dataPtr->init[0])] = 1; } if (dataPtr->final[0] != '\0') { dataPtr->prefixBytes[UCHAR(dataPtr->final[0])] = 1; } /* * Package everything into an encoding structure. */ type.encodingName = name; type.toUtfProc = EscapeToUtfProc; type.fromUtfProc = EscapeFromUtfProc; type.freeProc = EscapeFreeProc; type.nullSize = 1; type.clientData = dataPtr; return Tcl_CreateEncoding(&type); } /* *------------------------------------------------------------------------- * * BinaryProc -- * * The default conversion when no other conversion is specified. No * translation is done; source bytes are copied directly to destination * bytes. * * Results: * Returns TCL_OK if conversion was successful. * * Side effects: * None. * *------------------------------------------------------------------------- */ static int BinaryProc( ClientData clientData, /* Not used. */ const char *src, /* Source string (unknown encoding). */ 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. */ 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. */ { int result; result = TCL_OK; dstLen -= TCL_UTF_MAX - 1; if (dstLen < 0) { dstLen = 0; } if ((flags & TCL_ENCODING_CHAR_LIMIT) && srcLen > *dstCharsPtr) { srcLen = *dstCharsPtr; } if (srcLen > dstLen) { srcLen = dstLen; result = TCL_CONVERT_NOSPACE; } *srcReadPtr = srcLen; *dstWrotePtr = srcLen; *dstCharsPtr = srcLen; memcpy(dst, src, (size_t) srcLen); return result; } /* *------------------------------------------------------------------------- * * UtfExtToUtfIntProc -- * * 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, /* Not used. */ 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, /* Not used. */ 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 * is not a no-op, because it will turn a stream of improperly formed * UTF-8 into a properly formed stream. * * Results: * Returns TCL_OK if conversion was successful. * * Side effects: * None. * *------------------------------------------------------------------------- */ static int UtfToUtfProc( ClientData clientData, /* Not used. */ 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. */ int pureNullMode) /* Convert embedded nulls from internal * representation to real null-bytes or vice * versa. */ { const char *srcStart, *srcEnd, *srcClose; const char *dstStart, *dstEnd; int result, numChars, charLimit = INT_MAX; Tcl_UniChar ch; result = TCL_OK; srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; if ((flags & TCL_ENCODING_END) == 0) { srcClose -= TCL_UTF_MAX; } if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; } dstStart = dst; dstEnd = dst + dstLen - TCL_UTF_MAX; for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) { 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. */ result = TCL_CONVERT_MULTIBYTE; break; } if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } if (UCHAR(*src) < 0x80 && !(UCHAR(*src) == 0 && pureNullMode == 0)) { /* * Copy 7bit chatacters, but skip null-bytes when we are in input * mode, so that they get converted to 0xc080. */ *dst++ = *src++; } else if (pureNullMode == 1 && UCHAR(*src) == 0xc0 && (src + 1 < srcEnd) && UCHAR(*(src+1)) == 0x80) { /* * Convert 0xc080 to real nulls when we are in output mode. */ *dst++ = 0; src += 2; } else if (!Tcl_UtfCharComplete(src, srcEnd - src)) { /* * Always check before using Tcl_UtfToUniChar. Not doing can so * cause it run beyond the endof the buffer! If we happen such an * incomplete char its byts are made to represent themselves. */ ch = (unsigned char) *src; src += 1; dst += Tcl_UniCharToUtf(ch, dst); } else { src += Tcl_UtfToUniChar(src, &ch); dst += Tcl_UniCharToUtf(ch, dst); } } *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } /* *------------------------------------------------------------------------- * * UnicodeToUtfProc -- * * Convert from Unicode to UTF-8. * * Results: * Returns TCL_OK if conversion was successful. * * Side effects: * None. * *------------------------------------------------------------------------- */ static int UnicodeToUtfProc( ClientData clientData, /* Not used. */ const char *src, /* Source string in Unicode. */ 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. */ { const char *srcStart, *srcEnd; const char *dstEnd, *dstStart; int result, numChars, charLimit = INT_MAX; Tcl_UniChar ch; if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; } result = TCL_OK; if ((srcLen % sizeof(Tcl_UniChar)) != 0) { result = TCL_CONVERT_MULTIBYTE; srcLen /= sizeof(Tcl_UniChar); srcLen *= sizeof(Tcl_UniChar); } srcStart = src; srcEnd = src + srcLen; dstStart = dst; dstEnd = dst + dstLen - TCL_UTF_MAX; for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) { if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } /* * Special case for 1-byte utf chars for speed. Make sure we work with * Tcl_UniChar-size data. */ ch = *(Tcl_UniChar *)src; if (ch && ch < 0x80) { *dst++ = (ch & 0xFF); } else { dst += Tcl_UniCharToUtf(ch, dst); } src += sizeof(Tcl_UniChar); } *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } /* *------------------------------------------------------------------------- * * UtfToUnicodeProc -- * * Convert from UTF-8 to Unicode. * * Results: * Returns TCL_OK if conversion was successful. * * Side effects: * None. * *------------------------------------------------------------------------- */ static int UtfToUnicodeProc( ClientData clientData, /* TableEncodingData that specifies * encoding. */ 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. */ { const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd; int result, numChars; Tcl_UniChar ch; srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; if ((flags & TCL_ENCODING_END) == 0) { srcClose -= TCL_UTF_MAX; } dstStart = dst; dstEnd = dst + dstLen - sizeof(Tcl_UniChar); result = TCL_OK; for (numChars = 0; src < srcEnd; numChars++) { 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. */ result = TCL_CONVERT_MULTIBYTE; break; } if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } src += TclUtfToUniChar(src, &ch); /* * Need to handle this in a way that won't cause misalignment by * casting dst to a Tcl_UniChar. [Bug 1122671] */ #ifdef WORDS_BIGENDIAN #if TCL_UTF_MAX > 4 *dst++ = (ch >> 24); *dst++ = ((ch >> 16) & 0xFF); *dst++ = ((ch >> 8) & 0xFF); *dst++ = (ch & 0xFF); #else *dst++ = (ch >> 8); *dst++ = (ch & 0xFF); #endif #else #if TCL_UTF_MAX > 4 *dst++ = (ch & 0xFF); *dst++ = ((ch >> 8) & 0xFF); *dst++ = ((ch >> 16) & 0xFF); *dst++ = (ch >> 24); #else *dst++ = (ch & 0xFF); *dst++ = (ch >> 8); #endif #endif } *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } /* *------------------------------------------------------------------------- * * TableToUtfProc -- * * Convert from the encoding specified by the TableEncodingData into * UTF-8. * * Results: * Returns TCL_OK if conversion was successful. * * Side effects: * None. * *------------------------------------------------------------------------- */ static int TableToUtfProc( ClientData clientData, /* TableEncodingData that specifies * encoding. */ const char *src, /* Source string in specified encoding. */ 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. */ { const char *srcStart, *srcEnd; const char *dstEnd, *dstStart, *prefixBytes; int result, byte, numChars, charLimit = INT_MAX; Tcl_UniChar ch; const unsigned short *const *toUnicode; const unsigned short *pageZero; TableEncodingData *dataPtr = clientData; if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; } srcStart = src; srcEnd = src + srcLen; dstStart = dst; dstEnd = dst + dstLen - TCL_UTF_MAX; toUnicode = (const unsigned short *const *) dataPtr->toUnicode; prefixBytes = dataPtr->prefixBytes; pageZero = toUnicode[0]; result = TCL_OK; for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) { if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } byte = *((unsigned char *) src); if (prefixBytes[byte]) { src++; if (src >= srcEnd) { src--; result = TCL_CONVERT_MULTIBYTE; break; } ch = toUnicode[byte][*((unsigned char *) src)]; } else { ch = pageZero[byte]; } if ((ch == 0) && (byte != 0)) { if (flags & TCL_ENCODING_STOPONERROR) { result = TCL_CONVERT_SYNTAX; break; } if (prefixBytes[byte]) { src--; } ch = (Tcl_UniChar) byte; } /* * Special case for 1-byte utf chars for speed. */ if (ch && ch < 0x80) { *dst++ = (char) ch; } else { dst += Tcl_UniCharToUtf(ch, dst); } src++; } *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } /* *------------------------------------------------------------------------- * * TableFromUtfProc -- * * Convert from UTF-8 into the encoding specified by the * TableEncodingData. * * Results: * Returns TCL_OK if conversion was successful. * * Side effects: * None. * *------------------------------------------------------------------------- */ static int TableFromUtfProc( ClientData clientData, /* TableEncodingData that specifies * encoding. */ 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. */ { const char *srcStart, *srcEnd, *srcClose; const char *dstStart, *dstEnd, *prefixBytes; Tcl_UniChar ch; int result, len, word, numChars; TableEncodingData *dataPtr = clientData; const unsigned short *const *fromUnicode; result = TCL_OK; prefixBytes = dataPtr->prefixBytes; fromUnicode = (const unsigned short *const *) dataPtr->fromUnicode; srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; if ((flags & TCL_ENCODING_END) == 0) { srcClose -= TCL_UTF_MAX; } dstStart = dst; dstEnd = dst + dstLen - 1; for (numChars = 0; src < srcEnd; numChars++) { 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. */ result = TCL_CONVERT_MULTIBYTE; break; } len = TclUtfToUniChar(src, &ch); #if TCL_UTF_MAX > 3 /* * This prevents a crash condition. More evaluation is required for * full support of int Tcl_UniChar. [Bug 1004065] */ if (ch & 0xffff0000) { word = 0; } else #endif word = fromUnicode[(ch >> 8)][ch & 0xff]; if ((word == 0) && (ch != 0)) { if (flags & TCL_ENCODING_STOPONERROR) { result = TCL_CONVERT_UNKNOWN; break; } word = dataPtr->fallback; } if (prefixBytes[(word >> 8)] != 0) { if (dst + 1 > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } dst[0] = (char) (word >> 8); dst[1] = (char) word; dst += 2; } else { if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } dst[0] = (char) word; dst++; } src += len; } *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } /* *------------------------------------------------------------------------- * * Iso88591ToUtfProc -- * * Convert from the "iso8859-1" encoding into UTF-8. * * Results: * Returns TCL_OK if conversion was successful. * * Side effects: * None. * *------------------------------------------------------------------------- */ static int Iso88591ToUtfProc( ClientData clientData, /* Ignored. */ const char *src, /* Source string in specified encoding. */ 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. */ { const char *srcStart, *srcEnd; const char *dstEnd, *dstStart; int result, numChars, charLimit = INT_MAX; if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; } srcStart = src; srcEnd = src + srcLen; dstStart = dst; dstEnd = dst + dstLen - TCL_UTF_MAX; result = TCL_OK; for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) { Tcl_UniChar ch; if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } ch = (Tcl_UniChar) *((unsigned char *) src); /* * Special case for 1-byte utf chars for speed. */ if (ch && ch < 0x80) { *dst++ = (char) ch; } else { dst += Tcl_UniCharToUtf(ch, dst); } src++; } *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } /* *------------------------------------------------------------------------- * * Iso88591FromUtfProc -- * * Convert from UTF-8 into the encoding "iso8859-1". * * Results: * Returns TCL_OK if conversion was successful. * * Side effects: * None. * *------------------------------------------------------------------------- */ static int Iso88591FromUtfProc( ClientData clientData, /* Ignored. */ 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. */ { const char *srcStart, *srcEnd, *srcClose; const char *dstStart, *dstEnd; int result, numChars; result = TCL_OK; srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; if ((flags & TCL_ENCODING_END) == 0) { srcClose -= TCL_UTF_MAX; } dstStart = dst; dstEnd = dst + dstLen - 1; for (numChars = 0; src < srcEnd; numChars++) { Tcl_UniChar ch; int len; 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. */ result = TCL_CONVERT_MULTIBYTE; break; } len = TclUtfToUniChar(src, &ch); /* * Check for illegal characters. */ if (ch > 0xff) { if (flags & TCL_ENCODING_STOPONERROR) { result = TCL_CONVERT_UNKNOWN; break; } /* * Plunge on, using '?' as a fallback character. */ ch = (Tcl_UniChar) '?'; } if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } *(dst++) = (char) ch; src += len; } *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } /* *--------------------------------------------------------------------------- * * TableFreeProc -- * * This function is invoked when an encoding is deleted. It deletes the * memory used by the TableEncodingData. * * Results: * None. * * Side effects: * Memory freed. * *--------------------------------------------------------------------------- */ static void TableFreeProc( ClientData clientData) /* TableEncodingData that specifies * encoding. */ { TableEncodingData *dataPtr = clientData; /* * Make sure we aren't freeing twice on shutdown. [Bug 219314] */ ckfree(dataPtr->toUnicode); dataPtr->toUnicode = NULL; ckfree(dataPtr->fromUnicode); dataPtr->fromUnicode = NULL; ckfree(dataPtr); } /* *------------------------------------------------------------------------- * * EscapeToUtfProc -- * * Convert from the encoding specified by the EscapeEncodingData into * UTF-8. * * Results: * Returns TCL_OK if conversion was successful. * * Side effects: * None. * *------------------------------------------------------------------------- */ static int EscapeToUtfProc( ClientData clientData, /* EscapeEncodingData that specifies * encoding. */ const char *src, /* Source string in specified encoding. */ 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. */ { EscapeEncodingData *dataPtr = clientData; const char *prefixBytes, *tablePrefixBytes, *srcStart, *srcEnd; const unsigned short *const *tableToUnicode; const Encoding *encodingPtr; int state, result, numChars, charLimit = INT_MAX; const char *dstStart, *dstEnd; if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; } result = TCL_OK; tablePrefixBytes = NULL; /* lint. */ tableToUnicode = NULL; /* lint. */ prefixBytes = dataPtr->prefixBytes; encodingPtr = NULL; srcStart = src; srcEnd = src + srcLen; dstStart = dst; dstEnd = dst + dstLen - TCL_UTF_MAX; state = PTR2INT(*statePtr); if (flags & TCL_ENCODING_START) { state = 0; } for (numChars = 0; src < srcEnd && numChars <= charLimit; ) { int byte, hi, lo, ch; if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } byte = *((unsigned char *) src); if (prefixBytes[byte]) { unsigned left, len, longest; int checked, i; const EscapeSubTable *subTablePtr; /* * Saw the beginning of an escape sequence. */ left = srcEnd - src; len = dataPtr->initLen; longest = len; checked = 0; if (len <= left) { checked++; if ((len > 0) && (memcmp(src, dataPtr->init, len) == 0)) { /* * If we see initialization string, skip it, even if we're * not at the beginning of the buffer. */ src += len; continue; } } len = dataPtr->finalLen; if (len > longest) { longest = len; } if (len <= left) { checked++; if ((len > 0) && (memcmp(src, dataPtr->final, len) == 0)) { /* * If we see finalization string, skip it, even if we're * not at the end of the buffer. */ src += len; continue; } } subTablePtr = dataPtr->subTables; for (i = 0; i < dataPtr->numSubTables; i++) { len = subTablePtr->sequenceLen; if (len > longest) { longest = len; } if (len <= left) { checked++; if ((len > 0) && (memcmp(src, subTablePtr->sequence, len) == 0)) { state = i; encodingPtr = NULL; subTablePtr = NULL; src += len; break; } } subTablePtr++; } if (subTablePtr == NULL) { /* * A match was found, the escape sequence was consumed, and * the state was updated. */ continue; } /* * We have a split-up or unrecognized escape sequence. If we * checked all the sequences, then it's a syntax error, otherwise * we need more bytes to determine a match. */ if ((checked == dataPtr->numSubTables + 2) || (flags & TCL_ENCODING_END)) { if ((flags & TCL_ENCODING_STOPONERROR) == 0) { /* * Skip the unknown escape sequence. */ src += longest; continue; } result = TCL_CONVERT_SYNTAX; } else { result = TCL_CONVERT_MULTIBYTE; } break; } if (encodingPtr == NULL) { TableEncodingData *tableDataPtr; encodingPtr = GetTableEncoding(dataPtr, state); tableDataPtr = encodingPtr->clientData; tablePrefixBytes = tableDataPtr->prefixBytes; tableToUnicode = (const unsigned short *const*) tableDataPtr->toUnicode; } if (tablePrefixBytes[byte]) { src++; if (src >= srcEnd) { src--; result = TCL_CONVERT_MULTIBYTE; break; } hi = byte; lo = *((unsigned char *) src); } else { hi = 0; lo = byte; } ch = tableToUnicode[hi][lo]; dst += Tcl_UniCharToUtf(ch, dst); src++; numChars++; } *statePtr = (Tcl_EncodingState) INT2PTR(state); *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } /* *------------------------------------------------------------------------- * * EscapeFromUtfProc -- * * Convert from UTF-8 into the encoding specified by the * EscapeEncodingData. * * Results: * Returns TCL_OK if conversion was successful. * * Side effects: * None. * *------------------------------------------------------------------------- */ static int EscapeFromUtfProc( ClientData clientData, /* EscapeEncodingData that specifies * encoding. */ 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. */ { EscapeEncodingData *dataPtr = clientData; const Encoding *encodingPtr; const char *srcStart, *srcEnd, *srcClose; const char *dstStart, *dstEnd; int state, result, numChars; const TableEncodingData *tableDataPtr; const char *tablePrefixBytes; const unsigned short *const *tableFromUnicode; result = TCL_OK; srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; if ((flags & TCL_ENCODING_END) == 0) { srcClose -= TCL_UTF_MAX; } dstStart = dst; dstEnd = dst + dstLen - 1; /* * RFC 1468 states that the text starts in ASCII, and switches to Japanese * characters, and that the text must end in ASCII. [Patch 474358] */ if (flags & TCL_ENCODING_START) { state = 0; if ((dst + dataPtr->initLen) > dstEnd) { *srcReadPtr = 0; *dstWrotePtr = 0; return TCL_CONVERT_NOSPACE; } memcpy(dst, dataPtr->init, (size_t)dataPtr->initLen); dst += dataPtr->initLen; } else { state = PTR2INT(*statePtr); } encodingPtr = GetTableEncoding(dataPtr, state); tableDataPtr = encodingPtr->clientData; tablePrefixBytes = tableDataPtr->prefixBytes; tableFromUnicode = (const unsigned short *const *) tableDataPtr->fromUnicode; for (numChars = 0; src < srcEnd; numChars++) { unsigned len; int word; Tcl_UniChar ch; 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. */ result = TCL_CONVERT_MULTIBYTE; break; } len = TclUtfToUniChar(src, &ch); word = tableFromUnicode[(ch >> 8)][ch & 0xff]; if ((word == 0) && (ch != 0)) { int oldState; const EscapeSubTable *subTablePtr; oldState = state; for (state = 0; state < dataPtr->numSubTables; state++) { encodingPtr = GetTableEncoding(dataPtr, state); tableDataPtr = encodingPtr->clientData; word = tableDataPtr->fromUnicode[(ch >> 8)][ch & 0xff]; if (word != 0) { break; } } if (word == 0) { state = oldState; if (flags & TCL_ENCODING_STOPONERROR) { result = TCL_CONVERT_UNKNOWN; break; } encodingPtr = GetTableEncoding(dataPtr, state); tableDataPtr = encodingPtr->clientData; word = tableDataPtr->fallback; } tablePrefixBytes = (const char *) tableDataPtr->prefixBytes; tableFromUnicode = (const unsigned short *const *) tableDataPtr->fromUnicode; /* * The state variable has the value of oldState when word is 0. * In this case, the escape sequense should not be copied to dst * because the current character set is not changed. */ if (state != oldState) { subTablePtr = &dataPtr->subTables[state]; if ((dst + subTablePtr->sequenceLen) > dstEnd) { /* * If there is no space to write the escape sequence, the * state variable must be changed to the value of oldState * variable because this escape sequence must be written * in the next conversion. */ state = oldState; result = TCL_CONVERT_NOSPACE; break; } memcpy(dst, subTablePtr->sequence, (size_t) subTablePtr->sequenceLen); dst += subTablePtr->sequenceLen; } } if (tablePrefixBytes[(word >> 8)] != 0) { if (dst + 1 > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } dst[0] = (char) (word >> 8); dst[1] = (char) word; dst += 2; } else { if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } dst[0] = (char) word; dst++; } src += len; } if ((result == TCL_OK) && (flags & TCL_ENCODING_END)) { unsigned len = dataPtr->subTables[0].sequenceLen; /* * Certain encodings like iso2022-jp need to write an escape sequence * after all characters have been converted. This logic checks that * enough room is available in the buffer for the escape bytes. The * TCL_ENCODING_END flag is cleared after a final escape sequence has * been added to the buffer so that another call to this method does * not attempt to append escape bytes a second time. */ if ((dst + dataPtr->finalLen + (state?len:0)) > dstEnd) { result = TCL_CONVERT_NOSPACE; } else { if (state) { memcpy(dst, dataPtr->subTables[0].sequence, len); dst += len; } memcpy(dst, dataPtr->final, (size_t) dataPtr->finalLen); dst += dataPtr->finalLen; state &= ~TCL_ENCODING_END; } } *statePtr = (Tcl_EncodingState) INT2PTR(state); *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } /* *--------------------------------------------------------------------------- * * EscapeFreeProc -- * * This function is invoked when an EscapeEncodingData encoding is * deleted. It deletes the memory used by the encoding. * * Results: * None. * * Side effects: * Memory freed. * *--------------------------------------------------------------------------- */ static void EscapeFreeProc( ClientData clientData) /* EscapeEncodingData that specifies * encoding. */ { EscapeEncodingData *dataPtr = clientData; EscapeSubTable *subTablePtr; int i; if (dataPtr == NULL) { return; } /* * The subTables should be freed recursively in normal operation but not * during TclFinalizeEncodingSubsystem because they are also present as a * weak reference in the toplevel encodingTable (i.e., they don't have a * +1 refcount for this), and unpredictable nuking order could remove them * from under the following loop's feet. [Bug 2891556] * * The encodingsInitialized flag, being reset on entry to TFES, can serve * as a "not in finalization" test. */ if (encodingsInitialized) { subTablePtr = dataPtr->subTables; for (i = 0; i < dataPtr->numSubTables; i++) { FreeEncoding((Tcl_Encoding) subTablePtr->encodingPtr); subTablePtr->encodingPtr = NULL; subTablePtr++; } } ckfree(dataPtr); } /* *--------------------------------------------------------------------------- * * GetTableEncoding -- * * Helper function for the EscapeEncodingData conversions. Gets the * encoding (of type TextEncodingData) that represents the specified * state. * * Results: * The return value is the encoding. * * Side effects: * If the encoding that represents the specified state has not already * been used by this EscapeEncoding, it will be loaded and cached in the * dataPtr. * *--------------------------------------------------------------------------- */ static Encoding * GetTableEncoding( EscapeEncodingData *dataPtr,/* Contains names of encodings. */ int state) /* Index in dataPtr of desired Encoding. */ { EscapeSubTable *subTablePtr = &dataPtr->subTables[state]; Encoding *encodingPtr = subTablePtr->encodingPtr; if (encodingPtr == NULL) { encodingPtr = (Encoding *) Tcl_GetEncoding(NULL, subTablePtr->name); if ((encodingPtr == NULL) || (encodingPtr->toUtfProc != TableToUtfProc && encodingPtr->toUtfProc != Iso88591ToUtfProc)) { Tcl_Panic("EscapeToUtfProc: invalid sub table"); } subTablePtr->encodingPtr = encodingPtr; } return encodingPtr; } /* *--------------------------------------------------------------------------- * * unilen -- * * A helper function for the Tcl_ExternalToUtf functions. This function * is similar to strlen for double-byte characters: it returns the number * of bytes in a 0x0000 terminated string. * * Results: * As above. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static size_t unilen( const char *src) { unsigned short *p; p = (unsigned short *) src; while (*p != 0x0000) { p++; } return (char *) p - src; } /* *------------------------------------------------------------------------- * * InitializeEncodingSearchPath -- * * This is the fallback routine that sets the default value of the * encoding search path if the application has not set one via a call to * Tcl_SetEncodingSearchPath() by the first time the search path is needed * to load encoding data. * * The default encoding search path is produced by taking each directory * in the library path, appending a subdirectory named "encoding", and if * the resulting directory exists, adding it to the encoding search path. * * Results: * None. * * Side effects: * Sets the encoding search path to an initial value. * *------------------------------------------------------------------------- */ static void InitializeEncodingSearchPath( char **valuePtr, int *lengthPtr, Tcl_Encoding *encodingPtr) { const char *bytes; int i, numDirs, numBytes; Tcl_Obj *libPathObj, *encodingObj, *searchPathObj; TclNewLiteralStringObj(encodingObj, "encoding"); TclNewObj(searchPathObj); Tcl_IncrRefCount(encodingObj); Tcl_IncrRefCount(searchPathObj); libPathObj = TclGetLibraryPath(); Tcl_IncrRefCount(libPathObj); Tcl_ListObjLength(NULL, libPathObj, &numDirs); for (i = 0; i < numDirs; i++) { Tcl_Obj *directoryObj, *pathObj; Tcl_StatBuf stat; Tcl_ListObjIndex(NULL, libPathObj, i, &directoryObj); pathObj = Tcl_FSJoinToPath(directoryObj, 1, &encodingObj); Tcl_IncrRefCount(pathObj); if ((0 == Tcl_FSStat(pathObj, &stat)) && S_ISDIR(stat.st_mode)) { Tcl_ListObjAppendElement(NULL, searchPathObj, pathObj); } Tcl_DecrRefCount(pathObj); } Tcl_DecrRefCount(libPathObj); Tcl_DecrRefCount(encodingObj); *encodingPtr = libraryPath.encoding; if (*encodingPtr) { ((Encoding *)(*encodingPtr))->refCount++; } bytes = Tcl_GetStringFromObj(searchPathObj, &numBytes); *lengthPtr = numBytes; *valuePtr = ckalloc(numBytes + 1); memcpy(*valuePtr, bytes, (size_t) numBytes + 1); Tcl_DecrRefCount(searchPathObj); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclCmdIL.c0000644000175000017500000035673412663660065015024 0ustar sergeisergei/* * tclCmdIL.c -- * * This file contains the top-level command routines for most of the Tcl * built-in commands whose names begin with the letters I through L. It * contains only commands in the generic core (i.e., those that don't * depend much upon UNIX facilities). * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1993-1997 Lucent Technologies. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2005 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclRegexp.h" /* * During execution of the "lsort" command, structures of the following type * are used to arrange the objects being sorted into a collection of linked * lists. */ typedef struct SortElement { union { /* The value that we sorting by. */ const char *strValuePtr; Tcl_WideInt wideValue; double doubleValue; Tcl_Obj *objValuePtr; } collationKey; union { /* Object being sorted, or its index. */ Tcl_Obj *objPtr; int index; } payload; struct SortElement *nextPtr;/* Next element in the list, or NULL for end * of list. */ } SortElement; /* * These function pointer types are used with the "lsearch" and "lsort" * commands to facilitate the "-nocase" option. */ typedef int (*SortStrCmpFn_t) (const char *, const char *); typedef int (*SortMemCmpFn_t) (const void *, const void *, size_t); /* * The "lsort" command needs to pass certain information down to the function * that compares two list elements, and the comparison function needs to pass * success or failure information back up to the top-level "lsort" command. * The following structure is used to pass this information. */ typedef struct SortInfo { int isIncreasing; /* Nonzero means sort in increasing order. */ int sortMode; /* The sort mode. One of SORTMODE_* values * defined below. */ Tcl_Obj *compareCmdPtr; /* The Tcl comparison command when sortMode is * SORTMODE_COMMAND. Pre-initialized to hold * base of command. */ int *indexv; /* If the -index option was specified, this * holds the indexes contained in the list * supplied as an argument to that option. * NULL if no indexes supplied, and points to * singleIndex field when only one * supplied. */ int indexc; /* Number of indexes in indexv array. */ int singleIndex; /* Static space for common index case. */ int unique; int numElements; Tcl_Interp *interp; /* The interpreter in which the sort is being * done. */ int resultCode; /* Completion code for the lsort command. If * an error occurs during the sort this is * changed from TCL_OK to TCL_ERROR. */ } SortInfo; /* * The "sortMode" field of the SortInfo structure can take on any of the * following values. */ #define SORTMODE_ASCII 0 #define SORTMODE_INTEGER 1 #define SORTMODE_REAL 2 #define SORTMODE_COMMAND 3 #define SORTMODE_DICTIONARY 4 #define SORTMODE_ASCII_NC 8 /* * Magic values for the index field of the SortInfo structure. Note that the * index "end-1" will be translated to SORTIDX_END-1, etc. */ #define SORTIDX_NONE -1 /* Not indexed; use whole value. */ #define SORTIDX_END -2 /* Indexed from end. */ /* * Forward declarations for procedures defined in this file: */ static int DictionaryCompare(const char *left, const char *right); static int IfConditionCallback(ClientData data[], Tcl_Interp *interp, int result); static int InfoArgsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoBodyCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoCmdCountCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoCommandsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoCompleteCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoDefaultCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* TIP #348 - New 'info' subcommand 'errorstack' */ static int InfoErrorStackCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* TIP #280 - New 'info' subcommand 'frame' */ static int InfoFrameCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoFunctionsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoHostnameCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoLevelCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoLibraryCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoLoadedCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoNameOfExecutableCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoPatchLevelCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoProcsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoScriptCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoSharedlibCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int InfoTclVersionCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static SortElement * MergeLists(SortElement *leftPtr, SortElement *rightPtr, SortInfo *infoPtr); static int SortCompare(SortElement *firstPtr, SortElement *second, SortInfo *infoPtr); static Tcl_Obj * SelectObjFromSublist(Tcl_Obj *firstPtr, SortInfo *infoPtr); /* * Array of values describing how to implement each standard subcommand of the * "info" command. */ static const EnsembleImplMap defaultInfoMap[] = { {"args", InfoArgsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"body", InfoBodyCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"cmdcount", InfoCmdCountCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"commands", InfoCommandsCmd, TclCompileInfoCommandsCmd, NULL, NULL, 0}, {"complete", InfoCompleteCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"coroutine", TclInfoCoroutineCmd, TclCompileInfoCoroutineCmd, NULL, NULL, 0}, {"default", InfoDefaultCmd, TclCompileBasic3ArgCmd, NULL, NULL, 0}, {"errorstack", InfoErrorStackCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"exists", TclInfoExistsCmd, TclCompileInfoExistsCmd, NULL, NULL, 0}, {"frame", InfoFrameCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"functions", InfoFunctionsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"globals", TclInfoGlobalsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"hostname", InfoHostnameCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"level", InfoLevelCmd, TclCompileInfoLevelCmd, NULL, NULL, 0}, {"library", InfoLibraryCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"loaded", InfoLoadedCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"locals", TclInfoLocalsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"nameofexecutable", InfoNameOfExecutableCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"patchlevel", InfoPatchLevelCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"procs", InfoProcsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"script", InfoScriptCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"sharedlibextension", InfoSharedlibCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"tclversion", InfoTclVersionCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"vars", TclInfoVarsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* *---------------------------------------------------------------------- * * Tcl_IfObjCmd -- * * This procedure is invoked to process the "if" Tcl command. See the * user documentation for details on what it does. * * With the bytecode compiler, this procedure is only called when a * command name is computed at runtime, and is "if" or the name to which * "if" was renamed: e.g., "set z if; $z 1 {puts foo}" * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_IfObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRIfObjCmd, dummy, objc, objv); } int TclNRIfObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *boolObj; if (objc <= 1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: no expression after \"%s\" argument", TclGetString(objv[0]))); Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); return TCL_ERROR; } /* * At this point, objv[1] refers to the main expression to test. The * arguments after the expression must be "then" (optional) and a script * to execute if the expression is true. */ TclNewObj(boolObj); Tcl_NRAddCallback(interp, IfConditionCallback, INT2PTR(objc), (ClientData) objv, INT2PTR(1), boolObj); return Tcl_NRExprObj(interp, objv[1], boolObj); } static int IfConditionCallback( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; int objc = PTR2INT(data[0]); Tcl_Obj *const *objv = data[1]; int i = PTR2INT(data[2]); Tcl_Obj *boolObj = data[3]; int value, thenScriptIndex = 0; const char *clause; if (result != TCL_OK) { TclDecrRefCount(boolObj); return result; } if (Tcl_GetBooleanFromObj(interp, boolObj, &value) != TCL_OK) { TclDecrRefCount(boolObj); return TCL_ERROR; } TclDecrRefCount(boolObj); while (1) { i++; if (i >= objc) { goto missingScript; } clause = TclGetString(objv[i]); if ((i < objc) && (strcmp(clause, "then") == 0)) { i++; } if (i >= objc) { goto missingScript; } if (value) { thenScriptIndex = i; value = 0; } /* * The expression evaluated to false. Skip the command, then see if * there is an "else" or "elseif" clause. */ i++; if (i >= objc) { if (thenScriptIndex) { /* * TIP #280. Make invoking context available to branch. */ return TclNREvalObjEx(interp, objv[thenScriptIndex], 0, iPtr->cmdFramePtr, thenScriptIndex); } return TCL_OK; } clause = TclGetString(objv[i]); if ((clause[0] != 'e') || (strcmp(clause, "elseif") != 0)) { break; } i++; /* * At this point in the loop, objv and objc refer to an expression to * test, either for the main expression or an expression following an * "elseif". The arguments after the expression must be "then" * (optional) and a script to execute if the expression is true. */ if (i >= objc) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: no expression after \"%s\" argument", clause)); Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); return TCL_ERROR; } if (!thenScriptIndex) { TclNewObj(boolObj); Tcl_NRAddCallback(interp, IfConditionCallback, data[0], data[1], INT2PTR(i), boolObj); return Tcl_NRExprObj(interp, objv[i], boolObj); } } /* * Couldn't find a "then" or "elseif" clause to execute. Check now for an * "else" clause. We know that there's at least one more argument when we * get here. */ if (strcmp(clause, "else") == 0) { i++; if (i >= objc) { goto missingScript; } } if (i < objc - 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "wrong # args: extra words after \"else\" clause in \"if\" command", -1)); Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); return TCL_ERROR; } if (thenScriptIndex) { /* * TIP #280. Make invoking context available to branch/else. */ return TclNREvalObjEx(interp, objv[thenScriptIndex], 0, iPtr->cmdFramePtr, thenScriptIndex); } return TclNREvalObjEx(interp, objv[i], 0, iPtr->cmdFramePtr, i); missingScript: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "wrong # args: no script following \"%s\" argument", TclGetString(objv[i-1]))); Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_IncrObjCmd -- * * This procedure is invoked to process the "incr" Tcl command. See the * user documentation for details on what it does. * * With the bytecode compiler, this procedure is only called when a * command name is computed at runtime, and is "incr" or the name to * which "incr" was renamed: e.g., "set z incr; $z i -1" * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_IncrObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *newValuePtr, *incrPtr; if ((objc != 2) && (objc != 3)) { Tcl_WrongNumArgs(interp, 1, objv, "varName ?increment?"); return TCL_ERROR; } if (objc == 3) { incrPtr = objv[2]; } else { incrPtr = Tcl_NewIntObj(1); } Tcl_IncrRefCount(incrPtr); newValuePtr = TclIncrObjVar2(interp, objv[1], NULL, incrPtr, TCL_LEAVE_ERR_MSG); Tcl_DecrRefCount(incrPtr); if (newValuePtr == NULL) { return TCL_ERROR; } /* * Set the interpreter's object result to refer to the variable's new * value object. */ Tcl_SetObjResult(interp, newValuePtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclInitInfoCmd -- * * This function is called to create the "info" Tcl command. See the user * documentation for details on what it does. * * Results: * Handle for the info command, or NULL on failure. * * Side effects: * none * *---------------------------------------------------------------------- */ Tcl_Command TclInitInfoCmd( Tcl_Interp *interp) /* Current interpreter. */ { return TclMakeEnsemble(interp, "info", defaultInfoMap); } /* *---------------------------------------------------------------------- * * InfoArgsCmd -- * * Called to implement the "info args" command that returns the argument * list for a procedure. Handles the following syntax: * * info args procName * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoArgsCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register Interp *iPtr = (Interp *) interp; const char *name; Proc *procPtr; CompiledLocal *localPtr; Tcl_Obj *listObjPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "procname"); return TCL_ERROR; } name = TclGetString(objv[1]); procPtr = TclFindProc(iPtr, name); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't a procedure", name)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, NULL); return TCL_ERROR; } /* * Build a return list containing the arguments. */ listObjPtr = Tcl_NewListObj(0, NULL); for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; localPtr = localPtr->nextPtr) { if (TclIsVarArgument(localPtr)) { Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj(localPtr->name, -1)); } } Tcl_SetObjResult(interp, listObjPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * InfoBodyCmd -- * * Called to implement the "info body" command that returns the body for * a procedure. Handles the following syntax: * * info body procName * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoBodyCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register Interp *iPtr = (Interp *) interp; const char *name; Proc *procPtr; Tcl_Obj *bodyPtr, *resultPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "procname"); return TCL_ERROR; } name = TclGetString(objv[1]); procPtr = TclFindProc(iPtr, name); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't a procedure", name)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", name, NULL); return TCL_ERROR; } /* * Here we used to return procPtr->bodyPtr, except when the body was * bytecompiled - in that case, the return was a copy of the body's string * rep. In order to better isolate the implementation details of the * compiler/engine subsystem, we now always return a copy of the string * rep. It is important to return a copy so that later manipulations of * the object do not invalidate the internal rep. */ bodyPtr = procPtr->bodyPtr; if (bodyPtr->bytes == NULL) { /* * The string rep might not be valid if the procedure has never been * run before. [Bug #545644] */ TclGetString(bodyPtr); } resultPtr = Tcl_NewStringObj(bodyPtr->bytes, bodyPtr->length); Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * InfoCmdCountCmd -- * * Called to implement the "info cmdcount" command that returns the * number of commands that have been executed. Handles the following * syntax: * * info cmdcount * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoCmdCountCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(iPtr->cmdCount)); return TCL_OK; } /* *---------------------------------------------------------------------- * * InfoCommandsCmd -- * * Called to implement the "info commands" command that returns the list * of commands in the interpreter that match an optional pattern. The * pattern, if any, consists of an optional sequence of namespace names * separated by "::" qualifiers, which is followed by a glob-style * pattern that restricts which commands are returned. Handles the * following syntax: * * info commands ?pattern? * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoCommandsCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *cmdName, *pattern; const char *simplePattern; register Tcl_HashEntry *entryPtr; Tcl_HashSearch search; Namespace *nsPtr; Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp); Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); Tcl_Obj *listPtr, *elemObjPtr; int specificNsInPattern = 0;/* Init. to avoid compiler warning. */ Tcl_Command cmd; int i; /* * Get the pattern and find the "effective namespace" in which to list * commands. */ if (objc == 1) { simplePattern = NULL; nsPtr = currNsPtr; specificNsInPattern = 0; } else if (objc == 2) { /* * From the pattern, get the effective namespace and the simple * pattern (no namespace qualifiers or ::'s) at the end. If an error * was found while parsing the pattern, return it. Otherwise, if the * namespace wasn't found, just leave nsPtr NULL: we will return an * empty list since no commands there can be found. */ Namespace *dummy1NsPtr, *dummy2NsPtr; pattern = TclGetString(objv[1]); TclGetNamespaceForQualName(interp, pattern, NULL, 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern); if (nsPtr != NULL) { /* We successfully found the pattern's ns. */ specificNsInPattern = (strcmp(simplePattern, pattern) != 0); } } else { Tcl_WrongNumArgs(interp, 1, objv, "?pattern?"); return TCL_ERROR; } /* * Exit as quickly as possible if we couldn't find the namespace. */ if (nsPtr == NULL) { return TCL_OK; } /* * Scan through the effective namespace's command table and create a list * with all commands that match the pattern. If a specific namespace was * requested in the pattern, qualify the command names with the namespace * name. */ listPtr = Tcl_NewListObj(0, NULL); if (simplePattern != NULL && TclMatchIsTrivial(simplePattern)) { /* * Special case for when the pattern doesn't include any of glob's * special characters. This lets us avoid scans of any hash tables. */ entryPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern); if (entryPtr != NULL) { if (specificNsInPattern) { cmd = Tcl_GetHashValue(entryPtr); elemObjPtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, cmd, elemObjPtr); } else { cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr); elemObjPtr = Tcl_NewStringObj(cmdName, -1); } Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); Tcl_SetObjResult(interp, listPtr); return TCL_OK; } if ((nsPtr != globalNsPtr) && !specificNsInPattern) { Tcl_HashTable *tablePtr = NULL; /* Quell warning. */ for (i=0 ; icommandPathLength ; i++) { Namespace *pathNsPtr = nsPtr->commandPathArray[i].nsPtr; if (pathNsPtr == NULL) { continue; } tablePtr = &pathNsPtr->cmdTable; entryPtr = Tcl_FindHashEntry(tablePtr, simplePattern); if (entryPtr != NULL) { break; } } if (entryPtr == NULL) { tablePtr = &globalNsPtr->cmdTable; entryPtr = Tcl_FindHashEntry(tablePtr, simplePattern); } if (entryPtr != NULL) { cmdName = Tcl_GetHashKey(tablePtr, entryPtr); Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(cmdName, -1)); Tcl_SetObjResult(interp, listPtr); return TCL_OK; } } } else if (nsPtr->commandPathLength == 0 || specificNsInPattern) { /* * The pattern is non-trivial, but either there is no explicit path or * there is an explicit namespace in the pattern. In both cases, the * old matching scheme is perfect. */ entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); while (entryPtr != NULL) { cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr); if ((simplePattern == NULL) || Tcl_StringMatch(cmdName, simplePattern)) { if (specificNsInPattern) { cmd = Tcl_GetHashValue(entryPtr); elemObjPtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, cmd, elemObjPtr); } else { elemObjPtr = Tcl_NewStringObj(cmdName, -1); } Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); } entryPtr = Tcl_NextHashEntry(&search); } /* * If the effective namespace isn't the global :: namespace, and a * specific namespace wasn't requested in the pattern, then add in all * global :: commands that match the simple pattern. Of course, we add * in only those commands that aren't hidden by a command in the * effective namespace. */ if ((nsPtr != globalNsPtr) && !specificNsInPattern) { entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search); while (entryPtr != NULL) { cmdName = Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr); if ((simplePattern == NULL) || Tcl_StringMatch(cmdName, simplePattern)) { if (Tcl_FindHashEntry(&nsPtr->cmdTable,cmdName) == NULL) { Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(cmdName, -1)); } } entryPtr = Tcl_NextHashEntry(&search); } } } else { /* * The pattern is non-trivial (can match more than one command name), * there is an explicit path, and there is no explicit namespace in * the pattern. This means that we have to traverse the path to * discover all the commands defined. */ Tcl_HashTable addedCommandsTable; int isNew; int foundGlobal = (nsPtr == globalNsPtr); /* * We keep a hash of the objects already added to the result list. */ Tcl_InitObjHashTable(&addedCommandsTable); entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); while (entryPtr != NULL) { cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr); if ((simplePattern == NULL) || Tcl_StringMatch(cmdName, simplePattern)) { elemObjPtr = Tcl_NewStringObj(cmdName, -1); Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); (void) Tcl_CreateHashEntry(&addedCommandsTable, elemObjPtr, &isNew); } entryPtr = Tcl_NextHashEntry(&search); } /* * Search the path next. */ for (i=0 ; icommandPathLength ; i++) { Namespace *pathNsPtr = nsPtr->commandPathArray[i].nsPtr; if (pathNsPtr == NULL) { continue; } if (pathNsPtr == globalNsPtr) { foundGlobal = 1; } entryPtr = Tcl_FirstHashEntry(&pathNsPtr->cmdTable, &search); while (entryPtr != NULL) { cmdName = Tcl_GetHashKey(&pathNsPtr->cmdTable, entryPtr); if ((simplePattern == NULL) || Tcl_StringMatch(cmdName, simplePattern)) { elemObjPtr = Tcl_NewStringObj(cmdName, -1); (void) Tcl_CreateHashEntry(&addedCommandsTable, elemObjPtr, &isNew); if (isNew) { Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); } else { TclDecrRefCount(elemObjPtr); } } entryPtr = Tcl_NextHashEntry(&search); } } /* * If the effective namespace isn't the global :: namespace, and a * specific namespace wasn't requested in the pattern, then add in all * global :: commands that match the simple pattern. Of course, we add * in only those commands that aren't hidden by a command in the * effective namespace. */ if (!foundGlobal) { entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search); while (entryPtr != NULL) { cmdName = Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr); if ((simplePattern == NULL) || Tcl_StringMatch(cmdName, simplePattern)) { elemObjPtr = Tcl_NewStringObj(cmdName, -1); if (Tcl_FindHashEntry(&addedCommandsTable, (char *) elemObjPtr) == NULL) { Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); } else { TclDecrRefCount(elemObjPtr); } } entryPtr = Tcl_NextHashEntry(&search); } } Tcl_DeleteHashTable(&addedCommandsTable); } Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * InfoCompleteCmd -- * * Called to implement the "info complete" command that determines * whether a string is a complete Tcl command. Handles the following * syntax: * * info complete command * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoCompleteCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "command"); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj( TclObjCommandComplete(objv[1]))); return TCL_OK; } /* *---------------------------------------------------------------------- * * InfoDefaultCmd -- * * Called to implement the "info default" command that returns the * default value for a procedure argument. Handles the following syntax: * * info default procName arg varName * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoDefaultCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; const char *procName, *argName; Proc *procPtr; CompiledLocal *localPtr; Tcl_Obj *valueObjPtr; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "procname arg varname"); return TCL_ERROR; } procName = TclGetString(objv[1]); argName = TclGetString(objv[2]); procPtr = TclFindProc(iPtr, procName); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't a procedure", procName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROCEDURE", procName, NULL); return TCL_ERROR; } for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; localPtr = localPtr->nextPtr) { if (TclIsVarArgument(localPtr) && (strcmp(argName, localPtr->name) == 0)) { if (localPtr->defValuePtr != NULL) { valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL, localPtr->defValuePtr, TCL_LEAVE_ERR_MSG); if (valueObjPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); } else { Tcl_Obj *nullObjPtr = Tcl_NewObj(); valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL, nullObjPtr, TCL_LEAVE_ERR_MSG); if (valueObjPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); } return TCL_OK; } } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "procedure \"%s\" doesn't have an argument \"%s\"", procName, argName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARGUMENT", argName, NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * InfoErrorStackCmd -- * * Called to implement the "info errorstack" command that returns information * about the last error's call stack. Handles the following syntax: * * info errorstack ?interp? * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoErrorStackCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Interp *target; Interp *iPtr; if ((objc != 1) && (objc != 2)) { Tcl_WrongNumArgs(interp, 1, objv, "?interp?"); return TCL_ERROR; } target = interp; if (objc == 2) { target = Tcl_GetSlave(interp, Tcl_GetString(objv[1])); if (target == NULL) { return TCL_ERROR; } } iPtr = (Interp *) target; Tcl_SetObjResult(interp, iPtr->errorStack); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclInfoExistsCmd -- * * Called to implement the "info exists" command that determines whether * a variable exists. Handles the following syntax: * * info exists varName * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ int TclInfoExistsCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *varName; Var *varPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "varName"); return TCL_ERROR; } varName = TclGetString(objv[1]); varPtr = TclVarTraceExists(interp, varName); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(varPtr && varPtr->value.objPtr)); return TCL_OK; } /* *---------------------------------------------------------------------- * * InfoFrameCmd -- * TIP #280 * * Called to implement the "info frame" command that returns the location * of either the currently executing command, or its caller. Handles the * following syntax: * * info frame ?number? * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoFrameCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; int level, code = TCL_OK; CmdFrame *framePtr, **cmdFramePtrPtr = &iPtr->cmdFramePtr; CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; int topLevel = 0; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?number?"); return TCL_ERROR; } while (corPtr) { while (*cmdFramePtrPtr) { topLevel++; cmdFramePtrPtr = &((*cmdFramePtrPtr)->nextPtr); } if (corPtr->caller.cmdFramePtr) { *cmdFramePtrPtr = corPtr->caller.cmdFramePtr; } corPtr = corPtr->callerEEPtr->corPtr; } topLevel += (*cmdFramePtrPtr)->level; if (topLevel != iPtr->cmdFramePtr->level) { framePtr = iPtr->cmdFramePtr; while (framePtr) { framePtr->level = topLevel--; framePtr = framePtr->nextPtr; } if (topLevel) { Tcl_Panic("Broken frame level calculation"); } topLevel = iPtr->cmdFramePtr->level; } if (objc == 1) { /* * Just "info frame". */ Tcl_SetObjResult(interp, Tcl_NewIntObj(topLevel)); goto done; } /* * We've got "info frame level" and must parse the level first. */ if (TclGetIntFromObj(interp, objv[1], &level) != TCL_OK) { code = TCL_ERROR; goto done; } if ((level > topLevel) || (level <= - topLevel)) { levelError: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad level \"%s\"", TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "STACK_FRAME", TclGetString(objv[1]), NULL); code = TCL_ERROR; goto done; } /* * Let us convert to relative so that we know how many levels to go back */ if (level > 0) { level -= topLevel; } framePtr = iPtr->cmdFramePtr; while (++level <= 0) { framePtr = framePtr->nextPtr; if (!framePtr) { goto levelError; } } Tcl_SetObjResult(interp, TclInfoFrame(interp, framePtr)); done: cmdFramePtrPtr = &iPtr->cmdFramePtr; corPtr = iPtr->execEnvPtr->corPtr; while (corPtr) { CmdFrame *endPtr = corPtr->caller.cmdFramePtr; if (endPtr) { if (*cmdFramePtrPtr == endPtr) { *cmdFramePtrPtr = NULL; } else { CmdFrame *runPtr = *cmdFramePtrPtr; while (runPtr->nextPtr != endPtr) { runPtr->level -= endPtr->level; runPtr = runPtr->nextPtr; } runPtr->level = 1; runPtr->nextPtr = NULL; } cmdFramePtrPtr = &corPtr->caller.cmdFramePtr; } corPtr = corPtr->callerEEPtr->corPtr; } return code; } /* *---------------------------------------------------------------------- * * TclInfoFrame -- * * Core of InfoFrameCmd, returns TIP280 dict for a given frame. * * Results: * Returns TIP280 dict. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * TclInfoFrame( Tcl_Interp *interp, /* Current interpreter. */ CmdFrame *framePtr) /* Frame to get info for. */ { Interp *iPtr = (Interp *) interp; Tcl_Obj *tmpObj; Tcl_Obj *lv[20]; /* Keep uptodate when more keys are added to * the dict. */ int lc = 0; /* * This array is indexed by the TCL_LOCATION_... values, except * for _LAST. */ static const char *const typeString[TCL_LOCATION_LAST] = { "eval", "eval", "eval", "precompiled", "source", "proc" }; Proc *procPtr = framePtr->framePtr ? framePtr->framePtr->procPtr : NULL; int needsFree = -1; /* * Pull the information and construct the dictionary to return, as list. * Regarding use of the CmdFrame fields see tclInt.h, and its definition. */ #define ADD_PAIR(name, value) \ TclNewLiteralStringObj(tmpObj, name); \ lv[lc++] = tmpObj; \ lv[lc++] = (value) switch (framePtr->type) { case TCL_LOCATION_EVAL: /* * Evaluation, dynamic script. Type, line, cmd, the latter through * str. */ ADD_PAIR("type", Tcl_NewStringObj(typeString[framePtr->type], -1)); if (framePtr->line) { ADD_PAIR("line", Tcl_NewIntObj(framePtr->line[0])); } else { ADD_PAIR("line", Tcl_NewIntObj(1)); } ADD_PAIR("cmd", TclGetSourceFromFrame(framePtr, 0, NULL)); break; case TCL_LOCATION_PREBC: /* * Precompiled. Result contains the type as signal, nothing else. */ ADD_PAIR("type", Tcl_NewStringObj(typeString[framePtr->type], -1)); break; case TCL_LOCATION_BC: { /* * Execution of bytecode. Talk to the BC engine to fill out the frame. */ CmdFrame *fPtr = TclStackAlloc(interp, sizeof(CmdFrame)); *fPtr = *framePtr; /* * Note: * Type BC => f.data.eval.path is not used. * f.data.tebc.codePtr is used instead. */ TclGetSrcInfoForPc(fPtr); /* * Now filled: cmd.str.(cmd,len), line * Possibly modified: type, path! */ ADD_PAIR("type", Tcl_NewStringObj(typeString[fPtr->type], -1)); if (fPtr->line) { ADD_PAIR("line", Tcl_NewIntObj(fPtr->line[0])); } if (fPtr->type == TCL_LOCATION_SOURCE) { ADD_PAIR("file", fPtr->data.eval.path); /* * Death of reference by TclGetSrcInfoForPc. */ Tcl_DecrRefCount(fPtr->data.eval.path); } ADD_PAIR("cmd", TclGetSourceFromFrame(fPtr, 0, NULL)); if (fPtr->cmdObj && framePtr->cmdObj == NULL) { needsFree = lc - 1; } TclStackFree(interp, fPtr); break; } case TCL_LOCATION_SOURCE: /* * Evaluation of a script file. */ ADD_PAIR("type", Tcl_NewStringObj(typeString[framePtr->type], -1)); ADD_PAIR("line", Tcl_NewIntObj(framePtr->line[0])); ADD_PAIR("file", framePtr->data.eval.path); /* * Refcount framePtr->data.eval.path goes up when lv is converted into * the result list object. */ ADD_PAIR("cmd", TclGetSourceFromFrame(framePtr, 0, NULL)); break; case TCL_LOCATION_PROC: Tcl_Panic("TCL_LOCATION_PROC found in standard frame"); break; } /* * 'proc'. Common to all frame types. Conditional on having an associated * Procedure CallFrame. */ if (procPtr != NULL) { Tcl_HashEntry *namePtr = procPtr->cmdPtr->hPtr; if (namePtr) { Tcl_Obj *procNameObj; /* * This is a regular command. */ TclNewObj(procNameObj); Tcl_GetCommandFullName(interp, (Tcl_Command) procPtr->cmdPtr, procNameObj); ADD_PAIR("proc", procNameObj); } else if (procPtr->cmdPtr->clientData) { ExtraFrameInfo *efiPtr = procPtr->cmdPtr->clientData; int i; /* * This is a non-standard command. Luckily, it's told us how to * render extra information about its frame. */ for (i=0 ; ilength ; i++) { lv[lc++] = Tcl_NewStringObj(efiPtr->fields[i].name, -1); if (efiPtr->fields[i].proc) { lv[lc++] = efiPtr->fields[i].proc(efiPtr->fields[i].clientData); } else { lv[lc++] = efiPtr->fields[i].clientData; } } } } /* * 'level'. Common to all frame types. Conditional on having an associated * _visible_ CallFrame. */ if ((framePtr->framePtr != NULL) && (iPtr->varFramePtr != NULL)) { CallFrame *current = framePtr->framePtr; CallFrame *top = iPtr->varFramePtr; CallFrame *idx; for (idx=top ; idx!=NULL ; idx=idx->callerVarPtr) { if (idx == current) { int c = framePtr->framePtr->level; int t = iPtr->varFramePtr->level; ADD_PAIR("level", Tcl_NewIntObj(t - c)); break; } } } tmpObj = Tcl_NewListObj(lc, lv); if (needsFree >= 0) { Tcl_DecrRefCount(lv[needsFree]); } return tmpObj; } /* *---------------------------------------------------------------------- * * InfoFunctionsCmd -- * * Called to implement the "info functions" command that returns the list * of math functions matching an optional pattern. Handles the following * syntax: * * info functions ?pattern? * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoFunctionsCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *script; int code; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?pattern?"); return TCL_ERROR; } script = Tcl_NewStringObj( " ::apply [::list {{pattern *}} {\n" " ::set cmds {}\n" " ::foreach cmd [::info commands ::tcl::mathfunc::$pattern] {\n" " ::lappend cmds [::namespace tail $cmd]\n" " }\n" " ::foreach cmd [::info commands tcl::mathfunc::$pattern] {\n" " ::set cmd [::namespace tail $cmd]\n" " ::if {$cmd ni $cmds} {\n" " ::lappend cmds $cmd\n" " }\n" " }\n" " ::return $cmds\n" " } [::namespace current]] ", -1); if (objc == 2) { Tcl_Obj *arg = Tcl_NewListObj(1, &(objv[1])); Tcl_AppendObjToObj(script, arg); Tcl_DecrRefCount(arg); } Tcl_IncrRefCount(script); code = Tcl_EvalObjEx(interp, script, 0); Tcl_DecrRefCount(script); return code; } /* *---------------------------------------------------------------------- * * InfoHostnameCmd -- * * Called to implement the "info hostname" command that returns the host * name. Handles the following syntax: * * info hostname * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoHostnameCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *name; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } name = Tcl_GetHostName(); if (name) { Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1)); return TCL_OK; } Tcl_SetObjResult(interp, Tcl_NewStringObj( "unable to determine name of host", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "HOSTNAME", "UNKNOWN", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * InfoLevelCmd -- * * Called to implement the "info level" command that returns information * about the call stack. Handles the following syntax: * * info level ?number? * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoLevelCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; if (objc == 1) { /* Just "info level" */ Tcl_SetObjResult(interp, Tcl_NewIntObj(iPtr->varFramePtr->level)); return TCL_OK; } if (objc == 2) { int level; CallFrame *framePtr, *rootFramePtr = iPtr->rootFramePtr; if (TclGetIntFromObj(interp, objv[1], &level) != TCL_OK) { return TCL_ERROR; } if (level <= 0) { if (iPtr->varFramePtr == rootFramePtr) { goto levelError; } level += iPtr->varFramePtr->level; } for (framePtr=iPtr->varFramePtr ; framePtr!=rootFramePtr; framePtr=framePtr->callerVarPtr) { if (framePtr->level == level) { break; } } if (framePtr == rootFramePtr) { goto levelError; } Tcl_SetObjResult(interp, Tcl_NewListObj(framePtr->objc, framePtr->objv)); return TCL_OK; } Tcl_WrongNumArgs(interp, 1, objv, "?number?"); return TCL_ERROR; levelError: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad level \"%s\"", TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "STACK_LEVEL", TclGetString(objv[1]), NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * InfoLibraryCmd -- * * Called to implement the "info library" command that returns the * library directory for the Tcl installation. Handles the following * syntax: * * info library * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoLibraryCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *libDirName; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } libDirName = Tcl_GetVar(interp, "tcl_library", TCL_GLOBAL_ONLY); if (libDirName != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(libDirName, -1)); return TCL_OK; } Tcl_SetObjResult(interp, Tcl_NewStringObj( "no library has been specified for Tcl", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", "tcl_library",NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * InfoLoadedCmd -- * * Called to implement the "info loaded" command that returns the * packages that have been loaded into an interpreter. Handles the * following syntax: * * info loaded ?interp? * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoLoadedCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *interpName; if ((objc != 1) && (objc != 2)) { Tcl_WrongNumArgs(interp, 1, objv, "?interp?"); return TCL_ERROR; } if (objc == 1) { /* Get loaded pkgs in all interpreters. */ interpName = NULL; } else { /* Get pkgs just in specified interp. */ interpName = TclGetString(objv[1]); } return TclGetLoadedPackages(interp, interpName); } /* *---------------------------------------------------------------------- * * InfoNameOfExecutableCmd -- * * Called to implement the "info nameofexecutable" command that returns * the name of the binary file running this application. Handles the * following syntax: * * info nameofexecutable * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoNameOfExecutableCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, TclGetObjNameOfExecutable()); return TCL_OK; } /* *---------------------------------------------------------------------- * * InfoPatchLevelCmd -- * * Called to implement the "info patchlevel" command that returns the * default value for an argument to a procedure. Handles the following * syntax: * * info patchlevel * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoPatchLevelCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *patchlevel; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } patchlevel = Tcl_GetVar(interp, "tcl_patchLevel", (TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG)); if (patchlevel != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(patchlevel, -1)); return TCL_OK; } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * InfoProcsCmd -- * * Called to implement the "info procs" command that returns the list of * procedures in the interpreter that match an optional pattern. The * pattern, if any, consists of an optional sequence of namespace names * separated by "::" qualifiers, which is followed by a glob-style * pattern that restricts which commands are returned. Handles the * following syntax: * * info procs ?pattern? * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoProcsCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *cmdName, *pattern; const char *simplePattern; Namespace *nsPtr; #ifdef INFO_PROCS_SEARCH_GLOBAL_NS Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp); #endif Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); Tcl_Obj *listPtr, *elemObjPtr; int specificNsInPattern = 0;/* Init. to avoid compiler warning. */ register Tcl_HashEntry *entryPtr; Tcl_HashSearch search; Command *cmdPtr, *realCmdPtr; /* * Get the pattern and find the "effective namespace" in which to list * procs. */ if (objc == 1) { simplePattern = NULL; nsPtr = currNsPtr; specificNsInPattern = 0; } else if (objc == 2) { /* * From the pattern, get the effective namespace and the simple * pattern (no namespace qualifiers or ::'s) at the end. If an error * was found while parsing the pattern, return it. Otherwise, if the * namespace wasn't found, just leave nsPtr NULL: we will return an * empty list since no commands there can be found. */ Namespace *dummy1NsPtr, *dummy2NsPtr; pattern = TclGetString(objv[1]); TclGetNamespaceForQualName(interp, pattern, NULL, /*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern); if (nsPtr != NULL) { /* We successfully found the pattern's ns. */ specificNsInPattern = (strcmp(simplePattern, pattern) != 0); } } else { Tcl_WrongNumArgs(interp, 1, objv, "?pattern?"); return TCL_ERROR; } if (nsPtr == NULL) { return TCL_OK; } /* * Scan through the effective namespace's command table and create a list * with all procs that match the pattern. If a specific namespace was * requested in the pattern, qualify the command names with the namespace * name. */ listPtr = Tcl_NewListObj(0, NULL); #ifndef INFO_PROCS_SEARCH_GLOBAL_NS if (simplePattern != NULL && TclMatchIsTrivial(simplePattern)) { entryPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern); if (entryPtr != NULL) { cmdPtr = Tcl_GetHashValue(entryPtr); if (!TclIsProc(cmdPtr)) { realCmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr); if (realCmdPtr != NULL && TclIsProc(realCmdPtr)) { goto simpleProcOK; } } else { simpleProcOK: if (specificNsInPattern) { elemObjPtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, elemObjPtr); } else { elemObjPtr = Tcl_NewStringObj(simplePattern, -1); } Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); } } } else #endif /* !INFO_PROCS_SEARCH_GLOBAL_NS */ { entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); while (entryPtr != NULL) { cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, entryPtr); if ((simplePattern == NULL) || Tcl_StringMatch(cmdName, simplePattern)) { cmdPtr = Tcl_GetHashValue(entryPtr); if (!TclIsProc(cmdPtr)) { realCmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr); if (realCmdPtr != NULL && TclIsProc(realCmdPtr)) { goto procOK; } } else { procOK: if (specificNsInPattern) { elemObjPtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, elemObjPtr); } else { elemObjPtr = Tcl_NewStringObj(cmdName, -1); } Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); } } entryPtr = Tcl_NextHashEntry(&search); } /* * If the effective namespace isn't the global :: namespace, and a * specific namespace wasn't requested in the pattern, then add in all * global :: procs that match the simple pattern. Of course, we add in * only those procs that aren't hidden by a proc in the effective * namespace. */ #ifdef INFO_PROCS_SEARCH_GLOBAL_NS /* * If "info procs" worked like "info commands", returning the commands * also seen in the global namespace, then you would include this * code. As this could break backwards compatibilty with 8.0-8.2, we * decided not to "fix" it in 8.3, leaving the behavior slightly * different. */ if ((nsPtr != globalNsPtr) && !specificNsInPattern) { entryPtr = Tcl_FirstHashEntry(&globalNsPtr->cmdTable, &search); while (entryPtr != NULL) { cmdName = Tcl_GetHashKey(&globalNsPtr->cmdTable, entryPtr); if ((simplePattern == NULL) || Tcl_StringMatch(cmdName, simplePattern)) { if (Tcl_FindHashEntry(&nsPtr->cmdTable,cmdName) == NULL) { cmdPtr = Tcl_GetHashValue(entryPtr); realCmdPtr = (Command *) TclGetOriginalCommand( (Tcl_Command) cmdPtr); if (TclIsProc(cmdPtr) || ((realCmdPtr != NULL) && TclIsProc(realCmdPtr))) { Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(cmdName, -1)); } } } entryPtr = Tcl_NextHashEntry(&search); } } #endif } Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * InfoScriptCmd -- * * Called to implement the "info script" command that returns the script * file that is currently being evaluated. Handles the following syntax: * * info script ?newName? * * If newName is specified, it will set that as the internal name. * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. It may change the internal * script filename. * *---------------------------------------------------------------------- */ static int InfoScriptCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; if ((objc != 1) && (objc != 2)) { Tcl_WrongNumArgs(interp, 1, objv, "?filename?"); return TCL_ERROR; } if (objc == 2) { if (iPtr->scriptFile != NULL) { Tcl_DecrRefCount(iPtr->scriptFile); } iPtr->scriptFile = objv[1]; Tcl_IncrRefCount(iPtr->scriptFile); } if (iPtr->scriptFile != NULL) { Tcl_SetObjResult(interp, iPtr->scriptFile); } return TCL_OK; } /* *---------------------------------------------------------------------- * * InfoSharedlibCmd -- * * Called to implement the "info sharedlibextension" command that returns * the file extension used for shared libraries. Handles the following * syntax: * * info sharedlibextension * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoSharedlibCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } #ifdef TCL_SHLIB_EXT Tcl_SetObjResult(interp, Tcl_NewStringObj(TCL_SHLIB_EXT, -1)); #endif return TCL_OK; } /* *---------------------------------------------------------------------- * * InfoTclVersionCmd -- * * Called to implement the "info tclversion" command that returns the * version number for this Tcl library. Handles the following syntax: * * info tclversion * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ static int InfoTclVersionCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *version; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } version = Tcl_GetVar2Ex(interp, "tcl_version", NULL, (TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG)); if (version != NULL) { Tcl_SetObjResult(interp, version); return TCL_OK; } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_JoinObjCmd -- * * This procedure is invoked to process the "join" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_JoinObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { int listLen, i; Tcl_Obj *resObjPtr, *joinObjPtr, **elemPtrs; if ((objc < 2) || (objc > 3)) { Tcl_WrongNumArgs(interp, 1, objv, "list ?joinString?"); return TCL_ERROR; } /* * Make sure the list argument is a list object and get its length and a * pointer to its array of element pointers. */ if (TclListObjGetElements(interp, objv[1], &listLen, &elemPtrs) != TCL_OK) { return TCL_ERROR; } joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2]; Tcl_IncrRefCount(joinObjPtr); resObjPtr = Tcl_NewObj(); for (i = 0; i < listLen; i++) { if (i > 0) { Tcl_AppendObjToObj(resObjPtr, joinObjPtr); } Tcl_AppendObjToObj(resObjPtr, elemPtrs[i]); } Tcl_DecrRefCount(joinObjPtr); Tcl_SetObjResult(interp, resObjPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_LassignObjCmd -- * * This object-based procedure is invoked to process the "lassign" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_LassignObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *listCopyPtr; Tcl_Obj **listObjv; /* The contents of the list. */ int listObjc; /* The length of the list. */ int code = TCL_OK; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "list ?varName ...?"); return TCL_ERROR; } listCopyPtr = TclListObjCopy(interp, objv[1]); if (listCopyPtr == NULL) { return TCL_ERROR; } TclListObjGetElements(NULL, listCopyPtr, &listObjc, &listObjv); objc -= 2; objv += 2; while (code == TCL_OK && objc > 0 && listObjc > 0) { if (Tcl_ObjSetVar2(interp, *objv++, NULL, *listObjv++, TCL_LEAVE_ERR_MSG) == NULL) { code = TCL_ERROR; } objc--; listObjc--; } if (code == TCL_OK && objc > 0) { Tcl_Obj *emptyObj; TclNewObj(emptyObj); Tcl_IncrRefCount(emptyObj); while (code == TCL_OK && objc-- > 0) { if (Tcl_ObjSetVar2(interp, *objv++, NULL, emptyObj, TCL_LEAVE_ERR_MSG) == NULL) { code = TCL_ERROR; } } Tcl_DecrRefCount(emptyObj); } if (code == TCL_OK && listObjc > 0) { Tcl_SetObjResult(interp, Tcl_NewListObj(listObjc, listObjv)); } Tcl_DecrRefCount(listCopyPtr); return code; } /* *---------------------------------------------------------------------- * * Tcl_LindexObjCmd -- * * This object-based procedure is invoked to process the "lindex" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_LindexObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *elemPtr; /* Pointer to the element being extracted. */ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "list ?index ...?"); return TCL_ERROR; } /* * If objc==3, then objv[2] may be either a single index or a list of * indices: go to TclLindexList to determine which. If objc>=4, or * objc==2, then objv[2 .. objc-2] are all single indices and processed as * such in TclLindexFlat. */ if (objc == 3) { elemPtr = TclLindexList(interp, objv[1], objv[2]); } else { elemPtr = TclLindexFlat(interp, objv[1], objc-2, objv+2); } /* * Set the interpreter's object result to the last element extracted. */ if (elemPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, elemPtr); Tcl_DecrRefCount(elemPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_LinsertObjCmd -- * * This object-based procedure is invoked to process the "linsert" Tcl * command. See the user documentation for details on what it does. * * Results: * A new Tcl list object formed by inserting zero or more elements into a * list. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_LinsertObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ register int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *listPtr; int index, len, result; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "list index ?element ...?"); return TCL_ERROR; } result = TclListObjLength(interp, objv[1], &len); if (result != TCL_OK) { return result; } /* * Get the index. "end" is interpreted to be the index after the last * element, such that using it will cause any inserted elements to be * appended to the list. */ result = TclGetIntForIndexM(interp, objv[2], /*end*/ len, &index); if (result != TCL_OK) { return result; } if (index > len) { index = len; } /* * If the list object is unshared we can modify it directly. Otherwise we * create a copy to modify: this is "copy on write". */ listPtr = objv[1]; if (Tcl_IsShared(listPtr)) { listPtr = TclListObjCopy(NULL, listPtr); } if ((objc == 4) && (index == len)) { /* * Special case: insert one element at the end of the list. */ Tcl_ListObjAppendElement(NULL, listPtr, objv[3]); } else { if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, index, 0, (objc-3), &(objv[3]))) { return TCL_ERROR; } } /* * Set the interpreter's object result. */ Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ListObjCmd -- * * This procedure is invoked to process the "list" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_ListObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ register int objc, /* Number of arguments. */ register Tcl_Obj *const objv[]) /* The argument objects. */ { /* * If there are no list elements, the result is an empty object. * Otherwise set the interpreter's result object to be a list object. */ if (objc > 1) { Tcl_SetObjResult(interp, Tcl_NewListObj(objc-1, &objv[1])); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_LlengthObjCmd -- * * This object-based procedure is invoked to process the "llength" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_LlengthObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ register Tcl_Obj *const objv[]) /* Argument objects. */ { int listLen, result; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "list"); return TCL_ERROR; } result = TclListObjLength(interp, objv[1], &listLen); if (result != TCL_OK) { return result; } /* * Set the interpreter's object result to an integer object holding the * length. */ Tcl_SetObjResult(interp, Tcl_NewIntObj(listLen)); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_LrangeObjCmd -- * * This procedure is invoked to process the "lrange" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_LrangeObjCmd( ClientData notUsed, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ register Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj **elemPtrs; int listLen, first, last, result; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "list first last"); return TCL_ERROR; } result = TclListObjLength(interp, objv[1], &listLen); if (result != TCL_OK) { return result; } result = TclGetIntForIndexM(interp, objv[2], /*endValue*/ listLen - 1, &first); if (result != TCL_OK) { return result; } if (first < 0) { first = 0; } result = TclGetIntForIndexM(interp, objv[3], /*endValue*/ listLen - 1, &last); if (result != TCL_OK) { return result; } if (last >= listLen) { last = listLen - 1; } if (first > last) { /* * Returning an empty list is easy. */ return TCL_OK; } result = TclListObjGetElements(interp, objv[1], &listLen, &elemPtrs); if (result != TCL_OK) { return result; } if (Tcl_IsShared(objv[1]) || ((ListRepPtr(objv[1])->refCount > 1))) { Tcl_SetObjResult(interp, Tcl_NewListObj(last - first + 1, &elemPtrs[first])); } else { /* * In-place is possible. */ if (last < (listLen - 1)) { Tcl_ListObjReplace(interp, objv[1], last + 1, listLen - 1 - last, 0, NULL); } /* * This one is not conditioned on (first > 0) in order to preserve the * string-canonizing effect of [lrange 0 end]. */ Tcl_ListObjReplace(interp, objv[1], 0, first, 0, NULL); Tcl_SetObjResult(interp, objv[1]); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_LrepeatObjCmd -- * * This procedure is invoked to process the "lrepeat" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_LrepeatObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ register int objc, /* Number of arguments. */ register Tcl_Obj *const objv[]) /* The argument objects. */ { int elementCount, i, totalElems; Tcl_Obj *listPtr, **dataArray = NULL; /* * Check arguments for legality: * lrepeat count ?value ...? */ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "count ?value ...?"); return TCL_ERROR; } if (TCL_OK != TclGetIntFromObj(interp, objv[1], &elementCount)) { return TCL_ERROR; } if (elementCount < 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad count \"%d\": must be integer >= 0", elementCount)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPEAT", "NEGARG", NULL); return TCL_ERROR; } /* * Skip forward to the interesting arguments now we've finished parsing. */ objc -= 2; objv += 2; /* Final sanity check. Do not exceed limits on max list length. */ if (elementCount && objc > LIST_MAX/elementCount) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "max length of a Tcl list (%d elements) exceeded", LIST_MAX)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); return TCL_ERROR; } totalElems = objc * elementCount; /* * Get an empty list object that is allocated large enough to hold each * init value elementCount times. */ listPtr = Tcl_NewListObj(totalElems, NULL); if (totalElems) { List *listRepPtr = ListRepPtr(listPtr); listRepPtr->elemCount = elementCount*objc; dataArray = &listRepPtr->elements; } /* * Set the elements. Note that we handle the common degenerate case of a * single value being repeated separately to permit the compiler as much * room as possible to optimize a loop that might be run a very large * number of times. */ CLANG_ASSERT(dataArray || totalElems == 0 ); if (objc == 1) { register Tcl_Obj *tmpPtr = objv[0]; tmpPtr->refCount += elementCount; for (i=0 ; i= listLen) && (listLen > 0)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "list doesn't contain element %s", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPLACE", "BADIDX", NULL); return TCL_ERROR; } if (last >= listLen) { last = listLen - 1; } if (first <= last) { numToDelete = last - first + 1; } else { numToDelete = 0; } /* * If the list object is unshared we can modify it directly, otherwise we * create a copy to modify: this is "copy on write". */ listPtr = objv[1]; if (Tcl_IsShared(listPtr)) { listPtr = TclListObjCopy(NULL, listPtr); } /* * Note that we call Tcl_ListObjReplace even when numToDelete == 0 and * objc == 4. In this case, the list value of listPtr is not changed (no * elements are removed or added), but by making the call we are assured * we end up with a list in canonical form. Resist any temptation to * optimize this case away. */ if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, first, numToDelete, objc-4, objv+4)) { return TCL_ERROR; } /* * Set the interpreter's object result. */ Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_LreverseObjCmd -- * * This procedure is invoked to process the "lreverse" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_LreverseObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument values. */ { Tcl_Obj **elemv; int elemc, i, j; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "list"); return TCL_ERROR; } if (TclListObjGetElements(interp, objv[1], &elemc, &elemv) != TCL_OK) { return TCL_ERROR; } /* * If the list is empty, just return it. [Bug 1876793] */ if (!elemc) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } if (Tcl_IsShared(objv[1]) || (ListRepPtr(objv[1])->refCount > 1)) { /* Bug 1675044 */ Tcl_Obj *resultObj, **dataArray; List *listRepPtr; resultObj = Tcl_NewListObj(elemc, NULL); listRepPtr = ListRepPtr(resultObj); listRepPtr->elemCount = elemc; dataArray = &listRepPtr->elements; for (i=0,j=elemc-1 ; i objc-4) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing starting index", -1)); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); result = TCL_ERROR; goto done; } i++; if (objv[i] == objv[objc - 2]) { /* * Take copy to prevent shimmering problems. Note that it does * not matter if the index obj is also a component of the list * being searched. We only need to copy where the list and the * index are one-and-the-same. */ startPtr = Tcl_DuplicateObj(objv[i]); } else { startPtr = objv[i]; Tcl_IncrRefCount(startPtr); } break; case LSEARCH_INDEX: { /* -index */ Tcl_Obj **indices; int j; if (sortInfo.indexc > 1) { TclStackFree(interp, sortInfo.indexv); } if (i > objc-4) { if (startPtr != NULL) { Tcl_DecrRefCount(startPtr); } Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-index\" option must be followed by list index", -1)); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); return TCL_ERROR; } /* * Store the extracted indices for processing by sublist * extraction. Note that we don't do this using objects because * that has shimmering problems. */ i++; if (TclListObjGetElements(interp, objv[i], &sortInfo.indexc, &indices) != TCL_OK) { if (startPtr != NULL) { Tcl_DecrRefCount(startPtr); } return TCL_ERROR; } switch (sortInfo.indexc) { case 0: sortInfo.indexv = NULL; break; case 1: sortInfo.indexv = &sortInfo.singleIndex; break; default: sortInfo.indexv = TclStackAlloc(interp, sizeof(int) * sortInfo.indexc); } /* * Fill the array by parsing each index. We don't know whether * their scale is sensible yet, but we at least perform the * syntactic check here. */ for (j=0 ; j listc-1) { if (sortInfo.indexc > 1) { TclStackFree(interp, sortInfo.indexv); } if (allMatches || inlineReturn) { Tcl_ResetResult(interp); } else { Tcl_SetObjResult(interp, Tcl_NewIntObj(-1)); } return TCL_OK; } } patObj = objv[objc - 1]; patternBytes = NULL; if (mode == EXACT || mode == SORTED) { switch ((enum datatypes) dataType) { case ASCII: case DICTIONARY: patternBytes = TclGetStringFromObj(patObj, &length); break; case INTEGER: result = TclGetWideIntFromObj(interp, patObj, &patWide); if (result != TCL_OK) { goto done; } /* * List representation might have been shimmered; restore it. [Bug * 1844789] */ TclListObjGetElements(NULL, objv[objc - 2], &listc, &listv); break; case REAL: result = Tcl_GetDoubleFromObj(interp, patObj, &patDouble); if (result != TCL_OK) { goto done; } /* * List representation might have been shimmered; restore it. [Bug * 1844789] */ TclListObjGetElements(NULL, objv[objc - 2], &listc, &listv); break; } } else { patternBytes = TclGetStringFromObj(patObj, &length); } /* * Set default index value to -1, indicating failure; if we find the item * in the course of our search, index will be set to the correct value. */ index = -1; match = 0; if (mode == SORTED && !allMatches && !negatedMatch) { /* * If the data is sorted, we can do a more intelligent search. Note * that there is no point in being smart when -all was specified; in * that case, we have to look at all items anyway, and there is no * sense in doing this when the match sense is inverted. */ lower = offset - 1; upper = listc; while (lower + 1 != upper && sortInfo.resultCode == TCL_OK) { i = (lower + upper)/2; if (sortInfo.indexc != 0) { itemPtr = SelectObjFromSublist(listv[i], &sortInfo); if (sortInfo.resultCode != TCL_OK) { result = sortInfo.resultCode; goto done; } } else { itemPtr = listv[i]; } switch ((enum datatypes) dataType) { case ASCII: bytes = TclGetString(itemPtr); match = strCmpFn(patternBytes, bytes); break; case DICTIONARY: bytes = TclGetString(itemPtr); match = DictionaryCompare(patternBytes, bytes); break; case INTEGER: result = TclGetWideIntFromObj(interp, itemPtr, &objWide); if (result != TCL_OK) { goto done; } if (patWide == objWide) { match = 0; } else if (patWide < objWide) { match = -1; } else { match = 1; } break; case REAL: result = Tcl_GetDoubleFromObj(interp, itemPtr, &objDouble); if (result != TCL_OK) { goto done; } if (patDouble == objDouble) { match = 0; } else if (patDouble < objDouble) { match = -1; } else { match = 1; } break; } if (match == 0) { /* * Normally, binary search is written to stop when it finds a * match. If there are duplicates of an element in the list, * our first match might not be the first occurance. * Consider: 0 0 0 1 1 1 2 2 2 * * To maintain consistancy with standard lsearch semantics, we * must find the leftmost occurance of the pattern in the * list. Thus we don't just stop searching here. This * variation means that a search always makes log n * comparisons (normal binary search might "get lucky" with an * early comparison). * * In bisect mode though, we want the last of equals. */ index = i; if (bisect) { lower = i; } else { upper = i; } } else if (match > 0) { if (isIncreasing) { lower = i; } else { upper = i; } } else { if (isIncreasing) { upper = i; } else { lower = i; } } } if (bisect && index < 0) { index = lower; } } else { /* * We need to do a linear search, because (at least one) of: * - our matcher can only tell equal vs. not equal * - our matching sense is negated * - we're building a list of all matched items */ if (allMatches) { listPtr = Tcl_NewListObj(0, NULL); } for (i = offset; i < listc; i++) { match = 0; if (sortInfo.indexc != 0) { itemPtr = SelectObjFromSublist(listv[i], &sortInfo); if (sortInfo.resultCode != TCL_OK) { if (listPtr != NULL) { Tcl_DecrRefCount(listPtr); } result = sortInfo.resultCode; goto done; } } else { itemPtr = listv[i]; } switch (mode) { case SORTED: case EXACT: switch ((enum datatypes) dataType) { case ASCII: bytes = TclGetStringFromObj(itemPtr, &elemLen); if (length == elemLen) { /* * This split allows for more optimal compilation of * memcmp/strcasecmp. */ if (noCase) { match = (TclUtfCasecmp(bytes, patternBytes) == 0); } else { match = (memcmp(bytes, patternBytes, (size_t) length) == 0); } } break; case DICTIONARY: bytes = TclGetString(itemPtr); match = (DictionaryCompare(bytes, patternBytes) == 0); break; case INTEGER: result = TclGetWideIntFromObj(interp, itemPtr, &objWide); if (result != TCL_OK) { if (listPtr != NULL) { Tcl_DecrRefCount(listPtr); } goto done; } match = (objWide == patWide); break; case REAL: result = Tcl_GetDoubleFromObj(interp,itemPtr, &objDouble); if (result != TCL_OK) { if (listPtr) { Tcl_DecrRefCount(listPtr); } goto done; } match = (objDouble == patDouble); break; } break; case GLOB: match = Tcl_StringCaseMatch(TclGetString(itemPtr), patternBytes, noCase); break; case REGEXP: match = Tcl_RegExpExecObj(interp, regexp, itemPtr, 0, 0, 0); if (match < 0) { Tcl_DecrRefCount(patObj); if (listPtr != NULL) { Tcl_DecrRefCount(listPtr); } result = TCL_ERROR; goto done; } break; } /* * Invert match condition for -not. */ if (negatedMatch) { match = !match; } if (!match) { continue; } if (!allMatches) { index = i; break; } else if (inlineReturn) { /* * Note that these appends are not expected to fail. */ if (returnSubindices && (sortInfo.indexc != 0)) { itemPtr = SelectObjFromSublist(listv[i], &sortInfo); } else { itemPtr = listv[i]; } Tcl_ListObjAppendElement(interp, listPtr, itemPtr); } else if (returnSubindices) { int j; itemPtr = Tcl_NewIntObj(i); for (j=0 ; j 1) { TclStackFree(interp, sortInfo.indexv); } return result; } /* *---------------------------------------------------------------------- * * Tcl_LsetObjCmd -- * * This procedure is invoked to process the "lset" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_LsetObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument values. */ { Tcl_Obj *listPtr; /* Pointer to the list being altered. */ Tcl_Obj *finalValuePtr; /* Value finally assigned to the variable. */ /* * Check parameter count. */ if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "listVar ?index? ?index ...? value"); return TCL_ERROR; } /* * Look up the list variable's value. */ listPtr = Tcl_ObjGetVar2(interp, objv[1], NULL, TCL_LEAVE_ERR_MSG); if (listPtr == NULL) { return TCL_ERROR; } /* * Substitute the value in the value. Return either the value or else an * unshared copy of it. */ if (objc == 4) { finalValuePtr = TclLsetList(interp, listPtr, objv[2], objv[3]); } else { finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2, objv[objc-1]); } /* * If substitution has failed, bail out. */ if (finalValuePtr == NULL) { return TCL_ERROR; } /* * Finally, update the variable so that traces fire. */ listPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, finalValuePtr, TCL_LEAVE_ERR_MSG); Tcl_DecrRefCount(finalValuePtr); if (listPtr == NULL) { return TCL_ERROR; } /* * Return the new value of the variable as the interpreter result. */ Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_LsortObjCmd -- * * This procedure is invoked to process the "lsort" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_LsortObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument values. */ { int i, j, index, indices, length, nocase = 0, indexc; int sortMode = SORTMODE_ASCII; int group, groupSize, groupOffset, idx, allocatedIndexVector = 0; Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr; SortElement *elementArray, *elementPtr; SortInfo sortInfo; /* Information about this sort that needs to * be passed to the comparison function. */ # define NUM_LISTS 30 SortElement *subList[NUM_LISTS+1]; /* This array holds pointers to temporary * lists built during the merge sort. Element * i of the array holds a list of length * 2**i. */ static const char *const switches[] = { "-ascii", "-command", "-decreasing", "-dictionary", "-increasing", "-index", "-indices", "-integer", "-nocase", "-real", "-stride", "-unique", NULL }; enum Lsort_Switches { LSORT_ASCII, LSORT_COMMAND, LSORT_DECREASING, LSORT_DICTIONARY, LSORT_INCREASING, LSORT_INDEX, LSORT_INDICES, LSORT_INTEGER, LSORT_NOCASE, LSORT_REAL, LSORT_STRIDE, LSORT_UNIQUE }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "?-option value ...? list"); return TCL_ERROR; } /* * Parse arguments to set up the mode for the sort. */ sortInfo.isIncreasing = 1; sortInfo.sortMode = SORTMODE_ASCII; sortInfo.indexv = NULL; sortInfo.indexc = 0; sortInfo.unique = 0; sortInfo.interp = interp; sortInfo.resultCode = TCL_OK; cmdPtr = NULL; indices = 0; group = 0; groupSize = 1; groupOffset = 0; indexPtr = NULL; for (i = 1; i < objc-1; i++) { if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0, &index) != TCL_OK) { sortInfo.resultCode = TCL_ERROR; goto done2; } switch ((enum Lsort_Switches) index) { case LSORT_ASCII: sortInfo.sortMode = SORTMODE_ASCII; break; case LSORT_COMMAND: if (i == objc-2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-command\" option must be followed " "by comparison command", -1)); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); sortInfo.resultCode = TCL_ERROR; goto done2; } sortInfo.sortMode = SORTMODE_COMMAND; cmdPtr = objv[i+1]; i++; break; case LSORT_DECREASING: sortInfo.isIncreasing = 0; break; case LSORT_DICTIONARY: sortInfo.sortMode = SORTMODE_DICTIONARY; break; case LSORT_INCREASING: sortInfo.isIncreasing = 1; break; case LSORT_INDEX: { int indexc, dummy; Tcl_Obj **indexv; if (i == objc-2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-index\" option must be followed by list index", -1)); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); sortInfo.resultCode = TCL_ERROR; goto done2; } if (TclListObjGetElements(interp, objv[i+1], &indexc, &indexv) != TCL_OK) { sortInfo.resultCode = TCL_ERROR; goto done2; } /* * Check each of the indices for syntactic correctness. Note that * we do not store the converted values here because we do not * know if this is the only -index option yet and so we can't * allocate any space; that happens after the scan through all the * options is done. */ for (j=0 ; j 0) { /* * Use the first value in the list supplied to -index as the * offset of the element within each group by which to sort. */ groupOffset = sortInfo.indexv[0]; if (groupOffset <= SORTIDX_END) { groupOffset = (groupOffset - SORTIDX_END) + groupSize - 1; } if (groupOffset < 0 || groupOffset >= groupSize) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "when used with \"-stride\", the leading \"-index\"" " value must be within the group", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSORT", "BADINDEX", NULL); sortInfo.resultCode = TCL_ERROR; goto done; } if (sortInfo.indexc == 1) { sortInfo.indexc = 0; sortInfo.indexv = NULL; } else { sortInfo.indexc--; /* * Do not shrink the actual memory block used; that doesn't * work with TclStackAlloc-allocated memory. [Bug 2918962] */ for (i = 0; i < sortInfo.indexc; i++) { sortInfo.indexv[i] = sortInfo.indexv[i+1]; } } } } sortInfo.numElements = length; indexc = sortInfo.indexc; sortMode = sortInfo.sortMode; if ((sortMode == SORTMODE_ASCII_NC) || (sortMode == SORTMODE_DICTIONARY)) { /* * For this function's purpose all string-based modes are equivalent */ sortMode = SORTMODE_ASCII; } /* * Initialize the sublists. After the following loop, subList[i] will * contain a sorted sublist of length 2**i. Use one extra subList at the * end, always at NULL, to indicate the end of the lists. */ for (j=0 ; j<=NUM_LISTS ; j++) { subList[j] = NULL; } /* * The following loop creates a SortElement for each list element and * begins sorting it into the sublists as it appears. */ elementArray = TclStackAlloc(interp, length * sizeof(SortElement)); for (i=0; i < length; i++){ idx = groupSize * i + groupOffset; if (indexc) { /* * If this is an indexed sort, retrieve the corresponding element */ indexPtr = SelectObjFromSublist(listObjPtrs[idx], &sortInfo); if (sortInfo.resultCode != TCL_OK) { goto done1; } } else { indexPtr = listObjPtrs[idx]; } /* * Determine the "value" of this object for sorting purposes */ if (sortMode == SORTMODE_ASCII) { elementArray[i].collationKey.strValuePtr = TclGetString(indexPtr); } else if (sortMode == SORTMODE_INTEGER) { Tcl_WideInt a; if (TclGetWideIntFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) { sortInfo.resultCode = TCL_ERROR; goto done1; } elementArray[i].collationKey.wideValue = a; } else if (sortMode == SORTMODE_REAL) { double a; if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) { sortInfo.resultCode = TCL_ERROR; goto done1; } elementArray[i].collationKey.doubleValue = a; } else { elementArray[i].collationKey.objValuePtr = indexPtr; } /* * Determine the representation of this element in the result: either * the objPtr itself, or its index in the original list. */ if (indices || group) { elementArray[i].payload.index = idx; } else { elementArray[i].payload.objPtr = listObjPtrs[idx]; } /* * Merge this element in the pre-existing sublists (and merge together * sublists when we have two of the same size). */ elementArray[i].nextPtr = NULL; elementPtr = &elementArray[i]; for (j=0 ; subList[j] ; j++) { elementPtr = MergeLists(subList[j], elementPtr, &sortInfo); subList[j] = NULL; } if (j >= NUM_LISTS) { j = NUM_LISTS-1; } subList[j] = elementPtr; } /* * Merge all sublists */ elementPtr = subList[0]; for (j=1 ; jelements; if (group) { for (i=0; elementPtr!=NULL ; elementPtr=elementPtr->nextPtr) { idx = elementPtr->payload.index; for (j = 0; j < groupSize; j++) { if (indices) { objPtr = Tcl_NewIntObj(idx + j - groupOffset); newArray[i++] = objPtr; Tcl_IncrRefCount(objPtr); } else { objPtr = listObjPtrs[idx + j - groupOffset]; newArray[i++] = objPtr; Tcl_IncrRefCount(objPtr); } } } } else if (indices) { for (i=0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr) { objPtr = Tcl_NewIntObj(elementPtr->payload.index); newArray[i++] = objPtr; Tcl_IncrRefCount(objPtr); } } else { for (i=0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr) { objPtr = elementPtr->payload.objPtr; newArray[i++] = objPtr; Tcl_IncrRefCount(objPtr); } } listRepPtr->elemCount = i; Tcl_SetObjResult(interp, resultPtr); } done1: TclStackFree(interp, elementArray); done: if (sortMode == SORTMODE_COMMAND) { TclDecrRefCount(sortInfo.compareCmdPtr); TclDecrRefCount(listObj); sortInfo.compareCmdPtr = NULL; } done2: if (allocatedIndexVector) { TclStackFree(interp, sortInfo.indexv); } return sortInfo.resultCode; } /* *---------------------------------------------------------------------- * * MergeLists - * * This procedure combines two sorted lists of SortElement structures * into a single sorted list. * * Results: * The unified list of SortElement structures. * * Side effects: * If infoPtr->unique is set then infoPtr->numElements may be updated. * Possibly others, if a user-defined comparison command does something * weird. * * Note: * If infoPtr->unique is set, the merge assumes that there are no * "repeated" elements in each of the left and right lists. In that case, * if any element of the left list is equivalent to one in the right list * it is omitted from the merged list. * * This simplified mechanism works because of the special way our * MergeSort creates the sublists to be merged and will fail to eliminate * all repeats in the general case where they are already present in * either the left or right list. A general code would need to skip * adjacent initial repeats in the left and right lists before comparing * their initial elements, at each step. * *---------------------------------------------------------------------- */ static SortElement * MergeLists( SortElement *leftPtr, /* First list to be merged; may be NULL. */ SortElement *rightPtr, /* Second list to be merged; may be NULL. */ SortInfo *infoPtr) /* Information needed by the comparison * operator. */ { SortElement *headPtr, *tailPtr; int cmp; if (leftPtr == NULL) { return rightPtr; } if (rightPtr == NULL) { return leftPtr; } cmp = SortCompare(leftPtr, rightPtr, infoPtr); if (cmp > 0 || (cmp == 0 && infoPtr->unique)) { if (cmp == 0) { infoPtr->numElements--; leftPtr = leftPtr->nextPtr; } tailPtr = rightPtr; rightPtr = rightPtr->nextPtr; } else { tailPtr = leftPtr; leftPtr = leftPtr->nextPtr; } headPtr = tailPtr; if (!infoPtr->unique) { while ((leftPtr != NULL) && (rightPtr != NULL)) { cmp = SortCompare(leftPtr, rightPtr, infoPtr); if (cmp > 0) { tailPtr->nextPtr = rightPtr; tailPtr = rightPtr; rightPtr = rightPtr->nextPtr; } else { tailPtr->nextPtr = leftPtr; tailPtr = leftPtr; leftPtr = leftPtr->nextPtr; } } } else { while ((leftPtr != NULL) && (rightPtr != NULL)) { cmp = SortCompare(leftPtr, rightPtr, infoPtr); if (cmp >= 0) { if (cmp == 0) { infoPtr->numElements--; leftPtr = leftPtr->nextPtr; } tailPtr->nextPtr = rightPtr; tailPtr = rightPtr; rightPtr = rightPtr->nextPtr; } else { tailPtr->nextPtr = leftPtr; tailPtr = leftPtr; leftPtr = leftPtr->nextPtr; } } } if (leftPtr != NULL) { tailPtr->nextPtr = leftPtr; } else { tailPtr->nextPtr = rightPtr; } return headPtr; } /* *---------------------------------------------------------------------- * * SortCompare -- * * This procedure is invoked by MergeLists to determine the proper * ordering between two elements. * * Results: * A negative results means the the first element comes before the * second, and a positive results means that the second element should * come first. A result of zero means the two elements are equal and it * doesn't matter which comes first. * * Side effects: * None, unless a user-defined comparison command does something weird. * *---------------------------------------------------------------------- */ static int SortCompare( SortElement *elemPtr1, SortElement *elemPtr2, /* Values to be compared. */ SortInfo *infoPtr) /* Information passed from the top-level * "lsort" command. */ { int order = 0; if (infoPtr->sortMode == SORTMODE_ASCII) { order = strcmp(elemPtr1->collationKey.strValuePtr, elemPtr2->collationKey.strValuePtr); } else if (infoPtr->sortMode == SORTMODE_ASCII_NC) { order = TclUtfCasecmp(elemPtr1->collationKey.strValuePtr, elemPtr2->collationKey.strValuePtr); } else if (infoPtr->sortMode == SORTMODE_DICTIONARY) { order = DictionaryCompare(elemPtr1->collationKey.strValuePtr, elemPtr2->collationKey.strValuePtr); } else if (infoPtr->sortMode == SORTMODE_INTEGER) { Tcl_WideInt a, b; a = elemPtr1->collationKey.wideValue; b = elemPtr2->collationKey.wideValue; order = ((a >= b) - (a <= b)); } else if (infoPtr->sortMode == SORTMODE_REAL) { double a, b; a = elemPtr1->collationKey.doubleValue; b = elemPtr2->collationKey.doubleValue; order = ((a >= b) - (a <= b)); } else { Tcl_Obj **objv, *paramObjv[2]; int objc; Tcl_Obj *objPtr1, *objPtr2; if (infoPtr->resultCode != TCL_OK) { /* * Once an error has occurred, skip any future comparisons so as * to preserve the error message in sortInterp->result. */ return 0; } objPtr1 = elemPtr1->collationKey.objValuePtr; objPtr2 = elemPtr2->collationKey.objValuePtr; paramObjv[0] = objPtr1; paramObjv[1] = objPtr2; /* * We made space in the command list for the two things to compare. * Replace them and evaluate the result. */ TclListObjLength(infoPtr->interp, infoPtr->compareCmdPtr, &objc); Tcl_ListObjReplace(infoPtr->interp, infoPtr->compareCmdPtr, objc - 2, 2, 2, paramObjv); TclListObjGetElements(infoPtr->interp, infoPtr->compareCmdPtr, &objc, &objv); infoPtr->resultCode = Tcl_EvalObjv(infoPtr->interp, objc, objv, 0); if (infoPtr->resultCode != TCL_OK) { Tcl_AddErrorInfo(infoPtr->interp, "\n (-compare command)"); return 0; } /* * Parse the result of the command. */ if (TclGetIntFromObj(infoPtr->interp, Tcl_GetObjResult(infoPtr->interp), &order) != TCL_OK) { Tcl_SetObjResult(infoPtr->interp, Tcl_NewStringObj( "-compare command returned non-integer result", -1)); Tcl_SetErrorCode(infoPtr->interp, "TCL", "OPERATION", "LSORT", "COMPARISONFAILED", NULL); infoPtr->resultCode = TCL_ERROR; return 0; } } if (!infoPtr->isIncreasing) { order = -order; } return order; } /* *---------------------------------------------------------------------- * * DictionaryCompare * * This function compares two strings as if they were being used in an * index or card catalog. The case of alphabetic characters is ignored, * except to break ties. Thus "B" comes before "b" but after "a". Also, * integers embedded in the strings compare in numerical order. In other * words, "x10y" comes after "x9y", not * before it as it would when * using strcmp(). * * Results: * A negative result means that the first element comes before the * second, and a positive result means that the second element should * come first. A result of zero means the two elements are equal and it * doesn't matter which comes first. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int DictionaryCompare( const char *left, const char *right) /* The strings to compare. */ { Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower; int diff, zeros; int secondaryDiff = 0; while (1) { if (isdigit(UCHAR(*right)) /* INTL: digit */ && isdigit(UCHAR(*left))) { /* INTL: digit */ /* * There are decimal numbers embedded in the two strings. Compare * them as numbers, rather than strings. If one number has more * leading zeros than the other, the number with more leading * zeros sorts later, but only as a secondary choice. */ zeros = 0; while ((*right == '0') && isdigit(UCHAR(right[1]))) { right++; zeros--; } while ((*left == '0') && isdigit(UCHAR(left[1]))) { left++; zeros++; } if (secondaryDiff == 0) { secondaryDiff = zeros; } /* * The code below compares the numbers in the two strings without * ever converting them to integers. It does this by first * comparing the lengths of the numbers and then comparing the * digit values. */ diff = 0; while (1) { if (diff == 0) { diff = UCHAR(*left) - UCHAR(*right); } right++; left++; if (!isdigit(UCHAR(*right))) { /* INTL: digit */ if (isdigit(UCHAR(*left))) { /* INTL: digit */ return 1; } else { /* * The two numbers have the same length. See if their * values are different. */ if (diff != 0) { return diff; } break; } } else if (!isdigit(UCHAR(*left))) { /* INTL: digit */ return -1; } } continue; } /* * Convert character to Unicode for comparison purposes. If either * string is at the terminating null, do a byte-wise comparison and * bail out immediately. */ if ((*left != '\0') && (*right != '\0')) { left += Tcl_UtfToUniChar(left, &uniLeft); right += Tcl_UtfToUniChar(right, &uniRight); /* * Convert both chars to lower for the comparison, because * dictionary sorts are case insensitve. Covert to lower, not * upper, so chars between Z and a will sort before A (where most * other interesting punctuations occur). */ uniLeftLower = Tcl_UniCharToLower(uniLeft); uniRightLower = Tcl_UniCharToLower(uniRight); } else { diff = UCHAR(*left) - UCHAR(*right); break; } diff = uniLeftLower - uniRightLower; if (diff) { return diff; } if (secondaryDiff == 0) { if (Tcl_UniCharIsUpper(uniLeft) && Tcl_UniCharIsLower(uniRight)) { secondaryDiff = -1; } else if (Tcl_UniCharIsUpper(uniRight) && Tcl_UniCharIsLower(uniLeft)) { secondaryDiff = 1; } } } if (diff == 0) { diff = secondaryDiff; } return diff; } /* *---------------------------------------------------------------------- * * SelectObjFromSublist -- * * This procedure is invoked from lsearch and SortCompare. It is used for * implementing the -index option, for the lsort and lsearch commands. * * Results: * Returns NULL if a failure occurs, and sets the result in the infoPtr. * Otherwise returns the Tcl_Obj* to the item. * * Side effects: * None. * * Note: * No reference counting is done, as the result is only used internally * and never passed directly to user code. * *---------------------------------------------------------------------- */ static Tcl_Obj * SelectObjFromSublist( Tcl_Obj *objPtr, /* Obj to select sublist from. */ SortInfo *infoPtr) /* Information passed from the top-level * "lsearch" or "lsort" command. */ { int i; /* * Quick check for case when no "-index" option is there. */ if (infoPtr->indexc == 0) { return objPtr; } /* * Iterate over the indices, traversing through the nested sublists as we * go. */ for (i=0 ; iindexc ; i++) { int listLen, index; Tcl_Obj *currentObj; if (TclListObjLength(infoPtr->interp, objPtr, &listLen) != TCL_OK) { infoPtr->resultCode = TCL_ERROR; return NULL; } index = infoPtr->indexv[i]; /* * Adjust for end-based indexing. */ if (index < SORTIDX_NONE) { index += listLen + 1; } if (Tcl_ListObjIndex(infoPtr->interp, objPtr, index, ¤tObj) != TCL_OK) { infoPtr->resultCode = TCL_ERROR; return NULL; } if (currentObj == NULL) { Tcl_SetObjResult(infoPtr->interp, Tcl_ObjPrintf( "element %d missing from sublist \"%s\"", index, TclGetString(objPtr))); Tcl_SetErrorCode(infoPtr->interp, "TCL", "OPERATION", "LSORT", "INDEXFAILED", NULL); infoPtr->resultCode = TCL_ERROR; return NULL; } objPtr = currentObj; } return objPtr; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * End: */ tcl8.6.5/generic/tclNamesp.c0000644000175000017500000045470312663660065015312 0ustar sergeisergei/* * tclNamesp.c -- * * Contains support for namespaces, which provide a separate context of * commands and global variables. The global :: namespace is the * traditional Tcl "global" scope. Other namespaces are created as * children of the global namespace. These other namespaces contain * special-purpose commands and variables for packages. * * Copyright (c) 1993-1997 Lucent Technologies. * Copyright (c) 1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2002-2005 Donal K. Fellows. * Copyright (c) 2006 Neil Madden. * Contributions from Don Porter, NIST, 2007. (not subject to US copyright) * * Originally implemented by * Michael J. McLennan * Bell Labs Innovations for Lucent Technologies * mmclennan@lucent.com * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" /* for TclLogCommandInfo visibility */ /* * Thread-local storage used to avoid having a global lock on data that is not * limited to a single interpreter. */ typedef struct ThreadSpecificData { long numNsCreated; /* Count of the number of namespaces created * within the thread. This value is used as a * unique id for each namespace. Cannot be * per-interp because the nsId is used to * distinguish objects which can be passed * around between interps in the same thread, * but does not need to be global because * object internal reps are always per-thread * anyway. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * This structure contains a cached pointer to a namespace that is the result * of resolving the namespace's name in some other namespace. It is the * internal representation for a nsName object. It contains the pointer along * with some information that is used to check the cached pointer's validity. */ typedef struct ResolvedNsName { Namespace *nsPtr; /* A cached pointer to the Namespace that the * name resolved to. */ Namespace *refNsPtr; /* Points to the namespace context in which * the name was resolved. NULL if the name is * fully qualified and thus the resolution * does not depend on the context. */ int refCount; /* Reference count: 1 for each nsName object * that has a pointer to this ResolvedNsName * structure as its internal rep. This * structure can be freed when refCount * becomes zero. */ } ResolvedNsName; /* * Declarations for functions local to this file: */ static void DeleteImportedCmd(ClientData clientData); static int DoImport(Tcl_Interp *interp, Namespace *nsPtr, Tcl_HashEntry *hPtr, const char *cmdName, const char *pattern, Namespace *importNsPtr, int allowOverwrite); static void DupNsNameInternalRep(Tcl_Obj *objPtr,Tcl_Obj *copyPtr); static char * ErrorCodeRead(ClientData clientData,Tcl_Interp *interp, const char *name1, const char *name2, int flags); static char * ErrorInfoRead(ClientData clientData,Tcl_Interp *interp, const char *name1, const char *name2, int flags); static char * EstablishErrorCodeTraces(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); static char * EstablishErrorInfoTraces(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); static void FreeNsNameInternalRep(Tcl_Obj *objPtr); static int GetNamespaceFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr); static int InvokeImportedCmd(ClientData clientData, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static int InvokeImportedNRCmd(ClientData clientData, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static int NamespaceChildrenCmd(ClientData dummy, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static int NamespaceCodeCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NamespaceCurrentCmd(ClientData dummy, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static int NamespaceDeleteCmd(ClientData dummy,Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NamespaceEvalCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NRNamespaceEvalCmd(ClientData dummy, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static int NamespaceExistsCmd(ClientData dummy,Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NamespaceExportCmd(ClientData dummy,Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NamespaceForgetCmd(ClientData dummy,Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void NamespaceFree(Namespace *nsPtr); static int NamespaceImportCmd(ClientData dummy,Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NamespaceInscopeCmd(ClientData dummy, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static int NRNamespaceInscopeCmd(ClientData dummy, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static int NamespaceOriginCmd(ClientData dummy,Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NamespaceParentCmd(ClientData dummy,Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NamespacePathCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NamespaceQualifiersCmd(ClientData dummy, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static int NamespaceTailCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NamespaceUpvarCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int NamespaceUnknownCmd(ClientData dummy, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static int NamespaceWhichCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int SetNsNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void UnlinkNsPath(Namespace *nsPtr); static Tcl_NRPostProc NsEval_Callback; /* * This structure defines a Tcl object type that contains a namespace * reference. It is used in commands that take the name of a namespace as an * argument. The namespace reference is resolved, and the result in cached in * the object. */ static const Tcl_ObjType nsNameType = { "nsName", /* the type's name */ FreeNsNameInternalRep, /* freeIntRepProc */ DupNsNameInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ SetNsNameFromAny /* setFromAnyProc */ }; /* * Array of values describing how to implement each standard subcommand of the * "namespace" command. */ static const EnsembleImplMap defaultNamespaceMap[] = { {"children", NamespaceChildrenCmd, TclCompileBasic0To2ArgCmd, NULL, NULL, 0}, {"code", NamespaceCodeCmd, TclCompileNamespaceCodeCmd, NULL, NULL, 0}, {"current", NamespaceCurrentCmd, TclCompileNamespaceCurrentCmd, NULL, NULL, 0}, {"delete", NamespaceDeleteCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"ensemble", TclNamespaceEnsembleCmd, NULL, NULL, NULL, 0}, {"eval", NamespaceEvalCmd, NULL, NRNamespaceEvalCmd, NULL, 0}, {"exists", NamespaceExistsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"export", NamespaceExportCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"forget", NamespaceForgetCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"import", NamespaceImportCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"inscope", NamespaceInscopeCmd, NULL, NRNamespaceInscopeCmd, NULL, 0}, {"origin", NamespaceOriginCmd, TclCompileNamespaceOriginCmd, NULL, NULL, 0}, {"parent", NamespaceParentCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"path", NamespacePathCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"qualifiers", NamespaceQualifiersCmd, TclCompileNamespaceQualifiersCmd, NULL, NULL, 0}, {"tail", NamespaceTailCmd, TclCompileNamespaceTailCmd, NULL, NULL, 0}, {"unknown", NamespaceUnknownCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"upvar", NamespaceUpvarCmd, TclCompileNamespaceUpvarCmd, NULL, NULL, 0}, {"which", NamespaceWhichCmd, TclCompileNamespaceWhichCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* *---------------------------------------------------------------------- * * TclInitNamespaceSubsystem -- * * This function is called to initialize all the structures that are used * by namespaces on a per-process basis. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclInitNamespaceSubsystem(void) { /* * Does nothing for now. */ } /* *---------------------------------------------------------------------- * * Tcl_GetCurrentNamespace -- * * Returns a pointer to an interpreter's currently active namespace. * * Results: * Returns a pointer to the interpreter's current namespace. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Namespace * Tcl_GetCurrentNamespace( register Tcl_Interp *interp)/* Interpreter whose current namespace is * being queried. */ { return TclGetCurrentNamespace(interp); } /* *---------------------------------------------------------------------- * * Tcl_GetGlobalNamespace -- * * Returns a pointer to an interpreter's global :: namespace. * * Results: * Returns a pointer to the specified interpreter's global namespace. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Namespace * Tcl_GetGlobalNamespace( register Tcl_Interp *interp)/* Interpreter whose global namespace should * be returned. */ { return TclGetGlobalNamespace(interp); } /* *---------------------------------------------------------------------- * * Tcl_PushCallFrame -- * * Pushes a new call frame onto the interpreter's Tcl call stack. Called * when executing a Tcl procedure or a "namespace eval" or "namespace * inscope" command. * * Results: * Returns TCL_OK if successful, or TCL_ERROR (along with an error * message in the interpreter's result object) if something goes wrong. * * Side effects: * Modifies the interpreter's Tcl call stack. * *---------------------------------------------------------------------- */ int Tcl_PushCallFrame( Tcl_Interp *interp, /* Interpreter in which the new call frame is * to be pushed. */ Tcl_CallFrame *callFramePtr,/* Points to a call frame structure to push. * Storage for this has already been allocated * by the caller; typically this is the * address of a CallFrame structure allocated * on the caller's C stack. The call frame * will be initialized by this function. The * caller can pop the frame later with * Tcl_PopCallFrame, and it is responsible for * freeing the frame's storage. */ Tcl_Namespace *namespacePtr,/* Points to the namespace in which the frame * will execute. If NULL, the interpreter's * current namespace will be used. */ int isProcCallFrame) /* If nonzero, the frame represents a called * Tcl procedure and may have local vars. Vars * will ordinarily be looked up in the frame. * If new variables are created, they will be * created in the frame. If 0, the frame is * for a "namespace eval" or "namespace * inscope" command and var references are * treated as references to namespace * variables. */ { Interp *iPtr = (Interp *) interp; register CallFrame *framePtr = (CallFrame *) callFramePtr; register Namespace *nsPtr; if (namespacePtr == NULL) { nsPtr = (Namespace *) TclGetCurrentNamespace(interp); } else { nsPtr = (Namespace *) namespacePtr; /* * TODO: Examine whether it would be better to guard based on NS_DYING * or NS_KILLED. It appears that these are not tested because they can * be set in a global interp that has been [namespace delete]d, but * which never really completely goes away because of lingering global * things like ::errorInfo and [::unknown] and hidden commands. * Review of those designs might permit stricter checking here. */ if (nsPtr->flags & NS_DEAD) { Tcl_Panic("Trying to push call frame for dead namespace"); /*NOTREACHED*/ } } nsPtr->activationCount++; framePtr->nsPtr = nsPtr; framePtr->isProcCallFrame = isProcCallFrame; framePtr->objc = 0; framePtr->objv = NULL; framePtr->callerPtr = iPtr->framePtr; framePtr->callerVarPtr = iPtr->varFramePtr; if (iPtr->varFramePtr != NULL) { framePtr->level = (iPtr->varFramePtr->level + 1); } else { framePtr->level = 0; } framePtr->procPtr = NULL; /* no called procedure */ framePtr->varTablePtr = NULL; /* and no local variables */ framePtr->numCompiledLocals = 0; framePtr->compiledLocals = NULL; framePtr->clientData = NULL; framePtr->localCachePtr = NULL; framePtr->tailcallPtr = NULL; /* * Push the new call frame onto the interpreter's stack of procedure call * frames making it the current frame. */ iPtr->framePtr = framePtr; iPtr->varFramePtr = framePtr; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_PopCallFrame -- * * Removes a call frame from the Tcl call stack for the interpreter. * Called to remove a frame previously pushed by Tcl_PushCallFrame. * * Results: * None. * * Side effects: * Modifies the call stack of the interpreter. Resets various fields of * the popped call frame. If a namespace has been deleted and has no more * activations on the call stack, the namespace is destroyed. * *---------------------------------------------------------------------- */ void Tcl_PopCallFrame( Tcl_Interp *interp) /* Interpreter with call frame to pop. */ { register Interp *iPtr = (Interp *) interp; register CallFrame *framePtr = iPtr->framePtr; Namespace *nsPtr; /* * It's important to remove the call frame from the interpreter's stack of * call frames before deleting local variables, so that traces invoked by * the variable deletion don't see the partially-deleted frame. */ if (framePtr->callerPtr) { iPtr->framePtr = framePtr->callerPtr; iPtr->varFramePtr = framePtr->callerVarPtr; } else { /* Tcl_PopCallFrame: trying to pop rootCallFrame! */ } if (framePtr->varTablePtr != NULL) { TclDeleteVars(iPtr, framePtr->varTablePtr); ckfree(framePtr->varTablePtr); framePtr->varTablePtr = NULL; } if (framePtr->numCompiledLocals > 0) { TclDeleteCompiledLocalVars(iPtr, framePtr); if (--framePtr->localCachePtr->refCount == 0) { TclFreeLocalCache(interp, framePtr->localCachePtr); } framePtr->localCachePtr = NULL; } /* * Decrement the namespace's count of active call frames. If the namespace * is "dying" and there are no more active call frames, call * Tcl_DeleteNamespace to destroy it. */ nsPtr = framePtr->nsPtr; nsPtr->activationCount--; if ((nsPtr->flags & NS_DYING) && (nsPtr->activationCount - (nsPtr == iPtr->globalNsPtr) == 0)) { Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr); } framePtr->nsPtr = NULL; if (framePtr->tailcallPtr) { TclSetTailcall(interp, framePtr->tailcallPtr); } } /* *---------------------------------------------------------------------- * * TclPushStackFrame -- * * Allocates a new call frame in the interpreter's execution stack, then * pushes it onto the interpreter's Tcl call stack. Called when executing * a Tcl procedure or a "namespace eval" or "namespace inscope" command. * * Results: * Returns TCL_OK if successful, or TCL_ERROR (along with an error * message in the interpreter's result object) if something goes wrong. * * Side effects: * Modifies the interpreter's Tcl call stack. * *---------------------------------------------------------------------- */ int TclPushStackFrame( Tcl_Interp *interp, /* Interpreter in which the new call frame is * to be pushed. */ Tcl_CallFrame **framePtrPtr,/* Place to store a pointer to the stack * allocated call frame. */ Tcl_Namespace *namespacePtr,/* Points to the namespace in which the frame * will execute. If NULL, the interpreter's * current namespace will be used. */ int isProcCallFrame) /* If nonzero, the frame represents a called * Tcl procedure and may have local vars. Vars * will ordinarily be looked up in the frame. * If new variables are created, they will be * created in the frame. If 0, the frame is * for a "namespace eval" or "namespace * inscope" command and var references are * treated as references to namespace * variables. */ { *framePtrPtr = TclStackAlloc(interp, sizeof(CallFrame)); return Tcl_PushCallFrame(interp, *framePtrPtr, namespacePtr, isProcCallFrame); } void TclPopStackFrame( Tcl_Interp *interp) /* Interpreter with call frame to pop. */ { CallFrame *freePtr = ((Interp *) interp)->framePtr; Tcl_PopCallFrame(interp); TclStackFree(interp, freePtr); } /* *---------------------------------------------------------------------- * * EstablishErrorCodeTraces -- * * Creates traces on the ::errorCode variable to keep its value * consistent with the expectations of legacy code. * * Results: * None. * * Side effects: * Read and unset traces are established on ::errorCode. * *---------------------------------------------------------------------- */ static char * EstablishErrorCodeTraces( ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags) { Tcl_TraceVar2(interp, "errorCode", NULL, TCL_GLOBAL_ONLY|TCL_TRACE_READS, ErrorCodeRead, NULL); Tcl_TraceVar2(interp, "errorCode", NULL, TCL_GLOBAL_ONLY|TCL_TRACE_UNSETS, EstablishErrorCodeTraces, NULL); return NULL; } /* *---------------------------------------------------------------------- * * ErrorCodeRead -- * * Called when the ::errorCode variable is read. Copies the current value * of the interp's errorCode field into ::errorCode. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static char * ErrorCodeRead( ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags) { Interp *iPtr = (Interp *) interp; if (Tcl_InterpDeleted(interp) || !(iPtr->flags & ERR_LEGACY_COPY)) { return NULL; } if (iPtr->errorCode) { Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL, iPtr->errorCode, TCL_GLOBAL_ONLY); return NULL; } if (NULL == Tcl_ObjGetVar2(interp, iPtr->ecVar, NULL, TCL_GLOBAL_ONLY)) { Tcl_ObjSetVar2(interp, iPtr->ecVar, NULL, Tcl_NewObj(), TCL_GLOBAL_ONLY); } return NULL; } /* *---------------------------------------------------------------------- * * EstablishErrorInfoTraces -- * * Creates traces on the ::errorInfo variable to keep its value * consistent with the expectations of legacy code. * * Results: * None. * * Side effects: * Read and unset traces are established on ::errorInfo. * *---------------------------------------------------------------------- */ static char * EstablishErrorInfoTraces( ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags) { Tcl_TraceVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY|TCL_TRACE_READS, ErrorInfoRead, NULL); Tcl_TraceVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY|TCL_TRACE_UNSETS, EstablishErrorInfoTraces, NULL); return NULL; } /* *---------------------------------------------------------------------- * * ErrorInfoRead -- * * Called when the ::errorInfo variable is read. Copies the current value * of the interp's errorInfo field into ::errorInfo. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static char * ErrorInfoRead( ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags) { Interp *iPtr = (Interp *) interp; if (Tcl_InterpDeleted(interp) || !(iPtr->flags & ERR_LEGACY_COPY)) { return NULL; } if (iPtr->errorInfo) { Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL, iPtr->errorInfo, TCL_GLOBAL_ONLY); return NULL; } if (NULL == Tcl_ObjGetVar2(interp, iPtr->eiVar, NULL, TCL_GLOBAL_ONLY)) { Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL, Tcl_NewObj(), TCL_GLOBAL_ONLY); } return NULL; } /* *---------------------------------------------------------------------- * * Tcl_CreateNamespace -- * * Creates a new namespace with the given name. If there is no active * namespace (i.e., the interpreter is being initialized), the global :: * namespace is created and returned. * * Results: * Returns a pointer to the new namespace if successful. If the namespace * already exists or if another error occurs, this routine returns NULL, * along with an error message in the interpreter's result object. * * Side effects: * If the name contains "::" qualifiers and a parent namespace does not * already exist, it is automatically created. * *---------------------------------------------------------------------- */ Tcl_Namespace * Tcl_CreateNamespace( Tcl_Interp *interp, /* Interpreter in which a new namespace is * being created. Also used for error * reporting. */ const char *name, /* Name for the new namespace. May be a * qualified name with names of ancestor * namespaces separated by "::"s. */ ClientData clientData, /* One-word value to store with namespace. */ Tcl_NamespaceDeleteProc *deleteProc) /* Function called to delete client data when * the namespace is deleted. NULL if no * function should be called. */ { Interp *iPtr = (Interp *) interp; register Namespace *nsPtr, *ancestorPtr; Namespace *parentPtr, *dummy1Ptr, *dummy2Ptr; Namespace *globalNsPtr = iPtr->globalNsPtr; const char *simpleName; Tcl_HashEntry *entryPtr; Tcl_DString buffer1, buffer2; Tcl_DString *namePtr, *buffPtr; int newEntry, nameLen; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); const char *nameStr; Tcl_DString tmpBuffer; Tcl_DStringInit(&tmpBuffer); /* * If there is no active namespace, the interpreter is being initialized. */ if ((globalNsPtr == NULL) && (iPtr->varFramePtr == NULL)) { /* * Treat this namespace as the global namespace, and avoid looking for * a parent. */ parentPtr = NULL; simpleName = ""; goto doCreate; } /* * Ensure that there are no trailing colons as that causes chaos when a * deleteProc is specified. [Bug d614d63989] */ if (deleteProc != NULL) { nameStr = name + strlen(name) - 2; if (nameStr >= name && nameStr[1] == ':' && nameStr[0] == ':') { Tcl_DStringAppend(&tmpBuffer, name, -1); while ((nameLen = Tcl_DStringLength(&tmpBuffer)) > 0 && Tcl_DStringValue(&tmpBuffer)[nameLen-1] == ':') { Tcl_DStringSetLength(&tmpBuffer, nameLen-1); } name = Tcl_DStringValue(&tmpBuffer); } } /* * If we've ended up with an empty string now, we're attempting to create * the global namespace despite the global namespace existing. That's * naughty! */ if (*name == '\0') { Tcl_SetObjResult(interp, Tcl_NewStringObj("can't create namespace" " \"\": only global namespace can have empty name", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NAMESPACE", "CREATEGLOBAL", NULL); Tcl_DStringFree(&tmpBuffer); return NULL; } /* * Find the parent for the new namespace. */ TclGetNamespaceForQualName(interp, name, NULL, TCL_CREATE_NS_IF_UNKNOWN, &parentPtr, &dummy1Ptr, &dummy2Ptr, &simpleName); /* * If the unqualified name at the end is empty, there were trailing "::"s * after the namespace's name which we ignore. The new namespace was * already (recursively) created and is pointed to by parentPtr. */ if (*simpleName == '\0') { Tcl_DStringFree(&tmpBuffer); return (Tcl_Namespace *) parentPtr; } /* * Check for a bad namespace name and make sure that the name does not * already exist in the parent namespace. */ if ( #ifndef BREAK_NAMESPACE_COMPAT Tcl_FindHashEntry(&parentPtr->childTable, simpleName) != NULL #else parentPtr->childTablePtr != NULL && Tcl_FindHashEntry(parentPtr->childTablePtr, simpleName) != NULL #endif ) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create namespace \"%s\": already exists", name)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NAMESPACE", "CREATEEXISTING", NULL); Tcl_DStringFree(&tmpBuffer); return NULL; } /* * Create the new namespace and root it in its parent. Increment the count * of namespaces created. */ doCreate: nsPtr = ckalloc(sizeof(Namespace)); nameLen = strlen(simpleName) + 1; nsPtr->name = ckalloc(nameLen); memcpy(nsPtr->name, simpleName, nameLen); nsPtr->fullName = NULL; /* Set below. */ nsPtr->clientData = clientData; nsPtr->deleteProc = deleteProc; nsPtr->parentPtr = parentPtr; #ifndef BREAK_NAMESPACE_COMPAT Tcl_InitHashTable(&nsPtr->childTable, TCL_STRING_KEYS); #else nsPtr->childTablePtr = NULL; #endif nsPtr->nsId = ++(tsdPtr->numNsCreated); nsPtr->interp = interp; nsPtr->flags = 0; nsPtr->activationCount = 0; nsPtr->refCount = 0; Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS); TclInitVarHashTable(&nsPtr->varTable, nsPtr); nsPtr->exportArrayPtr = NULL; nsPtr->numExportPatterns = 0; nsPtr->maxExportPatterns = 0; nsPtr->cmdRefEpoch = 0; nsPtr->resolverEpoch = 0; nsPtr->cmdResProc = NULL; nsPtr->varResProc = NULL; nsPtr->compiledVarResProc = NULL; nsPtr->exportLookupEpoch = 0; nsPtr->ensembles = NULL; nsPtr->unknownHandlerPtr = NULL; nsPtr->commandPathLength = 0; nsPtr->commandPathArray = NULL; nsPtr->commandPathSourceList = NULL; nsPtr->earlyDeleteProc = NULL; if (parentPtr != NULL) { entryPtr = Tcl_CreateHashEntry( TclGetNamespaceChildTable((Tcl_Namespace *) parentPtr), simpleName, &newEntry); Tcl_SetHashValue(entryPtr, nsPtr); } else { /* * In the global namespace create traces to maintain the ::errorInfo * and ::errorCode variables. */ iPtr->globalNsPtr = nsPtr; EstablishErrorInfoTraces(NULL, interp, NULL, NULL, 0); EstablishErrorCodeTraces(NULL, interp, NULL, NULL, 0); } /* * Build the fully qualified name for this namespace. */ Tcl_DStringInit(&buffer1); Tcl_DStringInit(&buffer2); namePtr = &buffer1; buffPtr = &buffer2; for (ancestorPtr = nsPtr; ancestorPtr != NULL; ancestorPtr = ancestorPtr->parentPtr) { if (ancestorPtr != globalNsPtr) { register Tcl_DString *tempPtr = namePtr; TclDStringAppendLiteral(buffPtr, "::"); Tcl_DStringAppend(buffPtr, ancestorPtr->name, -1); TclDStringAppendDString(buffPtr, namePtr); /* * Clear the unwanted buffer or we end up appending to previous * results, making the namespace fullNames of nested namespaces * very wrong (and strange). */ TclDStringClear(namePtr); /* * Now swap the buffer pointers so that we build in the other * buffer. This is faster than repeated copying back and forth * between buffers. */ namePtr = buffPtr; buffPtr = tempPtr; } } name = Tcl_DStringValue(namePtr); nameLen = Tcl_DStringLength(namePtr); nsPtr->fullName = ckalloc(nameLen + 1); memcpy(nsPtr->fullName, name, (unsigned) nameLen + 1); Tcl_DStringFree(&buffer1); Tcl_DStringFree(&buffer2); Tcl_DStringFree(&tmpBuffer); /* * If compilation of commands originating from the parent NS is * suppressed, suppress it for commands originating in this one too. */ if (nsPtr->parentPtr != NULL && nsPtr->parentPtr->flags & NS_SUPPRESS_COMPILATION) { nsPtr->flags |= NS_SUPPRESS_COMPILATION; } /* * Return a pointer to the new namespace. */ return (Tcl_Namespace *) nsPtr; } /* *---------------------------------------------------------------------- * * Tcl_DeleteNamespace -- * * Deletes a namespace and all of the commands, variables, and other * namespaces within it. * * Results: * None. * * Side effects: * When a namespace is deleted, it is automatically removed as a child of * its parent namespace. Also, all its commands, variables and child * namespaces are deleted. * *---------------------------------------------------------------------- */ void Tcl_DeleteNamespace( Tcl_Namespace *namespacePtr)/* Points to the namespace to delete. */ { register Namespace *nsPtr = (Namespace *) namespacePtr; Interp *iPtr = (Interp *) nsPtr->interp; Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace((Tcl_Interp *) iPtr); Tcl_HashEntry *entryPtr; Tcl_HashSearch search; Command *cmdPtr; /* * Give anyone interested - notably TclOO - a chance to use this namespace * normally despite the fact that the namespace is going to go. Allows the * calling of destructors. Will only be called once (unless re-established * by the called function). [Bug 2950259] * * Note that setting this field requires access to the internal definition * of namespaces, so it should only be accessed by code that knows about * being careful with reentrancy. */ if (nsPtr->earlyDeleteProc != NULL) { Tcl_NamespaceDeleteProc *earlyDeleteProc = nsPtr->earlyDeleteProc; nsPtr->earlyDeleteProc = NULL; nsPtr->activationCount++; earlyDeleteProc(nsPtr->clientData); nsPtr->activationCount--; } /* * Delete all coroutine commands now: break the circular ref cycle between * the namespace and the coroutine command [Bug 2724403]. This code is * essentially duplicated in TclTeardownNamespace() for all other * commands. Don't optimize to Tcl_NextHashEntry() because of traces. * * NOTE: we could avoid traversing the ns's command list by keeping a * separate list of coros. */ for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); entryPtr != NULL;) { cmdPtr = Tcl_GetHashValue(entryPtr); if (cmdPtr->nreProc == TclNRInterpCoroutine) { Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr, (Tcl_Command) cmdPtr); entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); } else { entryPtr = Tcl_NextHashEntry(&search); } } /* * If the namespace has associated ensemble commands, delete them first. * This leaves the actual contents of the namespace alone (unless they are * linked ensemble commands, of course). Note that this code is actually * reentrant so command delete traces won't purturb things badly. */ while (nsPtr->ensembles != NULL) { EnsembleConfig *ensemblePtr = (EnsembleConfig *) nsPtr->ensembles; /* * Splice out and link to indicate that we've already been killed. */ nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr->next; ensemblePtr->next = ensemblePtr; Tcl_DeleteCommandFromToken(nsPtr->interp, ensemblePtr->token); } /* * If the namespace has a registered unknown handler (TIP 181), then free * it here. */ if (nsPtr->unknownHandlerPtr != NULL) { Tcl_DecrRefCount(nsPtr->unknownHandlerPtr); nsPtr->unknownHandlerPtr = NULL; } /* * If the namespace is on the call frame stack, it is marked as "dying" * (NS_DYING is OR'd into its flags): the namespace can't be looked up by * name but its commands and variables are still usable by those active * call frames. When all active call frames referring to the namespace * have been popped from the Tcl stack, Tcl_PopCallFrame will call this * function again to delete everything in the namespace. If no nsName * objects refer to the namespace (i.e., if its refCount is zero), its * commands and variables are deleted and the storage for its namespace * structure is freed. Otherwise, if its refCount is nonzero, the * namespace's commands and variables are deleted but the structure isn't * freed. Instead, NS_DEAD is OR'd into the structure's flags to allow the * namespace resolution code to recognize that the namespace is "deleted". * The structure's storage is freed by FreeNsNameInternalRep when its * refCount reaches 0. */ if (nsPtr->activationCount - (nsPtr == globalNsPtr) > 0) { nsPtr->flags |= NS_DYING; if (nsPtr->parentPtr != NULL) { entryPtr = Tcl_FindHashEntry( TclGetNamespaceChildTable((Tcl_Namespace *) nsPtr->parentPtr), nsPtr->name); if (entryPtr != NULL) { Tcl_DeleteHashEntry(entryPtr); } } nsPtr->parentPtr = NULL; } else if (!(nsPtr->flags & NS_KILLED)) { /* * Delete the namespace and everything in it. If this is the global * namespace, then clear it but don't free its storage unless the * interpreter is being torn down. Set the NS_KILLED flag to avoid * recursive calls here - if the namespace is really in the process of * being deleted, ignore any second call. */ nsPtr->flags |= (NS_DYING|NS_KILLED); TclTeardownNamespace(nsPtr); if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) { /* * If this is the global namespace, then it may have residual * "errorInfo" and "errorCode" variables for errors that occurred * while it was being torn down. Try to clear the variable list * one last time. */ TclDeleteNamespaceVars(nsPtr); #ifndef BREAK_NAMESPACE_COMPAT Tcl_DeleteHashTable(&nsPtr->childTable); #else if (nsPtr->childTablePtr != NULL) { Tcl_DeleteHashTable(nsPtr->childTablePtr); ckfree(nsPtr->childTablePtr); } #endif Tcl_DeleteHashTable(&nsPtr->cmdTable); /* * If the reference count is 0, then discard the namespace. * Otherwise, mark it as "dead" so that it can't be used. */ if (nsPtr->refCount == 0) { NamespaceFree(nsPtr); } else { nsPtr->flags |= NS_DEAD; } } else { /* * Restore the ::errorInfo and ::errorCode traces. */ EstablishErrorInfoTraces(NULL, nsPtr->interp, NULL, NULL, 0); EstablishErrorCodeTraces(NULL, nsPtr->interp, NULL, NULL, 0); /* * We didn't really kill it, so remove the KILLED marks, so it can * get killed later, avoiding mem leaks. */ nsPtr->flags &= ~(NS_DYING|NS_KILLED); } } } /* *---------------------------------------------------------------------- * * TclTeardownNamespace -- * * Used internally to dismantle and unlink a namespace when it is * deleted. Divorces the namespace from its parent, and deletes all * commands, variables, and child namespaces. * * This is kept separate from Tcl_DeleteNamespace so that the global * namespace can be handled specially. * * Results: * None. * * Side effects: * Removes this namespace from its parent's child namespace hashtable. * Deletes all commands, variables and namespaces in this namespace. * *---------------------------------------------------------------------- */ void TclTeardownNamespace( register Namespace *nsPtr) /* Points to the namespace to be dismantled * and unlinked from its parent. */ { Interp *iPtr = (Interp *) nsPtr->interp; register Tcl_HashEntry *entryPtr; Tcl_HashSearch search; Tcl_Namespace *childNsPtr; Tcl_Command cmd; int i; /* * Start by destroying the namespace's variable table, since variables * might trigger traces. Variable table should be cleared but not freed! * TclDeleteNamespaceVars frees it, so we reinitialize it afterwards. */ TclDeleteNamespaceVars(nsPtr); TclInitVarHashTable(&nsPtr->varTable, nsPtr); /* * Delete all commands in this namespace. Be careful when traversing the * hash table: when each command is deleted, it removes itself from the * command table. * * Don't optimize to Tcl_NextHashEntry() because of traces. */ for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); entryPtr != NULL; entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search)) { cmd = Tcl_GetHashValue(entryPtr); Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr, cmd); } Tcl_DeleteHashTable(&nsPtr->cmdTable); Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS); /* * Remove the namespace from its parent's child hashtable. */ if (nsPtr->parentPtr != NULL) { entryPtr = Tcl_FindHashEntry( TclGetNamespaceChildTable((Tcl_Namespace *) nsPtr->parentPtr), nsPtr->name); if (entryPtr != NULL) { Tcl_DeleteHashEntry(entryPtr); } } nsPtr->parentPtr = NULL; /* * Delete the namespace path if one is installed. */ if (nsPtr->commandPathLength != 0) { UnlinkNsPath(nsPtr); nsPtr->commandPathLength = 0; } if (nsPtr->commandPathSourceList != NULL) { NamespacePathEntry *nsPathPtr = nsPtr->commandPathSourceList; do { if (nsPathPtr->nsPtr != NULL && nsPathPtr->creatorNsPtr != NULL) { nsPathPtr->creatorNsPtr->cmdRefEpoch++; } nsPathPtr->nsPtr = NULL; nsPathPtr = nsPathPtr->nextPtr; } while (nsPathPtr != NULL); nsPtr->commandPathSourceList = NULL; } /* * Delete all the child namespaces. * * BE CAREFUL: When each child is deleted, it will divorce itself from its * parent. You can't traverse a hash table properly if its elements are * being deleted. We use only the Tcl_FirstHashEntry function to be safe. * * Don't optimize to Tcl_NextHashEntry() because of traces. */ #ifndef BREAK_NAMESPACE_COMPAT for (entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search); entryPtr != NULL; entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search)) { childNsPtr = Tcl_GetHashValue(entryPtr); Tcl_DeleteNamespace(childNsPtr); } #else if (nsPtr->childTablePtr != NULL) { for (entryPtr = Tcl_FirstHashEntry(nsPtr->childTablePtr, &search); entryPtr != NULL; entryPtr = Tcl_FirstHashEntry(nsPtr->childTablePtr,&search)) { childNsPtr = Tcl_GetHashValue(entryPtr); Tcl_DeleteNamespace(childNsPtr); } } #endif /* * Free the namespace's export pattern array. */ if (nsPtr->exportArrayPtr != NULL) { for (i = 0; i < nsPtr->numExportPatterns; i++) { ckfree(nsPtr->exportArrayPtr[i]); } ckfree(nsPtr->exportArrayPtr); nsPtr->exportArrayPtr = NULL; nsPtr->numExportPatterns = 0; nsPtr->maxExportPatterns = 0; } /* * Free any client data associated with the namespace. */ if (nsPtr->deleteProc != NULL) { nsPtr->deleteProc(nsPtr->clientData); } nsPtr->deleteProc = NULL; nsPtr->clientData = NULL; /* * Reset the namespace's id field to ensure that this namespace won't be * interpreted as valid by, e.g., the cache validation code for cached * command references in Tcl_GetCommandFromObj. */ nsPtr->nsId = 0; } /* *---------------------------------------------------------------------- * * NamespaceFree -- * * Called after a namespace has been deleted, when its reference count * reaches 0. Frees the data structure representing the namespace. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void NamespaceFree( register Namespace *nsPtr) /* Points to the namespace to free. */ { /* * Most of the namespace's contents are freed when the namespace is * deleted by Tcl_DeleteNamespace. All that remains is to free its names * (for error messages), and the structure itself. */ ckfree(nsPtr->name); ckfree(nsPtr->fullName); ckfree(nsPtr); } /* *---------------------------------------------------------------------- * * TclNsDecrRefCount -- * * Drops a reference to a namespace and frees it if the namespace has * been deleted and the last reference has just been dropped. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclNsDecrRefCount( Namespace *nsPtr) { nsPtr->refCount--; if ((nsPtr->refCount == 0) && (nsPtr->flags & NS_DEAD)) { NamespaceFree(nsPtr); } } /* *---------------------------------------------------------------------- * * Tcl_Export -- * * Makes all the commands matching a pattern available to later be * imported from the namespace specified by namespacePtr (or the current * namespace if namespacePtr is NULL). The specified pattern is appended * onto the namespace's export pattern list, which is optionally cleared * beforehand. * * Results: * Returns TCL_OK if successful, or TCL_ERROR (along with an error * message in the interpreter's result) if something goes wrong. * * Side effects: * Appends the export pattern onto the namespace's export list. * Optionally reset the namespace's export pattern list. * *---------------------------------------------------------------------- */ int Tcl_Export( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Namespace *namespacePtr,/* Points to the namespace from which commands * are to be exported. NULL for the current * namespace. */ const char *pattern, /* String pattern indicating which commands to * export. This pattern may not include any * namespace qualifiers; only commands in the * specified namespace may be exported. */ int resetListFirst) /* If nonzero, resets the namespace's export * list before appending. */ { #define INIT_EXPORT_PATTERNS 5 Namespace *nsPtr, *exportNsPtr, *dummyPtr; Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp); const char *simplePattern; char *patternCpy; int neededElems, len, i; /* * If the specified namespace is NULL, use the current namespace. */ if (namespacePtr == NULL) { nsPtr = (Namespace *) currNsPtr; } else { nsPtr = (Namespace *) namespacePtr; } /* * If resetListFirst is true (nonzero), clear the namespace's export * pattern list. */ if (resetListFirst) { if (nsPtr->exportArrayPtr != NULL) { for (i = 0; i < nsPtr->numExportPatterns; i++) { ckfree(nsPtr->exportArrayPtr[i]); } ckfree(nsPtr->exportArrayPtr); nsPtr->exportArrayPtr = NULL; TclInvalidateNsCmdLookup(nsPtr); nsPtr->numExportPatterns = 0; nsPtr->maxExportPatterns = 0; } } /* * Check that the pattern doesn't have namespace qualifiers. */ TclGetNamespaceForQualName(interp, pattern, nsPtr, TCL_NAMESPACE_ONLY, &exportNsPtr, &dummyPtr, &dummyPtr, &simplePattern); if ((exportNsPtr != nsPtr) || (strcmp(pattern, simplePattern) != 0)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("invalid export pattern" " \"%s\": pattern can't specify a namespace", pattern)); Tcl_SetErrorCode(interp, "TCL", "EXPORT", "INVALID", NULL); return TCL_ERROR; } /* * Make sure that we don't already have the pattern in the array */ if (nsPtr->exportArrayPtr != NULL) { for (i = 0; i < nsPtr->numExportPatterns; i++) { if (strcmp(pattern, nsPtr->exportArrayPtr[i]) == 0) { /* * The pattern already exists in the list. */ return TCL_OK; } } } /* * Make sure there is room in the namespace's pattern array for the new * pattern. */ neededElems = nsPtr->numExportPatterns + 1; if (neededElems > nsPtr->maxExportPatterns) { nsPtr->maxExportPatterns = nsPtr->maxExportPatterns ? 2 * nsPtr->maxExportPatterns : INIT_EXPORT_PATTERNS; nsPtr->exportArrayPtr = ckrealloc(nsPtr->exportArrayPtr, sizeof(char *) * nsPtr->maxExportPatterns); } /* * Add the pattern to the namespace's array of export patterns. */ len = strlen(pattern); patternCpy = ckalloc(len + 1); memcpy(patternCpy, pattern, (unsigned) len + 1); nsPtr->exportArrayPtr[nsPtr->numExportPatterns] = patternCpy; nsPtr->numExportPatterns++; /* * The list of commands actually exported from the namespace might have * changed (probably will have!) However, we do not need to recompute this * just yet; next time we need the info will be soon enough. */ TclInvalidateNsCmdLookup(nsPtr); return TCL_OK; #undef INIT_EXPORT_PATTERNS } /* *---------------------------------------------------------------------- * * Tcl_AppendExportList -- * * Appends onto the argument object the list of export patterns for the * specified namespace. * * Results: * The return value is normally TCL_OK; in this case the object * referenced by objPtr has each export pattern appended to it. If an * error occurs, TCL_ERROR is returned and the interpreter's result holds * an error message. * * Side effects: * If necessary, the object referenced by objPtr is converted into a list * object. * *---------------------------------------------------------------------- */ int Tcl_AppendExportList( Tcl_Interp *interp, /* Interpreter used for error reporting. */ Tcl_Namespace *namespacePtr,/* Points to the namespace whose export * pattern list is appended onto objPtr. NULL * for the current namespace. */ Tcl_Obj *objPtr) /* Points to the Tcl object onto which the * export pattern list is appended. */ { Namespace *nsPtr; int i, result; /* * If the specified namespace is NULL, use the current namespace. */ if (namespacePtr == NULL) { nsPtr = (Namespace *) TclGetCurrentNamespace(interp); } else { nsPtr = (Namespace *) namespacePtr; } /* * Append the export pattern list onto objPtr. */ for (i = 0; i < nsPtr->numExportPatterns; i++) { result = Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(nsPtr->exportArrayPtr[i], -1)); if (result != TCL_OK) { return result; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_Import -- * * Imports all of the commands matching a pattern into the namespace * specified by namespacePtr (or the current namespace if contextNsPtr is * NULL). This is done by creating a new command (the "imported command") * that points to the real command in its original namespace. * * If matching commands are on the autoload path but haven't been loaded * yet, this command forces them to be loaded, then creates the links to * them. * * Results: * Returns TCL_OK if successful, or TCL_ERROR (along with an error * message in the interpreter's result) if something goes wrong. * * Side effects: * Creates new commands in the importing namespace. These indirect calls * back to the real command and are deleted if the real commands are * deleted. * *---------------------------------------------------------------------- */ int Tcl_Import( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Namespace *namespacePtr,/* Points to the namespace into which the * commands are to be imported. NULL for the * current namespace. */ const char *pattern, /* String pattern indicating which commands to * import. This pattern should be qualified by * the name of the namespace from which to * import the command(s). */ int allowOverwrite) /* If nonzero, allow existing commands to be * overwritten by imported commands. If 0, * return an error if an imported cmd * conflicts with an existing one. */ { Namespace *nsPtr, *importNsPtr, *dummyPtr; const char *simplePattern; register Tcl_HashEntry *hPtr; Tcl_HashSearch search; /* * If the specified namespace is NULL, use the current namespace. */ if (namespacePtr == NULL) { nsPtr = (Namespace *) TclGetCurrentNamespace(interp); } else { nsPtr = (Namespace *) namespacePtr; } /* * First, invoke the "auto_import" command with the pattern being * imported. This command is part of the Tcl library. It looks for * imported commands in autoloaded libraries and loads them in. That way, * they will be found when we try to create links below. * * Note that we don't just call Tcl_EvalObjv() directly because we do not * want absence of the command to be a failure case. */ if (Tcl_FindCommand(interp,"auto_import",NULL,TCL_GLOBAL_ONLY) != NULL) { Tcl_Obj *objv[2]; int result; TclNewLiteralStringObj(objv[0], "auto_import"); objv[1] = Tcl_NewStringObj(pattern, -1); Tcl_IncrRefCount(objv[0]); Tcl_IncrRefCount(objv[1]); result = Tcl_EvalObjv(interp, 2, objv, TCL_GLOBAL_ONLY); Tcl_DecrRefCount(objv[0]); Tcl_DecrRefCount(objv[1]); if (result != TCL_OK) { return TCL_ERROR; } Tcl_ResetResult(interp); } /* * From the pattern, find the namespace from which we are importing and * get the simple pattern (no namespace qualifiers or ::'s) at the end. */ if (strlen(pattern) == 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj("empty import pattern",-1)); Tcl_SetErrorCode(interp, "TCL", "IMPORT", "EMPTY", NULL); return TCL_ERROR; } TclGetNamespaceForQualName(interp, pattern, nsPtr, TCL_NAMESPACE_ONLY, &importNsPtr, &dummyPtr, &dummyPtr, &simplePattern); if (importNsPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown namespace in import pattern \"%s\"", pattern)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, NULL); return TCL_ERROR; } if (importNsPtr == nsPtr) { if (pattern == simplePattern) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "no namespace specified in import pattern \"%s\"", pattern)); Tcl_SetErrorCode(interp, "TCL", "IMPORT", "ORIGIN", NULL); } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "import pattern \"%s\" tries to import from namespace" " \"%s\" into itself", pattern, importNsPtr->name)); Tcl_SetErrorCode(interp, "TCL", "IMPORT", "SELF", NULL); } return TCL_ERROR; } /* * Scan through the command table in the source namespace and look for * exported commands that match the string pattern. Create an "imported * command" in the current namespace for each imported command; these * commands redirect their invocations to the "real" command. */ if ((simplePattern != NULL) && TclMatchIsTrivial(simplePattern)) { hPtr = Tcl_FindHashEntry(&importNsPtr->cmdTable, simplePattern); if (hPtr == NULL) { return TCL_OK; } return DoImport(interp, nsPtr, hPtr, simplePattern, pattern, importNsPtr, allowOverwrite); } for (hPtr = Tcl_FirstHashEntry(&importNsPtr->cmdTable, &search); (hPtr != NULL); hPtr = Tcl_NextHashEntry(&search)) { char *cmdName = Tcl_GetHashKey(&importNsPtr->cmdTable, hPtr); if (Tcl_StringMatch(cmdName, simplePattern) && DoImport(interp, nsPtr, hPtr, cmdName, pattern, importNsPtr, allowOverwrite) == TCL_ERROR) { return TCL_ERROR; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * DoImport -- * * Import a particular command from one namespace into another. Helper * for Tcl_Import(). * * Results: * Standard Tcl result code. If TCL_ERROR, appends an error message to * the interpreter result. * * Side effects: * A new command is created in the target namespace unless this is a * reimport of exactly the same command as before. * *---------------------------------------------------------------------- */ static int DoImport( Tcl_Interp *interp, Namespace *nsPtr, Tcl_HashEntry *hPtr, const char *cmdName, const char *pattern, Namespace *importNsPtr, int allowOverwrite) { int i = 0, exported = 0; Tcl_HashEntry *found; /* * The command cmdName in the source namespace matches the pattern. Check * whether it was exported. If it wasn't, we ignore it. */ while (!exported && (i < importNsPtr->numExportPatterns)) { exported |= Tcl_StringMatch(cmdName, importNsPtr->exportArrayPtr[i++]); } if (!exported) { return TCL_OK; } /* * Unless there is a name clash, create an imported command in the current * namespace that refers to cmdPtr. */ found = Tcl_FindHashEntry(&nsPtr->cmdTable, cmdName); if ((found == NULL) || allowOverwrite) { /* * Create the imported command and its client data. To create the new * command in the current namespace, generate a fully qualified name * for it. */ Tcl_DString ds; Tcl_Command importedCmd; ImportedCmdData *dataPtr; Command *cmdPtr; ImportRef *refPtr; Tcl_DStringInit(&ds); Tcl_DStringAppend(&ds, nsPtr->fullName, -1); if (nsPtr != ((Interp *) interp)->globalNsPtr) { TclDStringAppendLiteral(&ds, "::"); } Tcl_DStringAppend(&ds, cmdName, -1); /* * Check whether creating the new imported command in the current * namespace would create a cycle of imported command references. */ cmdPtr = Tcl_GetHashValue(hPtr); if (found != NULL && cmdPtr->deleteProc == DeleteImportedCmd) { Command *overwrite = Tcl_GetHashValue(found); Command *linkCmd = cmdPtr; while (linkCmd->deleteProc == DeleteImportedCmd) { dataPtr = linkCmd->objClientData; linkCmd = dataPtr->realCmdPtr; if (overwrite == linkCmd) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "import pattern \"%s\" would create a loop" " containing command \"%s\"", pattern, Tcl_DStringValue(&ds))); Tcl_DStringFree(&ds); Tcl_SetErrorCode(interp, "TCL", "IMPORT", "LOOP", NULL); return TCL_ERROR; } } } dataPtr = ckalloc(sizeof(ImportedCmdData)); importedCmd = Tcl_NRCreateCommand(interp, Tcl_DStringValue(&ds), InvokeImportedCmd, InvokeImportedNRCmd, dataPtr, DeleteImportedCmd); dataPtr->realCmdPtr = cmdPtr; dataPtr->selfPtr = (Command *) importedCmd; dataPtr->selfPtr->compileProc = cmdPtr->compileProc; Tcl_DStringFree(&ds); /* * Create an ImportRef structure describing this new import command * and add it to the import ref list in the "real" command. */ refPtr = ckalloc(sizeof(ImportRef)); refPtr->importedCmdPtr = (Command *) importedCmd; refPtr->nextPtr = cmdPtr->importRefPtr; cmdPtr->importRefPtr = refPtr; } else { Command *overwrite = Tcl_GetHashValue(found); if (overwrite->deleteProc == DeleteImportedCmd) { ImportedCmdData *dataPtr = overwrite->objClientData; if (dataPtr->realCmdPtr == Tcl_GetHashValue(hPtr)) { /* * Repeated import of same command is acceptable. */ return TCL_OK; } } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't import command \"%s\": already exists", cmdName)); Tcl_SetErrorCode(interp, "TCL", "IMPORT", "OVERWRITE", NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ForgetImport -- * * Deletes commands previously imported into the namespace indicated. * The by namespacePtr, or the current namespace of interp, when * namespacePtr is NULL. The pattern controls which imported commands are * deleted. A simple pattern, one without namespace separators, matches * the current command names of imported commands in the namespace. * Matching imported commands are deleted. A qualified pattern is * interpreted as deletion selection on the basis of where the command is * imported from. The original command and "first link" command for each * imported command are determined, and they are matched against the * pattern. A match leads to deletion of the imported command. * * Results: * Returns TCL_ERROR and records an error message in the interp result if * a namespace qualified pattern refers to a namespace that does not * exist. Otherwise, returns TCL_OK. * * Side effects: * May delete commands. * *---------------------------------------------------------------------- */ int Tcl_ForgetImport( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Namespace *namespacePtr,/* Points to the namespace from which * previously imported commands should be * removed. NULL for current namespace. */ const char *pattern) /* String pattern indicating which imported * commands to remove. */ { Namespace *nsPtr, *sourceNsPtr, *dummyPtr; const char *simplePattern; char *cmdName; register Tcl_HashEntry *hPtr; Tcl_HashSearch search; /* * If the specified namespace is NULL, use the current namespace. */ if (namespacePtr == NULL) { nsPtr = (Namespace *) TclGetCurrentNamespace(interp); } else { nsPtr = (Namespace *) namespacePtr; } /* * Parse the pattern into its namespace-qualification (if any) and the * simple pattern. */ TclGetNamespaceForQualName(interp, pattern, nsPtr, TCL_NAMESPACE_ONLY, &sourceNsPtr, &dummyPtr, &dummyPtr, &simplePattern); if (sourceNsPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown namespace in namespace forget pattern \"%s\"", pattern)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", pattern, NULL); return TCL_ERROR; } if (strcmp(pattern, simplePattern) == 0) { /* * The pattern is simple. Delete any imported commands that match it. */ if (TclMatchIsTrivial(simplePattern)) { hPtr = Tcl_FindHashEntry(&nsPtr->cmdTable, simplePattern); if (hPtr != NULL) { Command *cmdPtr = Tcl_GetHashValue(hPtr); if (cmdPtr && (cmdPtr->deleteProc == DeleteImportedCmd)) { Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr); } } return TCL_OK; } for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); (hPtr != NULL); hPtr = Tcl_NextHashEntry(&search)) { Command *cmdPtr = Tcl_GetHashValue(hPtr); if (cmdPtr->deleteProc != DeleteImportedCmd) { continue; } cmdName = Tcl_GetHashKey(&nsPtr->cmdTable, hPtr); if (Tcl_StringMatch(cmdName, simplePattern)) { Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr); } } return TCL_OK; } /* * The pattern was namespace-qualified. */ for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); (hPtr != NULL); hPtr = Tcl_NextHashEntry(&search)) { Tcl_CmdInfo info; Tcl_Command token = Tcl_GetHashValue(hPtr); Tcl_Command origin = TclGetOriginalCommand(token); if (Tcl_GetCommandInfoFromToken(origin, &info) == 0) { continue; /* Not an imported command. */ } if (info.namespacePtr != (Tcl_Namespace *) sourceNsPtr) { /* * Original not in namespace we're matching. Check the first link * in the import chain. */ Command *cmdPtr = (Command *) token; ImportedCmdData *dataPtr = cmdPtr->objClientData; Tcl_Command firstToken = (Tcl_Command) dataPtr->realCmdPtr; if (firstToken == origin) { continue; } Tcl_GetCommandInfoFromToken(firstToken, &info); if (info.namespacePtr != (Tcl_Namespace *) sourceNsPtr) { continue; } origin = firstToken; } if (Tcl_StringMatch(Tcl_GetCommandName(NULL, origin), simplePattern)){ Tcl_DeleteCommandFromToken(interp, token); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclGetOriginalCommand -- * * An imported command is created in an namespace when a "real" command * is imported from another namespace. If the specified command is an * imported command, this function returns the original command it refers * to. * * Results: * If the command was imported into a sequence of namespaces a, b,...,n * where each successive namespace just imports the command from the * previous namespace, this function returns the Tcl_Command token in the * first namespace, a. Otherwise, if the specified command is not an * imported command, the function returns NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Command TclGetOriginalCommand( Tcl_Command command) /* The imported command for which the original * command should be returned. */ { register Command *cmdPtr = (Command *) command; ImportedCmdData *dataPtr; if (cmdPtr->deleteProc != DeleteImportedCmd) { return NULL; } while (cmdPtr->deleteProc == DeleteImportedCmd) { dataPtr = cmdPtr->objClientData; cmdPtr = dataPtr->realCmdPtr; } return (Tcl_Command) cmdPtr; } /* *---------------------------------------------------------------------- * * InvokeImportedCmd -- * * Invoked by Tcl whenever the user calls an imported command that was * created by Tcl_Import. Finds the "real" command (in another * namespace), and passes control to it. * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Returns a result in the interpreter's result object. If anything goes * wrong, the result object is set to an error message. * *---------------------------------------------------------------------- */ static int InvokeImportedNRCmd( ClientData clientData, /* Points to the imported command's * ImportedCmdData structure. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { ImportedCmdData *dataPtr = clientData; Command *realCmdPtr = dataPtr->realCmdPtr; TclSkipTailcall(interp); return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NOERR, realCmdPtr); } static int InvokeImportedCmd( ClientData clientData, /* Points to the imported command's * ImportedCmdData structure. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { return Tcl_NRCallObjProc(interp, InvokeImportedNRCmd, clientData, objc, objv); } /* *---------------------------------------------------------------------- * * DeleteImportedCmd -- * * Invoked by Tcl whenever an imported command is deleted. The "real" * command keeps a list of all the imported commands that refer to it, so * those imported commands can be deleted when the real command is * deleted. This function removes the imported command reference from the * real command's list, and frees up the memory associated with the * imported command. * * Results: * None. * * Side effects: * Removes the imported command from the real command's import list. * *---------------------------------------------------------------------- */ static void DeleteImportedCmd( ClientData clientData) /* Points to the imported command's * ImportedCmdData structure. */ { ImportedCmdData *dataPtr = clientData; Command *realCmdPtr = dataPtr->realCmdPtr; Command *selfPtr = dataPtr->selfPtr; register ImportRef *refPtr, *prevPtr; prevPtr = NULL; for (refPtr = realCmdPtr->importRefPtr; refPtr != NULL; refPtr = refPtr->nextPtr) { if (refPtr->importedCmdPtr == selfPtr) { /* * Remove *refPtr from real command's list of imported commands * that refer to it. */ if (prevPtr == NULL) { /* refPtr is first in list. */ realCmdPtr->importRefPtr = refPtr->nextPtr; } else { prevPtr->nextPtr = refPtr->nextPtr; } ckfree(refPtr); ckfree(dataPtr); return; } prevPtr = refPtr; } Tcl_Panic("DeleteImportedCmd: did not find cmd in real cmd's list of import references"); } /* *---------------------------------------------------------------------- * * TclGetNamespaceForQualName -- * * Given a qualified name specifying a command, variable, or namespace, * and a namespace in which to resolve the name, this function returns a * pointer to the namespace that contains the item. A qualified name * consists of the "simple" name of an item qualified by the names of an * arbitrary number of containing namespace separated by "::"s. If the * qualified name starts with "::", it is interpreted absolutely from the * global namespace. Otherwise, it is interpreted relative to the * namespace specified by cxtNsPtr if it is non-NULL. If cxtNsPtr is * NULL, the name is interpreted relative to the current namespace. * * A relative name like "foo::bar::x" can be found starting in either the * current namespace or in the global namespace. So each search usually * follows two tracks, and two possible namespaces are returned. If the * function sets either *nsPtrPtr or *altNsPtrPtr to NULL, then that path * failed. * * If "flags" contains TCL_GLOBAL_ONLY, the relative qualified name is * sought only in the global :: namespace. The alternate search (also) * starting from the global namespace is ignored and *altNsPtrPtr is set * NULL. * * If "flags" contains TCL_NAMESPACE_ONLY, the relative qualified name is * sought only in the namespace specified by cxtNsPtr. The alternate * search starting from the global namespace is ignored and *altNsPtrPtr * is set NULL. If both TCL_GLOBAL_ONLY and TCL_NAMESPACE_ONLY are * specified, TCL_GLOBAL_ONLY is ignored and the search starts from the * namespace specified by cxtNsPtr. * * If "flags" contains TCL_CREATE_NS_IF_UNKNOWN, all namespace components * of the qualified name that cannot be found are automatically created * within their specified parent. This makes sure that functions like * Tcl_CreateCommand always succeed. There is no alternate search path, * so *altNsPtrPtr is set NULL. * * If "flags" contains TCL_FIND_ONLY_NS, the qualified name is treated as * a reference to a namespace, and the entire qualified name is followed. * If the name is relative, the namespace is looked up only in the * current namespace. A pointer to the namespace is stored in *nsPtrPtr * and NULL is stored in *simpleNamePtr. Otherwise, if TCL_FIND_ONLY_NS * is not specified, only the leading components are treated as namespace * names, and a pointer to the simple name of the final component is * stored in *simpleNamePtr. * * Results: * It sets *nsPtrPtr and *altNsPtrPtr to point to the two possible * namespaces which represent the last (containing) namespace in the * qualified name. If the function sets either *nsPtrPtr or *altNsPtrPtr * to NULL, then the search along that path failed. The function also * stores a pointer to the simple name of the final component in * *simpleNamePtr. If the qualified name is "::" or was treated as a * namespace reference (TCL_FIND_ONLY_NS), the function stores a pointer * to the namespace in *nsPtrPtr, NULL in *altNsPtrPtr, and sets * *simpleNamePtr to point to an empty string. * * If there is an error, this function returns TCL_ERROR. If "flags" * contains TCL_LEAVE_ERR_MSG, an error message is returned in the * interpreter's result object. Otherwise, the interpreter's result * object is left unchanged. * * *actualCxtPtrPtr is set to the actual context namespace. It is set to * the input context namespace pointer in cxtNsPtr. If cxtNsPtr is NULL, * it is set to the current namespace context. * * For backwards compatibility with the TclPro byte code loader, this * function always returns TCL_OK. * * Side effects: * If "flags" contains TCL_CREATE_NS_IF_UNKNOWN, new namespaces may be * created. * *---------------------------------------------------------------------- */ int TclGetNamespaceForQualName( Tcl_Interp *interp, /* Interpreter in which to find the namespace * containing qualName. */ const char *qualName, /* A namespace-qualified name of an command, * variable, or namespace. */ Namespace *cxtNsPtr, /* The namespace in which to start the search * for qualName's namespace. If NULL start * from the current namespace. Ignored if * TCL_GLOBAL_ONLY is set. */ int flags, /* Flags controlling the search: an OR'd * combination of TCL_GLOBAL_ONLY, * TCL_NAMESPACE_ONLY, TCL_FIND_ONLY_NS, and * TCL_CREATE_NS_IF_UNKNOWN. */ Namespace **nsPtrPtr, /* Address where function stores a pointer to * containing namespace if qualName is found * starting from *cxtNsPtr or, if * TCL_GLOBAL_ONLY is set, if qualName is * found in the global :: namespace. NULL is * stored otherwise. */ Namespace **altNsPtrPtr, /* Address where function stores a pointer to * containing namespace if qualName is found * starting from the global :: namespace. * NULL is stored if qualName isn't found * starting from :: or if the TCL_GLOBAL_ONLY, * TCL_NAMESPACE_ONLY, TCL_FIND_ONLY_NS, * TCL_CREATE_NS_IF_UNKNOWN flag is set. */ Namespace **actualCxtPtrPtr,/* Address where function stores a pointer to * the actual namespace from which the search * started. This is either cxtNsPtr, the :: * namespace if TCL_GLOBAL_ONLY was specified, * or the current namespace if cxtNsPtr was * NULL. */ const char **simpleNamePtr) /* Address where function stores the simple * name at end of the qualName, or NULL if * qualName is "::" or the flag * TCL_FIND_ONLY_NS was specified. */ { Interp *iPtr = (Interp *) interp; Namespace *nsPtr = cxtNsPtr; Namespace *altNsPtr; Namespace *globalNsPtr = iPtr->globalNsPtr; const char *start, *end; const char *nsName; Tcl_HashEntry *entryPtr; Tcl_DString buffer; int len; /* * Determine the context namespace nsPtr in which to start the primary * search. If the qualName name starts with a "::" or TCL_GLOBAL_ONLY was * specified, search from the global namespace. Otherwise, use the * namespace given in cxtNsPtr, or if that is NULL, use the current * namespace context. Note that we always treat two or more adjacent ":"s * as a namespace separator. */ if (flags & TCL_GLOBAL_ONLY) { nsPtr = globalNsPtr; } else if (nsPtr == NULL) { nsPtr = iPtr->varFramePtr->nsPtr; } start = qualName; /* Points to start of qualifying * namespace. */ if ((*qualName == ':') && (*(qualName+1) == ':')) { start = qualName+2; /* Skip over the initial :: */ while (*start == ':') { start++; /* Skip over a subsequent : */ } nsPtr = globalNsPtr; if (*start == '\0') { /* qualName is just two or more * ":"s. */ *nsPtrPtr = globalNsPtr; *altNsPtrPtr = NULL; *actualCxtPtrPtr = globalNsPtr; *simpleNamePtr = start; /* Points to empty string. */ return TCL_OK; } } *actualCxtPtrPtr = nsPtr; /* * Start an alternate search path starting with the global namespace. * However, if the starting context is the global namespace, or if the * flag is set to search only the namespace *cxtNsPtr, ignore the * alternate search path. */ altNsPtr = globalNsPtr; if ((nsPtr == globalNsPtr) || (flags & (TCL_NAMESPACE_ONLY | TCL_FIND_ONLY_NS))) { altNsPtr = NULL; } /* * Loop to resolve each namespace qualifier in qualName. */ Tcl_DStringInit(&buffer); end = start; while (*start != '\0') { /* * Find the next namespace qualifier (i.e., a name ending in "::") or * the end of the qualified name (i.e., a name ending in "\0"). Set * len to the number of characters, starting from start, in the name; * set end to point after the "::"s or at the "\0". */ len = 0; for (end = start; *end != '\0'; end++) { if ((*end == ':') && (*(end+1) == ':')) { end += 2; /* Skip over the initial :: */ while (*end == ':') { end++; /* Skip over the subsequent : */ } break; /* Exit for loop; end is after ::'s */ } len++; } if (*end=='\0' && !(end-start>=2 && *(end-1)==':' && *(end-2)==':')) { /* * qualName ended with a simple name at start. If TCL_FIND_ONLY_NS * was specified, look this up as a namespace. Otherwise, start is * the name of a cmd or var and we are done. */ if (flags & TCL_FIND_ONLY_NS) { nsName = start; } else { *nsPtrPtr = nsPtr; *altNsPtrPtr = altNsPtr; *simpleNamePtr = start; Tcl_DStringFree(&buffer); return TCL_OK; } } else { /* * start points to the beginning of a namespace qualifier ending * in "::". end points to the start of a name in that namespace * that might be empty. Copy the namespace qualifier to a buffer * so it can be null terminated. We can't modify the incoming * qualName since it may be a string constant. */ TclDStringClear(&buffer); Tcl_DStringAppend(&buffer, start, len); nsName = Tcl_DStringValue(&buffer); } /* * Look up the namespace qualifier nsName in the current namespace * context. If it isn't found but TCL_CREATE_NS_IF_UNKNOWN is set, * create that qualifying namespace. This is needed for functions like * Tcl_CreateCommand that cannot fail. */ if (nsPtr != NULL) { #ifndef BREAK_NAMESPACE_COMPAT entryPtr = Tcl_FindHashEntry(&nsPtr->childTable, nsName); #else if (nsPtr->childTablePtr == NULL) { entryPtr = NULL; } else { entryPtr = Tcl_FindHashEntry(nsPtr->childTablePtr, nsName); } #endif if (entryPtr != NULL) { nsPtr = Tcl_GetHashValue(entryPtr); } else if (flags & TCL_CREATE_NS_IF_UNKNOWN) { Tcl_CallFrame *framePtr; (void) TclPushStackFrame(interp, &framePtr, (Tcl_Namespace *) nsPtr, /*isProcCallFrame*/ 0); nsPtr = (Namespace *) Tcl_CreateNamespace(interp, nsName, NULL, NULL); TclPopStackFrame(interp); if (nsPtr == NULL) { Tcl_Panic("Could not create namespace '%s'", nsName); } } else { /* Namespace not found and was not * created. */ nsPtr = NULL; } } /* * Look up the namespace qualifier in the alternate search path too. */ if (altNsPtr != NULL) { #ifndef BREAK_NAMESPACE_COMPAT entryPtr = Tcl_FindHashEntry(&altNsPtr->childTable, nsName); #else if (altNsPtr->childTablePtr != NULL) { entryPtr = Tcl_FindHashEntry(altNsPtr->childTablePtr, nsName); } else { entryPtr = NULL; } #endif if (entryPtr != NULL) { altNsPtr = Tcl_GetHashValue(entryPtr); } else { altNsPtr = NULL; } } /* * If both search paths have failed, return NULL results. */ if ((nsPtr == NULL) && (altNsPtr == NULL)) { *nsPtrPtr = NULL; *altNsPtrPtr = NULL; *simpleNamePtr = NULL; Tcl_DStringFree(&buffer); return TCL_OK; } start = end; } /* * We ignore trailing "::"s in a namespace name, but in a command or * variable name, trailing "::"s refer to the cmd or var named {}. */ if ((flags & TCL_FIND_ONLY_NS) || (end>start && *(end-1)!=':')) { *simpleNamePtr = NULL; /* Found namespace name. */ } else { *simpleNamePtr = end; /* Found cmd/var: points to empty * string. */ } /* * As a special case, if we are looking for a namespace and qualName is "" * and the current active namespace (nsPtr) is not the global namespace, * return NULL (no namespace was found). This is because namespaces can * not have empty names except for the global namespace. */ if ((flags & TCL_FIND_ONLY_NS) && (*qualName == '\0') && (nsPtr != globalNsPtr)) { nsPtr = NULL; } *nsPtrPtr = nsPtr; *altNsPtrPtr = altNsPtr; Tcl_DStringFree(&buffer); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_FindNamespace -- * * Searches for a namespace. * * Results: * Returns a pointer to the namespace if it is found. Otherwise, returns * NULL and leaves an error message in the interpreter's result object if * "flags" contains TCL_LEAVE_ERR_MSG. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Namespace * Tcl_FindNamespace( Tcl_Interp *interp, /* The interpreter in which to find the * namespace. */ const char *name, /* Namespace name. If it starts with "::", * will be looked up in global namespace. * Else, looked up first in contextNsPtr * (current namespace if contextNsPtr is * NULL), then in global namespace. */ Tcl_Namespace *contextNsPtr,/* Ignored if TCL_GLOBAL_ONLY flag is set or * if the name starts with "::". Otherwise, * points to namespace in which to resolve * name; if NULL, look up name in the current * namespace. */ register int flags) /* Flags controlling namespace lookup: an OR'd * combination of TCL_GLOBAL_ONLY and * TCL_LEAVE_ERR_MSG flags. */ { Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr; const char *dummy; /* * Find the namespace(s) that contain the specified namespace name. Add * the TCL_FIND_ONLY_NS flag to resolve the name all the way down to its * last component, a namespace. */ TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr, flags|TCL_FIND_ONLY_NS, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy); if (nsPtr != NULL) { return (Tcl_Namespace *) nsPtr; } if (flags & TCL_LEAVE_ERR_MSG) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown namespace \"%s\"", name)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, NULL); } return NULL; } /* *---------------------------------------------------------------------- * * Tcl_FindCommand -- * * Searches for a command. * * Results: * Returns a token for the command if it is found. Otherwise, if it can't * be found or there is an error, returns NULL and leaves an error * message in the interpreter's result object if "flags" contains * TCL_LEAVE_ERR_MSG. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Command Tcl_FindCommand( Tcl_Interp *interp, /* The interpreter in which to find the * command and to report errors. */ const char *name, /* Command's name. If it starts with "::", * will be looked up in global namespace. * Else, looked up first in contextNsPtr * (current namespace if contextNsPtr is * NULL), then in global namespace. */ Tcl_Namespace *contextNsPtr,/* Ignored if TCL_GLOBAL_ONLY flag set. * Otherwise, points to namespace in which to * resolve name. If NULL, look up name in the * current namespace. */ int flags) /* An OR'd combination of flags: * TCL_GLOBAL_ONLY (look up name only in * global namespace), TCL_NAMESPACE_ONLY (look * up only in contextNsPtr, or the current * namespace if contextNsPtr is NULL), and * TCL_LEAVE_ERR_MSG. If both TCL_GLOBAL_ONLY * and TCL_NAMESPACE_ONLY are given, * TCL_GLOBAL_ONLY is ignored. */ { Interp *iPtr = (Interp *) interp; Namespace *cxtNsPtr; register Tcl_HashEntry *entryPtr; register Command *cmdPtr; const char *simpleName; int result; /* * If this namespace has a command resolver, then give it first crack at * the command resolution. If the interpreter has any command resolvers, * consult them next. The command resolver functions may return a * Tcl_Command value, they may signal to continue onward, or they may * signal an error. */ if ((flags & TCL_GLOBAL_ONLY) || !strncmp(name, "::", 2)) { cxtNsPtr = (Namespace *) TclGetGlobalNamespace(interp); } else if (contextNsPtr != NULL) { cxtNsPtr = (Namespace *) contextNsPtr; } else { cxtNsPtr = (Namespace *) TclGetCurrentNamespace(interp); } if (cxtNsPtr->cmdResProc != NULL || iPtr->resolverPtr != NULL) { ResolverScheme *resPtr = iPtr->resolverPtr; Tcl_Command cmd; if (cxtNsPtr->cmdResProc) { result = cxtNsPtr->cmdResProc(interp, name, (Tcl_Namespace *) cxtNsPtr, flags, &cmd); } else { result = TCL_CONTINUE; } while (result == TCL_CONTINUE && resPtr) { if (resPtr->cmdResProc) { result = resPtr->cmdResProc(interp, name, (Tcl_Namespace *) cxtNsPtr, flags, &cmd); } resPtr = resPtr->nextPtr; } if (result == TCL_OK) { return cmd; } else if (result != TCL_CONTINUE) { return NULL; } } /* * Find the namespace(s) that contain the command. */ cmdPtr = NULL; if (cxtNsPtr->commandPathLength!=0 && strncmp(name, "::", 2) && !(flags & TCL_NAMESPACE_ONLY)) { int i; Namespace *pathNsPtr, *realNsPtr, *dummyNsPtr; (void) TclGetNamespaceForQualName(interp, name, cxtNsPtr, TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr, &simpleName); if ((realNsPtr != NULL) && (simpleName != NULL)) { if ((cxtNsPtr == realNsPtr) || !(realNsPtr->flags & NS_DYING)) { entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName); if (entryPtr != NULL) { cmdPtr = Tcl_GetHashValue(entryPtr); } } } /* * Next, check along the path. */ for (i=0 ; icommandPathLength && cmdPtr==NULL ; i++) { pathNsPtr = cxtNsPtr->commandPathArray[i].nsPtr; if (pathNsPtr == NULL) { continue; } (void) TclGetNamespaceForQualName(interp, name, pathNsPtr, TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr, &simpleName); if ((realNsPtr != NULL) && (simpleName != NULL) && !(realNsPtr->flags & NS_DYING)) { entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName); if (entryPtr != NULL) { cmdPtr = Tcl_GetHashValue(entryPtr); } } } /* * If we've still not found the command, look in the global namespace * as a last resort. */ if (cmdPtr == NULL) { (void) TclGetNamespaceForQualName(interp, name, NULL, TCL_GLOBAL_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr, &simpleName); if ((realNsPtr != NULL) && (simpleName != NULL) && !(realNsPtr->flags & NS_DYING)) { entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName); if (entryPtr != NULL) { cmdPtr = Tcl_GetHashValue(entryPtr); } } } } else { Namespace *nsPtr[2]; register int search; TclGetNamespaceForQualName(interp, name, (Namespace *) contextNsPtr, flags, &nsPtr[0], &nsPtr[1], &cxtNsPtr, &simpleName); /* * Look for the command in the command table of its namespace. Be sure * to check both possible search paths: from the specified namespace * context and from the global namespace. */ for (search = 0; (search < 2) && (cmdPtr == NULL); search++) { if ((nsPtr[search] != NULL) && (simpleName != NULL)) { entryPtr = Tcl_FindHashEntry(&nsPtr[search]->cmdTable, simpleName); if (entryPtr != NULL) { cmdPtr = Tcl_GetHashValue(entryPtr); } } } } if (cmdPtr != NULL) { return (Tcl_Command) cmdPtr; } if (flags & TCL_LEAVE_ERR_MSG) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown command \"%s\"", name)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", name, NULL); } return NULL; } /* *---------------------------------------------------------------------- * * TclResetShadowedCmdRefs -- * * Called when a command is added to a namespace to check for existing * command references that the new command may invalidate. Consider the * following cases that could happen when you add a command "foo" to a * namespace "b": * 1. It could shadow a command named "foo" at the global scope. If * it does, all command references in the namespace "b" are * suspect. * 2. Suppose the namespace "b" resides in a namespace "a". Then to * "a" the new command "b::foo" could shadow another command * "b::foo" in the global namespace. If so, then all command * references in "a" * are suspect. * The same checks are applied to all parent namespaces, until we reach * the global :: namespace. * * Results: * None. * * Side effects: * If the new command shadows an existing command, the cmdRefEpoch * counter is incremented in each namespace that sees the shadow. This * invalidates all command references that were previously cached in that * namespace. The next time the commands are used, they are resolved from * scratch. * *---------------------------------------------------------------------- */ void TclResetShadowedCmdRefs( Tcl_Interp *interp, /* Interpreter containing the new command. */ Command *newCmdPtr) /* Points to the new command. */ { char *cmdName; Tcl_HashEntry *hPtr; register Namespace *nsPtr; Namespace *trailNsPtr, *shadowNsPtr; Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp); int found, i; int trailFront = -1; int trailSize = 5; /* Formerly NUM_TRAIL_ELEMS. */ Namespace **trailPtr = TclStackAlloc(interp, trailSize * sizeof(Namespace *)); /* * Start at the namespace containing the new command, and work up through * the list of parents. Stop just before the global namespace, since the * global namespace can't "shadow" its own entries. * * The namespace "trail" list we build consists of the names of each * namespace that encloses the new command, in order from outermost to * innermost: for example, "a" then "b". Each iteration of this loop * eventually extends the trail upwards by one namespace, nsPtr. We use * this trail list to see if nsPtr (e.g. "a" in 2. above) could have * now-invalid cached command references. This will happen if nsPtr * (e.g. "a") contains a sequence of child namespaces (e.g. "b") such that * there is a identically-named sequence of child namespaces starting from * :: (e.g. "::b") whose tail namespace contains a command also named * cmdName. */ cmdName = Tcl_GetHashKey(newCmdPtr->hPtr->tablePtr, newCmdPtr->hPtr); for (nsPtr=newCmdPtr->nsPtr ; (nsPtr!=NULL) && (nsPtr!=globalNsPtr) ; nsPtr=nsPtr->parentPtr) { /* * Find the maximal sequence of child namespaces contained in nsPtr * such that there is a identically-named sequence of child namespaces * starting from ::. shadowNsPtr will be the tail of this sequence, or * the deepest namespace under :: that might contain a command now * shadowed by cmdName. We check below if shadowNsPtr actually * contains a command cmdName. */ found = 1; shadowNsPtr = globalNsPtr; for (i = trailFront; i >= 0; i--) { trailNsPtr = trailPtr[i]; #ifndef BREAK_NAMESPACE_COMPAT hPtr = Tcl_FindHashEntry(&shadowNsPtr->childTable, trailNsPtr->name); #else if (shadowNsPtr->childTablePtr != NULL) { hPtr = Tcl_FindHashEntry(shadowNsPtr->childTablePtr, trailNsPtr->name); } else { hPtr = NULL; } #endif if (hPtr != NULL) { shadowNsPtr = Tcl_GetHashValue(hPtr); } else { found = 0; break; } } /* * If shadowNsPtr contains a command named cmdName, we invalidate all * of the command refs cached in nsPtr. As a boundary case, * shadowNsPtr is initially :: and we check for case 1. above. */ if (found) { hPtr = Tcl_FindHashEntry(&shadowNsPtr->cmdTable, cmdName); if (hPtr != NULL) { nsPtr->cmdRefEpoch++; TclInvalidateNsPath(nsPtr); /* * If the shadowed command was compiled to bytecodes, we * invalidate all the bytecodes in nsPtr, to force a new * compilation. We use the resolverEpoch to signal the need * for a fresh compilation of every bytecode. */ if (((Command *)Tcl_GetHashValue(hPtr))->compileProc != NULL){ nsPtr->resolverEpoch++; } } } /* * Insert nsPtr at the front of the trail list: i.e., at the end of * the trailPtr array. */ trailFront++; if (trailFront == trailSize) { int newSize = 2 * trailSize; trailPtr = TclStackRealloc(interp, trailPtr, newSize * sizeof(Namespace *)); trailSize = newSize; } trailPtr[trailFront] = nsPtr; } TclStackFree(interp, trailPtr); } /* *---------------------------------------------------------------------- * * TclGetNamespaceFromObj, GetNamespaceFromObj -- * * Gets the namespace specified by the name in a Tcl_Obj. * * Results: * Returns TCL_OK if the namespace was resolved successfully, and stores * a pointer to the namespace in the location specified by nsPtrPtr. If * the namespace can't be found, or anything else goes wrong, this * function returns TCL_ERROR and writes an error message to interp, * if non-NULL. * * Side effects: * May update the internal representation for the object, caching the * namespace reference. The next time this function is called, the * namespace value can be found quickly. * *---------------------------------------------------------------------- */ int TclGetNamespaceFromObj( Tcl_Interp *interp, /* The current interpreter. */ Tcl_Obj *objPtr, /* The object to be resolved as the name of a * namespace. */ Tcl_Namespace **nsPtrPtr) /* Result namespace pointer goes here. */ { if (GetNamespaceFromObj(interp, objPtr, nsPtrPtr) == TCL_ERROR) { const char *name = TclGetString(objPtr); if ((name[0] == ':') && (name[1] == ':')) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "namespace \"%s\" not found", name)); } else { /* * Get the current namespace name. */ NamespaceCurrentCmd(NULL, interp, 1, NULL); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "namespace \"%s\" not found in \"%s\"", name, Tcl_GetStringResult(interp))); } Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", name, NULL); return TCL_ERROR; } return TCL_OK; } static int GetNamespaceFromObj( Tcl_Interp *interp, /* The current interpreter. */ Tcl_Obj *objPtr, /* The object to be resolved as the name of a * namespace. */ Tcl_Namespace **nsPtrPtr) /* Result namespace pointer goes here. */ { ResolvedNsName *resNamePtr; Namespace *nsPtr, *refNsPtr; if (objPtr->typePtr == &nsNameType) { /* * Check that the ResolvedNsName is still valid; avoid letting the ref * cross interps. */ resNamePtr = objPtr->internalRep.twoPtrValue.ptr1; nsPtr = resNamePtr->nsPtr; refNsPtr = resNamePtr->refNsPtr; if (!(nsPtr->flags & NS_DYING) && (interp == nsPtr->interp) && (!refNsPtr || ((interp == refNsPtr->interp) && (refNsPtr== (Namespace *) Tcl_GetCurrentNamespace(interp))))){ *nsPtrPtr = (Tcl_Namespace *) nsPtr; return TCL_OK; } } if (SetNsNameFromAny(interp, objPtr) == TCL_OK) { resNamePtr = objPtr->internalRep.twoPtrValue.ptr1; *nsPtrPtr = (Tcl_Namespace *) resNamePtr->nsPtr; return TCL_OK; } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclInitNamespaceCmd -- * * This function is called to create the "namespace" Tcl command. See the * user documentation for details on what it does. * * Results: * Handle for the namespace command, or NULL on failure. * * Side effects: * none * *---------------------------------------------------------------------- */ Tcl_Command TclInitNamespaceCmd( Tcl_Interp *interp) /* Current interpreter. */ { return TclMakeEnsemble(interp, "namespace", defaultNamespaceMap); } /* *---------------------------------------------------------------------- * * NamespaceChildrenCmd -- * * Invoked to implement the "namespace children" command that returns a * list containing the fully-qualified names of the child namespaces of a * given namespace. Handles the following syntax: * * namespace children ?name? ?pattern? * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Returns a result in the interpreter's result object. If anything goes * wrong, the result is an error message. * *---------------------------------------------------------------------- */ static int NamespaceChildrenCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *namespacePtr; Namespace *nsPtr, *childNsPtr; Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp); const char *pattern = NULL; Tcl_DString buffer; register Tcl_HashEntry *entryPtr; Tcl_HashSearch search; Tcl_Obj *listPtr, *elemPtr; /* * Get a pointer to the specified namespace, or the current namespace. */ if (objc == 1) { nsPtr = (Namespace *) TclGetCurrentNamespace(interp); } else if ((objc == 2) || (objc == 3)) { if (TclGetNamespaceFromObj(interp, objv[1], &namespacePtr) != TCL_OK){ return TCL_ERROR; } nsPtr = (Namespace *) namespacePtr; } else { Tcl_WrongNumArgs(interp, 1, objv, "?name? ?pattern?"); return TCL_ERROR; } /* * Get the glob-style pattern, if any, used to narrow the search. */ Tcl_DStringInit(&buffer); if (objc == 3) { const char *name = TclGetString(objv[2]); if ((*name == ':') && (*(name+1) == ':')) { pattern = name; } else { Tcl_DStringAppend(&buffer, nsPtr->fullName, -1); if (nsPtr != globalNsPtr) { TclDStringAppendLiteral(&buffer, "::"); } Tcl_DStringAppend(&buffer, name, -1); pattern = Tcl_DStringValue(&buffer); } } /* * Create a list containing the full names of all child namespaces whose * names match the specified pattern, if any. */ listPtr = Tcl_NewListObj(0, NULL); if ((pattern != NULL) && TclMatchIsTrivial(pattern)) { unsigned int length = strlen(nsPtr->fullName); if (strncmp(pattern, nsPtr->fullName, length) != 0) { goto searchDone; } if ( #ifndef BREAK_NAMESPACE_COMPAT Tcl_FindHashEntry(&nsPtr->childTable, pattern+length) != NULL #else nsPtr->childTablePtr != NULL && Tcl_FindHashEntry(nsPtr->childTablePtr, pattern+length) != NULL #endif ) { Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(pattern, -1)); } goto searchDone; } #ifndef BREAK_NAMESPACE_COMPAT entryPtr = Tcl_FirstHashEntry(&nsPtr->childTable, &search); #else if (nsPtr->childTablePtr == NULL) { goto searchDone; } entryPtr = Tcl_FirstHashEntry(nsPtr->childTablePtr, &search); #endif while (entryPtr != NULL) { childNsPtr = Tcl_GetHashValue(entryPtr); if ((pattern == NULL) || Tcl_StringMatch(childNsPtr->fullName, pattern)) { elemPtr = Tcl_NewStringObj(childNsPtr->fullName, -1); Tcl_ListObjAppendElement(interp, listPtr, elemPtr); } entryPtr = Tcl_NextHashEntry(&search); } searchDone: Tcl_SetObjResult(interp, listPtr); Tcl_DStringFree(&buffer); return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceCodeCmd -- * * Invoked to implement the "namespace code" command to capture the * namespace context of a command. Handles the following syntax: * * namespace code arg * * Here "arg" can be a list. "namespace code arg" produces a result * equivalent to that produced by the command * * list ::namespace inscope [namespace current] $arg * * However, if "arg" is itself a scoped value starting with "::namespace * inscope", then the result is just "arg". * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * If anything goes wrong, this function returns an error message as the * result in the interpreter's result object. * *---------------------------------------------------------------------- */ static int NamespaceCodeCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Namespace *currNsPtr; Tcl_Obj *listPtr, *objPtr; register const char *arg; int length; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "arg"); return TCL_ERROR; } /* * If "arg" is already a scoped value, then return it directly. * Take care to only check for scoping in precisely the style that * [::namespace code] generates it. Anything more forgiving can have * the effect of failing in namespaces that contain their own custom " "namespace" command. [Bug 3202171]. */ arg = TclGetStringFromObj(objv[1], &length); if (*arg==':' && length > 20 && strncmp(arg, "::namespace inscope ", 20) == 0) { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } /* * Otherwise, construct a scoped command by building a list with * "namespace inscope", the full name of the current namespace, and the * argument "arg". By constructing a list, we ensure that scoped commands * are interpreted properly when they are executed later, by the * "namespace inscope" command. */ TclNewObj(listPtr); TclNewLiteralStringObj(objPtr, "::namespace"); Tcl_ListObjAppendElement(interp, listPtr, objPtr); TclNewLiteralStringObj(objPtr, "inscope"); Tcl_ListObjAppendElement(interp, listPtr, objPtr); currNsPtr = (Namespace *) TclGetCurrentNamespace(interp); if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) { TclNewLiteralStringObj(objPtr, "::"); } else { objPtr = Tcl_NewStringObj(currNsPtr->fullName, -1); } Tcl_ListObjAppendElement(interp, listPtr, objPtr); Tcl_ListObjAppendElement(interp, listPtr, objv[1]); Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceCurrentCmd -- * * Invoked to implement the "namespace current" command which returns the * fully-qualified name of the current namespace. Handles the following * syntax: * * namespace current * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Returns a result in the interpreter's result object. If anything goes * wrong, the result is an error message. * *---------------------------------------------------------------------- */ static int NamespaceCurrentCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register Namespace *currNsPtr; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } /* * The "real" name of the global namespace ("::") is the null string, but * we return "::" for it as a convenience to programmers. Note that "" and * "::" are treated as synonyms by the namespace code so that it is still * easy to do things like: * * namespace [namespace current]::bar { ... } */ currNsPtr = (Namespace *) TclGetCurrentNamespace(interp); if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("::", 2)); } else { Tcl_SetObjResult(interp, Tcl_NewStringObj(currNsPtr->fullName, -1)); } return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceDeleteCmd -- * * Invoked to implement the "namespace delete" command to delete * namespace(s). Handles the following syntax: * * namespace delete ?name name...? * * Each name identifies a namespace. It may include a sequence of * namespace qualifiers separated by "::"s. If a namespace is found, it * is deleted: all variables and procedures contained in that namespace * are deleted. If that namespace is being used on the call stack, it is * kept alive (but logically deleted) until it is removed from the call * stack: that is, it can no longer be referenced by name but any * currently executing procedure that refers to it is allowed to do so * until the procedure returns. If the namespace can't be found, this * function returns an error. If no namespaces are specified, this * command does nothing. * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Deletes the specified namespaces. If anything goes wrong, this * function returns an error message in the interpreter's result object. * *---------------------------------------------------------------------- */ static int NamespaceDeleteCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *namespacePtr; const char *name; register int i; if (objc < 1) { Tcl_WrongNumArgs(interp, 1, objv, "?name name...?"); return TCL_ERROR; } /* * Destroying one namespace may cause another to be destroyed. Break this * into two passes: first check to make sure that all namespaces on the * command line are valid, and report any errors. */ for (i = 1; i < objc; i++) { name = TclGetString(objv[i]); namespacePtr = Tcl_FindNamespace(interp, name, NULL, /*flags*/ 0); if ((namespacePtr == NULL) || (((Namespace *) namespacePtr)->flags & NS_KILLED)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown namespace \"%s\" in namespace delete command", TclGetString(objv[i]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", TclGetString(objv[i]), NULL); return TCL_ERROR; } } /* * Okay, now delete each namespace. */ for (i = 1; i < objc; i++) { name = TclGetString(objv[i]); namespacePtr = Tcl_FindNamespace(interp, name, NULL, /* flags */ 0); if (namespacePtr) { Tcl_DeleteNamespace(namespacePtr); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceEvalCmd -- * * Invoked to implement the "namespace eval" command. Executes commands * in a namespace. If the namespace does not already exist, it is * created. Handles the following syntax: * * namespace eval name arg ?arg...? * * If more than one arg argument is specified, the command that is * executed is the result of concatenating the arguments together with a * space between each argument. * * Results: * Returns TCL_OK if the namespace is found and the commands are executed * successfully. Returns TCL_ERROR if anything goes wrong. * * Side effects: * Returns the result of the command in the interpreter's result object. * If anything goes wrong, this function returns an error message as the * result. * *---------------------------------------------------------------------- */ static int NamespaceEvalCmd( ClientData clientData, /* Arbitrary value passed to cmd. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, NRNamespaceEvalCmd, clientData, objc, objv); } static int NRNamespaceEvalCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; CmdFrame *invoker; int word; Tcl_Namespace *namespacePtr; CallFrame *framePtr, **framePtrPtr; Tcl_Obj *objPtr; int result; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "name arg ?arg...?"); return TCL_ERROR; } /* * Try to resolve the namespace reference, caching the result in the * namespace object along the way. */ result = GetNamespaceFromObj(interp, objv[1], &namespacePtr); /* * If the namespace wasn't found, try to create it. */ if (result == TCL_ERROR) { const char *name = TclGetString(objv[1]); namespacePtr = Tcl_CreateNamespace(interp, name, NULL, NULL); if (namespacePtr == NULL) { return TCL_ERROR; } } /* * Make the specified namespace the current namespace and evaluate the * command(s). */ /* This is needed to satisfy GCC 3.3's strict aliasing rules */ framePtrPtr = &framePtr; (void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr, namespacePtr, /*isProcCallFrame*/ 0); if (iPtr->ensembleRewrite.sourceObjs == NULL) { framePtr->objc = objc; framePtr->objv = objv; } else { framePtr->objc = objc + iPtr->ensembleRewrite.numRemovedObjs - iPtr->ensembleRewrite.numInsertedObjs; framePtr->objv = iPtr->ensembleRewrite.sourceObjs; } if (objc == 3) { /* * TIP #280: Make actual argument location available to eval'd script. */ objPtr = objv[2]; invoker = iPtr->cmdFramePtr; word = 3; TclArgumentGet(interp, objPtr, &invoker, &word); } else { /* * More than one argument: concatenate them together with spaces * between, then evaluate the result. Tcl_EvalObjEx will delete the * object when it decrements its refcount after eval'ing it. */ objPtr = Tcl_ConcatObj(objc-2, objv+2); invoker = NULL; word = 0; } /* * TIP #280: Make invoking context available to eval'd script. */ TclNRAddCallback(interp, NsEval_Callback, namespacePtr, "eval", NULL, NULL); return TclNREvalObjEx(interp, objPtr, 0, invoker, word); } static int NsEval_Callback( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Namespace *namespacePtr = data[0]; if (result == TCL_ERROR) { int length = strlen(namespacePtr->fullName); int limit = 200; int overflow = (length > limit); char *cmd = data[1]; Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (in namespace %s \"%.*s%s\" script line %d)", cmd, (overflow ? limit : length), namespacePtr->fullName, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } /* * Restore the previous "current" namespace. */ TclPopStackFrame(interp); return result; } /* *---------------------------------------------------------------------- * * NamespaceExistsCmd -- * * Invoked to implement the "namespace exists" command that returns true * if the given namespace currently exists, and false otherwise. Handles * the following syntax: * * namespace exists name * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Returns a result in the interpreter's result object. If anything goes * wrong, the result is an error message. * *---------------------------------------------------------------------- */ static int NamespaceExistsCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *namespacePtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj( GetNamespaceFromObj(interp, objv[1], &namespacePtr) == TCL_OK)); return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceExportCmd -- * * Invoked to implement the "namespace export" command that specifies * which commands are exported from a namespace. The exported commands * are those that can be imported into another namespace using "namespace * import". Both commands defined in a namespace and commands the * namespace has imported can be exported by a namespace. This command * has the following syntax: * * namespace export ?-clear? ?pattern pattern...? * * Each pattern may contain "string match"-style pattern matching special * characters, but the pattern may not include any namespace qualifiers: * that is, the pattern must specify commands in the current (exporting) * namespace. The specified patterns are appended onto the namespace's * list of export patterns. * * To reset the namespace's export pattern list, specify the "-clear" * flag. * * If there are no export patterns and the "-clear" flag isn't given, * this command returns the namespace's current export list. * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Returns a result in the interpreter's result object. If anything goes * wrong, the result is an error message. * *---------------------------------------------------------------------- */ static int NamespaceExportCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int firstArg, i; if (objc < 1) { Tcl_WrongNumArgs(interp, 1, objv, "?-clear? ?pattern pattern...?"); return TCL_ERROR; } /* * If no pattern arguments are given, and "-clear" isn't specified, return * the namespace's current export pattern list. */ if (objc == 1) { Tcl_Obj *listPtr = Tcl_NewObj(); (void) Tcl_AppendExportList(interp, NULL, listPtr); Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* * Process the optional "-clear" argument. */ firstArg = 1; if (strcmp("-clear", Tcl_GetString(objv[firstArg])) == 0) { Tcl_Export(interp, NULL, "::", 1); Tcl_ResetResult(interp); firstArg++; } /* * Add each pattern to the namespace's export pattern list. */ for (i = firstArg; i < objc; i++) { int result = Tcl_Export(interp, NULL, Tcl_GetString(objv[i]), 0); if (result != TCL_OK) { return result; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceForgetCmd -- * * Invoked to implement the "namespace forget" command to remove imported * commands from a namespace. Handles the following syntax: * * namespace forget ?pattern pattern...? * * Each pattern is a name like "foo::*" or "a::b::x*". That is, the * pattern may include the special pattern matching characters recognized * by the "string match" command, but only in the command name at the end * of the qualified name; the special pattern characters may not appear * in a namespace name. All of the commands that match that pattern are * checked to see if they have an imported command in the current * namespace that refers to the matched command. If there is an alias, it * is removed. * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Imported commands are removed from the current namespace. If anything * goes wrong, this function returns an error message in the * interpreter's result object. * *---------------------------------------------------------------------- */ static int NamespaceForgetCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *pattern; register int i, result; if (objc < 1) { Tcl_WrongNumArgs(interp, 1, objv, "?pattern pattern...?"); return TCL_ERROR; } for (i = 1; i < objc; i++) { pattern = TclGetString(objv[i]); result = Tcl_ForgetImport(interp, NULL, pattern); if (result != TCL_OK) { return result; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceImportCmd -- * * Invoked to implement the "namespace import" command that imports * commands into a namespace. Handles the following syntax: * * namespace import ?-force? ?pattern pattern...? * * Each pattern is a namespace-qualified name like "foo::*", "a::b::x*", * or "bar::p". That is, the pattern may include the special pattern * matching characters recognized by the "string match" command, but only * in the command name at the end of the qualified name; the special * pattern characters may not appear in a namespace name. All of the * commands that match the pattern and which are exported from their * namespace are made accessible from the current namespace context. This * is done by creating a new "imported command" in the current namespace * that points to the real command in its original namespace; when the * imported command is called, it invokes the real command. * * If an imported command conflicts with an existing command, it is * treated as an error. But if the "-force" option is included, then * existing commands are overwritten by the imported commands. * * If there are no pattern arguments and the "-force" flag isn't given, * this command returns the list of commands currently imported in * the current namespace. * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Adds imported commands to the current namespace. If anything goes * wrong, this function returns an error message in the interpreter's * result object. * *---------------------------------------------------------------------- */ static int NamespaceImportCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int allowOverwrite = 0; const char *string, *pattern; register int i, result; int firstArg; if (objc < 1) { Tcl_WrongNumArgs(interp, 1, objv, "?-force? ?pattern pattern...?"); return TCL_ERROR; } /* * Skip over the optional "-force" as the first argument. */ firstArg = 1; if (firstArg < objc) { string = TclGetString(objv[firstArg]); if ((*string == '-') && (strcmp(string, "-force") == 0)) { allowOverwrite = 1; firstArg++; } } else { /* * When objc == 1, command is just [namespace import]. Introspection * form to return list of imported commands. */ Tcl_HashEntry *hPtr; Tcl_HashSearch search; Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp); Tcl_Obj *listPtr; TclNewObj(listPtr); for (hPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Command *cmdPtr = Tcl_GetHashValue(hPtr); if (cmdPtr->deleteProc == DeleteImportedCmd) { Tcl_ListObjAppendElement(NULL, listPtr, Tcl_NewStringObj( Tcl_GetHashKey(&nsPtr->cmdTable, hPtr) ,-1)); } } Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* * Handle the imports for each of the patterns. */ for (i = firstArg; i < objc; i++) { pattern = TclGetString(objv[i]); result = Tcl_Import(interp, NULL, pattern, allowOverwrite); if (result != TCL_OK) { return result; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceInscopeCmd -- * * Invoked to implement the "namespace inscope" command that executes a * script in the context of a particular namespace. This command is not * expected to be used directly by programmers; calls to it are generated * implicitly when programs use "namespace code" commands to register * callback scripts. Handles the following syntax: * * namespace inscope name arg ?arg...? * * The "namespace inscope" command is much like the "namespace eval" * command except that it has lappend semantics and the namespace must * already exist. It treats the first argument as a list, and appends any * arguments after the first onto the end as proper list elements. For * example, * * namespace inscope ::foo {a b} c d e * * is equivalent to * * namespace eval ::foo [concat {a b} [list c d e]] * * This lappend semantics is important because many callback scripts are * actually prefixes. * * Results: * Returns TCL_OK to indicate success, or TCL_ERROR to indicate failure. * * Side effects: * Returns a result in the Tcl interpreter's result object. * *---------------------------------------------------------------------- */ static int NamespaceInscopeCmd( ClientData clientData, /* Arbitrary value passed to cmd. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, NRNamespaceInscopeCmd, clientData, objc, objv); } static int NRNamespaceInscopeCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *namespacePtr; CallFrame *framePtr, **framePtrPtr; register Interp *iPtr = (Interp *) interp; int i; Tcl_Obj *cmdObjPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "name arg ?arg...?"); return TCL_ERROR; } /* * Resolve the namespace reference. */ if (TclGetNamespaceFromObj(interp, objv[1], &namespacePtr) != TCL_OK) { return TCL_ERROR; } /* * Make the specified namespace the current namespace. */ framePtrPtr = &framePtr; /* This is needed to satisfy GCC's * strict aliasing rules. */ (void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr, namespacePtr, /*isProcCallFrame*/ 0); if (iPtr->ensembleRewrite.sourceObjs == NULL) { framePtr->objc = objc; framePtr->objv = objv; } else { framePtr->objc = objc + iPtr->ensembleRewrite.numRemovedObjs - iPtr->ensembleRewrite.numInsertedObjs; framePtr->objv = iPtr->ensembleRewrite.sourceObjs; } /* * Execute the command. If there is just one argument, just treat it as a * script and evaluate it. Otherwise, create a list from the arguments * after the first one, then concatenate the first argument and the list * of extra arguments to form the command to evaluate. */ if (objc == 3) { cmdObjPtr = objv[2]; } else { Tcl_Obj *concatObjv[2]; register Tcl_Obj *listPtr; listPtr = Tcl_NewListObj(0, NULL); for (i = 3; i < objc; i++) { if (Tcl_ListObjAppendElement(interp, listPtr, objv[i]) != TCL_OK){ Tcl_DecrRefCount(listPtr); /* Free unneeded obj. */ return TCL_ERROR; } } concatObjv[0] = objv[2]; concatObjv[1] = listPtr; cmdObjPtr = Tcl_ConcatObj(2, concatObjv); Tcl_DecrRefCount(listPtr); /* We're done with the list object. */ } TclNRAddCallback(interp, NsEval_Callback, namespacePtr, "inscope", NULL, NULL); return TclNREvalObjEx(interp, cmdObjPtr, 0, NULL, 0); } /* *---------------------------------------------------------------------- * * NamespaceOriginCmd -- * * Invoked to implement the "namespace origin" command to return the * fully-qualified name of the "real" command to which the specified * "imported command" refers. Handles the following syntax: * * namespace origin name * * Results: * An imported command is created in an namespace when that namespace * imports a command from another namespace. If a command is imported * into a sequence of namespaces a, b,...,n where each successive * namespace just imports the command from the previous namespace, this * command returns the fully-qualified name of the original command in * the first namespace, a. If "name" does not refer to an alias, its * fully-qualified name is returned. The returned name is stored in the * interpreter's result object. This function returns TCL_OK if * successful, and TCL_ERROR if anything goes wrong. * * Side effects: * If anything goes wrong, this function returns an error message in the * interpreter's result object. * *---------------------------------------------------------------------- */ static int NamespaceOriginCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Command command, origCommand; Tcl_Obj *resultPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } command = Tcl_GetCommandFromObj(interp, objv[1]); if (command == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid command name \"%s\"", TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", TclGetString(objv[1]), NULL); return TCL_ERROR; } origCommand = TclGetOriginalCommand(command); TclNewObj(resultPtr); if (origCommand == NULL) { /* * The specified command isn't an imported command. Return the * command's name qualified by the full name of the namespace it was * defined in. */ Tcl_GetCommandFullName(interp, command, resultPtr); } else { Tcl_GetCommandFullName(interp, origCommand, resultPtr); } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceParentCmd -- * * Invoked to implement the "namespace parent" command that returns the * fully-qualified name of the parent namespace for a specified * namespace. Handles the following syntax: * * namespace parent ?name? * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Returns a result in the interpreter's result object. If anything goes * wrong, the result is an error message. * *---------------------------------------------------------------------- */ static int NamespaceParentCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *nsPtr; if (objc == 1) { nsPtr = TclGetCurrentNamespace(interp); } else if (objc == 2) { if (TclGetNamespaceFromObj(interp, objv[1], &nsPtr) != TCL_OK) { return TCL_ERROR; } } else { Tcl_WrongNumArgs(interp, 1, objv, "?name?"); return TCL_ERROR; } /* * Report the parent of the specified namespace. */ if (nsPtr->parentPtr != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( nsPtr->parentPtr->fullName, -1)); } return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespacePathCmd -- * * Invoked to implement the "namespace path" command that reads and * writes the current namespace's command resolution path. Has one * optional argument: if present, it is a list of named namespaces to set * the path to, and if absent, the current path should be returned. * Handles the following syntax: * * namespace path ?nsList? * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong * (most notably if the namespace list contains the name of something * other than a namespace). In the successful-exit case, may set the * interpreter result to the list of names of the namespaces on the * current namespace's path. * * Side effects: * May update the namespace path (triggering a recomputing of all command * names that depend on the namespace for resolution). * *---------------------------------------------------------------------- */ static int NamespacePathCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp); int i, nsObjc, result = TCL_ERROR; Tcl_Obj **nsObjv; Tcl_Namespace **namespaceList = NULL; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?pathList?"); return TCL_ERROR; } /* * If no path is given, return the current path. */ if (objc == 1) { Tcl_Obj *resultObj = Tcl_NewObj(); for (i=0 ; icommandPathLength ; i++) { if (nsPtr->commandPathArray[i].nsPtr != NULL) { Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj( nsPtr->commandPathArray[i].nsPtr->fullName, -1)); } } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * There is a path given, so parse it into an array of namespace pointers. */ if (TclListObjGetElements(interp, objv[1], &nsObjc, &nsObjv) != TCL_OK) { goto badNamespace; } if (nsObjc != 0) { namespaceList = TclStackAlloc(interp, sizeof(Tcl_Namespace *) * nsObjc); for (i=0 ; icommandPathSourceList; if (tmpPathArray[i].nextPtr != NULL) { tmpPathArray[i].nextPtr->prevPtr = &tmpPathArray[i]; } tmpPathArray[i].nsPtr->commandPathSourceList = &tmpPathArray[i]; } if (nsPtr->commandPathLength != 0) { UnlinkNsPath(nsPtr); } nsPtr->commandPathArray = tmpPathArray; } else { if (nsPtr->commandPathLength != 0) { UnlinkNsPath(nsPtr); } } nsPtr->commandPathLength = pathLength; nsPtr->cmdRefEpoch++; nsPtr->resolverEpoch++; } /* *---------------------------------------------------------------------- * * UnlinkNsPath -- * * Delete the given namespace's command name resolution path. Only call * if the path is non-empty. Caller must reset the counter containing the * path size. * * Results: * nothing * * Side effects: * Deletes the array of path entries and unlinks those path entries from * the target namespace's list of interested namespaces. * *---------------------------------------------------------------------- */ static void UnlinkNsPath( Namespace *nsPtr) { int i; for (i=0 ; icommandPathLength ; i++) { NamespacePathEntry *nsPathPtr = &nsPtr->commandPathArray[i]; if (nsPathPtr->prevPtr != NULL) { nsPathPtr->prevPtr->nextPtr = nsPathPtr->nextPtr; } if (nsPathPtr->nextPtr != NULL) { nsPathPtr->nextPtr->prevPtr = nsPathPtr->prevPtr; } if (nsPathPtr->nsPtr != NULL) { if (nsPathPtr->nsPtr->commandPathSourceList == nsPathPtr) { nsPathPtr->nsPtr->commandPathSourceList = nsPathPtr->nextPtr; } } } ckfree(nsPtr->commandPathArray); } /* *---------------------------------------------------------------------- * * TclInvalidateNsPath -- * * Invalidate the name resolution caches for all names looked up in * namespaces whose name path includes the given namespace. * * Results: * nothing * * Side effects: * Increments the command reference epoch in each namespace whose path * includes the given namespace. This causes any cached resolved names * whose root cacheing context starts at that namespace to be recomputed * the next time they are used. * *---------------------------------------------------------------------- */ void TclInvalidateNsPath( Namespace *nsPtr) { NamespacePathEntry *nsPathPtr = nsPtr->commandPathSourceList; while (nsPathPtr != NULL) { if (nsPathPtr->nsPtr != NULL) { nsPathPtr->creatorNsPtr->cmdRefEpoch++; } nsPathPtr = nsPathPtr->nextPtr; } } /* *---------------------------------------------------------------------- * * NamespaceQualifiersCmd -- * * Invoked to implement the "namespace qualifiers" command that returns * any leading namespace qualifiers in a string. These qualifiers are * namespace names separated by "::"s. For example, for "::foo::p" this * command returns "::foo", and for "::" it returns "". This command is * the complement of the "namespace tail" command. Note that this command * does not check whether the "namespace" names are, in fact, the names * of currently defined namespaces. Handles the following syntax: * * namespace qualifiers string * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Returns a result in the interpreter's result object. If anything goes * wrong, the result is an error message. * *---------------------------------------------------------------------- */ static int NamespaceQualifiersCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register const char *name, *p; int length; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "string"); return TCL_ERROR; } /* * Find the end of the string, then work backward and find the start of * the last "::" qualifier. */ name = TclGetString(objv[1]); for (p = name; *p != '\0'; p++) { /* empty body */ } while (--p >= name) { if ((*p == ':') && (p > name) && (*(p-1) == ':')) { p -= 2; /* Back up over the :: */ while ((p >= name) && (*p == ':')) { p--; /* Back up over the preceeding : */ } break; } } if (p >= name) { length = p-name+1; Tcl_SetObjResult(interp, Tcl_NewStringObj(name, length)); } return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceUnknownCmd -- * * Invoked to implement the "namespace unknown" command (TIP 181) that * sets or queries a per-namespace unknown command handler. This handler * is called when command lookup fails (current and global ns). The * default handler for the global namespace is ::unknown. The default * handler for other namespaces is to call the global namespace unknown * handler. Passing an empty list results in resetting the handler to its * default. * * namespace unknown ?handler? * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * If no handler is specified, returns a result in the interpreter's * result object, otherwise it sets the unknown handler pointer in the * current namespace to the script fragment provided. If anything goes * wrong, the result is an error message. * *---------------------------------------------------------------------- */ static int NamespaceUnknownCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Namespace *currNsPtr; Tcl_Obj *resultPtr; int rc; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?script?"); return TCL_ERROR; } currNsPtr = TclGetCurrentNamespace(interp); if (objc == 1) { /* * Introspection - return the current namespace handler. */ resultPtr = Tcl_GetNamespaceUnknownHandler(interp, currNsPtr); if (resultPtr == NULL) { TclNewObj(resultPtr); } Tcl_SetObjResult(interp, resultPtr); } else { rc = Tcl_SetNamespaceUnknownHandler(interp, currNsPtr, objv[1]); if (rc == TCL_OK) { Tcl_SetObjResult(interp, objv[1]); } return rc; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetNamespaceUnknownHandler -- * * Returns the unknown command handler registered for the given * namespace. * * Results: * Returns the current unknown command handler, or NULL if none exists * for the namespace. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_GetNamespaceUnknownHandler( Tcl_Interp *interp, /* The interpreter in which the namespace * exists. */ Tcl_Namespace *nsPtr) /* The namespace. */ { Namespace *currNsPtr = (Namespace *) nsPtr; if (currNsPtr->unknownHandlerPtr == NULL && currNsPtr == ((Interp *) interp)->globalNsPtr) { /* * Default handler for global namespace is "::unknown". For all other * namespaces, it is NULL (which falls back on the global unknown * handler). */ TclNewLiteralStringObj(currNsPtr->unknownHandlerPtr, "::unknown"); Tcl_IncrRefCount(currNsPtr->unknownHandlerPtr); } return currNsPtr->unknownHandlerPtr; } /* *---------------------------------------------------------------------- * * Tcl_SetNamespaceUnknownHandler -- * * Sets the unknown command handler for the given namespace to the * command prefix passed. * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Sets the namespace unknown command handler. If the passed in handler * is NULL or an empty list, then the handler is reset to its default. If * an error occurs, then an error message is left in the interpreter * result. * *---------------------------------------------------------------------- */ int Tcl_SetNamespaceUnknownHandler( Tcl_Interp *interp, /* Interpreter in which the namespace * exists. */ Tcl_Namespace *nsPtr, /* Namespace which is being updated. */ Tcl_Obj *handlerPtr) /* The new handler, or NULL to reset. */ { int lstlen = 0; Namespace *currNsPtr = (Namespace *) nsPtr; /* * Ensure that we check for errors *first* before we change anything. */ if (handlerPtr != NULL) { if (TclListObjLength(interp, handlerPtr, &lstlen) != TCL_OK) { /* * Not a list. */ return TCL_ERROR; } if (lstlen > 0) { /* * We are going to be saving this handler. Increment the reference * count before decrementing the refcount on the previous handler, * so that nothing strange can happen if we are told to set the * handler to the previous value. */ Tcl_IncrRefCount(handlerPtr); } } /* * Remove old handler next. */ if (currNsPtr->unknownHandlerPtr != NULL) { Tcl_DecrRefCount(currNsPtr->unknownHandlerPtr); } /* * Install the new handler. */ if (lstlen > 0) { /* * Just store the handler. It already has the correct reference count. */ currNsPtr->unknownHandlerPtr = handlerPtr; } else { /* * If NULL or an empty list is passed, this resets to the default * handler. */ currNsPtr->unknownHandlerPtr = NULL; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceTailCmd -- * * Invoked to implement the "namespace tail" command that returns the * trailing name at the end of a string with "::" namespace qualifiers. * These qualifiers are namespace names separated by "::"s. For example, * for "::foo::p" this command returns "p", and for "::" it returns "". * This command is the complement of the "namespace qualifiers" command. * Note that this command does not check whether the "namespace" names * are, in fact, the names of currently defined namespaces. Handles the * following syntax: * * namespace tail string * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Returns a result in the interpreter's result object. If anything goes * wrong, the result is an error message. * *---------------------------------------------------------------------- */ static int NamespaceTailCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register const char *name, *p; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "string"); return TCL_ERROR; } /* * Find the end of the string, then work backward and find the last "::" * qualifier. */ name = TclGetString(objv[1]); for (p = name; *p != '\0'; p++) { /* empty body */ } while (--p > name) { if ((*p == ':') && (*(p-1) == ':')) { p++; /* Just after the last "::" */ break; } } if (p >= name) { Tcl_SetObjResult(interp, Tcl_NewStringObj(p, -1)); } return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceUpvarCmd -- * * Invoked to implement the "namespace upvar" command, that creates * variables in the current scope linked to variables in another * namespace. Handles the following syntax: * * namespace upvar ns otherVar myVar ?otherVar myVar ...? * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Creates new variables in the current scope, linked to the * corresponding variables in the stipulated nmamespace. If anything goes * wrong, the result is an error message. * *---------------------------------------------------------------------- */ static int NamespaceUpvarCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; Tcl_Namespace *nsPtr, *savedNsPtr; Var *otherPtr, *arrayPtr; const char *myName; if (objc < 2 || (objc & 1)) { Tcl_WrongNumArgs(interp, 1, objv, "ns ?otherVar myVar ...?"); return TCL_ERROR; } if (TclGetNamespaceFromObj(interp, objv[1], &nsPtr) != TCL_OK) { return TCL_ERROR; } objc -= 2; objv += 2; for (; objc>0 ; objc-=2, objv+=2) { /* * Locate the other variable. */ savedNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr; iPtr->varFramePtr->nsPtr = (Namespace *) nsPtr; otherPtr = TclObjLookupVarEx(interp, objv[0], NULL, (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); iPtr->varFramePtr->nsPtr = (Namespace *) savedNsPtr; if (otherPtr == NULL) { return TCL_ERROR; } /* * Create the new variable and link it to otherPtr. */ myName = TclGetString(objv[1]); if (TclPtrMakeUpvar(interp, otherPtr, myName, 0, -1) != TCL_OK) { return TCL_ERROR; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceWhichCmd -- * * Invoked to implement the "namespace which" command that returns the * fully-qualified name of a command or variable. If the specified * command or variable does not exist, it returns "". Handles the * following syntax: * * namespace which ?-command? ?-variable? name * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Returns a result in the interpreter's result object. If anything goes * wrong, the result is an error message. * *---------------------------------------------------------------------- */ static int NamespaceWhichCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const opts[] = { "-command", "-variable", NULL }; int lookupType = 0; Tcl_Obj *resultPtr; if (objc < 2 || objc > 3) { badArgs: Tcl_WrongNumArgs(interp, 1, objv, "?-command? ?-variable? name"); return TCL_ERROR; } else if (objc == 3) { /* * Look for a flag controlling the lookup. */ if (Tcl_GetIndexFromObj(interp, objv[1], opts, "option", 0, &lookupType) != TCL_OK) { /* * Preserve old style of error message! */ Tcl_ResetResult(interp); goto badArgs; } } TclNewObj(resultPtr); switch (lookupType) { case 0: { /* -command */ Tcl_Command cmd = Tcl_GetCommandFromObj(interp, objv[objc-1]); if (cmd != NULL) { Tcl_GetCommandFullName(interp, cmd, resultPtr); } break; } case 1: { /* -variable */ Tcl_Var var = Tcl_FindNamespaceVar(interp, TclGetString(objv[objc-1]), NULL, /*flags*/ 0); if (var != NULL) { Tcl_GetVariableFullName(interp, var, resultPtr); } break; } } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * FreeNsNameInternalRep -- * * Frees the resources associated with a nsName object's internal * representation. * * Results: * None. * * Side effects: * Decrements the ref count of any Namespace structure pointed to by the * nsName's internal representation. If there are no more references to * the namespace, it's structure will be freed. * *---------------------------------------------------------------------- */ static void FreeNsNameInternalRep( register Tcl_Obj *objPtr) /* nsName object with internal representation * to free. */ { ResolvedNsName *resNamePtr = objPtr->internalRep.twoPtrValue.ptr1; /* * Decrement the reference count of the namespace. If there are no more * references, free it up. */ resNamePtr->refCount--; if (resNamePtr->refCount == 0) { /* * Decrement the reference count for the cached namespace. If the * namespace is dead, and there are no more references to it, free * it. */ TclNsDecrRefCount(resNamePtr->nsPtr); ckfree(resNamePtr); } objPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * DupNsNameInternalRep -- * * Initializes the internal representation of a nsName object to a copy * of the internal representation of another nsName object. * * Results: * None. * * Side effects: * copyPtr's internal rep is set to refer to the same namespace * referenced by srcPtr's internal rep. Increments the ref count of the * ResolvedNsName structure used to hold the namespace reference. * *---------------------------------------------------------------------- */ static void DupNsNameInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ register Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { ResolvedNsName *resNamePtr = srcPtr->internalRep.twoPtrValue.ptr1; copyPtr->internalRep.twoPtrValue.ptr1 = resNamePtr; resNamePtr->refCount++; copyPtr->typePtr = &nsNameType; } /* *---------------------------------------------------------------------- * * SetNsNameFromAny -- * * Attempt to generate a nsName internal representation for a Tcl object. * * Results: * Returns TCL_OK if the value could be converted to a proper namespace * reference. Otherwise, it returns TCL_ERROR, along with an error * message in the interpreter's result object. * * Side effects: * If successful, the object is made a nsName object. Its internal rep is * set to point to a ResolvedNsName, which contains a cached pointer to * the Namespace. Reference counts are kept on both the ResolvedNsName * and the Namespace, so we can keep track of their usage and free them * when appropriate. * *---------------------------------------------------------------------- */ static int SetNsNameFromAny( Tcl_Interp *interp, /* Points to the namespace in which to resolve * name. Also used for error reporting if not * NULL. */ register Tcl_Obj *objPtr) /* The object to convert. */ { const char *dummy; Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr; register ResolvedNsName *resNamePtr; const char *name; if (interp == NULL) { return TCL_ERROR; } name = TclGetString(objPtr); TclGetNamespaceForQualName(interp, name, NULL, TCL_FIND_ONLY_NS, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy); /* * If we found a namespace, then create a new ResolvedNsName structure * that holds a reference to it. */ if ((nsPtr == NULL) || (nsPtr->flags & NS_DYING)) { /* * Our failed lookup proves any previously cached nsName intrep is no * longer valid. Get rid of it so we no longer waste memory storing * it, nor time determining its invalidity again and again. */ if (objPtr->typePtr == &nsNameType) { TclFreeIntRep(objPtr); } return TCL_ERROR; } nsPtr->refCount++; resNamePtr = ckalloc(sizeof(ResolvedNsName)); resNamePtr->nsPtr = nsPtr; if ((name[0] == ':') && (name[1] == ':')) { resNamePtr->refNsPtr = NULL; } else { resNamePtr->refNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); } resNamePtr->refCount = 1; TclFreeIntRep(objPtr); objPtr->internalRep.twoPtrValue.ptr1 = resNamePtr; objPtr->typePtr = &nsNameType; return TCL_OK; } /* *---------------------------------------------------------------------- * * TclGetNamespaceCommandTable -- * * Returns the hash table of commands. * * Results: * Pointer to the hash table. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_HashTable * TclGetNamespaceCommandTable( Tcl_Namespace *nsPtr) { return &((Namespace *) nsPtr)->cmdTable; } /* *---------------------------------------------------------------------- * * TclGetNamespaceChildTable -- * * Returns the hash table of child namespaces. * * Results: * Pointer to the hash table. * * Side effects: * Might allocate memory. * *---------------------------------------------------------------------- */ Tcl_HashTable * TclGetNamespaceChildTable( Tcl_Namespace *nsPtr) { Namespace *nPtr = (Namespace *) nsPtr; #ifndef BREAK_NAMESPACE_COMPAT return &nPtr->childTable; #else if (nPtr->childTablePtr == NULL) { nPtr->childTablePtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(nPtr->childTablePtr, TCL_STRING_KEYS); } return nPtr->childTablePtr; #endif } /* *---------------------------------------------------------------------- * * TclLogCommandInfo -- * * This function is invoked after an error occurs in an interpreter. It * adds information to iPtr->errorInfo/errorStack fields to describe the * command that was being executed when the error occurred. When pc and * tosPtr are non-NULL, conveying a bytecode execution "inner context", * and the offending instruction is suitable, that inner context is * recorded in errorStack. * * Results: * None. * * Side effects: * Information about the command is added to errorInfo/errorStack and the * line number stored internally in the interpreter is set. * *---------------------------------------------------------------------- */ void TclLogCommandInfo( Tcl_Interp *interp, /* Interpreter in which to log information. */ const char *script, /* First character in script containing * command (must be <= command). */ const char *command, /* First character in command that generated * the error. */ int length, /* Number of bytes in command (-1 means use * all bytes up to first null byte). */ const unsigned char *pc, /* Current pc of bytecode execution context */ Tcl_Obj **tosPtr) /* Current stack of bytecode execution * context */ { register const char *p; Interp *iPtr = (Interp *) interp; int overflow, limit = 150; Var *varPtr, *arrayPtr; if (iPtr->flags & ERR_ALREADY_LOGGED) { /* * Someone else has already logged error information for this command; * we shouldn't add anything more. */ return; } if (command != NULL) { /* * Compute the line number where the error occurred. */ iPtr->errorLine = 1; for (p = script; p != command; p++) { if (*p == '\n') { iPtr->errorLine++; } } if (length < 0) { length = strlen(command); } overflow = (length > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n %s\n\"%.*s%s\"", ((iPtr->errorInfo == NULL) ? "while executing" : "invoked from within"), (overflow ? limit : length), command, (overflow ? "..." : ""))); varPtr = TclObjLookupVarEx(interp, iPtr->eiVar, NULL, TCL_GLOBAL_ONLY, NULL, 0, 0, &arrayPtr); if ((varPtr == NULL) || !TclIsVarTraced(varPtr)) { /* * Should not happen. */ return; } else { Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr); VarTrace *tracePtr = Tcl_GetHashValue(hPtr); if (tracePtr->traceProc != EstablishErrorInfoTraces) { /* * The most recent trace set on ::errorInfo is not the one the * core itself puts on last. This means some other code is * tracing the variable, and the additional trace(s) might be * write traces that expect the timing of writes to * ::errorInfo that existed Tcl releases before 8.5. To * satisfy that compatibility need, we write the current * -errorinfo value to the ::errorInfo variable. */ Tcl_ObjSetVar2(interp, iPtr->eiVar, NULL, iPtr->errorInfo, TCL_GLOBAL_ONLY); } } } /* * TIP #348 */ if (Tcl_IsShared(iPtr->errorStack)) { Tcl_Obj *newObj; newObj = Tcl_DuplicateObj(iPtr->errorStack); Tcl_DecrRefCount(iPtr->errorStack); Tcl_IncrRefCount(newObj); iPtr->errorStack = newObj; } if (iPtr->resetErrorStack) { int len; iPtr->resetErrorStack = 0; Tcl_ListObjLength(interp, iPtr->errorStack, &len); /* * Reset while keeping the list intrep as much as possible. */ Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, 0, NULL); if (pc != NULL) { Tcl_Obj *innerContext; innerContext = TclGetInnerContext(interp, pc, tosPtr); if (innerContext != NULL) { Tcl_ListObjAppendElement(NULL, iPtr->errorStack, iPtr->innerLiteral); Tcl_ListObjAppendElement(NULL, iPtr->errorStack, innerContext); } } else if (command != NULL) { Tcl_ListObjAppendElement(NULL, iPtr->errorStack, iPtr->innerLiteral); Tcl_ListObjAppendElement(NULL, iPtr->errorStack, Tcl_NewStringObj(command, length)); } } if (!iPtr->framePtr->objc) { /* * Special frame, nothing to report. */ } else if (iPtr->varFramePtr != iPtr->framePtr) { /* * uplevel case, [lappend errorstack UP $relativelevel] */ Tcl_ListObjAppendElement(NULL, iPtr->errorStack, iPtr->upLiteral); Tcl_ListObjAppendElement(NULL, iPtr->errorStack, Tcl_NewIntObj( iPtr->framePtr->level - iPtr->varFramePtr->level)); } else if (iPtr->framePtr != iPtr->rootFramePtr) { /* * normal case, [lappend errorstack CALL [info level 0]] */ Tcl_ListObjAppendElement(NULL, iPtr->errorStack, iPtr->callLiteral); Tcl_ListObjAppendElement(NULL, iPtr->errorStack, Tcl_NewListObj( iPtr->framePtr->objc, iPtr->framePtr->objv)); } } /* *---------------------------------------------------------------------- * * TclErrorStackResetIf -- * * The TIP 348 reset/no-bc part of TLCI, for specific use by * TclCompileSyntaxError. * * Results: * None. * * Side effects: * Reset errorstack if it needs be, and in that case remember the * passed-in error message as inner context. * *---------------------------------------------------------------------- */ void TclErrorStackResetIf( Tcl_Interp *interp, const char *msg, int length) { Interp *iPtr = (Interp *) interp; if (Tcl_IsShared(iPtr->errorStack)) { Tcl_Obj *newObj; newObj = Tcl_DuplicateObj(iPtr->errorStack); Tcl_DecrRefCount(iPtr->errorStack); Tcl_IncrRefCount(newObj); iPtr->errorStack = newObj; } if (iPtr->resetErrorStack) { int len; iPtr->resetErrorStack = 0; Tcl_ListObjLength(interp, iPtr->errorStack, &len); /* * Reset while keeping the list intrep as much as possible. */ Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, 0, NULL); Tcl_ListObjAppendElement(NULL, iPtr->errorStack, iPtr->innerLiteral); Tcl_ListObjAppendElement(NULL, iPtr->errorStack, Tcl_NewStringObj(msg, length)); } } /* *---------------------------------------------------------------------- * * Tcl_LogCommandInfo -- * * This function is invoked after an error occurs in an interpreter. It * adds information to iPtr->errorInfo/errorStack fields to describe the * command that was being executed when the error occurred. * * Results: * None. * * Side effects: * Information about the command is added to errorInfo/errorStack and the * line number stored internally in the interpreter is set. * *---------------------------------------------------------------------- */ void Tcl_LogCommandInfo( Tcl_Interp *interp, /* Interpreter in which to log information. */ const char *script, /* First character in script containing * command (must be <= command). */ const char *command, /* First character in command that generated * the error. */ int length) /* Number of bytes in command (-1 means use * all bytes up to first null byte). */ { TclLogCommandInfo(interp, script, command, length, NULL, NULL); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * End: */ tcl8.6.5/generic/tclOOInfo.c0000644000175000017500000011235712663660065015214 0ustar sergeisergei/* * tclOODefineCmds.c -- * * This file contains the implementation of the ::oo-related [info] * subcommands. * * Copyright (c) 2006-2011 by Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tclInt.h" #include "tclOOInt.h" static inline Class * GetClassFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr); static Tcl_ObjCmdProc InfoObjectCallCmd; static Tcl_ObjCmdProc InfoObjectClassCmd; static Tcl_ObjCmdProc InfoObjectDefnCmd; static Tcl_ObjCmdProc InfoObjectFiltersCmd; static Tcl_ObjCmdProc InfoObjectForwardCmd; static Tcl_ObjCmdProc InfoObjectIsACmd; static Tcl_ObjCmdProc InfoObjectMethodsCmd; static Tcl_ObjCmdProc InfoObjectMethodTypeCmd; static Tcl_ObjCmdProc InfoObjectMixinsCmd; static Tcl_ObjCmdProc InfoObjectNsCmd; static Tcl_ObjCmdProc InfoObjectVarsCmd; static Tcl_ObjCmdProc InfoObjectVariablesCmd; static Tcl_ObjCmdProc InfoClassCallCmd; static Tcl_ObjCmdProc InfoClassConstrCmd; static Tcl_ObjCmdProc InfoClassDefnCmd; static Tcl_ObjCmdProc InfoClassDestrCmd; static Tcl_ObjCmdProc InfoClassFiltersCmd; static Tcl_ObjCmdProc InfoClassForwardCmd; static Tcl_ObjCmdProc InfoClassInstancesCmd; static Tcl_ObjCmdProc InfoClassMethodsCmd; static Tcl_ObjCmdProc InfoClassMethodTypeCmd; static Tcl_ObjCmdProc InfoClassMixinsCmd; static Tcl_ObjCmdProc InfoClassSubsCmd; static Tcl_ObjCmdProc InfoClassSupersCmd; static Tcl_ObjCmdProc InfoClassVariablesCmd; /* * List of commands that are used to implement the [info object] subcommands. */ static const EnsembleImplMap infoObjectCmds[] = { {"call", InfoObjectCallCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"class", InfoObjectClassCmd, TclCompileInfoObjectClassCmd, NULL, NULL, 0}, {"definition", InfoObjectDefnCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"filters", InfoObjectFiltersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"forward", InfoObjectForwardCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"isa", InfoObjectIsACmd, TclCompileInfoObjectIsACmd, NULL, NULL, 0}, {"methods", InfoObjectMethodsCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0}, {"methodtype", InfoObjectMethodTypeCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"mixins", InfoObjectMixinsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"namespace", InfoObjectNsCmd, TclCompileInfoObjectNamespaceCmd, NULL, NULL, 0}, {"variables", InfoObjectVariablesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"vars", InfoObjectVarsCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* * List of commands that are used to implement the [info class] subcommands. */ static const EnsembleImplMap infoClassCmds[] = { {"call", InfoClassCallCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"constructor", InfoClassConstrCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"definition", InfoClassDefnCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"destructor", InfoClassDestrCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"filters", InfoClassFiltersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"forward", InfoClassForwardCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"instances", InfoClassInstancesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"methods", InfoClassMethodsCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0}, {"methodtype", InfoClassMethodTypeCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"mixins", InfoClassMixinsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"subclasses", InfoClassSubsCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"superclasses", InfoClassSupersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"variables", InfoClassVariablesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* * ---------------------------------------------------------------------- * * TclOOInitInfo -- * * Adjusts the Tcl core [info] command to contain subcommands ("object" * and "class") for introspection of objects and classes. * * ---------------------------------------------------------------------- */ void TclOOInitInfo( Tcl_Interp *interp) { Tcl_Command infoCmd; Tcl_Obj *mapDict; /* * Build the ensembles used to implement [info object] and [info class]. */ TclMakeEnsemble(interp, "::oo::InfoObject", infoObjectCmds); TclMakeEnsemble(interp, "::oo::InfoClass", infoClassCmds); /* * Install into the master [info] ensemble. */ infoCmd = Tcl_FindCommand(interp, "info", NULL, TCL_GLOBAL_ONLY); Tcl_GetEnsembleMappingDict(NULL, infoCmd, &mapDict); Tcl_DictObjPut(NULL, mapDict, Tcl_NewStringObj("object", -1), Tcl_NewStringObj("::oo::InfoObject", -1)); Tcl_DictObjPut(NULL, mapDict, Tcl_NewStringObj("class", -1), Tcl_NewStringObj("::oo::InfoClass", -1)); Tcl_SetEnsembleMappingDict(interp, infoCmd, mapDict); } /* * ---------------------------------------------------------------------- * * GetClassFromObj -- * * How to correctly get a class from a Tcl_Obj. Just a wrapper round * Tcl_GetObjectFromObj, but this is an idiom that was used heavily. * * ---------------------------------------------------------------------- */ static inline Class * GetClassFromObj( Tcl_Interp *interp, Tcl_Obj *objPtr) { Object *oPtr = (Object *) Tcl_GetObjectFromObj(interp, objPtr); if (oPtr == NULL) { return NULL; } if (oPtr->classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not a class", TclGetString(objPtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS", TclGetString(objPtr), NULL); return NULL; } return oPtr->classPtr; } /* * ---------------------------------------------------------------------- * * InfoObjectClassCmd -- * * Implements [info object class $objName ?$className?] * * ---------------------------------------------------------------------- */ static int InfoObjectClassCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Object *oPtr; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "objName ?className?"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } if (objc == 2) { Tcl_SetObjResult(interp, TclOOObjectName(interp, oPtr->selfCls->thisPtr)); return TCL_OK; } else { Class *mixinPtr, *o2clsPtr; int i; o2clsPtr = GetClassFromObj(interp, objv[2]); if (o2clsPtr == NULL) { return TCL_ERROR; } FOREACH(mixinPtr, oPtr->mixins) { if (!mixinPtr) { continue; } if (TclOOIsReachable(o2clsPtr, mixinPtr)) { Tcl_SetObjResult(interp, Tcl_NewIntObj(1)); return TCL_OK; } } Tcl_SetObjResult(interp, Tcl_NewIntObj( TclOOIsReachable(o2clsPtr, oPtr->selfCls))); return TCL_OK; } } /* * ---------------------------------------------------------------------- * * InfoObjectDefnCmd -- * * Implements [info object definition $objName $methodName] * * ---------------------------------------------------------------------- */ static int InfoObjectDefnCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Object *oPtr; Tcl_HashEntry *hPtr; Proc *procPtr; CompiledLocal *localPtr; Tcl_Obj *resultObjs[2]; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "objName methodName"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } if (!oPtr->methodsPtr) { goto unknownMethod; } hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]); if (hPtr == NULL) { unknownMethod: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown method \"%s\"", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[2]), NULL); return TCL_ERROR; } procPtr = TclOOGetProcFromMethod(Tcl_GetHashValue(hPtr)); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "definition not available for this kind of method", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[2]), NULL); return TCL_ERROR; } resultObjs[0] = Tcl_NewObj(); for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL; localPtr=localPtr->nextPtr) { if (TclIsVarArgument(localPtr)) { Tcl_Obj *argObj; argObj = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, argObj, Tcl_NewStringObj(localPtr->name, -1)); if (localPtr->defValuePtr != NULL) { Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr); } Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj); } } resultObjs[1] = TclOOGetMethodBody(Tcl_GetHashValue(hPtr)); Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObjs)); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoObjectFiltersCmd -- * * Implements [info object filters $objName] * * ---------------------------------------------------------------------- */ static int InfoObjectFiltersCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int i; Tcl_Obj *filterObj, *resultObj; Object *oPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "objName"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(filterObj, oPtr->filters) { Tcl_ListObjAppendElement(NULL, resultObj, filterObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoObjectForwardCmd -- * * Implements [info object forward $objName $methodName] * * ---------------------------------------------------------------------- */ static int InfoObjectForwardCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Object *oPtr; Tcl_HashEntry *hPtr; Tcl_Obj *prefixObj; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "objName methodName"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } if (!oPtr->methodsPtr) { goto unknownMethod; } hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]); if (hPtr == NULL) { unknownMethod: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown method \"%s\"", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[2]), NULL); return TCL_ERROR; } prefixObj = TclOOGetFwdFromMethod(Tcl_GetHashValue(hPtr)); if (prefixObj == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "prefix argument list not available for this kind of method", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[2]), NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, prefixObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoObjectIsACmd -- * * Implements [info object isa $category $objName ...] * * ---------------------------------------------------------------------- */ static int InfoObjectIsACmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { static const char *const categories[] = { "class", "metaclass", "mixin", "object", "typeof", NULL }; enum IsACats { IsClass, IsMetaclass, IsMixin, IsObject, IsType }; Object *oPtr, *o2Ptr; int idx, i, result = 0; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "category objName ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], categories, "category", 0, &idx) != TCL_OK) { return TCL_ERROR; } /* * Now we know what test we are doing, we can check we've got the right * number of arguments. */ switch ((enum IsACats) idx) { case IsObject: case IsClass: case IsMetaclass: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "objName"); return TCL_ERROR; } break; case IsMixin: case IsType: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "objName className"); return TCL_ERROR; } break; } /* * Perform the check. Note that we can guarantee that we will not fail * from here on; "failures" result in a false-TCL_OK result. */ oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]); if (oPtr == NULL) { goto failPrecondition; } switch ((enum IsACats) idx) { case IsObject: result = 1; break; case IsClass: result = (oPtr->classPtr != NULL); break; case IsMetaclass: if (oPtr->classPtr != NULL) { result = TclOOIsReachable(TclOOGetFoundation(interp)->classCls, oPtr->classPtr); } break; case IsMixin: o2Ptr = (Object *) Tcl_GetObjectFromObj(interp, objv[3]); if (o2Ptr == NULL) { goto failPrecondition; } if (o2Ptr->classPtr != NULL) { Class *mixinPtr; FOREACH(mixinPtr, oPtr->mixins) { if (!mixinPtr) { continue; } if (TclOOIsReachable(o2Ptr->classPtr, mixinPtr)) { result = 1; break; } } } break; case IsType: o2Ptr = (Object *) Tcl_GetObjectFromObj(interp, objv[3]); if (o2Ptr == NULL) { goto failPrecondition; } if (o2Ptr->classPtr != NULL) { result = TclOOIsReachable(o2Ptr->classPtr, oPtr->selfCls); } break; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; failPrecondition: Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoObjectMethodsCmd -- * * Implements [info object methods $objName ?$option ...?] * * ---------------------------------------------------------------------- */ static int InfoObjectMethodsCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Object *oPtr; int flag = PUBLIC_METHOD, recurse = 0; FOREACH_HASH_DECLS; Tcl_Obj *namePtr, *resultObj; Method *mPtr; static const char *const options[] = { "-all", "-localprivate", "-private", NULL }; enum Options { OPT_ALL, OPT_LOCALPRIVATE, OPT_PRIVATE }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "objName ?-option value ...?"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } if (objc != 2) { int i, idx; for (i=2 ; i 0) { ckfree(names); } } else if (oPtr->methodsPtr) { FOREACH_HASH(namePtr, mPtr, oPtr->methodsPtr) { if (mPtr->typePtr != NULL && (mPtr->flags & flag) == flag) { Tcl_ListObjAppendElement(NULL, resultObj, namePtr); } } } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoObjectMethodTypeCmd -- * * Implements [info object methodtype $objName $methodName] * * ---------------------------------------------------------------------- */ static int InfoObjectMethodTypeCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Object *oPtr; Tcl_HashEntry *hPtr; Method *mPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "objName methodName"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } if (!oPtr->methodsPtr) { goto unknownMethod; } hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]); if (hPtr == NULL) { unknownMethod: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown method \"%s\"", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[2]), NULL); return TCL_ERROR; } mPtr = Tcl_GetHashValue(hPtr); if (mPtr->typePtr == NULL) { /* * Special entry for visibility control: pretend the method doesnt * exist. */ goto unknownMethod; } Tcl_SetObjResult(interp, Tcl_NewStringObj(mPtr->typePtr->name, -1)); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoObjectMixinsCmd -- * * Implements [info object mixins $objName] * * ---------------------------------------------------------------------- */ static int InfoObjectMixinsCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Class *mixinPtr; Object *oPtr; Tcl_Obj *resultObj; int i; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "objName"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(mixinPtr, oPtr->mixins) { if (!mixinPtr) { continue; } Tcl_ListObjAppendElement(NULL, resultObj, TclOOObjectName(interp, mixinPtr->thisPtr)); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoObjectNsCmd -- * * Implements [info object namespace $objName] * * ---------------------------------------------------------------------- */ static int InfoObjectNsCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Object *oPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "objName"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewStringObj(oPtr->namespacePtr->fullName, -1)); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoObjectVariablesCmd -- * * Implements [info object variables $objName] * * ---------------------------------------------------------------------- */ static int InfoObjectVariablesCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Object *oPtr; Tcl_Obj *variableObj, *resultObj; int i; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "objName"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(variableObj, oPtr->variables) { Tcl_ListObjAppendElement(NULL, resultObj, variableObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoObjectVarsCmd -- * * Implements [info object vars $objName ?$pattern?] * * ---------------------------------------------------------------------- */ static int InfoObjectVarsCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Object *oPtr; const char *pattern = NULL; FOREACH_HASH_DECLS; VarInHash *vihPtr; Tcl_Obj *nameObj, *resultObj; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "objName ?pattern?"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } if (objc == 3) { pattern = TclGetString(objv[2]); } resultObj = Tcl_NewObj(); /* * Extract the information we need from the object's namespace's table of * variables. Note that this involves horrific knowledge of the guts of * tclVar.c, so we can't leverage our hash-iteration macros properly. */ FOREACH_HASH_VALUE(vihPtr, &((Namespace *) oPtr->namespacePtr)->varTable.table) { nameObj = vihPtr->entry.key.objPtr; if (TclIsVarUndefined(&vihPtr->var) || !TclIsVarNamespaceVar(&vihPtr->var)) { continue; } if (pattern != NULL && !Tcl_StringMatch(TclGetString(nameObj), pattern)) { continue; } Tcl_ListObjAppendElement(NULL, resultObj, nameObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassConstrCmd -- * * Implements [info class constructor $clsName] * * ---------------------------------------------------------------------- */ static int InfoClassConstrCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Proc *procPtr; CompiledLocal *localPtr; Tcl_Obj *resultObjs[2]; Class *clsPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "className"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } if (clsPtr->constructorPtr == NULL) { return TCL_OK; } procPtr = TclOOGetProcFromMethod(clsPtr->constructorPtr); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "definition not available for this kind of method", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "METHOD_TYPE", NULL); return TCL_ERROR; } resultObjs[0] = Tcl_NewObj(); for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL; localPtr=localPtr->nextPtr) { if (TclIsVarArgument(localPtr)) { Tcl_Obj *argObj; argObj = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, argObj, Tcl_NewStringObj(localPtr->name, -1)); if (localPtr->defValuePtr != NULL) { Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr); } Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj); } } resultObjs[1] = TclOOGetMethodBody(clsPtr->constructorPtr); Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObjs)); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassDefnCmd -- * * Implements [info class definition $clsName $methodName] * * ---------------------------------------------------------------------- */ static int InfoClassDefnCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_HashEntry *hPtr; Proc *procPtr; CompiledLocal *localPtr; Tcl_Obj *resultObjs[2]; Class *clsPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "className methodName"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, (char *) objv[2]); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown method \"%s\"", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[2]), NULL); return TCL_ERROR; } procPtr = TclOOGetProcFromMethod(Tcl_GetHashValue(hPtr)); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "definition not available for this kind of method", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[2]), NULL); return TCL_ERROR; } resultObjs[0] = Tcl_NewObj(); for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL; localPtr=localPtr->nextPtr) { if (TclIsVarArgument(localPtr)) { Tcl_Obj *argObj; argObj = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, argObj, Tcl_NewStringObj(localPtr->name, -1)); if (localPtr->defValuePtr != NULL) { Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr); } Tcl_ListObjAppendElement(NULL, resultObjs[0], argObj); } } resultObjs[1] = TclOOGetMethodBody(Tcl_GetHashValue(hPtr)); Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObjs)); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassDestrCmd -- * * Implements [info class destructor $clsName] * * ---------------------------------------------------------------------- */ static int InfoClassDestrCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Proc *procPtr; Class *clsPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "className"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } if (clsPtr->destructorPtr == NULL) { return TCL_OK; } procPtr = TclOOGetProcFromMethod(clsPtr->destructorPtr); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "definition not available for this kind of method", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "METHOD_TYPE", NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, TclOOGetMethodBody(clsPtr->destructorPtr)); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassFiltersCmd -- * * Implements [info class filters $clsName] * * ---------------------------------------------------------------------- */ static int InfoClassFiltersCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int i; Tcl_Obj *filterObj, *resultObj; Class *clsPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "className"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(filterObj, clsPtr->filters) { Tcl_ListObjAppendElement(NULL, resultObj, filterObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassForwardCmd -- * * Implements [info class forward $clsName $methodName] * * ---------------------------------------------------------------------- */ static int InfoClassForwardCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_HashEntry *hPtr; Tcl_Obj *prefixObj; Class *clsPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "className methodName"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, (char *) objv[2]); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown method \"%s\"", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[2]), NULL); return TCL_ERROR; } prefixObj = TclOOGetFwdFromMethod(Tcl_GetHashValue(hPtr)); if (prefixObj == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "prefix argument list not available for this kind of method", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[2]), NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, prefixObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassInstancesCmd -- * * Implements [info class instances $clsName ?$pattern?] * * ---------------------------------------------------------------------- */ static int InfoClassInstancesCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Object *oPtr; Class *clsPtr; int i; const char *pattern = NULL; Tcl_Obj *resultObj; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "className ?pattern?"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } if (objc == 3) { pattern = TclGetString(objv[2]); } resultObj = Tcl_NewObj(); FOREACH(oPtr, clsPtr->instances) { Tcl_Obj *tmpObj = TclOOObjectName(interp, oPtr); if (pattern && !Tcl_StringMatch(TclGetString(tmpObj), pattern)) { continue; } Tcl_ListObjAppendElement(NULL, resultObj, tmpObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassMethodsCmd -- * * Implements [info class methods $clsName ?-private?] * * ---------------------------------------------------------------------- */ static int InfoClassMethodsCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int flag = PUBLIC_METHOD, recurse = 0; Tcl_Obj *namePtr, *resultObj; Method *mPtr; Class *clsPtr; static const char *const options[] = { "-all", "-localprivate", "-private", NULL }; enum Options { OPT_ALL, OPT_LOCALPRIVATE, OPT_PRIVATE }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "className ?-option value ...?"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } if (objc != 2) { int i, idx; for (i=2 ; i 0) { ckfree(names); } } else { FOREACH_HASH_DECLS; FOREACH_HASH(namePtr, mPtr, &clsPtr->classMethods) { if (mPtr->typePtr != NULL && (mPtr->flags & flag) == flag) { Tcl_ListObjAppendElement(NULL, resultObj, namePtr); } } } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassMethodTypeCmd -- * * Implements [info class methodtype $clsName $methodName] * * ---------------------------------------------------------------------- */ static int InfoClassMethodTypeCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_HashEntry *hPtr; Method *mPtr; Class *clsPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "className methodName"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, (char *) objv[2]); if (hPtr == NULL) { unknownMethod: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown method \"%s\"", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[2]), NULL); return TCL_ERROR; } mPtr = Tcl_GetHashValue(hPtr); if (mPtr->typePtr == NULL) { /* * Special entry for visibility control: pretend the method doesnt * exist. */ goto unknownMethod; } Tcl_SetObjResult(interp, Tcl_NewStringObj(mPtr->typePtr->name, -1)); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassMixinsCmd -- * * Implements [info class mixins $clsName] * * ---------------------------------------------------------------------- */ static int InfoClassMixinsCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Class *clsPtr, *mixinPtr; Tcl_Obj *resultObj; int i; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "className"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(mixinPtr, clsPtr->mixins) { if (!mixinPtr) { continue; } Tcl_ListObjAppendElement(NULL, resultObj, TclOOObjectName(interp, mixinPtr->thisPtr)); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassSubsCmd -- * * Implements [info class subclasses $clsName ?$pattern?] * * ---------------------------------------------------------------------- */ static int InfoClassSubsCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Class *clsPtr, *subclassPtr; Tcl_Obj *resultObj; int i; const char *pattern = NULL; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "className ?pattern?"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } if (objc == 3) { pattern = TclGetString(objv[2]); } resultObj = Tcl_NewObj(); FOREACH(subclassPtr, clsPtr->subclasses) { Tcl_Obj *tmpObj = TclOOObjectName(interp, subclassPtr->thisPtr); if (pattern && !Tcl_StringMatch(TclGetString(tmpObj), pattern)) { continue; } Tcl_ListObjAppendElement(NULL, resultObj, tmpObj); } FOREACH(subclassPtr, clsPtr->mixinSubs) { Tcl_Obj *tmpObj = TclOOObjectName(interp, subclassPtr->thisPtr); if (pattern && !Tcl_StringMatch(TclGetString(tmpObj), pattern)) { continue; } Tcl_ListObjAppendElement(NULL, resultObj, tmpObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassSupersCmd -- * * Implements [info class superclasses $clsName] * * ---------------------------------------------------------------------- */ static int InfoClassSupersCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Class *clsPtr, *superPtr; Tcl_Obj *resultObj; int i; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "className"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(superPtr, clsPtr->superclasses) { Tcl_ListObjAppendElement(NULL, resultObj, TclOOObjectName(interp, superPtr->thisPtr)); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassVariablesCmd -- * * Implements [info class variables $clsName] * * ---------------------------------------------------------------------- */ static int InfoClassVariablesCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Class *clsPtr; Tcl_Obj *variableObj, *resultObj; int i; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "className"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } resultObj = Tcl_NewObj(); FOREACH(variableObj, clsPtr->variables) { Tcl_ListObjAppendElement(NULL, resultObj, variableObj); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoObjectCallCmd -- * * Implements [info object call $objName $methodName] * * ---------------------------------------------------------------------- */ static int InfoObjectCallCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Object *oPtr; CallContext *contextPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "objName methodName"); return TCL_ERROR; } oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]); if (oPtr == NULL) { return TCL_ERROR; } /* * Get the call context and render its call chain. */ contextPtr = TclOOGetCallContext(oPtr, objv[2], PUBLIC_METHOD, NULL); if (contextPtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot construct any call chain", -1)); return TCL_ERROR; } Tcl_SetObjResult(interp, TclOORenderCallChain(interp, contextPtr->callPtr)); TclOODeleteContext(contextPtr); return TCL_OK; } /* * ---------------------------------------------------------------------- * * InfoClassCallCmd -- * * Implements [info class call $clsName $methodName] * * ---------------------------------------------------------------------- */ static int InfoClassCallCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Class *clsPtr; CallChain *callPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "className methodName"); return TCL_ERROR; } clsPtr = GetClassFromObj(interp, objv[1]); if (clsPtr == NULL) { return TCL_ERROR; } /* * Get an render the stereotypical call chain. */ callPtr = TclOOGetStereotypeCallChain(clsPtr, objv[2], PUBLIC_METHOD); if (callPtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot construct any call chain", -1)); return TCL_ERROR; } Tcl_SetObjResult(interp, TclOORenderCallChain(interp, callPtr)); TclOODeleteChain(callPtr); return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclOOInt.h0000644000175000017500000005640312663660065015057 0ustar sergeisergei/* * tclOOInt.h -- * * This file contains the structure definitions and some of the function * declarations for the object-system (NB: not Tcl_Obj, but ::oo). * * Copyright (c) 2006-2012 by Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef TCL_OO_INTERNAL_H #define TCL_OO_INTERNAL_H 1 #include "tclInt.h" #include "tclOO.h" /* * Hack to make things work with Objective C. Note that ObjC isn't really * supported, but we don't want to to be actively hostile to it. [Bug 2163447] */ #ifdef __OBJC__ #define Class TclOOClass #define Object TclOOObject #endif /* __OBJC__ */ /* * Forward declarations. */ struct CallChain; struct Class; struct Foundation; struct Object; /* * The data that needs to be stored per method. This record is used to collect * information about all sorts of methods, including forwards, constructors * and destructors. */ typedef struct Method { const Tcl_MethodType *typePtr; /* The type of method. If NULL, this is a * special flag record which is just used for * the setting of the flags field. */ int refCount; ClientData clientData; /* Type-specific data. */ Tcl_Obj *namePtr; /* Name of the method. */ struct Object *declaringObjectPtr; /* The object that declares this method, or * NULL if it was declared by a class. */ struct Class *declaringClassPtr; /* The class that declares this method, or * NULL if it was declared directly on an * object. */ int flags; /* Assorted flags. Includes whether this * method is public/exported or not. */ } Method; /* * Pre- and post-call callbacks, to allow procedure-like methods to be fine * tuned in their behaviour. */ typedef int (TclOO_PreCallProc)(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, Tcl_CallFrame *framePtr, int *isFinished); typedef int (TclOO_PostCallProc)(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, Tcl_Namespace *namespacePtr, int result); typedef void (TclOO_PmCDDeleteProc)(ClientData clientData); typedef ClientData (TclOO_PmCDCloneProc)(ClientData clientData); /* * Procedure-like methods have the following extra information. */ typedef struct ProcedureMethod { int version; /* Version of this structure. Currently must * be 0. */ Proc *procPtr; /* Core of the implementation of the method; * includes the argument definition and the * body bytecodes. */ int flags; /* Flags to control features. */ int refCount; ClientData clientData; TclOO_PmCDDeleteProc *deleteClientdataProc; TclOO_PmCDCloneProc *cloneClientdataProc; ProcErrorProc *errProc; /* Replacement error handler. */ TclOO_PreCallProc *preCallProc; /* Callback to allow for additional setup * before the method executes. */ TclOO_PostCallProc *postCallProc; /* Callback to allow for additional cleanup * after the method executes. */ GetFrameInfoValueProc *gfivProc; /* Callback to allow for fine tuning of how * the method reports itself. */ } ProcedureMethod; #define TCLOO_PROCEDURE_METHOD_VERSION 0 /* * Flags for use in a ProcedureMethod. * * When the USE_DECLARER_NS flag is set, the method will use the namespace of * the object or class that declared it (or the clone of it, if it was from * such that the implementation of the method came to the particular use) * instead of the namespace of the object on which the method was invoked. * This flag must be distinct from all others that are associated with * methods. */ #define USE_DECLARER_NS 0x80 /* * Forwarded methods have the following extra information. */ typedef struct ForwardMethod { Tcl_Obj *prefixObj; /* The list of values to use to replace the * object and method name with. Will be a * non-empty list. */ } ForwardMethod; /* * Helper definitions that declare a "list" array. The two varieties are * either optimized for simplicity (in the case that the whole array is * typically assigned at once) or efficiency (in the case that the array is * expected to be expanded over time). These lists are designed to be iterated * over with the help of the FOREACH macro (see later in this file). * * The "num" field always counts the number of listType_t elements used in the * "list" field. When a "size" field exists, it describes how many elements * are present in the list; when absent, exactly "num" elements are present. */ #define LIST_STATIC(listType_t) \ struct { int num; listType_t *list; } #define LIST_DYNAMIC(listType_t) \ struct { int num, size; listType_t *list; } /* * Now, the definition of what an object actually is. */ typedef struct Object { struct Foundation *fPtr; /* The basis for the object system. Putting * this here allows the avoidance of quite a * lot of hash lookups on the critical path * for object invokation and creation. */ Tcl_Namespace *namespacePtr;/* This object's tame namespace. */ Tcl_Command command; /* Reference to this object's public * command. */ Tcl_Command myCommand; /* Reference to this object's internal * command. */ struct Class *selfCls; /* This object's class. */ Tcl_HashTable *methodsPtr; /* Object-local Tcl_Obj (method name) to * Method* mapping. */ LIST_STATIC(struct Class *) mixins; /* Classes mixed into this object. */ LIST_STATIC(Tcl_Obj *) filters; /* List of filter names. */ struct Class *classPtr; /* All classes have this non-NULL; it points * to the class structure. Everything else has * this NULL. */ int refCount; /* Number of strong references to this object. * Note that there may be many more weak * references; this mechanism is there to * avoid Tcl_Preserve. */ int flags; int creationEpoch; /* Unique value to make comparisons of objects * easier. */ int epoch; /* Per-object epoch, incremented when the way * an object should resolve call chains is * changed. */ Tcl_HashTable *metadataPtr; /* Mapping from pointers to metadata type to * the ClientData values that are the values * of each piece of attached metadata. This * field starts out as NULL and is only * allocated if metadata is attached. */ Tcl_Obj *cachedNameObj; /* Cache of the name of the object. */ Tcl_HashTable *chainCache; /* Place to keep unused contexts. This table * is indexed by method name as Tcl_Obj. */ Tcl_ObjectMapMethodNameProc *mapMethodNameProc; /* Function to allow remapping of method * names. For itcl-ng. */ LIST_STATIC(Tcl_Obj *) variables; } Object; #define OBJECT_DELETED 1 /* Flag to say that an object has been * destroyed. */ #define DESTRUCTOR_CALLED 2 /* Flag to say that the destructor has been * called. */ #define CLASS_GONE 4 /* Indicates that the class of this object has * been deleted, and so the object should not * attempt to remove itself from its class. */ #define ROOT_OBJECT 0x1000 /* Flag to say that this object is the root of * the class hierarchy and should be treated * specially during teardown. */ #define FILTER_HANDLING 0x2000 /* Flag set when the object is processing a * filter; when set, filters are *not* * processed on the object, preventing nasty * recursive filtering problems. */ #define USE_CLASS_CACHE 0x4000 /* Flag set to say that the object is a pure * instance of the class, and has had nothing * added that changes the dispatch chain (i.e. * no methods, mixins, or filters. */ #define ROOT_CLASS 0x8000 /* Flag to say that this object is the root * class of classes, and should be treated * specially during teardown (and in a few * other spots). */ #define FORCE_UNKNOWN 0x10000 /* States that we are *really* looking up the * unknown method handler at that point. */ /* * And the definition of a class. Note that every class also has an associated * object, through which it is manipulated. */ typedef struct Class { Object *thisPtr; /* Reference to the object associated with * this class. */ int refCount; /* Number of strong references to this class. * Weak references are not counted; the * purpose of this is to avoid Tcl_Preserve as * that is quite slow. */ int flags; /* Assorted flags. */ LIST_STATIC(struct Class *) superclasses; /* List of superclasses, used for generation * of method call chains. */ LIST_DYNAMIC(struct Class *) subclasses; /* List of subclasses, used to ensure deletion * of dependent entities happens properly when * the class itself is deleted. */ LIST_DYNAMIC(Object *) instances; /* List of instances, used to ensure deletion * of dependent entities happens properly when * the class itself is deleted. */ LIST_STATIC(Tcl_Obj *) filters; /* List of filter names, used for generation * of method call chains. */ LIST_STATIC(struct Class *) mixins; /* List of mixin classes, used for generation * of method call chains. */ LIST_DYNAMIC(struct Class *) mixinSubs; /* List of classes that this class is mixed * into, used to ensure deletion of dependent * entities happens properly when the class * itself is deleted. */ Tcl_HashTable classMethods; /* Hash table of all methods. Hash maps from * the (Tcl_Obj*) method name to the (Method*) * method record. */ Method *constructorPtr; /* Method record of the class constructor (if * any). */ Method *destructorPtr; /* Method record of the class destructor (if * any). */ Tcl_HashTable *metadataPtr; /* Mapping from pointers to metadata type to * the ClientData values that are the values * of each piece of attached metadata. This * field starts out as NULL and is only * allocated if metadata is attached. */ struct CallChain *constructorChainPtr; struct CallChain *destructorChainPtr; Tcl_HashTable *classChainCache; /* Places where call chains are stored. For * constructors, the class chain is always * used. For destructors and ordinary methods, * the class chain is only used when the * object doesn't override with its own mixins * (and filters and method implementations for * when getting method chains). */ LIST_STATIC(Tcl_Obj *) variables; } Class; /* * The foundation of the object system within an interpreter contains * references to the key classes and namespaces, together with a few other * useful bits and pieces. Probably ought to eventually go in the Interp * structure itself. */ typedef struct ThreadLocalData { int nsCount; /* Master epoch counter is used for keeping * the values used in Tcl_Obj internal * representations sane. Must be thread-local * because Tcl_Objs can cross interpreter * boundaries within a thread (objects don't * generally cross threads). */ } ThreadLocalData; typedef struct Foundation { Tcl_Interp *interp; Class *objectCls; /* The root of the object system. */ Class *classCls; /* The class of all classes. */ Tcl_Namespace *ooNs; /* Master ::oo namespace. */ Tcl_Namespace *defineNs; /* Namespace containing special commands for * manipulating objects and classes. The * "oo::define" command acts as a special kind * of ensemble for this namespace. */ Tcl_Namespace *objdefNs; /* Namespace containing special commands for * manipulating objects and classes. The * "oo::objdefine" command acts as a special * kind of ensemble for this namespace. */ Tcl_Namespace *helpersNs; /* Namespace containing the commands that are * only valid when executing inside a * procedural method. */ int epoch; /* Used to invalidate method chains when the * class structure changes. */ ThreadLocalData *tsdPtr; /* Counter so we can allocate a unique * namespace to each object. */ Tcl_Obj *unknownMethodNameObj; /* Shared object containing the name of the * unknown method handler method. */ Tcl_Obj *constructorName; /* Shared object containing the "name" of a * constructor. */ Tcl_Obj *destructorName; /* Shared object containing the "name" of a * destructor. */ Tcl_Obj *clonedName; /* Shared object containing the name of a * "" pseudo-constructor. */ Tcl_Obj *defineName; /* Fully qualified name of oo::define. */ } Foundation; /* * A call context structure is built when a method is called. They contain the * chain of method implementations that are to be invoked by a particular * call, and the process of calling walks the chain, with the [next] command * proceeding to the next entry in the chain. */ #define CALL_CHAIN_STATIC_SIZE 4 struct MInvoke { Method *mPtr; /* Reference to the method implementation * record. */ int isFilter; /* Whether this is a filter invokation. */ Class *filterDeclarer; /* What class decided to add the filter; if * NULL, it was added by the object. */ }; typedef struct CallChain { int objectCreationEpoch; /* The object's creation epoch. Note that the * object reference is not stored in the call * chain; it is in the call context. */ int objectEpoch; /* Local (object structure) epoch counter * snapshot. */ int epoch; /* Global (class structure) epoch counter * snapshot. */ int flags; /* Assorted flags, see below. */ int refCount; /* Reference count. */ int numChain; /* Size of the call chain. */ struct MInvoke *chain; /* Array of call chain entries. May point to * staticChain if the number of entries is * small. */ struct MInvoke staticChain[CALL_CHAIN_STATIC_SIZE]; } CallChain; typedef struct CallContext { Object *oPtr; /* The object associated with this call. */ int index; /* Index into the call chain of the currently * executing method implementation. */ int skip; /* Current number of arguments to skip; can * vary depending on whether it is a direct * method call or a continuation via the * [next] command. */ CallChain *callPtr; /* The actual call chain. */ } CallContext; /* * Bits for the 'flags' field of the call chain. */ #define PUBLIC_METHOD 0x01 /* This is a public (exported) method. */ #define PRIVATE_METHOD 0x02 /* This is a private (class's direct instances * only) method. */ #define OO_UNKNOWN_METHOD 0x04 /* This is an unknown method. */ #define CONSTRUCTOR 0x08 /* This is a constructor. */ #define DESTRUCTOR 0x10 /* This is a destructor. */ /* * Structure containing definition information about basic class methods. */ typedef struct { const char *name; /* Name of the method in question. */ int isPublic; /* Whether the method is public by default. */ Tcl_MethodType definition; /* How to call the method. */ } DeclaredClassMethod; /* *---------------------------------------------------------------- * Commands relating to OO support. *---------------------------------------------------------------- */ MODULE_SCOPE int TclOOInit(Tcl_Interp *interp); MODULE_SCOPE int TclOODefineObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOOObjDefObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOODefineConstructorObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOODefineDeleteMethodObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOODefineDestructorObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOODefineExportObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOODefineForwardObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOODefineMethodObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOODefineRenameMethodObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOODefineUnexportObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOODefineClassObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOODefineSelfObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOOUnknownDefinition(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOOCopyObjectCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOONextObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOONextToObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOOSelfObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); /* * Method implementations (in tclOOBasic.c). */ MODULE_SCOPE int TclOO_Class_Constructor(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOO_Class_Create(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOO_Class_CreateNs(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOO_Class_New(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOO_Object_Destroy(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOO_Object_Eval(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOO_Object_LinkVar(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOO_Object_Unknown(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); MODULE_SCOPE int TclOO_Object_VarName(ClientData clientData, Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv); /* * Private definitions, some of which perhaps ought to be exposed properly or * maybe just put in the internal stubs table. */ MODULE_SCOPE void TclOOAddToInstances(Object *oPtr, Class *clsPtr); MODULE_SCOPE void TclOOAddToMixinSubs(Class *subPtr, Class *mixinPtr); MODULE_SCOPE void TclOOAddToSubclasses(Class *subPtr, Class *superPtr); MODULE_SCOPE int TclNRNewObjectInstance(Tcl_Interp *interp, Tcl_Class cls, const char *nameStr, const char *nsNameStr, int objc, Tcl_Obj *const *objv, int skip, Tcl_Object *objectPtr); MODULE_SCOPE int TclOODefineSlots(Foundation *fPtr); MODULE_SCOPE void TclOODeleteChain(CallChain *callPtr); MODULE_SCOPE void TclOODeleteChainCache(Tcl_HashTable *tablePtr); MODULE_SCOPE void TclOODeleteContext(CallContext *contextPtr); MODULE_SCOPE void TclOODelMethodRef(Method *method); MODULE_SCOPE CallContext *TclOOGetCallContext(Object *oPtr, Tcl_Obj *methodNameObj, int flags, Tcl_Obj *cacheInThisObj); MODULE_SCOPE CallChain *TclOOGetStereotypeCallChain(Class *clsPtr, Tcl_Obj *methodNameObj, int flags); MODULE_SCOPE Foundation *TclOOGetFoundation(Tcl_Interp *interp); MODULE_SCOPE Tcl_Obj * TclOOGetFwdFromMethod(Method *mPtr); MODULE_SCOPE Proc * TclOOGetProcFromMethod(Method *mPtr); MODULE_SCOPE Tcl_Obj * TclOOGetMethodBody(Method *mPtr); MODULE_SCOPE int TclOOGetSortedClassMethodList(Class *clsPtr, int flags, const char ***stringsPtr); MODULE_SCOPE int TclOOGetSortedMethodList(Object *oPtr, int flags, const char ***stringsPtr); MODULE_SCOPE int TclOOInit(Tcl_Interp *interp); MODULE_SCOPE void TclOOInitInfo(Tcl_Interp *interp); MODULE_SCOPE int TclOOInvokeContext(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclNRObjectContextInvokeNext(Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv, int skip); MODULE_SCOPE void TclOONewBasicMethod(Tcl_Interp *interp, Class *clsPtr, const DeclaredClassMethod *dcm); MODULE_SCOPE Tcl_Obj * TclOOObjectName(Tcl_Interp *interp, Object *oPtr); MODULE_SCOPE void TclOORemoveFromInstances(Object *oPtr, Class *clsPtr); MODULE_SCOPE void TclOORemoveFromMixinSubs(Class *subPtr, Class *mixinPtr); MODULE_SCOPE void TclOORemoveFromSubclasses(Class *subPtr, Class *superPtr); MODULE_SCOPE Tcl_Obj * TclOORenderCallChain(Tcl_Interp *interp, CallChain *callPtr); MODULE_SCOPE void TclOOStashContext(Tcl_Obj *objPtr, CallContext *contextPtr); MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr); /* * Include all the private API, generated from tclOO.decls. */ #include "tclOOIntDecls.h" /* * A convenience macro for iterating through the lists used in the internal * memory management of objects. This is a bit gnarly because we want to do * the assignment of the picked-out value only when the body test succeeds, * but we cannot rely on the assigned value being useful, forcing us to do * some nasty stuff with the comma operator. The compiler's optimizer should * be able to sort it all out! * * REQUIRES DECLARATION: int i; */ #define FOREACH(var,ary) \ for(i=0 ; (i<(ary).num?((var=(ary).list[i]),1):0) ; i++) /* * Convenience macros for iterating through hash tables. FOREACH_HASH_DECLS * sets up the declarations needed for the main macro, FOREACH_HASH, which * does the actual iteration. FOREACH_HASH_VALUE is a restricted version that * only iterates over values. */ #define FOREACH_HASH_DECLS \ Tcl_HashEntry *hPtr;Tcl_HashSearch search #define FOREACH_HASH(key,val,tablePtr) \ for(hPtr=Tcl_FirstHashEntry((tablePtr),&search); hPtr!=NULL ? \ ((key)=(void *)Tcl_GetHashKey((tablePtr),hPtr),\ (val)=Tcl_GetHashValue(hPtr),1):0; hPtr=Tcl_NextHashEntry(&search)) #define FOREACH_HASH_VALUE(val,tablePtr) \ for(hPtr=Tcl_FirstHashEntry((tablePtr),&search); hPtr!=NULL ? \ ((val)=Tcl_GetHashValue(hPtr),1):0;hPtr=Tcl_NextHashEntry(&search)) /* * Convenience macro for duplicating a list. Needs no external declaration, * but all arguments are used multiple times and so must have no side effects. */ #undef DUPLICATE /* prevent possible conflict with definition in WINAPI nb30.h */ #define DUPLICATE(target,source,type) \ do { \ register unsigned len = sizeof(type) * ((target).num=(source).num);\ if (len != 0) { \ memcpy(((target).list=(type*)ckalloc(len)), (source).list, len); \ } else { \ (target).list = NULL; \ } \ } while(0) /* * Alternatives to Tcl_Preserve/Tcl_EventuallyFree/Tcl_Release. */ #define AddRef(ptr) ((ptr)->refCount++) #define DelRef(ptr) do { \ if ((ptr)->refCount-- <= 1) { \ ckfree((char *) (ptr)); \ } \ } while(0) #endif /* TCL_OO_INTERNAL_H */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclOO.c0000644000175000017500000024601112663660065014373 0ustar sergeisergei/* * tclOO.c -- * * This file contains the object-system core (NB: not Tcl_Obj, but ::oo) * * Copyright (c) 2005-2012 by Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tclInt.h" #include "tclOOInt.h" /* * Commands in oo::define. */ static const struct { const char *name; Tcl_ObjCmdProc *objProc; int flag; } defineCmds[] = { {"constructor", TclOODefineConstructorObjCmd, 0}, {"deletemethod", TclOODefineDeleteMethodObjCmd, 0}, {"destructor", TclOODefineDestructorObjCmd, 0}, {"export", TclOODefineExportObjCmd, 0}, {"forward", TclOODefineForwardObjCmd, 0}, {"method", TclOODefineMethodObjCmd, 0}, {"renamemethod", TclOODefineRenameMethodObjCmd, 0}, {"self", TclOODefineSelfObjCmd, 0}, {"unexport", TclOODefineUnexportObjCmd, 0}, {NULL, NULL, 0} }, objdefCmds[] = { {"class", TclOODefineClassObjCmd, 1}, {"deletemethod", TclOODefineDeleteMethodObjCmd, 1}, {"export", TclOODefineExportObjCmd, 1}, {"forward", TclOODefineForwardObjCmd, 1}, {"method", TclOODefineMethodObjCmd, 1}, {"renamemethod", TclOODefineRenameMethodObjCmd, 1}, {"unexport", TclOODefineUnexportObjCmd, 1}, {NULL, NULL, 0} }; /* * What sort of size of things we like to allocate. */ #define ALLOC_CHUNK 8 /* * Function declarations for things defined in this file. */ static Class * AllocClass(Tcl_Interp *interp, Object *useThisObj); static Object * AllocObject(Tcl_Interp *interp, const char *nameStr, const char *nsNameStr); static void ClearMixins(Class *clsPtr); static void ClearSuperclasses(Class *clsPtr); static int CloneClassMethod(Tcl_Interp *interp, Class *clsPtr, Method *mPtr, Tcl_Obj *namePtr, Method **newMPtrPtr); static int CloneObjectMethod(Tcl_Interp *interp, Object *oPtr, Method *mPtr, Tcl_Obj *namePtr); static void DeletedDefineNamespace(ClientData clientData); static void DeletedObjdefNamespace(ClientData clientData); static void DeletedHelpersNamespace(ClientData clientData); static int FinalizeAlloc(ClientData data[], Tcl_Interp *interp, int result); static int FinalizeNext(ClientData data[], Tcl_Interp *interp, int result); static int FinalizeObjectCall(ClientData data[], Tcl_Interp *interp, int result); static int InitFoundation(Tcl_Interp *interp); static void KillFoundation(ClientData clientData, Tcl_Interp *interp); static void MyDeleted(ClientData clientData); static void ObjectNamespaceDeleted(ClientData clientData); static void ObjectRenamedTrace(ClientData clientData, Tcl_Interp *interp, const char *oldName, const char *newName, int flags); static void ReleaseClassContents(Tcl_Interp *interp,Object *oPtr); static inline void SquelchCachedName(Object *oPtr); static void SquelchedNsFirst(ClientData clientData); static int PublicObjectCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int PublicNRObjectCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int PrivateObjectCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static int PrivateNRObjectCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); /* * Methods in the oo::object and oo::class classes. First, we define a helper * macro that makes building the method type declaration structure a lot * easier. No point in making life harder than it has to be! * * Note that the core methods don't need clone or free proc callbacks. */ #define DCM(name,visibility,proc) \ {name,visibility,\ {TCL_OO_METHOD_VERSION_CURRENT,"core method: "#name,proc,NULL,NULL}} static const DeclaredClassMethod objMethods[] = { DCM("destroy", 1, TclOO_Object_Destroy), DCM("eval", 0, TclOO_Object_Eval), DCM("unknown", 0, TclOO_Object_Unknown), DCM("variable", 0, TclOO_Object_LinkVar), DCM("varname", 0, TclOO_Object_VarName), {NULL, 0, {0, NULL, NULL, NULL, NULL}} }, clsMethods[] = { DCM("create", 1, TclOO_Class_Create), DCM("new", 1, TclOO_Class_New), DCM("createWithNamespace", 0, TclOO_Class_CreateNs), {NULL, 0, {0, NULL, NULL, NULL, NULL}} }; /* * And for the oo::class constructor... */ static const Tcl_MethodType classConstructor = { TCL_OO_METHOD_VERSION_CURRENT, "oo::class constructor", TclOO_Class_Constructor, NULL, NULL }; /* * Scripted parts of TclOO. First, the master script (cannot be outside this * file). */ static const char *initScript = "package ifneeded TclOO " TCLOO_PATCHLEVEL " {# Already present, OK?};" "namespace eval ::oo { variable version " TCLOO_VERSION " };" "namespace eval ::oo { variable patchlevel " TCLOO_PATCHLEVEL " };"; /* "tcl_findLibrary tcloo $oo::version $oo::version" */ /* " tcloo.tcl OO_LIBRARY oo::library;"; */ /* * The scripted part of the definitions of slots. */ static const char *slotScript = "::oo::define ::oo::Slot {\n" " method Get {} {error unimplemented}\n" " method Set list {error unimplemented}\n" " method -set args {\n" " uplevel 1 [list [namespace which my] Set $args]\n" " }\n" " method -append args {\n" " uplevel 1 [list [namespace which my] Set [list" " {*}[uplevel 1 [list [namespace which my] Get]] {*}$args]]\n" " }\n" " method -clear {} {uplevel 1 [list [namespace which my] Set {}]}\n" " forward --default-operation my -append\n" " method unknown {args} {\n" " set def --default-operation\n" " if {[llength $args] == 0} {\n" " return [uplevel 1 [list [namespace which my] $def]]\n" " } elseif {![string match -* [lindex $args 0]]} {\n" " return [uplevel 1 [list [namespace which my] $def {*}$args]]\n" " }\n" " next {*}$args\n" " }\n" " export -set -append -clear\n" " unexport unknown destroy\n" "}\n" "::oo::objdefine ::oo::define::superclass forward --default-operation my -set\n" "::oo::objdefine ::oo::define::mixin forward --default-operation my -set\n" "::oo::objdefine ::oo::objdefine::mixin forward --default-operation my -set\n"; /* * The body of the method of oo::object. */ static const char *clonedBody = "foreach p [info procs [info object namespace $originObject]::*] {" " set args [info args $p];" " set idx -1;" " foreach a $args {" " lset args [incr idx] " " [if {[info default $p $a d]} {list $a $d} {list $a}]" " };" " set b [info body $p];" " set p [namespace tail $p];" " proc $p $args $b;" "};" "foreach v [info vars [info object namespace $originObject]::*] {" " upvar 0 $v vOrigin;" " namespace upvar [namespace current] [namespace tail $v] vNew;" " if {[info exists vOrigin]} {" " if {[array exists vOrigin]} {" " array set vNew [array get vOrigin];" " } else {" " set vNew $vOrigin;" " }" " }" "}"; /* * The actual definition of the variable holding the TclOO stub table. */ MODULE_SCOPE const TclOOStubs tclOOStubs; /* * Convenience macro for getting the foundation from an interpreter. */ #define GetFoundation(interp) \ ((Foundation *)((Interp *)(interp))->objectFoundation) /* * Macros to make inspecting into the guts of an object cleaner. * * The ocPtr parameter (only in these macros) is assumed to work fine with * either an oPtr or a classPtr. Note that the roots oo::object and oo::class * have _both_ their object and class flags tagged with ROOT_OBJECT and * ROOT_CLASS respectively. */ #define Deleted(oPtr) (((Object *)(oPtr))->command == NULL) #define IsRootObject(ocPtr) ((ocPtr)->flags & ROOT_OBJECT) #define IsRootClass(ocPtr) ((ocPtr)->flags & ROOT_CLASS) #define IsRoot(ocPtr) ((ocPtr)->flags & (ROOT_OBJECT|ROOT_CLASS)) /* * ---------------------------------------------------------------------- * * TclOOInit -- * * Called to initialise the OO system within an interpreter. * * Result: * TCL_OK if the setup succeeded. Currently assumed to always work. * * Side effects: * Creates namespaces, commands, several classes and a number of * callbacks. Upon return, the OO system is ready for use. * * ---------------------------------------------------------------------- */ int TclOOInit( Tcl_Interp *interp) /* The interpreter to install into. */ { /* * Build the core of the OO system. */ if (InitFoundation(interp) != TCL_OK) { return TCL_ERROR; } /* * Run our initialization script and, if that works, declare the package * to be fully provided. */ if (Tcl_Eval(interp, initScript) != TCL_OK) { return TCL_ERROR; } return Tcl_PkgProvideEx(interp, "TclOO", TCLOO_PATCHLEVEL, (ClientData) &tclOOStubs); } /* * ---------------------------------------------------------------------- * * TclOOGetFoundation -- * * Get a reference to the OO core class system. * * ---------------------------------------------------------------------- */ Foundation * TclOOGetFoundation( Tcl_Interp *interp) { return GetFoundation(interp); } /* * ---------------------------------------------------------------------- * * InitFoundation -- * * Set up the core of the OO core class system. This is a structure * holding references to the magical bits that need to be known about in * other places, plus the oo::object and oo::class classes. * * ---------------------------------------------------------------------- */ static int InitFoundation( Tcl_Interp *interp) { static Tcl_ThreadDataKey tsdKey; ThreadLocalData *tsdPtr = Tcl_GetThreadData(&tsdKey, sizeof(ThreadLocalData)); Foundation *fPtr = ckalloc(sizeof(Foundation)); Tcl_Obj *namePtr, *argsPtr, *bodyPtr; Tcl_DString buffer; Command *cmdPtr; int i; /* * Initialize the structure that holds the OO system core. This is * attached to the interpreter via an assocData entry; not very efficient, * but the best we can do without hacking the core more. */ memset(fPtr, 0, sizeof(Foundation)); ((Interp *) interp)->objectFoundation = fPtr; fPtr->interp = interp; fPtr->ooNs = Tcl_CreateNamespace(interp, "::oo", fPtr, NULL); Tcl_Export(interp, fPtr->ooNs, "[a-z]*", 1); fPtr->defineNs = Tcl_CreateNamespace(interp, "::oo::define", fPtr, DeletedDefineNamespace); fPtr->objdefNs = Tcl_CreateNamespace(interp, "::oo::objdefine", fPtr, DeletedObjdefNamespace); fPtr->helpersNs = Tcl_CreateNamespace(interp, "::oo::Helpers", fPtr, DeletedHelpersNamespace); fPtr->epoch = 0; fPtr->tsdPtr = tsdPtr; TclNewLiteralStringObj(fPtr->unknownMethodNameObj, "unknown"); TclNewLiteralStringObj(fPtr->constructorName, ""); TclNewLiteralStringObj(fPtr->destructorName, ""); TclNewLiteralStringObj(fPtr->clonedName, ""); TclNewLiteralStringObj(fPtr->defineName, "::oo::define"); Tcl_IncrRefCount(fPtr->unknownMethodNameObj); Tcl_IncrRefCount(fPtr->constructorName); Tcl_IncrRefCount(fPtr->destructorName); Tcl_IncrRefCount(fPtr->clonedName); Tcl_IncrRefCount(fPtr->defineName); Tcl_CreateObjCommand(interp, "::oo::UnknownDefinition", TclOOUnknownDefinition, NULL, NULL); TclNewLiteralStringObj(namePtr, "::oo::UnknownDefinition"); Tcl_SetNamespaceUnknownHandler(interp, fPtr->defineNs, namePtr); Tcl_SetNamespaceUnknownHandler(interp, fPtr->objdefNs, namePtr); /* * Create the subcommands in the oo::define and oo::objdefine spaces. */ Tcl_DStringInit(&buffer); for (i=0 ; defineCmds[i].name ; i++) { TclDStringAppendLiteral(&buffer, "::oo::define::"); Tcl_DStringAppend(&buffer, defineCmds[i].name, -1); Tcl_CreateObjCommand(interp, Tcl_DStringValue(&buffer), defineCmds[i].objProc, INT2PTR(defineCmds[i].flag), NULL); Tcl_DStringFree(&buffer); } for (i=0 ; objdefCmds[i].name ; i++) { TclDStringAppendLiteral(&buffer, "::oo::objdefine::"); Tcl_DStringAppend(&buffer, objdefCmds[i].name, -1); Tcl_CreateObjCommand(interp, Tcl_DStringValue(&buffer), objdefCmds[i].objProc, INT2PTR(objdefCmds[i].flag), NULL); Tcl_DStringFree(&buffer); } Tcl_CallWhenDeleted(interp, KillFoundation, NULL); /* * Create the objects at the core of the object system. These need to be * spliced manually. */ fPtr->objectCls = AllocClass(interp, AllocObject(interp, "::oo::object", NULL)); fPtr->classCls = AllocClass(interp, AllocObject(interp, "::oo::class", NULL)); fPtr->objectCls->thisPtr->selfCls = fPtr->classCls; fPtr->objectCls->thisPtr->flags |= ROOT_OBJECT; fPtr->objectCls->flags |= ROOT_OBJECT; fPtr->objectCls->superclasses.num = 0; ckfree(fPtr->objectCls->superclasses.list); fPtr->objectCls->superclasses.list = NULL; fPtr->classCls->thisPtr->selfCls = fPtr->classCls; fPtr->classCls->thisPtr->flags |= ROOT_CLASS; fPtr->classCls->flags |= ROOT_CLASS; TclOOAddToInstances(fPtr->objectCls->thisPtr, fPtr->classCls); TclOOAddToInstances(fPtr->classCls->thisPtr, fPtr->classCls); TclOOAddToSubclasses(fPtr->classCls, fPtr->objectCls); AddRef(fPtr->objectCls->thisPtr); AddRef(fPtr->objectCls); /* * Basic method declarations for the core classes. */ for (i=0 ; objMethods[i].name ; i++) { TclOONewBasicMethod(interp, fPtr->objectCls, &objMethods[i]); } for (i=0 ; clsMethods[i].name ; i++) { TclOONewBasicMethod(interp, fPtr->classCls, &clsMethods[i]); } /* * Create the default method implementation, used when 'oo::copy' * is called to finish the copying of one object to another. */ TclNewLiteralStringObj(argsPtr, "originObject"); Tcl_IncrRefCount(argsPtr); bodyPtr = Tcl_NewStringObj(clonedBody, -1); TclOONewProcMethod(interp, fPtr->objectCls, 0, fPtr->clonedName, argsPtr, bodyPtr, NULL); TclDecrRefCount(argsPtr); /* * Finish setting up the class of classes by marking the 'new' method as * private; classes, unlike general objects, must have explicit names. We * also need to create the constructor for classes. */ TclNewLiteralStringObj(namePtr, "new"); Tcl_NewInstanceMethod(interp, (Tcl_Object) fPtr->classCls->thisPtr, namePtr /* keeps ref */, 0 /* ==private */, NULL, NULL); fPtr->classCls->constructorPtr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) fPtr->classCls, NULL, 0, &classConstructor, NULL); /* * Create non-object commands and plug ourselves into the Tcl [info] * ensemble. */ cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "::oo::Helpers::next", NULL, TclOONextObjCmd, NULL, NULL); cmdPtr->compileProc = TclCompileObjectNextCmd; cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "::oo::Helpers::nextto", NULL, TclOONextToObjCmd, NULL, NULL); cmdPtr->compileProc = TclCompileObjectNextToCmd; cmdPtr = (Command *) Tcl_CreateObjCommand(interp, "::oo::Helpers::self", TclOOSelfObjCmd, NULL, NULL); cmdPtr->compileProc = TclCompileObjectSelfCmd; Tcl_CreateObjCommand(interp, "::oo::define", TclOODefineObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "::oo::objdefine", TclOOObjDefObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "::oo::copy", TclOOCopyObjectCmd, NULL,NULL); TclOOInitInfo(interp); /* * Now make the class of slots. */ if (TclOODefineSlots(fPtr) != TCL_OK) { return TCL_ERROR; } return Tcl_Eval(interp, slotScript); } /* * ---------------------------------------------------------------------- * * DeletedDefineNamespace, DeletedObjdefNamespace, DeletedHelpersNamespace -- * * Simple helpers used to clear fields of the foundation when they no * longer hold useful information. * * ---------------------------------------------------------------------- */ static void DeletedDefineNamespace( ClientData clientData) { Foundation *fPtr = clientData; fPtr->defineNs = NULL; } static void DeletedObjdefNamespace( ClientData clientData) { Foundation *fPtr = clientData; fPtr->objdefNs = NULL; } static void DeletedHelpersNamespace( ClientData clientData) { Foundation *fPtr = clientData; fPtr->helpersNs = NULL; } /* * ---------------------------------------------------------------------- * * KillFoundation -- * * Delete those parts of the OO core that are not deleted automatically * when the objects and classes themselves are destroyed. * * ---------------------------------------------------------------------- */ static void KillFoundation( ClientData clientData, /* Pointer to the OO system foundation * structure. */ Tcl_Interp *interp) /* The interpreter containing the OO system * foundation. */ { Foundation *fPtr = GetFoundation(interp); DelRef(fPtr->objectCls->thisPtr); DelRef(fPtr->objectCls); TclDecrRefCount(fPtr->unknownMethodNameObj); TclDecrRefCount(fPtr->constructorName); TclDecrRefCount(fPtr->destructorName); TclDecrRefCount(fPtr->clonedName); TclDecrRefCount(fPtr->defineName); ckfree(fPtr); } /* * ---------------------------------------------------------------------- * * AllocObject -- * * Allocate an object of basic type. Does not splice the object into its * class's instance list. * * ---------------------------------------------------------------------- */ static Object * AllocObject( Tcl_Interp *interp, /* Interpreter within which to create the * object. */ const char *nameStr, /* The name of the object to create, or NULL * if the OO system should pick the object * name itself (equal to the namespace * name). */ const char *nsNameStr) /* The name of the namespace to create, or * NULL if the OO system should pick a unique * name itself. If this is non-NULL but names * a namespace that already exists, the effect * will be the same as if this was NULL. */ { Foundation *fPtr = GetFoundation(interp); Object *oPtr; Command *cmdPtr; CommandTrace *tracePtr; int creationEpoch, ignored; oPtr = ckalloc(sizeof(Object)); memset(oPtr, 0, sizeof(Object)); /* * Every object has a namespace; make one. Note that this also normally * computes the creation epoch value for the object, a sequence number * that is unique to the object (and which allows us to manage method * caching without comparing pointers). * * When creating a namespace, we first check to see if the caller * specified the name for the namespace. If not, we generate namespace * names using the epoch until such time as a new namespace is actually * created. */ if (nsNameStr != NULL) { oPtr->namespacePtr = Tcl_CreateNamespace(interp, nsNameStr, oPtr, ObjectNamespaceDeleted); if (oPtr->namespacePtr != NULL) { creationEpoch = ++fPtr->tsdPtr->nsCount; goto configNamespace; } Tcl_ResetResult(interp); } while (1) { char objName[10 + TCL_INTEGER_SPACE]; sprintf(objName, "::oo::Obj%d", ++fPtr->tsdPtr->nsCount); oPtr->namespacePtr = Tcl_CreateNamespace(interp, objName, oPtr, ObjectNamespaceDeleted); if (oPtr->namespacePtr != NULL) { creationEpoch = fPtr->tsdPtr->nsCount; break; } /* * Could not make that namespace, so we make another. But first we * have to get rid of the error message from Tcl_CreateNamespace, * since that's something that should not be exposed to the user. */ Tcl_ResetResult(interp); } /* * Make the namespace know about the helper commands. This grants access * to the [self] and [next] commands. */ configNamespace: if (fPtr->helpersNs != NULL) { TclSetNsPath((Namespace *) oPtr->namespacePtr, 1, &fPtr->helpersNs); } TclOOSetupVariableResolver(oPtr->namespacePtr); /* * Suppress use of compiled versions of the commands in this object's * namespace and its children; causes wrong behaviour without expensive * recompilation. [Bug 2037727] */ ((Namespace *) oPtr->namespacePtr)->flags |= NS_SUPPRESS_COMPILATION; /* * Set up a callback to get notification of the deletion of a namespace * when enough of the namespace still remains to execute commands and * access variables in it. [Bug 2950259] */ ((Namespace *) oPtr->namespacePtr)->earlyDeleteProc = SquelchedNsFirst; /* * Fill in the rest of the non-zero/NULL parts of the structure. */ oPtr->fPtr = fPtr; oPtr->selfCls = fPtr->objectCls; oPtr->creationEpoch = creationEpoch; oPtr->refCount = 1; oPtr->flags = USE_CLASS_CACHE; /* * Finally, create the object commands and initialize the trace on the * public command (so that the object structures are deleted when the * command is deleted). */ if (!nameStr) { oPtr->command = Tcl_CreateObjCommand(interp, oPtr->namespacePtr->fullName, PublicObjectCmd, oPtr, NULL); } else if (nameStr[0] == ':' && nameStr[1] == ':') { oPtr->command = Tcl_CreateObjCommand(interp, nameStr, PublicObjectCmd, oPtr, NULL); } else { Tcl_DString buffer; Tcl_DStringInit(&buffer); Tcl_DStringAppend(&buffer, Tcl_GetCurrentNamespace(interp)->fullName, -1); TclDStringAppendLiteral(&buffer, "::"); Tcl_DStringAppend(&buffer, nameStr, -1); oPtr->command = Tcl_CreateObjCommand(interp, Tcl_DStringValue(&buffer), PublicObjectCmd, oPtr, NULL); Tcl_DStringFree(&buffer); } /* * Add the NRE command and trace directly. While this breaks a number of * abstractions, it is faster and we're inside Tcl here so we're allowed. */ cmdPtr = (Command *) oPtr->command; cmdPtr->nreProc = PublicNRObjectCmd; cmdPtr->tracePtr = tracePtr = ckalloc(sizeof(CommandTrace)); tracePtr->traceProc = ObjectRenamedTrace; tracePtr->clientData = oPtr; tracePtr->flags = TCL_TRACE_RENAME|TCL_TRACE_DELETE; tracePtr->nextPtr = NULL; tracePtr->refCount = 1; /* * Access the namespace command table directly when creating "my" to avoid * a bottleneck in string manipulation. Another abstraction-buster. */ cmdPtr = ckalloc(sizeof(Command)); memset(cmdPtr, 0, sizeof(Command)); cmdPtr->nsPtr = (Namespace *) oPtr->namespacePtr; cmdPtr->hPtr = Tcl_CreateHashEntry(&cmdPtr->nsPtr->cmdTable, "my", &ignored); cmdPtr->refCount = 1; cmdPtr->objProc = PrivateObjectCmd; cmdPtr->deleteProc = MyDeleted; cmdPtr->objClientData = cmdPtr->deleteData = oPtr; cmdPtr->proc = TclInvokeObjectCommand; cmdPtr->clientData = cmdPtr; cmdPtr->nreProc = PrivateNRObjectCmd; Tcl_SetHashValue(cmdPtr->hPtr, cmdPtr); oPtr->myCommand = (Tcl_Command) cmdPtr; return oPtr; } /* * ---------------------------------------------------------------------- * * SquelchCachedName -- * * Encapsulates how to throw away a cached object name. Called from * object rename traces and at object destruction. * * ---------------------------------------------------------------------- */ static inline void SquelchCachedName( Object *oPtr) { if (oPtr->cachedNameObj) { Tcl_DecrRefCount(oPtr->cachedNameObj); oPtr->cachedNameObj = NULL; } } /* * ---------------------------------------------------------------------- * * MyDeleted -- * * This callback is triggered when the object's [my] command is deleted * by any mechanism. It just marks the object as not having a [my] * command, and so prevents cleanup of that when the object itself is * deleted. * * ---------------------------------------------------------------------- */ static void MyDeleted( ClientData clientData) /* Reference to the object whose [my] has been * squelched. */ { register Object *oPtr = clientData; oPtr->myCommand = NULL; } /* * ---------------------------------------------------------------------- * * SquelchedNsFirst -- * * This callback is triggered when the object's namespace is deleted by * any mechanism. It deletes the object's public command if it has not * already been deleted, so ensuring that destructors get run at an * appropriate time. [Bug 2950259] * * ---------------------------------------------------------------------- */ static void SquelchedNsFirst( ClientData clientData) { Object *oPtr = clientData; if (oPtr->command) { Tcl_DeleteCommandFromToken(oPtr->fPtr->interp, oPtr->command); } } /* * ---------------------------------------------------------------------- * * ObjectRenamedTrace -- * * This callback is triggered when the object is deleted by any * mechanism. It runs the destructors and arranges for the actual cleanup * of the object's namespace, which in turn triggers cleansing of the * object data structures. * * ---------------------------------------------------------------------- */ static void ObjectRenamedTrace( ClientData clientData, /* The object being deleted. */ Tcl_Interp *interp, /* The interpreter containing the object. */ const char *oldName, /* What the object was (last) called. */ const char *newName, /* What it's getting renamed to. (unused) */ int flags) /* Why was the object deleted? */ { Object *oPtr = clientData; Foundation *fPtr = oPtr->fPtr; /* * If this is a rename and not a delete of the object, we just flush the * cache of the object name. */ if (flags & TCL_TRACE_RENAME) { SquelchCachedName(oPtr); return; } /* * Oh dear, the object really is being deleted. Handle this by running the * destructors and deleting the object's namespace, which in turn causes * the real object structures to be deleted. * * Note that it is possible for the namespace to be deleted before the * command. Because of that case, we must take care here to mark the * command as being deleted so that if we return here we don't run into * reentrancy problems. * * We also do not run destructors on the core class objects when the * interpreter is being deleted; their incestuous nature causes problems * in that case when the destructor is partially deleted before the uses * of it have gone. [Bug 2949397] */ AddRef(oPtr); AddRef(fPtr->classCls); AddRef(fPtr->objectCls); AddRef(fPtr->classCls->thisPtr); AddRef(fPtr->objectCls->thisPtr); oPtr->command = NULL; if (!(oPtr->flags & DESTRUCTOR_CALLED) && !Tcl_InterpDeleted(interp)) { CallContext *contextPtr = TclOOGetCallContext(oPtr, NULL, DESTRUCTOR, NULL); int result; Tcl_InterpState state; oPtr->flags |= DESTRUCTOR_CALLED; if (contextPtr != NULL) { contextPtr->callPtr->flags |= DESTRUCTOR; contextPtr->skip = 0; state = Tcl_SaveInterpState(interp, TCL_OK); result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr, 0, NULL); if (result != TCL_OK) { Tcl_BackgroundException(interp, result); } Tcl_RestoreInterpState(interp, state); TclOODeleteContext(contextPtr); } } /* * OK, the destructor's been run. Time to splat the class data (if any) * and nuke the namespace (which triggers the final crushing of the object * structure itself). * * The class of objects needs some special care; if it is deleted (and * we're not killing the whole interpreter) we force the delete of the * class of classes now as well. Due to the incestuous nature of those two * classes, if one goes the other must too and yet the tangle can * sometimes not go away automatically; we force it here. [Bug 2962664] */ if (!Tcl_InterpDeleted(interp) && IsRootObject(oPtr) && !Deleted(fPtr->classCls->thisPtr)) { Tcl_DeleteCommandFromToken(interp, fPtr->classCls->thisPtr->command); } if (oPtr->classPtr != NULL) { AddRef(oPtr->classPtr); ReleaseClassContents(interp, oPtr); } /* * The namespace is only deleted if it hasn't already been deleted. [Bug * 2950259] */ if (((Namespace *) oPtr->namespacePtr)->earlyDeleteProc != NULL) { Tcl_DeleteNamespace(oPtr->namespacePtr); } if (oPtr->classPtr) { DelRef(oPtr->classPtr); } DelRef(fPtr->classCls->thisPtr); DelRef(fPtr->objectCls->thisPtr); DelRef(fPtr->classCls); DelRef(fPtr->objectCls); DelRef(oPtr); } /* * ---------------------------------------------------------------------- * * ClearMixins, ClearSuperclasses -- * * Utility functions for correctly clearing the list of mixins or * superclasses of a class. Will ckfree() the list storage. * * ---------------------------------------------------------------------- */ static void ClearMixins( Class *clsPtr) { int i; Class *mixinPtr; if (clsPtr->mixins.num == 0) { return; } FOREACH(mixinPtr, clsPtr->mixins) { TclOORemoveFromMixinSubs(clsPtr, mixinPtr); } ckfree(clsPtr->mixins.list); clsPtr->mixins.list = NULL; clsPtr->mixins.num = 0; } static void ClearSuperclasses( Class *clsPtr) { int i; Class *superPtr; if (clsPtr->superclasses.num == 0) { return; } FOREACH(superPtr, clsPtr->superclasses) { TclOORemoveFromSubclasses(clsPtr, superPtr); } ckfree(clsPtr->superclasses.list); clsPtr->superclasses.list = NULL; clsPtr->superclasses.num = 0; } /* * ---------------------------------------------------------------------- * * ReleaseClassContents -- * * Tear down the special class data structure, including deleting all * dependent classes and objects. * * ---------------------------------------------------------------------- */ static void ReleaseClassContents( Tcl_Interp *interp, /* The interpreter containing the class. */ Object *oPtr) /* The object representing the class. */ { FOREACH_HASH_DECLS; int i; Class *clsPtr = oPtr->classPtr, *mixinSubclassPtr, *subclassPtr; Object *instancePtr; Foundation *fPtr = oPtr->fPtr; /* * Sanity check! */ if (!Deleted(oPtr)) { if (IsRootClass(oPtr)) { Tcl_Panic("deleting class structure for non-deleted %s", "::oo::class"); } else if (IsRootObject(oPtr)) { Tcl_Panic("deleting class structure for non-deleted %s", "::oo::object"); } else { Tcl_Panic("deleting class structure for non-deleted %s", "general object"); } } /* * Lock a number of dependent objects until we've stopped putting our * fingers in them. */ FOREACH(mixinSubclassPtr, clsPtr->mixinSubs) { if (mixinSubclassPtr != NULL) { AddRef(mixinSubclassPtr); AddRef(mixinSubclassPtr->thisPtr); } } FOREACH(subclassPtr, clsPtr->subclasses) { if (subclassPtr != NULL && !IsRoot(subclassPtr)) { AddRef(subclassPtr); AddRef(subclassPtr->thisPtr); } } if (!IsRootClass(oPtr)) { FOREACH(instancePtr, clsPtr->instances) { int j; if (instancePtr->selfCls == clsPtr) { instancePtr->flags |= CLASS_GONE; } for(j=0 ; jmixins.num ; j++) { Class *mixin = instancePtr->mixins.list[j]; if (mixin == clsPtr) { instancePtr->mixins.list[j] = NULL; } } if (instancePtr != NULL && !IsRoot(instancePtr)) { AddRef(instancePtr); } } } /* * Squelch classes that this class has been mixed into. */ FOREACH(mixinSubclassPtr, clsPtr->mixinSubs) { if (!Deleted(mixinSubclassPtr->thisPtr)) { Tcl_DeleteCommandFromToken(interp, mixinSubclassPtr->thisPtr->command); } ClearMixins(mixinSubclassPtr); DelRef(mixinSubclassPtr->thisPtr); DelRef(mixinSubclassPtr); } if (clsPtr->mixinSubs.list != NULL) { ckfree(clsPtr->mixinSubs.list); clsPtr->mixinSubs.list = NULL; clsPtr->mixinSubs.num = 0; } /* * Squelch subclasses of this class. */ FOREACH(subclassPtr, clsPtr->subclasses) { if (IsRoot(subclassPtr)) { continue; } if (!Deleted(subclassPtr->thisPtr)) { Tcl_DeleteCommandFromToken(interp, subclassPtr->thisPtr->command); } ClearSuperclasses(subclassPtr); DelRef(subclassPtr->thisPtr); DelRef(subclassPtr); } if (clsPtr->subclasses.list != NULL) { ckfree(clsPtr->subclasses.list); clsPtr->subclasses.list = NULL; clsPtr->subclasses.num = 0; } /* * Squelch instances of this class (includes objects we're mixed into). */ if (!IsRootClass(oPtr)) { FOREACH(instancePtr, clsPtr->instances) { if (instancePtr == NULL || IsRoot(instancePtr)) { continue; } if (!Deleted(instancePtr)) { Tcl_DeleteCommandFromToken(interp, instancePtr->command); /* * Tcl_DeleteCommandFromToken() may have done to whole * job for us. Roll back and check again. */ i--; continue; } DelRef(instancePtr); } } if (clsPtr->instances.list != NULL) { ckfree(clsPtr->instances.list); clsPtr->instances.list = NULL; clsPtr->instances.num = 0; } /* * Special: We delete these after everything else. */ if (IsRootClass(oPtr) && !Deleted(fPtr->objectCls->thisPtr)) { Tcl_DeleteCommandFromToken(interp, fPtr->objectCls->thisPtr->command); } /* * Squelch method implementation chain caches. */ if (clsPtr->constructorChainPtr) { TclOODeleteChain(clsPtr->constructorChainPtr); clsPtr->constructorChainPtr = NULL; } if (clsPtr->destructorChainPtr) { TclOODeleteChain(clsPtr->destructorChainPtr); clsPtr->destructorChainPtr = NULL; } if (clsPtr->classChainCache) { CallChain *callPtr; FOREACH_HASH_VALUE(callPtr, clsPtr->classChainCache) { TclOODeleteChain(callPtr); } Tcl_DeleteHashTable(clsPtr->classChainCache); ckfree(clsPtr->classChainCache); clsPtr->classChainCache = NULL; } /* * Squelch our filter list. */ if (clsPtr->filters.num) { Tcl_Obj *filterObj; FOREACH(filterObj, clsPtr->filters) { TclDecrRefCount(filterObj); } ckfree(clsPtr->filters.list); clsPtr->filters.num = 0; } /* * Squelch our metadata. */ if (clsPtr->metadataPtr != NULL) { Tcl_ObjectMetadataType *metadataTypePtr; ClientData value; FOREACH_HASH(metadataTypePtr, value, clsPtr->metadataPtr) { metadataTypePtr->deleteProc(value); } Tcl_DeleteHashTable(clsPtr->metadataPtr); ckfree(clsPtr->metadataPtr); clsPtr->metadataPtr = NULL; } } /* * ---------------------------------------------------------------------- * * ObjectNamespaceDeleted -- * * Callback when the object's namespace is deleted. Used to clean up the * data structures associated with the object. The complicated bit is * that this can sometimes happen before the object's command is deleted * (interpreter teardown is complex!) * * ---------------------------------------------------------------------- */ static void ObjectNamespaceDeleted( ClientData clientData) /* Pointer to the class whose namespace is * being deleted. */ { Object *oPtr = clientData; FOREACH_HASH_DECLS; Class *clsPtr = oPtr->classPtr, *mixinPtr; Method *mPtr; Tcl_Obj *filterObj, *variableObj; int i; /* * Instruct everyone to no longer use any allocated fields of the object. * Also delete the commands that refer to the object at this point (if * they still exist) because otherwise their references to the object * point into freed memory, allowing crashes. */ if (oPtr->command) { Tcl_DeleteCommandFromToken(oPtr->fPtr->interp, oPtr->command); } if (oPtr->myCommand) { Tcl_DeleteCommandFromToken(oPtr->fPtr->interp, oPtr->myCommand); } /* * Splice the object out of its context. After this, we must *not* call * methods on the object. */ if (!IsRootObject(oPtr) && !(oPtr->flags & CLASS_GONE)) { TclOORemoveFromInstances(oPtr, oPtr->selfCls); } FOREACH(mixinPtr, oPtr->mixins) { if (mixinPtr) { TclOORemoveFromInstances(oPtr, mixinPtr); } } if (i) { ckfree(oPtr->mixins.list); } FOREACH(filterObj, oPtr->filters) { TclDecrRefCount(filterObj); } if (i) { ckfree(oPtr->filters.list); } if (oPtr->methodsPtr) { FOREACH_HASH_VALUE(mPtr, oPtr->methodsPtr) { TclOODelMethodRef(mPtr); } Tcl_DeleteHashTable(oPtr->methodsPtr); ckfree(oPtr->methodsPtr); } FOREACH(variableObj, oPtr->variables) { TclDecrRefCount(variableObj); } if (i) { ckfree(oPtr->variables.list); } if (oPtr->chainCache) { TclOODeleteChainCache(oPtr->chainCache); } SquelchCachedName(oPtr); if (oPtr->metadataPtr != NULL) { Tcl_ObjectMetadataType *metadataTypePtr; ClientData value; FOREACH_HASH(metadataTypePtr, value, oPtr->metadataPtr) { metadataTypePtr->deleteProc(value); } Tcl_DeleteHashTable(oPtr->metadataPtr); ckfree(oPtr->metadataPtr); oPtr->metadataPtr = NULL; } /* * If this was a class, there's additional deletion work to do. */ if (clsPtr != NULL) { Tcl_ObjectMetadataType *metadataTypePtr; ClientData value; if (clsPtr->metadataPtr != NULL) { FOREACH_HASH(metadataTypePtr, value, clsPtr->metadataPtr) { metadataTypePtr->deleteProc(value); } Tcl_DeleteHashTable(clsPtr->metadataPtr); ckfree(clsPtr->metadataPtr); clsPtr->metadataPtr = NULL; } FOREACH(filterObj, clsPtr->filters) { TclDecrRefCount(filterObj); } if (i) { ckfree(clsPtr->filters.list); clsPtr->filters.num = 0; } ClearMixins(clsPtr); ClearSuperclasses(clsPtr); if (clsPtr->subclasses.list) { ckfree(clsPtr->subclasses.list); clsPtr->subclasses.num = 0; } if (clsPtr->instances.list) { ckfree(clsPtr->instances.list); clsPtr->instances.num = 0; } if (clsPtr->mixinSubs.list) { ckfree(clsPtr->mixinSubs.list); clsPtr->mixinSubs.num = 0; } FOREACH_HASH_VALUE(mPtr, &clsPtr->classMethods) { TclOODelMethodRef(mPtr); } Tcl_DeleteHashTable(&clsPtr->classMethods); TclOODelMethodRef(clsPtr->constructorPtr); TclOODelMethodRef(clsPtr->destructorPtr); FOREACH(variableObj, clsPtr->variables) { TclDecrRefCount(variableObj); } if (i) { ckfree(clsPtr->variables.list); } DelRef(clsPtr); } /* * Delete the object structure itself. */ DelRef(oPtr); } /* * ---------------------------------------------------------------------- * * TclOORemoveFromInstances -- * * Utility function to remove an object from the list of instances within * a class. * * ---------------------------------------------------------------------- */ void TclOORemoveFromInstances( Object *oPtr, /* The instance to remove. */ Class *clsPtr) /* The class (possibly) containing the * reference to the instance. */ { int i; Object *instPtr; FOREACH(instPtr, clsPtr->instances) { if (oPtr == instPtr) { goto removeInstance; } } return; removeInstance: if (Deleted(clsPtr->thisPtr)) { if (!IsRootClass(clsPtr)) { DelRef(clsPtr->instances.list[i]); } clsPtr->instances.list[i] = NULL; } else { clsPtr->instances.num--; if (i < clsPtr->instances.num) { clsPtr->instances.list[i] = clsPtr->instances.list[clsPtr->instances.num]; } clsPtr->instances.list[clsPtr->instances.num] = NULL; } } /* * ---------------------------------------------------------------------- * * TclOOAddToInstances -- * * Utility function to add an object to the list of instances within a * class. * * ---------------------------------------------------------------------- */ void TclOOAddToInstances( Object *oPtr, /* The instance to add. */ Class *clsPtr) /* The class to add the instance to. It is * assumed that the class is not already * present as an instance in the class. */ { if (Deleted(clsPtr->thisPtr)) { return; } if (clsPtr->instances.num >= clsPtr->instances.size) { clsPtr->instances.size += ALLOC_CHUNK; if (clsPtr->instances.size == ALLOC_CHUNK) { clsPtr->instances.list = ckalloc(sizeof(Object *) * ALLOC_CHUNK); } else { clsPtr->instances.list = ckrealloc(clsPtr->instances.list, sizeof(Object *) * clsPtr->instances.size); } } clsPtr->instances.list[clsPtr->instances.num++] = oPtr; } /* * ---------------------------------------------------------------------- * * TclOORemoveFromSubclasses -- * * Utility function to remove a class from the list of subclasses within * another class. * * ---------------------------------------------------------------------- */ void TclOORemoveFromSubclasses( Class *subPtr, /* The subclass to remove. */ Class *superPtr) /* The superclass to (possibly) remove the * subclass reference from. */ { int i; Class *subclsPtr; FOREACH(subclsPtr, superPtr->subclasses) { if (subPtr == subclsPtr) { goto removeSubclass; } } return; removeSubclass: if (!Deleted(superPtr->thisPtr)) { superPtr->subclasses.num--; if (i < superPtr->subclasses.num) { superPtr->subclasses.list[i] = superPtr->subclasses.list[superPtr->subclasses.num]; } superPtr->subclasses.list[superPtr->subclasses.num] = NULL; } } /* * ---------------------------------------------------------------------- * * TclOOAddToSubclasses -- * * Utility function to add a class to the list of subclasses within * another class. * * ---------------------------------------------------------------------- */ void TclOOAddToSubclasses( Class *subPtr, /* The subclass to add. */ Class *superPtr) /* The superclass to add the subclass to. It * is assumed that the class is not already * present as a subclass in the superclass. */ { if (Deleted(superPtr->thisPtr)) { return; } if (superPtr->subclasses.num >= superPtr->subclasses.size) { superPtr->subclasses.size += ALLOC_CHUNK; if (superPtr->subclasses.size == ALLOC_CHUNK) { superPtr->subclasses.list = ckalloc(sizeof(Class*) * ALLOC_CHUNK); } else { superPtr->subclasses.list = ckrealloc(superPtr->subclasses.list, sizeof(Class *) * superPtr->subclasses.size); } } superPtr->subclasses.list[superPtr->subclasses.num++] = subPtr; } /* * ---------------------------------------------------------------------- * * TclOORemoveFromMixinSubs -- * * Utility function to remove a class from the list of mixinSubs within * another class. * * ---------------------------------------------------------------------- */ void TclOORemoveFromMixinSubs( Class *subPtr, /* The subclass to remove. */ Class *superPtr) /* The superclass to (possibly) remove the * subclass reference from. */ { int i; Class *subclsPtr; FOREACH(subclsPtr, superPtr->mixinSubs) { if (subPtr == subclsPtr) { goto removeSubclass; } } return; removeSubclass: if (!Deleted(superPtr->thisPtr)) { superPtr->mixinSubs.num--; if (i < superPtr->mixinSubs.num) { superPtr->mixinSubs.list[i] = superPtr->mixinSubs.list[superPtr->mixinSubs.num]; } superPtr->mixinSubs.list[superPtr->mixinSubs.num] = NULL; } } /* * ---------------------------------------------------------------------- * * TclOOAddToMixinSubs -- * * Utility function to add a class to the list of mixinSubs within * another class. * * ---------------------------------------------------------------------- */ void TclOOAddToMixinSubs( Class *subPtr, /* The subclass to add. */ Class *superPtr) /* The superclass to add the subclass to. It * is assumed that the class is not already * present as a subclass in the superclass. */ { if (Deleted(superPtr->thisPtr)) { return; } if (superPtr->mixinSubs.num >= superPtr->mixinSubs.size) { superPtr->mixinSubs.size += ALLOC_CHUNK; if (superPtr->mixinSubs.size == ALLOC_CHUNK) { superPtr->mixinSubs.list = ckalloc(sizeof(Class *) * ALLOC_CHUNK); } else { superPtr->mixinSubs.list = ckrealloc(superPtr->mixinSubs.list, sizeof(Class *) * superPtr->mixinSubs.size); } } superPtr->mixinSubs.list[superPtr->mixinSubs.num++] = subPtr; } /* * ---------------------------------------------------------------------- * * AllocClass -- * * Allocate a basic class. Does not splice the class object into its * class's instance list. * * ---------------------------------------------------------------------- */ static Class * AllocClass( Tcl_Interp *interp, /* Interpreter within which to allocate the * class. */ Object *useThisObj) /* Object that is to act as the class * representation, or NULL if a new object * (with automatic name) is to be used. */ { Foundation *fPtr = GetFoundation(interp); Class *clsPtr = ckalloc(sizeof(Class)); /* * Make an object if we haven't been given one. */ memset(clsPtr, 0, sizeof(Class)); if (useThisObj == NULL) { clsPtr->thisPtr = AllocObject(interp, NULL, NULL); } else { clsPtr->thisPtr = useThisObj; } /* * Configure the namespace path for the class's object. */ if (fPtr->helpersNs != NULL) { Tcl_Namespace *path[2]; path[0] = fPtr->helpersNs; path[1] = fPtr->ooNs; TclSetNsPath((Namespace *) clsPtr->thisPtr->namespacePtr, 2, path); } else { TclSetNsPath((Namespace *) clsPtr->thisPtr->namespacePtr, 1, &fPtr->ooNs); } /* * Class objects inherit from the class of classes unless they inherit * from some subclass of it. Enforce this right now. */ clsPtr->thisPtr->selfCls = fPtr->classCls; /* * Classes are subclasses of oo::object, i.e. the objects they create are * objects. */ clsPtr->superclasses.num = 1; clsPtr->superclasses.list = ckalloc(sizeof(Class *)); clsPtr->superclasses.list[0] = fPtr->objectCls; /* * Finish connecting the class structure to the object structure. */ clsPtr->thisPtr->classPtr = clsPtr; /* * That's the complicated bit. Now fill in the rest of the non-zero/NULL * fields. */ clsPtr->refCount = 1; Tcl_InitObjHashTable(&clsPtr->classMethods); return clsPtr; } /* * ---------------------------------------------------------------------- * * Tcl_NewObjectInstance -- * * Allocate a new instance of an object. * * ---------------------------------------------------------------------- */ Tcl_Object Tcl_NewObjectInstance( Tcl_Interp *interp, /* Interpreter context. */ Tcl_Class cls, /* Class to create an instance of. */ const char *nameStr, /* Name of object to create, or NULL to ask * the code to pick its own unique name. */ const char *nsNameStr, /* Name of namespace to create inside object, * or NULL to ask the code to pick its own * unique name. */ int objc, /* Number of arguments. Negative value means * do not call constructor. */ Tcl_Obj *const *objv, /* Argument list. */ int skip) /* Number of arguments to _not_ pass to the * constructor. */ { register Class *classPtr = (Class *) cls; Foundation *fPtr = GetFoundation(interp); Object *oPtr; /* * Check if we're going to create an object over an existing command; * that's not allowed. */ if (nameStr && Tcl_FindCommand(interp, nameStr, NULL, TCL_NAMESPACE_ONLY)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create object \"%s\": command already exists with" " that name", nameStr)); Tcl_SetErrorCode(interp, "TCL", "OO", "OVERWRITE_OBJECT", NULL); return NULL; } /* * Create the object. */ oPtr = AllocObject(interp, nameStr, nsNameStr); oPtr->selfCls = classPtr; TclOOAddToInstances(oPtr, classPtr); /* * Check to see if we're really creating a class. If so, allocate the * class structure as well. */ if (TclOOIsReachable(fPtr->classCls, classPtr)) { /* * Is a class, so attach a class structure. Note that the AllocClass * function splices the structure into the object, so we don't have * to. Once that's done, we need to repatch the object to have the * right class since AllocClass interferes with that. */ AllocClass(interp, oPtr); oPtr->selfCls = classPtr; TclOOAddToSubclasses(oPtr->classPtr, fPtr->objectCls); } /* * Run constructors, except when objc < 0 (a special flag case used for * object cloning only). */ if (objc >= 0) { CallContext *contextPtr = TclOOGetCallContext(oPtr, NULL, CONSTRUCTOR, NULL); if (contextPtr != NULL) { int result; Tcl_InterpState state; state = Tcl_SaveInterpState(interp, TCL_OK); contextPtr->callPtr->flags |= CONSTRUCTOR; contextPtr->skip = skip; /* * Adjust the ensmble tracking record if necessary. [Bug 3514761] */ if (((Interp*) interp)->ensembleRewrite.sourceObjs) { ((Interp*) interp)->ensembleRewrite.numInsertedObjs += skip-1; ((Interp*) interp)->ensembleRewrite.numRemovedObjs += skip-1; } result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr, objc, objv); /* * It's an error if the object was whacked in the constructor. * Force this if it isn't already an error (don't want to lose * errors by accident...) [Bug 2903011] */ if (result != TCL_ERROR && Deleted(oPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "object deleted in constructor", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "STILLBORN", NULL); result = TCL_ERROR; } TclOODeleteContext(contextPtr); if (result != TCL_OK) { Tcl_DiscardInterpState(state); /* * Take care to not delete a deleted object; that would be * bad. [Bug 2903011] Also take care to make sure that we have * the name of the command before we delete it. [Bug * 9dd1bd7a74] */ if (!Deleted(oPtr)) { (void) TclOOObjectName(interp, oPtr); Tcl_DeleteCommandFromToken(interp, oPtr->command); } return NULL; } Tcl_RestoreInterpState(interp, state); } } return (Tcl_Object) oPtr; } int TclNRNewObjectInstance( Tcl_Interp *interp, /* Interpreter context. */ Tcl_Class cls, /* Class to create an instance of. */ const char *nameStr, /* Name of object to create, or NULL to ask * the code to pick its own unique name. */ const char *nsNameStr, /* Name of namespace to create inside object, * or NULL to ask the code to pick its own * unique name. */ int objc, /* Number of arguments. Negative value means * do not call constructor. */ Tcl_Obj *const *objv, /* Argument list. */ int skip, /* Number of arguments to _not_ pass to the * constructor. */ Tcl_Object *objectPtr) /* Place to write the object reference upon * successful allocation. */ { register Class *classPtr = (Class *) cls; Foundation *fPtr = GetFoundation(interp); CallContext *contextPtr; Tcl_InterpState state; Object *oPtr; /* * Check if we're going to create an object over an existing command; * that's not allowed. */ if (nameStr && Tcl_FindCommand(interp, nameStr, NULL, TCL_NAMESPACE_ONLY)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create object \"%s\": command already exists with" " that name", nameStr)); Tcl_SetErrorCode(interp, "TCL", "OO", "OVERWRITE_OBJECT", NULL); return TCL_ERROR; } /* * Create the object. */ oPtr = AllocObject(interp, nameStr, nsNameStr); oPtr->selfCls = classPtr; TclOOAddToInstances(oPtr, classPtr); /* * Check to see if we're really creating a class. If so, allocate the * class structure as well. */ if (TclOOIsReachable(fPtr->classCls, classPtr)) { /* * Is a class, so attach a class structure. Note that the AllocClass * function splices the structure into the object, so we don't have * to. Once that's done, we need to repatch the object to have the * right class since AllocClass interferes with that. */ AllocClass(interp, oPtr); oPtr->selfCls = classPtr; TclOOAddToSubclasses(oPtr->classPtr, fPtr->objectCls); } /* * Run constructors, except when objc < 0 (a special flag case used for * object cloning only). If there aren't any constructors, we do nothing. */ if (objc < 0) { *objectPtr = (Tcl_Object) oPtr; return TCL_OK; } contextPtr = TclOOGetCallContext(oPtr, NULL, CONSTRUCTOR, NULL); if (contextPtr == NULL) { *objectPtr = (Tcl_Object) oPtr; return TCL_OK; } state = Tcl_SaveInterpState(interp, TCL_OK); contextPtr->callPtr->flags |= CONSTRUCTOR; contextPtr->skip = skip; /* * Adjust the ensmble tracking record if necessary. [Bug 3514761] */ if (((Interp *) interp)->ensembleRewrite.sourceObjs) { ((Interp *) interp)->ensembleRewrite.numInsertedObjs += skip - 1; ((Interp *) interp)->ensembleRewrite.numRemovedObjs += skip - 1; } /* * Fire off the constructors non-recursively. */ AddRef(oPtr); TclNRAddCallback(interp, FinalizeAlloc, contextPtr, oPtr, state, objectPtr); TclPushTailcallPoint(interp); return TclOOInvokeContext(contextPtr, interp, objc, objv); } static int FinalizeAlloc( ClientData data[], Tcl_Interp *interp, int result) { CallContext *contextPtr = data[0]; Object *oPtr = data[1]; Tcl_InterpState state = data[2]; Tcl_Object *objectPtr = data[3]; /* * It's an error if the object was whacked in the constructor. Force this * if it isn't already an error (don't want to lose errors by accident...) * [Bug 2903011] */ if (result != TCL_ERROR && Deleted(oPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "object deleted in constructor", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "STILLBORN", NULL); result = TCL_ERROR; } TclOODeleteContext(contextPtr); if (result != TCL_OK) { Tcl_DiscardInterpState(state); /* * Take care to not delete a deleted object; that would be bad. [Bug * 2903011] Also take care to make sure that we have the name of the * command before we delete it. [Bug 9dd1bd7a74] */ if (!Deleted(oPtr)) { (void) TclOOObjectName(interp, oPtr); Tcl_DeleteCommandFromToken(interp, oPtr->command); } DelRef(oPtr); return TCL_ERROR; } Tcl_RestoreInterpState(interp, state); *objectPtr = (Tcl_Object) oPtr; DelRef(oPtr); return TCL_OK; } /* * ---------------------------------------------------------------------- * * Tcl_CopyObjectInstance -- * * Creates a copy of an object. Does not copy the backing namespace, * since the correct way to do that (e.g., shallow/deep) depends on the * object/class's own policies. * * ---------------------------------------------------------------------- */ Tcl_Object Tcl_CopyObjectInstance( Tcl_Interp *interp, Tcl_Object sourceObject, const char *targetName, const char *targetNamespaceName) { Object *oPtr = (Object *) sourceObject, *o2Ptr; FOREACH_HASH_DECLS; Method *mPtr; Class *mixinPtr; CallContext *contextPtr; Tcl_Obj *keyPtr, *filterObj, *variableObj, *args[3]; int i, result; /* * Sanity check. */ if (IsRootClass(oPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may not clone the class of classes", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "CLONING_CLASS", NULL); return NULL; } /* * Build the instance. Note that this does not run any constructors. */ o2Ptr = (Object *) Tcl_NewObjectInstance(interp, (Tcl_Class) oPtr->selfCls, targetName, targetNamespaceName, -1, NULL, -1); if (o2Ptr == NULL) { return NULL; } /* * Copy the object-local methods to the new object. */ if (oPtr->methodsPtr) { FOREACH_HASH(keyPtr, mPtr, oPtr->methodsPtr) { if (CloneObjectMethod(interp, o2Ptr, mPtr, keyPtr) != TCL_OK) { Tcl_DeleteCommandFromToken(interp, o2Ptr->command); return NULL; } } } /* * Copy the object's mixin references to the new object. */ FOREACH(mixinPtr, o2Ptr->mixins) { if (mixinPtr && mixinPtr != o2Ptr->selfCls) { TclOORemoveFromInstances(o2Ptr, mixinPtr); } } DUPLICATE(o2Ptr->mixins, oPtr->mixins, Class *); FOREACH(mixinPtr, o2Ptr->mixins) { if (mixinPtr && mixinPtr != o2Ptr->selfCls) { TclOOAddToInstances(o2Ptr, mixinPtr); } } /* * Copy the object's filter list to the new object. */ DUPLICATE(o2Ptr->filters, oPtr->filters, Tcl_Obj *); FOREACH(filterObj, o2Ptr->filters) { Tcl_IncrRefCount(filterObj); } /* * Copy the object's variable resolution list to the new object. */ DUPLICATE(o2Ptr->variables, oPtr->variables, Tcl_Obj *); FOREACH(variableObj, o2Ptr->variables) { Tcl_IncrRefCount(variableObj); } /* * Copy the object's flags to the new object, clearing those that must be * kept object-local. The duplicate is never deleted at this point, nor is * it the root of the object system or in the midst of processing a filter * call. */ o2Ptr->flags = oPtr->flags & ~( OBJECT_DELETED | ROOT_OBJECT | ROOT_CLASS | FILTER_HANDLING); /* * Copy the object's metadata. */ if (oPtr->metadataPtr != NULL) { Tcl_ObjectMetadataType *metadataTypePtr; ClientData value, duplicate; FOREACH_HASH(metadataTypePtr, value, oPtr->metadataPtr) { if (metadataTypePtr->cloneProc == NULL) { duplicate = value; } else { if (metadataTypePtr->cloneProc(interp, value, &duplicate) != TCL_OK) { Tcl_DeleteCommandFromToken(interp, o2Ptr->command); return NULL; } } if (duplicate != NULL) { Tcl_ObjectSetMetadata((Tcl_Object) o2Ptr, metadataTypePtr, duplicate); } } } /* * Copy the class, if present. Note that if there is a class present in * the source object, there must also be one in the copy. */ if (oPtr->classPtr != NULL) { Class *clsPtr = oPtr->classPtr; Class *cls2Ptr = o2Ptr->classPtr; Class *superPtr; /* * Copy the class flags across. */ cls2Ptr->flags = clsPtr->flags; /* * Ensure that the new class's superclass structure is the same as the * old class's. */ FOREACH(superPtr, cls2Ptr->superclasses) { TclOORemoveFromSubclasses(cls2Ptr, superPtr); } if (cls2Ptr->superclasses.num) { cls2Ptr->superclasses.list = ckrealloc(cls2Ptr->superclasses.list, sizeof(Class *) * clsPtr->superclasses.num); } else { cls2Ptr->superclasses.list = ckalloc(sizeof(Class *) * clsPtr->superclasses.num); } memcpy(cls2Ptr->superclasses.list, clsPtr->superclasses.list, sizeof(Class *) * clsPtr->superclasses.num); cls2Ptr->superclasses.num = clsPtr->superclasses.num; FOREACH(superPtr, cls2Ptr->superclasses) { TclOOAddToSubclasses(cls2Ptr, superPtr); } /* * Duplicate the source class's filters. */ DUPLICATE(cls2Ptr->filters, clsPtr->filters, Tcl_Obj *); FOREACH(filterObj, cls2Ptr->filters) { Tcl_IncrRefCount(filterObj); } /* * Copy the source class's variable resolution list. */ DUPLICATE(cls2Ptr->variables, clsPtr->variables, Tcl_Obj *); FOREACH(variableObj, cls2Ptr->variables) { Tcl_IncrRefCount(variableObj); } /* * Duplicate the source class's mixins (which cannot be circular * references to the duplicate). */ FOREACH(mixinPtr, cls2Ptr->mixins) { TclOORemoveFromMixinSubs(cls2Ptr, mixinPtr); } if (cls2Ptr->mixins.num != 0) { ckfree(clsPtr->mixins.list); } DUPLICATE(cls2Ptr->mixins, clsPtr->mixins, Class *); FOREACH(mixinPtr, cls2Ptr->mixins) { TclOOAddToMixinSubs(cls2Ptr, mixinPtr); } /* * Duplicate the source class's methods, constructor and destructor. */ FOREACH_HASH(keyPtr, mPtr, &clsPtr->classMethods) { if (CloneClassMethod(interp, cls2Ptr, mPtr, keyPtr, NULL) != TCL_OK) { Tcl_DeleteCommandFromToken(interp, o2Ptr->command); return NULL; } } if (clsPtr->constructorPtr) { if (CloneClassMethod(interp, cls2Ptr, clsPtr->constructorPtr, NULL, &cls2Ptr->constructorPtr) != TCL_OK) { Tcl_DeleteCommandFromToken(interp, o2Ptr->command); return NULL; } } if (clsPtr->destructorPtr) { if (CloneClassMethod(interp, cls2Ptr, clsPtr->destructorPtr, NULL, &cls2Ptr->destructorPtr) != TCL_OK) { Tcl_DeleteCommandFromToken(interp, o2Ptr->command); return NULL; } } /* * Duplicate the class's metadata. */ if (clsPtr->metadataPtr != NULL) { Tcl_ObjectMetadataType *metadataTypePtr; ClientData value, duplicate; FOREACH_HASH(metadataTypePtr, value, clsPtr->metadataPtr) { if (metadataTypePtr->cloneProc == NULL) { duplicate = value; } else { if (metadataTypePtr->cloneProc(interp, value, &duplicate) != TCL_OK) { Tcl_DeleteCommandFromToken(interp, o2Ptr->command); return NULL; } } if (duplicate != NULL) { Tcl_ClassSetMetadata((Tcl_Class) cls2Ptr, metadataTypePtr, duplicate); } } } } TclResetRewriteEnsemble(interp, 1); contextPtr = TclOOGetCallContext(o2Ptr, oPtr->fPtr->clonedName, 0, NULL); if (contextPtr) { args[0] = TclOOObjectName(interp, o2Ptr); args[1] = oPtr->fPtr->clonedName; args[2] = TclOOObjectName(interp, oPtr); Tcl_IncrRefCount(args[0]); Tcl_IncrRefCount(args[1]); Tcl_IncrRefCount(args[2]); result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr, 3, args); TclDecrRefCount(args[0]); TclDecrRefCount(args[1]); TclDecrRefCount(args[2]); TclOODeleteContext(contextPtr); if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (while performing post-copy callback)"); } if (result != TCL_OK) { Tcl_DeleteCommandFromToken(interp, o2Ptr->command); return NULL; } } return (Tcl_Object) o2Ptr; } /* * ---------------------------------------------------------------------- * * CloneObjectMethod, CloneClassMethod -- * * Helper functions used for cloning methods. They work identically to * each other, except for the difference between them in how they * register the cloned method on a successful clone. * * ---------------------------------------------------------------------- */ static int CloneObjectMethod( Tcl_Interp *interp, Object *oPtr, Method *mPtr, Tcl_Obj *namePtr) { if (mPtr->typePtr == NULL) { Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr, mPtr->flags & PUBLIC_METHOD, NULL, NULL); } else if (mPtr->typePtr->cloneProc) { ClientData newClientData; if (mPtr->typePtr->cloneProc(interp, mPtr->clientData, &newClientData) != TCL_OK) { return TCL_ERROR; } Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, newClientData); } else { Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, mPtr->clientData); } return TCL_OK; } static int CloneClassMethod( Tcl_Interp *interp, Class *clsPtr, Method *mPtr, Tcl_Obj *namePtr, Method **m2PtrPtr) { Method *m2Ptr; if (mPtr->typePtr == NULL) { m2Ptr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr, namePtr, mPtr->flags & PUBLIC_METHOD, NULL, NULL); } else if (mPtr->typePtr->cloneProc) { ClientData newClientData; if (mPtr->typePtr->cloneProc(interp, mPtr->clientData, &newClientData) != TCL_OK) { return TCL_ERROR; } m2Ptr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr, namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, newClientData); } else { m2Ptr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr, namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, mPtr->clientData); } if (m2PtrPtr != NULL) { *m2PtrPtr = m2Ptr; } return TCL_OK; } /* * ---------------------------------------------------------------------- * * Tcl_ClassGetMetadata, Tcl_ClassSetMetadata, Tcl_ObjectGetMetadata, * Tcl_ObjectSetMetadata -- * * Metadata management API. The metadata system allows code in extensions * to attach arbitrary non-NULL pointers to objects and classes without * the different things that might be interested being able to interfere * with each other. Apart from non-NULL-ness, these routines attach no * interpretation to the meaning of the metadata pointers. * * The Tcl_*GetMetadata routines get the metadata pointer attached that * has been related with a particular type, or NULL if no metadata * associated with the given type has been attached. * * The Tcl_*SetMetadata routines set or delete the metadata pointer that * is related to a particular type. The value associated with the type is * deleted (if present; no-op otherwise) if the value is NULL, and * attached (replacing the previous value, which is deleted if present) * otherwise. This means it is impossible to attach a NULL value for any * metadata type. * * ---------------------------------------------------------------------- */ ClientData Tcl_ClassGetMetadata( Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr) { Class *clsPtr = (Class *) clazz; Tcl_HashEntry *hPtr; /* * If there's no metadata store attached, the type in question has * definitely not been attached either! */ if (clsPtr->metadataPtr == NULL) { return NULL; } /* * There is a metadata store, so look in it for the given type. */ hPtr = Tcl_FindHashEntry(clsPtr->metadataPtr, (char *) typePtr); /* * Return the metadata value if we found it, otherwise NULL. */ if (hPtr == NULL) { return NULL; } return Tcl_GetHashValue(hPtr); } void Tcl_ClassSetMetadata( Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr, ClientData metadata) { Class *clsPtr = (Class *) clazz; Tcl_HashEntry *hPtr; int isNew; /* * Attach the metadata store if not done already. */ if (clsPtr->metadataPtr == NULL) { if (metadata == NULL) { return; } clsPtr->metadataPtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(clsPtr->metadataPtr, TCL_ONE_WORD_KEYS); } /* * If the metadata is NULL, we're deleting the metadata for the type. */ if (metadata == NULL) { hPtr = Tcl_FindHashEntry(clsPtr->metadataPtr, (char *) typePtr); if (hPtr != NULL) { typePtr->deleteProc(Tcl_GetHashValue(hPtr)); Tcl_DeleteHashEntry(hPtr); } return; } /* * Otherwise we're attaching the metadata. Note that if there was already * some metadata attached of this type, we delete that first. */ hPtr = Tcl_CreateHashEntry(clsPtr->metadataPtr, (char *) typePtr, &isNew); if (!isNew) { typePtr->deleteProc(Tcl_GetHashValue(hPtr)); } Tcl_SetHashValue(hPtr, metadata); } ClientData Tcl_ObjectGetMetadata( Tcl_Object object, const Tcl_ObjectMetadataType *typePtr) { Object *oPtr = (Object *) object; Tcl_HashEntry *hPtr; /* * If there's no metadata store attached, the type in question has * definitely not been attached either! */ if (oPtr->metadataPtr == NULL) { return NULL; } /* * There is a metadata store, so look in it for the given type. */ hPtr = Tcl_FindHashEntry(oPtr->metadataPtr, (char *) typePtr); /* * Return the metadata value if we found it, otherwise NULL. */ if (hPtr == NULL) { return NULL; } return Tcl_GetHashValue(hPtr); } void Tcl_ObjectSetMetadata( Tcl_Object object, const Tcl_ObjectMetadataType *typePtr, ClientData metadata) { Object *oPtr = (Object *) object; Tcl_HashEntry *hPtr; int isNew; /* * Attach the metadata store if not done already. */ if (oPtr->metadataPtr == NULL) { if (metadata == NULL) { return; } oPtr->metadataPtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(oPtr->metadataPtr, TCL_ONE_WORD_KEYS); } /* * If the metadata is NULL, we're deleting the metadata for the type. */ if (metadata == NULL) { hPtr = Tcl_FindHashEntry(oPtr->metadataPtr, (char *) typePtr); if (hPtr != NULL) { typePtr->deleteProc(Tcl_GetHashValue(hPtr)); Tcl_DeleteHashEntry(hPtr); } return; } /* * Otherwise we're attaching the metadata. Note that if there was already * some metadata attached of this type, we delete that first. */ hPtr = Tcl_CreateHashEntry(oPtr->metadataPtr, (char *) typePtr, &isNew); if (!isNew) { typePtr->deleteProc(Tcl_GetHashValue(hPtr)); } Tcl_SetHashValue(hPtr, metadata); } /* * ---------------------------------------------------------------------- * * PublicObjectCmd, PrivateObjectCmd, TclOOInvokeObject -- * * Main entry point for object invokations. The Public* and Private* * wrapper functions (implementations of both object instance commands * and [my]) are just thin wrappers round the main TclOOObjectCmdCore * function. Note that the core is function is NRE-aware. * * ---------------------------------------------------------------------- */ static int PublicObjectCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { return Tcl_NRCallObjProc(interp, PublicNRObjectCmd, clientData,objc,objv); } static int PublicNRObjectCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { return TclOOObjectCmdCore(clientData, interp, objc, objv, PUBLIC_METHOD, NULL); } static int PrivateObjectCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { return Tcl_NRCallObjProc(interp, PrivateNRObjectCmd,clientData,objc,objv); } static int PrivateNRObjectCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { return TclOOObjectCmdCore(clientData, interp, objc, objv, 0, NULL); } int TclOOInvokeObject( Tcl_Interp *interp, /* Interpreter for commands, variables, * results, error reporting, etc. */ Tcl_Object object, /* The object to invoke. */ Tcl_Class startCls, /* Where in the class chain to start the * invoke from, or NULL to traverse the whole * chain including filters. */ int publicPrivate, /* Whether this is an invoke from a public * context (PUBLIC_METHOD), a private context * (PRIVATE_METHOD), or a *really* private * context (any other value; conventionally * 0). */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* Array of argument objects. It is assumed * that the name of the method to invoke will * be at index 1. */ { switch (publicPrivate) { case PUBLIC_METHOD: return TclOOObjectCmdCore((Object *) object, interp, objc, objv, PUBLIC_METHOD, (Class *) startCls); case PRIVATE_METHOD: return TclOOObjectCmdCore((Object *) object, interp, objc, objv, PRIVATE_METHOD, (Class *) startCls); default: return TclOOObjectCmdCore((Object *) object, interp, objc, objv, 0, (Class *) startCls); } } /* * ---------------------------------------------------------------------- * * TclOOObjectCmdCore, FinalizeObjectCall -- * * Main function for object invokations. Does call chain creation, * management and invokation. The function FinalizeObjectCall exists to * clean up after the non-recursive processing of TclOOObjectCmdCore. * * ---------------------------------------------------------------------- */ int TclOOObjectCmdCore( Object *oPtr, /* The object being invoked. */ Tcl_Interp *interp, /* The interpreter containing the object. */ int objc, /* How many arguments are being passed in. */ Tcl_Obj *const *objv, /* The array of arguments. */ int flags, /* Whether this is an invokation through the * public or the private command interface. */ Class *startCls) /* Where to start in the call chain, or NULL * if we are to start at the front with * filters and the object's methods (which is * the normal case). */ { CallContext *contextPtr; Tcl_Obj *methodNamePtr; int result; /* * If we've no method name, throw this directly into the unknown * processing. */ if (objc < 2) { flags |= FORCE_UNKNOWN; methodNamePtr = NULL; goto noMapping; } /* * Give plugged in code a chance to remap the method name. */ methodNamePtr = objv[1]; if (oPtr->mapMethodNameProc != NULL) { register Class **startClsPtr = &startCls; Tcl_Obj *mappedMethodName = Tcl_DuplicateObj(methodNamePtr); result = oPtr->mapMethodNameProc(interp, (Tcl_Object) oPtr, (Tcl_Class *) startClsPtr, mappedMethodName); if (result != TCL_OK) { TclDecrRefCount(mappedMethodName); if (result == TCL_BREAK) { goto noMapping; } else if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (while mapping method name)"); } return result; } /* * Get the call chain for the remapped name. */ Tcl_IncrRefCount(mappedMethodName); contextPtr = TclOOGetCallContext(oPtr, mappedMethodName, flags | (oPtr->flags & FILTER_HANDLING), methodNamePtr); TclDecrRefCount(mappedMethodName); if (contextPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "impossible to invoke method \"%s\": no defined method or" " unknown method", TclGetString(methodNamePtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD_MAPPED", TclGetString(methodNamePtr), NULL); return TCL_ERROR; } } else { /* * Get the call chain. */ noMapping: contextPtr = TclOOGetCallContext(oPtr, methodNamePtr, flags | (oPtr->flags & FILTER_HANDLING), NULL); if (contextPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "impossible to invoke method \"%s\": no defined method or" " unknown method", TclGetString(methodNamePtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(methodNamePtr), NULL); return TCL_ERROR; } } /* * Check to see if we need to apply magical tricks to start part way * through the call chain. */ if (startCls != NULL) { for (; contextPtr->index < contextPtr->callPtr->numChain; contextPtr->index++) { register struct MInvoke *miPtr = &contextPtr->callPtr->chain[contextPtr->index]; if (miPtr->isFilter) { continue; } if (miPtr->mPtr->declaringClassPtr == startCls) { break; } } if (contextPtr->index >= contextPtr->callPtr->numChain) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "no valid method implementation", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(methodNamePtr), NULL); TclOODeleteContext(contextPtr); return TCL_ERROR; } } /* * Invoke the call chain, locking the object structure against deletion * for the duration. */ TclNRAddCallback(interp, FinalizeObjectCall, contextPtr, NULL,NULL,NULL); return TclOOInvokeContext(contextPtr, interp, objc, objv); } static int FinalizeObjectCall( ClientData data[], Tcl_Interp *interp, int result) { /* * Dispose of the call chain, which drops the lock on the object's * structure. */ TclOODeleteContext(data[0]); return result; } /* * ---------------------------------------------------------------------- * * Tcl_ObjectContextInvokeNext, TclNRObjectContextInvokeNext, FinalizeNext -- * * Invokes the next stage of the call chain described in an object * context. This is the core of the implementation of the [next] command. * Does not do management of the call-frame stack. Available in public * (standard API) and private (NRE-aware) forms. FinalizeNext is a * private function used to clean up in the NRE case. * * ---------------------------------------------------------------------- */ int Tcl_ObjectContextInvokeNext( Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv, int skip) { CallContext *contextPtr = (CallContext *) context; int savedIndex = contextPtr->index; int savedSkip = contextPtr->skip; int result; if (contextPtr->index+1 >= contextPtr->callPtr->numChain) { /* * We're at the end of the chain; generate an error message unless the * interpreter is being torn down, in which case we might be getting * here because of methods/destructors doing a [next] (or equivalent) * unexpectedly. */ const char *methodType; if (Tcl_InterpDeleted(interp)) { return TCL_OK; } if (contextPtr->callPtr->flags & CONSTRUCTOR) { methodType = "constructor"; } else if (contextPtr->callPtr->flags & DESTRUCTOR) { methodType = "destructor"; } else { methodType = "method"; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "no next %s implementation", methodType)); Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", NULL); return TCL_ERROR; } /* * Advance to the next method implementation in the chain in the method * call context while we process the body. However, need to adjust the * argument-skip control because we're guaranteed to have a single prefix * arg (i.e., 'next') and not the variable amount that can happen because * method invokations (i.e., '$obj meth' and 'my meth'), constructors * (i.e., '$cls new' and '$cls create obj') and destructors (no args at * all) come through the same code. */ contextPtr->index++; contextPtr->skip = skip; /* * Invoke the (advanced) method call context in the caller context. */ result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr, objc, objv); /* * Restore the call chain context index as we've finished the inner invoke * and want to operate in the outer context again. */ contextPtr->index = savedIndex; contextPtr->skip = savedSkip; return result; } int TclNRObjectContextInvokeNext( Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv, int skip) { register CallContext *contextPtr = (CallContext *) context; if (contextPtr->index+1 >= contextPtr->callPtr->numChain) { /* * We're at the end of the chain; generate an error message unless the * interpreter is being torn down, in which case we might be getting * here because of methods/destructors doing a [next] (or equivalent) * unexpectedly. */ const char *methodType; if (Tcl_InterpDeleted(interp)) { return TCL_OK; } if (contextPtr->callPtr->flags & CONSTRUCTOR) { methodType = "constructor"; } else if (contextPtr->callPtr->flags & DESTRUCTOR) { methodType = "destructor"; } else { methodType = "method"; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "no next %s implementation", methodType)); Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", NULL); return TCL_ERROR; } /* * Advance to the next method implementation in the chain in the method * call context while we process the body. However, need to adjust the * argument-skip control because we're guaranteed to have a single prefix * arg (i.e., 'next') and not the variable amount that can happen because * method invokations (i.e., '$obj meth' and 'my meth'), constructors * (i.e., '$cls new' and '$cls create obj') and destructors (no args at * all) come through the same code. */ TclNRAddCallback(interp, FinalizeNext, contextPtr, INT2PTR(contextPtr->index), INT2PTR(contextPtr->skip), NULL); contextPtr->index++; contextPtr->skip = skip; /* * Invoke the (advanced) method call context in the caller context. */ return TclOOInvokeContext(contextPtr, interp, objc, objv); } static int FinalizeNext( ClientData data[], Tcl_Interp *interp, int result) { CallContext *contextPtr = data[0]; /* * Restore the call chain context index as we've finished the inner invoke * and want to operate in the outer context again. */ contextPtr->index = PTR2INT(data[1]); contextPtr->skip = PTR2INT(data[2]); return result; } /* * ---------------------------------------------------------------------- * * Tcl_GetObjectFromObj -- * * Utility function to get an object from a Tcl_Obj containing its name. * * ---------------------------------------------------------------------- */ Tcl_Object Tcl_GetObjectFromObj( Tcl_Interp *interp, /* Interpreter in which to locate the object. * Will have an error message placed in it if * the name does not refer to an object. */ Tcl_Obj *objPtr) /* The name of the object to look up, which is * exactly the name of its public command. */ { Command *cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objPtr); if (cmdPtr == NULL) { goto notAnObject; } if (cmdPtr->objProc != PublicObjectCmd) { cmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr); if (cmdPtr == NULL || cmdPtr->objProc != PublicObjectCmd) { goto notAnObject; } } return cmdPtr->objClientData; notAnObject: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s does not refer to an object", TclGetString(objPtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "OBJECT", TclGetString(objPtr), NULL); return NULL; } /* * ---------------------------------------------------------------------- * * TclOOIsReachable -- * * Utility function that tests whether a class is a subclass (whether * directly or indirectly) of another class. * * ---------------------------------------------------------------------- */ int TclOOIsReachable( Class *targetPtr, Class *startPtr) { int i; Class *superPtr; tailRecurse: if (startPtr == targetPtr) { return 1; } if (startPtr->superclasses.num == 1 && startPtr->mixins.num == 0) { startPtr = startPtr->superclasses.list[0]; goto tailRecurse; } FOREACH(superPtr, startPtr->superclasses) { if (TclOOIsReachable(targetPtr, superPtr)) { return 1; } } FOREACH(superPtr, startPtr->mixins) { if (TclOOIsReachable(targetPtr, superPtr)) { return 1; } } return 0; } /* * ---------------------------------------------------------------------- * * TclOOObjectName, Tcl_GetObjectName -- * * Utility function that returns the name of the object. Note that this * simplifies cache management by keeping the code to do it in one place * and not sprayed all over. The value returned always has a reference * count of at least one. * * ---------------------------------------------------------------------- */ Tcl_Obj * TclOOObjectName( Tcl_Interp *interp, Object *oPtr) { Tcl_Obj *namePtr; if (oPtr->cachedNameObj) { return oPtr->cachedNameObj; } namePtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, oPtr->command, namePtr); Tcl_IncrRefCount(namePtr); oPtr->cachedNameObj = namePtr; return namePtr; } Tcl_Obj * Tcl_GetObjectName( Tcl_Interp *interp, Tcl_Object object) { return TclOOObjectName(interp, (Object *) object); } /* * ---------------------------------------------------------------------- * * assorted trivial 'getter' functions * * ---------------------------------------------------------------------- */ Tcl_Method Tcl_ObjectContextMethod( Tcl_ObjectContext context) { CallContext *contextPtr = (CallContext *) context; return (Tcl_Method) contextPtr->callPtr->chain[contextPtr->index].mPtr; } int Tcl_ObjectContextIsFiltering( Tcl_ObjectContext context) { CallContext *contextPtr = (CallContext *) context; return contextPtr->callPtr->chain[contextPtr->index].isFilter; } Tcl_Object Tcl_ObjectContextObject( Tcl_ObjectContext context) { return (Tcl_Object) ((CallContext *)context)->oPtr; } int Tcl_ObjectContextSkippedArgs( Tcl_ObjectContext context) { return ((CallContext *)context)->skip; } Tcl_Namespace * Tcl_GetObjectNamespace( Tcl_Object object) { return ((Object *)object)->namespacePtr; } Tcl_Command Tcl_GetObjectCommand( Tcl_Object object) { return ((Object *)object)->command; } Tcl_Class Tcl_GetObjectAsClass( Tcl_Object object) { return (Tcl_Class) ((Object *)object)->classPtr; } int Tcl_ObjectDeleted( Tcl_Object object) { return Deleted(object) ? 1 : 0; } Tcl_Object Tcl_GetClassAsObject( Tcl_Class clazz) { return (Tcl_Object) ((Class *)clazz)->thisPtr; } Tcl_ObjectMapMethodNameProc * Tcl_ObjectGetMethodNameMapper( Tcl_Object object) { return ((Object *) object)->mapMethodNameProc; } void Tcl_ObjectSetMethodNameMapper( Tcl_Object object, Tcl_ObjectMapMethodNameProc *mapMethodNameProc) { ((Object *) object)->mapMethodNameProc = mapMethodNameProc; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclDate.c0000644000175000017500000023124712663660065014740 0ustar sergeisergei/* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 1 /* Using locations. */ #define YYLSP_NEEDED 1 /* Substitute the variable and function names. */ #define yyparse TclDateparse #define yylex TclDatelex #define yyerror TclDateerror #define yylval TclDatelval #define yychar TclDatechar #define yydebug TclDatedebug #define yynerrs TclDatenerrs #define yylloc TclDatelloc /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { tAGO = 258, tDAY = 259, tDAYZONE = 260, tID = 261, tMERIDIAN = 262, tMONTH = 263, tMONTH_UNIT = 264, tSTARDATE = 265, tSEC_UNIT = 266, tSNUMBER = 267, tUNUMBER = 268, tZONE = 269, tEPOCH = 270, tDST = 271, tISOBASE = 272, tDAY_UNIT = 273, tNEXT = 274 }; #endif /* Tokens. */ #define tAGO 258 #define tDAY 259 #define tDAYZONE 260 #define tID 261 #define tMERIDIAN 262 #define tMONTH 263 #define tMONTH_UNIT 264 #define tSTARDATE 265 #define tSEC_UNIT 266 #define tSNUMBER 267 #define tUNUMBER 268 #define tZONE 269 #define tEPOCH 270 #define tDST 271 #define tISOBASE 272 #define tDAY_UNIT 273 #define tNEXT 274 /* Copy the first part of user declarations. */ /* * tclDate.c -- * * This file is generated from a yacc grammar defined in the file * tclGetDate.y. It should not be edited directly. * * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans. * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Bison generates several labels that happen to be unused. MS Visual C++ * doesn't like that, and complains. Tell it to shut up. */ #ifdef _MSC_VER #pragma warning( disable : 4102 ) #endif /* _MSC_VER */ /* * yyparse will accept a 'struct DateInfo' as its parameter; that's where the * parsed fields will be returned. */ typedef struct DateInfo { Tcl_Obj* messages; /* Error messages */ const char* separatrix; /* String separating messages */ time_t dateYear; time_t dateMonth; time_t dateDay; int dateHaveDate; time_t dateHour; time_t dateMinutes; time_t dateSeconds; int dateMeridian; int dateHaveTime; time_t dateTimezone; int dateDSTmode; int dateHaveZone; time_t dateRelMonth; time_t dateRelDay; time_t dateRelSeconds; int dateHaveRel; time_t dateMonthOrdinal; int dateHaveOrdinalMonth; time_t dateDayOrdinal; time_t dateDayNumber; int dateHaveDay; const char *dateStart; const char *dateInput; time_t *dateRelPointer; int dateDigitCount; } DateInfo; #define YYMALLOC ckalloc #define YYFREE(x) (ckfree((void*) (x))) #define yyDSTmode (info->dateDSTmode) #define yyDayOrdinal (info->dateDayOrdinal) #define yyDayNumber (info->dateDayNumber) #define yyMonthOrdinal (info->dateMonthOrdinal) #define yyHaveDate (info->dateHaveDate) #define yyHaveDay (info->dateHaveDay) #define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth) #define yyHaveRel (info->dateHaveRel) #define yyHaveTime (info->dateHaveTime) #define yyHaveZone (info->dateHaveZone) #define yyTimezone (info->dateTimezone) #define yyDay (info->dateDay) #define yyMonth (info->dateMonth) #define yyYear (info->dateYear) #define yyHour (info->dateHour) #define yyMinutes (info->dateMinutes) #define yySeconds (info->dateSeconds) #define yyMeridian (info->dateMeridian) #define yyRelMonth (info->dateRelMonth) #define yyRelDay (info->dateRelDay) #define yyRelSeconds (info->dateRelSeconds) #define yyRelPointer (info->dateRelPointer) #define yyInput (info->dateInput) #define yyDigitCount (info->dateDigitCount) #define EPOCH 1970 #define START_OF_TIME 1902 #define END_OF_TIME 2037 /* * The offset of tm_year of struct tm returned by localtime, gmtime, etc. * Posix requires 1900. */ #define TM_YEAR_BASE 1900 #define HOUR(x) ((int) (60 * x)) #define SECSPERDAY (24L * 60L * 60L) #define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) /* * An entry in the lexical lookup table. */ typedef struct _TABLE { const char *name; int type; time_t value; } TABLE; /* * Daylight-savings mode: on, off, or not yet known. */ typedef enum _DSTMODE { DSTon, DSToff, DSTmaybe } DSTMODE; /* * Meridian: am, pm, or 24-hour style. */ typedef enum _MERIDIAN { MERam, MERpm, MER24 } MERIDIAN; /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { time_t Number; enum _MERIDIAN Meridian; } /* Line 187 of yacc.c. */ YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED typedef struct YYLTYPE { int first_line; int first_column; int last_line; int last_column; } YYLTYPE; # define yyltype YYLTYPE /* obsolescent; will be withdrawn */ # define YYLTYPE_IS_DECLARED 1 # define YYLTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ /* * Prototypes of internal functions. */ static int LookupWord(YYSTYPE* yylvalPtr, char *buff); static void TclDateerror(YYLTYPE* location, DateInfo* info, const char *s); static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location, DateInfo* info); static time_t ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian); MODULE_SCOPE int yyparse(DateInfo*); /* Line 216 of yacc.c. */ #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int i) #else static int YYID (i) int i; #endif { return i; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss; YYSTYPE yyvs; YYLTYPE yyls; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 79 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 26 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 16 /* YYNRULES -- Number of rules. */ #define YYNRULES 56 /* YYNRULES -- Number of states. */ #define YYNSTATES 83 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 274 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 25, 22, 21, 24, 23, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 20, 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, 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, 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, 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, 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, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint8 yyprhs[] = { 0, 0, 3, 4, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 28, 33, 39, 46, 54, 57, 59, 61, 63, 66, 69, 73, 76, 80, 86, 88, 94, 100, 103, 108, 111, 113, 117, 120, 124, 128, 136, 139, 144, 147, 149, 153, 156, 159, 163, 165, 167, 169, 171, 173, 175, 177, 178 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 27, 0, -1, -1, 27, 28, -1, 29, -1, 30, -1, 32, -1, 33, -1, 31, -1, 36, -1, 34, -1, 35, -1, 40, -1, 13, 7, -1, 13, 20, 13, 41, -1, 13, 20, 13, 21, 13, -1, 13, 20, 13, 20, 13, 41, -1, 13, 20, 13, 20, 13, 21, 13, -1, 14, 16, -1, 14, -1, 5, -1, 4, -1, 4, 22, -1, 13, 4, -1, 38, 13, 4, -1, 19, 4, -1, 13, 23, 13, -1, 13, 23, 13, 23, 13, -1, 17, -1, 13, 21, 8, 21, 13, -1, 13, 21, 13, 21, 13, -1, 8, 13, -1, 8, 13, 22, 13, -1, 13, 8, -1, 15, -1, 13, 8, 13, -1, 19, 8, -1, 19, 13, 8, -1, 17, 14, 17, -1, 17, 14, 13, 20, 13, 20, 13, -1, 17, 17, -1, 10, 13, 24, 13, -1, 37, 3, -1, 37, -1, 38, 13, 39, -1, 13, 39, -1, 19, 39, -1, 19, 13, 39, -1, 39, -1, 21, -1, 25, -1, 11, -1, 18, -1, 9, -1, 13, -1, -1, 7, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 225, 225, 226, 229, 232, 235, 238, 241, 244, 247, 251, 256, 259, 265, 271, 279, 285, 296, 300, 304, 310, 314, 318, 322, 326, 332, 336, 341, 346, 351, 356, 360, 365, 369, 374, 381, 385, 391, 400, 409, 419, 433, 438, 441, 444, 447, 450, 453, 458, 461, 466, 470, 474, 480, 498, 501 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "tAGO", "tDAY", "tDAYZONE", "tID", "tMERIDIAN", "tMONTH", "tMONTH_UNIT", "tSTARDATE", "tSEC_UNIT", "tSNUMBER", "tUNUMBER", "tZONE", "tEPOCH", "tDST", "tISOBASE", "tDAY_UNIT", "tNEXT", "':'", "'-'", "','", "'/'", "'.'", "'+'", "$accept", "spec", "item", "time", "zone", "day", "date", "ordMonth", "iso", "trek", "relspec", "relunits", "sign", "unit", "number", "o_merid", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 58, 45, 44, 47, 46, 43 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 26, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 30, 30, 30, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 34, 34, 34, 35, 36, 36, 37, 37, 37, 37, 37, 38, 38, 39, 39, 39, 40, 41, 41 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 5, 6, 7, 2, 1, 1, 1, 2, 2, 3, 2, 3, 5, 1, 5, 5, 2, 4, 2, 1, 3, 2, 3, 3, 7, 2, 4, 2, 1, 3, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 0, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 2, 0, 1, 21, 20, 0, 53, 0, 51, 54, 19, 34, 28, 52, 0, 49, 50, 3, 4, 5, 8, 6, 7, 10, 11, 9, 43, 0, 48, 12, 22, 31, 0, 23, 13, 33, 0, 0, 0, 45, 18, 0, 40, 25, 36, 0, 46, 42, 0, 0, 0, 35, 55, 0, 0, 26, 0, 38, 37, 47, 24, 44, 32, 41, 56, 0, 0, 14, 0, 0, 0, 0, 55, 15, 29, 30, 27, 0, 0, 16, 0, 17, 39 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { -1, 1, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 67 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -22 static const yytype_int8 yypact[] = { -22, 2, -22, -21, -22, -4, -22, 1, -22, 22, 18, -22, 8, -22, 40, -22, -22, -22, -22, -22, -22, -22, -22, -22, -22, -22, 32, 28, -22, -22, -22, 24, 26, -22, -22, 42, 47, -5, 49, -22, -22, 15, -22, -22, -22, 48, -22, -22, 43, 50, 51, -22, 17, 44, 46, 45, 52, -22, -22, -22, -22, -22, -22, -22, -22, 56, 57, -22, 58, 60, 61, 62, -3, -22, -22, -22, -22, 59, 63, -22, 64, -22, -22 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -22, -22, -22, -22, -22, -22, -22, -22, -22, -22, -22, -22, -22, -9, -22, 6 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { 39, 30, 2, 53, 64, 46, 3, 4, 54, 31, 5, 6, 7, 8, 32, 9, 10, 11, 78, 12, 13, 14, 41, 15, 64, 42, 33, 16, 56, 34, 35, 6, 57, 8, 40, 47, 59, 65, 66, 61, 13, 48, 36, 37, 43, 38, 49, 60, 44, 6, 50, 8, 6, 45, 8, 51, 58, 6, 13, 8, 52, 13, 55, 62, 63, 68, 13, 69, 70, 72, 73, 74, 71, 75, 76, 77, 81, 82, 79, 80 }; static const yytype_uint8 yycheck[] = { 9, 22, 0, 8, 7, 14, 4, 5, 13, 13, 8, 9, 10, 11, 13, 13, 14, 15, 21, 17, 18, 19, 14, 21, 7, 17, 4, 25, 13, 7, 8, 9, 17, 11, 16, 3, 45, 20, 21, 48, 18, 13, 20, 21, 4, 23, 22, 4, 8, 9, 24, 11, 9, 13, 11, 13, 8, 9, 18, 11, 13, 18, 13, 13, 13, 21, 18, 21, 23, 13, 13, 13, 20, 13, 13, 13, 13, 13, 72, 20 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 27, 0, 4, 5, 8, 9, 10, 11, 13, 14, 15, 17, 18, 19, 21, 25, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 22, 13, 13, 4, 7, 8, 20, 21, 23, 39, 16, 14, 17, 4, 8, 13, 39, 3, 13, 22, 24, 13, 13, 8, 13, 13, 13, 17, 8, 39, 4, 39, 13, 13, 7, 20, 21, 41, 21, 21, 23, 20, 13, 13, 13, 13, 13, 13, 21, 41, 20, 13, 13 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (&yylloc, info, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) #else # define YYLEX yylex (&yylval, &yylloc, info) #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value, Location, info); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, info) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; YYLTYPE const * const yylocationp; DateInfo* info; #endif { if (!yyvaluep) return; YYUSE (yylocationp); YYUSE (info); # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, info) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; YYLTYPE const * const yylocationp; DateInfo* info; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); YY_LOCATION_PRINT (yyoutput, *yylocationp); YYFPRINTF (yyoutput, ": "); yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, info); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void yy_stack_print (bottom, top) yytype_int16 *bottom; yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); for (; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, DateInfo* info) #else static void yy_reduce_print (yyvsp, yylsp, yyrule, info) YYSTYPE *yyvsp; YYLTYPE *yylsp; int yyrule; DateInfo* info; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { fprintf (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) , &(yylsp[(yyi + 1) - (yynrhs)]) , info); fprintf (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, yylsp, Rule, info); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, DateInfo* info) #else static void yydestruct (yymsg, yytype, yyvaluep, yylocationp, info) const char *yymsg; int yytype; YYSTYPE *yyvaluep; YYLTYPE *yylocationp; DateInfo* info; #endif { YYUSE (yyvaluep); YYUSE (yylocationp); YYUSE (info); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (DateInfo* info); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (DateInfo* info) #else int yyparse (info) DateInfo* info; #endif #endif { /* The look-ahead symbol. */ int yychar; /* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /* Location data for the look-ahead symbol. */ YYLTYPE yylloc; int yystate; int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss = yyssa; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; YYSTYPE *yyvsp; /* The location stack. */ YYLTYPE yylsa[YYINITDEPTH]; YYLTYPE *yyls = yylsa; YYLTYPE *yylsp; /* The locations where the error started and ended. */ YYLTYPE yyerror_range[2]; #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; YYLTYPE yyloc; /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; yylsp = yyls; #if YYLTYPE_IS_TRIVIAL /* Initialize the default location before parsing starts. */ yylloc.first_line = yylloc.last_line = 1; yylloc.first_column = yylloc.last_column = 0; #endif goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; YYLTYPE *yyls1 = yyls; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yyls1, yysize * sizeof (*yylsp), &yystacksize); yyls = yyls1; yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); YYSTACK_RELOCATE (yyls); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; yylsp = yyls + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a look-ahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a look-ahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } if (yyn == YYFINAL) YYACCEPT; /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; *++yylsp = yylloc; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; /* Default location. */ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); YY_REDUCE_PRINT (yyn); switch (yyn) { case 4: { yyHaveTime++; ;} break; case 5: { yyHaveZone++; ;} break; case 6: { yyHaveDate++; ;} break; case 7: { yyHaveOrdinalMonth++; ;} break; case 8: { yyHaveDay++; ;} break; case 9: { yyHaveRel++; ;} break; case 10: { yyHaveTime++; yyHaveDate++; ;} break; case 11: { yyHaveTime++; yyHaveDate++; yyHaveRel++; ;} break; case 13: { yyHour = (yyvsp[(1) - (2)].Number); yyMinutes = 0; yySeconds = 0; yyMeridian = (yyvsp[(2) - (2)].Meridian); ;} break; case 14: { yyHour = (yyvsp[(1) - (4)].Number); yyMinutes = (yyvsp[(3) - (4)].Number); yySeconds = 0; yyMeridian = (yyvsp[(4) - (4)].Meridian); ;} break; case 15: { yyHour = (yyvsp[(1) - (5)].Number); yyMinutes = (yyvsp[(3) - (5)].Number); yyMeridian = MER24; yyDSTmode = DSToff; yyTimezone = ((yyvsp[(5) - (5)].Number) % 100 + ((yyvsp[(5) - (5)].Number) / 100) * 60); ++yyHaveZone; ;} break; case 16: { yyHour = (yyvsp[(1) - (6)].Number); yyMinutes = (yyvsp[(3) - (6)].Number); yySeconds = (yyvsp[(5) - (6)].Number); yyMeridian = (yyvsp[(6) - (6)].Meridian); ;} break; case 17: { yyHour = (yyvsp[(1) - (7)].Number); yyMinutes = (yyvsp[(3) - (7)].Number); yySeconds = (yyvsp[(5) - (7)].Number); yyMeridian = MER24; yyDSTmode = DSToff; yyTimezone = ((yyvsp[(7) - (7)].Number) % 100 + ((yyvsp[(7) - (7)].Number) / 100) * 60); ++yyHaveZone; ;} break; case 18: { yyTimezone = (yyvsp[(1) - (2)].Number); yyDSTmode = DSTon; ;} break; case 19: { yyTimezone = (yyvsp[(1) - (1)].Number); yyDSTmode = DSToff; ;} break; case 20: { yyTimezone = (yyvsp[(1) - (1)].Number); yyDSTmode = DSTon; ;} break; case 21: { yyDayOrdinal = 1; yyDayNumber = (yyvsp[(1) - (1)].Number); ;} break; case 22: { yyDayOrdinal = 1; yyDayNumber = (yyvsp[(1) - (2)].Number); ;} break; case 23: { yyDayOrdinal = (yyvsp[(1) - (2)].Number); yyDayNumber = (yyvsp[(2) - (2)].Number); ;} break; case 24: { yyDayOrdinal = (yyvsp[(1) - (3)].Number) * (yyvsp[(2) - (3)].Number); yyDayNumber = (yyvsp[(3) - (3)].Number); ;} break; case 25: { yyDayOrdinal = 2; yyDayNumber = (yyvsp[(2) - (2)].Number); ;} break; case 26: { yyMonth = (yyvsp[(1) - (3)].Number); yyDay = (yyvsp[(3) - (3)].Number); ;} break; case 27: { yyMonth = (yyvsp[(1) - (5)].Number); yyDay = (yyvsp[(3) - (5)].Number); yyYear = (yyvsp[(5) - (5)].Number); ;} break; case 28: { yyYear = (yyvsp[(1) - (1)].Number) / 10000; yyMonth = ((yyvsp[(1) - (1)].Number) % 10000)/100; yyDay = (yyvsp[(1) - (1)].Number) % 100; ;} break; case 29: { yyDay = (yyvsp[(1) - (5)].Number); yyMonth = (yyvsp[(3) - (5)].Number); yyYear = (yyvsp[(5) - (5)].Number); ;} break; case 30: { yyMonth = (yyvsp[(3) - (5)].Number); yyDay = (yyvsp[(5) - (5)].Number); yyYear = (yyvsp[(1) - (5)].Number); ;} break; case 31: { yyMonth = (yyvsp[(1) - (2)].Number); yyDay = (yyvsp[(2) - (2)].Number); ;} break; case 32: { yyMonth = (yyvsp[(1) - (4)].Number); yyDay = (yyvsp[(2) - (4)].Number); yyYear = (yyvsp[(4) - (4)].Number); ;} break; case 33: { yyMonth = (yyvsp[(2) - (2)].Number); yyDay = (yyvsp[(1) - (2)].Number); ;} break; case 34: { yyMonth = 1; yyDay = 1; yyYear = EPOCH; ;} break; case 35: { yyMonth = (yyvsp[(2) - (3)].Number); yyDay = (yyvsp[(1) - (3)].Number); yyYear = (yyvsp[(3) - (3)].Number); ;} break; case 36: { yyMonthOrdinal = 1; yyMonth = (yyvsp[(2) - (2)].Number); ;} break; case 37: { yyMonthOrdinal = (yyvsp[(2) - (3)].Number); yyMonth = (yyvsp[(3) - (3)].Number); ;} break; case 38: { if ((yyvsp[(2) - (3)].Number) != HOUR( 7)) YYABORT; yyYear = (yyvsp[(1) - (3)].Number) / 10000; yyMonth = ((yyvsp[(1) - (3)].Number) % 10000)/100; yyDay = (yyvsp[(1) - (3)].Number) % 100; yyHour = (yyvsp[(3) - (3)].Number) / 10000; yyMinutes = ((yyvsp[(3) - (3)].Number) % 10000)/100; yySeconds = (yyvsp[(3) - (3)].Number) % 100; ;} break; case 39: { if ((yyvsp[(2) - (7)].Number) != HOUR( 7)) YYABORT; yyYear = (yyvsp[(1) - (7)].Number) / 10000; yyMonth = ((yyvsp[(1) - (7)].Number) % 10000)/100; yyDay = (yyvsp[(1) - (7)].Number) % 100; yyHour = (yyvsp[(3) - (7)].Number); yyMinutes = (yyvsp[(5) - (7)].Number); yySeconds = (yyvsp[(7) - (7)].Number); ;} break; case 40: { yyYear = (yyvsp[(1) - (2)].Number) / 10000; yyMonth = ((yyvsp[(1) - (2)].Number) % 10000)/100; yyDay = (yyvsp[(1) - (2)].Number) % 100; yyHour = (yyvsp[(2) - (2)].Number) / 10000; yyMinutes = ((yyvsp[(2) - (2)].Number) % 10000)/100; yySeconds = (yyvsp[(2) - (2)].Number) % 100; ;} break; case 41: { /* * Offset computed year by -377 so that the returned years will be * in a range accessible with a 32 bit clock seconds value. */ yyYear = (yyvsp[(2) - (4)].Number)/1000 + 2323 - 377; yyDay = 1; yyMonth = 1; yyRelDay += (((yyvsp[(2) - (4)].Number)%1000)*(365 + IsLeapYear(yyYear)))/1000; yyRelSeconds += (yyvsp[(4) - (4)].Number) * 144 * 60; ;} break; case 42: { yyRelSeconds *= -1; yyRelMonth *= -1; yyRelDay *= -1; ;} break; case 44: { *yyRelPointer += (yyvsp[(1) - (3)].Number) * (yyvsp[(2) - (3)].Number) * (yyvsp[(3) - (3)].Number); ;} break; case 45: { *yyRelPointer += (yyvsp[(1) - (2)].Number) * (yyvsp[(2) - (2)].Number); ;} break; case 46: { *yyRelPointer += (yyvsp[(2) - (2)].Number); ;} break; case 47: { *yyRelPointer += (yyvsp[(2) - (3)].Number) * (yyvsp[(3) - (3)].Number); ;} break; case 48: { *yyRelPointer += (yyvsp[(1) - (1)].Number); ;} break; case 49: { (yyval.Number) = -1; ;} break; case 50: { (yyval.Number) = 1; ;} break; case 51: { (yyval.Number) = (yyvsp[(1) - (1)].Number); yyRelPointer = &yyRelSeconds; ;} break; case 52: { (yyval.Number) = (yyvsp[(1) - (1)].Number); yyRelPointer = &yyRelDay; ;} break; case 53: { (yyval.Number) = (yyvsp[(1) - (1)].Number); yyRelPointer = &yyRelMonth; ;} break; case 54: { if (yyHaveTime && yyHaveDate && !yyHaveRel) { yyYear = (yyvsp[(1) - (1)].Number); } else { yyHaveTime++; if (yyDigitCount <= 2) { yyHour = (yyvsp[(1) - (1)].Number); yyMinutes = 0; } else { yyHour = (yyvsp[(1) - (1)].Number) / 100; yyMinutes = (yyvsp[(1) - (1)].Number) % 100; } yySeconds = 0; yyMeridian = MER24; } ;} break; case 55: { (yyval.Meridian) = MER24; ;} break; case 56: { (yyval.Meridian) = (yyvsp[(1) - (1)].Meridian); ;} break; /* Line 1267 of yacc.c. */ default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; *++yylsp = yyloc; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (&yylloc, info, YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (&yylloc, info, yymsg); } else { yyerror (&yylloc, info, YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } yyerror_range[0] = yylloc; if (yyerrstatus == 3) { /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval, &yylloc, info); yychar = YYEMPTY; } } /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; yyerror_range[0] = yylsp[1-yylen]; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yyerror_range[0] = *yylsp; yydestruct ("Error: popping", yystos[yystate], yyvsp, yylsp, info); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; *++yyvsp = yylval; yyerror_range[1] = yylloc; /* Using YYLLOC is tempting, but would change the location of the look-ahead. YYLOC is available though. */ YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); *++yylsp = yyloc; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (&yylloc, info, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEOF && yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc, info); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp, yylsp, info); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } /* * Month and day table. */ static const TABLE MonthDayTable[] = { { "january", tMONTH, 1 }, { "february", tMONTH, 2 }, { "march", tMONTH, 3 }, { "april", tMONTH, 4 }, { "may", tMONTH, 5 }, { "june", tMONTH, 6 }, { "july", tMONTH, 7 }, { "august", tMONTH, 8 }, { "september", tMONTH, 9 }, { "sept", tMONTH, 9 }, { "october", tMONTH, 10 }, { "november", tMONTH, 11 }, { "december", tMONTH, 12 }, { "sunday", tDAY, 0 }, { "monday", tDAY, 1 }, { "tuesday", tDAY, 2 }, { "tues", tDAY, 2 }, { "wednesday", tDAY, 3 }, { "wednes", tDAY, 3 }, { "thursday", tDAY, 4 }, { "thur", tDAY, 4 }, { "thurs", tDAY, 4 }, { "friday", tDAY, 5 }, { "saturday", tDAY, 6 }, { NULL, 0, 0 } }; /* * Time units table. */ static const TABLE UnitsTable[] = { { "year", tMONTH_UNIT, 12 }, { "month", tMONTH_UNIT, 1 }, { "fortnight", tDAY_UNIT, 14 }, { "week", tDAY_UNIT, 7 }, { "day", tDAY_UNIT, 1 }, { "hour", tSEC_UNIT, 60 * 60 }, { "minute", tSEC_UNIT, 60 }, { "min", tSEC_UNIT, 60 }, { "second", tSEC_UNIT, 1 }, { "sec", tSEC_UNIT, 1 }, { NULL, 0, 0 } }; /* * Assorted relative-time words. */ static const TABLE OtherTable[] = { { "tomorrow", tDAY_UNIT, 1 }, { "yesterday", tDAY_UNIT, -1 }, { "today", tDAY_UNIT, 0 }, { "now", tSEC_UNIT, 0 }, { "last", tUNUMBER, -1 }, { "this", tSEC_UNIT, 0 }, { "next", tNEXT, 1 }, #if 0 { "first", tUNUMBER, 1 }, { "second", tUNUMBER, 2 }, { "third", tUNUMBER, 3 }, { "fourth", tUNUMBER, 4 }, { "fifth", tUNUMBER, 5 }, { "sixth", tUNUMBER, 6 }, { "seventh", tUNUMBER, 7 }, { "eighth", tUNUMBER, 8 }, { "ninth", tUNUMBER, 9 }, { "tenth", tUNUMBER, 10 }, { "eleventh", tUNUMBER, 11 }, { "twelfth", tUNUMBER, 12 }, #endif { "ago", tAGO, 1 }, { "epoch", tEPOCH, 0 }, { "stardate", tSTARDATE, 0 }, { NULL, 0, 0 } }; /* * The timezone table. (Note: This table was modified to not use any floating * point constants to work around an SGI compiler bug). */ static const TABLE TimezoneTable[] = { { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */ { "utc", tZONE, HOUR( 0) }, { "uct", tZONE, HOUR( 0) }, /* Universal Coordinated Time */ { "wet", tZONE, HOUR( 0) }, /* Western European */ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */ { "wat", tZONE, HOUR( 1) }, /* West Africa */ { "at", tZONE, HOUR( 2) }, /* Azores */ #if 0 /* For completeness. BST is also British Summer, and GST is * also Guam Standard. */ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */ #endif { "nft", tZONE, HOUR( 7/2) }, /* Newfoundland */ { "nst", tZONE, HOUR( 7/2) }, /* Newfoundland Standard */ { "ndt", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */ { "cst", tZONE, HOUR( 6) }, /* Central Standard */ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */ { "cat", tZONE, HOUR(10) }, /* Central Alaska */ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */ { "nt", tZONE, HOUR(11) }, /* Nome */ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */ { "cet", tZONE, -HOUR( 1) }, /* Central European */ { "cest", tDAYZONE, -HOUR( 1) }, /* Central European Summer */ { "met", tZONE, -HOUR( 1) }, /* Middle European */ { "mewt", tZONE, -HOUR( 1) }, /* Middle European Winter */ { "mest", tDAYZONE, -HOUR( 1) }, /* Middle European Summer */ { "swt", tZONE, -HOUR( 1) }, /* Swedish Winter */ { "sst", tDAYZONE, -HOUR( 1) }, /* Swedish Summer */ { "fwt", tZONE, -HOUR( 1) }, /* French Winter */ { "fst", tDAYZONE, -HOUR( 1) }, /* French Summer */ { "eet", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */ { "bt", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */ { "it", tZONE, -HOUR( 7/2) }, /* Iran */ { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */ { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */ { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */ { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */ #if 0 /* For completeness. NST is also Newfoundland Stanard, nad SST is * also Swedish Summer. */ { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */ { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */ #endif /* 0 */ { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */ { "wadt", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */ { "jt", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */ { "cct", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */ { "jst", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */ { "jdt", tDAYZONE, -HOUR( 9) }, /* Japan Daylight */ { "kst", tZONE, -HOUR( 9) }, /* Korea Standard */ { "kdt", tDAYZONE, -HOUR( 9) }, /* Korea Daylight */ { "cast", tZONE, -HOUR(19/2) }, /* Central Australian Standard */ { "cadt", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */ { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */ { "nzt", tZONE, -HOUR(12) }, /* New Zealand */ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */ { "idle", tZONE, -HOUR(12) }, /* International Date Line East */ /* ADDED BY Marco Nijdam */ { "dst", tDST, HOUR( 0) }, /* DST on (hour is ignored) */ /* End ADDED */ { NULL, 0, 0 } }; /* * Military timezone table. */ static const TABLE MilitaryTable[] = { { "a", tZONE, -HOUR( 1) }, { "b", tZONE, -HOUR( 2) }, { "c", tZONE, -HOUR( 3) }, { "d", tZONE, -HOUR( 4) }, { "e", tZONE, -HOUR( 5) }, { "f", tZONE, -HOUR( 6) }, { "g", tZONE, -HOUR( 7) }, { "h", tZONE, -HOUR( 8) }, { "i", tZONE, -HOUR( 9) }, { "k", tZONE, -HOUR(10) }, { "l", tZONE, -HOUR(11) }, { "m", tZONE, -HOUR(12) }, { "n", tZONE, HOUR( 1) }, { "o", tZONE, HOUR( 2) }, { "p", tZONE, HOUR( 3) }, { "q", tZONE, HOUR( 4) }, { "r", tZONE, HOUR( 5) }, { "s", tZONE, HOUR( 6) }, { "t", tZONE, HOUR( 7) }, { "u", tZONE, HOUR( 8) }, { "v", tZONE, HOUR( 9) }, { "w", tZONE, HOUR( 10) }, { "x", tZONE, HOUR( 11) }, { "y", tZONE, HOUR( 12) }, { "z", tZONE, HOUR( 0) }, { NULL, 0, 0 } }; /* * Dump error messages in the bit bucket. */ static void TclDateerror( YYLTYPE* location, DateInfo* infoPtr, const char *s) { Tcl_Obj* t; Tcl_AppendToObj(infoPtr->messages, infoPtr->separatrix, -1); Tcl_AppendToObj(infoPtr->messages, s, -1); Tcl_AppendToObj(infoPtr->messages, " (characters ", -1); t = Tcl_NewIntObj(location->first_column); Tcl_IncrRefCount(t); Tcl_AppendObjToObj(infoPtr->messages, t); Tcl_DecrRefCount(t); Tcl_AppendToObj(infoPtr->messages, "-", -1); t = Tcl_NewIntObj(location->last_column); Tcl_IncrRefCount(t); Tcl_AppendObjToObj(infoPtr->messages, t); Tcl_DecrRefCount(t); Tcl_AppendToObj(infoPtr->messages, ")", -1); infoPtr->separatrix = "\n"; } static time_t ToSeconds( time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian) { if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) { return -1; } switch (Meridian) { case MER24: if (Hours < 0 || Hours > 23) { return -1; } return (Hours * 60L + Minutes) * 60L + Seconds; case MERam: if (Hours < 1 || Hours > 12) { return -1; } return ((Hours % 12) * 60L + Minutes) * 60L + Seconds; case MERpm: if (Hours < 1 || Hours > 12) { return -1; } return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds; } return -1; /* Should never be reached */ } static int LookupWord( YYSTYPE* yylvalPtr, char *buff) { register char *p; register char *q; register const TABLE *tp; int i, abbrev; /* * Make it lowercase. */ Tcl_UtfToLower(buff); if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) { yylvalPtr->Meridian = MERam; return tMERIDIAN; } if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) { yylvalPtr->Meridian = MERpm; return tMERIDIAN; } /* * See if we have an abbreviation for a month. */ if (strlen(buff) == 3) { abbrev = 1; } else if (strlen(buff) == 4 && buff[3] == '.') { abbrev = 1; buff[3] = '\0'; } else { abbrev = 0; } for (tp = MonthDayTable; tp->name; tp++) { if (abbrev) { if (strncmp(buff, tp->name, 3) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } else if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } for (tp = TimezoneTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } for (tp = UnitsTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } /* * Strip off any plural and try the units table again. */ i = strlen(buff) - 1; if (i > 0 && buff[i] == 's') { buff[i] = '\0'; for (tp = UnitsTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } } for (tp = OtherTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } /* * Military timezones. */ if (buff[1] == '\0' && !(*buff & 0x80) && isalpha(UCHAR(*buff))) { /* INTL: ISO only */ for (tp = MilitaryTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } } /* * Drop out any periods and try the timezone table again. */ for (i = 0, p = q = buff; *q; q++) { if (*q != '.') { *p++ = *q; } else { i++; } } *p = '\0'; if (i) { for (tp = TimezoneTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } } return tID; } static int TclDatelex( YYSTYPE* yylvalPtr, YYLTYPE* location, DateInfo *info) { register char c; register char *p; char buff[20]; int Count; location->first_column = yyInput - info->dateStart; for ( ; ; ) { while (TclIsSpaceProc(*yyInput)) { yyInput++; } if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */ /* * Convert the string into a number; count the number of digits. */ Count = 0; for (yylvalPtr->Number = 0; isdigit(UCHAR(c = *yyInput++)); ) { /* INTL: digit */ yylvalPtr->Number = 10 * yylvalPtr->Number + c - '0'; Count++; } yyInput--; yyDigitCount = Count; /* * A number with 6 or more digits is considered an ISO 8601 base. */ if (Count >= 6) { location->last_column = yyInput - info->dateStart - 1; return tISOBASE; } else { location->last_column = yyInput - info->dateStart - 1; return tUNUMBER; } } if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */ for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */ || c == '.'; ) { if (p < &buff[sizeof buff - 1]) { *p++ = c; } } *p = '\0'; yyInput--; location->last_column = yyInput - info->dateStart - 1; return LookupWord(yylvalPtr, buff); } if (c != '(') { location->last_column = yyInput - info->dateStart; return *yyInput++; } Count = 0; do { c = *yyInput++; if (c == '\0') { location->last_column = yyInput - info->dateStart - 1; return c; } else if (c == '(') { Count++; } else if (c == ')') { Count--; } } while (Count > 0); } } int TclClockOldscanObjCmd( ClientData clientData, /* Unused */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Count of paraneters */ Tcl_Obj *const *objv) /* Parameters */ { Tcl_Obj *result, *resultElement; int yr, mo, da; DateInfo dateInfo; DateInfo* info = &dateInfo; int status; if (objc != 5) { Tcl_WrongNumArgs(interp, 1, objv, "stringToParse baseYear baseMonth baseDay" ); return TCL_ERROR; } yyInput = Tcl_GetString( objv[1] ); dateInfo.dateStart = yyInput; yyHaveDate = 0; if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK || Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK || Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) { return TCL_ERROR; } yyYear = yr; yyMonth = mo; yyDay = da; yyHaveTime = 0; yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24; yyHaveZone = 0; yyTimezone = 0; yyDSTmode = DSTmaybe; yyHaveOrdinalMonth = 0; yyMonthOrdinal = 0; yyHaveDay = 0; yyDayOrdinal = 0; yyDayNumber = 0; yyHaveRel = 0; yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL; dateInfo.messages = Tcl_NewObj(); dateInfo.separatrix = ""; Tcl_IncrRefCount(dateInfo.messages); status = yyparse(&dateInfo); if (status == 1) { Tcl_SetObjResult(interp, dateInfo.messages); Tcl_DecrRefCount(dateInfo.messages); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL); return TCL_ERROR; } else if (status == 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1)); Tcl_DecrRefCount(dateInfo.messages); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); return TCL_ERROR; } else if (status != 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj("Unknown status returned " "from date parser. Please " "report this error as a " "bug in Tcl.", -1)); Tcl_DecrRefCount(dateInfo.messages); Tcl_SetErrorCode(interp, "TCL", "BUG", NULL); return TCL_ERROR; } Tcl_DecrRefCount(dateInfo.messages); if (yyHaveDate > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj("more than one date in string", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); return TCL_ERROR; } if (yyHaveTime > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj("more than one time of day in string", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); return TCL_ERROR; } if (yyHaveZone > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj("more than one time zone in string", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); return TCL_ERROR; } if (yyHaveDay > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj("more than one weekday in string", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); return TCL_ERROR; } if (yyHaveOrdinalMonth > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj("more than one ordinal month in string", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); return TCL_ERROR; } result = Tcl_NewObj(); resultElement = Tcl_NewObj(); if (yyHaveDate) { Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyYear)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyMonth)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyDay)); } Tcl_ListObjAppendElement(interp, result, resultElement); if (yyHaveTime) { Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj((int) ToSeconds(yyHour, yyMinutes, yySeconds, yyMeridian))); } else { Tcl_ListObjAppendElement(interp, result, Tcl_NewObj()); } resultElement = Tcl_NewObj(); if (yyHaveZone) { Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) -yyTimezone)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj(1 - yyDSTmode)); } Tcl_ListObjAppendElement(interp, result, resultElement); resultElement = Tcl_NewObj(); if (yyHaveRel) { Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyRelMonth)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyRelDay)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyRelSeconds)); } Tcl_ListObjAppendElement(interp, result, resultElement); resultElement = Tcl_NewObj(); if (yyHaveDay && !yyHaveDate) { Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyDayOrdinal)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyDayNumber)); } Tcl_ListObjAppendElement(interp, result, resultElement); resultElement = Tcl_NewObj(); if (yyHaveOrdinalMonth) { Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyMonthOrdinal)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyMonth)); } Tcl_ListObjAppendElement(interp, result, resultElement); Tcl_SetObjResult(interp, result); return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tommath.h0000644000175000017500000000003312663653132015016 0ustar sergeisergei#include "tclTomMathInt.h" tcl8.6.5/generic/tclOOStubLib.c0000644000175000017500000000337412663660065015663 0ustar sergeisergei/* * ORIGINAL SOURCE: tk/generic/tkStubLib.c, version 1.9 2004/03/17 */ #include "tclOOInt.h" MODULE_SCOPE const TclOOStubs *tclOOStubsPtr; MODULE_SCOPE const TclOOIntStubs *tclOOIntStubsPtr; const TclOOStubs *tclOOStubsPtr = NULL; const TclOOIntStubs *tclOOIntStubsPtr = NULL; /* *---------------------------------------------------------------------- * * TclOOInitializeStubs -- * Load the tclOO package, initialize stub table pointer. Do not call * this function directly, use Tcl_OOInitStubs() macro instead. * * Results: * The actual version of the package that satisfies the request, or NULL * to indicate that an error occurred. * * Side effects: * Sets the stub table pointers. * *---------------------------------------------------------------------- */ #undef TclOOInitializeStubs MODULE_SCOPE const char * TclOOInitializeStubs( Tcl_Interp *interp, const char *version) { int exact = 0; const char *packageName = "TclOO"; const char *errMsg = NULL; TclOOStubs *stubsPtr = NULL; const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, exact, &stubsPtr); if (actualVersion == NULL) { return NULL; } if (stubsPtr == NULL) { errMsg = "missing stub table pointer"; } else { tclOOStubsPtr = stubsPtr; if (stubsPtr->hooks) { tclOOIntStubsPtr = stubsPtr->hooks->tclOOIntStubs; } else { tclOOIntStubsPtr = NULL; } return actualVersion; } tclStubsPtr->tcl_ResetResult(interp); tclStubsPtr->tcl_AppendResult(interp, "Error loading ", packageName, " (requested version ", version, ", actual version ", actualVersion, "): ", errMsg, NULL); return NULL; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclEnv.c0000644000175000017500000004726212663660065014615 0ustar sergeisergei/* * tclEnv.c -- * * Tcl support for environment variables, including a setenv function. * This file contains the generic portion of the environment module. It * is primarily responsible for keeping the "env" arrays in sync with the * system environment variables. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" TCL_DECLARE_MUTEX(envMutex) /* To serialize access to environ. */ static struct { int cacheSize; /* Number of env strings in cache. */ char **cache; /* Array containing all of the environment * strings that Tcl has allocated. */ #ifndef USE_PUTENV char **ourEnviron; /* Cache of the array that we allocate. We * need to track this in case another * subsystem swaps around the environ array * like we do. */ int ourEnvironSize; /* Non-zero means that the environ array was * malloced and has this many total entries * allocated to it (not all may be in use at * once). Zero means that the environment * array is in its original static state. */ #endif } env; /* * Declarations for local functions defined in this file: */ static char * EnvTraceProc(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); static void ReplaceString(const char *oldStr, char *newStr); MODULE_SCOPE void TclSetEnv(const char *name, const char *value); MODULE_SCOPE void TclUnsetEnv(const char *name); /* *---------------------------------------------------------------------- * * TclSetupEnv -- * * This function is invoked for an interpreter to make environment * variables accessible from that interpreter via the "env" associative * array. * * Results: * None. * * Side effects: * The interpreter is added to a list of interpreters managed by us, so * that its view of envariables can be kept consistent with the view in * other interpreters. If this is the first call to TclSetupEnv, then * additional initialization happens, such as copying the environment to * dynamically-allocated space for ease of management. * *---------------------------------------------------------------------- */ void TclSetupEnv( Tcl_Interp *interp) /* Interpreter whose "env" array is to be * managed. */ { Var *varPtr, *arrayPtr; Tcl_Obj *varNamePtr; Tcl_DString envString; Tcl_HashTable namesHash; Tcl_HashEntry *hPtr; Tcl_HashSearch search; /* * Synchronize the values in the environ array with the contents of the * Tcl "env" variable. To do this: * 1) Remove the trace that fires when the "env" var is updated. * 2) Find the existing contents of the "env", storing in a hash table. * 3) Create/update elements for each environ variable, removing * elements from the hash table as we go. * 4) Remove the elements for each remaining entry in the hash table, * which must have existed before yet have no analog in the environ * variable. * 5) Add a trace that synchronizes the "env" array. */ Tcl_UntraceVar2(interp, "env", NULL, TCL_GLOBAL_ONLY | TCL_TRACE_WRITES | TCL_TRACE_UNSETS | TCL_TRACE_READS | TCL_TRACE_ARRAY, EnvTraceProc, NULL); /* * Find out what elements are currently in the global env array. */ TclNewLiteralStringObj(varNamePtr, "env"); Tcl_IncrRefCount(varNamePtr); Tcl_InitObjHashTable(&namesHash); varPtr = TclObjLookupVarEx(interp, varNamePtr, NULL, TCL_GLOBAL_ONLY, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); TclFindArrayPtrElements(varPtr, &namesHash); /* * Go through the environment array and transfer its values into Tcl. At * the same time, remove those elements we add/update from the hash table * of existing elements, so that after this part processes, that table * will hold just the parts to remove. */ if (environ[0] != NULL) { int i; Tcl_MutexLock(&envMutex); for (i = 0; environ[i] != NULL; i++) { Tcl_Obj *obj1, *obj2; char *p1, *p2; p1 = Tcl_ExternalToUtfDString(NULL, environ[i], -1, &envString); p2 = strchr(p1, '='); if (p2 == NULL) { /* * This condition seem to happen occasionally under some * versions of Solaris, or when encoding accidents swallow the * '='; ignore the entry. */ continue; } p2++; p2[-1] = '\0'; obj1 = Tcl_NewStringObj(p1, -1); obj2 = Tcl_NewStringObj(p2, -1); Tcl_DStringFree(&envString); Tcl_IncrRefCount(obj1); Tcl_IncrRefCount(obj2); Tcl_ObjSetVar2(interp, varNamePtr, obj1, obj2, TCL_GLOBAL_ONLY); hPtr = Tcl_FindHashEntry(&namesHash, obj1); if (hPtr != NULL) { Tcl_DeleteHashEntry(hPtr); } Tcl_DecrRefCount(obj1); Tcl_DecrRefCount(obj2); } Tcl_MutexUnlock(&envMutex); } /* * Delete those elements that existed in the array but which had no * counterparts in the environment array. */ for (hPtr=Tcl_FirstHashEntry(&namesHash, &search); hPtr!=NULL; hPtr=Tcl_NextHashEntry(&search)) { Tcl_Obj *elemName = Tcl_GetHashValue(hPtr); TclObjUnsetVar2(interp, varNamePtr, elemName, TCL_GLOBAL_ONLY); } Tcl_DeleteHashTable(&namesHash); Tcl_DecrRefCount(varNamePtr); /* * Re-establish the trace. */ Tcl_TraceVar2(interp, "env", NULL, TCL_GLOBAL_ONLY | TCL_TRACE_WRITES | TCL_TRACE_UNSETS | TCL_TRACE_READS | TCL_TRACE_ARRAY, EnvTraceProc, NULL); } /* *---------------------------------------------------------------------- * * TclSetEnv -- * * Set an environment variable, replacing an existing value or creating a * new variable if there doesn't exist a variable by the given name. This * function is intended to be a stand-in for the UNIX "setenv" function * so that applications using that function will interface properly to * Tcl. To make it a stand-in, the Makefile must define "TclSetEnv" to * "setenv". * * Results: * None. * * Side effects: * The environ array gets updated. * *---------------------------------------------------------------------- */ void TclSetEnv( const char *name, /* Name of variable whose value is to be set * (UTF-8). */ const char *value) /* New value for variable (UTF-8). */ { Tcl_DString envString; unsigned nameLength, valueLength; int index, length; char *p, *oldValue; const char *p2; /* * Figure out where the entry is going to go. If the name doesn't already * exist, enlarge the array if necessary to make room. If the name exists, * free its old entry. */ Tcl_MutexLock(&envMutex); index = TclpFindVariable(name, &length); if (index == -1) { #ifndef USE_PUTENV /* * We need to handle the case where the environment may be changed * outside our control. ourEnvironSize is only valid if the current * environment is the one we allocated. [Bug 979640] */ if ((env.ourEnviron != environ) || (length+2 > env.ourEnvironSize)) { char **newEnviron = ckalloc((length + 5) * sizeof(char *)); memcpy(newEnviron, environ, length * sizeof(char *)); if ((env.ourEnvironSize != 0) && (env.ourEnviron != NULL)) { ckfree(env.ourEnviron); } environ = env.ourEnviron = newEnviron; env.ourEnvironSize = length + 5; } index = length; environ[index + 1] = NULL; #endif /* USE_PUTENV */ oldValue = NULL; nameLength = strlen(name); } else { const char *env; /* * Compare the new value to the existing value. If they're the same * then quit immediately (e.g. don't rewrite the value or propagate it * to other interpreters). Otherwise, when there are N interpreters * there will be N! propagations of the same value among the * interpreters. */ env = Tcl_ExternalToUtfDString(NULL, environ[index], -1, &envString); if (strcmp(value, env + (length + 1)) == 0) { Tcl_DStringFree(&envString); Tcl_MutexUnlock(&envMutex); return; } Tcl_DStringFree(&envString); oldValue = environ[index]; nameLength = (unsigned) length; } /* * Create a new entry. Build a complete UTF string that contains a * "name=value" pattern. Then convert the string to the native encoding, * and set the environ array value. */ valueLength = strlen(value); p = ckalloc(nameLength + valueLength + 2); memcpy(p, name, nameLength); p[nameLength] = '='; memcpy(p+nameLength+1, value, valueLength+1); p2 = Tcl_UtfToExternalDString(NULL, p, -1, &envString); /* * Copy the native string to heap memory. */ p = ckrealloc(p, Tcl_DStringLength(&envString) + 1); memcpy(p, p2, (unsigned) Tcl_DStringLength(&envString) + 1); Tcl_DStringFree(&envString); #ifdef USE_PUTENV /* * Update the system environment. */ putenv(p); index = TclpFindVariable(name, &length); #else environ[index] = p; #endif /* USE_PUTENV */ /* * Watch out for versions of putenv that copy the string (e.g. VC++). In * this case we need to free the string immediately. Otherwise update the * string in the cache. */ if ((index != -1) && (environ[index] == p)) { ReplaceString(oldValue, p); #ifdef HAVE_PUTENV_THAT_COPIES } else { /* * This putenv() copies instead of taking ownership. */ ckfree(p); #endif /* HAVE_PUTENV_THAT_COPIES */ } Tcl_MutexUnlock(&envMutex); if (!strcmp(name, "HOME")) { /* * If the user's home directory has changed, we must invalidate the * filesystem cache, because '~' expansions will now be incorrect. */ Tcl_FSMountsChanged(NULL); } } /* *---------------------------------------------------------------------- * * Tcl_PutEnv -- * * Set an environment variable. Similar to setenv except that the * information is passed in a single string of the form NAME=value, * rather than as separate name strings. This function is intended to be * a stand-in for the UNIX "putenv" function so that applications using * that function will interface properly to Tcl. To make it a stand-in, * the Makefile will define "Tcl_PutEnv" to "putenv". * * Results: * None. * * Side effects: * The environ array gets updated, as do all of the interpreters that we * manage. * *---------------------------------------------------------------------- */ int Tcl_PutEnv( const char *assignment) /* Info about environment variable in the form * NAME=value. (native) */ { Tcl_DString nameString; const char *name; char *value; if (assignment == NULL) { return 0; } /* * First convert the native string to UTF. Then separate the string into * name and value parts, and call TclSetEnv to do all of the real work. */ name = Tcl_ExternalToUtfDString(NULL, assignment, -1, &nameString); value = strchr(name, '='); if ((value != NULL) && (value != name)) { value[0] = '\0'; TclSetEnv(name, value+1); } Tcl_DStringFree(&nameString); return 0; } /* *---------------------------------------------------------------------- * * TclUnsetEnv -- * * Remove an environment variable, updating the "env" arrays in all * interpreters managed by us. This function is intended to replace the * UNIX "unsetenv" function (but to do this the Makefile must be modified * to redefine "TclUnsetEnv" to "unsetenv". * * Results: * None. * * Side effects: * Interpreters are updated, as is environ. * *---------------------------------------------------------------------- */ void TclUnsetEnv( const char *name) /* Name of variable to remove (UTF-8). */ { char *oldValue; int length; int index; #ifdef USE_PUTENV_FOR_UNSET Tcl_DString envString; char *string; #else char **envPtr; #endif /* USE_PUTENV_FOR_UNSET */ Tcl_MutexLock(&envMutex); index = TclpFindVariable(name, &length); /* * First make sure that the environment variable exists to avoid doing * needless work and to avoid recursion on the unset. */ if (index == -1) { Tcl_MutexUnlock(&envMutex); return; } /* * Remember the old value so we can free it if Tcl created the string. */ oldValue = environ[index]; /* * Update the system environment. This must be done before we update the * interpreters or we will recurse. */ #ifdef USE_PUTENV_FOR_UNSET /* * For those platforms that support putenv to unset, Linux indicates * that no = should be included, and Windows requires it. */ #if defined(_WIN32) string = ckalloc(length + 2); memcpy(string, name, (size_t) length); string[length] = '='; string[length+1] = '\0'; #else string = ckalloc(length + 1); memcpy(string, name, (size_t) length); string[length] = '\0'; #endif /* _WIN32 */ Tcl_UtfToExternalDString(NULL, string, -1, &envString); string = ckrealloc(string, Tcl_DStringLength(&envString) + 1); memcpy(string, Tcl_DStringValue(&envString), (unsigned) Tcl_DStringLength(&envString)+1); Tcl_DStringFree(&envString); putenv(string); /* * Watch out for versions of putenv that copy the string (e.g. VC++). In * this case we need to free the string immediately. Otherwise update the * string in the cache. */ if (environ[index] == string) { ReplaceString(oldValue, string); #ifdef HAVE_PUTENV_THAT_COPIES } else { /* * This putenv() copies instead of taking ownership. */ ckfree(string); #endif /* HAVE_PUTENV_THAT_COPIES */ } #else /* !USE_PUTENV_FOR_UNSET */ for (envPtr = environ+index+1; ; envPtr++) { envPtr[-1] = *envPtr; if (*envPtr == NULL) { break; } } ReplaceString(oldValue, NULL); #endif /* USE_PUTENV_FOR_UNSET */ Tcl_MutexUnlock(&envMutex); } /* *--------------------------------------------------------------------------- * * TclGetEnv -- * * Retrieve the value of an environment variable. * * Results: * The result is a pointer to a string specifying the value of the * environment variable, or NULL if that environment variable does not * exist. Storage for the result string is allocated in valuePtr; the * caller must call Tcl_DStringFree() when the result is no longer * needed. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * TclGetEnv( const char *name, /* Name of environment variable to find * (UTF-8). */ Tcl_DString *valuePtr) /* Uninitialized or free DString in which the * value of the environment variable is * stored. */ { int length, index; const char *result; Tcl_MutexLock(&envMutex); index = TclpFindVariable(name, &length); result = NULL; if (index != -1) { Tcl_DString envStr; result = Tcl_ExternalToUtfDString(NULL, environ[index], -1, &envStr); result += length; if (*result == '=') { result++; Tcl_DStringInit(valuePtr); Tcl_DStringAppend(valuePtr, result, -1); result = Tcl_DStringValue(valuePtr); } else { result = NULL; } Tcl_DStringFree(&envStr); } Tcl_MutexUnlock(&envMutex); return result; } /* *---------------------------------------------------------------------- * * EnvTraceProc -- * * This function is invoked whenever an environment variable is read, * modified or deleted. It propagates the change to the global "environ" * array. * * Results: * Returns NULL to indicate success, or an error-message if the array * element being handled doesn't exist. * * Side effects: * Environment variable changes get propagated. If the whole "env" array * is deleted, then we stop managing things for this interpreter (usually * this happens because the whole interpreter is being deleted). * *---------------------------------------------------------------------- */ /* ARGSUSED */ static char * EnvTraceProc( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Interpreter whose "env" variable is being * modified. */ const char *name1, /* Better be "env". */ const char *name2, /* Name of variable being modified, or NULL if * whole array is being deleted (UTF-8). */ int flags) /* Indicates what's happening. */ { /* * For array traces, let TclSetupEnv do all the work. */ if (flags & TCL_TRACE_ARRAY) { TclSetupEnv(interp); return NULL; } /* * If name2 is NULL, then return and do nothing. */ if (name2 == NULL) { return NULL; } /* * If a value is being set, call TclSetEnv to do all of the work. */ if (flags & TCL_TRACE_WRITES) { const char *value; value = Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY); TclSetEnv(name2, value); } /* * If a value is being read, call TclGetEnv to do all of the work. */ if (flags & TCL_TRACE_READS) { Tcl_DString valueString; const char *value = TclGetEnv(name2, &valueString); if (value == NULL) { return (char *) "no such variable"; } Tcl_SetVar2(interp, name1, name2, value, 0); Tcl_DStringFree(&valueString); } /* * For unset traces, let TclUnsetEnv do all the work. */ if (flags & TCL_TRACE_UNSETS) { TclUnsetEnv(name2); } return NULL; } /* *---------------------------------------------------------------------- * * ReplaceString -- * * Replace one string with another in the environment variable cache. The * cache keeps track of all of the environment variables that Tcl has * modified so they can be freed later. * * Results: * None. * * Side effects: * May free the old string. * *---------------------------------------------------------------------- */ static void ReplaceString( const char *oldStr, /* Old environment string. */ char *newStr) /* New environment string. */ { int i; /* * Check to see if the old value was allocated by Tcl. If so, it needs to * be deallocated to avoid memory leaks. Note that this algorithm is O(n), * not O(1). This will result in n-squared behavior if lots of environment * changes are being made. */ for (i = 0; i < env.cacheSize; i++) { if (env.cache[i]==oldStr || env.cache[i]==NULL) { break; } } if (i < env.cacheSize) { /* * Replace or delete the old value. */ if (env.cache[i]) { ckfree(env.cache[i]); } if (newStr) { env.cache[i] = newStr; } else { for (; i < env.cacheSize-1; i++) { env.cache[i] = env.cache[i+1]; } env.cache[env.cacheSize-1] = NULL; } } else { /* * We need to grow the cache in order to hold the new string. */ const int growth = 5; env.cache = ckrealloc(env.cache, (env.cacheSize + growth) * sizeof(char *)); env.cache[env.cacheSize] = newStr; (void) memset(env.cache+env.cacheSize+1, 0, (size_t) (growth-1) * sizeof(char *)); env.cacheSize += growth; } } /* *---------------------------------------------------------------------- * * TclFinalizeEnvironment -- * * This function releases any storage allocated by this module that isn't * still in use by the global environment. Any strings that are still in * the environment will be leaked. * * Results: * None. * * Side effects: * May deallocate storage. * *---------------------------------------------------------------------- */ void TclFinalizeEnvironment(void) { /* * For now we just deallocate the cache array and none of the environment * strings. This may leak more memory that strictly necessary, since some * of the strings may no longer be in the environment. However, * determining which ones are ok to delete is n-squared, and is pretty * unlikely, so we don't bother. */ if (env.cache) { ckfree(env.cache); env.cache = NULL; env.cacheSize = 0; #ifndef USE_PUTENV env.ourEnvironSize = 0; #endif } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclThreadAlloc.c0000644000175000017500000006746512663660065016256 0ustar sergeisergei/* * tclThreadAlloc.c -- * * This is a very fast storage allocator for used with threads (designed * avoid lock contention). The basic strategy is to allocate memory in * fixed size blocks from block caches. * * The Initial Developer of the Original Code is America Online, Inc. * Portions created by AOL are Copyright (C) 1999 America Online, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) /* * If range checking is enabled, an additional byte will be allocated to store * the magic number at the end of the requested memory. */ #ifndef RCHECK #ifdef NDEBUG #define RCHECK 0 #else #define RCHECK 1 #endif #endif /* * The following define the number of Tcl_Obj's to allocate/move at a time and * the high water mark to prune a per-thread cache. On a 32 bit system, * sizeof(Tcl_Obj) = 24 so 800 * 24 = ~16k. */ #define NOBJALLOC 800 /* Actual definition moved to tclInt.h */ #define NOBJHIGH ALLOC_NOBJHIGH /* * The following union stores accounting information for each block including * two small magic numbers and a bucket number when in use or a next pointer * when free. The original requested size (not including the Block overhead) * is also maintained. */ typedef union Block { struct { union { union Block *next; /* Next in free list. */ struct { unsigned char magic1; /* First magic number. */ unsigned char bucket; /* Bucket block allocated from. */ unsigned char unused; /* Padding. */ unsigned char magic2; /* Second magic number. */ } s; } u; size_t reqSize; /* Requested allocation size. */ } b; unsigned char padding[TCL_ALLOCALIGN]; } Block; #define nextBlock b.u.next #define sourceBucket b.u.s.bucket #define magicNum1 b.u.s.magic1 #define magicNum2 b.u.s.magic2 #define MAGIC 0xEF #define blockReqSize b.reqSize /* * The following defines the minimum and and maximum block sizes and the number * of buckets in the bucket cache. */ #define MINALLOC ((sizeof(Block) + 8 + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1)) #define NBUCKETS (11 - (MINALLOC >> 5)) #define MAXALLOC (MINALLOC << (NBUCKETS - 1)) /* * The following structure defines a bucket of blocks with various accounting * and statistics information. */ typedef struct Bucket { Block *firstPtr; /* First block available */ Block *lastPtr; /* End of block list */ long numFree; /* Number of blocks available */ /* All fields below for accounting only */ long numRemoves; /* Number of removes from bucket */ long numInserts; /* Number of inserts into bucket */ long numWaits; /* Number of waits to acquire a lock */ long numLocks; /* Number of locks acquired */ long totalAssigned; /* Total space assigned to bucket */ } Bucket; /* * The following structure defines a cache of buckets and objs, of which there * will be (at most) one per thread. Any changes need to be reflected in the * struct AllocCache defined in tclInt.h, possibly also in the initialisation * code in Tcl_CreateInterp(). */ typedef struct Cache { struct Cache *nextPtr; /* Linked list of cache entries */ Tcl_ThreadId owner; /* Which thread's cache is this? */ Tcl_Obj *firstObjPtr; /* List of free objects for thread */ int numObjects; /* Number of objects for thread */ Tcl_Obj *lastPtr; /* Last object in this cache */ int totalAssigned; /* Total space assigned to thread */ Bucket buckets[NBUCKETS]; /* The buckets for this thread */ } Cache; /* * The following array specifies various per-bucket limits and locks. The * values are statically initialized to avoid calculating them repeatedly. */ static struct { size_t blockSize; /* Bucket blocksize. */ int maxBlocks; /* Max blocks before move to share. */ int numMove; /* Num blocks to move to share. */ Tcl_Mutex *lockPtr; /* Share bucket lock. */ } bucketInfo[NBUCKETS]; /* * Static functions defined in this file. */ static Cache * GetCache(void); static void LockBucket(Cache *cachePtr, int bucket); static void UnlockBucket(Cache *cachePtr, int bucket); static void PutBlocks(Cache *cachePtr, int bucket, int numMove); static int GetBlocks(Cache *cachePtr, int bucket); static Block * Ptr2Block(char *ptr); static char * Block2Ptr(Block *blockPtr, int bucket, unsigned int reqSize); static void MoveObjs(Cache *fromPtr, Cache *toPtr, int numMove); static void PutObjs(Cache *fromPtr, int numMove); /* * Local variables defined in this file and initialized at startup. */ static Tcl_Mutex *listLockPtr; static Tcl_Mutex *objLockPtr; static Cache sharedCache; static Cache *sharedPtr = &sharedCache; static Cache *firstCachePtr = &sharedCache; #if defined(HAVE_FAST_TSD) static __thread Cache *tcachePtr; # define GETCACHE(cachePtr) \ do { \ if (!tcachePtr) { \ tcachePtr = GetCache(); \ } \ (cachePtr) = tcachePtr; \ } while (0) #else # define GETCACHE(cachePtr) \ do { \ (cachePtr) = TclpGetAllocCache(); \ if ((cachePtr) == NULL) { \ (cachePtr) = GetCache(); \ } \ } while (0) #endif /* *---------------------------------------------------------------------- * * GetCache --- * * Gets per-thread memory cache, allocating it if necessary. * * Results: * Pointer to cache. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Cache * GetCache(void) { Cache *cachePtr; /* * Check for first-time initialization. */ if (listLockPtr == NULL) { Tcl_Mutex *initLockPtr; unsigned int i; initLockPtr = Tcl_GetAllocMutex(); Tcl_MutexLock(initLockPtr); if (listLockPtr == NULL) { listLockPtr = TclpNewAllocMutex(); objLockPtr = TclpNewAllocMutex(); for (i = 0; i < NBUCKETS; ++i) { bucketInfo[i].blockSize = MINALLOC << i; bucketInfo[i].maxBlocks = 1 << (NBUCKETS - 1 - i); bucketInfo[i].numMove = i < NBUCKETS - 1 ? 1 << (NBUCKETS - 2 - i) : 1; bucketInfo[i].lockPtr = TclpNewAllocMutex(); } } Tcl_MutexUnlock(initLockPtr); } /* * Get this thread's cache, allocating if necessary. */ cachePtr = TclpGetAllocCache(); if (cachePtr == NULL) { cachePtr = TclpSysAlloc(sizeof(Cache), 0); if (cachePtr == NULL) { Tcl_Panic("alloc: could not allocate new cache"); } memset(cachePtr, 0, sizeof(Cache)); Tcl_MutexLock(listLockPtr); cachePtr->nextPtr = firstCachePtr; firstCachePtr = cachePtr; Tcl_MutexUnlock(listLockPtr); cachePtr->owner = Tcl_GetCurrentThread(); TclpSetAllocCache(cachePtr); } return cachePtr; } /* *---------------------------------------------------------------------- * * TclFreeAllocCache -- * * Flush and delete a cache, removing from list of caches. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclFreeAllocCache( void *arg) { Cache *cachePtr = arg; Cache **nextPtrPtr; register unsigned int bucket; /* * Flush blocks. */ for (bucket = 0; bucket < NBUCKETS; ++bucket) { if (cachePtr->buckets[bucket].numFree > 0) { PutBlocks(cachePtr, bucket, cachePtr->buckets[bucket].numFree); } } /* * Flush objs. */ if (cachePtr->numObjects > 0) { PutObjs(cachePtr, cachePtr->numObjects); } /* * Remove from pool list. */ Tcl_MutexLock(listLockPtr); nextPtrPtr = &firstCachePtr; while (*nextPtrPtr != cachePtr) { nextPtrPtr = &(*nextPtrPtr)->nextPtr; } *nextPtrPtr = cachePtr->nextPtr; cachePtr->nextPtr = NULL; Tcl_MutexUnlock(listLockPtr); TclpSysFree(cachePtr); } /* *---------------------------------------------------------------------- * * TclpAlloc -- * * Allocate memory. * * Results: * Pointer to memory just beyond Block pointer. * * Side effects: * May allocate more blocks for a bucket. * *---------------------------------------------------------------------- */ char * TclpAlloc( unsigned int reqSize) { Cache *cachePtr; Block *blockPtr; register int bucket; size_t size; #ifndef __LP64__ if (sizeof(int) >= sizeof(size_t)) { /* An unsigned int overflow can also be a size_t overflow */ const size_t zero = 0; const size_t max = ~zero; if (((size_t) reqSize) > max - sizeof(Block) - RCHECK) { /* Requested allocation exceeds memory */ return NULL; } } #endif GETCACHE(cachePtr); /* * Increment the requested size to include room for the Block structure. * Call TclpSysAlloc() directly if the required amount is greater than the * largest block, otherwise pop the smallest block large enough, * allocating more blocks if necessary. */ blockPtr = NULL; size = reqSize + sizeof(Block); #if RCHECK size++; #endif if (size > MAXALLOC) { bucket = NBUCKETS; blockPtr = TclpSysAlloc(size, 0); if (blockPtr != NULL) { cachePtr->totalAssigned += reqSize; } } else { bucket = 0; while (bucketInfo[bucket].blockSize < size) { bucket++; } if (cachePtr->buckets[bucket].numFree || GetBlocks(cachePtr, bucket)) { blockPtr = cachePtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr->nextBlock; cachePtr->buckets[bucket].numFree--; cachePtr->buckets[bucket].numRemoves++; cachePtr->buckets[bucket].totalAssigned += reqSize; } } if (blockPtr == NULL) { return NULL; } return Block2Ptr(blockPtr, bucket, reqSize); } /* *---------------------------------------------------------------------- * * TclpFree -- * * Return blocks to the thread block cache. * * Results: * None. * * Side effects: * May move blocks to shared cache. * *---------------------------------------------------------------------- */ void TclpFree( char *ptr) { Cache *cachePtr; Block *blockPtr; int bucket; if (ptr == NULL) { return; } GETCACHE(cachePtr); /* * Get the block back from the user pointer and call system free directly * for large blocks. Otherwise, push the block back on the bucket and move * blocks to the shared cache if there are now too many free. */ blockPtr = Ptr2Block(ptr); bucket = blockPtr->sourceBucket; if (bucket == NBUCKETS) { cachePtr->totalAssigned -= blockPtr->blockReqSize; TclpSysFree(blockPtr); return; } cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize; blockPtr->nextBlock = cachePtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr; if (cachePtr->buckets[bucket].numFree == 0) { cachePtr->buckets[bucket].lastPtr = blockPtr; } cachePtr->buckets[bucket].numFree++; cachePtr->buckets[bucket].numInserts++; if (cachePtr != sharedPtr && cachePtr->buckets[bucket].numFree > bucketInfo[bucket].maxBlocks) { PutBlocks(cachePtr, bucket, bucketInfo[bucket].numMove); } } /* *---------------------------------------------------------------------- * * TclpRealloc -- * * Re-allocate memory to a larger or smaller size. * * Results: * Pointer to memory just beyond Block pointer. * * Side effects: * Previous memory, if any, may be freed. * *---------------------------------------------------------------------- */ char * TclpRealloc( char *ptr, unsigned int reqSize) { Cache *cachePtr; Block *blockPtr; void *newPtr; size_t size, min; int bucket; if (ptr == NULL) { return TclpAlloc(reqSize); } #ifndef __LP64__ if (sizeof(int) >= sizeof(size_t)) { /* An unsigned int overflow can also be a size_t overflow */ const size_t zero = 0; const size_t max = ~zero; if (((size_t) reqSize) > max - sizeof(Block) - RCHECK) { /* Requested allocation exceeds memory */ return NULL; } } #endif GETCACHE(cachePtr); /* * If the block is not a system block and fits in place, simply return the * existing pointer. Otherwise, if the block is a system block and the new * size would also require a system block, call TclpSysRealloc() directly. */ blockPtr = Ptr2Block(ptr); size = reqSize + sizeof(Block); #if RCHECK size++; #endif bucket = blockPtr->sourceBucket; if (bucket != NBUCKETS) { if (bucket > 0) { min = bucketInfo[bucket-1].blockSize; } else { min = 0; } if (size > min && size <= bucketInfo[bucket].blockSize) { cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize; cachePtr->buckets[bucket].totalAssigned += reqSize; return Block2Ptr(blockPtr, bucket, reqSize); } } else if (size > MAXALLOC) { cachePtr->totalAssigned -= blockPtr->blockReqSize; cachePtr->totalAssigned += reqSize; blockPtr = TclpSysRealloc(blockPtr, size); if (blockPtr == NULL) { return NULL; } return Block2Ptr(blockPtr, NBUCKETS, reqSize); } /* * Finally, perform an expensive malloc/copy/free. */ newPtr = TclpAlloc(reqSize); if (newPtr != NULL) { if (reqSize > blockPtr->blockReqSize) { reqSize = blockPtr->blockReqSize; } memcpy(newPtr, ptr, reqSize); TclpFree(ptr); } return newPtr; } /* *---------------------------------------------------------------------- * * TclThreadAllocObj -- * * Allocate a Tcl_Obj from the per-thread cache. * * Results: * Pointer to uninitialized Tcl_Obj. * * Side effects: * May move Tcl_Obj's from shared cached or allocate new Tcl_Obj's if * list is empty. * * Note: * If this code is updated, the changes need to be reflected in the macro * TclAllocObjStorageEx() defined in tclInt.h * *---------------------------------------------------------------------- */ Tcl_Obj * TclThreadAllocObj(void) { register Cache *cachePtr; register Tcl_Obj *objPtr; GETCACHE(cachePtr); /* * Get this thread's obj list structure and move or allocate new objs if * necessary. */ if (cachePtr->numObjects == 0) { register int numMove; Tcl_MutexLock(objLockPtr); numMove = sharedPtr->numObjects; if (numMove > 0) { if (numMove > NOBJALLOC) { numMove = NOBJALLOC; } MoveObjs(sharedPtr, cachePtr, numMove); } Tcl_MutexUnlock(objLockPtr); if (cachePtr->numObjects == 0) { Tcl_Obj *newObjsPtr; cachePtr->numObjects = numMove = NOBJALLOC; newObjsPtr = TclpSysAlloc(sizeof(Tcl_Obj) * numMove, 0); if (newObjsPtr == NULL) { Tcl_Panic("alloc: could not allocate %d new objects", numMove); } cachePtr->lastPtr = newObjsPtr + numMove - 1; objPtr = cachePtr->firstObjPtr; /* NULL */ while (--numMove >= 0) { newObjsPtr[numMove].internalRep.twoPtrValue.ptr1 = objPtr; objPtr = newObjsPtr + numMove; } cachePtr->firstObjPtr = newObjsPtr; } } /* * Pop the first object. */ objPtr = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr->internalRep.twoPtrValue.ptr1; cachePtr->numObjects--; return objPtr; } /* *---------------------------------------------------------------------- * * TclThreadFreeObj -- * * Return a free Tcl_Obj to the per-thread cache. * * Results: * None. * * Side effects: * May move free Tcl_Obj's to shared list upon hitting high water mark. * * Note: * If this code is updated, the changes need to be reflected in the macro * TclAllocObjStorageEx() defined in tclInt.h * *---------------------------------------------------------------------- */ void TclThreadFreeObj( Tcl_Obj *objPtr) { Cache *cachePtr; GETCACHE(cachePtr); /* * Get this thread's list and push on the free Tcl_Obj. */ objPtr->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr; if (cachePtr->numObjects == 0) { cachePtr->lastPtr = objPtr; } cachePtr->numObjects++; /* * If the number of free objects has exceeded the high water mark, move * some blocks to the shared list. */ if (cachePtr->numObjects > NOBJHIGH) { PutObjs(cachePtr, NOBJALLOC); } } /* *---------------------------------------------------------------------- * * Tcl_GetMemoryInfo -- * * Return a list-of-lists of memory stats. * * Results: * None. * * Side effects: * List appended to given dstring. * *---------------------------------------------------------------------- */ void Tcl_GetMemoryInfo( Tcl_DString *dsPtr) { Cache *cachePtr; char buf[200]; unsigned int n; Tcl_MutexLock(listLockPtr); cachePtr = firstCachePtr; while (cachePtr != NULL) { Tcl_DStringStartSublist(dsPtr); if (cachePtr == sharedPtr) { Tcl_DStringAppendElement(dsPtr, "shared"); } else { sprintf(buf, "thread%p", cachePtr->owner); Tcl_DStringAppendElement(dsPtr, buf); } for (n = 0; n < NBUCKETS; ++n) { sprintf(buf, "%lu %ld %ld %ld %ld %ld %ld", (unsigned long) bucketInfo[n].blockSize, cachePtr->buckets[n].numFree, cachePtr->buckets[n].numRemoves, cachePtr->buckets[n].numInserts, cachePtr->buckets[n].totalAssigned, cachePtr->buckets[n].numLocks, cachePtr->buckets[n].numWaits); Tcl_DStringAppendElement(dsPtr, buf); } Tcl_DStringEndSublist(dsPtr); cachePtr = cachePtr->nextPtr; } Tcl_MutexUnlock(listLockPtr); } /* *---------------------------------------------------------------------- * * MoveObjs -- * * Move Tcl_Obj's between caches. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void MoveObjs( Cache *fromPtr, Cache *toPtr, int numMove) { register Tcl_Obj *objPtr = fromPtr->firstObjPtr; Tcl_Obj *fromFirstObjPtr = objPtr; toPtr->numObjects += numMove; fromPtr->numObjects -= numMove; /* * Find the last object to be moved; set the next one (the first one not * to be moved) as the first object in the 'from' cache. */ while (--numMove) { objPtr = objPtr->internalRep.twoPtrValue.ptr1; } fromPtr->firstObjPtr = objPtr->internalRep.twoPtrValue.ptr1; /* * Move all objects as a block - they are already linked to each other, we * just have to update the first and last. */ toPtr->lastPtr = objPtr; objPtr->internalRep.twoPtrValue.ptr1 = toPtr->firstObjPtr; /* NULL */ toPtr->firstObjPtr = fromFirstObjPtr; } /* *---------------------------------------------------------------------- * * PutObjs -- * * Move Tcl_Obj's from thread cache to shared cache. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void PutObjs( Cache *fromPtr, int numMove) { int keep = fromPtr->numObjects - numMove; Tcl_Obj *firstPtr, *lastPtr = NULL; fromPtr->numObjects = keep; firstPtr = fromPtr->firstObjPtr; if (keep == 0) { fromPtr->firstObjPtr = NULL; } else { do { lastPtr = firstPtr; firstPtr = firstPtr->internalRep.twoPtrValue.ptr1; } while (--keep > 0); lastPtr->internalRep.twoPtrValue.ptr1 = NULL; } /* * Move all objects as a block - they are already linked to each other, we * just have to update the first and last. */ Tcl_MutexLock(objLockPtr); fromPtr->lastPtr->internalRep.twoPtrValue.ptr1 = sharedPtr->firstObjPtr; sharedPtr->firstObjPtr = firstPtr; if (sharedPtr->numObjects == 0) { sharedPtr->lastPtr = fromPtr->lastPtr; } sharedPtr->numObjects += numMove; Tcl_MutexUnlock(objLockPtr); fromPtr->lastPtr = lastPtr; } /* *---------------------------------------------------------------------- * * Block2Ptr, Ptr2Block -- * * Convert between internal blocks and user pointers. * * Results: * User pointer or internal block. * * Side effects: * Invalid blocks will abort the server. * *---------------------------------------------------------------------- */ static char * Block2Ptr( Block *blockPtr, int bucket, unsigned int reqSize) { register void *ptr; blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC; blockPtr->sourceBucket = bucket; blockPtr->blockReqSize = reqSize; ptr = ((void *) (blockPtr + 1)); #if RCHECK ((unsigned char *)(ptr))[reqSize] = MAGIC; #endif return (char *) ptr; } static Block * Ptr2Block( char *ptr) { register Block *blockPtr; blockPtr = (((Block *) ptr) - 1); if (blockPtr->magicNum1 != MAGIC || blockPtr->magicNum2 != MAGIC) { Tcl_Panic("alloc: invalid block: %p: %x %x", blockPtr, blockPtr->magicNum1, blockPtr->magicNum2); } #if RCHECK if (((unsigned char *) ptr)[blockPtr->blockReqSize] != MAGIC) { Tcl_Panic("alloc: invalid block: %p: %x %x %x", blockPtr, blockPtr->magicNum1, blockPtr->magicNum2, ((unsigned char *) ptr)[blockPtr->blockReqSize]); } #endif return blockPtr; } /* *---------------------------------------------------------------------- * * LockBucket, UnlockBucket -- * * Set/unset the lock to access a bucket in the shared cache. * * Results: * None. * * Side effects: * Lock activity and contention are monitored globally and on a per-cache * basis. * *---------------------------------------------------------------------- */ static void LockBucket( Cache *cachePtr, int bucket) { Tcl_MutexLock(bucketInfo[bucket].lockPtr); cachePtr->buckets[bucket].numLocks++; sharedPtr->buckets[bucket].numLocks++; } static void UnlockBucket( Cache *cachePtr, int bucket) { Tcl_MutexUnlock(bucketInfo[bucket].lockPtr); } /* *---------------------------------------------------------------------- * * PutBlocks -- * * Return unused blocks to the shared cache. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void PutBlocks( Cache *cachePtr, int bucket, int numMove) { /* * We have numFree. Want to shed numMove. So compute how many * Blocks to keep. */ int keep = cachePtr->buckets[bucket].numFree - numMove; Block *lastPtr = NULL, *firstPtr; cachePtr->buckets[bucket].numFree = keep; firstPtr = cachePtr->buckets[bucket].firstPtr; if (keep == 0) { cachePtr->buckets[bucket].firstPtr = NULL; } else { do { lastPtr = firstPtr; firstPtr = firstPtr->nextBlock; } while (--keep > 0); lastPtr->nextBlock = NULL; } /* * Aquire the lock and place the list of blocks at the front of the shared * cache bucket. */ LockBucket(cachePtr, bucket); cachePtr->buckets[bucket].lastPtr->nextBlock = sharedPtr->buckets[bucket].firstPtr; sharedPtr->buckets[bucket].firstPtr = firstPtr; if (sharedPtr->buckets[bucket].numFree == 0) { sharedPtr->buckets[bucket].lastPtr = cachePtr->buckets[bucket].lastPtr; } sharedPtr->buckets[bucket].numFree += numMove; UnlockBucket(cachePtr, bucket); cachePtr->buckets[bucket].lastPtr = lastPtr; } /* *---------------------------------------------------------------------- * * GetBlocks -- * * Get more blocks for a bucket. * * Results: * 1 if blocks where allocated, 0 otherwise. * * Side effects: * Cache may be filled with available blocks. * *---------------------------------------------------------------------- */ static int GetBlocks( Cache *cachePtr, int bucket) { register Block *blockPtr; register int n; /* * First, atttempt to move blocks from the shared cache. Note the * potentially dirty read of numFree before acquiring the lock which is a * slight performance enhancement. The value is verified after the lock is * actually acquired. */ if (cachePtr != sharedPtr && sharedPtr->buckets[bucket].numFree > 0) { LockBucket(cachePtr, bucket); if (sharedPtr->buckets[bucket].numFree > 0) { /* * Either move the entire list or walk the list to find the last * block to move. */ n = bucketInfo[bucket].numMove; if (n >= sharedPtr->buckets[bucket].numFree) { cachePtr->buckets[bucket].firstPtr = sharedPtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].lastPtr = sharedPtr->buckets[bucket].lastPtr; cachePtr->buckets[bucket].numFree = sharedPtr->buckets[bucket].numFree; sharedPtr->buckets[bucket].firstPtr = NULL; sharedPtr->buckets[bucket].numFree = 0; } else { blockPtr = sharedPtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr; sharedPtr->buckets[bucket].numFree -= n; cachePtr->buckets[bucket].numFree = n; while (--n > 0) { blockPtr = blockPtr->nextBlock; } sharedPtr->buckets[bucket].firstPtr = blockPtr->nextBlock; cachePtr->buckets[bucket].lastPtr = blockPtr; blockPtr->nextBlock = NULL; } } UnlockBucket(cachePtr, bucket); } if (cachePtr->buckets[bucket].numFree == 0) { register size_t size; /* * If no blocks could be moved from shared, first look for a larger * block in this cache to split up. */ blockPtr = NULL; n = NBUCKETS; size = 0; /* lint */ while (--n > bucket) { if (cachePtr->buckets[n].numFree > 0) { size = bucketInfo[n].blockSize; blockPtr = cachePtr->buckets[n].firstPtr; cachePtr->buckets[n].firstPtr = blockPtr->nextBlock; cachePtr->buckets[n].numFree--; break; } } /* * Otherwise, allocate a big new block directly. */ if (blockPtr == NULL) { size = MAXALLOC; blockPtr = TclpSysAlloc(size, 0); if (blockPtr == NULL) { return 0; } } /* * Split the larger block into smaller blocks for this bucket. */ n = size / bucketInfo[bucket].blockSize; cachePtr->buckets[bucket].numFree = n; cachePtr->buckets[bucket].firstPtr = blockPtr; while (--n > 0) { blockPtr->nextBlock = (Block *) ((char *) blockPtr + bucketInfo[bucket].blockSize); blockPtr = blockPtr->nextBlock; } cachePtr->buckets[bucket].lastPtr = blockPtr; blockPtr->nextBlock = NULL; } return 1; } /* *---------------------------------------------------------------------- * * TclFinalizeThreadAlloc -- * * This procedure is used to destroy all private resources used in this * file. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclFinalizeThreadAlloc(void) { unsigned int i; for (i = 0; i < NBUCKETS; ++i) { TclpFreeAllocMutex(bucketInfo[i].lockPtr); bucketInfo[i].lockPtr = NULL; } TclpFreeAllocMutex(objLockPtr); objLockPtr = NULL; TclpFreeAllocMutex(listLockPtr); listLockPtr = NULL; TclpFreeAllocCache(NULL); } /* *---------------------------------------------------------------------- * * TclFinalizeThreadAllocThread -- * * This procedure is used to destroy single thread private resources used * in this file. * Called in TclpFinalizeThreadData when a thread exits (Tcl_FinalizeThread). * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclFinalizeThreadAllocThread(void) { Cache *cachePtr = TclpGetAllocCache(); if (cachePtr != NULL) { TclpFreeAllocCache(cachePtr); } } #else /* !(TCL_THREADS && USE_THREAD_ALLOC) */ /* *---------------------------------------------------------------------- * * Tcl_GetMemoryInfo -- * * Return a list-of-lists of memory stats. * * Results: * None. * * Side effects: * List appended to given dstring. * *---------------------------------------------------------------------- */ void Tcl_GetMemoryInfo( Tcl_DString *dsPtr) { Tcl_Panic("Tcl_GetMemoryInfo called when threaded memory allocator not in use"); } /* *---------------------------------------------------------------------- * * TclFinalizeThreadAlloc -- * * This procedure is used to destroy all private resources used in this * file. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclFinalizeThreadAlloc(void) { Tcl_Panic("TclFinalizeThreadAlloc called when threaded memory allocator not in use"); } #endif /* TCL_THREADS && USE_THREAD_ALLOC */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclLoadNone.c0000644000175000017500000000703612663660065015557 0ustar sergeisergei/* * tclLoadNone.c -- * * This procedure provides a version of the TclpDlopen for use in * systems that don't support dynamic loading; it just returns an error. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* *---------------------------------------------------------------------- * * TclpDlopen -- * * This procedure is called to carry out dynamic loading of binary code; * it is intended for use only on systems that don't support dynamic * loading (it returns an error). * * Results: * The result is TCL_ERROR, and an error message is left in the interp's * result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclpDlopen( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Obj *pathPtr, /* Name of the file containing the desired * code (UTF-8). */ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr, /* Filled with address of Tcl_FSUnloadFileProc * function which should be used for this * file. */ int flags) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "dynamic loading is not currently available on this system", -1)); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclGuessPackageName -- * * If the "load" command is invoked without providing a package name, * this procedure is invoked to try to figure it out. * * Results: * Always returns 0 to indicate that we couldn't figure out a package * name; generic code will then try to guess the package from the file * name. A return value of 1 would have meant that we figured out the * package name and put it in bufPtr. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclGuessPackageName( const char *fileName, /* Name of file containing package (already * translated to local form if needed). */ Tcl_DString *bufPtr) /* Initialized empty dstring. Append package * name to this if possible. */ { return 0; } /* * These functions are fallbacks if we somehow determine that the platform can * do loading from memory but the user wishes to disable it. They just report * (gracefully) that they fail. */ #ifdef TCL_LOAD_FROM_MEMORY MODULE_SCOPE void * TclpLoadMemoryGetBuffer( Tcl_Interp *interp, /* Dummy: unused by this implementation */ int size) /* Dummy: unused by this implementation */ { return NULL; } MODULE_SCOPE int TclpLoadMemory( Tcl_Interp *interp, /* Used for error reporting. */ void *buffer, /* Dummy: unused by this implementation */ int size, /* Dummy: unused by this implementation */ int codeSize, /* Dummy: unused by this implementation */ Tcl_LoadHandle *loadHandle, /* Dummy: unused by this implementation */ Tcl_FSUnloadFileProc **unloadProcPtr, /* Dummy: unused by this implementation */ int flags) /* Dummy: unused by this implementation */ { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj("dynamic loading from memory " "is not available on this system", -1)); } return TCL_ERROR; } #endif /* TCL_LOAD_FROM_MEMORY */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclOODecls.h0000644000175000017500000002164312665173571015360 0ustar sergeisergei/* * This file is (mostly) automatically generated from tclOO.decls. */ #ifndef _TCLOODECLS #define _TCLOODECLS #ifndef TCLAPI # ifdef BUILD_tcl # define TCLAPI extern DLLEXPORT # else # define TCLAPI extern DLLIMPORT # endif #endif #ifdef USE_TCL_STUBS # undef USE_TCLOO_STUBS # define USE_TCLOO_STUBS #endif /* !BEGIN!: Do not edit below this line. */ #ifdef __cplusplus extern "C" { #endif /* * Exported function declarations: */ /* 0 */ TCLAPI Tcl_Object Tcl_CopyObjectInstance(Tcl_Interp *interp, Tcl_Object sourceObject, const char *targetName, const char *targetNamespaceName); /* 1 */ TCLAPI Tcl_Object Tcl_GetClassAsObject(Tcl_Class clazz); /* 2 */ TCLAPI Tcl_Class Tcl_GetObjectAsClass(Tcl_Object object); /* 3 */ TCLAPI Tcl_Command Tcl_GetObjectCommand(Tcl_Object object); /* 4 */ TCLAPI Tcl_Object Tcl_GetObjectFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr); /* 5 */ TCLAPI Tcl_Namespace * Tcl_GetObjectNamespace(Tcl_Object object); /* 6 */ TCLAPI Tcl_Class Tcl_MethodDeclarerClass(Tcl_Method method); /* 7 */ TCLAPI Tcl_Object Tcl_MethodDeclarerObject(Tcl_Method method); /* 8 */ TCLAPI int Tcl_MethodIsPublic(Tcl_Method method); /* 9 */ TCLAPI int Tcl_MethodIsType(Tcl_Method method, const Tcl_MethodType *typePtr, ClientData *clientDataPtr); /* 10 */ TCLAPI Tcl_Obj * Tcl_MethodName(Tcl_Method method); /* 11 */ TCLAPI Tcl_Method Tcl_NewInstanceMethod(Tcl_Interp *interp, Tcl_Object object, Tcl_Obj *nameObj, int isPublic, const Tcl_MethodType *typePtr, ClientData clientData); /* 12 */ TCLAPI Tcl_Method Tcl_NewMethod(Tcl_Interp *interp, Tcl_Class cls, Tcl_Obj *nameObj, int isPublic, const Tcl_MethodType *typePtr, ClientData clientData); /* 13 */ TCLAPI Tcl_Object Tcl_NewObjectInstance(Tcl_Interp *interp, Tcl_Class cls, const char *nameStr, const char *nsNameStr, int objc, Tcl_Obj *const *objv, int skip); /* 14 */ TCLAPI int Tcl_ObjectDeleted(Tcl_Object object); /* 15 */ TCLAPI int Tcl_ObjectContextIsFiltering( Tcl_ObjectContext context); /* 16 */ TCLAPI Tcl_Method Tcl_ObjectContextMethod(Tcl_ObjectContext context); /* 17 */ TCLAPI Tcl_Object Tcl_ObjectContextObject(Tcl_ObjectContext context); /* 18 */ TCLAPI int Tcl_ObjectContextSkippedArgs( Tcl_ObjectContext context); /* 19 */ TCLAPI ClientData Tcl_ClassGetMetadata(Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr); /* 20 */ TCLAPI void Tcl_ClassSetMetadata(Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr, ClientData metadata); /* 21 */ TCLAPI ClientData Tcl_ObjectGetMetadata(Tcl_Object object, const Tcl_ObjectMetadataType *typePtr); /* 22 */ TCLAPI void Tcl_ObjectSetMetadata(Tcl_Object object, const Tcl_ObjectMetadataType *typePtr, ClientData metadata); /* 23 */ TCLAPI int Tcl_ObjectContextInvokeNext(Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv, int skip); /* 24 */ TCLAPI Tcl_ObjectMapMethodNameProc * Tcl_ObjectGetMethodNameMapper( Tcl_Object object); /* 25 */ TCLAPI void Tcl_ObjectSetMethodNameMapper(Tcl_Object object, Tcl_ObjectMapMethodNameProc *mapMethodNameProc); /* 26 */ TCLAPI void Tcl_ClassSetConstructor(Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method); /* 27 */ TCLAPI void Tcl_ClassSetDestructor(Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method); /* 28 */ TCLAPI Tcl_Obj * Tcl_GetObjectName(Tcl_Interp *interp, Tcl_Object object); typedef struct { const struct TclOOIntStubs *tclOOIntStubs; } TclOOStubHooks; typedef struct TclOOStubs { int magic; const TclOOStubHooks *hooks; Tcl_Object (*tcl_CopyObjectInstance) (Tcl_Interp *interp, Tcl_Object sourceObject, const char *targetName, const char *targetNamespaceName); /* 0 */ Tcl_Object (*tcl_GetClassAsObject) (Tcl_Class clazz); /* 1 */ Tcl_Class (*tcl_GetObjectAsClass) (Tcl_Object object); /* 2 */ Tcl_Command (*tcl_GetObjectCommand) (Tcl_Object object); /* 3 */ Tcl_Object (*tcl_GetObjectFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 4 */ Tcl_Namespace * (*tcl_GetObjectNamespace) (Tcl_Object object); /* 5 */ Tcl_Class (*tcl_MethodDeclarerClass) (Tcl_Method method); /* 6 */ Tcl_Object (*tcl_MethodDeclarerObject) (Tcl_Method method); /* 7 */ int (*tcl_MethodIsPublic) (Tcl_Method method); /* 8 */ int (*tcl_MethodIsType) (Tcl_Method method, const Tcl_MethodType *typePtr, ClientData *clientDataPtr); /* 9 */ Tcl_Obj * (*tcl_MethodName) (Tcl_Method method); /* 10 */ Tcl_Method (*tcl_NewInstanceMethod) (Tcl_Interp *interp, Tcl_Object object, Tcl_Obj *nameObj, int isPublic, const Tcl_MethodType *typePtr, ClientData clientData); /* 11 */ Tcl_Method (*tcl_NewMethod) (Tcl_Interp *interp, Tcl_Class cls, Tcl_Obj *nameObj, int isPublic, const Tcl_MethodType *typePtr, ClientData clientData); /* 12 */ Tcl_Object (*tcl_NewObjectInstance) (Tcl_Interp *interp, Tcl_Class cls, const char *nameStr, const char *nsNameStr, int objc, Tcl_Obj *const *objv, int skip); /* 13 */ int (*tcl_ObjectDeleted) (Tcl_Object object); /* 14 */ int (*tcl_ObjectContextIsFiltering) (Tcl_ObjectContext context); /* 15 */ Tcl_Method (*tcl_ObjectContextMethod) (Tcl_ObjectContext context); /* 16 */ Tcl_Object (*tcl_ObjectContextObject) (Tcl_ObjectContext context); /* 17 */ int (*tcl_ObjectContextSkippedArgs) (Tcl_ObjectContext context); /* 18 */ ClientData (*tcl_ClassGetMetadata) (Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr); /* 19 */ void (*tcl_ClassSetMetadata) (Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr, ClientData metadata); /* 20 */ ClientData (*tcl_ObjectGetMetadata) (Tcl_Object object, const Tcl_ObjectMetadataType *typePtr); /* 21 */ void (*tcl_ObjectSetMetadata) (Tcl_Object object, const Tcl_ObjectMetadataType *typePtr, ClientData metadata); /* 22 */ int (*tcl_ObjectContextInvokeNext) (Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv, int skip); /* 23 */ Tcl_ObjectMapMethodNameProc * (*tcl_ObjectGetMethodNameMapper) (Tcl_Object object); /* 24 */ void (*tcl_ObjectSetMethodNameMapper) (Tcl_Object object, Tcl_ObjectMapMethodNameProc *mapMethodNameProc); /* 25 */ void (*tcl_ClassSetConstructor) (Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method); /* 26 */ void (*tcl_ClassSetDestructor) (Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method); /* 27 */ Tcl_Obj * (*tcl_GetObjectName) (Tcl_Interp *interp, Tcl_Object object); /* 28 */ } TclOOStubs; extern const TclOOStubs *tclOOStubsPtr; #ifdef __cplusplus } #endif #if defined(USE_TCLOO_STUBS) /* * Inline function declarations: */ #define Tcl_CopyObjectInstance \ (tclOOStubsPtr->tcl_CopyObjectInstance) /* 0 */ #define Tcl_GetClassAsObject \ (tclOOStubsPtr->tcl_GetClassAsObject) /* 1 */ #define Tcl_GetObjectAsClass \ (tclOOStubsPtr->tcl_GetObjectAsClass) /* 2 */ #define Tcl_GetObjectCommand \ (tclOOStubsPtr->tcl_GetObjectCommand) /* 3 */ #define Tcl_GetObjectFromObj \ (tclOOStubsPtr->tcl_GetObjectFromObj) /* 4 */ #define Tcl_GetObjectNamespace \ (tclOOStubsPtr->tcl_GetObjectNamespace) /* 5 */ #define Tcl_MethodDeclarerClass \ (tclOOStubsPtr->tcl_MethodDeclarerClass) /* 6 */ #define Tcl_MethodDeclarerObject \ (tclOOStubsPtr->tcl_MethodDeclarerObject) /* 7 */ #define Tcl_MethodIsPublic \ (tclOOStubsPtr->tcl_MethodIsPublic) /* 8 */ #define Tcl_MethodIsType \ (tclOOStubsPtr->tcl_MethodIsType) /* 9 */ #define Tcl_MethodName \ (tclOOStubsPtr->tcl_MethodName) /* 10 */ #define Tcl_NewInstanceMethod \ (tclOOStubsPtr->tcl_NewInstanceMethod) /* 11 */ #define Tcl_NewMethod \ (tclOOStubsPtr->tcl_NewMethod) /* 12 */ #define Tcl_NewObjectInstance \ (tclOOStubsPtr->tcl_NewObjectInstance) /* 13 */ #define Tcl_ObjectDeleted \ (tclOOStubsPtr->tcl_ObjectDeleted) /* 14 */ #define Tcl_ObjectContextIsFiltering \ (tclOOStubsPtr->tcl_ObjectContextIsFiltering) /* 15 */ #define Tcl_ObjectContextMethod \ (tclOOStubsPtr->tcl_ObjectContextMethod) /* 16 */ #define Tcl_ObjectContextObject \ (tclOOStubsPtr->tcl_ObjectContextObject) /* 17 */ #define Tcl_ObjectContextSkippedArgs \ (tclOOStubsPtr->tcl_ObjectContextSkippedArgs) /* 18 */ #define Tcl_ClassGetMetadata \ (tclOOStubsPtr->tcl_ClassGetMetadata) /* 19 */ #define Tcl_ClassSetMetadata \ (tclOOStubsPtr->tcl_ClassSetMetadata) /* 20 */ #define Tcl_ObjectGetMetadata \ (tclOOStubsPtr->tcl_ObjectGetMetadata) /* 21 */ #define Tcl_ObjectSetMetadata \ (tclOOStubsPtr->tcl_ObjectSetMetadata) /* 22 */ #define Tcl_ObjectContextInvokeNext \ (tclOOStubsPtr->tcl_ObjectContextInvokeNext) /* 23 */ #define Tcl_ObjectGetMethodNameMapper \ (tclOOStubsPtr->tcl_ObjectGetMethodNameMapper) /* 24 */ #define Tcl_ObjectSetMethodNameMapper \ (tclOOStubsPtr->tcl_ObjectSetMethodNameMapper) /* 25 */ #define Tcl_ClassSetConstructor \ (tclOOStubsPtr->tcl_ClassSetConstructor) /* 26 */ #define Tcl_ClassSetDestructor \ (tclOOStubsPtr->tcl_ClassSetDestructor) /* 27 */ #define Tcl_GetObjectName \ (tclOOStubsPtr->tcl_GetObjectName) /* 28 */ #endif /* defined(USE_TCLOO_STUBS) */ /* !END!: Do not edit above this line. */ #endif /* _TCLOODECLS */ tcl8.6.5/generic/tclFCmd.c0000644000175000017500000011421112663660065014663 0ustar sergeisergei/* * tclFCmd.c * * This file implements the generic portion of file manipulation * subcommands of the "file" command. * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclFileSystem.h" /* * Declarations for local functions defined in this file: */ static int CopyRenameOneFile(Tcl_Interp *interp, Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, int copyFlag, int force); static Tcl_Obj * FileBasename(Tcl_Interp *interp, Tcl_Obj *pathPtr); static int FileCopyRename(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int copyFlag); static int FileForceOption(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int *forcePtr); /* *--------------------------------------------------------------------------- * * TclFileRenameCmd * * This function implements the "rename" subcommand of the "file" * command. Filename arguments need to be translated to native format * before being passed to platform-specific code that implements rename * functionality. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *--------------------------------------------------------------------------- */ int TclFileRenameCmd( ClientData clientData, /* Unused */ Tcl_Interp *interp, /* Interp for error reporting or recursive * calls in the case of a tricky rename. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings passed to Tcl_FileCmd. */ { return FileCopyRename(interp, objc, objv, 0); } /* *--------------------------------------------------------------------------- * * TclFileCopyCmd * * This function implements the "copy" subcommand of the "file" command. * Filename arguments need to be translated to native format before being * passed to platform-specific code that implements copy functionality. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *--------------------------------------------------------------------------- */ int TclFileCopyCmd( ClientData clientData, /* Unused */ Tcl_Interp *interp, /* Used for error reporting or recursive calls * in the case of a tricky copy. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings passed to Tcl_FileCmd. */ { return FileCopyRename(interp, objc, objv, 1); } /* *--------------------------------------------------------------------------- * * FileCopyRename -- * * Performs the work of TclFileRenameCmd and TclFileCopyCmd. See * comments for those functions. * * Results: * See above. * * Side effects: * See above. * *--------------------------------------------------------------------------- */ static int FileCopyRename( Tcl_Interp *interp, /* Used for error reporting. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[], /* Argument strings passed to Tcl_FileCmd. */ int copyFlag) /* If non-zero, copy source(s). Otherwise, * rename them. */ { int i, result, force; Tcl_StatBuf statBuf; Tcl_Obj *target; i = FileForceOption(interp, objc - 1, objv + 1, &force); if (i < 0) { return TCL_ERROR; } i++; if ((objc - i) < 2) { Tcl_WrongNumArgs(interp, 1, objv, "?-option value ...? source ?source ...? target"); return TCL_ERROR; } /* * If target doesn't exist or isn't a directory, try the copy/rename. More * than 2 arguments is only valid if the target is an existing directory. */ target = objv[objc - 1]; if (Tcl_FSConvertToPathType(interp, target) != TCL_OK) { return TCL_ERROR; } result = TCL_OK; /* * Call Tcl_FSStat() so that if target is a symlink that points to a * directory we will put the sources in that directory instead of * overwriting the symlink. */ if ((Tcl_FSStat(target, &statBuf) != 0) || !S_ISDIR(statBuf.st_mode)) { if ((objc - i) > 2) { errno = ENOTDIR; Tcl_PosixError(interp); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error %s: target \"%s\" is not a directory", (copyFlag?"copying":"renaming"), TclGetString(target))); result = TCL_ERROR; } else { /* * Even though already have target == translated(objv[i+1]), pass * the original argument down, so if there's an error, the error * message will reflect the original arguments. */ result = CopyRenameOneFile(interp, objv[i], objv[i + 1], copyFlag, force); } return result; } /* * Move each source file into target directory. Extract the basename from * each source, and append it to the end of the target path. */ for ( ; i 20) { /* * Too many links. */ Tcl_SetErrno(EMLINK); errfile = source; goto done; } } /* Now 'actualSource' is the correct file */ } } #endif /* S_ISLNK */ #endif if (S_ISDIR(sourceStatBuf.st_mode)) { result = Tcl_FSCopyDirectory(actualSource, target, &errorBuffer); if (result != TCL_OK) { if (errno == EXDEV) { /* * The copy failed because we're trying to do a * cross-filesystem copy. We do this through our Tcl library. */ Tcl_Obj *copyCommand, *cmdObj, *opObj; TclNewObj(copyCommand); TclNewLiteralStringObj(cmdObj, "::tcl::CopyDirectory"); Tcl_ListObjAppendElement(interp, copyCommand, cmdObj); if (copyFlag) { TclNewLiteralStringObj(opObj, "copying"); } else { TclNewLiteralStringObj(opObj, "renaming"); } Tcl_ListObjAppendElement(interp, copyCommand, opObj); Tcl_ListObjAppendElement(interp, copyCommand, source); Tcl_ListObjAppendElement(interp, copyCommand, target); Tcl_IncrRefCount(copyCommand); result = Tcl_EvalObjEx(interp, copyCommand, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); Tcl_DecrRefCount(copyCommand); if (result != TCL_OK) { /* * There was an error in the Tcl-level copy. We will pass * on the Tcl error message and can ensure this by setting * errfile to NULL */ errfile = NULL; } } else { errfile = errorBuffer; if (Tcl_FSEqualPaths(errfile, source)) { errfile = source; } else if (Tcl_FSEqualPaths(errfile, target)) { errfile = target; } } } } else { result = Tcl_FSCopyFile(actualSource, target); if ((result != TCL_OK) && (errno == EXDEV)) { result = TclCrossFilesystemCopy(interp, source, target); } if (result != TCL_OK) { /* * We could examine 'errno' to double-check if the problem was * with the target, but we checked the source above, so it should * be quite clear */ errfile = target; } /* * We now need to reset the result, because the above call, * may have left set it. (Ideally we would prefer not to pass * an interpreter in above, but the channel IO code used by * TclCrossFilesystemCopy currently requires one) */ Tcl_ResetResult(interp); } if ((copyFlag == 0) && (result == TCL_OK)) { if (S_ISDIR(sourceStatBuf.st_mode)) { result = Tcl_FSRemoveDirectory(source, 1, &errorBuffer); if (result != TCL_OK) { errfile = errorBuffer; if (Tcl_FSEqualPaths(errfile, source) == 0) { errfile = source; } } } else { result = Tcl_FSDeleteFile(source); if (result != TCL_OK) { errfile = source; } } if (result != TCL_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("can't unlink \"%s\": %s", TclGetString(errfile), Tcl_PosixError(interp))); errfile = NULL; } } done: if (errfile != NULL) { Tcl_Obj *errorMsg = Tcl_ObjPrintf("error %s \"%s\"", (copyFlag ? "copying" : "renaming"), TclGetString(source)); if (errfile != source) { Tcl_AppendPrintfToObj(errorMsg, " to \"%s\"", TclGetString(target)); if (errfile != target) { Tcl_AppendPrintfToObj(errorMsg, ": \"%s\"", TclGetString(errfile)); } } Tcl_AppendPrintfToObj(errorMsg, ": %s", Tcl_PosixError(interp)); Tcl_SetObjResult(interp, errorMsg); } if (errorBuffer != NULL) { Tcl_DecrRefCount(errorBuffer); } if (actualSource != NULL) { Tcl_DecrRefCount(actualSource); } return result; } /* *--------------------------------------------------------------------------- * * FileForceOption -- * * Helps parse command line options for file commands that take the * "-force" and "--" options. * * Results: * The return value is how many arguments from argv were consumed by this * function, or -1 if there was an error parsing the options. If an error * occurred, an error message is left in the interp's result. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static int FileForceOption( Tcl_Interp *interp, /* Interp, for error return. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[], /* Argument strings. First command line * option, if it exists, begins at 0. */ int *forcePtr) /* If the "-force" was specified, *forcePtr is * filled with 1, otherwise with 0. */ { int force, i, idx; static const char *const options[] = { "-force", "--", NULL }; force = 0; for (i = 0; i < objc; i++) { if (TclGetString(objv[i])[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", TCL_EXACT, &idx) != TCL_OK) { return -1; } if (idx == 0 /* -force */) { force = 1; } else { /* -- */ i++; break; } } *forcePtr = force; return i; } /* *--------------------------------------------------------------------------- * * FileBasename -- * * Given a path in either tcl format (with / separators), or in the * platform-specific format for the current platform, return all the * characters in the path after the last directory separator. But, if * path is the root directory, returns no characters. * * Results: * Returns the string object that represents the basename. If there is an * error, an error message is left in interp, and NULL is returned. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static Tcl_Obj * FileBasename( Tcl_Interp *interp, /* Interp, for error return. */ Tcl_Obj *pathPtr) /* Path whose basename to extract. */ { int objc; Tcl_Obj *splitPtr; Tcl_Obj *resultPtr = NULL; splitPtr = Tcl_FSSplitPath(pathPtr, &objc); Tcl_IncrRefCount(splitPtr); if (objc != 0) { if ((objc == 1) && (*TclGetString(pathPtr) == '~')) { Tcl_DecrRefCount(splitPtr); if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) { return NULL; } splitPtr = Tcl_FSSplitPath(pathPtr, &objc); Tcl_IncrRefCount(splitPtr); } /* * Return the last component, unless it is the only component, and it * is the root of an absolute path. */ if (objc > 0) { Tcl_ListObjIndex(NULL, splitPtr, objc-1, &resultPtr); if ((objc == 1) && (Tcl_FSGetPathType(resultPtr) != TCL_PATH_RELATIVE)) { resultPtr = NULL; } } } if (resultPtr == NULL) { resultPtr = Tcl_NewObj(); } Tcl_IncrRefCount(resultPtr); Tcl_DecrRefCount(splitPtr); return resultPtr; } /* *---------------------------------------------------------------------- * * TclFileAttrsCmd -- * * Sets or gets the platform-specific attributes of a file. The objc-objv * points to the file name with the rest of the command line following. * This routine uses platform-specific tables of option strings and * callbacks. The callback to get the attributes take three parameters: * Tcl_Interp *interp; The interp to report errors with. Since * this is an object-based API, the object * form of the result should be used. * const char *fileName; This is extracted using * Tcl_TranslateFileName. * TclObj **attrObjPtrPtr; A new object to hold the attribute is * allocated and put here. * The first two parameters of the callback used to write out the * attributes are the same. The third parameter is: * const *attrObjPtr; A pointer to the object that has the new * attribute. * They both return standard TCL errors; if the routine to get an * attribute fails, no object is allocated and *attrObjPtrPtr is * unchanged. * * Results: * Standard TCL error. * * Side effects: * May set file attributes for the file name. * *---------------------------------------------------------------------- */ int TclFileAttrsCmd( ClientData clientData, /* Unused */ Tcl_Interp *interp, /* The interpreter for error reporting. */ int objc, /* Number of command line arguments. */ Tcl_Obj *const objv[]) /* The command line objects. */ { int result; const char *const *attributeStrings; const char **attributeStringsAllocated = NULL; Tcl_Obj *objStrings = NULL; int numObjStrings = -1; Tcl_Obj *filePtr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "name ?-option value ...?"); return TCL_ERROR; } filePtr = objv[1]; if (Tcl_FSConvertToPathType(interp, filePtr) != TCL_OK) { return TCL_ERROR; } objc -= 2; objv += 2; result = TCL_ERROR; Tcl_SetErrno(0); /* * Get the set of attribute names from the filesystem. */ attributeStrings = Tcl_FSFileAttrStrings(filePtr, &objStrings); if (attributeStrings == NULL) { int index; Tcl_Obj *objPtr; if (objStrings == NULL) { if (Tcl_GetErrno() != 0) { /* * There was an error, probably that the filePtr is not * accepted by any filesystem */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not read \"%s\": %s", TclGetString(filePtr), Tcl_PosixError(interp))); } return TCL_ERROR; } /* * We own the object now. */ Tcl_IncrRefCount(objStrings); /* * Use objStrings as a list object. */ if (Tcl_ListObjLength(interp, objStrings, &numObjStrings) != TCL_OK) { goto end; } attributeStringsAllocated = (const char **) TclStackAlloc(interp, (1+numObjStrings) * sizeof(char *)); for (index = 0; index < numObjStrings; index++) { Tcl_ListObjIndex(interp, objStrings, index, &objPtr); attributeStringsAllocated[index] = TclGetString(objPtr); } attributeStringsAllocated[index] = NULL; attributeStrings = attributeStringsAllocated; } else if (objStrings != NULL) { Tcl_Panic("must not update objPtrRef's variable and return non-NULL"); } /* * Process the attributes to produce a list of all of them, the value of a * particular attribute, or to set one or more attributes (depending on * the number of arguments). */ if (objc == 0) { /* * Get all attributes. */ int index, res = TCL_OK, nbAtts = 0; Tcl_Obj *listPtr; listPtr = Tcl_NewListObj(0, NULL); for (index = 0; attributeStrings[index] != NULL; index++) { Tcl_Obj *objPtrAttr; if (res != TCL_OK) { /* * Clear the error from the last iteration. */ Tcl_ResetResult(interp); } res = Tcl_FSFileAttrsGet(interp, index, filePtr, &objPtrAttr); if (res == TCL_OK) { Tcl_Obj *objPtr = Tcl_NewStringObj(attributeStrings[index], -1); Tcl_ListObjAppendElement(interp, listPtr, objPtr); Tcl_ListObjAppendElement(interp, listPtr, objPtrAttr); nbAtts++; } } if (index > 0 && nbAtts == 0) { /* * Error: no valid attributes found. */ Tcl_DecrRefCount(listPtr); goto end; } Tcl_SetObjResult(interp, listPtr); } else if (objc == 1) { /* * Get one attribute. */ int index; Tcl_Obj *objPtr = NULL; if (numObjStrings == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\", there are no file attributes in this" " filesystem", TclGetString(objv[0]))); Tcl_SetErrorCode(interp, "TCL","OPERATION","FATTR","NONE", NULL); goto end; } if (Tcl_GetIndexFromObj(interp, objv[0], attributeStrings, "option", 0, &index) != TCL_OK) { goto end; } if (attributeStringsAllocated != NULL) { TclFreeIntRep(objv[0]); } if (Tcl_FSFileAttrsGet(interp, index, filePtr, &objPtr) != TCL_OK) { goto end; } Tcl_SetObjResult(interp, objPtr); } else { /* * Set option/value pairs. */ int i, index; if (numObjStrings == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad option \"%s\", there are no file attributes in this" " filesystem", TclGetString(objv[0]))); Tcl_SetErrorCode(interp, "TCL","OPERATION","FATTR","NONE", NULL); goto end; } for (i = 0; i < objc ; i += 2) { if (Tcl_GetIndexFromObj(interp, objv[i], attributeStrings, "option", 0, &index) != TCL_OK) { goto end; } if (attributeStringsAllocated != NULL) { TclFreeIntRep(objv[i]); } if (i + 1 == objc) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "value for \"%s\" missing", TclGetString(objv[i]))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "FATTR", "NOVALUE", NULL); goto end; } if (Tcl_FSFileAttrsSet(interp, index, filePtr, objv[i + 1]) != TCL_OK) { goto end; } } } result = TCL_OK; /* * Free up the array we allocated and drop our reference to any list of * attribute names issued by the filesystem. */ end: if (attributeStringsAllocated != NULL) { TclStackFree(interp, (void *) attributeStringsAllocated); } if (objStrings != NULL) { Tcl_DecrRefCount(objStrings); } return result; } /* *---------------------------------------------------------------------- * * TclFileLinkCmd -- * * This function is invoked to process the "file link" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * May create a new link. * *---------------------------------------------------------------------- */ int TclFileLinkCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *contents; int index; if (objc < 2 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "?-linktype? linkname ?target?"); return TCL_ERROR; } /* * Index of the 'source' argument. */ if (objc == 4) { index = 2; } else { index = 1; } if (objc > 2) { int linkAction; if (objc == 4) { /* * We have a '-linktype' argument. */ static const char *const linkTypes[] = { "-symbolic", "-hard", NULL }; if (Tcl_GetIndexFromObj(interp, objv[1], linkTypes, "option", 0, &linkAction) != TCL_OK) { return TCL_ERROR; } if (linkAction == 0) { linkAction = TCL_CREATE_SYMBOLIC_LINK; } else { linkAction = TCL_CREATE_HARD_LINK; } } else { linkAction = TCL_CREATE_SYMBOLIC_LINK | TCL_CREATE_HARD_LINK; } if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) { return TCL_ERROR; } /* * Create link from source to target. */ contents = Tcl_FSLink(objv[index], objv[index+1], linkAction); if (contents == NULL) { /* * We handle three common error cases specially, and for all other * errors, we use the standard posix error message. */ if (errno == EEXIST) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not create new link \"%s\": that path already" " exists", TclGetString(objv[index]))); Tcl_PosixError(interp); } else if (errno == ENOENT) { /* * There are two cases here: either the target doesn't exist, * or the directory of the src doesn't exist. */ int access; Tcl_Obj *dirPtr = TclPathPart(interp, objv[index], TCL_PATH_DIRNAME); if (dirPtr == NULL) { return TCL_ERROR; } access = Tcl_FSAccess(dirPtr, F_OK); Tcl_DecrRefCount(dirPtr); if (access != 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not create new link \"%s\": no such file" " or directory", TclGetString(objv[index]))); Tcl_PosixError(interp); } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not create new link \"%s\": target \"%s\" " "doesn't exist", TclGetString(objv[index]), TclGetString(objv[index+1]))); errno = ENOENT; Tcl_PosixError(interp); } } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not create new link \"%s\" pointing to \"%s\": %s", TclGetString(objv[index]), TclGetString(objv[index+1]), Tcl_PosixError(interp))); } return TCL_ERROR; } } else { if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) { return TCL_ERROR; } /* * Read link */ contents = Tcl_FSLink(objv[index], NULL, 0); if (contents == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not read link \"%s\": %s", TclGetString(objv[index]), Tcl_PosixError(interp))); return TCL_ERROR; } } Tcl_SetObjResult(interp, contents); if (objc == 2) { /* * If we are reading a link, we need to free this result refCount. If * we are creating a link, this will just be objv[index+1], and so we * don't own it. */ Tcl_DecrRefCount(contents); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclFileReadLinkCmd -- * * This function is invoked to process the "file readlink" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclFileReadLinkCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *contents; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) { return TCL_ERROR; } contents = Tcl_FSLink(objv[1], NULL, 0); if (contents == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not read link \"%s\": %s", TclGetString(objv[1]), Tcl_PosixError(interp))); return TCL_ERROR; } Tcl_SetObjResult(interp, contents); Tcl_DecrRefCount(contents); return TCL_OK; } /* *--------------------------------------------------------------------------- * * TclFileTemporaryCmd * * This function implements the "tempfile" subcommand of the "file" * command. * * Results: * Returns a standard Tcl result. * * Side effects: * Creates a temporary file. Opens a channel to that file and puts the * name of that channel in the result. *Might* register suitable exit * handlers to ensure that the temporary file gets deleted. Might write * to a variable, so reentrancy is a potential issue. * *--------------------------------------------------------------------------- */ int TclFileTemporaryCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *nameVarObj = NULL; /* Variable to store the name of the temporary * file in. */ Tcl_Obj *nameObj = NULL; /* Object that will contain the filename. */ Tcl_Channel chan; /* The channel opened (RDWR) on the temporary * file, or NULL if there's an error. */ Tcl_Obj *tempDirObj = NULL, *tempBaseObj = NULL, *tempExtObj = NULL; /* Pieces of template. Each piece is NULL if * it is omitted. The platform temporary file * engine might ignore some pieces. */ if (objc < 1 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?nameVar? ?template?"); return TCL_ERROR; } if (objc > 1) { nameVarObj = objv[1]; TclNewObj(nameObj); } if (objc > 2) { int length; Tcl_Obj *templateObj = objv[2]; const char *string = TclGetStringFromObj(templateObj, &length); /* * Treat an empty string as if it wasn't there. */ if (length == 0) { goto makeTemporary; } /* * The template only gives a directory if there is a directory * separator in it. */ if (strchr(string, '/') != NULL || (tclPlatform == TCL_PLATFORM_WINDOWS && strchr(string, '\\') != NULL)) { tempDirObj = TclPathPart(interp, templateObj, TCL_PATH_DIRNAME); /* * Only allow creation of temporary files in the native filesystem * since they are frequently used for integration with external * tools or system libraries. [Bug 2388866] */ if (tempDirObj != NULL && Tcl_FSGetFileSystemForPath(tempDirObj) != &tclNativeFilesystem) { TclDecrRefCount(tempDirObj); tempDirObj = NULL; } } /* * The template only gives the filename if the last character isn't a * directory separator. */ if (string[length-1] != '/' && (tclPlatform != TCL_PLATFORM_WINDOWS || string[length-1] != '\\')) { Tcl_Obj *tailObj = TclPathPart(interp, templateObj, TCL_PATH_TAIL); if (tailObj != NULL) { tempBaseObj = TclPathPart(interp, tailObj, TCL_PATH_ROOT); tempExtObj = TclPathPart(interp, tailObj, TCL_PATH_EXTENSION); TclDecrRefCount(tailObj); } } } /* * Convert empty parts of the template into unspecified parts. */ if (tempDirObj && !TclGetString(tempDirObj)[0]) { TclDecrRefCount(tempDirObj); tempDirObj = NULL; } if (tempBaseObj && !TclGetString(tempBaseObj)[0]) { TclDecrRefCount(tempBaseObj); tempBaseObj = NULL; } if (tempExtObj && !TclGetString(tempExtObj)[0]) { TclDecrRefCount(tempExtObj); tempExtObj = NULL; } /* * Create and open the temporary file. */ makeTemporary: chan = TclpOpenTemporaryFile(tempDirObj,tempBaseObj,tempExtObj, nameObj); /* * If we created pieces of template, get rid of them now. */ if (tempDirObj) { TclDecrRefCount(tempDirObj); } if (tempBaseObj) { TclDecrRefCount(tempBaseObj); } if (tempExtObj) { TclDecrRefCount(tempExtObj); } /* * Deal with results. */ if (chan == NULL) { if (nameVarObj) { TclDecrRefCount(nameObj); } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create temporary file: %s", Tcl_PosixError(interp))); return TCL_ERROR; } Tcl_RegisterChannel(interp, chan); if (nameVarObj != NULL) { if (Tcl_ObjSetVar2(interp, nameVarObj, NULL, nameObj, TCL_LEAVE_ERR_MSG) == NULL) { Tcl_UnregisterChannel(interp, chan); return TCL_ERROR; } } Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetChannelName(chan), -1)); return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclThreadStorage.c0000644000175000017500000002126512663660065016614 0ustar sergeisergei/* * tclThreadStorage.c -- * * This file implements platform independent thread storage operations to * work around system limits on the number of thread-specific variables. * * Copyright (c) 2003-2004 by Joe Mistachkin * Copyright (c) 2008 by George Peter Staplin * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #ifdef TCL_THREADS #include /* * IMPLEMENTATION NOTES: * * The primary idea is that we create one platform-specific TSD slot, and use * it for storing a table pointer. Each Tcl_ThreadDataKey has an offset into * the table of TSD values. We don't use more than 1 platform-specific TSD * slot, because there is a hard limit on the number of TSD slots. Valid key * offsets are greater than 0; 0 is for the initialized Tcl_ThreadDataKey. */ /* * The master collection of information about TSDs. This is shared across the * whole process, and includes the mutex used to protect it. */ static struct TSDMaster { void *key; /* Key into the system TSD structure. The * collection of Tcl TSD values for a * particular thread will hang off the * back-end of this. */ sig_atomic_t counter; /* The number of different Tcl TSDs used * across *all* threads. This is a strictly * increasing value. */ Tcl_Mutex mutex; /* Protection for the rest of this structure, * which holds per-process data. */ } tsdMaster = { NULL, 0, NULL }; /* * The type of the data held per thread in a system TSD. */ typedef struct TSDTable { ClientData *tablePtr; /* The table of Tcl TSDs. */ sig_atomic_t allocated; /* The size of the table in the current * thread. */ } TSDTable; /* * The actual type of Tcl_ThreadDataKey. */ typedef union TSDUnion { volatile sig_atomic_t offset; /* The type is really an offset into the * thread-local table of TSDs, which is this * field. */ void *ptr; /* For alignment purposes only. Not actually * accessed through this. */ } TSDUnion; /* * Forward declarations of functions in this file. */ static TSDTable * TSDTableCreate(void); static void TSDTableDelete(TSDTable *tsdTablePtr); static void TSDTableGrow(TSDTable *tsdTablePtr, sig_atomic_t atLeast); /* * Allocator and deallocator for a TSDTable structure. */ static TSDTable * TSDTableCreate(void) { TSDTable *tsdTablePtr; sig_atomic_t i; tsdTablePtr = TclpSysAlloc(sizeof(TSDTable), 0); if (tsdTablePtr == NULL) { Tcl_Panic("unable to allocate TSDTable"); } tsdTablePtr->allocated = 8; tsdTablePtr->tablePtr = TclpSysAlloc(sizeof(void *) * tsdTablePtr->allocated, 0); if (tsdTablePtr->tablePtr == NULL) { Tcl_Panic("unable to allocate TSDTable"); } for (i = 0; i < tsdTablePtr->allocated; ++i) { tsdTablePtr->tablePtr[i] = NULL; } return tsdTablePtr; } static void TSDTableDelete( TSDTable *tsdTablePtr) { sig_atomic_t i; for (i=0 ; iallocated ; i++) { if (tsdTablePtr->tablePtr[i] != NULL) { /* * These values were allocated in Tcl_GetThreadData in tclThread.c * and must now be deallocated or they will leak. */ ckfree(tsdTablePtr->tablePtr[i]); } } TclpSysFree(tsdTablePtr->tablePtr); TclpSysFree(tsdTablePtr); } /* *---------------------------------------------------------------------- * * TSDTableGrow -- * * This procedure makes the passed TSDTable grow to fit the atLeast * value. * * Results: * None. * * Side effects: * The table is enlarged. * *---------------------------------------------------------------------- */ static void TSDTableGrow( TSDTable *tsdTablePtr, sig_atomic_t atLeast) { sig_atomic_t newAllocated = tsdTablePtr->allocated * 2; ClientData *newTablePtr; sig_atomic_t i; if (newAllocated <= atLeast) { newAllocated = atLeast + 10; } newTablePtr = TclpSysRealloc(tsdTablePtr->tablePtr, sizeof(ClientData) * newAllocated); if (newTablePtr == NULL) { Tcl_Panic("unable to reallocate TSDTable"); } for (i = tsdTablePtr->allocated; i < newAllocated; ++i) { newTablePtr[i] = NULL; } tsdTablePtr->allocated = newAllocated; tsdTablePtr->tablePtr = newTablePtr; } /* *---------------------------------------------------------------------- * * TclThreadStorageKeyGet -- * * This procedure gets the value associated with the passed key. * * Results: * A pointer value associated with the Tcl_ThreadDataKey or NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ void * TclThreadStorageKeyGet( Tcl_ThreadDataKey *dataKeyPtr) { TSDTable *tsdTablePtr = TclpThreadGetMasterTSD(tsdMaster.key); ClientData resultPtr = NULL; TSDUnion *keyPtr = (TSDUnion *) dataKeyPtr; sig_atomic_t offset = keyPtr->offset; if ((tsdTablePtr != NULL) && (offset > 0) && (offset < tsdTablePtr->allocated)) { resultPtr = tsdTablePtr->tablePtr[offset]; } return resultPtr; } /* *---------------------------------------------------------------------- * * TclThreadStorageKeySet -- * * This procedure set an association of value with the key passed. The * associated value may be retrieved with TclThreadDataKeyGet(). * * Results: * None. * * Side effects: * The thread-specific table may be created or reallocated. * *---------------------------------------------------------------------- */ void TclThreadStorageKeySet( Tcl_ThreadDataKey *dataKeyPtr, void *value) { TSDTable *tsdTablePtr = TclpThreadGetMasterTSD(tsdMaster.key); TSDUnion *keyPtr = (TSDUnion *) dataKeyPtr; if (tsdTablePtr == NULL) { tsdTablePtr = TSDTableCreate(); TclpThreadSetMasterTSD(tsdMaster.key, tsdTablePtr); } /* * Get the lock while we check if this TSD is new or not. Note that this * is the only place where Tcl_ThreadDataKey values are set. We use a * double-checked lock to try to avoid having to grab this lock a lot, * since it is on quite a few critical paths and will only get set once in * each location. */ if (keyPtr->offset == 0) { Tcl_MutexLock(&tsdMaster.mutex); if (keyPtr->offset == 0) { /* * The Tcl_ThreadDataKey hasn't been used yet. Make a new one. */ keyPtr->offset = ++tsdMaster.counter; } Tcl_MutexUnlock(&tsdMaster.mutex); } /* * Check if this is the first time this Tcl_ThreadDataKey has been used * with the current thread. Note that we don't need to hold a lock when * doing this, as we are *definitely* the only point accessing this * tsdTablePtr right now; it's thread-local. */ if (keyPtr->offset >= tsdTablePtr->allocated) { TSDTableGrow(tsdTablePtr, keyPtr->offset); } /* * Set the value in the Tcl thread-local variable. */ tsdTablePtr->tablePtr[keyPtr->offset] = value; } /* *---------------------------------------------------------------------- * * TclFinalizeThreadDataThread -- * * This procedure finalizes the data for a single thread. * * Results: * None. * * Side effects: * The TSDTable is deleted/freed. * *---------------------------------------------------------------------- */ void TclFinalizeThreadDataThread(void) { TSDTable *tsdTablePtr = TclpThreadGetMasterTSD(tsdMaster.key); if (tsdTablePtr != NULL) { TSDTableDelete(tsdTablePtr); TclpThreadSetMasterTSD(tsdMaster.key, NULL); } } /* *---------------------------------------------------------------------- * * TclInitializeThreadStorage -- * * This procedure initializes the TSD subsystem with per-platform code. * This should be called before any Tcl threads are created. * * Results: * None. * * Side effects: * Allocates a system TSD. * *---------------------------------------------------------------------- */ void TclInitThreadStorage(void) { tsdMaster.key = TclpThreadCreateKey(); } /* *---------------------------------------------------------------------- * * TclFinalizeThreadStorage -- * * This procedure cleans up the thread storage data key for all threads. * IMPORTANT: All Tcl threads must be finalized before calling this! * * Results: * None. * * Side effects: * Releases the thread data key. * *---------------------------------------------------------------------- */ void TclFinalizeThreadStorage(void) { TclpThreadDeleteKey(tsdMaster.key); tsdMaster.key = NULL; } #else /* !TCL_THREADS */ /* * Stub functions for non-threaded builds */ void TclInitThreadStorage(void) { } void TclFinalizeThreadDataThread(void) { } void TclFinalizeThreadStorage(void) { } #endif /* TCL_THREADS */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/regc_nfa.c0000644000175000017500000024445712663660065015133 0ustar sergeisergei/* * NFA utilities. * This file is #included by regcomp.c. * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * One or two things that technically ought to be in here are actually in * color.c, thanks to some incestuous relationships in the color chains. */ #define NISERR() VISERR(nfa->v) #define NERR(e) VERR(nfa->v, (e)) #define STACK_TOO_DEEP(x) (0) #define CANCEL_REQUESTED(x) (0) #define REG_CANCEL 777 /* - newnfa - set up an NFA ^ static struct nfa *newnfa(struct vars *, struct colormap *, struct nfa *); */ static struct nfa * /* the NFA, or NULL */ newnfa( struct vars *v, struct colormap *cm, struct nfa *parent) /* NULL if primary NFA */ { struct nfa *nfa; nfa = (struct nfa *) MALLOC(sizeof(struct nfa)); if (nfa == NULL) { ERR(REG_ESPACE); return NULL; } nfa->states = NULL; nfa->slast = NULL; nfa->free = NULL; nfa->nstates = 0; nfa->cm = cm; nfa->v = v; nfa->bos[0] = nfa->bos[1] = COLORLESS; nfa->eos[0] = nfa->eos[1] = COLORLESS; nfa->parent = parent; /* Precedes newfstate so parent is valid. */ nfa->post = newfstate(nfa, '@'); /* number 0 */ nfa->pre = newfstate(nfa, '>'); /* number 1 */ nfa->init = newstate(nfa); /* May become invalid later. */ nfa->final = newstate(nfa); if (ISERR()) { freenfa(nfa); return NULL; } rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->pre, nfa->init); newarc(nfa, '^', 1, nfa->pre, nfa->init); newarc(nfa, '^', 0, nfa->pre, nfa->init); rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->final, nfa->post); newarc(nfa, '$', 1, nfa->final, nfa->post); newarc(nfa, '$', 0, nfa->final, nfa->post); if (ISERR()) { freenfa(nfa); return NULL; } return nfa; } /* - freenfa - free an entire NFA ^ static void freenfa(struct nfa *); */ static void freenfa( struct nfa *nfa) { struct state *s; while ((s = nfa->states) != NULL) { s->nins = s->nouts = 0; /* don't worry about arcs */ freestate(nfa, s); } while ((s = nfa->free) != NULL) { nfa->free = s->next; destroystate(nfa, s); } nfa->slast = NULL; nfa->nstates = -1; nfa->pre = NULL; nfa->post = NULL; FREE(nfa); } /* - newstate - allocate an NFA state, with zero flag value ^ static struct state *newstate(struct nfa *); */ static struct state * /* NULL on error */ newstate( struct nfa *nfa) { struct state *s; if (nfa->free != NULL) { s = nfa->free; nfa->free = s->next; } else { if (nfa->v->spaceused >= REG_MAX_COMPILE_SPACE) { NERR(REG_ETOOBIG); return NULL; } s = (struct state *) MALLOC(sizeof(struct state)); if (s == NULL) { NERR(REG_ESPACE); return NULL; } nfa->v->spaceused += sizeof(struct state); s->oas.next = NULL; s->free = NULL; s->noas = 0; } assert(nfa->nstates >= 0); s->no = nfa->nstates++; s->flag = 0; if (nfa->states == NULL) { nfa->states = s; } s->nins = 0; s->ins = NULL; s->nouts = 0; s->outs = NULL; s->tmp = NULL; s->next = NULL; if (nfa->slast != NULL) { assert(nfa->slast->next == NULL); nfa->slast->next = s; } s->prev = nfa->slast; nfa->slast = s; return s; } /* - newfstate - allocate an NFA state with a specified flag value ^ static struct state *newfstate(struct nfa *, int flag); */ static struct state * /* NULL on error */ newfstate( struct nfa *nfa, int flag) { struct state *s; s = newstate(nfa); if (s != NULL) { s->flag = (char) flag; } return s; } /* - dropstate - delete a state's inarcs and outarcs and free it ^ static void dropstate(struct nfa *, struct state *); */ static void dropstate( struct nfa *nfa, struct state *s) { struct arc *a; while ((a = s->ins) != NULL) { freearc(nfa, a); } while ((a = s->outs) != NULL) { freearc(nfa, a); } freestate(nfa, s); } /* - freestate - free a state, which has no in-arcs or out-arcs ^ static void freestate(struct nfa *, struct state *); */ static void freestate( struct nfa *nfa, struct state *s) { assert(s != NULL); assert(s->nins == 0 && s->nouts == 0); s->no = FREESTATE; s->flag = 0; if (s->next != NULL) { s->next->prev = s->prev; } else { assert(s == nfa->slast); nfa->slast = s->prev; } if (s->prev != NULL) { s->prev->next = s->next; } else { assert(s == nfa->states); nfa->states = s->next; } s->prev = NULL; s->next = nfa->free; /* don't delete it, put it on the free list */ nfa->free = s; } /* - destroystate - really get rid of an already-freed state ^ static void destroystate(struct nfa *, struct state *); */ static void destroystate( struct nfa *nfa, struct state *s) { struct arcbatch *ab; struct arcbatch *abnext; assert(s->no == FREESTATE); for (ab=s->oas.next ; ab!=NULL ; ab=abnext) { abnext = ab->next; FREE(ab); nfa->v->spaceused -= sizeof(struct arcbatch); } s->ins = NULL; s->outs = NULL; s->next = NULL; FREE(s); nfa->v->spaceused -= sizeof(struct state); } /* - newarc - set up a new arc within an NFA ^ static void newarc(struct nfa *, int, pcolor, struct state *, ^ struct state *); */ /* * This function checks to make sure that no duplicate arcs are created. * In general we never want duplicates. */ static void newarc( struct nfa *nfa, int t, pcolor co, struct state *from, struct state *to) { struct arc *a; assert(from != NULL && to != NULL); /* check for duplicate arc, using whichever chain is shorter */ if (from->nouts <= to->nins) { for (a = from->outs; a != NULL; a = a->outchain) { if (a->to == to && a->co == co && a->type == t) { return; } } } else { for (a = to->ins; a != NULL; a = a->inchain) { if (a->from == from && a->co == co && a->type == t) { return; } } } /* no dup, so create the arc */ createarc(nfa, t, co, from, to); } /* * createarc - create a new arc within an NFA * * This function must *only* be used after verifying that there is no existing * identical arc (same type/color/from/to). */ static void createarc( struct nfa * nfa, int t, pcolor co, struct state * from, struct state * to) { struct arc *a; /* the arc is physically allocated within its from-state */ a = allocarc(nfa, from); if (NISERR()) { return; } assert(a != NULL); a->type = t; a->co = (color) co; a->to = to; a->from = from; /* * Put the new arc on the beginning, not the end, of the chains; it's * simpler here, and freearc() is the same cost either way. See also the * logic in moveins() and its cohorts, as well as fixempties(). */ a->inchain = to->ins; a->inchainRev = NULL; if (to->ins) { to->ins->inchainRev = a; } to->ins = a; a->outchain = from->outs; a->outchainRev = NULL; if (from->outs) { from->outs->outchainRev = a; } from->outs = a; from->nouts++; to->nins++; if (COLORED(a) && nfa->parent == NULL) { colorchain(nfa->cm, a); } } /* - allocarc - allocate a new out-arc within a state ^ static struct arc *allocarc(struct nfa *, struct state *); */ static struct arc * /* NULL for failure */ allocarc( struct nfa *nfa, struct state *s) { struct arc *a; /* * Shortcut */ if (s->free == NULL && s->noas < ABSIZE) { a = &s->oas.a[s->noas]; s->noas++; return a; } /* * if none at hand, get more */ if (s->free == NULL) { struct arcbatch *newAb; int i; if (nfa->v->spaceused >= REG_MAX_COMPILE_SPACE) { NERR(REG_ETOOBIG); return NULL; } newAb = (struct arcbatch *) MALLOC(sizeof(struct arcbatch)); if (newAb == NULL) { NERR(REG_ESPACE); return NULL; } nfa->v->spaceused += sizeof(struct arcbatch); newAb->next = s->oas.next; s->oas.next = newAb; for (i=0 ; ia[i].type = 0; newAb->a[i].freechain = &newAb->a[i+1]; } newAb->a[ABSIZE-1].freechain = NULL; s->free = &newAb->a[0]; } assert(s->free != NULL); a = s->free; s->free = a->freechain; return a; } /* - freearc - free an arc ^ static void freearc(struct nfa *, struct arc *); */ static void freearc( struct nfa *nfa, struct arc *victim) { struct state *from = victim->from; struct state *to = victim->to; struct arc *predecessor; assert(victim->type != 0); /* * Take it off color chain if necessary. */ if (COLORED(victim) && nfa->parent == NULL) { uncolorchain(nfa->cm, victim); } /* * Take it off source's out-chain. */ assert(from != NULL); predecessor = victim->outchainRev; if (predecessor == NULL) { assert(from->outs == victim); from->outs = victim->outchain; } else { assert(predecessor->outchain == victim); predecessor->outchain = victim->outchain; } if (victim->outchain != NULL) { assert(victim->outchain->outchainRev == victim); victim->outchain->outchainRev = predecessor; } from->nouts--; /* * Take it off target's in-chain. */ assert(to != NULL); predecessor = victim->inchainRev; if (predecessor == NULL) { assert(to->ins == victim); to->ins = victim->inchain; } else { assert(predecessor->inchain == victim); predecessor->inchain = victim->inchain; } if (victim->inchain != NULL) { assert(victim->inchain->inchainRev == victim); victim->inchain->inchainRev = predecessor; } to->nins--; /* * Clean up and place on from-state's free list. */ victim->type = 0; victim->from = NULL; /* precautions... */ victim->to = NULL; victim->inchain = NULL; victim->inchainRev = NULL; victim->outchain = NULL; victim->outchainRev = NULL; victim->freechain = from->free; from->free = victim; } /* * changearctarget - flip an arc to have a different to state * * Caller must have verified that there is no pre-existing duplicate arc. * * Note that because we store arcs in their from state, we can't easily have * a similar changearcsource function. */ static void changearctarget(struct arc * a, struct state * newto) { struct state *oldto = a->to; struct arc *predecessor; assert(oldto != newto); /* take it off old target's in-chain */ assert(oldto != NULL); predecessor = a->inchainRev; if (predecessor == NULL) { assert(oldto->ins == a); oldto->ins = a->inchain; } else { assert(predecessor->inchain == a); predecessor->inchain = a->inchain; } if (a->inchain != NULL) { assert(a->inchain->inchainRev == a); a->inchain->inchainRev = predecessor; } oldto->nins--; a->to = newto; /* prepend it to new target's in-chain */ a->inchain = newto->ins; a->inchainRev = NULL; if (newto->ins) { newto->ins->inchainRev = a; } newto->ins = a; newto->nins++; } /* - hasnonemptyout - Does state have a non-EMPTY out arc? ^ static int hasnonemptyout(struct state *); */ static int hasnonemptyout( struct state *s) { struct arc *a; for (a = s->outs; a != NULL; a = a->outchain) { if (a->type != EMPTY) { return 1; } } return 0; } /* - findarc - find arc, if any, from given source with given type and color * If there is more than one such arc, the result is random. ^ static struct arc *findarc(struct state *, int, pcolor); */ static struct arc * findarc( struct state *s, int type, pcolor co) { struct arc *a; for (a=s->outs ; a!=NULL ; a=a->outchain) { if (a->type == type && a->co == co) { return a; } } return NULL; } /* - cparc - allocate a new arc within an NFA, copying details from old one ^ static void cparc(struct nfa *, struct arc *, struct state *, ^ struct state *); */ static void cparc( struct nfa *nfa, struct arc *oa, struct state *from, struct state *to) { newarc(nfa, oa->type, oa->co, from, to); } /* * sortins - sort the in arcs of a state by from/color/type */ static void sortins( struct nfa * nfa, struct state * s) { struct arc **sortarray; struct arc *a; int n = s->nins; int i; if (n <= 1) { return; /* nothing to do */ } /* make an array of arc pointers ... */ sortarray = (struct arc **) MALLOC(n * sizeof(struct arc *)); if (sortarray == NULL) { NERR(REG_ESPACE); return; } i = 0; for (a = s->ins; a != NULL; a = a->inchain) { sortarray[i++] = a; } assert(i == n); /* ... sort the array */ qsort(sortarray, n, sizeof(struct arc *), sortins_cmp); /* ... and rebuild arc list in order */ /* it seems worth special-casing first and last items to simplify loop */ a = sortarray[0]; s->ins = a; a->inchain = sortarray[1]; a->inchainRev = NULL; for (i = 1; i < n - 1; i++) { a = sortarray[i]; a->inchain = sortarray[i + 1]; a->inchainRev = sortarray[i - 1]; } a = sortarray[i]; a->inchain = NULL; a->inchainRev = sortarray[i - 1]; FREE(sortarray); } static int sortins_cmp( const void *a, const void *b) { const struct arc *aa = *((const struct arc * const *) a); const struct arc *bb = *((const struct arc * const *) b); /* we check the fields in the order they are most likely to be different */ if (aa->from->no < bb->from->no) { return -1; } if (aa->from->no > bb->from->no) { return 1; } if (aa->co < bb->co) { return -1; } if (aa->co > bb->co) { return 1; } if (aa->type < bb->type) { return -1; } if (aa->type > bb->type) { return 1; } return 0; } /* * sortouts - sort the out arcs of a state by to/color/type */ static void sortouts( struct nfa * nfa, struct state * s) { struct arc **sortarray; struct arc *a; int n = s->nouts; int i; if (n <= 1) { return; /* nothing to do */ } /* make an array of arc pointers ... */ sortarray = (struct arc **) MALLOC(n * sizeof(struct arc *)); if (sortarray == NULL) { NERR(REG_ESPACE); return; } i = 0; for (a = s->outs; a != NULL; a = a->outchain) { sortarray[i++] = a; } assert(i == n); /* ... sort the array */ qsort(sortarray, n, sizeof(struct arc *), sortouts_cmp); /* ... and rebuild arc list in order */ /* it seems worth special-casing first and last items to simplify loop */ a = sortarray[0]; s->outs = a; a->outchain = sortarray[1]; a->outchainRev = NULL; for (i = 1; i < n - 1; i++) { a = sortarray[i]; a->outchain = sortarray[i + 1]; a->outchainRev = sortarray[i - 1]; } a = sortarray[i]; a->outchain = NULL; a->outchainRev = sortarray[i - 1]; FREE(sortarray); } static int sortouts_cmp( const void *a, const void *b) { const struct arc *aa = *((const struct arc * const *) a); const struct arc *bb = *((const struct arc * const *) b); /* we check the fields in the order they are most likely to be different */ if (aa->to->no < bb->to->no) { return -1; } if (aa->to->no > bb->to->no) { return 1; } if (aa->co < bb->co) { return -1; } if (aa->co > bb->co) { return 1; } if (aa->type < bb->type) { return -1; } if (aa->type > bb->type) { return 1; } return 0; } /* * Common decision logic about whether to use arc-by-arc operations or * sort/merge. If there's just a few source arcs we cannot recoup the * cost of sorting the destination arc list, no matter how large it is. * Otherwise, limit the number of arc-by-arc comparisons to about 1000 * (a somewhat arbitrary choice, but the breakeven point would probably * be machine dependent anyway). */ #define BULK_ARC_OP_USE_SORT(nsrcarcs, ndestarcs) \ ((nsrcarcs) < 4 ? 0 : ((nsrcarcs) > 32 || (ndestarcs) > 32)) /* - moveins - move all in arcs of a state to another state * You might think this could be done better by just updating the * existing arcs, and you would be right if it weren't for the need * for duplicate suppression, which makes it easier to just make new * ones to exploit the suppression built into newarc. * * However, if we have a whole lot of arcs to deal with, retail duplicate * checks become too slow. In that case we proceed by sorting and merging * the arc lists, and then we can indeed just update the arcs in-place. * ^ static void moveins(struct nfa *, struct state *, struct state *); */ static void moveins( struct nfa *nfa, struct state *oldState, struct state *newState) { assert(oldState != newState); if (!BULK_ARC_OP_USE_SORT(oldState->nins, newState->nins)) { /* With not too many arcs, just do them one at a time */ struct arc *a; while ((a = oldState->ins) != NULL) { cparc(nfa, a, a->from, newState); freearc(nfa, a); } } else { /* * With many arcs, use a sort-merge approach. Note changearctarget() * will put the arc onto the front of newState's chain, so it does not * break our walk through the sorted part of the chain. */ struct arc *oa; struct arc *na; /* * Because we bypass newarc() in this code path, we'd better include a * cancel check. */ if (CANCEL_REQUESTED(nfa->v->re)) { NERR(REG_CANCEL); return; } sortins(nfa, oldState); sortins(nfa, newState); if (NISERR()) { return; /* might have failed to sort */ } oa = oldState->ins; na = newState->ins; while (oa != NULL && na != NULL) { struct arc *a = oa; switch (sortins_cmp(&oa, &na)) { case -1: /* newState does not have anything matching oa */ oa = oa->inchain; /* * Rather than doing createarc+freearc, we can just unlink * and relink the existing arc struct. */ changearctarget(a, newState); break; case 0: /* match, advance in both lists */ oa = oa->inchain; na = na->inchain; /* ... and drop duplicate arc from oldState */ freearc(nfa, a); break; case +1: /* advance only na; oa might have a match later */ na = na->inchain; break; default: assert(NOTREACHED); } } while (oa != NULL) { /* newState does not have anything matching oa */ struct arc *a = oa; oa = oa->inchain; changearctarget(a, newState); } } assert(oldState->nins == 0); assert(oldState->ins == NULL); } /* - copyins - copy in arcs of a state to another state ^ static VOID copyins(struct nfa *, struct state *, struct state *, int); */ static void copyins( struct nfa *nfa, struct state *oldState, struct state *newState) { assert(oldState != newState); if (!BULK_ARC_OP_USE_SORT(oldState->nins, newState->nins)) { /* With not too many arcs, just do them one at a time */ struct arc *a; for (a = oldState->ins; a != NULL; a = a->inchain) { cparc(nfa, a, a->from, newState); } } else { /* * With many arcs, use a sort-merge approach. Note that createarc() * will put new arcs onto the front of newState's chain, so it does * not break our walk through the sorted part of the chain. */ struct arc *oa; struct arc *na; /* * Because we bypass newarc() in this code path, we'd better include a * cancel check. */ if (CANCEL_REQUESTED(nfa->v->re)) { NERR(REG_CANCEL); return; } sortins(nfa, oldState); sortins(nfa, newState); if (NISERR()) { return; /* might have failed to sort */ } oa = oldState->ins; na = newState->ins; while (oa != NULL && na != NULL) { struct arc *a = oa; switch (sortins_cmp(&oa, &na)) { case -1: /* newState does not have anything matching oa */ oa = oa->inchain; createarc(nfa, a->type, a->co, a->from, newState); break; case 0: /* match, advance in both lists */ oa = oa->inchain; na = na->inchain; break; case +1: /* advance only na; oa might have a match later */ na = na->inchain; break; default: assert(NOTREACHED); } } while (oa != NULL) { /* newState does not have anything matching oa */ struct arc *a = oa; oa = oa->inchain; createarc(nfa, a->type, a->co, a->from, newState); } } } /* * mergeins - merge a list of inarcs into a state * * This is much like copyins, but the source arcs are listed in an array, * and are not guaranteed unique. It's okay to clobber the array contents. */ static void mergeins( struct nfa * nfa, struct state * s, struct arc ** arcarray, int arccount) { struct arc *na; int i; int j; if (arccount <= 0) { return; } /* * Because we bypass newarc() in this code path, we'd better include a * cancel check. */ if (CANCEL_REQUESTED(nfa->v->re)) { NERR(REG_CANCEL); return; } /* Sort existing inarcs as well as proposed new ones */ sortins(nfa, s); if (NISERR()) { return; /* might have failed to sort */ } qsort(arcarray, arccount, sizeof(struct arc *), sortins_cmp); /* * arcarray very likely includes dups, so we must eliminate them. (This * could be folded into the next loop, but it's not worth the trouble.) */ j = 0; for (i = 1; i < arccount; i++) { switch (sortins_cmp(&arcarray[j], &arcarray[i])) { case -1: /* non-dup */ arcarray[++j] = arcarray[i]; break; case 0: /* dup */ break; default: /* trouble */ assert(NOTREACHED); } } arccount = j + 1; /* * Now merge into s' inchain. Note that createarc() will put new arcs * onto the front of s's chain, so it does not break our walk through the * sorted part of the chain. */ i = 0; na = s->ins; while (i < arccount && na != NULL) { struct arc *a = arcarray[i]; switch (sortins_cmp(&a, &na)) { case -1: /* s does not have anything matching a */ createarc(nfa, a->type, a->co, a->from, s); i++; break; case 0: /* match, advance in both lists */ i++; na = na->inchain; break; case +1: /* advance only na; array might have a match later */ na = na->inchain; break; default: assert(NOTREACHED); } } while (i < arccount) { /* s does not have anything matching a */ struct arc *a = arcarray[i]; createarc(nfa, a->type, a->co, a->from, s); i++; } } /* - moveouts - move all out arcs of a state to another state ^ static void moveouts(struct nfa *, struct state *, struct state *); */ static void moveouts( struct nfa *nfa, struct state *oldState, struct state *newState) { assert(oldState != newState); if (!BULK_ARC_OP_USE_SORT(oldState->nouts, newState->nouts)) { /* With not too many arcs, just do them one at a time */ struct arc *a; while ((a = oldState->outs) != NULL) { cparc(nfa, a, newState, a->to); freearc(nfa, a); } } else { /* * With many arcs, use a sort-merge approach. Note that createarc() * will put new arcs onto the front of newState's chain, so it does * not break our walk through the sorted part of the chain. */ struct arc *oa; struct arc *na; /* * Because we bypass newarc() in this code path, we'd better include a * cancel check. */ if (CANCEL_REQUESTED(nfa->v->re)) { NERR(REG_CANCEL); return; } sortouts(nfa, oldState); sortouts(nfa, newState); if (NISERR()) { return; /* might have failed to sort */ } oa = oldState->outs; na = newState->outs; while (oa != NULL && na != NULL) { struct arc *a = oa; switch (sortouts_cmp(&oa, &na)) { case -1: /* newState does not have anything matching oa */ oa = oa->outchain; createarc(nfa, a->type, a->co, newState, a->to); freearc(nfa, a); break; case 0: /* match, advance in both lists */ oa = oa->outchain; na = na->outchain; /* ... and drop duplicate arc from oldState */ freearc(nfa, a); break; case +1: /* advance only na; oa might have a match later */ na = na->outchain; break; default: assert(NOTREACHED); } } while (oa != NULL) { /* newState does not have anything matching oa */ struct arc *a = oa; oa = oa->outchain; createarc(nfa, a->type, a->co, newState, a->to); freearc(nfa, a); } } assert(oldState->nouts == 0); assert(oldState->outs == NULL); } /* - copyouts - copy out arcs of a state to another state ^ static VOID copyouts(struct nfa *, struct state *, struct state *, int); */ static void copyouts( struct nfa *nfa, struct state *oldState, struct state *newState) { assert(oldState != newState); if (!BULK_ARC_OP_USE_SORT(oldState->nouts, newState->nouts)) { /* With not too many arcs, just do them one at a time */ struct arc *a; for (a = oldState->outs; a != NULL; a = a->outchain) { cparc(nfa, a, newState, a->to); } } else { /* * With many arcs, use a sort-merge approach. Note that createarc() * will put new arcs onto the front of newState's chain, so it does * not break our walk through the sorted part of the chain. */ struct arc *oa; struct arc *na; /* * Because we bypass newarc() in this code path, we'd better include a * cancel check. */ if (CANCEL_REQUESTED(nfa->v->re)) { NERR(REG_CANCEL); return; } sortouts(nfa, oldState); sortouts(nfa, newState); if (NISERR()) { return; /* might have failed to sort */ } oa = oldState->outs; na = newState->outs; while (oa != NULL && na != NULL) { struct arc *a = oa; switch (sortouts_cmp(&oa, &na)) { case -1: /* newState does not have anything matching oa */ oa = oa->outchain; createarc(nfa, a->type, a->co, newState, a->to); break; case 0: /* match, advance in both lists */ oa = oa->outchain; na = na->outchain; break; case +1: /* advance only na; oa might have a match later */ na = na->outchain; break; default: assert(NOTREACHED); } } while (oa != NULL) { /* newState does not have anything matching oa */ struct arc *a = oa; oa = oa->outchain; createarc(nfa, a->type, a->co, newState, a->to); } } } /* - cloneouts - copy out arcs of a state to another state pair, modifying type ^ static void cloneouts(struct nfa *, struct state *, struct state *, ^ struct state *, int); */ static void cloneouts( struct nfa *nfa, struct state *old, struct state *from, struct state *to, int type) { struct arc *a; assert(old != from); for (a=old->outs ; a!=NULL ; a=a->outchain) { newarc(nfa, type, a->co, from, to); } } /* - delsub - delete a sub-NFA, updating subre pointers if necessary * This uses a recursive traversal of the sub-NFA, marking already-seen * states using their tmp pointer. ^ static void delsub(struct nfa *, struct state *, struct state *); */ static void delsub( struct nfa *nfa, struct state *lp, /* the sub-NFA goes from here... */ struct state *rp) /* ...to here, *not* inclusive */ { assert(lp != rp); rp->tmp = rp; /* mark end */ deltraverse(nfa, lp, lp); assert(lp->nouts == 0 && rp->nins == 0); /* did the job */ assert(lp->no != FREESTATE && rp->no != FREESTATE); /* no more */ rp->tmp = NULL; /* unmark end */ lp->tmp = NULL; /* and begin, marked by deltraverse */ } /* - deltraverse - the recursive heart of delsub * This routine's basic job is to destroy all out-arcs of the state. ^ static void deltraverse(struct nfa *, struct state *, struct state *); */ static void deltraverse( struct nfa *nfa, struct state *leftend, struct state *s) { struct arc *a; struct state *to; if (s->nouts == 0) { return; /* nothing to do */ } if (s->tmp != NULL) { return; /* already in progress */ } s->tmp = s; /* mark as in progress */ while ((a = s->outs) != NULL) { to = a->to; deltraverse(nfa, leftend, to); assert(to->nouts == 0 || to->tmp != NULL); freearc(nfa, a); if (to->nins == 0 && to->tmp == NULL) { assert(to->nouts == 0); freestate(nfa, to); } } assert(s->no != FREESTATE); /* we're still here */ assert(s == leftend || s->nins != 0); /* and still reachable */ assert(s->nouts == 0); /* but have no outarcs */ s->tmp = NULL; /* we're done here */ } /* - dupnfa - duplicate sub-NFA * Another recursive traversal, this time using tmp to point to duplicates as * well as mark already-seen states. (You knew there was a reason why it's a * state pointer, didn't you? :-)) ^ static void dupnfa(struct nfa *, struct state *, struct state *, ^ struct state *, struct state *); */ static void dupnfa( struct nfa *nfa, struct state *start, /* duplicate of subNFA starting here */ struct state *stop, /* and stopping here */ struct state *from, /* stringing duplicate from here */ struct state *to) /* to here */ { if (start == stop) { newarc(nfa, EMPTY, 0, from, to); return; } stop->tmp = to; duptraverse(nfa, start, from, 0); /* done, except for clearing out the tmp pointers */ stop->tmp = NULL; cleartraverse(nfa, start); } /* - duptraverse - recursive heart of dupnfa ^ static void duptraverse(struct nfa *, struct state *, struct state *); */ static void duptraverse( struct nfa *nfa, struct state *s, struct state *stmp, /* s's duplicate, or NULL */ int depth) { struct arc *a; if (s->tmp != NULL) { return; /* already done */ } s->tmp = (stmp == NULL) ? newstate(nfa) : stmp; if (s->tmp == NULL) { assert(NISERR()); return; } /* * Arbitrary depth limit. Needs tuning, but this value is sufficient to * make all normal tests (not reg-33.14) pass. */ #ifndef DUPTRAVERSE_MAX_DEPTH #define DUPTRAVERSE_MAX_DEPTH 15000 #endif if (depth++ > DUPTRAVERSE_MAX_DEPTH) { NERR(REG_ESPACE); } for (a=s->outs ; a!=NULL && !NISERR() ; a=a->outchain) { duptraverse(nfa, a->to, NULL, depth); if (NISERR()) { break; } assert(a->to->tmp != NULL); cparc(nfa, a, s->tmp, a->to->tmp); } } /* - cleartraverse - recursive cleanup for algorithms that leave tmp ptrs set ^ static void cleartraverse(struct nfa *, struct state *); */ static void cleartraverse( struct nfa *nfa, struct state *s) { struct arc *a; if (s->tmp == NULL) { return; } s->tmp = NULL; for (a=s->outs ; a!=NULL ; a=a->outchain) { cleartraverse(nfa, a->to); } } /* - specialcolors - fill in special colors for an NFA ^ static void specialcolors(struct nfa *); */ static void specialcolors( struct nfa *nfa) { /* * False colors for BOS, BOL, EOS, EOL */ if (nfa->parent == NULL) { nfa->bos[0] = pseudocolor(nfa->cm); nfa->bos[1] = pseudocolor(nfa->cm); nfa->eos[0] = pseudocolor(nfa->cm); nfa->eos[1] = pseudocolor(nfa->cm); } else { assert(nfa->parent->bos[0] != COLORLESS); nfa->bos[0] = nfa->parent->bos[0]; assert(nfa->parent->bos[1] != COLORLESS); nfa->bos[1] = nfa->parent->bos[1]; assert(nfa->parent->eos[0] != COLORLESS); nfa->eos[0] = nfa->parent->eos[0]; assert(nfa->parent->eos[1] != COLORLESS); nfa->eos[1] = nfa->parent->eos[1]; } } /* - optimize - optimize an NFA ^ static long optimize(struct nfa *, FILE *); */ /* * The main goal of this function is not so much "optimization" (though it * does try to get rid of useless NFA states) as reducing the NFA to a form * the regex executor can handle. The executor, and indeed the cNFA format * that is its input, can only handle PLAIN and LACON arcs. The output of * the regex parser also includes EMPTY (do-nothing) arcs, as well as * ^, $, AHEAD, and BEHIND constraint arcs, which we must get rid of here. * We first get rid of EMPTY arcs and then deal with the constraint arcs. * The hardest part of either job is to get rid of circular loops of the * target arc type. We would have to do that in any case, though, as such a * loop would otherwise allow the executor to cycle through the loop endlessly * without making any progress in the input string. */ static long /* re_info bits */ optimize( struct nfa *nfa, FILE *f) /* for debug output; NULL none */ { int verbose = (f != NULL) ? 1 : 0; if (verbose) { fprintf(f, "\ninitial cleanup:\n"); } cleanup(nfa); /* may simplify situation */ if (verbose) { dumpnfa(nfa, f); } if (verbose) { fprintf(f, "\nempties:\n"); } fixempties(nfa, f); /* get rid of EMPTY arcs */ if (verbose) { fprintf(f, "\nconstraints:\n"); } fixconstraintloops(nfa, f); /* get rid of constraint loops */ pullback(nfa, f); /* pull back constraints backward */ pushfwd(nfa, f); /* push fwd constraints forward */ if (verbose) { fprintf(f, "\nfinal cleanup:\n"); } cleanup(nfa); /* final tidying */ #ifdef REG_DEBUG if (verbose) { dumpnfa(nfa, f); } #endif return analyze(nfa); /* and analysis */ } /* - pullback - pull back constraints backward to eliminate them ^ static void pullback(struct nfa *, FILE *); */ static void pullback( struct nfa *nfa, FILE *f) /* for debug output; NULL none */ { struct state *s; struct state *nexts; struct arc *a; struct arc *nexta; struct state *intermediates; int progress; /* * Find and pull until there are no more. */ do { progress = 0; for (s=nfa->states ; s!=NULL && !NISERR() ; s=nexts) { nexts = s->next; intermediates = NULL; for (a=s->outs ; a!=NULL && !NISERR() ; a=nexta) { nexta = a->outchain; if (a->type == '^' || a->type == BEHIND) { if (pull(nfa, a, &intermediates)) { progress = 1; } } assert(nexta == NULL || s->no != FREESTATE); } /* clear tmp fields of intermediate states created here */ while (intermediates != NULL) { struct state *ns = intermediates->tmp; intermediates->tmp = NULL; intermediates = ns; } /* if s is now useless, get rid of it */ if ((s->nins == 0 || s->nouts == 0) && !s->flag) { dropstate(nfa, s); } } if (progress && f != NULL) { dumpnfa(nfa, f); } } while (progress && !NISERR()); if (NISERR()) { return; } /* * Any ^ constraints we were able to pull to the start state can now be * replaced by PLAIN arcs referencing the BOS or BOL colors. There should * be no other ^ or BEHIND arcs left in the NFA, though we do not check * that here (compact() will fail if so). */ for (a=nfa->pre->outs ; a!=NULL ; a=nexta) { nexta = a->outchain; if (a->type == '^') { assert(a->co == 0 || a->co == 1); newarc(nfa, PLAIN, nfa->bos[a->co], a->from, a->to); freearc(nfa, a); } } } /* - pull - pull a back constraint backward past its source state * * Returns 1 if successful (which it always is unless the source is the * start state or we have an internal error), 0 if nothing happened. * * A significant property of this function is that it deletes no pre-existing * states, and no outarcs of the constraint's from state other than the given * constraint arc. This makes the loops in pullback() safe, at the cost that * we may leave useless states behind. Therefore, we leave it to pullback() * to delete such states. * * If the from state has multiple back-constraint outarcs, and/or multiple * compatible constraint inarcs, we only need to create one new intermediate * state per combination of predecessor and successor states. *intermediates * points to a list of such intermediate states for this from state (chained * through their tmp fields). ^ static int pull(struct nfa *, struct arc *); */ static int pull( struct nfa *nfa, struct arc *con, struct state **intermediates) { struct state *from = con->from; struct state *to = con->to; struct arc *a; struct arc *nexta; struct state *s; assert(from != to); /* should have gotten rid of this earlier */ if (from->flag) { /* can't pull back beyond start */ return 0; } if (from->nins == 0) { /* unreachable */ freearc(nfa, con); return 1; } /* * First, clone from state if necessary to avoid other outarcs. This may * seem wasteful, but it simplifies the logic, and we'll get rid of the * clone state again at the bottom. */ if (from->nouts > 1) { s = newstate(nfa); if (NISERR()) { return 0; } copyins(nfa, from, s); /* duplicate inarcs */ cparc(nfa, con, s, to); /* move constraint arc */ freearc(nfa, con); if (NISERR()) { return 0; } from = s; con = from->outs; } assert(from->nouts == 1); /* * Propagate the constraint into the from state's inarcs. */ for (a=from->ins ; a!=NULL && !NISERR(); a=nexta) { nexta = a->inchain; switch (combine(con, a)) { case INCOMPATIBLE: /* destroy the arc */ freearc(nfa, a); break; case SATISFIED: /* no action needed */ break; case COMPATIBLE: /* swap the two arcs, more or less */ /* need an intermediate state, but might have one already */ for (s = *intermediates; s != NULL; s = s->tmp) { assert(s->nins > 0 && s->nouts > 0); if (s->ins->from == a->from && s->outs->to == to) { break; } } if (s == NULL) { s = newstate(nfa); if (NISERR()) { return 0; } s->tmp = *intermediates; *intermediates = s; } cparc(nfa, con, a->from, s); cparc(nfa, a, s, to); freearc(nfa, a); break; default: assert(NOTREACHED); break; } } /* * Remaining inarcs, if any, incorporate the constraint. */ moveins(nfa, from, to); freearc(nfa, con); /* from state is now useless, but we leave it to pullback() to clean up */ return 1; } /* - pushfwd - push forward constraints forward to eliminate them ^ static void pushfwd(struct nfa *, FILE *); */ static void pushfwd( struct nfa *nfa, FILE *f) /* for debug output; NULL none */ { struct state *s; struct state *nexts; struct arc *a; struct arc *nexta; struct state *intermediates; int progress; /* * Find and push until there are no more. */ do { progress = 0; for (s=nfa->states ; s!=NULL && !NISERR() ; s=nexts) { nexts = s->next; intermediates = NULL; for (a = s->ins; a != NULL && !NISERR(); a = nexta) { nexta = a->inchain; if (a->type == '$' || a->type == AHEAD) { if (push(nfa, a, &intermediates)) { progress = 1; } } } /* clear tmp fields of intermediate states created here */ while (intermediates != NULL) { struct state *ns = intermediates->tmp; intermediates->tmp = NULL; intermediates = ns; } /* if s is now useless, get rid of it */ if ((s->nins == 0 || s->nouts == 0) && !s->flag) { dropstate(nfa, s); } } if (progress && f != NULL) { dumpnfa(nfa, f); } } while (progress && !NISERR()); if (NISERR()) { return; } /* * Any $ constraints we were able to push to the post state can now be * replaced by PLAIN arcs referencing the EOS or EOL colors. There should * be no other $ or AHEAD arcs left in the NFA, though we do not check * that here (compact() will fail if so). */ for (a = nfa->post->ins; a != NULL; a = nexta) { nexta = a->inchain; if (a->type == '$') { assert(a->co == 0 || a->co == 1); newarc(nfa, PLAIN, nfa->eos[a->co], a->from, a->to); freearc(nfa, a); } } } /* - push - push a forward constraint forward past its destination state * * Returns 1 if successful (which it always is unless the destination is the * post state or we have an internal error), 0 if nothing happened. * * A significant property of this function is that it deletes no pre-existing * states, and no inarcs of the constraint's to state other than the given * constraint arc. This makes the loops in pushfwd() safe, at the cost that * we may leave useless states behind. Therefore, we leave it to pushfwd() * to delete such states. * * If the to state has multiple forward-constraint inarcs, and/or multiple * compatible constraint outarcs, we only need to create one new intermediate * state per combination of predecessor and successor states. *intermediates * points to a list of such intermediate states for this to state (chained * through their tmp fields). ^ static int push(struct nfa *, struct arc *); */ static int push( struct nfa *nfa, struct arc *con, struct state **intermediates) { struct state *from = con->from; struct state *to = con->to; struct arc *a; struct arc *nexta; struct state *s; assert(to != from); /* should have gotten rid of this earlier */ if (to->flag) { /* can't push forward beyond end */ return 0; } if (to->nouts == 0) { /* dead end */ freearc(nfa, con); return 1; } /* * First, clone to state if necessary to avoid other inarcs. This may * seem wasteful, but it simplifies the logic, and we'll get rid of the * clone state again at the bottom. */ if (to->nins > 1) { s = newstate(nfa); if (NISERR()) { return 0; } copyouts(nfa, to, s); /* duplicate outarcs */ cparc(nfa, con, from, s); /* move constraint arc */ freearc(nfa, con); if (NISERR()) { return 0; } to = s; con = to->ins; } assert(to->nins == 1); /* * Propagate the constraint into the to state's outarcs. */ for (a = to->outs; a != NULL && !NISERR(); a = nexta) { nexta = a->outchain; switch (combine(con, a)) { case INCOMPATIBLE: /* destroy the arc */ freearc(nfa, a); break; case SATISFIED: /* no action needed */ break; case COMPATIBLE: /* swap the two arcs, more or less */ /* need an intermediate state, but might have one already */ for (s = *intermediates; s != NULL; s = s->tmp) { assert(s->nins > 0 && s->nouts > 0); if (s->ins->from == from && s->outs->to == a->to) { break; } } if (s == NULL) { s = newstate(nfa); if (NISERR()) { return 0; } s->tmp = *intermediates; *intermediates = s; } cparc(nfa, con, s, a->to); cparc(nfa, a, from, s); freearc(nfa, a); break; default: assert(NOTREACHED); break; } } /* * Remaining outarcs, if any, incorporate the constraint. */ moveouts(nfa, to, from); freearc(nfa, con); /* to state is now useless, but we leave it to pushfwd() to clean up */ return 1; } /* - combine - constraint lands on an arc, what happens? ^ #def INCOMPATIBLE 1 // destroys arc ^ #def SATISFIED 2 // constraint satisfied ^ #def COMPATIBLE 3 // compatible but not satisfied yet ^ static int combine(struct arc *, struct arc *); */ static int combine( struct arc *con, struct arc *a) { #define CA(ct,at) (((ct)<type, a->type)) { case CA('^', PLAIN): /* newlines are handled separately */ case CA('$', PLAIN): return INCOMPATIBLE; break; case CA(AHEAD, PLAIN): /* color constraints meet colors */ case CA(BEHIND, PLAIN): if (con->co == a->co) { return SATISFIED; } return INCOMPATIBLE; break; case CA('^', '^'): /* collision, similar constraints */ case CA('$', '$'): case CA(AHEAD, AHEAD): case CA(BEHIND, BEHIND): if (con->co == a->co) { /* true duplication */ return SATISFIED; } return INCOMPATIBLE; break; case CA('^', BEHIND): /* collision, dissimilar constraints */ case CA(BEHIND, '^'): case CA('$', AHEAD): case CA(AHEAD, '$'): return INCOMPATIBLE; break; case CA('^', '$'): /* constraints passing each other */ case CA('^', AHEAD): case CA(BEHIND, '$'): case CA(BEHIND, AHEAD): case CA('$', '^'): case CA('$', BEHIND): case CA(AHEAD, '^'): case CA(AHEAD, BEHIND): case CA('^', LACON): case CA(BEHIND, LACON): case CA('$', LACON): case CA(AHEAD, LACON): return COMPATIBLE; break; } assert(NOTREACHED); return INCOMPATIBLE; /* for benefit of blind compilers */ } /* - fixempties - get rid of EMPTY arcs ^ static void fixempties(struct nfa *, FILE *); */ static void fixempties( struct nfa *nfa, FILE *f) /* for debug output; NULL none */ { struct state *s; struct state *s2; struct state *nexts; struct arc *a; struct arc *nexta; int totalinarcs; struct arc **inarcsorig; struct arc **arcarray; int arccount; int prevnins; int nskip; /* * First, get rid of any states whose sole out-arc is an EMPTY, * since they're basically just aliases for their successor. The * parsing algorithm creates enough of these that it's worth * special-casing this. */ for (s = nfa->states; s != NULL && !NISERR(); s = nexts) { nexts = s->next; if (s->flag || s->nouts != 1) { continue; } a = s->outs; assert(a != NULL && a->outchain == NULL); if (a->type != EMPTY) { continue; } if (s != a->to) { moveins(nfa, s, a->to); } dropstate(nfa, s); } /* * Similarly, get rid of any state with a single EMPTY in-arc, by * folding it into its predecessor. */ for (s = nfa->states; s != NULL && !NISERR(); s = nexts) { nexts = s->next; /* Ensure tmp fields are clear for next step */ assert(s->tmp == NULL); if (s->flag || s->nins != 1) { continue; } a = s->ins; assert(a != NULL && a->inchain == NULL); if (a->type != EMPTY) { continue; } if (s != a->from) { moveouts(nfa, s, a->from); } dropstate(nfa, s); } if (NISERR()) { return; } /* * For each remaining NFA state, find all other states from which it is * reachable by a chain of one or more EMPTY arcs. Then generate new arcs * that eliminate the need for each such chain. * * We could replace a chain of EMPTY arcs that leads from a "from" state * to a "to" state either by pushing non-EMPTY arcs forward (linking * directly from "from"'s predecessors to "to") or by pulling them back * (linking directly from "from" to "to"'s successors). We choose to * always do the former; this choice is somewhat arbitrary, but the * approach below requires that we uniformly do one or the other. * * Suppose we have a chain of N successive EMPTY arcs (where N can easily * approach the size of the NFA). All of the intermediate states must * have additional inarcs and outarcs, else they'd have been removed by * the steps above. Assuming their inarcs are mostly not empties, we will * add O(N^2) arcs to the NFA, since a non-EMPTY inarc leading to any one * state in the chain must be duplicated to lead to all its successor * states as well. So there is no hope of doing less than O(N^2) work; * however, we should endeavor to keep the big-O cost from being even * worse than that, which it can easily become without care. In * particular, suppose we were to copy all S1's inarcs forward to S2, and * then also to S3, and then later we consider pushing S2's inarcs forward * to S3. If we include the arcs already copied from S1 in that, we'd be * doing O(N^3) work. (The duplicate-arc elimination built into newarc() * and its cohorts would get rid of the extra arcs, but not without cost.) * * We can avoid this cost by treating only arcs that existed at the start * of this phase as candidates to be pushed forward. To identify those, * we remember the first inarc each state had to start with. We rely on * the fact that newarc() and friends put new arcs on the front of their * to-states' inchains, and that this phase never deletes arcs, so that * the original arcs must be the last arcs in their to-states' inchains. * * So the process here is that, for each state in the NFA, we gather up * all non-EMPTY inarcs of states that can reach the target state via * EMPTY arcs. We then sort, de-duplicate, and merge these arcs into the * target state's inchain. (We can safely use sort-merge for this as long * as we update each state's original-arcs pointer after we add arcs to * it; the sort step of mergeins probably changed the order of the old * arcs.) * * Another refinement worth making is that, because we only add non-EMPTY * arcs during this phase, and all added arcs have the same from-state as * the non-EMPTY arc they were cloned from, we know ahead of time that any * states having only EMPTY outarcs will be useless for lack of outarcs * after we drop the EMPTY arcs. (They cannot gain non-EMPTY outarcs if * they had none to start with.) So we need not bother to update the * inchains of such states at all. */ /* Remember the states' first original inarcs */ /* ... and while at it, count how many old inarcs there are altogether */ inarcsorig = (struct arc **) MALLOC(nfa->nstates * sizeof(struct arc *)); if (inarcsorig == NULL) { NERR(REG_ESPACE); return; } totalinarcs = 0; for (s = nfa->states; s != NULL; s = s->next) { inarcsorig[s->no] = s->ins; totalinarcs += s->nins; } /* * Create a workspace for accumulating the inarcs to be added to the * current target state. totalinarcs is probably a considerable * overestimate of the space needed, but the NFA is unlikely to be large * enough at this point to make it worth being smarter. */ arcarray = (struct arc **) MALLOC(totalinarcs * sizeof(struct arc *)); if (arcarray == NULL) { NERR(REG_ESPACE); FREE(inarcsorig); return; } /* And iterate over the target states */ for (s = nfa->states; s != NULL && !NISERR(); s = s->next) { /* Ignore target states without non-EMPTY outarcs, per note above */ if (!s->flag && !hasnonemptyout(s)) { continue; } /* Find predecessor states and accumulate their original inarcs */ arccount = 0; for (s2 = emptyreachable(nfa, s, s, inarcsorig); s2 != s; s2 = nexts) { /* Add s2's original inarcs to arcarray[], but ignore empties */ for (a = inarcsorig[s2->no]; a != NULL; a = a->inchain) { if (a->type != EMPTY) { arcarray[arccount++] = a; } } /* Reset the tmp fields as we walk back */ nexts = s2->tmp; s2->tmp = NULL; } s->tmp = NULL; assert(arccount <= totalinarcs); /* Remember how many original inarcs this state has */ prevnins = s->nins; /* Add non-duplicate inarcs to target state */ mergeins(nfa, s, arcarray, arccount); /* Now we must update the state's inarcsorig pointer */ nskip = s->nins - prevnins; a = s->ins; while (nskip-- > 0) { a = a->inchain; } inarcsorig[s->no] = a; } FREE(arcarray); FREE(inarcsorig); if (NISERR()) { return; } /* * Remove all the EMPTY arcs, since we don't need them anymore. */ for (s = nfa->states; s != NULL; s = s->next) { for (a = s->outs; a != NULL; a = nexta) { nexta = a->outchain; if (a->type == EMPTY) { freearc(nfa, a); } } } /* * And remove any states that have become useless. (This cleanup is * not very thorough, and would be even less so if we tried to * combine it with the previous step; but cleanup() will take care * of anything we miss.) */ for (s = nfa->states; s != NULL; s = nexts) { nexts = s->next; if ((s->nins == 0 || s->nouts == 0) && !s->flag) { dropstate(nfa, s); } } if (f != NULL) { dumpnfa(nfa, f); } } /* - emptyreachable - recursively find all states that can reach s by EMPTY arcs * The return value is the last such state found. Its tmp field links back * to the next-to-last such state, and so on back to s, so that all these * states can be located without searching the whole NFA. * * Since this is only used in fixempties(), we pass in the inarcsorig[] array * maintained by that function. This lets us skip over all new inarcs, which * are certainly not EMPTY arcs. * * The maximum recursion depth here is equal to the length of the longest * loop-free chain of EMPTY arcs, which is surely no more than the size of * the NFA, and in practice will be less than that. ^ static struct state *emptyreachable(struct state *, struct state *); */ static struct state * emptyreachable( struct nfa *nfa, struct state *s, struct state *lastfound, struct arc **inarcsorig) { struct arc *a; s->tmp = lastfound; lastfound = s; for (a = inarcsorig[s->no]; a != NULL; a = a->inchain) { if (a->type == EMPTY && a->from->tmp == NULL) { lastfound = emptyreachable(nfa, a->from, lastfound, inarcsorig); } } return lastfound; } /* * isconstraintarc - detect whether an arc is of a constraint type */ static inline int isconstraintarc(struct arc * a) { switch (a->type) { case '^': case '$': case BEHIND: case AHEAD: case LACON: return 1; } return 0; } /* * hasconstraintout - does state have a constraint out arc? */ static int hasconstraintout(struct state * s) { struct arc *a; for (a = s->outs; a != NULL; a = a->outchain) { if (isconstraintarc(a)) { return 1; } } return 0; } /* * fixconstraintloops - get rid of loops containing only constraint arcs * * A loop of states that contains only constraint arcs is useless, since * passing around the loop represents no forward progress. Moreover, it * would cause infinite looping in pullback/pushfwd, so we need to get rid * of such loops before doing that. */ static void fixconstraintloops( struct nfa * nfa, FILE *f) /* for debug output; NULL none */ { struct state *s; struct state *nexts; struct arc *a; struct arc *nexta; int hasconstraints; /* * In the trivial case of a state that loops to itself, we can just drop * the constraint arc altogether. This is worth special-casing because * such loops are far more common than loops containing multiple states. * While we're at it, note whether any constraint arcs survive. */ hasconstraints = 0; for (s = nfa->states; s != NULL && !NISERR(); s = nexts) { nexts = s->next; /* while we're at it, ensure tmp fields are clear for next step */ assert(s->tmp == NULL); for (a = s->outs; a != NULL && !NISERR(); a = nexta) { nexta = a->outchain; if (isconstraintarc(a)) { if (a->to == s) { freearc(nfa, a); } else { hasconstraints = 1; } } } /* If we removed all the outarcs, the state is useless. */ if (s->nouts == 0 && !s->flag) { dropstate(nfa, s); } } /* Nothing to do if no remaining constraint arcs */ if (NISERR() || !hasconstraints) { return; } /* * Starting from each remaining NFA state, search outwards for a * constraint loop. If we find a loop, break the loop, then start the * search over. (We could possibly retain some state from the first scan, * but it would complicate things greatly, and multi-state constraint * loops are rare enough that it's not worth optimizing the case.) */ restart: for (s = nfa->states; s != NULL && !NISERR(); s = s->next) { if (findconstraintloop(nfa, s)) { goto restart; } } if (NISERR()) { return; } /* * Now remove any states that have become useless. (This cleanup is not * very thorough, and would be even less so if we tried to combine it with * the previous step; but cleanup() will take care of anything we miss.) * * Because findconstraintloop intentionally doesn't reset all tmp fields, * we have to clear them after it's done. This is a convenient place to * do that, too. */ for (s = nfa->states; s != NULL; s = nexts) { nexts = s->next; s->tmp = NULL; if ((s->nins == 0 || s->nouts == 0) && !s->flag) { dropstate(nfa, s); } } if (f != NULL) { dumpnfa(nfa, f); } } /* * findconstraintloop - recursively find a loop of constraint arcs * * If we find a loop, break it by calling breakconstraintloop(), then * return 1; otherwise return 0. * * State tmp fields are guaranteed all NULL on a success return, because * breakconstraintloop does that. After a failure return, any state that * is known not to be part of a loop is marked with s->tmp == s; this allows * us not to have to re-prove that fact on later calls. (This convention is * workable because we already eliminated single-state loops.) * * Note that the found loop doesn't necessarily include the first state we * are called on. Any loop reachable from that state will do. * * The maximum recursion depth here is one more than the length of the longest * loop-free chain of constraint arcs, which is surely no more than the size * of the NFA, and in practice will be a lot less than that. */ static int findconstraintloop(struct nfa * nfa, struct state * s) { struct arc *a; /* Since this is recursive, it could be driven to stack overflow */ if (STACK_TOO_DEEP(nfa->v->re)) { NERR(REG_ETOOBIG); return 1; /* to exit as quickly as possible */ } if (s->tmp != NULL) { /* Already proven uninteresting? */ if (s->tmp == s) { return 0; } /* Found a loop involving s */ breakconstraintloop(nfa, s); /* The tmp fields have been cleaned up by breakconstraintloop */ return 1; } for (a = s->outs; a != NULL; a = a->outchain) { if (isconstraintarc(a)) { struct state *sto = a->to; assert(sto != s); s->tmp = sto; if (findconstraintloop(nfa, sto)) { return 1; } } } /* * If we get here, no constraint loop exists leading out from s. Mark it * with s->tmp == s so we need not rediscover that fact again later. */ s->tmp = s; return 0; } /* * breakconstraintloop - break a loop of constraint arcs * * sinitial is any one member state of the loop. Each loop member's tmp * field links to its successor within the loop. (Note that this function * will reset all the tmp fields to NULL.) * * We can break the loop by, for any one state S1 in the loop, cloning its * loop successor state S2 (and possibly following states), and then moving * all S1->S2 constraint arcs to point to the cloned S2. The cloned S2 should * copy any non-constraint outarcs of S2. Constraint outarcs should be * dropped if they point back to S1, else they need to be copied as arcs to * similarly cloned states S3, S4, etc. In general, each cloned state copies * non-constraint outarcs, drops constraint outarcs that would lead to itself * or any earlier cloned state, and sends other constraint outarcs to newly * cloned states. No cloned state will have any inarcs that aren't constraint * arcs or do not lead from S1 or earlier-cloned states. It's okay to drop * constraint back-arcs since they would not take us to any state we've not * already been in; therefore, no new constraint loop is created. In this way * we generate a modified NFA that can still represent every useful state * sequence, but not sequences that represent state loops with no consumption * of input data. Note that the set of cloned states will certainly include * all of the loop member states other than S1, and it may also include * non-loop states that are reachable from S2 via constraint arcs. This is * important because there is no guarantee that findconstraintloop found a * maximal loop (and searching for one would be NP-hard, so don't try). * Frequently the "non-loop states" are actually part of a larger loop that * we didn't notice, and indeed there may be several overlapping loops. * This technique ensures convergence in such cases, while considering only * the originally-found loop does not. * * If there is only one S1->S2 constraint arc, then that constraint is * certainly satisfied when we enter any of the clone states. This means that * in the common case where many of the constraint arcs are identically * labeled, we can merge together clone states linked by a similarly-labeled * constraint: if we can get to the first one we can certainly get to the * second, so there's no need to distinguish. This greatly reduces the number * of new states needed, so we preferentially break the given loop at a state * pair where this is true. * * Furthermore, it's fairly common to find that a cloned successor state has * no outarcs, especially if we're a bit aggressive about removing unnecessary * outarcs. If that happens, then there is simply not any interesting state * that can be reached through the predecessor's loop arcs, which means we can * break the loop just by removing those loop arcs, with no new states added. */ static void breakconstraintloop(struct nfa * nfa, struct state * sinitial) { struct state *s; struct state *shead; struct state *stail; struct state *sclone; struct state *nexts; struct arc *refarc; struct arc *a; struct arc *nexta; /* * Start by identifying which loop step we want to break at. * Preferentially this is one with only one constraint arc. (XXX are * there any other secondary heuristics we want to use here?) Set refarc * to point to the selected lone constraint arc, if there is one. */ refarc = NULL; s = sinitial; do { nexts = s->tmp; assert(nexts != s); /* should not see any one-element loops */ if (refarc == NULL) { int narcs = 0; for (a = s->outs; a != NULL; a = a->outchain) { if (a->to == nexts && isconstraintarc(a)) { refarc = a; narcs++; } } assert(narcs > 0); if (narcs > 1) { refarc = NULL; /* multiple constraint arcs here, no good */ } } s = nexts; } while (s != sinitial); if (refarc) { /* break at the refarc */ shead = refarc->from; stail = refarc->to; assert(stail == shead->tmp); } else { /* for lack of a better idea, break after sinitial */ shead = sinitial; stail = sinitial->tmp; } /* * Reset the tmp fields so that we can use them for local storage in * clonesuccessorstates. (findconstraintloop won't mind, since it's just * going to abandon its search anyway.) */ for (s = nfa->states; s != NULL; s = s->next) { s->tmp = NULL; } /* * Recursively build clone state(s) as needed. */ sclone = newstate(nfa); if (sclone == NULL) { assert(NISERR()); return; } clonesuccessorstates(nfa, stail, sclone, shead, refarc, NULL, NULL, nfa->nstates); if (NISERR()) { return; } /* * It's possible that sclone has no outarcs at all, in which case it's * useless. (We don't try extremely hard to get rid of useless states * here, but this is an easy and fairly common case.) */ if (sclone->nouts == 0) { freestate(nfa, sclone); sclone = NULL; } /* * Move shead's constraint-loop arcs to point to sclone, or just drop them * if we discovered we don't need sclone. */ for (a = shead->outs; a != NULL; a = nexta) { nexta = a->outchain; if (a->to == stail && isconstraintarc(a)) { if (sclone) { cparc(nfa, a, shead, sclone); } freearc(nfa, a); if (NISERR()) { break; } } } } /* * clonesuccessorstates - create a tree of constraint-arc successor states * * ssource is the state to be cloned, and sclone is the state to copy its * outarcs into. sclone's inarcs, if any, should already be set up. * * spredecessor is the original predecessor state that we are trying to build * successors for (it may not be the immediate predecessor of ssource). * refarc, if not NULL, is the original constraint arc that is known to have * been traversed out of spredecessor to reach the successor(s). * * For each cloned successor state, we transiently create a "donemap" that is * a boolean array showing which source states we've already visited for this * clone state. This prevents infinite recursion as well as useless repeat * visits to the same state subtree (which can add up fast, since typical NFAs * have multiple redundant arc pathways). Each donemap is a char array * indexed by state number. The donemaps are all of the same size "nstates", * which is nfa->nstates as of the start of the recursion. This is enough to * have entries for all pre-existing states, but *not* entries for clone * states created during the recursion. That's okay since we have no need to * mark those. * * curdonemap is NULL when recursing to a new sclone state, or sclone's * donemap when we are recursing without having created a new state (which we * do when we decide we can merge a successor state into the current clone * state). outerdonemap is NULL at the top level and otherwise the parent * clone state's donemap. * * The successor states we create and fill here form a strict tree structure, * with each state having exactly one predecessor, except that the toplevel * state has no inarcs as yet (breakconstraintloop will add its inarcs from * spredecessor after we're done). Thus, we can examine sclone's inarcs back * to the root, plus refarc if any, to identify the set of constraints already * known valid at the current point. This allows us to avoid generating extra * successor states. */ static void clonesuccessorstates( struct nfa * nfa, struct state * ssource, struct state * sclone, struct state * spredecessor, struct arc * refarc, char *curdonemap, char *outerdonemap, int nstates) { char *donemap; struct arc *a; /* Since this is recursive, it could be driven to stack overflow */ if (STACK_TOO_DEEP(nfa->v->re)) { NERR(REG_ETOOBIG); return; } /* If this state hasn't already got a donemap, create one */ donemap = curdonemap; if (donemap == NULL) { donemap = (char *) MALLOC(nstates * sizeof(char)); if (donemap == NULL) { NERR(REG_ESPACE); return; } if (outerdonemap != NULL) { /* * Not at outermost recursion level, so copy the outer level's * donemap; this ensures that we see states in process of being * visited at outer levels, or already merged into predecessor * states, as ones we shouldn't traverse back to. */ memcpy(donemap, outerdonemap, nstates * sizeof(char)); } else { /* At outermost level, only spredecessor is off-limits */ memset(donemap, 0, nstates * sizeof(char)); assert(spredecessor->no < nstates); donemap[spredecessor->no] = 1; } } /* Mark ssource as visited in the donemap */ assert(ssource->no < nstates); assert(donemap[ssource->no] == 0); donemap[ssource->no] = 1; /* * We proceed by first cloning all of ssource's outarcs, creating new * clone states as needed but not doing more with them than that. Then in * a second pass, recurse to process the child clone states. This allows * us to have only one child clone state per reachable source state, even * when there are multiple outarcs leading to the same state. Also, when * we do visit a child state, its set of inarcs is known exactly, which * makes it safe to apply the constraint-is-already-checked optimization. * Also, this ensures that we've merged all the states we can into the * current clone before we recurse to any children, thus possibly saving * them from making extra images of those states. * * While this function runs, child clone states of the current state are * marked by setting their tmp fields to point to the original state they * were cloned from. This makes it possible to detect multiple outarcs * leading to the same state, and also makes it easy to distinguish clone * states from original states (which will have tmp == NULL). */ for (a = ssource->outs; a != NULL && !NISERR(); a = a->outchain) { struct state *sto = a->to; /* * We do not consider cloning successor states that have no constraint * outarcs; just link to them as-is. They cannot be part of a * constraint loop so there is no need to make copies. In particular, * this rule keeps us from trying to clone the post state, which would * be a bad idea. */ if (isconstraintarc(a) && hasconstraintout(sto)) { struct state *prevclone; int canmerge; struct arc *a2; /* * Back-link constraint arcs must not be followed. Nor is there a * need to revisit states previously merged into this clone. */ assert(sto->no < nstates); if (donemap[sto->no] != 0) { continue; } /* * Check whether we already have a child clone state for this * source state. */ prevclone = NULL; for (a2 = sclone->outs; a2 != NULL; a2 = a2->outchain) { if (a2->to->tmp == sto) { prevclone = a2->to; break; } } /* * If this arc is labeled the same as refarc, or the same as any * arc we must have traversed to get to sclone, then no additional * constraints need to be met to get to sto, so we should just * merge its outarcs into sclone. */ if (refarc && a->type == refarc->type && a->co == refarc->co) { canmerge = 1; } else { struct state *s; canmerge = 0; for (s = sclone; s->ins; s = s->ins->from) { if (s->nins == 1 && a->type == s->ins->type && a->co == s->ins->co) { canmerge = 1; break; } } } if (canmerge) { /* * We can merge into sclone. If we previously made a child * clone state, drop it; there's no need to visit it. (This * can happen if ssource has multiple pathways to sto, and we * only just now found one that is provably a no-op.) */ if (prevclone) { dropstate(nfa, prevclone); /* kills our outarc, too */ } /* Recurse to merge sto's outarcs into sclone */ clonesuccessorstates(nfa, sto, sclone, spredecessor, refarc, donemap, outerdonemap, nstates); /* sto should now be marked as previously visited */ assert(NISERR() || donemap[sto->no] == 1); } else if (prevclone) { /* * We already have a clone state for this successor, so just * make another arc to it. */ cparc(nfa, a, sclone, prevclone); } else { /* * We need to create a new successor clone state. */ struct state *stoclone; stoclone = newstate(nfa); if (stoclone == NULL) { assert(NISERR()); break; } /* Mark it as to what it's a clone of */ stoclone->tmp = sto; /* ... and add the outarc leading to it */ cparc(nfa, a, sclone, stoclone); } } else { /* * Non-constraint outarcs just get copied to sclone, as do outarcs * leading to states with no constraint outarc. */ cparc(nfa, a, sclone, sto); } } /* * If we are at outer level for this clone state, recurse to all its child * clone states, clearing their tmp fields as we go. (If we're not * outermost for sclone, leave this to be done by the outer call level.) * Note that if we have multiple outarcs leading to the same clone state, * it will only be recursed-to once. */ if (curdonemap == NULL) { for (a = sclone->outs; a != NULL && !NISERR(); a = a->outchain) { struct state *stoclone = a->to; struct state *sto = stoclone->tmp; if (sto != NULL) { stoclone->tmp = NULL; clonesuccessorstates(nfa, sto, stoclone, spredecessor, refarc, NULL, donemap, nstates); } } /* Don't forget to free sclone's donemap when done with it */ FREE(donemap); } } /* - cleanup - clean up NFA after optimizations ^ static void cleanup(struct nfa *); */ static void cleanup( struct nfa *nfa) { struct state *s; struct state *nexts; int n; /* * Clear out unreachable or dead-end states. Use pre to mark reachable, * then post to mark can-reach-post. */ markreachable(nfa, nfa->pre, NULL, nfa->pre); markcanreach(nfa, nfa->post, nfa->pre, nfa->post); for (s = nfa->states; s != NULL; s = nexts) { nexts = s->next; if (s->tmp != nfa->post && !s->flag) { dropstate(nfa, s); } } assert(nfa->post->nins == 0 || nfa->post->tmp == nfa->post); cleartraverse(nfa, nfa->pre); assert(nfa->post->nins == 0 || nfa->post->tmp == NULL); /* the nins==0 (final unreachable) case will be caught later */ /* * Renumber surviving states. */ n = 0; for (s = nfa->states; s != NULL; s = s->next) { s->no = n++; } nfa->nstates = n; } /* - markreachable - recursive marking of reachable states ^ static void markreachable(struct nfa *, struct state *, struct state *, ^ struct state *); */ static void markreachable( struct nfa *nfa, struct state *s, struct state *okay, /* consider only states with this mark */ struct state *mark) /* the value to mark with */ { struct arc *a; if (s->tmp != okay) { return; } s->tmp = mark; for (a = s->outs; a != NULL; a = a->outchain) { markreachable(nfa, a->to, okay, mark); } } /* - markcanreach - recursive marking of states which can reach here ^ static void markcanreach(struct nfa *, struct state *, struct state *, ^ struct state *); */ static void markcanreach( struct nfa *nfa, struct state *s, struct state *okay, /* consider only states with this mark */ struct state *mark) /* the value to mark with */ { struct arc *a; if (s->tmp != okay) { return; } s->tmp = mark; for (a = s->ins; a != NULL; a = a->inchain) { markcanreach(nfa, a->from, okay, mark); } } /* - analyze - ascertain potentially-useful facts about an optimized NFA ^ static long analyze(struct nfa *); */ static long /* re_info bits to be ORed in */ analyze( struct nfa *nfa) { struct arc *a; struct arc *aa; if (nfa->pre->outs == NULL) { return REG_UIMPOSSIBLE; } for (a = nfa->pre->outs; a != NULL; a = a->outchain) { for (aa = a->to->outs; aa != NULL; aa = aa->outchain) { if (aa->to == nfa->post) { return REG_UEMPTYMATCH; } } } return 0; } /* - compact - construct the compact representation of an NFA ^ static void compact(struct nfa *, struct cnfa *); */ static void compact( struct nfa *nfa, struct cnfa *cnfa) { struct state *s; struct arc *a; size_t nstates; size_t narcs; struct carc *ca; struct carc *first; assert(!NISERR()); nstates = 0; narcs = 0; for (s = nfa->states; s != NULL; s = s->next) { nstates++; narcs += s->nouts + 1; /* need one extra for endmarker */ } cnfa->stflags = (char *) MALLOC(nstates * sizeof(char)); cnfa->states = (struct carc **) MALLOC(nstates * sizeof(struct carc *)); cnfa->arcs = (struct carc *) MALLOC(narcs * sizeof(struct carc)); if (cnfa->stflags == NULL || cnfa->states == NULL || cnfa->arcs == NULL) { if (cnfa->stflags != NULL) { FREE(cnfa->stflags); } if (cnfa->states != NULL) { FREE(cnfa->states); } if (cnfa->arcs != NULL) { FREE(cnfa->arcs); } NERR(REG_ESPACE); return; } cnfa->nstates = nstates; cnfa->pre = nfa->pre->no; cnfa->post = nfa->post->no; cnfa->bos[0] = nfa->bos[0]; cnfa->bos[1] = nfa->bos[1]; cnfa->eos[0] = nfa->eos[0]; cnfa->eos[1] = nfa->eos[1]; cnfa->ncolors = maxcolor(nfa->cm) + 1; cnfa->flags = 0; ca = cnfa->arcs; for (s = nfa->states; s != NULL; s = s->next) { assert((size_t) s->no < nstates); cnfa->stflags[s->no] = 0; cnfa->states[s->no] = ca; first = ca; for (a = s->outs; a != NULL; a = a->outchain) { switch (a->type) { case PLAIN: ca->co = a->co; ca->to = a->to->no; ca++; break; case LACON: assert(s->no != cnfa->pre); ca->co = (color) (cnfa->ncolors + a->co); ca->to = a->to->no; ca++; cnfa->flags |= HASLACONS; break; default: NERR(REG_ASSERT); break; } } carcsort(first, ca - first); ca->co = COLORLESS; ca->to = 0; ca++; } assert(ca == &cnfa->arcs[narcs]); assert(cnfa->nstates != 0); /* * Mark no-progress states. */ for (a = nfa->pre->outs; a != NULL; a = a->outchain) { cnfa->stflags[a->to->no] = CNFA_NOPROGRESS; } cnfa->stflags[nfa->pre->no] = CNFA_NOPROGRESS; } /* - carcsort - sort compacted-NFA arcs by color ^ static void carcsort(struct carc *, struct carc *); */ static void carcsort( struct carc *first, size_t n) { if (n > 1) { qsort(first, n, sizeof(struct carc), carc_cmp); } } static int carc_cmp( const void *a, const void *b) { const struct carc *aa = (const struct carc *) a; const struct carc *bb = (const struct carc *) b; if (aa->co < bb->co) { return -1; } if (aa->co > bb->co) { return +1; } if (aa->to < bb->to) { return -1; } if (aa->to > bb->to) { return +1; } return 0; } /* - freecnfa - free a compacted NFA ^ static void freecnfa(struct cnfa *); */ static void freecnfa( struct cnfa *cnfa) { assert(cnfa->nstates != 0); /* not empty already */ cnfa->nstates = 0; FREE(cnfa->stflags); FREE(cnfa->states); FREE(cnfa->arcs); } /* - dumpnfa - dump an NFA in human-readable form ^ static void dumpnfa(struct nfa *, FILE *); */ static void dumpnfa( struct nfa *nfa, FILE *f) { #ifdef REG_DEBUG struct state *s; int nstates = 0; int narcs = 0; fprintf(f, "pre %d, post %d", nfa->pre->no, nfa->post->no); if (nfa->bos[0] != COLORLESS) { fprintf(f, ", bos [%ld]", (long) nfa->bos[0]); } if (nfa->bos[1] != COLORLESS) { fprintf(f, ", bol [%ld]", (long) nfa->bos[1]); } if (nfa->eos[0] != COLORLESS) { fprintf(f, ", eos [%ld]", (long) nfa->eos[0]); } if (nfa->eos[1] != COLORLESS) { fprintf(f, ", eol [%ld]", (long) nfa->eos[1]); } fprintf(f, "\n"); for (s = nfa->states; s != NULL; s = s->next) { dumpstate(s, f); nstates++; narcs += s->nouts; } fprintf(f, "total of %d states, %d arcs\n", nstates, narcs); if (nfa->parent == NULL) { dumpcolors(nfa->cm, f); } fflush(f); #endif } #ifdef REG_DEBUG /* subordinates of dumpnfa */ /* ^ #ifdef REG_DEBUG */ /* - dumpstate - dump an NFA state in human-readable form ^ static void dumpstate(struct state *, FILE *); */ static void dumpstate( struct state *s, FILE *f) { struct arc *a; fprintf(f, "%d%s%c", s->no, (s->tmp != NULL) ? "T" : "", (s->flag) ? s->flag : '.'); if (s->prev != NULL && s->prev->next != s) { fprintf(f, "\tstate chain bad\n"); } if (s->nouts == 0) { fprintf(f, "\tno out arcs\n"); } else { dumparcs(s, f); } fflush(f); for (a = s->ins; a != NULL; a = a->inchain) { if (a->to != s) { fprintf(f, "\tlink from %d to %d on %d's in-chain\n", a->from->no, a->to->no, s->no); } } } /* - dumparcs - dump out-arcs in human-readable form ^ static void dumparcs(struct state *, FILE *); */ static void dumparcs( struct state *s, FILE *f) { int pos; struct arc *a; /* printing oldest arcs first is usually clearer */ a = s->outs; assert(a != NULL); while (a->outchain != NULL) { a = a->outchain; } pos = 1; do { dumparc(a, s, f); if (pos == 5) { fprintf(f, "\n"); pos = 1; } else { pos++; } a = a->outchainRev; } while (a != NULL); if (pos != 1) { fprintf(f, "\n"); } } /* - dumparc - dump one outarc in readable form, including prefixing tab ^ static void dumparc(struct arc *, struct state *, FILE *); */ static void dumparc( struct arc *a, struct state *s, FILE *f) { struct arc *aa; struct arcbatch *ab; fprintf(f, "\t"); switch (a->type) { case PLAIN: fprintf(f, "[%ld]", (long) a->co); break; case AHEAD: fprintf(f, ">%ld>", (long) a->co); break; case BEHIND: fprintf(f, "<%ld<", (long) a->co); break; case LACON: fprintf(f, ":%ld:", (long) a->co); break; case '^': case '$': fprintf(f, "%c%d", a->type, (int) a->co); break; case EMPTY: break; default: fprintf(f, "0x%x/0%lo", a->type, (long) a->co); break; } if (a->from != s) { fprintf(f, "?%d?", a->from->no); } for (ab = &a->from->oas; ab != NULL; ab = ab->next) { for (aa = &ab->a[0]; aa < &ab->a[ABSIZE]; aa++) { if (aa == a) { break; /* NOTE BREAK OUT */ } } if (aa < &ab->a[ABSIZE]) { /* propagate break */ break; /* NOTE BREAK OUT */ } } if (ab == NULL) { fprintf(f, "?!?"); /* not in allocated space */ } fprintf(f, "->"); if (a->to == NULL) { fprintf(f, "NULL"); return; } fprintf(f, "%d", a->to->no); for (aa = a->to->ins; aa != NULL; aa = aa->inchain) { if (aa == a) { break; /* NOTE BREAK OUT */ } } if (aa == NULL) { fprintf(f, "?!?"); /* missing from in-chain */ } } /* ^ #endif */ #endif /* ifdef REG_DEBUG */ /* - dumpcnfa - dump a compacted NFA in human-readable form ^ static void dumpcnfa(struct cnfa *, FILE *); */ static void dumpcnfa( struct cnfa *cnfa, FILE *f) { #ifdef REG_DEBUG int st; fprintf(f, "pre %d, post %d", cnfa->pre, cnfa->post); if (cnfa->bos[0] != COLORLESS) { fprintf(f, ", bos [%ld]", (long) cnfa->bos[0]); } if (cnfa->bos[1] != COLORLESS) { fprintf(f, ", bol [%ld]", (long) cnfa->bos[1]); } if (cnfa->eos[0] != COLORLESS) { fprintf(f, ", eos [%ld]", (long) cnfa->eos[0]); } if (cnfa->eos[1] != COLORLESS) { fprintf(f, ", eol [%ld]", (long) cnfa->eos[1]); } if (cnfa->flags&HASLACONS) { fprintf(f, ", haslacons"); } fprintf(f, "\n"); for (st = 0; st < cnfa->nstates; st++) { dumpcstate(st, cnfa, f); } fflush(f); #endif } #ifdef REG_DEBUG /* subordinates of dumpcnfa */ /* ^ #ifdef REG_DEBUG */ /* - dumpcstate - dump a compacted-NFA state in human-readable form ^ static void dumpcstate(int, struct cnfa *, FILE *); */ static void dumpcstate( int st, struct cnfa *cnfa, FILE *f) { struct carc *ca; int pos; fprintf(f, "%d%s", st, (cnfa->stflags[st] & CNFA_NOPROGRESS) ? ":" : "."); pos = 1; for (ca = cnfa->states[st]; ca->co != COLORLESS; ca++) { if (ca->co < cnfa->ncolors) { fprintf(f, "\t[%ld]->%d", (long) ca->co, ca->to); } else { fprintf(f, "\t:%ld:->%d", (long) (ca->co - cnfa->ncolors), ca->to); } if (pos == 5) { fprintf(f, "\n"); pos = 1; } else { pos++; } } if (ca == cnfa->states[st] || pos != 1) { fprintf(f, "\n"); } fflush(f); } /* ^ #endif */ #endif /* ifdef REG_DEBUG */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclDecls.h0000644000175000017500000051332112665173571015121 0ustar sergeisergei/* * tclDecls.h -- * * Declarations of functions in the platform independent public Tcl API. * * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLDECLS #define _TCLDECLS #undef TCL_STORAGE_CLASS #ifdef BUILD_tcl # define TCL_STORAGE_CLASS DLLEXPORT #else # ifdef USE_TCL_STUBS # define TCL_STORAGE_CLASS # else # define TCL_STORAGE_CLASS DLLIMPORT # endif #endif /* * WARNING: This file is automatically generated by the tools/genStubs.tcl * script. Any modifications to the function declarations below should be made * in the generic/tcl.decls script. */ /* !BEGIN!: Do not edit below this line. */ #ifdef __cplusplus extern "C" { #endif /* * Exported function declarations: */ /* 0 */ EXTERN int Tcl_PkgProvideEx(Tcl_Interp *interp, const char *name, const char *version, const void *clientData); /* 1 */ EXTERN CONST84_RETURN char * Tcl_PkgRequireEx(Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr); /* 2 */ EXTERN TCL_NORETURN void Tcl_Panic(const char *format, ...) TCL_FORMAT_PRINTF(1, 2); /* 3 */ EXTERN char * Tcl_Alloc(unsigned int size); /* 4 */ EXTERN void Tcl_Free(char *ptr); /* 5 */ EXTERN char * Tcl_Realloc(char *ptr, unsigned int size); /* 6 */ EXTERN char * Tcl_DbCkalloc(unsigned int size, const char *file, int line); /* 7 */ EXTERN void Tcl_DbCkfree(char *ptr, const char *file, int line); /* 8 */ EXTERN char * Tcl_DbCkrealloc(char *ptr, unsigned int size, const char *file, int line); #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ /* 9 */ EXTERN void Tcl_CreateFileHandler(int fd, int mask, Tcl_FileProc *proc, ClientData clientData); #endif /* UNIX */ #ifdef MAC_OSX_TCL /* MACOSX */ /* 9 */ EXTERN void Tcl_CreateFileHandler(int fd, int mask, Tcl_FileProc *proc, ClientData clientData); #endif /* MACOSX */ #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ /* 10 */ EXTERN void Tcl_DeleteFileHandler(int fd); #endif /* UNIX */ #ifdef MAC_OSX_TCL /* MACOSX */ /* 10 */ EXTERN void Tcl_DeleteFileHandler(int fd); #endif /* MACOSX */ /* 11 */ EXTERN void Tcl_SetTimer(const Tcl_Time *timePtr); /* 12 */ EXTERN void Tcl_Sleep(int ms); /* 13 */ EXTERN int Tcl_WaitForEvent(const Tcl_Time *timePtr); /* 14 */ EXTERN int Tcl_AppendAllObjTypes(Tcl_Interp *interp, Tcl_Obj *objPtr); /* 15 */ EXTERN void Tcl_AppendStringsToObj(Tcl_Obj *objPtr, ...); /* 16 */ EXTERN void Tcl_AppendToObj(Tcl_Obj *objPtr, const char *bytes, int length); /* 17 */ EXTERN Tcl_Obj * Tcl_ConcatObj(int objc, Tcl_Obj *const objv[]); /* 18 */ EXTERN int Tcl_ConvertToType(Tcl_Interp *interp, Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 19 */ EXTERN void Tcl_DbDecrRefCount(Tcl_Obj *objPtr, const char *file, int line); /* 20 */ EXTERN void Tcl_DbIncrRefCount(Tcl_Obj *objPtr, const char *file, int line); /* 21 */ EXTERN int Tcl_DbIsShared(Tcl_Obj *objPtr, const char *file, int line); /* 22 */ EXTERN Tcl_Obj * Tcl_DbNewBooleanObj(int boolValue, const char *file, int line); /* 23 */ EXTERN Tcl_Obj * Tcl_DbNewByteArrayObj(const unsigned char *bytes, int length, const char *file, int line); /* 24 */ EXTERN Tcl_Obj * Tcl_DbNewDoubleObj(double doubleValue, const char *file, int line); /* 25 */ EXTERN Tcl_Obj * Tcl_DbNewListObj(int objc, Tcl_Obj *const *objv, const char *file, int line); /* 26 */ EXTERN Tcl_Obj * Tcl_DbNewLongObj(long longValue, const char *file, int line); /* 27 */ EXTERN Tcl_Obj * Tcl_DbNewObj(const char *file, int line); /* 28 */ EXTERN Tcl_Obj * Tcl_DbNewStringObj(const char *bytes, int length, const char *file, int line); /* 29 */ EXTERN Tcl_Obj * Tcl_DuplicateObj(Tcl_Obj *objPtr); /* 30 */ EXTERN void TclFreeObj(Tcl_Obj *objPtr); /* 31 */ EXTERN int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, int *boolPtr); /* 32 */ EXTERN int Tcl_GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *boolPtr); /* 33 */ EXTERN unsigned char * Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, int *lengthPtr); /* 34 */ EXTERN int Tcl_GetDouble(Tcl_Interp *interp, const char *src, double *doublePtr); /* 35 */ EXTERN int Tcl_GetDoubleFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, double *doublePtr); /* 36 */ EXTERN int Tcl_GetIndexFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, CONST84 char *const *tablePtr, const char *msg, int flags, int *indexPtr); /* 37 */ EXTERN int Tcl_GetInt(Tcl_Interp *interp, const char *src, int *intPtr); /* 38 */ EXTERN int Tcl_GetIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 39 */ EXTERN int Tcl_GetLongFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr); /* 40 */ EXTERN CONST86 Tcl_ObjType * Tcl_GetObjType(const char *typeName); /* 41 */ EXTERN char * Tcl_GetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr); /* 42 */ EXTERN void Tcl_InvalidateStringRep(Tcl_Obj *objPtr); /* 43 */ EXTERN int Tcl_ListObjAppendList(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr); /* 44 */ EXTERN int Tcl_ListObjAppendElement(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr); /* 45 */ EXTERN int Tcl_ListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 46 */ EXTERN int Tcl_ListObjIndex(Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj **objPtrPtr); /* 47 */ EXTERN int Tcl_ListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr, int *lengthPtr); /* 48 */ EXTERN int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, int first, int count, int objc, Tcl_Obj *const objv[]); /* 49 */ EXTERN Tcl_Obj * Tcl_NewBooleanObj(int boolValue); /* 50 */ EXTERN Tcl_Obj * Tcl_NewByteArrayObj(const unsigned char *bytes, int length); /* 51 */ EXTERN Tcl_Obj * Tcl_NewDoubleObj(double doubleValue); /* 52 */ EXTERN Tcl_Obj * Tcl_NewIntObj(int intValue); /* 53 */ EXTERN Tcl_Obj * Tcl_NewListObj(int objc, Tcl_Obj *const objv[]); /* 54 */ EXTERN Tcl_Obj * Tcl_NewLongObj(long longValue); /* 55 */ EXTERN Tcl_Obj * Tcl_NewObj(void); /* 56 */ EXTERN Tcl_Obj * Tcl_NewStringObj(const char *bytes, int length); /* 57 */ EXTERN void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int boolValue); /* 58 */ EXTERN unsigned char * Tcl_SetByteArrayLength(Tcl_Obj *objPtr, int length); /* 59 */ EXTERN void Tcl_SetByteArrayObj(Tcl_Obj *objPtr, const unsigned char *bytes, int length); /* 60 */ EXTERN void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue); /* 61 */ EXTERN void Tcl_SetIntObj(Tcl_Obj *objPtr, int intValue); /* 62 */ EXTERN void Tcl_SetListObj(Tcl_Obj *objPtr, int objc, Tcl_Obj *const objv[]); /* 63 */ EXTERN void Tcl_SetLongObj(Tcl_Obj *objPtr, long longValue); /* 64 */ EXTERN void Tcl_SetObjLength(Tcl_Obj *objPtr, int length); /* 65 */ EXTERN void Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes, int length); /* 66 */ EXTERN void Tcl_AddErrorInfo(Tcl_Interp *interp, const char *message); /* 67 */ EXTERN void Tcl_AddObjErrorInfo(Tcl_Interp *interp, const char *message, int length); /* 68 */ EXTERN void Tcl_AllowExceptions(Tcl_Interp *interp); /* 69 */ EXTERN void Tcl_AppendElement(Tcl_Interp *interp, const char *element); /* 70 */ EXTERN void Tcl_AppendResult(Tcl_Interp *interp, ...); /* 71 */ EXTERN Tcl_AsyncHandler Tcl_AsyncCreate(Tcl_AsyncProc *proc, ClientData clientData); /* 72 */ EXTERN void Tcl_AsyncDelete(Tcl_AsyncHandler async); /* 73 */ EXTERN int Tcl_AsyncInvoke(Tcl_Interp *interp, int code); /* 74 */ EXTERN void Tcl_AsyncMark(Tcl_AsyncHandler async); /* 75 */ EXTERN int Tcl_AsyncReady(void); /* 76 */ EXTERN void Tcl_BackgroundError(Tcl_Interp *interp); /* 77 */ EXTERN char Tcl_Backslash(const char *src, int *readPtr); /* 78 */ EXTERN int Tcl_BadChannelOption(Tcl_Interp *interp, const char *optionName, const char *optionList); /* 79 */ EXTERN void Tcl_CallWhenDeleted(Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 80 */ EXTERN void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, ClientData clientData); /* 81 */ EXTERN int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan); /* 82 */ EXTERN int Tcl_CommandComplete(const char *cmd); /* 83 */ EXTERN char * Tcl_Concat(int argc, CONST84 char *const *argv); /* 84 */ EXTERN int Tcl_ConvertElement(const char *src, char *dst, int flags); /* 85 */ EXTERN int Tcl_ConvertCountedElement(const char *src, int length, char *dst, int flags); /* 86 */ EXTERN int Tcl_CreateAlias(Tcl_Interp *slave, const char *slaveCmd, Tcl_Interp *target, const char *targetCmd, int argc, CONST84 char *const *argv); /* 87 */ EXTERN int Tcl_CreateAliasObj(Tcl_Interp *slave, const char *slaveCmd, Tcl_Interp *target, const char *targetCmd, int objc, Tcl_Obj *const objv[]); /* 88 */ EXTERN Tcl_Channel Tcl_CreateChannel(const Tcl_ChannelType *typePtr, const char *chanName, ClientData instanceData, int mask); /* 89 */ EXTERN void Tcl_CreateChannelHandler(Tcl_Channel chan, int mask, Tcl_ChannelProc *proc, ClientData clientData); /* 90 */ EXTERN void Tcl_CreateCloseHandler(Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData); /* 91 */ EXTERN Tcl_Command Tcl_CreateCommand(Tcl_Interp *interp, const char *cmdName, Tcl_CmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 92 */ EXTERN void Tcl_CreateEventSource(Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, ClientData clientData); /* 93 */ EXTERN void Tcl_CreateExitHandler(Tcl_ExitProc *proc, ClientData clientData); /* 94 */ EXTERN Tcl_Interp * Tcl_CreateInterp(void); /* 95 */ EXTERN void Tcl_CreateMathFunc(Tcl_Interp *interp, const char *name, int numArgs, Tcl_ValueType *argTypes, Tcl_MathProc *proc, ClientData clientData); /* 96 */ EXTERN Tcl_Command Tcl_CreateObjCommand(Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 97 */ EXTERN Tcl_Interp * Tcl_CreateSlave(Tcl_Interp *interp, const char *slaveName, int isSafe); /* 98 */ EXTERN Tcl_TimerToken Tcl_CreateTimerHandler(int milliseconds, Tcl_TimerProc *proc, ClientData clientData); /* 99 */ EXTERN Tcl_Trace Tcl_CreateTrace(Tcl_Interp *interp, int level, Tcl_CmdTraceProc *proc, ClientData clientData); /* 100 */ EXTERN void Tcl_DeleteAssocData(Tcl_Interp *interp, const char *name); /* 101 */ EXTERN void Tcl_DeleteChannelHandler(Tcl_Channel chan, Tcl_ChannelProc *proc, ClientData clientData); /* 102 */ EXTERN void Tcl_DeleteCloseHandler(Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData); /* 103 */ EXTERN int Tcl_DeleteCommand(Tcl_Interp *interp, const char *cmdName); /* 104 */ EXTERN int Tcl_DeleteCommandFromToken(Tcl_Interp *interp, Tcl_Command command); /* 105 */ EXTERN void Tcl_DeleteEvents(Tcl_EventDeleteProc *proc, ClientData clientData); /* 106 */ EXTERN void Tcl_DeleteEventSource(Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, ClientData clientData); /* 107 */ EXTERN void Tcl_DeleteExitHandler(Tcl_ExitProc *proc, ClientData clientData); /* 108 */ EXTERN void Tcl_DeleteHashEntry(Tcl_HashEntry *entryPtr); /* 109 */ EXTERN void Tcl_DeleteHashTable(Tcl_HashTable *tablePtr); /* 110 */ EXTERN void Tcl_DeleteInterp(Tcl_Interp *interp); /* 111 */ EXTERN void Tcl_DetachPids(int numPids, Tcl_Pid *pidPtr); /* 112 */ EXTERN void Tcl_DeleteTimerHandler(Tcl_TimerToken token); /* 113 */ EXTERN void Tcl_DeleteTrace(Tcl_Interp *interp, Tcl_Trace trace); /* 114 */ EXTERN void Tcl_DontCallWhenDeleted(Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 115 */ EXTERN int Tcl_DoOneEvent(int flags); /* 116 */ EXTERN void Tcl_DoWhenIdle(Tcl_IdleProc *proc, ClientData clientData); /* 117 */ EXTERN char * Tcl_DStringAppend(Tcl_DString *dsPtr, const char *bytes, int length); /* 118 */ EXTERN char * Tcl_DStringAppendElement(Tcl_DString *dsPtr, const char *element); /* 119 */ EXTERN void Tcl_DStringEndSublist(Tcl_DString *dsPtr); /* 120 */ EXTERN void Tcl_DStringFree(Tcl_DString *dsPtr); /* 121 */ EXTERN void Tcl_DStringGetResult(Tcl_Interp *interp, Tcl_DString *dsPtr); /* 122 */ EXTERN void Tcl_DStringInit(Tcl_DString *dsPtr); /* 123 */ EXTERN void Tcl_DStringResult(Tcl_Interp *interp, Tcl_DString *dsPtr); /* 124 */ EXTERN void Tcl_DStringSetLength(Tcl_DString *dsPtr, int length); /* 125 */ EXTERN void Tcl_DStringStartSublist(Tcl_DString *dsPtr); /* 126 */ EXTERN int Tcl_Eof(Tcl_Channel chan); /* 127 */ EXTERN CONST84_RETURN char * Tcl_ErrnoId(void); /* 128 */ EXTERN CONST84_RETURN char * Tcl_ErrnoMsg(int err); /* 129 */ EXTERN int Tcl_Eval(Tcl_Interp *interp, const char *script); /* 130 */ EXTERN int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName); /* 131 */ EXTERN int Tcl_EvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr); /* 132 */ EXTERN void Tcl_EventuallyFree(ClientData clientData, Tcl_FreeProc *freeProc); /* 133 */ EXTERN TCL_NORETURN void Tcl_Exit(int status); /* 134 */ EXTERN int Tcl_ExposeCommand(Tcl_Interp *interp, const char *hiddenCmdToken, const char *cmdName); /* 135 */ EXTERN int Tcl_ExprBoolean(Tcl_Interp *interp, const char *expr, int *ptr); /* 136 */ EXTERN int Tcl_ExprBooleanObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *ptr); /* 137 */ EXTERN int Tcl_ExprDouble(Tcl_Interp *interp, const char *expr, double *ptr); /* 138 */ EXTERN int Tcl_ExprDoubleObj(Tcl_Interp *interp, Tcl_Obj *objPtr, double *ptr); /* 139 */ EXTERN int Tcl_ExprLong(Tcl_Interp *interp, const char *expr, long *ptr); /* 140 */ EXTERN int Tcl_ExprLongObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *ptr); /* 141 */ EXTERN int Tcl_ExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr); /* 142 */ EXTERN int Tcl_ExprString(Tcl_Interp *interp, const char *expr); /* 143 */ EXTERN void Tcl_Finalize(void); /* 144 */ EXTERN void Tcl_FindExecutable(const char *argv0); /* 145 */ EXTERN Tcl_HashEntry * Tcl_FirstHashEntry(Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr); /* 146 */ EXTERN int Tcl_Flush(Tcl_Channel chan); /* 147 */ EXTERN void Tcl_FreeResult(Tcl_Interp *interp); /* 148 */ EXTERN int Tcl_GetAlias(Tcl_Interp *interp, const char *slaveCmd, Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr, int *argcPtr, CONST84 char ***argvPtr); /* 149 */ EXTERN int Tcl_GetAliasObj(Tcl_Interp *interp, const char *slaveCmd, Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr, int *objcPtr, Tcl_Obj ***objv); /* 150 */ EXTERN ClientData Tcl_GetAssocData(Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc **procPtr); /* 151 */ EXTERN Tcl_Channel Tcl_GetChannel(Tcl_Interp *interp, const char *chanName, int *modePtr); /* 152 */ EXTERN int Tcl_GetChannelBufferSize(Tcl_Channel chan); /* 153 */ EXTERN int Tcl_GetChannelHandle(Tcl_Channel chan, int direction, ClientData *handlePtr); /* 154 */ EXTERN ClientData Tcl_GetChannelInstanceData(Tcl_Channel chan); /* 155 */ EXTERN int Tcl_GetChannelMode(Tcl_Channel chan); /* 156 */ EXTERN CONST84_RETURN char * Tcl_GetChannelName(Tcl_Channel chan); /* 157 */ EXTERN int Tcl_GetChannelOption(Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, Tcl_DString *dsPtr); /* 158 */ EXTERN CONST86 Tcl_ChannelType * Tcl_GetChannelType(Tcl_Channel chan); /* 159 */ EXTERN int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr); /* 160 */ EXTERN CONST84_RETURN char * Tcl_GetCommandName(Tcl_Interp *interp, Tcl_Command command); /* 161 */ EXTERN int Tcl_GetErrno(void); /* 162 */ EXTERN CONST84_RETURN char * Tcl_GetHostName(void); /* 163 */ EXTERN int Tcl_GetInterpPath(Tcl_Interp *askInterp, Tcl_Interp *slaveInterp); /* 164 */ EXTERN Tcl_Interp * Tcl_GetMaster(Tcl_Interp *interp); /* 165 */ EXTERN const char * Tcl_GetNameOfExecutable(void); /* 166 */ EXTERN Tcl_Obj * Tcl_GetObjResult(Tcl_Interp *interp); #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ /* 167 */ EXTERN int Tcl_GetOpenFile(Tcl_Interp *interp, const char *chanID, int forWriting, int checkUsage, ClientData *filePtr); #endif /* UNIX */ #ifdef MAC_OSX_TCL /* MACOSX */ /* 167 */ EXTERN int Tcl_GetOpenFile(Tcl_Interp *interp, const char *chanID, int forWriting, int checkUsage, ClientData *filePtr); #endif /* MACOSX */ /* 168 */ EXTERN Tcl_PathType Tcl_GetPathType(const char *path); /* 169 */ EXTERN int Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr); /* 170 */ EXTERN int Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr); /* 171 */ EXTERN int Tcl_GetServiceMode(void); /* 172 */ EXTERN Tcl_Interp * Tcl_GetSlave(Tcl_Interp *interp, const char *slaveName); /* 173 */ EXTERN Tcl_Channel Tcl_GetStdChannel(int type); /* 174 */ EXTERN CONST84_RETURN char * Tcl_GetStringResult(Tcl_Interp *interp); /* 175 */ EXTERN CONST84_RETURN char * Tcl_GetVar(Tcl_Interp *interp, const char *varName, int flags); /* 176 */ EXTERN CONST84_RETURN char * Tcl_GetVar2(Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 177 */ EXTERN int Tcl_GlobalEval(Tcl_Interp *interp, const char *command); /* 178 */ EXTERN int Tcl_GlobalEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr); /* 179 */ EXTERN int Tcl_HideCommand(Tcl_Interp *interp, const char *cmdName, const char *hiddenCmdToken); /* 180 */ EXTERN int Tcl_Init(Tcl_Interp *interp); /* 181 */ EXTERN void Tcl_InitHashTable(Tcl_HashTable *tablePtr, int keyType); /* 182 */ EXTERN int Tcl_InputBlocked(Tcl_Channel chan); /* 183 */ EXTERN int Tcl_InputBuffered(Tcl_Channel chan); /* 184 */ EXTERN int Tcl_InterpDeleted(Tcl_Interp *interp); /* 185 */ EXTERN int Tcl_IsSafe(Tcl_Interp *interp); /* 186 */ EXTERN char * Tcl_JoinPath(int argc, CONST84 char *const *argv, Tcl_DString *resultPtr); /* 187 */ EXTERN int Tcl_LinkVar(Tcl_Interp *interp, const char *varName, char *addr, int type); /* Slot 188 is reserved */ /* 189 */ EXTERN Tcl_Channel Tcl_MakeFileChannel(ClientData handle, int mode); /* 190 */ EXTERN int Tcl_MakeSafe(Tcl_Interp *interp); /* 191 */ EXTERN Tcl_Channel Tcl_MakeTcpClientChannel(ClientData tcpSocket); /* 192 */ EXTERN char * Tcl_Merge(int argc, CONST84 char *const *argv); /* 193 */ EXTERN Tcl_HashEntry * Tcl_NextHashEntry(Tcl_HashSearch *searchPtr); /* 194 */ EXTERN void Tcl_NotifyChannel(Tcl_Channel channel, int mask); /* 195 */ EXTERN Tcl_Obj * Tcl_ObjGetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 196 */ EXTERN Tcl_Obj * Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags); /* 197 */ EXTERN Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc, CONST84 char **argv, int flags); /* 198 */ EXTERN Tcl_Channel Tcl_OpenFileChannel(Tcl_Interp *interp, const char *fileName, const char *modeString, int permissions); /* 199 */ EXTERN Tcl_Channel Tcl_OpenTcpClient(Tcl_Interp *interp, int port, const char *address, const char *myaddr, int myport, int async); /* 200 */ EXTERN Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port, const char *host, Tcl_TcpAcceptProc *acceptProc, ClientData callbackData); /* 201 */ EXTERN void Tcl_Preserve(ClientData data); /* 202 */ EXTERN void Tcl_PrintDouble(Tcl_Interp *interp, double value, char *dst); /* 203 */ EXTERN int Tcl_PutEnv(const char *assignment); /* 204 */ EXTERN CONST84_RETURN char * Tcl_PosixError(Tcl_Interp *interp); /* 205 */ EXTERN void Tcl_QueueEvent(Tcl_Event *evPtr, Tcl_QueuePosition position); /* 206 */ EXTERN int Tcl_Read(Tcl_Channel chan, char *bufPtr, int toRead); /* 207 */ EXTERN void Tcl_ReapDetachedProcs(void); /* 208 */ EXTERN int Tcl_RecordAndEval(Tcl_Interp *interp, const char *cmd, int flags); /* 209 */ EXTERN int Tcl_RecordAndEvalObj(Tcl_Interp *interp, Tcl_Obj *cmdPtr, int flags); /* 210 */ EXTERN void Tcl_RegisterChannel(Tcl_Interp *interp, Tcl_Channel chan); /* 211 */ EXTERN void Tcl_RegisterObjType(const Tcl_ObjType *typePtr); /* 212 */ EXTERN Tcl_RegExp Tcl_RegExpCompile(Tcl_Interp *interp, const char *pattern); /* 213 */ EXTERN int Tcl_RegExpExec(Tcl_Interp *interp, Tcl_RegExp regexp, const char *text, const char *start); /* 214 */ EXTERN int Tcl_RegExpMatch(Tcl_Interp *interp, const char *text, const char *pattern); /* 215 */ EXTERN void Tcl_RegExpRange(Tcl_RegExp regexp, int index, CONST84 char **startPtr, CONST84 char **endPtr); /* 216 */ EXTERN void Tcl_Release(ClientData clientData); /* 217 */ EXTERN void Tcl_ResetResult(Tcl_Interp *interp); /* 218 */ EXTERN int Tcl_ScanElement(const char *src, int *flagPtr); /* 219 */ EXTERN int Tcl_ScanCountedElement(const char *src, int length, int *flagPtr); /* 220 */ EXTERN int Tcl_SeekOld(Tcl_Channel chan, int offset, int mode); /* 221 */ EXTERN int Tcl_ServiceAll(void); /* 222 */ EXTERN int Tcl_ServiceEvent(int flags); /* 223 */ EXTERN void Tcl_SetAssocData(Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 224 */ EXTERN void Tcl_SetChannelBufferSize(Tcl_Channel chan, int sz); /* 225 */ EXTERN int Tcl_SetChannelOption(Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, const char *newValue); /* 226 */ EXTERN int Tcl_SetCommandInfo(Tcl_Interp *interp, const char *cmdName, const Tcl_CmdInfo *infoPtr); /* 227 */ EXTERN void Tcl_SetErrno(int err); /* 228 */ EXTERN void Tcl_SetErrorCode(Tcl_Interp *interp, ...); /* 229 */ EXTERN void Tcl_SetMaxBlockTime(const Tcl_Time *timePtr); /* 230 */ EXTERN void Tcl_SetPanicProc( TCL_NORETURN1 Tcl_PanicProc *panicProc); /* 231 */ EXTERN int Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth); /* 232 */ EXTERN void Tcl_SetResult(Tcl_Interp *interp, char *result, Tcl_FreeProc *freeProc); /* 233 */ EXTERN int Tcl_SetServiceMode(int mode); /* 234 */ EXTERN void Tcl_SetObjErrorCode(Tcl_Interp *interp, Tcl_Obj *errorObjPtr); /* 235 */ EXTERN void Tcl_SetObjResult(Tcl_Interp *interp, Tcl_Obj *resultObjPtr); /* 236 */ EXTERN void Tcl_SetStdChannel(Tcl_Channel channel, int type); /* 237 */ EXTERN CONST84_RETURN char * Tcl_SetVar(Tcl_Interp *interp, const char *varName, const char *newValue, int flags); /* 238 */ EXTERN CONST84_RETURN char * Tcl_SetVar2(Tcl_Interp *interp, const char *part1, const char *part2, const char *newValue, int flags); /* 239 */ EXTERN CONST84_RETURN char * Tcl_SignalId(int sig); /* 240 */ EXTERN CONST84_RETURN char * Tcl_SignalMsg(int sig); /* 241 */ EXTERN void Tcl_SourceRCFile(Tcl_Interp *interp); /* 242 */ EXTERN int Tcl_SplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr, CONST84 char ***argvPtr); /* 243 */ EXTERN void Tcl_SplitPath(const char *path, int *argcPtr, CONST84 char ***argvPtr); /* 244 */ EXTERN void Tcl_StaticPackage(Tcl_Interp *interp, const char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc); /* 245 */ EXTERN int Tcl_StringMatch(const char *str, const char *pattern); /* 246 */ EXTERN int Tcl_TellOld(Tcl_Channel chan); /* 247 */ EXTERN int Tcl_TraceVar(Tcl_Interp *interp, const char *varName, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 248 */ EXTERN int Tcl_TraceVar2(Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 249 */ EXTERN char * Tcl_TranslateFileName(Tcl_Interp *interp, const char *name, Tcl_DString *bufferPtr); /* 250 */ EXTERN int Tcl_Ungets(Tcl_Channel chan, const char *str, int len, int atHead); /* 251 */ EXTERN void Tcl_UnlinkVar(Tcl_Interp *interp, const char *varName); /* 252 */ EXTERN int Tcl_UnregisterChannel(Tcl_Interp *interp, Tcl_Channel chan); /* 253 */ EXTERN int Tcl_UnsetVar(Tcl_Interp *interp, const char *varName, int flags); /* 254 */ EXTERN int Tcl_UnsetVar2(Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 255 */ EXTERN void Tcl_UntraceVar(Tcl_Interp *interp, const char *varName, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 256 */ EXTERN void Tcl_UntraceVar2(Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 257 */ EXTERN void Tcl_UpdateLinkedVar(Tcl_Interp *interp, const char *varName); /* 258 */ EXTERN int Tcl_UpVar(Tcl_Interp *interp, const char *frameName, const char *varName, const char *localName, int flags); /* 259 */ EXTERN int Tcl_UpVar2(Tcl_Interp *interp, const char *frameName, const char *part1, const char *part2, const char *localName, int flags); /* 260 */ EXTERN int Tcl_VarEval(Tcl_Interp *interp, ...); /* 261 */ EXTERN ClientData Tcl_VarTraceInfo(Tcl_Interp *interp, const char *varName, int flags, Tcl_VarTraceProc *procPtr, ClientData prevClientData); /* 262 */ EXTERN ClientData Tcl_VarTraceInfo2(Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *procPtr, ClientData prevClientData); /* 263 */ EXTERN int Tcl_Write(Tcl_Channel chan, const char *s, int slen); /* 264 */ EXTERN void Tcl_WrongNumArgs(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], const char *message); /* 265 */ EXTERN int Tcl_DumpActiveMemory(const char *fileName); /* 266 */ EXTERN void Tcl_ValidateAllMemory(const char *file, int line); /* 267 */ EXTERN void Tcl_AppendResultVA(Tcl_Interp *interp, va_list argList); /* 268 */ EXTERN void Tcl_AppendStringsToObjVA(Tcl_Obj *objPtr, va_list argList); /* 269 */ EXTERN char * Tcl_HashStats(Tcl_HashTable *tablePtr); /* 270 */ EXTERN CONST84_RETURN char * Tcl_ParseVar(Tcl_Interp *interp, const char *start, CONST84 char **termPtr); /* 271 */ EXTERN CONST84_RETURN char * Tcl_PkgPresent(Tcl_Interp *interp, const char *name, const char *version, int exact); /* 272 */ EXTERN CONST84_RETURN char * Tcl_PkgPresentEx(Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr); /* 273 */ EXTERN int Tcl_PkgProvide(Tcl_Interp *interp, const char *name, const char *version); /* 274 */ EXTERN CONST84_RETURN char * Tcl_PkgRequire(Tcl_Interp *interp, const char *name, const char *version, int exact); /* 275 */ EXTERN void Tcl_SetErrorCodeVA(Tcl_Interp *interp, va_list argList); /* 276 */ EXTERN int Tcl_VarEvalVA(Tcl_Interp *interp, va_list argList); /* 277 */ EXTERN Tcl_Pid Tcl_WaitPid(Tcl_Pid pid, int *statPtr, int options); /* 278 */ EXTERN TCL_NORETURN void Tcl_PanicVA(const char *format, va_list argList); /* 279 */ EXTERN void Tcl_GetVersion(int *major, int *minor, int *patchLevel, int *type); /* 280 */ EXTERN void Tcl_InitMemory(Tcl_Interp *interp); /* 281 */ EXTERN Tcl_Channel Tcl_StackChannel(Tcl_Interp *interp, const Tcl_ChannelType *typePtr, ClientData instanceData, int mask, Tcl_Channel prevChan); /* 282 */ EXTERN int Tcl_UnstackChannel(Tcl_Interp *interp, Tcl_Channel chan); /* 283 */ EXTERN Tcl_Channel Tcl_GetStackedChannel(Tcl_Channel chan); /* 284 */ EXTERN void Tcl_SetMainLoop(Tcl_MainLoopProc *proc); /* Slot 285 is reserved */ /* 286 */ EXTERN void Tcl_AppendObjToObj(Tcl_Obj *objPtr, Tcl_Obj *appendObjPtr); /* 287 */ EXTERN Tcl_Encoding Tcl_CreateEncoding(const Tcl_EncodingType *typePtr); /* 288 */ EXTERN void Tcl_CreateThreadExitHandler(Tcl_ExitProc *proc, ClientData clientData); /* 289 */ EXTERN void Tcl_DeleteThreadExitHandler(Tcl_ExitProc *proc, ClientData clientData); /* 290 */ EXTERN void Tcl_DiscardResult(Tcl_SavedResult *statePtr); /* 291 */ EXTERN int Tcl_EvalEx(Tcl_Interp *interp, const char *script, int numBytes, int flags); /* 292 */ EXTERN int Tcl_EvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 293 */ EXTERN int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 294 */ EXTERN void Tcl_ExitThread(int status); /* 295 */ EXTERN int Tcl_ExternalToUtf(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); /* 296 */ EXTERN char * Tcl_ExternalToUtfDString(Tcl_Encoding encoding, const char *src, int srcLen, Tcl_DString *dsPtr); /* 297 */ EXTERN void Tcl_FinalizeThread(void); /* 298 */ EXTERN void Tcl_FinalizeNotifier(ClientData clientData); /* 299 */ EXTERN void Tcl_FreeEncoding(Tcl_Encoding encoding); /* 300 */ EXTERN Tcl_ThreadId Tcl_GetCurrentThread(void); /* 301 */ EXTERN Tcl_Encoding Tcl_GetEncoding(Tcl_Interp *interp, const char *name); /* 302 */ EXTERN CONST84_RETURN char * Tcl_GetEncodingName(Tcl_Encoding encoding); /* 303 */ EXTERN void Tcl_GetEncodingNames(Tcl_Interp *interp); /* 304 */ EXTERN int Tcl_GetIndexFromObjStruct(Tcl_Interp *interp, Tcl_Obj *objPtr, const void *tablePtr, int offset, const char *msg, int flags, int *indexPtr); /* 305 */ EXTERN void * Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr, int size); /* 306 */ EXTERN Tcl_Obj * Tcl_GetVar2Ex(Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 307 */ EXTERN ClientData Tcl_InitNotifier(void); /* 308 */ EXTERN void Tcl_MutexLock(Tcl_Mutex *mutexPtr); /* 309 */ EXTERN void Tcl_MutexUnlock(Tcl_Mutex *mutexPtr); /* 310 */ EXTERN void Tcl_ConditionNotify(Tcl_Condition *condPtr); /* 311 */ EXTERN void Tcl_ConditionWait(Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr, const Tcl_Time *timePtr); /* 312 */ EXTERN int Tcl_NumUtfChars(const char *src, int length); /* 313 */ EXTERN int Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr, int charsToRead, int appendFlag); /* 314 */ EXTERN void Tcl_RestoreResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr); /* 315 */ EXTERN void Tcl_SaveResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr); /* 316 */ EXTERN int Tcl_SetSystemEncoding(Tcl_Interp *interp, const char *name); /* 317 */ EXTERN Tcl_Obj * Tcl_SetVar2Ex(Tcl_Interp *interp, const char *part1, const char *part2, Tcl_Obj *newValuePtr, int flags); /* 318 */ EXTERN void Tcl_ThreadAlert(Tcl_ThreadId threadId); /* 319 */ EXTERN void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId, Tcl_Event *evPtr, Tcl_QueuePosition position); /* 320 */ EXTERN Tcl_UniChar Tcl_UniCharAtIndex(const char *src, int index); /* 321 */ EXTERN Tcl_UniChar Tcl_UniCharToLower(int ch); /* 322 */ EXTERN Tcl_UniChar Tcl_UniCharToTitle(int ch); /* 323 */ EXTERN Tcl_UniChar Tcl_UniCharToUpper(int ch); /* 324 */ EXTERN int Tcl_UniCharToUtf(int ch, char *buf); /* 325 */ EXTERN CONST84_RETURN char * Tcl_UtfAtIndex(const char *src, int index); /* 326 */ EXTERN int Tcl_UtfCharComplete(const char *src, int length); /* 327 */ EXTERN int Tcl_UtfBackslash(const char *src, int *readPtr, char *dst); /* 328 */ EXTERN CONST84_RETURN char * Tcl_UtfFindFirst(const char *src, int ch); /* 329 */ EXTERN CONST84_RETURN char * Tcl_UtfFindLast(const char *src, int ch); /* 330 */ EXTERN CONST84_RETURN char * Tcl_UtfNext(const char *src); /* 331 */ EXTERN CONST84_RETURN char * Tcl_UtfPrev(const char *src, const char *start); /* 332 */ EXTERN 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); /* 333 */ EXTERN char * Tcl_UtfToExternalDString(Tcl_Encoding encoding, const char *src, int srcLen, Tcl_DString *dsPtr); /* 334 */ EXTERN int Tcl_UtfToLower(char *src); /* 335 */ EXTERN int Tcl_UtfToTitle(char *src); /* 336 */ EXTERN int Tcl_UtfToUniChar(const char *src, Tcl_UniChar *chPtr); /* 337 */ EXTERN int Tcl_UtfToUpper(char *src); /* 338 */ EXTERN int Tcl_WriteChars(Tcl_Channel chan, const char *src, int srcLen); /* 339 */ EXTERN int Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr); /* 340 */ EXTERN char * Tcl_GetString(Tcl_Obj *objPtr); /* 341 */ EXTERN CONST84_RETURN char * Tcl_GetDefaultEncodingDir(void); /* 342 */ EXTERN void Tcl_SetDefaultEncodingDir(const char *path); /* 343 */ EXTERN void Tcl_AlertNotifier(ClientData clientData); /* 344 */ EXTERN void Tcl_ServiceModeHook(int mode); /* 345 */ EXTERN int Tcl_UniCharIsAlnum(int ch); /* 346 */ EXTERN int Tcl_UniCharIsAlpha(int ch); /* 347 */ EXTERN int Tcl_UniCharIsDigit(int ch); /* 348 */ EXTERN int Tcl_UniCharIsLower(int ch); /* 349 */ EXTERN int Tcl_UniCharIsSpace(int ch); /* 350 */ EXTERN int Tcl_UniCharIsUpper(int ch); /* 351 */ EXTERN int Tcl_UniCharIsWordChar(int ch); /* 352 */ EXTERN int Tcl_UniCharLen(const Tcl_UniChar *uniStr); /* 353 */ EXTERN int Tcl_UniCharNcmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsigned long numChars); /* 354 */ EXTERN char * Tcl_UniCharToUtfDString(const Tcl_UniChar *uniStr, int uniLength, Tcl_DString *dsPtr); /* 355 */ EXTERN Tcl_UniChar * Tcl_UtfToUniCharDString(const char *src, int length, Tcl_DString *dsPtr); /* 356 */ EXTERN Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, Tcl_Obj *patObj, int flags); /* 357 */ EXTERN Tcl_Obj * Tcl_EvalTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr, int count); /* 358 */ EXTERN void Tcl_FreeParse(Tcl_Parse *parsePtr); /* 359 */ EXTERN void Tcl_LogCommandInfo(Tcl_Interp *interp, const char *script, const char *command, int length); /* 360 */ EXTERN int Tcl_ParseBraces(Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append, CONST84 char **termPtr); /* 361 */ EXTERN int Tcl_ParseCommand(Tcl_Interp *interp, const char *start, int numBytes, int nested, Tcl_Parse *parsePtr); /* 362 */ EXTERN int Tcl_ParseExpr(Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr); /* 363 */ EXTERN int Tcl_ParseQuotedString(Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append, CONST84 char **termPtr); /* 364 */ EXTERN int Tcl_ParseVarName(Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append); /* 365 */ EXTERN char * Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 366 */ EXTERN int Tcl_Chdir(const char *dirName); /* 367 */ EXTERN int Tcl_Access(const char *path, int mode); /* 368 */ EXTERN int Tcl_Stat(const char *path, struct stat *bufPtr); /* 369 */ EXTERN int Tcl_UtfNcmp(const char *s1, const char *s2, unsigned long n); /* 370 */ EXTERN int Tcl_UtfNcasecmp(const char *s1, const char *s2, unsigned long n); /* 371 */ EXTERN int Tcl_StringCaseMatch(const char *str, const char *pattern, int nocase); /* 372 */ EXTERN int Tcl_UniCharIsControl(int ch); /* 373 */ EXTERN int Tcl_UniCharIsGraph(int ch); /* 374 */ EXTERN int Tcl_UniCharIsPrint(int ch); /* 375 */ EXTERN int Tcl_UniCharIsPunct(int ch); /* 376 */ EXTERN int Tcl_RegExpExecObj(Tcl_Interp *interp, Tcl_RegExp regexp, Tcl_Obj *textObj, int offset, int nmatches, int flags); /* 377 */ EXTERN void Tcl_RegExpGetInfo(Tcl_RegExp regexp, Tcl_RegExpInfo *infoPtr); /* 378 */ EXTERN Tcl_Obj * Tcl_NewUnicodeObj(const Tcl_UniChar *unicode, int numChars); /* 379 */ EXTERN void Tcl_SetUnicodeObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int numChars); /* 380 */ EXTERN int Tcl_GetCharLength(Tcl_Obj *objPtr); /* 381 */ EXTERN Tcl_UniChar Tcl_GetUniChar(Tcl_Obj *objPtr, int index); /* 382 */ EXTERN Tcl_UniChar * Tcl_GetUnicode(Tcl_Obj *objPtr); /* 383 */ EXTERN Tcl_Obj * Tcl_GetRange(Tcl_Obj *objPtr, int first, int last); /* 384 */ EXTERN void Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int length); /* 385 */ EXTERN int Tcl_RegExpMatchObj(Tcl_Interp *interp, Tcl_Obj *textObj, Tcl_Obj *patternObj); /* 386 */ EXTERN void Tcl_SetNotifier(Tcl_NotifierProcs *notifierProcPtr); /* 387 */ EXTERN Tcl_Mutex * Tcl_GetAllocMutex(void); /* 388 */ EXTERN int Tcl_GetChannelNames(Tcl_Interp *interp); /* 389 */ EXTERN int Tcl_GetChannelNamesEx(Tcl_Interp *interp, const char *pattern); /* 390 */ EXTERN int Tcl_ProcObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 391 */ EXTERN void Tcl_ConditionFinalize(Tcl_Condition *condPtr); /* 392 */ EXTERN void Tcl_MutexFinalize(Tcl_Mutex *mutex); /* 393 */ EXTERN int Tcl_CreateThread(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, ClientData clientData, int stackSize, int flags); /* 394 */ EXTERN int Tcl_ReadRaw(Tcl_Channel chan, char *dst, int bytesToRead); /* 395 */ EXTERN int Tcl_WriteRaw(Tcl_Channel chan, const char *src, int srcLen); /* 396 */ EXTERN Tcl_Channel Tcl_GetTopChannel(Tcl_Channel chan); /* 397 */ EXTERN int Tcl_ChannelBuffered(Tcl_Channel chan); /* 398 */ EXTERN CONST84_RETURN char * Tcl_ChannelName( const Tcl_ChannelType *chanTypePtr); /* 399 */ EXTERN Tcl_ChannelTypeVersion Tcl_ChannelVersion( const Tcl_ChannelType *chanTypePtr); /* 400 */ EXTERN Tcl_DriverBlockModeProc * Tcl_ChannelBlockModeProc( const Tcl_ChannelType *chanTypePtr); /* 401 */ EXTERN Tcl_DriverCloseProc * Tcl_ChannelCloseProc( const Tcl_ChannelType *chanTypePtr); /* 402 */ EXTERN Tcl_DriverClose2Proc * Tcl_ChannelClose2Proc( const Tcl_ChannelType *chanTypePtr); /* 403 */ EXTERN Tcl_DriverInputProc * Tcl_ChannelInputProc( const Tcl_ChannelType *chanTypePtr); /* 404 */ EXTERN Tcl_DriverOutputProc * Tcl_ChannelOutputProc( const Tcl_ChannelType *chanTypePtr); /* 405 */ EXTERN Tcl_DriverSeekProc * Tcl_ChannelSeekProc( const Tcl_ChannelType *chanTypePtr); /* 406 */ EXTERN Tcl_DriverSetOptionProc * Tcl_ChannelSetOptionProc( const Tcl_ChannelType *chanTypePtr); /* 407 */ EXTERN Tcl_DriverGetOptionProc * Tcl_ChannelGetOptionProc( const Tcl_ChannelType *chanTypePtr); /* 408 */ EXTERN Tcl_DriverWatchProc * Tcl_ChannelWatchProc( const Tcl_ChannelType *chanTypePtr); /* 409 */ EXTERN Tcl_DriverGetHandleProc * Tcl_ChannelGetHandleProc( const Tcl_ChannelType *chanTypePtr); /* 410 */ EXTERN Tcl_DriverFlushProc * Tcl_ChannelFlushProc( const Tcl_ChannelType *chanTypePtr); /* 411 */ EXTERN Tcl_DriverHandlerProc * Tcl_ChannelHandlerProc( const Tcl_ChannelType *chanTypePtr); /* 412 */ EXTERN int Tcl_JoinThread(Tcl_ThreadId threadId, int *result); /* 413 */ EXTERN int Tcl_IsChannelShared(Tcl_Channel channel); /* 414 */ EXTERN int Tcl_IsChannelRegistered(Tcl_Interp *interp, Tcl_Channel channel); /* 415 */ EXTERN void Tcl_CutChannel(Tcl_Channel channel); /* 416 */ EXTERN void Tcl_SpliceChannel(Tcl_Channel channel); /* 417 */ EXTERN void Tcl_ClearChannelHandlers(Tcl_Channel channel); /* 418 */ EXTERN int Tcl_IsChannelExisting(const char *channelName); /* 419 */ EXTERN int Tcl_UniCharNcasecmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsigned long numChars); /* 420 */ EXTERN int Tcl_UniCharCaseMatch(const Tcl_UniChar *uniStr, const Tcl_UniChar *uniPattern, int nocase); /* 421 */ EXTERN Tcl_HashEntry * Tcl_FindHashEntry(Tcl_HashTable *tablePtr, const void *key); /* 422 */ EXTERN Tcl_HashEntry * Tcl_CreateHashEntry(Tcl_HashTable *tablePtr, const void *key, int *newPtr); /* 423 */ EXTERN void Tcl_InitCustomHashTable(Tcl_HashTable *tablePtr, int keyType, const Tcl_HashKeyType *typePtr); /* 424 */ EXTERN void Tcl_InitObjHashTable(Tcl_HashTable *tablePtr); /* 425 */ EXTERN ClientData Tcl_CommandTraceInfo(Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *procPtr, ClientData prevClientData); /* 426 */ EXTERN int Tcl_TraceCommand(Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, ClientData clientData); /* 427 */ EXTERN void Tcl_UntraceCommand(Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, ClientData clientData); /* 428 */ EXTERN char * Tcl_AttemptAlloc(unsigned int size); /* 429 */ EXTERN char * Tcl_AttemptDbCkalloc(unsigned int size, const char *file, int line); /* 430 */ EXTERN char * Tcl_AttemptRealloc(char *ptr, unsigned int size); /* 431 */ EXTERN char * Tcl_AttemptDbCkrealloc(char *ptr, unsigned int size, const char *file, int line); /* 432 */ EXTERN int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr, int length); /* 433 */ EXTERN Tcl_ThreadId Tcl_GetChannelThread(Tcl_Channel channel); /* 434 */ EXTERN Tcl_UniChar * Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr, int *lengthPtr); /* 435 */ EXTERN int Tcl_GetMathFuncInfo(Tcl_Interp *interp, const char *name, int *numArgsPtr, Tcl_ValueType **argTypesPtr, Tcl_MathProc **procPtr, ClientData *clientDataPtr); /* 436 */ EXTERN Tcl_Obj * Tcl_ListMathFuncs(Tcl_Interp *interp, const char *pattern); /* 437 */ EXTERN Tcl_Obj * Tcl_SubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 438 */ EXTERN int Tcl_DetachChannel(Tcl_Interp *interp, Tcl_Channel channel); /* 439 */ EXTERN int Tcl_IsStandardChannel(Tcl_Channel channel); /* 440 */ EXTERN int Tcl_FSCopyFile(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 441 */ EXTERN int Tcl_FSCopyDirectory(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr); /* 442 */ EXTERN int Tcl_FSCreateDirectory(Tcl_Obj *pathPtr); /* 443 */ 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_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); /* 445 */ EXTERN int Tcl_FSMatchInDirectory(Tcl_Interp *interp, Tcl_Obj *result, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types); /* 446 */ EXTERN Tcl_Obj * Tcl_FSLink(Tcl_Obj *pathPtr, Tcl_Obj *toPtr, int linkAction); /* 447 */ EXTERN int Tcl_FSRemoveDirectory(Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr); /* 448 */ EXTERN int Tcl_FSRenameFile(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 449 */ EXTERN int Tcl_FSLstat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 450 */ EXTERN int Tcl_FSUtime(Tcl_Obj *pathPtr, struct utimbuf *tval); /* 451 */ EXTERN int Tcl_FSFileAttrsGet(Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); /* 452 */ EXTERN int Tcl_FSFileAttrsSet(Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj *objPtr); /* 453 */ EXTERN const char *CONST86 * Tcl_FSFileAttrStrings(Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); /* 454 */ EXTERN int Tcl_FSStat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 455 */ EXTERN int Tcl_FSAccess(Tcl_Obj *pathPtr, int mode); /* 456 */ EXTERN Tcl_Channel Tcl_FSOpenFileChannel(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *modeString, int permissions); /* 457 */ EXTERN Tcl_Obj * Tcl_FSGetCwd(Tcl_Interp *interp); /* 458 */ EXTERN int Tcl_FSChdir(Tcl_Obj *pathPtr); /* 459 */ EXTERN int Tcl_FSConvertToPathType(Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 460 */ EXTERN Tcl_Obj * Tcl_FSJoinPath(Tcl_Obj *listObj, int elements); /* 461 */ EXTERN Tcl_Obj * Tcl_FSSplitPath(Tcl_Obj *pathPtr, int *lenPtr); /* 462 */ EXTERN int Tcl_FSEqualPaths(Tcl_Obj *firstPtr, Tcl_Obj *secondPtr); /* 463 */ EXTERN Tcl_Obj * Tcl_FSGetNormalizedPath(Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 464 */ EXTERN Tcl_Obj * Tcl_FSJoinToPath(Tcl_Obj *pathPtr, int objc, Tcl_Obj *const objv[]); /* 465 */ EXTERN ClientData Tcl_FSGetInternalRep(Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr); /* 466 */ EXTERN Tcl_Obj * Tcl_FSGetTranslatedPath(Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 467 */ EXTERN int Tcl_FSEvalFile(Tcl_Interp *interp, Tcl_Obj *fileName); /* 468 */ EXTERN Tcl_Obj * Tcl_FSNewNativePath( const Tcl_Filesystem *fromFilesystem, ClientData clientData); /* 469 */ EXTERN const void * Tcl_FSGetNativePath(Tcl_Obj *pathPtr); /* 470 */ EXTERN Tcl_Obj * Tcl_FSFileSystemInfo(Tcl_Obj *pathPtr); /* 471 */ EXTERN Tcl_Obj * Tcl_FSPathSeparator(Tcl_Obj *pathPtr); /* 472 */ EXTERN Tcl_Obj * Tcl_FSListVolumes(void); /* 473 */ EXTERN int Tcl_FSRegister(ClientData clientData, const Tcl_Filesystem *fsPtr); /* 474 */ EXTERN int Tcl_FSUnregister(const Tcl_Filesystem *fsPtr); /* 475 */ EXTERN ClientData Tcl_FSData(const Tcl_Filesystem *fsPtr); /* 476 */ EXTERN const char * Tcl_FSGetTranslatedStringPath(Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 477 */ EXTERN CONST86 Tcl_Filesystem * Tcl_FSGetFileSystemForPath(Tcl_Obj *pathPtr); /* 478 */ EXTERN Tcl_PathType Tcl_FSGetPathType(Tcl_Obj *pathPtr); /* 479 */ EXTERN int Tcl_OutputBuffered(Tcl_Channel chan); /* 480 */ EXTERN void Tcl_FSMountsChanged(const Tcl_Filesystem *fsPtr); /* 481 */ EXTERN int Tcl_EvalTokensStandard(Tcl_Interp *interp, Tcl_Token *tokenPtr, int count); /* 482 */ EXTERN void Tcl_GetTime(Tcl_Time *timeBuf); /* 483 */ EXTERN Tcl_Trace Tcl_CreateObjTrace(Tcl_Interp *interp, int level, int flags, Tcl_CmdObjTraceProc *objProc, ClientData clientData, Tcl_CmdObjTraceDeleteProc *delProc); /* 484 */ EXTERN int Tcl_GetCommandInfoFromToken(Tcl_Command token, Tcl_CmdInfo *infoPtr); /* 485 */ EXTERN int Tcl_SetCommandInfoFromToken(Tcl_Command token, const Tcl_CmdInfo *infoPtr); /* 486 */ EXTERN Tcl_Obj * Tcl_DbNewWideIntObj(Tcl_WideInt wideValue, const char *file, int line); /* 487 */ EXTERN int Tcl_GetWideIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideInt *widePtr); /* 488 */ EXTERN Tcl_Obj * Tcl_NewWideIntObj(Tcl_WideInt wideValue); /* 489 */ EXTERN void Tcl_SetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt wideValue); /* 490 */ EXTERN Tcl_StatBuf * Tcl_AllocStatBuf(void); /* 491 */ EXTERN Tcl_WideInt Tcl_Seek(Tcl_Channel chan, Tcl_WideInt offset, int mode); /* 492 */ EXTERN Tcl_WideInt Tcl_Tell(Tcl_Channel chan); /* 493 */ EXTERN Tcl_DriverWideSeekProc * Tcl_ChannelWideSeekProc( const Tcl_ChannelType *chanTypePtr); /* 494 */ EXTERN int Tcl_DictObjPut(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj *valuePtr); /* 495 */ EXTERN int Tcl_DictObjGet(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr); /* 496 */ EXTERN int Tcl_DictObjRemove(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr); /* 497 */ EXTERN int Tcl_DictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr); /* 498 */ EXTERN int Tcl_DictObjFirst(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 499 */ EXTERN void Tcl_DictObjNext(Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 500 */ EXTERN void Tcl_DictObjDone(Tcl_DictSearch *searchPtr); /* 501 */ EXTERN int Tcl_DictObjPutKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr); /* 502 */ EXTERN int Tcl_DictObjRemoveKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const *keyv); /* 503 */ EXTERN Tcl_Obj * Tcl_NewDictObj(void); /* 504 */ EXTERN Tcl_Obj * Tcl_DbNewDictObj(const char *file, int line); /* 505 */ EXTERN void Tcl_RegisterConfig(Tcl_Interp *interp, const char *pkgName, const Tcl_Config *configuration, const char *valEncoding); /* 506 */ EXTERN Tcl_Namespace * Tcl_CreateNamespace(Tcl_Interp *interp, const char *name, ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc); /* 507 */ EXTERN void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr); /* 508 */ EXTERN int Tcl_AppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *objPtr); /* 509 */ EXTERN int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int resetListFirst); /* 510 */ EXTERN int Tcl_Import(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int allowOverwrite); /* 511 */ EXTERN int Tcl_ForgetImport(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern); /* 512 */ EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace(Tcl_Interp *interp); /* 513 */ EXTERN Tcl_Namespace * Tcl_GetGlobalNamespace(Tcl_Interp *interp); /* 514 */ EXTERN Tcl_Namespace * Tcl_FindNamespace(Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags); /* 515 */ EXTERN Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags); /* 516 */ EXTERN Tcl_Command Tcl_GetCommandFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr); /* 517 */ EXTERN void Tcl_GetCommandFullName(Tcl_Interp *interp, Tcl_Command command, Tcl_Obj *objPtr); /* 518 */ EXTERN int Tcl_FSEvalFileEx(Tcl_Interp *interp, Tcl_Obj *fileName, const char *encodingName); /* 519 */ EXTERN Tcl_ExitProc * Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc); /* 520 */ EXTERN void Tcl_LimitAddHandler(Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData, Tcl_LimitHandlerDeleteProc *deleteProc); /* 521 */ EXTERN void Tcl_LimitRemoveHandler(Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData); /* 522 */ EXTERN int Tcl_LimitReady(Tcl_Interp *interp); /* 523 */ EXTERN int Tcl_LimitCheck(Tcl_Interp *interp); /* 524 */ EXTERN int Tcl_LimitExceeded(Tcl_Interp *interp); /* 525 */ EXTERN void Tcl_LimitSetCommands(Tcl_Interp *interp, int commandLimit); /* 526 */ EXTERN void Tcl_LimitSetTime(Tcl_Interp *interp, Tcl_Time *timeLimitPtr); /* 527 */ EXTERN void Tcl_LimitSetGranularity(Tcl_Interp *interp, int type, int granularity); /* 528 */ EXTERN int Tcl_LimitTypeEnabled(Tcl_Interp *interp, int type); /* 529 */ EXTERN int Tcl_LimitTypeExceeded(Tcl_Interp *interp, int type); /* 530 */ EXTERN void Tcl_LimitTypeSet(Tcl_Interp *interp, int type); /* 531 */ EXTERN void Tcl_LimitTypeReset(Tcl_Interp *interp, int type); /* 532 */ EXTERN int Tcl_LimitGetCommands(Tcl_Interp *interp); /* 533 */ EXTERN void Tcl_LimitGetTime(Tcl_Interp *interp, Tcl_Time *timeLimitPtr); /* 534 */ EXTERN int Tcl_LimitGetGranularity(Tcl_Interp *interp, int type); /* 535 */ EXTERN Tcl_InterpState Tcl_SaveInterpState(Tcl_Interp *interp, int status); /* 536 */ EXTERN int Tcl_RestoreInterpState(Tcl_Interp *interp, Tcl_InterpState state); /* 537 */ EXTERN void Tcl_DiscardInterpState(Tcl_InterpState state); /* 538 */ EXTERN int Tcl_SetReturnOptions(Tcl_Interp *interp, Tcl_Obj *options); /* 539 */ EXTERN Tcl_Obj * Tcl_GetReturnOptions(Tcl_Interp *interp, int result); /* 540 */ EXTERN int Tcl_IsEnsemble(Tcl_Command token); /* 541 */ EXTERN Tcl_Command Tcl_CreateEnsemble(Tcl_Interp *interp, const char *name, Tcl_Namespace *namespacePtr, int flags); /* 542 */ EXTERN Tcl_Command Tcl_FindEnsemble(Tcl_Interp *interp, Tcl_Obj *cmdNameObj, int flags); /* 543 */ EXTERN int Tcl_SetEnsembleSubcommandList(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *subcmdList); /* 544 */ EXTERN int Tcl_SetEnsembleMappingDict(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *mapDict); /* 545 */ EXTERN int Tcl_SetEnsembleUnknownHandler(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *unknownList); /* 546 */ EXTERN int Tcl_SetEnsembleFlags(Tcl_Interp *interp, Tcl_Command token, int flags); /* 547 */ EXTERN int Tcl_GetEnsembleSubcommandList(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **subcmdListPtr); /* 548 */ EXTERN int Tcl_GetEnsembleMappingDict(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **mapDictPtr); /* 549 */ EXTERN int Tcl_GetEnsembleUnknownHandler(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **unknownListPtr); /* 550 */ EXTERN int Tcl_GetEnsembleFlags(Tcl_Interp *interp, Tcl_Command token, int *flagsPtr); /* 551 */ EXTERN int Tcl_GetEnsembleNamespace(Tcl_Interp *interp, Tcl_Command token, Tcl_Namespace **namespacePtrPtr); /* 552 */ EXTERN void Tcl_SetTimeProc(Tcl_GetTimeProc *getProc, Tcl_ScaleTimeProc *scaleProc, ClientData clientData); /* 553 */ EXTERN void Tcl_QueryTimeProc(Tcl_GetTimeProc **getProc, Tcl_ScaleTimeProc **scaleProc, ClientData *clientData); /* 554 */ EXTERN Tcl_DriverThreadActionProc * Tcl_ChannelThreadActionProc( const Tcl_ChannelType *chanTypePtr); /* 555 */ EXTERN Tcl_Obj * Tcl_NewBignumObj(mp_int *value); /* 556 */ EXTERN Tcl_Obj * Tcl_DbNewBignumObj(mp_int *value, const char *file, int line); /* 557 */ EXTERN void Tcl_SetBignumObj(Tcl_Obj *obj, mp_int *value); /* 558 */ EXTERN int Tcl_GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value); /* 559 */ EXTERN int Tcl_TakeBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value); /* 560 */ EXTERN int Tcl_TruncateChannel(Tcl_Channel chan, Tcl_WideInt length); /* 561 */ EXTERN Tcl_DriverTruncateProc * Tcl_ChannelTruncateProc( const Tcl_ChannelType *chanTypePtr); /* 562 */ EXTERN void Tcl_SetChannelErrorInterp(Tcl_Interp *interp, Tcl_Obj *msg); /* 563 */ EXTERN void Tcl_GetChannelErrorInterp(Tcl_Interp *interp, Tcl_Obj **msg); /* 564 */ EXTERN void Tcl_SetChannelError(Tcl_Channel chan, Tcl_Obj *msg); /* 565 */ EXTERN void Tcl_GetChannelError(Tcl_Channel chan, Tcl_Obj **msg); /* 566 */ EXTERN int Tcl_InitBignumFromDouble(Tcl_Interp *interp, double initval, mp_int *toInit); /* 567 */ EXTERN Tcl_Obj * Tcl_GetNamespaceUnknownHandler(Tcl_Interp *interp, Tcl_Namespace *nsPtr); /* 568 */ EXTERN int Tcl_SetNamespaceUnknownHandler(Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *handlerPtr); /* 569 */ EXTERN int Tcl_GetEncodingFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr); /* 570 */ EXTERN Tcl_Obj * Tcl_GetEncodingSearchPath(void); /* 571 */ EXTERN int Tcl_SetEncodingSearchPath(Tcl_Obj *searchPath); /* 572 */ EXTERN const char * Tcl_GetEncodingNameFromEnvironment( Tcl_DString *bufPtr); /* 573 */ EXTERN int Tcl_PkgRequireProc(Tcl_Interp *interp, const char *name, int objc, Tcl_Obj *const objv[], void *clientDataPtr); /* 574 */ EXTERN void Tcl_AppendObjToErrorInfo(Tcl_Interp *interp, Tcl_Obj *objPtr); /* 575 */ EXTERN void Tcl_AppendLimitedToObj(Tcl_Obj *objPtr, const char *bytes, int length, int limit, const char *ellipsis); /* 576 */ EXTERN Tcl_Obj * Tcl_Format(Tcl_Interp *interp, const char *format, int objc, Tcl_Obj *const objv[]); /* 577 */ EXTERN int Tcl_AppendFormatToObj(Tcl_Interp *interp, Tcl_Obj *objPtr, const char *format, int objc, Tcl_Obj *const objv[]); /* 578 */ EXTERN Tcl_Obj * Tcl_ObjPrintf(const char *format, ...) TCL_FORMAT_PRINTF(1, 2); /* 579 */ EXTERN void Tcl_AppendPrintfToObj(Tcl_Obj *objPtr, const char *format, ...) TCL_FORMAT_PRINTF(2, 3); /* 580 */ EXTERN int Tcl_CancelEval(Tcl_Interp *interp, Tcl_Obj *resultObjPtr, ClientData clientData, int flags); /* 581 */ EXTERN int Tcl_Canceled(Tcl_Interp *interp, int flags); /* 582 */ EXTERN int Tcl_CreatePipe(Tcl_Interp *interp, Tcl_Channel *rchan, Tcl_Channel *wchan, int flags); /* 583 */ EXTERN Tcl_Command Tcl_NRCreateCommand(Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, Tcl_ObjCmdProc *nreProc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 584 */ EXTERN int Tcl_NREvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 585 */ EXTERN int Tcl_NREvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 586 */ EXTERN int Tcl_NRCmdSwap(Tcl_Interp *interp, Tcl_Command cmd, int objc, Tcl_Obj *const objv[], int flags); /* 587 */ EXTERN void Tcl_NRAddCallback(Tcl_Interp *interp, Tcl_NRPostProc *postProcPtr, ClientData data0, ClientData data1, ClientData data2, ClientData data3); /* 588 */ EXTERN int Tcl_NRCallObjProc(Tcl_Interp *interp, Tcl_ObjCmdProc *objProc, ClientData clientData, int objc, Tcl_Obj *const objv[]); /* 589 */ EXTERN unsigned Tcl_GetFSDeviceFromStat(const Tcl_StatBuf *statPtr); /* 590 */ EXTERN unsigned Tcl_GetFSInodeFromStat(const Tcl_StatBuf *statPtr); /* 591 */ EXTERN unsigned Tcl_GetModeFromStat(const Tcl_StatBuf *statPtr); /* 592 */ EXTERN int Tcl_GetLinkCountFromStat(const Tcl_StatBuf *statPtr); /* 593 */ EXTERN int Tcl_GetUserIdFromStat(const Tcl_StatBuf *statPtr); /* 594 */ EXTERN int Tcl_GetGroupIdFromStat(const Tcl_StatBuf *statPtr); /* 595 */ EXTERN int Tcl_GetDeviceTypeFromStat(const Tcl_StatBuf *statPtr); /* 596 */ EXTERN Tcl_WideInt Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr); /* 597 */ EXTERN Tcl_WideInt Tcl_GetModificationTimeFromStat( const Tcl_StatBuf *statPtr); /* 598 */ EXTERN Tcl_WideInt Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr); /* 599 */ EXTERN Tcl_WideUInt Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr); /* 600 */ EXTERN Tcl_WideUInt Tcl_GetBlocksFromStat(const Tcl_StatBuf *statPtr); /* 601 */ EXTERN unsigned Tcl_GetBlockSizeFromStat(const Tcl_StatBuf *statPtr); /* 602 */ EXTERN int Tcl_SetEnsembleParameterList(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *paramList); /* 603 */ EXTERN int Tcl_GetEnsembleParameterList(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **paramListPtr); /* 604 */ EXTERN int Tcl_ParseArgsObjv(Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, int *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 605 */ EXTERN int Tcl_GetErrorLine(Tcl_Interp *interp); /* 606 */ EXTERN void Tcl_SetErrorLine(Tcl_Interp *interp, int lineNum); /* 607 */ EXTERN void Tcl_TransferResult(Tcl_Interp *sourceInterp, int result, Tcl_Interp *targetInterp); /* 608 */ EXTERN int Tcl_InterpActive(Tcl_Interp *interp); /* 609 */ EXTERN void Tcl_BackgroundException(Tcl_Interp *interp, int code); /* 610 */ EXTERN int Tcl_ZlibDeflate(Tcl_Interp *interp, int format, Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj); /* 611 */ EXTERN int Tcl_ZlibInflate(Tcl_Interp *interp, int format, Tcl_Obj *data, int buffersize, Tcl_Obj *gzipHeaderDictObj); /* 612 */ EXTERN unsigned int Tcl_ZlibCRC32(unsigned int crc, const unsigned char *buf, int len); /* 613 */ EXTERN unsigned int Tcl_ZlibAdler32(unsigned int adler, const unsigned char *buf, int len); /* 614 */ EXTERN int Tcl_ZlibStreamInit(Tcl_Interp *interp, int mode, int format, int level, Tcl_Obj *dictObj, Tcl_ZlibStream *zshandle); /* 615 */ EXTERN Tcl_Obj * Tcl_ZlibStreamGetCommandName(Tcl_ZlibStream zshandle); /* 616 */ EXTERN int Tcl_ZlibStreamEof(Tcl_ZlibStream zshandle); /* 617 */ EXTERN int Tcl_ZlibStreamChecksum(Tcl_ZlibStream zshandle); /* 618 */ EXTERN int Tcl_ZlibStreamPut(Tcl_ZlibStream zshandle, Tcl_Obj *data, int flush); /* 619 */ EXTERN int Tcl_ZlibStreamGet(Tcl_ZlibStream zshandle, Tcl_Obj *data, int count); /* 620 */ EXTERN int Tcl_ZlibStreamClose(Tcl_ZlibStream zshandle); /* 621 */ EXTERN int Tcl_ZlibStreamReset(Tcl_ZlibStream zshandle); /* 622 */ EXTERN void Tcl_SetStartupScript(Tcl_Obj *path, const char *encoding); /* 623 */ EXTERN Tcl_Obj * Tcl_GetStartupScript(const char **encodingPtr); /* 624 */ EXTERN int Tcl_CloseEx(Tcl_Interp *interp, Tcl_Channel chan, int flags); /* 625 */ EXTERN int Tcl_NRExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj *resultPtr); /* 626 */ EXTERN int Tcl_NRSubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 627 */ EXTERN int Tcl_LoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *const symv[], int flags, void *procPtrs, Tcl_LoadHandle *handlePtr); /* 628 */ EXTERN void * Tcl_FindSymbol(Tcl_Interp *interp, Tcl_LoadHandle handle, const char *symbol); /* 629 */ EXTERN int Tcl_FSUnloadFile(Tcl_Interp *interp, Tcl_LoadHandle handlePtr); /* 630 */ EXTERN void Tcl_ZlibStreamSetCompressionDictionary( Tcl_ZlibStream zhandle, Tcl_Obj *compressionDictionaryObj); typedef struct { const struct TclPlatStubs *tclPlatStubs; const struct TclIntStubs *tclIntStubs; const struct TclIntPlatStubs *tclIntPlatStubs; } TclStubHooks; typedef struct TclStubs { int magic; const TclStubHooks *hooks; int (*tcl_PkgProvideEx) (Tcl_Interp *interp, const char *name, const char *version, const void *clientData); /* 0 */ CONST84_RETURN char * (*tcl_PkgRequireEx) (Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr); /* 1 */ TCL_NORETURN1 void (*tcl_Panic) (const char *format, ...) TCL_FORMAT_PRINTF(1, 2); /* 2 */ char * (*tcl_Alloc) (unsigned int size); /* 3 */ void (*tcl_Free) (char *ptr); /* 4 */ char * (*tcl_Realloc) (char *ptr, unsigned int size); /* 5 */ char * (*tcl_DbCkalloc) (unsigned int size, const char *file, int line); /* 6 */ void (*tcl_DbCkfree) (char *ptr, const char *file, int line); /* 7 */ char * (*tcl_DbCkrealloc) (char *ptr, unsigned int size, const char *file, int line); /* 8 */ #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ void (*tcl_CreateFileHandler) (int fd, int mask, Tcl_FileProc *proc, ClientData clientData); /* 9 */ #endif /* UNIX */ #if defined(_WIN32) /* WIN */ void (*reserved9)(void); #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ void (*tcl_CreateFileHandler) (int fd, int mask, Tcl_FileProc *proc, ClientData clientData); /* 9 */ #endif /* MACOSX */ #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ void (*tcl_DeleteFileHandler) (int fd); /* 10 */ #endif /* UNIX */ #if defined(_WIN32) /* WIN */ void (*reserved10)(void); #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ void (*tcl_DeleteFileHandler) (int fd); /* 10 */ #endif /* MACOSX */ void (*tcl_SetTimer) (const Tcl_Time *timePtr); /* 11 */ void (*tcl_Sleep) (int ms); /* 12 */ int (*tcl_WaitForEvent) (const Tcl_Time *timePtr); /* 13 */ int (*tcl_AppendAllObjTypes) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 14 */ void (*tcl_AppendStringsToObj) (Tcl_Obj *objPtr, ...); /* 15 */ void (*tcl_AppendToObj) (Tcl_Obj *objPtr, const char *bytes, int length); /* 16 */ Tcl_Obj * (*tcl_ConcatObj) (int objc, Tcl_Obj *const objv[]); /* 17 */ int (*tcl_ConvertToType) (Tcl_Interp *interp, Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 18 */ void (*tcl_DbDecrRefCount) (Tcl_Obj *objPtr, const char *file, int line); /* 19 */ void (*tcl_DbIncrRefCount) (Tcl_Obj *objPtr, const char *file, int line); /* 20 */ int (*tcl_DbIsShared) (Tcl_Obj *objPtr, const char *file, int line); /* 21 */ Tcl_Obj * (*tcl_DbNewBooleanObj) (int boolValue, const char *file, int line); /* 22 */ Tcl_Obj * (*tcl_DbNewByteArrayObj) (const unsigned char *bytes, int length, const char *file, int line); /* 23 */ Tcl_Obj * (*tcl_DbNewDoubleObj) (double doubleValue, const char *file, int line); /* 24 */ Tcl_Obj * (*tcl_DbNewListObj) (int objc, Tcl_Obj *const *objv, const char *file, int line); /* 25 */ Tcl_Obj * (*tcl_DbNewLongObj) (long longValue, const char *file, int line); /* 26 */ Tcl_Obj * (*tcl_DbNewObj) (const char *file, int line); /* 27 */ Tcl_Obj * (*tcl_DbNewStringObj) (const char *bytes, int length, const char *file, int line); /* 28 */ Tcl_Obj * (*tcl_DuplicateObj) (Tcl_Obj *objPtr); /* 29 */ void (*tclFreeObj) (Tcl_Obj *objPtr); /* 30 */ int (*tcl_GetBoolean) (Tcl_Interp *interp, const char *src, int *boolPtr); /* 31 */ int (*tcl_GetBooleanFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *boolPtr); /* 32 */ unsigned char * (*tcl_GetByteArrayFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 33 */ int (*tcl_GetDouble) (Tcl_Interp *interp, const char *src, double *doublePtr); /* 34 */ int (*tcl_GetDoubleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, double *doublePtr); /* 35 */ int (*tcl_GetIndexFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, CONST84 char *const *tablePtr, const char *msg, int flags, int *indexPtr); /* 36 */ int (*tcl_GetInt) (Tcl_Interp *interp, const char *src, int *intPtr); /* 37 */ int (*tcl_GetIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr); /* 38 */ int (*tcl_GetLongFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr); /* 39 */ CONST86 Tcl_ObjType * (*tcl_GetObjType) (const char *typeName); /* 40 */ char * (*tcl_GetStringFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 41 */ void (*tcl_InvalidateStringRep) (Tcl_Obj *objPtr); /* 42 */ int (*tcl_ListObjAppendList) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr); /* 43 */ int (*tcl_ListObjAppendElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr); /* 44 */ int (*tcl_ListObjGetElements) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *objcPtr, Tcl_Obj ***objvPtr); /* 45 */ int (*tcl_ListObjIndex) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj **objPtrPtr); /* 46 */ int (*tcl_ListObjLength) (Tcl_Interp *interp, Tcl_Obj *listPtr, int *lengthPtr); /* 47 */ int (*tcl_ListObjReplace) (Tcl_Interp *interp, Tcl_Obj *listPtr, int first, int count, int objc, Tcl_Obj *const objv[]); /* 48 */ Tcl_Obj * (*tcl_NewBooleanObj) (int boolValue); /* 49 */ Tcl_Obj * (*tcl_NewByteArrayObj) (const unsigned char *bytes, int length); /* 50 */ Tcl_Obj * (*tcl_NewDoubleObj) (double doubleValue); /* 51 */ Tcl_Obj * (*tcl_NewIntObj) (int intValue); /* 52 */ Tcl_Obj * (*tcl_NewListObj) (int objc, Tcl_Obj *const objv[]); /* 53 */ Tcl_Obj * (*tcl_NewLongObj) (long longValue); /* 54 */ Tcl_Obj * (*tcl_NewObj) (void); /* 55 */ Tcl_Obj * (*tcl_NewStringObj) (const char *bytes, int length); /* 56 */ void (*tcl_SetBooleanObj) (Tcl_Obj *objPtr, int boolValue); /* 57 */ unsigned char * (*tcl_SetByteArrayLength) (Tcl_Obj *objPtr, int length); /* 58 */ void (*tcl_SetByteArrayObj) (Tcl_Obj *objPtr, const unsigned char *bytes, int length); /* 59 */ void (*tcl_SetDoubleObj) (Tcl_Obj *objPtr, double doubleValue); /* 60 */ void (*tcl_SetIntObj) (Tcl_Obj *objPtr, int intValue); /* 61 */ void (*tcl_SetListObj) (Tcl_Obj *objPtr, int objc, Tcl_Obj *const objv[]); /* 62 */ void (*tcl_SetLongObj) (Tcl_Obj *objPtr, long longValue); /* 63 */ void (*tcl_SetObjLength) (Tcl_Obj *objPtr, int length); /* 64 */ void (*tcl_SetStringObj) (Tcl_Obj *objPtr, const char *bytes, int length); /* 65 */ void (*tcl_AddErrorInfo) (Tcl_Interp *interp, const char *message); /* 66 */ void (*tcl_AddObjErrorInfo) (Tcl_Interp *interp, const char *message, int length); /* 67 */ void (*tcl_AllowExceptions) (Tcl_Interp *interp); /* 68 */ void (*tcl_AppendElement) (Tcl_Interp *interp, const char *element); /* 69 */ void (*tcl_AppendResult) (Tcl_Interp *interp, ...); /* 70 */ Tcl_AsyncHandler (*tcl_AsyncCreate) (Tcl_AsyncProc *proc, ClientData clientData); /* 71 */ void (*tcl_AsyncDelete) (Tcl_AsyncHandler async); /* 72 */ int (*tcl_AsyncInvoke) (Tcl_Interp *interp, int code); /* 73 */ void (*tcl_AsyncMark) (Tcl_AsyncHandler async); /* 74 */ int (*tcl_AsyncReady) (void); /* 75 */ void (*tcl_BackgroundError) (Tcl_Interp *interp); /* 76 */ char (*tcl_Backslash) (const char *src, int *readPtr); /* 77 */ int (*tcl_BadChannelOption) (Tcl_Interp *interp, const char *optionName, const char *optionList); /* 78 */ void (*tcl_CallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 79 */ void (*tcl_CancelIdleCall) (Tcl_IdleProc *idleProc, ClientData clientData); /* 80 */ int (*tcl_Close) (Tcl_Interp *interp, Tcl_Channel chan); /* 81 */ int (*tcl_CommandComplete) (const char *cmd); /* 82 */ char * (*tcl_Concat) (int argc, CONST84 char *const *argv); /* 83 */ int (*tcl_ConvertElement) (const char *src, char *dst, int flags); /* 84 */ int (*tcl_ConvertCountedElement) (const char *src, int length, char *dst, int flags); /* 85 */ int (*tcl_CreateAlias) (Tcl_Interp *slave, const char *slaveCmd, Tcl_Interp *target, const char *targetCmd, int argc, CONST84 char *const *argv); /* 86 */ int (*tcl_CreateAliasObj) (Tcl_Interp *slave, const char *slaveCmd, Tcl_Interp *target, const char *targetCmd, int objc, Tcl_Obj *const objv[]); /* 87 */ Tcl_Channel (*tcl_CreateChannel) (const Tcl_ChannelType *typePtr, const char *chanName, ClientData instanceData, int mask); /* 88 */ void (*tcl_CreateChannelHandler) (Tcl_Channel chan, int mask, Tcl_ChannelProc *proc, ClientData clientData); /* 89 */ void (*tcl_CreateCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData); /* 90 */ Tcl_Command (*tcl_CreateCommand) (Tcl_Interp *interp, const char *cmdName, Tcl_CmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 91 */ void (*tcl_CreateEventSource) (Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, ClientData clientData); /* 92 */ void (*tcl_CreateExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 93 */ Tcl_Interp * (*tcl_CreateInterp) (void); /* 94 */ void (*tcl_CreateMathFunc) (Tcl_Interp *interp, const char *name, int numArgs, Tcl_ValueType *argTypes, Tcl_MathProc *proc, ClientData clientData); /* 95 */ Tcl_Command (*tcl_CreateObjCommand) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 96 */ Tcl_Interp * (*tcl_CreateSlave) (Tcl_Interp *interp, const char *slaveName, int isSafe); /* 97 */ Tcl_TimerToken (*tcl_CreateTimerHandler) (int milliseconds, Tcl_TimerProc *proc, ClientData clientData); /* 98 */ Tcl_Trace (*tcl_CreateTrace) (Tcl_Interp *interp, int level, Tcl_CmdTraceProc *proc, ClientData clientData); /* 99 */ void (*tcl_DeleteAssocData) (Tcl_Interp *interp, const char *name); /* 100 */ void (*tcl_DeleteChannelHandler) (Tcl_Channel chan, Tcl_ChannelProc *proc, ClientData clientData); /* 101 */ void (*tcl_DeleteCloseHandler) (Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData); /* 102 */ int (*tcl_DeleteCommand) (Tcl_Interp *interp, const char *cmdName); /* 103 */ int (*tcl_DeleteCommandFromToken) (Tcl_Interp *interp, Tcl_Command command); /* 104 */ void (*tcl_DeleteEvents) (Tcl_EventDeleteProc *proc, ClientData clientData); /* 105 */ void (*tcl_DeleteEventSource) (Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, ClientData clientData); /* 106 */ void (*tcl_DeleteExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 107 */ void (*tcl_DeleteHashEntry) (Tcl_HashEntry *entryPtr); /* 108 */ void (*tcl_DeleteHashTable) (Tcl_HashTable *tablePtr); /* 109 */ void (*tcl_DeleteInterp) (Tcl_Interp *interp); /* 110 */ void (*tcl_DetachPids) (int numPids, Tcl_Pid *pidPtr); /* 111 */ void (*tcl_DeleteTimerHandler) (Tcl_TimerToken token); /* 112 */ void (*tcl_DeleteTrace) (Tcl_Interp *interp, Tcl_Trace trace); /* 113 */ void (*tcl_DontCallWhenDeleted) (Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 114 */ int (*tcl_DoOneEvent) (int flags); /* 115 */ void (*tcl_DoWhenIdle) (Tcl_IdleProc *proc, ClientData clientData); /* 116 */ char * (*tcl_DStringAppend) (Tcl_DString *dsPtr, const char *bytes, int length); /* 117 */ char * (*tcl_DStringAppendElement) (Tcl_DString *dsPtr, const char *element); /* 118 */ void (*tcl_DStringEndSublist) (Tcl_DString *dsPtr); /* 119 */ void (*tcl_DStringFree) (Tcl_DString *dsPtr); /* 120 */ void (*tcl_DStringGetResult) (Tcl_Interp *interp, Tcl_DString *dsPtr); /* 121 */ void (*tcl_DStringInit) (Tcl_DString *dsPtr); /* 122 */ void (*tcl_DStringResult) (Tcl_Interp *interp, Tcl_DString *dsPtr); /* 123 */ void (*tcl_DStringSetLength) (Tcl_DString *dsPtr, int length); /* 124 */ void (*tcl_DStringStartSublist) (Tcl_DString *dsPtr); /* 125 */ int (*tcl_Eof) (Tcl_Channel chan); /* 126 */ CONST84_RETURN char * (*tcl_ErrnoId) (void); /* 127 */ CONST84_RETURN char * (*tcl_ErrnoMsg) (int err); /* 128 */ int (*tcl_Eval) (Tcl_Interp *interp, const char *script); /* 129 */ int (*tcl_EvalFile) (Tcl_Interp *interp, const char *fileName); /* 130 */ int (*tcl_EvalObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 131 */ void (*tcl_EventuallyFree) (ClientData clientData, Tcl_FreeProc *freeProc); /* 132 */ TCL_NORETURN1 void (*tcl_Exit) (int status); /* 133 */ int (*tcl_ExposeCommand) (Tcl_Interp *interp, const char *hiddenCmdToken, const char *cmdName); /* 134 */ int (*tcl_ExprBoolean) (Tcl_Interp *interp, const char *expr, int *ptr); /* 135 */ int (*tcl_ExprBooleanObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *ptr); /* 136 */ int (*tcl_ExprDouble) (Tcl_Interp *interp, const char *expr, double *ptr); /* 137 */ int (*tcl_ExprDoubleObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, double *ptr); /* 138 */ int (*tcl_ExprLong) (Tcl_Interp *interp, const char *expr, long *ptr); /* 139 */ int (*tcl_ExprLongObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, long *ptr); /* 140 */ int (*tcl_ExprObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr); /* 141 */ int (*tcl_ExprString) (Tcl_Interp *interp, const char *expr); /* 142 */ void (*tcl_Finalize) (void); /* 143 */ void (*tcl_FindExecutable) (const char *argv0); /* 144 */ Tcl_HashEntry * (*tcl_FirstHashEntry) (Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr); /* 145 */ int (*tcl_Flush) (Tcl_Channel chan); /* 146 */ void (*tcl_FreeResult) (Tcl_Interp *interp); /* 147 */ int (*tcl_GetAlias) (Tcl_Interp *interp, const char *slaveCmd, Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr, int *argcPtr, CONST84 char ***argvPtr); /* 148 */ int (*tcl_GetAliasObj) (Tcl_Interp *interp, const char *slaveCmd, Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr, int *objcPtr, Tcl_Obj ***objv); /* 149 */ ClientData (*tcl_GetAssocData) (Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc **procPtr); /* 150 */ Tcl_Channel (*tcl_GetChannel) (Tcl_Interp *interp, const char *chanName, int *modePtr); /* 151 */ int (*tcl_GetChannelBufferSize) (Tcl_Channel chan); /* 152 */ int (*tcl_GetChannelHandle) (Tcl_Channel chan, int direction, ClientData *handlePtr); /* 153 */ ClientData (*tcl_GetChannelInstanceData) (Tcl_Channel chan); /* 154 */ int (*tcl_GetChannelMode) (Tcl_Channel chan); /* 155 */ CONST84_RETURN char * (*tcl_GetChannelName) (Tcl_Channel chan); /* 156 */ int (*tcl_GetChannelOption) (Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, Tcl_DString *dsPtr); /* 157 */ CONST86 Tcl_ChannelType * (*tcl_GetChannelType) (Tcl_Channel chan); /* 158 */ int (*tcl_GetCommandInfo) (Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr); /* 159 */ CONST84_RETURN char * (*tcl_GetCommandName) (Tcl_Interp *interp, Tcl_Command command); /* 160 */ int (*tcl_GetErrno) (void); /* 161 */ CONST84_RETURN char * (*tcl_GetHostName) (void); /* 162 */ int (*tcl_GetInterpPath) (Tcl_Interp *askInterp, Tcl_Interp *slaveInterp); /* 163 */ Tcl_Interp * (*tcl_GetMaster) (Tcl_Interp *interp); /* 164 */ const char * (*tcl_GetNameOfExecutable) (void); /* 165 */ Tcl_Obj * (*tcl_GetObjResult) (Tcl_Interp *interp); /* 166 */ #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ int (*tcl_GetOpenFile) (Tcl_Interp *interp, const char *chanID, int forWriting, int checkUsage, ClientData *filePtr); /* 167 */ #endif /* UNIX */ #if defined(_WIN32) /* WIN */ void (*reserved167)(void); #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ int (*tcl_GetOpenFile) (Tcl_Interp *interp, const char *chanID, int forWriting, int checkUsage, ClientData *filePtr); /* 167 */ #endif /* MACOSX */ Tcl_PathType (*tcl_GetPathType) (const char *path); /* 168 */ int (*tcl_Gets) (Tcl_Channel chan, Tcl_DString *dsPtr); /* 169 */ int (*tcl_GetsObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 170 */ int (*tcl_GetServiceMode) (void); /* 171 */ Tcl_Interp * (*tcl_GetSlave) (Tcl_Interp *interp, const char *slaveName); /* 172 */ Tcl_Channel (*tcl_GetStdChannel) (int type); /* 173 */ CONST84_RETURN char * (*tcl_GetStringResult) (Tcl_Interp *interp); /* 174 */ CONST84_RETURN char * (*tcl_GetVar) (Tcl_Interp *interp, const char *varName, int flags); /* 175 */ CONST84_RETURN char * (*tcl_GetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 176 */ int (*tcl_GlobalEval) (Tcl_Interp *interp, const char *command); /* 177 */ int (*tcl_GlobalEvalObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 178 */ int (*tcl_HideCommand) (Tcl_Interp *interp, const char *cmdName, const char *hiddenCmdToken); /* 179 */ int (*tcl_Init) (Tcl_Interp *interp); /* 180 */ void (*tcl_InitHashTable) (Tcl_HashTable *tablePtr, int keyType); /* 181 */ int (*tcl_InputBlocked) (Tcl_Channel chan); /* 182 */ int (*tcl_InputBuffered) (Tcl_Channel chan); /* 183 */ int (*tcl_InterpDeleted) (Tcl_Interp *interp); /* 184 */ int (*tcl_IsSafe) (Tcl_Interp *interp); /* 185 */ char * (*tcl_JoinPath) (int argc, CONST84 char *const *argv, Tcl_DString *resultPtr); /* 186 */ int (*tcl_LinkVar) (Tcl_Interp *interp, const char *varName, char *addr, int type); /* 187 */ void (*reserved188)(void); Tcl_Channel (*tcl_MakeFileChannel) (ClientData handle, int mode); /* 189 */ int (*tcl_MakeSafe) (Tcl_Interp *interp); /* 190 */ Tcl_Channel (*tcl_MakeTcpClientChannel) (ClientData tcpSocket); /* 191 */ char * (*tcl_Merge) (int argc, CONST84 char *const *argv); /* 192 */ Tcl_HashEntry * (*tcl_NextHashEntry) (Tcl_HashSearch *searchPtr); /* 193 */ void (*tcl_NotifyChannel) (Tcl_Channel channel, int mask); /* 194 */ Tcl_Obj * (*tcl_ObjGetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 195 */ Tcl_Obj * (*tcl_ObjSetVar2) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags); /* 196 */ Tcl_Channel (*tcl_OpenCommandChannel) (Tcl_Interp *interp, int argc, CONST84 char **argv, int flags); /* 197 */ Tcl_Channel (*tcl_OpenFileChannel) (Tcl_Interp *interp, const char *fileName, const char *modeString, int permissions); /* 198 */ Tcl_Channel (*tcl_OpenTcpClient) (Tcl_Interp *interp, int port, const char *address, const char *myaddr, int myport, int async); /* 199 */ Tcl_Channel (*tcl_OpenTcpServer) (Tcl_Interp *interp, int port, const char *host, Tcl_TcpAcceptProc *acceptProc, ClientData callbackData); /* 200 */ void (*tcl_Preserve) (ClientData data); /* 201 */ void (*tcl_PrintDouble) (Tcl_Interp *interp, double value, char *dst); /* 202 */ int (*tcl_PutEnv) (const char *assignment); /* 203 */ CONST84_RETURN char * (*tcl_PosixError) (Tcl_Interp *interp); /* 204 */ void (*tcl_QueueEvent) (Tcl_Event *evPtr, Tcl_QueuePosition position); /* 205 */ int (*tcl_Read) (Tcl_Channel chan, char *bufPtr, int toRead); /* 206 */ void (*tcl_ReapDetachedProcs) (void); /* 207 */ int (*tcl_RecordAndEval) (Tcl_Interp *interp, const char *cmd, int flags); /* 208 */ int (*tcl_RecordAndEvalObj) (Tcl_Interp *interp, Tcl_Obj *cmdPtr, int flags); /* 209 */ void (*tcl_RegisterChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 210 */ void (*tcl_RegisterObjType) (const Tcl_ObjType *typePtr); /* 211 */ Tcl_RegExp (*tcl_RegExpCompile) (Tcl_Interp *interp, const char *pattern); /* 212 */ int (*tcl_RegExpExec) (Tcl_Interp *interp, Tcl_RegExp regexp, const char *text, const char *start); /* 213 */ int (*tcl_RegExpMatch) (Tcl_Interp *interp, const char *text, const char *pattern); /* 214 */ void (*tcl_RegExpRange) (Tcl_RegExp regexp, int index, CONST84 char **startPtr, CONST84 char **endPtr); /* 215 */ void (*tcl_Release) (ClientData clientData); /* 216 */ void (*tcl_ResetResult) (Tcl_Interp *interp); /* 217 */ int (*tcl_ScanElement) (const char *src, int *flagPtr); /* 218 */ int (*tcl_ScanCountedElement) (const char *src, int length, int *flagPtr); /* 219 */ int (*tcl_SeekOld) (Tcl_Channel chan, int offset, int mode); /* 220 */ int (*tcl_ServiceAll) (void); /* 221 */ int (*tcl_ServiceEvent) (int flags); /* 222 */ void (*tcl_SetAssocData) (Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc *proc, ClientData clientData); /* 223 */ void (*tcl_SetChannelBufferSize) (Tcl_Channel chan, int sz); /* 224 */ int (*tcl_SetChannelOption) (Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, const char *newValue); /* 225 */ int (*tcl_SetCommandInfo) (Tcl_Interp *interp, const char *cmdName, const Tcl_CmdInfo *infoPtr); /* 226 */ void (*tcl_SetErrno) (int err); /* 227 */ void (*tcl_SetErrorCode) (Tcl_Interp *interp, ...); /* 228 */ void (*tcl_SetMaxBlockTime) (const Tcl_Time *timePtr); /* 229 */ void (*tcl_SetPanicProc) (TCL_NORETURN1 Tcl_PanicProc *panicProc); /* 230 */ int (*tcl_SetRecursionLimit) (Tcl_Interp *interp, int depth); /* 231 */ void (*tcl_SetResult) (Tcl_Interp *interp, char *result, Tcl_FreeProc *freeProc); /* 232 */ int (*tcl_SetServiceMode) (int mode); /* 233 */ void (*tcl_SetObjErrorCode) (Tcl_Interp *interp, Tcl_Obj *errorObjPtr); /* 234 */ void (*tcl_SetObjResult) (Tcl_Interp *interp, Tcl_Obj *resultObjPtr); /* 235 */ void (*tcl_SetStdChannel) (Tcl_Channel channel, int type); /* 236 */ CONST84_RETURN char * (*tcl_SetVar) (Tcl_Interp *interp, const char *varName, const char *newValue, int flags); /* 237 */ CONST84_RETURN char * (*tcl_SetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, const char *newValue, int flags); /* 238 */ CONST84_RETURN char * (*tcl_SignalId) (int sig); /* 239 */ CONST84_RETURN char * (*tcl_SignalMsg) (int sig); /* 240 */ void (*tcl_SourceRCFile) (Tcl_Interp *interp); /* 241 */ int (*tcl_SplitList) (Tcl_Interp *interp, const char *listStr, int *argcPtr, CONST84 char ***argvPtr); /* 242 */ void (*tcl_SplitPath) (const char *path, int *argcPtr, CONST84 char ***argvPtr); /* 243 */ void (*tcl_StaticPackage) (Tcl_Interp *interp, const char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc); /* 244 */ int (*tcl_StringMatch) (const char *str, const char *pattern); /* 245 */ int (*tcl_TellOld) (Tcl_Channel chan); /* 246 */ int (*tcl_TraceVar) (Tcl_Interp *interp, const char *varName, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 247 */ int (*tcl_TraceVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 248 */ char * (*tcl_TranslateFileName) (Tcl_Interp *interp, const char *name, Tcl_DString *bufferPtr); /* 249 */ int (*tcl_Ungets) (Tcl_Channel chan, const char *str, int len, int atHead); /* 250 */ void (*tcl_UnlinkVar) (Tcl_Interp *interp, const char *varName); /* 251 */ int (*tcl_UnregisterChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 252 */ int (*tcl_UnsetVar) (Tcl_Interp *interp, const char *varName, int flags); /* 253 */ int (*tcl_UnsetVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 254 */ void (*tcl_UntraceVar) (Tcl_Interp *interp, const char *varName, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 255 */ void (*tcl_UntraceVar2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *proc, ClientData clientData); /* 256 */ void (*tcl_UpdateLinkedVar) (Tcl_Interp *interp, const char *varName); /* 257 */ int (*tcl_UpVar) (Tcl_Interp *interp, const char *frameName, const char *varName, const char *localName, int flags); /* 258 */ int (*tcl_UpVar2) (Tcl_Interp *interp, const char *frameName, const char *part1, const char *part2, const char *localName, int flags); /* 259 */ int (*tcl_VarEval) (Tcl_Interp *interp, ...); /* 260 */ ClientData (*tcl_VarTraceInfo) (Tcl_Interp *interp, const char *varName, int flags, Tcl_VarTraceProc *procPtr, ClientData prevClientData); /* 261 */ ClientData (*tcl_VarTraceInfo2) (Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *procPtr, ClientData prevClientData); /* 262 */ int (*tcl_Write) (Tcl_Channel chan, const char *s, int slen); /* 263 */ void (*tcl_WrongNumArgs) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], const char *message); /* 264 */ int (*tcl_DumpActiveMemory) (const char *fileName); /* 265 */ void (*tcl_ValidateAllMemory) (const char *file, int line); /* 266 */ void (*tcl_AppendResultVA) (Tcl_Interp *interp, va_list argList); /* 267 */ void (*tcl_AppendStringsToObjVA) (Tcl_Obj *objPtr, va_list argList); /* 268 */ char * (*tcl_HashStats) (Tcl_HashTable *tablePtr); /* 269 */ CONST84_RETURN char * (*tcl_ParseVar) (Tcl_Interp *interp, const char *start, CONST84 char **termPtr); /* 270 */ CONST84_RETURN char * (*tcl_PkgPresent) (Tcl_Interp *interp, const char *name, const char *version, int exact); /* 271 */ CONST84_RETURN char * (*tcl_PkgPresentEx) (Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr); /* 272 */ int (*tcl_PkgProvide) (Tcl_Interp *interp, const char *name, const char *version); /* 273 */ CONST84_RETURN char * (*tcl_PkgRequire) (Tcl_Interp *interp, const char *name, const char *version, int exact); /* 274 */ void (*tcl_SetErrorCodeVA) (Tcl_Interp *interp, va_list argList); /* 275 */ int (*tcl_VarEvalVA) (Tcl_Interp *interp, va_list argList); /* 276 */ Tcl_Pid (*tcl_WaitPid) (Tcl_Pid pid, int *statPtr, int options); /* 277 */ TCL_NORETURN1 void (*tcl_PanicVA) (const char *format, va_list argList); /* 278 */ void (*tcl_GetVersion) (int *major, int *minor, int *patchLevel, int *type); /* 279 */ void (*tcl_InitMemory) (Tcl_Interp *interp); /* 280 */ Tcl_Channel (*tcl_StackChannel) (Tcl_Interp *interp, const Tcl_ChannelType *typePtr, ClientData instanceData, int mask, Tcl_Channel prevChan); /* 281 */ int (*tcl_UnstackChannel) (Tcl_Interp *interp, Tcl_Channel chan); /* 282 */ Tcl_Channel (*tcl_GetStackedChannel) (Tcl_Channel chan); /* 283 */ void (*tcl_SetMainLoop) (Tcl_MainLoopProc *proc); /* 284 */ void (*reserved285)(void); void (*tcl_AppendObjToObj) (Tcl_Obj *objPtr, Tcl_Obj *appendObjPtr); /* 286 */ Tcl_Encoding (*tcl_CreateEncoding) (const Tcl_EncodingType *typePtr); /* 287 */ void (*tcl_CreateThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 288 */ void (*tcl_DeleteThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 289 */ void (*tcl_DiscardResult) (Tcl_SavedResult *statePtr); /* 290 */ int (*tcl_EvalEx) (Tcl_Interp *interp, const char *script, int numBytes, int flags); /* 291 */ int (*tcl_EvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 292 */ int (*tcl_EvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 293 */ void (*tcl_ExitThread) (int status); /* 294 */ int (*tcl_ExternalToUtf) (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); /* 295 */ char * (*tcl_ExternalToUtfDString) (Tcl_Encoding encoding, const char *src, int srcLen, Tcl_DString *dsPtr); /* 296 */ void (*tcl_FinalizeThread) (void); /* 297 */ void (*tcl_FinalizeNotifier) (ClientData clientData); /* 298 */ void (*tcl_FreeEncoding) (Tcl_Encoding encoding); /* 299 */ Tcl_ThreadId (*tcl_GetCurrentThread) (void); /* 300 */ Tcl_Encoding (*tcl_GetEncoding) (Tcl_Interp *interp, const char *name); /* 301 */ CONST84_RETURN char * (*tcl_GetEncodingName) (Tcl_Encoding encoding); /* 302 */ void (*tcl_GetEncodingNames) (Tcl_Interp *interp); /* 303 */ int (*tcl_GetIndexFromObjStruct) (Tcl_Interp *interp, Tcl_Obj *objPtr, const void *tablePtr, int offset, const char *msg, int flags, int *indexPtr); /* 304 */ void * (*tcl_GetThreadData) (Tcl_ThreadDataKey *keyPtr, int size); /* 305 */ Tcl_Obj * (*tcl_GetVar2Ex) (Tcl_Interp *interp, const char *part1, const char *part2, int flags); /* 306 */ ClientData (*tcl_InitNotifier) (void); /* 307 */ void (*tcl_MutexLock) (Tcl_Mutex *mutexPtr); /* 308 */ void (*tcl_MutexUnlock) (Tcl_Mutex *mutexPtr); /* 309 */ void (*tcl_ConditionNotify) (Tcl_Condition *condPtr); /* 310 */ void (*tcl_ConditionWait) (Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr, const Tcl_Time *timePtr); /* 311 */ int (*tcl_NumUtfChars) (const char *src, int length); /* 312 */ int (*tcl_ReadChars) (Tcl_Channel channel, Tcl_Obj *objPtr, int charsToRead, int appendFlag); /* 313 */ void (*tcl_RestoreResult) (Tcl_Interp *interp, Tcl_SavedResult *statePtr); /* 314 */ void (*tcl_SaveResult) (Tcl_Interp *interp, Tcl_SavedResult *statePtr); /* 315 */ int (*tcl_SetSystemEncoding) (Tcl_Interp *interp, const char *name); /* 316 */ Tcl_Obj * (*tcl_SetVar2Ex) (Tcl_Interp *interp, const char *part1, const char *part2, Tcl_Obj *newValuePtr, int flags); /* 317 */ void (*tcl_ThreadAlert) (Tcl_ThreadId threadId); /* 318 */ void (*tcl_ThreadQueueEvent) (Tcl_ThreadId threadId, Tcl_Event *evPtr, Tcl_QueuePosition position); /* 319 */ Tcl_UniChar (*tcl_UniCharAtIndex) (const char *src, int index); /* 320 */ Tcl_UniChar (*tcl_UniCharToLower) (int ch); /* 321 */ Tcl_UniChar (*tcl_UniCharToTitle) (int ch); /* 322 */ Tcl_UniChar (*tcl_UniCharToUpper) (int ch); /* 323 */ int (*tcl_UniCharToUtf) (int ch, char *buf); /* 324 */ CONST84_RETURN char * (*tcl_UtfAtIndex) (const char *src, int index); /* 325 */ int (*tcl_UtfCharComplete) (const char *src, int length); /* 326 */ int (*tcl_UtfBackslash) (const char *src, int *readPtr, char *dst); /* 327 */ CONST84_RETURN char * (*tcl_UtfFindFirst) (const char *src, int ch); /* 328 */ CONST84_RETURN char * (*tcl_UtfFindLast) (const char *src, int ch); /* 329 */ CONST84_RETURN char * (*tcl_UtfNext) (const char *src); /* 330 */ CONST84_RETURN char * (*tcl_UtfPrev) (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 */ int (*tcl_UtfToTitle) (char *src); /* 335 */ int (*tcl_UtfToUniChar) (const char *src, Tcl_UniChar *chPtr); /* 336 */ int (*tcl_UtfToUpper) (char *src); /* 337 */ int (*tcl_WriteChars) (Tcl_Channel chan, const char *src, int srcLen); /* 338 */ int (*tcl_WriteObj) (Tcl_Channel chan, Tcl_Obj *objPtr); /* 339 */ char * (*tcl_GetString) (Tcl_Obj *objPtr); /* 340 */ CONST84_RETURN char * (*tcl_GetDefaultEncodingDir) (void); /* 341 */ void (*tcl_SetDefaultEncodingDir) (const char *path); /* 342 */ void (*tcl_AlertNotifier) (ClientData clientData); /* 343 */ void (*tcl_ServiceModeHook) (int mode); /* 344 */ int (*tcl_UniCharIsAlnum) (int ch); /* 345 */ int (*tcl_UniCharIsAlpha) (int ch); /* 346 */ int (*tcl_UniCharIsDigit) (int ch); /* 347 */ int (*tcl_UniCharIsLower) (int ch); /* 348 */ int (*tcl_UniCharIsSpace) (int ch); /* 349 */ int (*tcl_UniCharIsUpper) (int ch); /* 350 */ int (*tcl_UniCharIsWordChar) (int ch); /* 351 */ int (*tcl_UniCharLen) (const Tcl_UniChar *uniStr); /* 352 */ int (*tcl_UniCharNcmp) (const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsigned long numChars); /* 353 */ char * (*tcl_UniCharToUtfDString) (const Tcl_UniChar *uniStr, int uniLength, Tcl_DString *dsPtr); /* 354 */ Tcl_UniChar * (*tcl_UtfToUniCharDString) (const char *src, int length, Tcl_DString *dsPtr); /* 355 */ Tcl_RegExp (*tcl_GetRegExpFromObj) (Tcl_Interp *interp, Tcl_Obj *patObj, int flags); /* 356 */ Tcl_Obj * (*tcl_EvalTokens) (Tcl_Interp *interp, Tcl_Token *tokenPtr, int count); /* 357 */ void (*tcl_FreeParse) (Tcl_Parse *parsePtr); /* 358 */ void (*tcl_LogCommandInfo) (Tcl_Interp *interp, const char *script, const char *command, int length); /* 359 */ int (*tcl_ParseBraces) (Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append, CONST84 char **termPtr); /* 360 */ int (*tcl_ParseCommand) (Tcl_Interp *interp, const char *start, int numBytes, int nested, Tcl_Parse *parsePtr); /* 361 */ int (*tcl_ParseExpr) (Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr); /* 362 */ int (*tcl_ParseQuotedString) (Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append, CONST84 char **termPtr); /* 363 */ int (*tcl_ParseVarName) (Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append); /* 364 */ char * (*tcl_GetCwd) (Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 365 */ int (*tcl_Chdir) (const char *dirName); /* 366 */ int (*tcl_Access) (const char *path, int mode); /* 367 */ int (*tcl_Stat) (const char *path, struct stat *bufPtr); /* 368 */ int (*tcl_UtfNcmp) (const char *s1, const char *s2, unsigned long n); /* 369 */ int (*tcl_UtfNcasecmp) (const char *s1, const char *s2, unsigned long n); /* 370 */ int (*tcl_StringCaseMatch) (const char *str, const char *pattern, int nocase); /* 371 */ int (*tcl_UniCharIsControl) (int ch); /* 372 */ int (*tcl_UniCharIsGraph) (int ch); /* 373 */ int (*tcl_UniCharIsPrint) (int ch); /* 374 */ int (*tcl_UniCharIsPunct) (int ch); /* 375 */ int (*tcl_RegExpExecObj) (Tcl_Interp *interp, Tcl_RegExp regexp, Tcl_Obj *textObj, int offset, int nmatches, int flags); /* 376 */ void (*tcl_RegExpGetInfo) (Tcl_RegExp regexp, Tcl_RegExpInfo *infoPtr); /* 377 */ Tcl_Obj * (*tcl_NewUnicodeObj) (const Tcl_UniChar *unicode, int numChars); /* 378 */ void (*tcl_SetUnicodeObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int numChars); /* 379 */ int (*tcl_GetCharLength) (Tcl_Obj *objPtr); /* 380 */ Tcl_UniChar (*tcl_GetUniChar) (Tcl_Obj *objPtr, int index); /* 381 */ Tcl_UniChar * (*tcl_GetUnicode) (Tcl_Obj *objPtr); /* 382 */ Tcl_Obj * (*tcl_GetRange) (Tcl_Obj *objPtr, int first, int last); /* 383 */ void (*tcl_AppendUnicodeToObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int length); /* 384 */ int (*tcl_RegExpMatchObj) (Tcl_Interp *interp, Tcl_Obj *textObj, Tcl_Obj *patternObj); /* 385 */ void (*tcl_SetNotifier) (Tcl_NotifierProcs *notifierProcPtr); /* 386 */ Tcl_Mutex * (*tcl_GetAllocMutex) (void); /* 387 */ int (*tcl_GetChannelNames) (Tcl_Interp *interp); /* 388 */ int (*tcl_GetChannelNamesEx) (Tcl_Interp *interp, const char *pattern); /* 389 */ int (*tcl_ProcObjCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 390 */ void (*tcl_ConditionFinalize) (Tcl_Condition *condPtr); /* 391 */ void (*tcl_MutexFinalize) (Tcl_Mutex *mutex); /* 392 */ int (*tcl_CreateThread) (Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, ClientData clientData, int stackSize, int flags); /* 393 */ int (*tcl_ReadRaw) (Tcl_Channel chan, char *dst, int bytesToRead); /* 394 */ int (*tcl_WriteRaw) (Tcl_Channel chan, const char *src, int srcLen); /* 395 */ Tcl_Channel (*tcl_GetTopChannel) (Tcl_Channel chan); /* 396 */ int (*tcl_ChannelBuffered) (Tcl_Channel chan); /* 397 */ CONST84_RETURN char * (*tcl_ChannelName) (const Tcl_ChannelType *chanTypePtr); /* 398 */ Tcl_ChannelTypeVersion (*tcl_ChannelVersion) (const Tcl_ChannelType *chanTypePtr); /* 399 */ Tcl_DriverBlockModeProc * (*tcl_ChannelBlockModeProc) (const Tcl_ChannelType *chanTypePtr); /* 400 */ Tcl_DriverCloseProc * (*tcl_ChannelCloseProc) (const Tcl_ChannelType *chanTypePtr); /* 401 */ Tcl_DriverClose2Proc * (*tcl_ChannelClose2Proc) (const Tcl_ChannelType *chanTypePtr); /* 402 */ Tcl_DriverInputProc * (*tcl_ChannelInputProc) (const Tcl_ChannelType *chanTypePtr); /* 403 */ Tcl_DriverOutputProc * (*tcl_ChannelOutputProc) (const Tcl_ChannelType *chanTypePtr); /* 404 */ Tcl_DriverSeekProc * (*tcl_ChannelSeekProc) (const Tcl_ChannelType *chanTypePtr); /* 405 */ Tcl_DriverSetOptionProc * (*tcl_ChannelSetOptionProc) (const Tcl_ChannelType *chanTypePtr); /* 406 */ Tcl_DriverGetOptionProc * (*tcl_ChannelGetOptionProc) (const Tcl_ChannelType *chanTypePtr); /* 407 */ Tcl_DriverWatchProc * (*tcl_ChannelWatchProc) (const Tcl_ChannelType *chanTypePtr); /* 408 */ Tcl_DriverGetHandleProc * (*tcl_ChannelGetHandleProc) (const Tcl_ChannelType *chanTypePtr); /* 409 */ Tcl_DriverFlushProc * (*tcl_ChannelFlushProc) (const Tcl_ChannelType *chanTypePtr); /* 410 */ Tcl_DriverHandlerProc * (*tcl_ChannelHandlerProc) (const Tcl_ChannelType *chanTypePtr); /* 411 */ int (*tcl_JoinThread) (Tcl_ThreadId threadId, int *result); /* 412 */ int (*tcl_IsChannelShared) (Tcl_Channel channel); /* 413 */ int (*tcl_IsChannelRegistered) (Tcl_Interp *interp, Tcl_Channel channel); /* 414 */ void (*tcl_CutChannel) (Tcl_Channel channel); /* 415 */ void (*tcl_SpliceChannel) (Tcl_Channel channel); /* 416 */ void (*tcl_ClearChannelHandlers) (Tcl_Channel channel); /* 417 */ int (*tcl_IsChannelExisting) (const char *channelName); /* 418 */ int (*tcl_UniCharNcasecmp) (const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsigned long numChars); /* 419 */ int (*tcl_UniCharCaseMatch) (const Tcl_UniChar *uniStr, const Tcl_UniChar *uniPattern, int nocase); /* 420 */ Tcl_HashEntry * (*tcl_FindHashEntry) (Tcl_HashTable *tablePtr, const void *key); /* 421 */ Tcl_HashEntry * (*tcl_CreateHashEntry) (Tcl_HashTable *tablePtr, const void *key, int *newPtr); /* 422 */ void (*tcl_InitCustomHashTable) (Tcl_HashTable *tablePtr, int keyType, const Tcl_HashKeyType *typePtr); /* 423 */ void (*tcl_InitObjHashTable) (Tcl_HashTable *tablePtr); /* 424 */ ClientData (*tcl_CommandTraceInfo) (Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *procPtr, ClientData prevClientData); /* 425 */ int (*tcl_TraceCommand) (Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, ClientData clientData); /* 426 */ void (*tcl_UntraceCommand) (Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, ClientData clientData); /* 427 */ char * (*tcl_AttemptAlloc) (unsigned int size); /* 428 */ char * (*tcl_AttemptDbCkalloc) (unsigned int size, const char *file, int line); /* 429 */ char * (*tcl_AttemptRealloc) (char *ptr, unsigned int size); /* 430 */ char * (*tcl_AttemptDbCkrealloc) (char *ptr, unsigned int size, const char *file, int line); /* 431 */ int (*tcl_AttemptSetObjLength) (Tcl_Obj *objPtr, int length); /* 432 */ Tcl_ThreadId (*tcl_GetChannelThread) (Tcl_Channel channel); /* 433 */ Tcl_UniChar * (*tcl_GetUnicodeFromObj) (Tcl_Obj *objPtr, int *lengthPtr); /* 434 */ int (*tcl_GetMathFuncInfo) (Tcl_Interp *interp, const char *name, int *numArgsPtr, Tcl_ValueType **argTypesPtr, Tcl_MathProc **procPtr, ClientData *clientDataPtr); /* 435 */ Tcl_Obj * (*tcl_ListMathFuncs) (Tcl_Interp *interp, const char *pattern); /* 436 */ Tcl_Obj * (*tcl_SubstObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 437 */ int (*tcl_DetachChannel) (Tcl_Interp *interp, Tcl_Channel channel); /* 438 */ int (*tcl_IsStandardChannel) (Tcl_Channel channel); /* 439 */ int (*tcl_FSCopyFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 440 */ 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_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 */ int (*tcl_FSRenameFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 448 */ int (*tcl_FSLstat) (Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 449 */ int (*tcl_FSUtime) (Tcl_Obj *pathPtr, struct utimbuf *tval); /* 450 */ int (*tcl_FSFileAttrsGet) (Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); /* 451 */ int (*tcl_FSFileAttrsSet) (Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj *objPtr); /* 452 */ const char *CONST86 * (*tcl_FSFileAttrStrings) (Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); /* 453 */ int (*tcl_FSStat) (Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 454 */ int (*tcl_FSAccess) (Tcl_Obj *pathPtr, int mode); /* 455 */ Tcl_Channel (*tcl_FSOpenFileChannel) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *modeString, int permissions); /* 456 */ Tcl_Obj * (*tcl_FSGetCwd) (Tcl_Interp *interp); /* 457 */ int (*tcl_FSChdir) (Tcl_Obj *pathPtr); /* 458 */ int (*tcl_FSConvertToPathType) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 459 */ Tcl_Obj * (*tcl_FSJoinPath) (Tcl_Obj *listObj, int elements); /* 460 */ Tcl_Obj * (*tcl_FSSplitPath) (Tcl_Obj *pathPtr, int *lenPtr); /* 461 */ int (*tcl_FSEqualPaths) (Tcl_Obj *firstPtr, Tcl_Obj *secondPtr); /* 462 */ Tcl_Obj * (*tcl_FSGetNormalizedPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 463 */ Tcl_Obj * (*tcl_FSJoinToPath) (Tcl_Obj *pathPtr, int objc, Tcl_Obj *const objv[]); /* 464 */ ClientData (*tcl_FSGetInternalRep) (Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr); /* 465 */ Tcl_Obj * (*tcl_FSGetTranslatedPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 466 */ int (*tcl_FSEvalFile) (Tcl_Interp *interp, Tcl_Obj *fileName); /* 467 */ Tcl_Obj * (*tcl_FSNewNativePath) (const Tcl_Filesystem *fromFilesystem, ClientData clientData); /* 468 */ const void * (*tcl_FSGetNativePath) (Tcl_Obj *pathPtr); /* 469 */ Tcl_Obj * (*tcl_FSFileSystemInfo) (Tcl_Obj *pathPtr); /* 470 */ Tcl_Obj * (*tcl_FSPathSeparator) (Tcl_Obj *pathPtr); /* 471 */ Tcl_Obj * (*tcl_FSListVolumes) (void); /* 472 */ int (*tcl_FSRegister) (ClientData clientData, const Tcl_Filesystem *fsPtr); /* 473 */ int (*tcl_FSUnregister) (const Tcl_Filesystem *fsPtr); /* 474 */ ClientData (*tcl_FSData) (const Tcl_Filesystem *fsPtr); /* 475 */ const char * (*tcl_FSGetTranslatedStringPath) (Tcl_Interp *interp, Tcl_Obj *pathPtr); /* 476 */ CONST86 Tcl_Filesystem * (*tcl_FSGetFileSystemForPath) (Tcl_Obj *pathPtr); /* 477 */ Tcl_PathType (*tcl_FSGetPathType) (Tcl_Obj *pathPtr); /* 478 */ int (*tcl_OutputBuffered) (Tcl_Channel chan); /* 479 */ void (*tcl_FSMountsChanged) (const Tcl_Filesystem *fsPtr); /* 480 */ int (*tcl_EvalTokensStandard) (Tcl_Interp *interp, Tcl_Token *tokenPtr, int count); /* 481 */ void (*tcl_GetTime) (Tcl_Time *timeBuf); /* 482 */ Tcl_Trace (*tcl_CreateObjTrace) (Tcl_Interp *interp, int level, int flags, Tcl_CmdObjTraceProc *objProc, ClientData clientData, Tcl_CmdObjTraceDeleteProc *delProc); /* 483 */ int (*tcl_GetCommandInfoFromToken) (Tcl_Command token, Tcl_CmdInfo *infoPtr); /* 484 */ int (*tcl_SetCommandInfoFromToken) (Tcl_Command token, const Tcl_CmdInfo *infoPtr); /* 485 */ Tcl_Obj * (*tcl_DbNewWideIntObj) (Tcl_WideInt wideValue, const char *file, int line); /* 486 */ int (*tcl_GetWideIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideInt *widePtr); /* 487 */ Tcl_Obj * (*tcl_NewWideIntObj) (Tcl_WideInt wideValue); /* 488 */ void (*tcl_SetWideIntObj) (Tcl_Obj *objPtr, Tcl_WideInt wideValue); /* 489 */ Tcl_StatBuf * (*tcl_AllocStatBuf) (void); /* 490 */ Tcl_WideInt (*tcl_Seek) (Tcl_Channel chan, Tcl_WideInt offset, int mode); /* 491 */ Tcl_WideInt (*tcl_Tell) (Tcl_Channel chan); /* 492 */ Tcl_DriverWideSeekProc * (*tcl_ChannelWideSeekProc) (const Tcl_ChannelType *chanTypePtr); /* 493 */ int (*tcl_DictObjPut) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj *valuePtr); /* 494 */ int (*tcl_DictObjGet) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr); /* 495 */ int (*tcl_DictObjRemove) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr); /* 496 */ int (*tcl_DictObjSize) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr); /* 497 */ int (*tcl_DictObjFirst) (Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 498 */ void (*tcl_DictObjNext) (Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr); /* 499 */ void (*tcl_DictObjDone) (Tcl_DictSearch *searchPtr); /* 500 */ int (*tcl_DictObjPutKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr); /* 501 */ int (*tcl_DictObjRemoveKeyList) (Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const *keyv); /* 502 */ Tcl_Obj * (*tcl_NewDictObj) (void); /* 503 */ Tcl_Obj * (*tcl_DbNewDictObj) (const char *file, int line); /* 504 */ void (*tcl_RegisterConfig) (Tcl_Interp *interp, const char *pkgName, const Tcl_Config *configuration, const char *valEncoding); /* 505 */ Tcl_Namespace * (*tcl_CreateNamespace) (Tcl_Interp *interp, const char *name, ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc); /* 506 */ void (*tcl_DeleteNamespace) (Tcl_Namespace *nsPtr); /* 507 */ int (*tcl_AppendExportList) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *objPtr); /* 508 */ int (*tcl_Export) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int resetListFirst); /* 509 */ int (*tcl_Import) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int allowOverwrite); /* 510 */ int (*tcl_ForgetImport) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern); /* 511 */ Tcl_Namespace * (*tcl_GetCurrentNamespace) (Tcl_Interp *interp); /* 512 */ Tcl_Namespace * (*tcl_GetGlobalNamespace) (Tcl_Interp *interp); /* 513 */ Tcl_Namespace * (*tcl_FindNamespace) (Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags); /* 514 */ Tcl_Command (*tcl_FindCommand) (Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags); /* 515 */ Tcl_Command (*tcl_GetCommandFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 516 */ void (*tcl_GetCommandFullName) (Tcl_Interp *interp, Tcl_Command command, Tcl_Obj *objPtr); /* 517 */ int (*tcl_FSEvalFileEx) (Tcl_Interp *interp, Tcl_Obj *fileName, const char *encodingName); /* 518 */ Tcl_ExitProc * (*tcl_SetExitProc) (TCL_NORETURN1 Tcl_ExitProc *proc); /* 519 */ void (*tcl_LimitAddHandler) (Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData, Tcl_LimitHandlerDeleteProc *deleteProc); /* 520 */ void (*tcl_LimitRemoveHandler) (Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData); /* 521 */ int (*tcl_LimitReady) (Tcl_Interp *interp); /* 522 */ int (*tcl_LimitCheck) (Tcl_Interp *interp); /* 523 */ int (*tcl_LimitExceeded) (Tcl_Interp *interp); /* 524 */ void (*tcl_LimitSetCommands) (Tcl_Interp *interp, int commandLimit); /* 525 */ void (*tcl_LimitSetTime) (Tcl_Interp *interp, Tcl_Time *timeLimitPtr); /* 526 */ void (*tcl_LimitSetGranularity) (Tcl_Interp *interp, int type, int granularity); /* 527 */ int (*tcl_LimitTypeEnabled) (Tcl_Interp *interp, int type); /* 528 */ int (*tcl_LimitTypeExceeded) (Tcl_Interp *interp, int type); /* 529 */ void (*tcl_LimitTypeSet) (Tcl_Interp *interp, int type); /* 530 */ void (*tcl_LimitTypeReset) (Tcl_Interp *interp, int type); /* 531 */ int (*tcl_LimitGetCommands) (Tcl_Interp *interp); /* 532 */ void (*tcl_LimitGetTime) (Tcl_Interp *interp, Tcl_Time *timeLimitPtr); /* 533 */ int (*tcl_LimitGetGranularity) (Tcl_Interp *interp, int type); /* 534 */ Tcl_InterpState (*tcl_SaveInterpState) (Tcl_Interp *interp, int status); /* 535 */ int (*tcl_RestoreInterpState) (Tcl_Interp *interp, Tcl_InterpState state); /* 536 */ void (*tcl_DiscardInterpState) (Tcl_InterpState state); /* 537 */ int (*tcl_SetReturnOptions) (Tcl_Interp *interp, Tcl_Obj *options); /* 538 */ Tcl_Obj * (*tcl_GetReturnOptions) (Tcl_Interp *interp, int result); /* 539 */ int (*tcl_IsEnsemble) (Tcl_Command token); /* 540 */ Tcl_Command (*tcl_CreateEnsemble) (Tcl_Interp *interp, const char *name, Tcl_Namespace *namespacePtr, int flags); /* 541 */ Tcl_Command (*tcl_FindEnsemble) (Tcl_Interp *interp, Tcl_Obj *cmdNameObj, int flags); /* 542 */ int (*tcl_SetEnsembleSubcommandList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *subcmdList); /* 543 */ int (*tcl_SetEnsembleMappingDict) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *mapDict); /* 544 */ int (*tcl_SetEnsembleUnknownHandler) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *unknownList); /* 545 */ int (*tcl_SetEnsembleFlags) (Tcl_Interp *interp, Tcl_Command token, int flags); /* 546 */ int (*tcl_GetEnsembleSubcommandList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **subcmdListPtr); /* 547 */ int (*tcl_GetEnsembleMappingDict) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **mapDictPtr); /* 548 */ int (*tcl_GetEnsembleUnknownHandler) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **unknownListPtr); /* 549 */ int (*tcl_GetEnsembleFlags) (Tcl_Interp *interp, Tcl_Command token, int *flagsPtr); /* 550 */ int (*tcl_GetEnsembleNamespace) (Tcl_Interp *interp, Tcl_Command token, Tcl_Namespace **namespacePtrPtr); /* 551 */ void (*tcl_SetTimeProc) (Tcl_GetTimeProc *getProc, Tcl_ScaleTimeProc *scaleProc, ClientData clientData); /* 552 */ void (*tcl_QueryTimeProc) (Tcl_GetTimeProc **getProc, Tcl_ScaleTimeProc **scaleProc, ClientData *clientData); /* 553 */ Tcl_DriverThreadActionProc * (*tcl_ChannelThreadActionProc) (const Tcl_ChannelType *chanTypePtr); /* 554 */ Tcl_Obj * (*tcl_NewBignumObj) (mp_int *value); /* 555 */ Tcl_Obj * (*tcl_DbNewBignumObj) (mp_int *value, const char *file, int line); /* 556 */ void (*tcl_SetBignumObj) (Tcl_Obj *obj, mp_int *value); /* 557 */ int (*tcl_GetBignumFromObj) (Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value); /* 558 */ int (*tcl_TakeBignumFromObj) (Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value); /* 559 */ int (*tcl_TruncateChannel) (Tcl_Channel chan, Tcl_WideInt length); /* 560 */ Tcl_DriverTruncateProc * (*tcl_ChannelTruncateProc) (const Tcl_ChannelType *chanTypePtr); /* 561 */ void (*tcl_SetChannelErrorInterp) (Tcl_Interp *interp, Tcl_Obj *msg); /* 562 */ void (*tcl_GetChannelErrorInterp) (Tcl_Interp *interp, Tcl_Obj **msg); /* 563 */ void (*tcl_SetChannelError) (Tcl_Channel chan, Tcl_Obj *msg); /* 564 */ void (*tcl_GetChannelError) (Tcl_Channel chan, Tcl_Obj **msg); /* 565 */ int (*tcl_InitBignumFromDouble) (Tcl_Interp *interp, double initval, mp_int *toInit); /* 566 */ Tcl_Obj * (*tcl_GetNamespaceUnknownHandler) (Tcl_Interp *interp, Tcl_Namespace *nsPtr); /* 567 */ int (*tcl_SetNamespaceUnknownHandler) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *handlerPtr); /* 568 */ int (*tcl_GetEncodingFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr); /* 569 */ Tcl_Obj * (*tcl_GetEncodingSearchPath) (void); /* 570 */ int (*tcl_SetEncodingSearchPath) (Tcl_Obj *searchPath); /* 571 */ const char * (*tcl_GetEncodingNameFromEnvironment) (Tcl_DString *bufPtr); /* 572 */ int (*tcl_PkgRequireProc) (Tcl_Interp *interp, const char *name, int objc, Tcl_Obj *const objv[], void *clientDataPtr); /* 573 */ void (*tcl_AppendObjToErrorInfo) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 574 */ void (*tcl_AppendLimitedToObj) (Tcl_Obj *objPtr, const char *bytes, int length, int limit, const char *ellipsis); /* 575 */ Tcl_Obj * (*tcl_Format) (Tcl_Interp *interp, const char *format, int objc, Tcl_Obj *const objv[]); /* 576 */ int (*tcl_AppendFormatToObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, const char *format, int objc, Tcl_Obj *const objv[]); /* 577 */ Tcl_Obj * (*tcl_ObjPrintf) (const char *format, ...) TCL_FORMAT_PRINTF(1, 2); /* 578 */ void (*tcl_AppendPrintfToObj) (Tcl_Obj *objPtr, const char *format, ...) TCL_FORMAT_PRINTF(2, 3); /* 579 */ int (*tcl_CancelEval) (Tcl_Interp *interp, Tcl_Obj *resultObjPtr, ClientData clientData, int flags); /* 580 */ int (*tcl_Canceled) (Tcl_Interp *interp, int flags); /* 581 */ int (*tcl_CreatePipe) (Tcl_Interp *interp, Tcl_Channel *rchan, Tcl_Channel *wchan, int flags); /* 582 */ Tcl_Command (*tcl_NRCreateCommand) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, Tcl_ObjCmdProc *nreProc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 583 */ int (*tcl_NREvalObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 584 */ int (*tcl_NREvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 585 */ int (*tcl_NRCmdSwap) (Tcl_Interp *interp, Tcl_Command cmd, int objc, Tcl_Obj *const objv[], int flags); /* 586 */ void (*tcl_NRAddCallback) (Tcl_Interp *interp, Tcl_NRPostProc *postProcPtr, ClientData data0, ClientData data1, ClientData data2, ClientData data3); /* 587 */ int (*tcl_NRCallObjProc) (Tcl_Interp *interp, Tcl_ObjCmdProc *objProc, ClientData clientData, int objc, Tcl_Obj *const objv[]); /* 588 */ unsigned (*tcl_GetFSDeviceFromStat) (const Tcl_StatBuf *statPtr); /* 589 */ unsigned (*tcl_GetFSInodeFromStat) (const Tcl_StatBuf *statPtr); /* 590 */ unsigned (*tcl_GetModeFromStat) (const Tcl_StatBuf *statPtr); /* 591 */ int (*tcl_GetLinkCountFromStat) (const Tcl_StatBuf *statPtr); /* 592 */ int (*tcl_GetUserIdFromStat) (const Tcl_StatBuf *statPtr); /* 593 */ int (*tcl_GetGroupIdFromStat) (const Tcl_StatBuf *statPtr); /* 594 */ int (*tcl_GetDeviceTypeFromStat) (const Tcl_StatBuf *statPtr); /* 595 */ Tcl_WideInt (*tcl_GetAccessTimeFromStat) (const Tcl_StatBuf *statPtr); /* 596 */ Tcl_WideInt (*tcl_GetModificationTimeFromStat) (const Tcl_StatBuf *statPtr); /* 597 */ Tcl_WideInt (*tcl_GetChangeTimeFromStat) (const Tcl_StatBuf *statPtr); /* 598 */ Tcl_WideUInt (*tcl_GetSizeFromStat) (const Tcl_StatBuf *statPtr); /* 599 */ Tcl_WideUInt (*tcl_GetBlocksFromStat) (const Tcl_StatBuf *statPtr); /* 600 */ unsigned (*tcl_GetBlockSizeFromStat) (const Tcl_StatBuf *statPtr); /* 601 */ int (*tcl_SetEnsembleParameterList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *paramList); /* 602 */ int (*tcl_GetEnsembleParameterList) (Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **paramListPtr); /* 603 */ int (*tcl_ParseArgsObjv) (Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, int *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv); /* 604 */ int (*tcl_GetErrorLine) (Tcl_Interp *interp); /* 605 */ void (*tcl_SetErrorLine) (Tcl_Interp *interp, int lineNum); /* 606 */ void (*tcl_TransferResult) (Tcl_Interp *sourceInterp, int result, Tcl_Interp *targetInterp); /* 607 */ int (*tcl_InterpActive) (Tcl_Interp *interp); /* 608 */ void (*tcl_BackgroundException) (Tcl_Interp *interp, int code); /* 609 */ int (*tcl_ZlibDeflate) (Tcl_Interp *interp, int format, Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj); /* 610 */ int (*tcl_ZlibInflate) (Tcl_Interp *interp, int format, Tcl_Obj *data, int buffersize, Tcl_Obj *gzipHeaderDictObj); /* 611 */ unsigned int (*tcl_ZlibCRC32) (unsigned int crc, const unsigned char *buf, int len); /* 612 */ unsigned int (*tcl_ZlibAdler32) (unsigned int adler, const unsigned char *buf, int len); /* 613 */ int (*tcl_ZlibStreamInit) (Tcl_Interp *interp, int mode, int format, int level, Tcl_Obj *dictObj, Tcl_ZlibStream *zshandle); /* 614 */ Tcl_Obj * (*tcl_ZlibStreamGetCommandName) (Tcl_ZlibStream zshandle); /* 615 */ int (*tcl_ZlibStreamEof) (Tcl_ZlibStream zshandle); /* 616 */ int (*tcl_ZlibStreamChecksum) (Tcl_ZlibStream zshandle); /* 617 */ int (*tcl_ZlibStreamPut) (Tcl_ZlibStream zshandle, Tcl_Obj *data, int flush); /* 618 */ int (*tcl_ZlibStreamGet) (Tcl_ZlibStream zshandle, Tcl_Obj *data, int count); /* 619 */ int (*tcl_ZlibStreamClose) (Tcl_ZlibStream zshandle); /* 620 */ int (*tcl_ZlibStreamReset) (Tcl_ZlibStream zshandle); /* 621 */ void (*tcl_SetStartupScript) (Tcl_Obj *path, const char *encoding); /* 622 */ Tcl_Obj * (*tcl_GetStartupScript) (const char **encodingPtr); /* 623 */ int (*tcl_CloseEx) (Tcl_Interp *interp, Tcl_Channel chan, int flags); /* 624 */ int (*tcl_NRExprObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj *resultPtr); /* 625 */ int (*tcl_NRSubstObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /* 626 */ int (*tcl_LoadFile) (Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *const symv[], int flags, void *procPtrs, Tcl_LoadHandle *handlePtr); /* 627 */ void * (*tcl_FindSymbol) (Tcl_Interp *interp, Tcl_LoadHandle handle, const char *symbol); /* 628 */ int (*tcl_FSUnloadFile) (Tcl_Interp *interp, Tcl_LoadHandle handlePtr); /* 629 */ void (*tcl_ZlibStreamSetCompressionDictionary) (Tcl_ZlibStream zhandle, Tcl_Obj *compressionDictionaryObj); /* 630 */ } TclStubs; extern const TclStubs *tclStubsPtr; #ifdef __cplusplus } #endif #if defined(USE_TCL_STUBS) /* * Inline function declarations: */ #define Tcl_PkgProvideEx \ (tclStubsPtr->tcl_PkgProvideEx) /* 0 */ #define Tcl_PkgRequireEx \ (tclStubsPtr->tcl_PkgRequireEx) /* 1 */ #define Tcl_Panic \ (tclStubsPtr->tcl_Panic) /* 2 */ #define Tcl_Alloc \ (tclStubsPtr->tcl_Alloc) /* 3 */ #define Tcl_Free \ (tclStubsPtr->tcl_Free) /* 4 */ #define Tcl_Realloc \ (tclStubsPtr->tcl_Realloc) /* 5 */ #define Tcl_DbCkalloc \ (tclStubsPtr->tcl_DbCkalloc) /* 6 */ #define Tcl_DbCkfree \ (tclStubsPtr->tcl_DbCkfree) /* 7 */ #define Tcl_DbCkrealloc \ (tclStubsPtr->tcl_DbCkrealloc) /* 8 */ #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ #define Tcl_CreateFileHandler \ (tclStubsPtr->tcl_CreateFileHandler) /* 9 */ #endif /* UNIX */ #ifdef MAC_OSX_TCL /* MACOSX */ #define Tcl_CreateFileHandler \ (tclStubsPtr->tcl_CreateFileHandler) /* 9 */ #endif /* MACOSX */ #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ #define Tcl_DeleteFileHandler \ (tclStubsPtr->tcl_DeleteFileHandler) /* 10 */ #endif /* UNIX */ #ifdef MAC_OSX_TCL /* MACOSX */ #define Tcl_DeleteFileHandler \ (tclStubsPtr->tcl_DeleteFileHandler) /* 10 */ #endif /* MACOSX */ #define Tcl_SetTimer \ (tclStubsPtr->tcl_SetTimer) /* 11 */ #define Tcl_Sleep \ (tclStubsPtr->tcl_Sleep) /* 12 */ #define Tcl_WaitForEvent \ (tclStubsPtr->tcl_WaitForEvent) /* 13 */ #define Tcl_AppendAllObjTypes \ (tclStubsPtr->tcl_AppendAllObjTypes) /* 14 */ #define Tcl_AppendStringsToObj \ (tclStubsPtr->tcl_AppendStringsToObj) /* 15 */ #define Tcl_AppendToObj \ (tclStubsPtr->tcl_AppendToObj) /* 16 */ #define Tcl_ConcatObj \ (tclStubsPtr->tcl_ConcatObj) /* 17 */ #define Tcl_ConvertToType \ (tclStubsPtr->tcl_ConvertToType) /* 18 */ #define Tcl_DbDecrRefCount \ (tclStubsPtr->tcl_DbDecrRefCount) /* 19 */ #define Tcl_DbIncrRefCount \ (tclStubsPtr->tcl_DbIncrRefCount) /* 20 */ #define Tcl_DbIsShared \ (tclStubsPtr->tcl_DbIsShared) /* 21 */ #define Tcl_DbNewBooleanObj \ (tclStubsPtr->tcl_DbNewBooleanObj) /* 22 */ #define Tcl_DbNewByteArrayObj \ (tclStubsPtr->tcl_DbNewByteArrayObj) /* 23 */ #define Tcl_DbNewDoubleObj \ (tclStubsPtr->tcl_DbNewDoubleObj) /* 24 */ #define Tcl_DbNewListObj \ (tclStubsPtr->tcl_DbNewListObj) /* 25 */ #define Tcl_DbNewLongObj \ (tclStubsPtr->tcl_DbNewLongObj) /* 26 */ #define Tcl_DbNewObj \ (tclStubsPtr->tcl_DbNewObj) /* 27 */ #define Tcl_DbNewStringObj \ (tclStubsPtr->tcl_DbNewStringObj) /* 28 */ #define Tcl_DuplicateObj \ (tclStubsPtr->tcl_DuplicateObj) /* 29 */ #define TclFreeObj \ (tclStubsPtr->tclFreeObj) /* 30 */ #define Tcl_GetBoolean \ (tclStubsPtr->tcl_GetBoolean) /* 31 */ #define Tcl_GetBooleanFromObj \ (tclStubsPtr->tcl_GetBooleanFromObj) /* 32 */ #define Tcl_GetByteArrayFromObj \ (tclStubsPtr->tcl_GetByteArrayFromObj) /* 33 */ #define Tcl_GetDouble \ (tclStubsPtr->tcl_GetDouble) /* 34 */ #define Tcl_GetDoubleFromObj \ (tclStubsPtr->tcl_GetDoubleFromObj) /* 35 */ #define Tcl_GetIndexFromObj \ (tclStubsPtr->tcl_GetIndexFromObj) /* 36 */ #define Tcl_GetInt \ (tclStubsPtr->tcl_GetInt) /* 37 */ #define Tcl_GetIntFromObj \ (tclStubsPtr->tcl_GetIntFromObj) /* 38 */ #define Tcl_GetLongFromObj \ (tclStubsPtr->tcl_GetLongFromObj) /* 39 */ #define Tcl_GetObjType \ (tclStubsPtr->tcl_GetObjType) /* 40 */ #define Tcl_GetStringFromObj \ (tclStubsPtr->tcl_GetStringFromObj) /* 41 */ #define Tcl_InvalidateStringRep \ (tclStubsPtr->tcl_InvalidateStringRep) /* 42 */ #define Tcl_ListObjAppendList \ (tclStubsPtr->tcl_ListObjAppendList) /* 43 */ #define Tcl_ListObjAppendElement \ (tclStubsPtr->tcl_ListObjAppendElement) /* 44 */ #define Tcl_ListObjGetElements \ (tclStubsPtr->tcl_ListObjGetElements) /* 45 */ #define Tcl_ListObjIndex \ (tclStubsPtr->tcl_ListObjIndex) /* 46 */ #define Tcl_ListObjLength \ (tclStubsPtr->tcl_ListObjLength) /* 47 */ #define Tcl_ListObjReplace \ (tclStubsPtr->tcl_ListObjReplace) /* 48 */ #define Tcl_NewBooleanObj \ (tclStubsPtr->tcl_NewBooleanObj) /* 49 */ #define Tcl_NewByteArrayObj \ (tclStubsPtr->tcl_NewByteArrayObj) /* 50 */ #define Tcl_NewDoubleObj \ (tclStubsPtr->tcl_NewDoubleObj) /* 51 */ #define Tcl_NewIntObj \ (tclStubsPtr->tcl_NewIntObj) /* 52 */ #define Tcl_NewListObj \ (tclStubsPtr->tcl_NewListObj) /* 53 */ #define Tcl_NewLongObj \ (tclStubsPtr->tcl_NewLongObj) /* 54 */ #define Tcl_NewObj \ (tclStubsPtr->tcl_NewObj) /* 55 */ #define Tcl_NewStringObj \ (tclStubsPtr->tcl_NewStringObj) /* 56 */ #define Tcl_SetBooleanObj \ (tclStubsPtr->tcl_SetBooleanObj) /* 57 */ #define Tcl_SetByteArrayLength \ (tclStubsPtr->tcl_SetByteArrayLength) /* 58 */ #define Tcl_SetByteArrayObj \ (tclStubsPtr->tcl_SetByteArrayObj) /* 59 */ #define Tcl_SetDoubleObj \ (tclStubsPtr->tcl_SetDoubleObj) /* 60 */ #define Tcl_SetIntObj \ (tclStubsPtr->tcl_SetIntObj) /* 61 */ #define Tcl_SetListObj \ (tclStubsPtr->tcl_SetListObj) /* 62 */ #define Tcl_SetLongObj \ (tclStubsPtr->tcl_SetLongObj) /* 63 */ #define Tcl_SetObjLength \ (tclStubsPtr->tcl_SetObjLength) /* 64 */ #define Tcl_SetStringObj \ (tclStubsPtr->tcl_SetStringObj) /* 65 */ #define Tcl_AddErrorInfo \ (tclStubsPtr->tcl_AddErrorInfo) /* 66 */ #define Tcl_AddObjErrorInfo \ (tclStubsPtr->tcl_AddObjErrorInfo) /* 67 */ #define Tcl_AllowExceptions \ (tclStubsPtr->tcl_AllowExceptions) /* 68 */ #define Tcl_AppendElement \ (tclStubsPtr->tcl_AppendElement) /* 69 */ #define Tcl_AppendResult \ (tclStubsPtr->tcl_AppendResult) /* 70 */ #define Tcl_AsyncCreate \ (tclStubsPtr->tcl_AsyncCreate) /* 71 */ #define Tcl_AsyncDelete \ (tclStubsPtr->tcl_AsyncDelete) /* 72 */ #define Tcl_AsyncInvoke \ (tclStubsPtr->tcl_AsyncInvoke) /* 73 */ #define Tcl_AsyncMark \ (tclStubsPtr->tcl_AsyncMark) /* 74 */ #define Tcl_AsyncReady \ (tclStubsPtr->tcl_AsyncReady) /* 75 */ #define Tcl_BackgroundError \ (tclStubsPtr->tcl_BackgroundError) /* 76 */ #define Tcl_Backslash \ (tclStubsPtr->tcl_Backslash) /* 77 */ #define Tcl_BadChannelOption \ (tclStubsPtr->tcl_BadChannelOption) /* 78 */ #define Tcl_CallWhenDeleted \ (tclStubsPtr->tcl_CallWhenDeleted) /* 79 */ #define Tcl_CancelIdleCall \ (tclStubsPtr->tcl_CancelIdleCall) /* 80 */ #define Tcl_Close \ (tclStubsPtr->tcl_Close) /* 81 */ #define Tcl_CommandComplete \ (tclStubsPtr->tcl_CommandComplete) /* 82 */ #define Tcl_Concat \ (tclStubsPtr->tcl_Concat) /* 83 */ #define Tcl_ConvertElement \ (tclStubsPtr->tcl_ConvertElement) /* 84 */ #define Tcl_ConvertCountedElement \ (tclStubsPtr->tcl_ConvertCountedElement) /* 85 */ #define Tcl_CreateAlias \ (tclStubsPtr->tcl_CreateAlias) /* 86 */ #define Tcl_CreateAliasObj \ (tclStubsPtr->tcl_CreateAliasObj) /* 87 */ #define Tcl_CreateChannel \ (tclStubsPtr->tcl_CreateChannel) /* 88 */ #define Tcl_CreateChannelHandler \ (tclStubsPtr->tcl_CreateChannelHandler) /* 89 */ #define Tcl_CreateCloseHandler \ (tclStubsPtr->tcl_CreateCloseHandler) /* 90 */ #define Tcl_CreateCommand \ (tclStubsPtr->tcl_CreateCommand) /* 91 */ #define Tcl_CreateEventSource \ (tclStubsPtr->tcl_CreateEventSource) /* 92 */ #define Tcl_CreateExitHandler \ (tclStubsPtr->tcl_CreateExitHandler) /* 93 */ #define Tcl_CreateInterp \ (tclStubsPtr->tcl_CreateInterp) /* 94 */ #define Tcl_CreateMathFunc \ (tclStubsPtr->tcl_CreateMathFunc) /* 95 */ #define Tcl_CreateObjCommand \ (tclStubsPtr->tcl_CreateObjCommand) /* 96 */ #define Tcl_CreateSlave \ (tclStubsPtr->tcl_CreateSlave) /* 97 */ #define Tcl_CreateTimerHandler \ (tclStubsPtr->tcl_CreateTimerHandler) /* 98 */ #define Tcl_CreateTrace \ (tclStubsPtr->tcl_CreateTrace) /* 99 */ #define Tcl_DeleteAssocData \ (tclStubsPtr->tcl_DeleteAssocData) /* 100 */ #define Tcl_DeleteChannelHandler \ (tclStubsPtr->tcl_DeleteChannelHandler) /* 101 */ #define Tcl_DeleteCloseHandler \ (tclStubsPtr->tcl_DeleteCloseHandler) /* 102 */ #define Tcl_DeleteCommand \ (tclStubsPtr->tcl_DeleteCommand) /* 103 */ #define Tcl_DeleteCommandFromToken \ (tclStubsPtr->tcl_DeleteCommandFromToken) /* 104 */ #define Tcl_DeleteEvents \ (tclStubsPtr->tcl_DeleteEvents) /* 105 */ #define Tcl_DeleteEventSource \ (tclStubsPtr->tcl_DeleteEventSource) /* 106 */ #define Tcl_DeleteExitHandler \ (tclStubsPtr->tcl_DeleteExitHandler) /* 107 */ #define Tcl_DeleteHashEntry \ (tclStubsPtr->tcl_DeleteHashEntry) /* 108 */ #define Tcl_DeleteHashTable \ (tclStubsPtr->tcl_DeleteHashTable) /* 109 */ #define Tcl_DeleteInterp \ (tclStubsPtr->tcl_DeleteInterp) /* 110 */ #define Tcl_DetachPids \ (tclStubsPtr->tcl_DetachPids) /* 111 */ #define Tcl_DeleteTimerHandler \ (tclStubsPtr->tcl_DeleteTimerHandler) /* 112 */ #define Tcl_DeleteTrace \ (tclStubsPtr->tcl_DeleteTrace) /* 113 */ #define Tcl_DontCallWhenDeleted \ (tclStubsPtr->tcl_DontCallWhenDeleted) /* 114 */ #define Tcl_DoOneEvent \ (tclStubsPtr->tcl_DoOneEvent) /* 115 */ #define Tcl_DoWhenIdle \ (tclStubsPtr->tcl_DoWhenIdle) /* 116 */ #define Tcl_DStringAppend \ (tclStubsPtr->tcl_DStringAppend) /* 117 */ #define Tcl_DStringAppendElement \ (tclStubsPtr->tcl_DStringAppendElement) /* 118 */ #define Tcl_DStringEndSublist \ (tclStubsPtr->tcl_DStringEndSublist) /* 119 */ #define Tcl_DStringFree \ (tclStubsPtr->tcl_DStringFree) /* 120 */ #define Tcl_DStringGetResult \ (tclStubsPtr->tcl_DStringGetResult) /* 121 */ #define Tcl_DStringInit \ (tclStubsPtr->tcl_DStringInit) /* 122 */ #define Tcl_DStringResult \ (tclStubsPtr->tcl_DStringResult) /* 123 */ #define Tcl_DStringSetLength \ (tclStubsPtr->tcl_DStringSetLength) /* 124 */ #define Tcl_DStringStartSublist \ (tclStubsPtr->tcl_DStringStartSublist) /* 125 */ #define Tcl_Eof \ (tclStubsPtr->tcl_Eof) /* 126 */ #define Tcl_ErrnoId \ (tclStubsPtr->tcl_ErrnoId) /* 127 */ #define Tcl_ErrnoMsg \ (tclStubsPtr->tcl_ErrnoMsg) /* 128 */ #define Tcl_Eval \ (tclStubsPtr->tcl_Eval) /* 129 */ #define Tcl_EvalFile \ (tclStubsPtr->tcl_EvalFile) /* 130 */ #define Tcl_EvalObj \ (tclStubsPtr->tcl_EvalObj) /* 131 */ #define Tcl_EventuallyFree \ (tclStubsPtr->tcl_EventuallyFree) /* 132 */ #define Tcl_Exit \ (tclStubsPtr->tcl_Exit) /* 133 */ #define Tcl_ExposeCommand \ (tclStubsPtr->tcl_ExposeCommand) /* 134 */ #define Tcl_ExprBoolean \ (tclStubsPtr->tcl_ExprBoolean) /* 135 */ #define Tcl_ExprBooleanObj \ (tclStubsPtr->tcl_ExprBooleanObj) /* 136 */ #define Tcl_ExprDouble \ (tclStubsPtr->tcl_ExprDouble) /* 137 */ #define Tcl_ExprDoubleObj \ (tclStubsPtr->tcl_ExprDoubleObj) /* 138 */ #define Tcl_ExprLong \ (tclStubsPtr->tcl_ExprLong) /* 139 */ #define Tcl_ExprLongObj \ (tclStubsPtr->tcl_ExprLongObj) /* 140 */ #define Tcl_ExprObj \ (tclStubsPtr->tcl_ExprObj) /* 141 */ #define Tcl_ExprString \ (tclStubsPtr->tcl_ExprString) /* 142 */ #define Tcl_Finalize \ (tclStubsPtr->tcl_Finalize) /* 143 */ #define Tcl_FindExecutable \ (tclStubsPtr->tcl_FindExecutable) /* 144 */ #define Tcl_FirstHashEntry \ (tclStubsPtr->tcl_FirstHashEntry) /* 145 */ #define Tcl_Flush \ (tclStubsPtr->tcl_Flush) /* 146 */ #define Tcl_FreeResult \ (tclStubsPtr->tcl_FreeResult) /* 147 */ #define Tcl_GetAlias \ (tclStubsPtr->tcl_GetAlias) /* 148 */ #define Tcl_GetAliasObj \ (tclStubsPtr->tcl_GetAliasObj) /* 149 */ #define Tcl_GetAssocData \ (tclStubsPtr->tcl_GetAssocData) /* 150 */ #define Tcl_GetChannel \ (tclStubsPtr->tcl_GetChannel) /* 151 */ #define Tcl_GetChannelBufferSize \ (tclStubsPtr->tcl_GetChannelBufferSize) /* 152 */ #define Tcl_GetChannelHandle \ (tclStubsPtr->tcl_GetChannelHandle) /* 153 */ #define Tcl_GetChannelInstanceData \ (tclStubsPtr->tcl_GetChannelInstanceData) /* 154 */ #define Tcl_GetChannelMode \ (tclStubsPtr->tcl_GetChannelMode) /* 155 */ #define Tcl_GetChannelName \ (tclStubsPtr->tcl_GetChannelName) /* 156 */ #define Tcl_GetChannelOption \ (tclStubsPtr->tcl_GetChannelOption) /* 157 */ #define Tcl_GetChannelType \ (tclStubsPtr->tcl_GetChannelType) /* 158 */ #define Tcl_GetCommandInfo \ (tclStubsPtr->tcl_GetCommandInfo) /* 159 */ #define Tcl_GetCommandName \ (tclStubsPtr->tcl_GetCommandName) /* 160 */ #define Tcl_GetErrno \ (tclStubsPtr->tcl_GetErrno) /* 161 */ #define Tcl_GetHostName \ (tclStubsPtr->tcl_GetHostName) /* 162 */ #define Tcl_GetInterpPath \ (tclStubsPtr->tcl_GetInterpPath) /* 163 */ #define Tcl_GetMaster \ (tclStubsPtr->tcl_GetMaster) /* 164 */ #define Tcl_GetNameOfExecutable \ (tclStubsPtr->tcl_GetNameOfExecutable) /* 165 */ #define Tcl_GetObjResult \ (tclStubsPtr->tcl_GetObjResult) /* 166 */ #if !defined(_WIN32) && !defined(MAC_OSX_TCL) /* UNIX */ #define Tcl_GetOpenFile \ (tclStubsPtr->tcl_GetOpenFile) /* 167 */ #endif /* UNIX */ #ifdef MAC_OSX_TCL /* MACOSX */ #define Tcl_GetOpenFile \ (tclStubsPtr->tcl_GetOpenFile) /* 167 */ #endif /* MACOSX */ #define Tcl_GetPathType \ (tclStubsPtr->tcl_GetPathType) /* 168 */ #define Tcl_Gets \ (tclStubsPtr->tcl_Gets) /* 169 */ #define Tcl_GetsObj \ (tclStubsPtr->tcl_GetsObj) /* 170 */ #define Tcl_GetServiceMode \ (tclStubsPtr->tcl_GetServiceMode) /* 171 */ #define Tcl_GetSlave \ (tclStubsPtr->tcl_GetSlave) /* 172 */ #define Tcl_GetStdChannel \ (tclStubsPtr->tcl_GetStdChannel) /* 173 */ #define Tcl_GetStringResult \ (tclStubsPtr->tcl_GetStringResult) /* 174 */ #define Tcl_GetVar \ (tclStubsPtr->tcl_GetVar) /* 175 */ #define Tcl_GetVar2 \ (tclStubsPtr->tcl_GetVar2) /* 176 */ #define Tcl_GlobalEval \ (tclStubsPtr->tcl_GlobalEval) /* 177 */ #define Tcl_GlobalEvalObj \ (tclStubsPtr->tcl_GlobalEvalObj) /* 178 */ #define Tcl_HideCommand \ (tclStubsPtr->tcl_HideCommand) /* 179 */ #define Tcl_Init \ (tclStubsPtr->tcl_Init) /* 180 */ #define Tcl_InitHashTable \ (tclStubsPtr->tcl_InitHashTable) /* 181 */ #define Tcl_InputBlocked \ (tclStubsPtr->tcl_InputBlocked) /* 182 */ #define Tcl_InputBuffered \ (tclStubsPtr->tcl_InputBuffered) /* 183 */ #define Tcl_InterpDeleted \ (tclStubsPtr->tcl_InterpDeleted) /* 184 */ #define Tcl_IsSafe \ (tclStubsPtr->tcl_IsSafe) /* 185 */ #define Tcl_JoinPath \ (tclStubsPtr->tcl_JoinPath) /* 186 */ #define Tcl_LinkVar \ (tclStubsPtr->tcl_LinkVar) /* 187 */ /* Slot 188 is reserved */ #define Tcl_MakeFileChannel \ (tclStubsPtr->tcl_MakeFileChannel) /* 189 */ #define Tcl_MakeSafe \ (tclStubsPtr->tcl_MakeSafe) /* 190 */ #define Tcl_MakeTcpClientChannel \ (tclStubsPtr->tcl_MakeTcpClientChannel) /* 191 */ #define Tcl_Merge \ (tclStubsPtr->tcl_Merge) /* 192 */ #define Tcl_NextHashEntry \ (tclStubsPtr->tcl_NextHashEntry) /* 193 */ #define Tcl_NotifyChannel \ (tclStubsPtr->tcl_NotifyChannel) /* 194 */ #define Tcl_ObjGetVar2 \ (tclStubsPtr->tcl_ObjGetVar2) /* 195 */ #define Tcl_ObjSetVar2 \ (tclStubsPtr->tcl_ObjSetVar2) /* 196 */ #define Tcl_OpenCommandChannel \ (tclStubsPtr->tcl_OpenCommandChannel) /* 197 */ #define Tcl_OpenFileChannel \ (tclStubsPtr->tcl_OpenFileChannel) /* 198 */ #define Tcl_OpenTcpClient \ (tclStubsPtr->tcl_OpenTcpClient) /* 199 */ #define Tcl_OpenTcpServer \ (tclStubsPtr->tcl_OpenTcpServer) /* 200 */ #define Tcl_Preserve \ (tclStubsPtr->tcl_Preserve) /* 201 */ #define Tcl_PrintDouble \ (tclStubsPtr->tcl_PrintDouble) /* 202 */ #define Tcl_PutEnv \ (tclStubsPtr->tcl_PutEnv) /* 203 */ #define Tcl_PosixError \ (tclStubsPtr->tcl_PosixError) /* 204 */ #define Tcl_QueueEvent \ (tclStubsPtr->tcl_QueueEvent) /* 205 */ #define Tcl_Read \ (tclStubsPtr->tcl_Read) /* 206 */ #define Tcl_ReapDetachedProcs \ (tclStubsPtr->tcl_ReapDetachedProcs) /* 207 */ #define Tcl_RecordAndEval \ (tclStubsPtr->tcl_RecordAndEval) /* 208 */ #define Tcl_RecordAndEvalObj \ (tclStubsPtr->tcl_RecordAndEvalObj) /* 209 */ #define Tcl_RegisterChannel \ (tclStubsPtr->tcl_RegisterChannel) /* 210 */ #define Tcl_RegisterObjType \ (tclStubsPtr->tcl_RegisterObjType) /* 211 */ #define Tcl_RegExpCompile \ (tclStubsPtr->tcl_RegExpCompile) /* 212 */ #define Tcl_RegExpExec \ (tclStubsPtr->tcl_RegExpExec) /* 213 */ #define Tcl_RegExpMatch \ (tclStubsPtr->tcl_RegExpMatch) /* 214 */ #define Tcl_RegExpRange \ (tclStubsPtr->tcl_RegExpRange) /* 215 */ #define Tcl_Release \ (tclStubsPtr->tcl_Release) /* 216 */ #define Tcl_ResetResult \ (tclStubsPtr->tcl_ResetResult) /* 217 */ #define Tcl_ScanElement \ (tclStubsPtr->tcl_ScanElement) /* 218 */ #define Tcl_ScanCountedElement \ (tclStubsPtr->tcl_ScanCountedElement) /* 219 */ #define Tcl_SeekOld \ (tclStubsPtr->tcl_SeekOld) /* 220 */ #define Tcl_ServiceAll \ (tclStubsPtr->tcl_ServiceAll) /* 221 */ #define Tcl_ServiceEvent \ (tclStubsPtr->tcl_ServiceEvent) /* 222 */ #define Tcl_SetAssocData \ (tclStubsPtr->tcl_SetAssocData) /* 223 */ #define Tcl_SetChannelBufferSize \ (tclStubsPtr->tcl_SetChannelBufferSize) /* 224 */ #define Tcl_SetChannelOption \ (tclStubsPtr->tcl_SetChannelOption) /* 225 */ #define Tcl_SetCommandInfo \ (tclStubsPtr->tcl_SetCommandInfo) /* 226 */ #define Tcl_SetErrno \ (tclStubsPtr->tcl_SetErrno) /* 227 */ #define Tcl_SetErrorCode \ (tclStubsPtr->tcl_SetErrorCode) /* 228 */ #define Tcl_SetMaxBlockTime \ (tclStubsPtr->tcl_SetMaxBlockTime) /* 229 */ #define Tcl_SetPanicProc \ (tclStubsPtr->tcl_SetPanicProc) /* 230 */ #define Tcl_SetRecursionLimit \ (tclStubsPtr->tcl_SetRecursionLimit) /* 231 */ #define Tcl_SetResult \ (tclStubsPtr->tcl_SetResult) /* 232 */ #define Tcl_SetServiceMode \ (tclStubsPtr->tcl_SetServiceMode) /* 233 */ #define Tcl_SetObjErrorCode \ (tclStubsPtr->tcl_SetObjErrorCode) /* 234 */ #define Tcl_SetObjResult \ (tclStubsPtr->tcl_SetObjResult) /* 235 */ #define Tcl_SetStdChannel \ (tclStubsPtr->tcl_SetStdChannel) /* 236 */ #define Tcl_SetVar \ (tclStubsPtr->tcl_SetVar) /* 237 */ #define Tcl_SetVar2 \ (tclStubsPtr->tcl_SetVar2) /* 238 */ #define Tcl_SignalId \ (tclStubsPtr->tcl_SignalId) /* 239 */ #define Tcl_SignalMsg \ (tclStubsPtr->tcl_SignalMsg) /* 240 */ #define Tcl_SourceRCFile \ (tclStubsPtr->tcl_SourceRCFile) /* 241 */ #define Tcl_SplitList \ (tclStubsPtr->tcl_SplitList) /* 242 */ #define Tcl_SplitPath \ (tclStubsPtr->tcl_SplitPath) /* 243 */ #define Tcl_StaticPackage \ (tclStubsPtr->tcl_StaticPackage) /* 244 */ #define Tcl_StringMatch \ (tclStubsPtr->tcl_StringMatch) /* 245 */ #define Tcl_TellOld \ (tclStubsPtr->tcl_TellOld) /* 246 */ #define Tcl_TraceVar \ (tclStubsPtr->tcl_TraceVar) /* 247 */ #define Tcl_TraceVar2 \ (tclStubsPtr->tcl_TraceVar2) /* 248 */ #define Tcl_TranslateFileName \ (tclStubsPtr->tcl_TranslateFileName) /* 249 */ #define Tcl_Ungets \ (tclStubsPtr->tcl_Ungets) /* 250 */ #define Tcl_UnlinkVar \ (tclStubsPtr->tcl_UnlinkVar) /* 251 */ #define Tcl_UnregisterChannel \ (tclStubsPtr->tcl_UnregisterChannel) /* 252 */ #define Tcl_UnsetVar \ (tclStubsPtr->tcl_UnsetVar) /* 253 */ #define Tcl_UnsetVar2 \ (tclStubsPtr->tcl_UnsetVar2) /* 254 */ #define Tcl_UntraceVar \ (tclStubsPtr->tcl_UntraceVar) /* 255 */ #define Tcl_UntraceVar2 \ (tclStubsPtr->tcl_UntraceVar2) /* 256 */ #define Tcl_UpdateLinkedVar \ (tclStubsPtr->tcl_UpdateLinkedVar) /* 257 */ #define Tcl_UpVar \ (tclStubsPtr->tcl_UpVar) /* 258 */ #define Tcl_UpVar2 \ (tclStubsPtr->tcl_UpVar2) /* 259 */ #define Tcl_VarEval \ (tclStubsPtr->tcl_VarEval) /* 260 */ #define Tcl_VarTraceInfo \ (tclStubsPtr->tcl_VarTraceInfo) /* 261 */ #define Tcl_VarTraceInfo2 \ (tclStubsPtr->tcl_VarTraceInfo2) /* 262 */ #define Tcl_Write \ (tclStubsPtr->tcl_Write) /* 263 */ #define Tcl_WrongNumArgs \ (tclStubsPtr->tcl_WrongNumArgs) /* 264 */ #define Tcl_DumpActiveMemory \ (tclStubsPtr->tcl_DumpActiveMemory) /* 265 */ #define Tcl_ValidateAllMemory \ (tclStubsPtr->tcl_ValidateAllMemory) /* 266 */ #define Tcl_AppendResultVA \ (tclStubsPtr->tcl_AppendResultVA) /* 267 */ #define Tcl_AppendStringsToObjVA \ (tclStubsPtr->tcl_AppendStringsToObjVA) /* 268 */ #define Tcl_HashStats \ (tclStubsPtr->tcl_HashStats) /* 269 */ #define Tcl_ParseVar \ (tclStubsPtr->tcl_ParseVar) /* 270 */ #define Tcl_PkgPresent \ (tclStubsPtr->tcl_PkgPresent) /* 271 */ #define Tcl_PkgPresentEx \ (tclStubsPtr->tcl_PkgPresentEx) /* 272 */ #define Tcl_PkgProvide \ (tclStubsPtr->tcl_PkgProvide) /* 273 */ #define Tcl_PkgRequire \ (tclStubsPtr->tcl_PkgRequire) /* 274 */ #define Tcl_SetErrorCodeVA \ (tclStubsPtr->tcl_SetErrorCodeVA) /* 275 */ #define Tcl_VarEvalVA \ (tclStubsPtr->tcl_VarEvalVA) /* 276 */ #define Tcl_WaitPid \ (tclStubsPtr->tcl_WaitPid) /* 277 */ #define Tcl_PanicVA \ (tclStubsPtr->tcl_PanicVA) /* 278 */ #define Tcl_GetVersion \ (tclStubsPtr->tcl_GetVersion) /* 279 */ #define Tcl_InitMemory \ (tclStubsPtr->tcl_InitMemory) /* 280 */ #define Tcl_StackChannel \ (tclStubsPtr->tcl_StackChannel) /* 281 */ #define Tcl_UnstackChannel \ (tclStubsPtr->tcl_UnstackChannel) /* 282 */ #define Tcl_GetStackedChannel \ (tclStubsPtr->tcl_GetStackedChannel) /* 283 */ #define Tcl_SetMainLoop \ (tclStubsPtr->tcl_SetMainLoop) /* 284 */ /* Slot 285 is reserved */ #define Tcl_AppendObjToObj \ (tclStubsPtr->tcl_AppendObjToObj) /* 286 */ #define Tcl_CreateEncoding \ (tclStubsPtr->tcl_CreateEncoding) /* 287 */ #define Tcl_CreateThreadExitHandler \ (tclStubsPtr->tcl_CreateThreadExitHandler) /* 288 */ #define Tcl_DeleteThreadExitHandler \ (tclStubsPtr->tcl_DeleteThreadExitHandler) /* 289 */ #define Tcl_DiscardResult \ (tclStubsPtr->tcl_DiscardResult) /* 290 */ #define Tcl_EvalEx \ (tclStubsPtr->tcl_EvalEx) /* 291 */ #define Tcl_EvalObjv \ (tclStubsPtr->tcl_EvalObjv) /* 292 */ #define Tcl_EvalObjEx \ (tclStubsPtr->tcl_EvalObjEx) /* 293 */ #define Tcl_ExitThread \ (tclStubsPtr->tcl_ExitThread) /* 294 */ #define Tcl_ExternalToUtf \ (tclStubsPtr->tcl_ExternalToUtf) /* 295 */ #define Tcl_ExternalToUtfDString \ (tclStubsPtr->tcl_ExternalToUtfDString) /* 296 */ #define Tcl_FinalizeThread \ (tclStubsPtr->tcl_FinalizeThread) /* 297 */ #define Tcl_FinalizeNotifier \ (tclStubsPtr->tcl_FinalizeNotifier) /* 298 */ #define Tcl_FreeEncoding \ (tclStubsPtr->tcl_FreeEncoding) /* 299 */ #define Tcl_GetCurrentThread \ (tclStubsPtr->tcl_GetCurrentThread) /* 300 */ #define Tcl_GetEncoding \ (tclStubsPtr->tcl_GetEncoding) /* 301 */ #define Tcl_GetEncodingName \ (tclStubsPtr->tcl_GetEncodingName) /* 302 */ #define Tcl_GetEncodingNames \ (tclStubsPtr->tcl_GetEncodingNames) /* 303 */ #define Tcl_GetIndexFromObjStruct \ (tclStubsPtr->tcl_GetIndexFromObjStruct) /* 304 */ #define Tcl_GetThreadData \ (tclStubsPtr->tcl_GetThreadData) /* 305 */ #define Tcl_GetVar2Ex \ (tclStubsPtr->tcl_GetVar2Ex) /* 306 */ #define Tcl_InitNotifier \ (tclStubsPtr->tcl_InitNotifier) /* 307 */ #define Tcl_MutexLock \ (tclStubsPtr->tcl_MutexLock) /* 308 */ #define Tcl_MutexUnlock \ (tclStubsPtr->tcl_MutexUnlock) /* 309 */ #define Tcl_ConditionNotify \ (tclStubsPtr->tcl_ConditionNotify) /* 310 */ #define Tcl_ConditionWait \ (tclStubsPtr->tcl_ConditionWait) /* 311 */ #define Tcl_NumUtfChars \ (tclStubsPtr->tcl_NumUtfChars) /* 312 */ #define Tcl_ReadChars \ (tclStubsPtr->tcl_ReadChars) /* 313 */ #define Tcl_RestoreResult \ (tclStubsPtr->tcl_RestoreResult) /* 314 */ #define Tcl_SaveResult \ (tclStubsPtr->tcl_SaveResult) /* 315 */ #define Tcl_SetSystemEncoding \ (tclStubsPtr->tcl_SetSystemEncoding) /* 316 */ #define Tcl_SetVar2Ex \ (tclStubsPtr->tcl_SetVar2Ex) /* 317 */ #define Tcl_ThreadAlert \ (tclStubsPtr->tcl_ThreadAlert) /* 318 */ #define Tcl_ThreadQueueEvent \ (tclStubsPtr->tcl_ThreadQueueEvent) /* 319 */ #define Tcl_UniCharAtIndex \ (tclStubsPtr->tcl_UniCharAtIndex) /* 320 */ #define Tcl_UniCharToLower \ (tclStubsPtr->tcl_UniCharToLower) /* 321 */ #define Tcl_UniCharToTitle \ (tclStubsPtr->tcl_UniCharToTitle) /* 322 */ #define Tcl_UniCharToUpper \ (tclStubsPtr->tcl_UniCharToUpper) /* 323 */ #define Tcl_UniCharToUtf \ (tclStubsPtr->tcl_UniCharToUtf) /* 324 */ #define Tcl_UtfAtIndex \ (tclStubsPtr->tcl_UtfAtIndex) /* 325 */ #define Tcl_UtfCharComplete \ (tclStubsPtr->tcl_UtfCharComplete) /* 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 Tcl_UtfToExternal \ (tclStubsPtr->tcl_UtfToExternal) /* 332 */ #define Tcl_UtfToExternalDString \ (tclStubsPtr->tcl_UtfToExternalDString) /* 333 */ #define Tcl_UtfToLower \ (tclStubsPtr->tcl_UtfToLower) /* 334 */ #define Tcl_UtfToTitle \ (tclStubsPtr->tcl_UtfToTitle) /* 335 */ #define Tcl_UtfToUniChar \ (tclStubsPtr->tcl_UtfToUniChar) /* 336 */ #define Tcl_UtfToUpper \ (tclStubsPtr->tcl_UtfToUpper) /* 337 */ #define Tcl_WriteChars \ (tclStubsPtr->tcl_WriteChars) /* 338 */ #define Tcl_WriteObj \ (tclStubsPtr->tcl_WriteObj) /* 339 */ #define Tcl_GetString \ (tclStubsPtr->tcl_GetString) /* 340 */ #define Tcl_GetDefaultEncodingDir \ (tclStubsPtr->tcl_GetDefaultEncodingDir) /* 341 */ #define Tcl_SetDefaultEncodingDir \ (tclStubsPtr->tcl_SetDefaultEncodingDir) /* 342 */ #define Tcl_AlertNotifier \ (tclStubsPtr->tcl_AlertNotifier) /* 343 */ #define Tcl_ServiceModeHook \ (tclStubsPtr->tcl_ServiceModeHook) /* 344 */ #define Tcl_UniCharIsAlnum \ (tclStubsPtr->tcl_UniCharIsAlnum) /* 345 */ #define Tcl_UniCharIsAlpha \ (tclStubsPtr->tcl_UniCharIsAlpha) /* 346 */ #define Tcl_UniCharIsDigit \ (tclStubsPtr->tcl_UniCharIsDigit) /* 347 */ #define Tcl_UniCharIsLower \ (tclStubsPtr->tcl_UniCharIsLower) /* 348 */ #define Tcl_UniCharIsSpace \ (tclStubsPtr->tcl_UniCharIsSpace) /* 349 */ #define Tcl_UniCharIsUpper \ (tclStubsPtr->tcl_UniCharIsUpper) /* 350 */ #define Tcl_UniCharIsWordChar \ (tclStubsPtr->tcl_UniCharIsWordChar) /* 351 */ #define Tcl_UniCharLen \ (tclStubsPtr->tcl_UniCharLen) /* 352 */ #define Tcl_UniCharNcmp \ (tclStubsPtr->tcl_UniCharNcmp) /* 353 */ #define Tcl_UniCharToUtfDString \ (tclStubsPtr->tcl_UniCharToUtfDString) /* 354 */ #define Tcl_UtfToUniCharDString \ (tclStubsPtr->tcl_UtfToUniCharDString) /* 355 */ #define Tcl_GetRegExpFromObj \ (tclStubsPtr->tcl_GetRegExpFromObj) /* 356 */ #define Tcl_EvalTokens \ (tclStubsPtr->tcl_EvalTokens) /* 357 */ #define Tcl_FreeParse \ (tclStubsPtr->tcl_FreeParse) /* 358 */ #define Tcl_LogCommandInfo \ (tclStubsPtr->tcl_LogCommandInfo) /* 359 */ #define Tcl_ParseBraces \ (tclStubsPtr->tcl_ParseBraces) /* 360 */ #define Tcl_ParseCommand \ (tclStubsPtr->tcl_ParseCommand) /* 361 */ #define Tcl_ParseExpr \ (tclStubsPtr->tcl_ParseExpr) /* 362 */ #define Tcl_ParseQuotedString \ (tclStubsPtr->tcl_ParseQuotedString) /* 363 */ #define Tcl_ParseVarName \ (tclStubsPtr->tcl_ParseVarName) /* 364 */ #define Tcl_GetCwd \ (tclStubsPtr->tcl_GetCwd) /* 365 */ #define Tcl_Chdir \ (tclStubsPtr->tcl_Chdir) /* 366 */ #define Tcl_Access \ (tclStubsPtr->tcl_Access) /* 367 */ #define Tcl_Stat \ (tclStubsPtr->tcl_Stat) /* 368 */ #define Tcl_UtfNcmp \ (tclStubsPtr->tcl_UtfNcmp) /* 369 */ #define Tcl_UtfNcasecmp \ (tclStubsPtr->tcl_UtfNcasecmp) /* 370 */ #define Tcl_StringCaseMatch \ (tclStubsPtr->tcl_StringCaseMatch) /* 371 */ #define Tcl_UniCharIsControl \ (tclStubsPtr->tcl_UniCharIsControl) /* 372 */ #define Tcl_UniCharIsGraph \ (tclStubsPtr->tcl_UniCharIsGraph) /* 373 */ #define Tcl_UniCharIsPrint \ (tclStubsPtr->tcl_UniCharIsPrint) /* 374 */ #define Tcl_UniCharIsPunct \ (tclStubsPtr->tcl_UniCharIsPunct) /* 375 */ #define Tcl_RegExpExecObj \ (tclStubsPtr->tcl_RegExpExecObj) /* 376 */ #define Tcl_RegExpGetInfo \ (tclStubsPtr->tcl_RegExpGetInfo) /* 377 */ #define Tcl_NewUnicodeObj \ (tclStubsPtr->tcl_NewUnicodeObj) /* 378 */ #define Tcl_SetUnicodeObj \ (tclStubsPtr->tcl_SetUnicodeObj) /* 379 */ #define Tcl_GetCharLength \ (tclStubsPtr->tcl_GetCharLength) /* 380 */ #define Tcl_GetUniChar \ (tclStubsPtr->tcl_GetUniChar) /* 381 */ #define Tcl_GetUnicode \ (tclStubsPtr->tcl_GetUnicode) /* 382 */ #define Tcl_GetRange \ (tclStubsPtr->tcl_GetRange) /* 383 */ #define Tcl_AppendUnicodeToObj \ (tclStubsPtr->tcl_AppendUnicodeToObj) /* 384 */ #define Tcl_RegExpMatchObj \ (tclStubsPtr->tcl_RegExpMatchObj) /* 385 */ #define Tcl_SetNotifier \ (tclStubsPtr->tcl_SetNotifier) /* 386 */ #define Tcl_GetAllocMutex \ (tclStubsPtr->tcl_GetAllocMutex) /* 387 */ #define Tcl_GetChannelNames \ (tclStubsPtr->tcl_GetChannelNames) /* 388 */ #define Tcl_GetChannelNamesEx \ (tclStubsPtr->tcl_GetChannelNamesEx) /* 389 */ #define Tcl_ProcObjCmd \ (tclStubsPtr->tcl_ProcObjCmd) /* 390 */ #define Tcl_ConditionFinalize \ (tclStubsPtr->tcl_ConditionFinalize) /* 391 */ #define Tcl_MutexFinalize \ (tclStubsPtr->tcl_MutexFinalize) /* 392 */ #define Tcl_CreateThread \ (tclStubsPtr->tcl_CreateThread) /* 393 */ #define Tcl_ReadRaw \ (tclStubsPtr->tcl_ReadRaw) /* 394 */ #define Tcl_WriteRaw \ (tclStubsPtr->tcl_WriteRaw) /* 395 */ #define Tcl_GetTopChannel \ (tclStubsPtr->tcl_GetTopChannel) /* 396 */ #define Tcl_ChannelBuffered \ (tclStubsPtr->tcl_ChannelBuffered) /* 397 */ #define Tcl_ChannelName \ (tclStubsPtr->tcl_ChannelName) /* 398 */ #define Tcl_ChannelVersion \ (tclStubsPtr->tcl_ChannelVersion) /* 399 */ #define Tcl_ChannelBlockModeProc \ (tclStubsPtr->tcl_ChannelBlockModeProc) /* 400 */ #define Tcl_ChannelCloseProc \ (tclStubsPtr->tcl_ChannelCloseProc) /* 401 */ #define Tcl_ChannelClose2Proc \ (tclStubsPtr->tcl_ChannelClose2Proc) /* 402 */ #define Tcl_ChannelInputProc \ (tclStubsPtr->tcl_ChannelInputProc) /* 403 */ #define Tcl_ChannelOutputProc \ (tclStubsPtr->tcl_ChannelOutputProc) /* 404 */ #define Tcl_ChannelSeekProc \ (tclStubsPtr->tcl_ChannelSeekProc) /* 405 */ #define Tcl_ChannelSetOptionProc \ (tclStubsPtr->tcl_ChannelSetOptionProc) /* 406 */ #define Tcl_ChannelGetOptionProc \ (tclStubsPtr->tcl_ChannelGetOptionProc) /* 407 */ #define Tcl_ChannelWatchProc \ (tclStubsPtr->tcl_ChannelWatchProc) /* 408 */ #define Tcl_ChannelGetHandleProc \ (tclStubsPtr->tcl_ChannelGetHandleProc) /* 409 */ #define Tcl_ChannelFlushProc \ (tclStubsPtr->tcl_ChannelFlushProc) /* 410 */ #define Tcl_ChannelHandlerProc \ (tclStubsPtr->tcl_ChannelHandlerProc) /* 411 */ #define Tcl_JoinThread \ (tclStubsPtr->tcl_JoinThread) /* 412 */ #define Tcl_IsChannelShared \ (tclStubsPtr->tcl_IsChannelShared) /* 413 */ #define Tcl_IsChannelRegistered \ (tclStubsPtr->tcl_IsChannelRegistered) /* 414 */ #define Tcl_CutChannel \ (tclStubsPtr->tcl_CutChannel) /* 415 */ #define Tcl_SpliceChannel \ (tclStubsPtr->tcl_SpliceChannel) /* 416 */ #define Tcl_ClearChannelHandlers \ (tclStubsPtr->tcl_ClearChannelHandlers) /* 417 */ #define Tcl_IsChannelExisting \ (tclStubsPtr->tcl_IsChannelExisting) /* 418 */ #define Tcl_UniCharNcasecmp \ (tclStubsPtr->tcl_UniCharNcasecmp) /* 419 */ #define Tcl_UniCharCaseMatch \ (tclStubsPtr->tcl_UniCharCaseMatch) /* 420 */ #define Tcl_FindHashEntry \ (tclStubsPtr->tcl_FindHashEntry) /* 421 */ #define Tcl_CreateHashEntry \ (tclStubsPtr->tcl_CreateHashEntry) /* 422 */ #define Tcl_InitCustomHashTable \ (tclStubsPtr->tcl_InitCustomHashTable) /* 423 */ #define Tcl_InitObjHashTable \ (tclStubsPtr->tcl_InitObjHashTable) /* 424 */ #define Tcl_CommandTraceInfo \ (tclStubsPtr->tcl_CommandTraceInfo) /* 425 */ #define Tcl_TraceCommand \ (tclStubsPtr->tcl_TraceCommand) /* 426 */ #define Tcl_UntraceCommand \ (tclStubsPtr->tcl_UntraceCommand) /* 427 */ #define Tcl_AttemptAlloc \ (tclStubsPtr->tcl_AttemptAlloc) /* 428 */ #define Tcl_AttemptDbCkalloc \ (tclStubsPtr->tcl_AttemptDbCkalloc) /* 429 */ #define Tcl_AttemptRealloc \ (tclStubsPtr->tcl_AttemptRealloc) /* 430 */ #define Tcl_AttemptDbCkrealloc \ (tclStubsPtr->tcl_AttemptDbCkrealloc) /* 431 */ #define Tcl_AttemptSetObjLength \ (tclStubsPtr->tcl_AttemptSetObjLength) /* 432 */ #define Tcl_GetChannelThread \ (tclStubsPtr->tcl_GetChannelThread) /* 433 */ #define Tcl_GetUnicodeFromObj \ (tclStubsPtr->tcl_GetUnicodeFromObj) /* 434 */ #define Tcl_GetMathFuncInfo \ (tclStubsPtr->tcl_GetMathFuncInfo) /* 435 */ #define Tcl_ListMathFuncs \ (tclStubsPtr->tcl_ListMathFuncs) /* 436 */ #define Tcl_SubstObj \ (tclStubsPtr->tcl_SubstObj) /* 437 */ #define Tcl_DetachChannel \ (tclStubsPtr->tcl_DetachChannel) /* 438 */ #define Tcl_IsStandardChannel \ (tclStubsPtr->tcl_IsStandardChannel) /* 439 */ #define Tcl_FSCopyFile \ (tclStubsPtr->tcl_FSCopyFile) /* 440 */ #define Tcl_FSCopyDirectory \ (tclStubsPtr->tcl_FSCopyDirectory) /* 441 */ #define Tcl_FSCreateDirectory \ (tclStubsPtr->tcl_FSCreateDirectory) /* 442 */ #define Tcl_FSDeleteFile \ (tclStubsPtr->tcl_FSDeleteFile) /* 443 */ #define Tcl_FSLoadFile \ (tclStubsPtr->tcl_FSLoadFile) /* 444 */ #define Tcl_FSMatchInDirectory \ (tclStubsPtr->tcl_FSMatchInDirectory) /* 445 */ #define Tcl_FSLink \ (tclStubsPtr->tcl_FSLink) /* 446 */ #define Tcl_FSRemoveDirectory \ (tclStubsPtr->tcl_FSRemoveDirectory) /* 447 */ #define Tcl_FSRenameFile \ (tclStubsPtr->tcl_FSRenameFile) /* 448 */ #define Tcl_FSLstat \ (tclStubsPtr->tcl_FSLstat) /* 449 */ #define Tcl_FSUtime \ (tclStubsPtr->tcl_FSUtime) /* 450 */ #define Tcl_FSFileAttrsGet \ (tclStubsPtr->tcl_FSFileAttrsGet) /* 451 */ #define Tcl_FSFileAttrsSet \ (tclStubsPtr->tcl_FSFileAttrsSet) /* 452 */ #define Tcl_FSFileAttrStrings \ (tclStubsPtr->tcl_FSFileAttrStrings) /* 453 */ #define Tcl_FSStat \ (tclStubsPtr->tcl_FSStat) /* 454 */ #define Tcl_FSAccess \ (tclStubsPtr->tcl_FSAccess) /* 455 */ #define Tcl_FSOpenFileChannel \ (tclStubsPtr->tcl_FSOpenFileChannel) /* 456 */ #define Tcl_FSGetCwd \ (tclStubsPtr->tcl_FSGetCwd) /* 457 */ #define Tcl_FSChdir \ (tclStubsPtr->tcl_FSChdir) /* 458 */ #define Tcl_FSConvertToPathType \ (tclStubsPtr->tcl_FSConvertToPathType) /* 459 */ #define Tcl_FSJoinPath \ (tclStubsPtr->tcl_FSJoinPath) /* 460 */ #define Tcl_FSSplitPath \ (tclStubsPtr->tcl_FSSplitPath) /* 461 */ #define Tcl_FSEqualPaths \ (tclStubsPtr->tcl_FSEqualPaths) /* 462 */ #define Tcl_FSGetNormalizedPath \ (tclStubsPtr->tcl_FSGetNormalizedPath) /* 463 */ #define Tcl_FSJoinToPath \ (tclStubsPtr->tcl_FSJoinToPath) /* 464 */ #define Tcl_FSGetInternalRep \ (tclStubsPtr->tcl_FSGetInternalRep) /* 465 */ #define Tcl_FSGetTranslatedPath \ (tclStubsPtr->tcl_FSGetTranslatedPath) /* 466 */ #define Tcl_FSEvalFile \ (tclStubsPtr->tcl_FSEvalFile) /* 467 */ #define Tcl_FSNewNativePath \ (tclStubsPtr->tcl_FSNewNativePath) /* 468 */ #define Tcl_FSGetNativePath \ (tclStubsPtr->tcl_FSGetNativePath) /* 469 */ #define Tcl_FSFileSystemInfo \ (tclStubsPtr->tcl_FSFileSystemInfo) /* 470 */ #define Tcl_FSPathSeparator \ (tclStubsPtr->tcl_FSPathSeparator) /* 471 */ #define Tcl_FSListVolumes \ (tclStubsPtr->tcl_FSListVolumes) /* 472 */ #define Tcl_FSRegister \ (tclStubsPtr->tcl_FSRegister) /* 473 */ #define Tcl_FSUnregister \ (tclStubsPtr->tcl_FSUnregister) /* 474 */ #define Tcl_FSData \ (tclStubsPtr->tcl_FSData) /* 475 */ #define Tcl_FSGetTranslatedStringPath \ (tclStubsPtr->tcl_FSGetTranslatedStringPath) /* 476 */ #define Tcl_FSGetFileSystemForPath \ (tclStubsPtr->tcl_FSGetFileSystemForPath) /* 477 */ #define Tcl_FSGetPathType \ (tclStubsPtr->tcl_FSGetPathType) /* 478 */ #define Tcl_OutputBuffered \ (tclStubsPtr->tcl_OutputBuffered) /* 479 */ #define Tcl_FSMountsChanged \ (tclStubsPtr->tcl_FSMountsChanged) /* 480 */ #define Tcl_EvalTokensStandard \ (tclStubsPtr->tcl_EvalTokensStandard) /* 481 */ #define Tcl_GetTime \ (tclStubsPtr->tcl_GetTime) /* 482 */ #define Tcl_CreateObjTrace \ (tclStubsPtr->tcl_CreateObjTrace) /* 483 */ #define Tcl_GetCommandInfoFromToken \ (tclStubsPtr->tcl_GetCommandInfoFromToken) /* 484 */ #define Tcl_SetCommandInfoFromToken \ (tclStubsPtr->tcl_SetCommandInfoFromToken) /* 485 */ #define Tcl_DbNewWideIntObj \ (tclStubsPtr->tcl_DbNewWideIntObj) /* 486 */ #define Tcl_GetWideIntFromObj \ (tclStubsPtr->tcl_GetWideIntFromObj) /* 487 */ #define Tcl_NewWideIntObj \ (tclStubsPtr->tcl_NewWideIntObj) /* 488 */ #define Tcl_SetWideIntObj \ (tclStubsPtr->tcl_SetWideIntObj) /* 489 */ #define Tcl_AllocStatBuf \ (tclStubsPtr->tcl_AllocStatBuf) /* 490 */ #define Tcl_Seek \ (tclStubsPtr->tcl_Seek) /* 491 */ #define Tcl_Tell \ (tclStubsPtr->tcl_Tell) /* 492 */ #define Tcl_ChannelWideSeekProc \ (tclStubsPtr->tcl_ChannelWideSeekProc) /* 493 */ #define Tcl_DictObjPut \ (tclStubsPtr->tcl_DictObjPut) /* 494 */ #define Tcl_DictObjGet \ (tclStubsPtr->tcl_DictObjGet) /* 495 */ #define Tcl_DictObjRemove \ (tclStubsPtr->tcl_DictObjRemove) /* 496 */ #define Tcl_DictObjSize \ (tclStubsPtr->tcl_DictObjSize) /* 497 */ #define Tcl_DictObjFirst \ (tclStubsPtr->tcl_DictObjFirst) /* 498 */ #define Tcl_DictObjNext \ (tclStubsPtr->tcl_DictObjNext) /* 499 */ #define Tcl_DictObjDone \ (tclStubsPtr->tcl_DictObjDone) /* 500 */ #define Tcl_DictObjPutKeyList \ (tclStubsPtr->tcl_DictObjPutKeyList) /* 501 */ #define Tcl_DictObjRemoveKeyList \ (tclStubsPtr->tcl_DictObjRemoveKeyList) /* 502 */ #define Tcl_NewDictObj \ (tclStubsPtr->tcl_NewDictObj) /* 503 */ #define Tcl_DbNewDictObj \ (tclStubsPtr->tcl_DbNewDictObj) /* 504 */ #define Tcl_RegisterConfig \ (tclStubsPtr->tcl_RegisterConfig) /* 505 */ #define Tcl_CreateNamespace \ (tclStubsPtr->tcl_CreateNamespace) /* 506 */ #define Tcl_DeleteNamespace \ (tclStubsPtr->tcl_DeleteNamespace) /* 507 */ #define Tcl_AppendExportList \ (tclStubsPtr->tcl_AppendExportList) /* 508 */ #define Tcl_Export \ (tclStubsPtr->tcl_Export) /* 509 */ #define Tcl_Import \ (tclStubsPtr->tcl_Import) /* 510 */ #define Tcl_ForgetImport \ (tclStubsPtr->tcl_ForgetImport) /* 511 */ #define Tcl_GetCurrentNamespace \ (tclStubsPtr->tcl_GetCurrentNamespace) /* 512 */ #define Tcl_GetGlobalNamespace \ (tclStubsPtr->tcl_GetGlobalNamespace) /* 513 */ #define Tcl_FindNamespace \ (tclStubsPtr->tcl_FindNamespace) /* 514 */ #define Tcl_FindCommand \ (tclStubsPtr->tcl_FindCommand) /* 515 */ #define Tcl_GetCommandFromObj \ (tclStubsPtr->tcl_GetCommandFromObj) /* 516 */ #define Tcl_GetCommandFullName \ (tclStubsPtr->tcl_GetCommandFullName) /* 517 */ #define Tcl_FSEvalFileEx \ (tclStubsPtr->tcl_FSEvalFileEx) /* 518 */ #define Tcl_SetExitProc \ (tclStubsPtr->tcl_SetExitProc) /* 519 */ #define Tcl_LimitAddHandler \ (tclStubsPtr->tcl_LimitAddHandler) /* 520 */ #define Tcl_LimitRemoveHandler \ (tclStubsPtr->tcl_LimitRemoveHandler) /* 521 */ #define Tcl_LimitReady \ (tclStubsPtr->tcl_LimitReady) /* 522 */ #define Tcl_LimitCheck \ (tclStubsPtr->tcl_LimitCheck) /* 523 */ #define Tcl_LimitExceeded \ (tclStubsPtr->tcl_LimitExceeded) /* 524 */ #define Tcl_LimitSetCommands \ (tclStubsPtr->tcl_LimitSetCommands) /* 525 */ #define Tcl_LimitSetTime \ (tclStubsPtr->tcl_LimitSetTime) /* 526 */ #define Tcl_LimitSetGranularity \ (tclStubsPtr->tcl_LimitSetGranularity) /* 527 */ #define Tcl_LimitTypeEnabled \ (tclStubsPtr->tcl_LimitTypeEnabled) /* 528 */ #define Tcl_LimitTypeExceeded \ (tclStubsPtr->tcl_LimitTypeExceeded) /* 529 */ #define Tcl_LimitTypeSet \ (tclStubsPtr->tcl_LimitTypeSet) /* 530 */ #define Tcl_LimitTypeReset \ (tclStubsPtr->tcl_LimitTypeReset) /* 531 */ #define Tcl_LimitGetCommands \ (tclStubsPtr->tcl_LimitGetCommands) /* 532 */ #define Tcl_LimitGetTime \ (tclStubsPtr->tcl_LimitGetTime) /* 533 */ #define Tcl_LimitGetGranularity \ (tclStubsPtr->tcl_LimitGetGranularity) /* 534 */ #define Tcl_SaveInterpState \ (tclStubsPtr->tcl_SaveInterpState) /* 535 */ #define Tcl_RestoreInterpState \ (tclStubsPtr->tcl_RestoreInterpState) /* 536 */ #define Tcl_DiscardInterpState \ (tclStubsPtr->tcl_DiscardInterpState) /* 537 */ #define Tcl_SetReturnOptions \ (tclStubsPtr->tcl_SetReturnOptions) /* 538 */ #define Tcl_GetReturnOptions \ (tclStubsPtr->tcl_GetReturnOptions) /* 539 */ #define Tcl_IsEnsemble \ (tclStubsPtr->tcl_IsEnsemble) /* 540 */ #define Tcl_CreateEnsemble \ (tclStubsPtr->tcl_CreateEnsemble) /* 541 */ #define Tcl_FindEnsemble \ (tclStubsPtr->tcl_FindEnsemble) /* 542 */ #define Tcl_SetEnsembleSubcommandList \ (tclStubsPtr->tcl_SetEnsembleSubcommandList) /* 543 */ #define Tcl_SetEnsembleMappingDict \ (tclStubsPtr->tcl_SetEnsembleMappingDict) /* 544 */ #define Tcl_SetEnsembleUnknownHandler \ (tclStubsPtr->tcl_SetEnsembleUnknownHandler) /* 545 */ #define Tcl_SetEnsembleFlags \ (tclStubsPtr->tcl_SetEnsembleFlags) /* 546 */ #define Tcl_GetEnsembleSubcommandList \ (tclStubsPtr->tcl_GetEnsembleSubcommandList) /* 547 */ #define Tcl_GetEnsembleMappingDict \ (tclStubsPtr->tcl_GetEnsembleMappingDict) /* 548 */ #define Tcl_GetEnsembleUnknownHandler \ (tclStubsPtr->tcl_GetEnsembleUnknownHandler) /* 549 */ #define Tcl_GetEnsembleFlags \ (tclStubsPtr->tcl_GetEnsembleFlags) /* 550 */ #define Tcl_GetEnsembleNamespace \ (tclStubsPtr->tcl_GetEnsembleNamespace) /* 551 */ #define Tcl_SetTimeProc \ (tclStubsPtr->tcl_SetTimeProc) /* 552 */ #define Tcl_QueryTimeProc \ (tclStubsPtr->tcl_QueryTimeProc) /* 553 */ #define Tcl_ChannelThreadActionProc \ (tclStubsPtr->tcl_ChannelThreadActionProc) /* 554 */ #define Tcl_NewBignumObj \ (tclStubsPtr->tcl_NewBignumObj) /* 555 */ #define Tcl_DbNewBignumObj \ (tclStubsPtr->tcl_DbNewBignumObj) /* 556 */ #define Tcl_SetBignumObj \ (tclStubsPtr->tcl_SetBignumObj) /* 557 */ #define Tcl_GetBignumFromObj \ (tclStubsPtr->tcl_GetBignumFromObj) /* 558 */ #define Tcl_TakeBignumFromObj \ (tclStubsPtr->tcl_TakeBignumFromObj) /* 559 */ #define Tcl_TruncateChannel \ (tclStubsPtr->tcl_TruncateChannel) /* 560 */ #define Tcl_ChannelTruncateProc \ (tclStubsPtr->tcl_ChannelTruncateProc) /* 561 */ #define Tcl_SetChannelErrorInterp \ (tclStubsPtr->tcl_SetChannelErrorInterp) /* 562 */ #define Tcl_GetChannelErrorInterp \ (tclStubsPtr->tcl_GetChannelErrorInterp) /* 563 */ #define Tcl_SetChannelError \ (tclStubsPtr->tcl_SetChannelError) /* 564 */ #define Tcl_GetChannelError \ (tclStubsPtr->tcl_GetChannelError) /* 565 */ #define Tcl_InitBignumFromDouble \ (tclStubsPtr->tcl_InitBignumFromDouble) /* 566 */ #define Tcl_GetNamespaceUnknownHandler \ (tclStubsPtr->tcl_GetNamespaceUnknownHandler) /* 567 */ #define Tcl_SetNamespaceUnknownHandler \ (tclStubsPtr->tcl_SetNamespaceUnknownHandler) /* 568 */ #define Tcl_GetEncodingFromObj \ (tclStubsPtr->tcl_GetEncodingFromObj) /* 569 */ #define Tcl_GetEncodingSearchPath \ (tclStubsPtr->tcl_GetEncodingSearchPath) /* 570 */ #define Tcl_SetEncodingSearchPath \ (tclStubsPtr->tcl_SetEncodingSearchPath) /* 571 */ #define Tcl_GetEncodingNameFromEnvironment \ (tclStubsPtr->tcl_GetEncodingNameFromEnvironment) /* 572 */ #define Tcl_PkgRequireProc \ (tclStubsPtr->tcl_PkgRequireProc) /* 573 */ #define Tcl_AppendObjToErrorInfo \ (tclStubsPtr->tcl_AppendObjToErrorInfo) /* 574 */ #define Tcl_AppendLimitedToObj \ (tclStubsPtr->tcl_AppendLimitedToObj) /* 575 */ #define Tcl_Format \ (tclStubsPtr->tcl_Format) /* 576 */ #define Tcl_AppendFormatToObj \ (tclStubsPtr->tcl_AppendFormatToObj) /* 577 */ #define Tcl_ObjPrintf \ (tclStubsPtr->tcl_ObjPrintf) /* 578 */ #define Tcl_AppendPrintfToObj \ (tclStubsPtr->tcl_AppendPrintfToObj) /* 579 */ #define Tcl_CancelEval \ (tclStubsPtr->tcl_CancelEval) /* 580 */ #define Tcl_Canceled \ (tclStubsPtr->tcl_Canceled) /* 581 */ #define Tcl_CreatePipe \ (tclStubsPtr->tcl_CreatePipe) /* 582 */ #define Tcl_NRCreateCommand \ (tclStubsPtr->tcl_NRCreateCommand) /* 583 */ #define Tcl_NREvalObj \ (tclStubsPtr->tcl_NREvalObj) /* 584 */ #define Tcl_NREvalObjv \ (tclStubsPtr->tcl_NREvalObjv) /* 585 */ #define Tcl_NRCmdSwap \ (tclStubsPtr->tcl_NRCmdSwap) /* 586 */ #define Tcl_NRAddCallback \ (tclStubsPtr->tcl_NRAddCallback) /* 587 */ #define Tcl_NRCallObjProc \ (tclStubsPtr->tcl_NRCallObjProc) /* 588 */ #define Tcl_GetFSDeviceFromStat \ (tclStubsPtr->tcl_GetFSDeviceFromStat) /* 589 */ #define Tcl_GetFSInodeFromStat \ (tclStubsPtr->tcl_GetFSInodeFromStat) /* 590 */ #define Tcl_GetModeFromStat \ (tclStubsPtr->tcl_GetModeFromStat) /* 591 */ #define Tcl_GetLinkCountFromStat \ (tclStubsPtr->tcl_GetLinkCountFromStat) /* 592 */ #define Tcl_GetUserIdFromStat \ (tclStubsPtr->tcl_GetUserIdFromStat) /* 593 */ #define Tcl_GetGroupIdFromStat \ (tclStubsPtr->tcl_GetGroupIdFromStat) /* 594 */ #define Tcl_GetDeviceTypeFromStat \ (tclStubsPtr->tcl_GetDeviceTypeFromStat) /* 595 */ #define Tcl_GetAccessTimeFromStat \ (tclStubsPtr->tcl_GetAccessTimeFromStat) /* 596 */ #define Tcl_GetModificationTimeFromStat \ (tclStubsPtr->tcl_GetModificationTimeFromStat) /* 597 */ #define Tcl_GetChangeTimeFromStat \ (tclStubsPtr->tcl_GetChangeTimeFromStat) /* 598 */ #define Tcl_GetSizeFromStat \ (tclStubsPtr->tcl_GetSizeFromStat) /* 599 */ #define Tcl_GetBlocksFromStat \ (tclStubsPtr->tcl_GetBlocksFromStat) /* 600 */ #define Tcl_GetBlockSizeFromStat \ (tclStubsPtr->tcl_GetBlockSizeFromStat) /* 601 */ #define Tcl_SetEnsembleParameterList \ (tclStubsPtr->tcl_SetEnsembleParameterList) /* 602 */ #define Tcl_GetEnsembleParameterList \ (tclStubsPtr->tcl_GetEnsembleParameterList) /* 603 */ #define Tcl_ParseArgsObjv \ (tclStubsPtr->tcl_ParseArgsObjv) /* 604 */ #define Tcl_GetErrorLine \ (tclStubsPtr->tcl_GetErrorLine) /* 605 */ #define Tcl_SetErrorLine \ (tclStubsPtr->tcl_SetErrorLine) /* 606 */ #define Tcl_TransferResult \ (tclStubsPtr->tcl_TransferResult) /* 607 */ #define Tcl_InterpActive \ (tclStubsPtr->tcl_InterpActive) /* 608 */ #define Tcl_BackgroundException \ (tclStubsPtr->tcl_BackgroundException) /* 609 */ #define Tcl_ZlibDeflate \ (tclStubsPtr->tcl_ZlibDeflate) /* 610 */ #define Tcl_ZlibInflate \ (tclStubsPtr->tcl_ZlibInflate) /* 611 */ #define Tcl_ZlibCRC32 \ (tclStubsPtr->tcl_ZlibCRC32) /* 612 */ #define Tcl_ZlibAdler32 \ (tclStubsPtr->tcl_ZlibAdler32) /* 613 */ #define Tcl_ZlibStreamInit \ (tclStubsPtr->tcl_ZlibStreamInit) /* 614 */ #define Tcl_ZlibStreamGetCommandName \ (tclStubsPtr->tcl_ZlibStreamGetCommandName) /* 615 */ #define Tcl_ZlibStreamEof \ (tclStubsPtr->tcl_ZlibStreamEof) /* 616 */ #define Tcl_ZlibStreamChecksum \ (tclStubsPtr->tcl_ZlibStreamChecksum) /* 617 */ #define Tcl_ZlibStreamPut \ (tclStubsPtr->tcl_ZlibStreamPut) /* 618 */ #define Tcl_ZlibStreamGet \ (tclStubsPtr->tcl_ZlibStreamGet) /* 619 */ #define Tcl_ZlibStreamClose \ (tclStubsPtr->tcl_ZlibStreamClose) /* 620 */ #define Tcl_ZlibStreamReset \ (tclStubsPtr->tcl_ZlibStreamReset) /* 621 */ #define Tcl_SetStartupScript \ (tclStubsPtr->tcl_SetStartupScript) /* 622 */ #define Tcl_GetStartupScript \ (tclStubsPtr->tcl_GetStartupScript) /* 623 */ #define Tcl_CloseEx \ (tclStubsPtr->tcl_CloseEx) /* 624 */ #define Tcl_NRExprObj \ (tclStubsPtr->tcl_NRExprObj) /* 625 */ #define Tcl_NRSubstObj \ (tclStubsPtr->tcl_NRSubstObj) /* 626 */ #define Tcl_LoadFile \ (tclStubsPtr->tcl_LoadFile) /* 627 */ #define Tcl_FindSymbol \ (tclStubsPtr->tcl_FindSymbol) /* 628 */ #define Tcl_FSUnloadFile \ (tclStubsPtr->tcl_FSUnloadFile) /* 629 */ #define Tcl_ZlibStreamSetCompressionDictionary \ (tclStubsPtr->tcl_ZlibStreamSetCompressionDictionary) /* 630 */ #endif /* defined(USE_TCL_STUBS) */ /* !END!: Do not edit above this line. */ #if defined(USE_TCL_STUBS) # undef Tcl_CreateInterp # undef Tcl_FindExecutable # undef Tcl_GetStringResult # undef Tcl_Init # undef Tcl_SetPanicProc # undef Tcl_SetVar # undef Tcl_ObjSetVar2 # undef Tcl_StaticPackage # undef TclFSGetNativePath # define Tcl_CreateInterp() (tclStubsPtr->tcl_CreateInterp()) # define Tcl_GetStringResult(interp) (tclStubsPtr->tcl_GetStringResult(interp)) # define Tcl_Init(interp) (tclStubsPtr->tcl_Init(interp)) # define Tcl_SetPanicProc(proc) (tclStubsPtr->tcl_SetPanicProc(proc)) # define Tcl_SetVar(interp, varName, newValue, flags) \ (tclStubsPtr->tcl_SetVar(interp, varName, newValue, flags)) # define Tcl_ObjSetVar2(interp, part1, part2, newValue, flags) \ (tclStubsPtr->tcl_ObjSetVar2(interp, part1, part2, newValue, flags)) #endif #if defined(_WIN32) && defined(UNICODE) # define Tcl_FindExecutable(arg) ((Tcl_FindExecutable)((const char *)(arg))) # define Tcl_MainEx Tcl_MainExW EXTERN void Tcl_MainExW(int argc, wchar_t **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); #endif #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT #undef Tcl_SeekOld #undef Tcl_TellOld #undef Tcl_PkgPresent #define Tcl_PkgPresent(interp, name, version, exact) \ Tcl_PkgPresentEx(interp, name, version, exact, NULL) #undef Tcl_PkgProvide #define Tcl_PkgProvide(interp, name, version) \ Tcl_PkgProvideEx(interp, name, version, NULL) #undef Tcl_PkgRequire #define Tcl_PkgRequire(interp, name, version, exact) \ Tcl_PkgRequireEx(interp, name, version, exact, NULL) #undef Tcl_GetIndexFromObj #define Tcl_GetIndexFromObj(interp, objPtr, tablePtr, msg, flags, indexPtr) \ Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, \ sizeof(char *), msg, flags, indexPtr) #undef Tcl_NewBooleanObj #define Tcl_NewBooleanObj(boolValue) \ Tcl_NewIntObj((boolValue)!=0) #undef Tcl_DbNewBooleanObj #define Tcl_DbNewBooleanObj(boolValue, file, line) \ Tcl_DbNewLongObj((boolValue)!=0, file, line) #undef Tcl_SetBooleanObj #define Tcl_SetBooleanObj(objPtr, boolValue) \ Tcl_SetIntObj((objPtr), (boolValue)!=0) #undef Tcl_SetVar #define Tcl_SetVar(interp, varName, newValue, flags) \ Tcl_SetVar2(interp, varName, NULL, newValue, flags) #undef Tcl_UnsetVar #define Tcl_UnsetVar(interp, varName, flags) \ Tcl_UnsetVar2(interp, varName, NULL, flags) #undef Tcl_GetVar #define Tcl_GetVar(interp, varName, flags) \ Tcl_GetVar2(interp, varName, NULL, flags) #undef Tcl_TraceVar #define Tcl_TraceVar(interp, varName, flags, proc, clientData) \ Tcl_TraceVar2(interp, varName, NULL, flags, proc, clientData) #undef Tcl_UntraceVar #define Tcl_UntraceVar(interp, varName, flags, proc, clientData) \ Tcl_UntraceVar2(interp, varName, NULL, flags, proc, clientData) #undef Tcl_VarTraceInfo #define Tcl_VarTraceInfo(interp, varName, flags, proc, prevClientData) \ Tcl_VarTraceInfo2(interp, varName, NULL, flags, proc, prevClientData) #undef Tcl_UpVar #define Tcl_UpVar(interp, frameName, varName, localName, flags) \ Tcl_UpVar2(interp, frameName, varName, NULL, localName, flags) #if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) # if defined(__CYGWIN__) && defined(TCL_WIDE_INT_IS_LONG) /* On Cygwin64, long is 64-bit while on Win64 long is 32-bit. Therefore * we have to make sure that all stub entries on Cygwin64 follow the * Win64 signature. Cygwin64 stubbed extensions cannot use those stub * entries any more, they should use the 64-bit alternatives where * possible. Tcl 9 must find a better solution, but that cannot be done * without introducing a binary incompatibility. */ # undef Tcl_DbNewLongObj # undef Tcl_GetLongFromObj # undef Tcl_NewLongObj # undef Tcl_SetLongObj # undef Tcl_ExprLong # undef Tcl_ExprLongObj # undef Tcl_UniCharNcmp # undef Tcl_UtfNcmp # undef Tcl_UtfNcasecmp # undef Tcl_UniCharNcasecmp # define Tcl_DbNewLongObj ((Tcl_Obj*(*)(long,const char*,int))Tcl_DbNewWideIntObj) # define Tcl_GetLongFromObj ((int(*)(Tcl_Interp*,Tcl_Obj*,long*))Tcl_GetWideIntFromObj) # define Tcl_NewLongObj ((Tcl_Obj*(*)(long))Tcl_NewWideIntObj) # define Tcl_SetLongObj ((void(*)(Tcl_Obj*,long))Tcl_SetWideIntObj) # define Tcl_ExprLong TclExprLong static inline int TclExprLong(Tcl_Interp *interp, const char *string, long *ptr){ int intValue; int result = tclStubsPtr->tcl_ExprLong(interp, string, (long *)&intValue); if (result == TCL_OK) *ptr = (long)intValue; return result; } # define Tcl_ExprLongObj TclExprLongObj static inline int TclExprLongObj(Tcl_Interp *interp, Tcl_Obj *obj, long *ptr){ int intValue; int result = tclStubsPtr->tcl_ExprLongObj(interp, obj, (long *)&intValue); if (result == TCL_OK) *ptr = (long)intValue; return result; } # define Tcl_UniCharNcmp(ucs,uct,n) \ ((int(*)(const Tcl_UniChar*,const Tcl_UniChar*,unsigned int))tclStubsPtr->tcl_UniCharNcmp)(ucs,uct,(unsigned int)(n)) # define Tcl_UtfNcmp(s1,s2,n) \ ((int(*)(const char*,const char*,unsigned int))tclStubsPtr->tcl_UtfNcmp)(s1,s2,(unsigned int)(n)) # define Tcl_UtfNcasecmp(s1,s2,n) \ ((int(*)(const char*,const char*,unsigned int))tclStubsPtr->tcl_UtfNcasecmp)(s1,s2,(unsigned int)(n)) # define Tcl_UniCharNcasecmp(ucs,uct,n) \ ((int(*)(const Tcl_UniChar*,const Tcl_UniChar*,unsigned int))tclStubsPtr->tcl_UniCharNcasecmp)(ucs,uct,(unsigned int)(n)) # endif #endif /* * Deprecated Tcl procedures: */ #undef Tcl_EvalObj #define Tcl_EvalObj(interp,objPtr) \ Tcl_EvalObjEx((interp),(objPtr),0) #undef Tcl_GlobalEvalObj #define Tcl_GlobalEvalObj(interp,objPtr) \ Tcl_EvalObjEx((interp),(objPtr),TCL_EVAL_GLOBAL) #endif /* _TCLDECLS */ tcl8.6.5/generic/tclOO.decls0000644000175000017500000001503312663660065015241 0ustar sergeisergei# tclOO.decls -- # # This file contains the declarations for all supported public functions # that are exported by the TclOO package that is embedded within the Tcl # library via the stubs table. This file is used to generate the # tclOODecls.h, tclOOIntDecls.h and tclOOStubInit.c files. # # Copyright (c) 2008-2013 by Donal K. Fellows. # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. library tclOO ###################################################################### # Public API, exposed for general users of TclOO. # interface tclOO hooks tclOOInt scspec TCLAPI declare 0 { Tcl_Object Tcl_CopyObjectInstance(Tcl_Interp *interp, Tcl_Object sourceObject, const char *targetName, const char *targetNamespaceName) } declare 1 { Tcl_Object Tcl_GetClassAsObject(Tcl_Class clazz) } declare 2 { Tcl_Class Tcl_GetObjectAsClass(Tcl_Object object) } declare 3 { Tcl_Command Tcl_GetObjectCommand(Tcl_Object object) } declare 4 { Tcl_Object Tcl_GetObjectFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr) } declare 5 { Tcl_Namespace *Tcl_GetObjectNamespace(Tcl_Object object) } declare 6 { Tcl_Class Tcl_MethodDeclarerClass(Tcl_Method method) } declare 7 { Tcl_Object Tcl_MethodDeclarerObject(Tcl_Method method) } declare 8 { int Tcl_MethodIsPublic(Tcl_Method method) } declare 9 { int Tcl_MethodIsType(Tcl_Method method, const Tcl_MethodType *typePtr, ClientData *clientDataPtr) } declare 10 { Tcl_Obj *Tcl_MethodName(Tcl_Method method) } declare 11 { Tcl_Method Tcl_NewInstanceMethod(Tcl_Interp *interp, Tcl_Object object, Tcl_Obj *nameObj, int isPublic, const Tcl_MethodType *typePtr, ClientData clientData) } declare 12 { Tcl_Method Tcl_NewMethod(Tcl_Interp *interp, Tcl_Class cls, Tcl_Obj *nameObj, int isPublic, const Tcl_MethodType *typePtr, ClientData clientData) } declare 13 { Tcl_Object Tcl_NewObjectInstance(Tcl_Interp *interp, Tcl_Class cls, const char *nameStr, const char *nsNameStr, int objc, Tcl_Obj *const *objv, int skip) } declare 14 { int Tcl_ObjectDeleted(Tcl_Object object) } declare 15 { int Tcl_ObjectContextIsFiltering(Tcl_ObjectContext context) } declare 16 { Tcl_Method Tcl_ObjectContextMethod(Tcl_ObjectContext context) } declare 17 { Tcl_Object Tcl_ObjectContextObject(Tcl_ObjectContext context) } declare 18 { int Tcl_ObjectContextSkippedArgs(Tcl_ObjectContext context) } declare 19 { ClientData Tcl_ClassGetMetadata(Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr) } declare 20 { void Tcl_ClassSetMetadata(Tcl_Class clazz, const Tcl_ObjectMetadataType *typePtr, ClientData metadata) } declare 21 { ClientData Tcl_ObjectGetMetadata(Tcl_Object object, const Tcl_ObjectMetadataType *typePtr) } declare 22 { void Tcl_ObjectSetMetadata(Tcl_Object object, const Tcl_ObjectMetadataType *typePtr, ClientData metadata) } declare 23 { int Tcl_ObjectContextInvokeNext(Tcl_Interp *interp, Tcl_ObjectContext context, int objc, Tcl_Obj *const *objv, int skip) } declare 24 { Tcl_ObjectMapMethodNameProc *Tcl_ObjectGetMethodNameMapper( Tcl_Object object) } declare 25 { void Tcl_ObjectSetMethodNameMapper(Tcl_Object object, Tcl_ObjectMapMethodNameProc *mapMethodNameProc) } declare 26 { void Tcl_ClassSetConstructor(Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method) } declare 27 { void Tcl_ClassSetDestructor(Tcl_Interp *interp, Tcl_Class clazz, Tcl_Method method) } declare 28 { Tcl_Obj *Tcl_GetObjectName(Tcl_Interp *interp, Tcl_Object object) } ###################################################################### # Private API, exposed to support advanced OO systems that plug in on top of # TclOO; not intended for general use and does not have any commitment to # long-term support. # interface tclOOInt declare 0 { Tcl_Object TclOOGetDefineCmdContext(Tcl_Interp *interp) } declare 1 { Tcl_Method TclOOMakeProcInstanceMethod(Tcl_Interp *interp, Object *oPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, const Tcl_MethodType *typePtr, ClientData clientData, Proc **procPtrPtr) } declare 2 { Tcl_Method TclOOMakeProcMethod(Tcl_Interp *interp, Class *clsPtr, int flags, Tcl_Obj *nameObj, const char *namePtr, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, const Tcl_MethodType *typePtr, ClientData clientData, Proc **procPtrPtr) } declare 3 { Method *TclOONewProcInstanceMethod(Tcl_Interp *interp, Object *oPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr) } declare 4 { Method *TclOONewProcMethod(Tcl_Interp *interp, Class *clsPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ProcedureMethod **pmPtrPtr) } declare 5 { int TclOOObjectCmdCore(Object *oPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv, int publicOnly, Class *startCls) } declare 6 { int TclOOIsReachable(Class *targetPtr, Class *startPtr) } declare 7 { Method *TclOONewForwardMethod(Tcl_Interp *interp, Class *clsPtr, int isPublic, Tcl_Obj *nameObj, Tcl_Obj *prefixObj) } declare 8 { Method *TclOONewForwardInstanceMethod(Tcl_Interp *interp, Object *oPtr, int isPublic, Tcl_Obj *nameObj, Tcl_Obj *prefixObj) } declare 9 { Tcl_Method TclOONewProcInstanceMethodEx(Tcl_Interp *interp, Tcl_Object oPtr, TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, ClientData clientData, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags, void **internalTokenPtr) } declare 10 { Tcl_Method TclOONewProcMethodEx(Tcl_Interp *interp, Tcl_Class clsPtr, TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr, ProcErrorProc *errProc, ClientData clientData, Tcl_Obj *nameObj, Tcl_Obj *argsObj, Tcl_Obj *bodyObj, int flags, void **internalTokenPtr) } declare 11 { int TclOOInvokeObject(Tcl_Interp *interp, Tcl_Object object, Tcl_Class startCls, int publicPrivate, int objc, Tcl_Obj *const *objv) } declare 12 { void TclOOObjectSetFilters(Object *oPtr, int numFilters, Tcl_Obj *const *filters) } declare 13 { void TclOOClassSetFilters(Tcl_Interp *interp, Class *classPtr, int numFilters, Tcl_Obj *const *filters) } declare 14 { void TclOOObjectSetMixins(Object *oPtr, int numMixins, Class *const *mixins) } declare 15 { void TclOOClassSetMixins(Tcl_Interp *interp, Class *classPtr, int numMixins, Class *const *mixins) } return # Local Variables: # mode: tcl # End: tcl8.6.5/generic/tclIO.h0000644000175000017500000002702512663660065014374 0ustar sergeisergei/* * tclIO.h -- * * This file provides the generic portions (those that are the same on * all platforms and for all channel types) of Tcl's IO facilities. * * Copyright (c) 1998-2000 Ajuba Solutions * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ /* * Make sure that both EAGAIN and EWOULDBLOCK are defined. This does not * compile on systems where neither is defined. We want both defined so that * we can test safely for both. In the code we still have to test for both * because there may be systems on which both are defined and have different * values. */ #if ((!defined(EWOULDBLOCK)) && (defined(EAGAIN))) # define EWOULDBLOCK EAGAIN #endif #if ((!defined(EAGAIN)) && (defined(EWOULDBLOCK))) # define EAGAIN EWOULDBLOCK #endif #if ((!defined(EAGAIN)) && (!defined(EWOULDBLOCK))) #error one of EWOULDBLOCK or EAGAIN must be defined #endif /* * struct ChannelBuffer: * * Buffers data being sent to or from a channel. */ typedef struct ChannelBuffer { int refCount; /* Current uses count */ int nextAdded; /* The next position into which a character * will be put in the buffer. */ int nextRemoved; /* Position of next byte to be removed from * the buffer. */ int bufLength; /* How big is the buffer? */ struct ChannelBuffer *nextPtr; /* Next buffer in chain. */ char buf[1]; /* Placeholder for real buffer. The real * buffer occuppies this space + bufSize-1 * bytes. This must be the last field in the * structure. */ } ChannelBuffer; #define CHANNELBUFFER_HEADER_SIZE TclOffset(ChannelBuffer, buf) /* * How much extra space to allocate in buffer to hold bytes from previous * buffer (when converting to UTF-8) or to hold bytes that will go to next * buffer (when converting from UTF-8). */ #define BUFFER_PADDING 16 /* * The following defines the *default* buffer size for channels. */ #define CHANNELBUFFER_DEFAULT_SIZE (1024 * 4) /* * The following structure describes the information saved from a call to * "fileevent". This is used later when the event being waited for to invoke * the saved script in the interpreter designed in this record. */ typedef struct EventScriptRecord { struct Channel *chanPtr; /* The channel for which this script is * registered. This is used only when an error * occurs during evaluation of the script, to * delete the handler. */ Tcl_Obj *scriptPtr; /* Script to invoke. */ Tcl_Interp *interp; /* In what interpreter to invoke script? */ int mask; /* Events must overlap current mask for the * stored script to be invoked. */ struct EventScriptRecord *nextPtr; /* Next in chain of records. */ } EventScriptRecord; /* * struct Channel: * * One of these structures is allocated for each open channel. It contains * data specific to the channel but which belongs to the generic part of the * Tcl channel mechanism, and it points at an instance specific (and type * specific) instance data, and at a channel type structure. */ typedef struct Channel { struct ChannelState *state; /* Split out state information */ ClientData instanceData; /* Instance-specific data provided by creator * of channel. */ const Tcl_ChannelType *typePtr; /* Pointer to channel type structure. */ struct Channel *downChanPtr;/* Refers to channel this one was stacked * upon. This reference is NULL for normal * channels. See Tcl_StackChannel. */ struct Channel *upChanPtr; /* Refers to the channel above stacked this * one. NULL for the top most channel. */ /* * Intermediate buffers to hold pre-read data for consumption by a newly * stacked transformation. See 'Tcl_StackChannel'. */ ChannelBuffer *inQueueHead; /* Points at first buffer in input queue. */ ChannelBuffer *inQueueTail; /* Points at last buffer in input queue. */ int refCount; } Channel; /* * struct ChannelState: * * One of these structures is allocated for each open channel. It contains * data specific to the channel but which belongs to the generic part of the * Tcl channel mechanism, and it points at an instance specific (and type * specific) instance data, and at a channel type structure. */ typedef struct ChannelState { char *channelName; /* The name of the channel instance in Tcl * commands. Storage is owned by the generic * IO code, is dynamically allocated. */ int flags; /* ORed combination of the flags defined * below. */ Tcl_Encoding encoding; /* Encoding to apply when reading or writing * data on this channel. NULL means no * encoding is applied to data. */ Tcl_EncodingState inputEncodingState; /* Current encoding state, used when * converting input data bytes to UTF-8. */ int inputEncodingFlags; /* Encoding flags to pass to conversion * routine when converting input data bytes to * UTF-8. May be TCL_ENCODING_START before * converting first byte and TCL_ENCODING_END * when EOF is seen. */ Tcl_EncodingState outputEncodingState; /* Current encoding state, used when * converting UTF-8 to output data bytes. */ int outputEncodingFlags; /* Encoding flags to pass to conversion * routine when converting UTF-8 to output * data bytes. May be TCL_ENCODING_START * before converting first byte and * TCL_ENCODING_END when EOF is seen. */ TclEolTranslation inputTranslation; /* What translation to apply for end of line * sequences on input? */ TclEolTranslation outputTranslation; /* What translation to use for generating end * of line sequences in output? */ int inEofChar; /* If nonzero, use this as a signal of EOF on * input. */ int outEofChar; /* If nonzero, append this to the channel when * it is closed if it is open for writing. */ int unreportedError; /* Non-zero if an error report was deferred * because it happened in the background. The * value is the POSIX error code. */ int refCount; /* How many interpreters hold references to * this IO channel? */ struct CloseCallback *closeCbPtr; /* Callbacks registered to be called when the * channel is closed. */ char *outputStage; /* Temporary staging buffer used when * translating EOL before converting from * UTF-8 to external form. */ ChannelBuffer *curOutPtr; /* Current output buffer being filled. */ ChannelBuffer *outQueueHead;/* Points at first buffer in output queue. */ ChannelBuffer *outQueueTail;/* Points at last buffer in output queue. */ ChannelBuffer *saveInBufPtr;/* Buffer saved for input queue - eliminates * need to allocate a new buffer for "gets" * that crosses buffer boundaries. */ ChannelBuffer *inQueueHead; /* Points at first buffer in input queue. */ ChannelBuffer *inQueueTail; /* Points at last buffer in input queue. */ struct ChannelHandler *chPtr;/* List of channel handlers registered for * this channel. */ int interestMask; /* Mask of all events this channel has * handlers for. */ EventScriptRecord *scriptRecordPtr; /* Chain of all scripts registered for event * handlers ("fileevent") on this channel. */ int bufSize; /* What size buffers to allocate? */ Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */ struct CopyState *csPtrR; /* State of background copy for which channel * is input, or NULL. */ struct CopyState *csPtrW; /* State of background copy for which channel * is output, or NULL. */ Channel *topChanPtr; /* Refers to topmost channel in a stack. Never * NULL. */ Channel *bottomChanPtr; /* Refers to bottommost channel in a stack. * This channel can be relied on to live as * long as the channel state. Never NULL. */ struct ChannelState *nextCSPtr; /* Next in list of channels currently open. */ Tcl_ThreadId managingThread;/* TIP #10: Id of the thread managing this * stack of channels. */ /* * TIP #219 ... Info for the I/O system ... * Error message set by channel drivers, for the propagation of arbitrary * Tcl errors. This information, if present (chanMsg not NULL), takes * precedence over a posix error code returned by a channel operation. */ Tcl_Obj* chanMsg; Tcl_Obj* unreportedMsg; /* Non-NULL if an error report was deferred * because it happened in the background. The * value is the chanMg, if any. #219's * companion to 'unreportedError'. */ } ChannelState; /* * Values for the flags field in Channel. Any ORed combination of the * following flags can be stored in the field. These flags record various * options and state bits about the channel. In addition to the flags below, * the channel can also have TCL_READABLE (1<<1) and TCL_WRITABLE (1<<2) set. */ #define CHANNEL_NONBLOCKING (1<<3) /* Channel is currently in nonblocking * mode. */ #define CHANNEL_LINEBUFFERED (1<<4) /* Output to the channel must be * flushed after every newline. */ #define CHANNEL_UNBUFFERED (1<<5) /* Output to the channel must always * be flushed immediately. */ #define BG_FLUSH_SCHEDULED (1<<7) /* A background flush of the queued * output buffers has been * scheduled. */ #define CHANNEL_CLOSED (1<<8) /* Channel has been closed. No further * Tcl-level IO on the channel is * allowed. */ #define CHANNEL_EOF (1<<9) /* EOF occurred on this channel. This * bit is cleared before every input * operation. */ #define CHANNEL_STICKY_EOF (1<<10) /* EOF occurred on this channel * because we saw the input * eofChar. This bit prevents clearing * of the EOF bit before every input * operation. */ #define CHANNEL_BLOCKED (1<<11) /* EWOULDBLOCK or EAGAIN occurred on * this channel. This bit is cleared * before every input or output * operation. */ #define INPUT_SAW_CR (1<<12) /* Channel is in CRLF eol input * translation mode and the last byte * seen was a "\r". */ #define CHANNEL_DEAD (1<<13) /* The channel has been closed by the * exit handler (on exit) but not * deallocated. When any IO operation * sees this flag on a channel, it * does not call driver level * functions to avoid referring to * deallocated data. */ #define CHANNEL_NEED_MORE_DATA (1<<14) /* The last input operation failed * because there was not enough data * to complete the operation. This * flag is set when gets fails to get * a complete line or when read fails * to get a complete character. When * set, file events will not be * delivered for buffered data until * the state of the channel * changes. */ #define CHANNEL_RAW_MODE (1<<16) /* When set, notes that the Raw API is * being used. */ #define CHANNEL_INCLOSE (1<<19) /* Channel is currently being closed. * Its structures are still live and * usable, but it may not be closed * again from within the close * handler. */ #define CHANNEL_TAINTED (1<<20) /* Channel stack structure has changed. * Used by Channel Tcl_Obj type to * determine if we have to revalidate * the channel. */ #define CHANNEL_CLOSEDWRITE (1<<21) /* Channel write side has been closed. * No further Tcl-level write IO on * the channel is allowed. */ /* * The length of time to wait between synthetic timer events. Must be zero or * bad things tend to happen. */ #define SYNTHETIC_EVENT_TIME 0 /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclIndexObj.c0000644000175000017500000012252712663660065015565 0ustar sergeisergei/* * tclIndexObj.c -- * * This file implements objects of type "index". This object type is used * to lookup a keyword in a table of valid values and cache the index of * the matching entry. Also provides table-based argv/argc processing. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1997 Sun Microsystems, Inc. * Copyright (c) 2006 Sam Bromley. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Prototypes for functions defined later in this file: */ static int GetIndexFromObjList(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj *tableObjPtr, const char *msg, int flags, int *indexPtr); static int SetIndexFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void UpdateStringOfIndex(Tcl_Obj *objPtr); static void DupIndex(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr); static void FreeIndex(Tcl_Obj *objPtr); static int PrefixAllObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int PrefixLongestObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int PrefixMatchObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void PrintUsage(Tcl_Interp *interp, const Tcl_ArgvInfo *argTable); /* * The structure below defines the index Tcl object type by means of functions * that can be invoked by generic object code. */ static const Tcl_ObjType indexType = { "index", /* name */ FreeIndex, /* freeIntRepProc */ DupIndex, /* dupIntRepProc */ UpdateStringOfIndex, /* updateStringProc */ SetIndexFromAny /* setFromAnyProc */ }; /* * The definition of the internal representation of the "index" object; The * internalRep.twoPtrValue.ptr1 field of an object of "index" type will be a * pointer to one of these structures. * * Keep this structure declaration in sync with tclTestObj.c */ typedef struct { void *tablePtr; /* Pointer to the table of strings */ int offset; /* Offset between table entries */ int index; /* Selected index into table. */ } IndexRep; /* * The following macros greatly simplify moving through a table... */ #define STRING_AT(table, offset) \ (*((const char *const *)(((char *)(table)) + (offset)))) #define NEXT_ENTRY(table, offset) \ (&(STRING_AT(table, offset))) #define EXPAND_OF(indexRep) \ STRING_AT((indexRep)->tablePtr, (indexRep)->offset*(indexRep)->index) /* *---------------------------------------------------------------------- * * Tcl_GetIndexFromObj -- * * This function looks up an object's value in a table of strings and * returns the index of the matching string, if any. * * Results: * If the value of objPtr is identical to or a unique abbreviation for * one of the entries in tablePtr, then the return value is TCL_OK and the * index of the matching entry is stored at *indexPtr. If there isn't a * proper match, then TCL_ERROR is returned and an error message is left * in interp's result (unless interp is NULL). The msg argument is used * in the error message; for example, if msg has the value "option" then * the error message will say something flag 'bad option "foo": must be * ...' * * Side effects: * The result of the lookup is cached as the internal rep of objPtr, so * that repeated lookups can be done quickly. * *---------------------------------------------------------------------- */ #undef Tcl_GetIndexFromObj int Tcl_GetIndexFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr, /* Object containing the string to lookup. */ const char *const*tablePtr, /* Array of strings to compare against the * value of objPtr; last entry must be NULL * and there must not be duplicate entries. */ const char *msg, /* Identifying word to use in error * messages. */ int flags, /* 0 or TCL_EXACT */ int *indexPtr) /* Place to store resulting integer index. */ { /* * See if there is a valid cached result from a previous lookup (doing the * check here saves the overhead of calling Tcl_GetIndexFromObjStruct in * the common case where the result is cached). */ if (objPtr->typePtr == &indexType) { IndexRep *indexRep = objPtr->internalRep.twoPtrValue.ptr1; /* * Here's hoping we don't get hit by unfortunate packing constraints * on odd platforms like a Cray PVP... */ if (indexRep->tablePtr == (void *) tablePtr && indexRep->offset == sizeof(char *)) { *indexPtr = indexRep->index; return TCL_OK; } } return Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, sizeof(char *), msg, flags, indexPtr); } /* *---------------------------------------------------------------------- * * GetIndexFromObjList -- * * This procedure looks up an object's value in a table of strings and * returns the index of the matching string, if any. * * Results: * If the value of objPtr is identical to or a unique abbreviation for * one of the entries in tableObjPtr, then the return value is TCL_OK and * the index of the matching entry is stored at *indexPtr. If there isn't * a proper match, then TCL_ERROR is returned and an error message is * left in interp's result (unless interp is NULL). The msg argument is * used in the error message; for example, if msg has the value "option" * then the error message will say something flag 'bad option "foo": must * be ...' * * Side effects: * Removes any internal representation that the object might have. (TODO: * find a way to cache the lookup.) * *---------------------------------------------------------------------- */ int GetIndexFromObjList( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr, /* Object containing the string to lookup. */ Tcl_Obj *tableObjPtr, /* List of strings to compare against the * value of objPtr. */ const char *msg, /* Identifying word to use in error * messages. */ int flags, /* 0 or TCL_EXACT */ int *indexPtr) /* Place to store resulting integer index. */ { int objc, result, t; Tcl_Obj **objv; const char **tablePtr; /* * Use Tcl_GetIndexFromObjStruct to do the work to avoid duplicating most * of the code there. This is a bit ineffiecient but simpler. */ result = Tcl_ListObjGetElements(interp, tableObjPtr, &objc, &objv); if (result != TCL_OK) { return result; } /* * Build a string table from the list. */ tablePtr = ckalloc((objc + 1) * sizeof(char *)); for (t = 0; t < objc; t++) { if (objv[t] == objPtr) { /* * An exact match is always chosen, so we can stop here. */ ckfree(tablePtr); *indexPtr = t; return TCL_OK; } tablePtr[t] = Tcl_GetString(objv[t]); } tablePtr[objc] = NULL; result = Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, sizeof(char *), msg, flags, indexPtr); /* * The internal rep must be cleared since tablePtr will go away. */ TclFreeIntRep(objPtr); ckfree(tablePtr); return result; } /* *---------------------------------------------------------------------- * * Tcl_GetIndexFromObjStruct -- * * This function looks up an object's value given a starting string and * an offset for the amount of space between strings. This is useful when * the strings are embedded in some other kind of array. * * Results: * If the value of objPtr is identical to or a unique abbreviation for * one of the entries in tablePtr, then the return value is TCL_OK and * the index of the matching entry is stored at *indexPtr. If there isn't * a proper match, then TCL_ERROR is returned and an error message is * left in interp's result (unless interp is NULL). The msg argument is * used in the error message; for example, if msg has the value "option" * then the error message will say something like 'bad option "foo": must * be ...' * * Side effects: * The result of the lookup is cached as the internal rep of objPtr, so * that repeated lookups can be done quickly. * *---------------------------------------------------------------------- */ int Tcl_GetIndexFromObjStruct( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr, /* Object containing the string to lookup. */ const void *tablePtr, /* The first string in the table. The second * string will be at this address plus the * offset, the third plus the offset again, * etc. The last entry must be NULL and there * must not be duplicate entries. */ int offset, /* The number of bytes between entries */ const char *msg, /* Identifying word to use in error * messages. */ int flags, /* 0 or TCL_EXACT */ int *indexPtr) /* Place to store resulting integer index. */ { int index, idx, numAbbrev; const char *key, *p1; const char *p2; const char *const *entryPtr; Tcl_Obj *resultPtr; IndexRep *indexRep; /* Protect against invalid values, like -1 or 0. */ if (offset < (int)sizeof(char *)) { offset = (int)sizeof(char *); } /* * See if there is a valid cached result from a previous lookup. */ if (objPtr->typePtr == &indexType) { indexRep = objPtr->internalRep.twoPtrValue.ptr1; if (indexRep->tablePtr==tablePtr && indexRep->offset==offset) { *indexPtr = indexRep->index; return TCL_OK; } } /* * Lookup the value of the object in the table. Accept unique * abbreviations unless TCL_EXACT is set in flags. */ key = TclGetString(objPtr); index = -1; numAbbrev = 0; /* * Scan the table looking for one of: * - An exact match (always preferred) * - A single abbreviation (allowed depending on flags) * - Several abbreviations (never allowed, but overridden by exact match) */ for (entryPtr = tablePtr, idx = 0; *entryPtr != NULL; entryPtr = NEXT_ENTRY(entryPtr, offset), idx++) { for (p1 = key, p2 = *entryPtr; *p1 == *p2; p1++, p2++) { if (*p1 == '\0') { index = idx; goto done; } } if (*p1 == '\0') { /* * The value is an abbreviation for this entry. Continue checking * other entries to make sure it's unique. If we get more than one * unique abbreviation, keep searching to see if there is an exact * match, but remember the number of unique abbreviations and * don't allow either. */ numAbbrev++; index = idx; } } /* * Check if we were instructed to disallow abbreviations. */ if ((flags & TCL_EXACT) || (key[0] == '\0') || (numAbbrev != 1)) { goto error; } done: /* * Cache the found representation. Note that we want to avoid allocating a * new internal-rep if at all possible since that is potentially a slow * operation. */ if (objPtr->typePtr == &indexType) { indexRep = objPtr->internalRep.twoPtrValue.ptr1; } else { TclFreeIntRep(objPtr); indexRep = ckalloc(sizeof(IndexRep)); objPtr->internalRep.twoPtrValue.ptr1 = indexRep; objPtr->typePtr = &indexType; } indexRep->tablePtr = (void *) tablePtr; indexRep->offset = offset; indexRep->index = index; *indexPtr = index; return TCL_OK; error: if (interp != NULL) { /* * Produce a fancy error message. */ int count = 0; TclNewObj(resultPtr); entryPtr = tablePtr; while ((*entryPtr != NULL) && !**entryPtr) { entryPtr = NEXT_ENTRY(entryPtr, offset); } Tcl_AppendStringsToObj(resultPtr, (numAbbrev>1 && !(flags & TCL_EXACT) ? "ambiguous " : "bad "), msg, " \"", key, NULL); if (*entryPtr == NULL) { Tcl_AppendStringsToObj(resultPtr, "\": no valid options", NULL); } else { Tcl_AppendStringsToObj(resultPtr, "\": must be ", *entryPtr, NULL); entryPtr = NEXT_ENTRY(entryPtr, offset); while (*entryPtr != NULL) { if (*NEXT_ENTRY(entryPtr, offset) == NULL) { Tcl_AppendStringsToObj(resultPtr, (count > 0 ? "," : ""), " or ", *entryPtr, NULL); } else if (**entryPtr) { Tcl_AppendStringsToObj(resultPtr, ", ", *entryPtr, NULL); count++; } entryPtr = NEXT_ENTRY(entryPtr, offset); } } Tcl_SetObjResult(interp, resultPtr); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", msg, key, NULL); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * SetIndexFromAny -- * * This function is called to convert a Tcl object to index internal * form. However, this doesn't make sense (need to have a table of * keywords in order to do the conversion) so the function always * generates an error. * * Results: * The return value is always TCL_ERROR, and an error message is left in * interp's result if interp isn't NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int SetIndexFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr) /* The object to convert. */ { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can't convert value to index except via Tcl_GetIndexFromObj API", -1)); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * UpdateStringOfIndex -- * * This function is called to convert a Tcl object from index internal * form to its string form. No abbreviation is ever generated. * * Results: * None. * * Side effects: * The string representation of the object is updated. * *---------------------------------------------------------------------- */ static void UpdateStringOfIndex( Tcl_Obj *objPtr) { IndexRep *indexRep = objPtr->internalRep.twoPtrValue.ptr1; register char *buf; register unsigned len; register const char *indexStr = EXPAND_OF(indexRep); len = strlen(indexStr); buf = ckalloc(len + 1); memcpy(buf, indexStr, len+1); objPtr->bytes = buf; objPtr->length = len; } /* *---------------------------------------------------------------------- * * DupIndex -- * * This function is called to copy the internal rep of an index Tcl * object from to another object. * * Results: * None. * * Side effects: * The internal representation of the target object is updated and the * type is set. * *---------------------------------------------------------------------- */ static void DupIndex( Tcl_Obj *srcPtr, Tcl_Obj *dupPtr) { IndexRep *srcIndexRep = srcPtr->internalRep.twoPtrValue.ptr1; IndexRep *dupIndexRep = ckalloc(sizeof(IndexRep)); memcpy(dupIndexRep, srcIndexRep, sizeof(IndexRep)); dupPtr->internalRep.twoPtrValue.ptr1 = dupIndexRep; dupPtr->typePtr = &indexType; } /* *---------------------------------------------------------------------- * * FreeIndex -- * * This function is called to delete the internal rep of an index Tcl * object. * * Results: * None. * * Side effects: * The internal representation of the target object is deleted. * *---------------------------------------------------------------------- */ static void FreeIndex( Tcl_Obj *objPtr) { ckfree(objPtr->internalRep.twoPtrValue.ptr1); objPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * TclInitPrefixCmd -- * * This procedure creates the "prefix" Tcl command. See the user * documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ Tcl_Command TclInitPrefixCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap prefixImplMap[] = { {"all", PrefixAllObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"longest", PrefixLongestObjCmd,TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"match", PrefixMatchObjCmd, TclCompileBasicMin2ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; Tcl_Command prefixCmd; prefixCmd = TclMakeEnsemble(interp, "::tcl::prefix", prefixImplMap); Tcl_Export(interp, Tcl_FindNamespace(interp, "::tcl", NULL, 0), "prefix", 0); return prefixCmd; } /*---------------------------------------------------------------------- * * PrefixMatchObjCmd -- * * This function implements the 'prefix match' Tcl command. Refer to the * user documentation for details on what it does. * * Results: * Returns a standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PrefixMatchObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int flags = 0, result, index; int dummyLength, i, errorLength; Tcl_Obj *errorPtr = NULL; const char *message = "option"; Tcl_Obj *tablePtr, *objPtr, *resultPtr; static const char *const matchOptions[] = { "-error", "-exact", "-message", NULL }; enum matchOptions { PRFMATCH_ERROR, PRFMATCH_EXACT, PRFMATCH_MESSAGE }; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? table string"); return TCL_ERROR; } for (i = 1; i < (objc - 2); i++) { if (Tcl_GetIndexFromObj(interp, objv[i], matchOptions, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum matchOptions) index) { case PRFMATCH_EXACT: flags |= TCL_EXACT; break; case PRFMATCH_MESSAGE: if (i > objc-4) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing value for -message", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", NULL); return TCL_ERROR; } i++; message = Tcl_GetString(objv[i]); break; case PRFMATCH_ERROR: if (i > objc-4) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing value for -error", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", NULL); return TCL_ERROR; } i++; result = Tcl_ListObjLength(interp, objv[i], &errorLength); if (result != TCL_OK) { return TCL_ERROR; } if ((errorLength % 2) != 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "error options must have an even number of elements", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL); return TCL_ERROR; } errorPtr = objv[i]; break; } } tablePtr = objv[objc - 2]; objPtr = objv[objc - 1]; /* * Check that table is a valid list first, since we want to handle that * error case regardless of level. */ result = Tcl_ListObjLength(interp, tablePtr, &dummyLength); if (result != TCL_OK) { return result; } result = GetIndexFromObjList(interp, objPtr, tablePtr, message, flags, &index); if (result != TCL_OK) { if (errorPtr != NULL && errorLength == 0) { Tcl_ResetResult(interp); return TCL_OK; } else if (errorPtr == NULL) { return TCL_ERROR; } if (Tcl_IsShared(errorPtr)) { errorPtr = Tcl_DuplicateObj(errorPtr); } Tcl_ListObjAppendElement(interp, errorPtr, Tcl_NewStringObj("-code", 5)); Tcl_ListObjAppendElement(interp, errorPtr, Tcl_NewIntObj(result)); return Tcl_SetReturnOptions(interp, errorPtr); } result = Tcl_ListObjIndex(interp, tablePtr, index, &resultPtr); if (result != TCL_OK) { return result; } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /*---------------------------------------------------------------------- * * PrefixAllObjCmd -- * * This function implements the 'prefix all' Tcl command. Refer to the * user documentation for details on what it does. * * Results: * Returns a standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PrefixAllObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int tableObjc, result, t, length, elemLength; const char *string, *elemString; Tcl_Obj **tableObjv, *resultPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "table string"); return TCL_ERROR; } result = Tcl_ListObjGetElements(interp, objv[1], &tableObjc, &tableObjv); if (result != TCL_OK) { return result; } resultPtr = Tcl_NewListObj(0, NULL); string = Tcl_GetStringFromObj(objv[2], &length); for (t = 0; t < tableObjc; t++) { elemString = Tcl_GetStringFromObj(tableObjv[t], &elemLength); /* * A prefix cannot match if it is longest. */ if (length <= elemLength) { if (TclpUtfNcmp2(elemString, string, length) == 0) { Tcl_ListObjAppendElement(interp, resultPtr, tableObjv[t]); } } } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /*---------------------------------------------------------------------- * * PrefixLongestObjCmd -- * * This function implements the 'prefix longest' Tcl command. Refer to * the user documentation for details on what it does. * * Results: * Returns a standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PrefixLongestObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int tableObjc, result, i, t, length, elemLength, resultLength; const char *string, *elemString, *resultString; Tcl_Obj **tableObjv; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "table string"); return TCL_ERROR; } result = Tcl_ListObjGetElements(interp, objv[1], &tableObjc, &tableObjv); if (result != TCL_OK) { return result; } string = Tcl_GetStringFromObj(objv[2], &length); resultString = NULL; resultLength = 0; for (t = 0; t < tableObjc; t++) { elemString = Tcl_GetStringFromObj(tableObjv[t], &elemLength); /* * First check if the prefix string matches the element. A prefix * cannot match if it is longest. */ if ((length > elemLength) || TclpUtfNcmp2(elemString, string, length) != 0) { continue; } if (resultString == NULL) { /* * If this is the first match, the longest common substring this * far is the complete string. The result is part of this string * so we only need to adjust the length later. */ resultString = elemString; resultLength = elemLength; } else { /* * Longest common substring cannot be longer than shortest string. */ if (elemLength < resultLength) { resultLength = elemLength; } /* * Compare strings. */ for (i = 0; i < resultLength; i++) { if (resultString[i] != elemString[i]) { /* * Adjust in case we stopped in the middle of a UTF char. */ resultLength = Tcl_UtfPrev(&resultString[i+1], resultString) - resultString; break; } } } } if (resultLength > 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj(resultString, resultLength)); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_WrongNumArgs -- * * This function generates a "wrong # args" error message in an * interpreter. It is used as a utility function by many command * functions, including the function that implements procedures. * * Results: * None. * * Side effects: * An error message is generated in interp's result object to indicate * that a command was invoked with the wrong number of arguments. The * message has the form * wrong # args: should be "foo bar additional stuff" * where "foo" and "bar" are the initial objects in objv (objc determines * how many of these are printed) and "additional stuff" is the contents * of the message argument. * * The message printed is modified somewhat if the command is wrapped * inside an ensemble. In that case, the error message generated is * rewritten in such a way that it appears to be generated from the * user-visible command and not how that command is actually implemented, * giving a better overall user experience. * * Internally, the Tcl core may set the flag INTERP_ALTERNATE_WRONG_ARGS * in the interpreter to generate complex multi-part messages by calling * this function repeatedly. This allows the code that knows how to * handle ensemble-related error messages to be kept here while still * generating suitable error messages for commands like [read] and * [socket]. Ideally, this would be done through an extra flags argument, * but that wouldn't be source-compatible with the existing API and it's * a fairly rare requirement anyway. * *---------------------------------------------------------------------- */ void Tcl_WrongNumArgs( Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments to print from objv. */ Tcl_Obj *const objv[], /* Initial argument objects, which should be * included in the error message. */ const char *message) /* Error message to print after the leading * objects in objv. The message may be * NULL. */ { Tcl_Obj *objPtr; int i, len, elemLen, flags; Interp *iPtr = (Interp *) interp; const char *elementStr; /* * [incr Tcl] does something fairly horrific when generating error * messages for its ensembles; it passes the whole set of ensemble * arguments as a list in the first argument. This means that this code * causes a problem in iTcl if it attempts to correctly quote all * arguments, which would be the correct thing to do. We work around this * nasty behaviour for now, and hope that we can remove it all in the * future... */ #ifndef AVOID_HACKS_FOR_ITCL int isFirst = 1; /* Special flag used to inhibit the treating * of the first word as a list element so the * hacky way Itcl generates error messages for * its ensembles will still work. [Bug * 1066837] */ # define MAY_QUOTE_WORD (!isFirst) # define AFTER_FIRST_WORD (isFirst = 0) #else /* !AVOID_HACKS_FOR_ITCL */ # define MAY_QUOTE_WORD 1 # define AFTER_FIRST_WORD (void) 0 #endif /* AVOID_HACKS_FOR_ITCL */ TclNewObj(objPtr); if (iPtr->flags & INTERP_ALTERNATE_WRONG_ARGS) { iPtr->flags &= ~INTERP_ALTERNATE_WRONG_ARGS; Tcl_AppendObjToObj(objPtr, Tcl_GetObjResult(interp)); Tcl_AppendToObj(objPtr, " or \"", -1); } else { Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1); } /* * Check to see if we are processing an ensemble implementation, and if so * rewrite the results in terms of how the ensemble was invoked. */ if (iPtr->ensembleRewrite.sourceObjs != NULL) { int toSkip = iPtr->ensembleRewrite.numInsertedObjs; int toPrint = iPtr->ensembleRewrite.numRemovedObjs; Tcl_Obj *const *origObjv = iPtr->ensembleRewrite.sourceObjs; /* * We only know how to do rewriting if all the replaced objects are * actually arguments (in objv) to this function. Otherwise it just * gets too complicated and we'd be better off just giving a slightly * confusing error message... */ if (objc < toSkip) { goto addNormalArgumentsToMessage; } /* * Strip out the actual arguments that the ensemble inserted. */ objv += toSkip; objc -= toSkip; /* * We assume no object is of index type. */ for (i=0 ; itypePtr == &indexType) { register IndexRep *indexRep = origObjv[i]->internalRep.twoPtrValue.ptr1; elementStr = EXPAND_OF(indexRep); elemLen = strlen(elementStr); } else if (origObjv[i]->typePtr == &tclEnsembleCmdType) { register EnsembleCmdRep *ecrPtr = origObjv[i]->internalRep.twoPtrValue.ptr1; elementStr = ecrPtr->fullSubcmdName; elemLen = strlen(elementStr); } else { elementStr = TclGetStringFromObj(origObjv[i], &elemLen); } flags = 0; len = TclScanElement(elementStr, elemLen, &flags); if (MAY_QUOTE_WORD && len != elemLen) { char *quotedElementStr = TclStackAlloc(interp, (unsigned)len + 1); len = TclConvertElement(elementStr, elemLen, quotedElementStr, flags); Tcl_AppendToObj(objPtr, quotedElementStr, len); TclStackFree(interp, quotedElementStr); } else { Tcl_AppendToObj(objPtr, elementStr, elemLen); } AFTER_FIRST_WORD; /* * Add a space if the word is not the last one (which has a * moderately complex condition here). */ if (itypePtr == &indexType) { register IndexRep *indexRep = objv[i]->internalRep.twoPtrValue.ptr1; Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), NULL); } else if (objv[i]->typePtr == &tclEnsembleCmdType) { register EnsembleCmdRep *ecrPtr = objv[i]->internalRep.twoPtrValue.ptr1; Tcl_AppendStringsToObj(objPtr, ecrPtr->fullSubcmdName, NULL); } else { /* * Quote the argument if it contains spaces (Bug 942757). */ elementStr = TclGetStringFromObj(objv[i], &elemLen); flags = 0; len = TclScanElement(elementStr, elemLen, &flags); if (MAY_QUOTE_WORD && len != elemLen) { char *quotedElementStr = TclStackAlloc(interp, (unsigned) len + 1); len = TclConvertElement(elementStr, elemLen, quotedElementStr, flags); Tcl_AppendToObj(objPtr, quotedElementStr, len); TclStackFree(interp, quotedElementStr); } else { Tcl_AppendToObj(objPtr, elementStr, elemLen); } } AFTER_FIRST_WORD; /* * Append a space character (" ") if there is more text to follow * (either another element from objv, or the message string). */ if (i 0) { curArg = objv[srcIndex]; srcIndex++; objc--; str = Tcl_GetStringFromObj(curArg, &length); if (length > 0) { c = str[1]; } else { c = 0; } /* * Loop throught the argument descriptors searching for one with the * matching key string. If found, leave a pointer to it in matchPtr. */ matchPtr = NULL; infoPtr = argTable; for (; infoPtr != NULL && infoPtr->type != TCL_ARGV_END ; infoPtr++) { if (infoPtr->keyStr == NULL) { continue; } if ((infoPtr->keyStr[1] != c) || (strncmp(infoPtr->keyStr, str, length) != 0)) { continue; } if (infoPtr->keyStr[length] == 0) { matchPtr = infoPtr; goto gotMatch; } if (matchPtr != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "ambiguous option \"%s\"", str)); goto error; } matchPtr = infoPtr; } if (matchPtr == NULL) { /* * Unrecognized argument. Just copy it down, unless the caller * prefers an error to be registered. */ if (remObjv == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unrecognized argument \"%s\"", str)); goto error; } dstIndex++; /* This argument is now handled */ leftovers[nrem++] = curArg; continue; } /* * Take the appropriate action based on the option type */ gotMatch: infoPtr = matchPtr; switch (infoPtr->type) { case TCL_ARGV_CONSTANT: *((int *) infoPtr->dstPtr) = PTR2INT(infoPtr->srcPtr); break; case TCL_ARGV_INT: if (objc == 0) { goto missingArg; } if (Tcl_GetIntFromObj(interp, objv[srcIndex], (int *) infoPtr->dstPtr) == TCL_ERROR) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected integer argument for \"%s\" but got \"%s\"", infoPtr->keyStr, Tcl_GetString(objv[srcIndex]))); goto error; } srcIndex++; objc--; break; case TCL_ARGV_STRING: if (objc == 0) { goto missingArg; } *((const char **) infoPtr->dstPtr) = Tcl_GetString(objv[srcIndex]); srcIndex++; objc--; break; case TCL_ARGV_REST: /* * Only store the point where we got to if it's not to be written * to NULL, so that TCL_ARGV_AUTO_REST works. */ if (infoPtr->dstPtr != NULL) { *((int *) infoPtr->dstPtr) = dstIndex; } goto argsDone; case TCL_ARGV_FLOAT: if (objc == 0) { goto missingArg; } if (Tcl_GetDoubleFromObj(interp, objv[srcIndex], (double *) infoPtr->dstPtr) == TCL_ERROR) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected floating-point argument for \"%s\" but got \"%s\"", infoPtr->keyStr, Tcl_GetString(objv[srcIndex]))); goto error; } srcIndex++; objc--; break; case TCL_ARGV_FUNC: { Tcl_ArgvFuncProc *handlerProc = (Tcl_ArgvFuncProc *) infoPtr->srcPtr; Tcl_Obj *argObj; if (objc == 0) { argObj = NULL; } else { argObj = objv[srcIndex]; } if (handlerProc(infoPtr->clientData, argObj, infoPtr->dstPtr)) { srcIndex++; objc--; } break; } case TCL_ARGV_GENFUNC: { Tcl_ArgvGenFuncProc *handlerProc = (Tcl_ArgvGenFuncProc *) infoPtr->srcPtr; objc = handlerProc(infoPtr->clientData, interp, objc, &objv[srcIndex], infoPtr->dstPtr); if (objc < 0) { goto error; } break; } case TCL_ARGV_HELP: PrintUsage(interp, argTable); goto error; default: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad argument type %d in Tcl_ArgvInfo", infoPtr->type)); goto error; } } /* * If we broke out of the loop because of an OPT_REST argument, copy the * remaining arguments down. Note that there is always at least one * argument left over - the command name - so we always have a result if * our caller is willing to receive it. [Bug 3413857] */ argsDone: if (remObjv == NULL) { /* * Nothing to do. */ return TCL_OK; } if (objc > 0) { memcpy(leftovers+nrem, objv+srcIndex, objc*sizeof(Tcl_Obj *)); nrem += objc; } leftovers[nrem] = NULL; *objcPtr = nrem++; *remObjv = ckrealloc(leftovers, nrem * sizeof(Tcl_Obj *)); return TCL_OK; /* * Make sure to handle freeing any temporary space we've allocated on the * way to an error. */ missingArg: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" option requires an additional argument", str)); error: if (leftovers != NULL) { ckfree(leftovers); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * PrintUsage -- * * Generate a help string describing command-line options. * * Results: * The interp's result will be modified to hold a help string describing * all the options in argTable. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void PrintUsage( Tcl_Interp *interp, /* Place information in this interp's result * area. */ const Tcl_ArgvInfo *argTable) /* Array of command-specific argument * descriptions. */ { register const Tcl_ArgvInfo *infoPtr; int width, numSpaces; #define NUM_SPACES 20 static const char spaces[] = " "; char tmp[TCL_DOUBLE_SPACE]; Tcl_Obj *msg; /* * First, compute the width of the widest option key, so that we can make * everything line up. */ width = 4; for (infoPtr = argTable; infoPtr->type != TCL_ARGV_END; infoPtr++) { int length; if (infoPtr->keyStr == NULL) { continue; } length = strlen(infoPtr->keyStr); if (length > width) { width = length; } } /* * Now add the option information, with pretty-printing. */ msg = Tcl_NewStringObj("Command-specific options:", -1); for (infoPtr = argTable; infoPtr->type != TCL_ARGV_END; infoPtr++) { if ((infoPtr->type == TCL_ARGV_HELP) && (infoPtr->keyStr == NULL)) { Tcl_AppendPrintfToObj(msg, "\n%s", infoPtr->helpStr); continue; } Tcl_AppendPrintfToObj(msg, "\n %s:", infoPtr->keyStr); numSpaces = width + 1 - strlen(infoPtr->keyStr); while (numSpaces > 0) { if (numSpaces >= NUM_SPACES) { Tcl_AppendToObj(msg, spaces, NUM_SPACES); } else { Tcl_AppendToObj(msg, spaces, numSpaces); } numSpaces -= NUM_SPACES; } Tcl_AppendToObj(msg, infoPtr->helpStr, -1); switch (infoPtr->type) { case TCL_ARGV_INT: Tcl_AppendPrintfToObj(msg, "\n\t\tDefault value: %d", *((int *) infoPtr->dstPtr)); break; 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); if (string != NULL) { Tcl_AppendPrintfToObj(msg, "\n\t\tDefault value: \"%s\"", string); } break; } default: break; } } Tcl_SetObjResult(interp, msg); } /* *---------------------------------------------------------------------- * * TclGetCompletionCodeFromObj -- * * Parses Completion code Code * * Results: * Returns TCL_ERROR if the value is an invalid completion code. * Otherwise, returns TCL_OK, and writes the completion code to the * pointer provided. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclGetCompletionCodeFromObj( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *value, int *codePtr) /* Argument objects. */ { static const char *const returnCodes[] = { "ok", "error", "return", "break", "continue", NULL }; if ((value->typePtr != &indexType) && TclGetIntFromObj(NULL, value, codePtr) == TCL_OK) { return TCL_OK; } if (Tcl_GetIndexFromObj(NULL, value, returnCodes, NULL, TCL_EXACT, codePtr) == TCL_OK) { return TCL_OK; } /* * Value is not a legal completion code. */ if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad completion code \"%s\": must be" " ok, error, return, break, continue, or an integer", TclGetString(value))); Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_CODE", NULL); } return TCL_ERROR; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclIORChan.c0000644000175000017500000025540712663660065015312 0ustar sergeisergei/* * tclIORChan.c -- * * This file contains the implementation of Tcl's generic channel * reflection code, which allows the implementation of Tcl channels in * Tcl code. * * Parts of this file are based on code contributed by Jean-Claude * Wippler. * * See TIP #219 for the specification of this functionality. * * Copyright (c) 2004-2005 ActiveState, a divison of Sophos * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclIO.h" #include #ifndef EINVAL #define EINVAL 9 #endif #ifndef EOK #define EOK 0 #endif /* * Signatures of all functions used in the C layer of the reflection. */ static int ReflectClose(ClientData clientData, Tcl_Interp *interp); static int ReflectInput(ClientData clientData, char *buf, int toRead, int *errorCodePtr); static int ReflectOutput(ClientData clientData, const char *buf, int toWrite, int *errorCodePtr); static void ReflectWatch(ClientData clientData, int mask); static int ReflectBlock(ClientData clientData, int mode); #ifdef TCL_THREADS static void ReflectThread(ClientData clientData, int action); #endif static Tcl_WideInt ReflectSeekWide(ClientData clientData, Tcl_WideInt offset, int mode, int *errorCodePtr); static int ReflectSeek(ClientData clientData, long offset, int mode, int *errorCodePtr); static int ReflectGetOption(ClientData clientData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); static int ReflectSetOption(ClientData clientData, Tcl_Interp *interp, const char *optionName, const char *newValue); /* * The C layer channel type/driver definition used by the reflection. This is * a version 3 structure. */ static const Tcl_ChannelType tclRChannelType = { "tclrchannel", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ ReflectClose, /* Close channel, clean instance data */ ReflectInput, /* Handle read request */ ReflectOutput, /* Handle write request */ ReflectSeek, /* Move location of access point. NULL'able */ ReflectSetOption, /* Set options. NULL'able */ ReflectGetOption, /* Get options. NULL'able */ ReflectWatch, /* Initialize notifier */ NULL, /* Get OS handle from the channel. NULL'able */ NULL, /* No close2 support. NULL'able */ ReflectBlock, /* Set blocking/nonblocking. NULL'able */ NULL, /* Flush channel. Not used by core. NULL'able */ NULL, /* Handle events. NULL'able */ ReflectSeekWide, /* Move access point (64 bit). NULL'able */ #ifdef TCL_THREADS ReflectThread, /* thread action, tracking owner */ #else NULL, /* thread action */ #endif NULL /* truncate */ }; /* * Instance data for a reflected channel. =========================== */ typedef struct { Tcl_Channel chan; /* Back reference to generic channel * structure. */ Tcl_Interp *interp; /* Reference to the interpreter containing the * Tcl level part of the channel. NULL here * signals the channel is dead because the * interpreter/thread containing its Tcl * command is gone. */ #ifdef TCL_THREADS Tcl_ThreadId thread; /* Thread the 'interp' belongs to. == Handler thread */ Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */ #endif Tcl_Obj *cmd; /* Callback command prefix */ Tcl_Obj *methods; /* Methods to append to command prefix */ Tcl_Obj *name; /* Name of the channel as created */ int mode; /* Mask of R/W mode */ int interest; /* Mask of events the channel is interested * in. */ int dead; /* Boolean signal that some operations * should no longer be attempted. */ /* * Note regarding the usage of timers. * * Most channel implementations need a timer in the C level to ensure that * data in buffers is flushed out through the generation of fake file * events. * * See 'rechan', 'memchan', etc. * * Here this is _not_ required. Interest in events is posted to the Tcl * level via 'watch'. And posting of events is possible from the Tcl level * as well, via 'chan postevent'. This means that the generation of all * events, fake or not, timer based or not, is completely in the hands of * the Tcl level. Therefore no timer here. */ } ReflectedChannel; /* * Structure of the table maping from channel handles to reflected * channels. Each interpreter which has the handler command for one or more * reflected channels records them in such a table, so that 'chan postevent' * is able to find them even if the actual channel was moved to a different * interpreter and/or thread. * * The table is reachable via the standard interpreter AssocData, the key is * defined below. */ typedef struct { Tcl_HashTable map; } ReflectedChannelMap; #define RCMKEY "ReflectedChannelMap" /* * Event literals. ================================================== */ static const char *const eventOptions[] = { "read", "write", NULL }; typedef enum { EVENT_READ, EVENT_WRITE } EventOption; /* * Method literals. ================================================== */ static const char *const methodNames[] = { "blocking", /* OPT */ "cget", /* OPT \/ Together or none */ "cgetall", /* OPT /\ of these two */ "configure", /* OPT */ "finalize", /* */ "initialize", /* */ "read", /* OPT */ "seek", /* OPT */ "watch", /* */ "write", /* OPT */ NULL }; typedef enum { METH_BLOCKING, METH_CGET, METH_CGETALL, METH_CONFIGURE, METH_FINAL, METH_INIT, METH_READ, METH_SEEK, METH_WATCH, METH_WRITE } MethodName; #define FLAG(m) (1 << (m)) #define REQUIRED_METHODS \ (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)) #define RANDW \ (TCL_READABLE | TCL_WRITABLE) #define IMPLIES(a,b) ((!(a)) || (b)) #define NEGIMPL(a,b) #define HAS(x,f) (x & FLAG(f)) #ifdef TCL_THREADS /* * Thread specific types and structures. * * We are here essentially creating a very specific implementation of 'thread * send'. */ /* * Enumeration of all operations which can be forwarded. */ typedef enum { ForwardedClose, ForwardedInput, ForwardedOutput, ForwardedSeek, ForwardedWatch, ForwardedBlock, ForwardedSetOpt, ForwardedGetOpt, ForwardedGetOptAll } ForwardedOperation; /* * Event used to forward driver invocations to the thread actually managing * the channel. We cannot construct the command to execute and forward that. * Because then it will contain a mixture of Tcl_Obj's belonging to both the * command handler thread (CT), and the thread managing the channel (MT), * executed in CT. Tcl_Obj's are not allowed to cross thread boundaries. So we * forward an operation code, the argument details, and reference to results. * The command is assembled in the CT and belongs fully to that thread. No * sharing problems. */ typedef struct ForwardParamBase { int code; /* O: Ok/Fail of the cmd handler */ char *msgStr; /* O: Error message for handler failure */ int mustFree; /* O: True if msgStr is allocated, false if * otherwise (static). */ } ForwardParamBase; /* * Operation specific parameter/result structures. (These are "subtypes" of * ForwardParamBase. Where an operation does not need any special types, it * has no "subtype" and just uses ForwardParamBase, as listed above.) */ struct ForwardParamInput { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ char *buf; /* O: Where to store the read bytes */ int toRead; /* I: #bytes to read, * O: #bytes actually read */ }; struct ForwardParamOutput { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ const char *buf; /* I: Where the bytes to write come from */ int toWrite; /* I: #bytes to write, * O: #bytes actually written */ }; struct ForwardParamSeek { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ int seekMode; /* I: How to seek */ Tcl_WideInt offset; /* I: Where to seek, * O: New location */ }; struct ForwardParamWatch { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ int mask; /* I: What events to watch for */ }; struct ForwardParamBlock { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ int nonblocking; /* I: What mode to activate */ }; struct ForwardParamSetOpt { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ const char *name; /* Name of option to set */ const char *value; /* Value to set */ }; struct ForwardParamGetOpt { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ const char *name; /* Name of option to get, maybe NULL */ Tcl_DString *value; /* Result */ }; /* * Now join all these together in a single union for convenience. */ typedef union ForwardParam { ForwardParamBase base; struct ForwardParamInput input; struct ForwardParamOutput output; struct ForwardParamSeek seek; struct ForwardParamWatch watch; struct ForwardParamBlock block; struct ForwardParamSetOpt setOpt; struct ForwardParamGetOpt getOpt; } ForwardParam; /* * Forward declaration. */ typedef struct ForwardingResult ForwardingResult; /* * General event structure, with reference to operation specific data. */ typedef struct ForwardingEvent { Tcl_Event event; /* Basic event data, has to be first item */ ForwardingResult *resultPtr; ForwardedOperation op; /* Forwarded driver operation */ ReflectedChannel *rcPtr; /* Channel instance */ ForwardParam *param; /* Packaged arguments and return values, a * ForwardParam pointer. */ } ForwardingEvent; /* * Structure to manage the result of the forwarding. This is not the result of * the operation itself, but about the success of the forward event itself. * The event can be successful, even if the operation which was forwarded * failed. It is also there to manage the synchronization between the involved * threads. */ struct ForwardingResult { Tcl_ThreadId src; /* Originating thread. */ Tcl_ThreadId dst; /* Thread the op was forwarded to. */ Tcl_Interp *dsti; /* Interpreter in the thread the op was * forwarded to. */ /* * Note regarding 'dsti' above: Its information is also available via the * chain evPtr->rcPtr->interp, however, as can be seen, two more * indirections are needed to retrieve it. And the evPtr may be gone, * breaking the chain. */ Tcl_Condition done; /* Condition variable the forwarder blocks * on. */ int result; /* TCL_OK or TCL_ERROR */ ForwardingEvent *evPtr; /* Event the result belongs to. */ ForwardingResult *prevPtr, *nextPtr; /* Links into the list of pending forwarded * results. */ }; typedef struct ThreadSpecificData { /* * Table of all reflected channels owned by this thread. This is the * per-thread version of the per-interpreter map. */ ReflectedChannelMap *rcmPtr; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * List of forwarded operations which have not completed yet, plus the mutex * to protect the access to this process global list. */ static ForwardingResult *forwardList = NULL; TCL_DECLARE_MUTEX(rcForwardMutex) /* * Function containing the generic code executing a forward, and wrapper * macros for the actual operations we wish to forward. Uses ForwardProc as * the event function executed by the thread receiving a forwarding event * (which executes the appropriate function and collects the result, if any). * * The ExitProc ensures that things do not deadlock when the sending thread * involved in the forwarding exits. It also clean things up so that we don't * leak resources when threads go away. */ static void ForwardOpToHandlerThread(ReflectedChannel *rcPtr, ForwardedOperation op, const void *param); static int ForwardProc(Tcl_Event *evPtr, int mask); static void SrcExitProc(ClientData clientData); #define FreeReceivedError(p) \ if ((p)->base.mustFree) { \ ckfree((p)->base.msgStr); \ } #define PassReceivedErrorInterp(i,p) \ if ((i) != NULL) { \ Tcl_SetChannelErrorInterp((i), \ Tcl_NewStringObj((p)->base.msgStr, -1)); \ } \ FreeReceivedError(p) #define PassReceivedError(c,p) \ Tcl_SetChannelError((c), Tcl_NewStringObj((p)->base.msgStr, -1)); \ FreeReceivedError(p) #define ForwardSetStaticError(p,emsg) \ (p)->base.code = TCL_ERROR; \ (p)->base.mustFree = 0; \ (p)->base.msgStr = (char *) (emsg) #define ForwardSetDynamicError(p,emsg) \ (p)->base.code = TCL_ERROR; \ (p)->base.mustFree = 1; \ (p)->base.msgStr = (char *) (emsg) static void ForwardSetObjError(ForwardParam *p, Tcl_Obj *objPtr); static ReflectedChannelMap * GetThreadReflectedChannelMap(void); static void DeleteThreadReflectedChannelMap(ClientData clientData); #endif /* TCL_THREADS */ #define SetChannelErrorStr(c,msgStr) \ Tcl_SetChannelError((c), Tcl_NewStringObj((msgStr), -1)) static Tcl_Obj * MarshallError(Tcl_Interp *interp); static void UnmarshallErrorResult(Tcl_Interp *interp, Tcl_Obj *msgObj); /* * Static functions for this file: */ static int EncodeEventMask(Tcl_Interp *interp, const char *objName, Tcl_Obj *obj, int *mask); static Tcl_Obj * DecodeEventMask(int mask); static ReflectedChannel * NewReflectedChannel(Tcl_Interp *interp, Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj); static Tcl_Obj * NextHandle(void); static void FreeReflectedChannel(ReflectedChannel *rcPtr); static int InvokeTclMethod(ReflectedChannel *rcPtr, MethodName method, Tcl_Obj *argOneObj, Tcl_Obj *argTwoObj, Tcl_Obj **resultObjPtr); static ReflectedChannelMap * GetReflectedChannelMap(Tcl_Interp *interp); static void DeleteReflectedChannelMap(ClientData clientData, Tcl_Interp *interp); static int ErrnoReturn(ReflectedChannel *rcPtr, Tcl_Obj *resObj); static void MarkDead(ReflectedChannel *rcPtr); /* * Global constant strings (messages). ================== * These string are used directly as bypass errors, thus they have to be valid * Tcl lists where the last element is the message itself. Hence the * list-quoting to keep the words of the message together. See also [x]. */ static const char *msg_read_toomuch = "{read delivered more than requested}"; static const char *msg_write_toomuch = "{write wrote more than requested}"; static const char *msg_write_nothing = "{write wrote nothing}"; static const char *msg_seek_beforestart = "{Tried to seek before origin}"; #ifdef TCL_THREADS static const char *msg_send_originlost = "{Channel thread lost}"; #endif /* TCL_THREADS */ static const char *msg_send_dstlost = "{Owner lost}"; static const char *msg_dstlost = "-code 1 -level 0 -errorcode NONE -errorinfo {} -errorline 1 {Owner lost}"; /* * Main methods to plug into the 'chan' ensemble'. ================== */ /* *---------------------------------------------------------------------- * * TclChanCreateObjCmd -- * * This function is invoked to process the "chan create" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. The handle of the new channel is placed in the * interp result. * * Side effects: * Creates a new channel. * *---------------------------------------------------------------------- */ int TclChanCreateObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { ReflectedChannel *rcPtr; /* Instance data of the new channel */ Tcl_Obj *rcId; /* Handle of the new channel */ int mode; /* R/W mode of new channel. Has to match * abilities of handler commands */ Tcl_Obj *cmdObj; /* Command prefix, list of words */ Tcl_Obj *cmdNameObj; /* Command name */ Tcl_Channel chan; /* Token for the new channel */ Tcl_Obj *modeObj; /* mode in obj form for method call */ int listc; /* Result of 'initialize', and of */ Tcl_Obj **listv; /* its sublist in the 2nd element */ int methIndex; /* Encoded method name */ int result; /* Result code for 'initialize' */ Tcl_Obj *resObj; /* Result data for 'initialize' */ int methods; /* Bitmask for supported methods. */ Channel *chanPtr; /* 'chan' resolved to internal struct. */ Tcl_Obj *err; /* Error message */ ReflectedChannelMap *rcmPtr; /* Map of reflected channels with handlers in * this interp. */ Tcl_HashEntry *hPtr; /* Entry in the above map */ int isNew; /* Placeholder. */ /* * Syntax: chan create MODE CMDPREFIX * [0] [1] [2] [3] * * Actually: rCreate MODE CMDPREFIX * [0] [1] [2] */ #define MODE (1) #define CMD (2) /* * Number of arguments... */ if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "mode cmdprefix"); return TCL_ERROR; } /* * First argument is a list of modes. Allowed entries are "read", "write". * Expect at least one list element. Abbreviations are ok. */ modeObj = objv[MODE]; if (EncodeEventMask(interp, "mode", objv[MODE], &mode) != TCL_OK) { return TCL_ERROR; } /* * Second argument is command prefix, i.e. list of words, first word is * name of handler command, other words are fixed arguments. Run the * 'initialize' method to get the list of supported methods. Validate * this. */ cmdObj = objv[CMD]; /* * Basic check that the command prefix truly is a list. */ if (Tcl_ListObjIndex(interp, cmdObj, 0, &cmdNameObj) != TCL_OK) { return TCL_ERROR; } /* * Now create the channel. */ rcId = NextHandle(); rcPtr = NewReflectedChannel(interp, cmdObj, mode, rcId); /* * Invoke 'initialize' and validate that the handler is present and ok. * Squash the channel if not. * * Note: The conversion of 'mode' back into a Tcl_Obj ensures that * 'initialize' is invoked with canonical mode names, and no * abbreviations. Using modeObj directly could feed abbreviations into the * handler, and the handler is not specified to handle such. */ modeObj = DecodeEventMask(mode); /* assert modeObj.refCount == 1 */ result = InvokeTclMethod(rcPtr, METH_INIT, modeObj, NULL, &resObj); Tcl_DecrRefCount(modeObj); if (result != TCL_OK) { UnmarshallErrorResult(interp, resObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ goto error; } /* * Verify the result. * - List, of method names. Convert to mask. * Check for non-optionals through the mask. * Compare open mode against optional r/w. */ if (Tcl_ListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s initialize\" returned non-list: %s", Tcl_GetString(cmdObj), Tcl_GetString(resObj))); Tcl_DecrRefCount(resObj); goto error; } methods = 0; while (listc > 0) { if (Tcl_GetIndexFromObj(interp, listv[listc-1], methodNames, "method", TCL_EXACT, &methIndex) != TCL_OK) { TclNewLiteralStringObj(err, "chan handler \""); Tcl_AppendObjToObj(err, cmdObj); Tcl_AppendToObj(err, " initialize\" returned ", -1); Tcl_AppendObjToObj(err, Tcl_GetObjResult(interp)); Tcl_SetObjResult(interp, err); Tcl_DecrRefCount(resObj); goto error; } methods |= FLAG(methIndex); listc--; } Tcl_DecrRefCount(resObj); if ((REQUIRED_METHODS & methods) != REQUIRED_METHODS) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s\" does not support all required methods", Tcl_GetString(cmdObj))); goto error; } if ((mode & TCL_READABLE) && !HAS(methods, METH_READ)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s\" lacks a \"read\" method", Tcl_GetString(cmdObj))); goto error; } if ((mode & TCL_WRITABLE) && !HAS(methods, METH_WRITE)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s\" lacks a \"write\" method", Tcl_GetString(cmdObj))); goto error; } if (!IMPLIES(HAS(methods, METH_CGET), HAS(methods, METH_CGETALL))) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s\" supports \"cget\" but not \"cgetall\"", Tcl_GetString(cmdObj))); goto error; } if (!IMPLIES(HAS(methods, METH_CGETALL), HAS(methods, METH_CGET))) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s\" supports \"cgetall\" but not \"cget\"", Tcl_GetString(cmdObj))); goto error; } Tcl_ResetResult(interp); /* * Everything is fine now. */ chan = Tcl_CreateChannel(&tclRChannelType, TclGetString(rcId), rcPtr, mode); rcPtr->chan = chan; TclChannelPreserve(chan); chanPtr = (Channel *) chan; if ((methods & NULLABLE_METHODS) != NULLABLE_METHODS) { /* * Some of the nullable methods are not supported. We clone the * channel type, null the associated C functions, and use the result * as the actual channel type. */ Tcl_ChannelType *clonePtr = ckalloc(sizeof(Tcl_ChannelType)); memcpy(clonePtr, &tclRChannelType, sizeof(Tcl_ChannelType)); if (!(methods & FLAG(METH_CONFIGURE))) { clonePtr->setOptionProc = NULL; } if (!(methods & FLAG(METH_CGET)) && !(methods & FLAG(METH_CGETALL))) { clonePtr->getOptionProc = NULL; } if (!(methods & FLAG(METH_BLOCKING))) { clonePtr->blockModeProc = NULL; } if (!(methods & FLAG(METH_SEEK))) { clonePtr->seekProc = NULL; clonePtr->wideSeekProc = NULL; } chanPtr->typePtr = clonePtr; } /* * Register the channel in the I/O system, and in our our map for 'chan * postevent'. */ Tcl_RegisterChannel(interp, chan); rcmPtr = GetReflectedChannelMap(interp); hPtr = Tcl_CreateHashEntry(&rcmPtr->map, chanPtr->state->channelName, &isNew); if (!isNew && chanPtr != Tcl_GetHashValue(hPtr)) { Tcl_Panic("TclChanCreateObjCmd: duplicate channel names"); } Tcl_SetHashValue(hPtr, chan); #ifdef TCL_THREADS rcmPtr = GetThreadReflectedChannelMap(); hPtr = Tcl_CreateHashEntry(&rcmPtr->map, chanPtr->state->channelName, &isNew); Tcl_SetHashValue(hPtr, chan); #endif /* * Return handle as result of command. */ Tcl_SetObjResult(interp, Tcl_NewStringObj(chanPtr->state->channelName, -1)); return TCL_OK; error: Tcl_DecrRefCount(rcPtr->name); Tcl_DecrRefCount(rcPtr->methods); Tcl_DecrRefCount(rcPtr->cmd); ckfree((char*) rcPtr); return TCL_ERROR; #undef MODE #undef CMD } /* *---------------------------------------------------------------------- * * TclChanPostEventObjCmd -- * * This function is invoked to process the "chan postevent" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Posts events to a reflected channel, invokes event handlers. The * latter implies that arbitrary side effects are possible. * *---------------------------------------------------------------------- */ typedef struct ReflectEvent { Tcl_Event header; ReflectedChannel *rcPtr; int events; } ReflectEvent; static int ReflectEventRun( Tcl_Event *ev, int flags) { /* OWNER thread * * Note: When the channel is closed any pending events of this type are * deleted. See ReflectClose() for the Tcl_DeleteEvents() calls * accomplishing that. */ ReflectEvent *e = (ReflectEvent *) ev; Tcl_NotifyChannel(e->rcPtr->chan, e->events); return 1; } static int ReflectEventDelete( Tcl_Event *ev, ClientData cd) { /* OWNER thread * * Invoked by DeleteThreadReflectedChannelMap() and ReflectClose(). The * latter ensures that no pending events of this type are run on an * invalid channel. */ ReflectEvent *e = (ReflectEvent *) ev; if ((ev->proc != ReflectEventRun) || ((cd != NULL) && (cd != e->rcPtr))) { return 0; } return 1; } int TclChanPostEventObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { /* * Ensure -> HANDLER thread * * Syntax: chan postevent CHANNEL EVENTSPEC * [0] [1] [2] [3] * * Actually: rPostevent CHANNEL EVENTSPEC * [0] [1] [2] * * where EVENTSPEC = {read write ...} (Abbreviations allowed as well). */ #define CHAN (1) #define EVENT (2) const char *chanId; /* Tcl level channel handle */ Tcl_Channel chan; /* Channel associated to the handle */ const Tcl_ChannelType *chanTypePtr; /* Its associated driver structure */ ReflectedChannel *rcPtr; /* Associated instance data */ int events; /* Mask of events to post */ ReflectedChannelMap *rcmPtr;/* Map of reflected channels with handlers in * this interp. */ Tcl_HashEntry *hPtr; /* Entry in the above map */ /* * Number of arguments... */ if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "channel eventspec"); return TCL_ERROR; } /* * First argument is a channel, a reflected channel, and the call of this * command is done from the interp defining the channel handler cmd. */ chanId = TclGetString(objv[CHAN]); rcmPtr = GetReflectedChannelMap(interp); hPtr = Tcl_FindHashEntry(&rcmPtr->map, chanId); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can not find reflected channel named \"%s\"", chanId)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanId, NULL); return TCL_ERROR; } /* * Note that the search above subsumes several of the older checks, namely: * * (1) Does the channel handle refer to a reflected channel ? * (2) Is the post event issued from the interpreter holding the handler * of the reflected channel ? * * A successful search answers yes to both. Because the map holds only * handles of reflected channels, and only of such whose handler is * defined in this interpreter. * * We keep the old checks for both, for paranioa, but abort now instead of * throwing errors, as failure now means that our internal datastructures * have gone seriously haywire. */ chan = Tcl_GetHashValue(hPtr); chanTypePtr = Tcl_GetChannelType(chan); /* * We use a function referenced by the channel type as our cookie to * detect calls to non-reflecting channels. The channel type itself is not * suitable, as it might not be the static definition in this file, but a * clone thereof. And while we have reserved the name of the type nothing * in the core checks against violation, so someone else might have * created a channel type using our name, clashing with ourselves. */ if (chanTypePtr->watchProc != &ReflectWatch) { Tcl_Panic("TclChanPostEventObjCmd: channel is not a reflected channel"); } rcPtr = Tcl_GetChannelInstanceData(chan); if (rcPtr->interp != interp) { Tcl_Panic("TclChanPostEventObjCmd: postevent accepted for call from outside interpreter"); } /* * Second argument is a list of events. Allowed entries are "read", * "write". Expect at least one list element. Abbreviations are ok. */ if (EncodeEventMask(interp, "event", objv[EVENT], &events) != TCL_OK) { return TCL_ERROR; } /* * Check that the channel is actually interested in the provided events. */ if (events & ~rcPtr->interest) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "tried to post events channel \"%s\" is not interested in", chanId)); return TCL_ERROR; } /* * We have the channel and the events to post. */ #ifdef TCL_THREADS if (rcPtr->owner == rcPtr->thread) { #endif Tcl_NotifyChannel(chan, events); #ifdef TCL_THREADS } else { ReflectEvent *ev = ckalloc(sizeof(ReflectEvent)); ev->header.proc = ReflectEventRun; ev->events = events; ev->rcPtr = rcPtr; /* * We are not preserving the structure here. When the channel is * closed any pending events are deleted, see ReflectClose(), and * ReflectEventDelete(). Trying to preserve and later release when the * event is run may generate a situation where the channel structure * is deleted but not our structure, crashing in * FreeReflectedChannel(). * * Force creation of the RCM, for proper cleanup on thread teardown. * The teardown of unprocessed events is currently coupled to the * thread reflected channel map */ (void) GetThreadReflectedChannelMap(); /* XXX Race condition !! * XXX The destination thread may not exist anymore already. * XXX (Delayed postevent executed after channel got removed). * XXX Can we detect this ? (check the validity of the owner threadid ?) * XXX Actually, in that case the channel should be dead also ! */ Tcl_ThreadQueueEvent(rcPtr->owner, (Tcl_Event *) ev, TCL_QUEUE_TAIL); Tcl_ThreadAlert(rcPtr->owner); } #endif /* * Squash interp results left by the event script. */ Tcl_ResetResult(interp); return TCL_OK; #undef CHAN #undef EVENT } /* * Channel error message marshalling utilities. */ static Tcl_Obj * MarshallError( Tcl_Interp *interp) { /* * Capture the result status of the interpreter into a string. => List of * options and values, followed by the error message. The result has * refCount 0. */ Tcl_Obj *returnOpt = Tcl_GetReturnOptions(interp, TCL_ERROR); /* * => returnOpt.refCount == 0. We can append directly. */ Tcl_ListObjAppendElement(NULL, returnOpt, Tcl_GetObjResult(interp)); return returnOpt; } static void UnmarshallErrorResult( Tcl_Interp *interp, Tcl_Obj *msgObj) { int lc; Tcl_Obj **lv; int explicitResult; int numOptions; /* * Process the caught message. * * Syntax = (option value)... ?message? * * Bad syntax causes a panic. This is OK because the other side uses * Tcl_GetReturnOptions and list construction functions to marshall the * information; if we panic here, something has gone badly wrong already. */ if (Tcl_ListObjGetElements(interp, msgObj, &lc, &lv) != TCL_OK) { Tcl_Panic("TclChanCaughtErrorBypass: Bad syntax of caught result"); } if (interp == NULL) { return; } explicitResult = lc & 1; /* Odd number of values? */ numOptions = lc - explicitResult; if (explicitResult) { Tcl_SetObjResult(interp, lv[lc-1]); } (void) Tcl_SetReturnOptions(interp, Tcl_NewListObj(numOptions, lv)); ((Interp *) interp)->flags &= ~ERR_ALREADY_LOGGED; } int TclChanCaughtErrorBypass( Tcl_Interp *interp, Tcl_Channel chan) { Tcl_Obj *chanMsgObj = NULL; Tcl_Obj *interpMsgObj = NULL; Tcl_Obj *msgObj = NULL; /* * Get a bypassed error message from channel and/or interpreter, save the * reference, then kill the returned objects, if there were any. If there * are messages in both the channel has preference. */ if ((chan == NULL) && (interp == NULL)) { return 0; } if (chan != NULL) { Tcl_GetChannelError(chan, &chanMsgObj); } if (interp != NULL) { Tcl_GetChannelErrorInterp(interp, &interpMsgObj); } if (chanMsgObj != NULL) { msgObj = chanMsgObj; } else if (interpMsgObj != NULL) { msgObj = interpMsgObj; } if (msgObj != NULL) { Tcl_IncrRefCount(msgObj); } if (chanMsgObj != NULL) { Tcl_DecrRefCount(chanMsgObj); } if (interpMsgObj != NULL) { Tcl_DecrRefCount(interpMsgObj); } /* * No message returned, nothing caught. */ if (msgObj == NULL) { return 0; } UnmarshallErrorResult(interp, msgObj); Tcl_DecrRefCount(msgObj); return 1; } /* * Driver functions. ================================================ */ /* *---------------------------------------------------------------------- * * ReflectClose -- * * This function is invoked when the channel is closed, to delete the * driver specific instance data. * * Results: * A posix error. * * Side effects: * Releases memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectClose( ClientData clientData, Tcl_Interp *interp) { ReflectedChannel *rcPtr = clientData; int result; /* Result code for 'close' */ Tcl_Obj *resObj; /* Result data for 'close' */ ReflectedChannelMap *rcmPtr;/* Map of reflected channels with handlers in * this interp */ Tcl_HashEntry *hPtr; /* Entry in the above map */ const Tcl_ChannelType *tctPtr; if (TclInThreadExit()) { /* * This call comes from TclFinalizeIOSystem. There are no * interpreters, and therefore we cannot call upon the handler command * anymore. Threading is irrelevant as well. We simply clean up all * our C level data structures and leave the Tcl level to the other * finalization functions. */ /* * THREADED => Forward this to the origin thread * * Note: DeleteThreadReflectedChannelMap() is the thread exit handler * for the origin thread. Use this to clean up the structure? Except * if lost? */ #ifdef TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; ForwardOpToHandlerThread(rcPtr, ForwardedClose, &p); result = p.base.code; /* * Now squash the pending reflection events for this channel. */ Tcl_DeleteEvents(ReflectEventDelete, rcPtr); if (result != TCL_OK) { FreeReceivedError(&p); } } #endif tctPtr = ((Channel *)rcPtr->chan)->typePtr; if (tctPtr && tctPtr != &tclRChannelType) { ckfree((char *)tctPtr); ((Channel *)rcPtr->chan)->typePtr = NULL; } Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel); return EOK; } /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; ForwardOpToHandlerThread(rcPtr, ForwardedClose, &p); result = p.base.code; /* * Now squash the pending reflection events for this channel. */ Tcl_DeleteEvents(ReflectEventDelete, rcPtr); if (result != TCL_OK) { PassReceivedErrorInterp(interp, &p); } } else { #endif result = InvokeTclMethod(rcPtr, METH_FINAL, NULL, NULL, &resObj); if ((result != TCL_OK) && (interp != NULL)) { Tcl_SetChannelErrorInterp(interp, resObj); } Tcl_DecrRefCount(resObj); /* Remove reference we held from the * invoke */ /* * Remove the channel from the map before releasing the memory, to * prevent future accesses (like by 'postevent') from finding and * dereferencing a dangling pointer. * * NOTE: The channel may not be in the map. This is ok, that happens * when the channel was created in a different interpreter and/or * thread and then was moved here. * * NOTE: The channel may have been removed from the map already via * the per-interp DeleteReflectedChannelMap exit-handler. */ if (!rcPtr->dead) { rcmPtr = GetReflectedChannelMap(rcPtr->interp); hPtr = Tcl_FindHashEntry(&rcmPtr->map, Tcl_GetChannelName(rcPtr->chan)); if (hPtr) { Tcl_DeleteHashEntry(hPtr); } } #ifdef TCL_THREADS rcmPtr = GetThreadReflectedChannelMap(); hPtr = Tcl_FindHashEntry(&rcmPtr->map, Tcl_GetChannelName(rcPtr->chan)); if (hPtr) { Tcl_DeleteHashEntry(hPtr); } } #endif tctPtr = ((Channel *)rcPtr->chan)->typePtr; if (tctPtr && tctPtr != &tclRChannelType) { ckfree((char *)tctPtr); ((Channel *)rcPtr->chan)->typePtr = NULL; } Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel); return (result == TCL_OK) ? EOK : EINVAL; } /* *---------------------------------------------------------------------- * * ReflectInput -- * * This function is invoked when more data is requested from the channel. * * Results: * The number of bytes read. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectInput( ClientData clientData, char *buf, int toRead, int *errorCodePtr) { ReflectedChannel *rcPtr = clientData; Tcl_Obj *toReadObj; int bytec; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ Tcl_Obj *resObj; /* Result data for 'read' */ /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; p.input.buf = buf; p.input.toRead = toRead; ForwardOpToHandlerThread(rcPtr, ForwardedInput, &p); if (p.base.code != TCL_OK) { if (p.base.code < 0) { /* No error message, this is an errno signal. */ *errorCodePtr = -p.base.code; } else { PassReceivedError(rcPtr->chan, &p); *errorCodePtr = EINVAL; } p.input.toRead = -1; } else { *errorCodePtr = EOK; } return p.input.toRead; } #endif /* ASSERT: rcPtr->method & FLAG(METH_READ) */ /* ASSERT: rcPtr->mode & TCL_READABLE */ Tcl_Preserve(rcPtr); toReadObj = Tcl_NewIntObj(toRead); Tcl_IncrRefCount(toReadObj); if (InvokeTclMethod(rcPtr, METH_READ, toReadObj, NULL, &resObj)!=TCL_OK) { int code = ErrnoReturn(rcPtr, resObj); if (code < 0) { *errorCodePtr = -code; goto error; } Tcl_SetChannelError(rcPtr->chan, resObj); goto invalid; } bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); if (toRead < bytec) { SetChannelErrorStr(rcPtr->chan, msg_read_toomuch); goto invalid; } *errorCodePtr = EOK; if (bytec > 0) { memcpy(buf, bytev, (size_t) bytec); } stop: Tcl_DecrRefCount(toReadObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ Tcl_Release(rcPtr); return bytec; invalid: *errorCodePtr = EINVAL; error: bytec = -1; goto stop; } /* *---------------------------------------------------------------------- * * ReflectOutput -- * * This function is invoked when data is writen to the channel. * * Results: * The number of bytes actually written. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectOutput( ClientData clientData, const char *buf, int toWrite, int *errorCodePtr) { ReflectedChannel *rcPtr = clientData; Tcl_Obj *bufObj; Tcl_Obj *resObj; /* Result data for 'write' */ int written; /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; p.output.buf = buf; p.output.toWrite = toWrite; ForwardOpToHandlerThread(rcPtr, ForwardedOutput, &p); if (p.base.code != TCL_OK) { if (p.base.code < 0) { /* No error message, this is an errno signal. */ *errorCodePtr = -p.base.code; } else { PassReceivedError(rcPtr->chan, &p); *errorCodePtr = EINVAL; } p.output.toWrite = -1; } else { *errorCodePtr = EOK; } return p.output.toWrite; } #endif /* ASSERT: rcPtr->method & FLAG(METH_WRITE) */ /* ASSERT: rcPtr->mode & TCL_WRITABLE */ Tcl_Preserve(rcPtr); Tcl_Preserve(rcPtr->interp); bufObj = Tcl_NewByteArrayObj((unsigned char *) buf, toWrite); Tcl_IncrRefCount(bufObj); if (InvokeTclMethod(rcPtr, METH_WRITE, bufObj, NULL, &resObj) != TCL_OK) { int code = ErrnoReturn(rcPtr, resObj); if (code < 0) { *errorCodePtr = -code; goto error; } Tcl_SetChannelError(rcPtr->chan, resObj); goto invalid; } if (Tcl_InterpDeleted(rcPtr->interp)) { /* * The interp was destroyed during InvokeTclMethod(). */ SetChannelErrorStr(rcPtr->chan, msg_send_dstlost); goto invalid; } if (Tcl_GetIntFromObj(rcPtr->interp, resObj, &written) != TCL_OK) { Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp)); goto invalid; } if ((written == 0) && (toWrite > 0)) { /* * The handler claims to have written nothing of what it was * given. That is bad. */ SetChannelErrorStr(rcPtr->chan, msg_write_nothing); goto invalid; } if (toWrite < written) { /* * The handler claims to have written more than it was given. That is * bad. Note that the I/O core would crash if we were to return this * information, trying to write -nnn bytes in the next iteration. */ SetChannelErrorStr(rcPtr->chan, msg_write_toomuch); goto invalid; } *errorCodePtr = EOK; stop: Tcl_DecrRefCount(bufObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ Tcl_Release(rcPtr->interp); Tcl_Release(rcPtr); return written; invalid: *errorCodePtr = EINVAL; error: written = -1; goto stop; } /* *---------------------------------------------------------------------- * * ReflectSeekWide / ReflectSeek -- * * This function is invoked when the user wishes to seek on the channel. * * Results: * The new location of the access point. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static Tcl_WideInt ReflectSeekWide( ClientData clientData, Tcl_WideInt offset, int seekMode, int *errorCodePtr) { ReflectedChannel *rcPtr = clientData; Tcl_Obj *offObj, *baseObj; Tcl_Obj *resObj; /* Result for 'seek' */ Tcl_WideInt newLoc; /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; p.seek.seekMode = seekMode; p.seek.offset = offset; ForwardOpToHandlerThread(rcPtr, ForwardedSeek, &p); if (p.base.code != TCL_OK) { PassReceivedError(rcPtr->chan, &p); *errorCodePtr = EINVAL; p.seek.offset = -1; } else { *errorCodePtr = EOK; } return p.seek.offset; } #endif /* ASSERT: rcPtr->method & FLAG(METH_SEEK) */ Tcl_Preserve(rcPtr); offObj = Tcl_NewWideIntObj(offset); baseObj = Tcl_NewStringObj( (seekMode == SEEK_SET) ? "start" : (seekMode == SEEK_CUR) ? "current" : "end", -1); Tcl_IncrRefCount(offObj); Tcl_IncrRefCount(baseObj); if (InvokeTclMethod(rcPtr, METH_SEEK, offObj, baseObj, &resObj)!=TCL_OK) { Tcl_SetChannelError(rcPtr->chan, resObj); goto invalid; } if (Tcl_GetWideIntFromObj(rcPtr->interp, resObj, &newLoc) != TCL_OK) { Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp)); goto invalid; } if (newLoc < Tcl_LongAsWide(0)) { SetChannelErrorStr(rcPtr->chan, msg_seek_beforestart); goto invalid; } *errorCodePtr = EOK; stop: Tcl_DecrRefCount(offObj); Tcl_DecrRefCount(baseObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ Tcl_Release(rcPtr); return newLoc; invalid: *errorCodePtr = EINVAL; newLoc = -1; goto stop; } static int ReflectSeek( ClientData clientData, long offset, int seekMode, int *errorCodePtr) { /* * This function can be invoked from a transformation which is based on * standard seeking, i.e. non-wide. Because of this we have to implement * it, a dummy is not enough. We simply delegate the call to the wide * routine. */ return (int) ReflectSeekWide(clientData, Tcl_LongAsWide(offset), seekMode, errorCodePtr); } /* *---------------------------------------------------------------------- * * ReflectWatch -- * * This function is invoked to tell the channel what events the I/O * system is interested in. * * Results: * None. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static void ReflectWatch( ClientData clientData, int mask) { ReflectedChannel *rcPtr = clientData; Tcl_Obj *maskObj; /* * We restrict the interest to what the channel can support. IOW there * will never be write events for a channel which is not writable. * Analoguously for read events and non-readable channels. */ mask &= rcPtr->mode; if (mask == rcPtr->interest) { /* * Same old, same old, why should we do something? */ return; } rcPtr->interest = mask; /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; p.watch.mask = mask; ForwardOpToHandlerThread(rcPtr, ForwardedWatch, &p); /* * Any failure from the forward is ignored. We have no place to put * this. */ return; } #endif Tcl_Preserve(rcPtr); maskObj = DecodeEventMask(mask); /* assert maskObj.refCount == 1 */ (void) InvokeTclMethod(rcPtr, METH_WATCH, maskObj, NULL, NULL); Tcl_DecrRefCount(maskObj); Tcl_Release(rcPtr); } /* *---------------------------------------------------------------------- * * ReflectBlock -- * * This function is invoked to tell the channel which blocking behaviour * is required of it. * * Results: * A posix error number. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectBlock( ClientData clientData, int nonblocking) { ReflectedChannel *rcPtr = clientData; Tcl_Obj *blockObj; int errorNum; /* EINVAL or EOK (success). */ Tcl_Obj *resObj; /* Result data for 'blocking' */ /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; p.block.nonblocking = nonblocking; ForwardOpToHandlerThread(rcPtr, ForwardedBlock, &p); if (p.base.code != TCL_OK) { PassReceivedError(rcPtr->chan, &p); return EINVAL; } return EOK; } #endif blockObj = Tcl_NewBooleanObj(!nonblocking); Tcl_IncrRefCount(blockObj); Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr,METH_BLOCKING,blockObj,NULL,&resObj)!=TCL_OK) { Tcl_SetChannelError(rcPtr->chan, resObj); errorNum = EINVAL; } else { errorNum = EOK; } Tcl_DecrRefCount(blockObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ Tcl_Release(rcPtr); return errorNum; } #ifdef TCL_THREADS /* *---------------------------------------------------------------------- * * ReflectThread -- * * This function is invoked to tell the channel about thread movements. * * Results: * None. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static void ReflectThread( ClientData clientData, int action) { ReflectedChannel *rcPtr = clientData; switch (action) { case TCL_CHANNEL_THREAD_INSERT: rcPtr->owner = Tcl_GetCurrentThread(); break; case TCL_CHANNEL_THREAD_REMOVE: rcPtr->owner = NULL; break; default: Tcl_Panic("Unknown thread action code."); break; } } #endif /* *---------------------------------------------------------------------- * * ReflectSetOption -- * * This function is invoked to configure a channel option. * * Results: * A standard Tcl result code. * * Side effects: * Arbitrary, as it calls upon a Tcl script. * *---------------------------------------------------------------------- */ static int ReflectSetOption( ClientData clientData, /* Channel to query */ Tcl_Interp *interp, /* Interpreter to leave error messages in */ const char *optionName, /* Name of requested option */ const char *newValue) /* The new value */ { ReflectedChannel *rcPtr = clientData; Tcl_Obj *optionObj, *valueObj; int result; /* Result code for 'configure' */ Tcl_Obj *resObj; /* Result data for 'configure' */ /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; p.setOpt.name = optionName; p.setOpt.value = newValue; ForwardOpToHandlerThread(rcPtr, ForwardedSetOpt, &p); if (p.base.code != TCL_OK) { Tcl_Obj *err = Tcl_NewStringObj(p.base.msgStr, -1); UnmarshallErrorResult(interp, err); Tcl_DecrRefCount(err); FreeReceivedError(&p); } return p.base.code; } #endif Tcl_Preserve(rcPtr); optionObj = Tcl_NewStringObj(optionName, -1); valueObj = Tcl_NewStringObj(newValue, -1); Tcl_IncrRefCount(optionObj); Tcl_IncrRefCount(valueObj); result = InvokeTclMethod(rcPtr, METH_CONFIGURE,optionObj,valueObj, &resObj); if (result != TCL_OK) { UnmarshallErrorResult(interp, resObj); } Tcl_DecrRefCount(optionObj); Tcl_DecrRefCount(valueObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ Tcl_Release(rcPtr); return result; } /* *---------------------------------------------------------------------- * * ReflectGetOption -- * * This function is invoked to retrieve all or a channel option. * * Results: * A standard Tcl result code. * * Side effects: * Arbitrary, as it calls upon a Tcl script. * *---------------------------------------------------------------------- */ static int ReflectGetOption( ClientData clientData, /* Channel to query */ Tcl_Interp *interp, /* Interpreter to leave error messages in */ const char *optionName, /* Name of reuqested option */ Tcl_DString *dsPtr) /* String to place the result into */ { /* * This code is special. It has regular passing of Tcl result, and errors. * The bypass functions are not required. */ ReflectedChannel *rcPtr = clientData; Tcl_Obj *optionObj; Tcl_Obj *resObj; /* Result data for 'configure' */ int listc, result = TCL_OK; Tcl_Obj **listv; MethodName method; /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { int opcode; ForwardParam p; p.getOpt.name = optionName; p.getOpt.value = dsPtr; if (optionName == NULL) { opcode = ForwardedGetOptAll; } else { opcode = ForwardedGetOpt; } ForwardOpToHandlerThread(rcPtr, opcode, &p); if (p.base.code != TCL_OK) { Tcl_Obj *err = Tcl_NewStringObj(p.base.msgStr, -1); UnmarshallErrorResult(interp, err); Tcl_DecrRefCount(err); FreeReceivedError(&p); } return p.base.code; } #endif if (optionName == NULL) { /* * Retrieve all options. */ method = METH_CGETALL; optionObj = NULL; } else { /* * Retrieve the value of one option. */ method = METH_CGET; optionObj = Tcl_NewStringObj(optionName, -1); Tcl_IncrRefCount(optionObj); } Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, method, optionObj, NULL, &resObj)!=TCL_OK) { UnmarshallErrorResult(interp, resObj); goto error; } /* * The result has to go into the 'dsPtr' for propagation to the caller of * the driver. */ if (optionObj != NULL) { TclDStringAppendObj(dsPtr, resObj); goto ok; } /* * Extract the list and append each item as element. */ /* * NOTE (4): If we extract the string rep we can assume a properly quoted * string. Together with a separating space this way of simply appending * the whole string rep might be faster. It also doesn't check if the * result is a valid list. Nor that the list has an even number elements. */ if (Tcl_ListObjGetElements(interp, resObj, &listc, &listv) != TCL_OK) { goto error; } if ((listc % 2) == 1) { /* * Odd number of elements is wrong. */ Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "Expected list with even number of " "elements, got %d element%s instead", listc, (listc == 1 ? "" : "s"))); goto error; } else { int len; const char *str = Tcl_GetStringFromObj(resObj, &len); if (len) { TclDStringAppendLiteral(dsPtr, " "); Tcl_DStringAppend(dsPtr, str, len); } goto ok; } ok: result = TCL_OK; stop: if (optionObj) { Tcl_DecrRefCount(optionObj); } Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ Tcl_Release(rcPtr); return result; error: result = TCL_ERROR; goto stop; } /* * Helpers. ========================================================= */ /* *---------------------------------------------------------------------- * * EncodeEventMask -- * * This function takes a list of event items and constructs the * equivalent internal bitmask. The list must contain at least one * element. Elements are "read", "write", or any unique abbreviation of * them. Note that the bitmask is not changed if problems are * encountered. * * Results: * A standard Tcl error code. A bitmask where TCL_READABLE and/or * TCL_WRITABLE can be set. * * Side effects: * May shimmer 'obj' to a list representation. May place an error message * into the interp result. * *---------------------------------------------------------------------- */ static int EncodeEventMask( Tcl_Interp *interp, const char *objName, Tcl_Obj *obj, int *mask) { int events; /* Mask of events to post */ int listc; /* #elements in eventspec list */ Tcl_Obj **listv; /* Elements of eventspec list */ int evIndex; /* Id of event for an element of the eventspec * list. */ if (Tcl_ListObjGetElements(interp, obj, &listc, &listv) != TCL_OK) { return TCL_ERROR; } if (listc < 1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad %s list: is empty", objName)); return TCL_ERROR; } events = 0; while (listc > 0) { if (Tcl_GetIndexFromObj(interp, listv[listc-1], eventOptions, objName, 0, &evIndex) != TCL_OK) { return TCL_ERROR; } switch (evIndex) { case EVENT_READ: events |= TCL_READABLE; break; case EVENT_WRITE: events |= TCL_WRITABLE; break; } listc --; } *mask = events; return TCL_OK; } /* *---------------------------------------------------------------------- * * DecodeEventMask -- * * This function takes an internal bitmask of events and constructs the * equivalent list of event items. * * Results, Contract: * A Tcl_Obj reference. The object will have a refCount of one. The user * has to decrement it to release the object. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Tcl_Obj * DecodeEventMask( int mask) { register const char *eventStr; Tcl_Obj *evObj; switch (mask & RANDW) { case RANDW: eventStr = "read write"; break; case TCL_READABLE: eventStr = "read"; break; case TCL_WRITABLE: eventStr = "write"; break; default: eventStr = ""; break; } evObj = Tcl_NewStringObj(eventStr, -1); Tcl_IncrRefCount(evObj); /* assert evObj.refCount == 1 */ return evObj; } /* *---------------------------------------------------------------------- * * NewReflectedChannel -- * * This function is invoked to allocate and initialize the instance data * of a new reflected channel. * * Results: * A heap-allocated channel instance. * * Side effects: * Allocates memory. * *---------------------------------------------------------------------- */ static ReflectedChannel * NewReflectedChannel( Tcl_Interp *interp, Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj) { ReflectedChannel *rcPtr; MethodName mn = METH_BLOCKING; rcPtr = ckalloc(sizeof(ReflectedChannel)); /* rcPtr->chan: Assigned by caller. Dummy data here. */ rcPtr->chan = NULL; rcPtr->interp = interp; rcPtr->dead = 0; #ifdef TCL_THREADS rcPtr->thread = Tcl_GetCurrentThread(); #endif rcPtr->mode = mode; rcPtr->interest = 0; /* Initially no interest registered */ /* ASSERT: cmdpfxObj is a Tcl List */ rcPtr->cmd = TclListObjCopy(NULL, cmdpfxObj); Tcl_IncrRefCount(rcPtr->cmd); rcPtr->methods = Tcl_NewListObj(METH_WRITE + 1, NULL); while (mn <= METH_WRITE) { Tcl_ListObjAppendElement(NULL, rcPtr->methods, Tcl_NewStringObj(methodNames[mn++], -1)); } Tcl_IncrRefCount(rcPtr->methods); rcPtr->name = handleObj; Tcl_IncrRefCount(rcPtr->name); return rcPtr; } /* *---------------------------------------------------------------------- * * NextHandle -- * * This function is invoked to generate a channel handle for a new * reflected channel. * * Results: * A Tcl_Obj containing the string of the new channel handle. The * refcount of the returned object is -- zero --. * * Side effects: * May allocate memory. Mutex protected critical section locks out other * threads for a short time. * *---------------------------------------------------------------------- */ static Tcl_Obj * NextHandle(void) { /* * Count number of generated reflected channels. Used for id generation. * Ids are never reclaimed and there is no dealing with wrap around. On * the other hand, "unsigned long" should be big enough except for * absolute longrunners (generate a 100 ids per second => overflow will * occur in 1 1/3 years). */ TCL_DECLARE_MUTEX(rcCounterMutex) static unsigned long rcCounter = 0; Tcl_Obj *resObj; Tcl_MutexLock(&rcCounterMutex); resObj = Tcl_ObjPrintf("rc%lu", rcCounter); rcCounter++; Tcl_MutexUnlock(&rcCounterMutex); return resObj; } static void FreeReflectedChannel( ReflectedChannel *rcPtr) { Channel *chanPtr = (Channel *) rcPtr->chan; TclChannelRelease((Tcl_Channel)chanPtr); if (rcPtr->name) { Tcl_DecrRefCount(rcPtr->name); } if (rcPtr->methods) { Tcl_DecrRefCount(rcPtr->methods); } if (rcPtr->cmd) { Tcl_DecrRefCount(rcPtr->cmd); } ckfree(rcPtr); } /* *---------------------------------------------------------------------- * * InvokeTclMethod -- * * This function is used to invoke the Tcl level of a reflected channel. * It handles all the command assembly, invokation, and generic state and * result mgmt. It does *not* handle thread redirection; that is the * responsibility of clients of this function. * * Results: * Result code and data as returned by the method. * * Side effects: * Arbitrary, as it calls upon a Tcl script. * * Contract: * argOneObj.refCount >= 1 on entry and exit, if argOneObj != NULL * argTwoObj.refCount >= 1 on entry and exit, if argTwoObj != NULL * resObj.refCount in {0, 1, ...} * *---------------------------------------------------------------------- */ static int InvokeTclMethod( ReflectedChannel *rcPtr, MethodName method, Tcl_Obj *argOneObj, /* NULL'able */ Tcl_Obj *argTwoObj, /* NULL'able */ Tcl_Obj **resultObjPtr) /* NULL'able */ { Tcl_Obj *methObj = NULL; /* Method name in object form */ Tcl_InterpState sr; /* State of handler interp */ int result; /* Result code of method invokation */ Tcl_Obj *resObj = NULL; /* Result of method invokation. */ Tcl_Obj *cmd; if (rcPtr->dead) { /* * The channel is marked as dead. Bail out immediately, with an * appropriate error. */ if (resultObjPtr != NULL) { resObj = Tcl_NewStringObj(msg_dstlost,-1); *resultObjPtr = resObj; Tcl_IncrRefCount(resObj); } /* * Not touching argOneObj, argTwoObj, they have not been used. * See the contract as well. */ return TCL_ERROR; } /* * Insert method into the callback command, after the command prefix, * before the channel id. */ cmd = TclListObjCopy(NULL, rcPtr->cmd); Tcl_ListObjIndex(NULL, rcPtr->methods, method, &methObj); Tcl_ListObjAppendElement(NULL, cmd, methObj); Tcl_ListObjAppendElement(NULL, cmd, rcPtr->name); /* * Append the additional argument containing method specific details * behind the channel id. If specified. * * Because of the contract there is no need to increment the refcounts. * The objects will survive the Tcl_EvalObjv without change. */ if (argOneObj) { Tcl_ListObjAppendElement(NULL, cmd, argOneObj); if (argTwoObj) { Tcl_ListObjAppendElement(NULL, cmd, argTwoObj); } } /* * And run the handler... This is done in auch a manner which leaves any * existing state intact. */ Tcl_IncrRefCount(cmd); sr = Tcl_SaveInterpState(rcPtr->interp, 0 /* Dummy */); Tcl_Preserve(rcPtr->interp); result = Tcl_EvalObjEx(rcPtr->interp, cmd, TCL_EVAL_GLOBAL); /* * We do not try to extract the result information if the caller has no * interest in it. I.e. there is no need to put effort into creating * something which is discarded immediately after. */ if (resultObjPtr) { if (result == TCL_OK) { /* * Ok result taken as is, also if the caller requests that there * is no capture. */ resObj = Tcl_GetObjResult(rcPtr->interp); } else { /* * Non-ok result is always treated as an error. We have to capture * the full state of the result, including additional options. * * This is complex and ugly, and would be completely unnecessary * if we only added support for a TCL_FORBID_EXCEPTIONS flag. */ if (result != TCL_ERROR) { int cmdLen; const char *cmdString = Tcl_GetStringFromObj(cmd, &cmdLen); Tcl_IncrRefCount(cmd); Tcl_ResetResult(rcPtr->interp); Tcl_SetObjResult(rcPtr->interp, Tcl_ObjPrintf( "chan handler returned bad code: %d", result)); Tcl_LogCommandInfo(rcPtr->interp, cmdString, cmdString, cmdLen); Tcl_DecrRefCount(cmd); result = TCL_ERROR; } Tcl_AppendObjToErrorInfo(rcPtr->interp, Tcl_ObjPrintf( "\n (chan handler subcommand \"%s\")", methodNames[method])); resObj = MarshallError(rcPtr->interp); } Tcl_IncrRefCount(resObj); } Tcl_DecrRefCount(cmd); Tcl_RestoreInterpState(rcPtr->interp, sr); Tcl_Release(rcPtr->interp); /* * The resObj has a ref count of 1 at this location. This means that the * caller of InvokeTclMethod has to dispose of it (but only if it was * returned to it). */ if (resultObjPtr != NULL) { *resultObjPtr = resObj; } /* * There no need to handle the case where nothing is returned, because for * that case resObj was not set anyway. */ return result; } /* *---------------------------------------------------------------------- * * ErrnoReturn -- * * Checks a method error result if it returned an 'errno'. * * Results: * The negative errno found in the error result, or 0. * * Side effects: * None. * * Users: * ReflectInput/Output(), to enable the signaling of EAGAIN * on 0-sized short reads/writes. * *---------------------------------------------------------------------- */ static int ErrnoReturn( ReflectedChannel *rcPtr, Tcl_Obj *resObj) { int code; Tcl_InterpState sr; /* State of handler interp */ if (rcPtr->dead) { return 0; } sr = Tcl_SaveInterpState(rcPtr->interp, 0 /* Dummy */); UnmarshallErrorResult(rcPtr->interp, resObj); resObj = Tcl_GetObjResult(rcPtr->interp); if (((Tcl_GetIntFromObj(rcPtr->interp, resObj, &code) != TCL_OK) || (code >= 0))) { if (strcmp("EAGAIN", Tcl_GetString(resObj)) == 0) { code = -EAGAIN; } else { code = 0; } } Tcl_RestoreInterpState(rcPtr->interp, sr); return code; } /* *---------------------------------------------------------------------- * * GetReflectedChannelMap -- * * Gets and potentially initializes the reflected channel map for an * interpreter. * * Results: * A pointer to the map created, for use by the caller. * * Side effects: * Initializes the reflected channel map for an interpreter. * *---------------------------------------------------------------------- */ static ReflectedChannelMap * GetReflectedChannelMap( Tcl_Interp *interp) { ReflectedChannelMap *rcmPtr = Tcl_GetAssocData(interp, RCMKEY, NULL); if (rcmPtr == NULL) { rcmPtr = ckalloc(sizeof(ReflectedChannelMap)); Tcl_InitHashTable(&rcmPtr->map, TCL_STRING_KEYS); Tcl_SetAssocData(interp, RCMKEY, (Tcl_InterpDeleteProc *) DeleteReflectedChannelMap, rcmPtr); } return rcmPtr; } /* *---------------------------------------------------------------------- * * DeleteReflectedChannelMap -- * * Deletes the channel table for an interpreter, closing any open * channels whose refcount reaches zero. This procedure is invoked when * an interpreter is deleted, via the AssocData cleanup mechanism. * * Results: * None. * * Side effects: * Deletes the hash table of channels. May close channels. May flush * output on closed channels. Removes any channeEvent handlers that were * registered in this interpreter. * *---------------------------------------------------------------------- */ static void MarkDead( ReflectedChannel *rcPtr) { if (rcPtr->dead) { return; } if (rcPtr->name) { Tcl_DecrRefCount(rcPtr->name); rcPtr->name = NULL; } if (rcPtr->methods) { Tcl_DecrRefCount(rcPtr->methods); rcPtr->methods = NULL; } if (rcPtr->cmd) { Tcl_DecrRefCount(rcPtr->cmd); rcPtr->cmd = NULL; } rcPtr->dead = 1; } static void DeleteReflectedChannelMap( ClientData clientData, /* The per-interpreter data structure. */ Tcl_Interp *interp) /* The interpreter being deleted. */ { ReflectedChannelMap *rcmPtr = clientData; /* The map */ Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ ReflectedChannel *rcPtr; Tcl_Channel chan; #ifdef TCL_THREADS ForwardingResult *resultPtr; ForwardingEvent *evPtr; ForwardParam *paramPtr; #endif /* * Delete all entries. The channels may have been closed already, or will * be closed later, by the standard IO finalization of an interpreter * under destruction. Except for the channels which were moved to a * different interpreter and/or thread. They do not exist from the IO * systems point of view and will not get closed. Therefore mark all as * dead so that any future access will cause a proper error. For channels * in a different thread we actually do the same as * DeleteThreadReflectedChannelMap(), just restricted to the channels of * this interp. */ for (hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch); hPtr != NULL; hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch)) { chan = Tcl_GetHashValue(hPtr); rcPtr = Tcl_GetChannelInstanceData(chan); MarkDead(rcPtr); Tcl_DeleteHashEntry(hPtr); } Tcl_DeleteHashTable(&rcmPtr->map); ckfree(&rcmPtr->map); #ifdef TCL_THREADS /* * The origin interpreter for one or more reflected channels is gone. */ /* * Go through the list of pending results and cancel all whose events were * destined for this interpreter. While this is in progress we block any * other access to the list of pending results. */ Tcl_MutexLock(&rcForwardMutex); for (resultPtr = forwardList; resultPtr != NULL; resultPtr = resultPtr->nextPtr) { if (resultPtr->dsti != interp) { /* * Ignore results/events for other interpreters. */ continue; } /* * The receiver for the event exited, before processing the event. We * detach the result now, wake the originator up and signal failure. * * Attention: Results may have been detached already, by either the * receiver, or this thread, as part of other parts in the thread * teardown. Such results are ignored. See ticket [b47b176adf] for the * identical race condition in Tcl 8.6 IORTrans. */ evPtr = resultPtr->evPtr; /* Basic crash safety until this routine can get revised [3411310] */ if (evPtr == NULL) { continue; } paramPtr = evPtr->param; if (!evPtr) { continue; } evPtr->resultPtr = NULL; resultPtr->evPtr = NULL; resultPtr->result = TCL_ERROR; ForwardSetStaticError(paramPtr, msg_send_dstlost); Tcl_ConditionNotify(&resultPtr->done); } Tcl_MutexUnlock(&rcForwardMutex); /* * Get the map of all channels handled by the current thread. This is a * ReflectedChannelMap, but on a per-thread basis, not per-interp. Go * through the channels and remove all which were handled by this * interpreter. They have already been marked as dead. */ rcmPtr = GetThreadReflectedChannelMap(); for (hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { chan = Tcl_GetHashValue(hPtr); rcPtr = Tcl_GetChannelInstanceData(chan); if (rcPtr->interp != interp) { /* * Ignore entries for other interpreters. */ continue; } MarkDead(rcPtr); Tcl_DeleteHashEntry(hPtr); } #endif } #ifdef TCL_THREADS /* *---------------------------------------------------------------------- * * GetThreadReflectedChannelMap -- * * Gets and potentially initializes the reflected channel map for a * thread. * * Results: * A pointer to the map created, for use by the caller. * * Side effects: * Initializes the reflected channel map for a thread. * *---------------------------------------------------------------------- */ static ReflectedChannelMap * GetThreadReflectedChannelMap(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!tsdPtr->rcmPtr) { tsdPtr->rcmPtr = ckalloc(sizeof(ReflectedChannelMap)); Tcl_InitHashTable(&tsdPtr->rcmPtr->map, TCL_STRING_KEYS); Tcl_CreateThreadExitHandler(DeleteThreadReflectedChannelMap, NULL); } return tsdPtr->rcmPtr; } /* *---------------------------------------------------------------------- * * DeleteThreadReflectedChannelMap -- * * Deletes the channel table for a thread. This procedure is invoked when * a thread is deleted. The channels have already been marked as dead, in * DeleteReflectedChannelMap(). * * Results: * None. * * Side effects: * Deletes the hash table of channels. * *---------------------------------------------------------------------- */ static void DeleteThreadReflectedChannelMap( ClientData clientData) /* The per-thread data structure. */ { Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ Tcl_ThreadId self = Tcl_GetCurrentThread(); ReflectedChannelMap *rcmPtr; /* The map */ ForwardingResult *resultPtr; /* * The origin thread for one or more reflected channels is gone. * NOTE: If this function is called due to a thread getting killed the * per-interp DeleteReflectedChannelMap is apparently not called. */ /* * Go through the list of pending results and cancel all whose events were * destined for this thread. While this is in progress we block any * other access to the list of pending results. */ Tcl_MutexLock(&rcForwardMutex); for (resultPtr = forwardList; resultPtr != NULL; resultPtr = resultPtr->nextPtr) { ForwardingEvent *evPtr; ForwardParam *paramPtr; if (resultPtr->dst != self) { /* * Ignore results/events for other threads. */ continue; } /* * The receiver for the event exited, before processing the event. We * detach the result now, wake the originator up and signal failure. * * Attention: Results may have been detached already, by either the * receiver, or this thread, as part of other parts in the thread * teardown. Such results are ignored. See ticket [b47b176adf] for the * identical race condition in Tcl 8.6 IORTrans. */ evPtr = resultPtr->evPtr; /* Basic crash safety until this routine can get revised [3411310] */ if (evPtr == NULL ) { continue; } paramPtr = evPtr->param; if (!evPtr) { continue; } evPtr->resultPtr = NULL; resultPtr->evPtr = NULL; resultPtr->result = TCL_ERROR; ForwardSetStaticError(paramPtr, msg_send_dstlost); Tcl_ConditionNotify(&resultPtr->done); } Tcl_MutexUnlock(&rcForwardMutex); /* * Run over the event queue of this thread and remove all ReflectEvent's * still pending. These are inbound events for reflected channels this * thread owns but doesn't handle. The inverse of the channel map * actually. */ Tcl_DeleteEvents(ReflectEventDelete, NULL); /* * Get the map of all channels handled by the current thread. This is a * ReflectedChannelMap, but on a per-thread basis, not per-interp. Go * through the channels, remove all, mark them as dead. */ rcmPtr = GetThreadReflectedChannelMap(); for (hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch); hPtr != NULL; hPtr = Tcl_FirstHashEntry(&rcmPtr->map, &hSearch)) { Tcl_Channel chan = Tcl_GetHashValue(hPtr); ReflectedChannel *rcPtr = Tcl_GetChannelInstanceData(chan); MarkDead(rcPtr); Tcl_DeleteHashEntry(hPtr); } ckfree(rcmPtr); } static void ForwardOpToHandlerThread( ReflectedChannel *rcPtr, /* Channel instance */ ForwardedOperation op, /* Forwarded driver operation */ const void *param) /* Arguments */ { /* * Core of the communication from OWNER to HANDLER thread. * The receiver is ForwardProc() below. */ Tcl_ThreadId dst = rcPtr->thread; ForwardingEvent *evPtr; ForwardingResult *resultPtr; /* * We gather the lock early. This allows us to check the liveness of the * channel without interference from DeleteThreadReflectedChannelMap(). */ Tcl_MutexLock(&rcForwardMutex); if (rcPtr->dead) { /* * The channel is marked as dead. Bail out immediately, with an * appropriate error. Do not forget to unlock the mutex on this path. */ ForwardSetStaticError((ForwardParam *) param, msg_send_dstlost); Tcl_MutexUnlock(&rcForwardMutex); return; } /* * Create and initialize the event and data structures. */ evPtr = ckalloc(sizeof(ForwardingEvent)); resultPtr = ckalloc(sizeof(ForwardingResult)); evPtr->event.proc = ForwardProc; evPtr->resultPtr = resultPtr; evPtr->op = op; evPtr->rcPtr = rcPtr; evPtr->param = (ForwardParam *) param; resultPtr->src = Tcl_GetCurrentThread(); resultPtr->dst = dst; resultPtr->dsti = rcPtr->interp; resultPtr->done = NULL; resultPtr->result = -1; resultPtr->evPtr = evPtr; /* * Now execute the forward. */ TclSpliceIn(resultPtr, forwardList); /* Do not unlock here. That is done by the ConditionWait */ /* * Ensure cleanup of the event if the origin thread exits while this event * is pending or in progress. Exit of the destination thread is handled by * DeleteThreadReflectedChannelMap(), this is set up by * GetThreadReflectedChannelMap(). This is what we use the 'forwardList' * (see above) for. */ Tcl_CreateThreadExitHandler(SrcExitProc, evPtr); /* * Queue the event and poke the other thread's notifier. */ Tcl_ThreadQueueEvent(dst, (Tcl_Event *) evPtr, TCL_QUEUE_TAIL); Tcl_ThreadAlert(dst); /* * (*) Block until the handler thread has either processed the transfer or * rejected it. */ while (resultPtr->result < 0) { /* * NOTE (1): Is it possible that the current thread goes away while * waiting here? IOW Is it possible that "SrcExitProc" is called while * we are here? See complementary note (2) in "SrcExitProc" * * The ConditionWait unlocks the mutex during the wait and relocks it * immediately after. */ Tcl_ConditionWait(&resultPtr->done, &rcForwardMutex, NULL); } /* * Unlink result from the forwarder list. No need to lock. Either still * locked, or locked by the ConditionWait */ TclSpliceOut(resultPtr, forwardList); resultPtr->nextPtr = NULL; resultPtr->prevPtr = NULL; Tcl_MutexUnlock(&rcForwardMutex); Tcl_ConditionFinalize(&resultPtr->done); /* * Kill the cleanup handler now, and the result structure as well, before * returning the success code. * * Note: The event structure has already been deleted. */ Tcl_DeleteThreadExitHandler(SrcExitProc, evPtr); ckfree(resultPtr); } static int ForwardProc( Tcl_Event *evGPtr, int mask) { /* * HANDLER thread. * The receiver part for the operations coming from the OWNER thread. * See ForwardOpToHandlerThread() for the transmitter. * * Notes regarding access to the referenced data. * * In principle the data belongs to the originating thread (see * evPtr->src), however this thread is currently blocked at (*), i.e. * quiescent. Because of this we can treat the data as belonging to us, * without fear of race conditions. I.e. we can read and write as we like. * * The only thing we cannot be sure of is the resultPtr. This can be be * NULLed if the originating thread went away while the event is handled * here now. */ ForwardingEvent *evPtr = (ForwardingEvent *) evGPtr; ForwardingResult *resultPtr = evPtr->resultPtr; ReflectedChannel *rcPtr = evPtr->rcPtr; Tcl_Interp *interp = rcPtr->interp; ForwardParam *paramPtr = evPtr->param; Tcl_Obj *resObj = NULL; /* Interp result of InvokeTclMethod */ ReflectedChannelMap *rcmPtr;/* Map of reflected channels with handlers in * this interp. */ Tcl_HashEntry *hPtr; /* Entry in the above map */ /* * Ignore the event if no one is waiting for its result anymore. */ if (!resultPtr) { return 1; } paramPtr->base.code = TCL_OK; paramPtr->base.msgStr = NULL; paramPtr->base.mustFree = 0; switch (evPtr->op) { /* * The destination thread for the following operations is * rcPtr->thread, which contains rcPtr->interp, the interp we have to * call upon for the driver. */ case ForwardedClose: { /* * No parameters/results. */ if (InvokeTclMethod(rcPtr, METH_FINAL, NULL, NULL, &resObj)!=TCL_OK) { ForwardSetObjError(paramPtr, resObj); } /* * Freeing is done here, in the origin thread, callback command * objects belong to this thread. Deallocating them in a different * thread is not allowed * * We remove the channel from both interpreter and thread maps before * releasing the memory, to prevent future accesses (like by * 'postevent') from finding and dereferencing a dangling pointer. */ rcmPtr = GetReflectedChannelMap(interp); hPtr = Tcl_FindHashEntry(&rcmPtr->map, Tcl_GetChannelName(rcPtr->chan)); Tcl_DeleteHashEntry(hPtr); rcmPtr = GetThreadReflectedChannelMap(); hPtr = Tcl_FindHashEntry(&rcmPtr->map, Tcl_GetChannelName(rcPtr->chan)); Tcl_DeleteHashEntry(hPtr); MarkDead(rcPtr); break; } case ForwardedInput: { Tcl_Obj *toReadObj = Tcl_NewIntObj(paramPtr->input.toRead); Tcl_IncrRefCount(toReadObj); Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_READ, toReadObj, NULL, &resObj)!=TCL_OK){ int code = ErrnoReturn(rcPtr, resObj); if (code < 0) { paramPtr->base.code = code; } else { ForwardSetObjError(paramPtr, resObj); } paramPtr->input.toRead = -1; } else { /* * Process a regular result. */ int bytec; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); if (paramPtr->input.toRead < bytec) { ForwardSetStaticError(paramPtr, msg_read_toomuch); paramPtr->input.toRead = -1; } else { if (bytec > 0) { memcpy(paramPtr->input.buf, bytev, (size_t) bytec); } paramPtr->input.toRead = bytec; } } Tcl_Release(rcPtr); Tcl_DecrRefCount(toReadObj); break; } case ForwardedOutput: { Tcl_Obj *bufObj = Tcl_NewByteArrayObj((unsigned char *) paramPtr->output.buf, paramPtr->output.toWrite); Tcl_IncrRefCount(bufObj); Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_WRITE, bufObj, NULL, &resObj) != TCL_OK) { int code = ErrnoReturn(rcPtr, resObj); if (code < 0) { paramPtr->base.code = code; } else { ForwardSetObjError(paramPtr, resObj); } paramPtr->output.toWrite = -1; } else { /* * Process a regular result. */ int written; if (Tcl_GetIntFromObj(interp, resObj, &written) != TCL_OK) { Tcl_DecrRefCount(resObj); resObj = MarshallError(interp); ForwardSetObjError(paramPtr, resObj); paramPtr->output.toWrite = -1; } else if (written==0 || paramPtr->output.toWriteoutput.toWrite = -1; } else { paramPtr->output.toWrite = written; } } Tcl_Release(rcPtr); Tcl_DecrRefCount(bufObj); break; } case ForwardedSeek: { Tcl_Obj *offObj = Tcl_NewWideIntObj(paramPtr->seek.offset); Tcl_Obj *baseObj = Tcl_NewStringObj( (paramPtr->seek.seekMode==SEEK_SET) ? "start" : (paramPtr->seek.seekMode==SEEK_CUR) ? "current" : "end", -1); Tcl_IncrRefCount(offObj); Tcl_IncrRefCount(baseObj); Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_SEEK, offObj, baseObj, &resObj)!=TCL_OK){ ForwardSetObjError(paramPtr, resObj); paramPtr->seek.offset = -1; } else { /* * Process a regular result. If the type is wrong this may change * into an error. */ Tcl_WideInt newLoc; if (Tcl_GetWideIntFromObj(interp, resObj, &newLoc) == TCL_OK) { if (newLoc < Tcl_LongAsWide(0)) { ForwardSetStaticError(paramPtr, msg_seek_beforestart); paramPtr->seek.offset = -1; } else { paramPtr->seek.offset = newLoc; } } else { Tcl_DecrRefCount(resObj); resObj = MarshallError(interp); ForwardSetObjError(paramPtr, resObj); paramPtr->seek.offset = -1; } } Tcl_Release(rcPtr); Tcl_DecrRefCount(offObj); Tcl_DecrRefCount(baseObj); break; } case ForwardedWatch: { Tcl_Obj *maskObj = DecodeEventMask(paramPtr->watch.mask); /* assert maskObj.refCount == 1 */ Tcl_Preserve(rcPtr); (void) InvokeTclMethod(rcPtr, METH_WATCH, maskObj, NULL, NULL); Tcl_DecrRefCount(maskObj); Tcl_Release(rcPtr); break; } case ForwardedBlock: { Tcl_Obj *blockObj = Tcl_NewBooleanObj(!paramPtr->block.nonblocking); Tcl_IncrRefCount(blockObj); Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_BLOCKING, blockObj, NULL, &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); } Tcl_Release(rcPtr); Tcl_DecrRefCount(blockObj); break; } case ForwardedSetOpt: { Tcl_Obj *optionObj = Tcl_NewStringObj(paramPtr->setOpt.name, -1); Tcl_Obj *valueObj = Tcl_NewStringObj(paramPtr->setOpt.value, -1); Tcl_IncrRefCount(optionObj); Tcl_IncrRefCount(valueObj); Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_CONFIGURE, optionObj, valueObj, &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); } Tcl_Release(rcPtr); Tcl_DecrRefCount(optionObj); Tcl_DecrRefCount(valueObj); break; } case ForwardedGetOpt: { /* * Retrieve the value of one option. */ Tcl_Obj *optionObj = Tcl_NewStringObj(paramPtr->getOpt.name, -1); Tcl_IncrRefCount(optionObj); Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_CGET, optionObj, NULL, &resObj)!=TCL_OK){ ForwardSetObjError(paramPtr, resObj); } else { TclDStringAppendObj(paramPtr->getOpt.value, resObj); } Tcl_Release(rcPtr); Tcl_DecrRefCount(optionObj); break; } case ForwardedGetOptAll: /* * Retrieve all options. */ Tcl_Preserve(rcPtr); if (InvokeTclMethod(rcPtr, METH_CGETALL, NULL, NULL, &resObj) != TCL_OK){ ForwardSetObjError(paramPtr, resObj); } else { /* * Extract list, validate that it is a list, and #elements. See * NOTE (4) as well. */ int listc; Tcl_Obj **listv; if (Tcl_ListObjGetElements(interp, resObj, &listc, &listv) != TCL_OK) { Tcl_DecrRefCount(resObj); resObj = MarshallError(interp); ForwardSetObjError(paramPtr, resObj); } else if ((listc % 2) == 1) { /* * Odd number of elements is wrong. [x]. */ char *buf = ckalloc(200); sprintf(buf, "{Expected list with even number of elements, got %d %s instead}", listc, (listc == 1 ? "element" : "elements")); ForwardSetDynamicError(paramPtr, buf); } else { int len; const char *str = Tcl_GetStringFromObj(resObj, &len); if (len) { TclDStringAppendLiteral(paramPtr->getOpt.value, " "); Tcl_DStringAppend(paramPtr->getOpt.value, str, len); } } } Tcl_Release(rcPtr); break; default: /* * Bad operation code. */ Tcl_Panic("Bad operation code in ForwardProc"); break; } /* * Remove the reference we held on the result of the invoke, if we had * such. */ if (resObj != NULL) { Tcl_DecrRefCount(resObj); } if (resultPtr) { /* * Report the forwarding result synchronously to the waiting caller. * This unblocks (*) as well. This is wrapped into a conditional * because the caller may have exited in the mean time. */ Tcl_MutexLock(&rcForwardMutex); resultPtr->result = TCL_OK; Tcl_ConditionNotify(&resultPtr->done); Tcl_MutexUnlock(&rcForwardMutex); } return 1; } static void SrcExitProc( ClientData clientData) { ForwardingEvent *evPtr = clientData; ForwardingResult *resultPtr; ForwardParam *paramPtr; /* * NOTE (2): Can this handler be called with the originator blocked? */ /* * The originator for the event exited. It is not sure if this can happen, * as the originator should be blocked at (*) while the event is in * transit/pending. * * We make sure that the event cannot refer to the result anymore, remove * it from the list of pending results and free the structure. Locking the * access ensures that we cannot get in conflict with "ForwardProc", * should it already execute the event. */ Tcl_MutexLock(&rcForwardMutex); resultPtr = evPtr->resultPtr; paramPtr = evPtr->param; evPtr->resultPtr = NULL; resultPtr->evPtr = NULL; resultPtr->result = TCL_ERROR; ForwardSetStaticError(paramPtr, msg_send_originlost); /* * See below: TclSpliceOut(resultPtr, forwardList); */ Tcl_MutexUnlock(&rcForwardMutex); /* * This unlocks (*). The structure will be spliced out and freed by * "ForwardProc". Maybe. */ Tcl_ConditionNotify(&resultPtr->done); } static void ForwardSetObjError( ForwardParam *paramPtr, Tcl_Obj *obj) { int len; const char *msgStr = Tcl_GetStringFromObj(obj, &len); len++; ForwardSetDynamicError(paramPtr, ckalloc(len)); memcpy(paramPtr->base.msgStr, msgStr, (unsigned) len); } #endif /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * indent-tabs-mode: nil * End: */ tcl8.6.5/generic/tclStringTrim.h0000644000175000017500000000224512663660065016164 0ustar sergeisergei/* * tclStringTrim.h -- * * This file contains the definition of what characters are to be trimmed * from a string by [string trim] by default. It's only needed by Tcl's * implementation; it does not form a public or private API at all. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-2000 Scriptics Corporation. * Copyright (c) 2002 ActiveState Corporation. * Copyright (c) 2003-2013 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef TCL_STRING_TRIM_H #define TCL_STRING_TRIM_H /* * Default set of characters to trim in [string trim] and friends. This is a * UTF-8 literal string containing all Unicode space characters. [TIP #413] */ MODULE_SCOPE const char tclDefaultTrimSet[]; /* * The whitespace trimming set used when [concat]enating. This is a subset of * the above, and deliberately so. */ #define CONCAT_TRIM_SET " \f\v\r\t\n" #endif /* TCL_STRING_TRIM_H */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclParse.c0000644000175000017500000022235512663660065015135 0ustar sergeisergei/* * tclParse.c -- * * This file contains functions that parse Tcl scripts. They do so in a * general-purpose fashion that can be used for many different purposes, * including compilation, direct execution, code analysis, etc. * * Copyright (c) 1997 Sun Microsystems, Inc. * Copyright (c) 1998-2000 Ajuba Solutions. * Contributions from Don Porter, NIST, 2002. (not subject to US copyright) * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclParse.h" #include /* * The following table provides parsing information about each possible 8-bit * character. The table is designed to be referenced with either signed or * unsigned characters, so it has 384 entries. The first 128 entries * correspond to negative character values, the next 256 correspond to * positive character values. The last 128 entries are identical to the first * 128. The table is always indexed with a 128-byte offset (the 128th entry * corresponds to a character value of 0). * * The macro CHAR_TYPE is used to index into the table and return information * about its character argument. The following return values are defined. * * TYPE_NORMAL - All characters that don't have special significance to * the Tcl parser. * TYPE_SPACE - The character is a whitespace character other than * newline. * TYPE_COMMAND_END - Character is newline or semicolon. * TYPE_SUBS - Character begins a substitution or has other special * meaning in ParseTokens: backslash, dollar sign, or * open bracket. * TYPE_QUOTE - Character is a double quote. * TYPE_CLOSE_PAREN - Character is a right parenthesis. * TYPE_CLOSE_BRACK - Character is a right square bracket. * TYPE_BRACE - Character is a curly brace (either left or right). */ const char tclCharTypeTable[] = { /* * Negative character values, from -128 to -1: */ TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, /* * Positive character values, from 0-127: */ TYPE_SUBS, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_SPACE, TYPE_COMMAND_END, TYPE_SPACE, TYPE_SPACE, TYPE_SPACE, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_SPACE, TYPE_NORMAL, TYPE_QUOTE, TYPE_NORMAL, TYPE_SUBS, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_CLOSE_PAREN, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_COMMAND_END, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_SUBS, TYPE_SUBS, TYPE_CLOSE_BRACK, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_BRACE, TYPE_NORMAL, TYPE_BRACE, TYPE_NORMAL, TYPE_NORMAL, /* * Large unsigned character values, from 128-255: */ TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, TYPE_NORMAL, }; /* * Prototypes for local functions defined in this file: */ static inline int CommandComplete(const char *script, int numBytes); static int ParseComment(const char *src, int numBytes, Tcl_Parse *parsePtr); static int ParseTokens(const char *src, int numBytes, int mask, int flags, Tcl_Parse *parsePtr); static int ParseWhiteSpace(const char *src, int numBytes, int *incompletePtr, char *typePtr); /* *---------------------------------------------------------------------- * * TclParseInit -- * * Initialize the fields of a Tcl_Parse struct. * * Results: * None. * * Side effects: * The Tcl_Parse struct pointed to by parsePtr gets initialized. * *---------------------------------------------------------------------- */ void TclParseInit( Tcl_Interp *interp, /* Interpreter to use for error reporting */ const char *start, /* Start of string to be parsed. */ int numBytes, /* Total number of bytes in string. If < 0, * the script consists of all bytes up to the * first null character. */ Tcl_Parse *parsePtr) /* Points to struct to initialize */ { parsePtr->numWords = 0; parsePtr->tokenPtr = parsePtr->staticTokens; parsePtr->numTokens = 0; parsePtr->tokensAvailable = NUM_STATIC_TOKENS; parsePtr->string = start; parsePtr->end = start + numBytes; parsePtr->term = parsePtr->end; parsePtr->interp = interp; parsePtr->incomplete = 0; parsePtr->errorType = TCL_PARSE_SUCCESS; } /* *---------------------------------------------------------------------- * * Tcl_ParseCommand -- * * Given a string, this function parses the first Tcl command in the * string and returns information about the structure of the command. * * Results: * The return value is TCL_OK if the command was parsed successfully and * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then an * error message is left in its result. On a successful return, parsePtr * is filled in with information about the command that was parsed. * * Side effects: * If there is insufficient space in parsePtr to hold all the information * about the command, then additional space is malloc-ed. If the function * returns TCL_OK then the caller must eventually invoke Tcl_FreeParse to * release any additional space that was allocated. * *---------------------------------------------------------------------- */ int Tcl_ParseCommand( Tcl_Interp *interp, /* Interpreter to use for error reporting; if * NULL, then no error message is provided. */ const char *start, /* First character of string containing one or * more Tcl commands. */ register int numBytes, /* Total number of bytes in string. If < 0, * the script consists of all bytes up to the * first null character. */ int nested, /* Non-zero means this is a nested command: * close bracket should be considered a * command terminator. If zero, then close * bracket has no special meaning. */ register Tcl_Parse *parsePtr) /* Structure to fill in with information about * the parsed command; any previous * information in the structure is ignored. */ { register const char *src; /* Points to current character in the * command. */ char type; /* Result returned by CHAR_TYPE(*src). */ Tcl_Token *tokenPtr; /* Pointer to token being filled in. */ int wordIndex; /* Index of word token for current word. */ int terminators; /* CHAR_TYPE bits that indicate the end of a * command. */ const char *termPtr; /* Set by Tcl_ParseBraces/QuotedString to * point to char after terminating one. */ int scanned; if ((start == NULL) && (numBytes != 0)) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can't parse a NULL pointer", -1)); } return TCL_ERROR; } if (numBytes < 0) { numBytes = strlen(start); } TclParseInit(interp, start, numBytes, parsePtr); parsePtr->commentStart = NULL; parsePtr->commentSize = 0; parsePtr->commandStart = NULL; parsePtr->commandSize = 0; if (nested != 0) { terminators = TYPE_COMMAND_END | TYPE_CLOSE_BRACK; } else { terminators = TYPE_COMMAND_END; } /* * Parse any leading space and comments before the first word of the * command. */ scanned = ParseComment(start, numBytes, parsePtr); src = (start + scanned); numBytes -= scanned; if (numBytes == 0) { if (nested) { parsePtr->incomplete = nested; } } /* * The following loop parses the words of the command, one word in each * iteration through the loop. */ parsePtr->commandStart = src; while (1) { int expandWord = 0; /* * Create the token for the word. */ TclGrowParseTokenArray(parsePtr, 1); wordIndex = parsePtr->numTokens; tokenPtr = &parsePtr->tokenPtr[wordIndex]; tokenPtr->type = TCL_TOKEN_WORD; /* * Skip white space before the word. Also skip a backslash-newline * sequence: it should be treated just like white space. */ scanned = ParseWhiteSpace(src,numBytes, &parsePtr->incomplete, &type); src += scanned; numBytes -= scanned; if (numBytes == 0) { parsePtr->term = src; break; } if ((type & terminators) != 0) { parsePtr->term = src; src++; break; } tokenPtr->start = src; parsePtr->numTokens++; parsePtr->numWords++; /* * At this point the word can have one of four forms: something * enclosed in quotes, something enclosed in braces, and expanding * word, or an unquoted word (anything else). */ parseWord: if (*src == '"') { if (Tcl_ParseQuotedString(interp, src, numBytes, parsePtr, 1, &termPtr) != TCL_OK) { goto error; } src = termPtr; numBytes = parsePtr->end - src; } else if (*src == '{') { int expIdx = wordIndex + 1; Tcl_Token *expPtr; if (Tcl_ParseBraces(interp, src, numBytes, parsePtr, 1, &termPtr) != TCL_OK) { goto error; } src = termPtr; numBytes = parsePtr->end - src; /* * Check whether the braces contained the word expansion prefix * {*} */ expPtr = &parsePtr->tokenPtr[expIdx]; if ((0 == expandWord) /* Haven't seen prefix already */ && (1 == parsePtr->numTokens - expIdx) /* Only one token */ && (((1 == (size_t) expPtr->size) /* Same length as prefix */ && (expPtr->start[0] == '*'))) /* Is the prefix */ && (numBytes > 0) && (0 == ParseWhiteSpace(termPtr, numBytes, &parsePtr->incomplete, &type)) && (type != TYPE_COMMAND_END) /* Non-whitespace follows */) { expandWord = 1; parsePtr->numTokens--; goto parseWord; } } else { /* * This is an unquoted word. Call ParseTokens and let it do all of * the work. */ if (ParseTokens(src, numBytes, TYPE_SPACE|terminators, TCL_SUBST_ALL, parsePtr) != TCL_OK) { goto error; } src = parsePtr->term; numBytes = parsePtr->end - src; } /* * Finish filling in the token for the word and check for the special * case of a word consisting of a single range of literal text. */ tokenPtr = &parsePtr->tokenPtr[wordIndex]; tokenPtr->size = src - tokenPtr->start; tokenPtr->numComponents = parsePtr->numTokens - (wordIndex + 1); if (expandWord) { int i, isLiteral = 1; /* * When a command includes a word that is an expanded literal; for * example, {*}{1 2 3}, the parser performs that expansion * immediately, generating several TCL_TOKEN_SIMPLE_WORDs instead * of a single TCL_TOKEN_EXPAND_WORD that the Tcl_ParseCommand() * caller might have to expand. This notably makes it simpler for * those callers that wish to track line endings, such as those * that implement key parts of TIP 280. * * First check whether the thing to be expanded is a literal, * in the sense of being composed entirely of TCL_TOKEN_TEXT * tokens. */ for (i = 1; i <= tokenPtr->numComponents; i++) { if (tokenPtr[i].type != TCL_TOKEN_TEXT) { isLiteral = 0; break; } } if (isLiteral) { int elemCount = 0, code = TCL_OK, literal = 1; const char *nextElem, *listEnd, *elemStart; /* * The word to be expanded is a literal, so determine the * boundaries of the literal string to be treated as a list * and expanded. That literal string starts at * tokenPtr[1].start, and includes all bytes up to, but not * including (tokenPtr[tokenPtr->numComponents].start + * tokenPtr[tokenPtr->numComponents].size) */ listEnd = (tokenPtr[tokenPtr->numComponents].start + tokenPtr[tokenPtr->numComponents].size); nextElem = tokenPtr[1].start; /* * Step through the literal string, parsing and counting list * elements. */ while (nextElem < listEnd) { int size; code = TclFindElement(NULL, nextElem, listEnd - nextElem, &elemStart, &nextElem, &size, &literal); if ((code != TCL_OK) || !literal) { break; } if (elemStart < listEnd) { elemCount++; } } if ((code != TCL_OK) || !literal) { /* * Some list element could not be parsed, or is not * present as a literal substring of the script. The * compiler cannot handle list elements that get generated * by a call to TclCopyAndCollapse(). Defer the * handling of this to compile/eval time, where code is * already in place to report the "attempt to expand a * non-list" error or expand lists that require * substitution. */ tokenPtr->type = TCL_TOKEN_EXPAND_WORD; } else if (elemCount == 0) { /* * We are expanding a literal empty list. This means that * the expanding word completely disappears, leaving no * word generated this pass through the loop. Adjust * accounting appropriately. */ parsePtr->numWords--; parsePtr->numTokens = wordIndex; } else { /* * Recalculate the number of Tcl_Tokens needed to store * tokens representing the expanded list. */ const char *listStart; int growthNeeded = wordIndex + 2*elemCount - parsePtr->numTokens; parsePtr->numWords += elemCount - 1; if (growthNeeded > 0) { TclGrowParseTokenArray(parsePtr, growthNeeded); tokenPtr = &parsePtr->tokenPtr[wordIndex]; } parsePtr->numTokens = wordIndex + 2*elemCount; /* * Generate a TCL_TOKEN_SIMPLE_WORD token sequence for * each element of the literal list we are expanding in * place. Take care with the start and size fields of each * token so they point to the right literal characters in * the original script to represent the right expanded * word value. */ listStart = nextElem = tokenPtr[1].start; while (nextElem < listEnd) { int quoted; tokenPtr->type = TCL_TOKEN_SIMPLE_WORD; tokenPtr->numComponents = 1; tokenPtr++; tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->numComponents = 0; TclFindElement(NULL, nextElem, listEnd - nextElem, &(tokenPtr->start), &nextElem, &(tokenPtr->size), NULL); quoted = (tokenPtr->start[-1] == '{' || tokenPtr->start[-1] == '"') && tokenPtr->start > listStart; tokenPtr[-1].start = tokenPtr->start - quoted; tokenPtr[-1].size = tokenPtr->start + tokenPtr->size - tokenPtr[-1].start + quoted; tokenPtr++; } } } else { /* * The word to be expanded is not a literal, so defer * expansion to compile/eval time by marking with a * TCL_TOKEN_EXPAND_WORD token. */ tokenPtr->type = TCL_TOKEN_EXPAND_WORD; } } else if ((tokenPtr->numComponents == 1) && (tokenPtr[1].type == TCL_TOKEN_TEXT)) { tokenPtr->type = TCL_TOKEN_SIMPLE_WORD; } /* * Do two additional checks: (a) make sure we're really at the end of * a word (there might have been garbage left after a quoted or braced * word), and (b) check for the end of the command. */ scanned = ParseWhiteSpace(src,numBytes, &parsePtr->incomplete, &type); if (scanned) { src += scanned; numBytes -= scanned; continue; } if (numBytes == 0) { parsePtr->term = src; break; } if ((type & terminators) != 0) { parsePtr->term = src; src++; break; } if (src[-1] == '"') { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "extra characters after close-quote", -1)); } parsePtr->errorType = TCL_PARSE_QUOTE_EXTRA; } else { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "extra characters after close-brace", -1)); } parsePtr->errorType = TCL_PARSE_BRACE_EXTRA; } parsePtr->term = src; goto error; } parsePtr->commandSize = src - parsePtr->commandStart; return TCL_OK; error: Tcl_FreeParse(parsePtr); parsePtr->commandSize = parsePtr->end - parsePtr->commandStart; return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclIsSpaceProc -- * * Report whether byte is in the set of whitespace characters used by * Tcl to separate words in scripts or elements in lists. * * Results: * Returns 1, if byte is in the set, 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclIsSpaceProc( char byte) { return CHAR_TYPE(byte) & (TYPE_SPACE) || byte == '\n'; } /* *---------------------------------------------------------------------- * * TclIsBareword-- * * Report whether byte is one that can be part of a "bareword". * This concept is named in expression parsing, where it determines * what can be a legal function name, but is the same definition used * in determining what variable names can be parsed as variable * substitutions without the benefit of enclosing braces. The set of * ASCII chars that are accepted are the numeric chars ('0'-'9'), * the alphabetic chars ('a'-'z', 'A'-'Z') and underscore ('_'). * * Results: * Returns 1, if byte is in the accepted set of chars, 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclIsBareword( char byte) { if (byte < '0' || byte > 'z') { return 0; } if (byte <= '9' || byte >= 'a') { return 1; } if (byte == '_') { return 1; } if (byte < 'A' || byte > 'Z') { return 0; } return 1; } /* *---------------------------------------------------------------------- * * ParseWhiteSpace -- * * Scans up to numBytes bytes starting at src, consuming white space * between words as defined by Tcl's parsing rules. * * Results: * Returns the number of bytes recognized as white space. Records at * parsePtr, information about the parse. Records at typePtr the * character type of the non-whitespace character that terminated the * scan. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ParseWhiteSpace( const char *src, /* First character to parse. */ register int numBytes, /* Max number of bytes to scan. */ int *incompletePtr, /* Set this boolean memory to true if parsing * indicates an incomplete command. */ char *typePtr) /* Points to location to store character type * of character that ends run of whitespace */ { register char type = TYPE_NORMAL; register const char *p = src; while (1) { while (numBytes && ((type = CHAR_TYPE(*p)) & TYPE_SPACE)) { numBytes--; p++; } if (numBytes && (type & TYPE_SUBS)) { if (*p != '\\') { break; } if (--numBytes == 0) { break; } if (p[1] != '\n') { break; } p += 2; if (--numBytes == 0) { *incompletePtr = 1; break; } continue; } break; } *typePtr = type; return (p - src); } /* *---------------------------------------------------------------------- * * TclParseAllWhiteSpace -- * * Scans up to numBytes bytes starting at src, consuming all white space * including the command-terminating newline characters. * * Results: * Returns the number of bytes recognized as white space. * *---------------------------------------------------------------------- */ int TclParseAllWhiteSpace( const char *src, /* First character to parse. */ int numBytes) /* Max number of byes to scan */ { int dummy; char type; const char *p = src; do { int scanned = ParseWhiteSpace(p, numBytes, &dummy, &type); p += scanned; numBytes -= scanned; } while (numBytes && (*p == '\n') && (p++, --numBytes)); return (p-src); } /* *---------------------------------------------------------------------- * * TclParseHex -- * * Scans a hexadecimal number as a Tcl_UniChar value (e.g., for parsing * \x and \u escape sequences). At most numBytes bytes are scanned. * * Results: * The numeric value is stored in *resultPtr. Returns the number of bytes * consumed. * * Notes: * Relies on the following properties of the ASCII character set, with * which UTF-8 is compatible: * * The digits '0' .. '9' and the letters 'A' .. 'Z' and 'a' .. 'z' occupy * consecutive code points, and '0' < 'A' < 'a'. * *---------------------------------------------------------------------- */ int TclParseHex( const char *src, /* First character to parse. */ int numBytes, /* Max number of byes to scan */ int *resultPtr) /* Points to storage provided by caller where * the character resulting from the * conversion is to be written. */ { int result = 0; register const char *p = src; while (numBytes--) { unsigned char digit = UCHAR(*p); if (!isxdigit(digit) || (result > 0x10fff)) { break; } p++; result <<= 4; if (digit >= 'a') { result |= (10 + digit - 'a'); } else if (digit >= 'A') { result |= (10 + digit - 'A'); } else { result |= (digit - '0'); } } *resultPtr = result; return (p - src); } /* *---------------------------------------------------------------------- * * TclParseBackslash -- * * Scans up to numBytes bytes starting at src, consuming a backslash * sequence as defined by Tcl's parsing rules. * * Results: * Records at readPtr the number of bytes making up the backslash * sequence. Records at dst the UTF-8 encoded equivalent of that * backslash sequence. Returns the number of bytes written to dst, at * most TCL_UTF_MAX. Either readPtr or dst may be NULL, if the results * are not needed, but the return value is the same either way. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclParseBackslash( const char *src, /* Points to the backslash character of a a * backslash sequence. */ int numBytes, /* Max number of bytes to scan. */ int *readPtr, /* NULL, or points to storage where the number * of bytes scanned should be written. */ char *dst) /* NULL, or points to buffer where the UTF-8 * encoding of the backslash sequence is to be * written. At most TCL_UTF_MAX bytes will be * written there. */ { register const char *p = src+1; Tcl_UniChar unichar; int result; int count; char buf[TCL_UTF_MAX]; if (numBytes == 0) { if (readPtr != NULL) { *readPtr = 0; } return 0; } if (dst == NULL) { dst = buf; } if (numBytes == 1) { /* * Can only scan the backslash, so return it. */ result = '\\'; count = 1; goto done; } count = 2; switch (*p) { /* * Note: in the conversions below, use absolute values (e.g., 0xa) * rather than symbolic values (e.g. \n) that get converted by the * compiler. It's possible that compilers on some platforms will do * the symbolic conversions differently, which could result in * non-portable Tcl scripts. */ case 'a': result = 0x7; break; case 'b': result = 0x8; break; case 'f': result = 0xc; break; case 'n': result = 0xa; break; case 'r': result = 0xd; break; case 't': result = 0x9; break; case 'v': result = 0xb; break; case 'x': count += TclParseHex(p+1, (numBytes > 3) ? 2 : numBytes-2, &result); if (count == 2) { /* * No hexadigits -> This is just "x". */ result = 'x'; } else { /* * Keep only the last byte (2 hex digits). */ result = (unsigned char) result; } break; case 'u': count += TclParseHex(p+1, (numBytes > 5) ? 4 : numBytes-2, &result); if (count == 2) { /* * No hexadigits -> This is just "u". */ result = 'u'; } break; case 'U': count += TclParseHex(p+1, (numBytes > 9) ? 8 : numBytes-2, &result); if (count == 2) { /* * No hexadigits -> This is just "U". */ result = 'U'; } break; case '\n': count--; do { p++; count++; } while ((count < numBytes) && ((*p == ' ') || (*p == '\t'))); result = ' '; break; case 0: result = '\\'; count = 1; break; default: /* * Check for an octal number \oo?o? */ if (isdigit(UCHAR(*p)) && (UCHAR(*p) < '8')) { /* INTL: digit */ result = *p - '0'; p++; if ((numBytes == 2) || !isdigit(UCHAR(*p)) /* INTL: digit */ || (UCHAR(*p) >= '8')) { break; } count = 3; result = (result << 3) + (*p - '0'); p++; if ((numBytes == 3) || !isdigit(UCHAR(*p)) /* INTL: digit */ || (UCHAR(*p) >= '8') || (result >= 0x20)) { break; } count = 4; result = UCHAR((result << 3) + (*p - '0')); break; } /* * We have to convert here in case the user has put a backslash in * front of a multi-byte utf-8 character. While this means nothing * special, we shouldn't break up a correct utf-8 character. [Bug * #217987] test subst-3.2 */ if (Tcl_UtfCharComplete(p, numBytes - 1)) { count = Tcl_UtfToUniChar(p, &unichar) + 1; /* +1 for '\' */ } else { char utfBytes[TCL_UTF_MAX]; memcpy(utfBytes, p, (size_t) (numBytes - 1)); utfBytes[numBytes - 1] = '\0'; count = Tcl_UtfToUniChar(utfBytes, &unichar) + 1; } result = unichar; break; } done: if (readPtr != NULL) { *readPtr = count; } return Tcl_UniCharToUtf(result, dst); } /* *---------------------------------------------------------------------- * * ParseComment -- * * Scans up to numBytes bytes starting at src, consuming a Tcl comment as * defined by Tcl's parsing rules. * * Results: * Records in parsePtr information about the parse. Returns the number of * bytes consumed. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ParseComment( const char *src, /* First character to parse. */ register int numBytes, /* Max number of bytes to scan. */ Tcl_Parse *parsePtr) /* Information about parse in progress. * Updated if parsing indicates an incomplete * command. */ { register const char *p = src; while (numBytes) { char type; int scanned; do { scanned = ParseWhiteSpace(p, numBytes, &parsePtr->incomplete, &type); p += scanned; numBytes -= scanned; } while (numBytes && (*p == '\n') && (p++,numBytes--)); if ((numBytes == 0) || (*p != '#')) { break; } if (parsePtr->commentStart == NULL) { parsePtr->commentStart = p; } while (numBytes) { if (*p == '\\') { scanned = ParseWhiteSpace(p, numBytes, &parsePtr->incomplete, &type); if (scanned) { p += scanned; numBytes -= scanned; } else { /* * General backslash substitution in comments isn't part * of the formal spec, but test parse-15.47 and history * indicate that it has been the de facto rule. Don't * change it now. */ TclParseBackslash(p, numBytes, &scanned, NULL); p += scanned; numBytes -= scanned; } } else { p++; numBytes--; if (p[-1] == '\n') { break; } } } parsePtr->commentSize = p - parsePtr->commentStart; } return (p - src); } /* *---------------------------------------------------------------------- * * ParseTokens -- * * This function forms the heart of the Tcl parser. It parses one or more * tokens from a string, up to a termination point specified by the * caller. This function is used to parse unquoted command words (those * not in quotes or braces), words in quotes, and array indices for * variables. No more than numBytes bytes will be scanned. * * Results: * Tokens are added to parsePtr and parsePtr->term is filled in with the * address of the character that terminated the parse (the first one * whose CHAR_TYPE matched mask or the character at parsePtr->end). The * return value is TCL_OK if the parse completed successfully and * TCL_ERROR otherwise. If a parse error occurs and parsePtr->interp is * not NULL, then an error message is left in the interpreter's result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ParseTokens( register const char *src, /* First character to parse. */ register int numBytes, /* Max number of bytes to scan. */ int mask, /* Specifies when to stop parsing. The parse * stops at the first unquoted character whose * CHAR_TYPE contains any of the bits in * mask. */ int flags, /* OR-ed bits indicating what substitutions to * perform: TCL_SUBST_COMMANDS, * TCL_SUBST_VARIABLES, and * TCL_SUBST_BACKSLASHES */ Tcl_Parse *parsePtr) /* Information about parse in progress. * Updated with additional tokens and * termination information. */ { char type; int originalTokens; int noSubstCmds = !(flags & TCL_SUBST_COMMANDS); int noSubstVars = !(flags & TCL_SUBST_VARIABLES); int noSubstBS = !(flags & TCL_SUBST_BACKSLASHES); Tcl_Token *tokenPtr; /* * Each iteration through the following loop adds one token of type * TCL_TOKEN_TEXT, TCL_TOKEN_BS, TCL_TOKEN_COMMAND, or TCL_TOKEN_VARIABLE * to parsePtr. For TCL_TOKEN_VARIABLE tokens, additional tokens are added * for the parsed variable name. */ originalTokens = parsePtr->numTokens; while (numBytes && !((type = CHAR_TYPE(*src)) & mask)) { TclGrowParseTokenArray(parsePtr, 1); tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens]; tokenPtr->start = src; tokenPtr->numComponents = 0; if ((type & TYPE_SUBS) == 0) { /* * This is a simple range of characters. Scan to find the end of * the range. */ while ((++src, --numBytes) && !(CHAR_TYPE(*src) & (mask | TYPE_SUBS))) { /* empty loop */ } tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->size = src - tokenPtr->start; parsePtr->numTokens++; } else if (*src == '$') { int varToken; if (noSubstVars) { tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->size = 1; parsePtr->numTokens++; src++; numBytes--; continue; } /* * This is a variable reference. Call Tcl_ParseVarName to do all * the dirty work of parsing the name. */ varToken = parsePtr->numTokens; if (Tcl_ParseVarName(parsePtr->interp, src, numBytes, parsePtr, 1) != TCL_OK) { return TCL_ERROR; } src += parsePtr->tokenPtr[varToken].size; numBytes -= parsePtr->tokenPtr[varToken].size; } else if (*src == '[') { Tcl_Parse *nestedPtr; if (noSubstCmds) { tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->size = 1; parsePtr->numTokens++; src++; numBytes--; continue; } /* * Command substitution. Call Tcl_ParseCommand recursively (and * repeatedly) to parse the nested command(s), then throw away the * parse information. */ src++; numBytes--; nestedPtr = TclStackAlloc(parsePtr->interp, sizeof(Tcl_Parse)); while (1) { if (Tcl_ParseCommand(parsePtr->interp, src, numBytes, 1, nestedPtr) != TCL_OK) { parsePtr->errorType = nestedPtr->errorType; parsePtr->term = nestedPtr->term; parsePtr->incomplete = nestedPtr->incomplete; TclStackFree(parsePtr->interp, nestedPtr); return TCL_ERROR; } src = nestedPtr->commandStart + nestedPtr->commandSize; numBytes = parsePtr->end - src; Tcl_FreeParse(nestedPtr); /* * Check for the closing ']' that ends the command * substitution. It must have been the last character of the * parsed command. */ if ((nestedPtr->term < parsePtr->end) && (*(nestedPtr->term) == ']') && !(nestedPtr->incomplete)) { break; } if (numBytes == 0) { if (parsePtr->interp != NULL) { Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( "missing close-bracket", -1)); } parsePtr->errorType = TCL_PARSE_MISSING_BRACKET; parsePtr->term = tokenPtr->start; parsePtr->incomplete = 1; TclStackFree(parsePtr->interp, nestedPtr); return TCL_ERROR; } } TclStackFree(parsePtr->interp, nestedPtr); tokenPtr->type = TCL_TOKEN_COMMAND; tokenPtr->size = src - tokenPtr->start; parsePtr->numTokens++; } else if (*src == '\\') { if (noSubstBS) { tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->size = 1; parsePtr->numTokens++; src++; numBytes--; continue; } /* * Backslash substitution. */ TclParseBackslash(src, numBytes, &tokenPtr->size, NULL); if (tokenPtr->size == 1) { /* * Just a backslash, due to end of string. */ tokenPtr->type = TCL_TOKEN_TEXT; parsePtr->numTokens++; src++; numBytes--; continue; } if (src[1] == '\n') { if (numBytes == 2) { parsePtr->incomplete = 1; } /* * Note: backslash-newline is special in that it is treated * the same as a space character would be. This means that it * could terminate the token. */ if (mask & TYPE_SPACE) { if (parsePtr->numTokens == originalTokens) { goto finishToken; } break; } } tokenPtr->type = TCL_TOKEN_BS; parsePtr->numTokens++; src += tokenPtr->size; numBytes -= tokenPtr->size; } else if (*src == 0) { tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->size = 1; parsePtr->numTokens++; src++; numBytes--; } else { Tcl_Panic("ParseTokens encountered unknown character"); } } if (parsePtr->numTokens == originalTokens) { /* * There was nothing in this range of text. Add an empty token for the * empty range, so that there is always at least one token added. */ TclGrowParseTokenArray(parsePtr, 1); tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens]; tokenPtr->start = src; tokenPtr->numComponents = 0; finishToken: tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->size = 0; parsePtr->numTokens++; } parsePtr->term = src; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_FreeParse -- * * This function is invoked to free any dynamic storage that may have * been allocated by a previous call to Tcl_ParseCommand. * * Results: * None. * * Side effects: * If there is any dynamically allocated memory in *parsePtr, it is * freed. * *---------------------------------------------------------------------- */ void Tcl_FreeParse( Tcl_Parse *parsePtr) /* Structure that was filled in by a previous * call to Tcl_ParseCommand. */ { if (parsePtr->tokenPtr != parsePtr->staticTokens) { ckfree(parsePtr->tokenPtr); parsePtr->tokenPtr = parsePtr->staticTokens; } } /* *---------------------------------------------------------------------- * * Tcl_ParseVarName -- * * Given a string starting with a $ sign, parse off a variable name and * return information about the parse. No more than numBytes bytes will * be scanned. * * Results: * The return value is TCL_OK if the command was parsed successfully and * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then an * error message is left in its result. On a successful return, tokenPtr * and numTokens fields of parsePtr are filled in with information about * the variable name that was parsed. The "size" field of the first new * token gives the total number of bytes in the variable name. Other * fields in parsePtr are undefined. * * Side effects: * If there is insufficient space in parsePtr to hold all the information * about the command, then additional space is malloc-ed. If the function * returns TCL_OK then the caller must eventually invoke Tcl_FreeParse to * release any additional space that was allocated. * *---------------------------------------------------------------------- */ int Tcl_ParseVarName( Tcl_Interp *interp, /* Interpreter to use for error reporting; if * NULL, then no error message is provided. */ const char *start, /* Start of variable substitution string. * First character must be "$". */ register int numBytes, /* Total number of bytes in string. If < 0, * the string consists of all bytes up to the * first null character. */ Tcl_Parse *parsePtr, /* Structure to fill in with information about * the variable name. */ int append) /* Non-zero means append tokens to existing * information in parsePtr; zero means ignore * existing tokens in parsePtr and * reinitialize it. */ { Tcl_Token *tokenPtr; register const char *src; int varIndex; unsigned array; if ((numBytes == 0) || (start == NULL)) { return TCL_ERROR; } if (numBytes < 0) { numBytes = strlen(start); } if (!append) { TclParseInit(interp, start, numBytes, parsePtr); } /* * Generate one token for the variable, an additional token for the name, * plus any number of additional tokens for the index, if there is one. */ src = start; TclGrowParseTokenArray(parsePtr, 2); tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens]; tokenPtr->type = TCL_TOKEN_VARIABLE; tokenPtr->start = src; varIndex = parsePtr->numTokens; parsePtr->numTokens++; tokenPtr++; src++; numBytes--; if (numBytes == 0) { goto justADollarSign; } tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->start = src; tokenPtr->numComponents = 0; /* * The name of the variable can have three forms: * 1. The $ sign is followed by an open curly brace. Then the variable * name is everything up to the next close curly brace, and the * variable is a scalar variable. * 2. The $ sign is not followed by an open curly brace. Then the variable * name is everything up to the next character that isn't a letter, * digit, or underscore. :: sequences are also considered part of the * variable name, in order to support namespaces. If the following * character is an open parenthesis, then the information between * parentheses is the array element name. * 3. The $ sign is followed by something that isn't a letter, digit, or * underscore: in this case, there is no variable name and the token is * just "$". */ if (*src == '{') { src++; numBytes--; tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->start = src; tokenPtr->numComponents = 0; while (numBytes && (*src != '}')) { numBytes--; src++; } if (numBytes == 0) { if (parsePtr->interp != NULL) { Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( "missing close-brace for variable name", -1)); } parsePtr->errorType = TCL_PARSE_MISSING_VAR_BRACE; parsePtr->term = tokenPtr->start-1; parsePtr->incomplete = 1; goto error; } tokenPtr->size = src - tokenPtr->start; tokenPtr[-1].size = src - tokenPtr[-1].start; parsePtr->numTokens++; src++; } else { tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->start = src; tokenPtr->numComponents = 0; while (numBytes) { if (TclIsBareword(*src)) { src += 1; numBytes -= 1; continue; } if ((src[0] == ':') && (numBytes != 1) && (src[1] == ':')) { src += 2; numBytes -= 2; while (numBytes && (*src == ':')) { src++; numBytes--; } continue; } break; } /* * Support for empty array names here. */ array = (numBytes && (*src == '(')); tokenPtr->size = src - tokenPtr->start; if ((tokenPtr->size == 0) && !array) { goto justADollarSign; } parsePtr->numTokens++; if (array) { /* * This is a reference to an array element. Call ParseTokens * recursively to parse the element name, since it could contain * any number of substitutions. */ if (TCL_OK != ParseTokens(src+1, numBytes-1, TYPE_CLOSE_PAREN, TCL_SUBST_ALL, parsePtr)) { goto error; } if ((parsePtr->term == src+numBytes) || (*parsePtr->term != ')')){ if (parsePtr->interp != NULL) { Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( "missing )", -1)); } parsePtr->errorType = TCL_PARSE_MISSING_PAREN; parsePtr->term = src; parsePtr->incomplete = 1; goto error; } src = parsePtr->term + 1; } } tokenPtr = &parsePtr->tokenPtr[varIndex]; tokenPtr->size = src - tokenPtr->start; tokenPtr->numComponents = parsePtr->numTokens - (varIndex + 1); return TCL_OK; /* * The dollar sign isn't followed by a variable name. Replace the * TCL_TOKEN_VARIABLE token with a TCL_TOKEN_TEXT token for the dollar * sign. */ justADollarSign: tokenPtr = &parsePtr->tokenPtr[varIndex]; tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->size = 1; tokenPtr->numComponents = 0; return TCL_OK; error: Tcl_FreeParse(parsePtr); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_ParseVar -- * * Given a string starting with a $ sign, parse off a variable name and * return its value. * * Results: * The return value is the contents of the variable given by the leading * characters of string. If termPtr isn't NULL, *termPtr gets filled in * with the address of the character just after the last one in the * variable specifier. If the variable doesn't exist, then the return * value is NULL and an error message will be left in interp's result. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * Tcl_ParseVar( Tcl_Interp *interp, /* Context for looking up variable. */ register const char *start, /* Start of variable substitution. First * character must be "$". */ const char **termPtr) /* If non-NULL, points to word to fill in with * character just after last one in the * variable specifier. */ { register Tcl_Obj *objPtr; int code; Tcl_Parse *parsePtr = TclStackAlloc(interp, sizeof(Tcl_Parse)); if (Tcl_ParseVarName(interp, start, -1, parsePtr, 0) != TCL_OK) { TclStackFree(interp, parsePtr); return NULL; } if (termPtr != NULL) { *termPtr = start + parsePtr->tokenPtr->size; } if (parsePtr->numTokens == 1) { /* * There isn't a variable name after all: the $ is just a $. */ TclStackFree(interp, parsePtr); return "$"; } code = TclSubstTokens(interp, parsePtr->tokenPtr, parsePtr->numTokens, NULL, 1, NULL, NULL); Tcl_FreeParse(parsePtr); TclStackFree(interp, parsePtr); if (code != TCL_OK) { return NULL; } objPtr = Tcl_GetObjResult(interp); /* * At this point we should have an object containing the value of a * variable. Just return the string from that object. * * Since TclSubstTokens above returned TCL_OK, we know that objPtr * is shared. It is in both the interp result and the value of the * variable. Returning the string relies on that to be true. */ assert( Tcl_IsShared(objPtr) ); Tcl_ResetResult(interp); return TclGetString(objPtr); } /* *---------------------------------------------------------------------- * * Tcl_ParseBraces -- * * Given a string in braces such as a Tcl command argument or a string * value in a Tcl expression, this function parses the string and returns * information about the parse. No more than numBytes bytes will be * scanned. * * Results: * The return value is TCL_OK if the string was parsed successfully and * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then an * error message is left in its result. On a successful return, tokenPtr * and numTokens fields of parsePtr are filled in with information about * the string that was parsed. Other fields in parsePtr are undefined. * termPtr is set to point to the character just after the last one in * the braced string. * * Side effects: * If there is insufficient space in parsePtr to hold all the information * about the command, then additional space is malloc-ed. If the function * returns TCL_OK then the caller must eventually invoke Tcl_FreeParse to * release any additional space that was allocated. * *---------------------------------------------------------------------- */ int Tcl_ParseBraces( Tcl_Interp *interp, /* Interpreter to use for error reporting; if * NULL, then no error message is provided. */ const char *start, /* Start of string enclosed in braces. The * first character must be {'. */ register int numBytes, /* Total number of bytes in string. If < 0, * the string consists of all bytes up to the * first null character. */ register Tcl_Parse *parsePtr, /* Structure to fill in with information about * the string. */ int append, /* Non-zero means append tokens to existing * information in parsePtr; zero means ignore * existing tokens in parsePtr and * reinitialize it. */ const char **termPtr) /* If non-NULL, points to word in which to * store a pointer to the character just after * the terminating '}' if the parse was * successful. */ { Tcl_Token *tokenPtr; register const char *src; int startIndex, level, length; if ((numBytes == 0) || (start == NULL)) { return TCL_ERROR; } if (numBytes < 0) { numBytes = strlen(start); } if (!append) { TclParseInit(interp, start, numBytes, parsePtr); } src = start; startIndex = parsePtr->numTokens; TclGrowParseTokenArray(parsePtr, 1); tokenPtr = &parsePtr->tokenPtr[startIndex]; tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->start = src+1; tokenPtr->numComponents = 0; level = 1; while (1) { while (++src, --numBytes) { if (CHAR_TYPE(*src) != TYPE_NORMAL) { break; } } if (numBytes == 0) { goto missingBraceError; } switch (*src) { case '{': level++; break; case '}': if (--level == 0) { /* * Decide if we need to finish emitting a partially-finished * token. There are 3 cases: * {abc \newline xyz} or {xyz} * - finish emitting "xyz" token * {abc \newline} * - don't emit token after \newline * {} - finish emitting zero-sized token * * The last case ensures that there is a token (even if empty) * that describes the braced string. */ if ((src != tokenPtr->start) || (parsePtr->numTokens == startIndex)) { tokenPtr->size = (src - tokenPtr->start); parsePtr->numTokens++; } if (termPtr != NULL) { *termPtr = src+1; } return TCL_OK; } break; case '\\': TclParseBackslash(src, numBytes, &length, NULL); if ((length > 1) && (src[1] == '\n')) { /* * A backslash-newline sequence must be collapsed, even inside * braces, so we have to split the word into multiple tokens * so that the backslash-newline can be represented * explicitly. */ if (numBytes == 2) { parsePtr->incomplete = 1; } tokenPtr->size = (src - tokenPtr->start); if (tokenPtr->size != 0) { parsePtr->numTokens++; } TclGrowParseTokenArray(parsePtr, 2); tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens]; tokenPtr->type = TCL_TOKEN_BS; tokenPtr->start = src; tokenPtr->size = length; tokenPtr->numComponents = 0; parsePtr->numTokens++; src += length - 1; numBytes -= length - 1; tokenPtr++; tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->start = src + 1; tokenPtr->numComponents = 0; } else { src += length - 1; numBytes -= length - 1; } break; } } missingBraceError: parsePtr->errorType = TCL_PARSE_MISSING_BRACE; parsePtr->term = start; parsePtr->incomplete = 1; if (parsePtr->interp == NULL) { /* * Skip straight to the exit code since we have no interpreter to put * error message in. */ goto error; } Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( "missing close-brace", -1)); /* * Guess if the problem is due to comments by searching the source string * for a possible open brace within the context of a comment. Since we * aren't performing a full Tcl parse, just look for an open brace * preceded by a '#' on the same line. */ { register int openBrace = 0; while (--src > start) { switch (*src) { case '{': openBrace = 1; break; case '\n': openBrace = 0; break; case '#' : if (openBrace && TclIsSpaceProc(src[-1])) { Tcl_AppendToObj(Tcl_GetObjResult(parsePtr->interp), ": possible unbalanced brace in comment", -1); goto error; } break; } } } error: Tcl_FreeParse(parsePtr); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_ParseQuotedString -- * * Given a double-quoted string such as a quoted Tcl command argument or * a quoted value in a Tcl expression, this function parses the string * and returns information about the parse. No more than numBytes bytes * will be scanned. * * Results: * The return value is TCL_OK if the string was parsed successfully and * TCL_ERROR otherwise. If an error occurs and interp isn't NULL then an * error message is left in its result. On a successful return, tokenPtr * and numTokens fields of parsePtr are filled in with information about * the string that was parsed. Other fields in parsePtr are undefined. * termPtr is set to point to the character just after the quoted * string's terminating close-quote. * * Side effects: * If there is insufficient space in parsePtr to hold all the information * about the command, then additional space is malloc-ed. If the function * returns TCL_OK then the caller must eventually invoke Tcl_FreeParse to * release any additional space that was allocated. * *---------------------------------------------------------------------- */ int Tcl_ParseQuotedString( Tcl_Interp *interp, /* Interpreter to use for error reporting; if * NULL, then no error message is provided. */ const char *start, /* Start of the quoted string. The first * character must be '"'. */ register int numBytes, /* Total number of bytes in string. If < 0, * the string consists of all bytes up to the * first null character. */ register Tcl_Parse *parsePtr, /* Structure to fill in with information about * the string. */ int append, /* Non-zero means append tokens to existing * information in parsePtr; zero means ignore * existing tokens in parsePtr and * reinitialize it. */ const char **termPtr) /* If non-NULL, points to word in which to * store a pointer to the character just after * the quoted string's terminating close-quote * if the parse succeeds. */ { if ((numBytes == 0) || (start == NULL)) { return TCL_ERROR; } if (numBytes < 0) { numBytes = strlen(start); } if (!append) { TclParseInit(interp, start, numBytes, parsePtr); } if (TCL_OK != ParseTokens(start+1, numBytes-1, TYPE_QUOTE, TCL_SUBST_ALL, parsePtr)) { goto error; } if (*parsePtr->term != '"') { if (parsePtr->interp != NULL) { Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( "missing \"", -1)); } parsePtr->errorType = TCL_PARSE_MISSING_QUOTE; parsePtr->term = start; parsePtr->incomplete = 1; goto error; } if (termPtr != NULL) { *termPtr = (parsePtr->term + 1); } return TCL_OK; error: Tcl_FreeParse(parsePtr); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclSubstParse -- * * Token parser used by the [subst] command. Parses the string made up of * 'numBytes' bytes starting at 'bytes'. Parsing is controlled by the * flags argument to provide support for the -nobackslashes, -nocommands, * and -novariables options, as represented by the flag values * TCL_SUBST_BACKSLASHES, TCL_SUBST_COMMANDS, TCL_SUBST_VARIABLES. * * Results: * None. * * Side effects: * The Tcl_Parse struct '*parsePtr' is filled with parse results. * The caller is expected to eventually call Tcl_FreeParse() to properly * cleanup the value written there. * * If a parse error occurs, the Tcl_InterpState value '*statePtr' is * filled with the state created by that error. When *statePtr is written * to, the caller is expected to make the required calls to either * Tcl_RestoreInterpState() or Tcl_DiscardInterpState() to dispose of the * value written there. * *---------------------------------------------------------------------- */ void TclSubstParse( Tcl_Interp *interp, const char *bytes, int numBytes, int flags, Tcl_Parse *parsePtr, Tcl_InterpState *statePtr) { int length = numBytes; const char *p = bytes; TclParseInit(interp, p, length, parsePtr); /* * First parse the string rep of objPtr, as if it were enclosed as a * "-quoted word in a normal Tcl command. Honor flags that selectively * inhibit types of substitution. */ if (TCL_OK != ParseTokens(p, length, /* mask */ 0, flags, parsePtr)) { /* * There was a parse error. Save the interpreter state for possible * error reporting later. */ *statePtr = Tcl_SaveInterpState(interp, TCL_ERROR); /* * We need to re-parse to get the portion of the string we can [subst] * before the parse error. Sadly, all the Tcl_Token's created by the * first parse attempt are gone, freed according to the public spec * for the Tcl_Parse* routines. The only clue we have is parse.term, * which points to either the unmatched opener, or to characters that * follow a close brace or close quote. * * Call ParseTokens again, working on the string up to parse.term. * Keep repeating until we get a good parse on a prefix. */ do { parsePtr->numTokens = 0; parsePtr->tokensAvailable = NUM_STATIC_TOKENS; parsePtr->end = parsePtr->term; parsePtr->incomplete = 0; parsePtr->errorType = TCL_PARSE_SUCCESS; } while (TCL_OK != ParseTokens(p, parsePtr->end - p, 0, flags, parsePtr)); /* * The good parse will have to be followed by {, (, or [. */ switch (*(parsePtr->term)) { case '{': /* * Parse error was a missing } in a ${varname} variable * substitution at the toplevel. We will subst everything up to * that broken variable substitution before reporting the parse * error. Substituting the leftover '$' will have no side-effects, * so the current token stream is fine. */ break; case '(': /* * Parse error was during the parsing of the index part of an * array variable substitution at the toplevel. */ if (*(parsePtr->term - 1) == '$') { /* * Special case where removing the array index left us with * just a dollar sign (array variable with name the empty * string as its name), instead of with a scalar variable * reference. * * As in the previous case, existing token stream is OK. */ } else { /* * The current parse includes a successful parse of a scalar * variable substitution where there should have been an array * variable substitution. We remove that mistaken part of the * parse before moving on. A scalar variable substitution is * two tokens. */ Tcl_Token *varTokenPtr = parsePtr->tokenPtr + parsePtr->numTokens - 2; if (varTokenPtr->type != TCL_TOKEN_VARIABLE) { Tcl_Panic("TclSubstParse: programming error"); } if (varTokenPtr[1].type != TCL_TOKEN_TEXT) { Tcl_Panic("TclSubstParse: programming error"); } parsePtr->numTokens -= 2; } break; case '[': /* * Parse error occurred during parsing of a toplevel command * substitution. */ parsePtr->end = p + length; p = parsePtr->term + 1; length = parsePtr->end - p; if (length == 0) { /* * No commands, just an unmatched [. As in previous cases, * existing token stream is OK. */ } else { /* * We want to add the parsing of as many commands as we can * within that substitution until we reach the actual parse * error. We'll do additional parsing to determine what length * to claim for the final TCL_TOKEN_COMMAND token. */ Tcl_Token *tokenPtr; const char *lastTerm = parsePtr->term; Tcl_Parse *nestedPtr = TclStackAlloc(interp, sizeof(Tcl_Parse)); while (TCL_OK == Tcl_ParseCommand(NULL, p, length, 0, nestedPtr)) { Tcl_FreeParse(nestedPtr); p = nestedPtr->term + (nestedPtr->term < nestedPtr->end); length = nestedPtr->end - p; if ((length == 0) && (nestedPtr->term == nestedPtr->end)) { /* * If we run out of string, blame the missing close * bracket on the last command, and do not evaluate it * during substitution. */ break; } lastTerm = nestedPtr->term; } TclStackFree(interp, nestedPtr); if (lastTerm == parsePtr->term) { /* * Parse error in first command. No commands to subst, add * no more tokens. */ break; } /* * Create a command substitution token for whatever commands * got parsed. */ TclGrowParseTokenArray(parsePtr, 1); tokenPtr = &(parsePtr->tokenPtr[parsePtr->numTokens]); tokenPtr->start = parsePtr->term; tokenPtr->numComponents = 0; tokenPtr->type = TCL_TOKEN_COMMAND; tokenPtr->size = lastTerm - tokenPtr->start + 1; parsePtr->numTokens++; } break; default: Tcl_Panic("bad parse in TclSubstParse: %c", p[length]); } } } /* *---------------------------------------------------------------------- * * TclSubstTokens -- * * Accepts an array of count Tcl_Token's, and creates a result value in * the interp from concatenating the results of performing Tcl * substitution on each Tcl_Token. Substitution is interrupted if any * non-TCL_OK completion code arises. * * Results: * The return value is a standard Tcl completion code. The result in * interp is the substituted value, or an error message if TCL_ERROR is * returned. If tokensLeftPtr is not NULL, then it points to an int where * the number of tokens remaining to be processed is written. * * Side effects: * Can be anything, depending on the types of substitution done. * *---------------------------------------------------------------------- */ int TclSubstTokens( Tcl_Interp *interp, /* Interpreter in which to lookup variables, * execute nested commands, and report * errors. */ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to * evaluate and concatenate. */ int count, /* Number of tokens to consider at tokenPtr. * Must be at least 1. */ int *tokensLeftPtr, /* If not NULL, points to memory where an * integer representing the number of tokens * left to be substituted will be written */ int line, /* The line the script starts on. */ int *clNextOuter, /* Information about an outer context for */ const char *outerScript) /* continuation line data. This is set by * EvalEx() to properly handle [...]-nested * commands. The 'outerScript' refers to the * most-outer script containing the embedded * command, which is refered to by 'script'. * The 'clNextOuter' refers to the current * entry in the table of continuation lines in * this "master script", and the character * offsets are relative to the 'outerScript' * as well. * * If outerScript == script, then this call is * for words in the outer-most script or * command. See Tcl_EvalEx and TclEvalObjEx * for the places generating arguments for * which this is true. */ { Tcl_Obj *result; int code = TCL_OK; #define NUM_STATIC_POS 20 int isLiteral, maxNumCL, numCL, i, adjust; int *clPosition = NULL; Interp *iPtr = (Interp *) interp; int inFile = iPtr->evalFlags & TCL_EVAL_FILE; /* * Each pass through this loop will substitute one token, and its * components, if any. The only thing tricky here is that we go to some * effort to pass Tcl_Obj's through untouched, to avoid string copying and * Tcl_Obj creation if possible, to aid performance and limit shimmering. * * Further optimization opportunities might be to check for the equivalent * of Tcl_SetObjResult(interp, Tcl_GetObjResult(interp)) and omit them. */ /* * For the handling of continuation lines in literals we first check if * this is actually a literal. For if not we can forego the additional * processing. Otherwise we pre-allocate a small table to store the * locations of all continuation lines we find in this literal, if any. * The table is extended if needed. */ numCL = 0; maxNumCL = 0; isLiteral = 1; for (i=0 ; i < count; i++) { if ((tokenPtr[i].type != TCL_TOKEN_TEXT) && (tokenPtr[i].type != TCL_TOKEN_BS)) { isLiteral = 0; break; } } if (isLiteral) { maxNumCL = NUM_STATIC_POS; clPosition = ckalloc(maxNumCL * sizeof(int)); } adjust = 0; result = NULL; for (; count>0 && code==TCL_OK ; count--, tokenPtr++) { Tcl_Obj *appendObj = NULL; const char *append = NULL; int appendByteLength = 0; char utfCharBytes[TCL_UTF_MAX]; switch (tokenPtr->type) { case TCL_TOKEN_TEXT: append = tokenPtr->start; appendByteLength = tokenPtr->size; break; case TCL_TOKEN_BS: appendByteLength = TclParseBackslash(tokenPtr->start, tokenPtr->size, NULL, utfCharBytes); append = utfCharBytes; /* * If the backslash sequence we found is in a literal, and * represented a continuation line, we compute and store its * location (as char offset to the beginning of the _result_ * script). We may have to extend the table of locations. * * Note that the continuation line information is relevant even if * the word we are processing is not a literal, as it can affect * nested commands. See the branch for TCL_TOKEN_COMMAND below, * where the adjustment we are tracking here is taken into * account. The good thing is that we do not need a table of * everything, just the number of lines we have to add as * correction. */ if ((appendByteLength == 1) && (utfCharBytes[0] == ' ') && (tokenPtr->start[1] == '\n')) { if (isLiteral) { int clPos; if (result == 0) { clPos = 0; } else { Tcl_GetStringFromObj(result, &clPos); } if (numCL >= maxNumCL) { maxNumCL *= 2; clPosition = ckrealloc(clPosition, maxNumCL * sizeof(int)); } clPosition[numCL] = clPos; numCL++; } adjust++; } break; case TCL_TOKEN_COMMAND: { /* TIP #280: Transfer line information to nested command */ iPtr->numLevels++; code = TclInterpReady(interp); if (code == TCL_OK) { /* * Test cases: info-30.{6,8,9} */ int theline; TclAdvanceContinuations(&line, &clNextOuter, tokenPtr->start - outerScript); theline = line + adjust; code = TclEvalEx(interp, tokenPtr->start+1, tokenPtr->size-2, 0, theline, clNextOuter, outerScript); TclAdvanceLines(&line, tokenPtr->start+1, tokenPtr->start + tokenPtr->size - 1); /* * Restore flag reset by nested eval for future bracketed * commands and their cmdframe setup */ if (inFile) { iPtr->evalFlags |= TCL_EVAL_FILE; } } iPtr->numLevels--; TclResetCancellation(interp, 0); appendObj = Tcl_GetObjResult(interp); break; } case TCL_TOKEN_VARIABLE: { Tcl_Obj *arrayIndex = NULL; Tcl_Obj *varName = NULL; if (tokenPtr->numComponents > 1) { /* * Subst the index part of an array variable reference. */ code = TclSubstTokens(interp, tokenPtr+2, tokenPtr->numComponents - 1, NULL, line, NULL, NULL); arrayIndex = Tcl_GetObjResult(interp); Tcl_IncrRefCount(arrayIndex); } if (code == TCL_OK) { varName = Tcl_NewStringObj(tokenPtr[1].start, tokenPtr[1].size); appendObj = Tcl_ObjGetVar2(interp, varName, arrayIndex, TCL_LEAVE_ERR_MSG); Tcl_DecrRefCount(varName); if (appendObj == NULL) { code = TCL_ERROR; } } switch (code) { case TCL_OK: /* Got value */ case TCL_ERROR: /* Already have error message */ case TCL_BREAK: /* Will not substitute anyway */ case TCL_CONTINUE: /* Will not substitute anyway */ break; default: /* * All other return codes, we will subst the result from the * code-throwing evaluation. */ appendObj = Tcl_GetObjResult(interp); } if (arrayIndex != NULL) { Tcl_DecrRefCount(arrayIndex); } count -= tokenPtr->numComponents; tokenPtr += tokenPtr->numComponents; break; } default: Tcl_Panic("unexpected token type in TclSubstTokens: %d", tokenPtr->type); } if ((code == TCL_BREAK) || (code == TCL_CONTINUE)) { /* * Inhibit substitution. */ continue; } if (result == NULL) { /* * First pass through. If we have a Tcl_Obj, just use it. If not, * create one from our string. */ if (appendObj != NULL) { result = appendObj; } else { result = Tcl_NewStringObj(append, appendByteLength); } Tcl_IncrRefCount(result); } else { /* * Subsequent passes. Append to result. */ if (Tcl_IsShared(result)) { Tcl_DecrRefCount(result); result = Tcl_DuplicateObj(result); Tcl_IncrRefCount(result); } if (appendObj != NULL) { Tcl_AppendObjToObj(result, appendObj); } else { Tcl_AppendToObj(result, append, appendByteLength); } } } if (code != TCL_ERROR) { /* Keep error message in result! */ if (result != NULL) { Tcl_SetObjResult(interp, result); /* * If the code found continuation lines (which implies that this * word is a literal), then we store the accumulated table of * locations in the thread-global data structure for the bytecode * compiler to find later, assuming that the literal is a script * which will be compiled. */ if (numCL) { TclContinuationsEnter(result, numCL, clPosition); } /* * Release the temp table we used to collect the locations of * continuation lines, if any. */ if (maxNumCL) { ckfree(clPosition); } } else { Tcl_ResetResult(interp); } } if (tokensLeftPtr != NULL) { *tokensLeftPtr = count; } if (result != NULL) { Tcl_DecrRefCount(result); } return code; } /* *---------------------------------------------------------------------- * * CommandComplete -- * * This function is shared by TclCommandComplete and * Tcl_ObjCommandComplete; it does all the real work of seeing whether a * script is complete * * Results: * 1 is returned if the script is complete, 0 if there are open * delimiters such as " or (. 1 is also returned if there is a parse * error in the script other than unmatched delimiters. * * Side effects: * None. * *---------------------------------------------------------------------- */ static inline int CommandComplete( const char *script, /* Script to check. */ int numBytes) /* Number of bytes in script. */ { Tcl_Parse parse; const char *p, *end; int result; p = script; end = p + numBytes; while (Tcl_ParseCommand(NULL, p, end - p, 0, &parse) == TCL_OK) { p = parse.commandStart + parse.commandSize; if (p >= end) { break; } Tcl_FreeParse(&parse); } if (parse.incomplete) { result = 0; } else { result = 1; } Tcl_FreeParse(&parse); return result; } /* *---------------------------------------------------------------------- * * Tcl_CommandComplete -- * * Given a partial or complete Tcl script, this function determines * whether the script is complete in the sense of having matched braces * and quotes and brackets. * * Results: * 1 is returned if the script is complete, 0 otherwise. 1 is also * returned if there is a parse error in the script other than unmatched * delimiters. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_CommandComplete( const char *script) /* Script to check. */ { return CommandComplete(script, (int) strlen(script)); } /* *---------------------------------------------------------------------- * * TclObjCommandComplete -- * * Given a partial or complete Tcl command in a Tcl object, this function * determines whether the command is complete in the sense of having * matched braces and quotes and brackets. * * Results: * 1 is returned if the command is complete, 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclObjCommandComplete( Tcl_Obj *objPtr) /* Points to object holding script to * check. */ { int length; const char *script = Tcl_GetStringFromObj(objPtr, &length); return CommandComplete(script, length); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclDisassemble.c0000644000175000017500000012345412663660065016316 0ustar sergeisergei/* * tclDisassemble.c -- * * This file contains procedures that disassemble bytecode into either * human-readable or Tcl-processable forms. * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2013 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" #include "tclOOInt.h" #include /* * Prototypes for procedures defined later in this file: */ static Tcl_Obj * DisassembleByteCodeAsDicts(Tcl_Interp *interp, Tcl_Obj *objPtr); static Tcl_Obj * DisassembleByteCodeObj(Tcl_Interp *interp, Tcl_Obj *objPtr); static int FormatInstruction(ByteCode *codePtr, const unsigned char *pc, Tcl_Obj *bufferObj); static void GetLocationInformation(Tcl_Interp *interp, Proc *procPtr, Tcl_Obj **fileObjPtr, int *linePtr); static void PrintSourceToObj(Tcl_Obj *appendObj, const char *stringPtr, int maxChars); static void UpdateStringOfInstName(Tcl_Obj *objPtr); /* * The structure below defines an instruction name Tcl object to allow * reporting of inner contexts in errorstack without string allocation. */ static const Tcl_ObjType tclInstNameType = { "instname", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ UpdateStringOfInstName, /* updateStringProc */ NULL, /* setFromAnyProc */ }; /* * How to get the bytecode out of a Tcl_Obj. */ #define BYTECODE(objPtr) \ ((ByteCode *) (objPtr)->internalRep.twoPtrValue.ptr1) /* *---------------------------------------------------------------------- * * GetLocationInformation -- * * This procedure looks up the information about where a procedure was * originally declared. * * Results: * Writes to the variables pointed at by fileObjPtr and linePtr. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void GetLocationInformation( Tcl_Interp *interp, /* Where to look up the location * information. */ Proc *procPtr, /* What to look up the information for. */ Tcl_Obj **fileObjPtr, /* Where to write the information about what * file the code came from. Will be written * to, either with the object (assume shared!) * that describes what the file was, or with * NULL if the information is not * available. */ int *linePtr) /* Where to write the information about what * line number represented the start of the * code in question. Will be written to, * either with the line number or with -1 if * the information is not available. */ { Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hePtr; CmdFrame *cfPtr; *fileObjPtr = NULL; *linePtr = -1; if (iPtr != NULL && procPtr != NULL) { hePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, procPtr); if (hePtr != NULL && (cfPtr = Tcl_GetHashValue(hePtr)) != NULL) { *linePtr = cfPtr->line[0]; if (cfPtr->type == TCL_LOCATION_SOURCE) { *fileObjPtr = cfPtr->data.eval.path; } } } } #ifdef TCL_COMPILE_DEBUG /* *---------------------------------------------------------------------- * * TclPrintByteCodeObj -- * * This procedure prints ("disassembles") the instructions of a bytecode * object to stdout. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclPrintByteCodeObj( Tcl_Interp *interp, /* Used only for getting location info. */ Tcl_Obj *objPtr) /* The bytecode object to disassemble. */ { Tcl_Obj *bufPtr = DisassembleByteCodeObj(interp, objPtr); fprintf(stdout, "\n%s", TclGetString(bufPtr)); Tcl_DecrRefCount(bufPtr); } /* *---------------------------------------------------------------------- * * TclPrintInstruction -- * * This procedure prints ("disassembles") one instruction from a bytecode * object to stdout. * * Results: * Returns the length in bytes of the current instruiction. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclPrintInstruction( ByteCode *codePtr, /* Bytecode containing the instruction. */ const unsigned char *pc) /* Points to first byte of instruction. */ { Tcl_Obj *bufferObj; int numBytes; TclNewObj(bufferObj); numBytes = FormatInstruction(codePtr, pc, bufferObj); fprintf(stdout, "%s", TclGetString(bufferObj)); Tcl_DecrRefCount(bufferObj); return numBytes; } /* *---------------------------------------------------------------------- * * TclPrintObject -- * * This procedure prints up to a specified number of characters from the * argument Tcl object's string representation to a specified file. * * Results: * None. * * Side effects: * Outputs characters to the specified file. * *---------------------------------------------------------------------- */ void TclPrintObject( FILE *outFile, /* The file to print the source to. */ Tcl_Obj *objPtr, /* Points to the Tcl object whose string * representation should be printed. */ int maxChars) /* Maximum number of chars to print. */ { char *bytes; int length; bytes = Tcl_GetStringFromObj(objPtr, &length); TclPrintSource(outFile, bytes, TclMin(length, maxChars)); } /* *---------------------------------------------------------------------- * * TclPrintSource -- * * This procedure prints up to a specified number of characters from the * argument string to a specified file. It tries to produce legible * output by adding backslashes as necessary. * * Results: * None. * * Side effects: * Outputs characters to the specified file. * *---------------------------------------------------------------------- */ void TclPrintSource( FILE *outFile, /* The file to print the source to. */ const char *stringPtr, /* The string to print. */ int maxChars) /* Maximum number of chars to print. */ { Tcl_Obj *bufferObj; TclNewObj(bufferObj); PrintSourceToObj(bufferObj, stringPtr, maxChars); fprintf(outFile, "%s", TclGetString(bufferObj)); Tcl_DecrRefCount(bufferObj); } #endif /* TCL_COMPILE_DEBUG */ /* *---------------------------------------------------------------------- * * DisassembleByteCodeObj -- * * Given an object which is of bytecode type, return a disassembled * version of the bytecode (in a new refcount 0 object). No guarantees * are made about the details of the contents of the result. * *---------------------------------------------------------------------- */ static Tcl_Obj * DisassembleByteCodeObj( Tcl_Interp *interp, Tcl_Obj *objPtr) /* The bytecode object to disassemble. */ { ByteCode *codePtr = BYTECODE(objPtr); unsigned char *codeStart, *codeLimit, *pc; unsigned char *codeDeltaNext, *codeLengthNext; unsigned char *srcDeltaNext, *srcLengthNext; int codeOffset, codeLen, srcOffset, srcLen, numCmds, delta, i, line; Interp *iPtr = (Interp *) *codePtr->interpHandle; Tcl_Obj *bufferObj, *fileObj; char ptrBuf1[20], ptrBuf2[20]; TclNewObj(bufferObj); if (codePtr->refCount <= 0) { return bufferObj; /* Already freed. */ } codeStart = codePtr->codeStart; codeLimit = codeStart + codePtr->numCodeBytes; numCmds = codePtr->numCommands; /* * Print header lines describing the ByteCode. */ sprintf(ptrBuf1, "%p", codePtr); sprintf(ptrBuf2, "%p", iPtr); Tcl_AppendPrintfToObj(bufferObj, "ByteCode 0x%s, refCt %u, epoch %u, interp 0x%s (epoch %u)\n", ptrBuf1, codePtr->refCount, codePtr->compileEpoch, ptrBuf2, iPtr->compileEpoch); Tcl_AppendToObj(bufferObj, " Source ", -1); PrintSourceToObj(bufferObj, codePtr->source, TclMin(codePtr->numSrcBytes, 55)); GetLocationInformation(interp, codePtr->procPtr, &fileObj, &line); if (line > -1 && fileObj != NULL) { Tcl_AppendPrintfToObj(bufferObj, "\n File \"%s\" Line %d", Tcl_GetString(fileObj), line); } Tcl_AppendPrintfToObj(bufferObj, "\n Cmds %d, src %d, inst %d, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n", numCmds, codePtr->numSrcBytes, codePtr->numCodeBytes, codePtr->numLitObjects, codePtr->numAuxDataItems, codePtr->maxStackDepth, #ifdef TCL_COMPILE_STATS codePtr->numSrcBytes? codePtr->structureSize/(float)codePtr->numSrcBytes : #endif 0.0); #ifdef TCL_COMPILE_STATS Tcl_AppendPrintfToObj(bufferObj, " Code %lu = header %lu+inst %d+litObj %lu+exc %lu+aux %lu+cmdMap %d\n", (unsigned long) codePtr->structureSize, (unsigned long) (sizeof(ByteCode) - sizeof(size_t) - sizeof(Tcl_Time)), codePtr->numCodeBytes, (unsigned long) (codePtr->numLitObjects * sizeof(Tcl_Obj *)), (unsigned long) (codePtr->numExceptRanges*sizeof(ExceptionRange)), (unsigned long) (codePtr->numAuxDataItems * sizeof(AuxData)), codePtr->numCmdLocBytes); #endif /* TCL_COMPILE_STATS */ /* * If the ByteCode is the compiled body of a Tcl procedure, print * information about that procedure. Note that we don't know the * procedure's name since ByteCode's can be shared among procedures. */ if (codePtr->procPtr != NULL) { Proc *procPtr = codePtr->procPtr; int numCompiledLocals = procPtr->numCompiledLocals; sprintf(ptrBuf1, "%p", procPtr); Tcl_AppendPrintfToObj(bufferObj, " Proc 0x%s, refCt %d, args %d, compiled locals %d\n", ptrBuf1, procPtr->refCount, procPtr->numArgs, numCompiledLocals); if (numCompiledLocals > 0) { CompiledLocal *localPtr = procPtr->firstLocalPtr; for (i = 0; i < numCompiledLocals; i++) { Tcl_AppendPrintfToObj(bufferObj, " slot %d%s%s%s%s%s%s", i, (localPtr->flags & (VAR_ARRAY|VAR_LINK)) ? "" : ", scalar", (localPtr->flags & VAR_ARRAY) ? ", array" : "", (localPtr->flags & VAR_LINK) ? ", link" : "", (localPtr->flags & VAR_ARGUMENT) ? ", arg" : "", (localPtr->flags & VAR_TEMPORARY) ? ", temp" : "", (localPtr->flags & VAR_RESOLVED) ? ", resolved" : ""); if (TclIsVarTemporary(localPtr)) { Tcl_AppendToObj(bufferObj, "\n", -1); } else { Tcl_AppendPrintfToObj(bufferObj, ", \"%s\"\n", localPtr->name); } localPtr = localPtr->nextPtr; } } } /* * Print the ExceptionRange array. */ if (codePtr->numExceptRanges > 0) { Tcl_AppendPrintfToObj(bufferObj, " Exception ranges %d, depth %d:\n", codePtr->numExceptRanges, codePtr->maxExceptDepth); for (i = 0; i < codePtr->numExceptRanges; i++) { ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i]; Tcl_AppendPrintfToObj(bufferObj, " %d: level %d, %s, pc %d-%d, ", i, rangePtr->nestingLevel, (rangePtr->type==LOOP_EXCEPTION_RANGE ? "loop" : "catch"), rangePtr->codeOffset, (rangePtr->codeOffset + rangePtr->numCodeBytes - 1)); switch (rangePtr->type) { case LOOP_EXCEPTION_RANGE: Tcl_AppendPrintfToObj(bufferObj, "continue %d, break %d\n", rangePtr->continueOffset, rangePtr->breakOffset); break; case CATCH_EXCEPTION_RANGE: Tcl_AppendPrintfToObj(bufferObj, "catch %d\n", rangePtr->catchOffset); break; default: Tcl_Panic("DisassembleByteCodeObj: bad ExceptionRange type %d", rangePtr->type); } } } /* * If there were no commands (e.g., an expression or an empty string was * compiled), just print all instructions and return. */ if (numCmds == 0) { pc = codeStart; while (pc < codeLimit) { Tcl_AppendToObj(bufferObj, " ", -1); pc += FormatInstruction(codePtr, pc, bufferObj); } return bufferObj; } /* * Print table showing the code offset, source offset, and source length * for each command. These are encoded as a sequence of bytes. */ Tcl_AppendPrintfToObj(bufferObj, " Commands %d:", numCmds); codeDeltaNext = codePtr->codeDeltaStart; codeLengthNext = codePtr->codeLengthStart; srcDeltaNext = codePtr->srcDeltaStart; srcLengthNext = codePtr->srcLengthStart; codeOffset = srcOffset = 0; for (i = 0; i < numCmds; i++) { if ((unsigned) *codeDeltaNext == (unsigned) 0xFF) { codeDeltaNext++; delta = TclGetInt4AtPtr(codeDeltaNext); codeDeltaNext += 4; } else { delta = TclGetInt1AtPtr(codeDeltaNext); codeDeltaNext++; } codeOffset += delta; if ((unsigned) *codeLengthNext == (unsigned) 0xFF) { codeLengthNext++; codeLen = TclGetInt4AtPtr(codeLengthNext); codeLengthNext += 4; } else { codeLen = TclGetInt1AtPtr(codeLengthNext); codeLengthNext++; } if ((unsigned) *srcDeltaNext == (unsigned) 0xFF) { srcDeltaNext++; delta = TclGetInt4AtPtr(srcDeltaNext); srcDeltaNext += 4; } else { delta = TclGetInt1AtPtr(srcDeltaNext); srcDeltaNext++; } srcOffset += delta; if ((unsigned) *srcLengthNext == (unsigned) 0xFF) { srcLengthNext++; srcLen = TclGetInt4AtPtr(srcLengthNext); srcLengthNext += 4; } else { srcLen = TclGetInt1AtPtr(srcLengthNext); srcLengthNext++; } Tcl_AppendPrintfToObj(bufferObj, "%s%4d: pc %d-%d, src %d-%d", ((i % 2)? " " : "\n "), (i+1), codeOffset, (codeOffset + codeLen - 1), srcOffset, (srcOffset + srcLen - 1)); } if (numCmds > 0) { Tcl_AppendToObj(bufferObj, "\n", -1); } /* * Print each instruction. If the instruction corresponds to the start of * a command, print the command's source. Note that we don't need the code * length here. */ codeDeltaNext = codePtr->codeDeltaStart; srcDeltaNext = codePtr->srcDeltaStart; srcLengthNext = codePtr->srcLengthStart; codeOffset = srcOffset = 0; pc = codeStart; for (i = 0; i < numCmds; i++) { if ((unsigned) *codeDeltaNext == (unsigned) 0xFF) { codeDeltaNext++; delta = TclGetInt4AtPtr(codeDeltaNext); codeDeltaNext += 4; } else { delta = TclGetInt1AtPtr(codeDeltaNext); codeDeltaNext++; } codeOffset += delta; if ((unsigned) *srcDeltaNext == (unsigned) 0xFF) { srcDeltaNext++; delta = TclGetInt4AtPtr(srcDeltaNext); srcDeltaNext += 4; } else { delta = TclGetInt1AtPtr(srcDeltaNext); srcDeltaNext++; } srcOffset += delta; if ((unsigned) *srcLengthNext == (unsigned) 0xFF) { srcLengthNext++; srcLen = TclGetInt4AtPtr(srcLengthNext); srcLengthNext += 4; } else { srcLen = TclGetInt1AtPtr(srcLengthNext); srcLengthNext++; } /* * Print instructions before command i. */ while ((pc-codeStart) < codeOffset) { Tcl_AppendToObj(bufferObj, " ", -1); pc += FormatInstruction(codePtr, pc, bufferObj); } Tcl_AppendPrintfToObj(bufferObj, " Command %d: ", i+1); PrintSourceToObj(bufferObj, (codePtr->source + srcOffset), TclMin(srcLen, 55)); Tcl_AppendToObj(bufferObj, "\n", -1); } if (pc < codeLimit) { /* * Print instructions after the last command. */ while (pc < codeLimit) { Tcl_AppendToObj(bufferObj, " ", -1); pc += FormatInstruction(codePtr, pc, bufferObj); } } return bufferObj; } /* *---------------------------------------------------------------------- * * FormatInstruction -- * * Appends a representation of a bytecode instruction to a Tcl_Obj. * *---------------------------------------------------------------------- */ static int FormatInstruction( ByteCode *codePtr, /* Bytecode containing the instruction. */ const unsigned char *pc, /* Points to first byte of instruction. */ Tcl_Obj *bufferObj) /* Object to append instruction info to. */ { Proc *procPtr = codePtr->procPtr; unsigned char opCode = *pc; register const InstructionDesc *instDesc = &tclInstructionTable[opCode]; unsigned char *codeStart = codePtr->codeStart; unsigned pcOffset = pc - codeStart; int opnd = 0, i, j, numBytes = 1; int localCt = procPtr ? procPtr->numCompiledLocals : 0; CompiledLocal *localPtr = procPtr ? procPtr->firstLocalPtr : NULL; char suffixBuffer[128]; /* Additional info to print after main opcode * and immediates. */ char *suffixSrc = NULL; Tcl_Obj *suffixObj = NULL; AuxData *auxPtr = NULL; suffixBuffer[0] = '\0'; Tcl_AppendPrintfToObj(bufferObj, "(%u) %s ", pcOffset, instDesc->name); for (i = 0; i < instDesc->numOperands; i++) { switch (instDesc->opTypes[i]) { case OPERAND_INT1: opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++; Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd); break; case OPERAND_INT4: opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4; Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd); break; case OPERAND_UINT1: opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++; Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd); break; case OPERAND_UINT4: opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4; if (opCode == INST_START_CMD) { sprintf(suffixBuffer+strlen(suffixBuffer), ", %u cmds start here", opnd); } Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd); break; case OPERAND_OFFSET1: opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++; sprintf(suffixBuffer, "pc %u", pcOffset+opnd); Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd); break; case OPERAND_OFFSET4: opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4; if (opCode == INST_START_CMD) { sprintf(suffixBuffer, "next cmd at pc %u", pcOffset+opnd); } else { sprintf(suffixBuffer, "pc %u", pcOffset+opnd); } Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd); break; case OPERAND_LIT1: opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++; suffixObj = codePtr->objArrayPtr[opnd]; Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd); break; case OPERAND_LIT4: opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4; suffixObj = codePtr->objArrayPtr[opnd]; Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd); break; case OPERAND_AUX4: opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4; Tcl_AppendPrintfToObj(bufferObj, "%u ", (unsigned) opnd); auxPtr = &codePtr->auxDataArrayPtr[opnd]; break; case OPERAND_IDX4: opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4; if (opnd >= -1) { Tcl_AppendPrintfToObj(bufferObj, "%d ", opnd); } else if (opnd == -2) { Tcl_AppendPrintfToObj(bufferObj, "end "); } else { Tcl_AppendPrintfToObj(bufferObj, "end-%d ", -2-opnd); } break; case OPERAND_LVT1: opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++; goto printLVTindex; case OPERAND_LVT4: opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4; printLVTindex: if (localPtr != NULL) { if (opnd >= localCt) { Tcl_Panic("FormatInstruction: bad local var index %u (%u locals)", (unsigned) opnd, localCt); } for (j = 0; j < opnd; j++) { localPtr = localPtr->nextPtr; } if (TclIsVarTemporary(localPtr)) { sprintf(suffixBuffer, "temp var %u", (unsigned) opnd); } else { sprintf(suffixBuffer, "var "); suffixSrc = localPtr->name; } } Tcl_AppendPrintfToObj(bufferObj, "%%v%u ", (unsigned) opnd); break; case OPERAND_SCLS1: opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++; Tcl_AppendPrintfToObj(bufferObj, "%s ", tclStringClassTable[opnd].name); break; case OPERAND_NONE: default: break; } } if (suffixObj) { const char *bytes; int length; Tcl_AppendToObj(bufferObj, "\t# ", -1); bytes = Tcl_GetStringFromObj(codePtr->objArrayPtr[opnd], &length); PrintSourceToObj(bufferObj, bytes, TclMin(length, 40)); } else if (suffixBuffer[0]) { Tcl_AppendPrintfToObj(bufferObj, "\t# %s", suffixBuffer); if (suffixSrc) { PrintSourceToObj(bufferObj, suffixSrc, 40); } } Tcl_AppendToObj(bufferObj, "\n", -1); if (auxPtr && auxPtr->type->printProc) { Tcl_AppendToObj(bufferObj, "\t\t[", -1); auxPtr->type->printProc(auxPtr->clientData, bufferObj, codePtr, pcOffset); Tcl_AppendToObj(bufferObj, "]\n", -1); } return numBytes; } /* *---------------------------------------------------------------------- * * TclGetInnerContext -- * * If possible, returns a list capturing the inner context. Otherwise * return NULL. * *---------------------------------------------------------------------- */ Tcl_Obj * TclGetInnerContext( Tcl_Interp *interp, const unsigned char *pc, Tcl_Obj **tosPtr) { int objc = 0, off = 0; Tcl_Obj *result; Interp *iPtr = (Interp *) interp; switch (*pc) { case INST_STR_LEN: case INST_LNOT: case INST_BITNOT: case INST_UMINUS: case INST_UPLUS: case INST_TRY_CVT_TO_NUMERIC: case INST_EXPAND_STKTOP: case INST_EXPR_STK: objc = 1; break; case INST_LIST_IN: case INST_LIST_NOT_IN: /* Basic list containment operators. */ case INST_STR_EQ: case INST_STR_NEQ: /* String (in)equality check */ case INST_STR_CMP: /* String compare. */ case INST_STR_INDEX: case INST_STR_MATCH: case INST_REGEXP: case INST_EQ: case INST_NEQ: case INST_LT: case INST_GT: case INST_LE: case INST_GE: case INST_MOD: case INST_LSHIFT: case INST_RSHIFT: case INST_BITOR: case INST_BITXOR: case INST_BITAND: case INST_EXPON: case INST_ADD: case INST_SUB: case INST_DIV: case INST_MULT: objc = 2; break; case INST_RETURN_STK: /* early pop. TODO: dig out opt dict too :/ */ objc = 1; break; case INST_SYNTAX: case INST_RETURN_IMM: objc = 2; break; case INST_INVOKE_STK4: objc = TclGetUInt4AtPtr(pc+1); break; case INST_INVOKE_STK1: objc = TclGetUInt1AtPtr(pc+1); break; } result = iPtr->innerContext; if (Tcl_IsShared(result)) { Tcl_DecrRefCount(result); iPtr->innerContext = result = Tcl_NewListObj(objc + 1, NULL); Tcl_IncrRefCount(result); } else { int len; /* * Reset while keeping the list intrep as much as possible. */ Tcl_ListObjLength(interp, result, &len); Tcl_ListObjReplace(interp, result, 0, len, 0, NULL); } Tcl_ListObjAppendElement(NULL, result, TclNewInstNameObj(*pc)); for (; objc>0 ; objc--) { Tcl_Obj *objPtr; objPtr = tosPtr[1 - objc + off]; if (!objPtr) { Tcl_Panic("InnerContext: bad tos -- appending null object"); } if ((objPtr->refCount<=0) #ifdef TCL_MEM_DEBUG || (objPtr->refCount==0x61616161) #endif ) { Tcl_Panic("InnerContext: bad tos -- appending freed object %p", objPtr); } Tcl_ListObjAppendElement(NULL, result, objPtr); } return result; } /* *---------------------------------------------------------------------- * * TclNewInstNameObj -- * * Creates a new InstName Tcl_Obj based on the given instruction * *---------------------------------------------------------------------- */ Tcl_Obj * TclNewInstNameObj( unsigned char inst) { Tcl_Obj *objPtr = Tcl_NewObj(); objPtr->typePtr = &tclInstNameType; objPtr->internalRep.longValue = (long) inst; objPtr->bytes = NULL; return objPtr; } /* *---------------------------------------------------------------------- * * UpdateStringOfInstName -- * * Update the string representation for an instruction name object. * *---------------------------------------------------------------------- */ static void UpdateStringOfInstName( Tcl_Obj *objPtr) { int inst = objPtr->internalRep.longValue; char *s, buf[20]; int len; if ((inst < 0) || (inst > LAST_INST_OPCODE)) { sprintf(buf, "inst_%d", inst); s = buf; } else { s = (char *) tclInstructionTable[objPtr->internalRep.longValue].name; } len = strlen(s); objPtr->bytes = ckalloc(len + 1); memcpy(objPtr->bytes, s, len + 1); objPtr->length = len; } /* *---------------------------------------------------------------------- * * PrintSourceToObj -- * * Appends a quoted representation of a string to a Tcl_Obj. * *---------------------------------------------------------------------- */ static void PrintSourceToObj( Tcl_Obj *appendObj, /* The object to print the source to. */ const char *stringPtr, /* The string to print. */ int maxChars) /* Maximum number of chars to print. */ { register const char *p; register int i = 0, len; Tcl_UniChar ch = 0; if (stringPtr == NULL) { Tcl_AppendToObj(appendObj, "\"\"", -1); return; } Tcl_AppendToObj(appendObj, "\"", -1); p = stringPtr; for (; (*p != '\0') && (i < maxChars); p+=len) { len = TclUtfToUniChar(p, &ch); switch (ch) { case '"': Tcl_AppendToObj(appendObj, "\\\"", -1); i += 2; continue; case '\f': Tcl_AppendToObj(appendObj, "\\f", -1); i += 2; continue; case '\n': Tcl_AppendToObj(appendObj, "\\n", -1); i += 2; continue; case '\r': Tcl_AppendToObj(appendObj, "\\r", -1); i += 2; continue; case '\t': Tcl_AppendToObj(appendObj, "\\t", -1); i += 2; continue; case '\v': Tcl_AppendToObj(appendObj, "\\v", -1); i += 2; continue; default: #if TCL_UTF_MAX > 4 if (ch > 0xffff) { Tcl_AppendPrintfToObj(appendObj, "\\U%08x", ch); i += 10; } else #elif TCL_UTF_MAX > 3 /* If len == 0, this means we have a char > 0xffff, resulting in * TclUtfToUniChar producing a surrogate pair. We want to output * this pair as a single Unicode character. */ if (len == 0) { int upper = ((ch & 0x3ff) + 1) << 10; len = TclUtfToUniChar(p, &ch); Tcl_AppendPrintfToObj(appendObj, "\\U%08x", upper + (ch & 0x3ff)); i += 10; } else #endif if (ch < 0x20 || ch >= 0x7f) { Tcl_AppendPrintfToObj(appendObj, "\\u%04x", ch); i += 6; } else { Tcl_AppendPrintfToObj(appendObj, "%c", ch); i++; } continue; } } if (*p != '\0') { Tcl_AppendToObj(appendObj, "...", -1); } Tcl_AppendToObj(appendObj, "\"", -1); } /* *---------------------------------------------------------------------- * * DisassembleByteCodeAsDicts -- * * Given an object which is of bytecode type, return a disassembled * version of the bytecode (in a new refcount 0 object) in a dictionary. * No guarantees are made about the details of the contents of the * result, but it is intended to be more readable than the old output * format. * *---------------------------------------------------------------------- */ static Tcl_Obj * DisassembleByteCodeAsDicts( Tcl_Interp *interp, /* Used for looking up the CmdFrame for the * procedure, if one exists. */ Tcl_Obj *objPtr) /* The bytecode-holding value to take apart */ { ByteCode *codePtr = BYTECODE(objPtr); Tcl_Obj *description, *literals, *variables, *instructions, *inst; Tcl_Obj *aux, *exn, *commands, *file; unsigned char *pc, *opnd, *codeOffPtr, *codeLenPtr, *srcOffPtr, *srcLenPtr; int codeOffset, codeLength, sourceOffset, sourceLength; int i, val, line; /* * Get the literals from the bytecode. */ literals = Tcl_NewObj(); for (i=0 ; inumLitObjects ; i++) { Tcl_ListObjAppendElement(NULL, literals, codePtr->objArrayPtr[i]); } /* * Get the variables from the bytecode. */ variables = Tcl_NewObj(); if (codePtr->procPtr) { int localCount = codePtr->procPtr->numCompiledLocals; CompiledLocal *localPtr = codePtr->procPtr->firstLocalPtr; for (i=0 ; inextPtr) { Tcl_Obj *descriptor[2]; descriptor[0] = Tcl_NewObj(); if (!(localPtr->flags & (VAR_ARRAY|VAR_LINK))) { Tcl_ListObjAppendElement(NULL, descriptor[0], Tcl_NewStringObj("scalar", -1)); } if (localPtr->flags & VAR_ARRAY) { Tcl_ListObjAppendElement(NULL, descriptor[0], Tcl_NewStringObj("array", -1)); } if (localPtr->flags & VAR_LINK) { Tcl_ListObjAppendElement(NULL, descriptor[0], Tcl_NewStringObj("link", -1)); } if (localPtr->flags & VAR_ARGUMENT) { Tcl_ListObjAppendElement(NULL, descriptor[0], Tcl_NewStringObj("arg", -1)); } if (localPtr->flags & VAR_TEMPORARY) { Tcl_ListObjAppendElement(NULL, descriptor[0], Tcl_NewStringObj("temp", -1)); } if (localPtr->flags & VAR_RESOLVED) { Tcl_ListObjAppendElement(NULL, descriptor[0], Tcl_NewStringObj("resolved", -1)); } if (localPtr->flags & VAR_TEMPORARY) { Tcl_ListObjAppendElement(NULL, variables, Tcl_NewListObj(1, descriptor)); } else { descriptor[1] = Tcl_NewStringObj(localPtr->name, -1); Tcl_ListObjAppendElement(NULL, variables, Tcl_NewListObj(2, descriptor)); } } } /* * Get the instructions from the bytecode. */ instructions = Tcl_NewObj(); for (pc=codePtr->codeStart; pccodeStart+codePtr->numCodeBytes;){ const InstructionDesc *instDesc = &tclInstructionTable[*pc]; int address = pc - codePtr->codeStart; inst = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, inst, Tcl_NewStringObj( instDesc->name, -1)); opnd = pc + 1; for (i=0 ; inumOperands ; i++) { switch (instDesc->opTypes[i]) { case OPERAND_INT1: val = TclGetInt1AtPtr(opnd); opnd += 1; goto formatNumber; case OPERAND_UINT1: val = TclGetUInt1AtPtr(opnd); opnd += 1; goto formatNumber; case OPERAND_INT4: val = TclGetInt4AtPtr(opnd); opnd += 4; goto formatNumber; case OPERAND_UINT4: val = TclGetUInt4AtPtr(opnd); opnd += 4; formatNumber: Tcl_ListObjAppendElement(NULL, inst, Tcl_NewIntObj(val)); break; case OPERAND_OFFSET1: val = TclGetInt1AtPtr(opnd); opnd += 1; goto formatAddress; case OPERAND_OFFSET4: val = TclGetInt4AtPtr(opnd); opnd += 4; formatAddress: Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf( "pc %d", address + val)); break; case OPERAND_LIT1: val = TclGetUInt1AtPtr(opnd); opnd += 1; goto formatLiteral; case OPERAND_LIT4: val = TclGetUInt4AtPtr(opnd); opnd += 4; formatLiteral: Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf( "@%d", val)); break; case OPERAND_LVT1: val = TclGetUInt1AtPtr(opnd); opnd += 1; goto formatVariable; case OPERAND_LVT4: val = TclGetUInt4AtPtr(opnd); opnd += 4; formatVariable: Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf( "%%%d", val)); break; case OPERAND_IDX4: val = TclGetInt4AtPtr(opnd); opnd += 4; if (val >= -1) { Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf( ".%d", val)); } else if (val == -2) { Tcl_ListObjAppendElement(NULL, inst, Tcl_NewStringObj( ".end", -1)); } else { Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf( ".end-%d", -2-val)); } break; case OPERAND_AUX4: val = TclGetInt4AtPtr(opnd); opnd += 4; Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf( "?%d", val)); break; case OPERAND_SCLS1: val = TclGetUInt1AtPtr(opnd); opnd++; Tcl_ListObjAppendElement(NULL, inst, Tcl_ObjPrintf( "=%s", tclStringClassTable[val].name)); break; case OPERAND_NONE: Tcl_Panic("opcode %d with more than zero 'no' operands", *pc); } } Tcl_DictObjPut(NULL, instructions, Tcl_NewIntObj(address), inst); pc += instDesc->numBytes; } /* * Get the auxiliary data from the bytecode. */ aux = Tcl_NewObj(); for (i=0 ; inumAuxDataItems ; i++) { AuxData *auxData = &codePtr->auxDataArrayPtr[i]; Tcl_Obj *auxDesc = Tcl_NewStringObj(auxData->type->name, -1); if (auxData->type->disassembleProc) { Tcl_Obj *desc = Tcl_NewObj(); Tcl_DictObjPut(NULL, desc, Tcl_NewStringObj("name", -1), auxDesc); auxDesc = desc; auxData->type->disassembleProc(auxData->clientData, auxDesc, codePtr, 0); } else if (auxData->type->printProc) { Tcl_Obj *desc = Tcl_NewObj(); auxData->type->printProc(auxData->clientData, desc, codePtr, 0); Tcl_ListObjAppendElement(NULL, auxDesc, desc); } Tcl_ListObjAppendElement(NULL, aux, auxDesc); } /* * Get the exception ranges from the bytecode. */ exn = Tcl_NewObj(); for (i=0 ; inumExceptRanges ; i++) { ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i]; switch (rangePtr->type) { case LOOP_EXCEPTION_RANGE: Tcl_ListObjAppendElement(NULL, exn, Tcl_ObjPrintf( "type %s level %d from %d to %d break %d continue %d", "loop", rangePtr->nestingLevel, rangePtr->codeOffset, rangePtr->codeOffset + rangePtr->numCodeBytes - 1, rangePtr->breakOffset, rangePtr->continueOffset)); break; case CATCH_EXCEPTION_RANGE: Tcl_ListObjAppendElement(NULL, exn, Tcl_ObjPrintf( "type %s level %d from %d to %d catch %d", "catch", rangePtr->nestingLevel, rangePtr->codeOffset, rangePtr->codeOffset + rangePtr->numCodeBytes - 1, rangePtr->catchOffset)); break; } } /* * Get the command information from the bytecode. * * The way these are encoded in the bytecode is non-trivial; the Decode * macro (which updates its argument and returns the next decoded value) * handles this so that the rest of the code does not. */ #define Decode(ptr) \ ((TclGetUInt1AtPtr(ptr) == 0xFF) \ ? ((ptr)+=5 , TclGetInt4AtPtr((ptr)-4)) \ : ((ptr)+=1 , TclGetInt1AtPtr((ptr)-1))) commands = Tcl_NewObj(); codeOffPtr = codePtr->codeDeltaStart; codeLenPtr = codePtr->codeLengthStart; srcOffPtr = codePtr->srcDeltaStart; srcLenPtr = codePtr->srcLengthStart; codeOffset = sourceOffset = 0; for (i=0 ; inumCommands ; i++) { Tcl_Obj *cmd; codeOffset += Decode(codeOffPtr); codeLength = Decode(codeLenPtr); sourceOffset += Decode(srcOffPtr); sourceLength = Decode(srcLenPtr); cmd = Tcl_NewObj(); Tcl_DictObjPut(NULL, cmd, Tcl_NewStringObj("codefrom", -1), Tcl_NewIntObj(codeOffset)); Tcl_DictObjPut(NULL, cmd, Tcl_NewStringObj("codeto", -1), Tcl_NewIntObj(codeOffset + codeLength - 1)); /* * Convert byte offsets to character offsets; important if multibyte * characters are present in the source! */ Tcl_DictObjPut(NULL, cmd, Tcl_NewStringObj("scriptfrom", -1), Tcl_NewIntObj(Tcl_NumUtfChars(codePtr->source, sourceOffset))); Tcl_DictObjPut(NULL, cmd, Tcl_NewStringObj("scriptto", -1), Tcl_NewIntObj(Tcl_NumUtfChars(codePtr->source, sourceOffset + sourceLength - 1))); Tcl_DictObjPut(NULL, cmd, Tcl_NewStringObj("script", -1), Tcl_NewStringObj(codePtr->source+sourceOffset, sourceLength)); Tcl_ListObjAppendElement(NULL, commands, cmd); } #undef Decode /* * Get the source file and line number information from the CmdFrame * system if it is available. */ GetLocationInformation(interp, codePtr->procPtr, &file, &line); /* * Build the overall result. */ description = Tcl_NewObj(); Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("literals", -1), literals); Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("variables", -1), variables); Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("exception", -1), exn); Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("instructions", -1), instructions); Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("auxiliary", -1), aux); Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("commands", -1), commands); Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("script", -1), Tcl_NewStringObj(codePtr->source, codePtr->numSrcBytes)); Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("namespace", -1), Tcl_NewStringObj(codePtr->nsPtr->fullName, -1)); Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("stackdepth", -1), Tcl_NewIntObj(codePtr->maxStackDepth)); Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("exceptdepth", -1), Tcl_NewIntObj(codePtr->maxExceptDepth)); if (line > -1) { Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("initiallinenumber", -1), Tcl_NewIntObj(line)); } if (file) { Tcl_DictObjPut(NULL, description, Tcl_NewStringObj("sourcefile", -1), file); } return description; } /* *---------------------------------------------------------------------- * * Tcl_DisassembleObjCmd -- * * Implementation of the "::tcl::unsupported::disassemble" command. This * command is not documented, but will disassemble procedures, lambda * terms and general scripts. Note that will compile terms if necessary * in order to disassemble them. * *---------------------------------------------------------------------- */ int Tcl_DisassembleObjCmd( ClientData clientData, /* What type of operation. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const types[] = { "lambda", "method", "objmethod", "proc", "script", NULL }; enum Types { DISAS_LAMBDA, DISAS_CLASS_METHOD, DISAS_OBJECT_METHOD, DISAS_PROC, DISAS_SCRIPT }; int idx, result; Tcl_Obj *codeObjPtr = NULL; Proc *procPtr = NULL; Tcl_HashEntry *hPtr; Object *oPtr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "type ..."); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], types, "type", 0, &idx)!=TCL_OK){ return TCL_ERROR; } switch ((enum Types) idx) { case DISAS_LAMBDA: { Command cmd; Tcl_Obj *nsObjPtr; Tcl_Namespace *nsPtr; /* * Compile (if uncompiled) and disassemble a lambda term. * * WARNING! Pokes inside the lambda objtype. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "lambdaTerm"); return TCL_ERROR; } if (objv[2]->typePtr == &tclLambdaType) { procPtr = objv[2]->internalRep.twoPtrValue.ptr1; } if (procPtr == NULL || procPtr->iPtr != (Interp *) interp) { result = tclLambdaType.setFromAnyProc(interp, objv[2]); if (result != TCL_OK) { return result; } procPtr = objv[2]->internalRep.twoPtrValue.ptr1; } memset(&cmd, 0, sizeof(Command)); nsObjPtr = objv[2]->internalRep.twoPtrValue.ptr2; result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); if (result != TCL_OK) { return result; } cmd.nsPtr = (Namespace *) nsPtr; procPtr->cmdPtr = &cmd; result = TclPushProcCallFrame(procPtr, interp, objc, objv, 1); if (result != TCL_OK) { return result; } TclPopStackFrame(interp); codeObjPtr = procPtr->bodyPtr; break; } case DISAS_PROC: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "procName"); return TCL_ERROR; } procPtr = TclFindProc((Interp *) interp, TclGetString(objv[2])); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't a procedure", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PROC", TclGetString(objv[2]), NULL); return TCL_ERROR; } /* * Compile (if uncompiled) and disassemble a procedure. */ result = TclPushProcCallFrame(procPtr, interp, 2, objv+1, 1); if (result != TCL_OK) { return result; } TclPopStackFrame(interp); codeObjPtr = procPtr->bodyPtr; break; case DISAS_SCRIPT: /* * Compile and disassemble a script. */ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "script"); return TCL_ERROR; } if ((objv[2]->typePtr != &tclByteCodeType) && (TclSetByteCodeFromAny(interp, objv[2], NULL, NULL) != TCL_OK)) { return TCL_ERROR; } codeObjPtr = objv[2]; break; case DISAS_CLASS_METHOD: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "className methodName"); return TCL_ERROR; } /* * Look up the body of a class method. */ oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]); if (oPtr == NULL) { return TCL_ERROR; } if (oPtr->classPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not a class", TclGetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS", TclGetString(objv[2]), NULL); return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods, (char *) objv[3]); goto methodBody; case DISAS_OBJECT_METHOD: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "objectName methodName"); return TCL_ERROR; } /* * Look up the body of an instance method. */ oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]); if (oPtr == NULL) { return TCL_ERROR; } if (oPtr->methodsPtr == NULL) { goto unknownMethod; } hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[3]); /* * Compile (if necessary) and disassemble a method body. */ methodBody: if (hPtr == NULL) { unknownMethod: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown method \"%s\"", TclGetString(objv[3]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD", TclGetString(objv[3]), NULL); return TCL_ERROR; } procPtr = TclOOGetProcFromMethod(Tcl_GetHashValue(hPtr)); if (procPtr == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "body not available for this kind of method", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE", "METHODTYPE", NULL); return TCL_ERROR; } if (procPtr->bodyPtr->typePtr != &tclByteCodeType) { Command cmd; /* * Yes, this is ugly, but we need to pass the namespace in to the * compiler in two places. */ cmd.nsPtr = (Namespace *) oPtr->namespacePtr; procPtr->cmdPtr = &cmd; result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr, (Namespace *) oPtr->namespacePtr, "body of method", TclGetString(objv[3])); procPtr->cmdPtr = NULL; if (result != TCL_OK) { return result; } } codeObjPtr = procPtr->bodyPtr; break; default: CLANG_ASSERT(0); } /* * Do the actual disassembly. */ if (BYTECODE(codeObjPtr)->flags & TCL_BYTECODE_PRECOMPILED) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may not disassemble prebuilt bytecode", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "DISASSEMBLE", "BYTECODE", NULL); return TCL_ERROR; } if (PTR2INT(clientData)) { Tcl_SetObjResult(interp, DisassembleByteCodeAsDicts(interp, codeObjPtr)); } else { Tcl_SetObjResult(interp, DisassembleByteCodeObj(interp, codeObjPtr)); } return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * End: */ tcl8.6.5/generic/tclObj.c0000644000175000017500000037771012663660065014603 0ustar sergeisergei/* * tclObj.c -- * * This file contains Tcl object-related functions that are used by many * Tcl commands. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1999 by Scriptics Corporation. * Copyright (c) 2001 by ActiveState Corporation. * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tommath.h" #include /* * Table of all object types. */ static Tcl_HashTable typeTable; static int typeTableInitialized = 0; /* 0 means not yet initialized. */ TCL_DECLARE_MUTEX(tableMutex) /* * Head of the list of free Tcl_Obj structs we maintain. */ Tcl_Obj *tclFreeObjList = NULL; /* * The object allocator is single threaded. This mutex is referenced by the * TclNewObj macro, however, so must be visible. */ #ifdef TCL_THREADS MODULE_SCOPE Tcl_Mutex tclObjMutex; Tcl_Mutex tclObjMutex; #endif /* * Pointer to a heap-allocated string of length zero that the Tcl core uses as * the value of an empty string representation for an object. This value is * shared by all new objects allocated by Tcl_NewObj. */ char tclEmptyString = '\0'; char *tclEmptyStringRep = &tclEmptyString; #if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS) /* * Structure for tracking the source file and line number where a given * Tcl_Obj was allocated. We also track the pointer to the Tcl_Obj itself, * for sanity checking purposes. */ typedef struct ObjData { Tcl_Obj *objPtr; /* The pointer to the allocated Tcl_Obj. */ const char *file; /* The name of the source file calling this * function; used for debugging. */ int line; /* Line number in the source file; used for * debugging. */ } ObjData; #endif /* TCL_MEM_DEBUG && TCL_THREADS */ /* * All static variables used in this file are collected into a single instance * of the following structure. For multi-threaded implementations, there is * one instance of this structure for each thread. * * Notice that different structures with the same name appear in other files. * The structure defined below is used in this file only. */ typedef struct ThreadSpecificData { Tcl_HashTable *lineCLPtr; /* This table remembers for each Tcl_Obj * generated by a call to the function * TclSubstTokens() from a literal text * where bs+nl sequences occured in it, if * any. I.e. this table keeps track of * invisible and stripped continuation lines. * Its keys are Tcl_Obj pointers, the values * are ContLineLoc pointers. See the file * tclCompile.h for the definition of this * structure, and for references to all * related places in the core. */ #if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS) Tcl_HashTable *objThreadMap;/* Thread local table that is used to check * that a Tcl_Obj was not allocated by some * other thread. */ #endif /* TCL_MEM_DEBUG && TCL_THREADS */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; static void TclThreadFinalizeContLines(ClientData clientData); static ThreadSpecificData *TclGetContLineTable(void); /* * Nested Tcl_Obj deletion management support * * All context references used in the object freeing code are pointers to this * structure; every thread will have its own structure instance. The purpose * of this structure is to allow deeply nested collections of Tcl_Objs to be * freed without taking a vast depth of C stack (which could cause all sorts * of breakage.) */ typedef struct PendingObjData { int deletionCount; /* Count of the number of invokations of * TclFreeObj() are on the stack (at least * conceptually; many are actually expanded * macros). */ Tcl_Obj *deletionStack; /* Stack of objects that have had TclFreeObj() * invoked upon them but which can't be * deleted yet because they are in a nested * invokation of TclFreeObj(). By postponing * this way, we limit the maximum overall C * stack depth when deleting a complex object. * The down-side is that we alter the overall * behaviour by altering the order in which * objects are deleted, and we change the * order in which the string rep and the * internal rep of an object are deleted. Note * that code which assumes the previous * behaviour in either of these respects is * unsafe anyway; it was never documented as * to exactly what would happen in these * cases, and the overall contract of a * user-level Tcl_DecrRefCount() is still * preserved (assuming that a particular T_DRC * would delete an object is not very * safe). */ } PendingObjData; /* * These are separated out so that some semantic content is attached * to them. */ #define ObjDeletionLock(contextPtr) ((contextPtr)->deletionCount++) #define ObjDeletionUnlock(contextPtr) ((contextPtr)->deletionCount--) #define ObjDeletePending(contextPtr) ((contextPtr)->deletionCount > 0) #define ObjOnStack(contextPtr) ((contextPtr)->deletionStack != NULL) #define PushObjToDelete(contextPtr,objPtr) \ /* The string rep is already invalidated so we can use the bytes value \ * for our pointer chain: push onto the head of the stack. */ \ (objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \ (contextPtr)->deletionStack = (objPtr) #define PopObjToDelete(contextPtr,objPtrVar) \ (objPtrVar) = (contextPtr)->deletionStack; \ (contextPtr)->deletionStack = (Tcl_Obj *) (objPtrVar)->bytes /* * Macro to set up the local reference to the deletion context. */ #ifndef TCL_THREADS static PendingObjData pendingObjData; #define ObjInitDeletionContext(contextPtr) \ PendingObjData *const contextPtr = &pendingObjData #elif HAVE_FAST_TSD static __thread PendingObjData pendingObjData; #define ObjInitDeletionContext(contextPtr) \ PendingObjData *const contextPtr = &pendingObjData #else static Tcl_ThreadDataKey pendingObjDataKey; #define ObjInitDeletionContext(contextPtr) \ PendingObjData *const contextPtr = \ Tcl_GetThreadData(&pendingObjDataKey, sizeof(PendingObjData)) #endif /* * Macros to pack/unpack a bignum's fields in a Tcl_Obj internal rep */ #define PACK_BIGNUM(bignum, objPtr) \ if ((bignum).used > 0x7fff) { \ mp_int *temp = (void *) ckalloc((unsigned) sizeof(mp_int)); \ *temp = bignum; \ (objPtr)->internalRep.twoPtrValue.ptr1 = temp; \ (objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1); \ } else { \ if ((bignum).alloc > 0x7fff) { \ mp_shrink(&(bignum)); \ } \ (objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (bignum).dp; \ (objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR( ((bignum).sign << 30) \ | ((bignum).alloc << 15) | ((bignum).used)); \ } #define UNPACK_BIGNUM(objPtr, bignum) \ if ((objPtr)->internalRep.twoPtrValue.ptr2 == INT2PTR(-1)) { \ (bignum) = *((mp_int *) ((objPtr)->internalRep.twoPtrValue.ptr1)); \ } else { \ (bignum).dp = (objPtr)->internalRep.twoPtrValue.ptr1; \ (bignum).sign = PTR2INT((objPtr)->internalRep.twoPtrValue.ptr2) >> 30; \ (bignum).alloc = \ (PTR2INT((objPtr)->internalRep.twoPtrValue.ptr2) >> 15) & 0x7fff; \ (bignum).used = PTR2INT((objPtr)->internalRep.twoPtrValue.ptr2) & 0x7fff; \ } /* * Prototypes for functions defined later in this file: */ static int ParseBoolean(Tcl_Obj *objPtr); static int SetDoubleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static int SetIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void UpdateStringOfDouble(Tcl_Obj *objPtr); static void UpdateStringOfInt(Tcl_Obj *objPtr); #ifndef TCL_WIDE_INT_IS_LONG static void UpdateStringOfWideInt(Tcl_Obj *objPtr); static int SetWideIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); #endif static void FreeBignum(Tcl_Obj *objPtr); static void DupBignum(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); static void UpdateStringOfBignum(Tcl_Obj *objPtr); static int GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int copy, mp_int *bignumValue); /* * Prototypes for the array hash key methods. */ static Tcl_HashEntry * AllocObjEntry(Tcl_HashTable *tablePtr, void *keyPtr); /* * Prototypes for the CommandName object type. */ static void DupCmdNameInternalRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); static void FreeCmdNameInternalRep(Tcl_Obj *objPtr); static int SetCmdNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); /* * The structures below defines the Tcl object types defined in this file by * means of functions that can be invoked by generic object code. See also * tclStringObj.c, tclListObj.c, tclByteCode.c for other type manager * implementations. */ static const Tcl_ObjType oldBooleanType = { "boolean", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ NULL, /* updateStringProc */ TclSetBooleanFromAny /* setFromAnyProc */ }; const Tcl_ObjType tclBooleanType = { "booleanString", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ NULL, /* updateStringProc */ TclSetBooleanFromAny /* setFromAnyProc */ }; const Tcl_ObjType tclDoubleType = { "double", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ UpdateStringOfDouble, /* updateStringProc */ SetDoubleFromAny /* setFromAnyProc */ }; const Tcl_ObjType tclIntType = { "int", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ UpdateStringOfInt, /* updateStringProc */ SetIntFromAny /* setFromAnyProc */ }; #ifndef TCL_WIDE_INT_IS_LONG const Tcl_ObjType tclWideIntType = { "wideInt", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ UpdateStringOfWideInt, /* updateStringProc */ SetWideIntFromAny /* setFromAnyProc */ }; #endif const Tcl_ObjType tclBignumType = { "bignum", /* name */ FreeBignum, /* freeIntRepProc */ DupBignum, /* dupIntRepProc */ UpdateStringOfBignum, /* updateStringProc */ NULL /* setFromAnyProc */ }; /* * The structure below defines the Tcl obj hash key type. */ const Tcl_HashKeyType tclObjHashKeyType = { TCL_HASH_KEY_TYPE_VERSION, /* version */ 0, /* flags */ TclHashObjKey, /* hashKeyProc */ TclCompareObjKeys, /* compareKeysProc */ AllocObjEntry, /* allocEntryProc */ TclFreeObjEntry /* freeEntryProc */ }; /* * The structure below defines the command name Tcl object type by means of * functions that can be invoked by generic object code. Objects of this type * cache the Command pointer that results from looking up command names in the * command hashtable. Such objects appear as the zeroth ("command name") * argument in a Tcl command. * * NOTE: the ResolvedCmdName that gets cached is stored in the * twoPtrValue.ptr1 field, and the twoPtrValue.ptr2 field is unused. You might * think you could use the simpler otherValuePtr field to store the single * ResolvedCmdName pointer, but DO NOT DO THIS. It seems that some extensions * use the second internal pointer field of the twoPtrValue field for their * own purposes. * * TRICKY POINT! Some extensions update this structure! (Notably, these * include TclBlend and TCom). This is highly ill-advised on their part, but * does allow them to delete a command when references to it are gone, which * is fragile but useful given their somewhat-OO style. Because of this, this * structure MUST NOT be const so that the C compiler puts the data in * writable memory. [Bug 2558422] * TODO: Provide a better API for those extensions so that they can coexist... */ Tcl_ObjType tclCmdNameType = { "cmdName", /* name */ FreeCmdNameInternalRep, /* freeIntRepProc */ DupCmdNameInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ SetCmdNameFromAny /* setFromAnyProc */ }; /* * Structure containing a cached pointer to a command that is the result of * resolving the command's name in some namespace. It is the internal * representation for a cmdName object. It contains the pointer along with * some information that is used to check the pointer's validity. */ typedef struct ResolvedCmdName { Command *cmdPtr; /* A cached Command pointer. */ Namespace *refNsPtr; /* Points to the namespace containing the * reference (not the namespace that contains * the referenced command). NULL if the name * is fully qualified.*/ long refNsId; /* refNsPtr's unique namespace id. Used to * verify that refNsPtr is still valid (e.g., * it's possible that the cmd's containing * namespace was deleted and a new one created * at the same address). */ int refNsCmdEpoch; /* Value of the referencing namespace's * cmdRefEpoch when the pointer was cached. * Before using the cached pointer, we check * if the namespace's epoch was incremented; * if so, this cached pointer is invalid. */ int cmdEpoch; /* Value of the command's cmdEpoch when this * pointer was cached. Before using the cached * pointer, we check if the cmd's epoch was * incremented; if so, the cmd was renamed, * deleted, hidden, or exposed, and so the * pointer is invalid. */ int refCount; /* Reference count: 1 for each cmdName object * that has a pointer to this ResolvedCmdName * structure as its internal rep. This * structure can be freed when refCount * becomes zero. */ } ResolvedCmdName; /* *------------------------------------------------------------------------- * * TclInitObjectSubsystem -- * * This function is invoked to perform once-only initialization of the * type table. It also registers the object types defined in this file. * * Results: * None. * * Side effects: * Initializes the table of defined object types "typeTable" with builtin * object types defined in this file. * *------------------------------------------------------------------------- */ void TclInitObjSubsystem(void) { Tcl_MutexLock(&tableMutex); typeTableInitialized = 1; Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS); Tcl_MutexUnlock(&tableMutex); Tcl_RegisterObjType(&tclByteArrayType); Tcl_RegisterObjType(&tclDoubleType); Tcl_RegisterObjType(&tclEndOffsetType); Tcl_RegisterObjType(&tclIntType); Tcl_RegisterObjType(&tclStringType); Tcl_RegisterObjType(&tclListType); Tcl_RegisterObjType(&tclDictType); Tcl_RegisterObjType(&tclByteCodeType); Tcl_RegisterObjType(&tclArraySearchType); Tcl_RegisterObjType(&tclCmdNameType); Tcl_RegisterObjType(&tclRegexpType); Tcl_RegisterObjType(&tclProcBodyType); /* For backward compatibility only ... */ Tcl_RegisterObjType(&oldBooleanType); #ifndef TCL_WIDE_INT_IS_LONG Tcl_RegisterObjType(&tclWideIntType); #endif #ifdef TCL_COMPILE_STATS Tcl_MutexLock(&tclObjMutex); tclObjsAlloced = 0; tclObjsFreed = 0; { int i; for (i=0 ; iobjThreadMap; if (tablePtr != NULL) { for (hPtr = Tcl_FirstHashEntry(tablePtr, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { ObjData *objData = Tcl_GetHashValue(hPtr); if (objData != NULL) { ckfree(objData); } } Tcl_DeleteHashTable(tablePtr); ckfree(tablePtr); tsdPtr->objThreadMap = NULL; } #endif } /* *---------------------------------------------------------------------- * * TclFinalizeObjects -- * * This function is called by Tcl_Finalize to clean up all registered * Tcl_ObjType's and to reset the tclFreeObjList. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclFinalizeObjects(void) { Tcl_MutexLock(&tableMutex); if (typeTableInitialized) { Tcl_DeleteHashTable(&typeTable); typeTableInitialized = 0; } Tcl_MutexUnlock(&tableMutex); /* * All we do here is reset the head pointer of the linked list of free * Tcl_Obj's to NULL; the memory finalization will take care of releasing * memory for us. */ Tcl_MutexLock(&tclObjMutex); tclFreeObjList = NULL; Tcl_MutexUnlock(&tclObjMutex); } /* *---------------------------------------------------------------------- * * TclGetContLineTable -- * * This procedure is a helper which returns the thread-specific * hash-table used to track continuation line information associated with * Tcl_Obj*, and the objThreadMap, etc. * * Results: * A reference to the thread-data. * * Side effects: * May allocate memory for the thread-data. * * TIP #280 *---------------------------------------------------------------------- */ static ThreadSpecificData * TclGetContLineTable(void) { /* * Initialize the hashtable tracking invisible continuation lines. For * the release we use a thread exit handler to ensure that this is done * before TSD blocks are made invalid. The TclFinalizeObjects() which * would be the natural place for this is invoked afterwards, meaning that * we try to operate on a data structure already gone. */ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!tsdPtr->lineCLPtr) { tsdPtr->lineCLPtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(tsdPtr->lineCLPtr, TCL_ONE_WORD_KEYS); Tcl_CreateThreadExitHandler(TclThreadFinalizeContLines,NULL); } return tsdPtr; } /* *---------------------------------------------------------------------- * * TclContinuationsEnter -- * * This procedure is a helper which saves the continuation line * information associated with a Tcl_Obj*. * * Results: * A reference to the newly created continuation line location table. * * Side effects: * Allocates memory for the table of continuation line locations. * * TIP #280 *---------------------------------------------------------------------- */ ContLineLoc * TclContinuationsEnter( Tcl_Obj *objPtr, int num, int *loc) { int newEntry; ThreadSpecificData *tsdPtr = TclGetContLineTable(); Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(tsdPtr->lineCLPtr, objPtr, &newEntry); ContLineLoc *clLocPtr = ckalloc(sizeof(ContLineLoc) + num*sizeof(int)); if (!newEntry) { /* * We're entering ContLineLoc data for the same value more than one * time. Taking care not to leak the old entry. * * This can happen when literals in a proc body are shared. See for * example test info-30.19 where the action (code) for all branches of * the switch command is identical, mapping them all to the same * literal. An interesting result of this is that the number and * locations (offset) of invisible continuation lines in the literal * are the same for all occurences. * * Note that while reusing the existing entry is possible it requires * the same actions as for a new entry because we have to copy the * incoming num/loc data even so. Because we are called from * TclContinuationsEnterDerived for this case, which modified the * stored locations (Rebased to the proper relative offset). Just * returning the stored entry would rebase them a second time, or * more, hosing the data. It is easier to simply replace, as we are * doing. */ ckfree(Tcl_GetHashValue(hPtr)); } clLocPtr->num = num; memcpy(&clLocPtr->loc, loc, num*sizeof(int)); clLocPtr->loc[num] = CLL_END; /* Sentinel */ Tcl_SetHashValue(hPtr, clLocPtr); return clLocPtr; } /* *---------------------------------------------------------------------- * * TclContinuationsEnterDerived -- * * This procedure is a helper which computes the continuation line * information associated with a Tcl_Obj* cut from the middle of a * script. * * Results: * None. * * Side effects: * Allocates memory for the table of continuation line locations. * * TIP #280 *---------------------------------------------------------------------- */ void TclContinuationsEnterDerived( Tcl_Obj *objPtr, int start, int *clNext) { int length, end, num; int *wordCLLast = clNext; /* * We have to handle invisible continuations lines here as well, despite * the code we have in TclSubstTokens (TST) for that. Why ? Nesting. If * our script is the sole argument to an 'eval' command, for example, the * scriptCLLocPtr we are using was generated by a previous call to TST, * and while the words we have here may contain continuation lines they * are invisible already, and the inner call to TST had no bs+nl sequences * to trigger its code. * * Luckily for us, the table we have to create here for the current word * has to be a slice of the table currently in use, with the locations * suitably modified to be relative to the start of the word instead of * relative to the script. * * That is what we are doing now. Determine the slice we need, and if not * empty, wrap it into a new table, and save the result into our * thread-global hashtable, as usual. */ /* * First compute the range of the word within the script. (Is there a * better way which doesn't shimmer?) */ Tcl_GetStringFromObj(objPtr, &length); end = start + length; /* First char after the word */ /* * Then compute the table slice covering the range of the word. */ while (*wordCLLast >= 0 && *wordCLLast < end) { wordCLLast++; } /* * And generate the table from the slice, if it was not empty. */ num = wordCLLast - clNext; if (num) { int i; ContLineLoc *clLocPtr = TclContinuationsEnter(objPtr, num, clNext); /* * Re-base the locations. */ for (i=0 ; iloc[i] -= start; /* * Continuation lines coming before the string and affecting us * should not happen, due to the proper maintenance of clNext * during compilation. */ if (clLocPtr->loc[i] < 0) { Tcl_Panic("Derived ICL data for object using offsets from before the script"); } } } } /* *---------------------------------------------------------------------- * * TclContinuationsCopy -- * * This procedure is a helper which copies the continuation line * information associated with a Tcl_Obj* to another Tcl_Obj*. It is * assumed that both contain the same string/script. Use this when a * script is duplicated because it was shared. * * Results: * None. * * Side effects: * Allocates memory for the table of continuation line locations. * * TIP #280 *---------------------------------------------------------------------- */ void TclContinuationsCopy( Tcl_Obj *objPtr, Tcl_Obj *originObjPtr) { ThreadSpecificData *tsdPtr = TclGetContLineTable(); Tcl_HashEntry *hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, originObjPtr); if (hPtr) { ContLineLoc *clLocPtr = Tcl_GetHashValue(hPtr); TclContinuationsEnter(objPtr, clLocPtr->num, clLocPtr->loc); } } /* *---------------------------------------------------------------------- * * TclContinuationsGet -- * * This procedure is a helper which retrieves the continuation line * information associated with a Tcl_Obj*, if it has any. * * Results: * A reference to the continuation line location table, or NULL if the * Tcl_Obj* has no such information associated with it. * * Side effects: * None. * * TIP #280 *---------------------------------------------------------------------- */ ContLineLoc * TclContinuationsGet( Tcl_Obj *objPtr) { ThreadSpecificData *tsdPtr = TclGetContLineTable(); Tcl_HashEntry *hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr); if (!hPtr) { return NULL; } return Tcl_GetHashValue(hPtr); } /* *---------------------------------------------------------------------- * * TclThreadFinalizeContLines -- * * This procedure is a helper which releases all continuation line * information currently known. It is run as a thread exit handler. * * Results: * None. * * Side effects: * Releases memory. * * TIP #280 *---------------------------------------------------------------------- */ static void TclThreadFinalizeContLines( ClientData clientData) { /* * Release the hashtable tracking invisible continuation lines. */ ThreadSpecificData *tsdPtr = TclGetContLineTable(); Tcl_HashEntry *hPtr; Tcl_HashSearch hSearch; for (hPtr = Tcl_FirstHashEntry(tsdPtr->lineCLPtr, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { ckfree(Tcl_GetHashValue(hPtr)); Tcl_DeleteHashEntry(hPtr); } Tcl_DeleteHashTable(tsdPtr->lineCLPtr); ckfree(tsdPtr->lineCLPtr); tsdPtr->lineCLPtr = NULL; } /* *-------------------------------------------------------------- * * Tcl_RegisterObjType -- * * This function is called to register a new Tcl object type in the table * of all object types supported by Tcl. * * Results: * None. * * Side effects: * The type is registered in the Tcl type table. If there was already a * type with the same name as in typePtr, it is replaced with the new * type. * *-------------------------------------------------------------- */ void Tcl_RegisterObjType( const Tcl_ObjType *typePtr) /* Information about object type; storage must * be statically allocated (must live * forever). */ { int isNew; Tcl_MutexLock(&tableMutex); Tcl_SetHashValue( Tcl_CreateHashEntry(&typeTable, typePtr->name, &isNew), typePtr); Tcl_MutexUnlock(&tableMutex); } /* *---------------------------------------------------------------------- * * Tcl_AppendAllObjTypes -- * * This function appends onto the argument object the name of each object * type as a list element. This includes the builtin object types (e.g. * int, list) as well as those added using Tcl_NewObj. These names can be * used, for example, with Tcl_GetObjType to get pointers to the * corresponding Tcl_ObjType structures. * * Results: * The return value is normally TCL_OK; in this case the object * referenced by objPtr has each type name appended to it. If an error * occurs, TCL_ERROR is returned and the interpreter's result holds an * error message. * * Side effects: * If necessary, the object referenced by objPtr is converted into a list * object. * *---------------------------------------------------------------------- */ int Tcl_AppendAllObjTypes( Tcl_Interp *interp, /* Interpreter used for error reporting. */ Tcl_Obj *objPtr) /* Points to the Tcl object onto which the * name of each registered type is appended as * a list element. */ { register Tcl_HashEntry *hPtr; Tcl_HashSearch search; int numElems; /* * Get the test for a valid list out of the way first. */ if (TclListObjLength(interp, objPtr, &numElems) != TCL_OK) { return TCL_ERROR; } /* * Type names are NUL-terminated, not counted strings. This code relies on * that. */ Tcl_MutexLock(&tableMutex); for (hPtr = Tcl_FirstHashEntry(&typeTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj(Tcl_GetHashKey(&typeTable, hPtr), -1)); } Tcl_MutexUnlock(&tableMutex); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetObjType -- * * This function looks up an object type by name. * * Results: * If an object type with name matching "typeName" is found, a pointer to * its Tcl_ObjType structure is returned; otherwise, NULL is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ const Tcl_ObjType * Tcl_GetObjType( const char *typeName) /* Name of Tcl object type to look up. */ { register Tcl_HashEntry *hPtr; const Tcl_ObjType *typePtr = NULL; Tcl_MutexLock(&tableMutex); hPtr = Tcl_FindHashEntry(&typeTable, typeName); if (hPtr != NULL) { typePtr = Tcl_GetHashValue(hPtr); } Tcl_MutexUnlock(&tableMutex); return typePtr; } /* *---------------------------------------------------------------------- * * Tcl_ConvertToType -- * * Convert the Tcl object "objPtr" to have type "typePtr" if possible. * * Results: * The return value is TCL_OK on success and TCL_ERROR on failure. If * TCL_ERROR is returned, then the interpreter's result contains an error * message unless "interp" is NULL. Passing a NULL "interp" allows this * function to be used as a test whether the conversion could be done * (and in fact was done). * * Side effects: * Any internal representation for the old type is freed. * *---------------------------------------------------------------------- */ int Tcl_ConvertToType( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr, /* The object to convert. */ const Tcl_ObjType *typePtr) /* The target type. */ { if (objPtr->typePtr == typePtr) { return TCL_OK; } /* * Use the target type's Tcl_SetFromAnyProc to set "objPtr"s internal form * as appropriate for the target type. This frees the old internal * representation. */ if (typePtr->setFromAnyProc == NULL) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't convert value to type %s", typePtr->name)); Tcl_SetErrorCode(interp, "TCL", "API_ABUSE", NULL); } return TCL_ERROR; } return typePtr->setFromAnyProc(interp, objPtr); } /* *-------------------------------------------------------------- * * TclDbDumpActiveObjects -- * * This function is called to dump all of the active Tcl_Obj structs this * allocator knows about. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ void TclDbDumpActiveObjects( FILE *outFile) { #if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS) Tcl_HashSearch hSearch; Tcl_HashEntry *hPtr; Tcl_HashTable *tablePtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); tablePtr = tsdPtr->objThreadMap; if (tablePtr != NULL) { fprintf(outFile, "total objects: %d\n", tablePtr->numEntries); for (hPtr = Tcl_FirstHashEntry(tablePtr, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { ObjData *objData = Tcl_GetHashValue(hPtr); if (objData != NULL) { fprintf(outFile, "key = 0x%p, objPtr = 0x%p, file = %s, line = %d\n", Tcl_GetHashKey(tablePtr, hPtr), objData->objPtr, objData->file, objData->line); } else { fprintf(outFile, "key = 0x%p\n", Tcl_GetHashKey(tablePtr, hPtr)); } } } #endif } /* *---------------------------------------------------------------------- * * TclDbInitNewObj -- * * Called via the TclNewObj or TclDbNewObj macros when TCL_MEM_DEBUG is * enabled. This function will initialize the members of a Tcl_Obj * struct. Initilization would be done inline via the TclNewObj macro * when compiling without TCL_MEM_DEBUG. * * Results: * The Tcl_Obj struct members are initialized. * * Side effects: * None. *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG void TclDbInitNewObj( register Tcl_Obj *objPtr, register const char *file, /* The name of the source file calling this * function; used for debugging. */ register int line) /* Line number in the source file; used for * debugging. */ { objPtr->refCount = 0; objPtr->bytes = tclEmptyStringRep; objPtr->length = 0; objPtr->typePtr = NULL; #ifdef TCL_THREADS /* * Add entry to a thread local map used to check if a Tcl_Obj was * allocated by the currently executing thread. */ if (!TclInExit()) { Tcl_HashEntry *hPtr; Tcl_HashTable *tablePtr; int isNew; ObjData *objData; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->objThreadMap == NULL) { tsdPtr->objThreadMap = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(tsdPtr->objThreadMap, TCL_ONE_WORD_KEYS); } tablePtr = tsdPtr->objThreadMap; hPtr = Tcl_CreateHashEntry(tablePtr, objPtr, &isNew); if (!isNew) { Tcl_Panic("expected to create new entry for object map"); } /* * Record the debugging information. */ objData = ckalloc(sizeof(ObjData)); objData->objPtr = objPtr; objData->file = file; objData->line = line; Tcl_SetHashValue(hPtr, objData); } #endif /* TCL_THREADS */ } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_NewObj -- * * This function is normally called when not debugging: i.e., when * TCL_MEM_DEBUG is not defined. It creates new Tcl objects that denote * the empty string. These objects have a NULL object type and NULL * string representation byte pointer. Type managers call this routine to * allocate new objects that they further initialize. * * When TCL_MEM_DEBUG is defined, this function just returns the result * of calling the debugging version Tcl_DbNewObj. * * Results: * The result is a newly allocated object that represents the empty * string. The new object's typePtr is set NULL and its ref count is set * to 0. * * Side effects: * If compiling with TCL_COMPILE_STATS, this function increments the * global count of allocated objects (tclObjsAlloced). * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG #undef Tcl_NewObj Tcl_Obj * Tcl_NewObj(void) { return Tcl_DbNewObj("unknown", 0); } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_NewObj(void) { register Tcl_Obj *objPtr; /* * Use the macro defined in tclInt.h - it will use the correct allocator. */ TclNewObj(objPtr); return objPtr; } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_DbNewObj -- * * This function is normally called when debugging: i.e., when * TCL_MEM_DEBUG is defined. It creates new Tcl objects that denote the * empty string. It is the same as the Tcl_NewObj function above except * that it calls Tcl_DbCkalloc directly with the file name and line * number from its caller. This simplifies debugging since then the * [memory active] command will report the correct file name and line * number when reporting objects that haven't been freed. * * When TCL_MEM_DEBUG is not defined, this function just returns the * result of calling Tcl_NewObj. * * Results: * The result is a newly allocated that represents the empty string. The * new object's typePtr is set NULL and its ref count is set to 0. * * Side effects: * If compiling with TCL_COMPILE_STATS, this function increments the * global count of allocated objects (tclObjsAlloced). * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_DbNewObj( register const char *file, /* The name of the source file calling this * function; used for debugging. */ register int line) /* Line number in the source file; used for * debugging. */ { register Tcl_Obj *objPtr; /* * Use the macro defined in tclInt.h - it will use the correct allocator. */ TclDbNewObj(objPtr, file, line); return objPtr; } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_DbNewObj( const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { return Tcl_NewObj(); } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * TclAllocateFreeObjects -- * * Function to allocate a number of free Tcl_Objs. This is done using a * single ckalloc to reduce the overhead for Tcl_Obj allocation. * * Assumes mutex is held. * * Results: * None. * * Side effects: * tclFreeObjList, the head of the list of free Tcl_Objs, is set to the * first of a number of free Tcl_Obj's linked together by their * internalRep.twoPtrValue.ptr1's. * *---------------------------------------------------------------------- */ #define OBJS_TO_ALLOC_EACH_TIME 100 void TclAllocateFreeObjects(void) { size_t bytesToAlloc = (OBJS_TO_ALLOC_EACH_TIME * sizeof(Tcl_Obj)); char *basePtr; register Tcl_Obj *prevPtr, *objPtr; register int i; /* * This has been noted by Purify to be a potential leak. The problem is * that Tcl, when not TCL_MEM_DEBUG compiled, keeps around all allocated * Tcl_Obj's, pointed to by tclFreeObjList, when freed instead of actually * freeing the memory. TclFinalizeObjects() does not ckfree() this memory, * but leaves it to Tcl's memory subsystem finalization to release it. * Purify apparently can't figure that out, and fires a false alarm. */ basePtr = ckalloc(bytesToAlloc); prevPtr = NULL; objPtr = (Tcl_Obj *) basePtr; for (i = 0; i < OBJS_TO_ALLOC_EACH_TIME; i++) { objPtr->internalRep.twoPtrValue.ptr1 = prevPtr; prevPtr = objPtr; objPtr++; } tclFreeObjList = prevPtr; } #undef OBJS_TO_ALLOC_EACH_TIME /* *---------------------------------------------------------------------- * * TclFreeObj -- * * This function frees the memory associated with the argument object. * It is called by the tcl.h macro Tcl_DecrRefCount when an object's ref * count is zero. It is only "public" since it must be callable by that * macro wherever the macro is used. It should not be directly called by * clients. * * Results: * None. * * Side effects: * Deallocates the storage for the object's Tcl_Obj structure after * deallocating the string representation and calling the type-specific * Tcl_FreeInternalRepProc to deallocate the object's internal * representation. If compiling with TCL_COMPILE_STATS, this function * increments the global count of freed objects (tclObjsFreed). * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG void TclFreeObj( register Tcl_Obj *objPtr) /* The object to be freed. */ { register const Tcl_ObjType *typePtr = objPtr->typePtr; /* * This macro declares a variable, so must come here... */ ObjInitDeletionContext(context); # ifdef TCL_THREADS /* * Check to make sure that the Tcl_Obj was allocated by the current * thread. Don't do this check when shutting down since thread local * storage can be finalized before the last Tcl_Obj is freed. */ if (!TclInExit()) { Tcl_HashTable *tablePtr; Tcl_HashEntry *hPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); tablePtr = tsdPtr->objThreadMap; if (!tablePtr) { Tcl_Panic("TclFreeObj: object table not initialized"); } hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr); if (hPtr) { /* * As the Tcl_Obj is going to be deleted we remove the entry. */ ObjData *objData = Tcl_GetHashValue(hPtr); if (objData != NULL) { ckfree(objData); } Tcl_DeleteHashEntry(hPtr); } } # endif /* * Check for a double free of the same value. This is slightly tricky * because it is customary to free a Tcl_Obj when its refcount falls * either from 1 to 0, or from 0 to -1. Falling from -1 to -2, though, * and so on, is always a sign of a botch in the caller. */ if (objPtr->refCount < -1) { Tcl_Panic("Reference count for %p was negative", objPtr); } /* * Now, in case we just approved drop from 1 to 0 as acceptable, make * sure we do not accept a second free when falling from 0 to -1. * Skip that possibility so any double free will trigger the panic. */ objPtr->refCount = -1; /* * Invalidate the string rep first so we can use the bytes value for our * pointer chain, and signal an obj deletion (as opposed to shimmering) * with 'length == -1'. */ TclInvalidateStringRep(objPtr); objPtr->length = -1; if (ObjDeletePending(context)) { PushObjToDelete(context, objPtr); } else { TCL_DTRACE_OBJ_FREE(objPtr); if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { ObjDeletionLock(context); typePtr->freeIntRepProc(objPtr); ObjDeletionUnlock(context); } Tcl_MutexLock(&tclObjMutex); ckfree(objPtr); Tcl_MutexUnlock(&tclObjMutex); TclIncrObjsFreed(); ObjDeletionLock(context); while (ObjOnStack(context)) { Tcl_Obj *objToFree; PopObjToDelete(context, objToFree); TCL_DTRACE_OBJ_FREE(objToFree); TclFreeIntRep(objToFree); Tcl_MutexLock(&tclObjMutex); ckfree(objToFree); Tcl_MutexUnlock(&tclObjMutex); TclIncrObjsFreed(); } ObjDeletionUnlock(context); } /* * We cannot use TclGetContinuationTable() here, because that may * re-initialize the thread-data for calls coming after the finalization. * We have to access it using the low-level call and then check for * validity. This function can be called after TclFinalizeThreadData() has * already killed the thread-global data structures. Performing * TCL_TSD_INIT will leave us with an un-initialized memory block upon * which we crash (if we where to access the uninitialized hashtable). */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Tcl_HashEntry *hPtr; if (tsdPtr->lineCLPtr) { hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr); if (hPtr) { ckfree(Tcl_GetHashValue(hPtr)); Tcl_DeleteHashEntry(hPtr); } } } } #else /* TCL_MEM_DEBUG */ void TclFreeObj( register Tcl_Obj *objPtr) /* The object to be freed. */ { /* * Invalidate the string rep first so we can use the bytes value for our * pointer chain, and signal an obj deletion (as opposed to shimmering) * with 'length == -1'. */ TclInvalidateStringRep(objPtr); objPtr->length = -1; if (!objPtr->typePtr || !objPtr->typePtr->freeIntRepProc) { /* * objPtr can be freed safely, as it will not attempt to free any * other objects: it will not cause recursive calls to this function. */ TCL_DTRACE_OBJ_FREE(objPtr); TclFreeObjStorage(objPtr); TclIncrObjsFreed(); } else { /* * This macro declares a variable, so must come here... */ ObjInitDeletionContext(context); if (ObjDeletePending(context)) { PushObjToDelete(context, objPtr); } else { /* * Note that the contents of the while loop assume that the string * rep has already been freed and we don't want to do anything * fancy with adding to the queue inside ourselves. Must take care * to unstack the object first since freeing the internal rep can * add further objects to the stack. The code assumes that it is * the first thing in a block; all current usages in the core * satisfy this. */ TCL_DTRACE_OBJ_FREE(objPtr); ObjDeletionLock(context); objPtr->typePtr->freeIntRepProc(objPtr); ObjDeletionUnlock(context); TclFreeObjStorage(objPtr); TclIncrObjsFreed(); ObjDeletionLock(context); while (ObjOnStack(context)) { Tcl_Obj *objToFree; PopObjToDelete(context, objToFree); TCL_DTRACE_OBJ_FREE(objToFree); if ((objToFree->typePtr != NULL) && (objToFree->typePtr->freeIntRepProc != NULL)) { objToFree->typePtr->freeIntRepProc(objToFree); } TclFreeObjStorage(objToFree); TclIncrObjsFreed(); } ObjDeletionUnlock(context); } } /* * We cannot use TclGetContinuationTable() here, because that may * re-initialize the thread-data for calls coming after the finalization. * We have to access it using the low-level call and then check for * validity. This function can be called after TclFinalizeThreadData() has * already killed the thread-global data structures. Performing * TCL_TSD_INIT will leave us with an un-initialized memory block upon * which we crash (if we where to access the uninitialized hashtable). */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Tcl_HashEntry *hPtr; if (tsdPtr->lineCLPtr) { hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr); if (hPtr) { ckfree(Tcl_GetHashValue(hPtr)); Tcl_DeleteHashEntry(hPtr); } } } } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * TclObjBeingDeleted -- * * This function returns 1 when the Tcl_Obj is being deleted. It is * provided for the rare cases where the reason for the loss of an * internal rep might be relevant. [FR 1512138] * * Results: * 1 if being deleted, 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclObjBeingDeleted( Tcl_Obj *objPtr) { return (objPtr->length == -1); } /* *---------------------------------------------------------------------- * * Tcl_DuplicateObj -- * * Create and return a new object that is a duplicate of the argument * object. * * Results: * The return value is a pointer to a newly created Tcl_Obj. This object * has reference count 0 and the same type, if any, as the source object * objPtr. Also: * 1) If the source object has a valid string rep, we copy it; * otherwise, the duplicate's string rep is set NULL to mark it * invalid. * 2) If the source object has an internal representation (i.e. its * typePtr is non-NULL), the new object's internal rep is set to a * copy; otherwise the new internal rep is marked invalid. * * Side effects: * What constitutes "copying" the internal representation depends on the * type. For example, if the argument object is a list, the element * objects it points to will not actually be copied but will be shared * with the duplicate list. That is, the ref counts of the element * objects will be incremented. * *---------------------------------------------------------------------- */ #define SetDuplicateObj(dupPtr, objPtr) \ { \ const Tcl_ObjType *typePtr = (objPtr)->typePtr; \ const char *bytes = (objPtr)->bytes; \ if (bytes) { \ TclInitStringRep((dupPtr), bytes, (objPtr)->length); \ } else { \ (dupPtr)->bytes = NULL; \ } \ if (typePtr) { \ if (typePtr->dupIntRepProc) { \ typePtr->dupIntRepProc((objPtr), (dupPtr)); \ } else { \ (dupPtr)->internalRep = (objPtr)->internalRep; \ (dupPtr)->typePtr = typePtr; \ } \ } \ } Tcl_Obj * Tcl_DuplicateObj( Tcl_Obj *objPtr) /* The object to duplicate. */ { Tcl_Obj *dupPtr; TclNewObj(dupPtr); SetDuplicateObj(dupPtr, objPtr); return dupPtr; } void TclSetDuplicateObj( Tcl_Obj *dupPtr, Tcl_Obj *objPtr) { if (Tcl_IsShared(dupPtr)) { Tcl_Panic("%s called with shared object", "TclSetDuplicateObj"); } TclInvalidateStringRep(dupPtr); TclFreeIntRep(dupPtr); SetDuplicateObj(dupPtr, objPtr); } /* *---------------------------------------------------------------------- * * Tcl_GetString -- * * Returns the string representation byte array pointer for an object. * * Results: * Returns a pointer to the string representation of objPtr. The byte * array referenced by the returned pointer must not be modified by the * caller. Furthermore, the caller must copy the bytes if they need to * retain them since the object's string rep can change as a result of * other operations. * * Side effects: * May call the object's updateStringProc to update the string * representation from the internal representation. * *---------------------------------------------------------------------- */ char * Tcl_GetString( register Tcl_Obj *objPtr) /* Object whose string rep byte pointer should * be returned. */ { if (objPtr->bytes != NULL) { return objPtr->bytes; } /* * Note we do not check for objPtr->typePtr == NULL. An invariant of * a properly maintained Tcl_Obj is that at least one of objPtr->bytes * and objPtr->typePtr must not be NULL. If broken extensions fail to * maintain that invariant, we can crash here. */ if (objPtr->typePtr->updateStringProc == NULL) { /* * Those Tcl_ObjTypes which choose not to define an updateStringProc * must be written in such a way that (objPtr->bytes) never becomes * NULL. This panic was added in Tcl 8.1. */ Tcl_Panic("UpdateStringProc should not be invoked for type %s", objPtr->typePtr->name); } objPtr->typePtr->updateStringProc(objPtr); if (objPtr->bytes == NULL || objPtr->length < 0 || objPtr->bytes[objPtr->length] != '\0') { Tcl_Panic("UpdateStringProc for type '%s' " "failed to create a valid string rep", objPtr->typePtr->name); } return objPtr->bytes; } /* *---------------------------------------------------------------------- * * Tcl_GetStringFromObj -- * * Returns the string representation's byte array pointer and length for * an object. * * Results: * Returns a pointer to the string representation of objPtr. If lengthPtr * isn't NULL, the length of the string representation is stored at * *lengthPtr. The byte array referenced by the returned pointer must not * be modified by the caller. Furthermore, the caller must copy the bytes * if they need to retain them since the object's string rep can change * as a result of other operations. * * Side effects: * May call the object's updateStringProc to update the string * representation from the internal representation. * *---------------------------------------------------------------------- */ char * Tcl_GetStringFromObj( register Tcl_Obj *objPtr, /* Object whose string rep byte pointer should * be returned. */ register int *lengthPtr) /* If non-NULL, the location where the string * rep's byte array length should * be stored. * If NULL, no length is stored. */ { (void) TclGetString(objPtr); if (lengthPtr != NULL) { *lengthPtr = objPtr->length; } return objPtr->bytes; } /* *---------------------------------------------------------------------- * * Tcl_InvalidateStringRep -- * * This function is called to invalidate an object's string * representation. * * Results: * None. * * Side effects: * Deallocates the storage for any old string representation, then sets * the string representation NULL to mark it invalid. * *---------------------------------------------------------------------- */ void Tcl_InvalidateStringRep( register Tcl_Obj *objPtr) /* Object whose string rep byte pointer should * be freed. */ { TclInvalidateStringRep(objPtr); } /* *---------------------------------------------------------------------- * * Tcl_NewBooleanObj -- * * This function is normally called when not debugging: i.e., when * TCL_MEM_DEBUG is not defined. It creates a new Tcl_Obj and * initializes it from the argument boolean value. A nonzero "boolValue" * is coerced to 1. * * When TCL_MEM_DEBUG is defined, this function just returns the result * of calling the debugging version Tcl_DbNewBooleanObj. * * Results: * The newly created object is returned. This object will have an invalid * string representation. The returned object has ref count 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ #undef Tcl_NewBooleanObj #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_NewBooleanObj( register int boolValue) /* Boolean used to initialize new object. */ { return Tcl_DbNewBooleanObj(boolValue, "unknown", 0); } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_NewBooleanObj( register int boolValue) /* Boolean used to initialize new object. */ { register Tcl_Obj *objPtr; TclNewBooleanObj(objPtr, boolValue); return objPtr; } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_DbNewBooleanObj -- * * This function is normally called when debugging: i.e., when * TCL_MEM_DEBUG is defined. It creates new boolean objects. It is the * same as the Tcl_NewBooleanObj function above except that it calls * Tcl_DbCkalloc directly with the file name and line number from its * caller. This simplifies debugging since then the [memory active] * command will report the correct file name and line number when * reporting objects that haven't been freed. * * When TCL_MEM_DEBUG is not defined, this function just returns the * result of calling Tcl_NewBooleanObj. * * Results: * The newly created object is returned. This object will have an invalid * string representation. The returned object has ref count 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ #undef Tcl_DbNewBooleanObj #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_DbNewBooleanObj( register int boolValue, /* Boolean used to initialize new object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { register Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); objPtr->bytes = NULL; objPtr->internalRep.longValue = (boolValue? 1 : 0); objPtr->typePtr = &tclIntType; return objPtr; } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_DbNewBooleanObj( register int boolValue, /* Boolean used to initialize new object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { return Tcl_NewBooleanObj(boolValue); } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_SetBooleanObj -- * * Modify an object to be a boolean object and to have the specified * boolean value. A nonzero "boolValue" is coerced to 1. * * Results: * None. * * Side effects: * The object's old string rep, if any, is freed. Also, any old internal * rep is freed. * *---------------------------------------------------------------------- */ #undef Tcl_SetBooleanObj void Tcl_SetBooleanObj( register Tcl_Obj *objPtr, /* Object whose internal rep to init. */ register int boolValue) /* Boolean used to set object's value. */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetBooleanObj"); } TclSetBooleanObj(objPtr, boolValue); } /* *---------------------------------------------------------------------- * * Tcl_GetBooleanFromObj -- * * Attempt to return a boolean from the Tcl object "objPtr". This * includes conversion from any of Tcl's numeric types. * * Results: * The return value is a standard Tcl object result. If an error occurs * during conversion, an error message is left in the interpreter's * result unless "interp" is NULL. * * Side effects: * The intrep of *objPtr may be changed. * *---------------------------------------------------------------------- */ int Tcl_GetBooleanFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr, /* The object from which to get boolean. */ register int *boolPtr) /* Place to store resulting boolean. */ { do { if (objPtr->typePtr == &tclIntType) { *boolPtr = (objPtr->internalRep.longValue != 0); return TCL_OK; } if (objPtr->typePtr == &tclBooleanType) { *boolPtr = (int) objPtr->internalRep.longValue; return TCL_OK; } if (objPtr->typePtr == &tclDoubleType) { /* * Caution: Don't be tempted to check directly for the "double" * Tcl_ObjType and then compare the intrep to 0.0. This isn't * reliable because a "double" Tcl_ObjType can hold the NaN value. * Use the API Tcl_GetDoubleFromObj, which does the checking and * sets the proper error message for us. */ double d; if (Tcl_GetDoubleFromObj(interp, objPtr, &d) != TCL_OK) { return TCL_ERROR; } *boolPtr = (d != 0.0); return TCL_OK; } if (objPtr->typePtr == &tclBignumType) { *boolPtr = 1; return TCL_OK; } #ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { *boolPtr = (objPtr->internalRep.wideValue != 0); return TCL_OK; } #endif } while ((ParseBoolean(objPtr) == TCL_OK) || (TCL_OK == TclParseNumber(interp, objPtr, "boolean value", NULL,-1,NULL,0))); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclSetBooleanFromAny -- * * Attempt to generate a boolean internal form for the Tcl object * "objPtr". * * Results: * The return value is a standard Tcl result. If an error occurs during * conversion, an error message is left in the interpreter's result * unless "interp" is NULL. * * Side effects: * If no error occurs, an integer 1 or 0 is stored as "objPtr"s internal * representation and the type of "objPtr" is set to boolean. * *---------------------------------------------------------------------- */ int TclSetBooleanFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr) /* The object to convert. */ { /* * For some "pure" numeric Tcl_ObjTypes (no string rep), we can determine * whether a boolean conversion is possible without generating the string * rep. */ if (objPtr->bytes == NULL) { if (objPtr->typePtr == &tclIntType) { switch (objPtr->internalRep.longValue) { case 0L: case 1L: return TCL_OK; } goto badBoolean; } if (objPtr->typePtr == &tclBignumType) { goto badBoolean; } #ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { goto badBoolean; } #endif if (objPtr->typePtr == &tclDoubleType) { goto badBoolean; } } if (ParseBoolean(objPtr) == TCL_OK) { return TCL_OK; } badBoolean: if (interp != NULL) { int length; const char *str = Tcl_GetStringFromObj(objPtr, &length); Tcl_Obj *msg; TclNewLiteralStringObj(msg, "expected boolean value but got \""); Tcl_AppendLimitedToObj(msg, str, length, 50, ""); Tcl_AppendToObj(msg, "\"", -1); Tcl_SetObjResult(interp, msg); Tcl_SetErrorCode(interp, "TCL", "VALUE", "BOOLEAN", NULL); } return TCL_ERROR; } static int ParseBoolean( register Tcl_Obj *objPtr) /* The object to parse/convert. */ { int i, length, newBool; char lowerCase[6]; const char *str = TclGetStringFromObj(objPtr, &length); if ((length == 0) || (length > 5)) { /* * Longest valid boolean string rep. is "false". */ return TCL_ERROR; } switch (str[0]) { case '0': if (length == 1) { newBool = 0; goto numericBoolean; } return TCL_ERROR; case '1': if (length == 1) { newBool = 1; goto numericBoolean; } return TCL_ERROR; } /* * Force to lower case for case-insensitive detection. Filter out known * invalid characters at the same time. */ for (i=0; i < length; i++) { char c = str[i]; switch (c) { case 'A': case 'E': case 'F': case 'L': case 'N': case 'O': case 'R': case 'S': case 'T': case 'U': case 'Y': lowerCase[i] = c + (char) ('a' - 'A'); break; case 'a': case 'e': case 'f': case 'l': case 'n': case 'o': case 'r': case 's': case 't': case 'u': case 'y': lowerCase[i] = c; break; default: return TCL_ERROR; } } lowerCase[length] = 0; switch (lowerCase[0]) { case 'y': /* * Checking the 'y' is redundant, but makes the code clearer. */ if (strncmp(lowerCase, "yes", (size_t) length) == 0) { newBool = 1; goto goodBoolean; } return TCL_ERROR; case 'n': if (strncmp(lowerCase, "no", (size_t) length) == 0) { newBool = 0; goto goodBoolean; } return TCL_ERROR; case 't': if (strncmp(lowerCase, "true", (size_t) length) == 0) { newBool = 1; goto goodBoolean; } return TCL_ERROR; case 'f': if (strncmp(lowerCase, "false", (size_t) length) == 0) { newBool = 0; goto goodBoolean; } return TCL_ERROR; case 'o': if (length < 2) { return TCL_ERROR; } if (strncmp(lowerCase, "on", (size_t) length) == 0) { newBool = 1; goto goodBoolean; } else if (strncmp(lowerCase, "off", (size_t) length) == 0) { newBool = 0; goto goodBoolean; } return TCL_ERROR; default: return TCL_ERROR; } /* * Free the old internalRep before setting the new one. We do this as late * as possible to allow the conversion code, in particular * Tcl_GetStringFromObj, to use that old internalRep. */ goodBoolean: TclFreeIntRep(objPtr); objPtr->internalRep.longValue = newBool; objPtr->typePtr = &tclBooleanType; return TCL_OK; numericBoolean: TclFreeIntRep(objPtr); objPtr->internalRep.longValue = newBool; objPtr->typePtr = &tclIntType; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_NewDoubleObj -- * * This function is normally called when not debugging: i.e., when * TCL_MEM_DEBUG is not defined. It creates a new double object and * initializes it from the argument double value. * * When TCL_MEM_DEBUG is defined, this function just returns the result * of calling the debugging version Tcl_DbNewDoubleObj. * * Results: * The newly created object is returned. This object will have an * invalid string representation. The returned object has ref count 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG #undef Tcl_NewDoubleObj Tcl_Obj * Tcl_NewDoubleObj( register double dblValue) /* Double used to initialize the object. */ { return Tcl_DbNewDoubleObj(dblValue, "unknown", 0); } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_NewDoubleObj( register double dblValue) /* Double used to initialize the object. */ { register Tcl_Obj *objPtr; TclNewDoubleObj(objPtr, dblValue); return objPtr; } #endif /* if TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_DbNewDoubleObj -- * * This function is normally called when debugging: i.e., when * TCL_MEM_DEBUG is defined. It creates new double objects. It is the * same as the Tcl_NewDoubleObj function above except that it calls * Tcl_DbCkalloc directly with the file name and line number from its * caller. This simplifies debugging since then the [memory active] * command will report the correct file name and line number when * reporting objects that haven't been freed. * * When TCL_MEM_DEBUG is not defined, this function just returns the * result of calling Tcl_NewDoubleObj. * * Results: * The newly created object is returned. This object will have an invalid * string representation. The returned object has ref count 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_DbNewDoubleObj( register double dblValue, /* Double used to initialize the object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { register Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); objPtr->bytes = NULL; objPtr->internalRep.doubleValue = dblValue; objPtr->typePtr = &tclDoubleType; return objPtr; } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_DbNewDoubleObj( register double dblValue, /* Double used to initialize the object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { return Tcl_NewDoubleObj(dblValue); } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_SetDoubleObj -- * * Modify an object to be a double object and to have the specified * double value. * * Results: * None. * * Side effects: * The object's old string rep, if any, is freed. Also, any old internal * rep is freed. * *---------------------------------------------------------------------- */ void Tcl_SetDoubleObj( register Tcl_Obj *objPtr, /* Object whose internal rep to init. */ register double dblValue) /* Double used to set the object's value. */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetDoubleObj"); } TclSetDoubleObj(objPtr, dblValue); } /* *---------------------------------------------------------------------- * * Tcl_GetDoubleFromObj -- * * Attempt to return a double from the Tcl object "objPtr". If the object * is not already a double, an attempt will be made to convert it to one. * * Results: * The return value is a standard Tcl object result. If an error occurs * during conversion, an error message is left in the interpreter's * result unless "interp" is NULL. * * Side effects: * If the object is not already a double, the conversion will free any * old internal representation. * *---------------------------------------------------------------------- */ int Tcl_GetDoubleFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr, /* The object from which to get a double. */ register double *dblPtr) /* Place to store resulting double. */ { do { if (objPtr->typePtr == &tclDoubleType) { if (TclIsNaN(objPtr->internalRep.doubleValue)) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "floating point value is Not a Number", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DOUBLE", "NAN", NULL); } return TCL_ERROR; } *dblPtr = (double) objPtr->internalRep.doubleValue; return TCL_OK; } if (objPtr->typePtr == &tclIntType) { *dblPtr = objPtr->internalRep.longValue; return TCL_OK; } if (objPtr->typePtr == &tclBignumType) { mp_int big; UNPACK_BIGNUM(objPtr, big); *dblPtr = TclBignumToDouble(&big); return TCL_OK; } #ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { *dblPtr = (double) objPtr->internalRep.wideValue; return TCL_OK; } #endif } while (SetDoubleFromAny(interp, objPtr) == TCL_OK); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * SetDoubleFromAny -- * * Attempt to generate an double-precision floating point internal form * for the Tcl object "objPtr". * * Results: * The return value is a standard Tcl object result. If an error occurs * during conversion, an error message is left in the interpreter's * result unless "interp" is NULL. * * Side effects: * If no error occurs, a double is stored as "objPtr"s internal * representation. * *---------------------------------------------------------------------- */ static int SetDoubleFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr) /* The object to convert. */ { return TclParseNumber(interp, objPtr, "floating-point number", NULL, -1, NULL, 0); } /* *---------------------------------------------------------------------- * * UpdateStringOfDouble -- * * Update the string representation for a double-precision floating point * object. This must obey the current tcl_precision value for * double-to-string conversions. Note: This function does not free an * existing old string rep so storage will be lost if this has not * already been done. * * Results: * None. * * Side effects: * The object's string is set to a valid string that results from the * double-to-string conversion. * *---------------------------------------------------------------------- */ static void UpdateStringOfDouble( register Tcl_Obj *objPtr) /* Double obj with string rep to update. */ { char buffer[TCL_DOUBLE_SPACE]; register int len; Tcl_PrintDouble(NULL, objPtr->internalRep.doubleValue, buffer); len = strlen(buffer); objPtr->bytes = ckalloc(len + 1); memcpy(objPtr->bytes, buffer, (unsigned) len + 1); objPtr->length = len; } /* *---------------------------------------------------------------------- * * Tcl_NewIntObj -- * * If a client is compiled with TCL_MEM_DEBUG defined, calls to * Tcl_NewIntObj to create a new integer object end up calling the * debugging function Tcl_DbNewLongObj instead. * * Otherwise, if the client is compiled without TCL_MEM_DEBUG defined, * calls to Tcl_NewIntObj result in a call to one of the two * Tcl_NewIntObj implementations below. We provide two implementations so * that the Tcl core can be compiled to do memory debugging of the core * even if a client does not request it for itself. * * Integer and long integer objects share the same "integer" type * implementation. We store all integers as longs and Tcl_GetIntFromObj * checks whether the current value of the long can be represented by an * int. * * Results: * The newly created object is returned. This object will have an invalid * string representation. The returned object has ref count 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ #undef Tcl_NewIntObj #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_NewIntObj( register int intValue) /* Int used to initialize the new object. */ { return Tcl_DbNewLongObj((long)intValue, "unknown", 0); } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_NewIntObj( register int intValue) /* Int used to initialize the new object. */ { register Tcl_Obj *objPtr; TclNewIntObj(objPtr, intValue); return objPtr; } #endif /* if TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_SetIntObj -- * * Modify an object to be an integer and to have the specified integer * value. * * Results: * None. * * Side effects: * The object's old string rep, if any, is freed. Also, any old internal * rep is freed. * *---------------------------------------------------------------------- */ #undef Tcl_SetIntObj void Tcl_SetIntObj( register Tcl_Obj *objPtr, /* Object whose internal rep to init. */ register int intValue) /* Integer used to set object's value. */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetIntObj"); } TclSetIntObj(objPtr, intValue); } /* *---------------------------------------------------------------------- * * Tcl_GetIntFromObj -- * * Attempt to return an int from the Tcl object "objPtr". If the object * is not already an int, an attempt will be made to convert it to one. * * Integer and long integer objects share the same "integer" type * implementation. We store all integers as longs and Tcl_GetIntFromObj * checks whether the current value of the long can be represented by an * int. * * Results: * The return value is a standard Tcl object result. If an error occurs * during conversion or if the long integer held by the object can not be * represented by an int, an error message is left in the interpreter's * result unless "interp" is NULL. * * Side effects: * If the object is not already an int, the conversion will free any old * internal representation. * *---------------------------------------------------------------------- */ int Tcl_GetIntFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr, /* The object from which to get a int. */ register int *intPtr) /* Place to store resulting int. */ { #if (LONG_MAX == INT_MAX) return TclGetLongFromObj(interp, objPtr, (long *) intPtr); #else long l; if (TclGetLongFromObj(interp, objPtr, &l) != TCL_OK) { return TCL_ERROR; } if ((ULONG_MAX > UINT_MAX) && ((l > UINT_MAX) || (l < -(long)UINT_MAX))) { if (interp != NULL) { const char *s = "integer value too large to represent as non-long integer"; Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1)); Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL); } return TCL_ERROR; } *intPtr = (int) l; return TCL_OK; #endif } /* *---------------------------------------------------------------------- * * SetIntFromAny -- * * Attempts to force the internal representation for a Tcl object to * tclIntType, specifically. * * Results: * The return value is a standard object Tcl result. If an error occurs * during conversion, an error message is left in the interpreter's * result unless "interp" is NULL. * *---------------------------------------------------------------------- */ static int SetIntFromAny( Tcl_Interp *interp, /* Tcl interpreter */ Tcl_Obj *objPtr) /* Pointer to the object to convert */ { long l; return TclGetLongFromObj(interp, objPtr, &l); } /* *---------------------------------------------------------------------- * * UpdateStringOfInt -- * * Update the string representation for an integer object. Note: This * function does not free an existing old string rep so storage will be * lost if this has not already been done. * * Results: * None. * * Side effects: * The object's string is set to a valid string that results from the * int-to-string conversion. * *---------------------------------------------------------------------- */ static void UpdateStringOfInt( register Tcl_Obj *objPtr) /* Int object whose string rep to update. */ { char buffer[TCL_INTEGER_SPACE]; register int len; len = TclFormatInt(buffer, objPtr->internalRep.longValue); objPtr->bytes = ckalloc(len + 1); memcpy(objPtr->bytes, buffer, (unsigned) len + 1); objPtr->length = len; } /* *---------------------------------------------------------------------- * * Tcl_NewLongObj -- * * If a client is compiled with TCL_MEM_DEBUG defined, calls to * Tcl_NewLongObj to create a new long integer object end up calling the * debugging function Tcl_DbNewLongObj instead. * * Otherwise, if the client is compiled without TCL_MEM_DEBUG defined, * calls to Tcl_NewLongObj result in a call to one of the two * Tcl_NewLongObj implementations below. We provide two implementations * so that the Tcl core can be compiled to do memory debugging of the * core even if a client does not request it for itself. * * Integer and long integer objects share the same "integer" type * implementation. We store all integers as longs and Tcl_GetIntFromObj * checks whether the current value of the long can be represented by an * int. * * Results: * The newly created object is returned. This object will have an invalid * string representation. The returned object has ref count 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG #undef Tcl_NewLongObj Tcl_Obj * Tcl_NewLongObj( register long longValue) /* Long integer used to initialize the * new object. */ { return Tcl_DbNewLongObj(longValue, "unknown", 0); } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_NewLongObj( register long longValue) /* Long integer used to initialize the * new object. */ { register Tcl_Obj *objPtr; TclNewLongObj(objPtr, longValue); return objPtr; } #endif /* if TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_DbNewLongObj -- * * If a client is compiled with TCL_MEM_DEBUG defined, calls to * Tcl_NewIntObj and Tcl_NewLongObj to create new integer or long integer * objects end up calling the debugging function Tcl_DbNewLongObj * instead. We provide two implementations of Tcl_DbNewLongObj so that * whether the Tcl core is compiled to do memory debugging of the core is * independent of whether a client requests debugging for itself. * * When the core is compiled with TCL_MEM_DEBUG defined, Tcl_DbNewLongObj * calls Tcl_DbCkalloc directly with the file name and line number from * its caller. This simplifies debugging since then the [memory active] * command will report the caller's file name and line number when * reporting objects that haven't been freed. * * Otherwise, when the core is compiled without TCL_MEM_DEBUG defined, * this function just returns the result of calling Tcl_NewLongObj. * * Results: * The newly created long integer object is returned. This object will * have an invalid string representation. The returned object has ref * count 0. * * Side effects: * Allocates memory. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_DbNewLongObj( register long longValue, /* Long integer used to initialize the new * object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { register Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); objPtr->bytes = NULL; objPtr->internalRep.longValue = longValue; objPtr->typePtr = &tclIntType; return objPtr; } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_DbNewLongObj( register long longValue, /* Long integer used to initialize the new * object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { return Tcl_NewLongObj(longValue); } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_SetLongObj -- * * Modify an object to be an integer object and to have the specified * long integer value. * * Results: * None. * * Side effects: * The object's old string rep, if any, is freed. Also, any old internal * rep is freed. * *---------------------------------------------------------------------- */ void Tcl_SetLongObj( register Tcl_Obj *objPtr, /* Object whose internal rep to init. */ register long longValue) /* Long integer used to initialize the * object's value. */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetLongObj"); } TclSetLongObj(objPtr, longValue); } /* *---------------------------------------------------------------------- * * Tcl_GetLongFromObj -- * * Attempt to return an long integer from the Tcl object "objPtr". If the * object is not already an int object, an attempt will be made to * convert it to one. * * Results: * The return value is a standard Tcl object result. If an error occurs * during conversion, an error message is left in the interpreter's * result unless "interp" is NULL. * * Side effects: * If the object is not already an int object, the conversion will free * any old internal representation. * *---------------------------------------------------------------------- */ int Tcl_GetLongFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr, /* The object from which to get a long. */ register long *longPtr) /* Place to store resulting long. */ { do { if (objPtr->typePtr == &tclIntType) { *longPtr = objPtr->internalRep.longValue; return TCL_OK; } #ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { /* * We return any integer in the range -ULONG_MAX to ULONG_MAX * converted to a long, ignoring overflow. The rule preserves * existing semantics for conversion of integers on input, but * avoids inadvertent demotion of wide integers to 32-bit ones in * the internal rep. */ Tcl_WideInt w = objPtr->internalRep.wideValue; if (w >= -(Tcl_WideInt)(ULONG_MAX) && w <= (Tcl_WideInt)(ULONG_MAX)) { *longPtr = Tcl_WideAsLong(w); return TCL_OK; } goto tooLarge; } #endif if (objPtr->typePtr == &tclDoubleType) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected integer but got \"%s\"", Tcl_GetString(objPtr))); Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL); } return TCL_ERROR; } if (objPtr->typePtr == &tclBignumType) { /* * Must check for those bignum values that can fit in a long, even * when auto-narrowing is enabled. Only those values in the signed * long range get auto-narrowed to tclIntType, while all the * values in the unsigned long range will fit in a long. */ mp_int big; UNPACK_BIGNUM(objPtr, big); if ((size_t) big.used <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1) / DIGIT_BIT) { unsigned long value = 0, numBytes = sizeof(long); long scratch; unsigned char *bytes = (unsigned char *) &scratch; if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) { while (numBytes-- > 0) { value = (value << CHAR_BIT) | *bytes++; } if (big.sign) { *longPtr = - (long) value; } else { *longPtr = (long) value; } return TCL_OK; } } #ifndef TCL_WIDE_INT_IS_LONG tooLarge: #endif if (interp != NULL) { const char *s = "integer value too large to represent"; Tcl_Obj *msg = Tcl_NewStringObj(s, -1); Tcl_SetObjResult(interp, msg); Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL); } return TCL_ERROR; } } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL, TCL_PARSE_INTEGER_ONLY)==TCL_OK); return TCL_ERROR; } #ifndef TCL_WIDE_INT_IS_LONG /* *---------------------------------------------------------------------- * * UpdateStringOfWideInt -- * * Update the string representation for a wide integer object. Note: this * function does not free an existing old string rep so storage will be * lost if this has not already been done. * * Results: * None. * * Side effects: * The object's string is set to a valid string that results from the * wideInt-to-string conversion. * *---------------------------------------------------------------------- */ static void UpdateStringOfWideInt( register Tcl_Obj *objPtr) /* Int object whose string rep to update. */ { char buffer[TCL_INTEGER_SPACE+2]; register unsigned len; register Tcl_WideInt wideVal = objPtr->internalRep.wideValue; /* * Note that sprintf will generate a compiler warning under Mingw claiming * %I64 is an unknown format specifier. Just ignore this warning. We can't * use %L as the format specifier since that gets printed as a 32 bit * value. */ sprintf(buffer, "%" TCL_LL_MODIFIER "d", wideVal); len = strlen(buffer); objPtr->bytes = ckalloc(len + 1); memcpy(objPtr->bytes, buffer, len + 1); objPtr->length = len; } #endif /* !TCL_WIDE_INT_IS_LONG */ /* *---------------------------------------------------------------------- * * Tcl_NewWideIntObj -- * * If a client is compiled with TCL_MEM_DEBUG defined, calls to * Tcl_NewWideIntObj to create a new 64-bit integer object end up calling * the debugging function Tcl_DbNewWideIntObj instead. * * Otherwise, if the client is compiled without TCL_MEM_DEBUG defined, * calls to Tcl_NewWideIntObj result in a call to one of the two * Tcl_NewWideIntObj implementations below. We provide two * implementations so that the Tcl core can be compiled to do memory * debugging of the core even if a client does not request it for itself. * * Results: * The newly created object is returned. This object will have an invalid * string representation. The returned object has ref count 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG #undef Tcl_NewWideIntObj Tcl_Obj * Tcl_NewWideIntObj( register Tcl_WideInt wideValue) /* Wide integer used to initialize the new * object. */ { return Tcl_DbNewWideIntObj(wideValue, "unknown", 0); } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_NewWideIntObj( register Tcl_WideInt wideValue) /* Wide integer used to initialize the new * object. */ { register Tcl_Obj *objPtr; TclNewObj(objPtr); Tcl_SetWideIntObj(objPtr, wideValue); return objPtr; } #endif /* if TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_DbNewWideIntObj -- * * If a client is compiled with TCL_MEM_DEBUG defined, calls to * Tcl_NewWideIntObj to create new wide integer end up calling the * debugging function Tcl_DbNewWideIntObj instead. We provide two * implementations of Tcl_DbNewWideIntObj so that whether the Tcl core is * compiled to do memory debugging of the core is independent of whether * a client requests debugging for itself. * * When the core is compiled with TCL_MEM_DEBUG defined, * Tcl_DbNewWideIntObj calls Tcl_DbCkalloc directly with the file name * and line number from its caller. This simplifies debugging since then * the checkmem command will report the caller's file name and line * number when reporting objects that haven't been freed. * * Otherwise, when the core is compiled without TCL_MEM_DEBUG defined, * this function just returns the result of calling Tcl_NewWideIntObj. * * Results: * The newly created wide integer object is returned. This object will * have an invalid string representation. The returned object has ref * count 0. * * Side effects: * Allocates memory. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_DbNewWideIntObj( register Tcl_WideInt wideValue, /* Wide integer used to initialize the new * object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { register Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); Tcl_SetWideIntObj(objPtr, wideValue); return objPtr; } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_DbNewWideIntObj( register Tcl_WideInt wideValue, /* Long integer used to initialize the new * object. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { return Tcl_NewWideIntObj(wideValue); } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_SetWideIntObj -- * * Modify an object to be a wide integer object and to have the specified * wide integer value. * * Results: * None. * * Side effects: * The object's old string rep, if any, is freed. Also, any old internal * rep is freed. * *---------------------------------------------------------------------- */ void Tcl_SetWideIntObj( register Tcl_Obj *objPtr, /* Object w. internal rep to init. */ register Tcl_WideInt wideValue) /* Wide integer used to initialize the * object's value. */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetWideIntObj"); } if ((wideValue >= (Tcl_WideInt) LONG_MIN) && (wideValue <= (Tcl_WideInt) LONG_MAX)) { TclSetLongObj(objPtr, (long) wideValue); } else { #ifndef TCL_WIDE_INT_IS_LONG TclSetWideIntObj(objPtr, wideValue); #else mp_int big; TclBNInitBignumFromWideInt(&big, wideValue); Tcl_SetBignumObj(objPtr, &big); #endif } } /* *---------------------------------------------------------------------- * * Tcl_GetWideIntFromObj -- * * Attempt to return a wide integer from the Tcl object "objPtr". If the * object is not already a wide int object, an attempt will be made to * convert it to one. * * Results: * The return value is a standard Tcl object result. If an error occurs * during conversion, an error message is left in the interpreter's * result unless "interp" is NULL. * * Side effects: * If the object is not already an int object, the conversion will free * any old internal representation. * *---------------------------------------------------------------------- */ int Tcl_GetWideIntFromObj( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr, /* Object from which to get a wide int. */ register Tcl_WideInt *wideIntPtr) /* Place to store resulting long. */ { do { #ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { *wideIntPtr = objPtr->internalRep.wideValue; return TCL_OK; } #endif if (objPtr->typePtr == &tclIntType) { *wideIntPtr = (Tcl_WideInt) objPtr->internalRep.longValue; return TCL_OK; } if (objPtr->typePtr == &tclDoubleType) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected integer but got \"%s\"", Tcl_GetString(objPtr))); Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL); } return TCL_ERROR; } if (objPtr->typePtr == &tclBignumType) { /* * Must check for those bignum values that can fit in a * Tcl_WideInt, even when auto-narrowing is enabled. */ mp_int big; UNPACK_BIGNUM(objPtr, big); if ((size_t) big.used <= (CHAR_BIT * sizeof(Tcl_WideInt) + DIGIT_BIT - 1) / DIGIT_BIT) { Tcl_WideUInt value = 0; unsigned long numBytes = sizeof(Tcl_WideInt); Tcl_WideInt scratch; unsigned char *bytes = (unsigned char *) &scratch; if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) { while (numBytes-- > 0) { value = (value << CHAR_BIT) | *bytes++; } if (big.sign) { *wideIntPtr = - (Tcl_WideInt) value; } else { *wideIntPtr = (Tcl_WideInt) value; } return TCL_OK; } } if (interp != NULL) { const char *s = "integer value too large to represent"; Tcl_Obj *msg = Tcl_NewStringObj(s, -1); Tcl_SetObjResult(interp, msg); Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL); } return TCL_ERROR; } } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL, TCL_PARSE_INTEGER_ONLY)==TCL_OK); return TCL_ERROR; } #ifndef TCL_WIDE_INT_IS_LONG /* *---------------------------------------------------------------------- * * SetWideIntFromAny -- * * Attempts to force the internal representation for a Tcl object to * tclWideIntType, specifically. * * Results: * The return value is a standard object Tcl result. If an error occurs * during conversion, an error message is left in the interpreter's * result unless "interp" is NULL. * *---------------------------------------------------------------------- */ static int SetWideIntFromAny( Tcl_Interp *interp, /* Tcl interpreter */ Tcl_Obj *objPtr) /* Pointer to the object to convert */ { Tcl_WideInt w; return Tcl_GetWideIntFromObj(interp, objPtr, &w); } #endif /* !TCL_WIDE_INT_IS_LONG */ /* *---------------------------------------------------------------------- * * FreeBignum -- * * This function frees the internal rep of a bignum. * * Results: * None. * *---------------------------------------------------------------------- */ static void FreeBignum( Tcl_Obj *objPtr) { mp_int toFree; /* Bignum to free */ UNPACK_BIGNUM(objPtr, toFree); mp_clear(&toFree); if (PTR2INT(objPtr->internalRep.twoPtrValue.ptr2) < 0) { ckfree(objPtr->internalRep.twoPtrValue.ptr1); } objPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * DupBignum -- * * This function duplicates the internal rep of a bignum. * * Results: * None. * * Side effects: * The destination object receies a copy of the source object * *---------------------------------------------------------------------- */ static void DupBignum( Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) { mp_int bignumVal; mp_int bignumCopy; copyPtr->typePtr = &tclBignumType; UNPACK_BIGNUM(srcPtr, bignumVal); if (mp_init_copy(&bignumCopy, &bignumVal) != MP_OKAY) { Tcl_Panic("initialization failure in DupBignum"); } PACK_BIGNUM(bignumCopy, copyPtr); } /* *---------------------------------------------------------------------- * * UpdateStringOfBignum -- * * This function updates the string representation of a bignum object. * * Results: * None. * * Side effects: * The object's string is set to whatever results from the bignum- * to-string conversion. * * The object's existing string representation is NOT freed; memory will leak * if the string rep is still valid at the time this function is called. * *---------------------------------------------------------------------- */ static void UpdateStringOfBignum( Tcl_Obj *objPtr) { mp_int bignumVal; int size; int status; char *stringVal; UNPACK_BIGNUM(objPtr, bignumVal); status = mp_radix_size(&bignumVal, 10, &size); if (status != MP_OKAY) { Tcl_Panic("radix size failure in UpdateStringOfBignum"); } if (size == 3) { /* * mp_radix_size() returns 3 when more than INT_MAX bytes would be * needed to hold the string rep (because mp_radix_size ignores * integer overflow issues). When we know the string rep will be more * than 3, we can conclude the string rep would overflow our string * length limits. * * Note that so long as we enforce our bignums to the size that fits * in a packed bignum, this branch will never be taken. */ Tcl_Panic("UpdateStringOfBignum: string length limit exceeded"); } stringVal = ckalloc(size); status = mp_toradix_n(&bignumVal, stringVal, 10, size); if (status != MP_OKAY) { Tcl_Panic("conversion failure in UpdateStringOfBignum"); } objPtr->bytes = stringVal; objPtr->length = size - 1; /* size includes a trailing NUL byte. */ } /* *---------------------------------------------------------------------- * * Tcl_NewBignumObj -- * * Creates an initializes a bignum object. * * Results: * Returns the newly created object. * * Side effects: * The bignum value is cleared, since ownership has transferred to Tcl. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG #undef Tcl_NewBignumObj Tcl_Obj * Tcl_NewBignumObj( mp_int *bignumValue) { return Tcl_DbNewBignumObj(bignumValue, "unknown", 0); } #else Tcl_Obj * Tcl_NewBignumObj( mp_int *bignumValue) { Tcl_Obj *objPtr; TclNewObj(objPtr); Tcl_SetBignumObj(objPtr, bignumValue); return objPtr; } #endif /* *---------------------------------------------------------------------- * * Tcl_DbNewBignumObj -- * * This function is normally called when debugging: that is, when * TCL_MEM_DEBUG is defined. It constructs a bignum object, recording the * creation point so that [memory active] can report it. * * Results: * Returns the newly created object. * * Side effects: * The bignum value is cleared, since ownership has transferred to Tcl. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_DbNewBignumObj( mp_int *bignumValue, const char *file, int line) { Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); Tcl_SetBignumObj(objPtr, bignumValue); return objPtr; } #else Tcl_Obj * Tcl_DbNewBignumObj( mp_int *bignumValue, const char *file, int line) { return Tcl_NewBignumObj(bignumValue); } #endif /* *---------------------------------------------------------------------- * * GetBignumFromObj -- * * This function retrieves a 'bignum' value from a Tcl object, converting * the object if necessary. Either copies or transfers the mp_int value * depending on the copy flag value passed in. * * Results: * Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise. * * Side effects: * A copy of bignum is stored in *bignumValue, which is expected to be * uninitialized or cleared. If conversion fails, and the 'interp' * argument is not NULL, an error message is stored in the interpreter * result. * *---------------------------------------------------------------------- */ static int GetBignumFromObj( Tcl_Interp *interp, /* Tcl interpreter for error reporting */ Tcl_Obj *objPtr, /* Object to read */ int copy, /* Whether to copy the returned bignum value */ mp_int *bignumValue) /* Returned bignum value. */ { do { if (objPtr->typePtr == &tclBignumType) { if (copy || Tcl_IsShared(objPtr)) { mp_int temp; UNPACK_BIGNUM(objPtr, temp); mp_init_copy(bignumValue, &temp); } else { UNPACK_BIGNUM(objPtr, *bignumValue); objPtr->internalRep.twoPtrValue.ptr1 = NULL; objPtr->internalRep.twoPtrValue.ptr2 = NULL; objPtr->typePtr = NULL; if (objPtr->bytes == NULL) { TclInitStringRep(objPtr, tclEmptyStringRep, 0); } } return TCL_OK; } if (objPtr->typePtr == &tclIntType) { TclBNInitBignumFromLong(bignumValue, objPtr->internalRep.longValue); return TCL_OK; } #ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { TclBNInitBignumFromWideInt(bignumValue, objPtr->internalRep.wideValue); return TCL_OK; } #endif if (objPtr->typePtr == &tclDoubleType) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected integer but got \"%s\"", Tcl_GetString(objPtr))); Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL); } return TCL_ERROR; } } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL, TCL_PARSE_INTEGER_ONLY)==TCL_OK); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_GetBignumFromObj -- * * This function retrieves a 'bignum' value from a Tcl object, converting * the object if necessary. * * Results: * Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise. * * Side effects: * A copy of bignum is stored in *bignumValue, which is expected to be * uninitialized or cleared. If conversion fails, an the 'interp' * argument is not NULL, an error message is stored in the interpreter * result. * * It is expected that the caller will NOT have invoked mp_init on the * bignum value before passing it in. Tcl will initialize the mp_int as * it sets the value. The value is a copy of the value in objPtr, so it * becomes the responsibility of the caller to call mp_clear on it. * *---------------------------------------------------------------------- */ int Tcl_GetBignumFromObj( Tcl_Interp *interp, /* Tcl interpreter for error reporting */ Tcl_Obj *objPtr, /* Object to read */ mp_int *bignumValue) /* Returned bignum value. */ { return GetBignumFromObj(interp, objPtr, 1, bignumValue); } /* *---------------------------------------------------------------------- * * Tcl_TakeBignumFromObj -- * * This function retrieves a 'bignum' value from a Tcl object, converting * the object if necessary. * * Results: * Returns TCL_OK if the conversion is successful, TCL_ERROR otherwise. * * Side effects: * A copy of bignum is stored in *bignumValue, which is expected to be * uninitialized or cleared. If conversion fails, an the 'interp' * argument is not NULL, an error message is stored in the interpreter * result. * * It is expected that the caller will NOT have invoked mp_init on the * bignum value before passing it in. Tcl will initialize the mp_int as * it sets the value. The value is transferred from the internals of * objPtr to the caller, passing responsibility of the caller to call * mp_clear on it. The objPtr is cleared to hold an empty value. * *---------------------------------------------------------------------- */ int Tcl_TakeBignumFromObj( Tcl_Interp *interp, /* Tcl interpreter for error reporting */ Tcl_Obj *objPtr, /* Object to read */ mp_int *bignumValue) /* Returned bignum value. */ { return GetBignumFromObj(interp, objPtr, 0, bignumValue); } /* *---------------------------------------------------------------------- * * Tcl_SetBignumObj -- * * This function sets the value of a Tcl_Obj to a large integer. * * Results: * None. * * Side effects: * Object value is stored. The bignum value is cleared, since ownership * has transferred to Tcl. * *---------------------------------------------------------------------- */ void Tcl_SetBignumObj( Tcl_Obj *objPtr, /* Object to set */ mp_int *bignumValue) /* Value to store */ { if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetBignumObj"); } if ((size_t) bignumValue->used <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1) / DIGIT_BIT) { unsigned long value = 0, numBytes = sizeof(long); long scratch; unsigned char *bytes = (unsigned char *) &scratch; if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) { goto tooLargeForLong; } while (numBytes-- > 0) { value = (value << CHAR_BIT) | *bytes++; } if (value > (((~(unsigned long)0) >> 1) + bignumValue->sign)) { goto tooLargeForLong; } if (bignumValue->sign) { TclSetLongObj(objPtr, -(long)value); } else { TclSetLongObj(objPtr, (long)value); } mp_clear(bignumValue); return; } tooLargeForLong: #ifndef TCL_WIDE_INT_IS_LONG if ((size_t) bignumValue->used <= (CHAR_BIT * sizeof(Tcl_WideInt) + DIGIT_BIT - 1) / DIGIT_BIT) { Tcl_WideUInt value = 0; unsigned long numBytes = sizeof(Tcl_WideInt); Tcl_WideInt scratch; unsigned char *bytes = (unsigned char *)&scratch; if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) { goto tooLargeForWide; } while (numBytes-- > 0) { value = (value << CHAR_BIT) | *bytes++; } if (value > (((~(Tcl_WideUInt)0) >> 1) + bignumValue->sign)) { goto tooLargeForWide; } if (bignumValue->sign) { TclSetWideIntObj(objPtr, -(Tcl_WideInt)value); } else { TclSetWideIntObj(objPtr, (Tcl_WideInt)value); } mp_clear(bignumValue); return; } tooLargeForWide: #endif TclInvalidateStringRep(objPtr); TclFreeIntRep(objPtr); TclSetBignumIntRep(objPtr, bignumValue); } /* *---------------------------------------------------------------------- * * TclSetBignumIntRep -- * * Install a bignum into the internal representation of an object. * * Results: * None. * * Side effects: * Object internal representation is updated and object type is set. The * bignum value is cleared, since ownership has transferred to the * object. * *---------------------------------------------------------------------- */ void TclSetBignumIntRep( Tcl_Obj *objPtr, mp_int *bignumValue) { objPtr->typePtr = &tclBignumType; PACK_BIGNUM(*bignumValue, objPtr); /* * Clear the mp_int value. * * Don't call mp_clear() because it would free the digit array we just * packed into the Tcl_Obj. */ bignumValue->dp = NULL; bignumValue->alloc = bignumValue->used = 0; bignumValue->sign = MP_NEG; } /* *---------------------------------------------------------------------- * * TclGetNumberFromObj -- * * Extracts a number (of any possible numeric type) from an object. * * Results: * Whether the extraction worked. The type is stored in the variable * referred to by the typePtr argument, and a pointer to the * representation is stored in the variable referred to by the * clientDataPtr. * * Side effects: * Can allocate thread-specific data for handling the copy-out space for * bignums; this space is shared within a thread. * *---------------------------------------------------------------------- */ int TclGetNumberFromObj( Tcl_Interp *interp, Tcl_Obj *objPtr, ClientData *clientDataPtr, int *typePtr) { do { if (objPtr->typePtr == &tclDoubleType) { if (TclIsNaN(objPtr->internalRep.doubleValue)) { *typePtr = TCL_NUMBER_NAN; } else { *typePtr = TCL_NUMBER_DOUBLE; } *clientDataPtr = &objPtr->internalRep.doubleValue; return TCL_OK; } if (objPtr->typePtr == &tclIntType) { *typePtr = TCL_NUMBER_LONG; *clientDataPtr = &objPtr->internalRep.longValue; return TCL_OK; } #ifndef TCL_WIDE_INT_IS_LONG if (objPtr->typePtr == &tclWideIntType) { *typePtr = TCL_NUMBER_WIDE; *clientDataPtr = &objPtr->internalRep.wideValue; return TCL_OK; } #endif if (objPtr->typePtr == &tclBignumType) { static Tcl_ThreadDataKey bignumKey; mp_int *bigPtr = Tcl_GetThreadData(&bignumKey, (int) sizeof(mp_int)); UNPACK_BIGNUM(objPtr, *bigPtr); *typePtr = TCL_NUMBER_BIG; *clientDataPtr = bigPtr; return TCL_OK; } } while (TCL_OK == TclParseNumber(interp, objPtr, "number", NULL, -1, NULL, 0)); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_DbIncrRefCount -- * * This function is normally called when debugging: i.e., when * TCL_MEM_DEBUG is defined. This checks to see whether or not the memory * has been freed before incrementing the ref count. * * When TCL_MEM_DEBUG is not defined, this function just increments the * reference count of the object. * * Results: * None. * * Side effects: * The object's ref count is incremented. * *---------------------------------------------------------------------- */ void Tcl_DbIncrRefCount( register Tcl_Obj *objPtr, /* The object we are registering a reference * to. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { #ifdef TCL_MEM_DEBUG if (objPtr->refCount == 0x61616161) { fprintf(stderr, "file = %s, line = %d\n", file, line); fflush(stderr); Tcl_Panic("incrementing refCount of previously disposed object"); } # ifdef TCL_THREADS /* * Check to make sure that the Tcl_Obj was allocated by the current * thread. Don't do this check when shutting down since thread local * storage can be finalized before the last Tcl_Obj is freed. */ if (!TclInExit()) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Tcl_HashTable *tablePtr = tsdPtr->objThreadMap; Tcl_HashEntry *hPtr; if (!tablePtr) { Tcl_Panic("object table not initialized"); } hPtr = Tcl_FindHashEntry(tablePtr, objPtr); if (!hPtr) { Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread", "incr ref count"); } } # endif /* TCL_THREADS */ #endif /* TCL_MEM_DEBUG */ ++(objPtr)->refCount; } /* *---------------------------------------------------------------------- * * Tcl_DbDecrRefCount -- * * This function is normally called when debugging: i.e., when * TCL_MEM_DEBUG is defined. This checks to see whether or not the memory * has been freed before decrementing the ref count. * * When TCL_MEM_DEBUG is not defined, this function just decrements the * reference count of the object. * * Results: * None. * * Side effects: * The object's ref count is incremented. * *---------------------------------------------------------------------- */ void Tcl_DbDecrRefCount( register Tcl_Obj *objPtr, /* The object we are releasing a reference * to. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { #ifdef TCL_MEM_DEBUG if (objPtr->refCount == 0x61616161) { fprintf(stderr, "file = %s, line = %d\n", file, line); fflush(stderr); Tcl_Panic("decrementing refCount of previously disposed object"); } # ifdef TCL_THREADS /* * Check to make sure that the Tcl_Obj was allocated by the current * thread. Don't do this check when shutting down since thread local * storage can be finalized before the last Tcl_Obj is freed. */ if (!TclInExit()) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Tcl_HashTable *tablePtr = tsdPtr->objThreadMap; Tcl_HashEntry *hPtr; if (!tablePtr) { Tcl_Panic("object table not initialized"); } hPtr = Tcl_FindHashEntry(tablePtr, objPtr); if (!hPtr) { Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread", "decr ref count"); } } # endif /* TCL_THREADS */ #endif /* TCL_MEM_DEBUG */ if (objPtr->refCount-- <= 1) { TclFreeObj(objPtr); } } /* *---------------------------------------------------------------------- * * Tcl_DbIsShared -- * * This function is normally called when debugging: i.e., when * TCL_MEM_DEBUG is defined. It tests whether the object has a ref count * greater than one. * * When TCL_MEM_DEBUG is not defined, this function just tests if the * object has a ref count greater than one. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_DbIsShared( register Tcl_Obj *objPtr, /* The object to test for being shared. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { #ifdef TCL_MEM_DEBUG if (objPtr->refCount == 0x61616161) { fprintf(stderr, "file = %s, line = %d\n", file, line); fflush(stderr); Tcl_Panic("checking whether previously disposed object is shared"); } # ifdef TCL_THREADS /* * Check to make sure that the Tcl_Obj was allocated by the current * thread. Don't do this check when shutting down since thread local * storage can be finalized before the last Tcl_Obj is freed. */ if (!TclInExit()) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Tcl_HashTable *tablePtr = tsdPtr->objThreadMap; Tcl_HashEntry *hPtr; if (!tablePtr) { Tcl_Panic("object table not initialized"); } hPtr = Tcl_FindHashEntry(tablePtr, objPtr); if (!hPtr) { Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread", "check shared status"); } } # endif /* TCL_THREADS */ #endif /* TCL_MEM_DEBUG */ #ifdef TCL_COMPILE_STATS Tcl_MutexLock(&tclObjMutex); if ((objPtr)->refCount <= 1) { tclObjsShared[1]++; } else if ((objPtr)->refCount < TCL_MAX_SHARED_OBJ_STATS) { tclObjsShared[(objPtr)->refCount]++; } else { tclObjsShared[0]++; } Tcl_MutexUnlock(&tclObjMutex); #endif /* TCL_COMPILE_STATS */ return ((objPtr)->refCount > 1); } /* *---------------------------------------------------------------------- * * Tcl_InitObjHashTable -- * * Given storage for a hash table, set up the fields to prepare the hash * table for use, the keys are Tcl_Obj *. * * Results: * None. * * Side effects: * TablePtr is now ready to be passed to Tcl_FindHashEntry and * Tcl_CreateHashEntry. * *---------------------------------------------------------------------- */ void Tcl_InitObjHashTable( register Tcl_HashTable *tablePtr) /* Pointer to table record, which is supplied * by the caller. */ { Tcl_InitCustomHashTable(tablePtr, TCL_CUSTOM_PTR_KEYS, &tclObjHashKeyType); } /* *---------------------------------------------------------------------- * * AllocObjEntry -- * * Allocate space for a Tcl_HashEntry containing the Tcl_Obj * key. * * Results: * The return value is a pointer to the created entry. * * Side effects: * Increments the reference count on the object. * *---------------------------------------------------------------------- */ static Tcl_HashEntry * AllocObjEntry( Tcl_HashTable *tablePtr, /* Hash table. */ void *keyPtr) /* Key to store in the hash table entry. */ { Tcl_Obj *objPtr = keyPtr; Tcl_HashEntry *hPtr = ckalloc(sizeof(Tcl_HashEntry)); hPtr->key.objPtr = objPtr; Tcl_IncrRefCount(objPtr); hPtr->clientData = NULL; return hPtr; } /* *---------------------------------------------------------------------- * * TclCompareObjKeys -- * * Compares two Tcl_Obj * keys. * * Results: * The return value is 0 if they are different and 1 if they are the * same. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclCompareObjKeys( void *keyPtr, /* New key to compare. */ Tcl_HashEntry *hPtr) /* Existing key to compare. */ { Tcl_Obj *objPtr1 = keyPtr; Tcl_Obj *objPtr2 = (Tcl_Obj *) hPtr->key.oneWordValue; register const char *p1, *p2; register int l1, l2; /* * If the object pointers are the same then they match. * OPT: this comparison was moved to the caller if (objPtr1 == objPtr2) return 1; */ /* * Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being * in a register. */ p1 = TclGetString(objPtr1); l1 = objPtr1->length; p2 = TclGetString(objPtr2); l2 = objPtr2->length; /* * Only compare if the string representations are of the same length. */ if (l1 == l2) { for (;; p1++, p2++, l1--) { if (*p1 != *p2) { break; } if (l1 == 0) { return 1; } } } return 0; } /* *---------------------------------------------------------------------- * * TclFreeObjEntry -- * * Frees space for a Tcl_HashEntry containing the Tcl_Obj * key. * * Results: * The return value is a pointer to the created entry. * * Side effects: * Decrements the reference count of the object. * *---------------------------------------------------------------------- */ void TclFreeObjEntry( Tcl_HashEntry *hPtr) /* Hash entry to free. */ { Tcl_Obj *objPtr = (Tcl_Obj *) hPtr->key.oneWordValue; Tcl_DecrRefCount(objPtr); ckfree(hPtr); } /* *---------------------------------------------------------------------- * * TclHashObjKey -- * * Compute a one-word summary of the string representation of the * Tcl_Obj, which can be used to generate a hash index. * * Results: * The return value is a one-word summary of the information in the * string representation of the Tcl_Obj. * * Side effects: * None. * *---------------------------------------------------------------------- */ unsigned int TclHashObjKey( Tcl_HashTable *tablePtr, /* Hash table. */ void *keyPtr) /* Key from which to compute hash value. */ { Tcl_Obj *objPtr = keyPtr; int length; const char *string = TclGetStringFromObj(objPtr, &length); unsigned int result = 0; /* * I tried a zillion different hash functions and asked many other people * for advice. Many people had their own favorite functions, all * different, but no-one had much idea why they were good ones. I chose * the one below (multiply by 9 and add new character) because of the * following reasons: * * 1. Multiplying by 10 is perfect for keys that are decimal strings, and * multiplying by 9 is just about as good. * 2. Times-9 is (shift-left-3) plus (old). This means that each * character's bits hang around in the low-order bits of the hash value * for ever, plus they spread fairly rapidly up to the high-order bits * to fill out the hash value. This seems works well both for decimal * and non-decimal strings. * * Note that this function is very weak against malicious strings; it's * very easy to generate multiple keys that have the same hashcode. On the * other hand, that hardly ever actually occurs and this function *is* * very cheap, even by comparison with industry-standard hashes like FNV. * If real strength of hash is required though, use a custom hash based on * Bob Jenkins's lookup3(), but be aware that it's significantly slower. * Tcl does not use that level of strength because it typically does not * need it (and some of the aspects of that strength are genuinely * unnecessary given the rest of Tcl's hash machinery, and the fact that * we do not either transfer hashes to another machine, use them as a true * substitute for equality, or attempt to minimize work in rebuilding the * hash table). * * See also HashStringKey in tclHash.c. * See also HashString in tclLiteral.c. * * See [tcl-Feature Request #2958832] */ if (length > 0) { result = UCHAR(*string); while (--length) { result += (result << 3) + UCHAR(*++string); } } return result; } /* *---------------------------------------------------------------------- * * Tcl_GetCommandFromObj -- * * Returns the command specified by the name in a Tcl_Obj. * * Results: * Returns a token for the command if it is found. Otherwise, if it can't * be found or there is an error, returns NULL. * * Side effects: * May update the internal representation for the object, caching the * command reference so that the next time this function is called with * the same object, the command can be found quickly. * *---------------------------------------------------------------------- */ Tcl_Command Tcl_GetCommandFromObj( Tcl_Interp *interp, /* The interpreter in which to resolve the * command and to report errors. */ register Tcl_Obj *objPtr) /* The object containing the command's name. * If the name starts with "::", will be * looked up in global namespace. Else, looked * up first in the current namespace, then in * global namespace. */ { register ResolvedCmdName *resPtr; /* * Get the internal representation, converting to a command type if * needed. The internal representation is a ResolvedCmdName that points to * the actual command. * * Check the context namespace and the namespace epoch of the resolved * symbol to make sure that it is fresh. Note that we verify that the * namespace id of the context namespace is the same as the one we cached; * this insures that the namespace wasn't deleted and a new one created at * the same address with the same command epoch. Note that fully qualified * names have a NULL refNsPtr, these checks needn't be made. * * Check also that the command's epoch is up to date, and that the command * is not deleted. * * If any check fails, then force another conversion to the command type, * to discard the old rep and create a new one. */ resPtr = objPtr->internalRep.twoPtrValue.ptr1; if ((objPtr->typePtr == &tclCmdNameType) && (resPtr != NULL)) { register Command *cmdPtr = resPtr->cmdPtr; if ((cmdPtr->cmdEpoch == resPtr->cmdEpoch) && !(cmdPtr->flags & CMD_IS_DELETED) && (interp == cmdPtr->nsPtr->interp) && !(cmdPtr->nsPtr->flags & NS_DYING)) { register Namespace *refNsPtr = (Namespace *) TclGetCurrentNamespace(interp); if ((resPtr->refNsPtr == NULL) || ((refNsPtr == resPtr->refNsPtr) && (resPtr->refNsId == refNsPtr->nsId) && (resPtr->refNsCmdEpoch == refNsPtr->cmdRefEpoch))) { return (Tcl_Command) cmdPtr; } } } /* * OK, must create a new internal representation (or fail) as any cache we * had is invalid one way or another. */ if (SetCmdNameFromAny(interp, objPtr) != TCL_OK) { return NULL; } resPtr = objPtr->internalRep.twoPtrValue.ptr1; return (Tcl_Command) (resPtr ? resPtr->cmdPtr : NULL); } /* *---------------------------------------------------------------------- * * TclSetCmdNameObj -- * * Modify an object to be an CmdName object that refers to the argument * Command structure. * * Results: * None. * * Side effects: * The object's old internal rep is freed. It's string rep is not * changed. The refcount in the Command structure is incremented to keep * it from being freed if the command is later deleted until * TclNRExecuteByteCode has a chance to recognize that it was deleted. * *---------------------------------------------------------------------- */ void TclSetCmdNameObj( Tcl_Interp *interp, /* Points to interpreter containing command * that should be cached in objPtr. */ register Tcl_Obj *objPtr, /* Points to Tcl object to be changed to a * CmdName object. */ Command *cmdPtr) /* Points to Command structure that the * CmdName object should refer to. */ { Interp *iPtr = (Interp *) interp; register ResolvedCmdName *resPtr; register Namespace *currNsPtr; const char *name; if (objPtr->typePtr == &tclCmdNameType) { return; } cmdPtr->refCount++; resPtr = ckalloc(sizeof(ResolvedCmdName)); resPtr->cmdPtr = cmdPtr; resPtr->cmdEpoch = cmdPtr->cmdEpoch; resPtr->refCount = 1; name = TclGetString(objPtr); if ((*name++ == ':') && (*name == ':')) { /* * The name is fully qualified: set the referring namespace to * NULL. */ resPtr->refNsPtr = NULL; } else { /* * Get the current namespace. */ currNsPtr = iPtr->varFramePtr->nsPtr; resPtr->refNsPtr = currNsPtr; resPtr->refNsId = currNsPtr->nsId; resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch; } TclFreeIntRep(objPtr); objPtr->internalRep.twoPtrValue.ptr1 = resPtr; objPtr->internalRep.twoPtrValue.ptr2 = NULL; objPtr->typePtr = &tclCmdNameType; } /* *---------------------------------------------------------------------- * * FreeCmdNameInternalRep -- * * Frees the resources associated with a cmdName object's internal * representation. * * Results: * None. * * Side effects: * Decrements the ref count of any cached ResolvedCmdName structure * pointed to by the cmdName's internal representation. If this is the * last use of the ResolvedCmdName, it is freed. This in turn decrements * the ref count of the Command structure pointed to by the * ResolvedSymbol, which may free the Command structure. * *---------------------------------------------------------------------- */ static void FreeCmdNameInternalRep( register Tcl_Obj *objPtr) /* CmdName object with internal * representation to free. */ { register ResolvedCmdName *resPtr = objPtr->internalRep.twoPtrValue.ptr1; if (resPtr != NULL) { /* * Decrement the reference count of the ResolvedCmdName structure. If * there are no more uses, free the ResolvedCmdName structure. */ if (resPtr->refCount-- == 1) { /* * Now free the cached command, unless it is still in its hash * table or if there are other references to it from other cmdName * objects. */ Command *cmdPtr = resPtr->cmdPtr; TclCleanupCommandMacro(cmdPtr); ckfree(resPtr); } } objPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * DupCmdNameInternalRep -- * * Initialize the internal representation of an cmdName Tcl_Obj to a copy * of the internal representation of an existing cmdName object. * * Results: * None. * * Side effects: * "copyPtr"s internal rep is set to point to the ResolvedCmdName * structure corresponding to "srcPtr"s internal rep. Increments the ref * count of the ResolvedCmdName structure pointed to by the cmdName's * internal representation. * *---------------------------------------------------------------------- */ static void DupCmdNameInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ register Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { register ResolvedCmdName *resPtr = srcPtr->internalRep.twoPtrValue.ptr1; copyPtr->internalRep.twoPtrValue.ptr1 = resPtr; copyPtr->internalRep.twoPtrValue.ptr2 = NULL; if (resPtr != NULL) { resPtr->refCount++; } copyPtr->typePtr = &tclCmdNameType; } /* *---------------------------------------------------------------------- * * SetCmdNameFromAny -- * * Generate an cmdName internal form for the Tcl object "objPtr". * * Results: * The return value is a standard Tcl result. The conversion always * succeeds and TCL_OK is returned. * * Side effects: * A pointer to a ResolvedCmdName structure that holds a cached pointer * to the command with a name that matches objPtr's string rep is stored * as objPtr's internal representation. This ResolvedCmdName pointer will * be NULL if no matching command was found. The ref count of the cached * Command's structure (if any) is also incremented. * *---------------------------------------------------------------------- */ static int SetCmdNameFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr) /* The object to convert. */ { Interp *iPtr = (Interp *) interp; const char *name; register Command *cmdPtr; Namespace *currNsPtr; register ResolvedCmdName *resPtr; if (interp == NULL) { return TCL_ERROR; } /* * Find the Command structure, if any, that describes the command called * "name". Build a ResolvedCmdName that holds a cached pointer to this * Command, and bump the reference count in the referenced Command * structure. A Command structure will not be deleted as long as it is * referenced from a CmdName object. */ name = TclGetString(objPtr); cmdPtr = (Command *) Tcl_FindCommand(interp, name, /*ns*/ NULL, /*flags*/ 0); /* * Free the old internalRep before setting the new one. Do this after * getting the string rep to allow the conversion code (in particular, * Tcl_GetStringFromObj) to use that old internalRep. */ if (cmdPtr) { cmdPtr->refCount++; resPtr = objPtr->internalRep.twoPtrValue.ptr1; if ((objPtr->typePtr == &tclCmdNameType) && resPtr && (resPtr->refCount == 1)) { /* * Reuse the old ResolvedCmdName struct instead of freeing it */ Command *oldCmdPtr = resPtr->cmdPtr; if (--oldCmdPtr->refCount == 0) { TclCleanupCommandMacro(oldCmdPtr); } } else { TclFreeIntRep(objPtr); resPtr = ckalloc(sizeof(ResolvedCmdName)); resPtr->refCount = 1; objPtr->internalRep.twoPtrValue.ptr1 = resPtr; objPtr->internalRep.twoPtrValue.ptr2 = NULL; objPtr->typePtr = &tclCmdNameType; } resPtr->cmdPtr = cmdPtr; resPtr->cmdEpoch = cmdPtr->cmdEpoch; if ((*name++ == ':') && (*name == ':')) { /* * The name is fully qualified: set the referring namespace to * NULL. */ resPtr->refNsPtr = NULL; } else { /* * Get the current namespace. */ currNsPtr = iPtr->varFramePtr->nsPtr; resPtr->refNsPtr = currNsPtr; resPtr->refNsId = currNsPtr->nsId; resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch; } } else { TclFreeIntRep(objPtr); objPtr->internalRep.twoPtrValue.ptr1 = NULL; objPtr->internalRep.twoPtrValue.ptr2 = NULL; objPtr->typePtr = &tclCmdNameType; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_RepresentationCmd -- * * Implementation of the "tcl::unsupported::representation" command. * * Results: * Reports the current representation (Tcl_Obj type) of its argument. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_RepresentationCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { char ptrBuffer[2*TCL_INTEGER_SPACE+6]; Tcl_Obj *descObj; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "value"); return TCL_ERROR; } /* * Value is a bignum with a refcount of 14, object pointer at 0x12345678, * internal representation 0x45671234:0x98765432, string representation * "1872361827361287" */ sprintf(ptrBuffer, "%p", (void *) objv[1]); descObj = Tcl_ObjPrintf("value is a %s with a refcount of %d," " object pointer at %s", objv[1]->typePtr ? objv[1]->typePtr->name : "pure string", objv[1]->refCount, ptrBuffer); if (objv[1]->typePtr) { sprintf(ptrBuffer, "%p:%p", (void *) objv[1]->internalRep.twoPtrValue.ptr1, (void *) objv[1]->internalRep.twoPtrValue.ptr2); Tcl_AppendPrintfToObj(descObj, ", internal representation %s", ptrBuffer); } if (objv[1]->bytes) { Tcl_AppendToObj(descObj, ", string representation \"", -1); Tcl_AppendLimitedToObj(descObj, objv[1]->bytes, objv[1]->length, 16, "..."); Tcl_AppendToObj(descObj, "\"", -1); } else { Tcl_AppendToObj(descObj, ", no string representation", -1); } Tcl_SetObjResult(interp, descObj); return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * indent-tabs-mode: nil * End: */ tcl8.6.5/generic/tclEnsemble.c0000644000175000017500000030747612663660065015625 0ustar sergeisergei/* * tclEnsemble.c -- * * Contains support for ensembles (see TIP#112), which provide simple * mechanism for creating composite commands on top of namespaces. * * Copyright (c) 2005-2013 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" /* * Declarations for functions local to this file: */ static inline Tcl_Obj * NewNsObj(Tcl_Namespace *namespacePtr); static inline int EnsembleUnknownCallback(Tcl_Interp *interp, EnsembleConfig *ensemblePtr, int objc, Tcl_Obj *const objv[], Tcl_Obj **prefixObjPtr); static int NsEnsembleImplementationCmd(ClientData clientData, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static int NsEnsembleImplementationCmdNR(ClientData clientData, Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]); static void BuildEnsembleConfig(EnsembleConfig *ensemblePtr); static int NsEnsembleStringOrder(const void *strPtr1, const void *strPtr2); static void DeleteEnsembleConfig(ClientData clientData); static void MakeCachedEnsembleCommand(Tcl_Obj *objPtr, EnsembleConfig *ensemblePtr, const char *subcmdName, Tcl_Obj *prefixObjPtr); static void FreeEnsembleCmdRep(Tcl_Obj *objPtr); static void DupEnsembleCmdRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); static void StringOfEnsembleCmdRep(Tcl_Obj *objPtr); static void CompileToInvokedCommand(Tcl_Interp *interp, Tcl_Parse *parsePtr, Tcl_Obj *replacements, Command *cmdPtr, CompileEnv *envPtr); static int CompileBasicNArgCommand(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, CompileEnv *envPtr); /* * The lists of subcommands and options for the [namespace ensemble] command. */ static const char *const ensembleSubcommands[] = { "configure", "create", "exists", NULL }; enum EnsSubcmds { ENS_CONFIG, ENS_CREATE, ENS_EXISTS }; static const char *const ensembleCreateOptions[] = { "-command", "-map", "-parameters", "-prefixes", "-subcommands", "-unknown", NULL }; enum EnsCreateOpts { CRT_CMD, CRT_MAP, CRT_PARAM, CRT_PREFIX, CRT_SUBCMDS, CRT_UNKNOWN }; static const char *const ensembleConfigOptions[] = { "-map", "-namespace", "-parameters", "-prefixes", "-subcommands", "-unknown", NULL }; enum EnsConfigOpts { CONF_MAP, CONF_NAMESPACE, CONF_PARAM, CONF_PREFIX, CONF_SUBCMDS, CONF_UNKNOWN }; /* * This structure defines a Tcl object type that contains a reference to an * ensemble subcommand (e.g. the "length" in [string length ab]). It is used * to cache the mapping between the subcommand itself and the real command * that implements it. */ const Tcl_ObjType tclEnsembleCmdType = { "ensembleCommand", /* the type's name */ FreeEnsembleCmdRep, /* freeIntRepProc */ DupEnsembleCmdRep, /* dupIntRepProc */ StringOfEnsembleCmdRep, /* updateStringProc */ NULL /* setFromAnyProc */ }; static inline Tcl_Obj * NewNsObj( Tcl_Namespace *namespacePtr) { register Namespace *nsPtr = (Namespace *) namespacePtr; if (namespacePtr == TclGetGlobalNamespace(nsPtr->interp)) { return Tcl_NewStringObj("::", 2); } else { return Tcl_NewStringObj(nsPtr->fullName, -1); } } /* *---------------------------------------------------------------------- * * TclNamespaceEnsembleCmd -- * * Invoked to implement the "namespace ensemble" command that creates and * manipulates ensembles built on top of namespaces. Handles the * following syntax: * * namespace ensemble name ?dictionary? * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * Creates the ensemble for the namespace if one did not previously * exist. Alternatively, alters the way that the ensemble's subcommand => * implementation prefix is configured. * *---------------------------------------------------------------------- */ int TclNamespaceEnsembleCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Namespace *namespacePtr; Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp); Tcl_Command token; Tcl_DictSearch search; Tcl_Obj *listObj; int index, done; if (nsPtr == NULL || nsPtr->flags & NS_DYING) { if (!Tcl_InterpDeleted(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "tried to manipulate ensemble of deleted namespace", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "DEAD", NULL); } return TCL_ERROR; } if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], ensembleSubcommands, "subcommand", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum EnsSubcmds) index) { case ENS_CREATE: { const char *name; int len, allocatedMapFlag = 0; /* * Defaults */ Tcl_Obj *subcmdObj = NULL; Tcl_Obj *mapObj = NULL; int permitPrefix = 1; Tcl_Obj *unknownObj = NULL; Tcl_Obj *paramObj = NULL; /* * Check that we've got option-value pairs... [Bug 1558654] */ if (objc & 1) { Tcl_WrongNumArgs(interp, 2, objv, "?option value ...?"); return TCL_ERROR; } objv += 2; objc -= 2; /* * Work out what name to use for the command to create. If supplied, * it is either fully specified or relative to the current namespace. * If not supplied, it is exactly the name of the current namespace. */ name = nsPtr->fullName; /* * Parse the option list, applying type checks as we go. Note that we * are not incrementing any reference counts in the objects at this * stage, so the presence of an option multiple times won't cause any * memory leaks. */ for (; objc>1 ; objc-=2,objv+=2) { if (Tcl_GetIndexFromObj(interp, objv[0], ensembleCreateOptions, "option", 0, &index) != TCL_OK) { if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } switch ((enum EnsCreateOpts) index) { case CRT_CMD: name = TclGetString(objv[1]); continue; case CRT_SUBCMDS: if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } subcmdObj = (len > 0 ? objv[1] : NULL); continue; case CRT_PARAM: if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } paramObj = (len > 0 ? objv[1] : NULL); continue; case CRT_MAP: { Tcl_Obj *patchedDict = NULL, *subcmdWordsObj; /* * Verify that the map is sensible. */ if (Tcl_DictObjFirst(interp, objv[1], &search, &subcmdWordsObj, &listObj, &done) != TCL_OK) { if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } if (done) { mapObj = NULL; continue; } do { Tcl_Obj **listv; const char *cmd; if (TclListObjGetElements(interp, listObj, &len, &listv) != TCL_OK) { Tcl_DictObjDone(&search); if (patchedDict) { Tcl_DecrRefCount(patchedDict); } if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } if (len < 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "ensemble subcommand implementations " "must be non-empty lists", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "EMPTY_TARGET", NULL); Tcl_DictObjDone(&search); if (patchedDict) { Tcl_DecrRefCount(patchedDict); } if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } cmd = TclGetString(listv[0]); if (!(cmd[0] == ':' && cmd[1] == ':')) { Tcl_Obj *newList = Tcl_NewListObj(len, listv); Tcl_Obj *newCmd = NewNsObj((Tcl_Namespace *) nsPtr); if (nsPtr->parentPtr) { Tcl_AppendStringsToObj(newCmd, "::", NULL); } Tcl_AppendObjToObj(newCmd, listv[0]); Tcl_ListObjReplace(NULL, newList, 0, 1, 1, &newCmd); if (patchedDict == NULL) { patchedDict = Tcl_DuplicateObj(objv[1]); } Tcl_DictObjPut(NULL, patchedDict, subcmdWordsObj, newList); } Tcl_DictObjNext(&search, &subcmdWordsObj,&listObj, &done); } while (!done); if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } mapObj = (patchedDict ? patchedDict : objv[1]); if (patchedDict) { allocatedMapFlag = 1; } continue; } case CRT_PREFIX: if (Tcl_GetBooleanFromObj(interp, objv[1], &permitPrefix) != TCL_OK) { if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } continue; case CRT_UNKNOWN: if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } unknownObj = (len > 0 ? objv[1] : NULL); continue; } } /* * Create the ensemble. Note that this might delete another ensemble * linked to the same namespace, so we must be careful. However, we * should be OK because we only link the namespace into the list once * we've created it (and after any deletions have occurred.) */ token = Tcl_CreateEnsemble(interp, name, NULL, (permitPrefix ? TCL_ENSEMBLE_PREFIX : 0)); Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj); Tcl_SetEnsembleMappingDict(interp, token, mapObj); Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj); Tcl_SetEnsembleParameterList(interp, token, paramObj); /* * Tricky! Must ensure that the result is not shared (command delete * traces could have corrupted the pristine object that we started * with). [Snit test rename-1.5] */ Tcl_ResetResult(interp); Tcl_GetCommandFullName(interp, token, Tcl_GetObjResult(interp)); return TCL_OK; } case ENS_EXISTS: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "cmdname"); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj( Tcl_FindEnsemble(interp, objv[2], 0) != NULL)); return TCL_OK; case ENS_CONFIG: if (objc < 3 || (objc != 4 && !(objc & 1))) { Tcl_WrongNumArgs(interp, 2, objv, "cmdname ?-option value ...? ?arg ...?"); return TCL_ERROR; } token = Tcl_FindEnsemble(interp, objv[2], TCL_LEAVE_ERR_MSG); if (token == NULL) { return TCL_ERROR; } if (objc == 4) { Tcl_Obj *resultObj = NULL; /* silence gcc 4 warning */ if (Tcl_GetIndexFromObj(interp, objv[3], ensembleConfigOptions, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum EnsConfigOpts) index) { case CONF_SUBCMDS: Tcl_GetEnsembleSubcommandList(NULL, token, &resultObj); if (resultObj != NULL) { Tcl_SetObjResult(interp, resultObj); } break; case CONF_PARAM: Tcl_GetEnsembleParameterList(NULL, token, &resultObj); if (resultObj != NULL) { Tcl_SetObjResult(interp, resultObj); } break; case CONF_MAP: Tcl_GetEnsembleMappingDict(NULL, token, &resultObj); if (resultObj != NULL) { Tcl_SetObjResult(interp, resultObj); } break; case CONF_NAMESPACE: namespacePtr = NULL; /* silence gcc 4 warning */ Tcl_GetEnsembleNamespace(NULL, token, &namespacePtr); Tcl_SetObjResult(interp, NewNsObj(namespacePtr)); break; case CONF_PREFIX: { int flags = 0; /* silence gcc 4 warning */ Tcl_GetEnsembleFlags(NULL, token, &flags); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(flags & TCL_ENSEMBLE_PREFIX)); break; } case CONF_UNKNOWN: Tcl_GetEnsembleUnknownHandler(NULL, token, &resultObj); if (resultObj != NULL) { Tcl_SetObjResult(interp, resultObj); } break; } } else if (objc == 3) { /* * Produce list of all information. */ Tcl_Obj *resultObj, *tmpObj = NULL; /* silence gcc 4 warning */ int flags = 0; /* silence gcc 4 warning */ TclNewObj(resultObj); /* -map option */ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(ensembleConfigOptions[CONF_MAP], -1)); Tcl_GetEnsembleMappingDict(NULL, token, &tmpObj); Tcl_ListObjAppendElement(NULL, resultObj, (tmpObj != NULL) ? tmpObj : Tcl_NewObj()); /* -namespace option */ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(ensembleConfigOptions[CONF_NAMESPACE], -1)); namespacePtr = NULL; /* silence gcc 4 warning */ Tcl_GetEnsembleNamespace(NULL, token, &namespacePtr); Tcl_ListObjAppendElement(NULL, resultObj, NewNsObj(namespacePtr)); /* -parameters option */ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(ensembleConfigOptions[CONF_PARAM], -1)); Tcl_GetEnsembleParameterList(NULL, token, &tmpObj); Tcl_ListObjAppendElement(NULL, resultObj, (tmpObj != NULL) ? tmpObj : Tcl_NewObj()); /* -prefix option */ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(ensembleConfigOptions[CONF_PREFIX], -1)); Tcl_GetEnsembleFlags(NULL, token, &flags); Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewBooleanObj(flags & TCL_ENSEMBLE_PREFIX)); /* -subcommands option */ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(ensembleConfigOptions[CONF_SUBCMDS],-1)); Tcl_GetEnsembleSubcommandList(NULL, token, &tmpObj); Tcl_ListObjAppendElement(NULL, resultObj, (tmpObj != NULL) ? tmpObj : Tcl_NewObj()); /* -unknown option */ Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(ensembleConfigOptions[CONF_UNKNOWN],-1)); Tcl_GetEnsembleUnknownHandler(NULL, token, &tmpObj); Tcl_ListObjAppendElement(NULL, resultObj, (tmpObj != NULL) ? tmpObj : Tcl_NewObj()); Tcl_SetObjResult(interp, resultObj); } else { int len, allocatedMapFlag = 0; Tcl_Obj *subcmdObj = NULL, *mapObj = NULL, *paramObj = NULL, *unknownObj = NULL; /* Defaults, silence gcc 4 warnings */ int permitPrefix, flags = 0; /* silence gcc 4 warning */ Tcl_GetEnsembleSubcommandList(NULL, token, &subcmdObj); Tcl_GetEnsembleMappingDict(NULL, token, &mapObj); Tcl_GetEnsembleParameterList(NULL, token, ¶mObj); Tcl_GetEnsembleUnknownHandler(NULL, token, &unknownObj); Tcl_GetEnsembleFlags(NULL, token, &flags); permitPrefix = (flags & TCL_ENSEMBLE_PREFIX) != 0; objv += 3; objc -= 3; /* * Parse the option list, applying type checks as we go. Note that * we are not incrementing any reference counts in the objects at * this stage, so the presence of an option multiple times won't * cause any memory leaks. */ for (; objc>0 ; objc-=2,objv+=2) { if (Tcl_GetIndexFromObj(interp, objv[0],ensembleConfigOptions, "option", 0, &index) != TCL_OK) { freeMapAndError: if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } return TCL_ERROR; } switch ((enum EnsConfigOpts) index) { case CONF_SUBCMDS: if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { goto freeMapAndError; } subcmdObj = (len > 0 ? objv[1] : NULL); continue; case CONF_PARAM: if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { goto freeMapAndError; } paramObj = (len > 0 ? objv[1] : NULL); continue; case CONF_MAP: { Tcl_Obj *patchedDict = NULL, *subcmdWordsObj, **listv; const char *cmd; /* * Verify that the map is sensible. */ if (Tcl_DictObjFirst(interp, objv[1], &search, &subcmdWordsObj, &listObj, &done) != TCL_OK) { goto freeMapAndError; } if (done) { mapObj = NULL; continue; } do { if (TclListObjGetElements(interp, listObj, &len, &listv) != TCL_OK) { Tcl_DictObjDone(&search); if (patchedDict) { Tcl_DecrRefCount(patchedDict); } goto freeMapAndError; } if (len < 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "ensemble subcommand implementations " "must be non-empty lists", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "EMPTY_TARGET", NULL); Tcl_DictObjDone(&search); if (patchedDict) { Tcl_DecrRefCount(patchedDict); } goto freeMapAndError; } cmd = TclGetString(listv[0]); if (!(cmd[0] == ':' && cmd[1] == ':')) { Tcl_Obj *newList = Tcl_DuplicateObj(listObj); Tcl_Obj *newCmd = NewNsObj((Tcl_Namespace*)nsPtr); if (nsPtr->parentPtr) { Tcl_AppendStringsToObj(newCmd, "::", NULL); } Tcl_AppendObjToObj(newCmd, listv[0]); Tcl_ListObjReplace(NULL, newList, 0,1, 1,&newCmd); if (patchedDict == NULL) { patchedDict = Tcl_DuplicateObj(objv[1]); } Tcl_DictObjPut(NULL, patchedDict, subcmdWordsObj, newList); } Tcl_DictObjNext(&search, &subcmdWordsObj, &listObj, &done); } while (!done); if (allocatedMapFlag) { Tcl_DecrRefCount(mapObj); } mapObj = (patchedDict ? patchedDict : objv[1]); if (patchedDict) { allocatedMapFlag = 1; } continue; } case CONF_NAMESPACE: Tcl_SetObjResult(interp, Tcl_NewStringObj( "option -namespace is read-only", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "READ_ONLY", NULL); goto freeMapAndError; case CONF_PREFIX: if (Tcl_GetBooleanFromObj(interp, objv[1], &permitPrefix) != TCL_OK) { goto freeMapAndError; } continue; case CONF_UNKNOWN: if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { goto freeMapAndError; } unknownObj = (len > 0 ? objv[1] : NULL); continue; } } /* * Update the namespace now that we've finished the parsing stage. */ flags = (permitPrefix ? flags|TCL_ENSEMBLE_PREFIX : flags&~TCL_ENSEMBLE_PREFIX); Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj); Tcl_SetEnsembleMappingDict(interp, token, mapObj); Tcl_SetEnsembleParameterList(interp, token, paramObj); Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj); Tcl_SetEnsembleFlags(interp, token, flags); } return TCL_OK; default: Tcl_Panic("unexpected ensemble command"); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_CreateEnsemble -- * * Create a simple ensemble attached to the given namespace. * * Results: * The token for the command created. * * Side effects: * The ensemble is created and marked for compilation. * *---------------------------------------------------------------------- */ Tcl_Command Tcl_CreateEnsemble( Tcl_Interp *interp, const char *name, Tcl_Namespace *namespacePtr, int flags) { Namespace *nsPtr = (Namespace *) namespacePtr; EnsembleConfig *ensemblePtr = ckalloc(sizeof(EnsembleConfig)); Tcl_Obj *nameObj = NULL; if (nsPtr == NULL) { nsPtr = (Namespace *) TclGetCurrentNamespace(interp); } /* * Make the name of the ensemble into a fully qualified name. This might * allocate a temporary object. */ if (!(name[0] == ':' && name[1] == ':')) { nameObj = NewNsObj((Tcl_Namespace *) nsPtr); if (nsPtr->parentPtr == NULL) { Tcl_AppendStringsToObj(nameObj, name, NULL); } else { Tcl_AppendStringsToObj(nameObj, "::", name, NULL); } Tcl_IncrRefCount(nameObj); name = TclGetString(nameObj); } ensemblePtr->nsPtr = nsPtr; ensemblePtr->epoch = 0; Tcl_InitHashTable(&ensemblePtr->subcommandTable, TCL_STRING_KEYS); ensemblePtr->subcommandArrayPtr = NULL; ensemblePtr->subcmdList = NULL; ensemblePtr->subcommandDict = NULL; ensemblePtr->flags = flags; ensemblePtr->numParameters = 0; ensemblePtr->parameterList = NULL; ensemblePtr->unknownHandler = NULL; ensemblePtr->token = Tcl_NRCreateCommand(interp, name, NsEnsembleImplementationCmd, NsEnsembleImplementationCmdNR, ensemblePtr, DeleteEnsembleConfig); ensemblePtr->next = (EnsembleConfig *) nsPtr->ensembles; nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr; /* * Trigger an eventual recomputation of the ensemble command set. Note * that this is slightly tricky, as it means that we are not actually * counting the number of namespace export actions, but it is the simplest * way to go! */ nsPtr->exportLookupEpoch++; if (flags & ENSEMBLE_COMPILE) { ((Command *) ensemblePtr->token)->compileProc = TclCompileEnsemble; } if (nameObj != NULL) { TclDecrRefCount(nameObj); } return ensemblePtr->token; } /* *---------------------------------------------------------------------- * * Tcl_SetEnsembleSubcommandList -- * * Set the subcommand list for a particular ensemble. * * Results: * Tcl result code (error if command token does not indicate an ensemble * or the subcommand list - if non-NULL - is not a list). * * Side effects: * The ensemble is updated and marked for recompilation. * *---------------------------------------------------------------------- */ int Tcl_SetEnsembleSubcommandList( Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *subcmdList) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; Tcl_Obj *oldList; if (cmdPtr->objProc != NsEnsembleImplementationCmd) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command is not an ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL); return TCL_ERROR; } if (subcmdList != NULL) { int length; if (TclListObjLength(interp, subcmdList, &length) != TCL_OK) { return TCL_ERROR; } if (length < 1) { subcmdList = NULL; } } ensemblePtr = cmdPtr->objClientData; oldList = ensemblePtr->subcmdList; ensemblePtr->subcmdList = subcmdList; if (subcmdList != NULL) { Tcl_IncrRefCount(subcmdList); } if (oldList != NULL) { TclDecrRefCount(oldList); } /* * Trigger an eventual recomputation of the ensemble command set. Note * that this is slightly tricky, as it means that we are not actually * counting the number of namespace export actions, but it is the simplest * way to go! */ ensemblePtr->nsPtr->exportLookupEpoch++; /* * Special hack to make compiling of [info exists] work when the * dictionary is modified. */ if (cmdPtr->compileProc != NULL) { ((Interp *) interp)->compileEpoch++; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_SetEnsembleParameterList -- * * Set the parameter list for a particular ensemble. * * Results: * Tcl result code (error if command token does not indicate an ensemble * or the parameter list - if non-NULL - is not a list). * * Side effects: * The ensemble is updated and marked for recompilation. * *---------------------------------------------------------------------- */ int Tcl_SetEnsembleParameterList( Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *paramList) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; Tcl_Obj *oldList; int length; if (cmdPtr->objProc != NsEnsembleImplementationCmd) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command is not an ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL); return TCL_ERROR; } if (paramList == NULL) { length = 0; } else { if (TclListObjLength(interp, paramList, &length) != TCL_OK) { return TCL_ERROR; } if (length < 1) { paramList = NULL; } } ensemblePtr = cmdPtr->objClientData; oldList = ensemblePtr->parameterList; ensemblePtr->parameterList = paramList; if (paramList != NULL) { Tcl_IncrRefCount(paramList); } if (oldList != NULL) { TclDecrRefCount(oldList); } ensemblePtr->numParameters = length; /* * Trigger an eventual recomputation of the ensemble command set. Note * that this is slightly tricky, as it means that we are not actually * counting the number of namespace export actions, but it is the simplest * way to go! */ ensemblePtr->nsPtr->exportLookupEpoch++; /* * Special hack to make compiling of [info exists] work when the * dictionary is modified. */ if (cmdPtr->compileProc != NULL) { ((Interp *) interp)->compileEpoch++; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_SetEnsembleMappingDict -- * * Set the mapping dictionary for a particular ensemble. * * Results: * Tcl result code (error if command token does not indicate an ensemble * or the mapping - if non-NULL - is not a dict). * * Side effects: * The ensemble is updated and marked for recompilation. * *---------------------------------------------------------------------- */ int Tcl_SetEnsembleMappingDict( Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *mapDict) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; Tcl_Obj *oldDict; if (cmdPtr->objProc != NsEnsembleImplementationCmd) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command is not an ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL); return TCL_ERROR; } if (mapDict != NULL) { int size, done; Tcl_DictSearch search; Tcl_Obj *valuePtr; if (Tcl_DictObjSize(interp, mapDict, &size) != TCL_OK) { return TCL_ERROR; } for (Tcl_DictObjFirst(NULL, mapDict, &search, NULL, &valuePtr, &done); !done; Tcl_DictObjNext(&search, NULL, &valuePtr, &done)) { Tcl_Obj *cmdObjPtr; const char *bytes; if (Tcl_ListObjIndex(interp, valuePtr, 0, &cmdObjPtr) != TCL_OK) { Tcl_DictObjDone(&search); return TCL_ERROR; } bytes = TclGetString(cmdObjPtr); if (bytes[0] != ':' || bytes[1] != ':') { Tcl_SetObjResult(interp, Tcl_NewStringObj( "ensemble target is not a fully-qualified command", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNQUALIFIED_TARGET", NULL); Tcl_DictObjDone(&search); return TCL_ERROR; } } if (size < 1) { mapDict = NULL; } } ensemblePtr = cmdPtr->objClientData; oldDict = ensemblePtr->subcommandDict; ensemblePtr->subcommandDict = mapDict; if (mapDict != NULL) { Tcl_IncrRefCount(mapDict); } if (oldDict != NULL) { TclDecrRefCount(oldDict); } /* * Trigger an eventual recomputation of the ensemble command set. Note * that this is slightly tricky, as it means that we are not actually * counting the number of namespace export actions, but it is the simplest * way to go! */ ensemblePtr->nsPtr->exportLookupEpoch++; /* * Special hack to make compiling of [info exists] work when the * dictionary is modified. */ if (cmdPtr->compileProc != NULL) { ((Interp *) interp)->compileEpoch++; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_SetEnsembleUnknownHandler -- * * Set the unknown handler for a particular ensemble. * * Results: * Tcl result code (error if command token does not indicate an ensemble * or the unknown handler - if non-NULL - is not a list). * * Side effects: * The ensemble is updated and marked for recompilation. * *---------------------------------------------------------------------- */ int Tcl_SetEnsembleUnknownHandler( Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *unknownList) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; Tcl_Obj *oldList; if (cmdPtr->objProc != NsEnsembleImplementationCmd) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command is not an ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL); return TCL_ERROR; } if (unknownList != NULL) { int length; if (TclListObjLength(interp, unknownList, &length) != TCL_OK) { return TCL_ERROR; } if (length < 1) { unknownList = NULL; } } ensemblePtr = cmdPtr->objClientData; oldList = ensemblePtr->unknownHandler; ensemblePtr->unknownHandler = unknownList; if (unknownList != NULL) { Tcl_IncrRefCount(unknownList); } if (oldList != NULL) { TclDecrRefCount(oldList); } /* * Trigger an eventual recomputation of the ensemble command set. Note * that this is slightly tricky, as it means that we are not actually * counting the number of namespace export actions, but it is the simplest * way to go! */ ensemblePtr->nsPtr->exportLookupEpoch++; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_SetEnsembleFlags -- * * Set the flags for a particular ensemble. * * Results: * Tcl result code (error if command token does not indicate an * ensemble). * * Side effects: * The ensemble is updated and marked for recompilation. * *---------------------------------------------------------------------- */ int Tcl_SetEnsembleFlags( Tcl_Interp *interp, Tcl_Command token, int flags) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; int wasCompiled; if (cmdPtr->objProc != NsEnsembleImplementationCmd) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command is not an ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL); return TCL_ERROR; } ensemblePtr = cmdPtr->objClientData; wasCompiled = ensemblePtr->flags & ENSEMBLE_COMPILE; /* * This API refuses to set the ENSEMBLE_DEAD flag... */ ensemblePtr->flags &= ENSEMBLE_DEAD; ensemblePtr->flags |= flags & ~ENSEMBLE_DEAD; /* * Trigger an eventual recomputation of the ensemble command set. Note * that this is slightly tricky, as it means that we are not actually * counting the number of namespace export actions, but it is the simplest * way to go! */ ensemblePtr->nsPtr->exportLookupEpoch++; /* * If the ENSEMBLE_COMPILE flag status was changed, install or remove the * compiler function and bump the interpreter's compilation epoch so that * bytecode gets regenerated. */ if (flags & ENSEMBLE_COMPILE) { if (!wasCompiled) { ((Command*) ensemblePtr->token)->compileProc = TclCompileEnsemble; ((Interp *) interp)->compileEpoch++; } } else { if (wasCompiled) { ((Command *) ensemblePtr->token)->compileProc = NULL; ((Interp *) interp)->compileEpoch++; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetEnsembleSubcommandList -- * * Get the list of subcommands associated with a particular ensemble. * * Results: * Tcl result code (error if command token does not indicate an * ensemble). The list of subcommands is returned by updating the * variable pointed to by the last parameter (NULL if this is to be * derived from the mapping dictionary or the associated namespace's * exported commands). * * Side effects: * None * *---------------------------------------------------------------------- */ int Tcl_GetEnsembleSubcommandList( Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **subcmdListPtr) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; if (cmdPtr->objProc != NsEnsembleImplementationCmd) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command is not an ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL); } return TCL_ERROR; } ensemblePtr = cmdPtr->objClientData; *subcmdListPtr = ensemblePtr->subcmdList; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetEnsembleParameterList -- * * Get the list of parameters associated with a particular ensemble. * * Results: * Tcl result code (error if command token does not indicate an * ensemble). The list of parameters is returned by updating the * variable pointed to by the last parameter (NULL if there are * no parameters). * * Side effects: * None * *---------------------------------------------------------------------- */ int Tcl_GetEnsembleParameterList( Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **paramListPtr) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; if (cmdPtr->objProc != NsEnsembleImplementationCmd) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command is not an ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL); } return TCL_ERROR; } ensemblePtr = cmdPtr->objClientData; *paramListPtr = ensemblePtr->parameterList; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetEnsembleMappingDict -- * * Get the command mapping dictionary associated with a particular * ensemble. * * Results: * Tcl result code (error if command token does not indicate an * ensemble). The mapping dict is returned by updating the variable * pointed to by the last parameter (NULL if none is installed). * * Side effects: * None * *---------------------------------------------------------------------- */ int Tcl_GetEnsembleMappingDict( Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **mapDictPtr) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; if (cmdPtr->objProc != NsEnsembleImplementationCmd) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command is not an ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL); } return TCL_ERROR; } ensemblePtr = cmdPtr->objClientData; *mapDictPtr = ensemblePtr->subcommandDict; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetEnsembleUnknownHandler -- * * Get the unknown handler associated with a particular ensemble. * * Results: * Tcl result code (error if command token does not indicate an * ensemble). The unknown handler is returned by updating the variable * pointed to by the last parameter (NULL if no handler is installed). * * Side effects: * None * *---------------------------------------------------------------------- */ int Tcl_GetEnsembleUnknownHandler( Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **unknownListPtr) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; if (cmdPtr->objProc != NsEnsembleImplementationCmd) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command is not an ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL); } return TCL_ERROR; } ensemblePtr = cmdPtr->objClientData; *unknownListPtr = ensemblePtr->unknownHandler; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetEnsembleFlags -- * * Get the flags for a particular ensemble. * * Results: * Tcl result code (error if command token does not indicate an * ensemble). The flags are returned by updating the variable pointed to * by the last parameter. * * Side effects: * None * *---------------------------------------------------------------------- */ int Tcl_GetEnsembleFlags( Tcl_Interp *interp, Tcl_Command token, int *flagsPtr) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; if (cmdPtr->objProc != NsEnsembleImplementationCmd) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command is not an ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL); } return TCL_ERROR; } ensemblePtr = cmdPtr->objClientData; *flagsPtr = ensemblePtr->flags; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetEnsembleNamespace -- * * Get the namespace associated with a particular ensemble. * * Results: * Tcl result code (error if command token does not indicate an * ensemble). Namespace is returned by updating the variable pointed to * by the last parameter. * * Side effects: * None * *---------------------------------------------------------------------- */ int Tcl_GetEnsembleNamespace( Tcl_Interp *interp, Tcl_Command token, Tcl_Namespace **namespacePtrPtr) { Command *cmdPtr = (Command *) token; EnsembleConfig *ensemblePtr; if (cmdPtr->objProc != NsEnsembleImplementationCmd) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command is not an ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL); } return TCL_ERROR; } ensemblePtr = cmdPtr->objClientData; *namespacePtrPtr = (Tcl_Namespace *) ensemblePtr->nsPtr; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_FindEnsemble -- * * Given a command name, get the ensemble token for it, allowing for * [namespace import]s. [Bug 1017022] * * Results: * The token for the ensemble command with the given name, or NULL if the * command either does not exist or is not an ensemble (when an error * message will be written into the interp if thats non-NULL). * * Side effects: * None * *---------------------------------------------------------------------- */ Tcl_Command Tcl_FindEnsemble( Tcl_Interp *interp, /* Where to do the lookup, and where to write * the errors if TCL_LEAVE_ERR_MSG is set in * the flags. */ Tcl_Obj *cmdNameObj, /* Name of command to look up. */ int flags) /* Either 0 or TCL_LEAVE_ERR_MSG; other flags * are probably not useful. */ { Command *cmdPtr; cmdPtr = (Command *) Tcl_FindCommand(interp, TclGetString(cmdNameObj), NULL, flags); if (cmdPtr == NULL) { return NULL; } if (cmdPtr->objProc != NsEnsembleImplementationCmd) { /* * Reuse existing infrastructure for following import link chains * rather than duplicating it. */ cmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr); if (cmdPtr == NULL || cmdPtr->objProc != NsEnsembleImplementationCmd){ if (flags & TCL_LEAVE_ERR_MSG) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not an ensemble command", TclGetString(cmdNameObj))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENSEMBLE", TclGetString(cmdNameObj), NULL); } return NULL; } } return (Tcl_Command) cmdPtr; } /* *---------------------------------------------------------------------- * * Tcl_IsEnsemble -- * * Simple test for ensemble-hood that takes into account imported * ensemble commands as well. * * Results: * Boolean value * * Side effects: * None * *---------------------------------------------------------------------- */ int Tcl_IsEnsemble( Tcl_Command token) { Command *cmdPtr = (Command *) token; if (cmdPtr->objProc == NsEnsembleImplementationCmd) { return 1; } cmdPtr = (Command *) TclGetOriginalCommand((Tcl_Command) cmdPtr); if (cmdPtr == NULL || cmdPtr->objProc != NsEnsembleImplementationCmd) { return 0; } return 1; } /* *---------------------------------------------------------------------- * * TclMakeEnsemble -- * * Create an ensemble from a table of implementation commands. The * ensemble will be subject to (limited) compilation if any of the * implementation commands are compilable. * * The 'name' parameter may be a single command name or a list if * creating an ensemble subcommand (see the binary implementation). * * Currently, the TCL_ENSEMBLE_PREFIX ensemble flag is only used on * top-level ensemble commands. * * Results: * Handle for the new ensemble, or NULL on failure. * * Side effects: * May advance the bytecode compilation epoch. * *---------------------------------------------------------------------- */ Tcl_Command TclMakeEnsemble( Tcl_Interp *interp, const char *name, /* The ensemble name (as explained above) */ const EnsembleImplMap map[]) /* The subcommands to create */ { Tcl_Command ensemble; Tcl_Namespace *ns; Tcl_DString buf, hiddenBuf; const char **nameParts = NULL; const char *cmdName = NULL; int i, nameCount = 0, ensembleFlags = 0, hiddenLen; /* * Construct the path for the ensemble namespace and create it. */ Tcl_DStringInit(&buf); Tcl_DStringInit(&hiddenBuf); TclDStringAppendLiteral(&hiddenBuf, "tcl:"); Tcl_DStringAppend(&hiddenBuf, name, -1); TclDStringAppendLiteral(&hiddenBuf, ":"); hiddenLen = Tcl_DStringLength(&hiddenBuf); if (name[0] == ':' && name[1] == ':') { /* * An absolute name, so use it directly. */ cmdName = name; Tcl_DStringAppend(&buf, name, -1); ensembleFlags = TCL_ENSEMBLE_PREFIX; } else { /* * Not an absolute name, so do munging of it. Note that this treats a * multi-word list differently to a single word. */ TclDStringAppendLiteral(&buf, "::tcl"); if (Tcl_SplitList(NULL, name, &nameCount, &nameParts) != TCL_OK) { Tcl_Panic("invalid ensemble name '%s'", name); } for (i = 0; i < nameCount; ++i) { TclDStringAppendLiteral(&buf, "::"); Tcl_DStringAppend(&buf, nameParts[i], -1); } } ns = Tcl_FindNamespace(interp, Tcl_DStringValue(&buf), NULL, TCL_CREATE_NS_IF_UNKNOWN); if (!ns) { Tcl_Panic("unable to find or create %s namespace!", Tcl_DStringValue(&buf)); } /* * Create the named ensemble in the correct namespace */ if (cmdName == NULL) { if (nameCount == 1) { ensembleFlags = TCL_ENSEMBLE_PREFIX; cmdName = Tcl_DStringValue(&buf) + 5; } else { ns = ns->parentPtr; cmdName = nameParts[nameCount - 1]; } } /* * Switch on compilation always for core ensembles now that we can do * nice bytecode things with them. Do it now. Waiting until later will * just cause pointless epoch bumps. */ ensembleFlags |= ENSEMBLE_COMPILE; ensemble = Tcl_CreateEnsemble(interp, cmdName, ns, ensembleFlags); /* * Create the ensemble mapping dictionary and the ensemble command procs. */ if (ensemble != NULL) { Tcl_Obj *mapDict, *fromObj, *toObj; Command *cmdPtr; TclDStringAppendLiteral(&buf, "::"); TclNewObj(mapDict); for (i=0 ; map[i].name != NULL ; i++) { fromObj = Tcl_NewStringObj(map[i].name, -1); TclNewStringObj(toObj, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf)); Tcl_AppendToObj(toObj, map[i].name, -1); Tcl_DictObjPut(NULL, mapDict, fromObj, toObj); if (map[i].proc || map[i].nreProc) { /* * If the command is unsafe, hide it when we're in a safe * interpreter. The code to do this is really hokey! It also * doesn't work properly yet; this function is always * currently called before the safe-interp flag is set so the * Tcl_IsSafe check fails. */ if (map[i].unsafe && Tcl_IsSafe(interp)) { cmdPtr = (Command *) Tcl_NRCreateCommand(interp, "___tmp", map[i].proc, map[i].nreProc, map[i].clientData, NULL); Tcl_DStringSetLength(&hiddenBuf, hiddenLen); if (Tcl_HideCommand(interp, "___tmp", Tcl_DStringAppend(&hiddenBuf, map[i].name, -1))) { Tcl_Panic("%s", Tcl_GetString(Tcl_GetObjResult(interp))); } } else { /* * Not hidden, so just create it. Yay! */ cmdPtr = (Command *) Tcl_NRCreateCommand(interp, TclGetString(toObj), map[i].proc, map[i].nreProc, map[i].clientData, NULL); } cmdPtr->compileProc = map[i].compileProc; } } Tcl_SetEnsembleMappingDict(interp, ensemble, mapDict); } Tcl_DStringFree(&buf); Tcl_DStringFree(&hiddenBuf); if (nameParts != NULL) { ckfree((char *) nameParts); } return ensemble; } /* *---------------------------------------------------------------------- * * NsEnsembleImplementationCmd -- * * Implements an ensemble of commands (being those exported by a * namespace other than the global namespace) as a command with the same * (short) name as the namespace in the parent namespace. * * Results: * A standard Tcl result code. Will be TCL_ERROR if the command is not an * unambiguous prefix of any command exported by the ensemble's * namespace. * * Side effects: * Depends on the command within the namespace that gets executed. If the * ensemble itself returns TCL_ERROR, a descriptive error message will be * placed in the interpreter's result. * *---------------------------------------------------------------------- */ static int NsEnsembleImplementationCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { return Tcl_NRCallObjProc(interp, NsEnsembleImplementationCmdNR, clientData, objc, objv); } static int NsEnsembleImplementationCmdNR( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { EnsembleConfig *ensemblePtr = clientData; /* The ensemble itself. */ Tcl_Obj *prefixObj; /* An object containing the prefix words of * the command that implements the * subcommand. */ Tcl_HashEntry *hPtr; /* Used for efficient lookup of fully * specified but not yet cached command * names. */ int reparseCount = 0; /* Number of reparses. */ Tcl_Obj *errorObj; /* Used for building error messages. */ /* * Must recheck objc, since numParameters might have changed. Cf. test * namespace-53.9. */ restartEnsembleParse: if (objc < 2 + ensemblePtr->numParameters) { /* * We don't have a subcommand argument. Make error message. */ Tcl_DString buf; /* Message being built */ Tcl_Obj **elemPtrs; /* Parameter names */ int len; /* Number of parameters to append */ Tcl_DStringInit(&buf); if (ensemblePtr->parameterList == NULL) { len = 0; } else if (TclListObjGetElements(NULL, ensemblePtr->parameterList, &len, &elemPtrs) != TCL_OK) { Tcl_Panic("List of ensemble parameters is not a list"); } for (; len>0; len--,elemPtrs++) { TclDStringAppendObj(&buf, *elemPtrs); TclDStringAppendLiteral(&buf, " "); } TclDStringAppendLiteral(&buf, "subcommand ?arg ...?"); Tcl_WrongNumArgs(interp, 1, objv, Tcl_DStringValue(&buf)); Tcl_DStringFree(&buf); return TCL_ERROR; } if (ensemblePtr->nsPtr->flags & NS_DYING) { /* * Don't know how we got here, but make things give up quickly. */ if (!Tcl_InterpDeleted(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "ensemble activated for deleted namespace", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "DEAD", NULL); } return TCL_ERROR; } /* * Determine if the table of subcommands is right. If so, we can just look * up in there and go straight to dispatch. */ if (ensemblePtr->epoch == ensemblePtr->nsPtr->exportLookupEpoch) { /* * Table of subcommands is still valid; therefore there might be a * valid cache of discovered information which we can reuse. Do the * check here, and if we're still valid, we can jump straight to the * part where we do the invocation of the subcommand. */ if (objv[1+ensemblePtr->numParameters]->typePtr==&tclEnsembleCmdType){ EnsembleCmdRep *ensembleCmd = objv[1+ensemblePtr->numParameters] ->internalRep.twoPtrValue.ptr1; if (ensembleCmd->nsPtr == ensemblePtr->nsPtr && ensembleCmd->epoch == ensemblePtr->epoch && ensembleCmd->token == ensemblePtr->token) { prefixObj = ensembleCmd->realPrefixObj; Tcl_IncrRefCount(prefixObj); goto runResultingSubcommand; } } } else { BuildEnsembleConfig(ensemblePtr); ensemblePtr->epoch = ensemblePtr->nsPtr->exportLookupEpoch; } /* * Look in the hashtable for the subcommand name; this is the fastest way * of all if there is no cache in operation. */ hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable, TclGetString(objv[1 + ensemblePtr->numParameters])); if (hPtr != NULL) { char *fullName = Tcl_GetHashKey(&ensemblePtr->subcommandTable, hPtr); prefixObj = Tcl_GetHashValue(hPtr); /* * Cache for later in the subcommand object. */ MakeCachedEnsembleCommand(objv[1 + ensemblePtr->numParameters], ensemblePtr, fullName, prefixObj); } else if (!(ensemblePtr->flags & TCL_ENSEMBLE_PREFIX)) { /* * Could not map, no prefixing, go to unknown/error handling. */ goto unknownOrAmbiguousSubcommand; } else { /* * If we've not already confirmed the command with the hash as part of * building our export table, we need to scan the sorted array for * matches. */ const char *subcmdName; /* Name of the subcommand, or unique prefix of * it (will be an error for a non-unique * prefix). */ char *fullName = NULL; /* Full name of the subcommand. */ int stringLength, i; int tableLength = ensemblePtr->subcommandTable.numEntries; subcmdName = TclGetString(objv[1 + ensemblePtr->numParameters]); stringLength = objv[1 + ensemblePtr->numParameters]->length; for (i=0 ; isubcommandArrayPtr[i], (unsigned) stringLength); if (cmp == 0) { if (fullName != NULL) { /* * Since there's never the exact-match case to worry about * (hash search filters this), getting here indicates that * our subcommand is an ambiguous prefix of (at least) two * exported subcommands, which is an error case. */ goto unknownOrAmbiguousSubcommand; } fullName = ensemblePtr->subcommandArrayPtr[i]; } else if (cmp < 0) { /* * Because we are searching a sorted table, we can now stop * searching because we have gone past anything that could * possibly match. */ break; } } if (fullName == NULL) { /* * The subcommand is not a prefix of anything, so bail out! */ goto unknownOrAmbiguousSubcommand; } hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable, fullName); if (hPtr == NULL) { Tcl_Panic("full name %s not found in supposedly synchronized hash", fullName); } prefixObj = Tcl_GetHashValue(hPtr); /* * Cache for later in the subcommand object. */ MakeCachedEnsembleCommand(objv[1 + ensemblePtr->numParameters], ensemblePtr, fullName, prefixObj); } Tcl_IncrRefCount(prefixObj); runResultingSubcommand: /* * Do the real work of execution of the subcommand by building an array of * objects (note that this is potentially not the same length as the * number of arguments to this ensemble command), populating it and then * feeding it back through the main command-lookup engine. In theory, we * could look up the command in the namespace ourselves, as we already * have the namespace in which it is guaranteed to exist, * * ((Q: That's not true if the -map option is used, is it?)) * * but we don't do that (the cacheing of the command object used should * help with that.) */ { Tcl_Obj **prefixObjv; /* The list of objects to substitute in as the * target command prefix. */ Tcl_Obj *copyPtr; /* The actual list of words to dispatch to. * Will be freed by the dispatch engine. */ int prefixObjc, copyObjc; Interp *iPtr = (Interp *) interp; /* * Get the prefix that we're rewriting to. To do this we need to * ensure that the internal representation of the list does not change * so that we can safely keep the internal representations of the * elements in the list. * * TODO: Use conventional list operations to make this code sane! */ TclListObjGetElements(NULL, prefixObj, &prefixObjc, &prefixObjv); copyObjc = objc - 2 + prefixObjc; copyPtr = Tcl_NewListObj(copyObjc, NULL); if (copyObjc > 0) { register Tcl_Obj **copyObjv; /* Space used to construct the list of * arguments to pass to the command that * implements the ensemble subcommand. */ register List *listRepPtr = copyPtr->internalRep.twoPtrValue.ptr1; register int i; listRepPtr->elemCount = copyObjc; copyObjv = &listRepPtr->elements; memcpy(copyObjv, prefixObjv, sizeof(Tcl_Obj *) * prefixObjc); memcpy(copyObjv+prefixObjc, objv+1, sizeof(Tcl_Obj *) * ensemblePtr->numParameters); memcpy(copyObjv+prefixObjc+ensemblePtr->numParameters, objv+ensemblePtr->numParameters+2, sizeof(Tcl_Obj *) * (objc-ensemblePtr->numParameters-2)); for (i=0; i < copyObjc; i++) { Tcl_IncrRefCount(copyObjv[i]); } } TclDecrRefCount(prefixObj); /* * Record what arguments the script sent in so that things like * Tcl_WrongNumArgs can give the correct error message. Parameters * count both as inserted and removed arguments. */ if (iPtr->ensembleRewrite.sourceObjs == NULL) { iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = 2 + ensemblePtr->numParameters; iPtr->ensembleRewrite.numInsertedObjs = prefixObjc + ensemblePtr->numParameters; TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL); } else { register int ni = 2 + ensemblePtr->numParameters - iPtr->ensembleRewrite.numInsertedObjs; /* Position in objv of new front of insertion * relative to old one. */ if (ni > 0) { iPtr->ensembleRewrite.numRemovedObjs += ni; iPtr->ensembleRewrite.numInsertedObjs += prefixObjc-1; } else { iPtr->ensembleRewrite.numInsertedObjs += prefixObjc-2; } } /* * Hand off to the target command. */ TclSkipTailcall(interp); return TclNREvalObjEx(interp, copyPtr, TCL_EVAL_INVOKE, NULL,INT_MIN); } unknownOrAmbiguousSubcommand: /* * Have not been able to match the subcommand asked for with a real * subcommand that we export. See whether a handler has been registered * for dealing with this situation. Will only call (at most) once for any * particular ensemble invocation. */ if (ensemblePtr->unknownHandler != NULL && reparseCount++ < 1) { switch (EnsembleUnknownCallback(interp, ensemblePtr, objc, objv, &prefixObj)) { case TCL_OK: goto runResultingSubcommand; case TCL_ERROR: return TCL_ERROR; case TCL_CONTINUE: goto restartEnsembleParse; } } /* * We cannot determine what subcommand to hand off to, so generate a * (standard) failure message. Note the one odd case compared with * standard ensemble-like command, which is where a namespace has no * exported commands at all... */ Tcl_ResetResult(interp); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND", TclGetString(objv[1+ensemblePtr->numParameters]), NULL); if (ensemblePtr->subcommandTable.numEntries == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown subcommand \"%s\": namespace %s does not" " export any commands", TclGetString(objv[1+ensemblePtr->numParameters]), ensemblePtr->nsPtr->fullName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND", TclGetString(objv[1+ensemblePtr->numParameters]), NULL); return TCL_ERROR; } errorObj = Tcl_ObjPrintf("unknown%s subcommand \"%s\": must be ", (ensemblePtr->flags & TCL_ENSEMBLE_PREFIX ? " or ambiguous" : ""), TclGetString(objv[1+ensemblePtr->numParameters])); if (ensemblePtr->subcommandTable.numEntries == 1) { Tcl_AppendToObj(errorObj, ensemblePtr->subcommandArrayPtr[0], -1); } else { int i; for (i=0 ; isubcommandTable.numEntries-1 ; i++) { Tcl_AppendToObj(errorObj, ensemblePtr->subcommandArrayPtr[i], -1); Tcl_AppendToObj(errorObj, ", ", 2); } Tcl_AppendPrintfToObj(errorObj, "or %s", ensemblePtr->subcommandArrayPtr[i]); } Tcl_SetObjResult(interp, errorObj); return TCL_ERROR; } int TclClearRootEnsemble( ClientData data[], Tcl_Interp *interp, int result) { TclResetRewriteEnsemble(interp, 1); return result; } /* *---------------------------------------------------------------------- * * TclInitRewriteEnsemble -- * * Applies a rewrite of arguments so that an ensemble subcommand will * report error messages correctly for the overall command. * * Results: * Whether this is the first rewrite applied, a value which must be * passed to TclResetRewriteEnsemble when undoing this command's * behaviour. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclInitRewriteEnsemble( Tcl_Interp *interp, int numRemoved, int numInserted, Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL); if (isRootEnsemble) { iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = numRemoved; iPtr->ensembleRewrite.numInsertedObjs = numInserted; } else { int numIns = iPtr->ensembleRewrite.numInsertedObjs; if (numIns < numRemoved) { iPtr->ensembleRewrite.numRemovedObjs += numRemoved - numIns; iPtr->ensembleRewrite.numInsertedObjs += numInserted - 1; } else { iPtr->ensembleRewrite.numInsertedObjs += numInserted - numRemoved; } } return isRootEnsemble; } /* *---------------------------------------------------------------------- * * TclResetRewriteEnsemble -- * * Removes any rewrites applied to support proper reporting of error * messages used in ensembles. Should be paired with * TclInitRewriteEnsemble. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclResetRewriteEnsemble( Tcl_Interp *interp, int isRootEnsemble) { Interp *iPtr = (Interp *) interp; if (isRootEnsemble) { iPtr->ensembleRewrite.sourceObjs = NULL; iPtr->ensembleRewrite.numRemovedObjs = 0; iPtr->ensembleRewrite.numInsertedObjs = 0; } } /* * ---------------------------------------------------------------------- * * EnsmebleUnknownCallback -- * * Helper for the ensemble engine that handles the procesing of unknown * callbacks. See the user documentation of the ensemble unknown handler * for details; this function is only ever called when such a function is * defined, and is only ever called once per ensemble dispatch (i.e. if a * reparse still fails, this isn't called again). * * Results: * TCL_OK - *prefixObjPtr contains the command words to dispatch * to. * TCL_CONTINUE - Need to reparse (*prefixObjPtr is invalid). * TCL_ERROR - Something went wrong! Error message in interpreter. * * Side effects: * Calls the Tcl interpreter, so arbitrary. * * ---------------------------------------------------------------------- */ static inline int EnsembleUnknownCallback( Tcl_Interp *interp, EnsembleConfig *ensemblePtr, int objc, Tcl_Obj *const objv[], Tcl_Obj **prefixObjPtr) { int paramc, i, result, prefixObjc; Tcl_Obj **paramv, *unknownCmd, *ensObj; /* * Create the unknown command callback to determine what to do. */ unknownCmd = Tcl_DuplicateObj(ensemblePtr->unknownHandler); TclNewObj(ensObj); Tcl_GetCommandFullName(interp, ensemblePtr->token, ensObj); Tcl_ListObjAppendElement(NULL, unknownCmd, ensObj); for (i=1 ; iflags & ENSEMBLE_DEAD)) { if (!Tcl_InterpDeleted(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unknown subcommand handler deleted its ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNKNOWN_DELETED", NULL); } result = TCL_ERROR; } Tcl_Release(ensemblePtr); /* * If we succeeded, we should either have a list of words that form the * command to be executed, or an empty list. In the empty-list case, the * ensemble is believed to be updated so we should ask the ensemble engine * to reparse the original command. */ if (result == TCL_OK) { *prefixObjPtr = Tcl_GetObjResult(interp); Tcl_IncrRefCount(*prefixObjPtr); TclDecrRefCount(unknownCmd); Tcl_ResetResult(interp); /* * Namespace is still there. Check if the result is a valid list. If * it is, and it is non-empty, that list is what we are using as our * replacement. */ if (TclListObjLength(interp, *prefixObjPtr, &prefixObjc) != TCL_OK) { TclDecrRefCount(*prefixObjPtr); Tcl_AddErrorInfo(interp, "\n while parsing result of " "ensemble unknown subcommand handler"); return TCL_ERROR; } if (prefixObjc > 0) { return TCL_OK; } /* * Namespace alive & empty result => reparse. */ TclDecrRefCount(*prefixObjPtr); return TCL_CONTINUE; } /* * Oh no! An exceptional result. Convert to an error. */ if (!Tcl_InterpDeleted(interp)) { if (result != TCL_ERROR) { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewStringObj( "unknown subcommand handler returned bad code: ", -1)); switch (result) { case TCL_RETURN: Tcl_AppendToObj(Tcl_GetObjResult(interp), "return", -1); break; case TCL_BREAK: Tcl_AppendToObj(Tcl_GetObjResult(interp), "break", -1); break; case TCL_CONTINUE: Tcl_AppendToObj(Tcl_GetObjResult(interp), "continue", -1); break; default: Tcl_AppendPrintfToObj(Tcl_GetObjResult(interp), "%d", result); } Tcl_AddErrorInfo(interp, "\n result of " "ensemble unknown subcommand handler: "); Tcl_AppendObjToErrorInfo(interp, unknownCmd); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNKNOWN_RESULT", NULL); } else { Tcl_AddErrorInfo(interp, "\n (ensemble unknown subcommand handler)"); } } TclDecrRefCount(unknownCmd); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * MakeCachedEnsembleCommand -- * * Cache what we've computed so far; it's not nice to repeatedly copy * strings about. Note that to do this, we start by deleting any old * representation that there was (though if it was an out of date * ensemble rep, we can skip some of the deallocation process.) * * Results: * None * * Side effects: * Alters the internal representation of the first object parameter. * *---------------------------------------------------------------------- */ static void MakeCachedEnsembleCommand( Tcl_Obj *objPtr, EnsembleConfig *ensemblePtr, const char *subcommandName, Tcl_Obj *prefixObjPtr) { register EnsembleCmdRep *ensembleCmd; int length; if (objPtr->typePtr == &tclEnsembleCmdType) { ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1; Tcl_DecrRefCount(ensembleCmd->realPrefixObj); TclNsDecrRefCount(ensembleCmd->nsPtr); ckfree(ensembleCmd->fullSubcmdName); } else { /* * Kill the old internal rep, and replace it with a brand new one of * our own. */ TclFreeIntRep(objPtr); ensembleCmd = ckalloc(sizeof(EnsembleCmdRep)); objPtr->internalRep.twoPtrValue.ptr1 = ensembleCmd; objPtr->typePtr = &tclEnsembleCmdType; } /* * Populate the internal rep. */ ensembleCmd->nsPtr = ensemblePtr->nsPtr; ensembleCmd->epoch = ensemblePtr->epoch; ensembleCmd->token = ensemblePtr->token; ensemblePtr->nsPtr->refCount++; ensembleCmd->realPrefixObj = prefixObjPtr; length = strlen(subcommandName)+1; ensembleCmd->fullSubcmdName = ckalloc(length); memcpy(ensembleCmd->fullSubcmdName, subcommandName, (unsigned) length); Tcl_IncrRefCount(ensembleCmd->realPrefixObj); } /* *---------------------------------------------------------------------- * * DeleteEnsembleConfig -- * * Destroys the data structure used to represent an ensemble. This is * called when the ensemble's command is deleted (which happens * automatically if the ensemble's namespace is deleted.) Maintainers * should note that ensembles should be deleted by deleting their * commands. * * Results: * None. * * Side effects: * Memory is (eventually) deallocated. * *---------------------------------------------------------------------- */ static void DeleteEnsembleConfig( ClientData clientData) { EnsembleConfig *ensemblePtr = clientData; Namespace *nsPtr = ensemblePtr->nsPtr; Tcl_HashSearch search; Tcl_HashEntry *hEnt; /* * Unlink from the ensemble chain if it has not been marked as having been * done already. */ if (ensemblePtr->next != ensemblePtr) { EnsembleConfig *ensPtr = (EnsembleConfig *) nsPtr->ensembles; if (ensPtr == ensemblePtr) { nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr->next; } else { while (ensPtr != NULL) { if (ensPtr->next == ensemblePtr) { ensPtr->next = ensemblePtr->next; break; } ensPtr = ensPtr->next; } } } /* * Mark the namespace as dead so code that uses Tcl_Preserve() can tell * whether disaster happened anyway. */ ensemblePtr->flags |= ENSEMBLE_DEAD; /* * Kill the pointer-containing fields. */ if (ensemblePtr->subcommandTable.numEntries != 0) { ckfree(ensemblePtr->subcommandArrayPtr); } hEnt = Tcl_FirstHashEntry(&ensemblePtr->subcommandTable, &search); while (hEnt != NULL) { Tcl_Obj *prefixObj = Tcl_GetHashValue(hEnt); Tcl_DecrRefCount(prefixObj); hEnt = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&ensemblePtr->subcommandTable); if (ensemblePtr->subcmdList != NULL) { Tcl_DecrRefCount(ensemblePtr->subcmdList); } if (ensemblePtr->parameterList != NULL) { Tcl_DecrRefCount(ensemblePtr->parameterList); } if (ensemblePtr->subcommandDict != NULL) { Tcl_DecrRefCount(ensemblePtr->subcommandDict); } if (ensemblePtr->unknownHandler != NULL) { Tcl_DecrRefCount(ensemblePtr->unknownHandler); } /* * Arrange for the structure to be reclaimed. Note that this is complex * because we have to make sure that we can react sensibly when an * ensemble is deleted during the process of initialising the ensemble * (especially the unknown callback.) */ Tcl_EventuallyFree(ensemblePtr, TCL_DYNAMIC); } /* *---------------------------------------------------------------------- * * BuildEnsembleConfig -- * * Create the internal data structures that describe how an ensemble * looks, being a hash mapping from the full command name to the Tcl list * that describes the implementation prefix words, and a sorted array of * all the full command names to allow for reasonably efficient * unambiguous prefix handling. * * Results: * None. * * Side effects: * Reallocates and rebuilds the hash table and array stored at the * ensemblePtr argument. For large ensembles or large namespaces, this is * a potentially expensive operation. * *---------------------------------------------------------------------- */ static void BuildEnsembleConfig( EnsembleConfig *ensemblePtr) { Tcl_HashSearch search; /* Used for scanning the set of commands in * the namespace that backs up this * ensemble. */ int i, j, isNew; Tcl_HashTable *hash = &ensemblePtr->subcommandTable; Tcl_HashEntry *hPtr; if (hash->numEntries != 0) { /* * Remove pre-existing table. */ ckfree(ensemblePtr->subcommandArrayPtr); hPtr = Tcl_FirstHashEntry(hash, &search); while (hPtr != NULL) { Tcl_Obj *prefixObj = Tcl_GetHashValue(hPtr); Tcl_DecrRefCount(prefixObj); hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(hash); Tcl_InitHashTable(hash, TCL_STRING_KEYS); } /* * See if we've got an export list. If so, we will only export exactly * those commands, which may be either implemented by the prefix in the * subcommandDict or mapped directly onto the namespace's commands. */ if (ensemblePtr->subcmdList != NULL) { Tcl_Obj **subcmdv, *target, *cmdObj, *cmdPrefixObj; int subcmdc; TclListObjGetElements(NULL, ensemblePtr->subcmdList, &subcmdc, &subcmdv); for (i=0 ; isubcommandDict != NULL) { Tcl_DictObjGet(NULL, ensemblePtr->subcommandDict, subcmdv[i], &target); if (target != NULL) { Tcl_SetHashValue(hPtr, target); Tcl_IncrRefCount(target); continue; } } /* * Not there, so map onto the namespace. Note in this case that we * do not guarantee that the command is actually there; that is * the programmer's responsibility (or [::unknown] of course). */ cmdObj = NewNsObj((Tcl_Namespace *) ensemblePtr->nsPtr); if (ensemblePtr->nsPtr->parentPtr != NULL) { Tcl_AppendStringsToObj(cmdObj, "::", name, NULL); } else { Tcl_AppendStringsToObj(cmdObj, name, NULL); } cmdPrefixObj = Tcl_NewListObj(1, &cmdObj); Tcl_SetHashValue(hPtr, cmdPrefixObj); Tcl_IncrRefCount(cmdPrefixObj); } } else if (ensemblePtr->subcommandDict != NULL) { /* * No subcmd list, but we do have a mapping dictionary so we should * use the keys of that. Convert the dictionary's contents into the * form required for the ensemble's internal hashtable. */ Tcl_DictSearch dictSearch; Tcl_Obj *keyObj, *valueObj; int done; Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch, &keyObj, &valueObj, &done); while (!done) { const char *name = TclGetString(keyObj); hPtr = Tcl_CreateHashEntry(hash, name, &isNew); Tcl_SetHashValue(hPtr, valueObj); Tcl_IncrRefCount(valueObj); Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done); } } else { /* * Discover what commands are actually exported by the namespace. * What we have is an array of patterns and a hash table whose keys * are the command names exported by the namespace (the contents do * not matter here.) We must find out what commands are actually * exported by filtering each command in the namespace against each of * the patterns in the export list. Note that we use an intermediate * hash table to make memory management easier, and because that makes * exact matching far easier too. * * Suggestion for future enhancement: compute the unique prefixes and * place them in the hash too, which should make for even faster * matching. */ hPtr = Tcl_FirstHashEntry(&ensemblePtr->nsPtr->cmdTable, &search); for (; hPtr!= NULL ; hPtr=Tcl_NextHashEntry(&search)) { char *nsCmdName = /* Name of command in namespace. */ Tcl_GetHashKey(&ensemblePtr->nsPtr->cmdTable, hPtr); for (i=0 ; insPtr->numExportPatterns ; i++) { if (Tcl_StringMatch(nsCmdName, ensemblePtr->nsPtr->exportArrayPtr[i])) { hPtr = Tcl_CreateHashEntry(hash, nsCmdName, &isNew); /* * Remember, hash entries have a full reference to the * substituted part of the command (as a list) as their * content! */ if (isNew) { Tcl_Obj *cmdObj, *cmdPrefixObj; TclNewObj(cmdObj); Tcl_AppendStringsToObj(cmdObj, ensemblePtr->nsPtr->fullName, (ensemblePtr->nsPtr->parentPtr ? "::" : ""), nsCmdName, NULL); cmdPrefixObj = Tcl_NewListObj(1, &cmdObj); Tcl_SetHashValue(hPtr, cmdPrefixObj); Tcl_IncrRefCount(cmdPrefixObj); } break; } } } } if (hash->numEntries == 0) { ensemblePtr->subcommandArrayPtr = NULL; return; } /* * Create a sorted array of all subcommands in the ensemble; hash tables * are all very well for a quick look for an exact match, but they can't * determine things like whether a string is a prefix of another (not * without lots of preparation anyway) and they're no good for when we're * generating the error message either. * * We do this by filling an array with the names (we use the hash keys * directly to save a copy, since any time we change the array we change * the hash too, and vice versa) and running quicksort over the array. */ ensemblePtr->subcommandArrayPtr = ckalloc(sizeof(char *) * hash->numEntries); /* * Fill array from both ends as this makes us less likely to end up with * performance problems in qsort(), which is good. Note that doing this * makes this code much more opaque, but the naive alternatve: * * for (hPtr=Tcl_FirstHashEntry(hash,&search),i=0 ; * hPtr!=NULL ; hPtr=Tcl_NextHashEntry(&search),i++) { * ensemblePtr->subcommandArrayPtr[i] = Tcl_GetHashKey(hash, &hPtr); * } * * can produce long runs of precisely ordered table entries when the * commands in the namespace are declared in a sorted fashion (an ordering * some people like) and the hashing functions (or the command names * themselves) are fairly unfortunate. By filling from both ends, it * requires active malice (and probably a debugger) to get qsort() to have * awful runtime behaviour. */ i = 0; j = hash->numEntries; hPtr = Tcl_FirstHashEntry(hash, &search); while (hPtr != NULL) { ensemblePtr->subcommandArrayPtr[i++] = Tcl_GetHashKey(hash, hPtr); hPtr = Tcl_NextHashEntry(&search); if (hPtr == NULL) { break; } ensemblePtr->subcommandArrayPtr[--j] = Tcl_GetHashKey(hash, hPtr); hPtr = Tcl_NextHashEntry(&search); } if (hash->numEntries > 1) { qsort(ensemblePtr->subcommandArrayPtr, (unsigned) hash->numEntries, sizeof(char *), NsEnsembleStringOrder); } } /* *---------------------------------------------------------------------- * * NsEnsembleStringOrder -- * * Helper function to compare two pointers to two strings for use with * qsort(). * * Results: * -1 if the first string is smaller, 1 if the second string is smaller, * and 0 if they are equal. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int NsEnsembleStringOrder( const void *strPtr1, const void *strPtr2) { return strcmp(*(const char **)strPtr1, *(const char **)strPtr2); } /* *---------------------------------------------------------------------- * * FreeEnsembleCmdRep -- * * Destroys the internal representation of a Tcl_Obj that has been * holding information about a command in an ensemble. * * Results: * None. * * Side effects: * Memory is deallocated. If this held the last reference to a * namespace's main structure, that main structure will also be * destroyed. * *---------------------------------------------------------------------- */ static void FreeEnsembleCmdRep( Tcl_Obj *objPtr) { EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1; Tcl_DecrRefCount(ensembleCmd->realPrefixObj); ckfree(ensembleCmd->fullSubcmdName); TclNsDecrRefCount(ensembleCmd->nsPtr); ckfree(ensembleCmd); objPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * DupEnsembleCmdRep -- * * Makes one Tcl_Obj into a copy of another that is a subcommand of an * ensemble. * * Results: * None. * * Side effects: * Memory is allocated, and the namespace that the ensemble is built on * top of gains another reference. * *---------------------------------------------------------------------- */ static void DupEnsembleCmdRep( Tcl_Obj *objPtr, Tcl_Obj *copyPtr) { EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1; EnsembleCmdRep *ensembleCopy = ckalloc(sizeof(EnsembleCmdRep)); int length = strlen(ensembleCmd->fullSubcmdName); copyPtr->typePtr = &tclEnsembleCmdType; copyPtr->internalRep.twoPtrValue.ptr1 = ensembleCopy; ensembleCopy->nsPtr = ensembleCmd->nsPtr; ensembleCopy->epoch = ensembleCmd->epoch; ensembleCopy->token = ensembleCmd->token; ensembleCopy->nsPtr->refCount++; ensembleCopy->realPrefixObj = ensembleCmd->realPrefixObj; Tcl_IncrRefCount(ensembleCopy->realPrefixObj); ensembleCopy->fullSubcmdName = ckalloc(length + 1); memcpy(ensembleCopy->fullSubcmdName, ensembleCmd->fullSubcmdName, (unsigned) length+1); } /* *---------------------------------------------------------------------- * * StringOfEnsembleCmdRep -- * * Creates a string representation of a Tcl_Obj that holds a subcommand * of an ensemble. * * Results: * None. * * Side effects: * The object gains a string (UTF-8) representation. * *---------------------------------------------------------------------- */ static void StringOfEnsembleCmdRep( Tcl_Obj *objPtr) { EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1; int length = strlen(ensembleCmd->fullSubcmdName); objPtr->length = length; objPtr->bytes = ckalloc(length + 1); memcpy(objPtr->bytes, ensembleCmd->fullSubcmdName, (unsigned) length+1); } /* *---------------------------------------------------------------------- * * TclCompileEnsemble -- * * Procedure called to compile an ensemble command. Note that most * ensembles are not compiled, since modifying a compiled ensemble causes * a invalidation of all existing bytecode (expensive!) which is not * normally warranted. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the subcommands of the * ensemble at runtime if a compile-time mapping is possible. * *---------------------------------------------------------------------- */ int TclCompileEnsemble( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); Tcl_Obj *mapObj, *subcmdObj, *targetCmdObj, *listObj, **elems; Tcl_Obj *replaced = Tcl_NewObj(), *replacement; Tcl_Command ensemble = (Tcl_Command) cmdPtr; Command *oldCmdPtr = cmdPtr, *newCmdPtr; int len, result, flags = 0, i, depth = 1, invokeAnyway = 0; int ourResult = TCL_ERROR; unsigned numBytes; const char *word; DefineLineInformation; Tcl_IncrRefCount(replaced); if (parsePtr->numWords < depth + 1) { goto failed; } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { /* * Too hard. */ goto failed; } /* * This is where we return to if we are parsing multiple nested compiled * ensembles. [info object] is such a beast. */ checkNextWord: word = tokenPtr[1].start; numBytes = tokenPtr[1].size; /* * There's a sporting chance we'll be able to compile this. But now we * must check properly. To do that, check that we're compiling an ensemble * that has a compilable command as its appropriate subcommand. */ if (Tcl_GetEnsembleMappingDict(NULL, ensemble, &mapObj) != TCL_OK || mapObj == NULL) { /* * Either not an ensemble or a mapping isn't installed. Crud. Too hard * to proceed. */ goto failed; } /* * Also refuse to compile anything that uses a formal parameter list for * now, on the grounds that it is too complex. */ if (Tcl_GetEnsembleParameterList(NULL, ensemble, &listObj) != TCL_OK || listObj != NULL) { /* * Figuring out how to compile this has become too much. Bail out. */ goto failed; } /* * Next, get the flags. We need them on several code paths so that we can * know whether we're to do prefix matching. */ (void) Tcl_GetEnsembleFlags(NULL, ensemble, &flags); /* * Check to see if there's also a subcommand list; must check to see if * the subcommand we are calling is in that list if it exists, since that * list filters the entries in the map. */ (void) Tcl_GetEnsembleSubcommandList(NULL, ensemble, &listObj); if (listObj != NULL) { int sclen; const char *str; Tcl_Obj *matchObj = NULL; if (Tcl_ListObjGetElements(NULL, listObj, &len, &elems) != TCL_OK) { goto failed; } for (i=0 ; insPtr->flags & NS_SUPPRESS_COMPILATION || newCmdPtr->flags & CMD_HAS_EXEC_TRACES || ((Interp *)interp)->flags & DONT_COMPILE_CMDS_INLINE) { /* * Maps to an undefined command or a command without a compiler. * Cannot compile. */ goto cleanup; } cmdPtr = newCmdPtr; depth++; /* * See whether we have a nested ensemble. If we do, we can go round the * mulberry bush again, consuming the next word. */ if (cmdPtr->compileProc == TclCompileEnsemble) { tokenPtr = TokenAfter(tokenPtr); if (parsePtr->numWords < depth + 1 || tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { /* * Too hard because the user has done something unpleasant like * omitting the sub-ensemble's command name or used a non-constant * name for a sub-ensemble's command name; we respond by bailing * out completely (this is a rare case). [Bug 6d2f249a01] */ goto cleanup; } ensemble = (Tcl_Command) cmdPtr; goto checkNextWord; } /* * Now we've done the mapping process, can now actually try to compile. * If there is a subcommand compiler and that successfully produces code, * we'll use that. Otherwise, we fall back to generating opcodes to do the * invoke at runtime. */ invokeAnyway = 1; if (TCL_OK == TclAttemptCompileProc(interp, parsePtr, depth, cmdPtr, envPtr)) { ourResult = TCL_OK; goto cleanup; } /* * Throw out any line information generated by the failed compile attempt. */ while (mapPtr->nuloc - 1 > eclIndex) { mapPtr->nuloc--; ckfree(mapPtr->loc[mapPtr->nuloc].line); mapPtr->loc[mapPtr->nuloc].line = NULL; } /* * Reset the index of next command. Toss out any from failed nested * partial compiles. */ envPtr->numCommands = mapPtr->nuloc; /* * Failed to do a full compile for some reason. Try to do a direct invoke * instead of going through the ensemble lookup process again. */ failed: if (depth < 250) { if (depth > 1) { if (!invokeAnyway) { cmdPtr = oldCmdPtr; depth--; } } /* * The length of the "replaced" list must be depth-1. Trim back * any extra elements that might have been appended by failing * pathways above. */ (void) Tcl_ListObjReplace(NULL, replaced, depth-1, INT_MAX, 0, NULL); /* * TODO: Reconsider whether we ought to call CompileToInvokedCommand() * when depth==1. In that case we are choosing to emit the * INST_INVOKE_REPLACE bytecode when there is in fact no replacing * to be done. It would be equally functional and presumably more * performant to fall through to cleanup below, return TCL_ERROR, * and let the compiler harness emit the INST_INVOKE_STK * implementation for us. */ CompileToInvokedCommand(interp, parsePtr, replaced, cmdPtr, envPtr); ourResult = TCL_OK; } /* * Release the memory we allocated. If we've got here, we've either done * something useful or we're in a case that we can't compile at all and * we're just giving up. */ cleanup: Tcl_DecrRefCount(replaced); return ourResult; } int TclAttemptCompileProc( Tcl_Interp *interp, Tcl_Parse *parsePtr, int depth, Command *cmdPtr, CompileEnv *envPtr) /* Holds resulting instructions. */ { int result, i; Tcl_Token *saveTokenPtr = parsePtr->tokenPtr; int savedStackDepth = envPtr->currStackDepth; unsigned savedCodeNext = envPtr->codeNext - envPtr->codeStart; DefineLineInformation; if (cmdPtr->compileProc == NULL) { return TCL_ERROR; } /* * Advance parsePtr->tokenPtr so that it points at the last subcommand. * This will be wrong, but it will not matter, and it will put the * tokens for the arguments in the right place without the needed to * allocate a synthetic Tcl_Parse struct, or copy tokens around. */ for (i = 0; i < depth - 1; i++) { parsePtr->tokenPtr = TokenAfter(parsePtr->tokenPtr); } parsePtr->numWords -= (depth - 1); /* * Shift the line information arrays to account for different word * index values. */ mapPtr->loc[eclIndex].line += (depth - 1); mapPtr->loc[eclIndex].next += (depth - 1); /* * Hand off compilation to the subcommand compiler. At last! */ result = cmdPtr->compileProc(interp, parsePtr, cmdPtr, envPtr); /* * Undo the shift. */ mapPtr->loc[eclIndex].line -= (depth - 1); mapPtr->loc[eclIndex].next -= (depth - 1); parsePtr->numWords += (depth - 1); parsePtr->tokenPtr = saveTokenPtr; /* * If our target failed to compile, revert any data from failed partial * compiles. Note that envPtr->numCommands need not be checked because * we avoid compiling subcommands that recursively call TclCompileScript(). */ if (result != TCL_OK) { envPtr->currStackDepth = savedStackDepth; envPtr->codeNext = envPtr->codeStart + savedCodeNext; #ifdef TCL_COMPILE_DEBUG } else { /* * Confirm that the command compiler generated a single value on * the stack as its result. This is only done in debugging mode, * as it *should* be correct and normal users have no reasonable * way to fix it anyway. */ int diff = envPtr->currStackDepth - savedStackDepth; if (diff != 1) { Tcl_Panic("bad stack adjustment when compiling" " %.*s (was %d instead of 1)", parsePtr->tokenPtr->size, parsePtr->tokenPtr->start, diff); } #endif } return result; } /* * How to compile a subcommand to a _replacing_ invoke of its implementation * command. */ static void CompileToInvokedCommand( Tcl_Interp *interp, Tcl_Parse *parsePtr, Tcl_Obj *replacements, Command *cmdPtr, CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokPtr; Tcl_Obj *objPtr, **words; char *bytes; int length, i, numWords, cmdLit; DefineLineInformation; /* * Push the words of the command. Take care; the command words may be * scripts that have backslashes in them, and [info frame 0] can see the * difference. Hence the call to TclContinuationsEnterDerived... */ Tcl_ListObjGetElements(NULL, replacements, &numWords, &words); for (i = 0, tokPtr = parsePtr->tokenPtr; i < parsePtr->numWords; i++, tokPtr = TokenAfter(tokPtr)) { if (i > 0 && i < numWords+1) { bytes = Tcl_GetStringFromObj(words[i-1], &length); PushLiteral(envPtr, bytes, length); continue; } SetLineInformation(i); if (tokPtr->type == TCL_TOKEN_SIMPLE_WORD) { int literal = TclRegisterNewLiteral(envPtr, tokPtr[1].start, tokPtr[1].size); if (envPtr->clNext) { TclContinuationsEnterDerived( TclFetchLiteral(envPtr, literal), tokPtr[1].start - envPtr->source, envPtr->clNext); } TclEmitPush(literal, envPtr); } else { CompileTokens(envPtr, tokPtr, interp); } } /* * Push the name of the command we're actually dispatching to as part of * the implementation. */ objPtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr); bytes = Tcl_GetStringFromObj(objPtr, &length); cmdLit = TclRegisterNewCmdLiteral(envPtr, bytes, length); TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLit), cmdPtr); TclEmitPush(cmdLit, envPtr); TclDecrRefCount(objPtr); /* * Do the replacing dispatch. */ TclEmitInvoke(envPtr, INST_INVOKE_REPLACE, parsePtr->numWords,numWords+1); } /* * Helpers that do issuing of instructions for commands that "don't have * compilers" (well, they do; these). They all work by just generating base * code to invoke the command; they're intended for ensemble subcommands so * that the costs of INST_INVOKE_REPLACE can be avoided where we can work out * that they're not needed. * * Note that these are NOT suitable for commands where there's an argument * that is a script, as an [info level] or [info frame] in the inner context * can see the difference. */ static int CompileBasicNArgCommand( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Obj *objPtr = Tcl_NewObj(); Tcl_IncrRefCount(objPtr); Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr); TclCompileInvocation(interp, parsePtr->tokenPtr, objPtr, parsePtr->numWords, envPtr); Tcl_DecrRefCount(objPtr); return TCL_OK; } int TclCompileBasic0ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 1) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic1ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 2) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 3) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic3ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 4) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic0Or1ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 1 && parsePtr->numWords != 2) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic1Or2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 2 && parsePtr->numWords != 3) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic2Or3ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 3 && parsePtr->numWords != 4) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic0To2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords < 1 || parsePtr->numWords > 3) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic1To3ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords < 2 || parsePtr->numWords > 4) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasicMin0ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords < 1) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasicMin1ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords < 2) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasicMin2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords < 3) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclLoad.c0000644000175000017500000010062212663660065014732 0ustar sergeisergei/* * tclLoad.c -- * * This file provides the generic portion (those that are the same on all * platforms) of Tcl's dynamic loading facilities. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * The following structure describes a package 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 * 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 * is loaded statically. Malloc-ed. */ char *packageName; /* Name of package prefix for the package, * properly capitalized (first letter UC, * others LC), no "_", 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; /* Initialization function to call to * incorporate this package into a trusted * interpreter. */ Tcl_PackageInitProc *safeInitProc; /* Initialization function to call to * incorporate this package into a safe * interpreter (one that will execute * untrusted scripts). NULL means the package * can't be used in unsafe interpreters. */ Tcl_PackageUnloadProc *unloadProc; /* Finalisation function to unload a package * from a trusted interpreter. NULL means that * the package cannot be unloaded. */ Tcl_PackageUnloadProc *safeUnloadProc; /* Finalisation function to unload a package * from a safe interpreter. NULL means that * the package cannot be unloaded. */ int interpRefCount; /* How many times the package has been loaded * in trusted interpreters. */ int safeInterpRefCount; /* How many times the package has been loaded * in safe interpreters. */ struct LoadedPackage *nextPtr; /* Next in list of all packages loaded into * this application process. NULL means end of * list. */ } LoadedPackage; /* * TCL_THREADS * There is a global list of packages that is anchored at firstPackagePtr. * Access to this list is governed by a mutex. */ static LoadedPackage *firstPackagePtr = NULL; /* First in list of all packages loaded into * this process. */ TCL_DECLARE_MUTEX(packageMutex) /* * The following structure represents a particular package 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). */ typedef struct InterpPackage { LoadedPackage *pkgPtr; /* Points to detailed information about * package. */ struct InterpPackage *nextPtr; /* Next package in this interpreter, or NULL * for end of list. */ } InterpPackage; /* * Prototypes for functions that are private to this file: */ static void LoadCleanupProc(ClientData clientData, Tcl_Interp *interp); /* *---------------------------------------------------------------------- * * Tcl_LoadObjCmd -- * * This function is invoked to process the "load" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_LoadObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Interp *target; LoadedPackage *pkgPtr, *defaultPtr; Tcl_DString pkgName, tmp, initName, safeInitName; Tcl_DString unloadName, safeUnloadName; InterpPackage *ipFirstPtr, *ipPtr; int code, namesMatch, filesMatch, offset; const char *symbols[2]; Tcl_PackageInitProc *initProc; const char *p, *fullFileName, *packageName; Tcl_LoadHandle loadHandle; Tcl_UniChar ch; unsigned len; int index, flags = 0; Tcl_Obj *const *savedobjv = objv; static const char *const options[] = { "-global", "-lazy", "--", NULL }; enum options { LOAD_GLOBAL, LOAD_LAZY, LOAD_LAST }; while (objc > 2) { if (TclGetString(objv[1])[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } ++objv; --objc; if (LOAD_GLOBAL == (enum options) index) { flags |= TCL_LOAD_GLOBAL; } else if (LOAD_LAZY == (enum options) index) { flags |= TCL_LOAD_LAZY; } else { break; } } if ((objc < 2) || (objc > 4)) { Tcl_WrongNumArgs(interp, 1, savedobjv, "?-global? ?-lazy? ?--? fileName ?packageName? ?interp?"); return TCL_ERROR; } if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) { return TCL_ERROR; } fullFileName = Tcl_GetString(objv[1]); Tcl_DStringInit(&pkgName); Tcl_DStringInit(&initName); Tcl_DStringInit(&safeInitName); Tcl_DStringInit(&unloadName); Tcl_DStringInit(&safeUnloadName); Tcl_DStringInit(&tmp); packageName = NULL; if (objc >= 3) { packageName = Tcl_GetString(objv[2]); if (packageName[0] == '\0') { packageName = NULL; } } if ((fullFileName[0] == 0) && (packageName == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must specify either file name or package name", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOLIBRARY", NULL); code = TCL_ERROR; goto done; } /* * Figure out which interpreter we're going to load the package into. */ target = interp; if (objc == 4) { const char *slaveIntName = Tcl_GetString(objv[3]); target = Tcl_GetSlave(interp, slaveIntName); if (target == NULL) { code = TCL_ERROR; goto done; } } /* * 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 * 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. */ Tcl_MutexLock(&packageMutex); defaultPtr = NULL; for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) { if (packageName == NULL) { namesMatch = 0; } else { TclDStringClear(&pkgName); Tcl_DStringAppend(&pkgName, packageName, -1); TclDStringClear(&tmp); Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1); Tcl_UtfToLower(Tcl_DStringValue(&pkgName)); Tcl_UtfToLower(Tcl_DStringValue(&tmp)); if (strcmp(Tcl_DStringValue(&tmp), Tcl_DStringValue(&pkgName)) == 0) { namesMatch = 1; } else { namesMatch = 0; } } TclDStringClear(&pkgName); filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0); if (filesMatch && (namesMatch || (packageName == NULL))) { break; } if (namesMatch && (fullFileName[0] == 0)) { defaultPtr = pkgPtr; } if (filesMatch && !namesMatch && (fullFileName[0] != 0)) { /* * Can't have two different packages loaded from the same file. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "file \"%s\" is already loaded for package \"%s\"", fullFileName, pkgPtr->packageName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "SPLITPERSONALITY", NULL); code = TCL_ERROR; Tcl_MutexUnlock(&packageMutex); goto done; } } Tcl_MutexUnlock(&packageMutex); if (pkgPtr == NULL) { pkgPtr = defaultPtr; } /* * Scan through the list of packages already loaded in the target * interpreter. If the package we want is already loaded there, then * there's nothing for us to do. */ if (pkgPtr != NULL) { ipFirstPtr = Tcl_GetAssocData(target, "tclLoad", NULL); for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { if (ipPtr->pkgPtr == pkgPtr) { code = TCL_OK; goto done; } } } if (pkgPtr == NULL) { /* * The desired file isn't currently loaded, so load it. It's an error * if the desired package is a static one. */ if (fullFileName[0] == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "package \"%s\" isn't loaded statically", packageName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOTSTATIC", NULL); code = TCL_ERROR; goto done; } /* * Figure out the module name if it wasn't provided explicitly. */ if (packageName != NULL) { Tcl_DStringAppend(&pkgName, packageName, -1); } else { int retc; /* * Threading note - this call used to be protected by a mutex. */ retc = TclGuessPackageName(fullFileName, &pkgName); if (!retc) { Tcl_Obj *splitPtr, *pkgGuessPtr; int pElements; const char *pkgGuess; /* * 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. */ splitPtr = Tcl_FSSplitPath(objv[1], &pElements); Tcl_ListObjIndex(NULL, splitPtr, pElements -1, &pkgGuessPtr); pkgGuess = Tcl_GetString(pkgGuessPtr); if ((pkgGuess[0] == 'l') && (pkgGuess[1] == 'i') && (pkgGuess[2] == 'b')) { pkgGuess += 3; } #ifdef __CYGWIN__ if ((pkgGuess[0] == 'c') && (pkgGuess[1] == 'y') && (pkgGuess[2] == 'g')) { pkgGuess += 3; } #endif /* __CYGWIN__ */ for (p = pkgGuess; *p != 0; p += offset) { offset = Tcl_UtfToUniChar(p, &ch); if ((ch > 0x100) || !(isalpha(UCHAR(ch)) /* INTL: ISO only */ || (UCHAR(ch) == '_'))) { break; } } if (p == pkgGuess) { Tcl_DecrRefCount(splitPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't figure out package name for %s", fullFileName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "WHATPACKAGE", NULL); code = TCL_ERROR; goto done; } Tcl_DStringAppend(&pkgName, pkgGuess, p - pkgGuess); Tcl_DecrRefCount(splitPtr); } } /* * Fix the capitalization in the package name 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))); /* * Compute the names of the two initialization functions, based on the * package name. */ TclDStringAppendDString(&initName, &pkgName); TclDStringAppendLiteral(&initName, "_Init"); TclDStringAppendDString(&safeInitName, &pkgName); TclDStringAppendLiteral(&safeInitName, "_SafeInit"); TclDStringAppendDString(&unloadName, &pkgName); TclDStringAppendLiteral(&unloadName, "_Unload"); TclDStringAppendDString(&safeUnloadName, &pkgName); TclDStringAppendLiteral(&safeUnloadName, "_SafeUnload"); /* * Call platform-specific code to load the package and find the two * initialization functions. */ symbols[0] = Tcl_DStringValue(&initName); symbols[1] = NULL; Tcl_MutexLock(&packageMutex); code = Tcl_LoadFile(interp, objv[1], symbols, flags, &initProc, &loadHandle); Tcl_MutexUnlock(&packageMutex); if (code != TCL_OK) { goto done; } /* * Create a new record to describe this package. */ pkgPtr = ckalloc(sizeof(LoadedPackage)); len = strlen(fullFileName) + 1; pkgPtr->fileName = ckalloc(len); memcpy(pkgPtr->fileName, fullFileName, len); len = (unsigned) Tcl_DStringLength(&pkgName) + 1; pkgPtr->packageName = ckalloc(len); memcpy(pkgPtr->packageName, Tcl_DStringValue(&pkgName), len); pkgPtr->loadHandle = loadHandle; pkgPtr->initProc = initProc; pkgPtr->safeInitProc = (Tcl_PackageInitProc *) Tcl_FindSymbol(interp, loadHandle, Tcl_DStringValue(&safeInitName)); pkgPtr->unloadProc = (Tcl_PackageUnloadProc *) Tcl_FindSymbol(interp, loadHandle, Tcl_DStringValue(&unloadName)); pkgPtr->safeUnloadProc = (Tcl_PackageUnloadProc *) Tcl_FindSymbol(interp, loadHandle, Tcl_DStringValue(&safeUnloadName)); pkgPtr->interpRefCount = 0; pkgPtr->safeInterpRefCount = 0; Tcl_MutexLock(&packageMutex); pkgPtr->nextPtr = firstPackagePtr; firstPackagePtr = pkgPtr; Tcl_MutexUnlock(&packageMutex); /* * The Tcl_FindSymbol calls may have left a spurious error message in * the interpreter result. */ Tcl_ResetResult(interp); } /* * Invoke the package'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) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't use package in a safe interpreter: no" " %s_SafeInit procedure", pkgPtr->packageName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "UNSAFE", NULL); code = TCL_ERROR; goto done; } code = pkgPtr->safeInitProc(target); } else { if (pkgPtr->initProc == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't attach package to interpreter: no %s_Init procedure", pkgPtr->packageName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "ENTRYPOINT", NULL); code = TCL_ERROR; goto done; } code = pkgPtr->initProc(target); } /* * Test for whether the initialization failed. If so, transfer the error * from the target interpreter to the originating one. */ if (code != TCL_OK) { Tcl_TransferResult(target, code, interp); goto done; } /* * Record the fact that the package has been loaded in the target * interpreter. * * Update the proper reference count. */ Tcl_MutexLock(&packageMutex); if (Tcl_IsSafe(target)) { pkgPtr->safeInterpRefCount++; } else { pkgPtr->interpRefCount++; } Tcl_MutexUnlock(&packageMutex); /* * Refetch ipFirstPtr: loading the package may have introduced additional * static packages at the head of the linked list! */ ipFirstPtr = Tcl_GetAssocData(target, "tclLoad", NULL); ipPtr = ckalloc(sizeof(InterpPackage)); ipPtr->pkgPtr = pkgPtr; ipPtr->nextPtr = ipFirstPtr; Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipPtr); done: Tcl_DStringFree(&pkgName); Tcl_DStringFree(&initName); Tcl_DStringFree(&safeInitName); Tcl_DStringFree(&unloadName); Tcl_DStringFree(&safeUnloadName); Tcl_DStringFree(&tmp); return code; } /* *---------------------------------------------------------------------- * * Tcl_UnloadObjCmd -- * * This function is invoked to process the "unload" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_UnloadObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ 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; int i, index, code, complain = 1, keepLibrary = 0; int trustedRefCount = -1, safeRefCount = -1; const char *fullFileName = ""; const char *packageName; static const char *const options[] = { "-nocomplain", "-keeplibrary", "--", NULL }; enum options { UNLOAD_NOCOMPLAIN, UNLOAD_KEEPLIB, UNLOAD_LAST }; for (i = 1; i < objc; i++) { if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index) != TCL_OK) { fullFileName = Tcl_GetString(objv[i]); if (fullFileName[0] == '-') { /* * It looks like the command contains an option so signal an * error */ return TCL_ERROR; } else { /* * This clearly isn't an option; assume it's the filename. We * must clear the error. */ Tcl_ResetResult(interp); break; } } switch (index) { case UNLOAD_NOCOMPLAIN: /* -nocomplain */ complain = 0; break; case UNLOAD_KEEPLIB: /* -keeplibrary */ keepLibrary = 1; break; case UNLOAD_LAST: /* -- */ i++; goto endOfForLoop; } } endOfForLoop: if ((objc-i < 1) || (objc-i > 3)) { Tcl_WrongNumArgs(interp, 1, objv, "?-switch ...? fileName ?packageName? ?interp?"); return TCL_ERROR; } if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) { return TCL_ERROR; } fullFileName = Tcl_GetString(objv[i]); Tcl_DStringInit(&pkgName); Tcl_DStringInit(&tmp); packageName = NULL; if (objc - i >= 2) { packageName = Tcl_GetString(objv[i+1]); if (packageName[0] == '\0') { packageName = NULL; } } if ((fullFileName[0] == 0) && (packageName == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must specify either file name or package name", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NOLIBRARY", NULL); code = TCL_ERROR; goto done; } /* * Figure out which interpreter we're going to load the package into. */ target = interp; if (objc - i == 3) { const char *slaveIntName = Tcl_GetString(objv[i + 2]); target = Tcl_GetSlave(interp, slaveIntName); if (target == NULL) { return TCL_ERROR; } } /* * 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 * 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. */ Tcl_MutexLock(&packageMutex); defaultPtr = NULL; for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) { int namesMatch, filesMatch; if (packageName == NULL) { namesMatch = 0; } else { TclDStringClear(&pkgName); Tcl_DStringAppend(&pkgName, packageName, -1); TclDStringClear(&tmp); Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1); Tcl_UtfToLower(Tcl_DStringValue(&pkgName)); Tcl_UtfToLower(Tcl_DStringValue(&tmp)); if (strcmp(Tcl_DStringValue(&tmp), Tcl_DStringValue(&pkgName)) == 0) { namesMatch = 1; } else { namesMatch = 0; } } TclDStringClear(&pkgName); filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0); if (filesMatch && (namesMatch || (packageName == NULL))) { break; } if (namesMatch && (fullFileName[0] == 0)) { defaultPtr = pkgPtr; } if (filesMatch && !namesMatch && (fullFileName[0] != 0)) { break; } } Tcl_MutexUnlock(&packageMutex); if (fullFileName[0] == 0) { /* * It's an error to try unload a static package. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "package \"%s\" is loaded statically and cannot be unloaded", packageName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "STATIC", NULL); code = TCL_ERROR; goto done; } if (pkgPtr == NULL) { /* * The DLL pointed by the provided filename has never been loaded. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "file \"%s\" has never been loaded", fullFileName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NEVERLOADED", NULL); code = TCL_ERROR; goto done; } /* * Scan through the list of packages already loaded in the target * interpreter. If the package we want is already loaded there, then we * should proceed with unloading. */ code = TCL_ERROR; if (pkgPtr != NULL) { ipFirstPtr = Tcl_GetAssocData(target, "tclLoad", NULL); for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { if (ipPtr->pkgPtr == pkgPtr) { code = TCL_OK; break; } } } if (code != TCL_OK) { /* * The package has not been loaded in this interpreter. */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "file \"%s\" has never been loaded in this interpreter", fullFileName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NEVERLOADED", NULL); code = TCL_ERROR; goto done; } /* * 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. */ if (Tcl_IsSafe(target)) { if (pkgPtr->safeUnloadProc == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "file \"%s\" cannot be unloaded under a safe interpreter", fullFileName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "CANNOT", NULL); code = TCL_ERROR; goto done; } unloadProc = pkgPtr->safeUnloadProc; } else { if (pkgPtr->unloadProc == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "file \"%s\" cannot be unloaded under a trusted interpreter", fullFileName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "CANNOT", NULL); code = TCL_ERROR; goto done; } unloadProc = pkgPtr->unloadProc; } /* * We are ready to unload the package. 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 * only remove itself from the interpreter; the library will be unloaded * in a future call of unload. In case the library will be unloaded just * after the callback returns, TCL_UNLOAD_DETACH_FROM_PROCESS is passed. */ code = TCL_UNLOAD_DETACH_FROM_INTERPRETER; if (!keepLibrary) { Tcl_MutexLock(&packageMutex); trustedRefCount = pkgPtr->interpRefCount; safeRefCount = pkgPtr->safeInterpRefCount; Tcl_MutexUnlock(&packageMutex); if (Tcl_IsSafe(target)) { safeRefCount--; } else { trustedRefCount--; } if (safeRefCount <= 0 && trustedRefCount <= 0) { code = TCL_UNLOAD_DETACH_FROM_PROCESS; } } code = unloadProc(target, code); if (code != TCL_OK) { Tcl_TransferResult(target, code, interp); goto done; } /* * The unload function executed fine. Examine the reference count to see * if we unload the DLL. */ Tcl_MutexLock(&packageMutex); if (Tcl_IsSafe(target)) { pkgPtr->safeInterpRefCount--; /* * Do not let counter get negative. */ if (pkgPtr->safeInterpRefCount < 0) { pkgPtr->safeInterpRefCount = 0; } } else { pkgPtr->interpRefCount--; /* * Do not let counter get negative. */ if (pkgPtr->interpRefCount < 0) { pkgPtr->interpRefCount = 0; } } trustedRefCount = pkgPtr->interpRefCount; safeRefCount = pkgPtr->safeInterpRefCount; Tcl_MutexUnlock(&packageMutex); code = TCL_OK; if (pkgPtr->safeInterpRefCount <= 0 && pkgPtr->interpRefCount <= 0 && !keepLibrary) { /* * Unload the shared library from the application memory... */ #if defined(TCL_UNLOAD_DLLS) || defined(_WIN32) /* * Some Unix dlls are poorly behaved - registering things like atexit * calls that can't be unregistered. If you unload such dlls, you get * a core on exit because it wants to call a function in the dll after * it's been unloaded. */ if (pkgPtr->fileName[0] != '\0') { Tcl_MutexLock(&packageMutex); if (Tcl_FSUnloadFile(interp, pkgPtr->loadHandle) == TCL_OK) { /* * Remove this library from the loaded library cache. */ defaultPtr = pkgPtr; if (defaultPtr == firstPackagePtr) { firstPackagePtr = pkgPtr->nextPtr; } else { for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) { if (pkgPtr->nextPtr == defaultPtr) { pkgPtr->nextPtr = defaultPtr->nextPtr; break; } } } /* * Remove this library from the interpreter's library cache. */ ipFirstPtr = Tcl_GetAssocData(target, "tclLoad", NULL); ipPtr = ipFirstPtr; if (ipPtr->pkgPtr == defaultPtr) { ipFirstPtr = ipFirstPtr->nextPtr; } else { InterpPackage *ipPrevPtr; for (ipPrevPtr = ipPtr; ipPtr != NULL; ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) { if (ipPtr->pkgPtr == pkgPtr) { ipPrevPtr->nextPtr = ipPtr->nextPtr; break; } } } Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr); ckfree(defaultPtr->fileName); ckfree(defaultPtr->packageName); ckfree(defaultPtr); ckfree(ipPtr); Tcl_MutexUnlock(&packageMutex); } else { code = TCL_ERROR; } } #else Tcl_SetObjResult(interp, Tcl_ObjPrintf( "file \"%s\" cannot be unloaded: unloading disabled", fullFileName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "DISABLED", NULL); code = TCL_ERROR; #endif } done: Tcl_DStringFree(&pkgName); Tcl_DStringFree(&tmp); if (!complain && (code != TCL_OK)) { code = TCL_OK; Tcl_ResetResult(interp); } return code; } /* *---------------------------------------------------------------------- * * Tcl_StaticPackage -- * * This function is invoked to indicate that a particular package has * been linked statically with an application. * * Results: * None. * * Side effects: * Once this function completes, the package 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 * already been loaded into the given * interpreter by calling the appropriate init * proc. */ const char *pkgName, /* Name of package (must be properly * capitalized: first letter upper case, * others lower case). */ Tcl_PackageInitProc *initProc, /* Function to call to incorporate this * package into a trusted interpreter. */ Tcl_PackageInitProc *safeInitProc) /* Function to call to incorporate this * package into a safe interpreter (one that * will execute untrusted scripts). NULL means * the package can't be used in safe * interpreters. */ { LoadedPackage *pkgPtr; InterpPackage *ipPtr, *ipFirstPtr; /* * Check to see if someone else has already reported this package 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)) { break; } } Tcl_MutexUnlock(&packageMutex); /* * If the package is not yet recorded as being loaded statically, add it * to the list now. */ if (pkgPtr == NULL) { pkgPtr = ckalloc(sizeof(LoadedPackage)); pkgPtr->fileName = ckalloc(1); pkgPtr->fileName[0] = 0; pkgPtr->packageName = 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 (interp != NULL) { /* * If we're loading the package into an interpreter, determine whether * it's already loaded. */ ipFirstPtr = Tcl_GetAssocData(interp, "tclLoad", NULL); for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { if (ipPtr->pkgPtr == pkgPtr) { return; } } /* * Package isn't loade in the current interp yet. Mark it as now being * loaded. */ ipPtr = ckalloc(sizeof(InterpPackage)); ipPtr->pkgPtr = pkgPtr; ipPtr->nextPtr = ipFirstPtr; Tcl_SetAssocData(interp, "tclLoad", LoadCleanupProc, ipPtr); } } /* *---------------------------------------------------------------------- * * TclGetLoadedPackages -- * * This function returns information about all of the files that are * loaded (either in a particular intepreter, or for all interpreters). * * Results: * The return value is a standard Tcl completion code. If successful, a * 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. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclGetLoadedPackages( 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. */ { Tcl_Interp *target; LoadedPackage *pkgPtr; InterpPackage *ipPtr; Tcl_Obj *resultObj, *pkgDesc[2]; if (targetName == NULL) { /* * Return information about all of the available packages. */ resultObj = Tcl_NewObj(); 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_ListObjAppendElement(NULL, resultObj, Tcl_NewListObj(2, pkgDesc)); } Tcl_MutexUnlock(&packageMutex); Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* * Return information about only the packages that are loaded in a given * interpreter. */ target = Tcl_GetSlave(interp, targetName); if (target == NULL) { return TCL_ERROR; } ipPtr = Tcl_GetAssocData(target, "tclLoad", NULL); resultObj = Tcl_NewObj(); for (; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { pkgPtr = ipPtr->pkgPtr; pkgDesc[0] = Tcl_NewStringObj(pkgPtr->fileName, -1); pkgDesc[1] = Tcl_NewStringObj(pkgPtr->packageName, -1); Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewListObj(2, pkgDesc)); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* *---------------------------------------------------------------------- * * LoadCleanupProc -- * * This function is called to delete all of the InterpPackage structures * for an interpreter when the interpreter is deleted. It gets invoked * via the Tcl AssocData mechanism. * * Results: * None. * * Side effects: * Storage for all of the InterpPackage functions for interp get deleted. * *---------------------------------------------------------------------- */ static void LoadCleanupProc( ClientData clientData, /* Pointer to first InterpPackage structure * for interp. */ Tcl_Interp *interp) /* Interpreter that is being deleted. */ { InterpPackage *ipPtr, *nextPtr; ipPtr = clientData; while (ipPtr != NULL) { nextPtr = ipPtr->nextPtr; ckfree(ipPtr); ipPtr = nextPtr; } } /* *---------------------------------------------------------------------- * * TclFinalizeLoad -- * * This function is invoked just before the application exits. It frees * all of the LoadedPackage structures. * * Results: * None. * * Side effects: * Memory is freed. * *---------------------------------------------------------------------- */ void TclFinalizeLoad(void) { LoadedPackage *pkgPtr; /* * No synchronization here because there should just be one thread alive * at this point. Logically, packageMutex 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; #if defined(TCL_UNLOAD_DLLS) || defined(_WIN32) /* * Some Unix dlls are poorly behaved - registering things like atexit * calls that can't be unregistered. If you unload such dlls, you get * a core on exit because it wants to call a function in the dll after * it has been unloaded. */ if (pkgPtr->fileName[0] != '\0') { Tcl_FSUnloadFile(NULL, pkgPtr->loadHandle); } #endif ckfree(pkgPtr->fileName); ckfree(pkgPtr->packageName); ckfree(pkgPtr); } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclListObj.c0000644000175000017500000016430312664052331015417 0ustar sergeisergei/* * tclListObj.c -- * * This file contains functions that implement the Tcl list object type. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1998 by Scriptics Corporation. * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Prototypes for functions defined later in this file: */ static List * AttemptNewList(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static List * NewListIntRep(int objc, Tcl_Obj *const objv[], int p); static void DupListInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static void FreeListInternalRep(Tcl_Obj *listPtr); static int SetListFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void UpdateStringOfList(Tcl_Obj *listPtr); /* * The structure below defines the list Tcl object type by means of functions * that can be invoked by generic object code. * * The internal representation of a list object is a two-pointer * representation. The first pointer designates a List structure that contains * an array of pointers to the element objects, together with integers that * represent the current element count and the allocated size of the array. * The second pointer is normally NULL; during execution of functions in this * file that operate on nested sublists, it is occasionally used as working * storage to avoid an auxiliary stack. */ const Tcl_ObjType tclListType = { "list", /* name */ FreeListInternalRep, /* freeIntRepProc */ DupListInternalRep, /* dupIntRepProc */ UpdateStringOfList, /* updateStringProc */ SetListFromAny /* setFromAnyProc */ }; #ifndef TCL_MIN_ELEMENT_GROWTH #define TCL_MIN_ELEMENT_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Obj *) #endif /* *---------------------------------------------------------------------- * * NewListIntRep -- * * Creates a list internal rep with space for objc elements. objc * must be > 0. If objv!=NULL, initializes with the first objc values * in that array. If objv==NULL, initalize list internal rep to have * 0 elements, with space to add objc more. Flag value "p" indicates * how to behave on failure. * * Results: * A new List struct with refCount 0 is returned. If some failure * prevents this then if p=0, NULL is returned and otherwise the * routine panics. * * Side effects: * The ref counts of the elements in objv are incremented since the * resulting list now refers to them. * *---------------------------------------------------------------------- */ static List * NewListIntRep( int objc, Tcl_Obj *const objv[], int p) { List *listRepPtr; if (objc <= 0) { Tcl_Panic("NewListIntRep: expects postive element count"); } /* * First check to see if we'd overflow and try to allocate an object * larger than our memory allocator allows. Note that this is actually a * fairly small value when you're on a serious 64-bit machine, but that * requires API changes to fix. See [Bug 219196] for a discussion. */ if ((size_t)objc > LIST_MAX) { if (p) { Tcl_Panic("max length of a Tcl list (%d elements) exceeded", LIST_MAX); } return NULL; } listRepPtr = attemptckalloc(LIST_SIZE(objc)); if (listRepPtr == NULL) { if (p) { Tcl_Panic("list creation failed: unable to alloc %u bytes", LIST_SIZE(objc)); } return NULL; } listRepPtr->canonicalFlag = 0; listRepPtr->refCount = 0; listRepPtr->maxElemCount = objc; if (objv) { Tcl_Obj **elemPtrs; int i; listRepPtr->elemCount = objc; elemPtrs = &listRepPtr->elements; for (i = 0; i < objc; i++) { elemPtrs[i] = objv[i]; Tcl_IncrRefCount(elemPtrs[i]); } } else { listRepPtr->elemCount = 0; } return listRepPtr; } /* *---------------------------------------------------------------------- * * AttemptNewList -- * * Creates a list internal rep with space for objc elements. objc * must be > 0. If objv!=NULL, initializes with the first objc values * in that array. If objv==NULL, initalize list internal rep to have * 0 elements, with space to add objc more. * * Results: * A new List struct with refCount 0 is returned. If some failure * prevents this then NULL is returned, and an error message is left * in the interp result, unless interp is NULL. * * Side effects: * The ref counts of the elements in objv are incremented since the * resulting list now refers to them. * *---------------------------------------------------------------------- */ static List * AttemptNewList( Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { List *listRepPtr = NewListIntRep(objc, objv, 0); if (interp != NULL && listRepPtr == NULL) { if (objc > LIST_MAX) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "max length of a Tcl list (%d elements) exceeded", LIST_MAX)); } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "list creation failed: unable to alloc %u bytes", LIST_SIZE(objc))); } Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } return listRepPtr; } /* *---------------------------------------------------------------------- * * Tcl_NewListObj -- * * This function is normally called when not debugging: i.e., when * TCL_MEM_DEBUG is not defined. It creates a new list object from an * (objc,objv) array: that is, each of the objc elements of the array * referenced by objv is inserted as an element into a new Tcl object. * * When TCL_MEM_DEBUG is defined, this function just returns the result * of calling the debugging version Tcl_DbNewListObj. * * Results: * A new list object is returned that is initialized from the object * pointers in objv. If objc is less than or equal to zero, an empty * object is returned. The new object's string representation is left * NULL. The resulting new list object has ref count 0. * * Side effects: * The ref counts of the elements in objv are incremented since the * resulting list now refers to them. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG #undef Tcl_NewListObj Tcl_Obj * Tcl_NewListObj( int objc, /* Count of objects referenced by objv. */ Tcl_Obj *const objv[]) /* An array of pointers to Tcl objects. */ { return Tcl_DbNewListObj(objc, objv, "unknown", 0); } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_NewListObj( int objc, /* Count of objects referenced by objv. */ Tcl_Obj *const objv[]) /* An array of pointers to Tcl objects. */ { List *listRepPtr; Tcl_Obj *listPtr; TclNewObj(listPtr); if (objc <= 0) { return listPtr; } /* * Create the internal rep. */ listRepPtr = NewListIntRep(objc, objv, 1); /* * Now create the object. */ TclInvalidateStringRep(listPtr); ListSetIntRep(listPtr, listRepPtr); return listPtr; } #endif /* if TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_DbNewListObj -- * * This function is normally called when debugging: i.e., when * TCL_MEM_DEBUG is defined. It creates new list objects. It is the same * as the Tcl_NewListObj function above except that it calls * Tcl_DbCkalloc directly with the file name and line number from its * caller. This simplifies debugging since then the [memory active] * command will report the correct file name and line number when * reporting objects that haven't been freed. * * When TCL_MEM_DEBUG is not defined, this function just returns the * result of calling Tcl_NewListObj. * * Results: * A new list object is returned that is initialized from the object * pointers in objv. If objc is less than or equal to zero, an empty * object is returned. The new object's string representation is left * NULL. The new list object has ref count 0. * * Side effects: * The ref counts of the elements in objv are incremented since the * resulting list now refers to them. * *---------------------------------------------------------------------- */ #ifdef TCL_MEM_DEBUG Tcl_Obj * Tcl_DbNewListObj( int objc, /* Count of objects referenced by objv. */ Tcl_Obj *const objv[], /* An array of pointers to Tcl objects. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { Tcl_Obj *listPtr; List *listRepPtr; TclDbNewObj(listPtr, file, line); if (objc <= 0) { return listPtr; } /* * Create the internal rep. */ listRepPtr = NewListIntRep(objc, objv, 1); /* * Now create the object. */ TclInvalidateStringRep(listPtr); ListSetIntRep(listPtr, listRepPtr); return listPtr; } #else /* if not TCL_MEM_DEBUG */ Tcl_Obj * Tcl_DbNewListObj( int objc, /* Count of objects referenced by objv. */ Tcl_Obj *const objv[], /* An array of pointers to Tcl objects. */ const char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { return Tcl_NewListObj(objc, objv); } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_SetListObj -- * * Modify an object to be a list containing each of the objc elements of * the object array referenced by objv. * * Results: * None. * * Side effects: * The object is made a list object and is initialized from the object * pointers in objv. If objc is less than or equal to zero, an empty * object is returned. The new object's string representation is left * NULL. The ref counts of the elements in objv are incremented since the * list now refers to them. The object's old string and internal * representations are freed and its type is set NULL. * *---------------------------------------------------------------------- */ void Tcl_SetListObj( Tcl_Obj *objPtr, /* Object whose internal rep to init. */ int objc, /* Count of objects referenced by objv. */ Tcl_Obj *const objv[]) /* An array of pointers to Tcl objects. */ { List *listRepPtr; if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetListObj"); } /* * Free any old string rep and any internal rep for the old type. */ TclFreeIntRep(objPtr); TclInvalidateStringRep(objPtr); /* * Set the object's type to "list" and initialize the internal rep. * However, if there are no elements to put in the list, just give the * object an empty string rep and a NULL type. */ if (objc > 0) { listRepPtr = NewListIntRep(objc, objv, 1); ListSetIntRep(objPtr, listRepPtr); } else { objPtr->bytes = tclEmptyStringRep; objPtr->length = 0; } } /* *---------------------------------------------------------------------- * * TclListObjCopy -- * * Makes a "pure list" copy of a list value. This provides for the C * level a counterpart of the [lrange $list 0 end] command, while using * internals details to be as efficient as possible. * * Results: * Normally returns a pointer to a new Tcl_Obj, that contains the same * list value as *listPtr does. The returned Tcl_Obj has a refCount of * zero. If *listPtr does not hold a list, NULL is returned, and if * interp is non-NULL, an error message is recorded there. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * TclListObjCopy( Tcl_Interp *interp, /* Used to report errors if not NULL. */ Tcl_Obj *listPtr) /* List object for which an element array is * to be returned. */ { Tcl_Obj *copyPtr; if (listPtr->typePtr != &tclListType) { if (SetListFromAny(interp, listPtr) != TCL_OK) { return NULL; } } TclNewObj(copyPtr); TclInvalidateStringRep(copyPtr); DupListInternalRep(listPtr, copyPtr); return copyPtr; } /* *---------------------------------------------------------------------- * * Tcl_ListObjGetElements -- * * This function returns an (objc,objv) array of the elements in a list * object. * * Results: * The return value is normally TCL_OK; in this case *objcPtr is set to * the count of list elements and *objvPtr is set to a pointer to an * array of (*objcPtr) pointers to each list element. If listPtr does not * refer to a list object and the object can not be converted to one, * TCL_ERROR is returned and an error message will be left in the * interpreter's result if interp is not NULL. * * The objects referenced by the returned array should be treated as * readonly and their ref counts are _not_ incremented; the caller must * do that if it holds on to a reference. Furthermore, the pointer and * length returned by this function may change as soon as any function is * called on the list object; be careful about retaining the pointer in a * local data structure. * * Side effects: * The possible conversion of the object referenced by listPtr * to a list object. * *---------------------------------------------------------------------- */ int Tcl_ListObjGetElements( Tcl_Interp *interp, /* Used to report errors if not NULL. */ register Tcl_Obj *listPtr, /* List object for which an element array is * to be returned. */ int *objcPtr, /* Where to store the count of objects * referenced by objv. */ Tcl_Obj ***objvPtr) /* Where to store the pointer to an array of * pointers to the list's objects. */ { register List *listRepPtr; if (listPtr->typePtr != &tclListType) { int result; if (listPtr->bytes == tclEmptyStringRep) { *objcPtr = 0; *objvPtr = NULL; return TCL_OK; } result = SetListFromAny(interp, listPtr); if (result != TCL_OK) { return result; } } listRepPtr = ListRepPtr(listPtr); *objcPtr = listRepPtr->elemCount; *objvPtr = &listRepPtr->elements; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ListObjAppendList -- * * This function appends the elements in the list value referenced by * elemListPtr to the list value referenced by listPtr. * * Results: * The return value is normally TCL_OK. If listPtr or elemListPtr do not * refer to list values, TCL_ERROR is returned and an error message is * left in the interpreter's result if interp is not NULL. * * Side effects: * The reference counts of the elements in elemListPtr are incremented * since the list now refers to them. listPtr and elemListPtr are * converted, if necessary, to list objects. Also, appending the new * elements may cause listObj's array of element pointers to grow. * listPtr's old string representation, if any, is invalidated. * *---------------------------------------------------------------------- */ int Tcl_ListObjAppendList( Tcl_Interp *interp, /* Used to report errors if not NULL. */ register Tcl_Obj *listPtr, /* List object to append elements to. */ Tcl_Obj *elemListPtr) /* List obj with elements to append. */ { int objc; Tcl_Obj **objv; if (Tcl_IsShared(listPtr)) { Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendList"); } /* * Pull the elements to append from elemListPtr. */ if (TCL_OK != TclListObjGetElements(interp, elemListPtr, &objc, &objv)) { return TCL_ERROR; } /* * Insert the new elements starting after the lists's last element. * Delete zero existing elements. */ return Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0, objc, objv); } /* *---------------------------------------------------------------------- * * Tcl_ListObjAppendElement -- * * This function is a special purpose version of Tcl_ListObjAppendList: * it appends a single object referenced by objPtr to the list object * referenced by listPtr. If listPtr is not already a list object, an * attempt will be made to convert it to one. * * Results: * The return value is normally TCL_OK; in this case objPtr is added to * the end of listPtr's list. If listPtr does not refer to a list object * and the object can not be converted to one, TCL_ERROR is returned and * an error message will be left in the interpreter's result if interp is * not NULL. * * Side effects: * The ref count of objPtr is incremented since the list now refers to * it. listPtr will be converted, if necessary, to a list object. Also, * appending the new element may cause listObj's array of element * pointers to grow. listPtr's old string representation, if any, is * invalidated. * *---------------------------------------------------------------------- */ int Tcl_ListObjAppendElement( Tcl_Interp *interp, /* Used to report errors if not NULL. */ Tcl_Obj *listPtr, /* List object to append objPtr to. */ Tcl_Obj *objPtr) /* Object to append to listPtr's list. */ { register List *listRepPtr, *newPtr = NULL; int numElems, numRequired, needGrow, isShared, attempt; if (Tcl_IsShared(listPtr)) { Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendElement"); } if (listPtr->typePtr != &tclListType) { int result; if (listPtr->bytes == tclEmptyStringRep) { Tcl_SetListObj(listPtr, 1, &objPtr); return TCL_OK; } result = SetListFromAny(interp, listPtr); if (result != TCL_OK) { return result; } } listRepPtr = ListRepPtr(listPtr); numElems = listRepPtr->elemCount; numRequired = numElems + 1 ; needGrow = (numRequired > listRepPtr->maxElemCount); isShared = (listRepPtr->refCount > 1); if (numRequired > LIST_MAX) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "max length of a Tcl list (%d elements) exceeded", LIST_MAX)); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } return TCL_ERROR; } if (needGrow && !isShared) { /* * Need to grow + unshared intrep => try to realloc */ attempt = 2 * numRequired; if (attempt <= LIST_MAX) { newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); } if (newPtr == NULL) { attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH; if (attempt > LIST_MAX) { attempt = LIST_MAX; } newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); } if (newPtr == NULL) { attempt = numRequired; newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); } if (newPtr) { listRepPtr = newPtr; listRepPtr->maxElemCount = attempt; needGrow = 0; } } if (isShared || needGrow) { Tcl_Obj **dst, **src = &listRepPtr->elements; /* * Either we have a shared intrep and we must copy to write, or we * need to grow and realloc attempts failed. Attempt intrep copy. */ attempt = 2 * numRequired; newPtr = AttemptNewList(NULL, attempt, NULL); if (newPtr == NULL) { attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH; if (attempt > LIST_MAX) { attempt = LIST_MAX; } newPtr = AttemptNewList(NULL, attempt, NULL); } if (newPtr == NULL) { attempt = numRequired; newPtr = AttemptNewList(interp, attempt, NULL); } if (newPtr == NULL) { /* * All growth attempts failed; throw the error. */ return TCL_ERROR; } dst = &newPtr->elements; newPtr->refCount++; newPtr->canonicalFlag = listRepPtr->canonicalFlag; newPtr->elemCount = listRepPtr->elemCount; if (isShared) { /* * The original intrep must remain undisturbed. Copy into the new * one and bump refcounts */ while (numElems--) { *dst = *src++; Tcl_IncrRefCount(*dst++); } listRepPtr->refCount--; } else { /* * Old intrep to be freed, re-use refCounts. */ memcpy(dst, src, (size_t) numElems * sizeof(Tcl_Obj *)); ckfree(listRepPtr); } listRepPtr = newPtr; } listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; /* * Add objPtr to the end of listPtr's array of element pointers. Increment * the ref count for the (now shared) objPtr. */ *(&listRepPtr->elements + listRepPtr->elemCount) = objPtr; Tcl_IncrRefCount(objPtr); listRepPtr->elemCount++; /* * Invalidate any old string representation since the list's internal * representation has changed. */ TclInvalidateStringRep(listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ListObjIndex -- * * This function returns a pointer to the index'th object from the list * referenced by listPtr. The first element has index 0. If index is * negative or greater than or equal to the number of elements in the * list, a NULL is returned. If listPtr is not a list object, an attempt * will be made to convert it to a list. * * Results: * The return value is normally TCL_OK; in this case objPtrPtr is set to * the Tcl_Obj pointer for the index'th list element or NULL if index is * out of range. This object should be treated as readonly and its ref * count is _not_ incremented; the caller must do that if it holds on to * the reference. If listPtr does not refer to a list and can't be * converted to one, TCL_ERROR is returned and an error message is left * in the interpreter's result if interp is not NULL. * * Side effects: * listPtr will be converted, if necessary, to a list object. * *---------------------------------------------------------------------- */ int Tcl_ListObjIndex( Tcl_Interp *interp, /* Used to report errors if not NULL. */ register Tcl_Obj *listPtr, /* List object to index into. */ register int index, /* Index of element to return. */ Tcl_Obj **objPtrPtr) /* The resulting Tcl_Obj* is stored here. */ { register List *listRepPtr; if (listPtr->typePtr != &tclListType) { int result; if (listPtr->bytes == tclEmptyStringRep) { *objPtrPtr = NULL; return TCL_OK; } result = SetListFromAny(interp, listPtr); if (result != TCL_OK) { return result; } } listRepPtr = ListRepPtr(listPtr); if ((index < 0) || (index >= listRepPtr->elemCount)) { *objPtrPtr = NULL; } else { *objPtrPtr = (&listRepPtr->elements)[index]; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ListObjLength -- * * This function returns the number of elements in a list object. If the * object is not already a list object, an attempt will be made to * convert it to one. * * Results: * The return value is normally TCL_OK; in this case *intPtr will be set * to the integer count of list elements. If listPtr does not refer to a * list object and the object can not be converted to one, TCL_ERROR is * returned and an error message will be left in the interpreter's result * if interp is not NULL. * * Side effects: * The possible conversion of the argument object to a list object. * *---------------------------------------------------------------------- */ int Tcl_ListObjLength( Tcl_Interp *interp, /* Used to report errors if not NULL. */ register Tcl_Obj *listPtr, /* List object whose #elements to return. */ register int *intPtr) /* The resulting int is stored here. */ { register List *listRepPtr; if (listPtr->typePtr != &tclListType) { int result; if (listPtr->bytes == tclEmptyStringRep) { *intPtr = 0; return TCL_OK; } result = SetListFromAny(interp, listPtr); if (result != TCL_OK) { return result; } } listRepPtr = ListRepPtr(listPtr); *intPtr = listRepPtr->elemCount; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ListObjReplace -- * * This function replaces zero or more elements of the list referenced by * listPtr with the objects from an (objc,objv) array. The objc elements * of the array referenced by objv replace the count elements in listPtr * starting at first. * * If the argument first is zero or negative, it refers to the first * element. If first is greater than or equal to the number of elements * in the list, then no elements are deleted; the new elements are * appended to the list. Count gives the number of elements to replace. * If count is zero or negative then no elements are deleted; the new * elements are simply inserted before first. * * The argument objv refers to an array of objc pointers to the new * elements to be added to listPtr in place of those that were deleted. * If objv is NULL, no new elements are added. If listPtr is not a list * object, an attempt will be made to convert it to one. * * Results: * The return value is normally TCL_OK. If listPtr does not refer to a * list object and can not be converted to one, TCL_ERROR is returned and * an error message will be left in the interpreter's result if interp is * not NULL. * * Side effects: * The ref counts of the objc elements in objv are incremented since the * resulting list now refers to them. Similarly, the ref counts for * replaced objects are decremented. listPtr is converted, if necessary, * to a list object. listPtr's old string representation, if any, is * freed. * *---------------------------------------------------------------------- */ int Tcl_ListObjReplace( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *listPtr, /* List object whose elements to replace. */ int first, /* Index of first element to replace. */ int count, /* Number of elements to replace. */ int objc, /* Number of objects to insert. */ Tcl_Obj *const objv[]) /* An array of objc pointers to Tcl objects to * insert. */ { List *listRepPtr; register Tcl_Obj **elemPtrs; int needGrow, numElems, numRequired, numAfterLast, start, i, j, isShared; if (Tcl_IsShared(listPtr)) { Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace"); } if (listPtr->typePtr != &tclListType) { if (listPtr->bytes == tclEmptyStringRep) { if (!objc) { return TCL_OK; } Tcl_SetListObj(listPtr, objc, NULL); } else { int result = SetListFromAny(interp, listPtr); if (result != TCL_OK) { return result; } } } /* * Note that when count == 0 and objc == 0, this routine is logically a * no-op, removing and adding no elements to the list. However, by flowing * through this routine anyway, we get the important side effect that the * resulting listPtr is a list in canoncial form. This is important. * Resist any temptation to optimize this case. */ listRepPtr = ListRepPtr(listPtr); elemPtrs = &listRepPtr->elements; numElems = listRepPtr->elemCount; if (first < 0) { first = 0; } if (first >= numElems) { first = numElems; /* So we'll insert after last element. */ } if (count < 0) { count = 0; } else if (numElems < first+count || first+count < 0) { /* * The 'first+count < 0' condition here guards agains integer * overflow in determining 'first+count'. */ count = numElems - first; } if (objc > LIST_MAX - (numElems - count)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "max length of a Tcl list (%d elements) exceeded", LIST_MAX)); return TCL_ERROR; } isShared = (listRepPtr->refCount > 1); numRequired = numElems - count + objc; /* Known <= LIST_MAX */ needGrow = numRequired > listRepPtr->maxElemCount; for (i = 0; i < objc; i++) { Tcl_IncrRefCount(objv[i]); } if (needGrow && !isShared) { /* Try to use realloc */ List *newPtr = NULL; int attempt = 2 * numRequired; if (attempt <= LIST_MAX) { newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); } if (newPtr == NULL) { attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH; if (attempt > LIST_MAX) { attempt = LIST_MAX; } newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); } if (newPtr == NULL) { attempt = numRequired; newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); } if (newPtr) { listRepPtr = newPtr; listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; elemPtrs = &listRepPtr->elements; listRepPtr->maxElemCount = attempt; needGrow = numRequired > listRepPtr->maxElemCount; } } if (!needGrow && !isShared) { int shift; /* * Can use the current List struct. First "delete" count elements * starting at first. */ for (j = first; j < first + count; j++) { Tcl_Obj *victimPtr = elemPtrs[j]; TclDecrRefCount(victimPtr); } /* * Shift the elements after the last one removed to their new * locations. */ start = first + count; numAfterLast = numElems - start; shift = objc - count; /* numNewElems - numDeleted */ if ((numAfterLast > 0) && (shift != 0)) { Tcl_Obj **src = elemPtrs + start; memmove(src+shift, src, (size_t) numAfterLast * sizeof(Tcl_Obj*)); } } else { /* * Cannot use the current List struct; it is shared, too small, or * both. Allocate a new struct and insert elements into it. */ List *oldListRepPtr = listRepPtr; Tcl_Obj **oldPtrs = elemPtrs; int newMax; if (needGrow){ newMax = 2 * numRequired; } else { newMax = listRepPtr->maxElemCount; } listRepPtr = AttemptNewList(NULL, newMax, NULL); if (listRepPtr == NULL) { unsigned int limit = LIST_MAX - numRequired; unsigned int extra = numRequired - numElems + TCL_MIN_ELEMENT_GROWTH; int growth = (int) ((extra > limit) ? limit : extra); listRepPtr = AttemptNewList(NULL, numRequired + growth, NULL); if (listRepPtr == NULL) { listRepPtr = AttemptNewList(interp, numRequired, NULL); if (listRepPtr == NULL) { for (i = 0; i < objc; i++) { /* See bug 3598580 */ #if TCL_MAJOR_VERSION > 8 Tcl_DecrRefCount(objv[i]); #else objv[i]->refCount--; #endif } return TCL_ERROR; } } } listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; listRepPtr->refCount++; elemPtrs = &listRepPtr->elements; if (isShared) { /* * The old struct will remain in place; need new refCounts for the * new List struct references. Copy over only the surviving * elements. */ for (i=0; i < first; i++) { elemPtrs[i] = oldPtrs[i]; Tcl_IncrRefCount(elemPtrs[i]); } for (i = first + count, j = first + objc; j < numRequired; i++, j++) { elemPtrs[j] = oldPtrs[i]; Tcl_IncrRefCount(elemPtrs[j]); } oldListRepPtr->refCount--; } else { /* * The old struct will be removed; use its inherited refCounts. */ if (first > 0) { memcpy(elemPtrs, oldPtrs, (size_t) first * sizeof(Tcl_Obj *)); } /* * "Delete" count elements starting at first. */ for (j = first; j < first + count; j++) { Tcl_Obj *victimPtr = oldPtrs[j]; TclDecrRefCount(victimPtr); } /* * Copy the elements after the last one removed, shifted to their * new locations. */ start = first + count; numAfterLast = numElems - start; if (numAfterLast > 0) { memcpy(elemPtrs + first + objc, oldPtrs + start, (size_t) numAfterLast * sizeof(Tcl_Obj *)); } ckfree(oldListRepPtr); } } /* * Insert the new elements into elemPtrs before "first". */ for (i=0,j=first ; ielemCount = numRequired; /* * Invalidate and free any old string representation since it no longer * reflects the list's internal representation. */ TclInvalidateStringRep(listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclLindexList -- * * This procedure handles the 'lindex' command when objc==3. * * Results: * Returns a pointer to the object extracted, or NULL if an error * occurred. The returned object already includes one reference count for * the pointer returned. * * Side effects: * None. * * Notes: * This procedure is implemented entirely as a wrapper around * TclLindexFlat. All it does is reconfigure the argument format into the * form required by TclLindexFlat, while taking care to manage shimmering * in such a way that we tend to keep the most useful intreps and/or * avoid the most expensive conversions. * *---------------------------------------------------------------------- */ Tcl_Obj * TclLindexList( Tcl_Interp *interp, /* Tcl interpreter. */ Tcl_Obj *listPtr, /* List being unpacked. */ Tcl_Obj *argPtr) /* Index or index list. */ { int index; /* Index into the list. */ Tcl_Obj *indexListCopy; /* * Determine whether argPtr designates a list or a single index. We have * to be careful about the order of the checks to avoid repeated * shimmering; see TIP#22 and TIP#33 for the details. */ if (argPtr->typePtr != &tclListType && TclGetIntForIndexM(NULL , argPtr, 0, &index) == TCL_OK) { /* * argPtr designates a single index. */ return TclLindexFlat(interp, listPtr, 1, &argPtr); } /* * Here we make a private copy of the index list argument to avoid any * shimmering issues that might invalidate the indices array below while * we are still using it. This is probably unnecessary. It does not appear * that any damaging shimmering is possible, and no test has been devised * to show any error when this private copy is not made. But it's cheap, * and it offers some future-proofing insurance in case the TclLindexFlat * implementation changes in some unexpected way, or some new form of * trace or callback permits things to happen that the current * implementation does not. */ indexListCopy = TclListObjCopy(NULL, argPtr); if (indexListCopy == NULL) { /* * argPtr designates something that is neither an index nor a * well-formed list. Report the error via TclLindexFlat. */ return TclLindexFlat(interp, listPtr, 1, &argPtr); } if (indexListCopy->typePtr == &tclListType) { List *listRepPtr = ListRepPtr(indexListCopy); listPtr = TclLindexFlat(interp, listPtr, listRepPtr->elemCount, &listRepPtr->elements); } else { int indexCount = -1; /* Size of the array of list indices. */ Tcl_Obj **indices = NULL; /* Array of list indices. */ Tcl_ListObjGetElements(NULL, indexListCopy, &indexCount, &indices); listPtr = TclLindexFlat(interp, listPtr, indexCount, indices); } Tcl_DecrRefCount(indexListCopy); return listPtr; } /* *---------------------------------------------------------------------- * * TclLindexFlat -- * * This procedure is the core of the 'lindex' command, with all index * arguments presented as a flat list. * * Results: * Returns a pointer to the object extracted, or NULL if an error * occurred. The returned object already includes one reference count for * the pointer returned. * * Side effects: * None. * * Notes: * The reference count of the returned object includes one reference * corresponding to the pointer returned. Thus, the calling code will * usually do something like: * Tcl_SetObjResult(interp, result); * Tcl_DecrRefCount(result); * *---------------------------------------------------------------------- */ Tcl_Obj * TclLindexFlat( Tcl_Interp *interp, /* Tcl interpreter. */ Tcl_Obj *listPtr, /* Tcl object representing the list. */ int indexCount, /* Count of indices. */ Tcl_Obj *const indexArray[])/* Array of pointers to Tcl objects that * represent the indices in the list. */ { int i; Tcl_IncrRefCount(listPtr); for (i=0 ; i error. */ break; } TclListObjGetElements(NULL, sublistCopy, &listLen, &elemPtrs); if (TclGetIntForIndexM(interp, indexArray[i], /*endValue*/ listLen-1, &index) == TCL_OK) { if (index<0 || index>=listLen) { /* * Index is out of range. Break out of loop with empty result. * First check remaining indices for validity */ while (++i < indexCount) { if (TclGetIntForIndexM(interp, indexArray[i], -1, &index) != TCL_OK) { Tcl_DecrRefCount(sublistCopy); return NULL; } } listPtr = Tcl_NewObj(); } else { /* * Extract the pointer to the appropriate element. */ listPtr = elemPtrs[index]; } Tcl_IncrRefCount(listPtr); } Tcl_DecrRefCount(sublistCopy); } return listPtr; } /* *---------------------------------------------------------------------- * * TclLsetList -- * * Core of the 'lset' command when objc == 4. Objv[2] may be either a * scalar index or a list of indices. * * Results: * Returns the new value of the list variable, or NULL if there was an * error. The returned object includes one reference count for the * pointer returned. * * Side effects: * None. * * Notes: * This procedure is implemented entirely as a wrapper around * TclLsetFlat. All it does is reconfigure the argument format into the * form required by TclLsetFlat, while taking care to manage shimmering * in such a way that we tend to keep the most useful intreps and/or * avoid the most expensive conversions. * *---------------------------------------------------------------------- */ Tcl_Obj * TclLsetList( Tcl_Interp *interp, /* Tcl interpreter. */ Tcl_Obj *listPtr, /* Pointer to the list being modified. */ Tcl_Obj *indexArgPtr, /* Index or index-list arg to 'lset'. */ Tcl_Obj *valuePtr) /* Value arg to 'lset'. */ { int indexCount = 0; /* Number of indices in the index list. */ Tcl_Obj **indices = NULL; /* Vector of indices in the index list. */ Tcl_Obj *retValuePtr; /* Pointer to the list to be returned. */ int index; /* Current index in the list - discarded. */ Tcl_Obj *indexListCopy; /* * Determine whether the index arg designates a list or a single index. * We have to be careful about the order of the checks to avoid repeated * shimmering; see TIP #22 and #23 for details. */ if (indexArgPtr->typePtr != &tclListType && TclGetIntForIndexM(NULL, indexArgPtr, 0, &index) == TCL_OK) { /* * indexArgPtr designates a single index. */ return TclLsetFlat(interp, listPtr, 1, &indexArgPtr, valuePtr); } indexListCopy = TclListObjCopy(NULL, indexArgPtr); if (indexListCopy == NULL) { /* * indexArgPtr designates something that is neither an index nor a * well formed list. Report the error via TclLsetFlat. */ return TclLsetFlat(interp, listPtr, 1, &indexArgPtr, valuePtr); } TclListObjGetElements(NULL, indexArgPtr, &indexCount, &indices); /* * Let TclLsetFlat handle the actual lset'ting. */ retValuePtr = TclLsetFlat(interp, listPtr, indexCount, indices, valuePtr); Tcl_DecrRefCount(indexListCopy); return retValuePtr; } /* *---------------------------------------------------------------------- * * TclLsetFlat -- * * Core engine of the 'lset' command. * * Results: * Returns the new value of the list variable, or NULL if an error * occurred. The returned object includes one reference count for the * pointer returned. * * Side effects: * On entry, the reference count of the variable value does not reflect * any references held on the stack. The first action of this function is * to determine whether the object is shared, and to duplicate it if it * is. The reference count of the duplicate is incremented. At this * point, the reference count will be 1 for either case, so that the * object will appear to be unshared. * * If an error occurs, and the object has been duplicated, the reference * count on the duplicate is decremented so that it is now 0: this * dismisses any memory that was allocated by this function. * * If no error occurs, the reference count of the original object is * incremented if the object has not been duplicated, and nothing is done * to a reference count of the duplicate. Now the reference count of an * unduplicated object is 2 (the returned pointer, plus the one stored in * the variable). The reference count of a duplicate object is 1, * reflecting that the returned pointer is the only active reference. The * caller is expected to store the returned value back in the variable * and decrement its reference count. (INST_STORE_* does exactly this.) * * Surgery is performed on the unshared list value to produce the result. * TclLsetFlat maintains a linked list of Tcl_Obj's whose string * representations must be spoilt by threading via 'ptr2' of the * two-pointer internal representation. On entry to TclLsetFlat, the * values of 'ptr2' are immaterial; on exit, the 'ptr2' field of any * Tcl_Obj that has been modified is set to NULL. * *---------------------------------------------------------------------- */ Tcl_Obj * TclLsetFlat( Tcl_Interp *interp, /* Tcl interpreter. */ Tcl_Obj *listPtr, /* Pointer to the list being modified. */ int indexCount, /* Number of index args. */ Tcl_Obj *const indexArray[], /* Index args. */ Tcl_Obj *valuePtr) /* Value arg to 'lset'. */ { int index, result, len; Tcl_Obj *subListPtr, *retValuePtr, *chainPtr; /* * If there are no indices, simply return the new value. (Without * indices, [lset] is a synonym for [set]. */ if (indexCount == 0) { Tcl_IncrRefCount(valuePtr); return valuePtr; } /* * If the list is shared, make a copy we can modify (copy-on-write). We * use Tcl_DuplicateObj() instead of TclListObjCopy() for a few reasons: * 1) we have not yet confirmed listPtr is actually a list; 2) We make a * verbatim copy of any existing string rep, and when we combine that with * the delayed invalidation of string reps of modified Tcl_Obj's * implemented below, the outcome is that any error condition that causes * this routine to return NULL, will leave the string rep of listPtr and * all elements to be unchanged. */ subListPtr = Tcl_IsShared(listPtr) ? Tcl_DuplicateObj(listPtr) : listPtr; /* * Anchor the linked list of Tcl_Obj's whose string reps must be * invalidated if the operation succeeds. */ retValuePtr = subListPtr; chainPtr = NULL; result = TCL_OK; /* * Loop through all the index arguments, and for each one dive into the * appropriate sublist. */ do { int elemCount; Tcl_Obj *parentList, **elemPtrs; /* * Check for the possible error conditions... */ if (TclListObjGetElements(interp, subListPtr, &elemCount, &elemPtrs) != TCL_OK) { /* ...the sublist we're indexing into isn't a list at all. */ result = TCL_ERROR; break; } /* * WARNING: the macro TclGetIntForIndexM is not safe for * post-increments, avoid '*indexArray++' here. */ if (TclGetIntForIndexM(interp, *indexArray, elemCount - 1, &index) != TCL_OK) { /* ...the index we're trying to use isn't an index at all. */ result = TCL_ERROR; indexArray++; break; } indexArray++; if (index < 0 || index > elemCount) { /* ...the index points outside the sublist. */ if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("list index out of range", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSET", "BADINDEX", NULL); } result = TCL_ERROR; break; } /* * No error conditions. As long as we're not yet on the last index, * determine the next sublist for the next pass through the loop, and * take steps to make sure it is an unshared copy, as we intend to * modify it. */ if (--indexCount) { parentList = subListPtr; if (index == elemCount) { subListPtr = Tcl_NewObj(); } else { subListPtr = elemPtrs[index]; } if (Tcl_IsShared(subListPtr)) { subListPtr = Tcl_DuplicateObj(subListPtr); } /* * Replace the original elemPtr[index] in parentList with a copy * we know to be unshared. This call will also deal with the * situation where parentList shares its intrep with other * Tcl_Obj's. Dealing with the shared intrep case can cause * subListPtr to become shared again, so detect that case and make * and store another copy. */ if (index == elemCount) { Tcl_ListObjAppendElement(NULL, parentList, subListPtr); } else { TclListObjSetElement(NULL, parentList, index, subListPtr); } if (Tcl_IsShared(subListPtr)) { subListPtr = Tcl_DuplicateObj(subListPtr); TclListObjSetElement(NULL, parentList, index, subListPtr); } /* * The TclListObjSetElement() calls do not spoil the string rep of * parentList, and that's fine for now, since all we've done so * far is replace a list element with an unshared copy. The list * value remains the same, so the string rep. is still valid, and * unchanged, which is good because if this whole routine returns * NULL, we'd like to leave no change to the value of the lset * variable. Later on, when we set valuePtr in its proper place, * then all containing lists will have their values changed, and * will need their string reps spoiled. We maintain a list of all * those Tcl_Obj's (via a little intrep surgery) so we can spoil * them at that time. */ parentList->internalRep.twoPtrValue.ptr2 = chainPtr; chainPtr = parentList; } } while (indexCount > 0); /* * Either we've detected and error condition, and exited the loop with * result == TCL_ERROR, or we've successfully reached the last index, and * we're ready to store valuePtr. In either case, we need to clean up our * string spoiling list of Tcl_Obj's. */ while (chainPtr) { Tcl_Obj *objPtr = chainPtr; if (result == TCL_OK) { /* * We're going to store valuePtr, so spoil string reps of all * containing lists. */ TclInvalidateStringRep(objPtr); } /* * Clear away our intrep surgery mess. */ chainPtr = objPtr->internalRep.twoPtrValue.ptr2; objPtr->internalRep.twoPtrValue.ptr2 = NULL; } if (result != TCL_OK) { /* * Error return; message is already in interp. Clean up any excess * memory. */ if (retValuePtr != listPtr) { Tcl_DecrRefCount(retValuePtr); } return NULL; } /* * Store valuePtr in proper sublist and return. The -1 is to avoid a * compiler warning (not a problem because we checked that we have a * proper list - or something convertible to one - above). */ len = -1; TclListObjLength(NULL, subListPtr, &len); if (index == len) { Tcl_ListObjAppendElement(NULL, subListPtr, valuePtr); } else { TclListObjSetElement(NULL, subListPtr, index, valuePtr); } TclInvalidateStringRep(subListPtr); Tcl_IncrRefCount(retValuePtr); return retValuePtr; } /* *---------------------------------------------------------------------- * * TclListObjSetElement -- * * Set a single element of a list to a specified value * * Results: * The return value is normally TCL_OK. If listPtr does not refer to a * list object and cannot be converted to one, TCL_ERROR is returned and * an error message will be left in the interpreter result if interp is * not NULL. Similarly, if index designates an element outside the range * [0..listLength-1], where listLength is the count of elements in the * list object designated by listPtr, TCL_ERROR is returned and an error * message is left in the interpreter result. * * Side effects: * Tcl_Panic if listPtr designates a shared object. Otherwise, attempts * to convert it to a list with a non-shared internal rep. Decrements the * ref count of the object at the specified index within the list, * replaces with the object designated by valuePtr, and increments the * ref count of the replacement object. * * It is the caller's responsibility to invalidate the string * representation of the object. * *---------------------------------------------------------------------- */ int TclListObjSetElement( Tcl_Interp *interp, /* Tcl interpreter; used for error reporting * if not NULL. */ Tcl_Obj *listPtr, /* List object in which element should be * stored. */ int index, /* Index of element to store. */ Tcl_Obj *valuePtr) /* Tcl object to store in the designated list * element. */ { List *listRepPtr; /* Internal representation of the list being * modified. */ Tcl_Obj **elemPtrs; /* Pointers to elements of the list. */ int elemCount; /* Number of elements in the list. */ /* * Ensure that the listPtr parameter designates an unshared list. */ if (Tcl_IsShared(listPtr)) { Tcl_Panic("%s called with shared object", "TclListObjSetElement"); } if (listPtr->typePtr != &tclListType) { int result; if (listPtr->bytes == tclEmptyStringRep) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("list index out of range", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSET", "BADINDEX", NULL); } return TCL_ERROR; } result = SetListFromAny(interp, listPtr); if (result != TCL_OK) { return result; } } listRepPtr = ListRepPtr(listPtr); elemCount = listRepPtr->elemCount; /* * Ensure that the index is in bounds. */ if (index<0 || index>=elemCount) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("list index out of range", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSET", "BADINDEX", NULL); } return TCL_ERROR; } /* * If the internal rep is shared, replace it with an unshared copy. */ if (listRepPtr->refCount > 1) { Tcl_Obj **dst, **src = &listRepPtr->elements; List *newPtr = AttemptNewList(NULL, listRepPtr->maxElemCount, NULL); if (newPtr == NULL) { newPtr = AttemptNewList(interp, elemCount, NULL); if (newPtr == NULL) { return TCL_ERROR; } } newPtr->refCount++; newPtr->elemCount = elemCount; newPtr->canonicalFlag = listRepPtr->canonicalFlag; dst = &newPtr->elements; while (elemCount--) { *dst = *src++; Tcl_IncrRefCount(*dst++); } listRepPtr->refCount--; listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr = newPtr; } elemPtrs = &listRepPtr->elements; /* * Add a reference to the new list element. */ Tcl_IncrRefCount(valuePtr); /* * Remove a reference from the old list element. */ Tcl_DecrRefCount(elemPtrs[index]); /* * Stash the new object in the list. */ elemPtrs[index] = valuePtr; return TCL_OK; } /* *---------------------------------------------------------------------- * * FreeListInternalRep -- * * Deallocate the storage associated with a list object's internal * representation. * * Results: * None. * * Side effects: * Frees listPtr's List* internal representation and sets listPtr's * internalRep.twoPtrValue.ptr1 to NULL. Decrements the ref counts of all * element objects, which may free them. * *---------------------------------------------------------------------- */ static void FreeListInternalRep( Tcl_Obj *listPtr) /* List object with internal rep to free. */ { List *listRepPtr = ListRepPtr(listPtr); if (listRepPtr->refCount-- <= 1) { Tcl_Obj **elemPtrs = &listRepPtr->elements; int i, numElems = listRepPtr->elemCount; for (i = 0; i < numElems; i++) { Tcl_DecrRefCount(elemPtrs[i]); } ckfree(listRepPtr); } listPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * DupListInternalRep -- * * Initialize the internal representation of a list Tcl_Obj to share the * internal representation of an existing list object. * * Results: * None. * * Side effects: * The reference count of the List internal rep is incremented. * *---------------------------------------------------------------------- */ static void DupListInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { List *listRepPtr = ListRepPtr(srcPtr); ListSetIntRep(copyPtr, listRepPtr); } /* *---------------------------------------------------------------------- * * SetListFromAny -- * * Attempt to generate a list internal form for the Tcl object "objPtr". * * Results: * The return value is TCL_OK or TCL_ERROR. If an error occurs during * conversion, an error message is left in the interpreter's result * unless "interp" is NULL. * * Side effects: * If no error occurs, a list is stored as "objPtr"s internal * representation. * *---------------------------------------------------------------------- */ static int SetListFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr) /* The object to convert. */ { List *listRepPtr; Tcl_Obj **elemPtrs; /* * Dictionaries are a special case; they have a string representation such * that *all* valid dictionaries are valid lists. Hence we can convert * more directly. Only do this when there's no existing string rep; if * there is, it is the string rep that's authoritative (because it could * describe duplicate keys). */ if (objPtr->typePtr == &tclDictType && !objPtr->bytes) { Tcl_Obj *keyPtr, *valuePtr; Tcl_DictSearch search; int done, size; /* * Create the new list representation. Note that we do not need to do * anything with the string representation as the transformation (and * the reverse back to a dictionary) are both order-preserving. Also * note that since we know we've got a valid dictionary (by * representation) we also know that fetching the size of the * dictionary or iterating over it will not fail. */ Tcl_DictObjSize(NULL, objPtr, &size); listRepPtr = AttemptNewList(interp, size > 0 ? 2*size : 1, NULL); if (!listRepPtr) { return TCL_ERROR; } listRepPtr->elemCount = 2 * size; /* * Populate the list representation. */ elemPtrs = &listRepPtr->elements; Tcl_DictObjFirst(NULL, objPtr, &search, &keyPtr, &valuePtr, &done); while (!done) { *elemPtrs++ = keyPtr; *elemPtrs++ = valuePtr; Tcl_IncrRefCount(keyPtr); Tcl_IncrRefCount(valuePtr); Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done); } } else { int estCount, length; const char *limit, *nextElem = TclGetStringFromObj(objPtr, &length); /* * Allocate enough space to hold a (Tcl_Obj *) for each * (possible) list element. */ estCount = TclMaxListLength(nextElem, length, &limit); estCount += (estCount == 0); /* Smallest list struct holds 1 * element. */ listRepPtr = AttemptNewList(interp, estCount, NULL); if (listRepPtr == NULL) { return TCL_ERROR; } elemPtrs = &listRepPtr->elements; /* * Each iteration, parse and store a list element. */ while (nextElem < limit) { const char *elemStart; int elemSize, literal; if (TCL_OK != TclFindElement(interp, nextElem, limit - nextElem, &elemStart, &nextElem, &elemSize, &literal)) { while (--elemPtrs >= &listRepPtr->elements) { Tcl_DecrRefCount(*elemPtrs); } ckfree((char *) listRepPtr); return TCL_ERROR; } if (elemStart == limit) { break; } /* TODO: replace panic with error on alloc failure? */ if (literal) { TclNewStringObj(*elemPtrs, elemStart, elemSize); } else { TclNewObj(*elemPtrs); (*elemPtrs)->bytes = ckalloc((unsigned) elemSize + 1); (*elemPtrs)->length = TclCopyAndCollapse(elemSize, elemStart, (*elemPtrs)->bytes); } Tcl_IncrRefCount(*elemPtrs++);/* Since list now holds ref to it. */ } listRepPtr->elemCount = elemPtrs - &listRepPtr->elements; } /* * Free the old internalRep before setting the new one. We do this as late * as possible to allow the conversion code, in particular * Tcl_GetStringFromObj, to use that old internalRep. */ TclFreeIntRep(objPtr); ListSetIntRep(objPtr, listRepPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * UpdateStringOfList -- * * Update the string representation for a list object. Note: This * function does not invalidate an existing old string rep so storage * will be lost if this has not already been done. * * Results: * None. * * Side effects: * The object's string is set to a valid string that results from the * list-to-string conversion. This string will be empty if the list has * no elements. The list internal representation should not be NULL and * we assume it is not NULL. * *---------------------------------------------------------------------- */ static void UpdateStringOfList( Tcl_Obj *listPtr) /* List object with string rep to update. */ { # define LOCAL_SIZE 20 int localFlags[LOCAL_SIZE], *flagPtr = NULL; List *listRepPtr = ListRepPtr(listPtr); int numElems = listRepPtr->elemCount; int i, length, bytesNeeded = 0; const char *elem; char *dst; Tcl_Obj **elemPtrs; /* * Mark the list as being canonical; although it will now have a string * rep, it is one we derived through proper "canonical" quoting and so * it's known to be free from nasties relating to [concat] and [eval]. */ listRepPtr->canonicalFlag = 1; /* * Handle empty list case first, so rest of the routine is simpler. */ if (numElems == 0) { listPtr->bytes = tclEmptyStringRep; listPtr->length = 0; return; } /* * Pass 1: estimate space, gather flags. */ if (numElems <= LOCAL_SIZE) { flagPtr = localFlags; } else { /* * We know numElems <= LIST_MAX, so this is safe. */ flagPtr = ckalloc(numElems * sizeof(int)); } elemPtrs = &listRepPtr->elements; for (i = 0; i < numElems; i++) { flagPtr[i] = (i ? TCL_DONT_QUOTE_HASH : 0); elem = TclGetStringFromObj(elemPtrs[i], &length); bytesNeeded += TclScanElement(elem, length, flagPtr+i); if (bytesNeeded < 0) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } } if (bytesNeeded > INT_MAX - numElems + 1) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } bytesNeeded += numElems; /* * Pass 2: copy into string rep buffer. */ listPtr->length = bytesNeeded - 1; listPtr->bytes = ckalloc(bytesNeeded); dst = listPtr->bytes; for (i = 0; i < numElems; i++) { flagPtr[i] |= (i ? TCL_DONT_QUOTE_HASH : 0); elem = TclGetStringFromObj(elemPtrs[i], &length); dst += TclConvertElement(elem, length, dst, flagPtr[i]); *dst++ = ' '; } listPtr->bytes[listPtr->length] = '\0'; if (flagPtr != localFlags) { ckfree(flagPtr); } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclCompile.h0000644000175000017500000021167112663660065015457 0ustar sergeisergei/* * tclCompile.h -- * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * Copyright (c) 1998-2000 by Scriptics Corporation. * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLCOMPILATION #define _TCLCOMPILATION 1 #include "tclInt.h" struct ByteCode; /* Forward declaration. */ /* *------------------------------------------------------------------------ * Variables related to compilation. These are used in tclCompile.c, * tclExecute.c, tclBasic.c, and their clients. *------------------------------------------------------------------------ */ #ifdef TCL_COMPILE_DEBUG /* * Variable that controls whether compilation tracing is enabled and, if so, * what level of tracing is desired: * 0: no compilation tracing * 1: summarize compilation of top level cmds and proc bodies * 2: display all instructions of each ByteCode compiled * This variable is linked to the Tcl variable "tcl_traceCompile". */ MODULE_SCOPE int tclTraceCompile; /* * Variable that controls whether execution tracing is enabled and, if so, * what level of tracing is desired: * 0: no execution tracing * 1: trace invocations of Tcl procs only * 2: trace invocations of all (not compiled away) commands * 3: display each instruction executed * This variable is linked to the Tcl variable "tcl_traceExec". */ MODULE_SCOPE int tclTraceExec; #endif /* * The type of lambda expressions. Note that every lambda will *always* have a * string representation. */ MODULE_SCOPE const Tcl_ObjType tclLambdaType; /* *------------------------------------------------------------------------ * Data structures related to compilation. *------------------------------------------------------------------------ */ /* * The structure used to implement Tcl "exceptions" (exceptional returns): for * example, those generated in loops by the break and continue commands, and * those generated by scripts and caught by the catch command. This * ExceptionRange structure describes a range of code (e.g., a loop body), the * kind of exceptions (e.g., a break or continue) that might occur, and the PC * offsets to jump to if a matching exception does occur. Exception ranges can * nest so this structure includes a nesting level that is used at runtime to * find the closest exception range surrounding a PC. For example, when a * break command is executed, the ExceptionRange structure for the most deeply * nested loop, if any, is found and used. These structures are also generated * for the "next" subcommands of for loops since a break there terminates the * for command. This means a for command actually generates two LoopInfo * structures. */ typedef enum { LOOP_EXCEPTION_RANGE, /* Exception's range is part of a loop. Break * and continue "exceptions" cause jumps to * appropriate PC offsets. */ CATCH_EXCEPTION_RANGE /* Exception's range is controlled by a catch * command. Errors in the range cause a jump * to a catch PC offset. */ } ExceptionRangeType; typedef struct ExceptionRange { ExceptionRangeType type; /* The kind of ExceptionRange. */ int nestingLevel; /* Static depth of the exception range. Used * to find the most deeply-nested range * surrounding a PC at runtime. */ int codeOffset; /* Offset of the first instruction byte of the * code range. */ int numCodeBytes; /* Number of bytes in the code range. */ int breakOffset; /* If LOOP_EXCEPTION_RANGE, the target PC * offset for a break command in the range. */ int continueOffset; /* If LOOP_EXCEPTION_RANGE and not -1, the * target PC offset for a continue command in * the code range. Otherwise, ignore this * range when processing a continue * command. */ int catchOffset; /* If a CATCH_EXCEPTION_RANGE, the target PC * offset for any "exception" in range. */ } ExceptionRange; /* * Auxiliary data used when issuing (currently just loop) exception ranges, * but which is not required during execution. */ typedef struct ExceptionAux { int supportsContinue; /* Whether this exception range will have a * continueOffset created for it; if it is a * loop exception range that *doesn't* have * one (see [for] next-clause) then we must * not pick up the range when scanning for a * target to continue to. */ int stackDepth; /* The stack depth at the point where the * exception range was created. This is used * to calculate the number of POPs required to * restore the stack to its prior state. */ int expandTarget; /* The number of expansions expected on the * auxData stack at the time the loop starts; * we can't currently discard them except by * doing INST_INVOKE_EXPANDED; this is a known * problem. */ int expandTargetDepth; /* The stack depth expected at the outermost * expansion within the loop. Not meaningful * if there are no open expansions between the * looping level and the point of jump * issue. */ int numBreakTargets; /* The number of [break]s that want to be * targeted to the place where this loop * exception will be bound to. */ int *breakTargets; /* The offsets of the INST_JUMP4 instructions * issued by the [break]s that we must * update. Note that resizing a jump (via * TclFixupForwardJump) can cause the contents * of this array to be updated. When * numBreakTargets==0, this is NULL. */ int allocBreakTargets; /* The size of the breakTargets array. */ int numContinueTargets; /* The number of [continue]s that want to be * targeted to the place where this loop * exception will be bound to. */ int *continueTargets; /* The offsets of the INST_JUMP4 instructions * issued by the [continue]s that we must * update. Note that resizing a jump (via * TclFixupForwardJump) can cause the contents * of this array to be updated. When * numContinueTargets==0, this is NULL. */ int allocContinueTargets; /* The size of the continueTargets array. */ } ExceptionAux; /* * Structure used to map between instruction pc and source locations. It * defines for each compiled Tcl command its code's starting offset and its * source's starting offset and length. Note that the code offset increases * monotonically: that is, the table is sorted in code offset order. The * source offset is not monotonic. */ typedef struct CmdLocation { int codeOffset; /* Offset of first byte of command code. */ int numCodeBytes; /* Number of bytes for command's code. */ int srcOffset; /* Offset of first char of the command. */ int numSrcBytes; /* Number of command source chars. */ } CmdLocation; /* * TIP #280 * Structure to record additional location information for byte code. This * information is internal and not saved. i.e. tbcload'ed code will not have * this information. It records the lines for all words of all commands found * in the byte code. The association with a ByteCode structure BC is done * through the 'lineBCPtr' HashTable in Interp, keyed by the address of BC. * Also recorded is information coming from the context, i.e. type of the * frame and associated information, like the path of a sourced file. */ typedef struct ECL { int srcOffset; /* Command location to find the entry. */ int nline; /* Number of words in the command */ int *line; /* Line information for all words in the * command. */ int **next; /* Transient information used by the compiler * for tracking of hidden continuation * lines. */ } ECL; typedef struct ExtCmdLoc { int type; /* Context type. */ int start; /* Starting line for compiled script. Needed * for the extended recompile check in * tclCompileObj. */ Tcl_Obj *path; /* Path of the sourced file the command is * in. */ ECL *loc; /* Command word locations (lines). */ int nloc; /* Number of allocated entries in 'loc'. */ int nuloc; /* Number of used entries in 'loc'. */ } ExtCmdLoc; /* * CompileProcs need the ability to record information during compilation that * can be used by bytecode instructions during execution. The AuxData * structure provides this "auxiliary data" mechanism. An arbitrary number of * these structures can be stored in the ByteCode record (during compilation * they are stored in a CompileEnv structure). Each AuxData record holds one * word of client-specified data (often a pointer) and is given an index that * instructions can later use to look up the structure and its data. * * The following definitions declare the types of procedures that are called * to duplicate or free this auxiliary data when the containing ByteCode * objects are duplicated and freed. Pointers to these procedures are kept in * the AuxData structure. */ typedef ClientData (AuxDataDupProc) (ClientData clientData); typedef void (AuxDataFreeProc) (ClientData clientData); typedef void (AuxDataPrintProc)(ClientData clientData, Tcl_Obj *appendObj, struct ByteCode *codePtr, unsigned int pcOffset); /* * We define a separate AuxDataType struct to hold type-related information * for the AuxData structure. This separation makes it possible for clients * outside of the TCL core to manipulate (in a limited fashion!) AuxData; for * example, it makes it possible to pickle and unpickle AuxData structs. */ typedef struct AuxDataType { const char *name; /* The name of the type. Types can be * registered and found by name */ AuxDataDupProc *dupProc; /* Callback procedure to invoke when the aux * data is duplicated (e.g., when the ByteCode * structure containing the aux data is * duplicated). NULL means just copy the * source clientData bits; no proc need be * called. */ AuxDataFreeProc *freeProc; /* Callback procedure to invoke when the aux * data is freed. NULL means no proc need be * called. */ AuxDataPrintProc *printProc;/* Callback function to invoke when printing * the aux data as part of debugging. NULL * means that the data can't be printed. */ AuxDataPrintProc *disassembleProc; /* Callback function to invoke when doing a * disassembly of the aux data (like the * printProc, except that the output is * intended to be script-readable). The * appendObj argument should be filled in with * a descriptive dictionary; it will start out * with "name" mapped to the content of the * name field. NULL means that the printProc * should be used instead. */ } AuxDataType; /* * The definition of the AuxData structure that holds information created * during compilation by CompileProcs and used by instructions during * execution. */ typedef struct AuxData { const AuxDataType *type; /* Pointer to the AuxData type associated with * this ClientData. */ ClientData clientData; /* The compilation data itself. */ } AuxData; /* * Structure defining the compilation environment. After compilation, fields * describing bytecode instructions are copied out into the more compact * ByteCode structure defined below. */ #define COMPILEENV_INIT_CODE_BYTES 250 #define COMPILEENV_INIT_NUM_OBJECTS 60 #define COMPILEENV_INIT_EXCEPT_RANGES 5 #define COMPILEENV_INIT_CMD_MAP_SIZE 40 #define COMPILEENV_INIT_AUX_DATA_SIZE 5 typedef struct CompileEnv { Interp *iPtr; /* Interpreter containing the code being * compiled. Commands and their compile procs * are specific to an interpreter so the code * emitted will depend on the interpreter. */ const char *source; /* The source string being compiled by * SetByteCodeFromAny. This pointer is not * owned by the CompileEnv and must not be * freed or changed by it. */ int numSrcBytes; /* Number of bytes in source. */ Proc *procPtr; /* If a procedure is being compiled, a pointer * to its Proc structure; otherwise NULL. Used * to compile local variables. Set from * information provided by ObjInterpProc in * tclProc.c. */ int numCommands; /* Number of commands compiled. */ int exceptDepth; /* Current exception range nesting level; -1 * if not in any range currently. */ int maxExceptDepth; /* Max nesting level of exception ranges; -1 * if no ranges have been compiled. */ int maxStackDepth; /* Maximum number of stack elements needed to * execute the code. Set by compilation * procedures before returning. */ int currStackDepth; /* Current stack depth. */ LiteralTable localLitTable; /* Contains LiteralEntry's describing all Tcl * objects referenced by this compiled code. * Indexed by the string representations of * the literals. Used to avoid creating * duplicate objects. */ unsigned char *codeStart; /* Points to the first byte of the code. */ unsigned char *codeNext; /* Points to next code array byte to use. */ unsigned char *codeEnd; /* Points just after the last allocated code * array byte. */ int mallocedCodeArray; /* Set 1 if code array was expanded and * codeStart points into the heap.*/ LiteralEntry *literalArrayPtr; /* Points to start of LiteralEntry array. */ int literalArrayNext; /* Index of next free object array entry. */ int literalArrayEnd; /* Index just after last obj array entry. */ int mallocedLiteralArray; /* 1 if object array was expanded and objArray * points into the heap, else 0. */ ExceptionRange *exceptArrayPtr; /* Points to start of the ExceptionRange * array. */ int exceptArrayNext; /* Next free ExceptionRange array index. * exceptArrayNext is the number of ranges and * (exceptArrayNext-1) is the index of the * current range's array entry. */ int exceptArrayEnd; /* Index after the last ExceptionRange array * entry. */ int mallocedExceptArray; /* 1 if ExceptionRange array was expanded and * exceptArrayPtr points in heap, else 0. */ ExceptionAux *exceptAuxArrayPtr; /* Array of information used to restore the * state when processing BREAK/CONTINUE * exceptions. Must be the same size as the * exceptArrayPtr. */ CmdLocation *cmdMapPtr; /* Points to start of CmdLocation array. * numCommands is the index of the next entry * to use; (numCommands-1) is the entry index * for the last command. */ int cmdMapEnd; /* Index after last CmdLocation entry. */ int mallocedCmdMap; /* 1 if command map array was expanded and * cmdMapPtr points in the heap, else 0. */ AuxData *auxDataArrayPtr; /* Points to auxiliary data array start. */ int auxDataArrayNext; /* Next free compile aux data array index. * auxDataArrayNext is the number of aux data * items and (auxDataArrayNext-1) is index of * current aux data array entry. */ int auxDataArrayEnd; /* Index after last aux data array entry. */ int mallocedAuxDataArray; /* 1 if aux data array was expanded and * auxDataArrayPtr points in heap else 0. */ unsigned char staticCodeSpace[COMPILEENV_INIT_CODE_BYTES]; /* Initial storage for code. */ LiteralEntry staticLiteralSpace[COMPILEENV_INIT_NUM_OBJECTS]; /* Initial storage of LiteralEntry array. */ ExceptionRange staticExceptArraySpace[COMPILEENV_INIT_EXCEPT_RANGES]; /* Initial ExceptionRange array storage. */ ExceptionAux staticExAuxArraySpace[COMPILEENV_INIT_EXCEPT_RANGES]; /* Initial static except auxiliary info array * storage. */ CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE]; /* Initial storage for cmd location map. */ AuxData staticAuxDataArraySpace[COMPILEENV_INIT_AUX_DATA_SIZE]; /* Initial storage for aux data array. */ /* TIP #280 */ ExtCmdLoc *extCmdMapPtr; /* Extended command location information for * 'info frame'. */ int line; /* First line of the script, based on the * invoking context, then the line of the * command currently compiled. */ int atCmdStart; /* Flag to say whether an INST_START_CMD * should be issued; they should never be * issued repeatedly, as that is significantly * inefficient. If set to 2, that instruction * should not be issued at all (by the generic * part of the command compiler). */ int expandCount; /* Number of INST_EXPAND_START instructions * encountered that have not yet been paired * with a corresponding * INST_INVOKE_EXPANDED. */ int *clNext; /* If not NULL, it refers to the next slot in * clLoc to check for an invisible * continuation line. */ } CompileEnv; /* * The structure defining the bytecode instructions resulting from compiling a * Tcl script. Note that this structure is variable length: a single heap * object is allocated to hold the ByteCode structure immediately followed by * the code bytes, the literal object array, the ExceptionRange array, the * CmdLocation map, and the compilation AuxData array. */ /* * A PRECOMPILED bytecode struct is one that was generated from a compiled * image rather than implicitly compiled from source */ #define TCL_BYTECODE_PRECOMPILED 0x0001 /* * When a bytecode is compiled, interp or namespace resolvers have not been * applied yet: this is indicated by the TCL_BYTECODE_RESOLVE_VARS flag. */ #define TCL_BYTECODE_RESOLVE_VARS 0x0002 #define TCL_BYTECODE_RECOMPILE 0x0004 typedef struct ByteCode { TclHandle interpHandle; /* Handle for interpreter containing the * compiled code. Commands and their compile * procs are specific to an interpreter so the * code emitted will depend on the * interpreter. */ int compileEpoch; /* Value of iPtr->compileEpoch when this * ByteCode was compiled. Used to invalidate * code when, e.g., commands with compile * procs are redefined. */ Namespace *nsPtr; /* Namespace context in which this code was * compiled. If the code is executed if a * different namespace, it must be * recompiled. */ int nsEpoch; /* Value of nsPtr->resolverEpoch when this * ByteCode was compiled. Used to invalidate * code when new namespace resolution rules * are put into effect. */ int refCount; /* Reference count: set 1 when created plus 1 * for each execution of the code currently * active. This structure can be freed when * refCount becomes zero. */ unsigned int flags; /* flags describing state for the codebyte. * this variable holds ORed values from the * TCL_BYTECODE_ masks defined above */ const char *source; /* The source string from which this ByteCode * was compiled. Note that this pointer is not * owned by the ByteCode and must not be freed * or modified by it. */ Proc *procPtr; /* If the ByteCode was compiled from a * procedure body, this is a pointer to its * Proc structure; otherwise NULL. This * pointer is also not owned by the ByteCode * and must not be freed by it. */ size_t structureSize; /* Number of bytes in the ByteCode structure * itself. Does not include heap space for * literal Tcl objects or storage referenced * by AuxData entries. */ int numCommands; /* Number of commands compiled. */ int numSrcBytes; /* Number of source bytes compiled. */ int numCodeBytes; /* Number of code bytes. */ int numLitObjects; /* Number of objects in literal array. */ int numExceptRanges; /* Number of ExceptionRange array elems. */ int numAuxDataItems; /* Number of AuxData items. */ int numCmdLocBytes; /* Number of bytes needed for encoded command * location information. */ int maxExceptDepth; /* Maximum nesting level of ExceptionRanges; * -1 if no ranges were compiled. */ int maxStackDepth; /* Maximum number of stack elements needed to * execute the code. */ unsigned char *codeStart; /* Points to the first byte of the code. This * is just after the final ByteCode member * cmdMapPtr. */ Tcl_Obj **objArrayPtr; /* Points to the start of the literal object * array. This is just after the last code * byte. */ ExceptionRange *exceptArrayPtr; /* Points to the start of the ExceptionRange * array. This is just after the last object * in the object array. */ AuxData *auxDataArrayPtr; /* Points to the start of the auxiliary data * array. This is just after the last entry in * the ExceptionRange array. */ unsigned char *codeDeltaStart; /* Points to the first of a sequence of bytes * that encode the change in the starting * offset of each command's code. If -127 <= * delta <= 127, it is encoded as 1 byte, * otherwise 0xFF (128) appears and the delta * is encoded by the next 4 bytes. Code deltas * are always positive. This sequence is just * after the last entry in the AuxData * array. */ unsigned char *codeLengthStart; /* Points to the first of a sequence of bytes * that encode the length of each command's * code. The encoding is the same as for code * deltas. Code lengths are always positive. * This sequence is just after the last entry * in the code delta sequence. */ unsigned char *srcDeltaStart; /* Points to the first of a sequence of bytes * that encode the change in the starting * offset of each command's source. The * encoding is the same as for code deltas. * Source deltas can be negative. This * sequence is just after the last byte in the * code length sequence. */ unsigned char *srcLengthStart; /* Points to the first of a sequence of bytes * that encode the length of each command's * source. The encoding is the same as for * code deltas. Source lengths are always * positive. This sequence is just after the * last byte in the source delta sequence. */ LocalCache *localCachePtr; /* Pointer to the start of the cached variable * names and initialisation data for local * variables. */ #ifdef TCL_COMPILE_STATS Tcl_Time createTime; /* Absolute time when the ByteCode was * created. */ #endif /* TCL_COMPILE_STATS */ } ByteCode; /* * Opcodes for the Tcl bytecode instructions. These must correspond to the * entries in the table of instruction descriptions, tclInstructionTable, in * tclCompile.c. Also, the order and number of the expression opcodes (e.g., * INST_LOR) must match the entries in the array operatorStrings in * tclExecute.c. */ /* Opcodes 0 to 9 */ #define INST_DONE 0 #define INST_PUSH1 1 #define INST_PUSH4 2 #define INST_POP 3 #define INST_DUP 4 #define INST_STR_CONCAT1 5 #define INST_INVOKE_STK1 6 #define INST_INVOKE_STK4 7 #define INST_EVAL_STK 8 #define INST_EXPR_STK 9 /* Opcodes 10 to 23 */ #define INST_LOAD_SCALAR1 10 #define INST_LOAD_SCALAR4 11 #define INST_LOAD_SCALAR_STK 12 #define INST_LOAD_ARRAY1 13 #define INST_LOAD_ARRAY4 14 #define INST_LOAD_ARRAY_STK 15 #define INST_LOAD_STK 16 #define INST_STORE_SCALAR1 17 #define INST_STORE_SCALAR4 18 #define INST_STORE_SCALAR_STK 19 #define INST_STORE_ARRAY1 20 #define INST_STORE_ARRAY4 21 #define INST_STORE_ARRAY_STK 22 #define INST_STORE_STK 23 /* Opcodes 24 to 33 */ #define INST_INCR_SCALAR1 24 #define INST_INCR_SCALAR_STK 25 #define INST_INCR_ARRAY1 26 #define INST_INCR_ARRAY_STK 27 #define INST_INCR_STK 28 #define INST_INCR_SCALAR1_IMM 29 #define INST_INCR_SCALAR_STK_IMM 30 #define INST_INCR_ARRAY1_IMM 31 #define INST_INCR_ARRAY_STK_IMM 32 #define INST_INCR_STK_IMM 33 /* Opcodes 34 to 39 */ #define INST_JUMP1 34 #define INST_JUMP4 35 #define INST_JUMP_TRUE1 36 #define INST_JUMP_TRUE4 37 #define INST_JUMP_FALSE1 38 #define INST_JUMP_FALSE4 39 /* Opcodes 40 to 64 */ #define INST_LOR 40 #define INST_LAND 41 #define INST_BITOR 42 #define INST_BITXOR 43 #define INST_BITAND 44 #define INST_EQ 45 #define INST_NEQ 46 #define INST_LT 47 #define INST_GT 48 #define INST_LE 49 #define INST_GE 50 #define INST_LSHIFT 51 #define INST_RSHIFT 52 #define INST_ADD 53 #define INST_SUB 54 #define INST_MULT 55 #define INST_DIV 56 #define INST_MOD 57 #define INST_UPLUS 58 #define INST_UMINUS 59 #define INST_BITNOT 60 #define INST_LNOT 61 #define INST_CALL_BUILTIN_FUNC1 62 #define INST_CALL_FUNC1 63 #define INST_TRY_CVT_TO_NUMERIC 64 /* Opcodes 65 to 66 */ #define INST_BREAK 65 #define INST_CONTINUE 66 /* Opcodes 67 to 68 */ #define INST_FOREACH_START4 67 /* DEPRECATED */ #define INST_FOREACH_STEP4 68 /* DEPRECATED */ /* Opcodes 69 to 72 */ #define INST_BEGIN_CATCH4 69 #define INST_END_CATCH 70 #define INST_PUSH_RESULT 71 #define INST_PUSH_RETURN_CODE 72 /* Opcodes 73 to 78 */ #define INST_STR_EQ 73 #define INST_STR_NEQ 74 #define INST_STR_CMP 75 #define INST_STR_LEN 76 #define INST_STR_INDEX 77 #define INST_STR_MATCH 78 /* Opcodes 78 to 81 */ #define INST_LIST 79 #define INST_LIST_INDEX 80 #define INST_LIST_LENGTH 81 /* Opcodes 82 to 87 */ #define INST_APPEND_SCALAR1 82 #define INST_APPEND_SCALAR4 83 #define INST_APPEND_ARRAY1 84 #define INST_APPEND_ARRAY4 85 #define INST_APPEND_ARRAY_STK 86 #define INST_APPEND_STK 87 /* Opcodes 88 to 93 */ #define INST_LAPPEND_SCALAR1 88 #define INST_LAPPEND_SCALAR4 89 #define INST_LAPPEND_ARRAY1 90 #define INST_LAPPEND_ARRAY4 91 #define INST_LAPPEND_ARRAY_STK 92 #define INST_LAPPEND_STK 93 /* TIP #22 - LINDEX operator with flat arg list */ #define INST_LIST_INDEX_MULTI 94 /* * TIP #33 - 'lset' command. Code gen also required a Forth-like * OVER operation. */ #define INST_OVER 95 #define INST_LSET_LIST 96 #define INST_LSET_FLAT 97 /* TIP#90 - 'return' command. */ #define INST_RETURN_IMM 98 /* TIP#123 - exponentiation operator. */ #define INST_EXPON 99 /* TIP #157 - {*}... (word expansion) language syntax support. */ #define INST_EXPAND_START 100 #define INST_EXPAND_STKTOP 101 #define INST_INVOKE_EXPANDED 102 /* * TIP #57 - 'lassign' command. Code generation requires immediate * LINDEX and LRANGE operators. */ #define INST_LIST_INDEX_IMM 103 #define INST_LIST_RANGE_IMM 104 #define INST_START_CMD 105 #define INST_LIST_IN 106 #define INST_LIST_NOT_IN 107 #define INST_PUSH_RETURN_OPTIONS 108 #define INST_RETURN_STK 109 /* * Dictionary (TIP#111) related commands. */ #define INST_DICT_GET 110 #define INST_DICT_SET 111 #define INST_DICT_UNSET 112 #define INST_DICT_INCR_IMM 113 #define INST_DICT_APPEND 114 #define INST_DICT_LAPPEND 115 #define INST_DICT_FIRST 116 #define INST_DICT_NEXT 117 #define INST_DICT_DONE 118 #define INST_DICT_UPDATE_START 119 #define INST_DICT_UPDATE_END 120 /* * Instruction to support jumps defined by tables (instead of the classic * [switch] technique of chained comparisons). */ #define INST_JUMP_TABLE 121 /* * Instructions to support compilation of global, variable, upvar and * [namespace upvar]. */ #define INST_UPVAR 122 #define INST_NSUPVAR 123 #define INST_VARIABLE 124 /* Instruction to support compiling syntax error to bytecode */ #define INST_SYNTAX 125 /* Instruction to reverse N items on top of stack */ #define INST_REVERSE 126 /* regexp instruction */ #define INST_REGEXP 127 /* For [info exists] compilation */ #define INST_EXIST_SCALAR 128 #define INST_EXIST_ARRAY 129 #define INST_EXIST_ARRAY_STK 130 #define INST_EXIST_STK 131 /* For [subst] compilation */ #define INST_NOP 132 #define INST_RETURN_CODE_BRANCH 133 /* For [unset] compilation */ #define INST_UNSET_SCALAR 134 #define INST_UNSET_ARRAY 135 #define INST_UNSET_ARRAY_STK 136 #define INST_UNSET_STK 137 /* For [dict with], [dict exists], [dict create] and [dict merge] */ #define INST_DICT_EXPAND 138 #define INST_DICT_RECOMBINE_STK 139 #define INST_DICT_RECOMBINE_IMM 140 #define INST_DICT_EXISTS 141 #define INST_DICT_VERIFY 142 /* For [string map] and [regsub] compilation */ #define INST_STR_MAP 143 #define INST_STR_FIND 144 #define INST_STR_FIND_LAST 145 #define INST_STR_RANGE_IMM 146 #define INST_STR_RANGE 147 /* For operations to do with coroutines and other NRE-manipulators */ #define INST_YIELD 148 #define INST_COROUTINE_NAME 149 #define INST_TAILCALL 150 /* For compilation of basic information operations */ #define INST_NS_CURRENT 151 #define INST_INFO_LEVEL_NUM 152 #define INST_INFO_LEVEL_ARGS 153 #define INST_RESOLVE_COMMAND 154 /* For compilation relating to TclOO */ #define INST_TCLOO_SELF 155 #define INST_TCLOO_CLASS 156 #define INST_TCLOO_NS 157 #define INST_TCLOO_IS_OBJECT 158 /* For compilation of [array] subcommands */ #define INST_ARRAY_EXISTS_STK 159 #define INST_ARRAY_EXISTS_IMM 160 #define INST_ARRAY_MAKE_STK 161 #define INST_ARRAY_MAKE_IMM 162 #define INST_INVOKE_REPLACE 163 #define INST_LIST_CONCAT 164 #define INST_EXPAND_DROP 165 /* New foreach implementation */ #define INST_FOREACH_START 166 #define INST_FOREACH_STEP 167 #define INST_FOREACH_END 168 #define INST_LMAP_COLLECT 169 /* For compilation of [string trim] and related */ #define INST_STR_TRIM 170 #define INST_STR_TRIM_LEFT 171 #define INST_STR_TRIM_RIGHT 172 #define INST_CONCAT_STK 173 #define INST_STR_UPPER 174 #define INST_STR_LOWER 175 #define INST_STR_TITLE 176 #define INST_STR_REPLACE 177 #define INST_ORIGIN_COMMAND 178 #define INST_TCLOO_NEXT 179 #define INST_TCLOO_NEXT_CLASS 180 #define INST_YIELD_TO_INVOKE 181 #define INST_NUM_TYPE 182 #define INST_TRY_CVT_TO_BOOLEAN 183 #define INST_STR_CLASS 184 #define INST_LAPPEND_LIST 185 #define INST_LAPPEND_LIST_ARRAY 186 #define INST_LAPPEND_LIST_ARRAY_STK 187 #define INST_LAPPEND_LIST_STK 188 /* The last opcode */ #define LAST_INST_OPCODE 188 /* * Table describing the Tcl bytecode instructions: their name (for displaying * code), total number of code bytes required (including operand bytes), and a * description of the type of each operand. These operand types include signed * and unsigned integers of length one and four bytes. The unsigned integers * are used for indexes or for, e.g., the count of objects to push in a "push" * instruction. */ #define MAX_INSTRUCTION_OPERANDS 2 typedef enum InstOperandType { OPERAND_NONE, OPERAND_INT1, /* One byte signed integer. */ OPERAND_INT4, /* Four byte signed integer. */ OPERAND_UINT1, /* One byte unsigned integer. */ OPERAND_UINT4, /* Four byte unsigned integer. */ OPERAND_IDX4, /* Four byte signed index (actually an * integer, but displayed differently.) */ OPERAND_LVT1, /* One byte unsigned index into the local * variable table. */ OPERAND_LVT4, /* Four byte unsigned index into the local * variable table. */ OPERAND_AUX4, /* Four byte unsigned index into the aux data * table. */ OPERAND_OFFSET1, /* One byte signed jump offset. */ OPERAND_OFFSET4, /* Four byte signed jump offset. */ OPERAND_LIT1, /* One byte unsigned index into table of * literals. */ OPERAND_LIT4, /* Four byte unsigned index into table of * literals. */ OPERAND_SCLS1 /* Index into tclStringClassTable. */ } InstOperandType; typedef struct InstructionDesc { const char *name; /* Name of instruction. */ int numBytes; /* Total number of bytes for instruction. */ int stackEffect; /* The worst-case balance stack effect of the * instruction, used for stack requirements * computations. The value INT_MIN signals * that the instruction's worst case effect is * (1-opnd1). */ int numOperands; /* Number of operands. */ InstOperandType opTypes[MAX_INSTRUCTION_OPERANDS]; /* The type of each operand. */ } InstructionDesc; MODULE_SCOPE InstructionDesc const tclInstructionTable[]; /* * Constants used by INST_STRING_CLASS to indicate character classes. These * correspond closely by name with what [string is] can support, but there is * no requirement to keep the values the same. */ typedef enum InstStringClassType { STR_CLASS_ALNUM, /* Unicode alphabet or digit characters. */ STR_CLASS_ALPHA, /* Unicode alphabet characters. */ STR_CLASS_ASCII, /* Characters in range U+000000..U+00007F. */ STR_CLASS_CONTROL, /* Unicode control characters. */ STR_CLASS_DIGIT, /* Unicode digit characters. */ STR_CLASS_GRAPH, /* Unicode printing characters, excluding * space. */ STR_CLASS_LOWER, /* Unicode lower-case alphabet characters. */ STR_CLASS_PRINT, /* Unicode printing characters, including * spaces. */ STR_CLASS_PUNCT, /* Unicode punctuation characters. */ STR_CLASS_SPACE, /* Unicode space characters. */ STR_CLASS_UPPER, /* Unicode upper-case alphabet characters. */ STR_CLASS_WORD, /* Unicode word (alphabetic, digit, connector * punctuation) characters. */ STR_CLASS_XDIGIT /* Characters that can be used as digits in * hexadecimal numbers ([0-9A-Fa-f]). */ } InstStringClassType; typedef struct StringClassDesc { const char *name; /* Name of the class. */ int (*comparator)(int); /* Function to test if a single unicode * character is a member of the class. */ } StringClassDesc; MODULE_SCOPE StringClassDesc const tclStringClassTable[]; /* * Compilation of some Tcl constructs such as if commands and the logical or * (||) and logical and (&&) operators in expressions requires the generation * of forward jumps. Since the PC target of these jumps isn't known when the * jumps are emitted, we record the offset of each jump in an array of * JumpFixup structures. There is one array for each sequence of jumps to one * target PC. When we learn the target PC, we update the jumps with the * correct distance. Also, if the distance is too great (> 127 bytes), we * replace the single-byte jump with a four byte jump instruction, move the * instructions after the jump down, and update the code offsets for any * commands between the jump and the target. */ typedef enum { TCL_UNCONDITIONAL_JUMP, TCL_TRUE_JUMP, TCL_FALSE_JUMP } TclJumpType; typedef struct JumpFixup { TclJumpType jumpType; /* Indicates the kind of jump. */ int codeOffset; /* Offset of the first byte of the one-byte * forward jump's code. */ int cmdIndex; /* Index of the first command after the one * for which the jump was emitted. Used to * update the code offsets for subsequent * commands if the two-byte jump at jumpPc * must be replaced with a five-byte one. */ int exceptIndex; /* Index of the first range entry in the * ExceptionRange array after the current one. * This field is used to adjust the code * offsets in subsequent ExceptionRange * records when a jump is grown from 2 bytes * to 5 bytes. */ } JumpFixup; #define JUMPFIXUP_INIT_ENTRIES 10 typedef struct JumpFixupArray { JumpFixup *fixup; /* Points to start of jump fixup array. */ int next; /* Index of next free array entry. */ int end; /* Index of last usable entry in array. */ int mallocedArray; /* 1 if array was expanded and fixups points * into the heap, else 0. */ JumpFixup staticFixupSpace[JUMPFIXUP_INIT_ENTRIES]; /* Initial storage for jump fixup array. */ } JumpFixupArray; /* * The structure describing one variable list of a foreach command. Note that * only foreach commands inside procedure bodies are compiled inline so a * ForeachVarList structure always describes local variables. Furthermore, * only scalar variables are supported for inline-compiled foreach loops. */ typedef struct ForeachVarList { int numVars; /* The number of variables in the list. */ int varIndexes[1]; /* An array of the indexes ("slot numbers") * for each variable in the procedure's array * of local variables. Only scalar variables * are supported. The actual size of this * field will be large enough to numVars * indexes. THIS MUST BE THE LAST FIELD IN THE * STRUCTURE! */ } ForeachVarList; /* * Structure used to hold information about a foreach command that is needed * during program execution. These structures are stored in CompileEnv and * ByteCode structures as auxiliary data. */ typedef struct ForeachInfo { int numLists; /* The number of both the variable and value * lists of the foreach command. */ int firstValueTemp; /* Index of the first temp var in a proc frame * used to point to a value list. */ int loopCtTemp; /* Index of temp var in a proc frame holding * the loop's iteration count. Used to * determine next value list element to assign * each loop var. */ ForeachVarList *varLists[1];/* An array of pointers to ForeachVarList * structures describing each var list. The * actual size of this field will be large * enough to numVars indexes. THIS MUST BE THE * LAST FIELD IN THE STRUCTURE! */ } ForeachInfo; /* * Structure used to hold information about a switch command that is needed * during program execution. These structures are stored in CompileEnv and * ByteCode structures as auxiliary data. */ typedef struct JumptableInfo { Tcl_HashTable hashTable; /* Hash that maps strings to signed ints (PC * offsets). */ } JumptableInfo; MODULE_SCOPE const AuxDataType tclJumptableInfoType; #define JUMPTABLEINFO(envPtr, index) \ ((JumptableInfo*)((envPtr)->auxDataArrayPtr[TclGetUInt4AtPtr(index)].clientData)) /* * Structure used to hold information about a [dict update] command that is * needed during program execution. These structures are stored in CompileEnv * and ByteCode structures as auxiliary data. */ typedef struct { int length; /* Size of array */ int varIndices[1]; /* Array of variable indices to manage when * processing the start and end of a [dict * update]. There is really more than one * entry, and the structure is allocated to * take account of this. MUST BE LAST FIELD IN * STRUCTURE. */ } DictUpdateInfo; /* * ClientData type used by the math operator commands. */ typedef struct { const char *op; /* Do not call it 'operator': C++ reserved */ const char *expected; union { int numArgs; int identity; } i; } TclOpCmdClientData; /* *---------------------------------------------------------------- * Procedures exported by tclBasic.c to be used within the engine. *---------------------------------------------------------------- */ MODULE_SCOPE Tcl_ObjCmdProc TclNRInterpCoroutine; /* *---------------------------------------------------------------- * Procedures exported by the engine to be used by tclBasic.c *---------------------------------------------------------------- */ MODULE_SCOPE ByteCode * TclCompileObj(Tcl_Interp *interp, Tcl_Obj *objPtr, const CmdFrame *invoker, int word); /* *---------------------------------------------------------------- * Procedures shared among Tcl bytecode compilation and execution modules but * not used outside: *---------------------------------------------------------------- */ MODULE_SCOPE int TclAttemptCompileProc(Tcl_Interp *interp, Tcl_Parse *parsePtr, int depth, Command *cmdPtr, CompileEnv *envPtr); MODULE_SCOPE void TclCleanupByteCode(ByteCode *codePtr); MODULE_SCOPE void TclCleanupStackForBreakContinue(CompileEnv *envPtr, ExceptionAux *auxPtr); MODULE_SCOPE void TclCompileCmdWord(Tcl_Interp *interp, Tcl_Token *tokenPtr, int count, CompileEnv *envPtr); MODULE_SCOPE void TclCompileExpr(Tcl_Interp *interp, const char *script, int numBytes, CompileEnv *envPtr, int optimize); MODULE_SCOPE void TclCompileExprWords(Tcl_Interp *interp, Tcl_Token *tokenPtr, int numWords, CompileEnv *envPtr); MODULE_SCOPE void TclCompileInvocation(Tcl_Interp *interp, Tcl_Token *tokenPtr, Tcl_Obj *cmdObj, int numWords, CompileEnv *envPtr); MODULE_SCOPE void TclCompileScript(Tcl_Interp *interp, const char *script, int numBytes, CompileEnv *envPtr); MODULE_SCOPE void TclCompileSyntaxError(Tcl_Interp *interp, CompileEnv *envPtr); MODULE_SCOPE void TclCompileTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr, int count, CompileEnv *envPtr); MODULE_SCOPE void TclCompileVarSubst(Tcl_Interp *interp, Tcl_Token *tokenPtr, CompileEnv *envPtr); MODULE_SCOPE int TclCreateAuxData(ClientData clientData, const AuxDataType *typePtr, CompileEnv *envPtr); MODULE_SCOPE int TclCreateExceptRange(ExceptionRangeType type, CompileEnv *envPtr); MODULE_SCOPE ExecEnv * TclCreateExecEnv(Tcl_Interp *interp, int size); MODULE_SCOPE Tcl_Obj * TclCreateLiteral(Interp *iPtr, char *bytes, int length, unsigned int hash, int *newPtr, Namespace *nsPtr, int flags, LiteralEntry **globalPtrPtr); MODULE_SCOPE void TclDeleteExecEnv(ExecEnv *eePtr); MODULE_SCOPE void TclDeleteLiteralTable(Tcl_Interp *interp, LiteralTable *tablePtr); MODULE_SCOPE void TclEmitForwardJump(CompileEnv *envPtr, TclJumpType jumpType, JumpFixup *jumpFixupPtr); MODULE_SCOPE void TclEmitInvoke(CompileEnv *envPtr, int opcode, ...); MODULE_SCOPE ExceptionRange * TclGetExceptionRangeForPc(unsigned char *pc, int catchOnly, ByteCode *codePtr); MODULE_SCOPE void TclExpandJumpFixupArray(JumpFixupArray *fixupArrayPtr); MODULE_SCOPE int TclNRExecuteByteCode(Tcl_Interp *interp, ByteCode *codePtr); MODULE_SCOPE Tcl_Obj * TclFetchLiteral(CompileEnv *envPtr, unsigned int index); MODULE_SCOPE int TclFindCompiledLocal(const char *name, int nameChars, int create, CompileEnv *envPtr); MODULE_SCOPE int TclFixupForwardJump(CompileEnv *envPtr, JumpFixup *jumpFixupPtr, int jumpDist, int distThreshold); MODULE_SCOPE void TclFreeCompileEnv(CompileEnv *envPtr); MODULE_SCOPE void TclFreeJumpFixupArray(JumpFixupArray *fixupArrayPtr); MODULE_SCOPE void TclInitByteCodeObj(Tcl_Obj *objPtr, CompileEnv *envPtr); MODULE_SCOPE void TclInitCompileEnv(Tcl_Interp *interp, CompileEnv *envPtr, const char *string, int numBytes, const CmdFrame *invoker, int word); MODULE_SCOPE void TclInitJumpFixupArray(JumpFixupArray *fixupArrayPtr); MODULE_SCOPE void TclInitLiteralTable(LiteralTable *tablePtr); MODULE_SCOPE ExceptionRange *TclGetInnermostExceptionRange(CompileEnv *envPtr, int returnCode, ExceptionAux **auxPtrPtr); MODULE_SCOPE void TclAddLoopBreakFixup(CompileEnv *envPtr, ExceptionAux *auxPtr); MODULE_SCOPE void TclAddLoopContinueFixup(CompileEnv *envPtr, ExceptionAux *auxPtr); MODULE_SCOPE void TclFinalizeLoopExceptionRange(CompileEnv *envPtr, int range); #ifdef TCL_COMPILE_STATS MODULE_SCOPE char * TclLiteralStats(LiteralTable *tablePtr); MODULE_SCOPE int TclLog2(int value); #endif MODULE_SCOPE int TclLocalScalar(const char *bytes, int numBytes, CompileEnv *envPtr); MODULE_SCOPE int TclLocalScalarFromToken(Tcl_Token *tokenPtr, CompileEnv *envPtr); MODULE_SCOPE void TclOptimizeBytecode(void *envPtr); #ifdef TCL_COMPILE_DEBUG MODULE_SCOPE void TclPrintByteCodeObj(Tcl_Interp *interp, Tcl_Obj *objPtr); #endif MODULE_SCOPE int TclPrintInstruction(ByteCode *codePtr, const unsigned char *pc); MODULE_SCOPE void TclPrintObject(FILE *outFile, Tcl_Obj *objPtr, int maxChars); MODULE_SCOPE void TclPrintSource(FILE *outFile, const char *string, int maxChars); MODULE_SCOPE void TclPushVarName(Tcl_Interp *interp, Tcl_Token *varTokenPtr, CompileEnv *envPtr, int flags, int *localIndexPtr, int *isScalarPtr); MODULE_SCOPE void TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr); MODULE_SCOPE void TclInvalidateCmdLiteral(Tcl_Interp *interp, const char *name, Namespace *nsPtr); MODULE_SCOPE int TclSingleOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclSortingOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclVariadicOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclNoIdentOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); #ifdef TCL_COMPILE_DEBUG MODULE_SCOPE void TclVerifyGlobalLiteralTable(Interp *iPtr); MODULE_SCOPE void TclVerifyLocalLiteralTable(CompileEnv *envPtr); #endif MODULE_SCOPE int TclWordKnownAtCompileTime(Tcl_Token *tokenPtr, Tcl_Obj *valuePtr); MODULE_SCOPE void TclLogCommandInfo(Tcl_Interp *interp, const char *script, const char *command, int length, const unsigned char *pc, Tcl_Obj **tosPtr); MODULE_SCOPE Tcl_Obj *TclGetInnerContext(Tcl_Interp *interp, const unsigned char *pc, Tcl_Obj **tosPtr); MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst); MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData, register Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int isLambda); /* *---------------------------------------------------------------- * Macros and flag values used by Tcl bytecode compilation and execution * modules inside the Tcl core but not used outside. *---------------------------------------------------------------- */ /* * Simplified form to access AuxData. * * ClientData TclFetchAuxData(CompileEng *envPtr, int index); */ #define TclFetchAuxData(envPtr, index) \ (envPtr)->auxDataArrayPtr[(index)].clientData #define LITERAL_ON_HEAP 0x01 #define LITERAL_CMD_NAME 0x02 /* * Form of TclRegisterLiteral with flags == 0. In that case, it is safe to * cast away constness, and it is cleanest to do that here, all in one place. * * int TclRegisterNewLiteral(CompileEnv *envPtr, const char *bytes, * int length); */ #define TclRegisterNewLiteral(envPtr, bytes, length) \ TclRegisterLiteral(envPtr, (char *)(bytes), length, /*flags*/ 0) /* * Form of TclRegisterLiteral with flags == LITERAL_CMD_NAME. In that case, it * is safe to cast away constness, and it is cleanest to do that here, all in * one place. * * int TclRegisterNewNSLiteral(CompileEnv *envPtr, const char *bytes, * int length); */ #define TclRegisterNewCmdLiteral(envPtr, bytes, length) \ TclRegisterLiteral(envPtr, (char *)(bytes), length, LITERAL_CMD_NAME) /* * Macro used to manually adjust the stack requirements; used in cases where * the stack effect cannot be computed from the opcode and its operands, but * is still known at compile time. * * void TclAdjustStackDepth(int delta, CompileEnv *envPtr); */ #define TclAdjustStackDepth(delta, envPtr) \ do { \ if ((delta) < 0) { \ if ((envPtr)->maxStackDepth < (envPtr)->currStackDepth) { \ (envPtr)->maxStackDepth = (envPtr)->currStackDepth; \ } \ } \ (envPtr)->currStackDepth += (delta); \ } while (0) #define TclGetStackDepth(envPtr) \ ((envPtr)->currStackDepth) #define TclSetStackDepth(depth, envPtr) \ (envPtr)->currStackDepth = (depth) #define TclCheckStackDepth(depth, envPtr) \ do { \ int dd = (depth); \ if (dd != (envPtr)->currStackDepth) { \ Tcl_Panic("bad stack depth computations: is %i, should be %i", \ (envPtr)->currStackDepth, dd); \ } \ } while (0) /* * Macro used to update the stack requirements. It is called by the macros * TclEmitOpCode, TclEmitInst1 and TclEmitInst4. * Remark that the very last instruction of a bytecode always reduces the * stack level: INST_DONE or INST_POP, so that the maxStackdepth is always * updated. * * void TclUpdateStackReqs(unsigned char op, int i, CompileEnv *envPtr); */ #define TclUpdateStackReqs(op, i, envPtr) \ do { \ int delta = tclInstructionTable[(op)].stackEffect; \ if (delta) { \ if (delta == INT_MIN) { \ delta = 1 - (i); \ } \ TclAdjustStackDepth(delta, envPtr); \ } \ } while (0) /* * Macros used to update the flag that indicates if we are at the start of a * command, based on whether the opcode is INST_START_COMMAND. * * void TclUpdateAtCmdStart(unsigned char op, CompileEnv *envPtr); */ #define TclUpdateAtCmdStart(op, envPtr) \ if ((envPtr)->atCmdStart < 2) { \ (envPtr)->atCmdStart = ((op) == INST_START_CMD ? 1 : 0); \ } /* * Macro to emit an opcode byte into a CompileEnv's code array. The ANSI C * "prototype" for this macro is: * * void TclEmitOpcode(unsigned char op, CompileEnv *envPtr); */ #define TclEmitOpcode(op, envPtr) \ do { \ if ((envPtr)->codeNext == (envPtr)->codeEnd) { \ TclExpandCodeArray(envPtr); \ } \ *(envPtr)->codeNext++ = (unsigned char) (op); \ TclUpdateAtCmdStart(op, envPtr); \ TclUpdateStackReqs(op, 0, envPtr); \ } while (0) /* * Macros to emit an integer operand. The ANSI C "prototype" for these macros * are: * * void TclEmitInt1(int i, CompileEnv *envPtr); * void TclEmitInt4(int i, CompileEnv *envPtr); */ #define TclEmitInt1(i, envPtr) \ do { \ if ((envPtr)->codeNext == (envPtr)->codeEnd) { \ TclExpandCodeArray(envPtr); \ } \ *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i)); \ } while (0) #define TclEmitInt4(i, envPtr) \ do { \ if (((envPtr)->codeNext + 4) > (envPtr)->codeEnd) { \ TclExpandCodeArray(envPtr); \ } \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) >> 24); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) >> 16); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) >> 8); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) ); \ } while (0) /* * Macros to emit an instruction with signed or unsigned integer operands. * Four byte integers are stored in "big-endian" order with the high order * byte stored at the lowest address. The ANSI C "prototypes" for these macros * are: * * void TclEmitInstInt1(unsigned char op, int i, CompileEnv *envPtr); * void TclEmitInstInt4(unsigned char op, int i, CompileEnv *envPtr); */ #define TclEmitInstInt1(op, i, envPtr) \ do { \ if (((envPtr)->codeNext + 2) > (envPtr)->codeEnd) { \ TclExpandCodeArray(envPtr); \ } \ *(envPtr)->codeNext++ = (unsigned char) (op); \ *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i)); \ TclUpdateAtCmdStart(op, envPtr); \ TclUpdateStackReqs(op, i, envPtr); \ } while (0) #define TclEmitInstInt4(op, i, envPtr) \ do { \ if (((envPtr)->codeNext + 5) > (envPtr)->codeEnd) { \ TclExpandCodeArray(envPtr); \ } \ *(envPtr)->codeNext++ = (unsigned char) (op); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) >> 24); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) >> 16); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) >> 8); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) ); \ TclUpdateAtCmdStart(op, envPtr); \ TclUpdateStackReqs(op, i, envPtr); \ } while (0) /* * Macro to push a Tcl object onto the Tcl evaluation stack. It emits the * object's one or four byte array index into the CompileEnv's code array. * These support, respectively, a maximum of 256 (2**8) and 2**32 objects in a * CompileEnv. The ANSI C "prototype" for this macro is: * * void TclEmitPush(int objIndex, CompileEnv *envPtr); */ #define TclEmitPush(objIndex, envPtr) \ do { \ register int objIndexCopy = (objIndex); \ if (objIndexCopy <= 255) { \ TclEmitInstInt1(INST_PUSH1, objIndexCopy, (envPtr)); \ } else { \ TclEmitInstInt4(INST_PUSH4, objIndexCopy, (envPtr)); \ } \ } while (0) /* * Macros to update a (signed or unsigned) integer starting at a pointer. The * two variants depend on the number of bytes. The ANSI C "prototypes" for * these macros are: * * void TclStoreInt1AtPtr(int i, unsigned char *p); * void TclStoreInt4AtPtr(int i, unsigned char *p); */ #define TclStoreInt1AtPtr(i, p) \ *(p) = (unsigned char) ((unsigned int) (i)) #define TclStoreInt4AtPtr(i, p) \ do { \ *(p) = (unsigned char) ((unsigned int) (i) >> 24); \ *(p+1) = (unsigned char) ((unsigned int) (i) >> 16); \ *(p+2) = (unsigned char) ((unsigned int) (i) >> 8); \ *(p+3) = (unsigned char) ((unsigned int) (i) ); \ } while (0) /* * Macros to update instructions at a particular pc with a new op code and a * (signed or unsigned) int operand. The ANSI C "prototypes" for these macros * are: * * void TclUpdateInstInt1AtPc(unsigned char op, int i, unsigned char *pc); * void TclUpdateInstInt4AtPc(unsigned char op, int i, unsigned char *pc); */ #define TclUpdateInstInt1AtPc(op, i, pc) \ do { \ *(pc) = (unsigned char) (op); \ TclStoreInt1AtPtr((i), ((pc)+1)); \ } while (0) #define TclUpdateInstInt4AtPc(op, i, pc) \ do { \ *(pc) = (unsigned char) (op); \ TclStoreInt4AtPtr((i), ((pc)+1)); \ } while (0) /* * Macro to fix up a forward jump to point to the current code-generation * position in the bytecode being created (the most common case). The ANSI C * "prototypes" for this macro is: * * int TclFixupForwardJumpToHere(CompileEnv *envPtr, JumpFixup *fixupPtr, * int threshold); */ #define TclFixupForwardJumpToHere(envPtr, fixupPtr, threshold) \ TclFixupForwardJump((envPtr), (fixupPtr), \ (envPtr)->codeNext-(envPtr)->codeStart-(fixupPtr)->codeOffset, \ (threshold)) /* * Macros to get a signed integer (GET_INT{1,2}) or an unsigned int * (GET_UINT{1,2}) from a pointer. There are two variants for each return type * that depend on the number of bytes fetched. The ANSI C "prototypes" for * these macros are: * * int TclGetInt1AtPtr(unsigned char *p); * int TclGetInt4AtPtr(unsigned char *p); * unsigned int TclGetUInt1AtPtr(unsigned char *p); * unsigned int TclGetUInt4AtPtr(unsigned char *p); */ /* * The TclGetInt1AtPtr macro is tricky because we want to do sign extension on * the 1-byte value. Unfortunately the "char" type isn't signed on all * platforms so sign-extension doesn't always happen automatically. Sometimes * we can explicitly declare the pointer to be signed, but other times we have * to explicitly sign-extend the value in software. */ #ifndef __CHAR_UNSIGNED__ # define TclGetInt1AtPtr(p) ((int) *((char *) p)) #elif defined(HAVE_SIGNED_CHAR) # define TclGetInt1AtPtr(p) ((int) *((signed char *) p)) #else # define TclGetInt1AtPtr(p) \ (((int) *((char *) p)) | ((*(p) & 0200) ? (-256) : 0)) #endif #define TclGetInt4AtPtr(p) \ (((int) TclGetInt1AtPtr(p) << 24) | \ (*((p)+1) << 16) | \ (*((p)+2) << 8) | \ (*((p)+3))) #define TclGetUInt1AtPtr(p) \ ((unsigned int) *(p)) #define TclGetUInt4AtPtr(p) \ ((unsigned int) (*(p) << 24) | \ (*((p)+1) << 16) | \ (*((p)+2) << 8) | \ (*((p)+3))) /* * Macros used to compute the minimum and maximum of two integers. The ANSI C * "prototypes" for these macros are: * * int TclMin(int i, int j); * int TclMax(int i, int j); */ #define TclMin(i, j) ((((int) i) < ((int) j))? (i) : (j)) #define TclMax(i, j) ((((int) i) > ((int) j))? (i) : (j)) /* * Convenience macros for use when compiling bodies of commands. The ANSI C * "prototype" for these macros are: * * static void BODY(Tcl_Token *tokenPtr, int word); */ #define BODY(tokenPtr, word) \ SetLineInformation((word)); \ TclCompileCmdWord(interp, (tokenPtr)+1, (tokenPtr)->numComponents, \ envPtr) /* * Convenience macro for use when compiling tokens to be pushed. The ANSI C * "prototype" for this macro is: * * static void CompileTokens(CompileEnv *envPtr, Tcl_Token *tokenPtr, * Tcl_Interp *interp); */ #define CompileTokens(envPtr, tokenPtr, interp) \ TclCompileTokens((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \ (envPtr)); /* * Convenience macros for use when pushing literals. The ANSI C "prototype" for * these macros are: * * static void PushLiteral(CompileEnv *envPtr, * const char *string, int length); * static void PushStringLiteral(CompileEnv *envPtr, * const char *string); */ #define PushLiteral(envPtr, string, length) \ TclEmitPush(TclRegisterNewLiteral((envPtr), (string), (length)), (envPtr)) #define PushStringLiteral(envPtr, string) \ PushLiteral((envPtr), (string), (int) (sizeof(string "") - 1)) /* * Macro to advance to the next token; it is more mnemonic than the address * arithmetic that it replaces. The ANSI C "prototype" for this macro is: * * static Tcl_Token * TokenAfter(Tcl_Token *tokenPtr); */ #define TokenAfter(tokenPtr) \ ((tokenPtr) + ((tokenPtr)->numComponents + 1)) /* * Macro to get the offset to the next instruction to be issued. The ANSI C * "prototype" for this macro is: * * static int CurrentOffset(CompileEnv *envPtr); */ #define CurrentOffset(envPtr) \ ((envPtr)->codeNext - (envPtr)->codeStart) /* * Note: the exceptDepth is a bit of a misnomer: TEBC only needs the * maximal depth of nested CATCH ranges in order to alloc runtime * memory. These macros should compute precisely that? OTOH, the nesting depth * of LOOP ranges is an interesting datum for debugging purposes, and that is * what we compute now. * * static int ExceptionRangeStarts(CompileEnv *envPtr, int index); * static void ExceptionRangeEnds(CompileEnv *envPtr, int index); * static void ExceptionRangeTarget(CompileEnv *envPtr, int index, LABEL); */ #define ExceptionRangeStarts(envPtr, index) \ (((envPtr)->exceptDepth++), \ ((envPtr)->maxExceptDepth = \ TclMax((envPtr)->exceptDepth, (envPtr)->maxExceptDepth)), \ ((envPtr)->exceptArrayPtr[(index)].codeOffset = CurrentOffset(envPtr))) #define ExceptionRangeEnds(envPtr, index) \ (((envPtr)->exceptDepth--), \ ((envPtr)->exceptArrayPtr[(index)].numCodeBytes = \ CurrentOffset(envPtr) - (envPtr)->exceptArrayPtr[(index)].codeOffset)) #define ExceptionRangeTarget(envPtr, index, targetType) \ ((envPtr)->exceptArrayPtr[(index)].targetType = CurrentOffset(envPtr)) /* * Check if there is an LVT for compiled locals */ #define EnvHasLVT(envPtr) \ (envPtr->procPtr || envPtr->iPtr->varFramePtr->localCachePtr) /* * Macros for making it easier to deal with tokens and DStrings. */ #define TclDStringAppendToken(dsPtr, tokenPtr) \ Tcl_DStringAppend((dsPtr), (tokenPtr)->start, (tokenPtr)->size) #define TclRegisterDStringLiteral(envPtr, dsPtr) \ TclRegisterLiteral(envPtr, Tcl_DStringValue(dsPtr), \ Tcl_DStringLength(dsPtr), /*flags*/ 0) /* * Macro that encapsulates an efficiency trick that avoids a function call for * the simplest of compiles. The ANSI C "prototype" for this macro is: * * static void CompileWord(CompileEnv *envPtr, Tcl_Token *tokenPtr, * Tcl_Interp *interp, int word); */ #define CompileWord(envPtr, tokenPtr, interp, word) \ if ((tokenPtr)->type == TCL_TOKEN_SIMPLE_WORD) { \ PushLiteral((envPtr), (tokenPtr)[1].start, (tokenPtr)[1].size); \ } else { \ SetLineInformation((word)); \ CompileTokens((envPtr), (tokenPtr), (interp)); \ } /* * TIP #280: Remember the per-word line information of the current command. An * index is used instead of a pointer as recursive compilation may reallocate, * i.e. move, the array. This is also the reason to save the nuloc now, it may * change during the course of the function. * * Macro to encapsulate the variable definition and setup. */ #define DefineLineInformation \ ExtCmdLoc *mapPtr = envPtr->extCmdMapPtr; \ int eclIndex = mapPtr->nuloc - 1 #define SetLineInformation(word) \ envPtr->line = mapPtr->loc[eclIndex].line[(word)]; \ envPtr->clNext = mapPtr->loc[eclIndex].next[(word)] #define PushVarNameWord(i,v,e,f,l,sc,word) \ SetLineInformation(word); \ TclPushVarName(i,v,e,f,l,sc) /* * Often want to issue one of two versions of an instruction based on whether * the argument will fit in a single byte or not. This makes it much clearer. */ #define Emit14Inst(nm,idx,envPtr) \ if (idx <= 255) { \ TclEmitInstInt1(nm##1,idx,envPtr); \ } else { \ TclEmitInstInt4(nm##4,idx,envPtr); \ } /* * How to get an anonymous local variable (used for holding temporary values * off the stack) or a local simple scalar. */ #define AnonymousLocal(envPtr) \ (TclFindCompiledLocal(NULL, /*nameChars*/ 0, /*create*/ 1, (envPtr))) #define LocalScalar(chars,len,envPtr) \ TclLocalScalar(chars, len, envPtr) #define LocalScalarFromToken(tokenPtr,envPtr) \ TclLocalScalarFromToken(tokenPtr, envPtr) /* * Flags bits used by TclPushVarName. */ #define TCL_NO_LARGE_INDEX 1 /* Do not return localIndex value > 255 */ #define TCL_NO_ELEMENT 2 /* Do not push the array element. */ /* * DTrace probe macros (NOPs if DTrace support is not enabled). */ /* * Define the following macros to enable debug logging of the DTrace proc, * cmd, and inst probes. Note that this does _not_ require a platform with * DTrace, it simply logs all probe output to /tmp/tclDTraceDebug-[pid].log. * * If the second macro is defined, logging to file starts immediately, * otherwise only after the first call to [tcl::dtrace]. Note that the debug * probe data is always computed, even when it is not logged to file. * * Defining the third macro enables debug logging of inst probes (disabled * by default due to the significant performance impact). */ /* #define TCL_DTRACE_DEBUG 1 #define TCL_DTRACE_DEBUG_LOG_ENABLED 1 #define TCL_DTRACE_DEBUG_INST_PROBES 1 */ #if !(defined(TCL_DTRACE_DEBUG) && defined(__GNUC__)) #ifdef USE_DTRACE #if defined(__GNUC__) && __GNUC__ > 2 /* * Use gcc branch prediction hint to minimize cost of DTrace ENABLED checks. */ #define unlikely(x) (__builtin_expect((x), 0)) #else #define unlikely(x) (x) #endif #define TCL_DTRACE_PROC_ENTRY_ENABLED() unlikely(TCL_PROC_ENTRY_ENABLED()) #define TCL_DTRACE_PROC_RETURN_ENABLED() unlikely(TCL_PROC_RETURN_ENABLED()) #define TCL_DTRACE_PROC_RESULT_ENABLED() unlikely(TCL_PROC_RESULT_ENABLED()) #define TCL_DTRACE_PROC_ARGS_ENABLED() unlikely(TCL_PROC_ARGS_ENABLED()) #define TCL_DTRACE_PROC_INFO_ENABLED() unlikely(TCL_PROC_INFO_ENABLED()) #define TCL_DTRACE_PROC_ENTRY(a0, a1, a2) TCL_PROC_ENTRY(a0, a1, a2) #define TCL_DTRACE_PROC_RETURN(a0, a1) TCL_PROC_RETURN(a0, a1) #define TCL_DTRACE_PROC_RESULT(a0, a1, a2, a3) TCL_PROC_RESULT(a0, a1, a2, a3) #define TCL_DTRACE_PROC_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ TCL_PROC_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) #define TCL_DTRACE_PROC_INFO(a0, a1, a2, a3, a4, a5, a6, a7) \ TCL_PROC_INFO(a0, a1, a2, a3, a4, a5, a6, a7) #define TCL_DTRACE_CMD_ENTRY_ENABLED() unlikely(TCL_CMD_ENTRY_ENABLED()) #define TCL_DTRACE_CMD_RETURN_ENABLED() unlikely(TCL_CMD_RETURN_ENABLED()) #define TCL_DTRACE_CMD_RESULT_ENABLED() unlikely(TCL_CMD_RESULT_ENABLED()) #define TCL_DTRACE_CMD_ARGS_ENABLED() unlikely(TCL_CMD_ARGS_ENABLED()) #define TCL_DTRACE_CMD_INFO_ENABLED() unlikely(TCL_CMD_INFO_ENABLED()) #define TCL_DTRACE_CMD_ENTRY(a0, a1, a2) TCL_CMD_ENTRY(a0, a1, a2) #define TCL_DTRACE_CMD_RETURN(a0, a1) TCL_CMD_RETURN(a0, a1) #define TCL_DTRACE_CMD_RESULT(a0, a1, a2, a3) TCL_CMD_RESULT(a0, a1, a2, a3) #define TCL_DTRACE_CMD_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ TCL_CMD_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) #define TCL_DTRACE_CMD_INFO(a0, a1, a2, a3, a4, a5, a6, a7) \ TCL_CMD_INFO(a0, a1, a2, a3, a4, a5, a6, a7) #define TCL_DTRACE_INST_START_ENABLED() unlikely(TCL_INST_START_ENABLED()) #define TCL_DTRACE_INST_DONE_ENABLED() unlikely(TCL_INST_DONE_ENABLED()) #define TCL_DTRACE_INST_START(a0, a1, a2) TCL_INST_START(a0, a1, a2) #define TCL_DTRACE_INST_DONE(a0, a1, a2) TCL_INST_DONE(a0, a1, a2) #define TCL_DTRACE_TCL_PROBE_ENABLED() unlikely(TCL_TCL_PROBE_ENABLED()) #define TCL_DTRACE_TCL_PROBE(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ TCL_TCL_PROBE(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) #define TCL_DTRACE_DEBUG_LOG() MODULE_SCOPE void TclDTraceInfo(Tcl_Obj *info, const char **args, int *argsi); #else /* USE_DTRACE */ #define TCL_DTRACE_PROC_ENTRY_ENABLED() 0 #define TCL_DTRACE_PROC_RETURN_ENABLED() 0 #define TCL_DTRACE_PROC_RESULT_ENABLED() 0 #define TCL_DTRACE_PROC_ARGS_ENABLED() 0 #define TCL_DTRACE_PROC_INFO_ENABLED() 0 #define TCL_DTRACE_PROC_ENTRY(a0, a1, a2) {if (a0) {}} #define TCL_DTRACE_PROC_RETURN(a0, a1) {if (a0) {}} #define TCL_DTRACE_PROC_RESULT(a0, a1, a2, a3) {if (a0) {}; if (a3) {}} #define TCL_DTRACE_PROC_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {} #define TCL_DTRACE_PROC_INFO(a0, a1, a2, a3, a4, a5, a6, a7) {} #define TCL_DTRACE_CMD_ENTRY_ENABLED() 0 #define TCL_DTRACE_CMD_RETURN_ENABLED() 0 #define TCL_DTRACE_CMD_RESULT_ENABLED() 0 #define TCL_DTRACE_CMD_ARGS_ENABLED() 0 #define TCL_DTRACE_CMD_INFO_ENABLED() 0 #define TCL_DTRACE_CMD_ENTRY(a0, a1, a2) {} #define TCL_DTRACE_CMD_RETURN(a0, a1) {} #define TCL_DTRACE_CMD_RESULT(a0, a1, a2, a3) {} #define TCL_DTRACE_CMD_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {} #define TCL_DTRACE_CMD_INFO(a0, a1, a2, a3, a4, a5, a6, a7) {} #define TCL_DTRACE_INST_START_ENABLED() 0 #define TCL_DTRACE_INST_DONE_ENABLED() 0 #define TCL_DTRACE_INST_START(a0, a1, a2) {} #define TCL_DTRACE_INST_DONE(a0, a1, a2) {} #define TCL_DTRACE_TCL_PROBE_ENABLED() 0 #define TCL_DTRACE_TCL_PROBE(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {} #define TclDTraceInfo(info, args, argsi) {*args = ""; *argsi = 0;} #endif /* USE_DTRACE */ #else /* TCL_DTRACE_DEBUG */ #define USE_DTRACE 1 #if !defined(TCL_DTRACE_DEBUG_LOG_ENABLED) || !(TCL_DTRACE_DEBUG_LOG_ENABLED) #undef TCL_DTRACE_DEBUG_LOG_ENABLED #define TCL_DTRACE_DEBUG_LOG_ENABLED 0 #endif #if !defined(TCL_DTRACE_DEBUG_INST_PROBES) || !(TCL_DTRACE_DEBUG_INST_PROBES) #undef TCL_DTRACE_DEBUG_INST_PROBES #define TCL_DTRACE_DEBUG_INST_PROBES 0 #endif MODULE_SCOPE int tclDTraceDebugEnabled, tclDTraceDebugIndent; MODULE_SCOPE FILE *tclDTraceDebugLog; MODULE_SCOPE void TclDTraceOpenDebugLog(void); MODULE_SCOPE void TclDTraceInfo(Tcl_Obj *info, const char **args, int *argsi); #define TCL_DTRACE_DEBUG_LOG() \ int tclDTraceDebugEnabled = TCL_DTRACE_DEBUG_LOG_ENABLED; \ int tclDTraceDebugIndent = 0; \ FILE *tclDTraceDebugLog = NULL; \ void TclDTraceOpenDebugLog(void) { \ char n[35]; \ sprintf(n, "/tmp/tclDTraceDebug-%lu.log", \ (unsigned long) getpid()); \ tclDTraceDebugLog = fopen(n, "a"); \ } #define TclDTraceDbgMsg(p, m, ...) \ do { \ if (tclDTraceDebugEnabled) { \ int _l, _t = 0; \ if (!tclDTraceDebugLog) { TclDTraceOpenDebugLog(); } \ fprintf(tclDTraceDebugLog, "%.12s:%.4d:%n", \ strrchr(__FILE__, '/')+1, __LINE__, &_l); _t += _l; \ fprintf(tclDTraceDebugLog, " %.*s():%n", \ (_t < 18 ? 18 - _t : 0) + 18, __func__, &_l); _t += _l; \ fprintf(tclDTraceDebugLog, "%*s" p "%n", \ (_t < 40 ? 40 - _t : 0) + 2 * tclDTraceDebugIndent, \ "", &_l); _t += _l; \ fprintf(tclDTraceDebugLog, "%*s" m "\n", \ (_t < 64 ? 64 - _t : 1), "", ##__VA_ARGS__); \ fflush(tclDTraceDebugLog); \ } \ } while (0) #define TCL_DTRACE_PROC_ENTRY_ENABLED() 1 #define TCL_DTRACE_PROC_RETURN_ENABLED() 1 #define TCL_DTRACE_PROC_RESULT_ENABLED() 1 #define TCL_DTRACE_PROC_ARGS_ENABLED() 1 #define TCL_DTRACE_PROC_INFO_ENABLED() 1 #define TCL_DTRACE_PROC_ENTRY(a0, a1, a2) \ tclDTraceDebugIndent++; \ TclDTraceDbgMsg("-> proc-entry", "%s %d %p", a0, a1, a2) #define TCL_DTRACE_PROC_RETURN(a0, a1) \ TclDTraceDbgMsg("<- proc-return", "%s %d", a0, a1); \ tclDTraceDebugIndent-- #define TCL_DTRACE_PROC_RESULT(a0, a1, a2, a3) \ TclDTraceDbgMsg(" | proc-result", "%s %d %s %p", a0, a1, a2, a3) #define TCL_DTRACE_PROC_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ TclDTraceDbgMsg(" | proc-args", "%s %s %s %s %s %s %s %s %s %s", a0, \ a1, a2, a3, a4, a5, a6, a7, a8, a9) #define TCL_DTRACE_PROC_INFO(a0, a1, a2, a3, a4, a5, a6, a7) \ TclDTraceDbgMsg(" | proc-info", "%s %s %s %s %d %d %s %s", a0, a1, \ a2, a3, a4, a5, a6, a7) #define TCL_DTRACE_CMD_ENTRY_ENABLED() 1 #define TCL_DTRACE_CMD_RETURN_ENABLED() 1 #define TCL_DTRACE_CMD_RESULT_ENABLED() 1 #define TCL_DTRACE_CMD_ARGS_ENABLED() 1 #define TCL_DTRACE_CMD_INFO_ENABLED() 1 #define TCL_DTRACE_CMD_ENTRY(a0, a1, a2) \ tclDTraceDebugIndent++; \ TclDTraceDbgMsg("-> cmd-entry", "%s %d %p", a0, a1, a2) #define TCL_DTRACE_CMD_RETURN(a0, a1) \ TclDTraceDbgMsg("<- cmd-return", "%s %d", a0, a1); \ tclDTraceDebugIndent-- #define TCL_DTRACE_CMD_RESULT(a0, a1, a2, a3) \ TclDTraceDbgMsg(" | cmd-result", "%s %d %s %p", a0, a1, a2, a3) #define TCL_DTRACE_CMD_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ TclDTraceDbgMsg(" | cmd-args", "%s %s %s %s %s %s %s %s %s %s", a0, \ a1, a2, a3, a4, a5, a6, a7, a8, a9) #define TCL_DTRACE_CMD_INFO(a0, a1, a2, a3, a4, a5, a6, a7) \ TclDTraceDbgMsg(" | cmd-info", "%s %s %s %s %d %d %s %s", a0, a1, \ a2, a3, a4, a5, a6, a7) #define TCL_DTRACE_INST_START_ENABLED() TCL_DTRACE_DEBUG_INST_PROBES #define TCL_DTRACE_INST_DONE_ENABLED() TCL_DTRACE_DEBUG_INST_PROBES #define TCL_DTRACE_INST_START(a0, a1, a2) \ TclDTraceDbgMsg(" | inst-start", "%s %d %p", a0, a1, a2) #define TCL_DTRACE_INST_DONE(a0, a1, a2) \ TclDTraceDbgMsg(" | inst-end", "%s %d %p", a0, a1, a2) #define TCL_DTRACE_TCL_PROBE_ENABLED() 1 #define TCL_DTRACE_TCL_PROBE(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ do { \ tclDTraceDebugEnabled = 1; \ TclDTraceDbgMsg(" | tcl-probe", "%s %s %s %s %s %s %s %s %s %s", a0, \ a1, a2, a3, a4, a5, a6, a7, a8, a9); \ } while (0) #endif /* TCL_DTRACE_DEBUG */ #endif /* _TCLCOMPILATION */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclAsync.c0000644000175000017500000002344112663653207015133 0ustar sergeisergei/* * tclAsync.c -- * * This file provides low-level support needed to invoke signal handlers * in a safe way. The code here doesn't actually handle signals, though. * This code is based on proposals made by Mark Diekhans and Don Libes. * * Copyright (c) 1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* Forward declaration */ struct ThreadSpecificData; /* * One of the following structures exists for each asynchronous handler: */ typedef struct AsyncHandler { int ready; /* Non-zero means this handler should be * invoked in the next call to * Tcl_AsyncInvoke. */ struct AsyncHandler *nextPtr; /* Next in list of all handlers for the * process. */ Tcl_AsyncProc *proc; /* Procedure to call when handler is * invoked. */ ClientData clientData; /* Value to pass to handler when it is * invoked. */ struct ThreadSpecificData *originTsd; /* Used in Tcl_AsyncMark to modify thread- * specific data from outside the thread it is * associated to. */ Tcl_ThreadId originThrdId; /* Origin thread where this token was created * and where it will be yielded. */ } AsyncHandler; typedef struct ThreadSpecificData { /* * The variables below maintain a list of all existing handlers specific * to the calling thread. */ AsyncHandler *firstHandler; /* First handler defined for process, or NULL * if none. */ AsyncHandler *lastHandler; /* Last handler or NULL. */ int asyncReady; /* This is set to 1 whenever a handler becomes * ready and it is cleared to zero whenever * Tcl_AsyncInvoke is called. It can be * checked elsewhere in the application by * calling Tcl_AsyncReady to see if * Tcl_AsyncInvoke should be invoked. */ int asyncActive; /* Indicates whether Tcl_AsyncInvoke is * currently working. If so then we won't set * asyncReady again until Tcl_AsyncInvoke * returns. */ Tcl_Mutex asyncMutex; /* Thread-specific AsyncHandler linked-list * lock */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* *---------------------------------------------------------------------- * * TclFinalizeAsync -- * * Finalizes the mutex in the thread local data structure for the async * subsystem. * * Results: * None. * * Side effects: * Forgets knowledge of the mutex should it have been created. * *---------------------------------------------------------------------- */ void TclFinalizeAsync(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->asyncMutex != NULL) { Tcl_MutexFinalize(&tsdPtr->asyncMutex); } } /* *---------------------------------------------------------------------- * * Tcl_AsyncCreate -- * * This procedure creates the data structures for an asynchronous * handler, so that no memory has to be allocated when the handler is * activated. * * Results: * The return value is a token for the handler, which can be used to * activate it later on. * * Side effects: * Information about the handler is recorded. * *---------------------------------------------------------------------- */ Tcl_AsyncHandler Tcl_AsyncCreate( Tcl_AsyncProc *proc, /* Procedure to call when handler is * invoked. */ ClientData clientData) /* Argument to pass to handler. */ { AsyncHandler *asyncPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); asyncPtr = ckalloc(sizeof(AsyncHandler)); asyncPtr->ready = 0; asyncPtr->nextPtr = NULL; asyncPtr->proc = proc; asyncPtr->clientData = clientData; asyncPtr->originTsd = tsdPtr; asyncPtr->originThrdId = Tcl_GetCurrentThread(); Tcl_MutexLock(&tsdPtr->asyncMutex); if (tsdPtr->firstHandler == NULL) { tsdPtr->firstHandler = asyncPtr; } else { tsdPtr->lastHandler->nextPtr = asyncPtr; } tsdPtr->lastHandler = asyncPtr; Tcl_MutexUnlock(&tsdPtr->asyncMutex); return (Tcl_AsyncHandler) asyncPtr; } /* *---------------------------------------------------------------------- * * Tcl_AsyncMark -- * * This procedure is called to request that an asynchronous handler be * invoked as soon as possible. It's typically called from an interrupt * handler, where it isn't safe to do anything that depends on or * modifies application state. * * Results: * None. * * Side effects: * The handler gets marked for invocation later. * *---------------------------------------------------------------------- */ void Tcl_AsyncMark( Tcl_AsyncHandler async) /* Token for handler. */ { AsyncHandler *token = (AsyncHandler *) async; Tcl_MutexLock(&token->originTsd->asyncMutex); token->ready = 1; if (!token->originTsd->asyncActive) { token->originTsd->asyncReady = 1; Tcl_ThreadAlert(token->originThrdId); } Tcl_MutexUnlock(&token->originTsd->asyncMutex); } /* *---------------------------------------------------------------------- * * Tcl_AsyncInvoke -- * * This procedure is called at a "safe" time at background level to * invoke any active asynchronous handlers. * * Results: * The return value is a normal Tcl result, which is intended to replace * the code argument as the current completion code for interp. * * Side effects: * Depends on the handlers that are active. * *---------------------------------------------------------------------- */ int Tcl_AsyncInvoke( Tcl_Interp *interp, /* If invoked from Tcl_Eval just after * completing a command, points to * interpreter. Otherwise it is NULL. */ int code) /* If interp is non-NULL, this gives * completion code from command that just * completed. */ { AsyncHandler *asyncPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Tcl_MutexLock(&tsdPtr->asyncMutex); if (tsdPtr->asyncReady == 0) { Tcl_MutexUnlock(&tsdPtr->asyncMutex); return code; } tsdPtr->asyncReady = 0; tsdPtr->asyncActive = 1; if (interp == NULL) { code = 0; } /* * Make one or more passes over the list of handlers, invoking at most one * handler in each pass. After invoking a handler, go back to the start of * the list again so that (a) if a new higher-priority handler gets marked * while executing a lower priority handler, we execute the higher- * priority handler next, and (b) if a handler gets deleted during the * execution of a handler, then the list structure may change so it isn't * safe to continue down the list anyway. */ while (1) { for (asyncPtr = tsdPtr->firstHandler; asyncPtr != NULL; asyncPtr = asyncPtr->nextPtr) { if (asyncPtr->ready) { break; } } if (asyncPtr == NULL) { break; } asyncPtr->ready = 0; Tcl_MutexUnlock(&tsdPtr->asyncMutex); code = asyncPtr->proc(asyncPtr->clientData, interp, code); Tcl_MutexLock(&tsdPtr->asyncMutex); } tsdPtr->asyncActive = 0; Tcl_MutexUnlock(&tsdPtr->asyncMutex); return code; } /* *---------------------------------------------------------------------- * * Tcl_AsyncDelete -- * * Frees up all the state for an asynchronous handler. The handler should * never be used again. * * Results: * None. * * Side effects: * The state associated with the handler is deleted. * * Failure to locate the handler in current thread private list * of async handlers will result in panic; exception: the list * is already empty (potential trouble?). * Consequently, threads should create and delete handlers * themselves. I.e. a handler created by one should not be * deleted by some other thread. * *---------------------------------------------------------------------- */ void Tcl_AsyncDelete( Tcl_AsyncHandler async) /* Token for handler to delete. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); AsyncHandler *asyncPtr = (AsyncHandler *) async; AsyncHandler *prevPtr, *thisPtr; /* * Assure early handling of the constraint */ if (asyncPtr->originThrdId != Tcl_GetCurrentThread()) { Tcl_Panic("Tcl_AsyncDelete: async handler deleted by the wrong thread"); } /* * If we come to this point when TSD's for the current * thread have already been garbage-collected, we are * in the _serious_ trouble. OTOH, we tolerate calling * with already cleaned-up handler list (should we?). */ Tcl_MutexLock(&tsdPtr->asyncMutex); if (tsdPtr->firstHandler != NULL) { prevPtr = thisPtr = tsdPtr->firstHandler; while (thisPtr != NULL && thisPtr != asyncPtr) { prevPtr = thisPtr; thisPtr = thisPtr->nextPtr; } if (thisPtr == NULL) { Tcl_Panic("Tcl_AsyncDelete: cannot find async handler"); } if (asyncPtr == tsdPtr->firstHandler) { tsdPtr->firstHandler = asyncPtr->nextPtr; } else { prevPtr->nextPtr = asyncPtr->nextPtr; } if (asyncPtr == tsdPtr->lastHandler) { tsdPtr->lastHandler = prevPtr; } } Tcl_MutexUnlock(&tsdPtr->asyncMutex); ckfree(asyncPtr); } /* *---------------------------------------------------------------------- * * Tcl_AsyncReady -- * * This procedure can be used to tell whether Tcl_AsyncInvoke needs to be * called. This procedure is the external interface for checking the * thread-specific asyncReady variable. * * Results: * The return value is 1 whenever a handler is ready and is 0 when no * handlers are ready. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_AsyncReady(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); return tsdPtr->asyncReady; } int * TclGetAsyncReadyPtr(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); return &(tsdPtr->asyncReady); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclPipe.c0000644000175000017500000007564112663660065014764 0ustar sergeisergei/* * tclPipe.c -- * * This file contains the generic portion of the command channel driver * as well as various utility routines used in managing subprocesses. * * Copyright (c) 1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * A linked list of the following structures is used to keep track of child * processes that have been detached but haven't exited yet, so we can make * sure that they're properly "reaped" (officially waited for) and don't lie * around as zombies cluttering the system. */ typedef struct Detached { Tcl_Pid pid; /* Id of process that's been detached but * isn't known to have exited. */ struct Detached *nextPtr; /* Next in list of all detached processes. */ } Detached; static Detached *detList = NULL;/* List of all detached proceses. */ TCL_DECLARE_MUTEX(pipeMutex) /* Guard access to detList. */ /* * Declarations for local functions defined in this file: */ static TclFile FileForRedirect(Tcl_Interp *interp, const char *spec, int atOk, const char *arg, const char *nextArg, int flags, int *skipPtr, int *closePtr, int *releasePtr); /* *---------------------------------------------------------------------- * * FileForRedirect -- * * This function does much of the work of parsing redirection operators. * It handles "@" if specified and allowed, and a file name, and opens * the file if necessary. * * Results: * The return value is the descriptor number for the file. If an error * occurs then NULL is returned and an error message is left in the * interp's result. Several arguments are side-effected; see the argument * list below for details. * * Side effects: * None. * *---------------------------------------------------------------------- */ static TclFile FileForRedirect( Tcl_Interp *interp, /* Intepreter to use for error reporting. */ const char *spec, /* Points to character just after redirection * character. */ int atOK, /* Non-zero means that '@' notation can be * used to specify a channel, zero means that * it isn't. */ const char *arg, /* Pointer to entire argument containing spec: * used for error reporting. */ const char *nextArg, /* Next argument in argc/argv array, if needed * for file name or channel name. May be * NULL. */ int flags, /* Flags to use for opening file or to specify * mode for channel. */ int *skipPtr, /* Filled with 1 if redirection target was in * spec, 2 if it was in nextArg. */ int *closePtr, /* Filled with one if the caller should close * the file when done with it, zero * otherwise. */ int *releasePtr) { int writing = (flags & O_WRONLY); Tcl_Channel chan; TclFile file; *skipPtr = 1; if ((atOK != 0) && (*spec == '@')) { spec++; if (*spec == '\0') { spec = nextArg; if (spec == NULL) { goto badLastArg; } *skipPtr = 2; } chan = Tcl_GetChannel(interp, spec, NULL); if (chan == (Tcl_Channel) NULL) { return NULL; } file = TclpMakeFile(chan, writing ? TCL_WRITABLE : TCL_READABLE); if (file == NULL) { Tcl_Obj *msg; Tcl_GetChannelError(chan, &msg); if (msg) { Tcl_SetObjResult(interp, msg); } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel \"%s\" wasn't opened for %s", Tcl_GetChannelName(chan), ((writing) ? "writing" : "reading"))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "BADCHAN", NULL); } return NULL; } *releasePtr = 1; if (writing) { /* * Be sure to flush output to the file, so that anything written * by the child appears after stuff we've already written. */ Tcl_Flush(chan); } } else { const char *name; Tcl_DString nameString; if (*spec == '\0') { spec = nextArg; if (spec == NULL) { goto badLastArg; } *skipPtr = 2; } name = Tcl_TranslateFileName(interp, spec, &nameString); if (name == NULL) { return NULL; } file = TclpOpenFile(name, flags); Tcl_DStringFree(&nameString); if (file == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't %s file \"%s\": %s", (writing ? "write" : "read"), spec, Tcl_PosixError(interp))); return NULL; } *closePtr = 1; } return file; badLastArg: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't specify \"%s\" as last word in command", arg)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "SYNTAX", NULL); return NULL; } /* *---------------------------------------------------------------------- * * Tcl_DetachPids -- * * This function is called to indicate that one or more child processes * have been placed in background and will never be waited for; they * should eventually be reaped by Tcl_ReapDetachedProcs. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_DetachPids( int numPids, /* Number of pids to detach: gives size of * array pointed to by pidPtr. */ Tcl_Pid *pidPtr) /* Array of pids to detach. */ { register Detached *detPtr; int i; Tcl_MutexLock(&pipeMutex); for (i = 0; i < numPids; i++) { detPtr = ckalloc(sizeof(Detached)); detPtr->pid = pidPtr[i]; detPtr->nextPtr = detList; detList = detPtr; } Tcl_MutexUnlock(&pipeMutex); } /* *---------------------------------------------------------------------- * * Tcl_ReapDetachedProcs -- * * This function checks to see if any detached processes have exited and, * if so, it "reaps" them by officially waiting on them. It should be * called "occasionally" to make sure that all detached processes are * eventually reaped. * * Results: * None. * * Side effects: * Processes are waited on, so that they can be reaped by the system. * *---------------------------------------------------------------------- */ void Tcl_ReapDetachedProcs(void) { register Detached *detPtr; Detached *nextPtr, *prevPtr; int status; Tcl_Pid pid; Tcl_MutexLock(&pipeMutex); for (detPtr = detList, prevPtr = NULL; detPtr != NULL; ) { pid = Tcl_WaitPid(detPtr->pid, &status, WNOHANG); if ((pid == 0) || ((pid == (Tcl_Pid) -1) && (errno != ECHILD))) { prevPtr = detPtr; detPtr = detPtr->nextPtr; continue; } nextPtr = detPtr->nextPtr; if (prevPtr == NULL) { detList = detPtr->nextPtr; } else { prevPtr->nextPtr = detPtr->nextPtr; } ckfree(detPtr); detPtr = nextPtr; } Tcl_MutexUnlock(&pipeMutex); } /* *---------------------------------------------------------------------- * * TclCleanupChildren -- * * This is a utility function used to wait for child processes to exit, * record information about abnormal exits, and then collect any stderr * output generated by them. * * Results: * The return value is a standard Tcl result. If anything at weird * happened with the child processes, TCL_ERROR is returned and a message * is left in the interp's result. * * Side effects: * If the last character of the interp's result is a newline, then it is * removed unless keepNewline is non-zero. File errorId gets closed, and * pidPtr is freed back to the storage allocator. * *---------------------------------------------------------------------- */ int TclCleanupChildren( Tcl_Interp *interp, /* Used for error messages. */ int numPids, /* Number of entries in pidPtr array. */ Tcl_Pid *pidPtr, /* Array of process ids of children. */ Tcl_Channel errorChan) /* Channel for file containing stderr output * from pipeline. NULL means there isn't any * stderr output. */ { int result = TCL_OK; int i, abnormalExit, anyErrorInfo; Tcl_Pid pid; int waitStatus; const char *msg; unsigned long resolvedPid; abnormalExit = 0; for (i = 0; i < numPids; i++) { /* * We need to get the resolved pid before we wait on it as the windows * implementation of Tcl_WaitPid deletes the information such that any * following calls to TclpGetPid fail. */ resolvedPid = TclpGetPid(pidPtr[i]); pid = Tcl_WaitPid(pidPtr[i], &waitStatus, 0); if (pid == (Tcl_Pid) -1) { result = TCL_ERROR; if (interp != NULL) { msg = Tcl_PosixError(interp); if (errno == ECHILD) { /* * This changeup in message suggested by Mark Diekhans to * remind people that ECHILD errors can occur on some * systems if SIGCHLD isn't in its default state. */ msg = "child process lost (is SIGCHLD ignored or trapped?)"; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error waiting for process to exit: %s", msg)); } continue; } /* * Create error messages for unusual process exits. An extra newline * gets appended to each error message, but it gets removed below (in * the same fashion that an extra newline in the command's output is * removed). */ if (!WIFEXITED(waitStatus) || (WEXITSTATUS(waitStatus) != 0)) { char msg1[TCL_INTEGER_SPACE], msg2[TCL_INTEGER_SPACE]; result = TCL_ERROR; sprintf(msg1, "%lu", resolvedPid); if (WIFEXITED(waitStatus)) { if (interp != NULL) { sprintf(msg2, "%u", WEXITSTATUS(waitStatus)); Tcl_SetErrorCode(interp, "CHILDSTATUS", msg1, msg2, NULL); } abnormalExit = 1; } else if (interp != NULL) { const char *p; if (WIFSIGNALED(waitStatus)) { p = Tcl_SignalMsg(WTERMSIG(waitStatus)); Tcl_SetErrorCode(interp, "CHILDKILLED", msg1, Tcl_SignalId(WTERMSIG(waitStatus)), p, NULL); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "child killed: %s\n", p)); } else if (WIFSTOPPED(waitStatus)) { p = Tcl_SignalMsg(WSTOPSIG(waitStatus)); Tcl_SetErrorCode(interp, "CHILDSUSP", msg1, Tcl_SignalId(WSTOPSIG(waitStatus)), p, NULL); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "child suspended: %s\n", p)); } else { Tcl_SetObjResult(interp, Tcl_NewStringObj( "child wait status didn't make sense\n", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "ODDWAITRESULT", msg1, NULL); } } } } /* * Read the standard error file. If there's anything there, then return an * error and add the file's contents to the result string. */ anyErrorInfo = 0; if (errorChan != NULL) { /* * Make sure we start at the beginning of the file. */ if (interp != NULL) { int count; Tcl_Obj *objPtr; Tcl_Seek(errorChan, (Tcl_WideInt)0, SEEK_SET); objPtr = Tcl_NewObj(); count = Tcl_ReadChars(errorChan, objPtr, -1, 0); if (count < 0) { result = TCL_ERROR; Tcl_DecrRefCount(objPtr); Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error reading stderr output file: %s", Tcl_PosixError(interp))); } else if (count > 0) { anyErrorInfo = 1; Tcl_SetObjResult(interp, objPtr); result = TCL_ERROR; } else { Tcl_DecrRefCount(objPtr); } } Tcl_Close(NULL, errorChan); } /* * If a child exited abnormally but didn't output any error information at * all, generate an error message here. */ if ((abnormalExit != 0) && (anyErrorInfo == 0) && (interp != NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "child process exited abnormally", -1)); } return result; } /* *---------------------------------------------------------------------- * * TclCreatePipeline -- * * Given an argc/argv array, instantiate a pipeline of processes as * described by the argv. * * This function is unofficially exported for use by BLT. * * Results: * The return value is a count of the number of new processes created, or * -1 if an error occurred while creating the pipeline. *pidArrayPtr is * filled in with the address of a dynamically allocated array giving the * ids of all of the processes. It is up to the caller to free this array * when it isn't needed anymore. If inPipePtr is non-NULL, *inPipePtr is * filled in with the file id for the input pipe for the pipeline (if * any): the caller must eventually close this file. If outPipePtr isn't * NULL, then *outPipePtr is filled in with the file id for the output * pipe from the pipeline: the caller must close this file. If errFilePtr * isn't NULL, then *errFilePtr is filled with a file id that may be used * to read error output after the pipeline completes. * * Side effects: * Processes and pipes are created. * *---------------------------------------------------------------------- */ int TclCreatePipeline( Tcl_Interp *interp, /* Interpreter to use for error reporting. */ int argc, /* Number of entries in argv. */ const char **argv, /* Array of strings describing commands in * pipeline plus I/O redirection with <, <<, * >, etc. Argv[argc] must be NULL. */ Tcl_Pid **pidArrayPtr, /* Word at *pidArrayPtr gets filled in with * address of array of pids for processes in * pipeline (first pid is first process in * pipeline). */ TclFile *inPipePtr, /* If non-NULL, input to the pipeline comes * from a pipe (unless overridden by * redirection in the command). The file id * with which to write to this pipe is stored * at *inPipePtr. NULL means command specified * its own input source. */ TclFile *outPipePtr, /* If non-NULL, output to the pipeline goes to * a pipe, unless overriden by redirection in * the command. The file id with which to read * frome this pipe is stored at *outPipePtr. * NULL means command specified its own output * sink. */ TclFile *errFilePtr) /* If non-NULL, all stderr output from the * pipeline will go to a temporary file * created here, and a descriptor to read the * file will be left at *errFilePtr. The file * will be removed already, so closing this * descriptor will be the end of the file. If * this is NULL, then all stderr output goes * to our stderr. If the pipeline specifies * redirection then the file will still be * created but it will never get any data. */ { Tcl_Pid *pidPtr = NULL; /* Points to malloc-ed array holding all the * pids of child processes. */ int numPids; /* Actual number of processes that exist at * *pidPtr right now. */ int cmdCount; /* Count of number of distinct commands found * in argc/argv. */ const char *inputLiteral = NULL; /* If non-null, then this points to a string * containing input data (specified via <<) to * be piped to the first process in the * pipeline. */ TclFile inputFile = NULL; /* If != NULL, gives file to use as input for * first process in pipeline (specified via < * or <@). */ int inputClose = 0; /* If non-zero, then inputFile should be * closed when cleaning up. */ int inputRelease = 0; TclFile outputFile = NULL; /* Writable file for output from last command * in pipeline (could be file or pipe). NULL * means use stdout. */ int outputClose = 0; /* If non-zero, then outputFile should be * closed when cleaning up. */ int outputRelease = 0; TclFile errorFile = NULL; /* Writable file for error output from all * commands in pipeline. NULL means use * stderr. */ int errorClose = 0; /* If non-zero, then errorFile should be * closed when cleaning up. */ int errorRelease = 0; const char *p; const char *nextArg; int skip, lastBar, lastArg, i, j, atOK, flags, needCmd, errorToOutput = 0; Tcl_DString execBuffer; TclFile pipeIn; TclFile curInFile, curOutFile, curErrFile; Tcl_Channel channel; if (inPipePtr != NULL) { *inPipePtr = NULL; } if (outPipePtr != NULL) { *outPipePtr = NULL; } if (errFilePtr != NULL) { *errFilePtr = NULL; } Tcl_DStringInit(&execBuffer); pipeIn = NULL; curInFile = NULL; curOutFile = NULL; numPids = 0; /* * First, scan through all the arguments to figure out the structure of * the pipeline. Process all of the input and output redirection arguments * and remove them from the argument list in the pipeline. Count the * number of distinct processes (it's the number of "|" arguments plus * one) but don't remove the "|" arguments because they'll be used in the * second pass to seperate the individual child processes. Cannot start * the child processes in this pass because the redirection symbols may * appear anywhere in the command line - e.g., the '<' that specifies the * input to the entire pipe may appear at the very end of the argument * list. */ lastBar = -1; cmdCount = 1; needCmd = 1; for (i = 0; i < argc; i++) { errorToOutput = 0; skip = 0; p = argv[i]; switch (*p++) { case '|': if (*p == '&') { p++; } if (*p == '\0') { if ((i == (lastBar + 1)) || (i == (argc - 1))) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "illegal use of | or |& in command", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "PIPESYNTAX", NULL); goto error; } } lastBar = i; cmdCount++; needCmd = 1; break; case '<': if (inputClose != 0) { inputClose = 0; TclpCloseFile(inputFile); } if (inputRelease != 0) { inputRelease = 0; TclpReleaseFile(inputFile); } if (*p == '<') { inputFile = NULL; inputLiteral = p + 1; skip = 1; if (*inputLiteral == '\0') { inputLiteral = ((i + 1) == argc) ? NULL : argv[i + 1]; if (inputLiteral == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't specify \"%s\" as last word in command", argv[i])); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "PIPESYNTAX", NULL); goto error; } skip = 2; } } else { nextArg = ((i + 1) == argc) ? NULL : argv[i + 1]; inputLiteral = NULL; inputFile = FileForRedirect(interp, p, 1, argv[i], nextArg, O_RDONLY, &skip, &inputClose, &inputRelease); if (inputFile == NULL) { goto error; } } break; case '>': atOK = 1; flags = O_WRONLY | O_CREAT | O_TRUNC; if (*p == '>') { p++; atOK = 0; /* * Note that the O_APPEND flag only has an effect on POSIX * platforms. On Windows, we just have to carry on regardless. */ flags = O_WRONLY | O_CREAT | O_APPEND; } if (*p == '&') { if (errorClose != 0) { errorClose = 0; TclpCloseFile(errorFile); } errorToOutput = 1; p++; } /* * Close the old output file, but only if the error file is not * also using it. */ if (outputClose != 0) { outputClose = 0; if (errorFile == outputFile) { errorClose = 1; } else { TclpCloseFile(outputFile); } } if (outputRelease != 0) { outputRelease = 0; if (errorFile == outputFile) { errorRelease = 1; } else { TclpReleaseFile(outputFile); } } nextArg = ((i + 1) == argc) ? NULL : argv[i + 1]; outputFile = FileForRedirect(interp, p, atOK, argv[i], nextArg, flags, &skip, &outputClose, &outputRelease); if (outputFile == NULL) { goto error; } if (errorToOutput) { if (errorClose != 0) { errorClose = 0; TclpCloseFile(errorFile); } if (errorRelease != 0) { errorRelease = 0; TclpReleaseFile(errorFile); } errorFile = outputFile; } break; case '2': if (*p != '>') { break; } p++; atOK = 1; flags = O_WRONLY | O_CREAT | O_TRUNC; if (*p == '>') { p++; atOK = 0; flags = O_WRONLY | O_CREAT; } if (errorClose != 0) { errorClose = 0; TclpCloseFile(errorFile); } if (errorRelease != 0) { errorRelease = 0; TclpReleaseFile(errorFile); } if (atOK && p[0] == '@' && p[1] == '1' && p[2] == '\0') { /* * Special case handling of 2>@1 to redirect stderr to the * exec/open output pipe as well. This is meant for the end of * the command string, otherwise use |& between commands. */ if (i != argc-1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "must specify \"%s\" as last word in command", argv[i])); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "PIPESYNTAX", NULL); goto error; } errorFile = outputFile; errorToOutput = 2; skip = 1; } else { nextArg = ((i + 1) == argc) ? NULL : argv[i + 1]; errorFile = FileForRedirect(interp, p, atOK, argv[i], nextArg, flags, &skip, &errorClose, &errorRelease); if (errorFile == NULL) { goto error; } } break; default: /* * Got a command word, not a redirection. */ needCmd = 0; break; } if (skip != 0) { for (j = i + skip; j < argc; j++) { argv[j - skip] = argv[j]; } argc -= skip; i -= 1; } } if (needCmd) { /* * We had a bar followed only by redirections. */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "illegal use of | or |& in command", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "PIPESYNTAX", NULL); goto error; } if (inputFile == NULL) { if (inputLiteral != NULL) { /* * The input for the first process is immediate data coming from * Tcl. Create a temporary file for it and put the data into the * file. */ inputFile = TclpCreateTempFile(inputLiteral); if (inputFile == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't create input file for command: %s", Tcl_PosixError(interp))); goto error; } inputClose = 1; } else if (inPipePtr != NULL) { /* * The input for the first process in the pipeline is to come from * a pipe that can be written from by the caller. */ if (TclpCreatePipe(&inputFile, inPipePtr) == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't create input pipe for command: %s", Tcl_PosixError(interp))); goto error; } inputClose = 1; } else { /* * The input for the first process comes from stdin. */ channel = Tcl_GetStdChannel(TCL_STDIN); if (channel != NULL) { inputFile = TclpMakeFile(channel, TCL_READABLE); if (inputFile != NULL) { inputRelease = 1; } } } } if (outputFile == NULL) { if (outPipePtr != NULL) { /* * Output from the last process in the pipeline is to go to a pipe * that can be read by the caller. */ if (TclpCreatePipe(outPipePtr, &outputFile) == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't create output pipe for command: %s", Tcl_PosixError(interp))); goto error; } outputClose = 1; } else { /* * The output for the last process goes to stdout. */ channel = Tcl_GetStdChannel(TCL_STDOUT); if (channel) { outputFile = TclpMakeFile(channel, TCL_WRITABLE); if (outputFile != NULL) { outputRelease = 1; } } } } if (errorFile == NULL) { if (errorToOutput == 2) { /* * Handle 2>@1 special case at end of cmd line. */ errorFile = outputFile; } else if (errFilePtr != NULL) { /* * Set up the standard error output sink for the pipeline, if * requested. Use a temporary file which is opened, then deleted. * Could potentially just use pipe, but if it filled up it could * cause the pipeline to deadlock: we'd be waiting for processes * to complete before reading stderr, and processes couldn't * complete because stderr was backed up. */ errorFile = TclpCreateTempFile(NULL); if (errorFile == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't create error file for command: %s", Tcl_PosixError(interp))); goto error; } *errFilePtr = errorFile; } else { /* * Errors from the pipeline go to stderr. */ channel = Tcl_GetStdChannel(TCL_STDERR); if (channel) { errorFile = TclpMakeFile(channel, TCL_WRITABLE); if (errorFile != NULL) { errorRelease = 1; } } } } /* * Scan through the argc array, creating a process for each group of * arguments between the "|" characters. */ Tcl_ReapDetachedProcs(); pidPtr = ckalloc(cmdCount * sizeof(Tcl_Pid)); curInFile = inputFile; for (i = 0; i < argc; i = lastArg + 1) { int result, joinThisError; Tcl_Pid pid; const char *oldName; /* * Convert the program name into native form. */ if (Tcl_TranslateFileName(interp, argv[i], &execBuffer) == NULL) { goto error; } /* * Find the end of the current segment of the pipeline. */ joinThisError = 0; for (lastArg = i; lastArg < argc; lastArg++) { if (argv[lastArg][0] != '|') { continue; } if (argv[lastArg][1] == '\0') { break; } if ((argv[lastArg][1] == '&') && (argv[lastArg][2] == '\0')) { joinThisError = 1; break; } } /* * If this is the last segment, use the specified outputFile. * Otherwise create an intermediate pipe. pipeIn will become the * curInFile for the next segment of the pipe. */ if (lastArg == argc) { curOutFile = outputFile; } else { argv[lastArg] = NULL; if (TclpCreatePipe(&pipeIn, &curOutFile) == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't create pipe: %s", Tcl_PosixError(interp))); goto error; } } if (joinThisError != 0) { curErrFile = curOutFile; } else { curErrFile = errorFile; } /* * Restore argv[i], since a caller wouldn't expect the contents of * argv to be modified. */ oldName = argv[i]; argv[i] = Tcl_DStringValue(&execBuffer); result = TclpCreateProcess(interp, lastArg - i, argv + i, curInFile, curOutFile, curErrFile, &pid); argv[i] = oldName; if (result != TCL_OK) { goto error; } Tcl_DStringFree(&execBuffer); pidPtr[numPids] = pid; numPids++; /* * Close off our copies of file descriptors that were set up for this * child, then set up the input for the next child. */ if ((curInFile != NULL) && (curInFile != inputFile)) { TclpCloseFile(curInFile); } curInFile = pipeIn; pipeIn = NULL; if ((curOutFile != NULL) && (curOutFile != outputFile)) { TclpCloseFile(curOutFile); } curOutFile = NULL; } *pidArrayPtr = pidPtr; /* * All done. Cleanup open files lying around and then return. */ cleanup: Tcl_DStringFree(&execBuffer); if (inputClose) { TclpCloseFile(inputFile); } else if (inputRelease) { TclpReleaseFile(inputFile); } if (outputClose) { TclpCloseFile(outputFile); } else if (outputRelease) { TclpReleaseFile(outputFile); } if (errorClose) { TclpCloseFile(errorFile); } else if (errorRelease) { TclpReleaseFile(errorFile); } return numPids; /* * An error occurred. There could have been extra files open, such as * pipes between children. Clean them all up. Detach any child processes * that have been created. */ error: if (pipeIn != NULL) { TclpCloseFile(pipeIn); } if ((curOutFile != NULL) && (curOutFile != outputFile)) { TclpCloseFile(curOutFile); } if ((curInFile != NULL) && (curInFile != inputFile)) { TclpCloseFile(curInFile); } if ((inPipePtr != NULL) && (*inPipePtr != NULL)) { TclpCloseFile(*inPipePtr); *inPipePtr = NULL; } if ((outPipePtr != NULL) && (*outPipePtr != NULL)) { TclpCloseFile(*outPipePtr); *outPipePtr = NULL; } if ((errFilePtr != NULL) && (*errFilePtr != NULL)) { TclpCloseFile(*errFilePtr); *errFilePtr = NULL; } if (pidPtr != NULL) { for (i = 0; i < numPids; i++) { if (pidPtr[i] != (Tcl_Pid) -1) { Tcl_DetachPids(1, &pidPtr[i]); } } ckfree(pidPtr); } numPids = -1; goto cleanup; } /* *---------------------------------------------------------------------- * * Tcl_OpenCommandChannel -- * * Opens an I/O channel to one or more subprocesses specified by argc and * argv. The flags argument determines the disposition of the stdio * handles. If the TCL_STDIN flag is set then the standard input for the * first subprocess will be tied to the channel: writing to the channel * will provide input to the subprocess. If TCL_STDIN is not set, then * standard input for the first subprocess will be the same as this * application's standard input. If TCL_STDOUT is set then standard * output from the last subprocess can be read from the channel; * otherwise it goes to this application's standard output. If TCL_STDERR * is set, standard error output for all subprocesses is returned to the * channel and results in an error when the channel is closed; otherwise * it goes to this application's standard error. If TCL_ENFORCE_MODE is * not set, then argc and argv can redirect the stdio handles to override * TCL_STDIN, TCL_STDOUT, and TCL_STDERR; if it is set, then it is an * error for argc and argv to override stdio channels for which * TCL_STDIN, TCL_STDOUT, and TCL_STDERR have been set. * * Results: * A new command channel, or NULL on failure with an error message left * in interp. * * Side effects: * Creates processes, opens pipes. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_OpenCommandChannel( Tcl_Interp *interp, /* Interpreter for error reporting. Can NOT be * NULL. */ int argc, /* How many arguments. */ const char **argv, /* Array of arguments for command pipe. */ int flags) /* Or'ed combination of TCL_STDIN, TCL_STDOUT, * TCL_STDERR, and TCL_ENFORCE_MODE. */ { TclFile *inPipePtr, *outPipePtr, *errFilePtr; TclFile inPipe, outPipe, errFile; int numPids; Tcl_Pid *pidPtr; Tcl_Channel channel; inPipe = outPipe = errFile = NULL; inPipePtr = (flags & TCL_STDIN) ? &inPipe : NULL; outPipePtr = (flags & TCL_STDOUT) ? &outPipe : NULL; errFilePtr = (flags & TCL_STDERR) ? &errFile : NULL; numPids = TclCreatePipeline(interp, argc, argv, &pidPtr, inPipePtr, outPipePtr, errFilePtr); if (numPids < 0) { goto error; } /* * Verify that the pipes that were created satisfy the readable/writable * constraints. */ if (flags & TCL_ENFORCE_MODE) { if ((flags & TCL_STDOUT) && (outPipe == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can't read output from command:" " standard output was redirected", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "BADREDIRECT", NULL); goto error; } if ((flags & TCL_STDIN) && (inPipe == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can't write input to command:" " standard input was redirected", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "BADREDIRECT", NULL); goto error; } } channel = TclpCreateCommandChannel(outPipe, inPipe, errFile, numPids, pidPtr); if (channel == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "pipe for command could not be created", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "NOPIPE", NULL); goto error; } return channel; error: if (numPids > 0) { Tcl_DetachPids(numPids, pidPtr); ckfree(pidPtr); } if (inPipe != NULL) { TclpCloseFile(inPipe); } if (outPipe != NULL) { TclpCloseFile(outPipe); } if (errFile != NULL) { TclpCloseFile(errFile); } return NULL; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclCompCmdsGR.c0000644000175000017500000025157512663660065016027 0ustar sergeisergei/* * tclCompCmdsGR.c -- * * This file contains compilation procedures that compile various Tcl * commands (beginning with the letters 'g' through 'r') into a sequence * of instructions ("bytecodes"). * * Copyright (c) 1997-1998 Sun Microsystems, Inc. * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2002 ActiveState Corporation. * Copyright (c) 2004-2013 by Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" #include /* * Prototypes for procedures defined later in this file: */ static void CompileReturnInternal(CompileEnv *envPtr, unsigned char op, int code, int level, Tcl_Obj *returnOpts); static int IndexTailVarIfKnown(Tcl_Interp *interp, Tcl_Token *varTokenPtr, CompileEnv *envPtr); #define INDEX_END (-2) /* *---------------------------------------------------------------------- * * GetIndexFromToken -- * * Parse a token and get the encoded version of the index (as understood * by TEBC), assuming it is at all knowable at compile time. Only handles * indices that are integers or 'end' or 'end-integer'. * * Returns: * TCL_OK if parsing succeeded, and TCL_ERROR if it failed. * * Side effects: * Sets *index to the index value if successful. * *---------------------------------------------------------------------- */ static inline int GetIndexFromToken( Tcl_Token *tokenPtr, int *index) { Tcl_Obj *tmpObj = Tcl_NewObj(); int result, idx; if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) { Tcl_DecrRefCount(tmpObj); return TCL_ERROR; } result = TclGetIntFromObj(NULL, tmpObj, &idx); if (result == TCL_OK) { if (idx < 0) { result = TCL_ERROR; } } else { result = TclGetIntForIndexM(NULL, tmpObj, INDEX_END, &idx); if (result == TCL_OK && idx > INDEX_END) { result = TCL_ERROR; } } Tcl_DecrRefCount(tmpObj); if (result == TCL_OK) { *index = idx; } return result; } /* *---------------------------------------------------------------------- * * TclCompileGlobalCmd -- * * Procedure called to compile the "global" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "global" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileGlobalCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *varTokenPtr; int localIndex, numWords, i; DefineLineInformation; /* TIP #280 */ /* TODO: Consider support for compiling expanded args. */ numWords = parsePtr->numWords; if (numWords < 2) { return TCL_ERROR; } /* * 'global' has no effect outside of proc bodies; handle that at runtime */ if (envPtr->procPtr == NULL) { return TCL_ERROR; } /* * Push the namespace */ PushStringLiteral(envPtr, "::"); /* * Loop over the variables. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); for (i=1; itokenPtr; wordIdx = 0; numWords = parsePtr->numWords; for (wordIdx = 0; wordIdx < numWords; wordIdx++) { if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TCL_ERROR; } tokenPtr = TokenAfter(tokenPtr); } TclInitJumpFixupArray(&jumpFalseFixupArray); TclInitJumpFixupArray(&jumpEndFixupArray); code = TCL_OK; /* * Each iteration of this loop compiles one "if expr ?then? body" or * "elseif expr ?then? body" clause. */ tokenPtr = parsePtr->tokenPtr; wordIdx = 0; while (wordIdx < numWords) { /* * Stop looping if the token isn't "if" or "elseif". */ word = tokenPtr[1].start; numBytes = tokenPtr[1].size; if ((tokenPtr == parsePtr->tokenPtr) || ((numBytes == 6) && (strncmp(word, "elseif", 6) == 0))) { tokenPtr = TokenAfter(tokenPtr); wordIdx++; } else { break; } if (wordIdx >= numWords) { code = TCL_ERROR; goto done; } /* * Compile the test expression then emit the conditional jump around * the "then" part. */ testTokenPtr = tokenPtr; if (realCond) { /* * Find out if the condition is a constant. */ Tcl_Obj *boolObj = Tcl_NewStringObj(testTokenPtr[1].start, testTokenPtr[1].size); Tcl_IncrRefCount(boolObj); code = Tcl_GetBooleanFromObj(NULL, boolObj, &boolVal); TclDecrRefCount(boolObj); if (code == TCL_OK) { /* * A static condition. */ realCond = 0; if (!boolVal) { compileScripts = 0; } } else { SetLineInformation(wordIdx); Tcl_ResetResult(interp); TclCompileExprWords(interp, testTokenPtr, 1, envPtr); if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) { TclExpandJumpFixupArray(&jumpFalseFixupArray); } jumpIndex = jumpFalseFixupArray.next; jumpFalseFixupArray.next++; TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, jumpFalseFixupArray.fixup+jumpIndex); } code = TCL_OK; } /* * Skip over the optional "then" before the then clause. */ tokenPtr = TokenAfter(testTokenPtr); wordIdx++; if (wordIdx >= numWords) { code = TCL_ERROR; goto done; } if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { word = tokenPtr[1].start; numBytes = tokenPtr[1].size; if ((numBytes == 4) && (strncmp(word, "then", 4) == 0)) { tokenPtr = TokenAfter(tokenPtr); wordIdx++; if (wordIdx >= numWords) { code = TCL_ERROR; goto done; } } } /* * Compile the "then" command body. */ if (compileScripts) { BODY(tokenPtr, wordIdx); } if (realCond) { /* * Jump to the end of the "if" command. Both jumpFalseFixupArray * and jumpEndFixupArray are indexed by "jumpIndex". */ if (jumpEndFixupArray.next >= jumpEndFixupArray.end) { TclExpandJumpFixupArray(&jumpEndFixupArray); } jumpEndFixupArray.next++; TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, jumpEndFixupArray.fixup+jumpIndex); /* * Fix the target of the jumpFalse after the test. Generate a 4 * byte jump if the distance is > 120 bytes. This is conservative, * and ensures that we won't have to replace this jump if we later * also need to replace the proceeding jump to the end of the "if" * with a 4 byte jump. */ TclAdjustStackDepth(-1, envPtr); if (TclFixupForwardJumpToHere(envPtr, jumpFalseFixupArray.fixup+jumpIndex, 120)) { /* * Adjust the code offset for the proceeding jump to the end * of the "if" command. */ jumpEndFixupArray.fixup[jumpIndex].codeOffset += 3; } } else if (boolVal) { /* * We were processing an "if 1 {...}"; stop compiling scripts. */ compileScripts = 0; } else { /* * We were processing an "if 0 {...}"; reset so that the rest * (elseif, else) is compiled correctly. */ realCond = 1; compileScripts = 1; } tokenPtr = TokenAfter(tokenPtr); wordIdx++; } /* * Check for the optional else clause. Do not compile anything if this was * an "if 1 {...}" case. */ if ((wordIdx < numWords) && (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD)) { /* * There is an else clause. Skip over the optional "else" word. */ word = tokenPtr[1].start; numBytes = tokenPtr[1].size; if ((numBytes == 4) && (strncmp(word, "else", 4) == 0)) { tokenPtr = TokenAfter(tokenPtr); wordIdx++; if (wordIdx >= numWords) { code = TCL_ERROR; goto done; } } if (compileScripts) { /* * Compile the else command body. */ BODY(tokenPtr, wordIdx); } /* * Make sure there are no words after the else clause. */ wordIdx++; if (wordIdx < numWords) { code = TCL_ERROR; goto done; } } else { /* * No else clause: the "if" command's result is an empty string. */ if (compileScripts) { PushStringLiteral(envPtr, ""); } } /* * Fix the unconditional jumps to the end of the "if" command. */ for (j = jumpEndFixupArray.next; j > 0; j--) { jumpIndex = (j - 1); /* i.e. process the closest jump first. */ if (TclFixupForwardJumpToHere(envPtr, jumpEndFixupArray.fixup+jumpIndex, 127)) { /* * Adjust the immediately preceeding "ifFalse" jump. We moved it's * target (just after this jump) down three bytes. */ unsigned char *ifFalsePc = envPtr->codeStart + jumpFalseFixupArray.fixup[jumpIndex].codeOffset; unsigned char opCode = *ifFalsePc; if (opCode == INST_JUMP_FALSE1) { jumpFalseDist = TclGetInt1AtPtr(ifFalsePc + 1); jumpFalseDist += 3; TclStoreInt1AtPtr(jumpFalseDist, (ifFalsePc + 1)); } else if (opCode == INST_JUMP_FALSE4) { jumpFalseDist = TclGetInt4AtPtr(ifFalsePc + 1); jumpFalseDist += 3; TclStoreInt4AtPtr(jumpFalseDist, (ifFalsePc + 1)); } else { Tcl_Panic("TclCompileIfCmd: unexpected opcode \"%d\" updating ifFalse jump", (int) opCode); } } } /* * Free the jumpFixupArray array if malloc'ed storage was used. */ done: TclFreeJumpFixupArray(&jumpFalseFixupArray); TclFreeJumpFixupArray(&jumpEndFixupArray); return code; } /* *---------------------------------------------------------------------- * * TclCompileIncrCmd -- * * Procedure called to compile the "incr" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "incr" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileIncrCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *varTokenPtr, *incrTokenPtr; int isScalar, localIndex, haveImmValue, immValue; DefineLineInformation; /* TIP #280 */ if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) { return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarNameWord(interp, varTokenPtr, envPtr, TCL_NO_LARGE_INDEX, &localIndex, &isScalar, 1); /* * If an increment is given, push it, but see first if it's a small * integer. */ haveImmValue = 0; immValue = 1; if (parsePtr->numWords == 3) { incrTokenPtr = TokenAfter(varTokenPtr); if (incrTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { const char *word = incrTokenPtr[1].start; int numBytes = incrTokenPtr[1].size; int code; Tcl_Obj *intObj = Tcl_NewStringObj(word, numBytes); Tcl_IncrRefCount(intObj); code = TclGetIntFromObj(NULL, intObj, &immValue); TclDecrRefCount(intObj); if ((code == TCL_OK) && (-127 <= immValue) && (immValue <= 127)) { haveImmValue = 1; } if (!haveImmValue) { PushLiteral(envPtr, word, numBytes); } } else { SetLineInformation(2); CompileTokens(envPtr, incrTokenPtr, interp); } } else { /* No incr amount given so use 1. */ haveImmValue = 1; } /* * Emit the instruction to increment the variable. */ if (isScalar) { /* Simple scalar variable. */ if (localIndex >= 0) { if (haveImmValue) { TclEmitInstInt1(INST_INCR_SCALAR1_IMM, localIndex, envPtr); TclEmitInt1(immValue, envPtr); } else { TclEmitInstInt1(INST_INCR_SCALAR1, localIndex, envPtr); } } else { if (haveImmValue) { TclEmitInstInt1(INST_INCR_STK_IMM, immValue, envPtr); } else { TclEmitOpcode( INST_INCR_STK, envPtr); } } } else { /* Simple array variable. */ if (localIndex >= 0) { if (haveImmValue) { TclEmitInstInt1(INST_INCR_ARRAY1_IMM, localIndex, envPtr); TclEmitInt1(immValue, envPtr); } else { TclEmitInstInt1(INST_INCR_ARRAY1, localIndex, envPtr); } } else { if (haveImmValue) { TclEmitInstInt1(INST_INCR_ARRAY_STK_IMM, immValue, envPtr); } else { TclEmitOpcode( INST_INCR_ARRAY_STK, envPtr); } } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileInfo*Cmd -- * * Procedures called to compile "info" subcommands. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "info" subcommand at * runtime. * *---------------------------------------------------------------------- */ int TclCompileInfoCommandsCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; Tcl_Obj *objPtr; char *bytes; /* * We require one compile-time known argument for the case we can compile. */ if (parsePtr->numWords == 1) { return TclCompileBasic0ArgCmd(interp, parsePtr, cmdPtr, envPtr); } else if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); objPtr = Tcl_NewObj(); Tcl_IncrRefCount(objPtr); if (!TclWordKnownAtCompileTime(tokenPtr, objPtr)) { goto notCompilable; } bytes = Tcl_GetString(objPtr); /* * We require that the argument start with "::" and not have any of "*\[?" * in it. (Theoretically, we should look in only the final component, but * the difference is so slight given current naming practices.) */ if (bytes[0] != ':' || bytes[1] != ':' || !TclMatchIsTrivial(bytes)) { goto notCompilable; } Tcl_DecrRefCount(objPtr); /* * Confirmed as a literal that will not frighten the horses. Compile. Note * that the result needs to be list-ified. */ /* TODO: Just push the known value */ CompileWord(envPtr, tokenPtr, interp, 1); TclEmitOpcode( INST_RESOLVE_COMMAND, envPtr); TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_STR_LEN, envPtr); TclEmitInstInt1( INST_JUMP_FALSE1, 7, envPtr); TclEmitInstInt4( INST_LIST, 1, envPtr); return TCL_OK; notCompilable: Tcl_DecrRefCount(objPtr); return TclCompileBasic1ArgCmd(interp, parsePtr, cmdPtr, envPtr); } int TclCompileInfoCoroutineCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Only compile [info coroutine] without arguments. */ if (parsePtr->numWords != 1) { return TCL_ERROR; } /* * Not much to do; we compile to a single instruction... */ TclEmitOpcode( INST_COROUTINE_NAME, envPtr); return TCL_OK; } int TclCompileInfoExistsCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; int isScalar, localIndex; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; } /* * Decide if we can use a frame slot for the var/array name or if we need * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarNameWord(interp, tokenPtr, envPtr, 0, &localIndex, &isScalar, 1); /* * Emit instruction to check the variable for existence. */ if (isScalar) { if (localIndex < 0) { TclEmitOpcode( INST_EXIST_STK, envPtr); } else { TclEmitInstInt4( INST_EXIST_SCALAR, localIndex, envPtr); } } else { if (localIndex < 0) { TclEmitOpcode( INST_EXIST_ARRAY_STK, envPtr); } else { TclEmitInstInt4( INST_EXIST_ARRAY, localIndex, envPtr); } } return TCL_OK; } int TclCompileInfoLevelCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Only compile [info level] without arguments or with a single argument. */ if (parsePtr->numWords == 1) { /* * Not much to do; we compile to a single instruction... */ TclEmitOpcode( INST_INFO_LEVEL_NUM, envPtr); } else if (parsePtr->numWords != 2) { return TCL_ERROR; } else { DefineLineInformation; /* TIP #280 */ /* * Compile the argument, then add the instruction to convert it into a * list of arguments. */ CompileWord(envPtr, TokenAfter(parsePtr->tokenPtr), interp, 1); TclEmitOpcode( INST_INFO_LEVEL_ARGS, envPtr); } return TCL_OK; } int TclCompileInfoObjectClassCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); if (parsePtr->numWords != 2) { return TCL_ERROR; } CompileWord(envPtr, tokenPtr, interp, 1); TclEmitOpcode( INST_TCLOO_CLASS, envPtr); return TCL_OK; } int TclCompileInfoObjectIsACmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); /* * We only handle [info object isa object ]. The first three * words are compressed to a single token by the ensemble compilation * engine. */ if (parsePtr->numWords != 3) { return TCL_ERROR; } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD || tokenPtr[1].size < 1 || strncmp(tokenPtr[1].start, "object", tokenPtr[1].size)) { return TCL_ERROR; } tokenPtr = TokenAfter(tokenPtr); /* * Issue the code. */ CompileWord(envPtr, tokenPtr, interp, 2); TclEmitOpcode( INST_TCLOO_IS_OBJECT, envPtr); return TCL_OK; } int TclCompileInfoObjectNamespaceCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); if (parsePtr->numWords != 2) { return TCL_ERROR; } CompileWord(envPtr, tokenPtr, interp, 1); TclEmitOpcode( INST_TCLOO_NS, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLappendCmd -- * * Procedure called to compile the "lappend" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "lappend" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileLappendCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *varTokenPtr, *valueTokenPtr; int isScalar, localIndex, numWords, i; DefineLineInformation; /* TIP #280 */ /* TODO: Consider support for compiling expanded args. */ numWords = parsePtr->numWords; if (numWords < 3) { return TCL_ERROR; } if (numWords != 3 || envPtr->procPtr == NULL) { goto lappendMultiple; } /* * Decide if we can use a frame slot for the var/array name or if we * need to emit code to compute and push the name at runtime. We use a * frame slot (entry in the array of local vars) if we are compiling a * procedure body and if the name is simple text that does not include * namespace qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarNameWord(interp, varTokenPtr, envPtr, 0, &localIndex, &isScalar, 1); /* * If we are doing an assignment, push the new value. In the no values * case, create an empty object. */ if (numWords > 2) { Tcl_Token *valueTokenPtr = TokenAfter(varTokenPtr); CompileWord(envPtr, valueTokenPtr, interp, 2); } /* * Emit instructions to set/get the variable. */ /* * The *_STK opcodes should be refactored to make better use of existing * LOAD/STORE instructions. */ if (isScalar) { if (localIndex < 0) { TclEmitOpcode( INST_LAPPEND_STK, envPtr); } else { Emit14Inst( INST_LAPPEND_SCALAR, localIndex, envPtr); } } else { if (localIndex < 0) { TclEmitOpcode( INST_LAPPEND_ARRAY_STK, envPtr); } else { Emit14Inst( INST_LAPPEND_ARRAY, localIndex, envPtr); } } return TCL_OK; lappendMultiple: varTokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarNameWord(interp, varTokenPtr, envPtr, 0, &localIndex, &isScalar, 1); valueTokenPtr = TokenAfter(varTokenPtr); for (i = 2 ; i < numWords ; i++) { CompileWord(envPtr, valueTokenPtr, interp, i); valueTokenPtr = TokenAfter(valueTokenPtr); } TclEmitInstInt4( INST_LIST, numWords-2, envPtr); if (isScalar) { if (localIndex < 0) { TclEmitOpcode( INST_LAPPEND_LIST_STK, envPtr); } else { TclEmitInstInt4(INST_LAPPEND_LIST, localIndex, envPtr); } } else { if (localIndex < 0) { TclEmitOpcode( INST_LAPPEND_LIST_ARRAY_STK, envPtr); } else { TclEmitInstInt4(INST_LAPPEND_LIST_ARRAY, localIndex,envPtr); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLassignCmd -- * * Procedure called to compile the "lassign" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "lassign" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileLassignCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; int isScalar, localIndex, numWords, idx; DefineLineInformation; /* TIP #280 */ numWords = parsePtr->numWords; /* * Check for command syntax error, but we'll punt that to runtime. */ if (numWords < 3) { return TCL_ERROR; } /* * Generate code to push list being taken apart by [lassign]. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); /* * Generate code to assign values from the list to variables. */ for (idx=0 ; idx= 0) { TclEmitOpcode( INST_DUP, envPtr); TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr); Emit14Inst( INST_STORE_SCALAR, localIndex, envPtr); TclEmitOpcode( INST_POP, envPtr); } else { TclEmitInstInt4(INST_OVER, 1, envPtr); TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr); TclEmitOpcode( INST_STORE_STK, envPtr); TclEmitOpcode( INST_POP, envPtr); } } else { if (localIndex >= 0) { TclEmitInstInt4(INST_OVER, 1, envPtr); TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr); Emit14Inst( INST_STORE_ARRAY, localIndex, envPtr); TclEmitOpcode( INST_POP, envPtr); } else { TclEmitInstInt4(INST_OVER, 2, envPtr); TclEmitInstInt4(INST_LIST_INDEX_IMM, idx, envPtr); TclEmitOpcode( INST_STORE_ARRAY_STK, envPtr); TclEmitOpcode( INST_POP, envPtr); } } } /* * Generate code to leave the rest of the list on the stack. */ TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr); TclEmitInt4( INDEX_END, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLindexCmd -- * * Procedure called to compile the "lindex" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "lindex" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileLindexCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *idxTokenPtr, *valTokenPtr; int i, idx, numWords = parsePtr->numWords; DefineLineInformation; /* TIP #280 */ /* * Quit if too few args. */ /* TODO: Consider support for compiling expanded args. */ if (numWords <= 1) { return TCL_ERROR; } valTokenPtr = TokenAfter(parsePtr->tokenPtr); if (numWords != 3) { goto emitComplexLindex; } idxTokenPtr = TokenAfter(valTokenPtr); if (GetIndexFromToken(idxTokenPtr, &idx) == TCL_OK) { /* * All checks have been completed, and we have exactly one of these * constructs: * lindex * lindex end- * This is best compiled as a push of the arbitrary value followed by * an "immediate lindex" which is the most efficient variety. */ CompileWord(envPtr, valTokenPtr, interp, 1); TclEmitInstInt4( INST_LIST_INDEX_IMM, idx, envPtr); return TCL_OK; } /* * If the value was not known at compile time, the conversion failed or * the value was negative, we just keep on going with the more complex * compilation. */ /* * Push the operands onto the stack. */ emitComplexLindex: for (i=1 ; inumWords == 1) { /* * [list] without arguments just pushes an empty object. */ PushStringLiteral(envPtr, ""); return TCL_OK; } /* * Test if all arguments are compile-time known. If they are, we can * implement with a simple push. */ numWords = parsePtr->numWords; valueTokenPtr = TokenAfter(parsePtr->tokenPtr); listObj = Tcl_NewObj(); for (i = 1; i < numWords && listObj != NULL; i++) { objPtr = Tcl_NewObj(); if (TclWordKnownAtCompileTime(valueTokenPtr, objPtr)) { (void) Tcl_ListObjAppendElement(NULL, listObj, objPtr); } else { Tcl_DecrRefCount(objPtr); Tcl_DecrRefCount(listObj); listObj = NULL; } valueTokenPtr = TokenAfter(valueTokenPtr); } if (listObj != NULL) { TclEmitPush(TclAddLiteralObj(envPtr, listObj, NULL), envPtr); return TCL_OK; } /* * Push the all values onto the stack. */ numWords = parsePtr->numWords; valueTokenPtr = TokenAfter(parsePtr->tokenPtr); concat = build = 0; for (i = 1; i < numWords; i++) { if (valueTokenPtr->type == TCL_TOKEN_EXPAND_WORD && build > 0) { TclEmitInstInt4( INST_LIST, build, envPtr); if (concat) { TclEmitOpcode( INST_LIST_CONCAT, envPtr); } build = 0; concat = 1; } CompileWord(envPtr, valueTokenPtr, interp, i); if (valueTokenPtr->type == TCL_TOKEN_EXPAND_WORD) { if (concat) { TclEmitOpcode( INST_LIST_CONCAT, envPtr); } else { concat = 1; } } else { build++; } valueTokenPtr = TokenAfter(valueTokenPtr); } if (build > 0) { TclEmitInstInt4( INST_LIST, build, envPtr); if (concat) { TclEmitOpcode( INST_LIST_CONCAT, envPtr); } } /* * If there was just one expanded word, we must ensure that it is a list * at this point. We use an [lrange ... 0 end] for this (instead of * [llength], as with literals) as we must drop any string representation * that might be hanging around. */ if (concat && numWords == 2) { TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr); TclEmitInt4( INDEX_END, envPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLlengthCmd -- * * Procedure called to compile the "llength" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "llength" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileLlengthCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *varTokenPtr; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, varTokenPtr, interp, 1); TclEmitOpcode( INST_LIST_LENGTH, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLrangeCmd -- * * How to compile the "lrange" command. We only bother because we needed * the opcode anyway for "lassign". * *---------------------------------------------------------------------- */ int TclCompileLrangeCmd( Tcl_Interp *interp, /* Tcl interpreter for context. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the * command. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds the resulting instructions. */ { Tcl_Token *tokenPtr, *listTokenPtr; DefineLineInformation; /* TIP #280 */ int idx1, idx2; if (parsePtr->numWords != 4) { return TCL_ERROR; } listTokenPtr = TokenAfter(parsePtr->tokenPtr); /* * Parse the indices. Will only compile if both are constants and not an * _integer_ less than zero (since we reserve negative indices here for * end-relative indexing) or an end-based index greater than 'end' itself. */ tokenPtr = TokenAfter(listTokenPtr); if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) { return TCL_ERROR; } tokenPtr = TokenAfter(tokenPtr); if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) { return TCL_ERROR; } /* * Issue instructions. It's not safe to skip doing the LIST_RANGE, as * we've not proved that the 'list' argument is really a list. Not that it * is worth trying to do that given current knowledge. */ CompileWord(envPtr, listTokenPtr, interp, 1); TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr); TclEmitInt4( idx2, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLinsertCmd -- * * How to compile the "linsert" command. We only bother with the case * where the index is constant. * *---------------------------------------------------------------------- */ int TclCompileLinsertCmd( Tcl_Interp *interp, /* Tcl interpreter for context. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the * command. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds the resulting instructions. */ { Tcl_Token *tokenPtr, *listTokenPtr; DefineLineInformation; /* TIP #280 */ int idx, i; if (parsePtr->numWords < 3) { return TCL_ERROR; } listTokenPtr = TokenAfter(parsePtr->tokenPtr); /* * Parse the index. Will only compile if it is constant and not an * _integer_ less than zero (since we reserve negative indices here for * end-relative indexing) or an end-based index greater than 'end' itself. */ tokenPtr = TokenAfter(listTokenPtr); if (GetIndexFromToken(tokenPtr, &idx) != TCL_OK) { return TCL_ERROR; } /* * There are four main cases. If there are no values to insert, this is * just a confirm-listiness check. If the index is '0', this is a prepend. * If the index is 'end' (== INDEX_END), this is an append. Otherwise, * this is a splice (== split, insert values as list, concat-3). */ CompileWord(envPtr, listTokenPtr, interp, 1); if (parsePtr->numWords == 3) { TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr); TclEmitInt4( INDEX_END, envPtr); return TCL_OK; } for (i=3 ; inumWords ; i++) { tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i); } TclEmitInstInt4( INST_LIST, i-3, envPtr); if (idx == 0 /*start*/) { TclEmitInstInt4( INST_REVERSE, 2, envPtr); TclEmitOpcode( INST_LIST_CONCAT, envPtr); } else if (idx == INDEX_END /*end*/) { TclEmitOpcode( INST_LIST_CONCAT, envPtr); } else { if (idx < 0) { idx++; } TclEmitInstInt4( INST_OVER, 1, envPtr); TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr); TclEmitInt4( idx-1, envPtr); TclEmitInstInt4( INST_REVERSE, 3, envPtr); TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr); TclEmitInt4( INDEX_END, envPtr); TclEmitOpcode( INST_LIST_CONCAT, envPtr); TclEmitOpcode( INST_LIST_CONCAT, envPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLreplaceCmd -- * * How to compile the "lreplace" command. We only bother with the case * where the indices are constant. * *---------------------------------------------------------------------- */ int TclCompileLreplaceCmd( Tcl_Interp *interp, /* Tcl interpreter for context. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the * command. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds the resulting instructions. */ { Tcl_Token *tokenPtr, *listTokenPtr; DefineLineInformation; /* TIP #280 */ Tcl_Obj *tmpObj; int idx1, idx2, i, offset, offset2; if (parsePtr->numWords < 4) { return TCL_ERROR; } listTokenPtr = TokenAfter(parsePtr->tokenPtr); /* * Parse the indices. Will only compile if both are constants and not an * _integer_ less than zero (since we reserve negative indices here for * end-relative indexing) or an end-based index greater than 'end' itself. */ tokenPtr = TokenAfter(listTokenPtr); if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) { return TCL_ERROR; } tokenPtr = TokenAfter(tokenPtr); if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) { return TCL_ERROR; } if(idx2 != INDEX_END && idx2 >= 0 && idx2 < idx1) { idx2 = idx1-1; } /* * Work out what this [lreplace] is actually doing. */ tmpObj = NULL; CompileWord(envPtr, listTokenPtr, interp, 1); if (parsePtr->numWords == 4) { if (idx1 == 0) { if (idx2 == INDEX_END) { goto dropAll; } idx1 = idx2 + 1; idx2 = INDEX_END; goto dropEnd; } else if (idx2 == INDEX_END) { idx2 = idx1 - 1; idx1 = 0; goto dropEnd; } else { if (idx1 > 0) { tmpObj = Tcl_NewIntObj(idx1); Tcl_IncrRefCount(tmpObj); } goto dropRange; } } tokenPtr = TokenAfter(tokenPtr); for (i=4 ; inumWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } TclEmitInstInt4( INST_LIST, i - 4, envPtr); TclEmitInstInt4( INST_REVERSE, 2, envPtr); if (idx1 == 0) { if (idx2 == INDEX_END) { goto replaceAll; } idx1 = idx2 + 1; idx2 = INDEX_END; goto replaceHead; } else if (idx2 == INDEX_END) { idx2 = idx1 - 1; idx1 = 0; goto replaceTail; } else { if (idx1 > 0 && idx2 > 0 && idx2 < idx1) { idx2 = idx1 - 1; } else if (idx1 < 0 && idx2 < 0 && idx2 < idx1) { idx2 = idx1 - 1; } if (idx1 > 0) { tmpObj = Tcl_NewIntObj(idx1); Tcl_IncrRefCount(tmpObj); } goto replaceRange; } /* * Issue instructions to perform the operations relating to configurations * that just drop. The only argument pushed on the stack is the list to * operate on. */ dropAll: TclEmitOpcode( INST_LIST_LENGTH, envPtr); TclEmitOpcode( INST_POP, envPtr); PushStringLiteral(envPtr, ""); goto done; dropEnd: TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr); TclEmitInt4( idx2, envPtr); goto done; dropRange: if (tmpObj != NULL) { TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_LIST_LENGTH, envPtr); TclEmitPush(TclAddLiteralObj(envPtr, tmpObj, NULL), envPtr); TclEmitOpcode( INST_GT, envPtr); offset = CurrentOffset(envPtr); TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr); TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_LIST_LENGTH, envPtr); offset2 = CurrentOffset(envPtr); TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr); TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf( "list doesn't contain element %d", idx1), NULL), envPtr); CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0, Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}")); TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset, envPtr->codeStart + offset + 1); TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2, envPtr->codeStart + offset2 + 1); TclAdjustStackDepth(-1, envPtr); } TclEmitOpcode( INST_DUP, envPtr); TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr); TclEmitInt4( idx1 - 1, envPtr); TclEmitInstInt4( INST_REVERSE, 2, envPtr); TclEmitInstInt4( INST_LIST_RANGE_IMM, idx2 + 1, envPtr); TclEmitInt4( INDEX_END, envPtr); TclEmitOpcode( INST_LIST_CONCAT, envPtr); goto done; /* * Issue instructions to perform the operations relating to configurations * that do real replacement. All arguments are pushed and assembled into a * pair: the list of values to replace with, and the list to do the * surgery on. */ replaceAll: TclEmitOpcode( INST_LIST_LENGTH, envPtr); TclEmitOpcode( INST_POP, envPtr); goto done; replaceHead: TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr); TclEmitInt4( idx2, envPtr); TclEmitOpcode( INST_LIST_CONCAT, envPtr); goto done; replaceTail: TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr); TclEmitInt4( idx2, envPtr); TclEmitInstInt4( INST_REVERSE, 2, envPtr); TclEmitOpcode( INST_LIST_CONCAT, envPtr); goto done; replaceRange: if (tmpObj != NULL) { TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_LIST_LENGTH, envPtr); TclEmitPush(TclAddLiteralObj(envPtr, tmpObj, NULL), envPtr); TclEmitOpcode( INST_GT, envPtr); offset = CurrentOffset(envPtr); TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr); TclEmitOpcode( INST_DUP, envPtr); TclEmitOpcode( INST_LIST_LENGTH, envPtr); offset2 = CurrentOffset(envPtr); TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr); TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf( "list doesn't contain element %d", idx1), NULL), envPtr); CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0, Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}")); TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset, envPtr->codeStart + offset + 1); TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2, envPtr->codeStart + offset2 + 1); TclAdjustStackDepth(-1, envPtr); } TclEmitOpcode( INST_DUP, envPtr); TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr); TclEmitInt4( idx1 - 1, envPtr); TclEmitInstInt4( INST_REVERSE, 2, envPtr); TclEmitInstInt4( INST_LIST_RANGE_IMM, idx2 + 1, envPtr); TclEmitInt4( INDEX_END, envPtr); TclEmitInstInt4( INST_REVERSE, 3, envPtr); TclEmitOpcode( INST_LIST_CONCAT, envPtr); TclEmitInstInt4( INST_REVERSE, 2, envPtr); TclEmitOpcode( INST_LIST_CONCAT, envPtr); goto done; /* * Clean up the allocated memory. */ done: if (tmpObj != NULL) { Tcl_DecrRefCount(tmpObj); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLsetCmd -- * * Procedure called to compile the "lset" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "lset" command at * runtime. * * The general template for execution of the "lset" command is: * (1) Instructions to push the variable name, unless the variable is * local to the stack frame. * (2) If the variable is an array element, instructions to push the * array element name. * (3) Instructions to push each of zero or more "index" arguments to the * stack, followed with the "newValue" element. * (4) Instructions to duplicate the variable name and/or array element * name onto the top of the stack, if either was pushed at steps (1) * and (2). * (5) The appropriate INST_LOAD_* instruction to place the original * value of the list variable at top of stack. * (6) At this point, the stack contains: * varName? arrayElementName? index1 index2 ... newValue oldList * The compiler emits one of INST_LSET_FLAT or INST_LSET_LIST * according as whether there is exactly one index element (LIST) or * either zero or else two or more (FLAT). This instruction removes * everything from the stack except for the two names and pushes the * new value of the variable. * (7) Finally, INST_STORE_* stores the new value in the variable and * cleans up the stack. * *---------------------------------------------------------------------- */ int TclCompileLsetCmd( Tcl_Interp *interp, /* Tcl interpreter for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the * command. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds the resulting instructions. */ { int tempDepth; /* Depth used for emitting one part of the * code burst. */ Tcl_Token *varTokenPtr; /* Pointer to the Tcl_Token representing the * parse of the variable name. */ int localIndex; /* Index of var in local var table. */ int isScalar; /* Flag == 1 if scalar, 0 if array. */ int i; DefineLineInformation; /* TIP #280 */ /* * Check argument count. */ /* TODO: Consider support for compiling expanded args. */ if (parsePtr->numWords < 3) { /* * Fail at run time, not in compilation. */ return TCL_ERROR; } /* * Decide if we can use a frame slot for the var/array name or if we need * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarNameWord(interp, varTokenPtr, envPtr, 0, &localIndex, &isScalar, 1); /* * Push the "index" args and the new element value. */ for (i=2 ; inumWords ; ++i) { varTokenPtr = TokenAfter(varTokenPtr); CompileWord(envPtr, varTokenPtr, interp, i); } /* * Duplicate the variable name if it's been pushed. */ if (localIndex < 0) { if (isScalar) { tempDepth = parsePtr->numWords - 2; } else { tempDepth = parsePtr->numWords - 1; } TclEmitInstInt4( INST_OVER, tempDepth, envPtr); } /* * Duplicate an array index if one's been pushed. */ if (!isScalar) { if (localIndex < 0) { tempDepth = parsePtr->numWords - 1; } else { tempDepth = parsePtr->numWords - 2; } TclEmitInstInt4( INST_OVER, tempDepth, envPtr); } /* * Emit code to load the variable's value. */ if (isScalar) { if (localIndex < 0) { TclEmitOpcode( INST_LOAD_STK, envPtr); } else { Emit14Inst( INST_LOAD_SCALAR, localIndex, envPtr); } } else { if (localIndex < 0) { TclEmitOpcode( INST_LOAD_ARRAY_STK, envPtr); } else { Emit14Inst( INST_LOAD_ARRAY, localIndex, envPtr); } } /* * Emit the correct variety of 'lset' instruction. */ if (parsePtr->numWords == 4) { TclEmitOpcode( INST_LSET_LIST, envPtr); } else { TclEmitInstInt4( INST_LSET_FLAT, parsePtr->numWords-1, envPtr); } /* * Emit code to put the value back in the variable. */ if (isScalar) { if (localIndex < 0) { TclEmitOpcode( INST_STORE_STK, envPtr); } else { Emit14Inst( INST_STORE_SCALAR, localIndex, envPtr); } } else { if (localIndex < 0) { TclEmitOpcode( INST_STORE_ARRAY_STK, envPtr); } else { Emit14Inst( INST_STORE_ARRAY, localIndex, envPtr); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileNamespace*Cmd -- * * Procedures called to compile the "namespace" command; currently, only * the subcommands "namespace current" and "namespace upvar" are compiled * to bytecodes, and the latter only inside a procedure(-like) context. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "namespace upvar" * command at runtime. * *---------------------------------------------------------------------- */ int TclCompileNamespaceCurrentCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Only compile [namespace current] without arguments. */ if (parsePtr->numWords != 1) { return TCL_ERROR; } /* * Not much to do; we compile to a single instruction... */ TclEmitOpcode( INST_NS_CURRENT, envPtr); return TCL_OK; } int TclCompileNamespaceCodeCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); /* * The specification of [namespace code] is rather shocking, in that it is * supposed to check if the argument is itself the result of [namespace * code] and not apply itself in that case. Which is excessively cautious, * but what the test suite checks for. */ if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD || (tokenPtr[1].size > 20 && strncmp(tokenPtr[1].start, "::namespace inscope ", 20) == 0)) { /* * Technically, we could just pass a literal '::namespace inscope ' * term through, but that's something which really shouldn't be * occurring as something that the user writes so we'll just punt it. */ return TCL_ERROR; } /* * Now we can compile using the same strategy as [namespace code]'s normal * implementation does internally. Note that we can't bind the namespace * name directly here, because TclOO plays complex games with namespaces; * the value needs to be determined at runtime for safety. */ PushStringLiteral(envPtr, "::namespace"); PushStringLiteral(envPtr, "inscope"); TclEmitOpcode( INST_NS_CURRENT, envPtr); CompileWord(envPtr, tokenPtr, interp, 1); TclEmitInstInt4( INST_LIST, 4, envPtr); return TCL_OK; } int TclCompileNamespaceOriginCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); TclEmitOpcode( INST_ORIGIN_COMMAND, envPtr); return TCL_OK; } int TclCompileNamespaceQualifiersCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); DefineLineInformation; /* TIP #280 */ int off; if (parsePtr->numWords != 2) { return TCL_ERROR; } CompileWord(envPtr, tokenPtr, interp, 1); PushStringLiteral(envPtr, "0"); PushStringLiteral(envPtr, "::"); TclEmitInstInt4( INST_OVER, 2, envPtr); TclEmitOpcode( INST_STR_FIND_LAST, envPtr); off = CurrentOffset(envPtr); PushStringLiteral(envPtr, "1"); TclEmitOpcode( INST_SUB, envPtr); TclEmitInstInt4( INST_OVER, 2, envPtr); TclEmitInstInt4( INST_OVER, 1, envPtr); TclEmitOpcode( INST_STR_INDEX, envPtr); PushStringLiteral(envPtr, ":"); TclEmitOpcode( INST_STR_EQ, envPtr); off = off - CurrentOffset(envPtr); TclEmitInstInt1( INST_JUMP_TRUE1, off, envPtr); TclEmitOpcode( INST_STR_RANGE, envPtr); return TCL_OK; } int TclCompileNamespaceTailCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); DefineLineInformation; /* TIP #280 */ JumpFixup jumpFixup; if (parsePtr->numWords != 2) { return TCL_ERROR; } /* * Take care; only add 2 to found index if the string was actually found. */ CompileWord(envPtr, tokenPtr, interp, 1); PushStringLiteral(envPtr, "::"); TclEmitInstInt4( INST_OVER, 1, envPtr); TclEmitOpcode( INST_STR_FIND_LAST, envPtr); TclEmitOpcode( INST_DUP, envPtr); PushStringLiteral(envPtr, "0"); TclEmitOpcode( INST_GE, envPtr); TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFixup); PushStringLiteral(envPtr, "2"); TclEmitOpcode( INST_ADD, envPtr); TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127); PushStringLiteral(envPtr, "end"); TclEmitOpcode( INST_STR_RANGE, envPtr); return TCL_OK; } int TclCompileNamespaceUpvarCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr, *otherTokenPtr, *localTokenPtr; int localIndex, numWords, i; DefineLineInformation; /* TIP #280 */ if (envPtr->procPtr == NULL) { return TCL_ERROR; } /* * Only compile [namespace upvar ...]: needs an even number of args, >=4 */ numWords = parsePtr->numWords; if ((numWords % 2) || (numWords < 4)) { return TCL_ERROR; } /* * Push the namespace */ tokenPtr = TokenAfter(parsePtr->tokenPtr); CompileWord(envPtr, tokenPtr, interp, 1); /* * Loop over the (otherVar, thisVar) pairs. If any of the thisVar is not a * local variable, return an error so that the non-compiled command will * be called at runtime. */ localTokenPtr = tokenPtr; for (i=2; inumWords < 2 || parsePtr->numWords > 3) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); idx = 1; /* * If there's an option, check that it's "-command". We don't handle * "-variable" (currently) and anything else is an error. */ if (parsePtr->numWords == 3) { if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TCL_ERROR; } opt = tokenPtr + 1; if (opt->size < 2 || opt->size > 8 || strncmp(opt->start, "-command", opt->size) != 0) { return TCL_ERROR; } tokenPtr = TokenAfter(tokenPtr); idx++; } /* * Issue the bytecode. */ CompileWord(envPtr, tokenPtr, interp, idx); TclEmitOpcode( INST_RESOLVE_COMMAND, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileRegexpCmd -- * * Procedure called to compile the "regexp" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "regexp" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileRegexpCmd( Tcl_Interp *interp, /* Tcl interpreter for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the * command. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds the resulting instructions. */ { Tcl_Token *varTokenPtr; /* Pointer to the Tcl_Token representing the * parse of the RE or string. */ int i, len, nocase, exact, sawLast, simple; const char *str; DefineLineInformation; /* TIP #280 */ /* * We are only interested in compiling simple regexp cases. Currently * supported compile cases are: * regexp ?-nocase? ?--? staticString $var * regexp ?-nocase? ?--? {^staticString$} $var */ if (parsePtr->numWords < 3) { return TCL_ERROR; } simple = 0; nocase = 0; sawLast = 0; varTokenPtr = parsePtr->tokenPtr; /* * We only look for -nocase and -- as options. Everything else gets pushed * to runtime execution. This is different than regexp's runtime option * handling, but satisfies our stricter needs. */ for (i = 1; i < parsePtr->numWords - 2; i++) { varTokenPtr = TokenAfter(varTokenPtr); if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { /* * Not a simple string, so punt to runtime. */ return TCL_ERROR; } str = varTokenPtr[1].start; len = varTokenPtr[1].size; if ((len == 2) && (str[0] == '-') && (str[1] == '-')) { sawLast++; i++; break; } else if ((len > 1) && (strncmp(str,"-nocase",(unsigned)len) == 0)) { nocase = 1; } else { /* * Not an option we recognize. */ return TCL_ERROR; } } if ((parsePtr->numWords - i) != 2) { /* * We don't support capturing to variables. */ return TCL_ERROR; } /* * Get the regexp string. If it is not a simple string or can't be * converted to a glob pattern, push the word for the INST_REGEXP. * Keep changes here in sync with TclCompileSwitchCmd Switch_Regexp. */ varTokenPtr = TokenAfter(varTokenPtr); if (varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { Tcl_DString ds; str = varTokenPtr[1].start; len = varTokenPtr[1].size; /* * If it has a '-', it could be an incorrectly formed regexp command. */ if ((*str == '-') && !sawLast) { return TCL_ERROR; } if (len == 0) { /* * The semantics of regexp are always match on re == "". */ PushStringLiteral(envPtr, "1"); return TCL_OK; } /* * Attempt to convert pattern to glob. If successful, push the * converted pattern as a literal. */ if (TclReToGlob(NULL, varTokenPtr[1].start, len, &ds, &exact, NULL) == TCL_OK) { simple = 1; PushLiteral(envPtr, Tcl_DStringValue(&ds),Tcl_DStringLength(&ds)); Tcl_DStringFree(&ds); } } if (!simple) { CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords-2); } /* * Push the string arg. */ varTokenPtr = TokenAfter(varTokenPtr); CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords-1); if (simple) { if (exact && !nocase) { TclEmitOpcode( INST_STR_EQ, envPtr); } else { TclEmitInstInt1( INST_STR_MATCH, nocase, envPtr); } } else { /* * Pass correct RE compile flags. We use only Int1 (8-bit), but * that handles all the flags we want to pass. * Don't use TCL_REG_NOSUB as we may have backrefs. */ int cflags = TCL_REG_ADVANCED | (nocase ? TCL_REG_NOCASE : 0); TclEmitInstInt1( INST_REGEXP, cflags, envPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileRegsubCmd -- * * Procedure called to compile the "regsub" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "regsub" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileRegsubCmd( Tcl_Interp *interp, /* Tcl interpreter for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the * command. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds the resulting instructions. */ { /* * We only compile the case with [regsub -all] where the pattern is both * known at compile time and simple (i.e., no RE metacharacters). That is, * the pattern must be translatable into a glob like "*foo*" with no other * glob metacharacters inside it; there must be some "foo" in there too. * The substitution string must also be known at compile time and free of * metacharacters ("\digit" and "&"). Finally, there must not be a * variable mentioned in the [regsub] to write the result back to (because * we can't get the count of substitutions that would be the result in * that case). The key is that these are the conditions under which a * [string map] could be used instead, in particular a [string map] of the * form we can compile to bytecode. * * In short, we look for: * * regsub -all [--] simpleRE string simpleReplacement * * The only optional part is the "--", and no other options are handled. */ DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr, *stringTokenPtr; Tcl_Obj *patternObj = NULL, *replacementObj = NULL; Tcl_DString pattern; const char *bytes; int len, exact, quantified, result = TCL_ERROR; if (parsePtr->numWords < 5 || parsePtr->numWords > 6) { return TCL_ERROR; } /* * Parse the "-all", which must be the first argument (other options not * supported, non-"-all" substitution we can't compile). */ tokenPtr = TokenAfter(parsePtr->tokenPtr); if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD || tokenPtr[1].size != 4 || strncmp(tokenPtr[1].start, "-all", 4)) { return TCL_ERROR; } /* * Get the pattern into patternObj, checking for "--" in the process. */ Tcl_DStringInit(&pattern); tokenPtr = TokenAfter(tokenPtr); patternObj = Tcl_NewObj(); if (!TclWordKnownAtCompileTime(tokenPtr, patternObj)) { goto done; } if (Tcl_GetString(patternObj)[0] == '-') { if (strcmp(Tcl_GetString(patternObj), "--") != 0 || parsePtr->numWords == 5) { goto done; } tokenPtr = TokenAfter(tokenPtr); Tcl_DecrRefCount(patternObj); patternObj = Tcl_NewObj(); if (!TclWordKnownAtCompileTime(tokenPtr, patternObj)) { goto done; } } else if (parsePtr->numWords == 6) { goto done; } /* * Identify the code which produces the string to apply the substitution * to (stringTokenPtr), and the replacement string (into replacementObj). */ stringTokenPtr = TokenAfter(tokenPtr); tokenPtr = TokenAfter(stringTokenPtr); replacementObj = Tcl_NewObj(); if (!TclWordKnownAtCompileTime(tokenPtr, replacementObj)) { goto done; } /* * Next, higher-level checks. Is the RE a very simple glob? Is the * replacement "simple"? */ bytes = Tcl_GetStringFromObj(patternObj, &len); if (TclReToGlob(NULL, bytes, len, &pattern, &exact, &quantified) != TCL_OK || exact || quantified) { goto done; } bytes = Tcl_DStringValue(&pattern); if (*bytes++ != '*') { goto done; } while (1) { switch (*bytes) { case '*': if (bytes[1] == '\0') { /* * OK, we've proved there are no metacharacters except for the * '*' at each end. */ len = Tcl_DStringLength(&pattern) - 2; if (len > 0) { goto isSimpleGlob; } /* * The pattern is "**"! I believe that should be impossible, * but we definitely can't handle that at all. */ } case '\0': case '?': case '[': case '\\': goto done; } bytes++; } isSimpleGlob: for (bytes = Tcl_GetString(replacementObj); *bytes; bytes++) { switch (*bytes) { case '\\': case '&': goto done; } } /* * Proved the simplicity constraints! Time to issue the code. */ result = TCL_OK; bytes = Tcl_DStringValue(&pattern) + 1; PushLiteral(envPtr, bytes, len); bytes = Tcl_GetStringFromObj(replacementObj, &len); PushLiteral(envPtr, bytes, len); CompileWord(envPtr, stringTokenPtr, interp, parsePtr->numWords-2); TclEmitOpcode( INST_STR_MAP, envPtr); done: Tcl_DStringFree(&pattern); if (patternObj) { Tcl_DecrRefCount(patternObj); } if (replacementObj) { Tcl_DecrRefCount(replacementObj); } return result; } /* *---------------------------------------------------------------------- * * TclCompileReturnCmd -- * * Procedure called to compile the "return" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "return" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileReturnCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * General syntax: [return ?-option value ...? ?result?] * An even number of words means an explicit result argument is present. */ int level, code, objc, size, status = TCL_OK; int numWords = parsePtr->numWords; int explicitResult = (0 == (numWords % 2)); int numOptionWords = numWords - 1 - explicitResult; Tcl_Obj *returnOpts, **objv; Tcl_Token *wordTokenPtr = TokenAfter(parsePtr->tokenPtr); DefineLineInformation; /* TIP #280 */ /* * Check for special case which can always be compiled: * return -options * Unlike the normal [return] compilation, this version does everything at * runtime so it can handle arbitrary words and not just literals. Note * that if INST_RETURN_STK wasn't already needed for something else * ('finally' clause processing) this piece of code would not be present. */ if ((numWords == 4) && (wordTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) && (wordTokenPtr[1].size == 8) && (strncmp(wordTokenPtr[1].start, "-options", 8) == 0)) { Tcl_Token *optsTokenPtr = TokenAfter(wordTokenPtr); Tcl_Token *msgTokenPtr = TokenAfter(optsTokenPtr); CompileWord(envPtr, optsTokenPtr, interp, 2); CompileWord(envPtr, msgTokenPtr, interp, 3); TclEmitInvoke(envPtr, INST_RETURN_STK); return TCL_OK; } /* * Allocate some working space. */ objv = TclStackAlloc(interp, numOptionWords * sizeof(Tcl_Obj *)); /* * Scan through the return options. If any are unknown at compile time, * there is no value in bytecompiling. Save the option values known in an * objv array for merging into a return options dictionary. * * TODO: There is potential for improvement if all option keys are known * at compile time and all option values relating to '-code' and '-level' * are known at compile time. */ for (objc = 0; objc < numOptionWords; objc++) { objv[objc] = Tcl_NewObj(); Tcl_IncrRefCount(objv[objc]); if (!TclWordKnownAtCompileTime(wordTokenPtr, objv[objc])) { /* * Non-literal, so punt to run-time assembly of the dictionary. */ for (; objc>=0 ; objc--) { TclDecrRefCount(objv[objc]); } TclStackFree(interp, objv); goto issueRuntimeReturn; } wordTokenPtr = TokenAfter(wordTokenPtr); } status = TclMergeReturnOptions(interp, objc, objv, &returnOpts, &code, &level); while (--objc >= 0) { TclDecrRefCount(objv[objc]); } TclStackFree(interp, objv); if (TCL_ERROR == status) { /* * Something was bogus in the return options. Clear the error message, * and report back to the compiler that this must be interpreted at * runtime. */ Tcl_ResetResult(interp); return TCL_ERROR; } /* * All options are known at compile time, so we're going to bytecompile. * Emit instructions to push the result on the stack. */ if (explicitResult) { CompileWord(envPtr, wordTokenPtr, interp, numWords-1); } else { /* * No explict result argument, so default result is empty string. */ PushStringLiteral(envPtr, ""); } /* * Check for optimization: When [return] is in a proc, and there's no * enclosing [catch], and there are no return options, then the INST_DONE * instruction is equivalent, and may be more efficient. */ if (numOptionWords == 0 && envPtr->procPtr != NULL) { /* * We have default return options and we're in a proc ... */ int index = envPtr->exceptArrayNext - 1; int enclosingCatch = 0; while (index >= 0) { ExceptionRange range = envPtr->exceptArrayPtr[index]; if ((range.type == CATCH_EXCEPTION_RANGE) && (range.catchOffset == -1)) { enclosingCatch = 1; break; } index--; } if (!enclosingCatch) { /* * ... and there is no enclosing catch. Issue the maximally * efficient exit instruction. */ Tcl_DecrRefCount(returnOpts); TclEmitOpcode(INST_DONE, envPtr); TclAdjustStackDepth(1, envPtr); return TCL_OK; } } /* Optimize [return -level 0 $x]. */ Tcl_DictObjSize(NULL, returnOpts, &size); if (size == 0 && level == 0 && code == TCL_OK) { Tcl_DecrRefCount(returnOpts); return TCL_OK; } /* * Could not use the optimization, so we push the return options dict, and * emit the INST_RETURN_IMM instruction with code and level as operands. */ CompileReturnInternal(envPtr, INST_RETURN_IMM, code, level, returnOpts); return TCL_OK; issueRuntimeReturn: /* * Assemble the option dictionary (as a list as that's good enough). */ wordTokenPtr = TokenAfter(parsePtr->tokenPtr); for (objc=1 ; objc<=numOptionWords ; objc++) { CompileWord(envPtr, wordTokenPtr, interp, objc); wordTokenPtr = TokenAfter(wordTokenPtr); } TclEmitInstInt4(INST_LIST, numOptionWords, envPtr); /* * Push the result. */ if (explicitResult) { CompileWord(envPtr, wordTokenPtr, interp, numWords-1); } else { PushStringLiteral(envPtr, ""); } /* * Issue the RETURN itself. */ TclEmitInvoke(envPtr, INST_RETURN_STK); return TCL_OK; } static void CompileReturnInternal( CompileEnv *envPtr, unsigned char op, int code, int level, Tcl_Obj *returnOpts) { if (level == 0 && (code == TCL_BREAK || code == TCL_CONTINUE)) { ExceptionRange *rangePtr; ExceptionAux *exceptAux; rangePtr = TclGetInnermostExceptionRange(envPtr, code, &exceptAux); if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) { TclCleanupStackForBreakContinue(envPtr, exceptAux); if (code == TCL_BREAK) { TclAddLoopBreakFixup(envPtr, exceptAux); } else { TclAddLoopContinueFixup(envPtr, exceptAux); } Tcl_DecrRefCount(returnOpts); return; } } TclEmitPush(TclAddLiteralObj(envPtr, returnOpts, NULL), envPtr); TclEmitInstInt4(op, code, envPtr); TclEmitInt4(level, envPtr); } void TclCompileSyntaxError( Tcl_Interp *interp, CompileEnv *envPtr) { Tcl_Obj *msg = Tcl_GetObjResult(interp); int numBytes; const char *bytes = TclGetStringFromObj(msg, &numBytes); TclErrorStackResetIf(interp, bytes, numBytes); TclEmitPush(TclRegisterNewLiteral(envPtr, bytes, numBytes), envPtr); CompileReturnInternal(envPtr, INST_SYNTAX, TCL_ERROR, 0, TclNoErrorStack(interp, Tcl_GetReturnOptions(interp, TCL_ERROR))); Tcl_ResetResult(interp); } /* *---------------------------------------------------------------------- * * TclCompileUpvarCmd -- * * Procedure called to compile the "upvar" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "upvar" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileUpvarCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr, *otherTokenPtr, *localTokenPtr; int localIndex, numWords, i; DefineLineInformation; /* TIP #280 */ Tcl_Obj *objPtr; if (envPtr->procPtr == NULL) { return TCL_ERROR; } numWords = parsePtr->numWords; if (numWords < 3) { return TCL_ERROR; } /* * Push the frame index if it is known at compile time */ objPtr = Tcl_NewObj(); tokenPtr = TokenAfter(parsePtr->tokenPtr); if (TclWordKnownAtCompileTime(tokenPtr, objPtr)) { CallFrame *framePtr; const Tcl_ObjType *newTypePtr, *typePtr = objPtr->typePtr; /* * Attempt to convert to a level reference. Note that TclObjGetFrame * only changes the obj type when a conversion was successful. */ TclObjGetFrame(interp, objPtr, &framePtr); newTypePtr = objPtr->typePtr; Tcl_DecrRefCount(objPtr); if (newTypePtr != typePtr) { if (numWords%2) { return TCL_ERROR; } /* TODO: Push the known value instead? */ CompileWord(envPtr, tokenPtr, interp, 1); otherTokenPtr = TokenAfter(tokenPtr); i = 2; } else { if (!(numWords%2)) { return TCL_ERROR; } PushStringLiteral(envPtr, "1"); otherTokenPtr = tokenPtr; i = 1; } } else { Tcl_DecrRefCount(objPtr); return TCL_ERROR; } /* * Loop over the (otherVar, thisVar) pairs. If any of the thisVar is not a * local variable, return an error so that the non-compiled command will * be called at runtime. */ for (; inumWords; if (numWords < 2) { return TCL_ERROR; } /* * Bail out if not compiling a proc body */ if (envPtr->procPtr == NULL) { return TCL_ERROR; } /* * Loop over the (var, value) pairs. */ valueTokenPtr = parsePtr->tokenPtr; for (i=1; inumComponents; Tcl_Token *lastTokenPtr; int full, localIndex; /* * Determine if the tail is (a) known at compile time, and (b) not an * array element. Should any of these fail, return an error so that the * non-compiled command will be called at runtime. * * In order for the tail to be known at compile time, the last token in * the word has to be constant and contain "::" if it is not the only one. */ if (!EnvHasLVT(envPtr)) { return -1; } TclNewObj(tailPtr); if (TclWordKnownAtCompileTime(varTokenPtr, tailPtr)) { full = 1; lastTokenPtr = varTokenPtr; } else { full = 0; lastTokenPtr = varTokenPtr + n; if (!TclWordKnownAtCompileTime(lastTokenPtr, tailPtr)) { Tcl_DecrRefCount(tailPtr); return -1; } } tailName = TclGetStringFromObj(tailPtr, &len); if (len) { if (*(tailName+len-1) == ')') { /* * Possible array: bail out */ Tcl_DecrRefCount(tailPtr); return -1; } /* * Get the tail: immediately after the last '::' */ for (p = tailName + len -1; p > tailName; p--) { if ((*p == ':') && (*(p-1) == ':')) { p++; break; } } if (!full && (p == tailName)) { /* * No :: in the last component. */ Tcl_DecrRefCount(tailPtr); return -1; } len -= p - tailName; tailName = p; } localIndex = TclFindCompiledLocal(tailName, len, 1, envPtr); Tcl_DecrRefCount(tailPtr); return localIndex; } /* * ---------------------------------------------------------------------- * * TclCompileObjectNextCmd, TclCompileObjectSelfCmd -- * * Compilations of the TclOO utility commands [next] and [self]. * * ---------------------------------------------------------------------- */ int TclCompileObjectNextCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; int i; if (parsePtr->numWords > 255) { return TCL_ERROR; } for (i=0 ; inumWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } TclEmitInstInt1( INST_TCLOO_NEXT, i, envPtr); return TCL_OK; } int TclCompileObjectNextToCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; int i; if (parsePtr->numWords < 2 || parsePtr->numWords > 255) { return TCL_ERROR; } for (i=0 ; inumWords ; i++) { CompileWord(envPtr, tokenPtr, interp, i); tokenPtr = TokenAfter(tokenPtr); } TclEmitInstInt1( INST_TCLOO_NEXT_CLASS, i, envPtr); return TCL_OK; } int TclCompileObjectSelfCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * We only handle [self] and [self object] (which is the same operation). * These are the only very common operations on [self] for which * bytecoding is at all reasonable. */ if (parsePtr->numWords == 1) { goto compileSelfObject; } else if (parsePtr->numWords == 2) { Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr), *subcmd; if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD || tokenPtr[1].size==0) { return TCL_ERROR; } subcmd = tokenPtr + 1; if (strncmp(subcmd->start, "object", subcmd->size) == 0) { goto compileSelfObject; } else if (strncmp(subcmd->start, "namespace", subcmd->size) == 0) { goto compileSelfNamespace; } } /* * Can't compile; handle with runtime call. */ return TCL_ERROR; compileSelfObject: /* * This delegates the entire problem to a single opcode. */ TclEmitOpcode( INST_TCLOO_SELF, envPtr); return TCL_OK; compileSelfNamespace: /* * This is formally only correct with TclOO methods as they are currently * implemented; it assumes that the current namespace is invariably when a * TclOO context is present is the object's namespace, and that's * technically only something that's a matter of current policy. But it * avoids creating another opcode, so that's all good! */ TclEmitOpcode( INST_TCLOO_SELF, envPtr); TclEmitOpcode( INST_POP, envPtr); TclEmitOpcode( INST_NS_CURRENT, envPtr); return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclIOGT.c0000644000175000017500000011335612663660065014625 0ustar sergeisergei/* * tclIOGT.c -- * * Implements a generic transformation exposing the underlying API at the * script level. Contributed by Andreas Kupries. * * Copyright (c) 2000 Ajuba Solutions * Copyright (c) 1999-2000 Andreas Kupries (a.kupries@westend.com) * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclIO.h" /* * Forward declarations of internal procedures. First the driver procedures of * the transformation. */ static int TransformBlockModeProc(ClientData instanceData, int mode); static int TransformCloseProc(ClientData instanceData, Tcl_Interp *interp); static int TransformInputProc(ClientData instanceData, char *buf, int toRead, int *errorCodePtr); static int TransformOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCodePtr); static int TransformSeekProc(ClientData instanceData, long offset, int mode, int *errorCodePtr); static int TransformSetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, const char *value); static int TransformGetOptionProc(ClientData instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); static void TransformWatchProc(ClientData instanceData, int mask); static int TransformGetFileHandleProc(ClientData instanceData, int direction, ClientData *handlePtr); static int TransformNotifyProc(ClientData instanceData, int mask); static Tcl_WideInt TransformWideSeekProc(ClientData instanceData, Tcl_WideInt offset, int mode, int *errorCodePtr); /* * Forward declarations of internal procedures. Secondly the procedures for * handling and generating fileeevents. */ static void TransformChannelHandlerTimer(ClientData clientData); /* * Forward declarations of internal procedures. Third, helper procedures * encapsulating essential tasks. */ typedef struct TransformChannelData TransformChannelData; static int ExecuteCallback(TransformChannelData *ctrl, Tcl_Interp *interp, unsigned char *op, unsigned char *buf, int bufLen, int transmit, int preserve); /* * Action codes to give to 'ExecuteCallback' (argument 'transmit'), telling * the procedure what to do with the result of the script it calls. */ #define TRANSMIT_DONT 0 /* No transfer to do. */ #define TRANSMIT_DOWN 1 /* Transfer to the underlying channel. */ #define TRANSMIT_SELF 2 /* Transfer into our channel. */ #define TRANSMIT_IBUF 3 /* Transfer to internal input buffer. */ #define TRANSMIT_NUM 4 /* Transfer number to 'maxRead'. */ /* * Codes for 'preserve' of 'ExecuteCallback'. */ #define P_PRESERVE 1 #define P_NO_PRESERVE 0 /* * Strings for the action codes delivered to the script implementing a * transformation. Argument 'op' of 'ExecuteCallback'. */ #define A_CREATE_WRITE (UCHARP("create/write")) #define A_DELETE_WRITE (UCHARP("delete/write")) #define A_FLUSH_WRITE (UCHARP("flush/write")) #define A_WRITE (UCHARP("write")) #define A_CREATE_READ (UCHARP("create/read")) #define A_DELETE_READ (UCHARP("delete/read")) #define A_FLUSH_READ (UCHARP("flush/read")) #define A_READ (UCHARP("read")) #define A_QUERY_MAXREAD (UCHARP("query/maxRead")) #define A_CLEAR_READ (UCHARP("clear/read")) /* * Management of a simple buffer. */ typedef struct ResultBuffer ResultBuffer; static inline void ResultClear(ResultBuffer *r); static inline void ResultInit(ResultBuffer *r); static inline int ResultEmpty(ResultBuffer *r); static inline int ResultCopy(ResultBuffer *r, unsigned char *buf, size_t toRead); static inline void ResultAdd(ResultBuffer *r, unsigned char *buf, size_t toWrite); /* * This structure describes the channel type structure for Tcl-based * transformations. */ static const Tcl_ChannelType transformChannelType = { "transform", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ TransformCloseProc, /* Close proc. */ TransformInputProc, /* Input proc. */ TransformOutputProc, /* Output proc. */ TransformSeekProc, /* Seek proc. */ TransformSetOptionProc, /* Set option proc. */ TransformGetOptionProc, /* Get option proc. */ TransformWatchProc, /* Initialize notifier. */ TransformGetFileHandleProc, /* Get OS handles out of channel. */ NULL, /* close2proc */ TransformBlockModeProc, /* Set blocking/nonblocking mode.*/ NULL, /* Flush proc. */ TransformNotifyProc, /* Handling of events bubbling up. */ TransformWideSeekProc, /* Wide seek proc. */ NULL, /* Thread action. */ NULL /* Truncate. */ }; /* * Possible values for 'flags' field in control structure, see below. */ #define CHANNEL_ASYNC (1<<0) /* Non-blocking mode. */ /* * Definition of the structure containing the information about the internal * input buffer. */ struct ResultBuffer { unsigned char *buf; /* Reference to the buffer area. */ size_t allocated; /* Allocated size of the buffer area. */ size_t used; /* Number of bytes in the buffer, no more than * number allocated. */ }; /* * Additional bytes to allocate during buffer expansion. */ #define INCREMENT 512 /* * Number of milliseconds to wait before firing an event to flush out * information waiting in buffers (fileevent support). */ #define FLUSH_DELAY 5 /* * Convenience macro to make some casts easier to use. */ #define UCHARP(x) ((unsigned char *) (x)) /* * Definition of a structure used by all transformations generated here to * maintain their local state. */ struct TransformChannelData { /* * General section. Data to integrate the transformation into the channel * system. */ Tcl_Channel self; /* Our own Channel handle. */ int readIsFlushed; /* Flag to note whether in.flushProc was * called or not. */ int eofPending; /* Flag: EOF seen down, not raised up */ int flags; /* Currently CHANNEL_ASYNC or zero. */ int watchMask; /* Current watch/event/interest mask. */ int mode; /* Mode of parent channel, OR'ed combination * of TCL_READABLE, TCL_WRITABLE. */ Tcl_TimerToken timer; /* Timer for automatic flushing of information * sitting in an internal buffer. Required for * full fileevent support. */ /* * Transformation specific data. */ int maxRead; /* Maximum allowed number of bytes to read, as * given to us by the Tcl script implementing * the transformation. */ Tcl_Interp *interp; /* Reference to the interpreter which created * the transformation. Used to execute the * code below. */ Tcl_Obj *command; /* Tcl code to execute for a buffer */ ResultBuffer result; /* Internal buffer used to store the result of * a transformation of incoming data. Also * serves as buffer of all data not yet * consumed by the reader. */ int refCount; }; static void PreserveData( TransformChannelData *dataPtr) { dataPtr->refCount++; } static void ReleaseData( TransformChannelData *dataPtr) { if (--dataPtr->refCount) { return; } ResultClear(&dataPtr->result); Tcl_DecrRefCount(dataPtr->command); ckfree(dataPtr); } /* *---------------------------------------------------------------------- * * TclChannelTransform -- * * Implements the Tcl "testchannel transform" debugging command. This is * part of the testing environment. This sets up a tcl script (cmdObjPtr) * to be used as a transform on the channel. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int TclChannelTransform( Tcl_Interp *interp, /* Interpreter for result. */ Tcl_Channel chan, /* Channel to transform. */ Tcl_Obj *cmdObjPtr) /* Script to use for transform. */ { Channel *chanPtr; /* The actual channel. */ ChannelState *statePtr; /* State info for channel. */ int mode; /* Read/write mode of the channel. */ int objc; TransformChannelData *dataPtr; Tcl_DString ds; if (chan == NULL) { return TCL_ERROR; } if (TCL_OK != Tcl_ListObjLength(interp, cmdObjPtr, &objc)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("-command value is not a list", -1)); return TCL_ERROR; } chanPtr = (Channel *) chan; statePtr = chanPtr->state; chanPtr = statePtr->topChanPtr; chan = (Tcl_Channel) chanPtr; mode = (statePtr->flags & (TCL_READABLE|TCL_WRITABLE)); /* * Now initialize the transformation state and stack it upon the specified * channel. One of the necessary things to do is to retrieve the blocking * regime of the underlying channel and to use the same for us too. */ dataPtr = ckalloc(sizeof(TransformChannelData)); dataPtr->refCount = 1; Tcl_DStringInit(&ds); Tcl_GetChannelOption(interp, chan, "-blocking", &ds); dataPtr->readIsFlushed = 0; dataPtr->eofPending = 0; dataPtr->flags = 0; if (ds.string[0] == '0') { dataPtr->flags |= CHANNEL_ASYNC; } Tcl_DStringFree(&ds); dataPtr->watchMask = 0; dataPtr->mode = mode; dataPtr->timer = NULL; dataPtr->maxRead = 4096; /* Initial value not relevant. */ dataPtr->interp = interp; dataPtr->command = cmdObjPtr; Tcl_IncrRefCount(dataPtr->command); ResultInit(&dataPtr->result); dataPtr->self = Tcl_StackChannel(interp, &transformChannelType, dataPtr, mode, chan); if (dataPtr->self == NULL) { Tcl_AppendPrintfToObj(Tcl_GetObjResult(interp), "\nfailed to stack channel \"%s\"", Tcl_GetChannelName(chan)); ReleaseData(dataPtr); return TCL_ERROR; } Tcl_Preserve(dataPtr->self); /* * At last initialize the transformation at the script level. */ PreserveData(dataPtr); if ((dataPtr->mode & TCL_WRITABLE) && ExecuteCallback(dataPtr, NULL, A_CREATE_WRITE, NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE) != TCL_OK){ Tcl_UnstackChannel(interp, chan); ReleaseData(dataPtr); return TCL_ERROR; } if ((dataPtr->mode & TCL_READABLE) && ExecuteCallback(dataPtr, NULL, A_CREATE_READ, NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE) != TCL_OK) { ExecuteCallback(dataPtr, NULL, A_DELETE_WRITE, NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE); Tcl_UnstackChannel(interp, chan); ReleaseData(dataPtr); return TCL_ERROR; } ReleaseData(dataPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * ExecuteCallback -- * * Executes the defined callback for buffer and operation. * * Side effects: * As of the executed tcl script. * * Result: * A standard TCL error code. In case of an error a message is left in * the result area of the specified interpreter. * *---------------------------------------------------------------------- */ static int ExecuteCallback( TransformChannelData *dataPtr, /* Transformation with the callback. */ Tcl_Interp *interp, /* Current interpreter, possibly NULL. */ unsigned char *op, /* Operation invoking the callback. */ unsigned char *buf, /* Buffer to give to the script. */ int bufLen, /* And its length. */ int transmit, /* Flag, determines whether the result of the * callback is sent to the underlying channel * or not. */ int preserve) /* Flag. If true the procedure will preserve * the result state of all accessed * interpreters. */ { Tcl_Obj *resObj; /* See below, switch (transmit). */ int resLen; unsigned char *resBuf; Tcl_InterpState state = NULL; int res = TCL_OK; Tcl_Obj *command = TclListObjCopy(NULL, dataPtr->command); Tcl_Interp *eval = dataPtr->interp; Tcl_Preserve(eval); /* * Step 1, create the complete command to execute. Do this by appending * operation and buffer to operate upon to a copy of the callback * definition. We *cannot* create a list containing 3 objects and then use * 'Tcl_EvalObjv', because the command may contain additional prefixed * arguments. Feather's curried commands would come in handy here. */ if (preserve == P_PRESERVE) { state = Tcl_SaveInterpState(eval, res); } Tcl_IncrRefCount(command); Tcl_ListObjAppendElement(NULL, command, Tcl_NewStringObj((char *) op, -1)); /* * Use a byte-array to prevent the misinterpretation of binary data coming * through as UTF while at the tcl level. */ Tcl_ListObjAppendElement(NULL, command, Tcl_NewByteArrayObj(buf, bufLen)); /* * Step 2, execute the command at the global level of the interpreter used * to create the transformation. Destroy the command afterward. If an * error occured and the current interpreter is defined and not equal to * the interpreter for the callback, then copy the error message into * current interpreter. Don't copy if in preservation mode. */ res = Tcl_EvalObjEx(eval, command, TCL_EVAL_GLOBAL); Tcl_DecrRefCount(command); command = NULL; if ((res != TCL_OK) && (interp != NULL) && (eval != interp) && (preserve == P_NO_PRESERVE)) { Tcl_SetObjResult(interp, Tcl_GetObjResult(eval)); Tcl_Release(eval); return res; } /* * Step 3, transmit a possible conversion result to the underlying * channel, or ourselves. */ switch (transmit) { case TRANSMIT_DONT: /* nothing to do */ break; case TRANSMIT_DOWN: if (dataPtr->self == NULL) { break; } resObj = Tcl_GetObjResult(eval); resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen); Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self), (char *) resBuf, resLen); break; case TRANSMIT_SELF: if (dataPtr->self == NULL) { break; } resObj = Tcl_GetObjResult(eval); resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen); Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen); break; case TRANSMIT_IBUF: resObj = Tcl_GetObjResult(eval); resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen); ResultAdd(&dataPtr->result, resBuf, resLen); break; case TRANSMIT_NUM: /* * Interpret result as integer number. */ resObj = Tcl_GetObjResult(eval); TclGetIntFromObj(eval, resObj, &dataPtr->maxRead); break; } Tcl_ResetResult(eval); if (preserve == P_PRESERVE) { (void) Tcl_RestoreInterpState(eval, state); } Tcl_Release(eval); return res; } /* *---------------------------------------------------------------------- * * TransformBlockModeProc -- * * Trap handler. Called by the generic IO system during option processing * to change the blocking mode of the channel. * * Side effects: * Forwards the request to the underlying channel. * * Result: * 0 if successful, errno when failed. * *---------------------------------------------------------------------- */ static int TransformBlockModeProc( ClientData instanceData, /* State of transformation. */ int mode) /* New blocking mode. */ { TransformChannelData *dataPtr = instanceData; if (mode == TCL_MODE_NONBLOCKING) { dataPtr->flags |= CHANNEL_ASYNC; } else { dataPtr->flags &= ~CHANNEL_ASYNC; } return 0; } /* *---------------------------------------------------------------------- * * TransformCloseProc -- * * Trap handler. Called by the generic IO system during destruction of * the transformation channel. * * Side effects: * Releases the memory allocated in 'Tcl_TransformObjCmd'. * * Result: * None. * *---------------------------------------------------------------------- */ static int TransformCloseProc( ClientData instanceData, Tcl_Interp *interp) { TransformChannelData *dataPtr = instanceData; /* * Important: In this procedure 'dataPtr->self' already points to the * underlying channel. * * There is no need to cancel an existing channel handler, this is already * done. Either by 'Tcl_UnstackChannel' or by the general cleanup in * 'Tcl_Close'. * * But we have to cancel an active timer to prevent it from firing on the * removed channel. */ if (dataPtr->timer != NULL) { Tcl_DeleteTimerHandler(dataPtr->timer); dataPtr->timer = NULL; } /* * Now flush data waiting in internal buffers to output and input. The * input must be done despite the fact that there is no real receiver for * it anymore. But the scripts might have sideeffects other parts of the * system rely on (f.e. signaling the close to interested parties). */ PreserveData(dataPtr); if (dataPtr->mode & TCL_WRITABLE) { ExecuteCallback(dataPtr, interp, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN, P_PRESERVE); } if ((dataPtr->mode & TCL_READABLE) && !dataPtr->readIsFlushed) { dataPtr->readIsFlushed = 1; ExecuteCallback(dataPtr, interp, A_FLUSH_READ, NULL, 0, TRANSMIT_IBUF, P_PRESERVE); } if (dataPtr->mode & TCL_WRITABLE) { ExecuteCallback(dataPtr, interp, A_DELETE_WRITE, NULL, 0, TRANSMIT_DONT, P_PRESERVE); } if (dataPtr->mode & TCL_READABLE) { ExecuteCallback(dataPtr, interp, A_DELETE_READ, NULL, 0, TRANSMIT_DONT, P_PRESERVE); } ReleaseData(dataPtr); /* * General cleanup. */ Tcl_Release(dataPtr->self); dataPtr->self = NULL; ReleaseData(dataPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TransformInputProc -- * * Called by the generic IO system to convert read data. * * Side effects: * As defined by the conversion. * * Result: * A transformed buffer. * *---------------------------------------------------------------------- */ static int TransformInputProc( ClientData instanceData, char *buf, int toRead, int *errorCodePtr) { TransformChannelData *dataPtr = instanceData; int gotBytes, read, copied; Tcl_Channel downChan; /* * Should assert(dataPtr->mode & TCL_READABLE); */ if (toRead == 0 || dataPtr->self == NULL) { /* * Catch a no-op. TODO: Is this a panic()? */ return 0; } gotBytes = 0; downChan = Tcl_GetStackedChannel(dataPtr->self); PreserveData(dataPtr); while (toRead > 0) { /* * Loop until the request is satisfied (or no data is available from * below, possibly EOF). */ copied = ResultCopy(&dataPtr->result, UCHARP(buf), toRead); toRead -= copied; buf += copied; gotBytes += copied; if (toRead == 0) { /* * The request was completely satisfied from our buffers. We can * break out of the loop and return to the caller. */ break; } /* * Length (dataPtr->result) == 0, toRead > 0 here. Use the incoming * 'buf'! as target to store the intermediary information read from * the underlying channel. * * Ask the tcl level how much data it allows us to read from the * underlying channel. This feature allows the transform to signal EOF * upstream although there is none downstream. Useful to control an * unbounded 'fcopy', either through counting bytes, or by pattern * matching. */ ExecuteCallback(dataPtr, NULL, A_QUERY_MAXREAD, NULL, 0, TRANSMIT_NUM /* -> maxRead */, P_PRESERVE); if (dataPtr->maxRead >= 0) { if (dataPtr->maxRead < toRead) { toRead = dataPtr->maxRead; } } /* else: 'maxRead < 0' == Accept the current value of toRead. */ if (toRead <= 0) { break; } if (dataPtr->eofPending) { /* * Already saw EOF from downChan; don't ask again. * NOTE: Could move this up to avoid the last maxRead * execution. Believe this would still be correct behavior, * but the test suite tests the whole command callback * sequence, so leave it unchanged for now. */ break; } /* * Get bytes from the underlying channel. */ read = Tcl_ReadRaw(downChan, buf, toRead); if (read < 0) { if (Tcl_InputBlocked(downChan) && (gotBytes > 0)) { /* * Zero bytes available from downChan because blocked. * But nonzero bytes already copied, so total is a * valid blocked short read. Return to caller. */ break; } /* * Either downChan is not blocked (there's a real error). * or it is and there are no bytes copied yet. In either * case we want to pass the "error" along to the caller, * either to report an error, or to signal to the caller * that zero bytes are available because blocked. */ *errorCodePtr = Tcl_GetErrno(); gotBytes = -1; break; } else if (read == 0) { /* * Zero returned from Tcl_ReadRaw() always indicates EOF * on the down channel. */ dataPtr->eofPending = 1; dataPtr->readIsFlushed = 1; ExecuteCallback(dataPtr, NULL, A_FLUSH_READ, NULL, 0, TRANSMIT_IBUF, P_PRESERVE); if (ResultEmpty(&dataPtr->result)) { /* * We had nothing to flush. */ break; } continue; /* at: while (toRead > 0) */ } /* read == 0 */ /* * Transform the read chunk and add the result to our read buffer * (dataPtr->result). */ if (ExecuteCallback(dataPtr, NULL, A_READ, UCHARP(buf), read, TRANSMIT_IBUF, P_PRESERVE) != TCL_OK) { *errorCodePtr = EINVAL; gotBytes = -1; break; } } /* while toRead > 0 */ if (gotBytes == 0) { dataPtr->eofPending = 0; } ReleaseData(dataPtr); return gotBytes; } /* *---------------------------------------------------------------------- * * TransformOutputProc -- * * Called by the generic IO system to convert data waiting to be written. * * Side effects: * As defined by the transformation. * * Result: * A transformed buffer. * *---------------------------------------------------------------------- */ static int TransformOutputProc( ClientData instanceData, const char *buf, int toWrite, int *errorCodePtr) { TransformChannelData *dataPtr = instanceData; /* * Should assert(dataPtr->mode & TCL_WRITABLE); */ if (toWrite == 0) { /* * Catch a no-op. */ return 0; } PreserveData(dataPtr); if (ExecuteCallback(dataPtr, NULL, A_WRITE, UCHARP(buf), toWrite, TRANSMIT_DOWN, P_NO_PRESERVE) != TCL_OK) { *errorCodePtr = EINVAL; toWrite = -1; } ReleaseData(dataPtr); return toWrite; } /* *---------------------------------------------------------------------- * * TransformSeekProc -- * * This procedure is called by the generic IO level to move the access * point in a channel. * * Side effects: * Moves the location at which the channel will be accessed in future * operations. Flushes all transformation buffers, then forwards it to * the underlying channel. * * Result: * -1 if failed, the new position if successful. An output argument * contains the POSIX error code if an error occurred, or zero. * *---------------------------------------------------------------------- */ static int TransformSeekProc( ClientData instanceData, /* The channel to manipulate. */ long offset, /* Size of movement. */ int mode, /* How to move. */ int *errorCodePtr) /* Location of error flag. */ { TransformChannelData *dataPtr = instanceData; Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self); const Tcl_ChannelType *parentType = Tcl_GetChannelType(parent); Tcl_DriverSeekProc *parentSeekProc = Tcl_ChannelSeekProc(parentType); if ((offset == 0) && (mode == SEEK_CUR)) { /* * This is no seek but a request to tell the caller the current * location. Simply pass the request down. */ return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset, mode, errorCodePtr); } /* * It is a real request to change the position. Flush all data waiting for * output and discard everything in the input buffers. Then pass the * request down, unchanged. */ PreserveData(dataPtr); if (dataPtr->mode & TCL_WRITABLE) { ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN, P_NO_PRESERVE); } if (dataPtr->mode & TCL_READABLE) { ExecuteCallback(dataPtr, NULL, A_CLEAR_READ, NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE); ResultClear(&dataPtr->result); dataPtr->readIsFlushed = 0; dataPtr->eofPending = 0; } ReleaseData(dataPtr); return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset, mode, errorCodePtr); } /* *---------------------------------------------------------------------- * * TransformWideSeekProc -- * * This procedure is called by the generic IO level to move the access * point in a channel, with a (potentially) 64-bit offset. * * Side effects: * Moves the location at which the channel will be accessed in future * operations. Flushes all transformation buffers, then forwards it to * the underlying channel. * * Result: * -1 if failed, the new position if successful. An output argument * contains the POSIX error code if an error occurred, or zero. * *---------------------------------------------------------------------- */ static Tcl_WideInt TransformWideSeekProc( ClientData instanceData, /* The channel to manipulate. */ Tcl_WideInt offset, /* Size of movement. */ int mode, /* How to move. */ int *errorCodePtr) /* Location of error flag. */ { TransformChannelData *dataPtr = instanceData; Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self); const Tcl_ChannelType *parentType = Tcl_GetChannelType(parent); Tcl_DriverSeekProc *parentSeekProc = Tcl_ChannelSeekProc(parentType); Tcl_DriverWideSeekProc *parentWideSeekProc = Tcl_ChannelWideSeekProc(parentType); ClientData parentData = Tcl_GetChannelInstanceData(parent); if ((offset == Tcl_LongAsWide(0)) && (mode == SEEK_CUR)) { /* * This is no seek but a request to tell the caller the current * location. Simply pass the request down. */ if (parentWideSeekProc != NULL) { return parentWideSeekProc(parentData, offset, mode, errorCodePtr); } return Tcl_LongAsWide(parentSeekProc(parentData, 0, mode, errorCodePtr)); } /* * It is a real request to change the position. Flush all data waiting for * output and discard everything in the input buffers. Then pass the * request down, unchanged. */ PreserveData(dataPtr); if (dataPtr->mode & TCL_WRITABLE) { ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN, P_NO_PRESERVE); } if (dataPtr->mode & TCL_READABLE) { ExecuteCallback(dataPtr, NULL, A_CLEAR_READ, NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE); ResultClear(&dataPtr->result); dataPtr->readIsFlushed = 0; dataPtr->eofPending = 0; } ReleaseData(dataPtr); /* * If we have a wide seek capability, we should stick with that. */ if (parentWideSeekProc != NULL) { return parentWideSeekProc(parentData, offset, mode, errorCodePtr); } /* * We're transferring to narrow seeks at this point; this is a bit complex * because we have to check whether the seek is possible first (i.e. * whether we are losing information in truncating the bits of the * offset). Luckily, there's a defined error for what happens when trying * to go out of the representable range. */ if (offsetTcl_LongAsWide(LONG_MAX)) { *errorCodePtr = EOVERFLOW; return Tcl_LongAsWide(-1); } return Tcl_LongAsWide(parentSeekProc(parentData, Tcl_WideAsLong(offset), mode, errorCodePtr)); } /* *---------------------------------------------------------------------- * * TransformSetOptionProc -- * * Called by generic layer to handle the reconfiguration of channel * specific options. As this channel type does not have such, it simply * passes all requests downstream. * * Side effects: * As defined by the channel downstream. * * Result: * A standard TCL error code. * *---------------------------------------------------------------------- */ static int TransformSetOptionProc( ClientData instanceData, Tcl_Interp *interp, const char *optionName, const char *value) { TransformChannelData *dataPtr = instanceData; Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self); Tcl_DriverSetOptionProc *setOptionProc; setOptionProc = Tcl_ChannelSetOptionProc(Tcl_GetChannelType(downChan)); if (setOptionProc == NULL) { return TCL_ERROR; } return setOptionProc(Tcl_GetChannelInstanceData(downChan), interp, optionName, value); } /* *---------------------------------------------------------------------- * * TransformGetOptionProc -- * * Called by generic layer to handle requests for the values of channel * specific options. As this channel type does not have such, it simply * passes all requests downstream. * * Side effects: * As defined by the channel downstream. * * Result: * A standard TCL error code. * *---------------------------------------------------------------------- */ static int TransformGetOptionProc( ClientData instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr) { TransformChannelData *dataPtr = instanceData; Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self); Tcl_DriverGetOptionProc *getOptionProc; getOptionProc = Tcl_ChannelGetOptionProc(Tcl_GetChannelType(downChan)); if (getOptionProc != NULL) { return getOptionProc(Tcl_GetChannelInstanceData(downChan), interp, optionName, dsPtr); } else if (optionName == NULL) { /* * Request is query for all options, this is ok. */ return TCL_OK; } /* * Request for a specific option has to fail, since we don't have any. */ return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TransformWatchProc -- * * Initialize the notifier to watch for events from this channel. * * Side effects: * Sets up the notifier so that a future event on the channel will be * seen by Tcl. * * Result: * None. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static void TransformWatchProc( ClientData instanceData, /* Channel to watch. */ int mask) /* Events of interest. */ { TransformChannelData *dataPtr = instanceData; Tcl_Channel downChan; /* * The caller expressed interest in events occuring for this channel. We * are forwarding the call to the underlying channel now. */ dataPtr->watchMask = mask; /* * No channel handlers any more. We will be notified automatically about * events on the channel below via a call to our 'TransformNotifyProc'. * But we have to pass the interest down now. We are allowed to add * additional 'interest' to the mask if we want to. But this * transformation has no such interest. It just passes the request down, * unchanged. */ if (dataPtr->self == NULL) { return; } downChan = Tcl_GetStackedChannel(dataPtr->self); Tcl_GetChannelType(downChan)->watchProc( Tcl_GetChannelInstanceData(downChan), mask); /* * Management of the internal timer. */ if ((dataPtr->timer != NULL) && (!(mask & TCL_READABLE) || ResultEmpty(&dataPtr->result))) { /* * A pending timer exists, but either is there no (more) interest in * the events it generates or nothing is available for reading, so * remove it. */ Tcl_DeleteTimerHandler(dataPtr->timer); dataPtr->timer = NULL; } if ((dataPtr->timer == NULL) && (mask & TCL_READABLE) && !ResultEmpty(&dataPtr->result)) { /* * There is no pending timer, but there is interest in readable events * and we actually have data waiting, so generate a timer to flush * that. */ dataPtr->timer = Tcl_CreateTimerHandler(FLUSH_DELAY, TransformChannelHandlerTimer, dataPtr); } } /* *---------------------------------------------------------------------- * * TransformGetFileHandleProc -- * * Called from Tcl_GetChannelHandle to retrieve OS specific file handle * from inside this channel. * * Side effects: * None. * * Result: * The appropriate Tcl_File or NULL if not present. * *---------------------------------------------------------------------- */ static int TransformGetFileHandleProc( ClientData instanceData, /* Channel to query. */ int direction, /* Direction of interest. */ ClientData *handlePtr) /* Place to store the handle into. */ { TransformChannelData *dataPtr = instanceData; /* * Return the handle belonging to parent channel. IOW, pass the request * down and the result up. */ return Tcl_GetChannelHandle(Tcl_GetStackedChannel(dataPtr->self), direction, handlePtr); } /* *---------------------------------------------------------------------- * * TransformNotifyProc -- * * Handler called by Tcl to inform us of activity on the underlying * channel. * * Side effects: * May process the incoming event by itself. * * Result: * None. * *---------------------------------------------------------------------- */ static int TransformNotifyProc( ClientData clientData, /* The state of the notified * transformation. */ int mask) /* The mask of occuring events. */ { TransformChannelData *dataPtr = clientData; /* * An event occured in the underlying channel. This transformation doesn't * process such events thus returns the incoming mask unchanged. */ if (dataPtr->timer != NULL) { /* * Delete an existing timer. It was not fired, yet we are here, so the * channel below generated such an event and we don't have to. The * renewal of the interest after the execution of channel handlers * will eventually cause us to recreate the timer (in * TransformWatchProc). */ Tcl_DeleteTimerHandler(dataPtr->timer); dataPtr->timer = NULL; } return mask; } /* *---------------------------------------------------------------------- * * TransformChannelHandlerTimer -- * * Called by the notifier (-> timer) to flush out information waiting in * the input buffer. * * Side effects: * As of 'Tcl_NotifyChannel'. * * Result: * None. * *---------------------------------------------------------------------- */ static void TransformChannelHandlerTimer( ClientData clientData) /* Transformation to query. */ { TransformChannelData *dataPtr = clientData; dataPtr->timer = NULL; if (!(dataPtr->watchMask&TCL_READABLE) || ResultEmpty(&dataPtr->result)) { /* * The timer fired, but either is there no (more) interest in the * events it generates or nothing is available for reading, so ignore * it and don't recreate it. */ return; } Tcl_NotifyChannel(dataPtr->self, TCL_READABLE); } /* *---------------------------------------------------------------------- * * ResultClear -- * * Deallocates any memory allocated by 'ResultAdd'. * * Side effects: * See above. * * Result: * None. * *---------------------------------------------------------------------- */ static inline void ResultClear( ResultBuffer *r) /* Reference to the buffer to clear out. */ { r->used = 0; if (r->allocated) { ckfree(r->buf); r->buf = NULL; r->allocated = 0; } } /* *---------------------------------------------------------------------- * * ResultInit -- * * Initializes the specified buffer structure. The structure will contain * valid information for an emtpy buffer. * * Side effects: * See above. * * Result: * None. * *---------------------------------------------------------------------- */ static inline void ResultInit( ResultBuffer *r) /* Reference to the structure to * initialize. */ { r->used = 0; r->allocated = 0; r->buf = NULL; } /* *---------------------------------------------------------------------- * * ResultEmpty -- * * Returns whether the number of bytes stored in the buffer is zero. * * Side effects: * None. * * Result: * A boolean. * *---------------------------------------------------------------------- */ static inline int ResultEmpty( ResultBuffer *r) /* The structure to query. */ { return r->used == 0; } /* *---------------------------------------------------------------------- * * ResultCopy -- * * Copies the requested number of bytes from the buffer into the * specified array and removes them from the buffer afterward. Copies * less if there is not enough data in the buffer. * * Side effects: * See above. * * Result: * The number of actually copied bytes, possibly less than 'toRead'. * *---------------------------------------------------------------------- */ static inline int ResultCopy( ResultBuffer *r, /* The buffer to read from. */ unsigned char *buf, /* The buffer to copy into. */ size_t toRead) /* Number of requested bytes. */ { if (r->used == 0) { /* * Nothing to copy in the case of an empty buffer. */ return 0; } else if (r->used == toRead) { /* * We have just enough. Copy everything to the caller. */ memcpy(buf, r->buf, toRead); r->used = 0; } else if (r->used > toRead) { /* * The internal buffer contains more than requested. Copy the * requested subset to the caller, and shift the remaining bytes down. */ memcpy(buf, r->buf, toRead); memmove(r->buf, r->buf + toRead, r->used - toRead); r->used -= toRead; } else { /* * There is not enough in the buffer to satisfy the caller, so take * everything. */ memcpy(buf, r->buf, r->used); toRead = r->used; r->used = 0; } return toRead; } /* *---------------------------------------------------------------------- * * ResultAdd -- * * Adds the bytes in the specified array to the buffer, by appending it. * * Side effects: * See above. * * Result: * None. * *---------------------------------------------------------------------- */ static inline void ResultAdd( ResultBuffer *r, /* The buffer to extend. */ unsigned char *buf, /* The buffer to read from. */ size_t toWrite) /* The number of bytes in 'buf'. */ { if (r->used + toWrite > r->allocated) { /* * Extension of the internal buffer is required. */ if (r->allocated == 0) { r->allocated = toWrite + INCREMENT; r->buf = ckalloc(r->allocated); } else { r->allocated += toWrite + INCREMENT; r->buf = ckrealloc(r->buf, r->allocated); } } /* * Now we may copy the data. */ memcpy(r->buf + r->used, buf, toWrite); r->used += toWrite; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/regguts.h0000644000175000017500000003576712663660065015056 0ustar sergeisergei/* * Internal interface definitions, etc., for the reg package * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Environmental customization. It should not (I hope) be necessary to alter * the file you are now reading -- regcustom.h should handle it all, given * care here and elsewhere. */ #include "regcustom.h" /* * Things that regcustom.h might override. */ /* assertions */ #ifndef assert #ifndef REG_DEBUG #ifndef NDEBUG #define NDEBUG /* no assertions */ #endif #endif /* !REG_DEBUG */ #include #endif /* voids */ #ifndef VOID #define VOID void /* for function return values */ #endif #ifndef DISCARD #define DISCARD void /* for throwing values away */ #endif #ifndef PVOID #define PVOID void * /* generic pointer */ #endif #ifndef VS #define VS(x) ((void*)(x)) /* cast something to generic ptr */ #endif #ifndef NOPARMS #define NOPARMS void /* for empty parm lists */ #endif /* function-pointer declarator */ #ifndef FUNCPTR #if __STDC__ >= 1 #define FUNCPTR(name, args) (*name)args #else #define FUNCPTR(name, args) (*name)() #endif #endif /* memory allocation */ #ifndef MALLOC #define MALLOC(n) malloc(n) #endif #ifndef REALLOC #define REALLOC(p, n) realloc(VS(p), n) #endif #ifndef FREE #define FREE(p) free(VS(p)) #endif /* want size of a char in bits, and max value in bounded quantifiers */ #ifndef _POSIX2_RE_DUP_MAX #define _POSIX2_RE_DUP_MAX 255 /* normally from */ #endif /* * misc */ #define NOTREACHED 0 #define xxx 1 #define DUPMAX _POSIX2_RE_DUP_MAX #define DUPINF (DUPMAX+1) #define REMAGIC 0xfed7 /* magic number for main struct */ /* * debugging facilities */ #ifdef REG_DEBUG /* FDEBUG does finite-state tracing */ #define FDEBUG(arglist) { if (v->eflags®_FTRACE) printf arglist; } /* MDEBUG does higher-level tracing */ #define MDEBUG(arglist) { if (v->eflags®_MTRACE) printf arglist; } #else #define FDEBUG(arglist) {} #define MDEBUG(arglist) {} #endif /* * bitmap manipulation */ #define UBITS (CHAR_BIT * sizeof(unsigned)) #define BSET(uv, sn) ((uv)[(sn)/UBITS] |= (unsigned)1 << ((sn)%UBITS)) #define ISBSET(uv, sn) ((uv)[(sn)/UBITS] & ((unsigned)1 << ((sn)%UBITS))) /* * We dissect a chr into byts for colormap table indexing. Here we define a * byt, which will be the same as a byte on most machines... The exact size of * a byt is not critical, but about 8 bits is good, and extraction of 8-bit * chunks is sometimes especially fast. */ #ifndef BYTBITS #define BYTBITS 8 /* bits in a byt */ #endif #define BYTTAB (1<flags&FREECOL) union tree *block; /* block of solid color, if any */ }; /* * The color map itself * * Much of the data in the colormap struct is only used at compile time. * However, the bulk of the space usage is in the "tree" structure, so it's * not clear that there's much point in converting the rest to a more compact * form when compilation is finished. */ struct colormap { int magic; #define CMMAGIC 0x876 struct vars *v; /* for compile error reporting */ size_t ncds; /* number of colordescs */ size_t max; /* highest in use */ color free; /* beginning of free chain (if non-0) */ struct colordesc *cd; #define CDEND(cm) (&(cm)->cd[(cm)->max + 1]) #define NINLINECDS ((size_t)10) struct colordesc cdspace[NINLINECDS]; union tree tree[NBYTS]; /* tree top, plus fill blocks */ }; /* optimization magic to do fast chr->color mapping */ #define B0(c) ((c) & BYTMASK) #define B1(c) (((c)>>BYTBITS) & BYTMASK) #define B2(c) (((c)>>(2*BYTBITS)) & BYTMASK) #define B3(c) (((c)>>(3*BYTBITS)) & BYTMASK) #if NBYTS == 1 #define GETCOLOR(cm, c) ((cm)->tree->tcolor[B0(c)]) #endif /* beware, for NBYTS>1, GETCOLOR() is unsafe -- 2nd arg used repeatedly */ #if NBYTS == 2 #define GETCOLOR(cm, c) ((cm)->tree->tptr[B1(c)]->tcolor[B0(c)]) #endif #if NBYTS == 4 #define GETCOLOR(cm, c) ((cm)->tree->tptr[B3(c)]->tptr[B2(c)]->tptr[B1(c)]->tcolor[B0(c)]) #endif /* * Interface definitions for locale-interface functions in locale.c. */ /* Representation of a set of characters. */ struct cvec { int nchrs; /* number of chrs */ int chrspace; /* number of chrs possible */ chr *chrs; /* pointer to vector of chrs */ int nranges; /* number of ranges (chr pairs) */ int rangespace; /* number of chrs possible */ chr *ranges; /* pointer to vector of chr pairs */ }; /* * definitions for non-deterministic finite autmaton (NFA) internal * representation * * Having a "from" pointer within each arc may seem redundant, but it saves a * lot of hassle. */ struct state; struct arc { int type; /* 0 if free, else an NFA arc type code */ color co; struct state *from; /* where it's from (and contained within) */ struct state *to; /* where it's to */ struct arc *outchain; /* link in *from's outs chain or free chain */ struct arc *outchainRev; /* back-link in *from's outs chain */ #define freechain outchain /* we do not maintain "freechainRev" */ struct arc *inchain; /* *to's ins chain */ struct arc *inchainRev; /* back-link in *to's ins chain */ struct arc *colorchain; /* color's arc chain */ struct arc *colorchainRev; /* back-link in color's arc chain */ }; struct arcbatch { /* for bulk allocation of arcs */ struct arcbatch *next; #define ABSIZE 10 struct arc a[ABSIZE]; }; struct state { int no; #define FREESTATE (-1) char flag; /* marks special states */ int nins; /* number of inarcs */ struct arc *ins; /* chain of inarcs */ int nouts; /* number of outarcs */ struct arc *outs; /* chain of outarcs */ struct arc *free; /* chain of free arcs */ struct state *tmp; /* temporary for traversal algorithms */ struct state *next; /* chain for traversing all */ struct state *prev; /* back chain */ struct arcbatch oas; /* first arcbatch, avoid malloc in easy case */ int noas; /* number of arcs used in first arcbatch */ }; struct nfa { struct state *pre; /* pre-initial state */ struct state *init; /* initial state */ struct state *final; /* final state */ struct state *post; /* post-final state */ int nstates; /* for numbering states */ struct state *states; /* state-chain header */ struct state *slast; /* tail of the chain */ struct state *free; /* free list */ struct colormap *cm; /* the color map */ color bos[2]; /* colors, if any, assigned to BOS and BOL */ color eos[2]; /* colors, if any, assigned to EOS and EOL */ struct vars *v; /* simplifies compile error reporting */ struct nfa *parent; /* parent NFA, if any */ }; /* * definitions for compacted NFA * * The main space savings in a compacted NFA is from making the arcs as small * as possible. We store only the transition color and next-state number for * each arc. The list of out arcs for each state is an array beginning at * cnfa.states[statenumber], and terminated by a dummy carc struct with * co == COLORLESS. * * The non-dummy carc structs are of two types: plain arcs and LACON arcs. * Plain arcs just store the transition color number as "co". LACON arcs * store the lookahead constraint number plus cnfa.ncolors as "co". LACON * arcs can be distinguished from plain by testing for co >= cnfa.ncolors. */ struct carc { color co; /* COLORLESS is list terminator */ int to; /* next-state number */ }; struct cnfa { int nstates; /* number of states */ int ncolors; /* number of colors */ int flags; #define HASLACONS 01 /* uses lookahead constraints */ int pre; /* setup state number */ int post; /* teardown state number */ color bos[2]; /* colors, if any, assigned to BOS and BOL */ color eos[2]; /* colors, if any, assigned to EOS and EOL */ char *stflags; /* vector of per-state flags bytes */ #define CNFA_NOPROGRESS 01 /* flag bit for a no-progress state */ struct carc **states; /* vector of pointers to outarc lists */ /* states[n] are pointers into a single malloc'd array of arcs */ struct carc *arcs; /* the area for the lists */ }; #define ZAPCNFA(cnfa) ((cnfa).nstates = 0) #define NULLCNFA(cnfa) ((cnfa).nstates == 0) /* * This symbol limits the transient heap space used by the regex compiler, * and thereby also the maximum complexity of NFAs that we'll deal with. * Currently we only count NFA states and arcs against this; the other * transient data is generally not large enough to notice compared to those. * Note that we do not charge anything for the final output data structures * (the compacted NFA and the colormap). */ #ifndef REG_MAX_COMPILE_SPACE #define REG_MAX_COMPILE_SPACE \ (100000 * sizeof(struct state) + 100000 * sizeof(struct arcbatch)) #endif /* * subexpression tree * * "op" is one of: * '=' plain regex without interesting substructure (implemented as DFA) * 'b' back-reference (has no substructure either) * '(' capture node: captures the match of its single child * '.' concatenation: matches a match for left, then a match for right * '|' alternation: matches a match for left or a match for right * '*' iteration: matches some number of matches of its single child * * Note: the right child of an alternation must be another alternation or * NULL; hence, an N-way branch requires N alternation nodes, not N-1 as you * might expect. This could stand to be changed. Actually I'd rather see * a single alternation node with N children, but that will take revising * the representation of struct subre. * * Note: when a backref is directly quantified, we stick the min/max counts * into the backref rather than plastering an iteration node on top. This is * for efficiency: there is no need to search for possible division points. */ struct subre { char op; /* see type codes above */ char flags; #define LONGER 01 /* prefers longer match */ #define SHORTER 02 /* prefers shorter match */ #define MIXED 04 /* mixed preference below */ #define CAP 010 /* capturing parens below */ #define BACKR 020 /* back reference below */ #define INUSE 0100 /* in use in final tree */ #define NOPROP 03 /* bits which may not propagate up */ #define LMIX(f) ((f)<<2) /* LONGER -> MIXED */ #define SMIX(f) ((f)<<1) /* SHORTER -> MIXED */ #define UP(f) (((f)&~NOPROP) | (LMIX(f) & SMIX(f) & MIXED)) #define MESSY(f) ((f)&(MIXED|CAP|BACKR)) #define PREF(f) ((f)&NOPROP) #define PREF2(f1, f2) ((PREF(f1) != 0) ? PREF(f1) : PREF(f2)) #define COMBINE(f1, f2) (UP((f1)|(f2)) | PREF2(f1, f2)) short id; /* ID of subre (1..ntree-1) */ int subno; /* subexpression number (for 'b' and '(') */ short min; /* min repetitions for iteration or backref */ short max; /* max repetitions for iteration or backref */ struct subre *left; /* left child, if any (also freelist chain) */ struct subre *right; /* right child, if any */ struct state *begin; /* outarcs from here... */ struct state *end; /* ...ending in inarcs here */ struct cnfa cnfa; /* compacted NFA, if any */ struct subre *chain; /* for bookkeeping and error cleanup */ }; /* * table of function pointers for generic manipulation functions. A regex_t's * re_fns points to one of these. */ struct fns { void FUNCPTR(free, (regex_t *)); }; /* * the insides of a regex_t, hidden behind a void * */ struct guts { int magic; #define GUTSMAGIC 0xfed9 int cflags; /* copy of compile flags */ long info; /* copy of re_info */ size_t nsub; /* copy of re_nsub */ struct subre *tree; struct cnfa search; /* for fast preliminary search */ int ntree; /* number of subre's, plus one */ struct colormap cmap; int FUNCPTR(compare, (const chr *, const chr *, size_t)); struct subre *lacons; /* lookahead-constraint vector */ int nlacons; /* size of lacons */ }; /* * Magic for allocating a variable workspace. This default version is * stack-hungry. */ #ifndef AllocVars #define AllocVars(vPtr) \ struct vars var; \ register struct vars *vPtr = &var #endif #ifndef FreeVars #define FreeVars(vPtr) ((void) 0) #endif /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclIOSock.c0000644000175000017500000001662112663660065015207 0ustar sergeisergei/* * tclIOSock.c -- * * Common routines used by all socket based channel types. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #if defined(_WIN32) && defined(UNICODE) /* On Windows, we need to do proper Unicode->UTF-8 conversion. */ typedef struct ThreadSpecificData { int initialized; Tcl_DString errorMsg; /* UTF-8 encoded error-message */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; #undef gai_strerror static const char *gai_strerror(int code) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->initialized) { Tcl_DStringFree(&tsdPtr->errorMsg); } else { tsdPtr->initialized = 1; } Tcl_WinTCharToUtf(gai_strerrorW(code), -1, &tsdPtr->errorMsg); return Tcl_DStringValue(&tsdPtr->errorMsg); } #endif /* *--------------------------------------------------------------------------- * * TclSockGetPort -- * * Maps from a string, which could be a service name, to a port. Used by * socket creation code to get port numbers and resolve registered * service names to port numbers. * * Results: * A standard Tcl result. On success, the port number is returned in * portPtr. On failure, an error message is left in the interp's result. * * Side effects: * None. * *--------------------------------------------------------------------------- */ int TclSockGetPort( Tcl_Interp *interp, const char *string, /* Integer or service name */ const char *proto, /* "tcp" or "udp", typically */ int *portPtr) /* Return port number */ { struct servent *sp; /* Protocol info for named services */ Tcl_DString ds; const char *native; if (Tcl_GetInt(NULL, string, portPtr) != TCL_OK) { /* * Don't bother translating 'proto' to native. */ native = Tcl_UtfToExternalDString(NULL, string, -1, &ds); sp = getservbyname(native, proto); /* INTL: Native. */ Tcl_DStringFree(&ds); if (sp != NULL) { *portPtr = ntohs((unsigned short) sp->s_port); return TCL_OK; } } if (Tcl_GetInt(interp, string, portPtr) != TCL_OK) { return TCL_ERROR; } if (*portPtr > 0xFFFF) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "couldn't open socket: port number too high", -1)); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclSockMinimumBuffers -- * * Ensure minimum buffer sizes (non zero). * * Results: * A standard Tcl result. * * Side effects: * Sets SO_SNDBUF and SO_RCVBUF sizes. * *---------------------------------------------------------------------- */ #if !defined(_WIN32) && !defined(__CYGWIN__) # define SOCKET int #endif int TclSockMinimumBuffers( void *sock, /* Socket file descriptor */ int size) /* Minimum buffer size */ { int current; socklen_t len; len = sizeof(int); getsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_SNDBUF, (char *) ¤t, &len); if (current < size) { len = sizeof(int); setsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_SNDBUF, (char *) &size, len); } len = sizeof(int); getsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_RCVBUF, (char *) ¤t, &len); if (current < size) { len = sizeof(int); setsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_RCVBUF, (char *) &size, len); } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCreateSocketAddress -- * * This function initializes a sockaddr structure for a host and port. * * Results: * 1 if the host was valid, 0 if the host could not be converted to an IP * address. * * Side effects: * Fills in the *sockaddrPtr structure. * *---------------------------------------------------------------------- */ int TclCreateSocketAddress( Tcl_Interp *interp, /* Interpreter for querying * the desired socket family */ struct addrinfo **addrlist, /* Socket address list */ const char *host, /* Host. NULL implies INADDR_ANY */ int port, /* Port number */ int willBind, /* Is this an address to bind() to or * to connect() to? */ const char **errorMsgPtr) /* Place to store the error message * detail, if available. */ { struct addrinfo hints; struct addrinfo *p; struct addrinfo *v4head = NULL, *v4ptr = NULL; struct addrinfo *v6head = NULL, *v6ptr = NULL; char *native = NULL, portbuf[TCL_INTEGER_SPACE], *portstring; const char *family = NULL; Tcl_DString ds; int result; if (host != NULL) { native = Tcl_UtfToExternalDString(NULL, host, -1, &ds); } /* * Workaround for OSX's apparent inability to resolve "localhost", "0" * when the loopback device is the only available network interface. */ if (host != NULL && port == 0) { portstring = NULL; } else { TclFormatInt(portbuf, port); portstring = portbuf; } (void) memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* * Magic variable to enforce a certain address family - to be superseded * by a TIP that adds explicit switches to [socket] */ if (interp != NULL) { family = Tcl_GetVar(interp, "::tcl::unsupported::socketAF", 0); if (family != NULL) { if (strcmp(family, "inet") == 0) { hints.ai_family = AF_INET; } else if (strcmp(family, "inet6") == 0) { hints.ai_family = AF_INET6; } } } hints.ai_socktype = SOCK_STREAM; #if 0 /* * We found some problems when using AI_ADDRCONFIG, e.g. on systems that * have no networking besides the loopback interface and want to resolve * localhost. See [Bugs 3385024, 3382419, 3382431]. As the advantage of * using AI_ADDRCONFIG in situations where it works, is probably low, * we'll leave it out for now. After all, it is just an optimisation. * * Missing on: OpenBSD, NetBSD. * Causes failure when used on AIX 5.1 and HP-UX */ #if defined(AI_ADDRCONFIG) && !defined(_AIX) && !defined(__hpux) hints.ai_flags |= AI_ADDRCONFIG; #endif /* AI_ADDRCONFIG && !_AIX && !__hpux */ #endif /* 0 */ if (willBind) { hints.ai_flags |= AI_PASSIVE; } result = getaddrinfo(native, portstring, &hints, addrlist); if (host != NULL) { Tcl_DStringFree(&ds); } if (result != 0) { *errorMsgPtr = #ifdef EAI_SYSTEM /* Doesn't exist on Windows */ (result == EAI_SYSTEM) ? Tcl_PosixError(interp) : #endif /* EAI_SYSTEM */ gai_strerror(result); return 0; } /* * Put IPv4 addresses before IPv6 addresses to maximize backwards * compatibility of [fconfigure -sockname] output. * * There might be more elegant/efficient ways to do this. */ if (willBind) { for (p = *addrlist; p != NULL; p = p->ai_next) { if (p->ai_family == AF_INET) { if (v4head == NULL) { v4head = p; } else { v4ptr->ai_next = p; } v4ptr = p; } else { if (v6head == NULL) { v6head = p; } else { v6ptr->ai_next = p; } v6ptr = p; } } *addrlist = NULL; if (v6head != NULL) { *addrlist = v6head; v6ptr->ai_next = NULL; } if (v4head != NULL) { v4ptr->ai_next = *addrlist; *addrlist = v4head; } } return 1; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclIORTrans.c0000644000175000017500000026115512663660065015525 0ustar sergeisergei/* * tclIORTrans.c -- * * This file contains the implementation of Tcl's generic transformation * reflection code, which allows the implementation of Tcl channel * transformations in Tcl code. * * Parts of this file are based on code contributed by Jean-Claude * Wippler. * * See TIP #230 for the specification of this functionality. * * Copyright (c) 2007-2008 ActiveState. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclIO.h" #include #ifndef EINVAL #define EINVAL 9 #endif #ifndef EOK #define EOK 0 #endif /* DUPLICATE of HaveVersion() in tclIO.c // TODO - MODULE_SCOPE */ static int HaveVersion(const Tcl_ChannelType *typePtr, Tcl_ChannelTypeVersion minimumVersion); /* * Signatures of all functions used in the C layer of the reflection. */ static int ReflectClose(ClientData clientData, Tcl_Interp *interp); static int ReflectInput(ClientData clientData, char *buf, int toRead, int *errorCodePtr); static int ReflectOutput(ClientData clientData, const char *buf, int toWrite, int *errorCodePtr); static void ReflectWatch(ClientData clientData, int mask); static int ReflectBlock(ClientData clientData, int mode); static Tcl_WideInt ReflectSeekWide(ClientData clientData, Tcl_WideInt offset, int mode, int *errorCodePtr); static int ReflectSeek(ClientData clientData, long offset, int mode, int *errorCodePtr); static int ReflectGetOption(ClientData clientData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); static int ReflectSetOption(ClientData clientData, Tcl_Interp *interp, const char *optionName, const char *newValue); static int ReflectHandle(ClientData clientData, int direction, ClientData *handle); static int ReflectNotify(ClientData clientData, int mask); /* * The C layer channel type/driver definition used by the reflection. */ static const Tcl_ChannelType tclRTransformType = { "tclrtransform", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel. */ ReflectClose, /* Close channel, clean instance data. */ ReflectInput, /* Handle read request. */ ReflectOutput, /* Handle write request. */ ReflectSeek, /* Move location of access point. */ ReflectSetOption, /* Set options. */ ReflectGetOption, /* Get options. */ ReflectWatch, /* Initialize notifier. */ ReflectHandle, /* Get OS handle from the channel. */ NULL, /* No close2 support. NULL'able. */ ReflectBlock, /* Set blocking/nonblocking. */ NULL, /* Flush channel. Not used by core. * NULL'able. */ ReflectNotify, /* Handle events. */ ReflectSeekWide, /* Move access point (64 bit). */ NULL, /* thread action */ NULL /* truncate */ }; /* * Structure of the buffer to hold transform results to be consumed by higher * layers upon reading from the channel, plus the functions to manage such. */ typedef struct _ResultBuffer_ { unsigned char *buf; /* Reference to the buffer area. */ int allocated; /* Allocated size of the buffer area. */ int used; /* Number of bytes in the buffer, * <= allocated. */ } ResultBuffer; #define ResultLength(r) ((r)->used) /* static int ResultLength(ResultBuffer *r); */ static void ResultClear(ResultBuffer *r); static void ResultInit(ResultBuffer *r); static void ResultAdd(ResultBuffer *r, unsigned char *buf, int toWrite); static int ResultCopy(ResultBuffer *r, unsigned char *buf, int toRead); #define RB_INCREMENT (512) /* * Convenience macro to make some casts easier to use. */ #define UCHARP(x) ((unsigned char *) (x)) /* * Instance data for a reflected transformation. =========================== */ typedef struct { Tcl_Channel chan; /* Back reference to the channel of the * transformation itself. */ Tcl_Channel parent; /* Reference to the channel the transformation * was pushed on. */ Tcl_Interp *interp; /* Reference to the interpreter containing the * Tcl level part of the channel. */ Tcl_Obj *handle; /* Reference to transform handle. Also stored * in the argv, see below. The separate field * gives us direct access, needed when working * with the reflection maps. */ #ifdef TCL_THREADS Tcl_ThreadId thread; /* Thread the 'interp' belongs to. */ #endif Tcl_TimerToken timer; /* See [==] as well. * Storage for the command prefix and the additional words required for * the invocation of methods in the command handler. * * argv [0] ... [.] | [argc-2] [argc-1] | [argc] [argc+2] * cmd ... pfx | method chan | detail1 detail2 * ~~~~ CT ~~~ ~~ CT ~~ * * CT = Belongs to the 'Command handler Thread'. */ int argc; /* Number of preallocated words - 2. */ Tcl_Obj **argv; /* Preallocated array for calling the handler. * args[0] is placeholder for cmd word. * Followed by the arguments in the prefix, * plus 4 placeholders for method, channel, * and at most two varying (method specific) * words. */ int methods; /* Bitmask of supported methods. */ /* * NOTE (9): Should we have predefined shared literals for the method * names? */ int mode; /* Mask of R/W mode */ int nonblocking; /* Flag: Channel is blocking or not. */ int readIsDrained; /* Flag: Read buffers are flushed. */ int eofPending; /* Flag: EOF seen down, but not raised up */ int dead; /* Boolean signal that some operations * should no longer be attempted. */ ResultBuffer result; } ReflectedTransform; /* * Structure of the table mapping from transform handles to reflected * transform (channels). Each interpreter which has the handler command for * one or more reflected transforms records them in such a table, so that we * are able to find them during interpreter/thread cleanup even if the actual * channel they belong to was moved to a different interpreter and/or thread. * * The table is reachable via the standard interpreter AssocData, the key is * defined below. */ typedef struct { Tcl_HashTable map; } ReflectedTransformMap; #define RTMKEY "ReflectedTransformMap" /* * Method literals. ================================================== */ static const char *const methodNames[] = { "clear", /* OPT */ "drain", /* OPT, drain => read */ "finalize", /* */ "flush", /* OPT, flush => write */ "initialize", /* */ "limit?", /* OPT */ "read", /* OPT */ "write", /* OPT */ NULL }; typedef enum { METH_CLEAR, METH_DRAIN, METH_FINAL, METH_FLUSH, METH_INIT, METH_LIMIT, METH_READ, METH_WRITE } MethodName; #define FLAG(m) (1 << (m)) #define REQUIRED_METHODS \ (FLAG(METH_INIT) | FLAG(METH_FINAL)) #define RANDW \ (TCL_READABLE | TCL_WRITABLE) #define IMPLIES(a,b) ((!(a)) || (b)) #define NEGIMPL(a,b) #define HAS(x,f) (x & FLAG(f)) #ifdef TCL_THREADS /* * Thread specific types and structures. * * We are here essentially creating a very specific implementation of 'thread * send'. */ /* * Enumeration of all operations which can be forwarded. */ typedef enum { ForwardedClear, ForwardedClose, ForwardedDrain, ForwardedFlush, ForwardedInput, ForwardedLimit, ForwardedOutput } ForwardedOperation; /* * Event used to forward driver invocations to the thread actually managing * the channel. We cannot construct the command to execute and forward that. * Because then it will contain a mixture of Tcl_Obj's belonging to both the * command handler thread (CT), and the thread managing the channel (MT), * executed in CT. Tcl_Obj's are not allowed to cross thread boundaries. So we * forward an operation code, the argument details, and reference to results. * The command is assembled in the CT and belongs fully to that thread. No * sharing problems. */ typedef struct ForwardParamBase { int code; /* O: Ok/Fail of the cmd handler */ char *msgStr; /* O: Error message for handler failure */ int mustFree; /* O: True if msgStr is allocated, false if * otherwise (static). */ } ForwardParamBase; /* * Operation specific parameter/result structures. (These are "subtypes" of * ForwardParamBase. Where an operation does not need any special types, it * has no "subtype" and just uses ForwardParamBase, as listed above.) */ struct ForwardParamTransform { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ char *buf; /* I: Bytes to transform, * O: Bytes in transform result */ int size; /* I: #bytes to transform, * O: #bytes in the transform result */ }; struct ForwardParamLimit { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ int max; /* O: Character read limit */ }; /* * Now join all these together in a single union for convenience. */ typedef union ForwardParam { ForwardParamBase base; struct ForwardParamTransform transform; struct ForwardParamLimit limit; } ForwardParam; /* * Forward declaration. */ typedef struct ForwardingResult ForwardingResult; /* * General event structure, with reference to operation specific data. */ typedef struct ForwardingEvent { Tcl_Event event; /* Basic event data, has to be first item */ ForwardingResult *resultPtr; ForwardedOperation op; /* Forwarded driver operation */ ReflectedTransform *rtPtr; /* Channel instance */ ForwardParam *param; /* Packaged arguments and return values, a * ForwardParam pointer. */ } ForwardingEvent; /* * Structure to manage the result of the forwarding. This is not the result of * the operation itself, but about the success of the forward event itself. * The event can be successful, even if the operation which was forwarded * failed. It is also there to manage the synchronization between the involved * threads. */ struct ForwardingResult { Tcl_ThreadId src; /* Originating thread. */ Tcl_ThreadId dst; /* Thread the op was forwarded to. */ Tcl_Interp *dsti; /* Interpreter in the thread the op was * forwarded to. */ Tcl_Condition done; /* Condition variable the forwarder blocks * on. */ int result; /* TCL_OK or TCL_ERROR */ ForwardingEvent *evPtr; /* Event the result belongs to. */ ForwardingResult *prevPtr, *nextPtr; /* Links into the list of pending forwarded * results. */ }; typedef struct ThreadSpecificData { /* * Table of all reflected transformations owned by this thread. */ ReflectedTransformMap *rtmPtr; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * List of forwarded operations which have not completed yet, plus the mutex * to protect the access to this process global list. */ static ForwardingResult *forwardList = NULL; TCL_DECLARE_MUTEX(rtForwardMutex) /* * Function containing the generic code executing a forward, and wrapper * macros for the actual operations we wish to forward. Uses ForwardProc as * the event function executed by the thread receiving a forwarding event * (which executes the appropriate function and collects the result, if any). * * The two ExitProcs are handlers so that things do not deadlock when either * thread involved in the forwarding exits. They also clean things up so that * we don't leak resources when threads go away. */ static void ForwardOpToOwnerThread(ReflectedTransform *rtPtr, ForwardedOperation op, const void *param); static int ForwardProc(Tcl_Event *evPtr, int mask); static void SrcExitProc(ClientData clientData); #define FreeReceivedError(p) \ do { \ if ((p)->base.mustFree) { \ ckfree((p)->base.msgStr); \ } \ } while (0) #define PassReceivedErrorInterp(i,p) \ do { \ if ((i) != NULL) { \ Tcl_SetChannelErrorInterp((i), \ Tcl_NewStringObj((p)->base.msgStr, -1)); \ } \ FreeReceivedError(p); \ } while (0) #define PassReceivedError(c,p) \ do { \ Tcl_SetChannelError((c), \ Tcl_NewStringObj((p)->base.msgStr, -1)); \ FreeReceivedError(p); \ } while (0) #define ForwardSetStaticError(p,emsg) \ do { \ (p)->base.code = TCL_ERROR; \ (p)->base.mustFree = 0; \ (p)->base.msgStr = (char *) (emsg); \ } while (0) #define ForwardSetDynamicError(p,emsg) \ do { \ (p)->base.code = TCL_ERROR; \ (p)->base.mustFree = 1; \ (p)->base.msgStr = (char *) (emsg); \ } while (0) static void ForwardSetObjError(ForwardParam *p, Tcl_Obj *objPtr); static ReflectedTransformMap * GetThreadReflectedTransformMap(void); static void DeleteThreadReflectedTransformMap( ClientData clientData); #endif /* TCL_THREADS */ #define SetChannelErrorStr(c,msgStr) \ Tcl_SetChannelError((c), Tcl_NewStringObj((msgStr), -1)) static Tcl_Obj * MarshallError(Tcl_Interp *interp); static void UnmarshallErrorResult(Tcl_Interp *interp, Tcl_Obj *msgObj); /* * Static functions for this file: */ static Tcl_Obj * DecodeEventMask(int mask); static ReflectedTransform * NewReflectedTransform(Tcl_Interp *interp, Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj, Tcl_Channel parentChan); static Tcl_Obj * NextHandle(void); static void FreeReflectedTransform(ReflectedTransform *rtPtr); static void FreeReflectedTransformArgs(ReflectedTransform *rtPtr); static int InvokeTclMethod(ReflectedTransform *rtPtr, const char *method, Tcl_Obj *argOneObj, Tcl_Obj *argTwoObj, Tcl_Obj **resultObjPtr); static ReflectedTransformMap * GetReflectedTransformMap(Tcl_Interp *interp); static void DeleteReflectedTransformMap(ClientData clientData, Tcl_Interp *interp); /* * Global constant strings (messages). ================== * These string are used directly as bypass errors, thus they have to be valid * Tcl lists where the last element is the message itself. Hence the * list-quoting to keep the words of the message together. See also [x]. */ static const char *msg_read_unsup = "{read not supported by Tcl driver}"; static const char *msg_write_unsup = "{write not supported by Tcl driver}"; #ifdef TCL_THREADS static const char *msg_send_originlost = "{Channel thread lost}"; static const char *msg_send_dstlost = "{Owner lost}"; #endif /* TCL_THREADS */ static const char *msg_dstlost = "-code 1 -level 0 -errorcode NONE -errorinfo {} -errorline 1 {Owner lost}"; /* * Timer management (flushing out buffered data via artificial events). */ /* * Helper functions encapsulating some of the thread forwarding to make the * control flow in callers easier. */ static void TimerKill(ReflectedTransform *rtPtr); static void TimerSetup(ReflectedTransform *rtPtr); static void TimerRun(ClientData clientData); static int TransformRead(ReflectedTransform *rtPtr, int *errorCodePtr, Tcl_Obj *bufObj); static int TransformWrite(ReflectedTransform *rtPtr, int *errorCodePtr, unsigned char *buf, int toWrite); static int TransformDrain(ReflectedTransform *rtPtr, int *errorCodePtr); static int TransformFlush(ReflectedTransform *rtPtr, int *errorCodePtr, int op); static void TransformClear(ReflectedTransform *rtPtr); static int TransformLimit(ReflectedTransform *rtPtr, int *errorCodePtr, int *maxPtr); /* * Operation codes for TransformFlush(). */ #define FLUSH_WRITE 1 #define FLUSH_DISCARD 0 /* * Main methods to plug into the 'chan' ensemble'. ================== */ /* *---------------------------------------------------------------------- * * TclChanPushObjCmd -- * * This function is invoked to process the "chan push" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. The handle of the new channel is placed in the * interp result. * * Side effects: * Creates a new channel. * *---------------------------------------------------------------------- */ int TclChanPushObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { ReflectedTransform *rtPtr; /* Instance data of the new (transform) * channel. */ Tcl_Obj *chanObj; /* Handle of parent channel */ Tcl_Channel parentChan; /* Token of parent channel */ int mode; /* R/W mode of parent, later the new channel. * Has to match the abilities of the handler * commands */ Tcl_Obj *cmdObj; /* Command prefix, list of words */ Tcl_Obj *cmdNameObj; /* Command name */ Tcl_Obj *rtId; /* Handle of the new transform (channel) */ Tcl_Obj *modeObj; /* mode in obj form for method call */ int listc; /* Result of 'initialize', and of */ Tcl_Obj **listv; /* its sublist in the 2nd element */ int methIndex; /* Encoded method name */ int result; /* Result code for 'initialize' */ Tcl_Obj *resObj; /* Result data for 'initialize' */ int methods; /* Bitmask for supported methods. */ ReflectedTransformMap *rtmPtr; /* Map of reflected transforms with handlers * in this interp. */ Tcl_HashEntry *hPtr; /* Entry in the above map */ int isNew; /* Placeholder. */ /* * Syntax: chan push CHANNEL CMDPREFIX * [0] [1] [2] [3] * * Actually: rPush CHANNEL CMDPREFIX * [0] [1] [2] */ #define CHAN (1) #define CMD (2) /* * Number of arguments... */ if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "channel cmdprefix"); return TCL_ERROR; } /* * First argument is a channel handle. */ chanObj = objv[CHAN]; parentChan = Tcl_GetChannel(interp, Tcl_GetString(chanObj), &mode); if (parentChan == NULL) { return TCL_ERROR; } parentChan = Tcl_GetTopChannel(parentChan); /* * Second argument is command prefix, i.e. list of words, first word is * name of handler command, other words are fixed arguments. Run the * 'initialize' method to get the list of supported methods. Validate * this. */ cmdObj = objv[CMD]; /* * Basic check that the command prefix truly is a list. */ if (Tcl_ListObjIndex(interp, cmdObj, 0, &cmdNameObj) != TCL_OK) { return TCL_ERROR; } /* * Now create the transformation (channel). */ rtId = NextHandle(); rtPtr = NewReflectedTransform(interp, cmdObj, mode, rtId, parentChan); /* * Invoke 'initialize' and validate that the handler is present and ok. * Squash the transformation if not. */ modeObj = DecodeEventMask(mode); /* assert modeObj.refCount == 1 */ result = InvokeTclMethod(rtPtr, "initialize", modeObj, NULL, &resObj); Tcl_DecrRefCount(modeObj); if (result != TCL_OK) { UnmarshallErrorResult(interp, resObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ goto error; } /* * Verify the result. * - List, of method names. Convert to mask. Check for non-optionals * through the mask. Compare open mode against optional r/w. */ if (Tcl_ListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s initialize\" returned non-list: %s", Tcl_GetString(cmdObj), Tcl_GetString(resObj))); Tcl_DecrRefCount(resObj); goto error; } methods = 0; while (listc > 0) { if (Tcl_GetIndexFromObj(interp, listv[listc-1], methodNames, "method", TCL_EXACT, &methIndex) != TCL_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s initialize\" returned %s", Tcl_GetString(cmdObj), Tcl_GetString(Tcl_GetObjResult(interp)))); Tcl_DecrRefCount(resObj); goto error; } methods |= FLAG(methIndex); listc--; } Tcl_DecrRefCount(resObj); if ((REQUIRED_METHODS & methods) != REQUIRED_METHODS) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s\" does not support all required methods", Tcl_GetString(cmdObj))); goto error; } /* * Mode tell us what the parent channel supports. The methods tell us what * the handler supports. We remove the non-supported bits from the mode * and check that the channel is not completely inacessible. Afterward the * mode tells us which methods are still required, and these methods will * also be supported by the handler, by design of the check. */ if (!HAS(methods, METH_READ)) { mode &= ~TCL_READABLE; } if (!HAS(methods, METH_WRITE)) { mode &= ~TCL_WRITABLE; } if (!mode) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s\" makes the channel inaccessible", Tcl_GetString(cmdObj))); goto error; } /* * The mode and support for it is ok, now check the internal constraints. */ if (!IMPLIES(HAS(methods, METH_DRAIN), HAS(methods, METH_READ))) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s\" supports \"drain\" but not \"read\"", Tcl_GetString(cmdObj))); goto error; } if (!IMPLIES(HAS(methods, METH_FLUSH), HAS(methods, METH_WRITE))) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "chan handler \"%s\" supports \"flush\" but not \"write\"", Tcl_GetString(cmdObj))); goto error; } Tcl_ResetResult(interp); /* * Everything is fine now. */ rtPtr->methods = methods; rtPtr->mode = mode; rtPtr->chan = Tcl_StackChannel(interp, &tclRTransformType, rtPtr, mode, rtPtr->parent); /* * Register the transform in our our map for proper handling of deleted * interpreters and/or threads. */ rtmPtr = GetReflectedTransformMap(interp); hPtr = Tcl_CreateHashEntry(&rtmPtr->map, Tcl_GetString(rtId), &isNew); if (!isNew && rtPtr != Tcl_GetHashValue(hPtr)) { Tcl_Panic("TclChanPushObjCmd: duplicate transformation handle"); } Tcl_SetHashValue(hPtr, rtPtr); #ifdef TCL_THREADS rtmPtr = GetThreadReflectedTransformMap(); hPtr = Tcl_CreateHashEntry(&rtmPtr->map, Tcl_GetString(rtId), &isNew); Tcl_SetHashValue(hPtr, rtPtr); #endif /* TCL_THREADS */ /* * Return the channel as the result of the command. */ Tcl_SetObjResult(interp, Tcl_NewStringObj( Tcl_GetChannelName(rtPtr->chan), -1)); return TCL_OK; error: /* * We are not going through ReflectClose as we never had a channel * structure. */ Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); return TCL_ERROR; #undef CHAN #undef CMD } /* *---------------------------------------------------------------------- * * TclChanPopObjCmd -- * * This function is invoked to process the "chan pop" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Posts events to a reflected channel, invokes event handlers. The * latter implies that arbitrary side effects are possible. * *---------------------------------------------------------------------- */ int TclChanPopObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { /* * Syntax: chan pop CHANNEL * [0] [1] [2] * * Actually: rPop CHANNEL * [0] [1] */ #define CHAN (1) const char *chanId; /* Tcl level channel handle */ Tcl_Channel chan; /* Channel associated to the handle */ int mode; /* Channel r/w mode */ /* * Number of arguments... */ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channel"); return TCL_ERROR; } /* * First argument is a channel, which may have a (reflected) * transformation. */ chanId = TclGetString(objv[CHAN]); chan = Tcl_GetChannel(interp, chanId, &mode); if (chan == NULL) { return TCL_ERROR; } /* * Removing transformations is generic, and not restricted to reflected * transformations. */ Tcl_UnstackChannel(interp, chan); return TCL_OK; #undef CHAN } /* * Channel error message marshalling utilities. */ static Tcl_Obj * MarshallError( Tcl_Interp *interp) { /* * Capture the result status of the interpreter into a string. => List of * options and values, followed by the error message. The result has * refCount 0. */ Tcl_Obj *returnOpt = Tcl_GetReturnOptions(interp, TCL_ERROR); /* * => returnOpt.refCount == 0. We can append directly. */ Tcl_ListObjAppendElement(NULL, returnOpt, Tcl_GetObjResult(interp)); return returnOpt; } static void UnmarshallErrorResult( Tcl_Interp *interp, Tcl_Obj *msgObj) { int lc; Tcl_Obj **lv; int explicitResult; int numOptions; /* * Process the caught message. * * Syntax = (option value)... ?message? * * Bad syntax causes a panic. This is OK because the other side uses * Tcl_GetReturnOptions and list construction functions to marshall the * information; if we panic here, something has gone badly wrong already. */ if (Tcl_ListObjGetElements(interp, msgObj, &lc, &lv) != TCL_OK) { Tcl_Panic("TclChanCaughtErrorBypass: Bad syntax of caught result"); } if (interp == NULL) { return; } explicitResult = lc & 1; /* Odd number of values? */ numOptions = lc - explicitResult; if (explicitResult) { Tcl_SetObjResult(interp, lv[lc-1]); } Tcl_SetReturnOptions(interp, Tcl_NewListObj(numOptions, lv)); ((Interp *) interp)->flags &= ~ERR_ALREADY_LOGGED; } /* * Driver functions. ================================================ */ /* *---------------------------------------------------------------------- * * ReflectClose -- * * This function is invoked when the channel is closed, to delete the * driver specific instance data. * * Results: * A posix error. * * Side effects: * Releases memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectClose( ClientData clientData, Tcl_Interp *interp) { ReflectedTransform *rtPtr = clientData; int errorCode, errorCodeSet = 0; int result = TCL_OK; /* Result code for 'close' */ Tcl_Obj *resObj; /* Result data for 'close' */ ReflectedTransformMap *rtmPtr; /* Map of reflected transforms with handlers * in this interp. */ Tcl_HashEntry *hPtr; /* Entry in the above map */ if (TclInThreadExit()) { /* * This call comes from TclFinalizeIOSystem. There are no * interpreters, and therefore we cannot call upon the handler command * anymore. Threading is irrelevant as well. We simply clean up all * our C level data structures and leave the Tcl level to the other * finalization functions. */ /* * THREADED => Forward this to the origin thread * * Note: DeleteThreadReflectedTransformMap() is the thread exit handler * for the origin thread. Use this to clean up the structure? Except * if lost? */ #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; ForwardOpToOwnerThread(rtPtr, ForwardedClose, &p); result = p.base.code; if (result != TCL_OK) { FreeReceivedError(&p); } } #endif /* TCL_THREADS */ Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); return EOK; } /* * In the reflected channel implementation a cleaned method mask here * implies that the channel creation was aborted, and "finalize" must not * be called. for transformations however we are not going through here on * such an abort, but directly through FreeReflectedTransform. So for us * that check is not necessary. We always go through 'finalize'. */ if (HAS(rtPtr->methods, METH_DRAIN) && !rtPtr->readIsDrained) { if (!TransformDrain(rtPtr, &errorCode)) { #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); return errorCode; } #endif /* TCL_THREADS */ errorCodeSet = 1; goto cleanup; } } if (HAS(rtPtr->methods, METH_FLUSH)) { if (!TransformFlush(rtPtr, &errorCode, FLUSH_WRITE)) { #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); return errorCode; } #endif /* TCL_THREADS */ errorCodeSet = 1; goto cleanup; } } /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; ForwardOpToOwnerThread(rtPtr, ForwardedClose, &p); result = p.base.code; Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); if (result != TCL_OK) { PassReceivedErrorInterp(interp, &p); return EINVAL; } return EOK; } #endif /* TCL_THREADS */ /* * Do the actual invokation of "finalize" now; we're in the right thread. */ result = InvokeTclMethod(rtPtr, "finalize", NULL, NULL, &resObj); if ((result != TCL_OK) && (interp != NULL)) { Tcl_SetChannelErrorInterp(interp, resObj); } Tcl_DecrRefCount(resObj); /* Remove reference we held from the * invoke. */ cleanup: /* * Remove the transform from the map before releasing the memory, to * prevent future accesses from finding and dereferencing a dangling * pointer. * * NOTE: The transform may not be in the map. This is ok, that happens * when the transform was created in a different interpreter and/or thread * and then was moved here. * * NOTE: The channel may have been removed from the map already via * the per-interp DeleteReflectedTransformMap exit-handler. */ if (!rtPtr->dead) { rtmPtr = GetReflectedTransformMap(rtPtr->interp); hPtr = Tcl_FindHashEntry(&rtmPtr->map, Tcl_GetString(rtPtr->handle)); if (hPtr) { Tcl_DeleteHashEntry(hPtr); } /* * In a threaded interpreter we manage a per-thread map as well, * to allow us to survive if the script level pulls the rug out * under a channel by deleting the owning thread. */ #ifdef TCL_THREADS rtmPtr = GetThreadReflectedTransformMap(); hPtr = Tcl_FindHashEntry(&rtmPtr->map, Tcl_GetString(rtPtr->handle)); if (hPtr) { Tcl_DeleteHashEntry(hPtr); } #endif /* TCL_THREADS */ } Tcl_EventuallyFree (rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); return errorCodeSet ? errorCode : ((result == TCL_OK) ? EOK : EINVAL); } /* *---------------------------------------------------------------------- * * ReflectInput -- * * This function is invoked when more data is requested from the channel. * * Results: * The number of bytes read. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectInput( ClientData clientData, char *buf, int toRead, int *errorCodePtr) { ReflectedTransform *rtPtr = clientData; int gotBytes, copied, readBytes; Tcl_Obj *bufObj; /* * The following check can be done before thread redirection, because we * are reading from an item which is readonly, i.e. will never change * during the lifetime of the channel. */ if (!(rtPtr->methods & FLAG(METH_READ))) { SetChannelErrorStr(rtPtr->chan, msg_read_unsup); *errorCodePtr = EINVAL; return -1; } Tcl_Preserve(rtPtr); /* TODO: Consider a more appropriate buffer size. */ bufObj = Tcl_NewByteArrayObj(NULL, toRead); Tcl_IncrRefCount(bufObj); gotBytes = 0; if (rtPtr->eofPending) { goto stop; } rtPtr->readIsDrained = 0; while (toRead > 0) { /* * Loop until the request is satisfied (or no data available from * below, possibly EOF). */ copied = ResultCopy(&rtPtr->result, UCHARP(buf), toRead); toRead -= copied; buf += copied; gotBytes += copied; if (toRead == 0) { goto stop; } if (rtPtr->eofPending) { goto stop; } /* * The buffer is exhausted, but the caller wants even more. We now * have to go to the underlying channel, get more bytes and then * transform them for delivery. We may not get what we want (full EOF * or temporarily out of data). * * Length (rtPtr->result) == 0, toRead > 0 here. Use 'buf'! as target * to store the intermediary information read from the parent channel. * * Ask the transform how much data it allows us to read from the * underlying channel. This feature allows the transform to signal EOF * upstream although there is none downstream. Useful to control an * unbounded 'fcopy' for example, either through counting bytes, or by * pattern matching. */ if ((rtPtr->methods & FLAG(METH_LIMIT))) { int maxRead = -1; if (!TransformLimit(rtPtr, errorCodePtr, &maxRead)) { goto error; } if (maxRead == 0) { goto stop; } else if (maxRead > 0) { if (maxRead < toRead) { toRead = maxRead; } } /* else: 'maxRead < 0' == Accept the current value of toRead */ } if (toRead <= 0) { goto stop; } readBytes = Tcl_ReadRaw(rtPtr->parent, (char *) Tcl_SetByteArrayLength(bufObj, toRead), toRead); if (readBytes < 0) { if (Tcl_InputBlocked(rtPtr->parent) && (gotBytes > 0)) { /* * Down channel is blocked and offers zero additional bytes. * The nonzero gotBytes already returned makes the total * operation a valid short read. Return to caller. */ goto stop; } /* * Either the down channel is not blocked (a real error) * or it is and there are gotBytes==0 byte copied so far. * In either case, pass up the error, so we either report * any real error, or do not mistakenly signal EOF by * returning 0 to the caller. */ *errorCodePtr = Tcl_GetErrno(); goto error; } if (readBytes == 0) { /* * Zero returned from Tcl_ReadRaw() always indicates EOF * on the down channel. */ rtPtr->eofPending = 1; /* * Now this is a bit different. The partial data waiting is * converted and returned. */ if (HAS(rtPtr->methods, METH_DRAIN)) { if (!TransformDrain(rtPtr, errorCodePtr)) { goto error; } } if (ResultLength(&rtPtr->result) == 0) { /* * The drain delivered nothing. */ goto stop; } continue; /* at: while (toRead > 0) */ } /* readBytes == 0 */ /* * Transform the read chunk, which was not empty. Anything we got back * is a transformation result is put into our buffers, and the next * iteration will put it into the result. */ Tcl_SetByteArrayLength(bufObj, readBytes); if (!TransformRead(rtPtr, errorCodePtr, bufObj)) { goto error; } if (Tcl_IsShared(bufObj)) { Tcl_DecrRefCount(bufObj); bufObj = Tcl_NewObj(); Tcl_IncrRefCount(bufObj); } Tcl_SetByteArrayLength(bufObj, 0); } /* while toRead > 0 */ stop: if (gotBytes == 0) { rtPtr->eofPending = 0; } Tcl_DecrRefCount(bufObj); Tcl_Release(rtPtr); return gotBytes; error: gotBytes = -1; goto stop; } /* *---------------------------------------------------------------------- * * ReflectOutput -- * * This function is invoked when data is written to the channel. * * Results: * The number of bytes actually written. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectOutput( ClientData clientData, const char *buf, int toWrite, int *errorCodePtr) { ReflectedTransform *rtPtr = clientData; /* * The following check can be done before thread redirection, because we * are reading from an item which is readonly, i.e. will never change * during the lifetime of the channel. */ if (!(rtPtr->methods & FLAG(METH_WRITE))) { SetChannelErrorStr(rtPtr->chan, msg_write_unsup); *errorCodePtr = EINVAL; return -1; } if (toWrite == 0) { /* * Nothing came in to write, ignore the call */ return 0; } /* * Discard partial data in the input buffers, i.e. on the read side. Like * we do when explicitly seeking as well. */ Tcl_Preserve(rtPtr); if ((rtPtr->methods & FLAG(METH_CLEAR))) { TransformClear(rtPtr); } /* * Hand the data to the transformation itself. Anything it deigned to * return to us is a (partial) transformation result and written to the * parent channel for further processing. */ if (!TransformWrite(rtPtr, errorCodePtr, UCHARP(buf), toWrite)) { Tcl_Release(rtPtr); return -1; } *errorCodePtr = EOK; Tcl_Release(rtPtr); return toWrite; } /* *---------------------------------------------------------------------- * * ReflectSeekWide / ReflectSeek -- * * This function is invoked when the user wishes to seek on the channel. * * Results: * The new location of the access point. * * Side effects: * Allocates memory. Arbitrary, per the parent channel, and the called * scripts. * *---------------------------------------------------------------------- */ static Tcl_WideInt ReflectSeekWide( ClientData clientData, Tcl_WideInt offset, int seekMode, int *errorCodePtr) { ReflectedTransform *rtPtr = clientData; Channel *parent = (Channel *) rtPtr->parent; Tcl_WideInt curPos; /* Position on the device. */ Tcl_DriverSeekProc *seekProc = Tcl_ChannelSeekProc(Tcl_GetChannelType(rtPtr->parent)); /* * Fail if the parent channel is not seekable. */ if (seekProc == NULL) { Tcl_SetErrno(EINVAL); return Tcl_LongAsWide(-1); } /* * Check if we can leave out involving the Tcl level, i.e. transformation * handler. This is true for tell requests, and transformations which * support neither flush, nor drain. For these cases we can pass the * request down and the result back up unchanged. */ Tcl_Preserve(rtPtr); if (((seekMode != SEEK_CUR) || (offset != 0)) && (HAS(rtPtr->methods, METH_CLEAR) || HAS(rtPtr->methods, METH_FLUSH))) { /* * Neither a tell request, nor clear/flush both not supported. We have * to go through the Tcl level to clear and/or flush the * transformation. */ if (rtPtr->methods & FLAG(METH_CLEAR)) { TransformClear(rtPtr); } /* * When flushing the transform for seeking the generated results are * irrelevant. We cannot put them into the channel, this would move * the location, throwing it off with regard to where we are and are * seeking to. */ if (HAS(rtPtr->methods, METH_FLUSH)) { if (!TransformFlush(rtPtr, errorCodePtr, FLUSH_DISCARD)) { Tcl_Release(rtPtr); return -1; } } } /* * Now seek to the new position in the channel as requested by the * caller. Note that we prefer the wideSeekProc if that is available and * non-NULL... */ if (HaveVersion(parent->typePtr, TCL_CHANNEL_VERSION_3) && parent->typePtr->wideSeekProc != NULL) { curPos = parent->typePtr->wideSeekProc(parent->instanceData, offset, seekMode, errorCodePtr); } else if (offset < Tcl_LongAsWide(LONG_MIN) || offset > Tcl_LongAsWide(LONG_MAX)) { *errorCodePtr = EOVERFLOW; curPos = Tcl_LongAsWide(-1); } else { curPos = Tcl_LongAsWide(parent->typePtr->seekProc( parent->instanceData, Tcl_WideAsLong(offset), seekMode, errorCodePtr)); } if (curPos == Tcl_LongAsWide(-1)) { Tcl_SetErrno(*errorCodePtr); } *errorCodePtr = EOK; Tcl_Release(rtPtr); return curPos; } static int ReflectSeek( ClientData clientData, long offset, int seekMode, int *errorCodePtr) { /* * This function can be invoked from a transformation which is based on * standard seeking, i.e. non-wide. Because of this we have to implement * it, a dummy is not enough. We simply delegate the call to the wide * routine. */ return (int) ReflectSeekWide(clientData, Tcl_LongAsWide(offset), seekMode, errorCodePtr); } /* *---------------------------------------------------------------------- * * ReflectWatch -- * * This function is invoked to tell the channel what events the I/O * system is interested in. * * Results: * None. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static void ReflectWatch( ClientData clientData, int mask) { ReflectedTransform *rtPtr = clientData; Tcl_DriverWatchProc *watchProc; watchProc = Tcl_ChannelWatchProc(Tcl_GetChannelType(rtPtr->parent)); watchProc(Tcl_GetChannelInstanceData(rtPtr->parent), mask); /* * Management of the internal timer. */ if (!(mask & TCL_READABLE) || (ResultLength(&rtPtr->result) == 0)) { /* * A pending timer may exist, but either is there no (more) interest * in the events it generates or nothing is available for reading. * Remove it, if existing. */ TimerKill(rtPtr); } else { /* * There might be no pending timer, but there is interest in readable * events and we actually have data waiting, so generate a timer to * flush that if it does not exist. */ TimerSetup(rtPtr); } } /* *---------------------------------------------------------------------- * * ReflectBlock -- * * This function is invoked to tell the channel which blocking behaviour * is required of it. * * Results: * A posix error number. * * Side effects: * Allocates memory. Arbitrary, as it calls upon a script. * *---------------------------------------------------------------------- */ static int ReflectBlock( ClientData clientData, int nonblocking) { ReflectedTransform *rtPtr = clientData; /* * Transformations simply record the blocking mode in their C level * structure for use by --> ReflectInput. The Tcl level doesn't see this * information or change. As such thread forwarding is not required. */ rtPtr->nonblocking = nonblocking; return EOK; } /* *---------------------------------------------------------------------- * * ReflectSetOption -- * * This function is invoked to configure a channel option. * * Results: * A standard Tcl result code. * * Side effects: * Arbitrary, per the parent channel. * *---------------------------------------------------------------------- */ static int ReflectSetOption( ClientData clientData, /* Channel to query */ Tcl_Interp *interp, /* Interpreter to leave error messages in */ const char *optionName, /* Name of requested option */ const char *newValue) /* The new value */ { ReflectedTransform *rtPtr = clientData; /* * Transformations have no options. Thus the call is passed down unchanged * to the parent channel for processing. Its results are passed back * unchanged as well. This all happens in the thread we are in. As the Tcl * level is not involved there is no need for thread forwarding. */ Tcl_DriverSetOptionProc *setOptionProc = Tcl_ChannelSetOptionProc(Tcl_GetChannelType(rtPtr->parent)); if (setOptionProc == NULL) { return TCL_ERROR; } return setOptionProc(Tcl_GetChannelInstanceData(rtPtr->parent), interp, optionName, newValue); } /* *---------------------------------------------------------------------- * * ReflectGetOption -- * * This function is invoked to retrieve all or a channel options. * * Results: * A standard Tcl result code. * * Side effects: * Arbitrary, per the parent channel. * *---------------------------------------------------------------------- */ static int ReflectGetOption( ClientData clientData, /* Channel to query */ Tcl_Interp *interp, /* Interpreter to leave error messages in */ const char *optionName, /* Name of reuqested option */ Tcl_DString *dsPtr) /* String to place the result into */ { ReflectedTransform *rtPtr = clientData; /* * Transformations have no options. Thus the call is passed down unchanged * to the parent channel for processing. Its results are passed back * unchanged as well. This all happens in the thread we are in. As the Tcl * level is not involved there is no need for thread forwarding. * * Note that the parent not having a driver for option retrieval is not an * immediate error. A query for all options is ok. Only a request for a * specific option has to fail. */ Tcl_DriverGetOptionProc *getOptionProc = Tcl_ChannelGetOptionProc(Tcl_GetChannelType(rtPtr->parent)); if (getOptionProc != NULL) { return getOptionProc(Tcl_GetChannelInstanceData(rtPtr->parent), interp, optionName, dsPtr); } else if (optionName == NULL) { return TCL_OK; } else { return TCL_ERROR; } } /* *---------------------------------------------------------------------- * * ReflectHandle -- * * This function is invoked to retrieve the associated file handle. * * Results: * A standard Tcl result code. * * Side effects: * Arbitrary, per the parent channel. * *---------------------------------------------------------------------- */ static int ReflectHandle( ClientData clientData, int direction, ClientData *handlePtr) { ReflectedTransform *rtPtr = clientData; /* * Transformations have no handle of their own. As such we simply query * the parent channel for it. This way the qery will ripple down through * all transformations until reaches the base channel. Which then returns * its handle, or fails. The former will then ripple up the stack. * * This all happens in the thread we are in. As the Tcl level is not * involved no forwarding is required. */ return Tcl_GetChannelHandle(rtPtr->parent, direction, handlePtr); } /* *---------------------------------------------------------------------- * * ReflectNotify -- * * This function is invoked to reported incoming events. * * Results: * A standard Tcl result code. * * Side effects: * Arbitrary, per the parent channel. * *---------------------------------------------------------------------- */ static int ReflectNotify( ClientData clientData, int mask) { ReflectedTransform *rtPtr = clientData; /* * An event occured in the underlying channel. * * We delete our timer. It was not fired, yet we are here, so the channel * below generated such an event and we don't have to. The renewal of the * interest after the execution of channel handlers will eventually cause * us to recreate the timer (in ReflectWatch). */ TimerKill(rtPtr); /* * Pass to higher layers. */ return mask; } /* * Helpers. ========================================================= */ /* *---------------------------------------------------------------------- * * DecodeEventMask -- * * This function takes an internal bitmask of events and constructs the * equivalent list of event items. * * Results: * A Tcl_Obj reference. The object will have a refCount of one. The user * has to decrement it to release the object. * * Side effects: * None. * *---------------------------------------------------------------------- * DUPLICATE of 'DecodeEventMask' in tclIORChan.c */ static Tcl_Obj * DecodeEventMask( int mask) { register const char *eventStr; Tcl_Obj *evObj; switch (mask & RANDW) { case RANDW: eventStr = "read write"; break; case TCL_READABLE: eventStr = "read"; break; case TCL_WRITABLE: eventStr = "write"; break; default: eventStr = ""; break; } evObj = Tcl_NewStringObj(eventStr, -1); Tcl_IncrRefCount(evObj); return evObj; } /* *---------------------------------------------------------------------- * * NewReflectedTransform -- * * This function is invoked to allocate and initialize the instance data * of a new reflected channel. * * Results: * A heap-allocated channel instance. * * Side effects: * Allocates memory. * *---------------------------------------------------------------------- */ static ReflectedTransform * NewReflectedTransform( Tcl_Interp *interp, Tcl_Obj *cmdpfxObj, int mode, Tcl_Obj *handleObj, Tcl_Channel parentChan) { ReflectedTransform *rtPtr; int listc; Tcl_Obj **listv; int i; rtPtr = ckalloc(sizeof(ReflectedTransform)); /* rtPtr->chan: Assigned by caller. Dummy data here. */ /* rtPtr->methods: Assigned by caller. Dummy data here. */ rtPtr->chan = NULL; rtPtr->methods = 0; #ifdef TCL_THREADS rtPtr->thread = Tcl_GetCurrentThread(); #endif rtPtr->parent = parentChan; rtPtr->interp = interp; rtPtr->handle = handleObj; Tcl_IncrRefCount(handleObj); rtPtr->timer = NULL; rtPtr->mode = 0; rtPtr->readIsDrained = 0; rtPtr->eofPending = 0; rtPtr->nonblocking = (((Channel *) parentChan)->state->flags & CHANNEL_NONBLOCKING); rtPtr->dead = 0; /* * Query parent for current blocking mode. */ ResultInit(&rtPtr->result); /* * Method placeholder. */ /* ASSERT: cmdpfxObj is a Tcl List */ Tcl_ListObjGetElements(interp, cmdpfxObj, &listc, &listv); /* * See [==] as well. * Storage for the command prefix and the additional words required for * the invocation of methods in the command handler. * * listv [0] [listc-1] | [listc] [listc+1] | * argv [0] ... [.] | [argc-2] [argc-1] | [argc] [argc+2] * cmd ... pfx | method chan | detail1 detail2 */ rtPtr->argc = listc + 2; rtPtr->argv = ckalloc(sizeof(Tcl_Obj *) * (listc+4)); /* * Duplicate object references. */ for (i=0; iargv[i] = listv[i]; Tcl_IncrRefCount(word); } i++; /* Skip placeholder for method */ /* * See [x] in FreeReflectedTransform for release */ rtPtr->argv[i] = handleObj; Tcl_IncrRefCount(handleObj); /* * The next two objects are kept empty, varying arguments. */ /* * Initialization complete. */ return rtPtr; } /* *---------------------------------------------------------------------- * * NextHandle -- * * This function is invoked to generate a channel handle for a new * reflected channel. * * Results: * A Tcl_Obj containing the string of the new channel handle. The * refcount of the returned object is -- zero --. * * Side effects: * May allocate memory. Mutex protected critical section locks out other * threads for a short time. * *---------------------------------------------------------------------- */ static Tcl_Obj * NextHandle(void) { /* * Count number of generated reflected channels. Used for id generation. * Ids are never reclaimed and there is no dealing with wrap around. On * the other hand, "unsigned long" should be big enough except for * absolute longrunners (generate a 100 ids per second => overflow will * occur in 1 1/3 years). */ TCL_DECLARE_MUTEX(rtCounterMutex) static unsigned long rtCounter = 0; Tcl_Obj *resObj; Tcl_MutexLock(&rtCounterMutex); resObj = Tcl_ObjPrintf("rt%lu", rtCounter); rtCounter++; Tcl_MutexUnlock(&rtCounterMutex); return resObj; } static void FreeReflectedTransformArgs( ReflectedTransform *rtPtr) { int i, n = rtPtr->argc - 2; if (n < 0) { return; } Tcl_DecrRefCount(rtPtr->handle); rtPtr->handle = NULL; for (i=0; iargv[i]); } /* * See [x] in NewReflectedTransform for lock * n+1 = argc-1. */ Tcl_DecrRefCount(rtPtr->argv[n+1]); rtPtr->argc = 1; } static void FreeReflectedTransform( ReflectedTransform *rtPtr) { TimerKill(rtPtr); ResultClear(&rtPtr->result); FreeReflectedTransformArgs(rtPtr); ckfree(rtPtr->argv); ckfree(rtPtr); } /* *---------------------------------------------------------------------- * * InvokeTclMethod -- * * This function is used to invoke the Tcl level of a reflected channel. * It handles all the command assembly, invokation, and generic state and * result mgmt. It does *not* handle thread redirection; that is the * responsibility of clients of this function. * * Results: * Result code and data as returned by the method. * * Side effects: * Arbitrary, as it calls upon a Tcl script. * * Contract: * argOneObj.refCount >= 1 on entry and exit, if argOneObj != NULL * argTwoObj.refCount >= 1 on entry and exit, if argTwoObj != NULL * resObj.refCount in {0, 1, ...} * *---------------------------------------------------------------------- * Semi-DUPLICATE of 'InvokeTclMethod' in tclIORChan.c * - Semi because different structures are used. * - Still possible to factor out the commonalities into a separate structure. */ static int InvokeTclMethod( ReflectedTransform *rtPtr, const char *method, Tcl_Obj *argOneObj, /* NULL'able */ Tcl_Obj *argTwoObj, /* NULL'able */ Tcl_Obj **resultObjPtr) /* NULL'able */ { int cmdc; /* #words in constructed command */ Tcl_Obj *methObj = NULL; /* Method name in object form */ Tcl_InterpState sr; /* State of handler interp */ int result; /* Result code of method invokation */ Tcl_Obj *resObj = NULL; /* Result of method invokation. */ if (rtPtr->dead) { /* * The transform is marked as dead. Bail out immediately, with an * appropriate error. */ if (resultObjPtr != NULL) { resObj = Tcl_NewStringObj(msg_dstlost,-1); *resultObjPtr = resObj; Tcl_IncrRefCount(resObj); } return TCL_ERROR; } /* * NOTE (5): Decide impl. issue: Cache objects with method names? * Requires TSD data as reflections can be created in many different * threads. * NO: Caching of command resolutions means storage per channel. */ /* * Insert method into the pre-allocated area, after the command prefix, * before the channel id. */ methObj = Tcl_NewStringObj(method, -1); Tcl_IncrRefCount(methObj); rtPtr->argv[rtPtr->argc - 2] = methObj; /* * Append the additional argument containing method specific details * behind the channel id. If specified. * * Because of the contract there is no need to increment the refcounts. * The objects will survive the Tcl_EvalObjv without change. */ cmdc = rtPtr->argc; if (argOneObj) { rtPtr->argv[cmdc] = argOneObj; cmdc++; if (argTwoObj) { rtPtr->argv[cmdc] = argTwoObj; cmdc++; } } /* * And run the handler... This is done in auch a manner which leaves any * existing state intact. */ sr = Tcl_SaveInterpState(rtPtr->interp, 0 /* Dummy */); Tcl_Preserve(rtPtr); Tcl_Preserve(rtPtr->interp); result = Tcl_EvalObjv(rtPtr->interp, cmdc, rtPtr->argv, TCL_EVAL_GLOBAL); /* * We do not try to extract the result information if the caller has no * interest in it. I.e. there is no need to put effort into creating * something which is discarded immediately after. */ if (resultObjPtr) { if (result == TCL_OK) { /* * Ok result taken as is, also if the caller requests that there * is no capture. */ resObj = Tcl_GetObjResult(rtPtr->interp); } else { /* * Non-ok result is always treated as an error. We have to capture * the full state of the result, including additional options. * * This is complex and ugly, and would be completely unnecessary * if we only added support for a TCL_FORBID_EXCEPTIONS flag. */ if (result != TCL_ERROR) { Tcl_Obj *cmd = Tcl_NewListObj(cmdc, rtPtr->argv); int cmdLen; const char *cmdString = Tcl_GetStringFromObj(cmd, &cmdLen); Tcl_IncrRefCount(cmd); Tcl_ResetResult(rtPtr->interp); Tcl_SetObjResult(rtPtr->interp, Tcl_ObjPrintf( "chan handler returned bad code: %d", result)); Tcl_LogCommandInfo(rtPtr->interp, cmdString, cmdString, cmdLen); Tcl_DecrRefCount(cmd); result = TCL_ERROR; } Tcl_AppendObjToErrorInfo(rtPtr->interp, Tcl_ObjPrintf( "\n (chan handler subcommand \"%s\")", method)); resObj = MarshallError(rtPtr->interp); } Tcl_IncrRefCount(resObj); } Tcl_RestoreInterpState(rtPtr->interp, sr); Tcl_Release(rtPtr->interp); Tcl_Release(rtPtr); /* * Cleanup of the dynamic parts of the command. * * The detail objects survived the Tcl_EvalObjv without change because of * the contract. Therefore there is no need to decrement the refcounts. Only * the internal method object has to be disposed of. */ Tcl_DecrRefCount(methObj); /* * The resObj has a ref count of 1 at this location. This means that the * caller of InvokeTclMethod has to dispose of it (but only if it was * returned to it). */ if (resultObjPtr != NULL) { *resultObjPtr = resObj; } /* * There no need to handle the case where nothing is returned, because for * that case resObj was not set anyway. */ return result; } /* *---------------------------------------------------------------------- * * GetReflectedTransformMap -- * * Gets and potentially initializes the reflected channel map for an * interpreter. * * Results: * A pointer to the map created, for use by the caller. * * Side effects: * Initializes the reflected channel map for an interpreter. * *---------------------------------------------------------------------- */ static ReflectedTransformMap * GetReflectedTransformMap( Tcl_Interp *interp) { ReflectedTransformMap *rtmPtr = Tcl_GetAssocData(interp, RTMKEY, NULL); if (rtmPtr == NULL) { rtmPtr = ckalloc(sizeof(ReflectedTransformMap)); Tcl_InitHashTable(&rtmPtr->map, TCL_STRING_KEYS); Tcl_SetAssocData(interp, RTMKEY, (Tcl_InterpDeleteProc *) DeleteReflectedTransformMap, rtmPtr); } return rtmPtr; } /* *---------------------------------------------------------------------- * * DeleteReflectedTransformMap -- * * Deletes the channel table for an interpreter, closing any open * channels whose refcount reaches zero. This procedure is invoked when * an interpreter is deleted, via the AssocData cleanup mechanism. * * Results: * None. * * Side effects: * Deletes the hash table of channels. May close channels. May flush * output on closed channels. Removes any channeEvent handlers that were * registered in this interpreter. * *---------------------------------------------------------------------- */ static void DeleteReflectedTransformMap( ClientData clientData, /* The per-interpreter data structure. */ Tcl_Interp *interp) /* The interpreter being deleted. */ { ReflectedTransformMap *rtmPtr; /* The map */ Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ ReflectedTransform *rtPtr; #ifdef TCL_THREADS ForwardingResult *resultPtr; ForwardingEvent *evPtr; ForwardParam *paramPtr; #endif /* TCL_THREADS */ /* * Delete all entries. The channels may have been closed already, or will * be closed later, by the standard IO finalization of an interpreter * under destruction. Except for the channels which were moved to a * different interpreter and/or thread. They do not exist from the IO * systems point of view and will not get closed. Therefore mark all as * dead so that any future access will cause a proper error. For channels * in a different thread we actually do the same as * DeleteThreadReflectedTransformMap(), just restricted to the channels of * this interp. */ rtmPtr = clientData; for (hPtr = Tcl_FirstHashEntry(&rtmPtr->map, &hSearch); hPtr != NULL; hPtr = Tcl_FirstHashEntry(&rtmPtr->map, &hSearch)) { rtPtr = Tcl_GetHashValue(hPtr); rtPtr->dead = 1; Tcl_DeleteHashEntry(hPtr); } Tcl_DeleteHashTable(&rtmPtr->map); ckfree(&rtmPtr->map); #ifdef TCL_THREADS /* * The origin interpreter for one or more reflected channels is gone. */ /* * Get the map of all channels handled by the current thread. This is a * ReflectedTransformMap, but on a per-thread basis, not per-interp. Go * through the channels and remove all which were handled by this * interpreter. They have already been marked as dead. */ rtmPtr = GetThreadReflectedTransformMap(); for (hPtr = Tcl_FirstHashEntry(&rtmPtr->map, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { rtPtr = Tcl_GetHashValue(hPtr); if (rtPtr->interp != interp) { /* * Ignore entries for other interpreters. */ continue; } rtPtr->dead = 1; FreeReflectedTransformArgs(rtPtr); Tcl_DeleteHashEntry(hPtr); } /* * Go through the list of pending results and cancel all whose events were * destined for this interpreter. While this is in progress we block any * other access to the list of pending results. */ Tcl_MutexLock(&rtForwardMutex); for (resultPtr = forwardList; resultPtr != NULL; resultPtr = resultPtr->nextPtr) { if (resultPtr->dsti != interp) { /* * Ignore results/events for other interpreters. */ continue; } /* * The receiver for the event exited, before processing the event. We * detach the result now, wake the originator up and signal failure. */ evPtr = resultPtr->evPtr; if (evPtr == NULL) { continue; } paramPtr = evPtr->param; evPtr->resultPtr = NULL; resultPtr->evPtr = NULL; resultPtr->result = TCL_ERROR; ForwardSetStaticError(paramPtr, msg_send_dstlost); Tcl_ConditionNotify(&resultPtr->done); } Tcl_MutexUnlock(&rtForwardMutex); #endif /* TCL_THREADS */ } #ifdef TCL_THREADS /* *---------------------------------------------------------------------- * * GetThreadReflectedTransformMap -- * * Gets and potentially initializes the reflected channel map for a * thread. * * Results: * A pointer to the map created, for use by the caller. * * Side effects: * Initializes the reflected channel map for a thread. * *---------------------------------------------------------------------- */ static ReflectedTransformMap * GetThreadReflectedTransformMap(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!tsdPtr->rtmPtr) { tsdPtr->rtmPtr = ckalloc(sizeof(ReflectedTransformMap)); Tcl_InitHashTable(&tsdPtr->rtmPtr->map, TCL_STRING_KEYS); Tcl_CreateThreadExitHandler(DeleteThreadReflectedTransformMap, NULL); } return tsdPtr->rtmPtr; } /* *---------------------------------------------------------------------- * * DeleteThreadReflectedTransformMap -- * * Deletes the channel table for a thread. This procedure is invoked when * a thread is deleted. The channels have already been marked as dead, in * DeleteReflectedTransformMap(). * * Results: * None. * * Side effects: * Deletes the hash table of channels. * *---------------------------------------------------------------------- */ static void DeleteThreadReflectedTransformMap( ClientData clientData) /* The per-thread data structure. */ { Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ Tcl_ThreadId self = Tcl_GetCurrentThread(); ReflectedTransformMap *rtmPtr; /* The map */ ForwardingResult *resultPtr; /* * The origin thread for one or more reflected channels is gone. * NOTE: If this function is called due to a thread getting killed the * per-interp DeleteReflectedTransformMap is apparently not called. */ /* * Get the map of all channels handled by the current thread. This is a * ReflectedTransformMap, but on a per-thread basis, not per-interp. Go * through the channels, remove all, mark them as dead. */ rtmPtr = GetThreadReflectedTransformMap(); for (hPtr = Tcl_FirstHashEntry(&rtmPtr->map, &hSearch); hPtr != NULL; hPtr = Tcl_FirstHashEntry(&rtmPtr->map, &hSearch)) { ReflectedTransform *rtPtr = Tcl_GetHashValue(hPtr); rtPtr->dead = 1; FreeReflectedTransformArgs(rtPtr); Tcl_DeleteHashEntry(hPtr); } ckfree(rtmPtr); /* * Go through the list of pending results and cancel all whose events were * destined for this thread. While this is in progress we block any * other access to the list of pending results. */ Tcl_MutexLock(&rtForwardMutex); for (resultPtr = forwardList; resultPtr != NULL; resultPtr = resultPtr->nextPtr) { ForwardingEvent *evPtr; ForwardParam *paramPtr; if (resultPtr->dst != self) { /* * Ignore results/events for other threads. */ continue; } /* * The receiver for the event exited, before processing the event. We * detach the result now, wake the originator up and signal failure. */ evPtr = resultPtr->evPtr; if (evPtr == NULL) { continue; } paramPtr = evPtr->param; evPtr->resultPtr = NULL; resultPtr->evPtr = NULL; resultPtr->result = TCL_ERROR; ForwardSetStaticError(paramPtr, msg_send_dstlost); Tcl_ConditionNotify(&resultPtr->done); } Tcl_MutexUnlock(&rtForwardMutex); } static void ForwardOpToOwnerThread( ReflectedTransform *rtPtr, /* Channel instance */ ForwardedOperation op, /* Forwarded driver operation */ const void *param) /* Arguments */ { Tcl_ThreadId dst = rtPtr->thread; ForwardingEvent *evPtr; ForwardingResult *resultPtr; /* * We gather the lock early. This allows us to check the liveness of the * channel without interference from DeleteThreadReflectedTransformMap(). */ Tcl_MutexLock(&rtForwardMutex); if (rtPtr->dead) { /* * The channel is marked as dead. Bail out immediately, with an * appropriate error. Do not forget to unlock the mutex on this path. */ ForwardSetStaticError((ForwardParam *) param, msg_send_dstlost); Tcl_MutexUnlock(&rtForwardMutex); return; } /* * Create and initialize the event and data structures. */ evPtr = ckalloc(sizeof(ForwardingEvent)); resultPtr = ckalloc(sizeof(ForwardingResult)); evPtr->event.proc = ForwardProc; evPtr->resultPtr = resultPtr; evPtr->op = op; evPtr->rtPtr = rtPtr; evPtr->param = (ForwardParam *) param; resultPtr->src = Tcl_GetCurrentThread(); resultPtr->dst = dst; resultPtr->dsti = rtPtr->interp; resultPtr->done = NULL; resultPtr->result = -1; resultPtr->evPtr = evPtr; /* * Now execute the forward. */ TclSpliceIn(resultPtr, forwardList); /* Do not unlock here. That is done by the ConditionWait */ /* * Ensure cleanup of the event if the origin thread exits while this event * is pending or in progress. Exit of the destination thread is handled by * DeleteThreadReflectionChannelMap(), this is set up by * GetThreadReflectedTransformMap(). This is what we use the 'forwardList' * (see above) for. */ Tcl_CreateThreadExitHandler(SrcExitProc, evPtr); /* * Queue the event and poke the other thread's notifier. */ Tcl_ThreadQueueEvent(dst, (Tcl_Event *) evPtr, TCL_QUEUE_TAIL); Tcl_ThreadAlert(dst); /* * (*) Block until the other thread has either processed the transfer or * rejected it. */ while (resultPtr->result < 0) { /* * NOTE (1): Is it possible that the current thread goes away while * waiting here? IOW Is it possible that "SrcExitProc" is called * while we are here? See complementary note (2) in "SrcExitProc" * * The ConditionWait unlocks the mutex during the wait and relocks it * immediately after. */ Tcl_ConditionWait(&resultPtr->done, &rtForwardMutex, NULL); } /* * Unlink result from the forwarder list. No need to lock. Either still * locked, or locked by the ConditionWait */ TclSpliceOut(resultPtr, forwardList); resultPtr->nextPtr = NULL; resultPtr->prevPtr = NULL; Tcl_MutexUnlock(&rtForwardMutex); Tcl_ConditionFinalize(&resultPtr->done); /* * Kill the cleanup handler now, and the result structure as well, before * returning the success code. * * Note: The event structure has already been deleted by the destination * notifier, after it serviced the event. */ Tcl_DeleteThreadExitHandler(SrcExitProc, evPtr); ckfree(resultPtr); } static int ForwardProc( Tcl_Event *evGPtr, int mask) { /* * Notes regarding access to the referenced data. * * In principle the data belongs to the originating thread (see * evPtr->src), however this thread is currently blocked at (*), i.e. * quiescent. Because of this we can treat the data as belonging to us, * without fear of race conditions. I.e. we can read and write as we like. * * The only thing we cannot be sure of is the resultPtr. This can be be * NULLed if the originating thread went away while the event is handled * here now. */ ForwardingEvent *evPtr = (ForwardingEvent *) evGPtr; ForwardingResult *resultPtr = evPtr->resultPtr; ReflectedTransform *rtPtr = evPtr->rtPtr; Tcl_Interp *interp = rtPtr->interp; ForwardParam *paramPtr = evPtr->param; Tcl_Obj *resObj = NULL; /* Interp result of InvokeTclMethod */ ReflectedTransformMap *rtmPtr; /* Map of reflected channels with handlers in * this interp. */ Tcl_HashEntry *hPtr; /* Entry in the above map */ /* * Ignore the event if no one is waiting for its result anymore. */ if (!resultPtr) { return 1; } paramPtr->base.code = TCL_OK; paramPtr->base.msgStr = NULL; paramPtr->base.mustFree = 0; switch (evPtr->op) { /* * The destination thread for the following operations is * rtPtr->thread, which contains rtPtr->interp, the interp we have to * call upon for the driver. */ case ForwardedClose: /* * No parameters/results. */ if (InvokeTclMethod(rtPtr, "finalize", NULL, NULL, &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); } /* * Freeing is done here, in the origin thread, because the argv[] * objects belong to this thread. Deallocating them in a different * thread is not allowed */ /* * Remove the channel from the map before releasing the memory, to * prevent future accesses (like by 'postevent') from finding and * dereferencing a dangling pointer. */ rtmPtr = GetReflectedTransformMap(interp); hPtr = Tcl_FindHashEntry(&rtmPtr->map, Tcl_GetString(rtPtr->handle)); Tcl_DeleteHashEntry(hPtr); /* * In a threaded interpreter we manage a per-thread map as well, to * allow us to survive if the script level pulls the rug out under a * channel by deleting the owning thread. */ rtmPtr = GetThreadReflectedTransformMap(); hPtr = Tcl_FindHashEntry(&rtmPtr->map, Tcl_GetString(rtPtr->handle)); Tcl_DeleteHashEntry(hPtr); FreeReflectedTransformArgs(rtPtr); break; case ForwardedInput: { Tcl_Obj *bufObj = Tcl_NewByteArrayObj((unsigned char *) paramPtr->transform.buf, paramPtr->transform.size); Tcl_IncrRefCount(bufObj); if (InvokeTclMethod(rtPtr, "read", bufObj, NULL, &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); paramPtr->transform.size = -1; } else { /* * Process a regular return. Contains the transformation result. * Sent it back to the request originator. */ int bytec; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); paramPtr->transform.size = bytec; if (bytec > 0) { paramPtr->transform.buf = ckalloc(bytec); memcpy(paramPtr->transform.buf, bytev, (size_t)bytec); } else { paramPtr->transform.buf = NULL; } } Tcl_DecrRefCount(bufObj); break; } case ForwardedOutput: { Tcl_Obj *bufObj = Tcl_NewByteArrayObj((unsigned char *) paramPtr->transform.buf, paramPtr->transform.size); Tcl_IncrRefCount(bufObj); if (InvokeTclMethod(rtPtr, "write", bufObj, NULL, &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); paramPtr->transform.size = -1; } else { /* * Process a regular return. Contains the transformation result. * Sent it back to the request originator. */ int bytec; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); paramPtr->transform.size = bytec; if (bytec > 0) { paramPtr->transform.buf = ckalloc(bytec); memcpy(paramPtr->transform.buf, bytev, (size_t)bytec); } else { paramPtr->transform.buf = NULL; } } Tcl_DecrRefCount(bufObj); break; } case ForwardedDrain: if (InvokeTclMethod(rtPtr, "drain", NULL, NULL, &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); paramPtr->transform.size = -1; } else { /* * Process a regular return. Contains the transformation result. * Sent it back to the request originator. */ int bytec; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); paramPtr->transform.size = bytec; if (bytec > 0) { paramPtr->transform.buf = ckalloc(bytec); memcpy(paramPtr->transform.buf, bytev, (size_t)bytec); } else { paramPtr->transform.buf = NULL; } } break; case ForwardedFlush: if (InvokeTclMethod(rtPtr, "flush", NULL, NULL, &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); paramPtr->transform.size = -1; } else { /* * Process a regular return. Contains the transformation result. * Sent it back to the request originator. */ int bytec; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); paramPtr->transform.size = bytec; if (bytec > 0) { paramPtr->transform.buf = ckalloc(bytec); memcpy(paramPtr->transform.buf, bytev, (size_t)bytec); } else { paramPtr->transform.buf = NULL; } } break; case ForwardedClear: (void) InvokeTclMethod(rtPtr, "clear", NULL, NULL, NULL); break; case ForwardedLimit: if (InvokeTclMethod(rtPtr, "limit?", NULL, NULL, &resObj) != TCL_OK) { ForwardSetObjError(paramPtr, resObj); paramPtr->limit.max = -1; } else if (Tcl_GetIntFromObj(interp, resObj, ¶mPtr->limit.max) != TCL_OK) { ForwardSetObjError(paramPtr, MarshallError(interp)); paramPtr->limit.max = -1; } break; default: /* * Bad operation code. */ Tcl_Panic("Bad operation code in ForwardProc"); break; } /* * Remove the reference we held on the result of the invoke, if we had * such. */ if (resObj != NULL) { Tcl_DecrRefCount(resObj); } if (resultPtr) { /* * Report the forwarding result synchronously to the waiting caller. * This unblocks (*) as well. This is wrapped into a conditional * because the caller may have exited in the mean time. */ Tcl_MutexLock(&rtForwardMutex); resultPtr->result = TCL_OK; Tcl_ConditionNotify(&resultPtr->done); Tcl_MutexUnlock(&rtForwardMutex); } return 1; } static void SrcExitProc( ClientData clientData) { ForwardingEvent *evPtr = clientData; ForwardingResult *resultPtr; ForwardParam *paramPtr; /* * NOTE (2): Can this handler be called with the originator blocked? */ /* * The originator for the event exited. It is not sure if this can happen, * as the originator should be blocked at (*) while the event is in * transit/pending. * * We make sure that the event cannot refer to the result anymore, remove * it from the list of pending results and free the structure. Locking the * access ensures that we cannot get in conflict with "ForwardProc", * should it already execute the event. */ Tcl_MutexLock(&rtForwardMutex); resultPtr = evPtr->resultPtr; paramPtr = evPtr->param; evPtr->resultPtr = NULL; resultPtr->evPtr = NULL; resultPtr->result = TCL_ERROR; ForwardSetStaticError(paramPtr, msg_send_originlost); /* * See below: TclSpliceOut(resultPtr, forwardList); */ Tcl_MutexUnlock(&rtForwardMutex); /* * This unlocks (*). The structure will be spliced out and freed by * "ForwardProc". Maybe. */ Tcl_ConditionNotify(&resultPtr->done); } static void ForwardSetObjError( ForwardParam *paramPtr, Tcl_Obj *obj) { int len; const char *msgStr = Tcl_GetStringFromObj(obj, &len); len++; ForwardSetDynamicError(paramPtr, ckalloc(len)); memcpy(paramPtr->base.msgStr, msgStr, (unsigned) len); } #endif /* TCL_THREADS */ /* *---------------------------------------------------------------------- * * TimerKill -- * * Timer management. Removes the internal timer if it exists. * * Side effects: * See above. * * Result: * None. * *---------------------------------------------------------------------- */ static void TimerKill( ReflectedTransform *rtPtr) { if (rtPtr->timer == NULL) { return; } /* * Delete an existing flush-out timer, prevent it from firing on a * removed/dead channel. */ Tcl_DeleteTimerHandler(rtPtr->timer); rtPtr->timer = NULL; } /* *---------------------------------------------------------------------- * * TimerSetup -- * * Timer management. Creates the internal timer if it does not exist. * * Side effects: * See above. * * Result: * None. * *---------------------------------------------------------------------- */ static void TimerSetup( ReflectedTransform *rtPtr) { if (rtPtr->timer != NULL) { return; } rtPtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, TimerRun, rtPtr); } /* *---------------------------------------------------------------------- * * TimerRun -- * * Called by the notifier (-> timer) to flush out information waiting in * channel buffers. * * Side effects: * As of 'Tcl_NotifyChannel'. * * Result: * None. * *---------------------------------------------------------------------- */ static void TimerRun( ClientData clientData) { ReflectedTransform *rtPtr = clientData; rtPtr->timer = NULL; Tcl_NotifyChannel(rtPtr->chan, TCL_READABLE); } /* *---------------------------------------------------------------------- * * ResultInit -- * * Initializes the specified buffer structure. The structure will contain * valid information for an emtpy buffer. * * Side effects: * See above. * * Result: * None. * *---------------------------------------------------------------------- */ static void ResultInit( ResultBuffer *rPtr) /* Reference to the structure to * initialize. */ { rPtr->used = 0; rPtr->allocated = 0; rPtr->buf = NULL; } /* *---------------------------------------------------------------------- * * ResultClear -- * * Deallocates any memory allocated by 'ResultAdd'. * * Side effects: * See above. * * Result: * None. * *---------------------------------------------------------------------- */ static void ResultClear( ResultBuffer *rPtr) /* Reference to the buffer to clear out */ { rPtr->used = 0; if (!rPtr->allocated) { return; } ckfree((char *) rPtr->buf); rPtr->buf = NULL; rPtr->allocated = 0; } /* *---------------------------------------------------------------------- * * ResultAdd -- * * Adds the bytes in the specified array to the buffer, by appending it. * * Side effects: * See above. * * Result: * None. * *---------------------------------------------------------------------- */ static void ResultAdd( ResultBuffer *rPtr, /* The buffer to extend */ unsigned char *buf, /* The buffer to read from */ int toWrite) /* The number of bytes in 'buf' */ { if ((rPtr->used + toWrite + 1) > rPtr->allocated) { /* * Extension of the internal buffer is required. * NOTE: Currently linear. Should be doubling to amortize. */ if (rPtr->allocated == 0) { rPtr->allocated = toWrite + RB_INCREMENT; rPtr->buf = UCHARP(ckalloc(rPtr->allocated)); } else { rPtr->allocated += toWrite + RB_INCREMENT; rPtr->buf = UCHARP(ckrealloc((char *) rPtr->buf, rPtr->allocated)); } } /* * Now copy data. */ memcpy(rPtr->buf + rPtr->used, buf, toWrite); rPtr->used += toWrite; } /* *---------------------------------------------------------------------- * * ResultCopy -- * * Copies the requested number of bytes from the buffer into the * specified array and removes them from the buffer afterward. Copies * less if there is not enough data in the buffer. * * Side effects: * See above. * * Result: * The number of actually copied bytes, possibly less than 'toRead'. * *---------------------------------------------------------------------- */ static int ResultCopy( ResultBuffer *rPtr, /* The buffer to read from */ unsigned char *buf, /* The buffer to copy into */ int toRead) /* Number of requested bytes */ { int copied; if (rPtr->used == 0) { /* * Nothing to copy in the case of an empty buffer. */ copied = 0; } else if (rPtr->used == toRead) { /* * We have just enough. Copy everything to the caller. */ memcpy(buf, rPtr->buf, toRead); rPtr->used = 0; copied = toRead; } else if (rPtr->used > toRead) { /* * The internal buffer contains more than requested. Copy the * requested subset to the caller, and shift the remaining bytes down. */ memcpy(buf, rPtr->buf, toRead); memmove(rPtr->buf, rPtr->buf + toRead, rPtr->used - toRead); rPtr->used -= toRead; copied = toRead; } else { /* * There is not enough in the buffer to satisfy the caller, so take * everything. */ memcpy(buf, rPtr->buf, rPtr->used); toRead = rPtr->used; rPtr->used = 0; copied = toRead; } /* -- common postwork code ------- */ return copied; } static int TransformRead( ReflectedTransform *rtPtr, int *errorCodePtr, Tcl_Obj *bufObj) { Tcl_Obj *resObj; int bytec; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; p.transform.buf = (char *) Tcl_GetByteArrayFromObj(bufObj, &(p.transform.size)); ForwardOpToOwnerThread(rtPtr, ForwardedInput, &p); if (p.base.code != TCL_OK) { PassReceivedError(rtPtr->chan, &p); *errorCodePtr = EINVAL; return 0; } *errorCodePtr = EOK; ResultAdd(&rtPtr->result, UCHARP(p.transform.buf), p.transform.size); ckfree(p.transform.buf); return 1; } #endif /* TCL_THREADS */ /* ASSERT: rtPtr->method & FLAG(METH_READ) */ /* ASSERT: rtPtr->mode & TCL_READABLE */ if (InvokeTclMethod(rtPtr, "read", bufObj, NULL, &resObj) != TCL_OK) { Tcl_SetChannelError(rtPtr->chan, resObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ *errorCodePtr = EINVAL; return 0; } bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); ResultAdd(&rtPtr->result, bytev, bytec); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ return 1; } static int TransformWrite( ReflectedTransform *rtPtr, int *errorCodePtr, unsigned char *buf, int toWrite) { Tcl_Obj *bufObj; Tcl_Obj *resObj; int bytec; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ int res; /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; p.transform.buf = (char *) buf; p.transform.size = toWrite; ForwardOpToOwnerThread(rtPtr, ForwardedOutput, &p); if (p.base.code != TCL_OK) { PassReceivedError(rtPtr->chan, &p); *errorCodePtr = EINVAL; return 0; } *errorCodePtr = EOK; res = Tcl_WriteRaw(rtPtr->parent, (char *) p.transform.buf, p.transform.size); ckfree(p.transform.buf); } else #endif /* TCL_THREADS */ { /* ASSERT: rtPtr->method & FLAG(METH_WRITE) */ /* ASSERT: rtPtr->mode & TCL_WRITABLE */ bufObj = Tcl_NewByteArrayObj((unsigned char *) buf, toWrite); Tcl_IncrRefCount(bufObj); if (InvokeTclMethod(rtPtr, "write", bufObj, NULL, &resObj) != TCL_OK) { *errorCodePtr = EINVAL; Tcl_SetChannelError(rtPtr->chan, resObj); Tcl_DecrRefCount(bufObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ return 0; } *errorCodePtr = EOK; bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); res = Tcl_WriteRaw(rtPtr->parent, (char *) bytev, bytec); Tcl_DecrRefCount(bufObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ } if (res < 0) { *errorCodePtr = Tcl_GetErrno(); return 0; } return 1; } static int TransformDrain( ReflectedTransform *rtPtr, int *errorCodePtr) { Tcl_Obj *resObj; int bytec; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; ForwardOpToOwnerThread(rtPtr, ForwardedDrain, &p); if (p.base.code != TCL_OK) { PassReceivedError(rtPtr->chan, &p); *errorCodePtr = EINVAL; return 0; } *errorCodePtr = EOK; ResultAdd(&rtPtr->result, UCHARP(p.transform.buf), p.transform.size); ckfree(p.transform.buf); } else #endif /* TCL_THREADS */ { if (InvokeTclMethod(rtPtr, "drain", NULL, NULL, &resObj)!=TCL_OK) { Tcl_SetChannelError(rtPtr->chan, resObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ *errorCodePtr = EINVAL; return 0; } bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); ResultAdd(&rtPtr->result, bytev, bytec); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ } rtPtr->readIsDrained = 1; return 1; } static int TransformFlush( ReflectedTransform *rtPtr, int *errorCodePtr, int op) { Tcl_Obj *resObj; int bytec; /* Number of returned bytes */ unsigned char *bytev; /* Array of returned bytes */ int res; /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; ForwardOpToOwnerThread(rtPtr, ForwardedFlush, &p); if (p.base.code != TCL_OK) { PassReceivedError(rtPtr->chan, &p); *errorCodePtr = EINVAL; return 0; } *errorCodePtr = EOK; if (op == FLUSH_WRITE) { res = Tcl_WriteRaw(rtPtr->parent, (char *) p.transform.buf, p.transform.size); } else { res = 0; } ckfree(p.transform.buf); } else #endif /* TCL_THREADS */ { if (InvokeTclMethod(rtPtr, "flush", NULL, NULL, &resObj)!=TCL_OK) { Tcl_SetChannelError(rtPtr->chan, resObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ *errorCodePtr = EINVAL; return 0; } if (op == FLUSH_WRITE) { bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); res = Tcl_WriteRaw(rtPtr->parent, (char *) bytev, bytec); } else { res = 0; } Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ } if (res < 0) { *errorCodePtr = Tcl_GetErrno(); return 0; } return 1; } static void TransformClear( ReflectedTransform *rtPtr) { /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; ForwardOpToOwnerThread(rtPtr, ForwardedClear, &p); return; } #endif /* TCL_THREADS */ /* ASSERT: rtPtr->method & FLAG(METH_READ) */ /* ASSERT: rtPtr->mode & TCL_READABLE */ (void) InvokeTclMethod(rtPtr, "clear", NULL, NULL, NULL); rtPtr->readIsDrained = 0; rtPtr->eofPending = 0; ResultClear(&rtPtr->result); } static int TransformLimit( ReflectedTransform *rtPtr, int *errorCodePtr, int *maxPtr) { Tcl_Obj *resObj; Tcl_InterpState sr; /* State of handler interp */ /* * Are we in the correct thread? */ #ifdef TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; ForwardOpToOwnerThread(rtPtr, ForwardedLimit, &p); if (p.base.code != TCL_OK) { PassReceivedError(rtPtr->chan, &p); *errorCodePtr = EINVAL; return 0; } *errorCodePtr = EOK; *maxPtr = p.limit.max; return 1; } #endif /* ASSERT: rtPtr->method & FLAG(METH_WRITE) */ /* ASSERT: rtPtr->mode & TCL_WRITABLE */ if (InvokeTclMethod(rtPtr, "limit?", NULL, NULL, &resObj) != TCL_OK) { Tcl_SetChannelError(rtPtr->chan, resObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ *errorCodePtr = EINVAL; return 0; } sr = Tcl_SaveInterpState(rtPtr->interp, 0 /* Dummy */); if (Tcl_GetIntFromObj(rtPtr->interp, resObj, maxPtr) != TCL_OK) { Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ Tcl_SetChannelError(rtPtr->chan, MarshallError(rtPtr->interp)); *errorCodePtr = EINVAL; Tcl_RestoreInterpState(rtPtr->interp, sr); return 0; } Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ Tcl_RestoreInterpState(rtPtr->interp, sr); return 1; } /* DUPLICATE of HaveVersion() in tclIO.c *---------------------------------------------------------------------- * * HaveVersion -- * * Return whether a channel type is (at least) of a given version. * * Results: * True if the minimum version is exceeded by the version actually * present. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int HaveVersion( const Tcl_ChannelType *chanTypePtr, Tcl_ChannelTypeVersion minimumVersion) { Tcl_ChannelTypeVersion actualVersion = Tcl_ChannelVersion(chanTypePtr); return PTR2INT(actualVersion) >= PTR2INT(minimumVersion); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclParse.h0000644000175000017500000000071112663660065015130 0ustar sergeisergei/* * Minimal set of shared macro definitions and declarations so that multiple * source files can make use of the parsing table in tclParse.c */ #define TYPE_NORMAL 0 #define TYPE_SPACE 0x1 #define TYPE_COMMAND_END 0x2 #define TYPE_SUBS 0x4 #define TYPE_QUOTE 0x8 #define TYPE_CLOSE_PAREN 0x10 #define TYPE_CLOSE_BRACK 0x20 #define TYPE_BRACE 0x40 #define CHAR_TYPE(c) (tclCharTypeTable+128)[(int)(c)] MODULE_SCOPE const char tclCharTypeTable[]; tcl8.6.5/generic/regfree.c0000644000175000017500000000420111555560472014763 0ustar sergeisergei/* * regfree - free an RE * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You might think that this could be incorporated into regcomp.c, and that * would be a reasonable idea... except that this is a generic function (with * a generic name), applicable to all compiled REs regardless of the size of * their characters, whereas the stuff in regcomp.c gets compiled once per * character size. */ #include "regguts.h" /* - regfree - free an RE (generic function, punts to RE-specific function) * * Ignoring invocation with NULL is a convenience. */ void regfree( regex_t *re) { if (re == NULL) { return; } (*((struct fns *)re->re_fns)->free)(re); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclPanic.c0000644000175000017500000000753312663660065015114 0ustar sergeisergei/* * tclPanic.c -- * * Source code for the "Tcl_Panic" library procedure for Tcl; individual * applications will probably call Tcl_SetPanicProc() to set an * application-specific panic procedure. * * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #if defined(_WIN32) || defined(__CYGWIN__) MODULE_SCOPE TCL_NORETURN void tclWinDebugPanic(const char *format, ...); #endif /* * The panicProc variable contains a pointer to an application specific panic * procedure. */ #if defined(__CYGWIN__) static TCL_NORETURN Tcl_PanicProc *panicProc = tclWinDebugPanic; #else static TCL_NORETURN1 Tcl_PanicProc *panicProc = NULL; #endif /* *---------------------------------------------------------------------- * * Tcl_SetPanicProc -- * * Replace the default panic behavior with the specified function. * * Results: * None. * * Side effects: * Sets the panicProc variable. * *---------------------------------------------------------------------- */ void Tcl_SetPanicProc( TCL_NORETURN1 Tcl_PanicProc *proc) { #if defined(_WIN32) /* tclWinDebugPanic only installs if there is no panicProc yet. */ if ((proc != tclWinDebugPanic) || (panicProc == NULL)) #elif defined(__CYGWIN__) if (proc == NULL) panicProc = tclWinDebugPanic; else #endif panicProc = proc; } /* *---------------------------------------------------------------------- * * Tcl_PanicVA -- * * Print an error message and kill the process. * * Results: * None. * * Side effects: * The process dies, entering the debugger if possible. * *---------------------------------------------------------------------- */ void Tcl_PanicVA( const char *format, /* Format string, suitable for passing to * fprintf. */ va_list argList) /* Variable argument list. */ { char *arg1, *arg2, *arg3; /* Additional arguments (variable in number) * to pass to fprintf. */ char *arg4, *arg5, *arg6, *arg7, *arg8; arg1 = va_arg(argList, char *); arg2 = va_arg(argList, char *); arg3 = va_arg(argList, char *); arg4 = va_arg(argList, char *); arg5 = va_arg(argList, char *); arg6 = va_arg(argList, char *); arg7 = va_arg(argList, char *); arg8 = va_arg(argList, char *); if (panicProc != NULL) { panicProc(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); #ifdef _WIN32 } else if (IsDebuggerPresent()) { tclWinDebugPanic(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); #endif } else { fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); fprintf(stderr, "\n"); fflush(stderr); #if defined(_WIN32) || defined(__CYGWIN__) # if defined(__GNUC__) __builtin_trap(); # elif defined(_WIN64) __debugbreak(); # elif defined(_MSC_VER) _asm {int 3} # else DebugBreak(); # endif #endif #if defined(_WIN32) ExitProcess(1); #else abort(); #endif } } /* *---------------------------------------------------------------------- * * Tcl_Panic -- * * Print an error message and kill the process. * * Results: * None. * * Side effects: * The process dies, entering the debugger if possible. * *---------------------------------------------------------------------- */ /* ARGSUSED */ /* * The following comment is here so that Coverity's static analizer knows that * a Tcl_Panic() call can never return and avoids lots of false positives. */ /* coverity[+kill] */ void Tcl_Panic( const char *format, ...) { va_list argList; va_start(argList, format); Tcl_PanicVA(format, argList); va_end (argList); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclBinary.c0000644000175000017500000022401212663660065015277 0ustar sergeisergei/* * tclBinary.c -- * * This file contains the implementation of the "binary" Tcl built-in * command and the Tcl binary data object. * * Copyright (c) 1997 by Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tommath.h" #include /* * The following constants are used by GetFormatSpec to indicate various * special conditions in the parsing of a format specifier. */ #define BINARY_ALL -1 /* Use all elements in the argument. */ #define BINARY_NOCOUNT -2 /* No count was specified in format. */ /* * The following flags may be ORed together and returned by GetFormatSpec */ #define BINARY_SIGNED 0 /* Field to be read as signed data */ #define BINARY_UNSIGNED 1 /* Field to be read as unsigned data */ /* * The following defines the maximum number of different (integer) numbers * placed in the object cache by 'binary scan' before it bails out and * switches back to Plan A (creating a new object for each value.) * Theoretically, it would be possible to keep the cache about for the values * that are already in it, but that makes the code slower in practise when * overflow happens, and makes little odds the rest of the time (as measured * on my machine.) It is also slower (on the sample I tried at least) to grow * the cache to hold all items we might want to put in it; presumably the * extra cost of managing the memory for the enlarged table outweighs the * benefit from allocating fewer objects. This is probably because as the * number of objects increases, the likelihood of reuse of any particular one * drops, and there is very little gain from larger maximum cache sizes (the * value below is chosen to allow caching to work in full with conversion of * bytes.) - DKF */ #define BINARY_SCAN_MAX_CACHE 260 /* * Prototypes for local procedures defined in this file: */ static void DupByteArrayInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static int FormatNumber(Tcl_Interp *interp, int type, Tcl_Obj *src, unsigned char **cursorPtr); static void FreeByteArrayInternalRep(Tcl_Obj *objPtr); static int GetFormatSpec(const char **formatPtr, char *cmdPtr, int *countPtr, int *flagsPtr); static Tcl_Obj * ScanNumber(unsigned char *buffer, int type, int flags, Tcl_HashTable **numberCachePtr); static int SetByteArrayFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void UpdateStringOfByteArray(Tcl_Obj *listPtr); static void DeleteScanNumberCache(Tcl_HashTable *numberCachePtr); static int NeedReversing(int format); static void CopyNumber(const void *from, void *to, unsigned length, int type); /* Binary ensemble commands */ static int BinaryFormatCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int BinaryScanCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* Binary encoding sub-ensemble commands */ static int BinaryEncodeHex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int BinaryDecodeHex(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int BinaryEncode64(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int BinaryDecode64(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int BinaryEncodeUu(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int BinaryDecodeUu(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* * The following tables are used by the binary encoders */ static const char HexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; static const char UueDigits[65] = { '`', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', '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', '[', '\\',']', '^', '_', '`' }; static const char B64Digits[65] = { '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', '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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=' }; /* * How to construct the ensembles. */ static const EnsembleImplMap binaryMap[] = { { "format", BinaryFormatCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0 }, { "scan", BinaryScanCmd, TclCompileBasicMin2ArgCmd, NULL, NULL, 0 }, { "encode", NULL, NULL, NULL, NULL, 0 }, { "decode", NULL, NULL, NULL, NULL, 0 }, { NULL, NULL, NULL, NULL, NULL, 0 } }; static const EnsembleImplMap encodeMap[] = { { "hex", BinaryEncodeHex, TclCompileBasic1ArgCmd, NULL, NULL, 0 }, { "uuencode", BinaryEncodeUu, NULL, NULL, NULL, 0 }, { "base64", BinaryEncode64, NULL, NULL, NULL, 0 }, { NULL, NULL, NULL, NULL, NULL, 0 } }; static const EnsembleImplMap decodeMap[] = { { "hex", BinaryDecodeHex, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, { "uuencode", BinaryDecodeUu, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, { "base64", BinaryDecode64, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, { NULL, NULL, NULL, NULL, NULL, 0 } }; /* * The following object type represents an array of bytes. An array of bytes * is not equivalent to an internationalized string. Conceptually, a string is * an array of 16-bit quantities organized as a sequence of properly formed * UTF-8 characters, while a ByteArray is an array of 8-bit quantities. * Accessor functions are provided to convert a ByteArray to a String or a * String to a ByteArray. Two or more consecutive bytes in an array of bytes * may look like a single UTF-8 character if the array is casually treated as * a string. But obtaining the String from a ByteArray is guaranteed to * produced properly formed UTF-8 sequences so that there is a one-to-one map * between bytes and characters. * * Converting a ByteArray to a String proceeds by casting each byte in the * array to a 16-bit quantity, treating that number as a Unicode character, * and storing the UTF-8 version of that Unicode character in the String. For * ByteArrays consisting entirely of values 1..127, the corresponding String * representation is the same as the ByteArray representation. * * Converting a String to a ByteArray proceeds by getting the Unicode * representation of each character in the String, casting it to a byte by * truncating the upper 8 bits, and then storing the byte in the ByteArray. * Converting from ByteArray to String and back to ByteArray is not lossy, but * converting an arbitrary String to a ByteArray may be. */ const Tcl_ObjType tclByteArrayType = { "bytearray", FreeByteArrayInternalRep, DupByteArrayInternalRep, UpdateStringOfByteArray, SetByteArrayFromAny }; /* * The following structure is the internal rep for a ByteArray object. Keeps * track of how much memory has been used and how much has been allocated for * the byte array to enable growing and shrinking of the ByteArray object with * fewer mallocs. */ typedef struct ByteArray { int used; /* The number of bytes used in the byte * array. */ int allocated; /* The amount of space actually allocated * minus 1 byte. */ unsigned char bytes[1]; /* The array of bytes. The actual size of this * field depends on the 'allocated' field * above. */ } ByteArray; #define BYTEARRAY_SIZE(len) \ ((unsigned) (TclOffset(ByteArray, bytes) + (len))) #define GET_BYTEARRAY(objPtr) \ ((ByteArray *) (objPtr)->internalRep.twoPtrValue.ptr1) #define SET_BYTEARRAY(objPtr, baPtr) \ (objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (baPtr) /* *---------------------------------------------------------------------- * * Tcl_NewByteArrayObj -- * * This procedure is creates a new ByteArray object and initializes it * from the given array of bytes. * * Results: * The newly create object is returned. This object will have no initial * string representation. The returned object has a ref count of 0. * * Side effects: * Memory allocated for new object and copy of byte array argument. * *---------------------------------------------------------------------- */ #undef Tcl_NewByteArrayObj Tcl_Obj * Tcl_NewByteArrayObj( const unsigned char *bytes, /* The array of bytes used to initialize the * new object. */ int length) /* Length of the array of bytes, which must be * >= 0. */ { #ifdef TCL_MEM_DEBUG return Tcl_DbNewByteArrayObj(bytes, length, "unknown", 0); #else /* if not TCL_MEM_DEBUG */ Tcl_Obj *objPtr; TclNewObj(objPtr); Tcl_SetByteArrayObj(objPtr, bytes, length); return objPtr; #endif /* TCL_MEM_DEBUG */ } /* *---------------------------------------------------------------------- * * Tcl_DbNewByteArrayObj -- * * This procedure is normally called when debugging: i.e., when * TCL_MEM_DEBUG is defined. It is the same as the Tcl_NewByteArrayObj * above except that it calls Tcl_DbCkalloc directly with the file name * and line number from its caller. This simplifies debugging since then * the [memory active] command will report the correct file name and line * number when reporting objects that haven't been freed. * * When TCL_MEM_DEBUG is not defined, this procedure just returns the * result of calling Tcl_NewByteArrayObj. * * Results: * The newly create object is returned. This object will have no initial * string representation. The returned object has a ref count of 0. * * Side effects: * Memory allocated for new object and copy of byte array argument. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_DbNewByteArrayObj( const unsigned char *bytes, /* The array of bytes used to initialize the * new object. */ int length, /* Length of the array of bytes, which must be * >= 0. */ const char *file, /* The name of the source file calling this * procedure; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ { #ifdef TCL_MEM_DEBUG Tcl_Obj *objPtr; TclDbNewObj(objPtr, file, line); Tcl_SetByteArrayObj(objPtr, bytes, length); return objPtr; #else /* if not TCL_MEM_DEBUG */ return Tcl_NewByteArrayObj(bytes, length); #endif /* TCL_MEM_DEBUG */ } /* *--------------------------------------------------------------------------- * * Tcl_SetByteArrayObj -- * * Modify an object to be a ByteArray object and to have the specified * array of bytes as its value. * * Results: * None. * * Side effects: * The object's old string rep and internal rep is freed. Memory * allocated for copy of byte array argument. * *---------------------------------------------------------------------- */ void Tcl_SetByteArrayObj( Tcl_Obj *objPtr, /* Object to initialize as a ByteArray. */ const unsigned char *bytes, /* The array of bytes to use as the new value. May be NULL even if length > 0. */ int length) /* Length of the array of bytes, which must be >= 0. */ { ByteArray *byteArrayPtr; if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayObj"); } TclFreeIntRep(objPtr); TclInvalidateStringRep(objPtr); if (length < 0) { length = 0; } byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length)); byteArrayPtr->used = length; byteArrayPtr->allocated = length; if ((bytes != NULL) && (length > 0)) { memcpy(byteArrayPtr->bytes, bytes, (size_t) length); } objPtr->typePtr = &tclByteArrayType; SET_BYTEARRAY(objPtr, byteArrayPtr); } /* *---------------------------------------------------------------------- * * Tcl_GetByteArrayFromObj -- * * Attempt to get the array of bytes from the Tcl object. If the object * is not already a ByteArray object, an attempt will be made to convert * it to one. * * Results: * Pointer to array of bytes representing the ByteArray object. * * Side effects: * Frees old internal rep. Allocates memory for new internal rep. * *---------------------------------------------------------------------- */ unsigned char * Tcl_GetByteArrayFromObj( Tcl_Obj *objPtr, /* The ByteArray object. */ int *lengthPtr) /* If non-NULL, filled with length of the * array of bytes in the ByteArray object. */ { ByteArray *baPtr; if (objPtr->typePtr != &tclByteArrayType) { SetByteArrayFromAny(NULL, objPtr); } baPtr = GET_BYTEARRAY(objPtr); if (lengthPtr != NULL) { *lengthPtr = baPtr->used; } return (unsigned char *) baPtr->bytes; } /* *---------------------------------------------------------------------- * * Tcl_SetByteArrayLength -- * * This procedure changes the length of the byte array for this object. * Once the caller has set the length of the array, it is acceptable to * directly modify the bytes in the array up until Tcl_GetStringFromObj() * has been called on this object. * * Results: * The new byte array of the specified length. * * Side effects: * Allocates enough memory for an array of bytes of the requested size. * When growing the array, the old array is copied to the new array; new * bytes are undefined. When shrinking, the old array is truncated to the * specified length. * *---------------------------------------------------------------------- */ unsigned char * Tcl_SetByteArrayLength( Tcl_Obj *objPtr, /* The ByteArray object. */ int length) /* New length for internal byte array. */ { ByteArray *byteArrayPtr; if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength"); } if (objPtr->typePtr != &tclByteArrayType) { SetByteArrayFromAny(NULL, objPtr); } byteArrayPtr = GET_BYTEARRAY(objPtr); if (length > byteArrayPtr->allocated) { byteArrayPtr = ckrealloc(byteArrayPtr, BYTEARRAY_SIZE(length)); byteArrayPtr->allocated = length; SET_BYTEARRAY(objPtr, byteArrayPtr); } TclInvalidateStringRep(objPtr); byteArrayPtr->used = length; return byteArrayPtr->bytes; } /* *---------------------------------------------------------------------- * * SetByteArrayFromAny -- * * Generate the ByteArray internal rep from the string rep. * * Results: * The return value is always TCL_OK. * * Side effects: * A ByteArray object is stored as the internal rep of objPtr. * *---------------------------------------------------------------------- */ static int SetByteArrayFromAny( Tcl_Interp *interp, /* Not used. */ Tcl_Obj *objPtr) /* The object to convert to type ByteArray. */ { int length; const char *src, *srcEnd; unsigned char *dst; ByteArray *byteArrayPtr; Tcl_UniChar ch; if (objPtr->typePtr != &tclByteArrayType) { src = TclGetStringFromObj(objPtr, &length); srcEnd = src + length; byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length)); for (dst = byteArrayPtr->bytes; src < srcEnd; ) { src += Tcl_UtfToUniChar(src, &ch); *dst++ = UCHAR(ch); } byteArrayPtr->used = dst - byteArrayPtr->bytes; byteArrayPtr->allocated = length; TclFreeIntRep(objPtr); objPtr->typePtr = &tclByteArrayType; SET_BYTEARRAY(objPtr, byteArrayPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * FreeByteArrayInternalRep -- * * Deallocate the storage associated with a ByteArray data object's * internal representation. * * Results: * None. * * Side effects: * Frees memory. * *---------------------------------------------------------------------- */ static void FreeByteArrayInternalRep( Tcl_Obj *objPtr) /* Object with internal rep to free. */ { ckfree(GET_BYTEARRAY(objPtr)); objPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * DupByteArrayInternalRep -- * * Initialize the internal representation of a ByteArray Tcl_Obj to a * copy of the internal representation of an existing ByteArray object. * * Results: * None. * * Side effects: * Allocates memory. * *---------------------------------------------------------------------- */ static void DupByteArrayInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { int length; ByteArray *srcArrayPtr, *copyArrayPtr; srcArrayPtr = GET_BYTEARRAY(srcPtr); length = srcArrayPtr->used; copyArrayPtr = ckalloc(BYTEARRAY_SIZE(length)); copyArrayPtr->used = length; copyArrayPtr->allocated = length; memcpy(copyArrayPtr->bytes, srcArrayPtr->bytes, (size_t) length); SET_BYTEARRAY(copyPtr, copyArrayPtr); copyPtr->typePtr = &tclByteArrayType; } /* *---------------------------------------------------------------------- * * UpdateStringOfByteArray -- * * Update the string representation for a ByteArray data object. Note: * This procedure does not invalidate an existing old string rep so * storage will be lost if this has not already been done. * * Results: * None. * * Side effects: * The object's string is set to a valid string that results from the * ByteArray-to-string conversion. * * The object becomes a string object -- the internal rep is discarded * and the typePtr becomes NULL. * *---------------------------------------------------------------------- */ static void UpdateStringOfByteArray( Tcl_Obj *objPtr) /* ByteArray object whose string rep to * update. */ { int i, length, size; unsigned char *src; char *dst; ByteArray *byteArrayPtr; byteArrayPtr = GET_BYTEARRAY(objPtr); src = byteArrayPtr->bytes; length = byteArrayPtr->used; /* * How much space will string rep need? */ size = length; for (i = 0; i < length && size >= 0; i++) { if ((src[i] == 0) || (src[i] > 127)) { size++; } } if (size < 0) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } dst = ckalloc(size + 1); objPtr->bytes = dst; objPtr->length = size; if (size == length) { memcpy(dst, src, (size_t) size); dst[size] = '\0'; } else { for (i = 0; i < length; i++) { dst += Tcl_UniCharToUtf(src[i], dst); } *dst = '\0'; } } /* *---------------------------------------------------------------------- * * TclAppendBytesToByteArray -- * * This function appends an array of bytes to a byte array object. Note * that the object *must* be unshared, and the array of bytes *must not* * refer to the object being appended to. * * Results: * None. * * Side effects: * Allocates enough memory for an array of bytes of the requested total * size, or possibly larger. [Bug 2992970] * *---------------------------------------------------------------------- */ void TclAppendBytesToByteArray( Tcl_Obj *objPtr, const unsigned char *bytes, int len) { ByteArray *byteArrayPtr; int needed; if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object","TclAppendBytesToByteArray"); } if (len < 0) { Tcl_Panic("%s must be called with definite number of bytes to append", "TclAppendBytesToByteArray"); } if (len == 0) { /* Append zero bytes is a no-op. */ return; } if (objPtr->typePtr != &tclByteArrayType) { SetByteArrayFromAny(NULL, objPtr); } byteArrayPtr = GET_BYTEARRAY(objPtr); if (len > INT_MAX - byteArrayPtr->used) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } needed = byteArrayPtr->used + len; /* * If we need to, resize the allocated space in the byte array. */ if (needed > byteArrayPtr->allocated) { ByteArray *ptr = NULL; int attempt; if (needed <= INT_MAX/2) { /* Try to allocate double the total space that is needed. */ attempt = 2 * needed; ptr = attemptckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt)); } if (ptr == NULL) { /* Try to allocate double the increment that is needed (plus). */ unsigned int limit = INT_MAX - needed; unsigned int extra = len + TCL_MIN_GROWTH; int growth = (int) ((extra > limit) ? limit : extra); attempt = needed + growth; ptr = attemptckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt)); } if (ptr == NULL) { /* Last chance: Try to allocate exactly what is needed. */ attempt = needed; ptr = ckrealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt)); } byteArrayPtr = ptr; byteArrayPtr->allocated = attempt; SET_BYTEARRAY(objPtr, byteArrayPtr); } if (bytes) { memcpy(byteArrayPtr->bytes + byteArrayPtr->used, bytes, len); } byteArrayPtr->used += len; TclInvalidateStringRep(objPtr); } /* *---------------------------------------------------------------------- * * TclInitBinaryCmd -- * * This function is called to create the "binary" Tcl command. See the * user documentation for details on what it does. * * Results: * A command token for the new command. * * Side effects: * Creates a new binary command as a mapped ensemble. * *---------------------------------------------------------------------- */ Tcl_Command TclInitBinaryCmd( Tcl_Interp *interp) { Tcl_Command binaryEnsemble; binaryEnsemble = TclMakeEnsemble(interp, "binary", binaryMap); TclMakeEnsemble(interp, "binary encode", encodeMap); TclMakeEnsemble(interp, "binary decode", decodeMap); return binaryEnsemble; } /* *---------------------------------------------------------------------- * * BinaryFormatCmd -- * * This procedure implements the "binary format" Tcl command. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int BinaryFormatCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int arg; /* Index of next argument to consume. */ int value = 0; /* Current integer value to be packed. * Initialized to avoid compiler warning. */ char cmd; /* Current format character. */ int count; /* Count associated with current format * character. */ int flags; /* Format field flags */ const char *format; /* Pointer to current position in format * string. */ Tcl_Obj *resultPtr = NULL; /* Object holding result buffer. */ unsigned char *buffer; /* Start of result buffer. */ unsigned char *cursor; /* Current position within result buffer. */ unsigned char *maxPos; /* Greatest position within result buffer that * cursor has visited.*/ const char *errorString; const char *errorValue, *str; int offset, size, length; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "formatString ?arg ...?"); return TCL_ERROR; } /* * To avoid copying the data, we format the string in two passes. The * first pass computes the size of the output buffer. The second pass * places the formatted data into the buffer. */ format = TclGetString(objv[1]); arg = 2; offset = 0; length = 0; while (*format != '\0') { str = format; flags = 0; if (!GetFormatSpec(&format, &cmd, &count, &flags)) { break; } switch (cmd) { case 'a': case 'A': case 'b': case 'B': case 'h': case 'H': /* * For string-type specifiers, the count corresponds to the number * of bytes in a single argument. */ if (arg >= objc) { goto badIndex; } if (count == BINARY_ALL) { Tcl_GetByteArrayFromObj(objv[arg], &count); } else if (count == BINARY_NOCOUNT) { count = 1; } arg++; if (cmd == 'a' || cmd == 'A') { offset += count; } else if (cmd == 'b' || cmd == 'B') { offset += (count + 7) / 8; } else { offset += (count + 1) / 2; } break; case 'c': size = 1; goto doNumbers; case 't': case 's': case 'S': size = 2; goto doNumbers; case 'n': case 'i': case 'I': size = 4; goto doNumbers; case 'm': case 'w': case 'W': size = 8; goto doNumbers; case 'r': case 'R': case 'f': size = sizeof(float); goto doNumbers; case 'q': case 'Q': case 'd': size = sizeof(double); doNumbers: if (arg >= objc) { goto badIndex; } /* * For number-type specifiers, the count corresponds to the number * of elements in the list stored in a single argument. If no * count is specified, then the argument is taken as a single * non-list value. */ if (count == BINARY_NOCOUNT) { arg++; count = 1; } else { int listc; Tcl_Obj **listv; /* * The macro evals its args more than once: avoid arg++ */ if (TclListObjGetElements(interp, objv[arg], &listc, &listv) != TCL_OK) { return TCL_ERROR; } arg++; if (count == BINARY_ALL) { count = listc; } else if (count > listc) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "number of elements in list does not match count", -1)); return TCL_ERROR; } } offset += count*size; break; case 'x': if (count == BINARY_ALL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot use \"*\" in format string with \"x\"", -1)); return TCL_ERROR; } else if (count == BINARY_NOCOUNT) { count = 1; } offset += count; break; case 'X': if (count == BINARY_NOCOUNT) { count = 1; } if ((count > offset) || (count == BINARY_ALL)) { count = offset; } if (offset > length) { length = offset; } offset -= count; break; case '@': if (offset > length) { length = offset; } if (count == BINARY_ALL) { offset = length; } else if (count == BINARY_NOCOUNT) { goto badCount; } else { offset = count; } break; default: errorString = str; goto badField; } } if (offset > length) { length = offset; } if (length == 0) { return TCL_OK; } /* * Prepare the result object by preallocating the caclulated number of * bytes and filling with nulls. */ resultPtr = Tcl_NewObj(); buffer = Tcl_SetByteArrayLength(resultPtr, length); memset(buffer, 0, (size_t) length); /* * Pack the data into the result object. Note that we can skip the * error checking during this pass, since we have already parsed the * string once. */ arg = 2; format = TclGetString(objv[1]); cursor = buffer; maxPos = cursor; while (*format != 0) { flags = 0; if (!GetFormatSpec(&format, &cmd, &count, &flags)) { break; } if ((count == 0) && (cmd != '@')) { if (cmd != 'x') { arg++; } continue; } switch (cmd) { case 'a': case 'A': { char pad = (char) (cmd == 'a' ? '\0' : ' '); unsigned char *bytes; bytes = Tcl_GetByteArrayFromObj(objv[arg++], &length); if (count == BINARY_ALL) { count = length; } else if (count == BINARY_NOCOUNT) { count = 1; } if (length >= count) { memcpy(cursor, bytes, (size_t) count); } else { memcpy(cursor, bytes, (size_t) length); memset(cursor + length, pad, (size_t) (count - length)); } cursor += count; break; } case 'b': case 'B': { unsigned char *last; str = TclGetStringFromObj(objv[arg], &length); arg++; if (count == BINARY_ALL) { count = length; } else if (count == BINARY_NOCOUNT) { count = 1; } last = cursor + ((count + 7) / 8); if (count > length) { count = length; } value = 0; errorString = "binary"; if (cmd == 'B') { for (offset = 0; offset < count; offset++) { value <<= 1; if (str[offset] == '1') { value |= 1; } else if (str[offset] != '0') { errorValue = str; Tcl_DecrRefCount(resultPtr); goto badValue; } if (((offset + 1) % 8) == 0) { *cursor++ = UCHAR(value); value = 0; } } } else { for (offset = 0; offset < count; offset++) { value >>= 1; if (str[offset] == '1') { value |= 128; } else if (str[offset] != '0') { errorValue = str; Tcl_DecrRefCount(resultPtr); goto badValue; } if (!((offset + 1) % 8)) { *cursor++ = UCHAR(value); value = 0; } } } if ((offset % 8) != 0) { if (cmd == 'B') { value <<= 8 - (offset % 8); } else { value >>= 8 - (offset % 8); } *cursor++ = UCHAR(value); } while (cursor < last) { *cursor++ = '\0'; } break; } case 'h': case 'H': { unsigned char *last; int c; str = TclGetStringFromObj(objv[arg], &length); arg++; if (count == BINARY_ALL) { count = length; } else if (count == BINARY_NOCOUNT) { count = 1; } last = cursor + ((count + 1) / 2); if (count > length) { count = length; } value = 0; errorString = "hexadecimal"; if (cmd == 'H') { for (offset = 0; offset < count; offset++) { value <<= 4; if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */ errorValue = str; Tcl_DecrRefCount(resultPtr); goto badValue; } c = str[offset] - '0'; if (c > 9) { c += ('0' - 'A') + 10; } if (c > 16) { c += ('A' - 'a'); } value |= (c & 0xf); if (offset % 2) { *cursor++ = (char) value; value = 0; } } } else { for (offset = 0; offset < count; offset++) { value >>= 4; if (!isxdigit(UCHAR(str[offset]))) { /* INTL: digit */ errorValue = str; Tcl_DecrRefCount(resultPtr); goto badValue; } c = str[offset] - '0'; if (c > 9) { c += ('0' - 'A') + 10; } if (c > 16) { c += ('A' - 'a'); } value |= ((c << 4) & 0xf0); if (offset % 2) { *cursor++ = UCHAR(value & 0xff); value = 0; } } } if (offset % 2) { if (cmd == 'H') { value <<= 4; } else { value >>= 4; } *cursor++ = UCHAR(value); } while (cursor < last) { *cursor++ = '\0'; } break; } case 'c': case 't': case 's': case 'S': case 'n': case 'i': case 'I': case 'm': case 'w': case 'W': case 'r': case 'R': case 'd': case 'q': case 'Q': case 'f': { int listc, i; Tcl_Obj **listv; if (count == BINARY_NOCOUNT) { /* * Note that we are casting away the const-ness of objv, but * this is safe since we aren't going to modify the array. */ listv = (Tcl_Obj **) (objv + arg); listc = 1; count = 1; } else { TclListObjGetElements(interp, objv[arg], &listc, &listv); if (count == BINARY_ALL) { count = listc; } } arg++; for (i = 0; i < count; i++) { if (FormatNumber(interp, cmd, listv[i], &cursor)!=TCL_OK) { Tcl_DecrRefCount(resultPtr); return TCL_ERROR; } } break; } case 'x': if (count == BINARY_NOCOUNT) { count = 1; } memset(cursor, 0, (size_t) count); cursor += count; break; case 'X': if (cursor > maxPos) { maxPos = cursor; } if (count == BINARY_NOCOUNT) { count = 1; } if ((count == BINARY_ALL) || (count > (cursor - buffer))) { cursor = buffer; } else { cursor -= count; } break; case '@': if (cursor > maxPos) { maxPos = cursor; } if (count == BINARY_ALL) { cursor = maxPos; } else { cursor = buffer + count; } break; } } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; badValue: Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected %s string but got \"%s\" instead", errorString, errorValue)); return TCL_ERROR; badCount: errorString = "missing count for \"@\" field specifier"; goto error; badIndex: errorString = "not enough arguments for all format specifiers"; goto error; badField: { Tcl_UniChar ch; char buf[TCL_UTF_MAX + 1]; Tcl_UtfToUniChar(errorString, &ch); buf[Tcl_UniCharToUtf(ch, buf)] = '\0'; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad field specifier \"%s\"", buf)); return TCL_ERROR; } error: Tcl_SetObjResult(interp, Tcl_NewStringObj(errorString, -1)); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * BinaryScanCmd -- * * This procedure implements the "binary scan" Tcl command. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int BinaryScanCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int arg; /* Index of next argument to consume. */ int value = 0; /* Current integer value to be packed. * Initialized to avoid compiler warning. */ char cmd; /* Current format character. */ int count; /* Count associated with current format * character. */ int flags; /* Format field flags */ const char *format; /* Pointer to current position in format * string. */ Tcl_Obj *resultPtr = NULL; /* Object holding result buffer. */ unsigned char *buffer; /* Start of result buffer. */ const char *errorString; const char *str; int offset, size, length; int i; Tcl_Obj *valuePtr, *elementPtr; Tcl_HashTable numberCacheHash; Tcl_HashTable *numberCachePtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "value formatString ?varName ...?"); return TCL_ERROR; } numberCachePtr = &numberCacheHash; Tcl_InitHashTable(numberCachePtr, TCL_ONE_WORD_KEYS); buffer = Tcl_GetByteArrayFromObj(objv[1], &length); format = TclGetString(objv[2]); arg = 3; offset = 0; while (*format != '\0') { str = format; flags = 0; if (!GetFormatSpec(&format, &cmd, &count, &flags)) { goto done; } switch (cmd) { case 'a': case 'A': { unsigned char *src; if (arg >= objc) { DeleteScanNumberCache(numberCachePtr); goto badIndex; } if (count == BINARY_ALL) { count = length - offset; } else { if (count == BINARY_NOCOUNT) { count = 1; } if (count > (length - offset)) { goto done; } } src = buffer + offset; size = count; /* * Trim trailing nulls and spaces, if necessary. */ if (cmd == 'A') { while (size > 0) { if (src[size-1] != '\0' && src[size-1] != ' ') { break; } size--; } } /* * Have to do this #ifdef-fery because (as part of defining * Tcl_NewByteArrayObj) we removed the #def that hides this stuff * normally. If this code ever gets copied to another file, it * should be changed back to the simpler version. */ #ifdef TCL_MEM_DEBUG valuePtr = Tcl_DbNewByteArrayObj(src, size, __FILE__, __LINE__); #else valuePtr = Tcl_NewByteArrayObj(src, size); #endif /* TCL_MEM_DEBUG */ resultPtr = Tcl_ObjSetVar2(interp, objv[arg], NULL, valuePtr, TCL_LEAVE_ERR_MSG); arg++; if (resultPtr == NULL) { DeleteScanNumberCache(numberCachePtr); return TCL_ERROR; } offset += count; break; } case 'b': case 'B': { unsigned char *src; char *dest; if (arg >= objc) { DeleteScanNumberCache(numberCachePtr); goto badIndex; } if (count == BINARY_ALL) { count = (length - offset) * 8; } else { if (count == BINARY_NOCOUNT) { count = 1; } if (count > (length - offset) * 8) { goto done; } } src = buffer + offset; valuePtr = Tcl_NewObj(); Tcl_SetObjLength(valuePtr, count); dest = TclGetString(valuePtr); if (cmd == 'b') { for (i = 0; i < count; i++) { if (i % 8) { value >>= 1; } else { value = *src++; } *dest++ = (char) ((value & 1) ? '1' : '0'); } } else { for (i = 0; i < count; i++) { if (i % 8) { value <<= 1; } else { value = *src++; } *dest++ = (char) ((value & 0x80) ? '1' : '0'); } } resultPtr = Tcl_ObjSetVar2(interp, objv[arg], NULL, valuePtr, TCL_LEAVE_ERR_MSG); arg++; if (resultPtr == NULL) { DeleteScanNumberCache(numberCachePtr); return TCL_ERROR; } offset += (count + 7) / 8; break; } case 'h': case 'H': { char *dest; unsigned char *src; static const char hexdigit[] = "0123456789abcdef"; if (arg >= objc) { DeleteScanNumberCache(numberCachePtr); goto badIndex; } if (count == BINARY_ALL) { count = (length - offset)*2; } else { if (count == BINARY_NOCOUNT) { count = 1; } if (count > (length - offset)*2) { goto done; } } src = buffer + offset; valuePtr = Tcl_NewObj(); Tcl_SetObjLength(valuePtr, count); dest = TclGetString(valuePtr); if (cmd == 'h') { for (i = 0; i < count; i++) { if (i % 2) { value >>= 4; } else { value = *src++; } *dest++ = hexdigit[value & 0xf]; } } else { for (i = 0; i < count; i++) { if (i % 2) { value <<= 4; } else { value = *src++; } *dest++ = hexdigit[(value >> 4) & 0xf]; } } resultPtr = Tcl_ObjSetVar2(interp, objv[arg], NULL, valuePtr, TCL_LEAVE_ERR_MSG); arg++; if (resultPtr == NULL) { DeleteScanNumberCache(numberCachePtr); return TCL_ERROR; } offset += (count + 1) / 2; break; } case 'c': size = 1; goto scanNumber; case 't': case 's': case 'S': size = 2; goto scanNumber; case 'n': case 'i': case 'I': size = 4; goto scanNumber; case 'm': case 'w': case 'W': size = 8; goto scanNumber; case 'r': case 'R': case 'f': size = sizeof(float); goto scanNumber; case 'q': case 'Q': case 'd': { unsigned char *src; size = sizeof(double); /* fall through */ scanNumber: if (arg >= objc) { DeleteScanNumberCache(numberCachePtr); goto badIndex; } if (count == BINARY_NOCOUNT) { if ((length - offset) < size) { goto done; } valuePtr = ScanNumber(buffer+offset, cmd, flags, &numberCachePtr); offset += size; } else { if (count == BINARY_ALL) { count = (length - offset) / size; } if ((length - offset) < (count * size)) { goto done; } valuePtr = Tcl_NewObj(); src = buffer + offset; for (i = 0; i < count; i++) { elementPtr = ScanNumber(src, cmd, flags, &numberCachePtr); src += size; Tcl_ListObjAppendElement(NULL, valuePtr, elementPtr); } offset += count * size; } resultPtr = Tcl_ObjSetVar2(interp, objv[arg], NULL, valuePtr, TCL_LEAVE_ERR_MSG); arg++; if (resultPtr == NULL) { DeleteScanNumberCache(numberCachePtr); return TCL_ERROR; } break; } case 'x': if (count == BINARY_NOCOUNT) { count = 1; } if ((count == BINARY_ALL) || (count > (length - offset))) { offset = length; } else { offset += count; } break; case 'X': if (count == BINARY_NOCOUNT) { count = 1; } if ((count == BINARY_ALL) || (count > offset)) { offset = 0; } else { offset -= count; } break; case '@': if (count == BINARY_NOCOUNT) { DeleteScanNumberCache(numberCachePtr); goto badCount; } if ((count == BINARY_ALL) || (count > length)) { offset = length; } else { offset = count; } break; default: DeleteScanNumberCache(numberCachePtr); errorString = str; goto badField; } } /* * Set the result to the last position of the cursor. */ done: Tcl_SetObjResult(interp, Tcl_NewLongObj(arg - 3)); DeleteScanNumberCache(numberCachePtr); return TCL_OK; badCount: errorString = "missing count for \"@\" field specifier"; goto error; badIndex: errorString = "not enough arguments for all format specifiers"; goto error; badField: { Tcl_UniChar ch; char buf[TCL_UTF_MAX + 1]; Tcl_UtfToUniChar(errorString, &ch); buf[Tcl_UniCharToUtf(ch, buf)] = '\0'; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad field specifier \"%s\"", buf)); return TCL_ERROR; } error: Tcl_SetObjResult(interp, Tcl_NewStringObj(errorString, -1)); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * GetFormatSpec -- * * This function parses the format strings used in the binary format and * scan commands. * * Results: * Moves the formatPtr to the start of the next command. Returns the * current command character and count in cmdPtr and countPtr. The count * is set to BINARY_ALL if the count character was '*' or BINARY_NOCOUNT * if no count was specified. Returns 1 on success, or 0 if the string * did not have a format specifier. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int GetFormatSpec( const char **formatPtr, /* Pointer to format string. */ char *cmdPtr, /* Pointer to location of command char. */ int *countPtr, /* Pointer to repeat count value. */ int *flagsPtr) /* Pointer to field flags */ { /* * Skip any leading blanks. */ while (**formatPtr == ' ') { (*formatPtr)++; } /* * The string was empty, except for whitespace, so fail. */ if (!(**formatPtr)) { return 0; } /* * Extract the command character and any trailing digits or '*'. */ *cmdPtr = **formatPtr; (*formatPtr)++; if (**formatPtr == 'u') { (*formatPtr)++; *flagsPtr |= BINARY_UNSIGNED; } if (**formatPtr == '*') { (*formatPtr)++; *countPtr = BINARY_ALL; } else if (isdigit(UCHAR(**formatPtr))) { /* INTL: digit */ *countPtr = strtoul(*formatPtr, (char **) formatPtr, 10); } else { *countPtr = BINARY_NOCOUNT; } return 1; } /* *---------------------------------------------------------------------- * * NeedReversing -- * * This routine determines, if bytes of a number need to be re-ordered, * and returns a numeric code indicating the re-ordering to be done. * This depends on the endiannes of the machine and the desired format. * It is in effect a table (whose contents depend on the endianness of * the system) describing whether a value needs reversing or not. Anyone * porting the code to a big-endian platform should take care to make * sure that they define WORDS_BIGENDIAN though this is already done by * configure for the Unix build; little-endian platforms (including * Windows) don't need to do anything. * * Results: * 0 No re-ordering needed. * 1 Reverse the bytes: 01234567 <-> 76543210 (little to big) * 2 Apply this re-ordering: 01234567 <-> 45670123 (Nokia to little) * 3 Apply this re-ordering: 01234567 <-> 32107654 (Nokia to big) * * Side effects: * None * *---------------------------------------------------------------------- */ static int NeedReversing( int format) { switch (format) { /* native floats and doubles: never reverse */ case 'd': case 'f': /* big endian ints: never reverse */ case 'I': case 'S': case 'W': #ifdef WORDS_BIGENDIAN /* native ints: reverse if we're little-endian */ case 'n': case 't': case 'm': /* f: reverse if we're little-endian */ case 'Q': case 'R': #else /* !WORDS_BIGENDIAN */ /* small endian floats: reverse if we're big-endian */ case 'r': #endif /* WORDS_BIGENDIAN */ return 0; #ifdef WORDS_BIGENDIAN /* small endian floats: reverse if we're big-endian */ case 'q': case 'r': #else /* !WORDS_BIGENDIAN */ /* native ints: reverse if we're little-endian */ case 'n': case 't': case 'm': /* f: reverse if we're little-endian */ case 'R': #endif /* WORDS_BIGENDIAN */ /* small endian ints: always reverse */ case 'i': case 's': case 'w': return 1; #ifndef WORDS_BIGENDIAN /* * The Q and q formats need special handling to account for the unusual * byte ordering of 8-byte floats on Nokia 770 systems, which claim to be * little-endian, but also reverse word order. */ case 'Q': if (TclNokia770Doubles()) { return 3; } return 1; case 'q': if (TclNokia770Doubles()) { return 2; } return 0; #endif } Tcl_Panic("unexpected fallthrough"); return 0; } /* *---------------------------------------------------------------------- * * CopyNumber -- * * This routine is called by FormatNumber and ScanNumber to copy a * floating-point number. If required, bytes are reversed while copying. * The behaviour is only fully defined when used with IEEE float and * double values (guaranteed to be 4 and 8 bytes long, respectively.) * * Results: * None * * Side effects: * Copies length bytes * *---------------------------------------------------------------------- */ static void CopyNumber( const void *from, /* source */ void *to, /* destination */ unsigned length, /* Number of bytes to copy */ int type) /* What type of thing are we copying? */ { switch (NeedReversing(type)) { case 0: memcpy(to, from, length); break; case 1: { const unsigned char *fromPtr = from; unsigned char *toPtr = to; switch (length) { case 4: toPtr[0] = fromPtr[3]; toPtr[1] = fromPtr[2]; toPtr[2] = fromPtr[1]; toPtr[3] = fromPtr[0]; break; case 8: toPtr[0] = fromPtr[7]; toPtr[1] = fromPtr[6]; toPtr[2] = fromPtr[5]; toPtr[3] = fromPtr[4]; toPtr[4] = fromPtr[3]; toPtr[5] = fromPtr[2]; toPtr[6] = fromPtr[1]; toPtr[7] = fromPtr[0]; break; } break; } case 2: { const unsigned char *fromPtr = from; unsigned char *toPtr = to; toPtr[0] = fromPtr[4]; toPtr[1] = fromPtr[5]; toPtr[2] = fromPtr[6]; toPtr[3] = fromPtr[7]; toPtr[4] = fromPtr[0]; toPtr[5] = fromPtr[1]; toPtr[6] = fromPtr[2]; toPtr[7] = fromPtr[3]; break; } case 3: { const unsigned char *fromPtr = from; unsigned char *toPtr = to; toPtr[0] = fromPtr[3]; toPtr[1] = fromPtr[2]; toPtr[2] = fromPtr[1]; toPtr[3] = fromPtr[0]; toPtr[4] = fromPtr[7]; toPtr[5] = fromPtr[6]; toPtr[6] = fromPtr[5]; toPtr[7] = fromPtr[4]; break; } } } /* *---------------------------------------------------------------------- * * FormatNumber -- * * This routine is called by Tcl_BinaryObjCmd to format a number into a * location pointed at by cursor. * * Results: * A standard Tcl result. * * Side effects: * Moves the cursor to the next location to be written into. * *---------------------------------------------------------------------- */ static int FormatNumber( Tcl_Interp *interp, /* Current interpreter, used to report * errors. */ int type, /* Type of number to format. */ Tcl_Obj *src, /* Number to format. */ unsigned char **cursorPtr) /* Pointer to index into destination buffer. */ { long value; double dvalue; Tcl_WideInt wvalue; float fvalue; switch (type) { case 'd': case 'q': case 'Q': /* * Double-precision floating point values. Tcl_GetDoubleFromObj * returns TCL_ERROR for NaN, but we can check by comparing the * object's type pointer. */ if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) { if (src->typePtr != &tclDoubleType) { return TCL_ERROR; } dvalue = src->internalRep.doubleValue; } CopyNumber(&dvalue, *cursorPtr, sizeof(double), type); *cursorPtr += sizeof(double); return TCL_OK; case 'f': case 'r': case 'R': /* * Single-precision floating point values. Tcl_GetDoubleFromObj * returns TCL_ERROR for NaN, but we can check by comparing the * object's type pointer. */ if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) { if (src->typePtr != &tclDoubleType) { return TCL_ERROR; } dvalue = src->internalRep.doubleValue; } /* * Because some compilers will generate floating point exceptions on * an overflow cast (e.g. Borland), we restrict the values to the * valid range for float. */ if (fabs(dvalue) > (double)FLT_MAX) { fvalue = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX; } else { fvalue = (float) dvalue; } CopyNumber(&fvalue, *cursorPtr, sizeof(float), type); *cursorPtr += sizeof(float); return TCL_OK; /* * 64-bit integer values. */ case 'w': case 'W': case 'm': if (Tcl_GetWideIntFromObj(interp, src, &wvalue) != TCL_OK) { return TCL_ERROR; } if (NeedReversing(type)) { *(*cursorPtr)++ = UCHAR(wvalue); *(*cursorPtr)++ = UCHAR(wvalue >> 8); *(*cursorPtr)++ = UCHAR(wvalue >> 16); *(*cursorPtr)++ = UCHAR(wvalue >> 24); *(*cursorPtr)++ = UCHAR(wvalue >> 32); *(*cursorPtr)++ = UCHAR(wvalue >> 40); *(*cursorPtr)++ = UCHAR(wvalue >> 48); *(*cursorPtr)++ = UCHAR(wvalue >> 56); } else { *(*cursorPtr)++ = UCHAR(wvalue >> 56); *(*cursorPtr)++ = UCHAR(wvalue >> 48); *(*cursorPtr)++ = UCHAR(wvalue >> 40); *(*cursorPtr)++ = UCHAR(wvalue >> 32); *(*cursorPtr)++ = UCHAR(wvalue >> 24); *(*cursorPtr)++ = UCHAR(wvalue >> 16); *(*cursorPtr)++ = UCHAR(wvalue >> 8); *(*cursorPtr)++ = UCHAR(wvalue); } return TCL_OK; /* * 32-bit integer values. */ case 'i': case 'I': case 'n': if (TclGetLongFromObj(interp, src, &value) != TCL_OK) { return TCL_ERROR; } if (NeedReversing(type)) { *(*cursorPtr)++ = UCHAR(value); *(*cursorPtr)++ = UCHAR(value >> 8); *(*cursorPtr)++ = UCHAR(value >> 16); *(*cursorPtr)++ = UCHAR(value >> 24); } else { *(*cursorPtr)++ = UCHAR(value >> 24); *(*cursorPtr)++ = UCHAR(value >> 16); *(*cursorPtr)++ = UCHAR(value >> 8); *(*cursorPtr)++ = UCHAR(value); } return TCL_OK; /* * 16-bit integer values. */ case 's': case 'S': case 't': if (TclGetLongFromObj(interp, src, &value) != TCL_OK) { return TCL_ERROR; } if (NeedReversing(type)) { *(*cursorPtr)++ = UCHAR(value); *(*cursorPtr)++ = UCHAR(value >> 8); } else { *(*cursorPtr)++ = UCHAR(value >> 8); *(*cursorPtr)++ = UCHAR(value); } return TCL_OK; /* * 8-bit integer values. */ case 'c': if (TclGetLongFromObj(interp, src, &value) != TCL_OK) { return TCL_ERROR; } *(*cursorPtr)++ = UCHAR(value); return TCL_OK; default: Tcl_Panic("unexpected fallthrough"); return TCL_ERROR; } } /* *---------------------------------------------------------------------- * * ScanNumber -- * * This routine is called by Tcl_BinaryObjCmd to scan a number out of a * buffer. * * Results: * Returns a newly created object containing the scanned number. This * object has a ref count of zero. * * Side effects: * Might reuse an object in the number cache, place a new object in the * cache, or delete the cache and set the reference to it (itself passed * in by reference) to NULL. * *---------------------------------------------------------------------- */ static Tcl_Obj * ScanNumber( unsigned char *buffer, /* Buffer to scan number from. */ int type, /* Format character from "binary scan" */ int flags, /* Format field flags */ Tcl_HashTable **numberCachePtrPtr) /* Place to look for cache of scanned * value objects, or NULL if too many * different numbers have been scanned. */ { long value; float fvalue; double dvalue; Tcl_WideUInt uwvalue; /* * We cannot rely on the compiler to properly sign extend integer values * when we cast from smaller values to larger values because we don't know * the exact size of the integer types. So, we have to handle sign * extension explicitly by checking the high bit and padding with 1's as * needed. This practice is disabled if the BINARY_UNSIGNED flag is set. */ switch (type) { case 'c': /* * Characters need special handling. We want to produce a signed * result, but on some platforms (such as AIX) chars are unsigned. To * deal with this, check for a value that should be negative but * isn't. */ value = buffer[0]; if (!(flags & BINARY_UNSIGNED)) { if (value & 0x80) { value |= -0x100; } } goto returnNumericObject; /* * 16-bit numeric values. We need the sign extension trick (see above) * here as well. */ case 's': case 'S': case 't': if (NeedReversing(type)) { value = (long) (buffer[0] + (buffer[1] << 8)); } else { value = (long) (buffer[1] + (buffer[0] << 8)); } if (!(flags & BINARY_UNSIGNED)) { if (value & 0x8000) { value |= -0x10000; } } goto returnNumericObject; /* * 32-bit numeric values. */ case 'i': case 'I': case 'n': if (NeedReversing(type)) { value = (long) (buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) + (((long)buffer[3]) << 24)); } else { value = (long) (buffer[3] + (buffer[2] << 8) + (buffer[1] << 16) + (((long) buffer[0]) << 24)); } /* * Check to see if the value was sign extended properly on systems * where an int is more than 32-bits. * We avoid caching unsigned integers as we cannot distinguish between * 32bit signed and unsigned in the hash (short and char are ok). */ if (flags & BINARY_UNSIGNED) { return Tcl_NewWideIntObj((Tcl_WideInt)(unsigned long)value); } if ((value & (((unsigned) 1)<<31)) && (value > 0)) { value -= (((unsigned) 1)<<31); value -= (((unsigned) 1)<<31); } returnNumericObject: if (*numberCachePtrPtr == NULL) { return Tcl_NewLongObj(value); } else { register Tcl_HashTable *tablePtr = *numberCachePtrPtr; register Tcl_HashEntry *hPtr; int isNew; hPtr = Tcl_CreateHashEntry(tablePtr, INT2PTR(value), &isNew); if (!isNew) { return Tcl_GetHashValue(hPtr); } if (tablePtr->numEntries <= BINARY_SCAN_MAX_CACHE) { register Tcl_Obj *objPtr = Tcl_NewLongObj(value); Tcl_IncrRefCount(objPtr); Tcl_SetHashValue(hPtr, objPtr); return objPtr; } /* * We've overflowed the cache! Someone's parsing a LOT of varied * binary data in a single call! Bail out by switching back to the * old behaviour for the rest of the scan. * * Note that anyone just using the 'c' conversion (for bytes) * cannot trigger this. */ DeleteScanNumberCache(tablePtr); *numberCachePtrPtr = NULL; return Tcl_NewLongObj(value); } /* * Do not cache wide (64-bit) values; they are already too large to * use as keys. */ case 'w': case 'W': case 'm': if (NeedReversing(type)) { uwvalue = ((Tcl_WideUInt) buffer[0]) | (((Tcl_WideUInt) buffer[1]) << 8) | (((Tcl_WideUInt) buffer[2]) << 16) | (((Tcl_WideUInt) buffer[3]) << 24) | (((Tcl_WideUInt) buffer[4]) << 32) | (((Tcl_WideUInt) buffer[5]) << 40) | (((Tcl_WideUInt) buffer[6]) << 48) | (((Tcl_WideUInt) buffer[7]) << 56); } else { uwvalue = ((Tcl_WideUInt) buffer[7]) | (((Tcl_WideUInt) buffer[6]) << 8) | (((Tcl_WideUInt) buffer[5]) << 16) | (((Tcl_WideUInt) buffer[4]) << 24) | (((Tcl_WideUInt) buffer[3]) << 32) | (((Tcl_WideUInt) buffer[2]) << 40) | (((Tcl_WideUInt) buffer[1]) << 48) | (((Tcl_WideUInt) buffer[0]) << 56); } if (flags & BINARY_UNSIGNED) { Tcl_Obj *bigObj = NULL; mp_int big; TclBNInitBignumFromWideUInt(&big, uwvalue); bigObj = Tcl_NewBignumObj(&big); return bigObj; } return Tcl_NewWideIntObj((Tcl_WideInt) uwvalue); /* * Do not cache double values; they are already too large to use as * keys and the values stored are utterly incompatible with the * integer part of the cache. */ /* * 32-bit IEEE single-precision floating point. */ case 'f': case 'R': case 'r': CopyNumber(buffer, &fvalue, sizeof(float), type); return Tcl_NewDoubleObj(fvalue); /* * 64-bit IEEE double-precision floating point. */ case 'd': case 'Q': case 'q': CopyNumber(buffer, &dvalue, sizeof(double), type); return Tcl_NewDoubleObj(dvalue); } return NULL; } /* *---------------------------------------------------------------------- * * DeleteScanNumberCache -- * * Deletes the hash table acting as a scan number cache. * * Results: * None * * Side effects: * Decrements the reference counts of the objects in the cache. * *---------------------------------------------------------------------- */ static void DeleteScanNumberCache( Tcl_HashTable *numberCachePtr) /* Pointer to the hash table, or NULL (when * the cache has already been deleted due to * overflow.) */ { Tcl_HashEntry *hEntry; Tcl_HashSearch search; if (numberCachePtr == NULL) { return; } hEntry = Tcl_FirstHashEntry(numberCachePtr, &search); while (hEntry != NULL) { register Tcl_Obj *value = Tcl_GetHashValue(hEntry); if (value != NULL) { Tcl_DecrRefCount(value); } hEntry = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(numberCachePtr); } /* * ---------------------------------------------------------------------- * * NOTES -- * * Some measurements show that it is faster to use a table to to perform * uuencode and base64 value encoding than to calculate the output (at * least on intel P4 arch). * * Conversely using a lookup table for the decoding is slower than just * calculating the values. We therefore use the fastest of each method. * * Presumably this has to do with the size of the tables. The base64 * decode table is 255 bytes while the encode table is only 65 bytes. The * choice likely depends on CPU memory cache sizes. */ /* *---------------------------------------------------------------------- * * BinaryEncodeHex -- * * Implement the [binary encode hex] binary encoding. clientData must be * a table to convert values to hexadecimal digits. * * Results: * Interp result set to an encoded byte array object * * Side effects: * None * *---------------------------------------------------------------------- */ static int BinaryEncodeHex( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultObj = NULL; unsigned char *data = NULL; unsigned char *cursor = NULL; int offset = 0, count = 0; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "data"); return TCL_ERROR; } TclNewObj(resultObj); data = Tcl_GetByteArrayFromObj(objv[1], &count); cursor = Tcl_SetByteArrayLength(resultObj, count * 2); for (offset = 0; offset < count; ++offset) { *cursor++ = HexDigits[((data[offset] >> 4) & 0x0f)]; *cursor++ = HexDigits[(data[offset] & 0x0f)]; } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* *---------------------------------------------------------------------- * * BinaryDecodeHex -- * * Implement the [binary decode hex] binary encoding. * * Results: * Interp result set to an decoded byte array object * * Side effects: * None * *---------------------------------------------------------------------- */ static int BinaryDecodeHex( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultObj = NULL; unsigned char *data, *datastart, *dataend; unsigned char *begin, *cursor, c; int i, index, value, size, count = 0, cut = 0, strict = 0; enum {OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? data"); return TCL_ERROR; } for (i = 1; i < objc-1; ++i) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case OPT_STRICT: strict = 1; break; } } TclNewObj(resultObj); datastart = data = (unsigned char *) TclGetStringFromObj(objv[objc-1], &count); dataend = data + count; size = (count + 1) / 2; begin = cursor = Tcl_SetByteArrayLength(resultObj, size); while (data < dataend) { value = 0; for (i=0 ; i<2 ; i++) { if (data >= dataend) { value <<= 4; break; } c = *data++; if (!isxdigit((int) c)) { if (strict || !isspace(c)) { goto badChar; } i--; continue; } value <<= 4; c -= '0'; if (c > 9) { c += ('0' - 'A') + 10; } if (c > 16) { c += ('A' - 'a'); } value |= (c & 0xf); } if (i < 2) { cut++; } *cursor++ = UCHAR(value); value = 0; } if (cut > size) { cut = size; } Tcl_SetByteArrayLength(resultObj, cursor - begin - cut); Tcl_SetObjResult(interp, resultObj); return TCL_OK; badChar: TclDecrRefCount(resultObj); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid hexadecimal digit \"%c\" at position %d", c, (int) (data - datastart - 1))); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * BinaryEncode64 -- * * This implements a generic 6 bit binary encoding. Input is broken into * 6 bit chunks and a lookup table passed in via clientData is used to * turn these values into output characters. This is used to implement * base64 binary encodings. * * Results: * Interp result set to an encoded byte array object * * Side effects: * None * *---------------------------------------------------------------------- */ #define OUTPUT(c) \ do { \ *cursor++ = (c); \ outindex++; \ if (maxlen > 0 && cursor != limit) { \ if (outindex == maxlen) { \ memcpy(cursor, wrapchar, wrapcharlen); \ cursor += wrapcharlen; \ outindex = 0; \ } \ } \ if (cursor > limit) { \ Tcl_Panic("limit hit"); \ } \ } while (0) static int BinaryEncode64( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultObj; unsigned char *data, *cursor, *limit; int maxlen = 0; const char *wrapchar = "\n"; int wrapcharlen = 1; int offset, i, index, size, outindex = 0, count = 0; enum {OPT_MAXLEN, OPT_WRAPCHAR }; static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL }; if (objc < 2 || objc%2 != 0) { Tcl_WrongNumArgs(interp, 1, objv, "?-maxlen len? ?-wrapchar char? data"); return TCL_ERROR; } for (i = 1; i < objc-1; i += 2) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case OPT_MAXLEN: if (Tcl_GetIntFromObj(interp, objv[i+1], &maxlen) != TCL_OK) { return TCL_ERROR; } if (maxlen < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "line length out of range", -1)); Tcl_SetErrorCode(interp, "TCL", "BINARY", "ENCODE", "LINE_LENGTH", NULL); return TCL_ERROR; } break; case OPT_WRAPCHAR: wrapchar = Tcl_GetStringFromObj(objv[i+1], &wrapcharlen); if (wrapcharlen == 0) { maxlen = 0; } break; } } resultObj = Tcl_NewObj(); data = Tcl_GetByteArrayFromObj(objv[objc-1], &count); if (count > 0) { size = (((count * 4) / 3) + 3) & ~3; /* ensure 4 byte chunks */ if (maxlen > 0 && size > maxlen) { int adjusted = size + (wrapcharlen * (size / maxlen)); if (size % maxlen == 0) { adjusted -= wrapcharlen; } size = adjusted; } cursor = Tcl_SetByteArrayLength(resultObj, size); limit = cursor + size; for (offset = 0; offset < count; offset+=3) { unsigned char d[3] = {0, 0, 0}; for (i = 0; i < 3 && offset+i < count; ++i) { d[i] = data[offset + i]; } OUTPUT(B64Digits[d[0] >> 2]); OUTPUT(B64Digits[((d[0] & 0x03) << 4) | (d[1] >> 4)]); if (offset+1 < count) { OUTPUT(B64Digits[((d[1] & 0x0f) << 2) | (d[2] >> 6)]); } else { OUTPUT(B64Digits[64]); } if (offset+2 < count) { OUTPUT(B64Digits[d[2] & 0x3f]); } else { OUTPUT(B64Digits[64]); } } } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } #undef OUTPUT /* *---------------------------------------------------------------------- * * BinaryEncodeUu -- * * This implements the uuencode binary encoding. Input is broken into 6 * bit chunks and a lookup table is used to turn these values into output * characters. This differs from the generic code above in that line * lengths are also encoded. * * Results: * Interp result set to an encoded byte array object * * Side effects: * None * *---------------------------------------------------------------------- */ static int BinaryEncodeUu( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultObj; unsigned char *data, *start, *cursor; int offset, count, rawLength, n, i, j, bits, index; int lineLength = 61; const unsigned char SingleNewline[] = { (unsigned char) '\n' }; const unsigned char *wrapchar = SingleNewline; int wrapcharlen = sizeof(SingleNewline); enum { OPT_MAXLEN, OPT_WRAPCHAR }; static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL }; if (objc < 2 || objc%2 != 0) { Tcl_WrongNumArgs(interp, 1, objv, "?-maxlen len? ?-wrapchar char? data"); return TCL_ERROR; } for (i = 1; i < objc-1; i += 2) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case OPT_MAXLEN: if (Tcl_GetIntFromObj(interp, objv[i+1], &lineLength) != TCL_OK) { return TCL_ERROR; } if (lineLength < 3 || lineLength > 85) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "line length out of range", -1)); Tcl_SetErrorCode(interp, "TCL", "BINARY", "ENCODE", "LINE_LENGTH", NULL); return TCL_ERROR; } break; case OPT_WRAPCHAR: wrapchar = Tcl_GetByteArrayFromObj(objv[i+1], &wrapcharlen); break; } } /* * Allocate the buffer. This is a little bit too long, but is "good * enough". */ resultObj = Tcl_NewObj(); offset = 0; data = Tcl_GetByteArrayFromObj(objv[objc-1], &count); rawLength = (lineLength - 1) * 3 / 4; start = cursor = Tcl_SetByteArrayLength(resultObj, (lineLength + wrapcharlen) * ((count + (rawLength - 1)) / rawLength)); n = bits = 0; /* * Encode the data. Each output line first has the length of raw data * encoded by the output line described in it by one encoded byte, then * the encoded data follows (encoding each 6 bits as one character). * Encoded lines are always terminated by a newline. */ while (offset < count) { int lineLen = count - offset; if (lineLen > rawLength) { lineLen = rawLength; } *cursor++ = UueDigits[lineLen]; for (i=0 ; i 6 ; bits -= 6) { *cursor++ = UueDigits[(n >> (bits-6)) & 0x3f]; } } if (bits > 0) { n <<= 8; *cursor++ = UueDigits[(n >> (bits + 2)) & 0x3f]; bits = 0; } for (j=0 ; j 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? data"); return TCL_ERROR; } for (i = 1; i < objc-1; ++i) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case OPT_STRICT: strict = 1; break; } } TclNewObj(resultObj); datastart = data = (unsigned char *) TclGetStringFromObj(objv[objc-1], &count); dataend = data + count; size = ((count + 3) & ~3) * 3 / 4; begin = cursor = Tcl_SetByteArrayLength(resultObj, size); lineLen = -1; /* * The decoding loop. First, we get the length of line (strictly, the * number of data bytes we expect to generate from the line) we're * processing this time round if it is not already known (i.e., when the * lineLen variable is set to the magic value, -1). */ while (data < dataend) { char d[4] = {0, 0, 0, 0}; if (lineLen < 0) { c = *data++; if (c < 32 || c > 96) { if (strict || !isspace(c)) { goto badUu; } i--; continue; } lineLen = (c - 32) & 0x3f; } /* * Now we read a four-character grouping. */ for (i=0 ; i<4 ; i++) { if (data < dataend) { d[i] = c = *data++; if (c < 32 || c > 96) { if (strict) { if (!isspace(c)) { goto badUu; } else if (c == '\n') { goto shortUu; } } i--; continue; } } } /* * Translate that grouping into (up to) three binary bytes output. */ if (lineLen > 0) { *cursor++ = (((d[0] - 0x20) & 0x3f) << 2) | (((d[1] - 0x20) & 0x3f) >> 4); if (--lineLen > 0) { *cursor++ = (((d[1] - 0x20) & 0x3f) << 4) | (((d[2] - 0x20) & 0x3f) >> 2); if (--lineLen > 0) { *cursor++ = (((d[2] - 0x20) & 0x3f) << 6) | (((d[3] - 0x20) & 0x3f)); lineLen--; } } } /* * If we've reached the end of the line, skip until we process a * newline. */ if (lineLen == 0 && data < dataend) { lineLen = -1; do { c = *data++; if (c == '\n') { break; } else if (c >= 32 && c <= 96) { data--; break; } else if (strict || !isspace(c)) { goto badUu; } } while (data < dataend); } } /* * Sanity check, clean up and finish. */ if (lineLen > 0 && strict) { goto shortUu; } Tcl_SetByteArrayLength(resultObj, cursor - begin); Tcl_SetObjResult(interp, resultObj); return TCL_OK; shortUu: Tcl_SetObjResult(interp, Tcl_ObjPrintf("short uuencode data")); Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "SHORT", NULL); TclDecrRefCount(resultObj); return TCL_ERROR; badUu: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid uuencode character \"%c\" at position %d", c, (int) (data - datastart - 1))); Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", NULL); TclDecrRefCount(resultObj); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * BinaryDecode64 -- * * Decode a base64 encoded string. * * Results: * Interp result set to an byte array object * * Side effects: * None * *---------------------------------------------------------------------- */ static int BinaryDecode64( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultObj = NULL; unsigned char *data, *datastart, *dataend, c = '\0'; unsigned char *begin = NULL; unsigned char *cursor = NULL; int strict = 0; int i, index, size, cut = 0, count = 0; enum { OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? data"); return TCL_ERROR; } for (i = 1; i < objc-1; ++i) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case OPT_STRICT: strict = 1; break; } } TclNewObj(resultObj); datastart = data = (unsigned char *) TclGetStringFromObj(objv[objc-1], &count); dataend = data + count; size = ((count + 3) & ~3) * 3 / 4; begin = cursor = Tcl_SetByteArrayLength(resultObj, size); while (data < dataend) { unsigned long value = 0; /* * Decode the current block. Each base64 block consists of four input * characters A-Z, a-z, 0-9, +, or /. Each character supplies six bits * of output data, so each block's output is 24 bits (three bytes) in * length. The final block can be shorter by one or two bytes, denoted * by the input ending with one or two ='s, respectively. */ for (i = 0; i < 4; i++) { /* * Get the next input character. At end of input, pad with at most * two ='s. If more than two ='s would be needed, instead discard * the block read thus far. */ if (data < dataend) { c = *data++; } else if (i > 1) { c = '='; } else { cut += 3; break; } /* * Load the character into the block value. Handle ='s specially * because they're only valid as the last character or two of the * final block of input. Unless strict mode is enabled, skip any * input whitespace characters. */ if (cut) { if (c == '=' && i > 1) { value <<= 6; cut++; } else if (!strict && isspace(c)) { i--; } else { goto bad64; } } else if (c >= 'A' && c <= 'Z') { value = (value << 6) | ((c - 'A') & 0x3f); } else if (c >= 'a' && c <= 'z') { value = (value << 6) | ((c - 'a' + 26) & 0x3f); } else if (c >= '0' && c <= '9') { value = (value << 6) | ((c - '0' + 52) & 0x3f); } else if (c == '+') { value = (value << 6) | 0x3e; } else if (c == '/') { value = (value << 6) | 0x3f; } else if (c == '=') { value <<= 6; cut++; } else if (strict || !isspace(c)) { goto bad64; } else { i--; } } *cursor++ = UCHAR((value >> 16) & 0xff); *cursor++ = UCHAR((value >> 8) & 0xff); *cursor++ = UCHAR(value & 0xff); /* * Since = is only valid within the final block, if it was encountered * but there are still more input characters, confirm that strict mode * is off and all subsequent characters are whitespace. */ if (cut && data < dataend) { if (strict) { goto bad64; } for (; data < dataend; data++) { if (!isspace(*data)) { goto bad64; } } } } Tcl_SetByteArrayLength(resultObj, cursor - begin - cut); Tcl_SetObjResult(interp, resultObj); return TCL_OK; bad64: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid base64 character \"%c\" at position %d", (char) c, (int) (data - datastart - 1))); TclDecrRefCount(resultObj); return TCL_ERROR; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/regcomp.c0000644000175000017500000016012312663660065015006 0ustar sergeisergei/* * re_*comp and friends - compile REs * This file #includes several others (see the bottom). * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "regguts.h" /* * forward declarations, up here so forward datatypes etc. are defined early */ /* =====^!^===== begin forwards =====^!^===== */ /* automatically gathered by fwd; do not hand-edit */ /* === regcomp.c === */ int compile(regex_t *, const chr *, size_t, int); static void moresubs(struct vars *, int); static int freev(struct vars *, int); static void makesearch(struct vars *, struct nfa *); static struct subre *parse(struct vars *, int, int, struct state *, struct state *); static struct subre *parsebranch(struct vars *, int, int, struct state *, struct state *, int); static void parseqatom(struct vars *, int, int, struct state *, struct state *, struct subre *); static void nonword(struct vars *, int, struct state *, struct state *); static void word(struct vars *, int, struct state *, struct state *); static int scannum(struct vars *); static void repeat(struct vars *, struct state *, struct state *, int, int); static void bracket(struct vars *, struct state *, struct state *); static void cbracket(struct vars *, struct state *, struct state *); static void brackpart(struct vars *, struct state *, struct state *); static const chr *scanplain(struct vars *); static void onechr(struct vars *, pchr, struct state *, struct state *); static void dovec(struct vars *, struct cvec *, struct state *, struct state *); static void wordchrs(struct vars *); static struct subre *subre(struct vars *, int, int, struct state *, struct state *); static void freesubre(struct vars *, struct subre *); static void freesrnode(struct vars *, struct subre *); static void optst(struct vars *, struct subre *); static int numst(struct subre *, int); static void markst(struct subre *); static void cleanst(struct vars *); static long nfatree(struct vars *, struct subre *, FILE *); static long nfanode(struct vars *, struct subre *, FILE *); static int newlacon(struct vars *, struct state *, struct state *, int); static void freelacons(struct subre *, int); static void rfree(regex_t *); static void dump(regex_t *, FILE *); static void dumpst(struct subre *, FILE *, int); static void stdump(struct subre *, FILE *, int); static const char *stid(struct subre *, char *, size_t); /* === regc_lex.c === */ static void lexstart(struct vars *); static void prefixes(struct vars *); static void lexnest(struct vars *, const chr *, const chr *); static void lexword(struct vars *); static int next(struct vars *); static int lexescape(struct vars *); static int lexdigits(struct vars *, int, int, int); static int brenext(struct vars *, pchr); static void skip(struct vars *); static chr newline(NOPARMS); static chr chrnamed(struct vars *, const chr *, const chr *, pchr); /* === regc_color.c === */ static void initcm(struct vars *, struct colormap *); static void freecm(struct colormap *); static void cmtreefree(struct colormap *, union tree *, int); static color setcolor(struct colormap *, pchr, pcolor); static color maxcolor(struct colormap *); static color newcolor(struct colormap *); static void freecolor(struct colormap *, pcolor); static color pseudocolor(struct colormap *); static color subcolor(struct colormap *, pchr c); static color newsub(struct colormap *, pcolor); static void subrange(struct vars *, pchr, pchr, struct state *, struct state *); static void subblock(struct vars *, pchr, struct state *, struct state *); static void okcolors(struct nfa *, struct colormap *); static void colorchain(struct colormap *, struct arc *); static void uncolorchain(struct colormap *, struct arc *); static void rainbow(struct nfa *, struct colormap *, int, pcolor, struct state *, struct state *); static void colorcomplement(struct nfa *, struct colormap *, int, struct state *, struct state *, struct state *); #ifdef REG_DEBUG static void dumpcolors(struct colormap *, FILE *); static void fillcheck(struct colormap *, union tree *, int, FILE *); static void dumpchr(pchr, FILE *); #endif /* === regc_nfa.c === */ static struct nfa *newnfa(struct vars *, struct colormap *, struct nfa *); static void freenfa(struct nfa *); static struct state *newstate(struct nfa *); static struct state *newfstate(struct nfa *, int flag); static void dropstate(struct nfa *, struct state *); static void freestate(struct nfa *, struct state *); static void destroystate(struct nfa *, struct state *); static void newarc(struct nfa *, int, pcolor, struct state *, struct state *); static void createarc(struct nfa *, int, pcolor, struct state *, struct state *); static struct arc *allocarc(struct nfa *, struct state *); static void freearc(struct nfa *, struct arc *); static void changearctarget(struct arc *, struct state *); static int hasnonemptyout(struct state *); static struct arc *findarc(struct state *, int, pcolor); static void cparc(struct nfa *, struct arc *, struct state *, struct state *); static void sortins(struct nfa *, struct state *); static int sortins_cmp(const void *, const void *); static void sortouts(struct nfa *, struct state *); static int sortouts_cmp(const void *, const void *); static void moveins(struct nfa *, struct state *, struct state *); static void copyins(struct nfa *, struct state *, struct state *); static void mergeins(struct nfa *, struct state *, struct arc **, int); static void moveouts(struct nfa *, struct state *, struct state *); static void copyouts(struct nfa *, struct state *, struct state *); static void cloneouts(struct nfa *, struct state *, struct state *, struct state *, int); static void delsub(struct nfa *, struct state *, struct state *); static void deltraverse(struct nfa *, struct state *, struct state *); static void dupnfa(struct nfa *, struct state *, struct state *, struct state *, struct state *); static void duptraverse(struct nfa *, struct state *, struct state *, int); static void cleartraverse(struct nfa *, struct state *); static void specialcolors(struct nfa *); static long optimize(struct nfa *, FILE *); static void pullback(struct nfa *, FILE *); static int pull(struct nfa *, struct arc *, struct state **); static void pushfwd(struct nfa *, FILE *); static int push(struct nfa *, struct arc *, struct state **); #define INCOMPATIBLE 1 /* destroys arc */ #define SATISFIED 2 /* constraint satisfied */ #define COMPATIBLE 3 /* compatible but not satisfied yet */ static int combine(struct arc *, struct arc *); static void fixempties(struct nfa *, FILE *); static struct state *emptyreachable(struct nfa *, struct state *, struct state *, struct arc **); static int isconstraintarc(struct arc *); static int hasconstraintout(struct state *); static void fixconstraintloops(struct nfa *, FILE *); static int findconstraintloop(struct nfa *, struct state *); static void breakconstraintloop(struct nfa *, struct state *); static void clonesuccessorstates(struct nfa *, struct state *, struct state *, struct state *, struct arc *, char *, char *, int); static void cleanup(struct nfa *); static void markreachable(struct nfa *, struct state *, struct state *, struct state *); static void markcanreach(struct nfa *, struct state *, struct state *, struct state *); static long analyze(struct nfa *); static void compact(struct nfa *, struct cnfa *); static void carcsort(struct carc *, size_t); static int carc_cmp(const void *, const void *); static void freecnfa(struct cnfa *); static void dumpnfa(struct nfa *, FILE *); #ifdef REG_DEBUG static void dumpstate(struct state *, FILE *); static void dumparcs(struct state *, FILE *); static void dumparc(struct arc *, struct state *, FILE *); #endif static void dumpcnfa(struct cnfa *, FILE *); #ifdef REG_DEBUG static void dumpcstate(int, struct cnfa *, FILE *); #endif /* === regc_cvec.c === */ static struct cvec *clearcvec(struct cvec *); static void addchr(struct cvec *, pchr); static void addrange(struct cvec *, pchr, pchr); static struct cvec *newcvec(int, int); static struct cvec *getcvec(struct vars *, int, int); static void freecvec(struct cvec *); /* === regc_locale.c === */ static celt element(struct vars *, const chr *, const chr *); static struct cvec *range(struct vars *, celt, celt, int); static int before(celt, celt); static struct cvec *eclass(struct vars *, celt, int); static struct cvec *cclass(struct vars *, const chr *, const chr *, int); static struct cvec *allcases(struct vars *, pchr); static int cmp(const chr *, const chr *, size_t); static int casecmp(const chr *, const chr *, size_t); /* automatically gathered by fwd; do not hand-edit */ /* =====^!^===== end forwards =====^!^===== */ /* internal variables, bundled for easy passing around */ struct vars { regex_t *re; const chr *now; /* scan pointer into string */ const chr *stop; /* end of string */ const chr *savenow; /* saved now and stop for "subroutine call" */ const chr *savestop; int err; /* error code (0 if none) */ int cflags; /* copy of compile flags */ int lasttype; /* type of previous token */ int nexttype; /* type of next token */ chr nextvalue; /* value (if any) of next token */ int lexcon; /* lexical context type (see lex.c) */ int nsubexp; /* subexpression count */ struct subre **subs; /* subRE pointer vector */ size_t nsubs; /* length of vector */ struct subre *sub10[10]; /* initial vector, enough for most */ struct nfa *nfa; /* the NFA */ struct colormap *cm; /* character color map */ color nlcolor; /* color of newline */ struct state *wordchrs; /* state in nfa holding word-char outarcs */ struct subre *tree; /* subexpression tree */ struct subre *treechain; /* all tree nodes allocated */ struct subre *treefree; /* any free tree nodes */ int ntree; /* number of tree nodes, plus one */ struct cvec *cv; /* interface cvec */ struct cvec *cv2; /* utility cvec */ struct subre *lacons; /* lookahead-constraint vector */ int nlacons; /* size of lacons */ size_t spaceused; /* approx. space used for compilation */ }; /* parsing macros; most know that `v' is the struct vars pointer */ #define NEXT() (next(v)) /* advance by one token */ #define SEE(t) (v->nexttype == (t)) /* is next token this? */ #define EAT(t) (SEE(t) && next(v)) /* if next is this, swallow it */ #define VISERR(vv) ((vv)->err != 0)/* have we seen an error yet? */ #define ISERR() VISERR(v) #define VERR(vv,e) ((vv)->nexttype = EOS, \ (vv)->err = ((vv)->err ? (vv)->err : (e))) #define ERR(e) VERR(v, e) /* record an error */ #define NOERR() {if (ISERR()) return;} /* if error seen, return */ #define NOERRN() {if (ISERR()) return NULL;} /* NOERR with retval */ #define NOERRZ() {if (ISERR()) return 0;} /* NOERR with retval */ #define INSIST(c, e) do { if (!(c)) ERR(e); } while (0) /* error if c false */ #define NOTE(b) (v->re->re_info |= (b)) /* note visible condition */ #define EMPTYARC(x, y) newarc(v->nfa, EMPTY, 0, x, y) /* token type codes, some also used as NFA arc types */ #define EMPTY 'n' /* no token present */ #define EOS 'e' /* end of string */ #define PLAIN 'p' /* ordinary character */ #define DIGIT 'd' /* digit (in bound) */ #define BACKREF 'b' /* back reference */ #define COLLEL 'I' /* start of [. */ #define ECLASS 'E' /* start of [= */ #define CCLASS 'C' /* start of [: */ #define END 'X' /* end of [. [= [: */ #define RANGE 'R' /* - within [] which might be range delim. */ #define LACON 'L' /* lookahead constraint subRE */ #define AHEAD 'a' /* color-lookahead arc */ #define BEHIND 'r' /* color-lookbehind arc */ #define WBDRY 'w' /* word boundary constraint */ #define NWBDRY 'W' /* non-word-boundary constraint */ #define SBEGIN 'A' /* beginning of string (even if not BOL) */ #define SEND 'Z' /* end of string (even if not EOL) */ #define PREFER 'P' /* length preference */ /* is an arc colored, and hence on a color chain? */ #define COLORED(a) \ ((a)->type == PLAIN || (a)->type == AHEAD || (a)->type == BEHIND) /* static function list */ static const struct fns functions = { rfree, /* regfree insides */ }; /* - compile - compile regular expression * Note: on failure, no resources remain allocated, so regfree() * need not be applied to re. ^ int compile(regex_t *, const chr *, size_t, int); */ int compile( regex_t *re, const chr *string, size_t len, int flags) { AllocVars(v); struct guts *g; int i; size_t j; FILE *debug = (flags®_PROGRESS) ? stdout : NULL; #define CNOERR() { if (ISERR()) return freev(v, v->err); } /* * Sanity checks. */ if (re == NULL || string == NULL) { FreeVars(v); return REG_INVARG; } if ((flags®_QUOTE) && (flags&(REG_ADVANCED|REG_EXPANDED|REG_NEWLINE))) { FreeVars(v); return REG_INVARG; } if (!(flags®_EXTENDED) && (flags®_ADVF)) { FreeVars(v); return REG_INVARG; } /* * Initial setup (after which freev() is callable). */ v->re = re; v->now = string; v->stop = v->now + len; v->savenow = v->savestop = NULL; v->err = 0; v->cflags = flags; v->nsubexp = 0; v->subs = v->sub10; v->nsubs = 10; for (j = 0; j < v->nsubs; j++) { v->subs[j] = NULL; } v->nfa = NULL; v->cm = NULL; v->nlcolor = COLORLESS; v->wordchrs = NULL; v->tree = NULL; v->treechain = NULL; v->treefree = NULL; v->cv = NULL; v->cv2 = NULL; v->lacons = NULL; v->nlacons = 0; v->spaceused = 0; re->re_magic = REMAGIC; re->re_info = 0; /* bits get set during parse */ re->re_csize = sizeof(chr); re->re_guts = NULL; re->re_fns = VS(&functions); /* * More complex setup, malloced things. */ re->re_guts = VS(MALLOC(sizeof(struct guts))); if (re->re_guts == NULL) { return freev(v, REG_ESPACE); } g = (struct guts *) re->re_guts; g->tree = NULL; initcm(v, &g->cmap); v->cm = &g->cmap; g->lacons = NULL; g->nlacons = 0; ZAPCNFA(g->search); v->nfa = newnfa(v, v->cm, NULL); CNOERR(); v->cv = newcvec(100, 20); if (v->cv == NULL) { return freev(v, REG_ESPACE); } /* * Parsing. */ lexstart(v); /* also handles prefixes */ if ((v->cflags®_NLSTOP) || (v->cflags®_NLANCH)) { /* * Assign newline a unique color. */ v->nlcolor = subcolor(v->cm, newline()); okcolors(v->nfa, v->cm); } CNOERR(); v->tree = parse(v, EOS, PLAIN, v->nfa->init, v->nfa->final); assert(SEE(EOS)); /* even if error; ISERR() => SEE(EOS) */ CNOERR(); assert(v->tree != NULL); /* * Finish setup of nfa and its subre tree. */ specialcolors(v->nfa); CNOERR(); if (debug != NULL) { fprintf(debug, "\n\n\n========= RAW ==========\n"); dumpnfa(v->nfa, debug); dumpst(v->tree, debug, 1); } optst(v, v->tree); v->ntree = numst(v->tree, 1); markst(v->tree); cleanst(v); if (debug != NULL) { fprintf(debug, "\n\n\n========= TREE FIXED ==========\n"); dumpst(v->tree, debug, 1); } /* * Build compacted NFAs for tree and lacons. */ re->re_info |= nfatree(v, v->tree, debug); CNOERR(); assert(v->nlacons == 0 || v->lacons != NULL); for (i = 1; i < v->nlacons; i++) { if (debug != NULL) { fprintf(debug, "\n\n\n========= LA%d ==========\n", i); } nfanode(v, &v->lacons[i], debug); } CNOERR(); if (v->tree->flags&SHORTER) { NOTE(REG_USHORTEST); } /* * Build compacted NFAs for tree, lacons, fast search. */ if (debug != NULL) { fprintf(debug, "\n\n\n========= SEARCH ==========\n"); } /* * Can sacrifice main NFA now, so use it as work area. */ (DISCARD) optimize(v->nfa, debug); CNOERR(); makesearch(v, v->nfa); CNOERR(); compact(v->nfa, &g->search); CNOERR(); /* * Looks okay, package it up. */ re->re_nsub = v->nsubexp; v->re = NULL; /* freev no longer frees re */ g->magic = GUTSMAGIC; g->cflags = v->cflags; g->info = re->re_info; g->nsub = re->re_nsub; g->tree = v->tree; v->tree = NULL; g->ntree = v->ntree; g->compare = (v->cflags®_ICASE) ? casecmp : cmp; g->lacons = v->lacons; v->lacons = NULL; g->nlacons = v->nlacons; if (flags®_DUMP) { dump(re, stdout); } assert(v->err == 0); return freev(v, 0); } /* - moresubs - enlarge subRE vector ^ static void moresubs(struct vars *, int); */ static void moresubs( struct vars *v, int wanted) /* want enough room for this one */ { struct subre **p; size_t n; assert(wanted > 0 && (size_t)wanted >= v->nsubs); n = (size_t)wanted * 3 / 2 + 1; if (v->subs == v->sub10) { p = (struct subre **) MALLOC(n * sizeof(struct subre *)); if (p != NULL) { memcpy(p, v->subs, v->nsubs * sizeof(struct subre *)); } } else { p = (struct subre **) REALLOC(v->subs, n*sizeof(struct subre *)); } if (p == NULL) { ERR(REG_ESPACE); return; } v->subs = p; for (p = &v->subs[v->nsubs]; v->nsubs < n; p++, v->nsubs++) { *p = NULL; } assert(v->nsubs == n); assert((size_t)wanted < v->nsubs); } /* - freev - free vars struct's substructures where necessary * Optionally does error-number setting, and always returns error code (if * any), to make error-handling code terser. ^ static int freev(struct vars *, int); */ static int freev( struct vars *v, int err) { register int ret; if (v->re != NULL) { rfree(v->re); } if (v->subs != v->sub10) { FREE(v->subs); } if (v->nfa != NULL) { freenfa(v->nfa); } if (v->tree != NULL) { freesubre(v, v->tree); } if (v->treechain != NULL) { cleanst(v); } if (v->cv != NULL) { freecvec(v->cv); } if (v->cv2 != NULL) { freecvec(v->cv2); } if (v->lacons != NULL) { freelacons(v->lacons, v->nlacons); } ERR(err); /* nop if err==0 */ ret = v->err; FreeVars(v); return ret; } /* - makesearch - turn an NFA into a search NFA (implicit prepend of .*?) * NFA must have been optimize()d already. ^ static void makesearch(struct vars *, struct nfa *); */ static void makesearch( struct vars *v, struct nfa *nfa) { struct arc *a, *b; struct state *pre = nfa->pre; struct state *s, *s2, *slist; /* * No loops are needed if it's anchored. */ for (a = pre->outs; a != NULL; a = a->outchain) { assert(a->type == PLAIN); if (a->co != nfa->bos[0] && a->co != nfa->bos[1]) { break; } } if (a != NULL) { /* * Add implicit .* in front. */ rainbow(nfa, v->cm, PLAIN, COLORLESS, pre, pre); /* * And ^* and \A* too -- not always necessary, but harmless. */ newarc(nfa, PLAIN, nfa->bos[0], pre, pre); newarc(nfa, PLAIN, nfa->bos[1], pre, pre); } /* * Now here's the subtle part. Because many REs have no lookback * constraints, often knowing when you were in the pre state tells you * little; it's the next state(s) that are informative. But some of them * may have other inarcs, i.e. it may be possible to make actual progress * and then return to one of them. We must de-optimize such cases, * splitting each such state into progress and no-progress states. */ /* * First, make a list of the states. */ slist = NULL; for (a=pre->outs ; a!=NULL ; a=a->outchain) { s = a->to; for (b=s->ins ; b!=NULL ; b=b->inchain) { if (b->from != pre) { break; } } /* * We want to mark states as being in the list already by having non * NULL tmp fields, but we can't just store the old slist value in tmp * because that doesn't work for the first such state. Instead, the * first list entry gets its own address in tmp. */ if (b != NULL && s->tmp == NULL) { s->tmp = (slist != NULL) ? slist : s; slist = s; } } /* * Do the splits. */ for (s=slist ; s!=NULL ; s=s2) { s2 = newstate(nfa); NOERR(); copyouts(nfa, s, s2); NOERR(); for (a=s->ins ; a!=NULL ; a=b) { b = a->inchain; if (a->from != pre) { cparc(nfa, a, a->from, s2); freearc(nfa, a); } } s2 = (s->tmp != s) ? s->tmp : NULL; s->tmp = NULL; /* clean up while we're at it */ } } /* - parse - parse an RE * This is actually just the top level, which parses a bunch of branches tied * together with '|'. They appear in the tree as the left children of a chain * of '|' subres. ^ static struct subre *parse(struct vars *, int, int, struct state *, ^ struct state *); */ static struct subre * parse( struct vars *v, int stopper, /* EOS or ')' */ int type, /* LACON (lookahead subRE) or PLAIN */ struct state *init, /* initial state */ struct state *final) /* final state */ { struct state *left, *right; /* scaffolding for branch */ struct subre *branches; /* top level */ struct subre *branch; /* current branch */ struct subre *t; /* temporary */ int firstbranch; /* is this the first branch? */ assert(stopper == ')' || stopper == EOS); branches = subre(v, '|', LONGER, init, final); NOERRN(); branch = branches; firstbranch = 1; do { /* a branch */ if (!firstbranch) { /* * Need a place to hang the branch. */ branch->right = subre(v, '|', LONGER, init, final); NOERRN(); branch = branch->right; } firstbranch = 0; left = newstate(v->nfa); right = newstate(v->nfa); NOERRN(); EMPTYARC(init, left); EMPTYARC(right, final); NOERRN(); branch->left = parsebranch(v, stopper, type, left, right, 0); NOERRN(); branch->flags |= UP(branch->flags | branch->left->flags); if ((branch->flags &~ branches->flags) != 0) { /* new flags */ for (t = branches; t != branch; t = t->right) { t->flags |= branch->flags; } } } while (EAT('|')); assert(SEE(stopper) || SEE(EOS)); if (!SEE(stopper)) { assert(stopper == ')' && SEE(EOS)); ERR(REG_EPAREN); } /* * Optimize out simple cases. */ if (branch == branches) { /* only one branch */ assert(branch->right == NULL); t = branch->left; branch->left = NULL; freesubre(v, branches); branches = t; } else if (!MESSY(branches->flags)) { /* no interesting innards */ freesubre(v, branches->left); branches->left = NULL; freesubre(v, branches->right); branches->right = NULL; branches->op = '='; } return branches; } /* - parsebranch - parse one branch of an RE * This mostly manages concatenation, working closely with parseqatom(). * Concatenated things are bundled up as much as possible, with separate * ',' nodes introduced only when necessary due to substructure. ^ static struct subre *parsebranch(struct vars *, int, int, struct state *, ^ struct state *, int); */ static struct subre * parsebranch( struct vars *v, int stopper, /* EOS or ')' */ int type, /* LACON (lookahead subRE) or PLAIN */ struct state *left, /* leftmost state */ struct state *right, /* rightmost state */ int partial) /* is this only part of a branch? */ { struct state *lp; /* left end of current construct */ int seencontent; /* is there anything in this branch yet? */ struct subre *t; lp = left; seencontent = 0; t = subre(v, '=', 0, left, right); /* op '=' is tentative */ NOERRN(); while (!SEE('|') && !SEE(stopper) && !SEE(EOS)) { if (seencontent) { /* implicit concat operator */ lp = newstate(v->nfa); NOERRN(); moveins(v->nfa, right, lp); } seencontent = 1; /* NB, recursion in parseqatom() may swallow rest of branch */ parseqatom(v, stopper, type, lp, right, t); NOERRN(); } if (!seencontent) { /* empty branch */ if (!partial) { NOTE(REG_UUNSPEC); } assert(lp == left); EMPTYARC(left, right); } return t; } /* - parseqatom - parse one quantified atom or constraint of an RE * The bookkeeping near the end cooperates very closely with parsebranch(); in * particular, it contains a recursion that can involve parsing the rest of * the branch, making this function's name somewhat inaccurate. ^ static void parseqatom(struct vars *, int, int, struct state *, ^ struct state *, struct subre *); */ static void parseqatom( struct vars *v, int stopper, /* EOS or ')' */ int type, /* LACON (lookahead subRE) or PLAIN */ struct state *lp, /* left state to hang it on */ struct state *rp, /* right state to hang it on */ struct subre *top) /* subtree top */ { struct state *s; /* temporaries for new states */ struct state *s2; #define ARCV(t, val) newarc(v->nfa, t, val, lp, rp) int m, n; struct subre *atom; /* atom's subtree */ struct subre *t; int cap; /* capturing parens? */ int pos; /* positive lookahead? */ int subno; /* capturing-parens or backref number */ int atomtype; int qprefer; /* quantifier short/long preference */ int f; struct subre **atomp; /* where the pointer to atom is */ /* * Initial bookkeeping. */ atom = NULL; assert(lp->nouts == 0); /* must string new code */ assert(rp->nins == 0); /* between lp and rp */ subno = 0; /* just to shut lint up */ /* * An atom or constraint... */ atomtype = v->nexttype; switch (atomtype) { /* first, constraints, which end by returning */ case '^': ARCV('^', 1); if (v->cflags®_NLANCH) { ARCV(BEHIND, v->nlcolor); } NEXT(); return; case '$': ARCV('$', 1); if (v->cflags®_NLANCH) { ARCV(AHEAD, v->nlcolor); } NEXT(); return; case SBEGIN: ARCV('^', 1); /* BOL */ ARCV('^', 0); /* or BOS */ NEXT(); return; case SEND: ARCV('$', 1); /* EOL */ ARCV('$', 0); /* or EOS */ NEXT(); return; case '<': wordchrs(v); /* does NEXT() */ s = newstate(v->nfa); NOERR(); nonword(v, BEHIND, lp, s); word(v, AHEAD, s, rp); return; case '>': wordchrs(v); /* does NEXT() */ s = newstate(v->nfa); NOERR(); word(v, BEHIND, lp, s); nonword(v, AHEAD, s, rp); return; case WBDRY: wordchrs(v); /* does NEXT() */ s = newstate(v->nfa); NOERR(); nonword(v, BEHIND, lp, s); word(v, AHEAD, s, rp); s = newstate(v->nfa); NOERR(); word(v, BEHIND, lp, s); nonword(v, AHEAD, s, rp); return; case NWBDRY: wordchrs(v); /* does NEXT() */ s = newstate(v->nfa); NOERR(); word(v, BEHIND, lp, s); word(v, AHEAD, s, rp); s = newstate(v->nfa); NOERR(); nonword(v, BEHIND, lp, s); nonword(v, AHEAD, s, rp); return; case LACON: /* lookahead constraint */ pos = v->nextvalue; NEXT(); s = newstate(v->nfa); s2 = newstate(v->nfa); NOERR(); t = parse(v, ')', LACON, s, s2); freesubre(v, t); /* internal structure irrelevant */ assert(SEE(')') || ISERR()); NEXT(); n = newlacon(v, s, s2, pos); NOERR(); ARCV(LACON, n); return; /* * Then errors, to get them out of the way. */ case '*': case '+': case '?': case '{': ERR(REG_BADRPT); return; default: ERR(REG_ASSERT); return; /* * Then plain characters, and minor variants on that theme. */ case ')': /* unbalanced paren */ if ((v->cflags®_ADVANCED) != REG_EXTENDED) { ERR(REG_EPAREN); return; } /* * Legal in EREs due to specification botch. */ NOTE(REG_UPBOTCH); /* fallthrough into case PLAIN */ case PLAIN: onechr(v, v->nextvalue, lp, rp); okcolors(v->nfa, v->cm); NOERR(); NEXT(); break; case '[': if (v->nextvalue == 1) { bracket(v, lp, rp); } else { cbracket(v, lp, rp); } assert(SEE(']') || ISERR()); NEXT(); break; case '.': rainbow(v->nfa, v->cm, PLAIN, (v->cflags®_NLSTOP) ? v->nlcolor : COLORLESS, lp, rp); NEXT(); break; /* * And finally the ugly stuff. */ case '(': /* value flags as capturing or non */ cap = (type == LACON) ? 0 : v->nextvalue; if (cap) { v->nsubexp++; subno = v->nsubexp; if ((size_t)subno >= v->nsubs) { moresubs(v, subno); } assert((size_t)subno < v->nsubs); } else { atomtype = PLAIN; /* something that's not '(' */ } NEXT(); /* * Need new endpoints because tree will contain pointers. */ s = newstate(v->nfa); s2 = newstate(v->nfa); NOERR(); EMPTYARC(lp, s); EMPTYARC(s2, rp); NOERR(); atom = parse(v, ')', PLAIN, s, s2); assert(SEE(')') || ISERR()); NEXT(); NOERR(); if (cap) { v->subs[subno] = atom; t = subre(v, '(', atom->flags|CAP, lp, rp); NOERR(); t->subno = subno; t->left = atom; atom = t; } /* * Postpone everything else pending possible {0}. */ break; case BACKREF: /* the Feature From The Black Lagoon */ INSIST(type != LACON, REG_ESUBREG); INSIST(v->nextvalue < v->nsubs, REG_ESUBREG); INSIST(v->subs[v->nextvalue] != NULL, REG_ESUBREG); NOERR(); assert(v->nextvalue > 0); atom = subre(v, 'b', BACKR, lp, rp); NOERR(); subno = v->nextvalue; atom->subno = subno; EMPTYARC(lp, rp); /* temporarily, so there's something */ NEXT(); break; } /* * ...and an atom may be followed by a quantifier. */ switch (v->nexttype) { case '*': m = 0; n = DUPINF; qprefer = (v->nextvalue) ? LONGER : SHORTER; NEXT(); break; case '+': m = 1; n = DUPINF; qprefer = (v->nextvalue) ? LONGER : SHORTER; NEXT(); break; case '?': m = 0; n = 1; qprefer = (v->nextvalue) ? LONGER : SHORTER; NEXT(); break; case '{': NEXT(); m = scannum(v); if (EAT(',')) { if (SEE(DIGIT)) { n = scannum(v); } else { n = DUPINF; } if (m > n) { ERR(REG_BADBR); return; } /* * {m,n} exercises preference, even if it's {m,m} */ qprefer = (v->nextvalue) ? LONGER : SHORTER; } else { n = m; /* * {m} passes operand's preference through. */ qprefer = 0; } if (!SEE('}')) { /* catches errors too */ ERR(REG_BADBR); return; } NEXT(); break; default: /* no quantifier */ m = n = 1; qprefer = 0; break; } /* * Annoying special case: {0} or {0,0} cancels everything. */ if (m == 0 && n == 0) { if (atom != NULL) { freesubre(v, atom); } if (atomtype == '(') { v->subs[subno] = NULL; } delsub(v->nfa, lp, rp); EMPTYARC(lp, rp); return; } /* * If not a messy case, avoid hard part. */ assert(!MESSY(top->flags)); f = top->flags | qprefer | ((atom != NULL) ? atom->flags : 0); if (atomtype != '(' && atomtype != BACKREF && !MESSY(UP(f))) { if (!(m == 1 && n == 1)) { repeat(v, lp, rp, m, n); } if (atom != NULL) { freesubre(v, atom); } top->flags = f; return; } /* * hard part: something messy * That is, capturing parens, back reference, short/long clash, or an atom * with substructure containing one of those. */ /* * Now we'll need a subre for the contents even if they're boring. */ if (atom == NULL) { atom = subre(v, '=', 0, lp, rp); NOERR(); } /* * Prepare a general-purpose state skeleton. * * In the no-backrefs case, we want this: * * [lp] ---> [s] ---prefix---> [begin] ---atom---> [end] ---rest---> [rp] * * where prefix is some repetitions of atom. In the general case we need * * [lp] ---> [s] ---iterator---> [s2] ---rest---> [rp] * * where the iterator wraps around [begin] ---atom---> [end] * * We make the s state here for both cases; s2 is made below if needed */ s = newstate(v->nfa); /* first, new endpoints for the atom */ s2 = newstate(v->nfa); NOERR(); moveouts(v->nfa, lp, s); moveins(v->nfa, rp, s2); NOERR(); atom->begin = s; atom->end = s2; s = newstate(v->nfa); /* set up starting state */ NOERR(); EMPTYARC(lp, s); NOERR(); /* * Break remaining subRE into x{...} and what follows. */ t = subre(v, '.', COMBINE(qprefer, atom->flags), lp, rp); NOERR(); t->left = atom; atomp = &t->left; /* * Here we should recurse... but we must postpone that to the end. */ /* * Split top into prefix and remaining. */ assert(top->op == '=' && top->left == NULL && top->right == NULL); top->left = subre(v, '=', top->flags, top->begin, lp); NOERR(); top->op = '.'; top->right = t; /* * If it's a backref, now is the time to replicate the subNFA. */ if (atomtype == BACKREF) { assert(atom->begin->nouts == 1); /* just the EMPTY */ delsub(v->nfa, atom->begin, atom->end); assert(v->subs[subno] != NULL); /* * And here's why the recursion got postponed: it must wait until the * skeleton is filled in, because it may hit a backref that wants to * copy the filled-in skeleton. */ dupnfa(v->nfa, v->subs[subno]->begin, v->subs[subno]->end, atom->begin, atom->end); NOERR(); } /* * It's quantifier time. If the atom is just a backref, we'll let it deal * with quantifiers internally. */ if (atomtype == BACKREF) { /* * Special case: backrefs have internal quantifiers. */ EMPTYARC(s, atom->begin); /* empty prefix */ /* * Just stuff everything into atom. */ repeat(v, atom->begin, atom->end, m, n); atom->min = (short) m; atom->max = (short) n; atom->flags |= COMBINE(qprefer, atom->flags); /* rest of branch can be strung starting from atom->end */ s2 = atom->end; } else if (m == 1 && n == 1) { /* * No/vacuous quantifier: done. */ EMPTYARC(s, atom->begin); /* empty prefix */ /* rest of branch can be strung starting from atom->end */ s2 = atom->end; } else if (m > 0 && !(atom->flags & BACKR)) { /* * If there's no backrefs involved, we can turn x{m,n} into * x{m-1,n-1}x, with capturing parens in only the second x. This * is valid because we only care about capturing matches from the * final iteration of the quantifier. It's a win because we can * implement the backref-free left side as a plain DFA node, since * we don't really care where its submatches are. */ dupnfa(v->nfa, atom->begin, atom->end, s, atom->begin); assert(m >= 1 && m != DUPINF && n >= 1); repeat(v, s, atom->begin, m-1, (n == DUPINF) ? n : n-1); f = COMBINE(qprefer, atom->flags); t = subre(v, '.', f, s, atom->end); /* prefix and atom */ NOERR(); t->left = subre(v, '=', PREF(f), s, atom->begin); NOERR(); t->right = atom; *atomp = t; /* rest of branch can be strung starting from atom->end */ s2 = atom->end; } else { /* general case: need an iteration node */ s2 = newstate(v->nfa); NOERR(); moveouts(v->nfa, atom->end, s2); NOERR(); dupnfa(v->nfa, atom->begin, atom->end, s, s2); repeat(v, s, s2, m, n); f = COMBINE(qprefer, atom->flags); t = subre(v, '*', f, s, s2); NOERR(); t->min = (short) m; t->max = (short) n; t->left = atom; *atomp = t; /* rest of branch is to be strung from iteration's end state */ } /* * And finally, look after that postponed recursion. */ t = top->right; if (!(SEE('|') || SEE(stopper) || SEE(EOS))) { t->right = parsebranch(v, stopper, type, s2, rp, 1); } else { EMPTYARC(s2, rp); t->right = subre(v, '=', 0, s2, rp); } NOERR(); assert(SEE('|') || SEE(stopper) || SEE(EOS)); t->flags |= COMBINE(t->flags, t->right->flags); top->flags |= COMBINE(top->flags, t->flags); } /* - nonword - generate arcs for non-word-character ahead or behind ^ static void nonword(struct vars *, int, struct state *, struct state *); */ static void nonword( struct vars *v, int dir, /* AHEAD or BEHIND */ struct state *lp, struct state *rp) { int anchor = (dir == AHEAD) ? '$' : '^'; assert(dir == AHEAD || dir == BEHIND); newarc(v->nfa, anchor, 1, lp, rp); newarc(v->nfa, anchor, 0, lp, rp); colorcomplement(v->nfa, v->cm, dir, v->wordchrs, lp, rp); /* (no need for special attention to \n) */ } /* - word - generate arcs for word character ahead or behind ^ static void word(struct vars *, int, struct state *, struct state *); */ static void word( struct vars *v, int dir, /* AHEAD or BEHIND */ struct state *lp, struct state *rp) { assert(dir == AHEAD || dir == BEHIND); cloneouts(v->nfa, v->wordchrs, lp, rp, dir); /* (no need for special attention to \n) */ } /* - scannum - scan a number ^ static int scannum(struct vars *); */ static int /* value, <= DUPMAX */ scannum( struct vars *v) { int n = 0; while (SEE(DIGIT) && n < DUPMAX) { n = n*10 + v->nextvalue; NEXT(); } if (SEE(DIGIT) || n > DUPMAX) { ERR(REG_BADBR); return 0; } return n; } /* - repeat - replicate subNFA for quantifiers * The sub-NFA strung from lp to rp is modified to represent m to n * repetitions of its initial contents. * The duplication sequences used here are chosen carefully so that any * pointers starting out pointing into the subexpression end up pointing into * the last occurrence. (Note that it may not be strung between the same left * and right end states, however!) This used to be important for the subRE * tree, although the important bits are now handled by the in-line code in * parse(), and when this is called, it doesn't matter any more. ^ static void repeat(struct vars *, struct state *, struct state *, int, int); */ static void repeat( struct vars *v, struct state *lp, struct state *rp, int m, int n) { #define SOME 2 #define INF 3 #define PAIR(x, y) ((x)*4 + (y)) #define REDUCE(x) ( ((x) == DUPINF) ? INF : (((x) > 1) ? SOME : (x)) ) const int rm = REDUCE(m); const int rn = REDUCE(n); struct state *s, *s2; switch (PAIR(rm, rn)) { case PAIR(0, 0): /* empty string */ delsub(v->nfa, lp, rp); EMPTYARC(lp, rp); break; case PAIR(0, 1): /* do as x| */ EMPTYARC(lp, rp); break; case PAIR(0, SOME): /* do as x{1,n}| */ repeat(v, lp, rp, 1, n); NOERR(); EMPTYARC(lp, rp); break; case PAIR(0, INF): /* loop x around */ s = newstate(v->nfa); NOERR(); moveouts(v->nfa, lp, s); moveins(v->nfa, rp, s); EMPTYARC(lp, s); EMPTYARC(s, rp); break; case PAIR(1, 1): /* no action required */ break; case PAIR(1, SOME): /* do as x{0,n-1}x = (x{1,n-1}|)x */ s = newstate(v->nfa); NOERR(); moveouts(v->nfa, lp, s); dupnfa(v->nfa, s, rp, lp, s); NOERR(); repeat(v, lp, s, 1, n-1); NOERR(); EMPTYARC(lp, s); break; case PAIR(1, INF): /* add loopback arc */ s = newstate(v->nfa); s2 = newstate(v->nfa); NOERR(); moveouts(v->nfa, lp, s); moveins(v->nfa, rp, s2); EMPTYARC(lp, s); EMPTYARC(s2, rp); EMPTYARC(s2, s); break; case PAIR(SOME, SOME): /* do as x{m-1,n-1}x */ s = newstate(v->nfa); NOERR(); moveouts(v->nfa, lp, s); dupnfa(v->nfa, s, rp, lp, s); NOERR(); repeat(v, lp, s, m-1, n-1); break; case PAIR(SOME, INF): /* do as x{m-1,}x */ s = newstate(v->nfa); NOERR(); moveouts(v->nfa, lp, s); dupnfa(v->nfa, s, rp, lp, s); NOERR(); repeat(v, lp, s, m-1, n); break; default: ERR(REG_ASSERT); break; } } /* - bracket - handle non-complemented bracket expression * Also called from cbracket for complemented bracket expressions. ^ static void bracket(struct vars *, struct state *, struct state *); */ static void bracket( struct vars *v, struct state *lp, struct state *rp) { assert(SEE('[')); NEXT(); while (!SEE(']') && !SEE(EOS)) { brackpart(v, lp, rp); } assert(SEE(']') || ISERR()); okcolors(v->nfa, v->cm); } /* - cbracket - handle complemented bracket expression * We do it by calling bracket() with dummy endpoints, and then complementing * the result. The alternative would be to invoke rainbow(), and then delete * arcs as the b.e. is seen... but that gets messy. ^ static void cbracket(struct vars *, struct state *, struct state *); */ static void cbracket( struct vars *v, struct state *lp, struct state *rp) { struct state *left = newstate(v->nfa); struct state *right = newstate(v->nfa); NOERR(); bracket(v, left, right); if (v->cflags®_NLSTOP) { newarc(v->nfa, PLAIN, v->nlcolor, left, right); } NOERR(); assert(lp->nouts == 0); /* all outarcs will be ours */ /* * Easy part of complementing, and all there is to do since the MCCE code * was removed. */ colorcomplement(v->nfa, v->cm, PLAIN, left, lp, rp); NOERR(); dropstate(v->nfa, left); assert(right->nins == 0); freestate(v->nfa, right); return; } /* - brackpart - handle one item (or range) within a bracket expression ^ static void brackpart(struct vars *, struct state *, struct state *); */ static void brackpart( struct vars *v, struct state *lp, struct state *rp) { celt startc, endc; struct cvec *cv; const chr *startp, *endp; chr c; /* * Parse something, get rid of special cases, take shortcuts. */ switch (v->nexttype) { case RANGE: /* a-b-c or other botch */ ERR(REG_ERANGE); return; break; case PLAIN: c = v->nextvalue; NEXT(); /* * Shortcut for ordinary chr (not range). */ if (!SEE(RANGE)) { onechr(v, c, lp, rp); return; } startc = element(v, &c, &c+1); NOERR(); break; case COLLEL: startp = v->now; endp = scanplain(v); INSIST(startp < endp, REG_ECOLLATE); NOERR(); startc = element(v, startp, endp); NOERR(); break; case ECLASS: startp = v->now; endp = scanplain(v); INSIST(startp < endp, REG_ECOLLATE); NOERR(); startc = element(v, startp, endp); NOERR(); cv = eclass(v, startc, (v->cflags®_ICASE)); NOERR(); dovec(v, cv, lp, rp); return; break; case CCLASS: startp = v->now; endp = scanplain(v); INSIST(startp < endp, REG_ECTYPE); NOERR(); cv = cclass(v, startp, endp, (v->cflags®_ICASE)); NOERR(); dovec(v, cv, lp, rp); return; break; default: ERR(REG_ASSERT); return; break; } if (SEE(RANGE)) { NEXT(); switch (v->nexttype) { case PLAIN: case RANGE: c = v->nextvalue; NEXT(); endc = element(v, &c, &c+1); NOERR(); break; case COLLEL: startp = v->now; endp = scanplain(v); INSIST(startp < endp, REG_ECOLLATE); NOERR(); endc = element(v, startp, endp); NOERR(); break; default: ERR(REG_ERANGE); return; break; } } else { endc = startc; } /* * Ranges are unportable. Actually, standard C does guarantee that digits * are contiguous, but making that an exception is just too complicated. */ if (startc != endc) { NOTE(REG_UUNPORT); } cv = range(v, startc, endc, (v->cflags®_ICASE)); NOERR(); dovec(v, cv, lp, rp); } /* - scanplain - scan PLAIN contents of [. etc. * Certain bits of trickery in lex.c know that this code does not try to look * past the final bracket of the [. etc. ^ static const chr *scanplain(struct vars *); */ static const chr * /* just after end of sequence */ scanplain( struct vars *v) { const chr *endp; assert(SEE(COLLEL) || SEE(ECLASS) || SEE(CCLASS)); NEXT(); endp = v->now; while (SEE(PLAIN)) { endp = v->now; NEXT(); } assert(SEE(END) || ISERR()); NEXT(); return endp; } /* - onechr - fill in arcs for a plain character, and possible case complements * This is mostly a shortcut for efficient handling of the common case. ^ static void onechr(struct vars *, pchr, struct state *, struct state *); */ static void onechr( struct vars *v, pchr c, struct state *lp, struct state *rp) { if (!(v->cflags®_ICASE)) { newarc(v->nfa, PLAIN, subcolor(v->cm, c), lp, rp); return; } /* * Rats, need general case anyway... */ dovec(v, allcases(v, c), lp, rp); } /* - dovec - fill in arcs for each element of a cvec ^ static void dovec(struct vars *, struct cvec *, struct state *, ^ struct state *); */ static void dovec( struct vars *v, struct cvec *cv, struct state *lp, struct state *rp) { chr ch, from, to; const chr *p; int i; for (p = cv->chrs, i = cv->nchrs; i > 0; p++, i--) { ch = *p; newarc(v->nfa, PLAIN, subcolor(v->cm, ch), lp, rp); } for (p = cv->ranges, i = cv->nranges; i > 0; p += 2, i--) { from = *p; to = *(p+1); if (from <= to) { subrange(v, from, to, lp, rp); } } } /* - wordchrs - set up word-chr list for word-boundary stuff, if needed * The list is kept as a bunch of arcs between two dummy states; it's disposed * of by the unreachable-states sweep in NFA optimization. Does NEXT(). Must * not be called from any unusual lexical context. This should be reconciled * with the \w etc. handling in lex.c, and should be cleaned up to reduce * dependencies on input scanning. ^ static void wordchrs(struct vars *); */ static void wordchrs( struct vars *v) { struct state *left, *right; if (v->wordchrs != NULL) { NEXT(); /* for consistency */ return; } left = newstate(v->nfa); right = newstate(v->nfa); NOERR(); /* * Fine point: implemented with [::], and lexer will set REG_ULOCALE. */ lexword(v); NEXT(); assert(v->savenow != NULL && SEE('[')); bracket(v, left, right); assert((v->savenow != NULL && SEE(']')) || ISERR()); NEXT(); NOERR(); v->wordchrs = left; } /* - subre - allocate a subre ^ static struct subre *subre(struct vars *, int, int, struct state *, ^ struct state *); */ static struct subre * subre( struct vars *v, int op, int flags, struct state *begin, struct state *end) { struct subre *ret = v->treefree; if (ret != NULL) { v->treefree = ret->left; } else { ret = (struct subre *) MALLOC(sizeof(struct subre)); if (ret == NULL) { ERR(REG_ESPACE); return NULL; } ret->chain = v->treechain; v->treechain = ret; } assert(strchr("=b|.*(", op) != NULL); ret->op = op; ret->flags = flags; ret->id = 0; /* will be assigned later */ ret->subno = 0; ret->min = ret->max = 1; ret->left = NULL; ret->right = NULL; ret->begin = begin; ret->end = end; ZAPCNFA(ret->cnfa); return ret; } /* - freesubre - free a subRE subtree ^ static void freesubre(struct vars *, struct subre *); */ static void freesubre( struct vars *v, /* might be NULL */ struct subre *sr) { if (sr == NULL) { return; } if (sr->left != NULL) { freesubre(v, sr->left); } if (sr->right != NULL) { freesubre(v, sr->right); } freesrnode(v, sr); } /* - freesrnode - free one node in a subRE subtree ^ static void freesrnode(struct vars *, struct subre *); */ static void freesrnode( struct vars *v, /* might be NULL */ struct subre *sr) { if (sr == NULL) { return; } if (!NULLCNFA(sr->cnfa)) { freecnfa(&sr->cnfa); } sr->flags = 0; if (v != NULL && v->treechain != NULL) { /* we're still parsing, maybe we can reuse the subre */ sr->left = v->treefree; v->treefree = sr; } else { FREE(sr); } } /* - optst - optimize a subRE subtree ^ static void optst(struct vars *, struct subre *); */ static void optst( struct vars *v, struct subre *t) { /* * DGP (2007-11-13): I assume it was the programmer's intent to eventually * come back and add code to optimize subRE trees, but the routine coded * just spends effort traversing the tree and doing nothing. We can do * nothing with less effort. */ return; } /* - numst - number tree nodes (assigning "id" indexes) ^ static int numst(struct subre *, int); */ static int /* next number */ numst( struct subre *t, int start) /* starting point for subtree numbers */ { int i; assert(t != NULL); i = start; t->id = (short) i++; if (t->left != NULL) { i = numst(t->left, i); } if (t->right != NULL) { i = numst(t->right, i); } return i; } /* - markst - mark tree nodes as INUSE * Note: this is a great deal more subtle than it looks. During initial * parsing of a regex, all subres are linked into the treechain list; * discarded ones are also linked into the treefree list for possible reuse. * After we are done creating all subres required for a regex, we run markst() * then cleanst(), which results in discarding all subres not reachable from * v->tree. We then clear v->treechain, indicating that subres must be found * by descending from v->tree. This changes the behavior of freesubre(): it * will henceforth FREE() unwanted subres rather than sticking them into the * treefree list. (Doing that any earlier would result in dangling links in * the treechain list.) This all means that freev() will clean up correctly * if invoked before or after markst()+cleanst(); but it would not work if * called partway through this state conversion, so we mustn't error out * in or between these two functions. ^ static void markst(struct subre *); */ static void markst( struct subre *t) { assert(t != NULL); t->flags |= INUSE; if (t->left != NULL) { markst(t->left); } if (t->right != NULL) { markst(t->right); } } /* - cleanst - free any tree nodes not marked INUSE ^ static void cleanst(struct vars *); */ static void cleanst( struct vars *v) { struct subre *t; struct subre *next; for (t = v->treechain; t != NULL; t = next) { next = t->chain; if (!(t->flags&INUSE)) { FREE(t); } } v->treechain = NULL; v->treefree = NULL; /* just on general principles */ } /* - nfatree - turn a subRE subtree into a tree of compacted NFAs ^ static long nfatree(struct vars *, struct subre *, FILE *); */ static long /* optimize results from top node */ nfatree( struct vars *v, struct subre *t, FILE *f) /* for debug output */ { assert(t != NULL && t->begin != NULL); if (t->left != NULL) { (DISCARD) nfatree(v, t->left, f); } if (t->right != NULL) { (DISCARD) nfatree(v, t->right, f); } return nfanode(v, t, f); } /* - nfanode - do one NFA for nfatree ^ static long nfanode(struct vars *, struct subre *, FILE *); */ static long /* optimize results */ nfanode( struct vars *v, struct subre *t, FILE *f) /* for debug output */ { struct nfa *nfa; long ret = 0; char idbuf[50]; assert(t->begin != NULL); if (f != NULL) { fprintf(f, "\n\n\n========= TREE NODE %s ==========\n", stid(t, idbuf, sizeof(idbuf))); } nfa = newnfa(v, v->cm, v->nfa); NOERRZ(); dupnfa(nfa, t->begin, t->end, nfa->init, nfa->final); if (!ISERR()) { specialcolors(nfa); ret = optimize(nfa, f); } if (!ISERR()) { compact(nfa, &t->cnfa); } freenfa(nfa); return ret; } /* - newlacon - allocate a lookahead-constraint subRE ^ static int newlacon(struct vars *, struct state *, struct state *, int); */ static int /* lacon number */ newlacon( struct vars *v, struct state *begin, struct state *end, int pos) { int n; struct subre *newlacons; struct subre *sub; if (v->nlacons == 0) { n = 1; /* skip 0th */ newlacons = (struct subre *) MALLOC(2 * sizeof(struct subre)); } else { n = v->nlacons; newlacons = (struct subre *) REALLOC(v->lacons, (n + 1) * sizeof(struct subre)); } if (newlacons == NULL) { ERR(REG_ESPACE); return 0; } v->lacons = newlacons; v->nlacons = n + 1; sub = &v->lacons[n]; sub->begin = begin; sub->end = end; sub->subno = pos; ZAPCNFA(sub->cnfa); return n; } /* - freelacons - free lookahead-constraint subRE vector ^ static void freelacons(struct subre *, int); */ static void freelacons( struct subre *subs, int n) { struct subre *sub; int i; assert(n > 0); for (sub=subs+1, i=n-1; i>0; sub++, i--) { /* no 0th */ if (!NULLCNFA(sub->cnfa)) { freecnfa(&sub->cnfa); } } FREE(subs); } /* - rfree - free a whole RE (insides of regfree) ^ static void rfree(regex_t *); */ static void rfree( regex_t *re) { struct guts *g; if (re == NULL || re->re_magic != REMAGIC) { return; } re->re_magic = 0; /* invalidate RE */ g = (struct guts *) re->re_guts; re->re_guts = NULL; re->re_fns = NULL; if (g != NULL) { g->magic = 0; freecm(&g->cmap); if (g->tree != NULL) { freesubre(NULL, g->tree); } if (g->lacons != NULL) { freelacons(g->lacons, g->nlacons); } if (!NULLCNFA(g->search)) { freecnfa(&g->search); } FREE(g); } } /* - dump - dump an RE in human-readable form ^ static void dump(regex_t *, FILE *); */ static void dump( regex_t *re, FILE *f) { #ifdef REG_DEBUG struct guts *g; int i; if (re->re_magic != REMAGIC) { fprintf(f, "bad magic number (0x%x not 0x%x)\n", re->re_magic, REMAGIC); } if (re->re_guts == NULL) { fprintf(f, "NULL guts!!!\n"); return; } g = (struct guts *) re->re_guts; if (g->magic != GUTSMAGIC) { fprintf(f, "bad guts magic number (0x%x not 0x%x)\n", g->magic, GUTSMAGIC); } fprintf(f, "\n\n\n========= DUMP ==========\n"); fprintf(f, "nsub %d, info 0%lo, csize %d, ntree %d\n", (int) re->re_nsub, re->re_info, re->re_csize, g->ntree); dumpcolors(&g->cmap, f); if (!NULLCNFA(g->search)) { fprintf(f, "\nsearch:\n"); dumpcnfa(&g->search, f); } for (i = 1; i < g->nlacons; i++) { fprintf(f, "\nla%d (%s):\n", i, (g->lacons[i].subno) ? "positive" : "negative"); dumpcnfa(&g->lacons[i].cnfa, f); } fprintf(f, "\n"); dumpst(g->tree, f, 0); #endif } /* - dumpst - dump a subRE tree ^ static void dumpst(struct subre *, FILE *, int); */ static void dumpst( struct subre *t, FILE *f, int nfapresent) /* is the original NFA still around? */ { if (t == NULL) { fprintf(f, "null tree\n"); } else { stdump(t, f, nfapresent); } fflush(f); } /* - stdump - recursive guts of dumpst ^ static void stdump(struct subre *, FILE *, int); */ static void stdump( struct subre *t, FILE *f, int nfapresent) /* is the original NFA still around? */ { char idbuf[50]; fprintf(f, "%s. `%c'", stid(t, idbuf, sizeof(idbuf)), t->op); if (t->flags&LONGER) { fprintf(f, " longest"); } if (t->flags&SHORTER) { fprintf(f, " shortest"); } if (t->flags&MIXED) { fprintf(f, " hasmixed"); } if (t->flags&CAP) { fprintf(f, " hascapture"); } if (t->flags&BACKR) { fprintf(f, " hasbackref"); } if (!(t->flags&INUSE)) { fprintf(f, " UNUSED"); } if (t->subno != 0) { fprintf(f, " (#%d)", t->subno); } if (t->min != 1 || t->max != 1) { fprintf(f, " {%d,", t->min); if (t->max != DUPINF) { fprintf(f, "%d", t->max); } fprintf(f, "}"); } if (nfapresent) { fprintf(f, " %ld-%ld", (long)t->begin->no, (long)t->end->no); } if (t->left != NULL) { fprintf(f, " L:%s", stid(t->left, idbuf, sizeof(idbuf))); } if (t->right != NULL) { fprintf(f, " R:%s", stid(t->right, idbuf, sizeof(idbuf))); } if (!NULLCNFA(t->cnfa)) { fprintf(f, "\n"); dumpcnfa(&t->cnfa, f); } fprintf(f, "\n"); if (t->left != NULL) { stdump(t->left, f, nfapresent); } if (t->right != NULL) { stdump(t->right, f, nfapresent); } } /* - stid - identify a subtree node for dumping ^ static const char *stid(struct subre *, char *, size_t); */ static const char * /* points to buf or constant string */ stid( struct subre *t, char *buf, size_t bufsize) { /* * Big enough for hex int or decimal t->id? */ if (bufsize < sizeof(void*)*2 + 3 || bufsize < sizeof(t->id)*3 + 1) { return "unable"; } if (t->id != 0) { sprintf(buf, "%d", t->id); } else { sprintf(buf, "%p", t); } return buf; } #include "regc_lex.c" #include "regc_color.c" #include "regc_nfa.c" #include "regc_cvec.c" #include "regc_locale.c" /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclFileName.c0000644000175000017500000020410612663660065015535 0ustar sergeisergei/* * tclFileName.c -- * * This file contains routines for converting file names betwen native * and network form. * * Copyright (c) 1995-1998 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclRegexp.h" #include "tclFileSystem.h" /* For TclGetPathType() */ /* * The following variable is set in the TclPlatformInit call to one of: * TCL_PLATFORM_UNIX or TCL_PLATFORM_WINDOWS. */ TclPlatformType tclPlatform = TCL_PLATFORM_UNIX; /* * Prototypes for local procedures defined in this file: */ static const char * DoTildeSubst(Tcl_Interp *interp, const char *user, Tcl_DString *resultPtr); static const char * ExtractWinRoot(const char *path, Tcl_DString *resultPtr, int offset, Tcl_PathType *typePtr); static int SkipToChar(char **stringPtr, int match); static Tcl_Obj * SplitWinPath(const char *path); static Tcl_Obj * SplitUnixPath(const char *path); static int DoGlob(Tcl_Interp *interp, Tcl_Obj *resultPtr, const char *separators, Tcl_Obj *pathPtr, int flags, char *pattern, Tcl_GlobTypeData *types); /* * When there is no support for getting the block size of a file in a stat() * call, use this as a guess. Allow it to be overridden in the platform- * specific files. */ #if (!defined(HAVE_STRUCT_STAT_ST_BLKSIZE) && !defined(GUESSED_BLOCK_SIZE)) #define GUESSED_BLOCK_SIZE 1024 #endif /* *---------------------------------------------------------------------- * * SetResultLength -- * * Resets the result DString for ExtractWinRoot to accommodate * any NT extended path prefixes. * * Results: * None. * * Side effects: * May modify the Tcl_DString. *---------------------------------------------------------------------- */ static void SetResultLength( Tcl_DString *resultPtr, int offset, int extended) { Tcl_DStringSetLength(resultPtr, offset); if (extended == 2) { TclDStringAppendLiteral(resultPtr, "//?/UNC/"); } else if (extended == 1) { TclDStringAppendLiteral(resultPtr, "//?/"); } } /* *---------------------------------------------------------------------- * * ExtractWinRoot -- * * Matches the root portion of a Windows path and appends it to the * specified Tcl_DString. * * Results: * Returns the position in the path immediately after the root including * any trailing slashes. Appends a cleaned up version of the root to the * Tcl_DString at the specified offest. * * Side effects: * Modifies the specified Tcl_DString. * *---------------------------------------------------------------------- */ static const char * ExtractWinRoot( const char *path, /* Path to parse. */ Tcl_DString *resultPtr, /* Buffer to hold result. */ int offset, /* Offset in buffer where result should be * stored. */ Tcl_PathType *typePtr) /* Where to store pathType result */ { int extended = 0; if ( (path[0] == '/' || path[0] == '\\') && (path[1] == '/' || path[1] == '\\') && (path[2] == '?') && (path[3] == '/' || path[3] == '\\')) { extended = 1; path = path + 4; if (path[0] == 'U' && path[1] == 'N' && path[2] == 'C' && (path[3] == '/' || path[3] == '\\')) { extended = 2; path = path + 4; } } if (path[0] == '/' || path[0] == '\\') { /* * Might be a UNC or Vol-Relative path. */ const char *host, *share, *tail; int hlen, slen; if (path[1] != '/' && path[1] != '\\') { SetResultLength(resultPtr, offset, extended); *typePtr = TCL_PATH_VOLUME_RELATIVE; TclDStringAppendLiteral(resultPtr, "/"); return &path[1]; } host = &path[2]; /* * Skip separators. */ while (host[0] == '/' || host[0] == '\\') { host++; } for (hlen = 0; host[hlen];hlen++) { if (host[hlen] == '/' || host[hlen] == '\\') { break; } } if (host[hlen] == 0 || host[hlen+1] == 0) { /* * The path given is simply of the form '/foo', '//foo', * '/////foo' or the same with backslashes. If there is exactly * one leading '/' the path is volume relative (see filename man * page). If there are more than one, we are simply assuming they * are superfluous and we trim them away. (An alternative * interpretation would be that it is a host name, but we have * been documented that that is not the case). */ *typePtr = TCL_PATH_VOLUME_RELATIVE; TclDStringAppendLiteral(resultPtr, "/"); return &path[2]; } SetResultLength(resultPtr, offset, extended); share = &host[hlen]; /* * Skip separators. */ while (share[0] == '/' || share[0] == '\\') { share++; } for (slen=0; share[slen]; slen++) { if (share[slen] == '/' || share[slen] == '\\') { break; } } TclDStringAppendLiteral(resultPtr, "//"); Tcl_DStringAppend(resultPtr, host, hlen); TclDStringAppendLiteral(resultPtr, "/"); Tcl_DStringAppend(resultPtr, share, slen); tail = &share[slen]; /* * Skip separators. */ while (tail[0] == '/' || tail[0] == '\\') { tail++; } *typePtr = TCL_PATH_ABSOLUTE; return tail; } else if (*path && path[1] == ':') { /* * Might be a drive separator. */ SetResultLength(resultPtr, offset, extended); if (path[2] != '/' && path[2] != '\\') { *typePtr = TCL_PATH_VOLUME_RELATIVE; Tcl_DStringAppend(resultPtr, path, 2); return &path[2]; } else { const char *tail = &path[3]; /* * Skip separators. */ while (*tail && (tail[0] == '/' || tail[0] == '\\')) { tail++; } *typePtr = TCL_PATH_ABSOLUTE; Tcl_DStringAppend(resultPtr, path, 2); TclDStringAppendLiteral(resultPtr, "/"); return tail; } } else { int abs = 0; /* * Check for Windows devices. */ if ((path[0] == 'c' || path[0] == 'C') && (path[1] == 'o' || path[1] == 'O')) { if ((path[2] == 'm' || path[2] == 'M') && path[3] >= '1' && path[3] <= '9') { /* * May have match for 'com[1-9]:?', which is a serial port. */ if (path[4] == '\0') { abs = 4; } else if (path [4] == ':' && path[5] == '\0') { abs = 5; } } else if ((path[2] == 'n' || path[2] == 'N') && path[3] == '\0') { /* * Have match for 'con'. */ abs = 3; } } else if ((path[0] == 'l' || path[0] == 'L') && (path[1] == 'p' || path[1] == 'P') && (path[2] == 't' || path[2] == 'T')) { if (path[3] >= '1' && path[3] <= '9') { /* * May have match for 'lpt[1-9]:?' */ if (path[4] == '\0') { abs = 4; } else if (path [4] == ':' && path[5] == '\0') { abs = 5; } } } else if ((path[0] == 'p' || path[0] == 'P') && (path[1] == 'r' || path[1] == 'R') && (path[2] == 'n' || path[2] == 'N') && path[3] == '\0') { /* * Have match for 'prn'. */ abs = 3; } else if ((path[0] == 'n' || path[0] == 'N') && (path[1] == 'u' || path[1] == 'U') && (path[2] == 'l' || path[2] == 'L') && path[3] == '\0') { /* * Have match for 'nul'. */ abs = 3; } else if ((path[0] == 'a' || path[0] == 'A') && (path[1] == 'u' || path[1] == 'U') && (path[2] == 'x' || path[2] == 'X') && path[3] == '\0') { /* * Have match for 'aux'. */ abs = 3; } if (abs != 0) { *typePtr = TCL_PATH_ABSOLUTE; SetResultLength(resultPtr, offset, extended); Tcl_DStringAppend(resultPtr, path, abs); return path + abs; } } /* * Anything else is treated as relative. */ *typePtr = TCL_PATH_RELATIVE; return path; } /* *---------------------------------------------------------------------- * * Tcl_GetPathType -- * * Determines whether a given path is relative to the current directory, * relative to the current volume, or absolute. * * The objectified Tcl_FSGetPathType should be used in preference to this * function (as you can see below, this is just a wrapper around that * other function). * * Results: * Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or * TCL_PATH_VOLUME_RELATIVE. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_PathType Tcl_GetPathType( const char *path) { Tcl_PathType type; Tcl_Obj *tempObj = Tcl_NewStringObj(path,-1); Tcl_IncrRefCount(tempObj); type = Tcl_FSGetPathType(tempObj); Tcl_DecrRefCount(tempObj); return type; } /* *---------------------------------------------------------------------- * * TclpGetNativePathType -- * * Determines whether a given path is relative to the current directory, * relative to the current volume, or absolute, but ONLY FOR THE NATIVE * FILESYSTEM. This function is called from tclIOUtil.c (but needs to be * here due to its dependence on static variables/functions in this * file). The exported function Tcl_FSGetPathType should be used by * extensions. * * Note that '~' paths are always considered TCL_PATH_ABSOLUTE, even * though expanding the '~' could lead to any possible path type. This * function should therefore be considered a low-level, string * manipulation function only -- it doesn't actually do any expansion in * making its determination. * * Results: * Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or * TCL_PATH_VOLUME_RELATIVE. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_PathType TclpGetNativePathType( Tcl_Obj *pathPtr, /* Native path of interest */ int *driveNameLengthPtr, /* Returns length of drive, if non-NULL and * path was absolute */ Tcl_Obj **driveNameRef) { Tcl_PathType type = TCL_PATH_ABSOLUTE; int pathLen; const char *path = Tcl_GetStringFromObj(pathPtr, &pathLen); if (path[0] == '~') { /* * This case is common to all platforms. Paths that begin with ~ are * absolute. */ if (driveNameLengthPtr != NULL) { const char *end = path + 1; while ((*end != '\0') && (*end != '/')) { end++; } *driveNameLengthPtr = end - path; } } else { switch (tclPlatform) { case TCL_PLATFORM_UNIX: { const char *origPath = path; /* * Paths that begin with / are absolute. */ if (path[0] == '/') { ++path; #if defined(__CYGWIN__) || defined(__QNX__) /* * Check for "//" network path prefix */ if ((*path == '/') && path[1] && (path[1] != '/')) { path += 2; while (*path && *path != '/') { ++path; } #if defined(__CYGWIN__) /* UNC paths need to be followed by a share name */ if (*path++ && (*path && *path != '/')) { ++path; while (*path && *path != '/') { ++path; } } else { path = origPath + 1; } #endif } #endif if (driveNameLengthPtr != NULL) { /* * We need this addition in case the QNX or Cygwin code was used. */ *driveNameLengthPtr = (path - origPath); } } else { type = TCL_PATH_RELATIVE; } break; } case TCL_PLATFORM_WINDOWS: { Tcl_DString ds; const char *rootEnd; Tcl_DStringInit(&ds); rootEnd = ExtractWinRoot(path, &ds, 0, &type); if ((rootEnd != path) && (driveNameLengthPtr != NULL)) { *driveNameLengthPtr = rootEnd - path; if (driveNameRef != NULL) { *driveNameRef = TclDStringToObj(&ds); Tcl_IncrRefCount(*driveNameRef); } } Tcl_DStringFree(&ds); break; } } } return type; } /* *--------------------------------------------------------------------------- * * TclpNativeSplitPath -- * * This function takes the given Tcl_Obj, which should be a valid path, * and returns a Tcl List object containing each segment of that path as * an element. * * Note this function currently calls the older Split(Plat)Path * functions, which require more memory allocation than is desirable. * * Results: * Returns list object with refCount of zero. If the passed in lenPtr is * non-NULL, we use it to return the number of elements in the returned * list. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj * TclpNativeSplitPath( Tcl_Obj *pathPtr, /* Path to split. */ int *lenPtr) /* int to store number of path elements. */ { Tcl_Obj *resultPtr = NULL; /* Needed only to prevent gcc warnings. */ /* * Perform platform specific splitting. */ switch (tclPlatform) { case TCL_PLATFORM_UNIX: resultPtr = SplitUnixPath(Tcl_GetString(pathPtr)); break; case TCL_PLATFORM_WINDOWS: resultPtr = SplitWinPath(Tcl_GetString(pathPtr)); break; } /* * Compute the number of elements in the result. */ if (lenPtr != NULL) { Tcl_ListObjLength(NULL, resultPtr, lenPtr); } return resultPtr; } /* *---------------------------------------------------------------------- * * Tcl_SplitPath -- * * Split a path into a list of path components. The first element of the * list will have the same path type as the original path. * * Results: * Returns a standard Tcl result. The interpreter result contains a list * of path components. *argvPtr will be filled in with the address of an * array whose elements point to the elements of path, in order. * *argcPtr will get filled in with the number of valid elements in the * array. A single block of memory is dynamically allocated to hold both * the argv array and a copy of the path elements. The caller must * eventually free this memory by calling ckfree() on *argvPtr. Note: * *argvPtr and *argcPtr are only modified if the procedure returns * normally. * * Side effects: * Allocates memory. * *---------------------------------------------------------------------- */ void Tcl_SplitPath( const char *path, /* Pointer to string containing a path. */ int *argcPtr, /* Pointer to location to fill in with the * number of elements in the path. */ const char ***argvPtr) /* Pointer to place to store pointer to array * of pointers to path elements. */ { Tcl_Obj *resultPtr = NULL; /* Needed only to prevent gcc warnings. */ Tcl_Obj *tmpPtr, *eltPtr; int i, size, len; char *p; const char *str; /* * Perform the splitting, using objectified, vfs-aware code. */ tmpPtr = Tcl_NewStringObj(path, -1); Tcl_IncrRefCount(tmpPtr); resultPtr = Tcl_FSSplitPath(tmpPtr, argcPtr); Tcl_IncrRefCount(resultPtr); Tcl_DecrRefCount(tmpPtr); /* * Calculate space required for the result. */ size = 1; for (i = 0; i < *argcPtr; i++) { Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr); Tcl_GetStringFromObj(eltPtr, &len); size += len + 1; } /* * Allocate a buffer large enough to hold the contents of all of the list * plus the argv pointers and the terminating NULL pointer. */ *argvPtr = ckalloc((((*argcPtr) + 1) * sizeof(char *)) + size); /* * Position p after the last argv pointer and copy the contents of the * list in, piece by piece. */ p = (char *) &(*argvPtr)[(*argcPtr) + 1]; for (i = 0; i < *argcPtr; i++) { Tcl_ListObjIndex(NULL, resultPtr, i, &eltPtr); str = Tcl_GetStringFromObj(eltPtr, &len); memcpy(p, str, (size_t) len+1); p += len+1; } /* * Now set up the argv pointers. */ p = (char *) &(*argvPtr)[(*argcPtr) + 1]; for (i = 0; i < *argcPtr; i++) { (*argvPtr)[i] = p; for (; *(p++)!='\0'; ); } (*argvPtr)[i] = NULL; /* * Free the result ptr given to us by Tcl_FSSplitPath */ Tcl_DecrRefCount(resultPtr); } /* *---------------------------------------------------------------------- * * SplitUnixPath -- * * This routine is used by Tcl_(FS)SplitPath to handle splitting Unix * paths. * * Results: * Returns a newly allocated Tcl list object. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Tcl_Obj * SplitUnixPath( const char *path) /* Pointer to string containing a path. */ { int length; const char *origPath = path, *elementStart; Tcl_Obj *result = Tcl_NewObj(); /* * Deal with the root directory as a special case. */ if (*path == '/') { Tcl_Obj *rootElt; ++path; #if defined(__CYGWIN__) || defined(__QNX__) /* * Check for "//" network path prefix */ if ((*path == '/') && path[1] && (path[1] != '/')) { path += 2; while (*path && *path != '/') { ++path; } #if defined(__CYGWIN__) /* UNC paths need to be followed by a share name */ if (*path++ && (*path && *path != '/')) { ++path; while (*path && *path != '/') { ++path; } } else { path = origPath + 1; } #endif } #endif rootElt = Tcl_NewStringObj(origPath, path - origPath); Tcl_ListObjAppendElement(NULL, result, rootElt); while (*path == '/') { ++path; } } /* * Split on slashes. Embedded elements that start with tilde will be * prefixed with "./" so they are not affected by tilde substitution. */ for (;;) { elementStart = path; while ((*path != '\0') && (*path != '/')) { path++; } length = path - elementStart; if (length > 0) { Tcl_Obj *nextElt; if ((elementStart[0] == '~') && (elementStart != origPath)) { TclNewLiteralStringObj(nextElt, "./"); Tcl_AppendToObj(nextElt, elementStart, length); } else { nextElt = Tcl_NewStringObj(elementStart, length); } Tcl_ListObjAppendElement(NULL, result, nextElt); } if (*path++ == '\0') { break; } } return result; } /* *---------------------------------------------------------------------- * * SplitWinPath -- * * This routine is used by Tcl_(FS)SplitPath to handle splitting Windows * paths. * * Results: * Returns a newly allocated Tcl list object. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Tcl_Obj * SplitWinPath( const char *path) /* Pointer to string containing a path. */ { int length; const char *p, *elementStart; Tcl_PathType type = TCL_PATH_ABSOLUTE; Tcl_DString buf; Tcl_Obj *result = Tcl_NewObj(); Tcl_DStringInit(&buf); p = ExtractWinRoot(path, &buf, 0, &type); /* * Terminate the root portion, if we matched something. */ if (p != path) { Tcl_ListObjAppendElement(NULL, result, TclDStringToObj(&buf)); } Tcl_DStringFree(&buf); /* * Split on slashes. Embedded elements that start with tilde or a drive * letter will be prefixed with "./" so they are not affected by tilde * substitution. */ do { elementStart = p; while ((*p != '\0') && (*p != '/') && (*p != '\\')) { p++; } length = p - elementStart; if (length > 0) { Tcl_Obj *nextElt; if ((elementStart != path) && ((elementStart[0] == '~') || (isalpha(UCHAR(elementStart[0])) && elementStart[1] == ':'))) { TclNewLiteralStringObj(nextElt, "./"); Tcl_AppendToObj(nextElt, elementStart, length); } else { nextElt = Tcl_NewStringObj(elementStart, length); } Tcl_ListObjAppendElement(NULL, result, nextElt); } } while (*p++ != '\0'); return result; } /* *--------------------------------------------------------------------------- * * Tcl_FSJoinToPath -- * * This function takes the given object, which should usually be a valid * path or NULL, and joins onto it the array of paths segments given. * * The objects in the array given will temporarily have their refCount * increased by one, and then decreased by one when this function exits * (which means if they had zero refCount when we were called, they will * be freed). * * Results: * Returns object owned by the caller (which should increment its * refCount) - typically an object with refCount of zero. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSJoinToPath( Tcl_Obj *pathPtr, /* Valid path or NULL. */ int objc, /* Number of array elements to join */ Tcl_Obj *const objv[]) /* Path elements to join. */ { if (pathPtr == NULL) { return TclJoinPath(objc, objv); } if (objc == 0) { return TclJoinPath(1, &pathPtr); } if (objc == 1) { Tcl_Obj *pair[2]; pair[0] = pathPtr; pair[1] = objv[0]; return TclJoinPath(2, pair); } else { int elemc = objc + 1; Tcl_Obj *ret, **elemv = ckalloc(elemc*sizeof(Tcl_Obj *)); elemv[0] = pathPtr; memcpy(elemv+1, objv, objc*sizeof(Tcl_Obj *)); ret = TclJoinPath(elemc, elemv); ckfree(elemv); return ret; } } /* *--------------------------------------------------------------------------- * * TclpNativeJoinPath -- * * 'prefix' is absolute, 'joining' is relative to prefix. * * Results: * modifies prefix * * Side effects: * None. * *--------------------------------------------------------------------------- */ void TclpNativeJoinPath( Tcl_Obj *prefix, const char *joining) { int length, needsSep; char *dest; const char *p; const char *start; start = Tcl_GetStringFromObj(prefix, &length); /* * Remove the ./ from tilde prefixed elements, and drive-letter prefixed * elements on Windows, unless it is the first component. */ p = joining; if (length != 0) { if ((p[0] == '.') && (p[1] == '/') && ((p[2] == '~') || (tclPlatform==TCL_PLATFORM_WINDOWS && isalpha(UCHAR(p[2])) && (p[3] == ':')))) { p += 2; } } if (*p == '\0') { return; } switch (tclPlatform) { case TCL_PLATFORM_UNIX: /* * Append a separator if needed. */ if (length > 0 && (start[length-1] != '/')) { Tcl_AppendToObj(prefix, "/", 1); Tcl_GetStringFromObj(prefix, &length); } needsSep = 0; /* * Append the element, eliminating duplicate and trailing slashes. */ Tcl_SetObjLength(prefix, length + (int) strlen(p)); dest = Tcl_GetString(prefix) + length; for (; *p != '\0'; p++) { if (*p == '/') { while (p[1] == '/') { p++; } if (p[1] != '\0' && needsSep) { *dest++ = '/'; } } else { *dest++ = *p; needsSep = 1; } } length = dest - Tcl_GetString(prefix); Tcl_SetObjLength(prefix, length); break; case TCL_PLATFORM_WINDOWS: /* * Check to see if we need to append a separator. */ if ((length > 0) && (start[length-1] != '/') && (start[length-1] != ':')) { Tcl_AppendToObj(prefix, "/", 1); Tcl_GetStringFromObj(prefix, &length); } needsSep = 0; /* * Append the element, eliminating duplicate and trailing slashes. */ Tcl_SetObjLength(prefix, length + (int) strlen(p)); dest = Tcl_GetString(prefix) + length; for (; *p != '\0'; p++) { if ((*p == '/') || (*p == '\\')) { while ((p[1] == '/') || (p[1] == '\\')) { p++; } if ((p[1] != '\0') && needsSep) { *dest++ = '/'; } } else { *dest++ = *p; needsSep = 1; } } length = dest - Tcl_GetString(prefix); Tcl_SetObjLength(prefix, length); break; } return; } /* *---------------------------------------------------------------------- * * Tcl_JoinPath -- * * Combine a list of paths in a platform specific manner. The function * 'Tcl_FSJoinPath' should be used in preference where possible. * * Results: * Appends the joined path to the end of the specified Tcl_DString * returning a pointer to the resulting string. Note that the * Tcl_DString must already be initialized. * * Side effects: * Modifies the Tcl_DString. * *---------------------------------------------------------------------- */ char * Tcl_JoinPath( int argc, const char *const *argv, Tcl_DString *resultPtr) /* Pointer to previously initialized DString */ { int i, len; Tcl_Obj *listObj = Tcl_NewObj(); Tcl_Obj *resultObj; const char *resultStr; /* * Build the list of paths. */ for (i = 0; i < argc; i++) { Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewStringObj(argv[i], -1)); } /* * Ask the objectified code to join the paths. */ Tcl_IncrRefCount(listObj); resultObj = Tcl_FSJoinPath(listObj, argc); Tcl_IncrRefCount(resultObj); Tcl_DecrRefCount(listObj); /* * Store the result. */ resultStr = Tcl_GetStringFromObj(resultObj, &len); Tcl_DStringAppend(resultPtr, resultStr, len); Tcl_DecrRefCount(resultObj); /* * Return a pointer to the result. */ return Tcl_DStringValue(resultPtr); } /* *--------------------------------------------------------------------------- * * Tcl_TranslateFileName -- * * Converts a file name into a form usable by the native system * interfaces. If the name starts with a tilde, it will produce a name * where the tilde and following characters have been replaced by the * home directory location for the named user. * * Results: * The return value is a pointer to a string containing the name after * tilde substitution. If there was no tilde substitution, the return * value is a pointer to a copy of the original string. If there was an * error in processing the name, then an error message is left in the * interp's result (if interp was not NULL) and the return value is NULL. * Space for the return value is allocated in bufferPtr; the caller must * call Tcl_DStringFree() to free the space if the return value was not * NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * Tcl_TranslateFileName( Tcl_Interp *interp, /* Interpreter in which to store error message * (if necessary). */ const char *name, /* File name, which may begin with "~" (to * indicate current user's home directory) or * "~" (to indicate any user's home * directory). */ Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with * name after tilde substitution. */ { Tcl_Obj *path = Tcl_NewStringObj(name, -1); Tcl_Obj *transPtr; Tcl_IncrRefCount(path); transPtr = Tcl_FSGetTranslatedPath(interp, path); if (transPtr == NULL) { Tcl_DecrRefCount(path); return NULL; } Tcl_DStringInit(bufferPtr); TclDStringAppendObj(bufferPtr, transPtr); Tcl_DecrRefCount(path); Tcl_DecrRefCount(transPtr); /* * Convert forward slashes to backslashes in Windows paths because some * system interfaces don't accept forward slashes. */ if (tclPlatform == TCL_PLATFORM_WINDOWS) { register char *p; for (p = Tcl_DStringValue(bufferPtr); *p != '\0'; p++) { if (*p == '/') { *p = '\\'; } } } return Tcl_DStringValue(bufferPtr); } /* *---------------------------------------------------------------------- * * TclGetExtension -- * * This function returns a pointer to the beginning of the extension part * of a file name. * * Results: * Returns a pointer into name which indicates where the extension * starts. If there is no extension, returns NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * TclGetExtension( const char *name) /* File name to parse. */ { const char *p, *lastSep; /* * First find the last directory separator. */ lastSep = NULL; /* Needed only to prevent gcc warnings. */ switch (tclPlatform) { case TCL_PLATFORM_UNIX: lastSep = strrchr(name, '/'); break; case TCL_PLATFORM_WINDOWS: lastSep = NULL; for (p = name; *p != '\0'; p++) { if (strchr("/\\:", *p) != NULL) { lastSep = p; } } break; } p = strrchr(name, '.'); if ((p != NULL) && (lastSep != NULL) && (lastSep > p)) { p = NULL; } /* * In earlier versions, we used to back up to the first period in a series * so that "foo..o" would be split into "foo" and "..o". This is a * confusing and usually incorrect behavior, so now we split at the last * period in the name. */ return p; } /* *---------------------------------------------------------------------- * * DoTildeSubst -- * * Given a string following a tilde, this routine returns the * corresponding home directory. * * Results: * The result is a pointer to a static string containing the home * directory in native format. If there was an error in processing the * substitution, then an error message is left in the interp's result and * the return value is NULL. On success, the results are appended to * resultPtr, and the contents of resultPtr are returned. * * Side effects: * Information may be left in resultPtr. * *---------------------------------------------------------------------- */ static const char * DoTildeSubst( Tcl_Interp *interp, /* Interpreter in which to store error message * (if necessary). */ const char *user, /* Name of user whose home directory should be * substituted, or "" for current user. */ Tcl_DString *resultPtr) /* Initialized DString filled with name after * tilde substitution. */ { const char *dir; if (*user == '\0') { Tcl_DString dirString; dir = TclGetEnv("HOME", &dirString); if (dir == NULL) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "couldn't find HOME environment " "variable to expand path", -1)); Tcl_SetErrorCode(interp, "TCL", "FILENAME", "NO_HOME", NULL); } return NULL; } Tcl_JoinPath(1, &dir, resultPtr); Tcl_DStringFree(&dirString); } else if (TclpGetUserHome(user, resultPtr) == NULL) { if (interp) { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "user \"%s\" doesn't exist", user)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "USER", user, NULL); } return NULL; } return Tcl_DStringValue(resultPtr); } /* *---------------------------------------------------------------------- * * Tcl_GlobObjCmd -- * * This procedure is invoked to process the "glob" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_GlobObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int index, i, globFlags, length, join, dir, result; char *string; const char *separators; Tcl_Obj *typePtr, *look; Tcl_Obj *pathOrDir = NULL; Tcl_DString prefix; static const char *const options[] = { "-directory", "-join", "-nocomplain", "-path", "-tails", "-types", "--", NULL }; enum options { GLOB_DIR, GLOB_JOIN, GLOB_NOCOMPLAIN, GLOB_PATH, GLOB_TAILS, GLOB_TYPE, GLOB_LAST }; enum pathDirOptions {PATH_NONE = -1 , PATH_GENERAL = 0, PATH_DIR = 1}; Tcl_GlobTypeData *globTypes = NULL; globFlags = 0; join = 0; dir = PATH_NONE; typePtr = NULL; for (i = 1; i < objc; i++) { if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index) != TCL_OK) { string = Tcl_GetStringFromObj(objv[i], &length); if (string[0] == '-') { /* * It looks like the command contains an option so signal an * error. */ return TCL_ERROR; } else { /* * This clearly isn't an option; assume it's the first glob * pattern. We must clear the error. */ Tcl_ResetResult(interp); break; } } switch (index) { case GLOB_NOCOMPLAIN: /* -nocomplain */ globFlags |= TCL_GLOBMODE_NO_COMPLAIN; break; case GLOB_DIR: /* -dir */ if (i == (objc-1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing argument to \"-directory\"", -1)); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); return TCL_ERROR; } if (dir != PATH_NONE) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-directory\" cannot be used with \"-path\"", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", "BADOPTIONCOMBINATION", NULL); return TCL_ERROR; } dir = PATH_DIR; globFlags |= TCL_GLOBMODE_DIR; pathOrDir = objv[i+1]; i++; break; case GLOB_JOIN: /* -join */ join = 1; break; case GLOB_TAILS: /* -tails */ globFlags |= TCL_GLOBMODE_TAILS; break; case GLOB_PATH: /* -path */ if (i == (objc-1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing argument to \"-path\"", -1)); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); return TCL_ERROR; } if (dir != PATH_NONE) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-path\" cannot be used with \"-directory\"", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", "BADOPTIONCOMBINATION", NULL); return TCL_ERROR; } dir = PATH_GENERAL; pathOrDir = objv[i+1]; i++; break; case GLOB_TYPE: /* -types */ if (i == (objc-1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "missing argument to \"-types\"", -1)); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL); return TCL_ERROR; } typePtr = objv[i+1]; if (Tcl_ListObjLength(interp, typePtr, &length) != TCL_OK) { return TCL_ERROR; } i++; break; case GLOB_LAST: /* -- */ i++; goto endOfForLoop; } } endOfForLoop: if ((globFlags & TCL_GLOBMODE_TAILS) && (pathOrDir == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-tails\" must be used with either " "\"-directory\" or \"-path\"", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", "BADOPTIONCOMBINATION", NULL); return TCL_ERROR; } separators = NULL; /* lint. */ switch (tclPlatform) { case TCL_PLATFORM_UNIX: separators = "/"; break; case TCL_PLATFORM_WINDOWS: separators = "/\\:"; break; } if (dir == PATH_GENERAL) { int pathlength; const char *last; const char *first = Tcl_GetStringFromObj(pathOrDir,&pathlength); /* * Find the last path separator in the path */ last = first + pathlength; for (; last != first; last--) { if (strchr(separators, *(last-1)) != NULL) { break; } } if (last == first + pathlength) { /* * It's really a directory. */ dir = PATH_DIR; } else { Tcl_DString pref; char *search, *find; Tcl_DStringInit(&pref); if (last == first) { /* * The whole thing is a prefix. This means we must remove any * 'tails' flag too, since it is irrelevant now (the same * effect will happen without it), but in particular its use * in TclGlob requires a non-NULL pathOrDir. */ Tcl_DStringAppend(&pref, first, -1); globFlags &= ~TCL_GLOBMODE_TAILS; pathOrDir = NULL; } else { /* * Have to split off the end. */ Tcl_DStringAppend(&pref, last, first+pathlength-last); pathOrDir = Tcl_NewStringObj(first, last-first-1); /* * We must ensure that we haven't cut off too much, and turned * a valid path like '/' or 'C:/' into an incorrect path like * '' or 'C:'. The way we do this is to add a separator if * there are none presently in the prefix. */ if (strpbrk(Tcl_GetString(pathOrDir), "\\/") == NULL) { Tcl_AppendToObj(pathOrDir, last-1, 1); } } /* * Need to quote 'prefix'. */ Tcl_DStringInit(&prefix); search = Tcl_DStringValue(&pref); while ((find = (strpbrk(search, "\\[]*?{}"))) != NULL) { Tcl_DStringAppend(&prefix, search, find-search); TclDStringAppendLiteral(&prefix, "\\"); Tcl_DStringAppend(&prefix, find, 1); search = find+1; if (*search == '\0') { break; } } if (*search != '\0') { Tcl_DStringAppend(&prefix, search, -1); } Tcl_DStringFree(&pref); } } if (pathOrDir != NULL) { Tcl_IncrRefCount(pathOrDir); } if (typePtr != NULL) { /* * The rest of the possible type arguments (except 'd') are platform * specific. We don't complain when they are used on an incompatible * platform. */ Tcl_ListObjLength(interp, typePtr, &length); if (length <= 0) { goto skipTypes; } globTypes = TclStackAlloc(interp, sizeof(Tcl_GlobTypeData)); globTypes->type = 0; globTypes->perm = 0; globTypes->macType = NULL; globTypes->macCreator = NULL; while (--length >= 0) { int len; const char *str; Tcl_ListObjIndex(interp, typePtr, length, &look); str = Tcl_GetStringFromObj(look, &len); if (strcmp("readonly", str) == 0) { globTypes->perm |= TCL_GLOB_PERM_RONLY; } else if (strcmp("hidden", str) == 0) { globTypes->perm |= TCL_GLOB_PERM_HIDDEN; } else if (len == 1) { switch (str[0]) { case 'r': globTypes->perm |= TCL_GLOB_PERM_R; break; case 'w': globTypes->perm |= TCL_GLOB_PERM_W; break; case 'x': globTypes->perm |= TCL_GLOB_PERM_X; break; case 'b': globTypes->type |= TCL_GLOB_TYPE_BLOCK; break; case 'c': globTypes->type |= TCL_GLOB_TYPE_CHAR; break; case 'd': globTypes->type |= TCL_GLOB_TYPE_DIR; break; case 'p': globTypes->type |= TCL_GLOB_TYPE_PIPE; break; case 'f': globTypes->type |= TCL_GLOB_TYPE_FILE; break; case 'l': globTypes->type |= TCL_GLOB_TYPE_LINK; break; case 's': globTypes->type |= TCL_GLOB_TYPE_SOCK; break; default: goto badTypesArg; } } else if (len == 4) { /* * This is assumed to be a MacOS file type. */ if (globTypes->macType != NULL) { goto badMacTypesArg; } globTypes->macType = look; Tcl_IncrRefCount(look); } else { Tcl_Obj *item; if ((Tcl_ListObjLength(NULL, look, &len) == TCL_OK) && (len == 3)) { Tcl_ListObjIndex(interp, look, 0, &item); if (!strcmp("macintosh", Tcl_GetString(item))) { Tcl_ListObjIndex(interp, look, 1, &item); if (!strcmp("type", Tcl_GetString(item))) { Tcl_ListObjIndex(interp, look, 2, &item); if (globTypes->macType != NULL) { goto badMacTypesArg; } globTypes->macType = item; Tcl_IncrRefCount(item); continue; } else if (!strcmp("creator", Tcl_GetString(item))) { Tcl_ListObjIndex(interp, look, 2, &item); if (globTypes->macCreator != NULL) { goto badMacTypesArg; } globTypes->macCreator = item; Tcl_IncrRefCount(item); continue; } } } /* * Error cases. We reset the 'join' flag to zero, since we * haven't yet made use of it. */ badTypesArg: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad argument to \"-types\": %s", Tcl_GetString(look))); Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "BAD", NULL); result = TCL_ERROR; join = 0; goto endOfGlob; badMacTypesArg: Tcl_SetObjResult(interp, Tcl_NewStringObj( "only one MacOS type or creator argument" " to \"-types\" allowed", -1)); result = TCL_ERROR; Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "BAD", NULL); join = 0; goto endOfGlob; } } } skipTypes: /* * Now we perform the actual glob below. This may involve joining together * the pattern arguments, dealing with particular file types etc. We use a * 'goto' to ensure we free any memory allocated along the way. */ objc -= i; objv += i; result = TCL_OK; if (join) { if (dir != PATH_GENERAL) { Tcl_DStringInit(&prefix); } for (i = 0; i < objc; i++) { TclDStringAppendObj(&prefix, objv[i]); if (i != objc -1) { Tcl_DStringAppend(&prefix, separators, 1); } } if (TclGlob(interp, Tcl_DStringValue(&prefix), pathOrDir, globFlags, globTypes) != TCL_OK) { result = TCL_ERROR; goto endOfGlob; } } else if (dir == PATH_GENERAL) { Tcl_DString str; for (i = 0; i < objc; i++) { Tcl_DStringInit(&str); if (dir == PATH_GENERAL) { TclDStringAppendDString(&str, &prefix); } TclDStringAppendObj(&str, objv[i]); if (TclGlob(interp, Tcl_DStringValue(&str), pathOrDir, globFlags, globTypes) != TCL_OK) { result = TCL_ERROR; Tcl_DStringFree(&str); goto endOfGlob; } } Tcl_DStringFree(&str); } else { for (i = 0; i < objc; i++) { string = Tcl_GetString(objv[i]); if (TclGlob(interp, string, pathOrDir, globFlags, globTypes) != TCL_OK) { result = TCL_ERROR; goto endOfGlob; } } } if ((globFlags & TCL_GLOBMODE_NO_COMPLAIN) == 0) { if (Tcl_ListObjLength(interp, Tcl_GetObjResult(interp), &length) != TCL_OK) { /* * This should never happen. Maybe we should be more dramatic. */ result = TCL_ERROR; goto endOfGlob; } if (length == 0) { Tcl_Obj *errorMsg = Tcl_ObjPrintf("no files matched glob pattern%s \"", (join || (objc == 1)) ? "" : "s"); if (join) { Tcl_AppendToObj(errorMsg, Tcl_DStringValue(&prefix), -1); } else { const char *sep = ""; for (i = 0; i < objc; i++) { Tcl_AppendPrintfToObj(errorMsg, "%s%s", sep, Tcl_GetString(objv[i])); sep = " "; } } Tcl_AppendToObj(errorMsg, "\"", -1); Tcl_SetObjResult(interp, errorMsg); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", "NOMATCH", NULL); result = TCL_ERROR; } } endOfGlob: if (join || (dir == PATH_GENERAL)) { Tcl_DStringFree(&prefix); } if (pathOrDir != NULL) { Tcl_DecrRefCount(pathOrDir); } if (globTypes != NULL) { if (globTypes->macType != NULL) { Tcl_DecrRefCount(globTypes->macType); } if (globTypes->macCreator != NULL) { Tcl_DecrRefCount(globTypes->macCreator); } TclStackFree(interp, globTypes); } return result; } /* *---------------------------------------------------------------------- * * TclGlob -- * * This procedure prepares arguments for the DoGlob call. It sets the * separator string based on the platform, performs * tilde substitution, * and calls DoGlob. * * The interpreter's result, on entry to this function, must be a valid * Tcl list (e.g. it could be empty), since we will lappend any new * results to that list. If it is not a valid list, this function will * fail to do anything very meaningful. * * Note that if globFlags contains 'TCL_GLOBMODE_TAILS' then pathPrefix * cannot be NULL (it is only allowed with -dir or -path). * * Results: * The return value is a standard Tcl result indicating whether an error * occurred in globbing. After a normal return the result in interp (set * by DoGlob) holds all of the file names given by the pattern and * pathPrefix arguments. After an error the result in interp will hold * an error message. * * Side effects: * The 'pattern' is written to. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int TclGlob( Tcl_Interp *interp, /* Interpreter for returning error message or * appending list of matching file names. */ char *pattern, /* Glob pattern to match. Must not refer to a * static string. */ Tcl_Obj *pathPrefix, /* Path prefix to glob pattern, if non-null, * which is considered literally. */ int globFlags, /* Stores or'ed combination of flags */ Tcl_GlobTypeData *types) /* Struct containing acceptable types. May be * NULL. */ { const char *separators; const char *head; char *tail, *start; int result; Tcl_Obj *filenamesObj, *savedResultObj; separators = NULL; /* lint. */ switch (tclPlatform) { case TCL_PLATFORM_UNIX: separators = "/"; break; case TCL_PLATFORM_WINDOWS: separators = "/\\:"; break; } if (pathPrefix == NULL) { char c; Tcl_DString buffer; Tcl_DStringInit(&buffer); start = pattern; /* * Perform tilde substitution, if needed. */ if (start[0] == '~') { /* * Find the first path separator after the tilde. */ for (tail = start; *tail != '\0'; tail++) { if (*tail == '\\') { if (strchr(separators, tail[1]) != NULL) { break; } } else if (strchr(separators, *tail) != NULL) { break; } } /* * Determine the home directory for the specified user. */ c = *tail; *tail = '\0'; head = DoTildeSubst(interp, start+1, &buffer); *tail = c; if (head == NULL) { return TCL_ERROR; } if (head != Tcl_DStringValue(&buffer)) { Tcl_DStringAppend(&buffer, head, -1); } pathPrefix = TclDStringToObj(&buffer); Tcl_IncrRefCount(pathPrefix); globFlags |= TCL_GLOBMODE_DIR; if (c != '\0') { tail++; } Tcl_DStringFree(&buffer); } else { tail = pattern; } } else { Tcl_IncrRefCount(pathPrefix); tail = pattern; } /* * Handling empty path prefixes with glob patterns like 'C:' or * 'c:////////' is a pain on Windows if we leave it too late, since these * aren't really patterns at all! We therefore check the head of the * pattern now for such cases, if we don't have an unquoted prefix yet. * * Similarly on Unix with '/' at the head of the pattern -- it just * indicates the root volume, so we treat it as such. */ if (tclPlatform == TCL_PLATFORM_WINDOWS) { if (pathPrefix == NULL && tail[0] != '\0' && tail[1] == ':') { char *p = tail + 1; pathPrefix = Tcl_NewStringObj(tail, 1); while (*p != '\0') { char c = p[1]; if (*p == '\\') { if (strchr(separators, c) != NULL) { if (c == '\\') { c = '/'; } Tcl_AppendToObj(pathPrefix, &c, 1); p++; } else { break; } } else if (strchr(separators, *p) != NULL) { Tcl_AppendToObj(pathPrefix, p, 1); } else { break; } p++; } tail = p; Tcl_IncrRefCount(pathPrefix); } else if (pathPrefix == NULL && (tail[0] == '/' || (tail[0] == '\\' && tail[1] == '\\'))) { int driveNameLen; Tcl_Obj *driveName; Tcl_Obj *temp = Tcl_NewStringObj(tail, -1); Tcl_IncrRefCount(temp); switch (TclGetPathType(temp, NULL, &driveNameLen, &driveName)) { case TCL_PATH_VOLUME_RELATIVE: { /* * Volume relative path which is equivalent to a path in the * root of the cwd's volume. We will actually return * non-volume-relative paths here. i.e. 'glob /foo*' will * return 'C:/foobar'. This is much the same as globbing for a * path with '\\' will return one with '/' on Windows. */ Tcl_Obj *cwd = Tcl_FSGetCwd(interp); if (cwd == NULL) { Tcl_DecrRefCount(temp); return TCL_ERROR; } pathPrefix = Tcl_NewStringObj(Tcl_GetString(cwd), 3); Tcl_DecrRefCount(cwd); if (tail[0] == '/') { tail++; } else { tail += 2; } Tcl_IncrRefCount(pathPrefix); break; } case TCL_PATH_ABSOLUTE: /* * Absolute, possibly network path //Machine/Share. Use that * as the path prefix (it already has a refCount). */ pathPrefix = driveName; tail += driveNameLen; break; case TCL_PATH_RELATIVE: /* Do nothing */ break; } Tcl_DecrRefCount(temp); } /* * ':' no longer needed as a separator. It is only relevant to the * beginning of the path. */ separators = "/\\"; } else if (tclPlatform == TCL_PLATFORM_UNIX) { if (pathPrefix == NULL && tail[0] == '/') { pathPrefix = Tcl_NewStringObj(tail, 1); tail++; Tcl_IncrRefCount(pathPrefix); } } /* * Finally if we still haven't managed to generate a path prefix, check if * the path starts with a current volume. */ if (pathPrefix == NULL) { int driveNameLen; Tcl_Obj *driveName; if (TclFSNonnativePathType(tail, (int) strlen(tail), NULL, &driveNameLen, &driveName) == TCL_PATH_ABSOLUTE) { pathPrefix = driveName; tail += driveNameLen; } } /* * To process a [glob] invokation, this function may be called multiple * times. Each time, the previously discovered filenames are in the * interpreter result. We stash that away here so the result is free for * error messsages. */ savedResultObj = Tcl_GetObjResult(interp); Tcl_IncrRefCount(savedResultObj); Tcl_ResetResult(interp); TclNewObj(filenamesObj); Tcl_IncrRefCount(filenamesObj); /* * Now we do the actual globbing, adding filenames as we go to buffer in * filenamesObj */ if (*tail == '\0' && pathPrefix != NULL) { /* * An empty pattern. This means 'pathPrefix' is actually a full path * of a file/directory we want to simply check for existence and type. */ if (types == NULL) { /* * We just want to check for existence. In this case we make it * easy on Tcl_FSMatchInDirectory and its sub-implementations by * not bothering them (even though they should support this * situation) and we just use the simple existence check with * Tcl_FSAccess. */ if (Tcl_FSAccess(pathPrefix, F_OK) == 0) { Tcl_ListObjAppendElement(interp, filenamesObj, pathPrefix); } result = TCL_OK; } else { /* * We want to check for the correct type. Tcl_FSMatchInDirectory * is documented to do this for us, if we give it a NULL pattern. */ result = Tcl_FSMatchInDirectory(interp, filenamesObj, pathPrefix, NULL, types); } } else { result = DoGlob(interp, filenamesObj, separators, pathPrefix, globFlags & TCL_GLOBMODE_DIR, tail, types); } /* * Check for errors... */ if (result != TCL_OK) { TclDecrRefCount(filenamesObj); TclDecrRefCount(savedResultObj); if (pathPrefix != NULL) { Tcl_DecrRefCount(pathPrefix); } return result; } /* * If we only want the tails, we must strip off the prefix now. It may * seem more efficient to pass the tails flag down into DoGlob, * Tcl_FSMatchInDirectory, but those functions are continually adjusting * the prefix as the various pieces of the pattern are assimilated, so * that would add a lot of complexity to the code. This way is a little * slower (when the -tails flag is given), but much simpler to code. * * We do it by rewriting the result list in-place. */ if (globFlags & TCL_GLOBMODE_TAILS) { int objc, i; Tcl_Obj **objv; int prefixLen; const char *pre; /* * If this length has never been set, set it here. */ if (pathPrefix == NULL) { Tcl_Panic("Called TclGlob with TCL_GLOBMODE_TAILS and pathPrefix==NULL"); } pre = Tcl_GetStringFromObj(pathPrefix, &prefixLen); if (prefixLen > 0 && (strchr(separators, pre[prefixLen-1]) == NULL)) { /* * If we're on Windows and the prefix is a volume relative one * like 'C:', then there won't be a path separator in between, so * no need to skip it here. */ if ((tclPlatform != TCL_PLATFORM_WINDOWS) || (prefixLen != 2) || (pre[1] != ':')) { prefixLen++; } } Tcl_ListObjGetElements(NULL, filenamesObj, &objc, &objv); for (i = 0; i< objc; i++) { int len; const char *oldStr = Tcl_GetStringFromObj(objv[i], &len); Tcl_Obj *elem; if (len == prefixLen) { if ((pattern[0] == '\0') || (strchr(separators, pattern[0]) == NULL)) { TclNewLiteralStringObj(elem, "."); } else { TclNewLiteralStringObj(elem, "/"); } } else { elem = Tcl_NewStringObj(oldStr+prefixLen, len-prefixLen); } Tcl_ListObjReplace(interp, filenamesObj, i, 1, 1, &elem); } } /* * Now we have a list of discovered filenames in filenamesObj and a list * of previously discovered (saved earlier from the interpreter result) in * savedResultObj. Merge them and put them back in the interpreter result. */ if (Tcl_IsShared(savedResultObj)) { TclDecrRefCount(savedResultObj); savedResultObj = Tcl_DuplicateObj(savedResultObj); Tcl_IncrRefCount(savedResultObj); } if (Tcl_ListObjAppendList(interp, savedResultObj, filenamesObj) != TCL_OK){ result = TCL_ERROR; } else { Tcl_SetObjResult(interp, savedResultObj); } TclDecrRefCount(savedResultObj); TclDecrRefCount(filenamesObj); if (pathPrefix != NULL) { Tcl_DecrRefCount(pathPrefix); } return result; } /* *---------------------------------------------------------------------- * * SkipToChar -- * * This function traverses a glob pattern looking for the next unquoted * occurance of the specified character at the same braces nesting level. * * Results: * Updates stringPtr to point to the matching character, or to the end of * the string if nothing matched. The return value is 1 if a match was * found at the top level, otherwise it is 0. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int SkipToChar( char **stringPtr, /* Pointer string to check. */ int match) /* Character to find. */ { int quoted, level; register char *p; quoted = 0; level = 0; for (p = *stringPtr; *p != '\0'; p++) { if (quoted) { quoted = 0; continue; } if ((level == 0) && (*p == match)) { *stringPtr = p; return 1; } if (*p == '{') { level++; } else if (*p == '}') { level--; } else if (*p == '\\') { quoted = 1; } } *stringPtr = p; return 0; } /* *---------------------------------------------------------------------- * * DoGlob -- * * This recursive procedure forms the heart of the globbing code. It * performs a depth-first traversal of the tree given by the path name to * be globbed and the pattern. The directory and remainder are assumed to * be native format paths. The prefix contained in 'pathPtr' is either a * directory or path from which to start the search (or NULL). If pathPtr * is NULL, then the pattern must not start with an absolute path * specification (that case should be handled by moving the absolute path * prefix into pathPtr before calling DoGlob). * * Results: * The return value is a standard Tcl result indicating whether an error * occurred in globbing. After a normal return the result in interp will * be set to hold all of the file names given by the dir and remaining * arguments. After an error the result in interp will hold an error * message. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int DoGlob( Tcl_Interp *interp, /* Interpreter to use for error reporting * (e.g. unmatched brace). */ Tcl_Obj *matchesObj, /* Unshared list object in which to place all * resulting filenames. Caller allocates and * deallocates; DoGlob must not touch the * refCount of this object. */ const char *separators, /* String containing separator characters that * should be used to identify globbing * boundaries. */ Tcl_Obj *pathPtr, /* Completely expanded prefix. */ int flags, /* If non-zero then pathPtr is a directory */ char *pattern, /* The pattern to match against. Must not be a * pointer to a static string. */ Tcl_GlobTypeData *types) /* List object containing list of acceptable * types. May be NULL. */ { int baseLength, quoted, count; int result = TCL_OK; char *name, *p, *openBrace, *closeBrace, *firstSpecialChar; Tcl_Obj *joinedPtr; /* * Consume any leading directory separators, leaving pattern pointing just * past the last initial separator. */ count = 0; name = pattern; for (; *pattern != '\0'; pattern++) { if (*pattern == '\\') { /* * If the first character is escaped, either we have a directory * separator, or we have any other character. In the latter case * the rest is a pattern, and we must break from the loop. This * is particularly important on Windows where '\' is both the * escaping character and a directory separator. */ if (strchr(separators, pattern[1]) != NULL) { pattern++; } else { break; } } else if (strchr(separators, *pattern) == NULL) { break; } count++; } /* * Look for the first matching pair of braces or the first directory * separator that is not inside a pair of braces. */ openBrace = closeBrace = NULL; quoted = 0; for (p = pattern; *p != '\0'; p++) { if (quoted) { quoted = 0; } else if (*p == '\\') { quoted = 1; if (strchr(separators, p[1]) != NULL) { /* * Quoted directory separator. */ break; } } else if (strchr(separators, *p) != NULL) { /* * Unquoted directory separator. */ break; } else if (*p == '{') { openBrace = p; p++; if (SkipToChar(&p, '}')) { /* * Balanced braces. */ closeBrace = p; break; } Tcl_SetObjResult(interp, Tcl_NewStringObj( "unmatched open-brace in file name", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", "BALANCE", NULL); return TCL_ERROR; } else if (*p == '}') { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unmatched close-brace in file name", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", "BALANCE", NULL); return TCL_ERROR; } } /* * Substitute the alternate patterns from the braces and recurse. */ if (openBrace != NULL) { char *element; Tcl_DString newName; Tcl_DStringInit(&newName); /* * For each element within in the outermost pair of braces, append the * element and the remainder to the fixed portion before the first * brace and recursively call DoGlob. */ Tcl_DStringAppend(&newName, pattern, openBrace-pattern); baseLength = Tcl_DStringLength(&newName); *closeBrace = '\0'; for (p = openBrace; p != closeBrace; ) { p++; element = p; SkipToChar(&p, ','); Tcl_DStringSetLength(&newName, baseLength); Tcl_DStringAppend(&newName, element, p-element); Tcl_DStringAppend(&newName, closeBrace+1, -1); result = DoGlob(interp, matchesObj, separators, pathPtr, flags, Tcl_DStringValue(&newName), types); if (result != TCL_OK) { break; } } *closeBrace = '}'; Tcl_DStringFree(&newName); return result; } /* * At this point, there are no more brace substitutions to perform on this * path component. The variable p is pointing at a quoted or unquoted * directory separator or the end of the string. So we need to check for * special globbing characters in the current pattern. We avoid modifying * pattern if p is pointing at the end of the string. * * If we find any globbing characters, then we must call * Tcl_FSMatchInDirectory. If we're at the end of the string, then that's * all we need to do. If we're not at the end of the string, then we must * recurse, so we do that below. * * Alternatively, if there are no globbing characters then again there are * two cases. If we're at the end of the string, we just need to check for * the given path's existence and type. If we're not at the end of the * string, we recurse. */ if (*p != '\0') { char savedChar = *p; /* * Note that we are modifying the string in place. This won't work if * the string is a static. */ *p = '\0'; firstSpecialChar = strpbrk(pattern, "*[]?\\"); *p = savedChar; } else { firstSpecialChar = strpbrk(pattern, "*[]?\\"); } if (firstSpecialChar != NULL) { /* * Look for matching files in the given directory. The implementation * of this function is filesystem specific. For each file that * matches, it will add the match onto the resultPtr given. */ static Tcl_GlobTypeData dirOnly = { TCL_GLOB_TYPE_DIR, 0, NULL, NULL }; char save = *p; Tcl_Obj *subdirsPtr; if (*p == '\0') { return Tcl_FSMatchInDirectory(interp, matchesObj, pathPtr, pattern, types); } /* * We do the recursion ourselves. This makes implementing * Tcl_FSMatchInDirectory for each filesystem much easier. */ *p = '\0'; TclNewObj(subdirsPtr); Tcl_IncrRefCount(subdirsPtr); result = Tcl_FSMatchInDirectory(interp, subdirsPtr, pathPtr, pattern, &dirOnly); *p = save; if (result == TCL_OK) { int subdirc, i, repair = -1; Tcl_Obj **subdirv; result = Tcl_ListObjGetElements(interp, subdirsPtr, &subdirc, &subdirv); for (i=0; result==TCL_OK && ist_dev; } unsigned Tcl_GetFSInodeFromStat( const Tcl_StatBuf *statPtr) { return (unsigned) statPtr->st_ino; } unsigned Tcl_GetModeFromStat( const Tcl_StatBuf *statPtr) { return (unsigned) statPtr->st_mode; } int Tcl_GetLinkCountFromStat( const Tcl_StatBuf *statPtr) { return (int)statPtr->st_nlink; } int Tcl_GetUserIdFromStat( const Tcl_StatBuf *statPtr) { return (int) statPtr->st_uid; } int Tcl_GetGroupIdFromStat( const Tcl_StatBuf *statPtr) { return (int) statPtr->st_gid; } int Tcl_GetDeviceTypeFromStat( const Tcl_StatBuf *statPtr) { return (int) statPtr->st_rdev; } Tcl_WideInt Tcl_GetAccessTimeFromStat( const Tcl_StatBuf *statPtr) { return (Tcl_WideInt) statPtr->st_atime; } Tcl_WideInt Tcl_GetModificationTimeFromStat( const Tcl_StatBuf *statPtr) { return (Tcl_WideInt) statPtr->st_mtime; } Tcl_WideInt Tcl_GetChangeTimeFromStat( const Tcl_StatBuf *statPtr) { return (Tcl_WideInt) statPtr->st_ctime; } Tcl_WideUInt Tcl_GetSizeFromStat( const Tcl_StatBuf *statPtr) { return (Tcl_WideUInt) statPtr->st_size; } Tcl_WideUInt Tcl_GetBlocksFromStat( const Tcl_StatBuf *statPtr) { #ifdef HAVE_STRUCT_STAT_ST_BLOCKS return (Tcl_WideUInt) statPtr->st_blocks; #else register unsigned blksize = Tcl_GetBlockSizeFromStat(statPtr); return ((Tcl_WideUInt) statPtr->st_size + blksize - 1) / blksize; #endif } unsigned Tcl_GetBlockSizeFromStat( const Tcl_StatBuf *statPtr) { #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE return (unsigned) statPtr->st_blksize; #else /* * Not a great guess, but will do... */ return GUESSED_BLOCK_SIZE; #endif } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclScan.c0000644000175000017500000005676512663660065014761 0ustar sergeisergei/* * tclScan.c -- * * This file contains the implementation of the "scan" command. * * Copyright (c) 1998 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Flag values used by Tcl_ScanObjCmd. */ #define SCAN_NOSKIP 0x1 /* Don't skip blanks. */ #define SCAN_SUPPRESS 0x2 /* Suppress assignment. */ #define SCAN_UNSIGNED 0x4 /* Read an unsigned value. */ #define SCAN_WIDTH 0x8 /* A width value was supplied. */ #define SCAN_LONGER 0x400 /* Asked for a wide value. */ #define SCAN_BIG 0x800 /* Asked for a bignum value. */ /* * The following structure contains the information associated with a * character set. */ typedef struct CharSet { int exclude; /* 1 if this is an exclusion set. */ int nchars; Tcl_UniChar *chars; int nranges; struct Range { Tcl_UniChar start; Tcl_UniChar end; } *ranges; } CharSet; /* * Declarations for functions used only in this file. */ static const char * BuildCharSet(CharSet *cset, const char *format); static int CharInSet(CharSet *cset, int ch); static void ReleaseCharSet(CharSet *cset); static int ValidateFormat(Tcl_Interp *interp, const char *format, int numVars, int *totalVars); /* *---------------------------------------------------------------------- * * BuildCharSet -- * * This function examines a character set format specification and builds * a CharSet containing the individual characters and character ranges * specified. * * Results: * Returns the next format position. * * Side effects: * Initializes the charset. * *---------------------------------------------------------------------- */ static const char * BuildCharSet( CharSet *cset, const char *format) /* Points to first char of set. */ { Tcl_UniChar ch, start; int offset, nranges; const char *end; memset(cset, 0, sizeof(CharSet)); offset = Tcl_UtfToUniChar(format, &ch); if (ch == '^') { cset->exclude = 1; format += offset; offset = Tcl_UtfToUniChar(format, &ch); } end = format + offset; /* * Find the close bracket so we can overallocate the set. */ if (ch == ']') { end += Tcl_UtfToUniChar(end, &ch); } nranges = 0; while (ch != ']') { if (ch == '-') { nranges++; } end += Tcl_UtfToUniChar(end, &ch); } cset->chars = ckalloc(sizeof(Tcl_UniChar) * (end - format - 1)); if (nranges > 0) { cset->ranges = ckalloc(sizeof(struct Range) * nranges); } else { cset->ranges = NULL; } /* * Now build the character set. */ cset->nchars = cset->nranges = 0; format += Tcl_UtfToUniChar(format, &ch); start = ch; if (ch == ']' || ch == '-') { cset->chars[cset->nchars++] = ch; format += Tcl_UtfToUniChar(format, &ch); } while (ch != ']') { if (*format == '-') { /* * This may be the first character of a range, so don't add it * yet. */ start = ch; } else if (ch == '-') { /* * Check to see if this is the last character in the set, in which * case it is not a range and we should add the previous character * as well as the dash. */ if (*format == ']') { cset->chars[cset->nchars++] = start; cset->chars[cset->nchars++] = ch; } else { format += Tcl_UtfToUniChar(format, &ch); /* * Check to see if the range is in reverse order. */ if (start < ch) { cset->ranges[cset->nranges].start = start; cset->ranges[cset->nranges].end = ch; } else { cset->ranges[cset->nranges].start = ch; cset->ranges[cset->nranges].end = start; } cset->nranges++; } } else { cset->chars[cset->nchars++] = ch; } format += Tcl_UtfToUniChar(format, &ch); } return format; } /* *---------------------------------------------------------------------- * * CharInSet -- * * Check to see if a character matches the given set. * * Results: * Returns non-zero if the character matches the given set. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int CharInSet( CharSet *cset, int c) /* Character to test, passed as int because of * non-ANSI prototypes. */ { Tcl_UniChar ch = (Tcl_UniChar) c; int i, match = 0; for (i = 0; i < cset->nchars; i++) { if (cset->chars[i] == ch) { match = 1; break; } } if (!match) { for (i = 0; i < cset->nranges; i++) { if ((cset->ranges[i].start <= ch) && (ch <= cset->ranges[i].end)) { match = 1; break; } } } return (cset->exclude ? !match : match); } /* *---------------------------------------------------------------------- * * ReleaseCharSet -- * * Free the storage associated with a character set. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void ReleaseCharSet( CharSet *cset) { ckfree(cset->chars); if (cset->ranges) { ckfree(cset->ranges); } } /* *---------------------------------------------------------------------- * * ValidateFormat -- * * Parse the format string and verify that it is properly formed and that * there are exactly enough variables on the command line. * * Results: * A standard Tcl result. * * Side effects: * May place an error in the interpreter result. * *---------------------------------------------------------------------- */ static int ValidateFormat( Tcl_Interp *interp, /* Current interpreter. */ const char *format, /* The format string. */ int numVars, /* The number of variables passed to the scan * command. */ int *totalSubs) /* The number of variables that will be * required. */ { int gotXpg, gotSequential, value, i, flags; char *end; Tcl_UniChar ch; int objIndex, xpgSize, nspace = numVars; int *nassign = TclStackAlloc(interp, nspace * sizeof(int)); char buf[TCL_UTF_MAX+1]; Tcl_Obj *errorMsg; /* Place to build an error messages. Note that * these are messy operations because we do * not want to use the formatting engine; * we're inside there! */ /* * Initialize an array that records the number of times a variable is * assigned to by the format string. We use this to detect if a variable * is multiply assigned or left unassigned. */ for (i = 0; i < nspace; i++) { nassign[i] = 0; } xpgSize = objIndex = gotXpg = gotSequential = 0; while (*format != '\0') { format += Tcl_UtfToUniChar(format, &ch); flags = 0; if (ch != '%') { continue; } format += Tcl_UtfToUniChar(format, &ch); if (ch == '%') { continue; } if (ch == '*') { flags |= SCAN_SUPPRESS; format += Tcl_UtfToUniChar(format, &ch); goto xpgCheckDone; } if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ /* * Check for an XPG3-style %n$ specification. Note: there must * not be a mixture of XPG3 specs and non-XPG3 specs in the same * format string. */ value = strtoul(format-1, &end, 10); /* INTL: "C" locale. */ if (*end != '$') { goto notXpg; } format = end+1; format += Tcl_UtfToUniChar(format, &ch); gotXpg = 1; if (gotSequential) { goto mixedXPG; } objIndex = value - 1; if ((objIndex < 0) || (numVars && (objIndex >= numVars))) { goto badIndex; } else if (numVars == 0) { /* * In the case where no vars are specified, the user can * specify %9999$ legally, so we have to consider special * rules for growing the assign array. 'value' is guaranteed * to be > 0. */ xpgSize = (xpgSize > value) ? xpgSize : value; } goto xpgCheckDone; } notXpg: gotSequential = 1; if (gotXpg) { mixedXPG: Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot mix \"%\" and \"%n$\" conversion specifiers", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "MIXEDSPECTYPES", NULL); goto error; } xpgCheckDone: /* * Parse any width specifier. */ if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ value = strtoul(format-1, (char **) &format, 10); /* INTL: "C" locale. */ flags |= SCAN_WIDTH; format += Tcl_UtfToUniChar(format, &ch); } /* * Handle any size specifier. */ switch (ch) { case 'l': if (*format == 'l') { flags |= SCAN_BIG; format += 1; format += Tcl_UtfToUniChar(format, &ch); break; } case 'L': flags |= SCAN_LONGER; case 'h': format += Tcl_UtfToUniChar(format, &ch); } if (!(flags & SCAN_SUPPRESS) && numVars && (objIndex >= numVars)) { goto badIndex; } /* * Handle the various field types. */ switch (ch) { case 'c': if (flags & SCAN_WIDTH) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "field width may not be specified in %c conversion", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADWIDTH", NULL); goto error; } /* * Fall through! */ case 'n': case 's': if (flags & (SCAN_LONGER|SCAN_BIG)) { invalidFieldSize: buf[Tcl_UniCharToUtf(ch, buf)] = '\0'; errorMsg = Tcl_NewStringObj( "field size modifier may not be specified in %", -1); Tcl_AppendToObj(errorMsg, buf, -1); Tcl_AppendToObj(errorMsg, " conversion", -1); Tcl_SetObjResult(interp, errorMsg); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADSIZE", NULL); goto error; } /* * Fall through! */ case 'd': case 'e': case 'E': case 'f': case 'g': case 'G': case 'i': case 'o': case 'x': case 'X': case 'b': break; case 'u': if (flags & SCAN_BIG) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unsigned bignum scans are invalid", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADUNSIGNED",NULL); goto error; } break; /* * Bracket terms need special checking */ case '[': if (flags & (SCAN_LONGER|SCAN_BIG)) { goto invalidFieldSize; } if (*format == '\0') { goto badSet; } format += Tcl_UtfToUniChar(format, &ch); if (ch == '^') { if (*format == '\0') { goto badSet; } format += Tcl_UtfToUniChar(format, &ch); } if (ch == ']') { if (*format == '\0') { goto badSet; } format += Tcl_UtfToUniChar(format, &ch); } while (ch != ']') { if (*format == '\0') { goto badSet; } format += Tcl_UtfToUniChar(format, &ch); } break; badSet: Tcl_SetObjResult(interp, Tcl_NewStringObj( "unmatched [ in format string", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BRACKET", NULL); goto error; default: buf[Tcl_UniCharToUtf(ch, buf)] = '\0'; errorMsg = Tcl_NewStringObj( "bad scan conversion character \"", -1); Tcl_AppendToObj(errorMsg, buf, -1); Tcl_AppendToObj(errorMsg, "\"", -1); Tcl_SetObjResult(interp, errorMsg); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", NULL); goto error; } if (!(flags & SCAN_SUPPRESS)) { if (objIndex >= nspace) { /* * Expand the nassign buffer. If we are using XPG specifiers, * make sure that we grow to a large enough size. xpgSize is * guaranteed to be at least one larger than objIndex. */ value = nspace; if (xpgSize) { nspace = xpgSize; } else { nspace += 16; /* formerly STATIC_LIST_SIZE */ } nassign = TclStackRealloc(interp, nassign, nspace * sizeof(int)); for (i = value; i < nspace; i++) { nassign[i] = 0; } } nassign[objIndex]++; objIndex++; } } /* * Verify that all of the variable were assigned exactly once. */ if (numVars == 0) { if (xpgSize) { numVars = xpgSize; } else { numVars = objIndex; } } if (totalSubs) { *totalSubs = numVars; } for (i = 0; i < numVars; i++) { if (nassign[i] > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "variable is assigned by multiple \"%n$\" conversion specifiers", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "POLYASSIGNED", NULL); goto error; } else if (!xpgSize && (nassign[i] == 0)) { /* * If the space is empty, and xpgSize is 0 (means XPG wasn't used, * and/or numVars != 0), then too many vars were given */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "variable is not assigned by any conversion specifiers", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "UNASSIGNED", NULL); goto error; } } TclStackFree(interp, nassign); return TCL_OK; badIndex: if (gotXpg) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"%n$\" argument index out of range", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "INDEXRANGE", NULL); } else { Tcl_SetObjResult(interp, Tcl_NewStringObj( "different numbers of variable names and field specifiers", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "FIELDVARMISMATCH", NULL); } error: TclStackFree(interp, nassign); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_ScanObjCmd -- * * This function is invoked to process the "scan" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ScanObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *format; int numVars, nconversions, totalVars = -1; int objIndex, offset, i, result, code; long value; const char *string, *end, *baseString; char op = 0; int width, underflow = 0; Tcl_WideInt wideValue; Tcl_UniChar ch, sch; Tcl_Obj **objs = NULL, *objPtr = NULL; int flags; char buf[513]; /* Temporary buffer to hold scanned number * strings before they are passed to * strtoul. */ if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "string format ?varName ...?"); return TCL_ERROR; } format = Tcl_GetString(objv[2]); numVars = objc-3; /* * Check for errors in the format string. */ if (ValidateFormat(interp, format, numVars, &totalVars) == TCL_ERROR) { return TCL_ERROR; } /* * Allocate space for the result objects. */ if (totalVars > 0) { objs = ckalloc(sizeof(Tcl_Obj *) * totalVars); for (i = 0; i < totalVars; i++) { objs[i] = NULL; } } string = Tcl_GetString(objv[1]); baseString = string; /* * Iterate over the format string filling in the result objects until we * reach the end of input, the end of the format string, or there is a * mismatch. */ objIndex = 0; nconversions = 0; while (*format != '\0') { int parseFlag = TCL_PARSE_NO_WHITESPACE; format += Tcl_UtfToUniChar(format, &ch); flags = 0; /* * If we see whitespace in the format, skip whitespace in the string. */ if (Tcl_UniCharIsSpace(ch)) { offset = Tcl_UtfToUniChar(string, &sch); while (Tcl_UniCharIsSpace(sch)) { if (*string == '\0') { goto done; } string += offset; offset = Tcl_UtfToUniChar(string, &sch); } continue; } if (ch != '%') { literal: if (*string == '\0') { underflow = 1; goto done; } string += Tcl_UtfToUniChar(string, &sch); if (ch != sch) { goto done; } continue; } format += Tcl_UtfToUniChar(format, &ch); if (ch == '%') { goto literal; } /* * Check for assignment suppression ('*') or an XPG3-style assignment * ('%n$'). */ if (ch == '*') { flags |= SCAN_SUPPRESS; format += Tcl_UtfToUniChar(format, &ch); } else if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ char *formatEnd; value = strtoul(format-1, &formatEnd, 10);/* INTL: "C" locale. */ if (*formatEnd == '$') { format = formatEnd+1; format += Tcl_UtfToUniChar(format, &ch); objIndex = (int) value - 1; } } /* * Parse any width specifier. */ if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */ width = (int) strtoul(format-1, (char **) &format, 10);/* INTL: "C" locale. */ format += Tcl_UtfToUniChar(format, &ch); } else { width = 0; } /* * Handle any size specifier. */ switch (ch) { case 'l': if (*format == 'l') { flags |= SCAN_BIG; format += 1; format += Tcl_UtfToUniChar(format, &ch); break; } case 'L': flags |= SCAN_LONGER; /* * Fall through so we skip to the next character. */ case 'h': format += Tcl_UtfToUniChar(format, &ch); } /* * Handle the various field types. */ switch (ch) { case 'n': if (!(flags & SCAN_SUPPRESS)) { objPtr = Tcl_NewIntObj(string - baseString); Tcl_IncrRefCount(objPtr); CLANG_ASSERT(objs); objs[objIndex++] = objPtr; } nconversions++; continue; case 'd': op = 'i'; parseFlag |= TCL_PARSE_DECIMAL_ONLY; break; case 'i': op = 'i'; parseFlag |= TCL_PARSE_SCAN_PREFIXES; break; case 'o': op = 'i'; parseFlag |= TCL_PARSE_OCTAL_ONLY | TCL_PARSE_SCAN_PREFIXES; break; case 'x': case 'X': op = 'i'; parseFlag |= TCL_PARSE_HEXADECIMAL_ONLY; break; case 'b': op = 'i'; parseFlag |= TCL_PARSE_BINARY_ONLY; break; case 'u': op = 'i'; parseFlag |= TCL_PARSE_DECIMAL_ONLY; flags |= SCAN_UNSIGNED; break; case 'f': case 'e': case 'E': case 'g': case 'G': op = 'f'; break; case 's': op = 's'; break; case 'c': op = 'c'; flags |= SCAN_NOSKIP; break; case '[': op = '['; flags |= SCAN_NOSKIP; break; } /* * At this point, we will need additional characters from the string * to proceed. */ if (*string == '\0') { underflow = 1; goto done; } /* * Skip any leading whitespace at the beginning of a field unless the * format suppresses this behavior. */ if (!(flags & SCAN_NOSKIP)) { while (*string != '\0') { offset = Tcl_UtfToUniChar(string, &sch); if (!Tcl_UniCharIsSpace(sch)) { break; } string += offset; } if (*string == '\0') { underflow = 1; goto done; } } /* * Perform the requested scanning operation. */ switch (op) { case 's': /* * Scan a string up to width characters or whitespace. */ if (width == 0) { width = ~0; } end = string; while (*end != '\0') { offset = Tcl_UtfToUniChar(end, &sch); if (Tcl_UniCharIsSpace(sch)) { break; } end += offset; if (--width == 0) { break; } } if (!(flags & SCAN_SUPPRESS)) { objPtr = Tcl_NewStringObj(string, end-string); Tcl_IncrRefCount(objPtr); CLANG_ASSERT(objs); objs[objIndex++] = objPtr; } string = end; break; case '[': { CharSet cset; if (width == 0) { width = ~0; } end = string; format = BuildCharSet(&cset, format); while (*end != '\0') { offset = Tcl_UtfToUniChar(end, &sch); if (!CharInSet(&cset, (int)sch)) { break; } end += offset; if (--width == 0) { break; } } ReleaseCharSet(&cset); if (string == end) { /* * Nothing matched the range, stop processing. */ goto done; } if (!(flags & SCAN_SUPPRESS)) { objPtr = Tcl_NewStringObj(string, end-string); Tcl_IncrRefCount(objPtr); objs[objIndex++] = objPtr; } string = end; break; } case 'c': /* * Scan a single Unicode character. */ string += Tcl_UtfToUniChar(string, &sch); if (!(flags & SCAN_SUPPRESS)) { objPtr = Tcl_NewIntObj((int)sch); Tcl_IncrRefCount(objPtr); CLANG_ASSERT(objs); objs[objIndex++] = objPtr; } break; case 'i': /* * Scan an unsigned or signed integer. */ objPtr = Tcl_NewLongObj(0); Tcl_IncrRefCount(objPtr); if (width == 0) { width = ~0; } if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, string, width, &end, TCL_PARSE_INTEGER_ONLY | parseFlag)) { Tcl_DecrRefCount(objPtr); if (width < 0) { if (*end == '\0') { underflow = 1; } } else { if (end == string + width) { underflow = 1; } } goto done; } string = end; if (flags & SCAN_SUPPRESS) { Tcl_DecrRefCount(objPtr); break; } if (flags & SCAN_LONGER) { if (Tcl_GetWideIntFromObj(NULL, objPtr, &wideValue) != TCL_OK) { wideValue = ~(Tcl_WideUInt)0 >> 1; /* WIDE_MAX */ if (TclGetString(objPtr)[0] == '-') { wideValue++; /* WIDE_MAX + 1 = WIDE_MIN */ } } if ((flags & SCAN_UNSIGNED) && (wideValue < 0)) { sprintf(buf, "%" TCL_LL_MODIFIER "u", (Tcl_WideUInt)wideValue); Tcl_SetStringObj(objPtr, buf, -1); } else { Tcl_SetWideIntObj(objPtr, wideValue); } } else if (!(flags & SCAN_BIG)) { if (TclGetLongFromObj(NULL, objPtr, &value) != TCL_OK) { if (TclGetString(objPtr)[0] == '-') { value = LONG_MIN; } else { value = LONG_MAX; } } if ((flags & SCAN_UNSIGNED) && (value < 0)) { sprintf(buf, "%lu", value); /* INTL: ISO digit */ Tcl_SetStringObj(objPtr, buf, -1); } else { Tcl_SetLongObj(objPtr, value); } } objs[objIndex++] = objPtr; break; case 'f': /* * Scan a floating point number */ objPtr = Tcl_NewDoubleObj(0.0); Tcl_IncrRefCount(objPtr); if (width == 0) { width = ~0; } if (TCL_OK != TclParseNumber(NULL, objPtr, NULL, string, width, &end, TCL_PARSE_DECIMAL_ONLY | TCL_PARSE_NO_WHITESPACE)) { Tcl_DecrRefCount(objPtr); if (width < 0) { if (*end == '\0') { underflow = 1; } } else { if (end == string + width) { underflow = 1; } } goto done; } else if (flags & SCAN_SUPPRESS) { Tcl_DecrRefCount(objPtr); string = end; } else { double dvalue; if (Tcl_GetDoubleFromObj(NULL, objPtr, &dvalue) != TCL_OK) { #ifdef ACCEPT_NAN if (objPtr->typePtr == &tclDoubleType) { dvalue = objPtr->internalRep.doubleValue; } else #endif { Tcl_DecrRefCount(objPtr); goto done; } } Tcl_SetDoubleObj(objPtr, dvalue); CLANG_ASSERT(objs); objs[objIndex++] = objPtr; string = end; } } nconversions++; } done: result = 0; code = TCL_OK; if (numVars) { /* * In this case, variables were specified (classic scan). */ for (i = 0; i < totalVars; i++) { if (objs[i] == NULL) { continue; } result++; /* * In case of multiple errors in setting variables, just report * the first one. */ if (Tcl_ObjSetVar2(interp, objv[i+3], NULL, objs[i], (code == TCL_OK) ? TCL_LEAVE_ERR_MSG : 0) == NULL) { code = TCL_ERROR; } Tcl_DecrRefCount(objs[i]); } } else { /* * Here no vars were specified, we want a list returned (inline scan) */ objPtr = Tcl_NewObj(); for (i = 0; i < totalVars; i++) { if (objs[i] != NULL) { Tcl_ListObjAppendElement(NULL, objPtr, objs[i]); Tcl_DecrRefCount(objs[i]); } else { /* * More %-specifiers than matching chars, so we just spit out * empty strings for these. */ Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewObj()); } } } if (objs != NULL) { ckfree(objs); } if (code == TCL_OK) { if (underflow && (nconversions == 0)) { if (numVars) { objPtr = Tcl_NewIntObj(-1); } else { if (objPtr) { Tcl_SetListObj(objPtr, 0, NULL); } else { objPtr = Tcl_NewObj(); } } } else if (numVars) { objPtr = Tcl_NewIntObj(result); } Tcl_SetObjResult(interp, objPtr); } return code; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclExecute.c0000644000175000017500000110647412663660065015471 0ustar sergeisergei/* * tclExecute.c -- * * This file contains procedures that execute byte-compiled Tcl commands. * * Copyright (c) 1996-1997 Sun Microsystems, Inc. * Copyright (c) 1998-2000 by Scriptics Corporation. * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2002-2010 by Miguel Sofer. * Copyright (c) 2005-2007 by Donal K. Fellows. * Copyright (c) 2007 Daniel A. Steffen * Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" #include "tclOOInt.h" #include "tommath.h" #include #include /* * Hack to determine whether we may expect IEEE floating point. The hack is * formally incorrect in that non-IEEE platforms might have the same precision * and range, but VAX, IBM, and Cray do not; are there any other floating * point units that we might care about? */ #if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024) #define IEEE_FLOATING_POINT #endif /* * A mask (should be 2**n-1) that is used to work out when the bytecode engine * should call Tcl_AsyncReady() to see whether there is a signal that needs * handling. */ #ifndef ASYNC_CHECK_COUNT_MASK # define ASYNC_CHECK_COUNT_MASK 63 #endif /* !ASYNC_CHECK_COUNT_MASK */ /* * Boolean flag indicating whether the Tcl bytecode interpreter has been * initialized. */ static int execInitialized = 0; TCL_DECLARE_MUTEX(execMutex) static int cachedInExit = 0; #ifdef TCL_COMPILE_DEBUG /* * Variable that controls whether execution tracing is enabled and, if so, * what level of tracing is desired: * 0: no execution tracing * 1: trace invocations of Tcl procs only * 2: trace invocations of all (not compiled away) commands * 3: display each instruction executed * This variable is linked to the Tcl variable "tcl_traceExec". */ int tclTraceExec = 0; #endif /* * Mapping from expression instruction opcodes to strings; used for error * messages. Note that these entries must match the order and number of the * expression opcodes (e.g., INST_LOR) in tclCompile.h. * * Does not include the string for INST_EXPON (and beyond), as that is * disjoint for backward-compatability reasons. */ static const char *const operatorStrings[] = { "||", "&&", "|", "^", "&", "==", "!=", "<", ">", "<=", ">=", "<<", ">>", "+", "-", "*", "/", "%", "+", "-", "~", "!" }; /* * Mapping from Tcl result codes to strings; used for error and debugging * messages. */ #ifdef TCL_COMPILE_DEBUG static const char *const resultStrings[] = { "TCL_OK", "TCL_ERROR", "TCL_RETURN", "TCL_BREAK", "TCL_CONTINUE" }; #endif /* * These are used by evalstats to monitor object usage in Tcl. */ #ifdef TCL_COMPILE_STATS long tclObjsAlloced = 0; long tclObjsFreed = 0; long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 }; #endif /* TCL_COMPILE_STATS */ /* * Support pre-8.5 bytecodes unless specifically requested otherwise. */ #ifndef TCL_SUPPORT_84_BYTECODE #define TCL_SUPPORT_84_BYTECODE 1 #endif #if TCL_SUPPORT_84_BYTECODE /* * We need to know the tclBuiltinFuncTable to support translation of pre-8.5 * math functions to the namespace-based ::tcl::mathfunc::op in 8.5+. */ typedef struct { const char *name; /* Name of function. */ int numArgs; /* Number of arguments for function. */ } BuiltinFunc; /* * Table describing the built-in math functions. Entries in this table are * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's * operand byte. */ static BuiltinFunc const tclBuiltinFuncTable[] = { {"acos", 1}, {"asin", 1}, {"atan", 1}, {"atan2", 2}, {"ceil", 1}, {"cos", 1}, {"cosh", 1}, {"exp", 1}, {"floor", 1}, {"fmod", 2}, {"hypot", 2}, {"log", 1}, {"log10", 1}, {"pow", 2}, {"sin", 1}, {"sinh", 1}, {"sqrt", 1}, {"tan", 1}, {"tanh", 1}, {"abs", 1}, {"double", 1}, {"int", 1}, {"rand", 0}, {"round", 1}, {"srand", 1}, {"wide", 1}, {NULL, 0}, }; #define LAST_BUILTIN_FUNC 25 #endif /* * NR_TEBC * Helpers for NR - non-recursive calls to TEBC * Minimal data required to fully reconstruct the execution state. */ typedef struct TEBCdata { ByteCode *codePtr; /* Constant until the BC returns */ /* -----------------------------------------*/ ptrdiff_t *catchTop; /* These fields are used on return TO this */ Tcl_Obj *auxObjList; /* this level: they record the state when a */ CmdFrame cmdFrame; /* new codePtr was received for NR */ /* execution. */ void *stack[1]; /* Start of the actual combined catch and obj * stacks; the struct will be expanded as * necessary */ } TEBCdata; #define TEBC_YIELD() \ do { \ esPtr->tosPtr = tosPtr; \ TclNRAddCallback(interp, TEBCresume, \ TD, pc, INT2PTR(cleanup), NULL); \ } while (0) #define TEBC_DATA_DIG() \ do { \ tosPtr = esPtr->tosPtr; \ } while (0) #define PUSH_TAUX_OBJ(objPtr) \ do { \ if (auxObjList) { \ objPtr->length += auxObjList->length; \ } \ objPtr->internalRep.twoPtrValue.ptr1 = auxObjList; \ auxObjList = objPtr; \ } while (0) #define POP_TAUX_OBJ() \ do { \ tmpPtr = auxObjList; \ auxObjList = tmpPtr->internalRep.twoPtrValue.ptr1; \ Tcl_DecrRefCount(tmpPtr); \ } while (0) /* * These variable-access macros have to coincide with those in tclVar.c */ #define VarHashGetValue(hPtr) \ ((Var *) ((char *)hPtr - TclOffset(VarInHash, entry))) static inline Var * VarHashCreateVar( TclVarHashTable *tablePtr, Tcl_Obj *key, int *newPtr) { Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&tablePtr->table, key, newPtr); if (!hPtr) { return NULL; } return VarHashGetValue(hPtr); } #define VarHashFindVar(tablePtr, key) \ VarHashCreateVar((tablePtr), (key), NULL) /* * The new macro for ending an instruction; note that a reasonable C-optimiser * will resolve all branches at compile time. (result) is always a constant; * the macro NEXT_INST_F handles constant (nCleanup), NEXT_INST_V is resolved * at runtime for variable (nCleanup). * * ARGUMENTS: * pcAdjustment: how much to increment pc * nCleanup: how many objects to remove from the stack * resultHandling: 0 indicates no object should be pushed on the stack; * otherwise, push objResultPtr. If (result < 0), objResultPtr already * has the correct reference count. * * We use the new compile-time assertions to check that nCleanup is constant * and within range. */ /* Verify the stack depth, only when no expansion is in progress */ #ifdef TCL_COMPILE_DEBUG #define CHECK_STACK() \ do { \ ValidatePcAndStackTop(codePtr, pc, CURR_DEPTH, \ /*checkStack*/ !(starting || auxObjList)); \ starting = 0; \ } while (0) #else #define CHECK_STACK() #endif #define NEXT_INST_F(pcAdjustment, nCleanup, resultHandling) \ do { \ TCL_CT_ASSERT((nCleanup >= 0) && (nCleanup <= 2)); \ CHECK_STACK(); \ if (nCleanup == 0) { \ if (resultHandling != 0) { \ if ((resultHandling) > 0) { \ PUSH_OBJECT(objResultPtr); \ } else { \ *(++tosPtr) = objResultPtr; \ } \ } \ pc += (pcAdjustment); \ goto cleanup0; \ } else if (resultHandling != 0) { \ if ((resultHandling) > 0) { \ Tcl_IncrRefCount(objResultPtr); \ } \ pc += (pcAdjustment); \ switch (nCleanup) { \ case 1: goto cleanup1_pushObjResultPtr; \ case 2: goto cleanup2_pushObjResultPtr; \ case 0: break; \ } \ } else { \ pc += (pcAdjustment); \ switch (nCleanup) { \ case 1: goto cleanup1; \ case 2: goto cleanup2; \ case 0: break; \ } \ } \ } while (0) #define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \ CHECK_STACK(); \ do { \ pc += (pcAdjustment); \ cleanup = (nCleanup); \ if (resultHandling) { \ if ((resultHandling) > 0) { \ Tcl_IncrRefCount(objResultPtr); \ } \ goto cleanupV_pushObjResultPtr; \ } else { \ goto cleanupV; \ } \ } while (0) #ifndef TCL_COMPILE_DEBUG #define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \ do { \ pc += (pcAdjustment); \ switch (*pc) { \ case INST_JUMP_FALSE1: \ NEXT_INST_F(((condition)? 2 : TclGetInt1AtPtr(pc+1)), (cleanup), 0); \ case INST_JUMP_TRUE1: \ NEXT_INST_F(((condition)? TclGetInt1AtPtr(pc+1) : 2), (cleanup), 0); \ case INST_JUMP_FALSE4: \ NEXT_INST_F(((condition)? 5 : TclGetInt4AtPtr(pc+1)), (cleanup), 0); \ case INST_JUMP_TRUE4: \ NEXT_INST_F(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \ default: \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_F(0, (cleanup), 1); \ } \ } while (0) #define JUMP_PEEPHOLE_V(condition, pcAdjustment, cleanup) \ do { \ pc += (pcAdjustment); \ switch (*pc) { \ case INST_JUMP_FALSE1: \ NEXT_INST_V(((condition)? 2 : TclGetInt1AtPtr(pc+1)), (cleanup), 0); \ case INST_JUMP_TRUE1: \ NEXT_INST_V(((condition)? TclGetInt1AtPtr(pc+1) : 2), (cleanup), 0); \ case INST_JUMP_FALSE4: \ NEXT_INST_V(((condition)? 5 : TclGetInt4AtPtr(pc+1)), (cleanup), 0); \ case INST_JUMP_TRUE4: \ NEXT_INST_V(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \ default: \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_V(0, (cleanup), 1); \ } \ } while (0) #else /* TCL_COMPILE_DEBUG */ #define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \ do{ \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_F((pcAdjustment), (cleanup), 1); \ } while (0) #define JUMP_PEEPHOLE_V(condition, pcAdjustment, cleanup) \ do{ \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_V((pcAdjustment), (cleanup), 1); \ } while (0) #endif /* * Macros used to cache often-referenced Tcl evaluation stack information * in local variables. Note that a DECACHE_STACK_INFO()-CACHE_STACK_INFO() * pair must surround any call inside TclNRExecuteByteCode (and a few other * procedures that use this scheme) that could result in a recursive call * to TclNRExecuteByteCode. */ #define CACHE_STACK_INFO() \ checkInterp = 1 #define DECACHE_STACK_INFO() \ esPtr->tosPtr = tosPtr /* * Macros used to access items on the Tcl evaluation stack. PUSH_OBJECT * increments the object's ref count since it makes the stack have another * reference pointing to the object. However, POP_OBJECT does not decrement * the ref count. This is because the stack may hold the only reference to the * object, so the object would be destroyed if its ref count were decremented * before the caller had a chance to, e.g., store it in a variable. It is the * caller's responsibility to decrement the ref count when it is finished with * an object. * * WARNING! It is essential that objPtr only appear once in the PUSH_OBJECT * macro. The actual parameter might be an expression with side effects, and * this ensures that it will be executed only once. */ #define PUSH_OBJECT(objPtr) \ Tcl_IncrRefCount(*(++tosPtr) = (objPtr)) #define POP_OBJECT() *(tosPtr--) #define OBJ_AT_TOS *tosPtr #define OBJ_UNDER_TOS *(tosPtr-1) #define OBJ_AT_DEPTH(n) *(tosPtr-(n)) #define CURR_DEPTH ((ptrdiff_t) (tosPtr - initTosPtr)) #define STACK_BASE(esPtr) ((esPtr)->stackWords - 1) /* * Macros used to trace instruction execution. The macros TRACE, * TRACE_WITH_OBJ, and O2S are only used inside TclNRExecuteByteCode. O2S is * only used in TRACE* calls to get a string from an object. */ #ifdef TCL_COMPILE_DEBUG # define TRACE(a) \ while (traceInstructions) { \ fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, \ (int) CURR_DEPTH, \ (unsigned) (pc - codePtr->codeStart), \ GetOpcodeName(pc)); \ printf a; \ break; \ } # define TRACE_APPEND(a) \ while (traceInstructions) { \ printf a; \ break; \ } # define TRACE_ERROR(interp) \ TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); # define TRACE_WITH_OBJ(a, objPtr) \ while (traceInstructions) { \ fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, \ (int) CURR_DEPTH, \ (unsigned) (pc - codePtr->codeStart), \ GetOpcodeName(pc)); \ printf a; \ TclPrintObject(stdout, objPtr, 30); \ fprintf(stdout, "\n"); \ break; \ } # define O2S(objPtr) \ (objPtr ? TclGetString(objPtr) : "") #else /* !TCL_COMPILE_DEBUG */ # define TRACE(a) # define TRACE_APPEND(a) # define TRACE_ERROR(interp) # define TRACE_WITH_OBJ(a, objPtr) # define O2S(objPtr) #endif /* TCL_COMPILE_DEBUG */ /* * DTrace instruction probe macros. */ #define TCL_DTRACE_INST_NEXT() \ do { \ if (TCL_DTRACE_INST_DONE_ENABLED()) { \ if (curInstName) { \ TCL_DTRACE_INST_DONE(curInstName, (int) CURR_DEPTH, \ tosPtr); \ } \ curInstName = tclInstructionTable[*pc].name; \ if (TCL_DTRACE_INST_START_ENABLED()) { \ TCL_DTRACE_INST_START(curInstName, (int) CURR_DEPTH, \ tosPtr); \ } \ } else if (TCL_DTRACE_INST_START_ENABLED()) { \ TCL_DTRACE_INST_START(tclInstructionTable[*pc].name, \ (int) CURR_DEPTH, tosPtr); \ } \ } while (0) #define TCL_DTRACE_INST_LAST() \ do { \ if (TCL_DTRACE_INST_DONE_ENABLED() && curInstName) { \ TCL_DTRACE_INST_DONE(curInstName, (int) CURR_DEPTH, tosPtr);\ } \ } while (0) /* * Macro used in this file to save a function call for common uses of * TclGetNumberFromObj(). The ANSI C "prototype" is: * * MODULE_SCOPE int GetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, * ClientData *ptrPtr, int *tPtr); */ #ifdef TCL_WIDE_INT_IS_LONG #define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? (*(tPtr) = TCL_NUMBER_LONG, \ *(ptrPtr) = (ClientData) \ (&((objPtr)->internalRep.longValue)), TCL_OK) : \ ((objPtr)->typePtr == &tclDoubleType) \ ? (((TclIsNaN((objPtr)->internalRep.doubleValue)) \ ? (*(tPtr) = TCL_NUMBER_NAN) \ : (*(tPtr) = TCL_NUMBER_DOUBLE)), \ *(ptrPtr) = (ClientData) \ (&((objPtr)->internalRep.doubleValue)), TCL_OK) : \ ((((objPtr)->typePtr == NULL) && ((objPtr)->bytes == NULL)) || \ (((objPtr)->bytes != NULL) && ((objPtr)->length == 0))) \ ? (*(tPtr) = TCL_NUMBER_LONG),TCL_ERROR : \ TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr))) #else /* !TCL_WIDE_INT_IS_LONG */ #define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? (*(tPtr) = TCL_NUMBER_LONG, \ *(ptrPtr) = (ClientData) \ (&((objPtr)->internalRep.longValue)), TCL_OK) : \ ((objPtr)->typePtr == &tclWideIntType) \ ? (*(tPtr) = TCL_NUMBER_WIDE, \ *(ptrPtr) = (ClientData) \ (&((objPtr)->internalRep.wideValue)), TCL_OK) : \ ((objPtr)->typePtr == &tclDoubleType) \ ? (((TclIsNaN((objPtr)->internalRep.doubleValue)) \ ? (*(tPtr) = TCL_NUMBER_NAN) \ : (*(tPtr) = TCL_NUMBER_DOUBLE)), \ *(ptrPtr) = (ClientData) \ (&((objPtr)->internalRep.doubleValue)), TCL_OK) : \ ((((objPtr)->typePtr == NULL) && ((objPtr)->bytes == NULL)) || \ (((objPtr)->bytes != NULL) && ((objPtr)->length == 0))) \ ? (*(tPtr) = TCL_NUMBER_LONG),TCL_ERROR : \ TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr))) #endif /* TCL_WIDE_INT_IS_LONG */ /* * Macro used in this file to save a function call for common uses of * Tcl_GetBooleanFromObj(). The ANSI C "prototype" is: * * MODULE_SCOPE int TclGetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, * int *boolPtr); */ #define TclGetBooleanFromObj(interp, objPtr, boolPtr) \ ((((objPtr)->typePtr == &tclIntType) \ || ((objPtr)->typePtr == &tclBooleanType)) \ ? (*(boolPtr) = ((objPtr)->internalRep.longValue!=0), TCL_OK) \ : Tcl_GetBooleanFromObj((interp), (objPtr), (boolPtr))) /* * Macro used to make the check for type overflow more mnemonic. This works by * comparing sign bits; the rest of the word is irrelevant. The ANSI C * "prototype" (where inttype_t is any integer type) is: * * MODULE_SCOPE int Overflowing(inttype_t a, inttype_t b, inttype_t sum); * * Check first the condition most likely to fail in usual code (at least for * usage in [incr]: do the first summand and the sum have != signs? */ #define Overflowing(a,b,sum) ((((a)^(sum)) < 0) && (((a)^(b)) >= 0)) /* * Macro for checking whether the type is NaN, used when we're thinking about * throwing an error for supplying a non-number number. */ #ifndef ACCEPT_NAN #define IsErroringNaNType(type) ((type) == TCL_NUMBER_NAN) #else #define IsErroringNaNType(type) 0 #endif /* * Auxiliary tables used to compute powers of small integers. */ #if (LONG_MAX == 0x7fffffff) /* * Maximum base that, when raised to powers 2, 3, ... 8, fits in a 32-bit * signed integer. */ static const long MaxBase32[] = {46340, 1290, 215, 73, 35, 21, 14}; static const size_t MaxBase32Size = sizeof(MaxBase32)/sizeof(long); /* * Table giving 3, 4, ..., 11, raised to the powers 9, 10, ..., as far as they * fit in a 32-bit signed integer. Exp32Index[i] gives the starting index of * powers of i+3; Exp32Value[i] gives the corresponding powers. */ static const unsigned short Exp32Index[] = { 0, 11, 18, 23, 26, 29, 31, 32, 33 }; static const size_t Exp32IndexSize = sizeof(Exp32Index) / sizeof(unsigned short); static const long Exp32Value[] = { 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721, 129140163, 387420489, 1162261467, 262144, 1048576, 4194304, 16777216, 67108864, 268435456, 1073741824, 1953125, 9765625, 48828125, 244140625, 1220703125, 10077696, 60466176, 362797056, 40353607, 282475249, 1977326743, 134217728, 1073741824, 387420489, 1000000000 }; static const size_t Exp32ValueSize = sizeof(Exp32Value)/sizeof(long); #endif /* LONG_MAX == 0x7fffffff -- 32 bit machine */ #if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) /* * Maximum base that, when raised to powers 2, 3, ..., 16, fits in a * Tcl_WideInt. */ static const Tcl_WideInt MaxBase64[] = { (Tcl_WideInt)46340*65536+62259, /* 3037000499 == isqrt(2**63-1) */ (Tcl_WideInt)2097151, (Tcl_WideInt)55108, (Tcl_WideInt)6208, (Tcl_WideInt)1448, (Tcl_WideInt)511, (Tcl_WideInt)234, (Tcl_WideInt)127, (Tcl_WideInt)78, (Tcl_WideInt)52, (Tcl_WideInt)38, (Tcl_WideInt)28, (Tcl_WideInt)22, (Tcl_WideInt)18, (Tcl_WideInt)15 }; static const size_t MaxBase64Size = sizeof(MaxBase64)/sizeof(Tcl_WideInt); /* * Table giving 3, 4, ..., 13 raised to powers greater than 16 when the * results fit in a 64-bit signed integer. */ static const unsigned short Exp64Index[] = { 0, 23, 38, 49, 57, 63, 67, 70, 72, 74, 75, 76 }; static const size_t Exp64IndexSize = sizeof(Exp64Index) / sizeof(unsigned short); static const Tcl_WideInt Exp64Value[] = { (Tcl_WideInt)243*243*243*3*3, (Tcl_WideInt)243*243*243*3*3*3, (Tcl_WideInt)243*243*243*3*3*3*3, (Tcl_WideInt)243*243*243*243, (Tcl_WideInt)243*243*243*243*3, (Tcl_WideInt)243*243*243*243*3*3, (Tcl_WideInt)243*243*243*243*3*3*3, (Tcl_WideInt)243*243*243*243*3*3*3*3, (Tcl_WideInt)243*243*243*243*243, (Tcl_WideInt)243*243*243*243*243*3, (Tcl_WideInt)243*243*243*243*243*3*3, (Tcl_WideInt)243*243*243*243*243*3*3*3, (Tcl_WideInt)243*243*243*243*243*3*3*3*3, (Tcl_WideInt)243*243*243*243*243*243, (Tcl_WideInt)243*243*243*243*243*243*3, (Tcl_WideInt)243*243*243*243*243*243*3*3, (Tcl_WideInt)243*243*243*243*243*243*3*3*3, (Tcl_WideInt)243*243*243*243*243*243*3*3*3*3, (Tcl_WideInt)243*243*243*243*243*243*243, (Tcl_WideInt)243*243*243*243*243*243*243*3, (Tcl_WideInt)243*243*243*243*243*243*243*3*3, (Tcl_WideInt)243*243*243*243*243*243*243*3*3*3, (Tcl_WideInt)243*243*243*243*243*243*243*3*3*3*3, (Tcl_WideInt)1024*1024*1024*4*4, (Tcl_WideInt)1024*1024*1024*4*4*4, (Tcl_WideInt)1024*1024*1024*4*4*4*4, (Tcl_WideInt)1024*1024*1024*1024, (Tcl_WideInt)1024*1024*1024*1024*4, (Tcl_WideInt)1024*1024*1024*1024*4*4, (Tcl_WideInt)1024*1024*1024*1024*4*4*4, (Tcl_WideInt)1024*1024*1024*1024*4*4*4*4, (Tcl_WideInt)1024*1024*1024*1024*1024, (Tcl_WideInt)1024*1024*1024*1024*1024*4, (Tcl_WideInt)1024*1024*1024*1024*1024*4*4, (Tcl_WideInt)1024*1024*1024*1024*1024*4*4*4, (Tcl_WideInt)1024*1024*1024*1024*1024*4*4*4*4, (Tcl_WideInt)1024*1024*1024*1024*1024*1024, (Tcl_WideInt)1024*1024*1024*1024*1024*1024*4, (Tcl_WideInt)3125*3125*3125*5*5, (Tcl_WideInt)3125*3125*3125*5*5*5, (Tcl_WideInt)3125*3125*3125*5*5*5*5, (Tcl_WideInt)3125*3125*3125*3125, (Tcl_WideInt)3125*3125*3125*3125*5, (Tcl_WideInt)3125*3125*3125*3125*5*5, (Tcl_WideInt)3125*3125*3125*3125*5*5*5, (Tcl_WideInt)3125*3125*3125*3125*5*5*5*5, (Tcl_WideInt)3125*3125*3125*3125*3125, (Tcl_WideInt)3125*3125*3125*3125*3125*5, (Tcl_WideInt)3125*3125*3125*3125*3125*5*5, (Tcl_WideInt)7776*7776*7776*6*6, (Tcl_WideInt)7776*7776*7776*6*6*6, (Tcl_WideInt)7776*7776*7776*6*6*6*6, (Tcl_WideInt)7776*7776*7776*7776, (Tcl_WideInt)7776*7776*7776*7776*6, (Tcl_WideInt)7776*7776*7776*7776*6*6, (Tcl_WideInt)7776*7776*7776*7776*6*6*6, (Tcl_WideInt)7776*7776*7776*7776*6*6*6*6, (Tcl_WideInt)16807*16807*16807*7*7, (Tcl_WideInt)16807*16807*16807*7*7*7, (Tcl_WideInt)16807*16807*16807*7*7*7*7, (Tcl_WideInt)16807*16807*16807*16807, (Tcl_WideInt)16807*16807*16807*16807*7, (Tcl_WideInt)16807*16807*16807*16807*7*7, (Tcl_WideInt)32768*32768*32768*8*8, (Tcl_WideInt)32768*32768*32768*8*8*8, (Tcl_WideInt)32768*32768*32768*8*8*8*8, (Tcl_WideInt)32768*32768*32768*32768, (Tcl_WideInt)59049*59049*59049*9*9, (Tcl_WideInt)59049*59049*59049*9*9*9, (Tcl_WideInt)59049*59049*59049*9*9*9*9, (Tcl_WideInt)100000*100000*100000*10*10, (Tcl_WideInt)100000*100000*100000*10*10*10, (Tcl_WideInt)161051*161051*161051*11*11, (Tcl_WideInt)161051*161051*161051*11*11*11, (Tcl_WideInt)248832*248832*248832*12*12, (Tcl_WideInt)371293*371293*371293*13*13 }; static const size_t Exp64ValueSize = sizeof(Exp64Value) / sizeof(Tcl_WideInt); #endif /* (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) */ /* * Markers for ExecuteExtendedBinaryMathOp. */ #define DIVIDED_BY_ZERO ((Tcl_Obj *) -1) #define EXPONENT_OF_ZERO ((Tcl_Obj *) -2) #define GENERAL_ARITHMETIC_ERROR ((Tcl_Obj *) -3) /* * Declarations for local procedures to this file: */ #ifdef TCL_COMPILE_STATS static int EvalStatsCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); #endif /* TCL_COMPILE_STATS */ #ifdef TCL_COMPILE_DEBUG static const char * GetOpcodeName(const unsigned char *pc); static void PrintByteCodeInfo(ByteCode *codePtr); static const char * StringForResultCode(int result); static void ValidatePcAndStackTop(ByteCode *codePtr, const unsigned char *pc, int stackTop, int checkStack); #endif /* TCL_COMPILE_DEBUG */ static ByteCode * CompileExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr); static void DeleteExecStack(ExecStack *esPtr); static void DupExprCodeInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); MODULE_SCOPE int TclCompareTwoNumbers(Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr); static Tcl_Obj * ExecuteExtendedBinaryMathOp(Tcl_Interp *interp, int opcode, Tcl_Obj **constants, Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr); static Tcl_Obj * ExecuteExtendedUnaryMathOp(int opcode, Tcl_Obj *valuePtr); static void FreeExprCodeInternalRep(Tcl_Obj *objPtr); static ExceptionRange * GetExceptRangeForPc(const unsigned char *pc, int searchMode, ByteCode *codePtr); static const char * GetSrcInfoForPc(const unsigned char *pc, ByteCode *codePtr, int *lengthPtr, const unsigned char **pcBeg, int *cmdIdxPtr); static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, int growth, int move); static void IllegalExprOperandType(Tcl_Interp *interp, const unsigned char *pc, Tcl_Obj *opndPtr); static void InitByteCodeExecution(Tcl_Interp *interp); static inline int wordSkip(void *ptr); static void ReleaseDictIterator(Tcl_Obj *objPtr); /* Useful elsewhere, make available in tclInt.h or stubs? */ static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, int numWords); static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, int numWords); static Tcl_NRPostProc CopyCallback; static Tcl_NRPostProc ExprObjCallback; static Tcl_NRPostProc FinalizeOONext; static Tcl_NRPostProc FinalizeOONextFilter; static Tcl_NRPostProc TEBCresume; /* * The structure below defines a bytecode Tcl object type to hold the * compiled bytecode for Tcl expressions. */ static const Tcl_ObjType exprCodeType = { "exprcode", FreeExprCodeInternalRep, /* freeIntRepProc */ DupExprCodeInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ NULL /* setFromAnyProc */ }; /* * Custom object type only used in this file; values of its type should never * be seen by user scripts. */ static const Tcl_ObjType dictIteratorType = { "dictIterator", ReleaseDictIterator, NULL, NULL, NULL }; /* *---------------------------------------------------------------------- * * ReleaseDictIterator -- * * This takes apart a dictionary iterator that is stored in the given Tcl * object. * * Results: * None. * * Side effects: * Deallocates memory, marks the object as being untyped. * *---------------------------------------------------------------------- */ static void ReleaseDictIterator( Tcl_Obj *objPtr) { Tcl_DictSearch *searchPtr; Tcl_Obj *dictPtr; /* * First kill the search, and then release the reference to the dictionary * that we were holding. */ searchPtr = objPtr->internalRep.twoPtrValue.ptr1; Tcl_DictObjDone(searchPtr); ckfree(searchPtr); dictPtr = objPtr->internalRep.twoPtrValue.ptr2; TclDecrRefCount(dictPtr); objPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * InitByteCodeExecution -- * * This procedure is called once to initialize the Tcl bytecode * interpreter. * * Results: * None. * * Side effects: * This procedure initializes the array of instruction names. If * compiling with the TCL_COMPILE_STATS flag, it initializes the array * that counts the executions of each instruction and it creates the * "evalstats" command. It also establishes the link between the Tcl * "tcl_traceExec" and C "tclTraceExec" variables. * *---------------------------------------------------------------------- */ static void InitByteCodeExecution( Tcl_Interp *interp) /* Interpreter for which the Tcl variable * "tcl_traceExec" is linked to control * instruction tracing. */ { #ifdef TCL_COMPILE_DEBUG if (Tcl_LinkVar(interp, "tcl_traceExec", (char *) &tclTraceExec, TCL_LINK_INT) != TCL_OK) { Tcl_Panic("InitByteCodeExecution: can't create link for tcl_traceExec variable"); } #endif #ifdef TCL_COMPILE_STATS Tcl_CreateObjCommand(interp, "evalstats", EvalStatsCmd, NULL, NULL); #endif /* TCL_COMPILE_STATS */ } /* *---------------------------------------------------------------------- * * TclCreateExecEnv -- * * This procedure creates a new execution environment for Tcl bytecode * execution. An ExecEnv points to a Tcl evaluation stack. An ExecEnv is * typically created once for each Tcl interpreter (Interp structure) and * recursively passed to TclNRExecuteByteCode to execute ByteCode sequences * for nested commands. * * Results: * A newly allocated ExecEnv is returned. This points to an empty * evaluation stack of the standard initial size. * * Side effects: * The bytecode interpreter is also initialized here, as this procedure * will be called before any call to TclNRExecuteByteCode. * *---------------------------------------------------------------------- */ ExecEnv * TclCreateExecEnv( Tcl_Interp *interp, /* Interpreter for which the execution * environment is being created. */ int size) /* The initial stack size, in number of words * [sizeof(Tcl_Obj*)] */ { ExecEnv *eePtr = ckalloc(sizeof(ExecEnv)); ExecStack *esPtr = ckalloc(sizeof(ExecStack) + (size_t) (size-1) * sizeof(Tcl_Obj *)); eePtr->execStackPtr = esPtr; TclNewBooleanObj(eePtr->constants[0], 0); Tcl_IncrRefCount(eePtr->constants[0]); TclNewBooleanObj(eePtr->constants[1], 1); Tcl_IncrRefCount(eePtr->constants[1]); eePtr->interp = interp; eePtr->callbackPtr = NULL; eePtr->corPtr = NULL; eePtr->rewind = 0; esPtr->prevPtr = NULL; esPtr->nextPtr = NULL; esPtr->markerPtr = NULL; esPtr->endPtr = &esPtr->stackWords[size-1]; esPtr->tosPtr = STACK_BASE(esPtr); Tcl_MutexLock(&execMutex); if (!execInitialized) { InitByteCodeExecution(interp); execInitialized = 1; } Tcl_MutexUnlock(&execMutex); return eePtr; } /* *---------------------------------------------------------------------- * * TclDeleteExecEnv -- * * Frees the storage for an ExecEnv. * * Results: * None. * * Side effects: * Storage for an ExecEnv and its contained storage (e.g. the evaluation * stack) is freed. * *---------------------------------------------------------------------- */ static void DeleteExecStack( ExecStack *esPtr) { if (esPtr->markerPtr && !cachedInExit) { Tcl_Panic("freeing an execStack which is still in use"); } if (esPtr->prevPtr) { esPtr->prevPtr->nextPtr = esPtr->nextPtr; } if (esPtr->nextPtr) { esPtr->nextPtr->prevPtr = esPtr->prevPtr; } ckfree(esPtr); } void TclDeleteExecEnv( ExecEnv *eePtr) /* Execution environment to free. */ { ExecStack *esPtr = eePtr->execStackPtr, *tmpPtr; cachedInExit = TclInExit(); /* * Delete all stacks in this exec env. */ while (esPtr->nextPtr) { esPtr = esPtr->nextPtr; } while (esPtr) { tmpPtr = esPtr; esPtr = tmpPtr->prevPtr; DeleteExecStack(tmpPtr); } TclDecrRefCount(eePtr->constants[0]); TclDecrRefCount(eePtr->constants[1]); if (eePtr->callbackPtr && !cachedInExit) { Tcl_Panic("Deleting execEnv with pending TEOV callbacks!"); } if (eePtr->corPtr && !cachedInExit) { Tcl_Panic("Deleting execEnv with existing coroutine"); } ckfree(eePtr); } /* *---------------------------------------------------------------------- * * TclFinalizeExecution -- * * Finalizes the execution environment setup so that it can be later * reinitialized. * * Results: * None. * * Side effects: * After this call, the next time TclCreateExecEnv will be called it will * call InitByteCodeExecution. * *---------------------------------------------------------------------- */ void TclFinalizeExecution(void) { Tcl_MutexLock(&execMutex); execInitialized = 0; Tcl_MutexUnlock(&execMutex); } /* * Auxiliary code to insure that GrowEvaluationStack always returns correctly * aligned memory. * * WALLOCALIGN represents the alignment reqs in words, just as TCL_ALLOCALIGN * represents the reqs in bytes. This assumes that TCL_ALLOCALIGN is a * multiple of the wordsize 'sizeof(Tcl_Obj *)'. */ #define WALLOCALIGN \ (TCL_ALLOCALIGN/sizeof(Tcl_Obj *)) /* * wordSkip computes how many words have to be skipped until the next aligned * word. Note that we are only interested in the low order bits of ptr, so * that any possible information loss in PTR2INT is of no consequence. */ static inline int wordSkip( void *ptr) { int mask = TCL_ALLOCALIGN-1; int base = PTR2INT(ptr) & mask; return (TCL_ALLOCALIGN - base)/sizeof(Tcl_Obj *); } /* * Given a marker, compute where the following aligned memory starts. */ #define MEMSTART(markerPtr) \ ((markerPtr) + wordSkip(markerPtr)) /* *---------------------------------------------------------------------- * * GrowEvaluationStack -- * * This procedure grows a Tcl evaluation stack stored in an ExecEnv, * copying over the words since the last mark if so requested. A mark is * set at the beginning of the new area when no copying is requested. * * Results: * Returns a pointer to the first usable word in the (possibly) grown * stack. * * Side effects: * The size of the evaluation stack may be grown, a marker is set * *---------------------------------------------------------------------- */ static Tcl_Obj ** GrowEvaluationStack( ExecEnv *eePtr, /* Points to the ExecEnv with an evaluation * stack to enlarge. */ int growth, /* How much larger than the current used * size. */ int move) /* 1 if move words since last marker. */ { ExecStack *esPtr = eePtr->execStackPtr, *oldPtr = NULL; int newBytes, newElems, currElems; int needed = growth - (esPtr->endPtr - esPtr->tosPtr); Tcl_Obj **markerPtr = esPtr->markerPtr, **memStart; int moveWords = 0; if (move) { if (!markerPtr) { Tcl_Panic("STACK: Reallocating with no previous alloc"); } if (needed <= 0) { return MEMSTART(markerPtr); } } else { #ifndef PURIFY Tcl_Obj **tmpMarkerPtr = esPtr->tosPtr + 1; int offset = wordSkip(tmpMarkerPtr); if (needed + offset < 0) { /* * Put a marker pointing to the previous marker in this stack, and * store it in esPtr as the current marker. Return a pointer to * the start of aligned memory. */ esPtr->markerPtr = tmpMarkerPtr; memStart = tmpMarkerPtr + offset; esPtr->tosPtr = memStart - 1; *esPtr->markerPtr = (Tcl_Obj *) markerPtr; return memStart; } #endif } /* * Reset move to hold the number of words to be moved to new stack (if * any) and growth to hold the complete stack requirements: add one for * the marker, (WALLOCALIGN-1) for the maximal possible offset. */ if (move) { moveWords = esPtr->tosPtr - MEMSTART(markerPtr) + 1; } needed = growth + moveWords + WALLOCALIGN; /* * Check if there is enough room in the next stack (if there is one, it * should be both empty and the last one!) */ if (esPtr->nextPtr) { oldPtr = esPtr; esPtr = oldPtr->nextPtr; currElems = esPtr->endPtr - STACK_BASE(esPtr); if (esPtr->markerPtr || (esPtr->tosPtr != STACK_BASE(esPtr))) { Tcl_Panic("STACK: Stack after current is in use"); } if (esPtr->nextPtr) { Tcl_Panic("STACK: Stack after current is not last"); } if (needed <= currElems) { goto newStackReady; } DeleteExecStack(esPtr); esPtr = oldPtr; } else { currElems = esPtr->endPtr - STACK_BASE(esPtr); } /* * We need to allocate a new stack! It needs to store 'growth' words, * including the elements to be copied over and the new marker. */ #ifndef PURIFY newElems = 2*currElems; while (needed > newElems) { newElems *= 2; } #else newElems = needed; #endif newBytes = sizeof(ExecStack) + (newElems-1) * sizeof(Tcl_Obj *); oldPtr = esPtr; esPtr = ckalloc(newBytes); oldPtr->nextPtr = esPtr; esPtr->prevPtr = oldPtr; esPtr->nextPtr = NULL; esPtr->endPtr = &esPtr->stackWords[newElems-1]; newStackReady: eePtr->execStackPtr = esPtr; /* * Store a NULL marker at the beginning of the stack, to indicate that * this is the first marker in this stack and that rewinding to here * should actually be a return to the previous stack. */ esPtr->stackWords[0] = NULL; esPtr->markerPtr = &esPtr->stackWords[0]; memStart = MEMSTART(esPtr->markerPtr); esPtr->tosPtr = memStart - 1; if (move) { memcpy(memStart, MEMSTART(markerPtr), moveWords*sizeof(Tcl_Obj *)); esPtr->tosPtr += moveWords; oldPtr->markerPtr = (Tcl_Obj **) *markerPtr; oldPtr->tosPtr = markerPtr-1; } /* * Free the old stack if it is now unused. */ if (!oldPtr->markerPtr) { DeleteExecStack(oldPtr); } return memStart; } /* *-------------------------------------------------------------- * * TclStackAlloc, TclStackRealloc, TclStackFree -- * * Allocate memory from the execution stack; it has to be returned later * with a call to TclStackFree. * * Results: * A pointer to the first byte allocated, or panics if the allocation did * not succeed. * * Side effects: * The execution stack may be grown. * *-------------------------------------------------------------- */ static Tcl_Obj ** StackAllocWords( Tcl_Interp *interp, int numWords) { /* * Note that GrowEvaluationStack sets a marker in the stack. This marker * is read when rewinding, e.g., by TclStackFree. */ Interp *iPtr = (Interp *) interp; ExecEnv *eePtr = iPtr->execEnvPtr; Tcl_Obj **resPtr = GrowEvaluationStack(eePtr, numWords, 0); eePtr->execStackPtr->tosPtr += numWords; return resPtr; } static Tcl_Obj ** StackReallocWords( Tcl_Interp *interp, int numWords) { Interp *iPtr = (Interp *) interp; ExecEnv *eePtr = iPtr->execEnvPtr; Tcl_Obj **resPtr = GrowEvaluationStack(eePtr, numWords, 1); eePtr->execStackPtr->tosPtr += numWords; return resPtr; } void TclStackFree( Tcl_Interp *interp, void *freePtr) { Interp *iPtr = (Interp *) interp; ExecEnv *eePtr; ExecStack *esPtr; Tcl_Obj **markerPtr, *marker; if (iPtr == NULL || iPtr->execEnvPtr == NULL) { ckfree((char *) freePtr); return; } /* * Rewind the stack to the previous marker position. The current marker, * as set in the last call to GrowEvaluationStack, contains a pointer to * the previous marker. */ eePtr = iPtr->execEnvPtr; esPtr = eePtr->execStackPtr; markerPtr = esPtr->markerPtr; marker = *markerPtr; if ((freePtr != NULL) && (MEMSTART(markerPtr) != (Tcl_Obj **)freePtr)) { Tcl_Panic("TclStackFree: incorrect freePtr (%p != %p). Call out of sequence?", freePtr, MEMSTART(markerPtr)); } esPtr->tosPtr = markerPtr - 1; esPtr->markerPtr = (Tcl_Obj **) marker; if (marker) { return; } /* * Return to previous active stack. Note that repeated expansions or * reallocs could have generated several unused intervening stacks: free * them too. */ while (esPtr->nextPtr) { esPtr = esPtr->nextPtr; } esPtr->tosPtr = STACK_BASE(esPtr); while (esPtr->prevPtr) { ExecStack *tmpPtr = esPtr->prevPtr; if (tmpPtr->tosPtr == STACK_BASE(tmpPtr)) { DeleteExecStack(tmpPtr); } else { break; } } if (esPtr->prevPtr) { eePtr->execStackPtr = esPtr->prevPtr; #ifdef PURIFY eePtr->execStackPtr->nextPtr = NULL; DeleteExecStack(esPtr); #endif } else { eePtr->execStackPtr = esPtr; } } void * TclStackAlloc( Tcl_Interp *interp, int numBytes) { Interp *iPtr = (Interp *) interp; int numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *); if (iPtr == NULL || iPtr->execEnvPtr == NULL) { return (void *) ckalloc(numBytes); } return (void *) StackAllocWords(interp, numWords); } void * TclStackRealloc( Tcl_Interp *interp, void *ptr, int numBytes) { Interp *iPtr = (Interp *) interp; ExecEnv *eePtr; ExecStack *esPtr; Tcl_Obj **markerPtr; int numWords; if (iPtr == NULL || iPtr->execEnvPtr == NULL) { return (void *) ckrealloc((char *) ptr, numBytes); } eePtr = iPtr->execEnvPtr; esPtr = eePtr->execStackPtr; markerPtr = esPtr->markerPtr; if (MEMSTART(markerPtr) != (Tcl_Obj **)ptr) { Tcl_Panic("TclStackRealloc: incorrect ptr. Call out of sequence?"); } numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *); return (void *) StackReallocWords(interp, numWords); } /* *-------------------------------------------------------------- * * Tcl_ExprObj -- * * Evaluate an expression in a Tcl_Obj. * * Results: * A standard Tcl object result. If the result is other than TCL_OK, then * the interpreter's result contains an error message. If the result is * TCL_OK, then a pointer to the expression's result value object is * stored in resultPtrPtr. In that case, the object's ref count is * incremented to reflect the reference returned to the caller; the * caller is then responsible for the resulting object and must, for * example, decrement the ref count when it is finished with the object. * * Side effects: * Any side effects caused by subcommands in the expression, if any. The * interpreter result is not modified unless there is an error. * *-------------------------------------------------------------- */ int Tcl_ExprObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ register Tcl_Obj *objPtr, /* Points to Tcl object containing expression * to evaluate. */ Tcl_Obj **resultPtrPtr) /* Where the Tcl_Obj* that is the expression * result is stored if no errors occur. */ { NRE_callback *rootPtr = TOP_CB(interp); Tcl_Obj *resultPtr; TclNewObj(resultPtr); TclNRAddCallback(interp, CopyCallback, resultPtrPtr, resultPtr, NULL, NULL); Tcl_NRExprObj(interp, objPtr, resultPtr); return TclNRRunCallbacks(interp, TCL_OK, rootPtr); } static int CopyCallback( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj **resultPtrPtr = data[0]; Tcl_Obj *resultPtr = data[1]; if (result == TCL_OK) { *resultPtrPtr = resultPtr; Tcl_IncrRefCount(resultPtr); } else { Tcl_DecrRefCount(resultPtr); } return result; } /* *-------------------------------------------------------------- * * Tcl_NRExprObj -- * * Request evaluation of the expression in a Tcl_Obj by the NR stack. * * Results: * Returns TCL_OK. * * Side effects: * Compiles objPtr as a Tcl expression and places callbacks on the * NR stack to execute the bytecode and store the result in resultPtr. * If bytecode execution raises an exception, nothing is written * to resultPtr, and the exceptional return code flows up the NR * stack. If the exception is TCL_ERROR, an error message is left * in the interp result and the interp's return options dictionary * holds additional error information too. Execution of the bytecode * may have other side effects, depending on the expression. * *-------------------------------------------------------------- */ int Tcl_NRExprObj( Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj *resultPtr) { ByteCode *codePtr; Tcl_InterpState state = Tcl_SaveInterpState(interp, TCL_OK); Tcl_ResetResult(interp); codePtr = CompileExprObj(interp, objPtr); Tcl_NRAddCallback(interp, ExprObjCallback, state, resultPtr, NULL, NULL); return TclNRExecuteByteCode(interp, codePtr); } static int ExprObjCallback( ClientData data[], Tcl_Interp *interp, int result) { Tcl_InterpState state = data[0]; Tcl_Obj *resultPtr = data[1]; if (result == TCL_OK) { TclSetDuplicateObj(resultPtr, Tcl_GetObjResult(interp)); (void) Tcl_RestoreInterpState(interp, state); } else { Tcl_DiscardInterpState(state); } return result; } /* *---------------------------------------------------------------------- * * CompileExprObj -- * Compile a Tcl expression value into ByteCode. * * Results: * A (ByteCode *) is returned pointing to the resulting ByteCode. * The caller must manage its refCount and arrange for a call to * TclCleanupByteCode() when the last reference disappears. * * Side effects: * The Tcl_ObjType of objPtr is changed to the "bytecode" type, * and the ByteCode is kept in the internal rep (along with context * data for checking validity) for faster operations the next time * CompileExprObj is called on the same value. * *---------------------------------------------------------------------- */ static ByteCode * CompileExprObj( Tcl_Interp *interp, Tcl_Obj *objPtr) { Interp *iPtr = (Interp *) interp; CompileEnv compEnv; /* Compilation environment structure allocated * in frame. */ register ByteCode *codePtr = NULL; /* Tcl Internal type of bytecode. Initialized * to avoid compiler warning. */ /* * Get the expression ByteCode from the object. If it exists, make sure it * is valid in the current context. */ if (objPtr->typePtr == &exprCodeType) { Namespace *namespacePtr = iPtr->varFramePtr->nsPtr; codePtr = objPtr->internalRep.twoPtrValue.ptr1; if (((Interp *) *codePtr->interpHandle != iPtr) || (codePtr->compileEpoch != iPtr->compileEpoch) || (codePtr->nsPtr != namespacePtr) || (codePtr->nsEpoch != namespacePtr->resolverEpoch) || (codePtr->localCachePtr != iPtr->varFramePtr->localCachePtr)) { FreeExprCodeInternalRep(objPtr); } } if (objPtr->typePtr != &exprCodeType) { /* * TIP #280: No invoker (yet) - Expression compilation. */ int length; const char *string = TclGetStringFromObj(objPtr, &length); TclInitCompileEnv(interp, &compEnv, string, length, NULL, 0); TclCompileExpr(interp, string, length, &compEnv, 0); /* * Successful compilation. If the expression yielded no instructions, * push an zero object as the expression's result. */ if (compEnv.codeNext == compEnv.codeStart) { TclEmitPush(TclRegisterNewLiteral(&compEnv, "0", 1), &compEnv); } /* * Add a "done" instruction as the last instruction and change the * object into a ByteCode object. Ownership of the literal objects and * aux data items is given to the ByteCode object. */ TclEmitOpcode(INST_DONE, &compEnv); TclInitByteCodeObj(objPtr, &compEnv); objPtr->typePtr = &exprCodeType; TclFreeCompileEnv(&compEnv); codePtr = objPtr->internalRep.twoPtrValue.ptr1; if (iPtr->varFramePtr->localCachePtr) { codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr; codePtr->localCachePtr->refCount++; } #ifdef TCL_COMPILE_DEBUG if (tclTraceCompile == 2) { TclPrintByteCodeObj(interp, objPtr); fflush(stdout); } #endif /* TCL_COMPILE_DEBUG */ } return codePtr; } /* *---------------------------------------------------------------------- * * DupExprCodeInternalRep -- * * Part of the Tcl object type implementation for Tcl expression * bytecode. We do not copy the bytecode intrep. Instead, we return * without setting copyPtr->typePtr, so the copy is a plain string copy * of the expression value, and if it is to be used as a compiled * expression, it will just need a recompile. * * This makes sense, because with Tcl's copy-on-write practices, the * usual (only?) time Tcl_DuplicateObj() will be called is when the copy * is about to be modified, which would invalidate any copied bytecode * anyway. The only reason it might make sense to copy the bytecode is if * we had some modifying routines that operated directly on the intrep, * like we do for lists and dicts. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void DupExprCodeInternalRep( Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) { return; } /* *---------------------------------------------------------------------- * * FreeExprCodeInternalRep -- * * Part of the Tcl object type implementation for Tcl expression * bytecode. Frees the storage allocated to hold the internal rep, unless * ref counts indicate bytecode execution is still in progress. * * Results: * None. * * Side effects: * May free allocated memory. Leaves objPtr untyped. * *---------------------------------------------------------------------- */ static void FreeExprCodeInternalRep( Tcl_Obj *objPtr) { ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr1; objPtr->typePtr = NULL; if (codePtr->refCount-- <= 1) { TclCleanupByteCode(codePtr); } } /* *---------------------------------------------------------------------- * * TclCompileObj -- * * This procedure compiles the script contained in a Tcl_Obj. * * Results: * A pointer to the corresponding ByteCode, never NULL. * * Side effects: * The object is shimmered to bytecode type. * *---------------------------------------------------------------------- */ ByteCode * TclCompileObj( Tcl_Interp *interp, Tcl_Obj *objPtr, const CmdFrame *invoker, int word) { register Interp *iPtr = (Interp *) interp; register ByteCode *codePtr; /* Tcl Internal type of bytecode. */ Namespace *namespacePtr = iPtr->varFramePtr->nsPtr; /* * If the object is not already of tclByteCodeType, compile it (and reset * the compilation flags in the interpreter; this should be done after any * compilation). Otherwise, check that it is "fresh" enough. */ if (objPtr->typePtr == &tclByteCodeType) { /* * Make sure the Bytecode hasn't been invalidated by, e.g., someone * redefining a command with a compile procedure (this might make the * compiled code wrong). The object needs to be recompiled if it was * compiled in/for a different interpreter, or for a different * namespace, or for the same namespace but with different name * resolution rules. Precompiled objects, however, are immutable and * therefore they are not recompiled, even if the epoch has changed. * * To be pedantically correct, we should also check that the * originating procPtr is the same as the current context procPtr * (assuming one exists at all - none for global level). This code is * #def'ed out because [info body] was changed to never return a * bytecode type object, which should obviate us from the extra checks * here. */ codePtr = objPtr->internalRep.twoPtrValue.ptr1; if (((Interp *) *codePtr->interpHandle != iPtr) || (codePtr->compileEpoch != iPtr->compileEpoch) || (codePtr->nsPtr != namespacePtr) || (codePtr->nsEpoch != namespacePtr->resolverEpoch)) { if (!(codePtr->flags & TCL_BYTECODE_PRECOMPILED)) { goto recompileObj; } if ((Interp *) *codePtr->interpHandle != iPtr) { Tcl_Panic("Tcl_EvalObj: compiled script jumped interps"); } codePtr->compileEpoch = iPtr->compileEpoch; } /* * Check that any compiled locals do refer to the current proc * environment! If not, recompile. */ if (!(codePtr->flags & TCL_BYTECODE_PRECOMPILED) && (codePtr->procPtr == NULL) && (codePtr->localCachePtr != iPtr->varFramePtr->localCachePtr)){ goto recompileObj; } /* * #280. * Literal sharing fix. This part of the fix is not required by 8.4 * nor 8.5, because they eval-direct any literals, so just saving the * argument locations per command in bytecode is enough, embedded * 'eval' commands, etc. get the correct information. * * But in 8.6 all the embedded script are compiled, and the resulting * bytecode stored in the literal. Now the shared literal has bytecode * with location data for _one_ particular location this literal is * found at. If we get executed from a different location the bytecode * has to be recompiled to get the correct locations. Not doing this * will execute the saved bytecode with data for a different location, * causing 'info frame' to point to the wrong place in the sources. * * Future optimizations ... * (1) Save the location data (ExtCmdLoc) keyed by start line. In that * case we recompile once per location of the literal, but not * continously, because the moment we have all locations we do not * need to recompile any longer. * * (2) Alternative: Do not recompile, tell the execution engine the * offset between saved starting line and actual one. Then modify * the users to adjust the locations they have by this offset. * * (3) Alternative 2: Do not fully recompile, adjust just the location * information. */ if (invoker == NULL) { return codePtr; } else { Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr); ExtCmdLoc *eclPtr; CmdFrame *ctxCopyPtr; int redo; if (!hePtr) { return codePtr; } eclPtr = Tcl_GetHashValue(hePtr); redo = 0; ctxCopyPtr = TclStackAlloc(interp, sizeof(CmdFrame)); *ctxCopyPtr = *invoker; if (invoker->type == TCL_LOCATION_BC) { /* * Note: Type BC => ctx.data.eval.path is not used. * ctx.data.tebc.codePtr used instead */ TclGetSrcInfoForPc(ctxCopyPtr); if (ctxCopyPtr->type == TCL_LOCATION_SOURCE) { /* * The reference made by 'TclGetSrcInfoForPc' is dead. */ Tcl_DecrRefCount(ctxCopyPtr->data.eval.path); ctxCopyPtr->data.eval.path = NULL; } } if (word < ctxCopyPtr->nline) { /* * Note: We do not care if the line[word] is -1. This is a * difference and requires a recompile (location changed from * absolute to relative, literal is used fixed and through * variable) * * Example: * test info-32.0 using literal of info-24.8 * (dict with ... vs set body ...). */ redo = ((eclPtr->type == TCL_LOCATION_SOURCE) && (eclPtr->start != ctxCopyPtr->line[word])) || ((eclPtr->type == TCL_LOCATION_BC) && (ctxCopyPtr->type == TCL_LOCATION_SOURCE)); } TclStackFree(interp, ctxCopyPtr); if (!redo) { return codePtr; } } } recompileObj: iPtr->errorLine = 1; /* * TIP #280. Remember the invoker for a moment in the interpreter * structures so that the byte code compiler can pick it up when * initializing the compilation environment, i.e. the extended location * information. */ iPtr->invokeCmdFramePtr = invoker; iPtr->invokeWord = word; TclSetByteCodeFromAny(interp, objPtr, NULL, NULL); iPtr->invokeCmdFramePtr = NULL; codePtr = objPtr->internalRep.twoPtrValue.ptr1; if (iPtr->varFramePtr->localCachePtr) { codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr; codePtr->localCachePtr->refCount++; } return codePtr; } /* *---------------------------------------------------------------------- * * TclIncrObj -- * * Increment an integeral value in a Tcl_Obj by an integeral value held * in another Tcl_Obj. Caller is responsible for making sure we can * update the first object. * * Results: * TCL_ERROR if either object is non-integer, and TCL_OK otherwise. On * error, an error message is left in the interpreter (if it is not NULL, * of course). * * Side effects: * valuePtr gets the new incrmented value. * *---------------------------------------------------------------------- */ int TclIncrObj( Tcl_Interp *interp, Tcl_Obj *valuePtr, Tcl_Obj *incrPtr) { ClientData ptr1, ptr2; int type1, type2; mp_int value, incr; if (Tcl_IsShared(valuePtr)) { Tcl_Panic("%s called with shared object", "TclIncrObj"); } if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) { /* * Produce error message (reparse?!) */ return TclGetIntFromObj(interp, valuePtr, &type1); } if (GetNumberFromObj(NULL, incrPtr, &ptr2, &type2) != TCL_OK) { /* * Produce error message (reparse?!) */ TclGetIntFromObj(interp, incrPtr, &type1); Tcl_AddErrorInfo(interp, "\n (reading increment)"); return TCL_ERROR; } if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { long augend = *((const long *) ptr1); long addend = *((const long *) ptr2); long sum = augend + addend; /* * Overflow when (augend and sum have different sign) and (augend and * addend have the same sign). This is encapsulated in the Overflowing * macro. */ if (!Overflowing(augend, addend, sum)) { TclSetLongObj(valuePtr, sum); return TCL_OK; } #ifndef TCL_WIDE_INT_IS_LONG { Tcl_WideInt w1 = (Tcl_WideInt) augend; Tcl_WideInt w2 = (Tcl_WideInt) addend; /* * We know the sum value is outside the long range, so we use the * macro form that doesn't range test again. */ TclSetWideIntObj(valuePtr, w1 + w2); return TCL_OK; } #endif } if ((type1 == TCL_NUMBER_DOUBLE) || (type1 == TCL_NUMBER_NAN)) { /* * Produce error message (reparse?!) */ return TclGetIntFromObj(interp, valuePtr, &type1); } if ((type2 == TCL_NUMBER_DOUBLE) || (type2 == TCL_NUMBER_NAN)) { /* * Produce error message (reparse?!) */ TclGetIntFromObj(interp, incrPtr, &type1); Tcl_AddErrorInfo(interp, "\n (reading increment)"); return TCL_ERROR; } #ifndef TCL_WIDE_INT_IS_LONG if ((type1 != TCL_NUMBER_BIG) && (type2 != TCL_NUMBER_BIG)) { Tcl_WideInt w1, w2, sum; TclGetWideIntFromObj(NULL, valuePtr, &w1); TclGetWideIntFromObj(NULL, incrPtr, &w2); sum = w1 + w2; /* * Check for overflow. */ if (!Overflowing(w1, w2, sum)) { Tcl_SetWideIntObj(valuePtr, sum); return TCL_OK; } } #endif Tcl_TakeBignumFromObj(interp, valuePtr, &value); Tcl_GetBignumFromObj(interp, incrPtr, &incr); mp_add(&value, &incr, &value); mp_clear(&incr); Tcl_SetBignumObj(valuePtr, &value); return TCL_OK; } /* *---------------------------------------------------------------------- * * ArgumentBCEnter -- * * This is a helper for TclNRExecuteByteCode/TEBCresume that encapsulates * a code sequence that is fairly common in the code but *not* commonly * called. * * Results: * None * * Side effects: * May register information about the bytecode in the command frame. * *---------------------------------------------------------------------- */ static void ArgumentBCEnter( Tcl_Interp *interp, ByteCode *codePtr, TEBCdata *tdPtr, const unsigned char *pc, int objc, Tcl_Obj **objv) { int cmd; if (GetSrcInfoForPc(pc, codePtr, NULL, NULL, &cmd)) { TclArgumentBCEnter(interp, objv, objc, codePtr, &tdPtr->cmdFrame, cmd, pc - codePtr->codeStart); } } /* *---------------------------------------------------------------------- * * TclNRExecuteByteCode -- * * This procedure executes the instructions of a ByteCode structure. It * returns when a "done" instruction is executed or an error occurs. * * Results: * The return value is one of the return codes defined in tcl.h (such as * TCL_OK), and interp->objResultPtr refers to a Tcl object that either * contains the result of executing the code or an error message. * * Side effects: * Almost certainly, depending on the ByteCode's instructions. * *---------------------------------------------------------------------- */ #define bcFramePtr (&TD->cmdFrame) #define initCatchTop ((ptrdiff_t *) (&TD->stack[-1])) #define initTosPtr ((Tcl_Obj **) (initCatchTop+codePtr->maxExceptDepth)) #define esPtr (iPtr->execEnvPtr->execStackPtr) int TclNRExecuteByteCode( Tcl_Interp *interp, /* Token for command interpreter. */ ByteCode *codePtr) /* The bytecode sequence to interpret. */ { Interp *iPtr = (Interp *) interp; TEBCdata *TD; int size = sizeof(TEBCdata) - 1 + (codePtr->maxStackDepth + codePtr->maxExceptDepth) * sizeof(void *); int numWords = (size + sizeof(Tcl_Obj *) - 1) / sizeof(Tcl_Obj *); codePtr->refCount++; /* * Reserve the stack, setup the TEBCdataPtr (TD) and CallFrame * * The execution uses a unified stack: first a TEBCdata, immediately * above it a CmdFrame, then the catch stack, then the execution stack. * * Make sure the catch stack is large enough to hold the maximum number of * catch commands that could ever be executing at the same time (this will * be no more than the exception range array's depth). Make sure the * execution stack is large enough to execute this ByteCode. */ TD = (TEBCdata *) GrowEvaluationStack(iPtr->execEnvPtr, numWords, 0); esPtr->tosPtr = initTosPtr; TD->codePtr = codePtr; TD->catchTop = initCatchTop; TD->auxObjList = NULL; /* * TIP #280: Initialize the frame. Do not push it yet: it will be pushed * every time that we call out from this TD, popped when we return to it. */ bcFramePtr->type = ((codePtr->flags & TCL_BYTECODE_PRECOMPILED) ? TCL_LOCATION_PREBC : TCL_LOCATION_BC); bcFramePtr->level = (iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level+1 : 1); bcFramePtr->framePtr = iPtr->framePtr; bcFramePtr->nextPtr = iPtr->cmdFramePtr; bcFramePtr->nline = 0; bcFramePtr->line = NULL; bcFramePtr->litarg = NULL; bcFramePtr->data.tebc.codePtr = codePtr; bcFramePtr->data.tebc.pc = NULL; bcFramePtr->cmdObj = NULL; bcFramePtr->cmd = NULL; bcFramePtr->len = 0; #ifdef TCL_COMPILE_STATS iPtr->stats.numExecutions++; #endif /* * Push the callback for bytecode execution */ TclNRAddCallback(interp, TEBCresume, TD, /* pc */ NULL, /* cleanup */ INT2PTR(0), NULL); return TCL_OK; } static int TEBCresume( ClientData data[], Tcl_Interp *interp, int result) { /* * Compiler cast directive - not a real variable. * Interp *iPtr = (Interp *) interp; */ #define iPtr ((Interp *) interp) /* * Check just the read-traced/write-traced bit of a variable. */ #define ReadTraced(varPtr) ((varPtr)->flags & VAR_TRACED_READ) #define WriteTraced(varPtr) ((varPtr)->flags & VAR_TRACED_WRITE) #define UnsetTraced(varPtr) ((varPtr)->flags & VAR_TRACED_UNSET) /* * Bottom of allocated stack holds the NR data */ /* * Constants: variables that do not change during the execution, used * sporadically: no special need for speed. */ int instructionCount = 0; /* Counter that is used to work out when to * call Tcl_AsyncReady() */ const char *curInstName; #ifdef TCL_COMPILE_DEBUG int traceInstructions; /* Whether we are doing instruction-level * tracing or not. */ #endif Var *compiledLocals = iPtr->varFramePtr->compiledLocals; Tcl_Obj **constants = &iPtr->execEnvPtr->constants[0]; #define LOCAL(i) (&compiledLocals[(i)]) #define TCONST(i) (constants[(i)]) /* * These macros are just meant to save some global variables that are not * used too frequently */ TEBCdata *TD = data[0]; #define auxObjList (TD->auxObjList) #define catchTop (TD->catchTop) #define codePtr (TD->codePtr) /* * Globals: variables that store state, must remain valid at all times. */ Tcl_Obj **tosPtr; /* Cached pointer to top of evaluation * stack. */ const unsigned char *pc = data[1]; /* The current program counter. */ unsigned char inst; /* The currently running instruction */ /* * Transfer variables - needed only between opcodes, but not while * executing an instruction. */ int cleanup = PTR2INT(data[2]); Tcl_Obj *objResultPtr; int checkInterp; /* Indicates when a check of interp readyness * is necessary. Set by CACHE_STACK_INFO() */ /* * Locals - variables that are used within opcodes or bounded sections of * the file (jumps between opcodes within a family). * NOTE: These are now mostly defined locally where needed. */ Tcl_Obj *objPtr, *valuePtr, *value2Ptr, *part1Ptr, *part2Ptr, *tmpPtr; Tcl_Obj **objv; int objc = 0; int opnd, length, pcAdjustment; Var *varPtr, *arrayPtr; #ifdef TCL_COMPILE_DEBUG char cmdNameBuf[21]; #endif #ifdef TCL_COMPILE_DEBUG int starting = 1; traceInstructions = (tclTraceExec == 3); #endif TEBC_DATA_DIG(); #ifdef TCL_COMPILE_DEBUG if (!pc && (tclTraceExec >= 2)) { PrintByteCodeInfo(codePtr); fprintf(stdout, " Starting stack top=%d\n", (int) CURR_DEPTH); fflush(stdout); } #endif if (!pc) { /* bytecode is starting from scratch */ checkInterp = 0; pc = codePtr->codeStart; goto cleanup0; } else { /* resume from invocation */ CACHE_STACK_INFO(); NRE_ASSERT(iPtr->cmdFramePtr == bcFramePtr); if (bcFramePtr->cmdObj) { Tcl_DecrRefCount(bcFramePtr->cmdObj); bcFramePtr->cmdObj = NULL; bcFramePtr->cmd = NULL; } iPtr->cmdFramePtr = bcFramePtr->nextPtr; if (iPtr->flags & INTERP_DEBUG_FRAME) { TclArgumentBCRelease(interp, bcFramePtr); } if (iPtr->execEnvPtr->rewind) { result = TCL_ERROR; goto abnormalReturn; } if (codePtr->flags & TCL_BYTECODE_RECOMPILE) { iPtr->flags |= ERR_ALREADY_LOGGED; codePtr->flags &= ~TCL_BYTECODE_RECOMPILE; } if (result != TCL_OK) { pc--; goto processExceptionReturn; } /* * Push the call's object result and continue execution with the next * instruction. */ TRACE_WITH_OBJ(("%u => ... after \"%.20s\": TCL_OK, result=", objc, cmdNameBuf), Tcl_GetObjResult(interp)); /* * Reset the interp's result to avoid possible duplications of large * objects [Bug 781585]. We do not call Tcl_ResetResult to avoid any * side effects caused by the resetting of errorInfo and errorCode * [Bug 804681], which are not needed here. We chose instead to * manipulate the interp's object result directly. * * Note that the result object is now in objResultPtr, it keeps the * refCount it had in its role of iPtr->objResultPtr. */ objResultPtr = Tcl_GetObjResult(interp); TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); iPtr->objResultPtr = objPtr; #ifndef TCL_COMPILE_DEBUG if (*pc == INST_POP) { TclDecrRefCount(objResultPtr); NEXT_INST_V(1, cleanup, 0); } #endif NEXT_INST_V(0, cleanup, -1); } /* * Targets for standard instruction endings; unrolled for speed in the * most frequent cases (instructions that consume up to two stack * elements). * * This used to be a "for(;;)" loop, with each instruction doing its own * cleanup. */ cleanupV_pushObjResultPtr: switch (cleanup) { case 0: *(++tosPtr) = (objResultPtr); goto cleanup0; default: cleanup -= 2; while (cleanup--) { objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); } case 2: cleanup2_pushObjResultPtr: objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); case 1: cleanup1_pushObjResultPtr: objPtr = OBJ_AT_TOS; TclDecrRefCount(objPtr); } OBJ_AT_TOS = objResultPtr; goto cleanup0; cleanupV: switch (cleanup) { default: cleanup -= 2; while (cleanup--) { objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); } case 2: cleanup2: objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); case 1: cleanup1: objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); case 0: /* * We really want to do nothing now, but this is needed for some * compilers (SunPro CC). */ break; } cleanup0: /* * Check for asynchronous handlers [Bug 746722]; we do the check every * ASYNC_CHECK_COUNT_MASK instruction, of the form (2**n-1). */ if ((instructionCount++ & ASYNC_CHECK_COUNT_MASK) == 0) { DECACHE_STACK_INFO(); if (TclAsyncReady(iPtr)) { result = Tcl_AsyncInvoke(interp, result); if (result == TCL_ERROR) { CACHE_STACK_INFO(); goto gotError; } } if (TclCanceled(iPtr)) { if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) { CACHE_STACK_INFO(); goto gotError; } } if (TclLimitReady(iPtr->limit)) { if (Tcl_LimitCheck(interp) == TCL_ERROR) { CACHE_STACK_INFO(); goto gotError; } } CACHE_STACK_INFO(); } /* * These two instructions account for 26% of all instructions (according * to measurements on tclbench by Ben Vitale * [http://www.cs.toronto.edu/syslab/pubs/tcl2005-vitale-zaleski.pdf] * Resolving them before the switch reduces the cost of branch * mispredictions, seems to improve runtime by 5% to 15%, and (amazingly!) * reduces total obj size. */ inst = *pc; peepholeStart: #ifdef TCL_COMPILE_STATS iPtr->stats.instructionCount[*pc]++; #endif #ifdef TCL_COMPILE_DEBUG /* * Skip the stack depth check if an expansion is in progress. */ CHECK_STACK(); if (traceInstructions) { fprintf(stdout, "%2d: %2d ", iPtr->numLevels, (int) CURR_DEPTH); TclPrintInstruction(codePtr, pc); fflush(stdout); } #endif /* TCL_COMPILE_DEBUG */ TCL_DTRACE_INST_NEXT(); if (inst == INST_LOAD_SCALAR1) { goto instLoadScalar1; } else if (inst == INST_PUSH1) { PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt1AtPtr(pc+1)]); TRACE_WITH_OBJ(("%u => ", TclGetUInt1AtPtr(pc+1)), OBJ_AT_TOS); inst = *(pc += 2); goto peepholeStart; } else if (inst == INST_START_CMD) { /* * Peephole: do not run INST_START_CMD, just skip it */ iPtr->cmdCount += TclGetUInt4AtPtr(pc+5); if (checkInterp) { checkInterp = 0; if (((codePtr->compileEpoch != iPtr->compileEpoch) || (codePtr->nsEpoch != iPtr->varFramePtr->nsPtr->resolverEpoch)) && !(codePtr->flags & TCL_BYTECODE_PRECOMPILED)) { goto instStartCmdFailed; } } inst = *(pc += 9); goto peepholeStart; } else if (inst == INST_NOP) { #ifndef TCL_COMPILE_DEBUG while (inst == INST_NOP) #endif { inst = *++pc; } goto peepholeStart; } switch (inst) { case INST_SYNTAX: case INST_RETURN_IMM: { int code = TclGetInt4AtPtr(pc+1); int level = TclGetUInt4AtPtr(pc+5); /* * OBJ_AT_TOS is returnOpts, OBJ_UNDER_TOS is resultObjPtr. */ TRACE(("%u %u => ", code, level)); result = TclProcessReturn(interp, code, level, OBJ_AT_TOS); if (result == TCL_OK) { TRACE_APPEND(("continuing to next instruction (result=\"%.30s\")\n", O2S(objResultPtr))); NEXT_INST_F(9, 1, 0); } Tcl_SetObjResult(interp, OBJ_UNDER_TOS); if (*pc == INST_SYNTAX) { iPtr->flags &= ~ERR_ALREADY_LOGGED; } cleanup = 2; TRACE_APPEND(("\n")); goto processExceptionReturn; } case INST_RETURN_STK: TRACE(("=> ")); objResultPtr = POP_OBJECT(); result = Tcl_SetReturnOptions(interp, OBJ_AT_TOS); if (result == TCL_OK) { Tcl_DecrRefCount(OBJ_AT_TOS); OBJ_AT_TOS = objResultPtr; TRACE_APPEND(("continuing to next instruction (result=\"%.30s\")\n", O2S(objResultPtr))); NEXT_INST_F(1, 0, 0); } else if (result == TCL_ERROR) { /* * BEWARE! Must do this in this order, because an error in the * option dictionary overrides the result (and can be verified by * test). */ Tcl_SetObjResult(interp, objResultPtr); Tcl_SetReturnOptions(interp, OBJ_AT_TOS); Tcl_DecrRefCount(OBJ_AT_TOS); OBJ_AT_TOS = objResultPtr; } else { Tcl_DecrRefCount(OBJ_AT_TOS); OBJ_AT_TOS = objResultPtr; Tcl_SetObjResult(interp, objResultPtr); } cleanup = 1; TRACE_APPEND(("\n")); goto processExceptionReturn; { CoroutineData *corPtr; int yieldParameter; case INST_YIELD: corPtr = iPtr->execEnvPtr->corPtr; TRACE(("%.30s => ", O2S(OBJ_AT_TOS))); if (!corPtr) { TRACE_APPEND(("ERROR: yield outside coroutine\n")); Tcl_SetObjResult(interp, Tcl_NewStringObj( "yield can only be called in a coroutine", -1)); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", NULL); CACHE_STACK_INFO(); goto gotError; } #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= 2) { if (traceInstructions) { TRACE_APPEND(("YIELD...\n")); } else { fprintf(stdout, "%d: (%u) yielding value \"%.30s\"\n", iPtr->numLevels, (unsigned)(pc - codePtr->codeStart), Tcl_GetString(OBJ_AT_TOS)); } fflush(stdout); } #endif yieldParameter = 0; Tcl_SetObjResult(interp, OBJ_AT_TOS); goto doYield; case INST_YIELD_TO_INVOKE: corPtr = iPtr->execEnvPtr->corPtr; valuePtr = OBJ_AT_TOS; if (!corPtr) { TRACE(("[%.30s] => ERROR: yield outside coroutine\n", O2S(valuePtr))); Tcl_SetObjResult(interp, Tcl_NewStringObj( "yieldto can only be called in a coroutine", -1)); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", NULL); CACHE_STACK_INFO(); goto gotError; } if (((Namespace *)TclGetCurrentNamespace(interp))->flags & NS_DYING) { TRACE(("[%.30s] => ERROR: yield in deleted\n", O2S(valuePtr))); Tcl_SetObjResult(interp, Tcl_NewStringObj( "yieldto called in deleted namespace", -1)); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "YIELDTO_IN_DELETED", NULL); CACHE_STACK_INFO(); goto gotError; } #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= 2) { if (traceInstructions) { TRACE(("[%.30s] => YIELD...\n", O2S(valuePtr))); } else { /* FIXME: What is the right thing to trace? */ fprintf(stdout, "%d: (%u) yielding to [%.30s]\n", iPtr->numLevels, (unsigned)(pc - codePtr->codeStart), Tcl_GetString(valuePtr)); } fflush(stdout); } #endif /* * Install a tailcall record in the caller and continue with the * yield. The yield is switched into multi-return mode (via the * 'yieldParameter'). */ Tcl_IncrRefCount(valuePtr); iPtr->execEnvPtr = corPtr->callerEEPtr; TclSetTailcall(interp, valuePtr); iPtr->execEnvPtr = corPtr->eePtr; yieldParameter = (PTR2INT(NULL)+1); /*==CORO_ACTIVATE_YIELDM*/ doYield: /* TIP #280: Record the last piece of info needed by * 'TclGetSrcInfoForPc', and push the frame. */ bcFramePtr->data.tebc.pc = (char *) pc; iPtr->cmdFramePtr = bcFramePtr; if (iPtr->flags & INTERP_DEBUG_FRAME) { ArgumentBCEnter(interp, codePtr, TD, pc, objc, objv); } pc++; cleanup = 1; TEBC_YIELD(); TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr, INT2PTR(yieldParameter), NULL, NULL); return TCL_OK; } case INST_TAILCALL: { Tcl_Obj *listPtr, *nsObjPtr; opnd = TclGetUInt1AtPtr(pc+1); if (!(iPtr->varFramePtr->isProcCallFrame & 1)) { TRACE(("%d => ERROR: tailcall in non-proc context\n", opnd)); Tcl_SetObjResult(interp, Tcl_NewStringObj( "tailcall can only be called from a proc or lambda", -1)); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "TAILCALL", "ILLEGAL", NULL); CACHE_STACK_INFO(); goto gotError; } #ifdef TCL_COMPILE_DEBUG /* FIXME: What is the right thing to trace? */ { register int i; TRACE(("%d [", opnd)); for (i=opnd-1 ; i>=0 ; i--) { TRACE_APPEND(("\"%.30s\"", O2S(OBJ_AT_DEPTH(i)))); if (i > 0) { TRACE_APPEND((" ")); } } TRACE_APPEND(("] => RETURN...")); } #endif /* * Push the evaluation of the called command into the NR callback * stack. */ listPtr = Tcl_NewListObj(opnd, &OBJ_AT_DEPTH(opnd-1)); nsObjPtr = Tcl_NewStringObj(iPtr->varFramePtr->nsPtr->fullName, -1); TclListObjSetElement(interp, listPtr, 0, nsObjPtr); if (iPtr->varFramePtr->tailcallPtr) { Tcl_DecrRefCount(iPtr->varFramePtr->tailcallPtr); } iPtr->varFramePtr->tailcallPtr = listPtr; result = TCL_RETURN; cleanup = opnd; goto processExceptionReturn; } case INST_DONE: if (tosPtr > initTosPtr) { /* * Set the interpreter's object result to point to the topmost * object from the stack, and check for a possible [catch]. The * stackTop's level and refCount will be handled by "processCatch" * or "abnormalReturn". */ Tcl_SetObjResult(interp, OBJ_AT_TOS); #ifdef TCL_COMPILE_DEBUG TRACE_WITH_OBJ(("=> return code=%d, result=", result), iPtr->objResultPtr); if (traceInstructions) { fprintf(stdout, "\n"); } #endif goto checkForCatch; } (void) POP_OBJECT(); goto abnormalReturn; case INST_PUSH4: objResultPtr = codePtr->objArrayPtr[TclGetUInt4AtPtr(pc+1)]; TRACE_WITH_OBJ(("%u => ", TclGetUInt4AtPtr(pc+1)), objResultPtr); NEXT_INST_F(5, 0, 1); case INST_POP: TRACE_WITH_OBJ(("=> discarding "), OBJ_AT_TOS); objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); NEXT_INST_F(1, 0, 0); case INST_DUP: objResultPtr = OBJ_AT_TOS; TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); case INST_OVER: opnd = TclGetUInt4AtPtr(pc+1); objResultPtr = OBJ_AT_DEPTH(opnd); TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr); NEXT_INST_F(5, 0, 1); case INST_REVERSE: { Tcl_Obj **a, **b; opnd = TclGetUInt4AtPtr(pc+1); a = tosPtr-(opnd-1); b = tosPtr; while (a OK\n", opnd)); NEXT_INST_F(5, 0, 0); } case INST_STR_CONCAT1: { int appendLen = 0; char *bytes, *p; Tcl_Obj **currPtr; int onlyb = 1; opnd = TclGetUInt1AtPtr(pc+1); /* * Detect only-bytearray-or-null case. */ for (currPtr=&OBJ_AT_DEPTH(opnd-1); currPtr<=&OBJ_AT_TOS; currPtr++) { if (((*currPtr)->typePtr != &tclByteArrayType) && ((*currPtr)->bytes != tclEmptyStringRep)) { onlyb = 0; break; } else if (((*currPtr)->typePtr == &tclByteArrayType) && ((*currPtr)->bytes != NULL)) { onlyb = 0; break; } } /* * Compute the length to be appended. */ if (onlyb) { for (currPtr = &OBJ_AT_DEPTH(opnd-2); appendLen >= 0 && currPtr <= &OBJ_AT_TOS; currPtr++) { if ((*currPtr)->bytes != tclEmptyStringRep) { Tcl_GetByteArrayFromObj(*currPtr, &length); appendLen += length; } } } else { for (currPtr = &OBJ_AT_DEPTH(opnd-2); appendLen >= 0 && currPtr <= &OBJ_AT_TOS; currPtr++) { bytes = TclGetStringFromObj(*currPtr, &length); if (bytes != NULL) { appendLen += length; } } } if (appendLen < 0) { /* TODO: convert panic to error ? */ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } /* * If nothing is to be appended, just return the first object by * dropping all the others from the stack; this saves both the * computation and copy of the string rep of the first object, * enabling the fast '$x[set x {}]' idiom for 'K $x [set x {}]'. */ if (appendLen == 0) { TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr); NEXT_INST_V(2, (opnd-1), 0); } /* * If the first object is shared, we need a new obj for the result; * otherwise, we can reuse the first object. In any case, make sure it * has enough room to accomodate all the concatenated bytes. Note that * if it is unshared its bytes are copied by ckrealloc, so that we set * the loop parameters to avoid copying them again: p points to the * end of the already copied bytes, currPtr to the second object. */ objResultPtr = OBJ_AT_DEPTH(opnd-1); if (!onlyb) { bytes = TclGetStringFromObj(objResultPtr, &length); if (length + appendLen < 0) { /* TODO: convert panic to error ? */ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } #ifndef TCL_COMPILE_DEBUG if (bytes != tclEmptyStringRep && !Tcl_IsShared(objResultPtr)) { TclFreeIntRep(objResultPtr); objResultPtr->bytes = ckrealloc(bytes, length+appendLen+1); objResultPtr->length = length + appendLen; p = TclGetString(objResultPtr) + length; currPtr = &OBJ_AT_DEPTH(opnd - 2); } else #endif { p = ckalloc(length + appendLen + 1); TclNewObj(objResultPtr); objResultPtr->bytes = p; objResultPtr->length = length + appendLen; currPtr = &OBJ_AT_DEPTH(opnd - 1); } /* * Append the remaining characters. */ for (; currPtr <= &OBJ_AT_TOS; currPtr++) { bytes = TclGetStringFromObj(*currPtr, &length); if (bytes != NULL) { memcpy(p, bytes, (size_t) length); p += length; } } *p = '\0'; } else { bytes = (char *) Tcl_GetByteArrayFromObj(objResultPtr, &length); if (length + appendLen < 0) { /* TODO: convert panic to error ? */ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } #ifndef TCL_COMPILE_DEBUG if (!Tcl_IsShared(objResultPtr)) { bytes = (char *) Tcl_SetByteArrayLength(objResultPtr, length + appendLen); p = bytes + length; currPtr = &OBJ_AT_DEPTH(opnd - 2); } else #endif { TclNewObj(objResultPtr); bytes = (char *) Tcl_SetByteArrayLength(objResultPtr, length + appendLen); p = bytes; currPtr = &OBJ_AT_DEPTH(opnd - 1); } /* * Append the remaining characters. */ for (; currPtr <= &OBJ_AT_TOS; currPtr++) { if ((*currPtr)->bytes != tclEmptyStringRep) { bytes = (char *) Tcl_GetByteArrayFromObj(*currPtr,&length); memcpy(p, bytes, (size_t) length); p += length; } } } TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr); NEXT_INST_V(2, opnd, 1); } case INST_CONCAT_STK: /* * Pop the opnd (objc) top stack elements, run through Tcl_ConcatObj, * and then decrement their ref counts. */ opnd = TclGetUInt4AtPtr(pc+1); objResultPtr = Tcl_ConcatObj(opnd, &OBJ_AT_DEPTH(opnd-1)); TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr); NEXT_INST_V(5, opnd, 1); case INST_EXPAND_START: /* * Push an element to the auxObjList. This records the current * stack depth - i.e., the point in the stack where the expanded * command starts. * * Use a Tcl_Obj as linked list element; slight mem waste, but faster * allocation than ckalloc. This also abuses the Tcl_Obj structure, as * we do not define a special tclObjType for it. It is not dangerous * as the obj is never passed anywhere, so that all manipulations are * performed here and in INST_INVOKE_EXPANDED (in case of an expansion * error, also in INST_EXPAND_STKTOP). */ TclNewObj(objPtr); objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(CURR_DEPTH); objPtr->length = 0; PUSH_TAUX_OBJ(objPtr); TRACE(("=> mark depth as %d\n", (int) CURR_DEPTH)); NEXT_INST_F(1, 0, 0); case INST_EXPAND_DROP: /* * Drops an element of the auxObjList, popping stack elements to * restore the stack to the state before the point where the aux * element was created. */ CLANG_ASSERT(auxObjList); objc = CURR_DEPTH - PTR2INT(auxObjList->internalRep.twoPtrValue.ptr2); POP_TAUX_OBJ(); #ifdef TCL_COMPILE_DEBUG /* Ugly abuse! */ starting = 1; #endif TRACE(("=> drop %d items\n", objc)); NEXT_INST_V(1, objc, 0); case INST_EXPAND_STKTOP: { int i; ptrdiff_t moved; /* * Make sure that the element at stackTop is a list; if not, just * leave with an error. Note that the element from the expand list * will be removed at checkForCatch. */ objPtr = OBJ_AT_TOS; TRACE(("\"%.30s\" => ", O2S(objPtr))); if (TclListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } (void) POP_OBJECT(); /* * Make sure there is enough room in the stack to expand this list * *and* process the rest of the command (at least up to the next * argument expansion or command end). The operand is the current * stack depth, as seen by the compiler. */ auxObjList->length += objc - 1; if ((objc > 1) && (auxObjList->length > 0)) { length = auxObjList->length /* Total expansion room we need */ + codePtr->maxStackDepth /* Beyond the original max */ - CURR_DEPTH; /* Relative to where we are */ DECACHE_STACK_INFO(); moved = GrowEvaluationStack(iPtr->execEnvPtr, length, 1) - (Tcl_Obj **) TD; if (moved) { /* * Change the global data to point to the new stack: move the * TEBCdataPtr TD, recompute the position of every other * stack-allocated parameter, update the stack pointers. */ TD = (TEBCdata *) (((Tcl_Obj **)TD) + moved); catchTop += moved; tosPtr += moved; } } /* * Expand the list at stacktop onto the stack; free the list. Knowing * that it has a freeIntRepProc we use Tcl_DecrRefCount(). */ for (i = 0; i < objc; i++) { PUSH_OBJECT(objv[i]); } TRACE_APPEND(("OK\n")); Tcl_DecrRefCount(objPtr); NEXT_INST_F(5, 0, 0); } case INST_EXPR_STK: { ByteCode *newCodePtr; bcFramePtr->data.tebc.pc = (char *) pc; iPtr->cmdFramePtr = bcFramePtr; DECACHE_STACK_INFO(); newCodePtr = CompileExprObj(interp, OBJ_AT_TOS); CACHE_STACK_INFO(); cleanup = 1; pc++; TEBC_YIELD(); return TclNRExecuteByteCode(interp, newCodePtr); } /* * INVOCATION BLOCK */ instEvalStk: case INST_EVAL_STK: bcFramePtr->data.tebc.pc = (char *) pc; iPtr->cmdFramePtr = bcFramePtr; cleanup = 1; pc += 1; TEBC_YIELD(); return TclNREvalObjEx(interp, OBJ_AT_TOS, 0, NULL, 0); case INST_INVOKE_EXPANDED: CLANG_ASSERT(auxObjList); objc = CURR_DEPTH - PTR2INT(auxObjList->internalRep.twoPtrValue.ptr2); POP_TAUX_OBJ(); if (objc) { pcAdjustment = 1; goto doInvocation; } /* * Nothing was expanded, return {}. */ TclNewObj(objResultPtr); NEXT_INST_F(1, 0, 1); case INST_INVOKE_STK4: objc = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; goto doInvocation; case INST_INVOKE_STK1: objc = TclGetUInt1AtPtr(pc+1); pcAdjustment = 2; doInvocation: objv = &OBJ_AT_DEPTH(objc-1); cleanup = objc; #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= 2) { int i; if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); TRACE(("%u => call ", objc)); } else { fprintf(stdout, "%d: (%u) invoking ", iPtr->numLevels, (unsigned)(pc - codePtr->codeStart)); } for (i = 0; i < objc; i++) { TclPrintObject(stdout, objv[i], 15); fprintf(stdout, " "); } fprintf(stdout, "\n"); fflush(stdout); } #endif /*TCL_COMPILE_DEBUG*/ /* * Finally, let TclEvalObjv handle the command. * * TIP #280: Record the last piece of info needed by * 'TclGetSrcInfoForPc', and push the frame. */ bcFramePtr->data.tebc.pc = (char *) pc; iPtr->cmdFramePtr = bcFramePtr; if (iPtr->flags & INTERP_DEBUG_FRAME) { ArgumentBCEnter(interp, codePtr, TD, pc, objc, objv); } DECACHE_STACK_INFO(); pc += pcAdjustment; TEBC_YIELD(); return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NOERR | TCL_EVAL_SOURCE_IN_FRAME, NULL); #if TCL_SUPPORT_84_BYTECODE case INST_CALL_BUILTIN_FUNC1: /* * Call one of the built-in pre-8.5 Tcl math functions. This * translates to INST_INVOKE_STK1 with the first argument of * ::tcl::mathfunc::$objv[0]. We need to insert the named math * function into the stack. */ opnd = TclGetUInt1AtPtr(pc+1); if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) { TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd)); Tcl_Panic("TclNRExecuteByteCode: unrecognized builtin function code %d", opnd); } TclNewLiteralStringObj(objPtr, "::tcl::mathfunc::"); Tcl_AppendToObj(objPtr, tclBuiltinFuncTable[opnd].name, -1); /* * Only 0, 1 or 2 args. */ { int numArgs = tclBuiltinFuncTable[opnd].numArgs; Tcl_Obj *tmpPtr1, *tmpPtr2; if (numArgs == 0) { PUSH_OBJECT(objPtr); } else if (numArgs == 1) { tmpPtr1 = POP_OBJECT(); PUSH_OBJECT(objPtr); PUSH_OBJECT(tmpPtr1); Tcl_DecrRefCount(tmpPtr1); } else { tmpPtr2 = POP_OBJECT(); tmpPtr1 = POP_OBJECT(); PUSH_OBJECT(objPtr); PUSH_OBJECT(tmpPtr1); PUSH_OBJECT(tmpPtr2); Tcl_DecrRefCount(tmpPtr1); Tcl_DecrRefCount(tmpPtr2); } objc = numArgs + 1; } pcAdjustment = 2; goto doInvocation; case INST_CALL_FUNC1: /* * Call a non-builtin Tcl math function previously registered by a * call to Tcl_CreateMathFunc pre-8.5. This is essentially * INST_INVOKE_STK1 converting the first arg to * ::tcl::mathfunc::$objv[0]. */ objc = TclGetUInt1AtPtr(pc+1); /* Number of arguments. The function * name is the 0-th argument. */ objPtr = OBJ_AT_DEPTH(objc-1); TclNewLiteralStringObj(tmpPtr, "::tcl::mathfunc::"); Tcl_AppendObjToObj(tmpPtr, objPtr); Tcl_DecrRefCount(objPtr); /* * Variation of PUSH_OBJECT. */ OBJ_AT_DEPTH(objc-1) = tmpPtr; Tcl_IncrRefCount(tmpPtr); pcAdjustment = 2; goto doInvocation; #else /* * INST_CALL_BUILTIN_FUNC1 and INST_CALL_FUNC1 were made obsolete by the * changes to add a ::tcl::mathfunc namespace in 8.5. Optional support * remains for existing bytecode precompiled files. */ case INST_CALL_BUILTIN_FUNC1: Tcl_Panic("TclNRExecuteByteCode: obsolete INST_CALL_BUILTIN_FUNC1 found"); case INST_CALL_FUNC1: Tcl_Panic("TclNRExecuteByteCode: obsolete INST_CALL_FUNC1 found"); #endif case INST_INVOKE_REPLACE: objc = TclGetUInt4AtPtr(pc+1); opnd = TclGetUInt1AtPtr(pc+5); objPtr = POP_OBJECT(); objv = &OBJ_AT_DEPTH(objc-1); cleanup = objc; #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= 2) { int i; if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); TRACE(("%u => call (implementation %s) ", objc, O2S(objPtr))); } else { fprintf(stdout, "%d: (%u) invoking (using implementation %s) ", iPtr->numLevels, (unsigned)(pc - codePtr->codeStart), O2S(objPtr)); } for (i = 0; i < objc; i++) { if (i < opnd) { fprintf(stdout, "<"); TclPrintObject(stdout, objv[i], 15); fprintf(stdout, ">"); } else { TclPrintObject(stdout, objv[i], 15); } fprintf(stdout, " "); } fprintf(stdout, "\n"); fflush(stdout); } #endif /*TCL_COMPILE_DEBUG*/ { Tcl_Obj *copyPtr = Tcl_NewListObj(objc - opnd + 1, NULL); register List *listRepPtr = copyPtr->internalRep.twoPtrValue.ptr1; Tcl_Obj **copyObjv = &listRepPtr->elements; int i; listRepPtr->elemCount = objc - opnd + 1; copyObjv[0] = objPtr; memcpy(copyObjv+1, objv+opnd, sizeof(Tcl_Obj *) * (objc - opnd)); for (i=1 ; idata.tebc.pc = (char *) pc; iPtr->cmdFramePtr = bcFramePtr; if (iPtr->flags & INTERP_DEBUG_FRAME) { ArgumentBCEnter(interp, codePtr, TD, pc, objc, objv); } iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = opnd; iPtr->ensembleRewrite.numInsertedObjs = 1; DECACHE_STACK_INFO(); pc += 6; TEBC_YIELD(); TclMarkTailcall(interp); TclNRAddCallback(interp, TclClearRootEnsemble, NULL,NULL,NULL,NULL); return TclNREvalObjEx(interp, objPtr, TCL_EVAL_INVOKE, NULL, INT_MIN); /* * ----------------------------------------------------------------- * Start of INST_LOAD instructions. * * WARNING: more 'goto' here than your doctor recommended! The different * instructions set the value of some variables and then jump to some * common execution code. */ case INST_LOAD_SCALAR1: instLoadScalar1: opnd = TclGetUInt1AtPtr(pc+1); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { /* * No errors, no traces: just get the value. */ objResultPtr = varPtr->value.objPtr; TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_F(2, 0, 1); } pcAdjustment = 2; cleanup = 0; arrayPtr = NULL; part1Ptr = part2Ptr = NULL; goto doCallPtrGetVar; case INST_LOAD_SCALAR4: opnd = TclGetUInt4AtPtr(pc+1); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { /* * No errors, no traces: just get the value. */ objResultPtr = varPtr->value.objPtr; TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_F(5, 0, 1); } pcAdjustment = 5; cleanup = 0; arrayPtr = NULL; part1Ptr = part2Ptr = NULL; goto doCallPtrGetVar; case INST_LOAD_ARRAY4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; goto doLoadArray; case INST_LOAD_ARRAY1: opnd = TclGetUInt1AtPtr(pc+1); pcAdjustment = 2; doLoadArray: part1Ptr = NULL; part2Ptr = OBJ_AT_TOS; arrayPtr = LOCAL(opnd); while (TclIsVarLink(arrayPtr)) { arrayPtr = arrayPtr->value.linkPtr; } TRACE(("%u \"%.30s\" => ", opnd, O2S(part2Ptr))); if (TclIsVarArray(arrayPtr) && !ReadTraced(arrayPtr)) { varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr); if (varPtr && TclIsVarDirectReadable(varPtr)) { /* * No errors, no traces: just get the value. */ objResultPtr = varPtr->value.objPtr; TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_F(pcAdjustment, 1, 1); } } varPtr = TclLookupArrayElement(interp, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, "read", 0, 1, arrayPtr, opnd); if (varPtr == NULL) { TRACE_ERROR(interp); goto gotError; } cleanup = 1; goto doCallPtrGetVar; case INST_LOAD_ARRAY_STK: cleanup = 2; part2Ptr = OBJ_AT_TOS; /* element name */ objPtr = OBJ_UNDER_TOS; /* array name */ TRACE(("\"%.30s(%.30s)\" => ", O2S(objPtr), O2S(part2Ptr))); goto doLoadStk; case INST_LOAD_STK: case INST_LOAD_SCALAR_STK: cleanup = 1; part2Ptr = NULL; objPtr = OBJ_AT_TOS; /* variable name */ TRACE(("\"%.30s\" => ", O2S(objPtr))); doLoadStk: part1Ptr = objPtr; varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, "read", /*createPart1*/0, /*createPart2*/1, &arrayPtr); if (!varPtr) { TRACE_ERROR(interp); goto gotError; } if (TclIsVarDirectReadable2(varPtr, arrayPtr)) { /* * No errors, no traces: just get the value. */ objResultPtr = varPtr->value.objPtr; TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(1, cleanup, 1); } pcAdjustment = 1; opnd = -1; doCallPtrGetVar: /* * There are either errors or the variable is traced: call * TclPtrGetVar to process fully. */ DECACHE_STACK_INFO(); objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, opnd); CACHE_STACK_INFO(); if (!objResultPtr) { TRACE_ERROR(interp); goto gotError; } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(pcAdjustment, cleanup, 1); /* * End of INST_LOAD instructions. * ----------------------------------------------------------------- * Start of INST_STORE and related instructions. * * WARNING: more 'goto' here than your doctor recommended! The different * instructions set the value of some variables and then jump to somme * common execution code. */ { int storeFlags, len; case INST_STORE_ARRAY4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; goto doStoreArrayDirect; case INST_STORE_ARRAY1: opnd = TclGetUInt1AtPtr(pc+1); pcAdjustment = 2; doStoreArrayDirect: valuePtr = OBJ_AT_TOS; part2Ptr = OBJ_UNDER_TOS; arrayPtr = LOCAL(opnd); TRACE(("%u \"%.30s\" <- \"%.30s\" => ", opnd, O2S(part2Ptr), O2S(valuePtr))); while (TclIsVarLink(arrayPtr)) { arrayPtr = arrayPtr->value.linkPtr; } if (TclIsVarArray(arrayPtr) && !WriteTraced(arrayPtr)) { varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr); if (varPtr && TclIsVarDirectWritable(varPtr)) { tosPtr--; Tcl_DecrRefCount(OBJ_AT_TOS); OBJ_AT_TOS = valuePtr; goto doStoreVarDirect; } } cleanup = 2; storeFlags = TCL_LEAVE_ERR_MSG; part1Ptr = NULL; goto doStoreArrayDirectFailed; case INST_STORE_SCALAR4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; goto doStoreScalarDirect; case INST_STORE_SCALAR1: opnd = TclGetUInt1AtPtr(pc+1); pcAdjustment = 2; doStoreScalarDirect: valuePtr = OBJ_AT_TOS; varPtr = LOCAL(opnd); TRACE(("%u <- \"%.30s\" => ", opnd, O2S(valuePtr))); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (!TclIsVarDirectWritable(varPtr)) { storeFlags = TCL_LEAVE_ERR_MSG; part1Ptr = NULL; goto doStoreScalar; } /* * No traces, no errors, plain 'set': we can safely inline. The value * *will* be set to what's requested, so that the stack top remains * pointing to the same Tcl_Obj. */ doStoreVarDirect: valuePtr = varPtr->value.objPtr; if (valuePtr != NULL) { TclDecrRefCount(valuePtr); } objResultPtr = OBJ_AT_TOS; varPtr->value.objPtr = objResultPtr; #ifndef TCL_COMPILE_DEBUG if (*(pc+pcAdjustment) == INST_POP) { tosPtr--; NEXT_INST_F((pcAdjustment+1), 0, 0); } #else TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); #endif Tcl_IncrRefCount(objResultPtr); NEXT_INST_F(pcAdjustment, 0, 0); case INST_LAPPEND_STK: valuePtr = OBJ_AT_TOS; /* value to append */ part2Ptr = NULL; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT); goto doStoreStk; case INST_LAPPEND_ARRAY_STK: valuePtr = OBJ_AT_TOS; /* value to append */ part2Ptr = OBJ_UNDER_TOS; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT); goto doStoreStk; case INST_APPEND_STK: valuePtr = OBJ_AT_TOS; /* value to append */ part2Ptr = NULL; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); goto doStoreStk; case INST_APPEND_ARRAY_STK: valuePtr = OBJ_AT_TOS; /* value to append */ part2Ptr = OBJ_UNDER_TOS; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); goto doStoreStk; case INST_STORE_ARRAY_STK: valuePtr = OBJ_AT_TOS; part2Ptr = OBJ_UNDER_TOS; storeFlags = TCL_LEAVE_ERR_MSG; goto doStoreStk; case INST_STORE_STK: case INST_STORE_SCALAR_STK: valuePtr = OBJ_AT_TOS; part2Ptr = NULL; storeFlags = TCL_LEAVE_ERR_MSG; doStoreStk: objPtr = OBJ_AT_DEPTH(1 + (part2Ptr != NULL)); /* variable name */ part1Ptr = objPtr; #ifdef TCL_COMPILE_DEBUG if (part2Ptr == NULL) { TRACE(("\"%.30s\" <- \"%.30s\" =>", O2S(part1Ptr),O2S(valuePtr))); } else { TRACE(("\"%.30s(%.30s)\" <- \"%.30s\" => ", O2S(part1Ptr), O2S(part2Ptr), O2S(valuePtr))); } #endif varPtr = TclObjLookupVarEx(interp, objPtr,part2Ptr, TCL_LEAVE_ERR_MSG, "set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (!varPtr) { TRACE_ERROR(interp); goto gotError; } cleanup = ((part2Ptr == NULL)? 2 : 3); pcAdjustment = 1; opnd = -1; goto doCallPtrSetVar; case INST_LAPPEND_ARRAY4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT); goto doStoreArray; case INST_LAPPEND_ARRAY1: opnd = TclGetUInt1AtPtr(pc+1); pcAdjustment = 2; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT); goto doStoreArray; case INST_APPEND_ARRAY4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); goto doStoreArray; case INST_APPEND_ARRAY1: opnd = TclGetUInt1AtPtr(pc+1); pcAdjustment = 2; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); goto doStoreArray; doStoreArray: valuePtr = OBJ_AT_TOS; part2Ptr = OBJ_UNDER_TOS; arrayPtr = LOCAL(opnd); TRACE(("%u \"%.30s\" <- \"%.30s\" => ", opnd, O2S(part2Ptr), O2S(valuePtr))); while (TclIsVarLink(arrayPtr)) { arrayPtr = arrayPtr->value.linkPtr; } cleanup = 2; part1Ptr = NULL; doStoreArrayDirectFailed: varPtr = TclLookupArrayElement(interp, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, "set", 1, 1, arrayPtr, opnd); if (!varPtr) { TRACE_ERROR(interp); goto gotError; } goto doCallPtrSetVar; case INST_LAPPEND_SCALAR4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT); goto doStoreScalar; case INST_LAPPEND_SCALAR1: opnd = TclGetUInt1AtPtr(pc+1); pcAdjustment = 2; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE | TCL_LIST_ELEMENT); goto doStoreScalar; case INST_APPEND_SCALAR4: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); goto doStoreScalar; case INST_APPEND_SCALAR1: opnd = TclGetUInt1AtPtr(pc+1); pcAdjustment = 2; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); goto doStoreScalar; doStoreScalar: valuePtr = OBJ_AT_TOS; varPtr = LOCAL(opnd); TRACE(("%u <- \"%.30s\" => ", opnd, O2S(valuePtr))); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } cleanup = 1; arrayPtr = NULL; part1Ptr = part2Ptr = NULL; doCallPtrSetVar: DECACHE_STACK_INFO(); objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, valuePtr, storeFlags, opnd); CACHE_STACK_INFO(); if (!objResultPtr) { TRACE_ERROR(interp); goto gotError; } #ifndef TCL_COMPILE_DEBUG if (*(pc+pcAdjustment) == INST_POP) { NEXT_INST_V((pcAdjustment+1), cleanup, 0); } #endif TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(pcAdjustment, cleanup, 1); case INST_LAPPEND_LIST: opnd = TclGetUInt4AtPtr(pc+1); valuePtr = OBJ_AT_TOS; varPtr = LOCAL(opnd); cleanup = 1; pcAdjustment = 5; while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u <- \"%.30s\" => ", opnd, O2S(valuePtr))); if (TclListObjGetElements(interp, valuePtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } if (TclIsVarDirectReadable(varPtr) && TclIsVarDirectWritable(varPtr)) { goto lappendListDirect; } arrayPtr = NULL; part1Ptr = part2Ptr = NULL; goto lappendListPtr; case INST_LAPPEND_LIST_ARRAY: opnd = TclGetUInt4AtPtr(pc+1); valuePtr = OBJ_AT_TOS; part1Ptr = NULL; part2Ptr = OBJ_UNDER_TOS; arrayPtr = LOCAL(opnd); cleanup = 2; pcAdjustment = 5; while (TclIsVarLink(arrayPtr)) { arrayPtr = arrayPtr->value.linkPtr; } TRACE(("%u \"%.30s\" \"%.30s\" => ", opnd, O2S(part2Ptr), O2S(valuePtr))); if (TclListObjGetElements(interp, valuePtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } if (TclIsVarArray(arrayPtr) && !ReadTraced(arrayPtr) && !WriteTraced(arrayPtr)) { varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr); if (varPtr && TclIsVarDirectReadable(varPtr) && TclIsVarDirectWritable(varPtr)) { goto lappendListDirect; } } varPtr = TclLookupArrayElement(interp, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, "set", 1, 1, arrayPtr, opnd); if (varPtr == NULL) { TRACE_ERROR(interp); goto gotError; } goto lappendListPtr; case INST_LAPPEND_LIST_ARRAY_STK: pcAdjustment = 1; cleanup = 3; valuePtr = OBJ_AT_TOS; part2Ptr = OBJ_UNDER_TOS; /* element name */ part1Ptr = OBJ_AT_DEPTH(2); /* array name */ TRACE(("\"%.30s(%.30s)\" \"%.30s\" => ", O2S(part1Ptr), O2S(part2Ptr), O2S(valuePtr))); goto lappendList; case INST_LAPPEND_LIST_STK: pcAdjustment = 1; cleanup = 2; valuePtr = OBJ_AT_TOS; part2Ptr = NULL; part1Ptr = OBJ_UNDER_TOS; /* variable name */ TRACE(("\"%.30s\" \"%.30s\" => ", O2S(part1Ptr), O2S(valuePtr))); goto lappendList; lappendListDirect: objResultPtr = varPtr->value.objPtr; if (TclListObjLength(interp, objResultPtr, &len) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } if (Tcl_IsShared(objResultPtr)) { Tcl_Obj *newValue = Tcl_DuplicateObj(objResultPtr); TclDecrRefCount(objResultPtr); varPtr->value.objPtr = objResultPtr = newValue; Tcl_IncrRefCount(newValue); } if (Tcl_ListObjReplace(interp, objResultPtr, len, 0, objc, objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(pcAdjustment, cleanup, 1); lappendList: opnd = -1; if (TclListObjGetElements(interp, valuePtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } DECACHE_STACK_INFO(); varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, "set", 1, 1, &arrayPtr); CACHE_STACK_INFO(); if (!varPtr) { TRACE_ERROR(interp); goto gotError; } lappendListPtr: if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)++; } if (arrayPtr && TclIsVarInHash(arrayPtr)) { VarHashRefCount(arrayPtr)++; } DECACHE_STACK_INFO(); objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, opnd); CACHE_STACK_INFO(); if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)--; } if (arrayPtr && TclIsVarInHash(arrayPtr)) { VarHashRefCount(arrayPtr)--; } { int createdNewObj = 0; if (!objResultPtr) { objResultPtr = valuePtr; } else if (TclListObjLength(interp, objResultPtr, &len)!=TCL_OK) { TRACE_ERROR(interp); goto gotError; } else { if (Tcl_IsShared(objResultPtr)) { objResultPtr = Tcl_DuplicateObj(objResultPtr); createdNewObj = 1; } if (Tcl_ListObjReplace(interp, objResultPtr, len,0, objc,objv) != TCL_OK) { goto errorInLappendListPtr; } } DECACHE_STACK_INFO(); objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, objResultPtr, TCL_LEAVE_ERR_MSG, opnd); CACHE_STACK_INFO(); if (!objResultPtr) { errorInLappendListPtr: if (createdNewObj) { TclDecrRefCount(objResultPtr); } TRACE_ERROR(interp); goto gotError; } } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(pcAdjustment, cleanup, 1); } /* * End of INST_STORE and related instructions. * ----------------------------------------------------------------- * Start of INST_INCR instructions. * * WARNING: more 'goto' here than your doctor recommended! The different * instructions set the value of some variables and then jump to somme * common execution code. */ /*TODO: Consider more untangling here; merge with LOAD and STORE ? */ { Tcl_Obj *incrPtr; #ifndef TCL_WIDE_INT_IS_LONG Tcl_WideInt w; #endif long increment; case INST_INCR_SCALAR1: case INST_INCR_ARRAY1: case INST_INCR_ARRAY_STK: case INST_INCR_SCALAR_STK: case INST_INCR_STK: opnd = TclGetUInt1AtPtr(pc+1); incrPtr = POP_OBJECT(); switch (*pc) { case INST_INCR_SCALAR1: pcAdjustment = 2; goto doIncrScalar; case INST_INCR_ARRAY1: pcAdjustment = 2; goto doIncrArray; default: pcAdjustment = 1; goto doIncrStk; } case INST_INCR_ARRAY_STK_IMM: case INST_INCR_SCALAR_STK_IMM: case INST_INCR_STK_IMM: increment = TclGetInt1AtPtr(pc+1); incrPtr = Tcl_NewIntObj(increment); Tcl_IncrRefCount(incrPtr); pcAdjustment = 2; doIncrStk: if ((*pc == INST_INCR_ARRAY_STK_IMM) || (*pc == INST_INCR_ARRAY_STK)) { part2Ptr = OBJ_AT_TOS; objPtr = OBJ_UNDER_TOS; TRACE(("\"%.30s(%.30s)\" (by %ld) => ", O2S(objPtr), O2S(part2Ptr), increment)); } else { part2Ptr = NULL; objPtr = OBJ_AT_TOS; TRACE(("\"%.30s\" (by %ld) => ", O2S(objPtr), increment)); } part1Ptr = objPtr; opnd = -1; varPtr = TclObjLookupVarEx(interp, objPtr, part2Ptr, TCL_LEAVE_ERR_MSG, "read", 1, 1, &arrayPtr); if (!varPtr) { DECACHE_STACK_INFO(); Tcl_AddErrorInfo(interp, "\n (reading value of variable to increment)"); CACHE_STACK_INFO(); TRACE_ERROR(interp); Tcl_DecrRefCount(incrPtr); goto gotError; } cleanup = ((part2Ptr == NULL)? 1 : 2); goto doIncrVar; case INST_INCR_ARRAY1_IMM: opnd = TclGetUInt1AtPtr(pc+1); increment = TclGetInt1AtPtr(pc+2); incrPtr = Tcl_NewIntObj(increment); Tcl_IncrRefCount(incrPtr); pcAdjustment = 3; doIncrArray: part1Ptr = NULL; part2Ptr = OBJ_AT_TOS; arrayPtr = LOCAL(opnd); cleanup = 1; while (TclIsVarLink(arrayPtr)) { arrayPtr = arrayPtr->value.linkPtr; } TRACE(("%u \"%.30s\" (by %ld) => ", opnd, O2S(part2Ptr), increment)); varPtr = TclLookupArrayElement(interp, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, "read", 1, 1, arrayPtr, opnd); if (!varPtr) { TRACE_ERROR(interp); Tcl_DecrRefCount(incrPtr); goto gotError; } goto doIncrVar; case INST_INCR_SCALAR1_IMM: opnd = TclGetUInt1AtPtr(pc+1); increment = TclGetInt1AtPtr(pc+2); pcAdjustment = 3; cleanup = 0; varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (TclIsVarDirectModifyable(varPtr)) { ClientData ptr; int type; objPtr = varPtr->value.objPtr; if (GetNumberFromObj(NULL, objPtr, &ptr, &type) == TCL_OK) { if (type == TCL_NUMBER_LONG) { long augend = *((const long *)ptr); long sum = augend + increment; /* * Overflow when (augend and sum have different sign) and * (augend and increment have the same sign). This is * encapsulated in the Overflowing macro. */ if (!Overflowing(augend, increment, sum)) { TRACE(("%u %ld => ", opnd, increment)); if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared. */ TclNewLongObj(objResultPtr, sum); Tcl_IncrRefCount(objResultPtr); varPtr->value.objPtr = objResultPtr; } else { objResultPtr = objPtr; TclSetLongObj(objPtr, sum); } goto doneIncr; } #ifndef TCL_WIDE_INT_IS_LONG w = (Tcl_WideInt)augend; TRACE(("%u %ld => ", opnd, increment)); if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared. */ objResultPtr = Tcl_NewWideIntObj(w+increment); Tcl_IncrRefCount(objResultPtr); varPtr->value.objPtr = objResultPtr; } else { objResultPtr = objPtr; /* * We know the sum value is outside the long range; * use macro form that doesn't range test again. */ TclSetWideIntObj(objPtr, w+increment); } goto doneIncr; #endif } /* end if (type == TCL_NUMBER_LONG) */ #ifndef TCL_WIDE_INT_IS_LONG if (type == TCL_NUMBER_WIDE) { Tcl_WideInt sum; w = *((const Tcl_WideInt *) ptr); sum = w + increment; /* * Check for overflow. */ if (!Overflowing(w, increment, sum)) { TRACE(("%u %ld => ", opnd, increment)); if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared. */ objResultPtr = Tcl_NewWideIntObj(sum); Tcl_IncrRefCount(objResultPtr); varPtr->value.objPtr = objResultPtr; } else { objResultPtr = objPtr; /* * We *do not* know the sum value is outside the * long range (wide + long can yield long); use * the function call that checks range. */ Tcl_SetWideIntObj(objPtr, sum); } goto doneIncr; } } #endif } if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared */ objResultPtr = Tcl_DuplicateObj(objPtr); Tcl_IncrRefCount(objResultPtr); varPtr->value.objPtr = objResultPtr; } else { objResultPtr = objPtr; } TclNewLongObj(incrPtr, increment); if (TclIncrObj(interp, objResultPtr, incrPtr) != TCL_OK) { Tcl_DecrRefCount(incrPtr); TRACE_ERROR(interp); goto gotError; } Tcl_DecrRefCount(incrPtr); goto doneIncr; } /* * All other cases, flow through to generic handling. */ TclNewLongObj(incrPtr, increment); Tcl_IncrRefCount(incrPtr); doIncrScalar: varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } arrayPtr = NULL; part1Ptr = part2Ptr = NULL; cleanup = 0; TRACE(("%u %s => ", opnd, Tcl_GetString(incrPtr))); doIncrVar: if (TclIsVarDirectModifyable2(varPtr, arrayPtr)) { objPtr = varPtr->value.objPtr; if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared */ objResultPtr = Tcl_DuplicateObj(objPtr); Tcl_IncrRefCount(objResultPtr); varPtr->value.objPtr = objResultPtr; } else { objResultPtr = objPtr; } if (TclIncrObj(interp, objResultPtr, incrPtr) != TCL_OK) { Tcl_DecrRefCount(incrPtr); TRACE_ERROR(interp); goto gotError; } Tcl_DecrRefCount(incrPtr); } else { DECACHE_STACK_INFO(); objResultPtr = TclPtrIncrObjVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, incrPtr, TCL_LEAVE_ERR_MSG, opnd); CACHE_STACK_INFO(); Tcl_DecrRefCount(incrPtr); if (objResultPtr == NULL) { TRACE_ERROR(interp); goto gotError; } } doneIncr: TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); #ifndef TCL_COMPILE_DEBUG if (*(pc+pcAdjustment) == INST_POP) { NEXT_INST_V((pcAdjustment+1), cleanup, 0); } #endif NEXT_INST_V(pcAdjustment, cleanup, 1); } /* * End of INST_INCR instructions. * ----------------------------------------------------------------- * Start of INST_EXIST instructions. */ case INST_EXIST_SCALAR: cleanup = 0; pcAdjustment = 5; opnd = TclGetUInt4AtPtr(pc+1); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (ReadTraced(varPtr)) { DECACHE_STACK_INFO(); TclObjCallVarTraces(iPtr, NULL, varPtr, NULL, NULL, TCL_TRACE_READS, 0, opnd); CACHE_STACK_INFO(); if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, NULL); varPtr = NULL; } } goto afterExistsPeephole; case INST_EXIST_ARRAY: cleanup = 1; pcAdjustment = 5; opnd = TclGetUInt4AtPtr(pc+1); part2Ptr = OBJ_AT_TOS; arrayPtr = LOCAL(opnd); while (TclIsVarLink(arrayPtr)) { arrayPtr = arrayPtr->value.linkPtr; } TRACE(("%u \"%.30s\" => ", opnd, O2S(part2Ptr))); if (TclIsVarArray(arrayPtr) && !ReadTraced(arrayPtr)) { varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr); if (!varPtr || !ReadTraced(varPtr)) { goto afterExistsPeephole; } } varPtr = TclLookupArrayElement(interp, NULL, part2Ptr, 0, "access", 0, 1, arrayPtr, opnd); if (varPtr) { if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) { DECACHE_STACK_INFO(); TclObjCallVarTraces(iPtr, arrayPtr, varPtr, NULL, part2Ptr, TCL_TRACE_READS, 0, opnd); CACHE_STACK_INFO(); } if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, arrayPtr); varPtr = NULL; } } goto afterExistsPeephole; case INST_EXIST_ARRAY_STK: cleanup = 2; pcAdjustment = 1; part2Ptr = OBJ_AT_TOS; /* element name */ part1Ptr = OBJ_UNDER_TOS; /* array name */ TRACE(("\"%.30s(%.30s)\" => ", O2S(part1Ptr), O2S(part2Ptr))); goto doExistStk; case INST_EXIST_STK: cleanup = 1; pcAdjustment = 1; part2Ptr = NULL; part1Ptr = OBJ_AT_TOS; /* variable name */ TRACE(("\"%.30s\" => ", O2S(part1Ptr))); doExistStk: varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, 0, "access", /*createPart1*/0, /*createPart2*/1, &arrayPtr); if (varPtr) { if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) { DECACHE_STACK_INFO(); TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr,part2Ptr, TCL_TRACE_READS, 0, -1); CACHE_STACK_INFO(); } if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, arrayPtr); varPtr = NULL; } } /* * Peep-hole optimisation: if you're about to jump, do jump from here. */ afterExistsPeephole: { int found = (varPtr && !TclIsVarUndefined(varPtr)); TRACE_APPEND(("%d\n", found ? 1 : 0)); JUMP_PEEPHOLE_V(found, pcAdjustment, cleanup); } /* * End of INST_EXIST instructions. * ----------------------------------------------------------------- * Start of INST_UNSET instructions. */ { int flags; case INST_UNSET_SCALAR: flags = TclGetUInt1AtPtr(pc+1) ? TCL_LEAVE_ERR_MSG : 0; opnd = TclGetUInt4AtPtr(pc+2); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%s %u => ", (flags ? "normal" : "noerr"), opnd)); if (TclIsVarDirectUnsettable(varPtr) && !TclIsVarInHash(varPtr)) { /* * No errors, no traces, no searches: just make the variable cease * to exist. */ if (!TclIsVarUndefined(varPtr)) { TclDecrRefCount(varPtr->value.objPtr); } else if (flags & TCL_LEAVE_ERR_MSG) { goto slowUnsetScalar; } varPtr->value.objPtr = NULL; TRACE_APPEND(("OK\n")); NEXT_INST_F(6, 0, 0); } slowUnsetScalar: DECACHE_STACK_INFO(); if (TclPtrUnsetVar(interp, varPtr, NULL, NULL, NULL, flags, opnd) != TCL_OK && flags) { goto errorInUnset; } CACHE_STACK_INFO(); NEXT_INST_F(6, 0, 0); case INST_UNSET_ARRAY: flags = TclGetUInt1AtPtr(pc+1) ? TCL_LEAVE_ERR_MSG : 0; opnd = TclGetUInt4AtPtr(pc+2); part2Ptr = OBJ_AT_TOS; arrayPtr = LOCAL(opnd); while (TclIsVarLink(arrayPtr)) { arrayPtr = arrayPtr->value.linkPtr; } TRACE(("%s %u \"%.30s\" => ", (flags ? "normal" : "noerr"), opnd, O2S(part2Ptr))); if (TclIsVarArray(arrayPtr) && !UnsetTraced(arrayPtr)) { varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr); if (varPtr && TclIsVarDirectUnsettable(varPtr)) { /* * No nasty traces and element exists, so we can proceed to * unset it. Might still not exist though... */ if (!TclIsVarUndefined(varPtr)) { TclDecrRefCount(varPtr->value.objPtr); TclSetVarUndefined(varPtr); TclClearVarNamespaceVar(varPtr); TclCleanupVar(varPtr, arrayPtr); } else if (flags & TCL_LEAVE_ERR_MSG) { goto slowUnsetArray; } TRACE_APPEND(("OK\n")); NEXT_INST_F(6, 1, 0); } else if (!varPtr && !(flags & TCL_LEAVE_ERR_MSG)) { /* * Don't need to do anything here. */ TRACE_APPEND(("OK\n")); NEXT_INST_F(6, 1, 0); } } slowUnsetArray: DECACHE_STACK_INFO(); varPtr = TclLookupArrayElement(interp, NULL, part2Ptr, flags, "unset", 0, 0, arrayPtr, opnd); if (!varPtr) { if (flags & TCL_LEAVE_ERR_MSG) { goto errorInUnset; } } else if (TclPtrUnsetVar(interp, varPtr, arrayPtr, NULL, part2Ptr, flags, opnd) != TCL_OK && (flags & TCL_LEAVE_ERR_MSG)) { goto errorInUnset; } CACHE_STACK_INFO(); NEXT_INST_F(6, 1, 0); case INST_UNSET_ARRAY_STK: flags = TclGetUInt1AtPtr(pc+1) ? TCL_LEAVE_ERR_MSG : 0; cleanup = 2; part2Ptr = OBJ_AT_TOS; /* element name */ part1Ptr = OBJ_UNDER_TOS; /* array name */ TRACE(("%s \"%.30s(%.30s)\" => ", (flags ? "normal" : "noerr"), O2S(part1Ptr), O2S(part2Ptr))); goto doUnsetStk; case INST_UNSET_STK: flags = TclGetUInt1AtPtr(pc+1) ? TCL_LEAVE_ERR_MSG : 0; cleanup = 1; part2Ptr = NULL; part1Ptr = OBJ_AT_TOS; /* variable name */ TRACE(("%s \"%.30s\" => ", (flags ? "normal" : "noerr"), O2S(part1Ptr))); doUnsetStk: DECACHE_STACK_INFO(); if (TclObjUnsetVar2(interp, part1Ptr, part2Ptr, flags) != TCL_OK && (flags & TCL_LEAVE_ERR_MSG)) { goto errorInUnset; } CACHE_STACK_INFO(); TRACE_APPEND(("OK\n")); NEXT_INST_V(2, cleanup, 0); errorInUnset: CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; /* * This is really an unset operation these days. Do not issue. */ case INST_DICT_DONE: opnd = TclGetUInt4AtPtr(pc+1); TRACE(("%u => OK\n", opnd)); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (TclIsVarDirectUnsettable(varPtr) && !TclIsVarInHash(varPtr)) { if (!TclIsVarUndefined(varPtr)) { TclDecrRefCount(varPtr->value.objPtr); } varPtr->value.objPtr = NULL; } else { DECACHE_STACK_INFO(); TclPtrUnsetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd); CACHE_STACK_INFO(); } NEXT_INST_F(5, 0, 0); } /* * End of INST_UNSET instructions. * ----------------------------------------------------------------- * Start of INST_ARRAY instructions. */ case INST_ARRAY_EXISTS_IMM: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; cleanup = 0; part1Ptr = NULL; arrayPtr = NULL; TRACE(("%u => ", opnd)); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } goto doArrayExists; case INST_ARRAY_EXISTS_STK: opnd = -1; pcAdjustment = 1; cleanup = 1; part1Ptr = OBJ_AT_TOS; TRACE(("\"%.30s\" => ", O2S(part1Ptr))); varPtr = TclObjLookupVarEx(interp, part1Ptr, NULL, 0, NULL, /*createPart1*/0, /*createPart2*/0, &arrayPtr); doArrayExists: if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { DECACHE_STACK_INFO(); result = TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY| TCL_GLOBAL_ONLY|TCL_TRACE_ARRAY), 1, opnd); CACHE_STACK_INFO(); if (result == TCL_ERROR) { TRACE_ERROR(interp); goto gotError; } } if (varPtr && TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) { objResultPtr = TCONST(1); } else { objResultPtr = TCONST(0); } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(pcAdjustment, cleanup, 1); case INST_ARRAY_MAKE_IMM: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; cleanup = 0; part1Ptr = NULL; arrayPtr = NULL; TRACE(("%u => ", opnd)); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } goto doArrayMake; case INST_ARRAY_MAKE_STK: opnd = -1; pcAdjustment = 1; cleanup = 1; part1Ptr = OBJ_AT_TOS; TRACE(("\"%.30s\" => ", O2S(part1Ptr))); varPtr = TclObjLookupVarEx(interp, part1Ptr, NULL, TCL_LEAVE_ERR_MSG, "set", /*createPart1*/1, /*createPart2*/0, &arrayPtr); if (varPtr == NULL) { TRACE_ERROR(interp); goto gotError; } doArrayMake: if (varPtr && !TclIsVarArray(varPtr)) { if (TclIsVarArrayElement(varPtr) || !TclIsVarUndefined(varPtr)) { /* * Either an array element, or a scalar: lose! */ TclObjVarErrMsg(interp, part1Ptr, NULL, "array set", "variable isn't array", opnd); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL); CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } TclSetVarArray(varPtr); varPtr->value.tablePtr = ckalloc(sizeof(TclVarHashTable)); TclInitVarHashTable(varPtr->value.tablePtr, TclGetVarNsPtr(varPtr)); #ifdef TCL_COMPILE_DEBUG TRACE_APPEND(("done\n")); } else { TRACE_APPEND(("nothing to do\n")); #endif } NEXT_INST_V(pcAdjustment, cleanup, 0); /* * End of INST_ARRAY instructions. * ----------------------------------------------------------------- * Start of variable linking instructions. */ { Var *otherPtr; CallFrame *framePtr, *savedFramePtr; Tcl_Namespace *nsPtr; Namespace *savedNsPtr; case INST_UPVAR: TRACE(("%d %.30s %.30s => ", TclGetInt4AtPtr(pc+1), O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS))); if (TclObjGetFrame(interp, OBJ_UNDER_TOS, &framePtr) == -1) { TRACE_ERROR(interp); goto gotError; } /* * Locate the other variable. */ savedFramePtr = iPtr->varFramePtr; iPtr->varFramePtr = framePtr; otherPtr = TclObjLookupVarEx(interp, OBJ_AT_TOS, NULL, TCL_LEAVE_ERR_MSG, "access", /*createPart1*/ 1, /*createPart2*/ 1, &varPtr); iPtr->varFramePtr = savedFramePtr; if (!otherPtr) { TRACE_ERROR(interp); goto gotError; } goto doLinkVars; case INST_NSUPVAR: TRACE(("%d %.30s %.30s => ", TclGetInt4AtPtr(pc+1), O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS))); if (TclGetNamespaceFromObj(interp, OBJ_UNDER_TOS, &nsPtr) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } /* * Locate the other variable. */ savedNsPtr = iPtr->varFramePtr->nsPtr; iPtr->varFramePtr->nsPtr = (Namespace *) nsPtr; otherPtr = TclObjLookupVarEx(interp, OBJ_AT_TOS, NULL, (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access", /*createPart1*/ 1, /*createPart2*/ 1, &varPtr); iPtr->varFramePtr->nsPtr = savedNsPtr; if (!otherPtr) { TRACE_ERROR(interp); goto gotError; } goto doLinkVars; case INST_VARIABLE: TRACE(("%d, %.30s => ", TclGetInt4AtPtr(pc+1), O2S(OBJ_AT_TOS))); otherPtr = TclObjLookupVarEx(interp, OBJ_AT_TOS, NULL, (TCL_NAMESPACE_ONLY | TCL_LEAVE_ERR_MSG), "access", /*createPart1*/ 1, /*createPart2*/ 1, &varPtr); if (!otherPtr) { TRACE_ERROR(interp); goto gotError; } /* * Do the [variable] magic. */ TclSetVarNamespaceVar(otherPtr); doLinkVars: /* * If we are here, the local variable has already been created: do the * little work of TclPtrMakeUpvar that remains to be done right here * if there are no errors; otherwise, let it handle the case. */ opnd = TclGetInt4AtPtr(pc+1); varPtr = LOCAL(opnd); if ((varPtr != otherPtr) && !TclIsVarTraced(varPtr) && (TclIsVarUndefined(varPtr) || TclIsVarLink(varPtr))) { if (!TclIsVarUndefined(varPtr)) { /* * Then it is a defined link. */ Var *linkPtr = varPtr->value.linkPtr; if (linkPtr == otherPtr) { TRACE_APPEND(("already linked\n")); NEXT_INST_F(5, 1, 0); } if (TclIsVarInHash(linkPtr)) { VarHashRefCount(linkPtr)--; if (TclIsVarUndefined(linkPtr)) { TclCleanupVar(linkPtr, NULL); } } } TclSetVarLink(varPtr); varPtr->value.linkPtr = otherPtr; if (TclIsVarInHash(otherPtr)) { VarHashRefCount(otherPtr)++; } } else if (TclPtrObjMakeUpvar(interp, otherPtr, NULL, 0, opnd) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } /* * Do not pop the namespace or frame index, it may be needed for other * variables - and [variable] did not push it at all. */ TRACE_APPEND(("link made\n")); NEXT_INST_F(5, 1, 0); } /* * End of variable linking instructions. * ----------------------------------------------------------------- */ case INST_JUMP1: opnd = TclGetInt1AtPtr(pc+1); TRACE(("%d => new pc %u\n", opnd, (unsigned)(pc + opnd - codePtr->codeStart))); NEXT_INST_F(opnd, 0, 0); case INST_JUMP4: opnd = TclGetInt4AtPtr(pc+1); TRACE(("%d => new pc %u\n", opnd, (unsigned)(pc + opnd - codePtr->codeStart))); NEXT_INST_F(opnd, 0, 0); { int jmpOffset[2], b; /* TODO: consider rewrite so we don't compute the offset we're not * going to take. */ case INST_JUMP_FALSE4: jmpOffset[0] = TclGetInt4AtPtr(pc+1); /* FALSE offset */ jmpOffset[1] = 5; /* TRUE offset */ goto doCondJump; case INST_JUMP_TRUE4: jmpOffset[0] = 5; jmpOffset[1] = TclGetInt4AtPtr(pc+1); goto doCondJump; case INST_JUMP_FALSE1: jmpOffset[0] = TclGetInt1AtPtr(pc+1); jmpOffset[1] = 2; goto doCondJump; case INST_JUMP_TRUE1: jmpOffset[0] = 2; jmpOffset[1] = TclGetInt1AtPtr(pc+1); doCondJump: valuePtr = OBJ_AT_TOS; TRACE(("%d => ", jmpOffset[ (*pc==INST_JUMP_FALSE1 || *pc==INST_JUMP_FALSE4) ? 0 : 1])); /* TODO - check claim that taking address of b harms performance */ /* TODO - consider optimization search for constants */ if (TclGetBooleanFromObj(interp, valuePtr, &b) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } #ifdef TCL_COMPILE_DEBUG if (b) { if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE4)) { TRACE_APPEND(("%.20s true, new pc %u\n", O2S(valuePtr), (unsigned)(pc + jmpOffset[1] - codePtr->codeStart))); } else { TRACE_APPEND(("%.20s true\n", O2S(valuePtr))); } } else { if ((*pc == INST_JUMP_TRUE1) || (*pc == INST_JUMP_TRUE4)) { TRACE_APPEND(("%.20s false\n", O2S(valuePtr))); } else { TRACE_APPEND(("%.20s false, new pc %u\n", O2S(valuePtr), (unsigned)(pc + jmpOffset[0] - codePtr->codeStart))); } } #endif NEXT_INST_F(jmpOffset[b], 1, 0); } case INST_JUMP_TABLE: { Tcl_HashEntry *hPtr; JumptableInfo *jtPtr; /* * Jump to location looked up in a hashtable; fall through to next * instr if lookup fails. */ opnd = TclGetInt4AtPtr(pc+1); jtPtr = (JumptableInfo *) codePtr->auxDataArrayPtr[opnd].clientData; TRACE(("%d \"%.20s\" => ", opnd, O2S(OBJ_AT_TOS))); hPtr = Tcl_FindHashEntry(&jtPtr->hashTable, TclGetString(OBJ_AT_TOS)); if (hPtr != NULL) { int jumpOffset = PTR2INT(Tcl_GetHashValue(hPtr)); TRACE_APPEND(("found in table, new pc %u\n", (unsigned)(pc - codePtr->codeStart + jumpOffset))); NEXT_INST_F(jumpOffset, 1, 0); } else { TRACE_APPEND(("not found in table\n")); NEXT_INST_F(5, 1, 0); } } /* * These two instructions are now redundant: the complete logic of the LOR * and LAND is now handled by the expression compiler. */ case INST_LOR: case INST_LAND: { /* * Operands must be boolean or numeric. No int->double conversions are * performed. */ int i1, i2, iResult; value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; if (TclGetBooleanFromObj(NULL, valuePtr, &i1) != TCL_OK) { TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, pc, valuePtr); CACHE_STACK_INFO(); goto gotError; } if (TclGetBooleanFromObj(NULL, value2Ptr, &i2) != TCL_OK) { TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(value2Ptr), (value2Ptr->typePtr? value2Ptr->typePtr->name : "null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, pc, value2Ptr); CACHE_STACK_INFO(); goto gotError; } if (*pc == INST_LOR) { iResult = (i1 || i2); } else { iResult = (i1 && i2); } objResultPtr = TCONST(iResult); TRACE(("%.20s %.20s => %d\n", O2S(valuePtr),O2S(value2Ptr),iResult)); NEXT_INST_F(1, 2, 1); } /* * ----------------------------------------------------------------- * Start of general introspector instructions. */ case INST_NS_CURRENT: { Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp); if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) { TclNewLiteralStringObj(objResultPtr, "::"); } else { TclNewStringObj(objResultPtr, currNsPtr->fullName, strlen(currNsPtr->fullName)); } TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); } case INST_COROUTINE_NAME: { CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; TclNewObj(objResultPtr); if (corPtr && !(corPtr->cmdPtr->flags & CMD_IS_DELETED)) { Tcl_GetCommandFullName(interp, (Tcl_Command) corPtr->cmdPtr, objResultPtr); } TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); } case INST_INFO_LEVEL_NUM: TclNewIntObj(objResultPtr, iPtr->varFramePtr->level); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); case INST_INFO_LEVEL_ARGS: { int level; register CallFrame *framePtr = iPtr->varFramePtr; register CallFrame *rootFramePtr = iPtr->rootFramePtr; TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS))); if (TclGetIntFromObj(interp, OBJ_AT_TOS, &level) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } if (level <= 0) { level += framePtr->level; } for (; (framePtr->level!=level) && (framePtr!=rootFramePtr) ; framePtr = framePtr->callerVarPtr) { /* Empty loop body */ } if (framePtr == rootFramePtr) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad level \"%s\"", TclGetString(OBJ_AT_TOS))); TRACE_ERROR(interp); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "STACK_LEVEL", TclGetString(OBJ_AT_TOS), NULL); CACHE_STACK_INFO(); goto gotError; } objResultPtr = Tcl_NewListObj(framePtr->objc, framePtr->objv); TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } { Tcl_Command cmd, origCmd; case INST_RESOLVE_COMMAND: cmd = Tcl_GetCommandFromObj(interp, OBJ_AT_TOS); TclNewObj(objResultPtr); if (cmd != NULL) { Tcl_GetCommandFullName(interp, cmd, objResultPtr); } TRACE_WITH_OBJ(("\"%.20s\" => ", O2S(OBJ_AT_TOS)), objResultPtr); NEXT_INST_F(1, 1, 1); case INST_ORIGIN_COMMAND: TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS))); cmd = Tcl_GetCommandFromObj(interp, OBJ_AT_TOS); if (cmd == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid command name \"%s\"", TclGetString(OBJ_AT_TOS))); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", TclGetString(OBJ_AT_TOS), NULL); CACHE_STACK_INFO(); TRACE_APPEND(("ERROR: not command\n")); goto gotError; } origCmd = TclGetOriginalCommand(cmd); if (origCmd == NULL) { origCmd = cmd; } TclNewObj(objResultPtr); Tcl_GetCommandFullName(interp, origCmd, objResultPtr); TRACE_APPEND(("\"%.30s\"", O2S(OBJ_AT_TOS))); NEXT_INST_F(1, 1, 1); } /* * ----------------------------------------------------------------- * Start of TclOO support instructions. */ { Object *oPtr; CallFrame *framePtr; CallContext *contextPtr; int skip, newDepth; case INST_TCLOO_SELF: framePtr = iPtr->varFramePtr; if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) { TRACE(("=> ERROR: no TclOO call context\n")); Tcl_SetObjResult(interp, Tcl_NewStringObj( "self may only be called from inside a method", -1)); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); CACHE_STACK_INFO(); goto gotError; } contextPtr = framePtr->clientData; /* * Call out to get the name; it's expensive to compute but cached. */ objResultPtr = TclOOObjectName(interp, contextPtr->oPtr); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); case INST_TCLOO_NEXT_CLASS: opnd = TclGetUInt1AtPtr(pc+1); framePtr = iPtr->varFramePtr; valuePtr = OBJ_AT_DEPTH(opnd - 2); objv = &OBJ_AT_DEPTH(opnd - 1); skip = 2; TRACE(("%d => ", opnd)); if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) { TRACE_APPEND(("ERROR: no TclOO call context\n")); Tcl_SetObjResult(interp, Tcl_NewStringObj( "nextto may only be called from inside a method", -1)); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); CACHE_STACK_INFO(); goto gotError; } contextPtr = framePtr->clientData; oPtr = (Object *) Tcl_GetObjectFromObj(interp, valuePtr); if (oPtr == NULL) { TRACE_APPEND(("ERROR: \"%.30s\" not object\n", O2S(valuePtr))); goto gotError; } else { Class *classPtr = oPtr->classPtr; struct MInvoke *miPtr; int i; const char *methodType; if (classPtr == NULL) { TRACE_APPEND(("ERROR: \"%.30s\" not class\n", O2S(valuePtr))); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" is not a class", TclGetString(valuePtr))); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_REQUIRED", NULL); CACHE_STACK_INFO(); goto gotError; } for (i=contextPtr->index+1 ; icallPtr->numChain ; i++) { miPtr = contextPtr->callPtr->chain + i; if (!miPtr->isFilter && miPtr->mPtr->declaringClassPtr == classPtr) { newDepth = i; #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= 2) { if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); } else { fprintf(stdout, "%d: (%u) invoking ", iPtr->numLevels, (unsigned)(pc - codePtr->codeStart)); } for (i = 0; i < opnd; i++) { TclPrintObject(stdout, objv[i], 15); fprintf(stdout, " "); } fprintf(stdout, "\n"); fflush(stdout); } #endif /*TCL_COMPILE_DEBUG*/ goto doInvokeNext; } } if (contextPtr->callPtr->flags & CONSTRUCTOR) { methodType = "constructor"; } else if (contextPtr->callPtr->flags & DESTRUCTOR) { methodType = "destructor"; } else { methodType = "method"; } TRACE_APPEND(("ERROR: \"%.30s\" not on reachable chain\n", O2S(valuePtr))); for (i=contextPtr->index ; i>=0 ; i--) { miPtr = contextPtr->callPtr->chain + i; if (miPtr->isFilter || miPtr->mPtr->declaringClassPtr != classPtr) { continue; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s implementation by \"%s\" not reachable from here", methodType, TclGetString(valuePtr))); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_REACHABLE", NULL); CACHE_STACK_INFO(); goto gotError; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s has no non-filter implementation by \"%s\"", methodType, TclGetString(valuePtr))); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_NOT_THERE", NULL); CACHE_STACK_INFO(); goto gotError; } case INST_TCLOO_NEXT: opnd = TclGetUInt1AtPtr(pc+1); objv = &OBJ_AT_DEPTH(opnd - 1); framePtr = iPtr->varFramePtr; skip = 1; TRACE(("%d => ", opnd)); if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) { TRACE_APPEND(("ERROR: no TclOO call context\n")); Tcl_SetObjResult(interp, Tcl_NewStringObj( "next may only be called from inside a method", -1)); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "OO", "CONTEXT_REQUIRED", NULL); CACHE_STACK_INFO(); goto gotError; } contextPtr = framePtr->clientData; newDepth = contextPtr->index + 1; if (newDepth >= contextPtr->callPtr->numChain) { /* * We're at the end of the chain; generate an error message unless * the interpreter is being torn down, in which case we might be * getting here because of methods/destructors doing a [next] (or * equivalent) unexpectedly. */ const char *methodType; if (contextPtr->callPtr->flags & CONSTRUCTOR) { methodType = "constructor"; } else if (contextPtr->callPtr->flags & DESTRUCTOR) { methodType = "destructor"; } else { methodType = "method"; } TRACE_APPEND(("ERROR: no TclOO next impl\n")); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "no next %s implementation", methodType)); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", NULL); CACHE_STACK_INFO(); goto gotError; #ifdef TCL_COMPILE_DEBUG } else if (tclTraceExec >= 2) { int i; if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); } else { fprintf(stdout, "%d: (%u) invoking ", iPtr->numLevels, (unsigned)(pc - codePtr->codeStart)); } for (i = 0; i < opnd; i++) { TclPrintObject(stdout, objv[i], 15); fprintf(stdout, " "); } fprintf(stdout, "\n"); fflush(stdout); #endif /*TCL_COMPILE_DEBUG*/ } doInvokeNext: bcFramePtr->data.tebc.pc = (char *) pc; iPtr->cmdFramePtr = bcFramePtr; if (iPtr->flags & INTERP_DEBUG_FRAME) { ArgumentBCEnter(interp, codePtr, TD, pc, opnd, objv); } pcAdjustment = 2; cleanup = opnd; DECACHE_STACK_INFO(); iPtr->varFramePtr = framePtr->callerVarPtr; pc += pcAdjustment; TEBC_YIELD(); TclPushTailcallPoint(interp); oPtr = contextPtr->oPtr; if (oPtr->flags & FILTER_HANDLING) { TclNRAddCallback(interp, FinalizeOONextFilter, framePtr, contextPtr, INT2PTR(contextPtr->index), INT2PTR(contextPtr->skip)); } else { TclNRAddCallback(interp, FinalizeOONext, framePtr, contextPtr, INT2PTR(contextPtr->index), INT2PTR(contextPtr->skip)); } contextPtr->skip = skip; contextPtr->index = newDepth; if (contextPtr->callPtr->chain[newDepth].isFilter || contextPtr->callPtr->flags & FILTER_HANDLING) { oPtr->flags |= FILTER_HANDLING; } else { oPtr->flags &= ~FILTER_HANDLING; } { register Method *const mPtr = contextPtr->callPtr->chain[newDepth].mPtr; return mPtr->typePtr->callProc(mPtr->clientData, interp, (Tcl_ObjectContext) contextPtr, opnd, objv); } case INST_TCLOO_IS_OBJECT: oPtr = (Object *) Tcl_GetObjectFromObj(interp, OBJ_AT_TOS); objResultPtr = TCONST(oPtr != NULL ? 1 : 0); TRACE_WITH_OBJ(("%.30s => ", O2S(OBJ_AT_TOS)), objResultPtr); NEXT_INST_F(1, 1, 1); case INST_TCLOO_CLASS: oPtr = (Object *) Tcl_GetObjectFromObj(interp, OBJ_AT_TOS); if (oPtr == NULL) { TRACE(("%.30s => ERROR: not object\n", O2S(OBJ_AT_TOS))); goto gotError; } objResultPtr = TclOOObjectName(interp, oPtr->selfCls->thisPtr); TRACE_WITH_OBJ(("%.30s => ", O2S(OBJ_AT_TOS)), objResultPtr); NEXT_INST_F(1, 1, 1); case INST_TCLOO_NS: oPtr = (Object *) Tcl_GetObjectFromObj(interp, OBJ_AT_TOS); if (oPtr == NULL) { TRACE(("%.30s => ERROR: not object\n", O2S(OBJ_AT_TOS))); goto gotError; } /* * TclOO objects *never* have the global namespace as their NS. */ TclNewStringObj(objResultPtr, oPtr->namespacePtr->fullName, strlen(oPtr->namespacePtr->fullName)); TRACE_WITH_OBJ(("%.30s => ", O2S(OBJ_AT_TOS)), objResultPtr); NEXT_INST_F(1, 1, 1); } /* * End of TclOO support instructions. * ----------------------------------------------------------------- * Start of INST_LIST and related instructions. */ { int index, numIndices, fromIdx, toIdx; int nocase, match, length2, cflags, s1len, s2len; const char *s1, *s2; case INST_LIST: /* * Pop the opnd (objc) top stack elements into a new list obj and then * decrement their ref counts. */ opnd = TclGetUInt4AtPtr(pc+1); objResultPtr = Tcl_NewListObj(opnd, &OBJ_AT_DEPTH(opnd-1)); TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr); NEXT_INST_V(5, opnd, 1); case INST_LIST_LENGTH: TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS))); if (TclListObjLength(interp, OBJ_AT_TOS, &length) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } TclNewIntObj(objResultPtr, length); TRACE_APPEND(("%d\n", length)); NEXT_INST_F(1, 1, 1); case INST_LIST_INDEX: /* lindex with objc == 3 */ value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr))); /* * Extract the desired list element. */ if ((TclListObjGetElements(interp, valuePtr, &objc, &objv) == TCL_OK) && (value2Ptr->typePtr != &tclListType) && (TclGetIntForIndexM(NULL , value2Ptr, objc-1, &index) == TCL_OK)) { TclDecrRefCount(value2Ptr); tosPtr--; pcAdjustment = 1; goto lindexFastPath; } objResultPtr = TclLindexList(interp, valuePtr, value2Ptr); if (!objResultPtr) { TRACE_ERROR(interp); goto gotError; } /* * Stash the list element on the stack. */ TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, -1); /* Already has the correct refCount */ case INST_LIST_INDEX_IMM: /* lindex with objc==3 and index in bytecode * stream */ /* * Pop the list and get the index. */ valuePtr = OBJ_AT_TOS; opnd = TclGetInt4AtPtr(pc+1); TRACE(("\"%.30s\" %d => ", O2S(valuePtr), opnd)); /* * Get the contents of the list, making sure that it really is a list * in the process. */ if (TclListObjGetElements(interp, valuePtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } /* * Select the list item based on the index. Negative operand means * end-based indexing. */ if (opnd < -1) { index = opnd+1 + objc; } else { index = opnd; } pcAdjustment = 5; lindexFastPath: if (index >= 0 && index < objc) { objResultPtr = objv[index]; } else { TclNewObj(objResultPtr); } TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_F(pcAdjustment, 1, 1); case INST_LIST_INDEX_MULTI: /* 'lindex' with multiple index args */ /* * Determine the count of index args. */ opnd = TclGetUInt4AtPtr(pc+1); numIndices = opnd-1; /* * Do the 'lindex' operation. */ TRACE(("%d => ", opnd)); objResultPtr = TclLindexFlat(interp, OBJ_AT_DEPTH(numIndices), numIndices, &OBJ_AT_DEPTH(numIndices - 1)); if (!objResultPtr) { TRACE_ERROR(interp); goto gotError; } /* * Set result. */ TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_V(5, opnd, -1); case INST_LSET_FLAT: /* * Lset with 3, 5, or more args. Get the number of index args. */ opnd = TclGetUInt4AtPtr(pc + 1); numIndices = opnd - 2; TRACE(("%d => ", opnd)); /* * Get the old value of variable, and remove the stack ref. This is * safe because the variable still references the object; the ref * count will never go zero here - we can use the smaller macro * Tcl_DecrRefCount. */ valuePtr = POP_OBJECT(); Tcl_DecrRefCount(valuePtr); /* This one should be done here */ /* * Compute the new variable value. */ objResultPtr = TclLsetFlat(interp, valuePtr, numIndices, &OBJ_AT_DEPTH(numIndices), OBJ_AT_TOS); if (!objResultPtr) { TRACE_ERROR(interp); goto gotError; } /* * Set result. */ TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_V(5, numIndices+1, -1); case INST_LSET_LIST: /* 'lset' with 4 args */ /* * Get the old value of variable, and remove the stack ref. This is * safe because the variable still references the object; the ref * count will never go zero here - we can use the smaller macro * Tcl_DecrRefCount. */ objPtr = POP_OBJECT(); Tcl_DecrRefCount(objPtr); /* This one should be done here. */ /* * Get the new element value, and the index list. */ valuePtr = OBJ_AT_TOS; value2Ptr = OBJ_UNDER_TOS; TRACE(("\"%.30s\" \"%.30s\" \"%.30s\" => ", O2S(value2Ptr), O2S(valuePtr), O2S(objPtr))); /* * Compute the new variable value. */ objResultPtr = TclLsetList(interp, objPtr, value2Ptr, valuePtr); if (!objResultPtr) { TRACE_ERROR(interp); goto gotError; } /* * Set result. */ TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, -1); case INST_LIST_RANGE_IMM: /* lrange with objc==4 and both indices in * bytecode stream */ /* * Pop the list and get the indices. */ valuePtr = OBJ_AT_TOS; fromIdx = TclGetInt4AtPtr(pc+1); toIdx = TclGetInt4AtPtr(pc+5); TRACE(("\"%.30s\" %d %d => ", O2S(valuePtr), TclGetInt4AtPtr(pc+1), TclGetInt4AtPtr(pc+5))); /* * Get the contents of the list, making sure that it really is a list * in the process. */ if (TclListObjGetElements(interp, valuePtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } /* * Skip a lot of work if we're about to throw the result away (common * with uses of [lassign]). */ #ifndef TCL_COMPILE_DEBUG if (*(pc+9) == INST_POP) { NEXT_INST_F(10, 1, 0); } #endif /* * Adjust the indices for end-based handling. */ if (fromIdx < -1) { fromIdx += 1+objc; if (fromIdx < -1) { fromIdx = -1; } } else if (fromIdx > objc) { fromIdx = objc; } if (toIdx < -1) { toIdx += 1 + objc; if (toIdx < -1) { toIdx = -1; } } else if (toIdx > objc) { toIdx = objc; } /* * Check if we are referring to a valid, non-empty list range, and if * so, build the list of elements in that range. */ if (fromIdx<=toIdx && fromIdx=0) { if (fromIdx < 0) { fromIdx = 0; } if (toIdx >= objc) { toIdx = objc-1; } if (fromIdx == 0 && toIdx != objc-1 && !Tcl_IsShared(valuePtr)) { /* * BEWARE! This is looking inside the implementation of the * list type. */ List *listPtr = valuePtr->internalRep.twoPtrValue.ptr1; if (listPtr->refCount == 1) { for (index=toIdx+1; indexelemCount = toIdx+1; listPtr->canonicalFlag = 1; TclInvalidateStringRep(valuePtr); TRACE_APPEND(("%.30s\n", O2S(valuePtr))); NEXT_INST_F(9, 0, 0); } } objResultPtr = Tcl_NewListObj(toIdx-fromIdx+1, objv+fromIdx); } else { TclNewObj(objResultPtr); } TRACE_APPEND(("\"%.30s\"", O2S(objResultPtr))); NEXT_INST_F(9, 1, 1); case INST_LIST_IN: case INST_LIST_NOT_IN: /* Basic list containment operators. */ value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; s1 = TclGetStringFromObj(valuePtr, &s1len); TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr))); if (TclListObjLength(interp, value2Ptr, &length) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } match = 0; if (length > 0) { int i = 0; Tcl_Obj *o; /* * An empty list doesn't match anything. */ do { Tcl_ListObjIndex(NULL, value2Ptr, i, &o); if (o != NULL) { s2 = TclGetStringFromObj(o, &s2len); } else { s2 = ""; s2len = 0; } if (s1len == s2len) { match = (memcmp(s1, s2, s1len) == 0); } i++; } while (i < length && match == 0); } if (*pc == INST_LIST_NOT_IN) { match = !match; } TRACE_APPEND(("%d\n", match)); /* * Peep-hole optimisation: if you're about to jump, do jump from here. * We're saving the effort of pushing a boolean value only to pop it * for branching. */ JUMP_PEEPHOLE_F(match, 1, 2); case INST_LIST_CONCAT: value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr))); if (Tcl_IsShared(valuePtr)) { objResultPtr = Tcl_DuplicateObj(valuePtr); if (Tcl_ListObjAppendList(interp, objResultPtr, value2Ptr) != TCL_OK) { TRACE_ERROR(interp); TclDecrRefCount(objResultPtr); goto gotError; } TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } else { if (Tcl_ListObjAppendList(interp, valuePtr, value2Ptr) != TCL_OK){ TRACE_ERROR(interp); goto gotError; } TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); NEXT_INST_F(1, 1, 0); } /* * End of INST_LIST and related instructions. * ----------------------------------------------------------------- * Start of string-related instructions. */ case INST_STR_EQ: case INST_STR_NEQ: /* String (in)equality check */ case INST_STR_CMP: /* String compare. */ stringCompare: value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; if (valuePtr == value2Ptr) { match = 0; } else { /* * We only need to check (in)equality when we have equal length * strings. We can use memcmp in all (n)eq cases because we * don't need to worry about lexical LE/BE variance. */ typedef int (*memCmpFn_t)(const void*, const void*, size_t); memCmpFn_t memCmpFn; int checkEq = ((*pc == INST_EQ) || (*pc == INST_NEQ) || (*pc == INST_STR_EQ) || (*pc == INST_STR_NEQ)); if (TclIsPureByteArray(valuePtr) && TclIsPureByteArray(value2Ptr)) { s1 = (char *) Tcl_GetByteArrayFromObj(valuePtr, &s1len); s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len); memCmpFn = memcmp; } else if ((valuePtr->typePtr == &tclStringType) && (value2Ptr->typePtr == &tclStringType)) { /* * Do a unicode-specific comparison if both of the args are of * String type. If the char length == byte length, we can do a * memcmp. In benchmark testing this proved the most efficient * check between the unicode and string comparison operations. */ s1len = Tcl_GetCharLength(valuePtr); s2len = Tcl_GetCharLength(value2Ptr); if ((s1len == valuePtr->length) && (valuePtr->bytes != NULL) && (s2len == value2Ptr->length) && (value2Ptr->bytes != NULL)) { s1 = valuePtr->bytes; s2 = value2Ptr->bytes; memCmpFn = memcmp; } else { s1 = (char *) Tcl_GetUnicode(valuePtr); s2 = (char *) Tcl_GetUnicode(value2Ptr); if ( #ifdef WORDS_BIGENDIAN 1 #else checkEq #endif ) { memCmpFn = memcmp; s1len *= sizeof(Tcl_UniChar); s2len *= sizeof(Tcl_UniChar); } else { memCmpFn = (memCmpFn_t) Tcl_UniCharNcmp; } } } else { /* * strcmp can't do a simple memcmp in order to handle the * special Tcl \xC0\x80 null encoding for utf-8. */ s1 = TclGetStringFromObj(valuePtr, &s1len); s2 = TclGetStringFromObj(value2Ptr, &s2len); if (checkEq) { memCmpFn = memcmp; } else { memCmpFn = (memCmpFn_t) TclpUtfNcmp2; } } if (checkEq && (s1len != s2len)) { match = 1; } else { /* * The comparison function should compare up to the minimum * byte length only. */ match = memCmpFn(s1, s2, (size_t) ((s1len < s2len) ? s1len : s2len)); if (match == 0) { match = s1len - s2len; } } } /* * Make sure only -1,0,1 is returned * TODO: consider peephole opt. */ if (*pc != INST_STR_CMP) { /* * Take care of the opcodes that goto'ed into here. */ switch (*pc) { case INST_STR_EQ: case INST_EQ: match = (match == 0); break; case INST_STR_NEQ: case INST_NEQ: match = (match != 0); break; case INST_LT: match = (match < 0); break; case INST_GT: match = (match > 0); break; case INST_LE: match = (match <= 0); break; case INST_GE: match = (match >= 0); break; } } TRACE(("\"%.20s\" \"%.20s\" => %d\n", O2S(valuePtr), O2S(value2Ptr), (match < 0 ? -1 : match > 0 ? 1 : 0))); JUMP_PEEPHOLE_F(match, 1, 2); case INST_STR_LEN: valuePtr = OBJ_AT_TOS; length = Tcl_GetCharLength(valuePtr); TclNewIntObj(objResultPtr, length); TRACE(("\"%.20s\" => %d\n", O2S(valuePtr), length)); NEXT_INST_F(1, 1, 1); case INST_STR_UPPER: valuePtr = OBJ_AT_TOS; TRACE(("\"%.20s\" => ", O2S(valuePtr))); if (Tcl_IsShared(valuePtr)) { s1 = TclGetStringFromObj(valuePtr, &length); TclNewStringObj(objResultPtr, s1, length); length = Tcl_UtfToUpper(TclGetString(objResultPtr)); Tcl_SetObjLength(objResultPtr, length); TRACE_APPEND(("\"%.20s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } else { length = Tcl_UtfToUpper(TclGetString(valuePtr)); Tcl_SetObjLength(valuePtr, length); TclFreeIntRep(valuePtr); TRACE_APPEND(("\"%.20s\"\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } case INST_STR_LOWER: valuePtr = OBJ_AT_TOS; TRACE(("\"%.20s\" => ", O2S(valuePtr))); if (Tcl_IsShared(valuePtr)) { s1 = TclGetStringFromObj(valuePtr, &length); TclNewStringObj(objResultPtr, s1, length); length = Tcl_UtfToLower(TclGetString(objResultPtr)); Tcl_SetObjLength(objResultPtr, length); TRACE_APPEND(("\"%.20s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } else { length = Tcl_UtfToLower(TclGetString(valuePtr)); Tcl_SetObjLength(valuePtr, length); TclFreeIntRep(valuePtr); TRACE_APPEND(("\"%.20s\"\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } case INST_STR_TITLE: valuePtr = OBJ_AT_TOS; TRACE(("\"%.20s\" => ", O2S(valuePtr))); if (Tcl_IsShared(valuePtr)) { s1 = TclGetStringFromObj(valuePtr, &length); TclNewStringObj(objResultPtr, s1, length); length = Tcl_UtfToTitle(TclGetString(objResultPtr)); Tcl_SetObjLength(objResultPtr, length); TRACE_APPEND(("\"%.20s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } else { length = Tcl_UtfToTitle(TclGetString(valuePtr)); Tcl_SetObjLength(valuePtr, length); TclFreeIntRep(valuePtr); TRACE_APPEND(("\"%.20s\"\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } case INST_STR_INDEX: value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; TRACE(("\"%.20s\" %.20s => ", O2S(valuePtr), O2S(value2Ptr))); /* * Get char length to calulate what 'end' means. */ length = Tcl_GetCharLength(valuePtr); if (TclGetIntForIndexM(interp, value2Ptr, length-1, &index)!=TCL_OK) { TRACE_ERROR(interp); goto gotError; } if ((index < 0) || (index >= length)) { TclNewObj(objResultPtr); } else if (TclIsPureByteArray(valuePtr)) { objResultPtr = Tcl_NewByteArrayObj( Tcl_GetByteArrayFromObj(valuePtr, NULL)+index, 1); } else if (valuePtr->bytes && length == valuePtr->length) { objResultPtr = Tcl_NewStringObj((const char *) valuePtr->bytes+index, 1); } else { char buf[TCL_UTF_MAX]; Tcl_UniChar ch = Tcl_GetUniChar(valuePtr, index); /* * This could be: Tcl_NewUnicodeObj((const Tcl_UniChar *)&ch, 1) * but creating the object as a string seems to be faster in * practical use. */ length = Tcl_UniCharToUtf(ch, buf); objResultPtr = Tcl_NewStringObj(buf, length); } TRACE_APPEND(("\"%s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); case INST_STR_RANGE: TRACE(("\"%.20s\" %.20s %.20s =>", O2S(OBJ_AT_DEPTH(2)), O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS))); length = Tcl_GetCharLength(OBJ_AT_DEPTH(2)) - 1; if (TclGetIntForIndexM(interp, OBJ_UNDER_TOS, length, &fromIdx) != TCL_OK || TclGetIntForIndexM(interp, OBJ_AT_TOS, length, &toIdx) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } if (fromIdx < 0) { fromIdx = 0; } if (toIdx >= length) { toIdx = length; } if (toIdx >= fromIdx) { objResultPtr = Tcl_GetRange(OBJ_AT_DEPTH(2), fromIdx, toIdx); } else { TclNewObj(objResultPtr); } TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_V(1, 3, 1); case INST_STR_RANGE_IMM: valuePtr = OBJ_AT_TOS; fromIdx = TclGetInt4AtPtr(pc+1); toIdx = TclGetInt4AtPtr(pc+5); length = Tcl_GetCharLength(valuePtr); TRACE(("\"%.20s\" %d %d => ", O2S(valuePtr), fromIdx, toIdx)); /* * Adjust indices for end-based indexing. */ if (fromIdx < -1) { fromIdx += 1 + length; if (fromIdx < 0) { fromIdx = 0; } } else if (fromIdx >= length) { fromIdx = length; } if (toIdx < -1) { toIdx += 1 + length; } else if (toIdx >= length) { toIdx = length - 1; } /* * Check if we can do a sane substring. */ if (fromIdx <= toIdx) { objResultPtr = Tcl_GetRange(valuePtr, fromIdx, toIdx); } else { TclNewObj(objResultPtr); } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_F(9, 1, 1); { Tcl_UniChar *ustring1, *ustring2, *ustring3, *end, *p; int length3; Tcl_Obj *value3Ptr; case INST_STR_REPLACE: value3Ptr = POP_OBJECT(); valuePtr = OBJ_AT_DEPTH(2); length = Tcl_GetCharLength(valuePtr) - 1; TRACE(("\"%.20s\" %s %s \"%.20s\" => ", O2S(valuePtr), O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), O2S(value3Ptr))); if (TclGetIntForIndexM(interp, OBJ_UNDER_TOS, length, &fromIdx) != TCL_OK || TclGetIntForIndexM(interp, OBJ_AT_TOS, length, &toIdx) != TCL_OK) { TclDecrRefCount(value3Ptr); TRACE_ERROR(interp); goto gotError; } TclDecrRefCount(OBJ_AT_TOS); (void) POP_OBJECT(); TclDecrRefCount(OBJ_AT_TOS); (void) POP_OBJECT(); if (fromIdx < 0) { fromIdx = 0; } if (fromIdx > toIdx || fromIdx > length) { TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); TclDecrRefCount(value3Ptr); NEXT_INST_F(1, 0, 0); } if (toIdx > length) { toIdx = length; } if (fromIdx == 0 && toIdx == length) { TclDecrRefCount(OBJ_AT_TOS); OBJ_AT_TOS = value3Ptr; TRACE_APPEND(("\"%.30s\"\n", O2S(value3Ptr))); NEXT_INST_F(1, 0, 0); } length3 = Tcl_GetCharLength(value3Ptr); /* * Remove substring. In-place. */ if (length3 == 0 && !Tcl_IsShared(valuePtr) && toIdx == length) { TclDecrRefCount(value3Ptr); Tcl_SetObjLength(valuePtr, fromIdx); TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } /* * See if we can splice in place. This happens when the number of * characters being replaced is the same as the number of characters * in the string to be inserted. */ if (length3 - 1 == toIdx - fromIdx) { unsigned char *bytes1, *bytes2; if (Tcl_IsShared(valuePtr)) { objResultPtr = Tcl_DuplicateObj(valuePtr); if (TclIsPureByteArray(objResultPtr) && TclIsPureByteArray(value3Ptr)) { bytes1 = Tcl_GetByteArrayFromObj(objResultPtr, NULL); bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL); memcpy(bytes1 + fromIdx, bytes2, length3); } else { ustring1 = Tcl_GetUnicodeFromObj(objResultPtr, NULL); ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL); memcpy(ustring1 + fromIdx, ustring2, length3 * sizeof(Tcl_UniChar)); /* * Magic! Flush the info in the string internal rep that * refers to the about-to-be-invalidated UTF-8 rep. This * sets the 'allocated' field of the String structure to 0 * to indicate that a new buffer needs to be allocated. * This is safe; we know we've got a tclStringTypePtr set * at this point (post Tcl_GetUnicodeFromObj). */ ((int *) objResultPtr->internalRep.twoPtrValue.ptr1)[1] = 0; } Tcl_InvalidateStringRep(objResultPtr); TclDecrRefCount(value3Ptr); TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } else { if (TclIsPureByteArray(valuePtr) && TclIsPureByteArray(value3Ptr)) { bytes1 = Tcl_GetByteArrayFromObj(valuePtr, NULL); bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL); memcpy(bytes1 + fromIdx, bytes2, length3); } else { ustring1 = Tcl_GetUnicodeFromObj(valuePtr, NULL); ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL); memcpy(ustring1 + fromIdx, ustring2, length3 * sizeof(Tcl_UniChar)); /* * Magic! Flush the info in the string internal rep that * refers to the about-to-be-invalidated UTF-8 rep. This * sets the 'allocated' field of the String structure to 0 * to indicate that a new buffer needs to be allocated. * This is safe; we know we've got a tclStringTypePtr set * at this point (post Tcl_GetUnicodeFromObj). */ ((int *) objResultPtr->internalRep.twoPtrValue.ptr1)[1] = 0; } Tcl_InvalidateStringRep(valuePtr); TclDecrRefCount(value3Ptr); TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } } /* * Get the unicode representation; this is where we guarantee to lose * bytearrays. */ ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &length); length--; /* * Remove substring using copying. */ if (length3 == 0) { if (fromIdx > 0) { objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx); if (toIdx < length) { Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1, length - toIdx); } } else { objResultPtr = Tcl_NewUnicodeObj(ustring1 + toIdx + 1, length - toIdx); } TclDecrRefCount(value3Ptr); TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } /* * Splice string pieces by full copying. */ if (fromIdx > 0) { objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx); Tcl_AppendObjToObj(objResultPtr, value3Ptr); if (toIdx < length) { Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1, length - toIdx); } } else if (Tcl_IsShared(value3Ptr)) { objResultPtr = Tcl_DuplicateObj(value3Ptr); if (toIdx < length) { Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1, length - toIdx); } } else { /* * Be careful with splicing the stack in this case; we have a * refCount:1 object in value3Ptr and we want to append to it and * make it be the refCount:1 object at the top of the stack * afterwards. [Bug 82e7f67325] */ if (toIdx < length) { Tcl_AppendUnicodeToObj(value3Ptr, ustring1 + toIdx + 1, length - toIdx); } TRACE_APPEND(("\"%.30s\"\n", O2S(value3Ptr))); TclDecrRefCount(valuePtr); OBJ_AT_TOS = value3Ptr; /* Tricky! */ NEXT_INST_F(1, 0, 0); } TclDecrRefCount(value3Ptr); TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); case INST_STR_MAP: valuePtr = OBJ_AT_TOS; /* "Main" string. */ value3Ptr = OBJ_UNDER_TOS; /* "Target" string. */ value2Ptr = OBJ_AT_DEPTH(2); /* "Source" string. */ if (value3Ptr == value2Ptr) { objResultPtr = valuePtr; goto doneStringMap; } else if (valuePtr == value2Ptr) { objResultPtr = value3Ptr; goto doneStringMap; } ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &length); if (length == 0) { objResultPtr = valuePtr; goto doneStringMap; } ustring2 = Tcl_GetUnicodeFromObj(value2Ptr, &length2); if (length2 > length || length2 == 0) { objResultPtr = valuePtr; goto doneStringMap; } else if (length2 == length) { if (memcmp(ustring1, ustring2, sizeof(Tcl_UniChar) * length)) { objResultPtr = valuePtr; } else { objResultPtr = value3Ptr; } goto doneStringMap; } ustring3 = Tcl_GetUnicodeFromObj(value3Ptr, &length3); objResultPtr = Tcl_NewUnicodeObj(ustring1, 0); p = ustring1; end = ustring1 + length; for (; ustring1 < end; ustring1++) { if ((*ustring1 == *ustring2) && (length2==1 || memcmp(ustring1, ustring2, sizeof(Tcl_UniChar) * length2) == 0)) { if (p != ustring1) { Tcl_AppendUnicodeToObj(objResultPtr, p, ustring1-p); p = ustring1 + length2; } else { p += length2; } ustring1 = p - 1; Tcl_AppendUnicodeToObj(objResultPtr, ustring3, length3); } } if (p != ustring1) { /* * Put the rest of the unmapped chars onto result. */ Tcl_AppendUnicodeToObj(objResultPtr, p, ustring1 - p); } doneStringMap: TRACE_WITH_OBJ(("%.20s %.20s %.20s => ", O2S(value2Ptr), O2S(value3Ptr), O2S(valuePtr)), objResultPtr); NEXT_INST_V(1, 3, 1); case INST_STR_FIND: ustring1 = Tcl_GetUnicodeFromObj(OBJ_AT_TOS, &length); /* Haystack */ ustring2 = Tcl_GetUnicodeFromObj(OBJ_UNDER_TOS, &length2);/* Needle */ match = -1; if (length2 > 0 && length2 <= length) { end = ustring1 + length - length2 + 1; for (p=ustring1 ; p %d\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match)); TclNewIntObj(objResultPtr, match); NEXT_INST_F(1, 2, 1); case INST_STR_FIND_LAST: ustring1 = Tcl_GetUnicodeFromObj(OBJ_AT_TOS, &length); /* Haystack */ ustring2 = Tcl_GetUnicodeFromObj(OBJ_UNDER_TOS, &length2);/* Needle */ match = -1; if (length2 > 0 && length2 <= length) { for (p=ustring1+length-length2 ; p>=ustring1 ; p--) { if ((*p == *ustring2) && memcmp(ustring2,p,sizeof(Tcl_UniChar)*length2) == 0) { match = p - ustring1; break; } } } TRACE(("%.20s %.20s => %d\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match)); TclNewIntObj(objResultPtr, match); NEXT_INST_F(1, 2, 1); case INST_STR_CLASS: opnd = TclGetInt1AtPtr(pc+1); valuePtr = OBJ_AT_TOS; TRACE(("%s \"%.30s\" => ", tclStringClassTable[opnd].name, O2S(valuePtr))); ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &length); match = 1; if (length > 0) { end = ustring1 + length; for (p=ustring1 ; ptypePtr == &tclStringType) || (value2Ptr->typePtr == &tclStringType)) { Tcl_UniChar *ustring1, *ustring2; ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &length); ustring2 = Tcl_GetUnicodeFromObj(value2Ptr, &length2); match = TclUniCharMatch(ustring1, length, ustring2, length2, nocase); } else if (TclIsPureByteArray(valuePtr) && !nocase) { unsigned char *bytes1, *bytes2; bytes1 = Tcl_GetByteArrayFromObj(valuePtr, &length); bytes2 = Tcl_GetByteArrayFromObj(value2Ptr, &length2); match = TclByteArrayMatch(bytes1, length, bytes2, length2, 0); } else { match = Tcl_StringCaseMatch(TclGetString(valuePtr), TclGetString(value2Ptr), nocase); } /* * Reuse value2Ptr object already on stack if possible. Adjustment is * 2 due to the nocase byte */ TRACE(("%.20s %.20s => %d\n", O2S(valuePtr), O2S(value2Ptr), match)); /* * Peep-hole optimisation: if you're about to jump, do jump from here. */ JUMP_PEEPHOLE_F(match, 2, 2); { const char *string1, *string2; int trim1, trim2; case INST_STR_TRIM_LEFT: valuePtr = OBJ_UNDER_TOS; /* String */ value2Ptr = OBJ_AT_TOS; /* TrimSet */ string2 = TclGetStringFromObj(value2Ptr, &length2); string1 = TclGetStringFromObj(valuePtr, &length); trim1 = TclTrimLeft(string1, length, string2, length2); trim2 = 0; goto createTrimmedString; case INST_STR_TRIM_RIGHT: valuePtr = OBJ_UNDER_TOS; /* String */ value2Ptr = OBJ_AT_TOS; /* TrimSet */ string2 = TclGetStringFromObj(value2Ptr, &length2); string1 = TclGetStringFromObj(valuePtr, &length); trim2 = TclTrimRight(string1, length, string2, length2); trim1 = 0; goto createTrimmedString; case INST_STR_TRIM: valuePtr = OBJ_UNDER_TOS; /* String */ value2Ptr = OBJ_AT_TOS; /* TrimSet */ string2 = TclGetStringFromObj(value2Ptr, &length2); string1 = TclGetStringFromObj(valuePtr, &length); trim1 = TclTrimLeft(string1, length, string2, length2); if (trim1 < length) { trim2 = TclTrimRight(string1, length, string2, length2); } else { trim2 = 0; } createTrimmedString: /* * Careful here; trim set often contains non-ASCII characters so we * take care when printing. [Bug 971cb4f1db] */ #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { TRACE(("\"%.30s\" ", O2S(valuePtr))); TclPrintObject(stdout, value2Ptr, 30); printf(" => "); } #endif if (trim1 == 0 && trim2 == 0) { #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { TclPrintObject(stdout, valuePtr, 30); printf("\n"); } #endif NEXT_INST_F(1, 1, 0); } else { objResultPtr = Tcl_NewStringObj(string1+trim1, length-trim1-trim2); #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { TclPrintObject(stdout, objResultPtr, 30); printf("\n"); } #endif NEXT_INST_F(1, 2, 1); } } case INST_REGEXP: cflags = TclGetInt1AtPtr(pc+1); /* RE compile flages like NOCASE */ valuePtr = OBJ_AT_TOS; /* String */ value2Ptr = OBJ_UNDER_TOS; /* Pattern */ TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr))); /* * Compile and match the regular expression. */ { Tcl_RegExp regExpr = Tcl_GetRegExpFromObj(interp, value2Ptr, cflags); if (regExpr == NULL) { TRACE_ERROR(interp); goto gotError; } match = Tcl_RegExpExecObj(interp, regExpr, valuePtr, 0, 0, 0); if (match < 0) { TRACE_ERROR(interp); goto gotError; } } TRACE_APPEND(("%d\n", match)); /* * Peep-hole optimisation: if you're about to jump, do jump from here. * Adjustment is 2 due to the nocase byte. */ JUMP_PEEPHOLE_F(match, 2, 2); } /* * End of string-related instructions. * ----------------------------------------------------------------- * Start of numeric operator instructions. */ { ClientData ptr1, ptr2; int type1, type2; long l1, l2, lResult; case INST_NUM_TYPE: if (GetNumberFromObj(NULL, OBJ_AT_TOS, &ptr1, &type1) != TCL_OK) { type1 = 0; } else if (type1 == TCL_NUMBER_LONG) { /* value is between LONG_MIN and LONG_MAX */ /* [string is integer] is -UINT_MAX to UINT_MAX range */ int i; if (Tcl_GetIntFromObj(NULL, OBJ_AT_TOS, &i) != TCL_OK) { type1 = TCL_NUMBER_WIDE; } #ifndef TCL_WIDE_INT_IS_LONG } else if (type1 == TCL_NUMBER_WIDE) { /* value is between WIDE_MIN and WIDE_MAX */ /* [string is wideinteger] is -UWIDE_MAX to UWIDE_MAX range */ int i; if (Tcl_GetIntFromObj(NULL, OBJ_AT_TOS, &i) == TCL_OK) { type1 = TCL_NUMBER_LONG; } #endif } else if (type1 == TCL_NUMBER_BIG) { /* value is an integer outside the WIDE_MIN to WIDE_MAX range */ /* [string is wideinteger] is -UWIDE_MAX to UWIDE_MAX range */ Tcl_WideInt w; if (Tcl_GetWideIntFromObj(NULL, OBJ_AT_TOS, &w) == TCL_OK) { type1 = TCL_NUMBER_WIDE; } } TclNewIntObj(objResultPtr, type1); TRACE(("\"%.20s\" => %d\n", O2S(OBJ_AT_TOS), type1)); NEXT_INST_F(1, 1, 1); case INST_EQ: case INST_NEQ: case INST_LT: case INST_GT: case INST_LE: case INST_GE: { int iResult = 0, compare = 0; value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) { /* * At least one non-numeric argument - compare as strings. */ goto stringCompare; } if (type1 == TCL_NUMBER_NAN) { /* * NaN first arg: NaN != to everything, other compares are false. */ iResult = (*pc == INST_NEQ); goto foundResult; } if (valuePtr == value2Ptr) { compare = MP_EQ; goto convertComparison; } if (GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) { /* * At least one non-numeric argument - compare as strings. */ goto stringCompare; } if (type2 == TCL_NUMBER_NAN) { /* * NaN 2nd arg: NaN != to everything, other compares are false. */ iResult = (*pc == INST_NEQ); goto foundResult; } if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { l1 = *((const long *)ptr1); l2 = *((const long *)ptr2); compare = (l1 < l2) ? MP_LT : ((l1 > l2) ? MP_GT : MP_EQ); } else { compare = TclCompareTwoNumbers(valuePtr, value2Ptr); } /* * Turn comparison outcome into appropriate result for opcode. */ convertComparison: switch (*pc) { case INST_EQ: iResult = (compare == MP_EQ); break; case INST_NEQ: iResult = (compare != MP_EQ); break; case INST_LT: iResult = (compare == MP_LT); break; case INST_GT: iResult = (compare == MP_GT); break; case INST_LE: iResult = (compare != MP_GT); break; case INST_GE: iResult = (compare != MP_LT); break; } /* * Peep-hole optimisation: if you're about to jump, do jump from here. */ foundResult: TRACE(("\"%.20s\" \"%.20s\" => %d\n", O2S(valuePtr), O2S(value2Ptr), iResult)); JUMP_PEEPHOLE_F(iResult, 1, 2); } case INST_MOD: case INST_LSHIFT: case INST_RSHIFT: case INST_BITOR: case INST_BITXOR: case INST_BITAND: value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) || (type1==TCL_NUMBER_DOUBLE) || (type1==TCL_NUMBER_NAN)) { TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", O2S(valuePtr), O2S(value2Ptr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, pc, valuePtr); CACHE_STACK_INFO(); goto gotError; } if ((GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) || (type2==TCL_NUMBER_DOUBLE) || (type2==TCL_NUMBER_NAN)) { TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n", O2S(valuePtr), O2S(value2Ptr), (value2Ptr->typePtr? value2Ptr->typePtr->name : "null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, pc, value2Ptr); CACHE_STACK_INFO(); goto gotError; } /* * Check for common, simple case. */ if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { l1 = *((const long *)ptr1); l2 = *((const long *)ptr2); switch (*pc) { case INST_MOD: if (l2 == 0) { TRACE(("%s %s => DIVIDE BY ZERO\n", O2S(valuePtr), O2S(value2Ptr))); goto divideByZero; } else if ((l2 == 1) || (l2 == -1)) { /* * Div. by |1| always yields remainder of 0. */ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); objResultPtr = TCONST(0); TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } else if (l1 == 0) { /* * 0 % (non-zero) always yields remainder of 0. */ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); objResultPtr = TCONST(0); TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } else { lResult = l1 / l2; /* * Force Tcl's integer division rules. * TODO: examine for logic simplification */ if ((lResult < 0 || (lResult == 0 && ((l1 < 0 && l2 > 0) || (l1 > 0 && l2 < 0)))) && (lResult * l2 != l1)) { lResult -= 1; } lResult = l1 - l2*lResult; goto longResultOfArithmetic; } case INST_RSHIFT: if (l2 < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); #ifdef ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", "domain error: argument not in valid range", NULL); CACHE_STACK_INFO(); #endif /* ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR */ goto gotError; } else if (l1 == 0) { TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); objResultPtr = TCONST(0); TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } else { /* * Quickly force large right shifts to 0 or -1. */ if (l2 >= (long)(CHAR_BIT*sizeof(long))) { /* * We assume that INT_MAX is much larger than the * number of bits in a long. This is a pretty safe * assumption, given that the former is usually around * 4e9 and the latter 32 or 64... */ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); if (l1 > 0L) { objResultPtr = TCONST(0); } else { TclNewIntObj(objResultPtr, -1); } TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } /* * Handle shifts within the native long range. */ lResult = l1 >> ((int) l2); goto longResultOfArithmetic; } case INST_LSHIFT: if (l2 < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); #ifdef ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", "domain error: argument not in valid range", NULL); CACHE_STACK_INFO(); #endif /* ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR */ goto gotError; } else if (l1 == 0) { TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); objResultPtr = TCONST(0); TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } else if (l2 > (long) INT_MAX) { /* * Technically, we could hold the value (1 << (INT_MAX+1)) * in an mp_int, but since we're using mp_mul_2d() to do * the work, and it takes only an int argument, that's a * good place to draw the line. */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "integer value too large to represent", -1)); #ifdef ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", "integer value too large to represent", NULL); CACHE_STACK_INFO(); #endif /* ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR */ goto gotError; } else { int shift = (int) l2; /* * Handle shifts within the native long range. */ if ((size_t) shift < CHAR_BIT*sizeof(long) && (l1 != 0) && !((l1>0 ? l1 : ~l1) & -(1L<<(CHAR_BIT*sizeof(long) - 1 - shift)))) { lResult = l1 << shift; goto longResultOfArithmetic; } } /* * Too large; need to use the broken-out function. */ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); break; case INST_BITAND: lResult = l1 & l2; goto longResultOfArithmetic; case INST_BITOR: lResult = l1 | l2; goto longResultOfArithmetic; case INST_BITXOR: lResult = l1 ^ l2; longResultOfArithmetic: TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); if (Tcl_IsShared(valuePtr)) { TclNewLongObj(objResultPtr, lResult); TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } TclSetLongObj(valuePtr, lResult); TRACE(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 1, 0); } } /* * DO NOT MERGE THIS WITH THE EQUIVALENT SECTION LATER! That would * encourage the compiler to inline ExecuteExtendedBinaryMathOp, which * is highly undesirable due to the overall impact on size. */ TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); objResultPtr = ExecuteExtendedBinaryMathOp(interp, *pc, &TCONST(0), valuePtr, value2Ptr); if (objResultPtr == DIVIDED_BY_ZERO) { TRACE_APPEND(("DIVIDE BY ZERO\n")); goto divideByZero; } else if (objResultPtr == GENERAL_ARITHMETIC_ERROR) { TRACE_ERROR(interp); goto gotError; } else if (objResultPtr == NULL) { TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 1, 0); } else { TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } case INST_EXPON: case INST_ADD: case INST_SUB: case INST_DIV: case INST_MULT: value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) || IsErroringNaNType(type1)) { TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", O2S(value2Ptr), O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name: "null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, pc, valuePtr); CACHE_STACK_INFO(); goto gotError; } #ifdef ACCEPT_NAN if (type1 == TCL_NUMBER_NAN) { /* * NaN first argument -> result is also NaN. */ NEXT_INST_F(1, 1, 0); } #endif if ((GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) || IsErroringNaNType(type2)) { TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n", O2S(value2Ptr), O2S(valuePtr), (value2Ptr->typePtr? value2Ptr->typePtr->name: "null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, pc, value2Ptr); CACHE_STACK_INFO(); goto gotError; } #ifdef ACCEPT_NAN if (type2 == TCL_NUMBER_NAN) { /* * NaN second argument -> result is also NaN. */ objResultPtr = value2Ptr; NEXT_INST_F(1, 2, 1); } #endif /* * Handle (long,long) arithmetic as best we can without going out to * an external function. */ if ((type1 == TCL_NUMBER_LONG) && (type2 == TCL_NUMBER_LONG)) { Tcl_WideInt w1, w2, wResult; l1 = *((const long *)ptr1); l2 = *((const long *)ptr2); switch (*pc) { case INST_ADD: w1 = (Tcl_WideInt) l1; w2 = (Tcl_WideInt) l2; wResult = w1 + w2; #ifdef TCL_WIDE_INT_IS_LONG /* * Check for overflow. */ if (Overflowing(w1, w2, wResult)) { goto overflow; } #endif goto wideResultOfArithmetic; case INST_SUB: w1 = (Tcl_WideInt) l1; w2 = (Tcl_WideInt) l2; wResult = w1 - w2; #ifdef TCL_WIDE_INT_IS_LONG /* * Must check for overflow. The macro tests for overflows in * sums by looking at the sign bits. As we have a subtraction * here, we are adding -w2. As -w2 could in turn overflow, we * test with ~w2 instead: it has the opposite sign bit to w2 * so it does the job. Note that the only "bad" case (w2==0) * is irrelevant for this macro, as in that case w1 and * wResult have the same sign and there is no overflow anyway. */ if (Overflowing(w1, ~w2, wResult)) { goto overflow; } #endif wideResultOfArithmetic: TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); if (Tcl_IsShared(valuePtr)) { objResultPtr = Tcl_NewWideIntObj(wResult); TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } Tcl_SetWideIntObj(valuePtr, wResult); TRACE(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 1, 0); case INST_DIV: if (l2 == 0) { TRACE(("%s %s => DIVIDE BY ZERO\n", O2S(valuePtr), O2S(value2Ptr))); goto divideByZero; } else if ((l1 == LONG_MIN) && (l2 == -1)) { /* * Can't represent (-LONG_MIN) as a long. */ goto overflow; } lResult = l1 / l2; /* * Force Tcl's integer division rules. * TODO: examine for logic simplification */ if (((lResult < 0) || ((lResult == 0) && ((l1 < 0 && l2 > 0) || (l1 > 0 && l2 < 0)))) && ((lResult * l2) != l1)) { lResult -= 1; } goto longResultOfArithmetic; case INST_MULT: if (((sizeof(long) >= 2*sizeof(int)) && (l1 <= INT_MAX) && (l1 >= INT_MIN) && (l2 <= INT_MAX) && (l2 >= INT_MIN)) || ((sizeof(long) >= 2*sizeof(short)) && (l1 <= SHRT_MAX) && (l1 >= SHRT_MIN) && (l2 <= SHRT_MAX) && (l2 >= SHRT_MIN))) { lResult = l1 * l2; goto longResultOfArithmetic; } } /* * Fall through with INST_EXPON, INST_DIV and large multiplies. */ } overflow: TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); objResultPtr = ExecuteExtendedBinaryMathOp(interp, *pc, &TCONST(0), valuePtr, value2Ptr); if (objResultPtr == DIVIDED_BY_ZERO) { TRACE_APPEND(("DIVIDE BY ZERO\n")); goto divideByZero; } else if (objResultPtr == EXPONENT_OF_ZERO) { TRACE_APPEND(("EXPONENT OF ZERO\n")); goto exponOfZero; } else if (objResultPtr == GENERAL_ARITHMETIC_ERROR) { TRACE_ERROR(interp); goto gotError; } else if (objResultPtr == NULL) { TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 1, 0); } else { TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } case INST_LNOT: { int b; valuePtr = OBJ_AT_TOS; /* TODO - check claim that taking address of b harms performance */ /* TODO - consider optimization search for constants */ if (TclGetBooleanFromObj(NULL, valuePtr, &b) != TCL_OK) { TRACE(("\"%.20s\" => ERROR: illegal type %s\n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, pc, valuePtr); CACHE_STACK_INFO(); goto gotError; } /* TODO: Consider peephole opt. */ objResultPtr = TCONST(!b); TRACE_WITH_OBJ(("%s => ", O2S(valuePtr)), objResultPtr); NEXT_INST_F(1, 1, 1); } case INST_BITNOT: valuePtr = OBJ_AT_TOS; TRACE(("\"%.20s\" => ", O2S(valuePtr))); if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) || (type1==TCL_NUMBER_NAN) || (type1==TCL_NUMBER_DOUBLE)) { /* * ... ~$NonInteger => raise an error. */ TRACE_APPEND(("ERROR: illegal type %s\n", (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, pc, valuePtr); CACHE_STACK_INFO(); goto gotError; } if (type1 == TCL_NUMBER_LONG) { l1 = *((const long *) ptr1); if (Tcl_IsShared(valuePtr)) { TclNewLongObj(objResultPtr, ~l1); TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } TclSetLongObj(valuePtr, ~l1); TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } objResultPtr = ExecuteExtendedUnaryMathOp(*pc, valuePtr); if (objResultPtr != NULL) { TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } else { TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } case INST_UMINUS: valuePtr = OBJ_AT_TOS; TRACE(("\"%.20s\" => ", O2S(valuePtr))); if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) || IsErroringNaNType(type1)) { TRACE_APPEND(("ERROR: illegal type %s \n", (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, pc, valuePtr); CACHE_STACK_INFO(); goto gotError; } switch (type1) { case TCL_NUMBER_NAN: /* -NaN => NaN */ TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); case TCL_NUMBER_LONG: l1 = *((const long *) ptr1); if (l1 != LONG_MIN) { if (Tcl_IsShared(valuePtr)) { TclNewLongObj(objResultPtr, -l1); TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } TclSetLongObj(valuePtr, -l1); TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } /* FALLTHROUGH */ } objResultPtr = ExecuteExtendedUnaryMathOp(*pc, valuePtr); if (objResultPtr != NULL) { TRACE_APPEND(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); } else { TRACE_APPEND(("%s\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } case INST_UPLUS: case INST_TRY_CVT_TO_NUMERIC: /* * Try to convert the topmost stack object to numeric object. This is * done in order to support [expr]'s policy of interpreting operands * if at all possible as numbers first, then strings. */ valuePtr = OBJ_AT_TOS; TRACE(("\"%.20s\" => ", O2S(valuePtr))); if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) { if (*pc == INST_UPLUS) { /* * ... +$NonNumeric => raise an error. */ TRACE_APPEND(("ERROR: illegal type %s\n", (valuePtr->typePtr? valuePtr->typePtr->name:"null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, pc, valuePtr); CACHE_STACK_INFO(); goto gotError; } /* ... TryConvertToNumeric($NonNumeric) is acceptable */ TRACE_APPEND(("not numeric\n")); NEXT_INST_F(1, 0, 0); } if (IsErroringNaNType(type1)) { if (*pc == INST_UPLUS) { /* * ... +$NonNumeric => raise an error. */ TRACE_APPEND(("ERROR: illegal type %s\n", (valuePtr->typePtr? valuePtr->typePtr->name:"null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, pc, valuePtr); CACHE_STACK_INFO(); } else { /* * Numeric conversion of NaN -> error. */ TRACE_APPEND(("ERROR: IEEE floating pt error\n")); DECACHE_STACK_INFO(); TclExprFloatError(interp, *((const double *) ptr1)); CACHE_STACK_INFO(); } goto gotError; } /* * Ensure that the numeric value has a string rep the same as the * formatted version of its internal rep. This is used, e.g., to make * sure that "expr {0001}" yields "1", not "0001". We implement this * by _discarding_ the string rep since we know it will be * regenerated, if needed later, by formatting the internal rep's * value. */ if (valuePtr->bytes == NULL) { TRACE_APPEND(("numeric, same Tcl_Obj\n")); NEXT_INST_F(1, 0, 0); } if (Tcl_IsShared(valuePtr)) { /* * Here we do some surgery within the Tcl_Obj internals. We want * to copy the intrep, but not the string, so we temporarily hide * the string so we do not copy it. */ char *savedString = valuePtr->bytes; valuePtr->bytes = NULL; objResultPtr = Tcl_DuplicateObj(valuePtr); valuePtr->bytes = savedString; TRACE_APPEND(("numeric, new Tcl_Obj\n")); NEXT_INST_F(1, 1, 1); } TclInvalidateStringRep(valuePtr); TRACE_APPEND(("numeric, same Tcl_Obj\n")); NEXT_INST_F(1, 0, 0); } /* * End of numeric operator instructions. * ----------------------------------------------------------------- */ case INST_TRY_CVT_TO_BOOLEAN: valuePtr = OBJ_AT_TOS; if (valuePtr->typePtr == &tclBooleanType) { objResultPtr = TCONST(1); } else { int result = (TclSetBooleanFromAny(NULL, valuePtr) == TCL_OK); objResultPtr = TCONST(result); } TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(valuePtr)), objResultPtr); NEXT_INST_F(1, 0, 1); case INST_BREAK: /* DECACHE_STACK_INFO(); Tcl_ResetResult(interp); CACHE_STACK_INFO(); */ result = TCL_BREAK; cleanup = 0; TRACE(("=> BREAK!\n")); goto processExceptionReturn; case INST_CONTINUE: /* DECACHE_STACK_INFO(); Tcl_ResetResult(interp); CACHE_STACK_INFO(); */ result = TCL_CONTINUE; cleanup = 0; TRACE(("=> CONTINUE!\n")); goto processExceptionReturn; { ForeachInfo *infoPtr; Var *iterVarPtr, *listVarPtr; Tcl_Obj *oldValuePtr, *listPtr, **elements; ForeachVarList *varListPtr; int numLists, iterNum, listTmpIndex, listLen, numVars; int varIndex, valIndex, continueLoop, j, iterTmpIndex; long i; case INST_FOREACH_START4: /* DEPRECATED */ /* * Initialize the temporary local var that holds the count of the * number of iterations of the loop body to -1. */ opnd = TclGetUInt4AtPtr(pc+1); infoPtr = codePtr->auxDataArrayPtr[opnd].clientData; iterTmpIndex = infoPtr->loopCtTemp; iterVarPtr = LOCAL(iterTmpIndex); oldValuePtr = iterVarPtr->value.objPtr; if (oldValuePtr == NULL) { TclNewLongObj(iterVarPtr->value.objPtr, -1); Tcl_IncrRefCount(iterVarPtr->value.objPtr); } else { TclSetLongObj(oldValuePtr, -1); } TRACE(("%u => loop iter count temp %d\n", opnd, iterTmpIndex)); #ifndef TCL_COMPILE_DEBUG /* * Remark that the compiler ALWAYS sets INST_FOREACH_STEP4 immediately * after INST_FOREACH_START4 - let us just fall through instead of * jumping back to the top. */ pc += 5; TCL_DTRACE_INST_NEXT(); #else NEXT_INST_F(5, 0, 0); #endif case INST_FOREACH_STEP4: /* DEPRECATED */ /* * "Step" a foreach loop (i.e., begin its next iteration) by assigning * the next value list element to each loop var. */ opnd = TclGetUInt4AtPtr(pc+1); TRACE(("%u => ", opnd)); infoPtr = codePtr->auxDataArrayPtr[opnd].clientData; numLists = infoPtr->numLists; /* * Increment the temp holding the loop iteration number. */ iterVarPtr = LOCAL(infoPtr->loopCtTemp); valuePtr = iterVarPtr->value.objPtr; iterNum = valuePtr->internalRep.longValue + 1; TclSetLongObj(valuePtr, iterNum); /* * Check whether all value lists are exhausted and we should stop the * loop. */ continueLoop = 0; listTmpIndex = infoPtr->firstValueTemp; for (i = 0; i < numLists; i++) { varListPtr = infoPtr->varLists[i]; numVars = varListPtr->numVars; listVarPtr = LOCAL(listTmpIndex); listPtr = listVarPtr->value.objPtr; if (TclListObjLength(interp, listPtr, &listLen) != TCL_OK) { TRACE_APPEND(("ERROR converting list %ld, \"%.30s\": %s\n", i, O2S(listPtr), O2S(Tcl_GetObjResult(interp)))); goto gotError; } if (listLen > iterNum * numVars) { continueLoop = 1; } listTmpIndex++; } /* * If some var in some var list still has a remaining list element * iterate one more time. Assign to var the next element from its * value list. We already checked above that each list temp holds a * valid list object (by calling Tcl_ListObjLength), but cannot rely * on that check remaining valid: one list could have been shimmered * as a side effect of setting a traced variable. */ if (continueLoop) { listTmpIndex = infoPtr->firstValueTemp; for (i = 0; i < numLists; i++) { varListPtr = infoPtr->varLists[i]; numVars = varListPtr->numVars; listVarPtr = LOCAL(listTmpIndex); listPtr = TclListObjCopy(NULL, listVarPtr->value.objPtr); TclListObjGetElements(interp, listPtr, &listLen, &elements); valIndex = (iterNum * numVars); for (j = 0; j < numVars; j++) { if (valIndex >= listLen) { TclNewObj(valuePtr); } else { valuePtr = elements[valIndex]; } varIndex = varListPtr->varIndexes[j]; varPtr = LOCAL(varIndex); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (TclIsVarDirectWritable(varPtr)) { value2Ptr = varPtr->value.objPtr; if (valuePtr != value2Ptr) { if (value2Ptr != NULL) { TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = valuePtr; Tcl_IncrRefCount(valuePtr); } } else { DECACHE_STACK_INFO(); if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){ CACHE_STACK_INFO(); TRACE_APPEND(( "ERROR init. index temp %d: %s\n", varIndex, O2S(Tcl_GetObjResult(interp)))); TclDecrRefCount(listPtr); goto gotError; } CACHE_STACK_INFO(); } valIndex++; } TclDecrRefCount(listPtr); listTmpIndex++; } } TRACE_APPEND(("%d lists, iter %d, %s loop\n", numLists, iterNum, (continueLoop? "continue" : "exit"))); /* * Run-time peep-hole optimisation: the compiler ALWAYS follows * INST_FOREACH_STEP4 with an INST_JUMP_FALSE. We just skip that * instruction and jump direct from here. */ pc += 5; if (*pc == INST_JUMP_FALSE1) { NEXT_INST_F((continueLoop? 2 : TclGetInt1AtPtr(pc+1)), 0, 0); } else { NEXT_INST_F((continueLoop? 5 : TclGetInt4AtPtr(pc+1)), 0, 0); } } { ForeachInfo *infoPtr; Tcl_Obj *listPtr, **elements, *tmpPtr; ForeachVarList *varListPtr; int numLists, iterMax, listLen, numVars; int iterTmp, iterNum, listTmpDepth; int varIndex, valIndex, j; long i; case INST_FOREACH_START: /* * Initialize the data for the looping construct, pushing the * corresponding Tcl_Objs to the stack. */ opnd = TclGetUInt4AtPtr(pc+1); infoPtr = codePtr->auxDataArrayPtr[opnd].clientData; numLists = infoPtr->numLists; TRACE(("%u => ", opnd)); /* * Compute the number of iterations that will be run: iterMax */ iterMax = 0; listTmpDepth = numLists-1; for (i = 0; i < numLists; i++) { varListPtr = infoPtr->varLists[i]; numVars = varListPtr->numVars; listPtr = OBJ_AT_DEPTH(listTmpDepth); if (TclListObjLength(interp, listPtr, &listLen) != TCL_OK) { TRACE_APPEND(("ERROR converting list %ld, \"%s\": %s", i, O2S(listPtr), O2S(Tcl_GetObjResult(interp)))); goto gotError; } if (Tcl_IsShared(listPtr)) { objPtr = TclListObjCopy(NULL, listPtr); Tcl_IncrRefCount(objPtr); Tcl_DecrRefCount(listPtr); OBJ_AT_DEPTH(listTmpDepth) = objPtr; } iterTmp = (listLen + (numVars - 1))/numVars; if (iterTmp > iterMax) { iterMax = iterTmp; } listTmpDepth--; } /* * Store the iterNum and iterMax in a single Tcl_Obj; we keep a * nul-string obj with the pointer stored in the ptrValue so that the * thing is properly garbage collected. THIS OBJ MAKES NO SENSE, but * it will never leave this scope and is read-only. */ TclNewObj(tmpPtr); tmpPtr->internalRep.twoPtrValue.ptr1 = INT2PTR(0); tmpPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(iterMax); PUSH_OBJECT(tmpPtr); /* iterCounts object */ /* * Store a pointer to the ForeachInfo struct; same dirty trick * as above */ TclNewObj(tmpPtr); tmpPtr->internalRep.twoPtrValue.ptr1 = infoPtr; PUSH_OBJECT(tmpPtr); /* infoPtr object */ TRACE_APPEND(("jump to loop step\n")); /* * Jump directly to the INST_FOREACH_STEP instruction; the C code just * falls through. */ pc += 5 - infoPtr->loopCtTemp; case INST_FOREACH_STEP: /* * "Step" a foreach loop (i.e., begin its next iteration) by assigning * the next value list element to each loop var. */ tmpPtr = OBJ_AT_TOS; infoPtr = tmpPtr->internalRep.twoPtrValue.ptr1; numLists = infoPtr->numLists; TRACE(("=> ")); tmpPtr = OBJ_AT_DEPTH(1); iterNum = PTR2INT(tmpPtr->internalRep.twoPtrValue.ptr1); iterMax = PTR2INT(tmpPtr->internalRep.twoPtrValue.ptr2); /* * If some list still has a remaining list element iterate one more * time. Assign to var the next element from its value list. */ if (iterNum < iterMax) { /* * Set the variables and jump back to run the body */ tmpPtr->internalRep.twoPtrValue.ptr1 = INT2PTR(iterNum + 1); listTmpDepth = numLists + 1; for (i = 0; i < numLists; i++) { varListPtr = infoPtr->varLists[i]; numVars = varListPtr->numVars; listPtr = OBJ_AT_DEPTH(listTmpDepth); TclListObjGetElements(interp, listPtr, &listLen, &elements); valIndex = (iterNum * numVars); for (j = 0; j < numVars; j++) { if (valIndex >= listLen) { TclNewObj(valuePtr); } else { valuePtr = elements[valIndex]; } varIndex = varListPtr->varIndexes[j]; varPtr = LOCAL(varIndex); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (TclIsVarDirectWritable(varPtr)) { value2Ptr = varPtr->value.objPtr; if (valuePtr != value2Ptr) { if (value2Ptr != NULL) { TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = valuePtr; Tcl_IncrRefCount(valuePtr); } } else { DECACHE_STACK_INFO(); if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){ CACHE_STACK_INFO(); TRACE_APPEND(("ERROR init. index temp %d: %.30s", varIndex, O2S(Tcl_GetObjResult(interp)))); goto gotError; } CACHE_STACK_INFO(); } valIndex++; } listTmpDepth--; } TRACE_APPEND(("jump to loop start\n")); /* loopCtTemp being 'misused' for storing the jump size */ NEXT_INST_F(infoPtr->loopCtTemp, 0, 0); } TRACE_APPEND(("loop has no more iterations\n")); #ifdef TCL_COMPILE_DEBUG NEXT_INST_F(1, 0, 0); #else /* * FALL THROUGH */ pc++; #endif case INST_FOREACH_END: /* THIS INSTRUCTION IS ONLY CALLED AS A BREAK TARGET */ tmpPtr = OBJ_AT_TOS; infoPtr = tmpPtr->internalRep.twoPtrValue.ptr1; numLists = infoPtr->numLists; TRACE(("=> loop terminated\n")); NEXT_INST_V(1, numLists+2, 0); case INST_LMAP_COLLECT: /* * This instruction is only issued by lmap. The stack is: * - result * - infoPtr * - loop counters * - valLists * - collecting obj (unshared) * The instruction lappends the result to the collecting obj. */ tmpPtr = OBJ_AT_DEPTH(1); infoPtr = tmpPtr->internalRep.twoPtrValue.ptr1; numLists = infoPtr->numLists; TRACE_APPEND(("=> appending to list at depth %d\n", 3 + numLists)); objPtr = OBJ_AT_DEPTH(3 + numLists); Tcl_ListObjAppendElement(NULL, objPtr, OBJ_AT_TOS); NEXT_INST_F(1, 1, 0); } case INST_BEGIN_CATCH4: /* * Record start of the catch command with exception range index equal * to the operand. Push the current stack depth onto the special catch * stack. */ *(++catchTop) = CURR_DEPTH; TRACE(("%u => catchTop=%d, stackTop=%d\n", TclGetUInt4AtPtr(pc+1), (int) (catchTop - initCatchTop - 1), (int) CURR_DEPTH)); NEXT_INST_F(5, 0, 0); case INST_END_CATCH: catchTop--; DECACHE_STACK_INFO(); Tcl_ResetResult(interp); CACHE_STACK_INFO(); result = TCL_OK; TRACE(("=> catchTop=%d\n", (int) (catchTop - initCatchTop - 1))); NEXT_INST_F(1, 0, 0); case INST_PUSH_RESULT: objResultPtr = Tcl_GetObjResult(interp); TRACE_WITH_OBJ(("=> "), objResultPtr); /* * See the comments at INST_INVOKE_STK */ TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); iPtr->objResultPtr = objPtr; NEXT_INST_F(1, 0, -1); case INST_PUSH_RETURN_CODE: TclNewIntObj(objResultPtr, result); TRACE(("=> %u\n", result)); NEXT_INST_F(1, 0, 1); case INST_PUSH_RETURN_OPTIONS: DECACHE_STACK_INFO(); objResultPtr = Tcl_GetReturnOptions(interp, result); CACHE_STACK_INFO(); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); case INST_RETURN_CODE_BRANCH: { int code; if (TclGetIntFromObj(NULL, OBJ_AT_TOS, &code) != TCL_OK) { Tcl_Panic("INST_RETURN_CODE_BRANCH: TOS not a return code!"); } if (code == TCL_OK) { Tcl_Panic("INST_RETURN_CODE_BRANCH: TOS is TCL_OK!"); } if (code < TCL_ERROR || code > TCL_CONTINUE) { code = TCL_CONTINUE + 1; } TRACE(("\"%s\" => jump offset %d\n", O2S(OBJ_AT_TOS), 2*code-1)); NEXT_INST_F(2*code-1, 1, 0); } /* * ----------------------------------------------------------------- * Start of dictionary-related instructions. */ { int opnd2, allocateDict, done, i, allocdict; Tcl_Obj *dictPtr, *statePtr, *keyPtr, *listPtr, *varNamePtr, *keysPtr; Tcl_Obj *emptyPtr, **keyPtrPtr; Tcl_DictSearch *searchPtr; DictUpdateInfo *duiPtr; case INST_DICT_VERIFY: dictPtr = OBJ_AT_TOS; TRACE(("\"%.30s\" => ", O2S(dictPtr))); if (Tcl_DictObjSize(interp, dictPtr, &done) != TCL_OK) { TRACE_APPEND(("ERROR verifying dictionary nature of \"%.30s\": %s\n", O2S(dictPtr), O2S(Tcl_GetObjResult(interp)))); goto gotError; } TRACE_APPEND(("OK\n")); NEXT_INST_F(1, 1, 0); case INST_DICT_GET: case INST_DICT_EXISTS: { register Tcl_Interp *interp2 = interp; register int found; opnd = TclGetUInt4AtPtr(pc+1); TRACE(("%u => ", opnd)); dictPtr = OBJ_AT_DEPTH(opnd); if (*pc == INST_DICT_EXISTS) { interp2 = NULL; } if (opnd > 1) { dictPtr = TclTraceDictPath(interp2, dictPtr, opnd-1, &OBJ_AT_DEPTH(opnd-1), DICT_PATH_READ); if (dictPtr == NULL) { if (*pc == INST_DICT_EXISTS) { found = 0; goto afterDictExists; } TRACE_WITH_OBJ(( "ERROR tracing dictionary path into \"%.30s\": ", O2S(OBJ_AT_DEPTH(opnd))), Tcl_GetObjResult(interp)); goto gotError; } } if (Tcl_DictObjGet(interp2, dictPtr, OBJ_AT_TOS, &objResultPtr) == TCL_OK) { if (*pc == INST_DICT_EXISTS) { found = (objResultPtr ? 1 : 0); goto afterDictExists; } if (!objResultPtr) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "key \"%s\" not known in dictionary", TclGetString(OBJ_AT_TOS))); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT", TclGetString(OBJ_AT_TOS), NULL); CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(5, opnd+1, 1); } else if (*pc != INST_DICT_EXISTS) { TRACE_APPEND(("ERROR reading leaf dictionary key \"%.30s\": %s", O2S(dictPtr), O2S(Tcl_GetObjResult(interp)))); goto gotError; } else { found = 0; } afterDictExists: TRACE_APPEND(("%d\n", found)); /* * The INST_DICT_EXISTS instruction is usually followed by a * conditional jump, so we can take advantage of this to do some * peephole optimization (note that we're careful to not close out * someone doing something else). */ JUMP_PEEPHOLE_V(found, 5, opnd+1); } case INST_DICT_SET: case INST_DICT_UNSET: case INST_DICT_INCR_IMM: opnd = TclGetUInt4AtPtr(pc+1); opnd2 = TclGetUInt4AtPtr(pc+5); varPtr = LOCAL(opnd2); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u %u => ", opnd, opnd2)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { DECACHE_STACK_INFO(); dictPtr = TclPtrGetVar(interp, varPtr, NULL,NULL,NULL, 0, opnd2); CACHE_STACK_INFO(); } if (dictPtr == NULL) { TclNewObj(dictPtr); allocateDict = 1; } else { allocateDict = Tcl_IsShared(dictPtr); if (allocateDict) { dictPtr = Tcl_DuplicateObj(dictPtr); } } switch (*pc) { case INST_DICT_SET: cleanup = opnd + 1; result = Tcl_DictObjPutKeyList(interp, dictPtr, opnd, &OBJ_AT_DEPTH(opnd), OBJ_AT_TOS); break; case INST_DICT_INCR_IMM: cleanup = 1; opnd = TclGetInt4AtPtr(pc+1); result = Tcl_DictObjGet(interp, dictPtr, OBJ_AT_TOS, &valuePtr); if (result != TCL_OK) { break; } if (valuePtr == NULL) { Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS,Tcl_NewIntObj(opnd)); } else { value2Ptr = Tcl_NewIntObj(opnd); Tcl_IncrRefCount(value2Ptr); if (Tcl_IsShared(valuePtr)) { valuePtr = Tcl_DuplicateObj(valuePtr); Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS, valuePtr); } result = TclIncrObj(interp, valuePtr, value2Ptr); if (result == TCL_OK) { TclInvalidateStringRep(dictPtr); } TclDecrRefCount(value2Ptr); } break; case INST_DICT_UNSET: cleanup = opnd; result = Tcl_DictObjRemoveKeyList(interp, dictPtr, opnd, &OBJ_AT_DEPTH(opnd-1)); break; default: cleanup = 0; /* stop compiler warning */ Tcl_Panic("Should not happen!"); } if (result != TCL_OK) { if (allocateDict) { TclDecrRefCount(dictPtr); } TRACE_APPEND(("ERROR updating dictionary: %s\n", O2S(Tcl_GetObjResult(interp)))); goto checkForCatch; } if (TclIsVarDirectWritable(varPtr)) { if (allocateDict) { value2Ptr = varPtr->value.objPtr; Tcl_IncrRefCount(dictPtr); if (value2Ptr != NULL) { TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = dictPtr; } objResultPtr = dictPtr; } else { Tcl_IncrRefCount(dictPtr); DECACHE_STACK_INFO(); objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, dictPtr, TCL_LEAVE_ERR_MSG, opnd2); CACHE_STACK_INFO(); TclDecrRefCount(dictPtr); if (objResultPtr == NULL) { TRACE_ERROR(interp); goto gotError; } } #ifndef TCL_COMPILE_DEBUG if (*(pc+9) == INST_POP) { NEXT_INST_V(10, cleanup, 0); } #endif TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_V(9, cleanup, 1); case INST_DICT_APPEND: case INST_DICT_LAPPEND: opnd = TclGetUInt4AtPtr(pc+1); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { DECACHE_STACK_INFO(); dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd); CACHE_STACK_INFO(); } if (dictPtr == NULL) { TclNewObj(dictPtr); allocateDict = 1; } else { allocateDict = Tcl_IsShared(dictPtr); if (allocateDict) { dictPtr = Tcl_DuplicateObj(dictPtr); } } if (Tcl_DictObjGet(interp, dictPtr, OBJ_UNDER_TOS, &valuePtr) != TCL_OK) { if (allocateDict) { TclDecrRefCount(dictPtr); } TRACE_ERROR(interp); goto gotError; } /* * Note that a non-existent key results in a NULL valuePtr, which is a * case handled separately below. What we *can* say at this point is * that the write-back will always succeed. */ switch (*pc) { case INST_DICT_APPEND: if (valuePtr == NULL) { Tcl_DictObjPut(NULL, dictPtr, OBJ_UNDER_TOS, OBJ_AT_TOS); } else if (Tcl_IsShared(valuePtr)) { valuePtr = Tcl_DuplicateObj(valuePtr); Tcl_AppendObjToObj(valuePtr, OBJ_AT_TOS); Tcl_DictObjPut(NULL, dictPtr, OBJ_UNDER_TOS, valuePtr); } else { Tcl_AppendObjToObj(valuePtr, OBJ_AT_TOS); /* * Must invalidate the string representation of dictionary * here because we have directly updated the internal * representation; if we don't, callers could see the wrong * string rep despite the internal version of the dictionary * having the correct value. [Bug 3079830] */ TclInvalidateStringRep(dictPtr); } break; case INST_DICT_LAPPEND: /* * More complex because list-append can fail. */ if (valuePtr == NULL) { Tcl_DictObjPut(NULL, dictPtr, OBJ_UNDER_TOS, Tcl_NewListObj(1, &OBJ_AT_TOS)); break; } else if (Tcl_IsShared(valuePtr)) { valuePtr = Tcl_DuplicateObj(valuePtr); if (Tcl_ListObjAppendElement(interp, valuePtr, OBJ_AT_TOS) != TCL_OK) { TclDecrRefCount(valuePtr); if (allocateDict) { TclDecrRefCount(dictPtr); } TRACE_ERROR(interp); goto gotError; } Tcl_DictObjPut(NULL, dictPtr, OBJ_UNDER_TOS, valuePtr); } else { if (Tcl_ListObjAppendElement(interp, valuePtr, OBJ_AT_TOS) != TCL_OK) { if (allocateDict) { TclDecrRefCount(dictPtr); } TRACE_ERROR(interp); goto gotError; } /* * Must invalidate the string representation of dictionary * here because we have directly updated the internal * representation; if we don't, callers could see the wrong * string rep despite the internal version of the dictionary * having the correct value. [Bug 3079830] */ TclInvalidateStringRep(dictPtr); } break; default: Tcl_Panic("Should not happen!"); } if (TclIsVarDirectWritable(varPtr)) { if (allocateDict) { value2Ptr = varPtr->value.objPtr; Tcl_IncrRefCount(dictPtr); if (value2Ptr != NULL) { TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = dictPtr; } objResultPtr = dictPtr; } else { Tcl_IncrRefCount(dictPtr); DECACHE_STACK_INFO(); objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, dictPtr, TCL_LEAVE_ERR_MSG, opnd); CACHE_STACK_INFO(); TclDecrRefCount(dictPtr); if (objResultPtr == NULL) { TRACE_ERROR(interp); goto gotError; } } #ifndef TCL_COMPILE_DEBUG if (*(pc+5) == INST_POP) { NEXT_INST_F(6, 2, 0); } #endif TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_F(5, 2, 1); case INST_DICT_FIRST: opnd = TclGetUInt4AtPtr(pc+1); TRACE(("%u => ", opnd)); dictPtr = POP_OBJECT(); searchPtr = ckalloc(sizeof(Tcl_DictSearch)); if (Tcl_DictObjFirst(interp, dictPtr, searchPtr, &keyPtr, &valuePtr, &done) != TCL_OK) { /* * dictPtr is no longer on the stack, and we're not * moving it into the intrep of an iterator. We need * to drop the refcount [Tcl Bug 9b352768e6]. */ Tcl_DecrRefCount(dictPtr); ckfree(searchPtr); TRACE_ERROR(interp); goto gotError; } TclNewObj(statePtr); statePtr->typePtr = &dictIteratorType; statePtr->internalRep.twoPtrValue.ptr1 = searchPtr; statePtr->internalRep.twoPtrValue.ptr2 = dictPtr; varPtr = LOCAL(opnd); if (varPtr->value.objPtr) { if (varPtr->value.objPtr->typePtr == &dictIteratorType) { Tcl_Panic("mis-issued dictFirst!"); } TclDecrRefCount(varPtr->value.objPtr); } varPtr->value.objPtr = statePtr; Tcl_IncrRefCount(statePtr); goto pushDictIteratorResult; case INST_DICT_NEXT: opnd = TclGetUInt4AtPtr(pc+1); TRACE(("%u => ", opnd)); statePtr = (*LOCAL(opnd)).value.objPtr; if (statePtr == NULL || statePtr->typePtr != &dictIteratorType) { Tcl_Panic("mis-issued dictNext!"); } searchPtr = statePtr->internalRep.twoPtrValue.ptr1; Tcl_DictObjNext(searchPtr, &keyPtr, &valuePtr, &done); pushDictIteratorResult: if (done) { TclNewObj(emptyPtr); PUSH_OBJECT(emptyPtr); PUSH_OBJECT(emptyPtr); } else { PUSH_OBJECT(valuePtr); PUSH_OBJECT(keyPtr); } TRACE_APPEND(("\"%.30s\" \"%.30s\" %d\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), done)); /* * The INST_DICT_FIRST and INST_DICT_NEXT instructsions are always * followed by a conditional jump, so we can take advantage of this to * do some peephole optimization (note that we're careful to not close * out someone doing something else). */ JUMP_PEEPHOLE_F(done, 5, 0); case INST_DICT_UPDATE_START: opnd = TclGetUInt4AtPtr(pc+1); opnd2 = TclGetUInt4AtPtr(pc+5); TRACE(("%u => ", opnd)); varPtr = LOCAL(opnd); duiPtr = codePtr->auxDataArrayPtr[opnd2].clientData; while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { DECACHE_STACK_INFO(); dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, TCL_LEAVE_ERR_MSG, opnd); CACHE_STACK_INFO(); if (dictPtr == NULL) { TRACE_ERROR(interp); goto gotError; } } if (TclListObjGetElements(interp, OBJ_AT_TOS, &length, &keyPtrPtr) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } if (length != duiPtr->length) { Tcl_Panic("dictUpdateStart argument length mismatch"); } for (i=0 ; ivarIndices[i]); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } DECACHE_STACK_INFO(); if (valuePtr == NULL) { TclObjUnsetVar2(interp, localName(iPtr->varFramePtr, duiPtr->varIndices[i]), NULL, 0); } else if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, valuePtr, TCL_LEAVE_ERR_MSG, duiPtr->varIndices[i]) == NULL) { CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } CACHE_STACK_INFO(); } TRACE_APPEND(("OK\n")); NEXT_INST_F(9, 0, 0); case INST_DICT_UPDATE_END: opnd = TclGetUInt4AtPtr(pc+1); opnd2 = TclGetUInt4AtPtr(pc+5); TRACE(("%u => ", opnd)); varPtr = LOCAL(opnd); duiPtr = codePtr->auxDataArrayPtr[opnd2].clientData; while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { DECACHE_STACK_INFO(); dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd); CACHE_STACK_INFO(); } if (dictPtr == NULL) { TRACE_APPEND(("storage was unset\n")); NEXT_INST_F(9, 1, 0); } if (Tcl_DictObjSize(interp, dictPtr, &length) != TCL_OK || TclListObjGetElements(interp, OBJ_AT_TOS, &length, &keyPtrPtr) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } allocdict = Tcl_IsShared(dictPtr); if (allocdict) { dictPtr = Tcl_DuplicateObj(dictPtr); } if (length > 0) { TclInvalidateStringRep(dictPtr); } for (i=0 ; ivarIndices[i]); while (TclIsVarLink(var2Ptr)) { var2Ptr = var2Ptr->value.linkPtr; } if (TclIsVarDirectReadable(var2Ptr)) { valuePtr = var2Ptr->value.objPtr; } else { DECACHE_STACK_INFO(); valuePtr = TclPtrGetVar(interp, var2Ptr, NULL, NULL, NULL, 0, duiPtr->varIndices[i]); CACHE_STACK_INFO(); } if (valuePtr == NULL) { Tcl_DictObjRemove(interp, dictPtr, keyPtrPtr[i]); } else if (dictPtr == valuePtr) { Tcl_DictObjPut(interp, dictPtr, keyPtrPtr[i], Tcl_DuplicateObj(valuePtr)); } else { Tcl_DictObjPut(interp, dictPtr, keyPtrPtr[i], valuePtr); } } if (TclIsVarDirectWritable(varPtr)) { Tcl_IncrRefCount(dictPtr); TclDecrRefCount(varPtr->value.objPtr); varPtr->value.objPtr = dictPtr; } else { DECACHE_STACK_INFO(); objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, dictPtr, TCL_LEAVE_ERR_MSG, opnd); CACHE_STACK_INFO(); if (objResultPtr == NULL) { if (allocdict) { TclDecrRefCount(dictPtr); } TRACE_ERROR(interp); goto gotError; } } TRACE_APPEND(("written back\n")); NEXT_INST_F(9, 1, 0); case INST_DICT_EXPAND: dictPtr = OBJ_UNDER_TOS; listPtr = OBJ_AT_TOS; TRACE(("\"%.30s\" \"%.30s\" =>", O2S(dictPtr), O2S(listPtr))); if (TclListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } objResultPtr = TclDictWithInit(interp, dictPtr, objc, objv); if (objResultPtr == NULL) { TRACE_ERROR(interp); goto gotError; } TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); case INST_DICT_RECOMBINE_STK: keysPtr = POP_OBJECT(); varNamePtr = OBJ_UNDER_TOS; listPtr = OBJ_AT_TOS; TRACE(("\"%.30s\" \"%.30s\" \"%.30s\" => ", O2S(varNamePtr), O2S(valuePtr), O2S(keysPtr))); if (TclListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); TclDecrRefCount(keysPtr); goto gotError; } varPtr = TclObjLookupVarEx(interp, varNamePtr, NULL, TCL_LEAVE_ERR_MSG, "set", 1, 1, &arrayPtr); if (varPtr == NULL) { TRACE_ERROR(interp); TclDecrRefCount(keysPtr); goto gotError; } DECACHE_STACK_INFO(); result = TclDictWithFinish(interp, varPtr,arrayPtr,varNamePtr,NULL,-1, objc, objv, keysPtr); CACHE_STACK_INFO(); TclDecrRefCount(keysPtr); if (result != TCL_OK) { TRACE_ERROR(interp); goto gotError; } TRACE_APPEND(("OK\n")); NEXT_INST_F(1, 2, 0); case INST_DICT_RECOMBINE_IMM: opnd = TclGetUInt4AtPtr(pc+1); listPtr = OBJ_UNDER_TOS; keysPtr = OBJ_AT_TOS; varPtr = LOCAL(opnd); TRACE(("%u <- \"%.30s\" \"%.30s\" => ", opnd, O2S(valuePtr), O2S(keysPtr))); if (TclListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } DECACHE_STACK_INFO(); result = TclDictWithFinish(interp, varPtr, NULL, NULL, NULL, opnd, objc, objv, keysPtr); CACHE_STACK_INFO(); if (result != TCL_OK) { TRACE_ERROR(interp); goto gotError; } TRACE_APPEND(("OK\n")); NEXT_INST_F(5, 2, 0); } /* * End of dictionary-related instructions. * ----------------------------------------------------------------- */ default: Tcl_Panic("TclNRExecuteByteCode: unrecognized opCode %u", *pc); } /* end of switch on opCode */ /* * Block for variables needed to process exception returns. */ { ExceptionRange *rangePtr; /* Points to closest loop or catch exception * range enclosing the pc. Used by various * instructions and processCatch to process * break, continue, and errors. */ const char *bytes; /* * An external evaluation (INST_INVOKE or INST_EVAL) returned * something different from TCL_OK, or else INST_BREAK or * INST_CONTINUE were called. */ processExceptionReturn: #ifdef TCL_COMPILE_DEBUG switch (*pc) { case INST_INVOKE_STK1: opnd = TclGetUInt1AtPtr(pc+1); TRACE(("%u => ... after \"%.20s\": ", opnd, cmdNameBuf)); break; case INST_INVOKE_STK4: opnd = TclGetUInt4AtPtr(pc+1); TRACE(("%u => ... after \"%.20s\": ", opnd, cmdNameBuf)); break; case INST_EVAL_STK: /* * Note that the object at stacktop has to be used before doing * the cleanup. */ TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS))); break; default: TRACE(("=> ")); } #endif if ((result == TCL_CONTINUE) || (result == TCL_BREAK)) { rangePtr = GetExceptRangeForPc(pc, result, codePtr); if (rangePtr == NULL) { TRACE_APPEND(("no encl. loop or catch, returning %s\n", StringForResultCode(result))); goto abnormalReturn; } if (rangePtr->type == CATCH_EXCEPTION_RANGE) { TRACE_APPEND(("%s ...\n", StringForResultCode(result))); goto processCatch; } while (cleanup--) { valuePtr = POP_OBJECT(); TclDecrRefCount(valuePtr); } if (result == TCL_BREAK) { result = TCL_OK; pc = (codePtr->codeStart + rangePtr->breakOffset); TRACE_APPEND(("%s, range at %d, new pc %d\n", StringForResultCode(result), rangePtr->codeOffset, rangePtr->breakOffset)); NEXT_INST_F(0, 0, 0); } if (rangePtr->continueOffset == -1) { TRACE_APPEND(("%s, loop w/o continue, checking for catch\n", StringForResultCode(result))); goto checkForCatch; } result = TCL_OK; pc = (codePtr->codeStart + rangePtr->continueOffset); TRACE_APPEND(("%s, range at %d, new pc %d\n", StringForResultCode(result), rangePtr->codeOffset, rangePtr->continueOffset)); NEXT_INST_F(0, 0, 0); } #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { objPtr = Tcl_GetObjResult(interp); if ((result != TCL_ERROR) && (result != TCL_RETURN)) { TRACE_APPEND(("OTHER RETURN CODE %d, result=\"%.30s\"\n ", result, O2S(objPtr))); } else { TRACE_APPEND(("%s, result=\"%.30s\"\n", StringForResultCode(result), O2S(objPtr))); } } #endif goto checkForCatch; /* * Division by zero in an expression. Control only reaches this point * by "goto divideByZero". */ divideByZero: Tcl_SetObjResult(interp, Tcl_NewStringObj("divide by zero", -1)); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero", NULL); CACHE_STACK_INFO(); goto gotError; /* * Exponentiation of zero by negative number in an expression. Control * only reaches this point by "goto exponOfZero". */ exponOfZero: Tcl_SetObjResult(interp, Tcl_NewStringObj( "exponentiation of zero by negative power", -1)); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", "exponentiation of zero by negative power", NULL); CACHE_STACK_INFO(); /* * Almost all error paths feed through here rather than assigning to * result themselves (for a small but consistent saving). */ gotError: result = TCL_ERROR; /* * Execution has generated an "exception" such as TCL_ERROR. If the * exception is an error, record information about what was being * executed when the error occurred. Find the closest enclosing catch * range, if any. If no enclosing catch range is found, stop execution * and return the "exception" code. */ checkForCatch: if (iPtr->execEnvPtr->rewind) { goto abnormalReturn; } if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { const unsigned char *pcBeg; bytes = GetSrcInfoForPc(pc, codePtr, &length, &pcBeg, NULL); DECACHE_STACK_INFO(); TclLogCommandInfo(interp, codePtr->source, bytes, bytes ? length : 0, pcBeg, tosPtr); CACHE_STACK_INFO(); } iPtr->flags &= ~ERR_ALREADY_LOGGED; /* * Clear all expansions that may have started after the last * INST_BEGIN_CATCH. */ while (auxObjList) { if ((catchTop != initCatchTop) && (*catchTop > (ptrdiff_t) auxObjList->internalRep.twoPtrValue.ptr2)) { break; } POP_TAUX_OBJ(); } /* * We must not catch if the script in progress has been canceled with * the TCL_CANCEL_UNWIND flag. Instead, it blows outwards until we * either hit another interpreter (presumably where the script in * progress has not been canceled) or we get to the top-level. We do * NOT modify the interpreter result here because we know it will * already be set prior to vectoring down to this point in the code. */ if (TclCanceled(iPtr) && (Tcl_Canceled(interp, 0) == TCL_ERROR)) { #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { fprintf(stdout, " ... cancel with unwind, returning %s\n", StringForResultCode(result)); } #endif goto abnormalReturn; } /* * We must not catch an exceeded limit. Instead, it blows outwards * until we either hit another interpreter (presumably where the limit * is not exceeded) or we get to the top-level. */ if (TclLimitExceeded(iPtr->limit)) { #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { fprintf(stdout, " ... limit exceeded, returning %s\n", StringForResultCode(result)); } #endif goto abnormalReturn; } if (catchTop == initCatchTop) { #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { fprintf(stdout, " ... no enclosing catch, returning %s\n", StringForResultCode(result)); } #endif goto abnormalReturn; } rangePtr = GetExceptRangeForPc(pc, TCL_ERROR, codePtr); if (rangePtr == NULL) { /* * This is only possible when compiling a [catch] that sends its * script to INST_EVAL. Cannot correct the compiler without * breaking compat with previous .tbc compiled scripts. */ #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { fprintf(stdout, " ... no enclosing catch, returning %s\n", StringForResultCode(result)); } #endif goto abnormalReturn; } /* * A catch exception range (rangePtr) was found to handle an * "exception". It was found either by checkForCatch just above or by * an instruction during break, continue, or error processing. Jump to * its catchOffset after unwinding the operand stack to the depth it * had when starting to execute the range's catch command. */ processCatch: while (CURR_DEPTH > *catchTop) { valuePtr = POP_OBJECT(); TclDecrRefCount(valuePtr); } #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { fprintf(stdout, " ... found catch at %d, catchTop=%d, " "unwound to %ld, new pc %u\n", rangePtr->codeOffset, (int) (catchTop - initCatchTop - 1), (long) *catchTop, (unsigned) rangePtr->catchOffset); } #endif pc = (codePtr->codeStart + rangePtr->catchOffset); NEXT_INST_F(0, 0, 0); /* Restart the execution loop at pc. */ /* * end of infinite loop dispatching on instructions. */ /* * Abnormal return code. Restore the stack to state it had when * starting to execute the ByteCode. Panic if the stack is below the * initial level. */ abnormalReturn: TCL_DTRACE_INST_LAST(); /* * Clear all expansions and same-level NR calls. * * Note that expansion markers have a NULL type; avoid removing other * markers. */ while (auxObjList) { POP_TAUX_OBJ(); } while (tosPtr > initTosPtr) { objPtr = POP_OBJECT(); Tcl_DecrRefCount(objPtr); } if (tosPtr < initTosPtr) { fprintf(stderr, "\nTclNRExecuteByteCode: abnormal return at pc %u: " "stack top %d < entry stack top %d\n", (unsigned)(pc - codePtr->codeStart), (unsigned) CURR_DEPTH, (unsigned) 0); Tcl_Panic("TclNRExecuteByteCode execution failure: end stack top < start stack top"); } CLANG_ASSERT(bcFramePtr); } iPtr->cmdFramePtr = bcFramePtr->nextPtr; if (codePtr->refCount-- <= 1) { TclCleanupByteCode(codePtr); } TclStackFree(interp, TD); /* free my stack */ return result; /* * INST_START_CMD failure case removed where it doesn't bother that much * * Remark that if the interpreter is marked for deletion its * compileEpoch is modified, so that the epoch check also verifies * that the interp is not deleted. If no outside call has been made * since the last check, it is safe to omit the check. * case INST_START_CMD: */ instStartCmdFailed: { const char *bytes; checkInterp = 1; length = 0; /* * We used to switch to direct eval; for NRE-awareness we now * compile and eval the command so that this evaluation does not * add a new TEBC instance. [Bug 2910748] */ if (TclInterpReady(interp) == TCL_ERROR) { goto gotError; } codePtr->flags |= TCL_BYTECODE_RECOMPILE; bytes = GetSrcInfoForPc(pc, codePtr, &length, NULL, NULL); opnd = TclGetUInt4AtPtr(pc+1); pc += (opnd-1); assert(bytes); PUSH_OBJECT(Tcl_NewStringObj(bytes, length)); goto instEvalStk; } } #undef codePtr #undef iPtr #undef bcFramePtr #undef initCatchTop #undef initTosPtr #undef auxObjList #undef catchTop #undef TCONST #undef esPtr static int FinalizeOONext( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; CallContext *contextPtr = data[1]; /* * Reset the variable lookup frame. */ iPtr->varFramePtr = data[0]; /* * Restore the call chain context index as we've finished the inner invoke * and want to operate in the outer context again. */ contextPtr->index = PTR2INT(data[2]); contextPtr->skip = PTR2INT(data[3]); contextPtr->oPtr->flags &= ~FILTER_HANDLING; return result; } static int FinalizeOONextFilter( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; CallContext *contextPtr = data[1]; /* * Reset the variable lookup frame. */ iPtr->varFramePtr = data[0]; /* * Restore the call chain context index as we've finished the inner invoke * and want to operate in the outer context again. */ contextPtr->index = PTR2INT(data[2]); contextPtr->skip = PTR2INT(data[3]); contextPtr->oPtr->flags |= FILTER_HANDLING; return result; } /* *---------------------------------------------------------------------- * * ExecuteExtendedBinaryMathOp, ExecuteExtendedUnaryMathOp -- * * These functions do advanced math for binary and unary operators * respectively, so that the main TEBC code does not bear the cost of * them. * * Results: * A Tcl_Obj* result, or a NULL (in which case valuePtr is updated to * hold the result value), or one of the special flag values * GENERAL_ARITHMETIC_ERROR, EXPONENT_OF_ZERO or DIVIDED_BY_ZERO. The * latter two signify a zero value raised to a negative power or a value * divided by zero, respectively. With GENERAL_ARITHMETIC_ERROR, all * error information will have already been reported in the interpreter * result. * * Side effects: * May update the Tcl_Obj indicated valuePtr if it is unshared. Will * return a NULL when that happens. * *---------------------------------------------------------------------- */ static Tcl_Obj * ExecuteExtendedBinaryMathOp( Tcl_Interp *interp, /* Where to report errors. */ int opcode, /* What operation to perform. */ Tcl_Obj **constants, /* The execution environment's constants. */ Tcl_Obj *valuePtr, /* The first operand on the stack. */ Tcl_Obj *value2Ptr) /* The second operand on the stack. */ { #define LONG_RESULT(l) \ if (Tcl_IsShared(valuePtr)) { \ TclNewLongObj(objResultPtr, l); \ return objResultPtr; \ } else { \ Tcl_SetLongObj(valuePtr, l); \ return NULL; \ } #define WIDE_RESULT(w) \ if (Tcl_IsShared(valuePtr)) { \ return Tcl_NewWideIntObj(w); \ } else { \ Tcl_SetWideIntObj(valuePtr, w); \ return NULL; \ } #define BIG_RESULT(b) \ if (Tcl_IsShared(valuePtr)) { \ return Tcl_NewBignumObj(b); \ } else { \ Tcl_SetBignumObj(valuePtr, b); \ return NULL; \ } #define DOUBLE_RESULT(d) \ if (Tcl_IsShared(valuePtr)) { \ TclNewDoubleObj(objResultPtr, (d)); \ return objResultPtr; \ } else { \ Tcl_SetDoubleObj(valuePtr, (d)); \ return NULL; \ } int type1, type2; ClientData ptr1, ptr2; double d1, d2, dResult; long l1, l2, lResult; Tcl_WideInt w1, w2, wResult; mp_int big1, big2, bigResult, bigRemainder; Tcl_Obj *objResultPtr; int invalid, numPos, zero; long shift; (void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1); (void) GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2); switch (opcode) { case INST_MOD: /* TODO: Attempts to re-use unshared operands on stack */ l2 = 0; /* silence gcc warning */ if (type2 == TCL_NUMBER_LONG) { l2 = *((const long *)ptr2); if (l2 == 0) { return DIVIDED_BY_ZERO; } if ((l2 == 1) || (l2 == -1)) { /* * Div. by |1| always yields remainder of 0. */ return constants[0]; } } #ifndef TCL_WIDE_INT_IS_LONG if (type1 == TCL_NUMBER_WIDE) { w1 = *((const Tcl_WideInt *)ptr1); if (type2 != TCL_NUMBER_BIG) { Tcl_WideInt wQuotient, wRemainder; Tcl_GetWideIntFromObj(NULL, value2Ptr, &w2); wQuotient = w1 / w2; /* * Force Tcl's integer division rules. * TODO: examine for logic simplification */ if (((wQuotient < (Tcl_WideInt) 0) || ((wQuotient == (Tcl_WideInt) 0) && ((w1 < (Tcl_WideInt)0 && w2 > (Tcl_WideInt)0) || (w1 > (Tcl_WideInt)0 && w2 < (Tcl_WideInt)0)))) && (wQuotient * w2 != w1)) { wQuotient -= (Tcl_WideInt) 1; } wRemainder = w1 - w2*wQuotient; WIDE_RESULT(wRemainder); } Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); /* TODO: internals intrusion */ if ((w1 > ((Tcl_WideInt) 0)) ^ (big2.sign == MP_ZPOS)) { /* * Arguments are opposite sign; remainder is sum. */ TclBNInitBignumFromWideInt(&big1, w1); mp_add(&big2, &big1, &big2); mp_clear(&big1); BIG_RESULT(&big2); } /* * Arguments are same sign; remainder is first operand. */ mp_clear(&big2); return NULL; } #endif Tcl_GetBignumFromObj(NULL, valuePtr, &big1); Tcl_GetBignumFromObj(NULL, value2Ptr, &big2); mp_init(&bigResult); mp_init(&bigRemainder); mp_div(&big1, &big2, &bigResult, &bigRemainder); if (!mp_iszero(&bigRemainder) && (bigRemainder.sign != big2.sign)) { /* * Convert to Tcl's integer division rules. */ mp_sub_d(&bigResult, 1, &bigResult); mp_add(&bigRemainder, &big2, &bigRemainder); } mp_copy(&bigRemainder, &bigResult); mp_clear(&bigRemainder); mp_clear(&big1); mp_clear(&big2); BIG_RESULT(&bigResult); case INST_LSHIFT: case INST_RSHIFT: { /* * Reject negative shift argument. */ switch (type2) { case TCL_NUMBER_LONG: invalid = (*((const long *)ptr2) < 0L); break; #ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: invalid = (*((const Tcl_WideInt *)ptr2) < (Tcl_WideInt)0); break; #endif case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); invalid = (mp_cmp_d(&big2, 0) == MP_LT); mp_clear(&big2); break; default: /* Unused, here to silence compiler warning */ invalid = 0; } if (invalid) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); return GENERAL_ARITHMETIC_ERROR; } /* * Zero shifted any number of bits is still zero. */ if ((type1==TCL_NUMBER_LONG) && (*((const long *)ptr1) == (long)0)) { return constants[0]; } if (opcode == INST_LSHIFT) { /* * Large left shifts create integer overflow. * * BEWARE! Can't use Tcl_GetIntFromObj() here because that * converts values in the (unsigned) range to their signed int * counterparts, leading to incorrect results. */ if ((type2 != TCL_NUMBER_LONG) || (*((const long *)ptr2) > (long) INT_MAX)) { /* * Technically, we could hold the value (1 << (INT_MAX+1)) in * an mp_int, but since we're using mp_mul_2d() to do the * work, and it takes only an int argument, that's a good * place to draw the line. */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "integer value too large to represent", -1)); return GENERAL_ARITHMETIC_ERROR; } shift = (int)(*((const long *)ptr2)); /* * Handle shifts within the native wide range. */ if ((type1 != TCL_NUMBER_BIG) && ((size_t)shift < CHAR_BIT*sizeof(Tcl_WideInt))) { TclGetWideIntFromObj(NULL, valuePtr, &w1); if (!((w1>0 ? w1 : ~w1) & -(((Tcl_WideInt)1) << (CHAR_BIT*sizeof(Tcl_WideInt) - 1 - shift)))) { WIDE_RESULT(w1 << shift); } } } else { /* * Quickly force large right shifts to 0 or -1. */ if ((type2 != TCL_NUMBER_LONG) || (*(const long *)ptr2 > INT_MAX)) { /* * Again, technically, the value to be shifted could be an * mp_int so huge that a right shift by (INT_MAX+1) bits could * not take us to the result of 0 or -1, but since we're using * mp_div_2d to do the work, and it takes only an int * argument, we draw the line there. */ switch (type1) { case TCL_NUMBER_LONG: zero = (*(const long *)ptr1 > 0L); break; #ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: zero = (*(const Tcl_WideInt *)ptr1 > (Tcl_WideInt)0); break; #endif case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); zero = (mp_cmp_d(&big1, 0) == MP_GT); mp_clear(&big1); break; default: /* Unused, here to silence compiler warning. */ zero = 0; } if (zero) { return constants[0]; } LONG_RESULT(-1); } shift = (int)(*(const long *)ptr2); #ifndef TCL_WIDE_INT_IS_LONG /* * Handle shifts within the native wide range. */ if (type1 == TCL_NUMBER_WIDE) { w1 = *(const Tcl_WideInt *)ptr1; if ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideInt)) { if (w1 >= (Tcl_WideInt)0) { return constants[0]; } LONG_RESULT(-1); } WIDE_RESULT(w1 >> shift); } #endif } Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); mp_init(&bigResult); if (opcode == INST_LSHIFT) { mp_mul_2d(&big1, shift, &bigResult); } else { mp_init(&bigRemainder); mp_div_2d(&big1, shift, &bigResult, &bigRemainder); if (mp_cmp_d(&bigRemainder, 0) == MP_LT) { /* * Convert to Tcl's integer division rules. */ mp_sub_d(&bigResult, 1, &bigResult); } mp_clear(&bigRemainder); } mp_clear(&big1); BIG_RESULT(&bigResult); } case INST_BITOR: case INST_BITXOR: case INST_BITAND: if ((type1 == TCL_NUMBER_BIG) || (type2 == TCL_NUMBER_BIG)) { mp_int *First, *Second; Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); /* * Count how many positive arguments we have. If only one of the * arguments is negative, store it in 'Second'. */ if (mp_cmp_d(&big1, 0) != MP_LT) { numPos = 1 + (mp_cmp_d(&big2, 0) != MP_LT); First = &big1; Second = &big2; } else { First = &big2; Second = &big1; numPos = (mp_cmp_d(First, 0) != MP_LT); } mp_init(&bigResult); switch (opcode) { case INST_BITAND: switch (numPos) { case 2: /* * Both arguments positive, base case. */ mp_and(First, Second, &bigResult); break; case 1: /* * First is positive; second negative: * P & N = P & ~~N = P&~(-N-1) = P & (P ^ (-N-1)) */ mp_neg(Second, Second); mp_sub_d(Second, 1, Second); mp_xor(First, Second, &bigResult); mp_and(First, &bigResult, &bigResult); break; case 0: /* * Both arguments negative: * a & b = ~ (~a | ~b) = -(-a-1|-b-1)-1 */ mp_neg(First, First); mp_sub_d(First, 1, First); mp_neg(Second, Second); mp_sub_d(Second, 1, Second); mp_or(First, Second, &bigResult); mp_neg(&bigResult, &bigResult); mp_sub_d(&bigResult, 1, &bigResult); break; } break; case INST_BITOR: switch (numPos) { case 2: /* * Both arguments positive, base case. */ mp_or(First, Second, &bigResult); break; case 1: /* * First is positive; second negative: * N|P = ~(~N&~P) = ~((-N-1)&~P) = -((-N-1)&((-N-1)^P))-1 */ mp_neg(Second, Second); mp_sub_d(Second, 1, Second); mp_xor(First, Second, &bigResult); mp_and(Second, &bigResult, &bigResult); mp_neg(&bigResult, &bigResult); mp_sub_d(&bigResult, 1, &bigResult); break; case 0: /* * Both arguments negative: * a | b = ~ (~a & ~b) = -(-a-1&-b-1)-1 */ mp_neg(First, First); mp_sub_d(First, 1, First); mp_neg(Second, Second); mp_sub_d(Second, 1, Second); mp_and(First, Second, &bigResult); mp_neg(&bigResult, &bigResult); mp_sub_d(&bigResult, 1, &bigResult); break; } break; case INST_BITXOR: switch (numPos) { case 2: /* * Both arguments positive, base case. */ mp_xor(First, Second, &bigResult); break; case 1: /* * First is positive; second negative: * P^N = ~(P^~N) = -(P^(-N-1))-1 */ mp_neg(Second, Second); mp_sub_d(Second, 1, Second); mp_xor(First, Second, &bigResult); mp_neg(&bigResult, &bigResult); mp_sub_d(&bigResult, 1, &bigResult); break; case 0: /* * Both arguments negative: * a ^ b = (~a ^ ~b) = (-a-1^-b-1) */ mp_neg(First, First); mp_sub_d(First, 1, First); mp_neg(Second, Second); mp_sub_d(Second, 1, Second); mp_xor(First, Second, &bigResult); break; } break; } mp_clear(&big1); mp_clear(&big2); BIG_RESULT(&bigResult); } #ifndef TCL_WIDE_INT_IS_LONG if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) { TclGetWideIntFromObj(NULL, valuePtr, &w1); TclGetWideIntFromObj(NULL, value2Ptr, &w2); switch (opcode) { case INST_BITAND: wResult = w1 & w2; break; case INST_BITOR: wResult = w1 | w2; break; case INST_BITXOR: wResult = w1 ^ w2; break; default: /* Unused, here to silence compiler warning. */ wResult = 0; } WIDE_RESULT(wResult); } #endif l1 = *((const long *)ptr1); l2 = *((const long *)ptr2); switch (opcode) { case INST_BITAND: lResult = l1 & l2; break; case INST_BITOR: lResult = l1 | l2; break; case INST_BITXOR: lResult = l1 ^ l2; break; default: /* Unused, here to silence compiler warning. */ lResult = 0; } LONG_RESULT(lResult); case INST_EXPON: { int oddExponent = 0, negativeExponent = 0; unsigned short base; if ((type1 == TCL_NUMBER_DOUBLE) || (type2 == TCL_NUMBER_DOUBLE)) { Tcl_GetDoubleFromObj(NULL, valuePtr, &d1); Tcl_GetDoubleFromObj(NULL, value2Ptr, &d2); if (d1==0.0 && d2<0.0) { return EXPONENT_OF_ZERO; } dResult = pow(d1, d2); goto doubleResult; } l1 = l2 = 0; if (type2 == TCL_NUMBER_LONG) { l2 = *((const long *) ptr2); if (l2 == 0) { /* * Anything to the zero power is 1. */ return constants[1]; } else if (l2 == 1) { /* * Anything to the first power is itself */ return NULL; } } switch (type2) { case TCL_NUMBER_LONG: negativeExponent = (l2 < 0); oddExponent = (int) (l2 & 1); break; #ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); negativeExponent = (w2 < 0); oddExponent = (int) (w2 & (Tcl_WideInt)1); break; #endif case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); negativeExponent = (mp_cmp_d(&big2, 0) == MP_LT); mp_mod_2d(&big2, 1, &big2); oddExponent = !mp_iszero(&big2); mp_clear(&big2); break; } if (type1 == TCL_NUMBER_LONG) { l1 = *((const long *)ptr1); } if (negativeExponent) { if (type1 == TCL_NUMBER_LONG) { switch (l1) { case 0: /* * Zero to a negative power is div by zero error. */ return EXPONENT_OF_ZERO; case -1: if (oddExponent) { LONG_RESULT(-1); } /* fallthrough */ case 1: /* * 1 to any power is 1. */ return constants[1]; } } /* * Integers with magnitude greater than 1 raise to a negative * power yield the answer zero (see TIP 123). */ return constants[0]; } if (type1 == TCL_NUMBER_LONG) { switch (l1) { case 0: /* * Zero to a positive power is zero. */ return constants[0]; case 1: /* * 1 to any power is 1. */ return constants[1]; case -1: if (!oddExponent) { return constants[1]; } LONG_RESULT(-1); } } /* * We refuse to accept exponent arguments that exceed one mp_digit * which means the max exponent value is 2**28-1 = 0x0fffffff = * 268435455, which fits into a signed 32 bit int which is within the * range of the long int type. This means any numeric Tcl_Obj value * not using TCL_NUMBER_LONG type must hold a value larger than we * accept. */ if (type2 != TCL_NUMBER_LONG) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "exponent too large", -1)); return GENERAL_ARITHMETIC_ERROR; } if (type1 == TCL_NUMBER_LONG) { if (l1 == 2) { /* * Reduce small powers of 2 to shifts. */ if ((unsigned long) l2 < CHAR_BIT * sizeof(long) - 1) { LONG_RESULT(1L << l2); } #if !defined(TCL_WIDE_INT_IS_LONG) if ((unsigned long)l2 < CHAR_BIT*sizeof(Tcl_WideInt) - 1) { WIDE_RESULT(((Tcl_WideInt) 1) << l2); } #endif goto overflowExpon; } if (l1 == -2) { int signum = oddExponent ? -1 : 1; /* * Reduce small powers of 2 to shifts. */ if ((unsigned long) l2 < CHAR_BIT * sizeof(long) - 1) { LONG_RESULT(signum * (1L << l2)); } #if !defined(TCL_WIDE_INT_IS_LONG) if ((unsigned long)l2 < CHAR_BIT*sizeof(Tcl_WideInt) - 1){ WIDE_RESULT(signum * (((Tcl_WideInt) 1) << l2)); } #endif goto overflowExpon; } #if (LONG_MAX == 0x7fffffff) if (l2 - 2 < (long)MaxBase32Size && l1 <= MaxBase32[l2 - 2] && l1 >= -MaxBase32[l2 - 2]) { /* * Small powers of 32-bit integers. */ lResult = l1 * l1; /* b**2 */ switch (l2) { case 2: break; case 3: lResult *= l1; /* b**3 */ break; case 4: lResult *= lResult; /* b**4 */ break; case 5: lResult *= lResult; /* b**4 */ lResult *= l1; /* b**5 */ break; case 6: lResult *= l1; /* b**3 */ lResult *= lResult; /* b**6 */ break; case 7: lResult *= l1; /* b**3 */ lResult *= lResult; /* b**6 */ lResult *= l1; /* b**7 */ break; case 8: lResult *= lResult; /* b**4 */ lResult *= lResult; /* b**8 */ break; } LONG_RESULT(lResult); } if (l1 - 3 >= 0 && l1 -2 < (long)Exp32IndexSize && l2 - 2 < (long)(Exp32ValueSize + MaxBase32Size)) { base = Exp32Index[l1 - 3] + (unsigned short) (l2 - 2 - MaxBase32Size); if (base < Exp32Index[l1 - 2]) { /* * 32-bit number raised to intermediate power, done by * table lookup. */ LONG_RESULT(Exp32Value[base]); } } if (-l1 - 3 >= 0 && -l1 - 2 < (long)Exp32IndexSize && l2 - 2 < (long)(Exp32ValueSize + MaxBase32Size)) { base = Exp32Index[-l1 - 3] + (unsigned short) (l2 - 2 - MaxBase32Size); if (base < Exp32Index[-l1 - 2]) { /* * 32-bit number raised to intermediate power, done by * table lookup. */ lResult = (oddExponent) ? -Exp32Value[base] : Exp32Value[base]; LONG_RESULT(lResult); } } #endif } #if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) if (type1 == TCL_NUMBER_LONG) { w1 = l1; #ifndef TCL_WIDE_INT_IS_LONG } else if (type1 == TCL_NUMBER_WIDE) { w1 = *((const Tcl_WideInt *) ptr1); #endif } else { goto overflowExpon; } if (l2 - 2 < (long)MaxBase64Size && w1 <= MaxBase64[l2 - 2] && w1 >= -MaxBase64[l2 - 2]) { /* * Small powers of integers whose result is wide. */ wResult = w1 * w1; /* b**2 */ switch (l2) { case 2: break; case 3: wResult *= l1; /* b**3 */ break; case 4: wResult *= wResult; /* b**4 */ break; case 5: wResult *= wResult; /* b**4 */ wResult *= w1; /* b**5 */ break; case 6: wResult *= w1; /* b**3 */ wResult *= wResult; /* b**6 */ break; case 7: wResult *= w1; /* b**3 */ wResult *= wResult; /* b**6 */ wResult *= w1; /* b**7 */ break; case 8: wResult *= wResult; /* b**4 */ wResult *= wResult; /* b**8 */ break; case 9: wResult *= wResult; /* b**4 */ wResult *= wResult; /* b**8 */ wResult *= w1; /* b**9 */ break; case 10: wResult *= wResult; /* b**4 */ wResult *= w1; /* b**5 */ wResult *= wResult; /* b**10 */ break; case 11: wResult *= wResult; /* b**4 */ wResult *= w1; /* b**5 */ wResult *= wResult; /* b**10 */ wResult *= w1; /* b**11 */ break; case 12: wResult *= w1; /* b**3 */ wResult *= wResult; /* b**6 */ wResult *= wResult; /* b**12 */ break; case 13: wResult *= w1; /* b**3 */ wResult *= wResult; /* b**6 */ wResult *= wResult; /* b**12 */ wResult *= w1; /* b**13 */ break; case 14: wResult *= w1; /* b**3 */ wResult *= wResult; /* b**6 */ wResult *= w1; /* b**7 */ wResult *= wResult; /* b**14 */ break; case 15: wResult *= w1; /* b**3 */ wResult *= wResult; /* b**6 */ wResult *= w1; /* b**7 */ wResult *= wResult; /* b**14 */ wResult *= w1; /* b**15 */ break; case 16: wResult *= wResult; /* b**4 */ wResult *= wResult; /* b**8 */ wResult *= wResult; /* b**16 */ break; } WIDE_RESULT(wResult); } /* * Handle cases of powers > 16 that still fit in a 64-bit word by * doing table lookup. */ if (w1 - 3 >= 0 && w1 - 2 < (long)Exp64IndexSize && l2 - 2 < (long)(Exp64ValueSize + MaxBase64Size)) { base = Exp64Index[w1 - 3] + (unsigned short) (l2 - 2 - MaxBase64Size); if (base < Exp64Index[w1 - 2]) { /* * 64-bit number raised to intermediate power, done by * table lookup. */ WIDE_RESULT(Exp64Value[base]); } } if (-w1 - 3 >= 0 && -w1 - 2 < (long)Exp64IndexSize && l2 - 2 < (long)(Exp64ValueSize + MaxBase64Size)) { base = Exp64Index[-w1 - 3] + (unsigned short) (l2 - 2 - MaxBase64Size); if (base < Exp64Index[-w1 - 2]) { /* * 64-bit number raised to intermediate power, done by * table lookup. */ wResult = oddExponent ? -Exp64Value[base] : Exp64Value[base]; WIDE_RESULT(wResult); } } #endif overflowExpon: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); if (big2.used > 1) { mp_clear(&big2); Tcl_SetObjResult(interp, Tcl_NewStringObj( "exponent too large", -1)); return GENERAL_ARITHMETIC_ERROR; } Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); mp_init(&bigResult); mp_expt_d(&big1, big2.dp[0], &bigResult); mp_clear(&big1); mp_clear(&big2); BIG_RESULT(&bigResult); } case INST_ADD: case INST_SUB: case INST_MULT: case INST_DIV: if ((type1 == TCL_NUMBER_DOUBLE) || (type2 == TCL_NUMBER_DOUBLE)) { /* * At least one of the values is floating-point, so perform * floating point calculations. */ Tcl_GetDoubleFromObj(NULL, valuePtr, &d1); Tcl_GetDoubleFromObj(NULL, value2Ptr, &d2); switch (opcode) { case INST_ADD: dResult = d1 + d2; break; case INST_SUB: dResult = d1 - d2; break; case INST_MULT: dResult = d1 * d2; break; case INST_DIV: #ifndef IEEE_FLOATING_POINT if (d2 == 0.0) { return DIVIDED_BY_ZERO; } #endif /* * We presume that we are running with zero-divide unmasked if * we're on an IEEE box. Otherwise, this statement might cause * demons to fly out our noses. */ dResult = d1 / d2; break; default: /* Unused, here to silence compiler warning. */ dResult = 0; } doubleResult: #ifndef ACCEPT_NAN /* * Check now for IEEE floating-point error. */ if (TclIsNaN(dResult)) { TclExprFloatError(interp, dResult); return GENERAL_ARITHMETIC_ERROR; } #endif DOUBLE_RESULT(dResult); } if ((type1 != TCL_NUMBER_BIG) && (type2 != TCL_NUMBER_BIG)) { TclGetWideIntFromObj(NULL, valuePtr, &w1); TclGetWideIntFromObj(NULL, value2Ptr, &w2); switch (opcode) { case INST_ADD: wResult = w1 + w2; #ifndef TCL_WIDE_INT_IS_LONG if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) #endif { /* * Check for overflow. */ if (Overflowing(w1, w2, wResult)) { goto overflowBasic; } } break; case INST_SUB: wResult = w1 - w2; #ifndef TCL_WIDE_INT_IS_LONG if ((type1 == TCL_NUMBER_WIDE) || (type2 == TCL_NUMBER_WIDE)) #endif { /* * Must check for overflow. The macro tests for overflows * in sums by looking at the sign bits. As we have a * subtraction here, we are adding -w2. As -w2 could in * turn overflow, we test with ~w2 instead: it has the * opposite sign bit to w2 so it does the job. Note that * the only "bad" case (w2==0) is irrelevant for this * macro, as in that case w1 and wResult have the same * sign and there is no overflow anyway. */ if (Overflowing(w1, ~w2, wResult)) { goto overflowBasic; } } break; case INST_MULT: if ((type1 != TCL_NUMBER_LONG) || (type2 != TCL_NUMBER_LONG) || (sizeof(Tcl_WideInt) < 2*sizeof(long))) { goto overflowBasic; } wResult = w1 * w2; break; case INST_DIV: if (w2 == 0) { return DIVIDED_BY_ZERO; } /* * Need a bignum to represent (LLONG_MIN / -1) */ if ((w1 == LLONG_MIN) && (w2 == -1)) { goto overflowBasic; } wResult = w1 / w2; /* * Force Tcl's integer division rules. * TODO: examine for logic simplification */ if (((wResult < 0) || ((wResult == 0) && ((w1 < 0 && w2 > 0) || (w1 > 0 && w2 < 0)))) && (wResult*w2 != w1)) { wResult -= 1; } break; default: /* * Unused, here to silence compiler warning. */ wResult = 0; } WIDE_RESULT(wResult); } overflowBasic: Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); mp_init(&bigResult); switch (opcode) { case INST_ADD: mp_add(&big1, &big2, &bigResult); break; case INST_SUB: mp_sub(&big1, &big2, &bigResult); break; case INST_MULT: mp_mul(&big1, &big2, &bigResult); break; case INST_DIV: if (mp_iszero(&big2)) { mp_clear(&big1); mp_clear(&big2); mp_clear(&bigResult); return DIVIDED_BY_ZERO; } mp_init(&bigRemainder); mp_div(&big1, &big2, &bigResult, &bigRemainder); /* TODO: internals intrusion */ if (!mp_iszero(&bigRemainder) && (bigRemainder.sign != big2.sign)) { /* * Convert to Tcl's integer division rules. */ mp_sub_d(&bigResult, 1, &bigResult); mp_add(&bigRemainder, &big2, &bigRemainder); } mp_clear(&bigRemainder); break; } mp_clear(&big1); mp_clear(&big2); BIG_RESULT(&bigResult); } Tcl_Panic("unexpected opcode"); return NULL; } static Tcl_Obj * ExecuteExtendedUnaryMathOp( int opcode, /* What operation to perform. */ Tcl_Obj *valuePtr) /* The operand on the stack. */ { ClientData ptr; int type; Tcl_WideInt w; mp_int big; Tcl_Obj *objResultPtr; (void) GetNumberFromObj(NULL, valuePtr, &ptr, &type); switch (opcode) { case INST_BITNOT: #ifndef TCL_WIDE_INT_IS_LONG if (type == TCL_NUMBER_WIDE) { w = *((const Tcl_WideInt *) ptr); WIDE_RESULT(~w); } #endif Tcl_TakeBignumFromObj(NULL, valuePtr, &big); /* ~a = - a - 1 */ mp_neg(&big, &big); mp_sub_d(&big, 1, &big); BIG_RESULT(&big); case INST_UMINUS: switch (type) { case TCL_NUMBER_DOUBLE: DOUBLE_RESULT(-(*((const double *) ptr))); case TCL_NUMBER_LONG: w = (Tcl_WideInt) (*((const long *) ptr)); if (w != LLONG_MIN) { WIDE_RESULT(-w); } TclBNInitBignumFromLong(&big, *(const long *) ptr); break; #ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w = *((const Tcl_WideInt *) ptr); if (w != LLONG_MIN) { WIDE_RESULT(-w); } TclBNInitBignumFromWideInt(&big, w); break; #endif default: Tcl_TakeBignumFromObj(NULL, valuePtr, &big); } mp_neg(&big, &big); BIG_RESULT(&big); } Tcl_Panic("unexpected opcode"); return NULL; } #undef LONG_RESULT #undef WIDE_RESULT #undef BIG_RESULT #undef DOUBLE_RESULT /* *---------------------------------------------------------------------- * * CompareTwoNumbers -- * * This function compares a pair of numbers in Tcl_Objs. Each argument * must already be known to be numeric and not NaN. * * Results: * One of MP_LT, MP_EQ or MP_GT, depending on whether valuePtr is less * than, equal to, or greater than value2Ptr (respectively). * * Side effects: * None, provided both values are numeric. * *---------------------------------------------------------------------- */ int TclCompareTwoNumbers( Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr) { int type1, type2, compare; ClientData ptr1, ptr2; mp_int big1, big2; double d1, d2, tmp; long l1, l2; #ifndef TCL_WIDE_INT_IS_LONG Tcl_WideInt w1, w2; #endif (void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1); (void) GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2); switch (type1) { case TCL_NUMBER_LONG: l1 = *((const long *)ptr1); switch (type2) { case TCL_NUMBER_LONG: l2 = *((const long *)ptr2); longCompare: return (l1 < l2) ? MP_LT : ((l1 > l2) ? MP_GT : MP_EQ); #ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); w1 = (Tcl_WideInt)l1; goto wideCompare; #endif case TCL_NUMBER_DOUBLE: d2 = *((const double *)ptr2); d1 = (double) l1; /* * If the double has a fractional part, or if the long can be * converted to double without loss of precision, then compare as * doubles. */ if (DBL_MANT_DIG > CHAR_BIT*sizeof(long) || l1 == (long) d1 || modf(d2, &tmp) != 0.0) { goto doubleCompare; } /* * Otherwise, to make comparision based on full precision, need to * convert the double to a suitably sized integer. * * Need this to get comparsions like * expr 20000000000000003 < 20000000000000004.0 * right. Converting the first argument to double will yield two * double values that are equivalent within double precision. * Converting the double to an integer gets done exactly, then * integer comparison can tell the difference. */ if (d2 < (double)LONG_MIN) { return MP_GT; } if (d2 > (double)LONG_MAX) { return MP_LT; } l2 = (long) d2; goto longCompare; case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); if (mp_cmp_d(&big2, 0) == MP_LT) { compare = MP_GT; } else { compare = MP_LT; } mp_clear(&big2); return compare; } #ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w1 = *((const Tcl_WideInt *)ptr1); switch (type2) { case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); wideCompare: return (w1 < w2) ? MP_LT : ((w1 > w2) ? MP_GT : MP_EQ); case TCL_NUMBER_LONG: l2 = *((const long *)ptr2); w2 = (Tcl_WideInt)l2; goto wideCompare; case TCL_NUMBER_DOUBLE: d2 = *((const double *)ptr2); d1 = (double) w1; if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt) || w1 == (Tcl_WideInt) d1 || modf(d2, &tmp) != 0.0) { goto doubleCompare; } if (d2 < (double)LLONG_MIN) { return MP_GT; } if (d2 > (double)LLONG_MAX) { return MP_LT; } w2 = (Tcl_WideInt) d2; goto wideCompare; case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); if (mp_cmp_d(&big2, 0) == MP_LT) { compare = MP_GT; } else { compare = MP_LT; } mp_clear(&big2); return compare; } #endif case TCL_NUMBER_DOUBLE: d1 = *((const double *)ptr1); switch (type2) { case TCL_NUMBER_DOUBLE: d2 = *((const double *)ptr2); doubleCompare: return (d1 < d2) ? MP_LT : ((d1 > d2) ? MP_GT : MP_EQ); case TCL_NUMBER_LONG: l2 = *((const long *)ptr2); d2 = (double) l2; if (DBL_MANT_DIG > CHAR_BIT*sizeof(long) || l2 == (long) d2 || modf(d1, &tmp) != 0.0) { goto doubleCompare; } if (d1 < (double)LONG_MIN) { return MP_LT; } if (d1 > (double)LONG_MAX) { return MP_GT; } l1 = (long) d1; goto longCompare; #ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); d2 = (double) w2; if (DBL_MANT_DIG > CHAR_BIT*sizeof(Tcl_WideInt) || w2 == (Tcl_WideInt) d2 || modf(d1, &tmp) != 0.0) { goto doubleCompare; } if (d1 < (double)LLONG_MIN) { return MP_LT; } if (d1 > (double)LLONG_MAX) { return MP_GT; } w1 = (Tcl_WideInt) d1; goto wideCompare; #endif case TCL_NUMBER_BIG: if (TclIsInfinite(d1)) { return (d1 > 0.0) ? MP_GT : MP_LT; } Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); if ((d1 < (double)LONG_MAX) && (d1 > (double)LONG_MIN)) { if (mp_cmp_d(&big2, 0) == MP_LT) { compare = MP_GT; } else { compare = MP_LT; } mp_clear(&big2); return compare; } if (DBL_MANT_DIG > CHAR_BIT*sizeof(long) && modf(d1, &tmp) != 0.0) { d2 = TclBignumToDouble(&big2); mp_clear(&big2); goto doubleCompare; } Tcl_InitBignumFromDouble(NULL, d1, &big1); goto bigCompare; } case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); switch (type2) { #ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: #endif case TCL_NUMBER_LONG: compare = mp_cmp_d(&big1, 0); mp_clear(&big1); return compare; case TCL_NUMBER_DOUBLE: d2 = *((const double *)ptr2); if (TclIsInfinite(d2)) { compare = (d2 > 0.0) ? MP_LT : MP_GT; mp_clear(&big1); return compare; } if ((d2 < (double)LONG_MAX) && (d2 > (double)LONG_MIN)) { compare = mp_cmp_d(&big1, 0); mp_clear(&big1); return compare; } if (DBL_MANT_DIG > CHAR_BIT*sizeof(long) && modf(d2, &tmp) != 0.0) { d1 = TclBignumToDouble(&big1); mp_clear(&big1); goto doubleCompare; } Tcl_InitBignumFromDouble(NULL, d2, &big2); goto bigCompare; case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); bigCompare: compare = mp_cmp(&big1, &big2); mp_clear(&big1); mp_clear(&big2); return compare; } default: Tcl_Panic("unexpected number type"); return TCL_ERROR; } } #ifdef TCL_COMPILE_DEBUG /* *---------------------------------------------------------------------- * * PrintByteCodeInfo -- * * This procedure prints a summary about a bytecode object to stdout. It * is called by TclNRExecuteByteCode when starting to execute the bytecode * object if tclTraceExec has the value 2 or more. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void PrintByteCodeInfo( register ByteCode *codePtr) /* The bytecode whose summary is printed to * stdout. */ { Proc *procPtr = codePtr->procPtr; Interp *iPtr = (Interp *) *codePtr->interpHandle; fprintf(stdout, "\nExecuting ByteCode 0x%p, refCt %u, epoch %u, interp 0x%p (epoch %u)\n", codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr, iPtr->compileEpoch); fprintf(stdout, " Source: "); TclPrintSource(stdout, codePtr->source, 60); fprintf(stdout, "\n Cmds %d, src %d, inst %u, litObjs %u, aux %d, stkDepth %u, code/src %.2f\n", codePtr->numCommands, codePtr->numSrcBytes, codePtr->numCodeBytes, codePtr->numLitObjects, codePtr->numAuxDataItems, codePtr->maxStackDepth, #ifdef TCL_COMPILE_STATS codePtr->numSrcBytes? ((float)codePtr->structureSize)/codePtr->numSrcBytes : #endif 0.0); #ifdef TCL_COMPILE_STATS fprintf(stdout, " Code %lu = header %lu+inst %d+litObj %lu+exc %lu+aux %lu+cmdMap %d\n", (unsigned long) codePtr->structureSize, (unsigned long) (sizeof(ByteCode)-sizeof(size_t)-sizeof(Tcl_Time)), codePtr->numCodeBytes, (unsigned long) (codePtr->numLitObjects * sizeof(Tcl_Obj *)), (unsigned long) (codePtr->numExceptRanges*sizeof(ExceptionRange)), (unsigned long) (codePtr->numAuxDataItems * sizeof(AuxData)), codePtr->numCmdLocBytes); #endif /* TCL_COMPILE_STATS */ if (procPtr != NULL) { fprintf(stdout, " Proc 0x%p, refCt %d, args %d, compiled locals %d\n", procPtr, procPtr->refCount, procPtr->numArgs, procPtr->numCompiledLocals); } } #endif /* TCL_COMPILE_DEBUG */ /* *---------------------------------------------------------------------- * * ValidatePcAndStackTop -- * * This procedure is called by TclNRExecuteByteCode when debugging to * verify that the program counter and stack top are valid during * execution. * * Results: * None. * * Side effects: * Prints a message to stderr and panics if either the pc or stack top * are invalid. * *---------------------------------------------------------------------- */ #ifdef TCL_COMPILE_DEBUG static void ValidatePcAndStackTop( register ByteCode *codePtr, /* The bytecode whose summary is printed to * stdout. */ const unsigned char *pc, /* Points to first byte of a bytecode * instruction. The program counter. */ int stackTop, /* Current stack top. Must be between * stackLowerBound and stackUpperBound * (inclusive). */ int checkStack) /* 0 if the stack depth check should be * skipped. */ { int stackUpperBound = codePtr->maxStackDepth; /* Greatest legal value for stackTop. */ unsigned relativePc = (unsigned) (pc - codePtr->codeStart); unsigned long codeStart = (unsigned long) codePtr->codeStart; unsigned long codeEnd = (unsigned long) (codePtr->codeStart + codePtr->numCodeBytes); unsigned char opCode = *pc; if (((unsigned long) pc < codeStart) || ((unsigned long) pc > codeEnd)) { fprintf(stderr, "\nBad instruction pc 0x%p in TclNRExecuteByteCode\n", pc); Tcl_Panic("TclNRExecuteByteCode execution failure: bad pc"); } if ((unsigned) opCode > LAST_INST_OPCODE) { fprintf(stderr, "\nBad opcode %d at pc %u in TclNRExecuteByteCode\n", (unsigned) opCode, relativePc); Tcl_Panic("TclNRExecuteByteCode execution failure: bad opcode"); } if (checkStack && ((stackTop < 0) || (stackTop > stackUpperBound))) { int numChars; const char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars, NULL, NULL); fprintf(stderr, "\nBad stack top %d at pc %u in TclNRExecuteByteCode (min 0, max %i)", stackTop, relativePc, stackUpperBound); if (cmd != NULL) { Tcl_Obj *message; TclNewLiteralStringObj(message, "\n executing "); Tcl_IncrRefCount(message); Tcl_AppendLimitedToObj(message, cmd, numChars, 100, NULL); fprintf(stderr,"%s\n", Tcl_GetString(message)); Tcl_DecrRefCount(message); } else { fprintf(stderr, "\n"); } Tcl_Panic("TclNRExecuteByteCode execution failure: bad stack top"); } } #endif /* TCL_COMPILE_DEBUG */ /* *---------------------------------------------------------------------- * * IllegalExprOperandType -- * * Used by TclNRExecuteByteCode to append an error message to the interp * result when an illegal operand type is detected by an expression * instruction. The argument opndPtr holds the operand object in error. * * Results: * None. * * Side effects: * An error message is appended to the interp result. * *---------------------------------------------------------------------- */ static void IllegalExprOperandType( Tcl_Interp *interp, /* Interpreter to which error information * pertains. */ const unsigned char *pc, /* Points to the instruction being executed * when the illegal type was found. */ Tcl_Obj *opndPtr) /* Points to the operand holding the value * with the illegal type. */ { ClientData ptr; int type; const unsigned char opcode = *pc; const char *description, *operator = "unknown"; if (opcode == INST_EXPON) { operator = "**"; } else if (opcode <= INST_LNOT) { operator = operatorStrings[opcode - INST_LOR]; } if (GetNumberFromObj(NULL, opndPtr, &ptr, &type) != TCL_OK) { int numBytes; const char *bytes = Tcl_GetStringFromObj(opndPtr, &numBytes); if (numBytes == 0) { description = "empty string"; } else if (TclCheckBadOctal(NULL, bytes)) { description = "invalid octal number"; } else { description = "non-numeric string"; } } else if (type == TCL_NUMBER_NAN) { description = "non-numeric floating-point value"; } else if (type == TCL_NUMBER_DOUBLE) { description = "floating-point value"; } else { /* TODO: No caller needs this. Eliminate? */ description = "(big) integer"; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't use %s as operand of \"%s\"", description, operator)); Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description, NULL); } /* *---------------------------------------------------------------------- * * TclGetSrcInfoForPc, GetSrcInfoForPc, TclGetSourceFromFrame -- * * Given a program counter value, finds the closest command in the * bytecode code unit's CmdLocation array and returns information about * that command's source: a pointer to its first byte and the number of * characters. * * Results: * If a command is found that encloses the program counter value, a * pointer to the command's source is returned and the length of the * source is stored at *lengthPtr. If multiple commands resulted in code * at pc, information about the closest enclosing command is returned. If * no matching command is found, NULL is returned and *lengthPtr is * unchanged. * * Side effects: * The CmdFrame at *cfPtr is updated. * *---------------------------------------------------------------------- */ Tcl_Obj * TclGetSourceFromFrame( CmdFrame *cfPtr, int objc, Tcl_Obj *const objv[]) { if (cfPtr == NULL) { return Tcl_NewListObj(objc, objv); } if (cfPtr->cmdObj == NULL) { if (cfPtr->cmd == NULL) { ByteCode *codePtr = (ByteCode *) cfPtr->data.tebc.codePtr; cfPtr->cmd = GetSrcInfoForPc((unsigned char *) cfPtr->data.tebc.pc, codePtr, &cfPtr->len, NULL, NULL); } if (cfPtr->cmd) { cfPtr->cmdObj = Tcl_NewStringObj(cfPtr->cmd, cfPtr->len); } else { cfPtr->cmdObj = Tcl_NewListObj(objc, objv); } Tcl_IncrRefCount(cfPtr->cmdObj); } return cfPtr->cmdObj; } void TclGetSrcInfoForPc( CmdFrame *cfPtr) { ByteCode *codePtr = (ByteCode *) cfPtr->data.tebc.codePtr; assert(cfPtr->type == TCL_LOCATION_BC); if (cfPtr->cmd == NULL) { cfPtr->cmd = GetSrcInfoForPc( (unsigned char *) cfPtr->data.tebc.pc, codePtr, &cfPtr->len, NULL, NULL); } if (cfPtr->cmd != NULL) { /* * We now have the command. We can get the srcOffset back and from * there find the list of word locations for this command. */ ExtCmdLoc *eclPtr; ECL *locPtr = NULL; int srcOffset, i; Interp *iPtr = (Interp *) *codePtr->interpHandle; Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr); if (!hePtr) { return; } srcOffset = cfPtr->cmd - codePtr->source; eclPtr = Tcl_GetHashValue(hePtr); for (i=0; i < eclPtr->nuloc; i++) { if (eclPtr->loc[i].srcOffset == srcOffset) { locPtr = eclPtr->loc+i; break; } } if (locPtr == NULL) { Tcl_Panic("LocSearch failure"); } cfPtr->line = locPtr->line; cfPtr->nline = locPtr->nline; cfPtr->type = eclPtr->type; if (eclPtr->type == TCL_LOCATION_SOURCE) { cfPtr->data.eval.path = eclPtr->path; Tcl_IncrRefCount(cfPtr->data.eval.path); } /* * Do not set cfPtr->data.eval.path NULL for non-SOURCE. Needed for * cfPtr->data.tebc.codePtr. */ } } static const char * GetSrcInfoForPc( const unsigned char *pc, /* The program counter value for which to * return the closest command's source info. * This points within a bytecode instruction * in codePtr's code. */ ByteCode *codePtr, /* The bytecode sequence in which to look up * the command source for the pc. */ int *lengthPtr, /* If non-NULL, the location where the length * of the command's source should be stored. * If NULL, no length is stored. */ const unsigned char **pcBeg,/* If non-NULL, the bytecode location * where the current instruction starts. * If NULL; no pointer is stored. */ int *cmdIdxPtr) /* If non-NULL, the location where the index * of the command containing the pc should * be stored. */ { register int pcOffset = (pc - codePtr->codeStart); int numCmds = codePtr->numCommands; unsigned char *codeDeltaNext, *codeLengthNext; unsigned char *srcDeltaNext, *srcLengthNext; int codeOffset, codeLen, codeEnd, srcOffset, srcLen, delta, i; int bestDist = INT_MAX; /* Distance of pc to best cmd's start pc. */ int bestSrcOffset = -1; /* Initialized to avoid compiler warning. */ int bestSrcLength = -1; /* Initialized to avoid compiler warning. */ int bestCmdIdx = -1; /* The pc must point within the bytecode */ assert ((pcOffset >= 0) && (pcOffset < codePtr->numCodeBytes)); /* * Decode the code and source offset and length for each command. The * closest enclosing command is the last one whose code started before * pcOffset. */ codeDeltaNext = codePtr->codeDeltaStart; codeLengthNext = codePtr->codeLengthStart; srcDeltaNext = codePtr->srcDeltaStart; srcLengthNext = codePtr->srcLengthStart; codeOffset = srcOffset = 0; for (i = 0; i < numCmds; i++) { if ((unsigned) *codeDeltaNext == (unsigned) 0xFF) { codeDeltaNext++; delta = TclGetInt4AtPtr(codeDeltaNext); codeDeltaNext += 4; } else { delta = TclGetInt1AtPtr(codeDeltaNext); codeDeltaNext++; } codeOffset += delta; if ((unsigned) *codeLengthNext == (unsigned) 0xFF) { codeLengthNext++; codeLen = TclGetInt4AtPtr(codeLengthNext); codeLengthNext += 4; } else { codeLen = TclGetInt1AtPtr(codeLengthNext); codeLengthNext++; } codeEnd = (codeOffset + codeLen - 1); if ((unsigned) *srcDeltaNext == (unsigned) 0xFF) { srcDeltaNext++; delta = TclGetInt4AtPtr(srcDeltaNext); srcDeltaNext += 4; } else { delta = TclGetInt1AtPtr(srcDeltaNext); srcDeltaNext++; } srcOffset += delta; if ((unsigned) *srcLengthNext == (unsigned) 0xFF) { srcLengthNext++; srcLen = TclGetInt4AtPtr(srcLengthNext); srcLengthNext += 4; } else { srcLen = TclGetInt1AtPtr(srcLengthNext); srcLengthNext++; } if (codeOffset > pcOffset) { /* Best cmd already found */ break; } if (pcOffset <= codeEnd) { /* This cmd's code encloses pc */ int dist = (pcOffset - codeOffset); if (dist <= bestDist) { bestDist = dist; bestSrcOffset = srcOffset; bestSrcLength = srcLen; bestCmdIdx = i; } } } if (pcBeg != NULL) { const unsigned char *curr, *prev; /* * Walk from beginning of command or BC to pc, by complete * instructions. Stop when crossing pc; keep previous. */ curr = ((bestDist == INT_MAX) ? codePtr->codeStart : pc - bestDist); prev = curr; while (curr <= pc) { prev = curr; curr += tclInstructionTable[*curr].numBytes; } *pcBeg = prev; } if (bestDist == INT_MAX) { return NULL; } if (lengthPtr != NULL) { *lengthPtr = bestSrcLength; } if (cmdIdxPtr != NULL) { *cmdIdxPtr = bestCmdIdx; } return (codePtr->source + bestSrcOffset); } /* *---------------------------------------------------------------------- * * GetExceptRangeForPc -- * * Given a program counter value, return the closest enclosing * ExceptionRange. * * Results: * If the searchMode is TCL_ERROR, this procedure ignores loop exception * ranges and returns a pointer to the closest catch range. If the * searchMode is TCL_BREAK, this procedure returns a pointer to the most * closely enclosing ExceptionRange regardless of whether it is a loop or * catch exception range. If the searchMode is TCL_CONTINUE, this * procedure returns a pointer to the most closely enclosing * ExceptionRange (of any type) skipping only loop exception ranges if * they don't have a sensible continueOffset defined. If no matching * ExceptionRange is found that encloses pc, a NULL is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ static ExceptionRange * GetExceptRangeForPc( const unsigned char *pc, /* The program counter value for which to * search for a closest enclosing exception * range. This points to a bytecode * instruction in codePtr's code. */ int searchMode, /* If TCL_BREAK, consider either loop or catch * ExceptionRanges in search. If TCL_ERROR * consider only catch ranges (and ignore any * closer loop ranges). If TCL_CONTINUE, look * for loop ranges that define a continue * point or a catch range. */ ByteCode *codePtr) /* Points to the ByteCode in which to search * for the enclosing ExceptionRange. */ { ExceptionRange *rangeArrayPtr; int numRanges = codePtr->numExceptRanges; register ExceptionRange *rangePtr; int pcOffset = pc - codePtr->codeStart; register int start; if (numRanges == 0) { return NULL; } /* * This exploits peculiarities of our compiler: nested ranges are always * *after* their containing ranges, so that by scanning backwards we are * sure that the first matching range is indeed the deepest. */ rangeArrayPtr = codePtr->exceptArrayPtr; rangePtr = rangeArrayPtr + numRanges; while (--rangePtr >= rangeArrayPtr) { start = rangePtr->codeOffset; if ((start <= pcOffset) && (pcOffset < (start + rangePtr->numCodeBytes))) { if (rangePtr->type == CATCH_EXCEPTION_RANGE) { return rangePtr; } if (searchMode == TCL_BREAK) { return rangePtr; } if (searchMode == TCL_CONTINUE && rangePtr->continueOffset != -1){ return rangePtr; } } } return NULL; } /* *---------------------------------------------------------------------- * * GetOpcodeName -- * * This procedure is called by the TRACE and TRACE_WITH_OBJ macros used * in TclNRExecuteByteCode when debugging. It returns the name of the * bytecode instruction at a specified instruction pc. * * Results: * A character string for the instruction. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef TCL_COMPILE_DEBUG static const char * GetOpcodeName( const unsigned char *pc) /* Points to the instruction whose name should * be returned. */ { unsigned char opCode = *pc; return tclInstructionTable[opCode].name; } #endif /* TCL_COMPILE_DEBUG */ /* *---------------------------------------------------------------------- * * TclExprFloatError -- * * This procedure is called when an error occurs during a floating-point * operation. It reads errno and sets interp->objResultPtr accordingly. * * Results: * interp->objResultPtr is set to hold an error message. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclExprFloatError( Tcl_Interp *interp, /* Where to store error message. */ double value) /* Value returned after error; used to * distinguish underflows from overflows. */ { const char *s; if ((errno == EDOM) || TclIsNaN(value)) { s = "domain error: argument not in valid range"; Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1)); Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, NULL); } else if ((errno == ERANGE) || TclIsInfinite(value)) { if (value == 0.0) { s = "floating-point value too small to represent"; Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1)); Tcl_SetErrorCode(interp, "ARITH", "UNDERFLOW", s, NULL); } else { s = "floating-point value too large to represent"; Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1)); Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW", s, NULL); } } else { Tcl_Obj *objPtr = Tcl_ObjPrintf( "unknown floating-point error, errno = %d", errno); Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN", Tcl_GetString(objPtr), NULL); Tcl_SetObjResult(interp, objPtr); } } #ifdef TCL_COMPILE_STATS /* *---------------------------------------------------------------------- * * TclLog2 -- * * Procedure used while collecting compilation statistics to determine * the log base 2 of an integer. * * Results: * Returns the log base 2 of the operand. If the argument is less than or * equal to zero, a zero is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclLog2( register int value) /* The integer for which to compute the log * base 2. */ { register int n = value; register int result = 0; while (n > 1) { n = n >> 1; result++; } return result; } /* *---------------------------------------------------------------------- * * EvalStatsCmd -- * * Implements the "evalstats" command that prints instruction execution * counts to stdout. * * Results: * Standard Tcl results. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int EvalStatsCmd( ClientData unused, /* Unused. */ Tcl_Interp *interp, /* The current interpreter. */ int objc, /* The number of arguments. */ Tcl_Obj *const objv[]) /* The argument strings. */ { Interp *iPtr = (Interp *) interp; LiteralTable *globalTablePtr = &iPtr->literalTable; ByteCodeStats *statsPtr = &iPtr->stats; double totalCodeBytes, currentCodeBytes; double totalLiteralBytes, currentLiteralBytes; double objBytesIfUnshared, strBytesIfUnshared, sharingBytesSaved; double strBytesSharedMultX, strBytesSharedOnce; double numInstructions, currentHeaderBytes; long numCurrentByteCodes, numByteCodeLits; long refCountSum, literalMgmtBytes, sum; int numSharedMultX, numSharedOnce; int decadeHigh, minSizeDecade, maxSizeDecade, length, i; char *litTableStats; LiteralEntry *entryPtr; Tcl_Obj *objPtr; #define Percent(a,b) ((a) * 100.0 / (b)) objPtr = Tcl_NewObj(); Tcl_IncrRefCount(objPtr); numInstructions = 0.0; for (i = 0; i < 256; i++) { if (statsPtr->instructionCount[i] != 0) { numInstructions += statsPtr->instructionCount[i]; } } totalLiteralBytes = sizeof(LiteralTable) + iPtr->literalTable.numBuckets * sizeof(LiteralEntry *) + (statsPtr->numLiteralsCreated * sizeof(LiteralEntry)) + (statsPtr->numLiteralsCreated * sizeof(Tcl_Obj)) + statsPtr->totalLitStringBytes; totalCodeBytes = statsPtr->totalByteCodeBytes + totalLiteralBytes; numCurrentByteCodes = statsPtr->numCompilations - statsPtr->numByteCodesFreed; currentHeaderBytes = numCurrentByteCodes * (sizeof(ByteCode) - sizeof(size_t) - sizeof(Tcl_Time)); literalMgmtBytes = sizeof(LiteralTable) + (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)) + (iPtr->literalTable.numEntries * sizeof(LiteralEntry)); currentLiteralBytes = literalMgmtBytes + iPtr->literalTable.numEntries * sizeof(Tcl_Obj) + statsPtr->currentLitStringBytes; currentCodeBytes = statsPtr->currentByteCodeBytes + currentLiteralBytes; /* * Summary statistics, total and current source and ByteCode sizes. */ Tcl_AppendPrintfToObj(objPtr, "\n----------------------------------------------------------------\n"); Tcl_AppendPrintfToObj(objPtr, "Compilation and execution statistics for interpreter %#lx\n", (long int)iPtr); Tcl_AppendPrintfToObj(objPtr, "\nNumber ByteCodes executed\t%ld\n", statsPtr->numExecutions); Tcl_AppendPrintfToObj(objPtr, "Number ByteCodes compiled\t%ld\n", statsPtr->numCompilations); Tcl_AppendPrintfToObj(objPtr, " Mean executions/compile\t%.1f\n", statsPtr->numExecutions / (float)statsPtr->numCompilations); Tcl_AppendPrintfToObj(objPtr, "\nInstructions executed\t\t%.0f\n", numInstructions); Tcl_AppendPrintfToObj(objPtr, " Mean inst/compile\t\t%.0f\n", numInstructions / statsPtr->numCompilations); Tcl_AppendPrintfToObj(objPtr, " Mean inst/execution\t\t%.0f\n", numInstructions / statsPtr->numExecutions); Tcl_AppendPrintfToObj(objPtr, "\nTotal ByteCodes\t\t\t%ld\n", statsPtr->numCompilations); Tcl_AppendPrintfToObj(objPtr, " Source bytes\t\t\t%.6g\n", statsPtr->totalSrcBytes); Tcl_AppendPrintfToObj(objPtr, " Code bytes\t\t\t%.6g\n", totalCodeBytes); Tcl_AppendPrintfToObj(objPtr, " ByteCode bytes\t\t%.6g\n", statsPtr->totalByteCodeBytes); Tcl_AppendPrintfToObj(objPtr, " Literal bytes\t\t%.6g\n", totalLiteralBytes); Tcl_AppendPrintfToObj(objPtr, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n", (unsigned long) sizeof(LiteralTable), (unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)), (unsigned long) (statsPtr->numLiteralsCreated * sizeof(LiteralEntry)), (unsigned long) (statsPtr->numLiteralsCreated * sizeof(Tcl_Obj)), statsPtr->totalLitStringBytes); Tcl_AppendPrintfToObj(objPtr, " Mean code/compile\t\t%.1f\n", totalCodeBytes / statsPtr->numCompilations); Tcl_AppendPrintfToObj(objPtr, " Mean code/source\t\t%.1f\n", totalCodeBytes / statsPtr->totalSrcBytes); Tcl_AppendPrintfToObj(objPtr, "\nCurrent (active) ByteCodes\t%ld\n", numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, " Source bytes\t\t\t%.6g\n", statsPtr->currentSrcBytes); Tcl_AppendPrintfToObj(objPtr, " Code bytes\t\t\t%.6g\n", currentCodeBytes); Tcl_AppendPrintfToObj(objPtr, " ByteCode bytes\t\t%.6g\n", statsPtr->currentByteCodeBytes); Tcl_AppendPrintfToObj(objPtr, " Literal bytes\t\t%.6g\n", currentLiteralBytes); Tcl_AppendPrintfToObj(objPtr, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n", (unsigned long) sizeof(LiteralTable), (unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)), (unsigned long) (iPtr->literalTable.numEntries * sizeof(LiteralEntry)), (unsigned long) (iPtr->literalTable.numEntries * sizeof(Tcl_Obj)), statsPtr->currentLitStringBytes); Tcl_AppendPrintfToObj(objPtr, " Mean code/source\t\t%.1f\n", currentCodeBytes / statsPtr->currentSrcBytes); Tcl_AppendPrintfToObj(objPtr, " Code + source bytes\t\t%.6g (%0.1f mean code/src)\n", (currentCodeBytes + statsPtr->currentSrcBytes), (currentCodeBytes / statsPtr->currentSrcBytes) + 1.0); /* * Tcl_IsShared statistics check * * This gives the refcount of each obj as Tcl_IsShared was called for it. * Shared objects must be duplicated before they can be modified. */ numSharedMultX = 0; Tcl_AppendPrintfToObj(objPtr, "\nTcl_IsShared object check (all objects):\n"); Tcl_AppendPrintfToObj(objPtr, " Object had refcount <=1 (not shared)\t%ld\n", tclObjsShared[1]); for (i = 2; i < TCL_MAX_SHARED_OBJ_STATS; i++) { Tcl_AppendPrintfToObj(objPtr, " refcount ==%d\t\t%ld\n", i, tclObjsShared[i]); numSharedMultX += tclObjsShared[i]; } Tcl_AppendPrintfToObj(objPtr, " refcount >=%d\t\t%ld\n", i, tclObjsShared[0]); numSharedMultX += tclObjsShared[0]; Tcl_AppendPrintfToObj(objPtr, " Total shared objects\t\t\t%d\n", numSharedMultX); /* * Literal table statistics. */ numByteCodeLits = 0; refCountSum = 0; numSharedMultX = 0; numSharedOnce = 0; objBytesIfUnshared = 0.0; strBytesIfUnshared = 0.0; strBytesSharedMultX = 0.0; strBytesSharedOnce = 0.0; for (i = 0; i < globalTablePtr->numBuckets; i++) { for (entryPtr = globalTablePtr->buckets[i]; entryPtr != NULL; entryPtr = entryPtr->nextPtr) { if (entryPtr->objPtr->typePtr == &tclByteCodeType) { numByteCodeLits++; } (void) Tcl_GetStringFromObj(entryPtr->objPtr, &length); refCountSum += entryPtr->refCount; objBytesIfUnshared += (entryPtr->refCount * sizeof(Tcl_Obj)); strBytesIfUnshared += (entryPtr->refCount * (length+1)); if (entryPtr->refCount > 1) { numSharedMultX++; strBytesSharedMultX += (length+1); } else { numSharedOnce++; strBytesSharedOnce += (length+1); } } } sharingBytesSaved = (objBytesIfUnshared + strBytesIfUnshared) - currentLiteralBytes; Tcl_AppendPrintfToObj(objPtr, "\nTotal objects (all interps)\t%ld\n", tclObjsAlloced); Tcl_AppendPrintfToObj(objPtr, "Current objects\t\t\t%ld\n", (tclObjsAlloced - tclObjsFreed)); Tcl_AppendPrintfToObj(objPtr, "Total literal objects\t\t%ld\n", statsPtr->numLiteralsCreated); Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal objects\t\t%d (%0.1f%% of current objects)\n", globalTablePtr->numEntries, Percent(globalTablePtr->numEntries, tclObjsAlloced-tclObjsFreed)); Tcl_AppendPrintfToObj(objPtr, " ByteCode literals\t\t%ld (%0.1f%% of current literals)\n", numByteCodeLits, Percent(numByteCodeLits, globalTablePtr->numEntries)); Tcl_AppendPrintfToObj(objPtr, " Literals reused > 1x\t\t%d\n", numSharedMultX); Tcl_AppendPrintfToObj(objPtr, " Mean reference count\t\t%.2f\n", ((double) refCountSum) / globalTablePtr->numEntries); Tcl_AppendPrintfToObj(objPtr, " Mean len, str reused >1x \t%.2f\n", (numSharedMultX ? strBytesSharedMultX/numSharedMultX : 0.0)); Tcl_AppendPrintfToObj(objPtr, " Mean len, str used 1x\t\t%.2f\n", (numSharedOnce ? strBytesSharedOnce/numSharedOnce : 0.0)); Tcl_AppendPrintfToObj(objPtr, " Total sharing savings\t\t%.6g (%0.1f%% of bytes if no sharing)\n", sharingBytesSaved, Percent(sharingBytesSaved, objBytesIfUnshared+strBytesIfUnshared)); Tcl_AppendPrintfToObj(objPtr, " Bytes with sharing\t\t%.6g\n", currentLiteralBytes); Tcl_AppendPrintfToObj(objPtr, " table %lu + bkts %lu + entries %lu + objects %lu + strings %.6g\n", (unsigned long) sizeof(LiteralTable), (unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)), (unsigned long) (iPtr->literalTable.numEntries * sizeof(LiteralEntry)), (unsigned long) (iPtr->literalTable.numEntries * sizeof(Tcl_Obj)), statsPtr->currentLitStringBytes); Tcl_AppendPrintfToObj(objPtr, " Bytes if no sharing\t\t%.6g = objects %.6g + strings %.6g\n", (objBytesIfUnshared + strBytesIfUnshared), objBytesIfUnshared, strBytesIfUnshared); Tcl_AppendPrintfToObj(objPtr, " String sharing savings \t%.6g = unshared %.6g - shared %.6g\n", (strBytesIfUnshared - statsPtr->currentLitStringBytes), strBytesIfUnshared, statsPtr->currentLitStringBytes); Tcl_AppendPrintfToObj(objPtr, " Literal mgmt overhead\t\t%ld (%0.1f%% of bytes with sharing)\n", literalMgmtBytes, Percent(literalMgmtBytes, currentLiteralBytes)); Tcl_AppendPrintfToObj(objPtr, " table %lu + buckets %lu + entries %lu\n", (unsigned long) sizeof(LiteralTable), (unsigned long) (iPtr->literalTable.numBuckets * sizeof(LiteralEntry *)), (unsigned long) (iPtr->literalTable.numEntries * sizeof(LiteralEntry))); /* * Breakdown of current ByteCode space requirements. */ Tcl_AppendPrintfToObj(objPtr, "\nBreakdown of current ByteCode requirements:\n"); Tcl_AppendPrintfToObj(objPtr, " Bytes Pct of Avg per\n"); Tcl_AppendPrintfToObj(objPtr, " total ByteCode\n"); Tcl_AppendPrintfToObj(objPtr, "Total %12.6g 100.00%% %8.1f\n", statsPtr->currentByteCodeBytes, statsPtr->currentByteCodeBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Header %12.6g %8.1f%% %8.1f\n", currentHeaderBytes, Percent(currentHeaderBytes, statsPtr->currentByteCodeBytes), currentHeaderBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Instructions %12.6g %8.1f%% %8.1f\n", statsPtr->currentInstBytes, Percent(statsPtr->currentInstBytes,statsPtr->currentByteCodeBytes), statsPtr->currentInstBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Literal ptr array %12.6g %8.1f%% %8.1f\n", statsPtr->currentLitBytes, Percent(statsPtr->currentLitBytes,statsPtr->currentByteCodeBytes), statsPtr->currentLitBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Exception table %12.6g %8.1f%% %8.1f\n", statsPtr->currentExceptBytes, Percent(statsPtr->currentExceptBytes,statsPtr->currentByteCodeBytes), statsPtr->currentExceptBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Auxiliary data %12.6g %8.1f%% %8.1f\n", statsPtr->currentAuxBytes, Percent(statsPtr->currentAuxBytes,statsPtr->currentByteCodeBytes), statsPtr->currentAuxBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Command map %12.6g %8.1f%% %8.1f\n", statsPtr->currentCmdMapBytes, Percent(statsPtr->currentCmdMapBytes,statsPtr->currentByteCodeBytes), statsPtr->currentCmdMapBytes / numCurrentByteCodes); /* * Detailed literal statistics. */ Tcl_AppendPrintfToObj(objPtr, "\nLiteral string sizes:\n"); Tcl_AppendPrintfToObj(objPtr, "\t Up to length\t\tPercentage\n"); maxSizeDecade = 0; for (i = 31; i >= 0; i--) { if (statsPtr->literalCount[i] > 0) { maxSizeDecade = i; break; } } sum = 0; for (i = 0; i <= maxSizeDecade; i++) { decadeHigh = (1 << (i+1)) - 1; sum += statsPtr->literalCount[i]; Tcl_AppendPrintfToObj(objPtr, "\t%10d\t\t%8.0f%%\n", decadeHigh, Percent(sum, statsPtr->numLiteralsCreated)); } litTableStats = TclLiteralStats(globalTablePtr); Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal table statistics:\n%s\n", litTableStats); ckfree(litTableStats); /* * Source and ByteCode size distributions. */ Tcl_AppendPrintfToObj(objPtr, "\nSource sizes:\n"); Tcl_AppendPrintfToObj(objPtr, "\t Up to size\t\tPercentage\n"); minSizeDecade = maxSizeDecade = 0; for (i = 0; i < 31; i++) { if (statsPtr->srcCount[i] > 0) { minSizeDecade = i; break; } } for (i = 31; i >= 0; i--) { if (statsPtr->srcCount[i] > 0) { maxSizeDecade = i; break; } } sum = 0; for (i = minSizeDecade; i <= maxSizeDecade; i++) { decadeHigh = (1 << (i+1)) - 1; sum += statsPtr->srcCount[i]; Tcl_AppendPrintfToObj(objPtr, "\t%10d\t\t%8.0f%%\n", decadeHigh, Percent(sum, statsPtr->numCompilations)); } Tcl_AppendPrintfToObj(objPtr, "\nByteCode sizes:\n"); Tcl_AppendPrintfToObj(objPtr, "\t Up to size\t\tPercentage\n"); minSizeDecade = maxSizeDecade = 0; for (i = 0; i < 31; i++) { if (statsPtr->byteCodeCount[i] > 0) { minSizeDecade = i; break; } } for (i = 31; i >= 0; i--) { if (statsPtr->byteCodeCount[i] > 0) { maxSizeDecade = i; break; } } sum = 0; for (i = minSizeDecade; i <= maxSizeDecade; i++) { decadeHigh = (1 << (i+1)) - 1; sum += statsPtr->byteCodeCount[i]; Tcl_AppendPrintfToObj(objPtr, "\t%10d\t\t%8.0f%%\n", decadeHigh, Percent(sum, statsPtr->numCompilations)); } Tcl_AppendPrintfToObj(objPtr, "\nByteCode longevity (excludes Current ByteCodes):\n"); Tcl_AppendPrintfToObj(objPtr, "\t Up to ms\t\tPercentage\n"); minSizeDecade = maxSizeDecade = 0; for (i = 0; i < 31; i++) { if (statsPtr->lifetimeCount[i] > 0) { minSizeDecade = i; break; } } for (i = 31; i >= 0; i--) { if (statsPtr->lifetimeCount[i] > 0) { maxSizeDecade = i; break; } } sum = 0; for (i = minSizeDecade; i <= maxSizeDecade; i++) { decadeHigh = (1 << (i+1)) - 1; sum += statsPtr->lifetimeCount[i]; Tcl_AppendPrintfToObj(objPtr, "\t%12.3f\t\t%8.0f%%\n", decadeHigh/1000.0, Percent(sum, statsPtr->numByteCodesFreed)); } /* * Instruction counts. */ Tcl_AppendPrintfToObj(objPtr, "\nInstruction counts:\n"); for (i = 0; i <= LAST_INST_OPCODE; i++) { Tcl_AppendPrintfToObj(objPtr, "%20s %8ld ", tclInstructionTable[i].name, statsPtr->instructionCount[i]); if (statsPtr->instructionCount[i]) { Tcl_AppendPrintfToObj(objPtr, "%6.1f%%\n", Percent(statsPtr->instructionCount[i], numInstructions)); } else { Tcl_AppendPrintfToObj(objPtr, "0\n"); } } #ifdef TCL_MEM_DEBUG Tcl_AppendPrintfToObj(objPtr, "\nHeap Statistics:\n"); TclDumpMemoryInfo((ClientData) objPtr, 1); #endif Tcl_AppendPrintfToObj(objPtr, "\n----------------------------------------------------------------\n"); if (objc == 1) { Tcl_SetObjResult(interp, objPtr); } else { Tcl_Channel outChan; char *str = Tcl_GetStringFromObj(objv[1], &length); if (length) { if (strcmp(str, "stdout") == 0) { outChan = Tcl_GetStdChannel(TCL_STDOUT); } else if (strcmp(str, "stderr") == 0) { outChan = Tcl_GetStdChannel(TCL_STDERR); } else { outChan = Tcl_OpenFileChannel(NULL, str, "w", 0664); } } else { outChan = Tcl_GetStdChannel(TCL_STDOUT); } if (outChan != NULL) { Tcl_WriteObj(outChan, objPtr); } } Tcl_DecrRefCount(objPtr); return TCL_OK; } #endif /* TCL_COMPILE_STATS */ #ifdef TCL_COMPILE_DEBUG /* *---------------------------------------------------------------------- * * StringForResultCode -- * * Procedure that returns a human-readable string representing a Tcl * result code such as TCL_ERROR. * * Results: * If the result code is one of the standard Tcl return codes, the result * is a string representing that code such as "TCL_ERROR". Otherwise, the * result string is that code formatted as a sequence of decimal digit * characters. Note that the resulting string must not be modified by the * caller. * * Side effects: * None. * *---------------------------------------------------------------------- */ static const char * StringForResultCode( int result) /* The Tcl result code for which to generate a * string. */ { static char buf[TCL_INTEGER_SPACE]; if ((result >= TCL_OK) && (result <= TCL_CONTINUE)) { return resultStrings[result]; } TclFormatInt(buf, result); return buf; } #endif /* TCL_COMPILE_DEBUG */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclIOUtil.c0000644000175000017500000041231712663660065015227 0ustar sergeisergei/* * tclIOUtil.c -- * * This file contains the implementation of Tcl's generic filesystem * code, which supports a pluggable filesystem architecture allowing both * platform specific filesystems and 'virtual filesystems'. All * filesystem access should go through the functions defined in this * file. Most of this code was contributed by Vince Darley. * * Parts of this file are based on code contributed by Karl Lehenbauer, * Mark Diekhans and Peter da Silva. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 2001-2004 Vincent Darley. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #ifdef _WIN32 # include "tclWinInt.h" #endif #include "tclFileSystem.h" #ifdef TCL_TEMPLOAD_NO_UNLINK #ifndef NO_FSTATFS #include #endif #endif /* * struct FilesystemRecord -- * * A filesystem record is used to keep track of each filesystem currently * registered with the core, in a linked list. */ typedef struct FilesystemRecord { ClientData clientData; /* Client specific data for the new filesystem * (can be NULL) */ const Tcl_Filesystem *fsPtr;/* Pointer to filesystem dispatch table. */ struct FilesystemRecord *nextPtr; /* The next filesystem registered to Tcl, or * NULL if no more. */ struct FilesystemRecord *prevPtr; /* The previous filesystem registered to Tcl, * or NULL if no more. */ } FilesystemRecord; /* * This structure holds per-thread private copy of the current directory * maintained by the global cwdPathPtr. This structure holds per-thread * private copies of some global data. This way we avoid most of the * synchronization calls which boosts performance, at cost of having to update * this information each time the corresponding epoch counter changes. */ typedef struct ThreadSpecificData { int initialized; size_t cwdPathEpoch; size_t filesystemEpoch; Tcl_Obj *cwdPathPtr; ClientData cwdClientData; FilesystemRecord *filesystemList; size_t claims; } ThreadSpecificData; /* * Prototypes for functions defined later in this file. */ static int EvalFileCallback(ClientData data[], Tcl_Interp *interp, int result); static FilesystemRecord*FsGetFirstFilesystem(void); static void FsThrExitProc(ClientData cd); static Tcl_Obj * FsListMounts(Tcl_Obj *pathPtr, const char *pattern); static void FsAddMountsToGlobResult(Tcl_Obj *resultPtr, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types); static void FsUpdateCwd(Tcl_Obj *cwdObj, ClientData clientData); static void FsRecacheFilesystemList(void); static void Claim(void); static void Disclaim(void); static void * DivertFindSymbol(Tcl_Interp *interp, Tcl_LoadHandle loadHandle, const char *symbol); static void DivertUnloadFile(Tcl_LoadHandle loadHandle); /* * These form part of the native filesystem support. They are needed here * because we have a few native filesystem functions (which are the same for * win/unix) in this file. There is no need to place them in tclInt.h, because * they are not (and should not be) used anywhere else. */ MODULE_SCOPE const char *const tclpFileAttrStrings[]; MODULE_SCOPE const TclFileAttrProcs tclpFileAttrProcs[]; /* * Declare the native filesystem support. These functions should be considered * private to Tcl, and should really not be called directly by any code other * than this file (i.e. neither by Tcl's core nor by extensions). Similarly, * the old string-based Tclp... native filesystem functions should not be * called. * * The correct API to use now is the Tcl_FS... set of functions, which ensure * correct and complete virtual filesystem support. * * We cannot make all of these static, since some of them are implemented in * the platform-specific directories. */ static Tcl_FSFilesystemSeparatorProc NativeFilesystemSeparator; static Tcl_FSFreeInternalRepProc NativeFreeInternalRep; static Tcl_FSFileAttrStringsProc NativeFileAttrStrings; static Tcl_FSFileAttrsGetProc NativeFileAttrsGet; static Tcl_FSFileAttrsSetProc NativeFileAttrsSet; /* * The only reason these functions are not static is that they are either * called by code in the native (win/unix) directories or they are actually * implemented in those directories. They should simply not be called by code * outside Tcl's native filesystem core i.e. they should be considered * 'static' to Tcl's filesystem code (if we ever built the native filesystem * support into a separate code library, this could actually be enforced). */ Tcl_FSFilesystemPathTypeProc TclpFilesystemPathType; Tcl_FSInternalToNormalizedProc TclpNativeToNormalized; Tcl_FSStatProc TclpObjStat; Tcl_FSAccessProc TclpObjAccess; Tcl_FSMatchInDirectoryProc TclpMatchInDirectory; Tcl_FSChdirProc TclpObjChdir; Tcl_FSLstatProc TclpObjLstat; Tcl_FSCopyFileProc TclpObjCopyFile; Tcl_FSDeleteFileProc TclpObjDeleteFile; Tcl_FSRenameFileProc TclpObjRenameFile; Tcl_FSCreateDirectoryProc TclpObjCreateDirectory; Tcl_FSCopyDirectoryProc TclpObjCopyDirectory; Tcl_FSRemoveDirectoryProc TclpObjRemoveDirectory; Tcl_FSUnloadFileProc TclpUnloadFile; Tcl_FSLinkProc TclpObjLink; Tcl_FSListVolumesProc TclpObjListVolumes; /* * Define the native filesystem dispatch table. If necessary, it is ok to make * this non-static, but it should only be accessed by the functions actually * listed within it (or perhaps other helper functions of them). Anything * which is not part of this 'native filesystem implementation' should not be * delving inside here! */ const Tcl_Filesystem tclNativeFilesystem = { "native", sizeof(Tcl_Filesystem), TCL_FILESYSTEM_VERSION_2, TclNativePathInFilesystem, TclNativeDupInternalRep, NativeFreeInternalRep, TclpNativeToNormalized, TclNativeCreateNativeRep, TclpObjNormalizePath, TclpFilesystemPathType, NativeFilesystemSeparator, TclpObjStat, TclpObjAccess, TclpOpenFileChannel, TclpMatchInDirectory, TclpUtime, #ifndef S_IFLNK NULL, #else TclpObjLink, #endif /* S_IFLNK */ TclpObjListVolumes, NativeFileAttrStrings, NativeFileAttrsGet, NativeFileAttrsSet, TclpObjCreateDirectory, TclpObjRemoveDirectory, TclpObjDeleteFile, TclpObjCopyFile, TclpObjRenameFile, TclpObjCopyDirectory, TclpObjLstat, /* Needs casts since we're using version_2. */ (Tcl_FSLoadFileProc *) TclpDlopen, (Tcl_FSGetCwdProc *) TclpGetNativeCwd, TclpObjChdir }; /* * Define the tail of the linked list. Note that for unconventional uses of * Tcl without a native filesystem, we may in the future wish to modify the * current approach of hard-coding the native filesystem in the lookup list * 'filesystemList' below. * * We initialize the record so that it thinks one file uses it. This means it * will never be freed. */ static FilesystemRecord nativeFilesystemRecord = { NULL, &tclNativeFilesystem, NULL, NULL }; /* * This is incremented each time we modify the linked list of filesystems. Any * time it changes, all cached filesystem representations are suspect and must * be freed. For multithreading builds, change of the filesystem epoch will * trigger cache cleanup in all threads. */ static size_t theFilesystemEpoch = 1; /* * Stores the linked list of filesystems. A 1:1 copy of this list is also * maintained in the TSD for each thread. This is to avoid synchronization * issues. */ static FilesystemRecord *filesystemList = &nativeFilesystemRecord; TCL_DECLARE_MUTEX(filesystemMutex) /* * Used to implement Tcl_FSGetCwd in a file-system independent way. */ static Tcl_Obj *cwdPathPtr = NULL; static size_t cwdPathEpoch = 0; static ClientData cwdClientData = NULL; TCL_DECLARE_MUTEX(cwdMutex) static Tcl_ThreadDataKey fsDataKey; /* * One of these structures is used each time we successfully load a file from * a file system by way of making a temporary copy of the file on the native * filesystem. We need to store both the actual unloadProc/clientData * combination which was used, and the original and modified filenames, so * that we can correctly undo the entire operation when we want to unload the * code. */ typedef struct FsDivertLoad { Tcl_LoadHandle loadHandle; Tcl_FSUnloadFileProc *unloadProcPtr; Tcl_Obj *divertedFile; const Tcl_Filesystem *divertedFilesystem; ClientData divertedFileNativeRep; } FsDivertLoad; /* * The following functions are obsolete string based APIs, and should be * removed in a future release (Tcl 9 would be a good time). */ /* Obsolete */ int Tcl_Stat( const char *path, /* Path of file to stat (in current CP). */ struct stat *oldStyleBuf) /* Filled with results of stat call. */ { int ret; Tcl_StatBuf buf; Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1); Tcl_IncrRefCount(pathPtr); ret = Tcl_FSStat(pathPtr, &buf); Tcl_DecrRefCount(pathPtr); if (ret != -1) { #ifndef TCL_WIDE_INT_IS_LONG Tcl_WideInt tmp1, tmp2, tmp3 = 0; # define OUT_OF_RANGE(x) \ (((Tcl_WideInt)(x)) < Tcl_LongAsWide(LONG_MIN) || \ ((Tcl_WideInt)(x)) > Tcl_LongAsWide(LONG_MAX)) # define OUT_OF_URANGE(x) \ (((Tcl_WideUInt)(x)) > ((Tcl_WideUInt)ULONG_MAX)) /* * Perform the result-buffer overflow check manually. * * Note that ino_t/ino64_t is unsigned... * * Workaround gcc warning of "comparison is always false due to * limited range of data type" by assigning to tmp var of type * Tcl_WideInt. */ tmp1 = (Tcl_WideInt) buf.st_ino; tmp2 = (Tcl_WideInt) buf.st_size; #ifdef HAVE_STRUCT_STAT_ST_BLOCKS tmp3 = (Tcl_WideInt) buf.st_blocks; #endif if (OUT_OF_URANGE(tmp1) || OUT_OF_RANGE(tmp2) || OUT_OF_RANGE(tmp3)) { #if defined(EFBIG) errno = EFBIG; #elif defined(EOVERFLOW) errno = EOVERFLOW; #else #error "What status should be returned for file size out of range?" #endif return -1; } # undef OUT_OF_RANGE # undef OUT_OF_URANGE #endif /* !TCL_WIDE_INT_IS_LONG */ /* * Copy across all supported fields, with possible type coercions on * those fields that change between the normal and lf64 versions of * the stat structure (on Solaris at least). This is slow when the * structure sizes coincide, but that's what you get for using an * obsolete interface. */ oldStyleBuf->st_mode = buf.st_mode; oldStyleBuf->st_ino = (ino_t) buf.st_ino; oldStyleBuf->st_dev = buf.st_dev; oldStyleBuf->st_rdev = buf.st_rdev; oldStyleBuf->st_nlink = buf.st_nlink; oldStyleBuf->st_uid = buf.st_uid; oldStyleBuf->st_gid = buf.st_gid; oldStyleBuf->st_size = (off_t) buf.st_size; oldStyleBuf->st_atime = buf.st_atime; oldStyleBuf->st_mtime = buf.st_mtime; oldStyleBuf->st_ctime = buf.st_ctime; #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE oldStyleBuf->st_blksize = buf.st_blksize; #endif #ifdef HAVE_STRUCT_STAT_ST_BLOCKS #ifdef HAVE_BLKCNT_T oldStyleBuf->st_blocks = (blkcnt_t) buf.st_blocks; #else oldStyleBuf->st_blocks = (unsigned long) buf.st_blocks; #endif #endif } return ret; } /* Obsolete */ int Tcl_Access( const char *path, /* Path of file to access (in current CP). */ int mode) /* Permission setting. */ { int ret; Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1); Tcl_IncrRefCount(pathPtr); ret = Tcl_FSAccess(pathPtr,mode); Tcl_DecrRefCount(pathPtr); return ret; } /* Obsolete */ Tcl_Channel Tcl_OpenFileChannel( Tcl_Interp *interp, /* Interpreter for error reporting; can be * NULL. */ const char *path, /* Name of file to open. */ const char *modeString, /* A list of POSIX open modes or a string such * as "rw". */ int permissions) /* If the open involves creating a file, with * what modes to create it? */ { Tcl_Channel ret; Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1); Tcl_IncrRefCount(pathPtr); ret = Tcl_FSOpenFileChannel(interp, pathPtr, modeString, permissions); Tcl_DecrRefCount(pathPtr); return ret; } /* Obsolete */ int Tcl_Chdir( const char *dirName) { int ret; Tcl_Obj *pathPtr = Tcl_NewStringObj(dirName,-1); Tcl_IncrRefCount(pathPtr); ret = Tcl_FSChdir(pathPtr); Tcl_DecrRefCount(pathPtr); return ret; } /* Obsolete */ char * Tcl_GetCwd( Tcl_Interp *interp, Tcl_DString *cwdPtr) { Tcl_Obj *cwd = Tcl_FSGetCwd(interp); if (cwd == NULL) { return NULL; } Tcl_DStringInit(cwdPtr); TclDStringAppendObj(cwdPtr, cwd); Tcl_DecrRefCount(cwd); return Tcl_DStringValue(cwdPtr); } /* Obsolete */ int Tcl_EvalFile( Tcl_Interp *interp, /* Interpreter in which to process file. */ const char *fileName) /* Name of file to process. Tilde-substitution * will be performed on this name. */ { int ret; Tcl_Obj *pathPtr = Tcl_NewStringObj(fileName,-1); Tcl_IncrRefCount(pathPtr); ret = Tcl_FSEvalFile(interp, pathPtr); Tcl_DecrRefCount(pathPtr); return ret; } /* * Now move on to the basic filesystem implementation. */ static void FsThrExitProc( ClientData cd) { ThreadSpecificData *tsdPtr = cd; FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL; /* * Trash the cwd copy. */ if (tsdPtr->cwdPathPtr != NULL) { Tcl_DecrRefCount(tsdPtr->cwdPathPtr); tsdPtr->cwdPathPtr = NULL; } if (tsdPtr->cwdClientData != NULL) { NativeFreeInternalRep(tsdPtr->cwdClientData); } /* * Trash the filesystems cache. */ fsRecPtr = tsdPtr->filesystemList; while (fsRecPtr != NULL) { tmpFsRecPtr = fsRecPtr->nextPtr; fsRecPtr->fsPtr = NULL; ckfree(fsRecPtr); fsRecPtr = tmpFsRecPtr; } tsdPtr->filesystemList = NULL; tsdPtr->initialized = 0; } int TclFSCwdIsNative(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); if (tsdPtr->cwdClientData != NULL) { return 1; } else { return 0; } } /* *---------------------------------------------------------------------- * * TclFSCwdPointerEquals -- * * Check whether the current working directory is equal to the path * given. * * Results: * 1 (equal) or 0 (un-equal) as appropriate. * * Side effects: * If the paths are equal, but are not the same object, this method will * modify the given pathPtrPtr to refer to the same object. In this case * the object pointed to by pathPtrPtr will have its refCount * decremented, and it will be adjusted to point to the cwd (with a new * refCount). * *---------------------------------------------------------------------- */ int TclFSCwdPointerEquals( Tcl_Obj **pathPtrPtr) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); Tcl_MutexLock(&cwdMutex); if (tsdPtr->cwdPathPtr == NULL || tsdPtr->cwdPathEpoch != cwdPathEpoch) { if (tsdPtr->cwdPathPtr != NULL) { Tcl_DecrRefCount(tsdPtr->cwdPathPtr); } if (tsdPtr->cwdClientData != NULL) { NativeFreeInternalRep(tsdPtr->cwdClientData); } if (cwdPathPtr == NULL) { tsdPtr->cwdPathPtr = NULL; } else { tsdPtr->cwdPathPtr = Tcl_DuplicateObj(cwdPathPtr); Tcl_IncrRefCount(tsdPtr->cwdPathPtr); } if (cwdClientData == NULL) { tsdPtr->cwdClientData = NULL; } else { tsdPtr->cwdClientData = TclNativeDupInternalRep(cwdClientData); } tsdPtr->cwdPathEpoch = cwdPathEpoch; } Tcl_MutexUnlock(&cwdMutex); if (tsdPtr->initialized == 0) { Tcl_CreateThreadExitHandler(FsThrExitProc, tsdPtr); tsdPtr->initialized = 1; } if (pathPtrPtr == NULL) { return (tsdPtr->cwdPathPtr == NULL); } if (tsdPtr->cwdPathPtr == *pathPtrPtr) { return 1; } else { int len1, len2; const char *str1, *str2; str1 = Tcl_GetStringFromObj(tsdPtr->cwdPathPtr, &len1); str2 = Tcl_GetStringFromObj(*pathPtrPtr, &len2); if ((len1 == len2) && !memcmp(str1, str2, len1)) { /* * They are equal, but different objects. Update so they will be * the same object in the future. */ Tcl_DecrRefCount(*pathPtrPtr); *pathPtrPtr = tsdPtr->cwdPathPtr; Tcl_IncrRefCount(*pathPtrPtr); return 1; } else { return 0; } } } static void FsRecacheFilesystemList(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); FilesystemRecord *fsRecPtr, *tmpFsRecPtr = NULL, *toFree = NULL, *list; /* * Trash the current cache. */ fsRecPtr = tsdPtr->filesystemList; while (fsRecPtr != NULL) { tmpFsRecPtr = fsRecPtr->nextPtr; fsRecPtr->nextPtr = toFree; toFree = fsRecPtr; fsRecPtr = tmpFsRecPtr; } /* * Locate tail of the global filesystem list. */ Tcl_MutexLock(&filesystemMutex); fsRecPtr = filesystemList; while (fsRecPtr != NULL) { tmpFsRecPtr = fsRecPtr; fsRecPtr = fsRecPtr->nextPtr; } /* * Refill the cache honouring the order. */ list = NULL; fsRecPtr = tmpFsRecPtr; while (fsRecPtr != NULL) { tmpFsRecPtr = ckalloc(sizeof(FilesystemRecord)); *tmpFsRecPtr = *fsRecPtr; tmpFsRecPtr->nextPtr = list; tmpFsRecPtr->prevPtr = NULL; list = tmpFsRecPtr; fsRecPtr = fsRecPtr->prevPtr; } tsdPtr->filesystemList = list; tsdPtr->filesystemEpoch = theFilesystemEpoch; Tcl_MutexUnlock(&filesystemMutex); while (toFree) { FilesystemRecord *next = toFree->nextPtr; toFree->fsPtr = NULL; ckfree(toFree); toFree = next; } /* * Make sure the above gets released on thread exit. */ if (tsdPtr->initialized == 0) { Tcl_CreateThreadExitHandler(FsThrExitProc, tsdPtr); tsdPtr->initialized = 1; } } static FilesystemRecord * FsGetFirstFilesystem(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); if (tsdPtr->filesystemList == NULL || ((tsdPtr->claims == 0) && (tsdPtr->filesystemEpoch != theFilesystemEpoch))) { FsRecacheFilesystemList(); } return tsdPtr->filesystemList; } /* * The epoch can be changed both by filesystems being added or removed and by * env(HOME) changing. */ int TclFSEpochOk( size_t filesystemEpoch) { return (filesystemEpoch == 0 || filesystemEpoch == theFilesystemEpoch); } static void Claim(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); tsdPtr->claims++; } static void Disclaim(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); tsdPtr->claims--; } size_t TclFSEpoch(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); return tsdPtr->filesystemEpoch; } /* * If non-NULL, clientData is owned by us and must be freed later. */ static void FsUpdateCwd( Tcl_Obj *cwdObj, ClientData clientData) { int len; const char *str = NULL; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); if (cwdObj != NULL) { str = Tcl_GetStringFromObj(cwdObj, &len); } Tcl_MutexLock(&cwdMutex); if (cwdPathPtr != NULL) { Tcl_DecrRefCount(cwdPathPtr); } if (cwdClientData != NULL) { NativeFreeInternalRep(cwdClientData); } if (cwdObj == NULL) { cwdPathPtr = NULL; cwdClientData = NULL; } else { /* * This must be stored as string obj! */ cwdPathPtr = Tcl_NewStringObj(str, len); Tcl_IncrRefCount(cwdPathPtr); cwdClientData = TclNativeDupInternalRep(clientData); } if (++cwdPathEpoch == 0) { ++cwdPathEpoch; } tsdPtr->cwdPathEpoch = cwdPathEpoch; Tcl_MutexUnlock(&cwdMutex); if (tsdPtr->cwdPathPtr) { Tcl_DecrRefCount(tsdPtr->cwdPathPtr); } if (tsdPtr->cwdClientData) { NativeFreeInternalRep(tsdPtr->cwdClientData); } if (cwdObj == NULL) { tsdPtr->cwdPathPtr = NULL; tsdPtr->cwdClientData = NULL; } else { tsdPtr->cwdPathPtr = Tcl_NewStringObj(str, len); tsdPtr->cwdClientData = clientData; Tcl_IncrRefCount(tsdPtr->cwdPathPtr); } } /* *---------------------------------------------------------------------- * * TclFinalizeFilesystem -- * * Clean up the filesystem. After this, calls to all Tcl_FS... functions * will fail. * * We will later call TclResetFilesystem to restore the FS to a pristine * state. * * Results: * None. * * Side effects: * Frees any memory allocated by the filesystem. * *---------------------------------------------------------------------- */ void TclFinalizeFilesystem(void) { FilesystemRecord *fsRecPtr; /* * Assumption that only one thread is active now. Otherwise we would need * to put various mutexes around this code. */ if (cwdPathPtr != NULL) { Tcl_DecrRefCount(cwdPathPtr); cwdPathPtr = NULL; cwdPathEpoch = 0; } if (cwdClientData != NULL) { NativeFreeInternalRep(cwdClientData); cwdClientData = NULL; } /* * Remove all filesystems, freeing any allocated memory that is no longer * needed. */ fsRecPtr = filesystemList; while (fsRecPtr != NULL) { FilesystemRecord *tmpFsRecPtr = fsRecPtr->nextPtr; /* The native filesystem is static, so we don't free it. */ if (fsRecPtr != &nativeFilesystemRecord) { ckfree(fsRecPtr); } fsRecPtr = tmpFsRecPtr; } if (++theFilesystemEpoch == 0) { ++theFilesystemEpoch; } filesystemList = NULL; /* * Now filesystemList is NULL. This means that any attempt to use the * filesystem is likely to fail. */ #ifdef _WIN32 TclWinEncodingsCleanup(); #endif } /* *---------------------------------------------------------------------- * * TclResetFilesystem -- * * Restore the filesystem to a pristine state. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclResetFilesystem(void) { filesystemList = &nativeFilesystemRecord; if (++theFilesystemEpoch == 0) { ++theFilesystemEpoch; } #ifdef _WIN32 /* * Cleans up the win32 API filesystem proc lookup table. This must happen * very late in finalization so that deleting of copied dlls can occur. */ TclWinResetInterfaces(); #endif } /* *---------------------------------------------------------------------- * * Tcl_FSRegister -- * * Insert the filesystem function table at the head of the list of * functions which are used during calls to all file-system operations. * The filesystem will be added even if it is already in the list. (You * can use Tcl_FSData to check if it is in the list, provided the * ClientData used was not NULL). * * Note that the filesystem handling is head-to-tail of the list. Each * filesystem is asked in turn whether it can handle a particular * request, until one of them says 'yes'. At that point no further * filesystems are asked. * * In particular this means if you want to add a diagnostic filesystem * (which simply reports all fs activity), it must be at the head of the * list: i.e. it must be the last registered. * * Results: * Normally TCL_OK; TCL_ERROR if memory for a new node in the list could * not be allocated. * * Side effects: * Memory allocated and modifies the link list for filesystems. * *---------------------------------------------------------------------- */ int Tcl_FSRegister( ClientData clientData, /* Client specific data for this fs. */ const Tcl_Filesystem *fsPtr)/* The filesystem record for the new fs. */ { FilesystemRecord *newFilesystemPtr; if (fsPtr == NULL) { return TCL_ERROR; } newFilesystemPtr = ckalloc(sizeof(FilesystemRecord)); newFilesystemPtr->clientData = clientData; newFilesystemPtr->fsPtr = fsPtr; /* * Is this lock and wait strictly speaking necessary? Since any iterators * out there will have grabbed a copy of the head of the list and be * iterating away from that, if we add a new element to the head of the * list, it can't possibly have any effect on any of their loops. In fact * it could be better not to wait, since we are adjusting the filesystem * epoch, any cached representations calculated by existing iterators are * going to have to be thrown away anyway. * * However, since registering and unregistering filesystems is a very rare * action, this is not a very important point. */ Tcl_MutexLock(&filesystemMutex); newFilesystemPtr->nextPtr = filesystemList; newFilesystemPtr->prevPtr = NULL; if (filesystemList) { filesystemList->prevPtr = newFilesystemPtr; } filesystemList = newFilesystemPtr; /* * Increment the filesystem epoch counter, since existing paths might * conceivably now belong to different filesystems. */ if (++theFilesystemEpoch == 0) { ++theFilesystemEpoch; } Tcl_MutexUnlock(&filesystemMutex); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_FSUnregister -- * * Remove the passed filesystem from the list of filesystem function * tables. It also ensures that the built-in (native) filesystem is not * removable, although we may wish to change that decision in the future * to allow a smaller Tcl core, in which the native filesystem is not * used at all (we could, say, initialise Tcl completely over a network * connection). * * Results: * TCL_OK if the function pointer was successfully removed, TCL_ERROR * otherwise. * * Side effects: * Memory may be deallocated (or will be later, once no "path" objects * refer to this filesystem), but the list of registered filesystems is * updated immediately. * *---------------------------------------------------------------------- */ int Tcl_FSUnregister( const Tcl_Filesystem *fsPtr) /* The filesystem record to remove. */ { int retVal = TCL_ERROR; FilesystemRecord *fsRecPtr; Tcl_MutexLock(&filesystemMutex); /* * Traverse the 'filesystemList' looking for the particular node whose * 'fsPtr' member matches 'fsPtr' and remove that one from the list. * Ensure that the "default" node cannot be removed. */ fsRecPtr = filesystemList; while ((retVal == TCL_ERROR) && (fsRecPtr != &nativeFilesystemRecord)) { if (fsRecPtr->fsPtr == fsPtr) { if (fsRecPtr->prevPtr) { fsRecPtr->prevPtr->nextPtr = fsRecPtr->nextPtr; } else { filesystemList = fsRecPtr->nextPtr; } if (fsRecPtr->nextPtr) { fsRecPtr->nextPtr->prevPtr = fsRecPtr->prevPtr; } /* * Increment the filesystem epoch counter, since existing paths * might conceivably now belong to different filesystems. This * should also ensure that paths which have cached the filesystem * which is about to be deleted do not reference that filesystem * (which would of course lead to memory exceptions). */ if (++theFilesystemEpoch == 0) { ++theFilesystemEpoch; } ckfree(fsRecPtr); retVal = TCL_OK; } else { fsRecPtr = fsRecPtr->nextPtr; } } Tcl_MutexUnlock(&filesystemMutex); return retVal; } /* *---------------------------------------------------------------------- * * Tcl_FSMatchInDirectory -- * * This routine is used by the globbing code to search a directory for * all files which match a given pattern. The appropriate function for * the filesystem to which pathPtr belongs will be called. If pathPtr * does not belong to any filesystem and if it is NULL or the empty * string, then we assume the pattern is to be matched in the current * working directory. To avoid have the Tcl_FSMatchInDirectoryProc for * each filesystem from having to deal with this issue, we create a * pathPtr on the fly (equal to the cwd), and then remove it from the * results returned. This makes filesystems easy to write, since they can * assume the pathPtr passed to them is an ordinary path. In fact this * means we could remove such special case handling from Tcl's native * filesystems. * * If 'pattern' is NULL, then pathPtr is assumed to be a fully specified * path of a single file/directory which must be checked for existence * and correct type. * * Results: * * The return value is a standard Tcl result indicating whether an error * occurred in globbing. Error messages are placed in interp, but good * results are placed in the resultPtr given. * * Recursive searches, e.g. * glob -dir $dir -join * pkgIndex.tcl * which must recurse through each directory matching '*' are handled * internally by Tcl, by passing specific flags in a modified 'types' * parameter. This means the actual filesystem only ever sees patterns * which match in a single directory. * * Side effects: * The interpreter may have an error message inserted into it. * *---------------------------------------------------------------------- */ int Tcl_FSMatchInDirectory( Tcl_Interp *interp, /* Interpreter to receive error messages, but * may be NULL. */ Tcl_Obj *resultPtr, /* List object to receive results. */ Tcl_Obj *pathPtr, /* Contains path to directory to search. */ const char *pattern, /* Pattern to match against. */ Tcl_GlobTypeData *types) /* Object containing list of acceptable types. * May be NULL. In particular the directory * flag is very important. */ { const Tcl_Filesystem *fsPtr; Tcl_Obj *cwd, *tmpResultPtr, **elemsPtr; int resLength, i, ret = -1; if (types != NULL && (types->type & TCL_GLOB_TYPE_MOUNT)) { /* * We don't currently allow querying of mounts by external code (a * valuable future step), so since we're the only function that * actually knows about mounts, this means we're being called * recursively by ourself. Return no matches. */ return TCL_OK; } if (pathPtr != NULL) { fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); } else { fsPtr = NULL; } /* * Check if we've successfully mapped the path to a filesystem within * which to search. */ if (fsPtr != NULL) { if (fsPtr->matchInDirectoryProc == NULL) { Tcl_SetErrno(ENOENT); return -1; } ret = fsPtr->matchInDirectoryProc(interp, resultPtr, pathPtr, pattern, types); if (ret == TCL_OK && pattern != NULL) { FsAddMountsToGlobResult(resultPtr, pathPtr, pattern, types); } return ret; } /* * If the path isn't empty, we have no idea how to match files in a * directory which belongs to no known filesystem. */ if (pathPtr != NULL && TclGetString(pathPtr)[0] != '\0') { Tcl_SetErrno(ENOENT); return -1; } /* * We have an empty or NULL path. This is defined to mean we must search * for files within the current 'cwd'. We therefore use that, but then * since the proc we call will return results which include the cwd we * must then trim it off the front of each path in the result. We choose * to deal with this here (in the generic code), since if we don't, every * single filesystem's implementation of Tcl_FSMatchInDirectory will have * to deal with it for us. */ cwd = Tcl_FSGetCwd(NULL); if (cwd == NULL) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "glob couldn't determine the current working directory", -1)); } return TCL_ERROR; } fsPtr = Tcl_FSGetFileSystemForPath(cwd); if (fsPtr != NULL && fsPtr->matchInDirectoryProc != NULL) { TclNewObj(tmpResultPtr); Tcl_IncrRefCount(tmpResultPtr); ret = fsPtr->matchInDirectoryProc(interp, tmpResultPtr, cwd, pattern, types); if (ret == TCL_OK) { FsAddMountsToGlobResult(tmpResultPtr, cwd, pattern, types); /* * Note that we know resultPtr and tmpResultPtr are distinct. */ ret = Tcl_ListObjGetElements(interp, tmpResultPtr, &resLength, &elemsPtr); for (i=0 ; ret==TCL_OK && itype & TCL_GLOB_TYPE_DIR)); Tcl_Obj *mounts = FsListMounts(pathPtr, pattern); if (mounts == NULL) { return; } if (Tcl_ListObjLength(NULL, mounts, &mLength) != TCL_OK || mLength == 0) { goto endOfMounts; } if (Tcl_ListObjLength(NULL, resultPtr, &gLength) != TCL_OK) { goto endOfMounts; } for (i=0 ; ifsPtr == fsPtr) { retVal = fsRecPtr->clientData; } fsRecPtr = fsRecPtr->nextPtr; } return retVal; } /* *--------------------------------------------------------------------------- * * TclFSNormalizeToUniquePath -- * * Takes a path specification containing no ../, ./ sequences, and * converts it into a unique path for the given platform. On Unix, this * means the path must be free of symbolic links/aliases, and on Windows * it means we want the long form, with that long form's case-dependence * (which gives us a unique, case-dependent path). * * Results: * The pathPtr is modified in place. The return value is the last byte * offset which was recognised in the path string. * * Side effects: * None (beyond the memory allocation for the result). * * Special notes: * If the filesystem-specific normalizePathProcs can re-introduce ../, ./ * sequences into the path, then this function will not return the * correct result. This may be possible with symbolic links on unix. * * Important assumption: if startAt is non-zero, it must point to a * directory separator that we know exists and is already normalized (so * it is important not to point to the char just after the separator). * *--------------------------------------------------------------------------- */ int TclFSNormalizeToUniquePath( Tcl_Interp *interp, /* Used for error messages. */ Tcl_Obj *pathPtr, /* The path to normalize in place. */ int startAt) /* Start at this char-offset. */ { FilesystemRecord *fsRecPtr, *firstFsRecPtr; /* * Call each of the "normalise path" functions in succession. This is a * special case, in which if we have a native filesystem handler, we call * it first. This is because the root of Tcl's filesystem is always a * native filesystem (i.e. '/' on unix is native). */ firstFsRecPtr = FsGetFirstFilesystem(); Claim(); for (fsRecPtr=firstFsRecPtr; fsRecPtr!=NULL; fsRecPtr=fsRecPtr->nextPtr) { if (fsRecPtr->fsPtr != &tclNativeFilesystem) { continue; } /* * TODO: Assume that we always find the native file system; it should * always be there... */ if (fsRecPtr->fsPtr->normalizePathProc != NULL) { startAt = fsRecPtr->fsPtr->normalizePathProc(interp, pathPtr, startAt); } break; } for (fsRecPtr=firstFsRecPtr; fsRecPtr!=NULL; fsRecPtr=fsRecPtr->nextPtr) { /* * Skip the native system next time through. */ if (fsRecPtr->fsPtr == &tclNativeFilesystem) { continue; } if (fsRecPtr->fsPtr->normalizePathProc != NULL) { startAt = fsRecPtr->fsPtr->normalizePathProc(interp, pathPtr, startAt); } /* * We could add an efficiency check like this: * if (retVal == length-of(pathPtr)) {break;} * but there's not much benefit. */ } Disclaim(); return startAt; } /* *--------------------------------------------------------------------------- * * TclGetOpenMode -- * * This routine is an obsolete, limited version of TclGetOpenModeEx() * below. It exists only to satisfy any extensions imprudently using it * via Tcl's internal stubs table. * * Results: * Same as TclGetOpenModeEx(). * * Side effects: * Same as TclGetOpenModeEx(). * *--------------------------------------------------------------------------- */ int TclGetOpenMode( Tcl_Interp *interp, /* Interpreter to use for error reporting - * may be NULL. */ const char *modeString, /* Mode string, e.g. "r+" or "RDONLY CREAT" */ int *seekFlagPtr) /* Set this to 1 if the caller should seek to * EOF during the opening of the file. */ { int binary = 0; return TclGetOpenModeEx(interp, modeString, seekFlagPtr, &binary); } /* *--------------------------------------------------------------------------- * * TclGetOpenModeEx -- * * Computes a POSIX mode mask for opening a file, from a given string, * and also sets flags to indicate whether the caller should seek to EOF * after opening the file, and whether the caller should configure the * channel for binary data. * * Results: * On success, returns mode to pass to "open". If an error occurs, the * return value is -1 and if interp is not NULL, sets interp's result * object to an error message. * * Side effects: * Sets the integer referenced by seekFlagPtr to 1 to tell the caller to * seek to EOF after opening the file, or to 0 otherwise. Sets the * integer referenced by binaryPtr to 1 to tell the caller to seek to * configure the channel for binary data, or to 0 otherwise. * * Special note: * This code is based on a prototype implementation contributed by Mark * Diekhans. * *--------------------------------------------------------------------------- */ int TclGetOpenModeEx( Tcl_Interp *interp, /* Interpreter to use for error reporting - * may be NULL. */ const char *modeString, /* Mode string, e.g. "r+" or "RDONLY CREAT" */ int *seekFlagPtr, /* Set this to 1 if the caller should seek to * EOF during the opening of the file. */ int *binaryPtr) /* Set this to 1 if the caller should * configure the opened channel for binary * operations. */ { int mode, modeArgc, c, i, gotRW; const char **modeArgv, *flag; #define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR) /* * Check for the simpler fopen-like access modes (e.g. "r"). They are * distinguished from the POSIX access modes by the presence of a * lower-case first letter. */ *seekFlagPtr = 0; *binaryPtr = 0; mode = 0; /* * Guard against international characters before using byte oriented * routines. */ if (!(modeString[0] & 0x80) && islower(UCHAR(modeString[0]))) { /* INTL: ISO only. */ switch (modeString[0]) { case 'r': mode = O_RDONLY; break; case 'w': mode = O_WRONLY|O_CREAT|O_TRUNC; break; case 'a': /* * Added O_APPEND for proper automatic seek-to-end-on-write by the * OS. [Bug 680143] */ mode = O_WRONLY|O_CREAT|O_APPEND; *seekFlagPtr = 1; break; default: goto error; } i = 1; while (i<3 && modeString[i]) { if (modeString[i] == modeString[i-1]) { goto error; } switch (modeString[i++]) { case '+': /* * Must remove the O_APPEND flag so that the seek command * works. [Bug 1773127] */ mode &= ~(O_RDONLY|O_WRONLY|O_APPEND); mode |= O_RDWR; break; case 'b': *binaryPtr = 1; break; default: goto error; } } if (modeString[i] != 0) { goto error; } return mode; error: *seekFlagPtr = 0; *binaryPtr = 0; if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "illegal access mode \"%s\"", modeString)); } return -1; } /* * The access modes are specified using a list of POSIX modes such as * O_CREAT. * * IMPORTANT NOTE: We rely on Tcl_SplitList working correctly when a NULL * interpreter is passed in. */ if (Tcl_SplitList(interp, modeString, &modeArgc, &modeArgv) != TCL_OK) { if (interp != NULL) { Tcl_AddErrorInfo(interp, "\n while processing open access modes \""); Tcl_AddErrorInfo(interp, modeString); Tcl_AddErrorInfo(interp, "\""); } return -1; } gotRW = 0; for (i = 0; i < modeArgc; i++) { flag = modeArgv[i]; c = flag[0]; if ((c == 'R') && (strcmp(flag, "RDONLY") == 0)) { mode = (mode & ~RW_MODES) | O_RDONLY; gotRW = 1; } else if ((c == 'W') && (strcmp(flag, "WRONLY") == 0)) { mode = (mode & ~RW_MODES) | O_WRONLY; gotRW = 1; } else if ((c == 'R') && (strcmp(flag, "RDWR") == 0)) { mode = (mode & ~RW_MODES) | O_RDWR; gotRW = 1; } else if ((c == 'A') && (strcmp(flag, "APPEND") == 0)) { mode |= O_APPEND; *seekFlagPtr = 1; } else if ((c == 'C') && (strcmp(flag, "CREAT") == 0)) { mode |= O_CREAT; } else if ((c == 'E') && (strcmp(flag, "EXCL") == 0)) { mode |= O_EXCL; } else if ((c == 'N') && (strcmp(flag, "NOCTTY") == 0)) { #ifdef O_NOCTTY mode |= O_NOCTTY; #else if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "access mode \"%s\" not supported by this system", flag)); } ckfree(modeArgv); return -1; #endif } else if ((c == 'N') && (strcmp(flag, "NONBLOCK") == 0)) { #ifdef O_NONBLOCK mode |= O_NONBLOCK; #else if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "access mode \"%s\" not supported by this system", flag)); } ckfree(modeArgv); return -1; #endif } else if ((c == 'T') && (strcmp(flag, "TRUNC") == 0)) { mode |= O_TRUNC; } else if ((c == 'B') && (strcmp(flag, "BINARY") == 0)) { *binaryPtr = 1; } else { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid access mode \"%s\": must be RDONLY, WRONLY, " "RDWR, APPEND, BINARY, CREAT, EXCL, NOCTTY, NONBLOCK," " or TRUNC", flag)); } ckfree(modeArgv); return -1; } } ckfree(modeArgv); if (!gotRW) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "access mode must include either RDONLY, WRONLY, or RDWR", -1)); } return -1; } return mode; } /* *---------------------------------------------------------------------- * * Tcl_FSEvalFile, Tcl_FSEvalFileEx, TclNREvalFile -- * * Read in a file and process the entire file as one gigantic Tcl * command. Tcl_FSEvalFile is Tcl_FSEvalFileEx without encoding argument. * TclNREvalFile is an NRE-enabled version of Tcl_FSEvalFileEx. * * Results: * A standard Tcl result, which is either the result of executing the * file or an error indicating why the file couldn't be read. * * Side effects: * Depends on the commands in the file. During the evaluation of the * contents of the file, iPtr->scriptFile is made to point to pathPtr * (the old value is cached and replaced when this function returns). * *---------------------------------------------------------------------- */ int Tcl_FSEvalFile( Tcl_Interp *interp, /* Interpreter in which to process file. */ Tcl_Obj *pathPtr) /* Path of file to process. Tilde-substitution * will be performed on this name. */ { return Tcl_FSEvalFileEx(interp, pathPtr, NULL); } int Tcl_FSEvalFileEx( Tcl_Interp *interp, /* Interpreter in which to process file. */ Tcl_Obj *pathPtr, /* Path of file to process. Tilde-substitution * will be performed on this name. */ const char *encodingName) /* If non-NULL, then use this encoding for the * file. NULL means use the system encoding. */ { int length, result = TCL_ERROR; Tcl_StatBuf statBuf; Tcl_Obj *oldScriptFile; Interp *iPtr; const char *string; Tcl_Channel chan; Tcl_Obj *objPtr; if (Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL) { return result; } if (Tcl_FSStat(pathPtr, &statBuf) == -1) { Tcl_SetErrno(errno); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", Tcl_GetString(pathPtr), Tcl_PosixError(interp))); return result; } chan = Tcl_FSOpenFileChannel(interp, pathPtr, "r", 0644); if (chan == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", Tcl_GetString(pathPtr), Tcl_PosixError(interp))); return result; } /* * The eofchar is \32 (^Z). This is the usual on Windows, but we effect * this cross-platform to allow for scripted documents. [Bug: 2040] */ Tcl_SetChannelOption(interp, chan, "-eofchar", "\32"); /* * If the encoding is specified, set it for the channel. Else don't touch * it (and use the system encoding) Report error on unknown encoding. */ if (encodingName != NULL) { if (Tcl_SetChannelOption(interp, chan, "-encoding", encodingName) != TCL_OK) { Tcl_Close(interp,chan); return result; } } objPtr = Tcl_NewObj(); Tcl_IncrRefCount(objPtr); /* * Try to read first character of stream, so we can check for utf-8 BOM to * be handled especially. */ if (Tcl_ReadChars(chan, objPtr, 1, 0) < 0) { Tcl_Close(interp, chan); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", Tcl_GetString(pathPtr), Tcl_PosixError(interp))); goto end; } string = Tcl_GetString(objPtr); /* * If first character is not a BOM, append the remaining characters, * otherwise replace them. [Bug 3466099] */ if (Tcl_ReadChars(chan, objPtr, -1, memcmp(string, "\xef\xbb\xbf", 3)) < 0) { Tcl_Close(interp, chan); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", Tcl_GetString(pathPtr), Tcl_PosixError(interp))); goto end; } if (Tcl_Close(interp, chan) != TCL_OK) { goto end; } iPtr = (Interp *) interp; oldScriptFile = iPtr->scriptFile; iPtr->scriptFile = pathPtr; Tcl_IncrRefCount(iPtr->scriptFile); string = Tcl_GetStringFromObj(objPtr, &length); /* * TIP #280 Force the evaluator to open a frame for a sourced file. */ iPtr->evalFlags |= TCL_EVAL_FILE; result = TclEvalEx(interp, string, length, 0, 1, NULL, string); /* * Now we have to be careful; the script may have changed the * iPtr->scriptFile value, so we must reset it without assuming it still * points to 'pathPtr'. */ if (iPtr->scriptFile != NULL) { Tcl_DecrRefCount(iPtr->scriptFile); } iPtr->scriptFile = oldScriptFile; if (result == TCL_RETURN) { result = TclUpdateReturnInfo(iPtr); } else if (result == TCL_ERROR) { /* * Record information telling where the error occurred. */ const char *pathString = Tcl_GetStringFromObj(pathPtr, &length); int limit = 150; int overflow = (length > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (file \"%.*s%s\" line %d)", (overflow ? limit : length), pathString, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } end: Tcl_DecrRefCount(objPtr); return result; } int TclNREvalFile( Tcl_Interp *interp, /* Interpreter in which to process file. */ Tcl_Obj *pathPtr, /* Path of file to process. Tilde-substitution * will be performed on this name. */ const char *encodingName) /* If non-NULL, then use this encoding for the * file. NULL means use the system encoding. */ { Tcl_StatBuf statBuf; Tcl_Obj *oldScriptFile, *objPtr; Interp *iPtr; Tcl_Channel chan; const char *string; if (Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL) { return TCL_ERROR; } if (Tcl_FSStat(pathPtr, &statBuf) == -1) { Tcl_SetErrno(errno); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", Tcl_GetString(pathPtr), Tcl_PosixError(interp))); return TCL_ERROR; } chan = Tcl_FSOpenFileChannel(interp, pathPtr, "r", 0644); if (chan == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", Tcl_GetString(pathPtr), Tcl_PosixError(interp))); return TCL_ERROR; } /* * The eofchar is \32 (^Z). This is the usual on Windows, but we effect * this cross-platform to allow for scripted documents. [Bug: 2040] */ Tcl_SetChannelOption(interp, chan, "-eofchar", "\32"); /* * If the encoding is specified, set it for the channel. Else don't touch * it (and use the system encoding) Report error on unknown encoding. */ if (encodingName != NULL) { if (Tcl_SetChannelOption(interp, chan, "-encoding", encodingName) != TCL_OK) { Tcl_Close(interp,chan); return TCL_ERROR; } } objPtr = Tcl_NewObj(); Tcl_IncrRefCount(objPtr); /* * Try to read first character of stream, so we can check for utf-8 BOM to * be handled especially. */ if (Tcl_ReadChars(chan, objPtr, 1, 0) < 0) { Tcl_Close(interp, chan); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", Tcl_GetString(pathPtr), Tcl_PosixError(interp))); Tcl_DecrRefCount(objPtr); return TCL_ERROR; } string = Tcl_GetString(objPtr); /* * If first character is not a BOM, append the remaining characters, * otherwise replace them. [Bug 3466099] */ if (Tcl_ReadChars(chan, objPtr, -1, memcmp(string, "\xef\xbb\xbf", 3)) < 0) { Tcl_Close(interp, chan); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't read file \"%s\": %s", Tcl_GetString(pathPtr), Tcl_PosixError(interp))); Tcl_DecrRefCount(objPtr); return TCL_ERROR; } if (Tcl_Close(interp, chan) != TCL_OK) { Tcl_DecrRefCount(objPtr); return TCL_ERROR; } iPtr = (Interp *) interp; oldScriptFile = iPtr->scriptFile; iPtr->scriptFile = pathPtr; Tcl_IncrRefCount(iPtr->scriptFile); /* * TIP #280: Force the evaluator to open a frame for a sourced file. */ iPtr->evalFlags |= TCL_EVAL_FILE; TclNRAddCallback(interp, EvalFileCallback, oldScriptFile, pathPtr, objPtr, NULL); return TclNREvalObjEx(interp, objPtr, 0, NULL, INT_MIN); } static int EvalFileCallback( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_Obj *oldScriptFile = data[0]; Tcl_Obj *pathPtr = data[1]; Tcl_Obj *objPtr = data[2]; /* * Now we have to be careful; the script may have changed the * iPtr->scriptFile value, so we must reset it without assuming it still * points to 'pathPtr'. */ if (iPtr->scriptFile != NULL) { Tcl_DecrRefCount(iPtr->scriptFile); } iPtr->scriptFile = oldScriptFile; if (result == TCL_RETURN) { result = TclUpdateReturnInfo(iPtr); } else if (result == TCL_ERROR) { /* * Record information telling where the error occurred. */ int length; const char *pathString = Tcl_GetStringFromObj(pathPtr, &length); const int limit = 150; int overflow = (length > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (file \"%.*s%s\" line %d)", (overflow ? limit : length), pathString, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } Tcl_DecrRefCount(objPtr); return result; } /* *---------------------------------------------------------------------- * * Tcl_GetErrno -- * * Gets the current value of the Tcl error code variable. This is * currently the global variable "errno" but could in the future change * to something else. * * Results: * The value of the Tcl error code variable. * * Side effects: * None. Note that the value of the Tcl error code variable is UNDEFINED * if a call to Tcl_SetErrno did not precede this call. * *---------------------------------------------------------------------- */ int Tcl_GetErrno(void) { /* * On some platforms, errno is really a thread local (implemented by the C * library). */ return errno; } /* *---------------------------------------------------------------------- * * Tcl_SetErrno -- * * Sets the Tcl error code variable to the supplied value. On some saner * platforms this is actually a thread-local (this is implemented in the * C library) but this is *really* unsafe to assume! * * Results: * None. * * Side effects: * Modifies the value of the Tcl error code variable. * *---------------------------------------------------------------------- */ void Tcl_SetErrno( int err) /* The new value. */ { /* * On some platforms, errno is really a thread local (implemented by the C * library). */ errno = err; } /* *---------------------------------------------------------------------- * * Tcl_PosixError -- * * This function is typically called after UNIX kernel calls return * errors. It stores machine-readable information about the error in * errorCode field of interp and returns an information string for the * caller's use. * * Results: * The return value is a human-readable string describing the error. * * Side effects: * The errorCode field of the interp is set. * *---------------------------------------------------------------------- */ const char * Tcl_PosixError( Tcl_Interp *interp) /* Interpreter whose errorCode field is to be * set. */ { const char *id, *msg; msg = Tcl_ErrnoMsg(errno); id = Tcl_ErrnoId(); if (interp) { Tcl_SetErrorCode(interp, "POSIX", id, msg, NULL); } return msg; } /* *---------------------------------------------------------------------- * * Tcl_FSStat -- * * This function replaces the library version of stat and lsat. * * The appropriate function for the filesystem to which pathPtr belongs * will be called. * * Results: * See stat documentation. * * Side effects: * See stat documentation. * *---------------------------------------------------------------------- */ int Tcl_FSStat( Tcl_Obj *pathPtr, /* Path of file to stat (in current CP). */ Tcl_StatBuf *buf) /* Filled with results of stat call. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->statProc != NULL) { return fsPtr->statProc(pathPtr, buf); } Tcl_SetErrno(ENOENT); return -1; } /* *---------------------------------------------------------------------- * * Tcl_FSLstat -- * * This function replaces the library version of lstat. The appropriate * function for the filesystem to which pathPtr belongs will be called. * If no 'lstat' function is listed, but a 'stat' function is, then Tcl * will fall back on the stat function. * * Results: * See lstat documentation. * * Side effects: * See lstat documentation. * *---------------------------------------------------------------------- */ int Tcl_FSLstat( Tcl_Obj *pathPtr, /* Path of file to stat (in current CP). */ Tcl_StatBuf *buf) /* Filled with results of stat call. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL) { if (fsPtr->lstatProc != NULL) { return fsPtr->lstatProc(pathPtr, buf); } if (fsPtr->statProc != NULL) { return fsPtr->statProc(pathPtr, buf); } } Tcl_SetErrno(ENOENT); return -1; } /* *---------------------------------------------------------------------- * * Tcl_FSAccess -- * * This function replaces the library version of access. The appropriate * function for the filesystem to which pathPtr belongs will be called. * * Results: * See access documentation. * * Side effects: * See access documentation. * *---------------------------------------------------------------------- */ int Tcl_FSAccess( Tcl_Obj *pathPtr, /* Path of file to access (in current CP). */ int mode) /* Permission setting. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->accessProc != NULL) { return fsPtr->accessProc(pathPtr, mode); } Tcl_SetErrno(ENOENT); return -1; } /* *---------------------------------------------------------------------- * * Tcl_FSOpenFileChannel -- * * The appropriate function for the filesystem to which pathPtr belongs * will be called. * * Results: * The new channel or NULL, if the named file could not be opened. * * Side effects: * May open the channel and may cause creation of a file on the file * system. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_FSOpenFileChannel( Tcl_Interp *interp, /* Interpreter for error reporting; can be * NULL. */ Tcl_Obj *pathPtr, /* Name of file to open. */ const char *modeString, /* A list of POSIX open modes or a string such * as "rw". */ int permissions) /* If the open involves creating a file, with * what modes to create it? */ { const Tcl_Filesystem *fsPtr; Tcl_Channel retVal = NULL; /* * We need this just to ensure we return the correct error messages under * some circumstances. */ if (Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL) { return NULL; } fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->openFileChannelProc != NULL) { int mode, seekFlag, binary; /* * Parse the mode, picking up whether we want to seek to start with * and/or set the channel automatically into binary mode. */ mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary); if (mode == -1) { return NULL; } /* * Do the actual open() call. */ retVal = fsPtr->openFileChannelProc(interp, pathPtr, mode, permissions); if (retVal == NULL) { return NULL; } /* * Apply appropriate flags parsed out above. */ if (seekFlag && Tcl_Seek(retVal, (Tcl_WideInt) 0, SEEK_END) < (Tcl_WideInt) 0) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not seek to end of file while opening \"%s\": %s", Tcl_GetString(pathPtr), Tcl_PosixError(interp))); } Tcl_Close(NULL, retVal); return NULL; } if (binary) { Tcl_SetChannelOption(interp, retVal, "-translation", "binary"); } return retVal; } /* * File doesn't belong to any filesystem that can open it. */ Tcl_SetErrno(ENOENT); if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open \"%s\": %s", Tcl_GetString(pathPtr), Tcl_PosixError(interp))); } return NULL; } /* *---------------------------------------------------------------------- * * Tcl_FSUtime -- * * This function replaces the library version of utime. The appropriate * function for the filesystem to which pathPtr belongs will be called. * * Results: * See utime documentation. * * Side effects: * See utime documentation. * *---------------------------------------------------------------------- */ int Tcl_FSUtime( Tcl_Obj *pathPtr, /* File to change access/modification * times. */ struct utimbuf *tval) /* Structure containing access/modification * times to use. Should not be modified. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->utimeProc != NULL) { return fsPtr->utimeProc(pathPtr, tval); } /* TODO: set errno here? Tcl_SetErrno(ENOENT); */ return -1; } /* *---------------------------------------------------------------------- * * NativeFileAttrStrings -- * * This function implements the platform dependent 'file attributes' * subcommand, for the native filesystem, for listing the set of possible * attribute strings. This function is part of Tcl's native filesystem * support, and is placed here because it is shared by Unix and Windows * code. * * Results: * An array of strings * * Side effects: * None. * *---------------------------------------------------------------------- */ static const char *const * NativeFileAttrStrings( Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef) { return tclpFileAttrStrings; } /* *---------------------------------------------------------------------- * * NativeFileAttrsGet -- * * This function implements the platform dependent 'file attributes' * subcommand, for the native filesystem, for 'get' operations. This * function is part of Tcl's native filesystem support, and is placed * here because it is shared by Unix and Windows code. * * Results: * Standard Tcl return code. The object placed in objPtrRef (if TCL_OK * was returned) is likely to have a refCount of zero. Either way we must * either store it somewhere (e.g. the Tcl result), or Incr/Decr its * refCount to ensure it is properly freed. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int NativeFileAttrsGet( Tcl_Interp *interp, /* The interpreter for error reporting. */ int index, /* index of the attribute command. */ Tcl_Obj *pathPtr, /* path of file we are operating on. */ Tcl_Obj **objPtrRef) /* for output. */ { return tclpFileAttrProcs[index].getProc(interp, index, pathPtr,objPtrRef); } /* *---------------------------------------------------------------------- * * NativeFileAttrsSet -- * * This function implements the platform dependent 'file attributes' * subcommand, for the native filesystem, for 'set' operations. This * function is part of Tcl's native filesystem support, and is placed * here because it is shared by Unix and Windows code. * * Results: * Standard Tcl return code. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int NativeFileAttrsSet( Tcl_Interp *interp, /* The interpreter for error reporting. */ int index, /* index of the attribute command. */ Tcl_Obj *pathPtr, /* path of file we are operating on. */ Tcl_Obj *objPtr) /* set to this value. */ { return tclpFileAttrProcs[index].setProc(interp, index, pathPtr, objPtr); } /* *---------------------------------------------------------------------- * * Tcl_FSFileAttrStrings -- * * This function implements part of the hookable 'file attributes' * subcommand. The appropriate function for the filesystem to which * pathPtr belongs will be called. * * Results: * The called function may either return an array of strings, or may * instead return NULL and place a Tcl list into the given objPtrRef. * Tcl will take that list and first increment its refCount before using * it. On completion of that use, Tcl will decrement its refCount. Hence * if the list should be disposed of by Tcl when done, it should have a * refCount of zero, and if the list should not be disposed of, the * filesystem should ensure it retains a refCount on the object. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char *const * Tcl_FSFileAttrStrings( Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef) { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->fileAttrStringsProc != NULL) { return fsPtr->fileAttrStringsProc(pathPtr, objPtrRef); } Tcl_SetErrno(ENOENT); return NULL; } /* *---------------------------------------------------------------------- * * TclFSFileAttrIndex -- * * Helper function for converting an attribute name to an index into the * attribute table. * * Results: * Tcl result code, index written to *indexPtr on result==TCL_OK * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclFSFileAttrIndex( Tcl_Obj *pathPtr, /* File whose attributes are to be indexed * into. */ const char *attributeName, /* The attribute being looked for. */ int *indexPtr) /* Where to write the found index. */ { Tcl_Obj *listObj = NULL; const char *const *attrTable; /* * Get the attribute table for the file. */ attrTable = Tcl_FSFileAttrStrings(pathPtr, &listObj); if (listObj != NULL) { Tcl_IncrRefCount(listObj); } if (attrTable != NULL) { /* * It's a constant attribute table, so use T_GIFO. */ Tcl_Obj *tmpObj = Tcl_NewStringObj(attributeName, -1); int result; result = Tcl_GetIndexFromObj(NULL, tmpObj, attrTable, NULL, TCL_EXACT, indexPtr); TclDecrRefCount(tmpObj); if (listObj != NULL) { TclDecrRefCount(listObj); } return result; } else if (listObj != NULL) { /* * It's a non-constant attribute list, so do a literal search. */ int i, objc; Tcl_Obj **objv; if (Tcl_ListObjGetElements(NULL, listObj, &objc, &objv) != TCL_OK) { TclDecrRefCount(listObj); return TCL_ERROR; } for (i=0 ; ifileAttrsGetProc != NULL) { return fsPtr->fileAttrsGetProc(interp, index, pathPtr, objPtrRef); } Tcl_SetErrno(ENOENT); return -1; } /* *---------------------------------------------------------------------- * * Tcl_FSFileAttrsSet -- * * This function implements write access for the hookable 'file * attributes' subcommand. The appropriate function for the filesystem to * which pathPtr belongs will be called. * * Results: * Standard Tcl return code. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_FSFileAttrsSet( Tcl_Interp *interp, /* The interpreter for error reporting. */ int index, /* index of the attribute command. */ Tcl_Obj *pathPtr, /* filename we are operating on. */ Tcl_Obj *objPtr) /* Input value. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->fileAttrsSetProc != NULL) { return fsPtr->fileAttrsSetProc(interp, index, pathPtr, objPtr); } Tcl_SetErrno(ENOENT); return -1; } /* *---------------------------------------------------------------------- * * Tcl_FSGetCwd -- * * This function replaces the library version of getcwd(). * * Most VFS's will *not* implement a 'cwdProc'. Tcl now maintains its own * record (in a Tcl_Obj) of the cwd, and an attempt is made to synch this * with the cwd's containing filesystem, if that filesystem provides a * cwdProc (e.g. the native filesystem). * * Note that if Tcl's cwd is not in the native filesystem, then of course * Tcl's cwd and the native cwd are different: extensions should * therefore ensure they only access the cwd through this function to * avoid confusion. * * If a global cwdPathPtr already exists, it is cached in the thread's * private data structures and reference to the cached copy is returned, * subject to a synchronisation attempt in that cwdPathPtr's fs. * * Otherwise, the chain of functions that have been "inserted" into the * filesystem will be called in succession until either a value other * than NULL is returned, or the entire list is visited. * * Results: * The result is a pointer to a Tcl_Obj specifying the current directory, * or NULL if the current directory could not be determined. If NULL is * returned, an error message is left in the interp's result. * * The result already has its refCount incremented for the caller. When * it is no longer needed, that refCount should be decremented. * * Side effects: * Various objects may be freed and allocated. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSGetCwd( Tcl_Interp *interp) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); if (TclFSCwdPointerEquals(NULL)) { FilesystemRecord *fsRecPtr; Tcl_Obj *retVal = NULL; /* * We've never been called before, try to find a cwd. Call each of the * "Tcl_GetCwd" function in succession. A non-NULL return value * indicates the particular function has succeeded. */ fsRecPtr = FsGetFirstFilesystem(); Claim(); for (; (retVal == NULL) && (fsRecPtr != NULL); fsRecPtr = fsRecPtr->nextPtr) { ClientData retCd; TclFSGetCwdProc2 *proc2; if (fsRecPtr->fsPtr->getCwdProc == NULL) { continue; } if (fsRecPtr->fsPtr->version == TCL_FILESYSTEM_VERSION_1) { retVal = fsRecPtr->fsPtr->getCwdProc(interp); continue; } proc2 = (TclFSGetCwdProc2 *) fsRecPtr->fsPtr->getCwdProc; retCd = proc2(NULL); if (retCd != NULL) { Tcl_Obj *norm; /* * Looks like a new current directory. */ retVal = fsRecPtr->fsPtr->internalToNormalizedProc(retCd); Tcl_IncrRefCount(retVal); norm = TclFSNormalizeAbsolutePath(interp,retVal); if (norm != NULL) { /* * We found a cwd, which is now in our global storage. We * must make a copy. Norm already has a refCount of 1. * * Threading issue: note that multiple threads at system * startup could in principle call this function * simultaneously. They will therefore each set the * cwdPathPtr independently. That behaviour is a bit * peculiar, but should be fine. Once we have a cwd, we'll * always be in the 'else' branch below which is simpler. */ FsUpdateCwd(norm, retCd); Tcl_DecrRefCount(norm); } else { fsRecPtr->fsPtr->freeInternalRepProc(retCd); } Tcl_DecrRefCount(retVal); retVal = NULL; Disclaim(); goto cdDidNotChange; } else if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error getting working directory name: %s", Tcl_PosixError(interp))); } } Disclaim(); /* * Now the 'cwd' may NOT be normalized, at least on some platforms. * For the sake of efficiency, we want a completely normalized cwd at * all times. * * Finally, if retVal is NULL, we do not have a cwd, which could be * problematic. */ if (retVal != NULL) { Tcl_Obj *norm = TclFSNormalizeAbsolutePath(interp, retVal); if (norm != NULL) { /* * We found a cwd, which is now in our global storage. We must * make a copy. Norm already has a refCount of 1. * * Threading issue: note that multiple threads at system * startup could in principle call this function * simultaneously. They will therefore each set the cwdPathPtr * independently. That behaviour is a bit peculiar, but should * be fine. Once we have a cwd, we'll always be in the 'else' * branch below which is simpler. */ ClientData cd = (ClientData) Tcl_FSGetNativePath(norm); FsUpdateCwd(norm, TclNativeDupInternalRep(cd)); Tcl_DecrRefCount(norm); } Tcl_DecrRefCount(retVal); } } else { /* * We already have a cwd cached, but we want to give the filesystem it * is in a chance to check whether that cwd has changed, or is perhaps * no longer accessible. This allows an error to be thrown if, say, * the permissions on that directory have changed. */ const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(tsdPtr->cwdPathPtr); ClientData retCd = NULL; Tcl_Obj *retVal, *norm; /* * If the filesystem couldn't be found, or if no cwd function exists * for this filesystem, then we simply assume the cached cwd is ok. * If we do call a cwd, we must watch for errors (if the cwd returns * NULL). This ensures that, say, on Unix if the permissions of the * cwd change, 'pwd' does actually throw the correct error in Tcl. * (This is tested for in the test suite on unix). */ if (fsPtr == NULL || fsPtr->getCwdProc == NULL) { goto cdDidNotChange; } if (fsPtr->version == TCL_FILESYSTEM_VERSION_1) { retVal = fsPtr->getCwdProc(interp); } else { /* * New API. */ TclFSGetCwdProc2 *proc2 = (TclFSGetCwdProc2 *) fsPtr->getCwdProc; retCd = proc2(tsdPtr->cwdClientData); if (retCd == NULL && interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error getting working directory name: %s", Tcl_PosixError(interp))); } if (retCd == tsdPtr->cwdClientData) { goto cdDidNotChange; } /* * Looks like a new current directory. */ retVal = fsPtr->internalToNormalizedProc(retCd); Tcl_IncrRefCount(retVal); } /* * Check if the 'cwd' function returned an error; if so, reset the * cwd. */ if (retVal == NULL) { FsUpdateCwd(NULL, NULL); goto cdDidNotChange; } /* * Normalize the path. */ norm = TclFSNormalizeAbsolutePath(interp, retVal); /* * Check whether cwd has changed from the value previously stored in * cwdPathPtr. Really 'norm' shouldn't be NULL, but we are careful. */ if (norm == NULL) { /* Do nothing */ if (retCd != NULL) { fsPtr->freeInternalRepProc(retCd); } } else if (norm == tsdPtr->cwdPathPtr) { goto cdEqual; } else { /* * Note that both 'norm' and 'tsdPtr->cwdPathPtr' are normalized * paths. Therefore we can be more efficient than calling * 'Tcl_FSEqualPaths', and in addition avoid a nasty infinite loop * bug when trying to normalize tsdPtr->cwdPathPtr. */ int len1, len2; const char *str1, *str2; str1 = Tcl_GetStringFromObj(tsdPtr->cwdPathPtr, &len1); str2 = Tcl_GetStringFromObj(norm, &len2); if ((len1 == len2) && (strcmp(str1, str2) == 0)) { /* * If the paths were equal, we can be more efficient and * retain the old path object which will probably already be * shared. In this case we can simply free the normalized path * we just calculated. */ cdEqual: Tcl_DecrRefCount(norm); if (retCd != NULL) { fsPtr->freeInternalRepProc(retCd); } } else { FsUpdateCwd(norm, retCd); Tcl_DecrRefCount(norm); } } Tcl_DecrRefCount(retVal); } cdDidNotChange: if (tsdPtr->cwdPathPtr != NULL) { Tcl_IncrRefCount(tsdPtr->cwdPathPtr); } return tsdPtr->cwdPathPtr; } /* *---------------------------------------------------------------------- * * Tcl_FSChdir -- * * This function replaces the library version of chdir(). * * The path is normalized and then passed to the filesystem which claims * it. * * Results: * See chdir() documentation. If successful, we keep a record of the * successful path in cwdPathPtr for subsequent calls to getcwd. * * Side effects: * See chdir() documentation. The global cwdPathPtr may change value. * *---------------------------------------------------------------------- */ int Tcl_FSChdir( Tcl_Obj *pathPtr) { const Tcl_Filesystem *fsPtr, *oldFsPtr = NULL; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey); int retVal = -1; if (tsdPtr->cwdPathPtr != NULL) { oldFsPtr = Tcl_FSGetFileSystemForPath(tsdPtr->cwdPathPtr); } if (Tcl_FSGetNormalizedPath(NULL, pathPtr) == NULL) { Tcl_SetErrno(ENOENT); return retVal; } fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL) { if (fsPtr->chdirProc != NULL) { /* * If this fails, an appropriate errno will have been stored using * 'Tcl_SetErrno()'. */ retVal = fsPtr->chdirProc(pathPtr); } else { /* * Fallback on stat-based implementation. */ Tcl_StatBuf buf; /* * If the file can be stat'ed and is a directory and is readable, * then we can chdir. If any of these actions fail, then * 'Tcl_SetErrno()' should automatically have been called to set * an appropriate error code. */ if ((Tcl_FSStat(pathPtr, &buf) == 0) && (S_ISDIR(buf.st_mode)) && (Tcl_FSAccess(pathPtr, R_OK) == 0)) { /* * We allow the chdir. */ retVal = 0; } } } else { Tcl_SetErrno(ENOENT); } /* * The cwd changed, or an error was thrown. If an error was thrown, we can * just continue (and that will report the error to the user). If there * was no error we must assume that the cwd was actually changed to the * normalized value we calculated above, and we must therefore cache that * information. * * If the filesystem in question has a getCwdProc, then the correct logic * which performs the part below is already part of the Tcl_FSGetCwd() * call, so no need to replicate it again. This will have a side effect * though. The private authoritative representation of the current working * directory stored in cwdPathPtr in static memory will be out-of-sync * with the real OS-maintained value. The first call to Tcl_FSGetCwd will * however recalculate the private copy to match the OS-value so * everything will work right. * * However, if there is no getCwdProc, then we _must_ update our private * storage of the cwd, since this is the only opportunity to do that! * * Note: We currently call this block of code irrespective of whether * there was a getCwdProc or not, but the code should all in principle * work if we only call this block if fsPtr->getCwdProc == NULL. */ if (retVal == 0) { /* * Note that this normalized path may be different to what we found * above (or at least a different object), if the filesystem epoch * changed recently. This can actually happen with scripted documents * very easily. Therefore we ask for the normalized path again (the * correct value will have been cached as a result of the * Tcl_FSGetFileSystemForPath call above anyway). */ Tcl_Obj *normDirName = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (normDirName == NULL) { /* Not really true, but what else to do? */ Tcl_SetErrno(ENOENT); return -1; } if (fsPtr == &tclNativeFilesystem) { /* * For the native filesystem, we keep a cache of the native * representation of the cwd. But, we want to do that for the * exact format that is returned by 'getcwd' (so that we can later * compare the two representations for equality), which might not * be exactly the same char-string as the native representation of * the fully normalized path (e.g. on Windows there's a * forward-slash vs backslash difference). Hence we ask for this * again here. On Unix it might actually be true that we always * have the correct form in the native rep in which case we could * simply use: * cd = Tcl_FSGetNativePath(pathPtr); * instead. This should be examined by someone on Unix. */ ClientData cd; ClientData oldcd = tsdPtr->cwdClientData; /* * Assumption we are using a filesystem version 2. */ TclFSGetCwdProc2 *proc2 = (TclFSGetCwdProc2 *) fsPtr->getCwdProc; cd = proc2(oldcd); if (cd != oldcd) { FsUpdateCwd(normDirName, cd); } } else { FsUpdateCwd(normDirName, NULL); } /* * If the filesystem changed between old and new cwd * force filesystem refresh on path objects. */ if (oldFsPtr != NULL && fsPtr != oldFsPtr) { Tcl_FSMountsChanged(NULL); } } return retVal; } /* *---------------------------------------------------------------------- * * Tcl_FSLoadFile -- * * Dynamically loads a binary code file into memory and returns the * addresses of two functions within that file, if they are defined. The * appropriate function for the filesystem to which pathPtr belongs will * be called. * * Note that the native filesystem doesn't actually assume 'pathPtr' is a * path. Rather it assumes pathPtr is either a path or just the name * (tail) of a file which can be found somewhere in the environment's * loadable path. This behaviour is not very compatible with virtual * filesystems (and has other problems documented in the load man-page), * so it is advised that full paths are always used. * * Results: * A standard Tcl completion code. If an error occurs, an error message * is left in the interp's result. * * Side effects: * New code suddenly appears in memory. This may later be unloaded by * passing the clientData to the unloadProc. * *---------------------------------------------------------------------- */ int Tcl_FSLoadFile( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Obj *pathPtr, /* Name of the file containing the desired * code. */ const char *sym1, const char *sym2, /* Names of two functions to look up in the * file's symbol table. */ Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr, /* Where to return the addresses corresponding * to sym1 and sym2. */ Tcl_LoadHandle *handlePtr, /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr) /* Filled with address of Tcl_FSUnloadFileProc * function which should be used for this * file. */ { const char *symbols[3]; void *procPtrs[2]; int res; /* * Initialize the arrays. */ symbols[0] = sym1; symbols[1] = sym2; symbols[2] = NULL; /* * Perform the load. */ res = Tcl_LoadFile(interp, pathPtr, symbols, 0, procPtrs, handlePtr); if (res == TCL_OK) { *proc1Ptr = (Tcl_PackageInitProc *) procPtrs[0]; *proc2Ptr = (Tcl_PackageInitProc *) procPtrs[1]; } else { *proc1Ptr = *proc2Ptr = NULL; } return res; } /* *---------------------------------------------------------------------- * * Tcl_LoadFile -- * * Dynamically loads a binary code file into memory and returns the * addresses of a number of given functions within that file, if they are * defined. The appropriate function for the filesystem to which pathPtr * belongs will be called. * * Note that the native filesystem doesn't actually assume 'pathPtr' is a * path. Rather it assumes pathPtr is either a path or just the name * (tail) of a file which can be found somewhere in the environment's * loadable path. This behaviour is not very compatible with virtual * filesystems (and has other problems documented in the load man-page), * so it is advised that full paths are always used. * * Results: * A standard Tcl completion code. If an error occurs, an error message * is left in the interp's result. * * Side effects: * New code suddenly appears in memory. This may later be unloaded by * calling TclFS_UnloadFile. * *---------------------------------------------------------------------- */ /* * Workaround for issue with modern HPUX which do allow the unlink (no ETXTBSY * error) yet somehow trash some internal data structures which prevents the * second and further shared libraries from getting properly loaded. Only the * first is ok. We try to get around the issue by not unlinking, * i.e. emulating the behaviour of the older HPUX which denied removal. * * Doing the unlink is also an issue within docker containers, whose AUFS * bungles this as well, see * https://github.com/dotcloud/docker/issues/1911 * * For these situations the change below makes the execution of the unlink * semi-controllable at runtime. * * An AUFS filesystem (if it can be detected) will force avoidance of * unlink. The env variable TCL_TEMPLOAD_NO_UNLINK allows detection of a * users general request (unlink and not. * * By default the unlink is done (if not in AUFS). However if the variable is * present and set to true (any integer > 0) then the unlink is skipped. */ int TclSkipUnlink (Tcl_Obj* shlibFile) { /* Order of testing: * 1. On hpux we generally want to skip unlink in general * * Outside of hpux then: * 2. For a general user request (TCL_TEMPLOAD_NO_UNLINK present, non-empty, => int) * 3. For general AUFS environment (statfs, if available). * * Ad 2: This variable can disable/override the AUFS detection, i.e. for * testing if a newer AUFS does not have the bug any more. * * Ad 3: This is conditionally compiled in. Condition currently must be set manually. * This part needs proper tests in the configure(.in). */ #ifdef hpux return 1; #else char* skipstr; skipstr = getenv ("TCL_TEMPLOAD_NO_UNLINK"); if (skipstr && (skipstr[0] != '\0')) { return atoi(skipstr); } #ifdef TCL_TEMPLOAD_NO_UNLINK #ifndef NO_FSTATFS { struct statfs fs; /* Have fstatfs. May not have the AUFS super magic ... Indeed our build * box is too old to have it directly in the headers. Define taken from * http://mooon.googlecode.com/svn/trunk/linux_include/linux/aufs_type.h * http://aufs.sourceforge.net/ * Better reference will be gladly taken. */ #ifndef AUFS_SUPER_MAGIC #define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') #endif /* AUFS_SUPER_MAGIC */ if ((statfs(Tcl_GetString (shlibFile), &fs) == 0) && (fs.f_type == AUFS_SUPER_MAGIC)) { return 1; } } #endif /* ... NO_FSTATFS */ #endif /* ... TCL_TEMPLOAD_NO_UNLINK */ /* Fallback: !hpux, no EV override, no AUFS (detection, nor detected): * Don't skip */ return 0; #endif /* hpux */ } int Tcl_LoadFile( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Obj *pathPtr, /* Name of the file containing the desired * code. */ const char *const symbols[],/* Names of functions to look up in the file's * symbol table. */ int flags, /* Flags */ void *procVPtrs, /* Where to return the addresses corresponding * to symbols[]. */ Tcl_LoadHandle *handlePtr) /* Filled with token for shared library * information which can be used in * TclpFindSymbol. */ { void **procPtrs = (void **) procVPtrs; const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); const Tcl_Filesystem *copyFsPtr; Tcl_FSUnloadFileProc *unloadProcPtr; Tcl_Obj *copyToPtr; Tcl_LoadHandle newLoadHandle = NULL; Tcl_LoadHandle divertedLoadHandle = NULL; Tcl_FSUnloadFileProc *newUnloadProcPtr = NULL; FsDivertLoad *tvdlPtr; int retVal; int i; if (fsPtr == NULL) { Tcl_SetErrno(ENOENT); return TCL_ERROR; } if (fsPtr->loadFileProc != NULL) { int retVal = ((Tcl_FSLoadFileProc2 *)(fsPtr->loadFileProc)) (interp, pathPtr, handlePtr, &unloadProcPtr, flags); if (retVal == TCL_OK) { if (*handlePtr == NULL) { return TCL_ERROR; } if (interp) { Tcl_ResetResult(interp); } goto resolveSymbols; } if (Tcl_GetErrno() != EXDEV) { return retVal; } } /* * The filesystem doesn't support 'load', so we fall back on the following * technique: * * First check if it is readable -- and exists! */ if (Tcl_FSAccess(pathPtr, R_OK) != 0) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't load library \"%s\": %s", Tcl_GetString(pathPtr), Tcl_PosixError(interp))); } return TCL_ERROR; } #ifdef TCL_LOAD_FROM_MEMORY /* * The platform supports loading code from memory, so ask for a buffer of * the appropriate size, read the file into it and load the code from the * buffer: */ { int ret, size; void *buffer; Tcl_StatBuf statBuf; Tcl_Channel data; ret = Tcl_FSStat(pathPtr, &statBuf); if (ret < 0) { goto mustCopyToTempAnyway; } size = (int) statBuf.st_size; /* * Tcl_Read takes an int: check that file size isn't wide. */ if (size != (Tcl_WideInt) statBuf.st_size) { goto mustCopyToTempAnyway; } data = Tcl_FSOpenFileChannel(interp, pathPtr, "rb", 0666); if (!data) { goto mustCopyToTempAnyway; } buffer = TclpLoadMemoryGetBuffer(interp, size); if (!buffer) { Tcl_Close(interp, data); goto mustCopyToTempAnyway; } ret = Tcl_Read(data, buffer, size); Tcl_Close(interp, data); ret = TclpLoadMemory(interp, buffer, size, ret, handlePtr, &unloadProcPtr, flags); if (ret == TCL_OK && *handlePtr != NULL) { goto resolveSymbols; } } mustCopyToTempAnyway: if (interp) { Tcl_ResetResult(interp); } #endif /* TCL_LOAD_FROM_MEMORY */ /* * Get a temporary filename to use, first to copy the file into, and then * to load. */ copyToPtr = TclpTempFileNameForLibrary(interp, pathPtr); if (copyToPtr == NULL) { return TCL_ERROR; } Tcl_IncrRefCount(copyToPtr); copyFsPtr = Tcl_FSGetFileSystemForPath(copyToPtr); if ((copyFsPtr == NULL) || (copyFsPtr == fsPtr)) { /* * We already know we can't use Tcl_FSLoadFile from this filesystem, * and we must avoid a possible infinite loop. Try to delete the file * we probably created, and then exit. */ Tcl_FSDeleteFile(copyToPtr); Tcl_DecrRefCount(copyToPtr); if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "couldn't load from current filesystem", -1)); } return TCL_ERROR; } if (TclCrossFilesystemCopy(interp, pathPtr, copyToPtr) != TCL_OK) { /* * Cross-platform copy failed. */ Tcl_FSDeleteFile(copyToPtr); Tcl_DecrRefCount(copyToPtr); return TCL_ERROR; } #ifndef _WIN32 /* * Do we need to set appropriate permissions on the file? This may be * required on some systems. On Unix we could loop over the file * attributes, and set any that are called "-permissions" to 0700. However * we just do this directly, like this: */ { int index; Tcl_Obj *perm; TclNewLiteralStringObj(perm, "0700"); Tcl_IncrRefCount(perm); if (TclFSFileAttrIndex(copyToPtr, "-permissions", &index) == TCL_OK) { Tcl_FSFileAttrsSet(NULL, index, copyToPtr, perm); } Tcl_DecrRefCount(perm); } #endif /* * We need to reset the result now, because the cross-filesystem copy may * have stored the number of bytes in the result. */ if (interp) { Tcl_ResetResult(interp); } retVal = Tcl_LoadFile(interp, copyToPtr, symbols, flags, procPtrs, &newLoadHandle); if (retVal != TCL_OK) { /* * The file didn't load successfully. */ Tcl_FSDeleteFile(copyToPtr); Tcl_DecrRefCount(copyToPtr); return retVal; } /* * Try to delete the file immediately - this is possible in some OSes, and * avoids any worries about leaving the copy laying around on exit. */ if ( !TclSkipUnlink (copyToPtr) && (Tcl_FSDeleteFile(copyToPtr) == TCL_OK)) { Tcl_DecrRefCount(copyToPtr); /* * We tell our caller about the real shared library which was loaded. * Note that this does mean that the package list maintained by 'load' * will store the original (vfs) path alongside the temporary load * handle and unload proc ptr. */ *handlePtr = newLoadHandle; if (interp) { Tcl_ResetResult(interp); } return TCL_OK; } /* * When we unload this file, we need to divert the unloading so we can * unload and cleanup the temporary file correctly. */ tvdlPtr = ckalloc(sizeof(FsDivertLoad)); /* * Remember three pieces of information. This allows us to cleanup the * diverted load completely, on platforms which allow proper unloading of * code. */ tvdlPtr->loadHandle = newLoadHandle; tvdlPtr->unloadProcPtr = newUnloadProcPtr; if (copyFsPtr != &tclNativeFilesystem) { /* * copyToPtr is already incremented for this reference. */ tvdlPtr->divertedFile = copyToPtr; /* * This is the filesystem we loaded it into. Since we have a reference * to 'copyToPtr', we already have a refCount on this filesystem, so * we don't need to worry about it disappearing on us. */ tvdlPtr->divertedFilesystem = copyFsPtr; tvdlPtr->divertedFileNativeRep = NULL; } else { /* * We need the native rep. */ tvdlPtr->divertedFileNativeRep = TclNativeDupInternalRep( Tcl_FSGetInternalRep(copyToPtr, copyFsPtr)); /* * We don't need or want references to the copied Tcl_Obj or the * filesystem if it is the native one. */ tvdlPtr->divertedFile = NULL; tvdlPtr->divertedFilesystem = NULL; Tcl_DecrRefCount(copyToPtr); } copyToPtr = NULL; divertedLoadHandle = ckalloc(sizeof(struct Tcl_LoadHandle_)); divertedLoadHandle->clientData = tvdlPtr; divertedLoadHandle->findSymbolProcPtr = DivertFindSymbol; divertedLoadHandle->unloadFileProcPtr = DivertUnloadFile; *handlePtr = divertedLoadHandle; if (interp) { Tcl_ResetResult(interp); } return retVal; resolveSymbols: /* * At this point, *handlePtr is already set up to the handle for the * loaded library. We now try to resolve the symbols. */ if (symbols != NULL) { for (i=0 ; symbols[i] != NULL; i++) { procPtrs[i] = Tcl_FindSymbol(interp, *handlePtr, symbols[i]); if (procPtrs[i] == NULL) { /* * At least one symbol in the list was not found. Unload the * file, and report the problem back to the caller. * (Tcl_FindSymbol should already have left an appropriate * error message.) */ (*handlePtr)->unloadFileProcPtr(*handlePtr); *handlePtr = NULL; return TCL_ERROR; } } } return TCL_OK; } /* *---------------------------------------------------------------------- * * DivertFindSymbol -- * * Find a symbol in a shared library loaded by copy-from-VFS. * *---------------------------------------------------------------------- */ static void * DivertFindSymbol( Tcl_Interp *interp, /* Tcl interpreter */ Tcl_LoadHandle loadHandle, /* Handle to the diverted module */ const char *symbol) /* Symbol to resolve */ { FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle->clientData; Tcl_LoadHandle originalHandle = tvdlPtr->loadHandle; return originalHandle->findSymbolProcPtr(interp, originalHandle, symbol); } /* *---------------------------------------------------------------------- * * DivertUnloadFile -- * * Unloads a file that has been loaded by copying from VFS to the native * filesystem. * * Parameters: * loadHandle -- Handle of the file to unload * *---------------------------------------------------------------------- */ static void DivertUnloadFile( Tcl_LoadHandle loadHandle) { FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle->clientData; Tcl_LoadHandle originalHandle; /* * This test should never trigger, since we give the client data in the * function above. */ if (tvdlPtr == NULL) { return; } originalHandle = tvdlPtr->loadHandle; /* * Call the real 'unloadfile' proc we actually used. It is very important * that we call this first, so that the shared library is actually * unloaded by the OS. Otherwise, the following 'delete' may well fail * because the shared library is still in use. */ originalHandle->unloadFileProcPtr(originalHandle); /* * What filesystem contains the temp copy of the library? */ if (tvdlPtr->divertedFilesystem == NULL) { /* * It was the native filesystem, and we have a special function * available just for this purpose, which we know works even at this * late stage. */ TclpDeleteFile(tvdlPtr->divertedFileNativeRep); NativeFreeInternalRep(tvdlPtr->divertedFileNativeRep); } else { /* * Remove the temporary file we created. Note, we may crash here * because encodings have been taken down already. */ if (tvdlPtr->divertedFilesystem->deleteFileProc(tvdlPtr->divertedFile) != TCL_OK) { /* * The above may have failed because the filesystem, or something * it depends upon (e.g. encodings) have been taken down because * Tcl is exiting. * * We may need to work out how to delete this file more robustly * (or give the filesystem the information it needs to delete the * file more robustly). * * In particular, one problem might be that the filesystem cannot * extract the information it needs from the above path object * because Tcl's entire filesystem apparatus (the code in this * file) has been finalized, and it refuses to pass the internal * representation to the filesystem. */ } /* * And free up the allocations. This will also of course remove a * refCount from the Tcl_Filesystem to which this file belongs, which * could then free up the filesystem if we are exiting. */ Tcl_DecrRefCount(tvdlPtr->divertedFile); } ckfree(tvdlPtr); ckfree(loadHandle); } /* *---------------------------------------------------------------------- * * Tcl_FindSymbol -- * * Find a symbol in a loaded library * * Results: * Returns a pointer to the symbol if found. If not found, returns NULL * and leaves an error message in the interpreter result. * * This function was once filesystem-specific, but has been made portable by * having TclpDlopen return a structure that includes procedure pointers. * *---------------------------------------------------------------------- */ void * Tcl_FindSymbol( Tcl_Interp *interp, /* Tcl interpreter */ Tcl_LoadHandle loadHandle, /* Handle to the loaded library */ const char *symbol) /* Name of the symbol to resolve */ { return loadHandle->findSymbolProcPtr(interp, loadHandle, symbol); } /* *---------------------------------------------------------------------- * * Tcl_FSUnloadFile -- * * Unloads a library given its handle. Checks first that the library * supports unloading. * *---------------------------------------------------------------------- */ int Tcl_FSUnloadFile( Tcl_Interp *interp, /* Tcl interpreter */ Tcl_LoadHandle handle) /* Handle of the file to unload */ { if (handle->unloadFileProcPtr == NULL) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot unload: filesystem does not support unloading", -1)); } return TCL_ERROR; } TclpUnloadFile(handle); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclpUnloadFile -- * * Unloads a library given its handle * * This function was once filesystem-specific, but has been made portable by * having TclpDlopen return a structure that includes procedure pointers. * *---------------------------------------------------------------------- */ void TclpUnloadFile( Tcl_LoadHandle handle) { if (handle->unloadFileProcPtr != NULL) { handle->unloadFileProcPtr(handle); } } /* *---------------------------------------------------------------------- * * TclFSUnloadTempFile -- * * This function is called when we loaded a library of code via an * intermediate temporary file. This function ensures the library is * correctly unloaded and the temporary file is correctly deleted. * * Results: * None. * * Side effects: * The effects of the 'unload' function called, and of course the * temporary file will be deleted. * *---------------------------------------------------------------------- */ void TclFSUnloadTempFile( Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to * Tcl_FSLoadFile(). The loadHandle is a token * that represents the loaded file. */ { FsDivertLoad *tvdlPtr = (FsDivertLoad *) loadHandle; /* * This test should never trigger, since we give the client data in the * function above. */ if (tvdlPtr == NULL) { return; } /* * Call the real 'unloadfile' proc we actually used. It is very important * that we call this first, so that the shared library is actually * unloaded by the OS. Otherwise, the following 'delete' may well fail * because the shared library is still in use. */ if (tvdlPtr->unloadProcPtr != NULL) { tvdlPtr->unloadProcPtr(tvdlPtr->loadHandle); } if (tvdlPtr->divertedFilesystem == NULL) { /* * It was the native filesystem, and we have a special function * available just for this purpose, which we know works even at this * late stage. */ TclpDeleteFile(tvdlPtr->divertedFileNativeRep); NativeFreeInternalRep(tvdlPtr->divertedFileNativeRep); } else { /* * Remove the temporary file we created. Note, we may crash here * because encodings have been taken down already. */ if (tvdlPtr->divertedFilesystem->deleteFileProc(tvdlPtr->divertedFile) != TCL_OK) { /* * The above may have failed because the filesystem, or something * it depends upon (e.g. encodings) have been taken down because * Tcl is exiting. * * We may need to work out how to delete this file more robustly * (or give the filesystem the information it needs to delete the * file more robustly). * * In particular, one problem might be that the filesystem cannot * extract the information it needs from the above path object * because Tcl's entire filesystem apparatus (the code in this * file) has been finalized, and it refuses to pass the internal * representation to the filesystem. */ } /* * And free up the allocations. This will also of course remove a * refCount from the Tcl_Filesystem to which this file belongs, which * could then free up the filesystem if we are exiting. */ Tcl_DecrRefCount(tvdlPtr->divertedFile); } ckfree(tvdlPtr); } /* *--------------------------------------------------------------------------- * * Tcl_FSLink -- * * This function replaces the library version of readlink() and can also * be used to make links. The appropriate function for the filesystem to * which pathPtr belongs will be called. * * Results: * If toPtr is NULL, then the result is a Tcl_Obj specifying the contents * of the symbolic link given by 'pathPtr', or NULL if the symbolic link * could not be read. The result is owned by the caller, which should * call Tcl_DecrRefCount when the result is no longer needed. * * If toPtr is non-NULL, then the result is toPtr if the link action was * successful, or NULL if not. In this case the result has no additional * reference count, and need not be freed. The actual action to perform * is given by the 'linkAction' flags, which is an or'd combination of: * * TCL_CREATE_SYMBOLIC_LINK * TCL_CREATE_HARD_LINK * * Note that most filesystems will not support linking across to * different filesystems, so this function will usually fail unless toPtr * is in the same FS as pathPtr. * * Side effects: * See readlink() documentation. A new filesystem link object may appear. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSLink( Tcl_Obj *pathPtr, /* Path of file to readlink or link. */ Tcl_Obj *toPtr, /* NULL or path to be linked to. */ int linkAction) /* Action to perform. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->linkProc != NULL) { return fsPtr->linkProc(pathPtr, toPtr, linkAction); } /* * If S_IFLNK isn't defined it means that the machine doesn't support * symbolic links, so the file can't possibly be a symbolic link. Generate * an EINVAL error, which is what happens on machines that do support * symbolic links when you invoke readlink on a file that isn't a symbolic * link. */ #ifndef S_IFLNK errno = EINVAL; /* TODO: Change to Tcl_SetErrno()? */ #else Tcl_SetErrno(ENOENT); #endif /* S_IFLNK */ return NULL; } /* *--------------------------------------------------------------------------- * * Tcl_FSListVolumes -- * * Lists the currently mounted volumes. The chain of functions that have * been "inserted" into the filesystem will be called in succession; each * may return a list of volumes, all of which are added to the result * until all mounted file systems are listed. * * Notice that we assume the lists returned by each filesystem (if non * NULL) have been given a refCount for us already. However, we are NOT * allowed to hang on to the list itself (it belongs to the filesystem we * called). Therefore we quite naturally add its contents to the result * we are building, and then decrement the refCount. * * Results: * The list of volumes, in an object which has refCount 0. * * Side effects: * None * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSListVolumes(void) { FilesystemRecord *fsRecPtr; Tcl_Obj *resultPtr = Tcl_NewObj(); /* * Call each of the "listVolumes" function in succession. A non-NULL * return value indicates the particular function has succeeded. We call * all the functions registered, since we want a list of all drives from * all filesystems. */ fsRecPtr = FsGetFirstFilesystem(); Claim(); while (fsRecPtr != NULL) { if (fsRecPtr->fsPtr->listVolumesProc != NULL) { Tcl_Obj *thisFsVolumes = fsRecPtr->fsPtr->listVolumesProc(); if (thisFsVolumes != NULL) { Tcl_ListObjAppendList(NULL, resultPtr, thisFsVolumes); Tcl_DecrRefCount(thisFsVolumes); } } fsRecPtr = fsRecPtr->nextPtr; } Disclaim(); return resultPtr; } /* *--------------------------------------------------------------------------- * * FsListMounts -- * * List all mounts within the given directory, which match the given * pattern. * * Results: * The list of mounts, in a list object which has refCount 0, or NULL if * we didn't even find any filesystems to try to list mounts. * * Side effects: * None * *--------------------------------------------------------------------------- */ static Tcl_Obj * FsListMounts( Tcl_Obj *pathPtr, /* Contains path to directory to search. */ const char *pattern) /* Pattern to match against. */ { FilesystemRecord *fsRecPtr; Tcl_GlobTypeData mountsOnly = { TCL_GLOB_TYPE_MOUNT, 0, NULL, NULL }; Tcl_Obj *resultPtr = NULL; /* * Call each of the "matchInDirectory" functions in succession, with the * specific type information 'mountsOnly'. A non-NULL return value * indicates the particular function has succeeded. We call all the * functions registered, since we want a list from each filesystems. */ fsRecPtr = FsGetFirstFilesystem(); Claim(); while (fsRecPtr != NULL) { if (fsRecPtr->fsPtr != &tclNativeFilesystem && fsRecPtr->fsPtr->matchInDirectoryProc != NULL) { if (resultPtr == NULL) { resultPtr = Tcl_NewObj(); } fsRecPtr->fsPtr->matchInDirectoryProc(NULL, resultPtr, pathPtr, pattern, &mountsOnly); } fsRecPtr = fsRecPtr->nextPtr; } Disclaim(); return resultPtr; } /* *--------------------------------------------------------------------------- * * Tcl_FSSplitPath -- * * This function takes the given Tcl_Obj, which should be a valid path, * and returns a Tcl List object containing each segment of that path as * an element. * * Results: * Returns list object with refCount of zero. If the passed in lenPtr is * non-NULL, we use it to return the number of elements in the returned * list. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSSplitPath( Tcl_Obj *pathPtr, /* Path to split. */ int *lenPtr) /* int to store number of path elements. */ { Tcl_Obj *result = NULL; /* Needed only to prevent gcc warnings. */ const Tcl_Filesystem *fsPtr; char separator = '/'; int driveNameLength; const char *p; /* * Perform platform specific splitting. */ if (TclFSGetPathType(pathPtr, &fsPtr, &driveNameLength) == TCL_PATH_ABSOLUTE) { if (fsPtr == &tclNativeFilesystem) { return TclpNativeSplitPath(pathPtr, lenPtr); } } else { return TclpNativeSplitPath(pathPtr, lenPtr); } /* * We assume separators are single characters. */ if (fsPtr->filesystemSeparatorProc != NULL) { Tcl_Obj *sep = fsPtr->filesystemSeparatorProc(pathPtr); if (sep != NULL) { Tcl_IncrRefCount(sep); separator = Tcl_GetString(sep)[0]; Tcl_DecrRefCount(sep); } } /* * Place the drive name as first element of the result list. The drive * name may contain strange characters, like colons and multiple forward * slashes (for example 'ftp://' is a valid vfs drive name) */ result = Tcl_NewObj(); p = Tcl_GetString(pathPtr); Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(p, driveNameLength)); p += driveNameLength; /* * Add the remaining path elements to the list. */ for (;;) { const char *elementStart = p; int length; while ((*p != '\0') && (*p != separator)) { p++; } length = p - elementStart; if (length > 0) { Tcl_Obj *nextElt; if (elementStart[0] == '~') { TclNewLiteralStringObj(nextElt, "./"); Tcl_AppendToObj(nextElt, elementStart, length); } else { nextElt = Tcl_NewStringObj(elementStart, length); } Tcl_ListObjAppendElement(NULL, result, nextElt); } if (*p++ == '\0') { break; } } /* * Compute the number of elements in the result. */ if (lenPtr != NULL) { TclListObjLength(NULL, result, lenPtr); } return result; } /* *---------------------------------------------------------------------- * * TclGetPathType -- * * Helper function used by FSGetPathType. * * Results: * Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or * TCL_PATH_VOLUME_RELATIVE. The filesystem reference will be set if and * only if it is non-NULL and the function's return value is * TCL_PATH_ABSOLUTE. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_PathType TclGetPathType( Tcl_Obj *pathPtr, /* Path to determine type for. */ const Tcl_Filesystem **filesystemPtrPtr, /* If absolute path and this is not NULL, then * set to the filesystem which claims this * path. */ int *driveNameLengthPtr, /* If the path is absolute, and this is * non-NULL, then set to the length of the * driveName. */ Tcl_Obj **driveNameRef) /* If the path is absolute, and this is * non-NULL, then set to the name of the * drive, network-volume which contains the * path, already with a refCount for the * caller. */ { int pathLen; const char *path = Tcl_GetStringFromObj(pathPtr, &pathLen); Tcl_PathType type; type = TclFSNonnativePathType(path, pathLen, filesystemPtrPtr, driveNameLengthPtr, driveNameRef); if (type != TCL_PATH_ABSOLUTE) { type = TclpGetNativePathType(pathPtr, driveNameLengthPtr, driveNameRef); if ((type == TCL_PATH_ABSOLUTE) && (filesystemPtrPtr != NULL)) { *filesystemPtrPtr = &tclNativeFilesystem; } } return type; } /* *---------------------------------------------------------------------- * * TclFSNonnativePathType -- * * Helper function used by TclGetPathType. Its purpose is to check * whether the given path starts with a string which corresponds to a * file volume in any registered filesystem except the native one. For * speed and historical reasons the native filesystem has special * hard-coded checks dotted here and there in the filesystem code. * * Results: * Returns one of TCL_PATH_ABSOLUTE or TCL_PATH_RELATIVE. The filesystem * reference will be set if and only if it is non-NULL and the function's * return value is TCL_PATH_ABSOLUTE. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_PathType TclFSNonnativePathType( const char *path, /* Path to determine type for. */ int pathLen, /* Length of the path. */ const Tcl_Filesystem **filesystemPtrPtr, /* If absolute path and this is not NULL, then * set to the filesystem which claims this * path. */ int *driveNameLengthPtr, /* If the path is absolute, and this is * non-NULL, then set to the length of the * driveName. */ Tcl_Obj **driveNameRef) /* If the path is absolute, and this is * non-NULL, then set to the name of the * drive, network-volume which contains the * path, already with a refCount for the * caller. */ { FilesystemRecord *fsRecPtr; Tcl_PathType type = TCL_PATH_RELATIVE; /* * Call each of the "listVolumes" function in succession, checking whether * the given path is an absolute path on any of the volumes returned (this * is done by checking whether the path's prefix matches). */ fsRecPtr = FsGetFirstFilesystem(); Claim(); while (fsRecPtr != NULL) { /* * We want to skip the native filesystem in this loop because * otherwise we won't necessarily pass all the Tcl testsuite - this is * because some of the tests artificially change the current platform * (between win, unix) but the list of volumes we get by calling * fsRecPtr->fsPtr->listVolumesProc will reflect the current (real) * platform only and this may cause some tests to fail. In particular, * on Unix '/' will match the beginning of certain absolute Windows * paths starting '//' and those tests will go wrong. * * Besides these test-suite issues, there is one other reason to skip * the native filesystem - since the tclFilename.c code has nice fast * 'absolute path' checkers, we don't want to waste time repeating * that effort here, and this function is actually called quite often, * so if we can save the overhead of the native filesystem returning * us a list of volumes all the time, it is better. */ if ((fsRecPtr->fsPtr != &tclNativeFilesystem) && (fsRecPtr->fsPtr->listVolumesProc != NULL)) { int numVolumes; Tcl_Obj *thisFsVolumes = fsRecPtr->fsPtr->listVolumesProc(); if (thisFsVolumes != NULL) { if (Tcl_ListObjLength(NULL, thisFsVolumes, &numVolumes) != TCL_OK) { /* * This is VERY bad; the listVolumesProc didn't return a * valid list. Set numVolumes to -1 so that we skip the * while loop below and just return with the current value * of 'type'. * * It would be better if we could signal an error here * (but Tcl_Panic seems a bit excessive). */ numVolumes = -1; } while (numVolumes > 0) { Tcl_Obj *vol; int len; const char *strVol; numVolumes--; Tcl_ListObjIndex(NULL, thisFsVolumes, numVolumes, &vol); strVol = Tcl_GetStringFromObj(vol,&len); if (pathLen < len) { continue; } if (strncmp(strVol, path, (size_t) len) == 0) { type = TCL_PATH_ABSOLUTE; if (filesystemPtrPtr != NULL) { *filesystemPtrPtr = fsRecPtr->fsPtr; } if (driveNameLengthPtr != NULL) { *driveNameLengthPtr = len; } if (driveNameRef != NULL) { *driveNameRef = vol; Tcl_IncrRefCount(vol); } break; } } Tcl_DecrRefCount(thisFsVolumes); if (type == TCL_PATH_ABSOLUTE) { /* * We don't need to examine any more filesystems. */ break; } } } fsRecPtr = fsRecPtr->nextPtr; } Disclaim(); return type; } /* *--------------------------------------------------------------------------- * * Tcl_FSRenameFile -- * * If the two paths given belong to the same filesystem, we call that * filesystems rename function. Otherwise we simply return the POSIX * error 'EXDEV', and -1. * * Results: * Standard Tcl error code if a function was called. * * Side effects: * A file may be renamed. * *--------------------------------------------------------------------------- */ int Tcl_FSRenameFile( Tcl_Obj *srcPathPtr, /* Pathname of file or dir to be renamed * (UTF-8). */ Tcl_Obj *destPathPtr) /* New pathname of file or directory * (UTF-8). */ { int retVal = -1; const Tcl_Filesystem *fsPtr, *fsPtr2; fsPtr = Tcl_FSGetFileSystemForPath(srcPathPtr); fsPtr2 = Tcl_FSGetFileSystemForPath(destPathPtr); if ((fsPtr == fsPtr2) && (fsPtr != NULL) && (fsPtr->renameFileProc != NULL)) { retVal = fsPtr->renameFileProc(srcPathPtr, destPathPtr); } if (retVal == -1) { Tcl_SetErrno(EXDEV); } return retVal; } /* *--------------------------------------------------------------------------- * * Tcl_FSCopyFile -- * * If the two paths given belong to the same filesystem, we call that * filesystem's copy function. Otherwise we simply return the POSIX error * 'EXDEV', and -1. * * Note that in the native filesystems, 'copyFileProc' is defined to copy * soft links (i.e. it copies the links themselves, not the things they * point to). * * Results: * Standard Tcl error code if a function was called. * * Side effects: * A file may be copied. * *--------------------------------------------------------------------------- */ int Tcl_FSCopyFile( Tcl_Obj *srcPathPtr, /* Pathname of file to be copied (UTF-8). */ Tcl_Obj *destPathPtr) /* Pathname of file to copy to (UTF-8). */ { int retVal = -1; const Tcl_Filesystem *fsPtr, *fsPtr2; fsPtr = Tcl_FSGetFileSystemForPath(srcPathPtr); fsPtr2 = Tcl_FSGetFileSystemForPath(destPathPtr); if (fsPtr == fsPtr2 && fsPtr != NULL && fsPtr->copyFileProc != NULL) { retVal = fsPtr->copyFileProc(srcPathPtr, destPathPtr); } if (retVal == -1) { Tcl_SetErrno(EXDEV); } return retVal; } /* *--------------------------------------------------------------------------- * * TclCrossFilesystemCopy -- * * Helper for above function, and for Tcl_FSLoadFile, to copy files from * one filesystem to another. This function will overwrite the target * file if it already exists. * * Results: * Standard Tcl error code. * * Side effects: * A file may be created. * *--------------------------------------------------------------------------- */ int TclCrossFilesystemCopy( Tcl_Interp *interp, /* For error messages. */ Tcl_Obj *source, /* Pathname of file to be copied (UTF-8). */ Tcl_Obj *target) /* Pathname of file to copy to (UTF-8). */ { int result = TCL_ERROR; int prot = 0666; Tcl_Channel in, out; Tcl_StatBuf sourceStatBuf; struct utimbuf tval; out = Tcl_FSOpenFileChannel(interp, target, "wb", prot); if (out == NULL) { /* * It looks like we cannot copy it over. Bail out... */ goto done; } in = Tcl_FSOpenFileChannel(interp, source, "rb", prot); if (in == NULL) { /* * This is very strange, caller should have checked this... */ Tcl_Close(interp, out); goto done; } /* * Copy it synchronously. We might wish to add an asynchronous option to * support vfs's which are slow (e.g. network sockets). */ if (TclCopyChannel(interp, in, out, -1, NULL) == TCL_OK) { result = TCL_OK; } /* * If the copy failed, assume that copy channel left a good error message. */ Tcl_Close(interp, in); Tcl_Close(interp, out); /* * Set modification date of copied file. */ if (Tcl_FSLstat(source, &sourceStatBuf) == 0) { tval.actime = sourceStatBuf.st_atime; tval.modtime = sourceStatBuf.st_mtime; Tcl_FSUtime(target, &tval); } done: return result; } /* *--------------------------------------------------------------------------- * * Tcl_FSDeleteFile -- * * The appropriate function for the filesystem to which pathPtr belongs * will be called. * * Results: * Standard Tcl error code. * * Side effects: * A file may be deleted. * *--------------------------------------------------------------------------- */ int Tcl_FSDeleteFile( Tcl_Obj *pathPtr) /* Pathname of file to be removed (UTF-8). */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->deleteFileProc != NULL) { return fsPtr->deleteFileProc(pathPtr); } Tcl_SetErrno(ENOENT); return -1; } /* *--------------------------------------------------------------------------- * * Tcl_FSCreateDirectory -- * * The appropriate function for the filesystem to which pathPtr belongs * will be called. * * Results: * Standard Tcl error code. * * Side effects: * A directory may be created. * *--------------------------------------------------------------------------- */ int Tcl_FSCreateDirectory( Tcl_Obj *pathPtr) /* Pathname of directory to create (UTF-8). */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->createDirectoryProc != NULL) { return fsPtr->createDirectoryProc(pathPtr); } Tcl_SetErrno(ENOENT); return -1; } /* *--------------------------------------------------------------------------- * * Tcl_FSCopyDirectory -- * * If the two paths given belong to the same filesystem, we call that * filesystems copy-directory function. Otherwise we simply return the * POSIX error 'EXDEV', and -1. * * Results: * Standard Tcl error code if a function was called. * * Side effects: * A directory may be copied. * *--------------------------------------------------------------------------- */ int Tcl_FSCopyDirectory( Tcl_Obj *srcPathPtr, /* Pathname of directory to be copied * (UTF-8). */ Tcl_Obj *destPathPtr, /* Pathname of target directory (UTF-8). */ Tcl_Obj **errorPtr) /* If non-NULL, then will be set to a new * object containing name of file causing * error, with refCount 1. */ { int retVal = -1; const Tcl_Filesystem *fsPtr, *fsPtr2; fsPtr = Tcl_FSGetFileSystemForPath(srcPathPtr); fsPtr2 = Tcl_FSGetFileSystemForPath(destPathPtr); if (fsPtr == fsPtr2 && fsPtr != NULL && fsPtr->copyDirectoryProc != NULL){ retVal = fsPtr->copyDirectoryProc(srcPathPtr, destPathPtr, errorPtr); } if (retVal == -1) { Tcl_SetErrno(EXDEV); } return retVal; } /* *--------------------------------------------------------------------------- * * Tcl_FSRemoveDirectory -- * * The appropriate function for the filesystem to which pathPtr belongs * will be called. * * Results: * Standard Tcl error code. * * Side effects: * A directory may be deleted. * *--------------------------------------------------------------------------- */ int Tcl_FSRemoveDirectory( Tcl_Obj *pathPtr, /* Pathname of directory to be removed * (UTF-8). */ int recursive, /* If non-zero, removes directories that are * nonempty. Otherwise, will only remove empty * directories. */ Tcl_Obj **errorPtr) /* If non-NULL, then will be set to a new * object containing name of file causing * error, with refCount 1. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr == NULL || fsPtr->removeDirectoryProc == NULL) { Tcl_SetErrno(ENOENT); return -1; } /* * When working recursively, we check whether the cwd lies inside this * directory and move it if it does. */ if (recursive) { Tcl_Obj *cwdPtr = Tcl_FSGetCwd(NULL); if (cwdPtr != NULL) { const char *cwdStr, *normPathStr; int cwdLen, normLen; Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (normPath != NULL) { normPathStr = Tcl_GetStringFromObj(normPath, &normLen); cwdStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen); if ((cwdLen >= normLen) && (strncmp(normPathStr, cwdStr, (size_t) normLen) == 0)) { /* * The cwd is inside the directory, so we perform a 'cd * [file dirname $path]'. */ Tcl_Obj *dirPtr = TclPathPart(NULL, pathPtr, TCL_PATH_DIRNAME); Tcl_FSChdir(dirPtr); Tcl_DecrRefCount(dirPtr); } } Tcl_DecrRefCount(cwdPtr); } } return fsPtr->removeDirectoryProc(pathPtr, recursive, errorPtr); } /* *--------------------------------------------------------------------------- * * Tcl_FSGetFileSystemForPath -- * * This function determines which filesystem to use for a particular path * object, and returns the filesystem which accepts this file. If no * filesystem will accept this object as a valid file path, then NULL is * returned. * * Results: * NULL or a filesystem which will accept this path. * * Side effects: * The object may be converted to a path type. * *--------------------------------------------------------------------------- */ const Tcl_Filesystem * Tcl_FSGetFileSystemForPath( Tcl_Obj *pathPtr) { FilesystemRecord *fsRecPtr; const Tcl_Filesystem *retVal = NULL; if (pathPtr == NULL) { Tcl_Panic("Tcl_FSGetFileSystemForPath called with NULL object"); return NULL; } /* * If the object has a refCount of zero, we reject it. This is to avoid * possible segfaults or nondeterministic memory leaks (i.e. the user * doesn't know if they should decrement the ref count on return or not). */ if (pathPtr->refCount == 0) { Tcl_Panic("Tcl_FSGetFileSystemForPath called with object with refCount == 0"); return NULL; } /* * Check if the filesystem has changed in some way since this object's * internal representation was calculated. Before doing that, assure we * have the most up-to-date copy of the master filesystem. This is * accomplished by the FsGetFirstFilesystem() call. */ fsRecPtr = FsGetFirstFilesystem(); Claim(); if (TclFSEnsureEpochOk(pathPtr, &retVal) != TCL_OK) { Disclaim(); return NULL; } else if (retVal != NULL) { /* TODO: Can this happen? */ Disclaim(); return retVal; } /* * Call each of the "pathInFilesystem" functions in succession. A * non-return value of -1 indicates the particular function has succeeded. */ for (; fsRecPtr!=NULL ; fsRecPtr=fsRecPtr->nextPtr) { ClientData clientData = NULL; if (fsRecPtr->fsPtr->pathInFilesystemProc == NULL) { continue; } if (fsRecPtr->fsPtr->pathInFilesystemProc(pathPtr, &clientData)!=-1) { /* * We assume the type of pathPtr hasn't been changed by the above * call to the pathInFilesystemProc. */ TclFSSetPathDetails(pathPtr, fsRecPtr->fsPtr, clientData); Disclaim(); return fsRecPtr->fsPtr; } } Disclaim(); return NULL; } /* *--------------------------------------------------------------------------- * * Tcl_FSGetNativePath -- * * This function is for use by the Win/Unix native filesystems, so that * they can easily retrieve the native (char* or TCHAR*) representation * of a path. Other filesystems will probably want to implement similar * functions. They basically act as a safety net around * Tcl_FSGetInternalRep. Normally your file-system functions will always * be called with path objects already converted to the correct * filesystem, but if for some reason they are called directly (i.e. by * functions not in this file), then one cannot necessarily guarantee * that the path object pointer is from the correct filesystem. * * Note: in the future it might be desirable to have separate versions * of this function with different signatures, for example * Tcl_FSGetNativeWinPath, Tcl_FSGetNativeUnixPath etc. Right now, since * native paths are all string based, we use just one function. * * Results: * NULL or a valid native path. * * Side effects: * See Tcl_FSGetInternalRep. * *--------------------------------------------------------------------------- */ const void * Tcl_FSGetNativePath( Tcl_Obj *pathPtr) { return Tcl_FSGetInternalRep(pathPtr, &tclNativeFilesystem); } /* *--------------------------------------------------------------------------- * * NativeFreeInternalRep -- * * Free a native internal representation, which will be non-NULL. * * Results: * None. * * Side effects: * Memory is released. * *--------------------------------------------------------------------------- */ static void NativeFreeInternalRep( ClientData clientData) { ckfree(clientData); } /* *--------------------------------------------------------------------------- * * Tcl_FSFileSystemInfo -- * * This function returns a list of two elements. The first element is the * name of the filesystem (e.g. "native" or "vfs"), and the second is the * particular type of the given path within that filesystem. * * Results: * A list of two elements. * * Side effects: * The object may be converted to a path type. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSFileSystemInfo( Tcl_Obj *pathPtr) { Tcl_Obj *resPtr; const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr == NULL) { return NULL; } resPtr = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(NULL, resPtr, Tcl_NewStringObj(fsPtr->typeName, -1)); if (fsPtr->filesystemPathTypeProc != NULL) { Tcl_Obj *typePtr = fsPtr->filesystemPathTypeProc(pathPtr); if (typePtr != NULL) { Tcl_ListObjAppendElement(NULL, resPtr, typePtr); } } return resPtr; } /* *--------------------------------------------------------------------------- * * Tcl_FSPathSeparator -- * * This function returns the separator to be used for a given path. The * object returned should have a refCount of zero * * Results: * A Tcl object, with a refCount of zero. If the caller needs to retain a * reference to the object, it should call Tcl_IncrRefCount, and should * otherwise free the object. * * Side effects: * The path object may be converted to a path type. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSPathSeparator( Tcl_Obj *pathPtr) { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); Tcl_Obj *resultObj; if (fsPtr == NULL) { return NULL; } if (fsPtr->filesystemSeparatorProc != NULL) { return fsPtr->filesystemSeparatorProc(pathPtr); } /* * Allow filesystems not to provide a filesystemSeparatorProc if they wish * to use the standard forward slash. */ TclNewLiteralStringObj(resultObj, "/"); return resultObj; } /* *--------------------------------------------------------------------------- * * NativeFilesystemSeparator -- * * This function is part of the native filesystem support, and returns * the separator for the given path. * * Results: * String object containing the separator character. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static Tcl_Obj * NativeFilesystemSeparator( Tcl_Obj *pathPtr) { const char *separator = NULL; /* lint */ switch (tclPlatform) { case TCL_PLATFORM_UNIX: separator = "/"; break; case TCL_PLATFORM_WINDOWS: separator = "\\"; break; } return Tcl_NewStringObj(separator,1); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclTestProcBodyObj.c0000644000175000017500000001717512663660065017101 0ustar sergeisergei/* * tclTestProcBodyObj.c -- * * Implements the "procbodytest" package, which contains commands to test * creation of Tcl procedures whose body argument is a Tcl_Obj of type * "procbody" rather than a string. * * Copyright (c) 1998 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef USE_TCL_STUBS # define USE_TCL_STUBS #endif #include "tclInt.h" /* * name and version of this package */ static const char packageName[] = "procbodytest"; static const char packageVersion[] = "1.0"; /* * Name of the commands exported by this package */ static const char procCommand[] = "proc"; /* * this struct describes an entry in the table of command names and command * procs */ typedef struct CmdTable { const char *cmdName; /* command name */ Tcl_ObjCmdProc *proc; /* command proc */ int exportIt; /* if 1, export the command */ } CmdTable; /* * Declarations for functions defined in this file. */ static int ProcBodyTestProcObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ProcBodyTestInitInternal(Tcl_Interp *interp, int isSafe); static int RegisterCommand(Tcl_Interp* interp, const char *namespace, const CmdTable *cmdTablePtr); /* * List of commands to create when the package is loaded; must go after the * declarations of the enable command procedure. */ static const CmdTable commands[] = { { procCommand, ProcBodyTestProcObjCmd, 1 }, { 0, 0, 0 } }; static const CmdTable safeCommands[] = { { procCommand, ProcBodyTestProcObjCmd, 1 }, { 0, 0, 0 } }; /* *---------------------------------------------------------------------- * * Procbodytest_Init -- * * This function initializes the "procbodytest" package. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Procbodytest_Init( Tcl_Interp *interp) /* the Tcl interpreter for which the package * is initialized */ { return ProcBodyTestInitInternal(interp, 0); } /* *---------------------------------------------------------------------- * * Procbodytest_SafeInit -- * * This function initializes the "procbodytest" package. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Procbodytest_SafeInit( Tcl_Interp *interp) /* the Tcl interpreter for which the package * is initialized */ { return ProcBodyTestInitInternal(interp, 1); } /* *---------------------------------------------------------------------- * * RegisterCommand -- * * This function registers a command in the context of the given * namespace. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int RegisterCommand( Tcl_Interp* interp, /* the Tcl interpreter for which the operation * is performed */ const char *namespace, /* the namespace in which the command is * registered */ const CmdTable *cmdTablePtr)/* the command to register */ { char buf[128]; if (cmdTablePtr->exportIt) { sprintf(buf, "namespace eval %s { namespace export %s }", namespace, cmdTablePtr->cmdName); if (Tcl_EvalEx(interp, buf, -1, 0) != TCL_OK) { return TCL_ERROR; } } sprintf(buf, "%s::%s", namespace, cmdTablePtr->cmdName); Tcl_CreateObjCommand(interp, buf, cmdTablePtr->proc, 0, 0); return TCL_OK; } /* *---------------------------------------------------------------------- * * ProcBodyTestInitInternal -- * * This function initializes the Loader package. * The isSafe flag is 1 if the interpreter is safe, 0 otherwise. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ProcBodyTestInitInternal( Tcl_Interp *interp, /* the Tcl interpreter for which the package * is initialized */ int isSafe) /* 1 if this is a safe interpreter */ { const CmdTable *cmdTablePtr; cmdTablePtr = (isSafe) ? &safeCommands[0] : &commands[0]; for ( ; cmdTablePtr->cmdName ; cmdTablePtr++) { if (RegisterCommand(interp, packageName, cmdTablePtr) != TCL_OK) { return TCL_ERROR; } } return Tcl_PkgProvide(interp, packageName, packageVersion); } /* *---------------------------------------------------------------------- * * ProcBodyTestProcObjCmd -- * * Implements the "procbodytest::proc" command. Here is the command * description: * procbodytest::proc newName argList bodyName * Looks up a procedure called $bodyName and, if the procedure exists, * constructs a Tcl_Obj of type "procbody" and calls Tcl_ProcObjCmd. * Arguments: * newName the name of the procedure to be created * argList the argument list for the procedure * bodyName the name of an existing procedure from which the * body is to be copied. * This command can be used to trigger the branches in Tcl_ProcObjCmd that * construct a proc from a "procbody", for example: * proc a {x} {return $x} * a 123 * procbodytest::proc b {x} a * Note the call to "a 123", which is necessary so that the Proc pointer * for "a" is filled in by the internal compiler; this is a hack. * * Results: * Returns a standard Tcl code. * * Side effects: * A new procedure is created. * Leaves an error message in the interp's result on error. * *---------------------------------------------------------------------- */ static int ProcBodyTestProcObjCmd( ClientData dummy, /* context; not used */ Tcl_Interp *interp, /* the current interpreter */ int objc, /* argument count */ Tcl_Obj *const objv[]) /* arguments */ { const char *fullName; Tcl_Command procCmd; Command *cmdPtr; Proc *procPtr = NULL; Tcl_Obj *bodyObjPtr; Tcl_Obj *myobjv[5]; int result; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "newName argsList bodyName"); return TCL_ERROR; } /* * Find the Command pointer to this procedure */ fullName = Tcl_GetString(objv[3]); procCmd = Tcl_FindCommand(interp, fullName, NULL, TCL_LEAVE_ERR_MSG); if (procCmd == NULL) { return TCL_ERROR; } cmdPtr = (Command *) procCmd; /* * check that this is a procedure and not a builtin command: * If a procedure, cmdPtr->objClientData is TclIsProc(cmdPtr). */ if (cmdPtr->objClientData != TclIsProc(cmdPtr)) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "command \"", fullName, "\" is not a Tcl procedure", NULL); return TCL_ERROR; } /* * it is a Tcl procedure: the client data is the Proc structure */ procPtr = (Proc *) cmdPtr->objClientData; if (procPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "procedure \"", fullName, "\" does not have a Proc struct!", NULL); return TCL_ERROR; } /* * create a new object, initialize our argument vector, call into Tcl */ bodyObjPtr = TclNewProcBodyObj(procPtr); if (bodyObjPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "failed to create a procbody object for procedure \"", fullName, "\"", NULL); return TCL_ERROR; } Tcl_IncrRefCount(bodyObjPtr); myobjv[0] = objv[0]; myobjv[1] = objv[1]; myobjv[2] = objv[2]; myobjv[3] = bodyObjPtr; myobjv[4] = NULL; result = Tcl_ProcObjCmd(NULL, interp, objc, myobjv); Tcl_DecrRefCount(bodyObjPtr); return result; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclPathObj.c0000644000175000017500000021626312663660065015413 0ustar sergeisergei/* * tclPathObj.c -- * * This file contains the implementation of Tcl's "path" object type used * to represent and manipulate a general (virtual) filesystem entity in * an efficient manner. * * Copyright (c) 2003 Vince Darley. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclFileSystem.h" /* * Prototypes for functions defined later in this file. */ static Tcl_Obj * AppendPath(Tcl_Obj *head, Tcl_Obj *tail); static void DupFsPathInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static void FreeFsPathInternalRep(Tcl_Obj *pathPtr); static void UpdateStringOfFsPath(Tcl_Obj *pathPtr); static int SetFsPathFromAny(Tcl_Interp *interp, Tcl_Obj *pathPtr); static int FindSplitPos(const char *path, int separator); static int IsSeparatorOrNull(int ch); static Tcl_Obj * GetExtension(Tcl_Obj *pathPtr); static int MakePathFromNormalized(Tcl_Interp *interp, Tcl_Obj *pathPtr); /* * Define the 'path' object type, which Tcl uses to represent file paths * internally. */ static const Tcl_ObjType tclFsPathType = { "path", /* name */ FreeFsPathInternalRep, /* freeIntRepProc */ DupFsPathInternalRep, /* dupIntRepProc */ UpdateStringOfFsPath, /* updateStringProc */ SetFsPathFromAny /* setFromAnyProc */ }; /* * struct FsPath -- * * Internal representation of a Tcl_Obj of "path" type. This can be used to * represent relative or absolute paths, and has certain optimisations when * used to represent paths which are already normalized and absolute. * * Note that both 'translatedPathPtr' and 'normPathPtr' can be a circular * reference to the container Tcl_Obj of this FsPath. * * There are two cases, with the first being the most common: * * (i) flags == 0, => Ordinary path. * * translatedPathPtr contains the translated path (which may be a circular * reference to the object itself). If it is NULL then the path is pure * normalized (and the normPathPtr will be a circular reference). cwdPtr is * null for an absolute path, and non-null for a relative path (unless the cwd * has never been set, in which case the cwdPtr may also be null for a * relative path). * * (ii) flags != 0, => Special path, see TclNewFSPathObj * * Now, this is a path like 'file join $dir $tail' where, cwdPtr is the $dir * and normPathPtr is the $tail. * */ typedef struct FsPath { Tcl_Obj *translatedPathPtr; /* Name without any ~user sequences. If this * is NULL, then this is a pure normalized, * absolute path object, in which the parent * Tcl_Obj's string rep is already both * translated and normalized. */ Tcl_Obj *normPathPtr; /* Normalized absolute path, without ., .. or * ~user sequences. If the Tcl_Obj containing * this FsPath is already normalized, this may * be a circular reference back to the * container. If that is NOT the case, we have * a refCount on the object. */ Tcl_Obj *cwdPtr; /* If null, path is absolute, else this points * to the cwd object used for this path. We * have a refCount on the object. */ int flags; /* Flags to describe interpretation - see * below. */ ClientData nativePathPtr; /* Native representation of this path, which * is filesystem dependent. */ int filesystemEpoch; /* Used to ensure the path representation was * generated during the correct filesystem * epoch. The epoch changes when * filesystem-mounts are changed. */ const Tcl_Filesystem *fsPtr;/* The Tcl_Filesystem that claims this path */ } FsPath; /* * Flag values for FsPath->flags. */ #define TCLPATH_APPENDED 1 #define TCLPATH_NEEDNORM 4 /* * Define some macros to give us convenient access to path-object specific * fields. */ #define PATHOBJ(pathPtr) ((FsPath *) (pathPtr)->internalRep.twoPtrValue.ptr1) #define SETPATHOBJ(pathPtr,fsPathPtr) \ ((pathPtr)->internalRep.twoPtrValue.ptr1 = (void *) (fsPathPtr)) #define PATHFLAGS(pathPtr) (PATHOBJ(pathPtr)->flags) /* *--------------------------------------------------------------------------- * * TclFSNormalizeAbsolutePath -- * * Takes an absolute path specification and computes a 'normalized' path * from it. * * A normalized path is one which has all '../', './' removed. Also it is * one which is in the 'standard' format for the native platform. On * Unix, this means the path must be free of symbolic links/aliases, and * on Windows it means we want the long form, with that long form's * case-dependence (which gives us a unique, case-dependent path). * * The behaviour of this function if passed a non-absolute path is NOT * defined. * * pathPtr may have a refCount of zero, or may be a shared object. * * Results: * The result is returned in a Tcl_Obj with a refCount of 1, which is * therefore owned by the caller. It must be freed (with * Tcl_DecrRefCount) by the caller when no longer needed. * * Side effects: * None (beyond the memory allocation for the result). * * Special note: * This code was originally based on code from Matt Newman and * Jean-Claude Wippler, but has since been totally rewritten by Vince * Darley to deal with symbolic links. * *--------------------------------------------------------------------------- */ Tcl_Obj * TclFSNormalizeAbsolutePath( Tcl_Interp *interp, /* Interpreter to use */ Tcl_Obj *pathPtr) /* Absolute path to normalize */ { const char *dirSep, *oldDirSep; int first = 1; /* Set to zero once we've passed the first * directory separator - we can't use '..' to * remove the volume in a path. */ Tcl_Obj *retVal = NULL; dirSep = TclGetString(pathPtr); if (tclPlatform == TCL_PLATFORM_WINDOWS) { if ( (dirSep[0] == '/' || dirSep[0] == '\\') && (dirSep[1] == '/' || dirSep[1] == '\\') && (dirSep[2] == '?') && (dirSep[3] == '/' || dirSep[3] == '\\')) { /* NT extended path */ dirSep += 4; if ( (dirSep[0] == 'U' || dirSep[0] == 'u') && (dirSep[1] == 'N' || dirSep[1] == 'n') && (dirSep[2] == 'C' || dirSep[2] == 'c') && (dirSep[3] == '/' || dirSep[3] == '\\')) { /* NT extended UNC path */ dirSep += 4; } } if (dirSep[0] != 0 && dirSep[1] == ':' && (dirSep[2] == '/' || dirSep[2] == '\\')) { /* Do nothing */ } else if ((dirSep[0] == '/' || dirSep[0] == '\\') && (dirSep[1] == '/' || dirSep[1] == '\\')) { /* * UNC style path, where we must skip over the first separator, * since the first two segments are actually inseparable. */ dirSep += 2; dirSep += FindSplitPos(dirSep, '/'); if (*dirSep != 0) { dirSep++; } } } /* * Scan forward from one directory separator to the next, checking for * '..' and '.' sequences which must be handled specially. In particular * handling of '..' can be complicated if the directory before is a link, * since we will have to expand the link to be able to back up one level. */ while (*dirSep != 0) { oldDirSep = dirSep; if (!first) { dirSep++; } dirSep += FindSplitPos(dirSep, '/'); if (dirSep[0] == 0 || dirSep[1] == 0) { if (retVal != NULL) { Tcl_AppendToObj(retVal, oldDirSep, dirSep - oldDirSep); } break; } if (dirSep[1] == '.') { if (retVal != NULL) { Tcl_AppendToObj(retVal, oldDirSep, dirSep - oldDirSep); oldDirSep = dirSep; } again: if (IsSeparatorOrNull(dirSep[2])) { /* * Need to skip '.' in the path. */ int curLen; if (retVal == NULL) { const char *path = TclGetString(pathPtr); retVal = Tcl_NewStringObj(path, dirSep - path); Tcl_IncrRefCount(retVal); } Tcl_GetStringFromObj(retVal, &curLen); if (curLen == 0) { Tcl_AppendToObj(retVal, dirSep, 1); } dirSep += 2; oldDirSep = dirSep; if (dirSep[0] != 0 && dirSep[1] == '.') { goto again; } continue; } if (dirSep[2] == '.' && IsSeparatorOrNull(dirSep[3])) { Tcl_Obj *linkObj; int curLen; char *linkStr; /* * Have '..' so need to skip previous directory. */ if (retVal == NULL) { const char *path = TclGetString(pathPtr); retVal = Tcl_NewStringObj(path, dirSep - path); Tcl_IncrRefCount(retVal); } Tcl_GetStringFromObj(retVal, &curLen); if (curLen == 0) { Tcl_AppendToObj(retVal, dirSep, 1); } if (!first || (tclPlatform == TCL_PLATFORM_UNIX)) { linkObj = Tcl_FSLink(retVal, NULL, 0); /* Safety check in case driver caused sharing */ if (Tcl_IsShared(retVal)) { TclDecrRefCount(retVal); retVal = Tcl_DuplicateObj(retVal); Tcl_IncrRefCount(retVal); } if (linkObj != NULL) { /* * Got a link. Need to check if the link is relative * or absolute, for those platforms where relative * links exist. */ if (tclPlatform != TCL_PLATFORM_WINDOWS && Tcl_FSGetPathType(linkObj) == TCL_PATH_RELATIVE) { /* * We need to follow this link which is relative * to retVal's directory. This means concatenating * the link onto the directory of the path so far. */ const char *path = Tcl_GetStringFromObj(retVal, &curLen); while (--curLen >= 0) { if (IsSeparatorOrNull(path[curLen])) { break; } } /* * We want the trailing slash. */ Tcl_SetObjLength(retVal, curLen+1); Tcl_AppendObjToObj(retVal, linkObj); TclDecrRefCount(linkObj); linkStr = Tcl_GetStringFromObj(retVal, &curLen); } else { /* * Absolute link. */ TclDecrRefCount(retVal); if (Tcl_IsShared(linkObj)) { retVal = Tcl_DuplicateObj(linkObj); TclDecrRefCount(linkObj); } else { retVal = linkObj; } linkStr = Tcl_GetStringFromObj(retVal, &curLen); /* * Convert to forward-slashes on windows. */ if (tclPlatform == TCL_PLATFORM_WINDOWS) { int i; for (i = 0; i < curLen; i++) { if (linkStr[i] == '\\') { linkStr[i] = '/'; } } } } } else { linkStr = Tcl_GetStringFromObj(retVal, &curLen); } /* * Either way, we now remove the last path element (but * not the first character of the path). */ while (--curLen >= 0) { if (IsSeparatorOrNull(linkStr[curLen])) { if (curLen) { Tcl_SetObjLength(retVal, curLen); } else { Tcl_SetObjLength(retVal, 1); } break; } } } dirSep += 3; oldDirSep = dirSep; if ((curLen == 0) && (dirSep[0] != 0)) { Tcl_SetObjLength(retVal, 0); } if (dirSep[0] != 0 && dirSep[1] == '.') { goto again; } continue; } } first = 0; if (retVal != NULL) { Tcl_AppendToObj(retVal, oldDirSep, dirSep - oldDirSep); } } /* * If we didn't make any changes, just use the input path. */ if (retVal == NULL) { retVal = pathPtr; Tcl_IncrRefCount(retVal); if (Tcl_IsShared(retVal)) { /* * Unfortunately, the platform-specific normalization code which * will be called below has no way of dealing with the case where * an object is shared. It is expecting to modify an object in * place. So, we must duplicate this here to ensure an object with * a single ref-count. * * If that changes in the future (e.g. the normalize proc is given * one object and is able to return a different one), then we * could remove this code. */ TclDecrRefCount(retVal); retVal = Tcl_DuplicateObj(pathPtr); Tcl_IncrRefCount(retVal); } } /* * Ensure a windows drive like C:/ has a trailing separator. */ if (tclPlatform == TCL_PLATFORM_WINDOWS) { int len; const char *path = Tcl_GetStringFromObj(retVal, &len); if (len == 2 && path[0] != 0 && path[1] == ':') { if (Tcl_IsShared(retVal)) { TclDecrRefCount(retVal); retVal = Tcl_DuplicateObj(retVal); Tcl_IncrRefCount(retVal); } Tcl_AppendToObj(retVal, "/", 1); } } /* * Now we have an absolute path, with no '..', '.' sequences, but it still * may not be in 'unique' form, depending on the platform. For instance, * Unix is case-sensitive, so the path is ok. Windows is case-insensitive, * and also has the weird 'longname/shortname' thing (e.g. C:/Program * Files/ and C:/Progra~1/ are equivalent). * * Virtual file systems which may be registered may have other criteria * for normalizing a path. */ TclFSNormalizeToUniquePath(interp, retVal, 0); /* * Since we know it is a normalized path, we can actually convert this * object into an FsPath for greater efficiency */ MakePathFromNormalized(interp, retVal); /* * This has a refCount of 1 for the caller, unlike many Tcl_Obj APIs. */ return retVal; } /* *---------------------------------------------------------------------- * * Tcl_FSGetPathType -- * * Determines whether a given path is relative to the current directory, * relative to the current volume, or absolute. * * Results: * Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or * TCL_PATH_VOLUME_RELATIVE. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_PathType Tcl_FSGetPathType( Tcl_Obj *pathPtr) { return TclFSGetPathType(pathPtr, NULL, NULL); } /* *---------------------------------------------------------------------- * * TclFSGetPathType -- * * Determines whether a given path is relative to the current directory, * relative to the current volume, or absolute. If the caller wishes to * know which filesystem claimed the path (in the case for which the path * is absolute), then a reference to a filesystem pointer can be passed * in (but passing NULL is acceptable). * * Results: * Returns one of TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, or * TCL_PATH_VOLUME_RELATIVE. The filesystem reference will be set if and * only if it is non-NULL and the function's return value is * TCL_PATH_ABSOLUTE. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_PathType TclFSGetPathType( Tcl_Obj *pathPtr, const Tcl_Filesystem **filesystemPtrPtr, int *driveNameLengthPtr) { FsPath *fsPathPtr; if (Tcl_FSConvertToPathType(NULL, pathPtr) != TCL_OK) { return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr, NULL); } fsPathPtr = PATHOBJ(pathPtr); if (fsPathPtr->cwdPtr == NULL) { return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr, NULL); } if (PATHFLAGS(pathPtr) == 0) { /* The path is not absolute... */ #ifdef _WIN32 /* ... on Windows we must make another call to determine whether * it's relative or volumerelative [Bug 2571597]. */ return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr, NULL); #else /* On other systems, quickly deduce !absolute -> relative */ return TCL_PATH_RELATIVE; #endif } return TclFSGetPathType(fsPathPtr->cwdPtr, filesystemPtrPtr, driveNameLengthPtr); } /* *--------------------------------------------------------------------------- * * TclPathPart * * This function calculates the requested part of the given path, which * can be: * * - the directory above ('file dirname') * - the tail ('file tail') * - the extension ('file extension') * - the root ('file root') * * The 'portion' parameter dictates which of these to calculate. There * are a number of special cases both to be more efficient, and because * the behaviour when given a path with only a single element is defined * to require the expansion of that single element, where possible. * * Should look into integrating 'FileBasename' in tclFCmd.c into this * function. * * Results: * NULL if an error occurred, otherwise a Tcl_Obj owned by the caller * (i.e. most likely with refCount 1). * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj * TclPathPart( Tcl_Interp *interp, /* Used for error reporting */ Tcl_Obj *pathPtr, /* Path to take dirname of */ Tcl_PathPart portion) /* Requested portion of name */ { if (pathPtr->typePtr == &tclFsPathType) { FsPath *fsPathPtr = PATHOBJ(pathPtr); if (PATHFLAGS(pathPtr) != 0) { switch (portion) { case TCL_PATH_DIRNAME: { /* * Check if the joined-on bit has any directory delimiters in * it. If so, the 'dirname' would be a joining of the main * part with the dirname of the joined-on bit. We could handle * that special case here, but we don't, and instead just use * the standardPath code. */ int numBytes; const char *rest = Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &numBytes); if (strchr(rest, '/') != NULL) { goto standardPath; } /* * If the joined-on bit is empty, then [file dirname] is * documented to return all but the last non-empty element * of the path, so we need to split apart the main part to * get the right answer. We could do that here, but it's * simpler to fall back to the standardPath code. * [Bug 2710920] */ if (numBytes == 0) { goto standardPath; } if (tclPlatform == TCL_PLATFORM_WINDOWS && strchr(rest, '\\') != NULL) { goto standardPath; } /* * The joined-on path is simple, so we can just return here. */ Tcl_IncrRefCount(fsPathPtr->cwdPtr); return fsPathPtr->cwdPtr; } case TCL_PATH_TAIL: { /* * Check if the joined-on bit has any directory delimiters in * it. If so, the 'tail' would be only the part following the * last delimiter. We could handle that special case here, but * we don't, and instead just use the standardPath code. */ int numBytes; const char *rest = Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &numBytes); if (strchr(rest, '/') != NULL) { goto standardPath; } /* * If the joined-on bit is empty, then [file tail] is * documented to return the last non-empty element * of the path, so we need to split off the last element * of the main part to get the right answer. We could do * that here, but it's simpler to fall back to the * standardPath code. [Bug 2710920] */ if (numBytes == 0) { goto standardPath; } if (tclPlatform == TCL_PLATFORM_WINDOWS && strchr(rest, '\\') != NULL) { goto standardPath; } Tcl_IncrRefCount(fsPathPtr->normPathPtr); return fsPathPtr->normPathPtr; } case TCL_PATH_EXTENSION: return GetExtension(fsPathPtr->normPathPtr); case TCL_PATH_ROOT: { const char *fileName, *extension; int length; fileName = Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &length); extension = TclGetExtension(fileName); if (extension == NULL) { /* * There is no extension so the root is the same as the * path we were given. */ Tcl_IncrRefCount(pathPtr); return pathPtr; } else { /* * Need to return the whole path with the extension * suffix removed. Do that by joining our "head" to * our "tail" with the extension suffix removed from * the tail. */ Tcl_Obj *resultPtr = TclNewFSPathObj(fsPathPtr->cwdPtr, fileName, (int)(length - strlen(extension))); Tcl_IncrRefCount(resultPtr); return resultPtr; } } default: /* We should never get here */ Tcl_Panic("Bad portion to TclPathPart"); /* For less clever compilers */ return NULL; } } else if (fsPathPtr->cwdPtr != NULL) { /* Relative path */ goto standardPath; } else { /* Absolute path */ goto standardPath; } } else { int splitElements; Tcl_Obj *splitPtr, *resultPtr; standardPath: resultPtr = NULL; if (portion == TCL_PATH_EXTENSION) { return GetExtension(pathPtr); } else if (portion == TCL_PATH_ROOT) { int length; const char *fileName, *extension; fileName = Tcl_GetStringFromObj(pathPtr, &length); extension = TclGetExtension(fileName); if (extension == NULL) { Tcl_IncrRefCount(pathPtr); return pathPtr; } else { Tcl_Obj *root = Tcl_NewStringObj(fileName, (int) (length - strlen(extension))); Tcl_IncrRefCount(root); return root; } } /* * The behaviour we want here is slightly different to the standard * Tcl_FSSplitPath in the handling of home directories; * Tcl_FSSplitPath preserves the "~" while this code computes the * actual full path name, if we had just a single component. */ splitPtr = Tcl_FSSplitPath(pathPtr, &splitElements); Tcl_IncrRefCount(splitPtr); if (splitElements == 1 && TclGetString(pathPtr)[0] == '~') { Tcl_Obj *norm; TclDecrRefCount(splitPtr); norm = Tcl_FSGetNormalizedPath(interp, pathPtr); if (norm == NULL) { return NULL; } splitPtr = Tcl_FSSplitPath(norm, &splitElements); Tcl_IncrRefCount(splitPtr); } if (portion == TCL_PATH_TAIL) { /* * Return the last component, unless it is the only component, and * it is the root of an absolute path. */ if ((splitElements > 0) && ((splitElements > 1) || (Tcl_FSGetPathType(pathPtr) == TCL_PATH_RELATIVE))) { Tcl_ListObjIndex(NULL, splitPtr, splitElements-1, &resultPtr); } else { resultPtr = Tcl_NewObj(); } } else { /* * Return all but the last component. If there is only one * component, return it if the path was non-relative, otherwise * return the current directory. */ if (splitElements > 1) { resultPtr = Tcl_FSJoinPath(splitPtr, splitElements - 1); } else if (splitElements == 0 || (Tcl_FSGetPathType(pathPtr) == TCL_PATH_RELATIVE)) { TclNewLiteralStringObj(resultPtr, "."); } else { Tcl_ListObjIndex(NULL, splitPtr, 0, &resultPtr); } } Tcl_IncrRefCount(resultPtr); TclDecrRefCount(splitPtr); return resultPtr; } } /* * Simple helper function */ static Tcl_Obj * GetExtension( Tcl_Obj *pathPtr) { const char *tail, *extension; Tcl_Obj *ret; tail = TclGetString(pathPtr); extension = TclGetExtension(tail); if (extension == NULL) { ret = Tcl_NewObj(); } else { ret = Tcl_NewStringObj(extension, -1); } Tcl_IncrRefCount(ret); return ret; } /* *--------------------------------------------------------------------------- * * Tcl_FSJoinPath -- * * This function takes the given Tcl_Obj, which should be a valid list, * and returns the path object given by considering the first 'elements' * elements as valid path segments (each path segment may be a complete * path, a partial path or just a single possible directory or file * name). If any path segment is actually an absolute path, then all * prior path segments are discarded. * * If elements < 0, we use the entire list that was given. * * It is possible that the returned object is actually an element of the * given list, so the caller should be careful to store a refCount to it * before freeing the list. * * Results: * Returns object with refCount of zero, (or if non-zero, it has * references elsewhere in Tcl). Either way, the caller must increment * its refCount before use. Note that in the case where the caller has * asked to join zero elements of the list, the return value will be an * empty-string Tcl_Obj. * * If the given listObj was invalid, then the calling routine has a bug, * and this function will just return NULL. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSJoinPath( Tcl_Obj *listObj, /* Path elements to join, may have a zero * reference count. */ int elements) /* Number of elements to use (-1 = all) */ { Tcl_Obj *copy, *res; int objc; Tcl_Obj **objv; if (Tcl_ListObjLength(NULL, listObj, &objc) != TCL_OK) { return NULL; } elements = ((elements >= 0) && (elements <= objc)) ? elements : objc; copy = TclListObjCopy(NULL, listObj); Tcl_ListObjGetElements(NULL, listObj, &objc, &objv); res = TclJoinPath(elements, objv); Tcl_DecrRefCount(copy); return res; } Tcl_Obj * TclJoinPath( int elements, Tcl_Obj * const objv[]) { Tcl_Obj *res; int i; const Tcl_Filesystem *fsPtr = NULL; res = NULL; for (i = 0; i < elements; i++) { int driveNameLength, strEltLen, length; Tcl_PathType type; char *strElt, *ptr; Tcl_Obj *driveName = NULL; Tcl_Obj *elt = objv[i]; /* * This is a special case where we can be much more efficient, where * we are joining a single relative path onto an object that is * already of path type. The 'TclNewFSPathObj' call below creates an * object which can be normalized more efficiently. Currently we only * use the special case when we have exactly two elements, but we * could expand that in the future. */ if ((i == (elements-2)) && (i == 0) && (elt->typePtr == &tclFsPathType) && !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))) { Tcl_Obj *tailObj = objv[i+1]; type = TclGetPathType(tailObj, NULL, NULL, NULL); if (type == TCL_PATH_RELATIVE) { const char *str; int len; str = Tcl_GetStringFromObj(tailObj, &len); if (len == 0) { /* * This happens if we try to handle the root volume '/'. * There's no need to return a special path object, when * the base itself is just fine! */ if (res != NULL) { TclDecrRefCount(res); } return elt; } /* * If it doesn't begin with '.' and is a unix path or it a * windows path without backslashes, then we can be very * efficient here. (In fact even a windows path with * backslashes can be joined efficiently, but the path object * would not have forward slashes only, and this would * therefore contradict our 'file join' documentation). */ if (str[0] != '.' && ((tclPlatform != TCL_PLATFORM_WINDOWS) || (strchr(str, '\\') == NULL))) { /* * Finally, on Windows, 'file join' is defined to convert * all backslashes to forward slashes, so the base part * cannot have backslashes either. */ if ((tclPlatform != TCL_PLATFORM_WINDOWS) || (strchr(Tcl_GetString(elt), '\\') == NULL)) { if (res != NULL) { TclDecrRefCount(res); } return TclNewFSPathObj(elt, str, len); } } /* * Otherwise we don't have an easy join, and we must let the * more general code below handle things. */ } else if (tclPlatform == TCL_PLATFORM_UNIX) { if (res != NULL) { TclDecrRefCount(res); } return tailObj; } else { const char *str = TclGetString(tailObj); if (tclPlatform == TCL_PLATFORM_WINDOWS) { if (strchr(str, '\\') == NULL) { if (res != NULL) { TclDecrRefCount(res); } return tailObj; } } } } strElt = Tcl_GetStringFromObj(elt, &strEltLen); type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName); if (type != TCL_PATH_RELATIVE) { /* * Zero out the current result. */ if (res != NULL) { TclDecrRefCount(res); } if (driveName != NULL) { /* * We've been given a separate drive-name object, because the * prefix in 'elt' is not in a suitable format for us (e.g. it * may contain irrelevant multiple separators, like * C://///foo). */ res = Tcl_DuplicateObj(driveName); TclDecrRefCount(driveName); /* * Do not set driveName to NULL, because we will check its * value below (but we won't access the contents, since those * have been cleaned-up). */ } else { res = Tcl_NewStringObj(strElt, driveNameLength); } strElt += driveNameLength; } else if (driveName != NULL) { Tcl_DecrRefCount(driveName); } /* * Optimisation block: if this is the last element to be examined, and * it is absolute or the only element, and the drive-prefix was ok (if * there is one), it might be that the path is already in a suitable * form to be returned. Then we can short-cut the rest of this * function. */ if ((driveName == NULL) && (i == (elements - 1)) && (type != TCL_PATH_RELATIVE || res == NULL)) { /* * It's the last path segment. Perform a quick check if the path * is already in a suitable form. */ if (tclPlatform == TCL_PLATFORM_WINDOWS) { if (strchr(strElt, '\\') != NULL) { goto noQuickReturn; } } ptr = strElt; while (*ptr != '\0') { if (*ptr == '/' && (ptr[1] == '/' || ptr[1] == '\0')) { /* * We have a repeated file separator, which means the path * is not in normalized form */ goto noQuickReturn; } ptr++; } if (res != NULL) { TclDecrRefCount(res); } /* * This element is just what we want to return already; no further * manipulation is requred. */ return elt; } /* * The path element was not of a suitable form to be returned as is. * We need to perform a more complex operation here. */ noQuickReturn: if (res == NULL) { res = Tcl_NewObj(); ptr = Tcl_GetStringFromObj(res, &length); } else { ptr = Tcl_GetStringFromObj(res, &length); } /* * Strip off any './' before a tilde, unless this is the beginning of * the path. */ if (length > 0 && strEltLen > 0 && (strElt[0] == '.') && (strElt[1] == '/') && (strElt[2] == '~')) { strElt += 2; } /* * A NULL value for fsPtr at this stage basically means we're trying * to join a relative path onto something which is also relative (or * empty). There's nothing particularly wrong with that. */ if (*strElt == '\0') { continue; } if (fsPtr == &tclNativeFilesystem || fsPtr == NULL) { TclpNativeJoinPath(res, strElt); } else { char separator = '/'; int needsSep = 0; if (fsPtr->filesystemSeparatorProc != NULL) { Tcl_Obj *sep = fsPtr->filesystemSeparatorProc(res); if (sep != NULL) { separator = TclGetString(sep)[0]; } /* Safety check in case the VFS driver caused sharing */ if (Tcl_IsShared(res)) { TclDecrRefCount(res); res = Tcl_DuplicateObj(res); Tcl_IncrRefCount(res); } } if (length > 0 && ptr[length -1] != '/') { Tcl_AppendToObj(res, &separator, 1); Tcl_GetStringFromObj(res, &length); } Tcl_SetObjLength(res, length + (int) strlen(strElt)); ptr = TclGetString(res) + length; for (; *strElt != '\0'; strElt++) { if (*strElt == separator) { while (strElt[1] == separator) { strElt++; } if (strElt[1] != '\0') { if (needsSep) { *ptr++ = separator; } } } else { *ptr++ = *strElt; needsSep = 1; } } length = ptr - TclGetString(res); Tcl_SetObjLength(res, length); } } if (res == NULL) { res = Tcl_NewObj(); } return res; } /* *--------------------------------------------------------------------------- * * Tcl_FSConvertToPathType -- * * This function tries to convert the given Tcl_Obj to a valid Tcl path * type, taking account of the fact that the cwd may have changed even if * this object is already supposedly of the correct type. * * The filename may begin with "~" (to indicate current user's home * directory) or "~" (to indicate any user's home directory). * * Results: * Standard Tcl error code. * * Side effects: * The old representation may be freed, and new memory allocated. * *--------------------------------------------------------------------------- */ int Tcl_FSConvertToPathType( Tcl_Interp *interp, /* Interpreter in which to store error message * (if necessary). */ Tcl_Obj *pathPtr) /* Object to convert to a valid, current path * type. */ { /* * While it is bad practice to examine an object's type directly, this is * actually the best thing to do here. The reason is that if we are * converting this object to FsPath type for the first time, we don't need * to worry whether the 'cwd' has changed. On the other hand, if this * object is already of FsPath type, and is a relative path, we do have to * worry about the cwd. If the cwd has changed, we must recompute the * path. */ if (pathPtr->typePtr == &tclFsPathType) { if (TclFSEpochOk(PATHOBJ(pathPtr)->filesystemEpoch)) { return TCL_OK; } if (pathPtr->bytes == NULL) { UpdateStringOfFsPath(pathPtr); } FreeFsPathInternalRep(pathPtr); } return SetFsPathFromAny(interp, pathPtr); /* * We used to have more complex code here: * * FsPath *fsPathPtr = PATHOBJ(pathPtr); * if (fsPathPtr->cwdPtr == NULL || PATHFLAGS(pathPtr) != 0) { * return TCL_OK; * } else { * if (TclFSCwdPointerEquals(&fsPathPtr->cwdPtr)) { * return TCL_OK; * } else { * if (pathPtr->bytes == NULL) { * UpdateStringOfFsPath(pathPtr); * } * FreeFsPathInternalRep(pathPtr); * return Tcl_ConvertToType(interp, pathPtr, &tclFsPathType); * } * } * * But we no longer believe this is necessary. */ } /* * Helper function for normalization. */ static int IsSeparatorOrNull( int ch) { if (ch == 0) { return 1; } switch (tclPlatform) { case TCL_PLATFORM_UNIX: return (ch == '/' ? 1 : 0); case TCL_PLATFORM_WINDOWS: return ((ch == '/' || ch == '\\') ? 1 : 0); } return 0; } /* * Helper function for SetFsPathFromAny. Returns position of first directory * delimiter in the path. If no separator is found, then returns the position * of the end of the string. */ static int FindSplitPos( const char *path, int separator) { int count = 0; switch (tclPlatform) { case TCL_PLATFORM_UNIX: while (path[count] != 0) { if (path[count] == separator) { return count; } count++; } break; case TCL_PLATFORM_WINDOWS: while (path[count] != 0) { if (path[count] == separator || path[count] == '\\') { return count; } count++; } break; } return count; } /* *--------------------------------------------------------------------------- * * TclNewFSPathObj -- * * Creates a path object whose string representation is '[file join * dirPtr addStrRep]', but does so in a way that allows for more * efficient creation and caching of normalized paths, and more efficient * 'file dirname', 'file tail', etc. * * Assumptions: * 'dirPtr' must be an absolute path. 'len' may not be zero. * * Results: * The new Tcl object, with refCount zero. * * Side effects: * Memory is allocated. 'dirPtr' gets an additional refCount. * *--------------------------------------------------------------------------- */ Tcl_Obj * TclNewFSPathObj( Tcl_Obj *dirPtr, const char *addStrRep, int len) { FsPath *fsPathPtr; Tcl_Obj *pathPtr; const char *p; int state = 0, count = 0; /* [Bug 2806250] - this is only a partial solution of the problem. * The PATHFLAGS != 0 representation assumes in many places that * the "tail" part stored in the normPathPtr field is itself a * relative path. Strings that begin with "~" are not relative paths, * so we must prevent their storage in the normPathPtr field. * * More generally we ought to be testing "addStrRep" for any value * that is not a relative path, but in an unconstrained VFS world * that could be just about anything, and testing could be expensive. * Since this routine plays a big role in [glob], anything that slows * it down would be unwelcome. For now, continue the risk of further * bugs when some Tcl_Filesystem uses otherwise relative path strings * as absolute path strings. Sensible Tcl_Filesystems will avoid * that by mounting on path prefixes like foo:// which cannot be the * name of a file or directory read from a native [glob] operation. */ if (addStrRep[0] == '~') { Tcl_Obj *tail = Tcl_NewStringObj(addStrRep, len); pathPtr = AppendPath(dirPtr, tail); Tcl_DecrRefCount(tail); return pathPtr; } pathPtr = Tcl_NewObj(); fsPathPtr = ckalloc(sizeof(FsPath)); /* * Set up the path. */ fsPathPtr->translatedPathPtr = NULL; fsPathPtr->normPathPtr = Tcl_NewStringObj(addStrRep, len); Tcl_IncrRefCount(fsPathPtr->normPathPtr); fsPathPtr->cwdPtr = dirPtr; Tcl_IncrRefCount(dirPtr); fsPathPtr->nativePathPtr = NULL; fsPathPtr->fsPtr = NULL; fsPathPtr->filesystemEpoch = 0; SETPATHOBJ(pathPtr, fsPathPtr); PATHFLAGS(pathPtr) = TCLPATH_APPENDED; pathPtr->typePtr = &tclFsPathType; pathPtr->bytes = NULL; pathPtr->length = 0; /* * Look for path components made up of only "." * This is overly conservative analysis to keep simple. It may mark some * things as needing more aggressive normalization that don't actually * need it. No harm done. */ for (p = addStrRep; len > 0; p++, len--) { switch (state) { case 0: /* So far only "." since last dirsep or start */ switch (*p) { case '.': count++; break; case '/': case '\\': case ':': if (count) { PATHFLAGS(pathPtr) |= TCLPATH_NEEDNORM; len = 0; } break; default: count = 0; state = 1; } case 1: /* Scanning for next dirsep */ switch (*p) { case '/': case '\\': case ':': state = 0; break; } } } if (len == 0 && count) { PATHFLAGS(pathPtr) |= TCLPATH_NEEDNORM; } return pathPtr; } static Tcl_Obj * AppendPath( Tcl_Obj *head, Tcl_Obj *tail) { int numBytes; const char *bytes; Tcl_Obj *copy = Tcl_DuplicateObj(head); /* * This is likely buggy when dealing with virtual filesystem drivers * that use some character other than "/" as a path separator. I know * of no evidence that such a foolish thing exists. This solution was * chosen so that "JoinPath" operations that pass through either path * intrep produce the same results; that is, bugward compatibility. If * we need to fix that bug here, it needs fixing in TclJoinPath() too. */ bytes = Tcl_GetStringFromObj(tail, &numBytes); if (numBytes == 0) { Tcl_AppendToObj(copy, "/", 1); } else { TclpNativeJoinPath(copy, bytes); } return copy; } /* *--------------------------------------------------------------------------- * * TclFSMakePathRelative -- * * Only for internal use. * * Takes a path and a directory, where we _assume_ both path and * directory are absolute, normalized and that the path lies inside the * directory. Returns a Tcl_Obj representing filename of the path * relative to the directory. * * Results: * NULL on error, otherwise a valid object, typically with refCount of * zero, which it is assumed the caller will increment. * * Side effects: * The old representation may be freed, and new memory allocated. * *--------------------------------------------------------------------------- */ Tcl_Obj * TclFSMakePathRelative( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *pathPtr, /* The path we have. */ Tcl_Obj *cwdPtr) /* Make it relative to this. */ { int cwdLen, len; const char *tempStr; if (pathPtr->typePtr == &tclFsPathType) { FsPath *fsPathPtr = PATHOBJ(pathPtr); if (PATHFLAGS(pathPtr) != 0 && fsPathPtr->cwdPtr == cwdPtr) { return fsPathPtr->normPathPtr; } } /* * We know the cwd is a normalised object which does not end in a * directory delimiter, unless the cwd is the name of a volume, in which * case it will end in a delimiter! We handle this situation here. A * better test than the '!= sep' might be to simply check if 'cwd' is a * root volume. * * Note that if we get this wrong, we will strip off either too much or * too little below, leading to wrong answers returned by glob. */ tempStr = Tcl_GetStringFromObj(cwdPtr, &cwdLen); /* * Should we perhaps use 'Tcl_FSPathSeparator'? But then what about the * Windows special case? Perhaps we should just check if cwd is a root * volume. */ switch (tclPlatform) { case TCL_PLATFORM_UNIX: if (tempStr[cwdLen-1] != '/') { cwdLen++; } break; case TCL_PLATFORM_WINDOWS: if (tempStr[cwdLen-1] != '/' && tempStr[cwdLen-1] != '\\') { cwdLen++; } break; } tempStr = Tcl_GetStringFromObj(pathPtr, &len); return Tcl_NewStringObj(tempStr + cwdLen, len - cwdLen); } /* *--------------------------------------------------------------------------- * * MakePathFromNormalized -- * * Like SetFsPathFromAny, but assumes the given object is an absolute * normalized path. Only for internal use. * * Results: * Standard Tcl error code. * * Side effects: * The old representation may be freed, and new memory allocated. * *--------------------------------------------------------------------------- */ static int MakePathFromNormalized( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *pathPtr) /* The object to convert. */ { FsPath *fsPathPtr; if (pathPtr->typePtr == &tclFsPathType) { return TCL_OK; } /* * Free old representation */ if (pathPtr->typePtr != NULL) { if (pathPtr->bytes == NULL) { if (pathPtr->typePtr->updateStringProc == NULL) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can't find object string representation", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "PATH", "WTF", NULL); } return TCL_ERROR; } pathPtr->typePtr->updateStringProc(pathPtr); } TclFreeIntRep(pathPtr); } fsPathPtr = ckalloc(sizeof(FsPath)); /* * It's a pure normalized absolute path. */ fsPathPtr->translatedPathPtr = NULL; /* * Circular reference by design. */ fsPathPtr->normPathPtr = pathPtr; fsPathPtr->cwdPtr = NULL; fsPathPtr->nativePathPtr = NULL; fsPathPtr->fsPtr = NULL; /* Remember the epoch under which we decided pathPtr was normalized */ fsPathPtr->filesystemEpoch = TclFSEpoch(); SETPATHOBJ(pathPtr, fsPathPtr); PATHFLAGS(pathPtr) = 0; pathPtr->typePtr = &tclFsPathType; return TCL_OK; } /* *--------------------------------------------------------------------------- * * Tcl_FSNewNativePath -- * * This function performs the something like the reverse of the usual * obj->path->nativerep conversions. If some code retrieves a path in * native form (from, e.g. readlink or a native dialog), and that path is * to be used at the Tcl level, then calling this function is an * efficient way of creating the appropriate path object type. * * Any memory which is allocated for 'clientData' should be retained * until clientData is passed to the filesystem's freeInternalRepProc * when it can be freed. The built in platform-specific filesystems use * 'ckalloc' to allocate clientData, and ckfree to free it. * * Results: * NULL or a valid path object pointer, with refCount zero. * * Side effects: * New memory may be allocated. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSNewNativePath( const Tcl_Filesystem *fromFilesystem, ClientData clientData) { Tcl_Obj *pathPtr = NULL; FsPath *fsPathPtr; if (fromFilesystem->internalToNormalizedProc != NULL) { pathPtr = (*fromFilesystem->internalToNormalizedProc)(clientData); } if (pathPtr == NULL) { return NULL; } /* * Free old representation; shouldn't normally be any, but best to be * safe. */ if (pathPtr->typePtr != NULL) { if (pathPtr->bytes == NULL) { if (pathPtr->typePtr->updateStringProc == NULL) { return NULL; } pathPtr->typePtr->updateStringProc(pathPtr); } TclFreeIntRep(pathPtr); } fsPathPtr = ckalloc(sizeof(FsPath)); fsPathPtr->translatedPathPtr = NULL; /* * Circular reference, by design. */ fsPathPtr->normPathPtr = pathPtr; fsPathPtr->cwdPtr = NULL; fsPathPtr->nativePathPtr = clientData; fsPathPtr->fsPtr = fromFilesystem; fsPathPtr->filesystemEpoch = TclFSEpoch(); SETPATHOBJ(pathPtr, fsPathPtr); PATHFLAGS(pathPtr) = 0; pathPtr->typePtr = &tclFsPathType; return pathPtr; } /* *--------------------------------------------------------------------------- * * Tcl_FSGetTranslatedPath -- * * This function attempts to extract the translated path from the given * Tcl_Obj. If the translation succeeds (i.e. the object is a valid * path), then it is returned. Otherwise NULL will be returned, and an * error message may be left in the interpreter (if it is non-NULL) * * Results: * NULL or a valid Tcl_Obj pointer. * * Side effects: * Only those of 'Tcl_FSConvertToPathType' * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSGetTranslatedPath( Tcl_Interp *interp, Tcl_Obj *pathPtr) { Tcl_Obj *retObj = NULL; FsPath *srcFsPathPtr; if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) { return NULL; } srcFsPathPtr = PATHOBJ(pathPtr); if (srcFsPathPtr->translatedPathPtr == NULL) { if (PATHFLAGS(pathPtr) != 0) { /* * We lack a translated path result, but we have a directory * (cwdPtr) and a tail (normPathPtr), and if we join the * translated version of cwdPtr to normPathPtr, we'll get the * translated result we need, and can store it for future use. */ Tcl_Obj *translatedCwdPtr = Tcl_FSGetTranslatedPath(interp, srcFsPathPtr->cwdPtr); if (translatedCwdPtr == NULL) { return NULL; } retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1, &srcFsPathPtr->normPathPtr); srcFsPathPtr->translatedPathPtr = retObj; if (translatedCwdPtr->typePtr == &tclFsPathType) { srcFsPathPtr->filesystemEpoch = PATHOBJ(translatedCwdPtr)->filesystemEpoch; } else { srcFsPathPtr->filesystemEpoch = 0; } Tcl_IncrRefCount(retObj); Tcl_DecrRefCount(translatedCwdPtr); } else { /* * It is a pure absolute, normalized path object. This is * something like being a 'pure list'. The object's string, * translatedPath and normalizedPath are all identical. */ retObj = srcFsPathPtr->normPathPtr; } } else { /* * It is an ordinary path object. */ retObj = srcFsPathPtr->translatedPathPtr; } if (retObj != NULL) { Tcl_IncrRefCount(retObj); } return retObj; } /* *--------------------------------------------------------------------------- * * Tcl_FSGetTranslatedStringPath -- * * This function attempts to extract the translated path from the given * Tcl_Obj. If the translation succeeds (i.e. the object is a valid * path), then the path is returned. Otherwise NULL will be returned, and * an error message may be left in the interpreter (if it is non-NULL) * * Results: * NULL or a valid string. * * Side effects: * Only those of 'Tcl_FSConvertToPathType' * *--------------------------------------------------------------------------- */ const char * Tcl_FSGetTranslatedStringPath( Tcl_Interp *interp, Tcl_Obj *pathPtr) { Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(interp, pathPtr); if (transPtr != NULL) { int len; const char *orig = Tcl_GetStringFromObj(transPtr, &len); char *result = ckalloc(len+1); memcpy(result, orig, (size_t) len+1); TclDecrRefCount(transPtr); return result; } return NULL; } /* *--------------------------------------------------------------------------- * * Tcl_FSGetNormalizedPath -- * * This important function attempts to extract from the given Tcl_Obj a * unique normalised path representation, whose string value can be used * as a unique identifier for the file. * * Results: * NULL or a valid path object pointer. * * Side effects: * New memory may be allocated. The Tcl 'errno' may be modified in the * process of trying to examine various path possibilities. * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSGetNormalizedPath( Tcl_Interp *interp, Tcl_Obj *pathPtr) { FsPath *fsPathPtr; if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) { return NULL; } fsPathPtr = PATHOBJ(pathPtr); if (PATHFLAGS(pathPtr) != 0) { /* * This is a special path object which is the result of something like * 'file join' */ Tcl_Obj *dir, *copy; int tailLen, cwdLen, pathType; pathType = Tcl_FSGetPathType(fsPathPtr->cwdPtr); dir = Tcl_FSGetNormalizedPath(interp, fsPathPtr->cwdPtr); if (dir == NULL) { return NULL; } /* TODO: Figure out why this is needed. */ if (pathPtr->bytes == NULL) { UpdateStringOfFsPath(pathPtr); } Tcl_GetStringFromObj(fsPathPtr->normPathPtr, &tailLen); if (tailLen) { copy = AppendPath(dir, fsPathPtr->normPathPtr); } else { copy = Tcl_DuplicateObj(dir); } Tcl_IncrRefCount(dir); Tcl_IncrRefCount(copy); /* * We now own a reference on both 'dir' and 'copy' */ (void) Tcl_GetStringFromObj(dir, &cwdLen); cwdLen += (Tcl_GetString(copy)[cwdLen] == '/'); /* Normalize the combined string. */ if (PATHFLAGS(pathPtr) & TCLPATH_NEEDNORM) { /* * If the "tail" part has components (like /../) that cause the * combined path to need more complete normalizing, call on the * more powerful routine to accomplish that so we avoid [Bug * 2385549] ... */ Tcl_Obj *newCopy = TclFSNormalizeAbsolutePath(interp, copy); Tcl_DecrRefCount(copy); copy = newCopy; } else { /* * ... but in most cases where we join a trouble free tail to a * normalized head, we can more efficiently normalize the combined * path by passing over only the unnormalized tail portion. When * this is sufficient, prior developers claim this should be much * faster. We use 'cwdLen-1' so that we are already pointing at * the dir-separator that we know about. The normalization code * will actually start off directly after that separator. */ TclFSNormalizeToUniquePath(interp, copy, cwdLen-1); } /* Now we need to construct the new path object. */ if (pathType == TCL_PATH_RELATIVE) { Tcl_Obj *origDir = fsPathPtr->cwdPtr; /* * NOTE: here we are (dangerously?) assuming that origDir points * to a Tcl_Obj with Tcl_ObjType == &tclFsPathType. The * pathType = Tcl_FSGetPathType(fsPathPtr->cwdPtr); * above that set the pathType value should have established that, * but it's far less clear on what basis we know there's been no * shimmering since then. */ FsPath *origDirFsPathPtr = PATHOBJ(origDir); fsPathPtr->cwdPtr = origDirFsPathPtr->cwdPtr; Tcl_IncrRefCount(fsPathPtr->cwdPtr); TclDecrRefCount(fsPathPtr->normPathPtr); fsPathPtr->normPathPtr = copy; /* * That's our reference to copy used. */ TclDecrRefCount(dir); TclDecrRefCount(origDir); } else { TclDecrRefCount(fsPathPtr->cwdPtr); fsPathPtr->cwdPtr = NULL; TclDecrRefCount(fsPathPtr->normPathPtr); fsPathPtr->normPathPtr = copy; /* * That's our reference to copy used. */ TclDecrRefCount(dir); } PATHFLAGS(pathPtr) = 0; } /* * Ensure cwd hasn't changed. */ if (fsPathPtr->cwdPtr != NULL) { if (!TclFSCwdPointerEquals(&fsPathPtr->cwdPtr)) { if (pathPtr->bytes == NULL) { UpdateStringOfFsPath(pathPtr); } FreeFsPathInternalRep(pathPtr); if (SetFsPathFromAny(interp, pathPtr) != TCL_OK) { return NULL; } fsPathPtr = PATHOBJ(pathPtr); } else if (fsPathPtr->normPathPtr == NULL) { int cwdLen; Tcl_Obj *copy; copy = AppendPath(fsPathPtr->cwdPtr, pathPtr); (void) Tcl_GetStringFromObj(fsPathPtr->cwdPtr, &cwdLen); cwdLen += (Tcl_GetString(copy)[cwdLen] == '/'); /* * Normalize the combined string, but only starting after the end * of the previously normalized 'dir'. This should be much faster! */ TclFSNormalizeToUniquePath(interp, copy, cwdLen-1); fsPathPtr->normPathPtr = copy; Tcl_IncrRefCount(fsPathPtr->normPathPtr); } } if (fsPathPtr->normPathPtr == NULL) { Tcl_Obj *useThisCwd = NULL; int pureNormalized = 1; /* * Since normPathPtr is NULL, but this is a valid path object, we know * that the translatedPathPtr cannot be NULL. */ Tcl_Obj *absolutePath = fsPathPtr->translatedPathPtr; const char *path = TclGetString(absolutePath); Tcl_IncrRefCount(absolutePath); /* * We have to be a little bit careful here to avoid infinite loops * we're asking Tcl_FSGetPathType to return the path's type, but that * call can actually result in a lot of other filesystem action, which * might loop back through here. */ if (path[0] == '\0') { /* * Special handling for the empty string value. This one is very * weird with [file normalize {}] => {}. (The reasoning supporting * this is unknown to DGP, but he fears changing it.) Attempt here * to keep the expectations of other parts of Tcl_Filesystem code * about state of the FsPath fields satisfied. * * In particular, capture the cwd value and save so it can be * stored in the cwdPtr field below. */ useThisCwd = Tcl_FSGetCwd(interp); } else { /* * We don't ask for the type of 'pathPtr' here, because that is * not correct for our purposes when we have a path like '~'. Tcl * has a bit of a contradiction in that '~' paths are defined as * 'absolute', but in reality can be just about anything, * depending on how env(HOME) is set. */ Tcl_PathType type = Tcl_FSGetPathType(absolutePath); if (type == TCL_PATH_RELATIVE) { useThisCwd = Tcl_FSGetCwd(interp); if (useThisCwd == NULL) { return NULL; } pureNormalized = 0; Tcl_DecrRefCount(absolutePath); absolutePath = Tcl_FSJoinToPath(useThisCwd, 1, &absolutePath); Tcl_IncrRefCount(absolutePath); /* * We have a refCount on the cwd. */ #ifdef _WIN32 } else if (type == TCL_PATH_VOLUME_RELATIVE) { /* * Only Windows has volume-relative paths. */ Tcl_DecrRefCount(absolutePath); absolutePath = TclWinVolumeRelativeNormalize(interp, path, &useThisCwd); if (absolutePath == NULL) { return NULL; } pureNormalized = 0; #endif /* _WIN32 */ } } /* * Already has refCount incremented. */ fsPathPtr->normPathPtr = TclFSNormalizeAbsolutePath(interp, absolutePath); /* * Check if path is pure normalized (this can only be the case if it * is an absolute path). */ if (pureNormalized) { int normPathLen, pathLen; const char *normPath; path = TclGetStringFromObj(pathPtr, &pathLen); normPath = TclGetStringFromObj(fsPathPtr->normPathPtr, &normPathLen); if ((pathLen == normPathLen) && !memcmp(path, normPath, pathLen)) { /* * The path was already normalized. Get rid of the duplicate. */ TclDecrRefCount(fsPathPtr->normPathPtr); /* * We do *not* increment the refCount for this circular * reference. */ fsPathPtr->normPathPtr = pathPtr; } } if (useThisCwd != NULL) { /* * We just need to free an object we allocated above for relative * paths (this was returned by Tcl_FSJoinToPath above), and then * of course store the cwd. */ fsPathPtr->cwdPtr = useThisCwd; } TclDecrRefCount(absolutePath); } return fsPathPtr->normPathPtr; } /* *--------------------------------------------------------------------------- * * Tcl_FSGetInternalRep -- * * Extract the internal representation of a given path object, in the * given filesystem. If the path object belongs to a different * filesystem, we return NULL. * * If the internal representation is currently NULL, we attempt to * generate it, by calling the filesystem's * 'Tcl_FSCreateInternalRepProc'. * * Results: * NULL or a valid internal representation. * * Side effects: * An attempt may be made to convert the object. * *--------------------------------------------------------------------------- */ ClientData Tcl_FSGetInternalRep( Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr) { FsPath *srcFsPathPtr; if (Tcl_FSConvertToPathType(NULL, pathPtr) != TCL_OK) { return NULL; } srcFsPathPtr = PATHOBJ(pathPtr); /* * We will only return the native representation for the caller's * filesystem. Otherwise we will simply return NULL. This means that there * must be a unique bi-directional mapping between paths and filesystems, * and that this mapping will not allow 'remapped' files -- files which * are in one filesystem but mapped into another. Another way of putting * this is that 'stacked' filesystems are not allowed. We recognise that * this is a potentially useful feature for the future. * * Even something simple like a 'pass through' filesystem which logs all * activity and passes the calls onto the native system would be nice, but * not easily achievable with the current implementation. */ if (srcFsPathPtr->fsPtr == NULL) { /* * This only usually happens in wrappers like TclpStat which create a * string object and pass it to TclpObjStat. Code which calls the * Tcl_FS.. functions should always have a filesystem already set. * Whether this code path is legal or not depends on whether we decide * to allow external code to call the native filesystem directly. It * is at least safer to allow this sub-optimal routing. */ Tcl_FSGetFileSystemForPath(pathPtr); /* * If we fail through here, then the path is probably not a valid path * in the filesystsem, and is most likely to be a use of the empty * path "" via a direct call to one of the objectified interfaces * (e.g. from the Tcl testsuite). */ srcFsPathPtr = PATHOBJ(pathPtr); if (srcFsPathPtr->fsPtr == NULL) { return NULL; } } /* * There is still one possibility we should consider; if the file belongs * to a different filesystem, perhaps it is actually linked through to a * file in our own filesystem which we do care about. The way we can check * for this is we ask what filesystem this path belongs to. */ if (fsPtr != srcFsPathPtr->fsPtr) { const Tcl_Filesystem *actualFs = Tcl_FSGetFileSystemForPath(pathPtr); if (actualFs == fsPtr) { return Tcl_FSGetInternalRep(pathPtr, fsPtr); } return NULL; } if (srcFsPathPtr->nativePathPtr == NULL) { Tcl_FSCreateInternalRepProc *proc; char *nativePathPtr; proc = srcFsPathPtr->fsPtr->createInternalRepProc; if (proc == NULL) { return NULL; } nativePathPtr = proc(pathPtr); srcFsPathPtr = PATHOBJ(pathPtr); srcFsPathPtr->nativePathPtr = nativePathPtr; } return srcFsPathPtr->nativePathPtr; } /* *--------------------------------------------------------------------------- * * TclFSEnsureEpochOk -- * * This will ensure the pathPtr is up to date and can be converted into a * "path" type, and that we are able to generate a complete normalized * path which is used to determine the filesystem match. * * Results: * Standard Tcl return code. * * Side effects: * An attempt may be made to convert the object. * *--------------------------------------------------------------------------- */ int TclFSEnsureEpochOk( Tcl_Obj *pathPtr, const Tcl_Filesystem **fsPtrPtr) { FsPath *srcFsPathPtr; if (pathPtr->typePtr != &tclFsPathType) { return TCL_OK; } srcFsPathPtr = PATHOBJ(pathPtr); /* * Check if the filesystem has changed in some way since this object's * internal representation was calculated. */ if (!TclFSEpochOk(srcFsPathPtr->filesystemEpoch)) { /* * We have to discard the stale representation and recalculate it. */ if (pathPtr->bytes == NULL) { UpdateStringOfFsPath(pathPtr); } FreeFsPathInternalRep(pathPtr); if (SetFsPathFromAny(NULL, pathPtr) != TCL_OK) { return TCL_ERROR; } srcFsPathPtr = PATHOBJ(pathPtr); } /* * Check whether the object is already assigned to a fs. */ if (srcFsPathPtr->fsPtr != NULL) { *fsPtrPtr = srcFsPathPtr->fsPtr; } return TCL_OK; } /* *--------------------------------------------------------------------------- * * TclFSSetPathDetails -- * * ??? * * Results: * None * * Side effects: * ??? * *--------------------------------------------------------------------------- */ void TclFSSetPathDetails( Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr, ClientData clientData) { FsPath *srcFsPathPtr; /* * Make sure pathPtr is of the correct type. */ if (pathPtr->typePtr != &tclFsPathType) { if (SetFsPathFromAny(NULL, pathPtr) != TCL_OK) { return; } } srcFsPathPtr = PATHOBJ(pathPtr); srcFsPathPtr->fsPtr = fsPtr; srcFsPathPtr->nativePathPtr = clientData; srcFsPathPtr->filesystemEpoch = TclFSEpoch(); } /* *--------------------------------------------------------------------------- * * Tcl_FSEqualPaths -- * * This function tests whether the two paths given are equal path * objects. If either or both is NULL, 0 is always returned. * * Results: * 1 or 0. * * Side effects: * None. * *--------------------------------------------------------------------------- */ int Tcl_FSEqualPaths( Tcl_Obj *firstPtr, Tcl_Obj *secondPtr) { const char *firstStr, *secondStr; int firstLen, secondLen, tempErrno; if (firstPtr == secondPtr) { return 1; } if (firstPtr == NULL || secondPtr == NULL) { return 0; } firstStr = TclGetStringFromObj(firstPtr, &firstLen); secondStr = TclGetStringFromObj(secondPtr, &secondLen); if ((firstLen == secondLen) && !memcmp(firstStr, secondStr, firstLen)) { return 1; } /* * Try the most thorough, correct method of comparing fully normalized * paths. */ tempErrno = Tcl_GetErrno(); firstPtr = Tcl_FSGetNormalizedPath(NULL, firstPtr); secondPtr = Tcl_FSGetNormalizedPath(NULL, secondPtr); Tcl_SetErrno(tempErrno); if (firstPtr == NULL || secondPtr == NULL) { return 0; } firstStr = TclGetStringFromObj(firstPtr, &firstLen); secondStr = TclGetStringFromObj(secondPtr, &secondLen); return ((firstLen == secondLen) && !memcmp(firstStr, secondStr, firstLen)); } /* *--------------------------------------------------------------------------- * * SetFsPathFromAny -- * * This function tries to convert the given Tcl_Obj to a valid Tcl path * type. * * The filename may begin with "~" (to indicate current user's home * directory) or "~" (to indicate any user's home directory). * * Results: * Standard Tcl error code. * * Side effects: * The old representation may be freed, and new memory allocated. * *--------------------------------------------------------------------------- */ static int SetFsPathFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *pathPtr) /* The object to convert. */ { int len; FsPath *fsPathPtr; Tcl_Obj *transPtr; char *name; if (pathPtr->typePtr == &tclFsPathType) { return TCL_OK; } /* * First step is to translate the filename. This is similar to * Tcl_TranslateFilename, but shouldn't convert everything to windows * backslashes on that platform. The current implementation of this piece * is a slightly optimised version of the various Tilde/Split/Join stuff * to avoid multiple split/join operations. * * We remove any trailing directory separator. * * However, the split/join routines are quite complex, and one has to make * sure not to break anything on Unix or Win (fCmd.test, fileName.test and * cmdAH.test exercise most of the code). */ name = Tcl_GetStringFromObj(pathPtr, &len); /* * Handle tilde substitutions, if needed. */ if (name[0] == '~') { Tcl_DString temp; int split; char separator = '/'; split = FindSplitPos(name, separator); if (split != len) { /* * We have multiple pieces '~user/foo/bar...' */ name[split] = '\0'; } /* * Do some tilde substitution. */ if (name[1] == '\0') { /* * We have just '~' */ const char *dir; Tcl_DString dirString; if (split != len) { name[split] = separator; } dir = TclGetEnv("HOME", &dirString); if (dir == NULL) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "couldn't find HOME environment variable to" " expand path", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "PATH", "HOMELESS", NULL); } return TCL_ERROR; } Tcl_DStringInit(&temp); Tcl_JoinPath(1, &dir, &temp); Tcl_DStringFree(&dirString); } else { /* * We have a user name '~user' */ Tcl_DStringInit(&temp); if (TclpGetUserHome(name+1, &temp) == NULL) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "user \"%s\" doesn't exist", name+1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "PATH", "NOUSER", NULL); } Tcl_DStringFree(&temp); if (split != len) { name[split] = separator; } return TCL_ERROR; } if (split != len) { name[split] = separator; } } transPtr = TclDStringToObj(&temp); if (split != len) { /* * Join up the tilde substitution with the rest. */ if (name[split+1] == separator) { /* * Somewhat tricky case like ~//foo/bar. Make use of * Split/Join machinery to get it right. Assumes all paths * beginning with ~ are part of the native filesystem. */ int objc; Tcl_Obj **objv; Tcl_Obj *parts = TclpNativeSplitPath(pathPtr, NULL); Tcl_ListObjGetElements(NULL, parts, &objc, &objv); /* * Skip '~'. It's replaced by its expansion. */ objc--; objv++; while (objc--) { TclpNativeJoinPath(transPtr, Tcl_GetString(*objv++)); } TclDecrRefCount(parts); } else { Tcl_Obj *pair[2]; pair[0] = transPtr; pair[1] = Tcl_NewStringObj(name+split+1, -1); transPtr = TclJoinPath(2, pair); Tcl_DecrRefCount(pair[0]); Tcl_DecrRefCount(pair[1]); } } } else { transPtr = TclJoinPath(1, &pathPtr); } /* * Now we have a translated filename in 'transPtr'. This will have forward * slashes on Windows, and will not contain any ~user sequences. */ fsPathPtr = ckalloc(sizeof(FsPath)); fsPathPtr->translatedPathPtr = transPtr; if (transPtr != pathPtr) { Tcl_IncrRefCount(fsPathPtr->translatedPathPtr); /* Redo translation when $env(HOME) changes */ fsPathPtr->filesystemEpoch = TclFSEpoch(); } else { fsPathPtr->filesystemEpoch = 0; } fsPathPtr->normPathPtr = NULL; fsPathPtr->cwdPtr = NULL; fsPathPtr->nativePathPtr = NULL; fsPathPtr->fsPtr = NULL; /* * Free old representation before installing our new one. */ TclFreeIntRep(pathPtr); SETPATHOBJ(pathPtr, fsPathPtr); PATHFLAGS(pathPtr) = 0; pathPtr->typePtr = &tclFsPathType; return TCL_OK; } static void FreeFsPathInternalRep( Tcl_Obj *pathPtr) /* Path object with internal rep to free. */ { FsPath *fsPathPtr = PATHOBJ(pathPtr); if (fsPathPtr->translatedPathPtr != NULL) { if (fsPathPtr->translatedPathPtr != pathPtr) { TclDecrRefCount(fsPathPtr->translatedPathPtr); } } if (fsPathPtr->normPathPtr != NULL) { if (fsPathPtr->normPathPtr != pathPtr) { TclDecrRefCount(fsPathPtr->normPathPtr); } fsPathPtr->normPathPtr = NULL; } if (fsPathPtr->cwdPtr != NULL) { TclDecrRefCount(fsPathPtr->cwdPtr); } if (fsPathPtr->nativePathPtr != NULL && fsPathPtr->fsPtr != NULL) { Tcl_FSFreeInternalRepProc *freeProc = fsPathPtr->fsPtr->freeInternalRepProc; if (freeProc != NULL) { freeProc(fsPathPtr->nativePathPtr); fsPathPtr->nativePathPtr = NULL; } } ckfree(fsPathPtr); pathPtr->typePtr = NULL; } static void DupFsPathInternalRep( Tcl_Obj *srcPtr, /* Path obj with internal rep to copy. */ Tcl_Obj *copyPtr) /* Path obj with internal rep to set. */ { FsPath *srcFsPathPtr = PATHOBJ(srcPtr); FsPath *copyFsPathPtr = ckalloc(sizeof(FsPath)); SETPATHOBJ(copyPtr, copyFsPathPtr); if (srcFsPathPtr->translatedPathPtr == srcPtr) { /* Cycle in src -> make cycle in copy. */ copyFsPathPtr->translatedPathPtr = copyPtr; } else { copyFsPathPtr->translatedPathPtr = srcFsPathPtr->translatedPathPtr; if (copyFsPathPtr->translatedPathPtr != NULL) { Tcl_IncrRefCount(copyFsPathPtr->translatedPathPtr); } } if (srcFsPathPtr->normPathPtr == srcPtr) { /* Cycle in src -> make cycle in copy. */ copyFsPathPtr->normPathPtr = copyPtr; } else { copyFsPathPtr->normPathPtr = srcFsPathPtr->normPathPtr; if (copyFsPathPtr->normPathPtr != NULL) { Tcl_IncrRefCount(copyFsPathPtr->normPathPtr); } } copyFsPathPtr->cwdPtr = srcFsPathPtr->cwdPtr; if (copyFsPathPtr->cwdPtr != NULL) { Tcl_IncrRefCount(copyFsPathPtr->cwdPtr); } copyFsPathPtr->flags = srcFsPathPtr->flags; if (srcFsPathPtr->fsPtr != NULL && srcFsPathPtr->nativePathPtr != NULL) { Tcl_FSDupInternalRepProc *dupProc = srcFsPathPtr->fsPtr->dupInternalRepProc; if (dupProc != NULL) { copyFsPathPtr->nativePathPtr = dupProc(srcFsPathPtr->nativePathPtr); } else { copyFsPathPtr->nativePathPtr = NULL; } } else { copyFsPathPtr->nativePathPtr = NULL; } copyFsPathPtr->fsPtr = srcFsPathPtr->fsPtr; copyFsPathPtr->filesystemEpoch = srcFsPathPtr->filesystemEpoch; copyPtr->typePtr = &tclFsPathType; } /* *--------------------------------------------------------------------------- * * UpdateStringOfFsPath -- * * Gives an object a valid string rep. * * Results: * None. * * Side effects: * Memory may be allocated. * *--------------------------------------------------------------------------- */ static void UpdateStringOfFsPath( register Tcl_Obj *pathPtr) /* path obj with string rep to update. */ { FsPath *fsPathPtr = PATHOBJ(pathPtr); int cwdLen; Tcl_Obj *copy; if (PATHFLAGS(pathPtr) == 0 || fsPathPtr->cwdPtr == NULL) { Tcl_Panic("Called UpdateStringOfFsPath with invalid object"); } copy = AppendPath(fsPathPtr->cwdPtr, fsPathPtr->normPathPtr); pathPtr->bytes = Tcl_GetStringFromObj(copy, &cwdLen); pathPtr->length = cwdLen; copy->bytes = tclEmptyStringRep; copy->length = 0; TclDecrRefCount(copy); } /* *--------------------------------------------------------------------------- * * TclNativePathInFilesystem -- * * Any path object is acceptable to the native filesystem, by default (we * will throw errors when illegal paths are actually tried to be used). * * However, this behavior means the native filesystem must be the last * filesystem in the lookup list (otherwise it will claim all files * belong to it, and other filesystems will never get a look in). * * Results: * TCL_OK, to indicate 'yes', -1 to indicate no. * * Side effects: * None. * *--------------------------------------------------------------------------- */ int TclNativePathInFilesystem( Tcl_Obj *pathPtr, ClientData *clientDataPtr) { /* * A special case is required to handle the empty path "". This is a valid * path (i.e. the user should be able to do 'file exists ""' without * throwing an error), but equally the path doesn't exist. Those are the * semantics of Tcl (at present anyway), so we have to abide by them here. */ if (pathPtr->typePtr == &tclFsPathType) { if (pathPtr->bytes != NULL && pathPtr->bytes[0] == '\0') { /* * We reject the empty path "". */ return -1; } /* * Otherwise there is no way this path can be empty. */ } else { /* * It is somewhat unusual to reach this code path without the object * being of tclFsPathType. However, we do our best to deal with the * situation. */ int len; (void) Tcl_GetStringFromObj(pathPtr, &len); if (len == 0) { /* * We reject the empty path "". */ return -1; } } /* * Path is of correct type, or is of non-zero length, so we accept it. */ return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/regex.h0000644000175000017500000002465512663660065014502 0ustar sergeisergei#ifndef _REGEX_H_ #define _REGEX_H_ /* never again */ #include "tclInt.h" /* * regular expressions * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * Prototypes etc. marked with "^" within comments get gathered up (and * possibly edited) by the regfwd program and inserted near the bottom of this * file. * * We offer the option of declaring one wide-character version of the RE * functions as well as the char versions. To do that, define __REG_WIDE_T to * the type of wide characters (unfortunately, there is no consensus that * wchar_t is suitable) and __REG_WIDE_COMPILE and __REG_WIDE_EXEC to the * names to be used for the compile and execute functions (suggestion: * re_Xcomp and re_Xexec, where X is a letter suggestive of the wide type, * e.g. re_ucomp and re_uexec for Unicode). For cranky old compilers, it may * be necessary to do something like: * #define __REG_WIDE_COMPILE(a,b,c,d) re_Xcomp(a,b,c,d) * #define __REG_WIDE_EXEC(a,b,c,d,e,f,g) re_Xexec(a,b,c,d,e,f,g) * rather than just #defining the names as parameterless macros. * * For some specialized purposes, it may be desirable to suppress the * declarations of the "front end" functions, regcomp() and regexec(), or of * the char versions of the compile and execute functions. To suppress the * front-end functions, define __REG_NOFRONT. To suppress the char versions, * define __REG_NOCHAR. * * The right place to do those defines (and some others you may want, see * below) would be . If you don't have control of that file, the * right place to add your own defines to this file is marked below. This is * normally done automatically, by the makefile and regmkhdr, based on the * contents of regcustom.h. */ /* * voodoo for C++ */ #ifdef __cplusplus extern "C" { #endif /* * Add your own defines, if needed, here. */ /* * Location where a chunk of regcustom.h is automatically spliced into this * file (working from its prototype, regproto.h). */ /* --- begin --- */ /* ensure certain things don't sneak in from system headers */ #ifdef __REG_WIDE_T #undef __REG_WIDE_T #endif #ifdef __REG_WIDE_COMPILE #undef __REG_WIDE_COMPILE #endif #ifdef __REG_WIDE_EXEC #undef __REG_WIDE_EXEC #endif #ifdef __REG_REGOFF_T #undef __REG_REGOFF_T #endif #ifdef __REG_NOFRONT #undef __REG_NOFRONT #endif #ifdef __REG_NOCHAR #undef __REG_NOCHAR #endif /* interface types */ #define __REG_WIDE_T Tcl_UniChar #define __REG_REGOFF_T long /* not really right, but good enough... */ /* names and declarations */ #define __REG_WIDE_COMPILE TclReComp #define __REG_WIDE_EXEC TclReExec #define __REG_NOFRONT /* don't want regcomp() and regexec() */ #define __REG_NOCHAR /* or the char versions */ #define regfree TclReFree #define regerror TclReError /* --- end --- */ /* * interface types etc. */ /* * regoff_t has to be large enough to hold either off_t or ssize_t, and must * be signed; it's only a guess that long is suitable, so we offer * an override. */ #ifdef __REG_REGOFF_T typedef __REG_REGOFF_T regoff_t; #else typedef long regoff_t; #endif /* * other interface types */ /* the biggie, a compiled RE (or rather, a front end to same) */ typedef struct { int re_magic; /* magic number */ size_t re_nsub; /* number of subexpressions */ long re_info; /* information about RE */ #define REG_UBACKREF 000001 #define REG_ULOOKAHEAD 000002 #define REG_UBOUNDS 000004 #define REG_UBRACES 000010 #define REG_UBSALNUM 000020 #define REG_UPBOTCH 000040 #define REG_UBBS 000100 #define REG_UNONPOSIX 000200 #define REG_UUNSPEC 000400 #define REG_UUNPORT 001000 #define REG_ULOCALE 002000 #define REG_UEMPTYMATCH 004000 #define REG_UIMPOSSIBLE 010000 #define REG_USHORTEST 020000 int re_csize; /* sizeof(character) */ char *re_endp; /* backward compatibility kludge */ /* the rest is opaque pointers to hidden innards */ char *re_guts; /* `char *' is more portable than `void *' */ char *re_fns; } regex_t; /* result reporting (may acquire more fields later) */ typedef struct { regoff_t rm_so; /* start of substring */ regoff_t rm_eo; /* end of substring */ } regmatch_t; /* supplementary control and reporting */ typedef struct { regmatch_t rm_extend; /* see REG_EXPECT */ } rm_detail_t; /* * compilation ^ #ifndef __REG_NOCHAR ^ int re_comp(regex_t *, const char *, size_t, int); ^ #endif ^ #ifndef __REG_NOFRONT ^ int regcomp(regex_t *, const char *, int); ^ #endif ^ #ifdef __REG_WIDE_T ^ int __REG_WIDE_COMPILE(regex_t *, const __REG_WIDE_T *, size_t, int); ^ #endif */ #define REG_BASIC 000000 /* BREs (convenience) */ #define REG_EXTENDED 000001 /* EREs */ #define REG_ADVF 000002 /* advanced features in EREs */ #define REG_ADVANCED 000003 /* AREs (which are also EREs) */ #define REG_QUOTE 000004 /* no special characters, none */ #define REG_NOSPEC REG_QUOTE /* historical synonym */ #define REG_ICASE 000010 /* ignore case */ #define REG_NOSUB 000020 /* don't care about subexpressions */ #define REG_EXPANDED 000040 /* expanded format, white space & comments */ #define REG_NLSTOP 000100 /* \n doesn't match . or [^ ] */ #define REG_NLANCH 000200 /* ^ matches after \n, $ before */ #define REG_NEWLINE 000300 /* newlines are line terminators */ #define REG_PEND 000400 /* ugh -- backward-compatibility hack */ #define REG_EXPECT 001000 /* report details on partial/limited matches */ #define REG_BOSONLY 002000 /* temporary kludge for BOS-only matches */ #define REG_DUMP 004000 /* none of your business :-) */ #define REG_FAKE 010000 /* none of your business :-) */ #define REG_PROGRESS 020000 /* none of your business :-) */ /* * execution ^ #ifndef __REG_NOCHAR ^ int re_exec(regex_t *, const char *, size_t, ^ rm_detail_t *, size_t, regmatch_t [], int); ^ #endif ^ #ifndef __REG_NOFRONT ^ int regexec(regex_t *, const char *, size_t, regmatch_t [], int); ^ #endif ^ #ifdef __REG_WIDE_T ^ int __REG_WIDE_EXEC(regex_t *, const __REG_WIDE_T *, size_t, ^ rm_detail_t *, size_t, regmatch_t [], int); ^ #endif */ #define REG_NOTBOL 0001 /* BOS is not BOL */ #define REG_NOTEOL 0002 /* EOS is not EOL */ #define REG_STARTEND 0004 /* backward compatibility kludge */ #define REG_FTRACE 0010 /* none of your business */ #define REG_MTRACE 0020 /* none of your business */ #define REG_SMALL 0040 /* none of your business */ /* * misc generics (may be more functions here eventually) ^ void regfree(regex_t *); */ /* * error reporting * Be careful if modifying the list of error codes -- the table used by * regerror() is generated automatically from this file! * * Note that there is no wide-char variant of regerror at this time; what kind * of character is used for error reports is independent of what kind is used * in matching. * ^ extern size_t regerror(int, const regex_t *, char *, size_t); */ #define REG_OKAY 0 /* no errors detected */ #define REG_NOMATCH 1 /* failed to match */ #define REG_BADPAT 2 /* invalid regexp */ #define REG_ECOLLATE 3 /* invalid collating element */ #define REG_ECTYPE 4 /* invalid character class */ #define REG_EESCAPE 5 /* invalid escape \ sequence */ #define REG_ESUBREG 6 /* invalid backreference number */ #define REG_EBRACK 7 /* brackets [] not balanced */ #define REG_EPAREN 8 /* parentheses () not balanced */ #define REG_EBRACE 9 /* braces {} not balanced */ #define REG_BADBR 10 /* invalid repetition count(s) */ #define REG_ERANGE 11 /* invalid character range */ #define REG_ESPACE 12 /* out of memory */ #define REG_BADRPT 13 /* quantifier operand invalid */ #define REG_ASSERT 15 /* "can't happen" -- you found a bug */ #define REG_INVARG 16 /* invalid argument to regex function */ #define REG_MIXED 17 /* character widths of regex and string differ */ #define REG_BADOPT 18 /* invalid embedded option */ #define REG_ETOOBIG 19 /* regular expression is too complex */ #define REG_ECOLORS 20 /* too many colors */ /* two specials for debugging and testing */ #define REG_ATOI 101 /* convert error-code name to number */ #define REG_ITOA 102 /* convert error-code number to name */ /* * the prototypes, as possibly munched by regfwd */ /* =====^!^===== begin forwards =====^!^===== */ /* automatically gathered by fwd; do not hand-edit */ /* === regproto.h === */ #ifndef __REG_NOCHAR int re_comp(regex_t *, const char *, size_t, int); #endif #ifndef __REG_NOFRONT int regcomp(regex_t *, const char *, int); #endif #ifdef __REG_WIDE_T MODULE_SCOPE int __REG_WIDE_COMPILE(regex_t *, const __REG_WIDE_T *, size_t, int); #endif #ifndef __REG_NOCHAR int re_exec(regex_t *, const char *, size_t, rm_detail_t *, size_t, regmatch_t [], int); #endif #ifndef __REG_NOFRONT int regexec(regex_t *, const char *, size_t, regmatch_t [], int); #endif #ifdef __REG_WIDE_T MODULE_SCOPE int __REG_WIDE_EXEC(regex_t *, const __REG_WIDE_T *, size_t, rm_detail_t *, size_t, regmatch_t [], int); #endif MODULE_SCOPE void regfree(regex_t *); MODULE_SCOPE size_t regerror(int, const regex_t *, char *, size_t); /* automatically gathered by fwd; do not hand-edit */ /* =====^!^===== end forwards =====^!^===== */ /* * more C++ voodoo */ #ifdef __cplusplus } #endif #endif /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclCmdAH.c0000644000175000017500000022037012664052331014762 0ustar sergeisergei/* * tclCmdAH.c -- * * This file contains the top-level command routines for most of the Tcl * built-in commands whose names begin with the letters A to H. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include /* * The state structure used by [foreach]. Note that the actual structure has * all its working arrays appended afterwards so they can be allocated and * freed in a single step. */ struct ForeachState { Tcl_Obj *bodyPtr; /* The script body of the command. */ int bodyIdx; /* The argument index of the body. */ int j, maxj; /* Number of loop iterations. */ int numLists; /* Count of value lists. */ int *index; /* Array of value list indices. */ int *varcList; /* # loop variables per list. */ Tcl_Obj ***varvList; /* Array of var name lists. */ Tcl_Obj **vCopyList; /* Copies of var name list arguments. */ int *argcList; /* Array of value list sizes. */ Tcl_Obj ***argvList; /* Array of value lists. */ Tcl_Obj **aCopyList; /* Copies of value list arguments. */ Tcl_Obj *resultList; /* List of result values from the loop body, * or NULL if we're not collecting them * ([lmap] vs [foreach]). */ }; /* * Prototypes for local procedures defined in this file: */ static int CheckAccess(Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode); static int EncodingDirsObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static inline int ForeachAssignments(Tcl_Interp *interp, struct ForeachState *statePtr); static inline void ForeachCleanup(Tcl_Interp *interp, struct ForeachState *statePtr); static int GetStatBuf(Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_FSStatProc *statProc, Tcl_StatBuf *statPtr); static const char * GetTypeFromMode(int mode); static int StoreStatData(Tcl_Interp *interp, Tcl_Obj *varName, Tcl_StatBuf *statPtr); static inline int EachloopCmd(Tcl_Interp *interp, int collect, int objc, Tcl_Obj *const objv[]); static Tcl_NRPostProc CatchObjCmdCallback; static Tcl_NRPostProc ExprCallback; static Tcl_NRPostProc ForSetupCallback; static Tcl_NRPostProc ForCondCallback; static Tcl_NRPostProc ForNextCallback; static Tcl_NRPostProc ForPostNextCallback; static Tcl_NRPostProc ForeachLoopStep; static Tcl_NRPostProc EvalCmdErrMsg; static Tcl_ObjCmdProc BadFileSubcommand; static Tcl_ObjCmdProc FileAttrAccessTimeCmd; static Tcl_ObjCmdProc FileAttrIsDirectoryCmd; static Tcl_ObjCmdProc FileAttrIsExecutableCmd; static Tcl_ObjCmdProc FileAttrIsExistingCmd; static Tcl_ObjCmdProc FileAttrIsFileCmd; static Tcl_ObjCmdProc FileAttrIsOwnedCmd; static Tcl_ObjCmdProc FileAttrIsReadableCmd; static Tcl_ObjCmdProc FileAttrIsWritableCmd; static Tcl_ObjCmdProc FileAttrLinkStatCmd; static Tcl_ObjCmdProc FileAttrModifyTimeCmd; static Tcl_ObjCmdProc FileAttrSizeCmd; static Tcl_ObjCmdProc FileAttrStatCmd; static Tcl_ObjCmdProc FileAttrTypeCmd; static Tcl_ObjCmdProc FilesystemSeparatorCmd; static Tcl_ObjCmdProc FilesystemVolumesCmd; static Tcl_ObjCmdProc PathDirNameCmd; static Tcl_ObjCmdProc PathExtensionCmd; static Tcl_ObjCmdProc PathFilesystemCmd; static Tcl_ObjCmdProc PathJoinCmd; static Tcl_ObjCmdProc PathNativeNameCmd; static Tcl_ObjCmdProc PathNormalizeCmd; static Tcl_ObjCmdProc PathRootNameCmd; static Tcl_ObjCmdProc PathSplitCmd; static Tcl_ObjCmdProc PathTailCmd; static Tcl_ObjCmdProc PathTypeCmd; /* *---------------------------------------------------------------------- * * Tcl_BreakObjCmd -- * * This procedure is invoked to process the "break" Tcl command. See the * user documentation for details on what it does. * * With the bytecode compiler, this procedure is only called when a * command name is computed at runtime, and is "break" or the name to * which "break" was renamed: e.g., "set z break; $z" * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_BreakObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } return TCL_BREAK; } /* *---------------------------------------------------------------------- * * Tcl_CaseObjCmd -- * * This procedure is invoked to process the "case" Tcl command. See the * user documentation for details on what it does. THIS COMMAND IS * OBSOLETE AND DEPRECATED. SLATED FOR REMOVAL IN TCL 9.0. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_CaseObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register int i; int body, result, caseObjc; const char *stringPtr, *arg; Tcl_Obj *const *caseObjv; Tcl_Obj *armPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "string ?in? ?pattern body ...? ?default body?"); return TCL_ERROR; } stringPtr = TclGetString(objv[1]); body = -1; arg = TclGetString(objv[2]); if (strcmp(arg, "in") == 0) { i = 3; } else { i = 2; } caseObjc = objc - i; caseObjv = objv + i; /* * If all of the pattern/command pairs are lumped into a single argument, * split them out again. */ if (caseObjc == 1) { Tcl_Obj **newObjv; TclListObjGetElements(interp, caseObjv[0], &caseObjc, &newObjv); caseObjv = newObjv; } for (i = 0; i < caseObjc; i += 2) { int patObjc, j; const char **patObjv; const char *pat, *p; if (i == caseObjc-1) { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewStringObj( "extra case pattern with no body", -1)); return TCL_ERROR; } /* * Check for special case of single pattern (no list) with no * backslash sequences. */ pat = TclGetString(caseObjv[i]); for (p = pat; *p != '\0'; p++) { if (TclIsSpaceProc(*p) || (*p == '\\')) { break; } } if (*p == '\0') { if ((*pat == 'd') && (strcmp(pat, "default") == 0)) { body = i + 1; } if (Tcl_StringMatch(stringPtr, pat)) { body = i + 1; goto match; } continue; } /* * Break up pattern lists, then check each of the patterns in the * list. */ result = Tcl_SplitList(interp, pat, &patObjc, &patObjv); if (result != TCL_OK) { return result; } for (j = 0; j < patObjc; j++) { if (Tcl_StringMatch(stringPtr, patObjv[j])) { body = i + 1; break; } } ckfree(patObjv); if (j < patObjc) { break; } } match: if (body != -1) { armPtr = caseObjv[body - 1]; result = Tcl_EvalObjEx(interp, caseObjv[body], 0); if (result == TCL_ERROR) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%.50s\" arm line %d)", TclGetString(armPtr), Tcl_GetErrorLine(interp))); } return result; } /* * Nothing matched: return nothing. */ return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_CatchObjCmd -- * * This object-based procedure is invoked to process the "catch" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_CatchObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRCatchObjCmd, dummy, objc, objv); } int TclNRCatchObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *varNamePtr = NULL; Tcl_Obj *optionVarNamePtr = NULL; Interp *iPtr = (Interp *) interp; if ((objc < 2) || (objc > 4)) { Tcl_WrongNumArgs(interp, 1, objv, "script ?resultVarName? ?optionVarName?"); return TCL_ERROR; } if (objc >= 3) { varNamePtr = objv[2]; } if (objc == 4) { optionVarNamePtr = objv[3]; } TclNRAddCallback(interp, CatchObjCmdCallback, INT2PTR(objc), varNamePtr, optionVarNamePtr, NULL); /* * TIP #280. Make invoking context available to caught script. */ return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1); } static int CatchObjCmdCallback( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; int objc = PTR2INT(data[0]); Tcl_Obj *varNamePtr = data[1]; Tcl_Obj *optionVarNamePtr = data[2]; int rewind = iPtr->execEnvPtr->rewind; /* * We disable catch in interpreters where the limit has been exceeded. */ if (rewind || Tcl_LimitExceeded(interp)) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"catch\" body line %d)", Tcl_GetErrorLine(interp))); return TCL_ERROR; } if (objc >= 3) { if (NULL == Tcl_ObjSetVar2(interp, varNamePtr, NULL, Tcl_GetObjResult(interp), TCL_LEAVE_ERR_MSG)) { return TCL_ERROR; } } if (objc == 4) { Tcl_Obj *options = Tcl_GetReturnOptions(interp, result); if (NULL == Tcl_ObjSetVar2(interp, optionVarNamePtr, NULL, options, TCL_LEAVE_ERR_MSG)) { /* Do not decrRefCount 'options', it was already done by * Tcl_ObjSetVar2 */ return TCL_ERROR; } } Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewIntObj(result)); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_CdObjCmd -- * * This procedure is invoked to process the "cd" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_CdObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *dir; int result; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?dirName?"); return TCL_ERROR; } if (objc == 2) { dir = objv[1]; } else { TclNewLiteralStringObj(dir, "~"); Tcl_IncrRefCount(dir); } if (Tcl_FSConvertToPathType(interp, dir) != TCL_OK) { result = TCL_ERROR; } else { result = Tcl_FSChdir(dir); if (result != TCL_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't change working directory to \"%s\": %s", TclGetString(dir), Tcl_PosixError(interp))); result = TCL_ERROR; } } if (objc != 2) { Tcl_DecrRefCount(dir); } return result; } /* *---------------------------------------------------------------------- * * Tcl_ConcatObjCmd -- * * This object-based procedure is invoked to process the "concat" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ConcatObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc >= 2) { Tcl_SetObjResult(interp, Tcl_ConcatObj(objc-1, objv+1)); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ContinueObjCmd -- * * This procedure is invoked to process the "continue" Tcl command. See * the user documentation for details on what it does. * * With the bytecode compiler, this procedure is only called when a * command name is computed at runtime, and is "continue" or the name to * which "continue" was renamed: e.g., "set z continue; $z" * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ContinueObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } return TCL_CONTINUE; } /* *---------------------------------------------------------------------- * * Tcl_EncodingObjCmd -- * * This command manipulates encodings. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_EncodingObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int index; static const char *const optionStrings[] = { "convertfrom", "convertto", "dirs", "names", "system", NULL }; enum options { ENC_CONVERTFROM, ENC_CONVERTTO, ENC_DIRS, ENC_NAMES, ENC_SYSTEM }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { case ENC_CONVERTTO: case ENC_CONVERTFROM: { Tcl_Obj *data; Tcl_DString ds; Tcl_Encoding encoding; int length; const char *stringPtr; if (objc == 3) { encoding = Tcl_GetEncoding(interp, NULL); data = objv[2]; } else if (objc == 4) { if (Tcl_GetEncodingFromObj(interp, objv[2], &encoding) != TCL_OK) { return TCL_ERROR; } data = objv[3]; } else { Tcl_WrongNumArgs(interp, 2, objv, "?encoding? data"); return TCL_ERROR; } if ((enum options) index == ENC_CONVERTFROM) { /* * Treat the string as binary data. */ stringPtr = (char *) Tcl_GetByteArrayFromObj(data, &length); Tcl_ExternalToUtfDString(encoding, stringPtr, length, &ds); /* * Note that we cannot use Tcl_DStringResult here because it will * truncate the string at the first null byte. */ Tcl_SetObjResult(interp, TclDStringToObj(&ds)); } else { /* * Store the result as binary data. */ stringPtr = TclGetStringFromObj(data, &length); Tcl_UtfToExternalDString(encoding, stringPtr, length, &ds); Tcl_SetObjResult(interp, Tcl_NewByteArrayObj( (unsigned char *) Tcl_DStringValue(&ds), Tcl_DStringLength(&ds))); Tcl_DStringFree(&ds); } Tcl_FreeEncoding(encoding); break; } case ENC_DIRS: return EncodingDirsObjCmd(dummy, interp, objc, objv); case ENC_NAMES: if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } Tcl_GetEncodingNames(interp); break; case ENC_SYSTEM: if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?encoding?"); return TCL_ERROR; } if (objc == 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( Tcl_GetEncodingName(NULL), -1)); } else { return Tcl_SetSystemEncoding(interp, TclGetString(objv[2])); } break; } return TCL_OK; } /* *---------------------------------------------------------------------- * * EncodingDirsObjCmd -- * * This command manipulates the encoding search path. * * Results: * A standard Tcl result. * * Side effects: * Can set the encoding search path. * *---------------------------------------------------------------------- */ int EncodingDirsObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *dirListObj; if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?dirList?"); return TCL_ERROR; } if (objc == 2) { Tcl_SetObjResult(interp, Tcl_GetEncodingSearchPath()); return TCL_OK; } dirListObj = objv[2]; if (Tcl_SetEncodingSearchPath(dirListObj) == TCL_ERROR) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected directory list but got \"%s\"", TclGetString(dirListObj))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "ENCODING", "BADPATH", NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, dirListObj); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ErrorObjCmd -- * * This procedure is invoked to process the "error" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ErrorObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *options, *optName; if ((objc < 2) || (objc > 4)) { Tcl_WrongNumArgs(interp, 1, objv, "message ?errorInfo? ?errorCode?"); return TCL_ERROR; } TclNewLiteralStringObj(options, "-code error -level 0"); if (objc >= 3) { /* Process the optional info argument */ TclNewLiteralStringObj(optName, "-errorinfo"); Tcl_ListObjAppendElement(NULL, options, optName); Tcl_ListObjAppendElement(NULL, options, objv[2]); } if (objc >= 4) { /* Process the optional code argument */ TclNewLiteralStringObj(optName, "-errorcode"); Tcl_ListObjAppendElement(NULL, options, optName); Tcl_ListObjAppendElement(NULL, options, objv[3]); } Tcl_SetObjResult(interp, objv[1]); return Tcl_SetReturnOptions(interp, options); } /* *---------------------------------------------------------------------- * * Tcl_EvalObjCmd -- * * This object-based procedure is invoked to process the "eval" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int EvalCmdErrMsg( ClientData data[], Tcl_Interp *interp, int result) { if (result == TCL_ERROR) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"eval\" body line %d)", Tcl_GetErrorLine(interp))); } return result; } int Tcl_EvalObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNREvalObjCmd, dummy, objc, objv); } int TclNREvalObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { register Tcl_Obj *objPtr; Interp *iPtr = (Interp *) interp; CmdFrame *invoker = NULL; int word = 0; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "arg ?arg ...?"); return TCL_ERROR; } if (objc == 2) { /* * TIP #280. Make argument location available to eval'd script. */ invoker = iPtr->cmdFramePtr; word = 1; objPtr = objv[1]; TclArgumentGet(interp, objPtr, &invoker, &word); } else { /* * More than one argument: concatenate them together with spaces * between, then evaluate the result. Tcl_EvalObjEx will delete the * object when it decrements its refcount after eval'ing it. * * TIP #280. Make invoking context available to eval'd script, done * with the default values. */ objPtr = Tcl_ConcatObj(objc-1, objv+1); } TclNRAddCallback(interp, EvalCmdErrMsg, NULL, NULL, NULL, NULL); return TclNREvalObjEx(interp, objPtr, 0, invoker, word); } /* *---------------------------------------------------------------------- * * Tcl_ExitObjCmd -- * * This procedure is invoked to process the "exit" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ExitObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int value; if ((objc != 1) && (objc != 2)) { Tcl_WrongNumArgs(interp, 1, objv, "?returnCode?"); return TCL_ERROR; } if (objc == 1) { value = 0; } else if (Tcl_GetIntFromObj(interp, objv[1], &value) != TCL_OK) { return TCL_ERROR; } Tcl_Exit(value); /*NOTREACHED*/ return TCL_OK; /* Better not ever reach this! */ } /* *---------------------------------------------------------------------- * * Tcl_ExprObjCmd -- * * This object-based procedure is invoked to process the "expr" Tcl * command. See the user documentation for details on what it does. * * With the bytecode compiler, this procedure is called in two * circumstances: 1) to execute expr commands that are too complicated or * too unsafe to try compiling directly into an inline sequence of * instructions, and 2) to execute commands where the command name is * computed at runtime and is "expr" or the name to which "expr" was * renamed (e.g., "set z expr; $z 2+3") * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ExprObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRExprObjCmd, dummy, objc, objv); } int TclNRExprObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *resultPtr, *objPtr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "arg ?arg ...?"); return TCL_ERROR; } TclNewObj(resultPtr); Tcl_IncrRefCount(resultPtr); if (objc == 2) { objPtr = objv[1]; TclNRAddCallback(interp, ExprCallback, resultPtr, NULL, NULL, NULL); } else { objPtr = Tcl_ConcatObj(objc-1, objv+1); TclNRAddCallback(interp, ExprCallback, resultPtr, objPtr, NULL, NULL); } return Tcl_NRExprObj(interp, objPtr, resultPtr); } static int ExprCallback( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj *resultPtr = data[0]; Tcl_Obj *objPtr = data[1]; if (objPtr != NULL) { Tcl_DecrRefCount(objPtr); } if (result == TCL_OK) { Tcl_SetObjResult(interp, resultPtr); } Tcl_DecrRefCount(resultPtr); return result; } /* *---------------------------------------------------------------------- * * TclInitFileCmd -- * * This function builds the "file" Tcl command ensemble. See the user * documentation for details on what that ensemble does. * * PLEASE NOTE THAT THIS FAILS WITH FILENAMES AND PATHS WITH EMBEDDED * NULLS. With the object-based Tcl_FS APIs, the above NOTE may no longer * be true. In any case this assertion should be tested. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ Tcl_Command TclInitFileCmd( Tcl_Interp *interp) { /* * Note that most subcommands are unsafe because either they manipulate * the native filesystem or because they reveal information about the * native filesystem. */ static const EnsembleImplMap initMap[] = { {"atime", FileAttrAccessTimeCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"attributes", TclFileAttrsCmd, NULL, NULL, NULL, 0}, {"channels", TclChannelNamesCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"copy", TclFileCopyCmd, NULL, NULL, NULL, 0}, {"delete", TclFileDeleteCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"dirname", PathDirNameCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"executable", FileAttrIsExecutableCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"exists", FileAttrIsExistingCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"extension", PathExtensionCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"isdirectory", FileAttrIsDirectoryCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"isfile", FileAttrIsFileCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"join", PathJoinCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0}, {"link", TclFileLinkCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"lstat", FileAttrLinkStatCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"mtime", FileAttrModifyTimeCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"mkdir", TclFileMakeDirsCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"nativename", PathNativeNameCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"normalize", PathNormalizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"owned", FileAttrIsOwnedCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"pathtype", PathTypeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"readable", FileAttrIsReadableCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"readlink", TclFileReadLinkCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"rename", TclFileRenameCmd, NULL, NULL, NULL, 0}, {"rootname", PathRootNameCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"separator", FilesystemSeparatorCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"size", FileAttrSizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"split", PathSplitCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"stat", FileAttrStatCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"system", PathFilesystemCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"tail", PathTailCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"tempfile", TclFileTemporaryCmd, TclCompileBasic0To2ArgCmd, NULL, NULL, 0}, {"type", FileAttrTypeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"volumes", FilesystemVolumesCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"writable", FileAttrIsWritableCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; return TclMakeEnsemble(interp, "file", initMap); } /* *---------------------------------------------------------------------- * * TclMakeFileCommandSafe -- * * This function hides the unsafe subcommands of the "file" Tcl command * ensemble. It must only be called from TclHideUnsafeCommands. * * Results: * A standard Tcl result. * * Side effects: * Adds commands to the table of hidden commands. * *---------------------------------------------------------------------- */ int TclMakeFileCommandSafe( Tcl_Interp *interp) { static const struct { const char *cmdName; int unsafe; } unsafeInfo[] = { {"atime", 1}, {"attributes", 1}, {"channels", 0}, {"copy", 1}, {"delete", 1}, {"dirname", 1}, {"executable", 1}, {"exists", 1}, {"extension", 1}, {"isdirectory", 1}, {"isfile", 1}, {"join", 0}, {"link", 1}, {"lstat", 1}, {"mtime", 1}, {"mkdir", 1}, {"nativename", 1}, {"normalize", 1}, {"owned", 1}, {"pathtype", 0}, {"readable", 1}, {"readlink", 1}, {"rename", 1}, {"rootname", 1}, {"separator", 0}, {"size", 1}, {"split", 0}, {"stat", 1}, {"system", 0}, {"tail", 1}, {"tempfile", 1}, {"type", 1}, {"volumes", 1}, {"writable", 1}, {NULL, 0} }; int i; Tcl_DString oldBuf, newBuf; Tcl_DStringInit(&oldBuf); TclDStringAppendLiteral(&oldBuf, "::tcl::file::"); Tcl_DStringInit(&newBuf); TclDStringAppendLiteral(&newBuf, "tcl:file:"); for (i=0 ; unsafeInfo[i].cmdName != NULL ; i++) { if (unsafeInfo[i].unsafe) { const char *oldName, *newName; Tcl_DStringSetLength(&oldBuf, 13); oldName = Tcl_DStringAppend(&oldBuf, unsafeInfo[i].cmdName, -1); Tcl_DStringSetLength(&newBuf, 9); newName = Tcl_DStringAppend(&newBuf, unsafeInfo[i].cmdName, -1); if (TclRenameCommand(interp, oldName, "___tmp") != TCL_OK || Tcl_HideCommand(interp, "___tmp", newName) != TCL_OK) { Tcl_Panic("problem making 'file %s' safe: %s", unsafeInfo[i].cmdName, Tcl_GetString(Tcl_GetObjResult(interp))); } Tcl_CreateObjCommand(interp, oldName, BadFileSubcommand, (ClientData) unsafeInfo[i].cmdName, NULL); } } Tcl_DStringFree(&oldBuf); Tcl_DStringFree(&newBuf); /* * Ugh. The [file] command is now actually safe, but it is assumed by * scripts that it is not, which messes up security policies. [Bug * 3211758] */ if (Tcl_HideCommand(interp, "file", "file") != TCL_OK) { Tcl_Panic("problem making 'file' safe: %s", Tcl_GetString(Tcl_GetObjResult(interp))); } return TCL_OK; } /* *---------------------------------------------------------------------- * * BadFileSubcommand -- * * Command used to act as a backstop implementation when subcommands of * "file" are unsafe (the real implementations of the subcommands are * hidden). The clientData is always the full official subcommand name. * * Results: * A standard Tcl result (always a TCL_ERROR). * * Side effects: * None. * *---------------------------------------------------------------------- */ static int BadFileSubcommand( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { const char *subcommandName = (const char *) clientData; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "not allowed to invoke subcommand %s of file", subcommandName)); Tcl_SetErrorCode(interp, "TCL", "SAFE", "SUBCOMMAND", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * FileAttrAccessTimeCmd -- * * This function is invoked to process the "file atime" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * May update the access time on the file, if requested by the user. * *---------------------------------------------------------------------- */ static int FileAttrAccessTimeCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; struct utimbuf tval; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "name ?time?"); return TCL_ERROR; } if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) { return TCL_ERROR; } if (objc == 3) { /* * Need separate variable for reading longs from an object on 64-bit * platforms. [Bug 698146] */ long newTime; if (TclGetLongFromObj(interp, objv[2], &newTime) != TCL_OK) { return TCL_ERROR; } tval.actime = newTime; tval.modtime = buf.st_mtime; if (Tcl_FSUtime(objv[1], &tval) != 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not set access time for file \"%s\": %s", TclGetString(objv[1]), Tcl_PosixError(interp))); return TCL_ERROR; } /* * Do another stat to ensure that the we return the new recognized * atime - hopefully the same as the one we sent in. However, fs's * like FAT don't even know what atime is. */ if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) { return TCL_ERROR; } } Tcl_SetObjResult(interp, Tcl_NewLongObj((long) buf.st_atime)); return TCL_OK; } /* *---------------------------------------------------------------------- * * FileAttrModifyTimeCmd -- * * This function is invoked to process the "file mtime" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * May update the modification time on the file, if requested by the * user. * *---------------------------------------------------------------------- */ static int FileAttrModifyTimeCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; struct utimbuf tval; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "name ?time?"); return TCL_ERROR; } if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) { return TCL_ERROR; } if (objc == 3) { /* * Need separate variable for reading longs from an object on 64-bit * platforms. [Bug 698146] */ long newTime; if (TclGetLongFromObj(interp, objv[2], &newTime) != TCL_OK) { return TCL_ERROR; } tval.actime = buf.st_atime; tval.modtime = newTime; if (Tcl_FSUtime(objv[1], &tval) != 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not set modification time for file \"%s\": %s", TclGetString(objv[1]), Tcl_PosixError(interp))); return TCL_ERROR; } /* * Do another stat to ensure that the we return the new recognized * mtime - hopefully the same as the one we sent in. */ if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) { return TCL_ERROR; } } Tcl_SetObjResult(interp, Tcl_NewLongObj((long) buf.st_mtime)); return TCL_OK; } /* *---------------------------------------------------------------------- * * FileAttrLinkStatCmd -- * * This function is invoked to process the "file lstat" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Writes to an array named by the user. * *---------------------------------------------------------------------- */ static int FileAttrLinkStatCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "name varName"); return TCL_ERROR; } if (GetStatBuf(interp, objv[1], Tcl_FSLstat, &buf) != TCL_OK) { return TCL_ERROR; } return StoreStatData(interp, objv[2], &buf); } /* *---------------------------------------------------------------------- * * FileAttrStatCmd -- * * This function is invoked to process the "file stat" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * Writes to an array named by the user. * *---------------------------------------------------------------------- */ static int FileAttrStatCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "name varName"); return TCL_ERROR; } if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) { return TCL_ERROR; } return StoreStatData(interp, objv[2], &buf); } /* *---------------------------------------------------------------------- * * FileAttrTypeCmd -- * * This function is invoked to process the "file type" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FileAttrTypeCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } if (GetStatBuf(interp, objv[1], Tcl_FSLstat, &buf) != TCL_OK) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewStringObj( GetTypeFromMode((unsigned short) buf.st_mode), -1)); return TCL_OK; } /* *---------------------------------------------------------------------- * * FileAttrSizeCmd -- * * This function is invoked to process the "file size" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FileAttrSizeCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } if (GetStatBuf(interp, objv[1], Tcl_FSStat, &buf) != TCL_OK) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) buf.st_size)); return TCL_OK; } /* *---------------------------------------------------------------------- * * FileAttrIsDirectoryCmd -- * * This function is invoked to process the "file isdirectory" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FileAttrIsDirectoryCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; int value = 0; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } if (GetStatBuf(NULL, objv[1], Tcl_FSStat, &buf) == TCL_OK) { value = S_ISDIR(buf.st_mode); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value)); return TCL_OK; } /* *---------------------------------------------------------------------- * * FileAttrIsExecutableCmd -- * * This function is invoked to process the "file executable" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FileAttrIsExecutableCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } return CheckAccess(interp, objv[1], X_OK); } /* *---------------------------------------------------------------------- * * FileAttrIsExistingCmd -- * * This function is invoked to process the "file exists" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FileAttrIsExistingCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } return CheckAccess(interp, objv[1], F_OK); } /* *---------------------------------------------------------------------- * * FileAttrIsFileCmd -- * * This function is invoked to process the "file isfile" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FileAttrIsFileCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; int value = 0; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } if (GetStatBuf(NULL, objv[1], Tcl_FSStat, &buf) == TCL_OK) { value = S_ISREG(buf.st_mode); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value)); return TCL_OK; } /* *---------------------------------------------------------------------- * * FileAttrIsOwnedCmd -- * * This function is invoked to process the "file owned" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FileAttrIsOwnedCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_StatBuf buf; int value = 0; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } if (GetStatBuf(NULL, objv[1], Tcl_FSStat, &buf) == TCL_OK) { /* * For Windows, there are no user ids associated with a file, so we * always return 1. * * TODO: use GetSecurityInfo to get the real owner of the file and * test for equivalence to the current user. */ #if defined(_WIN32) || defined(__CYGWIN__) value = 1; #else value = (geteuid() == buf.st_uid); #endif } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value)); return TCL_OK; } /* *---------------------------------------------------------------------- * * FileAttrIsReadableCmd -- * * This function is invoked to process the "file readable" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FileAttrIsReadableCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } return CheckAccess(interp, objv[1], R_OK); } /* *---------------------------------------------------------------------- * * FileAttrIsWritableCmd -- * * This function is invoked to process the "file writable" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FileAttrIsWritableCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } return CheckAccess(interp, objv[1], W_OK); } /* *---------------------------------------------------------------------- * * PathDirNameCmd -- * * This function is invoked to process the "file dirname" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PathDirNameCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *dirPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } dirPtr = TclPathPart(interp, objv[1], TCL_PATH_DIRNAME); if (dirPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, dirPtr); Tcl_DecrRefCount(dirPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * PathExtensionCmd -- * * This function is invoked to process the "file extension" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PathExtensionCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *dirPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } dirPtr = TclPathPart(interp, objv[1], TCL_PATH_EXTENSION); if (dirPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, dirPtr); Tcl_DecrRefCount(dirPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * PathRootNameCmd -- * * This function is invoked to process the "file root" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PathRootNameCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *dirPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } dirPtr = TclPathPart(interp, objv[1], TCL_PATH_ROOT); if (dirPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, dirPtr); Tcl_DecrRefCount(dirPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * PathTailCmd -- * * This function is invoked to process the "file tail" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PathTailCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *dirPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } dirPtr = TclPathPart(interp, objv[1], TCL_PATH_TAIL); if (dirPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, dirPtr); Tcl_DecrRefCount(dirPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * PathFilesystemCmd -- * * This function is invoked to process the "file system" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PathFilesystemCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *fsInfo; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } fsInfo = Tcl_FSFileSystemInfo(objv[1]); if (fsInfo == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("unrecognised path", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "FILESYSTEM", Tcl_GetString(objv[1]), NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, fsInfo); return TCL_OK; } /* *---------------------------------------------------------------------- * * PathJoinCmd -- * * This function is invoked to process the "file join" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PathJoinCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "name ?name ...?"); return TCL_ERROR; } Tcl_SetObjResult(interp, TclJoinPath(objc - 1, objv + 1)); return TCL_OK; } /* *---------------------------------------------------------------------- * * PathNativeNameCmd -- * * This function is invoked to process the "file nativename" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PathNativeNameCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_DString ds; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } if (Tcl_TranslateFileName(interp, TclGetString(objv[1]), &ds) == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, TclDStringToObj(&ds)); return TCL_OK; } /* *---------------------------------------------------------------------- * * PathNormalizeCmd -- * * This function is invoked to process the "file normalize" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PathNormalizeCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *fileName; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } fileName = Tcl_FSGetNormalizedPath(interp, objv[1]); if (fileName == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, fileName); return TCL_OK; } /* *---------------------------------------------------------------------- * * PathSplitCmd -- * * This function is invoked to process the "file split" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PathSplitCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *res; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } res = Tcl_FSSplitPath(objv[1], NULL); if (res == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not read \"%s\": no such file or directory", TclGetString(objv[1]))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PATHSPLIT", "NONESUCH", NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, res); return TCL_OK; } /* *---------------------------------------------------------------------- * * PathTypeCmd -- * * This function is invoked to process the "file pathtype" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int PathTypeCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *typeName; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "name"); return TCL_ERROR; } switch (Tcl_FSGetPathType(objv[1])) { case TCL_PATH_ABSOLUTE: TclNewLiteralStringObj(typeName, "absolute"); break; case TCL_PATH_RELATIVE: TclNewLiteralStringObj(typeName, "relative"); break; case TCL_PATH_VOLUME_RELATIVE: TclNewLiteralStringObj(typeName, "volumerelative"); break; default: /* Should be unreachable */ return TCL_OK; } Tcl_SetObjResult(interp, typeName); return TCL_OK; } /* *---------------------------------------------------------------------- * * FilesystemSeparatorCmd -- * * This function is invoked to process the "file separator" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FilesystemSeparatorCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc < 1 || objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?name?"); return TCL_ERROR; } if (objc == 1) { const char *separator = NULL; /* lint */ switch (tclPlatform) { case TCL_PLATFORM_UNIX: separator = "/"; break; case TCL_PLATFORM_WINDOWS: separator = "\\"; break; } Tcl_SetObjResult(interp, Tcl_NewStringObj(separator, 1)); } else { Tcl_Obj *separatorObj = Tcl_FSPathSeparator(objv[1]); if (separatorObj == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unrecognised path", -1)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "FILESYSTEM", Tcl_GetString(objv[1]), NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, separatorObj); } return TCL_OK; } /* *---------------------------------------------------------------------- * * FilesystemVolumesCmd -- * * This function is invoked to process the "file volumes" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int FilesystemVolumesCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_FSListVolumes()); return TCL_OK; } /* *--------------------------------------------------------------------------- * * CheckAccess -- * * Utility procedure used by Tcl_FileObjCmd() to query file attributes * available through the access() system call. * * Results: * Always returns TCL_OK. Sets interp's result to boolean true or false * depending on whether the file has the specified attribute. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static int CheckAccess( Tcl_Interp *interp, /* Interp for status return. Must not be * NULL. */ Tcl_Obj *pathPtr, /* Name of file to check. */ int mode) /* Attribute to check; passed as argument to * access(). */ { int value; if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) { value = 0; } else { value = (Tcl_FSAccess(pathPtr, mode) == 0); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value)); return TCL_OK; } /* *--------------------------------------------------------------------------- * * GetStatBuf -- * * Utility procedure used by Tcl_FileObjCmd() to query file attributes * available through the stat() or lstat() system call. * * Results: * The return value is TCL_OK if the specified file exists and can be * stat'ed, TCL_ERROR otherwise. If TCL_ERROR is returned, an error * message is left in interp's result. If TCL_OK is returned, *statPtr is * filled with information about the specified file. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static int GetStatBuf( Tcl_Interp *interp, /* Interp for error return. May be NULL. */ Tcl_Obj *pathPtr, /* Path name to examine. */ Tcl_FSStatProc *statProc, /* Either stat() or lstat() depending on * desired behavior. */ Tcl_StatBuf *statPtr) /* Filled with info about file obtained by * calling (*statProc)(). */ { int status; if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) { return TCL_ERROR; } status = statProc(pathPtr, statPtr); if (status < 0) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not read \"%s\": %s", TclGetString(pathPtr), Tcl_PosixError(interp))); } return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * StoreStatData -- * * This is a utility procedure that breaks out the fields of a "stat" * structure and stores them in textual form into the elements of an * associative array. * * Results: * Returns a standard Tcl return value. If an error occurs then a message * is left in interp's result. * * Side effects: * Elements of the associative array given by "varName" are modified. * *---------------------------------------------------------------------- */ static int StoreStatData( Tcl_Interp *interp, /* Interpreter for error reports. */ Tcl_Obj *varName, /* Name of associative array variable in which * to store stat results. */ Tcl_StatBuf *statPtr) /* Pointer to buffer containing stat data to * store in varName. */ { Tcl_Obj *field, *value; register unsigned short mode; /* * Assume Tcl_ObjSetVar2() does not keep a copy of the field name! * * Might be a better idea to call Tcl_SetVar2Ex() instead, except we want * to have an object (i.e. possibly cached) array variable name but a * string element name, so no API exists. Messy. */ #define STORE_ARY(fieldName, object) \ TclNewLiteralStringObj(field, fieldName); \ Tcl_IncrRefCount(field); \ value = (object); \ if (Tcl_ObjSetVar2(interp,varName,field,value,TCL_LEAVE_ERR_MSG)==NULL) { \ TclDecrRefCount(field); \ return TCL_ERROR; \ } \ TclDecrRefCount(field); /* * Watch out porters; the inode is meant to be an *unsigned* value, so the * cast might fail when there isn't a real arithmetic 'long long' type... */ STORE_ARY("dev", Tcl_NewLongObj((long)statPtr->st_dev)); STORE_ARY("ino", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_ino)); STORE_ARY("nlink", Tcl_NewLongObj((long)statPtr->st_nlink)); STORE_ARY("uid", Tcl_NewLongObj((long)statPtr->st_uid)); STORE_ARY("gid", Tcl_NewLongObj((long)statPtr->st_gid)); STORE_ARY("size", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size)); #ifdef HAVE_STRUCT_STAT_ST_BLOCKS STORE_ARY("blocks", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks)); #endif #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE STORE_ARY("blksize", Tcl_NewLongObj((long)statPtr->st_blksize)); #endif STORE_ARY("atime", Tcl_NewLongObj((long)statPtr->st_atime)); STORE_ARY("mtime", Tcl_NewLongObj((long)statPtr->st_mtime)); STORE_ARY("ctime", Tcl_NewLongObj((long)statPtr->st_ctime)); mode = (unsigned short) statPtr->st_mode; STORE_ARY("mode", Tcl_NewIntObj(mode)); STORE_ARY("type", Tcl_NewStringObj(GetTypeFromMode(mode), -1)); #undef STORE_ARY return TCL_OK; } /* *---------------------------------------------------------------------- * * GetTypeFromMode -- * * Given a mode word, returns a string identifying the type of a file. * * Results: * A static text string giving the file type from mode. * * Side effects: * None. * *---------------------------------------------------------------------- */ static const char * GetTypeFromMode( int mode) { if (S_ISREG(mode)) { return "file"; } else if (S_ISDIR(mode)) { return "directory"; } else if (S_ISCHR(mode)) { return "characterSpecial"; } else if (S_ISBLK(mode)) { return "blockSpecial"; } else if (S_ISFIFO(mode)) { return "fifo"; #ifdef S_ISLNK } else if (S_ISLNK(mode)) { return "link"; #endif #ifdef S_ISSOCK } else if (S_ISSOCK(mode)) { return "socket"; #endif } return "unknown"; } /* *---------------------------------------------------------------------- * * Tcl_ForObjCmd -- * * This procedure is invoked to process the "for" Tcl command. See the * user documentation for details on what it does. * * With the bytecode compiler, this procedure is only called when a * command name is computed at runtime, and is "for" or the name to which * "for" was renamed: e.g., * "set z for; $z {set i 0} {$i<100} {incr i} {puts $i}" * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * * Notes: * This command is split into a lot of pieces so that it can avoid doing * reentrant TEBC calls. This makes things rather hard to follow, but * here's the plan: * * NR: ---------------_\ * Direct: Tcl_ForObjCmd -> TclNRForObjCmd * | * ForSetupCallback * | * [while] ------------> TclNRForIterCallback <---------. * | | * ForCondCallback | * | | * ForNextCallback ------------| * | | * ForPostNextCallback | * |____________________| * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ForObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRForObjCmd, dummy, objc, objv); } int TclNRForObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; ForIterData *iterPtr; if (objc != 5) { Tcl_WrongNumArgs(interp, 1, objv, "start test next command"); return TCL_ERROR; } TclSmallAllocEx(interp, sizeof(ForIterData), iterPtr); iterPtr->cond = objv[2]; iterPtr->body = objv[4]; iterPtr->next = objv[3]; iterPtr->msg = "\n (\"for\" body line %d)"; iterPtr->word = 4; TclNRAddCallback(interp, ForSetupCallback, iterPtr, NULL, NULL, NULL); /* * TIP #280. Make invoking context available to initial script. */ return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1); } static int ForSetupCallback( ClientData data[], Tcl_Interp *interp, int result) { ForIterData *iterPtr = data[0]; if (result != TCL_OK) { if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (\"for\" initial command)"); } TclSmallFreeEx(interp, iterPtr); return result; } TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL); return TCL_OK; } int TclNRForIterCallback( ClientData data[], Tcl_Interp *interp, int result) { ForIterData *iterPtr = data[0]; Tcl_Obj *boolObj; switch (result) { case TCL_OK: case TCL_CONTINUE: /* * We need to reset the result before evaluating the expression. * Otherwise, any error message will be appended to the result of the * last evaluation. */ Tcl_ResetResult(interp); TclNewObj(boolObj); TclNRAddCallback(interp, ForCondCallback, iterPtr, boolObj, NULL, NULL); return Tcl_NRExprObj(interp, iterPtr->cond, boolObj); case TCL_BREAK: result = TCL_OK; Tcl_ResetResult(interp); break; case TCL_ERROR: Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(iterPtr->msg, Tcl_GetErrorLine(interp))); } TclSmallFreeEx(interp, iterPtr); return result; } static int ForCondCallback( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; ForIterData *iterPtr = data[0]; Tcl_Obj *boolObj = data[1]; int value; if (result != TCL_OK) { Tcl_DecrRefCount(boolObj); TclSmallFreeEx(interp, iterPtr); return result; } else if (Tcl_GetBooleanFromObj(interp, boolObj, &value) != TCL_OK) { Tcl_DecrRefCount(boolObj); TclSmallFreeEx(interp, iterPtr); return TCL_ERROR; } Tcl_DecrRefCount(boolObj); if (value) { /* TIP #280. */ if (iterPtr->next) { TclNRAddCallback(interp, ForNextCallback, iterPtr, NULL, NULL, NULL); } else { TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL); } return TclNREvalObjEx(interp, iterPtr->body, 0, iPtr->cmdFramePtr, iterPtr->word); } TclSmallFreeEx(interp, iterPtr); return result; } static int ForNextCallback( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; ForIterData *iterPtr = data[0]; Tcl_Obj *next = iterPtr->next; if ((result == TCL_OK) || (result == TCL_CONTINUE)) { TclNRAddCallback(interp, ForPostNextCallback, iterPtr, NULL, NULL, NULL); /* * TIP #280. Make invoking context available to next script. */ return TclNREvalObjEx(interp, next, 0, iPtr->cmdFramePtr, 3); } TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL); return result; } static int ForPostNextCallback( ClientData data[], Tcl_Interp *interp, int result) { ForIterData *iterPtr = data[0]; if ((result != TCL_BREAK) && (result != TCL_OK)) { if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (\"for\" loop-end command)"); TclSmallFreeEx(interp, iterPtr); } return result; } TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL); return result; } /* *---------------------------------------------------------------------- * * Tcl_ForeachObjCmd, TclNRForeachCmd, EachloopCmd -- * * This object-based procedure is invoked to process the "foreach" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_ForeachObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRForeachCmd, dummy, objc, objv); } int TclNRForeachCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { return EachloopCmd(interp, TCL_EACH_KEEP_NONE, objc, objv); } int Tcl_LmapObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, TclNRLmapCmd, dummy, objc, objv); } int TclNRLmapCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { return EachloopCmd(interp, TCL_EACH_COLLECT, objc, objv); } static inline int EachloopCmd( Tcl_Interp *interp, /* Our context for variables and script * evaluation. */ int collect, /* Select collecting or accumulating mode * (TCL_EACH_*) */ int objc, /* The arguments being passed in... */ Tcl_Obj *const objv[]) { int numLists = (objc-2) / 2; register struct ForeachState *statePtr; int i, j, result; if (objc < 4 || (objc%2 != 0)) { Tcl_WrongNumArgs(interp, 1, objv, "varList list ?varList list ...? command"); return TCL_ERROR; } /* * Manage numList parallel value lists. * statePtr->argvList[i] is a value list counted by statePtr->argcList[i]; * statePtr->varvList[i] is the list of variables associated with the * value list; * statePtr->varcList[i] is the number of variables associated with the * value list; * statePtr->index[i] is the current pointer into the value list * statePtr->argvList[i]. * * The setting up of all of these pointers is moderately messy, but allows * the rest of this code to be simple and for us to use a single memory * allocation for better performance. */ statePtr = TclStackAlloc(interp, sizeof(struct ForeachState) + 3 * numLists * sizeof(int) + 2 * numLists * (sizeof(Tcl_Obj **) + sizeof(Tcl_Obj *))); memset(statePtr, 0, sizeof(struct ForeachState) + 3 * numLists * sizeof(int) + 2 * numLists * (sizeof(Tcl_Obj **) + sizeof(Tcl_Obj *))); statePtr->varvList = (Tcl_Obj ***) (statePtr + 1); statePtr->argvList = statePtr->varvList + numLists; statePtr->vCopyList = (Tcl_Obj **) (statePtr->argvList + numLists); statePtr->aCopyList = statePtr->vCopyList + numLists; statePtr->index = (int *) (statePtr->aCopyList + numLists); statePtr->varcList = statePtr->index + numLists; statePtr->argcList = statePtr->varcList + numLists; statePtr->numLists = numLists; statePtr->bodyPtr = objv[objc - 1]; statePtr->bodyIdx = objc - 1; if (collect == TCL_EACH_COLLECT) { statePtr->resultList = Tcl_NewListObj(0, NULL); } else { statePtr->resultList = NULL; } /* * Break up the value lists and variable lists into elements. */ for (i=0 ; ivCopyList[i] = TclListObjCopy(interp, objv[1+i*2]); if (statePtr->vCopyList[i] == NULL) { result = TCL_ERROR; goto done; } TclListObjGetElements(NULL, statePtr->vCopyList[i], &statePtr->varcList[i], &statePtr->varvList[i]); if (statePtr->varcList[i] < 1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s varlist is empty", (statePtr->resultList != NULL ? "lmap" : "foreach"))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", (statePtr->resultList != NULL ? "LMAP" : "FOREACH"), "NEEDVARS", NULL); result = TCL_ERROR; goto done; } statePtr->aCopyList[i] = TclListObjCopy(interp, objv[2+i*2]); if (statePtr->aCopyList[i] == NULL) { result = TCL_ERROR; goto done; } TclListObjGetElements(NULL, statePtr->aCopyList[i], &statePtr->argcList[i], &statePtr->argvList[i]); j = statePtr->argcList[i] / statePtr->varcList[i]; if ((statePtr->argcList[i] % statePtr->varcList[i]) != 0) { j++; } if (j > statePtr->maxj) { statePtr->maxj = j; } } /* * If there is any work to do, assign the variables and set things going * non-recursively. */ if (statePtr->maxj > 0) { result = ForeachAssignments(interp, statePtr); if (result == TCL_ERROR) { goto done; } TclNRAddCallback(interp, ForeachLoopStep, statePtr, NULL, NULL, NULL); return TclNREvalObjEx(interp, objv[objc-1], 0, ((Interp *) interp)->cmdFramePtr, objc-1); } /* * This cleanup stage is only used when an error occurs during setup or if * there is no work to do. */ result = TCL_OK; done: ForeachCleanup(interp, statePtr); return result; } /* * Post-body processing handler. */ static int ForeachLoopStep( ClientData data[], Tcl_Interp *interp, int result) { register struct ForeachState *statePtr = data[0]; /* * Process the result code from this run of the [foreach] body. Note that * this switch uses fallthroughs in several places. Maintainer aware! */ switch (result) { case TCL_CONTINUE: result = TCL_OK; break; case TCL_OK: if (statePtr->resultList != NULL) { Tcl_ListObjAppendElement(interp, statePtr->resultList, Tcl_GetObjResult(interp)); } break; case TCL_BREAK: result = TCL_OK; goto finish; case TCL_ERROR: Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%s\" body line %d)", (statePtr->resultList != NULL ? "lmap" : "foreach"), Tcl_GetErrorLine(interp))); default: goto done; } /* * Test if there is work still to be done. If so, do the next round of * variable assignments, reschedule ourselves and run the body again. */ if (statePtr->maxj > ++statePtr->j) { result = ForeachAssignments(interp, statePtr); if (result == TCL_ERROR) { goto done; } TclNRAddCallback(interp, ForeachLoopStep, statePtr, NULL, NULL, NULL); return TclNREvalObjEx(interp, statePtr->bodyPtr, 0, ((Interp *) interp)->cmdFramePtr, statePtr->bodyIdx); } /* * We're done. Tidy up our work space and finish off. */ finish: if (statePtr->resultList == NULL) { Tcl_ResetResult(interp); } else { Tcl_SetObjResult(interp, statePtr->resultList); statePtr->resultList = NULL; /* Don't clean it up */ } done: ForeachCleanup(interp, statePtr); return result; } /* * Factored out code to do the assignments in [foreach]. */ static inline int ForeachAssignments( Tcl_Interp *interp, struct ForeachState *statePtr) { int i, v, k; Tcl_Obj *valuePtr, *varValuePtr; for (i=0 ; inumLists ; i++) { for (v=0 ; vvarcList[i] ; v++) { k = statePtr->index[i]++; if (k < statePtr->argcList[i]) { valuePtr = statePtr->argvList[i][k]; } else { TclNewObj(valuePtr); /* Empty string */ } varValuePtr = Tcl_ObjSetVar2(interp, statePtr->varvList[i][v], NULL, valuePtr, TCL_LEAVE_ERR_MSG); if (varValuePtr == NULL) { Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (setting %s loop variable \"%s\")", (statePtr->resultList != NULL ? "lmap" : "foreach"), TclGetString(statePtr->varvList[i][v]))); return TCL_ERROR; } } } return TCL_OK; } /* * Factored out code for cleaning up the state of the foreach. */ static inline void ForeachCleanup( Tcl_Interp *interp, struct ForeachState *statePtr) { int i; for (i=0 ; inumLists ; i++) { if (statePtr->vCopyList[i]) { TclDecrRefCount(statePtr->vCopyList[i]); } if (statePtr->aCopyList[i]) { TclDecrRefCount(statePtr->aCopyList[i]); } } if (statePtr->resultList != NULL) { TclDecrRefCount(statePtr->resultList); } TclStackFree(interp, statePtr); } /* *---------------------------------------------------------------------- * * Tcl_FormatObjCmd -- * * This procedure is invoked to process the "format" Tcl command. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_FormatObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Obj *resultPtr; /* Where result is stored finally. */ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "formatString ?arg ...?"); return TCL_ERROR; } resultPtr = Tcl_Format(interp, TclGetString(objv[1]), objc-2, objv+2); if (resultPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/regexec.c0000644000175000017500000010622212663660065014774 0ustar sergeisergei/* * re_*exec and friends - match REs * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "regguts.h" /* * Lazy-DFA representation. */ struct arcp { /* "pointer" to an outarc */ struct sset *ss; color co; }; struct sset { /* state set */ unsigned *states; /* pointer to bitvector */ unsigned hash; /* hash of bitvector */ #define HASH(bv, nw) (((nw) == 1) ? *(bv) : hash(bv, nw)) #define HIT(h,bv,ss,nw) ((ss)->hash == (h) && ((nw) == 1 || \ memcmp(VS(bv), VS((ss)->states), (nw)*sizeof(unsigned)) == 0)) int flags; #define STARTER 01 /* the initial state set */ #define POSTSTATE 02 /* includes the goal state */ #define LOCKED 04 /* locked in cache */ #define NOPROGRESS 010 /* zero-progress state set */ struct arcp ins; /* chain of inarcs pointing here */ chr *lastseen; /* last entered on arrival here */ struct sset **outs; /* outarc vector indexed by color */ struct arcp *inchain; /* chain-pointer vector for outarcs */ }; struct dfa { int nssets; /* size of cache */ int nssused; /* how many entries occupied yet */ int nstates; /* number of states */ int ncolors; /* length of outarc and inchain vectors */ int wordsper; /* length of state-set bitvectors */ struct sset *ssets; /* state-set cache */ unsigned *statesarea; /* bitvector storage */ unsigned *work; /* pointer to work area within statesarea */ struct sset **outsarea; /* outarc-vector storage */ struct arcp *incarea; /* inchain storage */ struct cnfa *cnfa; struct colormap *cm; chr *lastpost; /* location of last cache-flushed success */ chr *lastnopr; /* location of last cache-flushed NOPROGRESS */ struct sset *search; /* replacement-search-pointer memory */ int cptsmalloced; /* were the areas individually malloced? */ char *mallocarea; /* self, or master malloced area, or NULL */ }; #define WORK 1 /* number of work bitvectors needed */ /* * Setup for non-malloc allocation for small cases. */ #define FEWSTATES 20 /* must be less than UBITS */ #define FEWCOLORS 15 struct smalldfa { struct dfa dfa; struct sset ssets[FEWSTATES*2]; unsigned statesarea[FEWSTATES*2 + WORK]; struct sset *outsarea[FEWSTATES*2 * FEWCOLORS]; struct arcp incarea[FEWSTATES*2 * FEWCOLORS]; }; #define DOMALLOC ((struct smalldfa *)NULL) /* force malloc */ /* * Internal variables, bundled for easy passing around. */ struct vars { regex_t *re; struct guts *g; int eflags; /* copies of arguments */ size_t nmatch; regmatch_t *pmatch; rm_detail_t *details; chr *start; /* start of string */ chr *stop; /* just past end of string */ int err; /* error code if any (0 none) */ struct dfa **subdfas; /* per-subre DFAs */ struct smalldfa dfa1; struct smalldfa dfa2; }; #define VISERR(vv) ((vv)->err != 0) /* have we seen an error yet? */ #define ISERR() VISERR(v) #define VERR(vv,e) ((vv)->err = ((vv)->err ? (vv)->err : (e))) #define ERR(e) VERR(v, e) /* record an error */ #define NOERR() {if (ISERR()) return v->err;} /* if error seen, return it */ #define OFF(p) ((p) - v->start) #define LOFF(p) ((long)OFF(p)) /* * forward declarations */ /* =====^!^===== begin forwards =====^!^===== */ /* automatically gathered by fwd; do not hand-edit */ /* === regexec.c === */ int exec(regex_t *, const chr *, size_t, rm_detail_t *, size_t, regmatch_t [], int); static struct dfa *getsubdfa(struct vars *, struct subre *); static int simpleFind(struct vars *const, struct cnfa *const, struct colormap *const); static int complicatedFind(struct vars *const, struct cnfa *const, struct colormap *const); static int complicatedFindLoop(struct vars *const, struct cnfa *const, struct colormap *const, struct dfa *const, struct dfa *const, chr **const); static void zapallsubs(regmatch_t *const, const size_t); static void zaptreesubs(struct vars *const, struct subre *const); static void subset(struct vars *const, struct subre *const, chr *const, chr *const); static int cdissect(struct vars *, struct subre *, chr *, chr *); static int ccondissect(struct vars *, struct subre *, chr *, chr *); static int crevcondissect(struct vars *, struct subre *, chr *, chr *); static int cbrdissect(struct vars *, struct subre *, chr *, chr *); static int caltdissect(struct vars *, struct subre *, chr *, chr *); static int citerdissect(struct vars *, struct subre *, chr *, chr *); static int creviterdissect(struct vars *, struct subre *, chr *, chr *); /* === rege_dfa.c === */ static chr *longest(struct vars *const, struct dfa *const, chr *const, chr *const, int *const); static chr *shortest(struct vars *const, struct dfa *const, chr *const, chr *const, chr *const, chr **const, int *const); static chr *lastCold(struct vars *const, struct dfa *const); static struct dfa *newDFA(struct vars *const, struct cnfa *const, struct colormap *const, struct smalldfa *); static void freeDFA(struct dfa *const); static unsigned hash(unsigned *const, const int); static struct sset *initialize(struct vars *const, struct dfa *const, chr *const); static struct sset *miss(struct vars *const, struct dfa *const, struct sset *const, const pcolor, chr *const, chr *const); static int checkLAConstraint(struct vars *const, struct cnfa *const, chr *const, const pcolor); static struct sset *getVacantSS(struct vars *const, struct dfa *const, chr *const, chr *const); static struct sset *pickNextSS(struct vars *const, struct dfa *const, chr *const, chr *const); /* automatically gathered by fwd; do not hand-edit */ /* =====^!^===== end forwards =====^!^===== */ /* - exec - match regular expression ^ int exec(regex_t *, const chr *, size_t, rm_detail_t *, ^ size_t, regmatch_t [], int); */ int exec( regex_t *re, const chr *string, size_t len, rm_detail_t *details, size_t nmatch, regmatch_t pmatch[], int flags) { AllocVars(v); int st, backref; size_t n; size_t i; #define LOCALMAT 20 regmatch_t mat[LOCALMAT]; #define LOCALDFAS 40 struct dfa *subdfas[LOCALDFAS]; /* * Sanity checks. */ if (re == NULL || string == NULL || re->re_magic != REMAGIC) { FreeVars(v); return REG_INVARG; } if (re->re_csize != sizeof(chr)) { FreeVars(v); return REG_MIXED; } /* * Setup. */ v->re = re; v->g = (struct guts *)re->re_guts; if ((v->g->cflags®_EXPECT) && details == NULL) { FreeVars(v); return REG_INVARG; } if (v->g->info®_UIMPOSSIBLE) { FreeVars(v); return REG_NOMATCH; } backref = (v->g->info®_UBACKREF) ? 1 : 0; v->eflags = flags; if (v->g->cflags®_NOSUB) { nmatch = 0; /* override client */ } v->nmatch = nmatch; if (backref) { /* * Need work area. */ if (v->g->nsub + 1 <= LOCALMAT) { v->pmatch = mat; } else { v->pmatch = (regmatch_t *) MALLOC((v->g->nsub + 1) * sizeof(regmatch_t)); } if (v->pmatch == NULL) { FreeVars(v); return REG_ESPACE; } v->nmatch = v->g->nsub + 1; } else { v->pmatch = pmatch; } v->details = details; v->start = (chr *)string; v->stop = (chr *)string + len; v->err = 0; assert(v->g->ntree >= 0); n = (size_t) v->g->ntree; if (n <= LOCALDFAS) v->subdfas = subdfas; else v->subdfas = (struct dfa **) MALLOC(n * sizeof(struct dfa *)); if (v->subdfas == NULL) { if (v->pmatch != pmatch && v->pmatch != mat) FREE(v->pmatch); FreeVars(v); return REG_ESPACE; } for (i = 0; i < n; i++) v->subdfas[i] = NULL; /* * Do it. */ assert(v->g->tree != NULL); if (backref) { st = complicatedFind(v, &v->g->tree->cnfa, &v->g->cmap); } else { st = simpleFind(v, &v->g->tree->cnfa, &v->g->cmap); } /* * Copy (portion of) match vector over if necessary. */ if (st == REG_OKAY && v->pmatch != pmatch && nmatch > 0) { zapallsubs(pmatch, nmatch); n = (nmatch < v->nmatch) ? nmatch : v->nmatch; memcpy(VS(pmatch), VS(v->pmatch), n*sizeof(regmatch_t)); } /* * Clean up. */ if (v->pmatch != pmatch && v->pmatch != mat) { FREE(v->pmatch); } n = (size_t) v->g->ntree; for (i = 0; i < n; i++) { if (v->subdfas[i] != NULL) freeDFA(v->subdfas[i]); } if (v->subdfas != subdfas) FREE(v->subdfas); FreeVars(v); return st; } /* - getsubdfa - create or re-fetch the DFA for a subre node * We only need to create the DFA once per overall regex execution. * The DFA will be freed by the cleanup step in exec(). */ static struct dfa * getsubdfa(struct vars * v, struct subre * t) { if (v->subdfas[t->id] == NULL) { v->subdfas[t->id] = newDFA(v, &t->cnfa, &v->g->cmap, DOMALLOC); if (ISERR()) return NULL; } return v->subdfas[t->id]; } /* - simpleFind - find a match for the main NFA (no-complications case) ^ static int simpleFind(struct vars *, struct cnfa *, struct colormap *); */ static int simpleFind( struct vars *const v, struct cnfa *const cnfa, struct colormap *const cm) { struct dfa *s, *d; chr *begin, *end = NULL; chr *cold; chr *open, *close; /* Open and close of range of possible * starts */ int hitend; int shorter = (v->g->tree->flags&SHORTER) ? 1 : 0; /* * First, a shot with the search RE. */ s = newDFA(v, &v->g->search, cm, &v->dfa1); assert(!(ISERR() && s != NULL)); NOERR(); MDEBUG(("\nsearch at %ld\n", LOFF(v->start))); cold = NULL; close = shortest(v, s, v->start, v->start, v->stop, &cold, NULL); freeDFA(s); NOERR(); if (v->g->cflags®_EXPECT) { assert(v->details != NULL); if (cold != NULL) { v->details->rm_extend.rm_so = OFF(cold); } else { v->details->rm_extend.rm_so = OFF(v->stop); } v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */ } if (close == NULL) { /* not found */ return REG_NOMATCH; } if (v->nmatch == 0) { /* found, don't need exact location */ return REG_OKAY; } /* * Find starting point and match. */ assert(cold != NULL); open = cold; cold = NULL; MDEBUG(("between %ld and %ld\n", LOFF(open), LOFF(close))); d = newDFA(v, cnfa, cm, &v->dfa1); assert(!(ISERR() && d != NULL)); NOERR(); for (begin = open; begin <= close; begin++) { MDEBUG(("\nfind trying at %ld\n", LOFF(begin))); if (shorter) { end = shortest(v, d, begin, begin, v->stop, NULL, &hitend); } else { end = longest(v, d, begin, v->stop, &hitend); } if (ISERR()) { freeDFA(d); return v->err; } if (hitend && cold == NULL) { cold = begin; } if (end != NULL) { break; /* NOTE BREAK OUT */ } } assert(end != NULL); /* search RE succeeded so loop should */ freeDFA(d); /* * And pin down details. */ assert(v->nmatch > 0); v->pmatch[0].rm_so = OFF(begin); v->pmatch[0].rm_eo = OFF(end); if (v->g->cflags®_EXPECT) { if (cold != NULL) { v->details->rm_extend.rm_so = OFF(cold); } else { v->details->rm_extend.rm_so = OFF(v->stop); } v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */ } if (v->nmatch == 1) { /* no need for submatches */ return REG_OKAY; } /* * Find submatches. */ zapallsubs(v->pmatch, v->nmatch); return cdissect(v, v->g->tree, begin, end); } /* - complicatedFind - find a match for the main NFA (with complications) ^ static int complicatedFind(struct vars *, struct cnfa *, struct colormap *); */ static int complicatedFind( struct vars *const v, struct cnfa *const cnfa, struct colormap *const cm) { struct dfa *s, *d; chr *cold = NULL; /* silence gcc 4 warning */ int ret; s = newDFA(v, &v->g->search, cm, &v->dfa1); NOERR(); d = newDFA(v, cnfa, cm, &v->dfa2); if (ISERR()) { assert(d == NULL); freeDFA(s); return v->err; } ret = complicatedFindLoop(v, cnfa, cm, d, s, &cold); freeDFA(d); freeDFA(s); NOERR(); if (v->g->cflags®_EXPECT) { assert(v->details != NULL); if (cold != NULL) { v->details->rm_extend.rm_so = OFF(cold); } else { v->details->rm_extend.rm_so = OFF(v->stop); } v->details->rm_extend.rm_eo = OFF(v->stop); /* unknown */ } return ret; } /* - complicatedFindLoop - the heart of complicatedFind ^ static int complicatedFindLoop(struct vars *, struct cnfa *, struct colormap *, ^ struct dfa *, struct dfa *, chr **); */ static int complicatedFindLoop( struct vars *const v, struct cnfa *const cnfa, struct colormap *const cm, struct dfa *const d, struct dfa *const s, chr **const coldp) /* where to put coldstart pointer */ { chr *begin, *end; chr *cold; chr *open, *close; /* Open and close of range of possible * starts */ chr *estart, *estop; int er, hitend; int shorter = v->g->tree->flags&SHORTER; assert(d != NULL && s != NULL); cold = NULL; close = v->start; do { MDEBUG(("\ncsearch at %ld\n", LOFF(close))); close = shortest(v, s, close, close, v->stop, &cold, NULL); if (close == NULL) { break; /* NOTE BREAK */ } assert(cold != NULL); open = cold; cold = NULL; MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close))); for (begin = open; begin <= close; begin++) { MDEBUG(("\ncomplicatedFind trying at %ld\n", LOFF(begin))); estart = begin; estop = v->stop; for (;;) { if (shorter) { end = shortest(v, d, begin, estart, estop, NULL, &hitend); } else { end = longest(v, d, begin, estop, &hitend); } if (hitend && cold == NULL) { cold = begin; } if (end == NULL) { break; /* NOTE BREAK OUT */ } MDEBUG(("tentative end %ld\n", LOFF(end))); zapallsubs(v->pmatch, v->nmatch); er = cdissect(v, v->g->tree, begin, end); if (er == REG_OKAY) { if (v->nmatch > 0) { v->pmatch[0].rm_so = OFF(begin); v->pmatch[0].rm_eo = OFF(end); } *coldp = cold; return REG_OKAY; } if (er != REG_NOMATCH) { ERR(er); *coldp = cold; return er; } if ((shorter) ? end == estop : end == begin) { break; } /* * Go around and try again */ if (shorter) { estart = end + 1; } else { estop = end - 1; } } } } while (close < v->stop); *coldp = cold; return REG_NOMATCH; } /* - zapallsubs - initialize all subexpression matches to "no match" ^ static void zapallsubs(regmatch_t *, size_t); */ static void zapallsubs( regmatch_t *const p, const size_t n) { size_t i; for (i = n-1; i > 0; i--) { p[i].rm_so = -1; p[i].rm_eo = -1; } } /* - zaptreesubs - initialize subexpressions within subtree to "no match" ^ static void zaptreesubs(struct vars *, struct subre *); */ static void zaptreesubs( struct vars *const v, struct subre *const t) { if (t->op == '(') { int n = t->subno; assert(n > 0); if ((size_t) n < v->nmatch) { v->pmatch[n].rm_so = -1; v->pmatch[n].rm_eo = -1; } } if (t->left != NULL) { zaptreesubs(v, t->left); } if (t->right != NULL) { zaptreesubs(v, t->right); } } /* - subset - set subexpression match data for a successful subre ^ static void subset(struct vars *, struct subre *, chr *, chr *); */ static void subset( struct vars *const v, struct subre *const sub, chr *const begin, chr *const end) { int n = sub->subno; assert(n > 0); if ((size_t)n >= v->nmatch) { return; } MDEBUG(("setting %d\n", n)); v->pmatch[n].rm_so = OFF(begin); v->pmatch[n].rm_eo = OFF(end); } /* - cdissect - check backrefs and determine subexpression matches * cdissect recursively processes a subre tree to check matching of backrefs * and/or identify submatch boundaries for capture nodes. The proposed match * runs from "begin" to "end" (not including "end"), and we are basically * "dissecting" it to see where the submatches are. * Before calling any level of cdissect, the caller must have run the node's * DFA and found that the proposed substring satisfies the DFA. (We make * the caller do that because in concatenation and iteration nodes, it's * much faster to check all the substrings against the child DFAs before we * recurse.) Also, caller must have cleared subexpression match data via * zaptreesubs (or zapallsubs at the top level). ^ static int cdissect(struct vars *, struct subre *, chr *, chr *); */ static int /* regexec return code */ cdissect( struct vars *v, struct subre *t, chr *begin, /* beginning of relevant substring */ chr *end) /* end of same */ { int er; assert(t != NULL); MDEBUG(("cdissect %ld-%ld %c\n", LOFF(begin), LOFF(end), t->op)); switch (t->op) { case '=': /* terminal node */ assert(t->left == NULL && t->right == NULL); er = REG_OKAY; /* no action, parent did the work */ break; case 'b': /* back reference */ assert(t->left == NULL && t->right == NULL); er = cbrdissect(v, t, begin, end); break; case '.': /* concatenation */ assert(t->left != NULL && t->right != NULL); if (t->left->flags & SHORTER) /* reverse scan */ er = crevcondissect(v, t, begin, end); else er = ccondissect(v, t, begin, end); break; case '|': /* alternation */ assert(t->left != NULL); er = caltdissect(v, t, begin, end); break; case '*': /* iteration */ assert(t->left != NULL); if (t->left->flags & SHORTER) /* reverse scan */ er = creviterdissect(v, t, begin, end); else er = citerdissect(v, t, begin, end); break; case '(': /* capturing */ assert(t->left != NULL && t->right == NULL); assert(t->subno > 0); er = cdissect(v, t->left, begin, end); if (er == REG_OKAY) { subset(v, t, begin, end); } break; default: er = REG_ASSERT; break; } /* * We should never have a match failure unless backrefs lurk below; * otherwise, either caller failed to check the DFA, or there's some * inconsistency between the DFA and the node's innards. */ assert(er != REG_NOMATCH || (t->flags & BACKR)); return er; } /* - ccondissect - dissect match for concatenation node ^ static int ccondissect(struct vars *, struct subre *, chr *, chr *); */ static int /* regexec return code */ ccondissect( struct vars *v, struct subre *t, chr *begin, /* beginning of relevant substring */ chr *end) /* end of same */ { struct dfa *d, *d2; chr *mid; assert(t->op == '.'); assert(t->left != NULL && t->left->cnfa.nstates > 0); assert(t->right != NULL && t->right->cnfa.nstates > 0); assert(!(t->left->flags & SHORTER)); d = getsubdfa(v, t->left); NOERR(); d2 = getsubdfa(v, t->right); NOERR(); MDEBUG(("cConcat %d\n", t->id)); /* * Pick a tentative midpoint. */ mid = longest(v, d, begin, end, (int *) NULL); if (mid == NULL) { return REG_NOMATCH; } MDEBUG(("tentative midpoint %ld\n", LOFF(mid))); /* * Iterate until satisfaction or failure. */ for (;;) { /* * Try this midpoint on for size. */ if (longest(v, d2, mid, end, NULL) == end) { int er = cdissect(v, t->left, begin, mid); if (er == REG_OKAY) { er = cdissect(v, t->right, mid, end); if (er == REG_OKAY) { /* * Satisfaction. */ MDEBUG(("successful\n")); return REG_OKAY; } } if (er != REG_NOMATCH) { return er; } } /* * That midpoint didn't work, find a new one. */ if (mid == begin) { /* * All possibilities exhausted. */ MDEBUG(("%d no midpoint\n", t->id)); return REG_NOMATCH; } mid = longest(v, d, begin, mid-1, NULL); if (mid == NULL) { /* * Failed to find a new one. */ MDEBUG(("%d failed midpoint\n", t->id)); return REG_NOMATCH; } MDEBUG(("%d: new midpoint %ld\n", t->id, LOFF(mid))); zaptreesubs(v, t->left); zaptreesubs(v, t->right); } } /* - crevcondissect - dissect match for concatenation node, shortest-first ^ static int crevcondissect(struct vars *, struct subre *, chr *, chr *); */ static int /* regexec return code */ crevcondissect( struct vars *v, struct subre *t, chr *begin, /* beginning of relevant substring */ chr *end) /* end of same */ { struct dfa *d, *d2; chr *mid; assert(t->op == '.'); assert(t->left != NULL && t->left->cnfa.nstates > 0); assert(t->right != NULL && t->right->cnfa.nstates > 0); assert(t->left->flags&SHORTER); d = getsubdfa(v, t->left); NOERR(); d2 = getsubdfa(v, t->right); NOERR(); MDEBUG(("crevcon %d\n", t->id)); /* * Pick a tentative midpoint. */ mid = shortest(v, d, begin, begin, end, (chr **) NULL, (int *) NULL); if (mid == NULL) { return REG_NOMATCH; } MDEBUG(("tentative midpoint %ld\n", LOFF(mid))); /* * Iterate until satisfaction or failure. */ for (;;) { /* * Try this midpoint on for size. */ if (longest(v, d2, mid, end, NULL) == end) { int er = cdissect(v, t->left, begin, mid); if (er == REG_OKAY) { er = cdissect(v, t->right, mid, end); if (er == REG_OKAY) { /* * Satisfaction. */ MDEBUG(("successful\n")); return REG_OKAY; } } if (er != REG_NOMATCH) { return er; } } /* * That midpoint didn't work, find a new one. */ if (mid == end) { /* * All possibilities exhausted. */ MDEBUG(("%d no midpoint\n", t->id)); return REG_NOMATCH; } mid = shortest(v, d, begin, mid+1, end, NULL, NULL); if (mid == NULL) { /* * Failed to find a new one. */ MDEBUG(("%d failed midpoint\n", t->id)); return REG_NOMATCH; } MDEBUG(("%d: new midpoint %ld\n", t->id, LOFF(mid))); zaptreesubs(v, t->left); zaptreesubs(v, t->right); } } /* - cbrdissect - dissect match for backref node ^ static int cbrdissect(struct vars *, struct subre *, chr *, chr *); */ static int /* regexec return code */ cbrdissect( struct vars *v, struct subre *t, chr *begin, /* beginning of relevant substring */ chr *end) /* end of same */ { int n = t->subno, min = t->min, max = t->max; size_t numreps; size_t tlen; size_t brlen; chr *brstring; chr *p; assert(t != NULL); assert(t->op == 'b'); assert(n >= 0); assert((size_t)n < v->nmatch); MDEBUG(("cbackref n%d %d{%d-%d}\n", t->id, n, min, max)); /* get the backreferenced string */ if (v->pmatch[n].rm_so == -1) { return REG_NOMATCH; } brstring = v->start + v->pmatch[n].rm_so; brlen = v->pmatch[n].rm_eo - v->pmatch[n].rm_so; /* special cases for zero-length strings */ if (brlen == 0) { /* * matches only if target is zero length, but any number of * repetitions can be considered to be present */ if (begin == end && min <= max) { MDEBUG(("cbackref matched trivially\n")); return REG_OKAY; } return REG_NOMATCH; } if (begin == end) { /* matches only if zero repetitions are okay */ if (min == 0) { MDEBUG(("cbackref matched trivially\n")); return REG_OKAY; } return REG_NOMATCH; } /* * check target length to see if it could possibly be an allowed number of * repetitions of brstring */ assert(end > begin); tlen = end - begin; if (tlen % brlen != 0) return REG_NOMATCH; numreps = tlen / brlen; if (numreps < (size_t)min || (numreps > (size_t)max && max != DUPINF)) return REG_NOMATCH; /* okay, compare the actual string contents */ p = begin; while (numreps-- > 0) { if ((*v->g->compare) (brstring, p, brlen) != 0) return REG_NOMATCH; p += brlen; } MDEBUG(("cbackref matched\n")); return REG_OKAY; } /* - caltdissect - dissect match for alternation node ^ static int caltdissect(struct vars *, struct subre *, chr *, chr *); */ static int /* regexec return code */ caltdissect( struct vars *v, struct subre *t, chr *begin, /* beginning of relevant substring */ chr *end) /* end of same */ { struct dfa *d; int er; /* We loop, rather than tail-recurse, to handle a chain of alternatives */ while (t != NULL) { assert(t->op == '|'); assert(t->left != NULL && t->left->cnfa.nstates > 0); MDEBUG(("calt n%d\n", t->id)); d = getsubdfa(v, t->left); NOERR(); if (longest(v, d, begin, end, (int *) NULL) == end) { MDEBUG(("calt matched\n")); er = cdissect(v, t->left, begin, end); if (er != REG_NOMATCH) { return er; } } t = t->right; } return REG_NOMATCH; } /* - citerdissect - dissect match for iteration node ^ static int citerdissect(struct vars *, struct subre *, chr *, chr *); */ static int /* regexec return code */ citerdissect(struct vars * v, struct subre * t, chr *begin, /* beginning of relevant substring */ chr *end) /* end of same */ { struct dfa *d; chr **endpts; chr *limit; int min_matches; size_t max_matches; int nverified; int k; int i; int er; assert(t->op == '*'); assert(t->left != NULL && t->left->cnfa.nstates > 0); assert(!(t->left->flags & SHORTER)); assert(begin <= end); /* * If zero matches are allowed, and target string is empty, just declare * victory. OTOH, if target string isn't empty, zero matches can't work * so we pretend the min is 1. */ min_matches = t->min; if (min_matches <= 0) { if (begin == end) return REG_OKAY; min_matches = 1; } /* * We need workspace to track the endpoints of each sub-match. Normally * we consider only nonzero-length sub-matches, so there can be at most * end-begin of them. However, if min is larger than that, we will also * consider zero-length sub-matches in order to find enough matches. * * For convenience, endpts[0] contains the "begin" pointer and we store * sub-match endpoints in endpts[1..max_matches]. */ max_matches = end - begin; if (max_matches > (size_t)t->max && t->max != DUPINF) max_matches = t->max; if (max_matches < (size_t)min_matches) max_matches = min_matches; endpts = (chr **) MALLOC((max_matches + 1) * sizeof(chr *)); if (endpts == NULL) return REG_ESPACE; endpts[0] = begin; d = getsubdfa(v, t->left); if (ISERR()) { FREE(endpts); return v->err; } MDEBUG(("citer %d\n", t->id)); /* * Our strategy is to first find a set of sub-match endpoints that are * valid according to the child node's DFA, and then recursively dissect * each sub-match to confirm validity. If any validity check fails, * backtrack the last sub-match and try again. And, when we next try for * a validity check, we need not recheck any successfully verified * sub-matches that we didn't move the endpoints of. nverified remembers * how many sub-matches are currently known okay. */ /* initialize to consider first sub-match */ nverified = 0; k = 1; limit = end; /* iterate until satisfaction or failure */ while (k > 0) { /* try to find an endpoint for the k'th sub-match */ endpts[k] = longest(v, d, endpts[k - 1], limit, (int *) NULL); if (endpts[k] == NULL) { /* no match possible, so see if we can shorten previous one */ k--; goto backtrack; } MDEBUG(("%d: working endpoint %d: %ld\n", t->id, k, LOFF(endpts[k]))); /* k'th sub-match can no longer be considered verified */ if (nverified >= k) nverified = k - 1; if (endpts[k] != end) { /* haven't reached end yet, try another iteration if allowed */ if ((size_t)k >= max_matches) { /* must try to shorten some previous match */ k--; goto backtrack; } /* reject zero-length match unless necessary to achieve min */ if (endpts[k] == endpts[k - 1] && (k >= min_matches || min_matches - k < end - endpts[k])) goto backtrack; k++; limit = end; continue; } /* * We've identified a way to divide the string into k sub-matches * that works so far as the child DFA can tell. If k is an allowed * number of matches, start the slow part: recurse to verify each * sub-match. We always have k <= max_matches, needn't check that. */ if (k < min_matches) goto backtrack; MDEBUG(("%d: verifying %d..%d\n", t->id, nverified + 1, k)); for (i = nverified + 1; i <= k; i++) { zaptreesubs(v, t->left); er = cdissect(v, t->left, endpts[i - 1], endpts[i]); if (er == REG_OKAY) { nverified = i; continue; } if (er == REG_NOMATCH) break; /* oops, something failed */ FREE(endpts); return er; } if (i > k) { /* satisfaction */ MDEBUG(("%d successful\n", t->id)); FREE(endpts); return REG_OKAY; } /* match failed to verify, so backtrack */ backtrack: /* * Must consider shorter versions of the current sub-match. However, * we'll only ask for a zero-length match if necessary. */ while (k > 0) { chr *prev_end = endpts[k - 1]; if (endpts[k] > prev_end) { limit = endpts[k] - 1; if (limit > prev_end || (k < min_matches && min_matches - k >= end - prev_end)) { /* break out of backtrack loop, continue the outer one */ break; } } /* can't shorten k'th sub-match any more, consider previous one */ k--; } } /* all possibilities exhausted */ MDEBUG(("%d failed\n", t->id)); FREE(endpts); return REG_NOMATCH; } /* - creviterdissect - dissect match for iteration node, shortest-first ^ static int creviterdissect(struct vars *, struct subre *, chr *, chr *); */ static int /* regexec return code */ creviterdissect(struct vars * v, struct subre * t, chr *begin, /* beginning of relevant substring */ chr *end) /* end of same */ { struct dfa *d; chr **endpts; chr *limit; int min_matches; size_t max_matches; int nverified; int k; int i; int er; assert(t->op == '*'); assert(t->left != NULL && t->left->cnfa.nstates > 0); assert(t->left->flags & SHORTER); assert(begin <= end); /* * If zero matches are allowed, and target string is empty, just declare * victory. OTOH, if target string isn't empty, zero matches can't work * so we pretend the min is 1. */ min_matches = t->min; if (min_matches <= 0) { if (begin == end) return REG_OKAY; min_matches = 1; } /* * We need workspace to track the endpoints of each sub-match. Normally * we consider only nonzero-length sub-matches, so there can be at most * end-begin of them. However, if min is larger than that, we will also * consider zero-length sub-matches in order to find enough matches. * * For convenience, endpts[0] contains the "begin" pointer and we store * sub-match endpoints in endpts[1..max_matches]. */ max_matches = end - begin; if (max_matches > (size_t)t->max && t->max != DUPINF) max_matches = t->max; if (max_matches < (size_t)min_matches) max_matches = min_matches; endpts = (chr **) MALLOC((max_matches + 1) * sizeof(chr *)); if (endpts == NULL) return REG_ESPACE; endpts[0] = begin; d = getsubdfa(v, t->left); if (ISERR()) { FREE(endpts); return v->err; } MDEBUG(("creviter %d\n", t->id)); /* * Our strategy is to first find a set of sub-match endpoints that are * valid according to the child node's DFA, and then recursively dissect * each sub-match to confirm validity. If any validity check fails, * backtrack the last sub-match and try again. And, when we next try for * a validity check, we need not recheck any successfully verified * sub-matches that we didn't move the endpoints of. nverified remembers * how many sub-matches are currently known okay. */ /* initialize to consider first sub-match */ nverified = 0; k = 1; limit = begin; /* iterate until satisfaction or failure */ while (k > 0) { /* disallow zero-length match unless necessary to achieve min */ if (limit == endpts[k - 1] && limit != end && (k >= min_matches || min_matches - k < end - limit)) limit++; /* if this is the last allowed sub-match, it must reach to the end */ if ((size_t)k >= max_matches) limit = end; /* try to find an endpoint for the k'th sub-match */ endpts[k] = shortest(v, d, endpts[k - 1], limit, end, (chr **) NULL, (int *) NULL); if (endpts[k] == NULL) { /* no match possible, so see if we can lengthen previous one */ k--; goto backtrack; } MDEBUG(("%d: working endpoint %d: %ld\n", t->id, k, LOFF(endpts[k]))); /* k'th sub-match can no longer be considered verified */ if (nverified >= k) nverified = k - 1; if (endpts[k] != end) { /* haven't reached end yet, try another iteration if allowed */ if ((size_t)k >= max_matches) { /* must try to lengthen some previous match */ k--; goto backtrack; } k++; limit = endpts[k - 1]; continue; } /* * We've identified a way to divide the string into k sub-matches * that works so far as the child DFA can tell. If k is an allowed * number of matches, start the slow part: recurse to verify each * sub-match. We always have k <= max_matches, needn't check that. */ if (k < min_matches) goto backtrack; MDEBUG(("%d: verifying %d..%d\n", t->id, nverified + 1, k)); for (i = nverified + 1; i <= k; i++) { zaptreesubs(v, t->left); er = cdissect(v, t->left, endpts[i - 1], endpts[i]); if (er == REG_OKAY) { nverified = i; continue; } if (er == REG_NOMATCH) break; /* oops, something failed */ FREE(endpts); return er; } if (i > k) { /* satisfaction */ MDEBUG(("%d successful\n", t->id)); FREE(endpts); return REG_OKAY; } /* match failed to verify, so backtrack */ backtrack: /* * Must consider longer versions of the current sub-match. */ while (k > 0) { if (endpts[k] < end) { limit = endpts[k] + 1; /* break out of backtrack loop, continue the outer one */ break; } /* can't lengthen k'th sub-match any more, consider previous one */ k--; } } /* all possibilities exhausted */ MDEBUG(("%d failed\n", t->id)); FREE(endpts); return REG_NOMATCH; } #include "rege_dfa.c" /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclTomMath.h0000644000175000017500000004372112663660065015437 0ustar sergeisergei/* LibTomMath, multiple-precision integer library -- Tom St Denis * * LibTomMath is a library that provides multiple-precision * integer arithmetic as well as number theoretic functionality. * * The library was designed directly after the MPI library by * Michael Fromberger but has been written from scratch with * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com */ #ifndef BN_H_ #define BN_H_ #include "tclTomMathDecls.h" #ifndef MODULE_SCOPE #define MODULE_SCOPE extern #endif #ifndef MIN # define MIN(x,y) ((x)<(y)?(x):(y)) #endif #ifndef MAX # define MAX(x,y) ((x)>(y)?(x):(y)) #endif #ifdef __cplusplus extern "C" { /* C++ compilers don't like assigning void * to mp_digit * */ #define OPT_CAST(x) (x *) #else /* C on the other hand doesn't care */ #define OPT_CAST(x) #endif /* detect 64-bit mode if possible */ #if defined(NEVER) /* 128-bit ints fail in too many places */ # if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT)) # define MP_64BIT # endif #endif /* some default configurations. * * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits * * At the very least a mp_digit must be able to hold 7 bits * [any size beyond that is ok provided it doesn't overflow the data type] */ #ifdef MP_8BIT #ifndef MP_DIGIT_DECLARED typedef unsigned char mp_digit; #define MP_DIGIT_DECLARED #endif typedef unsigned short mp_word; #elif defined(MP_16BIT) #ifndef MP_DIGIT_DECLARED typedef unsigned short mp_digit; #define MP_DIGIT_DECLARED #endif typedef unsigned long mp_word; #elif defined(MP_64BIT) /* for GCC only on supported platforms */ #ifndef CRYPT typedef unsigned long long ulong64; typedef signed long long long64; #endif #ifndef MP_DIGIT_DECLARED typedef unsigned long mp_digit; #define MP_DIGIT_DECLARED #endif typedef unsigned long mp_word __attribute__ ((mode(TI))); # define DIGIT_BIT 60 #else /* this is the default case, 28-bit digits */ /* this is to make porting into LibTomCrypt easier :-) */ #ifndef CRYPT # if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 ulong64; typedef signed __int64 long64; # else typedef unsigned long long ulong64; typedef signed long long long64; # endif #endif #ifndef MP_DIGIT_DECLARED typedef unsigned int mp_digit; #define MP_DIGIT_DECLARED #endif typedef ulong64 mp_word; #ifdef MP_31BIT /* this is an extension that uses 31-bit digits */ # define DIGIT_BIT 31 #else /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */ # define DIGIT_BIT 28 # define MP_28BIT #endif #endif /* define heap macros */ #if 0 /* these are macros in tclTomMathDecls.h */ #ifndef CRYPT /* default to libc stuff */ # ifndef XMALLOC # define XMALLOC malloc # define XFREE free # define XREALLOC realloc # define XCALLOC calloc # else /* prototypes for our heap functions */ extern void *XMALLOC(size_t n); extern void *XREALLOC(void *p, size_t n); extern void *XCALLOC(size_t n, size_t s); extern void XFREE(void *p); # endif #endif #endif /* otherwise the bits per digit is calculated automatically from the size of a mp_digit */ #ifndef DIGIT_BIT # define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */ #endif #define MP_DIGIT_BIT DIGIT_BIT #define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) #define MP_DIGIT_MAX MP_MASK /* equalities */ #define MP_LT -1 /* less than */ #define MP_EQ 0 /* equal to */ #define MP_GT 1 /* greater than */ #define MP_ZPOS 0 /* positive integer */ #define MP_NEG 1 /* negative */ #define MP_OKAY 0 /* ok result */ #define MP_MEM -2 /* out of mem */ #define MP_VAL -3 /* invalid input */ #define MP_RANGE MP_VAL #define MP_YES 1 /* yes response */ #define MP_NO 0 /* no response */ /* Primality generation flags */ #define LTM_PRIME_BBS 0x0001 /* BBS style prime */ #define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ #define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ typedef int mp_err; /* you'll have to tune these... */ #if defined(BUILD_tcl) || !defined(_WIN32) MODULE_SCOPE int KARATSUBA_MUL_CUTOFF, KARATSUBA_SQR_CUTOFF, TOOM_MUL_CUTOFF, TOOM_SQR_CUTOFF; #endif /* define this to use lower memory usage routines (exptmods mostly) */ /* #define MP_LOW_MEM */ /* default precision */ #ifndef MP_PREC # ifndef MP_LOW_MEM # define MP_PREC 32 /* default digits of precision */ # else # define MP_PREC 8 /* default digits of precision */ # endif #endif /* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ #define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) /* the infamous mp_int structure */ #ifndef MP_INT_DECLARED #define MP_INT_DECLARED typedef struct mp_int mp_int; #endif struct mp_int { int used, alloc, sign; mp_digit *dp; }; /* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */ typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); #define USED(m) ((m)->used) #define DIGIT(m,k) ((m)->dp[(k)]) #define SIGN(m) ((m)->sign) /* error code to char* string */ /* char *mp_error_to_string(int code); */ /* ---> init and deinit bignum functions <--- */ /* init a bignum */ /* int mp_init(mp_int *a); */ /* free a bignum */ /* void mp_clear(mp_int *a); */ /* init a null terminated series of arguments */ /* int mp_init_multi(mp_int *mp, ...); */ /* clear a null terminated series of arguments */ /* void mp_clear_multi(mp_int *mp, ...); */ /* exchange two ints */ /* void mp_exch(mp_int *a, mp_int *b); */ /* shrink ram required for a bignum */ /* int mp_shrink(mp_int *a); */ /* grow an int to a given size */ /* int mp_grow(mp_int *a, int size); */ /* init to a given number of digits */ /* int mp_init_size(mp_int *a, int size); */ /* ---> Basic Manipulations <--- */ #define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) #define mp_iseven(a) (((a)->used == 0 || (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) #define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) /* set to zero */ /* void mp_zero(mp_int *a); */ /* set to a digit */ /* void mp_set(mp_int *a, mp_digit b); */ /* set a 32-bit const */ /* int mp_set_int(mp_int *a, unsigned long b); */ /* get a 32-bit value */ unsigned long mp_get_int(mp_int * a); /* initialize and set a digit */ /* int mp_init_set (mp_int * a, mp_digit b); */ /* initialize and set 32-bit value */ /* int mp_init_set_int (mp_int * a, unsigned long b); */ /* copy, b = a */ /* int mp_copy(const mp_int *a, mp_int *b); */ /* inits and copies, a = b */ /* int mp_init_copy(mp_int *a, mp_int *b); */ /* trim unused digits */ /* void mp_clamp(mp_int *a); */ /* ---> digit manipulation <--- */ /* right shift by "b" digits */ /* void mp_rshd(mp_int *a, int b); */ /* left shift by "b" digits */ /* int mp_lshd(mp_int *a, int b); */ /* c = a / 2**b */ /* int mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d); */ /* b = a/2 */ /* int mp_div_2(mp_int *a, mp_int *b); */ /* c = a * 2**b */ /* int mp_mul_2d(const mp_int *a, int b, mp_int *c); */ /* b = a*2 */ /* int mp_mul_2(mp_int *a, mp_int *b); */ /* c = a mod 2**d */ /* int mp_mod_2d(const mp_int *a, int b, mp_int *c); */ /* computes a = 2**b */ /* int mp_2expt(mp_int *a, int b); */ /* Counts the number of lsbs which are zero before the first zero bit */ /* int mp_cnt_lsb(mp_int *a); */ /* I Love Earth! */ /* makes a pseudo-random int of a given size */ /* int mp_rand(mp_int *a, int digits); */ /* ---> binary operations <--- */ /* c = a XOR b */ /* int mp_xor(mp_int *a, mp_int *b, mp_int *c); */ /* c = a OR b */ /* int mp_or(mp_int *a, mp_int *b, mp_int *c); */ /* c = a AND b */ /* int mp_and(mp_int *a, mp_int *b, mp_int *c); */ /* ---> Basic arithmetic <--- */ /* b = -a */ /* int mp_neg(const mp_int *a, mp_int *b); */ /* b = |a| */ /* int mp_abs(mp_int *a, mp_int *b); */ /* compare a to b */ /* int mp_cmp(const mp_int *a, const mp_int *b); */ /* compare |a| to |b| */ /* int mp_cmp_mag(const mp_int *a, const mp_int *b); */ /* c = a + b */ /* int mp_add(mp_int *a, mp_int *b, mp_int *c); */ /* c = a - b */ /* int mp_sub(mp_int *a, mp_int *b, mp_int *c); */ /* c = a * b */ /* int mp_mul(mp_int *a, mp_int *b, mp_int *c); */ /* b = a*a */ /* int mp_sqr(mp_int *a, mp_int *b); */ /* a/b => cb + d == a */ /* int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d); */ /* c = a mod b, 0 <= c < b */ /* int mp_mod(mp_int *a, mp_int *b, mp_int *c); */ /* ---> single digit functions <--- */ /* compare against a single digit */ /* int mp_cmp_d(const mp_int *a, mp_digit b); */ /* c = a + b */ /* int mp_add_d(mp_int *a, mp_digit b, mp_int *c); */ /* c = a - b */ /* int mp_sub_d(mp_int *a, mp_digit b, mp_int *c); */ /* c = a * b */ /* int mp_mul_d(mp_int *a, mp_digit b, mp_int *c); */ /* a/b => cb + d == a */ /* int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d); */ /* a/3 => 3c + d == a */ /* int mp_div_3(mp_int *a, mp_int *c, mp_digit *d); */ /* c = a**b */ /* int mp_expt_d(mp_int *a, mp_digit b, mp_int *c); */ /* c = a mod b, 0 <= c < b */ /* int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c); */ /* ---> number theory <--- */ /* d = a + b (mod c) */ /* int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); */ /* d = a - b (mod c) */ /* int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); */ /* d = a * b (mod c) */ /* int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); */ /* c = a * a (mod b) */ /* int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c); */ /* c = 1/a (mod b) */ /* int mp_invmod(mp_int *a, mp_int *b, mp_int *c); */ /* c = (a, b) */ /* int mp_gcd(mp_int *a, mp_int *b, mp_int *c); */ /* produces value such that U1*a + U2*b = U3 */ /* int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3); */ /* c = [a, b] or (a*b)/(a, b) */ /* int mp_lcm(mp_int *a, mp_int *b, mp_int *c); */ /* finds one of the b'th root of a, such that |c|**b <= |a| * * returns error if a < 0 and b is even */ /* int mp_n_root(mp_int *a, mp_digit b, mp_int *c); */ /* special sqrt algo */ /* int mp_sqrt(mp_int *arg, mp_int *ret); */ /* is number a square? */ /* int mp_is_square(mp_int *arg, int *ret); */ /* computes the jacobi c = (a | n) (or Legendre if b is prime) */ /* int mp_jacobi(mp_int *a, mp_int *n, int *c); */ /* used to setup the Barrett reduction for a given modulus b */ /* int mp_reduce_setup(mp_int *a, mp_int *b); */ /* Barrett Reduction, computes a (mod b) with a precomputed value c * * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code]. */ /* int mp_reduce(mp_int *a, mp_int *b, mp_int *c); */ /* setups the montgomery reduction */ /* int mp_montgomery_setup(mp_int *a, mp_digit *mp); */ /* computes a = B**n mod b without division or multiplication useful for * normalizing numbers in a Montgomery system. */ /* int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); */ /* computes x/R == x (mod N) via Montgomery Reduction */ /* int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); */ /* returns 1 if a is a valid DR modulus */ /* int mp_dr_is_modulus(mp_int *a); */ /* sets the value of "d" required for mp_dr_reduce */ /* void mp_dr_setup(mp_int *a, mp_digit *d); */ /* reduces a modulo b using the Diminished Radix method */ /* int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp); */ /* returns true if a can be reduced with mp_reduce_2k */ /* int mp_reduce_is_2k(mp_int *a); */ /* determines k value for 2k reduction */ /* int mp_reduce_2k_setup(mp_int *a, mp_digit *d); */ /* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ /* int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d); */ /* returns true if a can be reduced with mp_reduce_2k_l */ /* int mp_reduce_is_2k_l(mp_int *a); */ /* determines k value for 2k reduction */ /* int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); */ /* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ /* int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); */ /* d = a**b (mod c) */ /* int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); */ /* ---> Primes <--- */ /* number of primes */ #ifdef MP_8BIT # define PRIME_SIZE 31 #else # define PRIME_SIZE 256 #endif /* table of first PRIME_SIZE primes */ #if defined(BUILD_tcl) || !defined(_WIN32) MODULE_SCOPE const mp_digit ltm_prime_tab[]; #endif /* result=1 if a is divisible by one of the first PRIME_SIZE primes */ /* int mp_prime_is_divisible(mp_int *a, int *result); */ /* performs one Fermat test of "a" using base "b". * Sets result to 0 if composite or 1 if probable prime */ /* int mp_prime_fermat(mp_int *a, mp_int *b, int *result); */ /* performs one Miller-Rabin test of "a" using base "b". * Sets result to 0 if composite or 1 if probable prime */ /* int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result); */ /* This gives [for a given bit size] the number of trials required * such that Miller-Rabin gives a prob of failure lower than 2^-96 */ /* int mp_prime_rabin_miller_trials(int size); */ /* performs t rounds of Miller-Rabin on "a" using the first * t prime bases. Also performs an initial sieve of trial * division. Determines if "a" is prime with probability * of error no more than (1/4)**t. * * Sets result to 1 if probably prime, 0 otherwise */ /* int mp_prime_is_prime(mp_int *a, int t, int *result); */ /* finds the next prime after the number "a" using "t" trials * of Miller-Rabin. * * bbs_style = 1 means the prime must be congruent to 3 mod 4 */ /* int mp_prime_next_prime(mp_int *a, int t, int bbs_style); */ /* makes a truly random prime of a given size (bytes), * call with bbs = 1 if you want it to be congruent to 3 mod 4 * * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself * so it can be NULL * * The prime generated will be larger than 2^(8*size). */ #define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat) /* makes a truly random prime of a given size (bits), * * Flags are as follows: * * LTM_PRIME_BBS - make prime congruent to 3 mod 4 * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero * LTM_PRIME_2MSB_ON - make the 2nd highest bit one * * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself * so it can be NULL * */ /* int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat); */ /* ---> radix conversion <--- */ /* int mp_count_bits(const mp_int *a); */ /* int mp_unsigned_bin_size(mp_int *a); */ /* int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c); */ /* int mp_to_unsigned_bin(mp_int *a, unsigned char *b); */ /* int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen); */ /* int mp_signed_bin_size(mp_int *a); */ /* int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c); */ /* int mp_to_signed_bin(mp_int *a, unsigned char *b); */ /* int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen); */ /* int mp_read_radix(mp_int *a, const char *str, int radix); */ /* int mp_toradix(mp_int *a, char *str, int radix); */ /* int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen); */ /* int mp_radix_size(mp_int *a, int radix, int *size); */ /* int mp_fread(mp_int *a, int radix, FILE *stream); */ /* int mp_fwrite(mp_int *a, int radix, FILE *stream); */ #define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len)) #define mp_raw_size(mp) mp_signed_bin_size(mp) #define mp_toraw(mp, str) mp_to_signed_bin((mp), (str)) #define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len)) #define mp_mag_size(mp) mp_unsigned_bin_size(mp) #define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) #define mp_tobinary(M, S) mp_toradix((M), (S), 2) #define mp_tooctal(M, S) mp_toradix((M), (S), 8) #define mp_todecimal(M, S) mp_toradix((M), (S), 10) #define mp_tohex(M, S) mp_toradix((M), (S), 16) /* lowlevel functions, do not call! */ /* int s_mp_add(mp_int *a, mp_int *b, mp_int *c); */ /* int s_mp_sub(mp_int *a, mp_int *b, mp_int *c); */ #define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) /* int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); */ /* int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); */ /* int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs); */ /* int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs); */ /* int fast_s_mp_sqr(mp_int *a, mp_int *b); */ /* int s_mp_sqr(mp_int *a, mp_int *b); */ /* int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c); */ /* int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c); */ /* int mp_karatsuba_sqr(mp_int *a, mp_int *b); */ /* int mp_toom_sqr(mp_int *a, mp_int *b); */ /* int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c); */ /* int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c); */ /* int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); */ /* int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode); */ /* int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int mode); */ /* void bn_reverse(unsigned char *s, int len); */ #if defined(BUILD_tcl) || !defined(_WIN32) MODULE_SCOPE const char *mp_s_rmap; #endif #ifdef __cplusplus } #endif #endif tcl8.6.5/generic/tclTimer.c0000644000175000017500000010770012663660065015137 0ustar sergeisergei/* * tclTimer.c -- * * This file provides timer event management facilities for Tcl, * including the "after" command. * * Copyright (c) 1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * For each timer callback that's pending there is one record of the following * type. The normal handlers (created by Tcl_CreateTimerHandler) are chained * together in a list sorted by time (earliest event first). */ typedef struct TimerHandler { Tcl_Time time; /* When timer is to fire. */ Tcl_TimerProc *proc; /* Function to call. */ ClientData clientData; /* Argument to pass to proc. */ Tcl_TimerToken token; /* Identifies handler so it can be deleted. */ struct TimerHandler *nextPtr; /* Next event in queue, or NULL for end of * queue. */ } TimerHandler; /* * The data structure below is used by the "after" command to remember the * command to be executed later. All of the pending "after" commands for an * interpreter are linked together in a list. */ typedef struct AfterInfo { struct AfterAssocData *assocPtr; /* Pointer to the "tclAfter" assocData for the * interp in which command will be * executed. */ Tcl_Obj *commandPtr; /* Command to execute. */ int id; /* Integer identifier for command; used to * cancel it. */ Tcl_TimerToken token; /* Used to cancel the "after" command. NULL * means that the command is run as an idle * handler rather than as a timer handler. * NULL means this is an "after idle" handler * rather than a timer handler. */ struct AfterInfo *nextPtr; /* Next in list of all "after" commands for * this interpreter. */ } AfterInfo; /* * One of the following structures is associated with each interpreter for * which an "after" command has ever been invoked. A pointer to this structure * is stored in the AssocData for the "tclAfter" key. */ typedef struct AfterAssocData { Tcl_Interp *interp; /* The interpreter for which this data is * registered. */ AfterInfo *firstAfterPtr; /* First in list of all "after" commands still * pending for this interpreter, or NULL if * none. */ } AfterAssocData; /* * There is one of the following structures for each of the handlers declared * in a call to Tcl_DoWhenIdle. All of the currently-active handlers are * linked together into a list. */ typedef struct IdleHandler { Tcl_IdleProc *proc; /* Function to call. */ ClientData clientData; /* Value to pass to proc. */ int generation; /* Used to distinguish older handlers from * recently-created ones. */ struct IdleHandler *nextPtr;/* Next in list of active handlers. */ } IdleHandler; /* * The timer and idle queues are per-thread because they are associated with * the notifier, which is also per-thread. * * All static variables used in this file are collected into a single instance * of the following structure. For multi-threaded implementations, there is * one instance of this structure for each thread. * * Notice that different structures with the same name appear in other files. * The structure defined below is used in this file only. */ typedef struct ThreadSpecificData { TimerHandler *firstTimerHandlerPtr; /* First event in queue. */ int lastTimerId; /* Timer identifier of most recently created * timer. */ int timerPending; /* 1 if a timer event is in the queue. */ IdleHandler *idleList; /* First in list of all idle handlers. */ IdleHandler *lastIdlePtr; /* Last in list (or NULL for empty list). */ int idleGeneration; /* Used to fill in the "generation" fields of * IdleHandler structures. Increments each * time Tcl_DoOneEvent starts calling idle * handlers, so that all old handlers can be * called without calling any of the new ones * created by old ones. */ int afterId; /* For unique identifiers of after events. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * Helper macros for working with times. TCL_TIME_BEFORE encodes how to write * the ordering relation on (normalized) times, and TCL_TIME_DIFF_MS computes * the number of milliseconds difference between two times. Both macros use * both of their arguments multiple times, so make sure they are cheap and * side-effect free. The "prototypes" for these macros are: * * static int TCL_TIME_BEFORE(Tcl_Time t1, Tcl_Time t2); * static long TCL_TIME_DIFF_MS(Tcl_Time t1, Tcl_Time t2); */ #define TCL_TIME_BEFORE(t1, t2) \ (((t1).sec<(t2).sec) || ((t1).sec==(t2).sec && (t1).usec<(t2).usec)) #define TCL_TIME_DIFF_MS(t1, t2) \ (1000*((Tcl_WideInt)(t1).sec - (Tcl_WideInt)(t2).sec) + \ ((long)(t1).usec - (long)(t2).usec)/1000) #define TCL_TIME_DIFF_MS_CEILING(t1, t2) \ (1000*((Tcl_WideInt)(t1).sec - (Tcl_WideInt)(t2).sec) + \ ((long)(t1).usec - (long)(t2).usec + 999)/1000) /* * Sleeps under that number of milliseconds don't get double-checked * and are done in exactly one Tcl_Sleep(). This to limit gettimeofday()s. */ #define SLEEP_OFFLOAD_GETTIMEOFDAY 20 /* * The maximum number of milliseconds for each Tcl_Sleep call in AfterDelay. * This is used to limit the maximum lag between interp limit and script * cancellation checks. */ #define TCL_TIME_MAXIMUM_SLICE 500 /* * Prototypes for functions referenced only in this file: */ static void AfterCleanupProc(ClientData clientData, Tcl_Interp *interp); static int AfterDelay(Tcl_Interp *interp, Tcl_WideInt ms); static void AfterProc(ClientData clientData); static void FreeAfterPtr(AfterInfo *afterPtr); static AfterInfo * GetAfterEvent(AfterAssocData *assocPtr, Tcl_Obj *commandPtr); static ThreadSpecificData *InitTimer(void); static void TimerExitProc(ClientData clientData); static int TimerHandlerEventProc(Tcl_Event *evPtr, int flags); static void TimerCheckProc(ClientData clientData, int flags); static void TimerSetupProc(ClientData clientData, int flags); /* *---------------------------------------------------------------------- * * InitTimer -- * * This function initializes the timer module. * * Results: * A pointer to the thread specific data. * * Side effects: * Registers the idle and timer event sources. * *---------------------------------------------------------------------- */ static ThreadSpecificData * InitTimer(void) { ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); if (tsdPtr == NULL) { tsdPtr = TCL_TSD_INIT(&dataKey); Tcl_CreateEventSource(TimerSetupProc, TimerCheckProc, NULL); Tcl_CreateThreadExitHandler(TimerExitProc, NULL); } return tsdPtr; } /* *---------------------------------------------------------------------- * * TimerExitProc -- * * This function is call at exit or unload time to remove the timer and * idle event sources. * * Results: * None. * * Side effects: * Removes the timer and idle event sources and remaining events. * *---------------------------------------------------------------------- */ static void TimerExitProc( ClientData clientData) /* Not used. */ { ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); Tcl_DeleteEventSource(TimerSetupProc, TimerCheckProc, NULL); if (tsdPtr != NULL) { register TimerHandler *timerHandlerPtr; timerHandlerPtr = tsdPtr->firstTimerHandlerPtr; while (timerHandlerPtr != NULL) { tsdPtr->firstTimerHandlerPtr = timerHandlerPtr->nextPtr; ckfree(timerHandlerPtr); timerHandlerPtr = tsdPtr->firstTimerHandlerPtr; } } } /* *-------------------------------------------------------------- * * Tcl_CreateTimerHandler -- * * Arrange for a given function to be invoked at a particular time in the * future. * * Results: * The return value is a token for the timer event, which may be used to * delete the event before it fires. * * Side effects: * When milliseconds have elapsed, proc will be invoked exactly once. * *-------------------------------------------------------------- */ Tcl_TimerToken Tcl_CreateTimerHandler( int milliseconds, /* How many milliseconds to wait before * invoking proc. */ Tcl_TimerProc *proc, /* Function to invoke. */ ClientData clientData) /* Arbitrary data to pass to proc. */ { Tcl_Time time; /* * Compute when the event should fire. */ Tcl_GetTime(&time); time.sec += milliseconds/1000; time.usec += (milliseconds%1000)*1000; if (time.usec >= 1000000) { time.usec -= 1000000; time.sec += 1; } return TclCreateAbsoluteTimerHandler(&time, proc, clientData); } /* *-------------------------------------------------------------- * * TclCreateAbsoluteTimerHandler -- * * Arrange for a given function to be invoked at a particular time in the * future. * * Results: * The return value is a token for the timer event, which may be used to * delete the event before it fires. * * Side effects: * When the time in timePtr has been reached, proc will be invoked * exactly once. * *-------------------------------------------------------------- */ Tcl_TimerToken TclCreateAbsoluteTimerHandler( Tcl_Time *timePtr, Tcl_TimerProc *proc, ClientData clientData) { register TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr; ThreadSpecificData *tsdPtr = InitTimer(); timerHandlerPtr = ckalloc(sizeof(TimerHandler)); /* * Fill in fields for the event. */ memcpy(&timerHandlerPtr->time, timePtr, sizeof(Tcl_Time)); timerHandlerPtr->proc = proc; timerHandlerPtr->clientData = clientData; tsdPtr->lastTimerId++; timerHandlerPtr->token = (Tcl_TimerToken) INT2PTR(tsdPtr->lastTimerId); /* * Add the event to the queue in the correct position * (ordered by event firing time). */ for (tPtr2 = tsdPtr->firstTimerHandlerPtr, prevPtr = NULL; tPtr2 != NULL; prevPtr = tPtr2, tPtr2 = tPtr2->nextPtr) { if (TCL_TIME_BEFORE(timerHandlerPtr->time, tPtr2->time)) { break; } } timerHandlerPtr->nextPtr = tPtr2; if (prevPtr == NULL) { tsdPtr->firstTimerHandlerPtr = timerHandlerPtr; } else { prevPtr->nextPtr = timerHandlerPtr; } TimerSetupProc(NULL, TCL_ALL_EVENTS); return timerHandlerPtr->token; } /* *-------------------------------------------------------------- * * Tcl_DeleteTimerHandler -- * * Delete a previously-registered timer handler. * * Results: * None. * * Side effects: * Destroy the timer callback identified by TimerToken, so that its * associated function will not be called. If the callback has already * fired, or if the given token doesn't exist, then nothing happens. * *-------------------------------------------------------------- */ void Tcl_DeleteTimerHandler( Tcl_TimerToken token) /* Result previously returned by * Tcl_DeleteTimerHandler. */ { register TimerHandler *timerHandlerPtr, *prevPtr; ThreadSpecificData *tsdPtr = InitTimer(); if (token == NULL) { return; } for (timerHandlerPtr = tsdPtr->firstTimerHandlerPtr, prevPtr = NULL; timerHandlerPtr != NULL; prevPtr = timerHandlerPtr, timerHandlerPtr = timerHandlerPtr->nextPtr) { if (timerHandlerPtr->token != token) { continue; } if (prevPtr == NULL) { tsdPtr->firstTimerHandlerPtr = timerHandlerPtr->nextPtr; } else { prevPtr->nextPtr = timerHandlerPtr->nextPtr; } ckfree(timerHandlerPtr); return; } } /* *---------------------------------------------------------------------- * * TimerSetupProc -- * * This function is called by Tcl_DoOneEvent to setup the timer event * source for before blocking. This routine checks both the idle and * after timer lists. * * Results: * None. * * Side effects: * May update the maximum notifier block time. * *---------------------------------------------------------------------- */ static void TimerSetupProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); if (((flags & TCL_IDLE_EVENTS) && tsdPtr->idleList) || ((flags & TCL_TIMER_EVENTS) && tsdPtr->timerPending)) { /* * There is an idle handler or a pending timer event, so just poll. */ blockTime.sec = 0; blockTime.usec = 0; } else if ((flags & TCL_TIMER_EVENTS) && tsdPtr->firstTimerHandlerPtr) { /* * Compute the timeout for the next timer on the list. */ Tcl_GetTime(&blockTime); blockTime.sec = tsdPtr->firstTimerHandlerPtr->time.sec - blockTime.sec; blockTime.usec = tsdPtr->firstTimerHandlerPtr->time.usec - blockTime.usec; if (blockTime.usec < 0) { blockTime.sec -= 1; blockTime.usec += 1000000; } if (blockTime.sec < 0) { blockTime.sec = 0; blockTime.usec = 0; } } else { return; } Tcl_SetMaxBlockTime(&blockTime); } /* *---------------------------------------------------------------------- * * TimerCheckProc -- * * This function is called by Tcl_DoOneEvent to check the timer event * source for events. This routine checks both the idle and after timer * lists. * * Results: * None. * * Side effects: * May queue an event and update the maximum notifier block time. * *---------------------------------------------------------------------- */ static void TimerCheckProc( ClientData data, /* Not used. */ int flags) /* Event flags as passed to Tcl_DoOneEvent. */ { Tcl_Event *timerEvPtr; Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); if ((flags & TCL_TIMER_EVENTS) && tsdPtr->firstTimerHandlerPtr) { /* * Compute the timeout for the next timer on the list. */ Tcl_GetTime(&blockTime); blockTime.sec = tsdPtr->firstTimerHandlerPtr->time.sec - blockTime.sec; blockTime.usec = tsdPtr->firstTimerHandlerPtr->time.usec - blockTime.usec; if (blockTime.usec < 0) { blockTime.sec -= 1; blockTime.usec += 1000000; } if (blockTime.sec < 0) { blockTime.sec = 0; blockTime.usec = 0; } /* * If the first timer has expired, stick an event on the queue. */ if (blockTime.sec == 0 && blockTime.usec == 0 && !tsdPtr->timerPending) { tsdPtr->timerPending = 1; timerEvPtr = ckalloc(sizeof(Tcl_Event)); timerEvPtr->proc = TimerHandlerEventProc; Tcl_QueueEvent(timerEvPtr, TCL_QUEUE_TAIL); } } } /* *---------------------------------------------------------------------- * * TimerHandlerEventProc -- * * This function is called by Tcl_ServiceEvent when a timer event reaches * the front of the event queue. This function handles the event by * invoking the callbacks for all timers that are ready. * * Results: * Returns 1 if the event was handled, meaning it should be removed from * the queue. Returns 0 if the event was not handled, meaning it should * stay on the queue. The only time the event isn't handled is if the * TCL_TIMER_EVENTS flag bit isn't set. * * Side effects: * Whatever the timer handler callback functions do. * *---------------------------------------------------------------------- */ static int TimerHandlerEventProc( Tcl_Event *evPtr, /* Event to service. */ int flags) /* Flags that indicate what events to handle, * such as TCL_FILE_EVENTS. */ { TimerHandler *timerHandlerPtr, **nextPtrPtr; Tcl_Time time; int currentTimerId; ThreadSpecificData *tsdPtr = InitTimer(); /* * Do nothing if timers aren't enabled. This leaves the event on the * queue, so we will get to it as soon as ServiceEvents() is called with * timers enabled. */ if (!(flags & TCL_TIMER_EVENTS)) { return 0; } /* * The code below is trickier than it may look, for the following reasons: * * 1. New handlers can get added to the list while the current one is * being processed. If new ones get added, we don't want to process * them during this pass through the list to avoid starving other event * sources. This is implemented using the token number in the handler: * new handlers will have a newer token than any of the ones currently * on the list. * 2. The handler can call Tcl_DoOneEvent, so we have to remove the * handler from the list before calling it. Otherwise an infinite loop * could result. * 3. Tcl_DeleteTimerHandler can be called to remove an element from the * list while a handler is executing, so the list could change * structure during the call. * 4. Because we only fetch the current time before entering the loop, the * only way a new timer will even be considered runnable is if its * expiration time is within the same millisecond as the current time. * This is fairly likely on Windows, since it has a course granularity * clock. Since timers are placed on the queue in time order with the * most recently created handler appearing after earlier ones with the * same expiration time, we don't have to worry about newer generation * timers appearing before later ones. */ tsdPtr->timerPending = 0; currentTimerId = tsdPtr->lastTimerId; Tcl_GetTime(&time); while (1) { nextPtrPtr = &tsdPtr->firstTimerHandlerPtr; timerHandlerPtr = tsdPtr->firstTimerHandlerPtr; if (timerHandlerPtr == NULL) { break; } if (TCL_TIME_BEFORE(time, timerHandlerPtr->time)) { break; } /* * Bail out if the next timer is of a newer generation. */ if ((currentTimerId - PTR2INT(timerHandlerPtr->token)) < 0) { break; } /* * Remove the handler from the queue before invoking it, to avoid * potential reentrancy problems. */ *nextPtrPtr = timerHandlerPtr->nextPtr; timerHandlerPtr->proc(timerHandlerPtr->clientData); ckfree(timerHandlerPtr); } TimerSetupProc(NULL, TCL_TIMER_EVENTS); return 1; } /* *-------------------------------------------------------------- * * Tcl_DoWhenIdle -- * * Arrange for proc to be invoked the next time the system is idle (i.e., * just before the next time that Tcl_DoOneEvent would have to wait for * something to happen). * * Results: * None. * * Side effects: * Proc will eventually be called, with clientData as argument. See the * manual entry for details. * *-------------------------------------------------------------- */ void Tcl_DoWhenIdle( Tcl_IdleProc *proc, /* Function to invoke. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { register IdleHandler *idlePtr; Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); idlePtr = ckalloc(sizeof(IdleHandler)); idlePtr->proc = proc; idlePtr->clientData = clientData; idlePtr->generation = tsdPtr->idleGeneration; idlePtr->nextPtr = NULL; if (tsdPtr->lastIdlePtr == NULL) { tsdPtr->idleList = idlePtr; } else { tsdPtr->lastIdlePtr->nextPtr = idlePtr; } tsdPtr->lastIdlePtr = idlePtr; blockTime.sec = 0; blockTime.usec = 0; Tcl_SetMaxBlockTime(&blockTime); } /* *---------------------------------------------------------------------- * * Tcl_CancelIdleCall -- * * If there are any when-idle calls requested to a given function with * given clientData, cancel all of them. * * Results: * None. * * Side effects: * If the proc/clientData combination were on the when-idle list, they * are removed so that they will never be called. * *---------------------------------------------------------------------- */ void Tcl_CancelIdleCall( Tcl_IdleProc *proc, /* Function that was previously registered. */ ClientData clientData) /* Arbitrary value to pass to proc. */ { register IdleHandler *idlePtr, *prevPtr; IdleHandler *nextPtr; ThreadSpecificData *tsdPtr = InitTimer(); for (prevPtr = NULL, idlePtr = tsdPtr->idleList; idlePtr != NULL; prevPtr = idlePtr, idlePtr = idlePtr->nextPtr) { while ((idlePtr->proc == proc) && (idlePtr->clientData == clientData)) { nextPtr = idlePtr->nextPtr; ckfree(idlePtr); idlePtr = nextPtr; if (prevPtr == NULL) { tsdPtr->idleList = idlePtr; } else { prevPtr->nextPtr = idlePtr; } if (idlePtr == NULL) { tsdPtr->lastIdlePtr = prevPtr; return; } } } } /* *---------------------------------------------------------------------- * * TclServiceIdle -- * * This function is invoked by the notifier when it becomes idle. It will * invoke all idle handlers that are present at the time the call is * invoked, but not those added during idle processing. * * Results: * The return value is 1 if TclServiceIdle found something to do, * otherwise return value is 0. * * Side effects: * Invokes all pending idle handlers. * *---------------------------------------------------------------------- */ int TclServiceIdle(void) { IdleHandler *idlePtr; int oldGeneration; Tcl_Time blockTime; ThreadSpecificData *tsdPtr = InitTimer(); if (tsdPtr->idleList == NULL) { return 0; } oldGeneration = tsdPtr->idleGeneration; tsdPtr->idleGeneration++; /* * The code below is trickier than it may look, for the following reasons: * * 1. New handlers can get added to the list while the current one is * being processed. If new ones get added, we don't want to process * them during this pass through the list (want to check for other work * to do first). This is implemented using the generation number in the * handler: new handlers will have a different generation than any of * the ones currently on the list. * 2. The handler can call Tcl_DoOneEvent, so we have to remove the * handler from the list before calling it. Otherwise an infinite loop * could result. * 3. Tcl_CancelIdleCall can be called to remove an element from the list * while a handler is executing, so the list could change structure * during the call. */ for (idlePtr = tsdPtr->idleList; ((idlePtr != NULL) && ((oldGeneration - idlePtr->generation) >= 0)); idlePtr = tsdPtr->idleList) { tsdPtr->idleList = idlePtr->nextPtr; if (tsdPtr->idleList == NULL) { tsdPtr->lastIdlePtr = NULL; } idlePtr->proc(idlePtr->clientData); ckfree(idlePtr); } if (tsdPtr->idleList) { blockTime.sec = 0; blockTime.usec = 0; Tcl_SetMaxBlockTime(&blockTime); } return 1; } /* *---------------------------------------------------------------------- * * Tcl_AfterObjCmd -- * * This function is invoked to process the "after" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_AfterObjCmd( ClientData clientData, /* Unused */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_WideInt ms = 0; /* Number of milliseconds to wait */ Tcl_Time wakeup; AfterInfo *afterPtr; AfterAssocData *assocPtr; int length; int index; static const char *const afterSubCmds[] = { "cancel", "idle", "info", NULL }; enum afterSubCmds {AFTER_CANCEL, AFTER_IDLE, AFTER_INFO}; ThreadSpecificData *tsdPtr = InitTimer(); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } /* * Create the "after" information associated for this interpreter, if it * doesn't already exist. */ assocPtr = Tcl_GetAssocData(interp, "tclAfter", NULL); if (assocPtr == NULL) { assocPtr = ckalloc(sizeof(AfterAssocData)); assocPtr->interp = interp; assocPtr->firstAfterPtr = NULL; Tcl_SetAssocData(interp, "tclAfter", AfterCleanupProc, assocPtr); } /* * First lets see if the command was passed a number as the first argument. */ if (objv[1]->typePtr == &tclIntType #ifndef TCL_WIDE_INT_IS_LONG || objv[1]->typePtr == &tclWideIntType #endif || objv[1]->typePtr == &tclBignumType || (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0, &index) != TCL_OK)) { index = -1; if (Tcl_GetWideIntFromObj(NULL, objv[1], &ms) != TCL_OK) { const char *arg = Tcl_GetString(objv[1]); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad argument \"%s\": must be" " cancel, idle, info, or an integer", arg)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "argument", arg, NULL); return TCL_ERROR; } } /* * At this point, either index = -1 and ms contains the number of ms * to wait, or else index is the index of a subcommand. */ switch (index) { case -1: { if (ms < 0) { ms = 0; } if (objc == 2) { return AfterDelay(interp, ms); } afterPtr = ckalloc(sizeof(AfterInfo)); afterPtr->assocPtr = assocPtr; if (objc == 3) { afterPtr->commandPtr = objv[2]; } else { afterPtr->commandPtr = Tcl_ConcatObj(objc-2, objv+2); } Tcl_IncrRefCount(afterPtr->commandPtr); /* * The variable below is used to generate unique identifiers for after * commands. This id can wrap around, which can potentially cause * problems. However, there are not likely to be problems in practice, * because after commands can only be requested to about a month in * the future, and wrap-around is unlikely to occur in less than about * 1-10 years. Thus it's unlikely that any old ids will still be * around when wrap-around occurs. */ afterPtr->id = tsdPtr->afterId; tsdPtr->afterId += 1; Tcl_GetTime(&wakeup); wakeup.sec += (long)(ms / 1000); wakeup.usec += ((long)(ms % 1000)) * 1000; if (wakeup.usec > 1000000) { wakeup.sec++; wakeup.usec -= 1000000; } afterPtr->token = TclCreateAbsoluteTimerHandler(&wakeup, AfterProc, afterPtr); afterPtr->nextPtr = assocPtr->firstAfterPtr; assocPtr->firstAfterPtr = afterPtr; Tcl_SetObjResult(interp, Tcl_ObjPrintf("after#%d", afterPtr->id)); return TCL_OK; } case AFTER_CANCEL: { Tcl_Obj *commandPtr; const char *command, *tempCommand; int tempLength; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "id|command"); return TCL_ERROR; } if (objc == 3) { commandPtr = objv[2]; } else { commandPtr = Tcl_ConcatObj(objc-2, objv+2);; } command = Tcl_GetStringFromObj(commandPtr, &length); for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL; afterPtr = afterPtr->nextPtr) { tempCommand = Tcl_GetStringFromObj(afterPtr->commandPtr, &tempLength); if ((length == tempLength) && !memcmp(command, tempCommand, (unsigned) length)) { break; } } if (afterPtr == NULL) { afterPtr = GetAfterEvent(assocPtr, commandPtr); } if (objc != 3) { Tcl_DecrRefCount(commandPtr); } if (afterPtr != NULL) { if (afterPtr->token != NULL) { Tcl_DeleteTimerHandler(afterPtr->token); } else { Tcl_CancelIdleCall(AfterProc, afterPtr); } FreeAfterPtr(afterPtr); } break; } case AFTER_IDLE: if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "script ?script ...?"); return TCL_ERROR; } afterPtr = ckalloc(sizeof(AfterInfo)); afterPtr->assocPtr = assocPtr; if (objc == 3) { afterPtr->commandPtr = objv[2]; } else { afterPtr->commandPtr = Tcl_ConcatObj(objc-2, objv+2); } Tcl_IncrRefCount(afterPtr->commandPtr); afterPtr->id = tsdPtr->afterId; tsdPtr->afterId += 1; afterPtr->token = NULL; afterPtr->nextPtr = assocPtr->firstAfterPtr; assocPtr->firstAfterPtr = afterPtr; Tcl_DoWhenIdle(AfterProc, afterPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf("after#%d", afterPtr->id)); break; case AFTER_INFO: if (objc == 2) { Tcl_Obj *resultObj = Tcl_NewObj(); for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL; afterPtr = afterPtr->nextPtr) { if (assocPtr->interp == interp) { Tcl_ListObjAppendElement(NULL, resultObj, Tcl_ObjPrintf( "after#%d", afterPtr->id)); } } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "?id?"); return TCL_ERROR; } afterPtr = GetAfterEvent(assocPtr, objv[2]); if (afterPtr == NULL) { const char *eventStr = TclGetString(objv[2]); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "event \"%s\" doesn't exist", eventStr)); Tcl_SetErrorCode(interp, "TCL","LOOKUP","EVENT", eventStr, NULL); return TCL_ERROR; } else { Tcl_Obj *resultListPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(interp, resultListPtr, afterPtr->commandPtr); Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj( (afterPtr->token == NULL) ? "idle" : "timer", -1)); Tcl_SetObjResult(interp, resultListPtr); } break; default: Tcl_Panic("Tcl_AfterObjCmd: bad subcommand index to afterSubCmds"); } return TCL_OK; } /* *---------------------------------------------------------------------- * * AfterDelay -- * * Implements the blocking delay behaviour of [after $time]. Tricky * because it has to take into account any time limit that has been set. * * Results: * Standard Tcl result code (with error set if an error occurred due to a * time limit being exceeded or being canceled). * * Side effects: * May adjust the time limit granularity marker. * *---------------------------------------------------------------------- */ static int AfterDelay( Tcl_Interp *interp, Tcl_WideInt ms) { Interp *iPtr = (Interp *) interp; Tcl_Time endTime, now; Tcl_WideInt diff; Tcl_GetTime(&now); endTime = now; endTime.sec += (long)(ms/1000); endTime.usec += ((int)(ms%1000))*1000; if (endTime.usec >= 1000000) { endTime.sec++; endTime.usec -= 1000000; } do { if (Tcl_AsyncReady()) { if (Tcl_AsyncInvoke(interp, TCL_OK) != TCL_OK) { return TCL_ERROR; } } if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) { return TCL_ERROR; } if (iPtr->limit.timeEvent != NULL && TCL_TIME_BEFORE(iPtr->limit.time, now)) { iPtr->limit.granularityTicker = 0; if (Tcl_LimitCheck(interp) != TCL_OK) { return TCL_ERROR; } } if (iPtr->limit.timeEvent == NULL || TCL_TIME_BEFORE(endTime, iPtr->limit.time)) { diff = TCL_TIME_DIFF_MS_CEILING(endTime, now); #ifndef TCL_WIDE_INT_IS_LONG if (diff > LONG_MAX) { diff = LONG_MAX; } #endif if (diff > TCL_TIME_MAXIMUM_SLICE) { diff = TCL_TIME_MAXIMUM_SLICE; } if (diff == 0 && TCL_TIME_BEFORE(now, endTime)) diff = 1; if (diff > 0) { Tcl_Sleep((long) diff); if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) break; } else break; } else { diff = TCL_TIME_DIFF_MS(iPtr->limit.time, now); #ifndef TCL_WIDE_INT_IS_LONG if (diff > LONG_MAX) { diff = LONG_MAX; } #endif if (diff > TCL_TIME_MAXIMUM_SLICE) { diff = TCL_TIME_MAXIMUM_SLICE; } if (diff > 0) { Tcl_Sleep((long) diff); } if (Tcl_AsyncReady()) { if (Tcl_AsyncInvoke(interp, TCL_OK) != TCL_OK) { return TCL_ERROR; } } if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) { return TCL_ERROR; } if (Tcl_LimitCheck(interp) != TCL_OK) { return TCL_ERROR; } } Tcl_GetTime(&now); } while (TCL_TIME_BEFORE(now, endTime)); return TCL_OK; } /* *---------------------------------------------------------------------- * * GetAfterEvent -- * * This function parses an "after" id such as "after#4" and returns a * pointer to the AfterInfo structure. * * Results: * The return value is either a pointer to an AfterInfo structure, if one * is found that corresponds to "cmdString" and is for interp, or NULL if * no corresponding after event can be found. * * Side effects: * None. * *---------------------------------------------------------------------- */ static AfterInfo * GetAfterEvent( AfterAssocData *assocPtr, /* Points to "after"-related information for * this interpreter. */ Tcl_Obj *commandPtr) { const char *cmdString; /* Textual identifier for after event, such as * "after#6". */ AfterInfo *afterPtr; int id; char *end; cmdString = TclGetString(commandPtr); if (strncmp(cmdString, "after#", 6) != 0) { return NULL; } cmdString += 6; id = strtoul(cmdString, &end, 10); if ((end == cmdString) || (*end != 0)) { return NULL; } for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL; afterPtr = afterPtr->nextPtr) { if (afterPtr->id == id) { return afterPtr; } } return NULL; } /* *---------------------------------------------------------------------- * * AfterProc -- * * Timer callback to execute commands registered with the "after" * command. * * Results: * None. * * Side effects: * Executes whatever command was specified. If the command returns an * error, then the command "bgerror" is invoked to process the error; if * bgerror fails then information about the error is output on stderr. * *---------------------------------------------------------------------- */ static void AfterProc( ClientData clientData) /* Describes command to execute. */ { AfterInfo *afterPtr = clientData; AfterAssocData *assocPtr = afterPtr->assocPtr; AfterInfo *prevPtr; int result; Tcl_Interp *interp; /* * First remove the callback from our list of callbacks; otherwise someone * could delete the callback while it's being executed, which could cause * a core dump. */ if (assocPtr->firstAfterPtr == afterPtr) { assocPtr->firstAfterPtr = afterPtr->nextPtr; } else { for (prevPtr = assocPtr->firstAfterPtr; prevPtr->nextPtr != afterPtr; prevPtr = prevPtr->nextPtr) { /* Empty loop body. */ } prevPtr->nextPtr = afterPtr->nextPtr; } /* * Execute the callback. */ interp = assocPtr->interp; Tcl_Preserve(interp); result = Tcl_EvalObjEx(interp, afterPtr->commandPtr, TCL_EVAL_GLOBAL); if (result != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (\"after\" script)"); Tcl_BackgroundException(interp, result); } Tcl_Release(interp); /* * Free the memory for the callback. */ Tcl_DecrRefCount(afterPtr->commandPtr); ckfree(afterPtr); } /* *---------------------------------------------------------------------- * * FreeAfterPtr -- * * This function removes an "after" command from the list of those that * are pending and frees its resources. This function does *not* cancel * the timer handler; if that's needed, the caller must do it. * * Results: * None. * * Side effects: * The memory associated with afterPtr is released. * *---------------------------------------------------------------------- */ static void FreeAfterPtr( AfterInfo *afterPtr) /* Command to be deleted. */ { AfterInfo *prevPtr; AfterAssocData *assocPtr = afterPtr->assocPtr; if (assocPtr->firstAfterPtr == afterPtr) { assocPtr->firstAfterPtr = afterPtr->nextPtr; } else { for (prevPtr = assocPtr->firstAfterPtr; prevPtr->nextPtr != afterPtr; prevPtr = prevPtr->nextPtr) { /* Empty loop body. */ } prevPtr->nextPtr = afterPtr->nextPtr; } Tcl_DecrRefCount(afterPtr->commandPtr); ckfree(afterPtr); } /* *---------------------------------------------------------------------- * * AfterCleanupProc -- * * This function is invoked whenever an interpreter is deleted * to cleanup the AssocData for "tclAfter". * * Results: * None. * * Side effects: * After commands are removed. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static void AfterCleanupProc( ClientData clientData, /* Points to AfterAssocData for the * interpreter. */ Tcl_Interp *interp) /* Interpreter that is being deleted. */ { AfterAssocData *assocPtr = clientData; AfterInfo *afterPtr; while (assocPtr->firstAfterPtr != NULL) { afterPtr = assocPtr->firstAfterPtr; assocPtr->firstAfterPtr = afterPtr->nextPtr; if (afterPtr->token != NULL) { Tcl_DeleteTimerHandler(afterPtr->token); } else { Tcl_CancelIdleCall(AfterProc, afterPtr); } Tcl_DecrRefCount(afterPtr->commandPtr); ckfree(afterPtr); } ckfree(assocPtr); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * indent-tabs-mode: nil * End: */ tcl8.6.5/generic/tclThreadTest.c0000644000175000017500000007505012663660065016130 0ustar sergeisergei/* * tclThreadTest.c -- * * This file implements the testthread command. Eventually this should be * tclThreadCmd.c * Some of this code is based on work done by Richard Hipp on behalf of * Conservation Through Innovation, Limited, with their permission. * * Copyright (c) 1998 by Sun Microsystems, Inc. * Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef USE_TCL_STUBS # define USE_TCL_STUBS #endif #include "tclInt.h" #ifdef TCL_THREADS /* * Each thread has an single instance of the following structure. There is one * instance of this structure per thread even if that thread contains multiple * interpreters. The interpreter identified by this structure is the main * interpreter for the thread. * * The main interpreter is the one that will process any messages received by * a thread. Any thread can send messages but only the main interpreter can * receive them. */ typedef struct ThreadSpecificData { Tcl_ThreadId threadId; /* Tcl ID for this thread */ Tcl_Interp *interp; /* Main interpreter for this thread */ int flags; /* See the TP_ defines below... */ struct ThreadSpecificData *nextPtr; /* List for "thread names" */ struct ThreadSpecificData *prevPtr; /* List for "thread names" */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * This list is used to list all threads that have interpreters. This is * protected by threadMutex. */ static ThreadSpecificData *threadList = NULL; /* * The following bit-values are legal for the "flags" field of the * ThreadSpecificData structure. */ #define TP_Dying 0x001 /* This thread is being canceled */ /* * An instance of the following structure contains all information that is * passed into a new thread when the thread is created using either the * "thread create" Tcl command or the ThreadCreate() C function. */ typedef struct ThreadCtrl { const char *script; /* The Tcl command this thread should * execute */ int flags; /* Initial value of the "flags" field in the * ThreadSpecificData structure for the new * thread. Might contain TP_Detached or * TP_TclThread. */ Tcl_Condition condWait; /* This condition variable is used to * synchronize the parent and child threads. * The child won't run until it acquires * threadMutex, and the parent function won't * complete until signaled on this condition * variable. */ } ThreadCtrl; /* * This is the event used to send scripts to other threads. */ typedef struct ThreadEvent { Tcl_Event event; /* Must be first */ char *script; /* The script to execute. */ struct ThreadEventResult *resultPtr; /* To communicate the result. This is NULL if * we don't care about it. */ } ThreadEvent; typedef struct ThreadEventResult { Tcl_Condition done; /* Signaled when the script completes */ int code; /* Return value of Tcl_Eval */ char *result; /* Result from the script */ char *errorInfo; /* Copy of errorInfo variable */ char *errorCode; /* Copy of errorCode variable */ Tcl_ThreadId srcThreadId; /* Id of sending thread, in case it dies */ Tcl_ThreadId dstThreadId; /* Id of target thread, in case it dies */ struct ThreadEvent *eventPtr; /* Back pointer */ struct ThreadEventResult *nextPtr; /* List for cleanup */ struct ThreadEventResult *prevPtr; } ThreadEventResult; static ThreadEventResult *resultList; /* * This is for simple error handling when a thread script exits badly. */ static Tcl_ThreadId mainThreadId; static Tcl_ThreadId errorThreadId; static char *errorProcString; /* * Access to the list of threads and to the thread send results is guarded by * this mutex. */ TCL_DECLARE_MUTEX(threadMutex) static int ThreadObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int ThreadCreate(Tcl_Interp *interp, const char *script, int joinable); static int ThreadList(Tcl_Interp *interp); static int ThreadSend(Tcl_Interp *interp, Tcl_ThreadId id, const char *script, int wait); static int ThreadCancel(Tcl_Interp *interp, Tcl_ThreadId id, const char *result, int flags); static Tcl_ThreadCreateType NewTestThread(ClientData clientData); static void ListRemove(ThreadSpecificData *tsdPtr); static void ListUpdateInner(ThreadSpecificData *tsdPtr); static int ThreadEventProc(Tcl_Event *evPtr, int mask); static void ThreadErrorProc(Tcl_Interp *interp); static void ThreadFreeProc(ClientData clientData); static int ThreadDeleteEvent(Tcl_Event *eventPtr, ClientData clientData); static void ThreadExitProc(ClientData clientData); extern int Tcltest_Init(Tcl_Interp *interp); /* *---------------------------------------------------------------------- * * TclThread_Init -- * * Initialize the test thread command. * * Results: * TCL_OK if the package was properly initialized. * * Side effects: * Add the "testthread" command to the interp. * *---------------------------------------------------------------------- */ int TclThread_Init( Tcl_Interp *interp) /* The current Tcl interpreter */ { /* * If the main thread Id has not been set, do it now. */ Tcl_MutexLock(&threadMutex); if (mainThreadId == 0) { mainThreadId = Tcl_GetCurrentThread(); } Tcl_MutexUnlock(&threadMutex); Tcl_CreateObjCommand(interp, "testthread", ThreadObjCmd, NULL, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * ThreadObjCmd -- * * This procedure is invoked to process the "testthread" Tcl command. See * the user documentation for details on what it does. * * thread cancel ?-unwind? id ?result? * thread create ?-joinable? ?script? * thread send ?-async? id script * thread event * thread exit * thread id ?-main? * thread names * thread wait * thread errorproc proc * thread join id * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ThreadObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); int option; static const char *const threadOptions[] = { "cancel", "create", "event", "exit", "id", "join", "names", "send", "wait", "errorproc", NULL }; enum options { THREAD_CANCEL, THREAD_CREATE, THREAD_EVENT, THREAD_EXIT, THREAD_ID, THREAD_JOIN, THREAD_NAMES, THREAD_SEND, THREAD_WAIT, THREAD_ERRORPROC }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], threadOptions, "option", 0, &option) != TCL_OK) { return TCL_ERROR; } /* * Make sure the initial thread is on the list before doing anything. */ if (tsdPtr->interp == NULL) { Tcl_MutexLock(&threadMutex); tsdPtr->interp = interp; ListUpdateInner(tsdPtr); Tcl_CreateThreadExitHandler(ThreadExitProc, NULL); Tcl_MutexUnlock(&threadMutex); } switch ((enum options)option) { case THREAD_CANCEL: { long id; const char *result; int flags, arg; if ((objc < 3) || (objc > 5)) { Tcl_WrongNumArgs(interp, 2, objv, "?-unwind? id ?result?"); return TCL_ERROR; } flags = 0; arg = 2; if ((objc == 4) || (objc == 5)) { if (strcmp("-unwind", Tcl_GetString(objv[arg])) == 0) { flags = TCL_CANCEL_UNWIND; arg++; } } if (Tcl_GetLongFromObj(interp, objv[arg], &id) != TCL_OK) { return TCL_ERROR; } arg++; if (arg < objc) { result = Tcl_GetString(objv[arg]); } else { result = NULL; } return ThreadCancel(interp, (Tcl_ThreadId) (size_t) id, result, flags); } case THREAD_CREATE: { const char *script; int joinable, len; if (objc == 2) { /* * Neither joinable nor special script */ joinable = 0; script = "testthread wait"; /* Just enter event loop */ } else if (objc == 3) { /* * Possibly -joinable, then no special script, no joinable, then * its a script. */ script = Tcl_GetStringFromObj(objv[2], &len); if ((len > 1) && (script[0] == '-') && (script[1] == 'j') && (0 == strncmp(script, "-joinable", (size_t) len))) { joinable = 1; script = "testthread wait"; /* Just enter event loop */ } else { /* * Remember the script */ joinable = 0; } } else if (objc == 4) { /* * Definitely a script available, but is the flag -joinable? */ script = Tcl_GetStringFromObj(objv[2], &len); joinable = ((len > 1) && (script[0] == '-') && (script[1] == 'j') && (0 == strncmp(script, "-joinable", (size_t) len))); script = Tcl_GetString(objv[3]); } else { Tcl_WrongNumArgs(interp, 2, objv, "?-joinable? ?script?"); return TCL_ERROR; } return ThreadCreate(interp, script, joinable); } case THREAD_EXIT: if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } ListRemove(NULL); Tcl_ExitThread(0); return TCL_OK; case THREAD_ID: if (objc == 2 || objc == 3) { Tcl_Obj *idObj; /* * Check if they want the main thread id or the current thread id. */ if (objc == 2) { idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)Tcl_GetCurrentThread()); } else if (objc == 3 && strcmp("-main", Tcl_GetString(objv[2])) == 0) { Tcl_MutexLock(&threadMutex); idObj = Tcl_NewLongObj((long)(size_t)mainThreadId); Tcl_MutexUnlock(&threadMutex); } else { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, idObj); return TCL_OK; } else { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } case THREAD_JOIN: { Tcl_WideInt id; int result, status; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "id"); return TCL_ERROR; } if (Tcl_GetWideIntFromObj(interp, objv[2], &id) != TCL_OK) { return TCL_ERROR; } result = Tcl_JoinThread((Tcl_ThreadId)(size_t)id, &status); if (result == TCL_OK) { Tcl_SetIntObj(Tcl_GetObjResult(interp), status); } else { char buf[20]; sprintf(buf, "%" TCL_LL_MODIFIER "d", id); Tcl_AppendResult(interp, "cannot join thread ", buf, NULL); } return result; } case THREAD_NAMES: if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } return ThreadList(interp); case THREAD_SEND: { Tcl_WideInt id; const char *script; int wait, arg; if ((objc != 4) && (objc != 5)) { Tcl_WrongNumArgs(interp, 2, objv, "?-async? id script"); return TCL_ERROR; } if (objc == 5) { if (strcmp("-async", Tcl_GetString(objv[2])) != 0) { Tcl_WrongNumArgs(interp, 2, objv, "?-async? id script"); return TCL_ERROR; } wait = 0; arg = 3; } else { wait = 1; arg = 2; } if (Tcl_GetWideIntFromObj(interp, objv[arg], &id) != TCL_OK) { return TCL_ERROR; } arg++; script = Tcl_GetString(objv[arg]); return ThreadSend(interp, (Tcl_ThreadId)(size_t)id, script, wait); } case THREAD_EVENT: { if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj( Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT))); return TCL_OK; } case THREAD_ERRORPROC: { /* * Arrange for this proc to handle thread death errors. */ const char *proc; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "proc"); return TCL_ERROR; } Tcl_MutexLock(&threadMutex); errorThreadId = Tcl_GetCurrentThread(); if (errorProcString) { ckfree(errorProcString); } proc = Tcl_GetString(objv[2]); errorProcString = ckalloc(strlen(proc) + 1); strcpy(errorProcString, proc); Tcl_MutexUnlock(&threadMutex); return TCL_OK; } case THREAD_WAIT: if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } while (1) { /* * If the script has been unwound, bail out immediately. This does * not follow the recommended guidelines for how extensions should * handle the script cancellation functionality because this is * not a "normal" extension. Most extensions do not have a command * that simply enters an infinite Tcl event loop. Normal * extensions should not specify the TCL_CANCEL_UNWIND when * calling Tcl_Canceled to check if the command has been canceled. */ if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG | TCL_CANCEL_UNWIND) == TCL_ERROR) { break; } (void) Tcl_DoOneEvent(TCL_ALL_EVENTS); } /* * If we get to this point, we have been canceled by another thread, * which is considered to be an "error". */ ThreadErrorProc(interp); return TCL_OK; } return TCL_OK; } /* *---------------------------------------------------------------------- * * ThreadCreate -- * * This procedure is invoked to create a thread containing an interp to * run a script. This returns after the thread has started executing. * * Results: * A standard Tcl result, which is the thread ID. * * Side effects: * Create a thread. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ThreadCreate( Tcl_Interp *interp, /* Current interpreter. */ const char *script, /* Script to execute */ int joinable) /* Flag, joinable thread or not */ { ThreadCtrl ctrl; Tcl_ThreadId id; ctrl.script = script; ctrl.condWait = NULL; ctrl.flags = 0; joinable = joinable ? TCL_THREAD_JOINABLE : TCL_THREAD_NOFLAGS; Tcl_MutexLock(&threadMutex); if (Tcl_CreateThread(&id, NewTestThread, (ClientData) &ctrl, TCL_THREAD_STACK_DEFAULT, joinable) != TCL_OK) { Tcl_MutexUnlock(&threadMutex); Tcl_AppendResult(interp, "can't create a new thread", NULL); return TCL_ERROR; } /* * Wait for the thread to start because it is using something on our stack! */ Tcl_ConditionWait(&ctrl.condWait, &threadMutex, NULL); Tcl_MutexUnlock(&threadMutex); Tcl_ConditionFinalize(&ctrl.condWait); Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)(size_t)id)); return TCL_OK; } /* *------------------------------------------------------------------------ * * NewTestThread -- * * This routine is the "main()" for a new thread whose task is to execute * a single Tcl script. The argument to this function is a pointer to a * structure that contains the text of the TCL script to be executed. * * Space to hold the script field of the ThreadControl structure passed * in as the only argument was obtained from malloc() and must be freed * by this function before it exits. Space to hold the ThreadControl * structure itself is released by the calling function, and the two * condition variables in the ThreadControl structure are destroyed by * the calling function. The calling function will destroy the * ThreadControl structure and the condition variable as soon as * ctrlPtr->condWait is signaled, so this routine must make copies of any * data it might need after that point. * * Results: * None * * Side effects: * A Tcl script is executed in a new thread. * *------------------------------------------------------------------------ */ Tcl_ThreadCreateType NewTestThread( ClientData clientData) { ThreadCtrl *ctrlPtr = clientData; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); int result; char *threadEvalScript; /* * Initialize the interpreter. This should be more general. */ tsdPtr->interp = Tcl_CreateInterp(); result = Tcl_Init(tsdPtr->interp); if (result != TCL_OK) { ThreadErrorProc(tsdPtr->interp); } /* * This is part of the test facility. Initialize _ALL_ test commands for * use by the new thread. */ result = Tcltest_Init(tsdPtr->interp); if (result != TCL_OK) { ThreadErrorProc(tsdPtr->interp); } /* * Update the list of threads. */ Tcl_MutexLock(&threadMutex); ListUpdateInner(tsdPtr); /* * We need to keep a pointer to the alloc'ed mem of the script we are * eval'ing, for the case that we exit during evaluation */ threadEvalScript = ckalloc(strlen(ctrlPtr->script) + 1); strcpy(threadEvalScript, ctrlPtr->script); Tcl_CreateThreadExitHandler(ThreadExitProc, threadEvalScript); /* * Notify the parent we are alive. */ Tcl_ConditionNotify(&ctrlPtr->condWait); Tcl_MutexUnlock(&threadMutex); /* * Run the script. */ Tcl_Preserve(tsdPtr->interp); result = Tcl_EvalEx(tsdPtr->interp, threadEvalScript, -1, 0); if (result != TCL_OK) { ThreadErrorProc(tsdPtr->interp); } /* * Clean up. */ Tcl_DeleteInterp(tsdPtr->interp); Tcl_Release(tsdPtr->interp); ListRemove(tsdPtr); Tcl_ExitThread(result); TCL_THREAD_CREATE_RETURN; } /* *------------------------------------------------------------------------ * * ThreadErrorProc -- * * Send a message to the thread willing to hear about errors. * * Results: * None * * Side effects: * Send an event. * *------------------------------------------------------------------------ */ static void ThreadErrorProc( Tcl_Interp *interp) /* Interp that failed */ { Tcl_Channel errChannel; const char *errorInfo, *argv[3]; char *script; char buf[TCL_DOUBLE_SPACE+1]; sprintf(buf, "%" TCL_LL_MODIFIER "d", (Tcl_WideInt)(size_t)Tcl_GetCurrentThread()); errorInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); if (errorProcString == NULL) { errChannel = Tcl_GetStdChannel(TCL_STDERR); Tcl_WriteChars(errChannel, "Error from thread ", -1); Tcl_WriteChars(errChannel, buf, -1); Tcl_WriteChars(errChannel, "\n", 1); Tcl_WriteChars(errChannel, errorInfo, -1); Tcl_WriteChars(errChannel, "\n", 1); } else { argv[0] = errorProcString; argv[1] = buf; argv[2] = errorInfo; script = Tcl_Merge(3, argv); ThreadSend(interp, errorThreadId, script, 0); ckfree(script); } } /* *------------------------------------------------------------------------ * * ListUpdateInner -- * * Add the thread local storage to the list. This assumes the caller has * obtained the mutex. * * Results: * None * * Side effects: * Add the thread local storage to its list. * *------------------------------------------------------------------------ */ static void ListUpdateInner( ThreadSpecificData *tsdPtr) { if (tsdPtr == NULL) { tsdPtr = TCL_TSD_INIT(&dataKey); } tsdPtr->threadId = Tcl_GetCurrentThread(); tsdPtr->nextPtr = threadList; if (threadList) { threadList->prevPtr = tsdPtr; } tsdPtr->prevPtr = NULL; threadList = tsdPtr; } /* *------------------------------------------------------------------------ * * ListRemove -- * * Remove the thread local storage from its list. This grabs the mutex to * protect the list. * * Results: * None * * Side effects: * Remove the thread local storage from its list. * *------------------------------------------------------------------------ */ static void ListRemove( ThreadSpecificData *tsdPtr) { if (tsdPtr == NULL) { tsdPtr = TCL_TSD_INIT(&dataKey); } Tcl_MutexLock(&threadMutex); if (tsdPtr->prevPtr) { tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr; } else { threadList = tsdPtr->nextPtr; } if (tsdPtr->nextPtr) { tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr; } tsdPtr->nextPtr = tsdPtr->prevPtr = 0; tsdPtr->interp = NULL; Tcl_MutexUnlock(&threadMutex); } /* *------------------------------------------------------------------------ * * ThreadList -- * * Return a list of threads running Tcl interpreters. * * Results: * A standard Tcl result. * * Side effects: * None. * *------------------------------------------------------------------------ */ static int ThreadList( Tcl_Interp *interp) { ThreadSpecificData *tsdPtr; Tcl_Obj *listPtr; listPtr = Tcl_NewListObj(0, NULL); Tcl_MutexLock(&threadMutex); for (tsdPtr = threadList ; tsdPtr ; tsdPtr = tsdPtr->nextPtr) { Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewWideIntObj((Tcl_WideInt)(size_t)tsdPtr->threadId)); } Tcl_MutexUnlock(&threadMutex); Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *------------------------------------------------------------------------ * * ThreadSend -- * * Send a script to another thread. * * Results: * A standard Tcl result. * * Side effects: * None. * *------------------------------------------------------------------------ */ static int ThreadSend( Tcl_Interp *interp, /* The current interpreter. */ Tcl_ThreadId id, /* Thread Id of other interpreter. */ const char *script, /* The script to evaluate. */ int wait) /* If 1, we block for the result. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ThreadEvent *threadEventPtr; ThreadEventResult *resultPtr; int found, code; Tcl_ThreadId threadId = (Tcl_ThreadId) id; /* * Verify the thread exists. */ Tcl_MutexLock(&threadMutex); found = 0; for (tsdPtr = threadList ; tsdPtr ; tsdPtr = tsdPtr->nextPtr) { if (tsdPtr->threadId == threadId) { found = 1; break; } } if (!found) { Tcl_MutexUnlock(&threadMutex); Tcl_AppendResult(interp, "invalid thread id", NULL); return TCL_ERROR; } /* * Short circut sends to ourself. Ought to do something with -async, like * run in an idle handler. */ if (threadId == Tcl_GetCurrentThread()) { Tcl_MutexUnlock(&threadMutex); return Tcl_EvalEx(interp, script,-1,TCL_EVAL_GLOBAL); } /* * Create the event for its event queue. */ threadEventPtr = ckalloc(sizeof(ThreadEvent)); threadEventPtr->script = ckalloc(strlen(script) + 1); strcpy(threadEventPtr->script, script); if (!wait) { resultPtr = threadEventPtr->resultPtr = NULL; } else { resultPtr = ckalloc(sizeof(ThreadEventResult)); threadEventPtr->resultPtr = resultPtr; /* * Initialize the result fields. */ resultPtr->done = NULL; resultPtr->code = 0; resultPtr->result = NULL; resultPtr->errorInfo = NULL; resultPtr->errorCode = NULL; /* * Maintain the cleanup list. */ resultPtr->srcThreadId = Tcl_GetCurrentThread(); resultPtr->dstThreadId = threadId; resultPtr->eventPtr = threadEventPtr; resultPtr->nextPtr = resultList; if (resultList) { resultList->prevPtr = resultPtr; } resultPtr->prevPtr = NULL; resultList = resultPtr; } /* * Queue the event and poke the other thread's notifier. */ threadEventPtr->event.proc = ThreadEventProc; Tcl_ThreadQueueEvent(threadId, (Tcl_Event *) threadEventPtr, TCL_QUEUE_TAIL); Tcl_ThreadAlert(threadId); if (!wait) { Tcl_MutexUnlock(&threadMutex); return TCL_OK; } /* * Block on the results and then get them. */ Tcl_ResetResult(interp); while (resultPtr->result == NULL) { Tcl_ConditionWait(&resultPtr->done, &threadMutex, NULL); } /* * Unlink result from the result list. */ if (resultPtr->prevPtr) { resultPtr->prevPtr->nextPtr = resultPtr->nextPtr; } else { resultList = resultPtr->nextPtr; } if (resultPtr->nextPtr) { resultPtr->nextPtr->prevPtr = resultPtr->prevPtr; } resultPtr->eventPtr = NULL; resultPtr->nextPtr = NULL; resultPtr->prevPtr = NULL; Tcl_MutexUnlock(&threadMutex); if (resultPtr->code != TCL_OK) { if (resultPtr->errorCode) { Tcl_SetErrorCode(interp, resultPtr->errorCode, NULL); ckfree(resultPtr->errorCode); } if (resultPtr->errorInfo) { Tcl_AddErrorInfo(interp, resultPtr->errorInfo); ckfree(resultPtr->errorInfo); } } Tcl_AppendResult(interp, resultPtr->result, NULL); Tcl_ConditionFinalize(&resultPtr->done); code = resultPtr->code; ckfree(resultPtr->result); ckfree(resultPtr); return code; } /* *------------------------------------------------------------------------ * * ThreadCancel -- * * Cancels a script in another thread. * * Results: * A standard Tcl result. * * Side effects: * None. * *------------------------------------------------------------------------ */ static int ThreadCancel( Tcl_Interp *interp, /* The current interpreter. */ Tcl_ThreadId id, /* Thread Id of other interpreter. */ const char *result, /* The result or NULL for default. */ int flags) /* Flags for Tcl_CancelEval. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); int found; Tcl_ThreadId threadId = (Tcl_ThreadId) id; /* * Verify the thread exists. */ Tcl_MutexLock(&threadMutex); found = 0; for (tsdPtr = threadList ; tsdPtr ; tsdPtr = tsdPtr->nextPtr) { if (tsdPtr->threadId == threadId) { found = 1; break; } } if (!found) { Tcl_MutexUnlock(&threadMutex); Tcl_AppendResult(interp, "invalid thread id", NULL); return TCL_ERROR; } /* * Since Tcl_CancelEval can be safely called from any thread, * we do it now. */ Tcl_MutexUnlock(&threadMutex); Tcl_ResetResult(interp); return Tcl_CancelEval(tsdPtr->interp, (result != NULL) ? Tcl_NewStringObj(result, -1) : NULL, 0, flags); } /* *------------------------------------------------------------------------ * * ThreadEventProc -- * * Handle the event in the target thread. * * Results: * Returns 1 to indicate that the event was processed. * * Side effects: * Fills out the ThreadEventResult struct. * *------------------------------------------------------------------------ */ static int ThreadEventProc( Tcl_Event *evPtr, /* Really ThreadEvent */ int mask) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ThreadEvent *threadEventPtr = (ThreadEvent *) evPtr; ThreadEventResult *resultPtr = threadEventPtr->resultPtr; Tcl_Interp *interp = tsdPtr->interp; int code; const char *result, *errorCode, *errorInfo; if (interp == NULL) { code = TCL_ERROR; result = "no target interp!"; errorCode = "THREAD"; errorInfo = ""; } else { Tcl_Preserve(interp); Tcl_ResetResult(interp); Tcl_CreateThreadExitHandler(ThreadFreeProc, threadEventPtr->script); code = Tcl_EvalEx(interp, threadEventPtr->script,-1,TCL_EVAL_GLOBAL); Tcl_DeleteThreadExitHandler(ThreadFreeProc, threadEventPtr->script); if (code != TCL_OK) { errorCode = Tcl_GetVar(interp, "errorCode", TCL_GLOBAL_ONLY); errorInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY); } else { errorCode = errorInfo = NULL; } result = Tcl_GetStringResult(interp); } ckfree(threadEventPtr->script); if (resultPtr) { Tcl_MutexLock(&threadMutex); resultPtr->code = code; resultPtr->result = ckalloc(strlen(result) + 1); strcpy(resultPtr->result, result); if (errorCode != NULL) { resultPtr->errorCode = ckalloc(strlen(errorCode) + 1); strcpy(resultPtr->errorCode, errorCode); } if (errorInfo != NULL) { resultPtr->errorInfo = ckalloc(strlen(errorInfo) + 1); strcpy(resultPtr->errorInfo, errorInfo); } Tcl_ConditionNotify(&resultPtr->done); Tcl_MutexUnlock(&threadMutex); } if (interp != NULL) { Tcl_Release(interp); } return 1; } /* *------------------------------------------------------------------------ * * ThreadFreeProc -- * * This is called from when we are exiting and memory needs * to be freed. * * Results: * None. * * Side effects: * Clears up mem specified in ClientData * *------------------------------------------------------------------------ */ /* ARGSUSED */ static void ThreadFreeProc( ClientData clientData) { if (clientData) { ckfree(clientData); } } /* *------------------------------------------------------------------------ * * ThreadDeleteEvent -- * * This is called from the ThreadExitProc to delete memory related * to events that we put on the queue. * * Results: * 1 it was our event and we want it removed, 0 otherwise. * * Side effects: * It cleans up our events in the event queue for this thread. * *------------------------------------------------------------------------ */ /* ARGSUSED */ static int ThreadDeleteEvent( Tcl_Event *eventPtr, /* Really ThreadEvent */ ClientData clientData) /* dummy */ { if (eventPtr->proc == ThreadEventProc) { ckfree(((ThreadEvent *) eventPtr)->script); return 1; } /* * If it was NULL, we were in the middle of servicing the event and it * should be removed */ return (eventPtr->proc == NULL); } /* *------------------------------------------------------------------------ * * ThreadExitProc -- * * This is called when the thread exits. * * Results: * None. * * Side effects: * It unblocks anyone that is waiting on a send to this thread. It cleans * up any events in the event queue for this thread. * *------------------------------------------------------------------------ */ /* ARGSUSED */ static void ThreadExitProc( ClientData clientData) { char *threadEvalScript = clientData; ThreadEventResult *resultPtr, *nextPtr; Tcl_ThreadId self = Tcl_GetCurrentThread(); ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->interp != NULL) { ListRemove(tsdPtr); } Tcl_MutexLock(&threadMutex); if (threadEvalScript) { ckfree(threadEvalScript); threadEvalScript = NULL; } Tcl_DeleteEvents((Tcl_EventDeleteProc *) ThreadDeleteEvent, NULL); for (resultPtr = resultList ; resultPtr ; resultPtr = nextPtr) { nextPtr = resultPtr->nextPtr; if (resultPtr->srcThreadId == self) { /* * We are going away. By freeing up the result we signal to the * other thread we don't care about the result. */ if (resultPtr->prevPtr) { resultPtr->prevPtr->nextPtr = resultPtr->nextPtr; } else { resultList = resultPtr->nextPtr; } if (resultPtr->nextPtr) { resultPtr->nextPtr->prevPtr = resultPtr->prevPtr; } resultPtr->nextPtr = resultPtr->prevPtr = 0; resultPtr->eventPtr->resultPtr = NULL; ckfree(resultPtr); } else if (resultPtr->dstThreadId == self) { /* * Dang. The target is going away. Unblock the caller. The result * string must be dynamically allocated because the main thread is * going to call free on it. */ const char *msg = "target thread died"; resultPtr->result = ckalloc(strlen(msg) + 1); strcpy(resultPtr->result, msg); resultPtr->code = TCL_ERROR; Tcl_ConditionNotify(&resultPtr->done); } } Tcl_MutexUnlock(&threadMutex); } #endif /* TCL_THREADS */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclHash.c0000644000175000017500000007246212663660065014750 0ustar sergeisergei/* * tclHash.c -- * * Implementation of in-memory hash tables for Tcl and Tcl-based * applications. * * Copyright (c) 1991-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Prevent macros from clashing with function definitions. */ #undef Tcl_FindHashEntry #undef Tcl_CreateHashEntry /* * When there are this many entries per bucket, on average, rebuild the hash * table to make it larger. */ #define REBUILD_MULTIPLIER 3 /* * The following macro takes a preliminary integer hash value and produces an * index into a hash tables bucket list. The idea is to make it so that * preliminary values that are arbitrarily similar will end up in different * buckets. The hash function was taken from a random-number generator. */ #define RANDOM_INDEX(tablePtr, i) \ ((((i)*1103515245L) >> (tablePtr)->downShift) & (tablePtr)->mask) /* * Prototypes for the array hash key methods. */ static Tcl_HashEntry * AllocArrayEntry(Tcl_HashTable *tablePtr, void *keyPtr); static int CompareArrayKeys(void *keyPtr, Tcl_HashEntry *hPtr); static unsigned int HashArrayKey(Tcl_HashTable *tablePtr, void *keyPtr); /* * Prototypes for the one word hash key methods. Not actually declared because * this is a critical path that is implemented in the core hash table access * function. */ #if 0 static Tcl_HashEntry * AllocOneWordEntry(Tcl_HashTable *tablePtr, void *keyPtr); static int CompareOneWordKeys(void *keyPtr, Tcl_HashEntry *hPtr); static unsigned int HashOneWordKey(Tcl_HashTable *tablePtr, void *keyPtr); #endif /* * Prototypes for the string hash key methods. */ static Tcl_HashEntry * AllocStringEntry(Tcl_HashTable *tablePtr, void *keyPtr); static int CompareStringKeys(void *keyPtr, Tcl_HashEntry *hPtr); static unsigned int HashStringKey(Tcl_HashTable *tablePtr, void *keyPtr); /* * Function prototypes for static functions in this file: */ static Tcl_HashEntry * BogusFind(Tcl_HashTable *tablePtr, const char *key); static Tcl_HashEntry * BogusCreate(Tcl_HashTable *tablePtr, const char *key, int *newPtr); static Tcl_HashEntry * CreateHashEntry(Tcl_HashTable *tablePtr, const char *key, int *newPtr); static Tcl_HashEntry * FindHashEntry(Tcl_HashTable *tablePtr, const char *key); static void RebuildTable(Tcl_HashTable *tablePtr); const Tcl_HashKeyType tclArrayHashKeyType = { TCL_HASH_KEY_TYPE_VERSION, /* version */ TCL_HASH_KEY_RANDOMIZE_HASH, /* flags */ HashArrayKey, /* hashKeyProc */ CompareArrayKeys, /* compareKeysProc */ AllocArrayEntry, /* allocEntryProc */ NULL /* freeEntryProc */ }; const Tcl_HashKeyType tclOneWordHashKeyType = { TCL_HASH_KEY_TYPE_VERSION, /* version */ 0, /* flags */ NULL, /* HashOneWordKey, */ /* hashProc */ NULL, /* CompareOneWordKey, */ /* compareProc */ NULL, /* AllocOneWordKey, */ /* allocEntryProc */ NULL /* FreeOneWordKey, */ /* freeEntryProc */ }; const Tcl_HashKeyType tclStringHashKeyType = { TCL_HASH_KEY_TYPE_VERSION, /* version */ 0, /* flags */ HashStringKey, /* hashKeyProc */ CompareStringKeys, /* compareKeysProc */ AllocStringEntry, /* allocEntryProc */ NULL /* freeEntryProc */ }; /* *---------------------------------------------------------------------- * * Tcl_InitHashTable -- * * Given storage for a hash table, set up the fields to prepare the hash * table for use. * * Results: * None. * * Side effects: * TablePtr is now ready to be passed to Tcl_FindHashEntry and * Tcl_CreateHashEntry. * *---------------------------------------------------------------------- */ void Tcl_InitHashTable( register Tcl_HashTable *tablePtr, /* Pointer to table record, which is supplied * by the caller. */ int keyType) /* Type of keys to use in table: * TCL_STRING_KEYS, TCL_ONE_WORD_KEYS, or an * integer >= 2. */ { /* * Use a special value to inform the extended version that it must not * access any of the new fields in the Tcl_HashTable. If an extension is * rebuilt then any calls to this function will be redirected to the * extended version by a macro. */ Tcl_InitCustomHashTable(tablePtr, keyType, (const Tcl_HashKeyType *) -1); } /* *---------------------------------------------------------------------- * * Tcl_InitCustomHashTable -- * * Given storage for a hash table, set up the fields to prepare the hash * table for use. This is an extended version of Tcl_InitHashTable which * supports user defined keys. * * Results: * None. * * Side effects: * TablePtr is now ready to be passed to Tcl_FindHashEntry and * Tcl_CreateHashEntry. * *---------------------------------------------------------------------- */ void Tcl_InitCustomHashTable( register Tcl_HashTable *tablePtr, /* Pointer to table record, which is supplied * by the caller. */ int keyType, /* Type of keys to use in table: * TCL_STRING_KEYS, TCL_ONE_WORD_KEYS, * TCL_CUSTOM_TYPE_KEYS, TCL_CUSTOM_PTR_KEYS, * or an integer >= 2. */ const Tcl_HashKeyType *typePtr) /* Pointer to structure which defines the * behaviour of this table. */ { #if (TCL_SMALL_HASH_TABLE != 4) Tcl_Panic("Tcl_InitCustomHashTable: TCL_SMALL_HASH_TABLE is %d, not 4", TCL_SMALL_HASH_TABLE); #endif tablePtr->buckets = tablePtr->staticBuckets; tablePtr->staticBuckets[0] = tablePtr->staticBuckets[1] = 0; tablePtr->staticBuckets[2] = tablePtr->staticBuckets[3] = 0; tablePtr->numBuckets = TCL_SMALL_HASH_TABLE; tablePtr->numEntries = 0; tablePtr->rebuildSize = TCL_SMALL_HASH_TABLE*REBUILD_MULTIPLIER; tablePtr->downShift = 28; tablePtr->mask = 3; tablePtr->keyType = keyType; tablePtr->findProc = FindHashEntry; tablePtr->createProc = CreateHashEntry; if (typePtr == NULL) { /* * The caller has been rebuilt so the hash table is an extended * version. */ } else if (typePtr != (Tcl_HashKeyType *) -1) { /* * The caller is requesting a customized hash table so it must be an * extended version. */ tablePtr->typePtr = typePtr; } else { /* * The caller has not been rebuilt so the hash table is not extended. */ } } /* *---------------------------------------------------------------------- * * Tcl_FindHashEntry -- * * Given a hash table find the entry with a matching key. * * Results: * The return value is a token for the matching entry in the hash table, * or NULL if there was no matching entry. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_HashEntry * Tcl_FindHashEntry( Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */ const void *key) /* Key to use to find matching entry. */ { return (*((tablePtr)->findProc))(tablePtr, key); } static Tcl_HashEntry * FindHashEntry( Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */ const char *key) /* Key to use to find matching entry. */ { return CreateHashEntry(tablePtr, key, NULL); } /* *---------------------------------------------------------------------- * * Tcl_CreateHashEntry -- * * Given a hash table with string keys, and a string key, find the entry * with a matching key. If there is no matching entry, then create a new * entry that does match. * * Results: * The return value is a pointer to the matching entry. If this is a * newly-created entry, then *newPtr will be set to a non-zero value; * otherwise *newPtr will be set to 0. If this is a new entry the value * stored in the entry will initially be 0. * * Side effects: * A new entry may be added to the hash table. * *---------------------------------------------------------------------- */ Tcl_HashEntry * Tcl_CreateHashEntry( Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */ const void *key, /* Key to use to find or create matching * entry. */ int *newPtr) /* Store info here telling whether a new entry * was created. */ { return (*((tablePtr)->createProc))(tablePtr, key, newPtr); } static Tcl_HashEntry * CreateHashEntry( Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */ const char *key, /* Key to use to find or create matching * entry. */ int *newPtr) /* Store info here telling whether a new entry * was created. */ { register Tcl_HashEntry *hPtr; const Tcl_HashKeyType *typePtr; unsigned int hash; int index; if (tablePtr->keyType == TCL_STRING_KEYS) { typePtr = &tclStringHashKeyType; } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) { typePtr = &tclOneWordHashKeyType; } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) { typePtr = tablePtr->typePtr; } else { typePtr = &tclArrayHashKeyType; } if (typePtr->hashKeyProc) { hash = typePtr->hashKeyProc(tablePtr, (void *) key); if (typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) { index = RANDOM_INDEX(tablePtr, hash); } else { index = hash & tablePtr->mask; } } else { hash = PTR2UINT(key); index = RANDOM_INDEX(tablePtr, hash); } /* * Search all of the entries in the appropriate bucket. */ if (typePtr->compareKeysProc) { Tcl_CompareHashKeysProc *compareKeysProc = typePtr->compareKeysProc; for (hPtr = tablePtr->buckets[index]; hPtr != NULL; hPtr = hPtr->nextPtr) { #if TCL_HASH_KEY_STORE_HASH if (hash != PTR2UINT(hPtr->hash)) { continue; } #endif if (((void *) key == hPtr) || compareKeysProc((void *) key, hPtr)) { if (newPtr) { *newPtr = 0; } return hPtr; } } } else { for (hPtr = tablePtr->buckets[index]; hPtr != NULL; hPtr = hPtr->nextPtr) { #if TCL_HASH_KEY_STORE_HASH if (hash != PTR2UINT(hPtr->hash)) { continue; } #endif if (key == hPtr->key.oneWordValue) { if (newPtr) { *newPtr = 0; } return hPtr; } } } if (!newPtr) { return NULL; } /* * Entry not found. Add a new one to the bucket. */ *newPtr = 1; if (typePtr->allocEntryProc) { hPtr = typePtr->allocEntryProc(tablePtr, (void *) key); } else { hPtr = ckalloc(sizeof(Tcl_HashEntry)); hPtr->key.oneWordValue = (char *) key; hPtr->clientData = 0; } hPtr->tablePtr = tablePtr; #if TCL_HASH_KEY_STORE_HASH hPtr->hash = UINT2PTR(hash); hPtr->nextPtr = tablePtr->buckets[index]; tablePtr->buckets[index] = hPtr; #else hPtr->bucketPtr = &tablePtr->buckets[index]; hPtr->nextPtr = *hPtr->bucketPtr; *hPtr->bucketPtr = hPtr; #endif tablePtr->numEntries++; /* * If the table has exceeded a decent size, rebuild it with many more * buckets. */ if (tablePtr->numEntries >= tablePtr->rebuildSize) { RebuildTable(tablePtr); } return hPtr; } /* *---------------------------------------------------------------------- * * Tcl_DeleteHashEntry -- * * Remove a single entry from a hash table. * * Results: * None. * * Side effects: * The entry given by entryPtr is deleted from its table and should never * again be used by the caller. It is up to the caller to free the * clientData field of the entry, if that is relevant. * *---------------------------------------------------------------------- */ void Tcl_DeleteHashEntry( Tcl_HashEntry *entryPtr) { register Tcl_HashEntry *prevPtr; const Tcl_HashKeyType *typePtr; Tcl_HashTable *tablePtr; Tcl_HashEntry **bucketPtr; #if TCL_HASH_KEY_STORE_HASH int index; #endif tablePtr = entryPtr->tablePtr; if (tablePtr->keyType == TCL_STRING_KEYS) { typePtr = &tclStringHashKeyType; } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) { typePtr = &tclOneWordHashKeyType; } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) { typePtr = tablePtr->typePtr; } else { typePtr = &tclArrayHashKeyType; } #if TCL_HASH_KEY_STORE_HASH if (typePtr->hashKeyProc == NULL || typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) { index = RANDOM_INDEX(tablePtr, PTR2INT(entryPtr->hash)); } else { index = PTR2UINT(entryPtr->hash) & tablePtr->mask; } bucketPtr = &tablePtr->buckets[index]; #else bucketPtr = entryPtr->bucketPtr; #endif if (*bucketPtr == entryPtr) { *bucketPtr = entryPtr->nextPtr; } else { for (prevPtr = *bucketPtr; ; prevPtr = prevPtr->nextPtr) { if (prevPtr == NULL) { Tcl_Panic("malformed bucket chain in Tcl_DeleteHashEntry"); } if (prevPtr->nextPtr == entryPtr) { prevPtr->nextPtr = entryPtr->nextPtr; break; } } } tablePtr->numEntries--; if (typePtr->freeEntryProc) { typePtr->freeEntryProc(entryPtr); } else { ckfree(entryPtr); } } /* *---------------------------------------------------------------------- * * Tcl_DeleteHashTable -- * * Free up everything associated with a hash table except for the record * for the table itself. * * Results: * None. * * Side effects: * The hash table is no longer useable. * *---------------------------------------------------------------------- */ void Tcl_DeleteHashTable( register Tcl_HashTable *tablePtr) /* Table to delete. */ { register Tcl_HashEntry *hPtr, *nextPtr; const Tcl_HashKeyType *typePtr; int i; if (tablePtr->keyType == TCL_STRING_KEYS) { typePtr = &tclStringHashKeyType; } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) { typePtr = &tclOneWordHashKeyType; } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) { typePtr = tablePtr->typePtr; } else { typePtr = &tclArrayHashKeyType; } /* * Free up all the entries in the table. */ for (i = 0; i < tablePtr->numBuckets; i++) { hPtr = tablePtr->buckets[i]; while (hPtr != NULL) { nextPtr = hPtr->nextPtr; if (typePtr->freeEntryProc) { typePtr->freeEntryProc(hPtr); } else { ckfree(hPtr); } hPtr = nextPtr; } } /* * Free up the bucket array, if it was dynamically allocated. */ if (tablePtr->buckets != tablePtr->staticBuckets) { if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) { TclpSysFree((char *) tablePtr->buckets); } else { ckfree(tablePtr->buckets); } } /* * Arrange for panics if the table is used again without * re-initialization. */ tablePtr->findProc = BogusFind; tablePtr->createProc = BogusCreate; } /* *---------------------------------------------------------------------- * * Tcl_FirstHashEntry -- * * Locate the first entry in a hash table and set up a record that can be * used to step through all the remaining entries of the table. * * Results: * The return value is a pointer to the first entry in tablePtr, or NULL * if tablePtr has no entries in it. The memory at *searchPtr is * initialized so that subsequent calls to Tcl_NextHashEntry will return * all of the entries in the table, one at a time. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_HashEntry * Tcl_FirstHashEntry( Tcl_HashTable *tablePtr, /* Table to search. */ Tcl_HashSearch *searchPtr) /* Place to store information about progress * through the table. */ { searchPtr->tablePtr = tablePtr; searchPtr->nextIndex = 0; searchPtr->nextEntryPtr = NULL; return Tcl_NextHashEntry(searchPtr); } /* *---------------------------------------------------------------------- * * Tcl_NextHashEntry -- * * Once a hash table enumeration has been initiated by calling * Tcl_FirstHashEntry, this function may be called to return successive * elements of the table. * * Results: * The return value is the next entry in the hash table being enumerated, * or NULL if the end of the table is reached. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_HashEntry * Tcl_NextHashEntry( register Tcl_HashSearch *searchPtr) /* Place to store information about progress * through the table. Must have been * initialized by calling * Tcl_FirstHashEntry. */ { Tcl_HashEntry *hPtr; Tcl_HashTable *tablePtr = searchPtr->tablePtr; while (searchPtr->nextEntryPtr == NULL) { if (searchPtr->nextIndex >= tablePtr->numBuckets) { return NULL; } searchPtr->nextEntryPtr = tablePtr->buckets[searchPtr->nextIndex]; searchPtr->nextIndex++; } hPtr = searchPtr->nextEntryPtr; searchPtr->nextEntryPtr = hPtr->nextPtr; return hPtr; } /* *---------------------------------------------------------------------- * * Tcl_HashStats -- * * Return statistics describing the layout of the hash table in its hash * buckets. * * Results: * The return value is a malloc-ed string containing information about * tablePtr. It is the caller's responsibility to free this string. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * Tcl_HashStats( Tcl_HashTable *tablePtr) /* Table for which to produce stats. */ { #define NUM_COUNTERS 10 int count[NUM_COUNTERS], overflow, i, j; double average, tmp; register Tcl_HashEntry *hPtr; char *result, *p; /* * Compute a histogram of bucket usage. */ for (i = 0; i < NUM_COUNTERS; i++) { count[i] = 0; } overflow = 0; average = 0.0; for (i = 0; i < tablePtr->numBuckets; i++) { j = 0; for (hPtr = tablePtr->buckets[i]; hPtr != NULL; hPtr = hPtr->nextPtr) { j++; } if (j < NUM_COUNTERS) { count[j]++; } else { overflow++; } tmp = j; if (tablePtr->numEntries != 0) { average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0; } } /* * Print out the histogram and a few other pieces of information. */ result = ckalloc((NUM_COUNTERS * 60) + 300); sprintf(result, "%d entries in table, %d buckets\n", tablePtr->numEntries, tablePtr->numBuckets); p = result + strlen(result); for (i = 0; i < NUM_COUNTERS; i++) { sprintf(p, "number of buckets with %d entries: %d\n", i, count[i]); p += strlen(p); } sprintf(p, "number of buckets with %d or more entries: %d\n", NUM_COUNTERS, overflow); p += strlen(p); sprintf(p, "average search distance for entry: %.1f", average); return result; } /* *---------------------------------------------------------------------- * * AllocArrayEntry -- * * Allocate space for a Tcl_HashEntry containing the array key. * * Results: * The return value is a pointer to the created entry. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Tcl_HashEntry * AllocArrayEntry( Tcl_HashTable *tablePtr, /* Hash table. */ void *keyPtr) /* Key to store in the hash table entry. */ { int *array = (int *) keyPtr; register int *iPtr1, *iPtr2; Tcl_HashEntry *hPtr; int count; unsigned int size; count = tablePtr->keyType; size = sizeof(Tcl_HashEntry) + (count*sizeof(int)) - sizeof(hPtr->key); if (size < sizeof(Tcl_HashEntry)) { size = sizeof(Tcl_HashEntry); } hPtr = ckalloc(size); for (iPtr1 = array, iPtr2 = hPtr->key.words; count > 0; count--, iPtr1++, iPtr2++) { *iPtr2 = *iPtr1; } hPtr->clientData = 0; return hPtr; } /* *---------------------------------------------------------------------- * * CompareArrayKeys -- * * Compares two array keys. * * Results: * The return value is 0 if they are different and 1 if they are the * same. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int CompareArrayKeys( void *keyPtr, /* New key to compare. */ Tcl_HashEntry *hPtr) /* Existing key to compare. */ { register const int *iPtr1 = (const int *) keyPtr; register const int *iPtr2 = (const int *) hPtr->key.words; Tcl_HashTable *tablePtr = hPtr->tablePtr; int count; for (count = tablePtr->keyType; ; count--, iPtr1++, iPtr2++) { if (count == 0) { return 1; } if (*iPtr1 != *iPtr2) { break; } } return 0; } /* *---------------------------------------------------------------------- * * HashArrayKey -- * * Compute a one-word summary of an array, which can be used to generate * a hash index. * * Results: * The return value is a one-word summary of the information in * string. * * Side effects: * None. * *---------------------------------------------------------------------- */ static unsigned int HashArrayKey( Tcl_HashTable *tablePtr, /* Hash table. */ void *keyPtr) /* Key from which to compute hash value. */ { register const int *array = (const int *) keyPtr; register unsigned int result; int count; for (result = 0, count = tablePtr->keyType; count > 0; count--, array++) { result += *array; } return result; } /* *---------------------------------------------------------------------- * * AllocStringEntry -- * * Allocate space for a Tcl_HashEntry containing the string key. * * Results: * The return value is a pointer to the created entry. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Tcl_HashEntry * AllocStringEntry( Tcl_HashTable *tablePtr, /* Hash table. */ void *keyPtr) /* Key to store in the hash table entry. */ { const char *string = (const char *) keyPtr; Tcl_HashEntry *hPtr; unsigned int size, allocsize; allocsize = size = strlen(string) + 1; if (size < sizeof(hPtr->key)) { allocsize = sizeof(hPtr->key); } hPtr = ckalloc(TclOffset(Tcl_HashEntry, key) + allocsize); memcpy(hPtr->key.string, string, size); hPtr->clientData = 0; return hPtr; } /* *---------------------------------------------------------------------- * * CompareStringKeys -- * * Compares two string keys. * * Results: * The return value is 0 if they are different and 1 if they are the * same. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int CompareStringKeys( void *keyPtr, /* New key to compare. */ Tcl_HashEntry *hPtr) /* Existing key to compare. */ { register const char *p1 = (const char *) keyPtr; register const char *p2 = (const char *) hPtr->key.string; return !strcmp(p1, p2); } /* *---------------------------------------------------------------------- * * HashStringKey -- * * Compute a one-word summary of a text string, which can be used to * generate a hash index. * * Results: * The return value is a one-word summary of the information in string. * * Side effects: * None. * *---------------------------------------------------------------------- */ static unsigned HashStringKey( Tcl_HashTable *tablePtr, /* Hash table. */ void *keyPtr) /* Key from which to compute hash value. */ { register const char *string = keyPtr; register unsigned int result; register char c; /* * I tried a zillion different hash functions and asked many other people * for advice. Many people had their own favorite functions, all * different, but no-one had much idea why they were good ones. I chose * the one below (multiply by 9 and add new character) because of the * following reasons: * * 1. Multiplying by 10 is perfect for keys that are decimal strings, and * multiplying by 9 is just about as good. * 2. Times-9 is (shift-left-3) plus (old). This means that each * character's bits hang around in the low-order bits of the hash value * for ever, plus they spread fairly rapidly up to the high-order bits * to fill out the hash value. This seems works well both for decimal * and non-decimal strings, but isn't strong against maliciously-chosen * keys. * * Note that this function is very weak against malicious strings; it's * very easy to generate multiple keys that have the same hashcode. On the * other hand, that hardly ever actually occurs and this function *is* * very cheap, even by comparison with industry-standard hashes like FNV. * If real strength of hash is required though, use a custom hash based on * Bob Jenkins's lookup3(), but be aware that it's significantly slower. * Since Tcl command and namespace names are usually reasonably-named (the * main use for string hashes in modern Tcl) speed is far more important * than strength. * * See also HashString in tclLiteral.c. * See also TclObjHashKey in tclObj.c. * * See [tcl-Feature Request #2958832] */ if ((result = UCHAR(*string)) != 0) { while ((c = *++string) != 0) { result += (result << 3) + UCHAR(c); } } return result; } /* *---------------------------------------------------------------------- * * BogusFind -- * * This function is invoked when an Tcl_FindHashEntry is called on a * table that has been deleted. * * Results: * If Tcl_Panic returns (which it shouldn't) this function returns NULL. * * Side effects: * Generates a panic. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static Tcl_HashEntry * BogusFind( Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */ const char *key) /* Key to use to find matching entry. */ { Tcl_Panic("called %s on deleted table", "Tcl_FindHashEntry"); return NULL; } /* *---------------------------------------------------------------------- * * BogusCreate -- * * This function is invoked when an Tcl_CreateHashEntry is called on a * table that has been deleted. * * Results: * If panic returns (which it shouldn't) this function returns NULL. * * Side effects: * Generates a panic. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static Tcl_HashEntry * BogusCreate( Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */ const char *key, /* Key to use to find or create matching * entry. */ int *newPtr) /* Store info here telling whether a new entry * was created. */ { Tcl_Panic("called %s on deleted table", "Tcl_CreateHashEntry"); return NULL; } /* *---------------------------------------------------------------------- * * RebuildTable -- * * This function is invoked when the ratio of entries to hash buckets * becomes too large. It creates a new table with a larger bucket array * and moves all of the entries into the new table. * * Results: * None. * * Side effects: * Memory gets reallocated and entries get re-hashed to new buckets. * *---------------------------------------------------------------------- */ static void RebuildTable( register Tcl_HashTable *tablePtr) /* Table to enlarge. */ { int oldSize, count, index; Tcl_HashEntry **oldBuckets; register Tcl_HashEntry **oldChainPtr, **newChainPtr; register Tcl_HashEntry *hPtr; const Tcl_HashKeyType *typePtr; if (tablePtr->keyType == TCL_STRING_KEYS) { typePtr = &tclStringHashKeyType; } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) { typePtr = &tclOneWordHashKeyType; } else if (tablePtr->keyType == TCL_CUSTOM_TYPE_KEYS || tablePtr->keyType == TCL_CUSTOM_PTR_KEYS) { typePtr = tablePtr->typePtr; } else { typePtr = &tclArrayHashKeyType; } oldSize = tablePtr->numBuckets; oldBuckets = tablePtr->buckets; /* * Allocate and initialize the new bucket array, and set up hashing * constants for new array size. */ tablePtr->numBuckets *= 4; if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) { tablePtr->buckets = (Tcl_HashEntry **) TclpSysAlloc((unsigned) (tablePtr->numBuckets * sizeof(Tcl_HashEntry *)), 0); } else { tablePtr->buckets = ckalloc(tablePtr->numBuckets * sizeof(Tcl_HashEntry *)); } for (count = tablePtr->numBuckets, newChainPtr = tablePtr->buckets; count > 0; count--, newChainPtr++) { *newChainPtr = NULL; } tablePtr->rebuildSize *= 4; tablePtr->downShift -= 2; tablePtr->mask = (tablePtr->mask << 2) + 3; /* * Rehash all of the existing entries into the new bucket array. */ for (oldChainPtr = oldBuckets; oldSize > 0; oldSize--, oldChainPtr++) { for (hPtr = *oldChainPtr; hPtr != NULL; hPtr = *oldChainPtr) { *oldChainPtr = hPtr->nextPtr; #if TCL_HASH_KEY_STORE_HASH if (typePtr->hashKeyProc == NULL || typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) { index = RANDOM_INDEX(tablePtr, PTR2INT(hPtr->hash)); } else { index = PTR2UINT(hPtr->hash) & tablePtr->mask; } hPtr->nextPtr = tablePtr->buckets[index]; tablePtr->buckets[index] = hPtr; #else void *key = Tcl_GetHashKey(tablePtr, hPtr); if (typePtr->hashKeyProc) { unsigned int hash; hash = typePtr->hashKeyProc(tablePtr, key); if (typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) { index = RANDOM_INDEX(tablePtr, hash); } else { index = hash & tablePtr->mask; } } else { index = RANDOM_INDEX(tablePtr, key); } hPtr->bucketPtr = &tablePtr->buckets[index]; hPtr->nextPtr = *hPtr->bucketPtr; *hPtr->bucketPtr = hPtr; #endif } } /* * Free up the old bucket array, if it was dynamically allocated. */ if (oldBuckets != tablePtr->staticBuckets) { if (typePtr->flags & TCL_HASH_KEY_SYSTEM_HASH) { TclpSysFree((char *) oldBuckets); } else { ckfree(oldBuckets); } } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclMain.c0000644000175000017500000006147212663660065014750 0ustar sergeisergei/* * tclMain.c -- * * Main program for Tcl shells and other Tcl-based applications. * This file contains a generic main program for Tcl shells and other * Tcl-based applications. It can be used as-is for many applications, * just by supplying a different appInitProc function for each specific * application. Or, it can be used as a template for creating new main * programs for Tcl applications. * * Copyright (c) 1988-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 2000 Ajuba Solutions. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ /* * On Windows, this file needs to be compiled twice, once with TCL_ASCII_MAIN * defined. This way both Tcl_Main and Tcl_MainExW can be implemented, sharing * the same source code. */ #if defined(TCL_ASCII_MAIN) # ifdef UNICODE # undef UNICODE # undef _UNICODE # else # define UNICODE # define _UNICODE # endif #endif #include "tclInt.h" /* * The default prompt used when the user has not overridden it. */ #define DEFAULT_PRIMARY_PROMPT "% " /* * This file can be compiled on Windows in UNICODE mode, as well as on all * other platforms using the native encoding. This is done by using the normal * Windows functions like _tcscmp, but on platforms which don't have * we have to translate that to strcmp here. */ #ifndef _WIN32 # define TCHAR char # define TEXT(arg) arg # define _tcscmp strcmp #endif /* * Further on, in UNICODE mode we just use Tcl_NewUnicodeObj, otherwise * NewNativeObj is needed (which provides proper conversion from native * encoding to UTF-8). */ #ifdef UNICODE # define NewNativeObj Tcl_NewUnicodeObj #else /* !UNICODE */ static inline Tcl_Obj * NewNativeObj( char *string, int length) { Tcl_DString ds; Tcl_ExternalToUtfDString(NULL, string, length, &ds); return TclDStringToObj(&ds); } #endif /* !UNICODE */ /* * Declarations for various library functions and variables (don't want to * include tclPort.h here, because people might copy this file out of the Tcl * source directory to make their own modified versions). */ #if defined _MSC_VER && _MSC_VER < 1900 /* isatty is always defined on MSVC 14.0, but not necessarily as CRTIMPORT. */ extern CRTIMPORT int isatty(int fd); #endif /* * The thread-local variables for this file's functions. */ typedef struct { Tcl_Obj *path; /* The filename of the script for *_Main() * routines to [source] as a startup script, * or NULL for none set, meaning enter * interactive mode. */ Tcl_Obj *encoding; /* The encoding of the startup script file. */ Tcl_MainLoopProc *mainLoopProc; /* Any installed main loop handler. The main * extension that installs these is Tk. */ } ThreadSpecificData; /* * Structure definition for information used to keep the state of an * interactive command processor that reads lines from standard input and * writes prompts and results to standard output. */ typedef enum { PROMPT_NONE, /* Print no prompt */ PROMPT_START, /* Print prompt for command start */ PROMPT_CONTINUE /* Print prompt for command continuation */ } PromptType; typedef struct InteractiveState { Tcl_Channel input; /* The standard input channel from which lines * are read. */ int tty; /* Non-zero means standard input is a * terminal-like device. Zero means it's a * file. */ Tcl_Obj *commandPtr; /* Used to assemble lines of input into Tcl * commands. */ PromptType prompt; /* Next prompt to print */ Tcl_Interp *interp; /* Interpreter that evaluates interactive * commands. */ } InteractiveState; /* * Forward declarations for functions defined later in this file. */ MODULE_SCOPE Tcl_MainLoopProc *TclGetMainLoop(void); static void Prompt(Tcl_Interp *interp, InteractiveState *isPtr); static void StdinProc(ClientData clientData, int mask); static void FreeMainInterp(ClientData clientData); #ifndef TCL_ASCII_MAIN static Tcl_ThreadDataKey dataKey; /* *---------------------------------------------------------------------- * * Tcl_SetStartupScript -- * * Sets the path and encoding of the startup script to be evaluated by * Tcl_Main, used to override the command line processing. * * Results: * None. * * Side effects: * *---------------------------------------------------------------------- */ void Tcl_SetStartupScript( Tcl_Obj *path, /* Filesystem path of startup script file */ const char *encoding) /* Encoding of the data in that file */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Tcl_Obj *newEncoding = NULL; if (encoding != NULL) { newEncoding = Tcl_NewStringObj(encoding, -1); } if (tsdPtr->path != NULL) { Tcl_DecrRefCount(tsdPtr->path); } tsdPtr->path = path; if (tsdPtr->path != NULL) { Tcl_IncrRefCount(tsdPtr->path); } if (tsdPtr->encoding != NULL) { Tcl_DecrRefCount(tsdPtr->encoding); } tsdPtr->encoding = newEncoding; if (tsdPtr->encoding != NULL) { Tcl_IncrRefCount(tsdPtr->encoding); } } /* *---------------------------------------------------------------------- * * Tcl_GetStartupScript -- * * Gets the path and encoding of the startup script to be evaluated by * Tcl_Main. * * Results: * The path of the startup script; NULL if none has been set. * * Side effects: * If encodingPtr is not NULL, stores a (const char *) in it pointing to * the encoding name registered for the startup script. Tcl retains * ownership of the string, and may free it. Caller should make a copy * for long-term use. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_GetStartupScript( const char **encodingPtr) /* When not NULL, points to storage for the * (const char *) that points to the * registered encoding name for the startup * script. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (encodingPtr != NULL) { if (tsdPtr->encoding == NULL) { *encodingPtr = NULL; } else { *encodingPtr = Tcl_GetString(tsdPtr->encoding); } } return tsdPtr->path; } /*---------------------------------------------------------------------- * * Tcl_SourceRCFile -- * * This function is typically invoked by Tcl_Main of Tk_Main function to * source an application specific rc file into the interpreter at startup * time. * * Results: * None. * * Side effects: * Depends on what's in the rc script. * *---------------------------------------------------------------------- */ void Tcl_SourceRCFile( Tcl_Interp *interp) /* Interpreter to source rc file into. */ { Tcl_DString temp; const char *fileName; Tcl_Channel chan; fileName = Tcl_GetVar(interp, "tcl_rcFileName", TCL_GLOBAL_ONLY); if (fileName != NULL) { Tcl_Channel c; const char *fullName; Tcl_DStringInit(&temp); fullName = Tcl_TranslateFileName(interp, fileName, &temp); if (fullName == NULL) { /* * Couldn't translate the file name (e.g. it referred to a bogus * user or there was no HOME environment variable). Just do * nothing. */ } else { /* * Test for the existence of the rc file before trying to read it. */ c = Tcl_OpenFileChannel(NULL, fullName, "r", 0); if (c != NULL) { Tcl_Close(NULL, c); if (Tcl_EvalFile(interp, fullName) != TCL_OK) { chan = Tcl_GetStdChannel(TCL_STDERR); if (chan) { Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); Tcl_WriteChars(chan, "\n", 1); } } } } Tcl_DStringFree(&temp); } } #endif /* !TCL_ASCII_MAIN */ /*---------------------------------------------------------------------- * * Tcl_Main, Tcl_MainEx -- * * Main program for tclsh and most other Tcl-based applications. * * Results: * None. This function never returns (it exits the process when it's * done). * * Side effects: * This function initializes the Tcl world and then starts interpreting * commands; almost anything could happen, depending on the script being * interpreted. * *---------------------------------------------------------------------- */ void Tcl_MainEx( int argc, /* Number of arguments. */ TCHAR **argv, /* Array of argument strings. */ Tcl_AppInitProc *appInitProc, /* Application-specific initialization * function to call after most initialization * but before starting to execute commands. */ Tcl_Interp *interp) { Tcl_Obj *path, *resultPtr, *argvPtr, *appName; const char *encodingName = NULL; int code, exitCode = 0; Tcl_MainLoopProc *mainLoopProc; Tcl_Channel chan; InteractiveState is; TclpSetInitialEncodings(); TclpFindExecutable((const char *)argv[0]); Tcl_InitMemory(interp); is.interp = interp; is.prompt = PROMPT_START; is.commandPtr = Tcl_NewObj(); /* * If the application has not already set a startup script, parse the * first few command line arguments to determine the script path and * encoding. */ if (NULL == Tcl_GetStartupScript(NULL)) { /* * Check whether first 3 args (argv[1] - argv[3]) look like * -encoding ENCODING FILENAME * or like * FILENAME */ if ((argc > 3) && (0 == _tcscmp(TEXT("-encoding"), argv[1])) && ('-' != argv[3][0])) { Tcl_Obj *value = NewNativeObj(argv[2], -1); Tcl_SetStartupScript(NewNativeObj(argv[3], -1), Tcl_GetString(value)); Tcl_DecrRefCount(value); argc -= 3; argv += 3; } else if ((argc > 1) && ('-' != argv[1][0])) { Tcl_SetStartupScript(NewNativeObj(argv[1], -1), NULL); argc--; argv++; } } path = Tcl_GetStartupScript(&encodingName); if (path == NULL) { appName = NewNativeObj(argv[0], -1); } else { appName = path; } Tcl_SetVar2Ex(interp, "argv0", NULL, appName, TCL_GLOBAL_ONLY); argc--; argv++; Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(argc), TCL_GLOBAL_ONLY); argvPtr = Tcl_NewListObj(0, NULL); while (argc--) { Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++, -1)); } Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY); /* * Set the "tcl_interactive" variable. */ is.tty = isatty(0); Tcl_SetVar2Ex(interp, "tcl_interactive", NULL, Tcl_NewIntObj(!path && is.tty), TCL_GLOBAL_ONLY); /* * Invoke application-specific initialization. */ Tcl_Preserve(interp); if (appInitProc(interp) != TCL_OK) { chan = Tcl_GetStdChannel(TCL_STDERR); if (chan) { Tcl_WriteChars(chan, "application-specific initialization failed: ", -1); Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); Tcl_WriteChars(chan, "\n", 1); } } if (Tcl_InterpDeleted(interp)) { goto done; } if (Tcl_LimitExceeded(interp)) { goto done; } if (TclFullFinalizationRequested()) { /* * Arrange for final deletion of the main interp */ /* ARGH Munchhausen effect */ Tcl_CreateExitHandler(FreeMainInterp, interp); } /* * Invoke the script specified on the command line, if any. Must fetch it * again, as the appInitProc might have reset it. */ path = Tcl_GetStartupScript(&encodingName); if (path != NULL) { Tcl_ResetResult(interp); code = Tcl_FSEvalFileEx(interp, path, encodingName); if (code != TCL_OK) { chan = Tcl_GetStdChannel(TCL_STDERR); if (chan) { Tcl_Obj *options = Tcl_GetReturnOptions(interp, code); Tcl_Obj *keyPtr, *valuePtr; TclNewLiteralStringObj(keyPtr, "-errorinfo"); Tcl_IncrRefCount(keyPtr); Tcl_DictObjGet(NULL, options, keyPtr, &valuePtr); Tcl_DecrRefCount(keyPtr); if (valuePtr) { Tcl_WriteObj(chan, valuePtr); } Tcl_WriteChars(chan, "\n", 1); Tcl_DecrRefCount(options); } exitCode = 1; } goto done; } /* * We're running interactively. Source a user-specific startup file if the * application specified one and if the file exists. */ Tcl_SourceRCFile(interp); if (Tcl_LimitExceeded(interp)) { goto done; } /* * Process commands from stdin until there's an end-of-file. Note that we * need to fetch the standard channels again after every eval, since they * may have been changed. */ Tcl_IncrRefCount(is.commandPtr); /* * Get a new value for tty if anyone writes to ::tcl_interactive */ Tcl_LinkVar(interp, "tcl_interactive", (char *) &is.tty, TCL_LINK_BOOLEAN); is.input = Tcl_GetStdChannel(TCL_STDIN); while ((is.input != NULL) && !Tcl_InterpDeleted(interp)) { mainLoopProc = TclGetMainLoop(); if (mainLoopProc == NULL) { int length; if (is.tty) { Prompt(interp, &is); if (Tcl_InterpDeleted(interp)) { break; } if (Tcl_LimitExceeded(interp)) { break; } is.input = Tcl_GetStdChannel(TCL_STDIN); if (is.input == NULL) { break; } } if (Tcl_IsShared(is.commandPtr)) { Tcl_DecrRefCount(is.commandPtr); is.commandPtr = Tcl_DuplicateObj(is.commandPtr); Tcl_IncrRefCount(is.commandPtr); } length = Tcl_GetsObj(is.input, is.commandPtr); if (length < 0) { if (Tcl_InputBlocked(is.input)) { /* * This can only happen if stdin has been set to * non-blocking. In that case cycle back and try again. * This sets up a tight polling loop (since we have no * event loop running). If this causes bad CPU hogging, we * might try toggling the blocking on stdin instead. */ continue; } /* * Either EOF, or an error on stdin; we're done */ break; } /* * Add the newline removed by Tcl_GetsObj back to the string. Have * to add it back before testing completeness, because it can make * a difference. [Bug 1775878] */ if (Tcl_IsShared(is.commandPtr)) { Tcl_DecrRefCount(is.commandPtr); is.commandPtr = Tcl_DuplicateObj(is.commandPtr); Tcl_IncrRefCount(is.commandPtr); } Tcl_AppendToObj(is.commandPtr, "\n", 1); if (!TclObjCommandComplete(is.commandPtr)) { is.prompt = PROMPT_CONTINUE; continue; } is.prompt = PROMPT_START; /* * The final newline is syntactically redundant, and causes some * error messages troubles deeper in, so lop it back off. */ Tcl_GetStringFromObj(is.commandPtr, &length); Tcl_SetObjLength(is.commandPtr, --length); code = Tcl_RecordAndEvalObj(interp, is.commandPtr, TCL_EVAL_GLOBAL); is.input = Tcl_GetStdChannel(TCL_STDIN); Tcl_DecrRefCount(is.commandPtr); is.commandPtr = Tcl_NewObj(); Tcl_IncrRefCount(is.commandPtr); if (code != TCL_OK) { chan = Tcl_GetStdChannel(TCL_STDERR); if (chan) { Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); Tcl_WriteChars(chan, "\n", 1); } } else if (is.tty) { resultPtr = Tcl_GetObjResult(interp); Tcl_IncrRefCount(resultPtr); Tcl_GetStringFromObj(resultPtr, &length); chan = Tcl_GetStdChannel(TCL_STDOUT); if ((length > 0) && chan) { Tcl_WriteObj(chan, resultPtr); Tcl_WriteChars(chan, "\n", 1); } Tcl_DecrRefCount(resultPtr); } } else { /* (mainLoopProc != NULL) */ /* * If a main loop has been defined while running interactively, we * want to start a fileevent based prompt by establishing a * channel handler for stdin. */ if (is.input) { if (is.tty) { Prompt(interp, &is); } Tcl_CreateChannelHandler(is.input, TCL_READABLE, StdinProc, &is); } mainLoopProc(); Tcl_SetMainLoop(NULL); if (is.input) { Tcl_DeleteChannelHandler(is.input, StdinProc, &is); } is.input = Tcl_GetStdChannel(TCL_STDIN); } /* * This code here only for the (unsupported and deprecated) [checkmem] * command. */ #ifdef TCL_MEM_DEBUG if (tclMemDumpFileName != NULL) { Tcl_SetMainLoop(NULL); Tcl_DeleteInterp(interp); } #endif /* TCL_MEM_DEBUG */ } done: mainLoopProc = TclGetMainLoop(); if ((exitCode == 0) && mainLoopProc && !Tcl_LimitExceeded(interp)) { /* * If everything has gone OK so far, call the main loop proc, if it * exists. Packages (like Tk) can set it to start processing events at * this point. */ mainLoopProc(); Tcl_SetMainLoop(NULL); } if (is.commandPtr != NULL) { Tcl_DecrRefCount(is.commandPtr); } /* * Rather than calling exit, invoke the "exit" command so that users can * replace "exit" with some other command to do additional cleanup on * exit. The Tcl_EvalObjEx call should never return. */ if (!Tcl_InterpDeleted(interp) && !Tcl_LimitExceeded(interp)) { Tcl_Obj *cmd = Tcl_ObjPrintf("exit %d", exitCode); Tcl_IncrRefCount(cmd); Tcl_EvalObjEx(interp, cmd, TCL_EVAL_GLOBAL); Tcl_DecrRefCount(cmd); } /* * If Tcl_EvalObjEx returns, trying to eval [exit], something unusual is * happening. Maybe interp has been deleted; maybe [exit] was redefined, * maybe we've blown up because of an exceeded limit. We still want to * cleanup and exit. */ Tcl_Exit(exitCode); } #if (TCL_MAJOR_VERSION == 8) && !defined(UNICODE) #undef Tcl_Main extern DLLEXPORT void Tcl_Main( int argc, /* Number of arguments. */ char **argv, /* Array of argument strings. */ Tcl_AppInitProc *appInitProc) /* Application-specific initialization * function to call after most initialization * but before starting to execute commands. */ { Tcl_MainEx(argc, argv, appInitProc, Tcl_CreateInterp()); } #endif /* TCL_MAJOR_VERSION == 8 && !UNICODE */ #ifndef TCL_ASCII_MAIN /* *--------------------------------------------------------------- * * Tcl_SetMainLoop -- * * Sets an alternative main loop function. * * Results: * None. * * Side effects: * This function will be called before Tcl exits, allowing for the * creation of an event loop. * *--------------------------------------------------------------- */ void Tcl_SetMainLoop( Tcl_MainLoopProc *proc) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); tsdPtr->mainLoopProc = proc; } /* *--------------------------------------------------------------- * * TclGetMainLoop -- * * Returns the current alternative main loop function. * * Results: * Returns the previously defined main loop function, or NULL to indicate * that no such function has been installed and standard tclsh behaviour * (i.e., exit once the script is evaluated if not interactive) is * requested.. * * Side effects: * None (other than possible creation of this file's TSD block). * *--------------------------------------------------------------- */ Tcl_MainLoopProc * TclGetMainLoop(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); return tsdPtr->mainLoopProc; } /* *---------------------------------------------------------------------- * * TclFullFinalizationRequested -- * * This function returns true when either -DPURIFY is specified, or the * environment variable TCL_FINALIZE_ON_EXIT is set and not "0". This * predicate is called at places affecting the exit sequence, so that the * default behavior is a fast and deadlock-free exit, and the modified * behavior is a more thorough finalization for debugging purposes (leak * hunting etc). * * Results: * A boolean. * *---------------------------------------------------------------------- */ MODULE_SCOPE int TclFullFinalizationRequested(void) { #ifdef PURIFY return 1; #else const char *fin; Tcl_DString ds; int finalize = 0; fin = TclGetEnv("TCL_FINALIZE_ON_EXIT", &ds); finalize = ((fin != NULL) && strcmp(fin, "0")); if (fin != NULL) { Tcl_DStringFree(&ds); } return finalize; #endif /* PURIFY */ } #endif /* !TCL_ASCII_MAIN */ /* *---------------------------------------------------------------------- * * StdinProc -- * * This function is invoked by the event dispatcher whenever standard * input becomes readable. It grabs the next line of input characters, * adds them to a command being assembled, and executes the command if * it's complete. * * Results: * None. * * Side effects: * Could be almost arbitrary, depending on the command that's typed. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static void StdinProc( ClientData clientData, /* The state of interactive cmd line */ int mask) /* Not used. */ { int code, length; InteractiveState *isPtr = clientData; Tcl_Channel chan = isPtr->input; Tcl_Obj *commandPtr = isPtr->commandPtr; Tcl_Interp *interp = isPtr->interp; if (Tcl_IsShared(commandPtr)) { Tcl_DecrRefCount(commandPtr); commandPtr = Tcl_DuplicateObj(commandPtr); Tcl_IncrRefCount(commandPtr); } length = Tcl_GetsObj(chan, commandPtr); if (length < 0) { if (Tcl_InputBlocked(chan)) { return; } if (isPtr->tty) { /* * Would be better to find a way to exit the mainLoop? Or perhaps * evaluate [exit]? Leaving as is for now due to compatibility * concerns. */ Tcl_Exit(0); } Tcl_DeleteChannelHandler(chan, StdinProc, isPtr); return; } if (Tcl_IsShared(commandPtr)) { Tcl_DecrRefCount(commandPtr); commandPtr = Tcl_DuplicateObj(commandPtr); Tcl_IncrRefCount(commandPtr); } Tcl_AppendToObj(commandPtr, "\n", 1); if (!TclObjCommandComplete(commandPtr)) { isPtr->prompt = PROMPT_CONTINUE; goto prompt; } isPtr->prompt = PROMPT_START; Tcl_GetStringFromObj(commandPtr, &length); Tcl_SetObjLength(commandPtr, --length); /* * Disable the stdin channel handler while evaluating the command; * otherwise if the command re-enters the event loop we might process * commands from stdin before the current command is finished. Among other * things, this will trash the text of the command being evaluated. */ Tcl_CreateChannelHandler(chan, 0, StdinProc, isPtr); code = Tcl_RecordAndEvalObj(interp, commandPtr, TCL_EVAL_GLOBAL); isPtr->input = chan = Tcl_GetStdChannel(TCL_STDIN); Tcl_DecrRefCount(commandPtr); isPtr->commandPtr = commandPtr = Tcl_NewObj(); Tcl_IncrRefCount(commandPtr); if (chan != NULL) { Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc, isPtr); } if (code != TCL_OK) { chan = Tcl_GetStdChannel(TCL_STDERR); if (chan != NULL) { Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); Tcl_WriteChars(chan, "\n", 1); } } else if (isPtr->tty) { Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); chan = Tcl_GetStdChannel(TCL_STDOUT); Tcl_IncrRefCount(resultPtr); Tcl_GetStringFromObj(resultPtr, &length); if ((length > 0) && (chan != NULL)) { Tcl_WriteObj(chan, resultPtr); Tcl_WriteChars(chan, "\n", 1); } Tcl_DecrRefCount(resultPtr); } /* * If a tty stdin is still around, output a prompt. */ prompt: if (isPtr->tty && (isPtr->input != NULL)) { Prompt(interp, isPtr); isPtr->input = Tcl_GetStdChannel(TCL_STDIN); } } /* *---------------------------------------------------------------------- * * Prompt -- * * Issue a prompt on standard output, or invoke a script to issue the * prompt. * * Results: * None. * * Side effects: * A prompt gets output, and a Tcl script may be evaluated in interp. * *---------------------------------------------------------------------- */ static void Prompt( Tcl_Interp *interp, /* Interpreter to use for prompting. */ InteractiveState *isPtr) /* InteractiveState. Filled with PROMPT_NONE * after a prompt is printed. */ { Tcl_Obj *promptCmdPtr; int code; Tcl_Channel chan; if (isPtr->prompt == PROMPT_NONE) { return; } promptCmdPtr = Tcl_GetVar2Ex(interp, (isPtr->prompt==PROMPT_CONTINUE ? "tcl_prompt2" : "tcl_prompt1"), NULL, TCL_GLOBAL_ONLY); if (Tcl_InterpDeleted(interp)) { return; } if (promptCmdPtr == NULL) { defaultPrompt: if (isPtr->prompt == PROMPT_START) { chan = Tcl_GetStdChannel(TCL_STDOUT); if (chan != NULL) { Tcl_WriteChars(chan, DEFAULT_PRIMARY_PROMPT, strlen(DEFAULT_PRIMARY_PROMPT)); } } } else { code = Tcl_EvalObjEx(interp, promptCmdPtr, TCL_EVAL_GLOBAL); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (script that generates prompt)"); chan = Tcl_GetStdChannel(TCL_STDERR); if (chan != NULL) { Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); Tcl_WriteChars(chan, "\n", 1); } goto defaultPrompt; } } chan = Tcl_GetStdChannel(TCL_STDOUT); if (chan != NULL) { Tcl_Flush(chan); } isPtr->prompt = PROMPT_NONE; } /* *---------------------------------------------------------------------- * * FreeMainInterp -- * * Exit handler used to cleanup the main interpreter and ancillary * startup script storage at exit. * *---------------------------------------------------------------------- */ static void FreeMainInterp( ClientData clientData) { Tcl_Interp *interp = clientData; /*if (TclInExit()) return;*/ if (!Tcl_InterpDeleted(interp)) { Tcl_DeleteInterp(interp); } Tcl_SetStartupScript(NULL, NULL); Tcl_Release(interp); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclZlib.c0000644000175000017500000031405312663660066014761 0ustar sergeisergei/* * tclZlib.c -- * * This file provides the interface to the Zlib library. * * Copyright (C) 2004-2005 Pascal Scheffers * Copyright (C) 2005 Unitas Software B.V. * Copyright (c) 2008-2012 Donal K. Fellows * * Parts written by Jean-Claude Wippler, as part of Tclkit, placed in the * public domain March 2003. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #ifdef HAVE_ZLIB #include #include "tclIO.h" /* * The version of the zlib "package" that this implements. Note that this * thoroughly supersedes the versions included with tclkit, which are "1.1", * so this is at least "2.0" (there's no general *commitment* to have the same * interface, even if that is mostly true). */ #define TCL_ZLIB_VERSION "2.0.1" /* * Magic flags used with wbits fields to indicate that we're handling the gzip * format or automatic detection of format. Putting it here is slightly less * gross! */ #define WBITS_RAW (-MAX_WBITS) #define WBITS_ZLIB (MAX_WBITS) #define WBITS_GZIP (MAX_WBITS | 16) #define WBITS_AUTODETECT (MAX_WBITS | 32) /* * Structure used for handling gzip headers that are generated from a * dictionary. It comprises the header structure itself plus some working * space that it is very convenient to have attached. */ #define MAX_COMMENT_LEN 256 typedef struct { gz_header header; char nativeFilenameBuf[MAXPATHLEN]; char nativeCommentBuf[MAX_COMMENT_LEN]; } GzipHeader; /* * Structure used for the Tcl_ZlibStream* commands and [zlib stream ...] */ typedef struct { Tcl_Interp *interp; z_stream stream; /* The interface to the zlib library. */ int streamEnd; /* If we've got to end-of-stream. */ Tcl_Obj *inData, *outData; /* Input / output buffers (lists) */ Tcl_Obj *currentInput; /* Pointer to what is currently being * inflated. */ int outPos; int mode; /* Either TCL_ZLIB_STREAM_DEFLATE or * TCL_ZLIB_STREAM_INFLATE. */ int format; /* Flags from the TCL_ZLIB_FORMAT_* */ int level; /* Default 5, 0-9 */ int flush; /* Stores the flush param for deferred the * decompression. */ int wbits; /* The encoded compression mode, so we can * restart the stream if necessary. */ Tcl_Command cmd; /* Token for the associated Tcl command. */ Tcl_Obj *compDictObj; /* Byte-array object containing compression * dictionary (not dictObj!) to use if * necessary. */ int flags; /* Miscellaneous flag bits. */ GzipHeader *gzHeaderPtr; /* If we've allocated a gzip header * structure. */ } ZlibStreamHandle; #define DICT_TO_SET 0x1 /* If we need to set a compression dictionary * in the low-level engine at the next * opportunity. */ /* * Macros to make it clearer in some of the twiddlier accesses what is * happening. */ #define IsRawStream(zshPtr) ((zshPtr)->format == TCL_ZLIB_FORMAT_RAW) #define HaveDictToSet(zshPtr) ((zshPtr)->flags & DICT_TO_SET) #define DictWasSet(zshPtr) ((zshPtr)->flags |= ~DICT_TO_SET) /* * Structure used for stacked channel compression and decompression. */ typedef struct { Tcl_Channel chan; /* Reference to the channel itself. */ Tcl_Channel parent; /* The underlying source and sink of bytes. */ int flags; /* General flag bits, see below... */ int mode; /* Either the value TCL_ZLIB_STREAM_DEFLATE * for compression on output, or * TCL_ZLIB_STREAM_INFLATE for decompression * on input. */ int format; /* What format of data is going on the wire. * Needed so that the correct [fconfigure] * options can be enabled. */ int readAheadLimit; /* The maximum number of bytes to read from * the underlying stream in one go. */ z_stream inStream; /* Structure used by zlib for decompression of * input. */ z_stream outStream; /* Structure used by zlib for compression of * output. */ char *inBuffer, *outBuffer; /* Working buffers. */ int inAllocated, outAllocated; /* Sizes of working buffers. */ GzipHeader inHeader; /* Header read from input stream, when * decompressing a gzip stream. */ GzipHeader outHeader; /* Header to write to an output stream, when * compressing a gzip stream. */ Tcl_TimerToken timer; /* Timer used for keeping events fresh. */ Tcl_DString decompressed; /* Buffer for decompression results. */ Tcl_Obj *compDictObj; /* Byte-array object containing compression * dictionary (not dictObj!) to use if * necessary. */ } ZlibChannelData; /* * Value bits for the flags field. Definitions are: * ASYNC - Whether this is an asynchronous channel. * IN_HEADER - Whether the inHeader field has been registered with * the input compressor. * OUT_HEADER - Whether the outputHeader field has been registered * with the output decompressor. */ #define ASYNC 0x1 #define IN_HEADER 0x2 #define OUT_HEADER 0x4 /* * Size of buffers allocated by default, and the range it can be set to. The * same sorts of values apply to streams, except with different limits (they * permit byte-level activity). Channels always use bytes unless told to use * larger buffers. */ #define DEFAULT_BUFFER_SIZE 4096 #define MIN_NONSTREAM_BUFFER_SIZE 16 #define MAX_BUFFER_SIZE 65536 /* * Prototypes for private procedures defined later in this file: */ static Tcl_CmdDeleteProc ZlibStreamCmdDelete; static Tcl_DriverBlockModeProc ZlibTransformBlockMode; static Tcl_DriverCloseProc ZlibTransformClose; static Tcl_DriverGetHandleProc ZlibTransformGetHandle; static Tcl_DriverGetOptionProc ZlibTransformGetOption; static Tcl_DriverHandlerProc ZlibTransformEventHandler; static Tcl_DriverInputProc ZlibTransformInput; static Tcl_DriverOutputProc ZlibTransformOutput; static Tcl_DriverSetOptionProc ZlibTransformSetOption; static Tcl_DriverWatchProc ZlibTransformWatch; static Tcl_ObjCmdProc ZlibCmd; static Tcl_ObjCmdProc ZlibStreamCmd; static Tcl_ObjCmdProc ZlibStreamAddCmd; static Tcl_ObjCmdProc ZlibStreamHeaderCmd; static Tcl_ObjCmdProc ZlibStreamPutCmd; static void ConvertError(Tcl_Interp *interp, int code, uLong adler); static Tcl_Obj * ConvertErrorToList(int code, uLong adler); static void ExtractHeader(gz_header *headerPtr, Tcl_Obj *dictObj); static int GenerateHeader(Tcl_Interp *interp, Tcl_Obj *dictObj, GzipHeader *headerPtr, int *extraSizePtr); static int ZlibPushSubcmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static inline int ResultCopy(ZlibChannelData *cd, char *buf, int toRead); static int ResultGenerate(ZlibChannelData *cd, int n, int flush, int *errorCodePtr); static Tcl_Channel ZlibStackChannelTransform(Tcl_Interp *interp, int mode, int format, int level, int limit, Tcl_Channel channel, Tcl_Obj *gzipHeaderDictPtr, Tcl_Obj *compDictObj); static void ZlibStreamCleanup(ZlibStreamHandle *zshPtr); static int ZlibStreamSubcmd(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static inline void ZlibTransformEventTimerKill(ZlibChannelData *cd); static void ZlibTransformTimerRun(ClientData clientData); /* * Type of zlib-based compressing and decompressing channels. */ static const Tcl_ChannelType zlibChannelType = { "zlib", TCL_CHANNEL_VERSION_3, ZlibTransformClose, ZlibTransformInput, ZlibTransformOutput, NULL, /* seekProc */ ZlibTransformSetOption, ZlibTransformGetOption, ZlibTransformWatch, ZlibTransformGetHandle, NULL, /* close2Proc */ ZlibTransformBlockMode, NULL, /* flushProc */ ZlibTransformEventHandler, NULL, /* wideSeekProc */ NULL, NULL }; /* *---------------------------------------------------------------------- * * ConvertError -- * * Utility function for converting a zlib error into a Tcl error. * * Results: * None. * * Side effects: * Updates the interpreter result and errorcode. * *---------------------------------------------------------------------- */ static void ConvertError( Tcl_Interp *interp, /* Interpreter to store the error in. May be * NULL, in which case nothing happens. */ int code, /* The zlib error code. */ uLong adler) /* The checksum expected (for Z_NEED_DICT) */ { const char *codeStr, *codeStr2 = NULL; char codeStrBuf[TCL_INTEGER_SPACE]; if (interp == NULL) { return; } switch (code) { /* * Firstly, the case that is *different* because it's really coming * from the OS and is just being reported via zlib. It should be * really uncommon because Tcl handles all I/O rather than delegating * it to zlib, but proving it can't happen is hard. */ case Z_ERRNO: Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_PosixError(interp),-1)); return; /* * Normal errors/conditions, some of which have additional detail and * some which don't. (This is not defined by array lookup because zlib * error codes are sometimes negative.) */ case Z_STREAM_ERROR: codeStr = "STREAM"; break; case Z_DATA_ERROR: codeStr = "DATA"; break; case Z_MEM_ERROR: codeStr = "MEM"; break; case Z_BUF_ERROR: codeStr = "BUF"; break; case Z_VERSION_ERROR: codeStr = "VERSION"; break; case Z_NEED_DICT: codeStr = "NEED_DICT"; codeStr2 = codeStrBuf; sprintf(codeStrBuf, "%lu", adler); break; /* * These should _not_ happen! This function is for dealing with error * cases, not non-errors! */ case Z_OK: Tcl_Panic("unexpected zlib result in error handler: Z_OK"); case Z_STREAM_END: Tcl_Panic("unexpected zlib result in error handler: Z_STREAM_END"); /* * Anything else is bad news; it's unexpected. Convert to generic * error. */ default: codeStr = "UNKNOWN"; codeStr2 = codeStrBuf; sprintf(codeStrBuf, "%d", code); break; } Tcl_SetObjResult(interp, Tcl_NewStringObj(zError(code), -1)); /* * Tricky point! We might pass NULL twice here (and will when the error * type is known). */ Tcl_SetErrorCode(interp, "TCL", "ZLIB", codeStr, codeStr2, NULL); } static Tcl_Obj * ConvertErrorToList( int code, /* The zlib error code. */ uLong adler) /* The checksum expected (for Z_NEED_DICT) */ { Tcl_Obj *objv[4]; TclNewLiteralStringObj(objv[0], "TCL"); TclNewLiteralStringObj(objv[1], "ZLIB"); switch (code) { case Z_STREAM_ERROR: TclNewLiteralStringObj(objv[2], "STREAM"); return Tcl_NewListObj(3, objv); case Z_DATA_ERROR: TclNewLiteralStringObj(objv[2], "DATA"); return Tcl_NewListObj(3, objv); case Z_MEM_ERROR: TclNewLiteralStringObj(objv[2], "MEM"); return Tcl_NewListObj(3, objv); case Z_BUF_ERROR: TclNewLiteralStringObj(objv[2], "BUF"); return Tcl_NewListObj(3, objv); case Z_VERSION_ERROR: TclNewLiteralStringObj(objv[2], "VERSION"); return Tcl_NewListObj(3, objv); case Z_ERRNO: TclNewLiteralStringObj(objv[2], "POSIX"); objv[3] = Tcl_NewStringObj(Tcl_ErrnoId(), -1); return Tcl_NewListObj(4, objv); case Z_NEED_DICT: TclNewLiteralStringObj(objv[2], "NEED_DICT"); objv[3] = Tcl_NewWideIntObj((Tcl_WideInt) adler); return Tcl_NewListObj(4, objv); /* * These should _not_ happen! This function is for dealing with error * cases, not non-errors! */ case Z_OK: Tcl_Panic("unexpected zlib result in error handler: Z_OK"); case Z_STREAM_END: Tcl_Panic("unexpected zlib result in error handler: Z_STREAM_END"); /* * Catch-all. Should be unreachable because all cases are already * listed above. */ default: TclNewLiteralStringObj(objv[2], "UNKNOWN"); TclNewIntObj(objv[3], code); return Tcl_NewListObj(4, objv); } } /* *---------------------------------------------------------------------- * * GenerateHeader -- * * Function for creating a gzip header from the contents of a dictionary * (as described in the documentation). GetValue is a helper function. * * Results: * A Tcl result code. * * Side effects: * Updates the fields of the given gz_header structure. Adds amount of * extra space required for the header to the variable referenced by the * extraSizePtr argument. * *---------------------------------------------------------------------- */ static inline int GetValue( Tcl_Interp *interp, Tcl_Obj *dictObj, const char *nameStr, Tcl_Obj **valuePtrPtr) { Tcl_Obj *name = Tcl_NewStringObj(nameStr, -1); int result = Tcl_DictObjGet(interp, dictObj, name, valuePtrPtr); TclDecrRefCount(name); return result; } static int GenerateHeader( Tcl_Interp *interp, /* Where to put error messages. */ Tcl_Obj *dictObj, /* The dictionary whose contents are to be * parsed. */ GzipHeader *headerPtr, /* Where to store the parsed-out values. */ int *extraSizePtr) /* Variable to add the length of header * strings (filename, comment) to. */ { Tcl_Obj *value; int len, result = TCL_ERROR; const char *valueStr; Tcl_Encoding latin1enc; static const char *const types[] = { "binary", "text" }; /* * RFC 1952 says that header strings are in ISO 8859-1 (LATIN-1). */ latin1enc = Tcl_GetEncoding(NULL, "iso8859-1"); if (latin1enc == NULL) { Tcl_Panic("no latin-1 encoding"); } if (GetValue(interp, dictObj, "comment", &value) != TCL_OK) { goto error; } else if (value != NULL) { valueStr = Tcl_GetStringFromObj(value, &len); Tcl_UtfToExternal(NULL, latin1enc, valueStr, len, 0, NULL, headerPtr->nativeCommentBuf, MAX_COMMENT_LEN-1, NULL, &len, NULL); headerPtr->nativeCommentBuf[len] = '\0'; headerPtr->header.comment = (Bytef *) headerPtr->nativeCommentBuf; if (extraSizePtr != NULL) { *extraSizePtr += len; } } if (GetValue(interp, dictObj, "crc", &value) != TCL_OK) { goto error; } else if (value != NULL && Tcl_GetBooleanFromObj(interp, value, &headerPtr->header.hcrc)) { goto error; } if (GetValue(interp, dictObj, "filename", &value) != TCL_OK) { goto error; } else if (value != NULL) { valueStr = Tcl_GetStringFromObj(value, &len); Tcl_UtfToExternal(NULL, latin1enc, valueStr, len, 0, NULL, headerPtr->nativeFilenameBuf, MAXPATHLEN-1, NULL, &len, NULL); headerPtr->nativeFilenameBuf[len] = '\0'; headerPtr->header.name = (Bytef *) headerPtr->nativeFilenameBuf; if (extraSizePtr != NULL) { *extraSizePtr += len; } } if (GetValue(interp, dictObj, "os", &value) != TCL_OK) { goto error; } else if (value != NULL && Tcl_GetIntFromObj(interp, value, &headerPtr->header.os) != TCL_OK) { goto error; } /* * Ignore the 'size' field, since that is controlled by the size of the * input data. */ if (GetValue(interp, dictObj, "time", &value) != TCL_OK) { goto error; } else if (value != NULL && Tcl_GetLongFromObj(interp, value, (long *) &headerPtr->header.time) != TCL_OK) { goto error; } if (GetValue(interp, dictObj, "type", &value) != TCL_OK) { goto error; } else if (value != NULL && Tcl_GetIndexFromObj(interp, value, types, "type", TCL_EXACT, &headerPtr->header.text) != TCL_OK) { goto error; } result = TCL_OK; error: Tcl_FreeEncoding(latin1enc); return result; } /* *---------------------------------------------------------------------- * * ExtractHeader -- * * Take the values out of a gzip header and store them in a dictionary. * SetValue is a helper macro. * * Results: * None. * * Side effects: * Updates the dictionary, which must be writable (i.e. refCount < 2). * *---------------------------------------------------------------------- */ #define SetValue(dictObj, key, value) \ Tcl_DictObjPut(NULL, (dictObj), Tcl_NewStringObj((key), -1), (value)) static void ExtractHeader( gz_header *headerPtr, /* The gzip header to extract from. */ Tcl_Obj *dictObj) /* The dictionary to store in. */ { Tcl_Encoding latin1enc = NULL; Tcl_DString tmp; if (headerPtr->comment != Z_NULL) { if (latin1enc == NULL) { /* * RFC 1952 says that header strings are in ISO 8859-1 (LATIN-1). */ latin1enc = Tcl_GetEncoding(NULL, "iso8859-1"); if (latin1enc == NULL) { Tcl_Panic("no latin-1 encoding"); } } Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->comment, -1, &tmp); SetValue(dictObj, "comment", TclDStringToObj(&tmp)); } SetValue(dictObj, "crc", Tcl_NewBooleanObj(headerPtr->hcrc)); if (headerPtr->name != Z_NULL) { if (latin1enc == NULL) { /* * RFC 1952 says that header strings are in ISO 8859-1 (LATIN-1). */ latin1enc = Tcl_GetEncoding(NULL, "iso8859-1"); if (latin1enc == NULL) { Tcl_Panic("no latin-1 encoding"); } } Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->name, -1, &tmp); SetValue(dictObj, "filename", TclDStringToObj(&tmp)); } if (headerPtr->os != 255) { SetValue(dictObj, "os", Tcl_NewIntObj(headerPtr->os)); } if (headerPtr->time != 0 /* magic - no time */) { SetValue(dictObj, "time", Tcl_NewLongObj((long) headerPtr->time)); } if (headerPtr->text != Z_UNKNOWN) { SetValue(dictObj, "type", Tcl_NewStringObj(headerPtr->text ? "text" : "binary", -1)); } if (latin1enc != NULL) { Tcl_FreeEncoding(latin1enc); } } static int SetInflateDictionary( z_streamp strm, Tcl_Obj *compDictObj) { if (compDictObj != NULL) { int length; unsigned char *bytes = Tcl_GetByteArrayFromObj(compDictObj, &length); return inflateSetDictionary(strm, bytes, (unsigned) length); } return Z_OK; } static int SetDeflateDictionary( z_streamp strm, Tcl_Obj *compDictObj) { if (compDictObj != NULL) { int length; unsigned char *bytes = Tcl_GetByteArrayFromObj(compDictObj, &length); return deflateSetDictionary(strm, bytes, (unsigned) length); } return Z_OK; } /* *---------------------------------------------------------------------- * * Tcl_ZlibStreamInit -- * * This command initializes a (de)compression context/handle for * (de)compressing data in chunks. * * Results: * A standard Tcl result. * * Side effects: * The variable pointed to by zshandlePtr is initialised and memory * allocated for internal state. Additionally, if interp is not null, a * Tcl command is created and its name placed in the interp result obj. * * Note: * At least one of interp and zshandlePtr should be non-NULL or the * reference to the stream will be completely lost. * *---------------------------------------------------------------------- */ int Tcl_ZlibStreamInit( Tcl_Interp *interp, int mode, /* Either TCL_ZLIB_STREAM_INFLATE or * TCL_ZLIB_STREAM_DEFLATE. */ int format, /* Flags from the TCL_ZLIB_FORMAT_* set. */ int level, /* 0-9 or TCL_ZLIB_COMPRESS_DEFAULT. */ Tcl_Obj *dictObj, /* Dictionary containing headers for gzip. */ Tcl_ZlibStream *zshandlePtr) { int wbits = 0; int e; ZlibStreamHandle *zshPtr = NULL; Tcl_DString cmdname; GzipHeader *gzHeaderPtr = NULL; switch (mode) { case TCL_ZLIB_STREAM_DEFLATE: /* * Compressed format is specified by the wbits parameter. See zlib.h * for details. */ switch (format) { case TCL_ZLIB_FORMAT_RAW: wbits = WBITS_RAW; break; case TCL_ZLIB_FORMAT_GZIP: wbits = WBITS_GZIP; if (dictObj) { gzHeaderPtr = ckalloc(sizeof(GzipHeader)); memset(gzHeaderPtr, 0, sizeof(GzipHeader)); if (GenerateHeader(interp, dictObj, gzHeaderPtr, NULL) != TCL_OK) { ckfree(gzHeaderPtr); return TCL_ERROR; } } break; case TCL_ZLIB_FORMAT_ZLIB: wbits = WBITS_ZLIB; break; default: Tcl_Panic("incorrect zlib data format, must be " "TCL_ZLIB_FORMAT_ZLIB, TCL_ZLIB_FORMAT_GZIP or " "TCL_ZLIB_FORMAT_RAW"); } if (level < -1 || level > 9) { Tcl_Panic("compression level should be between 0 (no compression)" " and 9 (best compression) or -1 for default compression " "level"); } break; case TCL_ZLIB_STREAM_INFLATE: /* * wbits are the same as DEFLATE, but FORMAT_AUTO is valid too. */ switch (format) { case TCL_ZLIB_FORMAT_RAW: wbits = WBITS_RAW; break; case TCL_ZLIB_FORMAT_GZIP: wbits = WBITS_GZIP; gzHeaderPtr = ckalloc(sizeof(GzipHeader)); memset(gzHeaderPtr, 0, sizeof(GzipHeader)); gzHeaderPtr->header.name = (Bytef *) gzHeaderPtr->nativeFilenameBuf; gzHeaderPtr->header.name_max = MAXPATHLEN - 1; gzHeaderPtr->header.comment = (Bytef *) gzHeaderPtr->nativeCommentBuf; gzHeaderPtr->header.name_max = MAX_COMMENT_LEN - 1; break; case TCL_ZLIB_FORMAT_ZLIB: wbits = WBITS_ZLIB; break; case TCL_ZLIB_FORMAT_AUTO: wbits = WBITS_AUTODETECT; break; default: Tcl_Panic("incorrect zlib data format, must be " "TCL_ZLIB_FORMAT_ZLIB, TCL_ZLIB_FORMAT_GZIP, " "TCL_ZLIB_FORMAT_RAW or TCL_ZLIB_FORMAT_AUTO"); } break; default: Tcl_Panic("bad mode, must be TCL_ZLIB_STREAM_DEFLATE or" " TCL_ZLIB_STREAM_INFLATE"); } zshPtr = ckalloc(sizeof(ZlibStreamHandle)); zshPtr->interp = interp; zshPtr->mode = mode; zshPtr->format = format; zshPtr->level = level; zshPtr->wbits = wbits; zshPtr->currentInput = NULL; zshPtr->streamEnd = 0; zshPtr->compDictObj = NULL; zshPtr->flags = 0; zshPtr->gzHeaderPtr = gzHeaderPtr; memset(&zshPtr->stream, 0, sizeof(z_stream)); zshPtr->stream.adler = 1; /* * No output buffer available yet */ if (mode == TCL_ZLIB_STREAM_DEFLATE) { e = deflateInit2(&zshPtr->stream, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); if (e == Z_OK && zshPtr->gzHeaderPtr) { e = deflateSetHeader(&zshPtr->stream, &zshPtr->gzHeaderPtr->header); } } else { e = inflateInit2(&zshPtr->stream, wbits); if (e == Z_OK && zshPtr->gzHeaderPtr) { e = inflateGetHeader(&zshPtr->stream, &zshPtr->gzHeaderPtr->header); } } if (e != Z_OK) { ConvertError(interp, e, zshPtr->stream.adler); goto error; } /* * I could do all this in C, but this is easier. */ if (interp != NULL) { if (Tcl_EvalEx(interp, "::incr ::tcl::zlib::cmdcounter", -1, 0) != TCL_OK) { goto error; } Tcl_DStringInit(&cmdname); TclDStringAppendLiteral(&cmdname, "::tcl::zlib::streamcmd_"); TclDStringAppendObj(&cmdname, Tcl_GetObjResult(interp)); if (Tcl_FindCommand(interp, Tcl_DStringValue(&cmdname), NULL, 0) != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "BUG: Stream command name already exists", -1)); Tcl_SetErrorCode(interp, "TCL", "BUG", "EXISTING_CMD", NULL); Tcl_DStringFree(&cmdname); goto error; } Tcl_ResetResult(interp); /* * Create the command. */ zshPtr->cmd = Tcl_CreateObjCommand(interp, Tcl_DStringValue(&cmdname), ZlibStreamCmd, zshPtr, ZlibStreamCmdDelete); Tcl_DStringFree(&cmdname); if (zshPtr->cmd == NULL) { goto error; } } else { zshPtr->cmd = NULL; } /* * Prepare the buffers for use. */ zshPtr->inData = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(zshPtr->inData); zshPtr->outData = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(zshPtr->outData); zshPtr->outPos = 0; /* * Now set the variable pointed to by *zshandlePtr to the pointer to the * zsh struct. */ if (zshandlePtr) { *zshandlePtr = (Tcl_ZlibStream) zshPtr; } return TCL_OK; error: if (zshPtr->compDictObj) { Tcl_DecrRefCount(zshPtr->compDictObj); } if (zshPtr->gzHeaderPtr) { ckfree(zshPtr->gzHeaderPtr); } ckfree(zshPtr); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * ZlibStreamCmdDelete -- * * This is the delete command which Tcl invokes when a zlibstream command * is deleted from the interpreter (on stream close, usually). * * Results: * None * * Side effects: * Invalidates the zlib stream handle as obtained from Tcl_ZlibStreamInit * *---------------------------------------------------------------------- */ static void ZlibStreamCmdDelete( ClientData cd) { ZlibStreamHandle *zshPtr = cd; zshPtr->cmd = NULL; ZlibStreamCleanup(zshPtr); } /* *---------------------------------------------------------------------- * * Tcl_ZlibStreamClose -- * * This procedure must be called after (de)compression is done to ensure * memory is freed and the command is deleted from the interpreter (if * any). * * Results: * A standard Tcl result. * * Side effects: * Invalidates the zlib stream handle as obtained from Tcl_ZlibStreamInit * *---------------------------------------------------------------------- */ int Tcl_ZlibStreamClose( Tcl_ZlibStream zshandle) /* As obtained from Tcl_ZlibStreamInit. */ { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; /* * If the interp is set, deleting the command will trigger * ZlibStreamCleanup in ZlibStreamCmdDelete. If no interp is set, call * ZlibStreamCleanup directly. */ if (zshPtr->interp && zshPtr->cmd) { Tcl_DeleteCommandFromToken(zshPtr->interp, zshPtr->cmd); } else { ZlibStreamCleanup(zshPtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * ZlibStreamCleanup -- * * This procedure is called by either Tcl_ZlibStreamClose or * ZlibStreamCmdDelete to cleanup the stream context. * * Results: * None * * Side effects: * Invalidates the zlib stream handle. * *---------------------------------------------------------------------- */ void ZlibStreamCleanup( ZlibStreamHandle *zshPtr) { if (!zshPtr->streamEnd) { if (zshPtr->mode == TCL_ZLIB_STREAM_DEFLATE) { deflateEnd(&zshPtr->stream); } else { inflateEnd(&zshPtr->stream); } } if (zshPtr->inData) { Tcl_DecrRefCount(zshPtr->inData); } if (zshPtr->outData) { Tcl_DecrRefCount(zshPtr->outData); } if (zshPtr->currentInput) { Tcl_DecrRefCount(zshPtr->currentInput); } if (zshPtr->compDictObj) { Tcl_DecrRefCount(zshPtr->compDictObj); } if (zshPtr->gzHeaderPtr) { ckfree(zshPtr->gzHeaderPtr); } ckfree(zshPtr); } /* *---------------------------------------------------------------------- * * Tcl_ZlibStreamReset -- * * This procedure will reinitialize an existing stream handle. * * Results: * A standard Tcl result. * * Side effects: * Any data left in the (de)compression buffer is lost. * *---------------------------------------------------------------------- */ int Tcl_ZlibStreamReset( Tcl_ZlibStream zshandle) /* As obtained from Tcl_ZlibStreamInit */ { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; int e; if (!zshPtr->streamEnd) { if (zshPtr->mode == TCL_ZLIB_STREAM_DEFLATE) { deflateEnd(&zshPtr->stream); } else { inflateEnd(&zshPtr->stream); } } Tcl_SetByteArrayLength(zshPtr->inData, 0); Tcl_SetByteArrayLength(zshPtr->outData, 0); if (zshPtr->currentInput) { Tcl_DecrRefCount(zshPtr->currentInput); zshPtr->currentInput = NULL; } zshPtr->outPos = 0; zshPtr->streamEnd = 0; memset(&zshPtr->stream, 0, sizeof(z_stream)); /* * No output buffer available yet. */ if (zshPtr->mode == TCL_ZLIB_STREAM_DEFLATE) { e = deflateInit2(&zshPtr->stream, zshPtr->level, Z_DEFLATED, zshPtr->wbits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); if (e == Z_OK && HaveDictToSet(zshPtr)) { e = SetDeflateDictionary(&zshPtr->stream, zshPtr->compDictObj); if (e == Z_OK) { DictWasSet(zshPtr); } } } else { e = inflateInit2(&zshPtr->stream, zshPtr->wbits); if (IsRawStream(zshPtr) && HaveDictToSet(zshPtr) && e == Z_OK) { e = SetInflateDictionary(&zshPtr->stream, zshPtr->compDictObj); if (e == Z_OK) { DictWasSet(zshPtr); } } } if (e != Z_OK) { ConvertError(zshPtr->interp, e, zshPtr->stream.adler); /* TODO:cleanup */ return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ZlibStreamGetCommandName -- * * This procedure will return the command name associated with the * stream. * * Results: * A Tcl_Obj with the name of the Tcl command or NULL if no command is * associated with the stream. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_ZlibStreamGetCommandName( Tcl_ZlibStream zshandle) /* As obtained from Tcl_ZlibStreamInit */ { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; Tcl_Obj *objPtr; if (!zshPtr->interp) { return NULL; } TclNewObj(objPtr); Tcl_GetCommandFullName(zshPtr->interp, zshPtr->cmd, objPtr); return objPtr; } /* *---------------------------------------------------------------------- * * Tcl_ZlibStreamEof -- * * This procedure This function returns 0 or 1 depending on the state of * the (de)compressor. For decompression, eof is reached when the entire * compressed stream has been decompressed. For compression, eof is * reached when the stream has been flushed with TCL_ZLIB_FINALIZE. * * Results: * Integer. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_ZlibStreamEof( Tcl_ZlibStream zshandle) /* As obtained from Tcl_ZlibStreamInit */ { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; return zshPtr->streamEnd; } /* *---------------------------------------------------------------------- * * Tcl_ZlibStreamChecksum -- * * Return the checksum of the uncompressed data seen so far by the * stream. * *---------------------------------------------------------------------- */ int Tcl_ZlibStreamChecksum( Tcl_ZlibStream zshandle) /* As obtained from Tcl_ZlibStreamInit */ { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; return zshPtr->stream.adler; } /* *---------------------------------------------------------------------- * * Tcl_ZlibStreamSetCompressionDictionary -- * * Sets the compression dictionary for a stream. This will be used as * appropriate for the next compression or decompression action performed * on the stream. * *---------------------------------------------------------------------- */ void Tcl_ZlibStreamSetCompressionDictionary( Tcl_ZlibStream zshandle, Tcl_Obj *compressionDictionaryObj) { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; if (compressionDictionaryObj != NULL) { if (Tcl_IsShared(compressionDictionaryObj)) { compressionDictionaryObj = Tcl_DuplicateObj(compressionDictionaryObj); } Tcl_IncrRefCount(compressionDictionaryObj); zshPtr->flags |= DICT_TO_SET; } else { zshPtr->flags &= ~DICT_TO_SET; } if (zshPtr->compDictObj != NULL) { Tcl_DecrRefCount(zshPtr->compDictObj); } zshPtr->compDictObj = compressionDictionaryObj; } /* *---------------------------------------------------------------------- * * Tcl_ZlibStreamPut -- * * Add data to the stream for compression or decompression from a * bytearray Tcl_Obj. * *---------------------------------------------------------------------- */ int Tcl_ZlibStreamPut( Tcl_ZlibStream zshandle, /* As obtained from Tcl_ZlibStreamInit */ Tcl_Obj *data, /* Data to compress/decompress */ int flush) /* TCL_ZLIB_NO_FLUSH, TCL_ZLIB_FLUSH, * TCL_ZLIB_FULLFLUSH, or TCL_ZLIB_FINALIZE */ { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; char *dataTmp = NULL; int e, size, outSize; Tcl_Obj *obj; if (zshPtr->streamEnd) { if (zshPtr->interp) { Tcl_SetObjResult(zshPtr->interp, Tcl_NewStringObj( "already past compressed stream end", -1)); Tcl_SetErrorCode(zshPtr->interp, "TCL", "ZIP", "CLOSED", NULL); } return TCL_ERROR; } if (zshPtr->mode == TCL_ZLIB_STREAM_DEFLATE) { zshPtr->stream.next_in = Tcl_GetByteArrayFromObj(data, &size); zshPtr->stream.avail_in = size; /* * Must not do a zero-length compress. [Bug 25842c161] */ if (size == 0) { return TCL_OK; } if (HaveDictToSet(zshPtr)) { e = SetDeflateDictionary(&zshPtr->stream, zshPtr->compDictObj); if (e != Z_OK) { if (zshPtr->interp) { ConvertError(zshPtr->interp, e, zshPtr->stream.adler); } return TCL_ERROR; } DictWasSet(zshPtr); } /* * Deflatebound doesn't seem to take various header sizes into * account, so we add 100 extra bytes. */ outSize = deflateBound(&zshPtr->stream, zshPtr->stream.avail_in)+100; zshPtr->stream.avail_out = outSize; dataTmp = ckalloc(zshPtr->stream.avail_out); zshPtr->stream.next_out = (Bytef *) dataTmp; e = deflate(&zshPtr->stream, flush); while (e == Z_BUF_ERROR) { /* * Output buffer too small to hold the data being generated; so * put a new buffer into place after saving the old generated * data to the outData list. */ obj = Tcl_NewByteArrayObj((unsigned char *) dataTmp, outSize); Tcl_ListObjAppendElement(NULL, zshPtr->outData, obj); if (outSize < 0xFFFF) { outSize = 0xFFFF; /* There may be *lots* of data left to * output... */ dataTmp = ckrealloc(dataTmp, outSize); } zshPtr->stream.avail_out = outSize; zshPtr->stream.next_out = (Bytef *) dataTmp; e = deflate(&zshPtr->stream, flush); } if (e != Z_OK && !(flush==Z_FINISH && e==Z_STREAM_END)) { if (zshPtr->interp) { ConvertError(zshPtr->interp, e, zshPtr->stream.adler); } return TCL_ERROR; } /* * And append the final data block. */ if (outSize - zshPtr->stream.avail_out > 0) { obj = Tcl_NewByteArrayObj((unsigned char *) dataTmp, outSize - zshPtr->stream.avail_out); /* * Now append the compressed data to the outData list. */ Tcl_ListObjAppendElement(NULL, zshPtr->outData, obj); } if (dataTmp) { ckfree(dataTmp); } } else { /* * This is easy. Just append to the inData list. */ Tcl_ListObjAppendElement(NULL, zshPtr->inData, data); /* * and we'll need the flush parameter for the Inflate call. */ zshPtr->flush = flush; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ZlibStreamGet -- * * Retrieve data (now compressed or decompressed) from the stream into a * bytearray Tcl_Obj. * *---------------------------------------------------------------------- */ int Tcl_ZlibStreamGet( Tcl_ZlibStream zshandle, /* As obtained from Tcl_ZlibStreamInit */ Tcl_Obj *data, /* A place to append the data. */ int count) /* Number of bytes to grab as a maximum, you * may get less! */ { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; int e, i, listLen, itemLen, dataPos = 0; Tcl_Obj *itemObj; unsigned char *dataPtr, *itemPtr; int existing; /* * Getting beyond the of stream, just return empty string. */ if (zshPtr->streamEnd) { return TCL_OK; } (void) Tcl_GetByteArrayFromObj(data, &existing); if (zshPtr->mode == TCL_ZLIB_STREAM_INFLATE) { if (count == -1) { /* * The only safe thing to do is restict to 65k. We might cause a * panic for out of memory if we just kept growing the buffer. */ count = MAX_BUFFER_SIZE; } /* * Prepare the place to store the data. */ dataPtr = Tcl_SetByteArrayLength(data, existing+count); dataPtr += existing; zshPtr->stream.next_out = dataPtr; zshPtr->stream.avail_out = count; if (zshPtr->stream.avail_in == 0) { /* * zlib will probably need more data to decompress. */ if (zshPtr->currentInput) { Tcl_DecrRefCount(zshPtr->currentInput); zshPtr->currentInput = NULL; } Tcl_ListObjLength(NULL, zshPtr->inData, &listLen); if (listLen > 0) { /* * There is more input available, get it from the list and * give it to zlib. At this point, the data must not be shared * since we require the bytearray representation to not vanish * under our feet. [Bug 3081008] */ Tcl_ListObjIndex(NULL, zshPtr->inData, 0, &itemObj); if (Tcl_IsShared(itemObj)) { itemObj = Tcl_DuplicateObj(itemObj); } itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen); Tcl_IncrRefCount(itemObj); zshPtr->currentInput = itemObj; zshPtr->stream.next_in = itemPtr; zshPtr->stream.avail_in = itemLen; /* * And remove it from the list */ Tcl_ListObjReplace(NULL, zshPtr->inData, 0, 1, 0, NULL); } } /* * When dealing with a raw stream, we set the dictionary here, once. * (You can't do it in response to getting Z_NEED_DATA as raw streams * don't ever issue that.) */ if (IsRawStream(zshPtr) && HaveDictToSet(zshPtr)) { e = SetInflateDictionary(&zshPtr->stream, zshPtr->compDictObj); if (e != Z_OK) { if (zshPtr->interp) { ConvertError(zshPtr->interp, e, zshPtr->stream.adler); } return TCL_ERROR; } DictWasSet(zshPtr); } e = inflate(&zshPtr->stream, zshPtr->flush); if (e == Z_NEED_DICT && HaveDictToSet(zshPtr)) { e = SetInflateDictionary(&zshPtr->stream, zshPtr->compDictObj); if (e == Z_OK) { DictWasSet(zshPtr); e = inflate(&zshPtr->stream, zshPtr->flush); } }; Tcl_ListObjLength(NULL, zshPtr->inData, &listLen); while ((zshPtr->stream.avail_out > 0) && (e == Z_OK || e == Z_BUF_ERROR) && (listLen > 0)) { /* * State: We have not satisfied the request yet and there may be * more to inflate. */ if (zshPtr->stream.avail_in > 0) { if (zshPtr->interp) { Tcl_SetObjResult(zshPtr->interp, Tcl_NewStringObj( "unexpected zlib internal state during" " decompression", -1)); Tcl_SetErrorCode(zshPtr->interp, "TCL", "ZIP", "STATE", NULL); } Tcl_SetByteArrayLength(data, existing); return TCL_ERROR; } if (zshPtr->currentInput) { Tcl_DecrRefCount(zshPtr->currentInput); zshPtr->currentInput = 0; } /* * Get the next block of data to go to inflate. At this point, the * data must not be shared since we require the bytearray * representation to not vanish under our feet. [Bug 3081008] */ Tcl_ListObjIndex(zshPtr->interp, zshPtr->inData, 0, &itemObj); if (Tcl_IsShared(itemObj)) { itemObj = Tcl_DuplicateObj(itemObj); } itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen); Tcl_IncrRefCount(itemObj); zshPtr->currentInput = itemObj; zshPtr->stream.next_in = itemPtr; zshPtr->stream.avail_in = itemLen; /* * Remove it from the list. */ Tcl_ListObjReplace(NULL, zshPtr->inData, 0, 1, 0, NULL); listLen--; /* * And call inflate again. */ do { e = inflate(&zshPtr->stream, zshPtr->flush); if (e != Z_NEED_DICT || !HaveDictToSet(zshPtr)) { break; } e = SetInflateDictionary(&zshPtr->stream,zshPtr->compDictObj); DictWasSet(zshPtr); } while (e == Z_OK); } if (zshPtr->stream.avail_out > 0) { Tcl_SetByteArrayLength(data, existing + count - zshPtr->stream.avail_out); } if (!(e==Z_OK || e==Z_STREAM_END || e==Z_BUF_ERROR)) { Tcl_SetByteArrayLength(data, existing); ConvertError(zshPtr->interp, e, zshPtr->stream.adler); return TCL_ERROR; } if (e == Z_STREAM_END) { zshPtr->streamEnd = 1; if (zshPtr->currentInput) { Tcl_DecrRefCount(zshPtr->currentInput); zshPtr->currentInput = 0; } inflateEnd(&zshPtr->stream); } } else { Tcl_ListObjLength(NULL, zshPtr->outData, &listLen); if (count == -1) { count = 0; for (i=0; ioutData, i, &itemObj); itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen); if (i == 0) { count += itemLen - zshPtr->outPos; } else { count += itemLen; } } } /* * Prepare the place to store the data. */ dataPtr = Tcl_SetByteArrayLength(data, existing + count); dataPtr += existing; while ((count > dataPos) && (Tcl_ListObjLength(NULL, zshPtr->outData, &listLen) == TCL_OK) && (listLen > 0)) { /* * Get the next chunk off our list of chunks and grab the data out * of it. */ Tcl_ListObjIndex(NULL, zshPtr->outData, 0, &itemObj); itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen); if (itemLen-zshPtr->outPos >= count-dataPos) { unsigned len = count - dataPos; memcpy(dataPtr + dataPos, itemPtr + zshPtr->outPos, len); zshPtr->outPos += len; dataPos += len; if (zshPtr->outPos == itemLen) { zshPtr->outPos = 0; } } else { unsigned len = itemLen - zshPtr->outPos; memcpy(dataPtr + dataPos, itemPtr + zshPtr->outPos, len); dataPos += len; zshPtr->outPos = 0; } if (zshPtr->outPos == 0) { Tcl_ListObjReplace(NULL, zshPtr->outData, 0, 1, 0, NULL); listLen--; } } Tcl_SetByteArrayLength(data, existing + dataPos); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ZlibDeflate -- * * Compress the contents of Tcl_Obj *data with compression level in * output format, producing the compressed data in the interpreter * result. * *---------------------------------------------------------------------- */ int Tcl_ZlibDeflate( Tcl_Interp *interp, int format, Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj) { int wbits = 0, inLen = 0, e = 0, extraSize = 0; Byte *inData = NULL; z_stream stream; GzipHeader header; gz_header *headerPtr = NULL; Tcl_Obj *obj; if (!interp) { return TCL_ERROR; } /* * Compressed format is specified by the wbits parameter. See zlib.h for * details. */ if (format == TCL_ZLIB_FORMAT_RAW) { wbits = WBITS_RAW; } else if (format == TCL_ZLIB_FORMAT_GZIP) { wbits = WBITS_GZIP; /* * Need to allocate extra space for the gzip header and footer. The * amount of space is (a bit less than) 32 bytes, plus a byte for each * byte of string that we add. Note that over-allocation is not a * problem. [Bug 2419061] */ extraSize = 32; if (gzipHeaderDictObj) { headerPtr = &header.header; memset(headerPtr, 0, sizeof(gz_header)); if (GenerateHeader(interp, gzipHeaderDictObj, &header, &extraSize) != TCL_OK) { return TCL_ERROR; } } } else if (format == TCL_ZLIB_FORMAT_ZLIB) { wbits = WBITS_ZLIB; } else { Tcl_Panic("incorrect zlib data format, must be TCL_ZLIB_FORMAT_ZLIB, " "TCL_ZLIB_FORMAT_GZIP or TCL_ZLIB_FORMAT_ZLIB"); } if (level < -1 || level > 9) { Tcl_Panic("compression level should be between 0 (uncompressed) and " "9 (best compression) or -1 for default compression level"); } /* * Allocate some space to store the output. */ TclNewObj(obj); /* * Obtain the pointer to the byte array, we'll pass this pointer straight * to the deflate command. */ inData = Tcl_GetByteArrayFromObj(data, &inLen); memset(&stream, 0, sizeof(z_stream)); stream.avail_in = (uInt) inLen; stream.next_in = inData; /* * No output buffer available yet, will alloc after deflateInit2. */ e = deflateInit2(&stream, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); if (e != Z_OK) { goto error; } if (headerPtr != NULL) { e = deflateSetHeader(&stream, headerPtr); if (e != Z_OK) { goto error; } } /* * Allocate the output buffer from the value of deflateBound(). This is * probably too much space. Before returning to the caller, we will reduce * it back to the actual compressed size. */ stream.avail_out = deflateBound(&stream, inLen) + extraSize; stream.next_out = Tcl_SetByteArrayLength(obj, stream.avail_out); /* * Perform the compression, Z_FINISH means do it in one go. */ e = deflate(&stream, Z_FINISH); if (e != Z_STREAM_END) { e = deflateEnd(&stream); /* * deflateEnd() returns Z_OK when there are bytes left to compress, at * this point we consider that an error, although we could continue by * allocating more memory and calling deflate() again. */ if (e == Z_OK) { e = Z_BUF_ERROR; } } else { e = deflateEnd(&stream); } if (e != Z_OK) { goto error; } /* * Reduce the bytearray length to the actual data length produced by * deflate. */ Tcl_SetByteArrayLength(obj, stream.total_out); Tcl_SetObjResult(interp, obj); return TCL_OK; error: ConvertError(interp, e, stream.adler); TclDecrRefCount(obj); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_ZlibInflate -- * * Decompress data in an object into the interpreter result. * *---------------------------------------------------------------------- */ int Tcl_ZlibInflate( Tcl_Interp *interp, int format, Tcl_Obj *data, int bufferSize, Tcl_Obj *gzipHeaderDictObj) { int wbits = 0, inLen = 0, e = 0, newBufferSize; Byte *inData = NULL, *outData = NULL, *newOutData = NULL; z_stream stream; gz_header header, *headerPtr = NULL; Tcl_Obj *obj; char *nameBuf = NULL, *commentBuf = NULL; if (!interp) { return TCL_ERROR; } /* * Compressed format is specified by the wbits parameter. See zlib.h for * details. */ switch (format) { case TCL_ZLIB_FORMAT_RAW: wbits = WBITS_RAW; gzipHeaderDictObj = NULL; break; case TCL_ZLIB_FORMAT_ZLIB: wbits = WBITS_ZLIB; gzipHeaderDictObj = NULL; break; case TCL_ZLIB_FORMAT_GZIP: wbits = WBITS_GZIP; break; case TCL_ZLIB_FORMAT_AUTO: wbits = WBITS_AUTODETECT; break; default: Tcl_Panic("incorrect zlib data format, must be TCL_ZLIB_FORMAT_ZLIB, " "TCL_ZLIB_FORMAT_GZIP, TCL_ZLIB_FORMAT_RAW or " "TCL_ZLIB_FORMAT_AUTO"); } if (gzipHeaderDictObj) { headerPtr = &header; memset(headerPtr, 0, sizeof(gz_header)); nameBuf = ckalloc(MAXPATHLEN); header.name = (Bytef *) nameBuf; header.name_max = MAXPATHLEN - 1; commentBuf = ckalloc(MAX_COMMENT_LEN); header.comment = (Bytef *) commentBuf; header.comm_max = MAX_COMMENT_LEN - 1; } inData = Tcl_GetByteArrayFromObj(data, &inLen); if (bufferSize < 1) { /* * Start with a buffer (up to) 3 times the size of the input data. */ if (inLen < 32*1024*1024) { bufferSize = 3*inLen; } else if (inLen < 256*1024*1024) { bufferSize = 2*inLen; } else { bufferSize = inLen; } } TclNewObj(obj); outData = Tcl_SetByteArrayLength(obj, bufferSize); memset(&stream, 0, sizeof(z_stream)); stream.avail_in = (uInt) inLen+1; /* +1 because zlib can "over-request" * input (but ignore it!) */ stream.next_in = inData; stream.avail_out = bufferSize; stream.next_out = outData; /* * Initialize zlib for decompression. */ e = inflateInit2(&stream, wbits); if (e != Z_OK) { goto error; } if (headerPtr) { e = inflateGetHeader(&stream, headerPtr); if (e != Z_OK) { inflateEnd(&stream); goto error; } } /* * Start the decompression cycle. */ while (1) { e = inflate(&stream, Z_FINISH); if (e != Z_BUF_ERROR) { break; } /* * Not enough room in the output buffer. Increase it by five times the * bytes still in the input buffer. (Because 3 times didn't do the * trick before, 5 times is what we do next.) Further optimization * should be done by the user, specify the decompressed size! */ if ((stream.avail_in == 0) && (stream.avail_out > 0)) { e = Z_STREAM_ERROR; break; } newBufferSize = bufferSize + 5 * stream.avail_in; if (newBufferSize == bufferSize) { newBufferSize = bufferSize+1000; } newOutData = Tcl_SetByteArrayLength(obj, newBufferSize); /* * Set next out to the same offset in the new location. */ stream.next_out = newOutData + stream.total_out; /* * And increase avail_out with the number of new bytes allocated. */ stream.avail_out += newBufferSize - bufferSize; outData = newOutData; bufferSize = newBufferSize; } if (e != Z_STREAM_END) { inflateEnd(&stream); goto error; } e = inflateEnd(&stream); if (e != Z_OK) { goto error; } /* * Reduce the BA length to the actual data length produced by deflate. */ Tcl_SetByteArrayLength(obj, stream.total_out); if (headerPtr != NULL) { ExtractHeader(&header, gzipHeaderDictObj); SetValue(gzipHeaderDictObj, "size", Tcl_NewLongObj((long) stream.total_out)); ckfree(nameBuf); ckfree(commentBuf); } Tcl_SetObjResult(interp, obj); return TCL_OK; error: TclDecrRefCount(obj); ConvertError(interp, e, stream.adler); if (nameBuf) { ckfree(nameBuf); } if (commentBuf) { ckfree(commentBuf); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_ZlibCRC32, Tcl_ZlibAdler32 -- * * Access to the checksumming engines. * *---------------------------------------------------------------------- */ unsigned int Tcl_ZlibCRC32( unsigned int crc, const unsigned char *buf, int len) { /* Nothing much to do, just wrap the crc32(). */ return crc32(crc, (Bytef *) buf, (unsigned) len); } unsigned int Tcl_ZlibAdler32( unsigned int adler, const unsigned char *buf, int len) { return adler32(adler, (Bytef *) buf, (unsigned) len); } /* *---------------------------------------------------------------------- * * ZlibCmd -- * * Implementation of the [zlib] command. * *---------------------------------------------------------------------- */ static int ZlibCmd( ClientData notUsed, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int command, dlen, i, option, level = -1; unsigned start, buffersize = 0; Byte *data; Tcl_Obj *headerDictObj; const char *extraInfoStr = NULL; static const char *const commands[] = { "adler32", "compress", "crc32", "decompress", "deflate", "gunzip", "gzip", "inflate", "push", "stream", NULL }; enum zlibCommands { CMD_ADLER, CMD_COMPRESS, CMD_CRC, CMD_DECOMPRESS, CMD_DEFLATE, CMD_GUNZIP, CMD_GZIP, CMD_INFLATE, CMD_PUSH, CMD_STREAM }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "command arg ?...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], commands, "command", 0, &command) != TCL_OK) { return TCL_ERROR; } switch ((enum zlibCommands) command) { case CMD_ADLER: /* adler32 str ?startvalue? * -> checksum */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?"); return TCL_ERROR; } if (objc>3 && Tcl_GetIntFromObj(interp, objv[3], (int *) &start) != TCL_OK) { return TCL_ERROR; } if (objc < 4) { start = Tcl_ZlibAdler32(0, NULL, 0); } data = Tcl_GetByteArrayFromObj(objv[2], &dlen); Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) (uLong) Tcl_ZlibAdler32(start, data, dlen))); return TCL_OK; case CMD_CRC: /* crc32 str ?startvalue? * -> checksum */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?"); return TCL_ERROR; } if (objc>3 && Tcl_GetIntFromObj(interp, objv[3], (int *) &start) != TCL_OK) { return TCL_ERROR; } if (objc < 4) { start = Tcl_ZlibCRC32(0, NULL, 0); } data = Tcl_GetByteArrayFromObj(objv[2], &dlen); Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) (uLong) Tcl_ZlibCRC32(start, data, dlen))); return TCL_OK; case CMD_DEFLATE: /* deflate data ?level? * -> rawCompressedData */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?level?"); return TCL_ERROR; } if (objc > 3) { if (Tcl_GetIntFromObj(interp, objv[3], &level) != TCL_OK) { return TCL_ERROR; } if (level < 0 || level > 9) { goto badLevel; } } return Tcl_ZlibDeflate(interp, TCL_ZLIB_FORMAT_RAW, objv[2], level, NULL); case CMD_COMPRESS: /* compress data ?level? * -> zlibCompressedData */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?level?"); return TCL_ERROR; } if (objc > 3) { if (Tcl_GetIntFromObj(interp, objv[3], &level) != TCL_OK) { return TCL_ERROR; } if (level < 0 || level > 9) { goto badLevel; } } return Tcl_ZlibDeflate(interp, TCL_ZLIB_FORMAT_ZLIB, objv[2], level, NULL); case CMD_GZIP: /* gzip data ?level? * -> gzippedCompressedData */ headerDictObj = NULL; /* * Legacy argument format support. */ if (objc == 4 && Tcl_GetIntFromObj(interp, objv[3], &level) == TCL_OK) { if (level < 0 || level > 9) { extraInfoStr = "\n (in -level option)"; goto badLevel; } return Tcl_ZlibDeflate(interp, TCL_ZLIB_FORMAT_GZIP, objv[2], level, NULL); } if (objc < 3 || objc > 7 || ((objc & 1) == 0)) { Tcl_WrongNumArgs(interp, 2, objv, "data ?-level level? ?-header header?"); return TCL_ERROR; } for (i=3 ; i 9) { extraInfoStr = "\n (in -level option)"; goto badLevel; } break; } } return Tcl_ZlibDeflate(interp, TCL_ZLIB_FORMAT_GZIP, objv[2], level, headerDictObj); case CMD_INFLATE: /* inflate rawcomprdata ?bufferSize? * -> decompressedData */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?bufferSize?"); return TCL_ERROR; } if (objc > 3) { if (Tcl_GetIntFromObj(interp, objv[3], (int *) &buffersize) != TCL_OK) { return TCL_ERROR; } if (buffersize < MIN_NONSTREAM_BUFFER_SIZE || buffersize > MAX_BUFFER_SIZE) { goto badBuffer; } } return Tcl_ZlibInflate(interp, TCL_ZLIB_FORMAT_RAW, objv[2], buffersize, NULL); case CMD_DECOMPRESS: /* decompress zlibcomprdata \ * ?bufferSize? * -> decompressedData */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?bufferSize?"); return TCL_ERROR; } if (objc > 3) { if (Tcl_GetIntFromObj(interp, objv[3], (int *) &buffersize) != TCL_OK) { return TCL_ERROR; } if (buffersize < MIN_NONSTREAM_BUFFER_SIZE || buffersize > MAX_BUFFER_SIZE) { goto badBuffer; } } return Tcl_ZlibInflate(interp, TCL_ZLIB_FORMAT_ZLIB, objv[2], buffersize, NULL); case CMD_GUNZIP: { /* gunzip gzippeddata ?bufferSize? * -> decompressedData */ Tcl_Obj *headerVarObj; if (objc < 3 || objc > 5 || ((objc & 1) == 0)) { Tcl_WrongNumArgs(interp, 2, objv, "data ?-headerVar varName?"); return TCL_ERROR; } headerDictObj = headerVarObj = NULL; for (i=3 ; i MAX_BUFFER_SIZE) { goto badBuffer; } break; case 1: headerVarObj = objv[i+1]; headerDictObj = Tcl_NewObj(); break; } } if (Tcl_ZlibInflate(interp, TCL_ZLIB_FORMAT_GZIP, objv[2], buffersize, headerDictObj) != TCL_OK) { if (headerDictObj) { TclDecrRefCount(headerDictObj); } return TCL_ERROR; } if (headerVarObj != NULL && Tcl_ObjSetVar2(interp, headerVarObj, NULL, headerDictObj, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } return TCL_OK; } case CMD_STREAM: /* stream deflate/inflate/...gunzip \ * ?options...? * -> handleCmd */ return ZlibStreamSubcmd(interp, objc, objv); case CMD_PUSH: /* push mode channel options... * -> channel */ return ZlibPushSubcmd(interp, objc, objv); }; return TCL_ERROR; badLevel: Tcl_SetObjResult(interp, Tcl_NewStringObj("level must be 0 to 9", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", NULL); if (extraInfoStr) { Tcl_AddErrorInfo(interp, extraInfoStr); } return TCL_ERROR; badBuffer: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "buffer size must be %d to %d", MIN_NONSTREAM_BUFFER_SIZE, MAX_BUFFER_SIZE)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * ZlibStreamSubcmd -- * * Implementation of the [zlib stream] subcommand. * *---------------------------------------------------------------------- */ static int ZlibStreamSubcmd( Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { static const char *const stream_formats[] = { "compress", "decompress", "deflate", "gunzip", "gzip", "inflate", NULL }; enum zlibFormats { FMT_COMPRESS, FMT_DECOMPRESS, FMT_DEFLATE, FMT_GUNZIP, FMT_GZIP, FMT_INFLATE }; int i, format, mode = 0, option, level; enum objIndices { OPT_COMPRESSION_DICTIONARY = 0, OPT_GZIP_HEADER = 1, OPT_COMPRESSION_LEVEL = 2, OPT_END = -1 }; Tcl_Obj *obj[3] = { NULL, NULL, NULL }; #define compDictObj obj[OPT_COMPRESSION_DICTIONARY] #define gzipHeaderObj obj[OPT_GZIP_HEADER] #define levelObj obj[OPT_COMPRESSION_LEVEL] typedef struct { const char *name; enum objIndices offset; } OptDescriptor; static const OptDescriptor compressionOpts[] = { { "-dictionary", OPT_COMPRESSION_DICTIONARY }, { "-level", OPT_COMPRESSION_LEVEL }, { NULL, OPT_END } }; static const OptDescriptor gzipOpts[] = { { "-header", OPT_GZIP_HEADER }, { "-level", OPT_COMPRESSION_LEVEL }, { NULL, OPT_END } }; static const OptDescriptor expansionOpts[] = { { "-dictionary", OPT_COMPRESSION_DICTIONARY }, { NULL, OPT_END } }; static const OptDescriptor gunzipOpts[] = { { NULL, OPT_END } }; const OptDescriptor *desc = NULL; Tcl_ZlibStream zh; if (objc < 3 || !(objc & 1)) { Tcl_WrongNumArgs(interp, 2, objv, "mode ?-option value...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], stream_formats, "mode", 0, &format) != TCL_OK) { return TCL_ERROR; } /* * The format determines the compression mode and the options that may be * specified. */ switch ((enum zlibFormats) format) { case FMT_DEFLATE: desc = compressionOpts; mode = TCL_ZLIB_STREAM_DEFLATE; format = TCL_ZLIB_FORMAT_RAW; break; case FMT_INFLATE: desc = expansionOpts; mode = TCL_ZLIB_STREAM_INFLATE; format = TCL_ZLIB_FORMAT_RAW; break; case FMT_COMPRESS: desc = compressionOpts; mode = TCL_ZLIB_STREAM_DEFLATE; format = TCL_ZLIB_FORMAT_ZLIB; break; case FMT_DECOMPRESS: desc = expansionOpts; mode = TCL_ZLIB_STREAM_INFLATE; format = TCL_ZLIB_FORMAT_ZLIB; break; case FMT_GZIP: desc = gzipOpts; mode = TCL_ZLIB_STREAM_DEFLATE; format = TCL_ZLIB_FORMAT_GZIP; break; case FMT_GUNZIP: desc = gunzipOpts; mode = TCL_ZLIB_STREAM_INFLATE; format = TCL_ZLIB_FORMAT_GZIP; break; default: Tcl_Panic("should be unreachable"); } /* * Parse the options. */ for (i=3 ; i 9) { Tcl_SetObjResult(interp, Tcl_NewStringObj("level must be 0 to 9",-1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", NULL); Tcl_AddErrorInfo(interp, "\n (in -level option)"); return TCL_ERROR; } /* * Construct the stream now we know its configuration. */ if (Tcl_ZlibStreamInit(interp, mode, format, level, gzipHeaderObj, &zh) != TCL_OK) { return TCL_ERROR; } if (compDictObj != NULL) { Tcl_ZlibStreamSetCompressionDictionary(zh, compDictObj); } Tcl_SetObjResult(interp, Tcl_ZlibStreamGetCommandName(zh)); return TCL_OK; #undef compDictObj #undef gzipHeaderObj #undef levelObj } /* *---------------------------------------------------------------------- * * ZlibPushSubcmd -- * * Implementation of the [zlib push] subcommand. * *---------------------------------------------------------------------- */ static int ZlibPushSubcmd( Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { static const char *const stream_formats[] = { "compress", "decompress", "deflate", "gunzip", "gzip", "inflate", NULL }; enum zlibFormats { FMT_COMPRESS, FMT_DECOMPRESS, FMT_DEFLATE, FMT_GUNZIP, FMT_GZIP, FMT_INFLATE }; Tcl_Channel chan; int chanMode, format, mode = 0, level, i, option; static const char *const pushCompressOptions[] = { "-dictionary", "-header", "-level", NULL }; static const char *const pushDecompressOptions[] = { "-dictionary", "-header", "-level", "-limit", NULL }; const char *const *pushOptions = pushDecompressOptions; enum pushOptions {poDictionary, poHeader, poLevel, poLimit}; Tcl_Obj *headerObj = NULL, *compDictObj = NULL; int limit = 1, dummy; if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, "mode channel ?options...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], stream_formats, "mode", 0, &format) != TCL_OK) { return TCL_ERROR; } switch ((enum zlibFormats) format) { case FMT_DEFLATE: mode = TCL_ZLIB_STREAM_DEFLATE; format = TCL_ZLIB_FORMAT_RAW; pushOptions = pushCompressOptions; break; case FMT_INFLATE: mode = TCL_ZLIB_STREAM_INFLATE; format = TCL_ZLIB_FORMAT_RAW; break; case FMT_COMPRESS: mode = TCL_ZLIB_STREAM_DEFLATE; format = TCL_ZLIB_FORMAT_ZLIB; pushOptions = pushCompressOptions; break; case FMT_DECOMPRESS: mode = TCL_ZLIB_STREAM_INFLATE; format = TCL_ZLIB_FORMAT_ZLIB; break; case FMT_GZIP: mode = TCL_ZLIB_STREAM_DEFLATE; format = TCL_ZLIB_FORMAT_GZIP; pushOptions = pushCompressOptions; break; case FMT_GUNZIP: mode = TCL_ZLIB_STREAM_INFLATE; format = TCL_ZLIB_FORMAT_GZIP; break; default: Tcl_Panic("should be unreachable"); } if (TclGetChannelFromObj(interp, objv[3], &chan, &chanMode, 0) != TCL_OK){ return TCL_ERROR; } /* * Sanity checks. */ if (mode == TCL_ZLIB_STREAM_DEFLATE && !(chanMode & TCL_WRITABLE)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "compression may only be applied to writable channels", -1)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "UNWRITABLE", NULL); return TCL_ERROR; } if (mode == TCL_ZLIB_STREAM_INFLATE && !(chanMode & TCL_READABLE)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "decompression may only be applied to readable channels",-1)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "UNREADABLE", NULL); return TCL_ERROR; } /* * Parse options. */ level = Z_DEFAULT_COMPRESSION; for (i=4 ; i objc-1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "value missing for %s option", pushOptions[option])); Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", NULL); return TCL_ERROR; } switch ((enum pushOptions) option) { case poHeader: headerObj = objv[i]; if (Tcl_DictObjSize(interp, headerObj, &dummy) != TCL_OK) { goto genericOptionError; } break; case poLevel: if (Tcl_GetIntFromObj(interp, objv[i], (int*) &level) != TCL_OK) { goto genericOptionError; } if (level < 0 || level > 9) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "level must be 0 to 9", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", NULL); goto genericOptionError; } break; case poLimit: if (Tcl_GetIntFromObj(interp, objv[i], (int*) &limit) != TCL_OK) { goto genericOptionError; } if (limit < 1 || limit > MAX_BUFFER_SIZE) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "read ahead limit must be 1 to %d", MAX_BUFFER_SIZE)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", NULL); goto genericOptionError; } break; case poDictionary: if (format == TCL_ZLIB_FORMAT_GZIP) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "a compression dictionary may not be set in the " "gzip format", -1)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "BADOPT", NULL); goto genericOptionError; } compDictObj = objv[i]; break; } } if (ZlibStackChannelTransform(interp, mode, format, level, limit, chan, headerObj, compDictObj) == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, objv[3]); return TCL_OK; genericOptionError: Tcl_AddErrorInfo(interp, "\n (in "); Tcl_AddErrorInfo(interp, pushOptions[option]); Tcl_AddErrorInfo(interp, " option)"); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * ZlibStreamCmd -- * * Implementation of the commands returned by [zlib stream]. * *---------------------------------------------------------------------- */ static int ZlibStreamCmd( ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_ZlibStream zstream = cd; int command, count, code; Tcl_Obj *obj; static const char *const cmds[] = { "add", "checksum", "close", "eof", "finalize", "flush", "fullflush", "get", "header", "put", "reset", NULL }; enum zlibStreamCommands { zs_add, zs_checksum, zs_close, zs_eof, zs_finalize, zs_flush, zs_fullflush, zs_get, zs_header, zs_put, zs_reset }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option data ?...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], cmds, "option", 0, &command) != TCL_OK) { return TCL_ERROR; } switch ((enum zlibStreamCommands) command) { case zs_add: /* $strm add ?$flushopt? $data */ return ZlibStreamAddCmd(zstream, interp, objc, objv); case zs_header: /* $strm header */ return ZlibStreamHeaderCmd(zstream, interp, objc, objv); case zs_put: /* $strm put ?$flushopt? $data */ return ZlibStreamPutCmd(zstream, interp, objc, objv); case zs_get: /* $strm get ?count? */ if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?count?"); return TCL_ERROR; } count = -1; if (objc >= 3) { if (Tcl_GetIntFromObj(interp, objv[2], &count) != TCL_OK) { return TCL_ERROR; } } TclNewObj(obj); code = Tcl_ZlibStreamGet(zstream, obj, count); if (code == TCL_OK) { Tcl_SetObjResult(interp, obj); } else { TclDecrRefCount(obj); } return code; case zs_flush: /* $strm flush */ if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } TclNewObj(obj); Tcl_IncrRefCount(obj); code = Tcl_ZlibStreamPut(zstream, obj, Z_SYNC_FLUSH); TclDecrRefCount(obj); return code; case zs_fullflush: /* $strm fullflush */ if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } TclNewObj(obj); Tcl_IncrRefCount(obj); code = Tcl_ZlibStreamPut(zstream, obj, Z_FULL_FLUSH); TclDecrRefCount(obj); return code; case zs_finalize: /* $strm finalize */ if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } /* * The flush commands slightly abuse the empty result obj as input * data. */ TclNewObj(obj); Tcl_IncrRefCount(obj); code = Tcl_ZlibStreamPut(zstream, obj, Z_FINISH); TclDecrRefCount(obj); return code; case zs_close: /* $strm close */ if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } return Tcl_ZlibStreamClose(zstream); case zs_eof: /* $strm eof */ if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_ZlibStreamEof(zstream))); return TCL_OK; case zs_checksum: /* $strm checksum */ if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) (uLong) Tcl_ZlibStreamChecksum(zstream))); return TCL_OK; case zs_reset: /* $strm reset */ if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } return Tcl_ZlibStreamReset(zstream); } return TCL_OK; } static int ZlibStreamAddCmd( ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_ZlibStream zstream = cd; int index, code, buffersize = -1, flush = -1, i; Tcl_Obj *obj, *compDictObj = NULL; static const char *const add_options[] = { "-buffer", "-dictionary", "-finalize", "-flush", "-fullflush", NULL }; enum addOptions { ao_buffer, ao_dictionary, ao_finalize, ao_flush, ao_fullflush }; for (i=2; i -1) { flush = -2; } else { flush = Z_SYNC_FLUSH; } break; case ao_fullflush: /* -fullflush */ if (flush > -1) { flush = -2; } else { flush = Z_FULL_FLUSH; } break; case ao_finalize: /* -finalize */ if (flush > -1) { flush = -2; } else { flush = Z_FINISH; } break; case ao_buffer: /* -buffer */ if (i == objc-2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-buffer\" option must be followed by integer " "decompression buffersize", -1)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", NULL); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[++i], &buffersize) != TCL_OK) { return TCL_ERROR; } if (buffersize < 1 || buffersize > MAX_BUFFER_SIZE) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "buffer size must be 1 to %d", MAX_BUFFER_SIZE)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", NULL); return TCL_ERROR; } break; case ao_dictionary: if (i == objc-2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-dictionary\" option must be followed by" " compression dictionary bytes", -1)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", NULL); return TCL_ERROR; } compDictObj = objv[++i]; break; } if (flush == -2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-flush\", \"-fullflush\" and \"-finalize\" options" " are mutually exclusive", -1)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "EXCLUSIVE", NULL); return TCL_ERROR; } } if (flush == -1) { flush = 0; } /* * Set the compression dictionary if requested. */ if (compDictObj != NULL) { int len; (void) Tcl_GetByteArrayFromObj(compDictObj, &len); if (len == 0) { compDictObj = NULL; } Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj); } /* * Send the data to the stream core, along with any flushing directive. */ if (Tcl_ZlibStreamPut(zstream, objv[objc-1], flush) != TCL_OK) { return TCL_ERROR; } /* * Get such data out as we can (up to the requested length). */ TclNewObj(obj); code = Tcl_ZlibStreamGet(zstream, obj, buffersize); if (code == TCL_OK) { Tcl_SetObjResult(interp, obj); } else { TclDecrRefCount(obj); } return code; } static int ZlibStreamPutCmd( ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_ZlibStream zstream = cd; int index, flush = -1, i; Tcl_Obj *compDictObj = NULL; static const char *const put_options[] = { "-dictionary", "-finalize", "-flush", "-fullflush", NULL }; enum putOptions { po_dictionary, po_finalize, po_flush, po_fullflush }; for (i=2; i -1) { flush = -2; } else { flush = Z_SYNC_FLUSH; } break; case po_fullflush: /* -fullflush */ if (flush > -1) { flush = -2; } else { flush = Z_FULL_FLUSH; } break; case po_finalize: /* -finalize */ if (flush > -1) { flush = -2; } else { flush = Z_FINISH; } break; case po_dictionary: if (i == objc-2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-dictionary\" option must be followed by" " compression dictionary bytes", -1)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", NULL); return TCL_ERROR; } compDictObj = objv[++i]; break; } if (flush == -2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-flush\", \"-fullflush\" and \"-finalize\" options" " are mutually exclusive", -1)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "EXCLUSIVE", NULL); return TCL_ERROR; } } if (flush == -1) { flush = 0; } /* * Set the compression dictionary if requested. */ if (compDictObj != NULL) { int len; (void) Tcl_GetByteArrayFromObj(compDictObj, &len); if (len == 0) { compDictObj = NULL; } Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj); } /* * Send the data to the stream core, along with any flushing directive. */ return Tcl_ZlibStreamPut(zstream, objv[objc-1], flush); } static int ZlibStreamHeaderCmd( ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { ZlibStreamHandle *zshPtr = cd; Tcl_Obj *resultObj; if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } else if (zshPtr->mode != TCL_ZLIB_STREAM_INFLATE || zshPtr->format != TCL_ZLIB_FORMAT_GZIP) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "only gunzip streams can produce header information", -1)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "BADOP", NULL); return TCL_ERROR; } TclNewObj(resultObj); ExtractHeader(&zshPtr->gzHeaderPtr->header, resultObj); Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* *---------------------------------------------------------------------- * Set of functions to support channel stacking. *---------------------------------------------------------------------- * * ZlibTransformClose -- * * How to shut down a stacked compressing/decompressing transform. * *---------------------------------------------------------------------- */ static int ZlibTransformClose( ClientData instanceData, Tcl_Interp *interp) { ZlibChannelData *cd = instanceData; int e, result = TCL_OK; /* * Delete the support timer. */ ZlibTransformEventTimerKill(cd); /* * Flush any data waiting to be compressed. */ if (cd->mode == TCL_ZLIB_STREAM_DEFLATE) { cd->outStream.avail_in = 0; do { cd->outStream.next_out = (Bytef *) cd->outBuffer; cd->outStream.avail_out = (unsigned) cd->outAllocated; e = deflate(&cd->outStream, Z_FINISH); if (e != Z_OK && e != Z_STREAM_END) { /* TODO: is this the right way to do errors on close? */ if (!TclInThreadExit()) { ConvertError(interp, e, cd->outStream.adler); } result = TCL_ERROR; break; } if (cd->outStream.avail_out != (unsigned) cd->outAllocated) { if (Tcl_WriteRaw(cd->parent, cd->outBuffer, cd->outAllocated - cd->outStream.avail_out) < 0) { /* TODO: is this the right way to do errors on close? * Note: when close is called from FinalizeIOSubsystem * then interp may be NULL */ if (!TclInThreadExit() && interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error while finalizing file: %s", Tcl_PosixError(interp))); } result = TCL_ERROR; break; } } } while (e != Z_STREAM_END); e = deflateEnd(&cd->outStream); } else { e = inflateEnd(&cd->inStream); } /* * Release all memory. */ if (cd->compDictObj) { Tcl_DecrRefCount(cd->compDictObj); cd->compDictObj = NULL; } Tcl_DStringFree(&cd->decompressed); if (cd->inBuffer) { ckfree(cd->inBuffer); cd->inBuffer = NULL; } if (cd->outBuffer) { ckfree(cd->outBuffer); cd->outBuffer = NULL; } ckfree(cd); return result; } /* *---------------------------------------------------------------------- * * ZlibTransformInput -- * * Reader filter that does decompression. * *---------------------------------------------------------------------- */ static int ZlibTransformInput( ClientData instanceData, char *buf, int toRead, int *errorCodePtr) { ZlibChannelData *cd = instanceData; Tcl_DriverInputProc *inProc = Tcl_ChannelInputProc(Tcl_GetChannelType(cd->parent)); int readBytes, gotBytes, copied; if (cd->mode == TCL_ZLIB_STREAM_DEFLATE) { return inProc(Tcl_GetChannelInstanceData(cd->parent), buf, toRead, errorCodePtr); } gotBytes = 0; while (toRead > 0) { /* * Loop until the request is satisfied (or no data available from * below, possibly EOF). */ copied = ResultCopy(cd, buf, toRead); toRead -= copied; buf += copied; gotBytes += copied; if (toRead == 0) { return gotBytes; } /* * The buffer is exhausted, but the caller wants even more. We now * have to go to the underlying channel, get more bytes and then * transform them for delivery. We may not get what we want (full EOF * or temporarily out of data). * * Length (cd->decompressed) == 0, toRead > 0 here. * * The zlib transform allows us to read at most one character from the * underlying channel to properly identify Z_STREAM_END without * reading over the border. */ readBytes = Tcl_ReadRaw(cd->parent, cd->inBuffer, cd->readAheadLimit); /* * Three cases here: * 1. Got some data from the underlying channel (readBytes > 0) so * it should be fed through the decompression engine. * 2. Got an error (readBytes < 0) which we should report up except * for the case where we can convert it to a short read. * 3. Got an end-of-data from EOF or blocking (readBytes == 0). If * it is EOF, try flushing the data out of the decompressor. */ if (readBytes < 0) { /* See ReflectInput() in tclIORTrans.c */ if (Tcl_InputBlocked(cd->parent) && (gotBytes > 0)) { return gotBytes; } *errorCodePtr = Tcl_GetErrno(); return -1; } if (readBytes == 0) { /* * Eof in parent. * * Now this is a bit different. The partial data waiting is * converted and returned. */ if (ResultGenerate(cd, 0, Z_SYNC_FLUSH, errorCodePtr) != TCL_OK) { return -1; } if (Tcl_DStringLength(&cd->decompressed) == 0) { /* * The drain delivered nothing. Time to deliver what we've * got. */ return gotBytes; } } else /* readBytes > 0 */ { /* * Transform the read chunk, which was not empty. Anything we get * back is a transformation result to be put into our buffers, and * the next iteration will put it into the result. */ if (ResultGenerate(cd, readBytes, Z_NO_FLUSH, errorCodePtr) != TCL_OK) { return -1; } } } return gotBytes; } /* *---------------------------------------------------------------------- * * ZlibTransformOutput -- * * Writer filter that does compression. * *---------------------------------------------------------------------- */ static int ZlibTransformOutput( ClientData instanceData, const char *buf, int toWrite, int *errorCodePtr) { ZlibChannelData *cd = instanceData; Tcl_DriverOutputProc *outProc = Tcl_ChannelOutputProc(Tcl_GetChannelType(cd->parent)); int e, produced; Tcl_Obj *errObj; if (cd->mode == TCL_ZLIB_STREAM_INFLATE) { return outProc(Tcl_GetChannelInstanceData(cd->parent), buf, toWrite, errorCodePtr); } cd->outStream.next_in = (Bytef *) buf; cd->outStream.avail_in = toWrite; do { cd->outStream.next_out = (Bytef *) cd->outBuffer; cd->outStream.avail_out = cd->outAllocated; e = deflate(&cd->outStream, Z_NO_FLUSH); produced = cd->outAllocated - cd->outStream.avail_out; if (e == Z_OK && produced > 0) { if (Tcl_WriteRaw(cd->parent, cd->outBuffer, produced) < 0) { *errorCodePtr = Tcl_GetErrno(); return -1; } } } while (e == Z_OK && produced > 0 && cd->outStream.avail_in > 0); if (e == Z_OK) { return toWrite - cd->outStream.avail_in; } errObj = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj("-errorcode",-1)); Tcl_ListObjAppendElement(NULL, errObj, ConvertErrorToList(e, cd->outStream.adler)); Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj(cd->outStream.msg, -1)); Tcl_SetChannelError(cd->parent, errObj); *errorCodePtr = EINVAL; return -1; } /* *---------------------------------------------------------------------- * * ZlibTransformFlush -- * * How to perform a flush of a compressing transform. * *---------------------------------------------------------------------- */ static int ZlibTransformFlush( Tcl_Interp *interp, ZlibChannelData *cd, int flushType) { int e, len; cd->outStream.avail_in = 0; do { /* * Get the bytes to go out of the compression engine. */ cd->outStream.next_out = (Bytef *) cd->outBuffer; cd->outStream.avail_out = cd->outAllocated; e = deflate(&cd->outStream, flushType); if (e != Z_OK && e != Z_BUF_ERROR) { ConvertError(interp, e, cd->outStream.adler); return TCL_ERROR; } /* * Write the bytes we've received to the next layer. */ len = cd->outStream.next_out - (Bytef *) cd->outBuffer; if (len > 0 && Tcl_WriteRaw(cd->parent, cd->outBuffer, len) < 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "problem flushing channel: %s", Tcl_PosixError(interp))); return TCL_ERROR; } /* * If we get to this point, either we're in the Z_OK or the * Z_BUF_ERROR state. In the former case, we're done. In the latter * case, it's because there's more bytes to go than would fit in the * buffer we provided, and we need to go round again to get some more. * * We also stop the loop if we would have done a zero-length write. * Those can cause problems at the OS level. */ } while (len > 0 && e == Z_BUF_ERROR); return TCL_OK; } /* *---------------------------------------------------------------------- * * ZlibTransformSetOption -- * * Writing side of [fconfigure] on our channel. * *---------------------------------------------------------------------- */ static int ZlibTransformSetOption( /* not used */ ClientData instanceData, Tcl_Interp *interp, const char *optionName, const char *value) { ZlibChannelData *cd = instanceData; Tcl_DriverSetOptionProc *setOptionProc = Tcl_ChannelSetOptionProc(Tcl_GetChannelType(cd->parent)); static const char *compressChanOptions = "dictionary flush"; static const char *gzipChanOptions = "flush"; static const char *decompressChanOptions = "dictionary limit"; static const char *gunzipChanOptions = "flush limit"; int haveFlushOpt = (cd->mode == TCL_ZLIB_STREAM_DEFLATE); if (optionName && (strcmp(optionName, "-dictionary") == 0) && (cd->format != TCL_ZLIB_FORMAT_GZIP)) { Tcl_Obj *compDictObj; int code; TclNewStringObj(compDictObj, value, strlen(value)); Tcl_IncrRefCount(compDictObj); (void) Tcl_GetByteArrayFromObj(compDictObj, NULL); if (cd->compDictObj) { TclDecrRefCount(cd->compDictObj); } cd->compDictObj = compDictObj; code = Z_OK; if (cd->mode == TCL_ZLIB_STREAM_DEFLATE) { code = SetDeflateDictionary(&cd->outStream, compDictObj); if (code != Z_OK) { ConvertError(interp, code, cd->outStream.adler); return TCL_ERROR; } } else if (cd->format == TCL_ZLIB_FORMAT_RAW) { code = SetInflateDictionary(&cd->inStream, compDictObj); if (code != Z_OK) { ConvertError(interp, code, cd->inStream.adler); return TCL_ERROR; } } return TCL_OK; } if (haveFlushOpt) { if (optionName && strcmp(optionName, "-flush") == 0) { int flushType; if (value[0] == 'f' && strcmp(value, "full") == 0) { flushType = Z_FULL_FLUSH; } else if (value[0] == 's' && strcmp(value, "sync") == 0) { flushType = Z_SYNC_FLUSH; } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown -flush type \"%s\": must be full or sync", value)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "FLUSH", NULL); return TCL_ERROR; } /* * Try to actually do the flush now. */ return ZlibTransformFlush(interp, cd, flushType); } } else { if (optionName && strcmp(optionName, "-limit") == 0) { int newLimit; if (Tcl_GetInt(interp, value, &newLimit) != TCL_OK) { return TCL_ERROR; } else if (newLimit < 1 || newLimit > MAX_BUFFER_SIZE) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "-limit must be between 1 and 65536", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "READLIMIT", NULL); return TCL_ERROR; } } } if (setOptionProc == NULL) { if (cd->format == TCL_ZLIB_FORMAT_GZIP) { return Tcl_BadChannelOption(interp, optionName, (cd->mode == TCL_ZLIB_STREAM_DEFLATE) ? gzipChanOptions : gunzipChanOptions); } else { return Tcl_BadChannelOption(interp, optionName, (cd->mode == TCL_ZLIB_STREAM_DEFLATE) ? compressChanOptions : decompressChanOptions); } } /* * Pass all unknown options down, to deeper transforms and/or the base * channel. */ return setOptionProc(Tcl_GetChannelInstanceData(cd->parent), interp, optionName, value); } /* *---------------------------------------------------------------------- * * ZlibTransformGetOption -- * * Reading side of [fconfigure] on our channel. * *---------------------------------------------------------------------- */ static int ZlibTransformGetOption( ClientData instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr) { ZlibChannelData *cd = instanceData; Tcl_DriverGetOptionProc *getOptionProc = Tcl_ChannelGetOptionProc(Tcl_GetChannelType(cd->parent)); static const char *compressChanOptions = "checksum dictionary"; static const char *gzipChanOptions = "checksum"; static const char *decompressChanOptions = "checksum dictionary limit"; static const char *gunzipChanOptions = "checksum header limit"; /* * The "crc" option reports the current CRC (calculated with the Adler32 * or CRC32 algorithm according to the format) given the data that has * been processed so far. */ if (optionName == NULL || strcmp(optionName, "-checksum") == 0) { uLong crc; char buf[12]; if (cd->mode == TCL_ZLIB_STREAM_DEFLATE) { crc = cd->outStream.adler; } else { crc = cd->inStream.adler; } sprintf(buf, "%lu", crc); if (optionName == NULL) { Tcl_DStringAppendElement(dsPtr, "-checksum"); Tcl_DStringAppendElement(dsPtr, buf); } else { Tcl_DStringAppend(dsPtr, buf, -1); return TCL_OK; } } if ((cd->format != TCL_ZLIB_FORMAT_GZIP) && (optionName == NULL || strcmp(optionName, "-dictionary") == 0)) { /* * Embedded NUL bytes are ok; they'll be C080-encoded. */ if (optionName == NULL) { Tcl_DStringAppendElement(dsPtr, "-dictionary"); if (cd->compDictObj) { Tcl_DStringAppendElement(dsPtr, Tcl_GetString(cd->compDictObj)); } else { Tcl_DStringAppendElement(dsPtr, ""); } } else { int len; const char *str = Tcl_GetStringFromObj(cd->compDictObj, &len); Tcl_DStringAppend(dsPtr, str, len); } } /* * The "header" option, which is only valid on inflating gzip channels, * reports the header that has been read from the start of the stream. */ if ((cd->flags & IN_HEADER) && ((optionName == NULL) || (strcmp(optionName, "-header") == 0))) { Tcl_Obj *tmpObj = Tcl_NewObj(); ExtractHeader(&cd->inHeader.header, tmpObj); if (optionName == NULL) { Tcl_DStringAppendElement(dsPtr, "-header"); Tcl_DStringAppendElement(dsPtr, Tcl_GetString(tmpObj)); Tcl_DecrRefCount(tmpObj); } else { TclDStringAppendObj(dsPtr, tmpObj); Tcl_DecrRefCount(tmpObj); return TCL_OK; } } /* * Now we do the standard processing of the stream we wrapped. */ if (getOptionProc) { return getOptionProc(Tcl_GetChannelInstanceData(cd->parent), interp, optionName, dsPtr); } if (optionName == NULL) { return TCL_OK; } if (cd->format == TCL_ZLIB_FORMAT_GZIP) { return Tcl_BadChannelOption(interp, optionName, (cd->mode == TCL_ZLIB_STREAM_DEFLATE) ? gzipChanOptions : gunzipChanOptions); } else { return Tcl_BadChannelOption(interp, optionName, (cd->mode == TCL_ZLIB_STREAM_DEFLATE) ? compressChanOptions : decompressChanOptions); } } /* *---------------------------------------------------------------------- * * ZlibTransformWatch, ZlibTransformEventHandler -- * * If we have data pending, trigger a readable event after a short time * (in order to allow a real event to catch up). * *---------------------------------------------------------------------- */ static void ZlibTransformWatch( ClientData instanceData, int mask) { ZlibChannelData *cd = instanceData; Tcl_DriverWatchProc *watchProc; /* * This code is based on the code in tclIORTrans.c */ watchProc = Tcl_ChannelWatchProc(Tcl_GetChannelType(cd->parent)); watchProc(Tcl_GetChannelInstanceData(cd->parent), mask); if (!(mask & TCL_READABLE) || Tcl_DStringLength(&cd->decompressed) == 0) { ZlibTransformEventTimerKill(cd); } else if (cd->timer == NULL) { cd->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ZlibTransformTimerRun, cd); } } static int ZlibTransformEventHandler( ClientData instanceData, int interestMask) { ZlibChannelData *cd = instanceData; ZlibTransformEventTimerKill(cd); return interestMask; } static inline void ZlibTransformEventTimerKill( ZlibChannelData *cd) { if (cd->timer != NULL) { Tcl_DeleteTimerHandler(cd->timer); cd->timer = NULL; } } static void ZlibTransformTimerRun( ClientData clientData) { ZlibChannelData *cd = clientData; cd->timer = NULL; Tcl_NotifyChannel(cd->chan, TCL_READABLE); } /* *---------------------------------------------------------------------- * * ZlibTransformGetHandle -- * * Anything that needs the OS handle is told to get it from what we are * stacked on top of. * *---------------------------------------------------------------------- */ static int ZlibTransformGetHandle( ClientData instanceData, int direction, ClientData *handlePtr) { ZlibChannelData *cd = instanceData; return Tcl_GetChannelHandle(cd->parent, direction, handlePtr); } /* *---------------------------------------------------------------------- * * ZlibTransformBlockMode -- * * We need to keep track of the blocking mode; it changes our behavior. * *---------------------------------------------------------------------- */ static int ZlibTransformBlockMode( ClientData instanceData, int mode) { ZlibChannelData *cd = instanceData; if (mode == TCL_MODE_NONBLOCKING) { cd->flags |= ASYNC; } else { cd->flags &= ~ASYNC; } return TCL_OK; } /* *---------------------------------------------------------------------- * * ZlibStackChannelTransform -- * * Stacks either compression or decompression onto a channel. * * Results: * The stacked channel, or NULL if there was an error. * *---------------------------------------------------------------------- */ static Tcl_Channel ZlibStackChannelTransform( Tcl_Interp *interp, /* Where to write error messages. */ int mode, /* Whether this is a compressing transform * (TCL_ZLIB_STREAM_DEFLATE) or a * decompressing transform * (TCL_ZLIB_STREAM_INFLATE). Note that * compressing transforms require that the * channel is writable, and decompressing * transforms require that the channel is * readable. */ int format, /* One of the TCL_ZLIB_FORMAT_* values that * indicates what compressed format to allow. * TCL_ZLIB_FORMAT_AUTO is only supported for * decompressing transforms. */ int level, /* What compression level to use. Ignored for * decompressing transforms. */ int limit, /* The limit on the number of bytes to read * ahead; always at least 1. */ Tcl_Channel channel, /* The channel to attach to. */ Tcl_Obj *gzipHeaderDictPtr, /* A description of header to use, or NULL to * use a default. Ignored if not compressing * to produce gzip-format data. */ Tcl_Obj *compDictObj) /* Byte-array object containing compression * dictionary (not dictObj!) to use if * necessary. */ { ZlibChannelData *cd = ckalloc(sizeof(ZlibChannelData)); Tcl_Channel chan; int wbits = 0; int e; if (mode != TCL_ZLIB_STREAM_DEFLATE && mode != TCL_ZLIB_STREAM_INFLATE) { Tcl_Panic("unknown mode: %d", mode); } memset(cd, 0, sizeof(ZlibChannelData)); cd->mode = mode; cd->format = format; cd->readAheadLimit = limit; if (format == TCL_ZLIB_FORMAT_GZIP || format == TCL_ZLIB_FORMAT_AUTO) { if (mode == TCL_ZLIB_STREAM_DEFLATE) { if (gzipHeaderDictPtr) { cd->flags |= OUT_HEADER; if (GenerateHeader(interp, gzipHeaderDictPtr, &cd->outHeader, NULL) != TCL_OK) { goto error; } } } else { cd->flags |= IN_HEADER; cd->inHeader.header.name = (Bytef *) &cd->inHeader.nativeFilenameBuf; cd->inHeader.header.name_max = MAXPATHLEN - 1; cd->inHeader.header.comment = (Bytef *) &cd->inHeader.nativeCommentBuf; cd->inHeader.header.comm_max = MAX_COMMENT_LEN - 1; } } if (compDictObj != NULL) { cd->compDictObj = Tcl_DuplicateObj(compDictObj); Tcl_IncrRefCount(cd->compDictObj); Tcl_GetByteArrayFromObj(cd->compDictObj, NULL); } if (format == TCL_ZLIB_FORMAT_RAW) { wbits = WBITS_RAW; } else if (format == TCL_ZLIB_FORMAT_ZLIB) { wbits = WBITS_ZLIB; } else if (format == TCL_ZLIB_FORMAT_GZIP) { wbits = WBITS_GZIP; } else if (format == TCL_ZLIB_FORMAT_AUTO) { wbits = WBITS_AUTODETECT; } else { Tcl_Panic("bad format: %d", format); } /* * Initialize input inflater or the output deflater. */ if (mode == TCL_ZLIB_STREAM_INFLATE) { e = inflateInit2(&cd->inStream, wbits); if (e != Z_OK) { goto error; } cd->inAllocated = DEFAULT_BUFFER_SIZE; cd->inBuffer = ckalloc(cd->inAllocated); if (cd->flags & IN_HEADER) { e = inflateGetHeader(&cd->inStream, &cd->inHeader.header); if (e != Z_OK) { goto error; } } if (cd->format == TCL_ZLIB_FORMAT_RAW && cd->compDictObj) { e = SetInflateDictionary(&cd->inStream, cd->compDictObj); if (e != Z_OK) { goto error; } TclDecrRefCount(cd->compDictObj); cd->compDictObj = NULL; } } else { e = deflateInit2(&cd->outStream, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); if (e != Z_OK) { goto error; } cd->outAllocated = DEFAULT_BUFFER_SIZE; cd->outBuffer = ckalloc(cd->outAllocated); if (cd->flags & OUT_HEADER) { e = deflateSetHeader(&cd->outStream, &cd->outHeader.header); if (e != Z_OK) { goto error; } } if (cd->compDictObj) { e = SetDeflateDictionary(&cd->outStream, cd->compDictObj); if (e != Z_OK) { goto error; } } } Tcl_DStringInit(&cd->decompressed); chan = Tcl_StackChannel(interp, &zlibChannelType, cd, Tcl_GetChannelMode(channel), channel); if (chan == NULL) { goto error; } cd->chan = chan; cd->parent = Tcl_GetStackedChannel(chan); Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetChannelName(chan), -1)); return chan; error: if (cd->inBuffer) { ckfree(cd->inBuffer); inflateEnd(&cd->inStream); } if (cd->outBuffer) { ckfree(cd->outBuffer); deflateEnd(&cd->outStream); } if (cd->compDictObj) { Tcl_DecrRefCount(cd->compDictObj); } ckfree(cd); return NULL; } /* *---------------------------------------------------------------------- * * ResultCopy -- * * Copies the requested number of bytes from the buffer into the * specified array and removes them from the buffer afterward. Copies * less if there is not enough data in the buffer. * * Side effects: * See above. * * Result: * The number of actually copied bytes, possibly less than 'toRead'. * *---------------------------------------------------------------------- */ static inline int ResultCopy( ZlibChannelData *cd, /* The location of the buffer to read from. */ char *buf, /* The buffer to copy into */ int toRead) /* Number of requested bytes */ { int have = Tcl_DStringLength(&cd->decompressed); if (have == 0) { /* * Nothing to copy in the case of an empty buffer. */ return 0; } else if (have > toRead) { /* * The internal buffer contains more than requested. Copy the * requested subset to the caller, shift the remaining bytes down, and * truncate. */ char *src = Tcl_DStringValue(&cd->decompressed); memcpy(buf, src, toRead); memmove(src, src + toRead, have - toRead); Tcl_DStringSetLength(&cd->decompressed, have - toRead); return toRead; } else /* have <= toRead */ { /* * There is just or not enough in the buffer to fully satisfy the * caller, so take everything as best effort. */ memcpy(buf, Tcl_DStringValue(&cd->decompressed), have); TclDStringClear(&cd->decompressed); return have; } } /* *---------------------------------------------------------------------- * * ResultGenerate -- * * Extract uncompressed bytes from the compression engine and store them * in our working buffer. * * Result: * TCL_OK/TCL_ERROR (with *errorCodePtr updated with reason). * * Side effects: * See above. * *---------------------------------------------------------------------- */ static int ResultGenerate( ZlibChannelData *cd, int n, int flush, int *errorCodePtr) { #define MAXBUF 1024 unsigned char buf[MAXBUF]; int e, written; Tcl_Obj *errObj; cd->inStream.next_in = (Bytef *) cd->inBuffer; cd->inStream.avail_in = n; while (1) { cd->inStream.next_out = (Bytef *) buf; cd->inStream.avail_out = MAXBUF; e = inflate(&cd->inStream, flush); if (e == Z_NEED_DICT && cd->compDictObj) { e = SetInflateDictionary(&cd->inStream, cd->compDictObj); if (e == Z_OK) { /* * A repetition of Z_NEED_DICT is just an error. */ cd->inStream.next_out = (Bytef *) buf; cd->inStream.avail_out = MAXBUF; e = inflate(&cd->inStream, flush); } } /* * avail_out is now the left over space in the output. Therefore * "MAXBUF - avail_out" is the amount of bytes generated. */ written = MAXBUF - cd->inStream.avail_out; if (written) { Tcl_DStringAppend(&cd->decompressed, (char *) buf, written); } /* * The cases where we're definitely done. */ if (((flush == Z_SYNC_FLUSH) && (e == Z_BUF_ERROR)) || (e == Z_STREAM_END) || (e == Z_OK && cd->inStream.avail_out == 0)) { return TCL_OK; } /* * Z_BUF_ERROR can be ignored as per http://www.zlib.net/zlib_how.html * * Just indicates that the zlib couldn't consume input/produce output, * and is fixed by supplying more input. * * Otherwise, we've got errors and need to report to higher-up. */ if ((e != Z_OK) && (e != Z_BUF_ERROR)) { goto handleError; } /* * Check if the inflate stopped early. */ if (cd->inStream.avail_in <= 0 && flush != Z_SYNC_FLUSH) { return TCL_OK; } } handleError: errObj = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj("-errorcode",-1)); Tcl_ListObjAppendElement(NULL, errObj, ConvertErrorToList(e, cd->inStream.adler)); Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj(cd->inStream.msg, -1)); Tcl_SetChannelError(cd->parent, errObj); *errorCodePtr = EINVAL; return TCL_ERROR; } /* *---------------------------------------------------------------------- * Finally, the TclZlibInit function. Used to install the zlib API. *---------------------------------------------------------------------- */ int TclZlibInit( Tcl_Interp *interp) { Tcl_Config cfg[2]; /* * This does two things. It creates a counter used in the creation of * stream commands, and it creates the namespace that will contain those * commands. */ Tcl_EvalEx(interp, "namespace eval ::tcl::zlib {variable cmdcounter 0}", -1, 0); /* * Create the public scripted interface to this file's functionality. */ Tcl_CreateObjCommand(interp, "zlib", ZlibCmd, 0, 0); /* * Store the underlying configuration information. * * TODO: Describe whether we're using the system version of the library or * a compatibility version built into Tcl? */ cfg[0].key = "zlibVersion"; cfg[0].value = zlibVersion(); cfg[1].key = NULL; Tcl_RegisterConfig(interp, "zlib", cfg, "iso8859-1"); /* * Formally provide the package as a Tcl built-in. */ return Tcl_PkgProvide(interp, "zlib", TCL_ZLIB_VERSION); } /* *---------------------------------------------------------------------- * Stubs used when a suitable zlib installation was not found during * configure. *---------------------------------------------------------------------- */ #else /* !HAVE_ZLIB */ int Tcl_ZlibStreamInit( Tcl_Interp *interp, int mode, int format, int level, Tcl_Obj *dictObj, Tcl_ZlibStream *zshandle) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1)); Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL); } return TCL_ERROR; } int Tcl_ZlibStreamClose( Tcl_ZlibStream zshandle) { return TCL_OK; } int Tcl_ZlibStreamReset( Tcl_ZlibStream zshandle) { return TCL_OK; } Tcl_Obj * Tcl_ZlibStreamGetCommandName( Tcl_ZlibStream zshandle) { return NULL; } int Tcl_ZlibStreamEof( Tcl_ZlibStream zshandle) { return 1; } int Tcl_ZlibStreamChecksum( Tcl_ZlibStream zshandle) { return 0; } int Tcl_ZlibStreamPut( Tcl_ZlibStream zshandle, Tcl_Obj *data, int flush) { return TCL_OK; } int Tcl_ZlibStreamGet( Tcl_ZlibStream zshandle, Tcl_Obj *data, int count) { return TCL_OK; } int Tcl_ZlibDeflate( Tcl_Interp *interp, int format, Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1)); Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL); } return TCL_ERROR; } int Tcl_ZlibInflate( Tcl_Interp *interp, int format, Tcl_Obj *data, int bufferSize, Tcl_Obj *gzipHeaderDictObj) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1)); Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", NULL); } return TCL_ERROR; } unsigned int Tcl_ZlibCRC32( unsigned int crc, const char *buf, int len) { return 0; } unsigned int Tcl_ZlibAdler32( unsigned int adler, const char *buf, int len) { return 0; } void Tcl_ZlibStreamSetCompressionDictionary( Tcl_ZlibStream zshandle, Tcl_Obj *compressionDictionaryObj) { /* Do nothing. */ } #endif /* HAVE_ZLIB */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclThread.c0000644000175000017500000002616612663660065015274 0ustar sergeisergei/* * tclThread.c -- * * This file implements Platform independent thread operations. Most of * the real work is done in the platform dependent files. * * Copyright (c) 1998 by Sun Microsystems, Inc. * Copyright (c) 2008 by George Peter Staplin * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * There are three classes of synchronization objects: mutexes, thread data * keys, and condition variables. The following are used to record the memory * used for these objects so they can be finalized. * * These statics are guarded by the mutex in the caller of * TclRememberThreadData, e.g., TclpThreadDataKeyInit */ typedef struct { int num; /* Number of objects remembered */ int max; /* Max size of the array */ void **list; /* List of pointers */ } SyncObjRecord; static SyncObjRecord keyRecord = {0, 0, NULL}; static SyncObjRecord mutexRecord = {0, 0, NULL}; static SyncObjRecord condRecord = {0, 0, NULL}; /* * Prototypes of functions used only in this file. */ static void ForgetSyncObject(void *objPtr, SyncObjRecord *recPtr); static void RememberSyncObject(void *objPtr, SyncObjRecord *recPtr); /* * Several functions are #defined to nothing in tcl.h if TCL_THREADS is not * specified. Here we undo that so the functions are defined in the stubs * table. */ #ifndef TCL_THREADS #undef Tcl_MutexLock #undef Tcl_MutexUnlock #undef Tcl_MutexFinalize #undef Tcl_ConditionNotify #undef Tcl_ConditionWait #undef Tcl_ConditionFinalize #endif /* *---------------------------------------------------------------------- * * Tcl_GetThreadData -- * * This function allocates and initializes a chunk of thread local * storage. * * Results: * A thread-specific pointer to the data structure. * * Side effects: * Will allocate memory the first time this thread calls for this chunk * of storage. * *---------------------------------------------------------------------- */ void * Tcl_GetThreadData( Tcl_ThreadDataKey *keyPtr, /* Identifier for the data chunk */ int size) /* Size of storage block */ { void *result; #ifdef TCL_THREADS /* * Initialize the key for this thread. */ result = TclThreadStorageKeyGet(keyPtr); if (result == NULL) { result = ckalloc(size); memset(result, 0, (size_t) size); TclThreadStorageKeySet(keyPtr, result); } #else /* TCL_THREADS */ if (*keyPtr == NULL) { result = ckalloc(size); memset(result, 0, (size_t)size); *keyPtr = result; RememberSyncObject(keyPtr, &keyRecord); } else { result = *keyPtr; } #endif /* TCL_THREADS */ return result; } /* *---------------------------------------------------------------------- * * TclThreadDataKeyGet -- * * This function returns a pointer to a block of thread local storage. * * Results: * A thread-specific pointer to the data structure, or NULL if the memory * has not been assigned to this key for this thread. * * Side effects: * None. * *---------------------------------------------------------------------- */ void * TclThreadDataKeyGet( Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk. */ { #ifdef TCL_THREADS return TclThreadStorageKeyGet(keyPtr); #else /* TCL_THREADS */ return *keyPtr; #endif /* TCL_THREADS */ } /* *---------------------------------------------------------------------- * * RememberSyncObject * * Keep a list of (mutexes/condition variable/data key) used during * finalization. * * Assume master lock is held. * * Results: * None. * * Side effects: * Add to the appropriate list. * *---------------------------------------------------------------------- */ static void RememberSyncObject( void *objPtr, /* Pointer to sync object */ SyncObjRecord *recPtr) /* Record of sync objects */ { void **newList; int i, j; /* * Reuse any free slot in the list. */ for (i=0 ; i < recPtr->num ; ++i) { if (recPtr->list[i] == NULL) { recPtr->list[i] = objPtr; return; } } /* * Grow the list of pointers if necessary, copying only non-NULL * pointers to the new list. */ if (recPtr->num >= recPtr->max) { recPtr->max += 8; newList = ckalloc(recPtr->max * sizeof(void *)); for (i=0,j=0 ; inum ; i++) { if (recPtr->list[i] != NULL) { newList[j++] = recPtr->list[i]; } } if (recPtr->list != NULL) { ckfree(recPtr->list); } recPtr->list = newList; recPtr->num = j; } recPtr->list[recPtr->num] = objPtr; recPtr->num++; } /* *---------------------------------------------------------------------- * * ForgetSyncObject * * Remove a single object from the list. * Assume master lock is held. * * Results: * None. * * Side effects: * Remove from the appropriate list. * *---------------------------------------------------------------------- */ static void ForgetSyncObject( void *objPtr, /* Pointer to sync object */ SyncObjRecord *recPtr) /* Record of sync objects */ { int i; for (i=0 ; inum ; i++) { if (objPtr == recPtr->list[i]) { recPtr->list[i] = NULL; return; } } } /* *---------------------------------------------------------------------- * * TclRememberMutex * * Keep a list of mutexes used during finalization. * Assume master lock is held. * * Results: * None. * * Side effects: * Add to the mutex list. * *---------------------------------------------------------------------- */ void TclRememberMutex( Tcl_Mutex *mutexPtr) { RememberSyncObject(mutexPtr, &mutexRecord); } /* *---------------------------------------------------------------------- * * Tcl_MutexFinalize -- * * Finalize a single mutex and remove it from the list of remembered * objects. * * Results: * None. * * Side effects: * Remove the mutex from the list. * *---------------------------------------------------------------------- */ void Tcl_MutexFinalize( Tcl_Mutex *mutexPtr) { #ifdef TCL_THREADS TclpFinalizeMutex(mutexPtr); #endif TclpMasterLock(); ForgetSyncObject(mutexPtr, &mutexRecord); TclpMasterUnlock(); } /* *---------------------------------------------------------------------- * * TclRememberCondition * * Keep a list of condition variables used during finalization. * Assume master lock is held. * * Results: * None. * * Side effects: * Add to the condition variable list. * *---------------------------------------------------------------------- */ void TclRememberCondition( Tcl_Condition *condPtr) { RememberSyncObject(condPtr, &condRecord); } /* *---------------------------------------------------------------------- * * Tcl_ConditionFinalize -- * * Finalize a single condition variable and remove it from the list of * remembered objects. * * Results: * None. * * Side effects: * Remove the condition variable from the list. * *---------------------------------------------------------------------- */ void Tcl_ConditionFinalize( Tcl_Condition *condPtr) { #ifdef TCL_THREADS TclpFinalizeCondition(condPtr); #endif TclpMasterLock(); ForgetSyncObject(condPtr, &condRecord); TclpMasterUnlock(); } /* *---------------------------------------------------------------------- * * TclFinalizeThreadData -- * * This function cleans up the thread-local storage. Secondary, it cleans * thread alloc cache. * This is called once for each thread before thread exits. * * Results: * None. * * Side effects: * Frees up all thread local storage. * *---------------------------------------------------------------------- */ void TclFinalizeThreadData(int quick) { TclFinalizeThreadDataThread(); #if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) if (!quick) { /* * Quick exit principle makes it useless to terminate allocators */ TclFinalizeThreadAllocThread(); } #endif } /* *---------------------------------------------------------------------- * * TclFinalizeSynchronization -- * * This function cleans up all synchronization objects: mutexes, * condition variables, and thread-local storage. * * Results: * None. * * Side effects: * Frees up the memory. * *---------------------------------------------------------------------- */ void TclFinalizeSynchronization(void) { int i; void *blockPtr; Tcl_ThreadDataKey *keyPtr; #ifdef TCL_THREADS Tcl_Mutex *mutexPtr; Tcl_Condition *condPtr; TclpMasterLock(); #endif /* * If we're running unthreaded, the TSD blocks are simply stored inside * their thread data keys. Free them here. */ if (keyRecord.list != NULL) { for (i=0 ; i * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ typedef struct Tcl_Obj Tcl_Obj; typedef const char* TclDTraceStr; /* * Tcl DTrace probes */ provider tcl { /***************************** proc probes *****************************/ /* * tcl*:::proc-entry probe * triggered immediately before proc bytecode execution * arg0: proc name (string) * arg1: number of arguments (int) * arg2: array of proc argument objects (Tcl_Obj**) */ probe proc__entry(TclDTraceStr name, int objc, struct Tcl_Obj **objv); /* * tcl*:::proc-return probe * triggered immediately after proc bytecode execution * arg0: proc name (string) * arg1: return code (int) */ probe proc__return(TclDTraceStr name, int code); /* * tcl*:::proc-result probe * triggered after proc-return probe and result processing * arg0: proc name (string) * arg1: return code (int) * arg2: proc result (string) * arg3: proc result object (Tcl_Obj*) */ probe proc__result(TclDTraceStr name, int code, TclDTraceStr result, struct Tcl_Obj *resultobj); /* * tcl*:::proc-args probe * triggered before proc-entry probe, gives access to string * representation of proc arguments * arg0: proc name (string) * arg1-arg9: proc arguments or NULL (strings) */ probe proc__args(TclDTraceStr name, TclDTraceStr arg1, TclDTraceStr arg2, TclDTraceStr arg3, TclDTraceStr arg4, TclDTraceStr arg5, TclDTraceStr arg6, TclDTraceStr arg7, TclDTraceStr arg8, TclDTraceStr arg9); /* * tcl*:::proc-info probe * triggered before proc-entry probe, gives access to TIP 280 * information for the proc invocation (i.e. [info frame 0]) * arg0: TIP 280 cmd (string) * arg1: TIP 280 type (string) * arg2: TIP 280 proc (string) * arg3: TIP 280 file (string) * arg4: TIP 280 line (int) * arg5: TIP 280 level (int) * arg6: TclOO method (string) * arg7: TclOO class/object (string) */ probe proc__info(TclDTraceStr cmd, TclDTraceStr type, TclDTraceStr proc, TclDTraceStr file, int line, int level, TclDTraceStr method, TclDTraceStr class); /***************************** cmd probes ******************************/ /* * tcl*:::cmd-entry probe * triggered immediately before commmand execution * arg0: command name (string) * arg1: number of arguments (int) * arg2: array of command argument objects (Tcl_Obj**) */ probe cmd__entry(TclDTraceStr name, int objc, struct Tcl_Obj **objv); /* * tcl*:::cmd-return probe * triggered immediately after commmand execution * arg0: command name (string) * arg1: return code (int) */ probe cmd__return(TclDTraceStr name, int code); /* * tcl*:::cmd-result probe * triggered after cmd-return probe and result processing * arg0: command name (string) * arg1: return code (int) * arg2: command result (string) * arg3: command result object (Tcl_Obj*) */ probe cmd__result(TclDTraceStr name, int code, TclDTraceStr result, struct Tcl_Obj *resultobj); /* * tcl*:::cmd-args probe * triggered before cmd-entry probe, gives access to string * representation of command arguments * arg0: command name (string) * arg1-arg9: command arguments or NULL (strings) */ probe cmd__args(TclDTraceStr name, TclDTraceStr arg1, TclDTraceStr arg2, TclDTraceStr arg3, TclDTraceStr arg4, TclDTraceStr arg5, TclDTraceStr arg6, TclDTraceStr arg7, TclDTraceStr arg8, TclDTraceStr arg9); /* * tcl*:::cmd-info probe * triggered before cmd-entry probe, gives access to TIP 280 * information for the command invocation (i.e. [info frame 0]) * arg0: TIP 280 cmd (string) * arg1: TIP 280 type (string) * arg2: TIP 280 proc (string) * arg3: TIP 280 file (string) * arg4: TIP 280 line (int) * arg5: TIP 280 level (int) * arg6: TclOO method (string) * arg7: TclOO class/object (string) */ probe cmd__info(TclDTraceStr cmd, TclDTraceStr type, TclDTraceStr proc, TclDTraceStr file, int line, int level, TclDTraceStr method, TclDTraceStr class); /***************************** inst probes *****************************/ /* * tcl*:::inst-start probe * triggered immediately before execution of a bytecode * arg0: bytecode name (string) * arg1: depth of stack (int) * arg2: top of stack (Tcl_Obj**) */ probe inst__start(TclDTraceStr name, int depth, struct Tcl_Obj **stack); /* * tcl*:::inst-done probe * triggered immediately after execution of a bytecode * arg0: bytecode name (string) * arg1: depth of stack (int) * arg2: top of stack (Tcl_Obj**) */ probe inst__done(TclDTraceStr name, int depth, struct Tcl_Obj **stack); /***************************** obj probes ******************************/ /* * tcl*:::obj-create probe * triggered immediately after a new Tcl_Obj has been created * arg0: object created (Tcl_Obj*) */ probe obj__create(struct Tcl_Obj* obj); /* * tcl*:::obj-free probe * triggered immediately before a Tcl_Obj is freed * arg0: object to be freed (Tcl_Obj*) */ probe obj__free(struct Tcl_Obj* obj); /***************************** tcl probes ******************************/ /* * tcl*:::tcl-probe probe * triggered when the ::tcl::dtrace command is called * arg0-arg9: command arguments (strings) */ probe tcl__probe(TclDTraceStr arg0, TclDTraceStr arg1, TclDTraceStr arg2, TclDTraceStr arg3, TclDTraceStr arg4, TclDTraceStr arg5, TclDTraceStr arg6, TclDTraceStr arg7, TclDTraceStr arg8, TclDTraceStr arg9); }; /* * Tcl types and constants for use in DTrace scripts */ typedef struct Tcl_ObjType { char *name; void *freeIntRepProc; void *dupIntRepProc; void *updateStringProc; void *setFromAnyProc; } Tcl_ObjType; struct Tcl_Obj { int refCount; char *bytes; int length; Tcl_ObjType *typePtr; union { long longValue; double doubleValue; void *otherValuePtr; int64_t wideValue; struct { void *ptr1; void *ptr2; } twoPtrValue; struct { void *ptr; unsigned long value; } ptrAndLongRep; } internalRep; }; enum return_codes { TCL_OK = 0, TCL_ERROR, TCL_RETURN, TCL_BREAK, TCL_CONTINUE }; #pragma D attributes Evolving/Evolving/Common provider tcl provider #pragma D attributes Private/Private/Common provider tcl module #pragma D attributes Private/Private/Common provider tcl function #pragma D attributes Evolving/Evolving/Common provider tcl name #pragma D attributes Evolving/Evolving/Common provider tcl args /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclInterp.c0000644000175000017500000040712512663660065015324 0ustar sergeisergei/* * tclInterp.c -- * * This file implements the "interp" command which allows creation and * manipulation of Tcl interpreters from within Tcl scripts. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 2004 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * A pointer to a string that holds an initialization script that if non-NULL * is evaluated in Tcl_Init() prior to the built-in initialization script * above. This variable can be modified by the function below. */ static const char *tclPreInitScript = NULL; /* Forward declaration */ struct Target; /* * struct Alias: * * Stores information about an alias. Is stored in the slave interpreter and * used by the source command to find the target command in the master when * the source command is invoked. */ typedef struct Alias { Tcl_Obj *token; /* Token for the alias command in the slave * interp. This used to be the command name in * the slave when the alias was first * created. */ Tcl_Interp *targetInterp; /* Interp in which target command will be * invoked. */ Tcl_Command slaveCmd; /* Source command in slave interpreter, bound * to command that invokes the target command * in the target interpreter. */ Tcl_HashEntry *aliasEntryPtr; /* Entry for the alias hash table in slave. * This is used by alias deletion to remove * the alias from the slave interpreter alias * table. */ struct Target *targetPtr; /* Entry for target command in master. This is * used in the master interpreter to map back * from the target command to aliases * redirecting to it. */ int objc; /* Count of Tcl_Obj in the prefix of the * target command to be invoked in the target * interpreter. Additional arguments specified * when calling the alias in the slave interp * will be appended to the prefix before the * command is invoked. */ Tcl_Obj *objPtr; /* The first actual prefix object - the target * command name; this has to be at the end of * the structure, which will be extended to * accomodate the remaining objects in the * prefix. */ } Alias; /* * * struct Slave: * * Used by the "interp" command to record and find information about slave * interpreters. Maps from a command name in the master to information about a * slave interpreter, e.g. what aliases are defined in it. */ typedef struct Slave { Tcl_Interp *masterInterp; /* Master interpreter for this slave. */ Tcl_HashEntry *slaveEntryPtr; /* Hash entry in masters slave table for this * slave interpreter. Used to find this * record, and used when deleting the slave * interpreter to delete it from the master's * table. */ Tcl_Interp *slaveInterp; /* The slave interpreter. */ Tcl_Command interpCmd; /* Interpreter object command. */ Tcl_HashTable aliasTable; /* Table which maps from names of commands in * slave interpreter to struct Alias defined * below. */ } Slave; /* * struct Target: * * Maps from master interpreter commands back to the source commands in slave * interpreters. This is needed because aliases can be created between sibling * interpreters and must be deleted when the target interpreter is deleted. In * case they would not be deleted the source interpreter would be left with a * "dangling pointer". One such record is stored in the Master record of the * master interpreter with the master for each alias which directs to a * command in the master. These records are used to remove the source command * for an from a slave if/when the master is deleted. They are organized in a * doubly-linked list attached to the master interpreter. */ typedef struct Target { Tcl_Command slaveCmd; /* Command for alias in slave interp. */ Tcl_Interp *slaveInterp; /* Slave Interpreter. */ struct Target *nextPtr; /* Next in list of target records, or NULL if * at the end of the list of targets. */ struct Target *prevPtr; /* Previous in list of target records, or NULL * if at the start of the list of targets. */ } Target; /* * struct Master: * * This record is used for two purposes: First, slaveTable (a hashtable) maps * from names of commands to slave interpreters. This hashtable is used to * store information about slave interpreters of this interpreter, to map over * all slaves, etc. The second purpose is to store information about all * aliases in slaves (or siblings) which direct to target commands in this * interpreter (using the targetsPtr doubly-linked list). * * NB: the flags field in the interp structure, used with SAFE_INTERP mask * denotes whether the interpreter is safe or not. Safe interpreters have * restricted functionality, can only create safe slave interpreters and can * only load safe extensions. */ typedef struct Master { Tcl_HashTable slaveTable; /* Hash table for slave interpreters. Maps * from command names to Slave records. */ Target *targetsPtr; /* The head of a doubly-linked list of all the * target records which denote aliases from * slaves or sibling interpreters that direct * to commands in this interpreter. This list * is used to remove dangling pointers from * the slave (or sibling) interpreters when * this interpreter is deleted. */ } Master; /* * The following structure keeps track of all the Master and Slave information * on a per-interp basis. */ typedef struct InterpInfo { Master master; /* Keeps track of all interps for which this * interp is the Master. */ Slave slave; /* Information necessary for this interp to * function as a slave. */ } InterpInfo; /* * Limit callbacks handled by scripts are modelled as structures which are * stored in hashes indexed by a two-word key. Note that the type of the * 'type' field in the key is not int; this is to make sure that things are * likely to work properly on 64-bit architectures. */ typedef struct ScriptLimitCallback { Tcl_Interp *interp; /* The interpreter in which to execute the * callback. */ Tcl_Obj *scriptObj; /* The script to execute to perform the * user-defined part of the callback. */ int type; /* What kind of callback is this. */ Tcl_HashEntry *entryPtr; /* The entry in the hash table maintained by * the target interpreter that refers to this * callback record, or NULL if the entry has * already been deleted from that hash * table. */ } ScriptLimitCallback; typedef struct ScriptLimitCallbackKey { Tcl_Interp *interp; /* The interpreter that the limit callback was * attached to. This is not the interpreter * that the callback runs in! */ long type; /* The type of callback that this is. */ } ScriptLimitCallbackKey; /* * TIP#143 limit handler internal representation. */ struct LimitHandler { int flags; /* The state of this particular handler. */ Tcl_LimitHandlerProc *handlerProc; /* The handler callback. */ ClientData clientData; /* Opaque argument to the handler callback. */ Tcl_LimitHandlerDeleteProc *deleteProc; /* How to delete the clientData. */ LimitHandler *prevPtr; /* Previous item in linked list of * handlers. */ LimitHandler *nextPtr; /* Next item in linked list of handlers. */ }; /* * Values for the LimitHandler flags field. * LIMIT_HANDLER_ACTIVE - Whether the handler is currently being * processed; handlers are never to be entered reentrantly. * LIMIT_HANDLER_DELETED - Whether the handler has been deleted. This * should not normally be observed because when a handler is * deleted it is also spliced out of the list of handlers, but * even so we will be careful. */ #define LIMIT_HANDLER_ACTIVE 0x01 #define LIMIT_HANDLER_DELETED 0x02 /* * Prototypes for local static functions: */ static int AliasCreate(Tcl_Interp *interp, Tcl_Interp *slaveInterp, Tcl_Interp *masterInterp, Tcl_Obj *namePtr, Tcl_Obj *targetPtr, int objc, Tcl_Obj *const objv[]); static int AliasDelete(Tcl_Interp *interp, Tcl_Interp *slaveInterp, Tcl_Obj *namePtr); static int AliasDescribe(Tcl_Interp *interp, Tcl_Interp *slaveInterp, Tcl_Obj *objPtr); static int AliasList(Tcl_Interp *interp, Tcl_Interp *slaveInterp); static int AliasObjCmd(ClientData dummy, Tcl_Interp *currentInterp, int objc, Tcl_Obj *const objv[]); static int AliasNRCmd(ClientData dummy, Tcl_Interp *currentInterp, int objc, Tcl_Obj *const objv[]); static void AliasObjCmdDeleteProc(ClientData clientData); static Tcl_Interp * GetInterp(Tcl_Interp *interp, Tcl_Obj *pathPtr); static Tcl_Interp * GetInterp2(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void InterpInfoDeleteProc(ClientData clientData, Tcl_Interp *interp); static int SlaveBgerror(Tcl_Interp *interp, Tcl_Interp *slaveInterp, int objc, Tcl_Obj *const objv[]); static Tcl_Interp * SlaveCreate(Tcl_Interp *interp, Tcl_Obj *pathPtr, int safe); static int SlaveDebugCmd(Tcl_Interp *interp, Tcl_Interp *slaveInterp, int objc, Tcl_Obj *const objv[]); static int SlaveEval(Tcl_Interp *interp, Tcl_Interp *slaveInterp, int objc, Tcl_Obj *const objv[]); static int SlaveExpose(Tcl_Interp *interp, Tcl_Interp *slaveInterp, int objc, Tcl_Obj *const objv[]); static int SlaveHide(Tcl_Interp *interp, Tcl_Interp *slaveInterp, int objc, Tcl_Obj *const objv[]); static int SlaveHidden(Tcl_Interp *interp, Tcl_Interp *slaveInterp); static int SlaveInvokeHidden(Tcl_Interp *interp, Tcl_Interp *slaveInterp, const char *namespaceName, int objc, Tcl_Obj *const objv[]); static int SlaveMarkTrusted(Tcl_Interp *interp, Tcl_Interp *slaveInterp); static int SlaveObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void SlaveObjCmdDeleteProc(ClientData clientData); static int SlaveRecursionLimit(Tcl_Interp *interp, Tcl_Interp *slaveInterp, int objc, Tcl_Obj *const objv[]); static int SlaveCommandLimitCmd(Tcl_Interp *interp, Tcl_Interp *slaveInterp, int consumedObjc, int objc, Tcl_Obj *const objv[]); static int SlaveTimeLimitCmd(Tcl_Interp *interp, Tcl_Interp *slaveInterp, int consumedObjc, int objc, Tcl_Obj *const objv[]); static void InheritLimitsFromMaster(Tcl_Interp *slaveInterp, Tcl_Interp *masterInterp); static void SetScriptLimitCallback(Tcl_Interp *interp, int type, Tcl_Interp *targetInterp, Tcl_Obj *scriptObj); static void CallScriptLimitCallback(ClientData clientData, Tcl_Interp *interp); static void DeleteScriptLimitCallback(ClientData clientData); static void RunLimitHandlers(LimitHandler *handlerPtr, Tcl_Interp *interp); static void TimeLimitCallback(ClientData clientData); /* NRE enabling */ static Tcl_NRPostProc NRPostInvokeHidden; static Tcl_ObjCmdProc NRInterpCmd; static Tcl_ObjCmdProc NRSlaveCmd; /* *---------------------------------------------------------------------- * * TclSetPreInitScript -- * * This routine is used to change the value of the internal variable, * tclPreInitScript. * * Results: * Returns the current value of tclPreInitScript. * * Side effects: * Changes the way Tcl_Init() routine behaves. * *---------------------------------------------------------------------- */ const char * TclSetPreInitScript( const char *string) /* Pointer to a script. */ { const char *prevString = tclPreInitScript; tclPreInitScript = string; return(prevString); } /* *---------------------------------------------------------------------- * * Tcl_Init -- * * This function is typically invoked by Tcl_AppInit functions to find * and source the "init.tcl" script, which should exist somewhere on the * Tcl library path. * * Results: * Returns a standard Tcl completion code and sets the interp's result if * there is an error. * * Side effects: * Depends on what's in the init.tcl script. * *---------------------------------------------------------------------- */ int Tcl_Init( Tcl_Interp *interp) /* Interpreter to initialize. */ { if (tclPreInitScript != NULL) { if (Tcl_Eval(interp, tclPreInitScript) == TCL_ERROR) { return TCL_ERROR; } } /* * In order to find init.tcl during initialization, the following script * is invoked by Tcl_Init(). It looks in several different directories: * * $tcl_library - can specify a primary location, if set, no * other locations will be checked. This is the * recommended way for a program that embeds * Tcl to specifically tell Tcl where to find * an init.tcl file. * * $env(TCL_LIBRARY) - highest priority so user can always override * the search path unless the application has * specified an exact directory above * * $tclDefaultLibrary - INTERNAL: This variable is set by Tcl on * those platforms where it can determine at * runtime the directory where it expects the * init.tcl file to be. After [tclInit] reads * and uses this value, it [unset]s it. * External users of Tcl should not make use of * the variable to customize [tclInit]. * * $tcl_libPath - OBSOLETE: This variable is no longer set by * Tcl itself, but [tclInit] examines it in * case some program that embeds Tcl is * customizing [tclInit] by setting this * variable to a list of directories in which * to search. * * [tcl::pkgconfig get scriptdir,runtime] * - the directory determined by configure to be * the place where Tcl's script library is to * be installed. * * The first directory on this path that contains a valid init.tcl script * will be set as the value of tcl_library. * * Note that this entire search mechanism can be bypassed by defining an * alternate tclInit command before calling Tcl_Init(). */ return Tcl_Eval(interp, "if {[namespace which -command tclInit] eq \"\"} {\n" " proc tclInit {} {\n" " global tcl_libPath tcl_library env tclDefaultLibrary\n" " rename tclInit {}\n" " if {[info exists tcl_library]} {\n" " set scripts {{set tcl_library}}\n" " } else {\n" " set scripts {}\n" " if {[info exists env(TCL_LIBRARY)] && ($env(TCL_LIBRARY) ne {})} {\n" " lappend scripts {set env(TCL_LIBRARY)}\n" " lappend scripts {\n" "if {[regexp ^tcl(.*)$ [file tail $env(TCL_LIBRARY)] -> tail] == 0} continue\n" "if {$tail eq [info tclversion]} continue\n" "file join [file dirname $env(TCL_LIBRARY)] tcl[info tclversion]}\n" " }\n" " if {[info exists tclDefaultLibrary]} {\n" " lappend scripts {set tclDefaultLibrary}\n" " } else {\n" " lappend scripts {::tcl::pkgconfig get scriptdir,runtime}\n" " }\n" " lappend scripts {\n" "set parentDir [file dirname [file dirname [info nameofexecutable]]]\n" "set grandParentDir [file dirname $parentDir]\n" "file join $parentDir lib tcl[info tclversion]} \\\n" " {file join $grandParentDir lib tcl[info tclversion]} \\\n" " {file join $parentDir library} \\\n" " {file join $grandParentDir library} \\\n" " {file join $grandParentDir tcl[info patchlevel] library} \\\n" " {\n" "file join [file dirname $grandParentDir] tcl[info patchlevel] library}\n" " if {[info exists tcl_libPath]\n" " && [catch {llength $tcl_libPath} len] == 0} {\n" " for {set i 0} {$i < $len} {incr i} {\n" " lappend scripts [list lindex \\$tcl_libPath $i]\n" " }\n" " }\n" " }\n" " set dirs {}\n" " set errors {}\n" " foreach script $scripts {\n" " lappend dirs [eval $script]\n" " set tcl_library [lindex $dirs end]\n" " set tclfile [file join $tcl_library init.tcl]\n" " if {[file exists $tclfile]} {\n" " if {[catch {uplevel #0 [list source $tclfile]} msg opts]} {\n" " append errors \"$tclfile: $msg\n\"\n" " append errors \"[dict get $opts -errorinfo]\n\"\n" " continue\n" " }\n" " unset -nocomplain tclDefaultLibrary\n" " return\n" " }\n" " }\n" " unset -nocomplain tclDefaultLibrary\n" " set msg \"Can't find a usable init.tcl in the following directories: \n\"\n" " append msg \" $dirs\n\n\"\n" " append msg \"$errors\n\n\"\n" " append msg \"This probably means that Tcl wasn't installed properly.\n\"\n" " error $msg\n" " }\n" "}\n" "tclInit"); } /* *--------------------------------------------------------------------------- * * TclInterpInit -- * * Initializes the invoking interpreter for using the master, slave and * safe interp facilities. This is called from inside Tcl_CreateInterp(). * * Results: * Always returns TCL_OK for backwards compatibility. * * Side effects: * Adds the "interp" command to an interpreter and initializes the * interpInfoPtr field of the invoking interpreter. * *--------------------------------------------------------------------------- */ int TclInterpInit( Tcl_Interp *interp) /* Interpreter to initialize. */ { InterpInfo *interpInfoPtr; Master *masterPtr; Slave *slavePtr; interpInfoPtr = ckalloc(sizeof(InterpInfo)); ((Interp *) interp)->interpInfo = interpInfoPtr; masterPtr = &interpInfoPtr->master; Tcl_InitHashTable(&masterPtr->slaveTable, TCL_STRING_KEYS); masterPtr->targetsPtr = NULL; slavePtr = &interpInfoPtr->slave; slavePtr->masterInterp = NULL; slavePtr->slaveEntryPtr = NULL; slavePtr->slaveInterp = interp; slavePtr->interpCmd = NULL; Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS); Tcl_NRCreateCommand(interp, "interp", Tcl_InterpObjCmd, NRInterpCmd, NULL, NULL); Tcl_CallWhenDeleted(interp, InterpInfoDeleteProc, NULL); return TCL_OK; } /* *--------------------------------------------------------------------------- * * InterpInfoDeleteProc -- * * Invoked when an interpreter is being deleted. It releases all storage * used by the master/slave/safe interpreter facilities. * * Results: * None. * * Side effects: * Cleans up storage. Sets the interpInfoPtr field of the interp to NULL. * *--------------------------------------------------------------------------- */ static void InterpInfoDeleteProc( ClientData clientData, /* Ignored. */ Tcl_Interp *interp) /* Interp being deleted. All commands for * slave interps should already be deleted. */ { InterpInfo *interpInfoPtr; Slave *slavePtr; Master *masterPtr; Target *targetPtr; interpInfoPtr = (InterpInfo *) ((Interp *) interp)->interpInfo; /* * There shouldn't be any commands left. */ masterPtr = &interpInfoPtr->master; if (masterPtr->slaveTable.numEntries != 0) { Tcl_Panic("InterpInfoDeleteProc: still exist commands"); } Tcl_DeleteHashTable(&masterPtr->slaveTable); /* * Tell any interps that have aliases to this interp that they should * delete those aliases. If the other interp was already dead, it would * have removed the target record already. */ for (targetPtr = masterPtr->targetsPtr; targetPtr != NULL; ) { Target *tmpPtr = targetPtr->nextPtr; Tcl_DeleteCommandFromToken(targetPtr->slaveInterp, targetPtr->slaveCmd); targetPtr = tmpPtr; } slavePtr = &interpInfoPtr->slave; if (slavePtr->interpCmd != NULL) { /* * Tcl_DeleteInterp() was called on this interpreter, rather "interp * delete" or the equivalent deletion of the command in the master. * First ensure that the cleanup callback doesn't try to delete the * interp again. */ slavePtr->slaveInterp = NULL; Tcl_DeleteCommandFromToken(slavePtr->masterInterp, slavePtr->interpCmd); } /* * There shouldn't be any aliases left. */ if (slavePtr->aliasTable.numEntries != 0) { Tcl_Panic("InterpInfoDeleteProc: still exist aliases"); } Tcl_DeleteHashTable(&slavePtr->aliasTable); ckfree(interpInfoPtr); } /* *---------------------------------------------------------------------- * * Tcl_InterpObjCmd -- * * This function is invoked to process the "interp" Tcl command. See the * user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_InterpObjCmd( ClientData clientData, /* Unused. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, NRInterpCmd, clientData, objc, objv); } static int NRInterpCmd( ClientData clientData, /* Unused. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Interp *slaveInterp; int index; static const char *const options[] = { "alias", "aliases", "bgerror", "cancel", "create", "debug", "delete", "eval", "exists", "expose", "hide", "hidden", "issafe", "invokehidden", "limit", "marktrusted", "recursionlimit", "slaves", "share", "target", "transfer", NULL }; enum option { OPT_ALIAS, OPT_ALIASES, OPT_BGERROR, OPT_CANCEL, OPT_CREATE, OPT_DEBUG, OPT_DELETE, OPT_EVAL, OPT_EXISTS, OPT_EXPOSE, OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHID, OPT_LIMIT, OPT_MARKTRUSTED,OPT_RECLIMIT, OPT_SLAVES, OPT_SHARE, OPT_TARGET, OPT_TRANSFER }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum option) index) { case OPT_ALIAS: { Tcl_Interp *masterInterp; if (objc < 4) { aliasArgs: Tcl_WrongNumArgs(interp, 2, objv, "slavePath slaveCmd ?masterPath masterCmd? ?arg ...?"); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[2]); if (slaveInterp == NULL) { return TCL_ERROR; } if (objc == 4) { return AliasDescribe(interp, slaveInterp, objv[3]); } if ((objc == 5) && (TclGetString(objv[4])[0] == '\0')) { return AliasDelete(interp, slaveInterp, objv[3]); } if (objc > 5) { masterInterp = GetInterp(interp, objv[4]); if (masterInterp == NULL) { return TCL_ERROR; } if (TclGetString(objv[5])[0] == '\0') { if (objc == 6) { return AliasDelete(interp, slaveInterp, objv[3]); } } else { return AliasCreate(interp, slaveInterp, masterInterp, objv[3], objv[5], objc - 6, objv + 6); } } goto aliasArgs; } case OPT_ALIASES: slaveInterp = GetInterp2(interp, objc, objv); if (slaveInterp == NULL) { return TCL_ERROR; } return AliasList(interp, slaveInterp); case OPT_BGERROR: if (objc != 3 && objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "path ?cmdPrefix?"); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[2]); if (slaveInterp == NULL) { return TCL_ERROR; } return SlaveBgerror(interp, slaveInterp, objc - 3, objv + 3); case OPT_CANCEL: { int i, flags; Tcl_Obj *resultObjPtr; static const char *const cancelOptions[] = { "-unwind", "--", NULL }; enum option { OPT_UNWIND, OPT_LAST }; flags = 0; for (i = 2; i < objc; i++) { if (TclGetString(objv[i])[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], cancelOptions, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum option) index) { case OPT_UNWIND: /* * The evaluation stack in the target interp is to be unwound. */ flags |= TCL_CANCEL_UNWIND; break; case OPT_LAST: i++; goto endOfForLoop; } } endOfForLoop: if ((i + 2) < objc) { Tcl_WrongNumArgs(interp, 2, objv, "?-unwind? ?--? ?path? ?result?"); return TCL_ERROR; } /* * Did they specify a slave interp to cancel the script in progress * in? If not, use the current interp. */ if (i < objc) { slaveInterp = GetInterp(interp, objv[i]); if (slaveInterp == NULL) { return TCL_ERROR; } i++; } else { slaveInterp = interp; } if (i < objc) { resultObjPtr = objv[i]; /* * Tcl_CancelEval removes this reference. */ Tcl_IncrRefCount(resultObjPtr); i++; } else { resultObjPtr = NULL; } return Tcl_CancelEval(slaveInterp, resultObjPtr, 0, flags); } case OPT_CREATE: { int i, last, safe; Tcl_Obj *slavePtr; char buf[16 + TCL_INTEGER_SPACE]; static const char *const createOptions[] = { "-safe", "--", NULL }; enum option { OPT_SAFE, OPT_LAST }; safe = Tcl_IsSafe(interp); /* * Weird historical rules: "-safe" is accepted at the end, too. */ slavePtr = NULL; last = 0; for (i = 2; i < objc; i++) { if ((last == 0) && (Tcl_GetString(objv[i])[0] == '-')) { if (Tcl_GetIndexFromObj(interp, objv[i], createOptions, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (index == OPT_SAFE) { safe = 1; continue; } i++; last = 1; } if (slavePtr != NULL) { Tcl_WrongNumArgs(interp, 2, objv, "?-safe? ?--? ?path?"); return TCL_ERROR; } if (i < objc) { slavePtr = objv[i]; } } buf[0] = '\0'; if (slavePtr == NULL) { /* * Create an anonymous interpreter -- we choose its name and the * name of the command. We check that the command name that we use * for the interpreter does not collide with an existing command * in the master interpreter. */ for (i = 0; ; i++) { Tcl_CmdInfo cmdInfo; sprintf(buf, "interp%d", i); if (Tcl_GetCommandInfo(interp, buf, &cmdInfo) == 0) { break; } } slavePtr = Tcl_NewStringObj(buf, -1); } if (SlaveCreate(interp, slavePtr, safe) == NULL) { if (buf[0] != '\0') { Tcl_DecrRefCount(slavePtr); } return TCL_ERROR; } Tcl_SetObjResult(interp, slavePtr); return TCL_OK; } case OPT_DEBUG: /* TIP #378 */ /* * Currently only -frame supported, otherwise ?-option ?value?? */ if (objc < 3 || objc > 5) { Tcl_WrongNumArgs(interp, 2, objv, "path ?-frame ?bool??"); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[2]); if (slaveInterp == NULL) { return TCL_ERROR; } return SlaveDebugCmd(interp, slaveInterp, objc - 3, objv + 3); case OPT_DELETE: { int i; InterpInfo *iiPtr; for (i = 2; i < objc; i++) { slaveInterp = GetInterp(interp, objv[i]); if (slaveInterp == NULL) { return TCL_ERROR; } else if (slaveInterp == interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot delete the current interpreter", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "DELETESELF", NULL); return TCL_ERROR; } iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo; Tcl_DeleteCommandFromToken(iiPtr->slave.masterInterp, iiPtr->slave.interpCmd); } return TCL_OK; } case OPT_EVAL: if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, "path arg ?arg ...?"); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[2]); if (slaveInterp == NULL) { return TCL_ERROR; } return SlaveEval(interp, slaveInterp, objc - 3, objv + 3); case OPT_EXISTS: { int exists = 1; slaveInterp = GetInterp2(interp, objc, objv); if (slaveInterp == NULL) { if (objc > 3) { return TCL_ERROR; } Tcl_ResetResult(interp); exists = 0; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(exists)); return TCL_OK; } case OPT_EXPOSE: if ((objc < 4) || (objc > 5)) { Tcl_WrongNumArgs(interp, 2, objv, "path hiddenCmdName ?cmdName?"); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[2]); if (slaveInterp == NULL) { return TCL_ERROR; } return SlaveExpose(interp, slaveInterp, objc - 3, objv + 3); case OPT_HIDE: if ((objc < 4) || (objc > 5)) { Tcl_WrongNumArgs(interp, 2, objv, "path cmdName ?hiddenCmdName?"); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[2]); if (slaveInterp == NULL) { return TCL_ERROR; } return SlaveHide(interp, slaveInterp, objc - 3, objv + 3); case OPT_HIDDEN: slaveInterp = GetInterp2(interp, objc, objv); if (slaveInterp == NULL) { return TCL_ERROR; } return SlaveHidden(interp, slaveInterp); case OPT_ISSAFE: slaveInterp = GetInterp2(interp, objc, objv); if (slaveInterp == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_IsSafe(slaveInterp))); return TCL_OK; case OPT_INVOKEHID: { int i; const char *namespaceName; static const char *const hiddenOptions[] = { "-global", "-namespace", "--", NULL }; enum hiddenOption { OPT_GLOBAL, OPT_NAMESPACE, OPT_LAST }; namespaceName = NULL; for (i = 3; i < objc; i++) { if (TclGetString(objv[i])[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (index == OPT_GLOBAL) { namespaceName = "::"; } else if (index == OPT_NAMESPACE) { if (++i == objc) { /* There must be more arguments. */ break; } else { namespaceName = TclGetString(objv[i]); } } else { i++; break; } } if (objc - i < 1) { Tcl_WrongNumArgs(interp, 2, objv, "path ?-namespace ns? ?-global? ?--? cmd ?arg ..?"); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[2]); if (slaveInterp == NULL) { return TCL_ERROR; } return SlaveInvokeHidden(interp, slaveInterp, namespaceName, objc - i, objv + i); } case OPT_LIMIT: { static const char *const limitTypes[] = { "commands", "time", NULL }; enum LimitTypes { LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME }; int limitType; if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, "path limitType ?-option value ...?"); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[2]); if (slaveInterp == NULL) { return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[3], limitTypes, "limit type", 0, &limitType) != TCL_OK) { return TCL_ERROR; } switch ((enum LimitTypes) limitType) { case LIMIT_TYPE_COMMANDS: return SlaveCommandLimitCmd(interp, slaveInterp, 4, objc,objv); case LIMIT_TYPE_TIME: return SlaveTimeLimitCmd(interp, slaveInterp, 4, objc, objv); } } case OPT_MARKTRUSTED: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "path"); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[2]); if (slaveInterp == NULL) { return TCL_ERROR; } return SlaveMarkTrusted(interp, slaveInterp); case OPT_RECLIMIT: if (objc != 3 && objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "path ?newlimit?"); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[2]); if (slaveInterp == NULL) { return TCL_ERROR; } return SlaveRecursionLimit(interp, slaveInterp, objc - 3, objv + 3); case OPT_SLAVES: { InterpInfo *iiPtr; Tcl_Obj *resultPtr; Tcl_HashEntry *hPtr; Tcl_HashSearch hashSearch; char *string; slaveInterp = GetInterp2(interp, objc, objv); if (slaveInterp == NULL) { return TCL_ERROR; } iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo; resultPtr = Tcl_NewObj(); hPtr = Tcl_FirstHashEntry(&iiPtr->master.slaveTable, &hashSearch); for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&hashSearch)) { string = Tcl_GetHashKey(&iiPtr->master.slaveTable, hPtr); Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj(string, -1)); } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } case OPT_TRANSFER: case OPT_SHARE: { Tcl_Interp *masterInterp; /* The master of the slave. */ Tcl_Channel chan; if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "srcPath channelId destPath"); return TCL_ERROR; } masterInterp = GetInterp(interp, objv[2]); if (masterInterp == NULL) { return TCL_ERROR; } chan = Tcl_GetChannel(masterInterp, TclGetString(objv[3]), NULL); if (chan == NULL) { Tcl_TransferResult(masterInterp, TCL_OK, interp); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[4]); if (slaveInterp == NULL) { return TCL_ERROR; } Tcl_RegisterChannel(slaveInterp, chan); if (index == OPT_TRANSFER) { /* * When transferring, as opposed to sharing, we must unhitch the * channel from the interpreter where it started. */ if (Tcl_UnregisterChannel(masterInterp, chan) != TCL_OK) { Tcl_TransferResult(masterInterp, TCL_OK, interp); return TCL_ERROR; } } return TCL_OK; } case OPT_TARGET: { InterpInfo *iiPtr; Tcl_HashEntry *hPtr; Alias *aliasPtr; const char *aliasName; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "path alias"); return TCL_ERROR; } slaveInterp = GetInterp(interp, objv[2]); if (slaveInterp == NULL) { return TCL_ERROR; } aliasName = TclGetString(objv[3]); iiPtr = (InterpInfo *) ((Interp *) slaveInterp)->interpInfo; hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "alias \"%s\" in path \"%s\" not found", aliasName, Tcl_GetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, NULL); return TCL_ERROR; } aliasPtr = Tcl_GetHashValue(hPtr); if (Tcl_GetInterpPath(interp, aliasPtr->targetInterp) != TCL_OK) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "target interpreter for alias \"%s\" in path \"%s\" is " "not my descendant", aliasName, Tcl_GetString(objv[2]))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "TARGETSHROUDED", NULL); return TCL_ERROR; } return TCL_OK; } } return TCL_OK; } /* *--------------------------------------------------------------------------- * * GetInterp2 -- * * Helper function for Tcl_InterpObjCmd() to convert the interp name * potentially specified on the command line to an Tcl_Interp. * * Results: * The return value is the interp specified on the command line, or the * interp argument itself if no interp was specified on the command line. * If the interp could not be found or the wrong number of arguments was * specified on the command line, the return value is NULL and an error * message is left in the interp's result. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static Tcl_Interp * GetInterp2( Tcl_Interp *interp, /* Default interp if no interp was specified * on the command line. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc == 2) { return interp; } else if (objc == 3) { return GetInterp(interp, objv[2]); } else { Tcl_WrongNumArgs(interp, 2, objv, "?path?"); return NULL; } } /* *---------------------------------------------------------------------- * * Tcl_CreateAlias -- * * Creates an alias between two interpreters. * * Results: * A standard Tcl result. * * Side effects: * Creates a new alias, manipulates the result field of slaveInterp. * *---------------------------------------------------------------------- */ int Tcl_CreateAlias( Tcl_Interp *slaveInterp, /* Interpreter for source command. */ const char *slaveCmd, /* Command to install in slave. */ Tcl_Interp *targetInterp, /* Interpreter for target command. */ const char *targetCmd, /* Name of target command. */ int argc, /* How many additional arguments? */ const char *const *argv) /* These are the additional args. */ { Tcl_Obj *slaveObjPtr, *targetObjPtr; Tcl_Obj **objv; int i; int result; objv = TclStackAlloc(slaveInterp, (unsigned) sizeof(Tcl_Obj *) * argc); for (i = 0; i < argc; i++) { objv[i] = Tcl_NewStringObj(argv[i], -1); Tcl_IncrRefCount(objv[i]); } slaveObjPtr = Tcl_NewStringObj(slaveCmd, -1); Tcl_IncrRefCount(slaveObjPtr); targetObjPtr = Tcl_NewStringObj(targetCmd, -1); Tcl_IncrRefCount(targetObjPtr); result = AliasCreate(slaveInterp, slaveInterp, targetInterp, slaveObjPtr, targetObjPtr, argc, objv); for (i = 0; i < argc; i++) { Tcl_DecrRefCount(objv[i]); } TclStackFree(slaveInterp, objv); Tcl_DecrRefCount(targetObjPtr); Tcl_DecrRefCount(slaveObjPtr); return result; } /* *---------------------------------------------------------------------- * * Tcl_CreateAliasObj -- * * Object version: Creates an alias between two interpreters. * * Results: * A standard Tcl result. * * Side effects: * Creates a new alias. * *---------------------------------------------------------------------- */ int Tcl_CreateAliasObj( Tcl_Interp *slaveInterp, /* Interpreter for source command. */ const char *slaveCmd, /* Command to install in slave. */ Tcl_Interp *targetInterp, /* Interpreter for target command. */ const char *targetCmd, /* Name of target command. */ int objc, /* How many additional arguments? */ Tcl_Obj *const objv[]) /* Argument vector. */ { Tcl_Obj *slaveObjPtr, *targetObjPtr; int result; slaveObjPtr = Tcl_NewStringObj(slaveCmd, -1); Tcl_IncrRefCount(slaveObjPtr); targetObjPtr = Tcl_NewStringObj(targetCmd, -1); Tcl_IncrRefCount(targetObjPtr); result = AliasCreate(slaveInterp, slaveInterp, targetInterp, slaveObjPtr, targetObjPtr, objc, objv); Tcl_DecrRefCount(slaveObjPtr); Tcl_DecrRefCount(targetObjPtr); return result; } /* *---------------------------------------------------------------------- * * Tcl_GetAlias -- * * Gets information about an alias. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetAlias( Tcl_Interp *interp, /* Interp to start search from. */ const char *aliasName, /* Name of alias to find. */ Tcl_Interp **targetInterpPtr, /* (Return) target interpreter. */ const char **targetNamePtr, /* (Return) name of target command. */ int *argcPtr, /* (Return) count of addnl args. */ const char ***argvPtr) /* (Return) additional arguments. */ { InterpInfo *iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo; Tcl_HashEntry *hPtr; Alias *aliasPtr; int i, objc; Tcl_Obj **objv; hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "alias \"%s\" not found", aliasName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, NULL); return TCL_ERROR; } aliasPtr = Tcl_GetHashValue(hPtr); objc = aliasPtr->objc; objv = &aliasPtr->objPtr; if (targetInterpPtr != NULL) { *targetInterpPtr = aliasPtr->targetInterp; } if (targetNamePtr != NULL) { *targetNamePtr = TclGetString(objv[0]); } if (argcPtr != NULL) { *argcPtr = objc - 1; } if (argvPtr != NULL) { *argvPtr = (const char **) ckalloc(sizeof(const char *) * (objc - 1)); for (i = 1; i < objc; i++) { (*argvPtr)[i - 1] = TclGetString(objv[i]); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetAliasObj -- * * Object version: Gets information about an alias. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetAliasObj( Tcl_Interp *interp, /* Interp to start search from. */ const char *aliasName, /* Name of alias to find. */ Tcl_Interp **targetInterpPtr, /* (Return) target interpreter. */ const char **targetNamePtr, /* (Return) name of target command. */ int *objcPtr, /* (Return) count of addnl args. */ Tcl_Obj ***objvPtr) /* (Return) additional args. */ { InterpInfo *iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo; Tcl_HashEntry *hPtr; Alias *aliasPtr; int objc; Tcl_Obj **objv; hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "alias \"%s\" not found", aliasName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", aliasName, NULL); return TCL_ERROR; } aliasPtr = Tcl_GetHashValue(hPtr); objc = aliasPtr->objc; objv = &aliasPtr->objPtr; if (targetInterpPtr != NULL) { *targetInterpPtr = aliasPtr->targetInterp; } if (targetNamePtr != NULL) { *targetNamePtr = TclGetString(objv[0]); } if (objcPtr != NULL) { *objcPtr = objc - 1; } if (objvPtr != NULL) { *objvPtr = objv + 1; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclPreventAliasLoop -- * * When defining an alias or renaming a command, prevent an alias loop * from being formed. * * Results: * A standard Tcl object result. * * Side effects: * If TCL_ERROR is returned, the function also stores an error message in * the interpreter's result object. * * NOTE: * This function is public internal (instead of being static to this * file) because it is also used from TclRenameCommand. * *---------------------------------------------------------------------- */ int TclPreventAliasLoop( Tcl_Interp *interp, /* Interp in which to report errors. */ Tcl_Interp *cmdInterp, /* Interp in which the command is being * defined. */ Tcl_Command cmd) /* Tcl command we are attempting to define. */ { Command *cmdPtr = (Command *) cmd; Alias *aliasPtr, *nextAliasPtr; Tcl_Command aliasCmd; Command *aliasCmdPtr; /* * If we are not creating or renaming an alias, then it is always OK to * create or rename the command. */ if (cmdPtr->objProc != AliasObjCmd) { return TCL_OK; } /* * OK, we are dealing with an alias, so traverse the chain of aliases. If * we encounter the alias we are defining (or renaming to) any in the * chain then we have a loop. */ aliasPtr = cmdPtr->objClientData; nextAliasPtr = aliasPtr; while (1) { Tcl_Obj *cmdNamePtr; /* * If the target of the next alias in the chain is the same as the * source alias, we have a loop. */ if (Tcl_InterpDeleted(nextAliasPtr->targetInterp)) { /* * The slave interpreter can be deleted while creating the alias. * [Bug #641195] */ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "cannot define or rename alias \"%s\": interpreter deleted", Tcl_GetCommandName(cmdInterp, cmd))); return TCL_ERROR; } cmdNamePtr = nextAliasPtr->objPtr; aliasCmd = Tcl_FindCommand(nextAliasPtr->targetInterp, TclGetString(cmdNamePtr), Tcl_GetGlobalNamespace(nextAliasPtr->targetInterp), /*flags*/ 0); if (aliasCmd == NULL) { return TCL_OK; } aliasCmdPtr = (Command *) aliasCmd; if (aliasCmdPtr == cmdPtr) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "cannot define or rename alias \"%s\": would create a loop", Tcl_GetCommandName(cmdInterp, cmd))); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "ALIASLOOP", NULL); return TCL_ERROR; } /* * Otherwise, follow the chain one step further. See if the target * command is an alias - if so, follow the loop to its target command. * Otherwise we do not have a loop. */ if (aliasCmdPtr->objProc != AliasObjCmd) { return TCL_OK; } nextAliasPtr = aliasCmdPtr->objClientData; } /* NOTREACHED */ } /* *---------------------------------------------------------------------- * * AliasCreate -- * * Helper function to do the work to actually create an alias. * * Results: * A standard Tcl result. * * Side effects: * An alias command is created and entered into the alias table for the * slave interpreter. * *---------------------------------------------------------------------- */ static int AliasCreate( Tcl_Interp *interp, /* Interp for error reporting. */ Tcl_Interp *slaveInterp, /* Interp where alias cmd will live or from * which alias will be deleted. */ Tcl_Interp *masterInterp, /* Interp in which target command will be * invoked. */ Tcl_Obj *namePtr, /* Name of alias cmd. */ Tcl_Obj *targetNamePtr, /* Name of target cmd. */ int objc, /* Additional arguments to store */ Tcl_Obj *const objv[]) /* with alias. */ { Alias *aliasPtr; Tcl_HashEntry *hPtr; Target *targetPtr; Slave *slavePtr; Master *masterPtr; Tcl_Obj **prefv; int isNew, i; aliasPtr = ckalloc(sizeof(Alias) + objc * sizeof(Tcl_Obj *)); aliasPtr->token = namePtr; Tcl_IncrRefCount(aliasPtr->token); aliasPtr->targetInterp = masterInterp; aliasPtr->objc = objc + 1; prefv = &aliasPtr->objPtr; *prefv = targetNamePtr; Tcl_IncrRefCount(targetNamePtr); for (i = 0; i < objc; i++) { *(++prefv) = objv[i]; Tcl_IncrRefCount(objv[i]); } Tcl_Preserve(slaveInterp); Tcl_Preserve(masterInterp); if (slaveInterp == masterInterp) { aliasPtr->slaveCmd = Tcl_NRCreateCommand(slaveInterp, TclGetString(namePtr), AliasObjCmd, AliasNRCmd, aliasPtr, AliasObjCmdDeleteProc); } else { aliasPtr->slaveCmd = Tcl_CreateObjCommand(slaveInterp, TclGetString(namePtr), AliasObjCmd, aliasPtr, AliasObjCmdDeleteProc); } if (TclPreventAliasLoop(interp, slaveInterp, aliasPtr->slaveCmd) != TCL_OK) { /* * Found an alias loop! The last call to Tcl_CreateObjCommand made the * alias point to itself. Delete the command and its alias record. Be * careful to wipe out its client data first, so the command doesn't * try to delete itself. */ Command *cmdPtr; Tcl_DecrRefCount(aliasPtr->token); Tcl_DecrRefCount(targetNamePtr); for (i = 0; i < objc; i++) { Tcl_DecrRefCount(objv[i]); } cmdPtr = (Command *) aliasPtr->slaveCmd; cmdPtr->clientData = NULL; cmdPtr->deleteProc = NULL; cmdPtr->deleteData = NULL; Tcl_DeleteCommandFromToken(slaveInterp, aliasPtr->slaveCmd); ckfree(aliasPtr); /* * The result was already set by TclPreventAliasLoop. */ Tcl_Release(slaveInterp); Tcl_Release(masterInterp); return TCL_ERROR; } /* * Make an entry in the alias table. If it already exists, retry. */ slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; while (1) { Tcl_Obj *newToken; const char *string; string = TclGetString(aliasPtr->token); hPtr = Tcl_CreateHashEntry(&slavePtr->aliasTable, string, &isNew); if (isNew != 0) { break; } /* * The alias name cannot be used as unique token, it is already taken. * We can produce a unique token by prepending "::" repeatedly. This * algorithm is a stop-gap to try to maintain the command name as * token for most use cases, fearful of possible backwards compat * problems. A better algorithm would produce unique tokens that need * not be related to the command name. * * ATTENTION: the tests in interp.test and possibly safe.test depend * on the precise definition of these tokens. */ TclNewLiteralStringObj(newToken, "::"); Tcl_AppendObjToObj(newToken, aliasPtr->token); Tcl_DecrRefCount(aliasPtr->token); aliasPtr->token = newToken; Tcl_IncrRefCount(aliasPtr->token); } aliasPtr->aliasEntryPtr = hPtr; Tcl_SetHashValue(hPtr, aliasPtr); /* * Create the new command. We must do it after deleting any old command, * because the alias may be pointing at a renamed alias, as in: * * interp alias {} foo {} bar # Create an alias "foo" * rename foo zop # Now rename the alias * interp alias {} foo {} zop # Now recreate "foo"... */ targetPtr = ckalloc(sizeof(Target)); targetPtr->slaveCmd = aliasPtr->slaveCmd; targetPtr->slaveInterp = slaveInterp; masterPtr = &((InterpInfo*) ((Interp*) masterInterp)->interpInfo)->master; targetPtr->nextPtr = masterPtr->targetsPtr; targetPtr->prevPtr = NULL; if (masterPtr->targetsPtr != NULL) { masterPtr->targetsPtr->prevPtr = targetPtr; } masterPtr->targetsPtr = targetPtr; aliasPtr->targetPtr = targetPtr; Tcl_SetObjResult(interp, aliasPtr->token); Tcl_Release(slaveInterp); Tcl_Release(masterInterp); return TCL_OK; } /* *---------------------------------------------------------------------- * * AliasDelete -- * * Deletes the given alias from the slave interpreter given. * * Results: * A standard Tcl result. * * Side effects: * Deletes the alias from the slave interpreter. * *---------------------------------------------------------------------- */ static int AliasDelete( Tcl_Interp *interp, /* Interpreter for result & errors. */ Tcl_Interp *slaveInterp, /* Interpreter containing alias. */ Tcl_Obj *namePtr) /* Name of alias to delete. */ { Slave *slavePtr; Alias *aliasPtr; Tcl_HashEntry *hPtr; /* * If the alias has been renamed in the slave, the master can still use * the original name (with which it was created) to find the alias to * delete it. */ slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; hPtr = Tcl_FindHashEntry(&slavePtr->aliasTable, TclGetString(namePtr)); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "alias \"%s\" not found", TclGetString(namePtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ALIAS", TclGetString(namePtr), NULL); return TCL_ERROR; } aliasPtr = Tcl_GetHashValue(hPtr); Tcl_DeleteCommandFromToken(slaveInterp, aliasPtr->slaveCmd); return TCL_OK; } /* *---------------------------------------------------------------------- * * AliasDescribe -- * * Sets the interpreter's result object to a Tcl list describing the * given alias in the given interpreter: its target command and the * additional arguments to prepend to any invocation of the alias. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int AliasDescribe( Tcl_Interp *interp, /* Interpreter for result & errors. */ Tcl_Interp *slaveInterp, /* Interpreter containing alias. */ Tcl_Obj *namePtr) /* Name of alias to describe. */ { Slave *slavePtr; Tcl_HashEntry *hPtr; Alias *aliasPtr; Tcl_Obj *prefixPtr; /* * If the alias has been renamed in the slave, the master can still use * the original name (with which it was created) to find the alias to * describe it. */ slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; hPtr = Tcl_FindHashEntry(&slavePtr->aliasTable, Tcl_GetString(namePtr)); if (hPtr == NULL) { return TCL_OK; } aliasPtr = Tcl_GetHashValue(hPtr); prefixPtr = Tcl_NewListObj(aliasPtr->objc, &aliasPtr->objPtr); Tcl_SetObjResult(interp, prefixPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * AliasList -- * * Computes a list of aliases defined in a slave interpreter. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int AliasList( Tcl_Interp *interp, /* Interp for data return. */ Tcl_Interp *slaveInterp) /* Interp whose aliases to compute. */ { Tcl_HashEntry *entryPtr; Tcl_HashSearch hashSearch; Tcl_Obj *resultPtr = Tcl_NewObj(); Alias *aliasPtr; Slave *slavePtr; slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; entryPtr = Tcl_FirstHashEntry(&slavePtr->aliasTable, &hashSearch); for ( ; entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&hashSearch)) { aliasPtr = Tcl_GetHashValue(entryPtr); Tcl_ListObjAppendElement(NULL, resultPtr, aliasPtr->token); } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * AliasObjCmd -- * * This is the function that services invocations of aliases in a slave * interpreter. One such command exists for each alias. When invoked, * this function redirects the invocation to the target command in the * master interpreter as designated by the Alias record associated with * this command. * * Results: * A standard Tcl result. * * Side effects: * Causes forwarding of the invocation; all possible side effects may * occur as a result of invoking the command to which the invocation is * forwarded. * *---------------------------------------------------------------------- */ static int AliasNRCmd( ClientData clientData, /* Alias record. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument vector. */ { Interp *iPtr = (Interp *) interp; Alias *aliasPtr = clientData; int prefc, cmdc, i; Tcl_Obj **prefv, **cmdv; int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL); Tcl_Obj *listPtr; List *listRep; int flags = TCL_EVAL_INVOKE; /* * Append the arguments to the command prefix and invoke the command in * the target interp's global namespace. */ prefc = aliasPtr->objc; prefv = &aliasPtr->objPtr; cmdc = prefc + objc - 1; listPtr = Tcl_NewListObj(cmdc, NULL); listRep = listPtr->internalRep.twoPtrValue.ptr1; listRep->elemCount = cmdc; cmdv = &listRep->elements; prefv = &aliasPtr->objPtr; memcpy(cmdv, prefv, (size_t) (prefc * sizeof(Tcl_Obj *))); memcpy(cmdv+prefc, objv+1, (size_t) ((objc-1) * sizeof(Tcl_Obj *))); for (i=0; iensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = 1; iPtr->ensembleRewrite.numInsertedObjs = prefc; } else { iPtr->ensembleRewrite.numInsertedObjs += prefc - 1; } /* * We are sending a 0-refCount obj, do not need a callback: it will be * cleaned up automatically. But we may need to clear the rootEnsemble * stuff ... */ if (isRootEnsemble) { TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL); } TclSkipTailcall(interp); return Tcl_NREvalObj(interp, listPtr, flags); } static int AliasObjCmd( ClientData clientData, /* Alias record. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument vector. */ { #define ALIAS_CMDV_PREALLOC 10 Alias *aliasPtr = clientData; Tcl_Interp *targetInterp = aliasPtr->targetInterp; int result, prefc, cmdc, i; Tcl_Obj **prefv, **cmdv; Tcl_Obj *cmdArr[ALIAS_CMDV_PREALLOC]; Interp *tPtr = (Interp *) targetInterp; int isRootEnsemble = (tPtr->ensembleRewrite.sourceObjs == NULL); /* * Append the arguments to the command prefix and invoke the command in * the target interp's global namespace. */ prefc = aliasPtr->objc; prefv = &aliasPtr->objPtr; cmdc = prefc + objc - 1; if (cmdc <= ALIAS_CMDV_PREALLOC) { cmdv = cmdArr; } else { cmdv = TclStackAlloc(interp, cmdc * sizeof(Tcl_Obj *)); } memcpy(cmdv, prefv, (size_t) (prefc * sizeof(Tcl_Obj *))); memcpy(cmdv+prefc, objv+1, (size_t) ((objc-1) * sizeof(Tcl_Obj *))); Tcl_ResetResult(targetInterp); for (i=0; iensembleRewrite.sourceObjs = objv; tPtr->ensembleRewrite.numRemovedObjs = 1; tPtr->ensembleRewrite.numInsertedObjs = prefc; } else { tPtr->ensembleRewrite.numInsertedObjs += prefc - 1; } /* * Protect the target interpreter if it isn't the same as the source * interpreter so that we can continue to work with it after the target * command completes. */ if (targetInterp != interp) { Tcl_Preserve(targetInterp); } /* * Execute the target command in the target interpreter. */ result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE); /* * Clean up the ensemble rewrite info if we set it in the first place. */ if (isRootEnsemble) { tPtr->ensembleRewrite.sourceObjs = NULL; tPtr->ensembleRewrite.numRemovedObjs = 0; tPtr->ensembleRewrite.numInsertedObjs = 0; } /* * If it was a cross-interpreter alias, we need to transfer the result * back to the source interpreter and release the lock we previously set * on the target interpreter. */ if (targetInterp != interp) { Tcl_TransferResult(targetInterp, result, interp); Tcl_Release(targetInterp); } for (i=0; itoken); objv = &aliasPtr->objPtr; for (i = 0; i < aliasPtr->objc; i++) { Tcl_DecrRefCount(objv[i]); } Tcl_DeleteHashEntry(aliasPtr->aliasEntryPtr); /* * Splice the target record out of the target interpreter's master list. */ targetPtr = aliasPtr->targetPtr; if (targetPtr->prevPtr != NULL) { targetPtr->prevPtr->nextPtr = targetPtr->nextPtr; } else { Master *masterPtr = &((InterpInfo *) ((Interp *) aliasPtr->targetInterp)->interpInfo)->master; masterPtr->targetsPtr = targetPtr->nextPtr; } if (targetPtr->nextPtr != NULL) { targetPtr->nextPtr->prevPtr = targetPtr->prevPtr; } ckfree(targetPtr); ckfree(aliasPtr); } /* *---------------------------------------------------------------------- * * Tcl_CreateSlave -- * * Creates a slave interpreter. The slavePath argument denotes the name * of the new slave relative to the current interpreter; the slave is a * direct descendant of the one-before-last component of the path, * e.g. it is a descendant of the current interpreter if the slavePath * argument contains only one component. Optionally makes the slave * interpreter safe. * * Results: * Returns the interpreter structure created, or NULL if an error * occurred. * * Side effects: * Creates a new interpreter and a new interpreter object command in the * interpreter indicated by the slavePath argument. * *---------------------------------------------------------------------- */ Tcl_Interp * Tcl_CreateSlave( Tcl_Interp *interp, /* Interpreter to start search at. */ const char *slavePath, /* Name of slave to create. */ int isSafe) /* Should new slave be "safe" ? */ { Tcl_Obj *pathPtr; Tcl_Interp *slaveInterp; pathPtr = Tcl_NewStringObj(slavePath, -1); slaveInterp = SlaveCreate(interp, pathPtr, isSafe); Tcl_DecrRefCount(pathPtr); return slaveInterp; } /* *---------------------------------------------------------------------- * * Tcl_GetSlave -- * * Finds a slave interpreter by its path name. * * Results: * Returns a Tcl_Interp * for the named interpreter or NULL if not found. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Interp * Tcl_GetSlave( Tcl_Interp *interp, /* Interpreter to start search from. */ const char *slavePath) /* Path of slave to find. */ { Tcl_Obj *pathPtr; Tcl_Interp *slaveInterp; pathPtr = Tcl_NewStringObj(slavePath, -1); slaveInterp = GetInterp(interp, pathPtr); Tcl_DecrRefCount(pathPtr); return slaveInterp; } /* *---------------------------------------------------------------------- * * Tcl_GetMaster -- * * Finds the master interpreter of a slave interpreter. * * Results: * Returns a Tcl_Interp * for the master interpreter or NULL if none. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Interp * Tcl_GetMaster( Tcl_Interp *interp) /* Get the master of this interpreter. */ { Slave *slavePtr; /* Slave record of this interpreter. */ if (interp == NULL) { return NULL; } slavePtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->slave; return slavePtr->masterInterp; } /* *---------------------------------------------------------------------- * * TclSetSlaveCancelFlags -- * * This function marks all slave interpreters belonging to a given * interpreter as being canceled or not canceled, depending on the * provided flags. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclSetSlaveCancelFlags( Tcl_Interp *interp, /* Set cancel flags of this interpreter. */ int flags, /* Collection of OR-ed bits that control * the cancellation of the script. Only * TCL_CANCEL_UNWIND is currently * supported. */ int force) /* Non-zero to ignore numLevels for the purpose * of resetting the cancellation flags. */ { Master *masterPtr; /* Master record of given interpreter. */ Tcl_HashEntry *hPtr; /* Search element. */ Tcl_HashSearch hashSearch; /* Search variable. */ Slave *slavePtr; /* Slave record of interpreter. */ Interp *iPtr; if (interp == NULL) { return; } flags &= (CANCELED | TCL_CANCEL_UNWIND); masterPtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->master; hPtr = Tcl_FirstHashEntry(&masterPtr->slaveTable, &hashSearch); for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&hashSearch)) { slavePtr = Tcl_GetHashValue(hPtr); iPtr = (Interp *) slavePtr->slaveInterp; if (iPtr == NULL) { continue; } if (flags == 0) { TclResetCancellation((Tcl_Interp *) iPtr, force); } else { TclSetCancelFlags(iPtr, flags); } /* * Now, recursively handle this for the slaves of this slave * interpreter. */ TclSetSlaveCancelFlags((Tcl_Interp *) iPtr, flags, force); } } /* *---------------------------------------------------------------------- * * Tcl_GetInterpPath -- * * Sets the result of the asking interpreter to a proper Tcl list * containing the names of interpreters between the asking and target * interpreters. The target interpreter must be either the same as the * asking interpreter or one of its slaves (including recursively). * * Results: * TCL_OK if the target interpreter is the same as, or a descendant of, * the asking interpreter; TCL_ERROR else. This way one can distinguish * between the case where the asking and target interps are the same (an * empty list is the result, and TCL_OK is returned) and when the target * is not a descendant of the asking interpreter (in which case the Tcl * result is an error message and the function returns TCL_ERROR). * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetInterpPath( Tcl_Interp *askingInterp, /* Interpreter to start search from. */ Tcl_Interp *targetInterp) /* Interpreter to find. */ { InterpInfo *iiPtr; if (targetInterp == askingInterp) { Tcl_SetObjResult(askingInterp, Tcl_NewObj()); return TCL_OK; } if (targetInterp == NULL) { return TCL_ERROR; } iiPtr = (InterpInfo *) ((Interp *) targetInterp)->interpInfo; if (Tcl_GetInterpPath(askingInterp, iiPtr->slave.masterInterp) != TCL_OK){ return TCL_ERROR; } Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(askingInterp), Tcl_NewStringObj(Tcl_GetHashKey(&iiPtr->master.slaveTable, iiPtr->slave.slaveEntryPtr), -1)); return TCL_OK; } /* *---------------------------------------------------------------------- * * GetInterp -- * * Helper function to find a slave interpreter given a pathname. * * Results: * Returns the slave interpreter known by that name in the calling * interpreter, or NULL if no interpreter known by that name exists. * * Side effects: * Assigns to the pointer variable passed in, if not NULL. * *---------------------------------------------------------------------- */ static Tcl_Interp * GetInterp( Tcl_Interp *interp, /* Interp. to start search from. */ Tcl_Obj *pathPtr) /* List object containing name of interp. to * be found. */ { Tcl_HashEntry *hPtr; /* Search element. */ Slave *slavePtr; /* Interim slave record. */ Tcl_Obj **objv; int objc, i; Tcl_Interp *searchInterp; /* Interim storage for interp. to find. */ InterpInfo *masterInfoPtr; if (TclListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) { return NULL; } searchInterp = interp; for (i = 0; i < objc; i++) { masterInfoPtr = (InterpInfo *) ((Interp *) searchInterp)->interpInfo; hPtr = Tcl_FindHashEntry(&masterInfoPtr->master.slaveTable, TclGetString(objv[i])); if (hPtr == NULL) { searchInterp = NULL; break; } slavePtr = Tcl_GetHashValue(hPtr); searchInterp = slavePtr->slaveInterp; if (searchInterp == NULL) { break; } } if (searchInterp == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not find interpreter \"%s\"", TclGetString(pathPtr))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INTERP", TclGetString(pathPtr), NULL); } return searchInterp; } /* *---------------------------------------------------------------------- * * SlaveBgerror -- * * Helper function to set/query the background error handling command * prefix of an interp * * Results: * A standard Tcl result. * * Side effects: * When (objc == 1), slaveInterp will be set to a new background handler * of objv[0]. * *---------------------------------------------------------------------- */ static int SlaveBgerror( Tcl_Interp *interp, /* Interp for error return. */ Tcl_Interp *slaveInterp, /* Interp in which limit is set/queried. */ int objc, /* Set or Query. */ Tcl_Obj *const objv[]) /* Argument strings. */ { if (objc) { int length; if (TCL_ERROR == TclListObjLength(NULL, objv[0], &length) || (length < 1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cmdPrefix must be list of length >= 1", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "BGERRORFORMAT", NULL); return TCL_ERROR; } TclSetBgErrorHandler(slaveInterp, objv[0]); } Tcl_SetObjResult(interp, TclGetBgErrorHandler(slaveInterp)); return TCL_OK; } /* *---------------------------------------------------------------------- * * SlaveCreate -- * * Helper function to do the actual work of creating a slave interp and * new object command. Also optionally makes the new slave interpreter * "safe". * * Results: * Returns the new Tcl_Interp * if successful or NULL if not. If failed, * the result of the invoking interpreter contains an error message. * * Side effects: * Creates a new slave interpreter and a new object command. * *---------------------------------------------------------------------- */ static Tcl_Interp * SlaveCreate( Tcl_Interp *interp, /* Interp. to start search from. */ Tcl_Obj *pathPtr, /* Path (name) of slave to create. */ int safe) /* Should we make it "safe"? */ { Tcl_Interp *masterInterp, *slaveInterp; Slave *slavePtr; InterpInfo *masterInfoPtr; Tcl_HashEntry *hPtr; const char *path; int isNew, objc; Tcl_Obj **objv; if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) { return NULL; } if (objc < 2) { masterInterp = interp; path = TclGetString(pathPtr); } else { Tcl_Obj *objPtr; objPtr = Tcl_NewListObj(objc - 1, objv); masterInterp = GetInterp(interp, objPtr); Tcl_DecrRefCount(objPtr); if (masterInterp == NULL) { return NULL; } path = TclGetString(objv[objc - 1]); } if (safe == 0) { safe = Tcl_IsSafe(masterInterp); } masterInfoPtr = (InterpInfo *) ((Interp *) masterInterp)->interpInfo; hPtr = Tcl_CreateHashEntry(&masterInfoPtr->master.slaveTable, path, &isNew); if (isNew == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "interpreter named \"%s\" already exists, cannot create", path)); return NULL; } slaveInterp = Tcl_CreateInterp(); slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; slavePtr->masterInterp = masterInterp; slavePtr->slaveEntryPtr = hPtr; slavePtr->slaveInterp = slaveInterp; slavePtr->interpCmd = Tcl_NRCreateCommand(masterInterp, path, SlaveObjCmd, NRSlaveCmd, slaveInterp, SlaveObjCmdDeleteProc); Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS); Tcl_SetHashValue(hPtr, slavePtr); Tcl_SetVar(slaveInterp, "tcl_interactive", "0", TCL_GLOBAL_ONLY); /* * Inherit the recursion limit. */ ((Interp *) slaveInterp)->maxNestingDepth = ((Interp *) masterInterp)->maxNestingDepth; if (safe) { if (Tcl_MakeSafe(slaveInterp) == TCL_ERROR) { goto error; } } else { if (Tcl_Init(slaveInterp) == TCL_ERROR) { goto error; } /* * This will create the "memory" command in slave interpreters if we * compiled with TCL_MEM_DEBUG, otherwise it does nothing. */ Tcl_InitMemory(slaveInterp); } /* * Inherit the TIP#143 limits. */ InheritLimitsFromMaster(slaveInterp, masterInterp); /* * The [clock] command presents a safe API, but uses unsafe features in * its implementation. This means it has to be implemented in safe interps * as an alias to a version in the (trusted) master. */ if (safe) { Tcl_Obj *clockObj; int status; TclNewLiteralStringObj(clockObj, "clock"); Tcl_IncrRefCount(clockObj); status = AliasCreate(interp, slaveInterp, masterInterp, clockObj, clockObj, 0, NULL); Tcl_DecrRefCount(clockObj); if (status != TCL_OK) { goto error2; } } return slaveInterp; error: Tcl_TransferResult(slaveInterp, TCL_ERROR, interp); error2: Tcl_DeleteInterp(slaveInterp); return NULL; } /* *---------------------------------------------------------------------- * * SlaveObjCmd -- * * Command to manipulate an interpreter, e.g. to send commands to it to * be evaluated. One such command exists for each slave interpreter. * * Results: * A standard Tcl result. * * Side effects: * See user documentation for details. * *---------------------------------------------------------------------- */ static int SlaveObjCmd( ClientData clientData, /* Slave interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_NRCallObjProc(interp, NRSlaveCmd, clientData, objc, objv); } static int NRSlaveCmd( ClientData clientData, /* Slave interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_Interp *slaveInterp = clientData; int index; static const char *const options[] = { "alias", "aliases", "bgerror", "debug", "eval", "expose", "hide", "hidden", "issafe", "invokehidden", "limit", "marktrusted", "recursionlimit", NULL }; enum options { OPT_ALIAS, OPT_ALIASES, OPT_BGERROR, OPT_DEBUG, OPT_EVAL, OPT_EXPOSE, OPT_HIDE, OPT_HIDDEN, OPT_ISSAFE, OPT_INVOKEHIDDEN, OPT_LIMIT, OPT_MARKTRUSTED, OPT_RECLIMIT }; if (slaveInterp == NULL) { Tcl_Panic("SlaveObjCmd: interpreter has been deleted"); } if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { case OPT_ALIAS: if (objc > 2) { if (objc == 3) { return AliasDescribe(interp, slaveInterp, objv[2]); } if (TclGetString(objv[3])[0] == '\0') { if (objc == 4) { return AliasDelete(interp, slaveInterp, objv[2]); } } else { return AliasCreate(interp, slaveInterp, interp, objv[2], objv[3], objc - 4, objv + 4); } } Tcl_WrongNumArgs(interp, 2, objv, "aliasName ?targetName? ?arg ...?"); return TCL_ERROR; case OPT_ALIASES: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } return AliasList(interp, slaveInterp); case OPT_BGERROR: if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "?cmdPrefix?"); return TCL_ERROR; } return SlaveBgerror(interp, slaveInterp, objc - 2, objv + 2); case OPT_DEBUG: /* * TIP #378 * Currently only -frame supported, otherwise ?-option ?value? ...? */ if (objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "?-frame ?bool??"); return TCL_ERROR; } return SlaveDebugCmd(interp, slaveInterp, objc - 2, objv + 2); case OPT_EVAL: if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "arg ?arg ...?"); return TCL_ERROR; } return SlaveEval(interp, slaveInterp, objc - 2, objv + 2); case OPT_EXPOSE: if ((objc < 3) || (objc > 4)) { Tcl_WrongNumArgs(interp, 2, objv, "hiddenCmdName ?cmdName?"); return TCL_ERROR; } return SlaveExpose(interp, slaveInterp, objc - 2, objv + 2); case OPT_HIDE: if ((objc < 3) || (objc > 4)) { Tcl_WrongNumArgs(interp, 2, objv, "cmdName ?hiddenCmdName?"); return TCL_ERROR; } return SlaveHide(interp, slaveInterp, objc - 2, objv + 2); case OPT_HIDDEN: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } return SlaveHidden(interp, slaveInterp); case OPT_ISSAFE: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_IsSafe(slaveInterp))); return TCL_OK; case OPT_INVOKEHIDDEN: { int i; const char *namespaceName; static const char *const hiddenOptions[] = { "-global", "-namespace", "--", NULL }; enum hiddenOption { OPT_GLOBAL, OPT_NAMESPACE, OPT_LAST }; namespaceName = NULL; for (i = 2; i < objc; i++) { if (TclGetString(objv[i])[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } if (index == OPT_GLOBAL) { namespaceName = "::"; } else if (index == OPT_NAMESPACE) { if (++i == objc) { /* There must be more arguments. */ break; } else { namespaceName = TclGetString(objv[i]); } } else { i++; break; } } if (objc - i < 1) { Tcl_WrongNumArgs(interp, 2, objv, "?-namespace ns? ?-global? ?--? cmd ?arg ..?"); return TCL_ERROR; } return SlaveInvokeHidden(interp, slaveInterp, namespaceName, objc - i, objv + i); } case OPT_LIMIT: { static const char *const limitTypes[] = { "commands", "time", NULL }; enum LimitTypes { LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME }; int limitType; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "limitType ?-option value ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], limitTypes, "limit type", 0, &limitType) != TCL_OK) { return TCL_ERROR; } switch ((enum LimitTypes) limitType) { case LIMIT_TYPE_COMMANDS: return SlaveCommandLimitCmd(interp, slaveInterp, 3, objc,objv); case LIMIT_TYPE_TIME: return SlaveTimeLimitCmd(interp, slaveInterp, 3, objc, objv); } } case OPT_MARKTRUSTED: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } return SlaveMarkTrusted(interp, slaveInterp); case OPT_RECLIMIT: if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "?newlimit?"); return TCL_ERROR; } return SlaveRecursionLimit(interp, slaveInterp, objc - 2, objv + 2); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * SlaveObjCmdDeleteProc -- * * Invoked when an object command for a slave interpreter is deleted; * cleans up all state associated with the slave interpreter and destroys * the slave interpreter. * * Results: * None. * * Side effects: * Cleans up all state associated with the slave interpreter and destroys * the slave interpreter. * *---------------------------------------------------------------------- */ static void SlaveObjCmdDeleteProc( ClientData clientData) /* The SlaveRecord for the command. */ { Slave *slavePtr; /* Interim storage for Slave record. */ Tcl_Interp *slaveInterp = clientData; /* And for a slave interp. */ slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; /* * Unlink the slave from its master interpreter. */ Tcl_DeleteHashEntry(slavePtr->slaveEntryPtr); /* * Set to NULL so that when the InterpInfo is cleaned up in the slave it * does not try to delete the command causing all sorts of grief. See * SlaveRecordDeleteProc(). */ slavePtr->interpCmd = NULL; if (slavePtr->slaveInterp != NULL) { Tcl_DeleteInterp(slavePtr->slaveInterp); } } /* *---------------------------------------------------------------------- * * SlaveDebugCmd -- TIP #378 * * Helper function to handle 'debug' command in a slave interpreter. * * Results: * A standard Tcl result. * * Side effects: * May modify INTERP_DEBUG_FRAME flag in the slave. * *---------------------------------------------------------------------- */ static int SlaveDebugCmd( Tcl_Interp *interp, /* Interp for error return. */ Tcl_Interp *slaveInterp, /* The slave interpreter in which command * will be evaluated. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const debugTypes[] = { "-frame", NULL }; enum DebugTypes { DEBUG_TYPE_FRAME }; int debugType; Interp *iPtr; Tcl_Obj *resultPtr; iPtr = (Interp *) slaveInterp; if (objc == 0) { resultPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewStringObj("-frame", -1)); Tcl_ListObjAppendElement(NULL, resultPtr, Tcl_NewBooleanObj(iPtr->flags & INTERP_DEBUG_FRAME)); Tcl_SetObjResult(interp, resultPtr); } else { if (Tcl_GetIndexFromObj(interp, objv[0], debugTypes, "debug option", 0, &debugType) != TCL_OK) { return TCL_ERROR; } if (debugType == DEBUG_TYPE_FRAME) { if (objc == 2) { /* set */ if (Tcl_GetBooleanFromObj(interp, objv[1], &debugType) != TCL_OK) { return TCL_ERROR; } /* * Quietly ignore attempts to disable interp debugging. This * is a one-way switch as frame debug info is maintained in a * stack that must be consistent once turned on. */ if (debugType) { iPtr->flags |= INTERP_DEBUG_FRAME; } } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(iPtr->flags & INTERP_DEBUG_FRAME)); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * SlaveEval -- * * Helper function to evaluate a command in a slave interpreter. * * Results: * A standard Tcl result. * * Side effects: * Whatever the command does. * *---------------------------------------------------------------------- */ static int SlaveEval( Tcl_Interp *interp, /* Interp for error return. */ Tcl_Interp *slaveInterp, /* The slave interpreter in which command * will be evaluated. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int result; /* * TIP #285: If necessary, reset the cancellation flags for the slave * interpreter now; otherwise, canceling a script in a master interpreter * can result in a situation where a slave interpreter can no longer * evaluate any scripts unless somebody calls the TclResetCancellation * function for that particular Tcl_Interp. */ TclSetSlaveCancelFlags(slaveInterp, 0, 0); Tcl_Preserve(slaveInterp); Tcl_AllowExceptions(slaveInterp); if (objc == 1) { /* * TIP #280: Make actual argument location available to eval'd script. */ Interp *iPtr = (Interp *) interp; CmdFrame *invoker = iPtr->cmdFramePtr; int word = 0; TclArgumentGet(interp, objv[0], &invoker, &word); result = TclEvalObjEx(slaveInterp, objv[0], 0, invoker, word); } else { Tcl_Obj *objPtr = Tcl_ConcatObj(objc, objv); Tcl_IncrRefCount(objPtr); result = Tcl_EvalObjEx(slaveInterp, objPtr, 0); Tcl_DecrRefCount(objPtr); } Tcl_TransferResult(slaveInterp, result, interp); Tcl_Release(slaveInterp); return result; } /* *---------------------------------------------------------------------- * * SlaveExpose -- * * Helper function to expose a command in a slave interpreter. * * Results: * A standard Tcl result. * * Side effects: * After this call scripts in the slave will be able to invoke the newly * exposed command. * *---------------------------------------------------------------------- */ static int SlaveExpose( Tcl_Interp *interp, /* Interp for error return. */ Tcl_Interp *slaveInterp, /* Interp in which command will be exposed. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { const char *name; if (Tcl_IsSafe(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "permission denied: safe interpreter cannot expose commands", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE", NULL); return TCL_ERROR; } name = TclGetString(objv[(objc == 1) ? 0 : 1]); if (Tcl_ExposeCommand(slaveInterp, TclGetString(objv[0]), name) != TCL_OK) { Tcl_TransferResult(slaveInterp, TCL_ERROR, interp); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * SlaveRecursionLimit -- * * Helper function to set/query the Recursion limit of an interp * * Results: * A standard Tcl result. * * Side effects: * When (objc == 1), slaveInterp will be set to a new recursion limit of * objv[0]. * *---------------------------------------------------------------------- */ static int SlaveRecursionLimit( Tcl_Interp *interp, /* Interp for error return. */ Tcl_Interp *slaveInterp, /* Interp in which limit is set/queried. */ int objc, /* Set or Query. */ Tcl_Obj *const objv[]) /* Argument strings. */ { Interp *iPtr; int limit; if (objc) { if (Tcl_IsSafe(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("permission denied: " "safe interpreters cannot change recursion limit", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE", NULL); return TCL_ERROR; } if (TclGetIntFromObj(interp, objv[0], &limit) == TCL_ERROR) { return TCL_ERROR; } if (limit <= 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "recursion limit must be > 0", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "BADLIMIT", NULL); return TCL_ERROR; } Tcl_SetRecursionLimit(slaveInterp, limit); iPtr = (Interp *) slaveInterp; if (interp == slaveInterp && iPtr->numLevels > limit) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "falling back due to new recursion limit", -1)); Tcl_SetErrorCode(interp, "TCL", "RECURSION", NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, objv[0]); return TCL_OK; } else { limit = Tcl_SetRecursionLimit(slaveInterp, 0); Tcl_SetObjResult(interp, Tcl_NewIntObj(limit)); return TCL_OK; } } /* *---------------------------------------------------------------------- * * SlaveHide -- * * Helper function to hide a command in a slave interpreter. * * Results: * A standard Tcl result. * * Side effects: * After this call scripts in the slave will no longer be able to invoke * the named command. * *---------------------------------------------------------------------- */ static int SlaveHide( Tcl_Interp *interp, /* Interp for error return. */ Tcl_Interp *slaveInterp, /* Interp in which command will be exposed. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { const char *name; if (Tcl_IsSafe(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "permission denied: safe interpreter cannot hide commands", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE", NULL); return TCL_ERROR; } name = TclGetString(objv[(objc == 1) ? 0 : 1]); if (Tcl_HideCommand(slaveInterp, TclGetString(objv[0]), name) != TCL_OK) { Tcl_TransferResult(slaveInterp, TCL_ERROR, interp); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * SlaveHidden -- * * Helper function to compute list of hidden commands in a slave * interpreter. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int SlaveHidden( Tcl_Interp *interp, /* Interp for data return. */ Tcl_Interp *slaveInterp) /* Interp whose hidden commands to query. */ { Tcl_Obj *listObjPtr = Tcl_NewObj(); /* Local object pointer. */ Tcl_HashTable *hTblPtr; /* For local searches. */ Tcl_HashEntry *hPtr; /* For local searches. */ Tcl_HashSearch hSearch; /* For local searches. */ hTblPtr = ((Interp *) slaveInterp)->hiddenCmdTablePtr; if (hTblPtr != NULL) { for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { Tcl_ListObjAppendElement(NULL, listObjPtr, Tcl_NewStringObj(Tcl_GetHashKey(hTblPtr, hPtr), -1)); } } Tcl_SetObjResult(interp, listObjPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * SlaveInvokeHidden -- * * Helper function to invoke a hidden command in a slave interpreter. * * Results: * A standard Tcl result. * * Side effects: * Whatever the hidden command does. * *---------------------------------------------------------------------- */ static int SlaveInvokeHidden( Tcl_Interp *interp, /* Interp for error return. */ Tcl_Interp *slaveInterp, /* The slave interpreter in which command will * be invoked. */ const char *namespaceName, /* The namespace to use, if any. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int result; if (Tcl_IsSafe(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "not allowed to invoke hidden commands from safe interpreter", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE", NULL); return TCL_ERROR; } Tcl_Preserve(slaveInterp); Tcl_AllowExceptions(slaveInterp); if (namespaceName == NULL) { NRE_callback *rootPtr = TOP_CB(slaveInterp); Tcl_NRAddCallback(interp, NRPostInvokeHidden, slaveInterp, rootPtr, NULL, NULL); return TclNRInvoke(NULL, slaveInterp, objc, objv); } else { Namespace *nsPtr, *dummy1, *dummy2; const char *tail; result = TclGetNamespaceForQualName(slaveInterp, namespaceName, NULL, TCL_FIND_ONLY_NS | TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG | TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail); if (result == TCL_OK) { result = TclObjInvokeNamespace(slaveInterp, objc, objv, (Tcl_Namespace *) nsPtr, TCL_INVOKE_HIDDEN); } } Tcl_TransferResult(slaveInterp, result, interp); Tcl_Release(slaveInterp); return result; } static int NRPostInvokeHidden( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Interp *slaveInterp = (Tcl_Interp *)data[0]; NRE_callback *rootPtr = (NRE_callback *)data[1]; if (interp != slaveInterp) { result = TclNRRunCallbacks(slaveInterp, result, rootPtr); Tcl_TransferResult(slaveInterp, result, interp); } Tcl_Release(slaveInterp); return result; } /* *---------------------------------------------------------------------- * * SlaveMarkTrusted -- * * Helper function to mark a slave interpreter as trusted (unsafe). * * Results: * A standard Tcl result. * * Side effects: * After this call the hard-wired security checks in the core no longer * prevent the slave from performing certain operations. * *---------------------------------------------------------------------- */ static int SlaveMarkTrusted( Tcl_Interp *interp, /* Interp for error return. */ Tcl_Interp *slaveInterp) /* The slave interpreter which will be marked * trusted. */ { if (Tcl_IsSafe(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "permission denied: safe interpreter cannot mark trusted", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "UNSAFE", NULL); return TCL_ERROR; } ((Interp *) slaveInterp)->flags &= ~SAFE_INTERP; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_IsSafe -- * * Determines whether an interpreter is safe * * Results: * 1 if it is safe, 0 if it is not. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_IsSafe( Tcl_Interp *interp) /* Is this interpreter "safe" ? */ { Interp *iPtr = (Interp *) interp; if (iPtr == NULL) { return 0; } return (iPtr->flags & SAFE_INTERP) ? 1 : 0; } /* *---------------------------------------------------------------------- * * Tcl_MakeSafe -- * * Makes its argument interpreter contain only functionality that is * defined to be part of Safe Tcl. Unsafe commands are hidden, the env * array is unset, and the standard channels are removed. * * Results: * None. * * Side effects: * Hides commands in its argument interpreter, and removes settings and * channels. * *---------------------------------------------------------------------- */ int Tcl_MakeSafe( Tcl_Interp *interp) /* Interpreter to be made safe. */ { Tcl_Channel chan; /* Channel to remove from safe interpreter. */ Interp *iPtr = (Interp *) interp; Tcl_Interp *master = ((InterpInfo*) iPtr->interpInfo)->slave.masterInterp; TclHideUnsafeCommands(interp); if (master != NULL) { /* * Alias these function implementations in the slave to those in the * master; the overall implementations are safe, but they're normally * defined by init.tcl which is not sourced by safe interpreters. * Assume these functions all work. [Bug 2895741] */ (void) Tcl_Eval(interp, "namespace eval ::tcl {namespace eval mathfunc {}}"); (void) Tcl_CreateAlias(interp, "::tcl::mathfunc::min", master, "::tcl::mathfunc::min", 0, NULL); (void) Tcl_CreateAlias(interp, "::tcl::mathfunc::max", master, "::tcl::mathfunc::max", 0, NULL); } iPtr->flags |= SAFE_INTERP; /* * Unsetting variables : (which should not have been set in the first * place, but...) */ /* * No env array in a safe slave. */ Tcl_UnsetVar(interp, "env", TCL_GLOBAL_ONLY); /* * Remove unsafe parts of tcl_platform */ Tcl_UnsetVar2(interp, "tcl_platform", "os", TCL_GLOBAL_ONLY); Tcl_UnsetVar2(interp, "tcl_platform", "osVersion", TCL_GLOBAL_ONLY); Tcl_UnsetVar2(interp, "tcl_platform", "machine", TCL_GLOBAL_ONLY); Tcl_UnsetVar2(interp, "tcl_platform", "user", TCL_GLOBAL_ONLY); /* * Unset path informations variables (the only one remaining is [info * nameofexecutable]) */ Tcl_UnsetVar(interp, "tclDefaultLibrary", TCL_GLOBAL_ONLY); Tcl_UnsetVar(interp, "tcl_library", TCL_GLOBAL_ONLY); Tcl_UnsetVar(interp, "tcl_pkgPath", TCL_GLOBAL_ONLY); /* * Remove the standard channels from the interpreter; safe interpreters do * not ordinarily have access to stdin, stdout and stderr. * * NOTE: These channels are not added to the interpreter by the * Tcl_CreateInterp call, but may be added later, by another I/O * operation. We want to ensure that the interpreter does not have these * channels even if it is being made safe after being used for some time.. */ chan = Tcl_GetStdChannel(TCL_STDIN); if (chan != NULL) { Tcl_UnregisterChannel(interp, chan); } chan = Tcl_GetStdChannel(TCL_STDOUT); if (chan != NULL) { Tcl_UnregisterChannel(interp, chan); } chan = Tcl_GetStdChannel(TCL_STDERR); if (chan != NULL) { Tcl_UnregisterChannel(interp, chan); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_LimitExceeded -- * * Tests whether any limit has been exceeded in the given interpreter * (i.e. whether the interpreter is currently unable to process further * scripts). * * Results: * A boolean value. * * Side effects: * None. * * Notes: * If you change this function, you MUST also update TclLimitExceeded() in * tclInt.h. *---------------------------------------------------------------------- */ int Tcl_LimitExceeded( Tcl_Interp *interp) { register Interp *iPtr = (Interp *) interp; return iPtr->limit.exceeded != 0; } /* *---------------------------------------------------------------------- * * Tcl_LimitReady -- * * Find out whether any limit has been set on the interpreter, and if so * check whether the granularity of that limit is such that the full * limit check should be carried out. * * Results: * A boolean value that indicates whether to call Tcl_LimitCheck. * * Side effects: * Increments the limit granularity counter. * * Notes: * If you change this function, you MUST also update TclLimitReady() in * tclInt.h. * *---------------------------------------------------------------------- */ int Tcl_LimitReady( Tcl_Interp *interp) { register Interp *iPtr = (Interp *) interp; if (iPtr->limit.active != 0) { register int ticker = ++iPtr->limit.granularityTicker; if ((iPtr->limit.active & TCL_LIMIT_COMMANDS) && ((iPtr->limit.cmdGranularity == 1) || (ticker % iPtr->limit.cmdGranularity == 0))) { return 1; } if ((iPtr->limit.active & TCL_LIMIT_TIME) && ((iPtr->limit.timeGranularity == 1) || (ticker % iPtr->limit.timeGranularity == 0))) { return 1; } } return 0; } /* *---------------------------------------------------------------------- * * Tcl_LimitCheck -- * * Check all currently set limits in the interpreter (where permitted by * granularity). If a limit is exceeded, call its callbacks and, if the * limit is still exceeded after the callbacks have run, make the * interpreter generate an error that cannot be caught within the limited * interpreter. * * Results: * A Tcl result value (TCL_OK if no limit is exceeded, and TCL_ERROR if a * limit has been exceeded). * * Side effects: * May invoke system calls. May invoke other interpreters. May be * reentrant. May put the interpreter into a state where it can no longer * execute commands without outside intervention. * *---------------------------------------------------------------------- */ int Tcl_LimitCheck( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; register int ticker = iPtr->limit.granularityTicker; if (Tcl_InterpDeleted(interp)) { return TCL_OK; } if ((iPtr->limit.active & TCL_LIMIT_COMMANDS) && ((iPtr->limit.cmdGranularity == 1) || (ticker % iPtr->limit.cmdGranularity == 0)) && (iPtr->limit.cmdCount < iPtr->cmdCount)) { iPtr->limit.exceeded |= TCL_LIMIT_COMMANDS; Tcl_Preserve(interp); RunLimitHandlers(iPtr->limit.cmdHandlers, interp); if (iPtr->limit.cmdCount >= iPtr->cmdCount) { iPtr->limit.exceeded &= ~TCL_LIMIT_COMMANDS; } else if (iPtr->limit.exceeded & TCL_LIMIT_COMMANDS) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "command count limit exceeded", -1)); Tcl_SetErrorCode(interp, "TCL", "LIMIT", "COMMANDS", NULL); Tcl_Release(interp); return TCL_ERROR; } Tcl_Release(interp); } if ((iPtr->limit.active & TCL_LIMIT_TIME) && ((iPtr->limit.timeGranularity == 1) || (ticker % iPtr->limit.timeGranularity == 0))) { Tcl_Time now; Tcl_GetTime(&now); if (iPtr->limit.time.sec < now.sec || (iPtr->limit.time.sec == now.sec && iPtr->limit.time.usec < now.usec)) { iPtr->limit.exceeded |= TCL_LIMIT_TIME; Tcl_Preserve(interp); RunLimitHandlers(iPtr->limit.timeHandlers, interp); if (iPtr->limit.time.sec > now.sec || (iPtr->limit.time.sec == now.sec && iPtr->limit.time.usec >= now.usec)) { iPtr->limit.exceeded &= ~TCL_LIMIT_TIME; } else if (iPtr->limit.exceeded & TCL_LIMIT_TIME) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "time limit exceeded", -1)); Tcl_SetErrorCode(interp, "TCL", "LIMIT", "TIME", NULL); Tcl_Release(interp); return TCL_ERROR; } Tcl_Release(interp); } } return TCL_OK; } /* *---------------------------------------------------------------------- * * RunLimitHandlers -- * * Invoke all the limit handlers in a list (for a particular limit). * Note that no particular limit handler callback will be invoked * reentrantly. * * Results: * None. * * Side effects: * Depends on the limit handlers. * *---------------------------------------------------------------------- */ static void RunLimitHandlers( LimitHandler *handlerPtr, Tcl_Interp *interp) { LimitHandler *nextPtr; for (; handlerPtr!=NULL ; handlerPtr=nextPtr) { if (handlerPtr->flags & (LIMIT_HANDLER_DELETED|LIMIT_HANDLER_ACTIVE)) { /* * Reentrant call or something seriously strange in the delete * code. */ nextPtr = handlerPtr->nextPtr; continue; } /* * Set the ACTIVE flag while running the limit handler itself so we * cannot reentrantly call this handler and know to use the alternate * method of deletion if necessary. */ handlerPtr->flags |= LIMIT_HANDLER_ACTIVE; handlerPtr->handlerProc(handlerPtr->clientData, interp); handlerPtr->flags &= ~LIMIT_HANDLER_ACTIVE; /* * Rediscover this value; it might have changed during the processing * of a limit handler. We have to record it here because we might * delete the structure below, and reading a value out of a deleted * structure is unsafe (even if actually legal with some * malloc()/free() implementations.) */ nextPtr = handlerPtr->nextPtr; /* * If we deleted the current handler while we were executing it, we * will have spliced it out of the list and set the * LIMIT_HANDLER_DELETED flag. */ if (handlerPtr->flags & LIMIT_HANDLER_DELETED) { if (handlerPtr->deleteProc != NULL) { handlerPtr->deleteProc(handlerPtr->clientData); } ckfree(handlerPtr); } } } /* *---------------------------------------------------------------------- * * Tcl_LimitAddHandler -- * * Add a callback handler for a particular resource limit. * * Results: * None. * * Side effects: * Extends the internal linked list of handlers for a limit. * *---------------------------------------------------------------------- */ void Tcl_LimitAddHandler( Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData, Tcl_LimitHandlerDeleteProc *deleteProc) { Interp *iPtr = (Interp *) interp; LimitHandler *handlerPtr; /* * Convert everything into a real deletion callback. */ if (deleteProc == (Tcl_LimitHandlerDeleteProc *) TCL_DYNAMIC) { deleteProc = (Tcl_LimitHandlerDeleteProc *) Tcl_Free; } if (deleteProc == (Tcl_LimitHandlerDeleteProc *) TCL_STATIC) { deleteProc = NULL; } /* * Allocate a handler record. */ handlerPtr = ckalloc(sizeof(LimitHandler)); handlerPtr->flags = 0; handlerPtr->handlerProc = handlerProc; handlerPtr->clientData = clientData; handlerPtr->deleteProc = deleteProc; handlerPtr->prevPtr = NULL; /* * Prepend onto the front of the correct linked list. */ switch (type) { case TCL_LIMIT_COMMANDS: handlerPtr->nextPtr = iPtr->limit.cmdHandlers; if (handlerPtr->nextPtr != NULL) { handlerPtr->nextPtr->prevPtr = handlerPtr; } iPtr->limit.cmdHandlers = handlerPtr; return; case TCL_LIMIT_TIME: handlerPtr->nextPtr = iPtr->limit.timeHandlers; if (handlerPtr->nextPtr != NULL) { handlerPtr->nextPtr->prevPtr = handlerPtr; } iPtr->limit.timeHandlers = handlerPtr; return; } Tcl_Panic("unknown type of resource limit"); } /* *---------------------------------------------------------------------- * * Tcl_LimitRemoveHandler -- * * Remove a callback handler for a particular resource limit. * * Results: * None. * * Side effects: * The handler is spliced out of the internal linked list for the limit, * and if not currently being invoked, deleted. Otherwise it is just * marked for deletion and removed when the limit handler has finished * executing. * *---------------------------------------------------------------------- */ void Tcl_LimitRemoveHandler( Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData) { Interp *iPtr = (Interp *) interp; LimitHandler *handlerPtr; switch (type) { case TCL_LIMIT_COMMANDS: handlerPtr = iPtr->limit.cmdHandlers; break; case TCL_LIMIT_TIME: handlerPtr = iPtr->limit.timeHandlers; break; default: Tcl_Panic("unknown type of resource limit"); return; } for (; handlerPtr!=NULL ; handlerPtr=handlerPtr->nextPtr) { if ((handlerPtr->handlerProc != handlerProc) || (handlerPtr->clientData != clientData)) { continue; } /* * We've found the handler to delete; mark it as doomed if not already * so marked (which shouldn't actually happen). */ if (handlerPtr->flags & LIMIT_HANDLER_DELETED) { return; } handlerPtr->flags |= LIMIT_HANDLER_DELETED; /* * Splice the handler out of the doubly-linked list. */ if (handlerPtr->prevPtr == NULL) { switch (type) { case TCL_LIMIT_COMMANDS: iPtr->limit.cmdHandlers = handlerPtr->nextPtr; break; case TCL_LIMIT_TIME: iPtr->limit.timeHandlers = handlerPtr->nextPtr; break; } } else { handlerPtr->prevPtr->nextPtr = handlerPtr->nextPtr; } if (handlerPtr->nextPtr != NULL) { handlerPtr->nextPtr->prevPtr = handlerPtr->prevPtr; } /* * If nothing is currently executing the handler, delete its client * data and the overall handler structure now. Otherwise it will all * go away when the handler returns. */ if (!(handlerPtr->flags & LIMIT_HANDLER_ACTIVE)) { if (handlerPtr->deleteProc != NULL) { handlerPtr->deleteProc(handlerPtr->clientData); } ckfree(handlerPtr); } return; } } /* *---------------------------------------------------------------------- * * TclLimitRemoveAllHandlers -- * * Remove all limit callback handlers for an interpreter. This is invoked * as part of deleting the interpreter. * * Results: * None. * * Side effects: * Limit handlers are deleted or marked for deletion (as with * Tcl_LimitRemoveHandler). * *---------------------------------------------------------------------- */ void TclLimitRemoveAllHandlers( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; LimitHandler *handlerPtr, *nextHandlerPtr; /* * Delete all command-limit handlers. */ for (handlerPtr=iPtr->limit.cmdHandlers, iPtr->limit.cmdHandlers=NULL; handlerPtr!=NULL; handlerPtr=nextHandlerPtr) { nextHandlerPtr = handlerPtr->nextPtr; /* * Do not delete here if it has already been marked for deletion. */ if (handlerPtr->flags & LIMIT_HANDLER_DELETED) { continue; } handlerPtr->flags |= LIMIT_HANDLER_DELETED; handlerPtr->prevPtr = NULL; handlerPtr->nextPtr = NULL; /* * If nothing is currently executing the handler, delete its client * data and the overall handler structure now. Otherwise it will all * go away when the handler returns. */ if (!(handlerPtr->flags & LIMIT_HANDLER_ACTIVE)) { if (handlerPtr->deleteProc != NULL) { handlerPtr->deleteProc(handlerPtr->clientData); } ckfree(handlerPtr); } } /* * Delete all time-limit handlers. */ for (handlerPtr=iPtr->limit.timeHandlers, iPtr->limit.timeHandlers=NULL; handlerPtr!=NULL; handlerPtr=nextHandlerPtr) { nextHandlerPtr = handlerPtr->nextPtr; /* * Do not delete here if it has already been marked for deletion. */ if (handlerPtr->flags & LIMIT_HANDLER_DELETED) { continue; } handlerPtr->flags |= LIMIT_HANDLER_DELETED; handlerPtr->prevPtr = NULL; handlerPtr->nextPtr = NULL; /* * If nothing is currently executing the handler, delete its client * data and the overall handler structure now. Otherwise it will all * go away when the handler returns. */ if (!(handlerPtr->flags & LIMIT_HANDLER_ACTIVE)) { if (handlerPtr->deleteProc != NULL) { handlerPtr->deleteProc(handlerPtr->clientData); } ckfree(handlerPtr); } } /* * Delete the timer callback that is used to trap limits that occur in * [vwait]s... */ if (iPtr->limit.timeEvent != NULL) { Tcl_DeleteTimerHandler(iPtr->limit.timeEvent); iPtr->limit.timeEvent = NULL; } } /* *---------------------------------------------------------------------- * * Tcl_LimitTypeEnabled -- * * Check whether a particular limit has been enabled for an interpreter. * * Results: * A boolean value. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_LimitTypeEnabled( Tcl_Interp *interp, int type) { Interp *iPtr = (Interp *) interp; return (iPtr->limit.active & type) != 0; } /* *---------------------------------------------------------------------- * * Tcl_LimitTypeExceeded -- * * Check whether a particular limit has been exceeded for an interpreter. * * Results: * A boolean value (note that Tcl_LimitExceeded will always return * non-zero when this function returns non-zero). * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_LimitTypeExceeded( Tcl_Interp *interp, int type) { Interp *iPtr = (Interp *) interp; return (iPtr->limit.exceeded & type) != 0; } /* *---------------------------------------------------------------------- * * Tcl_LimitTypeSet -- * * Enable a particular limit for an interpreter. * * Results: * None. * * Side effects: * The limit is turned on and will be checked in future at an interval * determined by the frequency of calling of Tcl_LimitReady and the * granularity of the limit in question. * *---------------------------------------------------------------------- */ void Tcl_LimitTypeSet( Tcl_Interp *interp, int type) { Interp *iPtr = (Interp *) interp; iPtr->limit.active |= type; } /* *---------------------------------------------------------------------- * * Tcl_LimitTypeReset -- * * Disable a particular limit for an interpreter. * * Results: * None. * * Side effects: * The limit is disabled. If the limit was exceeded when this function * was called, the limit will no longer be exceeded afterwards and the * interpreter will be free to execute further scripts (assuming it isn't * also deleted, of course). * *---------------------------------------------------------------------- */ void Tcl_LimitTypeReset( Tcl_Interp *interp, int type) { Interp *iPtr = (Interp *) interp; iPtr->limit.active &= ~type; iPtr->limit.exceeded &= ~type; } /* *---------------------------------------------------------------------- * * Tcl_LimitSetCommands -- * * Set the command limit for an interpreter. * * Results: * None. * * Side effects: * Also resets whether the command limit was exceeded. This might permit * a small amount of further execution in the interpreter even if the * limit itself is theoretically exceeded. * *---------------------------------------------------------------------- */ void Tcl_LimitSetCommands( Tcl_Interp *interp, int commandLimit) { Interp *iPtr = (Interp *) interp; iPtr->limit.cmdCount = commandLimit; iPtr->limit.exceeded &= ~TCL_LIMIT_COMMANDS; } /* *---------------------------------------------------------------------- * * Tcl_LimitGetCommands -- * * Get the number of commands that may be executed in the interpreter * before the command-limit is reached. * * Results: * An upper bound on the number of commands. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_LimitGetCommands( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; return iPtr->limit.cmdCount; } /* *---------------------------------------------------------------------- * * Tcl_LimitSetTime -- * * Set the time limit for an interpreter by copying it from the value * pointed to by the timeLimitPtr argument. * * Results: * None. * * Side effects: * Also resets whether the time limit was exceeded. This might permit a * small amount of further execution in the interpreter even if the limit * itself is theoretically exceeded. * *---------------------------------------------------------------------- */ void Tcl_LimitSetTime( Tcl_Interp *interp, Tcl_Time *timeLimitPtr) { Interp *iPtr = (Interp *) interp; Tcl_Time nextMoment; memcpy(&iPtr->limit.time, timeLimitPtr, sizeof(Tcl_Time)); if (iPtr->limit.timeEvent != NULL) { Tcl_DeleteTimerHandler(iPtr->limit.timeEvent); } nextMoment.sec = timeLimitPtr->sec; nextMoment.usec = timeLimitPtr->usec+10; if (nextMoment.usec >= 1000000) { nextMoment.sec++; nextMoment.usec -= 1000000; } iPtr->limit.timeEvent = TclCreateAbsoluteTimerHandler(&nextMoment, TimeLimitCallback, interp); iPtr->limit.exceeded &= ~TCL_LIMIT_TIME; } /* *---------------------------------------------------------------------- * * TimeLimitCallback -- * * Callback that allows time limits to be enforced even when doing a * blocking wait for events. * * Results: * None. * * Side effects: * May put the interpreter into a state where it can no longer execute * commands. May make callbacks into other interpreters. * *---------------------------------------------------------------------- */ static void TimeLimitCallback( ClientData clientData) { Tcl_Interp *interp = clientData; Interp *iPtr = clientData; int code; Tcl_Preserve(interp); iPtr->limit.timeEvent = NULL; /* * Must reset the granularity ticker here to force an immediate full * check. This is OK because we're swallowing the cost in the overall cost * of the event loop. [Bug 2891362] */ iPtr->limit.granularityTicker = 0; code = Tcl_LimitCheck(interp); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (while waiting for event)"); Tcl_BackgroundException(interp, code); } Tcl_Release(interp); } /* *---------------------------------------------------------------------- * * Tcl_LimitGetTime -- * * Get the current time limit. * * Results: * The time limit (by it being copied into the variable pointed to by the * timeLimitPtr). * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_LimitGetTime( Tcl_Interp *interp, Tcl_Time *timeLimitPtr) { Interp *iPtr = (Interp *) interp; memcpy(timeLimitPtr, &iPtr->limit.time, sizeof(Tcl_Time)); } /* *---------------------------------------------------------------------- * * Tcl_LimitSetGranularity -- * * Set the granularity divisor (which must be positive) for a particular * limit. * * Results: * None. * * Side effects: * The granularity is updated. * *---------------------------------------------------------------------- */ void Tcl_LimitSetGranularity( Tcl_Interp *interp, int type, int granularity) { Interp *iPtr = (Interp *) interp; if (granularity < 1) { Tcl_Panic("limit granularity must be positive"); } switch (type) { case TCL_LIMIT_COMMANDS: iPtr->limit.cmdGranularity = granularity; return; case TCL_LIMIT_TIME: iPtr->limit.timeGranularity = granularity; return; } Tcl_Panic("unknown type of resource limit"); } /* *---------------------------------------------------------------------- * * Tcl_LimitGetGranularity -- * * Get the granularity divisor for a particular limit. * * Results: * The granularity divisor for the given limit. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_LimitGetGranularity( Tcl_Interp *interp, int type) { Interp *iPtr = (Interp *) interp; switch (type) { case TCL_LIMIT_COMMANDS: return iPtr->limit.cmdGranularity; case TCL_LIMIT_TIME: return iPtr->limit.timeGranularity; } Tcl_Panic("unknown type of resource limit"); return -1; /* NOT REACHED */ } /* *---------------------------------------------------------------------- * * DeleteScriptLimitCallback -- * * Callback for when a script limit (a limit callback implemented as a * Tcl script in a master interpreter, as set up from Tcl) is deleted. * * Results: * None. * * Side effects: * The reference to the script callback from the controlling interpreter * is removed. * *---------------------------------------------------------------------- */ static void DeleteScriptLimitCallback( ClientData clientData) { ScriptLimitCallback *limitCBPtr = clientData; Tcl_DecrRefCount(limitCBPtr->scriptObj); if (limitCBPtr->entryPtr != NULL) { Tcl_DeleteHashEntry(limitCBPtr->entryPtr); } ckfree(limitCBPtr); } /* *---------------------------------------------------------------------- * * CallScriptLimitCallback -- * * Invoke a script limit callback. Used to implement limit callbacks set * at the Tcl level on child interpreters. * * Results: * None. * * Side effects: * Depends on the callback script. Errors are reported as background * errors. * *---------------------------------------------------------------------- */ static void CallScriptLimitCallback( ClientData clientData, Tcl_Interp *interp) /* Interpreter which failed the limit */ { ScriptLimitCallback *limitCBPtr = clientData; int code; if (Tcl_InterpDeleted(limitCBPtr->interp)) { return; } Tcl_Preserve(limitCBPtr->interp); code = Tcl_EvalObjEx(limitCBPtr->interp, limitCBPtr->scriptObj, TCL_EVAL_GLOBAL); if (code != TCL_OK && !Tcl_InterpDeleted(limitCBPtr->interp)) { Tcl_BackgroundException(limitCBPtr->interp, code); } Tcl_Release(limitCBPtr->interp); } /* *---------------------------------------------------------------------- * * SetScriptLimitCallback -- * * Install (or remove, if scriptObj is NULL) a limit callback script that * is called when the target interpreter exceeds the type of limit * specified. Each interpreter may only have one callback set on another * interpreter through this mechanism (though as many interpreters may be * limited as the programmer chooses overall). * * Results: * None. * * Side effects: * A limit callback implemented as an invokation of a Tcl script in * another interpreter is either installed or removed. * *---------------------------------------------------------------------- */ static void SetScriptLimitCallback( Tcl_Interp *interp, int type, Tcl_Interp *targetInterp, Tcl_Obj *scriptObj) { ScriptLimitCallback *limitCBPtr; Tcl_HashEntry *hashPtr; int isNew; ScriptLimitCallbackKey key; Interp *iPtr = (Interp *) interp; if (interp == targetInterp) { Tcl_Panic("installing limit callback to the limited interpreter"); } key.interp = targetInterp; key.type = type; if (scriptObj == NULL) { hashPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key); if (hashPtr != NULL) { Tcl_LimitRemoveHandler(targetInterp, type, CallScriptLimitCallback, Tcl_GetHashValue(hashPtr)); } return; } hashPtr = Tcl_CreateHashEntry(&iPtr->limit.callbacks, &key, &isNew); if (!isNew) { limitCBPtr = Tcl_GetHashValue(hashPtr); limitCBPtr->entryPtr = NULL; Tcl_LimitRemoveHandler(targetInterp, type, CallScriptLimitCallback, limitCBPtr); } limitCBPtr = ckalloc(sizeof(ScriptLimitCallback)); limitCBPtr->interp = interp; limitCBPtr->scriptObj = scriptObj; limitCBPtr->entryPtr = hashPtr; limitCBPtr->type = type; Tcl_IncrRefCount(scriptObj); Tcl_LimitAddHandler(targetInterp, type, CallScriptLimitCallback, limitCBPtr, DeleteScriptLimitCallback); Tcl_SetHashValue(hashPtr, limitCBPtr); } /* *---------------------------------------------------------------------- * * TclRemoveScriptLimitCallbacks -- * * Remove all script-implemented limit callbacks that make calls back * into the given interpreter. This invoked as part of deleting an * interpreter. * * Results: * None. * * Side effects: * The script limit callbacks are removed or marked for later removal. * *---------------------------------------------------------------------- */ void TclRemoveScriptLimitCallbacks( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hashPtr; Tcl_HashSearch search; ScriptLimitCallbackKey *keyPtr; hashPtr = Tcl_FirstHashEntry(&iPtr->limit.callbacks, &search); while (hashPtr != NULL) { keyPtr = (ScriptLimitCallbackKey *) Tcl_GetHashKey(&iPtr->limit.callbacks, hashPtr); Tcl_LimitRemoveHandler(keyPtr->interp, keyPtr->type, CallScriptLimitCallback, Tcl_GetHashValue(hashPtr)); hashPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&iPtr->limit.callbacks); } /* *---------------------------------------------------------------------- * * TclInitLimitSupport -- * * Initialise all the parts of the interpreter relating to resource limit * management. This allows an interpreter to both have limits set upon * itself and set limits upon other interpreters. * * Results: * None. * * Side effects: * The resource limit subsystem is initialised for the interpreter. * *---------------------------------------------------------------------- */ void TclInitLimitSupport( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; iPtr->limit.active = 0; iPtr->limit.granularityTicker = 0; iPtr->limit.exceeded = 0; iPtr->limit.cmdCount = 0; iPtr->limit.cmdHandlers = NULL; iPtr->limit.cmdGranularity = 1; memset(&iPtr->limit.time, 0, sizeof(Tcl_Time)); iPtr->limit.timeHandlers = NULL; iPtr->limit.timeEvent = NULL; iPtr->limit.timeGranularity = 10; Tcl_InitHashTable(&iPtr->limit.callbacks, sizeof(ScriptLimitCallbackKey)/sizeof(int)); } /* *---------------------------------------------------------------------- * * InheritLimitsFromMaster -- * * Derive the interpreter limit configuration for a slave interpreter * from the limit config for the master. * * Results: * None. * * Side effects: * The slave interpreter limits are set so that if the master has a * limit, it may not exceed it by handing off work to slave interpreters. * Note that this does not transfer limit callbacks from the master to * the slave. * *---------------------------------------------------------------------- */ static void InheritLimitsFromMaster( Tcl_Interp *slaveInterp, Tcl_Interp *masterInterp) { Interp *slavePtr = (Interp *) slaveInterp; Interp *masterPtr = (Interp *) masterInterp; if (masterPtr->limit.active & TCL_LIMIT_COMMANDS) { slavePtr->limit.active |= TCL_LIMIT_COMMANDS; slavePtr->limit.cmdCount = 0; slavePtr->limit.cmdGranularity = masterPtr->limit.cmdGranularity; } if (masterPtr->limit.active & TCL_LIMIT_TIME) { slavePtr->limit.active |= TCL_LIMIT_TIME; memcpy(&slavePtr->limit.time, &masterPtr->limit.time, sizeof(Tcl_Time)); slavePtr->limit.timeGranularity = masterPtr->limit.timeGranularity; } } /* *---------------------------------------------------------------------- * * SlaveCommandLimitCmd -- * * Implementation of the [interp limit $i commands] and [$i limit * commands] subcommands. See the interp manual page for a full * description. * * Results: * A standard Tcl result. * * Side effects: * Depends on the arguments. * *---------------------------------------------------------------------- */ static int SlaveCommandLimitCmd( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Interp *slaveInterp, /* Interpreter being adjusted. */ int consumedObjc, /* Number of args already parsed. */ int objc, /* Total number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const options[] = { "-command", "-granularity", "-value", NULL }; enum Options { OPT_CMD, OPT_GRAN, OPT_VAL }; Interp *iPtr = (Interp *) interp; int index; ScriptLimitCallbackKey key; ScriptLimitCallback *limitCBPtr; Tcl_HashEntry *hPtr; /* * First, ensure that we are not reading or writing the calling * interpreter's limits; it may only manipulate its children. Note that * the low level API enforces this with Tcl_Panic, which we want to * avoid. [Bug 3398794] */ if (interp == slaveInterp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "limits on current interpreter inaccessible", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "SELF", NULL); return TCL_ERROR; } if (objc == consumedObjc) { Tcl_Obj *dictPtr; TclNewObj(dictPtr); key.interp = slaveInterp; key.type = TCL_LIMIT_COMMANDS; hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key); if (hPtr != NULL) { limitCBPtr = Tcl_GetHashValue(hPtr); if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) { Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1), limitCBPtr->scriptObj); } else { goto putEmptyCommandInDict; } } else { Tcl_Obj *empty; putEmptyCommandInDict: TclNewObj(empty); Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1), empty); } Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[1], -1), Tcl_NewIntObj(Tcl_LimitGetGranularity(slaveInterp, TCL_LIMIT_COMMANDS))); if (Tcl_LimitTypeEnabled(slaveInterp, TCL_LIMIT_COMMANDS)) { Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[2], -1), Tcl_NewIntObj(Tcl_LimitGetCommands(slaveInterp))); } else { Tcl_Obj *empty; TclNewObj(empty); Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[2], -1), empty); } Tcl_SetObjResult(interp, dictPtr); return TCL_OK; } else if (objc == consumedObjc+1) { if (Tcl_GetIndexFromObj(interp, objv[consumedObjc], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum Options) index) { case OPT_CMD: key.interp = slaveInterp; key.type = TCL_LIMIT_COMMANDS; hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key); if (hPtr != NULL) { limitCBPtr = Tcl_GetHashValue(hPtr); if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) { Tcl_SetObjResult(interp, limitCBPtr->scriptObj); } } break; case OPT_GRAN: Tcl_SetObjResult(interp, Tcl_NewIntObj( Tcl_LimitGetGranularity(slaveInterp, TCL_LIMIT_COMMANDS))); break; case OPT_VAL: if (Tcl_LimitTypeEnabled(slaveInterp, TCL_LIMIT_COMMANDS)) { Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_LimitGetCommands(slaveInterp))); } break; } return TCL_OK; } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) { Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?"); return TCL_ERROR; } else { int i, scriptLen = 0, limitLen = 0; Tcl_Obj *scriptObj = NULL, *granObj = NULL, *limitObj = NULL; int gran = 0, limit = 0; for (i=consumedObjc ; i 0 ? scriptObj : NULL)); } if (granObj != NULL) { Tcl_LimitSetGranularity(slaveInterp, TCL_LIMIT_COMMANDS, gran); } if (limitObj != NULL) { if (limitLen > 0) { Tcl_LimitSetCommands(slaveInterp, limit); Tcl_LimitTypeSet(slaveInterp, TCL_LIMIT_COMMANDS); } else { Tcl_LimitTypeReset(slaveInterp, TCL_LIMIT_COMMANDS); } } return TCL_OK; } } /* *---------------------------------------------------------------------- * * SlaveTimeLimitCmd -- * * Implementation of the [interp limit $i time] and [$i limit time] * subcommands. See the interp manual page for a full description. * * Results: * A standard Tcl result. * * Side effects: * Depends on the arguments. * *---------------------------------------------------------------------- */ static int SlaveTimeLimitCmd( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Interp *slaveInterp, /* Interpreter being adjusted. */ int consumedObjc, /* Number of args already parsed. */ int objc, /* Total number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const options[] = { "-command", "-granularity", "-milliseconds", "-seconds", NULL }; enum Options { OPT_CMD, OPT_GRAN, OPT_MILLI, OPT_SEC }; Interp *iPtr = (Interp *) interp; int index; ScriptLimitCallbackKey key; ScriptLimitCallback *limitCBPtr; Tcl_HashEntry *hPtr; /* * First, ensure that we are not reading or writing the calling * interpreter's limits; it may only manipulate its children. Note that * the low level API enforces this with Tcl_Panic, which we want to * avoid. [Bug 3398794] */ if (interp == slaveInterp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "limits on current interpreter inaccessible", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "SELF", NULL); return TCL_ERROR; } if (objc == consumedObjc) { Tcl_Obj *dictPtr; TclNewObj(dictPtr); key.interp = slaveInterp; key.type = TCL_LIMIT_TIME; hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key); if (hPtr != NULL) { limitCBPtr = Tcl_GetHashValue(hPtr); if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) { Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1), limitCBPtr->scriptObj); } else { goto putEmptyCommandInDict; } } else { Tcl_Obj *empty; putEmptyCommandInDict: TclNewObj(empty); Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1), empty); } Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[1], -1), Tcl_NewIntObj(Tcl_LimitGetGranularity(slaveInterp, TCL_LIMIT_TIME))); if (Tcl_LimitTypeEnabled(slaveInterp, TCL_LIMIT_TIME)) { Tcl_Time limitMoment; Tcl_LimitGetTime(slaveInterp, &limitMoment); Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[2], -1), Tcl_NewLongObj(limitMoment.usec/1000)); Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[3], -1), Tcl_NewLongObj(limitMoment.sec)); } else { Tcl_Obj *empty; TclNewObj(empty); Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[2], -1), empty); Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[3], -1), empty); } Tcl_SetObjResult(interp, dictPtr); return TCL_OK; } else if (objc == consumedObjc+1) { if (Tcl_GetIndexFromObj(interp, objv[consumedObjc], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum Options) index) { case OPT_CMD: key.interp = slaveInterp; key.type = TCL_LIMIT_TIME; hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key); if (hPtr != NULL) { limitCBPtr = Tcl_GetHashValue(hPtr); if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) { Tcl_SetObjResult(interp, limitCBPtr->scriptObj); } } break; case OPT_GRAN: Tcl_SetObjResult(interp, Tcl_NewIntObj( Tcl_LimitGetGranularity(slaveInterp, TCL_LIMIT_TIME))); break; case OPT_MILLI: if (Tcl_LimitTypeEnabled(slaveInterp, TCL_LIMIT_TIME)) { Tcl_Time limitMoment; Tcl_LimitGetTime(slaveInterp, &limitMoment); Tcl_SetObjResult(interp, Tcl_NewLongObj(limitMoment.usec/1000)); } break; case OPT_SEC: if (Tcl_LimitTypeEnabled(slaveInterp, TCL_LIMIT_TIME)) { Tcl_Time limitMoment; Tcl_LimitGetTime(slaveInterp, &limitMoment); Tcl_SetObjResult(interp, Tcl_NewLongObj(limitMoment.sec)); } break; } return TCL_OK; } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) { Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?"); return TCL_ERROR; } else { int i, scriptLen = 0, milliLen = 0, secLen = 0; Tcl_Obj *scriptObj = NULL, *granObj = NULL; Tcl_Obj *milliObj = NULL, *secObj = NULL; int gran = 0; Tcl_Time limitMoment; int tmp; Tcl_LimitGetTime(slaveInterp, &limitMoment); for (i=consumedObjc ; i 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may only set -milliseconds if -seconds is not " "also being reset", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "BADUSAGE", NULL); return TCL_ERROR; } if (milliLen == 0 && (secObj == NULL || secLen > 0)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may only reset -milliseconds if -seconds is " "also being reset", -1)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "BADUSAGE", NULL); return TCL_ERROR; } } if (milliLen > 0 || secLen > 0) { /* * Force usec to be in range [0..1000000), possibly * incrementing sec in the process. This makes it much easier * for people to write scripts that do small time increments. */ limitMoment.sec += limitMoment.usec / 1000000; limitMoment.usec %= 1000000; Tcl_LimitSetTime(slaveInterp, &limitMoment); Tcl_LimitTypeSet(slaveInterp, TCL_LIMIT_TIME); } else { Tcl_LimitTypeReset(slaveInterp, TCL_LIMIT_TIME); } } if (scriptObj != NULL) { SetScriptLimitCallback(interp, TCL_LIMIT_TIME, slaveInterp, (scriptLen > 0 ? scriptObj : NULL)); } if (granObj != NULL) { Tcl_LimitSetGranularity(slaveInterp, TCL_LIMIT_TIME, gran); } return TCL_OK; } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclResolve.c0000644000175000017500000003247012663653207015477 0ustar sergeisergei/* * tclResolve.c -- * * Contains hooks for customized command/variable name resolution * schemes. These hooks allow extensions like [incr Tcl] to add their own * name resolution rules to the Tcl language. Rules can be applied to a * particular namespace, to the interpreter as a whole, or both. * * Copyright (c) 1998 Lucent Technologies, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Declarations for functions local to this file: */ static void BumpCmdRefEpochs(Namespace *nsPtr); /* *---------------------------------------------------------------------- * * Tcl_AddInterpResolvers -- * * Adds a set of command/variable resolution functions to an interpreter. * These functions are consulted when commands are resolved in * Tcl_FindCommand, and when variables are resolved in TclLookupVar and * LookupCompiledLocal. Each namespace may also have its own set of * resolution functions which take precedence over those for the * interpreter. * * When a name is resolved, it is handled as follows. First, the name is * passed to the resolution functions for the namespace. If not resolved, * the name is passed to each of the resolution functions added to the * interpreter. Finally, if still not resolved, the name is handled using * the default Tcl rules for name resolution. * * Results: * Returns pointers to the current name resolution functions in the * cmdProcPtr, varProcPtr and compiledVarProcPtr arguments. * * Side effects: * If a compiledVarProc is specified, this function bumps the * compileEpoch for the interpreter, forcing all code to be recompiled. * If a cmdProc is specified, this function bumps the cmdRefEpoch in all * namespaces, forcing commands to be resolved again using the new rules. * *---------------------------------------------------------------------- */ void Tcl_AddInterpResolvers( Tcl_Interp *interp, /* Interpreter whose name resolution rules are * being modified. */ const char *name, /* Name of this resolution scheme. */ Tcl_ResolveCmdProc *cmdProc,/* New function for command resolution. */ Tcl_ResolveVarProc *varProc,/* Function for variable resolution at * runtime. */ Tcl_ResolveCompiledVarProc *compiledVarProc) /* Function for variable resolution at compile * time. */ { Interp *iPtr = (Interp *) interp; ResolverScheme *resPtr; unsigned len; /* * Since we're adding a new name resolution scheme, we must force all code * to be recompiled to use the new scheme. If there are new compiled * variable resolution rules, bump the compiler epoch to invalidate * compiled code. If there are new command resolution rules, bump the * cmdRefEpoch in all namespaces. */ if (compiledVarProc) { iPtr->compileEpoch++; } if (cmdProc) { BumpCmdRefEpochs(iPtr->globalNsPtr); } /* * Look for an existing scheme with the given name. If found, then replace * its rules. */ for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) { if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { resPtr->cmdResProc = cmdProc; resPtr->varResProc = varProc; resPtr->compiledVarResProc = compiledVarProc; return; } } /* * Otherwise, this is a new scheme. Add it to the FRONT of the linked * list, so that it overrides existing schemes. */ resPtr = ckalloc(sizeof(ResolverScheme)); len = strlen(name) + 1; resPtr->name = ckalloc(len); memcpy(resPtr->name, name, len); resPtr->cmdResProc = cmdProc; resPtr->varResProc = varProc; resPtr->compiledVarResProc = compiledVarProc; resPtr->nextPtr = iPtr->resolverPtr; iPtr->resolverPtr = resPtr; } /* *---------------------------------------------------------------------- * * Tcl_GetInterpResolvers -- * * Looks for a set of command/variable resolution functions with the * given name in an interpreter. These functions are registered by * calling Tcl_AddInterpResolvers. * * Results: * If the name is recognized, this function returns non-zero, along with * pointers to the name resolution functions in the Tcl_ResolverInfo * structure. If the name is not recognized, this function returns zero. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetInterpResolvers( Tcl_Interp *interp, /* Interpreter whose name resolution rules are * being queried. */ const char *name, /* Look for a scheme with this name. */ Tcl_ResolverInfo *resInfoPtr) /* Returns pointers to the functions, if * found */ { Interp *iPtr = (Interp *) interp; ResolverScheme *resPtr; /* * Look for an existing scheme with the given name. If found, then return * pointers to its functions. */ for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) { if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { resInfoPtr->cmdResProc = resPtr->cmdResProc; resInfoPtr->varResProc = resPtr->varResProc; resInfoPtr->compiledVarResProc = resPtr->compiledVarResProc; return 1; } } return 0; } /* *---------------------------------------------------------------------- * * Tcl_RemoveInterpResolvers -- * * Removes a set of command/variable resolution functions previously * added by Tcl_AddInterpResolvers. The next time a command/variable name * is resolved, these functions won't be consulted. * * Results: * Returns non-zero if the name was recognized and the resolution scheme * was deleted. Returns zero otherwise. * * Side effects: * If a scheme with a compiledVarProc was deleted, this function bumps * the compileEpoch for the interpreter, forcing all code to be * recompiled. If a scheme with a cmdProc was deleted, this function * bumps the cmdRefEpoch in all namespaces, forcing commands to be * resolved again using the new rules. * *---------------------------------------------------------------------- */ int Tcl_RemoveInterpResolvers( Tcl_Interp *interp, /* Interpreter whose name resolution rules are * being modified. */ const char *name) /* Name of the scheme to be removed. */ { Interp *iPtr = (Interp *) interp; ResolverScheme **prevPtrPtr, *resPtr; /* * Look for an existing scheme with the given name. */ prevPtrPtr = &iPtr->resolverPtr; for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) { if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { break; } prevPtrPtr = &resPtr->nextPtr; } /* * If we found the scheme, delete it. */ if (resPtr) { /* * If we're deleting a scheme with compiled variable resolution rules, * bump the compiler epoch to invalidate compiled code. If we're * deleting a scheme with command resolution rules, bump the * cmdRefEpoch in all namespaces. */ if (resPtr->compiledVarResProc) { iPtr->compileEpoch++; } if (resPtr->cmdResProc) { BumpCmdRefEpochs(iPtr->globalNsPtr); } *prevPtrPtr = resPtr->nextPtr; ckfree(resPtr->name); ckfree(resPtr); return 1; } return 0; } /* *---------------------------------------------------------------------- * * BumpCmdRefEpochs -- * * This function is used to bump the cmdRefEpoch counters in the * specified namespace and all of its child namespaces. It is used * whenever name resolution schemes are added/removed from an * interpreter, to invalidate all command references. * * Results: * None. * * Side effects: * Bumps the cmdRefEpoch in the specified namespace and its children, * recursively. * *---------------------------------------------------------------------- */ static void BumpCmdRefEpochs( Namespace *nsPtr) /* Namespace being modified. */ { Tcl_HashEntry *entry; Tcl_HashSearch search; nsPtr->cmdRefEpoch++; #ifndef BREAK_NAMESPACE_COMPAT for (entry = Tcl_FirstHashEntry(&nsPtr->childTable, &search); entry != NULL; entry = Tcl_NextHashEntry(&search)) { Namespace *childNsPtr = Tcl_GetHashValue(entry); BumpCmdRefEpochs(childNsPtr); } #else if (nsPtr->childTablePtr != NULL) { for (entry = Tcl_FirstHashEntry(nsPtr->childTablePtr, &search); entry != NULL; entry = Tcl_NextHashEntry(&search)) { Namespace *childNsPtr = Tcl_GetHashValue(entry); BumpCmdRefEpochs(childNsPtr); } } #endif TclInvalidateNsPath(nsPtr); } /* *---------------------------------------------------------------------- * * Tcl_SetNamespaceResolvers -- * * Sets the command/variable resolution functions for a namespace, * thereby changing the way that command/variable names are interpreted. * This allows extension writers to support different name resolution * schemes, such as those for object-oriented packages. * * Command resolution is handled by a function of the following type: * * typedef int (Tcl_ResolveCmdProc)(Tcl_Interp *interp, * const char *name, Tcl_Namespace *context, * int flags, Tcl_Command *rPtr); * * Whenever a command is executed or Tcl_FindCommand is invoked within * the namespace, this function is called to resolve the command name. If * this function is able to resolve the name, it should return the status * code TCL_OK, along with the corresponding Tcl_Command in the rPtr * argument. Otherwise, the function can return TCL_CONTINUE, and the * command will be treated under the usual name resolution rules. Or, it * can return TCL_ERROR, and the command will be considered invalid. * * Variable resolution is handled by two functions. The first is called * whenever a variable needs to be resolved at compile time: * * typedef int (Tcl_ResolveCompiledVarProc)(Tcl_Interp *interp, * const char *name, Tcl_Namespace *context, * Tcl_ResolvedVarInfo *rPtr); * * If this function is able to resolve the name, it should return the * status code TCL_OK, along with variable resolution info in the rPtr * argument; this info will be used to set up compiled locals in the call * frame at runtime. The function may also return TCL_CONTINUE, and the * variable will be treated under the usual name resolution rules. Or, it * can return TCL_ERROR, and the variable will be considered invalid. * * Another function is used whenever a variable needs to be resolved at * runtime but it is not recognized as a compiled local. (For example, * the variable may be requested via Tcl_FindNamespaceVar.) This function * has the following type: * * typedef int (Tcl_ResolveVarProc)(Tcl_Interp *interp, * const char *name, Tcl_Namespace *context, * int flags, Tcl_Var *rPtr); * * This function is quite similar to the compile-time version. It returns * the same status codes, but if variable resolution succeeds, this * function returns a Tcl_Var directly via the rPtr argument. * * Results: * Nothing. * * Side effects: * Bumps the command epoch counter for the namespace, invalidating all * command references in that namespace. Also bumps the resolver epoch * counter for the namespace, forcing all code in the namespace to be * recompiled. * *---------------------------------------------------------------------- */ void Tcl_SetNamespaceResolvers( Tcl_Namespace *namespacePtr,/* Namespace whose resolution rules are being * modified. */ Tcl_ResolveCmdProc *cmdProc,/* Function for command resolution */ Tcl_ResolveVarProc *varProc,/* Function for variable resolution at * run-time */ Tcl_ResolveCompiledVarProc *compiledVarProc) /* Function for variable resolution at compile * time. */ { Namespace *nsPtr = (Namespace *) namespacePtr; /* * Plug in the new command resolver, and bump the epoch counters so that * all code will have to be recompiled and all commands will have to be * resolved again using the new policy. */ nsPtr->cmdResProc = cmdProc; nsPtr->varResProc = varProc; nsPtr->compiledVarResProc = compiledVarProc; nsPtr->cmdRefEpoch++; nsPtr->resolverEpoch++; TclInvalidateNsPath(nsPtr); } /* *---------------------------------------------------------------------- * * Tcl_GetNamespaceResolvers -- * * Returns the current command/variable resolution functions for a * namespace. By default, these functions are NULL. New functions can be * installed by calling Tcl_SetNamespaceResolvers, to provide new name * resolution rules. * * Results: * Returns non-zero if any name resolution functions have been assigned * to this namespace; also returns pointers to the functions in the * Tcl_ResolverInfo structure. Returns zero otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetNamespaceResolvers( Tcl_Namespace *namespacePtr,/* Namespace whose resolution rules are being * modified. */ Tcl_ResolverInfo *resInfoPtr) /* Returns: pointers for all name resolution * functions assigned to this namespace. */ { Namespace *nsPtr = (Namespace *) namespacePtr; resInfoPtr->cmdResProc = nsPtr->cmdResProc; resInfoPtr->varResProc = nsPtr->varResProc; resInfoPtr->compiledVarResProc = nsPtr->compiledVarResProc; if (nsPtr->cmdResProc != NULL || nsPtr->varResProc != NULL || nsPtr->compiledVarResProc != NULL) { return 1; } return 0; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclPlatDecls.h0000644000175000017500000000631712665173571015744 0ustar sergeisergei/* * tclPlatDecls.h -- * * Declarations of platform specific Tcl APIs. * * Copyright (c) 1998-1999 by Scriptics Corporation. * All rights reserved. */ #ifndef _TCLPLATDECLS #define _TCLPLATDECLS #undef TCL_STORAGE_CLASS #ifdef BUILD_tcl # define TCL_STORAGE_CLASS DLLEXPORT #else # ifdef USE_TCL_STUBS # define TCL_STORAGE_CLASS # else # define TCL_STORAGE_CLASS DLLIMPORT # endif #endif /* * WARNING: This file is automatically generated by the tools/genStubs.tcl * script. Any modifications to the function declarations below should be made * in the generic/tcl.decls script. */ /* * TCHAR is needed here for win32, so if it is not defined yet do it here. * This way, we don't need to include just for one define. */ #if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(_TCHAR_DEFINED) # if defined(_UNICODE) typedef wchar_t TCHAR; # else typedef char TCHAR; # endif # define _TCHAR_DEFINED #endif /* !BEGIN!: Do not edit below this line. */ #ifdef __cplusplus extern "C" { #endif /* * Exported function declarations: */ #if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ /* 0 */ EXTERN TCHAR * Tcl_WinUtfToTChar(const char *str, int len, Tcl_DString *dsPtr); /* 1 */ EXTERN char * Tcl_WinTCharToUtf(const TCHAR *str, int len, Tcl_DString *dsPtr); #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ /* 0 */ EXTERN int Tcl_MacOSXOpenBundleResources(Tcl_Interp *interp, const char *bundleName, int hasResourceFile, int maxPathLen, char *libraryPath); /* 1 */ EXTERN int Tcl_MacOSXOpenVersionedBundleResources( Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, int maxPathLen, char *libraryPath); #endif /* MACOSX */ typedef struct TclPlatStubs { int magic; void *hooks; #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 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ int (*tcl_MacOSXOpenBundleResources) (Tcl_Interp *interp, const char *bundleName, int hasResourceFile, int maxPathLen, char *libraryPath); /* 0 */ int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, int maxPathLen, char *libraryPath); /* 1 */ #endif /* MACOSX */ } TclPlatStubs; extern const TclPlatStubs *tclPlatStubsPtr; #ifdef __cplusplus } #endif #if defined(USE_TCL_STUBS) /* * Inline function declarations: */ #if defined(_WIN32) || defined(__CYGWIN__) /* WIN */ #define Tcl_WinUtfToTChar \ (tclPlatStubsPtr->tcl_WinUtfToTChar) /* 0 */ #define Tcl_WinTCharToUtf \ (tclPlatStubsPtr->tcl_WinTCharToUtf) /* 1 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ #define Tcl_MacOSXOpenBundleResources \ (tclPlatStubsPtr->tcl_MacOSXOpenBundleResources) /* 0 */ #define Tcl_MacOSXOpenVersionedBundleResources \ (tclPlatStubsPtr->tcl_MacOSXOpenVersionedBundleResources) /* 1 */ #endif /* MACOSX */ #endif /* defined(USE_TCL_STUBS) */ /* !END!: Do not edit above this line. */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT #endif /* _TCLPLATDECLS */ tcl8.6.5/generic/tclFileSystem.h0000644000175000017500000000463112663660065016147 0ustar sergeisergei/* * tclFileSystem.h -- * * This file contains the common defintions and prototypes for use by * Tcl's filesystem and path handling layers. * * Copyright (c) 2003 Vince Darley. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLFILESYSTEM #define _TCLFILESYSTEM #include "tcl.h" /* * The internal TclFS API provides routines for handling and manipulating * paths efficiently, taking direct advantage of the "path" Tcl_Obj type. * * These functions are not exported at all at present. */ MODULE_SCOPE int TclFSCwdPointerEquals(Tcl_Obj **pathPtrPtr); MODULE_SCOPE int TclFSNormalizeToUniquePath(Tcl_Interp *interp, Tcl_Obj *pathPtr, int startAt); MODULE_SCOPE Tcl_Obj * TclFSMakePathRelative(Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_Obj *cwdPtr); MODULE_SCOPE int TclFSEnsureEpochOk(Tcl_Obj *pathPtr, const Tcl_Filesystem **fsPtrPtr); MODULE_SCOPE void TclFSSetPathDetails(Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr, ClientData clientData); MODULE_SCOPE Tcl_Obj * TclFSNormalizeAbsolutePath(Tcl_Interp *interp, Tcl_Obj *pathPtr); MODULE_SCOPE size_t TclFSEpoch(void); /* * Private shared variables for use by tclIOUtil.c and tclPathObj.c */ MODULE_SCOPE const Tcl_Filesystem tclNativeFilesystem; /* * Private shared functions for use by tclIOUtil.c, tclPathObj.c and * tclFileName.c, and any platform-specific filesystem code. */ MODULE_SCOPE Tcl_PathType TclFSGetPathType(Tcl_Obj *pathPtr, const Tcl_Filesystem **filesystemPtrPtr, int *driveNameLengthPtr); MODULE_SCOPE Tcl_PathType TclFSNonnativePathType(const char *pathPtr, int pathLen, const Tcl_Filesystem **filesystemPtrPtr, int *driveNameLengthPtr, Tcl_Obj **driveNameRef); MODULE_SCOPE Tcl_PathType TclGetPathType(Tcl_Obj *pathPtr, const Tcl_Filesystem **filesystemPtrPtr, int *driveNameLengthPtr, Tcl_Obj **driveNameRef); MODULE_SCOPE int TclFSEpochOk(size_t filesystemEpoch); MODULE_SCOPE int TclFSCwdIsNative(void); MODULE_SCOPE Tcl_Obj * TclWinVolumeRelativeNormalize(Tcl_Interp *interp, const char *path, Tcl_Obj **useThisCwdPtr); MODULE_SCOPE Tcl_FSPathInFilesystemProc TclNativePathInFilesystem; MODULE_SCOPE Tcl_FSCreateInternalRepProc TclNativeCreateNativeRep; #endif /* _TCLFILESYSTEM */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/regc_locale.c0000644000175000017500000015015412663660065015614 0ustar sergeisergei/* * regc_locale.c -- * * This file contains the Unicode locale specific regexp routines. * This file is #included by regcomp.c. * * Copyright (c) 1998 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ /* ASCII character-name table */ static const struct cname { const char *name; const char code; } cnames[] = { {"NUL", '\0'}, {"SOH", '\001'}, {"STX", '\002'}, {"ETX", '\003'}, {"EOT", '\004'}, {"ENQ", '\005'}, {"ACK", '\006'}, {"BEL", '\007'}, {"alert", '\007'}, {"BS", '\010'}, {"backspace", '\b'}, {"HT", '\011'}, {"tab", '\t'}, {"LF", '\012'}, {"newline", '\n'}, {"VT", '\013'}, {"vertical-tab", '\v'}, {"FF", '\014'}, {"form-feed", '\f'}, {"CR", '\015'}, {"carriage-return", '\r'}, {"SO", '\016'}, {"SI", '\017'}, {"DLE", '\020'}, {"DC1", '\021'}, {"DC2", '\022'}, {"DC3", '\023'}, {"DC4", '\024'}, {"NAK", '\025'}, {"SYN", '\026'}, {"ETB", '\027'}, {"CAN", '\030'}, {"EM", '\031'}, {"SUB", '\032'}, {"ESC", '\033'}, {"IS4", '\034'}, {"FS", '\034'}, {"IS3", '\035'}, {"GS", '\035'}, {"IS2", '\036'}, {"RS", '\036'}, {"IS1", '\037'}, {"US", '\037'}, {"space", ' '}, {"exclamation-mark",'!'}, {"quotation-mark", '"'}, {"number-sign", '#'}, {"dollar-sign", '$'}, {"percent-sign", '%'}, {"ampersand", '&'}, {"apostrophe", '\''}, {"left-parenthesis",'('}, {"right-parenthesis", ')'}, {"asterisk", '*'}, {"plus-sign", '+'}, {"comma", ','}, {"hyphen", '-'}, {"hyphen-minus", '-'}, {"period", '.'}, {"full-stop", '.'}, {"slash", '/'}, {"solidus", '/'}, {"zero", '0'}, {"one", '1'}, {"two", '2'}, {"three", '3'}, {"four", '4'}, {"five", '5'}, {"six", '6'}, {"seven", '7'}, {"eight", '8'}, {"nine", '9'}, {"colon", ':'}, {"semicolon", ';'}, {"less-than-sign", '<'}, {"equals-sign", '='}, {"greater-than-sign", '>'}, {"question-mark", '?'}, {"commercial-at", '@'}, {"left-square-bracket", '['}, {"backslash", '\\'}, {"reverse-solidus", '\\'}, {"right-square-bracket", ']'}, {"circumflex", '^'}, {"circumflex-accent", '^'}, {"underscore", '_'}, {"low-line", '_'}, {"grave-accent", '`'}, {"left-brace", '{'}, {"left-curly-bracket", '{'}, {"vertical-line", '|'}, {"right-brace", '}'}, {"right-curly-bracket", '}'}, {"tilde", '~'}, {"DEL", '\177'}, {NULL, 0} }; /* * Unicode character-class tables. */ typedef struct { chr start; chr end; } crange; /* * Declarations of Unicode character ranges. This code * is automatically generated by the tools/uniClass.tcl script * and used in generic/regc_locale.c. Do not modify by hand. */ /* * Unicode: alphabetic characters. */ static const crange alphaRangeTable[] = { {0x41, 0x5a}, {0x61, 0x7a}, {0xc0, 0xd6}, {0xd8, 0xf6}, {0xf8, 0x2c1}, {0x2c6, 0x2d1}, {0x2e0, 0x2e4}, {0x370, 0x374}, {0x37a, 0x37d}, {0x388, 0x38a}, {0x38e, 0x3a1}, {0x3a3, 0x3f5}, {0x3f7, 0x481}, {0x48a, 0x52f}, {0x531, 0x556}, {0x561, 0x587}, {0x5d0, 0x5ea}, {0x5f0, 0x5f2}, {0x620, 0x64a}, {0x671, 0x6d3}, {0x6fa, 0x6fc}, {0x712, 0x72f}, {0x74d, 0x7a5}, {0x7ca, 0x7ea}, {0x800, 0x815}, {0x840, 0x858}, {0x8a0, 0x8b4}, {0x904, 0x939}, {0x958, 0x961}, {0x971, 0x980}, {0x985, 0x98c}, {0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9df, 0x9e1}, {0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa59, 0xa5c}, {0xa72, 0xa74}, {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0}, {0xab5, 0xab9}, {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb5f, 0xb61}, {0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39}, {0xc58, 0xc5a}, {0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xd05, 0xd0c}, {0xd0e, 0xd10}, {0xd12, 0xd3a}, {0xd5f, 0xd61}, {0xd7a, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6}, {0xe01, 0xe30}, {0xe40, 0xe46}, {0xe94, 0xe97}, {0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb0}, {0xec0, 0xec4}, {0xedc, 0xedf}, {0xf40, 0xf47}, {0xf49, 0xf6c}, {0xf88, 0xf8c}, {0x1000, 0x102a}, {0x1050, 0x1055}, {0x105a, 0x105d}, {0x106e, 0x1070}, {0x1075, 0x1081}, {0x10a0, 0x10c5}, {0x10d0, 0x10fa}, {0x10fc, 0x1248}, {0x124a, 0x124d}, {0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288}, {0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135a}, {0x1380, 0x138f}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd}, {0x1401, 0x166c}, {0x166f, 0x167f}, {0x1681, 0x169a}, {0x16a0, 0x16ea}, {0x16f1, 0x16f8}, {0x1700, 0x170c}, {0x170e, 0x1711}, {0x1720, 0x1731}, {0x1740, 0x1751}, {0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17b3}, {0x1820, 0x1877}, {0x1880, 0x18a8}, {0x18b0, 0x18f5}, {0x1900, 0x191e}, {0x1950, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19b0, 0x19c9}, {0x1a00, 0x1a16}, {0x1a20, 0x1a54}, {0x1b05, 0x1b33}, {0x1b45, 0x1b4b}, {0x1b83, 0x1ba0}, {0x1bba, 0x1be5}, {0x1c00, 0x1c23}, {0x1c4d, 0x1c4f}, {0x1c5a, 0x1c7d}, {0x1ce9, 0x1cec}, {0x1cee, 0x1cf1}, {0x1d00, 0x1dbf}, {0x1e00, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fbc}, {0x1fc2, 0x1fc4}, {0x1fc6, 0x1fcc}, {0x1fd0, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fe0, 0x1fec}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffc}, {0x2090, 0x209c}, {0x210a, 0x2113}, {0x2119, 0x211d}, {0x212a, 0x212d}, {0x212f, 0x2139}, {0x213c, 0x213f}, {0x2145, 0x2149}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2ce4}, {0x2ceb, 0x2cee}, {0x2d00, 0x2d25}, {0x2d30, 0x2d67}, {0x2d80, 0x2d96}, {0x2da0, 0x2da6}, {0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6}, {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x3031, 0x3035}, {0x3041, 0x3096}, {0x309d, 0x309f}, {0x30a1, 0x30fa}, {0x30fc, 0x30ff}, {0x3105, 0x312d}, {0x3131, 0x318e}, {0x31a0, 0x31ba}, {0x31f0, 0x31ff}, {0x3400, 0x4db5}, {0x4e00, 0x9fd5}, {0xa000, 0xa48c}, {0xa4d0, 0xa4fd}, {0xa500, 0xa60c}, {0xa610, 0xa61f}, {0xa640, 0xa66e}, {0xa67f, 0xa69d}, {0xa6a0, 0xa6e5}, {0xa717, 0xa71f}, {0xa722, 0xa788}, {0xa78b, 0xa7ad}, {0xa7b0, 0xa7b7}, {0xa7f7, 0xa801}, {0xa803, 0xa805}, {0xa807, 0xa80a}, {0xa80c, 0xa822}, {0xa840, 0xa873}, {0xa882, 0xa8b3}, {0xa8f2, 0xa8f7}, {0xa90a, 0xa925}, {0xa930, 0xa946}, {0xa960, 0xa97c}, {0xa984, 0xa9b2}, {0xa9e0, 0xa9e4}, {0xa9e6, 0xa9ef}, {0xa9fa, 0xa9fe}, {0xaa00, 0xaa28}, {0xaa40, 0xaa42}, {0xaa44, 0xaa4b}, {0xaa60, 0xaa76}, {0xaa7e, 0xaaaf}, {0xaab9, 0xaabd}, {0xaadb, 0xaadd}, {0xaae0, 0xaaea}, {0xaaf2, 0xaaf4}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e}, {0xab30, 0xab5a}, {0xab5c, 0xab65}, {0xab70, 0xabe2}, {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xdc00, 0xdc3e}, {0xdc40, 0xdc7e}, {0xde80, 0xdebe}, {0xdec0, 0xdefe}, {0xdf00, 0xdf3e}, {0xdf40, 0xdf7e}, {0xdf80, 0xdfbe}, {0xdfc0, 0xdffe}, {0xf900, 0xfa6d}, {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1f, 0xfb28}, {0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbb1}, {0xfbd3, 0xfd3d}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb}, {0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff21, 0xff3a}, {0xff41, 0xff5a}, {0xff66, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc} #if TCL_UTF_MAX > 4 ,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d}, {0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10280, 0x1029c}, {0x102a0, 0x102d0}, {0x10300, 0x1031f}, {0x10330, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375}, {0x10380, 0x1039d}, {0x103a0, 0x103c3}, {0x103c8, 0x103cf}, {0x10400, 0x1049d}, {0x10500, 0x10527}, {0x10530, 0x10563}, {0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10860, 0x10876}, {0x10880, 0x1089e}, {0x108e0, 0x108f2}, {0x10900, 0x10915}, {0x10920, 0x10939}, {0x10980, 0x109b7}, {0x10a10, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33}, {0x10a60, 0x10a7c}, {0x10a80, 0x10a9c}, {0x10ac0, 0x10ac7}, {0x10ac9, 0x10ae4}, {0x10b00, 0x10b35}, {0x10b40, 0x10b55}, {0x10b60, 0x10b72}, {0x10b80, 0x10b91}, {0x10c00, 0x10c48}, {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x11003, 0x11037}, {0x11083, 0x110af}, {0x110d0, 0x110e8}, {0x11103, 0x11126}, {0x11150, 0x11172}, {0x11183, 0x111b2}, {0x111c1, 0x111c4}, {0x11200, 0x11211}, {0x11213, 0x1122b}, {0x11280, 0x11286}, {0x1128a, 0x1128d}, {0x1128f, 0x1129d}, {0x1129f, 0x112a8}, {0x112b0, 0x112de}, {0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339}, {0x1135d, 0x11361}, {0x11480, 0x114af}, {0x11580, 0x115ae}, {0x115d8, 0x115db}, {0x11600, 0x1162f}, {0x11680, 0x116aa}, {0x11700, 0x11719}, {0x118a0, 0x118df}, {0x11ac0, 0x11af8}, {0x12000, 0x12399}, {0x12480, 0x12543}, {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e}, {0x16ad0, 0x16aed}, {0x16b00, 0x16b2f}, {0x16b40, 0x16b43}, {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d6c0}, {0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6fa}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d734}, {0x1d736, 0x1d74e}, {0x1d750, 0x1d76e}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d7a8}, {0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7cb}, {0x1e800, 0x1e8c4}, {0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d} #endif }; #define NUM_ALPHA_RANGE (sizeof(alphaRangeTable)/sizeof(crange)) static const chr alphaCharTable[] = { 0xaa, 0xb5, 0xba, 0x2ec, 0x2ee, 0x376, 0x377, 0x37f, 0x386, 0x38c, 0x559, 0x66e, 0x66f, 0x6d5, 0x6e5, 0x6e6, 0x6ee, 0x6ef, 0x6ff, 0x710, 0x7b1, 0x7f4, 0x7f5, 0x7fa, 0x81a, 0x824, 0x828, 0x93d, 0x950, 0x98f, 0x990, 0x9b2, 0x9bd, 0x9ce, 0x9dc, 0x9dd, 0x9f0, 0x9f1, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36, 0xa38, 0xa39, 0xa5e, 0xab2, 0xab3, 0xabd, 0xad0, 0xae0, 0xae1, 0xaf9, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb3d, 0xb5c, 0xb5d, 0xb71, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4, 0xbd0, 0xc3d, 0xc60, 0xc61, 0xcbd, 0xcde, 0xce0, 0xce1, 0xcf1, 0xcf2, 0xd3d, 0xd4e, 0xdbd, 0xe32, 0xe33, 0xe81, 0xe82, 0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xeb2, 0xeb3, 0xebd, 0xec6, 0xf00, 0x103f, 0x1061, 0x1065, 0x1066, 0x108e, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x17d7, 0x17dc, 0x18aa, 0x1aa7, 0x1bae, 0x1baf, 0x1cf5, 0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f, 0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183, 0x2184, 0x2cf2, 0x2cf3, 0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b, 0x303c, 0xa62a, 0xa62b, 0xa8fb, 0xa8fd, 0xa9cf, 0xaa7a, 0xaab1, 0xaab5, 0xaab6, 0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44 #if TCL_UTF_MAX > 4 ,0x1003c, 0x1003d, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4, 0x108f5, 0x109be, 0x109bf, 0x10a00, 0x11176, 0x111da, 0x111dc, 0x11288, 0x1130f, 0x11310, 0x11332, 0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644, 0x118ff, 0x16f50, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e #endif }; #define NUM_ALPHA_CHAR (sizeof(alphaCharTable)/sizeof(chr)) /* * Unicode: control characters. */ static const crange controlRangeTable[] = { {0x0, 0x1f}, {0x7f, 0x9f}, {0x600, 0x605}, {0x200b, 0x200f}, {0x202a, 0x202e}, {0x2060, 0x2064}, {0x2066, 0x206f}, {0xe000, 0xf8ff}, {0xfff9, 0xfffb} #if TCL_UTF_MAX > 4 ,{0x1bca0, 0x1bca3}, {0x1d173, 0x1d17a}, {0xe0020, 0xe007f}, {0xf0000, 0xffffd}, {0x100000, 0x10fffd} #endif }; #define NUM_CONTROL_RANGE (sizeof(controlRangeTable)/sizeof(crange)) static const chr controlCharTable[] = { 0xad, 0x61c, 0x6dd, 0x70f, 0x180e, 0xfeff #if TCL_UTF_MAX > 4 ,0x110bd, 0xe0001 #endif }; #define NUM_CONTROL_CHAR (sizeof(controlCharTable)/sizeof(chr)) /* * Unicode: decimal digit characters. */ static const crange digitRangeTable[] = { {0x30, 0x39}, {0x660, 0x669}, {0x6f0, 0x6f9}, {0x7c0, 0x7c9}, {0x966, 0x96f}, {0x9e6, 0x9ef}, {0xa66, 0xa6f}, {0xae6, 0xaef}, {0xb66, 0xb6f}, {0xbe6, 0xbef}, {0xc66, 0xc6f}, {0xce6, 0xcef}, {0xd66, 0xd6f}, {0xde6, 0xdef}, {0xe50, 0xe59}, {0xed0, 0xed9}, {0xf20, 0xf29}, {0x1040, 0x1049}, {0x1090, 0x1099}, {0x17e0, 0x17e9}, {0x1810, 0x1819}, {0x1946, 0x194f}, {0x19d0, 0x19d9}, {0x1a80, 0x1a89}, {0x1a90, 0x1a99}, {0x1b50, 0x1b59}, {0x1bb0, 0x1bb9}, {0x1c40, 0x1c49}, {0x1c50, 0x1c59}, {0xa620, 0xa629}, {0xa8d0, 0xa8d9}, {0xa900, 0xa909}, {0xa9d0, 0xa9d9}, {0xa9f0, 0xa9f9}, {0xaa50, 0xaa59}, {0xabf0, 0xabf9}, {0xff10, 0xff19} #if TCL_UTF_MAX > 4 ,{0x104a0, 0x104a9}, {0x11066, 0x1106f}, {0x110f0, 0x110f9}, {0x11136, 0x1113f}, {0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x114d0, 0x114d9}, {0x11650, 0x11659}, {0x116c0, 0x116c9}, {0x11730, 0x11739}, {0x118e0, 0x118e9}, {0x16a60, 0x16a69}, {0x16b50, 0x16b59}, {0x1d7ce, 0x1d7ff} #endif }; #define NUM_DIGIT_RANGE (sizeof(digitRangeTable)/sizeof(crange)) /* * no singletons of digit characters. */ /* * Unicode: punctuation characters. */ static const crange punctRangeTable[] = { {0x21, 0x23}, {0x25, 0x2a}, {0x2c, 0x2f}, {0x5b, 0x5d}, {0x55a, 0x55f}, {0x66a, 0x66d}, {0x700, 0x70d}, {0x7f7, 0x7f9}, {0x830, 0x83e}, {0xf04, 0xf12}, {0xf3a, 0xf3d}, {0xfd0, 0xfd4}, {0x104a, 0x104f}, {0x1360, 0x1368}, {0x16eb, 0x16ed}, {0x17d4, 0x17d6}, {0x17d8, 0x17da}, {0x1800, 0x180a}, {0x1aa0, 0x1aa6}, {0x1aa8, 0x1aad}, {0x1b5a, 0x1b60}, {0x1bfc, 0x1bff}, {0x1c3b, 0x1c3f}, {0x1cc0, 0x1cc7}, {0x2010, 0x2027}, {0x2030, 0x2043}, {0x2045, 0x2051}, {0x2053, 0x205e}, {0x2308, 0x230b}, {0x2768, 0x2775}, {0x27e6, 0x27ef}, {0x2983, 0x2998}, {0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e42}, {0x3001, 0x3003}, {0x3008, 0x3011}, {0x3014, 0x301f}, {0xa60d, 0xa60f}, {0xa6f2, 0xa6f7}, {0xa874, 0xa877}, {0xa8f8, 0xa8fa}, {0xa9c1, 0xa9cd}, {0xaa5c, 0xaa5f}, {0xfe10, 0xfe19}, {0xfe30, 0xfe52}, {0xfe54, 0xfe61}, {0xff01, 0xff03}, {0xff05, 0xff0a}, {0xff0c, 0xff0f}, {0xff3b, 0xff3d}, {0xff5f, 0xff65} #if TCL_UTF_MAX > 4 ,{0x10100, 0x10102}, {0x10a50, 0x10a58}, {0x10af0, 0x10af6}, {0x10b39, 0x10b3f}, {0x10b99, 0x10b9c}, {0x11047, 0x1104d}, {0x110be, 0x110c1}, {0x11140, 0x11143}, {0x111c5, 0x111c9}, {0x111dd, 0x111df}, {0x11238, 0x1123d}, {0x115c1, 0x115d7}, {0x11641, 0x11643}, {0x1173c, 0x1173e}, {0x12470, 0x12474}, {0x16b37, 0x16b3b}, {0x1da87, 0x1da8b} #endif }; #define NUM_PUNCT_RANGE (sizeof(punctRangeTable)/sizeof(crange)) static const chr punctCharTable[] = { 0x3a, 0x3b, 0x3f, 0x40, 0x5f, 0x7b, 0x7d, 0xa1, 0xa7, 0xab, 0xb6, 0xb7, 0xbb, 0xbf, 0x37e, 0x387, 0x589, 0x58a, 0x5be, 0x5c0, 0x5c3, 0x5c6, 0x5f3, 0x5f4, 0x609, 0x60a, 0x60c, 0x60d, 0x61b, 0x61e, 0x61f, 0x6d4, 0x85e, 0x964, 0x965, 0x970, 0xaf0, 0xdf4, 0xe4f, 0xe5a, 0xe5b, 0xf14, 0xf85, 0xfd9, 0xfda, 0x10fb, 0x1400, 0x166d, 0x166e, 0x169b, 0x169c, 0x1735, 0x1736, 0x1944, 0x1945, 0x1a1e, 0x1a1f, 0x1c7e, 0x1c7f, 0x1cd3, 0x207d, 0x207e, 0x208d, 0x208e, 0x2329, 0x232a, 0x27c5, 0x27c6, 0x29fc, 0x29fd, 0x2cfe, 0x2cff, 0x2d70, 0x3030, 0x303d, 0x30a0, 0x30fb, 0xa4fe, 0xa4ff, 0xa673, 0xa67e, 0xa8ce, 0xa8cf, 0xa8fc, 0xa92e, 0xa92f, 0xa95f, 0xa9de, 0xa9df, 0xaade, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f, 0xfe63, 0xfe68, 0xfe6a, 0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f, 0xff5b, 0xff5d #if TCL_UTF_MAX > 4 ,0x1039f, 0x103d0, 0x1056f, 0x10857, 0x1091f, 0x1093f, 0x10a7f, 0x110bb, 0x110bc, 0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x114c6, 0x16a6e, 0x16a6f, 0x16af5, 0x16b44, 0x1bc9f #endif }; #define NUM_PUNCT_CHAR (sizeof(punctCharTable)/sizeof(chr)) /* * Unicode: white space characters. */ static const crange spaceRangeTable[] = { {0x9, 0xd}, {0x2000, 0x200b} }; #define NUM_SPACE_RANGE (sizeof(spaceRangeTable)/sizeof(crange)) static const chr spaceCharTable[] = { 0x20, 0x85, 0xa0, 0x1680, 0x180e, 0x2028, 0x2029, 0x202f, 0x205f, 0x2060, 0x3000, 0xfeff }; #define NUM_SPACE_CHAR (sizeof(spaceCharTable)/sizeof(chr)) /* * Unicode: lowercase characters. */ static const crange lowerRangeTable[] = { {0x61, 0x7a}, {0xdf, 0xf6}, {0xf8, 0xff}, {0x17e, 0x180}, {0x199, 0x19b}, {0x1bd, 0x1bf}, {0x233, 0x239}, {0x24f, 0x293}, {0x295, 0x2af}, {0x37b, 0x37d}, {0x3ac, 0x3ce}, {0x3d5, 0x3d7}, {0x3ef, 0x3f3}, {0x430, 0x45f}, {0x561, 0x587}, {0x13f8, 0x13fd}, {0x1d00, 0x1d2b}, {0x1d6b, 0x1d77}, {0x1d79, 0x1d9a}, {0x1e95, 0x1e9d}, {0x1eff, 0x1f07}, {0x1f10, 0x1f15}, {0x1f20, 0x1f27}, {0x1f30, 0x1f37}, {0x1f40, 0x1f45}, {0x1f50, 0x1f57}, {0x1f60, 0x1f67}, {0x1f70, 0x1f7d}, {0x1f80, 0x1f87}, {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7}, {0x1fb0, 0x1fb4}, {0x1fc2, 0x1fc4}, {0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7}, {0x1ff2, 0x1ff4}, {0x2146, 0x2149}, {0x2c30, 0x2c5e}, {0x2c76, 0x2c7b}, {0x2d00, 0x2d25}, {0xa72f, 0xa731}, {0xa771, 0xa778}, {0xa793, 0xa795}, {0xab30, 0xab5a}, {0xab60, 0xab65}, {0xab70, 0xabbf}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xff41, 0xff5a} #if TCL_UTF_MAX > 4 ,{0x10428, 0x1044f}, {0x10cc0, 0x10cf2}, {0x118c0, 0x118df}, {0x1d41a, 0x1d433}, {0x1d44e, 0x1d454}, {0x1d456, 0x1d467}, {0x1d482, 0x1d49b}, {0x1d4b6, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf}, {0x1d4ea, 0x1d503}, {0x1d51e, 0x1d537}, {0x1d552, 0x1d56b}, {0x1d586, 0x1d59f}, {0x1d5ba, 0x1d5d3}, {0x1d5ee, 0x1d607}, {0x1d622, 0x1d63b}, {0x1d656, 0x1d66f}, {0x1d68a, 0x1d6a5}, {0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6e1}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d71b}, {0x1d736, 0x1d74e}, {0x1d750, 0x1d755}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d78f}, {0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9} #endif }; #define NUM_LOWER_RANGE (sizeof(lowerRangeTable)/sizeof(crange)) static const chr lowerCharTable[] = { 0xb5, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10b, 0x10d, 0x10f, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11b, 0x11d, 0x11f, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x133, 0x135, 0x137, 0x138, 0x13a, 0x13c, 0x13e, 0x140, 0x142, 0x144, 0x146, 0x148, 0x149, 0x14b, 0x14d, 0x14f, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15b, 0x15d, 0x15f, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16b, 0x16d, 0x16f, 0x171, 0x173, 0x175, 0x177, 0x17a, 0x17c, 0x183, 0x185, 0x188, 0x18c, 0x18d, 0x192, 0x195, 0x19e, 0x1a1, 0x1a3, 0x1a5, 0x1a8, 0x1aa, 0x1ab, 0x1ad, 0x1b0, 0x1b4, 0x1b6, 0x1b9, 0x1ba, 0x1c6, 0x1c9, 0x1cc, 0x1ce, 0x1d0, 0x1d2, 0x1d4, 0x1d6, 0x1d8, 0x1da, 0x1dc, 0x1dd, 0x1df, 0x1e1, 0x1e3, 0x1e5, 0x1e7, 0x1e9, 0x1eb, 0x1ed, 0x1ef, 0x1f0, 0x1f3, 0x1f5, 0x1f9, 0x1fb, 0x1fd, 0x1ff, 0x201, 0x203, 0x205, 0x207, 0x209, 0x20b, 0x20d, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21b, 0x21d, 0x21f, 0x221, 0x223, 0x225, 0x227, 0x229, 0x22b, 0x22d, 0x22f, 0x231, 0x23c, 0x23f, 0x240, 0x242, 0x247, 0x249, 0x24b, 0x24d, 0x371, 0x373, 0x377, 0x390, 0x3d0, 0x3d1, 0x3d9, 0x3db, 0x3dd, 0x3df, 0x3e1, 0x3e3, 0x3e5, 0x3e7, 0x3e9, 0x3eb, 0x3ed, 0x3f5, 0x3f8, 0x3fb, 0x3fc, 0x461, 0x463, 0x465, 0x467, 0x469, 0x46b, 0x46d, 0x46f, 0x471, 0x473, 0x475, 0x477, 0x479, 0x47b, 0x47d, 0x47f, 0x481, 0x48b, 0x48d, 0x48f, 0x491, 0x493, 0x495, 0x497, 0x499, 0x49b, 0x49d, 0x49f, 0x4a1, 0x4a3, 0x4a5, 0x4a7, 0x4a9, 0x4ab, 0x4ad, 0x4af, 0x4b1, 0x4b3, 0x4b5, 0x4b7, 0x4b9, 0x4bb, 0x4bd, 0x4bf, 0x4c2, 0x4c4, 0x4c6, 0x4c8, 0x4ca, 0x4cc, 0x4ce, 0x4cf, 0x4d1, 0x4d3, 0x4d5, 0x4d7, 0x4d9, 0x4db, 0x4dd, 0x4df, 0x4e1, 0x4e3, 0x4e5, 0x4e7, 0x4e9, 0x4eb, 0x4ed, 0x4ef, 0x4f1, 0x4f3, 0x4f5, 0x4f7, 0x4f9, 0x4fb, 0x4fd, 0x4ff, 0x501, 0x503, 0x505, 0x507, 0x509, 0x50b, 0x50d, 0x50f, 0x511, 0x513, 0x515, 0x517, 0x519, 0x51b, 0x51d, 0x51f, 0x521, 0x523, 0x525, 0x527, 0x529, 0x52b, 0x52d, 0x52f, 0x1e01, 0x1e03, 0x1e05, 0x1e07, 0x1e09, 0x1e0b, 0x1e0d, 0x1e0f, 0x1e11, 0x1e13, 0x1e15, 0x1e17, 0x1e19, 0x1e1b, 0x1e1d, 0x1e1f, 0x1e21, 0x1e23, 0x1e25, 0x1e27, 0x1e29, 0x1e2b, 0x1e2d, 0x1e2f, 0x1e31, 0x1e33, 0x1e35, 0x1e37, 0x1e39, 0x1e3b, 0x1e3d, 0x1e3f, 0x1e41, 0x1e43, 0x1e45, 0x1e47, 0x1e49, 0x1e4b, 0x1e4d, 0x1e4f, 0x1e51, 0x1e53, 0x1e55, 0x1e57, 0x1e59, 0x1e5b, 0x1e5d, 0x1e5f, 0x1e61, 0x1e63, 0x1e65, 0x1e67, 0x1e69, 0x1e6b, 0x1e6d, 0x1e6f, 0x1e71, 0x1e73, 0x1e75, 0x1e77, 0x1e79, 0x1e7b, 0x1e7d, 0x1e7f, 0x1e81, 0x1e83, 0x1e85, 0x1e87, 0x1e89, 0x1e8b, 0x1e8d, 0x1e8f, 0x1e91, 0x1e93, 0x1e9f, 0x1ea1, 0x1ea3, 0x1ea5, 0x1ea7, 0x1ea9, 0x1eab, 0x1ead, 0x1eaf, 0x1eb1, 0x1eb3, 0x1eb5, 0x1eb7, 0x1eb9, 0x1ebb, 0x1ebd, 0x1ebf, 0x1ec1, 0x1ec3, 0x1ec5, 0x1ec7, 0x1ec9, 0x1ecb, 0x1ecd, 0x1ecf, 0x1ed1, 0x1ed3, 0x1ed5, 0x1ed7, 0x1ed9, 0x1edb, 0x1edd, 0x1edf, 0x1ee1, 0x1ee3, 0x1ee5, 0x1ee7, 0x1ee9, 0x1eeb, 0x1eed, 0x1eef, 0x1ef1, 0x1ef3, 0x1ef5, 0x1ef7, 0x1ef9, 0x1efb, 0x1efd, 0x1fb6, 0x1fb7, 0x1fbe, 0x1fc6, 0x1fc7, 0x1fd6, 0x1fd7, 0x1ff6, 0x1ff7, 0x210a, 0x210e, 0x210f, 0x2113, 0x212f, 0x2134, 0x2139, 0x213c, 0x213d, 0x214e, 0x2184, 0x2c61, 0x2c65, 0x2c66, 0x2c68, 0x2c6a, 0x2c6c, 0x2c71, 0x2c73, 0x2c74, 0x2c81, 0x2c83, 0x2c85, 0x2c87, 0x2c89, 0x2c8b, 0x2c8d, 0x2c8f, 0x2c91, 0x2c93, 0x2c95, 0x2c97, 0x2c99, 0x2c9b, 0x2c9d, 0x2c9f, 0x2ca1, 0x2ca3, 0x2ca5, 0x2ca7, 0x2ca9, 0x2cab, 0x2cad, 0x2caf, 0x2cb1, 0x2cb3, 0x2cb5, 0x2cb7, 0x2cb9, 0x2cbb, 0x2cbd, 0x2cbf, 0x2cc1, 0x2cc3, 0x2cc5, 0x2cc7, 0x2cc9, 0x2ccb, 0x2ccd, 0x2ccf, 0x2cd1, 0x2cd3, 0x2cd5, 0x2cd7, 0x2cd9, 0x2cdb, 0x2cdd, 0x2cdf, 0x2ce1, 0x2ce3, 0x2ce4, 0x2cec, 0x2cee, 0x2cf3, 0x2d27, 0x2d2d, 0xa641, 0xa643, 0xa645, 0xa647, 0xa649, 0xa64b, 0xa64d, 0xa64f, 0xa651, 0xa653, 0xa655, 0xa657, 0xa659, 0xa65b, 0xa65d, 0xa65f, 0xa661, 0xa663, 0xa665, 0xa667, 0xa669, 0xa66b, 0xa66d, 0xa681, 0xa683, 0xa685, 0xa687, 0xa689, 0xa68b, 0xa68d, 0xa68f, 0xa691, 0xa693, 0xa695, 0xa697, 0xa699, 0xa69b, 0xa723, 0xa725, 0xa727, 0xa729, 0xa72b, 0xa72d, 0xa733, 0xa735, 0xa737, 0xa739, 0xa73b, 0xa73d, 0xa73f, 0xa741, 0xa743, 0xa745, 0xa747, 0xa749, 0xa74b, 0xa74d, 0xa74f, 0xa751, 0xa753, 0xa755, 0xa757, 0xa759, 0xa75b, 0xa75d, 0xa75f, 0xa761, 0xa763, 0xa765, 0xa767, 0xa769, 0xa76b, 0xa76d, 0xa76f, 0xa77a, 0xa77c, 0xa77f, 0xa781, 0xa783, 0xa785, 0xa787, 0xa78c, 0xa78e, 0xa791, 0xa797, 0xa799, 0xa79b, 0xa79d, 0xa79f, 0xa7a1, 0xa7a3, 0xa7a5, 0xa7a7, 0xa7a9, 0xa7b5, 0xa7b7, 0xa7fa #if TCL_UTF_MAX > 4 ,0x1d4bb, 0x1d7cb #endif }; #define NUM_LOWER_CHAR (sizeof(lowerCharTable)/sizeof(chr)) /* * Unicode: uppercase characters. */ static const crange upperRangeTable[] = { {0x41, 0x5a}, {0xc0, 0xd6}, {0xd8, 0xde}, {0x189, 0x18b}, {0x18e, 0x191}, {0x196, 0x198}, {0x1b1, 0x1b3}, {0x1f6, 0x1f8}, {0x243, 0x246}, {0x388, 0x38a}, {0x391, 0x3a1}, {0x3a3, 0x3ab}, {0x3d2, 0x3d4}, {0x3fd, 0x42f}, {0x531, 0x556}, {0x10a0, 0x10c5}, {0x13a0, 0x13f5}, {0x1f08, 0x1f0f}, {0x1f18, 0x1f1d}, {0x1f28, 0x1f2f}, {0x1f38, 0x1f3f}, {0x1f48, 0x1f4d}, {0x1f68, 0x1f6f}, {0x1fb8, 0x1fbb}, {0x1fc8, 0x1fcb}, {0x1fd8, 0x1fdb}, {0x1fe8, 0x1fec}, {0x1ff8, 0x1ffb}, {0x210b, 0x210d}, {0x2110, 0x2112}, {0x2119, 0x211d}, {0x212a, 0x212d}, {0x2130, 0x2133}, {0x2c00, 0x2c2e}, {0x2c62, 0x2c64}, {0x2c6d, 0x2c70}, {0x2c7e, 0x2c80}, {0xa7aa, 0xa7ad}, {0xa7b0, 0xa7b4}, {0xff21, 0xff3a} #if TCL_UTF_MAX > 4 ,{0x10400, 0x10427}, {0x10c80, 0x10cb2}, {0x118a0, 0x118bf}, {0x1d400, 0x1d419}, {0x1d434, 0x1d44d}, {0x1d468, 0x1d481}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d56c, 0x1d585}, {0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed}, {0x1d608, 0x1d621}, {0x1d63c, 0x1d655}, {0x1d670, 0x1d689}, {0x1d6a8, 0x1d6c0}, {0x1d6e2, 0x1d6fa}, {0x1d71c, 0x1d734}, {0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8} #endif }; #define NUM_UPPER_RANGE (sizeof(upperRangeTable)/sizeof(crange)) static const chr upperCharTable[] = { 0x100, 0x102, 0x104, 0x106, 0x108, 0x10a, 0x10c, 0x10e, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11a, 0x11c, 0x11e, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12a, 0x12c, 0x12e, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13b, 0x13d, 0x13f, 0x141, 0x143, 0x145, 0x147, 0x14a, 0x14c, 0x14e, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15a, 0x15c, 0x15e, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16a, 0x16c, 0x16e, 0x170, 0x172, 0x174, 0x176, 0x178, 0x179, 0x17b, 0x17d, 0x181, 0x182, 0x184, 0x186, 0x187, 0x193, 0x194, 0x19c, 0x19d, 0x19f, 0x1a0, 0x1a2, 0x1a4, 0x1a6, 0x1a7, 0x1a9, 0x1ac, 0x1ae, 0x1af, 0x1b5, 0x1b7, 0x1b8, 0x1bc, 0x1c4, 0x1c7, 0x1ca, 0x1cd, 0x1cf, 0x1d1, 0x1d3, 0x1d5, 0x1d7, 0x1d9, 0x1db, 0x1de, 0x1e0, 0x1e2, 0x1e4, 0x1e6, 0x1e8, 0x1ea, 0x1ec, 0x1ee, 0x1f1, 0x1f4, 0x1fa, 0x1fc, 0x1fe, 0x200, 0x202, 0x204, 0x206, 0x208, 0x20a, 0x20c, 0x20e, 0x210, 0x212, 0x214, 0x216, 0x218, 0x21a, 0x21c, 0x21e, 0x220, 0x222, 0x224, 0x226, 0x228, 0x22a, 0x22c, 0x22e, 0x230, 0x232, 0x23a, 0x23b, 0x23d, 0x23e, 0x241, 0x248, 0x24a, 0x24c, 0x24e, 0x370, 0x372, 0x376, 0x37f, 0x386, 0x38c, 0x38e, 0x38f, 0x3cf, 0x3d8, 0x3da, 0x3dc, 0x3de, 0x3e0, 0x3e2, 0x3e4, 0x3e6, 0x3e8, 0x3ea, 0x3ec, 0x3ee, 0x3f4, 0x3f7, 0x3f9, 0x3fa, 0x460, 0x462, 0x464, 0x466, 0x468, 0x46a, 0x46c, 0x46e, 0x470, 0x472, 0x474, 0x476, 0x478, 0x47a, 0x47c, 0x47e, 0x480, 0x48a, 0x48c, 0x48e, 0x490, 0x492, 0x494, 0x496, 0x498, 0x49a, 0x49c, 0x49e, 0x4a0, 0x4a2, 0x4a4, 0x4a6, 0x4a8, 0x4aa, 0x4ac, 0x4ae, 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8, 0x4ba, 0x4bc, 0x4be, 0x4c0, 0x4c1, 0x4c3, 0x4c5, 0x4c7, 0x4c9, 0x4cb, 0x4cd, 0x4d0, 0x4d2, 0x4d4, 0x4d6, 0x4d8, 0x4da, 0x4dc, 0x4de, 0x4e0, 0x4e2, 0x4e4, 0x4e6, 0x4e8, 0x4ea, 0x4ec, 0x4ee, 0x4f0, 0x4f2, 0x4f4, 0x4f6, 0x4f8, 0x4fa, 0x4fc, 0x4fe, 0x500, 0x502, 0x504, 0x506, 0x508, 0x50a, 0x50c, 0x50e, 0x510, 0x512, 0x514, 0x516, 0x518, 0x51a, 0x51c, 0x51e, 0x520, 0x522, 0x524, 0x526, 0x528, 0x52a, 0x52c, 0x52e, 0x10c7, 0x10cd, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0a, 0x1e0c, 0x1e0e, 0x1e10, 0x1e12, 0x1e14, 0x1e16, 0x1e18, 0x1e1a, 0x1e1c, 0x1e1e, 0x1e20, 0x1e22, 0x1e24, 0x1e26, 0x1e28, 0x1e2a, 0x1e2c, 0x1e2e, 0x1e30, 0x1e32, 0x1e34, 0x1e36, 0x1e38, 0x1e3a, 0x1e3c, 0x1e3e, 0x1e40, 0x1e42, 0x1e44, 0x1e46, 0x1e48, 0x1e4a, 0x1e4c, 0x1e4e, 0x1e50, 0x1e52, 0x1e54, 0x1e56, 0x1e58, 0x1e5a, 0x1e5c, 0x1e5e, 0x1e60, 0x1e62, 0x1e64, 0x1e66, 0x1e68, 0x1e6a, 0x1e6c, 0x1e6e, 0x1e70, 0x1e72, 0x1e74, 0x1e76, 0x1e78, 0x1e7a, 0x1e7c, 0x1e7e, 0x1e80, 0x1e82, 0x1e84, 0x1e86, 0x1e88, 0x1e8a, 0x1e8c, 0x1e8e, 0x1e90, 0x1e92, 0x1e94, 0x1e9e, 0x1ea0, 0x1ea2, 0x1ea4, 0x1ea6, 0x1ea8, 0x1eaa, 0x1eac, 0x1eae, 0x1eb0, 0x1eb2, 0x1eb4, 0x1eb6, 0x1eb8, 0x1eba, 0x1ebc, 0x1ebe, 0x1ec0, 0x1ec2, 0x1ec4, 0x1ec6, 0x1ec8, 0x1eca, 0x1ecc, 0x1ece, 0x1ed0, 0x1ed2, 0x1ed4, 0x1ed6, 0x1ed8, 0x1eda, 0x1edc, 0x1ede, 0x1ee0, 0x1ee2, 0x1ee4, 0x1ee6, 0x1ee8, 0x1eea, 0x1eec, 0x1eee, 0x1ef0, 0x1ef2, 0x1ef4, 0x1ef6, 0x1ef8, 0x1efa, 0x1efc, 0x1efe, 0x1f59, 0x1f5b, 0x1f5d, 0x1f5f, 0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x213e, 0x213f, 0x2145, 0x2183, 0x2c60, 0x2c67, 0x2c69, 0x2c6b, 0x2c72, 0x2c75, 0x2c82, 0x2c84, 0x2c86, 0x2c88, 0x2c8a, 0x2c8c, 0x2c8e, 0x2c90, 0x2c92, 0x2c94, 0x2c96, 0x2c98, 0x2c9a, 0x2c9c, 0x2c9e, 0x2ca0, 0x2ca2, 0x2ca4, 0x2ca6, 0x2ca8, 0x2caa, 0x2cac, 0x2cae, 0x2cb0, 0x2cb2, 0x2cb4, 0x2cb6, 0x2cb8, 0x2cba, 0x2cbc, 0x2cbe, 0x2cc0, 0x2cc2, 0x2cc4, 0x2cc6, 0x2cc8, 0x2cca, 0x2ccc, 0x2cce, 0x2cd0, 0x2cd2, 0x2cd4, 0x2cd6, 0x2cd8, 0x2cda, 0x2cdc, 0x2cde, 0x2ce0, 0x2ce2, 0x2ceb, 0x2ced, 0x2cf2, 0xa640, 0xa642, 0xa644, 0xa646, 0xa648, 0xa64a, 0xa64c, 0xa64e, 0xa650, 0xa652, 0xa654, 0xa656, 0xa658, 0xa65a, 0xa65c, 0xa65e, 0xa660, 0xa662, 0xa664, 0xa666, 0xa668, 0xa66a, 0xa66c, 0xa680, 0xa682, 0xa684, 0xa686, 0xa688, 0xa68a, 0xa68c, 0xa68e, 0xa690, 0xa692, 0xa694, 0xa696, 0xa698, 0xa69a, 0xa722, 0xa724, 0xa726, 0xa728, 0xa72a, 0xa72c, 0xa72e, 0xa732, 0xa734, 0xa736, 0xa738, 0xa73a, 0xa73c, 0xa73e, 0xa740, 0xa742, 0xa744, 0xa746, 0xa748, 0xa74a, 0xa74c, 0xa74e, 0xa750, 0xa752, 0xa754, 0xa756, 0xa758, 0xa75a, 0xa75c, 0xa75e, 0xa760, 0xa762, 0xa764, 0xa766, 0xa768, 0xa76a, 0xa76c, 0xa76e, 0xa779, 0xa77b, 0xa77d, 0xa77e, 0xa780, 0xa782, 0xa784, 0xa786, 0xa78b, 0xa78d, 0xa790, 0xa792, 0xa796, 0xa798, 0xa79a, 0xa79c, 0xa79e, 0xa7a0, 0xa7a2, 0xa7a4, 0xa7a6, 0xa7a8, 0xa7b6 #if TCL_UTF_MAX > 4 ,0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d504, 0x1d505, 0x1d538, 0x1d539, 0x1d546, 0x1d7ca #endif }; #define NUM_UPPER_CHAR (sizeof(upperCharTable)/sizeof(chr)) /* * Unicode: unicode print characters excluding space. */ static const crange graphRangeTable[] = { {0x21, 0x7e}, {0xa1, 0xac}, {0xae, 0x377}, {0x37a, 0x37f}, {0x384, 0x38a}, {0x38e, 0x3a1}, {0x3a3, 0x52f}, {0x531, 0x556}, {0x559, 0x55f}, {0x561, 0x587}, {0x58d, 0x58f}, {0x591, 0x5c7}, {0x5d0, 0x5ea}, {0x5f0, 0x5f4}, {0x606, 0x61b}, {0x61e, 0x6dc}, {0x6de, 0x70d}, {0x710, 0x74a}, {0x74d, 0x7b1}, {0x7c0, 0x7fa}, {0x800, 0x82d}, {0x830, 0x83e}, {0x840, 0x85b}, {0x8a0, 0x8b4}, {0x8e3, 0x983}, {0x985, 0x98c}, {0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9bc, 0x9c4}, {0x9cb, 0x9ce}, {0x9df, 0x9e3}, {0x9e6, 0x9fb}, {0xa01, 0xa03}, {0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa3e, 0xa42}, {0xa4b, 0xa4d}, {0xa59, 0xa5c}, {0xa66, 0xa75}, {0xa81, 0xa83}, {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0}, {0xab5, 0xab9}, {0xabc, 0xac5}, {0xac7, 0xac9}, {0xacb, 0xacd}, {0xae0, 0xae3}, {0xae6, 0xaf1}, {0xb01, 0xb03}, {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39}, {0xb3c, 0xb44}, {0xb4b, 0xb4d}, {0xb5f, 0xb63}, {0xb66, 0xb77}, {0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, {0xbae, 0xbb9}, {0xbbe, 0xbc2}, {0xbc6, 0xbc8}, {0xbca, 0xbcd}, {0xbe6, 0xbfa}, {0xc00, 0xc03}, {0xc05, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39}, {0xc3d, 0xc44}, {0xc46, 0xc48}, {0xc4a, 0xc4d}, {0xc58, 0xc5a}, {0xc60, 0xc63}, {0xc66, 0xc6f}, {0xc78, 0xc7f}, {0xc81, 0xc83}, {0xc85, 0xc8c}, {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xcbc, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd}, {0xce0, 0xce3}, {0xce6, 0xcef}, {0xd01, 0xd03}, {0xd05, 0xd0c}, {0xd0e, 0xd10}, {0xd12, 0xd3a}, {0xd3d, 0xd44}, {0xd46, 0xd48}, {0xd4a, 0xd4e}, {0xd5f, 0xd63}, {0xd66, 0xd75}, {0xd79, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6}, {0xdcf, 0xdd4}, {0xdd8, 0xddf}, {0xde6, 0xdef}, {0xdf2, 0xdf4}, {0xe01, 0xe3a}, {0xe3f, 0xe5b}, {0xe94, 0xe97}, {0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb9}, {0xebb, 0xebd}, {0xec0, 0xec4}, {0xec8, 0xecd}, {0xed0, 0xed9}, {0xedc, 0xedf}, {0xf00, 0xf47}, {0xf49, 0xf6c}, {0xf71, 0xf97}, {0xf99, 0xfbc}, {0xfbe, 0xfcc}, {0xfce, 0xfda}, {0x1000, 0x10c5}, {0x10d0, 0x1248}, {0x124a, 0x124d}, {0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288}, {0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135a}, {0x135d, 0x137c}, {0x1380, 0x1399}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd}, {0x1400, 0x167f}, {0x1681, 0x169c}, {0x16a0, 0x16f8}, {0x1700, 0x170c}, {0x170e, 0x1714}, {0x1720, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17dd}, {0x17e0, 0x17e9}, {0x17f0, 0x17f9}, {0x1800, 0x180d}, {0x1810, 0x1819}, {0x1820, 0x1877}, {0x1880, 0x18aa}, {0x18b0, 0x18f5}, {0x1900, 0x191e}, {0x1920, 0x192b}, {0x1930, 0x193b}, {0x1944, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19b0, 0x19c9}, {0x19d0, 0x19da}, {0x19de, 0x1a1b}, {0x1a1e, 0x1a5e}, {0x1a60, 0x1a7c}, {0x1a7f, 0x1a89}, {0x1a90, 0x1a99}, {0x1aa0, 0x1aad}, {0x1ab0, 0x1abe}, {0x1b00, 0x1b4b}, {0x1b50, 0x1b7c}, {0x1b80, 0x1bf3}, {0x1bfc, 0x1c37}, {0x1c3b, 0x1c49}, {0x1c4d, 0x1c7f}, {0x1cc0, 0x1cc7}, {0x1cd0, 0x1cf6}, {0x1d00, 0x1df5}, {0x1dfc, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fc4}, {0x1fc6, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffe}, {0x2010, 0x2027}, {0x2030, 0x205e}, {0x2074, 0x208e}, {0x2090, 0x209c}, {0x20a0, 0x20be}, {0x20d0, 0x20f0}, {0x2100, 0x218b}, {0x2190, 0x23fa}, {0x2400, 0x2426}, {0x2440, 0x244a}, {0x2460, 0x2b73}, {0x2b76, 0x2b95}, {0x2b98, 0x2bb9}, {0x2bbd, 0x2bc8}, {0x2bca, 0x2bd1}, {0x2bec, 0x2bef}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2cf3}, {0x2cf9, 0x2d25}, {0x2d30, 0x2d67}, {0x2d7f, 0x2d96}, {0x2da0, 0x2da6}, {0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6}, {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e42}, {0x2e80, 0x2e99}, {0x2e9b, 0x2ef3}, {0x2f00, 0x2fd5}, {0x2ff0, 0x2ffb}, {0x3001, 0x303f}, {0x3041, 0x3096}, {0x3099, 0x30ff}, {0x3105, 0x312d}, {0x3131, 0x318e}, {0x3190, 0x31ba}, {0x31c0, 0x31e3}, {0x31f0, 0x321e}, {0x3220, 0x32fe}, {0x3300, 0x4db5}, {0x4dc0, 0x9fd5}, {0xa000, 0xa48c}, {0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa6f7}, {0xa700, 0xa7ad}, {0xa7b0, 0xa7b7}, {0xa7f7, 0xa82b}, {0xa830, 0xa839}, {0xa840, 0xa877}, {0xa880, 0xa8c4}, {0xa8ce, 0xa8d9}, {0xa8e0, 0xa8fd}, {0xa900, 0xa953}, {0xa95f, 0xa97c}, {0xa980, 0xa9cd}, {0xa9cf, 0xa9d9}, {0xa9de, 0xa9fe}, {0xaa00, 0xaa36}, {0xaa40, 0xaa4d}, {0xaa50, 0xaa59}, {0xaa5c, 0xaac2}, {0xaadb, 0xaaf6}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e}, {0xab30, 0xab65}, {0xab70, 0xabed}, {0xabf0, 0xabf9}, {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xdc00, 0xdc3e}, {0xdc40, 0xdc7e}, {0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe}, {0xdd00, 0xdd3e}, {0xdd40, 0xdd7e}, {0xdd80, 0xddbe}, {0xddc0, 0xddfe}, {0xde00, 0xde3e}, {0xde40, 0xde7e}, {0xde80, 0xdebe}, {0xdec0, 0xdefe}, {0xdf00, 0xdf3e}, {0xdf40, 0xdf7e}, {0xdf80, 0xdfbe}, {0xdfc0, 0xdffe}, {0xf900, 0xfa6d}, {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1d, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbc1}, {0xfbd3, 0xfd3f}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfd}, {0xfe00, 0xfe19}, {0xfe20, 0xfe52}, {0xfe54, 0xfe66}, {0xfe68, 0xfe6b}, {0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff01, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc}, {0xffe0, 0xffe6}, {0xffe8, 0xffee} #if TCL_UTF_MAX > 4 ,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d}, {0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10100, 0x10102}, {0x10107, 0x10133}, {0x10137, 0x1018c}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c}, {0x102a0, 0x102d0}, {0x102e0, 0x102fb}, {0x10300, 0x10323}, {0x10330, 0x1034a}, {0x10350, 0x1037a}, {0x10380, 0x1039d}, {0x1039f, 0x103c3}, {0x103c8, 0x103d5}, {0x10400, 0x1049d}, {0x104a0, 0x104a9}, {0x10500, 0x10527}, {0x10530, 0x10563}, {0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10857, 0x1089e}, {0x108a7, 0x108af}, {0x108e0, 0x108f2}, {0x108fb, 0x1091b}, {0x1091f, 0x10939}, {0x10980, 0x109b7}, {0x109bc, 0x109cf}, {0x109d2, 0x10a03}, {0x10a0c, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33}, {0x10a38, 0x10a3a}, {0x10a3f, 0x10a47}, {0x10a50, 0x10a58}, {0x10a60, 0x10a9f}, {0x10ac0, 0x10ae6}, {0x10aeb, 0x10af6}, {0x10b00, 0x10b35}, {0x10b39, 0x10b55}, {0x10b58, 0x10b72}, {0x10b78, 0x10b91}, {0x10b99, 0x10b9c}, {0x10ba9, 0x10baf}, {0x10c00, 0x10c48}, {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10cfa, 0x10cff}, {0x10e60, 0x10e7e}, {0x11000, 0x1104d}, {0x11052, 0x1106f}, {0x1107f, 0x110bc}, {0x110be, 0x110c1}, {0x110d0, 0x110e8}, {0x110f0, 0x110f9}, {0x11100, 0x11134}, {0x11136, 0x11143}, {0x11150, 0x11176}, {0x11180, 0x111cd}, {0x111d0, 0x111df}, {0x111e1, 0x111f4}, {0x11200, 0x11211}, {0x11213, 0x1123d}, {0x11280, 0x11286}, {0x1128a, 0x1128d}, {0x1128f, 0x1129d}, {0x1129f, 0x112a9}, {0x112b0, 0x112ea}, {0x112f0, 0x112f9}, {0x11300, 0x11303}, {0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339}, {0x1133c, 0x11344}, {0x1134b, 0x1134d}, {0x1135d, 0x11363}, {0x11366, 0x1136c}, {0x11370, 0x11374}, {0x11480, 0x114c7}, {0x114d0, 0x114d9}, {0x11580, 0x115b5}, {0x115b8, 0x115dd}, {0x11600, 0x11644}, {0x11650, 0x11659}, {0x11680, 0x116b7}, {0x116c0, 0x116c9}, {0x11700, 0x11719}, {0x1171d, 0x1172b}, {0x11730, 0x1173f}, {0x118a0, 0x118f2}, {0x11ac0, 0x11af8}, {0x12000, 0x12399}, {0x12400, 0x1246e}, {0x12470, 0x12474}, {0x12480, 0x12543}, {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e}, {0x16a60, 0x16a69}, {0x16ad0, 0x16aed}, {0x16af0, 0x16af5}, {0x16b00, 0x16b45}, {0x16b50, 0x16b59}, {0x16b5b, 0x16b61}, {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99}, {0x1bc9c, 0x1bc9f}, {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126}, {0x1d129, 0x1d172}, {0x1d17b, 0x1d1e8}, {0x1d200, 0x1d245}, {0x1d300, 0x1d356}, {0x1d360, 0x1d371}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb}, {0x1d7ce, 0x1da8b}, {0x1da9b, 0x1da9f}, {0x1daa1, 0x1daaf}, {0x1e800, 0x1e8c4}, {0x1e8c7, 0x1e8d6}, {0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b}, {0x1f030, 0x1f093}, {0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5}, {0x1f100, 0x1f10c}, {0x1f110, 0x1f12e}, {0x1f130, 0x1f16b}, {0x1f170, 0x1f19a}, {0x1f1e6, 0x1f202}, {0x1f210, 0x1f23a}, {0x1f240, 0x1f248}, {0x1f300, 0x1f579}, {0x1f57b, 0x1f5a3}, {0x1f5a5, 0x1f6d0}, {0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6f3}, {0x1f700, 0x1f773}, {0x1f780, 0x1f7d4}, {0x1f800, 0x1f80b}, {0x1f810, 0x1f847}, {0x1f850, 0x1f859}, {0x1f860, 0x1f887}, {0x1f890, 0x1f8ad}, {0x1f910, 0x1f918}, {0x1f980, 0x1f984}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef} #endif }; #define NUM_GRAPH_RANGE (sizeof(graphRangeTable)/sizeof(crange)) static const chr graphCharTable[] = { 0x38c, 0x589, 0x58a, 0x85e, 0x98f, 0x990, 0x9b2, 0x9c7, 0x9c8, 0x9d7, 0x9dc, 0x9dd, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36, 0xa38, 0xa39, 0xa3c, 0xa47, 0xa48, 0xa51, 0xa5e, 0xab2, 0xab3, 0xad0, 0xaf9, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb47, 0xb48, 0xb56, 0xb57, 0xb5c, 0xb5d, 0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4, 0xbd0, 0xbd7, 0xc55, 0xc56, 0xcd5, 0xcd6, 0xcde, 0xcf1, 0xcf2, 0xd57, 0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6, 0xe81, 0xe82, 0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940, 0x1cf8, 0x1cf9, 0x1f59, 0x1f5b, 0x1f5d, 0x2070, 0x2071, 0x2d27, 0x2d2d, 0x2d6f, 0x2d70, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc, 0xfffd #if TCL_UTF_MAX > 4 ,0x1003c, 0x1003d, 0x101a0, 0x1056f, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4, 0x108f5, 0x1093f, 0x10a05, 0x10a06, 0x11288, 0x1130f, 0x11310, 0x11332, 0x11333, 0x11347, 0x11348, 0x11350, 0x11357, 0x118ff, 0x16a6e, 0x16a6f, 0x1b000, 0x1b001, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e, 0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f9c0 #endif }; #define NUM_GRAPH_CHAR (sizeof(graphCharTable)/sizeof(chr)) /* * End of auto-generated Unicode character ranges declarations. */ #define CH NOCELT /* - element - map collating-element name to celt ^ static celt element(struct vars *, const chr *, const chr *); */ static celt element( struct vars *v, /* context */ const chr *startp, /* points to start of name */ const chr *endp) /* points just past end of name */ { const struct cname *cn; size_t len; Tcl_DString ds; const char *np; /* * Generic: one-chr names stand for themselves. */ assert(startp < endp); len = endp - startp; if (len == 1) { return *startp; } NOTE(REG_ULOCALE); /* * Search table. */ Tcl_DStringInit(&ds); np = Tcl_UniCharToUtfDString(startp, (int)len, &ds); for (cn=cnames; cn->name!=NULL; cn++) { if (strlen(cn->name)==len && strncmp(cn->name, np, len)==0) { break; /* NOTE BREAK OUT */ } } Tcl_DStringFree(&ds); if (cn->name != NULL) { return CHR(cn->code); } /* * Couldn't find it. */ ERR(REG_ECOLLATE); return 0; } /* - range - supply cvec for a range, including legality check ^ static struct cvec *range(struct vars *, celt, celt, int); */ static struct cvec * range( struct vars *v, /* context */ celt a, /* range start */ celt b, /* range end, might equal a */ int cases) /* case-independent? */ { int nchrs; struct cvec *cv; celt c, lc, uc, tc; if (a != b && !before(a, b)) { ERR(REG_ERANGE); return NULL; } if (!cases) { /* easy version */ cv = getcvec(v, 0, 1); NOERRN(); addrange(cv, a, b); return cv; } /* * When case-independent, it's hard to decide when cvec ranges are usable, * so for now at least, we won't try. We allocate enough space for two * case variants plus a little extra for the two title case variants. */ nchrs = (b - a + 1)*2 + 4; cv = getcvec(v, nchrs, 0); NOERRN(); for (c=a; c<=b; c++) { addchr(cv, c); lc = Tcl_UniCharToLower((chr)c); uc = Tcl_UniCharToUpper((chr)c); tc = Tcl_UniCharToTitle((chr)c); if (c != lc) { addchr(cv, lc); } if (c != uc) { addchr(cv, uc); } if (c != tc && tc != uc) { addchr(cv, tc); } } return cv; } /* - before - is celt x before celt y, for purposes of range legality? ^ static int before(celt, celt); */ static int /* predicate */ before( celt x, celt y) /* collating elements */ { if (x < y) { return 1; } return 0; } /* - eclass - supply cvec for an equivalence class * Must include case counterparts on request. ^ static struct cvec *eclass(struct vars *, celt, int); */ static struct cvec * eclass( struct vars *v, /* context */ celt c, /* Collating element representing the * equivalence class. */ int cases) /* all cases? */ { struct cvec *cv; /* * Crude fake equivalence class for testing. */ if ((v->cflags®_FAKE) && c == 'x') { cv = getcvec(v, 4, 0); addchr(cv, (chr)'x'); addchr(cv, (chr)'y'); if (cases) { addchr(cv, (chr)'X'); addchr(cv, (chr)'Y'); } return cv; } /* * Otherwise, none. */ if (cases) { return allcases(v, c); } cv = getcvec(v, 1, 0); assert(cv != NULL); addchr(cv, (chr)c); return cv; } /* - cclass - supply cvec for a character class * Must include case counterparts on request. ^ static struct cvec *cclass(struct vars *, const chr *, const chr *, int); */ static struct cvec * cclass( struct vars *v, /* context */ const chr *startp, /* where the name starts */ const chr *endp, /* just past the end of the name */ int cases) /* case-independent? */ { size_t len; struct cvec *cv = NULL; Tcl_DString ds; const char *np; const char *const *namePtr; int i, index; /* * The following arrays define the valid character class names. */ static const char *const classNames[] = { "alnum", "alpha", "ascii", "blank", "cntrl", "digit", "graph", "lower", "print", "punct", "space", "upper", "xdigit", NULL }; enum classes { CC_ALNUM, CC_ALPHA, CC_ASCII, CC_BLANK, CC_CNTRL, CC_DIGIT, CC_GRAPH, CC_LOWER, CC_PRINT, CC_PUNCT, CC_SPACE, CC_UPPER, CC_XDIGIT }; /* * Extract the class name */ len = endp - startp; Tcl_DStringInit(&ds); np = Tcl_UniCharToUtfDString(startp, (int)len, &ds); /* * Map the name to the corresponding enumerated value. */ index = -1; for (namePtr=classNames,i=0 ; *namePtr!=NULL ; namePtr++,i++) { if ((strlen(*namePtr) == len) && (strncmp(*namePtr, np, len) == 0)) { index = i; break; } } Tcl_DStringFree(&ds); if (index == -1) { ERR(REG_ECTYPE); return NULL; } /* * Remap lower and upper to alpha if the match is case insensitive. */ if (cases && ((index == CC_LOWER) || (index == CC_UPPER))) { index = CC_ALNUM; } /* * Now compute the character class contents. */ switch((enum classes) index) { case CC_ALNUM: cv = getcvec(v, NUM_ALPHA_CHAR, NUM_DIGIT_RANGE + NUM_ALPHA_RANGE); if (cv) { for (i=0 ; (size_t)i 0; len--, x++, y++) { if ((*x!=*y) && (Tcl_UniCharToLower(*x) != Tcl_UniCharToLower(*y))) { return 1; } } return 0; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclInt.h0000644000175000017500000055726512663660065014635 0ustar sergeisergei/* * tclInt.h -- * * Declarations of things used internally by the Tcl interpreter. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1993-1997 Lucent Technologies. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2007 Daniel A. Steffen * Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved. * Copyright (c) 2008 by Miguel Sofer. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLINT #define _TCLINT /* * Some numerics configuration options. */ #undef ACCEPT_NAN /* * Common include files needed by most of the Tcl source files are included * here, so that system-dependent personalizations for the include files only * have to be made in once place. This results in a few extra includes, but * greater modularity. The order of the three groups of #includes is * important. For example, stdio.h is needed by tcl.h. */ #include "tclPort.h" #include #include #ifdef NO_STDLIB_H # include "../compat/stdlib.h" #else # include #endif #ifdef NO_STRING_H #include "../compat/string.h" #else #include #endif #ifdef STDC_HEADERS #include #else typedef int ptrdiff_t; #endif /* * Ensure WORDS_BIGENDIAN is defined correctly: * Needs to happen here in addition to configure to work with fat compiles on * Darwin (where configure runs only once for multiple architectures). */ #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef BYTE_ORDER # ifdef BIG_ENDIAN # if BYTE_ORDER == BIG_ENDIAN # undef WORDS_BIGENDIAN # define WORDS_BIGENDIAN 1 # endif # endif # ifdef LITTLE_ENDIAN # if BYTE_ORDER == LITTLE_ENDIAN # undef WORDS_BIGENDIAN # endif # endif #endif /* * Used to tag functions that are only to be visible within the module being * built and not outside it (where this is supported by the linker). */ #ifndef MODULE_SCOPE # ifdef __cplusplus # define MODULE_SCOPE extern "C" # else # define MODULE_SCOPE extern # endif #endif /* * Macros used to cast between pointers and integers (e.g. when storing an int * in ClientData), on 64-bit architectures they avoid gcc warning about "cast * to/from pointer from/to integer of different size". */ #if !defined(INT2PTR) && !defined(PTR2INT) # if defined(HAVE_INTPTR_T) || defined(intptr_t) # define INT2PTR(p) ((void *)(intptr_t)(p)) # define PTR2INT(p) ((int)(intptr_t)(p)) # else # define INT2PTR(p) ((void *)(p)) # define PTR2INT(p) ((int)(p)) # endif #endif #if !defined(UINT2PTR) && !defined(PTR2UINT) # if defined(HAVE_UINTPTR_T) || defined(uintptr_t) # define UINT2PTR(p) ((void *)(uintptr_t)(p)) # define PTR2UINT(p) ((unsigned int)(uintptr_t)(p)) # else # define UINT2PTR(p) ((void *)(p)) # define PTR2UINT(p) ((unsigned int)(p)) # endif #endif #if defined(_WIN32) && defined(_MSC_VER) # define vsnprintf _vsnprintf #endif /* * The following procedures allow namespaces to be customized to support * special name resolution rules for commands/variables. */ struct Tcl_ResolvedVarInfo; typedef Tcl_Var (Tcl_ResolveRuntimeVarProc)(Tcl_Interp *interp, struct Tcl_ResolvedVarInfo *vinfoPtr); typedef void (Tcl_ResolveVarDeleteProc)(struct Tcl_ResolvedVarInfo *vinfoPtr); /* * The following structure encapsulates the routines needed to resolve a * variable reference at runtime. Any variable specific state will typically * be appended to this structure. */ typedef struct Tcl_ResolvedVarInfo { Tcl_ResolveRuntimeVarProc *fetchProc; Tcl_ResolveVarDeleteProc *deleteProc; } Tcl_ResolvedVarInfo; typedef int (Tcl_ResolveCompiledVarProc)(Tcl_Interp *interp, CONST84 char *name, int length, Tcl_Namespace *context, Tcl_ResolvedVarInfo **rPtr); typedef int (Tcl_ResolveVarProc)(Tcl_Interp *interp, CONST84 char *name, Tcl_Namespace *context, int flags, Tcl_Var *rPtr); typedef int (Tcl_ResolveCmdProc)(Tcl_Interp *interp, CONST84 char *name, Tcl_Namespace *context, int flags, Tcl_Command *rPtr); typedef struct Tcl_ResolverInfo { Tcl_ResolveCmdProc *cmdResProc; /* Procedure handling command name * resolution. */ Tcl_ResolveVarProc *varResProc; /* Procedure handling variable name resolution * for variables that can only be handled at * runtime. */ Tcl_ResolveCompiledVarProc *compiledVarResProc; /* Procedure handling variable name resolution * at compile time. */ } Tcl_ResolverInfo; /* *---------------------------------------------------------------- * Data structures related to namespaces. *---------------------------------------------------------------- */ typedef struct Tcl_Ensemble Tcl_Ensemble; typedef struct NamespacePathEntry NamespacePathEntry; /* * Special hashtable for variables: this is just a Tcl_HashTable with an nsPtr * field added at the end: in this way variables can find their namespace * without having to copy a pointer in their struct: they can access it via * their hPtr->tablePtr. */ typedef struct TclVarHashTable { Tcl_HashTable table; struct Namespace *nsPtr; } TclVarHashTable; /* * This is for itcl - it likes to search our varTables directly :( */ #define TclVarHashFindVar(tablePtr, key) \ TclVarHashCreateVar((tablePtr), (key), NULL) /* * Define this to reduce the amount of space that the average namespace * consumes by only allocating the table of child namespaces when necessary. * Defining it breaks compatibility for Tcl extensions (e.g., itcl) which * reach directly into the Namespace structure. */ #undef BREAK_NAMESPACE_COMPAT /* * The structure below defines a namespace. * Note: the first five fields must match exactly the fields in a * Tcl_Namespace structure (see tcl.h). If you change one, be sure to change * the other. */ typedef struct Namespace { char *name; /* The namespace's simple (unqualified) name. * This contains no ::'s. The name of the * global namespace is "" although "::" is an * synonym. */ char *fullName; /* The namespace's fully qualified name. This * starts with ::. */ ClientData clientData; /* An arbitrary value associated with this * namespace. */ Tcl_NamespaceDeleteProc *deleteProc; /* Procedure invoked when deleting the * namespace to, e.g., free clientData. */ struct Namespace *parentPtr;/* Points to the namespace that contains this * one. NULL if this is the global * namespace. */ #ifndef BREAK_NAMESPACE_COMPAT Tcl_HashTable childTable; /* Contains any child namespaces. Indexed by * strings; values have type (Namespace *). */ #else Tcl_HashTable *childTablePtr; /* Contains any child namespaces. Indexed by * strings; values have type (Namespace *). If * NULL, there are no children. */ #endif long nsId; /* Unique id for the namespace. */ Tcl_Interp *interp; /* The interpreter containing this * namespace. */ int flags; /* OR-ed combination of the namespace status * flags NS_DYING and NS_DEAD listed below. */ int activationCount; /* Number of "activations" or active call * frames for this namespace that are on the * Tcl call stack. The namespace won't be * freed until activationCount becomes zero. */ int refCount; /* Count of references by namespaceName * objects. The namespace can't be freed until * refCount becomes zero. */ Tcl_HashTable cmdTable; /* Contains all the commands currently * registered in the namespace. Indexed by * strings; values have type (Command *). * Commands imported by Tcl_Import have * Command structures that point (via an * ImportedCmdRef structure) to the Command * structure in the source namespace's command * table. */ TclVarHashTable varTable; /* Contains all the (global) variables * currently in this namespace. Indexed by * strings; values have type (Var *). */ char **exportArrayPtr; /* Points to an array of string patterns * specifying which commands are exported. A * pattern may include "string match" style * wildcard characters to specify multiple * commands; however, no namespace qualifiers * are allowed. NULL if no export patterns are * registered. */ int numExportPatterns; /* Number of export patterns currently * registered using "namespace export". */ int maxExportPatterns; /* Mumber of export patterns for which space * is currently allocated. */ int cmdRefEpoch; /* Incremented if a newly added command * shadows a command for which this namespace * has already cached a Command* pointer; this * causes all its cached Command* pointers to * be invalidated. */ int resolverEpoch; /* Incremented whenever (a) the name * resolution rules change for this namespace * or (b) a newly added command shadows a * command that is compiled to bytecodes. This * invalidates all byte codes compiled in the * namespace, causing the code to be * recompiled under the new rules.*/ Tcl_ResolveCmdProc *cmdResProc; /* If non-null, this procedure overrides the * usual command resolution mechanism in Tcl. * This procedure is invoked within * Tcl_FindCommand to resolve all command * references within the namespace. */ Tcl_ResolveVarProc *varResProc; /* If non-null, this procedure overrides the * usual variable resolution mechanism in Tcl. * This procedure is invoked within * Tcl_FindNamespaceVar to resolve all * variable references within the namespace at * runtime. */ Tcl_ResolveCompiledVarProc *compiledVarResProc; /* If non-null, this procedure overrides the * usual variable resolution mechanism in Tcl. * This procedure is invoked within * LookupCompiledLocal to resolve variable * references within the namespace at compile * time. */ int exportLookupEpoch; /* Incremented whenever a command is added to * a namespace, removed from a namespace or * the exports of a namespace are changed. * Allows TIP#112-driven command lists to be * validated efficiently. */ Tcl_Ensemble *ensembles; /* List of structures that contain the details * of the ensembles that are implemented on * top of this namespace. */ Tcl_Obj *unknownHandlerPtr; /* A script fragment to be used when command * resolution in this namespace fails. TIP * 181. */ int commandPathLength; /* The length of the explicit path. */ NamespacePathEntry *commandPathArray; /* The explicit path of the namespace as an * array. */ NamespacePathEntry *commandPathSourceList; /* Linked list of path entries that point to * this namespace. */ Tcl_NamespaceDeleteProc *earlyDeleteProc; /* Just like the deleteProc field (and called * with the same clientData) but called at the * start of the deletion process, so there is * a chance for code to do stuff inside the * namespace before deletion completes. */ } Namespace; /* * An entry on a namespace's command resolution path. */ struct NamespacePathEntry { Namespace *nsPtr; /* What does this path entry point to? If it * is NULL, this path entry points is * redundant and should be skipped. */ Namespace *creatorNsPtr; /* Where does this path entry point from? This * allows for efficient invalidation of * references when the path entry's target * updates its current list of defined * commands. */ NamespacePathEntry *prevPtr, *nextPtr; /* Linked list pointers or NULL at either end * of the list that hangs off Namespace's * commandPathSourceList field. */ }; /* * Flags used to represent the status of a namespace: * * NS_DYING - 1 means Tcl_DeleteNamespace has been called to delete the * namespace but there are still active call frames on the Tcl * stack that refer to the namespace. When the last call frame * referring to it has been popped, it's variables and command * will be destroyed and it will be marked "dead" (NS_DEAD). The * namespace can no longer be looked up by name. * NS_DEAD - 1 means Tcl_DeleteNamespace has been called to delete the * namespace and no call frames still refer to it. Its variables * and command have already been destroyed. This bit allows the * namespace resolution code to recognize that the namespace is * "deleted". When the last namespaceName object in any byte code * unit that refers to the namespace has been freed (i.e., when * the namespace's refCount is 0), the namespace's storage will * be freed. * NS_KILLED - 1 means that TclTeardownNamespace has already been called on * this namespace and it should not be called again [Bug 1355942] * NS_SUPPRESS_COMPILATION - * Marks the commands in this namespace for not being compiled, * forcing them to be looked up every time. */ #define NS_DYING 0x01 #define NS_DEAD 0x02 #define NS_KILLED 0x04 #define NS_SUPPRESS_COMPILATION 0x08 /* * Flags passed to TclGetNamespaceForQualName: * * TCL_GLOBAL_ONLY - (see tcl.h) Look only in the global ns. * TCL_NAMESPACE_ONLY - (see tcl.h) Look only in the context ns. * TCL_CREATE_NS_IF_UNKNOWN - Create unknown namespaces. * TCL_FIND_ONLY_NS - The name sought is a namespace name. */ #define TCL_CREATE_NS_IF_UNKNOWN 0x800 #define TCL_FIND_ONLY_NS 0x1000 /* * The data cached in an ensemble subcommand's Tcl_Obj rep (reference in * twoPtrValue.ptr1 field). This structure is not shared between Tcl_Objs * referring to the same subcommand, even where one is a duplicate of another. */ typedef struct { Namespace *nsPtr; /* The namespace backing the ensemble which * this is a subcommand of. */ int epoch; /* Used to confirm when the data in this * really structure matches up with the * ensemble. */ Tcl_Command token; /* Reference to the comamnd for which this * structure is a cache of the resolution. */ char *fullSubcmdName; /* The full (local) name of the subcommand, * allocated with ckalloc(). */ Tcl_Obj *realPrefixObj; /* Object containing the prefix words of the * command that implements this ensemble * subcommand. */ } EnsembleCmdRep; /* * The client data for an ensemble command. This consists of the table of * commands that are actually exported by the namespace, and an epoch counter * that, combined with the exportLookupEpoch field of the namespace structure, * defines whether the table contains valid data or will need to be recomputed * next time the ensemble command is called. */ typedef struct EnsembleConfig { Namespace *nsPtr; /* The namspace backing this ensemble up. */ Tcl_Command token; /* The token for the command that provides * ensemble support for the namespace, or NULL * if the command has been deleted (or never * existed; the global namespace never has an * ensemble command.) */ int epoch; /* The epoch at which this ensemble's table of * exported commands is valid. */ char **subcommandArrayPtr; /* Array of ensemble subcommand names. At all * consistent points, this will have the same * number of entries as there are entries in * the subcommandTable hash. */ Tcl_HashTable subcommandTable; /* Hash table of ensemble subcommand names, * which are its keys so this also provides * the storage management for those subcommand * names. The contents of the entry values are * object version the prefix lists to use when * substituting for the command/subcommand to * build the ensemble implementation command. * Has to be stored here as well as in * subcommandDict because that field is NULL * when we are deriving the ensemble from the * namespace exports list. FUTURE WORK: use * object hash table here. */ struct EnsembleConfig *next;/* The next ensemble in the linked list of * ensembles associated with a namespace. If * this field points to this ensemble, the * structure has already been unlinked from * all lists, and cannot be found by scanning * the list from the namespace's ensemble * field. */ int flags; /* ORed combo of TCL_ENSEMBLE_PREFIX, * ENSEMBLE_DEAD and ENSEMBLE_COMPILE. */ /* OBJECT FIELDS FOR ENSEMBLE CONFIGURATION */ Tcl_Obj *subcommandDict; /* Dictionary providing mapping from * subcommands to their implementing command * prefixes, or NULL if we are to build the * map automatically from the namespace * exports. */ Tcl_Obj *subcmdList; /* List of commands that this ensemble * actually provides, and whose implementation * will be built using the subcommandDict (if * present and defined) and by simple mapping * to the namespace otherwise. If NULL, * indicates that we are using the (dynamic) * list of currently exported commands. */ Tcl_Obj *unknownHandler; /* Script prefix used to handle the case when * no match is found (according to the rule * defined by flag bit TCL_ENSEMBLE_PREFIX) or * NULL to use the default error-generating * behaviour. The script execution gets all * the arguments to the ensemble command * (including objv[0]) and will have the * results passed directly back to the caller * (including the error code) unless the code * is TCL_CONTINUE in which case the * subcommand will be reparsed by the ensemble * core, presumably because the ensemble * itself has been updated. */ Tcl_Obj *parameterList; /* List of ensemble parameter names. */ int numParameters; /* Cached number of parameters. This is either * 0 (if the parameterList field is NULL) or * the length of the list in the parameterList * field. */ } EnsembleConfig; /* * Various bits for the EnsembleConfig.flags field. */ #define ENSEMBLE_DEAD 0x1 /* Flag value to say that the ensemble is dead * and on its way out. */ #define ENSEMBLE_COMPILE 0x4 /* Flag to enable bytecode compilation of an * ensemble. */ /* *---------------------------------------------------------------- * Data structures related to variables. These are used primarily in tclVar.c *---------------------------------------------------------------- */ /* * The following structure defines a variable trace, which is used to invoke a * specific C procedure whenever certain operations are performed on a * variable. */ typedef struct VarTrace { Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given by * flags are performed on variable. */ ClientData clientData; /* Argument to pass to proc. */ int flags; /* What events the trace procedure is * interested in: OR-ed combination of * TCL_TRACE_READS, TCL_TRACE_WRITES, * TCL_TRACE_UNSETS and TCL_TRACE_ARRAY. */ struct VarTrace *nextPtr; /* Next in list of traces associated with a * particular variable. */ } VarTrace; /* * The following structure defines a command trace, which is used to invoke a * specific C procedure whenever certain operations are performed on a * command. */ typedef struct CommandTrace { Tcl_CommandTraceProc *traceProc; /* Procedure to call when operations given by * flags are performed on command. */ ClientData clientData; /* Argument to pass to proc. */ int flags; /* What events the trace procedure is * interested in: OR-ed combination of * TCL_TRACE_RENAME, TCL_TRACE_DELETE. */ struct CommandTrace *nextPtr; /* Next in list of traces associated with a * particular command. */ int refCount; /* Used to ensure this structure is not * deleted too early. Keeps track of how many * pieces of code have a pointer to this * structure. */ } CommandTrace; /* * When a command trace is active (i.e. its associated procedure is executing) * one of the following structures is linked into a list associated with the * command's interpreter. The information in the structure is needed in order * for Tcl to behave reasonably if traces are deleted while traces are active. */ typedef struct ActiveCommandTrace { struct Command *cmdPtr; /* Command that's being traced. */ struct ActiveCommandTrace *nextPtr; /* Next in list of all active command traces * for the interpreter, or NULL if no more. */ CommandTrace *nextTracePtr; /* Next trace to check after current trace * procedure returns; if this trace gets * deleted, must update pointer to avoid using * free'd memory. */ int reverseScan; /* Boolean set true when traces are scanning * in reverse order. */ } ActiveCommandTrace; /* * When a variable trace is active (i.e. its associated procedure is * executing) one of the following structures is linked into a list associated * with the variable's interpreter. The information in the structure is needed * in order for Tcl to behave reasonably if traces are deleted while traces * are active. */ typedef struct ActiveVarTrace { struct Var *varPtr; /* Variable that's being traced. */ struct ActiveVarTrace *nextPtr; /* Next in list of all active variable traces * for the interpreter, or NULL if no more. */ VarTrace *nextTracePtr; /* Next trace to check after current trace * procedure returns; if this trace gets * deleted, must update pointer to avoid using * free'd memory. */ } ActiveVarTrace; /* * The structure below defines a variable, which associates a string name with * a Tcl_Obj value. These structures are kept in procedure call frames (for * local variables recognized by the compiler) or in the heap (for global * variables and any variable not known to the compiler). For each Var * structure in the heap, a hash table entry holds the variable name and a * pointer to the Var structure. */ typedef struct Var { int flags; /* Miscellaneous bits of information about * variable. See below for definitions. */ union { Tcl_Obj *objPtr; /* The variable's object value. Used for * scalar variables and array elements. */ TclVarHashTable *tablePtr;/* For array variables, this points to * information about the hash table used to * implement the associative array. Points to * ckalloc-ed data. */ struct Var *linkPtr; /* If this is a global variable being referred * to in a procedure, or a variable created by * "upvar", this field points to the * referenced variable's Var struct. */ } value; } Var; typedef struct VarInHash { Var var; int refCount; /* Counts number of active uses of this * variable: 1 for the entry in the hash * table, 1 for each additional variable whose * linkPtr points here, 1 for each nested * trace active on variable, and 1 if the * variable is a namespace variable. This * record can't be deleted until refCount * becomes 0. */ Tcl_HashEntry entry; /* The hash table entry that refers to this * variable. This is used to find the name of * the variable and to delete it from its * hashtable if it is no longer needed. It * also holds the variable's name. */ } VarInHash; /* * Flag bits for variables. The first two (VAR_ARRAY and VAR_LINK) are * mutually exclusive and give the "type" of the variable. If none is set, * this is a scalar variable. * * VAR_ARRAY - 1 means this is an array variable rather than * a scalar variable or link. The "tablePtr" * field points to the array's hashtable for its * elements. * VAR_LINK - 1 means this Var structure contains a pointer * to another Var structure that either has the * real value or is itself another VAR_LINK * pointer. Variables like this come about * through "upvar" and "global" commands, or * through references to variables in enclosing * namespaces. * * Flags that indicate the type and status of storage; none is set for * compiled local variables (Var structs). * * VAR_IN_HASHTABLE - 1 means this variable is in a hashtable and * the Var structure is malloced. 0 if it is a * local variable that was assigned a slot in a * procedure frame by the compiler so the Var * storage is part of the call frame. * VAR_DEAD_HASH 1 means that this var's entry in the hashtable * has already been deleted. * VAR_ARRAY_ELEMENT - 1 means that this variable is an array * element, so it is not legal for it to be an * array itself (the VAR_ARRAY flag had better * not be set). * VAR_NAMESPACE_VAR - 1 means that this variable was declared as a * namespace variable. This flag ensures it * persists until its namespace is destroyed or * until the variable is unset; it will persist * even if it has not been initialized and is * marked undefined. The variable's refCount is * incremented to reflect the "reference" from * its namespace. * * Flag values relating to the variable's trace and search status. * * VAR_TRACED_READ * VAR_TRACED_WRITE * VAR_TRACED_UNSET * VAR_TRACED_ARRAY * VAR_TRACE_ACTIVE - 1 means that trace processing is currently * underway for a read or write access, so new * read or write accesses should not cause trace * procedures to be called and the variable can't * be deleted. * VAR_SEARCH_ACTIVE * * The following additional flags are used with the CompiledLocal type defined * below: * * VAR_ARGUMENT - 1 means that this variable holds a procedure * argument. * VAR_TEMPORARY - 1 if the local variable is an anonymous * temporary variable. Temporaries have a NULL * name. * VAR_RESOLVED - 1 if name resolution has been done for this * variable. * VAR_IS_ARGS 1 if this variable is the last argument and is * named "args". */ /* * FLAGS RENUMBERED: everything breaks already, make things simpler. * * IMPORTANT: skip the values 0x10, 0x20, 0x40, 0x800 corresponding to * TCL_TRACE_(READS/WRITES/UNSETS/ARRAY): makes code simpler in tclTrace.c * * Keep the flag values for VAR_ARGUMENT and VAR_TEMPORARY so that old values * in precompiled scripts keep working. */ /* Type of value (0 is scalar) */ #define VAR_ARRAY 0x1 #define VAR_LINK 0x2 /* Type of storage (0 is compiled local) */ #define VAR_IN_HASHTABLE 0x4 #define VAR_DEAD_HASH 0x8 #define VAR_ARRAY_ELEMENT 0x1000 #define VAR_NAMESPACE_VAR 0x80 /* KEEP OLD VALUE for Itcl */ #define VAR_ALL_HASH \ (VAR_IN_HASHTABLE|VAR_DEAD_HASH|VAR_NAMESPACE_VAR|VAR_ARRAY_ELEMENT) /* Trace and search state. */ #define VAR_TRACED_READ 0x10 /* TCL_TRACE_READS */ #define VAR_TRACED_WRITE 0x20 /* TCL_TRACE_WRITES */ #define VAR_TRACED_UNSET 0x40 /* TCL_TRACE_UNSETS */ #define VAR_TRACED_ARRAY 0x800 /* TCL_TRACE_ARRAY */ #define VAR_TRACE_ACTIVE 0x2000 #define VAR_SEARCH_ACTIVE 0x4000 #define VAR_ALL_TRACES \ (VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_TRACED_ARRAY|VAR_TRACED_UNSET) /* Special handling on initialisation (only CompiledLocal). */ #define VAR_ARGUMENT 0x100 /* KEEP OLD VALUE! See tclProc.c */ #define VAR_TEMPORARY 0x200 /* KEEP OLD VALUE! See tclProc.c */ #define VAR_IS_ARGS 0x400 #define VAR_RESOLVED 0x8000 /* * Macros to ensure that various flag bits are set properly for variables. * The ANSI C "prototypes" for these macros are: * * MODULE_SCOPE void TclSetVarScalar(Var *varPtr); * MODULE_SCOPE void TclSetVarArray(Var *varPtr); * MODULE_SCOPE void TclSetVarLink(Var *varPtr); * MODULE_SCOPE void TclSetVarArrayElement(Var *varPtr); * MODULE_SCOPE void TclSetVarUndefined(Var *varPtr); * MODULE_SCOPE void TclClearVarUndefined(Var *varPtr); */ #define TclSetVarScalar(varPtr) \ (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK) #define TclSetVarArray(varPtr) \ (varPtr)->flags = ((varPtr)->flags & ~VAR_LINK) | VAR_ARRAY #define TclSetVarLink(varPtr) \ (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_LINK #define TclSetVarArrayElement(varPtr) \ (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_ARRAY_ELEMENT #define TclSetVarUndefined(varPtr) \ (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK);\ (varPtr)->value.objPtr = NULL #define TclClearVarUndefined(varPtr) #define TclSetVarTraceActive(varPtr) \ (varPtr)->flags |= VAR_TRACE_ACTIVE #define TclClearVarTraceActive(varPtr) \ (varPtr)->flags &= ~VAR_TRACE_ACTIVE #define TclSetVarNamespaceVar(varPtr) \ if (!TclIsVarNamespaceVar(varPtr)) {\ (varPtr)->flags |= VAR_NAMESPACE_VAR;\ if (TclIsVarInHash(varPtr)) {\ ((VarInHash *)(varPtr))->refCount++;\ }\ } #define TclClearVarNamespaceVar(varPtr) \ if (TclIsVarNamespaceVar(varPtr)) {\ (varPtr)->flags &= ~VAR_NAMESPACE_VAR;\ if (TclIsVarInHash(varPtr)) {\ ((VarInHash *)(varPtr))->refCount--;\ }\ } /* * Macros to read various flag bits of variables. * The ANSI C "prototypes" for these macros are: * * MODULE_SCOPE int TclIsVarScalar(Var *varPtr); * MODULE_SCOPE int TclIsVarLink(Var *varPtr); * MODULE_SCOPE int TclIsVarArray(Var *varPtr); * MODULE_SCOPE int TclIsVarUndefined(Var *varPtr); * MODULE_SCOPE int TclIsVarArrayElement(Var *varPtr); * MODULE_SCOPE int TclIsVarTemporary(Var *varPtr); * MODULE_SCOPE int TclIsVarArgument(Var *varPtr); * MODULE_SCOPE int TclIsVarResolved(Var *varPtr); */ #define TclIsVarScalar(varPtr) \ !((varPtr)->flags & (VAR_ARRAY|VAR_LINK)) #define TclIsVarLink(varPtr) \ ((varPtr)->flags & VAR_LINK) #define TclIsVarArray(varPtr) \ ((varPtr)->flags & VAR_ARRAY) #define TclIsVarUndefined(varPtr) \ ((varPtr)->value.objPtr == NULL) #define TclIsVarArrayElement(varPtr) \ ((varPtr)->flags & VAR_ARRAY_ELEMENT) #define TclIsVarNamespaceVar(varPtr) \ ((varPtr)->flags & VAR_NAMESPACE_VAR) #define TclIsVarTemporary(varPtr) \ ((varPtr)->flags & VAR_TEMPORARY) #define TclIsVarArgument(varPtr) \ ((varPtr)->flags & VAR_ARGUMENT) #define TclIsVarResolved(varPtr) \ ((varPtr)->flags & VAR_RESOLVED) #define TclIsVarTraceActive(varPtr) \ ((varPtr)->flags & VAR_TRACE_ACTIVE) #define TclIsVarTraced(varPtr) \ ((varPtr)->flags & VAR_ALL_TRACES) #define TclIsVarInHash(varPtr) \ ((varPtr)->flags & VAR_IN_HASHTABLE) #define TclIsVarDeadHash(varPtr) \ ((varPtr)->flags & VAR_DEAD_HASH) #define TclGetVarNsPtr(varPtr) \ (TclIsVarInHash(varPtr) \ ? ((TclVarHashTable *) ((((VarInHash *) (varPtr))->entry.tablePtr)))->nsPtr \ : NULL) #define VarHashRefCount(varPtr) \ ((VarInHash *) (varPtr))->refCount /* * Macros for direct variable access by TEBC. */ #define TclIsVarDirectReadable(varPtr) \ ( !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ)) \ && (varPtr)->value.objPtr) #define TclIsVarDirectWritable(varPtr) \ !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_WRITE|VAR_DEAD_HASH)) #define TclIsVarDirectUnsettable(varPtr) \ !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_TRACED_UNSET|VAR_DEAD_HASH)) #define TclIsVarDirectModifyable(varPtr) \ ( !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ|VAR_TRACED_WRITE)) \ && (varPtr)->value.objPtr) #define TclIsVarDirectReadable2(varPtr, arrayPtr) \ (TclIsVarDirectReadable(varPtr) &&\ (!(arrayPtr) || !((arrayPtr)->flags & VAR_TRACED_READ))) #define TclIsVarDirectWritable2(varPtr, arrayPtr) \ (TclIsVarDirectWritable(varPtr) &&\ (!(arrayPtr) || !((arrayPtr)->flags & VAR_TRACED_WRITE))) #define TclIsVarDirectModifyable2(varPtr, arrayPtr) \ (TclIsVarDirectModifyable(varPtr) &&\ (!(arrayPtr) || !((arrayPtr)->flags & (VAR_TRACED_READ|VAR_TRACED_WRITE)))) /* *---------------------------------------------------------------- * Data structures related to procedures. These are used primarily in * tclProc.c, tclCompile.c, and tclExecute.c. *---------------------------------------------------------------- */ /* * Forward declaration to prevent an error when the forward reference to * Command is encountered in the Proc and ImportRef types declared below. */ struct Command; /* * The variable-length structure below describes a local variable of a * procedure that was recognized by the compiler. These variables have a name, * an element in the array of compiler-assigned local variables in the * procedure's call frame, and various other items of information. If the * local variable is a formal argument, it may also have a default value. The * compiler can't recognize local variables whose names are expressions (these * names are only known at runtime when the expressions are evaluated) or * local variables that are created as a result of an "upvar" or "uplevel" * command. These other local variables are kept separately in a hash table in * the call frame. */ typedef struct CompiledLocal { struct CompiledLocal *nextPtr; /* Next compiler-recognized local variable for * this procedure, or NULL if this is the last * local. */ int nameLength; /* The number of characters in local * variable's name. Used to speed up variable * lookups. */ int frameIndex; /* Index in the array of compiler-assigned * variables in the procedure call frame. */ int flags; /* Flag bits for the local variable. Same as * the flags for the Var structure above, * although only VAR_ARGUMENT, VAR_TEMPORARY, * and VAR_RESOLVED make sense. */ Tcl_Obj *defValuePtr; /* Pointer to the default value of an * argument, if any. NULL if not an argument * or, if an argument, no default value. */ Tcl_ResolvedVarInfo *resolveInfo; /* Customized variable resolution info * supplied by the Tcl_ResolveCompiledVarProc * associated with a namespace. Each variable * is marked by a unique ClientData tag during * compilation, and that same tag is used to * find the variable at runtime. */ char name[1]; /* Name of the local variable starts here. If * the name is NULL, this will just be '\0'. * The actual size of this field will be large * enough to hold the name. MUST BE THE LAST * FIELD IN THE STRUCTURE! */ } CompiledLocal; /* * The structure below defines a command procedure, which consists of a * collection of Tcl commands plus information about arguments and other local * variables recognized at compile time. */ typedef struct Proc { struct Interp *iPtr; /* Interpreter for which this command is * defined. */ int refCount; /* Reference count: 1 if still present in * command table plus 1 for each call to the * procedure that is currently active. This * structure can be freed when refCount * becomes zero. */ struct Command *cmdPtr; /* Points to the Command structure for this * procedure. This is used to get the * namespace in which to execute the * procedure. */ Tcl_Obj *bodyPtr; /* Points to the ByteCode object for * procedure's body command. */ int numArgs; /* Number of formal parameters. */ int numCompiledLocals; /* Count of local variables recognized by the * compiler including arguments and * temporaries. */ CompiledLocal *firstLocalPtr; /* Pointer to first of the procedure's * compiler-allocated local variables, or NULL * if none. The first numArgs entries in this * list describe the procedure's formal * arguments. */ CompiledLocal *lastLocalPtr;/* Pointer to the last allocated local * variable or NULL if none. This has frame * index (numCompiledLocals-1). */ } Proc; /* * The type of functions called to process errors found during the execution * of a procedure (or lambda term or ...). */ typedef void (ProcErrorProc)(Tcl_Interp *interp, Tcl_Obj *procNameObj); /* * The structure below defines a command trace. This is used to allow Tcl * clients to find out whenever a command is about to be executed. */ typedef struct Trace { int level; /* Only trace commands at nesting level less * than or equal to this. */ Tcl_CmdObjTraceProc *proc; /* Procedure to call to trace command. */ ClientData clientData; /* Arbitrary value to pass to proc. */ struct Trace *nextPtr; /* Next in list of traces for this interp. */ int flags; /* Flags governing the trace - see * Tcl_CreateObjTrace for details. */ Tcl_CmdObjTraceDeleteProc *delProc; /* Procedure to call when trace is deleted. */ } Trace; /* * When an interpreter trace is active (i.e. its associated procedure is * executing), one of the following structures is linked into a list * associated with the interpreter. The information in the structure is needed * in order for Tcl to behave reasonably if traces are deleted while traces * are active. */ typedef struct ActiveInterpTrace { struct ActiveInterpTrace *nextPtr; /* Next in list of all active command traces * for the interpreter, or NULL if no more. */ Trace *nextTracePtr; /* Next trace to check after current trace * procedure returns; if this trace gets * deleted, must update pointer to avoid using * free'd memory. */ int reverseScan; /* Boolean set true when traces are scanning * in reverse order. */ } ActiveInterpTrace; /* * Flag values designating types of execution traces. See tclTrace.c for * related flag values. * * TCL_TRACE_ENTER_EXEC - triggers enter/enterstep traces. * - passed to Tcl_CreateObjTrace to set up * "enterstep" traces. * TCL_TRACE_LEAVE_EXEC - triggers leave/leavestep traces. * - passed to Tcl_CreateObjTrace to set up * "leavestep" traces. */ #define TCL_TRACE_ENTER_EXEC 1 #define TCL_TRACE_LEAVE_EXEC 2 /* * The structure below defines an entry in the assocData hash table which is * associated with an interpreter. The entry contains a pointer to a function * to call when the interpreter is deleted, and a pointer to a user-defined * piece of data. */ typedef struct AssocData { Tcl_InterpDeleteProc *proc; /* Proc to call when deleting. */ ClientData clientData; /* Value to pass to proc. */ } AssocData; /* * The structure below defines a call frame. A call frame defines a naming * context for a procedure call: its local naming scope (for local variables) * and its global naming scope (a namespace, perhaps the global :: namespace). * A call frame can also define the naming context for a namespace eval or * namespace inscope command: the namespace in which the command's code should * execute. The Tcl_CallFrame structures exist only while procedures or * namespace eval/inscope's are being executed, and provide a kind of Tcl call * stack. * * WARNING!! The structure definition must be kept consistent with the * Tcl_CallFrame structure in tcl.h. If you change one, change the other. */ /* * Will be grown to contain: pointers to the varnames (allocated at the end), * plus the init values for each variable (suitable to be memcopied on init) */ typedef struct LocalCache { int refCount; int numVars; Tcl_Obj *varName0; } LocalCache; #define localName(framePtr, i) \ ((&((framePtr)->localCachePtr->varName0))[(i)]) MODULE_SCOPE void TclFreeLocalCache(Tcl_Interp *interp, LocalCache *localCachePtr); typedef struct CallFrame { Namespace *nsPtr; /* Points to the namespace used to resolve * commands and global variables. */ int isProcCallFrame; /* If 0, the frame was pushed to execute a * namespace command and var references are * treated as references to namespace vars; * varTablePtr and compiledLocals are ignored. * If FRAME_IS_PROC is set, the frame was * pushed to execute a Tcl procedure and may * have local vars. */ int objc; /* This and objv below describe the arguments * for this procedure call. */ Tcl_Obj *const *objv; /* Array of argument objects. */ struct CallFrame *callerPtr; /* Value of interp->framePtr when this * procedure was invoked (i.e. next higher in * stack of all active procedures). */ struct CallFrame *callerVarPtr; /* Value of interp->varFramePtr when this * procedure was invoked (i.e. determines * variable scoping within caller). Same as * callerPtr unless an "uplevel" command or * something equivalent was active in the * caller). */ int level; /* Level of this procedure, for "uplevel" * purposes (i.e. corresponds to nesting of * callerVarPtr's, not callerPtr's). 1 for * outermost procedure, 0 for top-level. */ Proc *procPtr; /* Points to the structure defining the called * procedure. Used to get information such as * the number of compiled local variables * (local variables assigned entries ["slots"] * in the compiledLocals array below). */ TclVarHashTable *varTablePtr; /* Hash table containing local variables not * recognized by the compiler, or created at * execution time through, e.g., upvar. * Initially NULL and created if needed. */ int numCompiledLocals; /* Count of local variables recognized by the * compiler including arguments. */ Var *compiledLocals; /* Points to the array of local variables * recognized by the compiler. The compiler * emits code that refers to these variables * using an index into this array. */ ClientData clientData; /* Pointer to some context that is used by * object systems. The meaning of the contents * of this field is defined by the code that * sets it, and it should only ever be set by * the code that is pushing the frame. In that * case, the code that sets it should also * have some means of discovering what the * meaning of the value is, which we do not * specify. */ LocalCache *localCachePtr; Tcl_Obj *tailcallPtr; /* NULL if no tailcall is scheduled */ } CallFrame; #define FRAME_IS_PROC 0x1 #define FRAME_IS_LAMBDA 0x2 #define FRAME_IS_METHOD 0x4 /* The frame is a method body, and the frame's * clientData field contains a CallContext * reference. Part of TIP#257. */ #define FRAME_IS_OO_DEFINE 0x8 /* The frame is part of the inside workings of * the [oo::define] command; the clientData * field contains an Object reference that has * been confirmed to refer to a class. Part of * TIP#257. */ /* * TIP #280 * The structure below defines a command frame. A command frame provides * location information for all commands executing a tcl script (source, eval, * uplevel, procedure bodies, ...). The runtime structure essentially contains * the stack trace as it would be if the currently executing command were to * throw an error. * * For commands where it makes sense it refers to the associated CallFrame as * well. * * The structures are chained in a single list, with the top of the stack * anchored in the Interp structure. * * Instances can be allocated on the C stack, or the heap, the former making * cleanup a bit simpler. */ typedef struct CmdFrame { /* * General data. Always available. */ int type; /* Values see below. */ int level; /* Number of frames in stack, prevent O(n) * scan of list. */ int *line; /* Lines the words of the command start on. */ int nline; CallFrame *framePtr; /* Procedure activation record, may be * NULL. */ struct CmdFrame *nextPtr; /* Link to calling frame. */ /* * Data needed for Eval vs TEBC * * EXECUTION CONTEXTS and usage of CmdFrame * * Field TEBC EvalEx * ======= ==== ====== * level yes yes * type BC/PREBC SRC/EVAL * line0 yes yes * framePtr yes yes * ======= ==== ====== * * ======= ==== ========= union data * line1 - yes * line3 - yes * path - yes * ------- ---- ------ * codePtr yes - * pc yes - * ======= ==== ====== * * ======= ==== ========= union cmd * str.cmd yes yes * str.len yes yes * ------- ---- ------ */ union { struct { Tcl_Obj *path; /* Path of the sourced file the command is * in. */ } eval; struct { const void *codePtr;/* Byte code currently executed... */ const char *pc; /* ... and instruction pointer. */ } tebc; } data; Tcl_Obj *cmdObj; const char *cmd; /* The executed command, if possible... */ int len; /* ... and its length. */ const struct CFWordBC *litarg; /* Link to set of literal arguments which have * ben pushed on the lineLABCPtr stack by * TclArgumentBCEnter(). These will be removed * by TclArgumentBCRelease. */ } CmdFrame; typedef struct CFWord { CmdFrame *framePtr; /* CmdFrame to access. */ int word; /* Index of the word in the command. */ int refCount; /* Number of times the word is on the * stack. */ } CFWord; typedef struct CFWordBC { CmdFrame *framePtr; /* CmdFrame to access. */ int pc; /* Instruction pointer of a command in * ExtCmdLoc.loc[.] */ int word; /* Index of word in * ExtCmdLoc.loc[cmd]->line[.] */ struct CFWordBC *prevPtr; /* Previous entry in stack for same Tcl_Obj. */ struct CFWordBC *nextPtr; /* Next entry for same command call. See * CmdFrame litarg field for the list start. */ Tcl_Obj *obj; /* Back reference to hashtable key */ } CFWordBC; /* * Structure to record the locations of invisible continuation lines in * literal scripts, as character offset from the beginning of the script. Both * compiler and direct evaluator use this information to adjust their line * counters when tracking through the script, because when it is invoked the * continuation line marker as a whole has been removed already, meaning that * the \n which was part of it is gone as well, breaking regular line * tracking. * * These structures are allocated and filled by both the function * TclSubstTokens() in the file "tclParse.c" and its caller TclEvalEx() in the * file "tclBasic.c", and stored in the thread-global hashtable "lineCLPtr" in * file "tclObj.c". They are used by the functions TclSetByteCodeFromAny() and * TclCompileScript(), both found in the file "tclCompile.c". Their memory is * released by the function TclFreeObj(), in the file "tclObj.c", and also by * the function TclThreadFinalizeObjects(), in the same file. */ #define CLL_END (-1) typedef struct ContLineLoc { int num; /* Number of entries in loc, not counting the * final -1 marker entry. */ int loc[1]; /* Table of locations, as character offsets. * The table is allocated as part of the * structure, extending behind the nominal end * of the structure. An entry containing the * value -1 is put after the last location, as * end-marker/sentinel. */ } ContLineLoc; /* * The following macros define the allowed values for the type field of the * CmdFrame structure above. Some of the values occur only in the extended * location data referenced via the 'baseLocPtr'. * * TCL_LOCATION_EVAL : Frame is for a script evaluated by EvalEx. * TCL_LOCATION_BC : Frame is for bytecode. * TCL_LOCATION_PREBC : Frame is for precompiled bytecode. * TCL_LOCATION_SOURCE : Frame is for a script evaluated by EvalEx, from a * sourced file. * TCL_LOCATION_PROC : Frame is for bytecode of a procedure. * * A TCL_LOCATION_BC type in a frame can be overridden by _SOURCE and _PROC * types, per the context of the byte code in execution. */ #define TCL_LOCATION_EVAL (0) /* Location in a dynamic eval script. */ #define TCL_LOCATION_BC (2) /* Location in byte code. */ #define TCL_LOCATION_PREBC (3) /* Location in precompiled byte code, no * location. */ #define TCL_LOCATION_SOURCE (4) /* Location in a file. */ #define TCL_LOCATION_PROC (5) /* Location in a dynamic proc. */ #define TCL_LOCATION_LAST (6) /* Number of values in the enum. */ /* * Structure passed to describe procedure-like "procedures" that are not * procedures (e.g. a lambda) so that their details can be reported correctly * by [info frame]. Contains a sub-structure for each extra field. */ typedef Tcl_Obj * (GetFrameInfoValueProc)(ClientData clientData); typedef struct { const char *name; /* Name of this field. */ GetFrameInfoValueProc *proc; /* Function to generate a Tcl_Obj* from the * clientData, or just use the clientData * directly (after casting) if NULL. */ ClientData clientData; /* Context for above function, or Tcl_Obj* if * proc field is NULL. */ } ExtraFrameInfoField; typedef struct { int length; /* Length of array. */ ExtraFrameInfoField fields[2]; /* Really as long as necessary, but this is * long enough for nearly anything. */ } ExtraFrameInfo; /* *---------------------------------------------------------------- * Data structures and procedures related to TclHandles, which are a very * lightweight method of preserving enough information to determine if an * arbitrary malloc'd block has been deleted. *---------------------------------------------------------------- */ typedef void **TclHandle; /* *---------------------------------------------------------------- * Experimental flag value passed to Tcl_GetRegExpFromObj. Intended for use * only by Expect. It will probably go away in a later release. *---------------------------------------------------------------- */ #define TCL_REG_BOSONLY 002000 /* Prepend \A to pattern so it only matches at * the beginning of the string. */ /* * These are a thin layer over TclpThreadKeyDataGet and TclpThreadKeyDataSet * when threads are used, or an emulation if there are no threads. These are * really internal and Tcl clients should use Tcl_GetThreadData. */ MODULE_SCOPE void * TclThreadDataKeyGet(Tcl_ThreadDataKey *keyPtr); MODULE_SCOPE void TclThreadDataKeySet(Tcl_ThreadDataKey *keyPtr, void *data); /* * This is a convenience macro used to initialize a thread local storage ptr. */ #define TCL_TSD_INIT(keyPtr) \ (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData)) /* *---------------------------------------------------------------- * Data structures related to bytecode compilation and execution. These are * used primarily in tclCompile.c, tclExecute.c, and tclBasic.c. *---------------------------------------------------------------- */ /* * Forward declaration to prevent errors when the forward references to * Tcl_Parse and CompileEnv are encountered in the procedure type CompileProc * declared below. */ struct CompileEnv; /* * The type of procedures called by the Tcl bytecode compiler to compile * commands. Pointers to these procedures are kept in the Command structure * describing each command. The integer value returned by a CompileProc must * be one of the following: * * TCL_OK Compilation completed normally. * TCL_ERROR Compilation could not be completed. This can be just a * judgment by the CompileProc that the command is too * complex to compile effectively, or it can indicate * that in the current state of the interp, the command * would raise an error. The bytecode compiler will not * do any error reporting at compiler time. Error * reporting is deferred until the actual runtime, * because by then changes in the interp state may allow * the command to be successfully evaluated. * TCL_OUT_LINE_COMPILE A source-compatible alias for TCL_ERROR, kept for the * sake of old code only. */ #define TCL_OUT_LINE_COMPILE TCL_ERROR typedef int (CompileProc)(Tcl_Interp *interp, Tcl_Parse *parsePtr, struct Command *cmdPtr, struct CompileEnv *compEnvPtr); /* * The type of procedure called from the compilation hook point in * SetByteCodeFromAny. */ typedef int (CompileHookProc)(Tcl_Interp *interp, struct CompileEnv *compEnvPtr, ClientData clientData); /* * The data structure for a (linked list of) execution stacks. */ typedef struct ExecStack { struct ExecStack *prevPtr; struct ExecStack *nextPtr; Tcl_Obj **markerPtr; Tcl_Obj **endPtr; Tcl_Obj **tosPtr; Tcl_Obj *stackWords[1]; } ExecStack; /* * The data structure defining the execution environment for ByteCode's. * There is one ExecEnv structure per Tcl interpreter. It holds the evaluation * stack that holds command operands and results. The stack grows towards * increasing addresses. The member stackPtr points to the stackItems of the * currently active execution stack. */ typedef struct CorContext { struct CallFrame *framePtr; struct CallFrame *varFramePtr; struct CmdFrame *cmdFramePtr; /* See Interp.cmdFramePtr */ Tcl_HashTable *lineLABCPtr; /* See Interp.lineLABCPtr */ } CorContext; typedef struct CoroutineData { struct Command *cmdPtr; /* The command handle for the coroutine. */ struct ExecEnv *eePtr; /* The special execution environment (stacks, * etc.) for the coroutine. */ struct ExecEnv *callerEEPtr;/* The execution environment for the caller of * the coroutine, which might be the * interpreter global environment or another * coroutine. */ CorContext caller; CorContext running; Tcl_HashTable *lineLABCPtr; /* See Interp.lineLABCPtr */ void *stackLevel; int auxNumLevels; /* While the coroutine is running the * numLevels of the create/resume command is * stored here; for suspended coroutines it * holds the nesting numLevels at yield. */ int nargs; /* Number of args required for resuming this * coroutine; -2 means "0 or 1" (default), -1 * means "any" */ } CoroutineData; typedef struct ExecEnv { ExecStack *execStackPtr; /* Points to the first item in the evaluation * stack on the heap. */ Tcl_Obj *constants[2]; /* Pointers to constant "0" and "1" objs. */ struct Tcl_Interp *interp; struct NRE_callback *callbackPtr; /* Top callback in NRE's stack. */ struct CoroutineData *corPtr; int rewind; } ExecEnv; #define COR_IS_SUSPENDED(corPtr) \ ((corPtr)->stackLevel == NULL) /* * The definitions for the LiteralTable and LiteralEntry structures. Each * interpreter contains a LiteralTable. It is used to reduce the storage * needed for all the Tcl objects that hold the literals of scripts compiled * by the interpreter. A literal's object is shared by all the ByteCodes that * refer to the literal. Each distinct literal has one LiteralEntry entry in * the LiteralTable. A literal table is a specialized hash table that is * indexed by the literal's string representation, which may contain null * characters. * * Note that we reduce the space needed for literals by sharing literal * objects both within a ByteCode (each ByteCode contains a local * LiteralTable) and across all an interpreter's ByteCodes (with the * interpreter's global LiteralTable). */ typedef struct LiteralEntry { struct LiteralEntry *nextPtr; /* Points to next entry in this hash bucket or * NULL if end of chain. */ Tcl_Obj *objPtr; /* Points to Tcl object that holds the * literal's bytes and length. */ int refCount; /* If in an interpreter's global literal * table, the number of ByteCode structures * that share the literal object; the literal * entry can be freed when refCount drops to * 0. If in a local literal table, -1. */ Namespace *nsPtr; /* Namespace in which this literal is used. We * try to avoid sharing literal non-FQ command * names among different namespaces to reduce * shimmering. */ } LiteralEntry; typedef struct LiteralTable { LiteralEntry **buckets; /* Pointer to bucket array. Each element * points to first entry in bucket's hash * chain, or NULL. */ LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; /* Bucket array used for small tables to avoid * mallocs and frees. */ int numBuckets; /* Total number of buckets allocated at * **buckets. */ int numEntries; /* Total number of entries present in * table. */ int rebuildSize; /* Enlarge table when numEntries gets to be * this large. */ int mask; /* Mask value used in hashing function. */ } LiteralTable; /* * The following structure defines for each Tcl interpreter various * statistics-related information about the bytecode compiler and * interpreter's operation in that interpreter. */ #ifdef TCL_COMPILE_STATS typedef struct ByteCodeStats { long numExecutions; /* Number of ByteCodes executed. */ long numCompilations; /* Number of ByteCodes created. */ long numByteCodesFreed; /* Number of ByteCodes destroyed. */ long instructionCount[256]; /* Number of times each instruction was * executed. */ double totalSrcBytes; /* Total source bytes ever compiled. */ double totalByteCodeBytes; /* Total bytes for all ByteCodes. */ double currentSrcBytes; /* Src bytes for all current ByteCodes. */ double currentByteCodeBytes;/* Code bytes in all current ByteCodes. */ long srcCount[32]; /* Source size distribution: # of srcs of * size [2**(n-1)..2**n), n in [0..32). */ long byteCodeCount[32]; /* ByteCode size distribution. */ long lifetimeCount[32]; /* ByteCode lifetime distribution (ms). */ double currentInstBytes; /* Instruction bytes-current ByteCodes. */ double currentLitBytes; /* Current literal bytes. */ double currentExceptBytes; /* Current exception table bytes. */ double currentAuxBytes; /* Current auxiliary information bytes. */ double currentCmdMapBytes; /* Current src<->code map bytes. */ long numLiteralsCreated; /* Total literal objects ever compiled. */ double totalLitStringBytes; /* Total string bytes in all literals. */ double currentLitStringBytes; /* String bytes in current literals. */ long literalCount[32]; /* Distribution of literal string sizes. */ } ByteCodeStats; #endif /* TCL_COMPILE_STATS */ /* * Structure used in implementation of those core ensembles which are * partially compiled. Used as an array of these, with a terminating field * whose 'name' is NULL. */ typedef struct { const char *name; /* The name of the subcommand. */ Tcl_ObjCmdProc *proc; /* The implementation of the subcommand. */ CompileProc *compileProc; /* The compiler for the subcommand. */ Tcl_ObjCmdProc *nreProc; /* NRE implementation of this command. */ ClientData clientData; /* Any clientData to give the command. */ int unsafe; /* Whether this command is to be hidden by * default in a safe interpreter. */ } EnsembleImplMap; /* *---------------------------------------------------------------- * Data structures related to commands. *---------------------------------------------------------------- */ /* * An imported command is created in an namespace when it imports a "real" * command from another namespace. An imported command has a Command structure * that points (via its ClientData value) to the "real" Command structure in * the source namespace's command table. The real command records all the * imported commands that refer to it in a list of ImportRef structures so * that they can be deleted when the real command is deleted. */ typedef struct ImportRef { struct Command *importedCmdPtr; /* Points to the imported command created in * an importing namespace; this command * redirects its invocations to the "real" * command. */ struct ImportRef *nextPtr; /* Next element on the linked list of imported * commands that refer to the "real" command. * The real command deletes these imported * commands on this list when it is * deleted. */ } ImportRef; /* * Data structure used as the ClientData of imported commands: commands * created in an namespace when it imports a "real" command from another * namespace. */ typedef struct ImportedCmdData { struct Command *realCmdPtr; /* "Real" command that this imported command * refers to. */ struct Command *selfPtr; /* Pointer to this imported command. Needed * only when deleting it in order to remove it * from the real command's linked list of * imported commands that refer to it. */ } ImportedCmdData; /* * A Command structure exists for each command in a namespace. The Tcl_Command * opaque type actually refers to these structures. */ typedef struct Command { Tcl_HashEntry *hPtr; /* Pointer to the hash table entry that refers * to this command. The hash table is either a * namespace's command table or an * interpreter's hidden command table. This * pointer is used to get a command's name * from its Tcl_Command handle. NULL means * that the hash table entry has been removed * already (this can happen if deleteProc * causes the command to be deleted or * recreated). */ Namespace *nsPtr; /* Points to the namespace containing this * command. */ int refCount; /* 1 if in command hashtable plus 1 for each * reference from a CmdName Tcl object * representing a command's name in a ByteCode * instruction sequence. This structure can be * freed when refCount becomes zero. */ int cmdEpoch; /* Incremented to invalidate any references * that point to this command when it is * renamed, deleted, hidden, or exposed. */ CompileProc *compileProc; /* Procedure called to compile command. NULL * if no compile proc exists for command. */ Tcl_ObjCmdProc *objProc; /* Object-based command procedure. */ ClientData objClientData; /* Arbitrary value passed to object proc. */ Tcl_CmdProc *proc; /* String-based command procedure. */ ClientData clientData; /* Arbitrary value passed to string proc. */ Tcl_CmdDeleteProc *deleteProc; /* Procedure invoked when deleting command to, * e.g., free all client data. */ ClientData deleteData; /* Arbitrary value passed to deleteProc. */ int flags; /* Miscellaneous bits of information about * command. See below for definitions. */ ImportRef *importRefPtr; /* List of each imported Command created in * another namespace when this command is * imported. These imported commands redirect * invocations back to this command. The list * is used to remove all those imported * commands when deleting this "real" * command. */ CommandTrace *tracePtr; /* First in list of all traces set for this * command. */ Tcl_ObjCmdProc *nreProc; /* NRE implementation of this command. */ } Command; /* * Flag bits for commands. * * CMD_IS_DELETED - Means that the command is in the process of * being deleted (its deleteProc is currently * executing). Other attempts to delete the * command should be ignored. * CMD_TRACE_ACTIVE - 1 means that trace processing is currently * underway for a rename/delete change. See the * two flags below for which is currently being * processed. * CMD_HAS_EXEC_TRACES - 1 means that this command has at least one * execution trace (as opposed to simple * delete/rename traces) in its tracePtr list. * CMD_COMPILES_EXPANDED - 1 means that this command has a compiler that * can handle expansion (provided it is not the * first word). * TCL_TRACE_RENAME - A rename trace is in progress. Further * recursive renames will not be traced. * TCL_TRACE_DELETE - A delete trace is in progress. Further * recursive deletes will not be traced. * (these last two flags are defined in tcl.h) */ #define CMD_IS_DELETED 0x1 #define CMD_TRACE_ACTIVE 0x2 #define CMD_HAS_EXEC_TRACES 0x4 #define CMD_COMPILES_EXPANDED 0x8 #define CMD_REDEF_IN_PROGRESS 0x10 /* *---------------------------------------------------------------- * Data structures related to name resolution procedures. *---------------------------------------------------------------- */ /* * The interpreter keeps a linked list of name resolution schemes. The scheme * for a namespace is consulted first, followed by the list of schemes in an * interpreter, followed by the default name resolution in Tcl. Schemes are * added/removed from the interpreter's list by calling Tcl_AddInterpResolver * and Tcl_RemoveInterpResolver. */ typedef struct ResolverScheme { char *name; /* Name identifying this scheme. */ Tcl_ResolveCmdProc *cmdResProc; /* Procedure handling command name * resolution. */ Tcl_ResolveVarProc *varResProc; /* Procedure handling variable name resolution * for variables that can only be handled at * runtime. */ Tcl_ResolveCompiledVarProc *compiledVarResProc; /* Procedure handling variable name resolution * at compile time. */ struct ResolverScheme *nextPtr; /* Pointer to next record in linked list. */ } ResolverScheme; /* * Forward declaration of the TIP#143 limit handler structure. */ typedef struct LimitHandler LimitHandler; /* * TIP #268. * Values for the selection mode, i.e the package require preferences. */ enum PkgPreferOptions { PKG_PREFER_LATEST, PKG_PREFER_STABLE }; /* *---------------------------------------------------------------- * This structure shadows the first few fields of the memory cache for the * allocator defined in tclThreadAlloc.c; it has to be kept in sync with the * definition there. * Some macros require knowledge of some fields in the struct in order to * avoid hitting the TSD unnecessarily. In order to facilitate this, a pointer * to the relevant fields is kept in the allocCache field in struct Interp. *---------------------------------------------------------------- */ typedef struct AllocCache { struct Cache *nextPtr; /* Linked list of cache entries. */ Tcl_ThreadId owner; /* Which thread's cache is this? */ Tcl_Obj *firstObjPtr; /* List of free objects for thread. */ int numObjects; /* Number of objects for thread. */ } AllocCache; /* *---------------------------------------------------------------- * This structure defines an interpreter, which is a collection of commands * plus other state information related to interpreting commands, such as * variable storage. Primary responsibility for this data structure is in * tclBasic.c, but almost every Tcl source file uses something in here. *---------------------------------------------------------------- */ typedef struct Interp { /* * Note: the first three fields must match exactly the fields in a * Tcl_Interp struct (see tcl.h). If you change one, be sure to change the * other. * * The interpreter's result is held in both the string and the * objResultPtr fields. These fields hold, respectively, the result's * string or object value. The interpreter's result is always in the * result field if that is non-empty, otherwise it is in objResultPtr. * The two fields are kept consistent unless some C code sets * interp->result directly. Programs should not access result and * objResultPtr directly; instead, they should always get and set the * result using procedures such as Tcl_SetObjResult, Tcl_GetObjResult, and * Tcl_GetStringResult. See the SetResult man page for details. */ char *result; /* If the last command returned a string * result, this points to it. Should not be * accessed directly; see comment above. */ Tcl_FreeProc *freeProc; /* Zero means a string result is statically * allocated. TCL_DYNAMIC means string result * was allocated with ckalloc and should be * freed with ckfree. Other values give * address of procedure to invoke to free the * string result. Tcl_Eval must free it before * executing next command. */ int errorLine; /* When TCL_ERROR is returned, this gives the * line number in the command where the error * occurred (1 means first line). */ const struct TclStubs *stubTable; /* Pointer to the exported Tcl stub table. On * previous versions of Tcl this is a pointer * to the objResultPtr or a pointer to a * buckets array in a hash table. We therefore * have to do some careful checking before we * can use this. */ TclHandle handle; /* Handle used to keep track of when this * interp is deleted. */ Namespace *globalNsPtr; /* The interpreter's global namespace. */ Tcl_HashTable *hiddenCmdTablePtr; /* Hash table used by tclBasic.c to keep track * of hidden commands on a per-interp * basis. */ ClientData interpInfo; /* Information used by tclInterp.c to keep * track of master/slave interps on a * per-interp basis. */ union { void (*optimizer)(void *envPtr); Tcl_HashTable unused2; /* No longer used (was mathFuncTable). The * unused space in interp was repurposed for * pluggable bytecode optimizers. The core * contains one optimizer, which can be * selectively overriden by extensions. */ } extra; /* * Information related to procedures and variables. See tclProc.c and * tclVar.c for usage. */ int numLevels; /* Keeps track of how many nested calls to * Tcl_Eval are in progress for this * interpreter. It's used to delay deletion of * the table until all Tcl_Eval invocations * are completed. */ int maxNestingDepth; /* If numLevels exceeds this value then Tcl * assumes that infinite recursion has * occurred and it generates an error. */ CallFrame *framePtr; /* Points to top-most in stack of all nested * procedure invocations. */ CallFrame *varFramePtr; /* Points to the call frame whose variables * are currently in use (same as framePtr * unless an "uplevel" command is * executing). */ ActiveVarTrace *activeVarTracePtr; /* First in list of active traces for interp, * or NULL if no active traces. */ int returnCode; /* [return -code] parameter. */ CallFrame *rootFramePtr; /* Global frame pointer for this * interpreter. */ Namespace *lookupNsPtr; /* Namespace to use ONLY on the next * TCL_EVAL_INVOKE call to Tcl_EvalObjv. */ /* * Information used by Tcl_AppendResult to keep track of partial results. * See Tcl_AppendResult code for details. */ char *appendResult; /* Storage space for results generated by * Tcl_AppendResult. Ckalloc-ed. NULL means * not yet allocated. */ int appendAvl; /* Total amount of space available at * partialResult. */ int appendUsed; /* Number of non-null bytes currently stored * at partialResult. */ /* * Information about packages. Used only in tclPkg.c. */ Tcl_HashTable packageTable; /* Describes all of the packages loaded in or * available to this interpreter. Keys are * package names, values are (Package *) * pointers. */ char *packageUnknown; /* Command to invoke during "package require" * commands for packages that aren't described * in packageTable. Ckalloc'ed, may be * NULL. */ /* * Miscellaneous information: */ int cmdCount; /* Total number of times a command procedure * has been called for this interpreter. */ int evalFlags; /* Flags to control next call to Tcl_Eval. * Normally zero, but may be set before * calling Tcl_Eval. See below for valid * values. */ int unused1; /* No longer used (was termOffset) */ LiteralTable literalTable; /* Contains LiteralEntry's describing all Tcl * objects holding literals of scripts * compiled by the interpreter. Indexed by the * string representations of literals. Used to * avoid creating duplicate objects. */ int compileEpoch; /* Holds the current "compilation epoch" for * this interpreter. This is incremented to * invalidate existing ByteCodes when, e.g., a * command with a compile procedure is * redefined. */ Proc *compiledProcPtr; /* If a procedure is being compiled, a pointer * to its Proc structure; otherwise, this is * NULL. Set by ObjInterpProc in tclProc.c and * used by tclCompile.c to process local * variables appropriately. */ ResolverScheme *resolverPtr; /* Linked list of name resolution schemes * added to this interpreter. Schemes are * added and removed by calling * Tcl_AddInterpResolvers and * Tcl_RemoveInterpResolver respectively. */ Tcl_Obj *scriptFile; /* NULL means there is no nested source * command active; otherwise this points to * pathPtr of the file being sourced. */ int flags; /* Various flag bits. See below. */ long randSeed; /* Seed used for rand() function. */ Trace *tracePtr; /* List of traces for this interpreter. */ Tcl_HashTable *assocData; /* Hash table for associating data with this * interpreter. Cleaned up when this * interpreter is deleted. */ struct ExecEnv *execEnvPtr; /* Execution environment for Tcl bytecode * execution. Contains a pointer to the Tcl * evaluation stack. */ Tcl_Obj *emptyObjPtr; /* Points to an object holding an empty * string. Returned by Tcl_ObjSetVar2 when * variable traces change a variable in a * gross way. */ char resultSpace[TCL_RESULT_SIZE+1]; /* Static space holding small results. */ Tcl_Obj *objResultPtr; /* If the last command returned an object * result, this points to it. Should not be * accessed directly; see comment above. */ Tcl_ThreadId threadId; /* ID of thread that owns the interpreter. */ ActiveCommandTrace *activeCmdTracePtr; /* First in list of active command traces for * interp, or NULL if no active traces. */ ActiveInterpTrace *activeInterpTracePtr; /* First in list of active traces for interp, * or NULL if no active traces. */ int tracesForbiddingInline; /* Count of traces (in the list headed by * tracePtr) that forbid inline bytecode * compilation. */ /* * Fields used to manage extensible return options (TIP 90). */ Tcl_Obj *returnOpts; /* A dictionary holding the options to the * last [return] command. */ Tcl_Obj *errorInfo; /* errorInfo value (now as a Tcl_Obj). */ Tcl_Obj *eiVar; /* cached ref to ::errorInfo variable. */ Tcl_Obj *errorCode; /* errorCode value (now as a Tcl_Obj). */ Tcl_Obj *ecVar; /* cached ref to ::errorInfo variable. */ int returnLevel; /* [return -level] parameter. */ /* * Resource limiting framework support (TIP#143). */ struct { int active; /* Flag values defining which limits have been * set. */ int granularityTicker; /* Counter used to determine how often to * check the limits. */ int exceeded; /* Which limits have been exceeded, described * as flag values the same as the 'active' * field. */ int cmdCount; /* Limit for how many commands to execute in * the interpreter. */ LimitHandler *cmdHandlers; /* Handlers to execute when the limit is * reached. */ int cmdGranularity; /* Mod factor used to determine how often to * evaluate the limit check. */ Tcl_Time time; /* Time limit for execution within the * interpreter. */ LimitHandler *timeHandlers; /* Handlers to execute when the limit is * reached. */ int timeGranularity; /* Mod factor used to determine how often to * evaluate the limit check. */ Tcl_TimerToken timeEvent; /* Handle for a timer callback that will occur * when the time-limit is exceeded. */ Tcl_HashTable callbacks;/* Mapping from (interp,type) pair to data * used to install a limit handler callback to * run in _this_ interp when the limit is * exceeded. */ } limit; /* * Information for improved default error generation from ensembles * (TIP#112). */ struct { Tcl_Obj *const *sourceObjs; /* What arguments were actually input into the * *root* ensemble command? (Nested ensembles * don't rewrite this.) NULL if we're not * processing an ensemble. */ int numRemovedObjs; /* How many arguments have been stripped off * because of ensemble processing. */ int numInsertedObjs; /* How many of the current arguments were * inserted by an ensemble. */ } ensembleRewrite; /* * TIP #219: Global info for the I/O system. */ Tcl_Obj *chanMsg; /* Error message set by channel drivers, for * the propagation of arbitrary Tcl errors. * This information, if present (chanMsg not * NULL), takes precedence over a POSIX error * code returned by a channel operation. */ /* * Source code origin information (TIP #280). */ CmdFrame *cmdFramePtr; /* Points to the command frame containing the * location information for the current * command. */ const CmdFrame *invokeCmdFramePtr; /* Points to the command frame which is the * invoking context of the bytecode compiler. * NULL when the byte code compiler is not * active. */ int invokeWord; /* Index of the word in the command which * is getting compiled. */ Tcl_HashTable *linePBodyPtr;/* This table remembers for each statically * defined procedure the location information * for its body. It is keyed by the address of * the Proc structure for a procedure. The * values are "struct CmdFrame*". */ Tcl_HashTable *lineBCPtr; /* This table remembers for each ByteCode * object the location information for its * body. It is keyed by the address of the * Proc structure for a procedure. The values * are "struct ExtCmdLoc*". (See * tclCompile.h) */ Tcl_HashTable *lineLABCPtr; Tcl_HashTable *lineLAPtr; /* This table remembers for each argument of a * command on the execution stack the index of * the argument in the command, and the * location data of the command. It is keyed * by the address of the Tcl_Obj containing * the argument. The values are "struct * CFWord*" (See tclBasic.c). This allows * commands like uplevel, eval, etc. to find * location information for their arguments, * if they are a proper literal argument to an * invoking command. Alt view: An index to the * CmdFrame stack keyed by command argument * holders. */ ContLineLoc *scriptCLLocPtr;/* This table points to the location data for * invisible continuation lines in the script, * if any. This pointer is set by the function * TclEvalObjEx() in file "tclBasic.c", and * used by function ...() in the same file. * It does for the eval/direct path of script * execution what CompileEnv.clLoc does for * the bytecode compiler. */ /* * TIP #268. The currently active selection mode, i.e. the package require * preferences. */ int packagePrefer; /* Current package selection mode. */ /* * Hashtables for variable traces and searches. */ Tcl_HashTable varTraces; /* Hashtable holding the start of a variable's * active trace list; varPtr is the key. */ Tcl_HashTable varSearches; /* Hashtable holding the start of a variable's * active searches list; varPtr is the key. */ /* * The thread-specific data ekeko: cache pointers or values that * (a) do not change during the thread's lifetime * (b) require access to TSD to determine at runtime * (c) are accessed very often (e.g., at each command call) * * Note that these are the same for all interps in the same thread. They * just have to be initialised for the thread's master interp, slaves * inherit the value. * * They are used by the macros defined below. */ AllocCache *allocCache; void *pendingObjDataPtr; /* Pointer to the Cache and PendingObjData * structs for this interp's thread; see * tclObj.c and tclThreadAlloc.c */ int *asyncReadyPtr; /* Pointer to the asyncReady indicator for * this interp's thread; see tclAsync.c */ /* * The pointer to the object system root ekeko. c.f. TIP #257. */ void *objectFoundation; /* Pointer to the Foundation structure of the * object system, which contains things like * references to key namespaces. See * tclOOInt.h and tclOO.c for real definition * and setup. */ struct NRE_callback *deferredCallbacks; /* Callbacks that are set previous to a call * to some Eval function but that actually * belong to the command that is about to be * called - i.e., they should be run *before* * any tailcall is invoked. */ /* * TIP #285, Script cancellation support. */ Tcl_AsyncHandler asyncCancel; /* Async handler token for Tcl_CancelEval. */ Tcl_Obj *asyncCancelMsg; /* Error message set by async cancel handler * for the propagation of arbitrary Tcl * errors. This information, if present * (asyncCancelMsg not NULL), takes precedence * over the default error messages returned by * a script cancellation operation. */ /* * TIP #348 IMPLEMENTATION - Substituted error stack */ Tcl_Obj *errorStack; /* [info errorstack] value (as a Tcl_Obj). */ Tcl_Obj *upLiteral; /* "UP" literal for [info errorstack] */ Tcl_Obj *callLiteral; /* "CALL" literal for [info errorstack] */ Tcl_Obj *innerLiteral; /* "INNER" literal for [info errorstack] */ Tcl_Obj *innerContext; /* cached list for fast reallocation */ int resetErrorStack; /* controls cleaning up of ::errorStack */ #ifdef TCL_COMPILE_STATS /* * Statistical information about the bytecode compiler and interpreter's * operation. This should be the last field of Interp. */ ByteCodeStats stats; /* Holds compilation and execution statistics * for this interpreter. */ #endif /* TCL_COMPILE_STATS */ } Interp; /* * Macros that use the TSD-ekeko. */ #define TclAsyncReady(iPtr) \ *((iPtr)->asyncReadyPtr) /* * Macros for script cancellation support (TIP #285). */ #define TclCanceled(iPtr) \ (((iPtr)->flags & CANCELED) || ((iPtr)->flags & TCL_CANCEL_UNWIND)) #define TclSetCancelFlags(iPtr, cancelFlags) \ (iPtr)->flags |= CANCELED; \ if ((cancelFlags) & TCL_CANCEL_UNWIND) { \ (iPtr)->flags |= TCL_CANCEL_UNWIND; \ } #define TclUnsetCancelFlags(iPtr) \ (iPtr)->flags &= (~(CANCELED | TCL_CANCEL_UNWIND)) /* * Macros for splicing into and out of doubly linked lists. They assume * existence of struct items 'prevPtr' and 'nextPtr'. * * a = element to add or remove. * b = list head. * * TclSpliceIn adds to the head of the list. */ #define TclSpliceIn(a,b) \ (a)->nextPtr = (b); \ if ((b) != NULL) { \ (b)->prevPtr = (a); \ } \ (a)->prevPtr = NULL, (b) = (a); #define TclSpliceOut(a,b) \ if ((a)->prevPtr != NULL) { \ (a)->prevPtr->nextPtr = (a)->nextPtr; \ } else { \ (b) = (a)->nextPtr; \ } \ if ((a)->nextPtr != NULL) { \ (a)->nextPtr->prevPtr = (a)->prevPtr; \ } /* * EvalFlag bits for Interp structures: * * TCL_ALLOW_EXCEPTIONS 1 means it's OK for the script to terminate with a * code other than TCL_OK or TCL_ERROR; 0 means codes * other than these should be turned into errors. */ #define TCL_ALLOW_EXCEPTIONS 0x04 #define TCL_EVAL_FILE 0x02 #define TCL_EVAL_SOURCE_IN_FRAME 0x10 #define TCL_EVAL_NORESOLVE 0x20 /* * Flag bits for Interp structures: * * DELETED: Non-zero means the interpreter has been deleted: * don't process any more commands for it, and destroy * the structure as soon as all nested invocations of * Tcl_Eval are done. * ERR_ALREADY_LOGGED: Non-zero means information has already been logged in * iPtr->errorInfo for the current Tcl_Eval instance, so * Tcl_Eval needn't log it (used to implement the "error * message log" command). * DONT_COMPILE_CMDS_INLINE: Non-zero means that the bytecode compiler should * not compile any commands into an inline sequence of * instructions. This is set 1, for example, when command * traces are requested. * RAND_SEED_INITIALIZED: Non-zero means that the randSeed value of the interp * has not be initialized. This is set 1 when we first * use the rand() or srand() functions. * SAFE_INTERP: Non zero means that the current interp is a safe * interp (i.e. it has only the safe commands installed, * less priviledge than a regular interp). * INTERP_DEBUG_FRAME: Used for switching on various extra interpreter * debug/info mechanisms (e.g. info frame eval/uplevel * tracing) which are performance intensive. * INTERP_TRACE_IN_PROGRESS: Non-zero means that an interp trace is currently * active; so no further trace callbacks should be * invoked. * INTERP_ALTERNATE_WRONG_ARGS: Used for listing second and subsequent forms * of the wrong-num-args string in Tcl_WrongNumArgs. * Makes it append instead of replacing and uses * different intermediate text. * CANCELED: Non-zero means that the script in progress should be * canceled as soon as possible. This can be checked by * extensions (and the core itself) by calling * Tcl_Canceled and checking if TCL_ERROR is returned. * This is a one-shot flag that is reset immediately upon * being detected; however, if the TCL_CANCEL_UNWIND flag * is set Tcl_Canceled will continue to report that the * script in progress has been canceled thereby allowing * the evaluation stack for the interp to be fully * unwound. * * WARNING: For the sake of some extensions that have made use of former * internal values, do not re-use the flag values 2 (formerly ERR_IN_PROGRESS) * or 8 (formerly ERROR_CODE_SET). */ #define DELETED 1 #define ERR_ALREADY_LOGGED 4 #define INTERP_DEBUG_FRAME 0x10 #define DONT_COMPILE_CMDS_INLINE 0x20 #define RAND_SEED_INITIALIZED 0x40 #define SAFE_INTERP 0x80 #define INTERP_TRACE_IN_PROGRESS 0x200 #define INTERP_ALTERNATE_WRONG_ARGS 0x400 #define ERR_LEGACY_COPY 0x800 #define CANCELED 0x1000 /* * Maximum number of levels of nesting permitted in Tcl commands (used to * catch infinite recursion). */ #define MAX_NESTING_DEPTH 1000 /* * The macro below is used to modify a "char" value (e.g. by casting it to an * unsigned character) so that it can be used safely with macros such as * isspace. */ #define UCHAR(c) ((unsigned char) (c)) /* * This macro is used to properly align the memory allocated by Tcl, giving * the same alignment as the native malloc. */ #if defined(__APPLE__) #define TCL_ALLOCALIGN 16 #else #define TCL_ALLOCALIGN (2*sizeof(void *)) #endif /* * This macro is used to determine the offset needed to safely allocate any * data structure in memory. Given a starting offset or size, it "rounds up" * or "aligns" the offset to the next 8-byte boundary so that any data * structure can be placed at the resulting offset without fear of an * alignment error. * * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce the * wrong result on platforms that allocate addresses that are divisible by 4 * or 2. Only use it for offsets or sizes. * * This macro is only used by tclCompile.c in the core (Bug 926445). It * however not be made file static, as extensions that touch bytecodes * (notably tbcload) require it. */ #define TCL_ALIGN(x) (((int)(x) + 7) & ~7) /* * The following enum values are used to specify the runtime platform setting * of the tclPlatform variable. */ typedef enum { TCL_PLATFORM_UNIX = 0, /* Any Unix-like OS. */ TCL_PLATFORM_WINDOWS = 2 /* Any Microsoft Windows OS. */ } TclPlatformType; /* * The following enum values are used to indicate the translation of a Tcl * channel. Declared here so that each platform can define * TCL_PLATFORM_TRANSLATION to the native translation on that platform. */ typedef enum TclEolTranslation { TCL_TRANSLATE_AUTO, /* Eol == \r, \n and \r\n. */ TCL_TRANSLATE_CR, /* Eol == \r. */ TCL_TRANSLATE_LF, /* Eol == \n. */ TCL_TRANSLATE_CRLF /* Eol == \r\n. */ } TclEolTranslation; /* * Flags for TclInvoke: * * TCL_INVOKE_HIDDEN Invoke a hidden command; if not set, invokes * an exposed command. * TCL_INVOKE_NO_UNKNOWN If set, "unknown" is not invoked if the * command to be invoked is not found. Only has * an effect if invoking an exposed command, * i.e. if TCL_INVOKE_HIDDEN is not also set. * TCL_INVOKE_NO_TRACEBACK Does not record traceback information if the * invoked command returns an error. Used if the * caller plans on recording its own traceback * information. */ #define TCL_INVOKE_HIDDEN (1<<0) #define TCL_INVOKE_NO_UNKNOWN (1<<1) #define TCL_INVOKE_NO_TRACEBACK (1<<2) /* * The structure used as the internal representation of Tcl list objects. This * struct is grown (reallocated and copied) as necessary to hold all the * list's element pointers. The struct might contain more slots than currently * used to hold all element pointers. This is done to make append operations * faster. */ typedef struct List { int refCount; int maxElemCount; /* Total number of element array slots. */ int elemCount; /* Current number of list elements. */ int canonicalFlag; /* Set if the string representation was * derived from the list representation. May * be ignored if there is no string rep at * all.*/ Tcl_Obj *elements; /* First list element; the struct is grown to * accomodate all elements. */ } List; #define LIST_MAX \ (1 + (int)(((size_t)UINT_MAX - sizeof(List))/sizeof(Tcl_Obj *))) #define LIST_SIZE(numElems) \ (unsigned)(sizeof(List) + (((numElems) - 1) * sizeof(Tcl_Obj *))) /* * Macro used to get the elements of a list object. */ #define ListRepPtr(listPtr) \ ((List *) (listPtr)->internalRep.twoPtrValue.ptr1) #define ListSetIntRep(objPtr, listRepPtr) \ (objPtr)->internalRep.twoPtrValue.ptr1 = (void *)(listRepPtr), \ (objPtr)->internalRep.twoPtrValue.ptr2 = NULL, \ (listRepPtr)->refCount++, \ (objPtr)->typePtr = &tclListType #define ListObjGetElements(listPtr, objc, objv) \ ((objv) = &(ListRepPtr(listPtr)->elements), \ (objc) = ListRepPtr(listPtr)->elemCount) #define ListObjLength(listPtr, len) \ ((len) = ListRepPtr(listPtr)->elemCount) #define ListObjIsCanonical(listPtr) \ (((listPtr)->bytes == NULL) || ListRepPtr(listPtr)->canonicalFlag) #define TclListObjGetElements(interp, listPtr, objcPtr, objvPtr) \ (((listPtr)->typePtr == &tclListType) \ ? ((ListObjGetElements((listPtr), *(objcPtr), *(objvPtr))), TCL_OK)\ : Tcl_ListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr))) #define TclListObjLength(interp, listPtr, lenPtr) \ (((listPtr)->typePtr == &tclListType) \ ? ((ListObjLength((listPtr), *(lenPtr))), TCL_OK)\ : Tcl_ListObjLength((interp), (listPtr), (lenPtr))) #define TclListObjIsCanonical(listPtr) \ (((listPtr)->typePtr == &tclListType) ? ListObjIsCanonical((listPtr)) : 0) /* * Modes for collecting (or not) in the implementations of TclNRForeachCmd, * TclNRLmapCmd and their compilations. */ #define TCL_EACH_KEEP_NONE 0 /* Discard iteration result like [foreach] */ #define TCL_EACH_COLLECT 1 /* Collect iteration result like [lmap] */ /* * Macros providing a faster path to integers: Tcl_GetLongFromObj everywhere, * Tcl_GetIntFromObj and TclGetIntForIndex on platforms where longs are ints. * * WARNING: these macros eval their args more than once. */ #define TclGetLongFromObj(interp, objPtr, longPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? ((*(longPtr) = (objPtr)->internalRep.longValue), TCL_OK) \ : Tcl_GetLongFromObj((interp), (objPtr), (longPtr))) #if (LONG_MAX == INT_MAX) #define TclGetIntFromObj(interp, objPtr, intPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? ((*(intPtr) = (objPtr)->internalRep.longValue), TCL_OK) \ : Tcl_GetIntFromObj((interp), (objPtr), (intPtr))) #define TclGetIntForIndexM(interp, objPtr, endValue, idxPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? ((*(idxPtr) = (objPtr)->internalRep.longValue), TCL_OK) \ : TclGetIntForIndex((interp), (objPtr), (endValue), (idxPtr))) #else #define TclGetIntFromObj(interp, objPtr, intPtr) \ Tcl_GetIntFromObj((interp), (objPtr), (intPtr)) #define TclGetIntForIndexM(interp, objPtr, ignore, idxPtr) \ TclGetIntForIndex(interp, objPtr, ignore, idxPtr) #endif /* * Macro used to save a function call for common uses of * Tcl_GetWideIntFromObj(). The ANSI C "prototype" is: * * MODULE_SCOPE int TclGetWideIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, * Tcl_WideInt *wideIntPtr); */ #ifdef TCL_WIDE_INT_IS_LONG #define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \ (((objPtr)->typePtr == &tclIntType) \ ? (*(wideIntPtr) = (Tcl_WideInt) \ ((objPtr)->internalRep.longValue), TCL_OK) : \ Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr))) #else /* !TCL_WIDE_INT_IS_LONG */ #define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \ (((objPtr)->typePtr == &tclWideIntType) \ ? (*(wideIntPtr) = (objPtr)->internalRep.wideValue, TCL_OK) : \ ((objPtr)->typePtr == &tclIntType) \ ? (*(wideIntPtr) = (Tcl_WideInt) \ ((objPtr)->internalRep.longValue), TCL_OK) : \ Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr))) #endif /* TCL_WIDE_INT_IS_LONG */ /* * Flag values for TclTraceDictPath(). * * DICT_PATH_READ indicates that all entries on the path must exist but no * updates will be needed. * * DICT_PATH_UPDATE indicates that we are going to be doing an update at the * tip of the path, so duplication of shared objects should be done along the * way. * * DICT_PATH_EXISTS indicates that we are performing an existance test and a * lookup failure should therefore not be an error. If (and only if) this flag * is set, TclTraceDictPath() will return the special value * DICT_PATH_NON_EXISTENT if the path is not traceable. * * DICT_PATH_CREATE (which also requires the DICT_PATH_UPDATE bit to be set) * indicates that we are to create non-existant dictionaries on the path. */ #define DICT_PATH_READ 0 #define DICT_PATH_UPDATE 1 #define DICT_PATH_EXISTS 2 #define DICT_PATH_CREATE 5 #define DICT_PATH_NON_EXISTENT ((Tcl_Obj *) (void *) 1) /* *---------------------------------------------------------------- * Data structures related to the filesystem internals *---------------------------------------------------------------- */ /* * The version_2 filesystem is private to Tcl. As and when these changes have * been thoroughly tested and investigated a new public filesystem interface * will be released. The aim is more versatile virtual filesystem interfaces, * more efficiency in 'path' manipulation and usage, and cleaner filesystem * code internally. */ #define TCL_FILESYSTEM_VERSION_2 ((Tcl_FSVersion) 0x2) typedef ClientData (TclFSGetCwdProc2)(ClientData clientData); typedef int (Tcl_FSLoadFileProc2) (Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr, int flags); /* * The following types are used for getting and storing platform-specific file * attributes in tclFCmd.c and the various platform-versions of that file. * This is done to have as much common code as possible in the file attributes * code. For more information about the callbacks, see TclFileAttrsCmd in * tclFCmd.c. */ typedef int (TclGetFileAttrProc)(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attrObjPtrPtr); typedef int (TclSetFileAttrProc)(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj *attrObjPtr); typedef struct TclFileAttrProcs { TclGetFileAttrProc *getProc;/* The procedure for getting attrs. */ TclSetFileAttrProc *setProc;/* The procedure for setting attrs. */ } TclFileAttrProcs; /* * Opaque handle used in pipeline routines to encapsulate platform-dependent * state. */ typedef struct TclFile_ *TclFile; /* * The "globParameters" argument of the function TclGlob is an or'ed * combination of the following values: */ #define TCL_GLOBMODE_NO_COMPLAIN 1 #define TCL_GLOBMODE_JOIN 2 #define TCL_GLOBMODE_DIR 4 #define TCL_GLOBMODE_TAILS 8 typedef enum Tcl_PathPart { TCL_PATH_DIRNAME, TCL_PATH_TAIL, TCL_PATH_EXTENSION, TCL_PATH_ROOT } Tcl_PathPart; /* *---------------------------------------------------------------- * Data structures related to obsolete filesystem hooks *---------------------------------------------------------------- */ typedef int (TclStatProc_)(const char *path, struct stat *buf); typedef int (TclAccessProc_)(const char *path, int mode); typedef Tcl_Channel (TclOpenFileChannelProc_)(Tcl_Interp *interp, const char *fileName, const char *modeString, int permissions); /* *---------------------------------------------------------------- * Data structures related to procedures *---------------------------------------------------------------- */ typedef Tcl_CmdProc *TclCmdProcType; typedef Tcl_ObjCmdProc *TclObjCmdProcType; /* *---------------------------------------------------------------- * Data structures for process-global values. *---------------------------------------------------------------- */ typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, int *lengthPtr, Tcl_Encoding *encodingPtr); /* * A ProcessGlobalValue struct exists for each internal value in Tcl that is * to be shared among several threads. Each thread sees a (Tcl_Obj) copy of * the value, and the master is kept as a counted string, with epoch and mutex * control. Each ProcessGlobalValue struct should be a static variable in some * file. */ typedef struct ProcessGlobalValue { int epoch; /* Epoch counter to detect changes in the * master value. */ int numBytes; /* Length of the master string. */ char *value; /* The master string value. */ Tcl_Encoding encoding; /* system encoding when master string was * initialized. */ TclInitProcessGlobalValueProc *proc; /* A procedure to initialize the master string * copy when a "get" request comes in before * any "set" request has been received. */ Tcl_Mutex mutex; /* Enforce orderly access from multiple * threads. */ Tcl_ThreadDataKey key; /* Key for per-thread data holding the * (Tcl_Obj) copy for each thread. */ } ProcessGlobalValue; /* *---------------------------------------------------------------------- * Flags for TclParseNumber *---------------------------------------------------------------------- */ #define TCL_PARSE_DECIMAL_ONLY 1 /* Leading zero doesn't denote octal or * hex. */ #define TCL_PARSE_OCTAL_ONLY 2 /* Parse octal even without prefix. */ #define TCL_PARSE_HEXADECIMAL_ONLY 4 /* Parse hexadecimal even without prefix. */ #define TCL_PARSE_INTEGER_ONLY 8 /* Disable floating point parsing. */ #define TCL_PARSE_SCAN_PREFIXES 16 /* Use [scan] rules dealing with 0? * prefixes. */ #define TCL_PARSE_NO_WHITESPACE 32 /* Reject leading/trailing whitespace. */ #define TCL_PARSE_BINARY_ONLY 64 /* Parse binary even without prefix. */ /* *---------------------------------------------------------------------- * Type values TclGetNumberFromObj *---------------------------------------------------------------------- */ #define TCL_NUMBER_LONG 1 #define TCL_NUMBER_WIDE 2 #define TCL_NUMBER_BIG 3 #define TCL_NUMBER_DOUBLE 4 #define TCL_NUMBER_NAN 5 /* *---------------------------------------------------------------- * Variables shared among Tcl modules but not used by the outside world. *---------------------------------------------------------------- */ 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; /* * TIP #233 (Virtualized Time) * Data for the time hooks, if any. */ MODULE_SCOPE Tcl_GetTimeProc *tclGetTimeProcPtr; MODULE_SCOPE Tcl_ScaleTimeProc *tclScaleTimeProcPtr; MODULE_SCOPE ClientData tclTimeClientData; /* * Variables denoting the Tcl object types defined in the core. */ MODULE_SCOPE const Tcl_ObjType tclBignumType; MODULE_SCOPE const Tcl_ObjType tclBooleanType; MODULE_SCOPE const Tcl_ObjType tclByteArrayType; MODULE_SCOPE const Tcl_ObjType tclByteCodeType; MODULE_SCOPE const Tcl_ObjType tclDoubleType; MODULE_SCOPE const Tcl_ObjType tclEndOffsetType; MODULE_SCOPE const Tcl_ObjType tclIntType; MODULE_SCOPE const Tcl_ObjType tclListType; MODULE_SCOPE const Tcl_ObjType tclDictType; MODULE_SCOPE const Tcl_ObjType tclProcBodyType; MODULE_SCOPE const Tcl_ObjType tclStringType; MODULE_SCOPE const Tcl_ObjType tclArraySearchType; MODULE_SCOPE const Tcl_ObjType tclEnsembleCmdType; #ifndef TCL_WIDE_INT_IS_LONG MODULE_SCOPE const Tcl_ObjType tclWideIntType; #endif MODULE_SCOPE const Tcl_ObjType tclRegexpType; MODULE_SCOPE Tcl_ObjType tclCmdNameType; /* * Variables denoting the hash key types defined in the core. */ MODULE_SCOPE const Tcl_HashKeyType tclArrayHashKeyType; MODULE_SCOPE const Tcl_HashKeyType tclOneWordHashKeyType; MODULE_SCOPE const Tcl_HashKeyType tclStringHashKeyType; MODULE_SCOPE const Tcl_HashKeyType tclObjHashKeyType; /* * The head of the list of free Tcl objects, and the total number of Tcl * objects ever allocated and freed. */ MODULE_SCOPE Tcl_Obj * tclFreeObjList; #ifdef TCL_COMPILE_STATS MODULE_SCOPE long tclObjsAlloced; MODULE_SCOPE long tclObjsFreed; #define TCL_MAX_SHARED_OBJ_STATS 5 MODULE_SCOPE long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS]; #endif /* TCL_COMPILE_STATS */ /* * Pointer to a heap-allocated string of length zero that the Tcl core uses as * the value of an empty string representation for an object. This value is * shared by all new objects allocated by Tcl_NewObj. */ MODULE_SCOPE char * tclEmptyStringRep; MODULE_SCOPE char tclEmptyString; /* *---------------------------------------------------------------- * Procedures shared among Tcl modules but not used by the outside world, * introduced by/for NRE. *---------------------------------------------------------------- */ MODULE_SCOPE Tcl_ObjCmdProc TclNRApplyObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNREvalObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRCatchObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRExprObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRForObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRForeachCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRIfObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRLmapCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRSourceObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRSubstObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRSwitchObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRTryObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRUplevelObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRWhileObjCmd; MODULE_SCOPE Tcl_NRPostProc TclNRForIterCallback; MODULE_SCOPE Tcl_NRPostProc TclNRCoroutineActivateCallback; MODULE_SCOPE Tcl_ObjCmdProc TclNRTailcallObjCmd; MODULE_SCOPE Tcl_NRPostProc TclNRTailcallEval; MODULE_SCOPE Tcl_ObjCmdProc TclNRCoroutineObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldmObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldToObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRInvoke; MODULE_SCOPE void TclSetTailcall(Tcl_Interp *interp, Tcl_Obj *tailcallPtr); MODULE_SCOPE void TclPushTailcallPoint(Tcl_Interp *interp); /* These two can be considered for the public api */ MODULE_SCOPE void TclMarkTailcall(Tcl_Interp *interp); MODULE_SCOPE void TclSkipTailcall(Tcl_Interp *interp); /* * This structure holds the data for the various iteration callbacks used to * NRE the 'for' and 'while' commands. We need a separate structure because we * have more than the 4 client data entries we can provide directly thorugh * the callback API. It is the 'word' information which puts us over the * limit. It is needed because the loop body is argument 4 of 'for' and * argument 2 of 'while'. Not providing the correct index confuses the #280 * code. We TclSmallAlloc/Free this. */ typedef struct ForIterData { Tcl_Obj *cond; /* Loop condition expression. */ Tcl_Obj *body; /* Loop body. */ Tcl_Obj *next; /* Loop step script, NULL for 'while'. */ const char *msg; /* Error message part. */ int word; /* Index of the body script in the command */ } ForIterData; /* TIP #357 - Structure doing the bookkeeping of handles for Tcl_LoadFile * and Tcl_FindSymbol. This structure corresponds to an opaque * typedef in tcl.h */ typedef void* TclFindSymbolProc(Tcl_Interp* interp, Tcl_LoadHandle loadHandle, const char* symbol); struct Tcl_LoadHandle_ { ClientData clientData; /* Client data is the load handle in the * native filesystem if a module was loaded * there, or an opaque pointer to a structure * for further bookkeeping on load-from-VFS * and load-from-memory */ TclFindSymbolProc* findSymbolProcPtr; /* Procedure that resolves symbols in a * loaded module */ Tcl_FSUnloadFileProc* unloadFileProcPtr; /* Procedure that unloads a loaded module */ }; /* Flags for conversion of doubles to digit strings */ #define TCL_DD_SHORTEST 0x4 /* Use the shortest possible string */ #define TCL_DD_STEELE 0x5 /* Use the original Steele&White algorithm */ #define TCL_DD_E_FORMAT 0x2 /* Use a fixed-length string of digits, * suitable for E format*/ #define TCL_DD_F_FORMAT 0x3 /* Use a fixed number of digits after the * decimal point, suitable for F format */ #define TCL_DD_SHORTEN_FLAG 0x4 /* Allow return of a shorter digit string * if it converts losslessly */ #define TCL_DD_NO_QUICK 0x8 /* Debug flag: forbid quick FP conversion */ #define TCL_DD_CONVERSION_TYPE_MASK 0x3 /* Mask to isolate the conversion type */ #define TCL_DD_STEELE0 0x1 /* 'Steele&White' after masking */ #define TCL_DD_SHORTEST0 0x0 /* 'Shortest possible' after masking */ /* *---------------------------------------------------------------- * Procedures shared among Tcl modules but not used by the outside world: *---------------------------------------------------------------- */ MODULE_SCOPE void TclAppendBytesToByteArray(Tcl_Obj *objPtr, const unsigned char *bytes, int len); MODULE_SCOPE int TclNREvalCmd(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); MODULE_SCOPE void TclAdvanceContinuations(int *line, int **next, int loc); MODULE_SCOPE void TclAdvanceLines(int *line, const char *start, const char *end); MODULE_SCOPE void TclArgumentEnter(Tcl_Interp *interp, Tcl_Obj *objv[], int objc, CmdFrame *cf); MODULE_SCOPE void TclArgumentRelease(Tcl_Interp *interp, Tcl_Obj *objv[], int objc); MODULE_SCOPE void TclArgumentBCEnter(Tcl_Interp *interp, Tcl_Obj *objv[], int objc, void *codePtr, CmdFrame *cfPtr, int cmd, int pc); MODULE_SCOPE void TclArgumentBCRelease(Tcl_Interp *interp, CmdFrame *cfPtr); MODULE_SCOPE void TclArgumentGet(Tcl_Interp *interp, Tcl_Obj *obj, CmdFrame **cfPtrPtr, int *wordPtr); MODULE_SCOPE int TclArraySet(Tcl_Interp *interp, Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj); MODULE_SCOPE double TclBignumToDouble(const mp_int *bignum); MODULE_SCOPE int TclByteArrayMatch(const unsigned char *string, int strLen, const unsigned char *pattern, int ptnLen, int flags); MODULE_SCOPE double TclCeil(const mp_int *a); MODULE_SCOPE void TclChannelPreserve(Tcl_Channel chan); MODULE_SCOPE void TclChannelRelease(Tcl_Channel chan); MODULE_SCOPE int TclCheckBadOctal(Tcl_Interp *interp, const char *value); MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp, Tcl_Channel chan); MODULE_SCOPE Tcl_ObjCmdProc TclChannelNamesCmd; MODULE_SCOPE int TclClearRootEnsemble(ClientData data[], Tcl_Interp *interp, int result); MODULE_SCOPE ContLineLoc *TclContinuationsEnter(Tcl_Obj *objPtr, int num, int *loc); MODULE_SCOPE void TclContinuationsEnterDerived(Tcl_Obj *objPtr, int start, int *clNext); MODULE_SCOPE ContLineLoc *TclContinuationsGet(Tcl_Obj *objPtr); MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr, Tcl_Obj *originObjPtr); MODULE_SCOPE int TclConvertElement(const char *src, int length, char *dst, int flags); MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr); MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp, const char *dict, int dictLength, const char **elementPtr, const char **nextPtr, int *sizePtr, int *literalPtr); /* TIP #280 - Modified token based evulation, with line information. */ MODULE_SCOPE int TclEvalEx(Tcl_Interp *interp, const char *script, int numBytes, int flags, int line, int *clNextOuter, const char *outerScript); MODULE_SCOPE Tcl_ObjCmdProc TclFileAttrsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileCopyCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileDeleteCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileLinkCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileMakeDirsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileReadLinkCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileRenameCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileTemporaryCmd; MODULE_SCOPE void TclCreateLateExitHandler(Tcl_ExitProc *proc, ClientData clientData); MODULE_SCOPE void TclDeleteLateExitHandler(Tcl_ExitProc *proc, ClientData clientData); MODULE_SCOPE char * TclDStringAppendObj(Tcl_DString *dsPtr, Tcl_Obj *objPtr); MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr, Tcl_DString *toAppendPtr); MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr); MODULE_SCOPE void TclFinalizeAllocSubsystem(void); MODULE_SCOPE void TclFinalizeAsync(void); MODULE_SCOPE void TclFinalizeDoubleConversion(void); MODULE_SCOPE void TclFinalizeEncodingSubsystem(void); MODULE_SCOPE void TclFinalizeEnvironment(void); MODULE_SCOPE void TclFinalizeEvaluation(void); MODULE_SCOPE void TclFinalizeExecution(void); MODULE_SCOPE void TclFinalizeIOSubsystem(void); MODULE_SCOPE void TclFinalizeFilesystem(void); MODULE_SCOPE void TclResetFilesystem(void); MODULE_SCOPE void TclFinalizeLoad(void); MODULE_SCOPE void TclFinalizeLock(void); MODULE_SCOPE void TclFinalizeMemorySubsystem(void); MODULE_SCOPE void TclFinalizeNotifier(void); MODULE_SCOPE void TclFinalizeObjects(void); MODULE_SCOPE void TclFinalizePreserve(void); MODULE_SCOPE void TclFinalizeSynchronization(void); MODULE_SCOPE void TclFinalizeThreadAlloc(void); MODULE_SCOPE void TclFinalizeThreadAllocThread(void); MODULE_SCOPE void TclFinalizeThreadData(int quick); MODULE_SCOPE void TclFinalizeThreadObjects(void); MODULE_SCOPE double TclFloor(const mp_int *a); MODULE_SCOPE void TclFormatNaN(double value, char *buffer); MODULE_SCOPE int TclFSFileAttrIndex(Tcl_Obj *pathPtr, const char *attributeName, int *indexPtr); MODULE_SCOPE int TclNREvalFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *encodingName); MODULE_SCOPE void TclFSUnloadTempFile(Tcl_LoadHandle loadHandle); MODULE_SCOPE int * TclGetAsyncReadyPtr(void); MODULE_SCOPE Tcl_Obj * TclGetBgErrorHandler(Tcl_Interp *interp); MODULE_SCOPE int TclGetChannelFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Channel *chanPtr, int *modePtr, int flags); MODULE_SCOPE int TclGetCompletionCodeFromObj(Tcl_Interp *interp, Tcl_Obj *value, int *code); MODULE_SCOPE int TclGetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, ClientData *clientDataPtr, int *typePtr); MODULE_SCOPE int TclGetOpenModeEx(Tcl_Interp *interp, const char *modeString, int *seekFlagPtr, int *binaryPtr); MODULE_SCOPE Tcl_Obj * TclGetProcessGlobalValue(ProcessGlobalValue *pgvPtr); 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 TclGlob(Tcl_Interp *interp, char *pattern, Tcl_Obj *unquotedPrefix, int globFlags, Tcl_GlobTypeData *types); MODULE_SCOPE int TclIncrObj(Tcl_Interp *interp, Tcl_Obj *valuePtr, Tcl_Obj *incrPtr); MODULE_SCOPE Tcl_Obj * TclIncrObjVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, int flags); MODULE_SCOPE int TclInfoExistsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclInfoCoroutineCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE Tcl_Obj * TclInfoFrame(Tcl_Interp *interp, CmdFrame *framePtr); MODULE_SCOPE int TclInfoGlobalsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclInfoLocalsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclInfoVarsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE void TclInitAlloc(void); MODULE_SCOPE void TclInitDbCkalloc(void); MODULE_SCOPE void TclInitDoubleConversion(void); MODULE_SCOPE void TclInitEmbeddedConfigurationInformation( Tcl_Interp *interp); MODULE_SCOPE void TclInitEncodingSubsystem(void); MODULE_SCOPE void TclInitIOSubsystem(void); MODULE_SCOPE void TclInitLimitSupport(Tcl_Interp *interp); MODULE_SCOPE void TclInitNamespaceSubsystem(void); MODULE_SCOPE void TclInitNotifier(void); MODULE_SCOPE void TclInitObjSubsystem(void); MODULE_SCOPE void TclInitSubsystems(void); MODULE_SCOPE int TclInterpReady(Tcl_Interp *interp); MODULE_SCOPE int TclIsSpaceProc(char byte); MODULE_SCOPE int TclIsBareword(char byte); MODULE_SCOPE Tcl_Obj * TclJoinPath(int elements, Tcl_Obj * const objv[]); MODULE_SCOPE int TclJoinThread(Tcl_ThreadId id, int *result); MODULE_SCOPE void TclLimitRemoveAllHandlers(Tcl_Interp *interp); MODULE_SCOPE Tcl_Obj * TclLindexList(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *argPtr); MODULE_SCOPE Tcl_Obj * TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr, int indexCount, Tcl_Obj *const indexArray[]); /* TIP #280 */ MODULE_SCOPE void TclListLines(Tcl_Obj *listObj, int line, int n, int *lines, Tcl_Obj *const *elems); MODULE_SCOPE Tcl_Obj * TclListObjCopy(Tcl_Interp *interp, Tcl_Obj *listPtr); MODULE_SCOPE Tcl_Obj * TclLsetList(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *indexPtr, Tcl_Obj *valuePtr); MODULE_SCOPE Tcl_Obj * TclLsetFlat(Tcl_Interp *interp, Tcl_Obj *listPtr, int indexCount, Tcl_Obj *const indexArray[], Tcl_Obj *valuePtr); MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name, const EnsembleImplMap map[]); MODULE_SCOPE int TclMaxListLength(const char *bytes, int numBytes, const char **endPtr); MODULE_SCOPE int TclMergeReturnOptions(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], Tcl_Obj **optionsPtrPtr, int *codePtr, int *levelPtr); MODULE_SCOPE Tcl_Obj * TclNoErrorStack(Tcl_Interp *interp, Tcl_Obj *options); MODULE_SCOPE int TclNokia770Doubles(void); MODULE_SCOPE void TclNsDecrRefCount(Namespace *nsPtr); MODULE_SCOPE void TclObjVarErrMsg(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const char *operation, const char *reason, int index); MODULE_SCOPE int TclObjInvokeNamespace(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], Tcl_Namespace *nsPtr, int flags); MODULE_SCOPE int TclObjUnsetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); MODULE_SCOPE int TclParseBackslash(const char *src, int numBytes, int *readPtr, char *dst); MODULE_SCOPE int TclParseHex(const char *src, int numBytes, int *resultPtr); MODULE_SCOPE int TclParseNumber(Tcl_Interp *interp, Tcl_Obj *objPtr, const char *expected, const char *bytes, int numBytes, const char **endPtrPtr, int flags); MODULE_SCOPE void TclParseInit(Tcl_Interp *interp, const char *string, int numBytes, Tcl_Parse *parsePtr); MODULE_SCOPE int TclParseAllWhiteSpace(const char *src, int numBytes); 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 * TclNewFSPathObj(Tcl_Obj *dirPtr, const char *addStrRep, int len); MODULE_SCOPE int TclpDeleteFile(const void *path); MODULE_SCOPE void TclpFinalizeCondition(Tcl_Condition *condPtr); MODULE_SCOPE void TclpFinalizeMutex(Tcl_Mutex *mutexPtr); MODULE_SCOPE void TclpFinalizePipes(void); MODULE_SCOPE void TclpFinalizeSockets(void); MODULE_SCOPE int TclCreateSocketAddress(Tcl_Interp *interp, struct addrinfo **addrlist, const char *host, int port, int willBind, const char **errorMsgPtr); MODULE_SCOPE int TclpThreadCreate(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, ClientData clientData, int stackSize, int flags); MODULE_SCOPE int TclpFindVariable(const char *name, int *lengthPtr); MODULE_SCOPE void TclpInitLibraryPath(char **valuePtr, int *lengthPtr, Tcl_Encoding *encodingPtr); MODULE_SCOPE void TclpInitLock(void); MODULE_SCOPE void TclpInitPlatform(void); MODULE_SCOPE void TclpInitUnlock(void); MODULE_SCOPE Tcl_Obj * TclpObjListVolumes(void); MODULE_SCOPE void TclpMasterLock(void); MODULE_SCOPE void TclpMasterUnlock(void); MODULE_SCOPE int TclpMatchFiles(Tcl_Interp *interp, char *separators, Tcl_DString *dirPtr, char *pattern, char *tail); MODULE_SCOPE int TclpObjNormalizePath(Tcl_Interp *interp, Tcl_Obj *pathPtr, int nextCheckpoint); MODULE_SCOPE void TclpNativeJoinPath(Tcl_Obj *prefix, const char *joining); MODULE_SCOPE Tcl_Obj * TclpNativeSplitPath(Tcl_Obj *pathPtr, int *lenPtr); MODULE_SCOPE Tcl_PathType TclpGetNativePathType(Tcl_Obj *pathPtr, int *driveNameLengthPtr, Tcl_Obj **driveNameRef); MODULE_SCOPE int TclCrossFilesystemCopy(Tcl_Interp *interp, Tcl_Obj *source, Tcl_Obj *target); MODULE_SCOPE int TclpMatchInDirectory(Tcl_Interp *interp, Tcl_Obj *resultPtr, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types); MODULE_SCOPE ClientData TclpGetNativeCwd(ClientData clientData); MODULE_SCOPE Tcl_FSDupInternalRepProc TclNativeDupInternalRep; MODULE_SCOPE Tcl_Obj * TclpObjLink(Tcl_Obj *pathPtr, Tcl_Obj *toPtr, int linkType); 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 Tcl_Obj * TclPathPart(Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_PathPart portion); MODULE_SCOPE char * TclpReadlink(const char *fileName, Tcl_DString *linkPtr); MODULE_SCOPE void TclpSetInterfaces(void); MODULE_SCOPE void TclpSetVariables(Tcl_Interp *interp); MODULE_SCOPE void * TclThreadStorageKeyGet(Tcl_ThreadDataKey *keyPtr); MODULE_SCOPE void TclThreadStorageKeySet(Tcl_ThreadDataKey *keyPtr, void *data); MODULE_SCOPE void TclpThreadExit(int status); MODULE_SCOPE void TclRememberCondition(Tcl_Condition *mutex); MODULE_SCOPE void TclRememberJoinableThread(Tcl_ThreadId id); MODULE_SCOPE void TclRememberMutex(Tcl_Mutex *mutex); MODULE_SCOPE void TclRemoveScriptLimitCallbacks(Tcl_Interp *interp); MODULE_SCOPE int TclReToGlob(Tcl_Interp *interp, const char *reStr, int reStrLen, Tcl_DString *dsPtr, int *flagsPtr, int *quantifiersFoundPtr); MODULE_SCOPE int TclScanElement(const char *string, int length, int *flagPtr); MODULE_SCOPE void TclSetBgErrorHandler(Tcl_Interp *interp, Tcl_Obj *cmdPrefix); MODULE_SCOPE void TclSetBignumIntRep(Tcl_Obj *objPtr, mp_int *bignumValue); MODULE_SCOPE int TclSetBooleanFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); MODULE_SCOPE void TclSetCmdNameObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Command *cmdPtr); MODULE_SCOPE void TclSetDuplicateObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr); MODULE_SCOPE void TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr, Tcl_Obj *newValue, Tcl_Encoding encoding); MODULE_SCOPE void TclSignalExitThread(Tcl_ThreadId id, int result); MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr, int numBytes); MODULE_SCOPE int TclStringMatch(const char *str, int strLen, const char *pattern, int ptnLen, int flags); MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj, Tcl_Obj *patternObj, int flags); MODULE_SCOPE Tcl_Obj * TclStringObjReverse(Tcl_Obj *objPtr); MODULE_SCOPE void TclSubstCompile(Tcl_Interp *interp, const char *bytes, int numBytes, int flags, int line, struct CompileEnv *envPtr); MODULE_SCOPE int TclSubstOptions(Tcl_Interp *interp, int numOpts, Tcl_Obj *const opts[], int *flagPtr); MODULE_SCOPE void TclSubstParse(Tcl_Interp *interp, const char *bytes, int numBytes, int flags, Tcl_Parse *parsePtr, Tcl_InterpState *statePtr); MODULE_SCOPE int TclSubstTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr, int count, int *tokensLeftPtr, int line, int *clNextOuter, const char *outerScript); MODULE_SCOPE int TclTrimLeft(const char *bytes, int numBytes, const char *trim, int numTrim); MODULE_SCOPE int TclTrimRight(const char *bytes, int numBytes, const char *trim, int numTrim); MODULE_SCOPE int TclUtfCasecmp(const char *cs, const char *ct); MODULE_SCOPE Tcl_Obj * TclpNativeToNormalized(ClientData clientData); MODULE_SCOPE Tcl_Obj * TclpFilesystemPathType(Tcl_Obj *pathPtr); MODULE_SCOPE int TclpDlopen(Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_LoadHandle *loadHandle, Tcl_FSUnloadFileProc **unloadProcPtr, int flags); MODULE_SCOPE int TclpUtime(Tcl_Obj *pathPtr, struct utimbuf *tval); #ifdef TCL_LOAD_FROM_MEMORY MODULE_SCOPE void * TclpLoadMemoryGetBuffer(Tcl_Interp *interp, int size); MODULE_SCOPE int TclpLoadMemory(Tcl_Interp *interp, void *buffer, int size, int codeSize, Tcl_LoadHandle *loadHandle, Tcl_FSUnloadFileProc **unloadProcPtr, int flags); #endif MODULE_SCOPE void TclInitThreadStorage(void); MODULE_SCOPE void TclFinalizeThreadDataThread(void); MODULE_SCOPE void TclFinalizeThreadStorage(void); #ifdef TCL_WIDE_CLICKS MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void); MODULE_SCOPE double TclpWideClicksToNanoseconds(Tcl_WideInt clicks); #endif MODULE_SCOPE int TclZlibInit(Tcl_Interp *interp); MODULE_SCOPE void * TclpThreadCreateKey(void); MODULE_SCOPE void TclpThreadDeleteKey(void *keyPtr); MODULE_SCOPE void TclpThreadSetMasterTSD(void *tsdKeyPtr, void *ptr); MODULE_SCOPE void * TclpThreadGetMasterTSD(void *tsdKeyPtr); MODULE_SCOPE void TclErrorStackResetIf(Tcl_Interp *interp, const char *msg, int length); /* *---------------------------------------------------------------- * Command procedures in the generic core: *---------------------------------------------------------------- */ MODULE_SCOPE int Tcl_AfterObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_AppendObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ApplyObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE Tcl_Command TclInitArrayCmd(Tcl_Interp *interp); MODULE_SCOPE Tcl_Command TclInitBinaryCmd(Tcl_Interp *interp); MODULE_SCOPE int Tcl_BreakObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_CaseObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_CatchObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_CdObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE Tcl_Command TclInitChanCmd(Tcl_Interp *interp); MODULE_SCOPE int TclChanCreateObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclChanPostEventObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclChanPopObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclChanPushObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE void TclClockInit(Tcl_Interp *interp); MODULE_SCOPE int TclClockOldscanObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_CloseObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ConcatObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ContinueObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE Tcl_TimerToken TclCreateAbsoluteTimerHandler( Tcl_Time *timePtr, Tcl_TimerProc *proc, ClientData clientData); MODULE_SCOPE int TclDefaultBgErrorHandlerObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE Tcl_Command TclInitDictCmd(Tcl_Interp *interp); MODULE_SCOPE int TclDictWithFinish(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int index, int pathc, Tcl_Obj *const pathv[], Tcl_Obj *keysPtr); MODULE_SCOPE Tcl_Obj * TclDictWithInit(Tcl_Interp *interp, Tcl_Obj *dictPtr, int pathc, Tcl_Obj *const pathv[]); MODULE_SCOPE int Tcl_DisassembleObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* Assemble command function */ MODULE_SCOPE int Tcl_AssembleObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclNRAssembleObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_EncodingObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_EofObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ErrorObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_EvalObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ExecObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ExitObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ExprObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_FblockedObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_FconfigureObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_FcopyObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE Tcl_Command TclInitFileCmd(Tcl_Interp *interp); MODULE_SCOPE int TclMakeFileCommandSafe(Tcl_Interp *interp); MODULE_SCOPE int Tcl_FileEventObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_FlushObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ForObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ForeachObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_FormatObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_GetsObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_GlobalObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_GlobObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_IfObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_IncrObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE Tcl_Command TclInitInfoCmd(Tcl_Interp *interp); MODULE_SCOPE int Tcl_InterpObjCmd(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_JoinObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LappendObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LassignObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LindexObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LinsertObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LlengthObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ListObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LmapObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LoadObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LrangeObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LrepeatObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LreplaceObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LreverseObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LsearchObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LsetObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_LsortObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE Tcl_Command TclInitNamespaceCmd(Tcl_Interp *interp); MODULE_SCOPE int TclNamespaceEnsembleCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_OpenObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_PackageObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_PidObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE Tcl_Command TclInitPrefixCmd(Tcl_Interp *interp); MODULE_SCOPE int Tcl_PutsObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_PwdObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ReadObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_RegexpObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_RegsubObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_RenameObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_RepresentationCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ReturnObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ScanObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_SeekObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_SetObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_SplitObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_SocketObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_SourceObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE Tcl_Command TclInitStringCmd(Tcl_Interp *interp); MODULE_SCOPE int Tcl_SubstObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_SwitchObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_TellObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_ThrowObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_TimeObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_TraceObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_TryObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_UnloadObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_UnsetObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_UpdateObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_UplevelObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_UpvarObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_VariableObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_VwaitObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tcl_WhileObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* *---------------------------------------------------------------- * Compilation procedures for commands in the generic core: *---------------------------------------------------------------- */ MODULE_SCOPE int TclCompileAppendCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileArrayExistsCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileArraySetCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileArrayUnsetCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBreakCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileCatchCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileConcatCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileContinueCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictAppendCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictCreateCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictExistsCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictForCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictGetCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictIncrCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictLappendCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictMapCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictMergeCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictSetCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictUnsetCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictUpdateCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileDictWithCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileEnsemble(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileErrorCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileExprCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileForCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileForeachCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileFormatCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileGlobalCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileIfCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileInfoCommandsCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileInfoCoroutineCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileInfoExistsCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileInfoLevelCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileInfoObjectClassCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileInfoObjectIsACmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileInfoObjectNamespaceCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileIncrCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileLappendCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileLassignCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileLindexCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileLinsertCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileListCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileLlengthCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileLmapCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileLrangeCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileLreplaceCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileLsetCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileNamespaceCodeCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileNamespaceCurrentCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileNamespaceOriginCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileNamespaceQualifiersCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileNamespaceTailCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileNamespaceUpvarCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileNamespaceWhichCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileNoOp(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileObjectNextCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileObjectNextToCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileObjectSelfCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileRegexpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileRegsubCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileReturnCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileSetCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringCatCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringCmpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringEqualCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringFirstCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringIndexCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringIsCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringLastCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringLenCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringMapCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringMatchCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringRangeCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringReplaceCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringToLowerCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringToTitleCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringToUpperCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringTrimCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringTrimLCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStringTrimRCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileSubstCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileSwitchCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileTailcallCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileThrowCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileTryCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileUnsetCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileUpvarCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileVariableCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileWhileCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileYieldCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileYieldToCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic0ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic1ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic2ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic3ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic0Or1ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic1Or2ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic2Or3ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic0To2ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic1To3ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasicMin0ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasicMin1ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasicMin2ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclInvertOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileInvertOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclNotOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileNotOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclAddOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileAddOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclMulOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileMulOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclAndOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileAndOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclOrOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileOrOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclXorOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileXorOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclPowOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompilePowOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclLshiftOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileLshiftOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclRshiftOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileRshiftOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclModOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileModOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclNeqOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileNeqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclStrneqOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileStrneqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclInOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileInOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclNiOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileNiOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclMinusOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileMinusOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclDivOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileDivOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclLessOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileLessOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclLeqOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileLeqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclGreaterOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileGreaterOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclGeqOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileGeqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclEqOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileEqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclStreqOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileStreqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); /* * Functions defined in generic/tclVar.c and currenttly exported only for use * by the bytecode compiler and engine. Some of these could later be placed in * the public interface. */ MODULE_SCOPE Var * TclObjLookupVarEx(Tcl_Interp * interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags, const char *msg, const int createPart1, const int createPart2, Var **arrayPtrPtr); MODULE_SCOPE Var * TclLookupArrayElement(Tcl_Interp *interp, Tcl_Obj *arrayNamePtr, Tcl_Obj *elNamePtr, const int flags, const char *msg, const int createPart1, const int createPart2, Var *arrayPtr, int index); MODULE_SCOPE Tcl_Obj * TclPtrGetVar(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags, int index); MODULE_SCOPE Tcl_Obj * TclPtrSetVar(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, const int flags, int index); MODULE_SCOPE Tcl_Obj * TclPtrIncrObjVar(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, const int flags, int index); MODULE_SCOPE int TclPtrObjMakeUpvar(Tcl_Interp *interp, Var *otherPtr, Tcl_Obj *myNamePtr, int myFlags, int index); MODULE_SCOPE int TclPtrUnsetVar(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const int flags, int index); MODULE_SCOPE void TclInvalidateNsPath(Namespace *nsPtr); MODULE_SCOPE void TclFindArrayPtrElements(Var *arrayPtr, Tcl_HashTable *tablePtr); /* * The new extended interface to the variable traces. */ MODULE_SCOPE int TclObjCallVarTraces(Interp *iPtr, Var *arrayPtr, Var *varPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags, int leaveErrMsg, int index); /* * So tclObj.c and tclDictObj.c can share these implementations. */ MODULE_SCOPE int TclCompareObjKeys(void *keyPtr, Tcl_HashEntry *hPtr); MODULE_SCOPE void TclFreeObjEntry(Tcl_HashEntry *hPtr); MODULE_SCOPE unsigned TclHashObjKey(Tcl_HashTable *tablePtr, void *keyPtr); MODULE_SCOPE int TclFullFinalizationRequested(void); /* *---------------------------------------------------------------- * Macros used by the Tcl core to create and release Tcl objects. * TclNewObj(objPtr) creates a new object denoting an empty string. * TclDecrRefCount(objPtr) decrements the object's reference count, and frees * the object if its reference count is zero. These macros are inline versions * of Tcl_NewObj() and Tcl_DecrRefCount(). Notice that the names differ in not * having a "_" after the "Tcl". Notice also that these macros reference their * argument more than once, so you should avoid calling them with an * expression that is expensive to compute or has side effects. The ANSI C * "prototypes" for these macros are: * * MODULE_SCOPE void TclNewObj(Tcl_Obj *objPtr); * MODULE_SCOPE void TclDecrRefCount(Tcl_Obj *objPtr); * * These macros are defined in terms of two macros that depend on memory * allocator in use: TclAllocObjStorage, TclFreeObjStorage. They are defined * below. *---------------------------------------------------------------- */ /* * DTrace object allocation probe macros. */ #ifdef USE_DTRACE #ifndef _TCLDTRACE_H typedef const char *TclDTraceStr; #include "tclDTrace.h" #endif #define TCL_DTRACE_OBJ_CREATE(objPtr) TCL_OBJ_CREATE(objPtr) #define TCL_DTRACE_OBJ_FREE(objPtr) TCL_OBJ_FREE(objPtr) #else /* USE_DTRACE */ #define TCL_DTRACE_OBJ_CREATE(objPtr) {} #define TCL_DTRACE_OBJ_FREE(objPtr) {} #endif /* USE_DTRACE */ #ifdef TCL_COMPILE_STATS # define TclIncrObjsAllocated() \ tclObjsAlloced++ # define TclIncrObjsFreed() \ tclObjsFreed++ #else # define TclIncrObjsAllocated() # define TclIncrObjsFreed() #endif /* TCL_COMPILE_STATS */ # define TclAllocObjStorage(objPtr) \ TclAllocObjStorageEx(NULL, (objPtr)) # define TclFreeObjStorage(objPtr) \ TclFreeObjStorageEx(NULL, (objPtr)) #ifndef TCL_MEM_DEBUG # define TclNewObj(objPtr) \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = tclEmptyStringRep; \ (objPtr)->length = 0; \ (objPtr)->typePtr = NULL; \ TCL_DTRACE_OBJ_CREATE(objPtr) /* * Invalidate the string rep first so we can use the bytes value for our * pointer chain, and signal an obj deletion (as opposed to shimmering) with * 'length == -1'. * Use empty 'if ; else' to handle use in unbraced outer if/else conditions. */ # define TclDecrRefCount(objPtr) \ if ((objPtr)->refCount-- > 1) ; else { \ if (!(objPtr)->typePtr || !(objPtr)->typePtr->freeIntRepProc) { \ TCL_DTRACE_OBJ_FREE(objPtr); \ if ((objPtr)->bytes \ && ((objPtr)->bytes != tclEmptyStringRep)) { \ ckfree((char *) (objPtr)->bytes); \ } \ (objPtr)->length = -1; \ TclFreeObjStorage(objPtr); \ TclIncrObjsFreed(); \ } else { \ TclFreeObj(objPtr); \ } \ } #if defined(PURIFY) /* * The PURIFY mode is like the regular mode, but instead of doing block * Tcl_Obj allocation and keeping a freed list for efficiency, it always * allocates and frees a single Tcl_Obj so that tools like Purify can better * track memory leaks. */ # define TclAllocObjStorageEx(interp, objPtr) \ (objPtr) = (Tcl_Obj *) ckalloc(sizeof(Tcl_Obj)) # define TclFreeObjStorageEx(interp, objPtr) \ ckfree((char *) (objPtr)) #undef USE_THREAD_ALLOC #undef USE_TCLALLOC #elif defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) /* * The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's from * per-thread caches. */ MODULE_SCOPE Tcl_Obj * TclThreadAllocObj(void); MODULE_SCOPE void TclThreadFreeObj(Tcl_Obj *); MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex(void); MODULE_SCOPE void TclFreeAllocCache(void *); MODULE_SCOPE void * TclpGetAllocCache(void); MODULE_SCOPE void TclpSetAllocCache(void *); MODULE_SCOPE void TclpFreeAllocMutex(Tcl_Mutex *mutex); MODULE_SCOPE void TclpFreeAllocCache(void *); /* * These macros need to be kept in sync with the code of TclThreadAllocObj() * and TclThreadFreeObj(). * * Note that the optimiser should resolve the case (interp==NULL) at compile * time. */ # define ALLOC_NOBJHIGH 1200 # define TclAllocObjStorageEx(interp, objPtr) \ do { \ AllocCache *cachePtr; \ if (((interp) == NULL) || \ ((cachePtr = ((Interp *)(interp))->allocCache), \ (cachePtr->numObjects == 0))) { \ (objPtr) = TclThreadAllocObj(); \ } else { \ (objPtr) = cachePtr->firstObjPtr; \ cachePtr->firstObjPtr = (objPtr)->internalRep.twoPtrValue.ptr1; \ --cachePtr->numObjects; \ } \ } while (0) # define TclFreeObjStorageEx(interp, objPtr) \ do { \ AllocCache *cachePtr; \ if (((interp) == NULL) || \ ((cachePtr = ((Interp *)(interp))->allocCache), \ ((cachePtr->numObjects == 0) || \ (cachePtr->numObjects >= ALLOC_NOBJHIGH)))) { \ TclThreadFreeObj(objPtr); \ } else { \ (objPtr)->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr; \ cachePtr->firstObjPtr = objPtr; \ ++cachePtr->numObjects; \ } \ } while (0) #else /* not PURIFY or USE_THREAD_ALLOC */ #if defined(USE_TCLALLOC) && USE_TCLALLOC MODULE_SCOPE void TclFinalizeAllocSubsystem(); MODULE_SCOPE void TclInitAlloc(); #else # define USE_TCLALLOC 0 #endif #ifdef TCL_THREADS /* declared in tclObj.c */ MODULE_SCOPE Tcl_Mutex tclObjMutex; #endif # define TclAllocObjStorageEx(interp, objPtr) \ do { \ Tcl_MutexLock(&tclObjMutex); \ if (tclFreeObjList == NULL) { \ TclAllocateFreeObjects(); \ } \ (objPtr) = tclFreeObjList; \ tclFreeObjList = (Tcl_Obj *) \ tclFreeObjList->internalRep.twoPtrValue.ptr1; \ Tcl_MutexUnlock(&tclObjMutex); \ } while (0) # define TclFreeObjStorageEx(interp, objPtr) \ do { \ Tcl_MutexLock(&tclObjMutex); \ (objPtr)->internalRep.twoPtrValue.ptr1 = (void *) tclFreeObjList; \ tclFreeObjList = (objPtr); \ Tcl_MutexUnlock(&tclObjMutex); \ } while (0) #endif #else /* TCL_MEM_DEBUG */ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, int line); # define TclDbNewObj(objPtr, file, line) \ do { \ TclIncrObjsAllocated(); \ (objPtr) = (Tcl_Obj *) \ Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \ TclDbInitNewObj((objPtr), (file), (line)); \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) # define TclNewObj(objPtr) \ TclDbNewObj(objPtr, __FILE__, __LINE__); # define TclDecrRefCount(objPtr) \ Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__) # define TclNewListObjDirect(objc, objv) \ TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__) #undef USE_THREAD_ALLOC #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------- * Macro used by the Tcl core to set a Tcl_Obj's string representation to a * copy of the "len" bytes starting at "bytePtr". This code works even if the * byte array contains NULLs as long as the length is correct. Because "len" * is referenced multiple times, it should be as simple an expression as * possible. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, int len); * * This macro should only be called on an unshared objPtr where * objPtr->typePtr->freeIntRepProc == NULL *---------------------------------------------------------------- */ #define TclInitStringRep(objPtr, bytePtr, len) \ if ((len) == 0) { \ (objPtr)->bytes = tclEmptyStringRep; \ (objPtr)->length = 0; \ } else { \ (objPtr)->bytes = (char *) ckalloc((unsigned) ((len) + 1)); \ memcpy((objPtr)->bytes, (bytePtr), (unsigned) (len)); \ (objPtr)->bytes[len] = '\0'; \ (objPtr)->length = (len); \ } /* *---------------------------------------------------------------- * Macro used by the Tcl core to get the string representation's byte array * pointer from a Tcl_Obj. This is an inline version of Tcl_GetString(). The * macro's expression result is the string rep's byte pointer which might be * NULL. The bytes referenced by this pointer must not be modified by the * caller. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE char * TclGetString(Tcl_Obj *objPtr); *---------------------------------------------------------------- */ #define TclGetString(objPtr) \ ((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString((objPtr))) #define TclGetStringFromObj(objPtr, lenPtr) \ ((objPtr)->bytes \ ? (*(lenPtr) = (objPtr)->length, (objPtr)->bytes) \ : Tcl_GetStringFromObj((objPtr), (lenPtr))) /* *---------------------------------------------------------------- * Macro used by the Tcl core to clean out an object's internal * representation. Does not actually reset the rep's bytes. The ANSI C * "prototype" for this macro is: * * MODULE_SCOPE void TclFreeIntRep(Tcl_Obj *objPtr); *---------------------------------------------------------------- */ #define TclFreeIntRep(objPtr) \ if ((objPtr)->typePtr != NULL) { \ if ((objPtr)->typePtr->freeIntRepProc != NULL) { \ (objPtr)->typePtr->freeIntRepProc(objPtr); \ } \ (objPtr)->typePtr = NULL; \ } /* *---------------------------------------------------------------- * Macro used by the Tcl core to clean out an object's string representation. * The ANSI C "prototype" for this macro is: * * MODULE_SCOPE void TclInvalidateStringRep(Tcl_Obj *objPtr); *---------------------------------------------------------------- */ #define TclInvalidateStringRep(objPtr) \ if (objPtr->bytes != NULL) { \ if (objPtr->bytes != tclEmptyStringRep) { \ ckfree((char *) objPtr->bytes); \ } \ objPtr->bytes = NULL; \ } /* *---------------------------------------------------------------- * Macros used by the Tcl core to grow Tcl_Token arrays. They use the same * growth algorithm as used in tclStringObj.c for growing strings. The ANSI C * "prototype" for this macro is: * * MODULE_SCOPE void TclGrowTokenArray(Tcl_Token *tokenPtr, int used, * int available, int append, * Tcl_Token *staticPtr); * MODULE_SCOPE void TclGrowParseTokenArray(Tcl_Parse *parsePtr, * int append); *---------------------------------------------------------------- */ /* General tuning for minimum growth in Tcl growth algorithms */ #ifndef TCL_MIN_GROWTH # ifdef TCL_GROWTH_MIN_ALLOC /* Support for any legacy tuners */ # define TCL_MIN_GROWTH TCL_GROWTH_MIN_ALLOC # else # define TCL_MIN_GROWTH 1024 # endif #endif /* Token growth tuning, default to the general value. */ #ifndef TCL_MIN_TOKEN_GROWTH #define TCL_MIN_TOKEN_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Token) #endif #define TCL_MAX_TOKENS (int)(UINT_MAX / sizeof(Tcl_Token)) #define TclGrowTokenArray(tokenPtr, used, available, append, staticPtr) \ do { \ int needed = (used) + (append); \ if (needed > TCL_MAX_TOKENS) { \ Tcl_Panic("max # of tokens for a Tcl parse (%d) exceeded", \ TCL_MAX_TOKENS); \ } \ if (needed > (available)) { \ int allocated = 2 * needed; \ Tcl_Token *oldPtr = (tokenPtr); \ Tcl_Token *newPtr; \ if (oldPtr == (staticPtr)) { \ oldPtr = NULL; \ } \ if (allocated > TCL_MAX_TOKENS) { \ allocated = TCL_MAX_TOKENS; \ } \ newPtr = (Tcl_Token *) attemptckrealloc((char *) oldPtr, \ (unsigned int) (allocated * sizeof(Tcl_Token))); \ if (newPtr == NULL) { \ allocated = needed + (append) + TCL_MIN_TOKEN_GROWTH; \ if (allocated > TCL_MAX_TOKENS) { \ allocated = TCL_MAX_TOKENS; \ } \ newPtr = (Tcl_Token *) ckrealloc((char *) oldPtr, \ (unsigned int) (allocated * sizeof(Tcl_Token))); \ } \ (available) = allocated; \ if (oldPtr == NULL) { \ memcpy(newPtr, staticPtr, \ (size_t) ((used) * sizeof(Tcl_Token))); \ } \ (tokenPtr) = newPtr; \ } \ } while (0) #define TclGrowParseTokenArray(parsePtr, append) \ TclGrowTokenArray((parsePtr)->tokenPtr, (parsePtr)->numTokens, \ (parsePtr)->tokensAvailable, (append), \ (parsePtr)->staticTokens) /* *---------------------------------------------------------------- * Macro used by the Tcl core get a unicode char from a utf string. It checks * to see if we have a one-byte utf char before calling the real * Tcl_UtfToUniChar, as this will save a lot of time for primarily ASCII * string handling. The macro's expression result is 1 for the 1-byte case or * the result of Tcl_UtfToUniChar. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE int TclUtfToUniChar(const char *string, Tcl_UniChar *ch); *---------------------------------------------------------------- */ #define TclUtfToUniChar(str, chPtr) \ ((((unsigned char) *(str)) < 0xC0) ? \ ((*(chPtr) = (Tcl_UniChar) *(str)), 1) \ : Tcl_UtfToUniChar(str, chPtr)) /* *---------------------------------------------------------------- * Macro counterpart of the Tcl_NumUtfChars() function. To be used in speed- * -sensitive points where it pays to avoid a function call in the common case * of counting along a string of all one-byte characters. The ANSI C * "prototype" for this macro is: * * MODULE_SCOPE void TclNumUtfChars(int numChars, const char *bytes, * int numBytes); *---------------------------------------------------------------- */ #define TclNumUtfChars(numChars, bytes, numBytes) \ do { \ int count, i = (numBytes); \ unsigned char *str = (unsigned char *) (bytes); \ while (i && (*str < 0xC0)) { i--; str++; } \ count = (numBytes) - i; \ if (i) { \ count += Tcl_NumUtfChars((bytes) + count, i); \ } \ (numChars) = count; \ } while (0); /* *---------------------------------------------------------------- * Macro that encapsulates the logic that determines when it is safe to * interpret a string as a byte array directly. In summary, the object must be * a byte array and must not have a string representation (as the operations * that it is used in are defined on strings, not byte arrays). Theoretically * it is possible to also be efficient in the case where the object's bytes * field is filled by generation from the byte array (c.f. list canonicality) * but we don't do that at the moment since this is purely about efficiency. * The ANSI C "prototype" for this macro is: * * MODULE_SCOPE int TclIsPureByteArray(Tcl_Obj *objPtr); *---------------------------------------------------------------- */ #define TclIsPureByteArray(objPtr) \ (((objPtr)->typePtr==&tclByteArrayType) && ((objPtr)->bytes==NULL)) /* *---------------------------------------------------------------- * Macro used by the Tcl core to compare Unicode strings. On big-endian * systems we can use the more efficient memcmp, but this would not be * lexically correct on little-endian systems. The ANSI C "prototype" for * this macro is: * * MODULE_SCOPE int TclUniCharNcmp(const Tcl_UniChar *cs, * const Tcl_UniChar *ct, unsigned long n); *---------------------------------------------------------------- */ #ifdef WORDS_BIGENDIAN # define TclUniCharNcmp(cs,ct,n) memcmp((cs),(ct),(n)*sizeof(Tcl_UniChar)) #else /* !WORDS_BIGENDIAN */ # define TclUniCharNcmp Tcl_UniCharNcmp #endif /* WORDS_BIGENDIAN */ /* *---------------------------------------------------------------- * Macro used by the Tcl core to increment a namespace's export export epoch * counter. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE void TclInvalidateNsCmdLookup(Namespace *nsPtr); *---------------------------------------------------------------- */ #define TclInvalidateNsCmdLookup(nsPtr) \ if ((nsPtr)->numExportPatterns) { \ (nsPtr)->exportLookupEpoch++; \ } \ if ((nsPtr)->commandPathLength) { \ (nsPtr)->cmdRefEpoch++; \ } /* *---------------------------------------------------------------------- * * Core procedure added to libtommath for bignum manipulation. * *---------------------------------------------------------------------- */ MODULE_SCOPE Tcl_PackageInitProc TclTommath_Init; /* *---------------------------------------------------------------------- * * External (platform specific) initialization routine, these declarations * explicitly don't use EXTERN since this code does not get compiled into the * library: * *---------------------------------------------------------------------- */ 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; /* *---------------------------------------------------------------- * Macro used by the Tcl core to check whether a pattern has any characters * special to [string match]. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE int TclMatchIsTrivial(const char *pattern); *---------------------------------------------------------------- */ #define TclMatchIsTrivial(pattern) \ (strpbrk((pattern), "*[?\\") == NULL) /* *---------------------------------------------------------------- * Macros used by the Tcl core to set a Tcl_Obj's numeric representation * avoiding the corresponding function calls in time critical parts of the * core. They should only be called on unshared objects. The ANSI C * "prototypes" for these macros are: * * MODULE_SCOPE void TclSetIntObj(Tcl_Obj *objPtr, int intValue); * MODULE_SCOPE void TclSetLongObj(Tcl_Obj *objPtr, long longValue); * MODULE_SCOPE void TclSetBooleanObj(Tcl_Obj *objPtr, long boolValue); * MODULE_SCOPE void TclSetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt w); * MODULE_SCOPE void TclSetDoubleObj(Tcl_Obj *objPtr, double d); *---------------------------------------------------------------- */ #define TclSetLongObj(objPtr, i) \ do { \ TclInvalidateStringRep(objPtr); \ TclFreeIntRep(objPtr); \ (objPtr)->internalRep.longValue = (long)(i); \ (objPtr)->typePtr = &tclIntType; \ } while (0) #define TclSetIntObj(objPtr, l) \ TclSetLongObj(objPtr, l) /* * NOTE: There is to be no such thing as a "pure" boolean. Boolean values set * programmatically go straight to being "int" Tcl_Obj's, with value 0 or 1. * The only "boolean" Tcl_Obj's shall be those holding the cached boolean * value of strings like: "yes", "no", "true", "false", "on", "off". */ #define TclSetBooleanObj(objPtr, b) \ TclSetLongObj(objPtr, (b)!=0); #ifndef TCL_WIDE_INT_IS_LONG #define TclSetWideIntObj(objPtr, w) \ do { \ TclInvalidateStringRep(objPtr); \ TclFreeIntRep(objPtr); \ (objPtr)->internalRep.wideValue = (Tcl_WideInt)(w); \ (objPtr)->typePtr = &tclWideIntType; \ } while (0) #endif #define TclSetDoubleObj(objPtr, d) \ do { \ TclInvalidateStringRep(objPtr); \ TclFreeIntRep(objPtr); \ (objPtr)->internalRep.doubleValue = (double)(d); \ (objPtr)->typePtr = &tclDoubleType; \ } while (0) /* *---------------------------------------------------------------- * Macros used by the Tcl core to create and initialise objects of standard * types, avoiding the corresponding function calls in time critical parts of * the core. The ANSI C "prototypes" for these macros are: * * MODULE_SCOPE void TclNewIntObj(Tcl_Obj *objPtr, int i); * MODULE_SCOPE void TclNewLongObj(Tcl_Obj *objPtr, long l); * MODULE_SCOPE void TclNewBooleanObj(Tcl_Obj *objPtr, int b); * MODULE_SCOPE void TclNewWideObj(Tcl_Obj *objPtr, Tcl_WideInt w); * MODULE_SCOPE void TclNewDoubleObj(Tcl_Obj *objPtr, double d); * MODULE_SCOPE void TclNewStringObj(Tcl_Obj *objPtr, char *s, int len); * MODULE_SCOPE void TclNewLiteralStringObj(Tcl_Obj*objPtr, char*sLiteral); * *---------------------------------------------------------------- */ #ifndef TCL_MEM_DEBUG #define TclNewLongObj(objPtr, i) \ do { \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = NULL; \ (objPtr)->internalRep.longValue = (long)(i); \ (objPtr)->typePtr = &tclIntType; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) #define TclNewIntObj(objPtr, l) \ TclNewLongObj(objPtr, l) /* * NOTE: There is to be no such thing as a "pure" boolean. * See comment above TclSetBooleanObj macro above. */ #define TclNewBooleanObj(objPtr, b) \ TclNewLongObj((objPtr), (b)!=0) #define TclNewDoubleObj(objPtr, d) \ do { \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = NULL; \ (objPtr)->internalRep.doubleValue = (double)(d); \ (objPtr)->typePtr = &tclDoubleType; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) #define TclNewStringObj(objPtr, s, len) \ do { \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ TclInitStringRep((objPtr), (s), (len)); \ (objPtr)->typePtr = NULL; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) #else /* TCL_MEM_DEBUG */ #define TclNewIntObj(objPtr, i) \ (objPtr) = Tcl_NewIntObj(i) #define TclNewLongObj(objPtr, l) \ (objPtr) = Tcl_NewLongObj(l) #define TclNewBooleanObj(objPtr, b) \ (objPtr) = Tcl_NewBooleanObj(b) #define TclNewDoubleObj(objPtr, d) \ (objPtr) = Tcl_NewDoubleObj(d) #define TclNewStringObj(objPtr, s, len) \ (objPtr) = Tcl_NewStringObj((s), (len)) #endif /* TCL_MEM_DEBUG */ /* * The sLiteral argument *must* be a string literal; the incantation with * sizeof(sLiteral "") will fail to compile otherwise. */ #define TclNewLiteralStringObj(objPtr, sLiteral) \ TclNewStringObj((objPtr), (sLiteral), (int) (sizeof(sLiteral "") - 1)) /* *---------------------------------------------------------------- * Convenience macros for DStrings. * The ANSI C "prototypes" for these macros are: * * MODULE_SCOPE char * TclDStringAppendLiteral(Tcl_DString *dsPtr, * const char *sLiteral); * MODULE_SCOPE void TclDStringClear(Tcl_DString *dsPtr); */ #define TclDStringAppendLiteral(dsPtr, sLiteral) \ Tcl_DStringAppend((dsPtr), (sLiteral), (int) (sizeof(sLiteral "") - 1)) #define TclDStringClear(dsPtr) \ Tcl_DStringSetLength((dsPtr), 0) /* *---------------------------------------------------------------- * Macros used by the Tcl core to test for some special double values. * The ANSI C "prototypes" for these macros are: * * MODULE_SCOPE int TclIsInfinite(double d); * MODULE_SCOPE int TclIsNaN(double d); */ #ifdef _MSC_VER # define TclIsInfinite(d) (!(_finite((d)))) # define TclIsNaN(d) (_isnan((d))) #else # define TclIsInfinite(d) ((d) > DBL_MAX || (d) < -DBL_MAX) # ifdef NO_ISNAN # define TclIsNaN(d) ((d) != (d)) # else # define TclIsNaN(d) (isnan(d)) # endif #endif /* * ---------------------------------------------------------------------- * Macro to use to find the offset of a field in a structure. Computes number * of bytes from beginning of structure to a given field. */ #ifdef offsetof #define TclOffset(type, field) ((int) offsetof(type, field)) #else #define TclOffset(type, field) ((int) ((char *) &((type *) 0)->field)) #endif /* *---------------------------------------------------------------- * Inline version of Tcl_GetCurrentNamespace and Tcl_GetGlobalNamespace. */ #define TclGetCurrentNamespace(interp) \ (Tcl_Namespace *) ((Interp *)(interp))->varFramePtr->nsPtr #define TclGetGlobalNamespace(interp) \ (Tcl_Namespace *) ((Interp *)(interp))->globalNsPtr /* *---------------------------------------------------------------- * Inline version of TclCleanupCommand; still need the function as it is in * the internal stubs, but the core can use the macro instead. */ #define TclCleanupCommandMacro(cmdPtr) \ if ((cmdPtr)->refCount-- <= 1) { \ ckfree((char *) (cmdPtr));\ } /* *---------------------------------------------------------------- * Inline versions of Tcl_LimitReady() and Tcl_LimitExceeded to limit number * of calls out of the critical path. Note that this code isn't particularly * readable; the non-inline version (in tclInterp.c) is much easier to * understand. Note also that these macros takes different args (iPtr->limit) * to the non-inline version. */ #define TclLimitExceeded(limit) ((limit).exceeded != 0) #define TclLimitReady(limit) \ (((limit).active == 0) ? 0 : \ (++(limit).granularityTicker, \ ((((limit).active & TCL_LIMIT_COMMANDS) && \ (((limit).cmdGranularity == 1) || \ ((limit).granularityTicker % (limit).cmdGranularity == 0))) \ ? 1 : \ (((limit).active & TCL_LIMIT_TIME) && \ (((limit).timeGranularity == 1) || \ ((limit).granularityTicker % (limit).timeGranularity == 0)))\ ? 1 : 0))) /* * Compile-time assertions: these produce a compile time error if the * expression is not known to be true at compile time. If the assertion is * known to be false, the compiler (or optimizer?) will error out with * "division by zero". If the assertion cannot be evaluated at compile time, * the compiler will error out with "non-static initializer". * * Adapted with permission from * http://www.pixelbeat.org/programming/gcc/static_assert.html */ #define TCL_CT_ASSERT(e) \ {enum { ct_assert_value = 1/(!!(e)) };} /* *---------------------------------------------------------------- * Allocator for small structs (<=sizeof(Tcl_Obj)) using the Tcl_Obj pool. * Only checked at compile time. * * ONLY USE FOR CONSTANT nBytes. * * DO NOT LET THEM CROSS THREAD BOUNDARIES *---------------------------------------------------------------- */ #define TclSmallAlloc(nbytes, memPtr) \ TclSmallAllocEx(NULL, (nbytes), (memPtr)) #define TclSmallFree(memPtr) \ TclSmallFreeEx(NULL, (memPtr)) #ifndef TCL_MEM_DEBUG #define TclSmallAllocEx(interp, nbytes, memPtr) \ do { \ Tcl_Obj *objPtr; \ TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj)); \ TclIncrObjsAllocated(); \ TclAllocObjStorageEx((interp), (objPtr)); \ memPtr = (ClientData) (objPtr); \ } while (0) #define TclSmallFreeEx(interp, memPtr) \ do { \ TclFreeObjStorageEx((interp), (Tcl_Obj *) (memPtr)); \ TclIncrObjsFreed(); \ } while (0) #else /* TCL_MEM_DEBUG */ #define TclSmallAllocEx(interp, nbytes, memPtr) \ do { \ Tcl_Obj *objPtr; \ TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj)); \ TclNewObj(objPtr); \ memPtr = (ClientData) objPtr; \ } while (0) #define TclSmallFreeEx(interp, memPtr) \ do { \ Tcl_Obj *objPtr = (Tcl_Obj *) memPtr; \ objPtr->bytes = NULL; \ objPtr->typePtr = NULL; \ objPtr->refCount = 1; \ TclDecrRefCount(objPtr); \ } while (0) #endif /* TCL_MEM_DEBUG */ /* * Support for Clang Static Analyzer */ #if defined(PURIFY) && defined(__clang__) #if __has_feature(attribute_analyzer_noreturn) && \ !defined(Tcl_Panic) && defined(Tcl_Panic_TCL_DECLARED) void Tcl_Panic(const char *, ...) __attribute__((analyzer_noreturn)); #endif #if !defined(CLANG_ASSERT) #include #define CLANG_ASSERT(x) assert(x) #endif #elif !defined(CLANG_ASSERT) #define CLANG_ASSERT(x) #endif /* PURIFY && __clang__ */ /* *---------------------------------------------------------------- * Parameters, structs and macros for the non-recursive engine (NRE) *---------------------------------------------------------------- */ #define NRE_USE_SMALL_ALLOC 1 /* Only turn off for debugging purposes. */ #ifndef NRE_ENABLE_ASSERTS #define NRE_ENABLE_ASSERTS 0 #endif /* * This is the main data struct for representing NR commands. It is designed * to fit in sizeof(Tcl_Obj) in order to exploit the fastest memory allocator * available. */ typedef struct NRE_callback { Tcl_NRPostProc *procPtr; ClientData data[4]; struct NRE_callback *nextPtr; } NRE_callback; #define TOP_CB(iPtr) (((Interp *)(iPtr))->execEnvPtr->callbackPtr) /* * Inline version of Tcl_NRAddCallback. */ #define TclNRAddCallback(interp,postProcPtr,data0,data1,data2,data3) \ do { \ NRE_callback *callbackPtr; \ TCLNR_ALLOC((interp), (callbackPtr)); \ callbackPtr->procPtr = (postProcPtr); \ callbackPtr->data[0] = (ClientData)(data0); \ callbackPtr->data[1] = (ClientData)(data1); \ callbackPtr->data[2] = (ClientData)(data2); \ callbackPtr->data[3] = (ClientData)(data3); \ callbackPtr->nextPtr = TOP_CB(interp); \ TOP_CB(interp) = callbackPtr; \ } while (0) #if NRE_USE_SMALL_ALLOC #define TCLNR_ALLOC(interp, ptr) \ TclSmallAllocEx(interp, sizeof(NRE_callback), (ptr)) #define TCLNR_FREE(interp, ptr) TclSmallFreeEx((interp), (ptr)) #else #define TCLNR_ALLOC(interp, ptr) \ (ptr = ((ClientData) ckalloc(sizeof(NRE_callback)))) #define TCLNR_FREE(interp, ptr) ckfree((char *) (ptr)) #endif #if NRE_ENABLE_ASSERTS #define NRE_ASSERT(expr) assert((expr)) #else #define NRE_ASSERT(expr) #endif #include "tclIntDecls.h" #include "tclIntPlatDecls.h" #include "tclTomMathDecls.h" #if !defined(USE_TCL_STUBS) && !defined(TCL_MEM_DEBUG) #define Tcl_AttemptAlloc(size) TclpAlloc(size) #define Tcl_AttemptRealloc(ptr, size) TclpRealloc((ptr), (size)) #define Tcl_Free(ptr) TclpFree(ptr) #endif #endif /* _TCLINT */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclIntDecls.h0000644000175000017500000015154412665173571015601 0ustar sergeisergei/* * tclIntDecls.h -- * * This file contains the declarations for all unsupported * functions that are exported by the Tcl library. These * interfaces are not guaranteed to remain the same between * versions. Use at your own risk. * * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLINTDECLS #define _TCLINTDECLS #include "tclPort.h" #undef TCL_STORAGE_CLASS #ifdef BUILD_tcl # define TCL_STORAGE_CLASS DLLEXPORT #else # ifdef USE_TCL_STUBS # define TCL_STORAGE_CLASS # else # define TCL_STORAGE_CLASS DLLIMPORT # endif #endif /* [Bug #803489] Tcl_FindNamespace problem in the Stubs table */ #undef Tcl_CreateNamespace #undef Tcl_DeleteNamespace #undef Tcl_AppendExportList #undef Tcl_Export #undef Tcl_Import #undef Tcl_ForgetImport #undef Tcl_GetCurrentNamespace #undef Tcl_GetGlobalNamespace #undef Tcl_FindNamespace #undef Tcl_FindCommand #undef Tcl_GetCommandFromObj #undef Tcl_GetCommandFullName #undef Tcl_SetStartupScript #undef Tcl_GetStartupScript /* * WARNING: This file is automatically generated by the tools/genStubs.tcl * script. Any modifications to the function declarations below should be made * in the generic/tclInt.decls script. */ /* !BEGIN!: Do not edit below this line. */ #ifdef __cplusplus extern "C" { #endif /* * Exported function declarations: */ /* Slot 0 is reserved */ /* Slot 1 is reserved */ /* Slot 2 is reserved */ /* 3 */ EXTERN void TclAllocateFreeObjects(void); /* Slot 4 is reserved */ /* 5 */ EXTERN int TclCleanupChildren(Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan); /* 6 */ EXTERN void TclCleanupCommand(Command *cmdPtr); /* 7 */ EXTERN int TclCopyAndCollapse(int count, const char *src, char *dst); /* 8 */ EXTERN int TclCopyChannelOld(Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj *cmdPtr); /* 9 */ EXTERN int TclCreatePipeline(Tcl_Interp *interp, int argc, const char **argv, Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, TclFile *errFilePtr); /* 10 */ EXTERN int TclCreateProc(Tcl_Interp *interp, Namespace *nsPtr, const char *procName, Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Proc **procPtrPtr); /* 11 */ EXTERN void TclDeleteCompiledLocalVars(Interp *iPtr, CallFrame *framePtr); /* 12 */ EXTERN void TclDeleteVars(Interp *iPtr, TclVarHashTable *tablePtr); /* Slot 13 is reserved */ /* 14 */ EXTERN int TclDumpMemoryInfo(ClientData clientData, int flags); /* Slot 15 is reserved */ /* 16 */ EXTERN void TclExprFloatError(Tcl_Interp *interp, double value); /* Slot 17 is reserved */ /* Slot 18 is reserved */ /* Slot 19 is reserved */ /* Slot 20 is reserved */ /* Slot 21 is reserved */ /* 22 */ EXTERN int TclFindElement(Tcl_Interp *interp, const char *listStr, int listLength, const char **elementPtr, const char **nextPtr, int *sizePtr, int *bracePtr); /* 23 */ EXTERN Proc * TclFindProc(Interp *iPtr, const char *procName); /* 24 */ EXTERN int TclFormatInt(char *buffer, long n); /* 25 */ EXTERN void TclFreePackageInfo(Interp *iPtr); /* Slot 26 is reserved */ /* Slot 27 is reserved */ /* 28 */ EXTERN Tcl_Channel TclpGetDefaultStdChannel(int type); /* Slot 29 is reserved */ /* Slot 30 is reserved */ /* 31 */ EXTERN const char * TclGetExtension(const char *name); /* 32 */ EXTERN int TclGetFrame(Tcl_Interp *interp, const char *str, CallFrame **framePtrPtr); /* Slot 33 is reserved */ /* 34 */ EXTERN int TclGetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr); /* Slot 35 is reserved */ /* Slot 36 is reserved */ /* 37 */ EXTERN int TclGetLoadedPackages(Tcl_Interp *interp, const char *targetName); /* 38 */ EXTERN int TclGetNamespaceForQualName(Tcl_Interp *interp, const char *qualName, Namespace *cxtNsPtr, int flags, Namespace **nsPtrPtr, Namespace **altNsPtrPtr, Namespace **actualCxtPtrPtr, const char **simpleNamePtr); /* 39 */ EXTERN TclObjCmdProcType TclGetObjInterpProc(void); /* 40 */ EXTERN int TclGetOpenMode(Tcl_Interp *interp, const char *str, int *seekFlagPtr); /* 41 */ EXTERN Tcl_Command TclGetOriginalCommand(Tcl_Command command); /* 42 */ EXTERN CONST86 char * TclpGetUserHome(const char *name, Tcl_DString *bufferPtr); /* Slot 43 is reserved */ /* 44 */ EXTERN int TclGuessPackageName(const char *fileName, Tcl_DString *bufPtr); /* 45 */ EXTERN int TclHideUnsafeCommands(Tcl_Interp *interp); /* 46 */ EXTERN int TclInExit(void); /* Slot 47 is reserved */ /* Slot 48 is reserved */ /* Slot 49 is reserved */ /* 50 */ EXTERN void TclInitCompiledLocals(Tcl_Interp *interp, CallFrame *framePtr, Namespace *nsPtr); /* 51 */ EXTERN int TclInterpInit(Tcl_Interp *interp); /* Slot 52 is reserved */ /* 53 */ EXTERN int TclInvokeObjectCommand(ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char **argv); /* 54 */ EXTERN int TclInvokeStringCommand(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 55 */ EXTERN Proc * TclIsProc(Command *cmdPtr); /* Slot 56 is reserved */ /* Slot 57 is reserved */ /* 58 */ EXTERN Var * TclLookupVar(Tcl_Interp *interp, const char *part1, const char *part2, int flags, const char *msg, int createPart1, int createPart2, Var **arrayPtrPtr); /* Slot 59 is reserved */ /* 60 */ EXTERN int TclNeedSpace(const char *start, const char *end); /* 61 */ EXTERN Tcl_Obj * TclNewProcBodyObj(Proc *procPtr); /* 62 */ EXTERN int TclObjCommandComplete(Tcl_Obj *cmdPtr); /* 63 */ EXTERN int TclObjInterpProc(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 64 */ EXTERN int TclObjInvoke(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* Slot 65 is reserved */ /* Slot 66 is reserved */ /* Slot 67 is reserved */ /* Slot 68 is reserved */ /* 69 */ EXTERN char * TclpAlloc(unsigned int size); /* Slot 70 is reserved */ /* Slot 71 is reserved */ /* Slot 72 is reserved */ /* Slot 73 is reserved */ /* 74 */ EXTERN void TclpFree(char *ptr); /* 75 */ EXTERN unsigned long TclpGetClicks(void); /* 76 */ EXTERN unsigned long TclpGetSeconds(void); /* 77 */ EXTERN void TclpGetTime(Tcl_Time *time); /* Slot 78 is reserved */ /* Slot 79 is reserved */ /* Slot 80 is reserved */ /* 81 */ EXTERN char * TclpRealloc(char *ptr, unsigned int size); /* Slot 82 is reserved */ /* Slot 83 is reserved */ /* Slot 84 is reserved */ /* Slot 85 is reserved */ /* Slot 86 is reserved */ /* Slot 87 is reserved */ /* 88 */ EXTERN char * TclPrecTraceProc(ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); /* 89 */ EXTERN int TclPreventAliasLoop(Tcl_Interp *interp, Tcl_Interp *cmdInterp, Tcl_Command cmd); /* Slot 90 is reserved */ /* 91 */ EXTERN void TclProcCleanupProc(Proc *procPtr); /* 92 */ EXTERN int TclProcCompileProc(Tcl_Interp *interp, Proc *procPtr, Tcl_Obj *bodyPtr, Namespace *nsPtr, const char *description, const char *procName); /* 93 */ EXTERN void TclProcDeleteProc(ClientData clientData); /* Slot 94 is reserved */ /* Slot 95 is reserved */ /* 96 */ EXTERN int TclRenameCommand(Tcl_Interp *interp, const char *oldName, const char *newName); /* 97 */ EXTERN void TclResetShadowedCmdRefs(Tcl_Interp *interp, Command *newCmdPtr); /* 98 */ EXTERN int TclServiceIdle(void); /* Slot 99 is reserved */ /* Slot 100 is reserved */ /* 101 */ EXTERN CONST86 char * TclSetPreInitScript(const char *string); /* 102 */ EXTERN void TclSetupEnv(Tcl_Interp *interp); /* 103 */ EXTERN int TclSockGetPort(Tcl_Interp *interp, const char *str, const char *proto, int *portPtr); /* 104 */ EXTERN int TclSockMinimumBuffersOld(int sock, int size); /* Slot 105 is reserved */ /* Slot 106 is reserved */ /* Slot 107 is reserved */ /* 108 */ EXTERN void TclTeardownNamespace(Namespace *nsPtr); /* 109 */ EXTERN int TclUpdateReturnInfo(Interp *iPtr); /* 110 */ EXTERN int TclSockMinimumBuffers(void *sock, int size); /* 111 */ EXTERN void Tcl_AddInterpResolvers(Tcl_Interp *interp, const char *name, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); /* 112 */ EXTERN int Tcl_AppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *objPtr); /* 113 */ EXTERN Tcl_Namespace * Tcl_CreateNamespace(Tcl_Interp *interp, const char *name, ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc); /* 114 */ EXTERN void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr); /* 115 */ EXTERN int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int resetListFirst); /* 116 */ EXTERN Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags); /* 117 */ EXTERN Tcl_Namespace * Tcl_FindNamespace(Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags); /* 118 */ EXTERN int Tcl_GetInterpResolvers(Tcl_Interp *interp, const char *name, Tcl_ResolverInfo *resInfo); /* 119 */ EXTERN int Tcl_GetNamespaceResolvers( Tcl_Namespace *namespacePtr, Tcl_ResolverInfo *resInfo); /* 120 */ EXTERN Tcl_Var Tcl_FindNamespaceVar(Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags); /* 121 */ EXTERN int Tcl_ForgetImport(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern); /* 122 */ EXTERN Tcl_Command Tcl_GetCommandFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr); /* 123 */ EXTERN void Tcl_GetCommandFullName(Tcl_Interp *interp, Tcl_Command command, Tcl_Obj *objPtr); /* 124 */ EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace(Tcl_Interp *interp); /* 125 */ EXTERN Tcl_Namespace * Tcl_GetGlobalNamespace(Tcl_Interp *interp); /* 126 */ EXTERN void Tcl_GetVariableFullName(Tcl_Interp *interp, Tcl_Var variable, Tcl_Obj *objPtr); /* 127 */ EXTERN int Tcl_Import(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int allowOverwrite); /* 128 */ EXTERN void Tcl_PopCallFrame(Tcl_Interp *interp); /* 129 */ EXTERN int Tcl_PushCallFrame(Tcl_Interp *interp, Tcl_CallFrame *framePtr, Tcl_Namespace *nsPtr, int isProcCallFrame); /* 130 */ EXTERN int Tcl_RemoveInterpResolvers(Tcl_Interp *interp, const char *name); /* 131 */ EXTERN void Tcl_SetNamespaceResolvers( Tcl_Namespace *namespacePtr, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); /* 132 */ EXTERN int TclpHasSockets(Tcl_Interp *interp); /* 133 */ EXTERN struct tm * TclpGetDate(const time_t *time, int useGMT); /* Slot 134 is reserved */ /* Slot 135 is reserved */ /* Slot 136 is reserved */ /* Slot 137 is reserved */ /* 138 */ EXTERN CONST84_RETURN char * TclGetEnv(const char *name, Tcl_DString *valuePtr); /* Slot 139 is reserved */ /* Slot 140 is reserved */ /* 141 */ EXTERN CONST84_RETURN char * TclpGetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 142 */ EXTERN int TclSetByteCodeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr, CompileHookProc *hookProc, ClientData clientData); /* 143 */ EXTERN int TclAddLiteralObj(struct CompileEnv *envPtr, Tcl_Obj *objPtr, LiteralEntry **litPtrPtr); /* 144 */ EXTERN void TclHideLiteral(Tcl_Interp *interp, struct CompileEnv *envPtr, int index); /* 145 */ EXTERN const struct AuxDataType * TclGetAuxDataType(const char *typeName); /* 146 */ EXTERN TclHandle TclHandleCreate(void *ptr); /* 147 */ EXTERN void TclHandleFree(TclHandle handle); /* 148 */ EXTERN TclHandle TclHandlePreserve(TclHandle handle); /* 149 */ EXTERN void TclHandleRelease(TclHandle handle); /* 150 */ EXTERN int TclRegAbout(Tcl_Interp *interp, Tcl_RegExp re); /* 151 */ EXTERN void TclRegExpRangeUniChar(Tcl_RegExp re, int index, int *startPtr, int *endPtr); /* 152 */ EXTERN void TclSetLibraryPath(Tcl_Obj *pathPtr); /* 153 */ EXTERN Tcl_Obj * TclGetLibraryPath(void); /* Slot 154 is reserved */ /* Slot 155 is reserved */ /* 156 */ EXTERN void TclRegError(Tcl_Interp *interp, const char *msg, int status); /* 157 */ EXTERN Var * TclVarTraceExists(Tcl_Interp *interp, const char *varName); /* 158 */ EXTERN void TclSetStartupScriptFileName(const char *filename); /* 159 */ EXTERN const char * TclGetStartupScriptFileName(void); /* Slot 160 is reserved */ /* 161 */ EXTERN int TclChannelTransform(Tcl_Interp *interp, Tcl_Channel chan, Tcl_Obj *cmdObjPtr); /* 162 */ EXTERN void TclChannelEventScriptInvoker(ClientData clientData, int flags); /* 163 */ EXTERN const void * TclGetInstructionTable(void); /* 164 */ EXTERN void TclExpandCodeArray(void *envPtr); /* 165 */ EXTERN void TclpSetInitialEncodings(void); /* 166 */ EXTERN int TclListObjSetElement(Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj *valuePtr); /* 167 */ EXTERN void TclSetStartupScriptPath(Tcl_Obj *pathPtr); /* 168 */ EXTERN Tcl_Obj * TclGetStartupScriptPath(void); /* 169 */ EXTERN int TclpUtfNcmp2(const char *s1, const char *s2, unsigned long n); /* 170 */ EXTERN int TclCheckInterpTraces(Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 171 */ EXTERN int TclCheckExecutionTraces(Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 172 */ EXTERN int TclInThreadExit(void); /* 173 */ EXTERN int TclUniCharMatch(const Tcl_UniChar *string, int strLen, const Tcl_UniChar *pattern, int ptnLen, int flags); /* Slot 174 is reserved */ /* 175 */ EXTERN int TclCallVarTraces(Interp *iPtr, Var *arrayPtr, Var *varPtr, const char *part1, const char *part2, int flags, int leaveErrMsg); /* 176 */ EXTERN void TclCleanupVar(Var *varPtr, Var *arrayPtr); /* 177 */ EXTERN void TclVarErrMsg(Tcl_Interp *interp, const char *part1, const char *part2, const char *operation, const char *reason); /* 178 */ EXTERN void Tcl_SetStartupScript(Tcl_Obj *pathPtr, const char *encodingName); /* 179 */ EXTERN Tcl_Obj * Tcl_GetStartupScript(const char **encodingNamePtr); /* Slot 180 is reserved */ /* Slot 181 is reserved */ /* 182 */ EXTERN struct tm * TclpLocaltime(const time_t *clock); /* 183 */ EXTERN struct tm * TclpGmtime(const time_t *clock); /* Slot 184 is reserved */ /* Slot 185 is reserved */ /* Slot 186 is reserved */ /* Slot 187 is reserved */ /* Slot 188 is reserved */ /* Slot 189 is reserved */ /* Slot 190 is reserved */ /* Slot 191 is reserved */ /* Slot 192 is reserved */ /* Slot 193 is reserved */ /* Slot 194 is reserved */ /* Slot 195 is reserved */ /* Slot 196 is reserved */ /* Slot 197 is reserved */ /* 198 */ EXTERN int TclObjGetFrame(Tcl_Interp *interp, Tcl_Obj *objPtr, CallFrame **framePtrPtr); /* Slot 199 is reserved */ /* 200 */ EXTERN int TclpObjRemoveDirectory(Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr); /* 201 */ EXTERN int TclpObjCopyDirectory(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr); /* 202 */ EXTERN int TclpObjCreateDirectory(Tcl_Obj *pathPtr); /* 203 */ EXTERN int TclpObjDeleteFile(Tcl_Obj *pathPtr); /* 204 */ EXTERN int TclpObjCopyFile(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 205 */ EXTERN int TclpObjRenameFile(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 206 */ EXTERN int TclpObjStat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 207 */ EXTERN int TclpObjAccess(Tcl_Obj *pathPtr, int mode); /* 208 */ EXTERN Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions); /* Slot 209 is reserved */ /* Slot 210 is reserved */ /* Slot 211 is reserved */ /* 212 */ EXTERN void TclpFindExecutable(const char *argv0); /* 213 */ EXTERN Tcl_Obj * TclGetObjNameOfExecutable(void); /* 214 */ EXTERN void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding); /* 215 */ EXTERN void * TclStackAlloc(Tcl_Interp *interp, int numBytes); /* 216 */ EXTERN void TclStackFree(Tcl_Interp *interp, void *freePtr); /* 217 */ EXTERN int TclPushStackFrame(Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame); /* 218 */ EXTERN void TclPopStackFrame(Tcl_Interp *interp); /* Slot 219 is reserved */ /* Slot 220 is reserved */ /* Slot 221 is reserved */ /* Slot 222 is reserved */ /* Slot 223 is reserved */ /* 224 */ EXTERN TclPlatformType * TclGetPlatform(void); /* 225 */ EXTERN Tcl_Obj * TclTraceDictPath(Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *const keyv[], int flags); /* 226 */ EXTERN int TclObjBeingDeleted(Tcl_Obj *objPtr); /* 227 */ EXTERN void TclSetNsPath(Namespace *nsPtr, int pathLength, Tcl_Namespace *pathAry[]); /* Slot 228 is reserved */ /* 229 */ EXTERN int TclPtrMakeUpvar(Tcl_Interp *interp, Var *otherP1Ptr, const char *myName, int myFlags, int index); /* 230 */ EXTERN Var * TclObjLookupVar(Tcl_Interp *interp, Tcl_Obj *part1Ptr, const char *part2, int flags, const char *msg, const int createPart1, const int createPart2, Var **arrayPtrPtr); /* 231 */ EXTERN int TclGetNamespaceFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr); /* 232 */ EXTERN int TclEvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word); /* 233 */ EXTERN void TclGetSrcInfoForPc(CmdFrame *contextPtr); /* 234 */ EXTERN Var * TclVarHashCreateVar(TclVarHashTable *tablePtr, const char *key, int *newPtr); /* 235 */ EXTERN void TclInitVarHashTable(TclVarHashTable *tablePtr, Namespace *nsPtr); /* 236 */ EXTERN void TclBackgroundException(Tcl_Interp *interp, int code); /* 237 */ EXTERN int TclResetCancellation(Tcl_Interp *interp, int force); /* 238 */ EXTERN int TclNRInterpProc(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 239 */ EXTERN int TclNRInterpProcCore(Tcl_Interp *interp, Tcl_Obj *procNameObj, int skip, ProcErrorProc *errorProc); /* 240 */ EXTERN int TclNRRunCallbacks(Tcl_Interp *interp, int result, struct NRE_callback *rootPtr); /* 241 */ EXTERN int TclNREvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word); /* 242 */ EXTERN int TclNREvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags, Command *cmdPtr); /* 243 */ EXTERN void TclDbDumpActiveObjects(FILE *outFile); /* 244 */ EXTERN Tcl_HashTable * TclGetNamespaceChildTable(Tcl_Namespace *nsPtr); /* 245 */ EXTERN Tcl_HashTable * TclGetNamespaceCommandTable(Tcl_Namespace *nsPtr); /* 246 */ EXTERN int TclInitRewriteEnsemble(Tcl_Interp *interp, int numRemoved, int numInserted, Tcl_Obj *const *objv); /* 247 */ EXTERN void TclResetRewriteEnsemble(Tcl_Interp *interp, int isRootEnsemble); /* 248 */ EXTERN int TclCopyChannel(Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr); /* 249 */ EXTERN char * TclDoubleDigits(double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 250 */ EXTERN void TclSetSlaveCancelFlags(Tcl_Interp *interp, int flags, int force); /* 251 */ EXTERN int TclRegisterLiteral(void *envPtr, char *bytes, int length, int flags); typedef struct TclIntStubs { int magic; void *hooks; void (*reserved0)(void); void (*reserved1)(void); void (*reserved2)(void); void (*tclAllocateFreeObjects) (void); /* 3 */ void (*reserved4)(void); int (*tclCleanupChildren) (Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan); /* 5 */ void (*tclCleanupCommand) (Command *cmdPtr); /* 6 */ int (*tclCopyAndCollapse) (int count, const char *src, char *dst); /* 7 */ int (*tclCopyChannelOld) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj *cmdPtr); /* 8 */ int (*tclCreatePipeline) (Tcl_Interp *interp, int argc, const char **argv, Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, TclFile *errFilePtr); /* 9 */ int (*tclCreateProc) (Tcl_Interp *interp, Namespace *nsPtr, const char *procName, Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Proc **procPtrPtr); /* 10 */ void (*tclDeleteCompiledLocalVars) (Interp *iPtr, CallFrame *framePtr); /* 11 */ void (*tclDeleteVars) (Interp *iPtr, TclVarHashTable *tablePtr); /* 12 */ void (*reserved13)(void); int (*tclDumpMemoryInfo) (ClientData clientData, int flags); /* 14 */ void (*reserved15)(void); void (*tclExprFloatError) (Tcl_Interp *interp, double value); /* 16 */ void (*reserved17)(void); void (*reserved18)(void); void (*reserved19)(void); void (*reserved20)(void); void (*reserved21)(void); int (*tclFindElement) (Tcl_Interp *interp, const char *listStr, int listLength, const char **elementPtr, const char **nextPtr, int *sizePtr, int *bracePtr); /* 22 */ Proc * (*tclFindProc) (Interp *iPtr, const char *procName); /* 23 */ int (*tclFormatInt) (char *buffer, long n); /* 24 */ void (*tclFreePackageInfo) (Interp *iPtr); /* 25 */ void (*reserved26)(void); void (*reserved27)(void); Tcl_Channel (*tclpGetDefaultStdChannel) (int type); /* 28 */ void (*reserved29)(void); void (*reserved30)(void); const char * (*tclGetExtension) (const char *name); /* 31 */ int (*tclGetFrame) (Tcl_Interp *interp, const char *str, CallFrame **framePtrPtr); /* 32 */ void (*reserved33)(void); int (*tclGetIntForIndex) (Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr); /* 34 */ void (*reserved35)(void); void (*reserved36)(void); int (*tclGetLoadedPackages) (Tcl_Interp *interp, const char *targetName); /* 37 */ int (*tclGetNamespaceForQualName) (Tcl_Interp *interp, const char *qualName, Namespace *cxtNsPtr, int flags, Namespace **nsPtrPtr, Namespace **altNsPtrPtr, Namespace **actualCxtPtrPtr, const char **simpleNamePtr); /* 38 */ TclObjCmdProcType (*tclGetObjInterpProc) (void); /* 39 */ int (*tclGetOpenMode) (Tcl_Interp *interp, const char *str, int *seekFlagPtr); /* 40 */ Tcl_Command (*tclGetOriginalCommand) (Tcl_Command command); /* 41 */ CONST86 char * (*tclpGetUserHome) (const char *name, Tcl_DString *bufferPtr); /* 42 */ void (*reserved43)(void); int (*tclGuessPackageName) (const char *fileName, Tcl_DString *bufPtr); /* 44 */ int (*tclHideUnsafeCommands) (Tcl_Interp *interp); /* 45 */ int (*tclInExit) (void); /* 46 */ void (*reserved47)(void); void (*reserved48)(void); void (*reserved49)(void); void (*tclInitCompiledLocals) (Tcl_Interp *interp, CallFrame *framePtr, Namespace *nsPtr); /* 50 */ int (*tclInterpInit) (Tcl_Interp *interp); /* 51 */ void (*reserved52)(void); int (*tclInvokeObjectCommand) (ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char **argv); /* 53 */ int (*tclInvokeStringCommand) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 54 */ Proc * (*tclIsProc) (Command *cmdPtr); /* 55 */ void (*reserved56)(void); void (*reserved57)(void); Var * (*tclLookupVar) (Tcl_Interp *interp, const char *part1, const char *part2, int flags, const char *msg, int createPart1, int createPart2, Var **arrayPtrPtr); /* 58 */ void (*reserved59)(void); int (*tclNeedSpace) (const char *start, const char *end); /* 60 */ Tcl_Obj * (*tclNewProcBodyObj) (Proc *procPtr); /* 61 */ int (*tclObjCommandComplete) (Tcl_Obj *cmdPtr); /* 62 */ int (*tclObjInterpProc) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 63 */ int (*tclObjInvoke) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 64 */ void (*reserved65)(void); void (*reserved66)(void); void (*reserved67)(void); void (*reserved68)(void); char * (*tclpAlloc) (unsigned int size); /* 69 */ void (*reserved70)(void); void (*reserved71)(void); void (*reserved72)(void); void (*reserved73)(void); void (*tclpFree) (char *ptr); /* 74 */ unsigned long (*tclpGetClicks) (void); /* 75 */ unsigned long (*tclpGetSeconds) (void); /* 76 */ void (*tclpGetTime) (Tcl_Time *time); /* 77 */ void (*reserved78)(void); void (*reserved79)(void); void (*reserved80)(void); char * (*tclpRealloc) (char *ptr, unsigned int size); /* 81 */ void (*reserved82)(void); void (*reserved83)(void); void (*reserved84)(void); void (*reserved85)(void); void (*reserved86)(void); void (*reserved87)(void); char * (*tclPrecTraceProc) (ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); /* 88 */ int (*tclPreventAliasLoop) (Tcl_Interp *interp, Tcl_Interp *cmdInterp, Tcl_Command cmd); /* 89 */ void (*reserved90)(void); void (*tclProcCleanupProc) (Proc *procPtr); /* 91 */ int (*tclProcCompileProc) (Tcl_Interp *interp, Proc *procPtr, Tcl_Obj *bodyPtr, Namespace *nsPtr, const char *description, const char *procName); /* 92 */ void (*tclProcDeleteProc) (ClientData clientData); /* 93 */ void (*reserved94)(void); void (*reserved95)(void); int (*tclRenameCommand) (Tcl_Interp *interp, const char *oldName, const char *newName); /* 96 */ void (*tclResetShadowedCmdRefs) (Tcl_Interp *interp, Command *newCmdPtr); /* 97 */ int (*tclServiceIdle) (void); /* 98 */ void (*reserved99)(void); void (*reserved100)(void); CONST86 char * (*tclSetPreInitScript) (const char *string); /* 101 */ void (*tclSetupEnv) (Tcl_Interp *interp); /* 102 */ int (*tclSockGetPort) (Tcl_Interp *interp, const char *str, const char *proto, int *portPtr); /* 103 */ int (*tclSockMinimumBuffersOld) (int sock, int size); /* 104 */ void (*reserved105)(void); void (*reserved106)(void); void (*reserved107)(void); void (*tclTeardownNamespace) (Namespace *nsPtr); /* 108 */ int (*tclUpdateReturnInfo) (Interp *iPtr); /* 109 */ int (*tclSockMinimumBuffers) (void *sock, int size); /* 110 */ void (*tcl_AddInterpResolvers) (Tcl_Interp *interp, const char *name, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); /* 111 */ int (*tcl_AppendExportList) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *objPtr); /* 112 */ Tcl_Namespace * (*tcl_CreateNamespace) (Tcl_Interp *interp, const char *name, ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc); /* 113 */ void (*tcl_DeleteNamespace) (Tcl_Namespace *nsPtr); /* 114 */ int (*tcl_Export) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int resetListFirst); /* 115 */ Tcl_Command (*tcl_FindCommand) (Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags); /* 116 */ Tcl_Namespace * (*tcl_FindNamespace) (Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags); /* 117 */ int (*tcl_GetInterpResolvers) (Tcl_Interp *interp, const char *name, Tcl_ResolverInfo *resInfo); /* 118 */ int (*tcl_GetNamespaceResolvers) (Tcl_Namespace *namespacePtr, Tcl_ResolverInfo *resInfo); /* 119 */ Tcl_Var (*tcl_FindNamespaceVar) (Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags); /* 120 */ int (*tcl_ForgetImport) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern); /* 121 */ Tcl_Command (*tcl_GetCommandFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 122 */ void (*tcl_GetCommandFullName) (Tcl_Interp *interp, Tcl_Command command, Tcl_Obj *objPtr); /* 123 */ Tcl_Namespace * (*tcl_GetCurrentNamespace) (Tcl_Interp *interp); /* 124 */ Tcl_Namespace * (*tcl_GetGlobalNamespace) (Tcl_Interp *interp); /* 125 */ void (*tcl_GetVariableFullName) (Tcl_Interp *interp, Tcl_Var variable, Tcl_Obj *objPtr); /* 126 */ int (*tcl_Import) (Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int allowOverwrite); /* 127 */ void (*tcl_PopCallFrame) (Tcl_Interp *interp); /* 128 */ int (*tcl_PushCallFrame) (Tcl_Interp *interp, Tcl_CallFrame *framePtr, Tcl_Namespace *nsPtr, int isProcCallFrame); /* 129 */ int (*tcl_RemoveInterpResolvers) (Tcl_Interp *interp, const char *name); /* 130 */ void (*tcl_SetNamespaceResolvers) (Tcl_Namespace *namespacePtr, Tcl_ResolveCmdProc *cmdProc, Tcl_ResolveVarProc *varProc, Tcl_ResolveCompiledVarProc *compiledVarProc); /* 131 */ int (*tclpHasSockets) (Tcl_Interp *interp); /* 132 */ struct tm * (*tclpGetDate) (const time_t *time, int useGMT); /* 133 */ void (*reserved134)(void); void (*reserved135)(void); void (*reserved136)(void); void (*reserved137)(void); CONST84_RETURN char * (*tclGetEnv) (const char *name, Tcl_DString *valuePtr); /* 138 */ void (*reserved139)(void); void (*reserved140)(void); CONST84_RETURN char * (*tclpGetCwd) (Tcl_Interp *interp, Tcl_DString *cwdPtr); /* 141 */ int (*tclSetByteCodeFromAny) (Tcl_Interp *interp, Tcl_Obj *objPtr, CompileHookProc *hookProc, ClientData clientData); /* 142 */ int (*tclAddLiteralObj) (struct CompileEnv *envPtr, Tcl_Obj *objPtr, LiteralEntry **litPtrPtr); /* 143 */ void (*tclHideLiteral) (Tcl_Interp *interp, struct CompileEnv *envPtr, int index); /* 144 */ const struct AuxDataType * (*tclGetAuxDataType) (const char *typeName); /* 145 */ TclHandle (*tclHandleCreate) (void *ptr); /* 146 */ void (*tclHandleFree) (TclHandle handle); /* 147 */ TclHandle (*tclHandlePreserve) (TclHandle handle); /* 148 */ void (*tclHandleRelease) (TclHandle handle); /* 149 */ int (*tclRegAbout) (Tcl_Interp *interp, Tcl_RegExp re); /* 150 */ void (*tclRegExpRangeUniChar) (Tcl_RegExp re, int index, int *startPtr, int *endPtr); /* 151 */ void (*tclSetLibraryPath) (Tcl_Obj *pathPtr); /* 152 */ Tcl_Obj * (*tclGetLibraryPath) (void); /* 153 */ void (*reserved154)(void); void (*reserved155)(void); void (*tclRegError) (Tcl_Interp *interp, const char *msg, int status); /* 156 */ Var * (*tclVarTraceExists) (Tcl_Interp *interp, const char *varName); /* 157 */ void (*tclSetStartupScriptFileName) (const char *filename); /* 158 */ const char * (*tclGetStartupScriptFileName) (void); /* 159 */ void (*reserved160)(void); int (*tclChannelTransform) (Tcl_Interp *interp, Tcl_Channel chan, Tcl_Obj *cmdObjPtr); /* 161 */ void (*tclChannelEventScriptInvoker) (ClientData clientData, int flags); /* 162 */ const void * (*tclGetInstructionTable) (void); /* 163 */ void (*tclExpandCodeArray) (void *envPtr); /* 164 */ void (*tclpSetInitialEncodings) (void); /* 165 */ int (*tclListObjSetElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj *valuePtr); /* 166 */ void (*tclSetStartupScriptPath) (Tcl_Obj *pathPtr); /* 167 */ Tcl_Obj * (*tclGetStartupScriptPath) (void); /* 168 */ int (*tclpUtfNcmp2) (const char *s1, const char *s2, unsigned long n); /* 169 */ int (*tclCheckInterpTraces) (Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 170 */ int (*tclCheckExecutionTraces) (Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 171 */ int (*tclInThreadExit) (void); /* 172 */ int (*tclUniCharMatch) (const Tcl_UniChar *string, int strLen, const Tcl_UniChar *pattern, int ptnLen, int flags); /* 173 */ void (*reserved174)(void); int (*tclCallVarTraces) (Interp *iPtr, Var *arrayPtr, Var *varPtr, const char *part1, const char *part2, int flags, int leaveErrMsg); /* 175 */ void (*tclCleanupVar) (Var *varPtr, Var *arrayPtr); /* 176 */ void (*tclVarErrMsg) (Tcl_Interp *interp, const char *part1, const char *part2, const char *operation, const char *reason); /* 177 */ void (*tcl_SetStartupScript) (Tcl_Obj *pathPtr, const char *encodingName); /* 178 */ Tcl_Obj * (*tcl_GetStartupScript) (const char **encodingNamePtr); /* 179 */ void (*reserved180)(void); void (*reserved181)(void); struct tm * (*tclpLocaltime) (const time_t *clock); /* 182 */ struct tm * (*tclpGmtime) (const time_t *clock); /* 183 */ void (*reserved184)(void); void (*reserved185)(void); void (*reserved186)(void); void (*reserved187)(void); void (*reserved188)(void); void (*reserved189)(void); void (*reserved190)(void); void (*reserved191)(void); void (*reserved192)(void); void (*reserved193)(void); void (*reserved194)(void); void (*reserved195)(void); void (*reserved196)(void); void (*reserved197)(void); int (*tclObjGetFrame) (Tcl_Interp *interp, Tcl_Obj *objPtr, CallFrame **framePtrPtr); /* 198 */ void (*reserved199)(void); int (*tclpObjRemoveDirectory) (Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr); /* 200 */ int (*tclpObjCopyDirectory) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr); /* 201 */ int (*tclpObjCreateDirectory) (Tcl_Obj *pathPtr); /* 202 */ int (*tclpObjDeleteFile) (Tcl_Obj *pathPtr); /* 203 */ int (*tclpObjCopyFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 204 */ int (*tclpObjRenameFile) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); /* 205 */ int (*tclpObjStat) (Tcl_Obj *pathPtr, Tcl_StatBuf *buf); /* 206 */ int (*tclpObjAccess) (Tcl_Obj *pathPtr, int mode); /* 207 */ Tcl_Channel (*tclpOpenFileChannel) (Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions); /* 208 */ void (*reserved209)(void); void (*reserved210)(void); void (*reserved211)(void); void (*tclpFindExecutable) (const char *argv0); /* 212 */ Tcl_Obj * (*tclGetObjNameOfExecutable) (void); /* 213 */ void (*tclSetObjNameOfExecutable) (Tcl_Obj *name, Tcl_Encoding encoding); /* 214 */ void * (*tclStackAlloc) (Tcl_Interp *interp, int numBytes); /* 215 */ void (*tclStackFree) (Tcl_Interp *interp, void *freePtr); /* 216 */ int (*tclPushStackFrame) (Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame); /* 217 */ void (*tclPopStackFrame) (Tcl_Interp *interp); /* 218 */ void (*reserved219)(void); void (*reserved220)(void); void (*reserved221)(void); void (*reserved222)(void); void (*reserved223)(void); TclPlatformType * (*tclGetPlatform) (void); /* 224 */ Tcl_Obj * (*tclTraceDictPath) (Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *const keyv[], int flags); /* 225 */ int (*tclObjBeingDeleted) (Tcl_Obj *objPtr); /* 226 */ void (*tclSetNsPath) (Namespace *nsPtr, int pathLength, Tcl_Namespace *pathAry[]); /* 227 */ void (*reserved228)(void); int (*tclPtrMakeUpvar) (Tcl_Interp *interp, Var *otherP1Ptr, const char *myName, int myFlags, int index); /* 229 */ Var * (*tclObjLookupVar) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, const char *part2, int flags, const char *msg, const int createPart1, const int createPart2, Var **arrayPtrPtr); /* 230 */ int (*tclGetNamespaceFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr); /* 231 */ int (*tclEvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word); /* 232 */ void (*tclGetSrcInfoForPc) (CmdFrame *contextPtr); /* 233 */ Var * (*tclVarHashCreateVar) (TclVarHashTable *tablePtr, const char *key, int *newPtr); /* 234 */ void (*tclInitVarHashTable) (TclVarHashTable *tablePtr, Namespace *nsPtr); /* 235 */ void (*tclBackgroundException) (Tcl_Interp *interp, int code); /* 236 */ int (*tclResetCancellation) (Tcl_Interp *interp, int force); /* 237 */ int (*tclNRInterpProc) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 238 */ int (*tclNRInterpProcCore) (Tcl_Interp *interp, Tcl_Obj *procNameObj, int skip, ProcErrorProc *errorProc); /* 239 */ int (*tclNRRunCallbacks) (Tcl_Interp *interp, int result, struct NRE_callback *rootPtr); /* 240 */ int (*tclNREvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word); /* 241 */ int (*tclNREvalObjv) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags, Command *cmdPtr); /* 242 */ void (*tclDbDumpActiveObjects) (FILE *outFile); /* 243 */ Tcl_HashTable * (*tclGetNamespaceChildTable) (Tcl_Namespace *nsPtr); /* 244 */ Tcl_HashTable * (*tclGetNamespaceCommandTable) (Tcl_Namespace *nsPtr); /* 245 */ int (*tclInitRewriteEnsemble) (Tcl_Interp *interp, int numRemoved, int numInserted, Tcl_Obj *const *objv); /* 246 */ void (*tclResetRewriteEnsemble) (Tcl_Interp *interp, int isRootEnsemble); /* 247 */ int (*tclCopyChannel) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr); /* 248 */ char * (*tclDoubleDigits) (double dv, int ndigits, int flags, int *decpt, int *signum, char **endPtr); /* 249 */ void (*tclSetSlaveCancelFlags) (Tcl_Interp *interp, int flags, int force); /* 250 */ int (*tclRegisterLiteral) (void *envPtr, char *bytes, int length, int flags); /* 251 */ } TclIntStubs; extern const TclIntStubs *tclIntStubsPtr; #ifdef __cplusplus } #endif #if defined(USE_TCL_STUBS) /* * Inline function declarations: */ /* Slot 0 is reserved */ /* Slot 1 is reserved */ /* Slot 2 is reserved */ #define TclAllocateFreeObjects \ (tclIntStubsPtr->tclAllocateFreeObjects) /* 3 */ /* Slot 4 is reserved */ #define TclCleanupChildren \ (tclIntStubsPtr->tclCleanupChildren) /* 5 */ #define TclCleanupCommand \ (tclIntStubsPtr->tclCleanupCommand) /* 6 */ #define TclCopyAndCollapse \ (tclIntStubsPtr->tclCopyAndCollapse) /* 7 */ #define TclCopyChannelOld \ (tclIntStubsPtr->tclCopyChannelOld) /* 8 */ #define TclCreatePipeline \ (tclIntStubsPtr->tclCreatePipeline) /* 9 */ #define TclCreateProc \ (tclIntStubsPtr->tclCreateProc) /* 10 */ #define TclDeleteCompiledLocalVars \ (tclIntStubsPtr->tclDeleteCompiledLocalVars) /* 11 */ #define TclDeleteVars \ (tclIntStubsPtr->tclDeleteVars) /* 12 */ /* Slot 13 is reserved */ #define TclDumpMemoryInfo \ (tclIntStubsPtr->tclDumpMemoryInfo) /* 14 */ /* Slot 15 is reserved */ #define TclExprFloatError \ (tclIntStubsPtr->tclExprFloatError) /* 16 */ /* Slot 17 is reserved */ /* Slot 18 is reserved */ /* Slot 19 is reserved */ /* Slot 20 is reserved */ /* Slot 21 is reserved */ #define TclFindElement \ (tclIntStubsPtr->tclFindElement) /* 22 */ #define TclFindProc \ (tclIntStubsPtr->tclFindProc) /* 23 */ #define TclFormatInt \ (tclIntStubsPtr->tclFormatInt) /* 24 */ #define TclFreePackageInfo \ (tclIntStubsPtr->tclFreePackageInfo) /* 25 */ /* Slot 26 is reserved */ /* Slot 27 is reserved */ #define TclpGetDefaultStdChannel \ (tclIntStubsPtr->tclpGetDefaultStdChannel) /* 28 */ /* Slot 29 is reserved */ /* Slot 30 is reserved */ #define TclGetExtension \ (tclIntStubsPtr->tclGetExtension) /* 31 */ #define TclGetFrame \ (tclIntStubsPtr->tclGetFrame) /* 32 */ /* Slot 33 is reserved */ #define TclGetIntForIndex \ (tclIntStubsPtr->tclGetIntForIndex) /* 34 */ /* Slot 35 is reserved */ /* Slot 36 is reserved */ #define TclGetLoadedPackages \ (tclIntStubsPtr->tclGetLoadedPackages) /* 37 */ #define TclGetNamespaceForQualName \ (tclIntStubsPtr->tclGetNamespaceForQualName) /* 38 */ #define TclGetObjInterpProc \ (tclIntStubsPtr->tclGetObjInterpProc) /* 39 */ #define TclGetOpenMode \ (tclIntStubsPtr->tclGetOpenMode) /* 40 */ #define TclGetOriginalCommand \ (tclIntStubsPtr->tclGetOriginalCommand) /* 41 */ #define TclpGetUserHome \ (tclIntStubsPtr->tclpGetUserHome) /* 42 */ /* Slot 43 is reserved */ #define TclGuessPackageName \ (tclIntStubsPtr->tclGuessPackageName) /* 44 */ #define TclHideUnsafeCommands \ (tclIntStubsPtr->tclHideUnsafeCommands) /* 45 */ #define TclInExit \ (tclIntStubsPtr->tclInExit) /* 46 */ /* Slot 47 is reserved */ /* Slot 48 is reserved */ /* Slot 49 is reserved */ #define TclInitCompiledLocals \ (tclIntStubsPtr->tclInitCompiledLocals) /* 50 */ #define TclInterpInit \ (tclIntStubsPtr->tclInterpInit) /* 51 */ /* Slot 52 is reserved */ #define TclInvokeObjectCommand \ (tclIntStubsPtr->tclInvokeObjectCommand) /* 53 */ #define TclInvokeStringCommand \ (tclIntStubsPtr->tclInvokeStringCommand) /* 54 */ #define TclIsProc \ (tclIntStubsPtr->tclIsProc) /* 55 */ /* Slot 56 is reserved */ /* Slot 57 is reserved */ #define TclLookupVar \ (tclIntStubsPtr->tclLookupVar) /* 58 */ /* Slot 59 is reserved */ #define TclNeedSpace \ (tclIntStubsPtr->tclNeedSpace) /* 60 */ #define TclNewProcBodyObj \ (tclIntStubsPtr->tclNewProcBodyObj) /* 61 */ #define TclObjCommandComplete \ (tclIntStubsPtr->tclObjCommandComplete) /* 62 */ #define TclObjInterpProc \ (tclIntStubsPtr->tclObjInterpProc) /* 63 */ #define TclObjInvoke \ (tclIntStubsPtr->tclObjInvoke) /* 64 */ /* Slot 65 is reserved */ /* Slot 66 is reserved */ /* Slot 67 is reserved */ /* Slot 68 is reserved */ #define TclpAlloc \ (tclIntStubsPtr->tclpAlloc) /* 69 */ /* Slot 70 is reserved */ /* Slot 71 is reserved */ /* Slot 72 is reserved */ /* Slot 73 is reserved */ #define TclpFree \ (tclIntStubsPtr->tclpFree) /* 74 */ #define TclpGetClicks \ (tclIntStubsPtr->tclpGetClicks) /* 75 */ #define TclpGetSeconds \ (tclIntStubsPtr->tclpGetSeconds) /* 76 */ #define TclpGetTime \ (tclIntStubsPtr->tclpGetTime) /* 77 */ /* Slot 78 is reserved */ /* Slot 79 is reserved */ /* Slot 80 is reserved */ #define TclpRealloc \ (tclIntStubsPtr->tclpRealloc) /* 81 */ /* Slot 82 is reserved */ /* Slot 83 is reserved */ /* Slot 84 is reserved */ /* Slot 85 is reserved */ /* Slot 86 is reserved */ /* Slot 87 is reserved */ #define TclPrecTraceProc \ (tclIntStubsPtr->tclPrecTraceProc) /* 88 */ #define TclPreventAliasLoop \ (tclIntStubsPtr->tclPreventAliasLoop) /* 89 */ /* Slot 90 is reserved */ #define TclProcCleanupProc \ (tclIntStubsPtr->tclProcCleanupProc) /* 91 */ #define TclProcCompileProc \ (tclIntStubsPtr->tclProcCompileProc) /* 92 */ #define TclProcDeleteProc \ (tclIntStubsPtr->tclProcDeleteProc) /* 93 */ /* Slot 94 is reserved */ /* Slot 95 is reserved */ #define TclRenameCommand \ (tclIntStubsPtr->tclRenameCommand) /* 96 */ #define TclResetShadowedCmdRefs \ (tclIntStubsPtr->tclResetShadowedCmdRefs) /* 97 */ #define TclServiceIdle \ (tclIntStubsPtr->tclServiceIdle) /* 98 */ /* Slot 99 is reserved */ /* Slot 100 is reserved */ #define TclSetPreInitScript \ (tclIntStubsPtr->tclSetPreInitScript) /* 101 */ #define TclSetupEnv \ (tclIntStubsPtr->tclSetupEnv) /* 102 */ #define TclSockGetPort \ (tclIntStubsPtr->tclSockGetPort) /* 103 */ #define TclSockMinimumBuffersOld \ (tclIntStubsPtr->tclSockMinimumBuffersOld) /* 104 */ /* Slot 105 is reserved */ /* Slot 106 is reserved */ /* Slot 107 is reserved */ #define TclTeardownNamespace \ (tclIntStubsPtr->tclTeardownNamespace) /* 108 */ #define TclUpdateReturnInfo \ (tclIntStubsPtr->tclUpdateReturnInfo) /* 109 */ #define TclSockMinimumBuffers \ (tclIntStubsPtr->tclSockMinimumBuffers) /* 110 */ #define Tcl_AddInterpResolvers \ (tclIntStubsPtr->tcl_AddInterpResolvers) /* 111 */ #define Tcl_AppendExportList \ (tclIntStubsPtr->tcl_AppendExportList) /* 112 */ #define Tcl_CreateNamespace \ (tclIntStubsPtr->tcl_CreateNamespace) /* 113 */ #define Tcl_DeleteNamespace \ (tclIntStubsPtr->tcl_DeleteNamespace) /* 114 */ #define Tcl_Export \ (tclIntStubsPtr->tcl_Export) /* 115 */ #define Tcl_FindCommand \ (tclIntStubsPtr->tcl_FindCommand) /* 116 */ #define Tcl_FindNamespace \ (tclIntStubsPtr->tcl_FindNamespace) /* 117 */ #define Tcl_GetInterpResolvers \ (tclIntStubsPtr->tcl_GetInterpResolvers) /* 118 */ #define Tcl_GetNamespaceResolvers \ (tclIntStubsPtr->tcl_GetNamespaceResolvers) /* 119 */ #define Tcl_FindNamespaceVar \ (tclIntStubsPtr->tcl_FindNamespaceVar) /* 120 */ #define Tcl_ForgetImport \ (tclIntStubsPtr->tcl_ForgetImport) /* 121 */ #define Tcl_GetCommandFromObj \ (tclIntStubsPtr->tcl_GetCommandFromObj) /* 122 */ #define Tcl_GetCommandFullName \ (tclIntStubsPtr->tcl_GetCommandFullName) /* 123 */ #define Tcl_GetCurrentNamespace \ (tclIntStubsPtr->tcl_GetCurrentNamespace) /* 124 */ #define Tcl_GetGlobalNamespace \ (tclIntStubsPtr->tcl_GetGlobalNamespace) /* 125 */ #define Tcl_GetVariableFullName \ (tclIntStubsPtr->tcl_GetVariableFullName) /* 126 */ #define Tcl_Import \ (tclIntStubsPtr->tcl_Import) /* 127 */ #define Tcl_PopCallFrame \ (tclIntStubsPtr->tcl_PopCallFrame) /* 128 */ #define Tcl_PushCallFrame \ (tclIntStubsPtr->tcl_PushCallFrame) /* 129 */ #define Tcl_RemoveInterpResolvers \ (tclIntStubsPtr->tcl_RemoveInterpResolvers) /* 130 */ #define Tcl_SetNamespaceResolvers \ (tclIntStubsPtr->tcl_SetNamespaceResolvers) /* 131 */ #define TclpHasSockets \ (tclIntStubsPtr->tclpHasSockets) /* 132 */ #define TclpGetDate \ (tclIntStubsPtr->tclpGetDate) /* 133 */ /* Slot 134 is reserved */ /* Slot 135 is reserved */ /* Slot 136 is reserved */ /* Slot 137 is reserved */ #define TclGetEnv \ (tclIntStubsPtr->tclGetEnv) /* 138 */ /* Slot 139 is reserved */ /* Slot 140 is reserved */ #define TclpGetCwd \ (tclIntStubsPtr->tclpGetCwd) /* 141 */ #define TclSetByteCodeFromAny \ (tclIntStubsPtr->tclSetByteCodeFromAny) /* 142 */ #define TclAddLiteralObj \ (tclIntStubsPtr->tclAddLiteralObj) /* 143 */ #define TclHideLiteral \ (tclIntStubsPtr->tclHideLiteral) /* 144 */ #define TclGetAuxDataType \ (tclIntStubsPtr->tclGetAuxDataType) /* 145 */ #define TclHandleCreate \ (tclIntStubsPtr->tclHandleCreate) /* 146 */ #define TclHandleFree \ (tclIntStubsPtr->tclHandleFree) /* 147 */ #define TclHandlePreserve \ (tclIntStubsPtr->tclHandlePreserve) /* 148 */ #define TclHandleRelease \ (tclIntStubsPtr->tclHandleRelease) /* 149 */ #define TclRegAbout \ (tclIntStubsPtr->tclRegAbout) /* 150 */ #define TclRegExpRangeUniChar \ (tclIntStubsPtr->tclRegExpRangeUniChar) /* 151 */ #define TclSetLibraryPath \ (tclIntStubsPtr->tclSetLibraryPath) /* 152 */ #define TclGetLibraryPath \ (tclIntStubsPtr->tclGetLibraryPath) /* 153 */ /* Slot 154 is reserved */ /* Slot 155 is reserved */ #define TclRegError \ (tclIntStubsPtr->tclRegError) /* 156 */ #define TclVarTraceExists \ (tclIntStubsPtr->tclVarTraceExists) /* 157 */ #define TclSetStartupScriptFileName \ (tclIntStubsPtr->tclSetStartupScriptFileName) /* 158 */ #define TclGetStartupScriptFileName \ (tclIntStubsPtr->tclGetStartupScriptFileName) /* 159 */ /* Slot 160 is reserved */ #define TclChannelTransform \ (tclIntStubsPtr->tclChannelTransform) /* 161 */ #define TclChannelEventScriptInvoker \ (tclIntStubsPtr->tclChannelEventScriptInvoker) /* 162 */ #define TclGetInstructionTable \ (tclIntStubsPtr->tclGetInstructionTable) /* 163 */ #define TclExpandCodeArray \ (tclIntStubsPtr->tclExpandCodeArray) /* 164 */ #define TclpSetInitialEncodings \ (tclIntStubsPtr->tclpSetInitialEncodings) /* 165 */ #define TclListObjSetElement \ (tclIntStubsPtr->tclListObjSetElement) /* 166 */ #define TclSetStartupScriptPath \ (tclIntStubsPtr->tclSetStartupScriptPath) /* 167 */ #define TclGetStartupScriptPath \ (tclIntStubsPtr->tclGetStartupScriptPath) /* 168 */ #define TclpUtfNcmp2 \ (tclIntStubsPtr->tclpUtfNcmp2) /* 169 */ #define TclCheckInterpTraces \ (tclIntStubsPtr->tclCheckInterpTraces) /* 170 */ #define TclCheckExecutionTraces \ (tclIntStubsPtr->tclCheckExecutionTraces) /* 171 */ #define TclInThreadExit \ (tclIntStubsPtr->tclInThreadExit) /* 172 */ #define TclUniCharMatch \ (tclIntStubsPtr->tclUniCharMatch) /* 173 */ /* Slot 174 is reserved */ #define TclCallVarTraces \ (tclIntStubsPtr->tclCallVarTraces) /* 175 */ #define TclCleanupVar \ (tclIntStubsPtr->tclCleanupVar) /* 176 */ #define TclVarErrMsg \ (tclIntStubsPtr->tclVarErrMsg) /* 177 */ #define Tcl_SetStartupScript \ (tclIntStubsPtr->tcl_SetStartupScript) /* 178 */ #define Tcl_GetStartupScript \ (tclIntStubsPtr->tcl_GetStartupScript) /* 179 */ /* Slot 180 is reserved */ /* Slot 181 is reserved */ #define TclpLocaltime \ (tclIntStubsPtr->tclpLocaltime) /* 182 */ #define TclpGmtime \ (tclIntStubsPtr->tclpGmtime) /* 183 */ /* Slot 184 is reserved */ /* Slot 185 is reserved */ /* Slot 186 is reserved */ /* Slot 187 is reserved */ /* Slot 188 is reserved */ /* Slot 189 is reserved */ /* Slot 190 is reserved */ /* Slot 191 is reserved */ /* Slot 192 is reserved */ /* Slot 193 is reserved */ /* Slot 194 is reserved */ /* Slot 195 is reserved */ /* Slot 196 is reserved */ /* Slot 197 is reserved */ #define TclObjGetFrame \ (tclIntStubsPtr->tclObjGetFrame) /* 198 */ /* Slot 199 is reserved */ #define TclpObjRemoveDirectory \ (tclIntStubsPtr->tclpObjRemoveDirectory) /* 200 */ #define TclpObjCopyDirectory \ (tclIntStubsPtr->tclpObjCopyDirectory) /* 201 */ #define TclpObjCreateDirectory \ (tclIntStubsPtr->tclpObjCreateDirectory) /* 202 */ #define TclpObjDeleteFile \ (tclIntStubsPtr->tclpObjDeleteFile) /* 203 */ #define TclpObjCopyFile \ (tclIntStubsPtr->tclpObjCopyFile) /* 204 */ #define TclpObjRenameFile \ (tclIntStubsPtr->tclpObjRenameFile) /* 205 */ #define TclpObjStat \ (tclIntStubsPtr->tclpObjStat) /* 206 */ #define TclpObjAccess \ (tclIntStubsPtr->tclpObjAccess) /* 207 */ #define TclpOpenFileChannel \ (tclIntStubsPtr->tclpOpenFileChannel) /* 208 */ /* Slot 209 is reserved */ /* Slot 210 is reserved */ /* Slot 211 is reserved */ #define TclpFindExecutable \ (tclIntStubsPtr->tclpFindExecutable) /* 212 */ #define TclGetObjNameOfExecutable \ (tclIntStubsPtr->tclGetObjNameOfExecutable) /* 213 */ #define TclSetObjNameOfExecutable \ (tclIntStubsPtr->tclSetObjNameOfExecutable) /* 214 */ #define TclStackAlloc \ (tclIntStubsPtr->tclStackAlloc) /* 215 */ #define TclStackFree \ (tclIntStubsPtr->tclStackFree) /* 216 */ #define TclPushStackFrame \ (tclIntStubsPtr->tclPushStackFrame) /* 217 */ #define TclPopStackFrame \ (tclIntStubsPtr->tclPopStackFrame) /* 218 */ /* Slot 219 is reserved */ /* Slot 220 is reserved */ /* Slot 221 is reserved */ /* Slot 222 is reserved */ /* Slot 223 is reserved */ #define TclGetPlatform \ (tclIntStubsPtr->tclGetPlatform) /* 224 */ #define TclTraceDictPath \ (tclIntStubsPtr->tclTraceDictPath) /* 225 */ #define TclObjBeingDeleted \ (tclIntStubsPtr->tclObjBeingDeleted) /* 226 */ #define TclSetNsPath \ (tclIntStubsPtr->tclSetNsPath) /* 227 */ /* Slot 228 is reserved */ #define TclPtrMakeUpvar \ (tclIntStubsPtr->tclPtrMakeUpvar) /* 229 */ #define TclObjLookupVar \ (tclIntStubsPtr->tclObjLookupVar) /* 230 */ #define TclGetNamespaceFromObj \ (tclIntStubsPtr->tclGetNamespaceFromObj) /* 231 */ #define TclEvalObjEx \ (tclIntStubsPtr->tclEvalObjEx) /* 232 */ #define TclGetSrcInfoForPc \ (tclIntStubsPtr->tclGetSrcInfoForPc) /* 233 */ #define TclVarHashCreateVar \ (tclIntStubsPtr->tclVarHashCreateVar) /* 234 */ #define TclInitVarHashTable \ (tclIntStubsPtr->tclInitVarHashTable) /* 235 */ #define TclBackgroundException \ (tclIntStubsPtr->tclBackgroundException) /* 236 */ #define TclResetCancellation \ (tclIntStubsPtr->tclResetCancellation) /* 237 */ #define TclNRInterpProc \ (tclIntStubsPtr->tclNRInterpProc) /* 238 */ #define TclNRInterpProcCore \ (tclIntStubsPtr->tclNRInterpProcCore) /* 239 */ #define TclNRRunCallbacks \ (tclIntStubsPtr->tclNRRunCallbacks) /* 240 */ #define TclNREvalObjEx \ (tclIntStubsPtr->tclNREvalObjEx) /* 241 */ #define TclNREvalObjv \ (tclIntStubsPtr->tclNREvalObjv) /* 242 */ #define TclDbDumpActiveObjects \ (tclIntStubsPtr->tclDbDumpActiveObjects) /* 243 */ #define TclGetNamespaceChildTable \ (tclIntStubsPtr->tclGetNamespaceChildTable) /* 244 */ #define TclGetNamespaceCommandTable \ (tclIntStubsPtr->tclGetNamespaceCommandTable) /* 245 */ #define TclInitRewriteEnsemble \ (tclIntStubsPtr->tclInitRewriteEnsemble) /* 246 */ #define TclResetRewriteEnsemble \ (tclIntStubsPtr->tclResetRewriteEnsemble) /* 247 */ #define TclCopyChannel \ (tclIntStubsPtr->tclCopyChannel) /* 248 */ #define TclDoubleDigits \ (tclIntStubsPtr->tclDoubleDigits) /* 249 */ #define TclSetSlaveCancelFlags \ (tclIntStubsPtr->tclSetSlaveCancelFlags) /* 250 */ #define TclRegisterLiteral \ (tclIntStubsPtr->tclRegisterLiteral) /* 251 */ #endif /* defined(USE_TCL_STUBS) */ /* !END!: Do not edit above this line. */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT #undef TclGetStartupScriptFileName #undef TclSetStartupScriptFileName #undef TclGetStartupScriptPath #undef TclSetStartupScriptPath #undef TclBackgroundException #if defined(USE_TCL_STUBS) && defined(TCL_NO_DEPRECATED) # undef Tcl_SetStartupScript # define Tcl_SetStartupScript \ (tclStubsPtr->tcl_SetStartupScript) /* 622 */ # undef Tcl_GetStartupScript # define Tcl_GetStartupScript \ (tclStubsPtr->tcl_GetStartupScript) /* 623 */ # undef Tcl_CreateNamespace # define Tcl_CreateNamespace \ (tclStubsPtr->tcl_CreateNamespace) /* 506 */ # undef Tcl_DeleteNamespace # define Tcl_DeleteNamespace \ (tclStubsPtr->tcl_DeleteNamespace) /* 507 */ # undef Tcl_AppendExportList # define Tcl_AppendExportList \ (tclStubsPtr->tcl_AppendExportList) /* 508 */ # undef Tcl_Export # define Tcl_Export \ (tclStubsPtr->tcl_Export) /* 509 */ # undef Tcl_Import # define Tcl_Import \ (tclStubsPtr->tcl_Import) /* 510 */ # undef Tcl_ForgetImport # define Tcl_ForgetImport \ (tclStubsPtr->tcl_ForgetImport) /* 511 */ # undef Tcl_GetCurrentNamespace # define Tcl_GetCurrentNamespace \ (tclStubsPtr->tcl_GetCurrentNamespace) /* 512 */ # undef Tcl_GetGlobalNamespace # define Tcl_GetGlobalNamespace \ (tclStubsPtr->tcl_GetGlobalNamespace) /* 513 */ # undef Tcl_FindNamespace # define Tcl_FindNamespace \ (tclStubsPtr->tcl_FindNamespace) /* 514 */ # undef Tcl_FindCommand # define Tcl_FindCommand \ (tclStubsPtr->tcl_FindCommand) /* 515 */ # undef Tcl_GetCommandFromObj # define Tcl_GetCommandFromObj \ (tclStubsPtr->tcl_GetCommandFromObj) /* 516 */ # undef Tcl_GetCommandFullName # define Tcl_GetCommandFullName \ (tclStubsPtr->tcl_GetCommandFullName) /* 517 */ #endif #undef TclCopyChannelOld #undef TclSockMinimumBuffersOld #endif /* _TCLINTDECLS */ tcl8.6.5/generic/tclCompExpr.c0000644000175000017500000024266212663660065015623 0ustar sergeisergei/* * tclCompExpr.c -- * * This file contains the code to parse and compile Tcl expressions and * implementations of the Tcl commands corresponding to expression * operators, such as the command ::tcl::mathop::+ . * * Contributions from Don Porter, NIST, 2006-2007. (not subject to US copyright) * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" /* CompileEnv */ /* * Expression parsing takes place in the routine ParseExpr(). It takes a * string as input, parses that string, and generates a representation of the * expression in the form of a tree of operators, a list of literals, a list * of function names, and an array of Tcl_Token's within a Tcl_Parse struct. * The tree is composed of OpNodes. */ typedef struct OpNode { int left; /* "Pointer" to the left operand. */ int right; /* "Pointer" to the right operand. */ union { int parent; /* "Pointer" to the parent operand. */ int prev; /* "Pointer" joining incomplete tree stack */ } p; unsigned char lexeme; /* Code that identifies the operator. */ unsigned char precedence; /* Precedence of the operator */ unsigned char mark; /* Mark used to control traversal. */ unsigned char constant; /* Flag marking constant subexpressions. */ } OpNode; /* * The storage for the tree is dynamically allocated array of OpNodes. The * array is grown as parsing needs dictate according to a scheme similar to * Tcl's string growth algorithm, so that the resizing costs are O(N) and so * that we use at least half the memory allocated as expressions get large. * * Each OpNode in the tree represents an operator in the expression, either * unary or binary. When parsing is completed successfully, a binary operator * OpNode will have its left and right fields filled with "pointers" to its * left and right operands. A unary operator OpNode will have its right field * filled with a pointer to its single operand. When an operand is a * subexpression the "pointer" takes the form of the index -- a non-negative * integer -- into the OpNode storage array where the root of that * subexpression parse tree is found. * * Non-operator elements of the expression do not get stored in the OpNode * tree. They are stored in the other structures according to their type. * Literal values get appended to the literal list. Elements that denote forms * of quoting or substitution known to the Tcl parser get stored as * Tcl_Tokens. These non-operator elements of the expression are the leaves of * the completed parse tree. When an operand of an OpNode is one of these leaf * elements, the following negative integer codes are used to indicate which * kind of elements it is. */ enum OperandTypes { OT_LITERAL = -3, /* Operand is a literal in the literal list */ OT_TOKENS = -2, /* Operand is sequence of Tcl_Tokens */ OT_EMPTY = -1 /* "Operand" is an empty string. This is a special * case used only to represent the EMPTY lexeme. See * below. */ }; /* * Readable macros to test whether a "pointer" value points to an operator. * They operate on the "non-negative integer -> operator; negative integer -> * a non-operator OperandType" distinction. */ #define IsOperator(l) ((l) >= 0) #define NotOperator(l) ((l) < 0) /* * Note that it is sufficient to store in the tree just the type of leaf * operand, without any explicit pointer to which leaf. This is true because * the traversals of the completed tree we perform are known to visit the * leaves in the same order as the original parse. * * In a completed parse tree, those OpNodes that are themselves (roots of * subexpression trees that are) operands of some operator store in their * p.parent field a "pointer" to the OpNode of that operator. The p.parent * field permits a traversal of the tree within a non-recursive routine * (ConvertTreeToTokens() and CompileExprTree()). This means that even * expression trees of great depth pose no risk of blowing the C stack. * * While the parse tree is being constructed, the same memory space is used to * hold the p.prev field which chains together a stack of incomplete trees * awaiting their right operands. * * The lexeme field is filled in with the lexeme of the operator that is * returned by the ParseLexeme() routine. Only lexemes for unary and binary * operators get stored in an OpNode. Other lexmes get different treatement. * * The precedence field provides a place to store the precedence of the * operator, so it need not be looked up again and again. * * The mark field is use to control the traversal of the tree, so that it can * be done non-recursively. The mark values are: */ enum Marks { MARK_LEFT, /* Next step of traversal is to visit left subtree */ MARK_RIGHT, /* Next step of traversal is to visit right subtree */ MARK_PARENT /* Next step of traversal is to return to parent */ }; /* * The constant field is a boolean flag marking which subexpressions are * completely known at compile time, and are eligible for computing then * rather than waiting until run time. */ /* * Each lexeme belongs to one of four categories, which determine its place in * the parse tree. We use the two high bits of the (unsigned char) value to * store a NODE_TYPE code. */ #define NODE_TYPE 0xC0 /* * The four category values are LEAF, UNARY, and BINARY, explained below, and * "uncategorized", which is used either temporarily, until context determines * which of the other three categories is correct, or for lexemes like * INVALID, which aren't really lexemes at all, but indicators of a parsing * error. Note that the codes must be distinct to distinguish categories, but * need not take the form of a bit array. */ #define BINARY 0x40 /* This lexeme is a binary operator. An OpNode * representing it should go into the parse * tree, and two operands should be parsed for * it in the expression. */ #define UNARY 0x80 /* This lexeme is a unary operator. An OpNode * representing it should go into the parse * tree, and one operand should be parsed for * it in the expression. */ #define LEAF 0xC0 /* This lexeme is a leaf operand in the parse * tree. No OpNode will be placed in the tree * for it. Either a literal value will be * appended to the list of literals in this * expression, or appropriate Tcl_Tokens will * be appended in a Tcl_Parse struct to * represent those leaves that require some * form of substitution. */ /* Uncategorized lexemes */ #define PLUS 1 /* Ambiguous. Resolves to UNARY_PLUS or * BINARY_PLUS according to context. */ #define MINUS 2 /* Ambiguous. Resolves to UNARY_MINUS or * BINARY_MINUS according to context. */ #define BAREWORD 3 /* Ambigous. Resolves to BOOLEAN or to * FUNCTION or a parse error according to * context and value. */ #define INCOMPLETE 4 /* A parse error. Used only when the single * "=" is encountered. */ #define INVALID 5 /* A parse error. Used when any punctuation * appears that's not a supported operator. */ /* Leaf lexemes */ #define NUMBER (LEAF | 1) /* For literal numbers */ #define SCRIPT (LEAF | 2) /* Script substitution; [foo] */ #define BOOLEAN (LEAF | BAREWORD) /* For literal booleans */ #define BRACED (LEAF | 4) /* Braced string; {foo bar} */ #define VARIABLE (LEAF | 5) /* Variable substitution; $x */ #define QUOTED (LEAF | 6) /* Quoted string; "foo $bar [soom]" */ #define EMPTY (LEAF | 7) /* Used only for an empty argument list to a * function. Represents the empty string * within parens in the expression: rand() */ /* Unary operator lexemes */ #define UNARY_PLUS (UNARY | PLUS) #define UNARY_MINUS (UNARY | MINUS) #define FUNCTION (UNARY | BAREWORD) /* This is a bit of "creative interpretation" * on the part of the parser. A function call * is parsed into the parse tree according to * the perspective that the function name is a * unary operator and its argument list, * enclosed in parens, is its operand. The * additional requirements not implied * generally by treatment as a unary operator * -- for example, the requirement that the * operand be enclosed in parens -- are hard * coded in the relevant portions of * ParseExpr(). We trade off the need to * include such exceptional handling in the * code against the need we would otherwise * have for more lexeme categories. */ #define START (UNARY | 4) /* This lexeme isn't parsed from the * expression text at all. It represents the * start of the expression and sits at the * root of the parse tree where it serves as * the start/end point of traversals. */ #define OPEN_PAREN (UNARY | 5) /* Another bit of creative interpretation, * where we treat "(" as a unary operator with * the sub-expression between it and its * matching ")" as its operand. See * CLOSE_PAREN below. */ #define NOT (UNARY | 6) #define BIT_NOT (UNARY | 7) /* Binary operator lexemes */ #define BINARY_PLUS (BINARY | PLUS) #define BINARY_MINUS (BINARY | MINUS) #define COMMA (BINARY | 3) /* The "," operator is a low precedence binary * operator that separates the arguments in a * function call. The additional constraint * that this operator can only legally appear * at the right places within a function call * argument list are hard coded within * ParseExpr(). */ #define MULT (BINARY | 4) #define DIVIDE (BINARY | 5) #define MOD (BINARY | 6) #define LESS (BINARY | 7) #define GREATER (BINARY | 8) #define BIT_AND (BINARY | 9) #define BIT_XOR (BINARY | 10) #define BIT_OR (BINARY | 11) #define QUESTION (BINARY | 12) /* These two lexemes make up the */ #define COLON (BINARY | 13) /* ternary conditional operator, $x ? $y : $z. * We treat them as two binary operators to * avoid another lexeme category, and code the * additional constraints directly in * ParseExpr(). For instance, the right * operand of a "?" operator must be a ":" * operator. */ #define LEFT_SHIFT (BINARY | 14) #define RIGHT_SHIFT (BINARY | 15) #define LEQ (BINARY | 16) #define GEQ (BINARY | 17) #define EQUAL (BINARY | 18) #define NEQ (BINARY | 19) #define AND (BINARY | 20) #define OR (BINARY | 21) #define STREQ (BINARY | 22) #define STRNEQ (BINARY | 23) #define EXPON (BINARY | 24) /* Unlike the other binary operators, EXPON is * right associative and this distinction is * coded directly in ParseExpr(). */ #define IN_LIST (BINARY | 25) #define NOT_IN_LIST (BINARY | 26) #define CLOSE_PAREN (BINARY | 27) /* By categorizing the CLOSE_PAREN lexeme as a * BINARY operator, the normal parsing rules * for binary operators assure that a close * paren will not directly follow another * operator, and the machinery already in * place to connect operands to operators * according to precedence performs most of * the work of matching open and close parens * for us. In the end though, a close paren is * not really a binary operator, and some * special coding in ParseExpr() make sure we * never put an actual CLOSE_PAREN node in the * parse tree. The sub-expression between * parens becomes the single argument of the * matching OPEN_PAREN unary operator. */ #define END (BINARY | 28) /* This lexeme represents the end of the * string being parsed. Treating it as a * binary operator follows the same logic as * the CLOSE_PAREN lexeme and END pairs with * START, in the same way that CLOSE_PAREN * pairs with OPEN_PAREN. */ /* * When ParseExpr() builds the parse tree it must choose which operands to * connect to which operators. This is done according to operator precedence. * The greater an operator's precedence the greater claim it has to link to an * available operand. The Precedence enumeration lists the precedence values * used by Tcl expression operators, from lowest to highest claim. Each * precedence level is commented with the operators that hold that precedence. */ enum Precedence { PREC_END = 1, /* END */ PREC_START, /* START */ PREC_CLOSE_PAREN, /* ")" */ PREC_OPEN_PAREN, /* "(" */ PREC_COMMA, /* "," */ PREC_CONDITIONAL, /* "?", ":" */ PREC_OR, /* "||" */ PREC_AND, /* "&&" */ PREC_BIT_OR, /* "|" */ PREC_BIT_XOR, /* "^" */ PREC_BIT_AND, /* "&" */ PREC_EQUAL, /* "==", "!=", "eq", "ne", "in", "ni" */ PREC_COMPARE, /* "<", ">", "<=", ">=" */ PREC_SHIFT, /* "<<", ">>" */ PREC_ADD, /* "+", "-" */ PREC_MULT, /* "*", "/", "%" */ PREC_EXPON, /* "**" */ PREC_UNARY /* "+", "-", FUNCTION, "!", "~" */ }; /* * Here the same information contained in the comments above is stored in * inverted form, so that given a lexeme, one can quickly look up its * precedence value. */ static const unsigned char prec[] = { /* Non-operator lexemes */ 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, 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, 0, 0, 0, 0, 0, 0, 0, /* Binary operator lexemes */ PREC_ADD, /* BINARY_PLUS */ PREC_ADD, /* BINARY_MINUS */ PREC_COMMA, /* COMMA */ PREC_MULT, /* MULT */ PREC_MULT, /* DIVIDE */ PREC_MULT, /* MOD */ PREC_COMPARE, /* LESS */ PREC_COMPARE, /* GREATER */ PREC_BIT_AND, /* BIT_AND */ PREC_BIT_XOR, /* BIT_XOR */ PREC_BIT_OR, /* BIT_OR */ PREC_CONDITIONAL, /* QUESTION */ PREC_CONDITIONAL, /* COLON */ PREC_SHIFT, /* LEFT_SHIFT */ PREC_SHIFT, /* RIGHT_SHIFT */ PREC_COMPARE, /* LEQ */ PREC_COMPARE, /* GEQ */ PREC_EQUAL, /* EQUAL */ PREC_EQUAL, /* NEQ */ PREC_AND, /* AND */ PREC_OR, /* OR */ PREC_EQUAL, /* STREQ */ PREC_EQUAL, /* STRNEQ */ PREC_EXPON, /* EXPON */ PREC_EQUAL, /* IN_LIST */ PREC_EQUAL, /* NOT_IN_LIST */ PREC_CLOSE_PAREN, /* CLOSE_PAREN */ PREC_END, /* END */ /* Expansion room for more binary operators */ 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, 0, 0, 0, 0, 0, 0, 0, /* Unary operator lexemes */ PREC_UNARY, /* UNARY_PLUS */ PREC_UNARY, /* UNARY_MINUS */ PREC_UNARY, /* FUNCTION */ PREC_START, /* START */ PREC_OPEN_PAREN, /* OPEN_PAREN */ PREC_UNARY, /* NOT*/ PREC_UNARY, /* BIT_NOT*/ }; /* * A table mapping lexemes to bytecode instructions, used by CompileExprTree(). */ static const unsigned char instruction[] = { /* Non-operator lexemes */ 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, 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, 0, 0, 0, 0, 0, 0, 0, /* Binary operator lexemes */ INST_ADD, /* BINARY_PLUS */ INST_SUB, /* BINARY_MINUS */ 0, /* COMMA */ INST_MULT, /* MULT */ INST_DIV, /* DIVIDE */ INST_MOD, /* MOD */ INST_LT, /* LESS */ INST_GT, /* GREATER */ INST_BITAND, /* BIT_AND */ INST_BITXOR, /* BIT_XOR */ INST_BITOR, /* BIT_OR */ 0, /* QUESTION */ 0, /* COLON */ INST_LSHIFT, /* LEFT_SHIFT */ INST_RSHIFT, /* RIGHT_SHIFT */ INST_LE, /* LEQ */ INST_GE, /* GEQ */ INST_EQ, /* EQUAL */ INST_NEQ, /* NEQ */ 0, /* AND */ 0, /* OR */ INST_STR_EQ, /* STREQ */ INST_STR_NEQ, /* STRNEQ */ INST_EXPON, /* EXPON */ INST_LIST_IN, /* IN_LIST */ INST_LIST_NOT_IN, /* NOT_IN_LIST */ 0, /* CLOSE_PAREN */ 0, /* END */ /* Expansion room for more binary operators */ 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, 0, 0, 0, 0, 0, 0, 0, /* Unary operator lexemes */ INST_UPLUS, /* UNARY_PLUS */ INST_UMINUS, /* UNARY_MINUS */ 0, /* FUNCTION */ 0, /* START */ 0, /* OPEN_PAREN */ INST_LNOT, /* NOT*/ INST_BITNOT, /* BIT_NOT*/ }; /* * A table mapping a byte value to the corresponding lexeme for use by * ParseLexeme(). */ static const unsigned char Lexeme[] = { INVALID /* NUL */, INVALID /* SOH */, INVALID /* STX */, INVALID /* ETX */, INVALID /* EOT */, INVALID /* ENQ */, INVALID /* ACK */, INVALID /* BEL */, INVALID /* BS */, INVALID /* HT */, INVALID /* LF */, INVALID /* VT */, INVALID /* FF */, INVALID /* CR */, INVALID /* SO */, INVALID /* SI */, INVALID /* DLE */, INVALID /* DC1 */, INVALID /* DC2 */, INVALID /* DC3 */, INVALID /* DC4 */, INVALID /* NAK */, INVALID /* SYN */, INVALID /* ETB */, INVALID /* CAN */, INVALID /* EM */, INVALID /* SUB */, INVALID /* ESC */, INVALID /* FS */, INVALID /* GS */, INVALID /* RS */, INVALID /* US */, INVALID /* SPACE */, 0 /* ! or != */, QUOTED /* " */, INVALID /* # */, VARIABLE /* $ */, MOD /* % */, 0 /* & or && */, INVALID /* ' */, OPEN_PAREN /* ( */, CLOSE_PAREN /* ) */, 0 /* * or ** */, PLUS /* + */, COMMA /* , */, MINUS /* - */, 0 /* . */, DIVIDE /* / */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-9 */ COLON /* : */, INVALID /* ; */, 0 /* < or << or <= */, 0 /* == or INVALID */, 0 /* > or >> or >= */, QUESTION /* ? */, INVALID /* @ */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A-M */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* N-Z */ SCRIPT /* [ */, INVALID /* \ */, INVALID /* ] */, BIT_XOR /* ^ */, INVALID /* _ */, INVALID /* ` */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a-m */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* n-z */ BRACED /* { */, 0 /* | or || */, INVALID /* } */, BIT_NOT /* ~ */, INVALID /* DEL */ }; /* * The JumpList struct is used to create a stack of data needed for the * TclEmitForwardJump() and TclFixupForwardJump() calls that are performed * when compiling the short-circuiting operators QUESTION/COLON, AND, and OR. * Keeping a stack permits the CompileExprTree() routine to be non-recursive. */ typedef struct JumpList { JumpFixup jump; /* Pass this argument to matching calls of * TclEmitForwardJump() and * TclFixupForwardJump(). */ struct JumpList *next; /* Point to next item on the stack */ } JumpList; /* * Declarations for local functions to this file: */ static void CompileExprTree(Tcl_Interp *interp, OpNode *nodes, int index, Tcl_Obj *const **litObjvPtr, Tcl_Obj *const *funcObjv, Tcl_Token *tokenPtr, CompileEnv *envPtr, int optimize); static void ConvertTreeToTokens(const char *start, int numBytes, OpNode *nodes, Tcl_Token *tokenPtr, Tcl_Parse *parsePtr); static int ExecConstantExprTree(Tcl_Interp *interp, OpNode *nodes, int index, Tcl_Obj * const **litObjvPtr); static int ParseExpr(Tcl_Interp *interp, const char *start, int numBytes, OpNode **opTreePtr, Tcl_Obj *litList, Tcl_Obj *funcList, Tcl_Parse *parsePtr, int parseOnly); static int ParseLexeme(const char *start, int numBytes, unsigned char *lexemePtr, Tcl_Obj **literalPtr); /* *---------------------------------------------------------------------- * * ParseExpr -- * * Given a string, the numBytes bytes starting at start, this function * parses it as a Tcl expression and constructs a tree representing the * structure of the expression. The caller must pass in empty lists as * the funcList and litList arguments. The elements of the parsed * expression are returned to the caller as that tree, a list of literal * values, a list of function names, and in Tcl_Tokens added to a * Tcl_Parse struct passed in by the caller. * * Results: * If the string is successfully parsed as a valid Tcl expression, TCL_OK * is returned, and data about the expression structure is written to the * last four arguments. If the string cannot be parsed as a valid Tcl * expression, TCL_ERROR is returned, and if interp is non-NULL, an error * message is written to interp. * * Side effects: * Memory will be allocated. If TCL_OK is returned, the caller must clean * up the returned data structures. The (OpNode *) value written to * opTreePtr should be passed to ckfree() and the parsePtr argument * should be passed to Tcl_FreeParse(). The elements appended to the * litList and funcList will automatically be freed whenever the refcount * on those lists indicates they can be freed. * *---------------------------------------------------------------------- */ static int ParseExpr( Tcl_Interp *interp, /* Used for error reporting. */ const char *start, /* Start of source string to parse. */ int numBytes, /* Number of bytes in string. */ OpNode **opTreePtr, /* Points to space where a pointer to the * allocated OpNode tree should go. */ Tcl_Obj *litList, /* List to append literals to. */ Tcl_Obj *funcList, /* List to append function names to. */ Tcl_Parse *parsePtr, /* Structure to fill with tokens representing * those operands that require run time * substitutions. */ int parseOnly) /* A boolean indicating whether the caller's * aim is just a parse, or whether it will go * on to compile the expression. Different * optimizations are appropriate for the two * scenarios. */ { OpNode *nodes = NULL; /* Pointer to the OpNode storage array where * we build the parse tree. */ int nodesAvailable = 64; /* Initial size of the storage array. This * value establishes a minimum tree memory * cost of only about 1 kibyte, and is large * enough for most expressions to parse with * no need for array growth and * reallocation. */ int nodesUsed = 0; /* Number of OpNodes filled. */ int scanned = 0; /* Capture number of byte scanned by parsing * routines. */ int lastParsed; /* Stores info about what the lexeme parsed * the previous pass through the parsing loop * was. If it was an operator, lastParsed is * the index of the OpNode for that operator. * If it was not an operator, lastParsed holds * an OperandTypes value encoding what we need * to know about it. */ int incomplete; /* Index of the most recent incomplete tree in * the OpNode array. Heads a stack of * incomplete trees linked by p.prev. */ int complete = OT_EMPTY; /* "Index" of the complete tree (that is, a * complete subexpression) determined at the * moment. OT_EMPTY is a nonsense value used * only to silence compiler warnings. During a * parse, complete will always hold an index * or an OperandTypes value pointing to an * actual leaf at the time the complete tree * is needed. */ /* * These variables control generation of the error message. */ Tcl_Obj *msg = NULL; /* The error message. */ Tcl_Obj *post = NULL; /* In a few cases, an additional postscript * for the error message, supplying more * information after the error msg and * location have been reported. */ const char *errCode = NULL; /* The detail word of the errorCode list, or * NULL to indicate that no changes to the * errorCode are to be done. */ const char *subErrCode = NULL; /* Extra information for use in generating the * errorCode. */ const char *mark = "_@_"; /* In the portion of the complete error * message where the error location is * reported, this "mark" substring is inserted * into the string being parsed to aid in * pinpointing the location of the syntax * error in the expression. */ int insertMark = 0; /* A boolean controlling whether the "mark" * should be inserted. */ const int limit = 25; /* Portions of the error message are * constructed out of substrings of the * original expression. In order to keep the * error message readable, we impose this * limit on the substring size we extract. */ TclParseInit(interp, start, numBytes, parsePtr); nodes = attemptckalloc(nodesAvailable * sizeof(OpNode)); if (nodes == NULL) { TclNewLiteralStringObj(msg, "not enough memory to parse expression"); errCode = "NOMEM"; goto error; } /* * Initialize the parse tree with the special "START" node. */ nodes->lexeme = START; nodes->precedence = prec[START]; nodes->mark = MARK_RIGHT; nodes->constant = 1; incomplete = lastParsed = nodesUsed; nodesUsed++; /* * Main parsing loop parses one lexeme per iteration. We exit the loop * only when there's a syntax error with a "goto error" which takes us to * the error handling code following the loop, or when we've successfully * completed the parse and we return to the caller. */ while (1) { OpNode *nodePtr; /* Points to the OpNode we may fill this pass * through the loop. */ unsigned char lexeme; /* The lexeme we parse this iteration. */ Tcl_Obj *literal; /* Filled by the ParseLexeme() call when a * literal is parsed that has a Tcl_Obj rep * worth preserving. */ /* * Each pass through this loop adds up to one more OpNode. Allocate * space for one if required. */ if (nodesUsed >= nodesAvailable) { int size = nodesUsed * 2; OpNode *newPtr = NULL; do { if (size <= UINT_MAX/sizeof(OpNode)) { newPtr = attemptckrealloc(nodes, size * sizeof(OpNode)); } } while ((newPtr == NULL) && ((size -= (size - nodesUsed) / 2) > nodesUsed)); if (newPtr == NULL) { TclNewLiteralStringObj(msg, "not enough memory to parse expression"); errCode = "NOMEM"; goto error; } nodesAvailable = size; nodes = newPtr; } nodePtr = nodes + nodesUsed; /* * Skip white space between lexemes. */ scanned = TclParseAllWhiteSpace(start, numBytes); start += scanned; numBytes -= scanned; scanned = ParseLexeme(start, numBytes, &lexeme, &literal); /* * Use context to categorize the lexemes that are ambiguous. */ if ((NODE_TYPE & lexeme) == 0) { int b; switch (lexeme) { case INVALID: msg = Tcl_ObjPrintf("invalid character \"%.*s\"", scanned, start); errCode = "BADCHAR"; goto error; case INCOMPLETE: msg = Tcl_ObjPrintf("incomplete operator \"%.*s\"", scanned, start); errCode = "PARTOP"; goto error; case BAREWORD: /* * Most barewords in an expression are a syntax error. The * exceptions are that when a bareword is followed by an open * paren, it might be a function call, and when the bareword * is a legal literal boolean value, we accept that as well. */ if (start[scanned+TclParseAllWhiteSpace( start+scanned, numBytes-scanned)] == '(') { lexeme = FUNCTION; /* * When we compile the expression we'll need the function * name, and there's no place in the parse tree to store * it, so we keep a separate list of all the function * names we've parsed in the order we found them. */ Tcl_ListObjAppendElement(NULL, funcList, literal); } else if (Tcl_GetBooleanFromObj(NULL,literal,&b) == TCL_OK) { lexeme = BOOLEAN; } else { Tcl_DecrRefCount(literal); msg = Tcl_ObjPrintf("invalid bareword \"%.*s%s\"", (scanned < limit) ? scanned : limit - 3, start, (scanned < limit) ? "" : "..."); post = Tcl_ObjPrintf( "should be \"$%.*s%s\" or \"{%.*s%s}\"", (scanned < limit) ? scanned : limit - 3, start, (scanned < limit) ? "" : "...", (scanned < limit) ? scanned : limit - 3, start, (scanned < limit) ? "" : "..."); Tcl_AppendPrintfToObj(post, " or \"%.*s%s(...)\" or ...", (scanned < limit) ? scanned : limit - 3, start, (scanned < limit) ? "" : "..."); errCode = "BAREWORD"; if (start[0] == '0') { const char *stop; TclParseNumber(NULL, NULL, NULL, start, scanned, &stop, TCL_PARSE_NO_WHITESPACE); if (isdigit(UCHAR(*stop)) || (stop == start + 1)) { switch (start[1]) { case 'b': Tcl_AppendToObj(post, " (invalid binary number?)", -1); parsePtr->errorType = TCL_PARSE_BAD_NUMBER; errCode = "BADNUMBER"; subErrCode = "BINARY"; break; case 'o': Tcl_AppendToObj(post, " (invalid octal number?)", -1); parsePtr->errorType = TCL_PARSE_BAD_NUMBER; errCode = "BADNUMBER"; subErrCode = "OCTAL"; break; default: if (isdigit(UCHAR(start[1]))) { Tcl_AppendToObj(post, " (invalid octal number?)", -1); parsePtr->errorType = TCL_PARSE_BAD_NUMBER; errCode = "BADNUMBER"; subErrCode = "OCTAL"; } break; } } } goto error; } break; case PLUS: case MINUS: if (IsOperator(lastParsed)) { /* * A "+" or "-" coming just after another operator must be * interpreted as a unary operator. */ lexeme |= UNARY; } else { lexeme |= BINARY; } } } /* Uncategorized lexemes */ /* * Handle lexeme based on its category. */ switch (NODE_TYPE & lexeme) { case LEAF: { /* * Each LEAF results in either a literal getting appended to the * litList, or a sequence of Tcl_Tokens representing a Tcl word * getting appended to the parsePtr->tokens. No OpNode is filled * for this lexeme. */ Tcl_Token *tokenPtr; const char *end = start; int wordIndex; int code = TCL_OK; /* * A leaf operand appearing just after something that's not an * operator is a syntax error. */ if (NotOperator(lastParsed)) { msg = Tcl_ObjPrintf("missing operator at %s", mark); errCode = "MISSING"; scanned = 0; insertMark = 1; /* * Free any literal to avoid a memleak. */ if ((lexeme == NUMBER) || (lexeme == BOOLEAN)) { Tcl_DecrRefCount(literal); } goto error; } switch (lexeme) { case NUMBER: case BOOLEAN: /* * TODO: Consider using a dict or hash to collapse all * duplicate literals into a single representative value. * (Like what is done with [split $s {}]). * Pro: ~75% memory saving on expressions like * {1+1+1+1+1+.....+1} (Convert "pointer + Tcl_Obj" cost * to "pointer" cost only) * Con: Cost of the dict store/retrieve on every literal in * every expression when expressions like the above tend * to be uncommon. * The memory savings is temporary; Compiling to bytecode * will collapse things as literals are registered * anyway, so the savings applies only to the time * between parsing and compiling. Possibly important due * to high-water mark nature of memory allocation. */ Tcl_ListObjAppendElement(NULL, litList, literal); complete = lastParsed = OT_LITERAL; start += scanned; numBytes -= scanned; continue; default: break; } /* * Remaining LEAF cases may involve filling Tcl_Tokens, so make * room for at least 2 more tokens. */ TclGrowParseTokenArray(parsePtr, 2); wordIndex = parsePtr->numTokens; tokenPtr = parsePtr->tokenPtr + wordIndex; tokenPtr->type = TCL_TOKEN_WORD; tokenPtr->start = start; parsePtr->numTokens++; switch (lexeme) { case QUOTED: code = Tcl_ParseQuotedString(NULL, start, numBytes, parsePtr, 1, &end); scanned = end - start; break; case BRACED: code = Tcl_ParseBraces(NULL, start, numBytes, parsePtr, 1, &end); scanned = end - start; break; case VARIABLE: code = Tcl_ParseVarName(NULL, start, numBytes, parsePtr, 1); /* * Handle the quirk that Tcl_ParseVarName reports a successful * parse even when it gets only a "$" with no variable name. */ tokenPtr = parsePtr->tokenPtr + wordIndex + 1; if (code == TCL_OK && tokenPtr->type != TCL_TOKEN_VARIABLE) { TclNewLiteralStringObj(msg, "invalid character \"$\""); errCode = "BADCHAR"; goto error; } scanned = tokenPtr->size; break; case SCRIPT: { Tcl_Parse *nestedPtr = TclStackAlloc(interp, sizeof(Tcl_Parse)); tokenPtr = parsePtr->tokenPtr + parsePtr->numTokens; tokenPtr->type = TCL_TOKEN_COMMAND; tokenPtr->start = start; tokenPtr->numComponents = 0; end = start + numBytes; start++; while (1) { code = Tcl_ParseCommand(interp, start, end - start, 1, nestedPtr); if (code != TCL_OK) { parsePtr->term = nestedPtr->term; parsePtr->errorType = nestedPtr->errorType; parsePtr->incomplete = nestedPtr->incomplete; break; } start = nestedPtr->commandStart + nestedPtr->commandSize; Tcl_FreeParse(nestedPtr); if ((nestedPtr->term < end) && (nestedPtr->term[0] == ']') && !nestedPtr->incomplete) { break; } if (start == end) { TclNewLiteralStringObj(msg, "missing close-bracket"); parsePtr->term = tokenPtr->start; parsePtr->errorType = TCL_PARSE_MISSING_BRACKET; parsePtr->incomplete = 1; code = TCL_ERROR; errCode = "UNBALANCED"; break; } } TclStackFree(interp, nestedPtr); end = start; start = tokenPtr->start; scanned = end - start; tokenPtr->size = scanned; parsePtr->numTokens++; break; } /* SCRIPT case */ } if (code != TCL_OK) { /* * Here we handle all the syntax errors generated by the * Tcl_Token generating parsing routines called in the switch * just above. If the value of parsePtr->incomplete is 1, then * the error was an unbalanced '[', '(', '{', or '"' and * parsePtr->term is pointing to that unbalanced character. If * the value of parsePtr->incomplete is 0, then the error is * one of lacking whitespace following a quoted word, for * example: expr {[an error {foo}bar]}, and parsePtr->term * points to where the whitespace is missing. We reset our * values of start and scanned so that when our error message * is constructed, the location of the syntax error is sure to * appear in it, even if the quoted expression is truncated. */ start = parsePtr->term; scanned = parsePtr->incomplete; if (parsePtr->incomplete) { errCode = "UNBALANCED"; } goto error; } tokenPtr = parsePtr->tokenPtr + wordIndex; tokenPtr->size = scanned; tokenPtr->numComponents = parsePtr->numTokens - wordIndex - 1; if (!parseOnly && ((lexeme == QUOTED) || (lexeme == BRACED))) { /* * When this expression is destined to be compiled, and a * braced or quoted word within an expression is known at * compile time (no runtime substitutions in it), we can store * it as a literal rather than in its tokenized form. This is * an advantage since the compiled bytecode is going to need * the argument in Tcl_Obj form eventually, so it's just as * well to get there now. Another advantage is that with this * conversion, larger constant expressions might be grown and * optimized. * * On the contrary, if the end goal of this parse is to fill a * Tcl_Parse for a caller of Tcl_ParseExpr(), then it's * wasteful to convert to a literal only to convert back again * later. */ literal = Tcl_NewObj(); if (TclWordKnownAtCompileTime(tokenPtr, literal)) { Tcl_ListObjAppendElement(NULL, litList, literal); complete = lastParsed = OT_LITERAL; parsePtr->numTokens = wordIndex; break; } Tcl_DecrRefCount(literal); } complete = lastParsed = OT_TOKENS; break; } /* case LEAF */ case UNARY: /* * A unary operator appearing just after something that's not an * operator is a syntax error -- something trying to be the left * operand of an operator that doesn't take one. */ if (NotOperator(lastParsed)) { msg = Tcl_ObjPrintf("missing operator at %s", mark); scanned = 0; insertMark = 1; errCode = "MISSING"; goto error; } /* * Create an OpNode for the unary operator. */ nodePtr->lexeme = lexeme; nodePtr->precedence = prec[lexeme]; nodePtr->mark = MARK_RIGHT; /* * A FUNCTION cannot be a constant expression, because Tcl allows * functions to return variable results with the same arguments; * for example, rand(). Other unary operators can root a constant * expression, so long as the argument is a constant expression. */ nodePtr->constant = (lexeme != FUNCTION); /* * This unary operator is a new incomplete tree, so push it onto * our stack of incomplete trees. Also remember it as the last * lexeme we parsed. */ nodePtr->p.prev = incomplete; incomplete = lastParsed = nodesUsed; nodesUsed++; break; case BINARY: { OpNode *incompletePtr; unsigned char precedence = prec[lexeme]; /* * A binary operator appearing just after another operator is a * syntax error -- one of the two operators is missing an operand. */ if (IsOperator(lastParsed)) { if ((lexeme == CLOSE_PAREN) && (nodePtr[-1].lexeme == OPEN_PAREN)) { if (nodePtr[-2].lexeme == FUNCTION) { /* * Normally, "()" is a syntax error, but as a special * case accept it as an argument list for a function. * Treat this as a special LEAF lexeme, and restart * the parsing loop with zero characters scanned. We * will parse the ")" again the next time through, but * with the OT_EMPTY leaf as the subexpression between * the parens. */ scanned = 0; complete = lastParsed = OT_EMPTY; break; } msg = Tcl_ObjPrintf("empty subexpression at %s", mark); scanned = 0; insertMark = 1; errCode = "EMPTY"; goto error; } if (nodePtr[-1].precedence > precedence) { if (nodePtr[-1].lexeme == OPEN_PAREN) { TclNewLiteralStringObj(msg, "unbalanced open paren"); parsePtr->errorType = TCL_PARSE_MISSING_PAREN; errCode = "UNBALANCED"; } else if (nodePtr[-1].lexeme == COMMA) { msg = Tcl_ObjPrintf( "missing function argument at %s", mark); scanned = 0; insertMark = 1; errCode = "MISSING"; } else if (nodePtr[-1].lexeme == START) { TclNewLiteralStringObj(msg, "empty expression"); errCode = "EMPTY"; } } else if (lexeme == CLOSE_PAREN) { TclNewLiteralStringObj(msg, "unbalanced close paren"); errCode = "UNBALANCED"; } else if ((lexeme == COMMA) && (nodePtr[-1].lexeme == OPEN_PAREN) && (nodePtr[-2].lexeme == FUNCTION)) { msg = Tcl_ObjPrintf("missing function argument at %s", mark); scanned = 0; insertMark = 1; errCode = "UNBALANCED"; } if (msg == NULL) { msg = Tcl_ObjPrintf("missing operand at %s", mark); scanned = 0; insertMark = 1; errCode = "MISSING"; } goto error; } /* * Here is where the tree comes together. At this point, we have a * stack of incomplete trees corresponding to substrings that are * incomplete expressions, followed by a complete tree * corresponding to a substring that is itself a complete * expression, followed by the binary operator we have just * parsed. The incomplete trees can each be completed by adding a * right operand. * * To illustrate with an example, when we parse the expression * "1+2*3-4" and we reach this point having just parsed the "-" * operator, we have these incomplete trees: START, "1+", and * "2*". Next we have the complete subexpression "3". Last is the * "-" we've just parsed. * * The next step is to join our complete tree to an operator. The * choice is governed by the precedence and associativity of the * competing operators. If we connect it as the right operand of * our most recent incomplete tree, we get a new complete tree, * and we can repeat the process. The while loop following repeats * this until precedence indicates it is time to join the complete * tree as the left operand of the just parsed binary operator. * * Continuing the example, the first pass through the loop will * join "3" to "2*"; the next pass will join "2*3" to "1+". Then * we'll exit the loop and join "1+2*3" to "-". When we return to * parse another lexeme, our stack of incomplete trees is START * and "1+2*3-". */ while (1) { incompletePtr = nodes + incomplete; if (incompletePtr->precedence < precedence) { break; } if (incompletePtr->precedence == precedence) { /* * Right association rules for exponentiation. */ if (lexeme == EXPON) { break; } /* * Special association rules for the conditional * operators. The "?" and ":" operators have equal * precedence, but must be linked up in sensible pairs. */ if ((incompletePtr->lexeme == QUESTION) && (NotOperator(complete) || (nodes[complete].lexeme != COLON))) { break; } if ((incompletePtr->lexeme == COLON) && (lexeme == QUESTION)) { break; } } /* * Some special syntax checks... */ /* Parens must balance */ if ((incompletePtr->lexeme == OPEN_PAREN) && (lexeme != CLOSE_PAREN)) { TclNewLiteralStringObj(msg, "unbalanced open paren"); parsePtr->errorType = TCL_PARSE_MISSING_PAREN; errCode = "UNBALANCED"; goto error; } /* Right operand of "?" must be ":" */ if ((incompletePtr->lexeme == QUESTION) && (NotOperator(complete) || (nodes[complete].lexeme != COLON))) { msg = Tcl_ObjPrintf("missing operator \":\" at %s", mark); scanned = 0; insertMark = 1; errCode = "MISSING"; goto error; } /* Operator ":" may only be right operand of "?" */ if (IsOperator(complete) && (nodes[complete].lexeme == COLON) && (incompletePtr->lexeme != QUESTION)) { TclNewLiteralStringObj(msg, "unexpected operator \":\" " "without preceding \"?\""); errCode = "SURPRISE"; goto error; } /* * Attach complete tree as right operand of most recent * incomplete tree. */ incompletePtr->right = complete; if (IsOperator(complete)) { nodes[complete].p.parent = incomplete; incompletePtr->constant = incompletePtr->constant && nodes[complete].constant; } else { incompletePtr->constant = incompletePtr->constant && (complete == OT_LITERAL); } /* * The QUESTION/COLON and FUNCTION/OPEN_PAREN combinations * each make up a single operator. Force them to agree whether * they have a constant expression. */ if ((incompletePtr->lexeme == QUESTION) || (incompletePtr->lexeme == FUNCTION)) { nodes[complete].constant = incompletePtr->constant; } if (incompletePtr->lexeme == START) { /* * Completing the START tree indicates we're done. * Transfer the parse tree to the caller and return. */ *opTreePtr = nodes; return TCL_OK; } /* * With a right operand attached, last incomplete tree has * become the complete tree. Pop it from the incomplete tree * stack. */ complete = incomplete; incomplete = incompletePtr->p.prev; /* CLOSE_PAREN can only close one OPEN_PAREN. */ if (incompletePtr->lexeme == OPEN_PAREN) { break; } } /* * More syntax checks... */ /* Parens must balance. */ if (lexeme == CLOSE_PAREN) { if (incompletePtr->lexeme != OPEN_PAREN) { TclNewLiteralStringObj(msg, "unbalanced close paren"); errCode = "UNBALANCED"; goto error; } } /* Commas must appear only in function argument lists. */ if (lexeme == COMMA) { if ((incompletePtr->lexeme != OPEN_PAREN) || (incompletePtr[-1].lexeme != FUNCTION)) { TclNewLiteralStringObj(msg, "unexpected \",\" outside function argument list"); errCode = "SURPRISE"; goto error; } } /* Operator ":" may only be right operand of "?" */ if (IsOperator(complete) && (nodes[complete].lexeme == COLON)) { TclNewLiteralStringObj(msg, "unexpected operator \":\" without preceding \"?\""); errCode = "SURPRISE"; goto error; } /* * Create no node for a CLOSE_PAREN lexeme. */ if (lexeme == CLOSE_PAREN) { break; } /* * Link complete tree as left operand of new node. */ nodePtr->lexeme = lexeme; nodePtr->precedence = precedence; nodePtr->mark = MARK_LEFT; nodePtr->left = complete; /* * The COMMA operator cannot be optimized, since the function * needs all of its arguments, and optimization would reduce the * number. Other binary operators root constant expressions when * both arguments are constant expressions. */ nodePtr->constant = (lexeme != COMMA); if (IsOperator(complete)) { nodes[complete].p.parent = nodesUsed; nodePtr->constant = nodePtr->constant && nodes[complete].constant; } else { nodePtr->constant = nodePtr->constant && (complete == OT_LITERAL); } /* * With a left operand attached and a right operand missing, the * just-parsed binary operator is root of a new incomplete tree. * Push it onto the stack of incomplete trees. */ nodePtr->p.prev = incomplete; incomplete = lastParsed = nodesUsed; nodesUsed++; break; } /* case BINARY */ } /* lexeme handler */ /* Advance past the just-parsed lexeme */ start += scanned; numBytes -= scanned; } /* main parsing loop */ /* * We only get here if there's been an error. Any errors that didn't get a * suitable parsePtr->errorType, get recorded as syntax errors. */ error: if (parsePtr->errorType == TCL_PARSE_SUCCESS) { parsePtr->errorType = TCL_PARSE_SYNTAX; } /* * Free any partial parse tree we've built. */ if (nodes != NULL) { ckfree(nodes); } if (interp == NULL) { /* * Nowhere to report an error message, so just free it. */ if (msg) { Tcl_DecrRefCount(msg); } } else { /* * Construct the complete error message. Start with the simple error * message, pulled from the interp result if necessary... */ if (msg == NULL) { msg = Tcl_GetObjResult(interp); } /* * Add a detailed quote from the bad expression, displaying and * sometimes marking the precise location of the syntax error. */ Tcl_AppendPrintfToObj(msg, "\nin expression \"%s%.*s%.*s%s%s%.*s%s\"", ((start - limit) < parsePtr->string) ? "" : "...", ((start - limit) < parsePtr->string) ? (int) (start - parsePtr->string) : limit - 3, ((start - limit) < parsePtr->string) ? parsePtr->string : start - limit + 3, (scanned < limit) ? scanned : limit - 3, start, (scanned < limit) ? "" : "...", insertMark ? mark : "", (start + scanned + limit > parsePtr->end) ? (int) (parsePtr->end - start) - scanned : limit-3, start + scanned, (start + scanned + limit > parsePtr->end) ? "" : "..."); /* * Next, append any postscript message. */ if (post != NULL) { Tcl_AppendToObj(msg, ";\n", -1); Tcl_AppendObjToObj(msg, post); Tcl_DecrRefCount(post); } Tcl_SetObjResult(interp, msg); /* * Finally, place context information in the errorInfo. */ numBytes = parsePtr->end - parsePtr->string; Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (parsing expression \"%.*s%s\")", (numBytes < limit) ? numBytes : limit - 3, parsePtr->string, (numBytes < limit) ? "" : "...")); if (errCode) { Tcl_SetErrorCode(interp, "TCL", "PARSE", "EXPR", errCode, subErrCode, NULL); } } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * ConvertTreeToTokens -- * * Given a string, the numBytes bytes starting at start, and an OpNode * tree and Tcl_Token array created by passing that same string to * ParseExpr(), this function writes into *parsePtr the sequence of * Tcl_Tokens needed so to satisfy the historical interface provided by * Tcl_ParseExpr(). Note that this routine exists only for the sake of * the public Tcl_ParseExpr() routine. It is not used by Tcl itself at * all. * * Results: * None. * * Side effects: * The Tcl_Parse *parsePtr is filled with Tcl_Tokens representing the * parsed expression. * *---------------------------------------------------------------------- */ static void ConvertTreeToTokens( const char *start, int numBytes, OpNode *nodes, Tcl_Token *tokenPtr, Tcl_Parse *parsePtr) { int subExprTokenIdx = 0; OpNode *nodePtr = nodes; int next = nodePtr->right; while (1) { Tcl_Token *subExprTokenPtr; int scanned, parentIdx; unsigned char lexeme; /* * Advance the mark so the next exit from this node won't retrace * steps over ground already covered. */ nodePtr->mark++; /* * Handle next child node or leaf. */ switch (next) { case OT_EMPTY: /* No tokens and no characters for the OT_EMPTY leaf. */ break; case OT_LITERAL: /* * Skip any white space that comes before the literal. */ scanned = TclParseAllWhiteSpace(start, numBytes); start += scanned; numBytes -= scanned; /* * Reparse the literal to get pointers into source string. */ scanned = ParseLexeme(start, numBytes, &lexeme, NULL); TclGrowParseTokenArray(parsePtr, 2); subExprTokenPtr = parsePtr->tokenPtr + parsePtr->numTokens; subExprTokenPtr->type = TCL_TOKEN_SUB_EXPR; subExprTokenPtr->start = start; subExprTokenPtr->size = scanned; subExprTokenPtr->numComponents = 1; subExprTokenPtr[1].type = TCL_TOKEN_TEXT; subExprTokenPtr[1].start = start; subExprTokenPtr[1].size = scanned; subExprTokenPtr[1].numComponents = 0; parsePtr->numTokens += 2; start += scanned; numBytes -= scanned; break; case OT_TOKENS: { /* * tokenPtr points to a token sequence that came from parsing a * Tcl word. A Tcl word is made up of a sequence of one or more * elements. When the word is only a single element, it's been the * historical practice to replace the TCL_TOKEN_WORD token * directly with a TCL_TOKEN_SUB_EXPR token. However, when the * word has multiple elements, a TCL_TOKEN_WORD token is kept as a * grouping device so that TCL_TOKEN_SUB_EXPR always has only one * element. Wise or not, these are the rules the Tcl expr parser * has followed, and for the sake of those few callers of * Tcl_ParseExpr() we do not change them now. Internally, we can * do better. */ int toCopy = tokenPtr->numComponents + 1; if (tokenPtr->numComponents == tokenPtr[1].numComponents + 1) { /* * Single element word. Copy tokens and convert the leading * token to TCL_TOKEN_SUB_EXPR. */ TclGrowParseTokenArray(parsePtr, toCopy); subExprTokenPtr = parsePtr->tokenPtr + parsePtr->numTokens; memcpy(subExprTokenPtr, tokenPtr, (size_t) toCopy * sizeof(Tcl_Token)); subExprTokenPtr->type = TCL_TOKEN_SUB_EXPR; parsePtr->numTokens += toCopy; } else { /* * Multiple element word. Create a TCL_TOKEN_SUB_EXPR token to * lead, with fields initialized from the leading token, then * copy entire set of word tokens. */ TclGrowParseTokenArray(parsePtr, toCopy+1); subExprTokenPtr = parsePtr->tokenPtr + parsePtr->numTokens; *subExprTokenPtr = *tokenPtr; subExprTokenPtr->type = TCL_TOKEN_SUB_EXPR; subExprTokenPtr->numComponents++; subExprTokenPtr++; memcpy(subExprTokenPtr, tokenPtr, (size_t) toCopy * sizeof(Tcl_Token)); parsePtr->numTokens += toCopy + 1; } scanned = tokenPtr->start + tokenPtr->size - start; start += scanned; numBytes -= scanned; tokenPtr += toCopy; break; } default: /* * Advance to the child node, which is an operator. */ nodePtr = nodes + next; /* * Skip any white space that comes before the subexpression. */ scanned = TclParseAllWhiteSpace(start, numBytes); start += scanned; numBytes -= scanned; /* * Generate tokens for the operator / subexpression... */ switch (nodePtr->lexeme) { case OPEN_PAREN: case COMMA: case COLON: /* * Historical practice has been to have no Tcl_Tokens for * these operators. */ break; default: { /* * Remember the index of the last subexpression we were * working on -- that of our parent. We'll stack it later. */ parentIdx = subExprTokenIdx; /* * Verify space for the two leading Tcl_Tokens representing * the subexpression rooted by this operator. The first * Tcl_Token will be of type TCL_TOKEN_SUB_EXPR; the second of * type TCL_TOKEN_OPERATOR. */ TclGrowParseTokenArray(parsePtr, 2); subExprTokenIdx = parsePtr->numTokens; subExprTokenPtr = parsePtr->tokenPtr + subExprTokenIdx; parsePtr->numTokens += 2; subExprTokenPtr->type = TCL_TOKEN_SUB_EXPR; subExprTokenPtr[1].type = TCL_TOKEN_OPERATOR; /* * Our current position scanning the string is the starting * point for this subexpression. */ subExprTokenPtr->start = start; /* * Eventually, we know that the numComponents field of the * Tcl_Token of type TCL_TOKEN_OPERATOR will be 0. This means * we can make other use of this field for now to track the * stack of subexpressions we have pending. */ subExprTokenPtr[1].numComponents = parentIdx; break; } } break; } /* Determine which way to exit the node on this pass. */ router: switch (nodePtr->mark) { case MARK_LEFT: next = nodePtr->left; break; case MARK_RIGHT: next = nodePtr->right; /* * Skip any white space that comes before the operator. */ scanned = TclParseAllWhiteSpace(start, numBytes); start += scanned; numBytes -= scanned; /* * Here we scan from the string the operator corresponding to * nodePtr->lexeme. */ scanned = ParseLexeme(start, numBytes, &lexeme, NULL); switch(nodePtr->lexeme) { case OPEN_PAREN: case COMMA: case COLON: /* * No tokens for these lexemes -> nothing to do. */ break; default: /* * Record in the TCL_TOKEN_OPERATOR token the pointers into * the string marking where the operator is. */ subExprTokenPtr = parsePtr->tokenPtr + subExprTokenIdx; subExprTokenPtr[1].start = start; subExprTokenPtr[1].size = scanned; break; } start += scanned; numBytes -= scanned; break; case MARK_PARENT: switch (nodePtr->lexeme) { case START: /* When we get back to the START node, we're done. */ return; case COMMA: case COLON: /* No tokens for these lexemes -> nothing to do. */ break; case OPEN_PAREN: /* * Skip past matching close paren. */ scanned = TclParseAllWhiteSpace(start, numBytes); start += scanned; numBytes -= scanned; scanned = ParseLexeme(start, numBytes, &lexeme, NULL); start += scanned; numBytes -= scanned; break; default: /* * Before we leave this node/operator/subexpression for the * last time, finish up its tokens.... * * Our current position scanning the string is where the * substring for the subexpression ends. */ subExprTokenPtr = parsePtr->tokenPtr + subExprTokenIdx; subExprTokenPtr->size = start - subExprTokenPtr->start; /* * All the Tcl_Tokens allocated and filled belong to * this subexpresion. The first token is the leading * TCL_TOKEN_SUB_EXPR token, and all the rest (one fewer) * are its components. */ subExprTokenPtr->numComponents = (parsePtr->numTokens - subExprTokenIdx) - 1; /* * Finally, as we return up the tree to our parent, pop the * parent subexpression off our subexpression stack, and * fill in the zero numComponents for the operator Tcl_Token. */ parentIdx = subExprTokenPtr[1].numComponents; subExprTokenPtr[1].numComponents = 0; subExprTokenIdx = parentIdx; break; } /* * Since we're returning to parent, skip child handling code. */ nodePtr = nodes + nodePtr->p.parent; goto router; } } } /* *---------------------------------------------------------------------- * * Tcl_ParseExpr -- * * Given a string, the numBytes bytes starting at start, this function * parses it as a Tcl expression and stores information about the * structure of the expression in the Tcl_Parse struct indicated by the * caller. * * Results: * If the string is successfully parsed as a valid Tcl expression, TCL_OK * is returned, and data about the expression structure is written to * *parsePtr. If the string cannot be parsed as a valid Tcl expression, * TCL_ERROR is returned, and if interp is non-NULL, an error message is * written to interp. * * Side effects: * If there is insufficient space in parsePtr to hold all the information * about the expression, then additional space is malloc-ed. If the * function returns TCL_OK then the caller must eventually invoke * Tcl_FreeParse to release any additional space that was allocated. * *---------------------------------------------------------------------- */ int Tcl_ParseExpr( Tcl_Interp *interp, /* Used for error reporting. */ const char *start, /* Start of source string to parse. */ int numBytes, /* Number of bytes in string. If < 0, the * string consists of all bytes up to the * first null character. */ Tcl_Parse *parsePtr) /* Structure to fill with information about * the parsed expression; any previous * information in the structure is ignored. */ { int code; OpNode *opTree = NULL; /* Will point to the tree of operators. */ Tcl_Obj *litList = Tcl_NewObj(); /* List to hold the literals. */ Tcl_Obj *funcList = Tcl_NewObj(); /* List to hold the functon names. */ Tcl_Parse *exprParsePtr = TclStackAlloc(interp, sizeof(Tcl_Parse)); /* Holds the Tcl_Tokens of substitutions. */ if (numBytes < 0) { numBytes = (start ? strlen(start) : 0); } code = ParseExpr(interp, start, numBytes, &opTree, litList, funcList, exprParsePtr, 1 /* parseOnly */); Tcl_DecrRefCount(funcList); Tcl_DecrRefCount(litList); TclParseInit(interp, start, numBytes, parsePtr); if (code == TCL_OK) { ConvertTreeToTokens(start, numBytes, opTree, exprParsePtr->tokenPtr, parsePtr); } else { parsePtr->term = exprParsePtr->term; parsePtr->errorType = exprParsePtr->errorType; } Tcl_FreeParse(exprParsePtr); TclStackFree(interp, exprParsePtr); ckfree(opTree); return code; } /* *---------------------------------------------------------------------- * * ParseLexeme -- * * Parse a single lexeme from the start of a string, scanning no more * than numBytes bytes. * * Results: * Returns the number of bytes scanned to produce the lexeme. * * Side effects: * Code identifying lexeme parsed is writen to *lexemePtr. * *---------------------------------------------------------------------- */ static int ParseLexeme( const char *start, /* Start of lexeme to parse. */ int numBytes, /* Number of bytes in string. */ unsigned char *lexemePtr, /* Write code of parsed lexeme to this * storage. */ Tcl_Obj **literalPtr) /* Write corresponding literal value to this storage, if non-NULL. */ { const char *end; int scanned; Tcl_UniChar ch; Tcl_Obj *literal = NULL; unsigned char byte; if (numBytes == 0) { *lexemePtr = END; return 0; } byte = UCHAR(*start); if (byte < sizeof(Lexeme) && Lexeme[byte] != 0) { *lexemePtr = Lexeme[byte]; return 1; } switch (byte) { case '*': if ((numBytes > 1) && (start[1] == '*')) { *lexemePtr = EXPON; return 2; } *lexemePtr = MULT; return 1; case '=': if ((numBytes > 1) && (start[1] == '=')) { *lexemePtr = EQUAL; return 2; } *lexemePtr = INCOMPLETE; return 1; case '!': if ((numBytes > 1) && (start[1] == '=')) { *lexemePtr = NEQ; return 2; } *lexemePtr = NOT; return 1; case '&': if ((numBytes > 1) && (start[1] == '&')) { *lexemePtr = AND; return 2; } *lexemePtr = BIT_AND; return 1; case '|': if ((numBytes > 1) && (start[1] == '|')) { *lexemePtr = OR; return 2; } *lexemePtr = BIT_OR; return 1; case '<': if (numBytes > 1) { switch (start[1]) { case '<': *lexemePtr = LEFT_SHIFT; return 2; case '=': *lexemePtr = LEQ; return 2; } } *lexemePtr = LESS; return 1; case '>': if (numBytes > 1) { switch (start[1]) { case '>': *lexemePtr = RIGHT_SHIFT; return 2; case '=': *lexemePtr = GEQ; return 2; } } *lexemePtr = GREATER; return 1; case 'i': if ((numBytes > 1) && (start[1] == 'n') && ((numBytes == 2) || start[2] & 0x80 || !isalpha(UCHAR(start[2])))) { /* * Must make this check so we can tell the difference between the * "in" operator and the "int" function name and the "infinity" * numeric value. */ *lexemePtr = IN_LIST; return 2; } break; case 'e': if ((numBytes > 1) && (start[1] == 'q') && ((numBytes == 2) || start[2] & 0x80 || !isalpha(UCHAR(start[2])))) { *lexemePtr = STREQ; return 2; } break; case 'n': if ((numBytes > 1) && ((numBytes == 2) || start[2] & 0x80 || !isalpha(UCHAR(start[2])))) { switch (start[1]) { case 'e': *lexemePtr = STRNEQ; return 2; case 'i': *lexemePtr = NOT_IN_LIST; return 2; } } } literal = Tcl_NewObj(); if (TclParseNumber(NULL, literal, NULL, start, numBytes, &end, TCL_PARSE_NO_WHITESPACE) == TCL_OK) { if (end < start + numBytes && !TclIsBareword(*end)) { number: TclInitStringRep(literal, start, end-start); *lexemePtr = NUMBER; if (literalPtr) { *literalPtr = literal; } else { Tcl_DecrRefCount(literal); } return (end-start); } else { unsigned char lexeme; /* * We have a number followed directly by bareword characters * (alpha, digit, underscore). Is this a number followed by * bareword syntax error? Or should we join into one bareword? * Example: Inf + luence + () becomes a valid function call. * [Bug 3401704] */ if (literal->typePtr == &tclDoubleType) { const char *p = start; while (p < end) { if (!TclIsBareword(*p++)) { /* * The number has non-bareword characters, so we * must treat it as a number. */ goto number; } } } ParseLexeme(end, numBytes-(end-start), &lexeme, NULL); if ((NODE_TYPE & lexeme) == BINARY) { /* * The bareword characters following the number take the * form of an operator (eq, ne, in, ni, ...) so we treat * as number + operator. */ goto number; } /* * Otherwise, fall through and parse the whole as a bareword. */ } } /* * We reject leading underscores in bareword. No sensible reason why. * Might be inspired by reserved identifier rules in C, which of course * have no direct relevance here. */ if (!TclIsBareword(*start) || *start == '_') { if (Tcl_UtfCharComplete(start, numBytes)) { scanned = Tcl_UtfToUniChar(start, &ch); } else { char utfBytes[TCL_UTF_MAX]; memcpy(utfBytes, start, (size_t) numBytes); utfBytes[numBytes] = '\0'; scanned = Tcl_UtfToUniChar(utfBytes, &ch); } *lexemePtr = INVALID; Tcl_DecrRefCount(literal); return scanned; } end = start; while (numBytes && TclIsBareword(*end)) { end += 1; numBytes -= 1; } *lexemePtr = BAREWORD; if (literalPtr) { Tcl_SetStringObj(literal, start, (int) (end-start)); *literalPtr = literal; } else { Tcl_DecrRefCount(literal); } return (end-start); } /* *---------------------------------------------------------------------- * * TclCompileExpr -- * * This procedure compiles a string containing a Tcl expression into Tcl * bytecodes. * * Results: * None. * * Side effects: * Adds instructions to envPtr to evaluate the expression at runtime. * *---------------------------------------------------------------------- */ void TclCompileExpr( Tcl_Interp *interp, /* Used for error reporting. */ const char *script, /* The source script to compile. */ int numBytes, /* Number of bytes in script. */ CompileEnv *envPtr, /* Holds resulting instructions. */ int optimize) /* 0 for one-off expressions. */ { OpNode *opTree = NULL; /* Will point to the tree of operators */ Tcl_Obj *litList = Tcl_NewObj(); /* List to hold the literals */ Tcl_Obj *funcList = Tcl_NewObj(); /* List to hold the functon names*/ Tcl_Parse *parsePtr = TclStackAlloc(interp, sizeof(Tcl_Parse)); /* Holds the Tcl_Tokens of substitutions */ int code = ParseExpr(interp, script, numBytes, &opTree, litList, funcList, parsePtr, 0 /* parseOnly */); if (code == TCL_OK) { /* * Valid parse; compile the tree. */ int objc; Tcl_Obj *const *litObjv; Tcl_Obj **funcObjv; /* TIP #280 : Track Lines within the expression */ TclAdvanceLines(&envPtr->line, script, script + TclParseAllWhiteSpace(script, numBytes)); TclListObjGetElements(NULL, litList, &objc, (Tcl_Obj ***)&litObjv); TclListObjGetElements(NULL, funcList, &objc, &funcObjv); CompileExprTree(interp, opTree, 0, &litObjv, funcObjv, parsePtr->tokenPtr, envPtr, optimize); } else { TclCompileSyntaxError(interp, envPtr); } Tcl_FreeParse(parsePtr); TclStackFree(interp, parsePtr); Tcl_DecrRefCount(funcList); Tcl_DecrRefCount(litList); ckfree(opTree); } /* *---------------------------------------------------------------------- * * ExecConstantExprTree -- * Compiles and executes bytecode for the subexpression tree at index * in the nodes array. This subexpression must be constant, made up * of only constant operators (not functions) and literals. * * Results: * A standard Tcl return code and result left in interp. * * Side effects: * Consumes subtree of nodes rooted at index. Advances the pointer * *litObjvPtr. * *---------------------------------------------------------------------- */ static int ExecConstantExprTree( Tcl_Interp *interp, OpNode *nodes, int index, Tcl_Obj *const **litObjvPtr) { CompileEnv *envPtr; ByteCode *byteCodePtr; int code; Tcl_Obj *byteCodeObj = Tcl_NewObj(); NRE_callback *rootPtr = TOP_CB(interp); /* * Note we are compiling an expression with literal arguments. This means * there can be no [info frame] calls when we execute the resulting * bytecode, so there's no need to tend to TIP 280 issues. */ envPtr = TclStackAlloc(interp, sizeof(CompileEnv)); TclInitCompileEnv(interp, envPtr, NULL, 0, NULL, 0); CompileExprTree(interp, nodes, index, litObjvPtr, NULL, NULL, envPtr, 0 /* optimize */); TclEmitOpcode(INST_DONE, envPtr); Tcl_IncrRefCount(byteCodeObj); TclInitByteCodeObj(byteCodeObj, envPtr); TclFreeCompileEnv(envPtr); TclStackFree(interp, envPtr); byteCodePtr = byteCodeObj->internalRep.twoPtrValue.ptr1; TclNRExecuteByteCode(interp, byteCodePtr); code = TclNRRunCallbacks(interp, TCL_OK, rootPtr); Tcl_DecrRefCount(byteCodeObj); return code; } /* *---------------------------------------------------------------------- * * CompileExprTree -- * * Compiles and writes to envPtr instructions for the subexpression tree * at index in the nodes array. (*litObjvPtr) must point to the proper * location in a corresponding literals list. Likewise, when non-NULL, * funcObjv and tokenPtr must point into matching arrays of function * names and Tcl_Token's derived from earlier call to ParseExpr(). When * optimize is true, any constant subexpressions will be precomputed. * * Results: * None. * * Side effects: * Adds instructions to envPtr to evaluate the expression at runtime. * Consumes subtree of nodes rooted at index. Advances the pointer * *litObjvPtr. * *---------------------------------------------------------------------- */ static void CompileExprTree( Tcl_Interp *interp, OpNode *nodes, int index, Tcl_Obj *const **litObjvPtr, Tcl_Obj *const *funcObjv, Tcl_Token *tokenPtr, CompileEnv *envPtr, int optimize) { OpNode *nodePtr = nodes + index; OpNode *rootPtr = nodePtr; int numWords = 0; JumpList *jumpPtr = NULL; int convert = 1; while (1) { int next; JumpList *freePtr, *newJump; if (nodePtr->mark == MARK_LEFT) { next = nodePtr->left; if (nodePtr->lexeme == QUESTION) { convert = 1; } } else if (nodePtr->mark == MARK_RIGHT) { next = nodePtr->right; switch (nodePtr->lexeme) { case FUNCTION: { Tcl_DString cmdName; const char *p; int length; Tcl_DStringInit(&cmdName); TclDStringAppendLiteral(&cmdName, "tcl::mathfunc::"); p = TclGetStringFromObj(*funcObjv, &length); funcObjv++; Tcl_DStringAppend(&cmdName, p, length); TclEmitPush(TclRegisterNewCmdLiteral(envPtr, Tcl_DStringValue(&cmdName), Tcl_DStringLength(&cmdName)), envPtr); Tcl_DStringFree(&cmdName); /* * Start a count of the number of words in this function * command invocation. In case there's already a count in * progress (nested functions), save it in our unused "left" * field for restoring later. */ nodePtr->left = numWords; numWords = 2; /* Command plus one argument */ break; } case QUESTION: newJump = TclStackAlloc(interp, sizeof(JumpList)); newJump->next = jumpPtr; jumpPtr = newJump; TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpPtr->jump); break; case COLON: newJump = TclStackAlloc(interp, sizeof(JumpList)); newJump->next = jumpPtr; jumpPtr = newJump; TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpPtr->jump); TclAdjustStackDepth(-1, envPtr); if (convert) { jumpPtr->jump.jumpType = TCL_TRUE_JUMP; } convert = 1; break; case AND: case OR: newJump = TclStackAlloc(interp, sizeof(JumpList)); newJump->next = jumpPtr; jumpPtr = newJump; TclEmitForwardJump(envPtr, (nodePtr->lexeme == AND) ? TCL_FALSE_JUMP : TCL_TRUE_JUMP, &jumpPtr->jump); break; } } else { int pc1, pc2, target; switch (nodePtr->lexeme) { case START: case QUESTION: if (convert && (nodePtr == rootPtr)) { TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr); } break; case OPEN_PAREN: /* do nothing */ break; case FUNCTION: /* * Use the numWords count we've kept to invoke the function * command with the correct number of arguments. */ if (numWords < 255) { TclEmitInvoke(envPtr, INST_INVOKE_STK1, numWords); } else { TclEmitInvoke(envPtr, INST_INVOKE_STK4, numWords); } /* * Restore any saved numWords value. */ numWords = nodePtr->left; convert = 1; break; case COMMA: /* * Each comma implies another function argument. */ numWords++; break; case COLON: CLANG_ASSERT(jumpPtr); if (jumpPtr->jump.jumpType == TCL_TRUE_JUMP) { jumpPtr->jump.jumpType = TCL_UNCONDITIONAL_JUMP; convert = 1; } target = jumpPtr->jump.codeOffset + 2; if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) { target += 3; } freePtr = jumpPtr; jumpPtr = jumpPtr->next; TclStackFree(interp, freePtr); TclFixupForwardJump(envPtr, &jumpPtr->jump, target - jumpPtr->jump.codeOffset, 127); freePtr = jumpPtr; jumpPtr = jumpPtr->next; TclStackFree(interp, freePtr); break; case AND: case OR: CLANG_ASSERT(jumpPtr); pc1 = CurrentOffset(envPtr); TclEmitInstInt1((nodePtr->lexeme == AND) ? INST_JUMP_FALSE1 : INST_JUMP_TRUE1, 0, envPtr); TclEmitPush(TclRegisterNewLiteral(envPtr, (nodePtr->lexeme == AND) ? "1" : "0", 1), envPtr); pc2 = CurrentOffset(envPtr); TclEmitInstInt1(INST_JUMP1, 0, envPtr); TclAdjustStackDepth(-1, envPtr); TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc1, envPtr->codeStart + pc1 + 1); if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) { pc2 += 3; } TclEmitPush(TclRegisterNewLiteral(envPtr, (nodePtr->lexeme == AND) ? "0" : "1", 1), envPtr); TclStoreInt1AtPtr(CurrentOffset(envPtr) - pc2, envPtr->codeStart + pc2 + 1); convert = 0; freePtr = jumpPtr; jumpPtr = jumpPtr->next; TclStackFree(interp, freePtr); break; default: TclEmitOpcode(instruction[nodePtr->lexeme], envPtr); convert = 0; break; } if (nodePtr == rootPtr) { /* We're done */ return; } nodePtr = nodes + nodePtr->p.parent; continue; } nodePtr->mark++; switch (next) { case OT_EMPTY: numWords = 1; /* No arguments, so just the command */ break; case OT_LITERAL: { Tcl_Obj *const *litObjv = *litObjvPtr; Tcl_Obj *literal = *litObjv; if (optimize) { int length; const char *bytes = TclGetStringFromObj(literal, &length); int index = TclRegisterNewLiteral(envPtr, bytes, length); Tcl_Obj *objPtr = TclFetchLiteral(envPtr, index); if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) { /* * Would like to do this: * * lePtr->objPtr = literal; * Tcl_IncrRefCount(literal); * Tcl_DecrRefCount(objPtr); * * However, the design of the "global" and "local" * LiteralTable does not permit the value of lePtr->objPtr * to change. So rather than replace lePtr->objPtr, we do * surgery to transfer our desired intrep into it. */ objPtr->typePtr = literal->typePtr; objPtr->internalRep = literal->internalRep; literal->typePtr = NULL; } TclEmitPush(index, envPtr); } else { /* * When optimize==0, we know the expression is a one-off and * there's nothing to be gained from sharing literals when * they won't live long, and the copies we have already have * an appropriate intrep. In this case, skip literal * registration that would enable sharing, and use the routine * that preserves intreps. */ TclEmitPush(TclAddLiteralObj(envPtr, literal, NULL), envPtr); } (*litObjvPtr)++; break; } case OT_TOKENS: CompileTokens(envPtr, tokenPtr, interp); tokenPtr += tokenPtr->numComponents + 1; break; default: if (optimize && nodes[next].constant) { Tcl_InterpState save = Tcl_SaveInterpState(interp, TCL_OK); if (ExecConstantExprTree(interp, nodes, next, litObjvPtr) == TCL_OK) { int index; Tcl_Obj *objPtr = Tcl_GetObjResult(interp); /* * Don't generate a string rep, but if we have one * already, then use it to share via the literal table. */ if (objPtr->bytes) { Tcl_Obj *tableValue; index = TclRegisterNewLiteral(envPtr, objPtr->bytes, objPtr->length); tableValue = TclFetchLiteral(envPtr, index); if ((tableValue->typePtr == NULL) && (objPtr->typePtr != NULL)) { /* * Same intrep surgery as for OT_LITERAL. */ tableValue->typePtr = objPtr->typePtr; tableValue->internalRep = objPtr->internalRep; objPtr->typePtr = NULL; } } else { index = TclAddLiteralObj(envPtr, objPtr, NULL); } TclEmitPush(index, envPtr); } else { TclCompileSyntaxError(interp, envPtr); } Tcl_RestoreInterpState(interp, save); convert = 0; } else { nodePtr = nodes + next; } } } } /* *---------------------------------------------------------------------- * * TclSingleOpCmd -- * * Implements the commands: ~, !, <<, >>, %, !=, ne, in, ni * in the ::tcl::mathop namespace. These commands have no * extension to arbitrary arguments; they accept only exactly one * or exactly two arguments as suitable for the operator. * * Results: * A standard Tcl return code and result left in interp. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclSingleOpCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { TclOpCmdClientData *occdPtr = clientData; unsigned char lexeme; OpNode nodes[2]; Tcl_Obj *const *litObjv = objv + 1; if (objc != 1 + occdPtr->i.numArgs) { Tcl_WrongNumArgs(interp, 1, objv, occdPtr->expected); return TCL_ERROR; } ParseLexeme(occdPtr->op, strlen(occdPtr->op), &lexeme, NULL); nodes[0].lexeme = START; nodes[0].mark = MARK_RIGHT; nodes[0].right = 1; nodes[1].lexeme = lexeme; if (objc == 2) { nodes[1].mark = MARK_RIGHT; } else { nodes[1].mark = MARK_LEFT; nodes[1].left = OT_LITERAL; } nodes[1].right = OT_LITERAL; nodes[1].p.parent = 0; return ExecConstantExprTree(interp, nodes, 0, &litObjv); } /* *---------------------------------------------------------------------- * * TclSortingOpCmd -- * Implements the commands: * <, <=, >, >=, ==, eq * in the ::tcl::mathop namespace. These commands are defined for * arbitrary number of arguments by computing the AND of the base * operator applied to all neighbor argument pairs. * * Results: * A standard Tcl return code and result left in interp. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclSortingOpCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int code = TCL_OK; if (objc < 3) { Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); } else { TclOpCmdClientData *occdPtr = clientData; Tcl_Obj **litObjv = TclStackAlloc(interp, 2 * (objc-2) * sizeof(Tcl_Obj *)); OpNode *nodes = TclStackAlloc(interp, 2 * (objc-2) * sizeof(OpNode)); unsigned char lexeme; int i, lastAnd = 1; Tcl_Obj *const *litObjPtrPtr = litObjv; ParseLexeme(occdPtr->op, strlen(occdPtr->op), &lexeme, NULL); litObjv[0] = objv[1]; nodes[0].lexeme = START; nodes[0].mark = MARK_RIGHT; for (i=2; ii.identity)); return TCL_OK; } ParseLexeme(occdPtr->op, strlen(occdPtr->op), &lexeme, NULL); lexeme |= BINARY; if (objc == 2) { Tcl_Obj *litObjv[2]; OpNode nodes[2]; int decrMe = 0; Tcl_Obj *const *litObjPtrPtr = litObjv; if (lexeme == EXPON) { litObjv[1] = Tcl_NewIntObj(occdPtr->i.identity); Tcl_IncrRefCount(litObjv[1]); decrMe = 1; litObjv[0] = objv[1]; nodes[0].lexeme = START; nodes[0].mark = MARK_RIGHT; nodes[0].right = 1; nodes[1].lexeme = lexeme; nodes[1].mark = MARK_LEFT; nodes[1].left = OT_LITERAL; nodes[1].right = OT_LITERAL; nodes[1].p.parent = 0; } else { if (lexeme == DIVIDE) { litObjv[0] = Tcl_NewDoubleObj(1.0); } else { litObjv[0] = Tcl_NewIntObj(occdPtr->i.identity); } Tcl_IncrRefCount(litObjv[0]); litObjv[1] = objv[1]; nodes[0].lexeme = START; nodes[0].mark = MARK_RIGHT; nodes[0].right = 1; nodes[1].lexeme = lexeme; nodes[1].mark = MARK_LEFT; nodes[1].left = OT_LITERAL; nodes[1].right = OT_LITERAL; nodes[1].p.parent = 0; } code = ExecConstantExprTree(interp, nodes, 0, &litObjPtrPtr); Tcl_DecrRefCount(litObjv[decrMe]); return code; } else { Tcl_Obj *const *litObjv = objv + 1; OpNode *nodes = TclStackAlloc(interp, (objc-1) * sizeof(OpNode)); int i, lastOp = OT_LITERAL; nodes[0].lexeme = START; nodes[0].mark = MARK_RIGHT; if (lexeme == EXPON) { for (i=objc-2; i>0; i--) { nodes[i].lexeme = lexeme; nodes[i].mark = MARK_LEFT; nodes[i].left = OT_LITERAL; nodes[i].right = lastOp; if (lastOp >= 0) { nodes[lastOp].p.parent = i; } lastOp = i; } } else { for (i=1; i= 0) { nodes[lastOp].p.parent = i; } nodes[i].right = OT_LITERAL; lastOp = i; } } nodes[0].right = lastOp; nodes[lastOp].p.parent = 0; code = ExecConstantExprTree(interp, nodes, 0, &litObjv); TclStackFree(interp, nodes); return code; } } /* *---------------------------------------------------------------------- * * TclNoIdentOpCmd -- * Implements the commands: -, / * in the ::tcl::mathop namespace. These commands are defined for * arbitrary non-zero number of arguments by repeatedly applying the base * operator with suitable associative rules. When no arguments are * provided, an error is raised. * * Results: * A standard Tcl return code and result left in interp. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclNoIdentOpCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { TclOpCmdClientData *occdPtr = clientData; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, occdPtr->expected); return TCL_ERROR; } return TclVariadicOpCmd(clientData, interp, objc, objv); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclUtil.c0000644000175000017500000035405312663660065015001 0ustar sergeisergei/* * tclUtil.c -- * * This file contains utility functions that are used by many Tcl * commands. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclParse.h" #include "tclStringTrim.h" #include /* * The absolute pathname of the executable in which this Tcl library is * running. */ static ProcessGlobalValue executableName = { 0, 0, NULL, NULL, NULL, NULL, NULL }; /* * The following values are used in the flags arguments of Tcl*Scan*Element * and Tcl*Convert*Element. The values TCL_DONT_USE_BRACES and * TCL_DONT_QUOTE_HASH are defined in tcl.h, like so: * #define TCL_DONT_USE_BRACES 1 #define TCL_DONT_QUOTE_HASH 8 * * Those are public flag bits which callers of the public routines * Tcl_Convert*Element() can use to indicate: * * TCL_DONT_USE_BRACES - 1 means the caller is insisting that brace * quoting not be used when converting the list * element. * TCL_DONT_QUOTE_HASH - 1 means the caller insists that a leading hash * character ('#') should *not* be quoted. This * is appropriate when the caller can guarantee * the element is not the first element of a * list, so [eval] cannot mis-parse the element * as a comment. * * The remaining values which can be carried by the flags of these routines * are for internal use only. Make sure they do not overlap with the public * values above. * * The Tcl*Scan*Element() routines make a determination which of 4 modes of * conversion is most appropriate for Tcl*Convert*Element() to perform, and * sets two bits of the flags value to indicate the mode selected. * * CONVERT_NONE The element needs no quoting. Its literal string is * suitable as is. * CONVERT_BRACE The conversion should be enclosing the literal string * in braces. * CONVERT_ESCAPE The conversion should be using backslashes to escape * any characters in the string that require it. * CONVERT_MASK A mask value used to extract the conversion mode from * the flags argument. * Also indicates a strange conversion mode where all * special characters are escaped with backslashes * *except for braces*. This is a strange and unnecessary * case, but it's part of the historical way in which * lists have been formatted in Tcl. To experiment with * removing this case, set the value of COMPAT to 0. * * One last flag value is used only by callers of TclScanElement(). The flag * value produced by a call to Tcl*Scan*Element() will never leave this bit * set. * * CONVERT_ANY The caller of TclScanElement() declares it can make no * promise about what public flags will be passed to the * matching call of TclConvertElement(). As such, * TclScanElement() has to determine the worst case * destination buffer length over all possibilities, and * in other cases this means an overestimate of the * required size. * * For more details, see the comments on the Tcl*Scan*Element and * Tcl*Convert*Element routines. */ #define COMPAT 1 #define CONVERT_NONE 0 #define CONVERT_BRACE 2 #define CONVERT_ESCAPE 4 #define CONVERT_MASK (CONVERT_BRACE | CONVERT_ESCAPE) #define CONVERT_ANY 16 /* * The following key is used by Tcl_PrintDouble and TclPrecTraceProc to * access the precision to be used for double formatting. */ static Tcl_ThreadDataKey precisionKey; /* * Prototypes for functions defined later in this file. */ static void ClearHash(Tcl_HashTable *tablePtr); static void FreeProcessGlobalValue(ClientData clientData); static void FreeThreadHash(ClientData clientData); static Tcl_HashTable * GetThreadHash(Tcl_ThreadDataKey *keyPtr); static int SetEndOffsetFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void UpdateStringOfEndOffset(Tcl_Obj *objPtr); static int FindElement(Tcl_Interp *interp, const char *string, int stringLength, const char *typeStr, const char *typeCode, const char **elementPtr, const char **nextPtr, int *sizePtr, int *literalPtr); /* * The following is the Tcl object type definition for an object that * represents a list index in the form, "end-offset". It is used as a * performance optimization in TclGetIntForIndex. The internal rep is an * integer, so no memory management is required for it. */ const Tcl_ObjType tclEndOffsetType = { "end-offset", /* name */ NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ UpdateStringOfEndOffset, /* updateStringProc */ SetEndOffsetFromAny }; /* * * STRING REPRESENTATION OF LISTS * * * * * The next several routines implement the conversions of strings to and from * Tcl lists. To understand their operation, the rules of parsing and * generating the string representation of lists must be known. Here we * describe them in one place. * * A list is made up of zero or more elements. Any string is a list if it is * made up of alternating substrings of element-separating ASCII whitespace * and properly formatted elements. * * The ASCII characters which can make up the whitespace between list elements * are: * * \u0009 \t TAB * \u000A \n NEWLINE * \u000B \v VERTICAL TAB * \u000C \f FORM FEED * \u000D \r CARRIAGE RETURN * \u0020 SPACE * * NOTE: differences between this and other places where Tcl defines a role * for "whitespace". * * * Unlike command parsing, here NEWLINE is just another whitespace * character; its role as a command terminator in a script has no * importance here. * * * Unlike command parsing, the BACKSLASH NEWLINE sequence is not * considered to be a whitespace character. * * * Other Unicode whitespace characters (recognized by [string is space] * or Tcl_UniCharIsSpace()) do not play any role as element separators * in Tcl lists. * * * The NUL byte ought not appear, as it is not in strings properly * encoded for Tcl, but if it is present, it is not treated as * separating whitespace, or a string terminator. It is just another * character in a list element. * * The interpretation of a formatted substring as a list element follows rules * similar to the parsing of the words of a command in a Tcl script. Backslash * substitution plays a key role, and is defined exactly as it is in command * parsing. The same routine, TclParseBackslash() is used in both command * parsing and list parsing. * * NOTE: This means that if and when backslash substitution rules ever change * for command parsing, the interpretation of strings as lists also changes. * * Backslash substitution replaces an "escape sequence" of one or more * characters starting with * \u005c \ BACKSLASH * with a single character. The one character escape sequence case happens only * when BACKSLASH is the last character in the string. In all other cases, the * escape sequence is at least two characters long. * * The formatted substrings are interpreted as element values according to the * following cases: * * * If the first character of a formatted substring is * \u007b { OPEN BRACE * then the end of the substring is the matching * \u007d } CLOSE BRACE * character, where matching is determined by counting nesting levels, and * not including any brace characters that are contained within a backslash * escape sequence in the nesting count. Having found the matching brace, * all characters between the braces are the string value of the element. * If no matching close brace is found before the end of the string, the * string is not a Tcl list. If the character following the close brace is * not an element separating whitespace character, or the end of the string, * then the string is not a Tcl list. * * NOTE: this differs from a brace-quoted word in the parsing of a Tcl * command only in its treatment of the backslash-newline sequence. In a * list element, the literal characters in the backslash-newline sequence * become part of the element value. In a script word, conversion to a * single SPACE character is done. * * NOTE: Most list element values can be represented by a formatted * substring using brace quoting. The exceptions are any element value that * includes an unbalanced brace not in a backslash escape sequence, and any * value that ends with a backslash not itself in a backslash escape * sequence. * * * If the first character of a formatted substring is * \u0022 " QUOTE * then the end of the substring is the next QUOTE character, not counting * any QUOTE characters that are contained within a backslash escape * sequence. If no next QUOTE is found before the end of the string, the * string is not a Tcl list. If the character following the closing QUOTE is * not an element separating whitespace character, or the end of the string, * then the string is not a Tcl list. Having found the limits of the * substring, the element value is produced by performing backslash * substitution on the character sequence between the open and close QUOTEs. * * NOTE: Any element value can be represented by this style of formatting, * given suitable choice of backslash escape sequences. * * * All other formatted substrings are terminated by the next element * separating whitespace character in the string. Having found the limits * of the substring, the element value is produced by performing backslash * substitution on it. * * NOTE: Any element value can be represented by this style of formatting, * given suitable choice of backslash escape sequences, with one exception. * The empty string cannot be represented as a list element without the use * of either braces or quotes to delimit it. * * This collection of parsing rules is implemented in the routine * FindElement(). * * In order to produce lists that can be parsed by these rules, we need the * ability to distinguish between characters that are part of a list element * value from characters providing syntax that define the structure of the * list. This means that our code that generates lists must at a minimum be * able to produce escape sequences for the 10 characters identified above * that have significance to a list parser. * * * * CANONICAL LISTS * * * * * * * In addition to the basic rules for parsing strings into Tcl lists, there * are additional properties to be met by the set of list values that are * generated by Tcl. Such list values are often said to be in "canonical * form": * * * When any canonical list is evaluated as a Tcl script, it is a script of * either zero commands (an empty list) or exactly one command. The command * word is exactly the first element of the list, and each argument word is * exactly one of the following elements of the list. This means that any * characters that have special meaning during script evaluation need * special treatment when canonical lists are produced: * * * Whitespace between elements may not include NEWLINE. * * The command terminating character, * \u003b ; SEMICOLON * must be BRACEd, QUOTEd, or escaped so that it does not terminate the * command prematurely. * * Any of the characters that begin substitutions in scripts, * \u0024 $ DOLLAR * \u005b [ OPEN BRACKET * \u005c \ BACKSLASH * need to be BRACEd or escaped. * * In any list where the first character of the first element is * \u0023 # HASH * that HASH character must be BRACEd, QUOTEd, or escaped so that it * does not convert the command into a comment. * * Any list element that contains the character sequence BACKSLASH * NEWLINE cannot be formatted with BRACEs. The BACKSLASH character * must be represented by an escape sequence, and unless QUOTEs are * used, the NEWLINE must be as well. * * * It is also guaranteed that one can use a canonical list as a building * block of a larger script within command substitution, as in this example: * set script "puts \[[list $cmd $arg]]"; eval $script * To support this usage, any appearance of the character * \u005d ] CLOSE BRACKET * in a list element must be BRACEd, QUOTEd, or escaped. * * * Finally it is guaranteed that enclosing a canonical list in braces * produces a new value that is also a canonical list. This new list has * length 1, and its only element is the original canonical list. This same * guarantee also makes it possible to construct scripts where an argument * word is given a list value by enclosing the canonical form of that list * in braces: * set script "puts {[list $one $two $three]}"; eval $script * This sort of coding was once fairly common, though it's become more * idiomatic to see the following instead: * set script [list puts [list $one $two $three]]; eval $script * In order to support this guarantee, every canonical list must have * balance when counting those braces that are not in escape sequences. * * Within these constraints, the canonical list generation routines * TclScanElement() and TclConvertElement() attempt to generate the string for * any list that is easiest to read. When an element value is itself * acceptable as the formatted substring, it is usually used (CONVERT_NONE). * When some quoting or escaping is required, use of BRACEs (CONVERT_BRACE) is * usually preferred over the use of escape sequences (CONVERT_ESCAPE). There * are some exceptions to both of these preferences for reasons of code * simplicity, efficiency, and continuation of historical habits. Canonical * lists never use the QUOTE formatting to delimit their elements because that * form of quoting does not nest, which makes construction of nested lists far * too much trouble. Canonical lists always use only a single SPACE character * for element-separating whitespace. * * * * FUTURE CONSIDERATIONS * * * * * When a list element requires quoting or escaping due to a CLOSE BRACKET * character or an internal QUOTE character, a strange formatting mode is * recommended. For example, if the value "a{b]c}d" is converted by the usual * modes: * * CONVERT_BRACE: a{b]c}d => {a{b]c}d} * CONVERT_ESCAPE: a{b]c}d => a\{b\]c\}d * * we get perfectly usable formatted list elements. However, this is not what * Tcl releases have been producing. Instead, we have: * * CONVERT_MASK: a{b]c}d => a{b\]c}d * * where the CLOSE BRACKET is escaped, but the BRACEs are not. The same effect * can be seen replacing ] with " in this example. There does not appear to be * any functional or aesthetic purpose for this strange additional mode. The * sole purpose I can see for preserving it is to keep generating the same * formatted lists programmers have become accustomed to, and perhaps written * tests to expect. That is, compatibility only. The additional code * complexity required to support this mode is significant. The lines of code * supporting it are delimited in the routines below with #if COMPAT * directives. This makes it easy to experiment with eliminating this * formatting mode simply with "#define COMPAT 0" above. I believe this is * worth considering. * * Another consideration is the treatment of QUOTE characters in list * elements. TclConvertElement() must have the ability to produce the escape * sequence \" so that when a list element begins with a QUOTE we do not * confuse that first character with a QUOTE used as list syntax to define * list structure. However, that is the only place where QUOTE characters need * quoting. In this way, handling QUOTE could really be much more like the way * we handle HASH which also needs quoting and escaping only in particular * situations. Following up this could increase the set of list elements that * can use the CONVERT_NONE formatting mode. * * More speculative is that the demands of canonical list form require brace * balance for the list as a whole, while the current implementation achieves * this by establishing brace balance for every element. * * Finally, a reminder that the rules for parsing and formatting lists are * closely tied together with the rules for parsing and evaluating scripts, * and will need to evolve in sync. */ /* *---------------------------------------------------------------------- * * TclMaxListLength -- * * Given 'bytes' pointing to 'numBytes' bytes, scan through them and * count the number of whitespace runs that could be list element * separators. If 'numBytes' is -1, scan to the terminating '\0'. Not a * full list parser. Typically used to get a quick and dirty overestimate * of length size in order to allocate space for an actual list parser to * operate with. * * Results: * Returns the largest number of list elements that could possibly be in * this string, interpreted as a Tcl list. If 'endPtr' is not NULL, * writes a pointer to the end of the string scanned there. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclMaxListLength( const char *bytes, int numBytes, const char **endPtr) { int count = 0; if ((numBytes == 0) || ((numBytes == -1) && (*bytes == '\0'))) { /* Empty string case - quick exit */ goto done; } /* * No list element before leading white space. */ count += 1 - TclIsSpaceProc(*bytes); /* * Count white space runs as potential element separators. */ while (numBytes) { if ((numBytes == -1) && (*bytes == '\0')) { break; } if (TclIsSpaceProc(*bytes)) { /* * Space run started; bump count. */ count++; do { bytes++; numBytes -= (numBytes != -1); } while (numBytes && TclIsSpaceProc(*bytes)); if ((numBytes == 0) || ((numBytes == -1) && (*bytes == '\0'))) { break; } /* * (*bytes) is non-space; return to counting state. */ } bytes++; numBytes -= (numBytes != -1); } /* * No list element following trailing white space. */ count -= TclIsSpaceProc(bytes[-1]); done: if (endPtr) { *endPtr = bytes; } return count; } /* *---------------------------------------------------------------------- * * TclFindElement -- * * Given a pointer into a Tcl list, locate the first (or next) element in * the list. * * Results: * The return value is normally TCL_OK, which means that the element was * successfully located. If TCL_ERROR is returned it means that list * didn't have proper list structure; the interp's result contains a more * detailed error message. * * If TCL_OK is returned, then *elementPtr will be set to point to the * first element of list, and *nextPtr will be set to point to the * character just after any white space following the last character * that's part of the element. If this is the last argument in the list, * then *nextPtr will point just after the last character in the list * (i.e., at the character at list+listLength). If sizePtr is non-NULL, * *sizePtr is filled in with the number of bytes in the element. If the * element is in braces, then *elementPtr will point to the character * after the opening brace and *sizePtr will not include either of the * braces. If there isn't an element in the list, *sizePtr will be zero, * and both *elementPtr and *nextPtr will point just after the last * character in the list. If literalPtr is non-NULL, *literalPtr is set * to a boolean value indicating whether the substring returned as the * values of **elementPtr and *sizePtr is the literal value of a list * element. If not, a call to TclCopyAndCollapse() is needed to produce * the actual value of the list element. Note: this function does NOT * collapse backslash sequences, but uses *literalPtr to tell callers * when it is required for them to do so. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclFindElement( Tcl_Interp *interp, /* Interpreter to use for error reporting. If * NULL, then no error message is left after * errors. */ const char *list, /* Points to the first byte of a string * containing a Tcl list with zero or more * elements (possibly in braces). */ int listLength, /* Number of bytes in the list's string. */ const char **elementPtr, /* Where to put address of first significant * character in first element of list. */ const char **nextPtr, /* Fill in with location of character just * after all white space following end of * argument (next arg or end of list). */ int *sizePtr, /* If non-zero, fill in with size of * element. */ int *literalPtr) /* If non-zero, fill in with non-zero/zero to * indicate that the substring of *sizePtr * bytes starting at **elementPtr is/is not * the literal list element and therefore * does not/does require a call to * TclCopyAndCollapse() by the caller. */ { return FindElement(interp, list, listLength, "list", "LIST", elementPtr, nextPtr, sizePtr, literalPtr); } int TclFindDictElement( Tcl_Interp *interp, /* Interpreter to use for error reporting. If * NULL, then no error message is left after * errors. */ const char *dict, /* Points to the first byte of a string * containing a Tcl dictionary with zero or * more keys and values (possibly in * braces). */ int dictLength, /* Number of bytes in the dict's string. */ const char **elementPtr, /* Where to put address of first significant * character in the first element (i.e., key * or value) of dict. */ const char **nextPtr, /* Fill in with location of character just * after all white space following end of * element (next arg or end of list). */ int *sizePtr, /* If non-zero, fill in with size of * element. */ int *literalPtr) /* If non-zero, fill in with non-zero/zero to * indicate that the substring of *sizePtr * bytes starting at **elementPtr is/is not * the literal key or value and therefore * does not/does require a call to * TclCopyAndCollapse() by the caller. */ { return FindElement(interp, dict, dictLength, "dict", "DICTIONARY", elementPtr, nextPtr, sizePtr, literalPtr); } static int FindElement( Tcl_Interp *interp, /* Interpreter to use for error reporting. If * NULL, then no error message is left after * errors. */ const char *string, /* Points to the first byte of a string * containing a Tcl list or dictionary with * zero or more elements (possibly in * braces). */ int stringLength, /* Number of bytes in the string. */ const char *typeStr, /* The name of the type of thing we are * parsing, for error messages. */ const char *typeCode, /* The type code for thing we are parsing, for * error messages. */ const char **elementPtr, /* Where to put address of first significant * character in first element. */ const char **nextPtr, /* Fill in with location of character just * after all white space following end of * argument (next arg or end of list/dict). */ int *sizePtr, /* If non-zero, fill in with size of * element. */ int *literalPtr) /* If non-zero, fill in with non-zero/zero to * indicate that the substring of *sizePtr * bytes starting at **elementPtr is/is not * the literal list/dict element and therefore * does not/does require a call to * TclCopyAndCollapse() by the caller. */ { const char *p = string; const char *elemStart; /* Points to first byte of first element. */ const char *limit; /* Points just after list/dict's last byte. */ int openBraces = 0; /* Brace nesting level during parse. */ int inQuotes = 0; int size = 0; /* lint. */ int numChars; int literal = 1; const char *p2; /* * Skim off leading white space and check for an opening brace or quote. * We treat embedded NULLs in the list/dict as bytes belonging to a list * element (or dictionary key or value). */ limit = (string + stringLength); while ((p < limit) && (TclIsSpaceProc(*p))) { p++; } if (p == limit) { /* no element found */ elemStart = limit; goto done; } if (*p == '{') { openBraces = 1; p++; } else if (*p == '"') { inQuotes = 1; p++; } elemStart = p; /* * Find element's end (a space, close brace, or the end of the string). */ while (p < limit) { switch (*p) { /* * Open brace: don't treat specially unless the element is in * braces. In this case, keep a nesting count. */ case '{': if (openBraces != 0) { openBraces++; } break; /* * Close brace: if element is in braces, keep nesting count and * quit when the last close brace is seen. */ case '}': if (openBraces > 1) { openBraces--; } else if (openBraces == 1) { size = (p - elemStart); p++; if ((p >= limit) || TclIsSpaceProc(*p)) { goto done; } /* * Garbage after the closing brace; return an error. */ if (interp != NULL) { p2 = p; while ((p2 < limit) && (!TclIsSpaceProc(*p2)) && (p2 < p+20)) { p2++; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s element in braces followed by \"%.*s\" " "instead of space", typeStr, (int) (p2-p), p)); Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "JUNK", NULL); } return TCL_ERROR; } break; /* * Backslash: skip over everything up to the end of the backslash * sequence. */ case '\\': if (openBraces == 0) { /* * A backslash sequence not within a brace quoted element * means the value of the element is different from the * substring we are parsing. A call to TclCopyAndCollapse() is * needed to produce the element value. Inform the caller. */ literal = 0; } TclParseBackslash(p, limit - p, &numChars, NULL); p += (numChars - 1); break; /* * Space: ignore if element is in braces or quotes; otherwise * terminate element. */ case ' ': case '\f': case '\n': case '\r': case '\t': case '\v': if ((openBraces == 0) && !inQuotes) { size = (p - elemStart); goto done; } break; /* * Double-quote: if element is in quotes then terminate it. */ case '"': if (inQuotes) { size = (p - elemStart); p++; if ((p >= limit) || TclIsSpaceProc(*p)) { goto done; } /* * Garbage after the closing quote; return an error. */ if (interp != NULL) { p2 = p; while ((p2 < limit) && (!TclIsSpaceProc(*p2)) && (p2 < p+20)) { p2++; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s element in quotes followed by \"%.*s\" " "instead of space", typeStr, (int) (p2-p), p)); Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "JUNK", NULL); } return TCL_ERROR; } break; } p++; } /* * End of list/dict: terminate element. */ if (p == limit) { if (openBraces != 0) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unmatched open brace in %s", typeStr)); Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "BRACE", NULL); } return TCL_ERROR; } else if (inQuotes) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unmatched open quote in %s", typeStr)); Tcl_SetErrorCode(interp, "TCL", "VALUE", typeCode, "QUOTE", NULL); } return TCL_ERROR; } size = (p - elemStart); } done: while ((p < limit) && (TclIsSpaceProc(*p))) { p++; } *elementPtr = elemStart; *nextPtr = p; if (sizePtr != 0) { *sizePtr = size; } if (literalPtr != 0) { *literalPtr = literal; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCopyAndCollapse -- * * Copy a string and substitute all backslash escape sequences * * Results: * Count bytes get copied from src to dst. Along the way, backslash * sequences are substituted in the copy. After scanning count bytes from * src, a null character is placed at the end of dst. Returns the number * of bytes that got written to dst. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclCopyAndCollapse( int count, /* Number of byte to copy from src. */ const char *src, /* Copy from here... */ char *dst) /* ... to here. */ { int newCount = 0; while (count > 0) { char c = *src; if (c == '\\') { int numRead; int backslashCount = TclParseBackslash(src, count, &numRead, dst); dst += backslashCount; newCount += backslashCount; src += numRead; count -= numRead; } else { *dst = c; dst++; newCount++; src++; count--; } } *dst = 0; return newCount; } /* *---------------------------------------------------------------------- * * Tcl_SplitList -- * * Splits a list up into its constituent fields. * * Results * The return value is normally TCL_OK, which means that the list was * successfully split up. If TCL_ERROR is returned, it means that "list" * didn't have proper list structure; the interp's result will contain a * more detailed error message. * * *argvPtr will be filled in with the address of an array whose elements * point to the elements of list, in order. *argcPtr will get filled in * with the number of valid elements in the array. A single block of * memory is dynamically allocated to hold both the argv array and a copy * of the list (with backslashes and braces removed in the standard way). * The caller must eventually free this memory by calling free() on * *argvPtr. Note: *argvPtr and *argcPtr are only modified if the * function returns normally. * * Side effects: * Memory is allocated. * *---------------------------------------------------------------------- */ int Tcl_SplitList( Tcl_Interp *interp, /* Interpreter to use for error reporting. If * NULL, no error message is left. */ const char *list, /* Pointer to string with list structure. */ int *argcPtr, /* Pointer to location to fill in with the * number of elements in the list. */ const char ***argvPtr) /* Pointer to place to store pointer to array * of pointers to list elements. */ { const char **argv, *end, *element; char *p; int length, size, i, result, elSize; /* * Allocate enough space to work in. A (const char *) for each (possible) * list element plus one more for terminating NULL, plus as many bytes as * in the original string value, plus one more for a terminating '\0'. * Space used to hold element separating white space in the original * string gets re-purposed to hold '\0' characters in the argv array. */ size = TclMaxListLength(list, -1, &end) + 1; length = end - list; argv = ckalloc((size * sizeof(char *)) + length + 1); for (i = 0, p = ((char *) argv) + size*sizeof(char *); *list != 0; i++) { const char *prevList = list; int literal; result = TclFindElement(interp, list, length, &element, &list, &elSize, &literal); length -= (list - prevList); if (result != TCL_OK) { ckfree(argv); return result; } if (*element == 0) { break; } if (i >= size) { ckfree(argv); if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "internal error in Tcl_SplitList", -1)); Tcl_SetErrorCode(interp, "TCL", "INTERNAL", "Tcl_SplitList", NULL); } return TCL_ERROR; } argv[i] = p; if (literal) { memcpy(p, element, (size_t) elSize); p += elSize; *p = 0; p++; } else { p += 1 + TclCopyAndCollapse(elSize, element, p); } } argv[i] = NULL; *argvPtr = argv; *argcPtr = i; return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ScanElement -- * * This function is a companion function to Tcl_ConvertElement. It scans * a string to see what needs to be done to it (e.g. add backslashes or * enclosing braces) to make the string into a valid Tcl list element. * * Results: * The return value is an overestimate of the number of bytes that will * be needed by Tcl_ConvertElement to produce a valid list element from * src. The word at *flagPtr is filled in with a value needed by * Tcl_ConvertElement when doing the actual conversion. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_ScanElement( register const char *src, /* String to convert to list element. */ register int *flagPtr) /* Where to store information to guide * Tcl_ConvertCountedElement. */ { return Tcl_ScanCountedElement(src, -1, flagPtr); } /* *---------------------------------------------------------------------- * * Tcl_ScanCountedElement -- * * This function is a companion function to Tcl_ConvertCountedElement. It * scans a string to see what needs to be done to it (e.g. add * backslashes or enclosing braces) to make the string into a valid Tcl * list element. If length is -1, then the string is scanned from src up * to the first null byte. * * Results: * The return value is an overestimate of the number of bytes that will * be needed by Tcl_ConvertCountedElement to produce a valid list element * from src. The word at *flagPtr is filled in with a value needed by * Tcl_ConvertCountedElement when doing the actual conversion. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_ScanCountedElement( const char *src, /* String to convert to Tcl list element. */ int length, /* Number of bytes in src, or -1. */ int *flagPtr) /* Where to store information to guide * Tcl_ConvertElement. */ { int flags = CONVERT_ANY; int numBytes = TclScanElement(src, length, &flags); *flagPtr = flags; return numBytes; } /* *---------------------------------------------------------------------- * * TclScanElement -- * * This function is a companion function to TclConvertElement. It scans a * string to see what needs to be done to it (e.g. add backslashes or * enclosing braces) to make the string into a valid Tcl list element. If * length is -1, then the string is scanned from src up to the first null * byte. A NULL value for src is treated as an empty string. The incoming * value of *flagPtr is a report from the caller what additional flags it * will pass to TclConvertElement(). * * Results: * The recommended formatting mode for the element is determined and a * value is written to *flagPtr indicating that recommendation. This * recommendation is combined with the incoming flag values in *flagPtr * set by the caller to determine how many bytes will be needed by * TclConvertElement() in which to write the formatted element following * the recommendation modified by the flag values. This number of bytes * is the return value of the routine. In some situations it may be an * overestimate, but so long as the caller passes the same flags to * TclConvertElement(), it will be large enough. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclScanElement( const char *src, /* String to convert to Tcl list element. */ int length, /* Number of bytes in src, or -1. */ int *flagPtr) /* Where to store information to guide * Tcl_ConvertElement. */ { const char *p = src; int nestingLevel = 0; /* Brace nesting count */ int forbidNone = 0; /* Do not permit CONVERT_NONE mode. Something * needs protection or escape. */ int requireEscape = 0; /* Force use of CONVERT_ESCAPE mode. For some * reason bare or brace-quoted form fails. */ int extra = 0; /* Count of number of extra bytes needed for * formatted element, assuming we use escape * sequences in formatting. */ int bytesNeeded; /* Buffer length computed to complete the * element formatting in the selected mode. */ #if COMPAT int preferEscape = 0; /* Use preferences to track whether to use */ int preferBrace = 0; /* CONVERT_MASK mode. */ int braceCount = 0; /* Count of all braces '{' '}' seen. */ #endif /* COMPAT */ if ((p == NULL) || (length == 0) || ((*p == '\0') && (length == -1))) { /* * Empty string element must be brace quoted. */ *flagPtr = CONVERT_BRACE; return 2; } if ((*p == '{') || (*p == '"')) { /* * Must escape or protect so leading character of value is not * misinterpreted as list element delimiting syntax. */ forbidNone = 1; #if COMPAT preferBrace = 1; #endif /* COMPAT */ } while (length) { if (CHAR_TYPE(*p) != TYPE_NORMAL) { switch (*p) { case '{': /* TYPE_BRACE */ #if COMPAT braceCount++; #endif /* COMPAT */ extra++; /* Escape '{' => '\{' */ nestingLevel++; break; case '}': /* TYPE_BRACE */ #if COMPAT braceCount++; #endif /* COMPAT */ extra++; /* Escape '}' => '\}' */ nestingLevel--; if (nestingLevel < 0) { /* * Unbalanced braces! Cannot format with brace quoting. */ requireEscape = 1; } break; case ']': /* TYPE_CLOSE_BRACK */ case '"': /* TYPE_SPACE */ #if COMPAT forbidNone = 1; extra++; /* Escapes all just prepend a backslash */ preferEscape = 1; break; #else /* FLOW THROUGH */ #endif /* COMPAT */ case '[': /* TYPE_SUBS */ case '$': /* TYPE_SUBS */ case ';': /* TYPE_COMMAND_END */ case ' ': /* TYPE_SPACE */ case '\f': /* TYPE_SPACE */ case '\n': /* TYPE_COMMAND_END */ case '\r': /* TYPE_SPACE */ case '\t': /* TYPE_SPACE */ case '\v': /* TYPE_SPACE */ forbidNone = 1; extra++; /* Escape sequences all one byte longer. */ #if COMPAT preferBrace = 1; #endif /* COMPAT */ break; case '\\': /* TYPE_SUBS */ extra++; /* Escape '\' => '\\' */ if ((length == 1) || ((length == -1) && (p[1] == '\0'))) { /* * Final backslash. Cannot format with brace quoting. */ requireEscape = 1; break; } if (p[1] == '\n') { extra++; /* Escape newline => '\n', one byte longer */ /* * Backslash newline sequence. Brace quoting not permitted. */ requireEscape = 1; length -= (length > 0); p++; break; } if ((p[1] == '{') || (p[1] == '}') || (p[1] == '\\')) { extra++; /* Escape sequences all one byte longer. */ length -= (length > 0); p++; } forbidNone = 1; #if COMPAT preferBrace = 1; #endif /* COMPAT */ break; case '\0': /* TYPE_SUBS */ if (length == -1) { goto endOfString; } /* TODO: Panic on improper encoding? */ break; } } length -= (length > 0); p++; } endOfString: if (nestingLevel != 0) { /* * Unbalanced braces! Cannot format with brace quoting. */ requireEscape = 1; } /* * We need at least as many bytes as are in the element value... */ bytesNeeded = p - src; if (requireEscape) { /* * We must use escape sequences. Add all the extra bytes needed to * have room to create them. */ bytesNeeded += extra; /* * Make room to escape leading #, if needed. */ if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) { bytesNeeded++; } *flagPtr = CONVERT_ESCAPE; goto overflowCheck; } if (*flagPtr & CONVERT_ANY) { /* * The caller has not let us know what flags it will pass to * TclConvertElement() so compute the max size we might need for any * possible choice. Normally the formatting using escape sequences is * the longer one, and a minimum "extra" value of 2 makes sure we * don't request too small a buffer in those edge cases where that's * not true. */ if (extra < 2) { extra = 2; } *flagPtr &= ~CONVERT_ANY; *flagPtr |= TCL_DONT_USE_BRACES; } if (forbidNone) { /* * We must request some form of quoting of escaping... */ #if COMPAT if (preferEscape && !preferBrace) { /* * If we are quoting solely due to ] or internal " characters use * the CONVERT_MASK mode where we escape all special characters * except for braces. "extra" counted space needed to escape * braces too, so substract "braceCount" to get our actual needs. */ bytesNeeded += (extra - braceCount); /* Make room to escape leading #, if needed. */ if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) { bytesNeeded++; } /* * If the caller reports it will direct TclConvertElement() to * use full escapes on the element, add back the bytes needed to * escape the braces. */ if (*flagPtr & TCL_DONT_USE_BRACES) { bytesNeeded += braceCount; } *flagPtr = CONVERT_MASK; goto overflowCheck; } #endif /* COMPAT */ if (*flagPtr & TCL_DONT_USE_BRACES) { /* * If the caller reports it will direct TclConvertElement() to * use escapes, add the extra bytes needed to have room for them. */ bytesNeeded += extra; /* * Make room to escape leading #, if needed. */ if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) { bytesNeeded++; } } else { /* * Add 2 bytes for room for the enclosing braces. */ bytesNeeded += 2; } *flagPtr = CONVERT_BRACE; goto overflowCheck; } /* * So far, no need to quote or escape anything. */ if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) { /* * If we need to quote a leading #, make room to enclose in braces. */ bytesNeeded += 2; } *flagPtr = CONVERT_NONE; overflowCheck: if (bytesNeeded < 0) { Tcl_Panic("TclScanElement: string length overflow"); } return bytesNeeded; } /* *---------------------------------------------------------------------- * * Tcl_ConvertElement -- * * This is a companion function to Tcl_ScanElement. Given the information * produced by Tcl_ScanElement, this function converts a string to a list * element equal to that string. * * Results: * Information is copied to *dst in the form of a list element identical * to src (i.e. if Tcl_SplitList is applied to dst it will produce a * string identical to src). The return value is a count of the number of * characters copied (not including the terminating NULL character). * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_ConvertElement( register const char *src, /* Source information for list element. */ register char *dst, /* Place to put list-ified element. */ register int flags) /* Flags produced by Tcl_ScanElement. */ { return Tcl_ConvertCountedElement(src, -1, dst, flags); } /* *---------------------------------------------------------------------- * * Tcl_ConvertCountedElement -- * * This is a companion function to Tcl_ScanCountedElement. Given the * information produced by Tcl_ScanCountedElement, this function converts * a string to a list element equal to that string. * * Results: * Information is copied to *dst in the form of a list element identical * to src (i.e. if Tcl_SplitList is applied to dst it will produce a * string identical to src). The return value is a count of the number of * characters copied (not including the terminating NULL character). * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_ConvertCountedElement( register const char *src, /* Source information for list element. */ int length, /* Number of bytes in src, or -1. */ char *dst, /* Place to put list-ified element. */ int flags) /* Flags produced by Tcl_ScanElement. */ { int numBytes = TclConvertElement(src, length, dst, flags); dst[numBytes] = '\0'; return numBytes; } /* *---------------------------------------------------------------------- * * TclConvertElement -- * * This is a companion function to TclScanElement. Given the information * produced by TclScanElement, this function converts a string to a list * element equal to that string. * * Results: * Information is copied to *dst in the form of a list element identical * to src (i.e. if Tcl_SplitList is applied to dst it will produce a * string identical to src). The return value is a count of the number of * characters copied (not including the terminating NULL character). * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclConvertElement( register const char *src, /* Source information for list element. */ int length, /* Number of bytes in src, or -1. */ char *dst, /* Place to put list-ified element. */ int flags) /* Flags produced by Tcl_ScanElement. */ { int conversion = flags & CONVERT_MASK; char *p = dst; /* * Let the caller demand we use escape sequences rather than braces. */ if ((flags & TCL_DONT_USE_BRACES) && (conversion & CONVERT_BRACE)) { conversion = CONVERT_ESCAPE; } /* * No matter what the caller demands, empty string must be braced! */ if ((src == NULL) || (length == 0) || (*src == '\0' && length == -1)) { src = tclEmptyStringRep; length = 0; conversion = CONVERT_BRACE; } /* * Escape leading hash as needed and requested. */ if ((*src == '#') && !(flags & TCL_DONT_QUOTE_HASH)) { if (conversion == CONVERT_ESCAPE) { p[0] = '\\'; p[1] = '#'; p += 2; src++; length -= (length > 0); } else { conversion = CONVERT_BRACE; } } /* * No escape or quoting needed. Copy the literal string value. */ if (conversion == CONVERT_NONE) { if (length == -1) { /* TODO: INT_MAX overflow? */ while (*src) { *p++ = *src++; } return p - dst; } else { memcpy(dst, src, length); return length; } } /* * Formatted string is original string enclosed in braces. */ if (conversion == CONVERT_BRACE) { *p = '{'; p++; if (length == -1) { /* TODO: INT_MAX overflow? */ while (*src) { *p++ = *src++; } } else { memcpy(p, src, length); p += length; } *p = '}'; p++; return p - dst; } /* conversion == CONVERT_ESCAPE or CONVERT_MASK */ /* * Formatted string is original string converted to escape sequences. */ for ( ; length; src++, length -= (length > 0)) { switch (*src) { case ']': case '[': case '$': case ';': case ' ': case '\\': case '"': *p = '\\'; p++; break; case '{': case '}': #if COMPAT if (conversion == CONVERT_ESCAPE) #endif /* COMPAT */ { *p = '\\'; p++; } break; case '\f': *p = '\\'; p++; *p = 'f'; p++; continue; case '\n': *p = '\\'; p++; *p = 'n'; p++; continue; case '\r': *p = '\\'; p++; *p = 'r'; p++; continue; case '\t': *p = '\\'; p++; *p = 't'; p++; continue; case '\v': *p = '\\'; p++; *p = 'v'; p++; continue; case '\0': if (length == -1) { return p - dst; } /* * If we reach this point, there's an embedded NULL in the string * range being processed, which should not happen when the * encoding rules for Tcl strings are properly followed. If the * day ever comes when we stop tolerating such things, this is * where to put the Tcl_Panic(). */ break; } *p = *src; p++; } return p - dst; } /* *---------------------------------------------------------------------- * * Tcl_Merge -- * * Given a collection of strings, merge them together into a single * string that has proper Tcl list structured (i.e. Tcl_SplitList may be * used to retrieve strings equal to the original elements, and Tcl_Eval * will parse the string back into its original elements). * * Results: * The return value is the address of a dynamically-allocated string * containing the merged list. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * Tcl_Merge( int argc, /* How many strings to merge. */ const char *const *argv) /* Array of string values. */ { #define LOCAL_SIZE 20 int localFlags[LOCAL_SIZE], *flagPtr = NULL; int i, bytesNeeded = 0; char *result, *dst; const int maxFlags = UINT_MAX / sizeof(int); /* * Handle empty list case first, so logic of the general case can be * simpler. */ if (argc == 0) { result = ckalloc(1); result[0] = '\0'; return result; } /* * Pass 1: estimate space, gather flags. */ if (argc <= LOCAL_SIZE) { flagPtr = localFlags; } else if (argc > maxFlags) { /* * We cannot allocate a large enough flag array to format this list in * one pass. We could imagine converting this routine to a multi-pass * implementation, but for sizeof(int) == 4, the limit is a max of * 2^30 list elements and since each element is at least one byte * formatted, and requires one byte space between it and the next one, * that a minimum space requirement of 2^31 bytes, which is already * INT_MAX. If we tried to format a list of > maxFlags elements, we're * just going to overflow the size limits on the formatted string * anyway, so just issue that same panic early. */ Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } else { flagPtr = ckalloc(argc * sizeof(int)); } for (i = 0; i < argc; i++) { flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 ); bytesNeeded += TclScanElement(argv[i], -1, &flagPtr[i]); if (bytesNeeded < 0) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } } if (bytesNeeded > INT_MAX - argc + 1) { Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX); } bytesNeeded += argc; /* * Pass two: copy into the result area. */ result = ckalloc(bytesNeeded); dst = result; for (i = 0; i < argc; i++) { flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 ); dst += TclConvertElement(argv[i], -1, dst, flagPtr[i]); *dst = ' '; dst++; } dst[-1] = 0; if (flagPtr != localFlags) { ckfree(flagPtr); } return result; } /* *---------------------------------------------------------------------- * * Tcl_Backslash -- * * Figure out how to handle a backslash sequence. * * Results: * The return value is the character that should be substituted in place * of the backslash sequence that starts at src. If readPtr isn't NULL * then it is filled in with a count of the number of characters in the * backslash sequence. * * Side effects: * None. * *---------------------------------------------------------------------- */ char Tcl_Backslash( const char *src, /* Points to the backslash character of a * backslash sequence. */ int *readPtr) /* Fill in with number of characters read from * src, unless NULL. */ { char buf[TCL_UTF_MAX]; Tcl_UniChar ch; Tcl_UtfBackslash(src, readPtr, buf); TclUtfToUniChar(buf, &ch); return (char) ch; } /* *---------------------------------------------------------------------- * * TclTrimRight -- * * Takes two counted strings in the Tcl encoding which must both be null * terminated. Conceptually trims from the right side of the first string * all characters found in the second string. * * Results: * The number of bytes to be removed from the end of the string. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclTrimRight( const char *bytes, /* String to be trimmed... */ int numBytes, /* ...and its length in bytes */ const char *trim, /* String of trim characters... */ int numTrim) /* ...and its length in bytes */ { const char *p = bytes + numBytes; int pInc; if ((bytes[numBytes] != '\0') || (trim[numTrim] != '\0')) { Tcl_Panic("TclTrimRight works only on null-terminated strings"); } /* * Empty strings -> nothing to do. */ if ((numBytes == 0) || (numTrim == 0)) { return 0; } /* * Outer loop: iterate over string to be trimmed. */ do { Tcl_UniChar ch1; const char *q = trim; int bytesLeft = numTrim; p = Tcl_UtfPrev(p, bytes); pInc = TclUtfToUniChar(p, &ch1); /* * Inner loop: scan trim string for match to current character. */ do { Tcl_UniChar ch2; int qInc = TclUtfToUniChar(q, &ch2); if (ch1 == ch2) { break; } q += qInc; bytesLeft -= qInc; } while (bytesLeft); if (bytesLeft == 0) { /* * No match; trim task done; *p is last non-trimmed char. */ p += pInc; break; } } while (p > bytes); return numBytes - (p - bytes); } /* *---------------------------------------------------------------------- * * TclTrimLeft -- * * Takes two counted strings in the Tcl encoding which must both be null * terminated. Conceptually trims from the left side of the first string * all characters found in the second string. * * Results: * The number of bytes to be removed from the start of the string. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclTrimLeft( const char *bytes, /* String to be trimmed... */ int numBytes, /* ...and its length in bytes */ const char *trim, /* String of trim characters... */ int numTrim) /* ...and its length in bytes */ { const char *p = bytes; if ((bytes[numBytes] != '\0') || (trim[numTrim] != '\0')) { Tcl_Panic("TclTrimLeft works only on null-terminated strings"); } /* * Empty strings -> nothing to do. */ if ((numBytes == 0) || (numTrim == 0)) { return 0; } /* * Outer loop: iterate over string to be trimmed. */ do { Tcl_UniChar ch1; int pInc = TclUtfToUniChar(p, &ch1); const char *q = trim; int bytesLeft = numTrim; /* * Inner loop: scan trim string for match to current character. */ do { Tcl_UniChar ch2; int qInc = TclUtfToUniChar(q, &ch2); if (ch1 == ch2) { break; } q += qInc; bytesLeft -= qInc; } while (bytesLeft); if (bytesLeft == 0) { /* * No match; trim task done; *p is first non-trimmed char. */ break; } p += pInc; numBytes -= pInc; } while (numBytes); return p - bytes; } /* *---------------------------------------------------------------------- * * Tcl_Concat -- * * Concatenate a set of strings into a single large string. * * Results: * The return value is dynamically-allocated string containing a * concatenation of all the strings in argv, with spaces between the * original argv elements. * * Side effects: * Memory is allocated for the result; the caller is responsible for * freeing the memory. * *---------------------------------------------------------------------- */ /* The whitespace characters trimmed during [concat] operations */ #define CONCAT_WS_SIZE (int) (sizeof(CONCAT_TRIM_SET "") - 1) char * Tcl_Concat( int argc, /* Number of strings to concatenate. */ const char *const *argv) /* Array of strings to concatenate. */ { int i, needSpace = 0, bytesNeeded = 0; char *result, *p; /* * Dispose of the empty result corner case first to simplify later code. */ if (argc == 0) { result = (char *) ckalloc(1); result[0] = '\0'; return result; } /* * First allocate the result buffer at the size required. */ for (i = 0; i < argc; i++) { bytesNeeded += strlen(argv[i]); if (bytesNeeded < 0) { Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded"); } } if (bytesNeeded + argc - 1 < 0) { /* * Panic test could be tighter, but not going to bother for this * legacy routine. */ Tcl_Panic("Tcl_Concat: max size of Tcl value exceeded"); } /* * All element bytes + (argc - 1) spaces + 1 terminating NULL. */ result = ckalloc((unsigned) (bytesNeeded + argc)); for (p = result, i = 0; i < argc; i++) { int trim, elemLength; const char *element; element = argv[i]; elemLength = strlen(argv[i]); /* * Trim away the leading whitespace. */ trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET, CONCAT_WS_SIZE); element += trim; elemLength -= trim; /* * Trim away the trailing whitespace. Do not permit trimming to expose * a final backslash character. */ trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET, CONCAT_WS_SIZE); trim -= trim && (element[elemLength - trim - 1] == '\\'); elemLength -= trim; /* * If we're left with empty element after trimming, do nothing. */ if (elemLength == 0) { continue; } /* * Append to the result with space if needed. */ if (needSpace) { *p++ = ' '; } memcpy(p, element, (size_t) elemLength); p += elemLength; needSpace = 1; } *p = '\0'; return result; } /* *---------------------------------------------------------------------- * * Tcl_ConcatObj -- * * Concatenate the strings from a set of objects into a single string * object with spaces between the original strings. * * Results: * The return value is a new string object containing a concatenation of * the strings in objv. Its ref count is zero. * * Side effects: * A new object is created. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_ConcatObj( int objc, /* Number of objects to concatenate. */ Tcl_Obj *const objv[]) /* Array of objects to concatenate. */ { int i, elemLength, needSpace = 0, bytesNeeded = 0; const char *element; Tcl_Obj *objPtr, *resPtr; /* * Check first to see if all the items are of list type or empty. If so, * we will concat them together as lists, and return a list object. This * is only valid when the lists are in canonical form. */ for (i = 0; i < objc; i++) { int length; objPtr = objv[i]; if (TclListObjIsCanonical(objPtr)) { continue; } Tcl_GetStringFromObj(objPtr, &length); if (length > 0) { break; } } if (i == objc) { resPtr = NULL; for (i = 0; i < objc; i++) { objPtr = objv[i]; if (objPtr->bytes && objPtr->length == 0) { continue; } if (resPtr) { if (TCL_OK != Tcl_ListObjAppendList(NULL, resPtr, objPtr)) { /* Abandon ship! */ Tcl_DecrRefCount(resPtr); goto slow; } } else { resPtr = TclListObjCopy(NULL, objPtr); } } if (!resPtr) { resPtr = Tcl_NewObj(); } return resPtr; } slow: /* * Something cannot be determined to be safe, so build the concatenation * the slow way, using the string representations. * * First try to pre-allocate the size required. */ for (i = 0; i < objc; i++) { element = TclGetStringFromObj(objv[i], &elemLength); bytesNeeded += elemLength; if (bytesNeeded < 0) { break; } } /* * Does not matter if this fails, will simply try later to build up the * string with each Append reallocating as needed with the usual string * append algorithm. When that fails it will report the error. */ TclNewObj(resPtr); (void) Tcl_AttemptSetObjLength(resPtr, bytesNeeded + objc - 1); Tcl_SetObjLength(resPtr, 0); for (i = 0; i < objc; i++) { int trim; element = TclGetStringFromObj(objv[i], &elemLength); /* * Trim away the leading whitespace. */ trim = TclTrimLeft(element, elemLength, CONCAT_TRIM_SET, CONCAT_WS_SIZE); element += trim; elemLength -= trim; /* * Trim away the trailing whitespace. Do not permit trimming to expose * a final backslash character. */ trim = TclTrimRight(element, elemLength, CONCAT_TRIM_SET, CONCAT_WS_SIZE); trim -= trim && (element[elemLength - trim - 1] == '\\'); elemLength -= trim; /* * If we're left with empty element after trimming, do nothing. */ if (elemLength == 0) { continue; } /* * Append to the result with space if needed. */ if (needSpace) { Tcl_AppendToObj(resPtr, " ", 1); } Tcl_AppendToObj(resPtr, element, elemLength); needSpace = 1; } return resPtr; } /* *---------------------------------------------------------------------- * * Tcl_StringMatch -- * * See if a particular string matches a particular pattern. * * Results: * The return value is 1 if string matches pattern, and 0 otherwise. The * matching operation permits the following special characters in the * pattern: *?\[] (see the manual entry for details on what these mean). * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_StringMatch( const char *str, /* String. */ const char *pattern) /* Pattern, which may contain special * characters. */ { return Tcl_StringCaseMatch(str, pattern, 0); } /* *---------------------------------------------------------------------- * * Tcl_StringCaseMatch -- * * See if a particular string matches a particular pattern. Allows case * insensitivity. * * Results: * The return value is 1 if string matches pattern, and 0 otherwise. The * matching operation permits the following special characters in the * pattern: *?\[] (see the manual entry for details on what these mean). * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_StringCaseMatch( const char *str, /* String. */ const char *pattern, /* Pattern, which may contain special * characters. */ int nocase) /* 0 for case sensitive, 1 for insensitive */ { int p, charLen; const char *pstart = pattern; Tcl_UniChar ch1, ch2; while (1) { p = *pattern; /* * See if we're at the end of both the pattern and the string. If so, * we succeeded. If we're at the end of the pattern but not at the end * of the string, we failed. */ if (p == '\0') { return (*str == '\0'); } if ((*str == '\0') && (p != '*')) { return 0; } /* * Check for a "*" as the next pattern character. It matches any * substring. We handle this by calling ourselves recursively for each * postfix of string, until either we match or we reach the end of the * string. */ if (p == '*') { /* * Skip all successive *'s in the pattern */ while (*(++pattern) == '*') {} p = *pattern; if (p == '\0') { return 1; } /* * This is a special case optimization for single-byte utf. */ if (UCHAR(*pattern) < 0x80) { ch2 = (Tcl_UniChar) (nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern)); } else { Tcl_UtfToUniChar(pattern, &ch2); if (nocase) { ch2 = Tcl_UniCharToLower(ch2); } } while (1) { /* * Optimization for matching - cruise through the string * quickly if the next char in the pattern isn't a special * character */ if ((p != '[') && (p != '?') && (p != '\\')) { if (nocase) { while (*str) { charLen = TclUtfToUniChar(str, &ch1); if (ch2==ch1 || ch2==Tcl_UniCharToLower(ch1)) { break; } str += charLen; } } else { /* * There's no point in trying to make this code * shorter, as the number of bytes you want to compare * each time is non-constant. */ while (*str) { charLen = TclUtfToUniChar(str, &ch1); if (ch2 == ch1) { break; } str += charLen; } } } if (Tcl_StringCaseMatch(str, pattern, nocase)) { return 1; } if (*str == '\0') { return 0; } str += TclUtfToUniChar(str, &ch1); } } /* * Check for a "?" as the next pattern character. It matches any * single character. */ if (p == '?') { pattern++; str += TclUtfToUniChar(str, &ch1); continue; } /* * Check for a "[" as the next pattern character. It is followed by a * list of characters that are acceptable, or by a range (two * characters separated by "-"). */ if (p == '[') { Tcl_UniChar startChar, endChar; pattern++; if (UCHAR(*str) < 0x80) { ch1 = (Tcl_UniChar) (nocase ? tolower(UCHAR(*str)) : UCHAR(*str)); str++; } else { str += Tcl_UtfToUniChar(str, &ch1); if (nocase) { ch1 = Tcl_UniCharToLower(ch1); } } while (1) { if ((*pattern == ']') || (*pattern == '\0')) { return 0; } if (UCHAR(*pattern) < 0x80) { startChar = (Tcl_UniChar) (nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern)); pattern++; } else { pattern += Tcl_UtfToUniChar(pattern, &startChar); if (nocase) { startChar = Tcl_UniCharToLower(startChar); } } if (*pattern == '-') { pattern++; if (*pattern == '\0') { return 0; } if (UCHAR(*pattern) < 0x80) { endChar = (Tcl_UniChar) (nocase ? tolower(UCHAR(*pattern)) : UCHAR(*pattern)); pattern++; } else { pattern += Tcl_UtfToUniChar(pattern, &endChar); if (nocase) { endChar = Tcl_UniCharToLower(endChar); } } if (((startChar <= ch1) && (ch1 <= endChar)) || ((endChar <= ch1) && (ch1 <= startChar))) { /* * Matches ranges of form [a-z] or [z-a]. */ break; } } else if (startChar == ch1) { break; } } while (*pattern != ']') { if (*pattern == '\0') { pattern = Tcl_UtfPrev(pattern, pstart); break; } pattern++; } pattern++; continue; } /* * If the next pattern character is '\', just strip off the '\' so we * do exact matching on the character that follows. */ if (p == '\\') { pattern++; if (*pattern == '\0') { return 0; } } /* * There's no special character. Just make sure that the next bytes of * each string match. */ str += TclUtfToUniChar(str, &ch1); pattern += TclUtfToUniChar(pattern, &ch2); if (nocase) { if (Tcl_UniCharToLower(ch1) != Tcl_UniCharToLower(ch2)) { return 0; } } else if (ch1 != ch2) { return 0; } } } /* *---------------------------------------------------------------------- * * TclByteArrayMatch -- * * See if a particular string matches a particular pattern. Does not * allow for case insensitivity. * Parallels tclUtf.c:TclUniCharMatch, adjusted for char* and sans nocase. * * Results: * The return value is 1 if string matches pattern, and 0 otherwise. The * matching operation permits the following special characters in the * pattern: *?\[] (see the manual entry for details on what these mean). * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclByteArrayMatch( const unsigned char *string,/* String. */ int strLen, /* Length of String */ const unsigned char *pattern, /* Pattern, which may contain special * characters. */ int ptnLen, /* Length of Pattern */ int flags) { const unsigned char *stringEnd, *patternEnd; unsigned char p; stringEnd = string + strLen; patternEnd = pattern + ptnLen; while (1) { /* * See if we're at the end of both the pattern and the string. If so, * we succeeded. If we're at the end of the pattern but not at the end * of the string, we failed. */ if (pattern == patternEnd) { return (string == stringEnd); } p = *pattern; if ((string == stringEnd) && (p != '*')) { return 0; } /* * Check for a "*" as the next pattern character. It matches any * substring. We handle this by skipping all the characters up to the * next matching one in the pattern, and then calling ourselves * recursively for each postfix of string, until either we match or we * reach the end of the string. */ if (p == '*') { /* * Skip all successive *'s in the pattern. */ while ((++pattern < patternEnd) && (*pattern == '*')) { /* empty body */ } if (pattern == patternEnd) { return 1; } p = *pattern; while (1) { /* * Optimization for matching - cruise through the string * quickly if the next char in the pattern isn't a special * character. */ if ((p != '[') && (p != '?') && (p != '\\')) { while ((string < stringEnd) && (p != *string)) { string++; } } if (TclByteArrayMatch(string, stringEnd - string, pattern, patternEnd - pattern, 0)) { return 1; } if (string == stringEnd) { return 0; } string++; } } /* * Check for a "?" as the next pattern character. It matches any * single character. */ if (p == '?') { pattern++; string++; continue; } /* * Check for a "[" as the next pattern character. It is followed by a * list of characters that are acceptable, or by a range (two * characters separated by "-"). */ if (p == '[') { unsigned char ch1, startChar, endChar; pattern++; ch1 = *string; string++; while (1) { if ((*pattern == ']') || (pattern == patternEnd)) { return 0; } startChar = *pattern; pattern++; if (*pattern == '-') { pattern++; if (pattern == patternEnd) { return 0; } endChar = *pattern; pattern++; if (((startChar <= ch1) && (ch1 <= endChar)) || ((endChar <= ch1) && (ch1 <= startChar))) { /* * Matches ranges of form [a-z] or [z-a]. */ break; } } else if (startChar == ch1) { break; } } while (*pattern != ']') { if (pattern == patternEnd) { pattern--; break; } pattern++; } pattern++; continue; } /* * If the next pattern character is '\', just strip off the '\' so we * do exact matching on the character that follows. */ if (p == '\\') { if (++pattern == patternEnd) { return 0; } } /* * There's no special character. Just make sure that the next bytes of * each string match. */ if (*string != *pattern) { return 0; } string++; pattern++; } } /* *---------------------------------------------------------------------- * * TclStringMatchObj -- * * See if a particular string matches a particular pattern. Allows case * insensitivity. This is the generic multi-type handler for the various * matching algorithms. * * Results: * The return value is 1 if string matches pattern, and 0 otherwise. The * matching operation permits the following special characters in the * pattern: *?\[] (see the manual entry for details on what these mean). * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclStringMatchObj( Tcl_Obj *strObj, /* string object. */ Tcl_Obj *ptnObj, /* pattern object. */ int flags) /* Only TCL_MATCH_NOCASE should be passed, or * 0. */ { int match, length, plen; /* * Promote based on the type of incoming object. * XXX: Currently doesn't take advantage of exact-ness that * XXX: TclReToGlob tells us about trivial = nocase ? 0 : TclMatchIsTrivial(TclGetString(ptnObj)); */ if ((strObj->typePtr == &tclStringType) || (strObj->typePtr == NULL)) { Tcl_UniChar *udata, *uptn; udata = Tcl_GetUnicodeFromObj(strObj, &length); uptn = Tcl_GetUnicodeFromObj(ptnObj, &plen); match = TclUniCharMatch(udata, length, uptn, plen, flags); } else if (TclIsPureByteArray(strObj) && !flags) { unsigned char *data, *ptn; data = Tcl_GetByteArrayFromObj(strObj, &length); ptn = Tcl_GetByteArrayFromObj(ptnObj, &plen); match = TclByteArrayMatch(data, length, ptn, plen, 0); } else { match = Tcl_StringCaseMatch(TclGetString(strObj), TclGetString(ptnObj), flags); } return match; } /* *---------------------------------------------------------------------- * * Tcl_DStringInit -- * * Initializes a dynamic string, discarding any previous contents of the * string (Tcl_DStringFree should have been called already if the dynamic * string was previously in use). * * Results: * None. * * Side effects: * The dynamic string is initialized to be empty. * *---------------------------------------------------------------------- */ void Tcl_DStringInit( Tcl_DString *dsPtr) /* Pointer to structure for dynamic string. */ { dsPtr->string = dsPtr->staticSpace; dsPtr->length = 0; dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; dsPtr->staticSpace[0] = '\0'; } /* *---------------------------------------------------------------------- * * Tcl_DStringAppend -- * * Append more bytes to the current value of a dynamic string. * * Results: * The return value is a pointer to the dynamic string's new value. * * Side effects: * Length bytes from "bytes" (or all of "bytes" if length is less than * zero) are added to the current value of the string. Memory gets * reallocated if needed to accomodate the string's new size. * *---------------------------------------------------------------------- */ char * Tcl_DStringAppend( Tcl_DString *dsPtr, /* Structure describing dynamic string. */ const char *bytes, /* String to append. If length is -1 then this * must be null-terminated. */ int length) /* Number of bytes from "bytes" to append. If * < 0, then append all of bytes, up to null * at end. */ { int newSize; if (length < 0) { length = strlen(bytes); } newSize = length + dsPtr->length; /* * Allocate a larger buffer for the string if the current one isn't large * enough. Allocate extra space in the new buffer so that there will be * room to grow before we have to allocate again. */ if (newSize >= dsPtr->spaceAvl) { dsPtr->spaceAvl = newSize * 2; if (dsPtr->string == dsPtr->staticSpace) { char *newString = ckalloc(dsPtr->spaceAvl); memcpy(newString, dsPtr->string, (size_t) dsPtr->length); dsPtr->string = newString; } else { dsPtr->string = ckrealloc(dsPtr->string, dsPtr->spaceAvl); } } /* * Copy the new string into the buffer at the end of the old one. */ memcpy(dsPtr->string + dsPtr->length, bytes, length); dsPtr->length += length; dsPtr->string[dsPtr->length] = '\0'; return dsPtr->string; } /* *---------------------------------------------------------------------- * * TclDStringAppendObj, TclDStringAppendDString -- * * Simple wrappers round Tcl_DStringAppend that make it easier to append * from particular sources of strings. * *---------------------------------------------------------------------- */ char * TclDStringAppendObj( Tcl_DString *dsPtr, Tcl_Obj *objPtr) { int length; char *bytes = Tcl_GetStringFromObj(objPtr, &length); return Tcl_DStringAppend(dsPtr, bytes, length); } char * TclDStringAppendDString( Tcl_DString *dsPtr, Tcl_DString *toAppendPtr) { return Tcl_DStringAppend(dsPtr, Tcl_DStringValue(toAppendPtr), Tcl_DStringLength(toAppendPtr)); } /* *---------------------------------------------------------------------- * * Tcl_DStringAppendElement -- * * Append a list element to the current value of a dynamic string. * * Results: * The return value is a pointer to the dynamic string's new value. * * Side effects: * String is reformatted as a list element and added to the current value * of the string. Memory gets reallocated if needed to accomodate the * string's new size. * *---------------------------------------------------------------------- */ char * Tcl_DStringAppendElement( Tcl_DString *dsPtr, /* Structure describing dynamic string. */ const char *element) /* String to append. Must be * null-terminated. */ { char *dst = dsPtr->string + dsPtr->length; int needSpace = TclNeedSpace(dsPtr->string, dst); int flags = needSpace ? TCL_DONT_QUOTE_HASH : 0; int newSize = dsPtr->length + needSpace + TclScanElement(element, -1, &flags); /* * Allocate a larger buffer for the string if the current one isn't large * enough. Allocate extra space in the new buffer so that there will be * room to grow before we have to allocate again. SPECIAL NOTE: must use * memcpy, not strcpy, to copy the string to a larger buffer, since there * may be embedded NULLs in the string in some cases. */ if (newSize >= dsPtr->spaceAvl) { dsPtr->spaceAvl = newSize * 2; if (dsPtr->string == dsPtr->staticSpace) { char *newString = ckalloc(dsPtr->spaceAvl); memcpy(newString, dsPtr->string, (size_t) dsPtr->length); dsPtr->string = newString; } else { dsPtr->string = ckrealloc(dsPtr->string, dsPtr->spaceAvl); } dst = dsPtr->string + dsPtr->length; } /* * Convert the new string to a list element and copy it into the buffer at * the end, with a space, if needed. */ if (needSpace) { *dst = ' '; dst++; dsPtr->length++; /* * If we need a space to separate this element from preceding stuff, * then this element will not lead a list, and need not have it's * leading '#' quoted. */ flags |= TCL_DONT_QUOTE_HASH; } dsPtr->length += TclConvertElement(element, -1, dst, flags); dsPtr->string[dsPtr->length] = '\0'; return dsPtr->string; } /* *---------------------------------------------------------------------- * * Tcl_DStringSetLength -- * * Change the length of a dynamic string. This can cause the string to * either grow or shrink, depending on the value of length. * * Results: * None. * * Side effects: * The length of dsPtr is changed to length and a null byte is stored at * that position in the string. If length is larger than the space * allocated for dsPtr, then a panic occurs. * *---------------------------------------------------------------------- */ void Tcl_DStringSetLength( Tcl_DString *dsPtr, /* Structure describing dynamic string. */ int length) /* New length for dynamic string. */ { int newsize; if (length < 0) { length = 0; } if (length >= dsPtr->spaceAvl) { /* * There are two interesting cases here. In the first case, the user * may be trying to allocate a large buffer of a specific size. It * would be wasteful to overallocate that buffer, so we just allocate * enough for the requested size plus the trailing null byte. In the * second case, we are growing the buffer incrementally, so we need * behavior similar to Tcl_DStringAppend. The requested length will * usually be a small delta above the current spaceAvl, so we'll end * up doubling the old size. This won't grow the buffer quite as * quickly, but it should be close enough. */ newsize = dsPtr->spaceAvl * 2; if (length < newsize) { dsPtr->spaceAvl = newsize; } else { dsPtr->spaceAvl = length + 1; } if (dsPtr->string == dsPtr->staticSpace) { char *newString = ckalloc(dsPtr->spaceAvl); memcpy(newString, dsPtr->string, (size_t) dsPtr->length); dsPtr->string = newString; } else { dsPtr->string = ckrealloc(dsPtr->string, dsPtr->spaceAvl); } } dsPtr->length = length; dsPtr->string[length] = 0; } /* *---------------------------------------------------------------------- * * Tcl_DStringFree -- * * Frees up any memory allocated for the dynamic string and reinitializes * the string to an empty state. * * Results: * None. * * Side effects: * The previous contents of the dynamic string are lost, and the new * value is an empty string. * *---------------------------------------------------------------------- */ void Tcl_DStringFree( Tcl_DString *dsPtr) /* Structure describing dynamic string. */ { if (dsPtr->string != dsPtr->staticSpace) { ckfree(dsPtr->string); } dsPtr->string = dsPtr->staticSpace; dsPtr->length = 0; dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; dsPtr->staticSpace[0] = '\0'; } /* *---------------------------------------------------------------------- * * Tcl_DStringResult -- * * This function moves the value of a dynamic string into an interpreter * as its string result. Afterwards, the dynamic string is reset to an * empty string. * * Results: * None. * * Side effects: * The string is "moved" to interp's result, and any existing string * result for interp is freed. dsPtr is reinitialized to an empty string. * *---------------------------------------------------------------------- */ void Tcl_DStringResult( Tcl_Interp *interp, /* Interpreter whose result is to be reset. */ Tcl_DString *dsPtr) /* Dynamic string that is to become the * result of interp. */ { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, TclDStringToObj(dsPtr)); } /* *---------------------------------------------------------------------- * * Tcl_DStringGetResult -- * * This function moves an interpreter's result into a dynamic string. * * Results: * None. * * Side effects: * The interpreter's string result is cleared, and the previous contents * of dsPtr are freed. * * If the string result is empty, the object result is moved to the * string result, then the object result is reset. * *---------------------------------------------------------------------- */ void Tcl_DStringGetResult( Tcl_Interp *interp, /* Interpreter whose result is to be reset. */ Tcl_DString *dsPtr) /* Dynamic string that is to become the result * of interp. */ { Interp *iPtr = (Interp *) interp; if (dsPtr->string != dsPtr->staticSpace) { ckfree(dsPtr->string); } /* * Do more efficient transfer when we know the result is a Tcl_Obj. When * there's no st`ring result, we only have to deal with two cases: * * 1. When the string rep is the empty string, when we don't copy but * instead use the staticSpace in the DString to hold an empty string. * 2. When the string rep is not there or there's a real string rep, when * we use Tcl_GetString to fetch (or generate) the string rep - which * we know to have been allocated with ckalloc() - and use it to * populate the DString space. Then, we free the internal rep. and set * the object's string representation back to the canonical empty * string. */ if (!iPtr->result[0] && iPtr->objResultPtr && !Tcl_IsShared(iPtr->objResultPtr)) { if (iPtr->objResultPtr->bytes == tclEmptyStringRep) { dsPtr->string = dsPtr->staticSpace; dsPtr->string[0] = 0; dsPtr->length = 0; dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; } else { dsPtr->string = Tcl_GetString(iPtr->objResultPtr); dsPtr->length = iPtr->objResultPtr->length; dsPtr->spaceAvl = dsPtr->length + 1; TclFreeIntRep(iPtr->objResultPtr); iPtr->objResultPtr->bytes = tclEmptyStringRep; iPtr->objResultPtr->length = 0; } return; } /* * If the string result is empty, move the object result to the string * result, then reset the object result. */ (void) Tcl_GetStringResult(interp); dsPtr->length = strlen(iPtr->result); if (iPtr->freeProc != NULL) { if (iPtr->freeProc == TCL_DYNAMIC) { dsPtr->string = iPtr->result; dsPtr->spaceAvl = dsPtr->length+1; } else { dsPtr->string = ckalloc(dsPtr->length+1); memcpy(dsPtr->string, iPtr->result, (unsigned) dsPtr->length+1); iPtr->freeProc(iPtr->result); } dsPtr->spaceAvl = dsPtr->length+1; iPtr->freeProc = NULL; } else { if (dsPtr->length < TCL_DSTRING_STATIC_SIZE) { dsPtr->string = dsPtr->staticSpace; dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; } else { dsPtr->string = ckalloc(dsPtr->length+1); dsPtr->spaceAvl = dsPtr->length + 1; } memcpy(dsPtr->string, iPtr->result, (unsigned) dsPtr->length+1); } iPtr->result = iPtr->resultSpace; iPtr->resultSpace[0] = 0; } /* *---------------------------------------------------------------------- * * TclDStringToObj -- * * This function moves a dynamic string's contents to a new Tcl_Obj. Be * aware that this function does *not* check that the encoding of the * contents of the dynamic string is correct; this is the caller's * responsibility to enforce. * * Results: * The newly-allocated untyped (i.e., typePtr==NULL) Tcl_Obj with a * reference count of zero. * * Side effects: * The string is "moved" to the object. dsPtr is reinitialized to an * empty string; it does not need to be Tcl_DStringFree'd after this if * not used further. * *---------------------------------------------------------------------- */ Tcl_Obj * TclDStringToObj( Tcl_DString *dsPtr) { Tcl_Obj *result; if (dsPtr->string == dsPtr->staticSpace) { if (dsPtr->length == 0) { TclNewObj(result); } else { /* * Static buffer, so must copy. */ TclNewStringObj(result, dsPtr->string, dsPtr->length); } } else { /* * Dynamic buffer, so transfer ownership and reset. */ TclNewObj(result); result->bytes = dsPtr->string; result->length = dsPtr->length; } /* * Re-establish the DString as empty with no buffer allocated. */ dsPtr->string = dsPtr->staticSpace; dsPtr->spaceAvl = TCL_DSTRING_STATIC_SIZE; dsPtr->length = 0; dsPtr->staticSpace[0] = '\0'; return result; } /* *---------------------------------------------------------------------- * * Tcl_DStringStartSublist -- * * This function adds the necessary information to a dynamic string * (e.g. " {") to start a sublist. Future element appends will be in the * sublist rather than the main list. * * Results: * None. * * Side effects: * Characters get added to the dynamic string. * *---------------------------------------------------------------------- */ void Tcl_DStringStartSublist( Tcl_DString *dsPtr) /* Dynamic string. */ { if (TclNeedSpace(dsPtr->string, dsPtr->string + dsPtr->length)) { TclDStringAppendLiteral(dsPtr, " {"); } else { TclDStringAppendLiteral(dsPtr, "{"); } } /* *---------------------------------------------------------------------- * * Tcl_DStringEndSublist -- * * This function adds the necessary characters to a dynamic string to end * a sublist (e.g. "}"). Future element appends will be in the enclosing * (sub)list rather than the current sublist. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_DStringEndSublist( Tcl_DString *dsPtr) /* Dynamic string. */ { TclDStringAppendLiteral(dsPtr, "}"); } /* *---------------------------------------------------------------------- * * Tcl_PrintDouble -- * * Given a floating-point value, this function converts it to an ASCII * string using. * * Results: * The ASCII equivalent of "value" is written at "dst". It is written * using the current precision, and it is guaranteed to contain a decimal * point or exponent, so that it looks like a floating-point value and * not an integer. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_PrintDouble( Tcl_Interp *interp, /* Interpreter whose tcl_precision variable * used to be used to control printing. It's * ignored now. */ double value, /* Value to print as string. */ char *dst) /* Where to store converted value; must have * at least TCL_DOUBLE_SPACE characters. */ { char *p, c; int exponent; int signum; char *digits; char *end; int *precisionPtr = Tcl_GetThreadData(&precisionKey, (int) sizeof(int)); /* * Handle NaN. */ if (TclIsNaN(value)) { TclFormatNaN(value, dst); return; } /* * Handle infinities. */ if (TclIsInfinite(value)) { /* * Remember to copy the terminating NUL too. */ if (value < 0) { memcpy(dst, "-Inf", 5); } else { memcpy(dst, "Inf", 4); } return; } /* * Ordinary (normal and denormal) values. */ if (*precisionPtr == 0) { digits = TclDoubleDigits(value, -1, TCL_DD_SHORTEST, &exponent, &signum, &end); } else { /* * There are at least two possible interpretations for tcl_precision. * * The first is, "choose the decimal representation having * $tcl_precision digits of significance that is nearest to the given * number, breaking ties by rounding to even, and then trimming * trailing zeros." This gives the greatest possible precision in the * decimal string, but offers the anomaly that [expr 0.1] will be * "0.10000000000000001". * * The second is "choose the decimal representation having at most * $tcl_precision digits of significance that is nearest to the given * number. If no such representation converts exactly to the given * number, choose the one that is closest, breaking ties by rounding * to even. If more than one such representation converts exactly to * the given number, choose the shortest, breaking ties in favour of * the nearest, breaking remaining ties in favour of the one ending in * an even digit." * * Tcl 8.4 implements the first of these, which gives rise to * anomalies in formatting: * * % expr 0.1 * 0.10000000000000001 * % expr 0.01 * 0.01 * % expr 1e-7 * 9.9999999999999995e-08 * * For human readability, it appears better to choose the second rule, * and let [expr 0.1] return 0.1. But for 8.4 compatibility, we prefer * the first (the recommended zero value for tcl_precision avoids the * problem entirely). * * Uncomment TCL_DD_SHORTEN_FLAG in the next call to prefer the method * that allows floating point values to be shortened if it can be done * without loss of precision. */ digits = TclDoubleDigits(value, *precisionPtr, TCL_DD_E_FORMAT /* | TCL_DD_SHORTEN_FLAG */, &exponent, &signum, &end); } if (signum) { *dst++ = '-'; } p = digits; if (exponent < -4 || exponent > 16) { /* * E format for numbers < 1e-3 or >= 1e17. */ *dst++ = *p++; c = *p; if (c != '\0') { *dst++ = '.'; while (c != '\0') { *dst++ = c; c = *++p; } } /* * Tcl 8.4 appears to format with at least a two-digit exponent; * preserve that behaviour when tcl_precision != 0 */ if (*precisionPtr == 0) { sprintf(dst, "e%+d", exponent); } else { sprintf(dst, "e%+03d", exponent); } } else { /* * F format for others. */ if (exponent < 0) { *dst++ = '0'; } c = *p; while (exponent-- >= 0) { if (c != '\0') { *dst++ = c; c = *++p; } else { *dst++ = '0'; } } *dst++ = '.'; if (c == '\0') { *dst++ = '0'; } else { while (++exponent < -1) { *dst++ = '0'; } while (c != '\0') { *dst++ = c; c = *++p; } } *dst++ = '\0'; } ckfree(digits); } /* *---------------------------------------------------------------------- * * TclPrecTraceProc -- * * This function is invoked whenever the variable "tcl_precision" is * written. * * Results: * Returns NULL if all went well, or an error message if the new value * for the variable doesn't make sense. * * Side effects: * If the new value doesn't make sense then this function undoes the * effect of the variable modification. Otherwise it modifies the format * string that's used by Tcl_PrintDouble. * *---------------------------------------------------------------------- */ /* ARGSUSED */ char * TclPrecTraceProc( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Interpreter containing variable. */ const char *name1, /* Name of variable. */ const char *name2, /* Second part of variable name. */ int flags) /* Information about what happened. */ { Tcl_Obj *value; int prec; int *precisionPtr = Tcl_GetThreadData(&precisionKey, (int) sizeof(int)); /* * If the variable is unset, then recreate the trace. */ if (flags & TCL_TRACE_UNSETS) { if ((flags & TCL_TRACE_DESTROYED) && !Tcl_InterpDeleted(interp)) { Tcl_TraceVar2(interp, name1, name2, TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES |TCL_TRACE_UNSETS, TclPrecTraceProc, clientData); } return NULL; } /* * When the variable is read, reset its value from our shared value. This * is needed in case the variable was modified in some other interpreter * so that this interpreter's value is out of date. */ if (flags & TCL_TRACE_READS) { Tcl_SetVar2Ex(interp, name1, name2, Tcl_NewIntObj(*precisionPtr), flags & TCL_GLOBAL_ONLY); return NULL; } /* * The variable is being written. Check the new value and disallow it if * it isn't reasonable or if this is a safe interpreter (we don't want * safe interpreters messing up the precision of other interpreters). */ if (Tcl_IsSafe(interp)) { return (char *) "can't modify precision from a safe interpreter"; } value = Tcl_GetVar2Ex(interp, name1, name2, flags & TCL_GLOBAL_ONLY); if (value == NULL || Tcl_GetIntFromObj(NULL, value, &prec) != TCL_OK || prec < 0 || prec > TCL_MAX_PREC) { return (char *) "improper value for precision"; } *precisionPtr = prec; return NULL; } /* *---------------------------------------------------------------------- * * TclNeedSpace -- * * This function checks to see whether it is appropriate to add a space * before appending a new list element to an existing string. * * Results: * The return value is 1 if a space is appropriate, 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclNeedSpace( const char *start, /* First character in string. */ const char *end) /* End of string (place where space will be * added, if appropriate). */ { /* * A space is needed unless either: * (a) we're at the start of the string, or */ if (end == start) { return 0; } /* * (b) we're at the start of a nested list-element, quoted with an open * curly brace; we can be nested arbitrarily deep, so long as the * first curly brace starts an element, so backtrack over open curly * braces that are trailing characters of the string; and */ end = Tcl_UtfPrev(end, start); while (*end == '{') { if (end == start) { return 0; } end = Tcl_UtfPrev(end, start); } /* * (c) the trailing character of the string is already a list-element * separator (according to TclFindElement); that is, one of these * characters: * \u0009 \t TAB * \u000A \n NEWLINE * \u000B \v VERTICAL TAB * \u000C \f FORM FEED * \u000D \r CARRIAGE RETURN * \u0020 SPACE * with the condition that the penultimate character is not a * backslash. */ if (*end > 0x20) { /* * Performance tweak. All ASCII spaces are <= 0x20. So get a quick * answer for most characters before comparing against all spaces in * the switch below. * * NOTE: Remove this if other Unicode spaces ever get accepted as * list-element separators. */ return 1; } switch (*end) { case ' ': case '\t': case '\n': case '\r': case '\v': case '\f': if ((end == start) || (end[-1] != '\\')) { return 0; } } return 1; } /* *---------------------------------------------------------------------- * * TclFormatInt -- * * This procedure formats an integer into a sequence of decimal digit * characters in a buffer. If the integer is negative, a minus sign is * inserted at the start of the buffer. A null character is inserted at * the end of the formatted characters. It is the caller's responsibility * to ensure that enough storage is available. This procedure has the * effect of sprintf(buffer, "%ld", n) but is faster as proven in * benchmarks. This is key to UpdateStringOfInt, which is a common path * for a lot of code (e.g. int-indexed arrays). * * Results: * An integer representing the number of characters formatted, not * including the terminating \0. * * Side effects: * The formatted characters are written into the storage pointer to by * the "buffer" argument. * *---------------------------------------------------------------------- */ int TclFormatInt( char *buffer, /* Points to the storage into which the * formatted characters are written. */ long n) /* The integer to format. */ { long intVal; int i; int numFormatted, j; const char *digits = "0123456789"; /* * Check first whether "n" is zero. */ if (n == 0) { buffer[0] = '0'; buffer[1] = 0; return 1; } /* * Check whether "n" is the maximum negative value. This is -2^(m-1) for * an m-bit word, and has no positive equivalent; negating it produces the * same value. */ intVal = -n; /* [Bug 3390638] Workaround for*/ if (n == -n || intVal == n) { /* broken compiler optimizers. */ return sprintf(buffer, "%ld", n); } /* * Generate the characters of the result backwards in the buffer. */ intVal = (n < 0? -n : n); i = 0; buffer[0] = '\0'; do { i++; buffer[i] = digits[intVal % 10]; intVal = intVal/10; } while (intVal > 0); if (n < 0) { i++; buffer[i] = '-'; } numFormatted = i; /* * Now reverse the characters. */ for (j = 0; j < i; j++, i--) { char tmp = buffer[i]; buffer[i] = buffer[j]; buffer[j] = tmp; } return numFormatted; } /* *---------------------------------------------------------------------- * * TclGetIntForIndex -- * * This function returns an integer corresponding to the list index held * in a Tcl object. The Tcl object's value is expected to be in the * format integer([+-]integer)? or the format end([+-]integer)?. * * Results: * The return value is normally TCL_OK, which means that the index was * successfully stored into the location referenced by "indexPtr". If the * Tcl object referenced by "objPtr" has the value "end", the value * stored is "endValue". If "objPtr"s values is not of one of the * expected formats, TCL_ERROR is returned and, if "interp" is non-NULL, * an error message is left in the interpreter's result object. * * Side effects: * The object referenced by "objPtr" might be converted to an integer, * wide integer, or end-based-index object. * *---------------------------------------------------------------------- */ int TclGetIntForIndex( Tcl_Interp *interp, /* Interpreter to use for error reporting. If * NULL, then no error message is left after * errors. */ Tcl_Obj *objPtr, /* Points to an object containing either "end" * or an integer. */ int endValue, /* The value to be stored at "indexPtr" if * "objPtr" holds "end". */ int *indexPtr) /* Location filled in with an integer * representing an index. */ { int length; char *opPtr; const char *bytes; if (TclGetIntFromObj(NULL, objPtr, indexPtr) == TCL_OK) { return TCL_OK; } if (SetEndOffsetFromAny(NULL, objPtr) == TCL_OK) { /* * If the object is already an offset from the end of the list, or can * be converted to one, use it. */ *indexPtr = endValue + objPtr->internalRep.longValue; return TCL_OK; } bytes = TclGetStringFromObj(objPtr, &length); /* * Leading whitespace is acceptable in an index. */ while (length && TclIsSpaceProc(*bytes)) { bytes++; length--; } if (TclParseNumber(NULL, NULL, NULL, bytes, length, (const char **)&opPtr, TCL_PARSE_INTEGER_ONLY | TCL_PARSE_NO_WHITESPACE) == TCL_OK) { int code, first, second; char savedOp = *opPtr; if ((savedOp != '+') && (savedOp != '-')) { goto parseError; } if (TclIsSpaceProc(opPtr[1])) { goto parseError; } *opPtr = '\0'; code = Tcl_GetInt(interp, bytes, &first); *opPtr = savedOp; if (code == TCL_ERROR) { goto parseError; } if (TCL_ERROR == Tcl_GetInt(interp, opPtr+1, &second)) { goto parseError; } if (savedOp == '+') { *indexPtr = first + second; } else { *indexPtr = first - second; } return TCL_OK; } /* * Report a parse error. */ parseError: if (interp != NULL) { bytes = Tcl_GetString(objPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad index \"%s\": must be integer?[+-]integer? or" " end?[+-]integer?", bytes)); if (!strncmp(bytes, "end-", 4)) { bytes += 4; } TclCheckBadOctal(interp, bytes); Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", NULL); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * UpdateStringOfEndOffset -- * * Update the string rep of a Tcl object holding an "end-offset" * expression. * * Results: * None. * * Side effects: * Stores a valid string in the object's string rep. * * This function does NOT free any earlier string rep. If it is called on an * object that already has a valid string rep, it will leak memory. * *---------------------------------------------------------------------- */ static void UpdateStringOfEndOffset( register Tcl_Obj *objPtr) { char buffer[TCL_INTEGER_SPACE + 5]; register int len = 3; memcpy(buffer, "end", 4); if (objPtr->internalRep.longValue != 0) { buffer[len++] = '-'; len += TclFormatInt(buffer+len, -(objPtr->internalRep.longValue)); } objPtr->bytes = ckalloc((unsigned) len+1); memcpy(objPtr->bytes, buffer, (unsigned) len+1); objPtr->length = len; } /* *---------------------------------------------------------------------- * * SetEndOffsetFromAny -- * * Look for a string of the form "end[+-]offset" and convert it to an * internal representation holding the offset. * * Results: * Returns TCL_OK if ok, TCL_ERROR if the string was badly formed. * * Side effects: * If interp is not NULL, stores an error message in the interpreter * result. * *---------------------------------------------------------------------- */ static int SetEndOffsetFromAny( Tcl_Interp *interp, /* Tcl interpreter or NULL */ Tcl_Obj *objPtr) /* Pointer to the object to parse */ { int offset; /* Offset in the "end-offset" expression */ register const char *bytes; /* String rep of the object */ int length; /* Length of the object's string rep */ /* * If it's already the right type, we're fine. */ if (objPtr->typePtr == &tclEndOffsetType) { return TCL_OK; } /* * Check for a string rep of the right form. */ bytes = TclGetStringFromObj(objPtr, &length); if ((*bytes != 'e') || (strncmp(bytes, "end", (size_t)((length > 3) ? 3 : length)) != 0)) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad index \"%s\": must be end?[+-]integer?", bytes)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", NULL); } return TCL_ERROR; } /* * Convert the string rep. */ if (length <= 3) { offset = 0; } else if ((length > 4) && ((bytes[3] == '-') || (bytes[3] == '+'))) { /* * This is our limited string expression evaluator. Pass everything * after "end-" to Tcl_GetInt, then reverse for offset. */ if (TclIsSpaceProc(bytes[4])) { goto badIndexFormat; } if (Tcl_GetInt(interp, bytes+4, &offset) != TCL_OK) { return TCL_ERROR; } if (bytes[3] == '-') { offset = -offset; } } else { /* * Conversion failed. Report the error. */ badIndexFormat: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad index \"%s\": must be end?[+-]integer?", bytes)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", NULL); } return TCL_ERROR; } /* * The conversion succeeded. Free the old internal rep and set the new * one. */ TclFreeIntRep(objPtr); objPtr->internalRep.longValue = offset; objPtr->typePtr = &tclEndOffsetType; return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCheckBadOctal -- * * This function checks for a bad octal value and appends a meaningful * error to the interp's result. * * Results: * 1 if the argument was a bad octal, else 0. * * Side effects: * The interpreter's result is modified. * *---------------------------------------------------------------------- */ int TclCheckBadOctal( Tcl_Interp *interp, /* Interpreter to use for error reporting. If * NULL, then no error message is left after * errors. */ const char *value) /* String to check. */ { register const char *p = value; /* * A frequent mistake is invalid octal values due to an unwanted leading * zero. Try to generate a meaningful error message. */ while (TclIsSpaceProc(*p)) { p++; } if (*p == '+' || *p == '-') { p++; } if (*p == '0') { if ((p[1] == 'o') || p[1] == 'O') { p += 2; } while (isdigit(UCHAR(*p))) { /* INTL: digit. */ p++; } while (TclIsSpaceProc(*p)) { p++; } if (*p == '\0') { /* * Reached end of string. */ if (interp != NULL) { /* * Don't reset the result here because we want this result to * be added to an existing error message as extra info. */ Tcl_AppendToObj(Tcl_GetObjResult(interp), " (looks like invalid octal number)", -1); } return 1; } } return 0; } /* *---------------------------------------------------------------------- * * ClearHash -- * * Remove all the entries in the hash table *tablePtr. * *---------------------------------------------------------------------- */ static void ClearHash( Tcl_HashTable *tablePtr) { Tcl_HashSearch search; Tcl_HashEntry *hPtr; for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Tcl_Obj *objPtr = Tcl_GetHashValue(hPtr); Tcl_DecrRefCount(objPtr); Tcl_DeleteHashEntry(hPtr); } } /* *---------------------------------------------------------------------- * * GetThreadHash -- * * Get a thread-specific (Tcl_HashTable *) associated with a thread data * key. * * Results: * The Tcl_HashTable * corresponding to *keyPtr. * * Side effects: * The first call on a keyPtr in each thread creates a new Tcl_HashTable, * and registers a thread exit handler to dispose of it. * *---------------------------------------------------------------------- */ static Tcl_HashTable * GetThreadHash( Tcl_ThreadDataKey *keyPtr) { Tcl_HashTable **tablePtrPtr = Tcl_GetThreadData(keyPtr, sizeof(Tcl_HashTable *)); if (NULL == *tablePtrPtr) { *tablePtrPtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_CreateThreadExitHandler(FreeThreadHash, *tablePtrPtr); Tcl_InitHashTable(*tablePtrPtr, TCL_ONE_WORD_KEYS); } return *tablePtrPtr; } /* *---------------------------------------------------------------------- * * FreeThreadHash -- * * Thread exit handler used by GetThreadHash to dispose of a thread hash * table. * * Side effects: * Frees a Tcl_HashTable. * *---------------------------------------------------------------------- */ static void FreeThreadHash( ClientData clientData) { Tcl_HashTable *tablePtr = clientData; ClearHash(tablePtr); Tcl_DeleteHashTable(tablePtr); ckfree(tablePtr); } /* *---------------------------------------------------------------------- * * FreeProcessGlobalValue -- * * Exit handler used by Tcl(Set|Get)ProcessGlobalValue to cleanup a * ProcessGlobalValue at exit. * *---------------------------------------------------------------------- */ static void FreeProcessGlobalValue( ClientData clientData) { ProcessGlobalValue *pgvPtr = clientData; pgvPtr->epoch++; pgvPtr->numBytes = 0; ckfree(pgvPtr->value); pgvPtr->value = NULL; if (pgvPtr->encoding) { Tcl_FreeEncoding(pgvPtr->encoding); pgvPtr->encoding = NULL; } Tcl_MutexFinalize(&pgvPtr->mutex); } /* *---------------------------------------------------------------------- * * TclSetProcessGlobalValue -- * * Utility routine to set a global value shared by all threads in the * process while keeping a thread-local copy as well. * *---------------------------------------------------------------------- */ void TclSetProcessGlobalValue( ProcessGlobalValue *pgvPtr, Tcl_Obj *newValue, Tcl_Encoding encoding) { const char *bytes; Tcl_HashTable *cacheMap; Tcl_HashEntry *hPtr; int dummy; Tcl_MutexLock(&pgvPtr->mutex); /* * Fill the global string value. */ pgvPtr->epoch++; if (NULL != pgvPtr->value) { ckfree(pgvPtr->value); } else { Tcl_CreateExitHandler(FreeProcessGlobalValue, pgvPtr); } bytes = Tcl_GetStringFromObj(newValue, &pgvPtr->numBytes); pgvPtr->value = ckalloc(pgvPtr->numBytes + 1); memcpy(pgvPtr->value, bytes, (unsigned) pgvPtr->numBytes + 1); if (pgvPtr->encoding) { Tcl_FreeEncoding(pgvPtr->encoding); } pgvPtr->encoding = encoding; /* * Fill the local thread copy directly with the Tcl_Obj value to avoid * loss of the intrep. Increment newValue refCount early to handle case * where we set a PGV to itself. */ Tcl_IncrRefCount(newValue); cacheMap = GetThreadHash(&pgvPtr->key); ClearHash(cacheMap); hPtr = Tcl_CreateHashEntry(cacheMap, INT2PTR(pgvPtr->epoch), &dummy); Tcl_SetHashValue(hPtr, newValue); Tcl_MutexUnlock(&pgvPtr->mutex); } /* *---------------------------------------------------------------------- * * TclGetProcessGlobalValue -- * * Retrieve a global value shared among all threads of the process, * preferring a thread-local copy as long as it remains valid. * * Results: * Returns a (Tcl_Obj *) that holds a copy of the global value. * *---------------------------------------------------------------------- */ Tcl_Obj * TclGetProcessGlobalValue( ProcessGlobalValue *pgvPtr) { Tcl_Obj *value = NULL; Tcl_HashTable *cacheMap; Tcl_HashEntry *hPtr; int epoch = pgvPtr->epoch; if (pgvPtr->encoding) { Tcl_Encoding current = Tcl_GetEncoding(NULL, NULL); if (pgvPtr->encoding != current) { /* * The system encoding has changed since the master string value * was saved. Convert the master value to be based on the new * system encoding. */ Tcl_DString native, newValue; Tcl_MutexLock(&pgvPtr->mutex); pgvPtr->epoch++; epoch = pgvPtr->epoch; Tcl_UtfToExternalDString(pgvPtr->encoding, pgvPtr->value, pgvPtr->numBytes, &native); Tcl_ExternalToUtfDString(current, Tcl_DStringValue(&native), Tcl_DStringLength(&native), &newValue); Tcl_DStringFree(&native); ckfree(pgvPtr->value); pgvPtr->value = ckalloc(Tcl_DStringLength(&newValue) + 1); memcpy(pgvPtr->value, Tcl_DStringValue(&newValue), (size_t) Tcl_DStringLength(&newValue) + 1); Tcl_DStringFree(&newValue); Tcl_FreeEncoding(pgvPtr->encoding); pgvPtr->encoding = current; Tcl_MutexUnlock(&pgvPtr->mutex); } else { Tcl_FreeEncoding(current); } } cacheMap = GetThreadHash(&pgvPtr->key); hPtr = Tcl_FindHashEntry(cacheMap, (char *) INT2PTR(epoch)); if (NULL == hPtr) { int dummy; /* * No cache for the current epoch - must be a new one. * * First, clear the cacheMap, as anything in it must refer to some * expired epoch. */ ClearHash(cacheMap); /* * If no thread has set the shared value, call the initializer. */ Tcl_MutexLock(&pgvPtr->mutex); if ((NULL == pgvPtr->value) && (pgvPtr->proc)) { pgvPtr->epoch++; pgvPtr->proc(&pgvPtr->value,&pgvPtr->numBytes,&pgvPtr->encoding); if (pgvPtr->value == NULL) { Tcl_Panic("PGV Initializer did not initialize"); } Tcl_CreateExitHandler(FreeProcessGlobalValue, pgvPtr); } /* * Store a copy of the shared value in our epoch-indexed cache. */ value = Tcl_NewStringObj(pgvPtr->value, pgvPtr->numBytes); hPtr = Tcl_CreateHashEntry(cacheMap, INT2PTR(pgvPtr->epoch), &dummy); Tcl_MutexUnlock(&pgvPtr->mutex); Tcl_SetHashValue(hPtr, value); Tcl_IncrRefCount(value); } return Tcl_GetHashValue(hPtr); } /* *---------------------------------------------------------------------- * * TclSetObjNameOfExecutable -- * * This function stores the absolute pathname of the executable file * (normally as computed by TclpFindExecutable). * * Results: * None. * * Side effects: * Stores the executable name. * *---------------------------------------------------------------------- */ void TclSetObjNameOfExecutable( Tcl_Obj *name, Tcl_Encoding encoding) { TclSetProcessGlobalValue(&executableName, name, encoding); } /* *---------------------------------------------------------------------- * * TclGetObjNameOfExecutable -- * * This function retrieves the absolute pathname of the application in * which the Tcl library is running, usually as previously stored by * TclpFindExecutable(). This function call is the C API equivalent to * the "info nameofexecutable" command. * * Results: * A pointer to an "fsPath" Tcl_Obj, or to an empty Tcl_Obj if the * pathname of the application is unknown. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Obj * TclGetObjNameOfExecutable(void) { return TclGetProcessGlobalValue(&executableName); } /* *---------------------------------------------------------------------- * * Tcl_GetNameOfExecutable -- * * This function retrieves the absolute pathname of the application in * which the Tcl library is running, and returns it in string form. * * The returned string belongs to Tcl and should be copied if the caller * plans to keep it, to guard against it becoming invalid. * * Results: * A pointer to the internal string or NULL if the internal full path * name has not been computed or unknown. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * Tcl_GetNameOfExecutable(void) { int numBytes; const char *bytes = Tcl_GetStringFromObj(TclGetObjNameOfExecutable(), &numBytes); if (numBytes == 0) { return NULL; } return bytes; } /* *---------------------------------------------------------------------- * * TclpGetTime -- * * Deprecated synonym for Tcl_GetTime. This function is provided for the * benefit of extensions written before Tcl_GetTime was exported from the * library. * * Results: * None. * * Side effects: * Stores current time in the buffer designated by "timePtr" * *---------------------------------------------------------------------- */ void TclpGetTime( Tcl_Time *timePtr) { Tcl_GetTime(timePtr); } /* *---------------------------------------------------------------------- * * TclGetPlatform -- * * This is a kludge that allows the test library to get access the * internal tclPlatform variable. * * Results: * Returns a pointer to the tclPlatform variable. * * Side effects: * None. * *---------------------------------------------------------------------- */ TclPlatformType * TclGetPlatform(void) { return &tclPlatform; } /* *---------------------------------------------------------------------- * * TclReToGlob -- * * Attempt to convert a regular expression to an equivalent glob pattern. * * Results: * Returns TCL_OK on success, TCL_ERROR on failure. If interp is not * NULL, an error message is placed in the result. On success, the * DString will contain an exact equivalent glob pattern. The caller is * responsible for calling Tcl_DStringFree on success. If exactPtr is not * NULL, it will be 1 if an exact match qualifies. * * Side effects: * None. * *---------------------------------------------------------------------- */ int TclReToGlob( Tcl_Interp *interp, const char *reStr, int reStrLen, Tcl_DString *dsPtr, int *exactPtr, int *quantifiersFoundPtr) { int anchorLeft, anchorRight, lastIsStar, numStars; char *dsStr, *dsStrStart; const char *msg, *p, *strEnd, *code; strEnd = reStr + reStrLen; Tcl_DStringInit(dsPtr); if (quantifiersFoundPtr != NULL) { *quantifiersFoundPtr = 0; } /* * "***=xxx" == "*xxx*", watch for glob-sensitive chars. */ if ((reStrLen >= 4) && (memcmp("***=", reStr, 4) == 0)) { /* * At most, the glob pattern has length 2*reStrLen + 2 to backslash * escape every character and have * at each end. */ Tcl_DStringSetLength(dsPtr, reStrLen + 2); dsStr = dsStrStart = Tcl_DStringValue(dsPtr); *dsStr++ = '*'; for (p = reStr + 4; p < strEnd; p++) { switch (*p) { case '\\': case '*': case '[': case ']': case '?': /* Only add \ where necessary for glob */ *dsStr++ = '\\'; /* fall through */ default: *dsStr++ = *p; break; } } *dsStr++ = '*'; Tcl_DStringSetLength(dsPtr, dsStr - dsStrStart); if (exactPtr) { *exactPtr = 0; } return TCL_OK; } /* * At most, the glob pattern has length reStrLen + 2 to account for * possible * at each end. */ Tcl_DStringSetLength(dsPtr, reStrLen + 2); dsStr = dsStrStart = Tcl_DStringValue(dsPtr); /* * Check for anchored REs (ie ^foo$), so we can use string equal if * possible. Do not alter the start of str so we can free it correctly. * * Keep track of the last char being an unescaped star to prevent multiple * instances. Simpler than checking that the last star may be escaped. */ msg = NULL; code = NULL; p = reStr; anchorRight = 0; lastIsStar = 0; numStars = 0; if (*p == '^') { anchorLeft = 1; p++; } else { anchorLeft = 0; *dsStr++ = '*'; lastIsStar = 1; } for ( ; p < strEnd; p++) { switch (*p) { case '\\': p++; switch (*p) { case 'a': *dsStr++ = '\a'; break; case 'b': *dsStr++ = '\b'; break; case 'f': *dsStr++ = '\f'; break; case 'n': *dsStr++ = '\n'; break; case 'r': *dsStr++ = '\r'; break; case 't': *dsStr++ = '\t'; break; case 'v': *dsStr++ = '\v'; break; case 'B': case '\\': *dsStr++ = '\\'; *dsStr++ = '\\'; anchorLeft = 0; /* prevent exact match */ break; case '*': case '[': case ']': case '?': /* Only add \ where necessary for glob */ *dsStr++ = '\\'; anchorLeft = 0; /* prevent exact match */ /* fall through */ case '{': case '}': case '(': case ')': case '+': case '.': case '|': case '^': case '$': *dsStr++ = *p; break; default: msg = "invalid escape sequence"; code = "BADESCAPE"; goto invalidGlob; } break; case '.': if (quantifiersFoundPtr != NULL) { *quantifiersFoundPtr = 1; } anchorLeft = 0; /* prevent exact match */ if (p+1 < strEnd) { if (p[1] == '*') { p++; if (!lastIsStar) { *dsStr++ = '*'; lastIsStar = 1; numStars++; } continue; } else if (p[1] == '+') { p++; *dsStr++ = '?'; *dsStr++ = '*'; lastIsStar = 1; numStars++; continue; } } *dsStr++ = '?'; break; case '$': if (p+1 != strEnd) { msg = "$ not anchor"; code = "NONANCHOR"; goto invalidGlob; } anchorRight = 1; break; case '*': case '+': case '?': case '|': case '^': case '{': case '}': case '(': case ')': case '[': case ']': msg = "unhandled RE special char"; code = "UNHANDLED"; goto invalidGlob; default: *dsStr++ = *p; break; } lastIsStar = 0; } if (numStars > 1) { /* * Heuristic: if >1 non-anchoring *, the risk is large that glob * matching is slower than the RE engine, so report invalid. */ msg = "excessive recursive glob backtrack potential"; code = "OVERCOMPLEX"; goto invalidGlob; } if (!anchorRight && !lastIsStar) { *dsStr++ = '*'; } Tcl_DStringSetLength(dsPtr, dsStr - dsStrStart); if (exactPtr) { *exactPtr = (anchorLeft && anchorRight); } return TCL_OK; invalidGlob: if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1)); Tcl_SetErrorCode(interp, "TCL", "RE2GLOB", code, NULL); } Tcl_DStringFree(dsPtr); return TCL_ERROR; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tcl.h0000644000175000017500000027102712665113557014150 0ustar sergeisergei/* * tcl.h -- * * This header file describes the externally-visible facilities of the * Tcl interpreter. * * Copyright (c) 1987-1994 The Regents of the University of California. * Copyright (c) 1993-1996 Lucent Technologies. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 1998-2000 by Scriptics Corporation. * Copyright (c) 2002 by Kevin B. Kenny. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCL #define _TCL /* * For C++ compilers, use extern "C" */ #ifdef __cplusplus extern "C" { #endif /* * The following defines are used to indicate the various release levels. */ #define TCL_ALPHA_RELEASE 0 #define TCL_BETA_RELEASE 1 #define TCL_FINAL_RELEASE 2 /* * When version numbers change here, must also go into the following files and * update the version numbers: * * library/init.tcl (1 LOC patch) * unix/configure.in (2 LOC Major, 2 LOC minor, 1 LOC patch) * win/configure.in (as above) * win/tcl.m4 (not patchlevel) * win/makefile.bc (not patchlevel) 2 LOC * README (sections 0 and 2, with and without separator) * macosx/Tcl.pbproj/project.pbxproj (not patchlevel) 1 LOC * macosx/Tcl.pbproj/default.pbxuser (not patchlevel) 1 LOC * macosx/Tcl.xcode/project.pbxproj (not patchlevel) 2 LOC * macosx/Tcl.xcode/default.pbxuser (not patchlevel) 1 LOC * macosx/Tcl-Common.xcconfig (not patchlevel) 1 LOC * win/README (not patchlevel) (sections 0 and 2) * unix/tcl.spec (1 LOC patch) * tools/tcl.hpj.in (not patchlevel, for windows installer) */ #define TCL_MAJOR_VERSION 8 #define TCL_MINOR_VERSION 6 #define TCL_RELEASE_LEVEL TCL_FINAL_RELEASE #define TCL_RELEASE_SERIAL 5 #define TCL_VERSION "8.6" #define TCL_PATCH_LEVEL "8.6.5" /* *---------------------------------------------------------------------------- * The following definitions set up the proper options for Windows compilers. * We use this method because there is no autoconf equivalent. */ #ifdef _WIN32 # ifndef __WIN32__ # define __WIN32__ # endif # ifndef WIN32 # define WIN32 # endif #endif /* * Utility macros: STRINGIFY takes an argument and wraps it in "" (double * quotation marks), JOIN joins two arguments. */ #ifndef STRINGIFY # define STRINGIFY(x) STRINGIFY1(x) # define STRINGIFY1(x) #x #endif #ifndef JOIN # define JOIN(a,b) JOIN1(a,b) # define JOIN1(a,b) a##b #endif /* * A special definition used to allow this header file to be included from * windows resource files so that they can obtain version information. * RC_INVOKED is defined by default by the windows RC tool. * * Resource compilers don't like all the C stuff, like typedefs and function * declarations, that occur below, so block them out. */ #ifndef RC_INVOKED /* * Special macro to define mutexes, that doesn't do anything if we are not * using threads. */ #ifdef TCL_THREADS #define TCL_DECLARE_MUTEX(name) static Tcl_Mutex name; #else #define TCL_DECLARE_MUTEX(name) #endif /* * Tcl's public routine Tcl_FSSeek() uses the values SEEK_SET, SEEK_CUR, and * SEEK_END, all #define'd by stdio.h . * * Also, many extensions need stdio.h, and they've grown accustomed to tcl.h * providing it for them rather than #include-ing it themselves as they * should, so also for their sake, we keep the #include to be consistent with * prior Tcl releases. */ #include /* *---------------------------------------------------------------------------- * Support for functions with a variable number of arguments. * * The following TCL_VARARGS* macros are to support old extensions * written for older versions of Tcl where the macros permitted * support for the varargs.h system as well as stdarg.h . * * New code should just directly be written to use stdarg.h conventions. */ #include #ifndef TCL_NO_DEPRECATED # define TCL_VARARGS(type, name) (type name, ...) # define TCL_VARARGS_DEF(type, name) (type name, ...) # define TCL_VARARGS_START(type, name, list) (va_start(list, name), name) #endif #if defined(__GNUC__) && (__GNUC__ > 2) # define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__printf__, a, b))) # define TCL_NORETURN __attribute__ ((noreturn)) # if defined(BUILD_tcl) || defined(BUILD_tk) # define TCL_NORETURN1 __attribute__ ((noreturn)) # else # define TCL_NORETURN1 /* nothing */ # endif #else # define TCL_FORMAT_PRINTF(a,b) # if defined(_MSC_VER) && (_MSC_VER >= 1310) # define TCL_NORETURN _declspec(noreturn) # else # define TCL_NORETURN /* nothing */ # endif # define TCL_NORETURN1 /* nothing */ #endif /* * Allow a part of Tcl's API to be explicitly marked as deprecated. * * Used to make TIP 330/336 generate moans even if people use the * compatibility macros. Change your code, guys! We won't support you forever. */ #if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) # if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) # define TCL_DEPRECATED_API(msg) __attribute__ ((__deprecated__ (msg))) # else # define TCL_DEPRECATED_API(msg) __attribute__ ((__deprecated__)) # endif #else # define TCL_DEPRECATED_API(msg) /* nothing portable */ #endif /* *---------------------------------------------------------------------------- * Macros used to declare a function to be exported by a DLL. Used by Windows, * maps to no-op declarations on non-Windows systems. The default build on * windows is for a DLL, which causes the DLLIMPORT and DLLEXPORT macros to be * nonempty. To build a static library, the macro STATIC_BUILD should be * defined. * * Note: when building static but linking dynamically to MSVCRT we must still * correctly decorate the C library imported function. Use CRTIMPORT * for this purpose. _DLL is defined by the compiler when linking to * MSVCRT. */ #if (defined(_WIN32) && (defined(_MSC_VER) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0550)) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec)))) # define HAVE_DECLSPEC 1 # ifdef STATIC_BUILD # define DLLIMPORT # define DLLEXPORT # ifdef _DLL # define CRTIMPORT __declspec(dllimport) # else # define CRTIMPORT # endif # else # define DLLIMPORT __declspec(dllimport) # define DLLEXPORT __declspec(dllexport) # define CRTIMPORT __declspec(dllimport) # endif #else # define DLLIMPORT # if defined(__GNUC__) && __GNUC__ > 3 # define DLLEXPORT __attribute__ ((visibility("default"))) # else # define DLLEXPORT # endif # define CRTIMPORT #endif /* * These macros are used to control whether functions are being declared for * import or export. If a function is being declared while it is being built * to be included in a shared library, then it should have the DLLEXPORT * storage class. If is being declared for use by a module that is going to * link against the shared library, then it should have the DLLIMPORT storage * class. If the symbol is beind declared for a static build or for use from a * stub library, then the storage class should be empty. * * The convention is that a macro called BUILD_xxxx, where xxxx is the name of * a library we are building, is set on the compile line for sources that are * to be placed in the library. When this macro is set, the storage class will * be set to DLLEXPORT. At the end of the header file, the storage class will * be reset to DLLIMPORT. */ #undef TCL_STORAGE_CLASS #ifdef BUILD_tcl # define TCL_STORAGE_CLASS DLLEXPORT #else # ifdef USE_TCL_STUBS # define TCL_STORAGE_CLASS # else # define TCL_STORAGE_CLASS DLLIMPORT # endif #endif /* * The following _ANSI_ARGS_ macro is to support old extensions * written for older versions of Tcl where it permitted support * for compilers written in the pre-prototype era of C. * * New code should use prototypes. */ #ifndef TCL_NO_DEPRECATED # undef _ANSI_ARGS_ # define _ANSI_ARGS_(x) x #endif /* * Definitions that allow this header file to be used either with or without * ANSI C features. */ #ifndef INLINE # define INLINE #endif #ifdef NO_CONST # ifndef const # define const # endif #endif #ifndef CONST # define CONST const #endif #ifdef USE_NON_CONST # ifdef USE_COMPAT_CONST # error define at most one of USE_NON_CONST and USE_COMPAT_CONST # endif # define CONST84 # define CONST84_RETURN #else # ifdef USE_COMPAT_CONST # define CONST84 # define CONST84_RETURN const # else # define CONST84 const # define CONST84_RETURN const # endif #endif #ifndef CONST86 # define CONST86 CONST84 #endif /* * Make sure EXTERN isn't defined elsewhere. */ #ifdef EXTERN # undef EXTERN #endif /* EXTERN */ #ifdef __cplusplus # define EXTERN extern "C" TCL_STORAGE_CLASS #else # define EXTERN extern TCL_STORAGE_CLASS #endif /* *---------------------------------------------------------------------------- * The following code is copied from winnt.h. If we don't replicate it here, * then can't be included after tcl.h, since tcl.h also defines * VOID. This block is skipped under Cygwin and Mingw. */ #if defined(_WIN32) && !defined(HAVE_WINNT_IGNORE_VOID) #ifndef VOID #define VOID void typedef char CHAR; typedef short SHORT; typedef long LONG; #endif #endif /* _WIN32 && !HAVE_WINNT_IGNORE_VOID */ /* * Macro to use instead of "void" for arguments that must have type "void *" * in ANSI C; maps them to type "char *" in non-ANSI systems. */ #ifndef __VXWORKS__ # ifndef NO_VOID # define VOID void # else # define VOID char # endif #endif /* * Miscellaneous declarations. */ #ifndef _CLIENTDATA # ifndef NO_VOID typedef void *ClientData; # else typedef int *ClientData; # endif # define _CLIENTDATA #endif /* * Darwin specific configure overrides (to support fat compiles, where * configure runs only once for multiple architectures): */ #ifdef __APPLE__ # ifdef __LP64__ # undef TCL_WIDE_INT_TYPE # define TCL_WIDE_INT_IS_LONG 1 # define TCL_CFG_DO64BIT 1 # else /* !__LP64__ */ # define TCL_WIDE_INT_TYPE long long # undef TCL_WIDE_INT_IS_LONG # undef TCL_CFG_DO64BIT # endif /* __LP64__ */ # undef HAVE_STRUCT_STAT64 #endif /* __APPLE__ */ /* * Define Tcl_WideInt to be a type that is (at least) 64-bits wide, and define * Tcl_WideUInt to be the unsigned variant of that type (assuming that where * we have one, we can have the other.) * * Also defines the following macros: * TCL_WIDE_INT_IS_LONG - if wide ints are really longs (i.e. we're on a real * 64-bit system.) * Tcl_WideAsLong - forgetful converter from wideInt to long. * Tcl_LongAsWide - sign-extending converter from long to wideInt. * Tcl_WideAsDouble - converter from wideInt to double. * Tcl_DoubleAsWide - converter from double to wideInt. * * The following invariant should hold for any long value 'longVal': * longVal == Tcl_WideAsLong(Tcl_LongAsWide(longVal)) * * Note on converting between Tcl_WideInt and strings. This implementation (in * tclObj.c) depends on the function * sprintf(...,"%" TCL_LL_MODIFIER "d",...). */ #if !defined(TCL_WIDE_INT_TYPE)&&!defined(TCL_WIDE_INT_IS_LONG) # if defined(_WIN32) # define TCL_WIDE_INT_TYPE __int64 # ifdef __BORLANDC__ # define TCL_LL_MODIFIER "L" # else /* __BORLANDC__ */ # define TCL_LL_MODIFIER "I64" # endif /* __BORLANDC__ */ # elif defined(__GNUC__) # define TCL_WIDE_INT_TYPE long long # define TCL_LL_MODIFIER "ll" # else /* ! _WIN32 && ! __GNUC__ */ /* * Don't know what platform it is and configure hasn't discovered what is * going on for us. Try to guess... */ # include # if (INT_MAX < LONG_MAX) # define TCL_WIDE_INT_IS_LONG 1 # else # define TCL_WIDE_INT_TYPE long long # endif # endif /* _WIN32 */ #endif /* !TCL_WIDE_INT_TYPE & !TCL_WIDE_INT_IS_LONG */ #ifdef TCL_WIDE_INT_IS_LONG # undef TCL_WIDE_INT_TYPE # define TCL_WIDE_INT_TYPE long #endif /* TCL_WIDE_INT_IS_LONG */ typedef TCL_WIDE_INT_TYPE Tcl_WideInt; typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt; #ifdef TCL_WIDE_INT_IS_LONG # define Tcl_WideAsLong(val) ((long)(val)) # define Tcl_LongAsWide(val) ((long)(val)) # define Tcl_WideAsDouble(val) ((double)((long)(val))) # define Tcl_DoubleAsWide(val) ((long)((double)(val))) # ifndef TCL_LL_MODIFIER # define TCL_LL_MODIFIER "l" # endif /* !TCL_LL_MODIFIER */ #else /* TCL_WIDE_INT_IS_LONG */ /* * The next short section of defines are only done when not running on Windows * or some other strange platform. */ # ifndef TCL_LL_MODIFIER # define TCL_LL_MODIFIER "ll" # endif /* !TCL_LL_MODIFIER */ # define Tcl_WideAsLong(val) ((long)((Tcl_WideInt)(val))) # define Tcl_LongAsWide(val) ((Tcl_WideInt)((long)(val))) # define Tcl_WideAsDouble(val) ((double)((Tcl_WideInt)(val))) # define Tcl_DoubleAsWide(val) ((Tcl_WideInt)((double)(val))) #endif /* TCL_WIDE_INT_IS_LONG */ #if defined(_WIN32) # ifdef __BORLANDC__ typedef struct stati64 Tcl_StatBuf; # elif defined(_WIN64) typedef struct __stat64 Tcl_StatBuf; # elif (defined(_MSC_VER) && (_MSC_VER < 1400)) || defined(_USE_32BIT_TIME_T) typedef struct _stati64 Tcl_StatBuf; # else typedef struct _stat32i64 Tcl_StatBuf; # endif /* _MSC_VER < 1400 */ #elif defined(__CYGWIN__) typedef struct { dev_t st_dev; unsigned short st_ino; unsigned short st_mode; short st_nlink; short st_uid; short st_gid; /* Here is a 2-byte gap */ dev_t st_rdev; /* Here is a 4-byte gap */ long long st_size; struct {long tv_sec;} st_atim; struct {long tv_sec;} st_mtim; struct {long tv_sec;} st_ctim; /* Here is a 4-byte gap */ } Tcl_StatBuf; #elif defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__) typedef struct stat64 Tcl_StatBuf; #else typedef struct stat Tcl_StatBuf; #endif /* *---------------------------------------------------------------------------- * Data structures defined opaquely in this module. The definitions below just * provide dummy types. A few fields are made visible in Tcl_Interp * structures, namely those used for returning a string result from commands. * Direct access to the result field is discouraged in Tcl 8.0. The * interpreter result is either an object or a string, and the two values are * kept consistent unless some C code sets interp->result directly. * Programmers should use either the function Tcl_GetObjResult() or * Tcl_GetStringResult() to read the interpreter's result. See the SetResult * man page for details. * * Note: any change to the Tcl_Interp definition below must be mirrored in the * "real" definition in tclInt.h. * * Note: Tcl_ObjCmdProc functions do not directly set result and freeProc. * Instead, they set a Tcl_Obj member in the "real" structure that can be * accessed with Tcl_GetObjResult() and Tcl_SetObjResult(). */ typedef struct Tcl_Interp #ifndef TCL_NO_DEPRECATED { /* TIP #330: Strongly discourage extensions from using the string * result. */ #ifdef USE_INTERP_RESULT char *result TCL_DEPRECATED_API("use Tcl_GetStringResult/Tcl_SetResult"); /* If the last command returned a string * result, this points to it. */ void (*freeProc) (char *blockPtr) TCL_DEPRECATED_API("use Tcl_GetStringResult/Tcl_SetResult"); /* Zero means the string result is statically * allocated. TCL_DYNAMIC means it was * allocated with ckalloc and should be freed * with ckfree. Other values give the address * of function to invoke to free the result. * Tcl_Eval must free it before executing next * command. */ #else char *resultDontUse; /* Don't use in extensions! */ void (*freeProcDontUse) (char *); /* Don't use in extensions! */ #endif #ifdef USE_INTERP_ERRORLINE int errorLine TCL_DEPRECATED_API("use Tcl_GetErrorLine/Tcl_SetErrorLine"); /* When TCL_ERROR is returned, this gives the * line number within the command where the * error occurred (1 if first line). */ #else int errorLineDontUse; /* Don't use in extensions! */ #endif } #endif /* TCL_NO_DEPRECATED */ Tcl_Interp; typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler; typedef struct Tcl_Channel_ *Tcl_Channel; typedef struct Tcl_ChannelTypeVersion_ *Tcl_ChannelTypeVersion; typedef struct Tcl_Command_ *Tcl_Command; typedef struct Tcl_Condition_ *Tcl_Condition; typedef struct Tcl_Dict_ *Tcl_Dict; typedef struct Tcl_EncodingState_ *Tcl_EncodingState; typedef struct Tcl_Encoding_ *Tcl_Encoding; typedef struct Tcl_Event Tcl_Event; typedef struct Tcl_InterpState_ *Tcl_InterpState; typedef struct Tcl_LoadHandle_ *Tcl_LoadHandle; typedef struct Tcl_Mutex_ *Tcl_Mutex; typedef struct Tcl_Pid_ *Tcl_Pid; typedef struct Tcl_RegExp_ *Tcl_RegExp; typedef struct Tcl_ThreadDataKey_ *Tcl_ThreadDataKey; typedef struct Tcl_ThreadId_ *Tcl_ThreadId; typedef struct Tcl_TimerToken_ *Tcl_TimerToken; typedef struct Tcl_Trace_ *Tcl_Trace; typedef struct Tcl_Var_ *Tcl_Var; typedef struct Tcl_ZLibStream_ *Tcl_ZlibStream; /* *---------------------------------------------------------------------------- * Definition of the interface to functions implementing threads. A function * following this definition is given to each call of 'Tcl_CreateThread' and * will be called as the main fuction of the new thread created by that call. */ #if defined _WIN32 typedef unsigned (__stdcall Tcl_ThreadCreateProc) (ClientData clientData); #else typedef void (Tcl_ThreadCreateProc) (ClientData clientData); #endif /* * Threading function return types used for abstracting away platform * differences when writing a Tcl_ThreadCreateProc. See the NewThread function * in generic/tclThreadTest.c for it's usage. */ #if defined _WIN32 # define Tcl_ThreadCreateType unsigned __stdcall # define TCL_THREAD_CREATE_RETURN return 0 #else # define Tcl_ThreadCreateType void # define TCL_THREAD_CREATE_RETURN #endif /* * Definition of values for default stacksize and the possible flags to be * given to Tcl_CreateThread. */ #define TCL_THREAD_STACK_DEFAULT (0) /* Use default size for stack. */ #define TCL_THREAD_NOFLAGS (0000) /* Standard flags, default * behaviour. */ #define TCL_THREAD_JOINABLE (0001) /* Mark the thread as joinable. */ /* * Flag values passed to Tcl_StringCaseMatch. */ #define TCL_MATCH_NOCASE (1<<0) /* * Flag values passed to Tcl_GetRegExpFromObj. */ #define TCL_REG_BASIC 000000 /* BREs (convenience). */ #define TCL_REG_EXTENDED 000001 /* EREs. */ #define TCL_REG_ADVF 000002 /* Advanced features in EREs. */ #define TCL_REG_ADVANCED 000003 /* AREs (which are also EREs). */ #define TCL_REG_QUOTE 000004 /* No special characters, none. */ #define TCL_REG_NOCASE 000010 /* Ignore case. */ #define TCL_REG_NOSUB 000020 /* Don't care about subexpressions. */ #define TCL_REG_EXPANDED 000040 /* Expanded format, white space & * comments. */ #define TCL_REG_NLSTOP 000100 /* \n doesn't match . or [^ ] */ #define TCL_REG_NLANCH 000200 /* ^ matches after \n, $ before. */ #define TCL_REG_NEWLINE 000300 /* Newlines are line terminators. */ #define TCL_REG_CANMATCH 001000 /* Report details on partial/limited * matches. */ /* * Flags values passed to Tcl_RegExpExecObj. */ #define TCL_REG_NOTBOL 0001 /* Beginning of string does not match ^. */ #define TCL_REG_NOTEOL 0002 /* End of string does not match $. */ /* * Structures filled in by Tcl_RegExpInfo. Note that all offset values are * relative to the start of the match string, not the beginning of the entire * string. */ typedef struct Tcl_RegExpIndices { long start; /* Character offset of first character in * match. */ long end; /* Character offset of first character after * the match. */ } Tcl_RegExpIndices; typedef struct Tcl_RegExpInfo { int nsubs; /* Number of subexpressions in the compiled * expression. */ Tcl_RegExpIndices *matches; /* Array of nsubs match offset pairs. */ long extendStart; /* The offset at which a subsequent match * might begin. */ long reserved; /* Reserved for later use. */ } Tcl_RegExpInfo; /* * Picky compilers complain if this typdef doesn't appear before the struct's * reference in tclDecls.h. */ typedef Tcl_StatBuf *Tcl_Stat_; typedef struct stat *Tcl_OldStat_; /* *---------------------------------------------------------------------------- * When a TCL command returns, the interpreter contains a result from the * command. Programmers are strongly encouraged to use one of the functions * Tcl_GetObjResult() or Tcl_GetStringResult() to read the interpreter's * result. See the SetResult man page for details. Besides this result, the * command function returns an integer code, which is one of the following: * * TCL_OK Command completed normally; the interpreter's result * contains the command's result. * TCL_ERROR The command couldn't be completed successfully; the * interpreter's result describes what went wrong. * TCL_RETURN The command requests that the current function return; * the interpreter's result contains the function's * return value. * TCL_BREAK The command requests that the innermost loop be * exited; the interpreter's result is meaningless. * TCL_CONTINUE Go on to the next iteration of the current loop; the * interpreter's result is meaningless. */ #define TCL_OK 0 #define TCL_ERROR 1 #define TCL_RETURN 2 #define TCL_BREAK 3 #define TCL_CONTINUE 4 #define TCL_RESULT_SIZE 200 /* *---------------------------------------------------------------------------- * Flags to control what substitutions are performed by Tcl_SubstObj(): */ #define TCL_SUBST_COMMANDS 001 #define TCL_SUBST_VARIABLES 002 #define TCL_SUBST_BACKSLASHES 004 #define TCL_SUBST_ALL 007 /* * Argument descriptors for math function callbacks in expressions: */ typedef enum { TCL_INT, TCL_DOUBLE, TCL_EITHER, TCL_WIDE_INT } Tcl_ValueType; typedef struct Tcl_Value { Tcl_ValueType type; /* Indicates intValue or doubleValue is valid, * or both. */ long intValue; /* Integer value. */ double doubleValue; /* Double-precision floating value. */ Tcl_WideInt wideValue; /* Wide (min. 64-bit) integer value. */ } Tcl_Value; /* * Forward declaration of Tcl_Obj to prevent an error when the forward * reference to Tcl_Obj is encountered in the function types declared below. */ struct Tcl_Obj; /* *---------------------------------------------------------------------------- * Function types defined by Tcl: */ typedef int (Tcl_AppInitProc) (Tcl_Interp *interp); typedef int (Tcl_AsyncProc) (ClientData clientData, Tcl_Interp *interp, int code); typedef void (Tcl_ChannelProc) (ClientData clientData, int mask); typedef void (Tcl_CloseProc) (ClientData data); typedef void (Tcl_CmdDeleteProc) (ClientData clientData); typedef int (Tcl_CmdProc) (ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[]); typedef void (Tcl_CmdTraceProc) (ClientData clientData, Tcl_Interp *interp, int level, char *command, Tcl_CmdProc *proc, ClientData cmdClientData, int argc, CONST84 char *argv[]); typedef int (Tcl_CmdObjTraceProc) (ClientData clientData, Tcl_Interp *interp, int level, const char *command, Tcl_Command commandInfo, int objc, struct Tcl_Obj *const *objv); typedef void (Tcl_CmdObjTraceDeleteProc) (ClientData clientData); typedef void (Tcl_DupInternalRepProc) (struct Tcl_Obj *srcPtr, struct Tcl_Obj *dupPtr); typedef int (Tcl_EncodingConvertProc) (ClientData clientData, const char *src, int srcLen, int flags, Tcl_EncodingState *statePtr, char *dst, int dstLen, int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr); typedef void (Tcl_EncodingFreeProc) (ClientData clientData); typedef int (Tcl_EventProc) (Tcl_Event *evPtr, int flags); typedef void (Tcl_EventCheckProc) (ClientData clientData, int flags); typedef int (Tcl_EventDeleteProc) (Tcl_Event *evPtr, ClientData clientData); typedef void (Tcl_EventSetupProc) (ClientData clientData, int flags); typedef void (Tcl_ExitProc) (ClientData clientData); typedef void (Tcl_FileProc) (ClientData clientData, int mask); typedef void (Tcl_FileFreeProc) (ClientData clientData); typedef void (Tcl_FreeInternalRepProc) (struct Tcl_Obj *objPtr); typedef void (Tcl_FreeProc) (char *blockPtr); typedef void (Tcl_IdleProc) (ClientData clientData); typedef void (Tcl_InterpDeleteProc) (ClientData clientData, Tcl_Interp *interp); typedef int (Tcl_MathProc) (ClientData clientData, Tcl_Interp *interp, Tcl_Value *args, Tcl_Value *resultPtr); 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 void (Tcl_PanicProc) (const char *format, ...); typedef void (Tcl_TcpAcceptProc) (ClientData callbackData, Tcl_Channel chan, char *address, int port); typedef void (Tcl_TimerProc) (ClientData clientData); typedef int (Tcl_SetFromAnyProc) (Tcl_Interp *interp, struct Tcl_Obj *objPtr); typedef void (Tcl_UpdateStringProc) (struct Tcl_Obj *objPtr); typedef char * (Tcl_VarTraceProc) (ClientData clientData, Tcl_Interp *interp, CONST84 char *part1, CONST84 char *part2, int flags); typedef void (Tcl_CommandTraceProc) (ClientData clientData, Tcl_Interp *interp, const char *oldName, const char *newName, int flags); typedef void (Tcl_CreateFileHandlerProc) (int fd, int mask, Tcl_FileProc *proc, ClientData clientData); typedef void (Tcl_DeleteFileHandlerProc) (int fd); typedef void (Tcl_AlertNotifierProc) (ClientData clientData); typedef void (Tcl_ServiceModeHookProc) (int mode); typedef ClientData (Tcl_InitNotifierProc) (void); typedef void (Tcl_FinalizeNotifierProc) (ClientData clientData); typedef void (Tcl_MainLoopProc) (void); /* *---------------------------------------------------------------------------- * The following structure represents a type of object, which is a particular * internal representation for an object plus a set of functions that provide * standard operations on objects of that type. */ typedef struct Tcl_ObjType { const char *name; /* Name of the type, e.g. "int". */ Tcl_FreeInternalRepProc *freeIntRepProc; /* Called to free any storage for the type's * internal rep. NULL if the internal rep does * not need freeing. */ Tcl_DupInternalRepProc *dupIntRepProc; /* Called to create a new object as a copy of * an existing object. */ Tcl_UpdateStringProc *updateStringProc; /* Called to update the string rep from the * type's internal representation. */ Tcl_SetFromAnyProc *setFromAnyProc; /* Called to convert the object's internal rep * to this type. Frees the internal rep of the * old type. Returns TCL_ERROR on failure. */ } Tcl_ObjType; /* * One of the following structures exists for each object in the Tcl system. * An object stores a value as either a string, some internal representation, * or both. */ typedef struct Tcl_Obj { int refCount; /* When 0 the object will be freed. */ char *bytes; /* This points to the first byte of the * object's string representation. The array * must be followed by a null byte (i.e., at * offset length) but may also contain * embedded null characters. The array's * storage is allocated by ckalloc. NULL means * the string rep is invalid and must be * regenerated from the internal rep. Clients * should use Tcl_GetStringFromObj or * Tcl_GetString to get a pointer to the byte * array as a readonly value. */ int length; /* The number of bytes at *bytes, not * including the terminating null. */ const Tcl_ObjType *typePtr; /* Denotes the object's type. Always * corresponds to the type of the object's * internal rep. NULL indicates the object has * no internal rep (has no type). */ union { /* The internal representation: */ long longValue; /* - an long integer value. */ double doubleValue; /* - a double-precision floating value. */ void *otherValuePtr; /* - another, type-specific value, not used internally any more. */ Tcl_WideInt wideValue; /* - a long long value. */ struct { /* - internal rep as two pointers. * the main use of which is a bignum's * tightly packed fields, where the alloc, * used and signum flags are packed into * ptr2 with everything else hung off ptr1. */ void *ptr1; void *ptr2; } twoPtrValue; struct { /* - internal rep as a pointer and a long, not used internally any more. */ void *ptr; unsigned long value; } ptrAndLongRep; } internalRep; } Tcl_Obj; /* * Macros to increment and decrement a Tcl_Obj's reference count, and to test * whether an object is shared (i.e. has reference count > 1). Note: clients * should use Tcl_DecrRefCount() when they are finished using an object, and * should never call TclFreeObj() directly. TclFreeObj() is only defined and * made public in tcl.h to support Tcl_DecrRefCount's macro definition. */ void Tcl_IncrRefCount(Tcl_Obj *objPtr); void Tcl_DecrRefCount(Tcl_Obj *objPtr); int Tcl_IsShared(Tcl_Obj *objPtr); /* *---------------------------------------------------------------------------- * The following structure contains the state needed by Tcl_SaveResult. No-one * outside of Tcl should access any of these fields. This structure is * typically allocated on the stack. */ typedef struct Tcl_SavedResult { char *result; Tcl_FreeProc *freeProc; Tcl_Obj *objResultPtr; char *appendResult; int appendAvl; int appendUsed; char resultSpace[TCL_RESULT_SIZE+1]; } Tcl_SavedResult; /* *---------------------------------------------------------------------------- * The following definitions support Tcl's namespace facility. Note: the first * five fields must match exactly the fields in a Namespace structure (see * tclInt.h). */ typedef struct Tcl_Namespace { char *name; /* The namespace's name within its parent * namespace. This contains no ::'s. The name * of the global namespace is "" although "::" * is an synonym. */ char *fullName; /* The namespace's fully qualified name. This * starts with ::. */ ClientData clientData; /* Arbitrary value associated with this * namespace. */ Tcl_NamespaceDeleteProc *deleteProc; /* Function invoked when deleting the * namespace to, e.g., free clientData. */ struct Tcl_Namespace *parentPtr; /* Points to the namespace that contains this * one. NULL if this is the global * namespace. */ } Tcl_Namespace; /* *---------------------------------------------------------------------------- * The following structure represents a call frame, or activation record. A * call frame defines a naming context for a procedure call: its local scope * (for local variables) and its namespace scope (used for non-local * variables; often the global :: namespace). A call frame can also define the * naming context for a namespace eval or namespace inscope command: the * namespace in which the command's code should execute. The Tcl_CallFrame * structures exist only while procedures or namespace eval/inscope's are * being executed, and provide a Tcl call stack. * * A call frame is initialized and pushed using Tcl_PushCallFrame and popped * using Tcl_PopCallFrame. Storage for a Tcl_CallFrame must be provided by the * Tcl_PushCallFrame caller, and callers typically allocate them on the C call * stack for efficiency. For this reason, Tcl_CallFrame is defined as a * structure and not as an opaque token. However, most Tcl_CallFrame fields * are hidden since applications should not access them directly; others are * declared as "dummyX". * * WARNING!! The structure definition must be kept consistent with the * CallFrame structure in tclInt.h. If you change one, change the other. */ typedef struct Tcl_CallFrame { Tcl_Namespace *nsPtr; int dummy1; int dummy2; void *dummy3; void *dummy4; void *dummy5; int dummy6; void *dummy7; void *dummy8; int dummy9; void *dummy10; void *dummy11; void *dummy12; void *dummy13; } Tcl_CallFrame; /* *---------------------------------------------------------------------------- * Information about commands that is returned by Tcl_GetCommandInfo and * passed to Tcl_SetCommandInfo. objProc is an objc/objv object-based command * function while proc is a traditional Tcl argc/argv string-based function. * Tcl_CreateObjCommand and Tcl_CreateCommand ensure that both objProc and * proc are non-NULL and can be called to execute the command. However, it may * be faster to call one instead of the other. The member isNativeObjectProc * is set to 1 if an object-based function was registered by * Tcl_CreateObjCommand, and to 0 if a string-based function was registered by * Tcl_CreateCommand. The other function is typically set to a compatibility * wrapper that does string-to-object or object-to-string argument conversions * then calls the other function. */ typedef struct Tcl_CmdInfo { int isNativeObjectProc; /* 1 if objProc was registered by a call to * Tcl_CreateObjCommand; 0 otherwise. * Tcl_SetCmdInfo does not modify this * field. */ Tcl_ObjCmdProc *objProc; /* Command's object-based function. */ ClientData objClientData; /* ClientData for object proc. */ Tcl_CmdProc *proc; /* Command's string-based function. */ ClientData clientData; /* ClientData for string proc. */ Tcl_CmdDeleteProc *deleteProc; /* Function to call when command is * deleted. */ ClientData deleteData; /* Value to pass to deleteProc (usually the * same as clientData). */ Tcl_Namespace *namespacePtr;/* Points to the namespace that contains this * command. Note that Tcl_SetCmdInfo will not * change a command's namespace; use * TclRenameCommand or Tcl_Eval (of 'rename') * to do that. */ } Tcl_CmdInfo; /* *---------------------------------------------------------------------------- * The structure defined below is used to hold dynamic strings. The only * fields that clients should use are string and length, accessible via the * macros Tcl_DStringValue and Tcl_DStringLength. */ #define TCL_DSTRING_STATIC_SIZE 200 typedef struct Tcl_DString { char *string; /* Points to beginning of string: either * staticSpace below or a malloced array. */ int length; /* Number of non-NULL characters in the * string. */ int spaceAvl; /* Total number of bytes available for the * string and its terminating NULL char. */ char staticSpace[TCL_DSTRING_STATIC_SIZE]; /* Space to use in common case where string is * small. */ } Tcl_DString; #define Tcl_DStringLength(dsPtr) ((dsPtr)->length) #define Tcl_DStringValue(dsPtr) ((dsPtr)->string) #define Tcl_DStringTrunc Tcl_DStringSetLength /* * Definitions for the maximum number of digits of precision that may be * specified in the "tcl_precision" variable, and the number of bytes of * buffer space required by Tcl_PrintDouble. */ #define TCL_MAX_PREC 17 #define TCL_DOUBLE_SPACE (TCL_MAX_PREC+10) /* * Definition for a number of bytes of buffer space sufficient to hold the * string representation of an integer in base 10 (assuming the existence of * 64-bit integers). */ #define TCL_INTEGER_SPACE 24 /* * Flag values passed to Tcl_ConvertElement. * TCL_DONT_USE_BRACES forces it not to enclose the element in braces, but to * use backslash quoting instead. * TCL_DONT_QUOTE_HASH disables the default quoting of the '#' character. It * is safe to leave the hash unquoted when the element is not the first * element of a list, and this flag can be used by the caller to indicate * that condition. */ #define TCL_DONT_USE_BRACES 1 #define TCL_DONT_QUOTE_HASH 8 /* * Flag that may be passed to Tcl_GetIndexFromObj to force it to disallow * abbreviated strings. */ #define TCL_EXACT 1 /* *---------------------------------------------------------------------------- * Flag values passed to Tcl_RecordAndEval, Tcl_EvalObj, Tcl_EvalObjv. * WARNING: these bit choices must not conflict with the bit choices for * evalFlag bits in tclInt.h! * * Meanings: * TCL_NO_EVAL: Just record this command * TCL_EVAL_GLOBAL: Execute script in global namespace * TCL_EVAL_DIRECT: Do not compile this script * TCL_EVAL_INVOKE: Magical Tcl_EvalObjv mode for aliases/ensembles * o Run in iPtr->lookupNsPtr or global namespace * o Cut out of error traces * o Don't reset the flags controlling ensemble * error message rewriting. * TCL_CANCEL_UNWIND: Magical Tcl_CancelEval mode that causes the * stack for the script in progress to be * completely unwound. * TCL_EVAL_NOERR: Do no exception reporting at all, just return * as the caller will report. */ #define TCL_NO_EVAL 0x010000 #define TCL_EVAL_GLOBAL 0x020000 #define TCL_EVAL_DIRECT 0x040000 #define TCL_EVAL_INVOKE 0x080000 #define TCL_CANCEL_UNWIND 0x100000 #define TCL_EVAL_NOERR 0x200000 /* * Special freeProc values that may be passed to Tcl_SetResult (see the man * page for details): */ #define TCL_VOLATILE ((Tcl_FreeProc *) 1) #define TCL_STATIC ((Tcl_FreeProc *) 0) #define TCL_DYNAMIC ((Tcl_FreeProc *) 3) /* * Flag values passed to variable-related functions. * WARNING: these bit choices must not conflict with the bit choice for * TCL_CANCEL_UNWIND, above. */ #define TCL_GLOBAL_ONLY 1 #define TCL_NAMESPACE_ONLY 2 #define TCL_APPEND_VALUE 4 #define TCL_LIST_ELEMENT 8 #define TCL_TRACE_READS 0x10 #define TCL_TRACE_WRITES 0x20 #define TCL_TRACE_UNSETS 0x40 #define TCL_TRACE_DESTROYED 0x80 #define TCL_INTERP_DESTROYED 0x100 #define TCL_LEAVE_ERR_MSG 0x200 #define TCL_TRACE_ARRAY 0x800 #ifndef TCL_REMOVE_OBSOLETE_TRACES /* Required to support old variable/vdelete/vinfo traces. */ #define TCL_TRACE_OLD_STYLE 0x1000 #endif /* Indicate the semantics of the result of a trace. */ #define TCL_TRACE_RESULT_DYNAMIC 0x8000 #define TCL_TRACE_RESULT_OBJECT 0x10000 /* * Flag values for ensemble commands. */ #define TCL_ENSEMBLE_PREFIX 0x02/* Flag value to say whether to allow * unambiguous prefixes of commands or to * require exact matches for command names. */ /* * Flag values passed to command-related functions. */ #define TCL_TRACE_RENAME 0x2000 #define TCL_TRACE_DELETE 0x4000 #define TCL_ALLOW_INLINE_COMPILATION 0x20000 /* * The TCL_PARSE_PART1 flag is deprecated and has no effect. The part1 is now * always parsed whenever the part2 is NULL. (This is to avoid a common error * when converting code to use the new object based APIs and forgetting to * give the flag) */ #ifndef TCL_NO_DEPRECATED # define TCL_PARSE_PART1 0x400 #endif /* * Types for linked variables: */ #define TCL_LINK_INT 1 #define TCL_LINK_DOUBLE 2 #define TCL_LINK_BOOLEAN 3 #define TCL_LINK_STRING 4 #define TCL_LINK_WIDE_INT 5 #define TCL_LINK_CHAR 6 #define TCL_LINK_UCHAR 7 #define TCL_LINK_SHORT 8 #define TCL_LINK_USHORT 9 #define TCL_LINK_UINT 10 #define TCL_LINK_LONG 11 #define TCL_LINK_ULONG 12 #define TCL_LINK_FLOAT 13 #define TCL_LINK_WIDE_UINT 14 #define TCL_LINK_READ_ONLY 0x80 /* *---------------------------------------------------------------------------- * Forward declarations of Tcl_HashTable and related types. */ typedef struct Tcl_HashKeyType Tcl_HashKeyType; typedef struct Tcl_HashTable Tcl_HashTable; typedef struct Tcl_HashEntry Tcl_HashEntry; typedef unsigned (Tcl_HashKeyProc) (Tcl_HashTable *tablePtr, void *keyPtr); typedef int (Tcl_CompareHashKeysProc) (void *keyPtr, Tcl_HashEntry *hPtr); typedef Tcl_HashEntry * (Tcl_AllocHashEntryProc) (Tcl_HashTable *tablePtr, void *keyPtr); typedef void (Tcl_FreeHashEntryProc) (Tcl_HashEntry *hPtr); /* * This flag controls whether the hash table stores the hash of a key, or * recalculates it. There should be no reason for turning this flag off as it * is completely binary and source compatible unless you directly access the * bucketPtr member of the Tcl_HashTableEntry structure. This member has been * removed and the space used to store the hash value. */ #ifndef TCL_HASH_KEY_STORE_HASH # define TCL_HASH_KEY_STORE_HASH 1 #endif /* * Structure definition for an entry in a hash table. No-one outside Tcl * should access any of these fields directly; use the macros defined below. */ struct Tcl_HashEntry { Tcl_HashEntry *nextPtr; /* Pointer to next entry in this hash bucket, * or NULL for end of chain. */ Tcl_HashTable *tablePtr; /* Pointer to table containing entry. */ #if TCL_HASH_KEY_STORE_HASH void *hash; /* Hash value, stored as pointer to ensure * that the offsets of the fields in this * structure are not changed. */ #else Tcl_HashEntry **bucketPtr; /* Pointer to bucket that points to first * entry in this entry's chain: used for * deleting the entry. */ #endif ClientData clientData; /* Application stores something here with * Tcl_SetHashValue. */ union { /* Key has one of these forms: */ char *oneWordValue; /* One-word value for key. */ Tcl_Obj *objPtr; /* Tcl_Obj * key value. */ int words[1]; /* Multiple integer words for key. The actual * size will be as large as necessary for this * table's keys. */ char string[1]; /* String for key. The actual size will be as * large as needed to hold the key. */ } key; /* MUST BE LAST FIELD IN RECORD!! */ }; /* * Flags used in Tcl_HashKeyType. * * TCL_HASH_KEY_RANDOMIZE_HASH - * There are some things, pointers for example * which don't hash well because they do not use * the lower bits. If this flag is set then the * hash table will attempt to rectify this by * randomising the bits and then using the upper * N bits as the index into the table. * TCL_HASH_KEY_SYSTEM_HASH - If this flag is set then all memory internally * allocated for the hash table that is not for an * entry will use the system heap. */ #define TCL_HASH_KEY_RANDOMIZE_HASH 0x1 #define TCL_HASH_KEY_SYSTEM_HASH 0x2 /* * Structure definition for the methods associated with a hash table key type. */ #define TCL_HASH_KEY_TYPE_VERSION 1 struct Tcl_HashKeyType { int version; /* Version of the table. If this structure is * extended in future then the version can be * used to distinguish between different * structures. */ int flags; /* Flags, see above for details. */ Tcl_HashKeyProc *hashKeyProc; /* Calculates a hash value for the key. If * this is NULL then the pointer itself is * used as a hash value. */ Tcl_CompareHashKeysProc *compareKeysProc; /* Compares two keys and returns zero if they * do not match, and non-zero if they do. If * this is NULL then the pointers are * compared. */ Tcl_AllocHashEntryProc *allocEntryProc; /* Called to allocate memory for a new entry, * i.e. if the key is a string then this could * allocate a single block which contains * enough space for both the entry and the * string. Only the key field of the allocated * Tcl_HashEntry structure needs to be filled * in. If something else needs to be done to * the key, i.e. incrementing a reference * count then that should be done by this * function. If this is NULL then Tcl_Alloc is * used to allocate enough space for a * Tcl_HashEntry and the key pointer is * assigned to key.oneWordValue. */ Tcl_FreeHashEntryProc *freeEntryProc; /* Called to free memory associated with an * entry. If something else needs to be done * to the key, i.e. decrementing a reference * count then that should be done by this * function. If this is NULL then Tcl_Free is * used to free the Tcl_HashEntry. */ }; /* * Structure definition for a hash table. Must be in tcl.h so clients can * allocate space for these structures, but clients should never access any * fields in this structure. */ #define TCL_SMALL_HASH_TABLE 4 struct Tcl_HashTable { Tcl_HashEntry **buckets; /* Pointer to bucket array. Each element * points to first entry in bucket's hash * chain, or NULL. */ Tcl_HashEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; /* Bucket array used for small tables (to * avoid mallocs and frees). */ int numBuckets; /* Total number of buckets allocated at * **bucketPtr. */ int numEntries; /* Total number of entries present in * table. */ int rebuildSize; /* Enlarge table when numEntries gets to be * this large. */ int downShift; /* Shift count used in hashing function. * Designed to use high-order bits of * randomized keys. */ int mask; /* Mask value used in hashing function. */ int keyType; /* Type of keys used in this table. It's * either TCL_CUSTOM_KEYS, TCL_STRING_KEYS, * TCL_ONE_WORD_KEYS, or an integer giving the * number of ints that is the size of the * key. */ Tcl_HashEntry *(*findProc) (Tcl_HashTable *tablePtr, const char *key); Tcl_HashEntry *(*createProc) (Tcl_HashTable *tablePtr, const char *key, int *newPtr); const Tcl_HashKeyType *typePtr; /* Type of the keys used in the * Tcl_HashTable. */ }; /* * Structure definition for information used to keep track of searches through * hash tables: */ typedef struct Tcl_HashSearch { Tcl_HashTable *tablePtr; /* Table being searched. */ int nextIndex; /* Index of next bucket to be enumerated after * present one. */ Tcl_HashEntry *nextEntryPtr;/* Next entry to be enumerated in the current * bucket. */ } Tcl_HashSearch; /* * Acceptable key types for hash tables: * * TCL_STRING_KEYS: The keys are strings, they are copied into the * entry. * TCL_ONE_WORD_KEYS: The keys are pointers, the pointer is stored * in the entry. * TCL_CUSTOM_TYPE_KEYS: The keys are arbitrary types which are copied * into the entry. * TCL_CUSTOM_PTR_KEYS: The keys are pointers to arbitrary types, the * pointer is stored in the entry. * * While maintaining binary compatability the above have to be distinct values * as they are used to differentiate between old versions of the hash table * which don't have a typePtr and new ones which do. Once binary compatability * is discarded in favour of making more wide spread changes TCL_STRING_KEYS * can be the same as TCL_CUSTOM_TYPE_KEYS, and TCL_ONE_WORD_KEYS can be the * same as TCL_CUSTOM_PTR_KEYS because they simply determine how the key is * accessed from the entry and not the behaviour. */ #define TCL_STRING_KEYS (0) #define TCL_ONE_WORD_KEYS (1) #define TCL_CUSTOM_TYPE_KEYS (-2) #define TCL_CUSTOM_PTR_KEYS (-1) /* * Structure definition for information used to keep track of searches through * dictionaries. These fields should not be accessed by code outside * tclDictObj.c */ typedef struct { void *next; /* Search position for underlying hash * table. */ int epoch; /* Epoch marker for dictionary being searched, * or -1 if search has terminated. */ Tcl_Dict dictionaryPtr; /* Reference to dictionary being searched. */ } Tcl_DictSearch; /* *---------------------------------------------------------------------------- * Flag values to pass to Tcl_DoOneEvent to disable searches for some kinds of * events: */ #define TCL_DONT_WAIT (1<<1) #define TCL_WINDOW_EVENTS (1<<2) #define TCL_FILE_EVENTS (1<<3) #define TCL_TIMER_EVENTS (1<<4) #define TCL_IDLE_EVENTS (1<<5) /* WAS 0x10 ???? */ #define TCL_ALL_EVENTS (~TCL_DONT_WAIT) /* * The following structure defines a generic event for the Tcl event system. * These are the things that are queued in calls to Tcl_QueueEvent and * serviced later by Tcl_DoOneEvent. There can be many different kinds of * events with different fields, corresponding to window events, timer events, * etc. The structure for a particular event consists of a Tcl_Event header * followed by additional information specific to that event. */ struct Tcl_Event { Tcl_EventProc *proc; /* Function to call to service this event. */ struct Tcl_Event *nextPtr; /* Next in list of pending events, or NULL. */ }; /* * Positions to pass to Tcl_QueueEvent: */ typedef enum { TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK } Tcl_QueuePosition; /* * Values to pass to Tcl_SetServiceMode to specify the behavior of notifier * event routines. */ #define TCL_SERVICE_NONE 0 #define TCL_SERVICE_ALL 1 /* * The following structure keeps is used to hold a time value, either as an * absolute time (the number of seconds from the epoch) or as an elapsed time. * On Unix systems the epoch is Midnight Jan 1, 1970 GMT. */ typedef struct Tcl_Time { long sec; /* Seconds. */ long usec; /* Microseconds. */ } Tcl_Time; typedef void (Tcl_SetTimerProc) (CONST86 Tcl_Time *timePtr); typedef int (Tcl_WaitForEventProc) (CONST86 Tcl_Time *timePtr); /* * TIP #233 (Virtualized Time) */ typedef void (Tcl_GetTimeProc) (Tcl_Time *timebuf, ClientData clientData); typedef void (Tcl_ScaleTimeProc) (Tcl_Time *timebuf, ClientData clientData); /* *---------------------------------------------------------------------------- * Bits to pass to Tcl_CreateFileHandler and Tcl_CreateChannelHandler to * indicate what sorts of events are of interest: */ #define TCL_READABLE (1<<1) #define TCL_WRITABLE (1<<2) #define TCL_EXCEPTION (1<<3) /* * Flag values to pass to Tcl_OpenCommandChannel to indicate the disposition * of the stdio handles. TCL_STDIN, TCL_STDOUT, TCL_STDERR, are also used in * Tcl_GetStdChannel. */ #define TCL_STDIN (1<<1) #define TCL_STDOUT (1<<2) #define TCL_STDERR (1<<3) #define TCL_ENFORCE_MODE (1<<4) /* * Bits passed to Tcl_DriverClose2Proc to indicate which side of a channel * should be closed. */ #define TCL_CLOSE_READ (1<<1) #define TCL_CLOSE_WRITE (1<<2) /* * Value to use as the closeProc for a channel that supports the close2Proc * interface. */ #define TCL_CLOSE2PROC ((Tcl_DriverCloseProc *) 1) /* * Channel version tag. This was introduced in 8.3.2/8.4. */ #define TCL_CHANNEL_VERSION_1 ((Tcl_ChannelTypeVersion) 0x1) #define TCL_CHANNEL_VERSION_2 ((Tcl_ChannelTypeVersion) 0x2) #define TCL_CHANNEL_VERSION_3 ((Tcl_ChannelTypeVersion) 0x3) #define TCL_CHANNEL_VERSION_4 ((Tcl_ChannelTypeVersion) 0x4) #define TCL_CHANNEL_VERSION_5 ((Tcl_ChannelTypeVersion) 0x5) /* * TIP #218: Channel Actions, Ids for Tcl_DriverThreadActionProc. */ #define TCL_CHANNEL_THREAD_INSERT (0) #define TCL_CHANNEL_THREAD_REMOVE (1) /* * Typedefs for the various operations in a channel type: */ typedef int (Tcl_DriverBlockModeProc) (ClientData instanceData, int mode); typedef int (Tcl_DriverCloseProc) (ClientData instanceData, Tcl_Interp *interp); typedef int (Tcl_DriverClose2Proc) (ClientData instanceData, Tcl_Interp *interp, int flags); typedef int (Tcl_DriverInputProc) (ClientData instanceData, char *buf, int toRead, int *errorCodePtr); typedef int (Tcl_DriverOutputProc) (ClientData instanceData, CONST84 char *buf, int toWrite, int *errorCodePtr); typedef int (Tcl_DriverSeekProc) (ClientData instanceData, long offset, int mode, int *errorCodePtr); typedef int (Tcl_DriverSetOptionProc) (ClientData instanceData, Tcl_Interp *interp, const char *optionName, const char *value); typedef int (Tcl_DriverGetOptionProc) (ClientData instanceData, Tcl_Interp *interp, CONST84 char *optionName, Tcl_DString *dsPtr); typedef void (Tcl_DriverWatchProc) (ClientData instanceData, int mask); typedef int (Tcl_DriverGetHandleProc) (ClientData instanceData, int direction, ClientData *handlePtr); typedef int (Tcl_DriverFlushProc) (ClientData instanceData); typedef int (Tcl_DriverHandlerProc) (ClientData instanceData, int interestMask); typedef Tcl_WideInt (Tcl_DriverWideSeekProc) (ClientData instanceData, Tcl_WideInt offset, int mode, int *errorCodePtr); /* * TIP #218, Channel Thread Actions */ typedef void (Tcl_DriverThreadActionProc) (ClientData instanceData, int action); /* * TIP #208, File Truncation (etc.) */ typedef int (Tcl_DriverTruncateProc) (ClientData instanceData, Tcl_WideInt length); /* * struct Tcl_ChannelType: * * One such structure exists for each type (kind) of channel. It collects * together in one place all the functions that are part of the specific * channel type. * * It is recommend that the Tcl_Channel* functions are used to access elements * of this structure, instead of direct accessing. */ typedef struct Tcl_ChannelType { const char *typeName; /* The name of the channel type in Tcl * commands. This storage is owned by channel * type. */ Tcl_ChannelTypeVersion version; /* Version of the channel type. */ Tcl_DriverCloseProc *closeProc; /* Function to call to close the channel, or * TCL_CLOSE2PROC if the close2Proc should be * used instead. */ Tcl_DriverInputProc *inputProc; /* Function to call for input on channel. */ Tcl_DriverOutputProc *outputProc; /* Function to call for output on channel. */ Tcl_DriverSeekProc *seekProc; /* Function to call to seek on the channel. * May be NULL. */ Tcl_DriverSetOptionProc *setOptionProc; /* Set an option on a channel. */ Tcl_DriverGetOptionProc *getOptionProc; /* Get an option from a channel. */ Tcl_DriverWatchProc *watchProc; /* Set up the notifier to watch for events on * this channel. */ Tcl_DriverGetHandleProc *getHandleProc; /* Get an OS handle from the channel or NULL * if not supported. */ Tcl_DriverClose2Proc *close2Proc; /* Function to call to close the channel if * the device supports closing the read & * write sides independently. */ Tcl_DriverBlockModeProc *blockModeProc; /* Set blocking mode for the raw channel. May * be NULL. */ /* * Only valid in TCL_CHANNEL_VERSION_2 channels or later. */ Tcl_DriverFlushProc *flushProc; /* Function to call to flush a channel. May be * NULL. */ Tcl_DriverHandlerProc *handlerProc; /* Function to call to handle a channel event. * This will be passed up the stacked channel * chain. */ /* * Only valid in TCL_CHANNEL_VERSION_3 channels or later. */ Tcl_DriverWideSeekProc *wideSeekProc; /* Function to call to seek on the channel * which can handle 64-bit offsets. May be * NULL, and must be NULL if seekProc is * NULL. */ /* * Only valid in TCL_CHANNEL_VERSION_4 channels or later. * TIP #218, Channel Thread Actions. */ Tcl_DriverThreadActionProc *threadActionProc; /* Function to call to notify the driver of * thread specific activity for a channel. May * be NULL. */ /* * Only valid in TCL_CHANNEL_VERSION_5 channels or later. * TIP #208, File Truncation. */ Tcl_DriverTruncateProc *truncateProc; /* Function to call to truncate the underlying * file to a particular length. May be NULL if * the channel does not support truncation. */ } Tcl_ChannelType; /* * The following flags determine whether the blockModeProc above should set * the channel into blocking or nonblocking mode. They are passed as arguments * to the blockModeProc function in the above structure. */ #define TCL_MODE_BLOCKING 0 /* Put channel into blocking mode. */ #define TCL_MODE_NONBLOCKING 1 /* Put channel into nonblocking * mode. */ /* *---------------------------------------------------------------------------- * Enum for different types of file paths. */ typedef enum Tcl_PathType { TCL_PATH_ABSOLUTE, TCL_PATH_RELATIVE, TCL_PATH_VOLUME_RELATIVE } Tcl_PathType; /* * The following structure is used to pass glob type data amongst the various * glob routines and Tcl_FSMatchInDirectory. */ typedef struct Tcl_GlobTypeData { int type; /* Corresponds to bcdpfls as in 'find -t'. */ int perm; /* Corresponds to file permissions. */ Tcl_Obj *macType; /* Acceptable Mac type. */ Tcl_Obj *macCreator; /* Acceptable Mac creator. */ } Tcl_GlobTypeData; /* * Type and permission definitions for glob command. */ #define TCL_GLOB_TYPE_BLOCK (1<<0) #define TCL_GLOB_TYPE_CHAR (1<<1) #define TCL_GLOB_TYPE_DIR (1<<2) #define TCL_GLOB_TYPE_PIPE (1<<3) #define TCL_GLOB_TYPE_FILE (1<<4) #define TCL_GLOB_TYPE_LINK (1<<5) #define TCL_GLOB_TYPE_SOCK (1<<6) #define TCL_GLOB_TYPE_MOUNT (1<<7) #define TCL_GLOB_PERM_RONLY (1<<0) #define TCL_GLOB_PERM_HIDDEN (1<<1) #define TCL_GLOB_PERM_R (1<<2) #define TCL_GLOB_PERM_W (1<<3) #define TCL_GLOB_PERM_X (1<<4) /* * Flags for the unload callback function. */ #define TCL_UNLOAD_DETACH_FROM_INTERPRETER (1<<0) #define TCL_UNLOAD_DETACH_FROM_PROCESS (1<<1) /* * Typedefs for the various filesystem operations: */ typedef int (Tcl_FSStatProc) (Tcl_Obj *pathPtr, Tcl_StatBuf *buf); typedef int (Tcl_FSAccessProc) (Tcl_Obj *pathPtr, int mode); typedef Tcl_Channel (Tcl_FSOpenFileChannelProc) (Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions); typedef int (Tcl_FSMatchInDirectoryProc) (Tcl_Interp *interp, Tcl_Obj *result, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types); typedef Tcl_Obj * (Tcl_FSGetCwdProc) (Tcl_Interp *interp); typedef int (Tcl_FSChdirProc) (Tcl_Obj *pathPtr); typedef int (Tcl_FSLstatProc) (Tcl_Obj *pathPtr, Tcl_StatBuf *buf); typedef int (Tcl_FSCreateDirectoryProc) (Tcl_Obj *pathPtr); typedef int (Tcl_FSDeleteFileProc) (Tcl_Obj *pathPtr); typedef int (Tcl_FSCopyDirectoryProc) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr); typedef int (Tcl_FSCopyFileProc) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); typedef int (Tcl_FSRemoveDirectoryProc) (Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr); typedef int (Tcl_FSRenameFileProc) (Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr); typedef void (Tcl_FSUnloadFileProc) (Tcl_LoadHandle loadHandle); typedef Tcl_Obj * (Tcl_FSListVolumesProc) (void); /* We have to declare the utime structure here. */ struct utimbuf; typedef int (Tcl_FSUtimeProc) (Tcl_Obj *pathPtr, struct utimbuf *tval); typedef int (Tcl_FSNormalizePathProc) (Tcl_Interp *interp, Tcl_Obj *pathPtr, int nextCheckpoint); typedef int (Tcl_FSFileAttrsGetProc) (Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); typedef const char *CONST86 * (Tcl_FSFileAttrStringsProc) (Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef); typedef int (Tcl_FSFileAttrsSetProc) (Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj *objPtr); typedef Tcl_Obj * (Tcl_FSLinkProc) (Tcl_Obj *pathPtr, Tcl_Obj *toPtr, int linkType); typedef int (Tcl_FSLoadFileProc) (Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr); typedef int (Tcl_FSPathInFilesystemProc) (Tcl_Obj *pathPtr, ClientData *clientDataPtr); typedef Tcl_Obj * (Tcl_FSFilesystemPathTypeProc) (Tcl_Obj *pathPtr); typedef Tcl_Obj * (Tcl_FSFilesystemSeparatorProc) (Tcl_Obj *pathPtr); typedef void (Tcl_FSFreeInternalRepProc) (ClientData clientData); typedef ClientData (Tcl_FSDupInternalRepProc) (ClientData clientData); typedef Tcl_Obj * (Tcl_FSInternalToNormalizedProc) (ClientData clientData); typedef ClientData (Tcl_FSCreateInternalRepProc) (Tcl_Obj *pathPtr); typedef struct Tcl_FSVersion_ *Tcl_FSVersion; /* *---------------------------------------------------------------------------- * Data structures related to hooking into the filesystem */ /* * Filesystem version tag. This was introduced in 8.4. */ #define TCL_FILESYSTEM_VERSION_1 ((Tcl_FSVersion) 0x1) /* * struct Tcl_Filesystem: * * One such structure exists for each type (kind) of filesystem. It collects * together in one place all the functions that are part of the specific * filesystem. Tcl always accesses the filesystem through one of these * structures. * * Not all entries need be non-NULL; any which are NULL are simply ignored. * However, a complete filesystem should provide all of these functions. The * explanations in the structure show the importance of each function. */ typedef struct Tcl_Filesystem { const char *typeName; /* The name of the filesystem. */ int structureLength; /* Length of this structure, so future binary * compatibility can be assured. */ Tcl_FSVersion version; /* Version of the filesystem type. */ Tcl_FSPathInFilesystemProc *pathInFilesystemProc; /* Function to check whether a path is in this * filesystem. This is the most important * filesystem function. */ Tcl_FSDupInternalRepProc *dupInternalRepProc; /* Function to duplicate internal fs rep. May * be NULL (but then fs is less efficient). */ Tcl_FSFreeInternalRepProc *freeInternalRepProc; /* Function to free internal fs rep. Must be * implemented if internal representations * need freeing, otherwise it can be NULL. */ Tcl_FSInternalToNormalizedProc *internalToNormalizedProc; /* Function to convert internal representation * to a normalized path. Only required if the * fs creates pure path objects with no * string/path representation. */ Tcl_FSCreateInternalRepProc *createInternalRepProc; /* Function to create a filesystem-specific * internal representation. May be NULL if * paths have no internal representation, or * if the Tcl_FSPathInFilesystemProc for this * filesystem always immediately creates an * internal representation for paths it * accepts. */ Tcl_FSNormalizePathProc *normalizePathProc; /* Function to normalize a path. Should be * implemented for all filesystems which can * have multiple string representations for * the same path object. */ Tcl_FSFilesystemPathTypeProc *filesystemPathTypeProc; /* Function to determine the type of a path in * this filesystem. May be NULL. */ Tcl_FSFilesystemSeparatorProc *filesystemSeparatorProc; /* Function to return the separator * character(s) for this filesystem. Must be * implemented. */ Tcl_FSStatProc *statProc; /* Function to process a 'Tcl_FSStat()' call. * Must be implemented for any reasonable * filesystem. */ Tcl_FSAccessProc *accessProc; /* Function to process a 'Tcl_FSAccess()' * call. Must be implemented for any * reasonable filesystem. */ Tcl_FSOpenFileChannelProc *openFileChannelProc; /* Function to process a * 'Tcl_FSOpenFileChannel()' call. Must be * implemented for any reasonable * filesystem. */ Tcl_FSMatchInDirectoryProc *matchInDirectoryProc; /* Function to process a * 'Tcl_FSMatchInDirectory()'. If not * implemented, then glob and recursive copy * functionality will be lacking in the * filesystem. */ Tcl_FSUtimeProc *utimeProc; /* Function to process a 'Tcl_FSUtime()' call. * Required to allow setting (not reading) of * times with 'file mtime', 'file atime' and * the open-r/open-w/fcopy implementation of * 'file copy'. */ Tcl_FSLinkProc *linkProc; /* Function to process a 'Tcl_FSLink()' call. * Should be implemented only if the * filesystem supports links (reading or * creating). */ Tcl_FSListVolumesProc *listVolumesProc; /* Function to list any filesystem volumes * added by this filesystem. Should be * implemented only if the filesystem adds * volumes at the head of the filesystem. */ Tcl_FSFileAttrStringsProc *fileAttrStringsProc; /* Function to list all attributes strings * which are valid for this filesystem. If not * implemented the filesystem will not support * the 'file attributes' command. This allows * arbitrary additional information to be * attached to files in the filesystem. */ Tcl_FSFileAttrsGetProc *fileAttrsGetProc; /* Function to process a * 'Tcl_FSFileAttrsGet()' call, used by 'file * attributes'. */ Tcl_FSFileAttrsSetProc *fileAttrsSetProc; /* Function to process a * 'Tcl_FSFileAttrsSet()' call, used by 'file * attributes'. */ Tcl_FSCreateDirectoryProc *createDirectoryProc; /* Function to process a * 'Tcl_FSCreateDirectory()' call. Should be * implemented unless the FS is read-only. */ Tcl_FSRemoveDirectoryProc *removeDirectoryProc; /* Function to process a * 'Tcl_FSRemoveDirectory()' call. Should be * implemented unless the FS is read-only. */ Tcl_FSDeleteFileProc *deleteFileProc; /* Function to process a 'Tcl_FSDeleteFile()' * call. Should be implemented unless the FS * is read-only. */ Tcl_FSCopyFileProc *copyFileProc; /* Function to process a 'Tcl_FSCopyFile()' * call. If not implemented Tcl will fall back * on open-r, open-w and fcopy as a copying * mechanism, for copying actions initiated in * Tcl (not C). */ Tcl_FSRenameFileProc *renameFileProc; /* Function to process a 'Tcl_FSRenameFile()' * call. If not implemented, Tcl will fall * back on a copy and delete mechanism, for * rename actions initiated in Tcl (not C). */ Tcl_FSCopyDirectoryProc *copyDirectoryProc; /* Function to process a * 'Tcl_FSCopyDirectory()' call. If not * implemented, Tcl will fall back on a * recursive create-dir, file copy mechanism, * for copying actions initiated in Tcl (not * C). */ Tcl_FSLstatProc *lstatProc; /* Function to process a 'Tcl_FSLstat()' call. * If not implemented, Tcl will attempt to use * the 'statProc' defined above instead. */ Tcl_FSLoadFileProc *loadFileProc; /* Function to process a 'Tcl_FSLoadFile()' * call. If not implemented, Tcl will fall * back on a copy to native-temp followed by a * Tcl_FSLoadFile on that temporary copy. */ Tcl_FSGetCwdProc *getCwdProc; /* Function to process a 'Tcl_FSGetCwd()' * call. Most filesystems need not implement * this. It will usually only be called once, * if 'getcwd' is called before 'chdir'. May * be NULL. */ Tcl_FSChdirProc *chdirProc; /* Function to process a 'Tcl_FSChdir()' call. * If filesystems do not implement this, it * will be emulated by a series of directory * access checks. Otherwise, virtual * filesystems which do implement it need only * respond with a positive return result if * the dirName is a valid directory in their * filesystem. They need not remember the * result, since that will be automatically * remembered for use by GetCwd. Real * filesystems should carry out the correct * action (i.e. call the correct system * 'chdir' api). If not implemented, then 'cd' * and 'pwd' will fail inside the * filesystem. */ } Tcl_Filesystem; /* * The following definitions are used as values for the 'linkAction' flag to * Tcl_FSLink, or the linkProc of any filesystem. Any combination of flags can * be given. For link creation, the linkProc should create a link which * matches any of the types given. * * TCL_CREATE_SYMBOLIC_LINK - Create a symbolic or soft link. * TCL_CREATE_HARD_LINK - Create a hard link. */ #define TCL_CREATE_SYMBOLIC_LINK 0x01 #define TCL_CREATE_HARD_LINK 0x02 /* *---------------------------------------------------------------------------- * The following structure represents the Notifier functions that you can * override with the Tcl_SetNotifier call. */ typedef struct Tcl_NotifierProcs { Tcl_SetTimerProc *setTimerProc; Tcl_WaitForEventProc *waitForEventProc; Tcl_CreateFileHandlerProc *createFileHandlerProc; Tcl_DeleteFileHandlerProc *deleteFileHandlerProc; Tcl_InitNotifierProc *initNotifierProc; Tcl_FinalizeNotifierProc *finalizeNotifierProc; Tcl_AlertNotifierProc *alertNotifierProc; Tcl_ServiceModeHookProc *serviceModeHookProc; } Tcl_NotifierProcs; /* *---------------------------------------------------------------------------- * The following data structures and declarations are for the new Tcl parser. * * For each word of a command, and for each piece of a word such as a variable * reference, one of the following structures is created to describe the * token. */ typedef struct Tcl_Token { int type; /* Type of token, such as TCL_TOKEN_WORD; see * below for valid types. */ const char *start; /* First character in token. */ int size; /* Number of bytes in token. */ int numComponents; /* If this token is composed of other tokens, * this field tells how many of them there are * (including components of components, etc.). * The component tokens immediately follow * this one. */ } Tcl_Token; /* * Type values defined for Tcl_Token structures. These values are defined as * mask bits so that it's easy to check for collections of types. * * TCL_TOKEN_WORD - The token describes one word of a command, * from the first non-blank character of the word * (which may be " or {) up to but not including * the space, semicolon, or bracket that * terminates the word. NumComponents counts the * total number of sub-tokens that make up the * word. This includes, for example, sub-tokens * of TCL_TOKEN_VARIABLE tokens. * TCL_TOKEN_SIMPLE_WORD - This token is just like TCL_TOKEN_WORD except * that the word is guaranteed to consist of a * single TCL_TOKEN_TEXT sub-token. * TCL_TOKEN_TEXT - The token describes a range of literal text * that is part of a word. NumComponents is * always 0. * TCL_TOKEN_BS - The token describes a backslash sequence that * must be collapsed. NumComponents is always 0. * TCL_TOKEN_COMMAND - The token describes a command whose result * must be substituted into the word. The token * includes the enclosing brackets. NumComponents * is always 0. * TCL_TOKEN_VARIABLE - The token describes a variable substitution, * including the dollar sign, variable name, and * array index (if there is one) up through the * right parentheses. NumComponents tells how * many additional tokens follow to represent the * variable name. The first token will be a * TCL_TOKEN_TEXT token that describes the * variable name. If the variable is an array * reference then there will be one or more * additional tokens, of type TCL_TOKEN_TEXT, * TCL_TOKEN_BS, TCL_TOKEN_COMMAND, and * TCL_TOKEN_VARIABLE, that describe the array * index; numComponents counts the total number * of nested tokens that make up the variable * reference, including sub-tokens of * TCL_TOKEN_VARIABLE tokens. * TCL_TOKEN_SUB_EXPR - The token describes one subexpression of an * expression, from the first non-blank character * of the subexpression up to but not including * the space, brace, or bracket that terminates * the subexpression. NumComponents counts the * total number of following subtokens that make * up the subexpression; this includes all * subtokens for any nested TCL_TOKEN_SUB_EXPR * tokens. For example, a numeric value used as a * primitive operand is described by a * TCL_TOKEN_SUB_EXPR token followed by a * TCL_TOKEN_TEXT token. A binary subexpression * is described by a TCL_TOKEN_SUB_EXPR token * followed by the TCL_TOKEN_OPERATOR token for * the operator, then TCL_TOKEN_SUB_EXPR tokens * for the left then the right operands. * TCL_TOKEN_OPERATOR - The token describes one expression operator. * An operator might be the name of a math * function such as "abs". A TCL_TOKEN_OPERATOR * token is always preceeded by one * TCL_TOKEN_SUB_EXPR token for the operator's * subexpression, and is followed by zero or more * TCL_TOKEN_SUB_EXPR tokens for the operator's * operands. NumComponents is always 0. * TCL_TOKEN_EXPAND_WORD - This token is just like TCL_TOKEN_WORD except * that it marks a word that began with the * literal character prefix "{*}". This word is * marked to be expanded - that is, broken into * words after substitution is complete. */ #define TCL_TOKEN_WORD 1 #define TCL_TOKEN_SIMPLE_WORD 2 #define TCL_TOKEN_TEXT 4 #define TCL_TOKEN_BS 8 #define TCL_TOKEN_COMMAND 16 #define TCL_TOKEN_VARIABLE 32 #define TCL_TOKEN_SUB_EXPR 64 #define TCL_TOKEN_OPERATOR 128 #define TCL_TOKEN_EXPAND_WORD 256 /* * Parsing error types. On any parsing error, one of these values will be * stored in the error field of the Tcl_Parse structure defined below. */ #define TCL_PARSE_SUCCESS 0 #define TCL_PARSE_QUOTE_EXTRA 1 #define TCL_PARSE_BRACE_EXTRA 2 #define TCL_PARSE_MISSING_BRACE 3 #define TCL_PARSE_MISSING_BRACKET 4 #define TCL_PARSE_MISSING_PAREN 5 #define TCL_PARSE_MISSING_QUOTE 6 #define TCL_PARSE_MISSING_VAR_BRACE 7 #define TCL_PARSE_SYNTAX 8 #define TCL_PARSE_BAD_NUMBER 9 /* * A structure of the following type is filled in by Tcl_ParseCommand. It * describes a single command parsed from an input string. */ #define NUM_STATIC_TOKENS 20 typedef struct Tcl_Parse { const char *commentStart; /* Pointer to # that begins the first of one * or more comments preceding the command. */ int commentSize; /* Number of bytes in comments (up through * newline character that terminates the last * comment). If there were no comments, this * field is 0. */ const char *commandStart; /* First character in first word of * command. */ int commandSize; /* Number of bytes in command, including first * character of first word, up through the * terminating newline, close bracket, or * semicolon. */ int numWords; /* Total number of words in command. May be * 0. */ Tcl_Token *tokenPtr; /* Pointer to first token representing the * words of the command. Initially points to * staticTokens, but may change to point to * malloc-ed space if command exceeds space in * staticTokens. */ int numTokens; /* Total number of tokens in command. */ int tokensAvailable; /* Total number of tokens available at * *tokenPtr. */ int errorType; /* One of the parsing error types defined * above. */ /* * The fields below are intended only for the private use of the parser. * They should not be used by functions that invoke Tcl_ParseCommand. */ const char *string; /* The original command string passed to * Tcl_ParseCommand. */ const char *end; /* Points to the character just after the last * one in the command string. */ Tcl_Interp *interp; /* Interpreter to use for error reporting, or * NULL. */ const char *term; /* Points to character in string that * terminated most recent token. Filled in by * ParseTokens. If an error occurs, points to * beginning of region where the error * occurred (e.g. the open brace if the close * brace is missing). */ int incomplete; /* This field is set to 1 by Tcl_ParseCommand * if the command appears to be incomplete. * This information is used by * Tcl_CommandComplete. */ Tcl_Token staticTokens[NUM_STATIC_TOKENS]; /* Initial space for tokens for command. This * space should be large enough to accommodate * most commands; dynamic space is allocated * for very large commands that don't fit * here. */ } Tcl_Parse; /* *---------------------------------------------------------------------------- * The following structure represents a user-defined encoding. It collects * together all the functions that are used by the specific encoding. */ typedef struct Tcl_EncodingType { const char *encodingName; /* The name of the encoding, e.g. "euc-jp". * This name is the unique key for this * encoding type. */ Tcl_EncodingConvertProc *toUtfProc; /* Function to convert from external encoding * into UTF-8. */ Tcl_EncodingConvertProc *fromUtfProc; /* Function to convert from UTF-8 into * external encoding. */ Tcl_EncodingFreeProc *freeProc; /* If non-NULL, function to call when this * encoding is deleted. */ ClientData clientData; /* Arbitrary value associated with encoding * type. Passed to conversion functions. */ int nullSize; /* Number of zero bytes that signify * end-of-string in this encoding. This number * is used to determine the source string * length when the srcLen argument is * negative. Must be 1 or 2. */ } Tcl_EncodingType; /* * The following definitions are used as values for the conversion control * flags argument when converting text from one character set to another: * * TCL_ENCODING_START - Signifies that the source buffer is the first * block in a (potentially multi-block) input * stream. Tells the conversion function to reset * to an initial state and perform any * initialization that needs to occur before the * first byte is converted. If the source buffer * contains the entire input stream to be * converted, this flag should be set. * TCL_ENCODING_END - Signifies that the source buffer is the last * block in a (potentially multi-block) input * stream. Tells the conversion routine to * perform any finalization that needs to occur * after the last byte is converted and then to * reset to an initial state. If the source * buffer contains the entire input stream to be * converted, this flag should be set. * TCL_ENCODING_STOPONERROR - If set, then the converter will return * immediately upon encountering an invalid byte * sequence or a source character that has no * mapping in the target encoding. If clear, then * the converter will skip the problem, * substituting one or more "close" characters in * the destination buffer and then continue to * convert the source. * TCL_ENCODING_NO_TERMINATE - If set, Tcl_ExternalToUtf will not append a * terminating NUL byte. Knowing that it will * not need space to do so, it will fill all * dstLen bytes with encoded UTF-8 content, as * other circumstances permit. If clear, the * default behavior is to reserve a byte in * the dst space for NUL termination, and to * append the NUL byte. * TCL_ENCODING_CHAR_LIMIT - If set and dstCharsPtr is not NULL, then * Tcl_ExternalToUtf takes the initial value * of *dstCharsPtr is taken as a limit of the * maximum number of chars to produce in the * encoded UTF-8 content. Otherwise, the * number of chars produced is controlled only * by other limiting factors. */ #define TCL_ENCODING_START 0x01 #define TCL_ENCODING_END 0x02 #define TCL_ENCODING_STOPONERROR 0x04 #define TCL_ENCODING_NO_TERMINATE 0x08 #define TCL_ENCODING_CHAR_LIMIT 0x10 /* * The following definitions are the error codes returned by the conversion * routines: * * TCL_OK - All characters were converted. * TCL_CONVERT_NOSPACE - The output buffer would not have been large * enough for all of the converted data; as many * characters as could fit were converted though. * TCL_CONVERT_MULTIBYTE - The last few bytes in the source string were * the beginning of a multibyte sequence, but * more bytes were needed to complete this * sequence. A subsequent call to the conversion * routine should pass the beginning of this * unconverted sequence plus additional bytes * from the source stream to properly convert the * formerly split-up multibyte sequence. * TCL_CONVERT_SYNTAX - The source stream contained an invalid * character sequence. This may occur if the * input stream has been damaged or if the input * encoding method was misidentified. This error * is reported only if TCL_ENCODING_STOPONERROR * was specified. * TCL_CONVERT_UNKNOWN - The source string contained a character that * could not be represented in the target * encoding. This error is reported only if * TCL_ENCODING_STOPONERROR was specified. */ #define TCL_CONVERT_MULTIBYTE (-1) #define TCL_CONVERT_SYNTAX (-2) #define TCL_CONVERT_UNKNOWN (-3) #define TCL_CONVERT_NOSPACE (-4) /* * The maximum number of bytes that are necessary to represent a single * Unicode character in UTF-8. The valid values should be 3, 4 or 6 * (or perhaps 1 if we want to support a non-unicode enabled core). If 3 or * 4, then Tcl_UniChar must be 2-bytes in size (UCS-2) (the default). If 6, * then Tcl_UniChar must be 4-bytes in size (UCS-4). At this time UCS-2 mode * is the default and recommended mode. UCS-4 is experimental and not * recommended. It works for the core, but most extensions expect UCS-2. */ #ifndef TCL_UTF_MAX #define TCL_UTF_MAX 3 #endif /* * This represents a Unicode character. Any changes to this should also be * reflected in regcustom.h. */ #if TCL_UTF_MAX > 4 /* * unsigned int isn't 100% accurate as it should be a strict 4-byte value * (perhaps wchar_t). 64-bit systems may have troubles. The size of this * value must be reflected correctly in regcustom.h and * in tclEncoding.c. * XXX: Tcl is currently UCS-2 and planning UTF-16 for the Unicode * XXX: string rep that Tcl_UniChar represents. Changing the size * XXX: of Tcl_UniChar is /not/ supported. */ typedef unsigned int Tcl_UniChar; #else typedef unsigned short Tcl_UniChar; #endif /* *---------------------------------------------------------------------------- * TIP #59: The following structure is used in calls 'Tcl_RegisterConfig' to * provide the system with the embedded configuration data. */ typedef struct Tcl_Config { const char *key; /* Configuration key to register. ASCII * encoded, thus UTF-8. */ const char *value; /* The value associated with the key. System * encoding. */ } Tcl_Config; /* *---------------------------------------------------------------------------- * Flags for TIP#143 limits, detailing which limits are active in an * interpreter. Used for Tcl_{Add,Remove}LimitHandler type argument. */ #define TCL_LIMIT_COMMANDS 0x01 #define TCL_LIMIT_TIME 0x02 /* * Structure containing information about a limit handler to be called when a * command- or time-limit is exceeded by an interpreter. */ typedef void (Tcl_LimitHandlerProc) (ClientData clientData, Tcl_Interp *interp); typedef void (Tcl_LimitHandlerDeleteProc) (ClientData clientData); /* *---------------------------------------------------------------------------- * Override definitions for libtommath. */ typedef struct mp_int mp_int; #define MP_INT_DECLARED typedef unsigned int mp_digit; #define MP_DIGIT_DECLARED /* *---------------------------------------------------------------------------- * Definitions needed for Tcl_ParseArgvObj routines. * Based on tkArgv.c. * Modifications from the original are copyright (c) Sam Bromley 2006 */ typedef struct { int type; /* Indicates the option type; see below. */ const char *keyStr; /* The key string that flags the option in the * argv array. */ void *srcPtr; /* Value to be used in setting dst; usage * depends on type.*/ void *dstPtr; /* Address of value to be modified; usage * depends on type.*/ const char *helpStr; /* Documentation message describing this * option. */ ClientData clientData; /* Word to pass to function callbacks. */ } Tcl_ArgvInfo; /* * Legal values for the type field of a Tcl_ArgInfo: see the user * documentation for details. */ #define TCL_ARGV_CONSTANT 15 #define TCL_ARGV_INT 16 #define TCL_ARGV_STRING 17 #define TCL_ARGV_REST 18 #define TCL_ARGV_FLOAT 19 #define TCL_ARGV_FUNC 20 #define TCL_ARGV_GENFUNC 21 #define TCL_ARGV_HELP 22 #define TCL_ARGV_END 23 /* * Types of callback functions for the TCL_ARGV_FUNC and TCL_ARGV_GENFUNC * argument types: */ typedef int (Tcl_ArgvFuncProc)(ClientData clientData, Tcl_Obj *objPtr, void *dstPtr); typedef int (Tcl_ArgvGenFuncProc)(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv, void *dstPtr); /* * Shorthand for commonly used argTable entries. */ #define TCL_ARGV_AUTO_HELP \ {TCL_ARGV_HELP, "-help", NULL, NULL, \ "Print summary of command-line options and abort", NULL} #define TCL_ARGV_AUTO_REST \ {TCL_ARGV_REST, "--", NULL, NULL, \ "Marks the end of the options", NULL} #define TCL_ARGV_TABLE_END \ {TCL_ARGV_END, NULL, NULL, NULL, NULL, NULL} /* *---------------------------------------------------------------------------- * Definitions needed for Tcl_Zlib routines. [TIP #234] * * Constants for the format flags describing what sort of data format is * desired/expected for the Tcl_ZlibDeflate, Tcl_ZlibInflate and * Tcl_ZlibStreamInit functions. */ #define TCL_ZLIB_FORMAT_RAW 1 #define TCL_ZLIB_FORMAT_ZLIB 2 #define TCL_ZLIB_FORMAT_GZIP 4 #define TCL_ZLIB_FORMAT_AUTO 8 /* * Constants that describe whether the stream is to operate in compressing or * decompressing mode. */ #define TCL_ZLIB_STREAM_DEFLATE 16 #define TCL_ZLIB_STREAM_INFLATE 32 /* * Constants giving compression levels. Use of TCL_ZLIB_COMPRESS_DEFAULT is * recommended. */ #define TCL_ZLIB_COMPRESS_NONE 0 #define TCL_ZLIB_COMPRESS_FAST 1 #define TCL_ZLIB_COMPRESS_BEST 9 #define TCL_ZLIB_COMPRESS_DEFAULT (-1) /* * Constants for types of flushing, used with Tcl_ZlibFlush. */ #define TCL_ZLIB_NO_FLUSH 0 #define TCL_ZLIB_FLUSH 2 #define TCL_ZLIB_FULLFLUSH 3 #define TCL_ZLIB_FINALIZE 4 /* *---------------------------------------------------------------------------- * Definitions needed for the Tcl_LoadFile function. [TIP #416] */ #define TCL_LOAD_GLOBAL 1 #define TCL_LOAD_LAZY 2 /* *---------------------------------------------------------------------------- * Single public declaration for NRE. */ typedef int (Tcl_NRPostProc) (ClientData data[], Tcl_Interp *interp, int result); /* *---------------------------------------------------------------------------- * The following constant is used to test for older versions of Tcl in the * stubs tables. * * Jan Nijtman's plus patch uses 0xFCA1BACF, so we need to pick a different * value since the stubs tables don't match. */ #define TCL_STUB_MAGIC ((int) 0xFCA3BACF) /* * The following function is required to be defined in all stubs aware * extensions. The function is actually implemented in the stub library, not * the main Tcl library, although there is a trivial implementation in the * main library in case an extension is statically linked into an application. */ const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version, int exact); const char * TclTomMathInitializeStubs(Tcl_Interp *interp, const char *version, int epoch, int revision); /* * When not using stubs, make it a macro. */ #ifndef USE_TCL_STUBS #define Tcl_InitStubs(interp, version, exact) \ Tcl_PkgInitStubsCheck(interp, version, exact) #endif /* * TODO - tommath stubs export goes here! */ /* * Public functions that are not accessible via the stubs table. * Tcl_GetMemoryInfo is needed for AOLserver. [Bug 1868171] */ #define Tcl_Main(argc, argv, proc) Tcl_MainEx(argc, argv, proc, \ ((Tcl_CreateInterp)())) EXTERN void Tcl_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); EXTERN const char * Tcl_PkgInitStubsCheck(Tcl_Interp *interp, const char *version, int exact); EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr); /* *---------------------------------------------------------------------------- * Include the public function declarations that are accessible via the stubs * table. */ #include "tclDecls.h" /* * Include platform specific public function declarations that are accessible * via the stubs table. Make all TclOO symbols MODULE_SCOPE (which only * has effect on building it as a shared library). See ticket [3010352]. */ #if defined(BUILD_tcl) # undef TCLAPI # define TCLAPI MODULE_SCOPE #endif #include "tclPlatDecls.h" /* *---------------------------------------------------------------------------- * The following declarations either map ckalloc and ckfree to malloc and * free, or they map them to functions with all sorts of debugging hooks * defined in tclCkalloc.c. */ #ifdef TCL_MEM_DEBUG # define ckalloc(x) \ ((void *) Tcl_DbCkalloc((unsigned)(x), __FILE__, __LINE__)) # define ckfree(x) \ Tcl_DbCkfree((char *)(x), __FILE__, __LINE__) # define ckrealloc(x,y) \ ((void *) Tcl_DbCkrealloc((char *)(x), (unsigned)(y), __FILE__, __LINE__)) # define attemptckalloc(x) \ ((void *) Tcl_AttemptDbCkalloc((unsigned)(x), __FILE__, __LINE__)) # define attemptckrealloc(x,y) \ ((void *) Tcl_AttemptDbCkrealloc((char *)(x), (unsigned)(y), __FILE__, __LINE__)) #else /* !TCL_MEM_DEBUG */ /* * If we are not using the debugging allocator, we should call the Tcl_Alloc, * et al. routines in order to guarantee that every module is using the same * memory allocator both inside and outside of the Tcl library. */ # define ckalloc(x) \ ((void *) Tcl_Alloc((unsigned)(x))) # define ckfree(x) \ Tcl_Free((char *)(x)) # define ckrealloc(x,y) \ ((void *) Tcl_Realloc((char *)(x), (unsigned)(y))) # define attemptckalloc(x) \ ((void *) Tcl_AttemptAlloc((unsigned)(x))) # define attemptckrealloc(x,y) \ ((void *) Tcl_AttemptRealloc((char *)(x), (unsigned)(y))) # undef Tcl_InitMemory # define Tcl_InitMemory(x) # undef Tcl_DumpActiveMemory # define Tcl_DumpActiveMemory(x) # undef Tcl_ValidateAllMemory # define Tcl_ValidateAllMemory(x,y) #endif /* !TCL_MEM_DEBUG */ #ifdef TCL_MEM_DEBUG # define Tcl_IncrRefCount(objPtr) \ Tcl_DbIncrRefCount(objPtr, __FILE__, __LINE__) # define Tcl_DecrRefCount(objPtr) \ Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__) # define Tcl_IsShared(objPtr) \ Tcl_DbIsShared(objPtr, __FILE__, __LINE__) #else # define Tcl_IncrRefCount(objPtr) \ ++(objPtr)->refCount /* * Use do/while0 idiom for optimum correctness without compiler warnings. * http://c2.com/cgi/wiki?TrivialDoWhileLoop */ # define Tcl_DecrRefCount(objPtr) \ do { \ Tcl_Obj *_objPtr = (objPtr); \ if ((_objPtr)->refCount-- <= 1) { \ TclFreeObj(_objPtr); \ } \ } while(0) # define Tcl_IsShared(objPtr) \ ((objPtr)->refCount > 1) #endif /* * Macros and definitions that help to debug the use of Tcl objects. When * TCL_MEM_DEBUG is defined, the Tcl_New declarations are overridden to call * debugging versions of the object creation functions. */ #ifdef TCL_MEM_DEBUG # undef Tcl_NewBignumObj # define Tcl_NewBignumObj(val) \ Tcl_DbNewBignumObj(val, __FILE__, __LINE__) # undef Tcl_NewBooleanObj # define Tcl_NewBooleanObj(val) \ Tcl_DbNewBooleanObj(val, __FILE__, __LINE__) # undef Tcl_NewByteArrayObj # define Tcl_NewByteArrayObj(bytes, len) \ Tcl_DbNewByteArrayObj(bytes, len, __FILE__, __LINE__) # undef Tcl_NewDoubleObj # define Tcl_NewDoubleObj(val) \ Tcl_DbNewDoubleObj(val, __FILE__, __LINE__) # undef Tcl_NewIntObj # define Tcl_NewIntObj(val) \ Tcl_DbNewLongObj(val, __FILE__, __LINE__) # undef Tcl_NewListObj # define Tcl_NewListObj(objc, objv) \ Tcl_DbNewListObj(objc, objv, __FILE__, __LINE__) # undef Tcl_NewLongObj # define Tcl_NewLongObj(val) \ Tcl_DbNewLongObj(val, __FILE__, __LINE__) # undef Tcl_NewObj # define Tcl_NewObj() \ Tcl_DbNewObj(__FILE__, __LINE__) # undef Tcl_NewStringObj # define Tcl_NewStringObj(bytes, len) \ Tcl_DbNewStringObj(bytes, len, __FILE__, __LINE__) # undef Tcl_NewWideIntObj # define Tcl_NewWideIntObj(val) \ Tcl_DbNewWideIntObj(val, __FILE__, __LINE__) #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------------- * Macros for clients to use to access fields of hash entries: */ #define Tcl_GetHashValue(h) ((h)->clientData) #define Tcl_SetHashValue(h, value) ((h)->clientData = (ClientData) (value)) #define Tcl_GetHashKey(tablePtr, h) \ ((void *) (((tablePtr)->keyType == TCL_ONE_WORD_KEYS || \ (tablePtr)->keyType == TCL_CUSTOM_PTR_KEYS) \ ? (h)->key.oneWordValue \ : (h)->key.string)) /* * Macros to use for clients to use to invoke find and create functions for * hash tables: */ #undef Tcl_FindHashEntry #define Tcl_FindHashEntry(tablePtr, key) \ (*((tablePtr)->findProc))(tablePtr, (const char *)(key)) #undef Tcl_CreateHashEntry #define Tcl_CreateHashEntry(tablePtr, key, newPtr) \ (*((tablePtr)->createProc))(tablePtr, (const char *)(key), newPtr) /* *---------------------------------------------------------------------------- * Macros that eliminate the overhead of the thread synchronization functions * when compiling without thread support. */ #ifndef TCL_THREADS #undef Tcl_MutexLock #define Tcl_MutexLock(mutexPtr) #undef Tcl_MutexUnlock #define Tcl_MutexUnlock(mutexPtr) #undef Tcl_MutexFinalize #define Tcl_MutexFinalize(mutexPtr) #undef Tcl_ConditionNotify #define Tcl_ConditionNotify(condPtr) #undef Tcl_ConditionWait #define Tcl_ConditionWait(condPtr, mutexPtr, timePtr) #undef Tcl_ConditionFinalize #define Tcl_ConditionFinalize(condPtr) #endif /* TCL_THREADS */ /* *---------------------------------------------------------------------------- * Deprecated Tcl functions: */ #ifndef TCL_NO_DEPRECATED /* * These function have been renamed. The old names are deprecated, but we * define these macros for backwards compatibilty. */ # define Tcl_Ckalloc Tcl_Alloc # define Tcl_Ckfree Tcl_Free # define Tcl_Ckrealloc Tcl_Realloc # define Tcl_Return Tcl_SetResult # define Tcl_TildeSubst Tcl_TranslateFileName # define panic Tcl_Panic # define panicVA Tcl_PanicVA #endif /* !TCL_NO_DEPRECATED */ /* *---------------------------------------------------------------------------- * Convenience declaration of Tcl_AppInit for backwards compatibility. This * function is not *implemented* by the tcl library, so the storage class is * neither DLLEXPORT nor DLLIMPORT. */ extern Tcl_AppInitProc Tcl_AppInit; #endif /* RC_INVOKED */ /* * end block for C++ */ #ifdef __cplusplus } #endif #endif /* _TCL */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/README0000644000175000017500000000030712663653207014063 0ustar sergeisergeiThis directory contains Tcl source files that work on all the platforms where Tcl runs (e.g. UNIX, PCs, and MacOSX). Platform-specific sources are in the directories ../unix, ../win, and ../macosx. tcl8.6.5/generic/tclThreadJoin.c0000644000175000017500000002231012663660065016077 0ustar sergeisergei/* * tclThreadJoin.c -- * * This file implements a platform independent emulation layer for the * handling of joinable threads. The Windows platform uses this code to * provide the functionality of joining threads. This code is currently * not necessary on Unix. * * Copyright (c) 2000 by Scriptics Corporation * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #ifdef _WIN32 /* * The information about each joinable thread is remembered in a structure as * defined below. */ typedef struct JoinableThread { Tcl_ThreadId id; /* The id of the joinable thread. */ int result; /* A place for the result after the demise of * the thread. */ int done; /* Boolean flag. Initialized to 0 and set to 1 * after the exit of the thread. This allows a * thread requesting a join to detect when * waiting is not necessary. */ int waitedUpon; /* Boolean flag. Initialized to 0 and set to 1 * by the thread waiting for this one via * Tcl_JoinThread. Used to lock any other * thread trying to wait on this one. */ Tcl_Mutex threadMutex; /* The mutex used to serialize access to this * structure. */ Tcl_Condition cond; /* This is the condition a thread has to wait * upon to get notified of the end of the * described thread. It is signaled indirectly * by Tcl_ExitThread. */ struct JoinableThread *nextThreadPtr; /* Reference to the next thread in the list of * joinable threads. */ } JoinableThread; /* * The following variable is used to maintain the global list of all joinable * threads. Usage by a thread is allowed only if the thread acquired the * 'joinMutex'. */ TCL_DECLARE_MUTEX(joinMutex) static JoinableThread *firstThreadPtr; /* *---------------------------------------------------------------------- * * TclJoinThread -- * * This procedure waits for the exit of the thread with the specified id * and returns its result. * * Results: * A standard tcl result signaling the overall success/failure of the * operation and an integer result delivered by the thread which was * waited upon. * * Side effects: * Deallocates the memory allocated by TclRememberJoinableThread. * Removes the data associated to the thread waited upon from the list of * joinable threads. * *---------------------------------------------------------------------- */ int TclJoinThread( Tcl_ThreadId id, /* The id of the thread to wait upon. */ int *result) /* Reference to a location for the result of * the thread we are waiting upon. */ { JoinableThread *threadPtr; /* * Steps done here: * i. Acquire the joinMutex and search for the thread. * ii. Error out if it could not be found. * iii. If found, switch from exclusive access to the list to exclusive * access to the thread structure. * iv. Error out if some other is already waiting. * v. Skip the waiting part of the thread is already done. * vi. Wait for the thread to exit, mark it as waited upon too. * vii. Get the result form the structure, * viii. switch to exclusive access of the list, * ix. remove the structure from the list, * x. then switch back to exclusive access to the structure * xi. and delete it. */ Tcl_MutexLock(&joinMutex); threadPtr = firstThreadPtr; while (threadPtr!=NULL && threadPtr->id!=id) { threadPtr = threadPtr->nextThreadPtr; } if (threadPtr == NULL) { /* * Thread not found. Either not joinable, or already waited upon and * exited. Whatever, an error is in order. */ Tcl_MutexUnlock(&joinMutex); return TCL_ERROR; } /* * [1] If we don't lock the structure before giving up exclusive access to * the list some other thread just completing its wait on the same thread * can delete the structure from under us, leaving us with a dangling * pointer. */ Tcl_MutexLock(&threadPtr->threadMutex); Tcl_MutexUnlock(&joinMutex); /* * [2] Now that we have the structure mutex any other thread that just * tries to delete structure will wait at location [3] until we are done * with the structure. And in that case we are done with it rather quickly * as 'waitedUpon' will be set and we will have to error out. */ if (threadPtr->waitedUpon) { Tcl_MutexUnlock(&threadPtr->threadMutex); return TCL_ERROR; } /* * We are waiting now, let other threads recognize this. */ threadPtr->waitedUpon = 1; while (!threadPtr->done) { Tcl_ConditionWait(&threadPtr->cond, &threadPtr->threadMutex, NULL); } /* * We have to release the structure before trying to access the list again * or we can run into deadlock with a thread at [1] (see above) because of * us holding the structure and the other holding the list. There is no * problem with dangling pointers here as 'waitedUpon == 1' is still valid * and any other thread will error out and not come to this place. IOW, * the fact that we are here also means that no other thread came here * before us and is able to delete the structure. */ Tcl_MutexUnlock(&threadPtr->threadMutex); Tcl_MutexLock(&joinMutex); /* * We have to search the list again as its structure may (may, almost * certainly) have changed while we were waiting. Especially now is the * time to compute the predecessor in the list. Any earlier result can be * dangling by now. */ if (firstThreadPtr == threadPtr) { firstThreadPtr = threadPtr->nextThreadPtr; } else { JoinableThread *prevThreadPtr = firstThreadPtr; while (prevThreadPtr->nextThreadPtr != threadPtr) { prevThreadPtr = prevThreadPtr->nextThreadPtr; } prevThreadPtr->nextThreadPtr = threadPtr->nextThreadPtr; } Tcl_MutexUnlock(&joinMutex); /* * [3] Now that the structure is not part of the list anymore no other * thread can acquire its mutex from now on. But it is possible that * another thread is still holding the mutex though, see location [2]. So * we have to acquire the mutex one more time to wait for that thread to * finish. We can (and have to) release the mutex immediately. */ Tcl_MutexLock(&threadPtr->threadMutex); Tcl_MutexUnlock(&threadPtr->threadMutex); /* * Copy the result to us, finalize the synchronisation objects, then free * the structure and return. */ *result = threadPtr->result; Tcl_ConditionFinalize(&threadPtr->cond); Tcl_MutexFinalize(&threadPtr->threadMutex); ckfree(threadPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclRememberJoinableThread -- * * This procedure remebers a thread as joinable. Only a call to * TclJoinThread will remove the structre created (and initialized) here. * IOW, not waiting upon a joinable thread will cause memory leaks. * * Results: * None. * * Side effects: * Allocates memory, adds it to the global list of all joinable threads. * *---------------------------------------------------------------------- */ void TclRememberJoinableThread( Tcl_ThreadId id) /* The thread to remember as joinable */ { JoinableThread *threadPtr; threadPtr = ckalloc(sizeof(JoinableThread)); threadPtr->id = id; threadPtr->done = 0; threadPtr->waitedUpon = 0; threadPtr->threadMutex = (Tcl_Mutex) NULL; threadPtr->cond = (Tcl_Condition) NULL; Tcl_MutexLock(&joinMutex); threadPtr->nextThreadPtr = firstThreadPtr; firstThreadPtr = threadPtr; Tcl_MutexUnlock(&joinMutex); } /* *---------------------------------------------------------------------- * * TclSignalExitThread -- * * This procedure signals that the specified thread is done with its * work. If the thread is joinable this signal is propagated to the * thread waiting upon it. * * Results: * None. * * Side effects: * Modifies the associated structure to hold the result. * *---------------------------------------------------------------------- */ void TclSignalExitThread( Tcl_ThreadId id, /* Id of the thread signaling its exit. */ int result) /* The result from the thread. */ { JoinableThread *threadPtr; Tcl_MutexLock(&joinMutex); threadPtr = firstThreadPtr; while ((threadPtr != NULL) && (threadPtr->id != id)) { threadPtr = threadPtr->nextThreadPtr; } if (threadPtr == NULL) { /* * Thread not found. Not joinable. No problem, nothing to do. */ Tcl_MutexUnlock(&joinMutex); return; } /* * Switch over the exclusive access from the list to the structure, then * store the result, set the flag and notify the waiting thread, provided * that it exists. The order of lock/unlock ensures that a thread entering * 'TclJoinThread' will not interfere with us. */ Tcl_MutexLock(&threadPtr->threadMutex); Tcl_MutexUnlock(&joinMutex); threadPtr->done = 1; threadPtr->result = result; if (threadPtr->waitedUpon) { Tcl_ConditionNotify(&threadPtr->cond); } Tcl_MutexUnlock(&threadPtr->threadMutex); } #endif /* _WIN32 */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclGetDate.y0000644000175000017500000006701312663653207015424 0ustar sergeisergei/* * tclGetDate.y -- * * Contains yacc grammar for parsing date and time strings. The output of * this file should be the file tclDate.c which is used directly in the * Tcl sources. Note that this file is largely obsolete in Tcl 8.5; it is * only used when doing free-form date parsing, an ill-defined process * anyway. * * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans. * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ %parse-param {DateInfo* info} %lex-param {DateInfo* info} %pure-parser /* %error-verbose would be nice, but our token names are meaningless */ %locations %{ /* * tclDate.c -- * * This file is generated from a yacc grammar defined in the file * tclGetDate.y. It should not be edited directly. * * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans. * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ #include "tclInt.h" /* * Bison generates several labels that happen to be unused. MS Visual C++ * doesn't like that, and complains. Tell it to shut up. */ #ifdef _MSC_VER #pragma warning( disable : 4102 ) #endif /* _MSC_VER */ /* * yyparse will accept a 'struct DateInfo' as its parameter; that's where the * parsed fields will be returned. */ typedef struct DateInfo { Tcl_Obj* messages; /* Error messages */ const char* separatrix; /* String separating messages */ time_t dateYear; time_t dateMonth; time_t dateDay; int dateHaveDate; time_t dateHour; time_t dateMinutes; time_t dateSeconds; int dateMeridian; int dateHaveTime; time_t dateTimezone; int dateDSTmode; int dateHaveZone; time_t dateRelMonth; time_t dateRelDay; time_t dateRelSeconds; int dateHaveRel; time_t dateMonthOrdinal; int dateHaveOrdinalMonth; time_t dateDayOrdinal; time_t dateDayNumber; int dateHaveDay; const char *dateStart; const char *dateInput; time_t *dateRelPointer; int dateDigitCount; } DateInfo; #define YYMALLOC ckalloc #define YYFREE(x) (ckfree((void*) (x))) #define yyDSTmode (info->dateDSTmode) #define yyDayOrdinal (info->dateDayOrdinal) #define yyDayNumber (info->dateDayNumber) #define yyMonthOrdinal (info->dateMonthOrdinal) #define yyHaveDate (info->dateHaveDate) #define yyHaveDay (info->dateHaveDay) #define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth) #define yyHaveRel (info->dateHaveRel) #define yyHaveTime (info->dateHaveTime) #define yyHaveZone (info->dateHaveZone) #define yyTimezone (info->dateTimezone) #define yyDay (info->dateDay) #define yyMonth (info->dateMonth) #define yyYear (info->dateYear) #define yyHour (info->dateHour) #define yyMinutes (info->dateMinutes) #define yySeconds (info->dateSeconds) #define yyMeridian (info->dateMeridian) #define yyRelMonth (info->dateRelMonth) #define yyRelDay (info->dateRelDay) #define yyRelSeconds (info->dateRelSeconds) #define yyRelPointer (info->dateRelPointer) #define yyInput (info->dateInput) #define yyDigitCount (info->dateDigitCount) #define EPOCH 1970 #define START_OF_TIME 1902 #define END_OF_TIME 2037 /* * The offset of tm_year of struct tm returned by localtime, gmtime, etc. * Posix requires 1900. */ #define TM_YEAR_BASE 1900 #define HOUR(x) ((int) (60 * x)) #define SECSPERDAY (24L * 60L * 60L) #define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) /* * An entry in the lexical lookup table. */ typedef struct _TABLE { const char *name; int type; time_t value; } TABLE; /* * Daylight-savings mode: on, off, or not yet known. */ typedef enum _DSTMODE { DSTon, DSToff, DSTmaybe } DSTMODE; /* * Meridian: am, pm, or 24-hour style. */ typedef enum _MERIDIAN { MERam, MERpm, MER24 } MERIDIAN; %} %union { time_t Number; enum _MERIDIAN Meridian; } %{ /* * Prototypes of internal functions. */ static int LookupWord(YYSTYPE* yylvalPtr, char *buff); static void TclDateerror(YYLTYPE* location, DateInfo* info, const char *s); static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location, DateInfo* info); static time_t ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian); MODULE_SCOPE int yyparse(DateInfo*); %} %token tAGO %token tDAY %token tDAYZONE %token tID %token tMERIDIAN %token tMONTH %token tMONTH_UNIT %token tSTARDATE %token tSEC_UNIT %token tSNUMBER %token tUNUMBER %token tZONE %token tEPOCH %token tDST %token tISOBASE %token tDAY_UNIT %token tNEXT %type tDAY %type tDAYZONE %type tMONTH %type tMONTH_UNIT %type tDST %type tSEC_UNIT %type tSNUMBER %type tUNUMBER %type tZONE %type tISOBASE %type tDAY_UNIT %type unit %type sign %type tNEXT %type tSTARDATE %type tMERIDIAN %type o_merid %% spec : /* NULL */ | spec item ; item : time { yyHaveTime++; } | zone { yyHaveZone++; } | date { yyHaveDate++; } | ordMonth { yyHaveOrdinalMonth++; } | day { yyHaveDay++; } | relspec { yyHaveRel++; } | iso { yyHaveTime++; yyHaveDate++; } | trek { yyHaveTime++; yyHaveDate++; yyHaveRel++; } | number ; time : tUNUMBER tMERIDIAN { yyHour = $1; yyMinutes = 0; yySeconds = 0; yyMeridian = $2; } | tUNUMBER ':' tUNUMBER o_merid { yyHour = $1; yyMinutes = $3; yySeconds = 0; yyMeridian = $4; } | tUNUMBER ':' tUNUMBER '-' tUNUMBER { yyHour = $1; yyMinutes = $3; yyMeridian = MER24; yyDSTmode = DSToff; yyTimezone = ($5 % 100 + ($5 / 100) * 60); ++yyHaveZone; } | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid { yyHour = $1; yyMinutes = $3; yySeconds = $5; yyMeridian = $6; } | tUNUMBER ':' tUNUMBER ':' tUNUMBER '-' tUNUMBER { yyHour = $1; yyMinutes = $3; yySeconds = $5; yyMeridian = MER24; yyDSTmode = DSToff; yyTimezone = ($7 % 100 + ($7 / 100) * 60); ++yyHaveZone; } ; zone : tZONE tDST { yyTimezone = $1; yyDSTmode = DSTon; } | tZONE { yyTimezone = $1; yyDSTmode = DSToff; } | tDAYZONE { yyTimezone = $1; yyDSTmode = DSTon; } ; day : tDAY { yyDayOrdinal = 1; yyDayNumber = $1; } | tDAY ',' { yyDayOrdinal = 1; yyDayNumber = $1; } | tUNUMBER tDAY { yyDayOrdinal = $1; yyDayNumber = $2; } | sign tUNUMBER tDAY { yyDayOrdinal = $1 * $2; yyDayNumber = $3; } | tNEXT tDAY { yyDayOrdinal = 2; yyDayNumber = $2; } ; date : tUNUMBER '/' tUNUMBER { yyMonth = $1; yyDay = $3; } | tUNUMBER '/' tUNUMBER '/' tUNUMBER { yyMonth = $1; yyDay = $3; yyYear = $5; } | tISOBASE { yyYear = $1 / 10000; yyMonth = ($1 % 10000)/100; yyDay = $1 % 100; } | tUNUMBER '-' tMONTH '-' tUNUMBER { yyDay = $1; yyMonth = $3; yyYear = $5; } | tUNUMBER '-' tUNUMBER '-' tUNUMBER { yyMonth = $3; yyDay = $5; yyYear = $1; } | tMONTH tUNUMBER { yyMonth = $1; yyDay = $2; } | tMONTH tUNUMBER ',' tUNUMBER { yyMonth = $1; yyDay = $2; yyYear = $4; } | tUNUMBER tMONTH { yyMonth = $2; yyDay = $1; } | tEPOCH { yyMonth = 1; yyDay = 1; yyYear = EPOCH; } | tUNUMBER tMONTH tUNUMBER { yyMonth = $2; yyDay = $1; yyYear = $3; } ; ordMonth: tNEXT tMONTH { yyMonthOrdinal = 1; yyMonth = $2; } | tNEXT tUNUMBER tMONTH { yyMonthOrdinal = $2; yyMonth = $3; } ; iso : tISOBASE tZONE tISOBASE { if ($2 != HOUR( 7)) YYABORT; yyYear = $1 / 10000; yyMonth = ($1 % 10000)/100; yyDay = $1 % 100; yyHour = $3 / 10000; yyMinutes = ($3 % 10000)/100; yySeconds = $3 % 100; } | tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER { if ($2 != HOUR( 7)) YYABORT; yyYear = $1 / 10000; yyMonth = ($1 % 10000)/100; yyDay = $1 % 100; yyHour = $3; yyMinutes = $5; yySeconds = $7; } | tISOBASE tISOBASE { yyYear = $1 / 10000; yyMonth = ($1 % 10000)/100; yyDay = $1 % 100; yyHour = $2 / 10000; yyMinutes = ($2 % 10000)/100; yySeconds = $2 % 100; } ; trek : tSTARDATE tUNUMBER '.' tUNUMBER { /* * Offset computed year by -377 so that the returned years will be * in a range accessible with a 32 bit clock seconds value. */ yyYear = $2/1000 + 2323 - 377; yyDay = 1; yyMonth = 1; yyRelDay += (($2%1000)*(365 + IsLeapYear(yyYear)))/1000; yyRelSeconds += $4 * 144 * 60; } ; relspec : relunits tAGO { yyRelSeconds *= -1; yyRelMonth *= -1; yyRelDay *= -1; } | relunits ; relunits : sign tUNUMBER unit { *yyRelPointer += $1 * $2 * $3; } | tUNUMBER unit { *yyRelPointer += $1 * $2; } | tNEXT unit { *yyRelPointer += $2; } | tNEXT tUNUMBER unit { *yyRelPointer += $2 * $3; } | unit { *yyRelPointer += $1; } ; sign : '-' { $$ = -1; } | '+' { $$ = 1; } ; unit : tSEC_UNIT { $$ = $1; yyRelPointer = &yyRelSeconds; } | tDAY_UNIT { $$ = $1; yyRelPointer = &yyRelDay; } | tMONTH_UNIT { $$ = $1; yyRelPointer = &yyRelMonth; } ; number : tUNUMBER { if (yyHaveTime && yyHaveDate && !yyHaveRel) { yyYear = $1; } else { yyHaveTime++; if (yyDigitCount <= 2) { yyHour = $1; yyMinutes = 0; } else { yyHour = $1 / 100; yyMinutes = $1 % 100; } yySeconds = 0; yyMeridian = MER24; } } ; o_merid : /* NULL */ { $$ = MER24; } | tMERIDIAN { $$ = $1; } ; %% /* * Month and day table. */ static const TABLE MonthDayTable[] = { { "january", tMONTH, 1 }, { "february", tMONTH, 2 }, { "march", tMONTH, 3 }, { "april", tMONTH, 4 }, { "may", tMONTH, 5 }, { "june", tMONTH, 6 }, { "july", tMONTH, 7 }, { "august", tMONTH, 8 }, { "september", tMONTH, 9 }, { "sept", tMONTH, 9 }, { "october", tMONTH, 10 }, { "november", tMONTH, 11 }, { "december", tMONTH, 12 }, { "sunday", tDAY, 0 }, { "monday", tDAY, 1 }, { "tuesday", tDAY, 2 }, { "tues", tDAY, 2 }, { "wednesday", tDAY, 3 }, { "wednes", tDAY, 3 }, { "thursday", tDAY, 4 }, { "thur", tDAY, 4 }, { "thurs", tDAY, 4 }, { "friday", tDAY, 5 }, { "saturday", tDAY, 6 }, { NULL, 0, 0 } }; /* * Time units table. */ static const TABLE UnitsTable[] = { { "year", tMONTH_UNIT, 12 }, { "month", tMONTH_UNIT, 1 }, { "fortnight", tDAY_UNIT, 14 }, { "week", tDAY_UNIT, 7 }, { "day", tDAY_UNIT, 1 }, { "hour", tSEC_UNIT, 60 * 60 }, { "minute", tSEC_UNIT, 60 }, { "min", tSEC_UNIT, 60 }, { "second", tSEC_UNIT, 1 }, { "sec", tSEC_UNIT, 1 }, { NULL, 0, 0 } }; /* * Assorted relative-time words. */ static const TABLE OtherTable[] = { { "tomorrow", tDAY_UNIT, 1 }, { "yesterday", tDAY_UNIT, -1 }, { "today", tDAY_UNIT, 0 }, { "now", tSEC_UNIT, 0 }, { "last", tUNUMBER, -1 }, { "this", tSEC_UNIT, 0 }, { "next", tNEXT, 1 }, #if 0 { "first", tUNUMBER, 1 }, { "second", tUNUMBER, 2 }, { "third", tUNUMBER, 3 }, { "fourth", tUNUMBER, 4 }, { "fifth", tUNUMBER, 5 }, { "sixth", tUNUMBER, 6 }, { "seventh", tUNUMBER, 7 }, { "eighth", tUNUMBER, 8 }, { "ninth", tUNUMBER, 9 }, { "tenth", tUNUMBER, 10 }, { "eleventh", tUNUMBER, 11 }, { "twelfth", tUNUMBER, 12 }, #endif { "ago", tAGO, 1 }, { "epoch", tEPOCH, 0 }, { "stardate", tSTARDATE, 0 }, { NULL, 0, 0 } }; /* * The timezone table. (Note: This table was modified to not use any floating * point constants to work around an SGI compiler bug). */ static const TABLE TimezoneTable[] = { { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */ { "utc", tZONE, HOUR( 0) }, { "uct", tZONE, HOUR( 0) }, /* Universal Coordinated Time */ { "wet", tZONE, HOUR( 0) }, /* Western European */ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */ { "wat", tZONE, HOUR( 1) }, /* West Africa */ { "at", tZONE, HOUR( 2) }, /* Azores */ #if 0 /* For completeness. BST is also British Summer, and GST is * also Guam Standard. */ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */ #endif { "nft", tZONE, HOUR( 7/2) }, /* Newfoundland */ { "nst", tZONE, HOUR( 7/2) }, /* Newfoundland Standard */ { "ndt", tDAYZONE, HOUR( 7/2) }, /* Newfoundland Daylight */ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */ { "cst", tZONE, HOUR( 6) }, /* Central Standard */ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */ { "cat", tZONE, HOUR(10) }, /* Central Alaska */ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */ { "nt", tZONE, HOUR(11) }, /* Nome */ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */ { "cet", tZONE, -HOUR( 1) }, /* Central European */ { "cest", tDAYZONE, -HOUR( 1) }, /* Central European Summer */ { "met", tZONE, -HOUR( 1) }, /* Middle European */ { "mewt", tZONE, -HOUR( 1) }, /* Middle European Winter */ { "mest", tDAYZONE, -HOUR( 1) }, /* Middle European Summer */ { "swt", tZONE, -HOUR( 1) }, /* Swedish Winter */ { "sst", tDAYZONE, -HOUR( 1) }, /* Swedish Summer */ { "fwt", tZONE, -HOUR( 1) }, /* French Winter */ { "fst", tDAYZONE, -HOUR( 1) }, /* French Summer */ { "eet", tZONE, -HOUR( 2) }, /* Eastern Europe, USSR Zone 1 */ { "bt", tZONE, -HOUR( 3) }, /* Baghdad, USSR Zone 2 */ { "it", tZONE, -HOUR( 7/2) }, /* Iran */ { "zp4", tZONE, -HOUR( 4) }, /* USSR Zone 3 */ { "zp5", tZONE, -HOUR( 5) }, /* USSR Zone 4 */ { "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */ { "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */ #if 0 /* For completeness. NST is also Newfoundland Stanard, nad SST is * also Swedish Summer. */ { "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */ { "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */ #endif /* 0 */ { "wast", tZONE, -HOUR( 7) }, /* West Australian Standard */ { "wadt", tDAYZONE, -HOUR( 7) }, /* West Australian Daylight */ { "jt", tZONE, -HOUR(15/2) }, /* Java (3pm in Cronusland!) */ { "cct", tZONE, -HOUR( 8) }, /* China Coast, USSR Zone 7 */ { "jst", tZONE, -HOUR( 9) }, /* Japan Standard, USSR Zone 8 */ { "jdt", tDAYZONE, -HOUR( 9) }, /* Japan Daylight */ { "kst", tZONE, -HOUR( 9) }, /* Korea Standard */ { "kdt", tDAYZONE, -HOUR( 9) }, /* Korea Daylight */ { "cast", tZONE, -HOUR(19/2) }, /* Central Australian Standard */ { "cadt", tDAYZONE, -HOUR(19/2) }, /* Central Australian Daylight */ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */ { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */ { "nzt", tZONE, -HOUR(12) }, /* New Zealand */ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */ { "idle", tZONE, -HOUR(12) }, /* International Date Line East */ /* ADDED BY Marco Nijdam */ { "dst", tDST, HOUR( 0) }, /* DST on (hour is ignored) */ /* End ADDED */ { NULL, 0, 0 } }; /* * Military timezone table. */ static const TABLE MilitaryTable[] = { { "a", tZONE, -HOUR( 1) }, { "b", tZONE, -HOUR( 2) }, { "c", tZONE, -HOUR( 3) }, { "d", tZONE, -HOUR( 4) }, { "e", tZONE, -HOUR( 5) }, { "f", tZONE, -HOUR( 6) }, { "g", tZONE, -HOUR( 7) }, { "h", tZONE, -HOUR( 8) }, { "i", tZONE, -HOUR( 9) }, { "k", tZONE, -HOUR(10) }, { "l", tZONE, -HOUR(11) }, { "m", tZONE, -HOUR(12) }, { "n", tZONE, HOUR( 1) }, { "o", tZONE, HOUR( 2) }, { "p", tZONE, HOUR( 3) }, { "q", tZONE, HOUR( 4) }, { "r", tZONE, HOUR( 5) }, { "s", tZONE, HOUR( 6) }, { "t", tZONE, HOUR( 7) }, { "u", tZONE, HOUR( 8) }, { "v", tZONE, HOUR( 9) }, { "w", tZONE, HOUR( 10) }, { "x", tZONE, HOUR( 11) }, { "y", tZONE, HOUR( 12) }, { "z", tZONE, HOUR( 0) }, { NULL, 0, 0 } }; /* * Dump error messages in the bit bucket. */ static void TclDateerror( YYLTYPE* location, DateInfo* infoPtr, const char *s) { Tcl_Obj* t; Tcl_AppendToObj(infoPtr->messages, infoPtr->separatrix, -1); Tcl_AppendToObj(infoPtr->messages, s, -1); Tcl_AppendToObj(infoPtr->messages, " (characters ", -1); t = Tcl_NewIntObj(location->first_column); Tcl_IncrRefCount(t); Tcl_AppendObjToObj(infoPtr->messages, t); Tcl_DecrRefCount(t); Tcl_AppendToObj(infoPtr->messages, "-", -1); t = Tcl_NewIntObj(location->last_column); Tcl_IncrRefCount(t); Tcl_AppendObjToObj(infoPtr->messages, t); Tcl_DecrRefCount(t); Tcl_AppendToObj(infoPtr->messages, ")", -1); infoPtr->separatrix = "\n"; } static time_t ToSeconds( time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian) { if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) { return -1; } switch (Meridian) { case MER24: if (Hours < 0 || Hours > 23) { return -1; } return (Hours * 60L + Minutes) * 60L + Seconds; case MERam: if (Hours < 1 || Hours > 12) { return -1; } return ((Hours % 12) * 60L + Minutes) * 60L + Seconds; case MERpm: if (Hours < 1 || Hours > 12) { return -1; } return (((Hours % 12) + 12) * 60L + Minutes) * 60L + Seconds; } return -1; /* Should never be reached */ } static int LookupWord( YYSTYPE* yylvalPtr, char *buff) { register char *p; register char *q; register const TABLE *tp; int i, abbrev; /* * Make it lowercase. */ Tcl_UtfToLower(buff); if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) { yylvalPtr->Meridian = MERam; return tMERIDIAN; } if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) { yylvalPtr->Meridian = MERpm; return tMERIDIAN; } /* * See if we have an abbreviation for a month. */ if (strlen(buff) == 3) { abbrev = 1; } else if (strlen(buff) == 4 && buff[3] == '.') { abbrev = 1; buff[3] = '\0'; } else { abbrev = 0; } for (tp = MonthDayTable; tp->name; tp++) { if (abbrev) { if (strncmp(buff, tp->name, 3) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } else if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } for (tp = TimezoneTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } for (tp = UnitsTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } /* * Strip off any plural and try the units table again. */ i = strlen(buff) - 1; if (i > 0 && buff[i] == 's') { buff[i] = '\0'; for (tp = UnitsTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } } for (tp = OtherTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } /* * Military timezones. */ if (buff[1] == '\0' && !(*buff & 0x80) && isalpha(UCHAR(*buff))) { /* INTL: ISO only */ for (tp = MilitaryTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } } /* * Drop out any periods and try the timezone table again. */ for (i = 0, p = q = buff; *q; q++) { if (*q != '.') { *p++ = *q; } else { i++; } } *p = '\0'; if (i) { for (tp = TimezoneTable; tp->name; tp++) { if (strcmp(buff, tp->name) == 0) { yylvalPtr->Number = tp->value; return tp->type; } } } return tID; } static int TclDatelex( YYSTYPE* yylvalPtr, YYLTYPE* location, DateInfo *info) { register char c; register char *p; char buff[20]; int Count; location->first_column = yyInput - info->dateStart; for ( ; ; ) { while (isspace(UCHAR(*yyInput))) { yyInput++; } if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */ /* * Convert the string into a number; count the number of digits. */ Count = 0; for (yylvalPtr->Number = 0; isdigit(UCHAR(c = *yyInput++)); ) { /* INTL: digit */ yylvalPtr->Number = 10 * yylvalPtr->Number + c - '0'; Count++; } yyInput--; yyDigitCount = Count; /* * A number with 6 or more digits is considered an ISO 8601 base. */ if (Count >= 6) { location->last_column = yyInput - info->dateStart - 1; return tISOBASE; } else { location->last_column = yyInput - info->dateStart - 1; return tUNUMBER; } } if (!(c & 0x80) && isalpha(UCHAR(c))) { /* INTL: ISO only. */ for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */ || c == '.'; ) { if (p < &buff[sizeof buff - 1]) { *p++ = c; } } *p = '\0'; yyInput--; location->last_column = yyInput - info->dateStart - 1; return LookupWord(yylvalPtr, buff); } if (c != '(') { location->last_column = yyInput - info->dateStart; return *yyInput++; } Count = 0; do { c = *yyInput++; if (c == '\0') { location->last_column = yyInput - info->dateStart - 1; return c; } else if (c == '(') { Count++; } else if (c == ')') { Count--; } } while (Count > 0); } } int TclClockOldscanObjCmd( ClientData clientData, /* Unused */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Count of paraneters */ Tcl_Obj *const *objv) /* Parameters */ { Tcl_Obj *result, *resultElement; int yr, mo, da; DateInfo dateInfo; DateInfo* info = &dateInfo; int status; if (objc != 5) { Tcl_WrongNumArgs(interp, 1, objv, "stringToParse baseYear baseMonth baseDay" ); return TCL_ERROR; } yyInput = Tcl_GetString( objv[1] ); dateInfo.dateStart = yyInput; yyHaveDate = 0; if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK || Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK || Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) { return TCL_ERROR; } yyYear = yr; yyMonth = mo; yyDay = da; yyHaveTime = 0; yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24; yyHaveZone = 0; yyTimezone = 0; yyDSTmode = DSTmaybe; yyHaveOrdinalMonth = 0; yyMonthOrdinal = 0; yyHaveDay = 0; yyDayOrdinal = 0; yyDayNumber = 0; yyHaveRel = 0; yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL; dateInfo.messages = Tcl_NewObj(); dateInfo.separatrix = ""; Tcl_IncrRefCount(dateInfo.messages); status = yyparse(&dateInfo); if (status == 1) { Tcl_SetObjResult(interp, dateInfo.messages); Tcl_DecrRefCount(dateInfo.messages); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL); return TCL_ERROR; } else if (status == 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1)); Tcl_DecrRefCount(dateInfo.messages); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); return TCL_ERROR; } else if (status != 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj("Unknown status returned " "from date parser. Please " "report this error as a " "bug in Tcl.", -1)); Tcl_DecrRefCount(dateInfo.messages); Tcl_SetErrorCode(interp, "TCL", "BUG", NULL); return TCL_ERROR; } Tcl_DecrRefCount(dateInfo.messages); if (yyHaveDate > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj("more than one date in string", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); return TCL_ERROR; } if (yyHaveTime > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj("more than one time of day in string", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); return TCL_ERROR; } if (yyHaveZone > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj("more than one time zone in string", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); return TCL_ERROR; } if (yyHaveDay > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj("more than one weekday in string", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); return TCL_ERROR; } if (yyHaveOrdinalMonth > 1) { Tcl_SetObjResult(interp, Tcl_NewStringObj("more than one ordinal month in string", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); return TCL_ERROR; } result = Tcl_NewObj(); resultElement = Tcl_NewObj(); if (yyHaveDate) { Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyYear)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyMonth)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyDay)); } Tcl_ListObjAppendElement(interp, result, resultElement); if (yyHaveTime) { Tcl_ListObjAppendElement(interp, result, Tcl_NewIntObj((int) ToSeconds(yyHour, yyMinutes, yySeconds, yyMeridian))); } else { Tcl_ListObjAppendElement(interp, result, Tcl_NewObj()); } resultElement = Tcl_NewObj(); if (yyHaveZone) { Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) -yyTimezone)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj(1 - yyDSTmode)); } Tcl_ListObjAppendElement(interp, result, resultElement); resultElement = Tcl_NewObj(); if (yyHaveRel) { Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyRelMonth)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyRelDay)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyRelSeconds)); } Tcl_ListObjAppendElement(interp, result, resultElement); resultElement = Tcl_NewObj(); if (yyHaveDay && !yyHaveDate) { Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyDayOrdinal)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyDayNumber)); } Tcl_ListObjAppendElement(interp, result, resultElement); resultElement = Tcl_NewObj(); if (yyHaveOrdinalMonth) { Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyMonthOrdinal)); Tcl_ListObjAppendElement(interp, resultElement, Tcl_NewIntObj((int) yyMonth)); } Tcl_ListObjAppendElement(interp, result, resultElement); Tcl_SetObjResult(interp, result); return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tcl.decls0000644000175000017500000017707012663660065015015 0ustar sergeisergei# tcl.decls -- # # This file contains the declarations for all supported public # functions that are exported by the Tcl library via the stubs table. # This file is used to generate the tclDecls.h, tclPlatDecls.h # and tclStubInit.c files. # # Copyright (c) 1998-1999 by Scriptics Corporation. # Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved. # Copyright (c) 2007 Daniel A. Steffen # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. library tcl # Define the tcl interface with several sub interfaces: # tclPlat - platform specific public # tclInt - generic private # tclPlatInt - platform specific private interface tcl hooks {tclPlat tclInt tclIntPlat} scspec EXTERN # Declare each of the functions in the public Tcl interface. Note that # the an index should never be reused for a different function in order # to preserve backwards compatibility. declare 0 { int Tcl_PkgProvideEx(Tcl_Interp *interp, const char *name, const char *version, const void *clientData) } declare 1 { CONST84_RETURN char *Tcl_PkgRequireEx(Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr) } declare 2 { TCL_NORETURN void Tcl_Panic(const char *format, ...) } declare 3 { char *Tcl_Alloc(unsigned int size) } declare 4 { void Tcl_Free(char *ptr) } declare 5 { char *Tcl_Realloc(char *ptr, unsigned int size) } declare 6 { char *Tcl_DbCkalloc(unsigned int size, const char *file, int line) } declare 7 { void Tcl_DbCkfree(char *ptr, const char *file, int line) } declare 8 { char *Tcl_DbCkrealloc(char *ptr, unsigned int size, const char *file, int line) } # Tcl_CreateFileHandler and Tcl_DeleteFileHandler are only available on unix, # but they are part of the old generic interface, so we include them here for # compatibility reasons. declare 9 unix { void Tcl_CreateFileHandler(int fd, int mask, Tcl_FileProc *proc, ClientData clientData) } declare 10 unix { void Tcl_DeleteFileHandler(int fd) } declare 11 { void Tcl_SetTimer(const Tcl_Time *timePtr) } declare 12 { void Tcl_Sleep(int ms) } declare 13 { int Tcl_WaitForEvent(const Tcl_Time *timePtr) } declare 14 { int Tcl_AppendAllObjTypes(Tcl_Interp *interp, Tcl_Obj *objPtr) } declare 15 { void Tcl_AppendStringsToObj(Tcl_Obj *objPtr, ...) } declare 16 { void Tcl_AppendToObj(Tcl_Obj *objPtr, const char *bytes, int length) } declare 17 { Tcl_Obj *Tcl_ConcatObj(int objc, Tcl_Obj *const objv[]) } declare 18 { int Tcl_ConvertToType(Tcl_Interp *interp, Tcl_Obj *objPtr, const Tcl_ObjType *typePtr) } declare 19 { void Tcl_DbDecrRefCount(Tcl_Obj *objPtr, const char *file, int line) } declare 20 { void Tcl_DbIncrRefCount(Tcl_Obj *objPtr, const char *file, int line) } declare 21 { int Tcl_DbIsShared(Tcl_Obj *objPtr, const char *file, int line) } declare 22 { Tcl_Obj *Tcl_DbNewBooleanObj(int boolValue, const char *file, int line) } declare 23 { Tcl_Obj *Tcl_DbNewByteArrayObj(const unsigned char *bytes, int length, const char *file, int line) } declare 24 { Tcl_Obj *Tcl_DbNewDoubleObj(double doubleValue, const char *file, int line) } declare 25 { Tcl_Obj *Tcl_DbNewListObj(int objc, Tcl_Obj *const *objv, const char *file, int line) } declare 26 { Tcl_Obj *Tcl_DbNewLongObj(long longValue, const char *file, int line) } declare 27 { Tcl_Obj *Tcl_DbNewObj(const char *file, int line) } declare 28 { Tcl_Obj *Tcl_DbNewStringObj(const char *bytes, int length, const char *file, int line) } declare 29 { Tcl_Obj *Tcl_DuplicateObj(Tcl_Obj *objPtr) } declare 30 { void TclFreeObj(Tcl_Obj *objPtr) } declare 31 { int Tcl_GetBoolean(Tcl_Interp *interp, const char *src, int *boolPtr) } declare 32 { int Tcl_GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *boolPtr) } declare 33 { unsigned char *Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, int *lengthPtr) } declare 34 { int Tcl_GetDouble(Tcl_Interp *interp, const char *src, double *doublePtr) } declare 35 { int Tcl_GetDoubleFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, double *doublePtr) } declare 36 { int Tcl_GetIndexFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, CONST84 char *const *tablePtr, const char *msg, int flags, int *indexPtr) } declare 37 { int Tcl_GetInt(Tcl_Interp *interp, const char *src, int *intPtr) } declare 38 { int Tcl_GetIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *intPtr) } declare 39 { int Tcl_GetLongFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr) } declare 40 { CONST86 Tcl_ObjType *Tcl_GetObjType(const char *typeName) } declare 41 { char *Tcl_GetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr) } declare 42 { void Tcl_InvalidateStringRep(Tcl_Obj *objPtr) } declare 43 { int Tcl_ListObjAppendList(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *elemListPtr) } declare 44 { int Tcl_ListObjAppendElement(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *objPtr) } declare 45 { int Tcl_ListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr, int *objcPtr, Tcl_Obj ***objvPtr) } declare 46 { int Tcl_ListObjIndex(Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj **objPtrPtr) } declare 47 { int Tcl_ListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr, int *lengthPtr) } declare 48 { int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, int first, int count, int objc, Tcl_Obj *const objv[]) } declare 49 { Tcl_Obj *Tcl_NewBooleanObj(int boolValue) } declare 50 { Tcl_Obj *Tcl_NewByteArrayObj(const unsigned char *bytes, int length) } declare 51 { Tcl_Obj *Tcl_NewDoubleObj(double doubleValue) } declare 52 { Tcl_Obj *Tcl_NewIntObj(int intValue) } declare 53 { Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *const objv[]) } declare 54 { Tcl_Obj *Tcl_NewLongObj(long longValue) } declare 55 { Tcl_Obj *Tcl_NewObj(void) } declare 56 { Tcl_Obj *Tcl_NewStringObj(const char *bytes, int length) } declare 57 { void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int boolValue) } declare 58 { unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, int length) } declare 59 { void Tcl_SetByteArrayObj(Tcl_Obj *objPtr, const unsigned char *bytes, int length) } declare 60 { void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue) } declare 61 { void Tcl_SetIntObj(Tcl_Obj *objPtr, int intValue) } declare 62 { void Tcl_SetListObj(Tcl_Obj *objPtr, int objc, Tcl_Obj *const objv[]) } declare 63 { void Tcl_SetLongObj(Tcl_Obj *objPtr, long longValue) } declare 64 { void Tcl_SetObjLength(Tcl_Obj *objPtr, int length) } declare 65 { void Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes, int length) } declare 66 { void Tcl_AddErrorInfo(Tcl_Interp *interp, const char *message) } declare 67 { void Tcl_AddObjErrorInfo(Tcl_Interp *interp, const char *message, int length) } declare 68 { void Tcl_AllowExceptions(Tcl_Interp *interp) } declare 69 { void Tcl_AppendElement(Tcl_Interp *interp, const char *element) } declare 70 { void Tcl_AppendResult(Tcl_Interp *interp, ...) } declare 71 { Tcl_AsyncHandler Tcl_AsyncCreate(Tcl_AsyncProc *proc, ClientData clientData) } declare 72 { void Tcl_AsyncDelete(Tcl_AsyncHandler async) } declare 73 { int Tcl_AsyncInvoke(Tcl_Interp *interp, int code) } declare 74 { void Tcl_AsyncMark(Tcl_AsyncHandler async) } declare 75 { int Tcl_AsyncReady(void) } declare 76 { void Tcl_BackgroundError(Tcl_Interp *interp) } declare 77 { char Tcl_Backslash(const char *src, int *readPtr) } declare 78 { int Tcl_BadChannelOption(Tcl_Interp *interp, const char *optionName, const char *optionList) } declare 79 { void Tcl_CallWhenDeleted(Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData) } declare 80 { void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, ClientData clientData) } declare 81 { int Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan) } declare 82 { int Tcl_CommandComplete(const char *cmd) } declare 83 { char *Tcl_Concat(int argc, CONST84 char *const *argv) } declare 84 { int Tcl_ConvertElement(const char *src, char *dst, int flags) } declare 85 { int Tcl_ConvertCountedElement(const char *src, int length, char *dst, int flags) } declare 86 { int Tcl_CreateAlias(Tcl_Interp *slave, const char *slaveCmd, Tcl_Interp *target, const char *targetCmd, int argc, CONST84 char *const *argv) } declare 87 { int Tcl_CreateAliasObj(Tcl_Interp *slave, const char *slaveCmd, Tcl_Interp *target, const char *targetCmd, int objc, Tcl_Obj *const objv[]) } declare 88 { Tcl_Channel Tcl_CreateChannel(const Tcl_ChannelType *typePtr, const char *chanName, ClientData instanceData, int mask) } declare 89 { void Tcl_CreateChannelHandler(Tcl_Channel chan, int mask, Tcl_ChannelProc *proc, ClientData clientData) } declare 90 { void Tcl_CreateCloseHandler(Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData) } declare 91 { Tcl_Command Tcl_CreateCommand(Tcl_Interp *interp, const char *cmdName, Tcl_CmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc) } declare 92 { void Tcl_CreateEventSource(Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, ClientData clientData) } declare 93 { void Tcl_CreateExitHandler(Tcl_ExitProc *proc, ClientData clientData) } declare 94 { Tcl_Interp *Tcl_CreateInterp(void) } declare 95 { void Tcl_CreateMathFunc(Tcl_Interp *interp, const char *name, int numArgs, Tcl_ValueType *argTypes, Tcl_MathProc *proc, ClientData clientData) } declare 96 { Tcl_Command Tcl_CreateObjCommand(Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc) } declare 97 { Tcl_Interp *Tcl_CreateSlave(Tcl_Interp *interp, const char *slaveName, int isSafe) } declare 98 { Tcl_TimerToken Tcl_CreateTimerHandler(int milliseconds, Tcl_TimerProc *proc, ClientData clientData) } declare 99 { Tcl_Trace Tcl_CreateTrace(Tcl_Interp *interp, int level, Tcl_CmdTraceProc *proc, ClientData clientData) } declare 100 { void Tcl_DeleteAssocData(Tcl_Interp *interp, const char *name) } declare 101 { void Tcl_DeleteChannelHandler(Tcl_Channel chan, Tcl_ChannelProc *proc, ClientData clientData) } declare 102 { void Tcl_DeleteCloseHandler(Tcl_Channel chan, Tcl_CloseProc *proc, ClientData clientData) } declare 103 { int Tcl_DeleteCommand(Tcl_Interp *interp, const char *cmdName) } declare 104 { int Tcl_DeleteCommandFromToken(Tcl_Interp *interp, Tcl_Command command) } declare 105 { void Tcl_DeleteEvents(Tcl_EventDeleteProc *proc, ClientData clientData) } declare 106 { void Tcl_DeleteEventSource(Tcl_EventSetupProc *setupProc, Tcl_EventCheckProc *checkProc, ClientData clientData) } declare 107 { void Tcl_DeleteExitHandler(Tcl_ExitProc *proc, ClientData clientData) } declare 108 { void Tcl_DeleteHashEntry(Tcl_HashEntry *entryPtr) } declare 109 { void Tcl_DeleteHashTable(Tcl_HashTable *tablePtr) } declare 110 { void Tcl_DeleteInterp(Tcl_Interp *interp) } declare 111 { void Tcl_DetachPids(int numPids, Tcl_Pid *pidPtr) } declare 112 { void Tcl_DeleteTimerHandler(Tcl_TimerToken token) } declare 113 { void Tcl_DeleteTrace(Tcl_Interp *interp, Tcl_Trace trace) } declare 114 { void Tcl_DontCallWhenDeleted(Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, ClientData clientData) } declare 115 { int Tcl_DoOneEvent(int flags) } declare 116 { void Tcl_DoWhenIdle(Tcl_IdleProc *proc, ClientData clientData) } declare 117 { char *Tcl_DStringAppend(Tcl_DString *dsPtr, const char *bytes, int length) } declare 118 { char *Tcl_DStringAppendElement(Tcl_DString *dsPtr, const char *element) } declare 119 { void Tcl_DStringEndSublist(Tcl_DString *dsPtr) } declare 120 { void Tcl_DStringFree(Tcl_DString *dsPtr) } declare 121 { void Tcl_DStringGetResult(Tcl_Interp *interp, Tcl_DString *dsPtr) } declare 122 { void Tcl_DStringInit(Tcl_DString *dsPtr) } declare 123 { void Tcl_DStringResult(Tcl_Interp *interp, Tcl_DString *dsPtr) } declare 124 { void Tcl_DStringSetLength(Tcl_DString *dsPtr, int length) } declare 125 { void Tcl_DStringStartSublist(Tcl_DString *dsPtr) } declare 126 { int Tcl_Eof(Tcl_Channel chan) } declare 127 { CONST84_RETURN char *Tcl_ErrnoId(void) } declare 128 { CONST84_RETURN char *Tcl_ErrnoMsg(int err) } declare 129 { int Tcl_Eval(Tcl_Interp *interp, const char *script) } # This is obsolete, use Tcl_FSEvalFile declare 130 { int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName) } declare 131 { int Tcl_EvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr) } declare 132 { void Tcl_EventuallyFree(ClientData clientData, Tcl_FreeProc *freeProc) } declare 133 { TCL_NORETURN void Tcl_Exit(int status) } declare 134 { int Tcl_ExposeCommand(Tcl_Interp *interp, const char *hiddenCmdToken, const char *cmdName) } declare 135 { int Tcl_ExprBoolean(Tcl_Interp *interp, const char *expr, int *ptr) } declare 136 { int Tcl_ExprBooleanObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *ptr) } declare 137 { int Tcl_ExprDouble(Tcl_Interp *interp, const char *expr, double *ptr) } declare 138 { int Tcl_ExprDoubleObj(Tcl_Interp *interp, Tcl_Obj *objPtr, double *ptr) } declare 139 { int Tcl_ExprLong(Tcl_Interp *interp, const char *expr, long *ptr) } declare 140 { int Tcl_ExprLongObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *ptr) } declare 141 { int Tcl_ExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **resultPtrPtr) } declare 142 { int Tcl_ExprString(Tcl_Interp *interp, const char *expr) } declare 143 { void Tcl_Finalize(void) } declare 144 { void Tcl_FindExecutable(const char *argv0) } declare 145 { Tcl_HashEntry *Tcl_FirstHashEntry(Tcl_HashTable *tablePtr, Tcl_HashSearch *searchPtr) } declare 146 { int Tcl_Flush(Tcl_Channel chan) } declare 147 { void Tcl_FreeResult(Tcl_Interp *interp) } declare 148 { int Tcl_GetAlias(Tcl_Interp *interp, const char *slaveCmd, Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr, int *argcPtr, CONST84 char ***argvPtr) } declare 149 { int Tcl_GetAliasObj(Tcl_Interp *interp, const char *slaveCmd, Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr, int *objcPtr, Tcl_Obj ***objv) } declare 150 { ClientData Tcl_GetAssocData(Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc **procPtr) } declare 151 { Tcl_Channel Tcl_GetChannel(Tcl_Interp *interp, const char *chanName, int *modePtr) } declare 152 { int Tcl_GetChannelBufferSize(Tcl_Channel chan) } declare 153 { int Tcl_GetChannelHandle(Tcl_Channel chan, int direction, ClientData *handlePtr) } declare 154 { ClientData Tcl_GetChannelInstanceData(Tcl_Channel chan) } declare 155 { int Tcl_GetChannelMode(Tcl_Channel chan) } declare 156 { CONST84_RETURN char *Tcl_GetChannelName(Tcl_Channel chan) } declare 157 { int Tcl_GetChannelOption(Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, Tcl_DString *dsPtr) } declare 158 { CONST86 Tcl_ChannelType *Tcl_GetChannelType(Tcl_Channel chan) } declare 159 { int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr) } declare 160 { CONST84_RETURN char *Tcl_GetCommandName(Tcl_Interp *interp, Tcl_Command command) } declare 161 { int Tcl_GetErrno(void) } declare 162 { CONST84_RETURN char *Tcl_GetHostName(void) } declare 163 { int Tcl_GetInterpPath(Tcl_Interp *askInterp, Tcl_Interp *slaveInterp) } declare 164 { Tcl_Interp *Tcl_GetMaster(Tcl_Interp *interp) } declare 165 { const char *Tcl_GetNameOfExecutable(void) } declare 166 { Tcl_Obj *Tcl_GetObjResult(Tcl_Interp *interp) } # Tcl_GetOpenFile is only available on unix, but it is a part of the old # generic interface, so we inlcude it here for compatibility reasons. declare 167 unix { int Tcl_GetOpenFile(Tcl_Interp *interp, const char *chanID, int forWriting, int checkUsage, ClientData *filePtr) } # Obsolete. Should now use Tcl_FSGetPathType which is objectified # and therefore usually faster. declare 168 { Tcl_PathType Tcl_GetPathType(const char *path) } declare 169 { int Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr) } declare 170 { int Tcl_GetsObj(Tcl_Channel chan, Tcl_Obj *objPtr) } declare 171 { int Tcl_GetServiceMode(void) } declare 172 { Tcl_Interp *Tcl_GetSlave(Tcl_Interp *interp, const char *slaveName) } declare 173 { Tcl_Channel Tcl_GetStdChannel(int type) } declare 174 { CONST84_RETURN char *Tcl_GetStringResult(Tcl_Interp *interp) } declare 175 { CONST84_RETURN char *Tcl_GetVar(Tcl_Interp *interp, const char *varName, int flags) } declare 176 { CONST84_RETURN char *Tcl_GetVar2(Tcl_Interp *interp, const char *part1, const char *part2, int flags) } declare 177 { int Tcl_GlobalEval(Tcl_Interp *interp, const char *command) } declare 178 { int Tcl_GlobalEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr) } declare 179 { int Tcl_HideCommand(Tcl_Interp *interp, const char *cmdName, const char *hiddenCmdToken) } declare 180 { int Tcl_Init(Tcl_Interp *interp) } declare 181 { void Tcl_InitHashTable(Tcl_HashTable *tablePtr, int keyType) } declare 182 { int Tcl_InputBlocked(Tcl_Channel chan) } declare 183 { int Tcl_InputBuffered(Tcl_Channel chan) } declare 184 { int Tcl_InterpDeleted(Tcl_Interp *interp) } declare 185 { int Tcl_IsSafe(Tcl_Interp *interp) } # Obsolete, use Tcl_FSJoinPath declare 186 { char *Tcl_JoinPath(int argc, CONST84 char *const *argv, Tcl_DString *resultPtr) } declare 187 { int Tcl_LinkVar(Tcl_Interp *interp, const char *varName, char *addr, int type) } # This slot is reserved for use by the plus patch: # declare 188 { # Tcl_MainLoop # } declare 189 { Tcl_Channel Tcl_MakeFileChannel(ClientData handle, int mode) } declare 190 { int Tcl_MakeSafe(Tcl_Interp *interp) } declare 191 { Tcl_Channel Tcl_MakeTcpClientChannel(ClientData tcpSocket) } declare 192 { char *Tcl_Merge(int argc, CONST84 char *const *argv) } declare 193 { Tcl_HashEntry *Tcl_NextHashEntry(Tcl_HashSearch *searchPtr) } declare 194 { void Tcl_NotifyChannel(Tcl_Channel channel, int mask) } declare 195 { Tcl_Obj *Tcl_ObjGetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags) } declare 196 { Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags) } declare 197 { Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc, CONST84 char **argv, int flags) } # This is obsolete, use Tcl_FSOpenFileChannel declare 198 { Tcl_Channel Tcl_OpenFileChannel(Tcl_Interp *interp, const char *fileName, const char *modeString, int permissions) } declare 199 { Tcl_Channel Tcl_OpenTcpClient(Tcl_Interp *interp, int port, const char *address, const char *myaddr, int myport, int async) } declare 200 { Tcl_Channel Tcl_OpenTcpServer(Tcl_Interp *interp, int port, const char *host, Tcl_TcpAcceptProc *acceptProc, ClientData callbackData) } declare 201 { void Tcl_Preserve(ClientData data) } declare 202 { void Tcl_PrintDouble(Tcl_Interp *interp, double value, char *dst) } declare 203 { int Tcl_PutEnv(const char *assignment) } declare 204 { CONST84_RETURN char *Tcl_PosixError(Tcl_Interp *interp) } declare 205 { void Tcl_QueueEvent(Tcl_Event *evPtr, Tcl_QueuePosition position) } declare 206 { int Tcl_Read(Tcl_Channel chan, char *bufPtr, int toRead) } declare 207 { void Tcl_ReapDetachedProcs(void) } declare 208 { int Tcl_RecordAndEval(Tcl_Interp *interp, const char *cmd, int flags) } declare 209 { int Tcl_RecordAndEvalObj(Tcl_Interp *interp, Tcl_Obj *cmdPtr, int flags) } declare 210 { void Tcl_RegisterChannel(Tcl_Interp *interp, Tcl_Channel chan) } declare 211 { void Tcl_RegisterObjType(const Tcl_ObjType *typePtr) } declare 212 { Tcl_RegExp Tcl_RegExpCompile(Tcl_Interp *interp, const char *pattern) } declare 213 { int Tcl_RegExpExec(Tcl_Interp *interp, Tcl_RegExp regexp, const char *text, const char *start) } declare 214 { int Tcl_RegExpMatch(Tcl_Interp *interp, const char *text, const char *pattern) } declare 215 { void Tcl_RegExpRange(Tcl_RegExp regexp, int index, CONST84 char **startPtr, CONST84 char **endPtr) } declare 216 { void Tcl_Release(ClientData clientData) } declare 217 { void Tcl_ResetResult(Tcl_Interp *interp) } declare 218 { int Tcl_ScanElement(const char *src, int *flagPtr) } declare 219 { int Tcl_ScanCountedElement(const char *src, int length, int *flagPtr) } # Obsolete declare 220 { int Tcl_SeekOld(Tcl_Channel chan, int offset, int mode) } declare 221 { int Tcl_ServiceAll(void) } declare 222 { int Tcl_ServiceEvent(int flags) } declare 223 { void Tcl_SetAssocData(Tcl_Interp *interp, const char *name, Tcl_InterpDeleteProc *proc, ClientData clientData) } declare 224 { void Tcl_SetChannelBufferSize(Tcl_Channel chan, int sz) } declare 225 { int Tcl_SetChannelOption(Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, const char *newValue) } declare 226 { int Tcl_SetCommandInfo(Tcl_Interp *interp, const char *cmdName, const Tcl_CmdInfo *infoPtr) } declare 227 { void Tcl_SetErrno(int err) } declare 228 { void Tcl_SetErrorCode(Tcl_Interp *interp, ...) } declare 229 { void Tcl_SetMaxBlockTime(const Tcl_Time *timePtr) } declare 230 { void Tcl_SetPanicProc(TCL_NORETURN1 Tcl_PanicProc *panicProc) } declare 231 { int Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth) } declare 232 { void Tcl_SetResult(Tcl_Interp *interp, char *result, Tcl_FreeProc *freeProc) } declare 233 { int Tcl_SetServiceMode(int mode) } declare 234 { void Tcl_SetObjErrorCode(Tcl_Interp *interp, Tcl_Obj *errorObjPtr) } declare 235 { void Tcl_SetObjResult(Tcl_Interp *interp, Tcl_Obj *resultObjPtr) } declare 236 { void Tcl_SetStdChannel(Tcl_Channel channel, int type) } declare 237 { CONST84_RETURN char *Tcl_SetVar(Tcl_Interp *interp, const char *varName, const char *newValue, int flags) } declare 238 { CONST84_RETURN char *Tcl_SetVar2(Tcl_Interp *interp, const char *part1, const char *part2, const char *newValue, int flags) } declare 239 { CONST84_RETURN char *Tcl_SignalId(int sig) } declare 240 { CONST84_RETURN char *Tcl_SignalMsg(int sig) } declare 241 { void Tcl_SourceRCFile(Tcl_Interp *interp) } declare 242 { int Tcl_SplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr, CONST84 char ***argvPtr) } # Obsolete, use Tcl_FSSplitPath declare 243 { void Tcl_SplitPath(const char *path, int *argcPtr, CONST84 char ***argvPtr) } declare 244 { void Tcl_StaticPackage(Tcl_Interp *interp, const char *pkgName, Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc) } declare 245 { int Tcl_StringMatch(const char *str, const char *pattern) } # Obsolete declare 246 { int Tcl_TellOld(Tcl_Channel chan) } declare 247 { int Tcl_TraceVar(Tcl_Interp *interp, const char *varName, int flags, Tcl_VarTraceProc *proc, ClientData clientData) } declare 248 { int Tcl_TraceVar2(Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *proc, ClientData clientData) } declare 249 { char *Tcl_TranslateFileName(Tcl_Interp *interp, const char *name, Tcl_DString *bufferPtr) } declare 250 { int Tcl_Ungets(Tcl_Channel chan, const char *str, int len, int atHead) } declare 251 { void Tcl_UnlinkVar(Tcl_Interp *interp, const char *varName) } declare 252 { int Tcl_UnregisterChannel(Tcl_Interp *interp, Tcl_Channel chan) } declare 253 { int Tcl_UnsetVar(Tcl_Interp *interp, const char *varName, int flags) } declare 254 { int Tcl_UnsetVar2(Tcl_Interp *interp, const char *part1, const char *part2, int flags) } declare 255 { void Tcl_UntraceVar(Tcl_Interp *interp, const char *varName, int flags, Tcl_VarTraceProc *proc, ClientData clientData) } declare 256 { void Tcl_UntraceVar2(Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *proc, ClientData clientData) } declare 257 { void Tcl_UpdateLinkedVar(Tcl_Interp *interp, const char *varName) } declare 258 { int Tcl_UpVar(Tcl_Interp *interp, const char *frameName, const char *varName, const char *localName, int flags) } declare 259 { int Tcl_UpVar2(Tcl_Interp *interp, const char *frameName, const char *part1, const char *part2, const char *localName, int flags) } declare 260 { int Tcl_VarEval(Tcl_Interp *interp, ...) } declare 261 { ClientData Tcl_VarTraceInfo(Tcl_Interp *interp, const char *varName, int flags, Tcl_VarTraceProc *procPtr, ClientData prevClientData) } declare 262 { ClientData Tcl_VarTraceInfo2(Tcl_Interp *interp, const char *part1, const char *part2, int flags, Tcl_VarTraceProc *procPtr, ClientData prevClientData) } declare 263 { int Tcl_Write(Tcl_Channel chan, const char *s, int slen) } declare 264 { void Tcl_WrongNumArgs(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], const char *message) } declare 265 { int Tcl_DumpActiveMemory(const char *fileName) } declare 266 { void Tcl_ValidateAllMemory(const char *file, int line) } declare 267 { void Tcl_AppendResultVA(Tcl_Interp *interp, va_list argList) } declare 268 { void Tcl_AppendStringsToObjVA(Tcl_Obj *objPtr, va_list argList) } declare 269 { char *Tcl_HashStats(Tcl_HashTable *tablePtr) } declare 270 { CONST84_RETURN char *Tcl_ParseVar(Tcl_Interp *interp, const char *start, CONST84 char **termPtr) } declare 271 { CONST84_RETURN char *Tcl_PkgPresent(Tcl_Interp *interp, const char *name, const char *version, int exact) } declare 272 { CONST84_RETURN char *Tcl_PkgPresentEx(Tcl_Interp *interp, const char *name, const char *version, int exact, void *clientDataPtr) } declare 273 { int Tcl_PkgProvide(Tcl_Interp *interp, const char *name, const char *version) } # TIP #268: The internally used new Require function is in slot 573. declare 274 { CONST84_RETURN char *Tcl_PkgRequire(Tcl_Interp *interp, const char *name, const char *version, int exact) } declare 275 { void Tcl_SetErrorCodeVA(Tcl_Interp *interp, va_list argList) } declare 276 { int Tcl_VarEvalVA(Tcl_Interp *interp, va_list argList) } declare 277 { Tcl_Pid Tcl_WaitPid(Tcl_Pid pid, int *statPtr, int options) } declare 278 { TCL_NORETURN void Tcl_PanicVA(const char *format, va_list argList) } declare 279 { void Tcl_GetVersion(int *major, int *minor, int *patchLevel, int *type) } declare 280 { void Tcl_InitMemory(Tcl_Interp *interp) } # Andreas Kupries , 03/21/1999 # "Trf-Patch for filtering channels" # # C-Level API for (un)stacking of channels. This allows the introduction # of filtering channels with relatively little changes to the core. # This patch was created in cooperation with Jan Nijtmans j.nijtmans@chello.nl # and is therefore part of his plus-patches too. # # It would have been possible to place the following definitions according # to the alphabetical order used elsewhere in this file, but I decided # against that to ease the maintenance of the patch across new tcl versions # (patch usually has no problems to integrate the patch file for the last # version into the new one). declare 281 { Tcl_Channel Tcl_StackChannel(Tcl_Interp *interp, const Tcl_ChannelType *typePtr, ClientData instanceData, int mask, Tcl_Channel prevChan) } declare 282 { int Tcl_UnstackChannel(Tcl_Interp *interp, Tcl_Channel chan) } declare 283 { Tcl_Channel Tcl_GetStackedChannel(Tcl_Channel chan) } # 284 was reserved, but added in 8.4a2 declare 284 { void Tcl_SetMainLoop(Tcl_MainLoopProc *proc) } # Reserved for future use (8.0.x vs. 8.1) # declare 285 { # } # Added in 8.1: declare 286 { void Tcl_AppendObjToObj(Tcl_Obj *objPtr, Tcl_Obj *appendObjPtr) } declare 287 { Tcl_Encoding Tcl_CreateEncoding(const Tcl_EncodingType *typePtr) } declare 288 { void Tcl_CreateThreadExitHandler(Tcl_ExitProc *proc, ClientData clientData) } declare 289 { void Tcl_DeleteThreadExitHandler(Tcl_ExitProc *proc, ClientData clientData) } declare 290 { void Tcl_DiscardResult(Tcl_SavedResult *statePtr) } declare 291 { int Tcl_EvalEx(Tcl_Interp *interp, const char *script, int numBytes, int flags) } declare 292 { int Tcl_EvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags) } declare 293 { int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) } declare 294 { void Tcl_ExitThread(int status) } declare 295 { int Tcl_ExternalToUtf(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) } declare 296 { char *Tcl_ExternalToUtfDString(Tcl_Encoding encoding, const char *src, int srcLen, Tcl_DString *dsPtr) } declare 297 { void Tcl_FinalizeThread(void) } declare 298 { void Tcl_FinalizeNotifier(ClientData clientData) } declare 299 { void Tcl_FreeEncoding(Tcl_Encoding encoding) } declare 300 { Tcl_ThreadId Tcl_GetCurrentThread(void) } declare 301 { Tcl_Encoding Tcl_GetEncoding(Tcl_Interp *interp, const char *name) } declare 302 { CONST84_RETURN char *Tcl_GetEncodingName(Tcl_Encoding encoding) } declare 303 { void Tcl_GetEncodingNames(Tcl_Interp *interp) } declare 304 { int Tcl_GetIndexFromObjStruct(Tcl_Interp *interp, Tcl_Obj *objPtr, const void *tablePtr, int offset, const char *msg, int flags, int *indexPtr) } declare 305 { void *Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr, int size) } declare 306 { Tcl_Obj *Tcl_GetVar2Ex(Tcl_Interp *interp, const char *part1, const char *part2, int flags) } declare 307 { ClientData Tcl_InitNotifier(void) } declare 308 { void Tcl_MutexLock(Tcl_Mutex *mutexPtr) } declare 309 { void Tcl_MutexUnlock(Tcl_Mutex *mutexPtr) } declare 310 { void Tcl_ConditionNotify(Tcl_Condition *condPtr) } declare 311 { void Tcl_ConditionWait(Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr, const Tcl_Time *timePtr) } declare 312 { int Tcl_NumUtfChars(const char *src, int length) } declare 313 { int Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr, int charsToRead, int appendFlag) } declare 314 { void Tcl_RestoreResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr) } declare 315 { void Tcl_SaveResult(Tcl_Interp *interp, Tcl_SavedResult *statePtr) } declare 316 { int Tcl_SetSystemEncoding(Tcl_Interp *interp, const char *name) } declare 317 { Tcl_Obj *Tcl_SetVar2Ex(Tcl_Interp *interp, const char *part1, const char *part2, Tcl_Obj *newValuePtr, int flags) } declare 318 { void Tcl_ThreadAlert(Tcl_ThreadId threadId) } declare 319 { void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId, Tcl_Event *evPtr, Tcl_QueuePosition position) } declare 320 { Tcl_UniChar Tcl_UniCharAtIndex(const char *src, int index) } declare 321 { Tcl_UniChar Tcl_UniCharToLower(int ch) } declare 322 { Tcl_UniChar Tcl_UniCharToTitle(int ch) } declare 323 { Tcl_UniChar Tcl_UniCharToUpper(int ch) } declare 324 { int Tcl_UniCharToUtf(int ch, char *buf) } declare 325 { CONST84_RETURN char *Tcl_UtfAtIndex(const char *src, int index) } declare 326 { int Tcl_UtfCharComplete(const char *src, int length) } declare 327 { int Tcl_UtfBackslash(const char *src, int *readPtr, char *dst) } declare 328 { CONST84_RETURN char *Tcl_UtfFindFirst(const char *src, int ch) } declare 329 { CONST84_RETURN char *Tcl_UtfFindLast(const char *src, int ch) } declare 330 { CONST84_RETURN char *Tcl_UtfNext(const char *src) } declare 331 { CONST84_RETURN char *Tcl_UtfPrev(const char *src, const char *start) } declare 332 { 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) } declare 333 { char *Tcl_UtfToExternalDString(Tcl_Encoding encoding, const char *src, int srcLen, Tcl_DString *dsPtr) } declare 334 { int Tcl_UtfToLower(char *src) } declare 335 { int Tcl_UtfToTitle(char *src) } declare 336 { int Tcl_UtfToUniChar(const char *src, Tcl_UniChar *chPtr) } declare 337 { int Tcl_UtfToUpper(char *src) } declare 338 { int Tcl_WriteChars(Tcl_Channel chan, const char *src, int srcLen) } declare 339 { int Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr) } declare 340 { char *Tcl_GetString(Tcl_Obj *objPtr) } declare 341 { CONST84_RETURN char *Tcl_GetDefaultEncodingDir(void) } declare 342 { void Tcl_SetDefaultEncodingDir(const char *path) } declare 343 { void Tcl_AlertNotifier(ClientData clientData) } declare 344 { void Tcl_ServiceModeHook(int mode) } declare 345 { int Tcl_UniCharIsAlnum(int ch) } declare 346 { int Tcl_UniCharIsAlpha(int ch) } declare 347 { int Tcl_UniCharIsDigit(int ch) } declare 348 { int Tcl_UniCharIsLower(int ch) } declare 349 { int Tcl_UniCharIsSpace(int ch) } declare 350 { int Tcl_UniCharIsUpper(int ch) } declare 351 { int Tcl_UniCharIsWordChar(int ch) } declare 352 { int Tcl_UniCharLen(const Tcl_UniChar *uniStr) } declare 353 { int Tcl_UniCharNcmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsigned long numChars) } declare 354 { char *Tcl_UniCharToUtfDString(const Tcl_UniChar *uniStr, int uniLength, Tcl_DString *dsPtr) } declare 355 { Tcl_UniChar *Tcl_UtfToUniCharDString(const char *src, int length, Tcl_DString *dsPtr) } declare 356 { Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, Tcl_Obj *patObj, int flags) } declare 357 { Tcl_Obj *Tcl_EvalTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr, int count) } declare 358 { void Tcl_FreeParse(Tcl_Parse *parsePtr) } declare 359 { void Tcl_LogCommandInfo(Tcl_Interp *interp, const char *script, const char *command, int length) } declare 360 { int Tcl_ParseBraces(Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append, CONST84 char **termPtr) } declare 361 { int Tcl_ParseCommand(Tcl_Interp *interp, const char *start, int numBytes, int nested, Tcl_Parse *parsePtr) } declare 362 { int Tcl_ParseExpr(Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr) } declare 363 { int Tcl_ParseQuotedString(Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append, CONST84 char **termPtr) } declare 364 { int Tcl_ParseVarName(Tcl_Interp *interp, const char *start, int numBytes, Tcl_Parse *parsePtr, int append) } # These 4 functions are obsolete, use Tcl_FSGetCwd, Tcl_FSChdir, # Tcl_FSAccess and Tcl_FSStat declare 365 { char *Tcl_GetCwd(Tcl_Interp *interp, Tcl_DString *cwdPtr) } declare 366 { int Tcl_Chdir(const char *dirName) } declare 367 { int Tcl_Access(const char *path, int mode) } declare 368 { int Tcl_Stat(const char *path, struct stat *bufPtr) } declare 369 { int Tcl_UtfNcmp(const char *s1, const char *s2, unsigned long n) } declare 370 { int Tcl_UtfNcasecmp(const char *s1, const char *s2, unsigned long n) } declare 371 { int Tcl_StringCaseMatch(const char *str, const char *pattern, int nocase) } declare 372 { int Tcl_UniCharIsControl(int ch) } declare 373 { int Tcl_UniCharIsGraph(int ch) } declare 374 { int Tcl_UniCharIsPrint(int ch) } declare 375 { int Tcl_UniCharIsPunct(int ch) } declare 376 { int Tcl_RegExpExecObj(Tcl_Interp *interp, Tcl_RegExp regexp, Tcl_Obj *textObj, int offset, int nmatches, int flags) } declare 377 { void Tcl_RegExpGetInfo(Tcl_RegExp regexp, Tcl_RegExpInfo *infoPtr) } declare 378 { Tcl_Obj *Tcl_NewUnicodeObj(const Tcl_UniChar *unicode, int numChars) } declare 379 { void Tcl_SetUnicodeObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int numChars) } declare 380 { int Tcl_GetCharLength(Tcl_Obj *objPtr) } declare 381 { Tcl_UniChar Tcl_GetUniChar(Tcl_Obj *objPtr, int index) } declare 382 { Tcl_UniChar *Tcl_GetUnicode(Tcl_Obj *objPtr) } declare 383 { Tcl_Obj *Tcl_GetRange(Tcl_Obj *objPtr, int first, int last) } declare 384 { void Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int length) } declare 385 { int Tcl_RegExpMatchObj(Tcl_Interp *interp, Tcl_Obj *textObj, Tcl_Obj *patternObj) } declare 386 { void Tcl_SetNotifier(Tcl_NotifierProcs *notifierProcPtr) } declare 387 { Tcl_Mutex *Tcl_GetAllocMutex(void) } declare 388 { int Tcl_GetChannelNames(Tcl_Interp *interp) } declare 389 { int Tcl_GetChannelNamesEx(Tcl_Interp *interp, const char *pattern) } declare 390 { int Tcl_ProcObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) } declare 391 { void Tcl_ConditionFinalize(Tcl_Condition *condPtr) } declare 392 { void Tcl_MutexFinalize(Tcl_Mutex *mutex) } declare 393 { int Tcl_CreateThread(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, ClientData clientData, int stackSize, int flags) } # Introduced in 8.3.2 declare 394 { int Tcl_ReadRaw(Tcl_Channel chan, char *dst, int bytesToRead) } declare 395 { int Tcl_WriteRaw(Tcl_Channel chan, const char *src, int srcLen) } declare 396 { Tcl_Channel Tcl_GetTopChannel(Tcl_Channel chan) } declare 397 { int Tcl_ChannelBuffered(Tcl_Channel chan) } declare 398 { CONST84_RETURN char *Tcl_ChannelName(const Tcl_ChannelType *chanTypePtr) } declare 399 { Tcl_ChannelTypeVersion Tcl_ChannelVersion( const Tcl_ChannelType *chanTypePtr) } declare 400 { Tcl_DriverBlockModeProc *Tcl_ChannelBlockModeProc( const Tcl_ChannelType *chanTypePtr) } declare 401 { Tcl_DriverCloseProc *Tcl_ChannelCloseProc( const Tcl_ChannelType *chanTypePtr) } declare 402 { Tcl_DriverClose2Proc *Tcl_ChannelClose2Proc( const Tcl_ChannelType *chanTypePtr) } declare 403 { Tcl_DriverInputProc *Tcl_ChannelInputProc( const Tcl_ChannelType *chanTypePtr) } declare 404 { Tcl_DriverOutputProc *Tcl_ChannelOutputProc( const Tcl_ChannelType *chanTypePtr) } declare 405 { Tcl_DriverSeekProc *Tcl_ChannelSeekProc( const Tcl_ChannelType *chanTypePtr) } declare 406 { Tcl_DriverSetOptionProc *Tcl_ChannelSetOptionProc( const Tcl_ChannelType *chanTypePtr) } declare 407 { Tcl_DriverGetOptionProc *Tcl_ChannelGetOptionProc( const Tcl_ChannelType *chanTypePtr) } declare 408 { Tcl_DriverWatchProc *Tcl_ChannelWatchProc( const Tcl_ChannelType *chanTypePtr) } declare 409 { Tcl_DriverGetHandleProc *Tcl_ChannelGetHandleProc( const Tcl_ChannelType *chanTypePtr) } declare 410 { Tcl_DriverFlushProc *Tcl_ChannelFlushProc( const Tcl_ChannelType *chanTypePtr) } declare 411 { Tcl_DriverHandlerProc *Tcl_ChannelHandlerProc( const Tcl_ChannelType *chanTypePtr) } # Introduced in 8.4a2 declare 412 { int Tcl_JoinThread(Tcl_ThreadId threadId, int *result) } declare 413 { int Tcl_IsChannelShared(Tcl_Channel channel) } declare 414 { int Tcl_IsChannelRegistered(Tcl_Interp *interp, Tcl_Channel channel) } declare 415 { void Tcl_CutChannel(Tcl_Channel channel) } declare 416 { void Tcl_SpliceChannel(Tcl_Channel channel) } declare 417 { void Tcl_ClearChannelHandlers(Tcl_Channel channel) } declare 418 { int Tcl_IsChannelExisting(const char *channelName) } declare 419 { int Tcl_UniCharNcasecmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsigned long numChars) } declare 420 { int Tcl_UniCharCaseMatch(const Tcl_UniChar *uniStr, const Tcl_UniChar *uniPattern, int nocase) } declare 421 { Tcl_HashEntry *Tcl_FindHashEntry(Tcl_HashTable *tablePtr, const void *key) } declare 422 { Tcl_HashEntry *Tcl_CreateHashEntry(Tcl_HashTable *tablePtr, const void *key, int *newPtr) } declare 423 { void Tcl_InitCustomHashTable(Tcl_HashTable *tablePtr, int keyType, const Tcl_HashKeyType *typePtr) } declare 424 { void Tcl_InitObjHashTable(Tcl_HashTable *tablePtr) } declare 425 { ClientData Tcl_CommandTraceInfo(Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *procPtr, ClientData prevClientData) } declare 426 { int Tcl_TraceCommand(Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, ClientData clientData) } declare 427 { void Tcl_UntraceCommand(Tcl_Interp *interp, const char *varName, int flags, Tcl_CommandTraceProc *proc, ClientData clientData) } declare 428 { char *Tcl_AttemptAlloc(unsigned int size) } declare 429 { char *Tcl_AttemptDbCkalloc(unsigned int size, const char *file, int line) } declare 430 { char *Tcl_AttemptRealloc(char *ptr, unsigned int size) } declare 431 { char *Tcl_AttemptDbCkrealloc(char *ptr, unsigned int size, const char *file, int line) } declare 432 { int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr, int length) } # TIP#10 (thread-aware channels) akupries declare 433 { Tcl_ThreadId Tcl_GetChannelThread(Tcl_Channel channel) } # introduced in 8.4a3 declare 434 { Tcl_UniChar *Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr, int *lengthPtr) } # TIP#15 (math function introspection) dkf declare 435 { int Tcl_GetMathFuncInfo(Tcl_Interp *interp, const char *name, int *numArgsPtr, Tcl_ValueType **argTypesPtr, Tcl_MathProc **procPtr, ClientData *clientDataPtr) } declare 436 { Tcl_Obj *Tcl_ListMathFuncs(Tcl_Interp *interp, const char *pattern) } # TIP#36 (better access to 'subst') dkf declare 437 { Tcl_Obj *Tcl_SubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) } # TIP#17 (virtual filesystem layer) vdarley declare 438 { int Tcl_DetachChannel(Tcl_Interp *interp, Tcl_Channel channel) } declare 439 { int Tcl_IsStandardChannel(Tcl_Channel channel) } declare 440 { int Tcl_FSCopyFile(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr) } declare 441 { int Tcl_FSCopyDirectory(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr) } declare 442 { int Tcl_FSCreateDirectory(Tcl_Obj *pathPtr) } declare 443 { int Tcl_FSDeleteFile(Tcl_Obj *pathPtr) } 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, Tcl_FSUnloadFileProc **unloadProcPtr) } declare 445 { int Tcl_FSMatchInDirectory(Tcl_Interp *interp, Tcl_Obj *result, Tcl_Obj *pathPtr, const char *pattern, Tcl_GlobTypeData *types) } declare 446 { Tcl_Obj *Tcl_FSLink(Tcl_Obj *pathPtr, Tcl_Obj *toPtr, int linkAction) } declare 447 { int Tcl_FSRemoveDirectory(Tcl_Obj *pathPtr, int recursive, Tcl_Obj **errorPtr) } declare 448 { int Tcl_FSRenameFile(Tcl_Obj *srcPathPtr, Tcl_Obj *destPathPtr) } declare 449 { int Tcl_FSLstat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf) } declare 450 { int Tcl_FSUtime(Tcl_Obj *pathPtr, struct utimbuf *tval) } declare 451 { int Tcl_FSFileAttrsGet(Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef) } declare 452 { int Tcl_FSFileAttrsSet(Tcl_Interp *interp, int index, Tcl_Obj *pathPtr, Tcl_Obj *objPtr) } declare 453 { const char *CONST86 *Tcl_FSFileAttrStrings(Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef) } declare 454 { int Tcl_FSStat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf) } declare 455 { int Tcl_FSAccess(Tcl_Obj *pathPtr, int mode) } declare 456 { Tcl_Channel Tcl_FSOpenFileChannel(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *modeString, int permissions) } declare 457 { Tcl_Obj *Tcl_FSGetCwd(Tcl_Interp *interp) } declare 458 { int Tcl_FSChdir(Tcl_Obj *pathPtr) } declare 459 { int Tcl_FSConvertToPathType(Tcl_Interp *interp, Tcl_Obj *pathPtr) } declare 460 { Tcl_Obj *Tcl_FSJoinPath(Tcl_Obj *listObj, int elements) } declare 461 { Tcl_Obj *Tcl_FSSplitPath(Tcl_Obj *pathPtr, int *lenPtr) } declare 462 { int Tcl_FSEqualPaths(Tcl_Obj *firstPtr, Tcl_Obj *secondPtr) } declare 463 { Tcl_Obj *Tcl_FSGetNormalizedPath(Tcl_Interp *interp, Tcl_Obj *pathPtr) } declare 464 { Tcl_Obj *Tcl_FSJoinToPath(Tcl_Obj *pathPtr, int objc, Tcl_Obj *const objv[]) } declare 465 { ClientData Tcl_FSGetInternalRep(Tcl_Obj *pathPtr, const Tcl_Filesystem *fsPtr) } declare 466 { Tcl_Obj *Tcl_FSGetTranslatedPath(Tcl_Interp *interp, Tcl_Obj *pathPtr) } declare 467 { int Tcl_FSEvalFile(Tcl_Interp *interp, Tcl_Obj *fileName) } declare 468 { Tcl_Obj *Tcl_FSNewNativePath(const Tcl_Filesystem *fromFilesystem, ClientData clientData) } declare 469 { const void *Tcl_FSGetNativePath(Tcl_Obj *pathPtr) } declare 470 { Tcl_Obj *Tcl_FSFileSystemInfo(Tcl_Obj *pathPtr) } declare 471 { Tcl_Obj *Tcl_FSPathSeparator(Tcl_Obj *pathPtr) } declare 472 { Tcl_Obj *Tcl_FSListVolumes(void) } declare 473 { int Tcl_FSRegister(ClientData clientData, const Tcl_Filesystem *fsPtr) } declare 474 { int Tcl_FSUnregister(const Tcl_Filesystem *fsPtr) } declare 475 { ClientData Tcl_FSData(const Tcl_Filesystem *fsPtr) } declare 476 { const char *Tcl_FSGetTranslatedStringPath(Tcl_Interp *interp, Tcl_Obj *pathPtr) } declare 477 { CONST86 Tcl_Filesystem *Tcl_FSGetFileSystemForPath(Tcl_Obj *pathPtr) } declare 478 { Tcl_PathType Tcl_FSGetPathType(Tcl_Obj *pathPtr) } # TIP#49 (detection of output buffering) akupries declare 479 { int Tcl_OutputBuffered(Tcl_Channel chan) } declare 480 { void Tcl_FSMountsChanged(const Tcl_Filesystem *fsPtr) } # TIP#56 (evaluate a parsed script) msofer declare 481 { int Tcl_EvalTokensStandard(Tcl_Interp *interp, Tcl_Token *tokenPtr, int count) } # TIP#73 (access to current time) kbk declare 482 { void Tcl_GetTime(Tcl_Time *timeBuf) } # TIP#32 (object-enabled traces) kbk declare 483 { Tcl_Trace Tcl_CreateObjTrace(Tcl_Interp *interp, int level, int flags, Tcl_CmdObjTraceProc *objProc, ClientData clientData, Tcl_CmdObjTraceDeleteProc *delProc) } declare 484 { int Tcl_GetCommandInfoFromToken(Tcl_Command token, Tcl_CmdInfo *infoPtr) } declare 485 { int Tcl_SetCommandInfoFromToken(Tcl_Command token, const Tcl_CmdInfo *infoPtr) } ### New functions on 64-bit dev branch ### # TIP#72 (64-bit values) dkf declare 486 { Tcl_Obj *Tcl_DbNewWideIntObj(Tcl_WideInt wideValue, const char *file, int line) } declare 487 { int Tcl_GetWideIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideInt *widePtr) } declare 488 { Tcl_Obj *Tcl_NewWideIntObj(Tcl_WideInt wideValue) } declare 489 { void Tcl_SetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt wideValue) } declare 490 { Tcl_StatBuf *Tcl_AllocStatBuf(void) } declare 491 { Tcl_WideInt Tcl_Seek(Tcl_Channel chan, Tcl_WideInt offset, int mode) } declare 492 { Tcl_WideInt Tcl_Tell(Tcl_Channel chan) } # TIP#91 (back-compat enhancements for channels) dkf declare 493 { Tcl_DriverWideSeekProc *Tcl_ChannelWideSeekProc( const Tcl_ChannelType *chanTypePtr) } # ----- BASELINE -- FOR -- 8.4.0 ----- # # TIP#111 (dictionaries) dkf declare 494 { int Tcl_DictObjPut(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj *valuePtr) } declare 495 { int Tcl_DictObjGet(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr, Tcl_Obj **valuePtrPtr) } declare 496 { int Tcl_DictObjRemove(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Obj *keyPtr) } declare 497 { int Tcl_DictObjSize(Tcl_Interp *interp, Tcl_Obj *dictPtr, int *sizePtr) } declare 498 { int Tcl_DictObjFirst(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr) } declare 499 { void Tcl_DictObjNext(Tcl_DictSearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr, int *donePtr) } declare 500 { void Tcl_DictObjDone(Tcl_DictSearch *searchPtr) } declare 501 { int Tcl_DictObjPutKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr) } declare 502 { int Tcl_DictObjRemoveKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr, int keyc, Tcl_Obj *const *keyv) } declare 503 { Tcl_Obj *Tcl_NewDictObj(void) } declare 504 { Tcl_Obj *Tcl_DbNewDictObj(const char *file, int line) } # TIP#59 (configuration reporting) akupries declare 505 { void Tcl_RegisterConfig(Tcl_Interp *interp, const char *pkgName, const Tcl_Config *configuration, const char *valEncoding) } # TIP #139 (partial exposure of namespace API - transferred from tclInt.decls) # dkf, API by Brent Welch? declare 506 { Tcl_Namespace *Tcl_CreateNamespace(Tcl_Interp *interp, const char *name, ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc) } declare 507 { void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr) } declare 508 { int Tcl_AppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *objPtr) } declare 509 { int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int resetListFirst) } declare 510 { int Tcl_Import(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern, int allowOverwrite) } declare 511 { int Tcl_ForgetImport(Tcl_Interp *interp, Tcl_Namespace *nsPtr, const char *pattern) } declare 512 { Tcl_Namespace *Tcl_GetCurrentNamespace(Tcl_Interp *interp) } declare 513 { Tcl_Namespace *Tcl_GetGlobalNamespace(Tcl_Interp *interp) } declare 514 { Tcl_Namespace *Tcl_FindNamespace(Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags) } declare 515 { Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNsPtr, int flags) } declare 516 { Tcl_Command Tcl_GetCommandFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr) } declare 517 { void Tcl_GetCommandFullName(Tcl_Interp *interp, Tcl_Command command, Tcl_Obj *objPtr) } # TIP#137 (encoding-aware source command) dgp for Anton Kovalenko declare 518 { int Tcl_FSEvalFileEx(Tcl_Interp *interp, Tcl_Obj *fileName, const char *encodingName) } # TIP#121 (exit handler) dkf for Joe Mistachkin declare 519 { Tcl_ExitProc *Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc) } # TIP#143 (resource limits) dkf declare 520 { void Tcl_LimitAddHandler(Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData, Tcl_LimitHandlerDeleteProc *deleteProc) } declare 521 { void Tcl_LimitRemoveHandler(Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData) } declare 522 { int Tcl_LimitReady(Tcl_Interp *interp) } declare 523 { int Tcl_LimitCheck(Tcl_Interp *interp) } declare 524 { int Tcl_LimitExceeded(Tcl_Interp *interp) } declare 525 { void Tcl_LimitSetCommands(Tcl_Interp *interp, int commandLimit) } declare 526 { void Tcl_LimitSetTime(Tcl_Interp *interp, Tcl_Time *timeLimitPtr) } declare 527 { void Tcl_LimitSetGranularity(Tcl_Interp *interp, int type, int granularity) } declare 528 { int Tcl_LimitTypeEnabled(Tcl_Interp *interp, int type) } declare 529 { int Tcl_LimitTypeExceeded(Tcl_Interp *interp, int type) } declare 530 { void Tcl_LimitTypeSet(Tcl_Interp *interp, int type) } declare 531 { void Tcl_LimitTypeReset(Tcl_Interp *interp, int type) } declare 532 { int Tcl_LimitGetCommands(Tcl_Interp *interp) } declare 533 { void Tcl_LimitGetTime(Tcl_Interp *interp, Tcl_Time *timeLimitPtr) } declare 534 { int Tcl_LimitGetGranularity(Tcl_Interp *interp, int type) } # TIP#226 (interpreter result state management) dgp declare 535 { Tcl_InterpState Tcl_SaveInterpState(Tcl_Interp *interp, int status) } declare 536 { int Tcl_RestoreInterpState(Tcl_Interp *interp, Tcl_InterpState state) } declare 537 { void Tcl_DiscardInterpState(Tcl_InterpState state) } # TIP#227 (return options interface) dgp declare 538 { int Tcl_SetReturnOptions(Tcl_Interp *interp, Tcl_Obj *options) } declare 539 { Tcl_Obj *Tcl_GetReturnOptions(Tcl_Interp *interp, int result) } # TIP#235 (ensembles) dkf declare 540 { int Tcl_IsEnsemble(Tcl_Command token) } declare 541 { Tcl_Command Tcl_CreateEnsemble(Tcl_Interp *interp, const char *name, Tcl_Namespace *namespacePtr, int flags) } declare 542 { Tcl_Command Tcl_FindEnsemble(Tcl_Interp *interp, Tcl_Obj *cmdNameObj, int flags) } declare 543 { int Tcl_SetEnsembleSubcommandList(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *subcmdList) } declare 544 { int Tcl_SetEnsembleMappingDict(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *mapDict) } declare 545 { int Tcl_SetEnsembleUnknownHandler(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *unknownList) } declare 546 { int Tcl_SetEnsembleFlags(Tcl_Interp *interp, Tcl_Command token, int flags) } declare 547 { int Tcl_GetEnsembleSubcommandList(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **subcmdListPtr) } declare 548 { int Tcl_GetEnsembleMappingDict(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **mapDictPtr) } declare 549 { int Tcl_GetEnsembleUnknownHandler(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **unknownListPtr) } declare 550 { int Tcl_GetEnsembleFlags(Tcl_Interp *interp, Tcl_Command token, int *flagsPtr) } declare 551 { int Tcl_GetEnsembleNamespace(Tcl_Interp *interp, Tcl_Command token, Tcl_Namespace **namespacePtrPtr) } # TIP#233 (virtualized time) akupries declare 552 { void Tcl_SetTimeProc(Tcl_GetTimeProc *getProc, Tcl_ScaleTimeProc *scaleProc, ClientData clientData) } declare 553 { void Tcl_QueryTimeProc(Tcl_GetTimeProc **getProc, Tcl_ScaleTimeProc **scaleProc, ClientData *clientData) } # TIP#218 (driver thread actions) davygrvy/akupries ChannelType ver 4 declare 554 { Tcl_DriverThreadActionProc *Tcl_ChannelThreadActionProc( const Tcl_ChannelType *chanTypePtr) } # TIP#237 (arbitrary-precision integers) kbk declare 555 { Tcl_Obj *Tcl_NewBignumObj(mp_int *value) } declare 556 { Tcl_Obj *Tcl_DbNewBignumObj(mp_int *value, const char *file, int line) } declare 557 { void Tcl_SetBignumObj(Tcl_Obj *obj, mp_int *value) } declare 558 { int Tcl_GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value) } declare 559 { int Tcl_TakeBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value) } # TIP #208 ('chan' command) jeffh declare 560 { int Tcl_TruncateChannel(Tcl_Channel chan, Tcl_WideInt length) } declare 561 { Tcl_DriverTruncateProc *Tcl_ChannelTruncateProc( const Tcl_ChannelType *chanTypePtr) } # TIP#219 (channel reflection api) akupries declare 562 { void Tcl_SetChannelErrorInterp(Tcl_Interp *interp, Tcl_Obj *msg) } declare 563 { void Tcl_GetChannelErrorInterp(Tcl_Interp *interp, Tcl_Obj **msg) } declare 564 { void Tcl_SetChannelError(Tcl_Channel chan, Tcl_Obj *msg) } declare 565 { void Tcl_GetChannelError(Tcl_Channel chan, Tcl_Obj **msg) } # TIP #237 (additional conversion functions for bignum support) kbk/dgp declare 566 { int Tcl_InitBignumFromDouble(Tcl_Interp *interp, double initval, mp_int *toInit) } # TIP#181 (namespace unknown command) dgp for Neil Madden declare 567 { Tcl_Obj *Tcl_GetNamespaceUnknownHandler(Tcl_Interp *interp, Tcl_Namespace *nsPtr) } declare 568 { int Tcl_SetNamespaceUnknownHandler(Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *handlerPtr) } # TIP#258 (enhanced interface for encodings) dgp declare 569 { int Tcl_GetEncodingFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Encoding *encodingPtr) } declare 570 { Tcl_Obj *Tcl_GetEncodingSearchPath(void) } declare 571 { int Tcl_SetEncodingSearchPath(Tcl_Obj *searchPath) } declare 572 { const char *Tcl_GetEncodingNameFromEnvironment(Tcl_DString *bufPtr) } # TIP#268 (extended version numbers and requirements) akupries declare 573 { int Tcl_PkgRequireProc(Tcl_Interp *interp, const char *name, int objc, Tcl_Obj *const objv[], void *clientDataPtr) } # TIP#270 (utility C routines for string formatting) dgp declare 574 { void Tcl_AppendObjToErrorInfo(Tcl_Interp *interp, Tcl_Obj *objPtr) } declare 575 { void Tcl_AppendLimitedToObj(Tcl_Obj *objPtr, const char *bytes, int length, int limit, const char *ellipsis) } declare 576 { Tcl_Obj *Tcl_Format(Tcl_Interp *interp, const char *format, int objc, Tcl_Obj *const objv[]) } declare 577 { int Tcl_AppendFormatToObj(Tcl_Interp *interp, Tcl_Obj *objPtr, const char *format, int objc, Tcl_Obj *const objv[]) } declare 578 { Tcl_Obj *Tcl_ObjPrintf(const char *format, ...) } declare 579 { void Tcl_AppendPrintfToObj(Tcl_Obj *objPtr, const char *format, ...) } # ----- BASELINE -- FOR -- 8.5.0 ----- # # TIP #285 (script cancellation support) jmistachkin declare 580 { int Tcl_CancelEval(Tcl_Interp *interp, Tcl_Obj *resultObjPtr, ClientData clientData, int flags) } declare 581 { int Tcl_Canceled(Tcl_Interp *interp, int flags) } # TIP#304 (chan pipe) aferrieux declare 582 { int Tcl_CreatePipe(Tcl_Interp *interp, Tcl_Channel *rchan, Tcl_Channel *wchan, int flags) } # TIP #322 (NRE public interface) msofer declare 583 { Tcl_Command Tcl_NRCreateCommand(Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, Tcl_ObjCmdProc *nreProc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc) } declare 584 { int Tcl_NREvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) } declare 585 { int Tcl_NREvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags) } declare 586 { int Tcl_NRCmdSwap(Tcl_Interp *interp, Tcl_Command cmd, int objc, Tcl_Obj *const objv[], int flags) } declare 587 { void Tcl_NRAddCallback(Tcl_Interp *interp, Tcl_NRPostProc *postProcPtr, ClientData data0, ClientData data1, ClientData data2, ClientData data3) } # For use by NR extenders, to have a simple way to also provide a (required!) # classic objProc declare 588 { int Tcl_NRCallObjProc(Tcl_Interp *interp, Tcl_ObjCmdProc *objProc, ClientData clientData, int objc, Tcl_Obj *const objv[]) } # TIP#316 (Tcl_StatBuf reader functions) dkf declare 589 { unsigned Tcl_GetFSDeviceFromStat(const Tcl_StatBuf *statPtr) } declare 590 { unsigned Tcl_GetFSInodeFromStat(const Tcl_StatBuf *statPtr) } declare 591 { unsigned Tcl_GetModeFromStat(const Tcl_StatBuf *statPtr) } declare 592 { int Tcl_GetLinkCountFromStat(const Tcl_StatBuf *statPtr) } declare 593 { int Tcl_GetUserIdFromStat(const Tcl_StatBuf *statPtr) } declare 594 { int Tcl_GetGroupIdFromStat(const Tcl_StatBuf *statPtr) } declare 595 { int Tcl_GetDeviceTypeFromStat(const Tcl_StatBuf *statPtr) } declare 596 { Tcl_WideInt Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr) } declare 597 { Tcl_WideInt Tcl_GetModificationTimeFromStat(const Tcl_StatBuf *statPtr) } declare 598 { Tcl_WideInt Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr) } declare 599 { Tcl_WideUInt Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr) } declare 600 { Tcl_WideUInt Tcl_GetBlocksFromStat(const Tcl_StatBuf *statPtr) } declare 601 { unsigned Tcl_GetBlockSizeFromStat(const Tcl_StatBuf *statPtr) } # TIP#314 (ensembles with parameters) dkf for Lars Hellstr"om declare 602 { int Tcl_SetEnsembleParameterList(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj *paramList) } declare 603 { int Tcl_GetEnsembleParameterList(Tcl_Interp *interp, Tcl_Command token, Tcl_Obj **paramListPtr) } # TIP#265 (option parser) dkf for Sam Bromley declare 604 { int Tcl_ParseArgsObjv(Tcl_Interp *interp, const Tcl_ArgvInfo *argTable, int *objcPtr, Tcl_Obj *const *objv, Tcl_Obj ***remObjv) } # TIP#336 (manipulate the error line) dgp declare 605 { int Tcl_GetErrorLine(Tcl_Interp *interp) } declare 606 { void Tcl_SetErrorLine(Tcl_Interp *interp, int lineNum) } # TIP#307 (move results between interpreters) dkf declare 607 { void Tcl_TransferResult(Tcl_Interp *sourceInterp, int result, Tcl_Interp *targetInterp) } # TIP#335 (detect if interpreter in use) jmistachkin declare 608 { int Tcl_InterpActive(Tcl_Interp *interp) } # TIP#337 (log exception for background processing) dgp declare 609 { void Tcl_BackgroundException(Tcl_Interp *interp, int code) } # TIP#234 (zlib interface) dkf/Pascal Scheffers declare 610 { int Tcl_ZlibDeflate(Tcl_Interp *interp, int format, Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj) } declare 611 { int Tcl_ZlibInflate(Tcl_Interp *interp, int format, Tcl_Obj *data, int buffersize, Tcl_Obj *gzipHeaderDictObj) } declare 612 { unsigned int Tcl_ZlibCRC32(unsigned int crc, const unsigned char *buf, int len) } declare 613 { unsigned int Tcl_ZlibAdler32(unsigned int adler, const unsigned char *buf, int len) } declare 614 { int Tcl_ZlibStreamInit(Tcl_Interp *interp, int mode, int format, int level, Tcl_Obj *dictObj, Tcl_ZlibStream *zshandle) } declare 615 { Tcl_Obj *Tcl_ZlibStreamGetCommandName(Tcl_ZlibStream zshandle) } declare 616 { int Tcl_ZlibStreamEof(Tcl_ZlibStream zshandle) } declare 617 { int Tcl_ZlibStreamChecksum(Tcl_ZlibStream zshandle) } declare 618 { int Tcl_ZlibStreamPut(Tcl_ZlibStream zshandle, Tcl_Obj *data, int flush) } declare 619 { int Tcl_ZlibStreamGet(Tcl_ZlibStream zshandle, Tcl_Obj *data, int count) } declare 620 { int Tcl_ZlibStreamClose(Tcl_ZlibStream zshandle) } declare 621 { int Tcl_ZlibStreamReset(Tcl_ZlibStream zshandle) } # TIP 338 (control over startup script) dgp declare 622 { void Tcl_SetStartupScript(Tcl_Obj *path, const char *encoding) } declare 623 { Tcl_Obj *Tcl_GetStartupScript(const char **encodingPtr) } # TIP#332 (half-close made public) aferrieux declare 624 { int Tcl_CloseEx(Tcl_Interp *interp, Tcl_Channel chan, int flags) } # TIP #353 (NR-enabled expressions) dgp declare 625 { int Tcl_NRExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj *resultPtr) } # TIP #356 (NR-enabled substitution) dgp declare 626 { int Tcl_NRSubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) } # TIP #357 (Export TclLoadFile and TclpFindSymbol) kbk declare 627 { int Tcl_LoadFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *const symv[], int flags, void *procPtrs, Tcl_LoadHandle *handlePtr) } declare 628 { void *Tcl_FindSymbol(Tcl_Interp *interp, Tcl_LoadHandle handle, const char *symbol) } declare 629 { int Tcl_FSUnloadFile(Tcl_Interp *interp, Tcl_LoadHandle handlePtr) } # TIP #400 declare 630 { void Tcl_ZlibStreamSetCompressionDictionary(Tcl_ZlibStream zhandle, Tcl_Obj *compressionDictionaryObj) } # ----- BASELINE -- FOR -- 8.6.0 ----- # ############################################################################## # Define the platform specific public Tcl interface. These functions are only # available on the designated platform. interface tclPlat ################################ # Unix specific functions # (none) ################################ # Windows specific functions # Added in Tcl 8.1 declare 0 win { TCHAR *Tcl_WinUtfToTChar(const char *str, int len, Tcl_DString *dsPtr) } declare 1 win { char *Tcl_WinTCharToUtf(const TCHAR *str, int len, Tcl_DString *dsPtr) } ################################ # Mac OS X specific functions declare 0 macosx { int Tcl_MacOSXOpenBundleResources(Tcl_Interp *interp, const char *bundleName, int hasResourceFile, int maxPathLen, char *libraryPath) } declare 1 macosx { int Tcl_MacOSXOpenVersionedBundleResources(Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, int maxPathLen, char *libraryPath) } ############################################################################## # Public functions that are not accessible via the stubs table. export { void Tcl_Main(int argc, char **argv, Tcl_AppInitProc *appInitProc) } export { const char *Tcl_InitStubs(Tcl_Interp *interp, const char *version, int exact) } export { const char *TclTomMathInitializeStubs(Tcl_Interp* interp, const char* version, int epoch, int revision) } export { const char *Tcl_PkgInitStubsCheck(Tcl_Interp *interp, const char *version, int exact) } export { void Tcl_GetMemoryInfo(Tcl_DString *dsPtr) } # Local Variables: # mode: tcl # End: tcl8.6.5/generic/regerror.c0000644000175000017500000000721212663660065015200 0ustar sergeisergei/* * regerror - error-code expansion * * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results. The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation of * software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "regguts.h" /* * Unknown-error explanation. */ static const char unk[] = "*** unknown regex error code 0x%x ***"; /* * Struct to map among codes, code names, and explanations. */ static const struct rerr { int code; const char *name; const char *explain; } rerrs[] = { /* The actual table is built from regex.h */ #include "regerrs.h" { -1, "", "oops" }, /* explanation special-cased in code */ }; /* - regerror - the interface to error numbers */ /* ARGSUSED */ size_t /* Actual space needed (including NUL) */ regerror( int code, /* Error code, or REG_ATOI or REG_ITOA */ const regex_t *preg, /* Associated regex_t (unused at present) */ char *errbuf, /* Result buffer (unless errbuf_size==0) */ size_t errbuf_size) /* Available space in errbuf, can be 0 */ { const struct rerr *r; const char *msg; char convbuf[sizeof(unk)+50]; /* 50 = plenty for int */ size_t len; int icode; switch (code) { case REG_ATOI: /* Convert name to number */ for (r = rerrs; r->code >= 0; r++) { if (strcmp(r->name, errbuf) == 0) { break; } } sprintf(convbuf, "%d", r->code); /* -1 for unknown */ msg = convbuf; break; case REG_ITOA: /* Convert number to name */ icode = atoi(errbuf); /* Not our problem if this fails */ for (r = rerrs; r->code >= 0; r++) { if (r->code == icode) { break; } } if (r->code >= 0) { msg = r->name; } else { /* Unknown; tell him the number */ sprintf(convbuf, "REG_%u", (unsigned)icode); msg = convbuf; } break; default: /* A real, normal error code */ for (r = rerrs; r->code >= 0; r++) { if (r->code == code) { break; } } if (r->code >= 0) { msg = r->explain; } else { /* Unknown; say so */ sprintf(convbuf, unk, code); msg = convbuf; } break; } len = strlen(msg) + 1; /* Space needed, including NUL */ if (errbuf_size > 0) { if (errbuf_size > len) { strcpy(errbuf, msg); } else { /* Truncate to fit */ strncpy(errbuf, msg, errbuf_size-1); errbuf[errbuf_size-1] = '\0'; } } return len; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/generic/tclIO.c0000644000175000017500000114713212663660065014372 0ustar sergeisergei/* * tclIO.c -- * * This file provides the generic portions (those that are the same on * all platforms and for all channel types) of Tcl's IO facilities. * * Copyright (c) 1998-2000 Ajuba Solutions * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Contributions from Don Porter, NIST, 2014. (not subject to US copyright) * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclIO.h" #include /* * For each channel handler registered in a call to Tcl_CreateChannelHandler, * there is one record of the following type. All of records for a specific * channel are chained together in a singly linked list which is stored in * the channel structure. */ typedef struct ChannelHandler { Channel *chanPtr; /* The channel structure for this channel. */ int mask; /* Mask of desired events. */ Tcl_ChannelProc *proc; /* Procedure to call in the type of * Tcl_CreateChannelHandler. */ ClientData clientData; /* Argument to pass to procedure. */ struct ChannelHandler *nextPtr; /* Next one in list of registered handlers. */ } ChannelHandler; /* * This structure keeps track of the current ChannelHandler being invoked in * the current invocation of Tcl_NotifyChannel. There is a potential * problem if a ChannelHandler is deleted while it is the current one, since * Tcl_NotifyChannel needs to look at the nextPtr field. To handle this * problem, structures of the type below indicate the next handler to be * processed for any (recursively nested) dispatches in progress. The * nextHandlerPtr field is updated if the handler being pointed to is deleted. * The nestedHandlerPtr field is used to chain together all recursive * invocations, so that Tcl_DeleteChannelHandler can find all the recursively * nested invocations of Tcl_NotifyChannel and compare the handler being * deleted against the NEXT handler to be invoked in that invocation; when it * finds such a situation, Tcl_DeleteChannelHandler updates the nextHandlerPtr * field of the structure to the next handler. */ typedef struct NextChannelHandler { ChannelHandler *nextHandlerPtr; /* The next handler to be invoked in * this invocation. */ struct NextChannelHandler *nestedHandlerPtr; /* Next nested invocation of * Tcl_NotifyChannel. */ } NextChannelHandler; /* * The following structure is used by Tcl_GetsObj() to encapsulates the * state for a "gets" operation. */ typedef struct GetsState { Tcl_Obj *objPtr; /* The object to which UTF-8 characters * will be appended. */ char **dstPtr; /* Pointer into objPtr's string rep where * next character should be stored. */ Tcl_Encoding encoding; /* The encoding to use to convert raw bytes * to UTF-8. */ ChannelBuffer *bufPtr; /* The current buffer of raw bytes being * emptied. */ Tcl_EncodingState state; /* The encoding state just before the last * external to UTF-8 conversion in * FilterInputBytes(). */ int rawRead; /* The number of bytes removed from bufPtr * in the last call to FilterInputBytes(). */ int bytesWrote; /* The number of bytes of UTF-8 data * appended to objPtr during the last call to * FilterInputBytes(). */ int charsWrote; /* The corresponding number of UTF-8 * characters appended to objPtr during the * last call to FilterInputBytes(). */ int totalChars; /* The total number of UTF-8 characters * appended to objPtr so far, just before the * last call to FilterInputBytes(). */ } GetsState; /* * The following structure encapsulates the state for a background channel * copy. Note that the data buffer for the copy will be appended to this * structure. */ typedef struct CopyState { struct Channel *readPtr; /* Pointer to input channel. */ struct Channel *writePtr; /* Pointer to output channel. */ int readFlags; /* Original read channel flags. */ int writeFlags; /* Original write channel flags. */ Tcl_WideInt toRead; /* Number of bytes to copy, or -1. */ Tcl_WideInt total; /* Total bytes transferred (written). */ Tcl_Interp *interp; /* Interp that started the copy. */ Tcl_Obj *cmdPtr; /* Command to be invoked at completion. */ int bufSize; /* Size of appended buffer. */ char buffer[1]; /* Copy buffer, this must be the last * field. */ } CopyState; /* * All static variables used in this file are collected into a single instance * of the following structure. For multi-threaded implementations, there is * one instance of this structure for each thread. * * Notice that different structures with the same name appear in other files. * The structure defined below is used in this file only. */ typedef struct ThreadSpecificData { NextChannelHandler *nestedHandlerPtr; /* This variable holds the list of nested * Tcl_NotifyChannel invocations. */ ChannelState *firstCSPtr; /* List of all channels currently open, * indexed by ChannelState, as only one * ChannelState exists per set of stacked * channels. */ Tcl_Channel stdinChannel; /* Static variable for the stdin channel. */ int stdinInitialized; Tcl_Channel stdoutChannel; /* Static variable for the stdout channel. */ int stdoutInitialized; Tcl_Channel stderrChannel; /* Static variable for the stderr channel. */ int stderrInitialized; Tcl_Encoding binaryEncoding; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * Structure to record a close callback. One such record exists for * each close callback registered for a channel. */ typedef struct CloseCallback { Tcl_CloseProc *proc; /* The procedure to call. */ ClientData clientData; /* Arbitrary one-word data to pass * to the callback. */ struct CloseCallback *nextPtr; /* For chaining close callbacks. */ } CloseCallback; /* * Static functions in this file: */ static ChannelBuffer * AllocChannelBuffer(int length); static void PreserveChannelBuffer(ChannelBuffer *bufPtr); static void ReleaseChannelBuffer(ChannelBuffer *bufPtr); static int IsShared(ChannelBuffer *bufPtr); static void ChannelFree(Channel *chanPtr); static void ChannelTimerProc(ClientData clientData); static int ChanRead(Channel *chanPtr, char *dst, int dstSize); static int CheckChannelErrors(ChannelState *statePtr, int direction); static int CheckForDeadChannel(Tcl_Interp *interp, ChannelState *statePtr); static void CheckForStdChannelsBeingClosed(Tcl_Channel chan); static void CleanupChannelHandlers(Tcl_Interp *interp, Channel *chanPtr); static int CloseChannel(Tcl_Interp *interp, Channel *chanPtr, int errorCode); static int CloseChannelPart(Tcl_Interp *interp, Channel *chanPtr, int errorCode, int flags); static int CloseWrite(Tcl_Interp *interp, Channel *chanPtr); static void CommonGetsCleanup(Channel *chanPtr); static int CopyData(CopyState *csPtr, int mask); static int MoveBytes(CopyState *csPtr); static void MBCallback(CopyState *csPtr, Tcl_Obj *errObj); static void MBError(CopyState *csPtr, int mask, int errorCode); static int MBRead(CopyState *csPtr); static int MBWrite(CopyState *csPtr); static void MBEvent(ClientData clientData, int mask); static void CopyEventProc(ClientData clientData, int mask); static void CreateScriptRecord(Tcl_Interp *interp, Channel *chanPtr, int mask, Tcl_Obj *scriptPtr); static void DeleteChannelTable(ClientData clientData, Tcl_Interp *interp); static void DeleteScriptRecord(Tcl_Interp *interp, Channel *chanPtr, int mask); static int DetachChannel(Tcl_Interp *interp, Tcl_Channel chan); static void DiscardInputQueued(ChannelState *statePtr, int discardSavedBuffers); static void DiscardOutputQueued(ChannelState *chanPtr); static int DoRead(Channel *chanPtr, char *dst, int bytesToRead, int allowShortReads); static int DoReadChars(Channel *chan, Tcl_Obj *objPtr, int toRead, int appendFlag); static int FilterInputBytes(Channel *chanPtr, GetsState *statePtr); static int FlushChannel(Tcl_Interp *interp, Channel *chanPtr, int calledFromAsyncFlush); static int TclGetsObjBinary(Tcl_Channel chan, Tcl_Obj *objPtr); static Tcl_Encoding GetBinaryEncoding(); static void FreeBinaryEncoding(ClientData clientData); static Tcl_HashTable * GetChannelTable(Tcl_Interp *interp); static int GetInput(Channel *chanPtr); static int HaveVersion(const Tcl_ChannelType *typePtr, Tcl_ChannelTypeVersion minimumVersion); static void PeekAhead(Channel *chanPtr, char **dstEndPtr, GetsState *gsPtr); static int ReadBytes(ChannelState *statePtr, Tcl_Obj *objPtr, int charsLeft); static int ReadChars(ChannelState *statePtr, Tcl_Obj *objPtr, int charsLeft, int *factorPtr); static void RecycleBuffer(ChannelState *statePtr, ChannelBuffer *bufPtr, int mustDiscard); static int StackSetBlockMode(Channel *chanPtr, int mode); static int SetBlockMode(Tcl_Interp *interp, Channel *chanPtr, int mode); static void StopCopy(CopyState *csPtr); static void TranslateInputEOL(ChannelState *statePtr, char *dst, const char *src, int *dstLenPtr, int *srcLenPtr); static void UpdateInterest(Channel *chanPtr); static int Write(Channel *chanPtr, const char *src, int srcLen, Tcl_Encoding encoding); static Tcl_Obj * FixLevelCode(Tcl_Obj *msg); static void SpliceChannel(Tcl_Channel chan); static void CutChannel(Tcl_Channel chan); static int WillRead(Channel *chanPtr); #define WriteChars(chanPtr, src, srcLen) \ Write(chanPtr, src, srcLen, chanPtr->state->encoding) #define WriteBytes(chanPtr, src, srcLen) \ Write(chanPtr, src, srcLen, tclIdentityEncoding) /* * Simplifying helper macros. All may use their argument(s) multiple times. * The ANSI C "prototypes" for the macros are listed below, together with a * short description of what the macro does. * * -------------------------------------------------------------------------- * int BytesLeft(ChannelBuffer *bufPtr) * * Returns the number of bytes of data remaining in the buffer. * * int SpaceLeft(ChannelBuffer *bufPtr) * * Returns the number of bytes of space remaining at the end of the * buffer. * * int IsBufferReady(ChannelBuffer *bufPtr) * * Returns whether a buffer has bytes available within it. * * int IsBufferEmpty(ChannelBuffer *bufPtr) * * Returns whether a buffer is entirely empty. Note that this is not the * inverse of the above operation; trying to merge the two seems to lead * to occasional crashes... * * int IsBufferFull(ChannelBuffer *bufPtr) * * Returns whether more data can be added to a buffer. * * int IsBufferOverflowing(ChannelBuffer *bufPtr) * * Returns whether a buffer has more data in it than it should. * * char *InsertPoint(ChannelBuffer *bufPtr) * * Returns a pointer to where characters should be added to the buffer. * * char *RemovePoint(ChannelBuffer *bufPtr) * * Returns a pointer to where characters should be removed from the * buffer. * -------------------------------------------------------------------------- */ #define BytesLeft(bufPtr) ((bufPtr)->nextAdded - (bufPtr)->nextRemoved) #define SpaceLeft(bufPtr) ((bufPtr)->bufLength - (bufPtr)->nextAdded) #define IsBufferReady(bufPtr) ((bufPtr)->nextAdded > (bufPtr)->nextRemoved) #define IsBufferEmpty(bufPtr) ((bufPtr)->nextAdded == (bufPtr)->nextRemoved) #define IsBufferFull(bufPtr) ((bufPtr) && (bufPtr)->nextAdded >= (bufPtr)->bufLength) #define IsBufferOverflowing(bufPtr) ((bufPtr)->nextAdded>(bufPtr)->bufLength) #define InsertPoint(bufPtr) ((bufPtr)->buf + (bufPtr)->nextAdded) #define RemovePoint(bufPtr) ((bufPtr)->buf + (bufPtr)->nextRemoved) /* * For working with channel state flag bits. */ #define SetFlag(statePtr, flag) ((statePtr)->flags |= (flag)) #define ResetFlag(statePtr, flag) ((statePtr)->flags &= ~(flag)) #define GotFlag(statePtr, flag) ((statePtr)->flags & (flag)) /* * Macro for testing whether a string (in optionName, length len) matches a * value (prefix matching rules). Arguments are the minimum length to match * and the value to match against. (Can't use Tcl_GetIndexFromObj as this is * used in a situation where no objects are available.) */ #define HaveOpt(minLength, nameString) \ ((len > (minLength)) && (optionName[1] == (nameString)[1]) \ && (strncmp(optionName, (nameString), len) == 0)) /* * The ChannelObjType type. We actually store the ChannelState structure * as that lives longest and we want to return the bottomChanPtr when * requested (consistent with Tcl_GetChannel). The setFromAny and * updateString can be NULL as they should not be called. */ static void DupChannelIntRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); static int SetChannelFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void FreeChannelIntRep(Tcl_Obj *objPtr); static const Tcl_ObjType chanObjType = { "channel", /* name for this type */ FreeChannelIntRep, /* freeIntRepProc */ DupChannelIntRep, /* dupIntRepProc */ NULL, /* updateStringProc */ NULL /* setFromAnyProc SetChannelFromAny */ }; #define GET_CHANNELSTATE(objPtr) \ ((ChannelState *) (objPtr)->internalRep.twoPtrValue.ptr1) #define SET_CHANNELSTATE(objPtr, storePtr) \ ((objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (storePtr)) #define GET_CHANNELINTERP(objPtr) \ ((Tcl_Interp *) (objPtr)->internalRep.twoPtrValue.ptr2) #define SET_CHANNELINTERP(objPtr, storePtr) \ ((objPtr)->internalRep.twoPtrValue.ptr2 = (void *) (storePtr)) #define BUSY_STATE(st, fl) \ ((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \ (((st)->csPtrW) && ((fl) & TCL_WRITABLE))) #define MAX_CHANNEL_BUFFER_SIZE (1024*1024) /* *--------------------------------------------------------------------------- * * ChanClose, ChanRead, ChanSeek, ChanThreadAction, ChanWatch, ChanWrite -- * * Simplify the access to selected channel driver "methods" that are used * in multiple places in a stereotypical fashion. These are just thin * wrappers around the driver functions. * *--------------------------------------------------------------------------- */ static inline int ChanClose( Channel *chanPtr, Tcl_Interp *interp) { if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { return chanPtr->typePtr->closeProc(chanPtr->instanceData, interp); } else { return chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, 0); } } static inline int ChanCloseHalf( Channel *chanPtr, Tcl_Interp *interp, int flags) { return chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, flags); } /* *--------------------------------------------------------------------------- * * ChanRead -- * * Read up to dstSize bytes using the inputProc of chanPtr, store * them at dst, and return the number of bytes stored. * * Results: * The return value of the driver inputProc, * - number of bytes stored at dst, ot * - -1 on error, with a Posix error code available to the * caller by calling Tcl_GetErrno(). * * Side effects: * The CHANNEL_BLOCKED and CHANNEL_EOF flags of the channel state are * set as appropriate. * On EOF, the inputEncodingFlags are set to perform ending operations * on decoding. * TODO - Is this really the right place for that? * *--------------------------------------------------------------------------- */ static int ChanRead( Channel *chanPtr, char *dst, int dstSize) { int bytesRead, result; /* * If the caller asked for zero bytes, we'd force the inputProc * to return zero bytes, and then misinterpret that as EOF. */ assert(dstSize > 0); /* * Each read op must set the blocked and eof states anew, not let * the effect of prior reads leak through. */ if (GotFlag(chanPtr->state, CHANNEL_EOF)) { chanPtr->state->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(chanPtr->state, CHANNEL_BLOCKED | CHANNEL_EOF); chanPtr->state->inputEncodingFlags &= ~TCL_ENCODING_END; if (WillRead(chanPtr) < 0) { return -1; } bytesRead = chanPtr->typePtr->inputProc(chanPtr->instanceData, dst, dstSize, &result); /* Stop any flag leakage through stacked channel levels */ if (GotFlag(chanPtr->state, CHANNEL_EOF)) { chanPtr->state->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(chanPtr->state, CHANNEL_BLOCKED | CHANNEL_EOF); chanPtr->state->inputEncodingFlags &= ~TCL_ENCODING_END; if (bytesRead > 0) { /* * If we get a short read, signal up that we may be BLOCKED. * We should avoid calling the driver because on some * platforms we will block in the low level reading code even * though the channel is set into nonblocking mode. */ if (bytesRead < dstSize) { SetFlag(chanPtr->state, CHANNEL_BLOCKED); } } else if (bytesRead == 0) { SetFlag(chanPtr->state, CHANNEL_EOF); chanPtr->state->inputEncodingFlags |= TCL_ENCODING_END; } else if (bytesRead < 0) { if ((result == EWOULDBLOCK) || (result == EAGAIN)) { SetFlag(chanPtr->state, CHANNEL_BLOCKED); result = EAGAIN; } Tcl_SetErrno(result); } return bytesRead; } static inline Tcl_WideInt ChanSeek( Channel *chanPtr, Tcl_WideInt offset, int mode, int *errnoPtr) { /* * Note that we prefer the wideSeekProc if that field is available in the * type and non-NULL. */ if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) && chanPtr->typePtr->wideSeekProc != NULL) { return chanPtr->typePtr->wideSeekProc(chanPtr->instanceData, offset, mode, errnoPtr); } if (offsetTcl_LongAsWide(LONG_MAX)) { *errnoPtr = EOVERFLOW; return Tcl_LongAsWide(-1); } return Tcl_LongAsWide(chanPtr->typePtr->seekProc(chanPtr->instanceData, Tcl_WideAsLong(offset), mode, errnoPtr)); } static inline void ChanThreadAction( Channel *chanPtr, int action) { Tcl_DriverThreadActionProc *threadActionProc = Tcl_ChannelThreadActionProc(chanPtr->typePtr); if (threadActionProc != NULL) { threadActionProc(chanPtr->instanceData, action); } } static inline void ChanWatch( Channel *chanPtr, int mask) { chanPtr->typePtr->watchProc(chanPtr->instanceData, mask); } static inline int ChanWrite( Channel *chanPtr, const char *src, int srcLen, int *errnoPtr) { return chanPtr->typePtr->outputProc(chanPtr->instanceData, src, srcLen, errnoPtr); } /* *--------------------------------------------------------------------------- * * TclInitIOSubsystem -- * * Initialize all resources used by this subsystem on a per-process * basis. * * Results: * None. * * Side effects: * Depends on the memory subsystems. * *--------------------------------------------------------------------------- */ void TclInitIOSubsystem(void) { /* * By fetching thread local storage we take care of allocating it for each * thread. */ (void) TCL_TSD_INIT(&dataKey); } /* *------------------------------------------------------------------------- * * TclFinalizeIOSubsystem -- * * Releases all resources used by this subsystem on a per-process basis. * Closes all extant channels that have not already been closed because * they were not owned by any interp. * * Results: * None. * * Side effects: * Depends on encoding and memory subsystems. * *------------------------------------------------------------------------- */ /* ARGSUSED */ void TclFinalizeIOSubsystem(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Channel *chanPtr = NULL; /* Iterates over open channels. */ ChannelState *statePtr; /* State of channel stack */ int active = 1; /* Flag == 1 while there's still work to do */ int doflushnb; /* Fetch the pre-TIP#398 compatibility flag */ { const char *s; Tcl_DString ds; s = TclGetEnv("TCL_FLUSH_NONBLOCKING_ON_EXIT", &ds); doflushnb = ((s != NULL) && strcmp(s, "0")); if (s != NULL) { Tcl_DStringFree(&ds); } } /* * Walk all channel state structures known to this thread and close * corresponding channels. */ while (active) { /* * Iterate through the open channel list, and find the first channel * that isn't dead. We start from the head of the list each time, * because the close action on one channel can close others. */ active = 0; for (statePtr = tsdPtr->firstCSPtr; statePtr != NULL; statePtr = statePtr->nextCSPtr) { chanPtr = statePtr->topChanPtr; if (GotFlag(statePtr, CHANNEL_DEAD)) { continue; } if (!GotFlag(statePtr, CHANNEL_INCLOSE | CHANNEL_CLOSED ) || GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { ResetFlag(statePtr, BG_FLUSH_SCHEDULED); active = 1; break; } } /* * We've found a live (or bg-closing) channel. Close it. */ if (active) { TclChannelPreserve((Tcl_Channel)chanPtr); /* * TIP #398: by default, we no longer set the channel back into * blocking mode. To restore the old blocking behavior, the * environment variable TCL_FLUSH_NONBLOCKING_ON_EXIT must be set * and not be "0". */ if (doflushnb) { /* Set the channel back into blocking mode to ensure that we wait * for all data to flush out. */ (void) Tcl_SetChannelOption(NULL, (Tcl_Channel) chanPtr, "-blocking", "on"); } if ((chanPtr == (Channel *) tsdPtr->stdinChannel) || (chanPtr == (Channel *) tsdPtr->stdoutChannel) || (chanPtr == (Channel *) tsdPtr->stderrChannel)) { /* * Decrement the refcount which was earlier artificially * bumped up to keep the channel from being closed. */ statePtr->refCount--; } if (statePtr->refCount <= 0) { /* * Close it only if the refcount indicates that the channel is * not referenced from any interpreter. If it is, that * interpreter will close the channel when it gets destroyed. */ (void) Tcl_Close(NULL, (Tcl_Channel) chanPtr); } else { /* * The refcount is greater than zero, so flush the channel. */ Tcl_Flush((Tcl_Channel) chanPtr); /* * Call the device driver to actually close the underlying * device for this channel. */ (void) ChanClose(chanPtr, NULL); /* * Finally, we clean up the fields in the channel data * structure since all of them have been deleted already. We * mark the channel with CHANNEL_DEAD to prevent any further * IO operations on it. */ chanPtr->instanceData = NULL; SetFlag(statePtr, CHANNEL_DEAD); } TclChannelRelease((Tcl_Channel)chanPtr); } } TclpFinalizeSockets(); TclpFinalizePipes(); } /* *---------------------------------------------------------------------- * * Tcl_SetStdChannel -- * * This function is used to change the channels that are used for * stdin/stdout/stderr in new interpreters. * * Results: * None * * Side effects: * None. * *---------------------------------------------------------------------- */ void Tcl_SetStdChannel( Tcl_Channel channel, int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); switch (type) { case TCL_STDIN: tsdPtr->stdinInitialized = 1; tsdPtr->stdinChannel = channel; break; case TCL_STDOUT: tsdPtr->stdoutInitialized = 1; tsdPtr->stdoutChannel = channel; break; case TCL_STDERR: tsdPtr->stderrInitialized = 1; tsdPtr->stderrChannel = channel; break; } } /* *---------------------------------------------------------------------- * * Tcl_GetStdChannel -- * * Returns the specified standard channel. * * Results: * Returns the specified standard channel, or NULL. * * Side effects: * May cause the creation of a standard channel and the underlying file. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_GetStdChannel( int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */ { Tcl_Channel channel = NULL; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * If the channels were not created yet, create them now and store them in * the static variables. */ switch (type) { case TCL_STDIN: if (!tsdPtr->stdinInitialized) { tsdPtr->stdinChannel = TclpGetDefaultStdChannel(TCL_STDIN); tsdPtr->stdinInitialized = 1; /* * Artificially bump the refcount to ensure that the channel is * only closed on exit. * * NOTE: Must only do this if stdinChannel is not NULL. It can be * NULL in situations where Tcl is unable to connect to the * standard input. */ if (tsdPtr->stdinChannel != NULL) { Tcl_RegisterChannel(NULL, tsdPtr->stdinChannel); } } channel = tsdPtr->stdinChannel; break; case TCL_STDOUT: if (!tsdPtr->stdoutInitialized) { tsdPtr->stdoutChannel = TclpGetDefaultStdChannel(TCL_STDOUT); tsdPtr->stdoutInitialized = 1; if (tsdPtr->stdoutChannel != NULL) { Tcl_RegisterChannel(NULL, tsdPtr->stdoutChannel); } } channel = tsdPtr->stdoutChannel; break; case TCL_STDERR: if (!tsdPtr->stderrInitialized) { tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR); tsdPtr->stderrInitialized = 1; if (tsdPtr->stderrChannel != NULL) { Tcl_RegisterChannel(NULL, tsdPtr->stderrChannel); } } channel = tsdPtr->stderrChannel; break; } return channel; } /* *---------------------------------------------------------------------- * * Tcl_CreateCloseHandler * * Creates a close callback which will be called when the channel is * closed. * * Results: * None. * * Side effects: * Causes the callback to be called in the future when the channel will * be closed. * *---------------------------------------------------------------------- */ void Tcl_CreateCloseHandler( Tcl_Channel chan, /* The channel for which to create the close * callback. */ Tcl_CloseProc *proc, /* The callback routine to call when the * channel will be closed. */ ClientData clientData) /* Arbitrary data to pass to the close * callback. */ { ChannelState *statePtr = ((Channel *) chan)->state; CloseCallback *cbPtr; cbPtr = ckalloc(sizeof(CloseCallback)); cbPtr->proc = proc; cbPtr->clientData = clientData; cbPtr->nextPtr = statePtr->closeCbPtr; statePtr->closeCbPtr = cbPtr; } /* *---------------------------------------------------------------------- * * Tcl_DeleteCloseHandler -- * * Removes a callback that would have been called on closing the channel. * If there is no matching callback then this function has no effect. * * Results: * None. * * Side effects: * The callback will not be called in the future when the channel is * eventually closed. * *---------------------------------------------------------------------- */ void Tcl_DeleteCloseHandler( Tcl_Channel chan, /* The channel for which to cancel the close * callback. */ Tcl_CloseProc *proc, /* The procedure for the callback to * remove. */ ClientData clientData) /* The callback data for the callback to * remove. */ { ChannelState *statePtr = ((Channel *) chan)->state; CloseCallback *cbPtr, *cbPrevPtr; for (cbPtr = statePtr->closeCbPtr, cbPrevPtr = NULL; cbPtr != NULL; cbPtr = cbPtr->nextPtr) { if ((cbPtr->proc == proc) && (cbPtr->clientData == clientData)) { if (cbPrevPtr == NULL) { statePtr->closeCbPtr = cbPtr->nextPtr; } else { cbPrevPtr->nextPtr = cbPtr->nextPtr; } ckfree(cbPtr); break; } cbPrevPtr = cbPtr; } } /* *---------------------------------------------------------------------- * * GetChannelTable -- * * Gets and potentially initializes the channel table for an interpreter. * If it is initializing the table it also inserts channels for stdin, * stdout and stderr if the interpreter is trusted. * * Results: * A pointer to the hash table created, for use by the caller. * * Side effects: * Initializes the channel table for an interpreter. May create channels * for stdin, stdout and stderr. * *---------------------------------------------------------------------- */ static Tcl_HashTable * GetChannelTable( Tcl_Interp *interp) { Tcl_HashTable *hTblPtr; /* Hash table of channels. */ Tcl_Channel stdinChan, stdoutChan, stderrChan; hTblPtr = Tcl_GetAssocData(interp, "tclIO", NULL); if (hTblPtr == NULL) { hTblPtr = ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(hTblPtr, TCL_STRING_KEYS); Tcl_SetAssocData(interp, "tclIO", (Tcl_InterpDeleteProc *) DeleteChannelTable, hTblPtr); /* * If the interpreter is trusted (not "safe"), insert channels for * stdin, stdout and stderr (possibly creating them in the process). */ if (Tcl_IsSafe(interp) == 0) { stdinChan = Tcl_GetStdChannel(TCL_STDIN); if (stdinChan != NULL) { Tcl_RegisterChannel(interp, stdinChan); } stdoutChan = Tcl_GetStdChannel(TCL_STDOUT); if (stdoutChan != NULL) { Tcl_RegisterChannel(interp, stdoutChan); } stderrChan = Tcl_GetStdChannel(TCL_STDERR); if (stderrChan != NULL) { Tcl_RegisterChannel(interp, stderrChan); } } } return hTblPtr; } /* *---------------------------------------------------------------------- * * DeleteChannelTable -- * * Deletes the channel table for an interpreter, closing any open * channels whose refcount reaches zero. This procedure is invoked when * an interpreter is deleted, via the AssocData cleanup mechanism. * * Results: * None. * * Side effects: * Deletes the hash table of channels. May close channels. May flush * output on closed channels. Removes any channeEvent handlers that were * registered in this interpreter. * *---------------------------------------------------------------------- */ static void DeleteChannelTable( ClientData clientData, /* The per-interpreter data structure. */ Tcl_Interp *interp) /* The interpreter being deleted. */ { Tcl_HashTable *hTblPtr; /* The hash table. */ Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ Channel *chanPtr; /* Channel being deleted. */ ChannelState *statePtr; /* State of Channel being deleted. */ EventScriptRecord *sPtr, *prevPtr, *nextPtr; /* Variables to loop over all channel events * registered, to delete the ones that refer * to the interpreter being deleted. */ /* * Delete all the registered channels - this will close channels whose * refcount reaches zero. */ hTblPtr = clientData; for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); hPtr != NULL; hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch)) { chanPtr = Tcl_GetHashValue(hPtr); statePtr = chanPtr->state; /* * Remove any fileevents registered in this interpreter. */ for (sPtr = statePtr->scriptRecordPtr, prevPtr = NULL; sPtr != NULL; sPtr = nextPtr) { nextPtr = sPtr->nextPtr; if (sPtr->interp == interp) { if (prevPtr == NULL) { statePtr->scriptRecordPtr = nextPtr; } else { prevPtr->nextPtr = nextPtr; } Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, TclChannelEventScriptInvoker, sPtr); TclDecrRefCount(sPtr->scriptPtr); ckfree(sPtr); } else { prevPtr = sPtr; } } /* * Cannot call Tcl_UnregisterChannel because that procedure calls * Tcl_GetAssocData to get the channel table, which might already be * inaccessible from the interpreter structure. Instead, we emulate * the behavior of Tcl_UnregisterChannel directly here. */ Tcl_DeleteHashEntry(hPtr); SetFlag(statePtr, CHANNEL_TAINTED); if (statePtr->refCount-- <= 1) { if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { (void) Tcl_Close(interp, (Tcl_Channel) chanPtr); } } } Tcl_DeleteHashTable(hTblPtr); ckfree(hTblPtr); } /* *---------------------------------------------------------------------- * * CheckForStdChannelsBeingClosed -- * * Perform special handling for standard channels being closed. When * given a standard channel, if the refcount is now 1, it means that the * last reference to the standard channel is being explicitly closed. Now * bump the refcount artificially down to 0, to ensure the normal * handling of channels being closed will occur. Also reset the static * pointer to the channel to NULL, to avoid dangling references. * * Results: * None. * * Side effects: * Manipulates the refcount on standard channels. May smash the global * static pointer to a standard channel. * *---------------------------------------------------------------------- */ static void CheckForStdChannelsBeingClosed( Tcl_Channel chan) { ChannelState *statePtr = ((Channel *) chan)->state; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->stdinInitialized && tsdPtr->stdinChannel != NULL && statePtr == ((Channel *)tsdPtr->stdinChannel)->state) { if (statePtr->refCount < 2) { statePtr->refCount = 0; tsdPtr->stdinChannel = NULL; return; } } else if (tsdPtr->stdoutInitialized && tsdPtr->stdoutChannel != NULL && statePtr == ((Channel *)tsdPtr->stdoutChannel)->state) { if (statePtr->refCount < 2) { statePtr->refCount = 0; tsdPtr->stdoutChannel = NULL; return; } } else if (tsdPtr->stderrInitialized && tsdPtr->stderrChannel != NULL && statePtr == ((Channel *)tsdPtr->stderrChannel)->state) { if (statePtr->refCount < 2) { statePtr->refCount = 0; tsdPtr->stderrChannel = NULL; return; } } } /* *---------------------------------------------------------------------- * * Tcl_IsStandardChannel -- * * Test if the given channel is a standard channel. No attempt is made to * check if the channel or the standard channels are initialized or * otherwise valid. * * Results: * Returns 1 if true, 0 if false. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_IsStandardChannel( Tcl_Channel chan) /* Channel to check. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if ((chan == tsdPtr->stdinChannel) || (chan == tsdPtr->stdoutChannel) || (chan == tsdPtr->stderrChannel)) { return 1; } else { return 0; } } /* *---------------------------------------------------------------------- * * Tcl_RegisterChannel -- * * Adds an already-open channel to the channel table of an interpreter. * If the interpreter passed as argument is NULL, it only increments the * channel refCount. * * Results: * None. * * Side effects: * May increment the reference count of a channel. * *---------------------------------------------------------------------- */ void Tcl_RegisterChannel( Tcl_Interp *interp, /* Interpreter in which to add the channel. */ Tcl_Channel chan) /* The channel to add to this interpreter * channel table. */ { Tcl_HashTable *hTblPtr; /* Hash table of channels. */ Tcl_HashEntry *hPtr; /* Search variable. */ int isNew; /* Is the hash entry new or does it exist? */ Channel *chanPtr; /* The actual channel. */ ChannelState *statePtr; /* State of the actual channel. */ /* * Always (un)register bottom-most channel in the stack. This makes * management of the channel list easier because no manipulation is * necessary during (un)stack operation. */ chanPtr = ((Channel *) chan)->state->bottomChanPtr; statePtr = chanPtr->state; if (statePtr->channelName == NULL) { Tcl_Panic("Tcl_RegisterChannel: channel without name"); } if (interp != NULL) { hTblPtr = GetChannelTable(interp); hPtr = Tcl_CreateHashEntry(hTblPtr, statePtr->channelName, &isNew); if (!isNew) { if (chan == Tcl_GetHashValue(hPtr)) { return; } Tcl_Panic("Tcl_RegisterChannel: duplicate channel names"); } Tcl_SetHashValue(hPtr, chanPtr); } statePtr->refCount++; } /* *---------------------------------------------------------------------- * * Tcl_UnregisterChannel -- * * Deletes the hash entry for a channel associated with an interpreter. * If the interpreter given as argument is NULL, it only decrements the * reference count. (This all happens in the Tcl_DetachChannel helper * function). * * Finally, if the reference count of the channel drops to zero, it is * deleted. * * Results: * A standard Tcl result. * * Side effects: * Calls Tcl_DetachChannel which deletes the hash entry for a channel * associated with an interpreter. * * May delete the channel, which can have a variety of consequences, * especially if we are forced to close the channel. * *---------------------------------------------------------------------- */ int Tcl_UnregisterChannel( Tcl_Interp *interp, /* Interpreter in which channel is defined. */ Tcl_Channel chan) /* Channel to delete. */ { ChannelState *statePtr; /* State of the real channel. */ statePtr = ((Channel *) chan)->state->bottomChanPtr->state; if (GotFlag(statePtr, CHANNEL_INCLOSE)) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "illegal recursive call to close through close-handler" " of channel", -1)); } return TCL_ERROR; } if (DetachChannel(interp, chan) != TCL_OK) { return TCL_OK; } statePtr = ((Channel *) chan)->state->bottomChanPtr->state; /* * Perform special handling for standard channels being closed. If the * refCount is now 1 it means that the last reference to the standard * channel is being explicitly closed, so bump the refCount down * artificially to 0. This will ensure that the channel is actually * closed, below. Also set the static pointer to NULL for the channel. */ CheckForStdChannelsBeingClosed(chan); /* * If the refCount reached zero, close the actual channel. */ if (statePtr->refCount <= 0) { Tcl_Preserve(statePtr); if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { /* * We don't want to re-enter Tcl_Close(). */ if (!GotFlag(statePtr, CHANNEL_CLOSED)) { if (Tcl_Close(interp, chan) != TCL_OK) { SetFlag(statePtr, CHANNEL_CLOSED); Tcl_Release(statePtr); return TCL_ERROR; } } } SetFlag(statePtr, CHANNEL_CLOSED); Tcl_Release(statePtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_DetachChannel -- * * Deletes the hash entry for a channel associated with an interpreter. * If the interpreter given as argument is NULL, it only decrements the * reference count. Even if the ref count drops to zero, the channel is * NOT closed or cleaned up. This allows a channel to be detached from an * interpreter and left in the same state it was in when it was * originally returned by 'Tcl_OpenFileChannel', for example. * * This function cannot be used on the standard channels, and will return * TCL_ERROR if that is attempted. * * This function should only be necessary for special purposes in which * you need to generate a pristine channel from one that has already been * used. All ordinary purposes will almost always want to use * Tcl_UnregisterChannel instead. * * Provided the channel is not attached to any other interpreter, it can * then be closed with Tcl_Close, rather than with Tcl_UnregisterChannel. * * Results: * A standard Tcl result. If the channel is not currently registered with * the given interpreter, TCL_ERROR is returned, otherwise TCL_OK. * However no error messages are left in the interp's result. * * Side effects: * Deletes the hash entry for a channel associated with an interpreter. * *---------------------------------------------------------------------- */ int Tcl_DetachChannel( Tcl_Interp *interp, /* Interpreter in which channel is defined. */ Tcl_Channel chan) /* Channel to delete. */ { if (Tcl_IsStandardChannel(chan)) { return TCL_ERROR; } return DetachChannel(interp, chan); } /* *---------------------------------------------------------------------- * * DetachChannel -- * * Deletes the hash entry for a channel associated with an interpreter. * If the interpreter given as argument is NULL, it only decrements the * reference count. Even if the ref count drops to zero, the channel is * NOT closed or cleaned up. This allows a channel to be detached from an * interpreter and left in the same state it was in when it was * originally returned by 'Tcl_OpenFileChannel', for example. * * Results: * A standard Tcl result. If the channel is not currently registered with * the given interpreter, TCL_ERROR is returned, otherwise TCL_OK. * However no error messages are left in the interp's result. * * Side effects: * Deletes the hash entry for a channel associated with an interpreter. * *---------------------------------------------------------------------- */ static int DetachChannel( Tcl_Interp *interp, /* Interpreter in which channel is defined. */ Tcl_Channel chan) /* Channel to delete. */ { Tcl_HashTable *hTblPtr; /* Hash table of channels. */ Tcl_HashEntry *hPtr; /* Search variable. */ Channel *chanPtr; /* The real IO channel. */ ChannelState *statePtr; /* State of the real channel. */ /* * Always (un)register bottom-most channel in the stack. This makes * management of the channel list easier because no manipulation is * necessary during (un)stack operation. */ chanPtr = ((Channel *) chan)->state->bottomChanPtr; statePtr = chanPtr->state; if (interp != NULL) { hTblPtr = Tcl_GetAssocData(interp, "tclIO", NULL); if (hTblPtr == NULL) { return TCL_ERROR; } hPtr = Tcl_FindHashEntry(hTblPtr, statePtr->channelName); if (hPtr == NULL) { return TCL_ERROR; } if ((Channel *) Tcl_GetHashValue(hPtr) != chanPtr) { return TCL_ERROR; } Tcl_DeleteHashEntry(hPtr); SetFlag(statePtr, CHANNEL_TAINTED); /* * Remove channel handlers that refer to this interpreter, so that * they will not be present if the actual close is delayed and more * events happen on the channel. This may occur if the channel is * shared between several interpreters, or if the channel has async * flushing active. */ CleanupChannelHandlers(interp, chanPtr); } statePtr->refCount--; return TCL_OK; } /* *--------------------------------------------------------------------------- * * Tcl_GetChannel -- * * Finds an existing Tcl_Channel structure by name in a given * interpreter. This function is public because it is used by * channel-type-specific functions. * * Results: * A Tcl_Channel or NULL on failure. If failed, interp's result object * contains an error message. *modePtr is filled with the modes in which * the channel was opened. * * Side effects: * None. * *--------------------------------------------------------------------------- */ Tcl_Channel Tcl_GetChannel( Tcl_Interp *interp, /* Interpreter in which to find or create the * channel. */ const char *chanName, /* The name of the channel. */ int *modePtr) /* Where to store the mode in which the * channel was opened? Will contain an ORed * combination of TCL_READABLE and * TCL_WRITABLE, if non-NULL. */ { Channel *chanPtr; /* The actual channel. */ Tcl_HashTable *hTblPtr; /* Hash table of channels. */ Tcl_HashEntry *hPtr; /* Search variable. */ const char *name; /* Translated name. */ /* * Substitute "stdin", etc. Note that even though we immediately find the * channel using Tcl_GetStdChannel, we still need to look it up in the * specified interpreter to ensure that it is present in the channel * table. Otherwise, safe interpreters would always have access to the * standard channels. */ name = chanName; if ((chanName[0] == 's') && (chanName[1] == 't')) { chanPtr = NULL; if (strcmp(chanName, "stdin") == 0) { chanPtr = (Channel *) Tcl_GetStdChannel(TCL_STDIN); } else if (strcmp(chanName, "stdout") == 0) { chanPtr = (Channel *) Tcl_GetStdChannel(TCL_STDOUT); } else if (strcmp(chanName, "stderr") == 0) { chanPtr = (Channel *) Tcl_GetStdChannel(TCL_STDERR); } if (chanPtr != NULL) { name = chanPtr->state->channelName; } } hTblPtr = GetChannelTable(interp); hPtr = Tcl_FindHashEntry(hTblPtr, name); if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can not find channel named \"%s\"", chanName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CHANNEL", chanName, NULL); return NULL; } /* * Always return bottom-most channel in the stack. This one lives the * longest - other channels may go away unnoticed. The other APIs * compensate where necessary to retrieve the topmost channel again. */ chanPtr = Tcl_GetHashValue(hPtr); chanPtr = chanPtr->state->bottomChanPtr; if (modePtr != NULL) { *modePtr = chanPtr->state->flags & (TCL_READABLE|TCL_WRITABLE); } return (Tcl_Channel) chanPtr; } /* *--------------------------------------------------------------------------- * * TclGetChannelFromObj -- * * Finds an existing Tcl_Channel structure by name in a given * interpreter. This function is public because it is used by * channel-type-specific functions. * * Results: * A Tcl_Channel or NULL on failure. If failed, interp's result object * contains an error message. *modePtr is filled with the modes in which * the channel was opened. * * Side effects: * None. * *--------------------------------------------------------------------------- */ int TclGetChannelFromObj( Tcl_Interp *interp, /* Interpreter in which to find or create the * channel. */ Tcl_Obj *objPtr, Tcl_Channel *channelPtr, int *modePtr, /* Where to store the mode in which the * channel was opened? Will contain an ORed * combination of TCL_READABLE and * TCL_WRITABLE, if non-NULL. */ int flags) { ChannelState *statePtr; if (SetChannelFromAny(interp, objPtr) != TCL_OK) { return TCL_ERROR; } statePtr = GET_CHANNELSTATE(objPtr); *channelPtr = (Tcl_Channel) statePtr->bottomChanPtr; if (modePtr != NULL) { *modePtr = statePtr->flags & (TCL_READABLE|TCL_WRITABLE); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_CreateChannel -- * * Creates a new entry in the hash table for a Tcl_Channel record. * * Results: * Returns the new Tcl_Channel. * * Side effects: * Creates a new Tcl_Channel instance and inserts it into the hash table. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_CreateChannel( const Tcl_ChannelType *typePtr, /* The channel type record. */ const char *chanName, /* Name of channel to record. */ ClientData instanceData, /* Instance specific data. */ int mask) /* TCL_READABLE & TCL_WRITABLE to indicate if * the channel is readable, writable. */ { Channel *chanPtr; /* The channel structure newly created. */ ChannelState *statePtr; /* The stack-level independent state info for * the channel. */ const char *name; char *tmp; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * With the change of the Tcl_ChannelType structure to use a version in * 8.3.2+, we have to make sure that our assumption that the structure * remains a binary compatible size is true. * * If this assertion fails on some system, then it can be removed only if * the user recompiles code with older channel drivers in the new system * as well. */ assert(sizeof(Tcl_ChannelTypeVersion) == sizeof(Tcl_DriverBlockModeProc *)); assert(typePtr->typeName != NULL); if (NULL == typePtr->closeProc) { Tcl_Panic("channel type %s must define closeProc", typePtr->typeName); } if ((TCL_READABLE & mask) && (NULL == typePtr->inputProc)) { Tcl_Panic("channel type %s must define inputProc when used for reader channel", typePtr->typeName); } if ((TCL_WRITABLE & mask) && (NULL == typePtr->outputProc)) { Tcl_Panic("channel type %s must define outputProc when used for writer channel", typePtr->typeName); } if (NULL == typePtr->watchProc) { Tcl_Panic("channel type %s must define watchProc", typePtr->typeName); } if ((NULL!=typePtr->wideSeekProc) && (NULL == typePtr->seekProc)) { Tcl_Panic("channel type %s must define seekProc if defining wideSeekProc", typePtr->typeName); } /* * JH: We could subsequently memset these to 0 to avoid the numerous * assignments to 0/NULL below. */ chanPtr = ckalloc(sizeof(Channel)); statePtr = ckalloc(sizeof(ChannelState)); chanPtr->state = statePtr; chanPtr->instanceData = instanceData; chanPtr->typePtr = typePtr; /* * Set all the bits that are part of the stack-independent state * information for the channel. */ if (chanName != NULL) { unsigned len = strlen(chanName) + 1; /* * Make sure we allocate at least 7 bytes, so it fits for "stdout" * later. */ tmp = ckalloc((len < 7) ? 7 : len); strcpy(tmp, chanName); } else { tmp = ckalloc(7); tmp[0] = '\0'; } statePtr->channelName = tmp; statePtr->flags = mask; /* * Set the channel to system default encoding. * * Note the strange bit of protection taking place here. If the system * encoding name is reported back as "binary", something weird is * happening. Tcl provides no "binary" encoding, so someone else has * provided one. We ignore it so as not to interfere with the "magic" * interpretation that Tcl_Channels give to the "-encoding binary" option. */ statePtr->encoding = NULL; name = Tcl_GetEncodingName(NULL); if (strcmp(name, "binary") != 0) { statePtr->encoding = Tcl_GetEncoding(NULL, name); } statePtr->inputEncodingState = NULL; statePtr->inputEncodingFlags = TCL_ENCODING_START; statePtr->outputEncodingState = NULL; statePtr->outputEncodingFlags = TCL_ENCODING_START; /* * Set the channel up initially in AUTO input translation mode to accept * "\n", "\r" and "\r\n". Output translation mode is set to a platform * specific default value. The eofChar is set to 0 for both input and * output, so that Tcl does not look for an in-file EOF indicator (e.g. * ^Z) and does not append an EOF indicator to files. */ statePtr->inputTranslation = TCL_TRANSLATE_AUTO; statePtr->outputTranslation = TCL_PLATFORM_TRANSLATION; statePtr->inEofChar = 0; statePtr->outEofChar = 0; statePtr->unreportedError = 0; statePtr->refCount = 0; statePtr->closeCbPtr = NULL; statePtr->curOutPtr = NULL; statePtr->outQueueHead = NULL; statePtr->outQueueTail = NULL; statePtr->saveInBufPtr = NULL; statePtr->inQueueHead = NULL; statePtr->inQueueTail = NULL; statePtr->chPtr = NULL; statePtr->interestMask = 0; statePtr->scriptRecordPtr = NULL; statePtr->bufSize = CHANNELBUFFER_DEFAULT_SIZE; statePtr->timer = NULL; statePtr->csPtrR = NULL; statePtr->csPtrW = NULL; statePtr->outputStage = NULL; /* * As we are creating the channel, it is obviously the top for now. */ statePtr->topChanPtr = chanPtr; statePtr->bottomChanPtr = chanPtr; chanPtr->downChanPtr = NULL; chanPtr->upChanPtr = NULL; chanPtr->inQueueHead = NULL; chanPtr->inQueueTail = NULL; chanPtr->refCount = 0; /* * TIP #219, Tcl Channel Reflection API */ statePtr->chanMsg = NULL; statePtr->unreportedMsg = NULL; /* * Link the channel into the list of all channels; create an on-exit * handler if there is not one already, to close off all the channels in * the list on exit. * * JH: Could call Tcl_SpliceChannel, but need to avoid NULL check. * * TIP #218. * AK: Just initialize the field to NULL before invoking Tcl_SpliceChannel * We need Tcl_SpliceChannel, for the threadAction calls. There is no * real reason to duplicate all of this. * NOTE: All drivers using thread actions now have to perform their TSD * manipulation only in their thread action proc. Doing it when * creating their instance structures will collide with the thread * action activity and lead to damaged lists. */ statePtr->nextCSPtr = NULL; SpliceChannel((Tcl_Channel) chanPtr); /* * Install this channel in the first empty standard channel slot, if the * channel was previously closed explicitly. */ if ((tsdPtr->stdinChannel == NULL) && (tsdPtr->stdinInitialized == 1)) { strcpy(tmp, "stdin"); Tcl_SetStdChannel((Tcl_Channel) chanPtr, TCL_STDIN); Tcl_RegisterChannel(NULL, (Tcl_Channel) chanPtr); } else if ((tsdPtr->stdoutChannel == NULL) && (tsdPtr->stdoutInitialized == 1)) { strcpy(tmp, "stdout"); Tcl_SetStdChannel((Tcl_Channel) chanPtr, TCL_STDOUT); Tcl_RegisterChannel(NULL, (Tcl_Channel) chanPtr); } else if ((tsdPtr->stderrChannel == NULL) && (tsdPtr->stderrInitialized == 1)) { strcpy(tmp, "stderr"); Tcl_SetStdChannel((Tcl_Channel) chanPtr, TCL_STDERR); Tcl_RegisterChannel(NULL, (Tcl_Channel) chanPtr); } return (Tcl_Channel) chanPtr; } /* *---------------------------------------------------------------------- * * Tcl_StackChannel -- * * Replaces an entry in the hash table for a Tcl_Channel record. The * replacement is a new channel with same name, it supercedes the * replaced channel. Input and output of the superceded channel is now * going through the newly created channel and allows the arbitrary * filtering/manipulation of the dataflow. * * Andreas Kupries , 12/13/1998 "Trf-Patch for * filtering channels" * * Results: * Returns the new Tcl_Channel, which actually contains the saved * information about prevChan. * * Side effects: * A new channel structure is allocated and linked below the existing * channel. The channel operations and client data of the existing * channel are copied down to the newly created channel, and the current * channel has its operations replaced by the new typePtr. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_StackChannel( Tcl_Interp *interp, /* The interpreter we are working in */ const Tcl_ChannelType *typePtr, /* The channel type record for the new * channel. */ ClientData instanceData, /* Instance specific data for the new * channel. */ int mask, /* TCL_READABLE & TCL_WRITABLE to indicate if * the channel is readable, writable. */ Tcl_Channel prevChan) /* The channel structure to replace */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Channel *chanPtr, *prevChanPtr; ChannelState *statePtr; /* * Find the given channel (prevChan) in the list of all channels. If we do * not find it, then it was never registered correctly. * * This operation should occur at the top of a channel stack. */ statePtr = (ChannelState *) tsdPtr->firstCSPtr; prevChanPtr = ((Channel *) prevChan)->state->topChanPtr; while ((statePtr != NULL) && (statePtr->topChanPtr != prevChanPtr)) { statePtr = statePtr->nextCSPtr; } if (statePtr == NULL) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't find state for channel \"%s\"", Tcl_GetChannelName(prevChan))); } return NULL; } /* * Here we check if the given "mask" matches the "flags" of the already * existing channel. * * | - | R | W | RW | * --+---+---+---+----+ <=> 0 != (chan->mask & prevChan->mask) * - | | | | | * R | | + | | + | The superceding channel is allowed to restrict * W | | | + | + | the capabilities of the superceded one! * RW| | + | + | + | * --+---+---+---+----+ */ if ((mask & (statePtr->flags & (TCL_READABLE | TCL_WRITABLE))) == 0) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "reading and writing both disallowed for channel \"%s\"", Tcl_GetChannelName(prevChan))); } return NULL; } /* * Flush the buffers. This ensures that any data still in them at this * time is not handled by the new transformation. Restrict this to * writable channels. Take care to hide a possible bg-copy in progress * from Tcl_Flush and the CheckForChannelErrors inside. */ if ((mask & TCL_WRITABLE) != 0) { CopyState *csPtrR = statePtr->csPtrR; CopyState *csPtrW = statePtr->csPtrW; statePtr->csPtrR = NULL; statePtr->csPtrW = NULL; /* * TODO: Examine what can go wrong if Tcl_Flush() call disturbs * the stacking state of this channel during its operations. */ if (Tcl_Flush((Tcl_Channel) prevChanPtr) != TCL_OK) { statePtr->csPtrR = csPtrR; statePtr->csPtrW = csPtrW; if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not flush channel \"%s\"", Tcl_GetChannelName(prevChan))); } return NULL; } statePtr->csPtrR = csPtrR; statePtr->csPtrW = csPtrW; } /* * Discard any input in the buffers. They are not yet read by the user of * the channel, so they have to go through the new transformation before * reading. As the buffers contain the untransformed form their contents * are not only useless but actually distorts our view of the system. * * To preserve the information without having to read them again and to * avoid problems with the location in the channel (seeking might be * impossible) we move the buffers from the common state structure into * the channel itself. We use the buffers in the channel below the new * transformation to hold the data. In the future this allows us to write * transformations which pre-read data and push the unused part back when * they are going away. */ if (((mask & TCL_READABLE) != 0) && (statePtr->inQueueHead != NULL)) { /* * When statePtr->inQueueHead is not NULL, we know * prevChanPtr->inQueueHead must be NULL. */ assert(prevChanPtr->inQueueHead == NULL); assert(prevChanPtr->inQueueTail == NULL); prevChanPtr->inQueueHead = statePtr->inQueueHead; prevChanPtr->inQueueTail = statePtr->inQueueTail; statePtr->inQueueHead = NULL; statePtr->inQueueTail = NULL; } chanPtr = ckalloc(sizeof(Channel)); /* * Save some of the current state into the new structure, reinitialize the * parts which will stay with the transformation. * * Remarks: */ chanPtr->state = statePtr; chanPtr->instanceData = instanceData; chanPtr->typePtr = typePtr; chanPtr->downChanPtr = prevChanPtr; chanPtr->upChanPtr = NULL; chanPtr->inQueueHead = NULL; chanPtr->inQueueTail = NULL; chanPtr->refCount = 0; /* * Place new block at the head of a possibly existing list of previously * stacked channels. */ prevChanPtr->upChanPtr = chanPtr; statePtr->topChanPtr = chanPtr; /* * TIP #218, Channel Thread Actions. * * We call the thread actions for the new channel directly. We _cannot_ * use SpliceChannel, because the (thread-)global list of all channels * always contains the _ChannelState_ for a stack of channels, not the * individual channels. And SpliceChannel would not only call the thread * actions, but also add the shared ChannelState to this list a second * time, mangling it. */ ChanThreadAction(chanPtr, TCL_CHANNEL_THREAD_INSERT); return (Tcl_Channel) chanPtr; } void TclChannelPreserve( Tcl_Channel chan) { ((Channel *)chan)->refCount++; } void TclChannelRelease( Tcl_Channel chan) { Channel *chanPtr = (Channel *) chan; if (chanPtr->refCount == 0) { Tcl_Panic("Channel released more than preserved"); } if (--chanPtr->refCount) { return; } if (chanPtr->typePtr == NULL) { ckfree(chanPtr); } } static void ChannelFree( Channel *chanPtr) { if (chanPtr->refCount == 0) { ckfree(chanPtr); return; } chanPtr->typePtr = NULL; } /* *---------------------------------------------------------------------- * * Tcl_UnstackChannel -- * * Unstacks an entry in the hash table for a Tcl_Channel record. This is * the reverse to 'Tcl_StackChannel'. * * Results: * A standard Tcl result. * * Side effects: * If TCL_ERROR is returned, the posix error code will be set with * Tcl_SetErrno. May leave a message in interp result as well. * *---------------------------------------------------------------------- */ int Tcl_UnstackChannel( Tcl_Interp *interp, /* The interpreter we are working in */ Tcl_Channel chan) /* The channel to unstack */ { Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; int result = 0; /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; if (chanPtr->downChanPtr != NULL) { /* * Instead of manipulating the per-thread / per-interp list/hashtable * of registered channels we wind down the state of the * transformation, and then restore the state of underlying channel * into the old structure. */ /* * TODO: Figure out how to handle the situation where the chan * operations called below by this unstacking operation cause * another unstacking recursively. In that case the downChanPtr * value we're holding on to will not be the right thing. */ Channel *downChanPtr = chanPtr->downChanPtr; /* * Flush the buffers. This ensures that any data still in them at this * time _is_ handled by the transformation we are unstacking right * now. Restrict this to writable channels. Take care to hide a * possible bg-copy in progress from Tcl_Flush and the * CheckForChannelErrors inside. */ if (GotFlag(statePtr, TCL_WRITABLE)) { CopyState *csPtrR = statePtr->csPtrR; CopyState *csPtrW = statePtr->csPtrW; statePtr->csPtrR = NULL; statePtr->csPtrW = NULL; if (Tcl_Flush((Tcl_Channel) chanPtr) != TCL_OK) { statePtr->csPtrR = csPtrR; statePtr->csPtrW = csPtrW; /* * TIP #219, Tcl Channel Reflection API. * Move error messages put by the driver into the chan/ip * bypass area into the regular interpreter result. Fall back * to the regular message if nothing was found in the * bypasses. */ if (!TclChanCaughtErrorBypass(interp, chan) && interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not flush channel \"%s\"", Tcl_GetChannelName((Tcl_Channel) chanPtr))); } return TCL_ERROR; } statePtr->csPtrR = csPtrR; statePtr->csPtrW = csPtrW; } /* * Anything in the input queue and the push-back buffers of the * transformation going away is transformed data, but not yet read. As * unstacking means that the caller does not want to see transformed * data any more we have to discard these bytes. To avoid writing an * analogue to 'DiscardInputQueued' we move the information in the * push back buffers to the input queue and then call * 'DiscardInputQueued' on that. */ if (GotFlag(statePtr, TCL_READABLE) && ((statePtr->inQueueHead != NULL) || (chanPtr->inQueueHead != NULL))) { if ((statePtr->inQueueHead != NULL) && (chanPtr->inQueueHead != NULL)) { statePtr->inQueueTail->nextPtr = chanPtr->inQueueHead; statePtr->inQueueTail = chanPtr->inQueueTail; statePtr->inQueueHead = statePtr->inQueueTail; } else if (chanPtr->inQueueHead != NULL) { statePtr->inQueueHead = chanPtr->inQueueHead; statePtr->inQueueTail = chanPtr->inQueueTail; } chanPtr->inQueueHead = NULL; chanPtr->inQueueTail = NULL; DiscardInputQueued(statePtr, 0); } /* * TIP #218, Channel Thread Actions. * * We call the thread actions for the new channel directly. We * _cannot_ use CutChannel, because the (thread-)global list of all * channels always contains the _ChannelState_ for a stack of * channels, not the individual channels. And SpliceChannel would not * only call the thread actions, but also remove the shared * ChannelState from this list despite there being more channels for * the state which are still active. */ ChanThreadAction(chanPtr, TCL_CHANNEL_THREAD_REMOVE); statePtr->topChanPtr = downChanPtr; downChanPtr->upChanPtr = NULL; /* * Leave this link intact for closeproc * chanPtr->downChanPtr = NULL; */ /* * Close and free the channel driver state. */ result = ChanClose(chanPtr, interp); ChannelFree(chanPtr); UpdateInterest(statePtr->topChanPtr); if (result != 0) { Tcl_SetErrno(result); /* * TIP #219, Tcl Channel Reflection API. * Move error messages put by the driver into the chan/ip bypass * area into the regular interpreter result. */ TclChanCaughtErrorBypass(interp, chan); return TCL_ERROR; } } else { /* * This channel does not cover another one. Simply do a close, if * necessary. */ if (statePtr->refCount <= 0) { if (Tcl_Close(interp, chan) != TCL_OK) { /* * TIP #219, Tcl Channel Reflection API. * "TclChanCaughtErrorBypass" is not required here, it was * done already by "Tcl_Close". */ return TCL_ERROR; } } /* * TIP #218, Channel Thread Actions. * Not required in this branch, this is done by Tcl_Close. If * Tcl_Close is not called then the ChannelState is still active in * the thread and no action has to be taken either. */ } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetStackedChannel -- * * Determines whether the specified channel is stacked upon another. * * Results: * NULL if the channel is not stacked upon another one, or a reference to * the channel it is stacked upon. This reference can be used in queries, * but modification is not allowed. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_GetStackedChannel( Tcl_Channel chan) { Channel *chanPtr = (Channel *) chan; /* The actual channel. */ return (Tcl_Channel) chanPtr->downChanPtr; } /* *---------------------------------------------------------------------- * * Tcl_GetTopChannel -- * * Returns the top channel of a channel stack. * * Results: * NULL if the channel is not stacked upon another one, or a reference to * the channel it is stacked upon. This reference can be used in queries, * but modification is not allowed. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_Channel Tcl_GetTopChannel( Tcl_Channel chan) { Channel *chanPtr = (Channel *) chan; /* The actual channel. */ return (Tcl_Channel) chanPtr->state->topChanPtr; } /* *---------------------------------------------------------------------- * * Tcl_GetChannelInstanceData -- * * Returns the client data associated with a channel. * * Results: * The client data. * * Side effects: * None. * *---------------------------------------------------------------------- */ ClientData Tcl_GetChannelInstanceData( Tcl_Channel chan) /* Channel for which to return client data. */ { Channel *chanPtr = (Channel *) chan; /* The actual channel. */ return chanPtr->instanceData; } /* *---------------------------------------------------------------------- * * Tcl_GetChannelThread -- * * Given a channel structure, returns the thread managing it. TIP #10 * * Results: * Returns the id of the thread managing the channel. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_ThreadId Tcl_GetChannelThread( Tcl_Channel chan) /* The channel to return the managing thread * for. */ { Channel *chanPtr = (Channel *) chan; /* The actual channel. */ return chanPtr->state->managingThread; } /* *---------------------------------------------------------------------- * * Tcl_GetChannelType -- * * Given a channel structure, returns the channel type structure. * * Results: * Returns a pointer to the channel type structure. * * Side effects: * None. * *---------------------------------------------------------------------- */ const Tcl_ChannelType * Tcl_GetChannelType( Tcl_Channel chan) /* The channel to return type for. */ { Channel *chanPtr = (Channel *) chan; /* The actual channel. */ return chanPtr->typePtr; } /* *---------------------------------------------------------------------- * * Tcl_GetChannelMode -- * * Computes a mask indicating whether the channel is open for reading and * writing. * * Results: * An OR-ed combination of TCL_READABLE and TCL_WRITABLE. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetChannelMode( Tcl_Channel chan) /* The channel for which the mode is being * computed. */ { ChannelState *statePtr = ((Channel *) chan)->state; /* State of actual channel. */ return (statePtr->flags & (TCL_READABLE | TCL_WRITABLE)); } /* *---------------------------------------------------------------------- * * Tcl_GetChannelName -- * * Returns the string identifying the channel name. * * Results: * The string containing the channel name. This memory is owned by the * generic layer and should not be modified by the caller. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * Tcl_GetChannelName( Tcl_Channel chan) /* The channel for which to return the name. */ { ChannelState *statePtr = ((Channel *) chan)->state; /* State of actual channel. */ return statePtr->channelName; } /* *---------------------------------------------------------------------- * * Tcl_GetChannelHandle -- * * Returns an OS handle associated with a channel. * * Results: * Returns TCL_OK and places the handle in handlePtr, or returns * TCL_ERROR on failure. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetChannelHandle( Tcl_Channel chan, /* The channel to get file from. */ int direction, /* TCL_WRITABLE or TCL_READABLE. */ ClientData *handlePtr) /* Where to store handle */ { Channel *chanPtr; /* The actual channel. */ ClientData handle; int result; chanPtr = ((Channel *) chan)->state->bottomChanPtr; if (!chanPtr->typePtr->getHandleProc) { Tcl_SetChannelError(chan, Tcl_ObjPrintf( "channel \"%s\" does not support OS handles", Tcl_GetChannelName(chan))); return TCL_ERROR; } result = chanPtr->typePtr->getHandleProc(chanPtr->instanceData, direction, &handle); if (handlePtr) { *handlePtr = handle; } return result; } /* *--------------------------------------------------------------------------- * * AllocChannelBuffer -- * * A channel buffer has BUFFER_PADDING bytes extra at beginning to hold * any bytes of a native-encoding character that got split by the end of * the previous buffer and need to be moved to the beginning of the next * buffer to make a contiguous string so it can be converted to UTF-8. * * A channel buffer has BUFFER_PADDING bytes extra at the end to hold any * bytes of a native-encoding character (generated from a UTF-8 * character) that overflow past the end of the buffer and need to be * moved to the next buffer. * * Results: * A newly allocated channel buffer. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static ChannelBuffer * AllocChannelBuffer( int length) /* Desired length of channel buffer. */ { ChannelBuffer *bufPtr; int n; n = length + CHANNELBUFFER_HEADER_SIZE + BUFFER_PADDING + BUFFER_PADDING; bufPtr = ckalloc(n); bufPtr->nextAdded = BUFFER_PADDING; bufPtr->nextRemoved = BUFFER_PADDING; bufPtr->bufLength = length + BUFFER_PADDING; bufPtr->nextPtr = NULL; bufPtr->refCount = 1; return bufPtr; } static void PreserveChannelBuffer( ChannelBuffer *bufPtr) { if (bufPtr->refCount == 0) { Tcl_Panic("Reuse of ChannelBuffer! %p", bufPtr); } bufPtr->refCount++; } static void ReleaseChannelBuffer( ChannelBuffer *bufPtr) { if (--bufPtr->refCount) { return; } ckfree(bufPtr); } static int IsShared( ChannelBuffer *bufPtr) { return bufPtr->refCount > 1; } /* *---------------------------------------------------------------------- * * RecycleBuffer -- * * Helper function to recycle input and output buffers. Ensures that two * input buffers are saved (one in the input queue and another in the * saveInBufPtr field) and that curOutPtr is set to a buffer. Only if * these conditions are met is the buffer freed to the OS. * * Results: * None. * * Side effects: * May free a buffer to the OS. * *---------------------------------------------------------------------- */ static void RecycleBuffer( ChannelState *statePtr, /* ChannelState in which to recycle buffers. */ ChannelBuffer *bufPtr, /* The buffer to recycle. */ int mustDiscard) /* If nonzero, free the buffer to the OS, * always. */ { /* * Do we have to free the buffer to the OS? */ if (IsShared(bufPtr)) { mustDiscard = 1; } if (mustDiscard) { ReleaseChannelBuffer(bufPtr); return; } /* * Only save buffers which have the requested buffersize for the * channel. This is to honor dynamic changes of the buffersize * made by the user. */ if ((bufPtr->bufLength - BUFFER_PADDING) != statePtr->bufSize) { ReleaseChannelBuffer(bufPtr); return; } /* * Only save buffers for the input queue if the channel is readable. */ if (GotFlag(statePtr, TCL_READABLE)) { if (statePtr->inQueueHead == NULL) { statePtr->inQueueHead = bufPtr; statePtr->inQueueTail = bufPtr; goto keepBuffer; } if (statePtr->saveInBufPtr == NULL) { statePtr->saveInBufPtr = bufPtr; goto keepBuffer; } } /* * Only save buffers for the output queue if the channel is writable. */ if (GotFlag(statePtr, TCL_WRITABLE)) { if (statePtr->curOutPtr == NULL) { statePtr->curOutPtr = bufPtr; goto keepBuffer; } } /* * If we reached this code we return the buffer to the OS. */ ReleaseChannelBuffer(bufPtr); return; keepBuffer: bufPtr->nextRemoved = BUFFER_PADDING; bufPtr->nextAdded = BUFFER_PADDING; bufPtr->nextPtr = NULL; } /* *---------------------------------------------------------------------- * * DiscardOutputQueued -- * * Discards all output queued in the output queue of a channel. * * Results: * None. * * Side effects: * Recycles buffers. * *---------------------------------------------------------------------- */ static void DiscardOutputQueued( ChannelState *statePtr) /* ChannelState for which to discard output. */ { ChannelBuffer *bufPtr; while (statePtr->outQueueHead != NULL) { bufPtr = statePtr->outQueueHead; statePtr->outQueueHead = bufPtr->nextPtr; RecycleBuffer(statePtr, bufPtr, 0); } statePtr->outQueueHead = NULL; statePtr->outQueueTail = NULL; bufPtr = statePtr->curOutPtr; if (bufPtr && BytesLeft(bufPtr)) { statePtr->curOutPtr = NULL; RecycleBuffer(statePtr, bufPtr, 0); } } /* *---------------------------------------------------------------------- * * CheckForDeadChannel -- * * This function checks is a given channel is Dead (a channel that has * been closed but not yet deallocated.) * * Results: * True (1) if channel is Dead, False (0) if channel is Ok * * Side effects: * None * *---------------------------------------------------------------------- */ static int CheckForDeadChannel( Tcl_Interp *interp, /* For error reporting (can be NULL) */ ChannelState *statePtr) /* The channel state to check. */ { if (!GotFlag(statePtr, CHANNEL_DEAD)) { return 0; } Tcl_SetErrno(EINVAL); if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unable to access channel: invalid channel", -1)); } return 1; } /* *---------------------------------------------------------------------- * * FlushChannel -- * * This function flushes as much of the queued output as is possible now. * If calledFromAsyncFlush is nonzero, it is being called in an event * handler to flush channel output asynchronously. * * Results: * 0 if successful, else the error code that was returned by the channel * type operation. May leave a message in the interp result. * * Side effects: * May produce output on a channel. May block indefinitely if the channel * is synchronous. May schedule an async flush on the channel. May * recycle memory for buffers in the output queue. * *---------------------------------------------------------------------- */ static int FlushChannel( Tcl_Interp *interp, /* For error reporting during close. */ Channel *chanPtr, /* The channel to flush on. */ int calledFromAsyncFlush) /* If nonzero then we are being called from an * asynchronous flush callback. */ { ChannelState *statePtr = chanPtr->state; /* State of the channel stack. */ ChannelBuffer *bufPtr; /* Iterates over buffered output queue. */ int written; /* Amount of output data actually written in * current round. */ int errorCode = 0; /* Stores POSIX error codes from channel * driver operations. */ int wroteSome = 0; /* Set to one if any data was written to the * driver. */ /* * Prevent writing on a dead channel -- a channel that has been closed but * not yet deallocated. This can occur if the exit handler for the channel * deallocation runs before all channels are deregistered in all * interpreters. */ if (CheckForDeadChannel(interp, statePtr)) { return -1; } /* * Should we shift the current output buffer over to the output queue? * First check that there are bytes in it. If so then... * If the output queue is empty, then yes, trusting the caller called * us only when written bytes ought to be flushed. * If the current output buffer is full, then yes, so we can meet * the post-condition that on a successful return to caller we've * left space in the current output buffer for more writing (the flush * call was to make new room). * If the channel is blocking, then yes, so we guarantee that * blocking flushes actually flush all pending data. * Otherwise, no. Keep the current output buffer where it is so more * can be written to it, possibly filling it, to promote more efficient * buffer usage. */ bufPtr = statePtr->curOutPtr; if (bufPtr && BytesLeft(bufPtr) && /* Keep empties off queue */ (statePtr->outQueueHead == NULL || IsBufferFull(bufPtr) || !GotFlag(statePtr, CHANNEL_NONBLOCKING))) { if (statePtr->outQueueHead == NULL) { statePtr->outQueueHead = bufPtr; } else { statePtr->outQueueTail->nextPtr = bufPtr; } statePtr->outQueueTail = bufPtr; statePtr->curOutPtr = NULL; } assert(!IsBufferFull(statePtr->curOutPtr)); /* * If we are not being called from an async flush and an async flush * is active, we just return without producing any output. */ if (!calledFromAsyncFlush && GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { return 0; } /* * Loop over the queued buffers and attempt to flush as much as possible * of the queued output to the channel. */ TclChannelPreserve((Tcl_Channel)chanPtr); while (statePtr->outQueueHead) { bufPtr = statePtr->outQueueHead; /* * Produce the output on the channel. */ PreserveChannelBuffer(bufPtr); written = ChanWrite(chanPtr, RemovePoint(bufPtr), BytesLeft(bufPtr), &errorCode); /* * If the write failed completely attempt to start the asynchronous * flush mechanism and break out of this loop - do not attempt to * write any more output at this time. */ if (written < 0) { /* * If the last attempt to write was interrupted, simply retry. */ if (errorCode == EINTR) { errorCode = 0; ReleaseChannelBuffer(bufPtr); continue; } /* * If the channel is non-blocking and we would have blocked, start * a background flushing handler and break out of the loop. */ if ((errorCode == EWOULDBLOCK) || (errorCode == EAGAIN)) { /* * This used to check for CHANNEL_NONBLOCKING, and panic if * the channel was blocking. However, it appears that setting * stdin to -blocking 0 has some effect on the stdout when * it's a tty channel (dup'ed underneath) */ if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED) && !TclInExit()) { SetFlag(statePtr, BG_FLUSH_SCHEDULED); UpdateInterest(chanPtr); } errorCode = 0; ReleaseChannelBuffer(bufPtr); break; } /* * Decide whether to report the error upwards or defer it. */ if (calledFromAsyncFlush) { /* * TIP #219, Tcl Channel Reflection API. * When defering the error copy a message from the bypass into * the unreported area. Or discard it if the new error is to be * ignored in favor of an earlier defered error. */ Tcl_Obj *msg = statePtr->chanMsg; if (statePtr->unreportedError == 0) { statePtr->unreportedError = errorCode; statePtr->unreportedMsg = msg; if (msg != NULL) { Tcl_IncrRefCount(msg); } } else { /* * An old unreported error is kept, and this error thrown * away. */ statePtr->chanMsg = NULL; if (msg != NULL) { TclDecrRefCount(msg); } } } else { /* * TIP #219, Tcl Channel Reflection API. * Move error messages put by the driver into the chan bypass * area into the regular interpreter result. Fall back to the * regular message if nothing was found in the bypasses. */ Tcl_SetErrno(errorCode); if (interp != NULL && !TclChanCaughtErrorBypass(interp, (Tcl_Channel) chanPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_PosixError(interp), -1)); } /* * An unreportable bypassed message is kept, for the caller of * Tcl_Seek, Tcl_Write, etc. */ } /* * When we get an error we throw away all the output currently * queued. */ DiscardOutputQueued(statePtr); ReleaseChannelBuffer(bufPtr); break; } else { /* TODO: Consider detecting and reacting to short writes * on blocking channels. Ought not happen. See iocmd-24.2. */ wroteSome = 1; } bufPtr->nextRemoved += written; /* * If this buffer is now empty, recycle it. */ if (IsBufferEmpty(bufPtr)) { statePtr->outQueueHead = bufPtr->nextPtr; if (statePtr->outQueueHead == NULL) { statePtr->outQueueTail = NULL; } RecycleBuffer(statePtr, bufPtr, 0); } ReleaseChannelBuffer(bufPtr); } /* Closes "while". */ /* * If we wrote some data while flushing in the background, we are done. * We can't finish the background flush until we run out of data and the * channel becomes writable again. This ensures that all of the pending * data has been flushed at the system level. */ if (GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { if (wroteSome) { goto done; } else if (statePtr->outQueueHead == NULL) { ResetFlag(statePtr, BG_FLUSH_SCHEDULED); ChanWatch(chanPtr, statePtr->interestMask); } else { /* * When we are calledFromAsyncFlush, that means a writable * state on the channel triggered the call, so we should be * able to write something. Either we did write something * and wroteSome should be set, or there was nothing left to * write in this call, and we've completed the BG flush. * These are the two cases above. If we get here, that means * there is some kind failure in the writable event machinery. * * The tls extension indeed suffers from flaws in its channel * event mgmt. See http://core.tcl.tk/tcl/info/c31ca233ca. * Until that patch is broadly distributed, disable the * assertion checking here, so that programs using Tcl and * tls can be debugged. assert(!calledFromAsyncFlush); */ } } /* * If the channel is flagged as closed, delete it when the refCount drops * to zero, the output queue is empty and there is no output in the * current output buffer. */ if (GotFlag(statePtr, CHANNEL_CLOSED) && (statePtr->refCount <= 0) && (statePtr->outQueueHead == NULL) && ((statePtr->curOutPtr == NULL) || IsBufferEmpty(statePtr->curOutPtr))) { errorCode = CloseChannel(interp, chanPtr, errorCode); goto done; } /* * If the write-side of the channel is flagged as closed, delete it when * the output queue is empty and there is no output in the current output * buffer. */ if (GotFlag(statePtr, CHANNEL_CLOSEDWRITE) && (statePtr->outQueueHead == NULL) && ((statePtr->curOutPtr == NULL) || IsBufferEmpty(statePtr->curOutPtr))) { errorCode = CloseChannelPart(interp, chanPtr, errorCode, TCL_CLOSE_WRITE); goto done; } done: TclChannelRelease((Tcl_Channel)chanPtr); return errorCode; } /* *---------------------------------------------------------------------- * * CloseChannel -- * * Utility procedure to close a channel and free associated resources. * * If the channel was stacked, then the it will copy the necessary * elements of the NEXT channel into the TOP channel, in essence * unstacking the channel. The NEXT channel will then be freed. * * If the channel was not stacked, then we will free all the bits for the * TOP channel, including the data structure itself. * * Results: * Error code from an unreported error or the driver close operation. * * Side effects: * May close the actual channel, may free memory, may change the value of * errno. * *---------------------------------------------------------------------- */ static int CloseChannel( Tcl_Interp *interp, /* For error reporting. */ Channel *chanPtr, /* The channel to close. */ int errorCode) /* Status of operation so far. */ { int result = 0; /* Of calling driver close operation. */ ChannelState *statePtr; /* State of the channel stack. */ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (chanPtr == NULL) { return result; } statePtr = chanPtr->state; /* * No more input can be consumed so discard any leftover input. */ DiscardInputQueued(statePtr, 1); /* * Discard a leftover buffer in the current output buffer field. */ if (statePtr->curOutPtr != NULL) { ReleaseChannelBuffer(statePtr->curOutPtr); statePtr->curOutPtr = NULL; } /* * The caller guarantees that there are no more buffers queued for output. */ if (statePtr->outQueueHead != NULL) { Tcl_Panic("TclFlush, closed channel: queued output left"); } /* * If the EOF character is set in the channel, append that to the output * device. */ if ((statePtr->outEofChar != 0) && GotFlag(statePtr, TCL_WRITABLE)) { int dummy; char c = (char) statePtr->outEofChar; (void) ChanWrite(chanPtr, &c, 1, &dummy); } /* * TIP #219, Tcl Channel Reflection API. * Move a leftover error message in the channel bypass into the * interpreter bypass. Just clear it if there is no interpreter. */ if (statePtr->chanMsg != NULL) { if (interp != NULL) { Tcl_SetChannelErrorInterp(interp, statePtr->chanMsg); } TclDecrRefCount(statePtr->chanMsg); statePtr->chanMsg = NULL; } /* * Remove this channel from of the list of all channels. */ CutChannel((Tcl_Channel) chanPtr); /* * Close and free the channel driver state. * This may leave a TIP #219 error message in the interp. */ result = ChanClose(chanPtr, interp); /* * Some resources can be cleared only if the bottom channel in a stack is * closed. All the other channels in the stack are not allowed to remove. */ if (chanPtr == statePtr->bottomChanPtr) { if (statePtr->channelName != NULL) { ckfree(statePtr->channelName); statePtr->channelName = NULL; } Tcl_FreeEncoding(statePtr->encoding); } /* * If we are being called synchronously, report either any latent error on * the channel or the current error. */ if (statePtr->unreportedError != 0) { errorCode = statePtr->unreportedError; /* * TIP #219, Tcl Channel Reflection API. * Move an error message found in the unreported area into the regular * bypass (interp). This kills any message in the channel bypass area. */ if (statePtr->chanMsg != NULL) { TclDecrRefCount(statePtr->chanMsg); statePtr->chanMsg = NULL; } if (interp) { Tcl_SetChannelErrorInterp(interp, statePtr->unreportedMsg); } } if (errorCode == 0) { errorCode = result; if (errorCode != 0) { Tcl_SetErrno(errorCode); } } /* * Cancel any outstanding timer. */ Tcl_DeleteTimerHandler(statePtr->timer); /* * Mark the channel as deleted by clearing the type structure. */ if (chanPtr->downChanPtr != NULL) { Channel *downChanPtr = chanPtr->downChanPtr; statePtr->nextCSPtr = tsdPtr->firstCSPtr; tsdPtr->firstCSPtr = statePtr; statePtr->topChanPtr = downChanPtr; downChanPtr->upChanPtr = NULL; ChannelFree(chanPtr); return Tcl_Close(interp, (Tcl_Channel) downChanPtr); } /* * There is only the TOP Channel, so we free the remaining pointers we * have and then ourselves. Since this is the last of the channels in the * stack, make sure to free the ChannelState structure associated with it. */ ChannelFree(chanPtr); Tcl_EventuallyFree(statePtr, TCL_DYNAMIC); return errorCode; } /* *---------------------------------------------------------------------- * * Tcl_CutChannel -- * CutChannel -- * * Removes a channel from the (thread-)global list of all channels (in * that thread). This is actually the statePtr for the stack of channel. * * Results: * Nothing. * * Side effects: * Resets the field 'nextCSPtr' of the specified channel state to NULL. * * NOTE: * The channel to cut out of the list must not be referenced in any * interpreter. This is something this procedure cannot check (despite * the refcount) because the caller usually wants fiddle with the channel * (like transfering it to a different thread) and thus keeps the * refcount artifically high to prevent its destruction. * *---------------------------------------------------------------------- */ static void CutChannel( Tcl_Channel chan) /* The channel being removed. Must not be * referenced in any interpreter. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ChannelState *prevCSPtr; /* Preceding channel state in list of all * states - used to splice a channel out of * the list on close. */ ChannelState *statePtr = ((Channel *) chan)->state; /* State of the channel stack. */ /* * Remove this channel from of the list of all channels (in the current * thread). */ if (tsdPtr->firstCSPtr && (statePtr == tsdPtr->firstCSPtr)) { tsdPtr->firstCSPtr = statePtr->nextCSPtr; } else { for (prevCSPtr = tsdPtr->firstCSPtr; prevCSPtr && (prevCSPtr->nextCSPtr != statePtr); prevCSPtr = prevCSPtr->nextCSPtr) { /* Empty loop body. */ } if (prevCSPtr == NULL) { Tcl_Panic("FlushChannel: damaged channel list"); } prevCSPtr->nextCSPtr = statePtr->nextCSPtr; } statePtr->nextCSPtr = NULL; /* * TIP #218, Channel Thread Actions */ ChanThreadAction((Channel *) chan, TCL_CHANNEL_THREAD_REMOVE); } void Tcl_CutChannel( Tcl_Channel chan) /* The channel being added. Must not be * referenced in any interpreter. */ { Channel *chanPtr = ((Channel *) chan)->state->bottomChanPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ChannelState *prevCSPtr; /* Preceding channel state in list of all * states - used to splice a channel out of * the list on close. */ ChannelState *statePtr = chanPtr->state; /* State of the channel stack. */ /* * Remove this channel from of the list of all channels (in the current * thread). */ if (tsdPtr->firstCSPtr && (statePtr == tsdPtr->firstCSPtr)) { tsdPtr->firstCSPtr = statePtr->nextCSPtr; } else { for (prevCSPtr = tsdPtr->firstCSPtr; prevCSPtr && (prevCSPtr->nextCSPtr != statePtr); prevCSPtr = prevCSPtr->nextCSPtr) { /* Empty loop body. */ } if (prevCSPtr == NULL) { Tcl_Panic("FlushChannel: damaged channel list"); } prevCSPtr->nextCSPtr = statePtr->nextCSPtr; } statePtr->nextCSPtr = NULL; /* * TIP #218, Channel Thread Actions * For all transformations and the base channel. */ for (; chanPtr != NULL ; chanPtr = chanPtr->upChanPtr) { ChanThreadAction(chanPtr, TCL_CHANNEL_THREAD_REMOVE); } } /* *---------------------------------------------------------------------- * * Tcl_SpliceChannel -- * SpliceChannel -- * * Adds a channel to the (thread-)global list of all channels (in that * thread). Expects that the field 'nextChanPtr' in the channel is set to * NULL. * * Results: * Nothing. * * Side effects: * Nothing. * * NOTE: * The channel to splice into the list must not be referenced in any * interpreter. This is something this procedure cannot check (despite * the refcount) because the caller usually wants figgle with the channel * (like transfering it to a different thread) and thus keeps the * refcount artifically high to prevent its destruction. * *---------------------------------------------------------------------- */ static void SpliceChannel( Tcl_Channel chan) /* The channel being added. Must not be * referenced in any interpreter. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ChannelState *statePtr = ((Channel *) chan)->state; if (statePtr->nextCSPtr != NULL) { Tcl_Panic("SpliceChannel: trying to add channel used in different list"); } statePtr->nextCSPtr = tsdPtr->firstCSPtr; tsdPtr->firstCSPtr = statePtr; /* * TIP #10. Mark the current thread as the new one managing this channel. * Note: 'Tcl_GetCurrentThread' returns sensible values even for * a non-threaded core. */ statePtr->managingThread = Tcl_GetCurrentThread(); /* * TIP #218, Channel Thread Actions */ ChanThreadAction((Channel *) chan, TCL_CHANNEL_THREAD_INSERT); } void Tcl_SpliceChannel( Tcl_Channel chan) /* The channel being added. Must not be * referenced in any interpreter. */ { Channel *chanPtr = ((Channel *) chan)->state->bottomChanPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ChannelState *statePtr = chanPtr->state; if (statePtr->nextCSPtr != NULL) { Tcl_Panic("SpliceChannel: trying to add channel used in different list"); } statePtr->nextCSPtr = tsdPtr->firstCSPtr; tsdPtr->firstCSPtr = statePtr; /* * TIP #10. Mark the current thread as the new one managing this channel. * Note: 'Tcl_GetCurrentThread' returns sensible values even for * a non-threaded core. */ statePtr->managingThread = Tcl_GetCurrentThread(); /* * TIP #218, Channel Thread Actions * For all transformations and the base channel. */ for (; chanPtr != NULL ; chanPtr = chanPtr->upChanPtr) { ChanThreadAction(chanPtr, TCL_CHANNEL_THREAD_INSERT); } } /* *---------------------------------------------------------------------- * * Tcl_Close -- * * Closes a channel. * * Results: * A standard Tcl result. * * Side effects: * Closes the channel if this is the last reference. * * NOTE: * Tcl_Close removes the channel as far as the user is concerned. * However, it may continue to exist for a while longer if it has a * background flush scheduled. The device itself is eventually closed and * the channel record removed, in CloseChannel, above. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_Close( Tcl_Interp *interp, /* Interpreter for errors. */ Tcl_Channel chan) /* The channel being closed. Must not be * referenced in any interpreter. */ { CloseCallback *cbPtr; /* Iterate over close callbacks for this * channel. */ Channel *chanPtr; /* The real IO channel. */ ChannelState *statePtr; /* State of real IO channel. */ int result; /* Of calling FlushChannel. */ int flushcode; int stickyError; if (chan == NULL) { return TCL_OK; } /* * Perform special handling for standard channels being closed. If the * refCount is now 1 it means that the last reference to the standard * channel is being explicitly closed, so bump the refCount down * artificially to 0. This will ensure that the channel is actually * closed, below. Also set the static pointer to NULL for the channel. */ CheckForStdChannelsBeingClosed(chan); /* * This operation should occur at the top of a channel stack. */ chanPtr = (Channel *) chan; statePtr = chanPtr->state; chanPtr = statePtr->topChanPtr; if (statePtr->refCount > 0) { Tcl_Panic("called Tcl_Close on channel with refCount > 0"); } if (GotFlag(statePtr, CHANNEL_INCLOSE)) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "illegal recursive call to close through close-handler" " of channel", -1)); } return TCL_ERROR; } SetFlag(statePtr, CHANNEL_INCLOSE); /* * When the channel has an escape sequence driven encoding such as * iso2022, the terminated escape sequence must write to the buffer. */ stickyError = 0; if (GotFlag(statePtr, TCL_WRITABLE) && (statePtr->encoding != NULL) && !(statePtr->outputEncodingFlags & TCL_ENCODING_START)) { int code = CheckChannelErrors(statePtr, TCL_WRITABLE); if (code == 0) { statePtr->outputEncodingFlags |= TCL_ENCODING_END; code = WriteChars(chanPtr, "", 0); statePtr->outputEncodingFlags &= ~TCL_ENCODING_END; statePtr->outputEncodingFlags |= TCL_ENCODING_START; } if (code < 0) { stickyError = Tcl_GetErrno(); } /* * TIP #219, Tcl Channel Reflection API. * Move an error message found in the channel bypass into the * interpreter bypass. Just clear it if there is no interpreter. */ if (statePtr->chanMsg != NULL) { if (interp != NULL) { Tcl_SetChannelErrorInterp(interp, statePtr->chanMsg); } TclDecrRefCount(statePtr->chanMsg); statePtr->chanMsg = NULL; } } Tcl_ClearChannelHandlers(chan); /* * Invoke the registered close callbacks and delete their records. */ while (statePtr->closeCbPtr != NULL) { cbPtr = statePtr->closeCbPtr; statePtr->closeCbPtr = cbPtr->nextPtr; cbPtr->proc(cbPtr->clientData); ckfree(cbPtr); } ResetFlag(statePtr, CHANNEL_INCLOSE); /* * If this channel supports it, close the read side, since we don't need * it anymore and this will help avoid deadlocks on some channel types. */ if (chanPtr->typePtr->closeProc == TCL_CLOSE2PROC) { result = chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, TCL_CLOSE_READ); } else { result = 0; } /* * The call to FlushChannel will flush any queued output and invoke the * close function of the channel driver, or it will set up the channel to * be flushed and closed asynchronously. */ SetFlag(statePtr, CHANNEL_CLOSED); flushcode = FlushChannel(interp, chanPtr, 0); /* * TIP #219. * Capture error messages put by the driver into the bypass area and put * them into the regular interpreter result. * * Notes: Due to the assertion of CHANNEL_CLOSED in the flags * FlushChannel() has called CloseChannel() and thus freed all the channel * structures. We must not try to access "chan" anymore, hence the NULL * argument in the call below. The only place which may still contain a * message is the interpreter itself, and "CloseChannel" made sure to lift * any channel message it generated into it. */ if (TclChanCaughtErrorBypass(interp, NULL)) { result = EINVAL; } if (stickyError != 0) { Tcl_SetErrno(stickyError); if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_PosixError(interp), -1)); } return TCL_ERROR; } /* * Bug 97069ea11a: set error message if a flush code is set and no error * message set up to now. */ if (flushcode != 0 && interp != NULL && 0 == Tcl_GetCharLength(Tcl_GetObjResult(interp)) ) { Tcl_SetErrno(flushcode); Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_PosixError(interp), -1)); } if ((flushcode != 0) || (result != 0)) { return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_CloseEx -- * * Closes one side of a channel, read or write. * * Results: * A standard Tcl result. * * Side effects: * Closes one direction of the channel. * * NOTE: * Tcl_CloseEx closes the specified direction of the channel as far as * the user is concerned. The channel keeps existing however. You cannot * calls this function to close the last possible direction of the * channel. Use Tcl_Close for that. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_CloseEx( Tcl_Interp *interp, /* Interpreter for errors. */ Tcl_Channel chan, /* The channel being closed. May still be used * by some interpreter. */ int flags) /* Flags telling us which side to close. */ { Channel *chanPtr; /* The real IO channel. */ ChannelState *statePtr; /* State of real IO channel. */ if (chan == NULL) { return TCL_OK; } /* TODO: assert flags validity ? */ chanPtr = (Channel *) chan; statePtr = chanPtr->state; /* * Does the channel support half-close anyway? Error if not. */ if (!chanPtr->typePtr->close2Proc) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "half-close of channels not supported by %ss", chanPtr->typePtr->typeName)); return TCL_ERROR; } /* * Is the channel unstacked ? If not we fail. */ if (chanPtr != statePtr->topChanPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "half-close not applicable to stack of transformations", -1)); return TCL_ERROR; } /* * Check direction against channel mode. It is an error if we try to close * a direction not supported by the channel (already closed, or never * opened for that direction). */ if (!(statePtr->flags & (TCL_READABLE | TCL_WRITABLE) & flags)) { const char *msg; if (flags & TCL_CLOSE_READ) { msg = "read"; } else { msg = "write"; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "Half-close of %s-side not possible, side not opened or" " already closed", msg)); return TCL_ERROR; } /* * A user may try to call half-close from within a channel close * handler. That won't do. */ if (statePtr->flags & CHANNEL_INCLOSE) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "illegal recursive call to close through close-handler" " of channel", -1)); } return TCL_ERROR; } if (flags & TCL_CLOSE_READ) { /* * Call the finalization code directly. There are no events to handle, * there cannot be for the read-side. */ return CloseChannelPart(interp, chanPtr, 0, flags); } else if (flags & TCL_CLOSE_WRITE) { Tcl_Preserve(statePtr); if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { /* * We don't want to re-enter CloseWrite(). */ if (!GotFlag(statePtr, CHANNEL_CLOSEDWRITE)) { if (CloseWrite(interp, chanPtr) != TCL_OK) { SetFlag(statePtr, CHANNEL_CLOSEDWRITE); Tcl_Release(statePtr); return TCL_ERROR; } } } SetFlag(statePtr, CHANNEL_CLOSEDWRITE); Tcl_Release(statePtr); } return TCL_OK; } /* *---------------------------------------------------------------------- * * CloseWrite -- * * Closes the write side a channel. * * Results: * A standard Tcl result. * * Side effects: * Closes the write side of the channel. * * NOTE: * CloseWrite removes the channel as far as the user is concerned. * However, the ooutput data structures may continue to exist for a while * longer if it has a background flush scheduled. The device itself is * eventually closed and the channel structures modified, in * CloseChannelPart, below. * *---------------------------------------------------------------------- */ static int CloseWrite( Tcl_Interp *interp, /* Interpreter for errors. */ Channel *chanPtr) /* The channel whose write side is being * closed. May still be used by some * interpreter */ { /* Notes: clear-channel-handlers - write side only ? or keep around, just * not called. */ /* No close cllbacks are run - channel is still open (read side) */ ChannelState *statePtr = chanPtr->state; /* State of real IO channel. */ int flushcode; int result = 0; /* * The call to FlushChannel will flush any queued output and invoke the * close function of the channel driver, or it will set up the channel to * be flushed and closed asynchronously. */ SetFlag(statePtr, CHANNEL_CLOSEDWRITE); flushcode = FlushChannel(interp, chanPtr, 0); /* * TIP #219. * Capture error messages put by the driver into the bypass area and put * them into the regular interpreter result. * * Notes: Due to the assertion of CHANNEL_CLOSEDWRITE in the flags * FlushChannel() has called CloseChannelPart(). While we can still access * "chan" (no structures were freed), the only place which may still * contain a message is the interpreter itself, and "CloseChannelPart" made * sure to lift any channel message it generated into it. Hence the NULL * argument in the call below. */ if (TclChanCaughtErrorBypass(interp, NULL)) { result = EINVAL; } if ((flushcode != 0) || (result != 0)) { return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * CloseChannelPart -- * * Utility procedure to close a channel partially and free associated * resources. If the channel was stacked it will never be run (The higher * level forbid this). If the channel was not stacked, then we will free * all the bits of the chosen side (read, or write) for the TOP channel. * * Results: * Error code from an unreported error or the driver close2 operation. * * Side effects: * May free memory, may change the value of errno. * *---------------------------------------------------------------------- */ static int CloseChannelPart( Tcl_Interp *interp, /* Interpreter for errors. */ Channel *chanPtr, /* The channel being closed. May still be used * by some interpreter. */ int errorCode, /* Status of operation so far. */ int flags) /* Flags telling us which side to close. */ { ChannelState *statePtr; /* State of real IO channel. */ int result; /* Of calling the close2proc. */ statePtr = chanPtr->state; if (flags & TCL_CLOSE_READ) { /* * No more input can be consumed so discard any leftover input. */ DiscardInputQueued(statePtr, 1); } else if (flags & TCL_CLOSE_WRITE) { /* * The caller guarantees that there are no more buffers queued for * output. */ if (statePtr->outQueueHead != NULL) { Tcl_Panic("ClosechanHalf, closed write-side of channel: " "queued output left"); } /* * If the EOF character is set in the channel, append that to the * output device. */ if ((statePtr->outEofChar != 0) && GotFlag(statePtr, TCL_WRITABLE)) { int dummy; char c = (char) statePtr->outEofChar; (void) ChanWrite(chanPtr, &c, 1, &dummy); } /* * TIP #219, Tcl Channel Reflection API. * Move a leftover error message in the channel bypass into the * interpreter bypass. Just clear it if there is no interpreter. */ if (statePtr->chanMsg != NULL) { if (interp != NULL) { Tcl_SetChannelErrorInterp(interp, statePtr->chanMsg); } TclDecrRefCount(statePtr->chanMsg); statePtr->chanMsg = NULL; } } /* * Finally do what is asked of us. Close and free the channel driver state * for the chosen side of the channel. This may leave a TIP #219 error * message in the interp. */ result = ChanCloseHalf(chanPtr, interp, flags); /* * If we are being called synchronously, report either any latent error on * the channel or the current error. */ if (statePtr->unreportedError != 0) { errorCode = statePtr->unreportedError; /* * TIP #219, Tcl Channel Reflection API. * Move an error message found in the unreported area into the regular * bypass (interp). This kills any message in the channel bypass area. */ if (statePtr->chanMsg != NULL) { TclDecrRefCount(statePtr->chanMsg); statePtr->chanMsg = NULL; } if (interp) { Tcl_SetChannelErrorInterp(interp, statePtr->unreportedMsg); } } if (errorCode == 0) { errorCode = result; if (errorCode != 0) { Tcl_SetErrno(errorCode); } } /* * TIP #219. * Capture error messages put by the driver into the bypass area and put * them into the regular interpreter result. See also the bottom of * CloseWrite(). */ if (TclChanCaughtErrorBypass(interp, (Tcl_Channel) chanPtr)) { result = EINVAL; } if (result != 0) { return TCL_ERROR; } /* * Remove the closed side from the channel mode/flags. */ ResetFlag(statePtr, flags & (TCL_READABLE | TCL_WRITABLE)); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_ClearChannelHandlers -- * * Removes all channel handlers and event scripts from the channel, * cancels all background copies involving the channel and any interest * in events. * * Results: * None. * * Side effects: * See above. Deallocates memory. * *---------------------------------------------------------------------- */ void Tcl_ClearChannelHandlers( Tcl_Channel channel) { ChannelHandler *chPtr, *chNext; /* Iterate over channel handlers. */ EventScriptRecord *ePtr, *eNextPtr; /* Iterate over eventscript records. */ Channel *chanPtr; /* The real IO channel. */ ChannelState *statePtr; /* State of real IO channel. */ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); NextChannelHandler *nhPtr; /* * This operation should occur at the top of a channel stack. */ chanPtr = (Channel *) channel; statePtr = chanPtr->state; chanPtr = statePtr->topChanPtr; /* * Cancel any outstanding timer. */ Tcl_DeleteTimerHandler(statePtr->timer); /* * Remove any references to channel handlers for this channel that may be * about to be invoked. */ for (nhPtr = tsdPtr->nestedHandlerPtr; nhPtr != NULL; nhPtr = nhPtr->nestedHandlerPtr) { if (nhPtr->nextHandlerPtr && (nhPtr->nextHandlerPtr->chanPtr == chanPtr)) { nhPtr->nextHandlerPtr = NULL; } } /* * Remove all the channel handler records attached to the channel itself. */ for (chPtr = statePtr->chPtr; chPtr != NULL; chPtr = chNext) { chNext = chPtr->nextPtr; ckfree(chPtr); } statePtr->chPtr = NULL; /* * Cancel any pending copy operation. */ StopCopy(statePtr->csPtrR); StopCopy(statePtr->csPtrW); /* * Must set the interest mask now to 0, otherwise infinite loops * will occur if Tcl_DoOneEvent is called before the channel is * finally deleted in FlushChannel. This can happen if the channel * has a background flush active. */ statePtr->interestMask = 0; /* * Remove any EventScript records for this channel. */ for (ePtr = statePtr->scriptRecordPtr; ePtr != NULL; ePtr = eNextPtr) { eNextPtr = ePtr->nextPtr; TclDecrRefCount(ePtr->scriptPtr); ckfree(ePtr); } statePtr->scriptRecordPtr = NULL; } /* *---------------------------------------------------------------------- * * Tcl_Write -- * * Puts a sequence of bytes into an output buffer, may queue the buffer * for output if it gets full, and also remembers whether the current * buffer is ready e.g. if it contains a newline and we are in line * buffering mode. Compensates stacking, i.e. will redirect the data from * the specified channel to the topmost channel in a stack. * * No encoding conversions are applied to the bytes being read. * * Results: * The number of bytes written or -1 in case of error. If -1, * Tcl_GetErrno will return the error code. * * Side effects: * May buffer up output and may cause output to be produced on the * channel. * *---------------------------------------------------------------------- */ int Tcl_Write( Tcl_Channel chan, /* The channel to buffer output for. */ const char *src, /* Data to queue in output buffer. */ int srcLen) /* Length of data in bytes, or < 0 for * strlen(). */ { /* * Always use the topmost channel of the stack */ Channel *chanPtr; ChannelState *statePtr; /* State info for channel */ statePtr = ((Channel *) chan)->state; chanPtr = statePtr->topChanPtr; if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { return -1; } if (srcLen < 0) { srcLen = strlen(src); } if (WriteBytes(chanPtr, src, srcLen) < 0) { return -1; } return srcLen; } /* *---------------------------------------------------------------------- * * Tcl_WriteRaw -- * * Puts a sequence of bytes into an output buffer, may queue the buffer * for output if it gets full, and also remembers whether the current * buffer is ready e.g. if it contains a newline and we are in line * buffering mode. Writes directly to the driver of the channel, does not * compensate for stacking. * * No encoding conversions are applied to the bytes being read. * * Results: * The number of bytes written or -1 in case of error. If -1, * Tcl_GetErrno will return the error code. * * Side effects: * May buffer up output and may cause output to be produced on the * channel. * *---------------------------------------------------------------------- */ int Tcl_WriteRaw( Tcl_Channel chan, /* The channel to buffer output for. */ const char *src, /* Data to queue in output buffer. */ int srcLen) /* Length of data in bytes, or < 0 for * strlen(). */ { Channel *chanPtr = ((Channel *) chan); ChannelState *statePtr = chanPtr->state; /* State info for channel */ int errorCode, written; if (CheckChannelErrors(statePtr, TCL_WRITABLE | CHANNEL_RAW_MODE) != 0) { return -1; } if (srcLen < 0) { srcLen = strlen(src); } /* * Go immediately to the driver, do all the error handling by ourselves. * The code was stolen from 'FlushChannel'. */ written = ChanWrite(chanPtr, src, srcLen, &errorCode); if (written < 0) { Tcl_SetErrno(errorCode); } return written; } /* *--------------------------------------------------------------------------- * * Tcl_WriteChars -- * * Takes a sequence of UTF-8 characters and converts them for output * using the channel's current encoding, may queue the buffer for output * if it gets full, and also remembers whether the current buffer is * ready e.g. if it contains a newline and we are in line buffering * mode. Compensates stacking, i.e. will redirect the data from the * specified channel to the topmost channel in a stack. * * Results: * The number of bytes written or -1 in case of error. If -1, * Tcl_GetErrno will return the error code. * * Side effects: * May buffer up output and may cause output to be produced on the * channel. * *---------------------------------------------------------------------- */ int Tcl_WriteChars( Tcl_Channel chan, /* The channel to buffer output for. */ const char *src, /* UTF-8 characters to queue in output * buffer. */ int len) /* Length of string in bytes, or < 0 for * strlen(). */ { Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ int result; Tcl_Obj *objPtr; if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { return -1; } chanPtr = statePtr->topChanPtr; if (len < 0) { len = strlen(src); } if (statePtr->encoding) { return WriteChars(chanPtr, src, len); } /* * Inefficient way to convert UTF-8 to byte-array, but the code * parallels the way it is done for objects. Special case for 1-byte * (used by eg [puts] for the \n) could be extended to more efficient * translation of the src string. */ if ((len == 1) && (UCHAR(*src) < 0xC0)) { return WriteBytes(chanPtr, src, len); } objPtr = Tcl_NewStringObj(src, len); src = (char *) Tcl_GetByteArrayFromObj(objPtr, &len); result = WriteBytes(chanPtr, src, len); TclDecrRefCount(objPtr); return result; } /* *--------------------------------------------------------------------------- * * Tcl_WriteObj -- * * Takes the Tcl object and queues its contents for output. If the * encoding of the channel is NULL, takes the byte-array representation * of the object and queues those bytes for output. Otherwise, takes the * characters in the UTF-8 (string) representation of the object and * converts them for output using the channel's current encoding. May * flush internal buffers to output if one becomes full or is ready for * some other reason, e.g. if it contains a newline and the channel is in * line buffering mode. * * Results: * The number of bytes written or -1 in case of error. If -1, * Tcl_GetErrno() will return the error code. * * Side effects: * May buffer up output and may cause output to be produced on the * channel. * *---------------------------------------------------------------------- */ int Tcl_WriteObj( Tcl_Channel chan, /* The channel to buffer output for. */ Tcl_Obj *objPtr) /* The object to write. */ { /* * Always use the topmost channel of the stack */ Channel *chanPtr; ChannelState *statePtr; /* State info for channel */ const char *src; int srcLen; statePtr = ((Channel *) chan)->state; chanPtr = statePtr->topChanPtr; if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { return -1; } if (statePtr->encoding == NULL) { src = (char *) Tcl_GetByteArrayFromObj(objPtr, &srcLen); return WriteBytes(chanPtr, src, srcLen); } else { src = TclGetStringFromObj(objPtr, &srcLen); return WriteChars(chanPtr, src, srcLen); } } static void WillWrite( Channel *chanPtr) { int inputBuffered; if ((chanPtr->typePtr->seekProc != NULL) && ((inputBuffered = Tcl_InputBuffered((Tcl_Channel) chanPtr)) > 0)){ int ignore; DiscardInputQueued(chanPtr->state, 0); ChanSeek(chanPtr, -inputBuffered, SEEK_CUR, &ignore); } } static int WillRead( Channel *chanPtr) { if (chanPtr->typePtr == NULL) { /* Prevent read attempts on a closed channel */ DiscardInputQueued(chanPtr->state, 0); Tcl_SetErrno(EINVAL); return -1; } if ((chanPtr->typePtr->seekProc != NULL) && (Tcl_OutputBuffered((Tcl_Channel) chanPtr) > 0)) { /* * CAVEAT - The assumption here is that FlushChannel() will * push out the bytes of any writes that are in progress. * Since this is a seekable channel, we assume it is not one * that can block and force bg flushing. Channels we know that * can do that -- sockets, pipes -- are not seekable. If the * assumption is wrong, more drastic measures may be required here * like temporarily setting the channel into blocking mode. */ if (FlushChannel(NULL, chanPtr, 0) != 0) { return -1; } } return 0; } /* *---------------------------------------------------------------------- * * Write -- * * Convert srcLen bytes starting at src according to encoding and write * produced bytes into an output buffer, may queue the buffer for output * if it gets full, and also remembers whether the current buffer is * ready e.g. if it contains a newline and we are in line buffering mode. * * Results: * The number of bytes written or -1 in case of error. If -1, * Tcl_GetErrno will return the error code. * * Side effects: * May buffer up output and may cause output to be produced on the * channel. * *---------------------------------------------------------------------- */ static int Write( Channel *chanPtr, /* The channel to buffer output for. */ const char *src, /* UTF-8 string to write. */ int srcLen, /* Length of UTF-8 string in bytes. */ Tcl_Encoding encoding) { ChannelState *statePtr = chanPtr->state; /* State info for channel */ char *nextNewLine = NULL; int endEncoding, saved = 0, total = 0, flushed = 0, needNlFlush = 0; if (srcLen) { WillWrite(chanPtr); } /* * Write the terminated escape sequence even if srcLen is 0. */ endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0); if (GotFlag(statePtr, CHANNEL_LINEBUFFERED) || (statePtr->outputTranslation != TCL_TRANSLATE_LF)) { nextNewLine = memchr(src, '\n', srcLen); } while (srcLen + saved + endEncoding > 0) { ChannelBuffer *bufPtr; char *dst, safe[BUFFER_PADDING]; int result, srcRead, dstLen, dstWrote, srcLimit = srcLen; if (nextNewLine) { srcLimit = nextNewLine - src; } /* Get space to write into */ bufPtr = statePtr->curOutPtr; if (bufPtr == NULL) { bufPtr = AllocChannelBuffer(statePtr->bufSize); statePtr->curOutPtr = bufPtr; } if (saved) { /* * Here's some translated bytes left over from the last buffer * that we need to stick at the beginning of this buffer. */ memcpy(InsertPoint(bufPtr), safe, (size_t) saved); bufPtr->nextAdded += saved; saved = 0; } PreserveChannelBuffer(bufPtr); dst = InsertPoint(bufPtr); dstLen = SpaceLeft(bufPtr); result = Tcl_UtfToExternal(NULL, encoding, src, srcLimit, statePtr->outputEncodingFlags, &statePtr->outputEncodingState, dst, dstLen + BUFFER_PADDING, &srcRead, &dstWrote, NULL); /* See chan-io-1.[89]. Tcl Bug 506297. */ statePtr->outputEncodingFlags &= ~TCL_ENCODING_START; if ((result != TCL_OK) && (srcRead + dstWrote == 0)) { /* We're reading from invalid/incomplete UTF-8 */ ReleaseChannelBuffer(bufPtr); if (total == 0) { Tcl_SetErrno(EINVAL); return -1; } break; } bufPtr->nextAdded += dstWrote; src += srcRead; srcLen -= srcRead; total += dstWrote; dst += dstWrote; dstLen -= dstWrote; if (src == nextNewLine && dstLen > 0) { static char crln[3] = "\r\n"; char *nl = NULL; int nlLen = 0; switch (statePtr->outputTranslation) { case TCL_TRANSLATE_LF: nl = crln + 1; nlLen = 1; break; case TCL_TRANSLATE_CR: nl = crln; nlLen = 1; break; case TCL_TRANSLATE_CRLF: nl = crln; nlLen = 2; break; default: Tcl_Panic("unknown output translation requested"); break; } result |= Tcl_UtfToExternal(NULL, encoding, nl, nlLen, statePtr->outputEncodingFlags, &statePtr->outputEncodingState, dst, dstLen + BUFFER_PADDING, &srcRead, &dstWrote, NULL); assert (srcRead == nlLen); bufPtr->nextAdded += dstWrote; src++; srcLen--; total += dstWrote; dst += dstWrote; dstLen -= dstWrote; nextNewLine = memchr(src, '\n', srcLen); needNlFlush = 1; } if (IsBufferOverflowing(bufPtr)) { /* * When translating from UTF-8 to external encoding, we * allowed the translation to produce a character that crossed * the end of the output buffer, so that we would get a * completely full buffer before flushing it. The extra bytes * will be moved to the beginning of the next buffer. */ saved = -SpaceLeft(bufPtr); memcpy(safe, dst + dstLen, (size_t) saved); bufPtr->nextAdded = bufPtr->bufLength; } if ((srcLen + saved == 0) && (result == TCL_OK)) { endEncoding = 0; } if (IsBufferFull(bufPtr)) { if (FlushChannel(NULL, chanPtr, 0) != 0) { ReleaseChannelBuffer(bufPtr); return -1; } flushed += statePtr->bufSize; /* * We just flushed. So if we have needNlFlush set to record * that we need to flush because theres a (translated) newline * in the buffer, that's likely not true any more. But there * is a tricky exception. If we have saved bytes that did not * really get flushed and those bytes came from a translation * of a newline as the last thing taken from the src array, * then needNlFlush needs to remain set to flag that the * next buffer still needs a newline flush. */ if (needNlFlush && (saved == 0 || src[-1] != '\n')) { needNlFlush = 0; } } ReleaseChannelBuffer(bufPtr); } if ((flushed < total) && (GotFlag(statePtr, CHANNEL_UNBUFFERED) || (needNlFlush && GotFlag(statePtr, CHANNEL_LINEBUFFERED)))) { if (FlushChannel(NULL, chanPtr, 0) != 0) { return -1; } } return total; } /* *--------------------------------------------------------------------------- * * Tcl_Gets -- * * Reads a complete line of input from the channel into a Tcl_DString. * * Results: * Length of line read (in characters) or -1 if error, EOF, or blocked. * If -1, use Tcl_GetErrno() to retrieve the POSIX error code for the * error or condition that occurred. * * Side effects: * May flush output on the channel. May cause input to be consumed from * the channel. * *--------------------------------------------------------------------------- */ int Tcl_Gets( Tcl_Channel chan, /* Channel from which to read. */ Tcl_DString *lineRead) /* The line read will be appended to this * DString as UTF-8 characters. The caller * must have initialized it and is responsible * for managing the storage. */ { Tcl_Obj *objPtr; int charsStored; TclNewObj(objPtr); charsStored = Tcl_GetsObj(chan, objPtr); if (charsStored > 0) { TclDStringAppendObj(lineRead, objPtr); } TclDecrRefCount(objPtr); return charsStored; } /* *--------------------------------------------------------------------------- * * Tcl_GetsObj -- * * Accumulate input from the input channel until end-of-line or * end-of-file has been seen. Bytes read from the input channel are * converted to UTF-8 using the encoding specified by the channel. * * Results: * Number of characters accumulated in the object or -1 if error, * blocked, or EOF. If -1, use Tcl_GetErrno() to retrieve the POSIX error * code for the error or condition that occurred. * * Side effects: * Consumes input from the channel. * * On reading EOF, leave channel pointing at EOF char. On reading EOL, * leave channel pointing after EOL, but don't return EOL in dst buffer. * *--------------------------------------------------------------------------- */ int Tcl_GetsObj( Tcl_Channel chan, /* Channel from which to read. */ Tcl_Obj *objPtr) /* The line read will be appended to this * object as UTF-8 characters. */ { GetsState gs; Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelBuffer *bufPtr; int inEofChar, skip, copiedTotal, oldLength, oldFlags, oldRemoved; Tcl_Encoding encoding; char *dst, *dstEnd, *eol, *eof; Tcl_EncodingState oldState; if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) { return -1; } /* * If we're sitting ready to read the eofchar, there's no need to * do it. */ if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) { SetFlag(statePtr, CHANNEL_EOF); assert( statePtr->inputEncodingFlags & TCL_ENCODING_END ); assert( !GotFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR) ); /* TODO: Do we need this? */ UpdateInterest(chanPtr); return -1; } /* * A binary version of Tcl_GetsObj. This could also handle encodings that * are ascii-7 pure (iso8859, utf-8, ...) with a final encoding conversion * done on objPtr. */ if ((statePtr->encoding == NULL) && ((statePtr->inputTranslation == TCL_TRANSLATE_LF) || (statePtr->inputTranslation == TCL_TRANSLATE_CR))) { return TclGetsObjBinary(chan, objPtr); } /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; TclChannelPreserve((Tcl_Channel)chanPtr); bufPtr = statePtr->inQueueHead; encoding = statePtr->encoding; /* * Preserved so we can restore the channel's state in case we don't find a * newline in the available input. */ TclGetStringFromObj(objPtr, &oldLength); oldFlags = statePtr->inputEncodingFlags; oldState = statePtr->inputEncodingState; oldRemoved = BUFFER_PADDING; if (bufPtr != NULL) { oldRemoved = bufPtr->nextRemoved; } /* * If there is no encoding, use "iso8859-1" -- Tcl_GetsObj() doesn't * produce ByteArray objects. */ if (encoding == NULL) { encoding = GetBinaryEncoding(); } /* * Object used by FilterInputBytes to keep track of how much data has been * consumed from the channel buffers. */ gs.objPtr = objPtr; gs.dstPtr = &dst; gs.encoding = encoding; gs.bufPtr = bufPtr; gs.state = oldState; gs.rawRead = 0; gs.bytesWrote = 0; gs.charsWrote = 0; gs.totalChars = 0; dst = objPtr->bytes + oldLength; dstEnd = dst; skip = 0; eof = NULL; inEofChar = statePtr->inEofChar; ResetFlag(statePtr, CHANNEL_BLOCKED); while (1) { if (dst >= dstEnd) { if (FilterInputBytes(chanPtr, &gs) != 0) { goto restore; } dstEnd = dst + gs.bytesWrote; } /* * Remember if EOF char is seen, then look for EOL anyhow, because the * EOL might be before the EOF char. */ if (inEofChar != '\0') { for (eol = dst; eol < dstEnd; eol++) { if (*eol == inEofChar) { dstEnd = eol; eof = eol; break; } } } /* * On EOL, leave current file position pointing after the EOL, but * don't store the EOL in the output string. */ switch (statePtr->inputTranslation) { case TCL_TRANSLATE_LF: for (eol = dst; eol < dstEnd; eol++) { if (*eol == '\n') { skip = 1; goto gotEOL; } } break; case TCL_TRANSLATE_CR: for (eol = dst; eol < dstEnd; eol++) { if (*eol == '\r') { skip = 1; goto gotEOL; } } break; case TCL_TRANSLATE_CRLF: for (eol = dst; eol < dstEnd; eol++) { if (*eol == '\r') { eol++; /* * If a CR is at the end of the buffer, then check for a * LF at the begining of the next buffer, unless EOF char * was found already. */ if (eol >= dstEnd) { int offset; if (eol != eof) { offset = eol - objPtr->bytes; dst = dstEnd; if (FilterInputBytes(chanPtr, &gs) != 0) { goto restore; } dstEnd = dst + gs.bytesWrote; eol = objPtr->bytes + offset; } if (eol >= dstEnd) { skip = 0; goto gotEOL; } } if (*eol == '\n') { eol--; skip = 2; goto gotEOL; } } } break; case TCL_TRANSLATE_AUTO: eol = dst; skip = 1; if (GotFlag(statePtr, INPUT_SAW_CR)) { ResetFlag(statePtr, INPUT_SAW_CR); if ((eol < dstEnd) && (*eol == '\n')) { /* * Skip the raw bytes that make up the '\n'. */ char tmp[TCL_UTF_MAX]; int rawRead; bufPtr = gs.bufPtr; Tcl_ExternalToUtf(NULL, gs.encoding, RemovePoint(bufPtr), gs.rawRead, statePtr->inputEncodingFlags | TCL_ENCODING_NO_TERMINATE, &gs.state, tmp, TCL_UTF_MAX, &rawRead, NULL, NULL); bufPtr->nextRemoved += rawRead; gs.rawRead -= rawRead; gs.bytesWrote--; gs.charsWrote--; memmove(dst, dst + 1, (size_t) (dstEnd - dst)); dstEnd--; } } for (eol = dst; eol < dstEnd; eol++) { if (*eol == '\r') { eol++; if (eol == dstEnd) { /* * If buffer ended on \r, peek ahead to see if a \n is * available, unless EOF char was found already. */ if (eol != eof) { int offset; offset = eol - objPtr->bytes; dst = dstEnd; PeekAhead(chanPtr, &dstEnd, &gs); eol = objPtr->bytes + offset; } if (eol >= dstEnd) { eol--; SetFlag(statePtr, INPUT_SAW_CR); goto gotEOL; } } if (*eol == '\n') { skip++; } eol--; goto gotEOL; } else if (*eol == '\n') { goto gotEOL; } } } if (eof != NULL) { /* * EOF character was seen. On EOF, leave current file position * pointing at the EOF character, but don't store the EOF * character in the output string. */ dstEnd = eof; SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF); statePtr->inputEncodingFlags |= TCL_ENCODING_END; ResetFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR); } if (GotFlag(statePtr, CHANNEL_EOF)) { skip = 0; eol = dstEnd; if (eol == objPtr->bytes + oldLength) { /* * If we didn't append any bytes before encountering EOF, * caller needs to see -1. */ Tcl_SetObjLength(objPtr, oldLength); CommonGetsCleanup(chanPtr); copiedTotal = -1; ResetFlag(statePtr, CHANNEL_BLOCKED); goto done; } goto gotEOL; } dst = dstEnd; } /* * Found EOL or EOF, but the output buffer may now contain too many UTF-8 * characters. We need to know how many raw bytes correspond to the number * of UTF-8 characters we want, plus how many raw bytes correspond to the * character(s) making up EOL (if any), so we can remove the correct * number of bytes from the channel buffer. */ gotEOL: /* * Regenerate the top channel, in case it was changed due to * self-modifying reflected transforms. */ if (chanPtr != statePtr->topChanPtr) { TclChannelRelease((Tcl_Channel)chanPtr); chanPtr = statePtr->topChanPtr; TclChannelPreserve((Tcl_Channel)chanPtr); } bufPtr = gs.bufPtr; if (bufPtr == NULL) { Tcl_Panic("Tcl_GetsObj: gotEOL reached with bufPtr==NULL"); } statePtr->inputEncodingState = gs.state; Tcl_ExternalToUtf(NULL, gs.encoding, RemovePoint(bufPtr), gs.rawRead, statePtr->inputEncodingFlags | TCL_ENCODING_NO_TERMINATE, &statePtr->inputEncodingState, dst, eol - dst + skip + TCL_UTF_MAX - 1, &gs.rawRead, NULL, &gs.charsWrote); bufPtr->nextRemoved += gs.rawRead; /* * Recycle all the emptied buffers. */ Tcl_SetObjLength(objPtr, eol - objPtr->bytes); CommonGetsCleanup(chanPtr); ResetFlag(statePtr, CHANNEL_BLOCKED); copiedTotal = gs.totalChars + gs.charsWrote - skip; goto done; /* * Couldn't get a complete line. This only happens if we get a error * reading from the channel or we are non-blocking and there wasn't an EOL * or EOF in the data available. */ restore: /* * Regenerate the top channel, in case it was changed due to * self-modifying reflected transforms. */ if (chanPtr != statePtr->topChanPtr) { TclChannelRelease((Tcl_Channel)chanPtr); chanPtr = statePtr->topChanPtr; TclChannelPreserve((Tcl_Channel)chanPtr); } bufPtr = statePtr->inQueueHead; if (bufPtr != NULL) { bufPtr->nextRemoved = oldRemoved; bufPtr = bufPtr->nextPtr; } for ( ; bufPtr != NULL; bufPtr = bufPtr->nextPtr) { bufPtr->nextRemoved = BUFFER_PADDING; } CommonGetsCleanup(chanPtr); statePtr->inputEncodingState = oldState; statePtr->inputEncodingFlags = oldFlags; Tcl_SetObjLength(objPtr, oldLength); /* * We didn't get a complete line so we need to indicate to UpdateInterest * that the gets blocked. It will wait for more data instead of firing a * timer, avoiding a busy wait. This is where we are assuming that the * next operation is a gets. No more file events will be delivered on this * channel until new data arrives or some operation is performed on the * channel (e.g. gets, read, fconfigure) that changes the blocking state. * Note that this means a file event will not be delivered even though a * read would be able to consume the buffered data. */ SetFlag(statePtr, CHANNEL_NEED_MORE_DATA); copiedTotal = -1; /* * Update the notifier state so we don't block while there is still data * in the buffers. */ done: assert(!GotFlag(statePtr, CHANNEL_EOF) || GotFlag(statePtr, CHANNEL_STICKY_EOF) || Tcl_InputBuffered((Tcl_Channel)chanPtr) == 0); assert( !(GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED) == (CHANNEL_EOF|CHANNEL_BLOCKED)) ); /* * Regenerate the top channel, in case it was changed due to * self-modifying reflected transforms. */ if (chanPtr != statePtr->topChanPtr) { TclChannelRelease((Tcl_Channel)chanPtr); chanPtr = statePtr->topChanPtr; TclChannelPreserve((Tcl_Channel)chanPtr); } UpdateInterest(chanPtr); TclChannelRelease((Tcl_Channel)chanPtr); return copiedTotal; } /* *--------------------------------------------------------------------------- * * TclGetsObjBinary -- * * A variation of Tcl_GetsObj that works directly on the buffers until * end-of-line or end-of-file has been seen. Bytes read from the input * channel return as a ByteArray obj. * * WARNING! The notion of "binary" used here is different from * notions of "binary" used in other places. In particular, this * "binary" routine may be called when an -eofchar is set on the * channel. * * Results: * Number of characters accumulated in the object or -1 if error, * blocked, or EOF. If -1, use Tcl_GetErrno() to retrieve the POSIX error * code for the error or condition that occurred. * * Side effects: * Consumes input from the channel. * * On reading EOF, leave channel pointing at EOF char. On reading EOL, * leave channel pointing after EOL, but don't return EOL in dst buffer. * *--------------------------------------------------------------------------- */ static int TclGetsObjBinary( Tcl_Channel chan, /* Channel from which to read. */ Tcl_Obj *objPtr) /* The line read will be appended to this * object as UTF-8 characters. */ { Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelBuffer *bufPtr; int inEofChar, skip, copiedTotal, oldLength, oldFlags, oldRemoved; int rawLen, byteLen, eolChar; unsigned char *dst, *dstEnd, *eol, *eof, *byteArray; /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; TclChannelPreserve((Tcl_Channel)chanPtr); bufPtr = statePtr->inQueueHead; /* * Preserved so we can restore the channel's state in case we don't find a * newline in the available input. */ byteArray = Tcl_GetByteArrayFromObj(objPtr, &byteLen); oldFlags = statePtr->inputEncodingFlags; oldRemoved = BUFFER_PADDING; oldLength = byteLen; if (bufPtr != NULL) { oldRemoved = bufPtr->nextRemoved; } rawLen = 0; skip = 0; eof = NULL; inEofChar = statePtr->inEofChar; /* * Only handle TCL_TRANSLATE_LF and TCL_TRANSLATE_CR. */ eolChar = (statePtr->inputTranslation == TCL_TRANSLATE_LF) ? '\n' : '\r'; ResetFlag(statePtr, CHANNEL_BLOCKED); while (1) { /* * Subtract the number of bytes that were removed from channel * buffer during last call. */ if (bufPtr != NULL) { bufPtr->nextRemoved += rawLen; if (!IsBufferReady(bufPtr)) { bufPtr = bufPtr->nextPtr; } } if ((bufPtr == NULL) || (bufPtr->nextAdded == BUFFER_PADDING)) { /* * All channel buffers were exhausted and the caller still * hasn't seen EOL. Need to read more bytes from the channel * device. Side effect is to allocate another channel buffer. */ if (GetInput(chanPtr) != 0) { goto restore; } bufPtr = statePtr->inQueueTail; if (bufPtr == NULL) { goto restore; } } else { /* * Incoming CHANNEL_STICKY_EOF is filtered out on entry. * A new CHANNEL_STICKY_EOF set in this routine leads to * return before coming back here. When we are not dealing * with CHANNEL_STICKY_EOF, a CHANNEL_EOF implies an * empty buffer. Here the buffer is non-empty so we know * we're a non-EOF */ assert ( !GotFlag(statePtr, CHANNEL_STICKY_EOF) ); assert ( !GotFlag(statePtr, CHANNEL_EOF) ); } dst = (unsigned char *) RemovePoint(bufPtr); dstEnd = dst + BytesLeft(bufPtr); /* * Remember if EOF char is seen, then look for EOL anyhow, because the * EOL might be before the EOF char. * XXX - in the binary case, consider coincident search for eol/eof. */ if (inEofChar != '\0') { for (eol = dst; eol < dstEnd; eol++) { if (*eol == inEofChar) { dstEnd = eol; eof = eol; break; } } } /* * On EOL, leave current file position pointing after the EOL, but * don't store the EOL in the output string. */ for (eol = dst; eol < dstEnd; eol++) { if (*eol == eolChar) { skip = 1; goto gotEOL; } } if (eof != NULL) { /* * EOF character was seen. On EOF, leave current file position * pointing at the EOF character, but don't store the EOF * character in the output string. */ SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF); statePtr->inputEncodingFlags |= TCL_ENCODING_END; ResetFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR); } if (GotFlag(statePtr, CHANNEL_EOF)) { skip = 0; eol = dstEnd; if ((dst == dstEnd) && (byteLen == oldLength)) { /* * If we didn't append any bytes before encountering EOF, * caller needs to see -1. */ byteArray = Tcl_SetByteArrayLength(objPtr, oldLength); CommonGetsCleanup(chanPtr); copiedTotal = -1; ResetFlag(statePtr, CHANNEL_BLOCKED); goto done; } goto gotEOL; } if (GotFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_NONBLOCKING) == (CHANNEL_BLOCKED|CHANNEL_NONBLOCKING)) { goto restore; } /* * Copy bytes from the channel buffer to the ByteArray. * This may realloc space, so keep track of result. */ rawLen = dstEnd - dst; byteArray = Tcl_SetByteArrayLength(objPtr, byteLen + rawLen); memcpy(byteArray + byteLen, dst, (size_t) rawLen); byteLen += rawLen; } /* * Found EOL or EOF, but the output buffer may now contain too many bytes. * We need to know how many bytes correspond to the number we want, so we * can remove the correct number of bytes from the channel buffer. */ gotEOL: if (bufPtr == NULL) { Tcl_Panic("TclGetsObjBinary: gotEOL reached with bufPtr==NULL"); } rawLen = eol - dst; byteArray = Tcl_SetByteArrayLength(objPtr, byteLen + rawLen); memcpy(byteArray + byteLen, dst, (size_t) rawLen); byteLen += rawLen; bufPtr->nextRemoved += rawLen + skip; /* * Convert the buffer if there was an encoding. * XXX - unimplemented. */ if (statePtr->encoding != NULL) { } /* * Recycle all the emptied buffers. */ CommonGetsCleanup(chanPtr); ResetFlag(statePtr, CHANNEL_BLOCKED); copiedTotal = byteLen; goto done; /* * Couldn't get a complete line. This only happens if we get a error * reading from the channel or we are non-blocking and there wasn't an EOL * or EOF in the data available. */ restore: bufPtr = statePtr->inQueueHead; if (bufPtr) { bufPtr->nextRemoved = oldRemoved; bufPtr = bufPtr->nextPtr; } for ( ; bufPtr != NULL; bufPtr = bufPtr->nextPtr) { bufPtr->nextRemoved = BUFFER_PADDING; } CommonGetsCleanup(chanPtr); statePtr->inputEncodingFlags = oldFlags; byteArray = Tcl_SetByteArrayLength(objPtr, oldLength); /* * We didn't get a complete line so we need to indicate to UpdateInterest * that the gets blocked. It will wait for more data instead of firing a * timer, avoiding a busy wait. This is where we are assuming that the * next operation is a gets. No more file events will be delivered on this * channel until new data arrives or some operation is performed on the * channel (e.g. gets, read, fconfigure) that changes the blocking state. * Note that this means a file event will not be delivered even though a * read would be able to consume the buffered data. */ SetFlag(statePtr, CHANNEL_NEED_MORE_DATA); copiedTotal = -1; /* * Update the notifier state so we don't block while there is still data * in the buffers. */ done: assert(!GotFlag(statePtr, CHANNEL_EOF) || GotFlag(statePtr, CHANNEL_STICKY_EOF) || Tcl_InputBuffered((Tcl_Channel)chanPtr) == 0); assert( !(GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED) == (CHANNEL_EOF|CHANNEL_BLOCKED)) ); UpdateInterest(chanPtr); TclChannelRelease((Tcl_Channel)chanPtr); return copiedTotal; } /* *--------------------------------------------------------------------------- * * FreeBinaryEncoding -- * * Frees any "iso8859-1" Tcl_Encoding created by [gets] on a binary * channel in a thread as part of that thread's finalization. * * Results: * None. * *--------------------------------------------------------------------------- */ static void FreeBinaryEncoding( ClientData dummy) /* Not used */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->binaryEncoding != NULL) { Tcl_FreeEncoding(tsdPtr->binaryEncoding); tsdPtr->binaryEncoding = NULL; } } static Tcl_Encoding GetBinaryEncoding() { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->binaryEncoding == NULL) { tsdPtr->binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1"); Tcl_CreateThreadExitHandler(FreeBinaryEncoding, NULL); } if (tsdPtr->binaryEncoding == NULL) { Tcl_Panic("binary encoding is not available"); } return tsdPtr->binaryEncoding; } /* *--------------------------------------------------------------------------- * * FilterInputBytes -- * * Helper function for Tcl_GetsObj. Produces UTF-8 characters from raw * bytes read from the channel. * * Consumes available bytes from channel buffers. When channel buffers * are exhausted, reads more bytes from channel device into a new channel * buffer. It is the caller's responsibility to free the channel buffers * that have been exhausted. * * Results: * The return value is -1 if there was an error reading from the channel, * 0 otherwise. * * Side effects: * Status object keeps track of how much data from channel buffers has * been consumed and where UTF-8 bytes should be stored. * *--------------------------------------------------------------------------- */ static int FilterInputBytes( Channel *chanPtr, /* Channel to read. */ GetsState *gsPtr) /* Current state of gets operation. */ { ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelBuffer *bufPtr; char *raw, *dst; int offset, toRead, dstNeeded, spaceLeft, result, rawLen; Tcl_Obj *objPtr; #define ENCODING_LINESIZE 20 /* Lower bound on how many bytes to convert at * a time. Since we don't know a priori how * many bytes of storage this many source * bytes will use, we actually need at least * ENCODING_LINESIZE * TCL_MAX_UTF bytes of * room. */ objPtr = gsPtr->objPtr; /* * Subtract the number of bytes that were removed from channel buffer * during last call. */ bufPtr = gsPtr->bufPtr; if (bufPtr != NULL) { bufPtr->nextRemoved += gsPtr->rawRead; if (!IsBufferReady(bufPtr)) { bufPtr = bufPtr->nextPtr; } } gsPtr->totalChars += gsPtr->charsWrote; if ((bufPtr == NULL) || (bufPtr->nextAdded == BUFFER_PADDING)) { /* * All channel buffers were exhausted and the caller still hasn't seen * EOL. Need to read more bytes from the channel device. Side effect * is to allocate another channel buffer. */ read: if (GotFlag(statePtr, CHANNEL_NONBLOCKING|CHANNEL_BLOCKED) == (CHANNEL_NONBLOCKING|CHANNEL_BLOCKED)) { gsPtr->charsWrote = 0; gsPtr->rawRead = 0; return -1; } if (GetInput(chanPtr) != 0) { gsPtr->charsWrote = 0; gsPtr->rawRead = 0; return -1; } bufPtr = statePtr->inQueueTail; gsPtr->bufPtr = bufPtr; if (bufPtr == NULL) { gsPtr->charsWrote = 0; gsPtr->rawRead = 0; return -1; } } else { /* * Incoming CHANNEL_STICKY_EOF is filtered out on entry. * A new CHANNEL_STICKY_EOF set in this routine leads to * return before coming back here. When we are not dealing * with CHANNEL_STICKY_EOF, a CHANNEL_EOF implies an * empty buffer. Here the buffer is non-empty so we know * we're a non-EOF */ assert ( !GotFlag(statePtr, CHANNEL_STICKY_EOF) ); assert ( !GotFlag(statePtr, CHANNEL_EOF) ); } /* * Convert some of the bytes from the channel buffer to UTF-8. Space in * objPtr's string rep is used to hold the UTF-8 characters. Grow the * string rep if we need more space. */ raw = RemovePoint(bufPtr); rawLen = BytesLeft(bufPtr); dst = *gsPtr->dstPtr; offset = dst - objPtr->bytes; toRead = ENCODING_LINESIZE; if (toRead > rawLen) { toRead = rawLen; } dstNeeded = toRead * TCL_UTF_MAX; spaceLeft = objPtr->length - offset; if (dstNeeded > spaceLeft) { int length = offset + ((offset < dstNeeded) ? dstNeeded : offset); if (Tcl_AttemptSetObjLength(objPtr, length) == 0) { length = offset + dstNeeded; if (Tcl_AttemptSetObjLength(objPtr, length) == 0) { dstNeeded = TCL_UTF_MAX - 1 + toRead; length = offset + dstNeeded; Tcl_SetObjLength(objPtr, length); } } spaceLeft = length - offset; dst = objPtr->bytes + offset; *gsPtr->dstPtr = dst; } gsPtr->state = statePtr->inputEncodingState; result = Tcl_ExternalToUtf(NULL, gsPtr->encoding, raw, rawLen, statePtr->inputEncodingFlags | TCL_ENCODING_NO_TERMINATE, &statePtr->inputEncodingState, dst, spaceLeft, &gsPtr->rawRead, &gsPtr->bytesWrote, &gsPtr->charsWrote); /* * Make sure that if we go through 'gets', that we reset the * TCL_ENCODING_START flag still. [Bug #523988] */ statePtr->inputEncodingFlags &= ~TCL_ENCODING_START; if (result == TCL_CONVERT_MULTIBYTE) { /* * The last few bytes in this channel buffer were the start of a * multibyte sequence. If this buffer was full, then move them to the * next buffer so the bytes will be contiguous. */ ChannelBuffer *nextPtr; int extra; nextPtr = bufPtr->nextPtr; if (!IsBufferFull(bufPtr)) { if (gsPtr->rawRead > 0) { /* * Some raw bytes were converted to UTF-8. Fall through, * returning those UTF-8 characters because a EOL might be * present in them. */ } else if (GotFlag(statePtr, CHANNEL_EOF)) { /* * There was a partial character followed by EOF on the * device. Fall through, returning that nothing was found. */ bufPtr->nextRemoved = bufPtr->nextAdded; } else { /* * There are no more cached raw bytes left. See if we can get * some more, but avoid blocking on a non-blocking channel. */ goto read; } } else { if (nextPtr == NULL) { nextPtr = AllocChannelBuffer(statePtr->bufSize); bufPtr->nextPtr = nextPtr; statePtr->inQueueTail = nextPtr; } extra = rawLen - gsPtr->rawRead; memcpy(nextPtr->buf + (BUFFER_PADDING - extra), raw + gsPtr->rawRead, (size_t) extra); nextPtr->nextRemoved -= extra; bufPtr->nextAdded -= extra; } } gsPtr->bufPtr = bufPtr; return 0; } /* *--------------------------------------------------------------------------- * * PeekAhead -- * * Helper function used by Tcl_GetsObj(). Called when we've seen a \r at * the end of the UTF-8 string and want to look ahead one character to * see if it is a \n. * * Results: * *gsPtr->dstPtr is filled with a pointer to the start of the range of * UTF-8 characters that were found by peeking and *dstEndPtr is filled * with a pointer to the bytes just after the end of the range. * * Side effects: * If no more raw bytes were available in one of the channel buffers, * tries to perform a non-blocking read to get more bytes from the * channel device. * *--------------------------------------------------------------------------- */ static void PeekAhead( Channel *chanPtr, /* The channel to read. */ char **dstEndPtr, /* Filled with pointer to end of new range of * UTF-8 characters. */ GetsState *gsPtr) /* Current state of gets operation. */ { ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelBuffer *bufPtr; Tcl_DriverBlockModeProc *blockModeProc; int bytesLeft; bufPtr = gsPtr->bufPtr; /* * If there's any more raw input that's still buffered, we'll peek into * that. Otherwise, only get more data from the channel driver if it looks * like there might actually be more data. The assumption is that if the * channel buffer is filled right up to the end, then there might be more * data to read. */ blockModeProc = NULL; if (bufPtr->nextPtr == NULL) { bytesLeft = BytesLeft(bufPtr) - gsPtr->rawRead; if (bytesLeft == 0) { if (!IsBufferFull(bufPtr)) { /* * Don't peek ahead if last read was short read. */ goto cleanup; } if (!GotFlag(statePtr, CHANNEL_NONBLOCKING)) { blockModeProc = Tcl_ChannelBlockModeProc(chanPtr->typePtr); if (blockModeProc == NULL) { /* * Don't peek ahead if cannot set non-blocking mode. */ goto cleanup; } StackSetBlockMode(chanPtr, TCL_MODE_NONBLOCKING); } } } if (FilterInputBytes(chanPtr, gsPtr) == 0) { *dstEndPtr = *gsPtr->dstPtr + gsPtr->bytesWrote; } if (blockModeProc != NULL) { StackSetBlockMode(chanPtr, TCL_MODE_BLOCKING); } return; cleanup: bufPtr->nextRemoved += gsPtr->rawRead; gsPtr->rawRead = 0; gsPtr->totalChars += gsPtr->charsWrote; gsPtr->bytesWrote = 0; gsPtr->charsWrote = 0; } /* *--------------------------------------------------------------------------- * * CommonGetsCleanup -- * * Helper function for Tcl_GetsObj() to restore the channel after a * "gets" operation. * * Results: * None. * * Side effects: * Encoding may be freed. * *--------------------------------------------------------------------------- */ static void CommonGetsCleanup( Channel *chanPtr) { ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelBuffer *bufPtr, *nextPtr; bufPtr = statePtr->inQueueHead; for ( ; bufPtr != NULL; bufPtr = nextPtr) { nextPtr = bufPtr->nextPtr; if (IsBufferReady(bufPtr)) { break; } RecycleBuffer(statePtr, bufPtr, 0); } statePtr->inQueueHead = bufPtr; if (bufPtr == NULL) { statePtr->inQueueTail = NULL; } else { /* * If any multi-byte characters were split across channel buffer * boundaries, the split-up bytes were moved to the next channel * buffer by FilterInputBytes(). Move the bytes back to their original * buffer because the caller could change the channel's encoding which * could change the interpretation of whether those bytes really made * up multi-byte characters after all. */ nextPtr = bufPtr->nextPtr; for ( ; nextPtr != NULL; nextPtr = bufPtr->nextPtr) { int extra; extra = SpaceLeft(bufPtr); if (extra > 0) { memcpy(InsertPoint(bufPtr), nextPtr->buf + (BUFFER_PADDING - extra), (size_t) extra); bufPtr->nextAdded += extra; nextPtr->nextRemoved = BUFFER_PADDING; } bufPtr = nextPtr; } } } /* *---------------------------------------------------------------------- * * Tcl_Read -- * * Reads a given number of bytes from a channel. EOL and EOF translation * is done on the bytes being read, so the number of bytes consumed from * the channel may not be equal to the number of bytes stored in the * destination buffer. * * No encoding conversions are applied to the bytes being read. * * Results: * The number of bytes read, or -1 on error. Use Tcl_GetErrno() to * retrieve the error code for the error that occurred. * * Side effects: * May cause input to be buffered. * *---------------------------------------------------------------------- */ int Tcl_Read( Tcl_Channel chan, /* The channel from which to read. */ char *dst, /* Where to store input read. */ int bytesToRead) /* Maximum number of bytes to read. */ { Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) { return -1; } return DoRead(chanPtr, dst, bytesToRead, 0); } /* *---------------------------------------------------------------------- * * Tcl_ReadRaw -- * * Reads a given number of bytes from a channel. EOL and EOF translation * is done on the bytes being read, so the number of bytes consumed from * the channel may not be equal to the number of bytes stored in the * destination buffer. * * No encoding conversions are applied to the bytes being read. * * Results: * The number of bytes read, or -1 on error. Use Tcl_GetErrno() to * retrieve the error code for the error that occurred. * * Side effects: * May cause input to be buffered. * *---------------------------------------------------------------------- */ int Tcl_ReadRaw( Tcl_Channel chan, /* The channel from which to read. */ char *readBuf, /* Where to store input read. */ int bytesToRead) /* Maximum number of bytes to read. */ { Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ int copied = 0; assert(bytesToRead > 0); if (CheckChannelErrors(statePtr, TCL_READABLE | CHANNEL_RAW_MODE) != 0) { return -1; } /* First read bytes from the push-back buffers. */ while (chanPtr->inQueueHead && bytesToRead > 0) { ChannelBuffer *bufPtr = chanPtr->inQueueHead; int bytesInBuffer = BytesLeft(bufPtr); int toCopy = (bytesInBuffer < bytesToRead) ? bytesInBuffer : bytesToRead; /* Copy the current chunk into the read buffer. */ memcpy(readBuf, RemovePoint(bufPtr), (size_t) toCopy); bufPtr->nextRemoved += toCopy; copied += toCopy; readBuf += toCopy; bytesToRead -= toCopy; /* If the current buffer is empty recycle it. */ if (IsBufferEmpty(bufPtr)) { chanPtr->inQueueHead = bufPtr->nextPtr; if (chanPtr->inQueueHead == NULL) { chanPtr->inQueueTail = NULL; } RecycleBuffer(chanPtr->state, bufPtr, 0); } } /* * Go to the driver only if we got nothing from pushback. * Have to do it this way to avoid EOF mis-timings when we * consider the ability that EOF may not be a permanent * condition in the driver, and in that case we have to * synchronize. */ if (copied) { return copied; } /* This test not needed. */ if (bytesToRead > 0) { int nread = ChanRead(chanPtr, readBuf, bytesToRead); if (nread > 0) { /* Successful read (short is OK) - add to bytes copied */ copied += nread; } else if (nread < 0) { /* * An error signaled. If CHANNEL_BLOCKED, then the error * is not real, but an indication of blocked state. In * that case, retain the flag and let caller receive the * short read of copied bytes from the pushback. * HOWEVER, if copied==0 bytes from pushback then repeat * signalling the blocked state as an error to caller so * there is no false report of an EOF. * When !CHANNEL_BLOCKED, the error is real and passes on * to caller. */ if (!GotFlag(statePtr, CHANNEL_BLOCKED) || copied == 0) { copied = -1; } } else { /* * nread == 0. Driver is at EOF. Let that state filter up. */ } } return copied; } /* *--------------------------------------------------------------------------- * * Tcl_ReadChars -- * * Reads from the channel until the requested number of characters have * been seen, EOF is seen, or the channel would block. EOL and EOF * translation is done. If reading binary data, the raw bytes are wrapped * in a Tcl byte array object. Otherwise, the raw bytes are converted to * UTF-8 using the channel's current encoding and stored in a Tcl string * object. * * Results: * The number of characters read, or -1 on error. Use Tcl_GetErrno() to * retrieve the error code for the error that occurred. * * Side effects: * May cause input to be buffered. * *--------------------------------------------------------------------------- */ int Tcl_ReadChars( Tcl_Channel chan, /* The channel to read. */ Tcl_Obj *objPtr, /* Input data is stored in this object. */ int toRead, /* Maximum number of characters to store, or * -1 to read all available data (up to EOF or * when channel blocks). */ int appendFlag) /* If non-zero, data read from the channel * will be appended to the object. Otherwise, * the data will replace the existing contents * of the object. */ { Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) { /* * Update the notifier state so we don't block while there is still * data in the buffers. */ UpdateInterest(chanPtr); return -1; } return DoReadChars(chanPtr, objPtr, toRead, appendFlag); } /* *--------------------------------------------------------------------------- * * DoReadChars -- * * Reads from the channel until the requested number of characters have * been seen, EOF is seen, or the channel would block. EOL and EOF * translation is done. If reading binary data, the raw bytes are wrapped * in a Tcl byte array object. Otherwise, the raw bytes are converted to * UTF-8 using the channel's current encoding and stored in a Tcl string * object. * * Results: * The number of characters read, or -1 on error. Use Tcl_GetErrno() to * retrieve the error code for the error that occurred. * * Side effects: * May cause input to be buffered. * *--------------------------------------------------------------------------- */ static int DoReadChars( Channel *chanPtr, /* The channel to read. */ Tcl_Obj *objPtr, /* Input data is stored in this object. */ int toRead, /* Maximum number of characters to store, or * -1 to read all available data (up to EOF or * when channel blocks). */ int appendFlag) /* If non-zero, data read from the channel * will be appended to the object. Otherwise, * the data will replace the existing contents * of the object. */ { ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelBuffer *bufPtr; int copied, copiedNow, result; Tcl_Encoding encoding = statePtr->encoding; int binaryMode; #define UTF_EXPANSION_FACTOR 1024 int factor = UTF_EXPANSION_FACTOR; binaryMode = (encoding == NULL) && (statePtr->inputTranslation == TCL_TRANSLATE_LF) && (statePtr->inEofChar == '\0'); if (appendFlag == 0) { if (binaryMode) { Tcl_SetByteArrayLength(objPtr, 0); } else { Tcl_SetObjLength(objPtr, 0); /* * We're going to access objPtr->bytes directly, so we must ensure * that this is actually a string object (otherwise it might have * been pure Unicode). * * Probably not needed anymore. */ TclGetString(objPtr); } } /* * Early out when next read will see eofchar. * * NOTE: See DoRead for argument that it's a bug (one we're keeping) * to have this escape before the one for zero-char read request. */ if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) { SetFlag(statePtr, CHANNEL_EOF); assert( statePtr->inputEncodingFlags & TCL_ENCODING_END ); assert( !GotFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR) ); /* TODO: We don't need this call? */ UpdateInterest(chanPtr); return 0; } /* Special handling for zero-char read request. */ if (toRead == 0) { if (GotFlag(statePtr, CHANNEL_EOF)) { statePtr->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF); statePtr->inputEncodingFlags &= ~TCL_ENCODING_END; /* TODO: We don't need this call? */ UpdateInterest(chanPtr); return 0; } /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; TclChannelPreserve((Tcl_Channel)chanPtr); /* Must clear the BLOCKED|EOF flags here since we check before reading */ if (GotFlag(statePtr, CHANNEL_EOF)) { statePtr->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF); statePtr->inputEncodingFlags &= ~TCL_ENCODING_END; for (copied = 0; (unsigned) toRead > 0; ) { copiedNow = -1; if (statePtr->inQueueHead != NULL) { if (binaryMode) { copiedNow = ReadBytes(statePtr, objPtr, toRead); } else { copiedNow = ReadChars(statePtr, objPtr, toRead, &factor); } /* * If the current buffer is empty recycle it. */ bufPtr = statePtr->inQueueHead; if (IsBufferEmpty(bufPtr)) { ChannelBuffer *nextPtr = bufPtr->nextPtr; RecycleBuffer(statePtr, bufPtr, 0); statePtr->inQueueHead = nextPtr; if (nextPtr == NULL) { statePtr->inQueueTail = NULL; } } } if (copiedNow < 0) { if (GotFlag(statePtr, CHANNEL_EOF)) { break; } if (GotFlag(statePtr, CHANNEL_NONBLOCKING|CHANNEL_BLOCKED) == (CHANNEL_NONBLOCKING|CHANNEL_BLOCKED)) { break; } result = GetInput(chanPtr); if (chanPtr != statePtr->topChanPtr) { TclChannelRelease((Tcl_Channel)chanPtr); chanPtr = statePtr->topChanPtr; TclChannelPreserve((Tcl_Channel)chanPtr); } if (result != 0) { if (!GotFlag(statePtr, CHANNEL_BLOCKED)) { copied = -1; } break; } } else { copied += copiedNow; toRead -= copiedNow; } } /* * Failure to fill a channel buffer may have left channel reporting * a "blocked" state, but so long as we fulfilled the request here, * the caller does not consider us blocked. */ if (toRead == 0) { ResetFlag(statePtr, CHANNEL_BLOCKED); } /* * Regenerate the top channel, in case it was changed due to * self-modifying reflected transforms. */ if (chanPtr != statePtr->topChanPtr) { TclChannelRelease((Tcl_Channel)chanPtr); chanPtr = statePtr->topChanPtr; TclChannelPreserve((Tcl_Channel)chanPtr); } /* * Update the notifier state so we don't block while there is still data * in the buffers. */ assert(!GotFlag(statePtr, CHANNEL_EOF) || GotFlag(statePtr, CHANNEL_STICKY_EOF) || Tcl_InputBuffered((Tcl_Channel)chanPtr) == 0); assert( !(GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED) == (CHANNEL_EOF|CHANNEL_BLOCKED)) ); UpdateInterest(chanPtr); TclChannelRelease((Tcl_Channel)chanPtr); return copied; } /* *--------------------------------------------------------------------------- * * ReadBytes -- * * Reads from the channel until the requested number of bytes have been * seen, EOF is seen, or the channel would block. Bytes from the channel * are stored in objPtr as a ByteArray object. EOL and EOF translation * are done. * * 'bytesToRead' can safely be a very large number because space is only * allocated to hold data read from the channel as needed. * * Results: * The return value is the number of bytes appended to the object, or * -1 to indicate that zero bytes were read due to an EOF. * * Side effects: * The storage of bytes in objPtr can cause (re-)allocation of memory. * *--------------------------------------------------------------------------- */ static int ReadBytes( ChannelState *statePtr, /* State of the channel to read. */ Tcl_Obj *objPtr, /* Input data is appended to this ByteArray * object. Its length is how much space has * been allocated to hold data, not how many * bytes of data have been stored in the * object. */ int bytesToRead) /* Maximum number of bytes to store, or < 0 to * get all available bytes. Bytes are obtained * from the first buffer in the queue - even * if this number is larger than the number of * bytes available in the first buffer, only * the bytes from the first buffer are * returned. */ { ChannelBuffer *bufPtr = statePtr->inQueueHead; int srcLen = BytesLeft(bufPtr); int toRead = bytesToRead>srcLen || bytesToRead<0 ? srcLen : bytesToRead; TclAppendBytesToByteArray(objPtr, (unsigned char *) RemovePoint(bufPtr), toRead); bufPtr->nextRemoved += toRead; return toRead; } /* *--------------------------------------------------------------------------- * * ReadChars -- * * Reads from the channel until the requested number of UTF-8 characters * have been seen, EOF is seen, or the channel would block. Raw bytes * from the channel are converted to UTF-8 and stored in objPtr. EOL and * EOF translation is done. * * 'charsToRead' can safely be a very large number because space is only * allocated to hold data read from the channel as needed. * * 'charsToRead' may *not* be 0. * * Results: * The return value is the number of characters appended to the object, * *offsetPtr is filled with the number of bytes that were appended, and * *factorPtr is filled with the expansion factor used to guess how many * bytes of UTF-8 to allocate to hold N source bytes. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static int ReadChars( ChannelState *statePtr, /* State of channel to read. */ Tcl_Obj *objPtr, /* Input data is appended to this object. * objPtr->length is how much space has been * allocated to hold data, not how many bytes * of data have been stored in the object. */ int charsToRead, /* Maximum number of characters to store, or * -1 to get all available characters. * Characters are obtained from the first * buffer in the queue -- even if this number * is larger than the number of characters * available in the first buffer, only the * characters from the first buffer are * returned. The execption is when there is * not any complete character in the first * buffer. In that case, a recursive call * effectively obtains chars from the * second buffer. */ int *factorPtr) /* On input, contains a guess of how many * bytes need to be allocated to hold the * result of converting N source bytes to * UTF-8. On output, contains another guess * based on the data seen so far. */ { Tcl_Encoding encoding = statePtr->encoding? statePtr->encoding : GetBinaryEncoding(); Tcl_EncodingState savedState = statePtr->inputEncodingState; ChannelBuffer *bufPtr = statePtr->inQueueHead; int savedIEFlags = statePtr->inputEncodingFlags; int savedFlags = statePtr->flags; char *dst, *src = RemovePoint(bufPtr); int numBytes, srcLen = BytesLeft(bufPtr); /* * One src byte can yield at most one character. So when the * number of src bytes we plan to read is less than the limit on * character count to be read, clearly we will remain within that * limit, and we can use the value of "srcLen" as a tighter limit * for sizing receiving buffers. */ int toRead = ((charsToRead<0)||(charsToRead > srcLen)) ? srcLen : charsToRead; /* * 'factor' is how much we guess that the bytes in the source buffer will * expand when converted to UTF-8 chars. This guess comes from analyzing * how many characters were produced by the previous pass. */ int factor = *factorPtr; int dstLimit = TCL_UTF_MAX - 1 + toRead * factor / UTF_EXPANSION_FACTOR; (void) TclGetStringFromObj(objPtr, &numBytes); Tcl_AppendToObj(objPtr, NULL, dstLimit); if (toRead == srcLen) { unsigned int size; dst = TclGetStringStorage(objPtr, &size) + numBytes; dstLimit = size - numBytes; } else { dst = TclGetString(objPtr) + numBytes; } /* * This routine is burdened with satisfying several constraints. * It cannot append more than 'charsToRead` chars onto objPtr. * This is measured after encoding and translation transformations * are completed. There is no precise number of src bytes that can * be associated with the limit. Yet, when we are done, we must know * precisely the number of src bytes that were consumed to produce * the appended chars, so that all subsequent bytes are left in * the buffers for future read operations. * * The consequence is that we have no choice but to implement a * "trial and error" approach, where in general we may need to * perform transformations and copies multiple times to achieve * a consistent set of results. This takes the shape of a loop. */ while (1) { int dstDecoded, dstRead, dstWrote, srcRead, numChars, code; int flags = statePtr->inputEncodingFlags | TCL_ENCODING_NO_TERMINATE; if (charsToRead > 0) { flags |= TCL_ENCODING_CHAR_LIMIT; numChars = charsToRead; } /* * Perform the encoding transformation. Read no more than * srcLen bytes, write no more than dstLimit bytes. * * Some trickiness with encoding flags here. We do not want * the end of a buffer to be treated as the end of all input * when the presence of bytes in a next buffer are already * known to exist. This is checked with an assert() because * so far no test case causing the assertion to be false has * been created. The normal operations of channel reading * appear to cause EOF and TCL_ENCODING_END setting to appear * only in situations where there are no further bytes in * any buffers. */ assert(bufPtr->nextPtr == NULL || BytesLeft(bufPtr->nextPtr) == 0 || (statePtr->inputEncodingFlags & TCL_ENCODING_END) == 0); code = Tcl_ExternalToUtf(NULL, encoding, src, srcLen, flags, &statePtr->inputEncodingState, dst, dstLimit, &srcRead, &dstDecoded, &numChars); /* * Perform the translation transformation in place. Read no more * than the dstDecoded bytes the encoding transformation actually * produced. Capture the number of bytes written in dstWrote. * Capture the number of bytes actually consumed in dstRead. */ dstWrote = dstLimit; dstRead = dstDecoded; TranslateInputEOL(statePtr, dst, dst, &dstWrote, &dstRead); if (dstRead < dstDecoded) { /* * The encoding transformation produced bytes that the * translation transformation did not consume. Why did * this happen? */ if (statePtr->inEofChar && dst[dstRead] == statePtr->inEofChar) { /* * 1) There's an eof char set on the channel, and * we saw it and stopped translating at that point. * * NOTE the bizarre spec of TranslateInputEOL in this case. * Clearly the eof char had to be read in order to account * for the stopping, but the value of dstRead does not * include it. * * Also rather bizarre, our caller can only notice an * EOF condition if we return the value -1 as the number * of chars read. This forces us to perform a 2-call * dance where the first call can read all the chars * up to the eof char, and the second call is solely * for consuming the encoded eof char then pointed at * by src so that we can return that magic -1 value. * This seems really wasteful, especially since * the first decoding pass of each call is likely to * decode many bytes beyond that eof char that's all we * care about. */ if (dstRead == 0) { /* * Curious choice in the eof char handling. We leave * the eof char in the buffer. So, no need to compute * a proper srcRead value. At this point, there * are no chars before the eof char in the buffer. */ Tcl_SetObjLength(objPtr, numBytes); return -1; } { /* * There are chars leading the buffer before the eof * char. Adjust the dstLimit so we go back and read * only those and do not encounter the eof char this * time. */ dstLimit = dstRead - 1 + TCL_UTF_MAX; statePtr->flags = savedFlags; statePtr->inputEncodingFlags = savedIEFlags; statePtr->inputEncodingState = savedState; continue; } } /* * 2) The other way to read fewer bytes than are decoded * is when the final byte is \r and we're in a CRLF * translation mode so we cannot decide whether to * record \r or \n yet. */ assert(dst[dstRead] == '\r'); assert(statePtr->inputTranslation == TCL_TRANSLATE_CRLF); if (dstWrote > 0) { /* * There are chars we can read before we hit the bare cr. * Go back with a smaller dstLimit so we get them in the * next pass, compute a matching srcRead, and don't end * up back here in this call. */ dstLimit = dstRead - 1 + TCL_UTF_MAX; statePtr->flags = savedFlags; statePtr->inputEncodingFlags = savedIEFlags; statePtr->inputEncodingState = savedState; continue; } assert(dstWrote == 0); assert(dstRead == 0); /* * We decoded only the bare cr, and we cannot read a * translated char from that alone. We have to know what's * next. So why do we only have the one decoded char? */ if (code != TCL_OK) { char buffer[TCL_UTF_MAX + 1]; int read, decoded, count; /* * Didn't get everything the buffer could offer */ statePtr->flags = savedFlags; statePtr->inputEncodingFlags = savedIEFlags; statePtr->inputEncodingState = savedState; assert(bufPtr->nextPtr == NULL || BytesLeft(bufPtr->nextPtr) == 0 || 0 == (statePtr->inputEncodingFlags & TCL_ENCODING_END)); Tcl_ExternalToUtf(NULL, encoding, src, srcLen, (statePtr->inputEncodingFlags | TCL_ENCODING_NO_TERMINATE), &statePtr->inputEncodingState, buffer, TCL_UTF_MAX + 1, &read, &decoded, &count); if (count == 2) { if (buffer[1] == '\n') { /* \r\n translate to \n */ dst[0] = '\n'; bufPtr->nextRemoved += read; } else { dst[0] = '\r'; bufPtr->nextRemoved += srcRead; } statePtr->inputEncodingFlags &= ~TCL_ENCODING_START; Tcl_SetObjLength(objPtr, numBytes + 1); return 1; } } else if (statePtr->flags & CHANNEL_EOF) { /* * The bare \r is the only char and we will never read * a subsequent char to make the determination. */ dst[0] = '\r'; bufPtr->nextRemoved = bufPtr->nextAdded; Tcl_SetObjLength(objPtr, numBytes + 1); return 1; } /* * Revise the dstRead value so that the numChars calc * below correctly computes zero characters read. */ dstRead = numChars; /* FALL THROUGH - get more data (dstWrote == 0) */ } /* * The translation transformation can only reduce the number * of chars when it converts \r\n into \n. The reduction in * the number of chars is the difference in bytes read and written. */ numChars -= (dstRead - dstWrote); if (charsToRead > 0 && numChars > charsToRead) { /* * TODO: This cannot happen anymore. * * We read more chars than allowed. Reset limits to * prevent that and try again. Don't forget the extra * padding of TCL_UTF_MAX bytes demanded by the * Tcl_ExternalToUtf() call! */ dstLimit = Tcl_UtfAtIndex(dst, charsToRead) - 1 + TCL_UTF_MAX - dst; statePtr->flags = savedFlags; statePtr->inputEncodingFlags = savedIEFlags; statePtr->inputEncodingState = savedState; continue; } if (dstWrote == 0) { ChannelBuffer *nextPtr; /* We were not able to read any chars. */ assert (numChars == 0); /* * There is one situation where this is the correct final * result. If the src buffer contains only a single \n * byte, and we are in TCL_TRANSLATE_AUTO mode, and * when the translation pass was made the INPUT_SAW_CR * flag was set on the channel. In that case, the * correct behavior is to consume that \n and produce the * empty string. */ if (dstRead == 1 && dst[0] == '\n') { assert(statePtr->inputTranslation == TCL_TRANSLATE_AUTO); goto consume; } /* Otherwise, reading zero characters indicates there's * something incomplete at the end of the src buffer. * Maybe there were not enough src bytes to decode into * a char. Maybe a lone \r could not be translated (crlf * mode). Need to combine any unused src bytes we have * in the first buffer with subsequent bytes to try again. */ nextPtr = bufPtr->nextPtr; if (nextPtr == NULL) { if (srcLen > 0) { SetFlag(statePtr, CHANNEL_NEED_MORE_DATA); } Tcl_SetObjLength(objPtr, numBytes); return -1; } /* * Space is made at the beginning of the buffer to copy the * previous unused bytes there. Check first if the buffer we * are using actually has enough space at its beginning for * the data we are copying. Because if not we will write over * the buffer management information, especially the 'nextPtr'. * * Note that the BUFFER_PADDING (See AllocChannelBuffer) is * used to prevent exactly this situation. I.e. it should never * happen. Therefore it is ok to panic should it happen despite * the precautions. */ if (nextPtr->nextRemoved - srcLen < 0) { Tcl_Panic("Buffer Underflow, BUFFER_PADDING not enough"); } nextPtr->nextRemoved -= srcLen; memcpy(RemovePoint(nextPtr), src, (size_t) srcLen); RecycleBuffer(statePtr, bufPtr, 0); statePtr->inQueueHead = nextPtr; Tcl_SetObjLength(objPtr, numBytes); return ReadChars(statePtr, objPtr, charsToRead, factorPtr); } statePtr->inputEncodingFlags &= ~TCL_ENCODING_START; consume: bufPtr->nextRemoved += srcRead; /* * If this read contained multibyte characters, revise factorPtr * so the next read will allocate bigger buffers. */ if (numChars && numChars < srcRead) { *factorPtr = srcRead * UTF_EXPANSION_FACTOR / numChars; } Tcl_SetObjLength(objPtr, numBytes + dstWrote); return numChars; } } /* *--------------------------------------------------------------------------- * * TranslateInputEOL -- * * Perform input EOL and EOF translation on the source buffer, leaving * the translated result in the destination buffer. * * Results: * The return value is 1 if the EOF character was found when copying * bytes to the destination buffer, 0 otherwise. * * Side effects: * None. * *--------------------------------------------------------------------------- */ static void TranslateInputEOL( ChannelState *statePtr, /* Channel being read, for EOL translation and * EOF character. */ char *dstStart, /* Output buffer filled with chars by applying * appropriate EOL translation to source * characters. */ const char *srcStart, /* Source characters. */ int *dstLenPtr, /* On entry, the maximum length of output * buffer in bytes. On exit, the number of * bytes actually used in output buffer. */ int *srcLenPtr) /* On entry, the length of source buffer. On * exit, the number of bytes read from the * source buffer. */ { const char *eof = NULL; int dstLen = *dstLenPtr; int srcLen = *srcLenPtr; int inEofChar = statePtr->inEofChar; /* * Depending on the translation mode in use, there's no need * to scan more srcLen bytes at srcStart than can possibly transform * to dstLen bytes. This keeps the scan for eof char below from * being pointlessly long. */ switch (statePtr->inputTranslation) { case TCL_TRANSLATE_LF: case TCL_TRANSLATE_CR: if (srcLen > dstLen) { /* In these modes, each src byte become a dst byte. */ srcLen = dstLen; } break; default: /* In other modes, at most 2 src bytes become a dst byte. */ if (srcLen/2 > dstLen) { srcLen = 2 * dstLen; } break; } if (inEofChar != '\0') { /* * Make sure we do not read past any logical end of channel input * created by the presence of the input eof char. */ if ((eof = memchr(srcStart, inEofChar, srcLen))) { srcLen = eof - srcStart; } } switch (statePtr->inputTranslation) { case TCL_TRANSLATE_LF: case TCL_TRANSLATE_CR: if (dstStart != srcStart) { memcpy(dstStart, srcStart, (size_t) srcLen); } if (statePtr->inputTranslation == TCL_TRANSLATE_CR) { char *dst = dstStart; char *dstEnd = dstStart + srcLen; while ((dst = memchr(dst, '\r', dstEnd - dst))) { *dst++ = '\n'; } } dstLen = srcLen; break; case TCL_TRANSLATE_CRLF: { const char *crFound, *src = srcStart; char *dst = dstStart; int lesser = (dstLen < srcLen) ? dstLen : srcLen; while ((crFound = memchr(src, '\r', lesser))) { int numBytes = crFound - src; memmove(dst, src, numBytes); dst += numBytes; dstLen -= numBytes; src += numBytes; srcLen -= numBytes; if (srcLen == 1) { /* valid src bytes end in \r */ if (eof) { *dst++ = '\r'; src++; srcLen--; } else { lesser = 0; break; } } else if (src[1] == '\n') { *dst++ = '\n'; src += 2; srcLen -= 2; } else { *dst++ = '\r'; src++; srcLen--; } dstLen--; lesser = (dstLen < srcLen) ? dstLen : srcLen; } memmove(dst, src, lesser); srcLen = src + lesser - srcStart; dstLen = dst + lesser - dstStart; break; } case TCL_TRANSLATE_AUTO: { const char *crFound, *src = srcStart; char *dst = dstStart; int lesser; if ((statePtr->flags & INPUT_SAW_CR) && srcLen) { if (*src == '\n') { src++; srcLen--; } ResetFlag(statePtr, INPUT_SAW_CR); } lesser = (dstLen < srcLen) ? dstLen : srcLen; while ((crFound = memchr(src, '\r', lesser))) { int numBytes = crFound - src; memmove(dst, src, numBytes); dst[numBytes] = '\n'; dst += numBytes + 1; dstLen -= numBytes + 1; src += numBytes + 1; srcLen -= numBytes + 1; if (srcLen == 0) { SetFlag(statePtr, INPUT_SAW_CR); } else if (*src == '\n') { src++; srcLen--; } lesser = (dstLen < srcLen) ? dstLen : srcLen; } memmove(dst, src, lesser); srcLen = src + lesser - srcStart; dstLen = dst + lesser - dstStart; break; } default: Tcl_Panic("unknown input translation %d", statePtr->inputTranslation); } *dstLenPtr = dstLen; *srcLenPtr = srcLen; if (srcStart + srcLen == eof) { /* * EOF character was seen in EOL translated range. Leave current file * position pointing at the EOF character, but don't store the EOF * character in the output string. */ SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF); statePtr->inputEncodingFlags |= TCL_ENCODING_END; ResetFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR); } } /* *---------------------------------------------------------------------- * * Tcl_Ungets -- * * Causes the supplied string to be added to the input queue of the * channel, at either the head or tail of the queue. * * Results: * The number of bytes stored in the channel, or -1 on error. * * Side effects: * Adds input to the input queue of a channel. * *---------------------------------------------------------------------- */ int Tcl_Ungets( Tcl_Channel chan, /* The channel for which to add the input. */ const char *str, /* The input itself. */ int len, /* The length of the input. */ int atEnd) /* If non-zero, add at end of queue; otherwise * add at head of queue. */ { Channel *chanPtr; /* The real IO channel. */ ChannelState *statePtr; /* State of actual channel. */ ChannelBuffer *bufPtr; /* Buffer to contain the data. */ int flags; chanPtr = (Channel *) chan; statePtr = chanPtr->state; /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; /* * CheckChannelErrors clears too many flag bits in this one case. */ flags = statePtr->flags; if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) { len = -1; goto done; } statePtr->flags = flags; /* * Clear the EOF flags, and clear the BLOCKED bit. */ if (GotFlag(statePtr, CHANNEL_EOF)) { statePtr->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(statePtr, CHANNEL_BLOCKED | CHANNEL_STICKY_EOF | CHANNEL_EOF | INPUT_SAW_CR); statePtr->inputEncodingFlags &= ~TCL_ENCODING_END; bufPtr = AllocChannelBuffer(len); memcpy(InsertPoint(bufPtr), str, (size_t) len); bufPtr->nextAdded += len; if (statePtr->inQueueHead == NULL) { bufPtr->nextPtr = NULL; statePtr->inQueueHead = bufPtr; statePtr->inQueueTail = bufPtr; } else if (atEnd) { bufPtr->nextPtr = NULL; statePtr->inQueueTail->nextPtr = bufPtr; statePtr->inQueueTail = bufPtr; } else { bufPtr->nextPtr = statePtr->inQueueHead; statePtr->inQueueHead = bufPtr; } /* * Update the notifier state so we don't block while there is still data * in the buffers. */ done: UpdateInterest(chanPtr); return len; } /* *---------------------------------------------------------------------- * * Tcl_Flush -- * * Flushes output data on a channel. * * Results: * A standard Tcl result. * * Side effects: * May flush output queued on this channel. * *---------------------------------------------------------------------- */ int Tcl_Flush( Tcl_Channel chan) /* The Channel to flush. */ { int result; /* Of calling FlushChannel. */ Channel *chanPtr = (Channel *) chan; /* The actual channel. */ ChannelState *statePtr = chanPtr->state; /* State of actual channel. */ /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { return -1; } result = FlushChannel(NULL, chanPtr, 0); if (result != 0) { return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * DiscardInputQueued -- * * Discards any input read from the channel but not yet consumed by Tcl * reading commands. * * Results: * None. * * Side effects: * May discard input from the channel. If discardLastBuffer is zero, * leaves one buffer in place for back-filling. * *---------------------------------------------------------------------- */ static void DiscardInputQueued( ChannelState *statePtr, /* Channel on which to discard the queued * input. */ int discardSavedBuffers) /* If non-zero, discard all buffers including * last one. */ { ChannelBuffer *bufPtr, *nxtPtr; /* Loop variables. */ bufPtr = statePtr->inQueueHead; statePtr->inQueueHead = NULL; statePtr->inQueueTail = NULL; for (; bufPtr != NULL; bufPtr = nxtPtr) { nxtPtr = bufPtr->nextPtr; RecycleBuffer(statePtr, bufPtr, discardSavedBuffers); } /* * If discardSavedBuffers is nonzero, must also discard any previously * saved buffer in the saveInBufPtr field. */ if (discardSavedBuffers && statePtr->saveInBufPtr != NULL) { ReleaseChannelBuffer(statePtr->saveInBufPtr); statePtr->saveInBufPtr = NULL; } } /* *--------------------------------------------------------------------------- * * GetInput -- * * Reads input data from a device into a channel buffer. * * IMPORTANT! This routine is only called on a chanPtr argument * that is the top channel of a stack! * * Results: * The return value is the Posix error code if an error occurred while * reading from the file, or 0 otherwise. * * Side effects: * Reads from the underlying device. * *--------------------------------------------------------------------------- */ static int GetInput( Channel *chanPtr) /* Channel to read input from. */ { int toRead; /* How much to read? */ int result; /* Of calling driver. */ int nread; /* How much was read from channel? */ ChannelBuffer *bufPtr; /* New buffer to add to input queue. */ ChannelState *statePtr = chanPtr->state; /* State info for channel */ /* * Verify that all callers know better than to call us when * it's recorded that the next char waiting to be read is the * eofchar. */ assert( !GotFlag(statePtr, CHANNEL_STICKY_EOF) ); /* * Prevent reading from a dead channel -- a channel that has been closed * but not yet deallocated, which can happen if the exit handler for * channel cleanup has run but the channel is still registered in some * interpreter. */ if (CheckForDeadChannel(NULL, statePtr)) { return EINVAL; } /* * WARNING: There was once a comment here claiming that it was * a bad idea to make another call to the inputproc of a channel * driver when EOF has already been detected on the channel. Through * much of Tcl's history, this warning was then completely negated * by having all (most?) read paths clear the EOF setting before * reaching here. So we had a guard that was never triggered. * * Don't be tempted to restore the guard. Even if EOF is set on * the channel, continue through and call the inputproc again. This * is the way to enable the ability to [read] again beyond the EOF, * which seems a strange thing to do, but for which use cases exist * [Tcl Bug 5adc350683] and which may even be essential for channels * representing things like ttys or other devices where the stream * might take the logical form of a series of 'files' separated by * an EOF condition. */ /* * First check for more buffers in the pushback area of the topmost * channel in the stack and use them. They can be the result of a * transformation which went away without reading all the information * placed in the area when it was stacked. */ if (chanPtr->inQueueHead != NULL) { /* TODO: Tests to cover this. */ assert(statePtr->inQueueHead == NULL); statePtr->inQueueHead = chanPtr->inQueueHead; statePtr->inQueueTail = chanPtr->inQueueTail; chanPtr->inQueueHead = NULL; chanPtr->inQueueTail = NULL; return 0; } /* * Nothing in the pushback area, fall back to the usual handling (driver, * etc.) */ /* * See if we can fill an existing buffer. If we can, read only as much as * will fit in it. Otherwise allocate a new buffer, add it to the input * queue and attempt to fill it to the max. */ bufPtr = statePtr->inQueueTail; if ((bufPtr == NULL) || IsBufferFull(bufPtr)) { bufPtr = statePtr->saveInBufPtr; statePtr->saveInBufPtr = NULL; /* * Check the actual buffersize against the requested buffersize. * Saved buffers of the wrong size are squashed. This is done * to honor dynamic changes of the buffersize made by the user. * TODO: Tests to cover this. */ if ((bufPtr != NULL) && (bufPtr->bufLength - BUFFER_PADDING != statePtr->bufSize)) { ReleaseChannelBuffer(bufPtr); bufPtr = NULL; } if (bufPtr == NULL) { bufPtr = AllocChannelBuffer(statePtr->bufSize); } bufPtr->nextPtr = NULL; toRead = SpaceLeft(bufPtr); assert(toRead == statePtr->bufSize); if (statePtr->inQueueTail == NULL) { statePtr->inQueueHead = bufPtr; } else { statePtr->inQueueTail->nextPtr = bufPtr; } statePtr->inQueueTail = bufPtr; } else { toRead = SpaceLeft(bufPtr); } PreserveChannelBuffer(bufPtr); nread = ChanRead(chanPtr, InsertPoint(bufPtr), toRead); if (nread < 0) { result = Tcl_GetErrno(); } else { result = 0; bufPtr->nextAdded += nread; } ReleaseChannelBuffer(bufPtr); return result; } /* *---------------------------------------------------------------------- * * Tcl_Seek -- * * Implements seeking on Tcl Channels. This is a public function so that * other C facilities may be implemented on top of it. * * Results: * The new access point or -1 on error. If error, use Tcl_GetErrno() to * retrieve the POSIX error code for the error that occurred. * * Side effects: * May flush output on the channel. May discard queued input. * *---------------------------------------------------------------------- */ Tcl_WideInt Tcl_Seek( Tcl_Channel chan, /* The channel on which to seek. */ Tcl_WideInt offset, /* Offset to seek to. */ int mode) /* Relative to which location to seek? */ { Channel *chanPtr = (Channel *) chan; /* The real IO channel. */ ChannelState *statePtr = chanPtr->state; /* State info for channel */ int inputBuffered, outputBuffered; /* # bytes held in buffers. */ int result; /* Of device driver operations. */ Tcl_WideInt curPos; /* Position on the device. */ int wasAsync; /* Was the channel nonblocking before the seek * operation? If so, must restore to * non-blocking mode after the seek. */ if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) { return Tcl_LongAsWide(-1); } /* * Disallow seek on dead channels - channels that have been closed but not * yet been deallocated. Such channels can be found if the exit handler * for channel cleanup has run but the channel is still registered in an * interpreter. */ if (CheckForDeadChannel(NULL, statePtr)) { return Tcl_LongAsWide(-1); } /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; /* * Disallow seek on channels whose type does not have a seek procedure * defined. This means that the channel does not support seeking. */ if (chanPtr->typePtr->seekProc == NULL) { Tcl_SetErrno(EINVAL); return Tcl_LongAsWide(-1); } /* * Compute how much input and output is buffered. If both input and output * is buffered, cannot compute the current position. */ inputBuffered = Tcl_InputBuffered(chan); outputBuffered = Tcl_OutputBuffered(chan); if ((inputBuffered != 0) && (outputBuffered != 0)) { Tcl_SetErrno(EFAULT); return Tcl_LongAsWide(-1); } /* * If we are seeking relative to the current position, compute the * corrected offset taking into account the amount of unread input. */ if (mode == SEEK_CUR) { offset -= inputBuffered; } /* * Discard any queued input - this input should not be read after the * seek. */ DiscardInputQueued(statePtr, 0); /* * Reset EOF and BLOCKED flags. We invalidate them by moving the access * point. Also clear CR related flags. */ if (GotFlag(statePtr, CHANNEL_EOF)) { statePtr->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF | CHANNEL_BLOCKED | INPUT_SAW_CR); statePtr->inputEncodingFlags &= ~TCL_ENCODING_END; /* * If the channel is in asynchronous output mode, switch it back to * synchronous mode and cancel any async flush that may be scheduled. * After the flush, the channel will be put back into asynchronous output * mode. */ wasAsync = 0; if (GotFlag(statePtr, CHANNEL_NONBLOCKING)) { wasAsync = 1; result = StackSetBlockMode(chanPtr, TCL_MODE_BLOCKING); if (result != 0) { return Tcl_LongAsWide(-1); } ResetFlag(statePtr, CHANNEL_NONBLOCKING); if (GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { ResetFlag(statePtr, BG_FLUSH_SCHEDULED); } } /* * If the flush fails we cannot recover the original position. In that * case the seek is not attempted because we do not know where the access * position is - instead we return the error. FlushChannel has already * called Tcl_SetErrno() to report the error upwards. If the flush * succeeds we do the seek also. */ if (FlushChannel(NULL, chanPtr, 0) != 0) { curPos = -1; } else { /* * Now seek to the new position in the channel as requested by the * caller. */ curPos = ChanSeek(chanPtr, offset, mode, &result); if (curPos == Tcl_LongAsWide(-1)) { Tcl_SetErrno(result); } } /* * Restore to nonblocking mode if that was the previous behavior. * * NOTE: Even if there was an async flush active we do not restore it now * because we already flushed all the queued output, above. */ if (wasAsync) { SetFlag(statePtr, CHANNEL_NONBLOCKING); result = StackSetBlockMode(chanPtr, TCL_MODE_NONBLOCKING); if (result != 0) { return Tcl_LongAsWide(-1); } } return curPos; } /* *---------------------------------------------------------------------- * * Tcl_Tell -- * * Returns the position of the next character to be read/written on this * channel. * * Results: * A nonnegative integer on success, -1 on failure. If failed, use * Tcl_GetErrno() to retrieve the POSIX error code for the error that * occurred. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_WideInt Tcl_Tell( Tcl_Channel chan) /* The channel to return pos for. */ { Channel *chanPtr = (Channel *) chan; /* The real IO channel. */ ChannelState *statePtr = chanPtr->state; /* State info for channel */ int inputBuffered, outputBuffered; /* # bytes held in buffers. */ int result; /* Of calling device driver. */ Tcl_WideInt curPos; /* Position on device. */ if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) { return Tcl_LongAsWide(-1); } /* * Disallow tell on dead channels -- channels that have been closed but * not yet been deallocated. Such channels can be found if the exit * handler for channel cleanup has run but the channel is still registered * in an interpreter. */ if (CheckForDeadChannel(NULL, statePtr)) { return Tcl_LongAsWide(-1); } /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; /* * Disallow tell on channels whose type does not have a seek procedure * defined. This means that the channel does not support seeking. */ if (chanPtr->typePtr->seekProc == NULL) { Tcl_SetErrno(EINVAL); return Tcl_LongAsWide(-1); } /* * Compute how much input and output is buffered. If both input and output * is buffered, cannot compute the current position. */ inputBuffered = Tcl_InputBuffered(chan); outputBuffered = Tcl_OutputBuffered(chan); /* * Get the current position in the device and compute the position where * the next character will be read or written. Note that we prefer the * wideSeekProc if that is available and non-NULL... */ curPos = ChanSeek(chanPtr, Tcl_LongAsWide(0), SEEK_CUR, &result); if (curPos == Tcl_LongAsWide(-1)) { Tcl_SetErrno(result); return Tcl_LongAsWide(-1); } if (inputBuffered != 0) { return curPos - inputBuffered; } return curPos + outputBuffered; } /* *--------------------------------------------------------------------------- * * Tcl_SeekOld, Tcl_TellOld -- * * Backward-compatability versions of the seek/tell interface that do not * support 64-bit offsets. This interface is not documented or expected * to be supported indefinitely. * * Results: * As for Tcl_Seek and Tcl_Tell respectively, except truncated to * whatever value will fit in an 'int'. * * Side effects: * As for Tcl_Seek and Tcl_Tell respectively. * *--------------------------------------------------------------------------- */ int Tcl_SeekOld( Tcl_Channel chan, /* The channel on which to seek. */ int offset, /* Offset to seek to. */ int mode) /* Relative to which location to seek? */ { Tcl_WideInt wOffset, wResult; wOffset = Tcl_LongAsWide((long) offset); wResult = Tcl_Seek(chan, wOffset, mode); return (int) Tcl_WideAsLong(wResult); } int Tcl_TellOld( Tcl_Channel chan) /* The channel to return pos for. */ { Tcl_WideInt wResult = Tcl_Tell(chan); return (int) Tcl_WideAsLong(wResult); } /* *--------------------------------------------------------------------------- * * Tcl_TruncateChannel -- * * Truncate a channel to the given length. * * Results: * TCL_OK on success, TCL_ERROR if the operation failed (e.g. is not * supported by the type of channel, or the underlying OS operation * failed in some way). * * Side effects: * Seeks the channel to the current location. Sets errno on OS error. * *--------------------------------------------------------------------------- */ int Tcl_TruncateChannel( Tcl_Channel chan, /* Channel to truncate. */ Tcl_WideInt length) /* Length to truncate it to. */ { Channel *chanPtr = (Channel *) chan; Tcl_DriverTruncateProc *truncateProc = Tcl_ChannelTruncateProc(chanPtr->typePtr); int result; if (truncateProc == NULL) { /* * Feature not supported and it's not emulatable. Pretend it's * returned an EINVAL, a very generic error! */ Tcl_SetErrno(EINVAL); return TCL_ERROR; } if (!GotFlag(chanPtr->state, TCL_WRITABLE)) { /* * We require that the file was opened of writing. Do that check now * so that we only flush if we think we're going to succeed. */ Tcl_SetErrno(EINVAL); return TCL_ERROR; } /* * Seek first to force a total flush of all pending buffers and ditch any * pre-read input data. */ WillWrite(chanPtr); if (WillRead(chanPtr) < 0) { return TCL_ERROR; } /* * We're all flushed to disk now and we also don't have any unfortunate * input baggage around either; can truncate with impunity. */ result = truncateProc(chanPtr->instanceData, length); if (result != 0) { Tcl_SetErrno(result); return TCL_ERROR; } return TCL_OK; } /* *--------------------------------------------------------------------------- * * CheckChannelErrors -- * * See if the channel is in an ready state and can perform the desired * operation. * * Results: * The return value is 0 if the channel is OK, otherwise the return value * is -1 and errno is set to indicate the error. * * Side effects: * May clear the EOF and/or BLOCKED bits if reading from channel. * *--------------------------------------------------------------------------- */ static int CheckChannelErrors( ChannelState *statePtr, /* Channel to check. */ int flags) /* Test if channel supports desired operation: * TCL_READABLE, TCL_WRITABLE. Also indicates * Raw read or write for special close * processing */ { int direction = flags & (TCL_READABLE|TCL_WRITABLE); /* * Check for unreported error. */ if (statePtr->unreportedError != 0) { Tcl_SetErrno(statePtr->unreportedError); statePtr->unreportedError = 0; /* * TIP #219, Tcl Channel Reflection API. * Move a defered error message back into the channel bypass. */ if (statePtr->chanMsg != NULL) { TclDecrRefCount(statePtr->chanMsg); } statePtr->chanMsg = statePtr->unreportedMsg; statePtr->unreportedMsg = NULL; return -1; } /* * Only the raw read and write operations are allowed during close in * order to drain data from stacked channels. */ if (GotFlag(statePtr, CHANNEL_CLOSED) && !(flags & CHANNEL_RAW_MODE)) { Tcl_SetErrno(EACCES); return -1; } /* * Fail if the channel is not opened for desired operation. */ if ((statePtr->flags & direction) == 0) { Tcl_SetErrno(EACCES); return -1; } /* * Fail if the channel is in the middle of a background copy. * * Don't do this tests for raw channels here or else the chaining in the * transformation drivers will fail with 'file busy' error instead of * retrieving and transforming the data to copy. */ if (BUSY_STATE(statePtr, flags) && ((flags & CHANNEL_RAW_MODE) == 0)) { Tcl_SetErrno(EBUSY); return -1; } if (direction == TCL_READABLE) { ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA); } return 0; } /* *---------------------------------------------------------------------- * * Tcl_Eof -- * * Returns 1 if the channel is at EOF, 0 otherwise. * * Results: * 1 or 0, always. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_Eof( Tcl_Channel chan) /* Does this channel have EOF? */ { ChannelState *statePtr = ((Channel *) chan)->state; /* State of real channel structure. */ return GotFlag(statePtr, CHANNEL_EOF) ? 1 : 0; } /* *---------------------------------------------------------------------- * * Tcl_InputBlocked -- * * Returns 1 if input is blocked on this channel, 0 otherwise. * * Results: * 0 or 1, always. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_InputBlocked( Tcl_Channel chan) /* Is this channel blocked? */ { ChannelState *statePtr = ((Channel *) chan)->state; /* State of real channel structure. */ return GotFlag(statePtr, CHANNEL_BLOCKED) ? 1 : 0; } /* *---------------------------------------------------------------------- * * Tcl_InputBuffered -- * * Returns the number of bytes of input currently buffered in the common * internal buffer of a channel. * * Results: * The number of input bytes buffered, or zero if the channel is not open * for reading. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_InputBuffered( Tcl_Channel chan) /* The channel to query. */ { ChannelState *statePtr = ((Channel *) chan)->state; /* State of real channel structure. */ ChannelBuffer *bufPtr; int bytesBuffered; for (bytesBuffered = 0, bufPtr = statePtr->inQueueHead; bufPtr != NULL; bufPtr = bufPtr->nextPtr) { bytesBuffered += BytesLeft(bufPtr); } /* * Don't forget the bytes in the topmost pushback area. */ for (bufPtr = statePtr->topChanPtr->inQueueHead; bufPtr != NULL; bufPtr = bufPtr->nextPtr) { bytesBuffered += BytesLeft(bufPtr); } return bytesBuffered; } /* *---------------------------------------------------------------------- * * Tcl_OutputBuffered -- * * Returns the number of bytes of output currently buffered in the common * internal buffer of a channel. * * Results: * The number of output bytes buffered, or zero if the channel is not open * for writing. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_OutputBuffered( Tcl_Channel chan) /* The channel to query. */ { ChannelState *statePtr = ((Channel *) chan)->state; /* State of real channel structure. */ ChannelBuffer *bufPtr; int bytesBuffered; for (bytesBuffered = 0, bufPtr = statePtr->outQueueHead; bufPtr != NULL; bufPtr = bufPtr->nextPtr) { bytesBuffered += BytesLeft(bufPtr); } if (statePtr->curOutPtr != NULL) { register ChannelBuffer *curOutPtr = statePtr->curOutPtr; if (IsBufferReady(curOutPtr)) { bytesBuffered += BytesLeft(curOutPtr); } } return bytesBuffered; } /* *---------------------------------------------------------------------- * * Tcl_ChannelBuffered -- * * Returns the number of bytes of input currently buffered in the * internal buffer (push back area) of a channel. * * Results: * The number of input bytes buffered, or zero if the channel is not open * for reading. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_ChannelBuffered( Tcl_Channel chan) /* The channel to query. */ { Channel *chanPtr = (Channel *) chan; /* Real channel structure. */ ChannelBuffer *bufPtr; int bytesBuffered = 0; for (bufPtr = chanPtr->inQueueHead; bufPtr != NULL; bufPtr = bufPtr->nextPtr) { bytesBuffered += BytesLeft(bufPtr); } return bytesBuffered; } /* *---------------------------------------------------------------------- * * Tcl_SetChannelBufferSize -- * * Sets the size of buffers to allocate to store input or output in the * channel. The size must be between 1 byte and 1 MByte. * * Results: * None. * * Side effects: * Sets the size of buffers subsequently allocated for this channel. * *---------------------------------------------------------------------- */ void Tcl_SetChannelBufferSize( Tcl_Channel chan, /* The channel whose buffer size to set. */ int sz) /* The size to set. */ { ChannelState *statePtr; /* State of real channel structure. */ /* * Clip the buffer size to force it into the [1,1M] range */ if (sz < 1) { sz = 1; } else if (sz > MAX_CHANNEL_BUFFER_SIZE) { sz = MAX_CHANNEL_BUFFER_SIZE; } statePtr = ((Channel *) chan)->state; if (statePtr->bufSize == sz) { return; } statePtr->bufSize = sz; /* * If bufsize changes, need to get rid of old utility buffer. */ if (statePtr->saveInBufPtr != NULL) { RecycleBuffer(statePtr, statePtr->saveInBufPtr, 1); statePtr->saveInBufPtr = NULL; } if ((statePtr->inQueueHead != NULL) && (statePtr->inQueueHead->nextPtr == NULL) && IsBufferEmpty(statePtr->inQueueHead)) { RecycleBuffer(statePtr, statePtr->inQueueHead, 1); statePtr->inQueueHead = NULL; statePtr->inQueueTail = NULL; } } /* *---------------------------------------------------------------------- * * Tcl_GetChannelBufferSize -- * * Retrieves the size of buffers to allocate for this channel. * * Results: * The size. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetChannelBufferSize( Tcl_Channel chan) /* The channel for which to find the buffer * size. */ { ChannelState *statePtr = ((Channel *) chan)->state; /* State of real channel structure. */ return statePtr->bufSize; } /* *---------------------------------------------------------------------- * * Tcl_BadChannelOption -- * * This procedure generates a "bad option" error message in an (optional) * interpreter. It is used by channel drivers when a invalid Set/Get * option is requested. Its purpose is to concatenate the generic options * list to the specific ones and factorize the generic options error * message string. * * Results: * TCL_ERROR. * * Side effects: * An error message is generated in interp's result object to indicate * that a command was invoked with the a bad option. The message has the * form: * bad option "blah": should be one of * <...generic options...>+<...specific options...> * "blah" is the optionName argument and "" is a space * separated list of specific option words. The function takes good care * of inserting minus signs before each option, commas after, and an "or" * before the last option. * *---------------------------------------------------------------------- */ int Tcl_BadChannelOption( Tcl_Interp *interp, /* Current interpreter (can be NULL).*/ const char *optionName, /* 'bad option' name */ const char *optionList) /* Specific options list to append to the * standard generic options. Can be NULL for * generic options only. */ { if (interp != NULL) { const char *genericopt = "blocking buffering buffersize encoding eofchar translation"; const char **argv; int argc, i; Tcl_DString ds; Tcl_Obj *errObj; Tcl_DStringInit(&ds); Tcl_DStringAppend(&ds, genericopt, -1); if (optionList && (*optionList)) { TclDStringAppendLiteral(&ds, " "); Tcl_DStringAppend(&ds, optionList, -1); } if (Tcl_SplitList(interp, Tcl_DStringValue(&ds), &argc, &argv) != TCL_OK) { Tcl_Panic("malformed option list in channel driver"); } Tcl_ResetResult(interp); errObj = Tcl_ObjPrintf("bad option \"%s\": should be one of ", optionName); argc--; for (i = 0; i < argc; i++) { Tcl_AppendPrintfToObj(errObj, "-%s, ", argv[i]); } Tcl_AppendPrintfToObj(errObj, "or -%s", argv[i]); Tcl_SetObjResult(interp, errObj); Tcl_DStringFree(&ds); ckfree(argv); } Tcl_SetErrno(EINVAL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_GetChannelOption -- * * Gets a mode associated with an IO channel. If the optionName arg is * non NULL, retrieves the value of that option. If the optionName arg is * NULL, retrieves a list of alternating option names and values for the * given channel. * * Results: * A standard Tcl result. Also sets the supplied DString to the string * value of the option(s) returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_GetChannelOption( Tcl_Interp *interp, /* For error reporting - can be NULL. */ Tcl_Channel chan, /* Channel on which to get option. */ const char *optionName, /* Option to get. */ Tcl_DString *dsPtr) /* Where to store value(s). */ { size_t len; /* Length of optionName string. */ char optionVal[128]; /* Buffer for sprintf. */ Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ int flags; /* * Disallow options on dead channels -- channels that have been closed but * not yet been deallocated. Such channels can be found if the exit * handler for channel cleanup has run but the channel is still registered * in an interpreter. */ if (CheckForDeadChannel(interp, statePtr)) { return TCL_ERROR; } /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; /* * If we are in the middle of a background copy, use the saved flags. */ if (statePtr->csPtrR) { flags = statePtr->csPtrR->readFlags; } else if (statePtr->csPtrW) { flags = statePtr->csPtrW->writeFlags; } else { flags = statePtr->flags; } /* * If the optionName is NULL it means that we want a list of all options * and values. */ if (optionName == NULL) { len = 0; } else { len = strlen(optionName); } if (len == 0 || HaveOpt(2, "-blocking")) { if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-blocking"); } Tcl_DStringAppendElement(dsPtr, (flags & CHANNEL_NONBLOCKING) ? "0" : "1"); if (len > 0) { return TCL_OK; } } if (len == 0 || HaveOpt(7, "-buffering")) { if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-buffering"); } if (flags & CHANNEL_LINEBUFFERED) { Tcl_DStringAppendElement(dsPtr, "line"); } else if (flags & CHANNEL_UNBUFFERED) { Tcl_DStringAppendElement(dsPtr, "none"); } else { Tcl_DStringAppendElement(dsPtr, "full"); } if (len > 0) { return TCL_OK; } } if (len == 0 || HaveOpt(7, "-buffersize")) { if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-buffersize"); } TclFormatInt(optionVal, statePtr->bufSize); Tcl_DStringAppendElement(dsPtr, optionVal); if (len > 0) { return TCL_OK; } } if (len == 0 || HaveOpt(2, "-encoding")) { if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-encoding"); } if (statePtr->encoding == NULL) { Tcl_DStringAppendElement(dsPtr, "binary"); } else { Tcl_DStringAppendElement(dsPtr, Tcl_GetEncodingName(statePtr->encoding)); } if (len > 0) { return TCL_OK; } } if (len == 0 || HaveOpt(2, "-eofchar")) { if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-eofchar"); } if (((flags & (TCL_READABLE|TCL_WRITABLE)) == (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) { Tcl_DStringStartSublist(dsPtr); } if (flags & TCL_READABLE) { if (statePtr->inEofChar == 0) { Tcl_DStringAppendElement(dsPtr, ""); } else { char buf[4]; sprintf(buf, "%c", statePtr->inEofChar); Tcl_DStringAppendElement(dsPtr, buf); } } if (flags & TCL_WRITABLE) { if (statePtr->outEofChar == 0) { Tcl_DStringAppendElement(dsPtr, ""); } else { char buf[4]; sprintf(buf, "%c", statePtr->outEofChar); Tcl_DStringAppendElement(dsPtr, buf); } } if (!(flags & (TCL_READABLE|TCL_WRITABLE))) { /* * Not readable or writable (e.g. server socket) */ Tcl_DStringAppendElement(dsPtr, ""); } if (((flags & (TCL_READABLE|TCL_WRITABLE)) == (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) { Tcl_DStringEndSublist(dsPtr); } if (len > 0) { return TCL_OK; } } if (len == 0 || HaveOpt(1, "-translation")) { if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-translation"); } if (((flags & (TCL_READABLE|TCL_WRITABLE)) == (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) { Tcl_DStringStartSublist(dsPtr); } if (flags & TCL_READABLE) { if (statePtr->inputTranslation == TCL_TRANSLATE_AUTO) { Tcl_DStringAppendElement(dsPtr, "auto"); } else if (statePtr->inputTranslation == TCL_TRANSLATE_CR) { Tcl_DStringAppendElement(dsPtr, "cr"); } else if (statePtr->inputTranslation == TCL_TRANSLATE_CRLF) { Tcl_DStringAppendElement(dsPtr, "crlf"); } else { Tcl_DStringAppendElement(dsPtr, "lf"); } } if (flags & TCL_WRITABLE) { if (statePtr->outputTranslation == TCL_TRANSLATE_AUTO) { Tcl_DStringAppendElement(dsPtr, "auto"); } else if (statePtr->outputTranslation == TCL_TRANSLATE_CR) { Tcl_DStringAppendElement(dsPtr, "cr"); } else if (statePtr->outputTranslation == TCL_TRANSLATE_CRLF) { Tcl_DStringAppendElement(dsPtr, "crlf"); } else { Tcl_DStringAppendElement(dsPtr, "lf"); } } if (!(flags & (TCL_READABLE|TCL_WRITABLE))) { /* * Not readable or writable (e.g. server socket) */ Tcl_DStringAppendElement(dsPtr, "auto"); } if (((flags & (TCL_READABLE|TCL_WRITABLE)) == (TCL_READABLE|TCL_WRITABLE)) && (len == 0)) { Tcl_DStringEndSublist(dsPtr); } if (len > 0) { return TCL_OK; } } if (chanPtr->typePtr->getOptionProc != NULL) { /* * Let the driver specific handle additional options and result code * and message. */ return chanPtr->typePtr->getOptionProc(chanPtr->instanceData, interp, optionName, dsPtr); } else { /* * No driver specific options case. */ if (len == 0) { return TCL_OK; } return Tcl_BadChannelOption(interp, optionName, NULL); } } /* *--------------------------------------------------------------------------- * * Tcl_SetChannelOption -- * * Sets an option on a channel. * * Results: * A standard Tcl result. On error, sets interp's result object if * interp is not NULL. * * Side effects: * May modify an option on a device. * *--------------------------------------------------------------------------- */ int Tcl_SetChannelOption( Tcl_Interp *interp, /* For error reporting - can be NULL. */ Tcl_Channel chan, /* Channel on which to set mode. */ const char *optionName, /* Which option to set? */ const char *newValue) /* New value for option. */ { Channel *chanPtr = (Channel *) chan; /* The real IO channel. */ ChannelState *statePtr = chanPtr->state; /* State info for channel */ size_t len; /* Length of optionName string. */ int argc; const char **argv; /* * If the channel is in the middle of a background copy, fail. */ if (statePtr->csPtrR || statePtr->csPtrW) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unable to set channel options: background copy in" " progress", -1)); } return TCL_ERROR; } /* * Disallow options on dead channels -- channels that have been closed but * not yet been deallocated. Such channels can be found if the exit * handler for channel cleanup has run but the channel is still registered * in an interpreter. */ if (CheckForDeadChannel(NULL, statePtr)) { return TCL_ERROR; } /* * This operation should occur at the top of a channel stack. */ chanPtr = statePtr->topChanPtr; len = strlen(optionName); if (HaveOpt(2, "-blocking")) { int newMode; if (Tcl_GetBoolean(interp, newValue, &newMode) == TCL_ERROR) { return TCL_ERROR; } if (newMode) { newMode = TCL_MODE_BLOCKING; } else { newMode = TCL_MODE_NONBLOCKING; } return SetBlockMode(interp, chanPtr, newMode); } else if (HaveOpt(7, "-buffering")) { len = strlen(newValue); if ((newValue[0] == 'f') && (strncmp(newValue, "full", len) == 0)) { ResetFlag(statePtr, CHANNEL_UNBUFFERED | CHANNEL_LINEBUFFERED); } else if ((newValue[0] == 'l') && (strncmp(newValue, "line", len) == 0)) { ResetFlag(statePtr, CHANNEL_UNBUFFERED); SetFlag(statePtr, CHANNEL_LINEBUFFERED); } else if ((newValue[0] == 'n') && (strncmp(newValue, "none", len) == 0)) { ResetFlag(statePtr, CHANNEL_LINEBUFFERED); SetFlag(statePtr, CHANNEL_UNBUFFERED); } else if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad value for -buffering: must be one of" " full, line, or none", -1)); return TCL_ERROR; } return TCL_OK; } else if (HaveOpt(7, "-buffersize")) { int newBufferSize; if (Tcl_GetInt(interp, newValue, &newBufferSize) == TCL_ERROR) { return TCL_ERROR; } Tcl_SetChannelBufferSize(chan, newBufferSize); return TCL_OK; } else if (HaveOpt(2, "-encoding")) { Tcl_Encoding encoding; if ((newValue[0] == '\0') || (strcmp(newValue, "binary") == 0)) { encoding = NULL; } else { encoding = Tcl_GetEncoding(interp, newValue); if (encoding == NULL) { return TCL_ERROR; } } /* * When the channel has an escape sequence driven encoding such as * iso2022, the terminated escape sequence must write to the buffer. */ if ((statePtr->encoding != NULL) && !(statePtr->outputEncodingFlags & TCL_ENCODING_START) && (CheckChannelErrors(statePtr, TCL_WRITABLE) == 0)) { statePtr->outputEncodingFlags |= TCL_ENCODING_END; WriteChars(chanPtr, "", 0); } Tcl_FreeEncoding(statePtr->encoding); statePtr->encoding = encoding; statePtr->inputEncodingState = NULL; statePtr->inputEncodingFlags = TCL_ENCODING_START; statePtr->outputEncodingState = NULL; statePtr->outputEncodingFlags = TCL_ENCODING_START; ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA); UpdateInterest(chanPtr); return TCL_OK; } else if (HaveOpt(2, "-eofchar")) { if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } if (argc == 0) { statePtr->inEofChar = 0; statePtr->outEofChar = 0; } else if (argc == 1 || argc == 2) { int outIndex = (argc - 1); int inValue = (int) argv[0][0]; int outValue = (int) argv[outIndex][0]; if (inValue & 0x80 || outValue & 0x80) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad value for -eofchar: must be non-NUL ASCII" " character", -1)); } ckfree(argv); return TCL_ERROR; } if (GotFlag(statePtr, TCL_READABLE)) { statePtr->inEofChar = inValue; } if (GotFlag(statePtr, TCL_WRITABLE)) { statePtr->outEofChar = outValue; } } else { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad value for -eofchar: should be a list of zero," " one, or two elements", -1)); } ckfree(argv); return TCL_ERROR; } if (argv != NULL) { ckfree(argv); } /* * [Bug 930851] Reset EOF and BLOCKED flags. Changing the character * which signals eof can transform a current eof condition into a 'go * ahead'. Ditto for blocked. */ if (GotFlag(statePtr, CHANNEL_EOF)) { statePtr->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(statePtr, CHANNEL_EOF|CHANNEL_STICKY_EOF|CHANNEL_BLOCKED); statePtr->inputEncodingFlags &= ~TCL_ENCODING_END; return TCL_OK; } else if (HaveOpt(1, "-translation")) { const char *readMode, *writeMode; if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) { return TCL_ERROR; } if (argc == 1) { readMode = GotFlag(statePtr, TCL_READABLE) ? argv[0] : NULL; writeMode = GotFlag(statePtr, TCL_WRITABLE) ? argv[0] : NULL; } else if (argc == 2) { readMode = GotFlag(statePtr, TCL_READABLE) ? argv[0] : NULL; writeMode = GotFlag(statePtr, TCL_WRITABLE) ? argv[1] : NULL; } else { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad value for -translation: must be a one or two" " element list", -1)); } ckfree(argv); return TCL_ERROR; } if (readMode) { TclEolTranslation translation; if (*readMode == '\0') { translation = statePtr->inputTranslation; } else if (strcmp(readMode, "auto") == 0) { translation = TCL_TRANSLATE_AUTO; } else if (strcmp(readMode, "binary") == 0) { translation = TCL_TRANSLATE_LF; statePtr->inEofChar = 0; Tcl_FreeEncoding(statePtr->encoding); statePtr->encoding = NULL; } else if (strcmp(readMode, "lf") == 0) { translation = TCL_TRANSLATE_LF; } else if (strcmp(readMode, "cr") == 0) { translation = TCL_TRANSLATE_CR; } else if (strcmp(readMode, "crlf") == 0) { translation = TCL_TRANSLATE_CRLF; } else if (strcmp(readMode, "platform") == 0) { translation = TCL_PLATFORM_TRANSLATION; } else { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad value for -translation: must be one of " "auto, binary, cr, lf, crlf, or platform", -1)); } ckfree(argv); return TCL_ERROR; } /* * Reset the EOL flags since we need to look at any buffered data * to see if the new translation mode allows us to complete the * line. */ if (translation != statePtr->inputTranslation) { statePtr->inputTranslation = translation; ResetFlag(statePtr, INPUT_SAW_CR | CHANNEL_NEED_MORE_DATA); UpdateInterest(chanPtr); } } if (writeMode) { if (*writeMode == '\0') { /* Do nothing. */ } else if (strcmp(writeMode, "auto") == 0) { /* * This is a hack to get TCP sockets to produce output in CRLF * mode if they are being set into AUTO mode. A better * solution for achieving this effect will be coded later. */ if (strcmp(Tcl_ChannelName(chanPtr->typePtr), "tcp") == 0) { statePtr->outputTranslation = TCL_TRANSLATE_CRLF; } else { statePtr->outputTranslation = TCL_PLATFORM_TRANSLATION; } } else if (strcmp(writeMode, "binary") == 0) { statePtr->outEofChar = 0; statePtr->outputTranslation = TCL_TRANSLATE_LF; Tcl_FreeEncoding(statePtr->encoding); statePtr->encoding = NULL; } else if (strcmp(writeMode, "lf") == 0) { statePtr->outputTranslation = TCL_TRANSLATE_LF; } else if (strcmp(writeMode, "cr") == 0) { statePtr->outputTranslation = TCL_TRANSLATE_CR; } else if (strcmp(writeMode, "crlf") == 0) { statePtr->outputTranslation = TCL_TRANSLATE_CRLF; } else if (strcmp(writeMode, "platform") == 0) { statePtr->outputTranslation = TCL_PLATFORM_TRANSLATION; } else { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "bad value for -translation: must be one of " "auto, binary, cr, lf, crlf, or platform", -1)); } ckfree(argv); return TCL_ERROR; } } ckfree(argv); return TCL_OK; } else if (chanPtr->typePtr->setOptionProc != NULL) { return chanPtr->typePtr->setOptionProc(chanPtr->instanceData, interp, optionName, newValue); } else { return Tcl_BadChannelOption(interp, optionName, NULL); } return TCL_OK; } /* *---------------------------------------------------------------------- * * CleanupChannelHandlers -- * * Removes channel handlers that refer to the supplied interpreter, so * that if the actual channel is not closed now, these handlers will not * run on subsequent events on the channel. This would be erroneous, * because the interpreter no longer has a reference to this channel. * * Results: * None. * * Side effects: * Removes channel handlers. * *---------------------------------------------------------------------- */ static void CleanupChannelHandlers( Tcl_Interp *interp, Channel *chanPtr) { ChannelState *statePtr = chanPtr->state; /* State info for channel */ EventScriptRecord *sPtr, *prevPtr, *nextPtr; /* * Remove fileevent records on this channel that refer to the given * interpreter. */ for (sPtr = statePtr->scriptRecordPtr, prevPtr = NULL; sPtr != NULL; sPtr = nextPtr) { nextPtr = sPtr->nextPtr; if (sPtr->interp == interp) { if (prevPtr == NULL) { statePtr->scriptRecordPtr = nextPtr; } else { prevPtr->nextPtr = nextPtr; } Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, TclChannelEventScriptInvoker, sPtr); TclDecrRefCount(sPtr->scriptPtr); ckfree(sPtr); } else { prevPtr = sPtr; } } } /* *---------------------------------------------------------------------- * * Tcl_NotifyChannel -- * * This procedure is called by a channel driver when a driver detects an * event on a channel. This procedure is responsible for actually * handling the event by invoking any channel handler callbacks. * * Results: * None. * * Side effects: * Whatever the channel handler callback procedure does. * *---------------------------------------------------------------------- */ void Tcl_NotifyChannel( Tcl_Channel channel, /* Channel that detected an event. */ int mask) /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, or TCL_EXCEPTION: indicates * which events were detected. */ { Channel *chanPtr = (Channel *) channel; ChannelState *statePtr = chanPtr->state; /* State info for channel */ ChannelHandler *chPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); NextChannelHandler nh; Channel *upChanPtr; const Tcl_ChannelType *upTypePtr; /* * In contrast to the other API functions this procedure walks towards the * top of a stack and not down from it. * * The channel calling this procedure is the one who generated the event, * and thus does not take part in handling it. IOW, its HandlerProc is not * called, instead we begin with the channel above it. * * This behaviour also allows the transformation channels to generate * their own events and pass them upward. */ while (mask && (chanPtr->upChanPtr != NULL)) { Tcl_DriverHandlerProc *upHandlerProc; upChanPtr = chanPtr->upChanPtr; upTypePtr = upChanPtr->typePtr; upHandlerProc = Tcl_ChannelHandlerProc(upTypePtr); if (upHandlerProc != NULL) { mask = upHandlerProc(upChanPtr->instanceData, mask); } /* * ELSE: Ignore transformations which are unable to handle the event * coming from below. Assume that they don't change the mask and pass * it on. */ chanPtr = upChanPtr; } channel = (Tcl_Channel) chanPtr; /* * Here we have either reached the top of the stack or the mask is empty. * We break out of the procedure if it is the latter. */ if (!mask) { return; } /* * We are now above the topmost channel in a stack and have events left. * Now call the channel handlers as usual. * * Preserve the channel struct in case the script closes it. */ TclChannelPreserve((Tcl_Channel)channel); Tcl_Preserve(statePtr); /* * If we are flushing in the background, be sure to call FlushChannel for * writable events. Note that we have to discard the writable event so we * don't call any write handlers before the flush is complete. */ if (GotFlag(statePtr, BG_FLUSH_SCHEDULED) && (mask & TCL_WRITABLE)) { if (0 == FlushChannel(NULL, chanPtr, 1)) { mask &= ~TCL_WRITABLE; } } /* * Add this invocation to the list of recursive invocations of * Tcl_NotifyChannel. */ nh.nextHandlerPtr = NULL; nh.nestedHandlerPtr = tsdPtr->nestedHandlerPtr; tsdPtr->nestedHandlerPtr = &nh; for (chPtr = statePtr->chPtr; chPtr != NULL; ) { /* * If this channel handler is interested in any of the events that * have occurred on the channel, invoke its procedure. */ if ((chPtr->mask & mask) != 0) { nh.nextHandlerPtr = chPtr->nextPtr; chPtr->proc(chPtr->clientData, chPtr->mask & mask); chPtr = nh.nextHandlerPtr; } else { chPtr = chPtr->nextPtr; } } /* * Update the notifier interest, since it may have changed after invoking * event handlers. Skip that if the channel was deleted in the call to the * channel handler. */ if (chanPtr->typePtr != NULL) { /* * TODO: This call may not be needed. If a handler induced a * change in interest, that handler should have made its own * UpdateInterest() call, one would think. */ UpdateInterest(chanPtr); } Tcl_Release(statePtr); TclChannelRelease(channel); tsdPtr->nestedHandlerPtr = nh.nestedHandlerPtr; } /* *---------------------------------------------------------------------- * * UpdateInterest -- * * Arrange for the notifier to call us back at appropriate times based on * the current state of the channel. * * Results: * None. * * Side effects: * May schedule a timer or driver handler. * *---------------------------------------------------------------------- */ static void UpdateInterest( Channel *chanPtr) /* Channel to update. */ { ChannelState *statePtr = chanPtr->state; /* State info for channel */ int mask = statePtr->interestMask; if (chanPtr->typePtr == NULL) { /* Do not update interest on a closed channel */ return; } /* * If there are flushed buffers waiting to be written, then we need to * watch for the channel to become writable. */ if (GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { mask |= TCL_WRITABLE; } /* * If there is data in the input queue, and we aren't waiting for more * data, then we need to schedule a timer so we don't block in the * notifier. Also, cancel the read interest so we don't get duplicate * events. */ if (mask & TCL_READABLE) { if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA) && (statePtr->inQueueHead != NULL) && IsBufferReady(statePtr->inQueueHead)) { mask &= ~TCL_READABLE; /* * Andreas Kupries, April 11, 2003 * * Some operating systems (Solaris 2.6 and higher (but not Solaris * 2.5, go figure)) generate READABLE and EXCEPTION events when * select()'ing [*] on a plain file, even if EOF was not yet * reached. This is a problem in the following situation: * * - An extension asks to get both READABLE and EXCEPTION events. * - It reads data into a buffer smaller than the buffer used by * Tcl itself. * - It does not process all events in the event queue, but only * one, at least in some situations. * * In that case we can get into a situation where * * - Tcl drops READABLE here, because it has data in its own * buffers waiting to be read by the extension. * - A READABLE event is syntesized via timer. * - The OS still reports the EXCEPTION condition on the file. * - And the extension gets the EXCPTION event first, and handles * this as EOF. * * End result ==> Premature end of reading from a file. * * The concrete example is 'Expect', and its [expect] command * (and at the C-level, deep in the bowels of Expect, * 'exp_get_next_event'. See marker 'SunOS' for commentary in * that function too). * * [*] As the Tcl notifier does. See also for marker 'SunOS' in * file 'exp_event.c' of Expect. * * Our solution here is to drop the interest in the EXCEPTION * events too. This compiles on all platforms, and also passes the * testsuite on all of them. */ mask &= ~TCL_EXCEPTION; if (!statePtr->timer) { statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ChannelTimerProc, chanPtr); } } } ChanWatch(chanPtr, mask); } /* *---------------------------------------------------------------------- * * ChannelTimerProc -- * * Timer handler scheduled by UpdateInterest to monitor the channel * buffers until they are empty. * * Results: * None. * * Side effects: * May invoke channel handlers. * *---------------------------------------------------------------------- */ static void ChannelTimerProc( ClientData clientData) { Channel *chanPtr = clientData; ChannelState *statePtr = chanPtr->state; /* State info for channel */ if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA) && (statePtr->interestMask & TCL_READABLE) && (statePtr->inQueueHead != NULL) && IsBufferReady(statePtr->inQueueHead)) { /* * Restart the timer in case a channel handler reenters the event loop * before UpdateInterest gets called by Tcl_NotifyChannel. */ statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ChannelTimerProc,chanPtr); Tcl_Preserve(statePtr); Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_READABLE); Tcl_Release(statePtr); } else { statePtr->timer = NULL; UpdateInterest(chanPtr); } } /* *---------------------------------------------------------------------- * * Tcl_CreateChannelHandler -- * * Arrange for a given procedure to be invoked whenever the channel * indicated by the chanPtr arg becomes readable or writable. * * Results: * None. * * Side effects: * From now on, whenever the I/O channel given by chanPtr becomes ready * in the way indicated by mask, proc will be invoked. See the manual * entry for details on the calling sequence to proc. If there is already * an event handler for chan, proc and clientData, then the mask will be * updated. * *---------------------------------------------------------------------- */ void Tcl_CreateChannelHandler( Tcl_Channel chan, /* The channel to create the handler for. */ int mask, /* OR'ed combination of TCL_READABLE, * TCL_WRITABLE, and TCL_EXCEPTION: indicates * conditions under which proc should be * called. Use 0 to disable a registered * handler. */ Tcl_ChannelProc *proc, /* Procedure to call for each selected * event. */ ClientData clientData) /* Arbitrary data to pass to proc. */ { ChannelHandler *chPtr; Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ /* * Check whether this channel handler is not already registered. If it is * not, create a new record, else reuse existing record (smash current * values). */ for (chPtr = statePtr->chPtr; chPtr != NULL; chPtr = chPtr->nextPtr) { if ((chPtr->chanPtr == chanPtr) && (chPtr->proc == proc) && (chPtr->clientData == clientData)) { break; } } if (chPtr == NULL) { chPtr = ckalloc(sizeof(ChannelHandler)); chPtr->mask = 0; chPtr->proc = proc; chPtr->clientData = clientData; chPtr->chanPtr = chanPtr; chPtr->nextPtr = statePtr->chPtr; statePtr->chPtr = chPtr; } /* * The remainder of the initialization below is done regardless of whether * or not this is a new record or a modification of an old one. */ chPtr->mask = mask; /* * Recompute the interest mask for the channel - this call may actually be * disabling an existing handler. */ statePtr->interestMask = 0; for (chPtr = statePtr->chPtr; chPtr != NULL; chPtr = chPtr->nextPtr) { statePtr->interestMask |= chPtr->mask; } UpdateInterest(statePtr->topChanPtr); } /* *---------------------------------------------------------------------- * * Tcl_DeleteChannelHandler -- * * Cancel a previously arranged callback arrangement for an IO channel. * * Results: * None. * * Side effects: * If a callback was previously registered for this chan, proc and * clientData, it is removed and the callback will no longer be called * when the channel becomes ready for IO. * *---------------------------------------------------------------------- */ void Tcl_DeleteChannelHandler( Tcl_Channel chan, /* The channel for which to remove the * callback. */ Tcl_ChannelProc *proc, /* The procedure in the callback to delete. */ ClientData clientData) /* The client data in the callback to * delete. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ChannelHandler *chPtr, *prevChPtr; Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ NextChannelHandler *nhPtr; /* * Find the entry and the previous one in the list. */ for (prevChPtr = NULL, chPtr = statePtr->chPtr; chPtr != NULL; chPtr = chPtr->nextPtr) { if ((chPtr->chanPtr == chanPtr) && (chPtr->clientData == clientData) && (chPtr->proc == proc)) { break; } prevChPtr = chPtr; } /* * If not found, return without doing anything. */ if (chPtr == NULL) { return; } /* * If Tcl_NotifyChannel is about to process this handler, tell it to * process the next one instead - we are going to delete *this* one. */ for (nhPtr = tsdPtr->nestedHandlerPtr; nhPtr != NULL; nhPtr = nhPtr->nestedHandlerPtr) { if (nhPtr->nextHandlerPtr == chPtr) { nhPtr->nextHandlerPtr = chPtr->nextPtr; } } /* * Splice it out of the list of channel handlers. */ if (prevChPtr == NULL) { statePtr->chPtr = chPtr->nextPtr; } else { prevChPtr->nextPtr = chPtr->nextPtr; } ckfree(chPtr); /* * Recompute the interest list for the channel, so that infinite loops * will not result if Tcl_DeleteChannelHandler is called inside an event. */ statePtr->interestMask = 0; for (chPtr = statePtr->chPtr; chPtr != NULL; chPtr = chPtr->nextPtr) { statePtr->interestMask |= chPtr->mask; } UpdateInterest(statePtr->topChanPtr); } /* *---------------------------------------------------------------------- * * DeleteScriptRecord -- * * Delete a script record for this combination of channel, interp and * mask. * * Results: * None. * * Side effects: * Deletes a script record and cancels a channel event handler. * *---------------------------------------------------------------------- */ static void DeleteScriptRecord( Tcl_Interp *interp, /* Interpreter in which script was to be * executed. */ Channel *chanPtr, /* The channel for which to delete the script * record (if any). */ int mask) /* Events in mask must exactly match mask of * script to delete. */ { ChannelState *statePtr = chanPtr->state; /* State info for channel */ EventScriptRecord *esPtr, *prevEsPtr; for (esPtr = statePtr->scriptRecordPtr, prevEsPtr = NULL; esPtr != NULL; prevEsPtr = esPtr, esPtr = esPtr->nextPtr) { if ((esPtr->interp == interp) && (esPtr->mask == mask)) { if (esPtr == statePtr->scriptRecordPtr) { statePtr->scriptRecordPtr = esPtr->nextPtr; } else { CLANG_ASSERT(prevEsPtr); prevEsPtr->nextPtr = esPtr->nextPtr; } Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, TclChannelEventScriptInvoker, esPtr); TclDecrRefCount(esPtr->scriptPtr); ckfree(esPtr); break; } } } /* *---------------------------------------------------------------------- * * CreateScriptRecord -- * * Creates a record to store a script to be executed when a specific * event fires on a specific channel. * * Results: * None. * * Side effects: * Causes the script to be stored for later execution. * *---------------------------------------------------------------------- */ static void CreateScriptRecord( Tcl_Interp *interp, /* Interpreter in which to execute the stored * script. */ Channel *chanPtr, /* Channel for which script is to be stored */ int mask, /* Set of events for which script will be * invoked. */ Tcl_Obj *scriptPtr) /* Pointer to script object. */ { ChannelState *statePtr = chanPtr->state; /* State info for channel */ EventScriptRecord *esPtr; int makeCH; for (esPtr=statePtr->scriptRecordPtr; esPtr!=NULL; esPtr=esPtr->nextPtr) { if ((esPtr->interp == interp) && (esPtr->mask == mask)) { TclDecrRefCount(esPtr->scriptPtr); esPtr->scriptPtr = NULL; break; } } makeCH = (esPtr == NULL); if (makeCH) { esPtr = ckalloc(sizeof(EventScriptRecord)); } /* * Initialize the structure before calling Tcl_CreateChannelHandler, * because a reflected channel calling 'chan postevent' aka * 'Tcl_NotifyChannel' in its 'watch'Proc will invoke * 'TclChannelEventScriptInvoker' immediately, and we do not wish it to * see uninitialized memory and crash. See [Bug 2918110]. */ esPtr->chanPtr = chanPtr; esPtr->interp = interp; esPtr->mask = mask; Tcl_IncrRefCount(scriptPtr); esPtr->scriptPtr = scriptPtr; if (makeCH) { esPtr->nextPtr = statePtr->scriptRecordPtr; statePtr->scriptRecordPtr = esPtr; Tcl_CreateChannelHandler((Tcl_Channel) chanPtr, mask, TclChannelEventScriptInvoker, esPtr); } } /* *---------------------------------------------------------------------- * * TclChannelEventScriptInvoker -- * * Invokes a script scheduled by "fileevent" for when the channel becomes * ready for IO. This function is invoked by the channel handler which * was created by the Tcl "fileevent" command. * * Results: * None. * * Side effects: * Whatever the script does. * *---------------------------------------------------------------------- */ void TclChannelEventScriptInvoker( ClientData clientData, /* The script+interp record. */ int mask) /* Not used. */ { Tcl_Interp *interp; /* Interpreter in which to eval the script. */ Channel *chanPtr; /* The channel for which this handler is * registered. */ EventScriptRecord *esPtr; /* The event script + interpreter to eval it * in. */ int result; /* Result of call to eval script. */ esPtr = clientData; chanPtr = esPtr->chanPtr; mask = esPtr->mask; interp = esPtr->interp; /* * We must preserve the interpreter so we can report errors on it later. * Note that we do not need to preserve the channel because that is done * by Tcl_NotifyChannel before calling channel handlers. */ Tcl_Preserve(interp); TclChannelPreserve((Tcl_Channel)chanPtr); result = Tcl_EvalObjEx(interp, esPtr->scriptPtr, TCL_EVAL_GLOBAL); /* * On error, cause a background error and remove the channel handler and * the script record. * * NOTE: Must delete channel handler before causing the background error * because the background error may want to reinstall the handler. */ if (result != TCL_OK) { if (chanPtr->typePtr != NULL) { DeleteScriptRecord(interp, chanPtr, mask); } Tcl_BackgroundException(interp, result); } TclChannelRelease((Tcl_Channel)chanPtr); Tcl_Release(interp); } /* *---------------------------------------------------------------------- * * Tcl_FileEventObjCmd -- * * This procedure implements the "fileevent" Tcl command. See the user * documentation for details on what it does. This command is based on * the Tk command "fileevent" which in turn is based on work contributed * by Mark Diekhans. * * Results: * A standard Tcl result. * * Side effects: * May create a channel handler for the specified channel. * *---------------------------------------------------------------------- */ /* ARGSUSED */ int Tcl_FileEventObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Interpreter in which the channel for which * to create the handler is found. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Channel *chanPtr; /* The channel to create the handler for. */ ChannelState *statePtr; /* State info for channel */ Tcl_Channel chan; /* The opaque type for the channel. */ const char *chanName; int modeIndex; /* Index of mode argument. */ int mask; static const char *const modeOptions[] = {"readable", "writable", NULL}; static const int maskArray[] = {TCL_READABLE, TCL_WRITABLE}; if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 1, objv, "channelId event ?script?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[2], modeOptions, "event name", 0, &modeIndex) != TCL_OK) { return TCL_ERROR; } mask = maskArray[modeIndex]; chanName = TclGetString(objv[1]); chan = Tcl_GetChannel(interp, chanName, NULL); if (chan == NULL) { return TCL_ERROR; } chanPtr = (Channel *) chan; statePtr = chanPtr->state; if ((statePtr->flags & mask) == 0) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("channel is not %s", (mask == TCL_READABLE) ? "readable" : "writable")); return TCL_ERROR; } /* * If we are supposed to return the script, do so. */ if (objc == 3) { EventScriptRecord *esPtr; for (esPtr = statePtr->scriptRecordPtr; esPtr != NULL; esPtr = esPtr->nextPtr) { if ((esPtr->interp == interp) && (esPtr->mask == mask)) { Tcl_SetObjResult(interp, esPtr->scriptPtr); break; } } return TCL_OK; } /* * If we are supposed to delete a stored script, do so. */ if (*(TclGetString(objv[3])) == '\0') { DeleteScriptRecord(interp, chanPtr, mask); return TCL_OK; } /* * Make the script record that will link between the event and the script * to invoke. This also creates a channel event handler which will * evaluate the script in the supplied interpreter. */ CreateScriptRecord(interp, chanPtr, mask, objv[3]); return TCL_OK; } /* *---------------------------------------------------------------------- * * ZeroTransferTimerProc -- * * Timer handler scheduled by TclCopyChannel so that -command is * called asynchronously even when -size is 0. * * Results: * None. * * Side effects: * Calls CopyData for -command invocation. * *---------------------------------------------------------------------- */ static void ZeroTransferTimerProc( ClientData clientData) { /* calling CopyData with mask==0 still implies immediate invocation of the * -command callback, and completion of the fcopy. */ CopyData(clientData, 0); } /* *---------------------------------------------------------------------- * * TclCopyChannel -- * * This routine copies data from one channel to another, either * synchronously or asynchronously. If a command script is supplied, the * operation runs in the background. The script is invoked when the copy * completes. Otherwise the function waits until the copy is completed * before returning. * * Results: * A standard Tcl result. * * Side effects: * May schedule a background copy operation that causes both channels to * be marked busy. * *---------------------------------------------------------------------- */ int TclCopyChannelOld( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Channel inChan, /* Channel to read from. */ Tcl_Channel outChan, /* Channel to write to. */ int toRead, /* Amount of data to copy, or -1 for all. */ Tcl_Obj *cmdPtr) /* Pointer to script to execute or NULL. */ { return TclCopyChannel(interp, inChan, outChan, (Tcl_WideInt) toRead, cmdPtr); } int TclCopyChannel( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Channel inChan, /* Channel to read from. */ Tcl_Channel outChan, /* Channel to write to. */ Tcl_WideInt toRead, /* Amount of data to copy, or -1 for all. */ Tcl_Obj *cmdPtr) /* Pointer to script to execute or NULL. */ { Channel *inPtr = (Channel *) inChan; Channel *outPtr = (Channel *) outChan; ChannelState *inStatePtr, *outStatePtr; int readFlags, writeFlags; CopyState *csPtr; int nonBlocking = (cmdPtr) ? CHANNEL_NONBLOCKING : 0; int moveBytes; inStatePtr = inPtr->state; outStatePtr = outPtr->state; if (BUSY_STATE(inStatePtr, TCL_READABLE)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel \"%s\" is busy", Tcl_GetChannelName(inChan))); } return TCL_ERROR; } if (BUSY_STATE(outStatePtr, TCL_WRITABLE)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "channel \"%s\" is busy", Tcl_GetChannelName(outChan))); } return TCL_ERROR; } readFlags = inStatePtr->flags; writeFlags = outStatePtr->flags; /* * Set up the blocking mode appropriately. Background copies need * non-blocking channels. Foreground copies need blocking channels. If * there is an error, restore the old blocking mode. */ if (nonBlocking != (readFlags & CHANNEL_NONBLOCKING)) { if (SetBlockMode(interp, inPtr, nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING) != TCL_OK) { return TCL_ERROR; } } if ((inPtr!=outPtr) && (nonBlocking!=(writeFlags&CHANNEL_NONBLOCKING)) && (SetBlockMode(NULL, outPtr, nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING) != TCL_OK) && (nonBlocking != (readFlags & CHANNEL_NONBLOCKING))) { SetBlockMode(NULL, inPtr, (readFlags & CHANNEL_NONBLOCKING) ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING); return TCL_ERROR; } /* * Make sure the output side is unbuffered. */ outStatePtr->flags = (outStatePtr->flags & ~CHANNEL_LINEBUFFERED) | CHANNEL_UNBUFFERED; /* * Test for conditions where we know we can just move bytes from input * channel to output channel with no transformation or even examination * of the bytes themselves. */ moveBytes = inStatePtr->inEofChar == '\0' /* No eofChar to stop input */ && inStatePtr->inputTranslation == TCL_TRANSLATE_LF && outStatePtr->outputTranslation == TCL_TRANSLATE_LF && inStatePtr->encoding == outStatePtr->encoding; /* * Allocate a new CopyState to maintain info about the current copy in * progress. This structure will be deallocated when the copy is * completed. */ csPtr = ckalloc(sizeof(CopyState) + !moveBytes * inStatePtr->bufSize); csPtr->bufSize = !moveBytes * inStatePtr->bufSize; csPtr->readPtr = inPtr; csPtr->writePtr = outPtr; csPtr->readFlags = readFlags; csPtr->writeFlags = writeFlags; csPtr->toRead = toRead; csPtr->total = (Tcl_WideInt) 0; csPtr->interp = interp; if (cmdPtr) { Tcl_IncrRefCount(cmdPtr); } csPtr->cmdPtr = cmdPtr; inStatePtr->csPtrR = csPtr; outStatePtr->csPtrW = csPtr; if (moveBytes) { return MoveBytes(csPtr); } /* * Special handling of -size 0 async transfers, so that the -command is * still called asynchronously. */ if ((nonBlocking == CHANNEL_NONBLOCKING) && (toRead == 0)) { Tcl_CreateTimerHandler(0, ZeroTransferTimerProc, csPtr); return 0; } /* * Start copying data between the channels. */ return CopyData(csPtr, 0); } /* *---------------------------------------------------------------------- * * CopyData -- * * This function implements the lowest level of the copying mechanism for * TclCopyChannel. * * Results: * Returns TCL_OK on success, else TCL_ERROR. * * Side effects: * Moves data between channels, may create channel handlers. * *---------------------------------------------------------------------- */ static void MBCallback( CopyState *csPtr, Tcl_Obj *errObj) { Tcl_Obj *cmdPtr = Tcl_DuplicateObj(csPtr->cmdPtr); Tcl_WideInt total = csPtr->total; Tcl_Interp *interp = csPtr->interp; int code; Tcl_IncrRefCount(cmdPtr); StopCopy(csPtr); /* TODO: What if cmdPtr is not a list?! */ Tcl_ListObjAppendElement(NULL, cmdPtr, Tcl_NewWideIntObj(total)); if (errObj) { Tcl_ListObjAppendElement(NULL, cmdPtr, errObj); } Tcl_Preserve(interp); code = Tcl_EvalObjEx(interp, cmdPtr, TCL_EVAL_GLOBAL); if (code != TCL_OK) { Tcl_BackgroundException(interp, code); } Tcl_Release(interp); TclDecrRefCount(cmdPtr); } static void MBError( CopyState *csPtr, int mask, int errorCode) { Tcl_Channel inChan = (Tcl_Channel) csPtr->readPtr; Tcl_Channel outChan = (Tcl_Channel) csPtr->writePtr; Tcl_Obj *errObj; Tcl_SetErrno(errorCode); errObj = Tcl_ObjPrintf( "error %sing \"%s\": %s", (mask & TCL_READABLE) ? "read" : "writ", Tcl_GetChannelName((mask & TCL_READABLE) ? inChan : outChan), Tcl_PosixError(csPtr->interp)); if (csPtr->cmdPtr) { MBCallback(csPtr, errObj); } else { Tcl_SetObjResult(csPtr->interp, errObj); StopCopy(csPtr); } } static void MBEvent( ClientData clientData, int mask) { CopyState *csPtr = (CopyState *) clientData; Tcl_Channel inChan = (Tcl_Channel) csPtr->readPtr; Tcl_Channel outChan = (Tcl_Channel) csPtr->writePtr; ChannelState *inStatePtr = csPtr->readPtr->state; if (mask & TCL_WRITABLE) { Tcl_DeleteChannelHandler(inChan, MBEvent, csPtr); Tcl_DeleteChannelHandler(outChan, MBEvent, csPtr); switch (MBWrite(csPtr)) { case TCL_OK: MBCallback(csPtr, NULL); break; case TCL_CONTINUE: Tcl_CreateChannelHandler(inChan, TCL_READABLE, MBEvent, csPtr); break; } } else if (mask & TCL_READABLE) { if (TCL_OK == MBRead(csPtr)) { /* When at least one full buffer is present, stop reading. */ if (IsBufferFull(inStatePtr->inQueueHead) || !Tcl_InputBlocked(inChan)) { Tcl_DeleteChannelHandler(inChan, MBEvent, csPtr); } /* Successful read -- set up to write the bytes we read */ Tcl_CreateChannelHandler(outChan, TCL_WRITABLE, MBEvent, csPtr); } } } static int MBRead( CopyState *csPtr) { ChannelState *inStatePtr = csPtr->readPtr->state; ChannelBuffer *bufPtr = inStatePtr->inQueueHead; int code; if (bufPtr && BytesLeft(bufPtr) > 0) { return TCL_OK; } code = GetInput(inStatePtr->topChanPtr); if (code == 0 || GotFlag(inStatePtr, CHANNEL_BLOCKED)) { return TCL_OK; } else { MBError(csPtr, TCL_READABLE, code); return TCL_ERROR; } } static int MBWrite( CopyState *csPtr) { ChannelState *inStatePtr = csPtr->readPtr->state; ChannelState *outStatePtr = csPtr->writePtr->state; ChannelBuffer *bufPtr = inStatePtr->inQueueHead; ChannelBuffer *tail = NULL; int code; Tcl_WideInt inBytes = 0; /* Count up number of bytes waiting in the input queue */ while (bufPtr) { inBytes += BytesLeft(bufPtr); tail = bufPtr; if (csPtr->toRead != -1 && csPtr->toRead < inBytes) { /* Queue has enough bytes to complete the copy */ break; } bufPtr = bufPtr->nextPtr; } if (bufPtr) { /* Split the overflowing buffer in two */ int extra = (int) (inBytes - csPtr->toRead); /* Note that going with int for extra assumes that inBytes is not too * much over toRead to require a wide itself. If that gets violated * then the calculations involving extra must be made wide too. * * Noted with Win32/MSVC debug build treating the warning (possible of * data in int64 to int conversion) as error. */ bufPtr = AllocChannelBuffer(extra); tail->nextAdded -= extra; memcpy(InsertPoint(bufPtr), InsertPoint(tail), extra); bufPtr->nextAdded += extra; bufPtr->nextPtr = tail->nextPtr; tail->nextPtr = NULL; inBytes = csPtr->toRead; } /* Update the byte counts */ if (csPtr->toRead != -1) { csPtr->toRead -= inBytes; } csPtr->total += inBytes; /* Move buffers from input to output channels */ if (outStatePtr->outQueueTail) { outStatePtr->outQueueTail->nextPtr = inStatePtr->inQueueHead; } else { outStatePtr->outQueueHead = inStatePtr->inQueueHead; } outStatePtr->outQueueTail = tail; inStatePtr->inQueueHead = bufPtr; if (inStatePtr->inQueueTail == tail) { inStatePtr->inQueueTail = bufPtr; } if (bufPtr == NULL) { inStatePtr->inQueueTail = NULL; } code = FlushChannel(csPtr->interp, outStatePtr->topChanPtr, 0); if (code) { MBError(csPtr, TCL_WRITABLE, code); return TCL_ERROR; } if (csPtr->toRead == 0 || GotFlag(inStatePtr, CHANNEL_EOF)) { return TCL_OK; } return TCL_CONTINUE; } static int MoveBytes( CopyState *csPtr) /* State of copy operation. */ { ChannelState *outStatePtr = csPtr->writePtr->state; ChannelBuffer *bufPtr = outStatePtr->curOutPtr; int errorCode; if (bufPtr && BytesLeft(bufPtr)) { /* If we start with unflushed bytes in the destination * channel, flush them out of the way first. */ errorCode = FlushChannel(csPtr->interp, outStatePtr->topChanPtr, 0); if (errorCode != 0) { MBError(csPtr, TCL_WRITABLE, errorCode); return TCL_ERROR; } } if (csPtr->cmdPtr) { Tcl_Channel inChan = (Tcl_Channel) csPtr->readPtr; Tcl_CreateChannelHandler(inChan, TCL_READABLE, MBEvent, csPtr); return TCL_OK; } while (1) { int code; if (TCL_ERROR == MBRead(csPtr)) { return TCL_ERROR; } code = MBWrite(csPtr); if (code == TCL_OK) { Tcl_SetObjResult(csPtr->interp, Tcl_NewWideIntObj(csPtr->total)); StopCopy(csPtr); return TCL_OK; } if (code == TCL_ERROR) { return TCL_ERROR; } /* code == TCL_CONTINUE --> continue the loop */ } return TCL_OK; /* Silence compiler warnings */ } static int CopyData( CopyState *csPtr, /* State of copy operation. */ int mask) /* Current channel event flags. */ { Tcl_Interp *interp; Tcl_Obj *cmdPtr, *errObj = NULL, *bufObj = NULL, *msg = NULL; Tcl_Channel inChan, outChan; ChannelState *inStatePtr, *outStatePtr; int result = TCL_OK, size, sizeb; Tcl_WideInt total; const char *buffer; int inBinary, outBinary, sameEncoding; /* Encoding control */ int underflow; /* Input underflow */ inChan = (Tcl_Channel) csPtr->readPtr; outChan = (Tcl_Channel) csPtr->writePtr; inStatePtr = csPtr->readPtr->state; outStatePtr = csPtr->writePtr->state; interp = csPtr->interp; cmdPtr = csPtr->cmdPtr; /* * Copy the data the slow way, using the translation mechanism. * * Note: We have make sure that we use the topmost channel in a stack for * the copying. The caller uses Tcl_GetChannel to access it, and thus gets * the bottom of the stack. */ inBinary = (inStatePtr->encoding == NULL); outBinary = (outStatePtr->encoding == NULL); sameEncoding = (inStatePtr->encoding == outStatePtr->encoding); if (!(inBinary || sameEncoding)) { TclNewObj(bufObj); Tcl_IncrRefCount(bufObj); } while (csPtr->toRead != (Tcl_WideInt) 0) { /* * Check for unreported background errors. */ Tcl_GetChannelError(inChan, &msg); if ((inStatePtr->unreportedError != 0) || (msg != NULL)) { Tcl_SetErrno(inStatePtr->unreportedError); inStatePtr->unreportedError = 0; goto readError; } Tcl_GetChannelError(outChan, &msg); if ((outStatePtr->unreportedError != 0) || (msg != NULL)) { Tcl_SetErrno(outStatePtr->unreportedError); outStatePtr->unreportedError = 0; goto writeError; } if (cmdPtr && (mask == 0)) { /* * In async mode, we skip reading synchronously and fake an * underflow instead to prime the readable fileevent. */ size = 0; underflow = 1; } else { /* * Read up to bufSize bytes. */ if ((csPtr->toRead == (Tcl_WideInt) -1) || (csPtr->toRead > (Tcl_WideInt) csPtr->bufSize)) { sizeb = csPtr->bufSize; } else { sizeb = (int) csPtr->toRead; } if (inBinary || sameEncoding) { size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb, !GotFlag(inStatePtr, CHANNEL_NONBLOCKING)); } else { size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb, 0 /* No append */); } underflow = (size >= 0) && (size < sizeb); /* Input underflow */ } if (size < 0) { readError: if (interp) { TclNewObj(errObj); Tcl_AppendStringsToObj(errObj, "error reading \"", Tcl_GetChannelName(inChan), "\": ", NULL); if (msg != NULL) { Tcl_AppendObjToObj(errObj, msg); } else { Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp), NULL); } } if (msg != NULL) { Tcl_DecrRefCount(msg); } break; } else if (underflow) { /* * We had an underflow on the read side. If we are at EOF, and not * in the synchronous part of an asynchronous fcopy, then the * copying is done, otherwise set up a channel handler to detect * when the channel becomes readable again. */ if ((size == 0) && Tcl_Eof(inChan) && !(cmdPtr && (mask == 0))) { break; } if (cmdPtr && (!Tcl_Eof(inChan) || (mask == 0)) && !(mask & TCL_READABLE)) { if (mask & TCL_WRITABLE) { Tcl_DeleteChannelHandler(outChan, CopyEventProc, csPtr); } Tcl_CreateChannelHandler(inChan, TCL_READABLE, CopyEventProc, csPtr); } if (size == 0) { if (!GotFlag(inStatePtr, CHANNEL_NONBLOCKING)) { /* We allowed a short read. Keep trying. */ continue; } if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } return TCL_OK; } } /* * Now write the buffer out. */ if (inBinary || sameEncoding) { buffer = csPtr->buffer; sizeb = size; } else { buffer = TclGetStringFromObj(bufObj, &sizeb); } if (outBinary || sameEncoding) { sizeb = WriteBytes(outStatePtr->topChanPtr, buffer, sizeb); } else { sizeb = WriteChars(outStatePtr->topChanPtr, buffer, sizeb); } /* * [Bug 2895565]. At this point 'size' still contains the number of * bytes or characters which have been read. We keep this to later to * update the totals and toRead information, see marker (UP) below. We * must not overwrite it with 'sizeb', which is the number of written * bytes or characters, and both EOL translation and encoding * conversion may have changed this number unpredictably in relation * to 'size' (It can be smaller or larger, in the latter case able to * drive toRead below -1, causing infinite looping). Completely * unsuitable for updating totals and toRead. */ if (sizeb < 0) { writeError: if (interp) { TclNewObj(errObj); Tcl_AppendStringsToObj(errObj, "error writing \"", Tcl_GetChannelName(outChan), "\": ", NULL); if (msg != NULL) { Tcl_AppendObjToObj(errObj, msg); } else { Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp), NULL); } } if (msg != NULL) { Tcl_DecrRefCount(msg); } break; } /* * Update the current byte count. Do it now so the count is valid * before a return or break takes us out of the loop. The invariant at * the top of the loop should be that csPtr->toRead holds the number * of bytes left to copy. */ if (csPtr->toRead != -1) { csPtr->toRead -= size; } csPtr->total += size; /* * Break loop if EOF && (size>0) */ if (Tcl_Eof(inChan)) { break; } /* * Check to see if the write is happening in the background. If so, * stop copying and wait for the channel to become writable again. * After input underflow we already installed a readable handler * therefore we don't need a writable handler. */ if (!underflow && GotFlag(outStatePtr, BG_FLUSH_SCHEDULED)) { if (!(mask & TCL_WRITABLE)) { if (mask & TCL_READABLE) { Tcl_DeleteChannelHandler(inChan, CopyEventProc, csPtr); } Tcl_CreateChannelHandler(outChan, TCL_WRITABLE, CopyEventProc, csPtr); } if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } return TCL_OK; } /* * For background copies, we only do one buffer per invocation so we * don't starve the rest of the system. */ if (cmdPtr && (csPtr->toRead != 0)) { /* * The first time we enter this code, there won't be a channel * handler established yet, so do it here. */ if (mask == 0) { Tcl_CreateChannelHandler(outChan, TCL_WRITABLE, CopyEventProc, csPtr); } if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } return TCL_OK; } } /* while */ if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } /* * Make the callback or return the number of bytes transferred. The local * total is used because StopCopy frees csPtr. */ total = csPtr->total; if (cmdPtr && interp) { int code; /* * Get a private copy of the command so we can mutate it by adding * arguments. Note that StopCopy frees our saved reference to the * original command obj. */ cmdPtr = Tcl_DuplicateObj(cmdPtr); Tcl_IncrRefCount(cmdPtr); StopCopy(csPtr); Tcl_Preserve(interp); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewWideIntObj(total)); if (errObj) { Tcl_ListObjAppendElement(interp, cmdPtr, errObj); } code = Tcl_EvalObjEx(interp, cmdPtr, TCL_EVAL_GLOBAL); if (code != TCL_OK) { Tcl_BackgroundException(interp, code); result = TCL_ERROR; } TclDecrRefCount(cmdPtr); Tcl_Release(interp); } else { StopCopy(csPtr); if (interp) { if (errObj) { Tcl_SetObjResult(interp, errObj); result = TCL_ERROR; } else { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(total)); } } } return result; } /* *---------------------------------------------------------------------- * * DoRead -- * * Stores up to "bytesToRead" bytes in memory pointed to by "dst". * These bytes come from reading the channel "chanPtr" and * performing the configured translations. No encoding conversions * are applied to the bytes being read. * * Results: * The number of bytes actually stored (<= bytesToRead), * or -1 if there is an error in reading the channel. Use * Tcl_GetErrno() to retrieve the error code for the error * that occurred. * * The number of bytes stored can be less than the number * requested when * - EOF is reached on the channel; or * - the channel is non-blocking, and we've read all we can * without blocking. * - a channel reading error occurs (and we return -1) * * Side effects: * May cause input to be buffered. * *---------------------------------------------------------------------- */ static int DoRead( Channel *chanPtr, /* The channel from which to read. */ char *dst, /* Where to store input read. */ int bytesToRead, /* Maximum number of bytes to read. */ int allowShortReads) /* Allow half-blocking (pipes,sockets) */ { ChannelState *statePtr = chanPtr->state; char *p = dst; assert (bytesToRead >= 0); /* * Early out when we know a read will get the eofchar. * * NOTE: This seems to be a bug. The special handling for * a zero-char read request ought to come first. As coded * the EOF due to eofchar has distinguishing behavior from * the EOF due to reported EOF on the underlying device, and * that seems undesirable. However recent history indicates * that new inconsistent behavior in a patchlevel has problems * too. Keep on keeping on for now. */ if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) { SetFlag(statePtr, CHANNEL_EOF); assert( statePtr->inputEncodingFlags & TCL_ENCODING_END ); assert( !GotFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR) ); /* TODO: Don't need this call */ UpdateInterest(chanPtr); return 0; } /* Special handling for zero-char read request. */ if (bytesToRead == 0) { if (GotFlag(statePtr, CHANNEL_EOF)) { statePtr->inputEncodingFlags |= TCL_ENCODING_START; } ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF); statePtr->inputEncodingFlags &= ~TCL_ENCODING_END; /* TODO: Don't need this call */ UpdateInterest(chanPtr); return 0; } TclChannelPreserve((Tcl_Channel)chanPtr); while (bytesToRead) { /* * Each pass through the loop is intended to process up to * one channel buffer. */ int bytesRead, bytesWritten; ChannelBuffer *bufPtr = statePtr->inQueueHead; /* * Don't read more data if we have what we need. */ while (!bufPtr || /* We got no buffer! OR */ (!IsBufferFull(bufPtr) && /* Our buffer has room AND */ (BytesLeft(bufPtr) < bytesToRead) ) ) { /* Not enough bytes in it * yet to fill the dst */ int code; moreData: code = GetInput(chanPtr); bufPtr = statePtr->inQueueHead; assert (bufPtr != NULL); if (GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED)) { /* Further reads cannot do any more */ break; } if (code) { /* Read error */ UpdateInterest(chanPtr); TclChannelRelease((Tcl_Channel)chanPtr); return -1; } assert (IsBufferFull(bufPtr)); } assert (bufPtr != NULL); bytesRead = BytesLeft(bufPtr); bytesWritten = bytesToRead; TranslateInputEOL(statePtr, p, RemovePoint(bufPtr), &bytesWritten, &bytesRead); bufPtr->nextRemoved += bytesRead; p += bytesWritten; bytesToRead -= bytesWritten; if (!IsBufferEmpty(bufPtr)) { /* * Buffer is not empty. How can that be? * * 0) We stopped early because we got all the bytes * we were seeking. That's fine. */ if (bytesToRead == 0) { break; } /* * 1) We're @EOF because we saw eof char. */ if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) { break; } /* * 2) The buffer holds a \r while in CRLF translation, * followed by the end of the buffer. */ assert(statePtr->inputTranslation == TCL_TRANSLATE_CRLF); assert(RemovePoint(bufPtr)[0] == '\r'); assert(BytesLeft(bufPtr) == 1); if (bufPtr->nextPtr == NULL) { /* There's no more buffered data.... */ if (statePtr->flags & CHANNEL_EOF) { /* ...and there never will be. */ *p++ = '\r'; bytesToRead--; bufPtr->nextRemoved++; } else if (statePtr->flags & CHANNEL_BLOCKED) { /* ...and we cannot get more now. */ SetFlag(statePtr, CHANNEL_NEED_MORE_DATA); break; } else { /* ... so we need to get some. */ goto moreData; } } if (bufPtr->nextPtr) { /* There's a next buffer. Shift orphan \r to it. */ ChannelBuffer *nextPtr = bufPtr->nextPtr; nextPtr->nextRemoved -= 1; RemovePoint(nextPtr)[0] = '\r'; bufPtr->nextRemoved++; } } if (IsBufferEmpty(bufPtr)) { statePtr->inQueueHead = bufPtr->nextPtr; if (statePtr->inQueueHead == NULL) { statePtr->inQueueTail = NULL; } RecycleBuffer(statePtr, bufPtr, 0); bufPtr = statePtr->inQueueHead; } if ((GotFlag(statePtr, CHANNEL_NONBLOCKING) || allowShortReads) && GotFlag(statePtr, CHANNEL_BLOCKED)) { break; } /* * When there's no buffered data to read, and we're at EOF, * escape to the caller. */ if (GotFlag(statePtr, CHANNEL_EOF) && (bufPtr == NULL || IsBufferEmpty(bufPtr))) { break; } } if (bytesToRead == 0) { ResetFlag(statePtr, CHANNEL_BLOCKED); } assert(!GotFlag(statePtr, CHANNEL_EOF) || GotFlag(statePtr, CHANNEL_STICKY_EOF) || Tcl_InputBuffered((Tcl_Channel)chanPtr) == 0); assert( !(GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED) == (CHANNEL_EOF|CHANNEL_BLOCKED)) ); UpdateInterest(chanPtr); TclChannelRelease((Tcl_Channel)chanPtr); return (int)(p - dst); } /* *---------------------------------------------------------------------- * * CopyEventProc -- * * This routine is invoked as a channel event handler for the background * copy operation. It is just a trivial wrapper around the CopyData * routine. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void CopyEventProc( ClientData clientData, int mask) { (void) CopyData(clientData, mask); } /* *---------------------------------------------------------------------- * * StopCopy -- * * This routine halts a copy that is in progress. * * Results: * None. * * Side effects: * Removes any pending channel handlers and restores the blocking and * buffering modes of the channels. The CopyState is freed. * *---------------------------------------------------------------------- */ static void StopCopy( CopyState *csPtr) /* State for bg copy to stop . */ { ChannelState *inStatePtr, *outStatePtr; Tcl_Channel inChan, outChan; int nonBlocking; if (!csPtr) { return; } inChan = (Tcl_Channel) csPtr->readPtr; outChan = (Tcl_Channel) csPtr->writePtr; inStatePtr = csPtr->readPtr->state; outStatePtr = csPtr->writePtr->state; /* * Restore the old blocking mode and output buffering mode. */ nonBlocking = csPtr->readFlags & CHANNEL_NONBLOCKING; if (nonBlocking != (inStatePtr->flags & CHANNEL_NONBLOCKING)) { SetBlockMode(NULL, csPtr->readPtr, nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING); } if (csPtr->readPtr != csPtr->writePtr) { nonBlocking = csPtr->writeFlags & CHANNEL_NONBLOCKING; if (nonBlocking != (outStatePtr->flags & CHANNEL_NONBLOCKING)) { SetBlockMode(NULL, csPtr->writePtr, nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING); } } ResetFlag(outStatePtr, CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED); outStatePtr->flags |= csPtr->writeFlags & (CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED); if (csPtr->cmdPtr) { Tcl_DeleteChannelHandler(inChan, CopyEventProc, csPtr); if (inChan != outChan) { Tcl_DeleteChannelHandler(outChan, CopyEventProc, csPtr); } Tcl_DeleteChannelHandler(inChan, MBEvent, csPtr); Tcl_DeleteChannelHandler(outChan, MBEvent, csPtr); TclDecrRefCount(csPtr->cmdPtr); } inStatePtr->csPtrR = NULL; outStatePtr->csPtrW = NULL; ckfree(csPtr); } /* *---------------------------------------------------------------------- * * StackSetBlockMode -- * * This function sets the blocking mode for a channel, iterating through * each channel in a stack and updates the state flags. * * Results: * 0 if OK, result code from failed blockModeProc otherwise. * * Side effects: * Modifies the blocking mode of the channel and possibly generates an * error. * *---------------------------------------------------------------------- */ static int StackSetBlockMode( Channel *chanPtr, /* Channel to modify. */ int mode) /* One of TCL_MODE_BLOCKING or * TCL_MODE_NONBLOCKING. */ { int result = 0; Tcl_DriverBlockModeProc *blockModeProc; ChannelState *statePtr = chanPtr->state; /* * Start at the top of the channel stack * TODO: Examine what can go wrong when blockModeProc calls * disturb the stacking state of the channel. */ chanPtr = statePtr->topChanPtr; while (chanPtr != NULL) { blockModeProc = Tcl_ChannelBlockModeProc(chanPtr->typePtr); if (blockModeProc != NULL) { result = blockModeProc(chanPtr->instanceData, mode); if (result != 0) { Tcl_SetErrno(result); return result; } } chanPtr = chanPtr->downChanPtr; } return 0; } /* *---------------------------------------------------------------------- * * SetBlockMode -- * * This function sets the blocking mode for a channel and updates the * state flags. * * Results: * A standard Tcl result. * * Side effects: * Modifies the blocking mode of the channel and possibly generates an * error. * *---------------------------------------------------------------------- */ static int SetBlockMode( Tcl_Interp *interp, /* Interp for error reporting. */ Channel *chanPtr, /* Channel to modify. */ int mode) /* One of TCL_MODE_BLOCKING or * TCL_MODE_NONBLOCKING. */ { int result = 0; ChannelState *statePtr = chanPtr->state; /* State info for channel */ result = StackSetBlockMode(chanPtr, mode); if (result != 0) { if (interp != NULL) { /* * TIP #219. * Move error messages put by the driver into the bypass area and * put them into the regular interpreter result. Fall back to the * regular message if nothing was found in the bypass. * * Note that we cannot have a message in the interpreter bypass * area, StackSetBlockMode is restricted to the channel bypass. * We still need the interp as the destination of the move. */ if (!TclChanCaughtErrorBypass(interp, (Tcl_Channel) chanPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error setting blocking mode: %s", Tcl_PosixError(interp))); } } else { /* * TIP #219. * If we have no interpreter to put a bypass message into we have * to clear it, to prevent its propagation and use in other places * unrelated to the actual occurence of the problem. */ Tcl_SetChannelError((Tcl_Channel) chanPtr, NULL); } return TCL_ERROR; } if (mode == TCL_MODE_BLOCKING) { ResetFlag(statePtr, CHANNEL_NONBLOCKING | BG_FLUSH_SCHEDULED); } else { SetFlag(statePtr, CHANNEL_NONBLOCKING); } return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GetChannelNames -- * * Return the names of all open channels in the interp. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * Interp result modified with list of channel names. * *---------------------------------------------------------------------- */ int Tcl_GetChannelNames( Tcl_Interp *interp) /* Interp for error reporting. */ { return Tcl_GetChannelNamesEx(interp, NULL); } /* *---------------------------------------------------------------------- * * Tcl_GetChannelNamesEx -- * * Return the names of open channels in the interp filtered filtered * through a pattern. If pattern is NULL, it returns all the open * channels. * * Results: * TCL_OK or TCL_ERROR. * * Side effects: * Interp result modified with list of channel names. * *---------------------------------------------------------------------- */ int Tcl_GetChannelNamesEx( Tcl_Interp *interp, /* Interp for error reporting. */ const char *pattern) /* Pattern to filter on. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ChannelState *statePtr; const char *name; /* Name for channel */ Tcl_Obj *resultPtr; /* Pointer to result object */ Tcl_HashTable *hTblPtr; /* Hash table of channels. */ Tcl_HashEntry *hPtr; /* Search variable. */ Tcl_HashSearch hSearch; /* Search variable. */ if (interp == NULL) { return TCL_OK; } /* * Get the channel table that stores the channels registered for this * interpreter. */ hTblPtr = GetChannelTable(interp); TclNewObj(resultPtr); if ((pattern != NULL) && TclMatchIsTrivial(pattern) && !((pattern[0] == 's') && (pattern[1] == 't') && (pattern[2] == 'd'))) { if ((Tcl_FindHashEntry(hTblPtr, pattern) != NULL) && (Tcl_ListObjAppendElement(interp, resultPtr, Tcl_NewStringObj(pattern, -1)) != TCL_OK)) { goto error; } goto done; } for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch); hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) { statePtr = ((Channel *) Tcl_GetHashValue(hPtr))->state; if (statePtr->topChanPtr == (Channel *) tsdPtr->stdinChannel) { name = "stdin"; } else if (statePtr->topChanPtr == (Channel *) tsdPtr->stdoutChannel) { name = "stdout"; } else if (statePtr->topChanPtr == (Channel *) tsdPtr->stderrChannel) { name = "stderr"; } else { /* * This is also stored in Tcl_GetHashKey(hTblPtr, hPtr), but it's * simpler to just grab the name from the statePtr. */ name = statePtr->channelName; } if (((pattern == NULL) || Tcl_StringMatch(name, pattern)) && (Tcl_ListObjAppendElement(interp, resultPtr, Tcl_NewStringObj(name, -1)) != TCL_OK)) { error: TclDecrRefCount(resultPtr); return TCL_ERROR; } } done: Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_IsChannelRegistered -- * * Checks whether the channel is associated with the interp. See also * Tcl_RegisterChannel and Tcl_UnregisterChannel. * * Results: * 0 if the channel is not registered in the interpreter, 1 else. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_IsChannelRegistered( Tcl_Interp *interp, /* The interp to query of the channel */ Tcl_Channel chan) /* The channel to check */ { Tcl_HashTable *hTblPtr; /* Hash table of channels. */ Tcl_HashEntry *hPtr; /* Search variable. */ Channel *chanPtr; /* The real IO channel. */ ChannelState *statePtr; /* State of the real channel. */ /* * Always check bottom-most channel in the stack. This is the one that * gets registered. */ chanPtr = ((Channel *) chan)->state->bottomChanPtr; statePtr = chanPtr->state; hTblPtr = Tcl_GetAssocData(interp, "tclIO", NULL); if (hTblPtr == NULL) { return 0; } hPtr = Tcl_FindHashEntry(hTblPtr, statePtr->channelName); if (hPtr == NULL) { return 0; } if ((Channel *) Tcl_GetHashValue(hPtr) != chanPtr) { return 0; } return 1; } /* *---------------------------------------------------------------------- * * Tcl_IsChannelShared -- * * Checks whether the channel is shared by multiple interpreters. * * Results: * A boolean value (0 = Not shared, 1 = Shared). * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_IsChannelShared( Tcl_Channel chan) /* The channel to query */ { ChannelState *statePtr = ((Channel *) chan)->state; /* State of real channel structure. */ return ((statePtr->refCount > 1) ? 1 : 0); } /* *---------------------------------------------------------------------- * * Tcl_IsChannelExisting -- * * Checks whether a channel of the given name exists in the * (thread)-global list of all channels. See Tcl_GetChannelNamesEx for * function exposed at the Tcl level. * * Results: * A boolean value (0 = Does not exist, 1 = Does exist). * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_IsChannelExisting( const char *chanName) /* The name of the channel to look for. */ { ChannelState *statePtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); const char *name; int chanNameLen; chanNameLen = strlen(chanName); for (statePtr = tsdPtr->firstCSPtr; statePtr != NULL; statePtr = statePtr->nextCSPtr) { if (statePtr->topChanPtr == (Channel *) tsdPtr->stdinChannel) { name = "stdin"; } else if (statePtr->topChanPtr == (Channel *) tsdPtr->stdoutChannel) { name = "stdout"; } else if (statePtr->topChanPtr == (Channel *) tsdPtr->stderrChannel) { name = "stderr"; } else { name = statePtr->channelName; } if ((*chanName == *name) && (memcmp(name, chanName, (size_t) chanNameLen + 1) == 0)) { return 1; } } return 0; } /* *---------------------------------------------------------------------- * * Tcl_ChannelName -- * * Return the name of the channel type. * * Results: * A pointer the name of the channel type. * * Side effects: * None. * *---------------------------------------------------------------------- */ const char * Tcl_ChannelName( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->typeName; } /* *---------------------------------------------------------------------- * * Tcl_ChannelVersion -- * * Return the of version of the channel type. * * Results: * One of the TCL_CHANNEL_VERSION_* constants from tcl.h * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_ChannelTypeVersion Tcl_ChannelVersion( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { if (chanTypePtr->version == TCL_CHANNEL_VERSION_2) { return TCL_CHANNEL_VERSION_2; } else if (chanTypePtr->version == TCL_CHANNEL_VERSION_3) { return TCL_CHANNEL_VERSION_3; } else if (chanTypePtr->version == TCL_CHANNEL_VERSION_4) { return TCL_CHANNEL_VERSION_4; } else if (chanTypePtr->version == TCL_CHANNEL_VERSION_5) { return TCL_CHANNEL_VERSION_5; } else { /* * In = (PTR2INT(minimumVersion)); } /* *---------------------------------------------------------------------- * * Tcl_ChannelBlockModeProc -- * * Return the Tcl_DriverBlockModeProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverBlockModeProc * Tcl_ChannelBlockModeProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_2)) { return chanTypePtr->blockModeProc; } /* * The v1 structure had the blockModeProc in a different place. */ return (Tcl_DriverBlockModeProc *) chanTypePtr->version; } /* *---------------------------------------------------------------------- * * Tcl_ChannelCloseProc -- * * Return the Tcl_DriverCloseProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverCloseProc * Tcl_ChannelCloseProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->closeProc; } /* *---------------------------------------------------------------------- * * Tcl_ChannelClose2Proc -- * * Return the Tcl_DriverClose2Proc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverClose2Proc * Tcl_ChannelClose2Proc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->close2Proc; } /* *---------------------------------------------------------------------- * * Tcl_ChannelInputProc -- * * Return the Tcl_DriverInputProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverInputProc * Tcl_ChannelInputProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->inputProc; } /* *---------------------------------------------------------------------- * * Tcl_ChannelOutputProc -- * * Return the Tcl_DriverOutputProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverOutputProc * Tcl_ChannelOutputProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->outputProc; } /* *---------------------------------------------------------------------- * * Tcl_ChannelSeekProc -- * * Return the Tcl_DriverSeekProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverSeekProc * Tcl_ChannelSeekProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->seekProc; } /* *---------------------------------------------------------------------- * * Tcl_ChannelSetOptionProc -- * * Return the Tcl_DriverSetOptionProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverSetOptionProc * Tcl_ChannelSetOptionProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->setOptionProc; } /* *---------------------------------------------------------------------- * * Tcl_ChannelGetOptionProc -- * * Return the Tcl_DriverGetOptionProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverGetOptionProc * Tcl_ChannelGetOptionProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->getOptionProc; } /* *---------------------------------------------------------------------- * * Tcl_ChannelWatchProc -- * * Return the Tcl_DriverWatchProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverWatchProc * Tcl_ChannelWatchProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->watchProc; } /* *---------------------------------------------------------------------- * * Tcl_ChannelGetHandleProc -- * * Return the Tcl_DriverGetHandleProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverGetHandleProc * Tcl_ChannelGetHandleProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { return chanTypePtr->getHandleProc; } /* *---------------------------------------------------------------------- * * Tcl_ChannelFlushProc -- * * Return the Tcl_DriverFlushProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverFlushProc * Tcl_ChannelFlushProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_2)) { return chanTypePtr->flushProc; } return NULL; } /* *---------------------------------------------------------------------- * * Tcl_ChannelHandlerProc -- * * Return the Tcl_DriverHandlerProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverHandlerProc * Tcl_ChannelHandlerProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_2)) { return chanTypePtr->handlerProc; } return NULL; } /* *---------------------------------------------------------------------- * * Tcl_ChannelWideSeekProc -- * * Return the Tcl_DriverWideSeekProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverWideSeekProc * Tcl_ChannelWideSeekProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_3)) { return chanTypePtr->wideSeekProc; } return NULL; } /* *---------------------------------------------------------------------- * * Tcl_ChannelThreadActionProc -- * * TIP #218, Channel Thread Actions. Return the * Tcl_DriverThreadActionProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverThreadActionProc * Tcl_ChannelThreadActionProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_4)) { return chanTypePtr->threadActionProc; } return NULL; } /* *---------------------------------------------------------------------- * * Tcl_SetChannelErrorInterp -- * * TIP #219, Tcl Channel Reflection API. * Store an error message for the I/O system. * * Results: * None. * * Side effects: * Discards a previously stored message. * *---------------------------------------------------------------------- */ void Tcl_SetChannelErrorInterp( Tcl_Interp *interp, /* Interp to store the data into. */ Tcl_Obj *msg) /* Error message to store. */ { Interp *iPtr = (Interp *) interp; if (iPtr->chanMsg != NULL) { TclDecrRefCount(iPtr->chanMsg); iPtr->chanMsg = NULL; } if (msg != NULL) { iPtr->chanMsg = FixLevelCode(msg); Tcl_IncrRefCount(iPtr->chanMsg); } return; } /* *---------------------------------------------------------------------- * * Tcl_SetChannelError -- * * TIP #219, Tcl Channel Reflection API. * Store an error message for the I/O system. * * Results: * None. * * Side effects: * Discards a previously stored message. * *---------------------------------------------------------------------- */ void Tcl_SetChannelError( Tcl_Channel chan, /* Channel to store the data into. */ Tcl_Obj *msg) /* Error message to store. */ { ChannelState *statePtr = ((Channel *) chan)->state; if (statePtr->chanMsg != NULL) { TclDecrRefCount(statePtr->chanMsg); statePtr->chanMsg = NULL; } if (msg != NULL) { statePtr->chanMsg = FixLevelCode(msg); Tcl_IncrRefCount(statePtr->chanMsg); } return; } /* *---------------------------------------------------------------------- * * FixLevelCode -- * * TIP #219, Tcl Channel Reflection API. * Scans an error message for bad -code / -level directives. Returns a * modified copy with such directives corrected, and the input if it had * no problems. * * Results: * A Tcl_Obj* * * Side effects: * None. * *---------------------------------------------------------------------- */ static Tcl_Obj * FixLevelCode( Tcl_Obj *msg) { int explicitResult, numOptions, lc, lcn; Tcl_Obj **lv, **lvn; int res, i, j, val, lignore, cignore; int newlevel = -1, newcode = -1; /* ASSERT msg != NULL */ /* * Process the caught message. * * Syntax = (option value)... ?message? * * Bad message syntax causes a panic, because the other side uses * Tcl_GetReturnOptions and list construction functions to marshall the * information. Hence an error means that we've got serious breakage. */ res = Tcl_ListObjGetElements(NULL, msg, &lc, &lv); if (res != TCL_OK) { Tcl_Panic("Tcl_SetChannelError: bad syntax of message"); } explicitResult = (1 == (lc % 2)); numOptions = lc - explicitResult; /* * No options, nothing to do. */ if (numOptions == 0) { return msg; } /* * Check for -code x, x != 1|error, and -level x, x != 0 */ for (i = 0; i < numOptions; i += 2) { if (0 == strcmp(TclGetString(lv[i]), "-code")) { /* * !"error", !integer, integer != 1 (numeric code for error) */ res = TclGetIntFromObj(NULL, lv[i+1], &val); if (((res == TCL_OK) && (val != 1)) || ((res != TCL_OK) && (0 != strcmp(TclGetString(lv[i+1]), "error")))) { newcode = 1; } } else if (0 == strcmp(TclGetString(lv[i]), "-level")) { /* * !integer, integer != 0 */ res = TclGetIntFromObj(NULL, lv [i+1], &val); if ((res != TCL_OK) || (val != 0)) { newlevel = 0; } } } /* * -code, -level are either not present or ok. Nothing to do. */ if ((newlevel < 0) && (newcode < 0)) { return msg; } lcn = numOptions; if (explicitResult) { lcn ++; } if (newlevel >= 0) { lcn += 2; } if (newcode >= 0) { lcn += 2; } lvn = ckalloc(lcn * sizeof(Tcl_Obj *)); /* * New level/code information is spliced into the first occurence of * -level, -code, further occurences are ignored. The options cannot be * not present, we would not come here. Options which are ok are simply * copied over. */ lignore = cignore = 0; for (i=0, j=0; i= 0) { lvn[j++] = lv[i]; lvn[j++] = Tcl_NewIntObj(newlevel); newlevel = -1; lignore = 1; continue; } else if (lignore) { continue; } } else if (0 == strcmp(TclGetString(lv[i]), "-code")) { if (newcode >= 0) { lvn[j++] = lv[i]; lvn[j++] = Tcl_NewIntObj(newcode); newcode = -1; cignore = 1; continue; } else if (cignore) { continue; } } /* * Keep everything else, possibly copied down. */ lvn[j++] = lv[i]; lvn[j++] = lv[i+1]; } if (newlevel >= 0) { Tcl_Panic("Defined newlevel not used in rewrite"); } if (newcode >= 0) { Tcl_Panic("Defined newcode not used in rewrite"); } if (explicitResult) { lvn[j++] = lv[i]; } msg = Tcl_NewListObj(j, lvn); ckfree(lvn); return msg; } /* *---------------------------------------------------------------------- * * Tcl_GetChannelErrorInterp -- * * TIP #219, Tcl Channel Reflection API. * Return the message stored by the channel driver. * * Results: * Tcl error message object. * * Side effects: * Resets the stored data to NULL. * *---------------------------------------------------------------------- */ void Tcl_GetChannelErrorInterp( Tcl_Interp *interp, /* Interp to query. */ Tcl_Obj **msg) /* Place for error message. */ { Interp *iPtr = (Interp *) interp; *msg = iPtr->chanMsg; iPtr->chanMsg = NULL; } /* *---------------------------------------------------------------------- * * Tcl_GetChannelError -- * * TIP #219, Tcl Channel Reflection API. * Return the message stored by the channel driver. * * Results: * Tcl error message object. * * Side effects: * Resets the stored data to NULL. * *---------------------------------------------------------------------- */ void Tcl_GetChannelError( Tcl_Channel chan, /* Channel to query. */ Tcl_Obj **msg) /* Place for error message. */ { ChannelState *statePtr = ((Channel *) chan)->state; *msg = statePtr->chanMsg; statePtr->chanMsg = NULL; } /* *---------------------------------------------------------------------- * * Tcl_ChannelTruncateProc -- * * TIP #208 (subsection relating to truncation, based on TIP #206). * Return the Tcl_DriverTruncateProc of the channel type. * * Results: * A pointer to the proc. * * Side effects: * None. * *---------------------------------------------------------------------- */ Tcl_DriverTruncateProc * Tcl_ChannelTruncateProc( const Tcl_ChannelType *chanTypePtr) /* Pointer to channel type. */ { if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_5)) { return chanTypePtr->truncateProc; } return NULL; } /* *---------------------------------------------------------------------- * * DupChannelIntRep -- * * Initialize the internal representation of a new Tcl_Obj to a copy of * the internal representation of an existing string object. * * Results: * None. * * Side effects: * copyPtr's internal rep is set to a copy of srcPtr's internal * representation. * *---------------------------------------------------------------------- */ static void DupChannelIntRep( register Tcl_Obj *srcPtr, /* Object with internal rep to copy. Must have * an internal rep of type "Channel". */ register Tcl_Obj *copyPtr) /* Object with internal rep to set. Must not * currently have an internal rep.*/ { ChannelState *statePtr = GET_CHANNELSTATE(srcPtr); SET_CHANNELSTATE(copyPtr, statePtr); SET_CHANNELINTERP(copyPtr, GET_CHANNELINTERP(srcPtr)); Tcl_Preserve(statePtr); copyPtr->typePtr = srcPtr->typePtr; } /* *---------------------------------------------------------------------- * * SetChannelFromAny -- * * Create an internal representation of type "Channel" for an object. * * Results: * This operation always succeeds and returns TCL_OK. * * Side effects: * Any old internal reputation for objPtr is freed and the internal * representation is set to "Channel". * *---------------------------------------------------------------------- */ static int SetChannelFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr) /* The object to convert. */ { ChannelState *statePtr; if (interp == NULL) { return TCL_ERROR; } if (objPtr->typePtr == &chanObjType) { /* * TODO: TAINT Flag and dup'd channel values? * The channel is valid until any call to DetachChannel occurs. * Ensure consistency checks are done. */ statePtr = GET_CHANNELSTATE(objPtr); if (GotFlag(statePtr, CHANNEL_TAINTED|CHANNEL_CLOSED)) { ResetFlag(statePtr, CHANNEL_TAINTED); Tcl_Release(statePtr); objPtr->typePtr = NULL; } else if (interp != GET_CHANNELINTERP(objPtr)) { Tcl_Release(statePtr); objPtr->typePtr = NULL; } } if (objPtr->typePtr != &chanObjType) { Tcl_Channel chan = Tcl_GetChannel(interp, TclGetString(objPtr), NULL); if (chan == NULL) { return TCL_ERROR; } TclFreeIntRep(objPtr); statePtr = ((Channel *) chan)->state; Tcl_Preserve(statePtr); SET_CHANNELSTATE(objPtr, statePtr); SET_CHANNELINTERP(objPtr, interp); objPtr->typePtr = &chanObjType; } return TCL_OK; } /* *---------------------------------------------------------------------- * * FreeChannelIntRep -- * * Release statePtr storage. * * Results: * None. * * Side effects: * May cause state to be freed. * *---------------------------------------------------------------------- */ static void FreeChannelIntRep( Tcl_Obj *objPtr) /* Object with internal rep to free. */ { Tcl_Release(GET_CHANNELSTATE(objPtr)); objPtr->typePtr = NULL; } #if 0 /* * For future debugging work, a simple function to print the flags of a * channel in semi-readable form. */ static int DumpFlags( char *str, int flags) { char buf[20]; int i = 0; #define ChanFlag(chr, bit) (buf[i++] = ((flags & (bit)) ? (chr) : '_')) ChanFlag('r', TCL_READABLE); ChanFlag('w', TCL_WRITABLE); ChanFlag('n', CHANNEL_NONBLOCKING); ChanFlag('l', CHANNEL_LINEBUFFERED); ChanFlag('u', CHANNEL_UNBUFFERED); ChanFlag('F', BG_FLUSH_SCHEDULED); ChanFlag('c', CHANNEL_CLOSED); ChanFlag('E', CHANNEL_EOF); ChanFlag('S', CHANNEL_STICKY_EOF); ChanFlag('B', CHANNEL_BLOCKED); ChanFlag('/', INPUT_SAW_CR); ChanFlag('D', CHANNEL_DEAD); ChanFlag('R', CHANNEL_RAW_MODE); ChanFlag('x', CHANNEL_INCLOSE); buf[i] ='\0'; fprintf(stderr, "%s: %s\n", str, buf); return 0; } #endif /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * indent-tabs-mode: nil * End: */ tcl8.6.5/changes0000644000175000017500000130135212665113557013130 0ustar sergeisergeiRecent user-visible changes to Tcl: 1. No more [command1] [command2] construct for grouping multiple commands on a single command line. 2. Semi-colon now available for grouping commands on a line. 3. For a command to span multiple lines, must now use backslash-return at the end of each line but the last. 4. "Var" command has been changed to "set". 5. Double-quotes now available as an argument grouping character. 6. "Return" may be used at top-level. 7. More backslash sequences available now. In particular, backslash-newline may be used to join lines in command files. 8. New or modified built-in commands: case, return, for, glob, info, print, return, set, source, string, uplevel. 9. After an error, the variable "errorInfo" is filled with a stack trace showing what was being executed when the error occurred. 10. Command abbreviations are accepted when parsing commands, but are not recommended except for purely-interactive commands. 11. $, set, and expr all complain now if a non-existent variable is referenced. 12. History facilities exist now. See Tcl.man and Tcl_RecordAndEval.man. 13. Changed to distinguish between empty variables and those that don't exist at all. Interfaces to Tcl_GetVar and Tcl_ParseVar have changed (NULL return value is now possible). *** POTENTIAL INCOMPATIBILITY *** 14. Changed meaning of "level" argument to "uplevel" command (1 now means "go up one level", not "go to level 1"; "#1" means "go to level 1"). *** POTENTIAL INCOMPATIBILITY *** 15. 3/19/90 Added "info exists" option to see if variable exists. 16. 3/19/90 Added "noAbbrev" variable to prohibit command abbreviations. 17. 3/19/90 Added extra errorInfo option to "error" command. 18. 3/21/90 Double-quotes now only affect space: command, variable, and backslash substitutions still occur inside double-quotes. *** POTENTIAL INCOMPATIBILITY *** 19. 3/21/90 Added support for \r. 20. 3/21/90 List, concat, eval, and glob commands all expect at least one argument now. *** POTENTIAL INCOMPATIBILITY *** 21. 3/22/90 Added "?:" operators to expressions. 22. 3/25/90 Fixed bug in Tcl_Result that caused memory to get trashed. ------------------- Released version 3.1 --------------------- 23. 3/29/90 Fixed bug that caused "file a.b/c ext" to return ".b/c". 24. 3/29/90 Semi-colon is not treated specially when enclosed in double-quotes. ------------------- Released version 3.2 --------------------- 25. 4/16/90 Rewrote "exec" not to use select or signals anymore. Should be more Sys-V compatible, and no slower in the normal case. 26. 4/18/90 Rewrote "glob" to eliminate GNU code (there's no GNU code left in Tcl, now), and added Tcl_TildeSubst procedure. Added automatic tilde-substitution in many commands, including "glob". ------------------- Released version 3.3 --------------------- 27. 7/11/90 Added "Tcl_AppendResult" procedure. 28. 7/20/90 "History" with no options now defaults to "history info" rather than to "history redo". Although this is a backward incompatibility, it should only be used interactively and thus shouldn't present any compatibility problems with scripts. 29. 7/20/90 Added "Tcl_GetInteger", "Tcl_GetDouble", and "Tcl_GetBoolean" procedures. 30. 7/22/90 Removed "Tcl_WatchInterp" procedure: doesn't seem to be necessary, since the same effect can be achieved with the deletion callbacks on individual commands. *** POTENTIAL INCOMPATIBILITY *** 31. 7/23/90 Added variable tracing: Tcl_TraceVar, Tcl_UnTraceVar, and Tcl_VarTraceInfo procedures, "trace" command. 32. 8/9/90 Mailed out list of all bug fixes since 3.3 release. 33. 8/29/90 Fixed bugs in Tcl_Merge relating to backslashes and semi-colons. Mailed out patch. 34. 9/3/90 Fixed bug in tclBasic.c: quotes weren't quoting ]'s. Mailed out patch. 35. 9/19/90 Rewrote exec to always use files both for input and output to the process. The old pipe-based version didn't work if the exec'ed process forked a child and then exited: Tcl waited around for stdout to get closed, which didn't happen until the grandchild exited. 36. 11/5/90 ERR_IN_PROGRESS flag wasn't being cleared soon enough in Tcl_Eval, allowing error messages from different commands to pile up in $errorInfo. Fixed by re-arranging code in Tcl_Eval that re-initializes result and ERR_IN_PROGRESS flag. Didn't mail out patch: changes too complicated to describe. 37. 12/19/90 Added Tcl_VarEval procedure as a convenience for assembling and executing Tcl commands. 38. 1/29/91 Fixed core leak in Tcl_AddErrorInfo. Also changed procedure and Tcl_Eval so that first call to Tcl_AddErrorInfo need not come from Tcl_Eval. ----------------- Released version 5.0 with Tk ------------------ 39. 4/3/91 Removed change bars from manual entries, leaving only those that came after version 3.3 was released. 40. 5/17/91 Changed tests to conform to Mary Ann May-Pumphrey's approach. 41. 5/23/91 Massive revision to Tcl parser to simplify the implementation of string and floating-point support in expressions. Newlines inside [] are now treated as command separators rather than word separators (this makes newline treatment consistent throughout Tcl). *** POTENTIAL INCOMPATIBILITY *** 42. 5/23/91 Massive rewrite of expression code to support floating-point values and simple string comparisons. The C interfaces to expression routines have changed (Tcl_Expr is replaced by Tcl_ExprLong, Tcl_ExprDouble, etc.), but all old Tcl expression strings should be accepted by the new expression code. *** POTENTIAL INCOMPATIBILITY *** 43. 5/23/91 Modified tclHistory.c to check for negative "keep" value. 44. 5/23/91 Modified Tcl_Backslash to handle backslash-newline. It now returns 0 to indicate that a backslash sequence should be replaced by no character at all. *** POTENTIAL INCOMPATIBILITY *** 45. 5/29/91 Modified to use ANSI C function prototypes. Must set "USE_ANSI" switch when compiling to get prototypes. 46. 5/29/91 Completed test suite by providing tests for all of the built-in Tcl commands. 47. 5/29/91 Changed Tcl_Concat to eliminate leading and trailing white-space in each of the things it concatenates and to ignore elements that are empty or have only white space in them. This produces cleaner output from the "concat" command. *** POTENTIAL INCOMPATIBILITY *** 48. 5/31/91 Changed "set" command and Tcl_SetVar procedure to return new value of variable. 49. 6/1/91 Added "while" and "cd" commands. 50. 6/1/91 Changed "exec" to delete the last character of program output if it is a newline. In most cases this makes it easier to process program-generated output. *** POTENTIAL INCOMPATIBILITY *** 51. 6/1/91 Made sure that pointers are never used after freeing them. 52. 6/1/91 Fixed bug in TclWordEnd where it wasn't dealing with [] inside quotes correctly. 53. 6/8/91 Fixed exec.test to accept return values of either 1 or 255 from "false" command. 54. 7/6/91 Massive overhaul of variable management. Associative arrays now available, along with "unset" command (and Tcl_UnsetVar procedure). Variable traces have been completely reworked: interfaces different both from Tcl and C, and multiple traces may exist on same variable. Can no longer redefine existing local variable to be global. Calling sequences have changed slightly for Tcl_GetVar and Tcl_SetVar ("global" is now "flags"). Tcl_SetVar can fail and return a NULL result. New forms of variable-manipulation procedures: Tcl_GetVar2, Tcl_SetVar2, etc. Syntax of variable $-notation changed to support array indexing. *** POTENTIAL INCOMPATIBILITY *** 55. 7/6/91 Added new list-manipulation procedures: Tcl_ScanElement, Tcl_ConvertElement, Tcl_AppendElement. 56. 7/12/91 Created new procedure Tcl_EvalFile, which does most of the work of the "source" command. 57. 7/20/91 Major reworking of "exec" command to allow pipelines, more redirection, background. Added new procedures Tcl_Fork, Tcl_WaitPids, Tcl_DetachPids, and Tcl_CreatePipeline. The old "< input" notation has been replaced by "<< input" ("<" is for redirection from a file). Also handles error returns and abnormal terminations (e.g. signals) differently. *** POTENTIAL INCOMPATIBILITY *** 58. 7/21/91 Added "append" and "lappend" commands. 59. 7/22/91 Reworked error messages and manual entries to use ?x? as the notation for an optional argument x, instead of [x]. The bracket notation was often confused with the use of brackets for command substitution. Also modified error messages to be more consistent. 60. 7/23/91 Tcl_DeleteCommand now returns an indication of whether or not the command actually existed, and the "rename" command uses this information to return an error if an attempt is made to delete a non-existent command. *** POTENTIAL INCOMPATIBILITY *** 61. 7/25/91 Added new "errorCode" mechanism, along with procedures Tcl_SetErrorCode, Tcl_UnixError, and Tcl_ResetResult. Renamed Tcl_Return to Tcl_SetResult, but left a #define for Tcl_Return to avoid compatibility problems. 62. 7/26/91 Extended "case" command with alternate syntax where all patterns and commands are together in a single list argument: makes it easier to write multi-line case statements. 63. 7/27/91 Changed "print" command to perform tilde-substitution on the file name. 64. 7/27/91 Added "tolower", "toupper", "trim", "trimleft", and "trimright" options to "string" command. 65. 7/29/91 Added "atime", "mtime", "size", and "stat" options to "file" command. 66. 8/1/91 Added "split" and "join" commands. 67. 8/11/91 Added commands for file I/O, including "open", "close", "read", "gets", "puts", "flush", "eof", "seek", and "tell". 68. 8/14/91 Switched to use a hash table for command lookups. Command abbreviations no longer have direct support in the Tcl interpreter, but it should be possible to simulate them with the auto-load features described below. The "noAbbrev" variable is no longer used by Tcl. *** POTENTIAL INCOMPATIBILITY *** 68.5 8/15/91 Added support for "unknown" command, which can be used to complete abbreviations, auto-load library files, auto-exec shell commands, etc. 69. 8/15/91 Added -nocomplain switch to "glob" command. 70. 8/20/91 Added "info library" option and TCL_LIBRARY #define. Also added "info script" option. 71. 8/20/91 Changed "file" command to take "option" argument as first argument (before file name), for consistency with other Tcl commands. *** POTENTIAL INCOMPATIBILITY *** 72. 8/20/91 Changed format of information in $errorInfo variable: comments such as ("while" body line 1) are now on separate lines from commands being executed. *** POTENTIAL INCOMPATIBILITY *** 73. 8/20/91 Changed Tcl_AppendResult so that it (eventually) frees large buffers that it allocates. 74. 8/21/91 Added "linsert", "lreplace", "lsearch", and "lsort" commands. 75. 8/28/91 Added "incr" and "exit" commands. 76. 8/30/91 Added "regexp" and "regsub" commands. 77. 9/4/91 Changed "dynamic" field in interpreters to "freeProc" (procedure address). This allows for alternative storage managers. *** POTENTIAL INCOMPATIBILITY *** 78. 9/6/91 Added "index", "length", and "range" options to "string" command. Added "lindex", "llength", and "lrange" commands. 79. 9/8/91 Removed "index", "length", "print" and "range" commands. "Print" is redundant with "puts", but less general, and the other commands are replaced with the new commands described in change 78 above. *** POTENTIAL INCOMPATIBILITY *** 80. 9/8/91 Changed history revision to occur even when history command is nested; needed in order to allow "history" to be invoked from "unknown" procedure. 81. 9/13/91 Changed "panic" not to use vfprintf (it's uglier and less general now, but makes it easier to run Tcl on systems that don't have vfprintf). Also changed "strerror" not to redeclare sys_errlist. 82. 9/19/91 Lots of changes to improve portability to different UNIX systems, including addition of "config" script to adapt Tcl to the configuration of the system it's being compiled on. 83. 9/22/91 Added "pwd" command. 84. 9/22/91 Renamed manual pages so that their filenames are no more than 14 characters in length, moved to "doc" subdirectory. 85. 9/24/91 Redid manual entries so they contain the supplemental macros that they need; can just print with "troff -man" or "man" now. 86. 9/26/91 Created initial version of script library, including a version of "unknown" that does auto-loading, auto-execution, and abbreviation expansion. This library is used by tclTest automatically. See the "library" manual entry for details. ----------------- Released version 6.0, 9/26/91 ------------------ 87. 9/30/91 Made "string tolower" and "string toupper" check case before converting: on some systems, "tolower" and "toupper" assume that character already has particular case. 88. 9/30/91 Fixed bug in Tcl_SetResult: wasn't always setting freeProc correctly when called with NULL value. This tended to cause memory allocation errors later. 89. 10/3/91 Added "upvar" command. 90. 10/4/91 Changed "format" so that internally it converts %D to %ld, %U to %lu, %O to %lo, and %F to %f. This eliminates some compatibility problems on some machines without affecting behavior. 91. 10/10/91 Fixed bug in "regsub" that caused core dumps with the -all option when the last match wasn't at the end of the string. 92. 10/17/91 Fixed problems with backslash sequences: \r support was incomplete and \f and \v weren't supported at all. 93. 10/24/91 Added Tcl_InitHistory procedure. 94. 10/24/91 Changed "regexp" to store "-1 -1" in subMatchVars that don't match, rather than returning an error. 95. 10/27/91 Modified "regexp" to return actual strings in matchVar and subMatchVars instead of indices. Added "-indices" switch to cause indices to be returned. *** POTENTIAL INCOMPATIBILITY *** 96. 10/27/91 Fixed bug in "scan" where it used hardwired constants for sizes of floats and doubles instead of using "sizeof". 97. 10/31/91 Fixed bug in tclParse.c where parse-related error messages weren't being storage-managed correctly, causing spurious free's. 98. 10/31/91 Form feed and vertical tab characters are now considered to be space characters by the parser. 99. 10/31/91 Added TCL_LEAVE_ERR_MSG flag to procedures like Tcl_SetVar. 100. 11/7/91 Fixed bug in "case" where "in" argument couldn't be omitted if all case branches were embedded in a single list. 101. 11/7/91 Switched to use "pid_t" and "uid_t" and other official POSIC types and function prototypes. ----------------- Released version 6.1, 11/7/91 ------------------ 102. 12/2/91 Modified Tcl_ScanElement and Tcl_ConvertElement in several ways. First, allowed caller to request that only backslashes be used (no braces). Second, made Tcl_ConvertElement more aggressive in using backslashes for braces and quotes. 103. 12/5/91 Added "type", "lstat", and "readlink" options to "file" command, plus added new "type" element to output of "stat" and "lstat" options. 104. 12/10/91 Manual entries had first lines that caused "man" program to try weird preprocessor. Added blank comment lines to fix problem. 105. 12/16/91 Fixed a few bugs in auto_mkindex proc: wasn't handling errors properly, and hadn't been upgraded for new "regexp" syntax. 106. 1/2/92 Fixed bug in "file" command where it didn't properly handle a file names containing tildes where the indicated user doesn't exist. 107. 1/2/92 Fixed lots of cases in tclUnixStr.c where two different errno symbols (e.g. EWOULDBLOCK and EAGAIN) have the same number; Tcl will only use one of them. 108. 1/2/92 Lots of changes to configuration script to handle many more systems more gracefully. E.g. should now detect the bogus strtoul that comes with AIX and substitute Tcl's own version instead. ----------------- Released version 6.2, 1/10/92 ------------------ 109. 1/20/92 Config didn't have code to actually use "uid_t" variable to set TCL_UIT_T #define. 110. 2/10/92 Tcl_Eval didn't properly reset "numLevels" variable when too-deep recursion occurred. 111. 2/29/92 Added "on" and "off" to keywords accepted by Tcl_GetBoolean. 112. 3/19/92 Config wasn't installing default version of strtod.c for systems that don't have one in libc.a. 113. 3/23/92 Fixed bug in tclExpr.c where numbers with leading "."s, like 0.75, couldn't be properly substituted into expressions with variable or command substitution. 114. 3/25/92 Fixed bug in tclUnixAZ.c where "gets" command wasn't checking to make sure that it was able to write the variable OK. 115. 4/16/92 Fixed bug in tclUnixAZ.c where "read" command didn't compute file size right for device files. 116. 4/23/92 Fixed but in tclCmdMZ.c where "trace vinfo" was overwriting the trace command. ----------------- Released version 6.3, 5/1/92 ------------------ 117. 5/1/92 Added Tcl_GlobalEval. 118. 6/1/92 Changed auto-load facility to source files at global level. 119. 6/8/92 Tcl_ParseVar wasn't always setting termPtr after errors, which sometimes caused core dumps. 120. 6/21/92 Fixed bug in initialization of regexp pattern cache. This bug caused segmentation violations in regexp commands under some conditions. 121. 6/22/92 Changed implementation of "glob" command to eliminate trailing slashes on directory names: they confuse some systems. There shouldn't be any user-visible changes in functionality except for names in error messages not having trailing slashes. 122. 7/2/92 Fixed bug that caused 'string match ** ""' to return 0. 123. 7/2/92 Fixed bug in Tcl_CreateCmdBuf where it wasn't initializing the buffer to an empty string. 124. 7/6/92 Fixed bug in "case" command where it used NULL pattern string after errors in the "default" clause. 125. 7/25/92 Speeded up auto_load procedure: don't reread all the index files unless the path has changed. 126. 8/3/92 Changed tclUnix.h to define MAXPATHLEN from PATH_MAX, not _POSIX_PATH_MAX. ----------------- Released version 6.4, 8/7/92 ------------------ 127. 8/10/92 Changed tclBasic.c so that comment lines can be continued by putting a backslash before the newline. 128. 8/21/92 Modified "unknown" to allow the source-ing of a file for an auto-load to trigger other nested auto-loads, as long as there isn't any recursion on the same command name. 129. 8/25/92 Modified "format" command to allow " " and "+" flags, and allow flags in any order. 130. 9/14/92 Modified Tcl_ParseVar so that it doesn't actually attempt to look up the variable if "noEval" mode is in effect in the interpreter (it just parses the name). This avoids the errors that used to occur in statements like "expr {[info exists foo] && $foo}". 131. 9/14/92 Fixed bug in "uplevel" command where it didn't output the correct error message if a level was specified but no command. 132. 9/14/92 Renamed manual entries to have extensions like .3 and .n, and added "install" target to Makefile. 133. 9/18/92 Modified "unknown" command to emulate !!, !, and ^^ csh history substitutions. 134. 9/21/92 Made the config script cleverer about figuring out which switches to pass to "nm". 135. 9/23/92 Fixed tclVar.c to be sure to copy flags when growing variables. Used to forget about traces in progress and make extra recursive calls on trace procs. 136. 9/28/92 Fixed bug in auto_reset where it was unsetting variables that might not exist. 137. 10/7/92 Changed "parray" library procedure to print any array accessible to caller, local or global. 138. 10/15/92 Fixed bug where propagation of new environment variable values among interpreters took N! time if there exist N interpreters. 139. 10/16/92 Changed auto_reset procedure so that it also deletes any existing procedures that are in the auto_load index (the assumption is that they should be re-loaded to get the latest versions). 140. 10/21/92 Fixed bug that caused lists to be incorrectly generated for elements that contained backslash-newline sequences. 141. 12/9/92 Added support for TCL_LIBRARY environment variable: use it as library location if it's present. 142. 12/9/92 Added "info complete" command, Tcl_CommandComplete procedure. 143. 12/16/92 Changed the Makefile to check to make sure "config" has been run (can't run config directly from the Makefile because it modifies the Makefile; thus make has to be run again after running config). ----------------- Released version 6.5, 12/17/92 ------------------ 144. 12/21/92 Changed config to look in several places for libc file. 145. 12/23/92 Added "elseif" support to if. Also, "then", "else", and "elseif" may no longer be abbreviated. *** POTENTIAL INCOMPATIBILITY *** 146. 12/28/92 Changed "puts" and "read" to support initial "-nonewline" switch instead of additional "nonewline" argument. The old form is still supported, but it is discouraged and is no longer documented. Also changed "puts" to make the file argument default to stdout: e.g. "puts foo" will print foo on standard output. 147. 1/6/93 Fixed bug whereby backslash-newline wasn't working when typed interactively, or in "info complete". 148. 1/22/93 Fixed bugs in "lreplace" and "linsert" where close quotes were being lost from last element before replacement or insertion. 149. 1/29/93 Fixed bug in Tcl_AssembleCmd where it wasn't requiring a newline at the end of a line before considering a command to be complete. The bug caused some very long lines in script files to be processed as multiple separate commands. 150. 1/29/93 Various changes in Makefile to add more configuration options, simplify installation, fix bugs (e.g. don't use -f switch for cp), etc. 151. 1/29/93 Changed "name1" and "name2" identifiers to "part1" and "part2" to avoid name conflicts with stupid C++ implementations that use "name1" and "name2" in a reserved way. 152. 2/1/93 Added "putenv" procedure to replace the standard system version so that it will work correctly with Tcl's environment handling. ----------------- Released version 6.6, 2/5/93 ------------------ 153. 2/10/93 Fixed bugs in config script: missing "endif" in libc loop, and tried to use strncasecmp.c instead of strcasecmp.c. 154. 2/10/93 Makefile improvements: added RANLIB variable for easier Sys-V configuration, added SHELL variable for SGI systems. ----------------- Released version 6.7, 2/11/93 ------------------ 153. 2/6/93 Changes in backslash processing: - \Cx, \Mx, \CMx, \e sequences no longer special - \ also eats up any space after the newline, replacing the whole sequence with a single space character - Hex sequences like \x24 are now supported, along with ANSI C's \a. - "format" no longer does backslash processing on its format string - there is no longer any special meaning to a 0 return value from Tcl_Backslash - unknown backslash sequences, like (e.g. \*), are replaced with the following character (e.g. *), instead of just treating the backslash as an ordinary character. *** POTENTIAL INCOMPATIBILITY *** 154. 2/6/93 Updated all copyright notices. The meaning hasn't changed at all but the wording does a better job of protecting U.C. from liability (according to U.C. lawyers, anyway). 155. 2/6/93 Changed "regsub" so that it overwrites the result variable in all cases, even if there is no match. *** POTENTIAL INCOMPATIBILITY *** 156. 2/8/93 Added support for XPG3 %n$ conversion specifiers to "format" command. 157. 2/17/93 Fixed bug in Tcl_Eval where errors due to infinite recursion could result in core dumps. 158. 2/17/93 Improved the auto-load mechanism to deal gracefully (i.e. return an error) with a situation where a library file that supposedly defines a procedure doesn't actually define it. 159. 2/17/93 Renamed Tcl_UnixError procedure to Tcl_PosixError, and changed errorCode variable usage to use POSIX as keyword instead of UNIX. *** POTENTIAL INCOMPATIBILITY *** 160. 2/19/93 Changes to exec and process control: - Added support for >>, >&, >>&, |&, <@, >@, and >&@ forms of redirection. - When exec puts processes into background, it returns a list of their pids as result. - Added support for file, etc. (i.e. no space between ">" and file name. - Added -keepnewline option. - Deleted Tcl_Fork and Tcl_WaitPids procedures (just use fork and waitpid instead). - Added waitpid compatibility procedure for systems that don't have it. - Added Tcl_ReapDetachedProcs procedure. - Changed "exec" to return an error if there is stderr output, even if the command returns a 0 exit status (it's always been documented this way, but the implementation wasn't correct). - If a process returns a non-zero exit status but doesn't generate any diagnostic output, then Tcl generates an error message for it. *** POTENTIAL INCOMPATIBILITY *** 161. 2/25/93 Fixed two memory-management problems having to do with managing the old result during variable trace callbacks. 162. 3/1/93 Added dynamic string library: Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringFree, Tcl_DStringResult, etc. 163. 3/1/93 Modified glob command to only return the names of files that exist, and to only return names ending in "/" if the file is a directory. *** POTENTIAL INCOMPATIBILITY *** 164. 3/19/93 Modified not to use system calls like "read" directly, but instead to use special Tcl procedures that retry automatically if interrupted by signals. 165. 4/3/93 Eliminated "noSep" argument to Tcl_AppendElement, plus TCL_NO_SPACE flag for Tcl_SetVar and Tcl_SetVar2. *** POTENTIAL INCOMPATIBILITY *** 166. 4/3/93 Eliminated "flags" and "termPtr" arguments to Tcl_Eval. *** POTENTIAL INCOMPATIBILITY *** 167. 4/3/93 Changes to expressions: - The "expr" command now accepts multiple arguments, which are concatenated together with space separators. - Integers aren't automatically promoted to floating-point if they overflow the word size: errors are generated instead. - Tcl can now handle "NaN" and other special values if the underlying library procedures handle them. - When printing floating-point numbers, Tcl ensures that there is a "." or "e" in the number, so it can't be treated as an integer accidentally. The procedure Tcl_PrintDouble is available to provide this function in other contexts. Also, the variable "tcl_precision" can be used to set the precision for printing (must be a decimal number giving digits of precision). - Expressions now support transcendental and other functions, e.g. sin, acos, hypot, ceil, and round. Can add new math functions with Tcl_CreateMathFunc(). - Boolean expressions can now have any of the string values accepted by Tcl_GetBoolean, such as "yes" or "no". *** POTENTIAL INCOMPATIBILITY *** 168. 4/5/93 Changed Tcl_UnsetVar and Tcl_UnsetVar2 to return TCL_OK or TCL_ERROR instead of 0 or -1. *** POTENTIAL INCOMPATIBILITY *** 169. 4/5/93 Eliminated Tcl_CmdBuf structure and associated procedures; can use Tcl_DStrings instead. *** POTENTIAL INCOMPATIBILITY *** 170. 4/8/93 Changed interface to Tcl_TildeSubst to use a dynamic string for buffer space. This makes the procedure re-entrant and thread-safe, whereas it wasn't before. *** POTENTIAL INCOMPATIBILITY *** 171. 4/14/93 Eliminated tclHash.h, and moved everything from it to tcl.h *** POTENTIAL INCOMPATIBILITY *** 172. 4/15/93 Eliminated Tcl_InitHistory, made "history" command always be part of interpreter. *** POTENTIAL INCOMPATIBILITY *** 173. 4/16/93 Modified "file" command so that "readable" option always exists, even on machines that don't support symbolic links (always returns same error as if the file wasn't a symbolic link). 174. 4/26/93 Fixed bugs in "regsub" where ^ patterns didn't get handled right (pretended not to match when it really did, and looped infinitely if -all was specified). 175. 4/29/93 Various improvements in the handling of variables: - Can create variables and array elements during a read trace. - Can delete variables during traces (note: unset traces will be invoked when this happens). - Can upvar to array elements. - Can retarget an upvar to another variable by re-issuing the upvar command with a different "other" variable. 176. 5/3/93 Added Tcl_GetCommandInfo, which returns info about a Tcl command such as whether it exists and its ClientData. Also added Tcl_SetCommandInfo, which allows any of this information to be modified and also allows a command's delete procedure to have a different ClientData value than its command procedure. 177. 5/5/93 Added Tcl_RegExpMatch procedure. 178. 5/6/93 Fixed bug in "scan" where it didn't properly handle %% conversion specifiers. Also changed "scan" to use Tcl_PrintDouble for printing real values. 179. 5/7/93 Added "-exact", "-glob", and "-regexp" options to "lsearch" command to allow different kinds of pattern matching. 180. 5/7/93 Added many new switches to "lsort" to control the sorting process: "-ascii", "-integer", "-real", "-command", "-increasing", and "-decreasing". 181. 5/10/93 Changes to file I/O: - Modified "open" command to support a list of POSIX access flags like {WRONLY CREAT TRUNC} in addition to current fopen-style access modes. Also added "permissions" argument to set permissions of newly-created files. - Fixed Scott Bolte's bug (can close stdin etc. in application and then re-open them with Tcl commands). - Exported access to Tcl's file table with new procedures Tcl_EnterFile and Tcl_GetOpenFile. 182. 5/15/93 Added new "pid" command, which can be used to retrieve either the current process id or a list of the process ids in a pipeline opened with "open |..." 183. 6/3/93 Changed to use GNU autoconfig for configuration instead of the home-brew "config" script. Also made many other configuration-related changes, such as using instead of explicitly declaring system calls in tclUnix.h. 184. 6/4/93 Fixed bug where core-dumps could occur if a procedure redefined itself (the memory for the procedure's body could get reallocated in the middle of evaluating the body); implemented simple reference count mechanism. 185. 6/5/93 Changed tclIndex file format in two ways: (a) it's now eval-ed instead of parsed, which makes it 3-4x faster; (b) the entries in auto_index are now commands to evaluate, which allows commands to be loaded in different ways such as dynamic-loading of C code. The old tclIndex file format is still supported. 186. 6/7/93 Eliminated tclTest program, added new "tclsh" program that is more like wish (allows script files to be invoked automatically using "#!/usr/local/bin/tclsh", makes arguments available to script, etc.). Added support for Tcl_AppInit plus default version; this allows new Tcl applications to be created without modifying the main program for tclsh. 187. 6/7/93 Fixed bug in TclWordEnd that kept backslash-newline from working correctly in some cases during interactive input. 188. 6/9/93 Added Tcl_LinkVar and related procedures, which automatically keep a Tcl variable in sync with a C variable. 189. 6/16/93 Increased maximum nesting depth from 100 to 1000. 190. 6/16/93 Modified "trace var" command so that error messages from within traces are returned properly as the result of the variable access, instead of the generic "access disallowed by trace command" message. 191. 6/16/93 Added Tcl_CallWhenDeleted to provide callbacks when an interpreter is deleted (same functionality as Tcl_WatchInterp, which used to exist in versions before 6.0). 193. 6/16/93 Added "-code" argument to "return" command; it's there primarily for completeness, so that procedures implementing control constructs can reflect exceptional conditions back to their callers. 194. 6/16/93 Split up Tcl.n to make separate manual entries for each Tcl command. Tcl.n now contains a summary of the language syntax. 195. 6/17/93 Added new "switch" command to replace "case": allows alternate forms of pattern matching (exact, glob, regexp), replaces pattern lists with single patterns (but you can use "-" bodies to share one body among several patterns), eliminates "in" noise word. "Case" command is now obsolete. 196. 6/17/93 Changed the "exec", "glob", "regexp", and "regsub" commands to include a "--" switch. All initial arguments starting with "-" are now treated as switches unless a "--" switch is present to end the list. *** POTENTIAL INCOMPATIBILITY *** 197. 6/17/93 Changed auto-exec so that the subprocess gets stdin, stdout, and stderr from the parent. This allows truly interactive sub-processes (e.g. vi) to be auto-exec'ed from a tcl shell command line. 198. 6/18/93 Added patchlevel.h, for use in coordinating future patch releases, and also added "info patchlevel" command to make the patch level available to Tcl scripts. 199. 6/19/93 Modified "glob" command so that a leading "//" in a name gets left as is (this is needed for systems like Apollos where "//" is the super-root; Tcl used to collapse the two slashes into a single slash). 200. 7/7/93 Added Tcl_SetRecursionLimit procedure so that the maximum allowable nesting depth can be controlled for an interpreter from C. ----------------- Released version 7.0 Beta 1, 7/9/93 ------------------ 201. 7/12/93 Modified Tcl_GetInt and tclExpr.c so that full-precision unsigned integers can be specified without overflow errors. 202. 7/12/93 Configuration changes: eliminate leading blank line in configure script; provide separate targets in Makefile for installing binary and non-binary information; check for size_t and a few other potentially missing typedefs; don't put tclAppInit.o into libtcl.a; better checks for matherr support. 203. 7/14/93 Changed tclExpr.c to check the termination pointer before errno after strtod calls, to avoid problems with some versions of strtod that set errno in unexpected ways. 204. 7/16/93 Changed "scan" command to be more ANSI-conformant: eliminated %F, %D, etc., added code to ignore "l", "h", and "L" modifiers but always convert %e, %f, and %g with implicit "l"; also added support for %u and %i. Also changed "format" command to eliminate %D, %U, %O, and add %i. *** POTENTIAL INCOMPATIBILITY *** 205. 7/17/93 Changed "uplevel" and "upvar" so that they can be used from global level to global level: this used to generate an error. 206. 7/19/93 Renamed "setenv", "putenv", and "unsetenv" procedures to avoid conflicts with system procedures with the same names. If you want Tcl's procedures to override the system procedures, do it in the Makefile (instructions are in the Makefile). *** POTENTIAL INCOMPATIBILITY *** ----------------- Released version 7.0 Beta 2, 7/21/93 ------------------ 207. 7/21/93 Fixed bug in tclVar.c where freed memory was accidentally used if a procedure returned an element of a local array. 208. 7/22/93 Fixed bug in "unknown" where it didn't properly handle errors occurring in the "auto_load" procedure, leaving its state inconsistent. 209. 7/23/93 Changed exec's ">2" redirection operator to "2>" for consistency with sh. This is incompatible with earlier beta releases of 7.0 but not with pre-7.0 releases, which didn't support either operator. 210. 7/28/93 Changed backslash-newline handling so that the resulting space character *is* treated as a word separator unless the backslash sequence is in quotes or braces. This is incompatible with 7.0b1 and 7.0b2 but is more compatible with pre-7.0 versions that the b1 and b2 releases were. 211. 7/28/93 Eliminated Tcl_LinkedVarWritable, added TCL_LINK_READ_ONLY to Tcl_LinkVar to accomplish same purpose. This change is incompatible with earlier beta releases, but not with releases before Tcl 7.0. 212. 7/29/93 Renamed regexp C functions so they won't clash with POSIX regexp functions that use the same name. 213. 8/3/93 Added "-errorinfo" and "-errorcode" options to "return" command: these allow for much better handling of the errorInfo and errorCode variables in some cases. 214. 8/12/93 Changed "expr" so that % always returns a remainder with the same sign as the divisor and absolute value smaller than the divisor. 215. 8/14/93 Turned off auto-exec in "unknown" unless the command was typed interactively. This means you must use "exec" when invoking subprocesses, unless it's a command that's typed interactively. *** POTENTIAL INCOMPATIBILITY *** 216. 8/14/93 Added support for tcl_prompt1 and tcl_prompt2 variables to tclMain.c: makes prompts user-settable. 217. 8/14/93 Added asynchronous handlers (Tcl_AsyncCreate etc.) so that signals can be taken cleanly by Tcl applications. 218. 8/16/93 Moved information about open files from the interpreter structure to global variables so that a file can be opened in one interpreter and read or written in another. 219. 8/16/93 Removed ENV_FLAGS from Makefile, so that there's no official support for overriding setenv, unsetenv, and putenv. 220. 8/20/93 Various configuration improvements: coerce chars to unsigned chars before using macros like isspace; source ~/.tclshrc file during initialization if it exists and program is running interactively; allow there to be directories in auto_path that don't exist or don't have tclIndex files (ignore them); added Tcl_Init procedure and changed Tcl_AppInit to call it. 221. 8/21/93 Fixed bug in expr where "+", "-", and " " were all getting treated as integers with value 0. 222. 8/26/93 Added "tcl_interactive" variable to tclsh. 223. 8/27/93 Added procedure Tcl_FilePermissions to return whether a given file can be read or written or both. Modified Tcl_EnterFile to take a permissions mask rather than separate read and write arguments. 224. 8/28/93 Fixed performance bug in "glob" command (unnecessary call to "access" for each file caused a 5-10x slow-down for big directories). ----------------- Released version 7.0 Beta 3, 8/28/93 ------------------ 225. 9/9/93 Renamed regexp.h to tclRegexp.h to avoid conflicts with system include file by same name. 226. 9/9/93 Added Tcl_DontCallWhenDeleted. 227. 9/16/93 Changed not to call exit C procedure directly; instead always invoke "exit" Tcl command so that application can redefine the command to do additional cleanup. 228. 9/17/93 Changed auto-exec to handle names that contain slashes (i.e. don't use PATH for them). 229. 9/23/93 Fixed bug in "read" and "gets" commands where they didn't clear EOF conditions. ----------------- Released version 7.0, 9/29/93 ------------------ 230. 10/7/93 "Scan" command wasn't properly aligning things in memory, so segmentation faults could arise under some circumstances. 231. 10/7/93 Fixed bug in Tcl_ConvertElement where it forgot to backslash leading curly brace when creating lists. 232. 10/7/93 Eliminated dependency of tclMain.c on tclInt.h and tclUnix.h, so that people can copy the file out of the Tcl source directory to make modified private versions. 233. 10/8/93 Fixed bug in auto-loader that reversed the priority order of entries in auto_path for new-style index files. Now things are back to the way they were before 3.0: first in auto_path is always highest priority. 234. 10/13/93 Fixed bug where Tcl_CommandComplete didn't recognize comments and treat them as such. Thus if you typed the line # { interactively, Tcl would think that the command wasn't complete and wait for more input before evaluating the script. 235. 10/14/93 Fixed bug where "regsub" didn't set the output variable if the input string was empty. 236. 10/23/93 Fixed bug where Tcl_CreatePipeline didn't close off enough file descriptors in child processes, causing children not to exit properly in some cases. 237. 10/28/93 Changed "list" and "concat" commands not to generate errors if given zero arguments, but instead to just return an empty string. ----------------- Released version 7.1, 11/4/93 ------------------ Note: there is no 7.2 release. It was flawed and was thus withdrawn shortly after it was released. 238. 11/10/93 TclMain.c didn't compile on some systems because of R_OK in call to "access". Changed to eliminate call to "access". ----------------- Released version 7.3, 11/26/93 ------------------ 239. 11/6/93 Modified "lindex", "linsert", "lrange", and "lreplace" so that "end" can be specified as an index. 240. 11/6/93 Modified "append" and "lappend" to allow only two words total (i.e., nothing to append) without generating an error. 241. 12/2/93 Changed to use EAGAIN as the errno for non-blocking I/O instead of EWOULDBLOCK: this should fix problem where non-blocking I/O didn't work correctly on System-V systems. 242. 12/22/93 Fixed bug in expressions where cancelled evaluation wasn't always working correctly (e.g. "set one 1; eval {1 || 1/$one}" failed with a divide by zero error). 243. 1/6/94 Changed TCL_VOLATILE definition from -1 to the address of a dummy procedure Tcl_Volatile, since -1 causes portability problems on some machines (e.g., Crays). 244. 2/4/94 Added support for unary plus. 245. 2/17/94 Changed Tcl_RecordAndEval and "history" command to call Tcl_GlobalEval instead of Tcl_Eval. Otherwise, invocation of these facilities in nested procedures can cause unwanted results. 246. 2/17/94 Fixed bug in tclExpr.c where an expression such as "expr {"12398712938788234-1298379" != ""}" triggers an integer overflow error for the number in quotes, even though it isn't really a proper integer anyway. 247. 2/19/94 Added new procedure Tcl_DStringGetResult to move result from interpreter to a dynamic string. 248. 2/19/94 Fixed bug in Tcl_DStringResult that caused it to overwrite the contents of a static result in some situations. This can cause bizarre errors such as variables suddenly having empty values. 249. 2/21/94 Fixed bug in Tcl_AppendElement, Tcl_DStringAppendElement, and the "lappend" command that caused improper omission of a separator space in some cases. For example, the script set x "abc{"; lappend x "def" used to return the result "abc{def" instead of "abc{ def". 250. 3/3/94 Tcl_ConvertElement was outputting empty elements as \0 if TCL_DONT_USE_BRACES was set. This depends on old pre-7.0 meaning of \0, which is no longer in effect, so it didn't really work. Changed to output empty elements as {} always. 251. 3/3/94 Renamed Tcl_DStringTrunc to Tcl_DStringSetLength and extended it so that it can be used to lengthen a string as well as shorten it. Tcl_DStringTrunc is defined as a macro for backward compatibility, but it is deprecated. 252. 3/3/94 Added Tcl_AllowExceptions procedure. 253. 3/13/94 Fixed bug in Tcl_FormatCmd that could cause "format" to mis-behave on 64-bit Big-Endian machines. 254. 3/13/94 Changed to use vfork instead of fork on systems where vfork exists. 255. 3/23/94 Fixed bug in expressions where ?: didn't associate right-to-left as they should. 256. 4/3/94 Fixed "exec" to flush any files used in >@ or >&@ redirection in exec, so that data buffered for them is written before any new data added by the subprocess. 257. 4/3/94 Added "subst" command. 258. 5/20/94 The tclsh main program is now called Tcl_Main; tclAppInit.c has a "main" procedure that calls Tcl_Main. This makes it easier to use Tcl with C++ programs, which need their own main programs, and it also allows an application to prefilter the argument list before calling Tcl_Main. *** POTENTIAL INCOMPATIBILITY *** 259. 6/6/94 Fixed bug in procedure returns where the errorInfo variable could get truncated if an unset trace was invoked as part of returning from the procedure. 260. 6/13/94 Added "wordstart" and "wordend" options to "string" command. 261. 6/27/94 Fixed bug in expressions where they didn't properly cancel the evaluation of math functions in &&, ||, and ?:. 262. 7/11/94 Incorrect boolean values, like "ogle", weren't being handled properly. 263. 7/15/94 Added Tcl_RegExpCompile, Tcl_RegExpExec, and Tcl_RegExpRange, which provide lower-level access to regular expression pattern matching. 264. 7/22/94 Fixed bug in "glob" command where "glob -nocomplain ~bad_user" would complain about a missing user. Now it doesn't complain anymore. 265. 8/4/94 Fixed bug with linked variables where they didn't behave correctly when accessed via upvars. 266. 8/17/94 Fixed bug in Tcl_EvalFile where it didn't clear interp->result. 267. 8/31/94 Modified "open" command so that errors in exec-ing subprocesses are returned by the open immediately, rather than being delayed until the "close" is executed. 268. 9/9/94 Modified "expr" command to generate errors for integer overflow (includes addition, subtraction, negation, multiplication, division). 269. 9/23/94 Modified "regsub" to return a count of the number of matches and replacements, rather than 0/1. 279. 10/4/94 Added new features to "array" command: - added "get" and "set" commands for easy conversion between arrays and lists. - added "exists" command to see if a variable is an array, changed "names" and "size" commands to treat a non-existent array (or scalar variable) just like an empty one. - added pattern option to "names" command. 280. 10/6/94 Modified Tcl_SetVar2 so that read traces on variables get called during append operations. 281. 10/20/94 Fixed bug in "read" command where reading from stdin required two control-D's to stop the reading. 282. 11/3/94 Changed "expr" command to use longs for division just like all other expr operators; it previously used ints for division. 283. 11/4/94 Fixed bugs in "unknown" procedure: it wasn't properly handling exception returns from commands that were executed after being auto-loaded. ----------------- Released version 7.4b1, 12/23/94 ------------------ 284. 12/26/94 Fixed "install" target in Makefile (couldn't always find install program). 285. 12/26/94 Added strcncasecmp procedure to compat directory. 286. 1/3/95 Fixed all procedure calls to explicitly cast arguments: implicit conversions from prototypes (especially integer->double) don't work when compiling under non-ANSI compilers. Tcl is now clean under gcc -Wconversion. 287. 1/4/95 Fixed problem in Tcl_ArrayCmd where same name was used for both a label and a variable; caused problems on several older compilers, making array command misbehave and causing many errors in Tcl test suite. ----------------- Released version 7.4b2, 1/12/95 ------------------ 288. 2/9/95 Modified Tcl_CreateCommand to return a token, and added Tcl_GetCommandName procedure. Together, these procedures make it possible to track renames of a command. 289. 2/13/95 Fixed bug in expr where "089" was interpreted as a floating-point number rather than a bogus octal number. *** POTENTIAL INCOMPATIBILITY *** 290. 2/14/95 Added code to Tcl_GetInt and Tcl_GetDouble to check for overflows when reading in numbers. 291. 2/18/95 Changed "array set" to stop after first error, rather than continuing after error. 292. 2/20/95 Upgraded to use autoconf version 2.2. 293. 2/20/95 Fixed core dump that could occur in "scan" command if a close bracket was omitted. 294. 2/27/95 Changed Makefile to always use install-sh for installations: there's just too much variation among "install" system programs, which makes installation flakey. ----------------- Released version 7.4b3, 3/24/95 ------------------ 3/25/95 (bug fix) Changed "install" to "./install" in Makefile so that "make install" will work even when "." isn't in the search path. 3/29/95 (bug fix) Fixed bug where the auto-loading mechanism wasn't protecting the values of the errorCode and errorInfo variables. 3/29/95 (new feature) Added optional pattern argument to "parray" procedure. 3/29/95 (bug fix) Made the full functionality of "return -code ... -errorcode ..." work not just inside procedures, but also in sourced files and at top level. 4/6/95 (new feature) Added "pattern" option to "array names" command. 4/18/95 (bug fix) Fixed bug in parser where it didn't allow backslash-newline immediately after an argument in braces or quotes. 4/19/95 (new feature) Added tcl_library variable, which application can set to override default library directory. 4/30/95 (bug fix) During trace callbacks for array elements, the variable name used in the original reference would be temporarily modified to separate the array name and element name; if the trace callback used the same name string, it would get the wrong name (the array name without element). Fixed to restore the variable name before making trace callbacks. 4/30/95 (new feature) Added -nobackslashes, -nocommands, and -novariables switches to "subst" command. 5/4/95 (new feature) Added TCL_EVAL_GLOBAL flag to Tcl_RecordAndEval. 5/5/95 (bug fix) Format command would overrun memory when printing integers with very large precision, as in "format %.1000d 0". 5/5/95 (portability improvement) Changed to use BSDgettimeofday on IRIX machines, to avoid compilation problems with the gettimeofday declaration. 5/6/95 (bug fix) Changed manual entries to use the standard .TH macro instead of a custom .HS macro; the .HS macro confuses index generators like makewhatis. 5/9/95 (bug fix) Modified configure script to check for Solaris bug that makes vfork unreliable (core dumps result if vforked child changes a signal handler); will use fork instead of vfork if the bug is present. 6/5/95 (bug fix) Modified "lsort" command to disallow recursive calls to lsort from a comparison function. This is needed because qsort is not reentrant. 6/5/95 (bug fix) Undid change 243 above: changed TCL_VOLATILE and TCL_DYNAMIC back to integer constants rather than procedure addresses. This was needed because procedure addresses can have multiple values under some dynamic loading systems (e.g. SunOS 4.1 and Windows). 6/8/95 (feature change) Modified interface to Tcl_Main to pass in the address of the application-specific initialization procedure. Tcl_AppInit is no longer hardwired into Tcl_Main. This is needed in order to make Tcl a shared library. 6/8/95 (feature change) Modified Makefile so that the installed versions of tclsh and libtcl.a have version number in them (e.g. tclsh7.4 and libtcl7.4.a) and the library directory name also has an embedded version number (e.g., /usr/local/lib/tcl7.4). This should make it easier for Tcl 7.4 to coexist with earlier versions. ----------------- Released version 7.4b4, 6/16/95 ------------------ 6/19/95 (bug fix) Fixed bugs in tclCkalloc.c that caused core dumps if TCL_MEM_DEBUG was enabled on word-addressed machines such as Crays. 6/21/95 (feature removal) Removed overflow checks for integer arithmetic: they just cause too much trouble (e.g. for random number generators). 6/28/95 (new features) Added tcl_patchLevel and tcl_version variables, for consistency with Tk. 6/29/95 (bug fix) Fixed problem in Tcl_Eval where it didn't record the right termination character if a script ended with a comment. This caused erroneous output for the following command, among others: puts "[ expr 1+1 # duh! ]" 6/29/95 (message change) Changed the error message for ECHILD slightly to provide a hint about why the problem is occurring. ----------------- Released version 7.4, 7/1/95 ------------------ 7/18/95 (bug fix) Changed "lreplace" so that nothing is deleted if the last index is less than the first index or if the last index is < 0. 7/18/95 (bug fix) Fixed bugs with backslashes in comments: Tcl_CommandComplete (and "info complete") didn't properly handle strings ending in backslash-newline, and neither Tcl_CommandComplete nor the Tcl parser handled other backslash sequences right, such as two backslashes before a newline. 7/19/95 (bug fix) Modified Tcl_DeleteCommand to delete the hash table entry for the command before invoking its callback. This is needed in order to deal with reentrancy. 7/22/95 (bug fix) "exec" wasn't reaping processes correctly after certain errors (e.g. if the name of the executable was bogus, as in "exec foobar"). 7/27/95 (bug fix) Makefile.in wasn't using the LIBS variable provided by the "configure" script. This caused problems on some SCO systems. 7/27/95 (bug fix) The version of strtod in fixstrtod.c didn't properly handle the case where endPtr == NULL. ----------------- Released patch 7.4p1, 7/29/95 ----------------------- 8/4/95 (bug fix) C-level trace callbacks for variables were sometimes receiving the PART1_NOT_PARSED flag, which could cause errors in subsequent Tcl library calls using the flags. (JO) 8/4/95 (bug fix) Calls to toupper and tolower weren't using the UCHAR macros, which caused trouble in non-U.S. locales. (JO) 8/10/95 (new feature) Added the "load" command for dynamic loading of binary packages, and the Tcl_PackageInitProc prototype for package initialization procedures. (JO) 8/23/95 (new features) Added "info sharedlibextension" and "info nameofexecutable" commands, plus Tcl_FindExtension procedure. (JO) 8/25/95 (bug fix) If the target of an "upvar" was non-existent but had traces set, the traces were silently lost. Change to generate an error instead. (JO) 8/25/95 (bug fix) Undid change from 7/19, so that commands can stay around while their deletion callbacks execute. Added lots of code to handle all of the reentrancy problems that this opens up. (JO) 8/25/95 (bug fix) Fixed core dump that could occur in TclDeleteVars if there was an upvar from one entry in the table to the next entry in the same table. (JO) 8/28/95 (bug fix) Exec wasn't handling bad user names properly, as in "exec ~bogus_user/foo". (JO) 8/29/95 (bug fixes) Changed backslash-newline handling to correct two problems: - Only spaces and tabs following the backslash-newline are now absorbed as part of the backslash-newline. Newlinew are no longer absorbed (add another backslash if you want to absorb another newline). - TclWordEnd returns the character just before the backslash in the sequence as the end of the sequence; it used to not consider the backslash-newline as a word separator. (JO) 8/31/95 (new feature) Changed man page installation (with "mkLinks" script) to create additional links for manual pages corresponding to each of the procedure and command names described in the pages. (JO) 9/10/95 Reorganized Tcl sources for Windows and Mac ports. All sources are now in subdirectories: "generic" contains sources that work on all platforms, "windows", "mac", and "unix" directories contain platform- specific sources. Some UNIX sources are also used on other platforms. (SS) 9/10/95 (feature change) Eliminated exported global variables (they don't work with Windows DLLs). Replaced tcl_AsyncReady and tcl_FileCloseProc with procedures Tcl_AsyncReady() and Tcl_SetFileCloseProc(). Replaced C variable tcl_RcFileName with a Tcl variable tcl_rcFileName. (SS) *** POTENTIAL INCOMPATIBILITY *** 9/11/95 (new feature) Added procedure Tcl_SetPanicProc to override the default implementation of "panic". (SS) 9/11/95 (new feature) Added "interp" command to allow creation of new interpreters and execution of untrusted scripts. Added many new procedures, such as Tcl_CreateSlave, Tcl_CreateAlias,and Tcl_MakeSafe, to provide C-level access to the interpreter facility. This mechanism now provides almost all of the generic functions of Borenstein's and Rose's Safe-Tcl (but not any Tk or email-related stuff). (JL) 9/11/95 (feature change) Changed file management so that files are no longer shared between interpreters: a file cannot normally be referenced in one interpreter if it was opened in another. This feature is needed to support safe interpreters. Added Tcl_ShareHandle() procedure for allowing files to be shared, and added "interp" argument to Tcl_FilePermissions procedure. (JL) *** POTENTIAL INCOMPATIBILITY *** 9/11/95 (new feature) Added "AssocData" mechanism, whereby extensions can associate their own data with an interpreter and get called back when the interpreter is deleted. This is visible at C level via the procedures Tcl_SetAssocData and Tcl_GetAssocData. (JL) 9/11/95 (new feature) Added Tcl_ErrnoMsg to translate an errno value into a human-readable string. This is now used instead of calling strerror because strerror mesages vary dramatically from platform to platform, which messes up Tcl tests. Tcl_ErrnoMsg uses the standard POSIX messages for all the common signals, and calls strerror for signals it doesn't understand. ----------------- Released patch 7.4p2, 9/15/95 ----------------------- ----------------- Released 7.5a1, 9/15/95 ----------------------- 9/22/95 (bug fix) Changed auto_mkindex to create tclIndex files that handle directories whose paths might contain spaces. (RJ) 9/27/95 (bug fix) The "format" command didn't check for huge or negative width specifiers, which could cause core dumps. (JO) 9/27/95 (bug fix) Core dumps could occur if an interactive command typed to tclsh returned a very long result for tclsh to print out. The bug is actually in printf (in Solaris 2.3 and 2.4, at least); switched to use puts instead. (JO) 9/28/95 (bug fix) Changed makefile.bc to eliminate a false dependency for tcl1675.dll on the Borland run time library. (SS) 9/28/95 (bug fix) Fixed tcl75.dll so it looks for tcl1675.dll instead of tcl16.dll. (SS) 9/28/95 (bug fix) Tcl was not correctly detecting the difference between Win32s and Windows '95. (SS) 9/28/95 (bug fix) "exec" was not passing environment changes to child processes under Windows. (SS) 9/28/95 (bug fix) Changed Tcl to ensure that open files are not passed to child processes under Windows. (SS) 9/28/95 (bug fix) Fixed Windows '95 and NT versions of exec so it can handle both console and windows apps. (SS) 9/28/95 (bug fix) Fixed Windows version of exec so it no longer leaves temp files lying around. Also changed it so the temp files are created in the appropriate system dependent temp directory. (SS) 9/28/95 (bug fix) Eliminated source dependency on the Win32s Universal Thunk header file, since it is not bundled with VC++. (SS) 9/28/95 (bug fix) Under Windows, Tcl now constructs the HOME environment variable from HOMEPATH and HOMEDRIVE when HOME is not already set. (SS) 9/28/95 (bug fix) Added support for "info nameofexecutable" and "info sharedlibextension" to the Windows version. (SS) 9/28/95 (bug fix) Changed tclsh to correctly parse command line arguments so that backslashes are preserved under Windows. (SS) 9/29/95 (bug fix) Tcl 7.5a1 treated either return or newline as end of line in "gets", which caused lines ending in CRLF to be treated as two separate lines. Changed to allow only character as end-of-line: carriage return on Macs, newline elsewhere. (JO) 9/29/95 (new feature) Changed to install "configInfo" file in same directory as library scripts. It didn't used to get installed. (JO) 9/29/95 (bug fix) Tcl was not converting Win32 errors into POSIX errors under some circumstances. (SS) 10/2/95 (bug fix) Safe interpreters no longer get initialized with a call to Tcl_Init(). (JL) 10/1/95 (new feature) Added "tcl_platform" global variable to provide environment information such as the instruction set and operating system. (JO) 10/1/95 (bug fix) "exec" command wasn't always generating the "child process exited abnormally" message when it should have. (JO) 10/2/95 (bug fix) Changed "mkLinks.tcl" so that the scripts it generates won't create links that overwrite original manual entries (there was a problem where pack-old.n was overwriting pack.n). (JO) 10/2/95 (feature change) Changed to use -ldl for dynamic loading under Linux if it is available, but fall back to -ldld if it isn't. (JO) 10/2/95 (bug fix) File sharing was causing refcounts to reach 0 prematurely for stdin, stdout and stderr, under some circumstances. (JL) 10/2/95 (platform support) Added support for Visual C++ compiler on Windows, Windows '95 and Windows NT, code donated by Gordon Chaffee. (JL) 10/3/95 (bug fix) Tcl now frees any libraries that it loads before it exits. (SS) 10/03/95 (bug fix) Fixed bug in Macintosh ls command where the -l and -C options would fail in anything but the HOME directory. (RJ) ----------------- Released 7.5a2, 10/6/95 ----------------------- 10/10/95 (bug fix) "file dirnam /." was returning ":" on UNIX instead of "/". (JO) 10/13/95 (bug fix) Eliminated dependency on MKS toolkit for generating the tcl.def file from Borland object files. (SS) 10/17/95 (new features) Moved the event loop from Tcl to Tk, made major revisions along the way: - New Tcl commands: after, update, vwait (replaces "tkwait variable"). - "tkerror" is now replaced with "bgerror". - The following procedures are similar to their old Tk counterparts: Tcl_DoOneEvent, Tcl_Sleep, Tcl_DoWhenIdle, Tcl_CancelIdleCall, Tcl_CreateFileHandler, Tcl_DeleteFileHandler, Tcl_CreateTimerHandler, Tcl_DeleteTimerHandler, Tcl_BackgroundError. - Revised notifier, add new concept of "event source" with the following procedures: Tcl_CreateEventSource, Tcl_DeleteEventSource, Tcl_WatchFile, Tcl_SetMaxBlockTime, Tcl_FileReady, Tcl_QueueEvent, Tcl_WaitForEvent. (JO) 10/31/95 (new features) Implemented cross platform file name support to make it easier to write cross platform scripts. Tcl now understands 4 file naming conventions: Windows (both DOS and UNC), Mac, Unix, and Network. The network convention is a new naming mechanism that can be used to paths in a platform independent fashion. See the "file" command manual page for more details. The primary interfaces changes are: - All Tcl commands that expect a file name now accept both network and native form. - Two new "file" subcommands, "nativename" and "networkname", provide a way to convert between network and native form. - Renamed Tcl_TildeSubst to Tcl_TranslateFileName, and changed it so that it always returns a filename in native form. Tcl_TildeSubst is defined as a macro for backward compatibility, but it is deprecated. (SS) 11/5/95 (new feature) Made "tkerror" and "bgerror" synonyms, so that either name can be used to manipulate the command (provides temporary backward compatibility for existing scripts that use tkerror). (JO) 11/5/95 (new feature) Added exit handlers and new C procedures Tcl_CreateExitHandler, Tcl_DeleteExitHandler, and Tcl_Exit. (JO) 11/6/95 (new feature) Added pid command for Macintosh version of Tcl (it didn't previously exist on the Mac). (RJ) 11/7/95 (new feature) New generic IO facility and support for IO to files, pipes and sockets based on a common buffering scheme. Support for asynchronous (non-blocking) IO and for event driver IO. Support for automatic (background) asynchronous flushing and asynchronous closing of channels. (JL) 11/7/95 (new feature) Added new commands "fconfigure" and "fblocked" to support new I/O features such as nonblocking I/O. Added "socket" command for creating TCP client and server sockets. (JL). 11/7/95 (new feature) Complete set of C APIs to the new generic IO facility: - Opening channels: Tcl_OpenFileChannel, Tcl_OpenCommandChannel, Tcl_OpenTcpClient, Tcl_OpenTcpServer. - I/O procedures on channels, which roughly mirror the ANSI C stdio library: Tcl_Read, Tcl_Gets, Tcl_Write, Tcl_Flush, Tcl_Seek, Tcl_Tell, Tcl_Close, Tcl_Eof, Tcl_InputBlocked, Tcl_GetChannelOption, Tcl_SetChannelOption. - Extension mechanism for creating new kinds of channels: Tcl_CreateChannel, Tcl_GetChannelInstanceData, Tcl_GetChannelType, Tcl_GetChannelName, Tcl_GetChannelFile, Tcl_RegisterChannel, Tcl_UnregisterChannel, Tcl_GetChannel. - Event-driven I/O on channels: Tcl_CreateChannelHandler, Tcl_DeleteChannelHandler. (JL) 11/7/95 (new feature) Channel driver interface specification to allow new types of channels to be added easily to Tcl. Currently being used in three drivers - for files, pipes and TCP-based sockets. (JL). 11/7/95 (new feature) interp delete now takes any number of path names of interpreters to delete, including zero. (JL). 11/8/95 (new feature) implemented 'info hostname' and Tcl_GetHostName command to get host name of machine on which the Tcl process is running. (JL) 11/9/95 (new feature) Implemented file APIs for access to low level files on each system. The APIs are: Tcl_CloseFile, Tcl_OpenFile, Tcl_ReadFile, Tcl_WriteFile and Tcl_SeekFile. Also implemented Tcl_WaitPid which waits in a system dependent manner for a child process. (JL) 11/9/95 (new feature) Added Tcl_UpdateLinkedVar procedure to force a Tcl variable to be updated after its C variable changes. (JO) 11/9/95 (bug fix) The glob command has been totally reimplemented so that it can support different file name conventions. It now handles Windows file names (both UNC and drive-relative) properly. It also supports nested braces correctly now. (SS) 11/13/95 (bug fix) Fixed Makefile.in so that configure can be run from a clean directory separate from the Tcl source tree, and compilations can be performed there. (JO) 11/14/95 (bug fix) Fixed file sharing between interpreters and file transferring between interpreters to correctly manage the refcount so that files are closed when the last reference to them is discarded. (JL) 11/14/95 (bug fix) Fixed gettimeofday implementation for the Macintosh. This fixes several timing related bugs. (RJ) 11/17/95 (new feature) Added missing support for info nameofexecutable on the Macintosh. (RJ) 11/17/95 (bug fix) The Tcl variables argc argv and argv0 now return something reasonable on the Mac. (RJ) 11/22/95 (new feature) Implemented "auto-detect" mode for end of line translations. On input, standalone "\r" mean MAC mode, standalone "\n" mean Unix mode and "\r\n" means Windows mode. On output, the mode is modified to whatever the platform specific mode for that platform is. (JL) 11/24/95 (feature change) Replaced "configInfo" file with tclConfig.sh, which is more complete and uses slightly different names. Also arranged for tclConfig.sh to be installed in the platform-specific library directory instead of Tcl's script library directory. (JO) *** POTENTIAL INCOMPATIBILITY with Tcl 7.5a2, but not with Tcl 7.4 *** ----------------- Released patch 7.4p3, 11/28/95 ----------------------- 12/5/95 (new feature) Added Tcl_File facility to support platform- independent file handles. Changed all interfaces that used Unix- style integer fd's to use Tcl_File's instead. (SS) *** POTENTIAL INCOMPATIBILITY *** 12/5/95 (new feature) Added a new "clock" command to Tcl. The command allows you to get the current "clicks" or seconds & allows you to format or scan human readable time/date strings. (RJ) 12/18/95 (new feature) Moved Tk_Preserve, Tk_Release, and Tk_EventuallyFree to Tcl, renamed to Tcl_Preserve, Tcl_Release, and Tcl_EventuallyFree. (JO) 12/18/95 (new feature) Added new "package" command and associated procedures Tcl_PkgRequire and Tcl_PkgProvide. Also wrote pkg_mkIndex library procedure to create index files from binaries and scripts. (JO) 12/20/95 (new feature) Added Tcl_WaitForFile procedure. (JO) 12/21/95 (new features) Made package name argument to "load" optional (Tcl will now attempt to guess the package name if necessary). Also added Tcl_StaticPackage and support in "load" for statically linked packages. (JO) 12/22/95 (new feature) Upgraded the foreach command to accept multiple loop variables and multiple value lists. This lets you iterate over multiple lists in parallel, and/or assign multiple loop variables from one value list during each iteration. The only potential compatibility problem is with scripts that used loop variables with a name that could be construed to be a list of variable names (i.e. contained spaces). (BW) 1/5/96 (new feature) Changed tclsh so it builds as a console mode application under Windows. Now tclsh can be used from the command line with pipes or interactively. Note that this only works under Windows 95 or NT. (SS) 1/17/96 (new feature) Modified Makefile and configure script to allow Tcl to be compiled as a shared library: use the --enable-shared option when configuing. (JO) 1/17/96 (removed obsolete features) Removed the procedures Tcl_EnterFile and Tcl_GetOpenFile: these no longer make sense with the new I/O system. (JL) *** POTENTIAL INCOMPATIBILITY *** 1/19/96 (bug fixes) Prevented formation of circular aliases, through the Tcl 'interp alias' command and through the 'rename' command, as well as through the C API Tcl_CreateAlias. (JL) 1/19/96 (bug fixes) Fixed several bugs in direct deletion of interpreters with Tcl_DeleteInterp when the interpreter is a slave; fixes based on a patch received from Viktor Dukhovni of ESM. (JL) 1/19/96 (new feature) Implemented on-close handlers for channels; added the C APIs Tcl_CreateCloseHandler and Tcl_DeleteCloseHandler. (JL) 1/19/96 (new feature) Implemented portable error reporting mechanism; added the C APIs Tcl_SetErrno and Tcl_GetErrno. (JL) 1/24/96 (bug fix) Unknown command processing properly invokes external commands under Windows NT and Windows '95 now. (SS) 1/23/96 (bug fix) Eliminated extremely long startup times under Windows '95. The problem was a result of the option database initialization code that concatenated $HOME with /.Xdefaults, resulting in a // in the middle of the file name. Under Windows '95, this is incorrectly interpreted as a UNC path. They delays came from the network timeouts needed to determine that the file name was invalid. Tcl_TranslateFileName now suppresses duplicate slashes that aren't at the beginning of the file name. (SS) 1/25/96 (bug fix) Changed exec and open to create children so they are attached to the application's console if it exists. (SS) 1/31/96 (bug fix) Fixed command line parsing to handle embedded spaces under Windows. (SS) ----------------- Released 7.5b1, 2/1/96 ----------------------- 2/7/96 (bug fix) Fixed off by one error in argument parsing code under Windows. (SS) 2/7/96 (bug fix) Fixed bugs in VC++ makefile that improperly initialized the tcl75.dll. Fixed bugs in Borland makefile that caused build failures under Windows NT. (SS) 2/9/96 (bug fix) Fixed deadlock problem in AUTO end of line translation mode which would cause a socket server with several concurrent clients writing in CRLF mode to hang. (JL) 2/9/96 (API change) Replaced -linemode option to fconfigure with a new -buffering option, added "none" setting to enable immediate write. (JL) *** INCOMPATIBILITY with b1 *** 2/9/96 (new feature) Added C API Tcl_InputBuffered which returns the count of bytes currently buffered in the input buffer of a channel, and o for output only channels. (JL) 2/9/96 (new feature) Implemented asynchronous connect for sockets. (JL) 2/9/96 (new feature) Added C API Tcl_SetDefaultTranslation to set (per channel) the default end of line translation mode. This is the mode that will be installed if an output operation is done on the channel while it is still in AUTO mode. (JL) 2/9/96 (bug fix) Changed Tcl_OpenCommandChannel interface to properly handle all of the combinations of stdio inheritance in background pipelines. See the Tcl_OpenFileChannel(3) man page for more info. This change fixes the bug where exec of a background pipeline was not getting passed the stdio handles properly. (SS) 2/9/96 (bug fix) Removed the new Tcl_CreatePipeline interface, and restored the old version for Unix platforms only. All new code should use Tcl_CreateCommandChannel instead. (SS) 2/9/96 (bug fix) Changed Makefile.in to use -L and -ltcl7.5 for Tcl library so that shared libraries are more likely to be found correctly on more platforms. (JO) 2/13/96 (new feature) Added C API Tcl_SetNotifierData and Tcl_GetNotifierData to allow notifier and channel driver writers to associate data with a Tcl_File. The result of this change is that Tcl_GetFileInfo now always returns an OS file handle, and Tcl_GetFile can be used to construct a Tcl_File for an externally constructed OS handle. (SS) 2/13/96 (bug fix) Changed Windows socket implementation so it doesn't set SO_REUSEADDR on server sockets. Now attempts to create a server socket on a port that is already in use will be properly identified and an error will be generated. (SS) 2/13/96 (bug fix) Fixed problems with DLL initialization under Visual C++ that left the C run time library uninitialized. (SS) 2/13/96 (bug fix) Fixed Windows socket initialization so it loads winsock the first time it is used, rather than at the time tcl75.dll is loaded. This should fix the bug where the modem immediately starts trying to connect to a service provider when wish or tclsh are started. (SS) 2/13/96 (new feature) Added C APIs Tcl_MakeFileChannel and Tcl_MakeTcpClientChannel to wrap up existing fds and sockets into channels. Provided implementations on Unix and Windows. (JL) 2/13/96 (bug fix) Fixed bug with seek leaving EOF and BLOCKING set. (JL) 2/14/96 (bug fix) Fixed reentrancy problem in fileevent handling and made it more robust in the face of errors. (JL) 2/14/96 (feature change) Made generic IO level emulate blocking mode if the channel driver is unable to provide it, e.g. if the low level device is always nonblocking. Thus, now blocking behavior is an advisory setting for channel drivers and can be ignored safely if the channel driver is unable to provide it. (JL) 2/15/96 (new feature) Added "binary" end of line translation mode, which is a synonym of "lf" mode. (JL) 2/15/96 (bug fix) Fixed reentrancy problem in fileevent handling vs deletion of channel event handlers. (JL) 2/15/96 (bug fix) Fixed bug in event handling which would cause a nonblocking channel to not see further readable events after the first readable event that had insufficient input. (JL) 2/17/96 (bug fix) "info complete" didn't properly handle comments in nested commands. (JO) 2/21/96 (bug fix) "exec" under Windows NT/95 did not properly handle very long command lines (>200 chars). (SS) 2/21/96 (bug fix) Sockets could get into an infinite loop if a read event arrived after all of the available data had been read. (SS) 2/22/96 (bug fix) Added cast of st_size elements to (long) before sprintf-ing in "file size" command. This is needed to handle systems like NetBSD with 64-bit file offsets. (JO) ----------------- Released 7.5b2, 2/23/96 ----------------------- 2/23/96 (bug fix) TCL_VARARGS macro in tcl.h wasn't defined properly when compiling with C++. (JO) 2/24/96 (bug fix) Removed dependencies on Makefile in the UNIX Makefile: this caused problems on some platforms (like Linux?). (JO) 2/24/96 (bug fix) Fixed configuration bug that made Tcl not compile correctly on Linux machines with neither -ldl or -ldld. (JO) 2/24/96 (new feature) Added a block of comments and definitions to Makefile.in to make it easier to have Tcl's TclSetEnv etc. replace the library procedures setenv etc, so that calls to setenv etc. in the application automatically update the Tcl "env" variable. (JO) 2/27/96 (feature change) Added optional Tcl_Interp * argument (may be NULL) to C API Tcl_Close and simplified closing of command channels. (JL) *** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** 2/27/96 (feature change) Added optional Tcl_Interp * argument (may be NULL) to C type definition Tcl_DriverCloseProc; modified all channel drivers to implement close procedures that accept the additional argument. (JL) *** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** 2/28/96 (bug fix) Fixed memory leak that could occur if an upvar referred to an element of an array in the same stack frame as the upvar. (JO) 2/29/96 (feature change) Modified both Tcl_DoOneEvent and Tcl_WaitForEvent so that they return immediately in cases where they would otherwise block forever (e.g. if there are no event handlers of any sort). (JO) 2/29/96 (new feature) Added C APIs Tcl_GetChannelBufferSize and Tcl_SetChannelBufferSize to set and retrieve the size, in bytes, for buffers allocated to store input or output in a channel. (JL) 2/29/96 (new feature) Added option -buffersize to Tcl fconfigure command to allow Tcl scripts to query and set the size of channel buffers. (JL) 2/29/96 (feature removed) Removed channel driver function to specify the buffer size to use when allocating a buffer. Removed the C typedef for Tcl_DriverBufferSizeProc. Channels are now created with a default buffer size of 4K. (JL) *** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** 2/29/96 (feature change) The channel driver function for setting blocking mode on the device may now be NULL. If the generic code detects that the function is NULL, operations that set the blocking mode on the channel simply succeed. (JL) 3/2/96 (bug fix) Fixed core dump that could occur if a syntax error (such as missing close paren) occurred in an array reference with a very long array name. (JO) 3/4/96 (bug fix) Removed code in the "auto_load" procedure that deletes all existing auto-load information whenever the "auto_path" variable is changed. Instead, new information adds to what was already there. Otherwise, changing the "auto_path" variable causes all package- related information to be lost. If you really want to get rid of existing auto-load information, use auto_reset before setting auto_path. (JO) 3/5/96 (new feature) Added version suffix to shared library names so that Tcl will compile under NetBSD and FreeBSD (I hope). (JO) 3/6/96 (bug fix) Cleaned up error messages in new I/O system to correspond more closely to old I/O system. (JO) 3/6/96 (new feature) Added -myaddr and -myport options to the socket command, removed -tcp and -- options. This lets clients and servers choose a particular interface. Also changed the default server address from the hostname to INADDR_ANY. The server accept callback now gets passed the client's port as well as IP address. The C interfaces for Tcl_OpenTcpClient and Tcl_OpenTcpServer have changed to support the above changes. (BW) *** POTENTIAL INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** 3/6/96 (changed feature) The library function auto_mkindex will now default to using the pattern "*.tcl" if no pattern is given. (RJ) 3/6/96 (bug fix) The socket channel code for the Macintosh has been rewritten to use native MacTcp. (RJ) 3/7/96 (new feature) Added Tcl_SetStdChannel and Tcl_GetStdChannel interfaces to allow applications to explicitly set and get the global standard channels. (SS) 3/7/96 (bug fix) Tcl did close not the file descriptors associated with "stdout", etc. when the corresponding channels were closed. (SS) 3/7/96 (bug fix) Reworked shared library and dynamic loading stuff to try to get it working under AIX. Added new @SHLIB_LD_LIBS@ autoconf symbol as part of this. AIX probably doesn't work yet, but it should be a lot closer. (JO) 3/7/96 (feature change) Added Tcl_ChannelProc typedef and changed the signature of Tcl_CreateChannelHandler and Tcl_DeleteChannelHandler to take Tcl_ChannelProc arguments instead of Tcl_FileProc arguments. This change should not affect any code outside Tcl because the signatures of Tcl_ChannelProc and Tcl_FileProc are compatible. (JL) 3/7/96 (API change) Modified signature of Tcl_GetChannelOption to return an int instead of char *, and to take a Tcl_DString * argument. Modified the implementation so that the option name can be NULL, to mean that the call should retrieve a list of alternating option names and values. (JL) *** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** 3/7/96 (API change) Added Tcl_DriverSetOptionProc, Tcl_DriverGetOptionProc typedefs, added two slots setOptionProc and getOptionProc to the channel type structure. These may be NULL to indicate that the channel type does not support any options. (JL) *** INCOMPATIBILITY with Tcl 7.5b2, but not with Tcl 7.4 *** 3/7/96 (feature change) stdin, stdout and stderr can now be put into nonblocking mode. (JL) 3/8/96 (feature change) Eliminated dependence on the registry for finding the Tcl library files. (SS) ----------------- Released 7.5b3, 3/8/96 ----------------------- 3/12/96 (feature improvement) Modified startup script to look in several different places for the Tcl library directory. This should allow Tcl to find the libraries under all but the weirdest conditions, even without the TCL_LIBRARY environment variable being set. (JO) 3/13/96 (bug fix) Eliminated use of the "linger" option from the Windows socket implementation. (JL) 3/13/96 (new feature) Added -peername and -sockname options for fconfigure for socket channels. Code contributed by John Haxby of HP. (JL) 3/13/96 (bug fix) Fixed panic and core dump that would occur if the accept callback script on a server socket encountered an error. (JL) 3/13/96 (feature change) Added -async option to the Tcl socket command. If the command is creating a client socket and the flag is present, the client is connected asynchronously. If the option is absent (the default), the client socket is connected synchronously, and the command returns only when the connection has been completed or failed. This change was suggested by Mark Diekhans. (JL) 3/13/96 (feature change) Modified the signature of Tcl_OpenTcpClient to take an additional int argument, async. If nonzero, the client is connected to the server asynchronously. If the value is zero, the connection is made synchronously, and the call to Tcl_OpenTcpClient returns only when the connection fails or succeeds. This change was suggested by Mark Diekhans. (JL) *** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** 3/14/96 (bug fix) "tclsh bogus_file_name" didn't print an error message. (JO) 3/14/96 (bug fix) Added new procedures to tclCkalloc.c so that libraries and applications can be compiled with TCL_MEM_DEBUG even if Tcl isn't (however, the converse is still not true). Patches provided by Jan Nijtmans. (JO) 3/15/96 (bug fix) Marked standard IO handles of a process as close-on-exec to fix bug in Ultrix where exec was not sharing standard IO handles with subprocesses. Fix suggested by Mark Diekhans. (JL) 3/15/96 (bug fix) Fixed asynchronous close mechanism so that it closes the channel instead of leaking system resources. The manifestation was that Tcl would eventually run out of file descriptors if it was handling a large number of nonblocking sockets or pipes with high congestion. (JL) 3/15/96 (bug fix) Fixed tests so that they no longer leak file descriptors. The manifestation was that Tcl would eventually run out of file descriptors if the tests were rerun many times (> a hundred times on Solaris). (JL) 3/15/96 (bug fix) Fixed channel creation code so that it never creates unnamed channels. This would cause a panic and core dump when the channel was closed. (JL) 3/16/96 (bug fixes) Made lots of changes in configuration stuff to get Tcl working under AIX (finally). Tcl should now support the "load" command under AIX and should work either with or without shared libraries for Tcl and Tk. (JO) 3/21/96 (configuration improvement) Changed configure script so it doesn't use version numbers (as in -ltcl7.5 and libtcl7.5.so) under SunOS 4.1, where they don't work anyway. (JO) 3/22/96 (new feature) Added C API Tcl_InterpDeleted that allows extension writers to discover when an interpreter is being deleted. (JL) 3/22/96 (bug fix) The standard IO channels are now added to each trusted interpreter as soon as the interpreter is created. This ensures against the bug where a child would do IO before the master had done any, and then the child is destroyed - the standard IO channels would be then closed and the master would be unable to do any IO. (JL) 3/22/96 (bug fix) Made Tcl more robust against interpreter deletion, by using Tcl_Preserve, Tcl_Release and Tcl_EventuallyFree to split the process of interpreter deletion into two distinct phases. Also went through all of Tcl and added calls to Tcl_Preserve and Tcl_Delete where needed. (JL) 3/22/96 (bug fix) Fixed several places where C code was reading and writing into freed memory, especially during interpreter deletion. (JL) 3/22/96 (bug fix) Fixed very deep bug in Tcl_Release that caused memory to be freed twice if the release callback did Tcl_Preserve and Tcl_Release on the same memory as the chunk currently being freed. (JL) 3/22/96 (bug fix) Removed several memory leaks that would cause memory buildup on half-K chunks in the generic IO level. (JL) 3/22/96 (bug fix) Fixed several core dumps which occurred when new AssocData was being created during the cleanups in interpreter deletion. The solution implemented now is to loop repeatedly over the AssocData until none is left to clean up. (JL) 3/22/96 (bug fix) Fixed a bug in event handling which caused an infinite loop if there were no files being watched and no timer. Fix suggested by Jan Nijtmans. (JL) 3/22/96 (bug fix) Fixed Tcl_CreateCommand, Tcl_DeleteCommand to be more robust if the interpreter is being deleted. Also fixed several order dependency bugs in Tcl_DeleteCommand which kicked in when an interpreter was being deleted. (JL) 3/26/96 (bug fix) Upon a "short read", the generic code no longer calls the driver for more input. Doing this caused blocking on some platforms even on nonblocking channels. Bug and fix courtesy Mark Roseman. (JL) 3/26/96 (new feature) Added 'package Tcltest' which is present only in test versions of Tcl; this allows the testing commands to be loaded into new interpreters besides the main one. (JL) 3/26/96 (restored feature) Recreated the Tcl_GetOpenFile C API. You can now get a FILE * from a registered channel; Unix only. (JL) 3/27/96 (bug fix) The regular expression code did not support more than 9 subexpressions. It now supports up to 20. (SS) 4/1/96 (bug fixes) The CHANNEL_BLOCKED bit was being left on on a short read, so that fileevents wouldn't fire correctly. Bug reported by Mark Roseman.(JL, RJ) 4/1/96 (bug fix) Moved Tcl_Release to match Tcl_Preserve exactly, in tclInterp.c; previously interpreters were being freed only conditionally and sometimes not at all. (JL) 4/1/96 (bug fix) Fixed error reporting in slave interpreters when the error message was being generated directly by C code. Fix suggested by Viktor Dukhovni of ESM. (JL) 4/2/96 (bug fixes) Fixed a series of bugs in Windows sockets that caused events to variously get lost, to get sent multiple times, or to be ignored by the driver. The manifestation was blocking if the channel is blocking, and either getting EAGAIN or infinite loops if the channel is nonblocking. This series of bugs was found by Ian Wallis of Cisco. Now all tests (also those that were previously commented out) in socket.test pass. (JL, SS) 4/2/96 (feature change/bug fix) Eliminated network name support in favor of better native name support. Added "file split", "file join", and "file pathtype" commands. See the "file" man page for more details. (SS) *** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** 4/2/96 (bug fix) Changed implementation of auto_mkindex so tclIndex files will properly handle path names in a cross platform context. (SS) 4/5/96 (bug fix) Fixed Tcl_ReadCmd to use the channel buffer size as the chunk size it reads, instead of a fixed 4K size. Thus, on large reads, the user can set the channel buffer size to a large size and the read will occur orders of magnitude faster. For example, on a 2MB file, reading in 4K chunks took 34 seconds, while reading in 1MB chunks took 1.5 seconds (on a SS-20). Problem identified and fix suggested by John Haxby of HP. (JL) 4/5/96 (bug fix) Fixed socket creation code to invoke gethostbyname only if inet_addr failed (very unlikely). Before this change the order was reversed and this made things much slower than they needed to be (gethostbyname generally requires an RPC, which is slow). Problem identified and fix suggested by John Loverso of OSF. (JL) 4/9/96 (feature change) Modified "auto" translation mode so that it recognizes any of "\n", "\r" and "\r\n" in input as end of line, so that a file can have mixed end-of-line sequences. It now outputs the platform specific end of line sequence on each platform for files and pipes, and for sockets it produces crlf in output on all platforms. (JL) *** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** 4/11/96 (new feature) Added -eofchar option to Tcl_SetChannelOption to allow setting of an end of file character for input and output. If an input eof char is set, it is recognized as EOF and further input from the channel is not presented to the caller. If an output eof char is set, on output, that byte is appended to the channel when it is closed. On Unix and Macintosh, all channels start with no eof char set for input or output. On Windows, files and pipes start with input and output eof chars set to Crlt-Z (ascii 26), and sockets start with no input or output eof char. (JL) *** INCOMPATIBILITY with Tcl 7.5b3, but not with Tcl 7.4 *** 4/17/96 (bug fix) Fixed series of bugs with handling of crlf sequence split across buffer boundaries in input, in AUTO mode. (JL, BW) 4/17/96 (test suite improvement) Fixed test suite so that tests that depend on the availability of Unix commands such as echo, cat and others are not run if these commands are not present. (JL) 4/17/96 (test suite improvement) The socket test now automatically starts, on platformst that support exec, a separate process for remote testsing. (JL) ----------------- Released 7.5, 4/21/96 ----------------------- 5/1/96 (bug fix) "file tail ~" did not correctly return the tail portion of the user's home directory. (SS) 5/1/96 (bug fix) Fixed bug in TclGetEnv where it didn't lookup environment variables correctly: could confuse "H" and "HOME", for example. (JO) 5/1/96 (bug fix) Changed to install tclConfig.sh under "make install-binaries", not "make install-libraries". (JO) 5/2/96 (bug fix) Changed pkg_mkIndex not to attempt to "load" a file unless it has the standard shared library extension. On SunOS, attempts to load Tcl scripts cause the whole application to be aborted (there's no way to get the error back into Tcl). (JO) 5/7/96 (bug fix) Moved initScript in tclUnixInit.c to writable memory to avoid potential core dumps. (JO) 5/7/96 (bug fix) Auto_reset procedure was removing procedure from init.tcl, such as pkg_mkIndex. (JO) 5/7/96 (bug fix) Fixed cast on socket address resolution code that would cause a failure to connect on Dec Alphas. (JL) 5/7/96 (bug fix) Added "time", "subst" and "fileevent" commands to set of commands available in a safe interpreter. (JL) 5/13/96 (bug fix) Preventing OS level handles for stdin, stdout and stderr from being implicitly closed when the last reference to the standard channel containing that handle is discarded when an interpreter is deleted. Explicitly closing standard channels by using "close" still works. (JL) 5/21/96 (bug fix) Do not create channels for stdin, stdout and stderr on Unix if the devices are closed. This prevents a duplicate channel name panic later on when the fd is used to open a channel and the channel is registered in an interpreter. (JL) 5/23/96 (bug fix) Fixed bug that prevented the use of standard channels in interpreters created after the last interpreter was destroyed. In the sequence interp = Tcl_CreateInterp(); Tcl_DeleteInterp(interp); interp = Tcl_CreateInterp(); channels for stdio would not be available in the second interpreter. (JL) 5/23/96 (bug fix) Fixed bug that allowed Tcl_MakeFileChannel to create new channels with Tcl_Files in them that are already used by another channel. This would cause core dumps when the Tcl_Files were being freed twice. (JL) 5/23/96 (bug fix) Fixed a logical timing bug that caused a standard channel to be removed from the standard channel table too early when the channel was being closed. If the channel was being flushed asynchronously, it could get recreated before being actually destroyed, and the recreated channel would contain the same Tcl_File as the one being closed, leading to dangling pointers and core dumps. (JL) 5/27/96 (bug fix) Fixed a bug in Tcl_GetChannelOption which caused it to always return a list of one element, a list of the settings, for -translation and -eofchar options. Now correctly returns the value described by the documentation (Mark Diekhans found this, thanks!). (JL) 5/30/96 (bug fix) Fixed a couple of syntax errors in io.test. (JL) 5/30/96 (bug fix) If a fileevent scripts gets an error, delete it before causing a background error. This is to allow the error handler to reinstall the fileevent and to prevent infinite loops if the event loop is reentered in the error handler. (JL) 5/31/96 (bug fix) Channels now will get properly flushed on exit. (JL) 6/5/96 (bug fix) Changed Tcl_Ckalloc, Tcl_Ckfree, and Tcl_Ckrealloc to Tcl_Alloc, Tcl_Free, and Tcl_Realloc. Added documentation for these routines now that they are officially supported. Extension writers should use these routines instead of free() and malloc(). (SS) 6/10/96 (bug fix) Changes the Tcl close command so that it no longer waits on nonblocking pipes for the piped processes to exit; instead it reaps them in the background. (JL) 6/11/96 (bug fix) Increased the length of the listen queue for server sockets on Unix from 5 to 100. Some OSes will disregard this and reset it to 5, but we should try to get as long a queue as we can, for performance reasons. (JL) 6/11/96 (bug fix) Fixed windows sockets bug that caused a cascade of events if the fileevent script read less than was available. Now reading less than is available does not cause a flood of Tcl events. (JL, SS) 6/11/96 (bug fix) Fixed bug in background flushing on closed channels that would prevent the last buffer from getting flushed. (JL) 6/13/96 (bug fix) Fixed bug in Windows sockets that caused a core dump if a DLL linked with tcl.dll and referred to e.g. ntohs() without opening a Tcl socket. The problem was that the indirection table was not being initialized. (JL) 6/13/96 (bug fix) Fixed OS level resource leak that would occur when a Tcl channel was still registered in some interpreter when the process exits. Previously the channel was not being closed and the OS level handles were not being released; the output was being flushed but the device was not being closed. Now the device is properly closed. This was only a problem on Win3.1 and MacOS. (JL, SS) 6/28/96 (bug fix) Fixed bug where transient errors were leaving an error code around, so that it would erroneously get reported later. This bug was exercised intermittently by closing a channel to a file on a very loaded NFS server, or to a socket whose other end blocked. (JL, BW) 7/3/96 (bug fix) Fileevents declared in an interpreter are now deleted when the channel is closed in that interpreter. Before this fix, the fileevent would hang around until the channel is completely closed, and would cause errors if events happened before the channel was closed. This could happen in two cases: first if the channel is shared between several interpreters, and second if an async flush is in progress that prevents the channel from being closed until the flush finishes. (JL) 7/10/96 (bug fix) Fixed bugs in both "lrange" and "lreplace" commands where too much white space was being removed. For example, the command lreplace {\}\ hello} end end was returning "\}\", losing the significant space in the first list element and corrupting the list. (JO) 7/20/96 (bug fix) The procedure pkg_mkIndex didn't work properly for extensions that depend on Tk, because it didn't load Tk into the child interpreter before loading the extension. Now it loads Tk if Tk is present in the parent. (JO) 7/23/96 (bug fix) Added compat version of strftime to fix crashes resulting from bad implementations under Windows. (SS) 7/23/96 (bug fix) Standard implementations of gmtime() and localtime() under Windows did not handle dates before 1970, so they were replaced with a revised implementation. (SS) 7/23/96 (bug fix) Tcl would crash on exit under Borland 5.0 because the global environ pointer was left pointing to freed memory. (SS) 7/29/96 (bug fix) Fixed memory leak in Tcl_LoadCmd that could occur if a package's AppInit procedure called Tcl_StaticPackage to register static packages. (JO) 8/1/96 (bug fix) Fixed a series of bugs in Windows sockets so that async writebehind in the presence of read event handlers now works, and so that async writebehind also works on sockets for which a read event handler was declared and whose channels were then closed before the async write finished. The bug was reported by John Loverso and Steven Wahl, independently, test case supplied by John Loverso. (JL) ----------------- Released patch 7.5p1, 8/2/96 ----------------------- 5/8/96 (new feature) Added Tcl_GetChannelMode C API for retrieving whether a channel is open for reading and writing. (JL) 5/8/96 (API changes) Revised C APIs for channel drivers: - Removed all Tcl_Files from channel driver interface; you can now have channels that are not based on Tcl_Files. - Added channelReadyProc and watchChannelProc procedures to interface; these are used to implement event notification for channels. - Added getFileProc to channel driver, to allow the generic IO code to retrieve a Tcl_File from a channel (presumably if the channel uses Tcl_Files they will be stored inside its instanceData). (JL) *** INCOMPATIBILITY with Tcl 7.5 *** 5/8/96 (API change) The Tcl_CreateChannel C API was modified to not take Tcl_File arguments, and instead to take a mask specifying whether the channel is readable and/or writable. (JL) *** INCOMPATIBILITY with Tcl 7.5 *** 6/3/96 (bug fix) Made Tcl_SetVar2 robust against the case where the value of the variable is a NULL pointer instead of "". (JL) 6/17/96 (bug fix) Fixed "reading uninitialized memory" error reported by Purify, in Tcl_Preserve/Tcl_Release. (JL) 8/9/96 (bug fix) Fixed bug in init.tcl that caused incorrect error message if the act of autoloading a procedure caused the procedure to be invoked again. (JO) 8/9/96 (bug fix) Configure script produced bad library names and extensions under SunOS and a few other platforms if the --disable-load switch was used. (JO) 8/9/96 (bug fix) Tcl_UpdateLinkedVar generated an error if the variable being updated was read-only. (JO) 8/14/96 (bug fix) The macintosh now supports synchronous socket connections. Other minor bugs were also fixed. (RJ) 8/15/96 (configuration improvement) Changed the file patchlevel.h to be tclPatch.h. This avoids conflict with the Tk file and is now in 8.3 format on the Windows platform. (RJ) 8/20/96 (bug fix) Fixed core dump in interp alias command for interpreters created with Tcl_CreateInterp (as opposed to with Tcl_CreateSlave). (JL) 8/20/96 (bug fix) No longer masking ECONNRESET on Windows sockets so that the higher level of the IO mechanism sees the error instead of entering an infinite loop. (JL) 8/20/96 (bug fix) Destroying the last interpreter no longer closes the standard channels. (JL) 8/20/96 (bug fix) Closing one of the stdin, stdout or stderr channels and then opening a new channel now correctly assigns the new channel as the standard channel that was closed. (JL) 8/20/96 (bug fix) Added code to unix/tclUnixChan.c for using ioctl with FIONBIO instead of fcntl with O_NONBLOCK, for those versions of Unix where either O_NONBLOCK is not supported or implemented incorrectly. (JL) 8/21/96 (bug fix) Fixed "file extension" so it correctly returns the extension on files like "foo..c" as "..c" instead of ".c". (SS) 8/22/96 (bug fix) If environ[] contains static strings, Tcl would core dump in TclSetupEnv because it was trying to write NULLs into the actual data in environ[]. Now we instead copy as appropriate. (JL) 8/22/96 (added impl) Added missing implementation of Tcl_MakeTcpClientChannel for Windows platform. Code contributed by Mark Diekhans. (JL) 8/22/96 (new feature) Added a new memory allocator for the Macintosh version of Tcl. It's quite a bit faster than MetroWerk's version. (RJ) 8/26/96 (documentation update) Removed old change bars (for all changes in Tcl 7.5 and earlier releases) from manual entries. (JO) 8/27/96 (enhancement) The exec and open commands behave better and work in more situations under Windows NT and Windows 95. Documentation describes what is still lacking. (CS) 8/27/96 (enhancement) The Windows makefiles will now compile even if the compiler is not in the path and/or the compiler's environment variables have not been set up. (CS) 8/27/96 (configuration improvement) The Windows resource files are automatically updated when the version/patch level changes. The header file now has a comment that reminds the user which other files must be manually updated when the version/patch level changes. (CS) 8/28/96 (new feature) Added file manipulation features (copy, rename, delete, mkdir) that are supported on all platforms. They are implemented as subcommands to the "file" command. See the documentation for the "file" command for more information. (JH) ----------------- Released 7.6b1, 8/30/96 ----------------------- 9/3/96 (bug fix) Simplified code so that standard channels are created lazily, they are added to an interpreter lazily, and they are never added to a safe interpreter. (JL) 9/3/96 (bug fix) Closing a channel after closing a standard channel, e.g. stdout, would cause the implicit recreation of that standard channel. (JL) 9/3/96 (new feature) Now calling Tcl_RegisterChannel with a NULL interpreter increments the refcount so that code outside any interpreter can use channels that are also registered in interpreters, without worrying that the channel may turn into a dangling pointer at any time. Calling Tcl_UnregisterChannel with a NULL interpreter only decrements the recount so that code outside any interpreter can safely declare it is no longer interested in a channel. (JL) 9/4/96 (new features) Two changes to dynamic loading: - If the file name is empty in the "load" command and there is no statically loaded version of the package, a dynamically loaded version will be used if there is one. - Tcl_StaticPackage ignores redundant calls for the same package. (JO) 9/6/96 (bug fix) Platform specific procedures for manipulating files are no longer macros and have been prefixed with "Tclp", such as TclpRenameFile. Unix file code now handles symbolic links and other special files correctly. The semantics of file copy and file rename has been changed so that if a target directory exists, the source files will NOT be merged with the existing files. (JH) 9/6/96 (bug fix) If standard channel is NULL, because Tcl cannot connect to the standard channel, do not increment the refcount. The channel can be NULL if there is for example no standard input. (JL) 9/6/96 (portability improvement) Changed parsing of backslash sequences like \n to translate directly to absolute values like 0xa instead of letting the compiler do the translation. This guarantees that the translation is done the same everywhere. (JO) 9/9/96 (bug fix) If channel is opened and not associated with any interpreter, but Tcl decides to use it as one of the standard channels, it became impossible to close the channel with Tcl_Close -- instead you had to call Tcl_UnregisterChannel. Fixed now so that it's safe to call Tcl_Close even when Tcl is using the channel as one of the standard ones. (JL) 9/11/96 (feature change) The Tcl library is now placed in the Tcl shared libraries resource. You no longer need to place the Tcl files in your applications explicitly. (RJ) 9/11/96 (feature change) Extensions no longer automatically have the resource fork of the extension opened for it. Instead you need to use the tclMacLibrary.c file in your extension. (RJ) *** POTENTIAL INCOMPATIBILITY *** 9/12/96 (bug fix) The extension loading mechanism on the Macintosh now looks at the 'cfrg' resource to determine where to load the code fragment from. This means FAT fragments should now work. (RJ) 9/18/96 (enhancement) The exec and open commands behave better and work in more situations under Windows 3.X. Documentation describes what is still lacking. (CS) 9/19/96 (bug fix) Fixed a panic which would occur if you delete a non-existent alias before any aliases are created. Now instead correctly returns an error that the alias is not found. (JL) 9/19/96 (bug fix) Slave interpreters could rename aliases and they would not get deleted when the alias was being redefined. This led to dangling pointers etc. (JL) 9/19/96 (bug fix) Fixed a panic where a hash table entry was being deleted twice during alias management operations. (JL) 9/19/96 (bug fix) Fixed bug in event loop that could cause the input focus in Tk to get confused during menu traversal, among other problems. The problem was related to handling of the "marker" when its event was deleted. (JO) 9/26/96 (bug fix) Windows was losing EOF on a socket if the FD_CLOSE event happened to precede any left over FD_READ events. Now correctly remembers seeing FD_CLOSE, so that trailing FD_READ events are not discarded if they do not contain any data. This allows Tcl to correctly get a zero read and notice EOF. (JL) 9/26/96 (bug fix) Was not resetting READABLE state properly on sockets under Windows if the driver discarded an FD_READ event because no data was present. Now correctly resets the state. (JL) 9/30/96 (bug fix) Made EOF sticky on Windows sockets, so that fileevent readable will fire repeatedly until the socket is closed. Previously the fileevent fired only once. This could lead to never-closed connections if the Tcl script in the fileevent wasn't closing the socket immediately. (JL) 10/2/96 (new feature) Improved the package loader: - Added new variable tcl_pkgPath, which holds the default directories under which packages are normally installed (each package goes in a separate subdirectory of a directory in $tcl_pkgPath). These directories are included in auto_path by default. - Changed the package auto-loader to look for pkgIndex.tcl files not only in the auto_path directories but also in their immediate children. This should make it easier to install and uninstall packages (don't have to change auto_path or merge pkgIndex.tcl files). (JO) 10/3/96 (bug fix) Changed tclsh to look for tclshrc.tcl instead of tclsh.rc on startup under Windows. This is more consistent with wish and uses the right extension. (SS) *** POTENTIAL INCOMPATIBILITY *** 10/8/96 (bug fix) Convertclock does not parse 24-hour times of the form "hhmm" correctly when hour = 00. In the parse code, hour must be >= 100 for minutes to be non-zero. Thanks to Lint LaCour for this bug fix. (RJ) 10/11/96 (bug fix) Under Windows, the pid command returned the process handle instead of the process id. (SS) ----------------- Released 7.6, 10/16/96 ----------------------- 10/29/96 (bug fix) Under Windows, sockets would consume 100% CPU time after the first accept(), due to a typo. (JL) 10/29/96 (bug fix) Incorrect refcount management caused standard channels not to get deleted at process exit or DLL unload time, causing a memory leak of upwards of 20K each time. (JL) 11/7/96 (bug fix) Auto-exec didn't work on file names that contained spaces. (JO) 11/8/96 (bug fix) Fixed core dump that would occur if more than one call to Tcl_DeleteChannelHandler was made to delete a given channel handler. (JL) 11/8/96 (bug fix) Fixed test for return value in Tcl_Seek and Tcl_SeekCmd to only treat -1 as error, instead of all negative numbers. (JL) 11/12/96 (bug fix) Do not blocking waiting for processes at the end of a pipe during exit cleanup. (JL) 11/12/96 (bug fix) If we are in exit cleanup, do not close the system level file descriptors 0, 1 and 2. Previously they were being closed which is incorrect, in the embedded case. This led to weird behavior for programs that want to interpose on I/O through the standard file descriptors (e.g. Netscape Navigator). (JL) 11/15/96 (bug fix) Fixed core dump on Windows sockets due to dependency on deletion order at exit. Now all socket functions check to see if sockets are (still) initialized, before calling through function pointers. Before, they would call and might end up calling unloaded object code. (JL) 11/15/96 (bug fix) Fixed core dump in Windows socket initialization routine if sockets were not installed on the system. Before, it was not properly checking the result of attempting to load the socket DLL, so it would call through uninitialized function pointers. (JL) 11/15/96 (bug fix) Fixed memory leak in Windows sockets which left socket DLL handle open and could hold the socket DLL in memory uneccessarily, until a reboot. (JL) 12/4/96 (bug fix) Fixed bug in Macintosh socket code that could result in lost data if a client was closed too soon after sending data. (RJ) 12/17/96 (bug fix) Fixed deadlock bug in Windows sockets due to losing an event. This was happening because of an interaction between buffering and nonblocking mode on sockets. Now switched to sockets being blocking by default, so we are also no longer emulating blocking through a private event loop. (JL) 1/21/97 (performance bug fix) Client TCP connections were slow to create because getservbyname was always called on the port. Now this is only done if Tcl_GetInt fails. (BW) 1/21/97 (configuration fix) Made it possible to override TCL_PACKAGE_PATH during make. Previously it was only set during autoconf process. 1/29/97 (bug fix) Fixed some problems with the clock command that impacted how dates were scaned after the year 2000. (RJ) ----------------- Released 7.6p2, 1/31/97 ----------------------- 2/5/97 (bug fix) Fixed a bug where in CR-LF translation mode, \r bytes in the input stream were not being handled correctly. (JL) 2/24/97 (bug fix) Fix bug with exec under Win32s not being able to create stderr file which caused all execs to fail. Fixed temp file leak under Win32s. Fixed optional parameter bug with SearchPath that only happened under Win32s 1.25. (CCS) ---------------------------------------------------------- Changes for Tcl 7.6 go above this line. Changes for Tcl 7.7 go below this line. ---------------------------------------------------------- 5/8/96 (new feature) Added Tcl_Ungets C API for putting a sequence of bytes into a channel's input buffer. This can be used for "push" model channels where the input is obtained via callbacks instead of by request of the generic IO code. No Tcl procedure yet. (JL) 11/15/96 (new feature) Implemented hidden commands. New C APIs: Tcl_HideCommand -- hides an existing exposed command. Tcl_ExposeCommand -- exposes an existing hidden command. New tcl APIs: interp invokehidden -- invokes a hidden command in a slave. interp hide -- hides an existing exposed command. interp expose -- exposes an existing hidden command. interp hidden -- returns a list of hidden commands. The implementation of Safe Tcl now uses the new hidden commands facility to implement the safe base, instead of deleting the commands from a safe interpreter. (JL) 11/15/96 (new feature) Implemented the safe base, a mechanism for installing and requesting security policies, purely in Tcl code. Overloads the package command to also allow an interpreter to "require" a policy. The following new library commands are provided: tcl_safeCreateInterp -- creates a slave an initializes the policy mechanism. tcl_safeInitInterp -- initializes an existing slave with the policy mechanism. tcl_safeDeleteInterp -- deletes a slave and deinitializes the policy mechanism. Added a new file to the library, safeinit.tcl, to hold implementation. (JL) On 7/9/97, removed the policy loading mechanism from the Safe Base. Left only the Safe Base aliases dealing with auto-loading and source. (JL) 12/6/96 (new feature) Implemented Tcl_Finalize, an API that should be called by a process when it is done using Tcl. This API runs all the exit handlers to allow them to clean up resources etc. (JL) 12/17/96 (new feature) Add an http Tcl script package to the Tcl library. This package implements the client side of HTTP/1.0; the GET, HEAD, and POST requests. (BW) 1/21/97 (new feature) Added a "marktrusted" subcommand to the "interp" and to the interpreter object command. It removes the "safe" mark on an interpreter and disables hard-wired checks for safety in the C sources. (JL) 1/21/97 (removed feature) Removed "vwait" from set of commands available in a safe interpreter. (JL) 2/11/97 (new feature, bug fix) http package. Added -accept to http_config so you can set the Accept header. Added -handler option to http_get so you can supply your own data handler. Also fixed POST operation to set the correct MIME type on the request. (BW) ---------------------------------------------------------- Changes for Tcl 7.7 go above this line. Changes for Tcl 8.0 go below this line. ---------------------------------------------------------- 9/17/96 (bug fix) Using "upvar" it was possible to turn an array element into an array itself. Changed to disallow this; it was quirky and didn't really work correctly anyway. (JO) 10/21/96 (new feature) The core of the Tcl interpreter has been replaced with an on-the-fly compiler that translates Tcl scripts to bytecoded instructions; a new interpreter then executes the bytecodes. The compiler introduces only a few minor changes at the level of Tcl scripts. The biggest changes are to expressions and lists. - A second level of substitutions is no longer done for expressions. This substantially improves their execution time. This means that the expression "$x*4" produces a different result than in the past if x is "$y+2". Fortunately, not much code depends on the old two-level semantics. Some expressions that do, such as "expr [join $list +]" can be recoded to work in Tcl8.0 by adding an eval: e.g., "eval expr [join $list +]". - Lists are now completely parsed on the first list operation to create a faster internal representation. In the past, if you had a misformed list but the erroneous part was after the point you inserted or extracted an element, then you never saw an error. In Tcl8.0 an error will be reported. This should only effect incorrect programs that took advantage of behavior of the old implementation that was not documented in the man pages. Other changes to Tcl scripts are discussed in the web page at http://www.scriptics.com/doc/compiler.html. (BL) *** POTENTIAL INCOMPATIBILITY *** 10/21/96 (new feature) In earlier versions of Tcl, strings were used as a universal representation; in Tcl 8.0 strings are replaced with Tcl_Obj structures ("objects") that can hold both a string value and an internal form such as a binary integer or compiled bytecodes. The new objects make it possible to store information in efficient internal forms and avoid the constant translations to and from strings that occurred with the old interpreter. There are new many new C APIs for managing objects. Some of the new library procedures for objects (such as Tcl_EvalObj) resemble existing string-based procedures (such as Tcl_Eval) but take advantage of the internal form stored in Tcl objects for greater speed. Other new procedures manage objects and allow extension writers to define new kinds of objects. See the manual entries doc/*Obj*.3 (BL) 10/24/96 (bug fix) Fixed memory leak on exit caused by some IO related data structures not being deallocated on exit because their refcount was artificially boosted. (JL) 10/24/96 (bug fix) Fixed core dump in Tcl_Close if called with NULL Tcl_Channel. (JL) 11/19/96 (new feature) Added library procedures for finding word breaks in strings in a platform specific manner. See the library.n manual entry for more information. (SS) 11/22/96 (feature improvements) Added support for different levels of tracing during bytecode compilation and execution. This should help in tracking down suspected problems with the compiler or with converting existing code to use Tcl8.0. Two global Tcl variables, traceCompile and traceExec, can be set to generate tracing information in stdout: - traceCompile: 0 no tracing (default) 1 trace compilations of top level commands and procs 2 trace and display instructions for all compilations - traceExec: 0 no tracing 1 trace only calls to Tcl procs 2 trace invocations of all commands including procs 3 detailed trace showing the result of each instruction traceExec >= 2 provides a one line summary of each called command and its arguments. Commands that have been "compiled away" such as set are not shown. (BL) 11/30/96 (bug fix) The command "info nameofexecutable" could sometimes return the name of a directory. (JO) 11/30/96 (feature improvements) Changed the code in library/init.tcl that reads in pkgIndex.tcl so that (a) it reads the files from child directories before those in the parent, so that the parent gets precedence, and (b) it doesn't quit if there is an error in a pkgIndex.tcl file; instead, it prints an error message on standard error and continues. (JO) 10/5/96 (feature improvements) Partial implementation of binary string support: the ability for Tcl string values to contain embedded null bytes. Changed the Tcl object-based APIs to take a byte pointer and length pair instead of a null-terminated C string. Modified several object type managers to support binary strings but not, for example, the list type manager. Existing string-based C APIs are unchanged and will truncate binary strings. Compiled scripts containing nulls are also truncated. (BL) 12/12/96 (feature change) Removed the commands "cp", "mkdir", "mv", "rm", and "rmdir" from the Macintosh version of Tcl. They were never officially supported and their functionality is now available via the file command. (RJ) ----------------- Released 8.0a1, 12/20/96 ----------------------- 1/7/97 (bug fix) Under Windows, "file stat c:" was returning error instead of stat for current dir on c: drive. 1/10/97 (new feature) Added Tcl_GetIndexFromObj procedure for quick lookups of keyword arguments. (JO) 1/12/97 (new feature) Serial IO channel drivers for Windows and Unix, available by using Tcl open command to open pseudo-files like "com1:" or "/dev/ttya". New option to Tcl fconfigure command for serial files: "-mode baud,parity,data,stop" to specify baud rate, parity, data bits, and stop bits. Serial IO is not yet available on Mac. 1/16/97 (feature change) Restored the Tcl7.x "two level substitution semantics" for expressions. Expressions not enclosed in braces are implemented, in general, by calling the expr command procedure (Tcl_ExprObjCmd) at runtime after the Tcl interpreter has already done a first round of substitutions. This is slow (about Tcl7.x speed) because new code for the expression is generally compiled each time. However, if the expression has only variable substitutions (and not command substitutions), "optimistic" fast code is generated inline. This inline code will fail if a second round of substitutions is needed (i.e., if the value of a substituted variable itself requires more substitutions). The optimistic code will catch the error and back off to call the slower but guaranteed correct expr command procedure. (BL) 1/16/97 (feature improvements) Added Tcl_ExprLongObj and Tcl_ExprDoubleObj to round out expression-related procedures. (BL) 1/16/97 (feature change) Under Windows, at startup the environment variables "path", "comspec", and "windir" in any capitalization are converted automatically to upper case. The PATH variable could be spelled as path, Path, PaTh, etc. and it makes programming rather annoying. All other environment variables are left alone. (CS) 1/20/97 (new features) Rewrote the "lsort" command: - The new version is based on reentrant merge sort code provided by Richard Hipp, so it eliminates the reentrancy and stability problems with the old qsort-based implementation. - The new version supports a -dictionary option for sorting, and it also supports a -index option for sorting lists using one element for comparison. - The new version is an object command, so it works well with the Tcl compiler, especially in conjunction with the new -index option. When the -index option is used, this version of lsort is more than 100 times faster than the Tcl 7.6 lsort, which had to use the -command option to get the same effect. (JO) 1/20/97 (feature improvements) Added the improved debugging support for Tcl objects prototyped by Karl Lehenbauer . If TCL_MEM_DEBUG is defined, the object creation calls use Tcl_DbCkalloc directly in order to record the caller's source file name and line number. (BL) 1/21/97 (removed feature) Desupported the tcl_precision variable: if set, it is ignored. Tcl now uses the full 17 digits of precision when converting real numbers to strings (with the new object system real numbers are rarely converted to strings so there is no efficiency disadvantage to printing all 17 digits; the new scheme improves accuracy and simplifies several APIs). (JO) *** POTENTIAL INCOMPATIBILITY *** 1/21/97 (feature change) Removed the "interp" argument for the procedures Tcl_GetStringFromObj, Tcl_StringObjAppend, and Tcl_StringObjAppendObj. Also removed the "interp" argument for the updateStringProc procedure in Tcl_ObjType structures. With the tcl_precision changes above, these are no longer needed. (JO) *** POTENTIAL INCOMPATIBILITY with Tcl 8.0a1, but not with Tcl 7.6 *** 1/22/97 (bug fix) Fixed http.tcl so that http_reset does not result in an extra call to the command callback. In addition, if the transaction gets a premature eof, the state(status) is "eof", not "ok". (BW) ----------------- Released 8.0a2, 1/24/97 ----------------------- 1/29/97 (feature change) Changed how two digit years are parsed in the clock command. The old interface just added 1900 which will seem broken by the year 2000. The new scheme follows the POSIX standard and treats dates 70-99 as 1970-1999 and dates 00-38 as 2000-2038. All other two digit dates are undefined. (RJ) *** POTENTIAL INCOMPATIBILITY *** 2/4/97 (bug fix) Fixed bug in clock code that dealt with relative dates. Using the relative month code you could get an invalid date because it jumped into a non-existant day. (For example, Jan 31 to Feb 31.) The code now will return the last valid day of the month in these situations. Thanks to Hume Smith for sending in this bug fix. (RJ) 2/10/97 (feature change) Eliminated Tcl_StringObjAppend and Tcl_StringObjAppendObj procedures, replaced them with Tcl_AppendToObj and Tcl_AppendStringsToObj procedures. Added new procedure Tcl_SetObjLength. (JO) *** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2, but not with Tcl 7.6 *** 2/10/97 (new feature) Added Tcl_WrongNumArgs procedure for generating error messages about incorrect number of arguments. (JO) 2/11/97 (new feature, bug fix) http package. Added -accept to http_config so you can set the Accept header. Added -handler option to http_get so you can supply your own data handler. Also fixed POST operation to set the correct MIME type on the request. (BW) 2/22/97 (bug fix) Fixed bug that caused $tcl_platform(osVersion) to be computed incorrectly under AIX. (JO) 2/25/97 (new feature, feature change) Added support for both int and long integer objects. Added Tcl_NewLongObj/Tcl_GetLongFromObj/Tcl_SetLongFromObj procedures and renamed the Tcl_Obj internalRep intValue member to longValue. Tcl_GetIntFromObj now checks for integer values too large to represent as non-long integers. Changed Tcl_GetAllObjTypes to Tcl_AppendAllObjTypes. (BL) 3/5/97 (new feature) Added new Tcl_SetListObj procedure to round out collection of procedures that set the type and value of existing Tcl objects. (BL) 3/6/97 (new feature) Added -global flag for interp invokehidden. (JL) 3/6/97 (new feature, feature change) Added isNativeObjectProc field to the Tcl_CmdInfo structure to indicate (when 1) if the command has an object-based command procedure. Removed the nameLength arg from Tcl_CreateObjCommand since command names can't contain null characters. (BL) 3/6/97 (bug fix) Fixed bug in "unknown" procedure that caused auto- loading to fail on commands whose names begin with digits. (JO) 3/7/97 (bug fix) Auto-loading now works in Safe Base. Safe interpreters only accept the Version 2 and onwards tclIndex files. (JL) 3/13/97 (bug fix) Fixed core dump due to interaction between aliases and hidden commands. Bug found by Lindsay Marshall. (JL) 3/14/97 (bug fix) Fixed mac bugs relating to time. The -gmt option now adjusts the time in the correct direction. (Thanks to Ed Hume for reporting a fix to this problem.) Also fixed file "mtime" etc. to return times from GMT rather than local time zone. (RJ) 3/18/97 (feature change) Declaration of objv in Tcl_ObjCmdProc function changed from "Tcl_Obj *objv[]" to "Tcl_Obj *CONST objv[]". All Tcl object commands changed to use new declaration of objv. Naive translation of string-based command procs to object-based command procs could very easily have yielded code where the contents of the objv array were changed. This is not a problem with string-based command procs, but doing something as simple as objv[2] = objv[3] would corrupt the runtime stack and cause Tcl to crash. Introduced CONST in declaration of objv so that attempted assignment of new pointer values to elements of the objv array will be caught by the compiler. (CCS) *** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 *** 3/19/97 (bug fix) Fixed panic due to object sharing. The root cause was that old code was using Tcl_ResetResult instead of Tcl_ResetObjResult. (JL) 3/20/97 (new feature) Added a new subcommand for the file command. file attributes filename can give a list of platform-specific options (such as file/creator type on the Mac, permissions on Unix) or set the values of them. Added a new subcommand for the file command. file nativename name gives back the platform-specific form for the file. This is useful when the filename is needed to pass to the OS, such as exec under Windows 95 or AppleScript on the Mac. For more info, see file.n. (SRP) 3/24/97 (removed feature) Removed the tcl_safePolicyPath procedure. Now the policy path is computed from the auto_path by appending the directory 'policies' to each element. Also fixed several bugs in automatic tracking of auto_path by computed policy path. (JL) *** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 but not with Tcl 7.6 *** 4/8/97 (new feature) If the variable whose name is passed to lappend doesn't already exist, and there are no value arguments, lappend now creates the variable with an empty value instead of returning an error. Change suggested by Tom Tromey. (BL) 4/9/97 (feature change) Changed the name of the TCL_PART1_NOT_PARSED flag to TCL_PARSE_PART1. (BL) *** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 but not with Tcl 7.6 *** 4/10/97 (bug fixes) Fixed various compilation-related bugs: - "UpdateStringOfCmdName should never be invoked" panic. - Bad code generated for expressions not in {}'s inside catch commands. - Segmentation fault in some command procedures when two argument object pointers refer to the same object. - Second level of substitutions were never done for expressions not in {}'s that consist of a single variable reference: e.g., "set x 27; set bool {$x}; if $bool {puts foo}" would fail with error. - Bad code generated when code storage was grown while compiling some expressions: ones with compilation errors or consisting of only a variable reference. - Bugs involving multiple interpreters: wasn't checking that a procedure's code was compiled for the same interpreter as the one executing it, and didn't invalidate code on hidden-exposed command transitions. - "Bad stack top" panic when executing scripts that require a huge amount of stack space. - Incorrect sharing of code for procedure bodies, and procedure code deallocated before last execution of the procedure finished. - Fixed compilation of expression words in quotes. For example, if "0 < 3" {puts foo}. - Fixed performance bug in array set command with large assignments. - Tcl_SetObjLength segmentation fault setting length of empty object. - If Tcl_SetObjectResult was passed the same object as the interpreter's result object, it freed the object instead of doing nothing. Bug fix by Michael J. McLennan. - Tcl_ListObjAppendList inserted elements from the wrong list. Bug fix by Michael J. McLennan. - Segmentation fault if empty variable list was specified in a foreach command. Bug fix by Jan Nijtmans. - NULL command name was always passed to Tcl_CreateTrace callback procedure. - Wrong string representation generated for the value LONG_MIN. For example, expr 1<<31 printed incorrectly on a 32 bit machine. - "set {a($x)} 1" stored value in wrong variable. - Tcl_GetBooleanFromObj was not checking for garbage after a numeric value. - Garbled "bad operand type" error message when evaluating expressions not surrounded by {}'s. (BL) 4/16/97 (new feature) The expr command now has the "rand()" and "srand()" functions for getting random numbers in expr. (RJ) 4/23/97 (bug fix) Fixed core dump in bgerror when the error handler command deletes the current interpreter. Found by Juergen Schoenwald. (JL) 4/23/97 (feature change) The notifier interfaces have been redesigned to make embedding in applications with external event loops possible. A number of interfaces in the notifier and the channel drivers have changed. Refer to the Notifier.3 and CrtChannel.3 manual entries for more details. (SS) *** POTENTIAL INCOMPATIBILITY *** 4/23/97 (removed feature) The Tcl_File interfaces have been removed. The Tcl_CreateFileHandler/Tcl_DeleteFileHandler interfaces now take Unix fd's and are only supported on the Unix platform. Tcl_GetChannelFile has been replaced with Tcl_GetChannelHandle. Tcl_MakeFileChannel now takes a platform specific file handle. (SS) *** POTENTIAL INCOMPATIBILITY *** 4/23/97 (removed feature) The modal timeout interface has been removed (Tcl_CreateModalTimeout/Tcl_DeleteModalTimeout) (SS) *** POTENTIAL INCOMPATIBILITY *** 4/23/97 (feature change) Channel drivers are now required to correctly implement blocking behavior when they are in blocking mode. (SS) *** POTENTIAL INCOMPATIBILITY *** 4/23/97 (new feature) Added the "binary" command for manipulating binary strings. Also, changed the "puts", "gets", and "read" commands to preserve embedded nulls. (SS) 4/23/97 (new feature) Added tcl_platform(byteOrder) element to the tcl_platform array to identify the native byte order for the current host. (SS) 4/23/97 (bug fix) Fixed bug in date parsing around year boundaries. (SS) 4/24/97 (bug fix) In the process of copying a file owned by another user, Tcl was changing the owner of the copy back to the owner of the original file, therefore causing further file operations to fail because the current user didn't own the copy anymore. The owner of the copy is now left as the current user. (CCS) 4/24/97 (feature change) Under Windows, don't automatically uppercase the environment variable "windir" -- it's supposed to be lower case. (CCS) 4/29/97 (new feature) Added namespace support based on a namespace implementation by Michael J. McLennan of Lucent Technologies. A namespace encapsulates a collection of commands and variables to ensure that they won't interfere the commands and variables of other namespaces. The global namespace holds all global variables and commands. Additional namespaces are created with the new namespace command. The new variable command lets you create Tcl variables inside a namespace. The names of Tcl variables and commands may now be qualified by the name of the namespace containing them. The key namespace-related commands are summarized below: - namespace ?eval? name arg ?arg...? Used to define the commands and variables in a namespace. Optionally creates the namespace. - namespace export ?-clear? ?pattern pattern...? Specifies which commands are exported from a namespace. These are the ones that can be imported into another namespace. - namespace import ?-force? ?pattern pattern...? Makes the specified commands accessible in the current namespace. - namespace current Returns the name of the current namespace. - variable name ?value? ?name ?value?...? Creates one or more namespace variables. (BTL) 5/1/97 (bug fix) Under Windows, file times were reported in GMT. Should be reported in local time. (CCS) 5/2/97 (feature change) Changed the name of the two Tcl variables used for tracing bytecode compilation and execution to tcl_traceCompile and tcl_traceExec respectively. These variables are now documented in the tclvars man page. (BL) 5/5/97 (new feature) Support "end" as the index for "lsort -index". (BW) 5/5/97 (bug fixes) Cleaned up the way the http package resets connections (BW) 5/8/97 (feature change) Newly created Tcl objects now have a reference count of zero instead of one. This simplifies C code that stores newly created objects in Tcl variables or in data structures such as list objects. That C code must increment the new object's reference count since the variable or data structure will contain a long-term reference to the object. Formerly, when new objects started out with reference count one, it was necessary to decrement the new object's reference count after the store to make sure it was left with the correct value; this is no longer necessary. (BL) 5/9/97 (new feature) Added the Tcl_GetsObj interface that takes an object reference instead of a dynamic string (as in Tcl_Gets). (SS) 5/12/97 (new feature) Added Tcl_CreateAliasObj and Tcl_GetAliasObj C APIs to allow an alias command to be created with a vector of Tcl_Obj structures and to get the vector back later. (JL) 5/12/97 (feature change) Changed Tcl_ExposeCommand and Tcl_HideCommand to leave an object result instead of a string result. (JL) 5/14/97 (feature change) Improved the handling of the interpreter result. This is still either an object or a string, but the two values are now kept consistent unless some C code reads or writes interp->result directly. See the SetResult man page for details. Removed the Tcl_ResetObjResult procedure. (BL) *** POTENTIAL INCOMPATIBILITY with Tcl 8.0a2 *** 5/16/97 (new feature) Added "fcopy" command to move data between channels. Refer to the manual page for more information. Removed the "unsupported0" command since it is obsolete now. (SS) 5/16/97 (new feature) Added Tcl_GetStringResult procedure to allow programs to get an interpreter's result as a string. If the result was previously set to an object, this procedure will convert the object to a string. Use of Tcl_GetStringResult is intended to replace direct access to interp->result, which is not safe. (BL) 5/20/97 (new features) Fixed "fcopy" to return the number of bytes transferred in the blocking case. Updated the http package to use fcopy instead of unsupported0. Added -timeout and -handler options to http_get. http_get is now blocking by default. It is only non-blocking if you supply a -command argument. (BW) 5/22/97 (bug fix) Fixed several bugs in the "lsort" command having to do with the -dictionary option and the presence of numbers embedded in the strings. (JO) ----------------- Released 8.0b1, 5/27/97 ----------------------- 6/2/97 (bug fix) Fixed bug in startup code that caused a problem in finding the library files when they are installed in a directory containing a space in the name. (SS) 6/2/97 (bug fix) Fixed bug in Unix notifier where the select mask was not being cleared under some circumstances. (SS) 6/4/97 (bug fix) Fixed bug that prevented creation of Tk widgets in namespaces. Tcl_CreateObjCommand and Tcl_CreateCommand now always create commands in the global namespace unless the command names are qualified. Tcl procedures continue to be created in the current namespace by default. (BL) 6/6/97 (new features) Added new namespace API procedures Tcl_AppendExportList and Tcl_Export to allow C code to get and set a namespace's export list. (BL) 6/11/97 (new feature) Added Tcl_ConcatObj. This object-based routine parallels the string-based routine Tcl_Concat. (SRP) 6/11/97 (new feature) Added Tcl_SetObjErrorCode. This object-based routines parallels the string-based routine Tcl_SetErrorCode. (SRP) 6/12/97 (bug fix) Fix the "unknown" procedure so that wish under Windows will exec an external program, instead of always complaining "console1 not opened for writing". (CCS) 6/12/97 (bug fix) Fixed core dump experienced by the following simple script: interp create x x alias exec exec interp delete x This panic was caused by not installing the new CmdDeleteProc when exec got redefined by the alias creation step. Reported by Lindsay Marshal (JL) 6/13/97 (new features) Tcl objects newly created by Tcl_NewObj now have a string representation that points to a shared heap string of length 1. (They used to have NULL bytes and typePtr fields. This was treated as a special case to indicate an empty string, but made type manager implementations complex and error prone.) The new procedure Tcl_InvalidateStringRep is used to mark an object's string representation invalid and to free any storage associated with the old string representation. (BL) *** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl7.6 *** 6/16/97 (bug fix) Tcl_ScanCountedElement could leave braces unmatched if the string ended with a backslash. (JO) 6/17/97 (bug fix) Fixed channel event bug where readable events would be lost during recursive events loops if the input buffers contained data. (SS) 6/17/97 (bug fix) Fixed bug in Windows socket code that didn't reenable read events in the case where an external entity is also reading from the socket. (SS) 6/18/97 (bug fix) Changed initial setting of the notifier service mode to TCL_SERVICE_NONE to avoid unexpected event handling during initialization. (SS) 6/19/97 (bug fix/feature change) The command callback to fcopy is now called in case of errors during the background copy. This adds a second, optional argument to the callback that is the error string. The callback in case of errors is required for proper cleanup by the user of fcopy. (BW) *** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 *** 6/19/97 (bug fix) Fixed a panic due to the following four line script: interp create x x alias foo bar x eval rename foo blotz x alias foo {} The problem was that the interp code was not using the actual current name of the command to be deleted as a result of un-aliasing foo. (JL) 6/19/97 (feature change) Pass interp down to the ChannelOption and driver specific calls so system errors can be differentiated from syntax ones. Changed Tcl_DriverGetOptionProc type. Affects Tcl_GetChannelOption, TcpGetOptionProc, TtyGetOptionProc, etc. (DL) *** POTENTIAL INCOMPATIBILITY *** 6/19/97 (new feature) Added Tcl_BadChannelOption for use by by driver specific option procedures (Set and Get) to return a complete and meaningful error message. (DL) 6/19/97 (bug fixes) If a system call error occurs while doing an fconfigure on tcp or tty/com channel: return the appropriate error message (instead of the syntax error one or none). (Fixed for Unix and most of the Win and Mac drivers). (DL) 6/20/97 (feature change) Eval is no longer assumed as the subcommand name in namespace commands: you must now write "namespace eval nsName {...}". Abbreviations of namespace subcommand names are now allowed. (BL) *** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl7.6 *** 6/20/97 (feature change) Changed the errorInfo traceback message for compilation errors from "invoked from within" to "while compiling". (BL) 6/20/97 (bug fixes) Fixed various compilation-related bugs: - "UpdateStringOfCmdName should never be called" and "UpdateStringOfByteCode should never be called" panics. - Segfault in TclObjInterpProc getting procedure name after evaluation stack is reallocated (grown). - Could not use ":" at end of variable and command names. - Bad code generated for while and for commands with test expressions enclosed in quotes: e.g., "set i 0; while "$i > 5" {}". - Command trace procedures would crash if they did a Tcl_EvalObj that reallocated the evaluation stack. - Break and continue commands did not reset the interpreter result. - The Tcl_ExprXXX routines, both string- or object-based, always modified the interpreter result even if there was no error. - The argument parsing procedure used by several compile procedures always treated "]" as end of a command: e.g., "set a ]" would fail. - Changed errorInfo traceback message for compilation errors from "invoked from within" to "while compiling". - Problem initializing Tcl object managers during interpreter creation. - Added check and error message if formal parameter to a procedure is an array element. (BL) 6/23/97 (new feature) Added "registry" package to allow manipulation of the Windows system registry. See manual entry for details. (SS) 6/24/97 (feature change) Converted http to a package and added the http1.0 subdirectory of the Tcl script library. This means you have to do a "package require http" to use this, as advertised in the man page. (BW) *** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 *** 6/24/97 (bug fix) Ensure that Tcl_Set/GetVar C APIs, when called without TCL_LEAVE_ERR_MSG, don't touch the interp result. (DL) 6/26/97 (feature change) Changed name of Tcl_ExprStringObj to Tcl_ExprObj. (BL) *** POTENTIAL INCOMPATIBILITY with Tcl 8.0b1, but not with Tcl 7.6 *** ----------------- Released 8.0b2, 6/30/97 ----------------------- 7/1/97 (new feature) TCL_BUILD_SHARED flag set in tclConfig.sh when Tcl has been built with --enable-shared. A new tclLibObjs make target, echoing the list of the .o's needed to build a tcl library, is now provided. (DL) 7/1/97 (feature change) compat/getcwd.c removed and changed the only place where getcwd is used so a new USEGETWD flag selects the use of the replacement "getwd". Adding this flag is recommended for SunOS 4 (because getcwd on SunOS 4 uses a pipe to pwd(1)!). (DL) 7/7/97 (feature change) The split command now supports binary data (i.e., null characters in strings). (BL) 7/7/97 (bug fix) string first returned the wrong result if the first argument string was empty. (BL) 7/8/97 (bug fix) Fixed core dump in fcopy that could occur when a command callback was supplied and an error or eof condition caused no background activity. A refcount bug triggered a panic in Tcl_ListObjAppendElement. (BW) 7/8/97 (bug fix) Relaxed the pattern matching on http_get so you do not need a trailing path component. You can now get away with just http_get www.scriptics.com (BW) 7/9/97 (bug fix) Creating anonymous interpreters no longer smashes existing commands with names similar to the generated name. Previously creating an anonymous interpreter could smash an existing command, now it skips until it finds a command name that isn't being used. (JL) 7/9/97 (feature change) Removed the policy management mechanism from the Safe Base; left the aliases to source and load modules, and to do a limited form of the "file" command. See entry of 11/15/96. (JL) 7/9/97 (bug fixes) Fixed various compilation-related bugs: - Line numbers in errorInfo now are the same as those in Tcl7.6 unless there are compilation errors. Compilation error messages now include the entire command in error. - Trailing ::s after namespace names weren't being ignored. - Could not refer to an namespace variable with an empty name using a name of the form "n::". (BL) 7/9/97 (bug fix) Fixed bug in Tcl_Export that prevented you from exporting from other than the current namespace. (BL) 7/9/97 (bug fix) env.test was removing env var needed for proper finding of libraries in child process. (DL) 7/10/97 (bug fixes/new feature) Cleanup in Tcl_MakeSafe. Less information is leaked to safe interps. Error message fixes for interp sub commands. Likewise changes in safealias.tcl; tcl_safeCreateInterp can now be called without argument to generate the slave name (like in interp create). (DL) 7/10/97 (bug fixes) Bytecode compiler now generates more detailed command location information: subcommands as well as commands now have location information. This means command trace procedures now get the correct source string for each command in their command parameter. (BL) 7/22/97 (bug fixes) Performance improvement in Safe interpreters handling. Added new mask value to (tclInt.h) Interp.flags record. (DL) 7/22/97 (bug fix) Fixed panic in 'interp target {} foo'. This bug was present since Tcl 7.6. (JL) 7/22/97 (bug fix) Fixed bug in compilation of procedures in namespaces: the procedure's namespace must be used to look up compile procedures, not the current namespace. (BL) 7/22/97 (bug fix) Use of the -channel option of http_get was not setting the end of line translations mode on the channel, so copying binary data with the -channel option was corrupting the result on non-unix platforms. (BW) 7/22/97 (bug fixes) file commands and ~user (seg fault and other improper returns). (DL) 7/23/97 (feature change) Reenabled "vwait" in Safe Base. (JL) 7/23/97 (bug fixes) Fixed two bugs involving read traces on array variables in procedures: trace procedures were sometimes not called, and reading nonexistant array elements didn't create undefined element variables that could later be defined by trace procedures. (BL) 7/24/97 (bug fix) Windows memory allocation performance was superlinear in some cases. Made the Mac allocator generic and changed both the Mac and Windows platforms to use the new allocator instead of malloc and free. (SS) 7/24/97 - 8/12/97 (bug fixes/change of features) Completely revamped safe sourcing/loading (see safe.n) to hide pathnames, use virtual paths tokens instead, improved security in several respects and made it more tunable. Multi level interp loading can work too now. Package auto loading now works in safe interps as long as the package directory is in the auto_path (no deep crawling allowed in safe interps). (DL) *** POTENTIAL INCOMPATIBILITY with previous alpha and beta releases *** 7/24/97 (bug fixes) Made Tcl_SetVar* and Tcl_NewString* treat a NULL value as an empty string. (This fixes hairy crash case where you would crash because load command for other interps assumed presence of errorInfo...). (DL) 7/28/97 (bug fix) Fixed pkg_mkIndex to understand namespaces. It will use the export list of a namespace and create auto_index entries for all export commands. Those names are in their fully qualified form in the auto_index. Therefore, I tweaked unknown to try both $cmd and ::$cmd. Also fixed pkg_mkIndex so you can have "package require" commands inside your packages. These commands are ignored, which is mostly ok except when you must load another package before loading yours because of linking dependencies. (BW) 7/28/97 (bug fix) A variable created by the variable command now persists until the namespace is destroyed or the variable is unset. This is true even if the variable has not been initialized; these variables used to be destroyed if an error occurred when accessing them. In addition, the "info vars" command lists uninitialized namespace variables, while the "info exists" command returns 0 for them. (BL) 7/29/97 (feature change) Changed the http package to use the ::http namespace. http_get renamed to http::geturl, http_config renamed to http::config, http_formatQuery renamed to http::formatQuery. It now provides the 2.0 version of the package. The 1.0 version is still available with the old names. *** POTENTIAL INCOMPATIBILITY with Tcl 8.0b2 but not with Tcl 7.6 *** 7/29/97 (bug fix, new feature) Tcl_Main now uses Tcl objects internally to preserve NULLs in commands and command output. Added new API procedure Tcl_RecordAndEvalObj that resembles Tcl_RecordAndEval but takes an object containing a command. (BL) 7/30/97 (bug fix) Tcl freed strings in the environ array even if it did not allocate them. (SS) 7/30/97 (bug fix) If a procedure is renamed into a different namespace, it now executes in the context of that namespace. (BL) 7/30/97 (bug fix) Prevent renaming of commands into and from namespaces as part of hiding them. (JL) 7/31/97 (feature change) Moved the history command from C to tcl. This uses the ::history namespace. The "words" and "substitute" options are no longer supported. In addition, the "keep" option without a value returns the current keep limit. There is a new "clear" option. The unknown command now supports !! again. (BW) *** POTENTIAL INCOMPATIBILTY *** 7/30/97 (bug fix) Made sure that a slave can not fool the master into hiding the wrong command. Made sure we don't crash in hiding + namespaces issues. (DL) 8/4/97 (bug fix) Concat, eval, uplevel, and similar commands were incorrectly trimming trailing space characters from their arguments even when the space characters were preceded by a backslash. (JO) 8/4/97 (bug fix) Removed the hard link between bgerror and tkerror. Only bgerror is supported in tcl core. Tk will still look for a tkerror but using regular tcl code for that feature. (DL) *** POTENTIAL INCOMPATIBILTY with code relying on the hard link *** 8/6/97 (bug fix) Reduced size required for compiled bytecodes by using a more compact encoding for the command pc-to-source map. (BL) 8/6/97 (new feature) Added support for additional compilation and execution statistics when Tcl is compiled with the TCL_COMPILE_STATS flag. (BL) 8/7/97 (bug fix) Expressions not in {}s that have a comparison operator as the topmost operator must be compiled out-of-line (call the expr cmd at runtime) to properly support expr's two-level substitution semantics. An example is "set a 2; set b {$a}; puts [expr $b == 2]". (BL) 8/11/97 (bug fix) The catch command would sometimes crash if a variable name was given and the bytecode evaluation stack was grown when executing the argument script. (BL) 8/12/97 (feature change) Reinstated the variable tcl_precision to control the number of digits used when floating-point values are converted to strings, with default of 12 digits. However, had to make tcl_precision shared among all interpreters (except that safe interpreters can't modify it). This makes the Tcl 8.0 behavior almost identical to 7.6 except that the default precision is 12 instead of 6. (JO) *** POTENTIAL INCOMPATIBILITY *** ----------------- Released 8.0, 8/18/97 ----------------------- 8/19/97 (bug fix) Minimal fix for glob -nocomplain bugs: "glob -nocomplain unreadableDir/*" was generating an anonymous error. More in depth fixes will come with 8.1. (DL). 8/20/97 (bug fix) Removed check for FLT_MIN in binary command so underflow conditions are handled by the compiler automatic conversions. (SS) 8/20/97 (bug fixes) Fixed several compilation-related bugs: - Array cmd wasn't detecting arrays that, while compiled, do not yet exist (e.g., are marked undefined since they haven't been assigned to yet). - The GetToken procedure in tclCompExpr.c wasn't recognizing properly whether an integer token was invalid. For example, "0x$" is not a valid integer. - Performance bug in TclExecuteByteCode: the size of its stack frame was reduced by over 20% by moving errorInfo code elsewhere. - Uninitialized memory read error in tclCompile.c. (BL) 8/21/97 (bug fix) safe::interpConfigure now behave like Tk widget's configure : it changes only the options you provide and you can get the current value of any single option. New ?-nested boolean? and ?-statics boolean? for all safe::interp* commands but we still accept (upward compatibility) the previously defined non valued flags ?-noStatics? and ?-nestedLoadOk?. Improved the documentation. (DL). 8/22/97 (bug fix) Updated PrintDbl.3 to reflect the fact that the tcl_precision variable is still used and that it is now shared by all interpreters. (BL) 8/25/97 (bug fix) Fixed array access bug in IllegalExprOperandType procedure in tclExecute.c: it was not properly supporting the || and && operators. (BL) 8/27/97 (bug fix) In cases where a channel handler was created with an empty event mask while data was still buffered in the channel, the channel code would get stuck spinning on a timer that would starve idle handlers. This mostly happened in Tk when reading from stdin. (SS) 9/4/97 (bug fix) Slave interps now inherit the maximum recursion limit of their parent instead of starting back at the default. {nb: this still does not prevent stack overflow by multi-interps recursion or aliasing} (DL) 9/11/97 (bug fix) An uninitialized variable in Tcl_WaitPid caused pipes to fail to report eof properly under Windows. (SS) 9/12/97 (bug fix) "exec" was misidentifying some DOS executables as not executable. (CCS) 9/14/97 (bug fix) Was using the wrong structure in sizeof operation in tclUnixChan.c. (JL) 9/15/97 (bug fix) Fixed notifier to break out of do-one-event loop if Tcl_WaitForEvent returns 1, so that callers of Tcl_DoOneEvent will get a chance to check whether the event just handled is significant. This affected mainly recursive calls to Tcl_VWaitCmd; these did not get a chance to notice that the variable they were waiting for has been set and thus they didn't terminate the vwait. (JL, DL, SS) 9/15/97 (bug fix) Alignment problems in "binary format" would cause a crash on some platforms when formatting floating point numbers. (SS) 9/15/97 (bug fix) Fixed bug in Macintosh socket code. Now passes all tests in socket.test that are not platform specific. (Thanks to Mark Roseman for the pointer on the fix.) (RJ) 9/18/97 (bug fix) Fixed bug -dictionary option of lsort that could cause the compare function to run off the end of an array if the number only contained 0's. (Thanks to Greg Couch for the report.) (RJ) 9/18/97 (bug fix) TclFinalizeEnvironment was not cleaning up properly. (DL, JI) 9/18/97 (bug fix) Fixed long-standing bug where an "array get" command did not trigger traces on the array or its elements. (BL) 9/18/97 (bug fixes) Fixed compilation-related bugs: - Fixed errorInfo traceback information for toplevel coomands that contain nested commands. - In the expr command, && and || now accept boolean operands as well as numeric ones. (BL) 9/22/97 (bug fix) Fixed bug that prevented translation modes from being set independently for input and output on sockets if input was "auto". (JL) 9/24/97 (bug fix) Tcl_EvalFile(3) and thus source(n) now works fine on files containing NUL chars. (DL) 9/26/97 (bug fix) Fixed use of uninitialized memory in the environ array that later could cause random core dumps. Applies to all platforms. (JL) 9/26/97 (bug fix) Fixed use of uninitialized memory in socket address data structure under some circumstances. This could cause random core dumps. This applies only to Unix. (JL) 9/26/97 (bug fix) Opening files on PC-NFS volumes would cause a hang until the system timed after the file was closed. (SS) 10/6/97 (bug fix) The join(n) command, though objectified, was loosing NULs in the joinString and in list elements after the 2nd one. Now you can "join $list \0" for instance. (DL) 10/9/97 (bug fix) Under windows, if env(TMP) or env(TEMP) referred to a non-existent directory, exec would fail when trying to create its temporary files. (CCS) 10/9/97 (bug fix) Under mac and windows, "info hostname" would crash if sockets were installed but the hostname could not be determined anyhow. Tcl_GetHostName() was returning NULL when it should have been returning an empty string. (CCS) 10/10/97 (bug fix) "file attribute /" returned error on windows. (CCS) 10/10/97 (bug fix) Fixed the auto_load procedure to handle procedures defined in namespaces better. Also fixed pgk_mkIndex so it sees procedures defined in nested namespaces. Index entries are still only made for exported procedures. (BW) 10/13/97 (bug fix) On unix, for files with unknown group or owner attributes, querying the "file attributes" would return an error rather than returning the group's or owner's id number, although tha command accepts numbers when setting the file's group or owner. (CCS) 10/22/97 (bug fix) "fcopy" did not eval the callback script at the global scope. (SS) 10/22/97 (bug fix) Fixed the signature of the CopyDone callback used in the http package(s) so they can handle error cases properly. (BW) 10/28/97 (bug fixes) Fixed a problem where lappend would free the Tcl object in a variable if a Tcl_ObjSetVar2 failed because of an error calling a trace on the variable. (BL) 10/28/97 (bug fix) Changed binary scan to properly handle sign extension of integers on 64-bit or larger machines. (SS) 11/3/97 (bug fixes) Fixed several bugs: - expressions such as "expr ($x)" must be compiled out-of-line (call the expr command procedure at runtime) to ensure the correct behavior when "$x" is an expression such as "5+10". - "array set a {}" now creates a new array var with an empty array value if the var didn't already exist. - "lreplace $foo end end" no longer returns an error (just an empty list) if foo is empty. - upvar will no longer create a variable in a namespace that refers to a variable in a procedure. - deleting a command trace within a command trace callback would make the code that calls traces to reference freed memory. - significantly sped up "string first" and "string last" (fix from darrel@gemstone.com). - seg fault in Tcl_NewStringObj() when a NULL is passed as the byte pointer argument and Tcl is compiled with -DTCL_MEM_DEBUG. - documentation and error msg fixes. (BL) 11/3/97 (bug fix) Fixed a number of I/O bugs related to word sizes on 64-bit machines. (SS) 11/6/97 (bug fix) The exit code of the first process created by Tcl on Windows was not properly reported due to an initialization problem. (SS) ----------------- Released 8.0p1, 11/7/97 ----------------------- 11/19/97 (bug fix) Fixed bug in linsert where it sometimes accidently cleared out a shared argument list object. (BL). 11/19/97 (bug fix) Autoloading in namespaces was not working properly. auto_mkindex is still not really namespace aware but most common cases should now be handled properly (see init.test). (BW, DL) 11/20/97 (enhancement) Made the changes required by the new Apple Universal Headers V.3.0, so that Tcl will compile with CW Pro 2. 11/24/97 (bug fix) Fixed tests in clock test suite that needed the -gmt flag set. Thanks to Jan Nijtmans for reporting the problem. (RJ) ----------------- Released 8.0p2, 11/25/97 ----------------------- 12/3/97 (bug fix/optimization) Removed uneeded and potentially dangerous instances of double evaluations if "if" and "expr" statements from the library files. It is recommended that unless you need a double evaluation you always use "expr {...}" instead of "expr ..." and "if {...} ..." instead of "if ... ...". It will also be faster thanks to the byte compiler. (DL) ---- Shipped as part of the plugin2.0b5 as 8.0p2Plugin1, Dec 8th 97 ---- 12/8/97 (bug fix) Need to protect the newly accepted channel in an accept callback on a socket, otherwise the callback may close it and cause an error, which would cause the C code to attempt to close the now deleted channel. Bumping the refcount assures that the channel sticks around to be really closed in this case. (JL) 12/8/97 (bug fix) Need to protect the channel in a fileevent so that it is not deleted before the fileevent handler returns. (CS, JL) 12/18/97 (bug fix) In the opt argument parsing package: if the description had only flags, the "too many arguments" case was not detected. The default value was not used for the special "args" ending argument. (DL) 1/15/98 (improvement) Moved common part of initScript in common file. Moved windows specific initialization to init.tcl so you can initialize Tcl in windows without having to call Tcl_Init which is now only searching for init.tcl {back ported from 8.1}. (DL) ---- Shipped as part of the plugin as 8.0p2Plugin2, Jan 15th 98 ---- 5/27/98 (bug fix) Windows socket driver did not notice new data arriving on nonblocking sockets until the event loop was entered. (SS) 5/27/98 (bug fix) Windows socket driver used FIONREAD, which is not supported correctly by WinSock. (SS) 6/9/98 (bug fix) Generic channel code failed to report readable file events on buffered data that was left behind by a gets or read that did not consume all available data. (SS) 6/18/98 (bug fix) Compilation of loop expressions was too aggressive and incorrectly inlined non-literal expressions. (SS) 6/18/98 (bug fix) "info var" and "info locals" incorrectly reported the existence of compiler temporary variables. (SS) 6/18/98 (bug fix) Dictionary sorting used signed character comparisons. (SS) 6/18/98 (bug fix) Compile procs corrupted the exception stack in some cases. (SS) 6/18/98 (bug fix) Array set had erratic behavior when initializing a variable from an empty value list. (SS) 6/18/98 (bug fix) The Windows registry package had a bad bounds check that could lead to a crash. (SS) 6/18/98 (bug fix) The foreach compile proc did not correctly handle non-local variable references. (SS) 6/25/98 (new features) Added name resolution hooks to support [incr Tcl]. There are new internal Tcl_*Resolver* APIs to add, query and remove the hooks. With this changes it should be possible to dynamically load [incr Tcl] as an extension. (MM) 7/1/97 (bug fix) The commands "info args, body, default, procs" did not correctly handle imported procedures. (RJ) 7/6/98 (improvement) pkg_mkIndex now implements the "package require" command. This makes it possible to create index files for packages that require another package and then execute code from that package in their file. Previously, this would throw an error because the required package had not been loaded. The -nopkgrequied flag is provided to revert back to the old functionality. (EMS) 7/6/98 (improvement) back-ported the -direct flag from 8.1 into pkg_mkIndex. This results in pkgIndex.tcl files that contain direct source or load commands instead of tclPkgSetup commands. (EMS) 7/6/98 (improvement) made changes to the AuxData items structures to support storage of compiled scripts on disk. Also some related minor changes in the compilation and execution engine. (EMS) 6/4/98 (enhancement) Added new internal routines to support inserting and deleting from the stat, access, and open-file-channel mechanisms. TclAccessInsertProc, TclStatInsertProc, & TclOpenFileChannelInsertProc insert pointers to such routines; TclAccessDeleteProc, TclStatDeleteProc, & TclOpenFileChannelDeleteProc delete pointers to such routines. See the file generic/tclIOUtils.c for more details. (SKS) 7/1/98 (enhancement) Added a new internal C variable tclPreInitScript. This is a pointer to a string that may hold an initialization script; If this pointer is non-NULL it is evaluated in Tcl_Init() prior to the built-in initialization script defined in the file generic/tclInitScript.h. (SKS) 7/6/98 (bug fix) Removed dead code in PlatformInitExitHandler so that the TCL_LIBRARY value can be safely patched in binaries. (BW) 7/24/98 (enhancement) Incorporated a new version of auto_mkindex that can support the [incr Tcl] class structures. This version will index all procedures in a source file, not just those where "proc" starts at the beginning of the line. If you want the old behavior, use the auto_mkindex_old procedure. (MM) 7/24/98 (feature change) Changed the Windows registry key to be HKEY_LOCAL_MACHINE\Software\Scriptics\Tcl\8.0, and to store the path in the default value instead of "Root". Also, this key can be specified at compile time in case Tcl is being used in a different context where it needs an alternate library path from the standard Tcl installation. (SS) 7/24/98 (feature change) Changed the search order for init.tcl. The tcl_library variable can now be set before calling Tcl_Init to avoid doing any searches. If it isn't set, then Tcl checks env(TCL_LIBRARY), the static value set at compile time, an install directory relative to the executable, a source directory relative to the executable, and a tcl directory relative to the source heirarchy containing the executable. See the comment at the top of generic/tclInitScript.h for more details. (SS) 7/27/98 (config change) Changed the use of the DBGX flag in configure.in and the makefile to be TCL_DBGX. Users of tclConfig.sh may need to pass this through their configure files with AC_SUBST. (BW) 729/98 (bug fix) Changed [info body] to return a copy of the body of a compiled procedure instead of the body itself, to avoid invalidation of the internal rep and loss of the byte-codes. (EMS) 8/5/98 (bug fix) The platform init code could walk off the end of a buffer when reading the PkgPath registry value on Windows. (SS) 8/5/98 (Windows makefile change) Introduced a set of macros to deal with exporting symbols when compiling DLLS on Windows. See win/README for details. (EMS) 8/5/98 (addendum) Added a second Windows registry key under HKEY_LOCAL_MACHINE\Software\Scriptics\Tcl\8.0, named "pkgPath". This is a multi-string value used to initialize the tcl_pkgPath variable. This is required if extension DLLs are in architecture specific subdirectories. (SS) 8/6/98 (new feature) Added tcl_findLibrary to init.tcl for use by extensions, including Tk. This searches in a canonical way for an extensions library directory and initialization file. (BW) 8/10/98 (bug fix) Imported commands used to get lost if the target of the import was redefined. Tcl_CreateCommand and Tcl_CreateObjCommand were updated to restore import links. (Note that if you rename a command, the import links move to the new name, and if you delete a command then the import links get lost. These semantics have not changed.) (MC) -------- Released 8.0.3 to the Tcl Consortium CD-ROM project, 8/10/98 ------ 9/3/98 (bug fix) Tcl_Realloc was failing under Windows because the GlobalReAlloc API was not correctly re-allocating blocks that were 32k+. The fix was to use newer Win32 APIs (HeapAlloc, HeapFree, and HeapReAlloc.) (BS) 10/5/98 (bug fix) Fixed bug in pkg_mkIndex that caused some files that do a "package require" of packages in the Tcl libraries to give a warning like warning: "xx.tcl" provides more than one package ({xx 2.0} {yy 0.3}) and generate a broken pkgIndex.tcl file. (EMS) 10/5/98 (bug fix) Pkg_mkIndex was not doing a case-insensitive comparison of extensions to determine whether to load or source a file. Thus, under Windows, MYDLLNAME.DLL was sourced, and mydllname.dll loaded. (EMS) 10/5/98 (new feature) Created a new Tcl_Obj type, "procbody". This object's internal representation holds a pointer to a Proc structure. Extended TclCreateProc to take both strings and "procbody". (EMS) 10/13/98 (bug fix) The "info complete" command can now handle strings with NULLs embedded. Thanks to colin@field.medicine.adelaide.edu.au for providing this fix. (RJ) 10/13/98 (bug fix) The "lsort -dictionary" command did not properly handle some numbers starting with 0. Thanks to Richard Hipp for submitting the fix to Scriptics. (RJ) 10/13/98 (bug fix) The function Tcl_SetListObj was creating an invalid Tcl_Obj if the list had zero elements (despite what the comments said it would do). Thanks to Sebastian Wangnick for reporting the problem. (RJ) 10/20/98 (new feature) Added tcl_platform(debug) element to the tcl_platform array on Windows platform. The existence of the debug element of the tcl_platform array indicates that the particular Tcl shell has been compiled with debug information. Using "info exists tcl_platform(debug)" a Tcl script can direct the interpreter to load debug versions of DLLs with the load command. (SKS) 10/20/98 (feature change) The Makefile and configure scripts have been changed for IRIX to build n32 binaries instead of the old 32 abi format. If you have extensions built with the o32 abi's you will need to update them to n32 for them to work with Tcl. (RJ) *** POTENTIAL INCOMPATIBILITY *** 10/23/98 (bug fix) tcl_findLibrary had a stray ] in one of the pathnames it searched for the initialization script. tclInitScript.h was incorrectly adding the parent of tcl_library to tcl_pkgPath. This logic was moved into init.tcl, and the initialization of auto_path was documented. Thanks to Donald Porter and Tom Silva for related patches. (BW) 10/29/98 (bug fix) Fixed Tcl_NotifyChannel to use Tcl_Preserve instead of Tcl_RegisterChannel so that 1) unregistered channels do not get closed after their first fileevent, and 2) errors that occur during close in a fileevent script are actually reflected by the close command. (BW) 10/30/98 (bug fix) Overhaul of pkg_mkIndex to deal with transitive package requires and packages split among scripts and binary files. Also fixed ommision of global for errorInfo in tcl_findLibrary. (BW) 11/08/98 (bug fix) Fixed the resource command to always detect the case where a file is opened a second time with the same permissions. IM claims that this will always cause the same FileRef to be returned, but in MacOS 8.1+, this is no longer the case, so we have to test for this explicitly. (JI) 11/10/98 (feature change) When compiling with Metrowerk's MSL, use the exit function from MSL rather than ExitToShell. This allows MSL to clean up its temporary files. Thanks to Vince Darley for this improvement. (JI) ----------------- Released 8.0.4, 11/19/98 ------------------------- 11/20/98 (bug fix) Handle possible NULL return in TclGetStdFiles. (RJ) 11/20/98 (bug fix) The dltests would not build on SGI. They reported that you could not mix n32 with 032 binaries. The configure script has been modified to get the EXTRA_CFLAGS from the tcl configure script. [Bug id: 840] (RJ) 12/3/98 (bug fix) Windows NT creates sockets so they are inheritable by default. Fixed socket code so it turns off this bit right after creation so sockets aren't kept open by exec'ed processes. [Bug: 892] Thanks to Kevin Kenny for this fix. (SS) 1/11/98 (bug fix) On HP, "info sharedlibextension" was returning empty string on static apps. It now always returns ".sl". (RJ) 1/28/99 (configure change) Now support -pipe option on gcc. (RJ) 2/2/99 (bug fix) Fixed initialization problem on Windows where no searching for init.tcl would be performed if the registry keys were missing. (stanton) 2/2/99 (bug fix) Added support for HKEY_PERFORMANCE_DATA and HKEY_DYN_DATA keys in the "registry" command. (stanton) 2/2/99 (bug fix) ENOTSUP and EOPNOTSUPP clashed on some Linux variants. (stanton) 2/2/99 (enhancement) The "open" command has been changed to use the object interfaces. (stanton) 2/2/99 (bug fix) In some cases Tcl would crash due to an overflow of the exception stack resulting from a missing byte code in some expressions. (stanton) 2/2/99 (bug fix) Changed configure so Linux and IRIX shared libraries are linked with the system libraries. (stanton) 2/2/99 (bug fix) Added support for BSDI 4.x (BSD/OS-4*) to the configure script. (stanton) 2/2/99 (bug fix) Fixed bug where upvar could resurrect a namespace variable after the namespace had been deleted. (stanton) 2/2/99 (bug fix) In some cases when creating variables, the interpreter result was being modified even if the TCL_LEAVE_ERR_MSG flag was set. (stanton) 2/2/99 (bug fix & new feature) Changed the socket drivers to properly handle failures during an async socket connection. Added a new fconfigure option "-error" to retrieve the failure message. See the socket.n manual entry for details. (stanton) 2/2/99 (bug fix) Deleting a renamed interp alias could result in a panic. (stanton) 2/2/99 (feature change/bug fix) Changed the behavior of "file extension" so that it splits at the last period. Now the extension of a file like "foo..o" is ".o" instead of "..o" as in previous versions. *** POTENTIAL INCOMPATIBILITY *** ----------------- Released 8.0.5, 3/9/99 ------------------------- ======== Changes for 8.0 go above this line ======== ======== Changes for 8.1 go below this line ======== 6/18/97 (new feature) Tcl now supports international character sets: - All C APIs now accept UTF-8 strings instead of iso8859-1 strings, wherever you see "char *", unless explicitly noted otherwise. - All Tcl strings represented in UTF-8, which is a convenient multi-byte encoding of Unicode. Variable names, procedure names, and all other values in Tcl may include arbitrary Unicode characters. For example, the Tcl command "string length" returns how many Unicode characters are in the argument string. - For Java compatibility, embedded null bytes in C strings are represented as \xC080 in UTF-8 strings, but the null byte at the end of a UTF-8 string remains \0. Thus Tcl strings once again do not contain null bytes, except for termination bytes. - For Java compatibility, "\uXXXX" is used in Tcl to enter a Unicode character. "\u0000" through "\uffff" are acceptable Unicode characters. - "\xXX" is used to enter a small Unicode character (between 0 and 255) in Tcl. - Tcl automatically translates between UTF-8 and the normal encoding for the platform during interactions with the system. - The fconfigure command now supports a -encoding option for specifying the encoding of an open file or socket. Tcl will automatically translate between the specified encoding and UTF-8 during I/O. See the directory library/encoding to find out what encodings are supported (eventually there will be an "encoding" command that makes this information more accessible). - There are several new C APIs that support UTF-8 and various encodings. See Utf.3 for procedures that translate between Unicode and UTF-8 and manipulate UTF-8 strings. See Encoding.3 for procedures that create new encodings and translate between encodings. See ToUpper.3 for procedures that perform case conversions on UTF-8 strings. 9/18/97 (enhancement) Literal objects are now shared by the ByteCode structures created when compiled different scripts. This saves up to 45% of the total memory needed for all literals. (BL) 9/24/97 (bug fixes) Fixed Tcl_ParseCommand parsing of backslash-newline sequences at start of command words. Suppressed Tcl_EvalDirect error logging if non-TCL_OK result wasn't an error. (BL) 10/17/97 (feature enhancement) "~username" now refers to the users' home directory on Windows (previously always returned failure). (CCS) 10/20/97 (implementation change) The Tcl parser has been completely rewritten to make it more modular. It can now be used to parse a script without actually executing it. The APIs for the new parser are not correctly exported, but they will eventually be exported and augmented with Tcl commands so that Tcl scripts can parse other Tcl scripts. (JO) 10/21/97 (API change) Added "flags" argument to Tcl_EvalObj, removed Tcl_GlobalEvalObj procedure. Added new procedures Tcl_Eval2 and Tcl_EvalObjv. (JO) *** POTENTIAL INCOMPATIBILITY *** 10/22/97 (API change) Renamed Tcl_ObjSetVar2 and Tcl_ObjGetVar2 to Tcl_SetObjVar2 and Tcl_GetObjVar2 (for consistency with other C APIs) and changed the name arguments to be strings instead of objects. (JO) *** POTENTIAL INCOMPATIBILITY *** 10/27/97 (enhancement) Bytecode compiler rewritten to use the new Tcl parser. (BL) 11/3/97 (New routines) Added Tcl_AppendObjToObj, which appends the string rep of one Tcl_Obj to another. Added Tcl_GetIndexFromObjStruct, which is similar to Tcl_GetIndexFromObj, except that you can give an offset between strings. This allows Tcl_GetIndexFromObjStruct to be called with a table of records which have strings in them. (SRP) 12/4/97 (enhancement) New Tcl expression parser added. Added new procedure Tcl_ParseExpr and new token types TCL_TOKEN_SUB_EXPR and TCL_TOKEN_OPERATOR. Expression compiler is reimplemented to use this parser. (BL) 12/9/97 (bug fix) Tcl_EvalObj() increments/decrements the refcount of the script object to prevent the object from deleting itself while in the middle of being evaluated. (CCS) 12/9/97 (bug fix) Memory leak in Tcl_GetsObjCmd(). (CCS) 12/11/97 (bug fix) Environment array leaked memory when compiled with Visual C++. (SS) 12/11/97 (bug fix) File events and non-blocking I/O did not work on pipes under Windows. Changed to use threads to achieve non-blocking behavior. (SS) 12/18/97 (bug fixes) Fixed segfault in "namespace import"; importing a procedure that causes a cycle now returns an error. Modified "info procs", "info args", "info body", and "info default" to return information about imported procedures as well as procedures defined in a namespace. (BL) 12/19/97 (enhancement) Added new Tcl_GetString() procedure that can be used in place of Tcl_GetStringFromObj() if the string representation's length isn't needed. (BL) 12/18/97 (bug fix) In the opt argument parsing package: if the description had only flags, the "too many arguments" case was not detected. The default value was not used for the special "args" ending argument. (DL) 1/7/98 (clean up) Moved everything not absolutly necessary out of init.tcl procs now in auto.tcl and package.tcl can be autoloaded if needed. (DL) 1/7/98 (enhancement) tcltest made at install time will search for it's init.tcl where it is, even when using virtual path compilation. (DL) 1/8/98 (os bug workaround) when needed, using a replacement for memcmp so string compare "char with high bit set" "char w/o high bit set" returns the expected value on all platforms. (DL) 1/8/98 (unix portability/configure) building from .../unix/targetName/ subdirectories and simply using "../configure" should now work fine. (DL) 1/14/98 (enhancement) Added new regular expression package that supports AREs, EREs, and BREs. The new package includes new escape characters, meta-syntax, and character classes inside brackets. Regexps involving backslashes may behave differently. (MH) *** POTENTIAL INCOMPATIBILITY *** 1/16/98 (os workaround) Under windows, "file volume" was causing chatter and/or several seconds of hanging when querying empty floppy drives. Changed implementation to call an empirically-derived function that doesn't cause this. (CCS) 1/16/98 (enhancement) Converted regular expressions to a Tcl_Obj type so their compiled form gets cached automatically. Reduced NSUBEXP from 100 to 20. (BW) 1/16/98 (documentation) Change unclear documentation and comments for functions like Tcl_TranslateFileName() and Tcl_ExternalToUtfDString(). Now it explicitly says they take an uninitialized or free DString. A DString that is "empty" or "not holding anything" could have been interpreted as one currently with a zero length, but with a large dynamically allocated buffer. (CCS) ----------------- Released 8.1a1, 1/22/98 ----------------------- 1/28/98 (new feature) Added a "-direct" optional flag to pkg_mkIndex to generate direct loading package indexes (such those you need if you use namespaces and plan on using namespace import just after package require). pkg_mkIndex still has limitations regarding package dependencies but errors are now ignored and with -direct, correct package indexes can be generated even if there are dependencies as long as the "package provide" are done early enough in the files. (DL) 1/28/98 (enhancement) Performance tuning of regexp and regsub. (CCS) 1/28/98 (bug fix) regexp and regsub with "-indices" returned the byte-offsets of the characters in the UTF-8 representation, not the character offsets themselves. (CCS) 1/28/98 (bug fix) "clock format 0 -format %Z -gmt 1" would return the local timezone string instead of "GMT" on Solaris and Windows. 1/28/98 (bug fix) Restore tty settings when closing serial device on Unix. This is good behavior when closing real serial devices, essential when closing the pseudo-device /dev/tty because the user's terminal settings would be left useless, in raw mode, when tcl quit. (CCS) 1/28/98 (bug fix) Tcl_OpenCommandChannel() was modifying the contents of the argv array passed to it, causing problems for any caller that wanted to continue to use the argv array after calling Tcl_OpenCommandChannel(). (CCS) 2/1/98 (bug fix) More bugs with %Z in format string argument to strftime(): 1. Borland always returned empty string. 2. MSVC always returned the timezone string for the current time, not the timezone string for the specified time. 3. With MSVC, "clock format 0 -format %Z -gmt 1" would return "GMT" the first time it was called, but would return the current timezone string on all subsequent calls. (CCS) 2/1/98 (bug fix) "file stat" was broken on Windows. 1. "file stat" of a root directory (local or network) or a relative path that resolved to a root directory (c:. when in pwd was c:/) was returning error. 2. "file stat" on a regular file (S_IFREG), the st_mode was sign extended to a negative int if the platform-dependant type "mode_t" was declared as a short instead of an unsigned short. 3. "file stat" of a network directory, the st_dev was incorrectly reported as the id of the last accessed local drive rather than the id of the network drive. (CCS) 2/1/98 (bug fix) "file attributes" of a relative path that resolved to a root directory was returning error. (CCS) 2/1/98 (bug fix) Change error message when "file attribute" could not determine the attributes for a file. Previously it would return different error messages on Unix vs. Windows vs. Mac. (CCS) 2/4/98 (bug fixes) Fixed several instances of bugs where the parser/compiler would reach outside the range of allocated memory. Improved the array lookup algorithm in set compilation. (DL) 2/5/98 (change) The TCL_PARSE_PART1 flag for Set/Get(Obj)Var2 C APIs is now deprecated and ignored. The part1 is always parsed when the part2 argument is NULL. This is to avoid a pattern of errors for extension writers converting from string based Tcl_SetVar() to new Tcl_SetObjVar2() and who could easily forget to provide the flag and thus get code working for normal variables but not for array elements. The performance hit is minimal. A side effect of that change is that is is no longer possible to create scalar variables that can't be accessed by tcl scripts because of their invalid name (ending with parenthesis). Likewise it is also parsed and checked to ensure that you don't create array elements of array whose name is a valid array element because they would not be accessible from scripts anyway. Note: There is still duplicate array elements parsing code. (DL) *** POTENTIAL INCOMPATIBILITY *** 2/11/98 (bug fix) Sharing objects between interps, such as by "interp eval" or "send" could cause a crash later when dereferencing an interp that had been deleted, given code such as: set a {set x y} interp create foo interp eval foo $a interp delete foo unset a Interp "foo" was gone, but "a" had a internal rep consisting of bytecodes containing a dangling pointer to "foo". Unsetting "a" would attempt to return resources back to "foo", causing a crash as random memory was accessed. The lesson is that that if an object's internal rep depends on an interp (or any other data structure) it must preserve that data in some fashion. (CCS) 2/11/98 (enhancement) The "interp" command was returning inconsistent error messages when the specified slave interp could not be found. (CCS) 2/11/98 (bug fix) Result codes like TCL_BREAK and TCL_CONTINUE were not propagating through the master/slave interp boundaries, such as "interp eval" and "interp alias". TCL_OK, TCL_ERROR, and non-standard codes like teh integer 57 work. There is still a question as to whether TCL_RETURN can/should propagate. (CCS) 2/11/98 (bug fix) TclCompileScript() was derefering memory 1 byte before start of the string to compile, looking for ']'. (CCS,DL) 2/11/98 (bug fix) Tcl_Eval2() was derefering memory 1 byte before start of the string to eval, looking for ']'. (CCS,DL) 2/11/98 (bug fix) Compiling "set a(b" was running off end of string. (CCS,DL) 2/11/98 (bug fix) Windows initialization code was dereferencing uninitialized memory if TCL_LIBRARY environment didn't exist. (CCS) 2/11/98 (bug fix) Windows "registry" command was dereferencing uninitialized memory when constructing the $errorCode for a failed registry call. (CCS) 2/11/98 (enhancement) Eliminate the TCL_USE_TIMEZONE_VAR definition from configure.in, because it was the same information as the already existing HAVE_TM_ZONE definition. The lack of HAVE_TM_ZONE is used to work around a Solaris and Windows bug where "clock format [clock sec] -format %Z -gmt 1" produces the local timezone string instead of "GMT". (CCS) 2/11/98 (bug fix) Memleaks and dereferencing of uninitialized memory in regexp if an error occurred while compiling a regular expression. (CCS). 2/18/98 (new feature) Added mutexes and thread local storage in order to make Tcl thread safe. For testing purposes, there is a testthread command that creates a new thread and an interpreter inside it. See thread.test for examples, but this script-level interface is not fixed. Each thread has its own notifier instance to manage its own events, and threads can post messages to each other's message queue. This uses pthreads on UNIX, and native thread support on other platforms. You enable this by configuring with --enable-threads. Note that at this time *Tk* is still not thread safe. Special thanks to Richard Hipp: his earlier implementation inspired this work. (BW, SS, JI) 2/18/98 (hidden feature change) The way the env() array is shared among interpreters changed. Updates to env used to trigger write traces in other interpreters. This undocumented feature is no longer implemented. Instead, variable tracing is used to keep the C-level environ array in sync with the Tcl-level env array. This required adding TCL_TRACE_ARRAY support to Tcl_TraceVar2 so that array names works properly. (BW) *** POTENTIAL INCOMPATIBILITY *** 2/18/98 (enhancement) Conditional compilation for unix systems (e.g., IRIX, SCO) that use f_bsize instead of st_blksize to determine disk block size. (CCS) 2/23/98 (bug fix) Fixed the emulation of polling selects in the threaded version of the Unix notifier. The bug was showing up on a multiprocessor as starvation of the notifier thread. (BW) ----------------- Released 8.1a2, Feb 23 1998 ----------------------- 9/22/98 (bug fix) Changed the value of TCL_TRACE_ARRAY so it no longer conflicts with the deprecated TCL_PARSE_PART1 flag. This should improve portability of C code. (stanton) 10/6/98 (bug fix) The compile procedure for "if" incorrectly attempted to match against the literal string "if", resulting in a stack overflow when "::if" was compiled. It also would incorrectly accept "if" instead of "elsif" in later clauses. (stanton) 10/15/98 (new feature) Added a "totitle" subcommand to the "string" command to convert strings to capitalize the first character of a string and lowercase all of the other characters. (stanton) 10/15/98 (bug fix) Changed regexp and string commands to properly handle case folding according to the Unicode character tables. (stanton) 10/21/98 (new feature) Added an "encoding" command to facilitate translations of strings between different character encodings. See the encoding.n manual entry for more details. (stanton) 11/3/98 (bug fix) The regular expression character classification syntax now includes Unicode characters in the supported classes. (stanton) 11/6/98 (bug fix) Variable traces were causing crashes when upvar variables went out of scope. [Bug: 796] (stanton) 11/9/98 (bug fix) "format" now correctly handles multibyte characters in %s format strings. (stanton) 11/10/98 (new feature) "regexp" now accepts three new switches ("-line", "-lineanchor", and "-linestop") that control how regular expressions treat line breaks. See the regexp manual entry for more details. (stanton) 11/17/98 (bug fix) "scan" now correctly handles Unicode characters. (stanton) 11/17/98 (new feature) "scan" now supports XPG3 position specifiers and the "%n" conversion character. See the "scan" manual entry for more details. (stanton) 11/17/98 (bug fix) The Tcl memory allocator now returns 8-byte aligned chunks of memory which improves performance on Windows and avoids crashes on other platforms. [Bug: 834] (stanton) 11/23/98 (bug fix) Applied various regular expression performance bug fixes supplied by Henry Spencer. (stanton) 11/30/98 (bug fix) Fixed various thread related race conditions. [Bug: 880 & 607] (stanton) 11/30/98 (bug fix) Fixed a number of memory overflow and leak bugs. [Bug: 584] (stanton) 12/1/98 (new feaure) Added support for Korean encodings. (stanton) 12/1/98 (feature change) Changed the Tcl_EvalObjv interface to remove the string and length arguments. *** POTENTIAL INCOMPATIBILITY with previous alpha releases *** 12/2/98 (bug fix) Fixed various bugs related to line feed translation. [Bug: 887] (stanton) 12/4/98 (new feature) Added a message catalog facility to help with localizing Tcl scripts. Thanks to Mark Harrison for contributing the initial implementation of the "msgcat" package. (stanton) 12/7/98 (bug fix) The memory allocator was failing to update the block list for large memory blocks that were reallocated into a different address. [Bug: 933] (stanton) ----------------- Released 8.1b1, Dec 10 1998 ----------------------- 12/22/98 (performance improvement) Improved the -command option of the lsort command to better use the object system for improved performance (about 5x speed up). Thanks to Syd Polk for suppling the patch. [RFE: 726] (rjohnson) 2/10/99 (bug fix) Restored the Tcl_ObjSetVar2/Tcl_ObjGetVar2 interfaces from 8.0 and renamed the Tcl_GetObjVar2/Tcl_SetObjVar2 interfaces to Tcl_GetVar2Ex and Tcl_SetVar2Ex. This should provide better compatibility with 8.0. (stanton) *** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases *** 2/10/99 (bug fix) Made the eval interfaces compatible with 8.0 by renaming Tcl_EvalObj to Tcl_EvalObjEx, renaming Tcl_Eval2 to Tcl_EvalEx and restoring Tcl_EvalObj and Tcl_GlobalEvalObj interfaces so they match Tcl 8.0. (stanton) *** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases *** 2/25/99 (bug fix/new feature) On Windows, the channel drivers for consoles and serial ports now completely support file events. (redman) 3/5/99 (bug fix) Integrated patches to fix various configure problems that affected HP-UX-11, 64-bit IRIX, Linux, and Solaris. (stanton) 3/9/99 (bug fix) Integrated various AIX related patches to improve support for shared libraries. (stanton) 3/9/99 (new feature) Added tcl_platform(user) to provide a portable way to get the name of the current user. (welch) 3/9/99 (new feature) Integrated the stub library mechanism contributed by Jan Nijtmans, Paul Duffin, and Jean-Claude Wippler. This feature should make it possible to write extensions that support multiple versions of Tcl simultaneously. It also makes it possible to dynamically load extensions into statically linked interpreters. This patch includes the following changes: - Added a Tcl_InitStubs() interface - Added Tcl_PkgProvideEx, Tcl_PkgRequireEx, Tcl_PkgPresentEx, and Tcl_PkgPresent. - Added va_list versions of all VARARGS functions so they can be invoked from wrapper functions. See the manual for more information. (stanton) 3/10/99 (feature change) Replaced Tcl_AlertNotifier with Tcl_ThreadAlert since the Tcl_AlertNotifier function relied on passing internal data structures. (stanton) *** POTENTIAL INCOMPATIBILITY with previous alpha/beta releases *** 3/10/99 (new feature) Added a Tcl_GetVersion API to make it easier to check the Tcl version and patch level from C. (redman) 3/14/99 (feature change) Tried to unify the TclpInitLibrary path routines to look in similar places from Windows to UNIX. The new library search path is: TCL_LIBRARY, TCL_LIBRARY/../tcl8.1, relative to DLL (Windows Only) relative to installed executable, relative to develop executable, and relative to compiled-in in location (UNIX Only.) This fix included: - Defining a TclpFindExecutable - Moving Tcl_FindExecutable to a common area in tclEncoding.c - Modifying the TclpInitLibraryPath routines. (surles) 3/14/99 (feature change) Added hooks for TclPro Wrapper to initialize the location of the encoding files and libraries. This fix included: - Adding the TclSetPerInitScript routine. - Modifying the Tcl_Init routines to evaluate the non-NULL pre-init script. - Adding the Tcl_SetdefaultEncodingDir and Tcl_GetDefaultEncodingDir routines. - Modifying the TclpInitLibrary routines to append the default encoding dir. (surles) 3/14/99 (feature change) Test suite now uses "test" namespace to define the test procedure and other auxiliary procedures as well as global variables. - Global array testConfige is now called ::test::testConfig. - Global variable VERBOSE is now called ::test::verbose, and ::test::verbose no longer works with numerical values. We've switched to a bitwise character string. You can set ::test::verbose by using the -verbose option on the Tcl command line. - Global variable TESTS is now called ::test::matchingTests, and can be set on the Tcl command line via the -match option. - There is now a ::test::skipTests variable (works similarly to ::test::matchTests) that can be set on the Tcl command line via the -match option. - The test suite can now be run in any working directory. When you run "make test", the working directory is nolonger switched to ../tests. (hirschl) *** POTENTIAL INCOMPATIBILITY *** --------------- Released 8.1b2, March 16, 1999 ---------------------- 3/18/99 (bug fix) Fixed missing/incorrect characters in shift-jis table (stanton) 3/18/99 (feature change) The glob command ignores the FS_CASE_IS_PRESERVED bit on file systesm and always returns exactly what it gets from the system. (stanton) *** POTENTIAL INCOMPATIBILITY *** 3/19/99 (new feature) Added support for --enable-64bit. For now, this is only supported on Solaris 7 64bit (SunOS 5.7) using the Sun compiler. (redman) 3/23/99 (bug fix) Fixed fileevents and gets on Windows consoles and serial devices so that non-blocking channels do not block on partial input lines. (redman) 3/23/99 (bug fix) Added a new Tcl_ServiceModeHook interface. This is used on Windows to avoid the various problems that people have been seeing where the system hangs when tclsh is running outside of the event loop. As part of this, renamed TclpAlertNotifier back to Tcl_AlertNotifier since it is public. (stanton) 3/23/99 (feature change) Test suite now uses "tcltest" namespace to define the test procedure and other auxiliary procedures as well as global variables. The previously chosen "test" namespace was thought to be too generic and likely to create conflits. (hirschl) *** POTENTIAL INCOMPATIBILITY *** 3/24/99 (bug fix) Make sockets thread safe on Windows. (redman) 3/24/99 (bug fix) Fix cases where expr would incorrect return a floating point value instead of an integer. (stanton) 3/25/99 (bug fix) Added ASCII to big5 and gb2312 encodings. (stanton) 3/25/99 (feature change) Changed so aliases are invoked at current scope in the target interpreter instead of at the global scope. This was an incompatibility introduced in 8.1 that is being removed. (stanton) *** POTENTIAL INCOMPATIBILITY with previous beta releases *** 3/26/99 (feature change) --enable-shared is now the default and build Tcl as a shared library; specify --disable-shared to build a static Tcl library and shell. *** POTENTIAL INCOMPATIBILITY *** 3/29/99 (bug fix) Removed the stub functions and changed the stub macros to just use the name without params. Pass &tclStubs into the interp (don't use tclStubsPtr because of collisions with the stubs on Solaris). (redman) 3/30/99 (bug fix) Loadable modules are now unloaded at the last possible moment during Tcl_Finalize to fix various exit-time crashes. (welch) 3/30/99 (bug fix) Tcl no longer calls setlocale(). It looks at env(LANG) and env(LC_TYPE) instead. (stanton) 4/1/99 (bug fix) Fixed the Ultrix multiple symbol definition problem. Now, even Tcl includes a copy of the Tcl stub library. (redman) 4/1/99 (bug fix) Internationalized the registry package. 4/1/99 (bug fix) Changed the implemenation of Tcl_ConditionWait and Tcl_ConditionNotify on Windows. The new algorithm eliminates a race condition and was suggested by Jim Davidson. (welch) 4/2/99 (new apis) Made various Unicode utility functions public. Tcl_UtfToUniCharDString, Tcl_UniCharToUtfDString, Tcl_UniCharLen, Tcl_UniCharNcmp, Tcl_UniCharIsAlnum, Tcl_UniCharIsAlpha, Tcl_UniCharIsDigit, Tcl_UniCharIsLower, Tcl_UniCharIsSpace, Tcl_UniCharIsUpper, Tcl_UniCharIsWordChar, Tcl_WinUtfToTChar, Tcl_WinTCharToUtf (stanton) 4/2/99 (feature change) Add new DDE package and removed the Tk send command from the Windows version. Changed DDE-based send code into "dde eval" command. The DDE package can be loaded into tclsh, not just wish. Windows only. (redman) 4/5/99 (bug fix) Changed safe-tcl so that the encoding command is an alias that masks out the "encoding system" subcommand. (redman) 4/5/99 (bug fix) Configure patches to improve support for OS/390 and BSD/OS 4.*. (stanton) 4/5/99 (bug fix) Fixed crash in the clock command that occurred with negative time values in timezones east of GMT. (stanton) 4/6/99 (bug fix) Moved the "array set" C level code into a common routine (TclArraySet). The TclSetupEnv routine now uses this API to create an env array w/ no elements. This fixes the bug caused when every environ varaible is removed, and the Tcl env variable is synched. If no environ vars existed, the Tcl env var would never be created. (surles) 4/6/99 (bug fix) Made the Env module I18N compliant. (surles) 4/6/99 (bug fix) Changed the FindVariable routine to TclpFindVariable, that now does a case insensitive string comparison on Windows, and not on UNIX. (surles) --------------- Released 8.1b3, April 6, 1999 ---------------------- 4/9/99 (bug fix) Fixed notifier deadlock situation when the pipe used to talk back notifier thread is filled with data. Found as a result of the focus.test for Tk hanging. (redman) 4/13/99 (bug fix) Fixed bug where socket -async combined with fileevent for writing did not work under Windows NT. (redman) 4/13/99 (encoding fix) Restored the double byte definition of GB2312 and added the EUC-CN encoding. EUC-CN is a variant of GB2312 that shifts the characters into bytes with the high bit set and includes ASCII as a subset. (stanton) 4/27/99 (bug fix) Added 'extern "C" {}' block around the stub table pointer declaration so the stub library can be used from C++. (stanton) --------------- Released 8.1 final, April 29, 1999 ---------------------- 4/22/99 (bug fix) Changed Windows NT socket implementation to avoid creating a communication window. This avoids the problem where the system hangs waiting for tclsh to respond to a system-wide synchronous broadcast (e.g. if you change system colors). (redman) 4/22/99 (bug fix) Added call to TclWinInit from TclpInitPlatform when building a static library since DllMain will not be invoked. This could break old code that explicitly called TclWinInit, but should be simpler in the long run. (stanton) *** POTENTIAL INCOMPATIBILITY *** 4/23/99 (bug fix) Added support for the koi8-r Cyrillic encoding. [Bug: 1771] (stanton) 4/28/99 (bug fix) Changed internal Tcl_Obj usage to avoid freeing the internal representation after the string representation has been freed. This makes it easier to debug extensions. (stanton) 4/30/99 (bug fix) Fixed a memory leak in CommandComplete. (stanton) 5/3/99 (bug fix) Fixed a bug where the Tcl_ObjType was not being set in a duplicated Tcl_Obj. [Bug: 1975, 2047] (stanton) 5/3/99 (bug fix) Changed Tcl_ParseCommand to avoid modifying eval'ed strings that are already null terminated. [Bug: 1793] (stanton) 5/3/99 (new feature) Applied Jeff Hobbs's string patch which includes the following changes: - added new subcommands: equal, repeat, map, is, replace - added -length option to "string compare|equal" - added -nocase option to "string compare|equal|match" - string and list indices can be an integer or end?-integer?. - added optional first and last index args to string toupper, et al. See the string.n manual entry for more details about the new string features. [Bug: 1845] (stanton) 5/6/99 (new feature) Added Tcl_UtfNcmp and Tcl_UtfNcasecmp to make Utf string comparision easier. (stanton) 5/7/99 (bug fix) Improved OS/390 support. [Bug: 1976, 1997] (stanton) 5/12/99 (bug fix) Changed Windows initialization code to avoid using GetUserName system call in favor of the env(USERNAME) variable. This provides a significant startup speed improvement. (stanton) 5/12/99 (bug fix) Replaced the per-interpreter regexp cache with a per-thread cache. Changed the Regexp object to take advantage of this extra cache. Added a reference count to the TclRegexp type so regexps can be shared by multiple objects. Removed the per-interp regexp cache from the interpreter. Now regexps can be used with no need for an interpreter. This set of changes should provide significant speed improvements for many Tcl scripts. [Bug: 1063] (stanton) 5/14/99 (bug fix) Durining initialization on Unix, Tcl now extracts the encoding subfield from the LANG/LC_ALL environment variables in cases where the locale is not found in the built-in locale table. It also attempts to initialize the locale subsystem so X11 is happy. [Bug: 1989] (stanton) 5/14/99 (bug fix) Applied the patch to fix 100-year and 400-year boundaries in leap year code, from Isaac Hollander. [Bug: 2066] (redman) 5/14/99 (bug fix) Fixed a crash caused by a failure to reset the result before evaluating the test expression in an uncompiled for statement. (stanton) 5/18/99 (bug fix) Modified initialization code on Windows to avoid inherenting closed or invalid channels. If the standard input is anything other than a console, file, serial port, or pipe, then we fall back to the standard Tk window console. (stanton) 5/19/99 (bug fix) Added an extern "C" block around the entire tcl.h header file to avoid C++ linkage issues. (redman) 5/19/99 (new feature) Applied Jeff Hobb's patch to add Tcl_StringCaseMatch to support case insensitive glob style matching and Tcl_UniCharIs* character classification functions. (stanton) 5/20/99 (bug fix) Added the directory containing the executuble and the ../lib directory relative to that to the auto_path variable. (redman) --------------- Released 8.1.1, May 25, 1999 ---------------------- 5/21/99 (bug fix) Fixed launching command.com on Win95/98, no longer hangs. [Bug: 2105] (redman) 5/28/99 (bug fix) Fixed bug where dde calls were being passed an invalid dde handle. [Bug: 2124] (stanton) 6/1/99 (bug fix) Small configure.in patches. [Bug: 2121] (stanton) 6/1/99 (bug fix) Applied latest regular expression patches to fix an infinite loop bug and add support for testing whether a string could match with additional input. [Bug: 2117] (stanton) 6/2/99 (bug fix) Fixed incorrect computation of relative ordering in Utf case-insensitive comparison. [Bug: 2135] (stanton) 6/3/99 (bug fix) Fxied bug where string equal/compare -nocase reported wrong result on null strings. [Bug: 2138] (stanton) 6/4/99 (new feature) Windows build now uses Cygwin tools plus GNU make and autoconf to build static/dynamic and debug/nodebug. (stanton) 6/7/99 (new feature) Optimized string index, length, range, and append commands. Added a new Unicode object type. (hershey) 6/8/99 (bug fix) Rolled back Windows socket driver to 8.1.0 version. (stanton) 6/9/99 (new feature) Added Tcl_RegExpMatchObj and Tcl_RegExpGetInfo to public Tcl API, these functions are needed by Expect. Changed tools/genStubs.tcl to always write output in LF mode. (stanton) 6/14/99 (new feature) Merged string and Unicode object types. Added new public Tcl API functions: Tcl_NewUnicodeObj, Tcl_SetUnicodeObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, Tcl_AppendUnicodeToObj. (hershey) 6/16/99 (new feature) Changed to conform to TEA specification, added tcl.m4 and aclocal.m4 macro libraries for configure. (wart) 6/17/99 (new feature) Added new regexp interfaces: -expanded, -line, -linestop, and -lineanchor switches. Renamed Tcl_RegExpMatchObj to Tcl_RegExpExecObj and added new Tcl_RegExpMatchObj that is equivalent to Tcl_RegExpMatch. Added public macros for regexp flags. Added REG_BOSONLY flag to allow Expect to iterate through a string and only find matches that start at the current position within the string. (stanton) 6/21/99 (bug fix) Fixed memory leak in TclpThreadCreate where thread attributes were not being released. [Bug: 2254] (stanton) 6/23/99 (new feature) Updated Unicode character tables to reflect Unicode 2.1 data. (stanton) 6/25/99 (new feature) Fixed bugs in non-greedy quantifiers for regular expression code. (stanton) 6/25/99 (new feature) Added initial implementation of new Tcl test harness package. Modified test files to use new tcltest package. (jenn) 6/26/99 (new feature) Applied patch from Peter Hardie to add poke command to dde and changed the dde package version number to 1.1. (redman) 6/28/99 (bug fix) Applied patch from Peter Hardie to fix problem in Tcl_GetIndexFromObj() when the key being passed is the empty string. [Bug: 1738] (redman) 6/29/99 (new feature) Added options to tcltest package: -preservecore, -limitconstraints, -help, -file, -notfile, and flags. (jenn) 7/3/99 (new feature) Changed parsing of variable names to allow empty array names. Now "$(foo)" is a variable reference. Previously you had to use something line $::(foo), which is slower. This change was requested by Jean-Luc Fontaine for his STOOOP package. (welch) 7/3/99 (new feature) Added Tcl_SetNotifier (public API) and associated hook points in the notifiers to be able to replace the notifier calls at runtime. The Xt notifier and test program use this hook. (welch) 7/3/99 (new feature) Added a new variant of the "Trf core patch" from Andreas Kupries that adds new C APIs Tcl_StackChannel, Tcl_UnstackChannel, and Tcl_GetStackedChannel. This allows the Trf extension to work without applying patches to the Tcl core. (welch) 7/6/99 (new feature) Added -timeout option to http.tcl to handle timeouts that occur during connection attempts to hosts that are down. (welch) 7/6/99 (bug fix) Applied new implementation of the Windows serial port driver from Rolf Schroedter that fixes reading only one byte from the port at a time. Uses polling every 10ms to implement fileevents. [Bug: 1980 2217] (redman) 7/8/99 (bug fix) Applied fix for bug in DFA state caching under lookahead conditions (regular expressions). [Bug: 2318] (stanton) 7/8/99 (bug fix) Fixed bug in string range bounds checking code. (stanton) --------------- Released 8.2b1, July 14, 1999 ---------------------- 7/16/99 (bug fix) Added Tcl_SetNotifier to stub table. [Bug: 2364] Added check for Alpha/Linux to correct the IEEE floating point flag, patch from Don Porter. (redman) 7/20/99 (bug fix) Merged 8.0.5 code to handle tcl_library properly, also fixed a bug that caused TCL_LIBRARY to be ignored. (hershey) 7/21/99 (bug fix) Implemented modified socket driver for Windows that uses a thread to manage the socket event window. Code works the same on all supported versions of Windows and was based on original 8.1.0 code. [Bug: 2178 2256 2259 2329 2323 2355] (redman) 7/21/99 (new feature) Applied patch from Rolf Schroedter to add -pollinterval option to fconfigure for Windows serial ports. Allows the maxblocktime to be modified to control how often serial ports are checked for fileevents. Also added documentation for \\.\comX notation for opening serial ports on Windows. (redman) 7/21/99 (bug fix) Changed APIs in stub tables to use "unsigned long" instead of the platform-specific "size_t", primarily after SunOS 4 users could no longer compile. (redman) 7/22/99 (bug fix) Fixed crashing during "array set a(b) {}". [Bug: 2427] (redman) 7/22/99 (bug fix) The install-sh script must be given execute permissions prior to running. [Bug: 2413] (redman) 7/22/99 (bug fix) Applied patch from Ulrich Ring to remove ANSI-style prototypes in the code. [Bug: 2391] (redman) 7/22/99 (bug fix) Added #if blocks around #includes of sys/*.h header files, to allow an extension author on Windows to use the MetroWerks compiler. [Bug: 2385] (redman) 7/22/99 (bug fix) Fixed running the safe.test test suite, one change to the Windows Makefile.in to fix paths and another in safe.test to check for the tcl_platform(threaded) variable properly. (redman) 7/22/99 (bug fix) Fixed hanging in new Win32 socket driver with threads enabled. (redman) 7/26/99 (bug fix) Fixed terminating of helper threads by holding any mutexes from the primary thread while waiting for the helper thread to terminate. Fixes dual-CPU WinNT hangs, only one rare sporadic hang that still exists with dual-CPU WinNT. Also fixed test cases so that they would not depend as much on timing for dual-CPU WinNT. (redman) 7/27/99 (bug fix) Some test suite cleanup. (jenn) 7/29/99 (bug fix) Applied patch to fix typo in .SH NAME line in doc/Encoding.n [Bug: 2451]. Applied patch to avoid linking pack.n to pack-old.n [Bug: 2469]. Patches from Don Porter. (redman) 7/29/99 (bug fix) Allow tcl to open CON and NUL, even for redirection of std channels. [Bug: 2393 2392 2209 2458] (redman) 7/30/99 (bug fix) Applied fixed Trf patch from Andreas Kupries. [Bug: 2386] (hobbs) 7/30/99 (bug fix) Fixed bug in info complete. [Bug: 2383 2466] (hobbs) 7/30/99 (bug fix) Applied patch to fix threading on Irix 6.5, patch provided by James Dennett. [Bug: 2450] (redman) 7/30/99 (bug fix) Fixed launching of 16bit applications on Win9x from wish. The command line was being primed with tclpip82.dll, but it was ignored later. 7/30/99 (bug fix) Added functions to stub table, patch provided by Jan Nijtmans. [Bug: 2445] (hobbs) 8/1/99 (bug fix) Changed Windows socket driver to terminate threads by sending a message to the window rather than calling TerminateThread(), which seems to leak about 4k from the helper thread's stack space. (redman) --------------- Released 8.2b2, August 5, 1999 ---------------------- 8/4/99 (bug fix) Applied patches supplied by Henry Spencer to greatly enhance performance of certain classes of regular expressions. [Bug: 2440 2447] (stanton) 8/5/99 (doc change) Made it clear that tcl_pkgPath was not set for Windows. [Bug: 2455] (hobbs) 8/5/99 (bug fix) Fixed reference to bytes that might not be null terminated in tclLiteral.c. [Bug: 2496] (hobbs) 8/5/99 (bug fix) Fixed typo in http.tcl. [Bug: 2502] (hobbs) 8/9/99 (bug fix) Fixed test suite to handle larger integers (64bit). Patch from Don Porter. (hobbs) 8/9/99 (documentation fix) Clarified Tcl_DecrRefCount docs [Bug: 1952]. Clarified array pattern docs [Bug: 1330]. Fixed clock docs [Bug: 693]. Fixed formatting errors [Bug: 2188 2189]. Fixed doc error in tclvars.n [Bug: 2042]. (hobbs) 8/9/99 (bug fix) Fixed path handling in auto_execok [Bug: 1276] (hobbs) 8/9/99 (internal api change) Removed the TclpMutexLock and TclpMutexUnlock APIs and added a new exported api, Tcl_GetAllocMutex. These APIs are all for the mutex used in the simple memory allocators. By making this change we are able to substitute different implementations of the thread-related APIs without having to recompile the Tcl core. (welch) 8/9/99 (new C API) Tcl_GetChannelNames returns a list of open channel names in the interpreter result. Still no Tcl-level version of this, but server-like applications can use this to clean up files without deleting interpreters. (welch) 8/9/99 (bug fix) Traces were not firing on "info exists", which used to happen in Tcl 7.6 and earlier. An "info exists" now fires a read trace, if defined. This makes it possible to fully implement variables that are defined via traces. (welch) 8/10/99 (bug fix) Fixed Brent's changes so that they work on Windows. (redman) --------------- Released 8.2b3, August 11, 1999 ---------------------- 8/12/99 (Mac) Rearrange projects in tclMacProjects.sea.hqx so that the build directory is separate from the sources. (Jim Ingham) 8/12/99 (bug fix) Fixed bug in Tcl_EvalEx where the termOffset was not being updated in cases where the evaluation returned a non TCL_OK error code. [Bug: 2535] (stanton) --------------- Released 8.2.0, August 17, 1999 ---------------------- 9/21/99 (config fixes) fixed several AIX configuration issues. gcc and threading may still cause problems on AIX. (hobbs) 9/21/99 (bug fix) fixed expr double-eval problem. [Bug: 732] (hobbs) 9/21/99 (bug fix) fixed static buffer overflow problem. [Bug: 2483] (hobbs) 9/21/99 (bug fix) fixed end-int linsert interpretation. [Bug: 2693] (hobbs) 9/21/99 (bug fix) fixed bug when setting array in non-existent namespace. [Bug: 2613] (hobbs) --- Released 8.2.1, October 04, 1999 --- See ChangeLog for details --- 10/30/99 (feature enhancement) new regexp engine from Henry Spencer was patched in - should greatly reduce stack space usage. (spencer) 10/30/99 (bug fix) fixed Purify reported memory leaks in findexecutable test command, TclpCreateProcess on Unix, in handling of C environ array, and in testthread code. No more known (reported) mem leaks for Tcl built using gcc on Solaris 2.5.1. Also none reported for Tcl on NT (using Purify 6.0). (hobbs) 10/30/99 (bug fix) fixed improper bytecode handling of 'eval {set array($unknownvar) 5}' (also for incr) (hobbs) 10/30/99 (bug fix) fixed event/io threading problems by making triggerPipe non-blocking (nick kisserbeth) 10/30/99 (bug fix) fixed Tcl_AppendStringsToObjVA and Tcl_AppendResultVA to only iterates once over the va_list (avoiding non-portable memcpy). (joe english, hobbs) 10/30/99 (bug fix) removed savedChar trick in tclCompile.c that appeared to be causing a segv when the literal table was released. [Bug: 2459, 2515] (David Whitehouse) 10/30/99 (bug fix) fixed [string index] to return ByteArrayObj when indexing into one (test case string-5.16) [Bug: 2871] (hobbs) 10/30/99 (bug fix) fixes for mac UTF filename handling (ingham) --- Released 8.2.2, November 04, 1999 --- See ChangeLog for details --- 11/19/99 (feature enhancement) bug fixes for http package as well as patch required by TLS (SSL) extension that adds http::(un)register and -type to http::geturl. Up'd http pkg version to 2.2. 11/19/99 (bug fix) removed extra decr of numLevels in Tcl_EvalObjEx that could cause seg fault (mjansen@wendt.de) 11/19/99 (bug fixes) numerous minor big fixes, including correcting the installation of the koi8-r encoding and tcltest1.0 on Windows. 11/30/99 (bug fix) fixes scan where %[..] didn't match anything 11/30/99 (bug fix) fixed setting of isNonBlocking flag in PipeBlockModeProc so you can now close a non-blocking channel without waiting. 11/30/99 (bug work-around) prevented the unloading of DLLs for Unix in TclFinalizeLoad. This stops the seg fault on exit that some users would see (ie with oratcl) when using DLLs that do nasty things like register atexit handlers. 12/07/99 (bug fix) fixes for 'expr + {[incr]}' and 'expr + {[error]}' cases (different causes). --- Released 8.2.3, December 16, 1999 --- See ChangeLog for details --- 1999-09-14 (feature enhancement) added -start switch to regexp and regsub. 1999-09-15 (feature enhancement) add 'array unset' command. 1999-09-15 (feature enhancement) rewrote runtime libraries to use new string functions 1999-08-18 (feature enhancement) added 'file channels' command, along with Tcl_GetChannelNames(Ex) public C APIs. 1999-10-19 (feature enhancement) enhanced tcltest package 1999-09-16 (feature enhancement) added -milliseconds switch to 'clock clicks' 1999-10-28 (feature enhancement) added support for inline 'scan' 1999-10-28 (feature enhancement) added support for touch functionality by extendeding 'file atime' and 'file mtime' to take an optional time argument 1999-11-24 (feature enhancement) added 'fconfigure $sock -lasterror' command to Windows to query the last error received on a serial socket. 1999-11-30 (bug fix) fixed handling of %Z on NT for timezones that don't have DST 1999-12-03 (feature enhancement) improved error message in bad octal cases and improper use of comments. (hobbs) 1999-12-07 (bug fix) fixed Tcl_ScanCountedElement to not step beyond the end of the counted string 1999-12-09 (feature enhancement) removed all references to 16 bit compatibility code for Windows (hobbs) 1999-12-10 (bug fix) removed check for vfork - Tcl now uses only fork in exec. (hobbs) 1999-12-10 (optimization) changed Tcl_ConcatObj to return a list object when it receives all pure list objects as input (used by 'concat'), added optimizations in Tcl_EvalObjEx for pure list case, and optimized INST_TRY_CVT_TO_NUMERIC in TclExecuteByteCode for boolean objects. (oakley, hobbs) 1999-12-12 (feature enhancement) enhanced glob command with -type, -path, -directory and -join switches. (darley, hobbs) 1999-12-21 (bug fix) changed CreateThread to _beginthreadex and ExitThread to _endthreadex to prevent 4K mem leak (gravereaux) 1999-12-21 (bug fix) fixed applescript for I18N 1999-12-21 (feature enhancement) added -unique option to lsort (hobbs) 1999-12-21 (bug fix) changed thread ids to longs (for 64bit systems) --- Released 8.3b1, December 22, 1999 --- See ChangeLog for details --- 2000-01-10 (feature enhancement) clock scan now supports the common ISO 8601 date/time formats. See docs for details. (melski) 2000-01-10 (bug fix) prevented \ooo substitution from accepting non-octal digits [Bug: 3975] (hobbs) 2000-01-11 (bug fix) fixed improper handling of DST by clock when using relative times (like "1 month" or "tomorrow"). (melski) 2000-01-12 (bug fix) improved build support for Tru64 v5, NetBSD and Reliant Unix (hobbs) 2000-01-12 (bug fix) made imported commands also import their compile procedure (duffin) 2000-01-12 (bug fix) fixed 'info procs ::namesp::*' behavior to return procs in a namespace (dejong) 2000-01-12 (feature enhancement) added support for setting permissions symbolicly (like chmod) in [file attributes $file -permissions ...] (schoebel) 2000-01-13 (bug fix) fixed lsort -dictionary problem when sorting characters between 'Z' and 'a' (flawed upper/lower comparison logic) (melski) --- Released 8.3b2, January 13, 2000 --- See ChangeLog for details --- 2000-01-14 (feature enhancement) clock format %Q added, clock scan updated 2000-01-20 (bug fix) corrected complex array elem compiling (Spjuth) 2000-01-20 (bug fix) made [info body] always return a string type arg, to prevent possible misuse of bytecodes in the wrong context (hobbs) 2000-01-20 (bug fixes) several fixes to variable handling to prevent possible crashes, and further definition of correct behavior (melski) 2000-01-25 (bug fixes) improved QNX, Ultrix and OSF1 (Tru64) config and compatibility (edge, furukawa) 2000-01-25 (bug fix) fixed mem leak when calling lsort with a bad -command argument (hobbs) 2000-01-27 (feature enhancement) package mechanism overhaul: changed behavior of pkg_mkIndex to do -direct by default, added -lazy option. Fixed pkg_mkIndex to handle odd proc names and auto_mkIndex to use platform independent file paths. Other fixes for odd package quirks. Added ::pkg namespace and ::pkg::create helper function. (melski) 2000-02-01 (bug fix) fixed problem where http POST would send one extra newline (vasiljevic) 2000-02-02 (feature enhancement) added docs for new regexp -inline and -all switches. (hobbs) 2000-02-08 (bug fix) corrected handling of "next monthname" in clock scan (melski) 2000-02-09 (bug fix) restored Mac source to build readiness and prevented mac panic from an error when closing an async socket (steffen, ingham) 2000-02-10 (feature enhancement) improved error reporting for failed loads on Windows (dejong, hobbs) --- Released 8.3.0, February 10, 2000 --- See ChangeLog for details --- 2000-03 (bug fixes, feature enhancement) overhaul of http package for proper handling of async callbacks (new options), version is now at 2.3 (tamhankar, welch) 2000-03 (performance enhancement) speedup in Windows filename handling (newman) and ==/!= empty string in exprs. (hobbs) 2000-03-27 (bug fix) added uniq'ing test to namespace export list to prevent unnecessary mem growth (hobbs) 2000-03-29 (bug fix) fixed mem leak when repeatedly sourcing the same bytecompiled (tbc) code repeatedly across different interpreters (hobbs) 2000-03-29 (config enhancement) improved build support for gcc/mingw on Windows (nijtmans, hobbs) and added RPM target (melski) 2000-03-31 (bug fix) corrected data encoding problem when using "exec << $data" construct (melski) 2000-04 (feature enhancement) overhaul of threading mechanism to better support tcl level thread command (new APIs Tcl_ConditionFinalize, Tcl_MutexFinalize, Tcl_CreateThread, etc, all docs in Thread.3). (kupries, graveraux) This enables the tcl level thread extension. (welch) 2000-04-10 (bug fix) fixed infinite loop case in regexp -all (melski) 2000-04-13 (config enhancement) added support for --enable-64bit-vis Sparc target. (hobbs) 2000-04-18 (bug fix) moved tclLibraryPath to thread-local storage to fix possible race condition on MP machines (hobbs) 2000-04-18 (config enhancement) added MacOS X build target and tclLoadDyld.c dl type. (sanchez) 2000-04-23 (bug fix) several Mac socket fixes (ingham) 2000-04-24 (bug fix) fixed hang in threaded Unix case when backgrounded exec process was running (dejong) --- Released 8.3.1, April 26, 2000 --- See ChangeLog for details --- 2000-04-26 (doc fix) updated/added documentation for many API's and commands (melski) 2000-05-02 (feature enhancement) added support for joinable threads; extended API's for channels to allow channels to move between threads (kupries) 2000-05-02 (feature enhancement) changed error return for procedures with incorrect args to be like the Tcl_WrongNumArgs API, with a "wrong # args: ..." message printed, with an args list (hobbs) 2000-05-08 (feature enhancement) added [array statistics] command 2000-05-08 (performance enhancement) rewrote Tcl_StringCaseMatch algorithm for better performance; this affects the [string match] command; added "eq" and "ne" operands to expr, for testing string equality and inequality (hobbs) 2000-05-09 (feature enhancement) extended [lsearch] to support sorted list searches and typed list searches (melski) 2000-05-10 (feature enhancement) added [namespace exists] command (darley) 2000-05-18 (build enhancement) added support for mingw compile env and cross-compiling (dejong) 2000-05-18 (bug fix) corrected clock grammar to properly handle the "ago" keyword when it follows multiple relative unit specifiers (melski) 2000-05-22 (compile fix) type cast cleanups (dejong) 2000-05-23 (performance enhancement) added byte-compiled implementation of [return] command and [string] command (melski) 2000-05-26 (performance enhancement) extended byte-compiled [string] command with support for [string compare/index/match] (hobbs) 2000-05-27 (feature enhancement) added ability to set [info script] return value ([info script ?newFileName?]) (welch) 2000-05-31 (feature enhancement) added support for regexp and exact pattern matching for [array names] (gazetta) 2000-05-31 (feature enhancement) added -nocomplain and -- flags to [unset] to allow for silent unset operation (hobbs) --- Released 8.4a1, June 6, 2000 --- See ChangeLog for details --- 2000-05-29 (bug fix) corrected resource cleanup in http error cases. Improved handling of error cases in http. (tamhankar) 2000-07 (feature rewrite) complete rewrite of the Tcl IO channel subsystem to correct problems (hangs, core dumps) with the initial stacked channel implementation. The new system has many more tests for robustness and scalability. There are new C APIs (see Tcl_CreateChannel), but only stacked channel drivers are affected (ie: TLS, Trf, iogt). The iogt extension has been added to the core test code to test the system. (hobbs, kupries) **** POTENTIAL INCOMPATABILITY **** 2000-07 (build improvements) cleanup of the makefiles and configure scripts to correct support for building under gcc for Windows. (dejong) 2000-08-07 (bug fix) corrected sizeof error in Tcl_GetIndexFromObjStruct. (perkins) 2000-08-07 (bug fix) correct off-by-one error in HistIndex, which was causing [history redo] to start its search at the wrong event index. (melski) 2000-08-07 (bug fix) corrected setlocale calls for XIM support and locale issues in startup. (takahashi) 2000-08-07 (bug fix) correct code to handle locale specific return values from strftime, if any. (wagner) 2000-08-07 (bug fix) tweaked grammar to properly handle the "ago" keyword when it follows multiple relative unit specifiers, as in "2 days 2 hours ago". (melski) 2000-08-07 (doc fixes) numerous doc fixes to correct SEE ALSO and NAME sections. (english) 2000-08-07 (bug fix) new man pages memory.n, TCL_MEM_DEBUG.3, Init.3 and DumpActiveMemory.3. (melski) --- Released 8.3.2, August 9, 2000 --- See ChangeLog for details --- 2000-06 thru 2000-11 (build improvements) Added support for mingw (gcc on Windows), AIX-5 and Win64 builds (dejong, hobbs) 2000-06-23 (feature enhancement) ability to use Tcl_Obj *s as hash keys (duffin) 2000-06-29 (new features) added [mcmax] and [mcmset] and extended [unknown] in msgcat package (duperval, krone, nelson) => msgcat 1.1 2000-08 thru 2000-09 added tclPlatDecls.h to default install (melski, hobbs) 2000-08-24 (new feature) Enhanced trace syntax to add: trace {add|remove|list} {variable|command} name ops command (darley, melski) 2000-09-06 (cross-platform feature) Set ^Z (\32) as default EOF char. (hobbs) 2000-09-07 partial fix for bug 2460 to prevent exec mem leak on Windows for the common case (gravereaux) 2000-09-14 Improved string allocation growth for large strings (hintermayer, melski) 2000-09-14 New non-panic'ing mem allocation functions Tcl_AttemptAlloc, Tcl_AttemptRealloc, Tcl_AttemptSetObjLength (melski) 2000-09-20 (new features) completely new, enhanced syntax in tcltest package. Backwards compatable with tcltest v1. (hom) => tcltest 2.0 2000-09-27 (bug fix) fixed a bug introduced by a partial fix in 8.3.2 that didn't set nonBlocking correctly when resetting the flags for the write side (mem leak) Correct mem leak in channels when statePtr was released (hobbs) 2000-09-29 (bug fix) corrected reporting of space parity on Windows (Eason) 2000-10-06 (bug fix) corrected [file channels] to only return channels in the current interpreter (hobbs) 2000-10-20 (performance enhancement) call stat only when necessary in 'glob' to speed up command significantly in base cases (hobbs) 2000-10-27 Fixed mem leak in Tcl_CreateChannel. Re-purified core via test suites. (hobbs) 2000-10-30 (new feature) add "ja_JP.eucJP" map to "euc-jp" encoding (takahashi) 2000-11-01 (mem leak) Corrected excessive mem use of info exists on a non-existent array element (hobbs) 2000-11-02 (bug fix) Corrected sharing of tclLibraryPath in threaded environment (gravereaux) 2000-11-03 (new feature) Tcl_SetMainLoop enables defining an event loop for tclsh. This enables Tk as a truly loadable package. (hobbs) --- Released 8.4a2, November 3, 2000 --- See ChangeLog for details --- 2000-09-27 (bug fix) fixed a bug introduced by a partial fix in 8.3.2 that didn't set nonBlocking correctly when resetting the flags for the write side (mem leak) Correct mem leak in channels when statePtr was released (hobbs) 2000-09-29 (bug fix) corrected reporting of space parity on Windows (Eason) 2000-10-06 (bug fix) corrected [file channels] to only return channels in the current interpreter (hobbs) 2000-10-20 (performance enhancement) call stat only when necessary in 'glob' to speed up command significantly in base cases (hobbs) 2000-11-01 (mem leak) Corrected excessive mem use of info exists on a non-existent array element (hobbs) 2000-11-02 (bug fix) Corrected sharing of tclLibraryPath in threaded environment (gravereaux) 2000-11-23 (mem leak) fixed potential memory leak in error case of lsort (fellows) 2000-12-09 (feature enhancement) changed %o and %x to use strtoul instead of strtol to correctly preserve scan<>format conversion of large integers (hobbs) Fixed handling of {!} in expressions (hobbs, fellows) 2000-12-14 (feature enhancement) improved (s)rand for 64-bit platforms (porter) 2001-01-04 (bug fix) corrected parsing of $tcl_libPath at startup on Windows (porter) 2001-01-30 (bug fix) Fixed possible hangs in fcopy. (porter) 2001-02-15 (performance enhancement) improved efficiency of [string split] (fellows) 2001-03-13 (bug fix) Correctly possible memory corruption in string map {} $str (fellows) 2001-03-29 (bug fix) prevent potential race condition and security leak in tmp filename creation on Unix. (max) Fixed handling of timeout for threads (corrects excessive CPU usage issue for Tk on Unix in threaded Tcl environment). (ruppert) 2001-03-30 (bug fix) corrected Windows memory error on exit (wu) Fixed race condition in readability of socket on Windows. 2001-04-03 (doc fixes) numerous doc corrections and clarifications. Update of READMEs. 2001-04-04 (build improvements) redid Mac build structure (steffen) Corrected IRIX-5* configure (english). Added support for AIX-5 (hobbs). Added support for Win64 (hobbs). --- Released 8.3.3, April 6, 2001 --- See ChangeLog for details --- 2000-11-23 (new feature)[TIP 7] higher resolution timer on Windows (kenny) 2001-01-18 (new feature) Tcl_InitHashTableEx renamed to Tcl_InitCustomHashTable (kupries) 2001-03-30 (new feature)[TIP 10] support for thread-aware/hot channels (kupries) 2001-04-06 (new feature)[219280] auto-loading hidden in ::errorInfo (porter) 2001-04-07 (bug fix)[406709] corrected panic when extra items left on the byte compiler execution stack (sofer) 2001-04-09 (bug fix)[219136,232558] improved use of thread-safe functions in unix time commands (kenny) 2001-04-24 (new feature)[TIP 27] started CONST-ification of the Tcl APIs (kenny) 2001-05-03 (new feature) [auto_import] now matches patterns like [namespace import], not like [string match] (porter) **** POTENTIAL INCOMPATABILITY **** 2001-05-07 (new feature)[416643] distinct srand() seed per interp (sofer) 2001-05-15 (new feature) new Tcl_GetUnicodeFromObj API (hobbs) 2001-05-16 (performance enhancement) byte-compiled versions of [lappend], [append] simple cases (hobbs) 2001-05-23 (new feature) added ISO-8859-15 and koi8-u encodings, updated other encoding tables based on http://www.unicode.org/Public/MAPPINGS/ (kuhn) 2001-05-27 (new feature) updated to Unicode 3.1.0 data set (still using 16 bits for Tcl_UniChar though) (hobbs) 2001-05-30 (new feature)[TIP 15] Tcl_GetMathFuncInfo, Tcl_ListMathFuncs, Tcl_InfoObjCmd, InfoFunctionsCmd APIs (fellows) 2001-06-08 (bug fix,feature enhancement)[219170,414936] all Tcl_Panic definitions brought into agreement (porter) 2001-06-12 (bug fix)[219232] regexp returned non-matching sub-pairs to have index pair {-1 -1} (fellows) 2001-06-27 (bug fix)[217987] corrected backslash substitution of non-ASCII characters. (hobbs, riefenstahl) 2001-06-28 (bug fix)[231259] failure to re-compile after cmd shadowing (sofer) 2001-07-02 (bug fix)[227512] corrected [concat] treatment of UTF-8 strings (hobbs, barras) 2001-07-12 (new feature)[TIP 36] Tcl_SubstObj API (fellows) 2001-07-16 (bug fix) corrected thread-enabled pipe closing on Windows (hobbs, jsmith) 2001-07-18 (bug fix)[427196] corrected memory overwrite error when buffer size of a channel is changed after channel use has already begun (kupries, porter) 2001-07-31 (new feature)[TIP 17] TclFS* APIs provide new virtual file system. This includes the addition of 'file normalize', 'file system', 'file separator' and 'glob -tails' (darley) 2001-08-06 (bug fix) removed use of tmpnam in TclpCreateTempFile on Unix (lim) * improved build support for IRIX, GNU HURD, Mac OS 9 and OS X * configure scripts revamped for better support of cygwin and gcc on Windows (mdejong) * corrected several minor errors noted by Purify (hobbs) --- Released 8.4a3, August 6, 2001 --- See ChangeLog for details --- 2001-06-27 (bug fix)[217987] corrected backslash substitution of non-ASCII characters. (hobbs, riefenstahl) 2001-06-28 (bug fix)[231259] failure to re-compile after cmd shadowing (sofer) 2001-07-02 (bug fix)[227512] corrected [concat] treatment of UTF-8 strings (hobbs, barras) 2001-07-16 (bug fix) corrected thread-enabled pipe closing on Windows (hobbs, jsmith) 2001-07-18 (bug fix)[427196] corrected memory overwrite error when buffer size of a channel is changed after channel use has already begun (kupries, porter) 2001-08-06 (bug fix)[442665] corrected object reference counting in [gets] (jikamens) 2001-08-06 (new feature) added GNU (HURD) configuration target. (brinkmann) 2001-08-07 (bug fix)[406709] corrected panic when extra items left on the byte compiler execution stack (see test foreach-5.5) (sofer, tallneil, jstrot) 2001-08-08 (new features) updated packages msgcat 1.1.1, opt 0.4.3, tcltest 1.0.1, dependencies checked (porter) 2001-08-20 (new feature)[452217] http 2.3.2: include port number in Host: header to comply with HTTP/1.1 spec (RFC 2068) (hobbs, tils) 2001-08-23 (new feature) added QNX-6 build support (loverso) 2001-08-23 (bug fix) corrected handling of spaces in path name passed to [exec] on Windows (kenpoole) 2001-08-24 (bug fix) corrected [package forget] stopping on non-existent package (porter) 2001-08-24 (bug fix) corrected construction of script library search path relative to executable (porter) 2001-08-24 (bug fix) [auto_import] now matches patterns like [namespace import], not like [string match] (porter) **** POTENTIAL INCOMPATABILITY **** 2001-08-27 (new feature) added Tcl_SetMainLoop() to enable loading Tk as a true package (hobbs) 2001-08-30 (bug fix) build support for Crays (andreasen) 2001-09-01 (bug fix) rewrite of Tcl_Async* APIs to better manage thread cleanup (gravereaux) 2001-09-06 (new feature) http 2.4: honor the Content-encoding and charset parameters; add -binary switch for forcing the issue (hobbs, saoukhi, orwell) => http 2.4 2001-09-06 (performance enhancement) rewrite of file I/O flush management on Windows. Approximately 100x speedup for some operations. (kupries, traum) 2001-09-10 (bug fix) corrected finalization error in TclInExit (darley) 2001-09-10 (bug fix) protect against alias loops (hobbs) 2001-09-12 (bug fix) added missing #include in tclLoadShl.c (techentin) 2001-09-12 (bug fix) script library path construction on Windows no longer uses registry, nor adds the current working directory to the path (porter) 2001-09-12 (bug fix) correct bugs in compatibility strtod() (porter) 2001-09-13 (bug fix) Tcl_UtfPrev now returns the proper location when the middle of a UTF-8 byte is passed in (hobbs) 2001-09-19 (bug fix) [format] and [scan] corrected for 64-bit machines (rmax) 2001-09-19 (new feature) --enable-64-bit support for HP-11. (hobbs) 2001-09-19 (new feature) native memory allocator now default on Windows (hobbs) 2001-09-20 (new feature) WIN64 support and extra processor definitions (hobbs, mstacy) 2001-09-26 (bug fix) corrected potential deadlock in channels that do not provide a BlockModeProc (kupries, kogorman) 2001-10-03 (new feature) WIN64 build support (hobbs) 2001-10-03 (bug fix) correction in thread finalization (rbrunner) 2001-10-04 (new feature) updated encodings with latest mappings from www.unicode.org (hobbs) 2001-10-11 (bug fix) corrected cleanup of self-referential bytecodes at interpreter deletion (sofer, rbrunner) 2001-10-16 (new feature) config support for MacOSX / Darwin (steffen) 2001-10-16 (new feature, Mac) change in binary extension format from MachO bundles to standard .dylib dynamic libraries like on other unices. *** POTENTIAL INCOMPATIBILITY *** 2001-10-18 (bug fix) corrected off-by-one-day error in clock scan with relative months and years during swing hours. (lavana) --- Released 8.3.4, October 19, 2001 --- See ChangeLog for details --- 2001-08-21 (bug fix)[219184] overagressive compilation of [catch] (sofer) 2001-08-22 (new feature)[227482] [dde request -binary] (hobbs) => dde 1.2 2001-08-30 (performance enhancement)[456668] fully qualified command names use cached Command for all namespaces, avoiding repeated lookups (sofer) 2001-08-31 (performance enhancement) bytecompiled [list] (hobbs) 2001-09-02 (bug fix)[403553] Add -Zl to VC++ compile line for tclStubLib to avoid any specific C-runtime library dependence. (gravereaux) 2001-09-05 (new feature) restored support for Borland compiler (gravereaux) 2001-09-05 (new feature)[TIP 49] Tcl_OutputBuffered API (schroedter, fellows) 2001-09-07 (new feature) restored VC++ 5.0 compatibility (gravereaux) 2001-09-10 (performance enhancement)[TIP 53,451441] [proc foo args {}] now compiles to 0 bytecodes (sofer) 2001-09-13 (new feature)[TIP 56] Tcl_EvalTokensStandard API (sofer) 2001-09-13 (new feature) Old ChangeLog entries => ChangeLog.1999 (hobbs) 2001-09-17 (new feature) compiling with TCL_COMPILE_DEBUG now required to enable all compile and execution tracing (sofer) *** POTENTIAL INCOMPATIBILITY *** 2001-09-19 (bug fix)[411825] made TclNeedSpace UTF-8 aware (fellows) 2001-09-19 (bug fix)[219166] overagressive compilation of "quoted" bodies of [for], [foreach], [if], and [while] (sofer) 2001-09-19 (performance enhancement) bytecompiled [string match] (hobbs) 2001-10-15 (new feature)[TIP 35] serial channel configuration: Win (schroedter) 2001-11-06 (bug fix)[478856] loss of fileevents due to short reads (kupries) 2001-11-06 (new feature) revitalized makefile.vc (gravereaux) 2001-11-07 (new feature) Cygwin gcc support dropped. Use mingw (dejong) *** POTENTIAL INCOMPATIBILITY *** 2001-11-07 (new feature) Support --include-dir= and --libdir= options to configure. Store in tclConfig.sh as TCL_INCLUDE_SPEC and TCL_LIB_SPEC. (dejong) *** POTENTIAL INCOMPATIBILITY *** 2001-11-08 (new feature) Enable --enable-threads on FreeBSD (dejong) 2001-11-08 (new feature) New make target 'make gdb' (dejong) 2001-11-09 (bug fix)[480176] [global] mishandled varnames matching :* (porter) 2001-11-12 (new feature)[TIP 22,33,45] new command [lset], [lindex] extended to accept multiple indices. (kenny, hobbs) 2001-11-16 (new feature) new configure option --enable-langinfo=no. By default, nl_langinfo() is used on Unix to determine system encoding. Tcl's built-in system is used only if that fails, or configured with --enable-langinfo=no. (hobbs, wagner) 2001-11-19 (new feature)[TIP 62] A Tcl_VarTraceProc can now return Tcl_Obj * or a dynamic string as well as a static string to indicate an error (fellows) 2001-11-19 (new feature)[TIP 73] Tcl_GetTime API (kenny) 2001-11-19 (bug fix)[478847] overflows in [time] of >2**31 microseconds (kenny) 2001-11-29 (performance enhancement) caching scheme added to [binary scan] (fellows) 2001-12-05 (new feature) new algorithm for [array get] adds safety when read traces modify the array. (sofer) *** POTENTIAL INCOMPATIBILITY *** 2001-12-10 (bug fix)[490514] doc fixes (porter,english) 2001-12-18 (new feature) removed unix/dltest/configure; unix/configure does all (dejong) 2001-12-19 (new feature) New make target 'make shell' (dejong) 2001-12-21 (new feature) MaxOSX / Darwin support (steffen) 2001-12-28 (new feature) new command [memory onexit] replaces [checkmem] when compiled with TCL_MEM_DEBUG. Added documentation. (porter) *** POTENTIAL INCOMPATIBILITY *** 2001-12-28 (bug fix) proper case in [auto_execok] use of $env(COMPSPEC) (hobbs) 2002-01-05 (feature rewrite) Tcl_Main() rewritten and documentation improved. Interactive operation and event loop operation (via Tcl_SetMainLoop) now interleave cleanly. Also more robust against strange happenings. (porter) 2002-01-17 (bug fix)[504642] Tcl_Obj refCounts in [gets] (griffen,kupries) 2002-01-21 (bug fix)[506297] infinite loop writing in iso2022-jap encoding (forssen,kupries) 2002-01-24 (HTTP server bug workaround)[504508] leave the default port out of the Host: header value => http 2.4.1 (hobbs) 2002-01-25 (new feature)[496733] socket options -eofchar and -translation return read-only values (dejong) 2002-01-28 (new feature) Old ChangeLog entries => ChangeLog.20900 (hobbs) 2002-01-28 (performance enhancement) bytecompiled [regexp] for trivial cases that amount to string matching. Also -nocase and --. (hobbs) 2002-02-05 (bug fix) [http::error] called when [::error] intended => http 2.4.2 (porter) 2002-02-05 (bug fix)[465765] avoid zero-byte writes to STREAMs (talcott,kupries) 2002-02-06 (performance enhancement) [regsub] special cases that map to [string map] detected. (hobbs) 2002-02-06 (bug fix)[495213] [scan] accept 0x as prefix of base 16 value (hobbs) 2002-02-10 (new feature)[TIP 32,79] Tcl_CreateObjTrace API (kenny) 2002-02-12 (new feature) partial support for DJGPP Tcl on DOS (gravereaux) 2002-02-14 (mem leak) Fixed leaking an empty Tcl_Obj when [gets $chan] errored out. (kupries, sofer) 2002-02-15 (new feature)[TIP 72] support for 64-bit integer values on 32-bit platforms and ability to work with >2GiB files. Extends many commands. See ChangeLog and TIP for details. *** POTENTIAL INCOMPATIBILITY *** 2002-02-22 (bug fix)[476537] Fix panic when loading shared library without proper use of stubs on platform without backlinking (porter) 2002-02-22 (new feature) 64-bit support for xlc compiler on AIX-4 (hobbs) 2002-02-22 (new feature)[521560] Removed limits on filename length and format [source]able through the Safe Base (hobbs) 2002-02-22 (performance enhancement) optimized bytecodes for [if], [for], [while] and constant conditions (sofer) 2002-02-22 (new feature)[TIP 76] [regsub] can now return result (fellows) 2002-02-25 (bug fix)[495207] buffer overrun when closing ] left out of argument to [subst] (sofer, english) 2002-02-25 (bug fix)[514392] [load] updated for Mac OS X 10.1 (steffen) 2002-02-26 (bug fix) [info hostname] choked on names >31 characters (hobbs) 2002-02-26 (new feature)[TIP 35] serial channel configuration: Unix (schroedter, hobbs) 2002-02-25 (bug fix)[483575] [fconfigure ... -error] now no-op on Mac (kupries) 2002-02-28 (performance enhancement)[458872] fully qualified command names use cached Command for all namespaces, avoiding repeated lookups (sofer) * (new feature)[TIP 27] completed CONST-ification of TCL APIs. Added compiler macro USE_NON_CONST to keep using those old API prototypes that present irreconcilable source incompatibilities with header files of prior Tcl releases. Others will need to be reconciled. *** POTENTIAL INCOMPATIBILITY *** 2002-03-04 (bug fix)[474358, 218099, 219314, 524674] fixed several problems related to the handling of iso2022 text and finalization of escape-based encodings. (taguchi, takahashi, hobbs) --- Released 8.4a4, March 5, 2002 --- See ChangeLog for details --- 2002-03-06 (new feature)[TIP 80] expanded [lsearch] options (wilkason, fellows) 2002-03-07 (new feature)[TIP 87] [interp recursionlimit] (trier) 2002-03-08 (platform feature) mingw 1.1 build favored (dejong) 2002-03-20 (new feature)[TIP 27] CONST-ified variable access functions (porter) 2002-03-24 (bug fix)[511666,511658,523217,530960] expanded Tcl_FSMatchInDirectory to handle assorted [glob] bugs in VFS. (darley) *** POTENTIAL INCOMPATIBILITY with prior 8.4a releases *** 2002-03-25 (bug fix)[495726] stopped tcltest disabling of auto-loading (porter) 2002-03-25 (bug fix)[495977] allow \n in test constraints (porter) 2002-03-27 (platform support)[527941,533862] VC/winhelp/W9X (spjuth, gravereaux) 2002-03-28 (bug fix)[219181] exception at level 0 issues (sofer) 2002-03-28 (bug fix)[219362] command termination; Tcl_CreateTrace (knoll,sofer) 2002-04-05 (bug fix)[536879] exceptions during variable subst (porter) 2002-04-15 (bug fix)[497446,513983] tcltest syntax errors now raised (porter) ***POTENTIAL INCOMPATIBILITY with prior tcltest 2.0.* (8.4aX)*** 2002-04-17 (bug fix)[495660] [(save|restore)state] deprecated (porter) 2002-04-17 (bug fix)[526524] escape-based encodings corrected (yamamoto, hobbs) 2002-04-18 (bug fix)[542588] [expr] error msgs improved (ehrens, sofer) 2002-04-18 (bug fix)[545325] [info level $level] now returns [namespace eval] as documented (suchenwirth,sofer) 2002-04-19 (bug fix)[544727] export [mcload]; ns context of [mcmax] (porter) => msgcat 1.2.3 2002-04-22 (performance enhancement) threaded memory allocator (AOL, hobbs) 2002-04-24 (new feature) TCLTK_NO_LIBRARY_TEXT_RESOURCES #define disables inclusion of tcl library code in resource fork on Mac. (steffen) 2002-05-21 (platform support) static libs on OSF (dejong) 2002-05-24 (bug fix)[557878] set encoding on listening socket (staplin, kupries) 2002-05-24 (new feature)[TIP 91] Tcl_Seek compatibility (fellows) 2002-05-28 (bug fix)[545579] VFS [load] left temp file (darley) 2002-05-28 (bug fix)[559376] plug timezone env leak on Windows (hobbs) 2002-05-29 (performance enhancement) [string compare] optimized (hobbs,fellows) 2002-05-31 (bug fix)[550534] plug interp leak in [pkg_mkIndex] (helmut) 2002-05-31 (dead code)[474335,555635] removed all use of matherr() (english) *** POTENTIAL INCOMPATIBILITY *** 2002-06-04 (new feature)[TIP 85,521362] custom result match in tcltest (markus, porter) => tcltest 2.1 2002-06-06 (bug fix)[524352] encoding, threading, and environment issues on MacOSX (steffen) 2002-06-06 (bug fix)[512214,558742,512214,461000] lazy initialization of tcltest constraints (porter) 2002-06-07 (bug fix)[563122,564595] EOVERFLOW definitions (fellows) 2002-06-11 (bug fix)[567386] [info locals] corrections (sofer) 2002-06-14 (new feature)[TIP 102] [trace list] renamed [trace info] (fellows) 2002-06-17 (new feature)[525522,525525] msgcat support for XPG4 locales; examination of LC_ALL, LC_MESSAGES environment variables (haible, porter) => msgcat 1.3 2002-06-17 (new feature)[565088] header files assume modern C compiler by default; older compilers may need configuration (english) *** POTENTIAL INCOMPATIBILITY *** 2002-06-17 (bug fix)[554068] [exec] argument quoting on Windows (darley) 2002-06-17 (new feature)[TIP 62,462580] command execution traces (lavana) 2002-06-19 (bug fix)[558324] regexp sets a linked variable (watson) * (performance enhancment) optimizations of bytecode execution (sofer) 2002-06-21 (new feature)[TIP 99,562970] new [file link] command (darley) 2002-06-24 (new feature)[TIP 101] new [tcltest::configure] command (porter) => tcltest 2.2 2002-06-25 (new feature) --enable-man-symlinks and --enable-man-compression options to configure (max) 2002-06-26 (bug fix)[565880] [clock format] now respects locale (max) *** POTENTIAL INCOMPATIBILITY *** 2002-07-03 (bug fix)[577015] [catch] catches even compile errors (sofer) --- Released 8.4b1, July 5, 2002 --- See ChangeLog for details --- 2002-07-08 (bug fix) restored compatibility of [viewFile] in tcltest (porter) 2002-07-11 (bug fix) [file normalize] returns long form on Win 95/98/ME (darley) 2002-07-15 (performance enhancment) variable operations rewritten to store and use cached Var pointers (sofer) 2002-07-22 (bug fix)[218000] Inf and Nan are floating-point values (fellows) 2002-07-23 (platform support)[219220] 64-bit compile on IRIX (dejong) 2002-07-25 (bug fix)[219218] return codes in background errors (english) 2002-07-28 (bug fix)[582522] alias fires exec traces (sofer) 2002-07-29 (bug fix)[578363] regexp (fellows,pvgoran) 2002-07-30 (bug fix)[584603] WriteChars infinite loop non-UTF-8 string (kupries) 2002-08-04 (new feature)[584051,580433,585105,582429][TIP 27] Tcl interfaces are now fully CONST-ified. Use the symbols USE_NON_CONST or USE_COMPAT_CONST to select interfaces with fewer changes. *** POTENTIAL INCOMPATIBILITY *** 2002-08-05 (bug fix)[589859] tcltest setup and cleanup scripts skipped when test body is skipped (porter) => tcltest 2.2 2002-08-07 (bug fix)[587488] mem leak with USE_THREAD_ALLOC (sofer,sass) 2002-08-07 (feature enhancement)[584794,584650,472576] boolean values are no longer always re-parsed from string. (sofer) Many internal bugs fixed. Considerable cleanup of the test suite. --- Released 8.4b2, August 9, 2002 --- See ChangeLog for details --- 2002-08-20 (new feature) --enable-memdebug configure option (kupries) 2002-08-23 (bug fix)[597936] mem leak with USE_THREAD_ALLOC (sofer,zoran) 2002-08-26 (bug fix)[599788] segfault in compiler (sofer,wilkason) 2002-08-28 (bug fix)[414910] avoid mem leaks accessing environment variables on Windows (welton,gravereaux) 2002-08-31 (platform support)[TIP 108] Mac OS X port (steffen,ingham) 2002-09-02 (platfrom support) 64-bit compile on HP-11 (martin) --- Released 8.4.0, September 10, 2002 --- See ChangeLog for details --- 2002-09-18 (platform support) Updated support for compiling with Cygwin and either mingw or gcc. (khan, howell, dejong) 2002-09-22 (bug fix)[612786, 611922] Corrected [puts -nonewline] within test bodies. Also corrected reporting of body return code. Updated tcltest to v2.2.1. 2002-09-24 (bug fix)[613117] More robust 64-bit wide integer value detection (fellows) 2002-09-26 (bug fix) correct overeager optimization of noop proc to handle the precompiled case. (sofer, hobbs) 2002-09-26 (bug fix)[615115] removed extraneous spaces in koi8-u.enc that confused encoding reader. 2002-09-29 (bug fix)[219355] Added proper exiting conditions using Win32 console signals. This handles the existing lack of a Ctrl+C exit to call exit handlers when built for thread support. Also, properly handles exits from other conditions such as CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals. In all cases, exit handlers will be called. (gravereaux) 2002-09-30 (bug fix) improve the checking for bad regular expressions during regexp compilation. Resultant compiles were correct, but much slower than necessary. (hobbs) 2002-10-01 (bug fix) fix precompiled locals to support 8.3 precompiled code. (hobbs) 2002-10-09 (bug fix)[620735] Added code to set an exit handler on Windows that terminates the thread that calibrates the performance counter, so that the thread won't outlive unloading the Tcl DLL. (kenny) 2002-10-09 (build support) all --enable-symbols to take the enhanced options yes|no|mem|compile|all. (hobbs) 2002-10-10 (build support) enable USE_THREAD_ALLOC (new threaded allocator) by default on Windows. (hobbs, gravereaux) 2002-10-14 (bug fix)[623269] correct possible mem leak in Tcl_PutEnv. (brouwers) 2002-10-15 (bug fix)[615043] fix in execution traces with idle tasks firing. (lavana) 2002-10-15 (platform support) Correct AIX-5 ppc and 4/5 64-bit build flags. Correct HP 11 64-bit gcc building. (martin, hobbs) 2002-10-17 (bug fix)[624755] Fixed code that check for proper # of args to [array names] (porter) 2002-10-18 (feature enhancement)[625453] Added support for broadcasting changes to the registry Environment on Windows. Updated registry package to v1.1. (hobbs) 2002-10-22 (platform support)[624509] On macosx, add embedded framework dirs to tcl_pkgPath: @executable_path/../Frameworks and @executable_path/../PrivateFrameworks (if they exist), as well as the dirs in DYLD_FRAMEWORK_PATH (if set). (steffen) --- Released 8.4.1, October 22, 2002 --- See ChangeLog for details --- 2002-10-28 (bug fix)[627660] [package unknown] chaining for platform specifics 2002-10-29 (bug fix)[627546] verbose [load] (dyld) error mesages on MacOSX 2002-11-01 (bug fix) [package provide registry] consistent versions. 2002-11-06 (bug fix)[582039] missing ar program -> configuration error 2002-11-06 (feature enhancement) added new TclInThreadExit function to test for thread exit vs whole process exit condition. The TclInExit function now correctly returns 1 during Tcl_Finalize processing. *** POTENTIAL INCOMPATIBILITY *** 2002-11-13 (bug fix)[615043] some execution traces were not firing 2002-11-18 (bug fix)[634856] multiple signs no longer accepted as valid integer [string is integer ++1] => 0 *** POTENTIAL INCOMPATIBILITY *** 2002-11-26 (bug fix)[593810,597924] clean exit of channel worker threads on Win 2002-11-28 (new feature) `make valgrind` target 2002-12-03 (bug fix)[615304] repeated load/unload of Tcl now possible 2002-12-11 (bug fix)[647307] negative return codes now propagated by procs 2002-12-11 (bug fix)[648441] syntax error in [expr 0x] now detected. 2003-01-07 (bug fix)[633204] [catch {return}] => 2 (not 0) 2003-01-09 (bug fix)[634151] [file (a|m)time $nonASCIIpath $time] now works 2003-01-16 (bug fix) dde eval with {} service name does not crash. => dde 1.2.1 2003-01-16 (bug fix)[635200,655645,615043,571385] many command trace fixes 2003-01-31 (bug fix)[675614,678415,676978] tcltest conflicts in cleanup and -outfile; also failure in space-containing path; also missing [close] => tcltest 2.2.2 2003-02-01 (bug fix)[670042] corrected [info loaded {}] for static packages in multiple interps. 2003-02-01 (bug fix)[675356] [clock clicks {}]; [clock clicks -] - syntax errs 2003-02-01 (bug fix)[656660] MT-safety for [clock format] 2003-02-03 (bug fix)[651271] command rename traces get fully-qualified names *** POTENTIAL INCOMPATIBILITY *** 2003-02-07 (performance improvement) [glob] on Windows is 2.5 times faster 2003-02-07 (feature change) lack of Cygwin support indicated by config error 2003-02-11 (bug fix)[684744] [info complete] stopped by \x00 2003-02-11 (bug fix)[685445] [glob -types l] missed broken symlinks on Unix 2003-02-11 (bug fix) [lsearch -regexp $a $a] doesn't crash 2003-02-13 (bug fix)[685926] accept non-ASCII7 for tcl_platform(user) on Win 2003-02-15 (bug fix)[673714] stop crash when Tcl_DeleteEvents deletes last 2003-02-15 (bug fix)[681841] parser missed some missing ] syntax errors 2003-02-17 (bug fix)[684756] memory leak during command rename plugged 2003-02-18 (bug fix)[689100] reduced per-thread memory overhead 2003-02-18 (platform support)[651811] use xnet library on HP 11 (64 bit). 2003-02-20 (bug fix)[Patch 689341] correct jis round-trip encoding 2003-02-20 (bug fix)[689835] stop MacOSX hang trying to read a write-only pipe 2003-02-07 (performance improvement) [tclPkgUnknown]: fewer vfs calls 2003-02-18 (platform support) cut and splice procs for file channels on Mac 2003-02-21 (bug fix)[690774] [binary scan] failed on some wide ints 2003-02-22 (bug fix)[571002] plugged data leak during thread exit 2003-02-25 (feature change) [pkg_mkIndex -load]: case-insensitive match *** POTENTIAL INCOMPATIBILITY *** 2003-02-27 (bug fix)[694232] stop [lsearch -start 0 {} x] segfault --- Released 8.4.2, March 3, 2003 --- See ChangeLog for details --- 2003-03-06 (bug fix)[699042] Correct case-insensitive unicode string comparison in Tcl_UniCharNcasecmp 2003-03-11 (bug fix) Corrected loading of tclpip8x.dll on Win9x 2003-03-12 (bug fix)[702383] Corrected parsing of interp create -- 2003-03-12 (bug fix)[685106] Correct Tcl_SubstObj handling of \x00 bytes 2003-03-14 (bug fix)[702622 699060] Correct wide int issues in 'format' 2003-03-14 (bug fix)[698146] Remove assumption that file times and longs are the same size. 2003-03-18 (bug fix)[697862] Allow Tcl to differentiate between reparse points which are symlinks and mounted drives on Windows 2003-03-19 (bug fix)[705406] Bad command count on TCL_OUT_LINE_COMPILE 2003-03-20 (bug fix)[707174] Store pointers to notifier funcs in a struct to work around some platform linker issues 2003-03-22 (bug fix)[708218] Load correct (non-)debug dll for dde or registry 2003-03-24 (bug fix)[631741 696893] Fixing ObjMakeUpvar's lookup algorithm for the created local variable 2003-04-07 (bug fix)[713562] Make sure that tclWideIntType is defined and somewhat sensible everywhere 2003-04-07 (bug fix)[711371] Corrected string limits of arguments interpolated in error messages for 'if' 2003-04-11 (bug fix)[718878] Corrected inconsistent results of [string is integer] observed on systems where sizeof(long) != sizeof(int) 2003-04-12 (bug fix) Substantial changes to the Windows clock synch phase-locked loop in a quest for improved loop stability 2003-04-16 [713562] Made changes so that the "wideInt" Tcl_ObjType is defined on all platforms, even those where TCL_WIDE_INT_IS_LONG is defined. Also made the Tcl_Value struct have a wideValue field on all platforms. Potential incompatibility for TCL_WIDE_INT_IS_LONG platforms because that struct changes size. *** POTENTIAL INCOMPATIBILITY *** 2003-04-25 (bug fix)[727271] Catch any errors returned by the Windows functions handling TLS ASAP instead of waiting to get some mysterious crash later on due to bogus pointers. 2003-04-29 (bug fix) Correct 'glob -path {[tcl]} *', where leading special character instead lists files in '/'. Bug only occurs on Windows where '\' is also a directory separator. 2003-05-09 (bug fix)[731754] Fixed memory leak in threaded allocator on Windows caused by treating cachePtr as a TLS index 2003-05-10 (bug fix)[710642] Ensure cd is thread-safe 2003-05-10 (bug fix)[718002] Correct mem leak on closing a Windows serial port 2003-05-10 (bug fix)[714106] Prevent string repeat crash when overflow sizes were given (throws error). 2003-05-13 (feature enhancement)[736774] Use new versioned bundle resource API to get tcl runtime library for TCL_VERSION on Mac OS X. 2003-05-13 (bug fix)[711232] Worked around the issue of realpath() not being thread-safe on Mac OS X by defining NO_REALPATH for threaded builds on Mac OS X. 2003-05-14 (bug fix)[557030] Correct handling of the gb2312 encoding by making it an alias of the euc-cn encoding and creating a gb2312-raw encoding for the original. Most uses of gb2312 really mean euc-cn. 2003-05-14 (bug fix)[736421] Corrected another putenv() copy behavior problem when compiling on Windows and using Microsoft's runtime. --- Released 8.4.3, May 20, 2003 --- See ChangeLog for details --- 2003-05-23 (bug fix)[726018] reverted internals change to the 'cmdName' Tcl_ObjType that broke several extensions (TclBlend, e4graph...) in the 8.4.3 release. 2003-06-10 (bug fix)[495830] stop eval of bytecode in deleted interp. 2003-06-17 (bug fix) corrections to regexp when matching emtpy string. 2003-06-25 (bug fix)[748957] -*ieee compiler flags for Tru64 builds. 2003-07-11 (bug fix) [pkg_mkIndex] indexes provided packages, not indexed ones. 2003-07-15 (feature enhancement) MacOSX build system rewrite. 2003-07-15 (bug fix)[771613] corrected segfault in [if] (buffer overflow) 2003-07-16 (bug fix)[756791] corrected assumption that Tcl_Free == free 2003-07-16 (feature enhancement) -DTCL_UTF_MAX=6 compile option forces internal UCS-4 representation of Unicode (default is recommended UCS-2). 2003-07-16 (bug fix)[767578] 64-bit corrections in thread notifier. 2003-07-16 (bug fix)[759607] Safe Base tests normalized paths. 2003-07-16 (feature enhancement)[Patch 679315] improved Cygwin path support 2003-07-18 (bug fix)[706359] corrected broken -output option of [tcltest::test] => tcltest 2.4.4 2003-07-18 (bug fix)[753315] MT-safety of VFS records. 2003-07-18 (bug fix)[759888] support for user:pass in URL by [http::geturl] => http 2.4.4 Improved documentation, new tests, and some code cleanup. [655300, 720634, 735364, 748700, 756112, 756744, 756951, 758488, 760768, 763312, 769895, 771539, 771840, 771947, 771949, 772333] --- Released 8.4.4, July 22, 2003 --- See ChangeLog for details --- 2003-07-23 (bug fix)[775976] fix registry compilation for VC7. 2003-08-05 (enhancement)[781585] Use Tcl_ResetResult in bytecodes to prevent potential costly Tcl_Obj duplication. 2003-08-06 (bug fix)[781609] prevent non-Windows platforms from trying to use the registry package inside msgcat. 2003-08-27 (bug fix)[411825] Fix TclNeedSpace to handle non-breaking space (\u00A0) and backslash escapes correctly. 2003-09-01 (bug fix)[788780] Fix thread-safety issues in filesystem records. 2003-09-19 (bug fix)[804681] Protect ::errorInfo and ::errorCode traces from corrupting stack. 2003-09-23 (bug fix)[218871] Fix handling of glob-sensitive chars in auto_load and auto_import. 2003-10-03 (bug fix)[811483] Fixed refcount management for command and execution traces. 2003-10-04 (bug fix)[789040] Fixed exec command.com error for Win9x. 2003-10-06 (bug fix)[767834, 813273] Fixed volumerelative file normalization and 'file join' inconsistencies. 2003-10-08 (bug fix)[769812] Fix Tcl_NumUtfChars string length calculation when negative parameter is given. 2003-10-22 (bug fix)[800106] Handle VFS mountpoints inside glob'd dirs. 2003-10-22 (bug fix)[599468] Watch for FD_CLOSE too on Windows when asked for writable events by the generic layer. 2003-10-23 (bug fix)[813606] Detect OS X pipes correctly. 2003-11-05 (bug fix)[832657] Allow .. in libpath initialization. 2003-11-11 (bug fix) Improve AIX-64 build configuration. 2003-11-17 (bug fix)[230589, 504785, 505048, 703709, 840258] fixes to various odd regexp "can't happen" bugs. --- Released 8.4.5, November 20, 2003 --- See ChangeLog for details --- 2003-12-02 (bug fix)[851747] object sharing fix in [binary scan] 2003-12-09 (platform support)[852369] update errno usage for recent glibc 2003-12-12 (bug fix)[858937] fix for [file normalize ~nobody] 2003-12-17 (bug fix)[839519] fixed two memory leaks (vasiljevic) 2004-01-09 (bug fix)[873311] fixed infinite loop in TclFinalizeFilesystem 2004-02-02 (bug fix)[405995] Tcl_Ungets buffer filling fix 2004-02-04 (bug fix)[833910] tcltest command line option parsing error => tcltest 2.4.5 2004-02-04 (bug fix)[833637] code error in tcltest -preservecore operation 2004-02-12 (feature enhancement) update HP-11 build libs setup 2004-02-17 (bug fix)[849514,859251] corrected [file normailze] of $link/.. 2004-02-17 (bug fix)[772288] Unix std channels forced to exist at startup. 2004-02-17 (new default) tcltest::configure -verbose {body error} 2004-02-19 (bug fix) init.tcl search path with unusual --libdir (samson) 2004-02-25 (bug fix)[554068] stopped broken [exec] quoting of { (gravereaux) 2004-02-25 (bug fix)[888777] plugged memory leak with long host names (cassoff) 2004-03-01 (bug fix)[462580] corrected level interpretation of Tcl_CreateTrace 2004-03-01 (platform support)[218561] Allow 64-bit configure on IRIX64-6.5* --- Released 8.4.6, March 1, 2004 --- See ChangeLog for details --- Changes to 8.5a1 include all changes to the 8.4 line through 8.4.6, plus the following, which focuses on the high-level feature changes in this changeset (new minor version) rather than bug fixes: * refactored IO code to split FS path code into generic/tclPathObj.c and generic/tclFileSystem.h * refactored trace code into generic/tclTrace.c * configure scripts now require autoconf 2.57 for regeneration * updated runtime library scripts to use newer Tcl code features (like replacing regsub with string map) * improve robustness of tcltest test suite across environments * changed the bytecode evaluation-stack addressing mode, from array-style to pointer-style; the catch stack and evaluation stack are now contiguous in memory * switch command is now byte-compiled * enhanced checking in 'file' command for Windows NT file permissions * [TIP #57] new 'lassign' command (adopted from TclX) * [TIP #75] switch -regexp now provides submatch info * [TIP #90] extended 'catch' and 'return' to enable creation of procs that are a true replacement for 'return' * [TIP #100] new 'unload' command (can unload DLLs loaded via 'load', requires the extension writer to support it) * [TIP #111] new 'dict' command. Several commands have been updated to handle the list form of dicts implicitly at the C level where only lists were previously accepted * [TIP #112] 'namespace ensemble' command addition allows for ensembles that build on the namespace abstraction * [TIP #118] file attributes -readonly option for unices that support chflags(), support Mac Classic attribute options on OS X, add -rsrclength for OS X, enhance file copy on OS X to copy finder attributes and resource forks transparently * [TIP #120] enable dde in safe interpreters * [TIP #130] enable unique dde server names on Windows * [TIP #135] change dde servername -exact option to -force => dde 1.3 * [TIP #121] new Tcl_SetExitProc C API to control application shutdown * [TIP #123] expr ** exponentiation operator * [TIP #124] 'clock clicks -milliseconds' now returns a wide integer and a new 'clock clicks -microseconds' returns a wide integer, representing the number of microseconds, both since the Posix epoch * [TIP #127] added 'lsearch -index' option * [TIP #136] added 'lrepeat' command * [TIP #137/151] Add -encoding option to 'source' command and main tclsh executable. *** POTENTIAL INCOMPATIBILITY *** For Tcl embedders that build on Tcl_Main() and make use of Tcl_Main's former ability to pass a leading "-encoding" option to interactive shell operations, this will now be consumed by Tcl. * [TIP #138] New TCL_HASH_KEY_SYSTEM_HASH option for Tcl hash tables * [TIP #139] documented portions of Tcl's namespace C APIs * [TIP #148] correct [list]-quoting of the '#' character *** POTENTIAL INCOMPATIBILITY *** For scripts that assume a particular (buggy) string rep for lists. * [TIP #156] add "root locale" to msgcat => msgcat 1.4 * [TIP #157] leading {expand} syntax on words to cause argument expansion. This is a safer/cleaner alternative to the use of 'eval'. --- Released 8.5a1, March 3, 2004 --- See ChangeLog for details --- 2004-03-04 (new feature) registry package is [unload]able (thoyts) => registry 1.1.4 2004-03-08 (bug fix)[910525] [glob -path] in root directory (darley) 2004-03-12 (new feature)[TIP 163] [dict merge] (english, fellows) 2004-03-18 (platform support) support for Mac Classic removed (steffen) 2004-03-28 (bug fix)[925121] corrected segfault in bc compiler (sofer) 2004-03-30 (bug fix)[495830,729692] bytecode execution checks each command/interp validity before executing. (sofer) 2004-03-31 (bug fix)[811457] support translation to "" (porter) 2004-03-31 (bug fix)[811461] ignore locales with no "language" part (porter) => msgcat 1.4.1 2004-04-01 (bug fix) make [glob -type d -dir . *] work across VFS boundary 2004-04-06 (clean up) refactored Tcl header file #include order. Might create need for changes in extensions that #include private headers. Changed source code files should work with older Tcl as well. See ChangeLog. *** POTENTIAL INCOMPATIBILITY *** 2004-04-07 (bug fix)[920667] install into any Unicode path on Win (hobbs) 2004-04-07 (platform support) properly substitute more values in Windows tclConfig.sh (hobbs) 2004-04-23 (bug fix)[930851] reset channel EOF when eofchar changes (kupries) 2004-04-28 (bug fix)[600812][TIP 184] [upvar 0 scalar array(foo)] raises error 2004-05-03 (bug fix)[947070] stack overflow prevention on Win (kenny) 2004-05-03 (bug fix)[868853] fix leak in [fconfigure $serial -xchar] (cassoff) 2004-05 (bug fix)[928353,929892,928808,947440,948177] test fixes: OSX (abner) 2004-05-05 (bug fix)[794839] socket connect error -> r/w fileevents (gravereaux) 2004-05-07 (bug fix)[949905] corrected utf-8 encoding of \u0000 on I/O (max) 2004-05-13 (new feature)[TIP 129] [binary scan tnmrRqQ] (markus, fellows) 2004-05-13 (new feature)[TIP 142] [interp limit] (fellows) 2004-05-14 (bug fix)[940278,922848] [clock] notices $::env(TZ) changes, gmt works on all platforms. (kenny, welton, glessner) 2004-05-16 (feature rewrite) bytecode execution of {expand} changed *** POTENTIAL INCOMPATIBILITY with prior 8.5a releases *** 2004-05-18 (platform support) makefile.vc now generates tclConfig.sh (thoyts) 2004-05-18 (bug fix)[500285,500389,852944] [clock %G %V] ISO8601 week numbers (kenny) 2004-05-22 (bug fix)[735335,736729] variable name resolution error (sofer) 2004-05-24 (bug fix) support for non-WIDE_INT aware math functions (hobbs) 2004-05-25 (new feature) [http::config -urlencoding] (hobbs) => http 2.5.0 2004-05-26 (bug fix)[960926] file count doubled when -singleproc 1 (porter) => tcltest 2.2.6 2004-05-26 (bug fix)[874058] improved build configuration on 64-bit systems. Corrects Tcl_StatBuf definition issues. (hobbs) 2004-05-30 (platform support) Win: allow signed short exit codes (gravereaux) 2004-06-05 (bug fix)[976722] hi-res clock fixes: Win (godfrey, suchenwirth, kenny) 2004-06-10 (bug fix)[932314] bad return values from Tcl_FSChdir() (vasiljevic) 2004-06-18 (platform support) regonize more unix locales (huang) 2004-06-18 (bug fix) prevent stack overflow from long free() chains (fellows) 2004-06-21 (platform support) exceptions w/ gcc -O3 on Win (dejong) 2004-06-23 (feature rewrite)[976496] thread local storage done with hash tables to avoid system limits (mistachkin) 2004-06-29 (bug fix)[981733] SafeBase global pollution (fellows) 2004-06-30 (new feature)[TIP 188] [string is wideinteger] (kenny) 2004-07-02 (new feature)[TIP 202] pipe redirection 2>@1 (hobbs) 2004-07-03 (bug fix)[908375] round() wide integer support (lavana, sofer) 2004-07-07 (bug fix)[458361] shimmer of single-word scripts suppressed (sofer) 2004-07-15 (bug fix)[770053] crash in thread finalize of notifier (vasiljevic) 2004-07-15 (bug fix)[990453] plug mutex leaks on reinit (mistachkin, vasiljevic) 2004-07-16 (bug fix)[990500] clean exit of notifier thread (mistachkin, kupries) 2004-07-19 (bug fix)[987967] improved self-init of mutexes on Win (vasiljevic) 2004-07-20 (bug fix) pure Darwin/CFLite support (steffen) 2004-07-20 (bug fix)[736426] plug leaky allocator reinit (mistachkin, kenny) 2004-07-30 (bug fix)[999084] no deadlock in re-entrant Tcl_Finalize (porter) 2004-08-02 (new feature)[TIP 207] [interp invokehidden -namespace] (porter) 2004-08-10 (bug fix) thread IDs on 64-bit systems (ratcliff,vasiljevic) 2004-08-13 (bug fix) avoid malicious code acceptance by [mclocale] (porter) => msgcat 1.3.3 2004-08-16 (bug fix)[1008314] Tcl_SetVar TCL_LIST_ELEMENT (sofer,porter) 2004-08-18 (new feature)[TIP 173,209] complete [clock] rewrite (kenny) *** POTENTIAL INCOMPATIBILITY *** 2004-08-18 (new feature)[TIP 189] package loading for Tcl Modules (kupries) 2004-08-19 (bug fix)[1011860] [scan %ld] fix on LP64 (fellows,porter) 2004-08-23 (bug fix)[695441] extend [tcl_findLibrary] search path to include $::auto_path and [pkgconfig get scriptdir,runtime] (porter) 2004-08-27 (platform support) TCL_MODULE_PATH values for Mac OSX (steffen) 2004-08-27 (bug fix)[1017022] recognize imported ensembles (fellows) 2004-08-30 (bug fix) [string map $x $x] crash (fellows) 2004-09-01 (bug fix)[1020445] WIN64 support (hobbs) 2004-09-03 (bug fix)[1020538] crash in [file copy] (violi,fellows) 2004-09-07 (bug fix)[1016167] [after] overwrites its imports (kenny) 2004-09-08 (bug fix) fixed [clock format 0 -format %k] (kenny) 2004-09-09 (bug fix)[560297] fixed broken [namespace forget] logic (porter) 2004-09-09 (bug fix)[1017299] fixed [namespace import] cycle prevention (porter) 2004-09-10 (performance) $x[set x {}] is now fast [K $x [set x {}]] (sofer) 2004-09-10 (bug fix)[868489] better control over int <-> wideInt (fellows,kenny) 2004-09-10 (bug fix)[1025359] POSIX errorCode from wide seeks (kupries,fellows) 2004-09-10 (bug fix)[707104,1026493] fix [rename] of [interp alias] (porter) 2004-09-18 (bug fix)[868467] fix [expr 5>>32] => 0, not 5 (hintermayer,fellows) 2004-09-21 (bug fix) consistent errorinfo from [namespace eval x error foo bar] and [namespace eval c {error foo bar}] (porter) 2004-09-22 (feature change) syntax errors not reported at compile time; deferred to runtime. Support [return -errorline]. (porter) 2004-09-23 (bug fix)[1016726] fix `make clean` in static config (leitgeb,dejong) 2004-09-22 (feature change) report all compile errors at runtime (porter) 2004-09-29 (bug fix)[1036649] syntax error in [subst] => buffer overflow (sofer) 2004-09-30 (bug fix)[1038021] save/restore error state: var traces (porter) 2004-10-01 (performance) stackframe level values in internal reps (fellows) 2004-10-01 (feature change)[1037235] auto-create [dict] key paths (fellows) 2004-10-04 (bug fix)[884830] eq and ne parse in expr (fellows) 2004-10-05 (reform) errorInfo, errorCode management (porter) *** POTENTIAL INCOMPATIBILITY for traces on those vars *** 2004-10-06 (feature change)[1041072] re-bless and enhance Tcl_AppendResult (dkf) 2004-10-06 (reform) more robust interp result appends (porter) => dde 1.3.1 => registry 1.1.5 2004-10-06 (reform) re-write of [glob] guts (fellows) 2004-10-07 (reform)[925620] improved platform split of VFS code (darley) 2004-10-08 (new feature)[TIP 201] "in" and "ni" expr operators (fellows) 2004-10-08 (new feature)[TIP 212] [dict update]; [dict with] (fellows) 2004-10-08 (bug fix)[954263] case insensitive [file exec] for Win (hobbs,darley) 2004-10-14 (performance) [info commands/globals/procs/vars $pattern] faster when $pattern is trivial (fellows) 2004-10-14 (new feature)[TIP 217] [lsort -indices] (salsman,fellows) 2004-10-24 (reform) replaced bit flag values with macros for Var handling *** POTENTIAL INCOMPATIBILITY for accesses to Var internals *** 2004-10-26 (new feature)[1054370] install msgcat, http, tcltest as TM's (porter) 2004-10-26 (bug fix)[767676] negative PIDs with pipes (giese,gravereaux) 2004-10-27 (bug fix)[731778] stop critical section leaks (mistachkin,gravereaux) 2004-10-27 (bug fix)[926088] -load option to find tested packages (gravereaux) 2004-10-28 (bug fix)[1030548] restore the --enable-symbols --enable-threads build on Win (mistachkin,kenny,kupries) 2004-10-29 (bug fix)[1055673] fix command line syntax error message (porter) => tcltest 2.2.7 2004-10-30 (bug fix)[926106] fix [file mtime] DST anomaly (kenny) 2004-10-31 (bug fix)[1057461] fix [info globals ::varName] (fellows) 2004-11-02 (bug fix)[761471] fix [expr {NaN == NaN}] (sofer) 2004-11-02 (bug fix)[1017151] misleading errorInfo after tests (seeger,porter) 2004-11-03 (bug fix)[527164] preserve errorinfo from var traces (porter) 2004-11-08 (bug fix){947693] Made -blocking option of channel during [close] consistent on Windows with Unix (gravereaux) *** POTENTIAL INCOMPATIBILITY *** 2004-11-11 (bug fix)[1034337] recursive file delete, MacOSX (steffen) 2004-11-12 (new feature)[TIP 221] [interp bgerror] (porter) 2004-11-12 (new feature)[TIP 226] Tcl_(Save|Restore|Discard)InterpState (porter) 2004-11-12 (new feature)[TIP 227] Tcl_(Get|Set)ReturnOptions (porter) 2004-11-12 (bug fix)[1004065] stop crash when TCL_UTF_MAX==6 (hobbs,porter) 2004-11-15 (bug fix)[10653678] [trace variable],[trace remove] interop (porter) 2004-11-16 (bug fix)[1067709] crash in [fconfigure -ttycontrol] (hobbs) 2004-11-18 (new feature) configure options --enable-man-suffix (max) 2004-11-22 (bug fix)[1030465] Improve HAVE_TYPE_OFF64_T check (dejong) 2004-11-22 (bug fix)[1043129] Fixed the treatment of backslashes in file join on Windows (darley) 2004-11-22 (bug fix)[976438] Move init.tcl search path construction to tclInit (porter) 2004-11-24 (bug fix)[1072654] Fixed segfault in info vars trivial matching branch (new in 8.4.8) (porter) 2004-11-24 (bug fix)[1001325, 1071701] Fixed readdir_r detection and usage (dejong, kenny, porter) 2004-11-24 (bug fix)[1071807] Fixed all uses of 'select' to use standard macros rather than older bit-whacking style (kenny) 2004-11-26 (bug fix)[1073524] Simplify the code to check for correctness of strstr, strtoul and strtod on unix (fellows) 2004-11-26 (bug fix)[1072136] Remove file normalize on tcl_findLibrary search path uniqification added in 8.4.8 (porter) 2004-11-30 (bug fix)[976520] Rework startup/initialization of the Tcl library, encoding search initialization, and Tcl_FindExecutable structure. [tclInit] no longer driven by the value of $::tcl_libPath (TCLLIBPATH). (porter) *** POTENTIAL INCOMPATIBILITY : makes encoding names case sensitive on Windows, where they have been case insensitive *** 2004-12-02 (bug fix)[1074671] Ensure tilde paths are not returned specially by 'glob' (darley) Doc improvements [759545,926590,935853,1017072,1018486,1022527,1027849, 1032243,1047928,1048005,1058446,1062647,1065732,1073334,etc.] Test suite expansion [1036649,1001997,etc.] --- Released 8.5a2, December 7, 2004 --- See ChangeLog for details --- 2004-12-13 (bug fix)[1083082] encoding memory leaks (ade,porter) 2004-12-13 (bug fix)[1082349] restored C++ extension support (porter) 2004-12-14 (bug fix)[1081541] workaround automake-ism "$U" (porter) 2004-12-15 (new feature) CallFrames on execution, not C, stack (sofer) 2004-12-16 (bug fix)[1085023] [interp limit] support in [vwait], etc. (fellows) 2004-12-29 (bug fix)[1090413] make [clock scan 0030] work (morian,kenny) 2004-12-29 (bug fix)[1092789] make [clock scan 10000] work (porter,kenny) 2004-12-29 (platform support)[1092952,1091967] MSVC7, gcc OPT compiles (hobbs) 2005-01-06 (performance)[1020491] [http::mapReply] (fellows) => http 2.5.1 2005-01-09 (bug fix)[1095909] stopped use of readdir_r (english) 2005-01-10 (enhancement)[1081595] stopped use of TCL_DBGX (english) 2005-01-17 (bug fix)[1100542] [glob] of Windows shares (schar,darley) 2005-01-19 (new feature)[TIP 235] C API for ensembles (fellows) 2005-01-21 (new feature)[TIP 233] virtual time (kupries) 2005-01-25 (bug fix)[1101670] [auto_reset] update for [namespace] (porter) ***POTENTIAL INCOMPATIBILITY*** May cause re-[source]-ing of files that have not anticipated that before. 2005-01-27 (new feature)[TIP 218] Tcl_Channel API update for threads (kupries) 2005-01-27 (bug fix)[1109484] Tcl_Expr* updates for Tcl_WideInt (hobbs) 2005-01-28 (platform support)[1021871] Solaris gcc 64-bit support (hobbs) 2005-02-10 (bug fix)[1119369] Tcl_EvalObjEx: avoid shimmer loss of List intrep (sofer,macdonald) 2005-02-11 (platform support) correct gcc builds for AIX-4+, HP-UX-11 (hobbs) 2005-02-24 (bug fix)[1119798] prevent [source $directory] (porter,mpettigr) => tcltest 2.2.8 2005-03-10 (bug fix)[1153871] bad ClientData cast (porter,victorovich) 2005-03-15 (platform support) OpenBSD ports patch (thoyts) 2005-03-18 (bug fix)[1115904] restore recursion limit in direct eval (porter) 2005-03-24 (bug fix) stop conflict between Tcltest and Thread packages (porter) 2005-03-29 (platform support) allow msys builds without cygwin (hobbs) 2005-04-01 (internal change)[1158008] internal rep of "list" Tcl_Obj's now uses a refcounted struct (sofer) ***POTENTIAL INCOMPATIBILITY*** For any code that goes poking into the internals of "list" Tcl_Obj's 2005-04-05 (performance)[1174551] Tcl_DecrRefCount of Tcl_Obj "chains" (sofer) 2005-04-08 (performance)[1077262] better Tcl_Encoding cache lifetimes (porter) 2005-04-10 (bug fix)[1180368] [interp invokehidden] mem leak (kenny,porter) 2005-04-12 (performance)[1177363] startup encoding file scan (porter) 2005-04-12 (performance)[1182459] [clock format] (kenny) 2005-04-13 (bug fix) min buffer size dropped from 10 to 1 byte (gravereaux) 2005-04-16 (bug fix)[1178445] fix memory waste at thread exit (vasiljevic) 2004-04-16 (bug fix)[1084111] [array names] memory leak (ade,sofer) 2005-04-19 (bug fix)[1185933] [clock] init clobbered global vars (ring,kenny) 2005-04-19 (new feature) [::tcl::unsupported::EncodingDirs] - unsupported command to set search path for encoding files (porter) 2005-04-20 (bug fix)[1090869] Tcl_GetInt accept 0x80000000, 64-bit (porter,singh) 2005-04-22 (bug fix)[1187123] [string is boolean] respect EIAS (porter) 2005-04-25 (enhancement) update to tzdata2005i (kenny) 2005-04-25 (platform support) builds on Mac OS X 10.1 (steffen) 2005-04-27 (new feature)[TIP 183] [open $f {... BINARY ...}] (porter) 2005-04-29 (new feature)[TIP 176] simple index arithmetic (porter) 2005-05-06 (platform support) x86_64 Solarix cc and Solaris 10 builds (hobbs) 2005-05-10 (bug fix)[1198892] [expr {i**0}] error (kaitschu,markus) 2005-05-10 (new feature)[TIP 132] floating-point conversion to string (kenny) ***POTENTIAL INCOMPATIBILITY*** For scripts that rely on (tcl_precision==12) number formatting 2005-05-10 (new feature)[TIP 232] math functions as commands (kenny) ***POTENTIAL INCOMPATIBILITY*** Tcl_GetMathFuncInfo functioning is reduced; routine is now deprecated 2005-05-13 (feature removed) TCL_NO_MATH compiler directive (porter) 2005-05-14 (platform support) Mac OSX: configurable CoreFoundation API (steffen) 2005-05-14 (platform support) Mac OSX: use realpath when threadsafe (steffen) 2005-05-17 (feature removed) Tcl_ObjType's "list", "procbody", "index", "ensembleCommand", "localVarName", "levelReference, "boolean" are no longer registered (porter) ***POTENTIAL INCOMPATIBILITY*** For any callers of Tcl_GetObjType on those strings 2005-05-20 (bug fix)[1201589] boolean literal prefix in expressions (porter) 2005-05-24 (platform support) Darwin build support merged into unix (steffen) 2005-05-24 (new feature)[1202209] Mac OSX: support [load] of .bundle binaries Can support [load] from memory as well (steffen) 2005-05-24 (new feature)[1202178] [time] returns non-integer result (steffen) 2005-05-25 (new feature)[TIP 182] [expr {bool(...)}] (mistachkin,porter) 2005-05-30 (new feature)[TIP 229] [namespace path] (fellows) 2005-05-31 (bug fix)[1082283] Unix: notifier thread now joinable (vasiljevic) 2005-06-01 (new feature)[TIP 241] -nocase: lsort, lsearch, switch (mistachkin) 2005-06-01 (bug fix)[1209759] "return TCL_RETURN;" could cause panic (porter) Documentation improvements [1075433,1085127,1117017,1124160,1149605,etc.] --- Released 8.5a3, June 4, 2005 --- See ChangeLog for details --- 2005-06-06 (bug fix)[1213678] Windows/gcc: crash in stack.test (kenny) 2005-06-07 (new feature)[TIP 208] [chan] and [chan truncate] (fellows) 2005-06-07 (revert) Restored registration of "procbody" Tcl_ObjType (porter) Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17. 2005-06-13 (bug fix)[1217375,1219176] [file mkdir] race (diekhans,darley) 2005-06-14 (bug fix)[1220058] [namespace delete] crash (duquette,fellows) 2005-06-17 (bug fix)[1221395] Tcl_LimitSetTime able to break [vwait] (fellows) 2005-06-18 (bug fix)[1154163] [format %h] on 64-bit OS's (kraft,fellows) 2005-06-21 (bug fix)[1201035,1224585] execution trace crashes (porter) 2005-06-21 (bug fix)[1194458] Windows: [file split] (kenny,porter) 2005-06-22 (bug fix)[1225727] Windows: pipe finalization crash (kenny) 2005-06-22 (bug fix)[1225571] Windows: [file pathtype] buffer overflow (thoyts) 2005-06-22 (bug fix)[1225044] Windows: UMR in pipe close (kenny) 2005-06-23 (bug fix)[1225957] Windows/gcc: crashes in assembler code (kenny) 2005-06-24 (bug fix) make Tcl_Preserve safe in Tk exit handlers (kenny) 2005-07-01 (bug fix)[1222872] notifier spurious wake-up protection (vasiljevic) 2005-07-05 (bug fix)[1230597] allow idempotent [namespace import] (porter) 2005-07-15 (bug fix)[1237907] localtime() => NULL => crash (kenny) 2005-07-21 (dropped support) IRIX 4, RISCos, Ultrix, and ancient BSD (kenny) ***POTENTIAL INCOMPATIBILITY*** 2005-07-22 (enhancement)[1237755] 8.4 features in script library (fradin,porter) 2005-07-24 (new feature) configure macros SC_PROG_TCLSH, SC_BUILD_TCLSH (dejong) 2005-07-26 (bug fix)[1047286] cmd delete traces during namespace delete (porter) 2005-07-26 (new unix feature)[1231015] ${prefix}/share on ::tcl_pkgPath (dejong) ***POTENTIAL INCOMPATIBILITY*** 2005-07-27 (bug fix)[1214462] [unknown] can return exceptions (porter) 2005-07-27 (new feature) value of ::tcl_precision now kept per-thread (porter) ***POTENTIAL INCOMPATIBILITY*** 2005-07-28 (unix bug fix)[1245953] O_APPEND for >> redirection (fellows) 2005-07-29 (bug fix)[1247135] [info globals] return only existing vars (fellows) 2005-07-30 (new Darwin feature) TCL_LOAD_FROM_MEMORY configuration (steffen) 2005-08-05 (bug fix)[1241572] correct [expr abs($LONG_MIN)] (kenny) 2005-08-05 (Solaris bug fix)[1252475] recognize cp1251 encoding (wagner,fellows) 2005-08-11 (config options) eliminated USE_THREAD_STORAGE option (kenny) 2005-08-23 (toolchain support) autoconf-2.59 now required (dejong) 2005-08-24 (new feature)[TIP 219] reflected channels ([chan create]) (kupries) 2005-08-25 (bug fix)[1267380] [lrepeat] buffer overflow prevention (fellows) 2005-08-26 (bug fix) fix [namespace ensemble] crashes in Snit (fellows) 2005-08-29 (bug fix)[1275043] restore round() away from zero (kenny) 2005-08-29 (bug fix)[1189657] correct [tcl::tm::roots] (porter) 2005-09-07 (bug fix)[1283976] invalid [format %c -1] result (porter) 2005-09-08 (new feature)[1242844][TIP 254] new types for Tcl_LinkVar (fellows) 2005-09-07 (toolchain support) deprecate TCL_VARARGS*; stdarg.h assumed (porter) ***POTENTIAL INCOMPATIBILITY*** 2005-09-15 (RHEL bug fix)[1287638] support open >2GB files RHEL 3 (palan) 2005-09-08 (new feature)[TIP 255] [expr min()] and [expr max()] (hobbs) 2005-09-30 (bug fix)[1306162] $argv encoding and list formatting (porter) 2005-10-04 (bug fix)[1067708] [fconfigure -ttycontrol] leak (hobbs) 2005-10-04 (bug fix)[1182373] [http::mapReply] update to RFC 3986 (aho,hobbs) => http 2.5.2 2005-10-04 (HPUX bug fix)[1204237] shl_load() and DYNAMIC_PATH (collins,hobbs) 2005-10-05 (bug fix)[979640] buffer overrun mixing putenv(), ::env (bold,hobbs) 2005-10-08 (new feature)[TIP 237] unlimited range for integers (kenny,porter) ***POTENTIAL INCOMPATIBILITY*** for any code that relies on implicit truncation of integer calculations to the range of a C long 2005-10-14 (platform support)[1256937] MSVC++ static builds (thoyts) 2005-10-19 (bug fix)[1331475] [dict append] crash (bills,sofer) 2005-10-20 (bug fix)[1333036] [lset] shared sublist handling (sofer) 2005-10-23 (bug fix)[1335006] memleack in [glob] (melbardis,darley) 2005-10-23 (bug fix)[1325803] Win: [file stat] on links (bonilla,darley) 2005-11-01 (bug fix)[1337941] Tcl_TraceCommand() -> crash (devilliers,porter) 2005-11-02 (platform support)[1256937] MSVC 8 support (thoyts) 2005-11-03 (new Win NT/XP feature) Unicode console support (kovalenko,thoyts) 2005-11-04 (bug fix)[1337229,1338280] [namespace delete] / unset traces (sofer) 2005-11-04 (enhancement) Korean timezone abbreviations (kenny) 2005-11-04 (platform support)[1163896] LynxOS [load] (heidibr) 2005-11-04 (bug fix)[1334947] value refcount error in var setting (sofer) 2005-11-04 (Win enhancement)[1267871] extended exit codes (newman,thoyts) 2005-11-07 (bug fix)[1348775] unset trace memory leak (sofer) 2005-11-08 (bug fix)[1162286] [package require] checks that the script registered by [package ifneeded] provides the version it claims (lavana,porter) *** POTENTIAL INCOMPATIBILITY *** 2005-11-09 (bug fix)[1350293,1350291] [after $negative $script] fixed (kenny) 2005-11-12 (bug fix)[1352734,1354540,1355942,1355342] [namespace delete] issues with [namespace path] and command delete traces (sofer,fellows) 2005-11-18 (bug fix)[1358369] URL parsing standards compliance (wu,fellows) => http 2.5.2 2005-11-18 (revert) Restored registration of "list" Tcl_ObjType (porter) Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17. 2005-11-18 (bug fix)[1359094] Tclkit crash (thoyts, kupries) 2005-11-20 (bug fix)[1091431] Tcl_InitStubs failure crashes wish (english) 2005-11-27 (platform support) Darwin 64bit, Tiger copyfile(), and Max OSX universal binaries support (steffen) 2005-11-28 (bug fix) [clock] DST transition error (mackerras,kenny) 2005-11-29 (bug fix)[1366683] [lsearch -regexp] backrefs (cleverly,fellows) 2005-11-30 (performance) recoded portions of [clock] in C (kenny) 2005-11-30 (enhancement) improved bytecode compiling of [switch] (fellows) *** POTENTIAL INCOMPATIBILITY *** For loading bytecode compiled and saved by earlier 8.5alpha releases 2005-12-05 (Darwin bug fix)[1034337] NFS recursive file delete (steffen) 2005-12-08 (platform support) Win x64 build (hobbs) 2005-12-09 (bug fix)[1374778] [lsearch -start $pastEnd] => -1 (fellows) 2005-12-12 (bug fix)[1377619] configure syntax error exposed in bash-3.1 (hobbs) 2005-12-13 (bug fix)[1379349] [dict for] CoW error (ring,hippler,fellows) 2005-12-18 (bug fix)[1382528] [dict for {k v} {} {}] crash (kovalenko,fellows) 2005-12-27 clock tzdata updated to Olson's tzdata2005r (kenny) 2005-12-27 libtommath updated to release 0.37 (kenny) 2006-01-09 (bug fix)[1480572] [info level $l] => "namespace inscope" (porter) 2006-01-11 (compat support)[1397843] when ::errorInfo is traced, fall back to old pattern of stack trace construction (porter). Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2004-10-05. 2006-01-12 (bug fix)[1366227] Win: [file stat] sharing violation (darley) 2006-01-23 (bug fix)[1410553] Tcl_GetRange Unicode confusion (twylite,spjuth) 2006-01-23 (bug fix)[1412695] args handling in precompiled procs (traum,sofer) 2006-02-01 (new feature)[1275435][TIP 250] [namespace upvar] (sofer) 2006-02-01 (new feature)[958222][TIP 181] [namespace unknown] (madden) 2006-02-01 (new feature)[944803][TIP 194] [apply] (mistachkin) 2006-02-08 (new feature)[1413934][TIP 258] [encoding dirs], etc. (porter) 2006-02-09 (new feature)[1413115][TIP 215] auto-init [incr] (leitgeb) 2006-03-02 (bug fix)[1379287] norm of paths with /../ back to root (porter) 2006-03-03 (compat support) Restored registration of a "boolean" Tcl_ObjType (porter) Reduces the ***POTENTIAL INCOMPATIBILITY*** from 2005-05-17. 2006-03-06 (bug fix)[1439836,1444291] fix TCL_EVAL_{GLOBAL,INVOKE} handling when auto-loading or exec traces are present (porter) 2006-03-10 (bug fix)[1437595] Win socket finalize with threads (vasiljevic) 2006-03-13 (revert 2005-07-26 change) ${prefix}/share on ::tcl_pkgPath (porter) 2006-03-14 (bug fix)[1448251] TCLX.y_TM_PATH handling (noble, kupries) 2006-03-14 (bug fix)[768659] pipeline error when last command missing (kupries) 2006-03-18 (bug fix)[1193497] Win porting of [file writable] (darley,vogel) 2006-03-18 (bug fix)[1084705] [glob -nocomplain] silence empty result only, no other errors (darley) ***POTENTIAL INCOMPATIBILITY*** 2006-03-21 (platform enhancement)[823329] HFS globbing support (steffen) 2006-03-23 (platform support) updated tcl.spec file (max) 2006-03-28 (bug fix)[1064247] BSD: path normalization with realpath() (steffen) 2006-04-03 (bug fix)[1462248] crash reading utf-8 chars spanning multiple buffers at end of file (kraft,kupries) 2006-04-05 (bug fix)[1464039] Tcl_GetIndexFromObj: empty key (fellows) 2006-04-05 (bug fix) overdue dde, registry patchelevel increments (porter) => dde 1.3.2 => registry 1.2 2006-04-06 (bug fix)[1457515] TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING removed (steffen) 2006-04-11 (bug fix)[1458266] enter/enterstep trace interference (leunissen) 2006-04-12 (feature change)[1376892] revised definition of [:print:] (fellows) (platform support) Use of _ANSI_ARGS_ purged. ANSI compiler required (fellows) Documentation improvements [1211078,1190891,1292427,1277503,1104682,1359183, 1415725,666770] --- Released 8.5a4, April 27, 2006 --- See ChangeLog for details --- 2006-05-04 (bug fix)[1480509] srand() accept wide input (porter,afredd) 2006-05-05 (bug fix)[1481986] interactive Tcl_Main blocks main loop (porter,lin) 2006-05-13 (bug fix)[1482718] proc re-compile: preserve the previous bytecode while references still on the stack (porter,ryazanov) 2006-05-27 (bug fix)[923072] Darwin: made unthreaded CoreFoundation notifier naked-fork safe on Tiger (steffen) 2006-06-20 (internal change) Dropped the internal routines used to hook into filesystem operations back in the pre-Tcl_Filesystem days. (porter) ***POTENTIAL INCOMPATIBILITY*** For extensions and programs that have never migrated to the supported Tcl 8.4 interface for virtual filesystems 2006-07-05 (enhancement) Expression parser rewrite avoids stack overflow, reduces from O(N^2) to O(N) complexity, and greatly improves syntas error messages (porter) ***POTENTIAL INCOMPATIBILITY*** For any code relying on exact error messages. 2006-07-20 (platform support) Mac OS X weak linking (steffen) 2006-07-20 (bug fix) Darwin: execve() works iff event loop not yet run (steffen) 2006-07-24 (bug fix)[1518166] Uninitialized Tcl_DString (afredd) 2006-07-30 (bug fix)[1426279,1505383,1494664,1531530] [clock] fixes (kenny) 2006-08-09 (bug fix)[1531184] [dict for {file stat} x {}] crash (fellows) 2006-08-10 (bug fix)[1538262,1530474] code cleanup; optimizations (afredd) 2006-08-18 (bug fix) intermittent failures in TclUnixWaitForFile() (steffen) 2006-08-18 (platform support) Darwin x86_64 (steffen) 2006-08-21 (bug fix)[1457797] Darwin 64-bit notifier hang (steffen) 2006-08-21 (bug fix) Darwin: recursively called event loop (steffen) 2006-08-21 (enhancement) Darwin: nanosec resolution clicks and [time] (steffen) 2006-08-28 (bug fix)[1547681] TclFormatObj count arguments (mistachkin,porter) 2006-08-28 (bug fix) stack.test failure on FreeBSD (mistachkin) 2006-08-30 (bug fix)[1548263] filesystem segfaults (hobbs,mccormack) 2006-08-31 (bug fix)[1541274] [expr {sqrt(-1)}] => -NaN (suchenwirth,porter) 2006-09-06 (bug fix)[999544] use of MT-safe system calls (vasiljevic) 2006-09-10 (platform support) Darwin: msgcat use CFLocale (steffen) => msgcat 1.4.2 2006-09-10 (new feature) tcltest option: -verbose line (steffen) => tcltest 2.3a1 2006-09-19 (bug fix)[1555271,1561260] Several ** operator bugs (porter) 2006-09-22 (bug fix)[1562528] NULL terminates variadic calls (fellows,ryazanov) 2006-09-22 (new feature)[1520767][TIP 268] [package] alpha/beta version; [package require] ranges, [package prefer] selection mode (kupries) 2006-09-26 (platform support) MSVC8 AMD64 support (thoyts) 2006-09-27 (bug fix)[1567222] bignum << errors (porter) 2006-09-30 (enhancement)[1190441] quiet no-op [history] (sofer) 2006-10-04 clock tzdata updated to Olson's tzdata2006m (kenny) 2006-10-05 (bug fix)[1570718] make [lappend $nonList] complain (sofer,virden) 2006-10-05 (bug fix)[1122671] alignment fixes in unicode encoding routines (hobbs,staplin) 2006-10-05 (enhancement) Allow "_" in Tcl Module filenames (kupries) 2006-10-05 (new feature) [set ::http::strict 0] (default value is 1) to disable URL validity checking against RFC 2986 (hobbs) => http 2.5.3 2006-10-06 (new feature)[1565751][TIP 275] [binary scan] unsigned (thoyts) 2006-10-10 (bug fix)[1566526] crash cleaning up [namespace path] data (porter) 2006-10-12 (bug fix)[1576006] better error messages from [interp alias] (sofer) 2006-10-13 (platform support) get stack size on Darwin (steffen) --- Released 8.5a5, October 20, 2006 --- See ChangeLog for details --- 2006-10-20 (configure change) Added autodetection for OS-supplied timezone files (max) 2006-10-23 (enhancement)[1577278] Ensure the Tcl call stack always has a CallFrame, even at level 0 (sofer) *** POTENTIAL INCOMPATIBILITY for users of tclInt.h *** 2006-10-23 (enhancement)[1577492] Tcl_PushCallFrame and [info level] enhanced for ensemble rewrites (sofer) *** POTENTIAL INCOMPATIBILITY for [info level 0] on interp alias *** 2006-11-02 (feature change)[TIP 293] Replace {expand} with {*} (hobbs) *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only *** 2006-11-04 (new feature)[TIP 274] Exponentiation operator is right associative (porter) 2006-11-09 (new feature)[TIP 272] Added [lreverse] and [string reverse] commands (fellows) 2006-11-14 (new feature)[TIP 261] [namespace import] returns list of imported commands (porter) 2006-11-15 (new feature)[TIP 270] New C routines Tcl_ObjPrintf, Tcl_AppendObjToErrorInfo, Tcl_Format, Tcl_AppendLimitedToObj, Tcl_AppendFormatToObj, Tcl_AppendPrintfToObj (porter) 2006-11-22 (feature change) Moved TCL_REG_BOSONLY from tcl.h to tclInt (porter) 2006-11-22 (new feature)[TIP 269] Added [string is list] classification command (mistackin, fellows) 2006-11-25 (new feature)[TIP 174] Added commands corresponding to most expr operators in ::tcl::mathop (fellows) 2006-11-26 (platform support)[1230558] --enable-64bit on more systems (steffen) 2006-11-27 (bug fix)[1602208] Fix 64-bit handling of select() on unix where fd was greater than 32 (fontaine, kenny) 2006-11-28 (new feature)[TIP 280] Added [info frame] command for more Tcl-level debugging information (kupries) 2006-12-01 (feature change)[TIP 298] Change Tcl_GetBignumAndClearObj to Tcl_TakeBignumFromObj (porter) 2006-12-01 (new feature)[TIP 287] Added [chan pending] subcommand (cleverly) 2006-12-01 (new feature)[TIP 299] Added isqrt() expr operator (kenny) 2006-12-04 (new feature)[TIP 267] Added -ignorestderr option to exec (fellows) 2006-12-05 (new feature)[TIP 291] ::tcl_platform(pointerSize) key (kupries) 2007-01-11 (configure change) Remove "-Wconversion" from deflt CFLAGS (english) 2007-01-25 (configure change) Ensure CPPFLAGS env var is used when set (steffen) 2007-02-19 (configure change) Use SHLIB_SUFFIX=".so" on HP-UX IA64 (was ".sl") (hobbs) 2007-02-20 (bug fix)[1479814] Handle Windows NT \\?\... extended paths (thoyts) 2007-03-01 (bug fix)[1671138] Fix infinite loop in compiled foreach with an empty list (fellows) 2007-03-07 (enhancement) Improved Windows time zone tables to handle new US DST rules (kenny) 2007-03-09 (enhancement) Improved Y2038 compliance of zoneinfo files (kenny) 2007-04-02 (enhancement) Added bytecode compilation for global, variable, upvar and namespace upvar (sofer) 2007-04-20 (bug fix) Improve clock localization for Japanese locale (kenny) 2007-04-20 (enhancement) Document Tcl_SetNotifier & Tcl_ServiceModeHook (kenny) 2007-04-23 (bug fix) fts_open() crash on 64bit Darwin 8 or earlier (steffen) --- Released 8.5a6, April 25, 2007 --- See ChangeLog for details --- 2007-04-30 (bug fix)[1705778] many valgrind-detected leaks corrected 2007-05-01 (bug fix)[1710709] leak in [string map] (porter) 2007-05-02 (bug fix)[1710707] leaks in filesystem paths (mistachkin,kenny) 2007-05-18 (feature change) {expand} syntax support removed. (porter) *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only *** 2007-05-29 (bug fix)[1712723] Joinable thread death on 64-bit (virden,hobbs) 2007-05-30 (feature change)[1725186] When expanded literals are parsed, (example: {*}{1 2 3}), TCL_TOKEN_EXPAND_WORD token is no longer returned. Tokens reflecting the expansion are returned instead. (porter) *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only *** 2007-06-06 (platform support) Darwin: add plist to tclsh (steffen) 2007-06-12 (enhancement) [info] is now a [namespace ensemble] (fellows) 2007-06-20 (enhancement) better `make html` results (hobbs) 2007-06-21 (feature change)[1740962] leave traces created during execution of traced command do not fire (sofer) *** POTENTIAL INCOMPATIBILITY *** 2007-06-23 (bug fix) Darwin: prevent post-fork() abort() (steffen) 2007-06-27 (bug fix)[1743941] Infinite loop in Tcl_CreateTrace traces (porter) 2007-06-29 (enhancement) Tcl_Alloc alignment on Darwin (steffen) 2007-06-30 (bug fix)[1726873] crash in thread sync objects (vasiljevic,twylite) 2007-06-30 (bug fix)[1717186] [lsort -command \{ $l] leak (afredd,fellows) 2007-07-05 (bug fix)[1743676] no command named "" error message (porter,virden) 2007-07-11 (bug fix)[1752146] [while 1 {}] & [interp limit] on commands (sofer) 2007-07-31 (bug fix)[681877] tcl_platform(user) from system, not env (fellows) 2007-07-31 (enhancement)[1750051] space efficiency of Tcl variables (sofer) *** POTENTIAL INCOMPATIBILITY for C code that accesses internal Tcl structs Var, Bytecode, Namespace, or CallFrame. *** 2007-08-01 (enhancement)[1764318] word.tcl proc rewrites (petasis,fellows) 2007-08-08 (bug fix)[1770224] [tcl::mathop::>> $big1 $big2] errors (porter) 2007-08-14 (platform support) Darwin [load] from VFS on intel & 64bit (steffen) 2007-08-15 (bug fix)[1773127] corrected open mode "a+" (rottman,fellows) 2007-08-16 (bug fix)[1773040] ::errorInfo trace crash (janssen,porter) 2007-08-16 (performance)[1564517] pre-compile constant expressions (porter) 2007-08-21 (bug fix)[1775878] 'puts \' in interactive tclsh failed to move to prompt for continuation line (porter) 2007-08-25 (bug fix)[1781282] [clock scan] case senstivity (kenny) 2007-08-25 (performance)[1767293] ** on native integer types (kenny) 2007-09-03 clock tzdata updated to Olson's tzdata2007g (kenny) 2007-09-06 (platform support) Darwin: drop support for Xcode 1.5 project, add project for Xcode 3.0 (steffen) 2007-09-08 (bug fix)[1786481] nested [dict update] crash (fellows) 2007-09-08 (bug fix)[1710710] TclPtrSetVar leak (mistachkin,sofer) 2005-09-09 (feature removed) Tcl_ObjType "nsName" no longer registered (porter) *** POTENTIAL INCOMPATIBILITY for Tcl_GetObjType("nsName") *** 2007-09-10 (bug fix)[1740631] Linked variable unlink prevention (maros,hobbs) 2007-09-11 (bug fix)[1786481] [dict update] stack management (sofer) *** POTENTIAL INCOMPATIBILITY with previous 8.5 alpha bytecode only *** 2007-09-11 (bug fix)[1578344] [package require -exact] 8.4 compat (porter) *** POTENTIAL INCOMPATIBILITY with previous 8.5 alphas only *** 2007-09-11 (bug fix)[1772989,1071322] Support _, : in test constraints (porter) => tcltest 2.3b1 2007-09-11 (platform support) Windows AMD64 support (thoyts) 2007-09-14 (enhancement)[1793984] DTrace provider for Tcl (steffen) 2007-09-14 (bug fix)[1519940] surplus ns path invalidation (fellows,bauer) 2007-09-15 (platform support) SunOS-5.1x link with cc, not ld (steffen) 2007-09-17 (platform support)[1748251] Fix NetBSD link failures (english) (bug fix)[1066755] Several stack efficiency efforts increases recursion limit on Windows to be larger than the default [interp recursionlimit] value --- Released 8.5b1, September 26, 2007 --- See ChangeLog for details --- 2007-10-02 (bug fix)[1806422] proper [tcl::tm::path] autoload (porter) 2007-10-02 (bug fix) Improve Tcl_DecrRefCount() robustness (staplin) 2007-10-11 (bug fix)[1805887] [string is int -failindex] for 0o, 0b (porter) 2007-10-15 (bug fix)[1813528] Tcl_ParseBraces read past buffer (mistachkin) 2007-10-25 (bug fix)[1726873] intermittent crash in threads (vasiljevic) --- Released 8.5b2, October 26, 2007 --- See ChangeLog for details --- 2007-10-27 (bug fix)[1821159] fixed broken compile on x86_64 (sofer) 2007-10-27 (bug fix)[1810264] stop panic in RE lexer (fellows) 2007-10-28 (enhancement)[1826906] Embed iso8859-1 encoding in libtcl (fellows) 2007-11-01 (bug fix)[1808258] [string is ascii \000] (fellows) 2007-11-05 (bug fix)[1823576] [fconfigure $serial -xchar \000] (cassof) 2007-11-07 (performance)[1827996] binary glob matching (hobbs) 2007-11-07 (performance) binary [gets] (hobbs) 2007-11-09 (performance)[1829248] interp state reset (sofer) 2007-11-10 (performance) stack checking (sofer) 2007-11-10 (performance) list indexing bytecode (sofer) 2007-11-11 (performance)[1830038] macros to fetch Tcl_Obj intreps (sofer) 2007-11-11 (performance)[1830166] RE bytecode for simple cases (hobbs) 2007-11-13 (performance) [switch] & [regexp] use RE bytecode (hobbs, fellows) 2007-11-14 (performance) bytecode for [info exists] (fellows) 2007-11-15 (new feature)[1231022] configure option: --disable-rpath (fellows) 2007-11-15 (bug fix)[1810038] infinite loop in RE compiler (lane,porter) Many significant documentation improvements (fellows, sofer) --- Released 8.5b3, November 19, 2007 --- See ChangeLog for details --- 2007-11-20 (enhancement) string rep of dict has stable order (fellows) 2007-11-21 (enhancement) compiled ensemble support (fellows) 2007-11-22 (enhancement) [dict] is now an ensemble (fellows) 2007-11-23 (enhancement) [string] is now an ensemble (fellows) 2007-11-26 (bug fix)[1815573] Correct stack checking failure (sofer,golovan) 2007-11-27 (bug fix)[800753] Document single byte char limit for [chan configure -eofchar] (cassoff) 2007-12-03 (enhancement)[1836519] [switch $val $body] safe/fast (fellows,spjuth) 2007-12-03 (release) tcltest package bump to 2.3.0 (porter) 2007-12-03 (bug fix)[1618235] fix BSD compile errors (fellows) 2007-12-05 (bug fix)[1844789] fix [lsearch -exact -integer] crash (fellows) 2007-12-05 (performance)[1845092] Tcl_ObjType for channel names (hobbs) 2007-12-14 (bug fix)[1602539] NUL pollution in [glob] result (hobbs) 2007-12-17 (bug fix)[1851832,1851524] memory alignment correction (sofer) 2007-12-18 (bug fix)[1810264] revised regexp engine to prevent debilitating over-consumption of resources (drewry,lane,ormandy,fellows) Several documentation and release notes improvements --- Released 8.5.0, December 20, 2007 --- See ChangeLog for details --- 2007-12-23 (bug fix)[1857126] restore backref support to regexps (hobbs) 2007-12-26 (enhancement)[1856994] [lsort] performance (sofer) 2008-01-10 (bug fix)[1867855] fix [format %lli 0] crash (porter) 2008-01-11 (bug fix)[1850424,1860425] stack checking on *bsd (sofer,noble) 2008-01-13 (bug fix)[1353846] crash in read-only serial (hobbs,newman) 2008-01-15 (bug fix)[1869989] mem leak; expr literals (porter,melbardis) 2008-01-20 (bug fix)[1869405] binary [gets]; stacked channels (hobbs,ficicchia) 2008-01-22 (bug fix)[1867855] fix [lreverse {}] crash (sofer,madden) 2008-01-30 (bug fix)[1882373] fix Tcl_GetAlias pointer code (an00na) Several documentation and release notes improvements --- Released 8.5.1, February 5, 2008 --- See ChangeLog for details --- 2008-02-06 (enhancement) [clock format] performance (kenny) 2008-02-12 (bug fix)[1891827] compiled [switch -nocase] error (fellows) 2008-02-22 (bug fix)[1818565] missing state array in http::status (thoyts) => http 2.5.4 2008-02-26 (bug fix)[1868845] corrected [eof] ordering (thoyts) 2008-02-26 (new feature) [http::meta] command (thoyts) => http 2.5.5 2008-02-26 (bug fix)[1902436] fixed regexps ending in \* (hobbs) 2008-02-27 (bug fix)[1862555,1902423] [clock] range & l10n (kenny) 2008-02-28 (bug fix) [return -level 0] memory leak (porter) 2008-02-28 (bug fix) [format %llx $big] memory leak (porter) 2008-02-28 (bug fix) expression parser error message memory leak (porter) 2008-02-28 (bug fix) memory leak when enter trace modifies command (porter) 2008-02-29 (enhancement) Consumer refcounting for Tcl_SetReturnOptions() and Tcl_AddObjToErrorInfo() (spjuth,porter) *** POTENTIAL INCOMPATIBILITY *** 2008-03-07 (bug fix)[1899164] Avoid expr and script bytecode confusion (porter) 2008-03-07 (bug fix)[1904907] finalize crash in Tcl_GetReturnOptions (kupries) 2008-03-10 (bug fix)[1893815] expr {abs(-1e-350)} => -0.0 (porter) 2008-03-10 (bug fix)[1901113] crash in [tcl::Bgerror {} {}] (madden,porter) 2008-03-11 (bug fix)[1911919] unset trace inf loop in namespace delete (sofer) 2008-03-12 (new feature) some HTTP 1.1 support in http (and more!) (hobbs) => http 2.7 2008-03-13 (enhancement) support space in INSTALL_ROOT or $builddir (steffen) 2008-03-16 (bug fix)[1903325] bytecode stack space prediction crash (fellows) 2008-03-18 (bug fix)[1914604] Tcl Modules: encoding fixed to utf-8; environment variables without "." added to customization hooks (kupries) *** POTENTIAL INCOMPATIBILITY *** 2008-03-18 (bug fix)[1914503] alignment of TclStackAlloc() return (sofer)\ 2008-03-20 (bug fix)[1868171] expose Tcl_GetMemoryInfo (for AOLserver) (fellows) 2008-03-24 (bug fix)[1923966] crash in [binary format x0s] (thoyts) 2008-03-27 (platform support)[1921166] Solaris 64bit build fixes (steffen) 2008-03-27 clock tzdata updated to Olson's tzdata2008b (kenny) --- Released 8.5.2, March 28, 2008 --- See ChangeLog for details --- 2008-03-30 (bug fix)[1783544] more robust TclIsNaN() (kenny,teterin) 2008-04-01 (interface)[1819422] tclStubsPtr no longer in libtcl (porter) *** POTENTIAL INCOMPATIBILITY *** 2008-04-01 (bug fix)[1839067] FP round fix for Solaris/x86 (kupries,schlenker) 2008-04-02 (bug fix)[780533,1932639] [fcopy] callbacks unreliable (ferrieux) 2008-04-02 (interface)[1819422] libtclstub symbols MODULE_SCOPE (steffen) 2008-04-04 (bug fix) [chan postevent] crash (kupries) 2008-04-07 (bug fix) Fix broken [format {% d}] (max) 2008-04-07 (bug fix)[1350564] Bi-directional [fcopy] now supported (ferrieux) 2008-04-16 (bug fix)[1938497] Tcl_SetNotifier() fixes (steffen) 2008-04-16 (interface)[1938497] make stubs tables 'static const' (steffen) 2008-05-02 (new feature) [binary] is now a [namespace ensemble] (thoyts) 2008-05-07 (bug fix) [dict append] crash (mccormack,fellows) 2008-05-21 (bug fix)[1968882] [info complete "\\\n"] => 0 (porter) 2008-05-22 (bug fix)[1968245] Tcl_LogCommandInfo() accept length=-1 (darroch) 2008-05-23 (bug fix)[1965787] 32-bit overflow in [tell] result (ferrieux) 2008-05-31 (new feature)[TIP 257] [oo::*] commands from TclOO (fellows) 2008-06-04 (new feature)[TIP 317] [binary encode]; [binary decode] (thoyts) 2008-06-06 (new feature)[TIP 230] [chan push]; [chan pop] (kupries) 2008-06-08 (enhancement)[1973096] bytecompiled [uplevel] scripts (sofer) 2008-06-12 (platform support) Solaris static build with DTrace (steffen) 2008-06-12 (platform support) Solaris/amd64 gcc 64bit support (steffen) 2008-06-13 (new feature)[TIP 285] [interp cancel]; Tcl_CancelEval() (mistachkin) 2008-06-20 (bug fix)[1999035] make [interp bgerror $i] act in $i (porter) 2008-06-23 (bug fix)[1972879] bad path intrep caching (porter) 2008-06-24 (bug fix)[1999176] crash in [glob -dir {} a] (porter) 2008-06-25 (bug fix)[1999119] Support TM packages in Safe Base (kupries) --- Released 8.6a1, June 25, 2008 --- See ChangeLog for details --- 2008-06-29 (bug fix)[2004480] plug memory leaks (ade,porter,steffen) 2008-07-01 (enhancement)[1905562] embed recursion limit in RE engine (fellows) 2008-07-03 (bug fix)[1969717] fix package finding on Samba shares (jos) 2008-07-03 (bug fix)[1987821] mem leak in [seek] on reflected chan (kupries) 2008-07-13 (enhancement)[2017110] new Non-Recursive Evaluation implementation enables deep Tcl evaluation stacks without deep C stacks. (sofer) 2008-07-20 (enhancement)[2008248] dict->list preserve item intreps (pasadyn) 2008-07-21 (bug fix)[582506] imported cmds now fire execution traces (sofer) 2008-07-21 (bug fix)[2015723] [file] bad use of inodes on Windows (thoyts) 2008-07-21 (new feature)[TIP 304] [chan pipe] (ferrieux) 2008-07-21 (bug fix)[2021443] more consistent "wrong # args" msgs (nijtmans) 2008-07-21 (enhancement) [info frame] returns file data in more cases (kupries) 2008-07-29 (bug fix)[2030670] fix rare panic in TclStackFree (pasadyn,sofer) 2008-08-01 Tcl_Finalize() no longer called implicitly on DLL_PROCESS_DETACH. 2008-08-05 (enhancement)[1994512] async connect logic simplified (jenglish) 2008-08-06 (bug fix)[2040295] stopped supplying a workaround for bugs in Itcl's use of [namespace code]. Itcl now supplies its own workaround. *** POTENTIAL INCOMPATIBILITY for older Itcl releases *** 2008-08-06 (bug fix)[2039178] repaired guard against dispatching oo methods in a deleted interp. (porter) 2008-08-08 tzdata updated to Olson's tzdata2008e (kenny) 2008-08-11 (bug fix)[2046846] 64bit support for http zlib crc (thoyts) => http 2.7.1 2008-08-11 (enhancement) automatic [package provide] for TMs (kupries) 2008-08-17 (bug fix)[2055782] crash involving Tcl_ConcatObj (sofer) 2008-08-21 (new feature) CONST-ified Tcl routines passing (Tcl_ObjType *), (Tcl_Filesystem *), or (Tcl_Timer *) arguments (nijtmans,porter) *** POTENTIAL INCOMPATIBILITY *** 2008-08-21 (bug fix)[2065115] Restored ***= regexp functioning (hobbs,porter) --- Released 8.6a2, August 25, 2008 --- See ChangeLog for details --- 2008-08-29 (bug fix)[2082299] Install TclOO header files (fellows) 2008-09-01 oo methods called during interp deletion no longer skipped if they do not need the dying interp (fellows) 2008-09-02 (support) Dropped support for pre-ANSI compilers. (porter) 2008-09-04 (bug fix)[2093947] var unset trace in coroutine (fellows,sofer) 2008-09-10 (enhancement) efficient list->dict conversion (elby,fellows) 2008-09-10 (bug fix)[2102930] faulty numLevels count (madden,sofer) 2008-09-16 (bug fix)[2114165] eval failure following cancel (sofer) 2008-09-17 (bug fix)[2116053] export [min] and [max] from tcl::mathfunc (sofer) 2008-09-22 (new feature)[TIP 320] oo common variable declaration (fellows) 2008-09-24 (new feature)[TIP 316] portable access to Tcl_StatBuf (fellows) 2008-09-24 (new feature)[TIP 323] [file delete], [file mkdir] zero pathNames (porter) 2008-09-25 (new feature)[TIP 315] new var: tcl_platform(pathSeparator) (vu,fellows) 2008-09-25 (new feature)[TIP 323] [global], [variable] zero varNames (porter) 2008-09-26 (new feature)[TIP 323] [lassign], [namespace upvar], [my variable] zero varNames (porter) 2008-09-26 (new feature)[TIP 323] [tcl::tm::path add|remove] zero pathNames (porter) 2008-09-26 (new feature)[TIP 323] [lrepeat] zero elements; zero repeats (porter) 2008-09-27 (bug fix)[2130992] prevent overflow crash in [lrepeat] (fellows) 2008-09-28 (new feature)[TIP 314] ensemble parameters before subcommand (hellström,fellows) 2008-09-29 (new feature)[TIP 318] revised defaults for [string trim] (poser) *** POTENTIAL INCOMPATIBILITY *** 2008-09-29 (new feature)[TIP 313] [lsearch -bisect] (spjuth) 2008-09-29 (new feature)[TIP 326] [lsort -stride] (elby) 2008-09-29 (new feature)[TIP 323] [linsert] zero elements (porter) 2008-09-29 (new feature)[TIP 323] [glob] zero patterns (porter) 2008-10-02 (new feature)[TIP 330] interp->result access disabled (kenny) *** POTENTIAL INCOMPATIBILITY *** 2008-10-03 (new feature)[TIP 265] Tcl_ParseArgv() (bromley) 2008-10-03 (new feature)[TIP 195] [tcl::prefix] (spjuth) 2008-10-04 (new feature) CONST-ified Tcl routines Tcl_GetIndexFromObj, Tcl_RegisterConfig, Tcl_InitCustomHashTable, and routines passing (Tcl_ChannelType *). (nijtmans) *** POTENTIAL INCOMPATIBILITY *** 2008-10-04 (bug fix)[2059262] unload only libraries marked unloadable (nijtmans) *** POTENTIAL INCOMPATIBILITY *** 2008-10-05 (new feature)[TIP 331] [lset listVar end+1 $value] (kenny) 2008-10-05 (bug fix)[2143288] correct bad isqrt() results (boffey,kenny) 2008-10-05 (new feature) CONST-ified return value of the Tcl_FSFileAttrStringsProc prototype. (nijtmans) *** POTENTIAL INCOMPATIBILITY for Tcl_Filesystems *** 2008-10-07 (new feature)[TIP 327] [tailcall] (sofer) 2008-10-07 (new feature)[TIP 328] [coroutine],[yield],[info coroutine] (sofer) 2008-10-08 (bug fix)[2151707] fix stack trace from variable trace (porter) 2008-10-10 (bug fix)[2155658] crash in oo method export (fellows) --- Released 8.6a3, October 10, 2008 --- See ChangeLog for details --- 2008-10-13 (bug fix) Fix ability to join threads on 64-bit Windows (thoyts) 2008-10-23 (bug fix)[2186888] Direct-eval [for] handling of [continue] was broken by NRE reform (sofer,porter) 2008-10-24 (bug fix) fix failure to read SHOUTcast streams (thoyts) => http 2.7.2 2008-10-27 (enhancement) system encoding at startup is now "iso8859-1", and no longer "identity". Use of identity encoding minimized (porter) *** POTENTIAL INCOMPATIBILITY *** 2008-10-31 (bug fix)[2200824] revised [oo::define] to include caller context when resolving names. (nassau,fellows) 2008-11-10 (bug fix)[2255235] [platform::shell::LOCATE] update (ring,kupries) => platform::shell 1.1.4 2008-11-13 (bug fix)[2269431] VFS [load] -> tempfile litter (ficicchia,nijtmans) 2008-11-26 (bug fix)[2114900] updated tclIndex file (cassoff,kenny) 2008-11-27 (bug fix)[2251175] [{*}{\{}] errors (hellström,ferrieux,porter) 2008-11-29 (new feature)[TIP 210] [file tempfile] (techentin,fellows) 2008-11-30 (bug fix)[2362156] [clock]: colon in format string (mizuno,kenny) 2008-12-02 (bug fix)[2270477] hang in channel finalization (ferrieux,kupries) 2008-12-02 (new feature)[TIP 336] Tcl_*ErrorLine() routines. Direct access to the errorLine field of the interp struct denied by default. (porter) *** POTENTIAL INCOMPATIBILITY *** *** Define USE_INTERP_ERRORLINE to restore access for legacy code *** 2008-12-04 (bug fix)[2385549] [file normalize] failed on some paths (porter) 2008-12-05 (new feature)[TIP 307] Tcl_TransferResult() (leunissen,fellows) 2008-12-05 (new feature)[TIP 335] Tcl_InterpActive() (mistachkin,fellows) 2008-12-09 (new feature)[TIP 337] Tcl_BackgroundException() (porter) 2008-12-10 (new feature)[TIP 341] >1 [dict filter] patterns (hellström,fellows) 2008-12-10 (new feature)[TIP 343] [format %b $n] [scan $s %b] (ferrieux) 2008-12-10 tzdata updated to Olson's tzdata2008i (kenny) 2008-12-11 (new feature)[TIP 234] [zlib] and Tcl_Zlib*() (sheffers,fellows) 2008-12-11 (bug fix)[2407783] spoil ChannelState when channel name passes among multiple interps (kupries) 2008-12-12 (new feature)[TIP 322] Tcl_NR*() routines to enabled non-recursive evaluation in extensions (sofer,kenny) 2008-12-09 (new feature)[TIP 338] Tcl_*StartupScript() (porter) *** POTENTIAL INCOMPATIBILITY for callers of Tcl*Startup* routines *** 2008-12-16 (new feature)[TIP 329] [try] [throw] (davel,fellows) 2008-12-17 (new feature)[TIP 308] package tdbc 1.0b1 (kenny) 2008-12-18 (new feature)[TIP 332] [close $chan read|write] (ferrieux) 2008-12-18 (bug fix)[2444274] panic in long commands from {*} (goth,porter) --- Released 8.6b1, December 19, 2008 --- See ChangeLog for details --- 2008-12-27 [TIP 234] Tcl_Zlib* interface revisions (fellows) *** INCOMPATIBILITY with interface of 8.6b1 *** 2009-01-02 (platform support)[878333] IRIX compat for mkstemp() (fellows) 2009-01-03 (bug fix)[2481670] [clock add] error message (talvo) 2009-01-05 (bug fix)[2412068] NR-enable [source] (fellows) 2009-01-06 (bug fix)[2489836] crash unknown method dispatch (nadkarni,fellows) 2009-01-06 (bug fix)[2481109] fix context of instance name check (fellows) 2009-01-08 (enhancement) more -errorcode values (fellows) 2009-01-19 (new feature) CONFIG_INSTALL_DIR - where tclConfig.sh goes (cassoff) 2009-01-19 (platform support) better tools for BSD ports (cassoff) 2009-01-21 (bug fix)[2458202] exit crash with [chan create]d channel (kupries) 2009-01-26 (bug fix)[2446662] uniformly declare EOF on RST on sockets (ferrieux) 2009-01-26 (bug fix)[1028264] delay WSACleanup() from under our feet (ferrieux) 2009-01-29 (bug fix)[2519474] Tcl_FindCommand() bug exposed by oo (fellows) 2009-01-29 (bug fix)[2537939] Fix Tcl_OOInitStubs() for no-stubs build (fellows) 2009-02-04 (bug fix)[2561746] [string repeat] overflow crash (porter) 2009-02-05 (enhancement) optimize string operations on bytearrays (fellows) 2009-02-12 (bug fix) enable simpler [oo::define] extension (ferri,fellows) 2009-02-15 (bug fix)[2603158] Tcl_AppendObjToObj: append to self crash (porter) 2009-02-17 (platform support) MSVC and _WIN64 (hobbs) 2009-02-20 (bug fix)[2571597] [file pathtype /a] wrong result (nadkarni,porter) 2009-03-03 (bug fix)[2662434] [zlib crc32] result now unsigned (gavilan,fellows) 2009-03-15 (platform support) translate SIGINFO where defined (BSD) (teterin) 2009-03-15 (bug fix)[2687952] TSD struct memleak (mistachkin) 2009-03-18 (bug fix)[2688184] memleak in [file normalize] (mistachkin) 2009-03-20 (bug fix)[2597185] crash in Tcl_AppendStringToObj (porter) 2009-03-20 (bug fix)[2561794,2669109,2494093,2553906] string overflow (porter) 2009-03-22 (bug fix)[2502037] NR-enable [namespace unknown] (sofer) 2009-03-27 (bug fix)[2710920] [file dirname|tail /foo/] errors (epler,porter) 2009-04-08 (bug fix)[2570363] unsafe [eval]s in tcltest (bron,porter) => tcltest 2.3.1 2009-04-08 (platform support) more Darwin kernel patterns (steffen) => platform 1.0.4 2009-04-09 (bug fix)[26245326] [http::geturl] connection failures (golovan) => http 2.7.3 2009-04-10 (new feature) Darwin: embeddable CoreFoundation notifier (steffen) 2009-04-10 (bug fix)[1961211] Darwin [load] back-compatibility (steffen) 2009-04-09 (new feature) http chunked+gzip modes (thoyts) => http 2.8.0 2009-04-11 (enhancement) clarified cmd name resolution in oo forwards (fellows) 20009-04-19 (bug fix)[2715421] http: excess bytes after POST (thoyts) => http 2.8.1 2009-04-30 (bug fix)[2486550] coroutine in [interp invokehidden] (sofer) 2009-05-07 (bug fix)[2785893] find command in deleted namespace (sofer) 2009-05-08 (bug fix)[2414858] tailcall in oo constructor (fellows) 2009-05-14 (new subcommand)[TIP 354] [info object namespace] (fellows) 2009-05-29 (platform support) account for ia64_32 (kupries) => platform 1.0.5 2009-06-02 (bug fix)[2798543] incorrect [expr] integer ** results (porter) 2009-06-10 (bug fix)[2801413] overflow in [format] (porter) 2009-06-13 (bug fix)[2802881] corrected compile env context (tasada,porter) 2009-06-17 (redesign) reduced ambition of [exit] finalization with aim to avoid otherwise very tricky multi-thread finalization bugs. (staplin,ferrieux) *** POTENTIAL INCOMPATIBILITY for exit handlers *** 2009-06-26 (platform support) updates for Xcode 3.1 & 3.2 (steffen) 2009-06-30 (platform support) clang static analyzer macros (steffen) 2009-07-01 (bug fix)[2806622] Win: bad tcl_platform(user) value (thoyts) 2009-07-05 (bug fix) zlib support asynch [chan copy] on chan transform (fellows) 2009-07-12 (bug fix)[1895546] TclOO support for Itcl 4 method caching (fellows) 2009-07-13 (bug fix)[1605269] NR-related [info frame] fixes (kupries) 2009-07-14 (bug fix)[2821401] NR-enable direct eval [switch] (kenny) 2009-07-16 (bug fix)[2819200] underflow settings on MIPS systems (porter) 2009-07-19 (interface)[TIP 354] new routine Tcl_GetObjectName() (fellows) 2009-07-20 (performance) favor [string is] success cases over empty (fellows) 2009-07-22 (interface) removed TclpPanic() routine (nijtmans) 2009-07-23 (bug fix)[2820349] plug event leak in notifier (mistachkin) 2009-07-24 (bug fix)[2826248] crash in Tcl_GetChannelHandle (sonnenburg,kupries) 2009-07-31 (bug fix)[2830354] overflow in [format] (misch,porter) 2009-08-06 (bug fix)[2827000] reflected channels can signal EGAIN (kupries) 2009-08-12 (new feature)[TIP 353] Tcl_NRExprObj() (porter) 2009-08-20 (bug fix)[2823276] NR-enable [if], [for], [while] (fellows) 2009-08-20 (bug fix)[2806250] EIAS violation in ~foo pathnames (porter) 2009-08-21 (bug fix)[2837800] [glob */foo] return ./~x/foo (porter) 2009-08-24 (bug fix) nested event loop notifier w/TkAqua Cocoa (alaoui,steffen) 2009-08-25 (bug fix) [info frame] account for continuation lines (kupries) 2009-08-27 (bug fix)[2845535] overflows in [format] (porter) 2009-09-01 (bug fix) improved error message in tcltest (porter) => tcltest 2.3.2 2009-09-11 (bug fix)[2849860] http handle "quoted" charset value (fellows) => http 2.7.4 2009-09-11 (enhancement)[2314561] [subst] now bytecompiled, NR-enabled (porter) 2009-09-24 (new feature)[TIP 356] Tcl_NRSubstObj() (porter) 2009-10-04 (bug fix)[2569449] Core Foundation memory bug in Tiger (steffen) 2009-10-06 (bug fix) repair intrep loss in slave interp evaluations introduced by first versions of the NRE conversion (nadkarni,porter) 2009-10-06 (bug fix)[1941434] broken tclTomMath.h includes (porter) 2009-10-07 (bug fix)[2871908] leaked hash table (mistachkin,kupries) 2009-10-08 (bug fix)[2874678] bignum leak in [dict incr] (fellows) 2009-10-17 (bug fix)[2629338] crash in var unset traces (raney,fellows) 2009-10-19 (bug fix)[2107634] extend [read] and [gets] to Tcl string limits (morrison,parker,porter) 2009-10-21 (bug fix)[2882561] Haiku OS signal support (morrison,fellows) 2009-10-22 (bug fix)[2883857] [my varname arr(index)] (boudaillier,fellows) 2009-10-23 (bug fix) 0-length writes: spurious SIG_PIPE (teterin,kupries) 2009-10-24 Broken DST applied EU rules to US zones (lehenbauer,kenny) 2009-10-29 (bug fix)[2800740] halved bignum memory on 64-bit systems (porter) *** POTENTIAL INCOMPATIBILITY *** 2009-11-05 (bug fix)[2854929] TM search path support in Safe Base (kupries) 2009-11-05 (enhancement) rewrite of the Safe Base commands (kupries) 2009-11-11 (bug fix)[2888099] [close] loses ENOSPC error (khomoutov,ferrieux) 2009-11-11 (bug fix)[2891171] RFC 3986 compliance for ? in URL (nijtmans) => http 2.8.2 2009-11-12 (bug fix)[2895565] [fcopy -size] miscounts when converting encodings (kupries) 2009-11-16 (bug fix)[2891556] encoding finalization crash (mistachkin,ferrieux) 2009-11-18 (bug fix)[2849797] consistent names for std chans (nijtmans,fellows) *** POTENTIAL INCOMPATIBILITY *** 2009-11-19 (enhancement) [load]able Tcltest extension (nijtmans) 2009-11-24 (bug fix)[2893771] [file stat] on Win locked files (thoyts) 2009-11-24 (bug fix)[2903011] crash call destructor from constructor (fellows) 2009-12-03 (bug fix)[2906841] Safe Base [glob ../*] fixes (fellows) 2009-12-09 (bug fix)[2901998] consistent I/O buffering (ferrieux,kupries) 2009-12-11 (bug fix)[2806407] NR-enabled coroutines (sofer) 2009-12-16 (bug fix)[2913616] msgcat: improved safe interp support (fellows) => msgcat 1.4.3 2009-12-22 (bug fix)[2918962] [lsort -index -stride] crash (moore,fellows) 2009-12-23 (bug fix)[2913625] [info script/nameof] in safe interps (fellows) 2009-12-28 (bug fix)[2891362] enable time limit in child interps (fellows) 2009-12-29 (bug fix)[2922555] [binary decode hex { }] crash (thoyts) 2009-12-29 (bug fix)[2895741] enable min(), max() in safe interps (fellows) 2009-12-30 (bug fix)[2824981] guard [unknown] against [set] undef (sofer) 2010-01-05 (bug fix)[2918610] [file rootname] corruption (magerya,porter) 2010-01-18 (bug fix)[2932421] less [format %s] shimmer (ferrieux) 2010-01-18 (bug fix)[2918110] [chan postevent] crash (bron,kupries) 2010-01-21 (bug fix)[2910748] NR-enable epoch fallback direct eval (sofer) 2010-01-30 (enhancement) [unset] now bytecompiled (fellows) 2010-02-01 (bug fix)[2942697] faster match: some pathological regexp patterns (lane,fellows) 2010-02-01 (bug fix)[2939073] [array unset] unset trace crash (ferrieux) 2010-02-02 (bug fix)[2944404] crash in oo destructor (fellows) 2010-02-02 (new feature) [array] is now a [namespace ensemble] (fellows) 2010-02-05 (enhancement) [error] now bytecompiled (fellows) 2010-02-08 (bug fix)[2947783] Tcl_Zlib*flate fail on shared values (fellows) 2010-02-09 (enhancement) [try] now bytecompiled (fellows) 2010-02-11 (bug fix)[2826551] line-sensitive matching in regexp (dejong) 2010-02-11 (bug fix)[2949740] [open |noSuch rb] crash (kovalenko,fellows) 2010-02-15 (bug fix)[2950259] harden (delete obj ns -> delete obj) (fellows) 2010-02-21 (bug fix)[2954959] get sign of abs($zero) right (nijtmans) 2010-02-22 (bug fix)[2762041] zlib chan transforms read EOF too early (kupries) 2010-02-27 (bug fix)[801429] Tcl_SetMainLoop() thread safety (fellows) *** POTENTIAL INCOMPATIBILITY *** 2010-03-02 (enhancement) -fvisibility-hidden build support (nijtmans) 2010-03-04 (bug fix)[2962664] [oo::class destroy] crash (fellows) 2010-03-05 (interface) TclOO typedefs for function pointers (fellows) *** POTENTIAL INCOMPATIBILITY *** 2010-03-09 (bug fix)[2936225] stop [chan copy] to slow channel consuming all memory with buffer backup (ferrieux) 2010-03-17 (bug fix)[2921116] crash in chan transfrom teardown (kupries) 2010-03-19 (enhancement) [throw] now bytecompiled (fellows) 2010-03-20 (enhancement) permit [fcopy] of > 2**31 bytes (fellows) 2010-03-24 (new feature) [info object methodtype] (fellows) 2010-03-24 (bug fix)[2383005] [return -errorcode] reject non-list (porter) 2010-03-25 (bug fix)[2976504] broken fstatfs() call (reeuwijk,fellows) 2010-03-30 (new feature)[TIP 362] [registry -32bit|-64bit] (courtney,fellows) => registry 1.3 2010-03-30 (bug fix)[2978773] refchan mem preservation (kupries) 2010-04-02 (new feature)[TIP 357] Tcl_LoadFile, Tcl_FindSymbol, etc. (kenny) 2010-04-05 (configure change)[TIP 364] default build: --enable-threads (fellows) *** POTENTIAL INCOMPATIBILITY *** 2010-04-02 (new feature)[TIP 348] [info errorstack], [return -errorstack] (ferrieux) 2010-04-20 (enhancement) update bundled zlib to 1.2.5 (nijtmans) 2010-04-29 (enhancement)[2992970] optimize bytearray appends (fellows) 2010-05-19 (bug fix)[3004007] dict/list shimmer w/o string rep loss (fellows) 2010-06-09 (bug fixes) platform: several fixes for 64 bit systems (kupries) => platform 1.0.9 2010-06-16 (bug fix)[3016135] [clock format] in he_IL locale (nijtmans) 2010-06-18 (bug fix)[3017997] Add .cmd to file extensions for [exec] (fellows) 2010-06-28 (bug fix)[3019634] support errno.h changes in MSVC++ 2010 (nijtmans) *** POTENTIAL INCOMPATIBILITY *** 2010-07-02 (enhancement) -errorcode for [expr] domain errors (fellows) 2010-07-28 (bug fix)[3037525] crash deleting vars @ callframe pop (sofer) 2010-08-04 (bug fix)[3034840] mem corrupt when refchan loses interp (kupries) 2010-08-04 (enhancement) Win [load] use LOAD_WITH_ALTERED_SEARCH_PATH (hobbs) 2010-08-04 (platform support) panic on detection of win9x system (hobbs) *** POTENTIAL INCOMPATIBILITY *** 2010-08-10 (fix) Handle non-null-terminated bytearrys in glob matching (hobbs) 2010-08-11 (fix) copy-paste bug in [yield] implementation (sofer, goth) 2010-08-11 (platform) Drop pre-aix 4.2 support, ldAix (hobbs) 2010-08-14 (frq)[2819611] changed signatures of hash fnctions, delete-file, and get-native-path (nijtmans) *** POTENTIAL INCOMPATIBILITY *** 2010-08-15 (bug fix)[3045010] tweaked error message for wrong#args of lambda's (fellows) 2010-08-18 (bug fix)[3004191] fixed safe [glob] (fellows) 2010-08-21 (patch)[3034251] genStubs steal features of ttkGenStubs (nijtmans) 2010-08-26 (bug fix)[1230554] configure, OSF-1 problems, windows manifest issues (hobbs) 2010-08-30 (bug fix) [3046594,3047235,3048771] reimplemented tailcall (sofer) 2010-08-31 fixed manifest handling on windows (hobbs, kupries) 2010-08-31 windows makefile and stub changes (nijtmans) 2010-09-01 (bug fix)[3057639] compiled lappend trace consistency (hobbs,kupries) *** POTENTIAL INCOMPATIBILITY *** 2010-09-01 fixed safe glob handling of -directory (kupries) 2010-09-02 fixed safe glob handling of -join (kupries) 2010-09-08 (bug fix)[3059922] build with mingw on amd64 (porter, mescalinum) 2010-09-15 (bug fix)[3067036] stop hang in bytearray append (fellows) 2010-09-22 unified set of link libraries between mingw and vc (nijtmans) 2010-09-22 (bug fix)[3072640] protect writes to ::error* variables (sofer) 2010-09-23 fix leak of return options [catch $err m constant] (porter, hobbs) 2010-09-24 (bugfix)[3056775] fixed race condition in windows sockets (kupries) 2010-09-24 (performance) string eq/cmp (hobbs) 2010-09-26 (patch)[3072080] rewritten NRE core (sofer) 2010-09-28 (new feature)[TIP 162] implementation of ipv6 sockets (max) 2010-10-02 (bug fix)[3079830] properly invalidate string rep of dicts (fellows) 2010-10-06 (bug fix)[3081065] fix writing to freed Tcl_Obj (porter) 2010-10-08 fix in ipv6 code on windows (nijtmans) 2010-10-09 fixed overallocation of execution stack (sofer) 2010-10-11 windows unicode changes (nijtmans) 2010-10-12 (bug fix)[3084338] fixed meamleak in ipv6 code (max) 2010-10-13 (bug fix)[467523,983660] alt fix allows empty literal share (porter) 2010-10-15 (bugfix)[3085863] updated unicode tables (nijtmans) *** POTENTIAL INCOMPATIBILITY *** 2010-10-16 refactored implementation of dict iteration (fellows) 2010-10-17 (patch)[2995655] report inner contexts on error stack (ferrieux) 2010-10-19 (bug fix)[3081008] fixed bytearray zlib interaction (fellows) 2010-10-19 improved crc, appending to bytearray (fellows) 2010-10-20 improved compilation of [dict for] (fellows) 2010-10-26 Added private support to disable reverse dns (max) 2010-10-26 Prevent crashes when querying socket options (fellows, max) 2010-10-28 (bug fix)[3093120] prevent freeaddrinfo(NULL) (porter, virden) 2010-10-29 (bug fix)[2905784] stop cycle waste in short [after] (ferrieux) 2010-11-01 tzdata updated to Olson's tzdata2010o (kenny) 2010-11-04 (bug fix)[3099086] Clarified docs of var substitution (fellows) 2010-11-04 improved install targets (cassof) 2010-11-04 improved testing of sockets (max) 2010-11-05 (frq)[491789] setargv/unicode cmdline for MSVC (nijtmans) 2010-11-09 (bug fix)[3105999] fixed memleak in OO var resolver (fellows) 2010-11-15 (TIP 378)[3081184] improved TIP 280 performance (kupries) 2010-11-16 (platform) VS 2005 SP1 MSVC compiler (nijtmans) 2010-11-18 (bug fix)[3111059] leak in [namespace delete] w coroutines (sofer) 2010-11-28 [3120139,3105247] Tcl_PrintDouble improvements (kenny) 2010-11-29 (new cmd) [tcl::unsupported::inject] (ferrieux,sofer) 2010-11-30 (enhancement) Restore TclFormatInt for performance (hobbs) 2010-12-09 (new feature) [file] is now a [namespace ensemble] (fellows) 2010-12-19 (bug fix) [fcopy -size 1 -command] asynchronous (ferrieux) 2010-12-12 (platform) OpenBSD build improvements (cassoff) 2010-12-17 (platform) Revisions to support rpm 4.4.2 (cassoff) 2010-12-27 (bug fix) crash in [lsort] w multiple -index options (fellows) 2010-12-30 (bug fix)[3142026] GrowEvaluationStack OBOE (harder,sofer) 2011-01-18 (bug fix)[3001438] [info frame -1] crash (mccormack,fellows) 2011-03-01 (performance)[3168398] optimize [interp cancel] (mistachkin) 2011-03-05 (bug fix)[3185009] crash in OO variables (danckaert,fellows) 2011-03-05 (new cmd) [tcl::unsupported::assemble] (ugurlu,kenny) 2011-03-06 (bug fix)[3200987,3192636] parser buffer overruns (porter) 2011-03-08 (bug fix)[3202905] failed intrep release of interp result (mccormack) 2011-03-09 (bug fix)[3202171] repair [namespace inscope] optimizer (porter) 2011-03-10 (new version) better tcltest reporting from child interps (fellows) => tcltest 2.3.3 2011-03-10 (new feature) [namespace] is now a [namespace ensemble] (fellows) 2011-03-12 (interface) reduce casting by ckalloc(), ckfree() callers (fellows) 2011-03-14 (bug fix) Fixes from libtommath 0.42.0 release (fellows) 2011-03-21 (bug fix)[3216070] [load] extension from embed Tcl apps (nijtmans) ***POTENTIAL INCOMPATIBILITY*** 2011-03-27 (performance) NRE: LIST lset foreach benchmark (twylite) 2011-04-11 (bug fix)[3282869] coroutine + eval + locals crash (ferrieux,sofer) 2011-04-13 (bug fix)[2662380] crash when variable append trace unsets (sofer) 2011-04-13 (bug fix)[3285375] Buffer overflow in [concat] (porter) 2011-05-02 (internals change) revised TclFindElement() interface (porter) *** POTENTIAL INCOMPATIBILITY *** 2011-05-05 (enhancement) dict->list w/o string rep generation (porter) 2011-05-10 (bug fix)[3173086] Crash parsing long lists (rogers,porter) 2011-05-24 (enhancement) msgcat internal improvements (fellows) => msgcat 1.4.4 2011-05-25 (TIP 381) [info object|class call] [self call] [nextto] (fellows) 2011-05-31 (bug fix)[3293874] let lists grow all the way to the limit (porter) 2011-06-02 (bug fix)[3185407] cmd resolution epoch flaw (nadkarni,fellows) 2011-06-13 (bug fix)[3315098] mem leak generating double string rep (neumann) 2011-06-22 (new feature) DEB_HOST_MULTIARCH support (kupries) => platform 1.0.10 2011-07-15 (bug fix)[3357771] Prevent circular refs in bytecode (porter) 2011-07-28 tzdata updated to Olson's tzdata2011h (porter) 2011-08-01 (bug fix)[3383616] memleak exposed by XOTcl (neumann,sofer) Many more Tcl built-in command errors now set an -errorcode. --- Released 8.6b2, August 8, 2011 --- See ChangeLog for details --- 2011-07-02 (bug fix)[3349507] correct double(1[string repeat 0 23]) (kenny) 2011-07-19 (bug fix)[3371644] Tcl_ConvertElement() segfault (sader, ferrieux) 2011-07-21 (bug fix)[3372130] hypot(.) segfault (nijtmans) 2011-08-12 (bug fix)[3389764] memleaks due to reference cycles in dup'd paths 2011-08-15 (bug fix)[3390272] leak of [info script] value (porter) 2011-08-17 (bug fix)[3393150] bignum leaks in Tcl_Get*() routines (porter) 2011-08-18 (bug fix)[3393714] [string toupper] overflow (nijtmans) 2011-08-30 (bug fix)[3398794] panic in interp limit setting (gavlian,fellows) 2011-09-08 (bug fix)[3401704] revised expr parser to permit function names like "nano()" instead of parsing as "nan o()" with missing op (duquette,porter) *** POTENTIAL INCOMPATIBILITY *** 2011-09-10 (bug fix)[3400658] wrong num args msg with TclOO (rsooltan,fellows) 2011-09-13 (bug fix)[3390638] solaris studio cc workaround (kechel,porter) 2011-09-13 (bug fix)[3405652] DTrace workaround (michelson,porter) 2011-09-16 (bug fix)[3391977] -headers overrides -type (ziegenhagen,fellows) => http 2.8.3 2011-09-16 (TIP 388) New \Uhhhhhhhh syntax (nijtmans) 2011-10-06 (enhancement) bytecode compile [dict with] (fellows) 2011-10-11 (bug fix)[2935503] [file stat] returns bad mode (nadkarni,nijtmans) 2011-10-20 (bug fix)[3418547] cmd lits and custom resolvers (soberning,fellows) 2011-10-31 (bug fix)[3414754] EIAS violation in fs paths (porter) 2011-11-22 (bug fix)[3354324] Win: [file mtime] sets wrong time (nijtmans) 2011-11-30 (bug fix)[967195] Simply args passed to child processes (nijtmans) => tcltest 2.3.4 2011-12-07 (bug fix)[3444754] fix [string tolower \u01C5] (nijtmans) 2011-12-11 (update)[3457031] Update [[:print:]] to Unicode 6.0 (nijtmans) 2011-12-24 (bug fix)[3464428] fix [string is graph \u0120] (nijtmans) 2012-01-08 (bug fix)[3470928] zoneinfo trouble with Windhoek data file (kenny) 2012-01-13 (bug fix)[3472316] fix retrieval of socket error (fellows) 2012-01-21 (bug fix)[3475667] [regexp] buffer read overflow (sebres) 2012-01-22 (bug fix)[3475264] [dict exists] return 0, not error (fellows) 2012-01-25 (bug fix)[3474460] [oo::copy] var resolution list (fellows) 2012-01-26 (bug fix)[3475569,3479689] mem corrupt in fs path (sebres,porter) 2012-01-30 (enhancement) improve bytecode compile of [catch] (fellows) 2012-02-02 (bug fix)[2974459,2879351,1951574,1852572,1661378,1613456] Fix problems where [file *able] would return false results on Win/Samba (porter) 2012-02-06 (bug fix)[3484621] bump bytecode epoch on exec traces (kuhn,sofer) 2012-02-15 (bug fix)[3487626] crash compiling [dict for] (fellows) 2012-02-15 (enhancement) bytecode compile [lrange],[lreplace] (fellows) 2012-02-17 (bug fix)[2233954] compile problem on AIX & Android (nijtmans) 2012-02-29 (bug fix)[3466099] BOM in Unicode (nijtmans) 2012-03-07 (bug fix)[3498327] RFC 3986 compliance (kupries) 2012-03-26 (TIP 380) New builtin class [oo::Slot] (fellows) *** POTENTIAL INCOMPATIBILITY *** 2012-03-27 (TIP 397) method to extend [oo::copy] (fellows) *** POTENTIAL INCOMPATIBILITY *** 2012-03-27 (TIP 395) New subcommand [string is entier] (fellows) 2012-04-02 (TIP 396) New command [yieldto] (fellows) 2012-04-04 (bug fix)[3514761] crash combining objects and ensembles (fellows) 2012-04-09 (bug fix)[2712377] [info vars] and oo variables (fellows) 2012-04-09 (bug fix)[3396896] no dups in oo var lists (fellows) 2012-04-11 (bug fix)[3448512] [clock scan 1958-01-01] fail on Win (nijtmans) 2012-04-15 (bug fix)[3517696] fix flush of zlib chan xform (fellows) 2012-04-18 tzdata updated to Olson's tzdata2012c (kenny) 2012-04-28 (TIP 398) exit non-blocking chan without flush (ferrieux) *** POTENTIAL INCOMPATIBILITY *** 2012-05-02 (enhancement) Better use of Intel cpuid instruction (nijtmans) 2012-05-03 (bug fix)[3428753] Unbreak synchronous [socket -async] (porter) 2012-05-10 (bug fix)[2812981] force consistent config of Tcl+pkgs (ferrieux) 2012-05-10 (bug fix)[473946] correct send of special characters (nijtmans) 2012-05-17 (bug fix)[3445787] fix [file] ensemble in Safe Base (fellows) 2012-05-17 (bug fix)[2964715] fix [glob] in Safe Base (fellows) 2012-05-17 (bug fix)[3106532] proper [switch -indexvar] values (fellows) *** POTENTIAL INCOMPATIBILITY *** 2012-05-21 (TIP 106) New -binary option to [dde execute|poke] (oehlmann) => dde 1.4.0 2012-05-23 (bug fix)[3525907] [zlib push decompress] & [chan event] (fellows,ferrieux,kupries) 2012-05-28 (bug fix)[3529949] Protect ~ paths in Safe Base (fellows) 2012-06-21 (bug fix)[3362446] [registry keys] failure (nijtmans) => registry 1.3.0 2012-06-25 (bug fix)[3537605] [encoding dirs a b] error message (fellows) 2012-06-25 (bug fix)[3024359] crash when multi-thread concurrent [file system] and Tcl_FSMountsChanged(). (porter) 2012-06-29 (bug fix)[3536888] fix locale guessing (oehlmann,nijtmans) 2012-07-05 (bug fix)[1189293] make "<<" redirect binary safe (porter) 2012-07-08 (bug fix)[3531209] accept IPv6 URLs (max) => http 2.8.4 2012-07-24 (bug fix) stop mem corruption in stacked channel events (max,porter) 2012-07-25 (bug fix)[3546275] [auto_execok] search match [exec] (danckaert) 2012-07-27 (update)[3464401] Support Unicode 6.2 (nijtmans) 2012-08-20 (bug fix)[3559678] [file normalize] EIAS failure (phao,dgp) 2012-08-25 (bug fix)[3561330] Ukranian translation of "March" (teterin) 2012-09-07 (TIP 404) New msgcat commands [mcflset], [mcflmset] (oehlmann) => msgcat 1.5.0 Many revisions to better support a Cygwin environment (nijtmans) Dropped support for OS X versions less than 10.4 (Tiger) (fellows) --- Released 8.6b3, September 18, 2012 --- See ChangeLog for details --- 2012-09-20 (enhancement) full Unicode support (nijtmans) => dde 1.4.0 2012-09-20 (enhancement) update bundled zlib to 1.2.7 (nijtmans) 2012-10-03 (bug fix) exit panic on stacked std channel (griffin,porter) 2012-10-14 (bug fix) [tcl::Bgerror] crash on non-dict options (nijtmans) 2012-10-16 (TIP 400) New [zlib] options to set compression dict (fellows) 2012-10-16 (TIP 405) New commands [lmap] and [dict map] (fellows) 2012-10-24 (enhancement) [dict unset] now bytecompiled (fellows) 2012-11-05 (TIP 413) Revisions to default [string trim*] trimset (nijtmans) *** POTENTIAL INCOMPATIBILITY *** 2012-11-05 (enhancement) Now bytecompiled: [array exists], [array set], [array unset], [dict create], [dict exists], [dict merge], [format], [info commands], [info coroutine], [info level], [info object], [namespace current], [namespace code], [namespace qualifiers], [namespace tail], [namespace which], [regsub], [self], [string first], [string last], [string map], [string range], [tailcall], [yield]. (fellows) 2012-11-06 (bug fix)[3581754] avoid multiple callback on keep-alive (fellows) => http 2.8.5 2012-11-07 tzdata updated to Olson's tzdata2012i (kenny) 2012-11-13 (bug fix)[3567063] thread fp settings from master (mistachkin) 2012-11-14 (bug fix)[2933003] tempfile creation in $TMPDIR (fellows) 2012-11-15 (TIP 416) New [load] options -global and -lazy (nijtmans) 2012-11-20 (bug fix)[3033307] base64 trail whitespace (kovalenko,goth) 2012-12-03 (bug fix) [configure] query broke init from argv (porter) => tcltest 2.3.5 2012-12-13 (bug fix)[3595576] crash: [catch {} -> noSuchNs::var] (sofer,porter) 2012-12-13 (bug fix) crash: [zlib gunzip $data -header noSuchNs::var] (porter) --- Released 8.6.0, December 20, 2012 --- See ChangeLog for details --- 2012-12-22 (bug fix)[3598150] DString to Tcl_Obj memleak (afredd) 2012-12-27 (bug fix)[3598580] Tcl_ListObjReplace() refcount fix (nijtmans) 2013-01-04 (bug fix) memleak in [format] compiler (fellows) 2013-01-08 (bug fix)[3092089,3587096] [file normalize] on junction points 2013-01-09 (bug fix)[3599395] status line processing (nijtmans) 2013-01-23 (bug fix)[2911139] repair async connection management (fellows) => http 2.8.6 2013-01-26 (bug fix)[3601804] Darwin segfault platformCPUID (nijtmans) 2013-01-28 (enhancement) improve ensemble bytecode (fellows) 2013-01-30 (enhancement) selected script code improvements (fradin) => tcltest 2.3.6 2013-01-30 (bug fix)[3599098] update to handle glibc banner changes (kupries) => platform 1.0.11 2013-01-31 (bug fix)[3598282] make install DESTDIR support (cassoff) 2013-02-05 (bug fix)[3603434] [file normalize a:/] flaw in VFS (porter,griffin) 2013-02-09 (bug fix)[3603695] $obj varname resolution rules (venable,fellows) 2013-02-11 (bug fix)[3603553] zlib flushing errors (vampiera,fellows) 2013-02-14 (bug fix)[3604576] msgcat use of Windows registry (oehlmann,nijtmans) => msgcat 1.5.1 2013-02-19 (bug fix)[2438181] report errors in trace handlers (yorick) 2013-02-21 (bug fix)[3605447] unbreak [namespace export -clear] (porter) 2013-02-23 (bug fix)[3599194] fallback IPv6 routines (afredd,max) 2013-02-27 (bug fix)[3606139] stop crash in [regexp] (lane) 2013-03-03 (bug fix)[3606258] major serial port update (english) 2013-03-06 (bug fix)[3606683] [regexp (((((a)*)*)*)*)* {}] hangs (grathwohl,lane,porter) 2013-03-12 (enhancement) better build support for Debian arch (shadura) 2013-03-19 (bug fix)[2893771] [file stat] on locked files (thoyts,nijtmans) 2013-03-21 (bug fix)[2102614] [auto_mkindex] ensemble support (griffin) 2013-03-27 Tcl_Zlib*() routines tolerate NULL interps (porter 2013-04-04 (bug fix) Support URLs with query but no path (max) => http 2.8.7 2013-04-08 (bug fix)[3610026] regexp crash on color overflow (linnakangas) 2013-04-29 (enhancement) [array set] compile improvement (fellows) 2013-04-30 (enhancement) broaden glibc version detection (kupries) => platform 1.0.12 2013-05-06 (platform support) Cygwin64 (nijtmans) 2013-05-15 (enhancement) Improved [list {*}...] compile (fellows) 2013-05-16 (platform support) mingw-4.0 (nijtmans) 2013-05-19 (platform support) FreeBSD updates (cerutti) 2013-05-20 (bug fix)[3613567] access error temp file creation (keene) 2013-05-20 (bug fix)[3613569] temp file open fail can crash [load] (keene) 2013-05-22 (bug fix)[3613609] [lsort -nocase] failed on non-ASCII (fellows) 2013-05-28 (bug fix)[3036566] Use language packs (Vista+) locale (oehlmann) => msgcat 1.5.2 2013-05-29 (bug fix)[3614102] [apply {{} {list [if 1]}}] stack woes (porter) 2013-06-03 Restored lost performance appending to long strings (elby,porter) 2013-06-05 (bug fix)[2835313] [while 1 {foo [continue]}] crash (fellows) 2013-06-17 (bug fix)[a876646] [:cntrl:] includes \x00 to \x1f (nijtmans) 2013-06-27 (bug fix)[983509] missing encodings for config values (nijtmans) 2013-06-27 (bug fix)[34538b] apply DST in 2099 (lang) 2013-07-02 (bug fix)[32afa6] corrected dirent64 check (griffin) 2013-07-06 tzdata updated to Olson's tzdata2013d (kenny) 2013-07-10 (bug fix)[86fb5e] [info frame] in compiled ensembles (porter) 2013-07-18 (bug fix)[1c17fb] revisd syntax errorinfo that shows error (porter) 2013-07-26 (bug fix)[6585b2] regexp {(\w).*?\1} abb (lane) 2013-07-29 [string is space \u202f] => 1 (nijtmans) 2013-08-01 [a0bc85] Limited support for fork with threads (for Rivet) (nijtmans) 2013-08-01 (bug fix)[1905562] RE recursion limit increased to support reported usage of large expressions (porter) 2013-08-02 (bug fix)[9d6162] superclass slot empty crash (vdgoot,fellows) 2013-08-03 (enhancement)[3611643] [auto_mkindex] support TclOO (fellows) 2013-08-14 (bug fix)[a16752] Missing command delete callbacks (porter) 2013-08-15 (bug fix)[3610404] reresolve traced forwards (porter) 2013-08-15 Errors from execution traces become errors of the command (porter) 2013-08-23 (bug fix)[8ff0cb9] Tcl_NR*Eval*() schedule only, as doc'd (porter) 2013-08-29 (bug fix)[2486550] enable [interp invokehidden {} yield] (porter) 2013-09-01 (bug fix)[b98fa55] [binary decode] fail on whitespace (reche,fellows) 2013-09-07 (bug fix)[86ceb4] have tm path favor first provider (neumann,porter) 2013-09-09 (bug fix)[3609693] copied object member variable confusion (fellows) => TclOO 1.0.1 2013-09-17 (bug fix)[2152292] [binary encode uuencode] corrected (fellows) 2013-09-19 (bug fix)[3487626] segfaults in [dict] compilers (porter) 2013-09-19 (bug fix)[31661d2] mem leak in [lreplace] (ade,porter) Many optmizations, improvements, and tightened stack management in bytecode. --- Released 8.6.1, September 20, 2013 --- http://core.tcl.tk/tcl/ for details 2013-09-27 (enhancement) improved ::env synchronization (fellows) 2013-10-20 (bug fix)[2835313] segfault from [apply {{} {while 1 {a {*}[return -level 0 -code continue]}}}] (fellows) 2013-10-22 (bug fix)[3556215] [scan %E%G%X] support (fellows) 2013-10-25 (bug fix)[3eb2ec1] upper case scheme names in url. (nijtmans) => http 2.8.8 2013-10-29 (bug fix)[414d103] HP-UX: restore [exec] in threaded Tcl (nijtmans) 2013-11-04 (bug fix) C++ friendly stubs struct declarations (nijtmans) 2013-11-05 (bug fix)[426679e] OpenBSD man page rendering (nijtmans) 2013-11-12 (bug fix)[5425f2c] [fconfigure -error] breaks [socket -async] 2013-11-20 (bug fix) Improved environment variable management (nijtmans) => tcltest 2.3.7 2013-11-21 (platforms) Support for Windows 8.1 (nijtmans) 2013-12-06 (RFE) improved [foreach] bytecode (fellows) 2013-12-10 (RFE) improved [lmap] bytecode (sofer) 2013-12-11 (RFE) improved [catch] bytecode (sofer) 2013-12-18 (bug fix)[0b874c3] SEGV [coroutine X coroutine Y info frame] (porter) 2013-12-20 (RFE) reduced numeric conversion in bytecode (sofer) 2014-01-07 (RFE) compilers for [concat], [linsert], [namespace origin], [next], [string replace], [string tolower], [string totitle], [string toupper], [string trim], [string trimleft], [string trimright] (fellows) 2014-01-22 (RFE) compilers for [nextto], [yieldto] (fellows) 2014-02-02 (RFE) compiler for [string is] (fellows) 2014-02-06 (bug fix)[a4494e2] panic in test namespace-13.2 (porter) 2014-03-20 (bug fix)[2f7cbd0] FreeBSD 10.0 build failure (nijtmans) 2014-03-26 (RFE)[b42b208] Cygwin: [file attr -readonly -archive -hidden -system] (nijtmans) 2014-03-27 (bug fix) segfault iocmd-23.11 (porter) 2014-04-02 (bug fix)[581937a] Win: readable event on async connect failure 2014-04-04 (bug fix)[581937a,97069ea] async socket connect fail (oehlmann) 2014-04-10 (bug fix)[792641f] Win: no \ in normalized path (nijtmans) 2014-04-11 (bug fix)[3118489] protect NUL in filenames (nijtmans) 2014-04-15 (bug fix)[88aef05] segfault iocmd-21.20 (porter) 2014-04-16 (update) Win: use Winsock 2.2 (nijtmans) 2014-04-16 (bug fix)[d19a30d] segfault clock-67.[23] (sebres) 2014-04-21 (bug fix) segfault iocmd-21.2[12] (porter) 2014-04-22 (bug fix) segfault iogt-2.4 (porter) 2014-04-23 (bug fix)[3493120] memleak in thread exit 2014-05-08 refactoring of core I/O functions (porter) 2014-05-09 (bug fix)[3389978] Win: extended paths support (nijtmans) 2014-05-09 (bug fix) segfault iocmd-32.1 (porter) 2014-05-11 (bug fix)[6d2f249] nested ensemble compile failure (fellows) 2014-05-17 (RFE)[47d6625] wideint support in [lsearch -integer] [lsort -integer] (nijtmans) *** POTENTIAL INCOMPATIBILITY *** 2014-05-20 (bug fix) Stop eof and blocked state leaking thru stacks (porter) *** POTENTIAL INCOMPATIBILITY *** 2014-05-20 (bug fix)[13d3af3] Win: socket -async tried only first IP address 2014-05-28 (platforms) work around systems that fail when a shared library is deleted after it is [load]ed (kupries) 2014-05-31 (bug fix) chan events on pipes must be on proper ends (porter) 2014-06-04 (bug fix) socket-2.12 (porter) 2014-06-05 (bug fix) io-12.6 (kupries,porter) 2014-06-15 (RFE)[1b0266d] [dict replace|remove] return canonical dict (fellows) *** POTENTIAL INCOMPATIBILITY *** 2014-06-16 (bug fix) socket-2.13 workaround broken select() (porter) 2014-06-20 (bug fix)[b47b176] iortrans.tf-11.0 (porter) 2014-06-22 (RFE)[2f9df4c] -cleanup scripts before -out compare (nijtmans) 2014-07-04 (update) Update Unicode data to 7.0 (nijtmans) *** POTENTIAL INCOMPATIBILITY *** 2014-07-08 (bug) [chan push] converts blocked writes to error (aspect,porter) 2014-07-10 (bug fix)[7368d2] memleak Tcl_SetVar2(..,TCL_APPEND_VALUE) (porter) *** POTENTIAL INCOMPATIBILITY *** 2014-07-11 (bug) leaks in SetFsPathFromAny, [info frame] (porter) 2014-07-15 (bug) compress dict leak in zlib xform channel close (porter) 2014-07-17 (bug fix)[9969cf8] leak trace data in coroutine deletion (porter) 2014-07-18 (RFE)[b43f2b4] fix [lappend] multi performance collapse (fellows) 2014-07-19 (bug fix)[75b8433] memleak managing oo instance lists (porter) 2014-07-21 (bug fix)[e6477e1] memleak in AtForkChild() (porter) 2014-07-22 (bug fix)[12b0997] memleak in iocmd.tf-32.0 (porter) 2014-07-28 (RFE) Optimized binary [chan copy] by moving buffers (porter) 2014-07-30 (enhancement) use refcounts, not Tcl_Preserve to manage lifetime of Tcl_Channel (porter) *** POTENTIAL INCOMPATIBILITY *** 2014-07-31 (bug fix)[a84a720] double free in oo chain deletion (porter) 2014-08-01 (bug fix)[e75faba] SEGV [apply {{} {namespace upvar a b [x]}}] (porter) 2014-08-01 (update) "macosx*-i386-x86_64" "macosx-universal" no longer compatible (kupries) => platform 1.0.13 2014-08-12 tzdata updated to Olson's tzdata2014f (kenny) 2014-08-17 (bug fix)[7d52e11] [info class subclasses oo::object] should include ::oo::class (fellows) 2014-08-25 (TIP 429) New command [string cat] (leitgeb,ferrieux) --- Released 8.6.2, August 27, 2014 --- http://core.tcl.tk/tcl/ for details 2014-08-28 (bug)[b9e1a3] Correct Method Search Order (nadkarni,fellows) => TclOO 1.0.3 *** POTENTIAL INCOMPATIBILITY *** 2014-09-05 (bug)[ccc2c2] Regression [lreplace {} 1 1] (bron,fellows) 2014-09-08 (bug) Crash regression in [oo::class destroy] (porter) 2014-09-09 (bug)[84af11] Regress [regsub -all {\(.*} a(b) {}] (fellows) 2014-09-10 (bug)[cee90e] [try {} on ok {} - on return {} {}] panic (porter) 2014-09-20 (feature) [tcl::unsupported::getbytecode] disassember (fellows) 2014-09-27 (enhancement) [string cat] bytecode optimization (leitgeb,ferrieux) 2014-09-27 (bug)[82521b] segfault in mangled bytecode (ogilvie,sofer) 2014-10-02 (bug)[bc5b79] Hang in some [read]s of limited size (rogers,porter) 2014-10-03 (bug)[bc1a96] segfault in [array set] of traced array (tab,porter) 2014-10-08 (bug)[59a2e7] MSVC14 compile support (dower,nijtmans) 2014-10-10 (bug)[ed29c4] [fcopy] treats [blocked] as error (rowen,porter) 2014-10-10 (bug)[bf7135] regression in Tcl_Write() interface (porter) 2014-10-18 (bug)[10dc6d] fix [gets] on non-blocking channels (fassel,porter) 2014-10-26 Support for Windows 10 (nijtmans) 2014-10-31 (bug)[dcc034] restore [open comX: r+] (lll,nijtmans) 2014-11-05 (bug)[214cc0] Restore [lappend v] return value (sayers,porter) 2014-11-06 (bug)[5adc35] Stop forcing EOF to be permanent (porter) --- Released 8.6.3, November 12, 2014 --- http://core.tcl.tk/tcl/ for details 2014-11-21 (bug)[743338] Win: socket error encoding (ladayaroslav,nijtmans) 2014-12-01 (bug) restore tbcload/tclcompiler support (kupries) 2014-12-03 (bug)[0c043a] Fix compiled [set var($) val] (porter) 2014-12-04 (bug)[d2ffcc] Limit $... and bareword parsing to ASCII (ladayaroslav,porter) *** POTENTIAL INCOMPATIBILITY *** 2014-12-06 (bug)[c6cd4a] Win: hang in async socket connection (shults,nadkarni) 2014-12-10 tzdata updated to Olson's tzdata2014j (venkat) 2014-12-13 fix header files installation on OS X (houben) 2014-12-17 (TIP 427) [fconfigure $h -connecting, -peername, -sockname] (oehlmann,rmax) 2014-12-18 (bug)[af08c8] Crash in full finalize encoding teardown (porter) 2014-12-18 (bug)[7c187a] [chan copy] crash (io-53.17) (benno,porter) 2015-01-26 (bug)[df0848] Trouble with INFINITY macro (dower,nijtmans) 2015-01-29 (bug) Stop crashes when extension var resolvers misbehave (porter) 2015-01-29 (bug)[088727] [read] past EOF (io-73.4) (fenugrec,porter) 2015-02-11 tzdata updated to Olson's tzdata2015a (venkat) 2015-02-20 (bug)[32b615] Fix compiled [lreplace] (lreplace-4.[345]) (aspect) 2015-03-10 (enhancement) Revise OS X notifier for better Cocoa (walzer) *** POTENTIAL INCOMPATIBILITY *** --- Released 8.6.4, March 12, 2015 --- http://core.tcl.tk/tcl/ for details 2015-03-19 (bug)[e66e44] Win: Ctrl-C/Ctrl-Break in console not EOF (nadkarni) 2015-03-21 (bug)[d87cb1] Proper tailcall from compiled ensembles (sofer) 2015-04-23 (bug)[19ea02] Win: shared read from linked dirs (bogdan,oehhar) 2015-04-24 (bug)[879a07] Incomplete chars @ buffer ends (leunissen,porter) 2015-04-29 (bug)[894da1] Hang flushing blocking channels (yorick) 2015-05-14 (enhance)[b9d043] Default use of gzip transfer encoding (fellows) => http 2.8.9 *** POTENTIAL INCOMPATIBILITY *** 2015-05-15 (bug)[9dd1bd] destructor [self] after failed constructor (calvo,fellows) 2015-05-15 (bug)[0f42ff] [tailcall] combined with [next] (aspect,fellows) 2015-05-18 (bug)[c11a51] http: race condition in -accept option (fellows) 2015-05-19 (enhance) More pure lists from compiled [list] (porter,fellows) 2015-05-27 (enhancement) Relax memdebug constraint on extensions (kupries) 2015-06-03 (bug)[268b23] crash in traced [expr] (execute-11.2)(tomkinson,porter) 2015-06-11 (bug)[478c44] Memleak in zlib compresion errors (mistachkin) 2015-06-16 (bug)[e770d9] Higher baud on serial channels (woods,nijtmans) 2015-06-18 (update) Update Unicode data to 8.0 (nijtmans) *** POTENTIAL INCOMPATIBILITY *** 2015-06-18 (bug)[a4cb3f] compiled [lreplace] handling of end (bron,aspect) 2015-06-23 (enhance) Use Unicode SendMessageTimeout() (nijtmans) => registry 1.3.1 2015-06-25 (TIP 412) msgcat dynamic locale change and package private locale (oehlmann) => msgcat 1.6.0 2015-07-05 (bug)[a0ece9] crash in traced [expr] (execute-11.3) (hans,porter) 2015-07-10 (TIP 436) [info object isa] favors 'false' over error (fellows) => TclOO 1.0.4 2015-07-15 (bug)[b1534b][9bad63] writes beyond buffer bounds (hanno,porter) 2015-07-18 (bug)[a3309d] Memleak in compiled [unset a($i)] (jeff,porter) 2015-07-23 (bug)[57945b] lock in forking/multi-threading (neumann,mistachkin) 2015-07-29 (bug)[3e7eca] Allocation overflow in expr parsing (rickyb,porter) 2015-07-30 (bug)[f00009] Win: Memleak in [file] (rp,sebres) 2015-07-31 (bug) Correct problems found in Coverity audit (sofer) 2015-08-19 (bug)[00189c] MSVC 14: semi-static UCRT support (dower,nijtmans) 2015-08-26 (bug)[0df7a1] Tolerate getcwd() failures (cato,nijtmans) 2015-09-21 (bug)[1115587][a3c350][d7ea9f][0e0e15][187d7f] Many fixes and improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich) 2015-09-23 (enhance) hash lookup microoptimization (hipp) 2015-09-23 (bug)[e0a7b3] Input buffer draining & file events (griffin,porter) 2015-09-29 (bug)[219866] Cygwin support error (yorick,nijtmans) => platform 1.0.14 2015-10-06 (bug)[b42a85] Win: [file normalize ~user] wrong dir (nadkarni) 2015-10-21 (bug)[1080042][8f2450] More regexp from Postgres (lane,porter) 2015-10-23 (bug)[4a0c16] [clock] react to msgcat locale change (oehlmann) 2015-11-10 (bug)[261a8a] Overflow segfault in I/O translation (brooks,porter) 2015-11-20 (bug)[40f628] ListObjReplace callers fail to detect max (porter) 2015-11-30 (enhance)[32c574] Improve list growth performance (brooks,porter) 2015-12-11 (bug)[c9eb6b] tolerate unset ::env(TZ) (gahr, nijtmans) 2016-01-29 (TIP 440) tcl_platform(engine) -- Tcl implementation (mistachkin) 2016-02-03 (bug)[25842c] stream [zlib deflate] fails with 0 input (ade,fellows) 2016-02-04 (bug)[3d96b7][593baa][cf74de] crashes in OO teardown (porter,fellows) 2016-02-22 (bug)[9b4702] [info exists env(missing)] kills trace (nijtmans) --- Released 8.6.5, February 29, 2016 --- http://core.tcl.tk/tcl/ for details tcl8.6.5/compat/0000755000175000017500000000000012665173607013055 5ustar sergeisergeitcl8.6.5/compat/unistd.h0000644000175000017500000000507312663660064014535 0ustar sergeisergei/* * unistd.h -- * * Macros, constants and prototypes for Posix conformance. * * Copyright 1989 Regents of the University of California Permission to use, * copy, modify, and distribute this software and its documentation for any * purpose and without fee is hereby granted, provided that the above * copyright notice appear in all copies. The University of California makes * no representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. */ #ifndef _UNISTD #define _UNISTD #include #ifndef NULL #define NULL 0 #endif /* * Strict POSIX stuff goes here. Extensions go down below, in the ifndef * _POSIX_SOURCE section. */ extern void _exit(int status); extern int access(const char *path, int mode); extern int chdir(const char *path); extern int chown(const char *path, uid_t owner, gid_t group); extern int close(int fd); extern int dup(int oldfd); extern int dup2(int oldfd, int newfd); extern int execl(const char *path, ...); extern int execle(const char *path, ...); extern int execlp(const char *file, ...); extern int execv(const char *path, char **argv); extern int execve(const char *path, char **argv, char **envp); extern int execvpw(const char *file, char **argv); extern pid_t fork(void); extern char * getcwd(char *buf, size_t size); extern gid_t getegid(void); extern uid_t geteuid(void); extern gid_t getgid(void); extern int getgroups(int bufSize, int *buffer); extern pid_t getpid(void); extern uid_t getuid(void); extern int isatty(int fd); extern long lseek(int fd, long offset, int whence); extern int pipe(int *fildes); extern int read(int fd, char *buf, size_t size); extern int setgid(gid_t group); extern int setuid(uid_t user); extern unsigned sleep(unsigned seconds); extern char * ttyname(int fd); extern int unlink(const char *path); extern int write(int fd, const char *buf, size_t size); #ifndef _POSIX_SOURCE extern char * crypt(const char *, const char *); extern int fchown(int fd, uid_t owner, gid_t group); extern int flock(int fd, int operation); extern int ftruncate(int fd, unsigned long length); extern int ioctl(int fd, int request, ...); extern int readlink(const char *path, char *buf, int bufsize); extern int setegid(gid_t group); extern int seteuidw(uid_t user); extern int setreuid(int ruid, int euid); extern int symlink(const char *, const char *); extern int ttyslot(void); extern int truncate(const char *path, unsigned long length); extern int vfork(void); #endif /* _POSIX_SOURCE */ #endif /* _UNISTD */ tcl8.6.5/compat/dirent.h0000644000175000017500000000076612663653206014520 0ustar sergeisergei/* * dirent.h -- * * This file is a replacement for in systems that * support the old BSD-style with a "struct direct". * * Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _DIRENT #define _DIRENT #include #define dirent direct #endif /* _DIRENT */ tcl8.6.5/compat/zlib/0000755000175000017500000000000012665173607014015 5ustar sergeisergeitcl8.6.5/compat/zlib/as400/0000755000175000017500000000000012665173607014644 5ustar sergeisergeitcl8.6.5/compat/zlib/as400/compile.clp0000644000175000017500000001225312663660064016773 0ustar sergeisergei/******************************************************************************/ /* */ /* ZLIB */ /* */ /* Compile sources into modules and link them into a service program. */ /* */ /******************************************************************************/ PGM /* Configuration adjustable parameters. */ DCL VAR(&SRCLIB) TYPE(*CHAR) LEN(10) + VALUE('ZLIB') /* Source library. */ DCL VAR(&SRCFILE) TYPE(*CHAR) LEN(10) + VALUE('SOURCES') /* Source member file. */ DCL VAR(&CTLFILE) TYPE(*CHAR) LEN(10) + VALUE('TOOLS') /* Control member file. */ DCL VAR(&MODLIB) TYPE(*CHAR) LEN(10) + VALUE('ZLIB') /* Module library. */ DCL VAR(&SRVLIB) TYPE(*CHAR) LEN(10) + VALUE('LGPL') /* Service program library. */ DCL VAR(&CFLAGS) TYPE(*CHAR) + VALUE('OPTIMIZE(40)') /* Compile options. */ DCL VAR(&TGTRLS) TYPE(*CHAR) + VALUE('V5R3M0') /* Target release. */ /* Working storage. */ DCL VAR(&CMDLEN) TYPE(*DEC) LEN(15 5) VALUE(300) /* Command length. */ DCL VAR(&CMD) TYPE(*CHAR) LEN(512) DCL VAR(&FIXDCMD) TYPE(*CHAR) LEN(512) /* Compile sources into modules. */ CHGVAR VAR(&FIXDCMD) VALUE('CRTCMOD' *BCAT &CFLAGS *BCAT + 'SYSIFCOPT(*IFS64IO)' *BCAT + 'DEFINE(''_LARGEFILE64_SOURCE''' *BCAT + '''_LFS64_LARGEFILE=1'') TGTRLS(' *TCAT &TGTRLS *TCAT + ') SRCFILE(' *TCAT &SRCLIB *TCAT '/' *TCAT + &SRCFILE *TCAT ') MODULE(' *TCAT &MODLIB *TCAT '/') CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'ADLER32)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'COMPRESS)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'CRC32)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'DEFLATE)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZCLOSE)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZLIB)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZREAD)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'GZWRITE)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFBACK)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFFAST)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFLATE)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'INFTREES)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'TREES)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'UNCOMPR)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) CHGVAR VAR(&CMD) VALUE(&FIXDCMD *TCAT 'ZUTIL)') CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN) /* Link modules into a service program. */ CRTSRVPGM SRVPGM(&SRVLIB/ZLIB) + MODULE(&MODLIB/ADLER32 &MODLIB/COMPRESS + &MODLIB/CRC32 &MODLIB/DEFLATE + &MODLIB/GZCLOSE &MODLIB/GZLIB + &MODLIB/GZREAD &MODLIB/GZWRITE + &MODLIB/INFBACK &MODLIB/INFFAST + &MODLIB/INFLATE &MODLIB/INFTREES + &MODLIB/TREES &MODLIB/UNCOMPR + &MODLIB/ZUTIL) + SRCFILE(&SRCLIB/&CTLFILE) SRCMBR(BNDSRC) + TEXT('ZLIB 1.2.8') TGTRLS(&TGTRLS) ENDPGM tcl8.6.5/compat/zlib/as400/zlib.inc0000644000175000017500000006635612663660064016313 0ustar sergeisergei * ZLIB.INC - Interface to the general purpose compression library * * ILE RPG400 version by Patrick Monnerat, DATASPHERE. * Version 1.2.8 * * * WARNING: * Procedures inflateInit(), inflateInit2(), deflateInit(), * deflateInit2() and inflateBackInit() need to be called with * two additional arguments: * the package version string and the stream control structure. * size. This is needed because RPG lacks some macro feature. * Call these procedures as: * inflateInit(...: ZLIB_VERSION: %size(z_stream)) * /if not defined(ZLIB_H_) /define ZLIB_H_ * ************************************************************************** * Constants ************************************************************************** * * Versioning information. * D ZLIB_VERSION C '1.2.8' D ZLIB_VERNUM C X'1280' D ZLIB_VER_MAJOR C 1 D ZLIB_VER_MINOR C 2 D ZLIB_VER_REVISION... D C 8 D ZLIB_VER_SUBREVISION... D C 0 * * Other equates. * D Z_NO_FLUSH C 0 D Z_PARTIAL_FLUSH... D C 1 D Z_SYNC_FLUSH C 2 D Z_FULL_FLUSH C 3 D Z_FINISH C 4 D Z_BLOCK C 5 D Z_TREES C 6 * D Z_OK C 0 D Z_STREAM_END C 1 D Z_NEED_DICT C 2 D Z_ERRNO C -1 D Z_STREAM_ERROR C -2 D Z_DATA_ERROR C -3 D Z_MEM_ERROR C -4 D Z_BUF_ERROR C -5 DZ_VERSION_ERROR C -6 * D Z_NO_COMPRESSION... D C 0 D Z_BEST_SPEED C 1 D Z_BEST_COMPRESSION... D C 9 D Z_DEFAULT_COMPRESSION... D C -1 * D Z_FILTERED C 1 D Z_HUFFMAN_ONLY C 2 D Z_RLE C 3 D Z_DEFAULT_STRATEGY... D C 0 * D Z_BINARY C 0 D Z_ASCII C 1 D Z_UNKNOWN C 2 * D Z_DEFLATED C 8 * D Z_NULL C 0 * ************************************************************************** * Types ************************************************************************** * D z_streamp S * Stream struct ptr D gzFile S * File pointer D z_off_t S 10i 0 Stream offsets D z_off64_t S 20i 0 Stream offsets * ************************************************************************** * Structures ************************************************************************** * * The GZIP encode/decode stream support structure. * D z_stream DS align based(z_streamp) D zs_next_in * Next input byte D zs_avail_in 10U 0 Byte cnt at next_in D zs_total_in 10U 0 Total bytes read D zs_next_out * Output buffer ptr D zs_avail_out 10U 0 Room left @ next_out D zs_total_out 10U 0 Total bytes written D zs_msg * Last errmsg or null D zs_state * Internal state D zs_zalloc * procptr Int. state allocator D zs_free * procptr Int. state dealloc. D zs_opaque * Private alloc. data D zs_data_type 10i 0 ASC/BIN best guess D zs_adler 10u 0 Uncompr. adler32 val D 10U 0 Reserved D 10U 0 Ptr. alignment * ************************************************************************** * Utility function prototypes ************************************************************************** * D compress PR 10I 0 extproc('compress') D dest 65535 options(*varsize) Destination buffer D destLen 10U 0 Destination length D source 65535 const options(*varsize) Source buffer D sourceLen 10u 0 value Source length * D compress2 PR 10I 0 extproc('compress2') D dest 65535 options(*varsize) Destination buffer D destLen 10U 0 Destination length D source 65535 const options(*varsize) Source buffer D sourceLen 10U 0 value Source length D level 10I 0 value Compression level * D compressBound PR 10U 0 extproc('compressBound') D sourceLen 10U 0 value * D uncompress PR 10I 0 extproc('uncompress') D dest 65535 options(*varsize) Destination buffer D destLen 10U 0 Destination length D source 65535 const options(*varsize) Source buffer D sourceLen 10U 0 value Source length * /if not defined(LARGE_FILES) D gzopen PR extproc('gzopen') D like(gzFile) D path * value options(*string) File pathname D mode * value options(*string) Open mode /else D gzopen PR extproc('gzopen64') D like(gzFile) D path * value options(*string) File pathname D mode * value options(*string) Open mode * D gzopen64 PR extproc('gzopen64') D like(gzFile) D path * value options(*string) File pathname D mode * value options(*string) Open mode /endif * D gzdopen PR extproc('gzdopen') D like(gzFile) D fd 10I 0 value File descriptor D mode * value options(*string) Open mode * D gzbuffer PR 10I 0 extproc('gzbuffer') D file value like(gzFile) File pointer D size 10U 0 value * D gzsetparams PR 10I 0 extproc('gzsetparams') D file value like(gzFile) File pointer D level 10I 0 value D strategy 10I 0 value * D gzread PR 10I 0 extproc('gzread') D file value like(gzFile) File pointer D buf 65535 options(*varsize) Buffer D len 10u 0 value Buffer length * D gzwrite PR 10I 0 extproc('gzwrite') D file value like(gzFile) File pointer D buf 65535 const options(*varsize) Buffer D len 10u 0 value Buffer length * D gzputs PR 10I 0 extproc('gzputs') D file value like(gzFile) File pointer D s * value options(*string) String to output * D gzgets PR * extproc('gzgets') D file value like(gzFile) File pointer D buf 65535 options(*varsize) Read buffer D len 10i 0 value Buffer length * D gzputc PR 10i 0 extproc('gzputc') D file value like(gzFile) File pointer D c 10I 0 value Character to write * D gzgetc PR 10i 0 extproc('gzgetc') D file value like(gzFile) File pointer * D gzgetc_ PR 10i 0 extproc('gzgetc_') D file value like(gzFile) File pointer * D gzungetc PR 10i 0 extproc('gzungetc') D c 10I 0 value Character to push D file value like(gzFile) File pointer * D gzflush PR 10i 0 extproc('gzflush') D file value like(gzFile) File pointer D flush 10I 0 value Type of flush * /if not defined(LARGE_FILES) D gzseek PR extproc('gzseek') D like(z_off_t) D file value like(gzFile) File pointer D offset value like(z_off_t) Offset D whence 10i 0 value Origin /else D gzseek PR extproc('gzseek64') D like(z_off_t) D file value like(gzFile) File pointer D offset value like(z_off_t) Offset D whence 10i 0 value Origin * D gzseek64 PR extproc('gzseek64') D like(z_off64_t) D file value like(gzFile) File pointer D offset value like(z_off64_t) Offset D whence 10i 0 value Origin /endif * D gzrewind PR 10i 0 extproc('gzrewind') D file value like(gzFile) File pointer * /if not defined(LARGE_FILES) D gztell PR extproc('gztell') D like(z_off_t) D file value like(gzFile) File pointer /else D gztell PR extproc('gztell64') D like(z_off_t) D file value like(gzFile) File pointer * D gztell64 PR extproc('gztell64') D like(z_off64_t) D file value like(gzFile) File pointer /endif * /if not defined(LARGE_FILES) D gzoffset PR extproc('gzoffset') D like(z_off_t) D file value like(gzFile) File pointer /else D gzoffset PR extproc('gzoffset64') D like(z_off_t) D file value like(gzFile) File pointer * D gzoffset64 PR extproc('gzoffset64') D like(z_off64_t) D file value like(gzFile) File pointer /endif * D gzeof PR 10i 0 extproc('gzeof') D file value like(gzFile) File pointer * D gzclose_r PR 10i 0 extproc('gzclose_r') D file value like(gzFile) File pointer * D gzclose_w PR 10i 0 extproc('gzclose_w') D file value like(gzFile) File pointer * D gzclose PR 10i 0 extproc('gzclose') D file value like(gzFile) File pointer * D gzerror PR * extproc('gzerror') Error string D file value like(gzFile) File pointer D errnum 10I 0 Error code * D gzclearerr PR extproc('gzclearerr') D file value like(gzFile) File pointer * ************************************************************************** * Basic function prototypes ************************************************************************** * D zlibVersion PR * extproc('zlibVersion') Version string * D deflateInit PR 10I 0 extproc('deflateInit_') Init. compression D strm like(z_stream) Compression stream D level 10I 0 value Compression level D version * value options(*string) Version string D stream_size 10i 0 value Stream struct. size * D deflate PR 10I 0 extproc('deflate') Compress data D strm like(z_stream) Compression stream D flush 10I 0 value Flush type required * D deflateEnd PR 10I 0 extproc('deflateEnd') Termin. compression D strm like(z_stream) Compression stream * D inflateInit PR 10I 0 extproc('inflateInit_') Init. expansion D strm like(z_stream) Expansion stream D version * value options(*string) Version string D stream_size 10i 0 value Stream struct. size * D inflate PR 10I 0 extproc('inflate') Expand data D strm like(z_stream) Expansion stream D flush 10I 0 value Flush type required * D inflateEnd PR 10I 0 extproc('inflateEnd') Termin. expansion D strm like(z_stream) Expansion stream * ************************************************************************** * Advanced function prototypes ************************************************************************** * D deflateInit2 PR 10I 0 extproc('deflateInit2_') Init. compression D strm like(z_stream) Compression stream D level 10I 0 value Compression level D method 10I 0 value Compression method D windowBits 10I 0 value log2(window size) D memLevel 10I 0 value Mem/cmpress tradeoff D strategy 10I 0 value Compression stategy D version * value options(*string) Version string D stream_size 10i 0 value Stream struct. size * D deflateSetDictionary... D PR 10I 0 extproc('deflateSetDictionary') Init. dictionary D strm like(z_stream) Compression stream D dictionary 65535 const options(*varsize) Dictionary bytes D dictLength 10U 0 value Dictionary length * D deflateCopy PR 10I 0 extproc('deflateCopy') Compress strm 2 strm D dest like(z_stream) Destination stream D source like(z_stream) Source stream * D deflateReset PR 10I 0 extproc('deflateReset') End and init. stream D strm like(z_stream) Compression stream * D deflateParams PR 10I 0 extproc('deflateParams') Change level & strat D strm like(z_stream) Compression stream D level 10I 0 value Compression level D strategy 10I 0 value Compression stategy * D deflateBound PR 10U 0 extproc('deflateBound') Change level & strat D strm like(z_stream) Compression stream D sourcelen 10U 0 value Compression level * D deflatePending PR 10I 0 extproc('deflatePending') Change level & strat D strm like(z_stream) Compression stream D pending 10U 0 Pending bytes D bits 10I 0 Pending bits * D deflatePrime PR 10I 0 extproc('deflatePrime') Change level & strat D strm like(z_stream) Compression stream D bits 10I 0 value # of bits to insert D value 10I 0 value Bits to insert * D inflateInit2 PR 10I 0 extproc('inflateInit2_') Init. expansion D strm like(z_stream) Expansion stream D windowBits 10I 0 value log2(window size) D version * value options(*string) Version string D stream_size 10i 0 value Stream struct. size * D inflateSetDictionary... D PR 10I 0 extproc('inflateSetDictionary') Init. dictionary D strm like(z_stream) Expansion stream D dictionary 65535 const options(*varsize) Dictionary bytes D dictLength 10U 0 value Dictionary length * D inflateGetDictionary... D PR 10I 0 extproc('inflateGetDictionary') Get dictionary D strm like(z_stream) Expansion stream D dictionary 65535 options(*varsize) Dictionary bytes D dictLength 10U 0 Dictionary length * D inflateSync PR 10I 0 extproc('inflateSync') Sync. expansion D strm like(z_stream) Expansion stream * D inflateCopy PR 10I 0 extproc('inflateCopy') D dest like(z_stream) Destination stream D source like(z_stream) Source stream * D inflateReset PR 10I 0 extproc('inflateReset') End and init. stream D strm like(z_stream) Expansion stream * D inflateReset2 PR 10I 0 extproc('inflateReset2') End and init. stream D strm like(z_stream) Expansion stream D windowBits 10I 0 value Log2(buffer size) * D inflatePrime PR 10I 0 extproc('inflatePrime') Insert bits D strm like(z_stream) Expansion stream D bits 10I 0 value Bit count D value 10I 0 value Bits to insert * D inflateMark PR 10I 0 extproc('inflateMark') Get inflate info D strm like(z_stream) Expansion stream * D inflateBackInit... D PR 10I 0 extproc('inflateBackInit_') D strm like(z_stream) Expansion stream D windowBits 10I 0 value Log2(buffer size) D window 65535 options(*varsize) Buffer D version * value options(*string) Version string D stream_size 10i 0 value Stream struct. size * D inflateBack PR 10I 0 extproc('inflateBack') D strm like(z_stream) Expansion stream D in * value procptr Input function D in_desc * value Input descriptor D out * value procptr Output function D out_desc * value Output descriptor * D inflateBackEnd PR 10I 0 extproc('inflateBackEnd') D strm like(z_stream) Expansion stream * D zlibCompileFlags... D PR 10U 0 extproc('zlibCompileFlags') * ************************************************************************** * Checksum function prototypes ************************************************************************** * D adler32 PR 10U 0 extproc('adler32') New checksum D adler 10U 0 value Old checksum D buf 65535 const options(*varsize) Bytes to accumulate D len 10U 0 value Buffer length * D crc32 PR 10U 0 extproc('crc32') New checksum D crc 10U 0 value Old checksum D buf 65535 const options(*varsize) Bytes to accumulate D len 10U 0 value Buffer length * ************************************************************************** * Miscellaneous function prototypes ************************************************************************** * D zError PR * extproc('zError') Error string D err 10I 0 value Error code * D inflateSyncPoint... D PR 10I 0 extproc('inflateSyncPoint') D strm like(z_stream) Expansion stream * D get_crc_table PR * extproc('get_crc_table') Ptr to ulongs * D inflateUndermine... D PR 10I 0 extproc('inflateUndermine') D strm like(z_stream) Expansion stream D arg 10I 0 value Error code * D inflateResetKeep... D PR 10I 0 extproc('inflateResetKeep') End and init. stream D strm like(z_stream) Expansion stream * D deflateResetKeep... D PR 10I 0 extproc('deflateResetKeep') End and init. stream D strm like(z_stream) Expansion stream * /endif tcl8.6.5/compat/zlib/as400/readme.txt0000644000175000017500000001157712663660064016651 0ustar sergeisergei ZLIB version 1.2.8 for AS400 installation instructions I) From an AS400 *SAVF file: 1) Unpacking archive to an AS400 save file On the AS400: _ Create the ZLIB AS400 library: CRTLIB LIB(ZLIB) TYPE(*PROD) TEXT('ZLIB compression API library') _ Create a work save file, for example: CRTSAVF FILE(ZLIB/ZLIBSAVF) On a PC connected to the target AS400: _ Unpack the save file image to a PC file "ZLIBSAVF" _ Upload this file into the save file on the AS400, for example using ftp in BINARY mode. 2) Populating the ZLIB AS400 source library On the AS400: _ Extract the saved objects into the ZLIB AS400 library using: RSTOBJ OBJ(*ALL) SAVLIB(ZLIB) DEV(*SAVF) SAVF(ZLIB/ZLIBSAVF) RSTLIB(ZLIB) 3) Customize installation: _ Edit CL member ZLIB/TOOLS(COMPILE) and change parameters if needed, according to the comments. _ Compile this member with: CRTCLPGM PGM(ZLIB/COMPILE) SRCFILE(ZLIB/TOOLS) SRCMBR(COMPILE) 4) Compile and generate the service program: _ This can now be done by executing: CALL PGM(ZLIB/COMPILE) II) From the original source distribution: 1) On the AS400, create the source library: CRTLIB LIB(ZLIB) TYPE(*PROD) TEXT('ZLIB compression API library') 2) Create the source files: CRTSRCPF FILE(ZLIB/SOURCES) RCDLEN(112) TEXT('ZLIB library modules') CRTSRCPF FILE(ZLIB/H) RCDLEN(112) TEXT('ZLIB library includes') CRTSRCPF FILE(ZLIB/TOOLS) RCDLEN(112) TEXT('ZLIB library control utilities') 3) From the machine hosting the distribution files, upload them (with FTP in text mode, for example) according to the following table: Original AS400 AS400 AS400 AS400 file file member type description SOURCES Original ZLIB C subprogram sources adler32.c ADLER32 C ZLIB - Compute the Adler-32 checksum of a dta strm compress.c COMPRESS C ZLIB - Compress a memory buffer crc32.c CRC32 C ZLIB - Compute the CRC-32 of a data stream deflate.c DEFLATE C ZLIB - Compress data using the deflation algorithm gzclose.c GZCLOSE C ZLIB - Close .gz files gzlib.c GZLIB C ZLIB - Miscellaneous .gz files IO support gzread.c GZREAD C ZLIB - Read .gz files gzwrite.c GZWRITE C ZLIB - Write .gz files infback.c INFBACK C ZLIB - Inflate using a callback interface inffast.c INFFAST C ZLIB - Fast proc. literals & length/distance pairs inflate.c INFLATE C ZLIB - Interface to inflate modules inftrees.c INFTREES C ZLIB - Generate Huffman trees for efficient decode trees.c TREES C ZLIB - Output deflated data using Huffman coding uncompr.c UNCOMPR C ZLIB - Decompress a memory buffer zutil.c ZUTIL C ZLIB - Target dependent utility functions H Original ZLIB C and ILE/RPG include files crc32.h CRC32 C ZLIB - CRC32 tables deflate.h DEFLATE C ZLIB - Internal compression state gzguts.h GZGUTS C ZLIB - Definitions for the gzclose module inffast.h INFFAST C ZLIB - Header to use inffast.c inffixed.h INFFIXED C ZLIB - Table for decoding fixed codes inflate.h INFLATE C ZLIB - Internal inflate state definitions inftrees.h INFTREES C ZLIB - Header to use inftrees.c trees.h TREES C ZLIB - Created automatically with -DGEN_TREES_H zconf.h ZCONF C ZLIB - Compression library configuration zlib.h ZLIB C ZLIB - Compression library C user interface as400/zlib.inc ZLIB.INC RPGLE ZLIB - Compression library ILE RPG user interface zutil.h ZUTIL C ZLIB - Internal interface and configuration TOOLS Building source software & AS/400 README as400/bndsrc BNDSRC Entry point exportation list as400/compile.clp COMPILE CLP Compile sources & generate service program as400/readme.txt README TXT Installation instructions 4) Continue as in I)3). Notes: For AS400 ILE RPG programmers, a /copy member defining the ZLIB API prototypes for ILE RPG can be found in ZLIB/H(ZLIB.INC). Please read comments in this member for more information. Remember that most foreign textual data are ASCII coded: this implementation does not handle conversion from/to ASCII, so text data code conversions must be done explicitely. Mainly for the reason above, always open zipped files in binary mode. tcl8.6.5/compat/zlib/as400/bndsrc0000644000175000017500000002044512663660064016043 0ustar sergeisergeiSTRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB') /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ /* Version 1.1.3 entry points. */ /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ /********************************************************************/ /* *MODULE ADLER32 ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("adler32") /********************************************************************/ /* *MODULE COMPRESS ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("compress") EXPORT SYMBOL("compress2") /********************************************************************/ /* *MODULE CRC32 ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("crc32") EXPORT SYMBOL("get_crc_table") /********************************************************************/ /* *MODULE DEFLATE ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("deflate") EXPORT SYMBOL("deflateEnd") EXPORT SYMBOL("deflateSetDictionary") EXPORT SYMBOL("deflateCopy") EXPORT SYMBOL("deflateReset") EXPORT SYMBOL("deflateParams") EXPORT SYMBOL("deflatePrime") EXPORT SYMBOL("deflateInit_") EXPORT SYMBOL("deflateInit2_") /********************************************************************/ /* *MODULE GZIO ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("gzopen") EXPORT SYMBOL("gzdopen") EXPORT SYMBOL("gzsetparams") EXPORT SYMBOL("gzread") EXPORT SYMBOL("gzwrite") EXPORT SYMBOL("gzprintf") EXPORT SYMBOL("gzputs") EXPORT SYMBOL("gzgets") EXPORT SYMBOL("gzputc") EXPORT SYMBOL("gzgetc") EXPORT SYMBOL("gzflush") EXPORT SYMBOL("gzseek") EXPORT SYMBOL("gzrewind") EXPORT SYMBOL("gztell") EXPORT SYMBOL("gzeof") EXPORT SYMBOL("gzclose") EXPORT SYMBOL("gzerror") /********************************************************************/ /* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("inflate") EXPORT SYMBOL("inflateEnd") EXPORT SYMBOL("inflateSetDictionary") EXPORT SYMBOL("inflateSync") EXPORT SYMBOL("inflateReset") EXPORT SYMBOL("inflateInit_") EXPORT SYMBOL("inflateInit2_") EXPORT SYMBOL("inflateSyncPoint") /********************************************************************/ /* *MODULE UNCOMPR ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("uncompress") /********************************************************************/ /* *MODULE ZUTIL ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("zlibVersion") EXPORT SYMBOL("zError") /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ /* Version 1.2.1 additional entry points. */ /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ /********************************************************************/ /* *MODULE COMPRESS ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("compressBound") /********************************************************************/ /* *MODULE DEFLATE ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("deflateBound") /********************************************************************/ /* *MODULE GZIO ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("gzungetc") EXPORT SYMBOL("gzclearerr") /********************************************************************/ /* *MODULE INFBACK ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("inflateBack") EXPORT SYMBOL("inflateBackEnd") EXPORT SYMBOL("inflateBackInit_") /********************************************************************/ /* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("inflateCopy") /********************************************************************/ /* *MODULE ZUTIL ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("zlibCompileFlags") /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ /* Version 1.2.5 additional entry points. */ /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ /********************************************************************/ /* *MODULE ADLER32 ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("adler32_combine") EXPORT SYMBOL("adler32_combine64") /********************************************************************/ /* *MODULE CRC32 ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("crc32_combine") EXPORT SYMBOL("crc32_combine64") /********************************************************************/ /* *MODULE GZLIB ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("gzbuffer") EXPORT SYMBOL("gzoffset") EXPORT SYMBOL("gzoffset64") EXPORT SYMBOL("gzopen64") EXPORT SYMBOL("gzseek64") EXPORT SYMBOL("gztell64") /********************************************************************/ /* *MODULE GZREAD ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("gzclose_r") /********************************************************************/ /* *MODULE GZWRITE ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("gzclose_w") /********************************************************************/ /* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("inflateMark") EXPORT SYMBOL("inflatePrime") EXPORT SYMBOL("inflateReset2") EXPORT SYMBOL("inflateUndermine") /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ /* Version 1.2.6 additional entry points. */ /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ /********************************************************************/ /* *MODULE DEFLATE ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("deflateResetKeep") EXPORT SYMBOL("deflatePending") /********************************************************************/ /* *MODULE GZWRITE ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("gzgetc_") /********************************************************************/ /* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("inflateResetKeep") /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ /* Version 1.2.8 additional entry points. */ /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ /********************************************************************/ /* *MODULE INFLATE ZLIB 01/02/01 00:15:09 */ /********************************************************************/ EXPORT SYMBOL("inflateGetDictionary") ENDPGMEXP tcl8.6.5/compat/zlib/zlib.pc.in0000644000175000017500000000037612663653206015710 0ustar sergeisergeiprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ sharedlibdir=@sharedlibdir@ includedir=@includedir@ Name: zlib Description: zlib compression library Version: @VERSION@ Requires: Libs: -L${libdir} -L${sharedlibdir} -lz Cflags: -I${includedir} tcl8.6.5/compat/zlib/deflate.c0000644000175000017500000021346412663660065015574 0ustar sergeisergei/* deflate.c -- compress data using the deflation algorithm * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process depends on being able to identify portions * of the input text which are identical to earlier input (within a * sliding window trailing behind the input currently being processed). * * The most straightforward technique turns out to be the fastest for * most input files: try all possible matches and select the longest. * The key feature of this algorithm is that insertions into the string * dictionary are very simple and thus fast, and deletions are avoided * completely. Insertions are performed at each input character, whereas * string matches are performed only when the previous match ends. So it * is preferable to spend more time in matches to allow very fast string * insertions and avoid deletions. The matching algorithm for small * strings is inspired from that of Rabin & Karp. A brute force approach * is used to find longer strings when a small match has been found. * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze * (by Leonid Broukhis). * A previous version of this file used a more sophisticated algorithm * (by Fiala and Greene) which is guaranteed to run in linear amortized * time, but has a larger average cost, uses more memory and is patented. * However the F&G algorithm may be faster for some highly redundant * files if the parameter max_chain_length (described below) is too large. * * ACKNOWLEDGEMENTS * * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and * I found it in 'freeze' written by Leonid Broukhis. * Thanks to many people for bug reports and testing. * * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". * Available in http://tools.ietf.org/html/rfc1951 * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. * * Fiala,E.R., and Greene,D.H. * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 * */ /* @(#) $Id$ */ #include "deflate.h" const char deflate_copyright[] = " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* =========================================================================== * Function prototypes. */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ finish_started, /* finish started, need only more output at next deflate */ finish_done /* finish done, accept no more input or output */ } block_state; typedef block_state (*compress_func) OF((deflate_state *s, int flush)); /* Compression function. Returns the block state after the call. */ local void fill_window OF((deflate_state *s)); local block_state deflate_stored OF((deflate_state *s, int flush)); local block_state deflate_fast OF((deflate_state *s, int flush)); #ifndef FASTEST local block_state deflate_slow OF((deflate_state *s, int flush)); #endif local block_state deflate_rle OF((deflate_state *s, int flush)); local block_state deflate_huff OF((deflate_state *s, int flush)); local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifdef ASMV void match_init OF((void)); /* asm code initialization */ uInt longest_match OF((deflate_state *s, IPos cur_match)); #else local uInt longest_match OF((deflate_state *s, IPos cur_match)); #endif #ifdef DEBUG local void check_match OF((deflate_state *s, IPos start, IPos match, int length)); #endif /* =========================================================================== * Local data */ #define NIL 0 /* Tail of hash chains */ #ifndef TOO_FAR # define TOO_FAR 4096 #endif /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ /* Values for max_lazy_match, good_match and max_chain_length, depending on * the desired pack level (0..9). The values given below have been tuned to * exclude worst case performance for pathological files. Better values may be * found for specific files. */ typedef struct config_s { ush good_length; /* reduce lazy search above this match length */ ush max_lazy; /* do not perform lazy search above this match length */ ush nice_length; /* quit search above this match length */ ush max_chain; compress_func func; } config; #ifdef FASTEST local const config configuration_table[2] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ #else local const config configuration_table[10] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ /* 2 */ {4, 5, 16, 8, deflate_fast}, /* 3 */ {4, 6, 32, 32, deflate_fast}, /* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ /* 5 */ {8, 16, 32, 32, deflate_slow}, /* 6 */ {8, 16, 128, 128, deflate_slow}, /* 7 */ {8, 32, 128, 256, deflate_slow}, /* 8 */ {32, 128, 258, 1024, deflate_slow}, /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ #endif /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. */ #define EQUAL 0 /* result of memcmp for equal strings */ #ifndef NO_DUMMY_DECL struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ #endif /* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ #define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to to UPDATE_HASH are made with consecutive * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== * Insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. * IN assertion: all calls to to INSERT_STRING are made with consecutive * input characters and the first MIN_MATCH bytes of str are valid * (except for the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #else #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #endif /* =========================================================================== * Initialize the hash table (avoiding 64K overflow for 16 bit systems). * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ s->head[s->hash_size-1] = NIL; \ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); /* ========================================================================= */ int ZEXPORT deflateInit_(strm, level, version, stream_size) z_streamp strm; int level; const char *version; int stream_size; { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, version, stream_size) z_streamp strm; int level; int method; int windowBits; int memLevel; int strategy; const char *version; int stream_size; { deflate_state *s; int wrap = 1; static const char my_version[] = ZLIB_VERSION; ushf *overlay; /* We overlay pending_buf and d_buf+l_buf. This works since the average * output size for (length,distance) codes is <= 24 bits. */ if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { return Z_VERSION_ERROR; } if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; if (strm->zalloc == (alloc_func)0) { #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; #endif } if (strm->zfree == (free_func)0) #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zfree = zcfree; #endif #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; windowBits = -windowBits; } #ifdef GZIP else if (windowBits > 15) { wrap = 2; /* write gzip wrapper instead */ windowBits -= 16; } #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state FAR *)s; s->strm = strm; s->wrap = wrap; s->gzhead = Z_NULL; s->w_bits = windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; s->hash_bits = memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); s->high_water = 0; /* nothing written to s->window yet */ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); s->pending_buf = (uchf *) overlay; s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { s->status = FINISH_STATE; strm->msg = ERR_MSG(Z_MEM_ERROR); deflateEnd (strm); return Z_MEM_ERROR; } s->d_buf = overlay + s->lit_bufsize/sizeof(ush); s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; s->level = level; s->strategy = strategy; s->method = (Byte)method; return deflateReset(strm); } /* ========================================================================= */ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; { deflate_state *s; uInt str, n; int wrap; unsigned avail; z_const unsigned char *next; if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) return Z_STREAM_ERROR; s = strm->state; wrap = s->wrap; if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) return Z_STREAM_ERROR; /* when using zlib wrappers, compute Adler-32 for provided dictionary */ if (wrap == 1) strm->adler = adler32(strm->adler, dictionary, dictLength); s->wrap = 0; /* avoid computing Adler-32 in read_buf */ /* if dictionary would fill window, just replace the history */ if (dictLength >= s->w_size) { if (wrap == 0) { /* already empty otherwise */ CLEAR_HASH(s); s->strstart = 0; s->block_start = 0L; s->insert = 0; } dictionary += dictLength - s->w_size; /* use the tail */ dictLength = s->w_size; } /* insert dictionary into window and hash */ avail = strm->avail_in; next = strm->next_in; strm->avail_in = dictLength; strm->next_in = (z_const Bytef *)dictionary; fill_window(s); while (s->lookahead >= MIN_MATCH) { str = s->strstart; n = s->lookahead - (MIN_MATCH-1); do { UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); #ifndef FASTEST s->prev[str & s->w_mask] = s->head[s->ins_h]; #endif s->head[s->ins_h] = (Pos)str; str++; } while (--n); s->strstart = str; s->lookahead = MIN_MATCH-1; fill_window(s); } s->strstart += s->lookahead; s->block_start = (long)s->strstart; s->insert = s->lookahead; s->lookahead = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; strm->next_in = next; strm->avail_in = avail; s->wrap = wrap; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateResetKeep (strm) z_streamp strm; { deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { return Z_STREAM_ERROR; } strm->total_in = strm->total_out = 0; strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ strm->data_type = Z_UNKNOWN; s = (deflate_state *)strm->state; s->pending = 0; s->pending_out = s->pending_buf; if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } s->status = s->wrap ? INIT_STATE : BUSY_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif adler32(0L, Z_NULL, 0); s->last_flush = Z_NO_FLUSH; _tr_init(s); return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateReset (strm) z_streamp strm; { int ret; ret = deflateResetKeep(strm); if (ret == Z_OK) lm_init(strm->state); return ret; } /* ========================================================================= */ int ZEXPORT deflateSetHeader (strm, head) z_streamp strm; gz_headerp head; { if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; if (strm->state->wrap != 2) return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflatePending (strm, pending, bits) unsigned *pending; int *bits; z_streamp strm; { if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; if (pending != Z_NULL) *pending = strm->state->pending; if (bits != Z_NULL) *bits = strm->state->bi_valid; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflatePrime (strm, bits, value) z_streamp strm; int bits; int value; { deflate_state *s; int put; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; s = strm->state; if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; do { put = Buf_size - s->bi_valid; if (put > bits) put = bits; s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); s->bi_valid += put; _tr_flush_bits(s); value >>= put; bits -= put; } while (bits); return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateParams(strm, level, strategy) z_streamp strm; int level; int strategy; { deflate_state *s; compress_func func; int err = Z_OK; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; s = strm->state; #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && strm->total_in != 0) { /* Flush the last buffer: */ err = deflate(strm, Z_BLOCK); if (err == Z_BUF_ERROR && s->pending == 0) err = Z_OK; } if (s->level != level) { s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; s->nice_match = configuration_table[level].nice_length; s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; return err; } /* ========================================================================= */ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) z_streamp strm; int good_length; int max_lazy; int nice_length; int max_chain; { deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; s = strm->state; s->good_match = good_length; s->max_lazy_match = max_lazy; s->nice_match = nice_length; s->max_chain_length = max_chain; return Z_OK; } /* ========================================================================= * For the default windowBits of 15 and memLevel of 8, this function returns * a close to exact, as well as small, upper bound on the compressed size. * They are coded as constants here for a reason--if the #define's are * changed, then this function needs to be changed as well. The return * value for 15 and 8 only works for those exact settings. * * For any setting other than those defaults for windowBits and memLevel, * the value returned is a conservative worst case for the maximum expansion * resulting from using fixed blocks instead of stored blocks, which deflate * can emit on compressed data for some combinations of the parameters. * * This function could be more sophisticated to provide closer upper bounds for * every combination of windowBits and memLevel. But even the conservative * upper bound of about 14% expansion does not seem onerous for output buffer * allocation. */ uLong ZEXPORT deflateBound(strm, sourceLen) z_streamp strm; uLong sourceLen; { deflate_state *s; uLong complen, wraplen; Bytef *str; /* conservative upper bound for compressed data */ complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; /* if can't get parameters, return conservative bound plus zlib wrapper */ if (strm == Z_NULL || strm->state == Z_NULL) return complen + 6; /* compute wrapper length */ s = strm->state; switch (s->wrap) { case 0: /* raw deflate */ wraplen = 0; break; case 1: /* zlib wrapper */ wraplen = 6 + (s->strstart ? 4 : 0); break; case 2: /* gzip wrapper */ wraplen = 18; if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ if (s->gzhead->extra != Z_NULL) wraplen += 2 + s->gzhead->extra_len; str = s->gzhead->name; if (str != Z_NULL) do { wraplen++; } while (*str++); str = s->gzhead->comment; if (str != Z_NULL) do { wraplen++; } while (*str++); if (s->gzhead->hcrc) wraplen += 2; } break; default: /* for compiler happiness */ wraplen = 6; } /* if not default parameters, return conservative bound */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) return complen + wraplen; /* default settings: return tight bound for that case */ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen; } /* ========================================================================= * Put a short in the pending buffer. The 16-bit value is put in MSB order. * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ local void putShortMSB (s, b) deflate_state *s; uInt b; { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } /* ========================================================================= * Flush as much pending output as possible. All deflate() output goes * through this function so some applications may wish to modify it * to avoid allocating a large strm->next_out buffer and copying into it. * (See also read_buf()). */ local void flush_pending(strm) z_streamp strm; { unsigned len; deflate_state *s = strm->state; _tr_flush_bits(s); len = s->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; zmemcpy(strm->next_out, s->pending_out, len); strm->next_out += len; s->pending_out += len; strm->total_out += len; strm->avail_out -= len; s->pending -= len; if (s->pending == 0) { s->pending_out = s->pending_buf; } } /* ========================================================================= */ int ZEXPORT deflate (strm, flush) z_streamp strm; int flush; { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || flush > Z_BLOCK || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); s->strm = strm; /* just in case */ old_flush = s->last_flush; s->last_flush = flush; /* Write the header */ if (s->status == INIT_STATE) { #ifdef GZIP if (s->wrap == 2) { strm->adler = crc32(0L, Z_NULL, 0); put_byte(s, 31); put_byte(s, 139); put_byte(s, 8); if (s->gzhead == Z_NULL) { put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, OS_CODE); s->status = BUSY_STATE; } else { put_byte(s, (s->gzhead->text ? 1 : 0) + (s->gzhead->hcrc ? 2 : 0) + (s->gzhead->extra == Z_NULL ? 0 : 4) + (s->gzhead->name == Z_NULL ? 0 : 8) + (s->gzhead->comment == Z_NULL ? 0 : 16) ); put_byte(s, (Byte)(s->gzhead->time & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, s->gzhead->os & 0xff); if (s->gzhead->extra != Z_NULL) { put_byte(s, s->gzhead->extra_len & 0xff); put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); } if (s->gzhead->hcrc) strm->adler = crc32(strm->adler, s->pending_buf, s->pending); s->gzindex = 0; s->status = EXTRA_STATE; } } else #endif { uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; uInt level_flags; if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) level_flags = 0; else if (s->level < 6) level_flags = 1; else if (s->level == 6) level_flags = 2; else level_flags = 3; header |= (level_flags << 6); if (s->strstart != 0) header |= PRESET_DICT; header += 31 - (header % 31); s->status = BUSY_STATE; putShortMSB(s, header); /* Save the adler32 of the preset dictionary: */ if (s->strstart != 0) { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } strm->adler = adler32(0L, Z_NULL, 0); } } #ifdef GZIP if (s->status == EXTRA_STATE) { if (s->gzhead->extra != Z_NULL) { uInt beg = s->pending; /* start of bytes to update crc */ while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) break; } put_byte(s, s->gzhead->extra[s->gzindex]); s->gzindex++; } if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (s->gzindex == s->gzhead->extra_len) { s->gzindex = 0; s->status = NAME_STATE; } } else s->status = NAME_STATE; } if (s->status == NAME_STATE) { if (s->gzhead->name != Z_NULL) { uInt beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) { val = 1; break; } } val = s->gzhead->name[s->gzindex++]; put_byte(s, val); } while (val != 0); if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (val == 0) { s->gzindex = 0; s->status = COMMENT_STATE; } } else s->status = COMMENT_STATE; } if (s->status == COMMENT_STATE) { if (s->gzhead->comment != Z_NULL) { uInt beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) { val = 1; break; } } val = s->gzhead->comment[s->gzindex++]; put_byte(s, val); } while (val != 0); if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (val == 0) s->status = HCRC_STATE; } else s->status = HCRC_STATE; } if (s->status == HCRC_STATE) { if (s->gzhead->hcrc) { if (s->pending + 2 > s->pending_buf_size) flush_pending(strm); if (s->pending + 2 <= s->pending_buf_size) { put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); strm->adler = crc32(0L, Z_NULL, 0); s->status = BUSY_STATE; } } else s->status = BUSY_STATE; } #endif /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); if (strm->avail_out == 0) { /* Since avail_out is 0, deflate will be called again with * more output space, but possibly with both pending and * avail_in equal to zero. There won't be anything to do, * but this is not an error situation so make sure we * return OK instead of BUF_ERROR at next call of deflate: */ s->last_flush = -1; return Z_OK; } /* Make sure there is something to do and avoid duplicate consecutive * flushes. For repeated and useless calls with Z_FINISH, we keep * returning Z_STREAM_END instead of Z_BUF_ERROR. */ } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && flush != Z_FINISH) { ERR_RETURN(strm, Z_BUF_ERROR); } /* User must not provide more input after the first FINISH: */ if (s->status == FINISH_STATE && strm->avail_in != 0) { ERR_RETURN(strm, Z_BUF_ERROR); } /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : (s->strategy == Z_RLE ? deflate_rle(s, flush) : (*(configuration_table[s->level].func))(s, flush)); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; } if (bstate == need_more || bstate == finish_started) { if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ } return Z_OK; /* If flush != Z_NO_FLUSH && avail_out == 0, the next call * of deflate should use the same flush parameter to make sure * that the flush is complete. So we don't have to output an * empty block here, this will be done at next call. This also * ensures that for a very small output buffer, we emit at most * one empty block. */ } if (bstate == block_done) { if (flush == Z_PARTIAL_FLUSH) { _tr_align(s); } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ _tr_stored_block(s, (char*)0, 0L, 0); /* For a full flush, this empty block will be recognized * as a special marker by inflate_sync(). */ if (flush == Z_FULL_FLUSH) { CLEAR_HASH(s); /* forget history */ if (s->lookahead == 0) { s->strstart = 0; s->block_start = 0L; s->insert = 0; } } } flush_pending(strm); if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ return Z_OK; } } } Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (s->wrap <= 0) return Z_STREAM_END; /* Write the trailer */ #ifdef GZIP if (s->wrap == 2) { put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); put_byte(s, (Byte)(strm->total_in & 0xff)); put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); } else #endif { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } flush_pending(strm); /* If avail_out is zero, the application will call deflate again * to flush the rest. */ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ return s->pending != 0 ? Z_OK : Z_STREAM_END; } /* ========================================================================= */ int ZEXPORT deflateEnd (strm) z_streamp strm; { int status; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; status = strm->state->status; if (status != INIT_STATE && status != EXTRA_STATE && status != NAME_STATE && status != COMMENT_STATE && status != HCRC_STATE && status != BUSY_STATE && status != FINISH_STATE) { return Z_STREAM_ERROR; } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); TRY_FREE(strm, strm->state->head); TRY_FREE(strm, strm->state->prev); TRY_FREE(strm, strm->state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; } /* ========================================================================= * Copy the source state to the destination state. * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ int ZEXPORT deflateCopy (dest, source) z_streamp dest; z_streamp source; { #ifdef MAXSEG_64K return Z_STREAM_ERROR; #else deflate_state *ds; deflate_state *ss; ushf *overlay; if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { return Z_STREAM_ERROR; } ss = source->state; zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state FAR *) ds; zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); ds->pending_buf = (uchf *) overlay; if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { deflateEnd (dest); return Z_MEM_ERROR; } /* following zmemcpy do not work for 16-bit MSDOS */ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; ds->bl_desc.dyn_tree = ds->bl_tree; return Z_OK; #endif /* MAXSEG_64K */ } /* =========================================================================== * Read a new buffer from the current input stream, update the adler32 * and total number of bytes read. All deflate() input goes through * this function so some applications may wish to modify it to avoid * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ local int read_buf(strm, buf, size) z_streamp strm; Bytef *buf; unsigned size; { unsigned len = strm->avail_in; if (len > size) len = size; if (len == 0) return 0; strm->avail_in -= len; zmemcpy(buf, strm->next_in, len); if (strm->state->wrap == 1) { strm->adler = adler32(strm->adler, buf, len); } #ifdef GZIP else if (strm->state->wrap == 2) { strm->adler = crc32(strm->adler, buf, len); } #endif strm->next_in += len; strm->total_in += len; return (int)len; } /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ local void lm_init (s) deflate_state *s; { s->window_size = (ulg)2L*s->w_size; CLEAR_HASH(s); /* Set the default configuration parameters: */ s->max_lazy_match = configuration_table[s->level].max_lazy; s->good_match = configuration_table[s->level].good_length; s->nice_match = configuration_table[s->level].nice_length; s->max_chain_length = configuration_table[s->level].max_chain; s->strstart = 0; s->block_start = 0L; s->lookahead = 0; s->insert = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; #ifndef FASTEST #ifdef ASMV match_init(); /* initialize the asm code */ #endif #endif } #ifndef FASTEST /* =========================================================================== * Set match_start to the longest match starting at the given string and * return its length. Matches shorter or equal to prev_length are discarded, * in which case the result is equal to prev_length and match_start is * garbage. * IN assertions: cur_match is the head of the hash chain for the current * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ #ifndef ASMV /* For 80x86 and 680x0, an optimized version will be provided in match.asm or * match.S. The code will be functionally equivalent. */ local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ int best_len = s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0. */ Posf *prev = s->prev; uInt wmask = s->w_mask; #ifdef UNALIGNED_OK /* Compare two bytes at a time. Note: this is not always beneficial. * Try with and without -DUNALIGNED_OK to check. */ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; register ush scan_start = *(ushf*)scan; register ush scan_end = *(ushf*)(scan+best_len-1); #else register Bytef *strend = s->window + s->strstart + MAX_MATCH; register Byte scan_end1 = scan[best_len-1]; register Byte scan_end = scan[best_len]; #endif /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); /* Do not waste too much time if we already have a good match: */ if (s->prev_length >= s->good_match) { chain_length >>= 2; } /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Skip to next match if the match length cannot increase * or if the match length is less than 2. Note that the checks below * for insufficient lookahead only occur occasionally for performance * reasons. Therefore uninitialized memory will be accessed, and * conditional jumps will be made that depend on those values. * However the length of the match is limited to the lookahead, so * the output of deflate is not affected by the uninitialized values. */ #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ if (*(ushf*)(match+best_len-1) != scan_end || *(ushf*)match != scan_start) continue; /* It is not necessary to compare scan[2] and match[2] since they are * always equal when the other bytes match, given that the hash keys * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at * strstart+3, +5, ... up to strstart+257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ /* Here, scan <= window+strstart+257 */ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); if (*scan == *match) scan++; len = (MAX_MATCH - 1) - (int)(strend-scan); scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ if (match[best_len] != scan_end || match[best_len-1] != scan_end1 || *match != *scan || *++match != scan[1]) continue; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match++; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; #endif /* UNALIGNED_OK */ if (len > best_len) { s->match_start = cur_match; best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK scan_end = *(ushf*)(scan+best_len-1); #else scan_end1 = scan[best_len-1]; scan_end = scan[best_len]; #endif } } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } #endif /* ASMV */ #else /* FASTEST */ /* --------------------------------------------------------------------------- * Optimized version for FASTEST only */ local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ { register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ register Bytef *strend = s->window + s->strstart + MAX_MATCH; /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Return failure if the match length is less than 2: */ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match += 2; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); if (len < MIN_MATCH) return MIN_MATCH - 1; s->match_start = cur_match; return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; } #endif /* FASTEST */ #ifdef DEBUG /* =========================================================================== * Check that the match at match_start is indeed a match. */ local void check_match(s, start, match, length) deflate_state *s; IPos start, match; int length; { /* check that the match is indeed a match */ if (zmemcmp(s->window + match, s->window + start, length) != EQUAL) { fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); do { fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); } while (--length != 0); z_error("invalid match"); } if (z_verbose > 1) { fprintf(stderr,"\\[%d,%d]", start-match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } #else # define check_match(s, start, match, length) #endif /* DEBUG */ /* =========================================================================== * Fill the window when the lookahead becomes insufficient. * Updates strstart and lookahead. * * IN assertion: lookahead < MIN_LOOKAHEAD * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD * At least one byte has been read, or avail_in == 0; reads are * performed for at least two bytes (required for the zip translate_eol * option -- not supported here). */ local void fill_window(s) deflate_state *s; { register unsigned n, m; register Posf *p; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); do { more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); /* Deal with !@#$% 64K limit: */ if (sizeof(int) <= 2) { if (more == 0 && s->strstart == 0 && s->lookahead == 0) { more = wsize; } else if (more == (unsigned)(-1)) { /* Very unlikely, but possible on 16 bit machine if * strstart == 0 && lookahead == 1 (input done a byte at time) */ more--; } } /* If the window is almost full and there is insufficient lookahead, * move the upper half to the lower one to make room in the upper half. */ if (s->strstart >= wsize+MAX_DIST(s)) { zmemcpy(s->window, s->window+wsize, (unsigned)wsize); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; /* Slide the hash table (could be avoided with 32 bit values at the expense of memory usage). We slide even when level == 0 to keep the hash table consistent if we switch back to level > 0 later. (Using level 0 permanently is not an optimal usage of zlib, so we don't care about this pathological case.) */ n = s->hash_size; p = &s->head[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); } while (--n); n = wsize; #ifndef FASTEST p = &s->prev[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); /* If n is not on any hash chain, prev[n] is garbage but * its value will never be used. */ } while (--n); #endif more += wsize; } if (s->strm->avail_in == 0) break; /* If there was no sliding: * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && * more == window_size - lookahead - strstart * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) * => more >= window_size - 2*WSIZE + 2 * In the BIG_MEM or MMAP case (not yet supported), * window_size == input_size + MIN_LOOKAHEAD && * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. * Otherwise, window_size == 2*WSIZE so more >= 2. * If there was sliding, more >= WSIZE. So in all cases, more >= 2. */ Assert(more >= 2, "more < 2"); n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); s->lookahead += n; /* Initialize the hash value now that we have some input: */ if (s->lookahead + s->insert >= MIN_MATCH) { uInt str = s->strstart - s->insert; s->ins_h = s->window[str]; UPDATE_HASH(s, s->ins_h, s->window[str + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif while (s->insert) { UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); #ifndef FASTEST s->prev[str & s->w_mask] = s->head[s->ins_h]; #endif s->head[s->ins_h] = (Pos)str; str++; s->insert--; if (s->lookahead + s->insert < MIN_MATCH) break; } } /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. */ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); /* If the WIN_INIT bytes after the end of the current data have never been * written, then zero those bytes in order to avoid memory check reports of * the use of uninitialized (or uninitialised as Julian writes) bytes by * the longest match routines. Update the high water mark for the next * time through here. WIN_INIT is set to MAX_MATCH since the longest match * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. */ if (s->high_water < s->window_size) { ulg curr = s->strstart + (ulg)(s->lookahead); ulg init; if (s->high_water < curr) { /* Previous high water mark below current data -- zero WIN_INIT * bytes or up to end of window, whichever is less. */ init = s->window_size - curr; if (init > WIN_INIT) init = WIN_INIT; zmemzero(s->window + curr, (unsigned)init); s->high_water = curr + init; } else if (s->high_water < (ulg)curr + WIN_INIT) { /* High water mark at or above current data, but below current data * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up * to end of window, whichever is less. */ init = (ulg)curr + WIN_INIT - s->high_water; if (init > s->window_size - s->high_water) init = s->window_size - s->high_water; zmemzero(s->window + s->high_water, (unsigned)init); s->high_water += init; } } Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, "not enough room for search"); } /* =========================================================================== * Flush the current block, with given end-of-file flag. * IN assertion: strstart is set to the end of the current match. */ #define FLUSH_BLOCK_ONLY(s, last) { \ _tr_flush_block(s, (s->block_start >= 0L ? \ (charf *)&s->window[(unsigned)s->block_start] : \ (charf *)Z_NULL), \ (ulg)((long)s->strstart - s->block_start), \ (last)); \ s->block_start = s->strstart; \ flush_pending(s->strm); \ Tracev((stderr,"[FLUSH]")); \ } /* Same but force premature exit if necessary. */ #define FLUSH_BLOCK(s, last) { \ FLUSH_BLOCK_ONLY(s, last); \ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ } /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. * This function does not insert new strings in the dictionary since * uncompressible data is probably not useful. This function is used * only for the level=0 compression option. * NOTE: this function should be optimized to avoid extra copying from * window to pending_buf. */ local block_state deflate_stored(s, flush) deflate_state *s; int flush; { /* Stored blocks are limited to 0xffff bytes, pending_buf is limited * to pending_buf_size, and each stored block has a 5 byte header: */ ulg max_block_size = 0xffff; ulg max_start; if (max_block_size > s->pending_buf_size - 5) { max_block_size = s->pending_buf_size - 5; } /* Copy as much as possible from input to output: */ for (;;) { /* Fill the window as much as possible: */ if (s->lookahead <= 1) { Assert(s->strstart < s->w_size+MAX_DIST(s) || s->block_start >= (long)s->w_size, "slide too late"); fill_window(s); if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; if (s->lookahead == 0) break; /* flush the current block */ } Assert(s->block_start >= 0L, "block gone"); s->strstart += s->lookahead; s->lookahead = 0; /* Emit a stored block if pending_buf will be full: */ max_start = s->block_start + max_block_size; if (s->strstart == 0 || (ulg)s->strstart >= max_start) { /* strstart == 0 is possible when wraparound on 16-bit machine */ s->lookahead = (uInt)(s->strstart - max_start); s->strstart = (uInt)max_start; FLUSH_BLOCK(s, 0); } /* Flush if we may have to slide, otherwise block_start may become * negative and the data will be gone: */ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { FLUSH_BLOCK(s, 0); } } s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if ((long)s->strstart > s->block_start) FLUSH_BLOCK(s, 0); return block_done; } /* =========================================================================== * Compress as much as possible from the input stream, return the current * block state. * This function does not perform lazy evaluation of matches and inserts * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ local block_state deflate_fast(s, flush) deflate_state *s; int flush; { IPos hash_head; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. * At this point we have always match_length < MIN_MATCH */ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ } if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->match_start, s->match_length); _tr_tally_dist(s, s->strstart - s->match_start, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ #ifndef FASTEST if (s->match_length <= s->max_insert_length && s->lookahead >= MIN_MATCH) { s->match_length--; /* string at strstart already in table */ do { s->strstart++; INSERT_STRING(s, s->strstart, hash_head); /* strstart never exceeds WSIZE-MAX_MATCH, so there are * always MIN_MATCH bytes ahead. */ } while (--s->match_length != 0); s->strstart++; } else #endif { s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ } } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->last_lit) FLUSH_BLOCK(s, 0); return block_done; } #ifndef FASTEST /* =========================================================================== * Same as above, but achieves better compression. We use a lazy * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ local block_state deflate_slow(s, flush) deflate_state *s; int flush; { IPos hash_head; /* head of hash chain */ int bflush; /* set if current block must be flushed */ /* Process the input block. */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. */ s->prev_length = s->match_length, s->prev_match = s->match_start; s->match_length = MIN_MATCH-1; if (hash_head != NIL && s->prev_length < s->max_lazy_match && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ if (s->match_length <= 5 && (s->strategy == Z_FILTERED #if TOO_FAR <= 32767 || (s->match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR) #endif )) { /* If prev_match is also MIN_MATCH, match_start is garbage * but we will ignore the current match anyway. */ s->match_length = MIN_MATCH-1; } } /* If there was a match at the previous step and the current * match is not better, output the previous match: */ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ check_match(s, s->strstart-1, s->prev_match, s->prev_length); _tr_tally_dist(s, s->strstart -1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. * strstart-1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ s->lookahead -= s->prev_length-1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { INSERT_STRING(s, s->strstart, hash_head); } } while (--s->prev_length != 0); s->match_available = 0; s->match_length = MIN_MATCH-1; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } else if (s->match_available) { /* If there was no match at the previous position, output a * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } s->strstart++; s->lookahead--; if (s->strm->avail_out == 0) return need_more; } else { /* There is no previous match to compare with, wait for * the next step to decide. */ s->match_available = 1; s->strstart++; s->lookahead--; } } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); s->match_available = 0; } s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->last_lit) FLUSH_BLOCK(s, 0); return block_done; } #endif /* FASTEST */ /* =========================================================================== * For Z_RLE, simply look for runs of bytes, generate matches only of distance * one. Do not maintain a hash table. (It will be regenerated if this run of * deflate switches away from Z_RLE.) */ local block_state deflate_rle(s, flush) deflate_state *s; int flush; { int bflush; /* set if current block must be flushed */ uInt prev; /* byte at distance one to match */ Bytef *scan, *strend; /* scan goes up to strend for length of run */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the longest run, plus one for the unrolled loop. */ if (s->lookahead <= MAX_MATCH) { fill_window(s); if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* See how many times the previous byte repeats */ s->match_length = 0; if (s->lookahead >= MIN_MATCH && s->strstart > 0) { scan = s->window + s->strstart - 1; prev = *scan; if (prev == *++scan && prev == *++scan && prev == *++scan) { strend = s->window + s->strstart + MAX_MATCH; do { } while (prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); s->match_length = MAX_MATCH - (int)(strend - scan); if (s->match_length > s->lookahead) s->match_length = s->lookahead; } Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->strstart - 1, s->match_length); _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; s->strstart += s->match_length; s->match_length = 0; } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->last_lit) FLUSH_BLOCK(s, 0); return block_done; } /* =========================================================================== * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. * (It will be regenerated if this run of deflate switches away from Huffman.) */ local block_state deflate_huff(s, flush) deflate_state *s; int flush; { int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we have a literal to write. */ if (s->lookahead == 0) { fill_window(s); if (s->lookahead == 0) { if (flush == Z_NO_FLUSH) return need_more; break; /* flush the current block */ } } /* Output a literal byte */ s->match_length = 0; Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->last_lit) FLUSH_BLOCK(s, 0); return block_done; } tcl8.6.5/compat/zlib/examples/0000755000175000017500000000000012665173607015633 5ustar sergeisergeitcl8.6.5/compat/zlib/examples/enough.c0000644000175000017500000005742212663660065017273 0ustar sergeisergei/* enough.c -- determine the maximum size of inflate's Huffman code tables over * all possible valid and complete Huffman codes, subject to a length limit. * Copyright (C) 2007, 2008, 2012 Mark Adler * Version 1.4 18 August 2012 Mark Adler */ /* Version history: 1.0 3 Jan 2007 First version (derived from codecount.c version 1.4) 1.1 4 Jan 2007 Use faster incremental table usage computation Prune examine() search on previously visited states 1.2 5 Jan 2007 Comments clean up As inflate does, decrease root for short codes Refuse cases where inflate would increase root 1.3 17 Feb 2008 Add argument for initial root table size Fix bug for initial root table size == max - 1 Use a macro to compute the history index 1.4 18 Aug 2012 Avoid shifts more than bits in type (caused endless loop!) Clean up comparisons of different types Clean up code indentation */ /* Examine all possible Huffman codes for a given number of symbols and a maximum code length in bits to determine the maximum table size for zilb's inflate. Only complete Huffman codes are counted. Two codes are considered distinct if the vectors of the number of codes per length are not identical. So permutations of the symbol assignments result in the same code for the counting, as do permutations of the assignments of the bit values to the codes (i.e. only canonical codes are counted). We build a code from shorter to longer lengths, determining how many symbols are coded at each length. At each step, we have how many symbols remain to be coded, what the last code length used was, and how many bit patterns of that length remain unused. Then we add one to the code length and double the number of unused patterns to graduate to the next code length. We then assign all portions of the remaining symbols to that code length that preserve the properties of a correct and eventually complete code. Those properties are: we cannot use more bit patterns than are available; and when all the symbols are used, there are exactly zero possible bit patterns remaining. The inflate Huffman decoding algorithm uses two-level lookup tables for speed. There is a single first-level table to decode codes up to root bits in length (root == 9 in the current inflate implementation). The table has 1 << root entries and is indexed by the next root bits of input. Codes shorter than root bits have replicated table entries, so that the correct entry is pointed to regardless of the bits that follow the short code. If the code is longer than root bits, then the table entry points to a second- level table. The size of that table is determined by the longest code with that root-bit prefix. If that longest code has length len, then the table has size 1 << (len - root), to index the remaining bits in that set of codes. Each subsequent root-bit prefix then has its own sub-table. The total number of table entries required by the code is calculated incrementally as the number of codes at each bit length is populated. When all of the codes are shorter than root bits, then root is reduced to the longest code length, resulting in a single, smaller, one-level table. The inflate algorithm also provides for small values of root (relative to the log2 of the number of symbols), where the shortest code has more bits than root. In that case, root is increased to the length of the shortest code. This program, by design, does not handle that case, so it is verified that the number of symbols is less than 2^(root + 1). In order to speed up the examination (by about ten orders of magnitude for the default arguments), the intermediate states in the build-up of a code are remembered and previously visited branches are pruned. The memory required for this will increase rapidly with the total number of symbols and the maximum code length in bits. However this is a very small price to pay for the vast speedup. First, all of the possible Huffman codes are counted, and reachable intermediate states are noted by a non-zero count in a saved-results array. Second, the intermediate states that lead to (root + 1) bit or longer codes are used to look at all sub-codes from those junctures for their inflate memory usage. (The amount of memory used is not affected by the number of codes of root bits or less in length.) Third, the visited states in the construction of those sub-codes and the associated calculation of the table size is recalled in order to avoid recalculating from the same juncture. Beginning the code examination at (root + 1) bit codes, which is enabled by identifying the reachable nodes, accounts for about six of the orders of magnitude of improvement for the default arguments. About another four orders of magnitude come from not revisiting previous states. Out of approximately 2x10^16 possible Huffman codes, only about 2x10^6 sub-codes need to be examined to cover all of the possible table memory usage cases for the default arguments of 286 symbols limited to 15-bit codes. Note that an unsigned long long type is used for counting. It is quite easy to exceed the capacity of an eight-byte integer with a large number of symbols and a large maximum code length, so multiple-precision arithmetic would need to replace the unsigned long long arithmetic in that case. This program will abort if an overflow occurs. The big_t type identifies where the counting takes place. An unsigned long long type is also used for calculating the number of possible codes remaining at the maximum length. This limits the maximum code length to the number of bits in a long long minus the number of bits needed to represent the symbols in a flat code. The code_t type identifies where the bit pattern counting takes place. */ #include #include #include #include #define local static /* special data types */ typedef unsigned long long big_t; /* type for code counting */ typedef unsigned long long code_t; /* type for bit pattern counting */ struct tab { /* type for been here check */ size_t len; /* length of bit vector in char's */ char *vec; /* allocated bit vector */ }; /* The array for saving results, num[], is indexed with this triplet: syms: number of symbols remaining to code left: number of available bit patterns at length len len: number of bits in the codes currently being assigned Those indices are constrained thusly when saving results: syms: 3..totsym (totsym == total symbols to code) left: 2..syms - 1, but only the evens (so syms == 8 -> 2, 4, 6) len: 1..max - 1 (max == maximum code length in bits) syms == 2 is not saved since that immediately leads to a single code. left must be even, since it represents the number of available bit patterns at the current length, which is double the number at the previous length. left ends at syms-1 since left == syms immediately results in a single code. (left > sym is not allowed since that would result in an incomplete code.) len is less than max, since the code completes immediately when len == max. The offset into the array is calculated for the three indices with the first one (syms) being outermost, and the last one (len) being innermost. We build the array with length max-1 lists for the len index, with syms-3 of those for each symbol. There are totsym-2 of those, with each one varying in length as a function of sym. See the calculation of index in count() for the index, and the calculation of size in main() for the size of the array. For the deflate example of 286 symbols limited to 15-bit codes, the array has 284,284 entries, taking up 2.17 MB for an 8-byte big_t. More than half of the space allocated for saved results is actually used -- not all possible triplets are reached in the generation of valid Huffman codes. */ /* The array for tracking visited states, done[], is itself indexed identically to the num[] array as described above for the (syms, left, len) triplet. Each element in the array is further indexed by the (mem, rem) doublet, where mem is the amount of inflate table space used so far, and rem is the remaining unused entries in the current inflate sub-table. Each indexed element is simply one bit indicating whether the state has been visited or not. Since the ranges for mem and rem are not known a priori, each bit vector is of a variable size, and grows as needed to accommodate the visited states. mem and rem are used to calculate a single index in a triangular array. Since the range of mem is expected in the default case to be about ten times larger than the range of rem, the array is skewed to reduce the memory usage, with eight times the range for mem than for rem. See the calculations for offset and bit in beenhere() for the details. For the deflate example of 286 symbols limited to 15-bit codes, the bit vectors grow to total approximately 21 MB, in addition to the 4.3 MB done[] array itself. */ /* Globals to avoid propagating constants or constant pointers recursively */ local int max; /* maximum allowed bit length for the codes */ local int root; /* size of base code table in bits */ local int large; /* largest code table so far */ local size_t size; /* number of elements in num and done */ local int *code; /* number of symbols assigned to each bit length */ local big_t *num; /* saved results array for code counting */ local struct tab *done; /* states already evaluated array */ /* Index function for num[] and done[] */ #define INDEX(i,j,k) (((size_t)((i-1)>>1)*((i-2)>>1)+(j>>1)-1)*(max-1)+k-1) /* Free allocated space. Uses globals code, num, and done. */ local void cleanup(void) { size_t n; if (done != NULL) { for (n = 0; n < size; n++) if (done[n].len) free(done[n].vec); free(done); } if (num != NULL) free(num); if (code != NULL) free(code); } /* Return the number of possible Huffman codes using bit patterns of lengths len through max inclusive, coding syms symbols, with left bit patterns of length len unused -- return -1 if there is an overflow in the counting. Keep a record of previous results in num to prevent repeating the same calculation. Uses the globals max and num. */ local big_t count(int syms, int len, int left) { big_t sum; /* number of possible codes from this juncture */ big_t got; /* value returned from count() */ int least; /* least number of syms to use at this juncture */ int most; /* most number of syms to use at this juncture */ int use; /* number of bit patterns to use in next call */ size_t index; /* index of this case in *num */ /* see if only one possible code */ if (syms == left) return 1; /* note and verify the expected state */ assert(syms > left && left > 0 && len < max); /* see if we've done this one already */ index = INDEX(syms, left, len); got = num[index]; if (got) return got; /* we have -- return the saved result */ /* we need to use at least this many bit patterns so that the code won't be incomplete at the next length (more bit patterns than symbols) */ least = (left << 1) - syms; if (least < 0) least = 0; /* we can use at most this many bit patterns, lest there not be enough available for the remaining symbols at the maximum length (if there were no limit to the code length, this would become: most = left - 1) */ most = (((code_t)left << (max - len)) - syms) / (((code_t)1 << (max - len)) - 1); /* count all possible codes from this juncture and add them up */ sum = 0; for (use = least; use <= most; use++) { got = count(syms - use, len + 1, (left - use) << 1); sum += got; if (got == (big_t)0 - 1 || sum < got) /* overflow */ return (big_t)0 - 1; } /* verify that all recursive calls are productive */ assert(sum != 0); /* save the result and return it */ num[index] = sum; return sum; } /* Return true if we've been here before, set to true if not. Set a bit in a bit vector to indicate visiting this state. Each (syms,len,left) state has a variable size bit vector indexed by (mem,rem). The bit vector is lengthened if needed to allow setting the (mem,rem) bit. */ local int beenhere(int syms, int len, int left, int mem, int rem) { size_t index; /* index for this state's bit vector */ size_t offset; /* offset in this state's bit vector */ int bit; /* mask for this state's bit */ size_t length; /* length of the bit vector in bytes */ char *vector; /* new or enlarged bit vector */ /* point to vector for (syms,left,len), bit in vector for (mem,rem) */ index = INDEX(syms, left, len); mem -= 1 << root; offset = (mem >> 3) + rem; offset = ((offset * (offset + 1)) >> 1) + rem; bit = 1 << (mem & 7); /* see if we've been here */ length = done[index].len; if (offset < length && (done[index].vec[offset] & bit) != 0) return 1; /* done this! */ /* we haven't been here before -- set the bit to show we have now */ /* see if we need to lengthen the vector in order to set the bit */ if (length <= offset) { /* if we have one already, enlarge it, zero out the appended space */ if (length) { do { length <<= 1; } while (length <= offset); vector = realloc(done[index].vec, length); if (vector != NULL) memset(vector + done[index].len, 0, length - done[index].len); } /* otherwise we need to make a new vector and zero it out */ else { length = 1 << (len - root); while (length <= offset) length <<= 1; vector = calloc(length, sizeof(char)); } /* in either case, bail if we can't get the memory */ if (vector == NULL) { fputs("abort: unable to allocate enough memory\n", stderr); cleanup(); exit(1); } /* install the new vector */ done[index].len = length; done[index].vec = vector; } /* set the bit */ done[index].vec[offset] |= bit; return 0; } /* Examine all possible codes from the given node (syms, len, left). Compute the amount of memory required to build inflate's decoding tables, where the number of code structures used so far is mem, and the number remaining in the current sub-table is rem. Uses the globals max, code, root, large, and done. */ local void examine(int syms, int len, int left, int mem, int rem) { int least; /* least number of syms to use at this juncture */ int most; /* most number of syms to use at this juncture */ int use; /* number of bit patterns to use in next call */ /* see if we have a complete code */ if (syms == left) { /* set the last code entry */ code[len] = left; /* complete computation of memory used by this code */ while (rem < left) { left -= rem; rem = 1 << (len - root); mem += rem; } assert(rem == left); /* if this is a new maximum, show the entries used and the sub-code */ if (mem > large) { large = mem; printf("max %d: ", mem); for (use = root + 1; use <= max; use++) if (code[use]) printf("%d[%d] ", code[use], use); putchar('\n'); fflush(stdout); } /* remove entries as we drop back down in the recursion */ code[len] = 0; return; } /* prune the tree if we can */ if (beenhere(syms, len, left, mem, rem)) return; /* we need to use at least this many bit patterns so that the code won't be incomplete at the next length (more bit patterns than symbols) */ least = (left << 1) - syms; if (least < 0) least = 0; /* we can use at most this many bit patterns, lest there not be enough available for the remaining symbols at the maximum length (if there were no limit to the code length, this would become: most = left - 1) */ most = (((code_t)left << (max - len)) - syms) / (((code_t)1 << (max - len)) - 1); /* occupy least table spaces, creating new sub-tables as needed */ use = least; while (rem < use) { use -= rem; rem = 1 << (len - root); mem += rem; } rem -= use; /* examine codes from here, updating table space as we go */ for (use = least; use <= most; use++) { code[len] = use; examine(syms - use, len + 1, (left - use) << 1, mem + (rem ? 1 << (len - root) : 0), rem << 1); if (rem == 0) { rem = 1 << (len - root); mem += rem; } rem--; } /* remove entries as we drop back down in the recursion */ code[len] = 0; } /* Look at all sub-codes starting with root + 1 bits. Look at only the valid intermediate code states (syms, left, len). For each completed code, calculate the amount of memory required by inflate to build the decoding tables. Find the maximum amount of memory required and show the code that requires that maximum. Uses the globals max, root, and num. */ local void enough(int syms) { int n; /* number of remaing symbols for this node */ int left; /* number of unused bit patterns at this length */ size_t index; /* index of this case in *num */ /* clear code */ for (n = 0; n <= max; n++) code[n] = 0; /* look at all (root + 1) bit and longer codes */ large = 1 << root; /* base table */ if (root < max) /* otherwise, there's only a base table */ for (n = 3; n <= syms; n++) for (left = 2; left < n; left += 2) { /* look at all reachable (root + 1) bit nodes, and the resulting codes (complete at root + 2 or more) */ index = INDEX(n, left, root + 1); if (root + 1 < max && num[index]) /* reachable node */ examine(n, root + 1, left, 1 << root, 0); /* also look at root bit codes with completions at root + 1 bits (not saved in num, since complete), just in case */ if (num[index - 1] && n <= left << 1) examine((n - left) << 1, root + 1, (n - left) << 1, 1 << root, 0); } /* done */ printf("done: maximum of %d table entries\n", large); } /* Examine and show the total number of possible Huffman codes for a given maximum number of symbols, initial root table size, and maximum code length in bits -- those are the command arguments in that order. The default values are 286, 9, and 15 respectively, for the deflate literal/length code. The possible codes are counted for each number of coded symbols from two to the maximum. The counts for each of those and the total number of codes are shown. The maximum number of inflate table entires is then calculated across all possible codes. Each new maximum number of table entries and the associated sub-code (starting at root + 1 == 10 bits) is shown. To count and examine Huffman codes that are not length-limited, provide a maximum length equal to the number of symbols minus one. For the deflate literal/length code, use "enough". For the deflate distance code, use "enough 30 6". This uses the %llu printf format to print big_t numbers, which assumes that big_t is an unsigned long long. If the big_t type is changed (for example to a multiple precision type), the method of printing will also need to be updated. */ int main(int argc, char **argv) { int syms; /* total number of symbols to code */ int n; /* number of symbols to code for this run */ big_t got; /* return value of count() */ big_t sum; /* accumulated number of codes over n */ code_t word; /* for counting bits in code_t */ /* set up globals for cleanup() */ code = NULL; num = NULL; done = NULL; /* get arguments -- default to the deflate literal/length code */ syms = 286; root = 9; max = 15; if (argc > 1) { syms = atoi(argv[1]); if (argc > 2) { root = atoi(argv[2]); if (argc > 3) max = atoi(argv[3]); } } if (argc > 4 || syms < 2 || root < 1 || max < 1) { fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n", stderr); return 1; } /* if not restricting the code length, the longest is syms - 1 */ if (max > syms - 1) max = syms - 1; /* determine the number of bits in a code_t */ for (n = 0, word = 1; word; n++, word <<= 1) ; /* make sure that the calculation of most will not overflow */ if (max > n || (code_t)(syms - 2) >= (((code_t)0 - 1) >> (max - 1))) { fputs("abort: code length too long for internal types\n", stderr); return 1; } /* reject impossible code requests */ if ((code_t)(syms - 1) > ((code_t)1 << max) - 1) { fprintf(stderr, "%d symbols cannot be coded in %d bits\n", syms, max); return 1; } /* allocate code vector */ code = calloc(max + 1, sizeof(int)); if (code == NULL) { fputs("abort: unable to allocate enough memory\n", stderr); return 1; } /* determine size of saved results array, checking for overflows, allocate and clear the array (set all to zero with calloc()) */ if (syms == 2) /* iff max == 1 */ num = NULL; /* won't be saving any results */ else { size = syms >> 1; if (size > ((size_t)0 - 1) / (n = (syms - 1) >> 1) || (size *= n, size > ((size_t)0 - 1) / (n = max - 1)) || (size *= n, size > ((size_t)0 - 1) / sizeof(big_t)) || (num = calloc(size, sizeof(big_t))) == NULL) { fputs("abort: unable to allocate enough memory\n", stderr); cleanup(); return 1; } } /* count possible codes for all numbers of symbols, add up counts */ sum = 0; for (n = 2; n <= syms; n++) { got = count(n, 1, 2); sum += got; if (got == (big_t)0 - 1 || sum < got) { /* overflow */ fputs("abort: can't count that high!\n", stderr); cleanup(); return 1; } printf("%llu %d-codes\n", got, n); } printf("%llu total codes for 2 to %d symbols", sum, syms); if (max < syms - 1) printf(" (%d-bit length limit)\n", max); else puts(" (no length limit)"); /* allocate and clear done array for beenhere() */ if (syms == 2) done = NULL; else if (size > ((size_t)0 - 1) / sizeof(struct tab) || (done = calloc(size, sizeof(struct tab))) == NULL) { fputs("abort: unable to allocate enough memory\n", stderr); cleanup(); return 1; } /* find and show maximum inflate table usage */ if (root > max) /* reduce root to max length */ root = max; if ((code_t)syms < ((code_t)1 << (root + 1))) enough(syms); else puts("cannot handle minimum code lengths > root"); /* done */ cleanup(); return 0; } tcl8.6.5/compat/zlib/examples/zlib_how.html0000644000175000017500000007220012663653206020333 0ustar sergeisergei zlib Usage Example

    zlib Usage Example

    We often get questions about how the deflate() and inflate() functions should be used. Users wonder when they should provide more input, when they should use more output, what to do with a Z_BUF_ERROR, how to make sure the process terminates properly, and so on. So for those who have read zlib.h (a few times), and would like further edification, below is an annotated example in C of simple routines to compress and decompress from an input file to an output file using deflate() and inflate() respectively. The annotations are interspersed between lines of the code. So please read between the lines. We hope this helps explain some of the intricacies of zlib.

    Without further adieu, here is the program zpipe.c:

    
    /* zpipe.c: example of proper use of zlib's inflate() and deflate()
       Not copyrighted -- provided to the public domain
       Version 1.4  11 December 2005  Mark Adler */
    
    /* Version history:
       1.0  30 Oct 2004  First version
       1.1   8 Nov 2004  Add void casting for unused return values
                         Use switch statement for inflate() return values
       1.2   9 Nov 2004  Add assertions to document zlib guarantees
       1.3   6 Apr 2005  Remove incorrect assertion in inf()
       1.4  11 Dec 2005  Add hack to avoid MSDOS end-of-line conversions
                         Avoid some compiler warnings for input and output buffers
     */
    
    We now include the header files for the required definitions. From stdio.h we use fopen(), fread(), fwrite(), feof(), ferror(), and fclose() for file i/o, and fputs() for error messages. From string.h we use strcmp() for command line argument processing. From assert.h we use the assert() macro. From zlib.h we use the basic compression functions deflateInit(), deflate(), and deflateEnd(), and the basic decompression functions inflateInit(), inflate(), and inflateEnd().
    
    #include <stdio.h>
    #include <string.h>
    #include <assert.h>
    #include "zlib.h"
    
    This is an ugly hack required to avoid corruption of the input and output data on Windows/MS-DOS systems. Without this, those systems would assume that the input and output files are text, and try to convert the end-of-line characters from one standard to another. That would corrupt binary data, and in particular would render the compressed data unusable. This sets the input and output to binary which suppresses the end-of-line conversions. SET_BINARY_MODE() will be used later on stdin and stdout, at the beginning of main().
    
    #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
    #  include <fcntl.h>
    #  include <io.h>
    #  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
    #else
    #  define SET_BINARY_MODE(file)
    #endif
    
    CHUNK is simply the buffer size for feeding data to and pulling data from the zlib routines. Larger buffer sizes would be more efficient, especially for inflate(). If the memory is available, buffers sizes on the order of 128K or 256K bytes should be used.
    
    #define CHUNK 16384
    
    The def() routine compresses data from an input file to an output file. The output data will be in the zlib format, which is different from the gzip or zip formats. The zlib format has a very small header of only two bytes to identify it as a zlib stream and to provide decoding information, and a four-byte trailer with a fast check value to verify the integrity of the uncompressed data after decoding.
    
    /* Compress from file source to file dest until EOF on source.
       def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
       allocated for processing, Z_STREAM_ERROR if an invalid compression
       level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
       version of the library linked do not match, or Z_ERRNO if there is
       an error reading or writing the files. */
    int def(FILE *source, FILE *dest, int level)
    {
    
    Here are the local variables for def(). ret will be used for zlib return codes. flush will keep track of the current flushing state for deflate(), which is either no flushing, or flush to completion after the end of the input file is reached. have is the amount of data returned from deflate(). The strm structure is used to pass information to and from the zlib routines, and to maintain the deflate() state. in and out are the input and output buffers for deflate().
    
        int ret, flush;
        unsigned have;
        z_stream strm;
        unsigned char in[CHUNK];
        unsigned char out[CHUNK];
    
    The first thing we do is to initialize the zlib state for compression using deflateInit(). This must be done before the first use of deflate(). The zalloc, zfree, and opaque fields in the strm structure must be initialized before calling deflateInit(). Here they are set to the zlib constant Z_NULL to request that zlib use the default memory allocation routines. An application may also choose to provide custom memory allocation routines here. deflateInit() will allocate on the order of 256K bytes for the internal state. (See zlib Technical Details.)

    deflateInit() is called with a pointer to the structure to be initialized and the compression level, which is an integer in the range of -1 to 9. Lower compression levels result in faster execution, but less compression. Higher levels result in greater compression, but slower execution. The zlib constant Z_DEFAULT_COMPRESSION, equal to -1, provides a good compromise between compression and speed and is equivalent to level 6. Level 0 actually does no compression at all, and in fact expands the data slightly to produce the zlib format (it is not a byte-for-byte copy of the input). More advanced applications of zlib may use deflateInit2() here instead. Such an application may want to reduce how much memory will be used, at some price in compression. Or it may need to request a gzip header and trailer instead of a zlib header and trailer, or raw encoding with no header or trailer at all.

    We must check the return value of deflateInit() against the zlib constant Z_OK to make sure that it was able to allocate memory for the internal state, and that the provided arguments were valid. deflateInit() will also check that the version of zlib that the zlib.h file came from matches the version of zlib actually linked with the program. This is especially important for environments in which zlib is a shared library.

    Note that an application can initialize multiple, independent zlib streams, which can operate in parallel. The state information maintained in the structure allows the zlib routines to be reentrant.

    
        /* allocate deflate state */
        strm.zalloc = Z_NULL;
        strm.zfree = Z_NULL;
        strm.opaque = Z_NULL;
        ret = deflateInit(&strm, level);
        if (ret != Z_OK)
            return ret;
    
    With the pleasantries out of the way, now we can get down to business. The outer do-loop reads all of the input file and exits at the bottom of the loop once end-of-file is reached. This loop contains the only call of deflate(). So we must make sure that all of the input data has been processed and that all of the output data has been generated and consumed before we fall out of the loop at the bottom.
    
        /* compress until end of file */
        do {
    
    We start off by reading data from the input file. The number of bytes read is put directly into avail_in, and a pointer to those bytes is put into next_in. We also check to see if end-of-file on the input has been reached. If we are at the end of file, then flush is set to the zlib constant Z_FINISH, which is later passed to deflate() to indicate that this is the last chunk of input data to compress. We need to use feof() to check for end-of-file as opposed to seeing if fewer than CHUNK bytes have been read. The reason is that if the input file length is an exact multiple of CHUNK, we will miss the fact that we got to the end-of-file, and not know to tell deflate() to finish up the compressed stream. If we are not yet at the end of the input, then the zlib constant Z_NO_FLUSH will be passed to deflate to indicate that we are still in the middle of the uncompressed data.

    If there is an error in reading from the input file, the process is aborted with deflateEnd() being called to free the allocated zlib state before returning the error. We wouldn't want a memory leak, now would we? deflateEnd() can be called at any time after the state has been initialized. Once that's done, deflateInit() (or deflateInit2()) would have to be called to start a new compression process. There is no point here in checking the deflateEnd() return code. The deallocation can't fail.

    
            strm.avail_in = fread(in, 1, CHUNK, source);
            if (ferror(source)) {
                (void)deflateEnd(&strm);
                return Z_ERRNO;
            }
            flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
            strm.next_in = in;
    
    The inner do-loop passes our chunk of input data to deflate(), and then keeps calling deflate() until it is done producing output. Once there is no more new output, deflate() is guaranteed to have consumed all of the input, i.e., avail_in will be zero.
    
            /* run deflate() on input until output buffer not full, finish
               compression if all of source has been read in */
            do {
    
    Output space is provided to deflate() by setting avail_out to the number of available output bytes and next_out to a pointer to that space.
    
                strm.avail_out = CHUNK;
                strm.next_out = out;
    
    Now we call the compression engine itself, deflate(). It takes as many of the avail_in bytes at next_in as it can process, and writes as many as avail_out bytes to next_out. Those counters and pointers are then updated past the input data consumed and the output data written. It is the amount of output space available that may limit how much input is consumed. Hence the inner loop to make sure that all of the input is consumed by providing more output space each time. Since avail_in and next_in are updated by deflate(), we don't have to mess with those between deflate() calls until it's all used up.

    The parameters to deflate() are a pointer to the strm structure containing the input and output information and the internal compression engine state, and a parameter indicating whether and how to flush data to the output. Normally deflate will consume several K bytes of input data before producing any output (except for the header), in order to accumulate statistics on the data for optimum compression. It will then put out a burst of compressed data, and proceed to consume more input before the next burst. Eventually, deflate() must be told to terminate the stream, complete the compression with provided input data, and write out the trailer check value. deflate() will continue to compress normally as long as the flush parameter is Z_NO_FLUSH. Once the Z_FINISH parameter is provided, deflate() will begin to complete the compressed output stream. However depending on how much output space is provided, deflate() may have to be called several times until it has provided the complete compressed stream, even after it has consumed all of the input. The flush parameter must continue to be Z_FINISH for those subsequent calls.

    There are other values of the flush parameter that are used in more advanced applications. You can force deflate() to produce a burst of output that encodes all of the input data provided so far, even if it wouldn't have otherwise, for example to control data latency on a link with compressed data. You can also ask that deflate() do that as well as erase any history up to that point so that what follows can be decompressed independently, for example for random access applications. Both requests will degrade compression by an amount depending on how often such requests are made.

    deflate() has a return value that can indicate errors, yet we do not check it here. Why not? Well, it turns out that deflate() can do no wrong here. Let's go through deflate()'s return values and dispense with them one by one. The possible values are Z_OK, Z_STREAM_END, Z_STREAM_ERROR, or Z_BUF_ERROR. Z_OK is, well, ok. Z_STREAM_END is also ok and will be returned for the last call of deflate(). This is already guaranteed by calling deflate() with Z_FINISH until it has no more output. Z_STREAM_ERROR is only possible if the stream is not initialized properly, but we did initialize it properly. There is no harm in checking for Z_STREAM_ERROR here, for example to check for the possibility that some other part of the application inadvertently clobbered the memory containing the zlib state. Z_BUF_ERROR will be explained further below, but suffice it to say that this is simply an indication that deflate() could not consume more input or produce more output. deflate() can be called again with more output space or more available input, which it will be in this code.

    
                ret = deflate(&strm, flush);    /* no bad return value */
                assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
    
    Now we compute how much output deflate() provided on the last call, which is the difference between how much space was provided before the call, and how much output space is still available after the call. Then that data, if any, is written to the output file. We can then reuse the output buffer for the next call of deflate(). Again if there is a file i/o error, we call deflateEnd() before returning to avoid a memory leak.
    
                have = CHUNK - strm.avail_out;
                if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
                    (void)deflateEnd(&strm);
                    return Z_ERRNO;
                }
    
    The inner do-loop is repeated until the last deflate() call fails to fill the provided output buffer. Then we know that deflate() has done as much as it can with the provided input, and that all of that input has been consumed. We can then fall out of this loop and reuse the input buffer.

    The way we tell that deflate() has no more output is by seeing that it did not fill the output buffer, leaving avail_out greater than zero. However suppose that deflate() has no more output, but just so happened to exactly fill the output buffer! avail_out is zero, and we can't tell that deflate() has done all it can. As far as we know, deflate() has more output for us. So we call it again. But now deflate() produces no output at all, and avail_out remains unchanged as CHUNK. That deflate() call wasn't able to do anything, either consume input or produce output, and so it returns Z_BUF_ERROR. (See, I told you I'd cover this later.) However this is not a problem at all. Now we finally have the desired indication that deflate() is really done, and so we drop out of the inner loop to provide more input to deflate().

    With flush set to Z_FINISH, this final set of deflate() calls will complete the output stream. Once that is done, subsequent calls of deflate() would return Z_STREAM_ERROR if the flush parameter is not Z_FINISH, and do no more processing until the state is reinitialized.

    Some applications of zlib have two loops that call deflate() instead of the single inner loop we have here. The first loop would call without flushing and feed all of the data to deflate(). The second loop would call deflate() with no more data and the Z_FINISH parameter to complete the process. As you can see from this example, that can be avoided by simply keeping track of the current flush state.

    
            } while (strm.avail_out == 0);
            assert(strm.avail_in == 0);     /* all input will be used */
    
    Now we check to see if we have already processed all of the input file. That information was saved in the flush variable, so we see if that was set to Z_FINISH. If so, then we're done and we fall out of the outer loop. We're guaranteed to get Z_STREAM_END from the last deflate() call, since we ran it until the last chunk of input was consumed and all of the output was generated.
    
            /* done when last data in file processed */
        } while (flush != Z_FINISH);
        assert(ret == Z_STREAM_END);        /* stream will be complete */
    
    The process is complete, but we still need to deallocate the state to avoid a memory leak (or rather more like a memory hemorrhage if you didn't do this). Then finally we can return with a happy return value.
    
        /* clean up and return */
        (void)deflateEnd(&strm);
        return Z_OK;
    }
    
    Now we do the same thing for decompression in the inf() routine. inf() decompresses what is hopefully a valid zlib stream from the input file and writes the uncompressed data to the output file. Much of the discussion above for def() applies to inf() as well, so the discussion here will focus on the differences between the two.
    
    /* Decompress from file source to file dest until stream ends or EOF.
       inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
       allocated for processing, Z_DATA_ERROR if the deflate data is
       invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
       the version of the library linked do not match, or Z_ERRNO if there
       is an error reading or writing the files. */
    int inf(FILE *source, FILE *dest)
    {
    
    The local variables have the same functionality as they do for def(). The only difference is that there is no flush variable, since inflate() can tell from the zlib stream itself when the stream is complete.
    
        int ret;
        unsigned have;
        z_stream strm;
        unsigned char in[CHUNK];
        unsigned char out[CHUNK];
    
    The initialization of the state is the same, except that there is no compression level, of course, and two more elements of the structure are initialized. avail_in and next_in must be initialized before calling inflateInit(). This is because the application has the option to provide the start of the zlib stream in order for inflateInit() to have access to information about the compression method to aid in memory allocation. In the current implementation of zlib (up through versions 1.2.x), the method-dependent memory allocations are deferred to the first call of inflate() anyway. However those fields must be initialized since later versions of zlib that provide more compression methods may take advantage of this interface. In any case, no decompression is performed by inflateInit(), so the avail_out and next_out fields do not need to be initialized before calling.

    Here avail_in is set to zero and next_in is set to Z_NULL to indicate that no input data is being provided.

    
        /* allocate inflate state */
        strm.zalloc = Z_NULL;
        strm.zfree = Z_NULL;
        strm.opaque = Z_NULL;
        strm.avail_in = 0;
        strm.next_in = Z_NULL;
        ret = inflateInit(&strm);
        if (ret != Z_OK)
            return ret;
    
    The outer do-loop decompresses input until inflate() indicates that it has reached the end of the compressed data and has produced all of the uncompressed output. This is in contrast to def() which processes all of the input file. If end-of-file is reached before the compressed data self-terminates, then the compressed data is incomplete and an error is returned.
    
        /* decompress until deflate stream ends or end of file */
        do {
    
    We read input data and set the strm structure accordingly. If we've reached the end of the input file, then we leave the outer loop and report an error, since the compressed data is incomplete. Note that we may read more data than is eventually consumed by inflate(), if the input file continues past the zlib stream. For applications where zlib streams are embedded in other data, this routine would need to be modified to return the unused data, or at least indicate how much of the input data was not used, so the application would know where to pick up after the zlib stream.
    
            strm.avail_in = fread(in, 1, CHUNK, source);
            if (ferror(source)) {
                (void)inflateEnd(&strm);
                return Z_ERRNO;
            }
            if (strm.avail_in == 0)
                break;
            strm.next_in = in;
    
    The inner do-loop has the same function it did in def(), which is to keep calling inflate() until has generated all of the output it can with the provided input.
    
            /* run inflate() on input until output buffer not full */
            do {
    
    Just like in def(), the same output space is provided for each call of inflate().
    
                strm.avail_out = CHUNK;
                strm.next_out = out;
    
    Now we run the decompression engine itself. There is no need to adjust the flush parameter, since the zlib format is self-terminating. The main difference here is that there are return values that we need to pay attention to. Z_DATA_ERROR indicates that inflate() detected an error in the zlib compressed data format, which means that either the data is not a zlib stream to begin with, or that the data was corrupted somewhere along the way since it was compressed. The other error to be processed is Z_MEM_ERROR, which can occur since memory allocation is deferred until inflate() needs it, unlike deflate(), whose memory is allocated at the start by deflateInit().

    Advanced applications may use deflateSetDictionary() to prime deflate() with a set of likely data to improve the first 32K or so of compression. This is noted in the zlib header, so inflate() requests that that dictionary be provided before it can start to decompress. Without the dictionary, correct decompression is not possible. For this routine, we have no idea what the dictionary is, so the Z_NEED_DICT indication is converted to a Z_DATA_ERROR.

    inflate() can also return Z_STREAM_ERROR, which should not be possible here, but could be checked for as noted above for def(). Z_BUF_ERROR does not need to be checked for here, for the same reasons noted for def(). Z_STREAM_END will be checked for later.

    
                ret = inflate(&strm, Z_NO_FLUSH);
                assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
                switch (ret) {
                case Z_NEED_DICT:
                    ret = Z_DATA_ERROR;     /* and fall through */
                case Z_DATA_ERROR:
                case Z_MEM_ERROR:
                    (void)inflateEnd(&strm);
                    return ret;
                }
    
    The output of inflate() is handled identically to that of deflate().
    
                have = CHUNK - strm.avail_out;
                if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
                    (void)inflateEnd(&strm);
                    return Z_ERRNO;
                }
    
    The inner do-loop ends when inflate() has no more output as indicated by not filling the output buffer, just as for deflate(). In this case, we cannot assert that strm.avail_in will be zero, since the deflate stream may end before the file does.
    
            } while (strm.avail_out == 0);
    
    The outer do-loop ends when inflate() reports that it has reached the end of the input zlib stream, has completed the decompression and integrity check, and has provided all of the output. This is indicated by the inflate() return value Z_STREAM_END. The inner loop is guaranteed to leave ret equal to Z_STREAM_END if the last chunk of the input file read contained the end of the zlib stream. So if the return value is not Z_STREAM_END, the loop continues to read more input.
    
            /* done when inflate() says it's done */
        } while (ret != Z_STREAM_END);
    
    At this point, decompression successfully completed, or we broke out of the loop due to no more data being available from the input file. If the last inflate() return value is not Z_STREAM_END, then the zlib stream was incomplete and a data error is returned. Otherwise, we return with a happy return value. Of course, inflateEnd() is called first to avoid a memory leak.
    
        /* clean up and return */
        (void)inflateEnd(&strm);
        return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
    }
    
    That ends the routines that directly use zlib. The following routines make this a command-line program by running data through the above routines from stdin to stdout, and handling any errors reported by def() or inf().

    zerr() is used to interpret the possible error codes from def() and inf(), as detailed in their comments above, and print out an error message. Note that these are only a subset of the possible return values from deflate() and inflate().

    
    /* report a zlib or i/o error */
    void zerr(int ret)
    {
        fputs("zpipe: ", stderr);
        switch (ret) {
        case Z_ERRNO:
            if (ferror(stdin))
                fputs("error reading stdin\n", stderr);
            if (ferror(stdout))
                fputs("error writing stdout\n", stderr);
            break;
        case Z_STREAM_ERROR:
            fputs("invalid compression level\n", stderr);
            break;
        case Z_DATA_ERROR:
            fputs("invalid or incomplete deflate data\n", stderr);
            break;
        case Z_MEM_ERROR:
            fputs("out of memory\n", stderr);
            break;
        case Z_VERSION_ERROR:
            fputs("zlib version mismatch!\n", stderr);
        }
    }
    
    Here is the main() routine used to test def() and inf(). The zpipe command is simply a compression pipe from stdin to stdout, if no arguments are given, or it is a decompression pipe if zpipe -d is used. If any other arguments are provided, no compression or decompression is performed. Instead a usage message is displayed. Examples are zpipe < foo.txt > foo.txt.z to compress, and zpipe -d < foo.txt.z > foo.txt to decompress.
    
    /* compress or decompress from stdin to stdout */
    int main(int argc, char **argv)
    {
        int ret;
    
        /* avoid end-of-line conversions */
        SET_BINARY_MODE(stdin);
        SET_BINARY_MODE(stdout);
    
        /* do compression if no arguments */
        if (argc == 1) {
            ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
            if (ret != Z_OK)
                zerr(ret);
            return ret;
        }
    
        /* do decompression if -d specified */
        else if (argc == 2 && strcmp(argv[1], "-d") == 0) {
            ret = inf(stdin, stdout);
            if (ret != Z_OK)
                zerr(ret);
            return ret;
        }
    
        /* otherwise, report usage */
        else {
            fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
            return 1;
        }
    }
    

    Copyright (c) 2004, 2005 by Mark Adler
    Last modified 11 December 2005
    tcl8.6.5/compat/zlib/examples/fitblk.c0000644000175000017500000002062212663653131017245 0ustar sergeisergei/* fitblk.c: example of fitting compressed output to a specified size Not copyrighted -- provided to the public domain Version 1.1 25 November 2004 Mark Adler */ /* Version history: 1.0 24 Nov 2004 First version 1.1 25 Nov 2004 Change deflateInit2() to deflateInit() Use fixed-size, stack-allocated raw buffers Simplify code moving compression to subroutines Use assert() for internal errors Add detailed description of approach */ /* Approach to just fitting a requested compressed size: fitblk performs three compression passes on a portion of the input data in order to determine how much of that input will compress to nearly the requested output block size. The first pass generates enough deflate blocks to produce output to fill the requested output size plus a specfied excess amount (see the EXCESS define below). The last deflate block may go quite a bit past that, but is discarded. The second pass decompresses and recompresses just the compressed data that fit in the requested plus excess sized buffer. The deflate process is terminated after that amount of input, which is less than the amount consumed on the first pass. The last deflate block of the result will be of a comparable size to the final product, so that the header for that deflate block and the compression ratio for that block will be about the same as in the final product. The third compression pass decompresses the result of the second step, but only the compressed data up to the requested size minus an amount to allow the compressed stream to complete (see the MARGIN define below). That will result in a final compressed stream whose length is less than or equal to the requested size. Assuming sufficient input and a requested size greater than a few hundred bytes, the shortfall will typically be less than ten bytes. If the input is short enough that the first compression completes before filling the requested output size, then that compressed stream is return with no recompression. EXCESS is chosen to be just greater than the shortfall seen in a two pass approach similar to the above. That shortfall is due to the last deflate block compressing more efficiently with a smaller header on the second pass. EXCESS is set to be large enough so that there is enough uncompressed data for the second pass to fill out the requested size, and small enough so that the final deflate block of the second pass will be close in size to the final deflate block of the third and final pass. MARGIN is chosen to be just large enough to assure that the final compression has enough room to complete in all cases. */ #include #include #include #include "zlib.h" #define local static /* print nastygram and leave */ local void quit(char *why) { fprintf(stderr, "fitblk abort: %s\n", why); exit(1); } #define RAWLEN 4096 /* intermediate uncompressed buffer size */ /* compress from file to def until provided buffer is full or end of input reached; return last deflate() return value, or Z_ERRNO if there was read error on the file */ local int partcompress(FILE *in, z_streamp def) { int ret, flush; unsigned char raw[RAWLEN]; flush = Z_NO_FLUSH; do { def->avail_in = fread(raw, 1, RAWLEN, in); if (ferror(in)) return Z_ERRNO; def->next_in = raw; if (feof(in)) flush = Z_FINISH; ret = deflate(def, flush); assert(ret != Z_STREAM_ERROR); } while (def->avail_out != 0 && flush == Z_NO_FLUSH); return ret; } /* recompress from inf's input to def's output; the input for inf and the output for def are set in those structures before calling; return last deflate() return value, or Z_MEM_ERROR if inflate() was not able to allocate enough memory when it needed to */ local int recompress(z_streamp inf, z_streamp def) { int ret, flush; unsigned char raw[RAWLEN]; flush = Z_NO_FLUSH; do { /* decompress */ inf->avail_out = RAWLEN; inf->next_out = raw; ret = inflate(inf, Z_NO_FLUSH); assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR && ret != Z_NEED_DICT); if (ret == Z_MEM_ERROR) return ret; /* compress what was decompresed until done or no room */ def->avail_in = RAWLEN - inf->avail_out; def->next_in = raw; if (inf->avail_out != 0) flush = Z_FINISH; ret = deflate(def, flush); assert(ret != Z_STREAM_ERROR); } while (ret != Z_STREAM_END && def->avail_out != 0); return ret; } #define EXCESS 256 /* empirically determined stream overage */ #define MARGIN 8 /* amount to back off for completion */ /* compress from stdin to fixed-size block on stdout */ int main(int argc, char **argv) { int ret; /* return code */ unsigned size; /* requested fixed output block size */ unsigned have; /* bytes written by deflate() call */ unsigned char *blk; /* intermediate and final stream */ unsigned char *tmp; /* close to desired size stream */ z_stream def, inf; /* zlib deflate and inflate states */ /* get requested output size */ if (argc != 2) quit("need one argument: size of output block"); ret = strtol(argv[1], argv + 1, 10); if (argv[1][0] != 0) quit("argument must be a number"); if (ret < 8) /* 8 is minimum zlib stream size */ quit("need positive size of 8 or greater"); size = (unsigned)ret; /* allocate memory for buffers and compression engine */ blk = malloc(size + EXCESS); def.zalloc = Z_NULL; def.zfree = Z_NULL; def.opaque = Z_NULL; ret = deflateInit(&def, Z_DEFAULT_COMPRESSION); if (ret != Z_OK || blk == NULL) quit("out of memory"); /* compress from stdin until output full, or no more input */ def.avail_out = size + EXCESS; def.next_out = blk; ret = partcompress(stdin, &def); if (ret == Z_ERRNO) quit("error reading input"); /* if it all fit, then size was undersubscribed -- done! */ if (ret == Z_STREAM_END && def.avail_out >= EXCESS) { /* write block to stdout */ have = size + EXCESS - def.avail_out; if (fwrite(blk, 1, have, stdout) != have || ferror(stdout)) quit("error writing output"); /* clean up and print results to stderr */ ret = deflateEnd(&def); assert(ret != Z_STREAM_ERROR); free(blk); fprintf(stderr, "%u bytes unused out of %u requested (all input)\n", size - have, size); return 0; } /* it didn't all fit -- set up for recompression */ inf.zalloc = Z_NULL; inf.zfree = Z_NULL; inf.opaque = Z_NULL; inf.avail_in = 0; inf.next_in = Z_NULL; ret = inflateInit(&inf); tmp = malloc(size + EXCESS); if (ret != Z_OK || tmp == NULL) quit("out of memory"); ret = deflateReset(&def); assert(ret != Z_STREAM_ERROR); /* do first recompression close to the right amount */ inf.avail_in = size + EXCESS; inf.next_in = blk; def.avail_out = size + EXCESS; def.next_out = tmp; ret = recompress(&inf, &def); if (ret == Z_MEM_ERROR) quit("out of memory"); /* set up for next reocmpression */ ret = inflateReset(&inf); assert(ret != Z_STREAM_ERROR); ret = deflateReset(&def); assert(ret != Z_STREAM_ERROR); /* do second and final recompression (third compression) */ inf.avail_in = size - MARGIN; /* assure stream will complete */ inf.next_in = tmp; def.avail_out = size; def.next_out = blk; ret = recompress(&inf, &def); if (ret == Z_MEM_ERROR) quit("out of memory"); assert(ret == Z_STREAM_END); /* otherwise MARGIN too small */ /* done -- write block to stdout */ have = size - def.avail_out; if (fwrite(blk, 1, have, stdout) != have || ferror(stdout)) quit("error writing output"); /* clean up and print results to stderr */ free(tmp); ret = inflateEnd(&inf); assert(ret != Z_STREAM_ERROR); ret = deflateEnd(&def); assert(ret != Z_STREAM_ERROR); free(blk); fprintf(stderr, "%u bytes unused out of %u requested (%lu input)\n", size - have, size, def.total_in); return 0; } tcl8.6.5/compat/zlib/examples/README.examples0000644000175000017500000000343112663653206020325 0ustar sergeisergeiThis directory contains examples of the use of zlib and other relevant programs and documentation. enough.c calculation and justification of ENOUGH parameter in inftrees.h - calculates the maximum table space used in inflate tree construction over all possible Huffman codes fitblk.c compress just enough input to nearly fill a requested output size - zlib isn't designed to do this, but fitblk does it anyway gun.c uncompress a gzip file - illustrates the use of inflateBack() for high speed file-to-file decompression using call-back functions - is approximately twice as fast as gzip -d - also provides Unix uncompress functionality, again twice as fast gzappend.c append to a gzip file - illustrates the use of the Z_BLOCK flush parameter for inflate() - illustrates the use of deflatePrime() to start at any bit gzjoin.c join gzip files without recalculating the crc or recompressing - illustrates the use of the Z_BLOCK flush parameter for inflate() - illustrates the use of crc32_combine() gzlog.c gzlog.h efficiently and robustly maintain a message log file in gzip format - illustrates use of raw deflate, Z_PARTIAL_FLUSH, deflatePrime(), and deflateSetDictionary() - illustrates use of a gzip header extra field zlib_how.html painfully comprehensive description of zpipe.c (see below) - describes in excruciating detail the use of deflate() and inflate() zpipe.c reads and writes zlib streams from stdin to stdout - illustrates the proper use of deflate() and inflate() - deeply commented in zlib_how.html (see above) zran.c index a zlib or gzip stream and randomly access it - illustrates the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() to provide random access tcl8.6.5/compat/zlib/examples/gzappend.c0000644000175000017500000004112112663660065017603 0ustar sergeisergei/* gzappend -- command to append to a gzip file Copyright (C) 2003, 2012 Mark Adler, all rights reserved version 1.2, 11 Oct 2012 This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Mark Adler madler@alumni.caltech.edu */ /* * Change history: * * 1.0 19 Oct 2003 - First version * 1.1 4 Nov 2003 - Expand and clarify some comments and notes * - Add version and copyright to help * - Send help to stdout instead of stderr * - Add some preemptive typecasts * - Add L to constants in lseek() calls * - Remove some debugging information in error messages * - Use new data_type definition for zlib 1.2.1 * - Simplfy and unify file operations * - Finish off gzip file in gztack() * - Use deflatePrime() instead of adding empty blocks * - Keep gzip file clean on appended file read errors * - Use in-place rotate instead of auxiliary buffer * (Why you ask? Because it was fun to write!) * 1.2 11 Oct 2012 - Fix for proper z_const usage * - Check for input buffer malloc failure */ /* gzappend takes a gzip file and appends to it, compressing files from the command line or data from stdin. The gzip file is written to directly, to avoid copying that file, in case it's large. Note that this results in the unfriendly behavior that if gzappend fails, the gzip file is corrupted. This program was written to illustrate the use of the new Z_BLOCK option of zlib 1.2.x's inflate() function. This option returns from inflate() at each block boundary to facilitate locating and modifying the last block bit at the start of the final deflate block. Also whether using Z_BLOCK or not, another required feature of zlib 1.2.x is that inflate() now provides the number of unusued bits in the last input byte used. gzappend will not work with versions of zlib earlier than 1.2.1. gzappend first decompresses the gzip file internally, discarding all but the last 32K of uncompressed data, and noting the location of the last block bit and the number of unused bits in the last byte of the compressed data. The gzip trailer containing the CRC-32 and length of the uncompressed data is verified. This trailer will be later overwritten. Then the last block bit is cleared by seeking back in the file and rewriting the byte that contains it. Seeking forward, the last byte of the compressed data is saved along with the number of unused bits to initialize deflate. A deflate process is initialized, using the last 32K of the uncompressed data from the gzip file to initialize the dictionary. If the total uncompressed data was less than 32K, then all of it is used to initialize the dictionary. The deflate output bit buffer is also initialized with the last bits from the original deflate stream. From here on, the data to append is simply compressed using deflate, and written to the gzip file. When that is complete, the new CRC-32 and uncompressed length are written as the trailer of the gzip file. */ #include #include #include #include #include #include "zlib.h" #define local static #define LGCHUNK 14 #define CHUNK (1U << LGCHUNK) #define DSIZE 32768U /* print an error message and terminate with extreme prejudice */ local void bye(char *msg1, char *msg2) { fprintf(stderr, "gzappend error: %s%s\n", msg1, msg2); exit(1); } /* return the greatest common divisor of a and b using Euclid's algorithm, modified to be fast when one argument much greater than the other, and coded to avoid unnecessary swapping */ local unsigned gcd(unsigned a, unsigned b) { unsigned c; while (a && b) if (a > b) { c = b; while (a - c >= c) c <<= 1; a -= c; } else { c = a; while (b - c >= c) c <<= 1; b -= c; } return a + b; } /* rotate list[0..len-1] left by rot positions, in place */ local void rotate(unsigned char *list, unsigned len, unsigned rot) { unsigned char tmp; unsigned cycles; unsigned char *start, *last, *to, *from; /* normalize rot and handle degenerate cases */ if (len < 2) return; if (rot >= len) rot %= len; if (rot == 0) return; /* pointer to last entry in list */ last = list + (len - 1); /* do simple left shift by one */ if (rot == 1) { tmp = *list; memcpy(list, list + 1, len - 1); *last = tmp; return; } /* do simple right shift by one */ if (rot == len - 1) { tmp = *last; memmove(list + 1, list, len - 1); *list = tmp; return; } /* otherwise do rotate as a set of cycles in place */ cycles = gcd(len, rot); /* number of cycles */ do { start = from = list + cycles; /* start index is arbitrary */ tmp = *from; /* save entry to be overwritten */ for (;;) { to = from; /* next step in cycle */ from += rot; /* go right rot positions */ if (from > last) from -= len; /* (pointer better not wrap) */ if (from == start) break; /* all but one shifted */ *to = *from; /* shift left */ } *to = tmp; /* complete the circle */ } while (--cycles); } /* structure for gzip file read operations */ typedef struct { int fd; /* file descriptor */ int size; /* 1 << size is bytes in buf */ unsigned left; /* bytes available at next */ unsigned char *buf; /* buffer */ z_const unsigned char *next; /* next byte in buffer */ char *name; /* file name for error messages */ } file; /* reload buffer */ local int readin(file *in) { int len; len = read(in->fd, in->buf, 1 << in->size); if (len == -1) bye("error reading ", in->name); in->left = (unsigned)len; in->next = in->buf; return len; } /* read from file in, exit if end-of-file */ local int readmore(file *in) { if (readin(in) == 0) bye("unexpected end of ", in->name); return 0; } #define read1(in) (in->left == 0 ? readmore(in) : 0, \ in->left--, *(in->next)++) /* skip over n bytes of in */ local void skip(file *in, unsigned n) { unsigned bypass; if (n > in->left) { n -= in->left; bypass = n & ~((1U << in->size) - 1); if (bypass) { if (lseek(in->fd, (off_t)bypass, SEEK_CUR) == -1) bye("seeking ", in->name); n -= bypass; } readmore(in); if (n > in->left) bye("unexpected end of ", in->name); } in->left -= n; in->next += n; } /* read a four-byte unsigned integer, little-endian, from in */ unsigned long read4(file *in) { unsigned long val; val = read1(in); val += (unsigned)read1(in) << 8; val += (unsigned long)read1(in) << 16; val += (unsigned long)read1(in) << 24; return val; } /* skip over gzip header */ local void gzheader(file *in) { int flags; unsigned n; if (read1(in) != 31 || read1(in) != 139) bye(in->name, " not a gzip file"); if (read1(in) != 8) bye("unknown compression method in", in->name); flags = read1(in); if (flags & 0xe0) bye("unknown header flags set in", in->name); skip(in, 6); if (flags & 4) { n = read1(in); n += (unsigned)(read1(in)) << 8; skip(in, n); } if (flags & 8) while (read1(in) != 0) ; if (flags & 16) while (read1(in) != 0) ; if (flags & 2) skip(in, 2); } /* decompress gzip file "name", return strm with a deflate stream ready to continue compression of the data in the gzip file, and return a file descriptor pointing to where to write the compressed data -- the deflate stream is initialized to compress using level "level" */ local int gzscan(char *name, z_stream *strm, int level) { int ret, lastbit, left, full; unsigned have; unsigned long crc, tot; unsigned char *window; off_t lastoff, end; file gz; /* open gzip file */ gz.name = name; gz.fd = open(name, O_RDWR, 0); if (gz.fd == -1) bye("cannot open ", name); gz.buf = malloc(CHUNK); if (gz.buf == NULL) bye("out of memory", ""); gz.size = LGCHUNK; gz.left = 0; /* skip gzip header */ gzheader(&gz); /* prepare to decompress */ window = malloc(DSIZE); if (window == NULL) bye("out of memory", ""); strm->zalloc = Z_NULL; strm->zfree = Z_NULL; strm->opaque = Z_NULL; ret = inflateInit2(strm, -15); if (ret != Z_OK) bye("out of memory", " or library mismatch"); /* decompress the deflate stream, saving append information */ lastbit = 0; lastoff = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; left = 0; strm->avail_in = gz.left; strm->next_in = gz.next; crc = crc32(0L, Z_NULL, 0); have = full = 0; do { /* if needed, get more input */ if (strm->avail_in == 0) { readmore(&gz); strm->avail_in = gz.left; strm->next_in = gz.next; } /* set up output to next available section of sliding window */ strm->avail_out = DSIZE - have; strm->next_out = window + have; /* inflate and check for errors */ ret = inflate(strm, Z_BLOCK); if (ret == Z_STREAM_ERROR) bye("internal stream error!", ""); if (ret == Z_MEM_ERROR) bye("out of memory", ""); if (ret == Z_DATA_ERROR) bye("invalid compressed data--format violated in", name); /* update crc and sliding window pointer */ crc = crc32(crc, window + have, DSIZE - have - strm->avail_out); if (strm->avail_out) have = DSIZE - strm->avail_out; else { have = 0; full = 1; } /* process end of block */ if (strm->data_type & 128) { if (strm->data_type & 64) left = strm->data_type & 0x1f; else { lastbit = strm->data_type & 0x1f; lastoff = lseek(gz.fd, 0L, SEEK_CUR) - strm->avail_in; } } } while (ret != Z_STREAM_END); inflateEnd(strm); gz.left = strm->avail_in; gz.next = strm->next_in; /* save the location of the end of the compressed data */ end = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; /* check gzip trailer and save total for deflate */ if (crc != read4(&gz)) bye("invalid compressed data--crc mismatch in ", name); tot = strm->total_out; if ((tot & 0xffffffffUL) != read4(&gz)) bye("invalid compressed data--length mismatch in", name); /* if not at end of file, warn */ if (gz.left || readin(&gz)) fprintf(stderr, "gzappend warning: junk at end of gzip file overwritten\n"); /* clear last block bit */ lseek(gz.fd, lastoff - (lastbit != 0), SEEK_SET); if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); *gz.buf = (unsigned char)(*gz.buf ^ (1 << ((8 - lastbit) & 7))); lseek(gz.fd, -1L, SEEK_CUR); if (write(gz.fd, gz.buf, 1) != 1) bye("writing after seek to ", name); /* if window wrapped, build dictionary from window by rotating */ if (full) { rotate(window, DSIZE, have); have = DSIZE; } /* set up deflate stream with window, crc, total_in, and leftover bits */ ret = deflateInit2(strm, level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); if (ret != Z_OK) bye("out of memory", ""); deflateSetDictionary(strm, window, have); strm->adler = crc; strm->total_in = tot; if (left) { lseek(gz.fd, --end, SEEK_SET); if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); deflatePrime(strm, 8 - left, *gz.buf); } lseek(gz.fd, end, SEEK_SET); /* clean up and return */ free(window); free(gz.buf); return gz.fd; } /* append file "name" to gzip file gd using deflate stream strm -- if last is true, then finish off the deflate stream at the end */ local void gztack(char *name, int gd, z_stream *strm, int last) { int fd, len, ret; unsigned left; unsigned char *in, *out; /* open file to compress and append */ fd = 0; if (name != NULL) { fd = open(name, O_RDONLY, 0); if (fd == -1) fprintf(stderr, "gzappend warning: %s not found, skipping ...\n", name); } /* allocate buffers */ in = malloc(CHUNK); out = malloc(CHUNK); if (in == NULL || out == NULL) bye("out of memory", ""); /* compress input file and append to gzip file */ do { /* get more input */ len = read(fd, in, CHUNK); if (len == -1) { fprintf(stderr, "gzappend warning: error reading %s, skipping rest ...\n", name); len = 0; } strm->avail_in = (unsigned)len; strm->next_in = in; if (len) strm->adler = crc32(strm->adler, in, (unsigned)len); /* compress and write all available output */ do { strm->avail_out = CHUNK; strm->next_out = out; ret = deflate(strm, last && len == 0 ? Z_FINISH : Z_NO_FLUSH); left = CHUNK - strm->avail_out; while (left) { len = write(gd, out + CHUNK - strm->avail_out - left, left); if (len == -1) bye("writing gzip file", ""); left -= (unsigned)len; } } while (strm->avail_out == 0 && ret != Z_STREAM_END); } while (len != 0); /* write trailer after last entry */ if (last) { deflateEnd(strm); out[0] = (unsigned char)(strm->adler); out[1] = (unsigned char)(strm->adler >> 8); out[2] = (unsigned char)(strm->adler >> 16); out[3] = (unsigned char)(strm->adler >> 24); out[4] = (unsigned char)(strm->total_in); out[5] = (unsigned char)(strm->total_in >> 8); out[6] = (unsigned char)(strm->total_in >> 16); out[7] = (unsigned char)(strm->total_in >> 24); len = 8; do { ret = write(gd, out + 8 - len, len); if (ret == -1) bye("writing gzip file", ""); len -= ret; } while (len); close(gd); } /* clean up and return */ free(out); free(in); if (fd > 0) close(fd); } /* process the compression level option if present, scan the gzip file, and append the specified files, or append the data from stdin if no other file names are provided on the command line -- the gzip file must be writable and seekable */ int main(int argc, char **argv) { int gd, level; z_stream strm; /* ignore command name */ argc--; argv++; /* provide usage if no arguments */ if (*argv == NULL) { printf( "gzappend 1.2 (11 Oct 2012) Copyright (C) 2003, 2012 Mark Adler\n" ); printf( "usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n"); return 0; } /* set compression level */ level = Z_DEFAULT_COMPRESSION; if (argv[0][0] == '-') { if (argv[0][1] < '0' || argv[0][1] > '9' || argv[0][2] != 0) bye("invalid compression level", ""); level = argv[0][1] - '0'; if (*++argv == NULL) bye("no gzip file name after options", ""); } /* prepare to append to gzip file */ gd = gzscan(*argv++, &strm, level); /* append files on command line, or from stdin if none */ if (*argv == NULL) gztack(NULL, gd, &strm, 1); else do { gztack(*argv, gd, &strm, argv[1] == NULL); } while (*++argv != NULL); return 0; } tcl8.6.5/compat/zlib/examples/zran.c0000644000175000017500000003611612663660065016755 0ustar sergeisergei/* zran.c -- example of zlib/gzip stream indexing and random access * Copyright (C) 2005, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h Version 1.1 29 Sep 2012 Mark Adler */ /* Version History: 1.0 29 May 2005 First version 1.1 29 Sep 2012 Fix memory reallocation error */ /* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() for random access of a compressed file. A file containing a zlib or gzip stream is provided on the command line. The compressed stream is decoded in its entirety, and an index built with access points about every SPAN bytes in the uncompressed output. The compressed file is left open, and can then be read randomly, having to decompress on the average SPAN/2 uncompressed bytes before getting to the desired block of data. An access point can be created at the start of any deflate block, by saving the starting file offset and bit of that block, and the 32K bytes of uncompressed data that precede that block. Also the uncompressed offset of that block is saved to provide a referece for locating a desired starting point in the uncompressed stream. build_index() works by decompressing the input zlib or gzip stream a block at a time, and at the end of each block deciding if enough uncompressed data has gone by to justify the creation of a new access point. If so, that point is saved in a data structure that grows as needed to accommodate the points. To use the index, an offset in the uncompressed data is provided, for which the latest accees point at or preceding that offset is located in the index. The input file is positioned to the specified location in the index, and if necessary the first few bits of the compressed data is read from the file. inflate is initialized with those bits and the 32K of uncompressed data, and the decompression then proceeds until the desired offset in the file is reached. Then the decompression continues to read the desired uncompressed data from the file. Another approach would be to generate the index on demand. In that case, requests for random access reads from the compressed data would try to use the index, but if a read far enough past the end of the index is required, then further index entries would be generated and added. There is some fair bit of overhead to starting inflation for the random access, mainly copying the 32K byte dictionary. So if small pieces of the file are being accessed, it would make sense to implement a cache to hold some lookahead and avoid many calls to extract() for small lengths. Another way to build an index would be to use inflateCopy(). That would not be constrained to have access points at block boundaries, but requires more memory per access point, and also cannot be saved to file due to the use of pointers in the state. The approach here allows for storage of the index in a file. */ #include #include #include #include "zlib.h" #define local static #define SPAN 1048576L /* desired distance between access points */ #define WINSIZE 32768U /* sliding window size */ #define CHUNK 16384 /* file input buffer size */ /* access point entry */ struct point { off_t out; /* corresponding offset in uncompressed data */ off_t in; /* offset in input file of first full byte */ int bits; /* number of bits (1-7) from byte at in - 1, or 0 */ unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */ }; /* access point list */ struct access { int have; /* number of list entries filled in */ int size; /* number of list entries allocated */ struct point *list; /* allocated list */ }; /* Deallocate an index built by build_index() */ local void free_index(struct access *index) { if (index != NULL) { free(index->list); free(index); } } /* Add an entry to the access point list. If out of memory, deallocate the existing list and return NULL. */ local struct access *addpoint(struct access *index, int bits, off_t in, off_t out, unsigned left, unsigned char *window) { struct point *next; /* if list is empty, create it (start with eight points) */ if (index == NULL) { index = malloc(sizeof(struct access)); if (index == NULL) return NULL; index->list = malloc(sizeof(struct point) << 3); if (index->list == NULL) { free(index); return NULL; } index->size = 8; index->have = 0; } /* if list is full, make it bigger */ else if (index->have == index->size) { index->size <<= 1; next = realloc(index->list, sizeof(struct point) * index->size); if (next == NULL) { free_index(index); return NULL; } index->list = next; } /* fill in entry and increment how many we have */ next = index->list + index->have; next->bits = bits; next->in = in; next->out = out; if (left) memcpy(next->window, window + WINSIZE - left, left); if (left < WINSIZE) memcpy(next->window + left, window, WINSIZE - left); index->have++; /* return list, possibly reallocated */ return index; } /* Make one entire pass through the compressed stream and build an index, with access points about every span bytes of uncompressed output -- span is chosen to balance the speed of random access against the memory requirements of the list, about 32K bytes per access point. Note that data after the end of the first zlib or gzip stream in the file is ignored. build_index() returns the number of access points on success (>= 1), Z_MEM_ERROR for out of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a file read error. On success, *built points to the resulting index. */ local int build_index(FILE *in, off_t span, struct access **built) { int ret; off_t totin, totout; /* our own total counters to avoid 4GB limit */ off_t last; /* totout value of last access point */ struct access *index; /* access points being generated */ z_stream strm; unsigned char input[CHUNK]; unsigned char window[WINSIZE]; /* initialize inflate */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */ if (ret != Z_OK) return ret; /* inflate the input, maintain a sliding window, and build an index -- this also validates the integrity of the compressed data using the check information at the end of the gzip or zlib stream */ totin = totout = last = 0; index = NULL; /* will be allocated by first addpoint() */ strm.avail_out = 0; do { /* get some compressed data from input file */ strm.avail_in = fread(input, 1, CHUNK, in); if (ferror(in)) { ret = Z_ERRNO; goto build_index_error; } if (strm.avail_in == 0) { ret = Z_DATA_ERROR; goto build_index_error; } strm.next_in = input; /* process all of that, or until end of stream */ do { /* reset sliding window if necessary */ if (strm.avail_out == 0) { strm.avail_out = WINSIZE; strm.next_out = window; } /* inflate until out of input, output, or at end of block -- update the total input and output counters */ totin += strm.avail_in; totout += strm.avail_out; ret = inflate(&strm, Z_BLOCK); /* return at end of block */ totin -= strm.avail_in; totout -= strm.avail_out; if (ret == Z_NEED_DICT) ret = Z_DATA_ERROR; if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) goto build_index_error; if (ret == Z_STREAM_END) break; /* if at end of block, consider adding an index entry (note that if data_type indicates an end-of-block, then all of the uncompressed data from that block has been delivered, and none of the compressed data after that block has been consumed, except for up to seven bits) -- the totout == 0 provides an entry point after the zlib or gzip header, and assures that the index always has at least one access point; we avoid creating an access point after the last block by checking bit 6 of data_type */ if ((strm.data_type & 128) && !(strm.data_type & 64) && (totout == 0 || totout - last > span)) { index = addpoint(index, strm.data_type & 7, totin, totout, strm.avail_out, window); if (index == NULL) { ret = Z_MEM_ERROR; goto build_index_error; } last = totout; } } while (strm.avail_in != 0); } while (ret != Z_STREAM_END); /* clean up and return index (release unused entries in list) */ (void)inflateEnd(&strm); index->list = realloc(index->list, sizeof(struct point) * index->have); index->size = index->have; *built = index; return index->size; /* return error */ build_index_error: (void)inflateEnd(&strm); if (index != NULL) free_index(index); return ret; } /* Use the index to read len bytes from offset into buf, return bytes read or negative for error (Z_DATA_ERROR or Z_MEM_ERROR). If data is requested past the end of the uncompressed data, then extract() will return a value less than len, indicating how much as actually read into buf. This function should not return a data error unless the file was modified since the index was generated. extract() may also return Z_ERRNO if there is an error on reading or seeking the input file. */ local int extract(FILE *in, struct access *index, off_t offset, unsigned char *buf, int len) { int ret, skip; z_stream strm; struct point *here; unsigned char input[CHUNK]; unsigned char discard[WINSIZE]; /* proceed only if something reasonable to do */ if (len < 0) return 0; /* find where in stream to start */ here = index->list; ret = index->have; while (--ret && here[1].out <= offset) here++; /* initialize file and inflate state to start there */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit2(&strm, -15); /* raw inflate */ if (ret != Z_OK) return ret; ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET); if (ret == -1) goto extract_ret; if (here->bits) { ret = getc(in); if (ret == -1) { ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR; goto extract_ret; } (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits)); } (void)inflateSetDictionary(&strm, here->window, WINSIZE); /* skip uncompressed bytes until offset reached, then satisfy request */ offset -= here->out; strm.avail_in = 0; skip = 1; /* while skipping to offset */ do { /* define where to put uncompressed data, and how much */ if (offset == 0 && skip) { /* at offset now */ strm.avail_out = len; strm.next_out = buf; skip = 0; /* only do this once */ } if (offset > WINSIZE) { /* skip WINSIZE bytes */ strm.avail_out = WINSIZE; strm.next_out = discard; offset -= WINSIZE; } else if (offset != 0) { /* last skip */ strm.avail_out = (unsigned)offset; strm.next_out = discard; offset = 0; } /* uncompress until avail_out filled, or end of stream */ do { if (strm.avail_in == 0) { strm.avail_in = fread(input, 1, CHUNK, in); if (ferror(in)) { ret = Z_ERRNO; goto extract_ret; } if (strm.avail_in == 0) { ret = Z_DATA_ERROR; goto extract_ret; } strm.next_in = input; } ret = inflate(&strm, Z_NO_FLUSH); /* normal inflate */ if (ret == Z_NEED_DICT) ret = Z_DATA_ERROR; if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) goto extract_ret; if (ret == Z_STREAM_END) break; } while (strm.avail_out != 0); /* if reach end of stream, then don't keep trying to get more */ if (ret == Z_STREAM_END) break; /* do until offset reached and requested data read, or stream ends */ } while (skip); /* compute number of uncompressed bytes read after offset */ ret = skip ? 0 : len - strm.avail_out; /* clean up and return bytes read or error */ extract_ret: (void)inflateEnd(&strm); return ret; } /* Demonstrate the use of build_index() and extract() by processing the file provided on the command line, and the extracting 16K from about 2/3rds of the way through the uncompressed output, and writing that to stdout. */ int main(int argc, char **argv) { int len; off_t offset; FILE *in; struct access *index = NULL; unsigned char buf[CHUNK]; /* open input file */ if (argc != 2) { fprintf(stderr, "usage: zran file.gz\n"); return 1; } in = fopen(argv[1], "rb"); if (in == NULL) { fprintf(stderr, "zran: could not open %s for reading\n", argv[1]); return 1; } /* build index */ len = build_index(in, SPAN, &index); if (len < 0) { fclose(in); switch (len) { case Z_MEM_ERROR: fprintf(stderr, "zran: out of memory\n"); break; case Z_DATA_ERROR: fprintf(stderr, "zran: compressed data error in %s\n", argv[1]); break; case Z_ERRNO: fprintf(stderr, "zran: read error on %s\n", argv[1]); break; default: fprintf(stderr, "zran: error %d while building index\n", len); } return 1; } fprintf(stderr, "zran: built index with %d access points\n", len); /* use index by reading some bytes from an arbitrary offset */ offset = (index->list[index->have - 1].out << 1) / 3; len = extract(in, index, offset, buf, CHUNK); if (len < 0) fprintf(stderr, "zran: extraction failed: %s error\n", len == Z_MEM_ERROR ? "out of memory" : "input corrupted"); else { fwrite(buf, 1, len, stdout); fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset); } /* clean up and exit */ free_index(index); fclose(in); return 0; } tcl8.6.5/compat/zlib/examples/gun.c0000644000175000017500000006252612663660065016600 0ustar sergeisergei/* gun.c -- simple gunzip to give an example of the use of inflateBack() * Copyright (C) 2003, 2005, 2008, 2010, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h Version 1.7 12 August 2012 Mark Adler */ /* Version history: 1.0 16 Feb 2003 First version for testing of inflateBack() 1.1 21 Feb 2005 Decompress concatenated gzip streams Remove use of "this" variable (C++ keyword) Fix return value for in() Improve allocation failure checking Add typecasting for void * structures Add -h option for command version and usage Add a bunch of comments 1.2 20 Mar 2005 Add Unix compress (LZW) decompression Copy file attributes from input file to output file 1.3 12 Jun 2005 Add casts for error messages [Oberhumer] 1.4 8 Dec 2006 LZW decompression speed improvements 1.5 9 Feb 2008 Avoid warning in latest version of gcc 1.6 17 Jan 2010 Avoid signed/unsigned comparison warnings 1.7 12 Aug 2012 Update for z_const usage in zlib 1.2.8 */ /* gun [ -t ] [ name ... ] decompresses the data in the named gzip files. If no arguments are given, gun will decompress from stdin to stdout. The names must end in .gz, -gz, .z, -z, _z, or .Z. The uncompressed data will be written to a file name with the suffix stripped. On success, the original file is deleted. On failure, the output file is deleted. For most failures, the command will continue to process the remaining names on the command line. A memory allocation failure will abort the command. If -t is specified, then the listed files or stdin will be tested as gzip files for integrity (without checking for a proper suffix), no output will be written, and no files will be deleted. Like gzip, gun allows concatenated gzip streams and will decompress them, writing all of the uncompressed data to the output. Unlike gzip, gun allows an empty file on input, and will produce no error writing an empty output file. gun will also decompress files made by Unix compress, which uses LZW compression. These files are automatically detected by virtue of their magic header bytes. Since the end of Unix compress stream is marked by the end-of-file, they cannot be concantenated. If a Unix compress stream is encountered in an input file, it is the last stream in that file. Like gunzip and uncompress, the file attributes of the orignal compressed file are maintained in the final uncompressed file, to the extent that the user permissions allow it. On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version 1.2.4) is on the same file, when gun is linked with zlib 1.2.2. Also the LZW decompression provided by gun is about twice as fast as the standard Unix uncompress command. */ /* external functions and related types and constants */ #include /* fprintf() */ #include /* malloc(), free() */ #include /* strerror(), strcmp(), strlen(), memcpy() */ #include /* errno */ #include /* open() */ #include /* read(), write(), close(), chown(), unlink() */ #include #include /* stat(), chmod() */ #include /* utime() */ #include "zlib.h" /* inflateBackInit(), inflateBack(), */ /* inflateBackEnd(), crc32() */ /* function declaration */ #define local static /* buffer constants */ #define SIZE 32768U /* input and output buffer sizes */ #define PIECE 16384 /* limits i/o chunks for 16-bit int case */ /* structure for infback() to pass to input function in() -- it maintains the input file and a buffer of size SIZE */ struct ind { int infile; unsigned char *inbuf; }; /* Load input buffer, assumed to be empty, and return bytes loaded and a pointer to them. read() is called until the buffer is full, or until it returns end-of-file or error. Return 0 on error. */ local unsigned in(void *in_desc, z_const unsigned char **buf) { int ret; unsigned len; unsigned char *next; struct ind *me = (struct ind *)in_desc; next = me->inbuf; *buf = next; len = 0; do { ret = PIECE; if ((unsigned)ret > SIZE - len) ret = (int)(SIZE - len); ret = (int)read(me->infile, next, ret); if (ret == -1) { len = 0; break; } next += ret; len += ret; } while (ret != 0 && len < SIZE); return len; } /* structure for infback() to pass to output function out() -- it maintains the output file, a running CRC-32 check on the output and the total number of bytes output, both for checking against the gzip trailer. (The length in the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and the output is greater than 4 GB.) */ struct outd { int outfile; int check; /* true if checking crc and total */ unsigned long crc; unsigned long total; }; /* Write output buffer and update the CRC-32 and total bytes written. write() is called until all of the output is written or an error is encountered. On success out() returns 0. For a write failure, out() returns 1. If the output file descriptor is -1, then nothing is written. */ local int out(void *out_desc, unsigned char *buf, unsigned len) { int ret; struct outd *me = (struct outd *)out_desc; if (me->check) { me->crc = crc32(me->crc, buf, len); me->total += len; } if (me->outfile != -1) do { ret = PIECE; if ((unsigned)ret > len) ret = (int)len; ret = (int)write(me->outfile, buf, ret); if (ret == -1) return 1; buf += ret; len -= ret; } while (len != 0); return 0; } /* next input byte macro for use inside lunpipe() and gunpipe() */ #define NEXT() (have ? 0 : (have = in(indp, &next)), \ last = have ? (have--, (int)(*next++)) : -1) /* memory for gunpipe() and lunpipe() -- the first 256 entries of prefix[] and suffix[] are never used, could have offset the index, but it's faster to waste the memory */ unsigned char inbuf[SIZE]; /* input buffer */ unsigned char outbuf[SIZE]; /* output buffer */ unsigned short prefix[65536]; /* index to LZW prefix string */ unsigned char suffix[65536]; /* one-character LZW suffix */ unsigned char match[65280 + 2]; /* buffer for reversed match or gzip 32K sliding window */ /* throw out what's left in the current bits byte buffer (this is a vestigial aspect of the compressed data format derived from an implementation that made use of a special VAX machine instruction!) */ #define FLUSHCODE() \ do { \ left = 0; \ rem = 0; \ if (chunk > have) { \ chunk -= have; \ have = 0; \ if (NEXT() == -1) \ break; \ chunk--; \ if (chunk > have) { \ chunk = have = 0; \ break; \ } \ } \ have -= chunk; \ next += chunk; \ chunk = 0; \ } while (0) /* Decompress a compress (LZW) file from indp to outfile. The compress magic header (two bytes) has already been read and verified. There are have bytes of buffered input at next. strm is used for passing error information back to gunpipe(). lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of file, read error, or write error (a write error indicated by strm->next_in not equal to Z_NULL), or Z_DATA_ERROR for invalid input. */ local int lunpipe(unsigned have, z_const unsigned char *next, struct ind *indp, int outfile, z_stream *strm) { int last; /* last byte read by NEXT(), or -1 if EOF */ unsigned chunk; /* bytes left in current chunk */ int left; /* bits left in rem */ unsigned rem; /* unused bits from input */ int bits; /* current bits per code */ unsigned code; /* code, table traversal index */ unsigned mask; /* mask for current bits codes */ int max; /* maximum bits per code for this stream */ unsigned flags; /* compress flags, then block compress flag */ unsigned end; /* last valid entry in prefix/suffix tables */ unsigned temp; /* current code */ unsigned prev; /* previous code */ unsigned final; /* last character written for previous code */ unsigned stack; /* next position for reversed string */ unsigned outcnt; /* bytes in output buffer */ struct outd outd; /* output structure */ unsigned char *p; /* set up output */ outd.outfile = outfile; outd.check = 0; /* process remainder of compress header -- a flags byte */ flags = NEXT(); if (last == -1) return Z_BUF_ERROR; if (flags & 0x60) { strm->msg = (char *)"unknown lzw flags set"; return Z_DATA_ERROR; } max = flags & 0x1f; if (max < 9 || max > 16) { strm->msg = (char *)"lzw bits out of range"; return Z_DATA_ERROR; } if (max == 9) /* 9 doesn't really mean 9 */ max = 10; flags &= 0x80; /* true if block compress */ /* clear table */ bits = 9; mask = 0x1ff; end = flags ? 256 : 255; /* set up: get first 9-bit code, which is the first decompressed byte, but don't create a table entry until the next code */ if (NEXT() == -1) /* no compressed data is ok */ return Z_OK; final = prev = (unsigned)last; /* low 8 bits of code */ if (NEXT() == -1) /* missing a bit */ return Z_BUF_ERROR; if (last & 1) { /* code must be < 256 */ strm->msg = (char *)"invalid lzw code"; return Z_DATA_ERROR; } rem = (unsigned)last >> 1; /* remaining 7 bits */ left = 7; chunk = bits - 2; /* 7 bytes left in this chunk */ outbuf[0] = (unsigned char)final; /* write first decompressed byte */ outcnt = 1; /* decode codes */ stack = 0; for (;;) { /* if the table will be full after this, increment the code size */ if (end >= mask && bits < max) { FLUSHCODE(); bits++; mask <<= 1; mask++; } /* get a code of length bits */ if (chunk == 0) /* decrement chunk modulo bits */ chunk = bits; code = rem; /* low bits of code */ if (NEXT() == -1) { /* EOF is end of compressed data */ /* write remaining buffered output */ if (outcnt && out(&outd, outbuf, outcnt)) { strm->next_in = outbuf; /* signal write error */ return Z_BUF_ERROR; } return Z_OK; } code += (unsigned)last << left; /* middle (or high) bits of code */ left += 8; chunk--; if (bits > left) { /* need more bits */ if (NEXT() == -1) /* can't end in middle of code */ return Z_BUF_ERROR; code += (unsigned)last << left; /* high bits of code */ left += 8; chunk--; } code &= mask; /* mask to current code length */ left -= bits; /* number of unused bits */ rem = (unsigned)last >> (8 - left); /* unused bits from last byte */ /* process clear code (256) */ if (code == 256 && flags) { FLUSHCODE(); bits = 9; /* initialize bits and mask */ mask = 0x1ff; end = 255; /* empty table */ continue; /* get next code */ } /* special code to reuse last match */ temp = code; /* save the current code */ if (code > end) { /* Be picky on the allowed code here, and make sure that the code we drop through (prev) will be a valid index so that random input does not cause an exception. The code != end + 1 check is empirically derived, and not checked in the original uncompress code. If this ever causes a problem, that check could be safely removed. Leaving this check in greatly improves gun's ability to detect random or corrupted input after a compress header. In any case, the prev > end check must be retained. */ if (code != end + 1 || prev > end) { strm->msg = (char *)"invalid lzw code"; return Z_DATA_ERROR; } match[stack++] = (unsigned char)final; code = prev; } /* walk through linked list to generate output in reverse order */ p = match + stack; while (code >= 256) { *p++ = suffix[code]; code = prefix[code]; } stack = p - match; match[stack++] = (unsigned char)code; final = code; /* link new table entry */ if (end < mask) { end++; prefix[end] = (unsigned short)prev; suffix[end] = (unsigned char)final; } /* set previous code for next iteration */ prev = temp; /* write output in forward order */ while (stack > SIZE - outcnt) { while (outcnt < SIZE) outbuf[outcnt++] = match[--stack]; if (out(&outd, outbuf, outcnt)) { strm->next_in = outbuf; /* signal write error */ return Z_BUF_ERROR; } outcnt = 0; } p = match + stack; do { outbuf[outcnt++] = *--p; } while (p > match); stack = 0; /* loop for next code with final and prev as the last match, rem and left provide the first 0..7 bits of the next code, end is the last valid table entry */ } } /* Decompress a gzip file from infile to outfile. strm is assumed to have been successfully initialized with inflateBackInit(). The input file may consist of a series of gzip streams, in which case all of them will be decompressed to the output file. If outfile is -1, then the gzip stream(s) integrity is checked and nothing is written. The return value is a zlib error code: Z_MEM_ERROR if out of memory, Z_DATA_ERROR if the header or the compressed data is invalid, or if the trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip stream) follows a valid gzip stream. */ local int gunpipe(z_stream *strm, int infile, int outfile) { int ret, first, last; unsigned have, flags, len; z_const unsigned char *next = NULL; struct ind ind, *indp; struct outd outd; /* setup input buffer */ ind.infile = infile; ind.inbuf = inbuf; indp = &ind; /* decompress concatenated gzip streams */ have = 0; /* no input data read in yet */ first = 1; /* looking for first gzip header */ strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */ for (;;) { /* look for the two magic header bytes for a gzip stream */ if (NEXT() == -1) { ret = Z_OK; break; /* empty gzip stream is ok */ } if (last != 31 || (NEXT() != 139 && last != 157)) { strm->msg = (char *)"incorrect header check"; ret = first ? Z_DATA_ERROR : Z_ERRNO; break; /* not a gzip or compress header */ } first = 0; /* next non-header is junk */ /* process a compress (LZW) file -- can't be concatenated after this */ if (last == 157) { ret = lunpipe(have, next, indp, outfile, strm); break; } /* process remainder of gzip header */ ret = Z_BUF_ERROR; if (NEXT() != 8) { /* only deflate method allowed */ if (last == -1) break; strm->msg = (char *)"unknown compression method"; ret = Z_DATA_ERROR; break; } flags = NEXT(); /* header flags */ NEXT(); /* discard mod time, xflgs, os */ NEXT(); NEXT(); NEXT(); NEXT(); NEXT(); if (last == -1) break; if (flags & 0xe0) { strm->msg = (char *)"unknown header flags set"; ret = Z_DATA_ERROR; break; } if (flags & 4) { /* extra field */ len = NEXT(); len += (unsigned)(NEXT()) << 8; if (last == -1) break; while (len > have) { len -= have; have = 0; if (NEXT() == -1) break; len--; } if (last == -1) break; have -= len; next += len; } if (flags & 8) /* file name */ while (NEXT() != 0 && last != -1) ; if (flags & 16) /* comment */ while (NEXT() != 0 && last != -1) ; if (flags & 2) { /* header crc */ NEXT(); NEXT(); } if (last == -1) break; /* set up output */ outd.outfile = outfile; outd.check = 1; outd.crc = crc32(0L, Z_NULL, 0); outd.total = 0; /* decompress data to output */ strm->next_in = next; strm->avail_in = have; ret = inflateBack(strm, in, indp, out, &outd); if (ret != Z_STREAM_END) break; next = strm->next_in; have = strm->avail_in; strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */ /* check trailer */ ret = Z_BUF_ERROR; if (NEXT() != (int)(outd.crc & 0xff) || NEXT() != (int)((outd.crc >> 8) & 0xff) || NEXT() != (int)((outd.crc >> 16) & 0xff) || NEXT() != (int)((outd.crc >> 24) & 0xff)) { /* crc error */ if (last != -1) { strm->msg = (char *)"incorrect data check"; ret = Z_DATA_ERROR; } break; } if (NEXT() != (int)(outd.total & 0xff) || NEXT() != (int)((outd.total >> 8) & 0xff) || NEXT() != (int)((outd.total >> 16) & 0xff) || NEXT() != (int)((outd.total >> 24) & 0xff)) { /* length error */ if (last != -1) { strm->msg = (char *)"incorrect length check"; ret = Z_DATA_ERROR; } break; } /* go back and look for another gzip stream */ } /* clean up and return */ return ret; } /* Copy file attributes, from -> to, as best we can. This is best effort, so no errors are reported. The mode bits, including suid, sgid, and the sticky bit are copied (if allowed), the owner's user id and group id are copied (again if allowed), and the access and modify times are copied. */ local void copymeta(char *from, char *to) { struct stat was; struct utimbuf when; /* get all of from's Unix meta data, return if not a regular file */ if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG) return; /* set to's mode bits, ignore errors */ (void)chmod(to, was.st_mode & 07777); /* copy owner's user and group, ignore errors */ (void)chown(to, was.st_uid, was.st_gid); /* copy access and modify times, ignore errors */ when.actime = was.st_atime; when.modtime = was.st_mtime; (void)utime(to, &when); } /* Decompress the file inname to the file outnname, of if test is true, just decompress without writing and check the gzip trailer for integrity. If inname is NULL or an empty string, read from stdin. If outname is NULL or an empty string, write to stdout. strm is a pre-initialized inflateBack structure. When appropriate, copy the file attributes from inname to outname. gunzip() returns 1 if there is an out-of-memory error or an unexpected return code from gunpipe(). Otherwise it returns 0. */ local int gunzip(z_stream *strm, char *inname, char *outname, int test) { int ret; int infile, outfile; /* open files */ if (inname == NULL || *inname == 0) { inname = "-"; infile = 0; /* stdin */ } else { infile = open(inname, O_RDONLY, 0); if (infile == -1) { fprintf(stderr, "gun cannot open %s\n", inname); return 0; } } if (test) outfile = -1; else if (outname == NULL || *outname == 0) { outname = "-"; outfile = 1; /* stdout */ } else { outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666); if (outfile == -1) { close(infile); fprintf(stderr, "gun cannot create %s\n", outname); return 0; } } errno = 0; /* decompress */ ret = gunpipe(strm, infile, outfile); if (outfile > 2) close(outfile); if (infile > 2) close(infile); /* interpret result */ switch (ret) { case Z_OK: case Z_ERRNO: if (infile > 2 && outfile > 2) { copymeta(inname, outname); /* copy attributes */ unlink(inname); } if (ret == Z_ERRNO) fprintf(stderr, "gun warning: trailing garbage ignored in %s\n", inname); break; case Z_DATA_ERROR: if (outfile > 2) unlink(outname); fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg); break; case Z_MEM_ERROR: if (outfile > 2) unlink(outname); fprintf(stderr, "gun out of memory error--aborting\n"); return 1; case Z_BUF_ERROR: if (outfile > 2) unlink(outname); if (strm->next_in != Z_NULL) { fprintf(stderr, "gun write error on %s: %s\n", outname, strerror(errno)); } else if (errno) { fprintf(stderr, "gun read error on %s: %s\n", inname, strerror(errno)); } else { fprintf(stderr, "gun unexpected end of file on %s\n", inname); } break; default: if (outfile > 2) unlink(outname); fprintf(stderr, "gun internal error--aborting\n"); return 1; } return 0; } /* Process the gun command line arguments. See the command syntax near the beginning of this source file. */ int main(int argc, char **argv) { int ret, len, test; char *outname; unsigned char *window; z_stream strm; /* initialize inflateBack state for repeated use */ window = match; /* reuse LZW match buffer */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; ret = inflateBackInit(&strm, 15, window); if (ret != Z_OK) { fprintf(stderr, "gun out of memory error--aborting\n"); return 1; } /* decompress each file to the same name with the suffix removed */ argc--; argv++; test = 0; if (argc && strcmp(*argv, "-h") == 0) { fprintf(stderr, "gun 1.6 (17 Jan 2010)\n"); fprintf(stderr, "Copyright (C) 2003-2010 Mark Adler\n"); fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n"); return 0; } if (argc && strcmp(*argv, "-t") == 0) { test = 1; argc--; argv++; } if (argc) do { if (test) outname = NULL; else { len = (int)strlen(*argv); if (strcmp(*argv + len - 3, ".gz") == 0 || strcmp(*argv + len - 3, "-gz") == 0) len -= 3; else if (strcmp(*argv + len - 2, ".z") == 0 || strcmp(*argv + len - 2, "-z") == 0 || strcmp(*argv + len - 2, "_z") == 0 || strcmp(*argv + len - 2, ".Z") == 0) len -= 2; else { fprintf(stderr, "gun error: no gz type on %s--skipping\n", *argv); continue; } outname = malloc(len + 1); if (outname == NULL) { fprintf(stderr, "gun out of memory error--aborting\n"); ret = 1; break; } memcpy(outname, *argv, len); outname[len] = 0; } ret = gunzip(&strm, *argv, outname, test); if (outname != NULL) free(outname); if (ret) break; } while (argv++, --argc); else ret = gunzip(&strm, NULL, NULL, test); /* clean up */ inflateBackEnd(&strm); return ret; } tcl8.6.5/compat/zlib/examples/gzlog.c0000644000175000017500000012077312663660065017130 0ustar sergeisergei/* * gzlog.c * Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved * For conditions of distribution and use, see copyright notice in gzlog.h * version 2.2, 14 Aug 2012 */ /* gzlog provides a mechanism for frequently appending short strings to a gzip file that is efficient both in execution time and compression ratio. The strategy is to write the short strings in an uncompressed form to the end of the gzip file, only compressing when the amount of uncompressed data has reached a given threshold. gzlog also provides protection against interruptions in the process due to system crashes. The status of the operation is recorded in an extra field in the gzip file, and is only updated once the gzip file is brought to a valid state. The last data to be appended or compressed is saved in an auxiliary file, so that if the operation is interrupted, it can be completed the next time an append operation is attempted. gzlog maintains another auxiliary file with the last 32K of data from the compressed portion, which is preloaded for the compression of the subsequent data. This minimizes the impact to the compression ratio of appending. */ /* Operations Concept: Files (log name "foo"): foo.gz -- gzip file with the complete log foo.add -- last message to append or last data to compress foo.dict -- dictionary of the last 32K of data for next compression foo.temp -- temporary dictionary file for compression after this one foo.lock -- lock file for reading and writing the other files foo.repairs -- log file for log file recovery operations (not compressed) gzip file structure: - fixed-length (no file name) header with extra field (see below) - compressed data ending initially with empty stored block - uncompressed data filling out originally empty stored block and subsequent stored blocks as needed (16K max each) - gzip trailer - no junk at end (no other gzip streams) When appending data, the information in the first three items above plus the foo.add file are sufficient to recover an interrupted append operation. The extra field has the necessary information to restore the start of the last stored block and determine where to append the data in the foo.add file, as well as the crc and length of the gzip data before the append operation. The foo.add file is created before the gzip file is marked for append, and deleted after the gzip file is marked as complete. So if the append operation is interrupted, the data to add will still be there. If due to some external force, the foo.add file gets deleted between when the append operation was interrupted and when recovery is attempted, the gzip file will still be restored, but without the appended data. When compressing data, the information in the first two items above plus the foo.add file are sufficient to recover an interrupted compress operation. The extra field has the necessary information to find the end of the compressed data, and contains both the crc and length of just the compressed data and of the complete set of data including the contents of the foo.add file. Again, the foo.add file is maintained during the compress operation in case of an interruption. If in the unlikely event the foo.add file with the data to be compressed is missing due to some external force, a gzip file with just the previous compressed data will be reconstructed. In this case, all of the data that was to be compressed is lost (approximately one megabyte). This will not occur if all that happened was an interruption of the compress operation. The third state that is marked is the replacement of the old dictionary with the new dictionary after a compress operation. Once compression is complete, the gzip file is marked as being in the replace state. This completes the gzip file, so an interrupt after being so marked does not result in recompression. Then the dictionary file is replaced, and the gzip file is marked as completed. This state prevents the possibility of restarting compression with the wrong dictionary file. All three operations are wrapped by a lock/unlock procedure. In order to gain exclusive access to the log files, first a foo.lock file must be exclusively created. When all operations are complete, the lock is released by deleting the foo.lock file. If when attempting to create the lock file, it already exists and the modify time of the lock file is more than five minutes old (set by the PATIENCE define below), then the old lock file is considered stale and deleted, and the exclusive creation of the lock file is retried. To assure that there are no false assessments of the staleness of the lock file, the operations periodically touch the lock file to update the modified date. Following is the definition of the extra field with all of the information required to enable the above append and compress operations and their recovery if interrupted. Multi-byte values are stored little endian (consistent with the gzip format). File pointers are eight bytes long. The crc's and lengths for the gzip trailer are four bytes long. (Note that the length at the end of a gzip file is used for error checking only, and for large files is actually the length modulo 2^32.) The stored block length is two bytes long. The gzip extra field two-byte identification is "ap" for append. It is assumed that writing the extra field to the file is an "atomic" operation. That is, either all of the extra field is written to the file, or none of it is, if the operation is interrupted right at the point of updating the extra field. This is a reasonable assumption, since the extra field is within the first 52 bytes of the file, which is smaller than any expected block size for a mass storage device (usually 512 bytes or larger). Extra field (35 bytes): - Pointer to first stored block length -- this points to the two-byte length of the first stored block, which is followed by the two-byte, one's complement of that length. The stored block length is preceded by the three-bit header of the stored block, which is the actual start of the stored block in the deflate format. See the bit offset field below. - Pointer to the last stored block length. This is the same as above, but for the last stored block of the uncompressed data in the gzip file. Initially this is the same as the first stored block length pointer. When the stored block gets to 16K (see the MAX_STORE define), then a new stored block as added, at which point the last stored block length pointer is different from the first stored block length pointer. When they are different, the first bit of the last stored block header is eight bits, or one byte back from the block length. - Compressed data crc and length. This is the crc and length of the data that is in the compressed portion of the deflate stream. These are used only in the event that the foo.add file containing the data to compress is lost after a compress operation is interrupted. - Total data crc and length. This is the crc and length of all of the data stored in the gzip file, compressed and uncompressed. It is used to reconstruct the gzip trailer when compressing, as well as when recovering interrupted operations. - Final stored block length. This is used to quickly find where to append, and allows the restoration of the original final stored block state when an append operation is interrupted. - First stored block start as the number of bits back from the final stored block first length byte. This value is in the range of 3..10, and is stored as the low three bits of the final byte of the extra field after subtracting three (0..7). This allows the last-block bit of the stored block header to be updated when a new stored block is added, for the case when the first stored block and the last stored block are the same. (When they are different, the numbers of bits back is known to be eight.) This also allows for new compressed data to be appended to the old compressed data in the compress operation, overwriting the previous first stored block, or for the compressed data to be terminated and a valid gzip file reconstructed on the off chance that a compression operation was interrupted and the data to compress in the foo.add file was deleted. - The operation in process. This is the next two bits in the last byte (the bits under the mask 0x18). The are interpreted as 0: nothing in process, 1: append in process, 2: compress in process, 3: replace in process. - The top three bits of the last byte in the extra field are reserved and are currently set to zero. Main procedure: - Exclusively create the foo.lock file using the O_CREAT and O_EXCL modes of the system open() call. If the modify time of an existing lock file is more than PATIENCE seconds old, then the lock file is deleted and the exclusive create is retried. - Load the extra field from the foo.gz file, and see if an operation was in progress but not completed. If so, apply the recovery procedure below. - Perform the append procedure with the provided data. - If the uncompressed data in the foo.gz file is 1MB or more, apply the compress procedure. - Delete the foo.lock file. Append procedure: - Put what to append in the foo.add file so that the operation can be restarted if this procedure is interrupted. - Mark the foo.gz extra field with the append operation in progress. + Restore the original last-block bit and stored block length of the last stored block from the information in the extra field, in case a previous append operation was interrupted. - Append the provided data to the last stored block, creating new stored blocks as needed and updating the stored blocks last-block bits and lengths. - Update the crc and length with the new data, and write the gzip trailer. - Write over the extra field (with a single write operation) with the new pointers, lengths, and crc's, and mark the gzip file as not in process. Though there is still a foo.add file, it will be ignored since nothing is in process. If a foo.add file is leftover from a previously completed operation, it is truncated when writing new data to it. - Delete the foo.add file. Compress and replace procedures: - Read all of the uncompressed data in the stored blocks in foo.gz and write it to foo.add. Also write foo.temp with the last 32K of that data to provide a dictionary for the next invocation of this procedure. - Rewrite the extra field marking foo.gz with a compression in process. * If there is no data provided to compress (due to a missing foo.add file when recovering), reconstruct and truncate the foo.gz file to contain only the previous compressed data and proceed to the step after the next one. Otherwise ... - Compress the data with the dictionary in foo.dict, and write to the foo.gz file starting at the bit immediately following the last previously compressed block. If there is no foo.dict, proceed anyway with the compression at slightly reduced efficiency. (For the foo.dict file to be missing requires some external failure beyond simply the interruption of a compress operation.) During this process, the foo.lock file is periodically touched to assure that that file is not considered stale by another process before we're done. The deflation is terminated with a non-last empty static block (10 bits long), that is then located and written over by a last-bit-set empty stored block. - Append the crc and length of the data in the gzip file (previously calculated during the append operations). - Write over the extra field with the updated stored block offsets, bits back, crc's, and lengths, and mark foo.gz as in process for a replacement of the dictionary. @ Delete the foo.add file. - Replace foo.dict with foo.temp. - Write over the extra field, marking foo.gz as complete. Recovery procedure: - If not a replace recovery, read in the foo.add file, and provide that data to the appropriate recovery below. If there is no foo.add file, provide a zero data length to the recovery. In that case, the append recovery restores the foo.gz to the previous compressed + uncompressed data state. For the the compress recovery, a missing foo.add file results in foo.gz being restored to the previous compressed-only data state. - Append recovery: - Pick up append at + step above - Compress recovery: - Pick up compress at * step above - Replace recovery: - Pick up compress at @ step above - Log the repair with a date stamp in foo.repairs */ #include #include /* rename, fopen, fprintf, fclose */ #include /* malloc, free */ #include /* strlen, strrchr, strcpy, strncpy, strcmp */ #include /* open */ #include /* lseek, read, write, close, unlink, sleep, */ /* ftruncate, fsync */ #include /* errno */ #include /* time, ctime */ #include /* stat */ #include /* utimes */ #include "zlib.h" /* crc32 */ #include "gzlog.h" /* header for external access */ #define local static typedef unsigned int uint; typedef unsigned long ulong; /* Macro for debugging to deterministically force recovery operations */ #ifdef DEBUG #include /* longjmp */ jmp_buf gzlog_jump; /* where to go back to */ int gzlog_bail = 0; /* which point to bail at (1..8) */ int gzlog_count = -1; /* number of times through to wait */ # define BAIL(n) do { if (n == gzlog_bail && gzlog_count-- == 0) \ longjmp(gzlog_jump, gzlog_bail); } while (0) #else # define BAIL(n) #endif /* how old the lock file can be in seconds before considering it stale */ #define PATIENCE 300 /* maximum stored block size in Kbytes -- must be in 1..63 */ #define MAX_STORE 16 /* number of stored Kbytes to trigger compression (must be >= 32 to allow dictionary construction, and <= 204 * MAX_STORE, in order for >> 10 to discard the stored block headers contribution of five bytes each) */ #define TRIGGER 1024 /* size of a deflate dictionary (this cannot be changed) */ #define DICT 32768U /* values for the operation (2 bits) */ #define NO_OP 0 #define APPEND_OP 1 #define COMPRESS_OP 2 #define REPLACE_OP 3 /* macros to extract little-endian integers from an unsigned byte buffer */ #define PULL2(p) ((p)[0]+((uint)((p)[1])<<8)) #define PULL4(p) (PULL2(p)+((ulong)PULL2(p+2)<<16)) #define PULL8(p) (PULL4(p)+((off_t)PULL4(p+4)<<32)) /* macros to store integers into a byte buffer in little-endian order */ #define PUT2(p,a) do {(p)[0]=a;(p)[1]=(a)>>8;} while(0) #define PUT4(p,a) do {PUT2(p,a);PUT2(p+2,a>>16);} while(0) #define PUT8(p,a) do {PUT4(p,a);PUT4(p+4,a>>32);} while(0) /* internal structure for log information */ #define LOGID "\106\035\172" /* should be three non-zero characters */ struct log { char id[4]; /* contains LOGID to detect inadvertent overwrites */ int fd; /* file descriptor for .gz file, opened read/write */ char *path; /* allocated path, e.g. "/var/log/foo" or "foo" */ char *end; /* end of path, for appending suffices such as ".gz" */ off_t first; /* offset of first stored block first length byte */ int back; /* location of first block id in bits back from first */ uint stored; /* bytes currently in last stored block */ off_t last; /* offset of last stored block first length byte */ ulong ccrc; /* crc of compressed data */ ulong clen; /* length (modulo 2^32) of compressed data */ ulong tcrc; /* crc of total data */ ulong tlen; /* length (modulo 2^32) of total data */ time_t lock; /* last modify time of our lock file */ }; /* gzip header for gzlog */ local unsigned char log_gzhead[] = { 0x1f, 0x8b, /* magic gzip id */ 8, /* compression method is deflate */ 4, /* there is an extra field (no file name) */ 0, 0, 0, 0, /* no modification time provided */ 0, 0xff, /* no extra flags, no OS specified */ 39, 0, 'a', 'p', 35, 0 /* extra field with "ap" subfield */ /* 35 is EXTRA, 39 is EXTRA + 4 */ }; #define HEAD sizeof(log_gzhead) /* should be 16 */ /* initial gzip extra field content (52 == HEAD + EXTRA + 1) */ local unsigned char log_gzext[] = { 52, 0, 0, 0, 0, 0, 0, 0, /* offset of first stored block length */ 52, 0, 0, 0, 0, 0, 0, 0, /* offset of last stored block length */ 0, 0, 0, 0, 0, 0, 0, 0, /* compressed data crc and length */ 0, 0, 0, 0, 0, 0, 0, 0, /* total data crc and length */ 0, 0, /* final stored block data length */ 5 /* op is NO_OP, last bit 8 bits back */ }; #define EXTRA sizeof(log_gzext) /* should be 35 */ /* initial gzip data and trailer */ local unsigned char log_gzbody[] = { 1, 0, 0, 0xff, 0xff, /* empty stored block (last) */ 0, 0, 0, 0, /* crc */ 0, 0, 0, 0 /* uncompressed length */ }; #define BODY sizeof(log_gzbody) /* Exclusively create foo.lock in order to negotiate exclusive access to the foo.* files. If the modify time of an existing lock file is greater than PATIENCE seconds in the past, then consider the lock file to have been abandoned, delete it, and try the exclusive create again. Save the lock file modify time for verification of ownership. Return 0 on success, or -1 on failure, usually due to an access restriction or invalid path. Note that if stat() or unlink() fails, it may be due to another process noticing the abandoned lock file a smidge sooner and deleting it, so those are not flagged as an error. */ local int log_lock(struct log *log) { int fd; struct stat st; strcpy(log->end, ".lock"); while ((fd = open(log->path, O_CREAT | O_EXCL, 0644)) < 0) { if (errno != EEXIST) return -1; if (stat(log->path, &st) == 0 && time(NULL) - st.st_mtime > PATIENCE) { unlink(log->path); continue; } sleep(2); /* relinquish the CPU for two seconds while waiting */ } close(fd); if (stat(log->path, &st) == 0) log->lock = st.st_mtime; return 0; } /* Update the modify time of the lock file to now, in order to prevent another task from thinking that the lock is stale. Save the lock file modify time for verification of ownership. */ local void log_touch(struct log *log) { struct stat st; strcpy(log->end, ".lock"); utimes(log->path, NULL); if (stat(log->path, &st) == 0) log->lock = st.st_mtime; } /* Check the log file modify time against what is expected. Return true if this is not our lock. If it is our lock, touch it to keep it. */ local int log_check(struct log *log) { struct stat st; strcpy(log->end, ".lock"); if (stat(log->path, &st) || st.st_mtime != log->lock) return 1; log_touch(log); return 0; } /* Unlock a previously acquired lock, but only if it's ours. */ local void log_unlock(struct log *log) { if (log_check(log)) return; strcpy(log->end, ".lock"); unlink(log->path); log->lock = 0; } /* Check the gzip header and read in the extra field, filling in the values in the log structure. Return op on success or -1 if the gzip header was not as expected. op is the current operation in progress last written to the extra field. This assumes that the gzip file has already been opened, with the file descriptor log->fd. */ local int log_head(struct log *log) { int op; unsigned char buf[HEAD + EXTRA]; if (lseek(log->fd, 0, SEEK_SET) < 0 || read(log->fd, buf, HEAD + EXTRA) != HEAD + EXTRA || memcmp(buf, log_gzhead, HEAD)) { return -1; } log->first = PULL8(buf + HEAD); log->last = PULL8(buf + HEAD + 8); log->ccrc = PULL4(buf + HEAD + 16); log->clen = PULL4(buf + HEAD + 20); log->tcrc = PULL4(buf + HEAD + 24); log->tlen = PULL4(buf + HEAD + 28); log->stored = PULL2(buf + HEAD + 32); log->back = 3 + (buf[HEAD + 34] & 7); op = (buf[HEAD + 34] >> 3) & 3; return op; } /* Write over the extra field contents, marking the operation as op. Use fsync to assure that the device is written to, and in the requested order. This operation, and only this operation, is assumed to be atomic in order to assure that the log is recoverable in the event of an interruption at any point in the process. Return -1 if the write to foo.gz failed. */ local int log_mark(struct log *log, int op) { int ret; unsigned char ext[EXTRA]; PUT8(ext, log->first); PUT8(ext + 8, log->last); PUT4(ext + 16, log->ccrc); PUT4(ext + 20, log->clen); PUT4(ext + 24, log->tcrc); PUT4(ext + 28, log->tlen); PUT2(ext + 32, log->stored); ext[34] = log->back - 3 + (op << 3); fsync(log->fd); ret = lseek(log->fd, HEAD, SEEK_SET) < 0 || write(log->fd, ext, EXTRA) != EXTRA ? -1 : 0; fsync(log->fd); return ret; } /* Rewrite the last block header bits and subsequent zero bits to get to a byte boundary, setting the last block bit if last is true, and then write the remainder of the stored block header (length and one's complement). Leave the file pointer after the end of the last stored block data. Return -1 if there is a read or write failure on the foo.gz file */ local int log_last(struct log *log, int last) { int back, len, mask; unsigned char buf[6]; /* determine the locations of the bytes and bits to modify */ back = log->last == log->first ? log->back : 8; len = back > 8 ? 2 : 1; /* bytes back from log->last */ mask = 0x80 >> ((back - 1) & 7); /* mask for block last-bit */ /* get the byte to modify (one or two back) into buf[0] -- don't need to read the byte if the last-bit is eight bits back, since in that case the entire byte will be modified */ buf[0] = 0; if (back != 8 && (lseek(log->fd, log->last - len, SEEK_SET) < 0 || read(log->fd, buf, 1) != 1)) return -1; /* change the last-bit of the last stored block as requested -- note that all bits above the last-bit are set to zero, per the type bits of a stored block being 00 and per the convention that the bits to bring the stream to a byte boundary are also zeros */ buf[1] = 0; buf[2 - len] = (*buf & (mask - 1)) + (last ? mask : 0); /* write the modified stored block header and lengths, move the file pointer to after the last stored block data */ PUT2(buf + 2, log->stored); PUT2(buf + 4, log->stored ^ 0xffff); return lseek(log->fd, log->last - len, SEEK_SET) < 0 || write(log->fd, buf + 2 - len, len + 4) != len + 4 || lseek(log->fd, log->stored, SEEK_CUR) < 0 ? -1 : 0; } /* Append len bytes from data to the locked and open log file. len may be zero if recovering and no .add file was found. In that case, the previous state of the foo.gz file is restored. The data is appended uncompressed in deflate stored blocks. Return -1 if there was an error reading or writing the foo.gz file. */ local int log_append(struct log *log, unsigned char *data, size_t len) { uint put; off_t end; unsigned char buf[8]; /* set the last block last-bit and length, in case recovering an interrupted append, then position the file pointer to append to the block */ if (log_last(log, 1)) return -1; /* append, adding stored blocks and updating the offset of the last stored block as needed, and update the total crc and length */ while (len) { /* append as much as we can to the last block */ put = (MAX_STORE << 10) - log->stored; if (put > len) put = (uint)len; if (put) { if (write(log->fd, data, put) != put) return -1; BAIL(1); log->tcrc = crc32(log->tcrc, data, put); log->tlen += put; log->stored += put; data += put; len -= put; } /* if we need to, add a new empty stored block */ if (len) { /* mark current block as not last */ if (log_last(log, 0)) return -1; /* point to new, empty stored block */ log->last += 4 + log->stored + 1; log->stored = 0; } /* mark last block as last, update its length */ if (log_last(log, 1)) return -1; BAIL(2); } /* write the new crc and length trailer, and truncate just in case (could be recovering from partial append with a missing foo.add file) */ PUT4(buf, log->tcrc); PUT4(buf + 4, log->tlen); if (write(log->fd, buf, 8) != 8 || (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) return -1; /* write the extra field, marking the log file as done, delete .add file */ if (log_mark(log, NO_OP)) return -1; strcpy(log->end, ".add"); unlink(log->path); /* ignore error, since may not exist */ return 0; } /* Replace the foo.dict file with the foo.temp file. Also delete the foo.add file, since the compress operation may have been interrupted before that was done. Returns 1 if memory could not be allocated, or -1 if reading or writing foo.gz fails, or if the rename fails for some reason other than foo.temp not existing. foo.temp not existing is a permitted error, since the replace operation may have been interrupted after the rename is done, but before foo.gz is marked as complete. */ local int log_replace(struct log *log) { int ret; char *dest; /* delete foo.add file */ strcpy(log->end, ".add"); unlink(log->path); /* ignore error, since may not exist */ BAIL(3); /* rename foo.name to foo.dict, replacing foo.dict if it exists */ strcpy(log->end, ".dict"); dest = malloc(strlen(log->path) + 1); if (dest == NULL) return -2; strcpy(dest, log->path); strcpy(log->end, ".temp"); ret = rename(log->path, dest); free(dest); if (ret && errno != ENOENT) return -1; BAIL(4); /* mark the foo.gz file as done */ return log_mark(log, NO_OP); } /* Compress the len bytes at data and append the compressed data to the foo.gz deflate data immediately after the previous compressed data. This overwrites the previous uncompressed data, which was stored in foo.add and is the data provided in data[0..len-1]. If this operation is interrupted, it picks up at the start of this routine, with the foo.add file read in again. If there is no data to compress (len == 0), then we simply terminate the foo.gz file after the previously compressed data, appending a final empty stored block and the gzip trailer. Return -1 if reading or writing the log.gz file failed, or -2 if there was a memory allocation failure. */ local int log_compress(struct log *log, unsigned char *data, size_t len) { int fd; uint got, max; ssize_t dict; off_t end; z_stream strm; unsigned char buf[DICT]; /* compress and append compressed data */ if (len) { /* set up for deflate, allocating memory */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) return -2; /* read in dictionary (last 32K of data that was compressed) */ strcpy(log->end, ".dict"); fd = open(log->path, O_RDONLY, 0); if (fd >= 0) { dict = read(fd, buf, DICT); close(fd); if (dict < 0) { deflateEnd(&strm); return -1; } if (dict) deflateSetDictionary(&strm, buf, (uint)dict); } log_touch(log); /* prime deflate with last bits of previous block, position write pointer to write those bits and overwrite what follows */ if (lseek(log->fd, log->first - (log->back > 8 ? 2 : 1), SEEK_SET) < 0 || read(log->fd, buf, 1) != 1 || lseek(log->fd, -1, SEEK_CUR) < 0) { deflateEnd(&strm); return -1; } deflatePrime(&strm, (8 - log->back) & 7, *buf); /* compress, finishing with a partial non-last empty static block */ strm.next_in = data; max = (((uint)0 - 1) >> 1) + 1; /* in case int smaller than size_t */ do { strm.avail_in = len > max ? max : (uint)len; len -= strm.avail_in; do { strm.avail_out = DICT; strm.next_out = buf; deflate(&strm, len ? Z_NO_FLUSH : Z_PARTIAL_FLUSH); got = DICT - strm.avail_out; if (got && write(log->fd, buf, got) != got) { deflateEnd(&strm); return -1; } log_touch(log); } while (strm.avail_out == 0); } while (len); deflateEnd(&strm); BAIL(5); /* find start of empty static block -- scanning backwards the first one bit is the second bit of the block, if the last byte is zero, then we know the byte before that has a one in the top bit, since an empty static block is ten bits long */ if ((log->first = lseek(log->fd, -1, SEEK_CUR)) < 0 || read(log->fd, buf, 1) != 1) return -1; log->first++; if (*buf) { log->back = 1; while ((*buf & ((uint)1 << (8 - log->back++))) == 0) ; /* guaranteed to terminate, since *buf != 0 */ } else log->back = 10; /* update compressed crc and length */ log->ccrc = log->tcrc; log->clen = log->tlen; } else { /* no data to compress -- fix up existing gzip stream */ log->tcrc = log->ccrc; log->tlen = log->clen; } /* complete and truncate gzip stream */ log->last = log->first; log->stored = 0; PUT4(buf, log->tcrc); PUT4(buf + 4, log->tlen); if (log_last(log, 1) || write(log->fd, buf, 8) != 8 || (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) return -1; BAIL(6); /* mark as being in the replace operation */ if (log_mark(log, REPLACE_OP)) return -1; /* execute the replace operation and mark the file as done */ return log_replace(log); } /* log a repair record to the .repairs file */ local void log_log(struct log *log, int op, char *record) { time_t now; FILE *rec; now = time(NULL); strcpy(log->end, ".repairs"); rec = fopen(log->path, "a"); if (rec == NULL) return; fprintf(rec, "%.24s %s recovery: %s\n", ctime(&now), op == APPEND_OP ? "append" : (op == COMPRESS_OP ? "compress" : "replace"), record); fclose(rec); return; } /* Recover the interrupted operation op. First read foo.add for recovering an append or compress operation. Return -1 if there was an error reading or writing foo.gz or reading an existing foo.add, or -2 if there was a memory allocation failure. */ local int log_recover(struct log *log, int op) { int fd, ret = 0; unsigned char *data = NULL; size_t len = 0; struct stat st; /* log recovery */ log_log(log, op, "start"); /* load foo.add file if expected and present */ if (op == APPEND_OP || op == COMPRESS_OP) { strcpy(log->end, ".add"); if (stat(log->path, &st) == 0 && st.st_size) { len = (size_t)(st.st_size); if ((off_t)len != st.st_size || (data = malloc(st.st_size)) == NULL) { log_log(log, op, "allocation failure"); return -2; } if ((fd = open(log->path, O_RDONLY, 0)) < 0) { log_log(log, op, ".add file read failure"); return -1; } ret = (size_t)read(fd, data, len) != len; close(fd); if (ret) { log_log(log, op, ".add file read failure"); return -1; } log_log(log, op, "loaded .add file"); } else log_log(log, op, "missing .add file!"); } /* recover the interrupted operation */ switch (op) { case APPEND_OP: ret = log_append(log, data, len); break; case COMPRESS_OP: ret = log_compress(log, data, len); break; case REPLACE_OP: ret = log_replace(log); } /* log status */ log_log(log, op, ret ? "failure" : "complete"); /* clean up */ if (data != NULL) free(data); return ret; } /* Close the foo.gz file (if open) and release the lock. */ local void log_close(struct log *log) { if (log->fd >= 0) close(log->fd); log->fd = -1; log_unlock(log); } /* Open foo.gz, verify the header, and load the extra field contents, after first creating the foo.lock file to gain exclusive access to the foo.* files. If foo.gz does not exist or is empty, then write the initial header, extra, and body content of an empty foo.gz log file. If there is an error creating the lock file due to access restrictions, or an error reading or writing the foo.gz file, or if the foo.gz file is not a proper log file for this object (e.g. not a gzip file or does not contain the expected extra field), then return true. If there is an error, the lock is released. Otherwise, the lock is left in place. */ local int log_open(struct log *log) { int op; /* release open file resource if left over -- can occur if lock lost between gzlog_open() and gzlog_write() */ if (log->fd >= 0) close(log->fd); log->fd = -1; /* negotiate exclusive access */ if (log_lock(log) < 0) return -1; /* open the log file, foo.gz */ strcpy(log->end, ".gz"); log->fd = open(log->path, O_RDWR | O_CREAT, 0644); if (log->fd < 0) { log_close(log); return -1; } /* if new, initialize foo.gz with an empty log, delete old dictionary */ if (lseek(log->fd, 0, SEEK_END) == 0) { if (write(log->fd, log_gzhead, HEAD) != HEAD || write(log->fd, log_gzext, EXTRA) != EXTRA || write(log->fd, log_gzbody, BODY) != BODY) { log_close(log); return -1; } strcpy(log->end, ".dict"); unlink(log->path); } /* verify log file and load extra field information */ if ((op = log_head(log)) < 0) { log_close(log); return -1; } /* check for interrupted process and if so, recover */ if (op != NO_OP && log_recover(log, op)) { log_close(log); return -1; } /* touch the lock file to prevent another process from grabbing it */ log_touch(log); return 0; } /* See gzlog.h for the description of the external methods below */ gzlog *gzlog_open(char *path) { size_t n; struct log *log; /* check arguments */ if (path == NULL || *path == 0) return NULL; /* allocate and initialize log structure */ log = malloc(sizeof(struct log)); if (log == NULL) return NULL; strcpy(log->id, LOGID); log->fd = -1; /* save path and end of path for name construction */ n = strlen(path); log->path = malloc(n + 9); /* allow for ".repairs" */ if (log->path == NULL) { free(log); return NULL; } strcpy(log->path, path); log->end = log->path + n; /* gain exclusive access and verify log file -- may perform a recovery operation if needed */ if (log_open(log)) { free(log->path); free(log); return NULL; } /* return pointer to log structure */ return log; } /* gzlog_compress() return values: 0: all good -1: file i/o error (usually access issue) -2: memory allocation failure -3: invalid log pointer argument */ int gzlog_compress(gzlog *logd) { int fd, ret; uint block; size_t len, next; unsigned char *data, buf[5]; struct log *log = logd; /* check arguments */ if (log == NULL || strcmp(log->id, LOGID)) return -3; /* see if we lost the lock -- if so get it again and reload the extra field information (it probably changed), recover last operation if necessary */ if (log_check(log) && log_open(log)) return -1; /* create space for uncompressed data */ len = ((size_t)(log->last - log->first) & ~(((size_t)1 << 10) - 1)) + log->stored; if ((data = malloc(len)) == NULL) return -2; /* do statement here is just a cheap trick for error handling */ do { /* read in the uncompressed data */ if (lseek(log->fd, log->first - 1, SEEK_SET) < 0) break; next = 0; while (next < len) { if (read(log->fd, buf, 5) != 5) break; block = PULL2(buf + 1); if (next + block > len || read(log->fd, (char *)data + next, block) != block) break; next += block; } if (lseek(log->fd, 0, SEEK_CUR) != log->last + 4 + log->stored) break; log_touch(log); /* write the uncompressed data to the .add file */ strcpy(log->end, ".add"); fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) break; ret = (size_t)write(fd, data, len) != len; if (ret | close(fd)) break; log_touch(log); /* write the dictionary for the next compress to the .temp file */ strcpy(log->end, ".temp"); fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) break; next = DICT > len ? len : DICT; ret = (size_t)write(fd, (char *)data + len - next, next) != next; if (ret | close(fd)) break; log_touch(log); /* roll back to compressed data, mark the compress in progress */ log->last = log->first; log->stored = 0; if (log_mark(log, COMPRESS_OP)) break; BAIL(7); /* compress and append the data (clears mark) */ ret = log_compress(log, data, len); free(data); return ret; } while (0); /* broke out of do above on i/o error */ free(data); return -1; } /* gzlog_write() return values: 0: all good -1: file i/o error (usually access issue) -2: memory allocation failure -3: invalid log pointer argument */ int gzlog_write(gzlog *logd, void *data, size_t len) { int fd, ret; struct log *log = logd; /* check arguments */ if (log == NULL || strcmp(log->id, LOGID)) return -3; if (data == NULL || len <= 0) return 0; /* see if we lost the lock -- if so get it again and reload the extra field information (it probably changed), recover last operation if necessary */ if (log_check(log) && log_open(log)) return -1; /* create and write .add file */ strcpy(log->end, ".add"); fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) return -1; ret = (size_t)write(fd, data, len) != len; if (ret | close(fd)) return -1; log_touch(log); /* mark log file with append in progress */ if (log_mark(log, APPEND_OP)) return -1; BAIL(8); /* append data (clears mark) */ if (log_append(log, data, len)) return -1; /* check to see if it's time to compress -- if not, then done */ if (((log->last - log->first) >> 10) + (log->stored >> 10) < TRIGGER) return 0; /* time to compress */ return gzlog_compress(log); } /* gzlog_close() return values: 0: ok -3: invalid log pointer argument */ int gzlog_close(gzlog *logd) { struct log *log = logd; /* check arguments */ if (log == NULL || strcmp(log->id, LOGID)) return -3; /* close the log file and release the lock */ log_close(log); /* free structure and return */ if (log->path != NULL) free(log->path); strcpy(log->id, "bad"); free(log); return 0; } tcl8.6.5/compat/zlib/examples/gzjoin.c0000644000175000017500000003346412663660065017306 0ustar sergeisergei/* gzjoin -- command to join gzip files into one gzip file Copyright (C) 2004, 2005, 2012 Mark Adler, all rights reserved version 1.2, 14 Aug 2012 This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Mark Adler madler@alumni.caltech.edu */ /* * Change history: * * 1.0 11 Dec 2004 - First version * 1.1 12 Jun 2005 - Changed ssize_t to long for portability * 1.2 14 Aug 2012 - Clean up for z_const usage */ /* gzjoin takes one or more gzip files on the command line and writes out a single gzip file that will uncompress to the concatenation of the uncompressed data from the individual gzip files. gzjoin does this without having to recompress any of the data and without having to calculate a new crc32 for the concatenated uncompressed data. gzjoin does however have to decompress all of the input data in order to find the bits in the compressed data that need to be modified to concatenate the streams. gzjoin does not do an integrity check on the input gzip files other than checking the gzip header and decompressing the compressed data. They are otherwise assumed to be complete and correct. Each joint between gzip files removes at least 18 bytes of previous trailer and subsequent header, and inserts an average of about three bytes to the compressed data in order to connect the streams. The output gzip file has a minimal ten-byte gzip header with no file name or modification time. This program was written to illustrate the use of the Z_BLOCK option of inflate() and the crc32_combine() function. gzjoin will not compile with versions of zlib earlier than 1.2.3. */ #include /* fputs(), fprintf(), fwrite(), putc() */ #include /* exit(), malloc(), free() */ #include /* open() */ #include /* close(), read(), lseek() */ #include "zlib.h" /* crc32(), crc32_combine(), inflateInit2(), inflate(), inflateEnd() */ #define local static /* exit with an error (return a value to allow use in an expression) */ local int bail(char *why1, char *why2) { fprintf(stderr, "gzjoin error: %s%s, output incomplete\n", why1, why2); exit(1); return 0; } /* -- simple buffered file input with access to the buffer -- */ #define CHUNK 32768 /* must be a power of two and fit in unsigned */ /* bin buffered input file type */ typedef struct { char *name; /* name of file for error messages */ int fd; /* file descriptor */ unsigned left; /* bytes remaining at next */ unsigned char *next; /* next byte to read */ unsigned char *buf; /* allocated buffer of length CHUNK */ } bin; /* close a buffered file and free allocated memory */ local void bclose(bin *in) { if (in != NULL) { if (in->fd != -1) close(in->fd); if (in->buf != NULL) free(in->buf); free(in); } } /* open a buffered file for input, return a pointer to type bin, or NULL on failure */ local bin *bopen(char *name) { bin *in; in = malloc(sizeof(bin)); if (in == NULL) return NULL; in->buf = malloc(CHUNK); in->fd = open(name, O_RDONLY, 0); if (in->buf == NULL || in->fd == -1) { bclose(in); return NULL; } in->left = 0; in->next = in->buf; in->name = name; return in; } /* load buffer from file, return -1 on read error, 0 or 1 on success, with 1 indicating that end-of-file was reached */ local int bload(bin *in) { long len; if (in == NULL) return -1; if (in->left != 0) return 0; in->next = in->buf; do { len = (long)read(in->fd, in->buf + in->left, CHUNK - in->left); if (len < 0) return -1; in->left += (unsigned)len; } while (len != 0 && in->left < CHUNK); return len == 0 ? 1 : 0; } /* get a byte from the file, bail if end of file */ #define bget(in) (in->left ? 0 : bload(in), \ in->left ? (in->left--, *(in->next)++) : \ bail("unexpected end of file on ", in->name)) /* get a four-byte little-endian unsigned integer from file */ local unsigned long bget4(bin *in) { unsigned long val; val = bget(in); val += (unsigned long)(bget(in)) << 8; val += (unsigned long)(bget(in)) << 16; val += (unsigned long)(bget(in)) << 24; return val; } /* skip bytes in file */ local void bskip(bin *in, unsigned skip) { /* check pointer */ if (in == NULL) return; /* easy case -- skip bytes in buffer */ if (skip <= in->left) { in->left -= skip; in->next += skip; return; } /* skip what's in buffer, discard buffer contents */ skip -= in->left; in->left = 0; /* seek past multiples of CHUNK bytes */ if (skip > CHUNK) { unsigned left; left = skip & (CHUNK - 1); if (left == 0) { /* exact number of chunks: seek all the way minus one byte to check for end-of-file with a read */ lseek(in->fd, skip - 1, SEEK_CUR); if (read(in->fd, in->buf, 1) != 1) bail("unexpected end of file on ", in->name); return; } /* skip the integral chunks, update skip with remainder */ lseek(in->fd, skip - left, SEEK_CUR); skip = left; } /* read more input and skip remainder */ bload(in); if (skip > in->left) bail("unexpected end of file on ", in->name); in->left -= skip; in->next += skip; } /* -- end of buffered input functions -- */ /* skip the gzip header from file in */ local void gzhead(bin *in) { int flags; /* verify gzip magic header and compression method */ if (bget(in) != 0x1f || bget(in) != 0x8b || bget(in) != 8) bail(in->name, " is not a valid gzip file"); /* get and verify flags */ flags = bget(in); if ((flags & 0xe0) != 0) bail("unknown reserved bits set in ", in->name); /* skip modification time, extra flags, and os */ bskip(in, 6); /* skip extra field if present */ if (flags & 4) { unsigned len; len = bget(in); len += (unsigned)(bget(in)) << 8; bskip(in, len); } /* skip file name if present */ if (flags & 8) while (bget(in) != 0) ; /* skip comment if present */ if (flags & 16) while (bget(in) != 0) ; /* skip header crc if present */ if (flags & 2) bskip(in, 2); } /* write a four-byte little-endian unsigned integer to out */ local void put4(unsigned long val, FILE *out) { putc(val & 0xff, out); putc((val >> 8) & 0xff, out); putc((val >> 16) & 0xff, out); putc((val >> 24) & 0xff, out); } /* Load up zlib stream from buffered input, bail if end of file */ local void zpull(z_streamp strm, bin *in) { if (in->left == 0) bload(in); if (in->left == 0) bail("unexpected end of file on ", in->name); strm->avail_in = in->left; strm->next_in = in->next; } /* Write header for gzip file to out and initialize trailer. */ local void gzinit(unsigned long *crc, unsigned long *tot, FILE *out) { fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out); *crc = crc32(0L, Z_NULL, 0); *tot = 0; } /* Copy the compressed data from name, zeroing the last block bit of the last block if clr is true, and adding empty blocks as needed to get to a byte boundary. If clr is false, then the last block becomes the last block of the output, and the gzip trailer is written. crc and tot maintains the crc and length (modulo 2^32) of the output for the trailer. The resulting gzip file is written to out. gzinit() must be called before the first call of gzcopy() to write the gzip header and to initialize crc and tot. */ local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot, FILE *out) { int ret; /* return value from zlib functions */ int pos; /* where the "last block" bit is in byte */ int last; /* true if processing the last block */ bin *in; /* buffered input file */ unsigned char *start; /* start of compressed data in buffer */ unsigned char *junk; /* buffer for uncompressed data -- discarded */ z_off_t len; /* length of uncompressed data (support > 4 GB) */ z_stream strm; /* zlib inflate stream */ /* open gzip file and skip header */ in = bopen(name); if (in == NULL) bail("could not open ", name); gzhead(in); /* allocate buffer for uncompressed data and initialize raw inflate stream */ junk = malloc(CHUNK); strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit2(&strm, -15); if (junk == NULL || ret != Z_OK) bail("out of memory", ""); /* inflate and copy compressed data, clear last-block bit if requested */ len = 0; zpull(&strm, in); start = in->next; last = start[0] & 1; if (last && clr) start[0] &= ~1; strm.avail_out = 0; for (;;) { /* if input used and output done, write used input and get more */ if (strm.avail_in == 0 && strm.avail_out != 0) { fwrite(start, 1, strm.next_in - start, out); start = in->buf; in->left = 0; zpull(&strm, in); } /* decompress -- return early when end-of-block reached */ strm.avail_out = CHUNK; strm.next_out = junk; ret = inflate(&strm, Z_BLOCK); switch (ret) { case Z_MEM_ERROR: bail("out of memory", ""); case Z_DATA_ERROR: bail("invalid compressed data in ", in->name); } /* update length of uncompressed data */ len += CHUNK - strm.avail_out; /* check for block boundary (only get this when block copied out) */ if (strm.data_type & 128) { /* if that was the last block, then done */ if (last) break; /* number of unused bits in last byte */ pos = strm.data_type & 7; /* find the next last-block bit */ if (pos != 0) { /* next last-block bit is in last used byte */ pos = 0x100 >> pos; last = strm.next_in[-1] & pos; if (last && clr) in->buf[strm.next_in - in->buf - 1] &= ~pos; } else { /* next last-block bit is in next unused byte */ if (strm.avail_in == 0) { /* don't have that byte yet -- get it */ fwrite(start, 1, strm.next_in - start, out); start = in->buf; in->left = 0; zpull(&strm, in); } last = strm.next_in[0] & 1; if (last && clr) in->buf[strm.next_in - in->buf] &= ~1; } } } /* update buffer with unused input */ in->left = strm.avail_in; in->next = in->buf + (strm.next_in - in->buf); /* copy used input, write empty blocks to get to byte boundary */ pos = strm.data_type & 7; fwrite(start, 1, in->next - start - 1, out); last = in->next[-1]; if (pos == 0 || !clr) /* already at byte boundary, or last file: write last byte */ putc(last, out); else { /* append empty blocks to last byte */ last &= ((0x100 >> pos) - 1); /* assure unused bits are zero */ if (pos & 1) { /* odd -- append an empty stored block */ putc(last, out); if (pos == 1) putc(0, out); /* two more bits in block header */ fwrite("\0\0\xff\xff", 1, 4, out); } else { /* even -- append 1, 2, or 3 empty fixed blocks */ switch (pos) { case 6: putc(last | 8, out); last = 0; case 4: putc(last | 0x20, out); last = 0; case 2: putc(last | 0x80, out); putc(0, out); } } } /* update crc and tot */ *crc = crc32_combine(*crc, bget4(in), len); *tot += (unsigned long)len; /* clean up */ inflateEnd(&strm); free(junk); bclose(in); /* write trailer if this is the last gzip file */ if (!clr) { put4(*crc, out); put4(*tot, out); } } /* join the gzip files on the command line, write result to stdout */ int main(int argc, char **argv) { unsigned long crc, tot; /* running crc and total uncompressed length */ /* skip command name */ argc--; argv++; /* show usage if no arguments */ if (argc == 0) { fputs("gzjoin usage: gzjoin f1.gz [f2.gz [f3.gz ...]] > fjoin.gz\n", stderr); return 0; } /* join gzip files on command line and write to stdout */ gzinit(&crc, &tot, stdout); while (argc--) gzcopy(*argv++, argc, &crc, &tot, stdout); /* done */ return 0; } tcl8.6.5/compat/zlib/examples/zpipe.c0000644000175000017500000001426312663653206017130 0ustar sergeisergei/* zpipe.c: example of proper use of zlib's inflate() and deflate() Not copyrighted -- provided to the public domain Version 1.4 11 December 2005 Mark Adler */ /* Version history: 1.0 30 Oct 2004 First version 1.1 8 Nov 2004 Add void casting for unused return values Use switch statement for inflate() return values 1.2 9 Nov 2004 Add assertions to document zlib guarantees 1.3 6 Apr 2005 Remove incorrect assertion in inf() 1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions Avoid some compiler warnings for input and output buffers */ #include #include #include #include "zlib.h" #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) # include # include # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) #else # define SET_BINARY_MODE(file) #endif #define CHUNK 16384 /* Compress from file source to file dest until EOF on source. def() returns Z_OK on success, Z_MEM_ERROR if memory could not be allocated for processing, Z_STREAM_ERROR if an invalid compression level is supplied, Z_VERSION_ERROR if the version of zlib.h and the version of the library linked do not match, or Z_ERRNO if there is an error reading or writing the files. */ int def(FILE *source, FILE *dest, int level) { int ret, flush; unsigned have; z_stream strm; unsigned char in[CHUNK]; unsigned char out[CHUNK]; /* allocate deflate state */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; ret = deflateInit(&strm, level); if (ret != Z_OK) return ret; /* compress until end of file */ do { strm.avail_in = fread(in, 1, CHUNK, source); if (ferror(source)) { (void)deflateEnd(&strm); return Z_ERRNO; } flush = feof(source) ? Z_FINISH : Z_NO_FLUSH; strm.next_in = in; /* run deflate() on input until output buffer not full, finish compression if all of source has been read in */ do { strm.avail_out = CHUNK; strm.next_out = out; ret = deflate(&strm, flush); /* no bad return value */ assert(ret != Z_STREAM_ERROR); /* state not clobbered */ have = CHUNK - strm.avail_out; if (fwrite(out, 1, have, dest) != have || ferror(dest)) { (void)deflateEnd(&strm); return Z_ERRNO; } } while (strm.avail_out == 0); assert(strm.avail_in == 0); /* all input will be used */ /* done when last data in file processed */ } while (flush != Z_FINISH); assert(ret == Z_STREAM_END); /* stream will be complete */ /* clean up and return */ (void)deflateEnd(&strm); return Z_OK; } /* Decompress from file source to file dest until stream ends or EOF. inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be allocated for processing, Z_DATA_ERROR if the deflate data is invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and the version of the library linked do not match, or Z_ERRNO if there is an error reading or writing the files. */ int inf(FILE *source, FILE *dest) { int ret; unsigned have; z_stream strm; unsigned char in[CHUNK]; unsigned char out[CHUNK]; /* allocate inflate state */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit(&strm); if (ret != Z_OK) return ret; /* decompress until deflate stream ends or end of file */ do { strm.avail_in = fread(in, 1, CHUNK, source); if (ferror(source)) { (void)inflateEnd(&strm); return Z_ERRNO; } if (strm.avail_in == 0) break; strm.next_in = in; /* run inflate() on input until output buffer not full */ do { strm.avail_out = CHUNK; strm.next_out = out; ret = inflate(&strm, Z_NO_FLUSH); assert(ret != Z_STREAM_ERROR); /* state not clobbered */ switch (ret) { case Z_NEED_DICT: ret = Z_DATA_ERROR; /* and fall through */ case Z_DATA_ERROR: case Z_MEM_ERROR: (void)inflateEnd(&strm); return ret; } have = CHUNK - strm.avail_out; if (fwrite(out, 1, have, dest) != have || ferror(dest)) { (void)inflateEnd(&strm); return Z_ERRNO; } } while (strm.avail_out == 0); /* done when inflate() says it's done */ } while (ret != Z_STREAM_END); /* clean up and return */ (void)inflateEnd(&strm); return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; } /* report a zlib or i/o error */ void zerr(int ret) { fputs("zpipe: ", stderr); switch (ret) { case Z_ERRNO: if (ferror(stdin)) fputs("error reading stdin\n", stderr); if (ferror(stdout)) fputs("error writing stdout\n", stderr); break; case Z_STREAM_ERROR: fputs("invalid compression level\n", stderr); break; case Z_DATA_ERROR: fputs("invalid or incomplete deflate data\n", stderr); break; case Z_MEM_ERROR: fputs("out of memory\n", stderr); break; case Z_VERSION_ERROR: fputs("zlib version mismatch!\n", stderr); } } /* compress or decompress from stdin to stdout */ int main(int argc, char **argv) { int ret; /* avoid end-of-line conversions */ SET_BINARY_MODE(stdin); SET_BINARY_MODE(stdout); /* do compression if no arguments */ if (argc == 1) { ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION); if (ret != Z_OK) zerr(ret); return ret; } /* do decompression if -d specified */ else if (argc == 2 && strcmp(argv[1], "-d") == 0) { ret = inf(stdin, stdout); if (ret != Z_OK) zerr(ret); return ret; } /* otherwise, report usage */ else { fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr); return 1; } } tcl8.6.5/compat/zlib/examples/gzlog.h0000644000175000017500000001071512663660065017127 0ustar sergeisergei/* gzlog.h Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved version 2.2, 14 Aug 2012 This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Mark Adler madler@alumni.caltech.edu */ /* Version History: 1.0 26 Nov 2004 First version 2.0 25 Apr 2008 Complete redesign for recovery of interrupted operations Interface changed slightly in that now path is a prefix Compression now occurs as needed during gzlog_write() gzlog_write() now always leaves the log file as valid gzip 2.1 8 Jul 2012 Fix argument checks in gzlog_compress() and gzlog_write() 2.2 14 Aug 2012 Clean up signed comparisons */ /* The gzlog object allows writing short messages to a gzipped log file, opening the log file locked for small bursts, and then closing it. The log object works by appending stored (uncompressed) data to the gzip file until 1 MB has been accumulated. At that time, the stored data is compressed, and replaces the uncompressed data in the file. The log file is truncated to its new size at that time. After each write operation, the log file is a valid gzip file that can decompressed to recover what was written. The gzlog operations can be interupted at any point due to an application or system crash, and the log file will be recovered the next time the log is opened with gzlog_open(). */ #ifndef GZLOG_H #define GZLOG_H /* gzlog object type */ typedef void gzlog; /* Open a gzlog object, creating the log file if it does not exist. Return NULL on error. Note that gzlog_open() could take a while to complete if it has to wait to verify that a lock is stale (possibly for five minutes), or if there is significant contention with other instantiations of this object when locking the resource. path is the prefix of the file names created by this object. If path is "foo", then the log file will be "foo.gz", and other auxiliary files will be created and destroyed during the process: "foo.dict" for a compression dictionary, "foo.temp" for a temporary (next) dictionary, "foo.add" for data being added or compressed, "foo.lock" for the lock file, and "foo.repairs" to log recovery operations performed due to interrupted gzlog operations. A gzlog_open() followed by a gzlog_close() will recover a previously interrupted operation, if any. */ gzlog *gzlog_open(char *path); /* Write to a gzlog object. Return zero on success, -1 if there is a file i/o error on any of the gzlog files (this should not happen if gzlog_open() succeeded, unless the device has run out of space or leftover auxiliary files have permissions or ownership that prevent their use), -2 if there is a memory allocation failure, or -3 if the log argument is invalid (e.g. if it was not created by gzlog_open()). This function will write data to the file uncompressed, until 1 MB has been accumulated, at which time that data will be compressed. The log file will be a valid gzip file upon successful return. */ int gzlog_write(gzlog *log, void *data, size_t len); /* Force compression of any uncompressed data in the log. This should be used sparingly, if at all. The main application would be when a log file will not be appended to again. If this is used to compress frequently while appending, it will both significantly increase the execution time and reduce the compression ratio. The return codes are the same as for gzlog_write(). */ int gzlog_compress(gzlog *log); /* Close a gzlog object. Return zero on success, -3 if the log argument is invalid. The log object is freed, and so cannot be referenced again. */ int gzlog_close(gzlog *log); #endif tcl8.6.5/compat/zlib/zutil.h0000644000175000017500000001515612663660065015342 0ustar sergeisergei/* zutil.h -- internal interface and configuration of the compression library * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id$ */ #ifndef ZUTIL_H #define ZUTIL_H #ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL #endif #include "zlib.h" #if defined(STDC) && !defined(Z_SOLO) # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) # include # endif # include # include #endif #ifdef Z_SOLO typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ typedef unsigned char uch; typedef uch FAR uchf; typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ return (strm->msg = ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif /* default windowBits for decompression. MAX_WBITS is for compression only */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default memLevel */ #define STORED_BLOCK 0 #define STATIC_TREES 1 #define DYN_TREES 2 /* The three kinds of block type */ #define MIN_MATCH 3 #define MAX_MATCH 258 /* The minimum and maximum match lengths */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ /* target dependencies */ #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 # ifndef Z_SOLO # if defined(__TURBOC__) || defined(__BORLANDC__) # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) /* Allow compilation with ANSI keywords only enabled */ void _Cdecl farfree( void *block ); void *_Cdecl farmalloc( unsigned long nbytes ); # else # include # endif # else /* MSC or DJGPP */ # include # endif # endif #endif #ifdef AMIGA # define OS_CODE 0x01 #endif #if defined(VAXC) || defined(VMS) # define OS_CODE 0x02 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif #if defined(ATARI) || defined(atarist) # define OS_CODE 0x05 #endif #ifdef OS2 # define OS_CODE 0x06 # if defined(M_I86) && !defined(Z_SOLO) # include # endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) # define OS_CODE 0x07 # ifndef Z_SOLO # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os # include /* for fdopen */ # else # ifndef fdopen # define fdopen(fd,mode) NULL /* No fdopen() */ # endif # endif # endif #endif #ifdef TOPS20 # define OS_CODE 0x0a #endif #ifdef WIN32 # ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ # define OS_CODE 0x0b # endif #endif #ifdef __50SERIES /* Prime/PRIMOS */ # define OS_CODE 0x0f #endif #if defined(_BEOS_) || defined(RISCOS) # define fdopen(fd,mode) NULL /* No fdopen() */ #endif #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX # if defined(_WIN32_WCE) # define fdopen(fd,mode) NULL /* No fdopen() */ # ifndef _PTRDIFF_T_DEFINED typedef int ptrdiff_t; # define _PTRDIFF_T_DEFINED # endif # else # define fdopen(fd,type) _fdopen(fd,type) # endif #endif #if defined(__BORLANDC__) && !defined(MSDOS) #pragma warn -8004 #pragma warn -8008 #pragma warn -8066 #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_WIN32) && \ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); #endif /* common defaults */ #ifndef OS_CODE # define OS_CODE 0x03 /* assume Unix */ #endif #ifndef F_OPEN # define F_OPEN(name, mode) fopen((name), (mode)) #endif /* functions */ #if defined(pyr) || defined(Z_SOLO) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) /* Use our own functions for small and medium model with MSC <= 5.0. * You may have to use the same strategy for Borland C (untested). * The __SC__ check is for Symantec. */ # define NO_MEMCPY #endif #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) # define HAVE_MEMCPY #endif #ifdef HAVE_MEMCPY # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ # define zmemcpy _fmemcpy # define zmemcmp _fmemcmp # define zmemzero(dest, len) _fmemset(dest, 0, len) # else # define zmemcpy memcpy # define zmemcmp memcmp # define zmemzero(dest, len) memset(dest, 0, len) # endif #else void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); #endif /* Diagnostic functions */ #ifdef DEBUG # include extern int ZLIB_INTERNAL z_verbose; extern void ZLIB_INTERNAL z_error OF((char *m)); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} # define Tracevv(x) {if (z_verbose>1) fprintf x ;} # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} #else # define Assert(cond,msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) # define Tracec(c,x) # define Tracecv(c,x) #endif #ifndef Z_SOLO voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, unsigned size)); void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); #endif #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} /* Reverse the bytes in a 32-bit value */ #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) #endif /* ZUTIL_H */ tcl8.6.5/compat/zlib/ChangeLog0000644000175000017500000022516212663660064015573 0ustar sergeisergei ChangeLog file for zlib Changes in 1.2.8 (28 Apr 2013) - Update contrib/minizip/iowin32.c for Windows RT [Vollant] - Do not force Z_CONST for C++ - Clean up contrib/vstudio [Ro§] - Correct spelling error in zlib.h - Fix mixed line endings in contrib/vstudio Changes in 1.2.7.3 (13 Apr 2013) - Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc Changes in 1.2.7.2 (13 Apr 2013) - Change check for a four-byte type back to hexadecimal - Fix typo in win32/Makefile.msc - Add casts in gzwrite.c for pointer differences Changes in 1.2.7.1 (24 Mar 2013) - Replace use of unsafe string functions with snprintf if available - Avoid including stddef.h on Windows for Z_SOLO compile [Niessink] - Fix gzgetc undefine when Z_PREFIX set [Turk] - Eliminate use of mktemp in Makefile (not always available) - Fix bug in 'F' mode for gzopen() - Add inflateGetDictionary() function - Correct comment in deflate.h - Use _snprintf for snprintf in Microsoft C - On Darwin, only use /usr/bin/libtool if libtool is not Apple - Delete "--version" file if created by "ar --version" [Richard G.] - Fix configure check for veracity of compiler error return codes - Fix CMake compilation of static lib for MSVC2010 x64 - Remove unused variable in infback9.c - Fix argument checks in gzlog_compress() and gzlog_write() - Clean up the usage of z_const and respect const usage within zlib - Clean up examples/gzlog.[ch] comparisons of different types - Avoid shift equal to bits in type (caused endless loop) - Fix unintialized value bug in gzputc() introduced by const patches - Fix memory allocation error in examples/zran.c [Nor] - Fix bug where gzopen(), gzclose() would write an empty file - Fix bug in gzclose() when gzwrite() runs out of memory - Check for input buffer malloc failure in examples/gzappend.c - Add note to contrib/blast to use binary mode in stdio - Fix comparisons of differently signed integers in contrib/blast - Check for invalid code length codes in contrib/puff - Fix serious but very rare decompression bug in inftrees.c - Update inflateBack() comments, since inflate() can be faster - Use underscored I/O function names for WINAPI_FAMILY - Add _tr_flush_bits to the external symbols prefixed by --zprefix - Add contrib/vstudio/vc10 pre-build step for static only - Quote --version-script argument in CMakeLists.txt - Don't specify --version-script on Apple platforms in CMakeLists.txt - Fix casting error in contrib/testzlib/testzlib.c - Fix types in contrib/minizip to match result of get_crc_table() - Simplify contrib/vstudio/vc10 with 'd' suffix - Add TOP support to win32/Makefile.msc - Suport i686 and amd64 assembler builds in CMakeLists.txt - Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h - Add vc11 and vc12 build files to contrib/vstudio - Add gzvprintf() as an undocumented function in zlib - Fix configure for Sun shell - Remove runtime check in configure for four-byte integer type - Add casts and consts to ease user conversion to C++ - Add man pages for minizip and miniunzip - In Makefile uninstall, don't rm if preceding cd fails - Do not return Z_BUF_ERROR if deflateParam() has nothing to write Changes in 1.2.7 (2 May 2012) - Replace use of memmove() with a simple copy for portability - Test for existence of strerror - Restore gzgetc_ for backward compatibility with 1.2.6 - Fix build with non-GNU make on Solaris - Require gcc 4.0 or later on Mac OS X to use the hidden attribute - Include unistd.h for Watcom C - Use __WATCOMC__ instead of __WATCOM__ - Do not use the visibility attribute if NO_VIZ defined - Improve the detection of no hidden visibility attribute - Avoid using __int64 for gcc or solo compilation - Cast to char * in gzprintf to avoid warnings [Zinser] - Fix make_vms.com for VAX [Zinser] - Don't use library or built-in byte swaps - Simplify test and use of gcc hidden attribute - Fix bug in gzclose_w() when gzwrite() fails to allocate memory - Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen() - Fix bug in test/minigzip.c for configure --solo - Fix contrib/vstudio project link errors [Mohanathas] - Add ability to choose the builder in make_vms.com [Schweda] - Add DESTDIR support to mingw32 win32/Makefile.gcc - Fix comments in win32/Makefile.gcc for proper usage - Allow overriding the default install locations for cmake - Generate and install the pkg-config file with cmake - Build both a static and a shared version of zlib with cmake - Include version symbols for cmake builds - If using cmake with MSVC, add the source directory to the includes - Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta] - Move obsolete emx makefile to old [Truta] - Allow the use of -Wundef when compiling or using zlib - Avoid the use of the -u option with mktemp - Improve inflate() documentation on the use of Z_FINISH - Recognize clang as gcc - Add gzopen_w() in Windows for wide character path names - Rename zconf.h in CMakeLists.txt to move it out of the way - Add source directory in CMakeLists.txt for building examples - Look in build directory for zlib.pc in CMakeLists.txt - Remove gzflags from zlibvc.def in vc9 and vc10 - Fix contrib/minizip compilation in the MinGW environment - Update ./configure for Solaris, support --64 [Mooney] - Remove -R. from Solaris shared build (possible security issue) - Avoid race condition for parallel make (-j) running example - Fix type mismatch between get_crc_table() and crc_table - Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler] - Fix the path to zlib.map in CMakeLists.txt - Force the native libtool in Mac OS X to avoid GNU libtool [Beebe] - Add instructions to win32/Makefile.gcc for shared install [Torri] Changes in 1.2.6.1 (12 Feb 2012) - Avoid the use of the Objective-C reserved name "id" - Include io.h in gzguts.h for Microsoft compilers - Fix problem with ./configure --prefix and gzgetc macro - Include gz_header definition when compiling zlib solo - Put gzflags() functionality back in zutil.c - Avoid library header include in crc32.c for Z_SOLO - Use name in GCC_CLASSIC as C compiler for coverage testing, if set - Minor cleanup in contrib/minizip/zip.c [Vollant] - Update make_vms.com [Zinser] - Remove unnecessary gzgetc_ function - Use optimized byte swap operations for Microsoft and GNU [Snyder] - Fix minor typo in zlib.h comments [Rzesniowiecki] Changes in 1.2.6 (29 Jan 2012) - Update the Pascal interface in contrib/pascal - Fix function numbers for gzgetc_ in zlibvc.def files - Fix configure.ac for contrib/minizip [Schiffer] - Fix large-entry detection in minizip on 64-bit systems [Schiffer] - Have ./configure use the compiler return code for error indication - Fix CMakeLists.txt for cross compilation [McClure] - Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes] - Fix compilation of contrib/minizip on FreeBSD [Marquez] - Correct suggested usages in win32/Makefile.msc [Shachar, Horvath] - Include io.h for Turbo C / Borland C on all platforms [Truta] - Make version explicit in contrib/minizip/configure.ac [Bosmans] - Avoid warning for no encryption in contrib/minizip/zip.c [Vollant] - Minor cleanup up contrib/minizip/unzip.c [Vollant] - Fix bug when compiling minizip with C++ [Vollant] - Protect for long name and extra fields in contrib/minizip [Vollant] - Avoid some warnings in contrib/minizip [Vollant] - Add -I../.. -L../.. to CFLAGS for minizip and miniunzip - Add missing libs to minizip linker command - Add support for VPATH builds in contrib/minizip - Add an --enable-demos option to contrib/minizip/configure - Add the generation of configure.log by ./configure - Exit when required parameters not provided to win32/Makefile.gcc - Have gzputc return the character written instead of the argument - Use the -m option on ldconfig for BSD systems [Tobias] - Correct in zlib.map when deflateResetKeep was added Changes in 1.2.5.3 (15 Jan 2012) - Restore gzgetc function for binary compatibility - Do not use _lseeki64 under Borland C++ [Truta] - Update win32/Makefile.msc to build test/*.c [Truta] - Remove old/visualc6 given CMakefile and other alternatives - Update AS400 build files and documentation [Monnerat] - Update win32/Makefile.gcc to build test/*.c [Truta] - Permit stronger flushes after Z_BLOCK flushes - Avoid extraneous empty blocks when doing empty flushes - Permit Z_NULL arguments to deflatePending - Allow deflatePrime() to insert bits in the middle of a stream - Remove second empty static block for Z_PARTIAL_FLUSH - Write out all of the available bits when using Z_BLOCK - Insert the first two strings in the hash table after a flush Changes in 1.2.5.2 (17 Dec 2011) - fix ld error: unable to find version dependency 'ZLIB_1.2.5' - use relative symlinks for shared libs - Avoid searching past window for Z_RLE strategy - Assure that high-water mark initialization is always applied in deflate - Add assertions to fill_window() in deflate.c to match comments - Update python link in README - Correct spelling error in gzread.c - Fix bug in gzgets() for a concatenated empty gzip stream - Correct error in comment for gz_make() - Change gzread() and related to ignore junk after gzip streams - Allow gzread() and related to continue after gzclearerr() - Allow gzrewind() and gzseek() after a premature end-of-file - Simplify gzseek() now that raw after gzip is ignored - Change gzgetc() to a macro for speed (~40% speedup in testing) - Fix gzclose() to return the actual error last encountered - Always add large file support for windows - Include zconf.h for windows large file support - Include zconf.h.cmakein for windows large file support - Update zconf.h.cmakein on make distclean - Merge vestigial vsnprintf determination from zutil.h to gzguts.h - Clarify how gzopen() appends in zlib.h comments - Correct documentation of gzdirect() since junk at end now ignored - Add a transparent write mode to gzopen() when 'T' is in the mode - Update python link in zlib man page - Get inffixed.h and MAKEFIXED result to match - Add a ./config --solo option to make zlib subset with no libary use - Add undocumented inflateResetKeep() function for CAB file decoding - Add --cover option to ./configure for gcc coverage testing - Add #define ZLIB_CONST option to use const in the z_stream interface - Add comment to gzdopen() in zlib.h to use dup() when using fileno() - Note behavior of uncompress() to provide as much data as it can - Add files in contrib/minizip to aid in building libminizip - Split off AR options in Makefile.in and configure - Change ON macro to Z_ARG to avoid application conflicts - Facilitate compilation with Borland C++ for pragmas and vsnprintf - Include io.h for Turbo C / Borland C++ - Move example.c and minigzip.c to test/ - Simplify incomplete code table filling in inflate_table() - Remove code from inflate.c and infback.c that is impossible to execute - Test the inflate code with full coverage - Allow deflateSetDictionary, inflateSetDictionary at any time (in raw) - Add deflateResetKeep and fix inflateResetKeep to retain dictionary - Fix gzwrite.c to accommodate reduced memory zlib compilation - Have inflate() with Z_FINISH avoid the allocation of a window - Do not set strm->adler when doing raw inflate - Fix gzeof() to behave just like feof() when read is not past end of file - Fix bug in gzread.c when end-of-file is reached - Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF - Document gzread() capability to read concurrently written files - Remove hard-coding of resource compiler in CMakeLists.txt [Blammo] Changes in 1.2.5.1 (10 Sep 2011) - Update FAQ entry on shared builds (#13) - Avoid symbolic argument to chmod in Makefile.in - Fix bug and add consts in contrib/puff [Oberhumer] - Update contrib/puff/zeros.raw test file to have all block types - Add full coverage test for puff in contrib/puff/Makefile - Fix static-only-build install in Makefile.in - Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno] - Add libz.a dependency to shared in Makefile.in for parallel builds - Spell out "number" (instead of "nb") in zlib.h for total_in, total_out - Replace $(...) with `...` in configure for non-bash sh [Bowler] - Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen] - Add solaris* to Linux* in configure to allow gcc use [Groffen] - Add *bsd* to Linux* case in configure [Bar-Lev] - Add inffast.obj to dependencies in win32/Makefile.msc - Correct spelling error in deflate.h [Kohler] - Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc - Add test to configure for GNU C looking for gcc in output of $cc -v - Add zlib.pc generation to win32/Makefile.gcc [Weigelt] - Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not - Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense - Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser) - Make stronger test in zconf.h to include unistd.h for LFS - Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack] - Fix zlib.h LFS support when Z_PREFIX used - Add updated as400 support (removed from old) [Monnerat] - Avoid deflate sensitivity to volatile input data - Avoid division in adler32_combine for NO_DIVIDE - Clarify the use of Z_FINISH with deflateBound() amount of space - Set binary for output file in puff.c - Use u4 type for crc_table to avoid conversion warnings - Apply casts in zlib.h to avoid conversion warnings - Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] - Improve inflateSync() documentation to note indeterminancy - Add deflatePending() function to return the amount of pending output - Correct the spelling of "specification" in FAQ [Randers-Pehrson] - Add a check in configure for stdarg.h, use for gzprintf() - Check that pointers fit in ints when gzprint() compiled old style - Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] - Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] - Add debug records in assmebler code [Londer] - Update RFC references to use http://tools.ietf.org/html/... [Li] - Add --archs option, use of libtool to configure for Mac OS X [Borstel] Changes in 1.2.5 (19 Apr 2010) - Disable visibility attribute in win32/Makefile.gcc [Bar-Lev] - Default to libdir as sharedlibdir in configure [Nieder] - Update copyright dates on modified source files - Update trees.c to be able to generate modified trees.h - Exit configure for MinGW, suggesting win32/Makefile.gcc - Check for NULL path in gz_open [Homurlu] Changes in 1.2.4.5 (18 Apr 2010) - Set sharedlibdir in configure [Torok] - Set LDFLAGS in Makefile.in [Bar-Lev] - Avoid mkdir objs race condition in Makefile.in [Bowler] - Add ZLIB_INTERNAL in front of internal inter-module functions and arrays - Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C - Don't use hidden attribute when it is a warning generator (e.g. Solaris) Changes in 1.2.4.4 (18 Apr 2010) - Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok] - Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty - Try to use bash or ksh regardless of functionality of /bin/sh - Fix configure incompatibility with NetBSD sh - Remove attempt to run under bash or ksh since have better NetBSD fix - Fix win32/Makefile.gcc for MinGW [Bar-Lev] - Add diagnostic messages when using CROSS_PREFIX in configure - Added --sharedlibdir option to configure [Weigelt] - Use hidden visibility attribute when available [Frysinger] Changes in 1.2.4.3 (10 Apr 2010) - Only use CROSS_PREFIX in configure for ar and ranlib if they exist - Use CROSS_PREFIX for nm [Bar-Lev] - Assume _LARGEFILE64_SOURCE defined is equivalent to true - Avoid use of undefined symbols in #if with && and || - Make *64 prototypes in gzguts.h consistent with functions - Add -shared load option for MinGW in configure [Bowler] - Move z_off64_t to public interface, use instead of off64_t - Remove ! from shell test in configure (not portable to Solaris) - Change +0 macro tests to -0 for possibly increased portability Changes in 1.2.4.2 (9 Apr 2010) - Add consistent carriage returns to readme.txt's in masmx86 and masmx64 - Really provide prototypes for *64 functions when building without LFS - Only define unlink() in minigzip.c if unistd.h not included - Update README to point to contrib/vstudio project files - Move projects/vc6 to old/ and remove projects/ - Include stdlib.h in minigzip.c for setmode() definition under WinCE - Clean up assembler builds in win32/Makefile.msc [Rowe] - Include sys/types.h for Microsoft for off_t definition - Fix memory leak on error in gz_open() - Symbolize nm as $NM in configure [Weigelt] - Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt] - Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined - Fix bug in gzeof() to take into account unused input data - Avoid initialization of structures with variables in puff.c - Updated win32/README-WIN32.txt [Rowe] Changes in 1.2.4.1 (28 Mar 2010) - Remove the use of [a-z] constructs for sed in configure [gentoo 310225] - Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech] - Restore "for debugging" comment on sprintf() in gzlib.c - Remove fdopen for MVS from gzguts.h - Put new README-WIN32.txt in win32 [Rowe] - Add check for shell to configure and invoke another shell if needed - Fix big fat stinking bug in gzseek() on uncompressed files - Remove vestigial F_OPEN64 define in zutil.h - Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE - Avoid errors on non-LFS systems when applications define LFS macros - Set EXE to ".exe" in configure for MINGW [Kahle] - Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill] - Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev] - Add DLL install in win32/makefile.gcc [Bar-Lev] - Allow Linux* or linux* from uname in configure [Bar-Lev] - Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev] - Add cross-compilation prefixes to configure [Bar-Lev] - Match type exactly in gz_load() invocation in gzread.c - Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func - Provide prototypes for *64 functions when building zlib without LFS - Don't use -lc when linking shared library on MinGW - Remove errno.h check in configure and vestigial errno code in zutil.h Changes in 1.2.4 (14 Mar 2010) - Fix VER3 extraction in configure for no fourth subversion - Update zlib.3, add docs to Makefile.in to make .pdf out of it - Add zlib.3.pdf to distribution - Don't set error code in gzerror() if passed pointer is NULL - Apply destination directory fixes to CMakeLists.txt [Lowman] - Move #cmakedefine's to a new zconf.in.cmakein - Restore zconf.h for builds that don't use configure or cmake - Add distclean to dummy Makefile for convenience - Update and improve INDEX, README, and FAQ - Update CMakeLists.txt for the return of zconf.h [Lowman] - Update contrib/vstudio/vc9 and vc10 [Vollant] - Change libz.dll.a back to libzdll.a in win32/Makefile.gcc - Apply license and readme changes to contrib/asm686 [Raiter] - Check file name lengths and add -c option in minigzip.c [Li] - Update contrib/amd64 and contrib/masmx86/ [Vollant] - Avoid use of "eof" parameter in trees.c to not shadow library variable - Update make_vms.com for removal of zlibdefs.h [Zinser] - Update assembler code and vstudio projects in contrib [Vollant] - Remove outdated assembler code contrib/masm686 and contrib/asm586 - Remove old vc7 and vc8 from contrib/vstudio - Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe] - Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open() - Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant] - Remove *64 functions from win32/zlib.def (they're not 64-bit yet) - Fix bug in void-returning vsprintf() case in gzwrite.c - Fix name change from inflate.h in contrib/inflate86/inffas86.c - Check if temporary file exists before removing in make_vms.com [Zinser] - Fix make install and uninstall for --static option - Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta] - Update readme.txt in contrib/masmx64 and masmx86 to assemble Changes in 1.2.3.9 (21 Feb 2010) - Expunge gzio.c - Move as400 build information to old - Fix updates in contrib/minizip and contrib/vstudio - Add const to vsnprintf test in configure to avoid warnings [Weigelt] - Delete zconf.h (made by configure) [Weigelt] - Change zconf.in.h to zconf.h.in per convention [Weigelt] - Check for NULL buf in gzgets() - Return empty string for gzgets() with len == 1 (like fgets()) - Fix description of gzgets() in zlib.h for end-of-file, NULL return - Update minizip to 1.1 [Vollant] - Avoid MSVC loss of data warnings in gzread.c, gzwrite.c - Note in zlib.h that gzerror() should be used to distinguish from EOF - Remove use of snprintf() from gzlib.c - Fix bug in gzseek() - Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant] - Fix zconf.h generation in CMakeLists.txt [Lowman] - Improve comments in zconf.h where modified by configure Changes in 1.2.3.8 (13 Feb 2010) - Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer] - Use z_off64_t in gz_zero() and gz_skip() to match state->skip - Avoid comparison problem when sizeof(int) == sizeof(z_off64_t) - Revert to Makefile.in from 1.2.3.6 (live with the clutter) - Fix missing error return in gzflush(), add zlib.h note - Add *64 functions to zlib.map [Levin] - Fix signed/unsigned comparison in gz_comp() - Use SFLAGS when testing shared linking in configure - Add --64 option to ./configure to use -m64 with gcc - Fix ./configure --help to correctly name options - Have make fail if a test fails [Levin] - Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson] - Remove assembler object files from contrib Changes in 1.2.3.7 (24 Jan 2010) - Always gzopen() with O_LARGEFILE if available - Fix gzdirect() to work immediately after gzopen() or gzdopen() - Make gzdirect() more precise when the state changes while reading - Improve zlib.h documentation in many places - Catch memory allocation failure in gz_open() - Complete close operation if seek forward in gzclose_w() fails - Return Z_ERRNO from gzclose_r() if close() fails - Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL - Return zero for gzwrite() errors to match zlib.h description - Return -1 on gzputs() error to match zlib.h description - Add zconf.in.h to allow recovery from configure modification [Weigelt] - Fix static library permissions in Makefile.in [Weigelt] - Avoid warnings in configure tests that hide functionality [Weigelt] - Add *BSD and DragonFly to Linux case in configure [gentoo 123571] - Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212] - Avoid access of uninitialized data for first inflateReset2 call [Gomes] - Keep object files in subdirectories to reduce the clutter somewhat - Remove default Makefile and zlibdefs.h, add dummy Makefile - Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_ - Remove zlibdefs.h completely -- modify zconf.h instead Changes in 1.2.3.6 (17 Jan 2010) - Avoid void * arithmetic in gzread.c and gzwrite.c - Make compilers happier with const char * for gz_error message - Avoid unused parameter warning in inflate.c - Avoid signed-unsigned comparison warning in inflate.c - Indent #pragma's for traditional C - Fix usage of strwinerror() in glib.c, change to gz_strwinerror() - Correct email address in configure for system options - Update make_vms.com and add make_vms.com to contrib/minizip [Zinser] - Update zlib.map [Brown] - Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok] - Apply various fixes to CMakeLists.txt [Lowman] - Add checks on len in gzread() and gzwrite() - Add error message for no more room for gzungetc() - Remove zlib version check in gzwrite() - Defer compression of gzprintf() result until need to - Use snprintf() in gzdopen() if available - Remove USE_MMAP configuration determination (only used by minigzip) - Remove examples/pigz.c (available separately) - Update examples/gun.c to 1.6 Changes in 1.2.3.5 (8 Jan 2010) - Add space after #if in zutil.h for some compilers - Fix relatively harmless bug in deflate_fast() [Exarevsky] - Fix same problem in deflate_slow() - Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown] - Add deflate_rle() for faster Z_RLE strategy run-length encoding - Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding - Change name of "write" variable in inffast.c to avoid library collisions - Fix premature EOF from gzread() in gzio.c [Brown] - Use zlib header window size if windowBits is 0 in inflateInit2() - Remove compressBound() call in deflate.c to avoid linking compress.o - Replace use of errno in gz* with functions, support WinCE [Alves] - Provide alternative to perror() in minigzip.c for WinCE [Alves] - Don't use _vsnprintf on later versions of MSVC [Lowman] - Add CMake build script and input file [Lowman] - Update contrib/minizip to 1.1 [Svensson, Vollant] - Moved nintendods directory from contrib to . - Replace gzio.c with a new set of routines with the same functionality - Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above - Update contrib/minizip to 1.1b - Change gzeof() to return 0 on error instead of -1 to agree with zlib.h Changes in 1.2.3.4 (21 Dec 2009) - Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility - Update comments in configure and Makefile.in for default --shared - Fix test -z's in configure [Marquess] - Build examplesh and minigzipsh when not testing - Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h - Import LDFLAGS from the environment in configure - Fix configure to populate SFLAGS with discovered CFLAGS options - Adapt make_vms.com to the new Makefile.in [Zinser] - Add zlib2ansi script for C++ compilation [Marquess] - Add _FILE_OFFSET_BITS=64 test to make test (when applicable) - Add AMD64 assembler code for longest match to contrib [Teterin] - Include options from $SFLAGS when doing $LDSHARED - Simplify 64-bit file support by introducing z_off64_t type - Make shared object files in objs directory to work around old Sun cc - Use only three-part version number for Darwin shared compiles - Add rc option to ar in Makefile.in for when ./configure not run - Add -WI,-rpath,. to LDFLAGS for OSF 1 V4* - Set LD_LIBRARYN32_PATH for SGI IRIX shared compile - Protect against _FILE_OFFSET_BITS being defined when compiling zlib - Rename Makefile.in targets allstatic to static and allshared to shared - Fix static and shared Makefile.in targets to be independent - Correct error return bug in gz_open() by setting state [Brown] - Put spaces before ;;'s in configure for better sh compatibility - Add pigz.c (parallel implementation of gzip) to examples/ - Correct constant in crc32.c to UL [Leventhal] - Reject negative lengths in crc32_combine() - Add inflateReset2() function to work like inflateEnd()/inflateInit2() - Include sys/types.h for _LARGEFILE64_SOURCE [Brown] - Correct typo in doc/algorithm.txt [Janik] - Fix bug in adler32_combine() [Zhu] - Catch missing-end-of-block-code error in all inflates and in puff Assures that random input to inflate eventually results in an error - Added enough.c (calculation of ENOUGH for inftrees.h) to examples/ - Update ENOUGH and its usage to reflect discovered bounds - Fix gzerror() error report on empty input file [Brown] - Add ush casts in trees.c to avoid pedantic runtime errors - Fix typo in zlib.h uncompress() description [Reiss] - Correct inflate() comments with regard to automatic header detection - Remove deprecation comment on Z_PARTIAL_FLUSH (it stays) - Put new version of gzlog (2.0) in examples with interruption recovery - Add puff compile option to permit invalid distance-too-far streams - Add puff TEST command options, ability to read piped input - Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but _LARGEFILE64_SOURCE not defined - Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart - Fix deflateSetDictionary() to use all 32K for output consistency - Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h) - Clear bytes after deflate lookahead to avoid use of uninitialized data - Change a limit in inftrees.c to be more transparent to Coverity Prevent - Update win32/zlib.def with exported symbols from zlib.h - Correct spelling errors in zlib.h [Willem, Sobrado] - Allow Z_BLOCK for deflate() to force a new block - Allow negative bits in inflatePrime() to delete existing bit buffer - Add Z_TREES flush option to inflate() to return at end of trees - Add inflateMark() to return current state information for random access - Add Makefile for NintendoDS to contrib [Costa] - Add -w in configure compile tests to avoid spurious warnings [Beucler] - Fix typos in zlib.h comments for deflateSetDictionary() - Fix EOF detection in transparent gzread() [Maier] Changes in 1.2.3.3 (2 October 2006) - Make --shared the default for configure, add a --static option - Add compile option to permit invalid distance-too-far streams - Add inflateUndermine() function which is required to enable above - Remove use of "this" variable name for C++ compatibility [Marquess] - Add testing of shared library in make test, if shared library built - Use ftello() and fseeko() if available instead of ftell() and fseek() - Provide two versions of all functions that use the z_off_t type for binary compatibility -- a normal version and a 64-bit offset version, per the Large File Support Extension when _LARGEFILE64_SOURCE is defined; use the 64-bit versions by default when _FILE_OFFSET_BITS is defined to be 64 - Add a --uname= option to configure to perhaps help with cross-compiling Changes in 1.2.3.2 (3 September 2006) - Turn off silly Borland warnings [Hay] - Use off64_t and define _LARGEFILE64_SOURCE when present - Fix missing dependency on inffixed.h in Makefile.in - Rig configure --shared to build both shared and static [Teredesai, Truta] - Remove zconf.in.h and instead create a new zlibdefs.h file - Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant] - Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt] Changes in 1.2.3.1 (16 August 2006) - Add watcom directory with OpenWatcom make files [Daniel] - Remove #undef of FAR in zconf.in.h for MVS [Fedtke] - Update make_vms.com [Zinser] - Use -fPIC for shared build in configure [Teredesai, Nicholson] - Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen] - Use fdopen() (not _fdopen()) for Interix in zutil.h [BŠck] - Add some FAQ entries about the contrib directory - Update the MVS question in the FAQ - Avoid extraneous reads after EOF in gzio.c [Brown] - Correct spelling of "successfully" in gzio.c [Randers-Pehrson] - Add comments to zlib.h about gzerror() usage [Brown] - Set extra flags in gzip header in gzopen() like deflate() does - Make configure options more compatible with double-dash conventions [Weigelt] - Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen] - Fix uninstall target in Makefile.in [Truta] - Add pkgconfig support [Weigelt] - Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt] - Replace set_data_type() with a more accurate detect_data_type() in trees.c, according to the txtvsbin.txt document [Truta] - Swap the order of #include and #include "zlib.h" in gzio.c, example.c and minigzip.c [Truta] - Shut up annoying VS2005 warnings about standard C deprecation [Rowe, Truta] (where?) - Fix target "clean" from win32/Makefile.bor [Truta] - Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe] - Update zlib www home address in win32/DLL_FAQ.txt [Truta] - Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove] - Enable browse info in the "Debug" and "ASM Debug" configurations in the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta] - Add pkgconfig support [Weigelt] - Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h, for use in win32/zlib1.rc [Polushin, Rowe, Truta] - Add a document that explains the new text detection scheme to doc/txtvsbin.txt [Truta] - Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta] - Move algorithm.txt into doc/ [Truta] - Synchronize FAQ with website - Fix compressBound(), was low for some pathological cases [Fearnley] - Take into account wrapper variations in deflateBound() - Set examples/zpipe.c input and output to binary mode for Windows - Update examples/zlib_how.html with new zpipe.c (also web site) - Fix some warnings in examples/gzlog.c and examples/zran.c (it seems that gcc became pickier in 4.0) - Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain un-versioned, the patch adds versioning only for symbols introduced in zlib-1.2.0 or later. It also declares as local those symbols which are not designed to be exported." [Levin] - Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure - Do not initialize global static by default in trees.c, add a response NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess] - Don't use strerror() in gzio.c under WinCE [Yakimov] - Don't use errno.h in zutil.h under WinCE [Yakimov] - Move arguments for AR to its usage to allow replacing ar [Marot] - Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson] - Improve inflateInit() and inflateInit2() documentation - Fix structure size comment in inflate.h - Change configure help option from --h* to --help [Santos] Changes in 1.2.3 (18 July 2005) - Apply security vulnerability fixes to contrib/infback9 as well - Clean up some text files (carriage returns, trailing space) - Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] Changes in 1.2.2.4 (11 July 2005) - Add inflatePrime() function for starting inflation at bit boundary - Avoid some Visual C warnings in deflate.c - Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit compile - Fix some spelling errors in comments [Betts] - Correct inflateInit2() error return documentation in zlib.h - Add zran.c example of compressed data random access to examples directory, shows use of inflatePrime() - Fix cast for assignments to strm->state in inflate.c and infback.c - Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] - Move declarations of gf2 functions to right place in crc32.c [Oberhumer] - Add cast in trees.c t avoid a warning [Oberhumer] - Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] - Update make_vms.com [Zinser] - Initialize state->write in inflateReset() since copied in inflate_fast() - Be more strict on incomplete code sets in inflate_table() and increase ENOUGH and MAXD -- this repairs a possible security vulnerability for invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for discovering the vulnerability and providing test cases. - Add ia64 support to configure for HP-UX [Smith] - Add error return to gzread() for format or i/o error [Levin] - Use malloc.h for OS/2 [Necasek] Changes in 1.2.2.3 (27 May 2005) - Replace 1U constants in inflate.c and inftrees.c for 64-bit compile - Typecast fread() return values in gzio.c [Vollant] - Remove trailing space in minigzip.c outmode (VC++ can't deal with it) - Fix crc check bug in gzread() after gzungetc() [Heiner] - Add the deflateTune() function to adjust internal compression parameters - Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) - Remove an incorrect assertion in examples/zpipe.c - Add C++ wrapper in infback9.h [Donais] - Fix bug in inflateCopy() when decoding fixed codes - Note in zlib.h how much deflateSetDictionary() actually uses - Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) - Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] - Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] - Add gzdirect() function to indicate transparent reads - Update contrib/minizip [Vollant] - Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] - Add casts in crc32.c to avoid warnings [Oberhumer] - Add contrib/masmx64 [Vollant] - Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] Changes in 1.2.2.2 (30 December 2004) - Replace structure assignments in deflate.c and inflate.c with zmemcpy to avoid implicit memcpy calls (portability for no-library compilation) - Increase sprintf() buffer size in gzdopen() to allow for large numbers - Add INFLATE_STRICT to check distances against zlib header - Improve WinCE errno handling and comments [Chang] - Remove comment about no gzip header processing in FAQ - Add Z_FIXED strategy option to deflateInit2() to force fixed trees - Add updated make_vms.com [Coghlan], update README - Create a new "examples" directory, move gzappend.c there, add zpipe.c, fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. - Add FAQ entry and comments in deflate.c on uninitialized memory access - Add Solaris 9 make options in configure [Gilbert] - Allow strerror() usage in gzio.c for STDC - Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] - Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] - Use z_off_t for adler32_combine() and crc32_combine() lengths - Make adler32() much faster for small len - Use OS_CODE in deflate() default gzip header Changes in 1.2.2.1 (31 October 2004) - Allow inflateSetDictionary() call for raw inflate - Fix inflate header crc check bug for file names and comments - Add deflateSetHeader() and gz_header structure for custom gzip headers - Add inflateGetheader() to retrieve gzip headers - Add crc32_combine() and adler32_combine() functions - Add alloc_func, free_func, in_func, out_func to Z_PREFIX list - Use zstreamp consistently in zlib.h (inflate_back functions) - Remove GUNZIP condition from definition of inflate_mode in inflate.h and in contrib/inflate86/inffast.S [Truta, Anderson] - Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] - Update projects/README.projects and projects/visualc6 [Truta] - Update win32/DLL_FAQ.txt [Truta] - Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] - Deprecate Z_ASCII; use Z_TEXT instead [Truta] - Use a new algorithm for setting strm->data_type in trees.c [Truta] - Do not define an exit() prototype in zutil.c unless DEBUG defined - Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] - Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() - Fix Darwin build version identification [Peterson] Changes in 1.2.2 (3 October 2004) - Update zlib.h comments on gzip in-memory processing - Set adler to 1 in inflateReset() to support Java test suite [Walles] - Add contrib/dotzlib [Ravn] - Update win32/DLL_FAQ.txt [Truta] - Update contrib/minizip [Vollant] - Move contrib/visual-basic.txt to old/ [Truta] - Fix assembler builds in projects/visualc6/ [Truta] Changes in 1.2.1.2 (9 September 2004) - Update INDEX file - Fix trees.c to update strm->data_type (no one ever noticed!) - Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] - Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) - Add limited multitasking protection to DYNAMIC_CRC_TABLE - Add NO_vsnprintf for VMS in zutil.h [Mozilla] - Don't declare strerror() under VMS [Mozilla] - Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize - Update contrib/ada [Anisimkov] - Update contrib/minizip [Vollant] - Fix configure to not hardcode directories for Darwin [Peterson] - Fix gzio.c to not return error on empty files [Brown] - Fix indentation; update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas [Truta] - Update mkasm.bat in contrib/masmx86 [Truta] - Update contrib/untgz [Truta] - Add projects/README.projects [Truta] - Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] - Update win32/DLL_FAQ.txt [Truta] - Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] - Remove an unnecessary assignment to curr in inftrees.c [Truta] - Add OS/2 to exe builds in configure [Poltorak] - Remove err dummy parameter in zlib.h [Kientzle] Changes in 1.2.1.1 (9 January 2004) - Update email address in README - Several FAQ updates - Fix a big fat bug in inftrees.c that prevented decoding valid dynamic blocks with only literals and no distance codes -- Thanks to "Hot Emu" for the bug report and sample file - Add a note to puff.c on no distance codes case. Changes in 1.2.1 (17 November 2003) - Remove a tab in contrib/gzappend/gzappend.c - Update some interfaces in contrib for new zlib functions - Update zlib version number in some contrib entries - Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] - Support shared libraries on Hurd and KFreeBSD [Brown] - Fix error in NO_DIVIDE option of adler32.c Changes in 1.2.0.8 (4 November 2003) - Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas - Add experimental NO_DIVIDE #define in adler32.c - Possibly faster on some processors (let me know if it is) - Correct Z_BLOCK to not return on first inflate call if no wrap - Fix strm->data_type on inflate() return to correctly indicate EOB - Add deflatePrime() function for appending in the middle of a byte - Add contrib/gzappend for an example of appending to a stream - Update win32/DLL_FAQ.txt [Truta] - Delete Turbo C comment in README [Truta] - Improve some indentation in zconf.h [Truta] - Fix infinite loop on bad input in configure script [Church] - Fix gzeof() for concatenated gzip files [Johnson] - Add example to contrib/visual-basic.txt [Michael B.] - Add -p to mkdir's in Makefile.in [vda] - Fix configure to properly detect presence or lack of printf functions - Add AS400 support [Monnerat] - Add a little Cygwin support [Wilson] Changes in 1.2.0.7 (21 September 2003) - Correct some debug formats in contrib/infback9 - Cast a type in a debug statement in trees.c - Change search and replace delimiter in configure from % to # [Beebe] - Update contrib/untgz to 0.2 with various fixes [Truta] - Add build support for Amiga [Nikl] - Remove some directories in old that have been updated to 1.2 - Add dylib building for Mac OS X in configure and Makefile.in - Remove old distribution stuff from Makefile - Update README to point to DLL_FAQ.txt, and add comment on Mac OS X - Update links in README Changes in 1.2.0.6 (13 September 2003) - Minor FAQ updates - Update contrib/minizip to 1.00 [Vollant] - Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] - Update POSTINC comment for 68060 [Nikl] - Add contrib/infback9 with deflate64 decoding (unsupported) - For MVS define NO_vsnprintf and undefine FAR [van Burik] - Add pragma for fdopen on MVS [van Burik] Changes in 1.2.0.5 (8 September 2003) - Add OF to inflateBackEnd() declaration in zlib.h - Remember start when using gzdopen in the middle of a file - Use internal off_t counters in gz* functions to properly handle seeks - Perform more rigorous check for distance-too-far in inffast.c - Add Z_BLOCK flush option to return from inflate at block boundary - Set strm->data_type on return from inflate - Indicate bits unused, if at block boundary, and if in last block - Replace size_t with ptrdiff_t in crc32.c, and check for correct size - Add condition so old NO_DEFLATE define still works for compatibility - FAQ update regarding the Windows DLL [Truta] - INDEX update: add qnx entry, remove aix entry [Truta] - Install zlib.3 into mandir [Wilson] - Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] - Adapt the zlib interface to the new DLL convention guidelines [Truta] - Introduce ZLIB_WINAPI macro to allow the export of functions using the WINAPI calling convention, for Visual Basic [Vollant, Truta] - Update msdos and win32 scripts and makefiles [Truta] - Export symbols by name, not by ordinal, in win32/zlib.def [Truta] - Add contrib/ada [Anisimkov] - Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] - Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] - Add contrib/masm686 [Truta] - Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm [Truta, Vollant] - Update contrib/delphi; rename to contrib/pascal; add example [Truta] - Remove contrib/delphi2; add a new contrib/delphi [Truta] - Avoid inclusion of the nonstandard in contrib/iostream, and fix some method prototypes [Truta] - Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip [Truta] - Avoid the use of backslash (\) in contrib/minizip [Vollant] - Fix file time handling in contrib/untgz; update makefiles [Truta] - Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines [Vollant] - Remove contrib/vstudio/vc15_16 [Vollant] - Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] - Update README.contrib [Truta] - Invert the assignment order of match_head and s->prev[...] in INSERT_STRING [Truta] - Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings [Truta] - Compare function pointers with 0, not with NULL or Z_NULL [Truta] - Fix prototype of syncsearch in inflate.c [Truta] - Introduce ASMINF macro to be enabled when using an ASM implementation of inflate_fast [Truta] - Change NO_DEFLATE to NO_GZCOMPRESS [Truta] - Modify test_gzio in example.c to take a single file name as a parameter [Truta] - Exit the example.c program if gzopen fails [Truta] - Add type casts around strlen in example.c [Truta] - Remove casting to sizeof in minigzip.c; give a proper type to the variable compared with SUFFIX_LEN [Truta] - Update definitions of STDC and STDC99 in zconf.h [Truta] - Synchronize zconf.h with the new Windows DLL interface [Truta] - Use SYS16BIT instead of __32BIT__ to distinguish between 16- and 32-bit platforms [Truta] - Use far memory allocators in small 16-bit memory models for Turbo C [Truta] - Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in zlibCompileFlags [Truta] - Cygwin has vsnprintf [Wilson] - In Windows16, OS_CODE is 0, as in MSDOS [Truta] - In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] Changes in 1.2.0.4 (10 August 2003) - Minor FAQ updates - Be more strict when checking inflateInit2's windowBits parameter - Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well - Add gzip wrapper option to deflateInit2 using windowBits - Add updated QNX rule in configure and qnx directory [Bonnefoy] - Make inflate distance-too-far checks more rigorous - Clean up FAR usage in inflate - Add casting to sizeof() in gzio.c and minigzip.c Changes in 1.2.0.3 (19 July 2003) - Fix silly error in gzungetc() implementation [Vollant] - Update contrib/minizip and contrib/vstudio [Vollant] - Fix printf format in example.c - Correct cdecl support in zconf.in.h [Anisimkov] - Minor FAQ updates Changes in 1.2.0.2 (13 July 2003) - Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons - Attempt to avoid warnings in crc32.c for pointer-int conversion - Add AIX to configure, remove aix directory [Bakker] - Add some casts to minigzip.c - Improve checking after insecure sprintf() or vsprintf() calls - Remove #elif's from crc32.c - Change leave label to inf_leave in inflate.c and infback.c to avoid library conflicts - Remove inflate gzip decoding by default--only enable gzip decoding by special request for stricter backward compatibility - Add zlibCompileFlags() function to return compilation information - More typecasting in deflate.c to avoid warnings - Remove leading underscore from _Capital #defines [Truta] - Fix configure to link shared library when testing - Add some Windows CE target adjustments [Mai] - Remove #define ZLIB_DLL in zconf.h [Vollant] - Add zlib.3 [Rodgers] - Update RFC URL in deflate.c and algorithm.txt [Mai] - Add zlib_dll_FAQ.txt to contrib [Truta] - Add UL to some constants [Truta] - Update minizip and vstudio [Vollant] - Remove vestigial NEED_DUMMY_RETURN from zconf.in.h - Expand use of NO_DUMMY_DECL to avoid all dummy structures - Added iostream3 to contrib [Schwardt] - Replace rewind() with fseek() for WinCE [Truta] - Improve setting of zlib format compression level flags - Report 0 for huffman and rle strategies and for level == 0 or 1 - Report 2 only for level == 6 - Only deal with 64K limit when necessary at compile time [Truta] - Allow TOO_FAR check to be turned off at compile time [Truta] - Add gzclearerr() function [Souza] - Add gzungetc() function Changes in 1.2.0.1 (17 March 2003) - Add Z_RLE strategy for run-length encoding [Truta] - When Z_RLE requested, restrict matches to distance one - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE - Correct FASTEST compilation to allow level == 0 - Clean up what gets compiled for FASTEST - Incorporate changes to zconf.in.h [Vollant] - Refine detection of Turbo C need for dummy returns - Refine ZLIB_DLL compilation - Include additional header file on VMS for off_t typedef - Try to use _vsnprintf where it supplants vsprintf [Vollant] - Add some casts in inffast.c - Enchance comments in zlib.h on what happens if gzprintf() tries to write more than 4095 bytes before compression - Remove unused state from inflateBackEnd() - Remove exit(0) from minigzip.c, example.c - Get rid of all those darn tabs - Add "check" target to Makefile.in that does the same thing as "test" - Add "mostlyclean" and "maintainer-clean" targets to Makefile.in - Update contrib/inflate86 [Anderson] - Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] - Add msdos and win32 directories with makefiles [Truta] - More additions and improvements to the FAQ Changes in 1.2.0 (9 March 2003) - New and improved inflate code - About 20% faster - Does not allocate 32K window unless and until needed - Automatically detects and decompresses gzip streams - Raw inflate no longer needs an extra dummy byte at end - Added inflateBack functions using a callback interface--even faster than inflate, useful for file utilities (gzip, zip) - Added inflateCopy() function to record state for random access on externally generated deflate streams (e.g. in gzip files) - More readable code (I hope) - New and improved crc32() - About 50% faster, thanks to suggestions from Rodney Brown - Add deflateBound() and compressBound() functions - Fix memory leak in deflateInit2() - Permit setting dictionary for raw deflate (for parallel deflate) - Fix const declaration for gzwrite() - Check for some malloc() failures in gzio.c - Fix bug in gzopen() on single-byte file 0x1f - Fix bug in gzread() on concatenated file with 0x1f at end of buffer and next buffer doesn't start with 0x8b - Fix uncompress() to return Z_DATA_ERROR on truncated input - Free memory at end of example.c - Remove MAX #define in trees.c (conflicted with some libraries) - Fix static const's in deflate.c, gzio.c, and zutil.[ch] - Declare malloc() and free() in gzio.c if STDC not defined - Use malloc() instead of calloc() in zutil.c if int big enough - Define STDC for AIX - Add aix/ with approach for compiling shared library on AIX - Add HP-UX support for shared libraries in configure - Add OpenUNIX support for shared libraries in configure - Use $cc instead of gcc to build shared library - Make prefix directory if needed when installing - Correct Macintosh avoidance of typedef Byte in zconf.h - Correct Turbo C memory allocation when under Linux - Use libz.a instead of -lz in Makefile (assure use of compiled library) - Update configure to check for snprintf or vsnprintf functions and their return value, warn during make if using an insecure function - Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that is lost when library is used--resolution is to build new zconf.h - Documentation improvements (in zlib.h): - Document raw deflate and inflate - Update RFCs URL - Point out that zlib and gzip formats are different - Note that Z_BUF_ERROR is not fatal - Document string limit for gzprintf() and possible buffer overflow - Note requirement on avail_out when flushing - Note permitted values of flush parameter of inflate() - Add some FAQs (and even answers) to the FAQ - Add contrib/inflate86/ for x86 faster inflate - Add contrib/blast/ for PKWare Data Compression Library decompression - Add contrib/puff/ simple inflate for deflate format description Changes in 1.1.4 (11 March 2002) - ZFREE was repeated on same allocation on some error conditions. This creates a security problem described in http://www.zlib.org/advisory-2002-03-11.txt - Returned incorrect error (Z_MEM_ERROR) on some invalid data - Avoid accesses before window for invalid distances with inflate window less than 32K. - force windowBits > 8 to avoid a bug in the encoder for a window size of 256 bytes. (A complete fix will be available in 1.1.5). Changes in 1.1.3 (9 July 1998) - fix "an inflate input buffer bug that shows up on rare but persistent occasions" (Mark) - fix gzread and gztell for concatenated .gz files (Didier Le Botlan) - fix gzseek(..., SEEK_SET) in write mode - fix crc check after a gzeek (Frank Faubert) - fix miniunzip when the last entry in a zip file is itself a zip file (J Lillge) - add contrib/asm586 and contrib/asm686 (Brian Raiter) See http://www.muppetlabs.com/~breadbox/software/assembly.html - add support for Delphi 3 in contrib/delphi (Bob Dellaca) - add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) - do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) - use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) - added a FAQ file - Support gzdopen on Mac with Metrowerks (Jason Linhart) - Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) - define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) - avoid some warnings with Borland C (Tom Tanner) - fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) - emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) - allow several arguments to configure (Tim Mooney, Frodo Looijaard) - use libdir and includedir in Makefile.in (Tim Mooney) - support shared libraries on OSF1 V4 (Tim Mooney) - remove so_locations in "make clean" (Tim Mooney) - fix maketree.c compilation error (Glenn, Mark) - Python interface to zlib now in Python 1.5 (Jeremy Hylton) - new Makefile.riscos (Rich Walker) - initialize static descriptors in trees.c for embedded targets (Nick Smith) - use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) - add the OS/2 files in Makefile.in too (Andrew Zabolotny) - fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) - fix maketree.c to allow clean compilation of inffixed.h (Mark) - fix parameter check in deflateCopy (Gunther Nikl) - cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) - Many portability patches by Christian Spieler: . zutil.c, zutil.h: added "const" for zmem* . Make_vms.com: fixed some typos . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists . msdos/Makefile.msc: remove "default rtl link library" info from obj files . msdos/Makefile.*: use model-dependent name for the built zlib library . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) - use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) - replace __far with _far for better portability (Christian Spieler, Tom Lane) - fix test for errno.h in configure (Tim Newsham) Changes in 1.1.2 (19 March 98) - added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) See http://www.winimage.com/zLibDll/unzip.html - preinitialize the inflate tables for fixed codes, to make the code completely thread safe (Mark) - some simplifications and slight speed-up to the inflate code (Mark) - fix gzeof on non-compressed files (Allan Schrum) - add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) - use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) - added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) - add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) - do not wrap extern "C" around system includes (Tom Lane) - mention zlib binding for TCL in README (Andreas Kupries) - added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) - allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) - allow "configure --prefix $HOME" (Tim Mooney) - remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) - move Makefile.sas to amiga/Makefile.sas Changes in 1.1.1 (27 Feb 98) - fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) - remove block truncation heuristic which had very marginal effect for zlib (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the compression ratio on some files. This also allows inlining _tr_tally for matches in deflate_slow. - added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) Changes in 1.1.0 (24 Feb 98) - do not return STREAM_END prematurely in inflate (John Bowler) - revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) - compile with -DFASTEST to get compression code optimized for speed only - in minigzip, try mmap'ing the input file first (Miguel Albrecht) - increase size of I/O buffers in minigzip.c and gzio.c (not a big gain on Sun but significant on HP) - add a pointer to experimental unzip library in README (Gilles Vollant) - initialize variable gcc in configure (Chris Herborth) Changes in 1.0.9 (17 Feb 1998) - added gzputs and gzgets functions - do not clear eof flag in gzseek (Mark Diekhans) - fix gzseek for files in transparent mode (Mark Diekhans) - do not assume that vsprintf returns the number of bytes written (Jens Krinke) - replace EXPORT with ZEXPORT to avoid conflict with other programs - added compress2 in zconf.h, zlib.def, zlib.dnt - new asm code from Gilles Vollant in contrib/asm386 - simplify the inflate code (Mark): . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() . ZALLOC the length list in inflate_trees_fixed() instead of using stack . ZALLOC the value area for huft_build() instead of using stack . Simplify Z_FINISH check in inflate() - Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 - in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) - in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with the declaration of FAR (Gilles VOllant) - install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) - read_buf buf parameter of type Bytef* instead of charf* - zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) - do not redeclare unlink in minigzip.c for WIN32 (John Bowler) - fix check for presence of directories in "make install" (Ian Willis) Changes in 1.0.8 (27 Jan 1998) - fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) - fix gzgetc and gzputc for big endian systems (Markus Oberhumer) - added compress2() to allow setting the compression level - include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) - use constant arrays for the static trees in trees.c instead of computing them at run time (thanks to Ken Raeburn for this suggestion). To create trees.h, compile with GEN_TREES_H and run "make test". - check return code of example in "make test" and display result - pass minigzip command line options to file_compress - simplifying code of inflateSync to avoid gcc 2.8 bug - support CC="gcc -Wall" in configure -s (QingLong) - avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) - fix test for shared library support to avoid compiler warnings - zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) - check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) - do not use fdopen for Metrowerks on Mac (Brad Pettit)) - add checks for gzputc and gzputc in example.c - avoid warnings in gzio.c and deflate.c (Andreas Kleinert) - use const for the CRC table (Ken Raeburn) - fixed "make uninstall" for shared libraries - use Tracev instead of Trace in infblock.c - in example.c use correct compressed length for test_sync - suppress +vnocompatwarnings in configure for HPUX (not always supported) Changes in 1.0.7 (20 Jan 1998) - fix gzseek which was broken in write mode - return error for gzseek to negative absolute position - fix configure for Linux (Chun-Chung Chen) - increase stack space for MSC (Tim Wegner) - get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) - define EXPORTVA for gzprintf (Gilles Vollant) - added man page zlib.3 (Rick Rodgers) - for contrib/untgz, fix makedir() and improve Makefile - check gzseek in write mode in example.c - allocate extra buffer for seeks only if gzseek is actually called - avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) - add inflateSyncPoint in zconf.h - fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def Changes in 1.0.6 (19 Jan 1998) - add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) - Fix a deflate bug occurring only with compression level 0 (thanks to Andy Buckler for finding this one). - In minigzip, pass transparently also the first byte for .Z files. - return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() - check Z_FINISH in inflate (thanks to Marc Schluper) - Implement deflateCopy (thanks to Adam Costello) - make static libraries by default in configure, add --shared option. - move MSDOS or Windows specific files to directory msdos - suppress the notion of partial flush to simplify the interface (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) - suppress history buffer provided by application to simplify the interface (this feature was not implemented anyway in 1.0.4) - next_in and avail_in must be initialized before calling inflateInit or inflateInit2 - add EXPORT in all exported functions (for Windows DLL) - added Makefile.nt (thanks to Stephen Williams) - added the unsupported "contrib" directory: contrib/asm386/ by Gilles Vollant 386 asm code replacing longest_match(). contrib/iostream/ by Kevin Ruland A C++ I/O streams interface to the zlib gz* functions contrib/iostream2/ by Tyge Løvset Another C++ I/O streams interface contrib/untgz/ by "Pedro A. Aranda Guti\irrez" A very simple tar.gz file extractor using zlib contrib/visual-basic.txt by Carlos Rios How to use compress(), uncompress() and the gz* functions from VB. - pass params -f (filtered data), -h (huffman only), -1 to -9 (compression level) in minigzip (thanks to Tom Lane) - use const for rommable constants in deflate - added test for gzseek and gztell in example.c - add undocumented function inflateSyncPoint() (hack for Paul Mackerras) - add undocumented function zError to convert error code to string (for Tim Smithers) - Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. - Use default memcpy for Symantec MSDOS compiler. - Add EXPORT keyword for check_func (needed for Windows DLL) - add current directory to LD_LIBRARY_PATH for "make test" - create also a link for libz.so.1 - added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) - use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) - added -soname for Linux in configure (Chun-Chung Chen, - assign numbers to the exported functions in zlib.def (for Windows DLL) - add advice in zlib.h for best usage of deflateSetDictionary - work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) - allow compilation with ANSI keywords only enabled for TurboC in large model - avoid "versionString"[0] (Borland bug) - add NEED_DUMMY_RETURN for Borland - use variable z_verbose for tracing in debug mode (L. Peter Deutsch). - allow compilation with CC - defined STDC for OS/2 (David Charlap) - limit external names to 8 chars for MVS (Thomas Lund) - in minigzip.c, use static buffers only for 16-bit systems - fix suffix check for "minigzip -d foo.gz" - do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) - use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) - added makelcc.bat for lcc-win32 (Tom St Denis) - in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) - Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. - check for unistd.h in configure (for off_t) - remove useless check parameter in inflate_blocks_free - avoid useless assignment of s->check to itself in inflate_blocks_new - do not flush twice in gzclose (thanks to Ken Raeburn) - rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h - use NO_ERRNO_H instead of enumeration of operating systems with errno.h - work around buggy fclose on pipes for HP/UX - support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) - fix configure if CC is already equal to gcc Changes in 1.0.5 (3 Jan 98) - Fix inflate to terminate gracefully when fed corrupted or invalid data - Use const for rommable constants in inflate - Eliminate memory leaks on error conditions in inflate - Removed some vestigial code in inflate - Update web address in README Changes in 1.0.4 (24 Jul 96) - In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF bit, so the decompressor could decompress all the correct data but went on to attempt decompressing extra garbage data. This affected minigzip too. - zlibVersion and gzerror return const char* (needed for DLL) - port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) - use z_error only for DEBUG (avoid problem with DLLs) Changes in 1.0.3 (2 Jul 96) - use z_streamp instead of z_stream *, which is now a far pointer in MSDOS small and medium models; this makes the library incompatible with previous versions for these models. (No effect in large model or on other systems.) - return OK instead of BUF_ERROR if previous deflate call returned with avail_out as zero but there is nothing to do - added memcmp for non STDC compilers - define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) - define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) - better check for 16-bit mode MSC (avoids problem with Symantec) Changes in 1.0.2 (23 May 96) - added Windows DLL support - added a function zlibVersion (for the DLL support) - fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) - Bytef is define's instead of typedef'd only for Borland C - avoid reading uninitialized memory in example.c - mention in README that the zlib format is now RFC1950 - updated Makefile.dj2 - added algorithm.doc Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] - fix array overlay in deflate.c which sometimes caused bad compressed data - fix inflate bug with empty stored block - fix MSDOS medium model which was broken in 0.99 - fix deflateParams() which could generated bad compressed data. - Bytef is define'd instead of typedef'ed (work around Borland bug) - added an INDEX file - new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) - speed up adler32 for modern machines without auto-increment - added -ansi for IRIX in configure - static_init_done in trees.c is an int - define unlink as delete for VMS - fix configure for QNX - add configure branch for SCO and HPUX - avoid many warnings (unused variables, dead assignments, etc...) - no fdopen for BeOS - fix the Watcom fix for 32 bit mode (define FAR as empty) - removed redefinition of Byte for MKWERKS - work around an MWKERKS bug (incorrect merge of all .h files) Changes in 0.99 (27 Jan 96) - allow preset dictionary shared between compressor and decompressor - allow compression level 0 (no compression) - add deflateParams in zlib.h: allow dynamic change of compression level and compression strategy. - test large buffers and deflateParams in example.c - add optional "configure" to build zlib as a shared library - suppress Makefile.qnx, use configure instead - fixed deflate for 64-bit systems (detected on Cray) - fixed inflate_blocks for 64-bit systems (detected on Alpha) - declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) - always return Z_BUF_ERROR when deflate() has nothing to do - deflateInit and inflateInit are now macros to allow version checking - prefix all global functions and types with z_ with -DZ_PREFIX - make falloc completely reentrant (inftrees.c) - fixed very unlikely race condition in ct_static_init - free in reverse order of allocation to help memory manager - use zlib-1.0/* instead of zlib/* inside the tar.gz - make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion -Wstrict-prototypes -Wmissing-prototypes" - allow gzread on concatenated .gz files - deflateEnd now returns Z_DATA_ERROR if it was premature - deflate is finally (?) fully deterministic (no matches beyond end of input) - Document Z_SYNC_FLUSH - add uninstall in Makefile - Check for __cpluplus in zlib.h - Better test in ct_align for partial flush - avoid harmless warnings for Borland C++ - initialize hash_head in deflate.c - avoid warning on fdopen (gzio.c) for HP cc -Aa - include stdlib.h for STDC compilers - include errno.h for Cray - ignore error if ranlib doesn't exist - call ranlib twice for NeXTSTEP - use exec_prefix instead of prefix for libz.a - renamed ct_* as _tr_* to avoid conflict with applications - clear z->msg in inflateInit2 before any error return - initialize opaque in example.c, gzio.c, deflate.c and inflate.c - fixed typo in zconf.h (_GNUC__ => __GNUC__) - check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) - fix typo in Make_vms.com (f$trnlnm -> f$getsyi) - in fcalloc, normalize pointer if size > 65520 bytes - don't use special fcalloc for 32 bit Borland C++ - use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... - use Z_BINARY instead of BINARY - document that gzclose after gzdopen will close the file - allow "a" as mode in gzopen. - fix error checking in gzread - allow skipping .gz extra-field on pipes - added reference to Perl interface in README - put the crc table in FAR data (I dislike more and more the medium model :) - added get_crc_table - added a dimension to all arrays (Borland C can't count). - workaround Borland C bug in declaration of inflate_codes_new & inflate_fast - guard against multiple inclusion of *.h (for precompiled header on Mac) - Watcom C pretends to be Microsoft C small model even in 32 bit mode. - don't use unsized arrays to avoid silly warnings by Visual C++: warning C4746: 'inflate_mask' : unsized array treated as '__far' (what's wrong with far data in far model?). - define enum out of inflate_blocks_state to allow compilation with C++ Changes in 0.95 (16 Aug 95) - fix MSDOS small and medium model (now easier to adapt to any compiler) - inlined send_bits - fix the final (:-) bug for deflate with flush (output was correct but not completely flushed in rare occasions). - default window size is same for compression and decompression (it's now sufficient to set MAX_WBITS in zconf.h). - voidp -> voidpf and voidnp -> voidp (for consistency with other typedefs and because voidnp was not near in large model). Changes in 0.94 (13 Aug 95) - support MSDOS medium model - fix deflate with flush (could sometimes generate bad output) - fix deflateReset (zlib header was incorrectly suppressed) - added support for VMS - allow a compression level in gzopen() - gzflush now calls fflush - For deflate with flush, flush even if no more input is provided. - rename libgz.a as libz.a - avoid complex expression in infcodes.c triggering Turbo C bug - work around a problem with gcc on Alpha (in INSERT_STRING) - don't use inline functions (problem with some gcc versions) - allow renaming of Byte, uInt, etc... with #define. - avoid warning about (unused) pointer before start of array in deflate.c - avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c - avoid reserved word 'new' in trees.c Changes in 0.93 (25 June 95) - temporarily disable inline functions - make deflate deterministic - give enough lookahead for PARTIAL_FLUSH - Set binary mode for stdin/stdout in minigzip.c for OS/2 - don't even use signed char in inflate (not portable enough) - fix inflate memory leak for segmented architectures Changes in 0.92 (3 May 95) - don't assume that char is signed (problem on SGI) - Clear bit buffer when starting a stored block - no memcpy on Pyramid - suppressed inftest.c - optimized fill_window, put longest_match inline for gcc - optimized inflate on stored blocks. - untabify all sources to simplify patches Changes in 0.91 (2 May 95) - Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h - Document the memory requirements in zconf.h - added "make install" - fix sync search logic in inflateSync - deflate(Z_FULL_FLUSH) now works even if output buffer too short - after inflateSync, don't scare people with just "lo world" - added support for DJGPP Changes in 0.9 (1 May 95) - don't assume that zalloc clears the allocated memory (the TurboC bug was Mark's bug after all :) - let again gzread copy uncompressed data unchanged (was working in 0.71) - deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented - added a test of inflateSync in example.c - moved MAX_WBITS to zconf.h because users might want to change that. - document explicitly that zalloc(64K) on MSDOS must return a normalized pointer (zero offset) - added Makefiles for Microsoft C, Turbo C, Borland C++ - faster crc32() Changes in 0.8 (29 April 95) - added fast inflate (inffast.c) - deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this is incompatible with previous versions of zlib which returned Z_OK. - work around a TurboC compiler bug (bad code for b << 0, see infutil.h) (actually that was not a compiler bug, see 0.81 above) - gzread no longer reads one extra byte in certain cases - In gzio destroy(), don't reference a freed structure - avoid many warnings for MSDOS - avoid the ERROR symbol which is used by MS Windows Changes in 0.71 (14 April 95) - Fixed more MSDOS compilation problems :( There is still a bug with TurboC large model. Changes in 0.7 (14 April 95) - Added full inflate support. - Simplified the crc32() interface. The pre- and post-conditioning (one's complement) is now done inside crc32(). WARNING: this is incompatible with previous versions; see zlib.h for the new usage. Changes in 0.61 (12 April 95) - workaround for a bug in TurboC. example and minigzip now work on MSDOS. Changes in 0.6 (11 April 95) - added minigzip.c - added gzdopen to reopen a file descriptor as gzFile - added transparent reading of non-gziped files in gzread. - fixed bug in gzread (don't read crc as data) - fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). - don't allocate big arrays in the stack (for MSDOS) - fix some MSDOS compilation problems Changes in 0.5: - do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but not yet Z_FULL_FLUSH. - support decompression but only in a single step (forced Z_FINISH) - added opaque object for zalloc and zfree. - added deflateReset and inflateReset - added a variable zlib_version for consistency checking. - renamed the 'filter' parameter of deflateInit2 as 'strategy'. Added Z_FILTERED and Z_HUFFMAN_ONLY constants. Changes in 0.4: - avoid "zip" everywhere, use zlib instead of ziplib. - suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush if compression method == 8. - added adler32 and crc32 - renamed deflateOptions as deflateInit2, call one or the other but not both - added the method parameter for deflateInit2. - added inflateInit2 - simplied considerably deflateInit and inflateInit by not supporting user-provided history buffer. This is supported only in deflateInit2 and inflateInit2. Changes in 0.3: - prefix all macro names with Z_ - use Z_FINISH instead of deflateEnd to finish compression. - added Z_HUFFMAN_ONLY - added gzerror() tcl8.6.5/compat/zlib/qnx/0000755000175000017500000000000012665173607014623 5ustar sergeisergeitcl8.6.5/compat/zlib/qnx/package.qpg0000644000175000017500000001443312663660065016731 0ustar sergeisergei Library Medium 2.0 zlib zlib alain.bonnefoy@icbt.com Public public www.gzip.org/zlib Jean-Loup Gailly,Mark Adler www.gzip.org/zlib zlib@gzip.org A massively spiffy yet delicately unobtrusive compression library. zlib is designed to be a free, general-purpose, legally unencumbered, lossless data compression library for use on virtually any computer hardware and operating system. http://www.gzip.org/zlib 1.2.8 Medium Stable No License Software Development/Libraries and Extensions/C Libraries zlib,compression qnx6 qnx6 None Developer Install Post No Ignore No Optional InstallOver zlib InstallOver zlib-dev tcl8.6.5/compat/zlib/nintendods/0000755000175000017500000000000012665173607016162 5ustar sergeisergeitcl8.6.5/compat/zlib/nintendods/Makefile0000644000175000017500000001120512663653206017615 0ustar sergeisergei#--------------------------------------------------------------------------------- .SUFFIXES: #--------------------------------------------------------------------------------- ifeq ($(strip $(DEVKITARM)),) $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") endif include $(DEVKITARM)/ds_rules #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed # SOURCES is a list of directories containing source code # DATA is a list of directories containing data files # INCLUDES is a list of directories containing header files #--------------------------------------------------------------------------------- TARGET := $(shell basename $(CURDIR)) BUILD := build SOURCES := ../../ DATA := data INCLUDES := include #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- ARCH := -mthumb -mthumb-interwork CFLAGS := -Wall -O2\ -march=armv5te -mtune=arm946e-s \ -fomit-frame-pointer -ffast-math \ $(ARCH) CFLAGS += $(INCLUDE) -DARM9 CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions ASFLAGS := $(ARCH) -march=armv5te -mtune=arm946e-s LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing # include and lib #--------------------------------------------------------------------------------- LIBDIRS := $(LIBNDS) #--------------------------------------------------------------------------------- # no real need to edit anything past this point unless you need to add additional # rules for different file extensions #--------------------------------------------------------------------------------- ifneq ($(BUILD),$(notdir $(CURDIR))) #--------------------------------------------------------------------------------- export OUTPUT := $(CURDIR)/lib/libz.a export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) export DEPSDIR := $(CURDIR)/$(BUILD) CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C #--------------------------------------------------------------------------------- ifeq ($(strip $(CPPFILES)),) #--------------------------------------------------------------------------------- export LD := $(CC) #--------------------------------------------------------------------------------- else #--------------------------------------------------------------------------------- export LD := $(CXX) #--------------------------------------------------------------------------------- endif #--------------------------------------------------------------------------------- export OFILES := $(addsuffix .o,$(BINFILES)) \ $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ -I$(CURDIR)/$(BUILD) .PHONY: $(BUILD) clean all #--------------------------------------------------------------------------------- all: $(BUILD) @[ -d $@ ] || mkdir -p include @cp ../../*.h include lib: @[ -d $@ ] || mkdir -p $@ $(BUILD): lib @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile #--------------------------------------------------------------------------------- clean: @echo clean ... @rm -fr $(BUILD) lib #--------------------------------------------------------------------------------- else DEPENDS := $(OFILES:.o=.d) #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- $(OUTPUT) : $(OFILES) #--------------------------------------------------------------------------------- %.bin.o : %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(bin2o) -include $(DEPENDS) #--------------------------------------------------------------------------------------- endif #--------------------------------------------------------------------------------------- tcl8.6.5/compat/zlib/nintendods/README0000644000175000017500000000032112663653206017032 0ustar sergeisergeiThis Makefile requires devkitARM (http://www.devkitpro.org/category/devkitarm/) and works inside "contrib/nds". It is based on a devkitARM template. Eduardo Costa January 3, 2009 tcl8.6.5/compat/zlib/amiga/0000755000175000017500000000000012665173607015073 5ustar sergeisergeitcl8.6.5/compat/zlib/amiga/Makefile.pup0000644000175000017500000000367512663653206017345 0ustar sergeisergei# Amiga powerUP (TM) Makefile # makefile for libpng and SAS C V6.58/7.00 PPC compiler # Copyright (C) 1998 by Andreas R. Kleinert LIBNAME = libzip.a CC = scppc CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \ OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 NOVER AR = ppc-amigaos-ar cr RANLIB = ppc-amigaos-ranlib LD = ppc-amigaos-ld -r LDFLAGS = -o LDLIBS = LIB:scppc.a LIB:end.o RM = delete quiet OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o TEST_OBJS = example.o minigzip.o all: example minigzip check: test test: all example echo hello world | minigzip | minigzip -d $(LIBNAME): $(OBJS) $(AR) $@ $(OBJS) -$(RANLIB) $@ example: example.o $(LIBNAME) $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS) minigzip: minigzip.o $(LIBNAME) $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS) mostlyclean: clean clean: $(RM) *.o example minigzip $(LIBNAME) foo.gz zip: zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \ descrip.mms *.[ch] tgz: cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \ zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch] # DO NOT DELETE THIS LINE -- make depend depends on it. adler32.o: zlib.h zconf.h compress.o: zlib.h zconf.h crc32.o: crc32.h zlib.h zconf.h deflate.o: deflate.h zutil.h zlib.h zconf.h example.o: zlib.h zconf.h gzclose.o: zlib.h zconf.h gzguts.h gzlib.o: zlib.h zconf.h gzguts.h gzread.o: zlib.h zconf.h gzguts.h gzwrite.o: zlib.h zconf.h gzguts.h inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inftrees.o: zutil.h zlib.h zconf.h inftrees.h minigzip.o: zlib.h zconf.h trees.o: deflate.h zutil.h zlib.h zconf.h trees.h uncompr.o: zlib.h zconf.h zutil.o: zutil.h zlib.h zconf.h tcl8.6.5/compat/zlib/amiga/Makefile.sas0000644000175000017500000000346712663653206017326 0ustar sergeisergei# SMakefile for zlib # Modified from the standard UNIX Makefile Copyright Jean-loup Gailly # Osma Ahvenlampi # Amiga, SAS/C 6.56 & Smake CC=sc CFLAGS=OPT #CFLAGS=OPT CPU=68030 #CFLAGS=DEBUG=LINE LDFLAGS=LIB z.lib SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \ NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \ DEF=POSTINC OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o TEST_OBJS = example.o minigzip.o all: SCOPTIONS example minigzip check: test test: all example echo hello world | minigzip | minigzip -d install: z.lib copy clone zlib.h zconf.h INCLUDE: copy clone z.lib LIB: z.lib: $(OBJS) oml z.lib r $(OBJS) example: example.o z.lib $(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS) minigzip: minigzip.o z.lib $(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS) mostlyclean: clean clean: -delete force quiet example minigzip *.o z.lib foo.gz *.lnk SCOPTIONS SCOPTIONS: Makefile.sas copy to $@ (gzip) or (zlib) or (raw) (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> HCRC -> TYPE (zlib) -> DICTID or TYPE DICTID -> DICT -> TYPE (raw) -> TYPEDO Read deflate blocks: TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK STORED -> COPY_ -> COPY -> TYPE TABLE -> LENLENS -> CODELENS -> LEN_ LEN_ -> LEN Read deflate codes in fixed or dynamic block: LEN -> LENEXT or LIT or TYPE LENEXT -> DIST -> DISTEXT -> MATCH -> LEN LIT -> LEN Process trailer: CHECK -> LENGTH -> DONE */ /* state maintained between inflate() calls. Approximately 10K bytes. */ struct inflate_state { inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags (0 if zlib) */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned long check; /* protected copy of check value */ unsigned long total; /* protected copy of output count */ gz_headerp head; /* where to save gzip header information */ /* sliding window */ unsigned wbits; /* log base 2 of requested window size */ unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if needed */ /* bit accumulator */ unsigned long hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ /* for string and stored block copying */ unsigned length; /* literal or length of data to copy */ unsigned offset; /* distance back to copy string from */ /* for table and code decoding */ unsigned extra; /* extra bits needed */ /* fixed and dynamic code tables */ code const FAR *lencode; /* starting table for length/literal codes */ code const FAR *distcode; /* starting table for distance codes */ unsigned lenbits; /* index bits for lencode */ unsigned distbits; /* index bits for distcode */ /* dynamic table building */ unsigned ncode; /* number of code length code lengths */ unsigned nlen; /* number of length code lengths */ unsigned ndist; /* number of distance code lengths */ unsigned have; /* number of code lengths in lens[] */ code FAR *next; /* next available space in codes[] */ unsigned short lens[320]; /* temporary storage for code lengths */ unsigned short work[288]; /* work area for code table building */ code codes[ENOUGH]; /* space for code tables */ int sane; /* if false, allow invalid distance too far */ int back; /* bits back of last unprocessed length/lit */ unsigned was; /* initial length of match */ }; tcl8.6.5/compat/zlib/compress.c0000644000175000017500000000474112663660064016016 0ustar sergeisergei/* compress.c -- compress a memory buffer * Copyright (C) 1995-2005 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #define ZLIB_INTERNAL #include "zlib.h" /* =========================================================================== Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least 0.1% larger than sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) Bytef *dest; uLongf *destLen; const Bytef *source; uLong sourceLen; int level; { z_stream stream; int err; stream.next_in = (z_const Bytef *)source; stream.avail_in = (uInt)sourceLen; #ifdef MAXSEG_64K /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; #endif stream.next_out = dest; stream.avail_out = (uInt)*destLen; if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; stream.opaque = (voidpf)0; err = deflateInit(&stream, level); if (err != Z_OK) return err; err = deflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { deflateEnd(&stream); return err == Z_OK ? Z_BUF_ERROR : err; } *destLen = stream.total_out; err = deflateEnd(&stream); return err; } /* =========================================================================== */ int ZEXPORT compress (dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; uLong sourceLen; { return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); } /* =========================================================================== If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ uLong ZEXPORT compressBound (sourceLen) uLong sourceLen; { return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13; } tcl8.6.5/compat/zlib/INDEX0000644000175000017500000000370412663660064014607 0ustar sergeisergeiCMakeLists.txt cmake build file ChangeLog history of changes FAQ Frequently Asked Questions about zlib INDEX this file Makefile dummy Makefile that tells you to ./configure Makefile.in template for Unix Makefile README guess what configure configure script for Unix make_vms.com makefile for VMS test/example.c zlib usages examples for build testing test/minigzip.c minimal gzip-like functionality for build testing test/infcover.c inf*.c code coverage for build coverage testing treebuild.xml XML description of source file dependencies zconf.h.cmakein zconf.h template for cmake zconf.h.in zconf.h template for configure zlib.3 Man page for zlib zlib.3.pdf Man page in PDF format zlib.map Linux symbol information zlib.pc.in Template for pkg-config descriptor zlib.pc.cmakein zlib.pc template for cmake zlib2ansi perl script to convert source files for C++ compilation amiga/ makefiles for Amiga SAS C as400/ makefiles for AS/400 doc/ documentation for formats and algorithms msdos/ makefiles for MSDOS nintendods/ makefile for Nintendo DS old/ makefiles for various architectures and zlib documentation files that have not yet been updated for zlib 1.2.x qnx/ makefiles for QNX watcom/ makefiles for OpenWatcom win32/ makefiles for Windows zlib public header files (required for library use): zconf.h zlib.h private source files used to build the zlib library: adler32.c compress.c crc32.c crc32.h deflate.c deflate.h gzclose.c gzguts.h gzlib.c gzread.c gzwrite.c infback.c inffast.c inffast.h inffixed.h inflate.c inflate.h inftrees.c inftrees.h trees.c trees.h uncompr.c zutil.c zutil.h source files for sample programs See examples/README.examples unsupported contributions by third parties See contrib/README.contrib tcl8.6.5/compat/zlib/win64/0000755000175000017500000000000012665173607014764 5ustar sergeisergeitcl8.6.5/compat/zlib/win64/zlib1.dll0000755000175000017500000033400012663660065016502 0ustar sergeisergeiMZÿÿ¸@€º´ Í!¸LÍ!This program cannot be run in DOS mode. $PEd† °íQð." Hl èb@ùÖ àÇðT „0h(`ò.textÀGH P`.data `L@`À.rdataJpLP@`@.bsspÀ€`À.edataÇàœ@0@.idataT ð ¤@0À.CRTX®@@À.tlsP°@`À.rsrc„ ²@0À.reloch0¶@0BS¹Hƒì èÁEH‰ÃH‰ÁèãH…ÛH‰ ÃH‰ øt HÇ0ÀHƒÄ [Ãffffff.„ATUWVL‰ÆSH‰ËHƒì …Òu}‹–¯1À…Ò~fƒê1À‰…¯ºðH±¿ÂH…Àt*H‹=sâ¾1Û@¹èÿ×H‰ØðH±5•ÂH…Àu苂ƒø„ ¹èE¸HƒÄ [^_]A\Ãú¸uëeH‹%0H‹h1ÀðH±-EÂ1ÿH…Àt9H9Å@·t1H‹=ïáE1äë fH9Å„(¹èÿ×L‰àðH±- ÂH…Àuß1ÿ‹÷Áƒø„+‹èÁ…ÀtT‹ÞÁƒø„ð…ÿu 1ÀðH‡ÏÁH‹ðOH…Àt I‰ðºH‰ÙÿЃg®HƒÄ ¸[^_]A\ÀHiîH RîÇxÁèDëH‹ YÁè4áH…ÀH‰ÃtIH‹ MÁè áH‰ÆHƒîH9ówH‹H…ÀtïHƒîÿÐH9óvíH‰ÙèÑCHÇÁHÇÁÇ Á1ÀðH‡ÁHƒÄ ¸[^_]A\ÿéèþÿÿH¦íH —íèrCÇÈÀéîþÿÿ¹èQCéÐþÿÿ@HƒìH…Ò‰ÄNH‰\$(H‰|$8‰ÓH‰l$@H‰t$0H‰ÏL‰Å…‚‹<­1ö…ÀtèAãI‰è1ÒH‰ùèÄõ‰Æƒût-…Ût)‰ðÇmNÿÿÿÿH‹\$(H‹t$0H‹|$8H‹l$@HƒÄHÃ@I‰è‰ÚH‰ùè“õI‰è‰ÚH‰ù‰Æè$ýÿÿ…À¸Dð믄èËâCÿƒøvSI‰è‰ÚH‰ùèFõ…À‰Æ…zÿÿÿƒû…qÿÿÿI‰è1ÒH‰ùè&õI‰è1ÒH‰ùè)õI‰è1ÒH‰ùè¼üÿÿéEÿÿÿ€I‰è‰ÚH‰ùè£üÿÿ…À‰Æ„0ÿÿÿI‰è‰ÚH‰ùèìô…À‰Æuƒû…ÿÿÿI‰è1ÒH‰ùèpüÿÿéÿÿÿƒûufDè æéSÿÿÿI‰èºH‰ùè–ô‰ÆéÍþÿÿffffff.„HƒìHƒúÇï«t HƒÄHéTþÿÿ@‰T$0H‰L$8L‰D$(èÝåèhéL‹D$(H‹L$8‹T$0HƒÄHé!þÿÿA‰ÊáÿÿSAÁêAƒøI‰Ñ„|H…ÒA»t]Aƒøw\E…Àt$HBAXÿHëHƒÀA¶I‰ÁÑAÊH9ØuëD™ÿÿùñÿD‰Ðºq€€DBÙ÷âÁêiÒñÿA)ÒAÁâE ÓD‰Ø[ÃAø¯A»q€€†=Aè°L‰Èº[fD¶Ù¶XFÙ¶XAÊÙ¶XAÊÙ¶XAÊÙ¶XAÊÙ¶XAÊÙ¶XAÊÙ¶XAÊÙ¶X AÊÙ¶X AÊÙ¶X AÊÙ¶X AÊÙ¶X AÊÙ¶XAÊÙ¶XHƒÀAÊÙAʃê…cÿÿÿ‰ÈIÁ°A÷ãD‰ÐÁêiÒñÿ)ÑA÷ãÁêiÒñÿA)ÒAø¯‡ÿÿÿE…ÀuFE‰ÓAÁãA ËD‰Ø[ö ÿÿùñÿCÈFEšÿÿAúñÿEBÚAÁãA ËéµþÿÿAƒø†ËAƒèE‰ÃAÁëE‰ÛL‰ØHÁàI\L‰È¶Ñ¶PF¶HAÒʶHAÒʶHAÒʶHAÒʶHAÒʶHAÒʶHAÒʶH AÒʶH AÒʶH AÒʶH AÒʶH AÒʶHAÒʶHHƒÀAÒ AÊH9Ø…aÿÿÿIÁãAƒàOL tAƒèE‰ÀKTA¶IƒÁÁAÊI9ÑuîA¸ñÿ‰È1ÒA÷ðD‰Ð‰Ñ1ÒA÷ðA‰Òé¨þÿÿE…ÀSA‰Ñ¸ÿÿÿÿˆ¬D‰À»q€€÷ëD‰ÀÁøFAÁúA)ÂEiÒñÿE)ÐE‰ÂD·ÁÁéE‰ÓE¯ØD‰Ø÷ãA·ÁAÁéE„ðÿBŒ ñÿÁêD)ÑiÒñÿA)ÓAøðÿD‰ÚtAèñÿAøðÿvAèñÿ‚þÿúâÿCЂÿÿúñÿBÂÁàD À[ÃE…ÀSA‰Ñ¸ÿÿÿÿˆ¬D‰À»q€€÷ëD‰ÀÁøFAÁúA)ÂEiÒñÿE)ÐE‰ÂD·ÁÁéE‰ÓE¯ØD‰Ø÷ãA·ÁAÁéE„ðÿBŒ ñÿÁêD)ÑiÒñÿA)ÓAøðÿD‰ÚtAèñÿAøðÿvAèñÿ‚þÿúâÿCЂÿÿúñÿBÂÁàD À[ÃHì˜H‰œ$€H‰´$ˆH\$ H‰¼$H‰Ö‹‹”$ÀL‰D$ LôVD‰L$(H‰L$0A¹XH‰Ù‰D$8HÇD$PHÇD$XHÇD$`èm;…À‰Çt'‰øH‹œ$€H‹´$ˆH‹¼$HĘÃDºH‰ÙèÃ#ƒø‰ÇtH‰Ùè7…ÿ¸ûÿÿÿDøë±„‹D$L ‡Së DöÂt+¶HƒÂ1ÈÁé¶ÀA3 Aƒèuâ‰È÷ÐHƒÄ[^_]ÃDAƒøH‰Ö†ÛEXàL 8SI‰ÐD‰ÛÁë‰ÛH‰ØHÁàLT A3¶ý‰Î¶ÁÁéA‹„ Áî‰É@¶öA3‰A3@A3„¹A3„±¶ô¶è‰ÁÁèÁé‰ÇA‹„© ¶ÉA3¹A3@A3„±A3„‰¶ô¶è‰ÁÁèÁé‰ÇA‹„© ¶ÉA3¹A3@ A3„±A3„‰¶ô¶è‰ÁÁèÁé‰ÇA‹„© ¶ÉA3¹A3@A3„±A3„‰¶ô¶è‰ÁÁèÁé‰ÇA‹„© ¶ÉA3¹A3@A3„±A3„‰¶ô¶è‰ÁÁèÁé‰ÇA‹„© ¶ÉA3¹A3@A3„±A3„‰¶ô‰Á¶èÁèÁé‰ÇA‹„© ¶ÉA3¹A3@IƒÀ A3„±A3„‰‰Á‰Æ¶øÁéÁî¶Ä‰É@¶öA‹ ‰A3Œ¹ A3ŒA3Œ±M9Â…XþÿÿHÁãE‰ØHt AƒàAƒøvmAƒèL WQH‰òD‰ÇÁï‰ÿH\¾€‹HƒÂ1ȉÁA‰ÂD¶ØÁéAÁê¶Ä‰ÉE¶ÒA‹ ‰C3Œ™ A3ŒC3Œ‘H9Úu¾Ht¾AƒàE…À„ŠýÿÿAƒèL áPH‰ðJ\f„¶HƒÀ1ÊÁé¶ÒA3 ‘H9Øuè‰È÷ÐéQýÿÿffffff.„HƒìHƒÄéCûÿÿHƒìHƒÄé3ûÿÿHƒìhH‰t$0L‰|$`1öH‰\$(H‰|$8H‰l$@L‰d$HL‰l$PL‰t$X‹iD‹¹”H‹YPD‹‰ D‹¤D‹±¸DúþÿÿA‰úN<D‰ÈD9ßv·)îN”IcùD‹©œL‹a`‹iLL‰T$E¶T?ÿDˆT$E‰ÂA¶0‹F(HkHn {)ø){…À‰F(u¹H‹FH‰F ë¯f.„AWAVAUATUWVSH‰ËHƒì8‰”$ˆ‹»œÿ†ä‹³”H‹SP‹‹€F‰÷#{L¶‹SpÓâH‹K`1Ð#C|‰Cp‰ÀHÀHCh·…Òf‰yf‰0t‹CD‰ñ)Ñ-9Á†ì‹ƒˆƒø†½‹“ôf+³˜ƒèH‹»ø‰ÑƒÂf‰4OH‹»èƒîˆH y…¶À‰“ô¶fƒ„ƒÀfþÿ‡hHQƒ·ö¶0H˜D‹ƒˆ‹»œfƒ„ƒ° ‹ƒðE1Ƀè9ÂA”ÁD)ÇD;ƒ¨‰»œ‡ƒÿ†„‹ƒ”D‹s|ApÿL‹k`D‹cLL‹[hL‹SP‰D$(‹‹€‹Cp‹T$(D‰L$,‰³ˆE‰ñ@ƒÂÓàƒîj‰“”A‰ÖE!æA¶,*1èD!È…ö‰Å‰CpI,kD·}fG‰|uf‰U‰³ˆu½DD$(D‹L$,D‰ƒ”E…É„Cþÿÿ‹ƒ„1ÒA)À…Àx‰ÂHSPE1ÉH‰Ù製H‹3‹ƒ”H‹~(‰ƒ„H‰ùèH»‹o(9nFn…í…_H‹‹p…ö…âýÿÿ1ÀHƒÄ8[^_]A\A]A^A_ÃDH‹CP‰öE1ɶ0‹ƒôH‹³ø‰ÁƒÀfÇNH‹³èˆfƒ„“¼‹“ð‹»œD‹ƒ”‰ƒôƒê9ÐA”ÁƒïAƒÀ‰»œD‰ƒ”éÿÿÿDƒ”H‹CPǃˆD‰ÂD‰ƒ”AH¶‰Sp¶‹‹€Óâ1Ð#C|‰CpéÎþÿÿf.„H‰Ùè(ùÿÿ‹¼$ˆ‹ƒœ…ÿ„š…À„¥ƒø‡îüÿÿ‹ƒˆ‹³”é;ýÿÿfÁîH å€H†%ÿ¶é†ýÿÿH‰ÙèHöÿÿ‹³”‰ƒˆéýÿÿH‹NH‹W A‰ìM‰àèt,‹G(LfLg n)è)n…À‰G(…pþÿÿH‹GH‰G écþÿÿ=†fþÿÿ…À…[ÿÿÿD‹ƒ”¸AƒøAFÀƒ¼$ˆ‰ƒ ts‹‹ô¸…É„)þÿÿ‹ƒ„1ÒA)À…Àx‰ÂHSPE1ÉH‰Ùèo»H‹3‹ƒ”H‹~(‰ƒ„H‰ù蹋o(9nFn…í…§H‹‹P…Ò•À¶ÀéÉýÿÿ‹ƒ„1ÒA)À…Àx‰ÂHSPA¹H‰Ùè »H‹3‹ƒ”H‹~(‰ƒ„H‰ù豸‹o(9nFn…íuH‹ƒxÀƒÀélýÿÿH‹NH‹W A‰ìM‰àè/+‹G(LfLg n)è)n…À‰G(uÂH‹GH‰G ë¸H‹NH‹W A‰ìM‰àèø*‹G(LfLg n)è)n…À‰G(…(ÿÿÿH‹GH‰G éÿÿÿffff.„AUATUWV‰ÖSH‰ËHƒì(‹«œf„ý†í‹»”H‹SP‹‹€G‰ý#kL¶‹SpÓâH‹K`1Ð#C|‰Cp‰ÀHÀHCh·f‰if‰8…Ò‹‹ˆ‹ƒ˜Çƒˆ‰‹ ‰ƒŒ„+;‹¨¸s‹kD)×í9f.„ƒù†»9Á‚³‹ƒ”D‹‹œƒéD‹“ôH‹»øAÁƒèf+ƒŒD‰ÒAƒéAƒÂf‰WH‹»èƒèˆ HѶÉD‰“ô¶ fƒ„“Àf=ÿ‡UH©}·À¶H˜‹«œD‹›ðfƒ„ƒ° ‹ƒ D‹ƒ”ƒÅAƒë)Ń艫œ‰ƒ DAƒÀE9ÁD‰ƒ”r?H‹KPAP‹{p¶‹‹€ÓçH‹K`1ú#S|D‰Ç#{L‰Sp‰ÒHÒHShD·"fD‰$yfD‰ƒè…À‰ƒ u¤AƒÀE9ÚǃǃˆD‰ƒ”… þÿÿ‹ƒ„1ÒA)À…Àx‰ÂHSPE1ÉH‰Ùè¸H‹;‹ƒ”H‹o(‰ƒ„H‰éèÁµD‹e(D9gDFgE…ä…H‹D‹XE…Û…œýÿÿ1ÀHƒÄ([^_]A\A]ÃD‹“E…Ò„Ü‹ƒ”H‹SPH‹»øƒè¶‹ƒô‰ÁƒÀfÇOH‹»èˆfƒ„“¼‹“ð‰ƒôƒê9ЄÍH‹‹«œƒƒ”D‹Hƒí‰«œE…É„hÿÿÿý‡ýÿÿH‰ÙèÏóÿÿ…ö‹ƒœ„¼…À„ǃø‡ìüÿÿ‹‹ˆ‹ƒ˜Çƒˆ‰ƒŒ‰‹ ¸éTýÿÿ@‹«œÇƒƒƒ”ƒí‰«œé‹üÿÿfÁèHP{H%ÿ¶éšýÿÿ‹ƒ„D‹ƒ”1ÒA)À…Àx‰ÂHSPE1ÉH‰Ùèu¶H‹;‹ƒ”H‹o(‰ƒ„H‰éè´D‹e(D9gDFgE…ä„ÛþÿÿH‹OH‹U E‰åM‰èè¡&‹E(LoLm DgD)àD)g…À‰E(…§þÿÿH‹EH‰E éšþÿÿH‰Ùèðÿÿƒø‰ƒˆwƒ»°teƒøtL‹‹ éDüÿÿH‹OH‹U E‰åM‰èè1&‹E(LoLm DgD)àD)g…À‰E(…µýÿÿH‹EH‰E é¨ýÿÿ‹“”+“˜úv Çƒˆ‹‹ ¸éÕûÿÿ=†ýÿÿ…À…9þÿÿD‹ƒE…ÀtL‹ƒ”H‹SPH‹»øƒè¶‹“ô‰ÑƒÂfÇOH‹»èˆfƒ„ƒ¼‰“ôǃD‹ƒ”¸AƒøAFÀƒþ‰ƒ tr‹«ô¸…í„ïüÿÿ‹ƒ„1ÒA)À…Àx‰ÂHSPE1ÉH‰Ù訴H‹3‹ƒ”H‹~(‰ƒ„H‰ùèM²‹o(9nFn…í…®H‹ƒx•À¶Àéüÿÿ‹ƒ„1ÒA)À…Àx‰ÂHSPA¹H‰ÙèF´H‹3‹ƒ”H‹~(‰ƒ„H‰ùè뱋o(9nFn…íuH‹ƒxÀHƒÄ([^_]A\ƒÀA]ÃH‹NH‹W A‰ìM‰àèa$‹G(LfLg n)è)n…À‰G(uºH‹GH‰G ë°H‹NH‹W A‰ìM‰àè*$‹G(LfLg n)è)n…À‰G(…!ÿÿÿH‹GH‰G éÿÿÿ¸éõùÿÿDAV¸ÿÿAUATUW‰×VSH‰ËHƒì ‹qƒîþÿÿCðë6€H‹D‹hE…í„‹“”‹ƒ„‹KD)Âé9ʃ‹“œƒú†b“”‹ƒ„ǃœD…Ò‰“”tD9ÂrµD)ÂD‰ƒ”A)À‰“œ1Ò…Àx‰ÂHSPE1ÉH‰Ù迲H‹+‹ƒ”L‹e(‰ƒ„L‰áèd°E‹l$(D9mDFmE…í„=ÿÿÿH‹MI‹T$ E‰îM‰ðèé"A‹D$(LuMt$ DmD)èD)m…ÀA‰D$(…ÿÿÿI‹D$I‰D$ H‹D‹hE…í…ùþÿÿf„1ÀHƒÄ [^_]A\A]A^ÃA‰Ð1Ò…Àx‰ÂHSPE1ÉH‰Ùè²H‹+‹ƒ”L‹e(‰ƒ„L‰á誯E‹l$(D9mDFmE…í…ÓH‹D‹`E…ät—‹“œƒú‡¦þÿÿ„H‰ÙèHîÿÿ‹“œ…Ò”À…ÿ„Þ„À„{þÿÿƒÿǃ „ÚD‹ƒ”‹‹„¸A9ÈŽ1ÿÿÿA)È1Ò…Éx‰ÊHSPE1ÉH‰ÙèE±H‹3‹ƒ”H‹~(‰ƒ„H‰ùèꮋo(9nFn…í…H‹ƒx•À¶ÀéØþÿÿfDH‹MI‹T$ E‰îM‰ðè\!A‹D$(LuMt$ DmD)èD)m…ÀA‰D$(…óþÿÿI‹D$I‰D$ éäþÿÿ„À„ýÿÿézþÿÿf.„‹ƒ„D‹ƒ”1ÒA)À…Àx‰ÂHSPA¹H‰Ùèv°H‹3‹ƒ”H‹~(‰ƒ„H‰ù讋o(9nFn…íuH‹ƒxÀƒÀéþÿÿH‹NH‹W A‰ìM‰àè™ ‹G(LfLg n)è)n…À‰G(uÂH‹GH‰G ë¸H‹NH‹W A‰ìM‰àèb ‹G(LfLg n)è)n…À‰G(…¼þÿÿH‹GH‰G é¯þÿÿ€HìˆH…ɸþÿÿÿH‰\$HH‰|$XH‰ËH‰l$`H‰t$PH‰×L‰d$hL‰l$pD‰ÅL‰t$xL‰¼$€u;H‹\$HH‹t$PH‹|$XH‹l$`L‹d$hL‹l$pL‹t$xL‹¼$€HĈÄH…ÒH‹q(u¸þÿÿÿëµH…ötô‹V,ƒú‰T$(t¤ƒú„nD‹¾œ¸þÿÿÿE…ÿuŠƒ|$(„a‹FDÇF,9ÅrD‹t$(E…ö„[)ÅHï‰Å‹CH‹H‰ñ‰kH‰;‰D$,H‰T$0èZëÿÿD‹®œAƒý† H‰\$8@D‹¦”‹FpA]þ‹Ž€L‹^PD‹V|L‹N`D‹FLH‹nhD‰âDzÓàA‰ÖE!ÆA¶<;1øD!ЉljFpH|}D·?fG‰D‹N(E‰Èë-‹V8H‹I0‰ÐƒÂ¶H‹N‰V8D‰ÂAƒÀ„ÀˆD‰F(tOH‹N0D9FuÍ‹Q<…Òt E9Á‚µH‹k(H‰éèxšD‹e(D9cDFcE…äu;D‹N(D;N„H‹N0E‰Èëˆ1íH‹F0‹@<…Àt E9Á‚³…ítD‹FféõÿÿH‹KH‹U E‰æM‰ðèÈ ‹E(LsLu DcD)àD)c…À‰E(u•H‹EH‰E ë‹ÇFgH‹F0éœþÿÿÇF8ÇF[H‹F0éìþÿÿI‹L$I‹U E‰÷M‰øèf A‹E(M|$M} Et$D)ðE)t$…ÀA‰E(…LøÿÿI‹EI‰E é?øÿÿH‹MI‹T$ E‰îM‰ðè A‹D$(LuMt$ DmD)èD)m…ÀA‰D$(…IõÿÿI‹D$I‰D$ é:õÿÿ=‡Düÿÿ1Àé¤ôÿÿÇF8ÇFIé?úÿÿ‹–¬ƒúŽøÿÿƒú°@Žøÿÿƒú°€ºÀEÂéþ÷ÿÿD‰ÊHV‹KLE)ÈèÒÿÿ‰CLéSúÿÿD‰ÊHV‹KLE)ÈèíÑÿÿ‰CLé1þÿÿ‹†„D‹†”1ÒA)À…Àx‰ÂHVPA¹H‰ñèËšH‹.‹†”L‹e(‰†„L‰áèp˜E‹l$(D9mDFmE…í…µH‹ƒxÀƒÀéÄóÿÿ1Ò1ÉE1ÀèlÑÿÿ‰CL‹F(H‹N‰ÂhÆH‹NPÆ‹H‹NPÆH‹V0‰n(H…Ò„•‰íHnƒ:A•Àƒz<É÷уáHƒzFÉ÷уáAÈHƒz É÷уáHƒz0A Ò÷ÒƒâHˆUH‹n0PL‹F‹mAˆ,H‹V0H‹n‹RÁêˆT H‹n0PL‹F¹·mAˆ,H‹n0PL‹F¶mAˆ,‹®¬P‰ÐHF‰V(ƒý tƒ¾°¹ŽUˆH‹n0BL‹FJ‹m Aˆ,H‹F0‰N(Hƒxt,‹@H‹n‰ÉˆD H‹F0JH‹nƒÂ‹@ÁèˆD H‹F0‰V(ƒx<tH‹V‹KLD‹F(èÐÿÿ‰CLH‹F0ÇF8ÇFEé öÿÿH‰ÙèÂØÿÿ‹F(P;V‡–ñÿÿéqûÿÿÇF[é´ûÿÿÇFgéAûÿÿD‰ÊHV‹KLE)Èè¤Ïÿÿ‰CLé3üÿÿD‰ÊHV‹KLE)ÈèŠÏÿÿ‰CLé!øÿÿ‹F(‹{LH‹N‰Â@ˆ<‹SLHH‹~Áꈷ{NPH‹N@ˆ<¶{OPH‹N@ˆ<‹{ PH‹N@ˆ<‹S HH‹~Áꈷ{PH‹N@ˆ<¶{PH‹NƒÀ@ˆ<‰F(éÃóÿÿ‰êHV‹KLA)èèìÎÿÿ‰CLH‹F0é¶öÿÿÇFIéÎöÿÿH‹MI‹T$ E‰îM‰ðè@LuMt$ D)mA‹D$(D)èDm…ÀA‰D$(…ýÿÿI‹D$I‰D$ éýÿÿ=š…ÿïÿÿé‡÷ÿÿAƒø‡fùÿÿé½÷ÿÿH‹MI‹T$ E‰îM‰ðè×LuMt$ D)mA‹D$(D)èDm…ÀA‰D$(…FòÿÿI‹D$I‰D$ é7òÿÿH‰ñèz•é-óÿÿ€|$/„ ðÿÿé­õÿÿE‰È½éƒöÿÿE‰È½énúÿÿD‹FtH‹Nh1ÒAƒèfBÇAMÀèVƒ¾œ…Ùòÿÿdž”dž„dž é¶òÿÿH‹V‰íÆ*H‹NPÆH‹NPÆH‹NPÆH‹NPƒÀÆ‹®¬‰ÂHV‰F(¹ƒý tƒ¾°¹ ƒížÁÁሠH‹NPƒÀÆ ‰F(ÇFqéÙîÿÿƒížÁÁáéüÿÿ„HƒìHH…ɸþÿÿÿH‰\$0H‰t$8‰ÓH‰|$@uH‹\$0H‹t$8H‹|$@HƒÄHÃH‹q(H…ötãƒúÿtƒú v¸þÿÿÿëÒ»D‰ÀÁè„ÀuçAƒø¸þÿÿÿµHc†¬H=HÁàD9†°L‹Ltz1Àƒy uK9ž¬t7‰ž¬HcÛHÁãHß·W‰–¨·‰–´·W‰–¸·W‰–¤D‰†°éBÿÿÿºD‰D$(èäìÿÿƒøûD‹D$(uœƒ~(ºDÂëŽHcÓ1ÀHÁâL9L…rÿÿÿéuÿÿÿHƒì8H…ɸþÿÿÿH‰\$(H‰t$0H‰ËuH‹\$(H‹t$0HƒÄ8ÃfDL‹A(M…ÀtâA‹pƒþEtƒþ*……DI‹PH…Òt H‹K@ÿS8L‹C(I‹PhH…Òt H‹K@ÿS8L‹C(I‹P`H…Òt H‹K@ÿS8L‹C(I‹PPH…Òt H‹K@ÿS8L‹C(H‹K@L‰ÂÿS81ÀƒþqHÇC(•ÀH‹\$(H‹t$0D@ýHƒÄ8Ãþ[„wÿÿÿƒþI„nÿÿÿƒþq„eÿÿÿƒþgf„Zÿÿÿþš…ÿÿÿéIÿÿÿf„Hƒìh¸úÿÿÿH‰t$@‰ÖH‹”$ H‰\$8H‰|$HH‰ËH‰l$PL‰d$XH…ÒL‰l$`‹¼$‹¬$˜‹Œ$¨u#H‹\$8H‹t$@H‹|$HH‹l$PL‹d$XL‹l$`HƒÄhÃùXt¸úÿÿÿëÑ€:1uôH…Û¸þÿÿÿtÂHƒ{0HÇC tQHƒ{8t=ƒþÿ¸DðE…Éx%AƒùA½~AƒéAµGÿƒøv4¸þÿÿÿéwÿÿÿA÷ÙE1íëæHúžH‰S8ë¶HÍžHÇC@H‰C0ëšAƒøuÆAƒùÀAƒù~ºƒþ µ‰ðÁè„Àu¬ƒý§‰èÁè„ÀužAƒù¸ H‹K@DDÈfA¸ ºD‰L$(ÿS0H…ÀI‰ÄD‹L$(„tH‰C(D‰h,A½D‰HHD‰ÉH‰HÇ@0D‰èD‰êÓàA¸A‰ÁA‰D$DAAÿA‰D$LG‰ÁA‰D$xÓ⹉ÐA‰T$t1ÒƒèA‰D$|G ÷ñD‰ÊH‹K@A‰„$€ÿS0A‹T$DH‹K@A¸I‰D$PÿS0A‹T$tH‹K@A¸I‰D$`ÿS0WI‰D$hAÇ„$A¸‰ÑAÓåH‹K@D‰êE‰¬$ðÿS0A‹”$ðIƒ|$PI‰D$ •A‰L$„‚Iƒ|$`tzIƒ|$htrH…Àtm‰Ñ‰ÒA‰´$¬ÑéHRA‰¬$°‰ÉAÆD$<H HHÐI‰„$èI‰Œ$øH‰ÙH‹t$@H‹\$8H‹|$HH‹l$PL‹d$XL‹l$`HƒÄhé™äÿÿ¸üÿÿÿémýÿÿH‹¨ AÇD$šH‰ÙH‰C èóûÿÿ¸üÿÿÿéGýÿÿf„Hƒì8M…À¸úÿÿÿH‰\$ H‰t$(H‰ËH‰|$0‰ÖuH‹\$ H‹t$(H‹|$0HƒÄ8Ãf.„AƒùXt¸úÿÿÿëÕA€81uóH…ɸþÿÿÿtÅHƒy0HÇA „Hƒ{8„tƒþÿtƒþ ŽŽ¸þÿÿÿë’¾H‹K@A¸ ºÿS0H…ÀH‰Ç„šH‰C(H‹K@A¸º€H‰Ç@,HÇ@0Ç@HÇ@D€Ç@LÿÇ@xÇ@t€Ç@|ÿÇ€€ÿS0‹WDH‹K@A¸H‰GPÿS0‹WtH‹K@A¸H‰G`ÿS0H‹K@º@H‰GhLJLJð@A¸ÿS0‹—ðHƒPH‰G •‰O„©Hƒ`„žHƒh„“H…À„Š‰Ñ‰Ò‰·¬ÑéHRLJ°‰ÉÆG<H HHÐH‰‡èH‰øH‰ÙH‹t$(H‹\$ H‹|$0HƒÄ8éqâÿÿHÚšH‰C8é|þÿÿHªšHÇA@H‰A0éYþÿÿ‰ðÁè„À…eþÿÿélþÿÿH‹P ÇGšH‰ÙH‰C èùÿÿ¸üÿÿÿéÕýÿÿ¸üÿÿÿéËýÿÿf„HƒìHH…ÒH‰\$ H‰t$(H‰ËH‰|$0H‰l$8L‰d$@u+¸þÿÿÿH‹\$ H‹t$(H‹|$0H‹l$8L‹d$@HƒÄHÄH…ÉtÐH‹j(¸þÿÿÿH…ítÇH‹A¸ H‰H‹BH‰AH‹BH‰AH‹BH‰AH‹B H‰A H‹B(H‰A(H‹B0H‰A0H‹J8H‰K8H‹J@H‰K@H‹rHH‰sHH‹RPH‰SPºÿÐI‰Ä¸üÿÿÿM…ä„SÿÿÿL‰c(¹äL‰çH‰îA¸óH¥I‰$A‹T$DH‹K@ÿS0A‹T$DH‹K@A¸I‰D$PÿS0A‹T$tH‹K@A¸I‰D$`ÿS0H‹K@I‰D$hA¸A‹”$ðÿS0I‹L$PH‰ÆI‰D$H…É„éIƒ|$`„ÝIƒ|$h„ÑH…À„ÈE‹D$DH‹UPEÀE‰ÀèNýE‹D$DI‹L$`H‹U`MÀè8ýE‹D$tI‹L$hH‹UhMÀè"ýE‹D$I‹L$H‹UèýI‹T$H‰ÐHE H+EI‰D$ A‹„$ð‰ÁH@ÑéHÂI„$¼‰ÉH NI‰”$èI‰„$@ I„$° I‰Œ$øI‰„$X I„$¤ I‰„$p 1ÀéäýÿÿH‰Ùè2÷ÿÿ¸üÿÿÿéÒýÿÿHƒìH…Ét'yOtHƒÄéå!DHƒÄé—€¸þÿÿÿHƒÄÃHƒì8L‰L$XLL$XL‰L$(èø®HƒÄ8ÃSH‰ËHƒì H‹IhH…Étƒ{dütèüûHÇChÇCdHƒÄ [Ãffffff.„HƒìhH‰l$P1íH…ÉH‰t$@H‰|$HH‰ÎH‰\$8L‰d$X‰×L‰l$`u&H‰èH‹\$8H‹t$@H‹|$HH‹l$PL‹d$XL‹l$`HƒÄhùÈL‰D$(è]ûH…ÀH‰ÃL‹D$(t¾Ç@(Ç@, HÇ@hÇ@Ç@TÿÿÿÿÇ@XÇ@@A¶„ÀtFH Ã5ë¾Àƒè0‰CTIƒÀA¶„À„ÄPЀú v߃è+H‰ñèAúI‰ÅMeL‰áèúùH…ÀH‰ÁH‰C „ÿÿÿƒÿþ„“LŠ4I‰ñL‰âè¯ýÿÿ‹Cº€=Ot0ƒýÒâüÿÿ‡ƒýÉáüÿÿÁÉ€=±yEÑ…ÿx|‰{ƒøtd=O„ÎÇH‰ÙÇC`H‰ÝèaýÿÿÇCÇCxé¼ýÿÿM…íufÆérÿÿÿ‹C@…À…eþÿÿÇC@éÿÿÿf„ÇC±y란ƒÿþ„¡A¸¶H‰ñè©«‰Çƒÿÿ‰{„þÿÿ‹CéZÿÿÿM‰àH‰òèùéÿÿÿE1À1ÉH‰òèùHƒøÿI‰Å…³þÿÿA¼E1íé©þÿÿ1ÒA¸‰ùèäøƒøÿ‰CHtD‹CÇ=O… ÿÿÿÇCLÇCPÇCDéóþÿÿA¸¶H‰ñÿO–‰ÇéYÿÿÿÇCHë³€HƒìI‰ÐºÿÿÿÿHƒÄéküÿÿff.„HƒìI‰ÐºÿÿÿÿHƒÄéKüÿÿff.„HƒìHH‰l$@1íƒùÿH‰\$(H‰t$0‰ËH‰|$8H‰ÖuH‰èH‹\$(H‹t$0H‹|$8H‹l$@HƒÄHùè¶÷H…ÀH‰ÇtÒL“3A‰ÙºH‰ÁèwûÿÿH‰ùI‰ð‰ÚèÊûÿÿH‰ùH‰Åè—÷ë¡ffff.„HƒìI‰ÐºþÿÿÿHƒÄé›ûÿÿff.„HƒìH…ɸÿÿÿÿuHƒÄÃD‹AAø±yt AøOuåD‹A(¸ÿÿÿÿE…Àu׃ú¸FÐ0À‰Q,ëÅ€S¸ÿÿÿÿH‰ËHƒì H…ÉuHƒÄ [ÄyOué‹Qdƒúût…ÒuÝHcSH‹KE1Àè÷H‰ÂHƒÂtÅ{OÇuÇCLÇCPÇCDÇC`H‰Ùè€úÿÿÇCÇCx1Àë€fffff.„Hƒì8H…ɸÿÿÿÿH‰\$(H‰t$0H‰Ë‰ÖuH‹\$(H‹t$0HƒÄ8Ã@‹QúO•Áú±yt„ÉuÕD‹KdAƒùût E…ɸÿÿÿÿuÁƒÈÿAƒøw¸E…Àu?+súOÇC`t8…öˆ´{O„……öt ÇC`‰s\‹Cðétÿÿÿƒ{`t¾s\빃{Du‰ðCx»‰ò+‹KA¸èÕõH‰ÂƒÂ„>ÿÿÿÇÇCLH‰ÙÇCPÇC`è^ùÿÿ‹CÇCxð‰Céÿÿÿ‹…Òx9Ö‰Ð}‰ð)ÂC)Ɖ‰ÂHSéYÿÿÿƒÈÿ„É…ÚþÿÿsˆÑþÿÿH‰Ùè þÿÿƒøÿ…'ÿÿÿé»þÿÿfffff.„HƒìHƒÄéƒþÿÿHƒìH…ɸÿÿÿÿuHƒÄËQú±yu"D‹I`1À‹QE…Ét‹A\ÐHƒÄÃf.„úOtÖëÄfDHƒìH…ɸÿÿÿÿuHƒÄËQú±yu"D‹Q`1À‹QE…Òt‹A\ÐHƒÄÃf.„úOtÖëÄfDS¸ÿÿÿÿH‰ËHƒì H…ÉuHƒÄ [Ä‹Qú±ytúOuß‹K1ÒA¸èEôƒøÿtÊ{OuÁ+Cxë¼f.„S¸ÿÿÿÿH‰ËHƒì H…ÉuHƒÄ [Ä‹Qú±ytúOuß‹K1ÒA¸èåóƒøÿtÊ{OuÁ+Cxë¼f.„Hƒì1ÀH…Ét‹Qú±yu1ÀúOtHƒÄÃúOuó1ÀúOué‹APHƒÄÃHƒì1ÀH…ÉuHƒÄÃD‹AAø±yu3H…Òt‹Ad‰ƒydüH/t×H‹AhH/H…ÀHDÂHƒÄÃDAøOtÄë°DHƒìH…Ét!‹A=±yu=OtHƒÄé½öÿÿ=OtéHƒÄÃÇALÇAPHƒÄé™öÿÿf„HƒìXH‰\$8H‰t$@H‰ÎH‰|$HH‰l$P‰ÓH‹IhL‰ÇH…Étƒ~dütètòHÇFhƒûût…Û…—H…ÿ‰^dtmƒûüthH‹n H‰éèfòH‰ùH‰Ãè[òHLèòH…ÀH‰ÃH‰FhtmH‰éè=òH‰ùH‰Æè2òLö-HTHñ-I‰éH‰ÙH‰|$(H‰D$ è²õÿÿH‹\$8H‹t$@H‹|$HH‹l$PHƒÄXÃf„Çé^ÿÿÿDÇFdüÿÿÿëÅHƒìHH‰\$ H‰t$(H‰ËH‰|$0H‰l$8HqpL‰d$@‹I(…É„‘D‹cxAƒüE‰à†gH‹Cp€8„3‹C@…ÀtNH‹K8H‹SpE‰ÀH‰KèHñ‹CxÇCDÇCxÇC@‰1ÀH‹\$ H‹t$(H‹|$0H‹l$8L‹d$@HƒÄHÃÇCxÇCL1ÀÇëÊfD‹{,‰ùèÆð ?H‰ÅH‰C0‰ÉèµðH…íH‰C8„îH…À„ÿL¶,‰{(Hǃ Hǃ¨Hǃ°A¹XÇCxHÇCpºH‰ñè"9…À„éþÿÿH‹K8èYðH‹K0èPðÇC(L:,ºüÿÿÿH‰Ùèýÿÿ¸ÿÿÿÿéÿÿÿ€x‹…ÃþÿÿH‰ñè^6ÇCDÇC@1ÀéÝþÿÿ‹SdƒúûuN‹SL…ÒtU1ÀE…À„ÃþÿÿAƒø‡uþÿÿA¸éwþÿÿH…Àt„H‰ÁèÅïH‹k0H…í„oÿÿÿH‰éè°ïébÿÿÿ…Ò¸ÿÿÿÿt©éyþÿÿE…ätH‹SpH‹C0¶ˆD‹cx‹k(1ÿD)åE‰äLc0ëÇ9ýv"‰ú‹KA‰èIA)øèü¡ƒøáuÇCLD‹CxH‹C0AøH‰CpD‰CxéDÿÿÿÿØŒ‹èiïƒÊÿI‰ÀH‰ÙèsüÿÿƒÈÿéïýÿÿff.„AVAUATUWHypVH‰ÎS1ÛHƒì ‹©ˆë+ƒøþt?ƒøü„ƃøý„éƒû‹†ˆ„}…ÀtyD‹NxE…Ét=1ÒH‰ùèã9ƒø‰Ãu¼LÝ*ºþÿÿÿH‰ñèèûÿÿ¸ÿÿÿÿHƒÄ [^_]A\A]A^Ã@‹Fdƒøû…·D‹FLE…À„¼Lz*ºûÿÿÿH‰ñè£ûÿÿ‹†ˆ)Å1À‰.‰íH÷ÝH®€ƒûH‰nuŸÇFDHƒÄ [^_]A\A]A^ÃL*‰ÂH‰ñè[ûÿÿHƒÄ ¸ÿÿÿÿ[^_]A\A]A^ÀH‹†Læ)‰ÚH‰ñH…ÀLEÀè!ûÿÿHƒÄ ¸ÿÿÿÿ[^_]A\A]A^Ã…À„Aÿÿÿ¸ÿÿÿÿéÿÿÿD‹n(L‹v0E1äëAÄE9åv#D‰â‹NE‰èIE)àè ƒøÞu%ÇFLDfxH‹F0H‰FpE…äD‰fx„óþÿÿé˜þÿÿÿè€íƒÊÿI‰ÀH‰ñèŠúÿÿƒÈÿéŸþÿÿfWVSH‰ËHƒì ‹CDƒøtnƒøt:…ÀuH‰Ùè]ûÿÿƒøÿt!‹SD…Òt‹…ÀuD‹[LE…ÛtÌD‹SxE…ÒuÃ1ÀHƒÄ [^_ËC(H‰ÙÀ‰ƒˆH‹C8H‰ƒ€è±ýÿÿƒøÿu»ëÓf.„‹s(H‹{81ÀÇöë9Ɖv"‰Â‹KA‰ðHA)À蟃øßuÇCLH‹C8H‰CHƒÄ 1À[^_Ãÿû‰‹èŒìƒÊÿI‰ÀH‰Ùè–ùÿÿƒÈÿéWÿÿÿfffff.„V1À‰ÖSH‰ËHƒì(…Òu&ëH|M9ðf„@)ƉÂ1À‰S‰ÐHC…öt9‹ƒøuÕD‹CLE…Àt‹Kx…Ét"H‰ÙèªþÿÿƒøÿuØHƒÄ([^Éò)ð1öë¾fDHƒÄ(1À[^ÀHƒìXH…ɸÿÿÿÿH‰\$ H‰t$(H‰ËH‰|$0H‰l$8H‰×L‰d$@L‰l$HD‰ÆL‰t$Pu(H‹\$ H‹t$(H‹|$0H‹l$8L‹d$@L‹l$HL‹t$PHƒÄXÃyOuÏ‹Qdƒúû…ƒþŒm¸t³D‹[`E…Û…9E1öëv€D‹SLE…Òt D‹KxE…É„å‹CD…À„Ä‹S(Ò9Ö‚·ƒøtc‰³ˆH‰»€H‰Ùè¸ûÿÿƒøÿ„Iÿÿÿ‹+ÇA‰ì)îkLçAî…ö„“‹+…ít‹9îH‹SH‰ùFîA‰ì)îM‰àè‚êLc)+ëÈ1íë fDÅ9îv+A‰õA‰ì‹KA)íJ'E‰èè꜃øÝuEÇCLD‰îë)îA‰ì놅Ò„÷þÿÿéµþÿÿH‰Ùèóüÿÿƒøÿ…qÿÿÿéŸþÿÿÇCPD‰ðéþÿÿÿ ‡‹è1êƒÊÿI‰ÀH‰Ùè;÷ÿÿƒÈÿémþÿÿ‹S\ÇC`H‰Ùè¡ýÿÿƒøÿ…¬þÿÿéMþÿÿL&ºýÿÿÿH‰ÙèÿöÿÿƒÈÿé1þÿÿ€Hƒì8H…ɸÿÿÿÿuHƒÄ8ÃyOuò‹Qdƒúûu ‹…Àt H‹QƒèƒA‰¶HƒÂH‰QëÊ…ÒtÜëÄHT$ A¸è–ýÿÿ‰ÂƒÈÿ…Ò~«¶D$ ë¤fDHƒì8H…ɸÿÿÿÿuHƒÄ8ÃyOuò‹Qdƒúûu ‹…Àt H‹QƒèƒA‰¶HƒÂH‰QëÊ…ÒtÜëÄHT$ A¸è&ýÿÿ‰ÂƒÈÿ…Ò~«¶D$ ë¤fDHƒì8H…ÒH‰\$(H‰t$0H‰Ó‰Îu¾ÿÿÿÿ‰ðH‹\$(H‹t$0HƒÄ8ÃfzOuß‹BdƒøûuG‹C`…ÀuF…öxÌ‹…ÒtZD‹C(EÀD9„§H‹CH;C8tlHPÿƒH‰S@ˆpÿÇCPƒkë•…ÀtµëŠ‹S\ÇC`H‰Ùèðûÿÿƒøÿu£‰Æéqÿÿÿ‹C(ÇÀ‰ÀHƒèHC8H‰C@ˆ0ÇCPƒkéEÿÿÿ‰ÒH D‰ÂHH9ÈsHƒéHƒê¶ˆH9K8ríH‰SH‰ÐécÿÿÿL8$ºýÿÿÿH‰ÙƒÎÿèðôÿÿéøþÿÿff.„HƒìxH…ÒH‰\$8H‰t$@H‰ÓH‰|$HH‰l$PH‰ÎL‰d$XL‰l$`L‰t$hL‰|$pu91ÀH‹\$8H‹t$@H‹|$HH‹l$PL‹d$XL‹l$`L‹t$hL‹|$pHƒÄxÃf.„H…ÉtÂ1ÀE…À~½yOu´‹Qdƒúû…•ƒ~`…¾E‰Ä1ÀAƒìt“‹I‰Ý…À„€D9àD‰çL‹~Føº ‰ýI‰èL‰ùèþæH…ÀI‰Æt ¿D)ÿljýL‰éI‰èL‰úèœæ‹HnIí~)øA)ü‰tM…öt1ÀI9Ý„ ÿÿÿAÆEH‰Øéÿÿÿ…Ò„cÿÿÿéÿÿÿH‰ñè%ùÿÿƒÀf„ñþÿÿ‹…À…cÿÿÿÇFP뵋V\ÇF`H‰ñD‰D$(èðùÿÿ‰Â1ÀD‹D$(ƒÂ…ÿÿÿé²þÿÿf„S1ÀH‰ËHƒì H…Ét yOt ‹C@HƒÄ [ËID…Éuð‹…ÒuêH‰Ùèôÿÿëà„Hƒì8H…ÉH‰\$ H‰t$(H‰ËH‰|$0¾þÿÿÿu ‰ðH‹\$ H‹t$(H‹|$0HƒÄ8Ãf.„yOu׋q(…öuB1öƒ{dûH‰Ù@•ÆE1À1Òè©òÿÿH‹K t¶ûèDå‹Kèä—H‰Ù‰Çè2å…ÿ¸ÿÿÿÿEðëŽHIpèeMH‹K8èåH‹K0è åë¡HƒìhH‰\$HH‰t$PH‰ËH‰l$`H‰|$X‹y,‰ýH‰éèÈäH…ÀH‰ÆH‰C0„Ø‹C@…Àt!‰{(1ÀH‹\$HH‹t$PH‹|$XH‹l$`HƒÄhÃH‰éèˆäH…ÀH‰C8„¹HR!‹STHKpHǃ Hǃ¨A¹H‰D$0‹CXA¸Hǃ°ÇD$8XÇD$ ‰D$(èïßÿÿ…Àu)‹S@‹C,…Ò‰C(u‰ƒˆH‹C8H‰ƒ€H‰C1ÀéFÿÿÿH‹K8èäH‹K0èøãL© ºüÿÿÿH‰Ùè<ñÿÿ¸ÿÿÿÿéÿÿÿH‰ñëØffff.„UW‰×VHqpSH‰ËHƒì(‹i(…í„ ‹K@…É…k‹‹ˆ1À…ÿ‰Ê„¶€…Ét ƒø…H‹SH‹«€)Õ……É„ÊH‹ƒ€H‰C‰Í‰úH‰ñè¡Êÿÿƒøþ„[‹‹ˆ9éu®1íƒÿ„3HƒÄ(‰è[^_]Ä‹C(‰ƒˆH‹C8H‰ƒ€‹»ˆH‰C1ÒH‰ñèHÊÿÿƒøþ„‹“ˆ9ú„Ñ…Ò‰×uÙH‹SH‹»€)×t¬‹KA‰øèi•…Àˆê9ø…â‹“ˆ…Òt‡H‹ƒ€ë’‹K(H‹C8‰‹ˆH‰ƒ€é$ÿÿÿDƒÿ‰Í„ÿÿÿH‹SH‹«€)Õ„òþÿÿf‹KA‰èèý”…Àˆ~9èuz‹‹ˆéÎþÿÿH‹Sp‹KD‹CxèÖ”…Àx[;CxuVÇCxHƒÄ(1í[^_‰è]ÃHƒÄ(1í[^_‰è]ÃH‰ñèÅÿÿHƒÄ(‰è[^_]ÃL®ºþÿÿÿH‰Ù½ÿÿÿÿè$ïÿÿéœþÿÿÿi‹½ÿÿÿÿèõáºÿÿÿÿI‰ÀH‰Ùèýîÿÿéuþÿÿè“üÿÿƒøÿ‰Å…äýÿÿé`þÿÿW‰×VH‰ÎSHƒì D‹AxE…Àuu…ÿ¸tO‹^(…Ûx29û.…Àu0H‹F0^1Ò‰^xH‰ñH‰Fpè{ýÿÿƒøÿt&)ßt2‹^(1À…ÛyÎ…À‰ûtÐH‹N0A‰Ø1Òè-áëÀ0ÀHƒÄ [^_ÄHƒÄ 1À[^_Ã1Òè/ýÿÿƒøÿ…{ÿÿÿëÔ@HƒìXH‰|$81ÿH…ÉH‰\$(H‰t$0H‰ËL‰d$HH‰l$@I‰ÔL‰l$PD‰Æt y±yt%‰øH‹\$(H‹t$0H‹|$8H‹l$@L‹d$HL‹l$PHƒÄXËAd…ÀuÔAƒøD‰ÇŒÁtÅD‹i(E…í„ÍD‹[`E…Û…Õ;s(r;D‹KxE…Ét1ÒH‰Ù1ÿèvüÿÿƒøÿtŒs1Ò‰sxL‰cpH‰Ù1ÿè[üÿÿƒøÿEþékÿÿÿ‹Cx…ÀtQH‹KpH‹S0‹k(È)ЉÁ)ÅH L‰â9õGîA‰íM‰èèïßkxk)î„,ÿÿÿ1ÒH‰Ùèüÿÿƒøÿt@‹CxMì…Àu¯H‹S0H‰ÑH‰SpëªL¤ºýÿÿÿ1ÿèøìÿÿéîþÿÿè‹úÿÿƒøÿ…%ÿÿÿ1ÿéÖþÿÿD‹SxÇC`D‹k\E…ÒubE…í¸u5éÿÿÿ„H‹C0k1Ò‰kxH‰ÙH‰Cpèxûÿÿƒøÿt±A)í„Úþÿÿ1À‹k(…íxA9í}D‰í…ÀtÅH‹K0A‰è1Òèßëµ1ÒH‰Ùè;ûÿÿƒÀu1ÿéJþÿÿffffff.„HƒìHH…ɸÿÿÿÿH‰\$8H‰t$@H‰Ë‰ÖuH‹\$8H‹t$@HƒÄHÃ@y±yuä‹Id…ÉuÝ‹S`…Òug‹K(…Ét2‹Sx…Òt!H‹C0Sp)Â9Ñv‰Ò@ˆ4@¶ÆƒCxƒCë§H‹C0H‰CpëÙHT$/A¸H‰Ù@ˆt$/æÿèbýÿÿ‰ÂƒÈÿƒêDÆéoÿÿÿ‹S\ÇC`H‰Ùè üÿÿƒøÿu‚éSÿÿÿfDHƒì8H‰t$(H‰|$0H‰ÎH‰×H‰ÑH‰\$ èÞH‰ú‰ÃA‰ÀH‰ñèÿüÿÿ…Ût …ÀºÿÿÿÿDÂH‹\$ H‹t$(H‹|$0HƒÄ8Ãffff.„HƒìXH…ÉH‰\$(H‰t$0H‰ËL‰d$HL‰l$PH‰ÖH‰|$8H‰l$@M‰ÄA½ÿÿÿÿt E1íy±yt.D‰èH‹\$(H‹t$0H‹|$8H‹l$@L‹d$HL‹l$PHƒÄXÄD‹YdE…ÛuÉD‹Q(E…ÒtoD‹K`E…É…‹{x…ÿt1ÒH‰ÙE1íèMùÿÿƒøÿtš‹k(H‹C0M‰áI‰ðHcýÆD8ÿH‰úH‹K0ÿÆz9èA‰Å}4…À~0H‹C0€|8ÿu%D‰kxH‰CpDkéQÿÿÿèº÷ÿÿƒøÿu‡Dé=ÿÿÿE1íé5ÿÿÿD‹CxÇC`‹k\E…Àui…í¸„_ÿÿÿ‹{(…ÿx?f„9ï2…Àu4H‹C0{1Ò‰{xH‰ÙH‰Cpèøÿÿƒøÿt )ý„"ÿÿÿ‹{(1À…ÿyÊ…À‰ïtÌH‹K0A‰ø1Òè>Üë¼1ÒH‰ÙE1íèWøÿÿƒÀu…éŸþÿÿffff.„Hƒì8L‰D$PLD$PL‰L$XL‰D$(è3þÿÿHƒÄ8Ãfffff.„Hƒì8H…ɸÿÿÿÿH‰\$(H‰t$0H‰Ë‰ÖuH‹\$(H‹t$0HƒÄ8Ã@y±yt¸þÿÿÿH‹\$(H‹t$0HƒÄ8ËQd°þ…Òuǃþwƒy`u‰òH‰Ùè¥÷ÿÿ‹Cdë­‹Q\ÇA`èÑùÿÿƒøÿuÝë—f.„Hƒì8H…ɸþÿÿÿH‰\$ H‰t$(H‰ËH‰|$0D‰Æ‰×uH‹\$ H‹t$(H‹|$0HƒÄ8Ày±yuÜD‹IdE…ÉuÓ9QTt@D‹C`E…ÀuI‹K(…Ét&ƒ{xtºH‰Ùè÷ÿÿƒÀt"HKpA‰ð‰úèCÔÿÿ‰{T‰sX1ÀëŽ1ÀD9AXu¸ë„‹Cdé|ÿÿÿ‹S\ÇC`H‰Ùèùÿÿƒøÿu é`ÿÿÿff.„Hƒì8H…ÉH‰\$ H‰t$(H‰ËH‰|$0¾þÿÿÿu ‰ðH‹\$ H‹t$(H‹|$0HƒÄ8Ãf.„y±yu׋Q`1ö…ÒunºH‰ÙèQöÿÿƒøÿ„ÌD‹[(E…ÛtD‹S@E…Ò„ÂH‹K0èñÙE1À1ÒH‰Ùè<çÿÿH‹K èÛÙ‹Kè{ŒH‰ÙƒøÿDðèÅÙéhÿÿÿ„‹AxÇA`‹y\…À…‰1ö…ÿ¸„nÿÿÿ‹s(…öx59þ1…Àu1H‹C0s1Ò‰sxH‰ÙH‰Cpè¥õÿÿƒøÿt^)÷tC1ÀëÌ„‰þëËH‹K0A‰ð1ÒèVÙë¿‹sdé,ÿÿÿ@HKpè×ÓÿÿH‹K8è&Ùé'ÿÿÿ1öéôþÿÿ1ÒèKõÿÿƒÀ…gÿÿÿ‹sdéÜþÿÿHƒì8M…ɸúÿÿÿH‰\$ H‰t$(H‰ËH‰|$0L‰Æ‰×uH‹\$ H‹t$(H‹|$0HƒÄ8Àƒ|$`Xt¸úÿÿÿë×A€91uóM…Àu¸þÿÿÿëÅH…Étôƒúïƒú~êHƒy0HÇA uHësHÇA@H‰A0Hƒ{8u H ñsH‰K8ºH‹K@A¸èÿS0H‰Â¸üÿÿÿH…Ò„_ÿÿÿ¸‰ùH‰S(ÓàÇB€‰z(‰B,H‰r81ÀÇB4ÇB0é,ÿÿÿ€HìèH…ɸþÿÿÿL‰¤$ÈL‰¬$ÐI‰ÌL‰´$ØH‰œ$¨I‰ÖH‰´$°H‰¼$¸M‰ÅH‰¬$ÀL‰¼$àL‰Œ$uNH‹œ$¨H‹´$°H‹¼$¸H‹¬$ÀL‹¤$ÈL‹¬$ÐL‹´$ØL‹¼$àHÄèÃfDH‹i(H…ít©H‹1öHÇA ÇE ÇEÇE0H…ÀH‰„$t‹qH‹E8‹M,L„$º 1Û1ÿL‰D$@M‰÷H‰D$P‰L$LH…HHH‰D$XH‰L$`ƒê ƒúvH‹”$¸þÿÿÿI‰$A‰t$éÿÿÿH ‰ÒHcHÿàH‹”$¸ýÿÿÿëÏD‹E,D;D$L‡²H‹”$¸ë±ÇEf„ƒþv|$L‡½D‹Eh¸H‹UXD‰ÁÓàƒè!øH ‚¶AD¶ D·QD¶ðD9óƒ‰ðL‹t$@ëRH‹´$‰ÙƒÃƒèD¶HƒÆH‰´$¾AÓáD‰ÁÓæDÏNÿ!ùH жqD¶ D·Q@¶Î9Ù† …ÀuªL‰òL‰éAÿ×…ÀtiH‹UXD‹Ehë“f‰ÙƒãøƒáÓïƒû‡Ÿ‰ðL‹t$@ë0@H‹´$‰ÙƒÃƒè¶HƒÆH‰´$Óâ׃û‡d…ÀuÐL‰òL‰éAÿ×…ÀuÉÆ1Ò¸ûÿÿÿévþÿÿDƒû ‡«‰ðL‹t$@ë(H‹´$‰ÙƒÃƒè¶HƒÆH‰´$Óâ׃û wx…ÀuÔL‰òL‰éAÿ×…ÀuÇë ‹M…É…*ƒûf‡Á‰ðL‹t$@ë-H‹´$‰ÙƒÃƒè¶HƒÆH‰´$Óâ׃û‡‰…ÀuÐL‰òL‰éAÿ×…ÀuÃé;ÿÿÿ‰Æ‰ø‰ù‰úƒàÁéÁê ƒáƒâƒÁƒÂÁïƒë=‰Et‰Mx‰Up‡‚ƒù‡y1ÀL‹t$@ÇE|‰Á‰ð‰Îƒûw9…À„„H‹´$‰ÙƒèƒÃ¶HƒÆH‰´$‹u|Óâ׋UpH A‰ðA‰ùƒÆAƒáÁïF·Aƒë9Ö‰u|fF‰ŒEˆr“‰ò‰Æƒú‰Ðw‰ÂƒÀ·QƒøfÇ„Uˆvè‰E|L‹D$XHEhH€ÇEhH‰D$xH‰L$pL‰…€L‰EXL…ˆH‹L$xH‹D$`L‰„$€L‹L$pA¸H‹”$€H‰L$ 1ÉH‰D$(èYB…À„ÂLžM‰D$ ÇE‹Ué2üÿÿL‰òL‰éAÿ×…À…åþÿÿé­ýÿÿ‰Æ‰øD·÷Áè5ÿÿA9Æ„9LM‰D$ ÇEë´fLM‰D$ ÇEë‰ÙÇEƒãøƒáÓï늄‹D$L‹U,9U0L‹D$PA‰t$A‰D$H‹„$M‰D$I‰$‰}@‰]Ds ‰Ð+D$L‰E0L‰áè I‹L$E‹D$I‹$A‹t$‹}@‹]DH‰L$PD‰D$LH‰„$éÿÿÿA‰Î‰ñ‰Æ‰ÈE„É„<E¶ÁAöÀð…›E·ÒD‰T$pD¶ÐC A¸AÓàD‰ÁƒéA‰È‰L$h‰ÁA!øAÓèDD$pJ‚D¶@D¶D·XA¶ÀA 9˃ð‰ðD‰t$xH‰îD‹t$h‹l$pL‰d$hE‰Ôëbf.„L‹Œ$‰ÙƒÃƒèE¶IƒÁL‰Œ$AÓàD‰áDÇA‰øE!ðAÓèAèJ ‚D¶AD¶ D·YA¶ÈE A9Ú†]…Àu¤H‹T$@L‰éAÿ×…À„ŸH‹VX닉ƉøÑïƒà‰E‰øƒàƒø„ƒø„Ƀø„ØÇE Áïƒëé¿ýÿÿD+D$LH‹U8H‹Œ$ÿ”$…À…H‹”$°éßùÿÿE…öD‰uH„L‰d$h‹\$LL‹d$PëN…ÛtoD9ö‰ßH‹”$DFöL‰áA9ÞAFþA‰þ)þ)ûM‰ðMôèOÐL´$D‹uHA)þE…öD‰uH„³…öu¯H‹T$@L‰éAÿ×…À‰ÆužL‹d$h1Ò¸ûÿÿÿéNùÿÿ‹],L‹e8H‹Œ$‰]0A‰ØL‰âÿ”$…À„jÿÿÿL‹d$hH‹”$¸ûÿÿÿéùÿÿ‰ÁE·ÒD)óÓïD‰UH‹T$L…Ò„*H‹L$PDˆHƒÁƒl$LH‰L$PÇEé„üÿÿH‹”$¸ûÿÿÿéÁøÿÿL‰d$PL‹d$h‰\$LÇE 1Û1ÿéTüÿÿ‰ÁE·ÒD)óÓïD‰UHAöÀ t ÇE é3üÿÿAƒà@„èL? M‰D$ ÇEéüÿÿH H I‰L$ ÇEé/þÿÿLpHé ÇEh ÇElÇEL‰EXH‰E`éÿýÿÿÇEéóýÿÿE‰âD‹t$xL‹d$hH‰õ‰Æ‰ÈD‰ÑD)óE¶ÀÓï‰ÁD)ÃÓïE·ÓE„ÉD‰UH„ÓþÿÿE¶Áé7ÿÿÿ‹E,L‹E8H‹Œ$L‰D$P‰D$LA‰À‰E0H‹T$Pÿ”$…À…ÆþÿÿD‹UHé›þÿÿAƒáE…ÉD‰MPtnA9ÙvR‰ðL‹t$@ë,@H‹´$‰ÙƒÃƒè¶HƒÆH‰´$Óâ×D9Ës…ÀuÔL‰òL‰éAÿ×…À„°øÿÿD‹MP뽉ÆD‰É¸D)ËÓàƒè!øEHÓïD‹Ul¸H‹U`D‰ÑÓàƒè!øH ‚¶AD¶D·ID¶ðD9óƒ…‰ðH‹t$@ëYfDL‹Œ$‰ÙƒÃƒèE¶IƒÁL‰Œ$AÓàD‰ÑDÇA¸AÓàAHÿ!ùL ŠA¶IE¶E·ID¶ñA9Þv…Àu©H‰òL‰éAÿ×…À„å÷ÿÿH‹U`D‹Ul뎉ƉÈA¶ÈöÁð…ûD¶ÐA¸E·ÙA AÓàD‰ÁƒéA‰È‰L$h‰ÁA!øAÓèEØJ ‚¶AD¶D·I¶ÈA 9˃¦‰ðD‰t$xL‰d$pD‰ÞI‰ìE‰Ö‹l$hëYDL‹Œ$‰ÙƒÃƒèE¶IƒÁL‰Œ$AÓàD‰ñDÇA‰øA!èAÓèAðN ‚A¶IE¶E·ID¶ÑGA9Úv…Àu¨H‹T$@L‰éAÿ×…À„I‹T$`ëŽL‰åE‰òL‹d$pD‹t$x‰Æ‰ÈD‰ÑD)óÓï¶Ð‰ÁE¶ÀÓï)ÓAöÀ@„“L M‰D$ ÇEéÕøÿÿfƒú„°fƒú„YE¶ÀE‰ÄD‰„$ŒAƒÄD9ãr4éçfL‹„$‰ÙƒÃƒèA¶IƒÀL‰„$Óâ×D9ヸ…ÀuÏH‰òL‰éAÿ×…Àu‰ÆL‹d$h1Ò¸ûÿÿÿé ôÿÿ‰ðD‹EtH‹t$@ÇE|L‰d$h‹UxDÂ9U|ƒiD‹UhºL‹MXD‰ÑÓâƒê!úI‘D¶B·RE¶ðD9órUërf.„L‹„$‰ÙƒÃƒèA¶IƒÀL‰„$ÓâD‰Ñ׺Óâƒê!úI‘D¶B·RE¶ðA9Þv…Àu³H‰òL‰éAÿ×…À„ÏL‹MXD‹Uhë˜fƒú‡«þÿÿD‰ÁD)óÓï‹M|A‰ÈƒÁfB‰”Eˆ‰M|D‹Eté ÿÿÿAƒàE·ÉE…ÀD‰MLD‰EPuq‹E,1Ò9E0BT$LA‰ÀA)ÐD9EL†ÅHpI‰D$ ÇEé÷ÿÿH‹T$@L‰éAÿ×…À‰Æ„D‹EPH‹„$‰ÙƒîƒÃ¶HƒÀH‰„$Óâ×D9ÃG…öuÐ뵉Æé­ùÿÿ¶Œ$ŒºùÿÿÿE1ÒD)òÓ‹U|ÓïA‰ùÁïAƒáAƒÁ D‹Et‹MxAÑDÁA9ɇð‰ÑƒÂA9ÑfD‰”MˆuíD‰M|é)þÿÿA‰öD‹L$LH‹t$PE…É„ë‹UL)ÐA9Á†Ê‰ÂE‰ÈHA)À‹EHHJA9ÀDGÀD)ÀE‰ÃE)ÁAÁë‰EHHFE‰ÚAÁâH9—ÀH9ΗÁ ÈAƒø—Á„È„ÛE…Ò„Ò1À1ÉóoƒÁóHƒÀA9ËwêE‰ÓD‰ÁD)ÑLÚE9ÐJt(LRƒéI ë fDIƒÂ¶ˆHƒÀI9ÊL‰Òuë‹EHAƒèJt…ÀtP‹E,éÿÿÿ‰ÒH‰ñE‰ÈH)ÑH‰Êé/ÿÿÿH‹u8‰E0A‰ÀH‹Œ$‰D$8H‰òÿ”$…ÀD‹L$8….‹E,éàþÿÿH‰t$PD‰L$LD‰öéõÿÿE¶ÀE`D9ãr5ëSf.„L‹Œ$‰ÙƒÃƒèA¶IƒÁL‰Œ$Óâ×D9ãs …ÀuÓD‰D$8H‰òL‰éAÿ×…ÀD‹D$8u¼éUüÿÿ‹U|D‰ÁD)óÓï…Ò„A‰ùJÿÁïAƒáƒëD·”MˆAƒÁéïýÿÿD‰Á¸D)ÃÓàƒè!øÓïELé#ýÿÿE¶ÀE`D9ãr2ëo€L‹Œ$‰ÙƒÃƒèA¶IƒÁL‰Œ$Óâ×D9ãs?…ÀuÓD‰D$8H‰òL‰éAÿ×…ÀD‹D$8u¼é¥ûÿÿ‰ÆL‹d$p1Ò¸ûÿÿÿéEðÿÿ1Ò¸ûÿÿÿé9ðÿÿD‰ÁºýÿÿÿE1ÒÓïD)òA‰ùÓÁïAƒá‹U|AƒÁé-ýÿÿƒ}‰ÆL‹d$h„±óÿÿfƒ½ˆu7LfM‰D$ ÇEéóÿÿL‹d$hL.‰ÆM‰D$ ÇEépóÿÿH‹D$XH‹L$`L‹L$pH‹”$€ÇEh H‰…€H‰EXH‹D$xH‰L$(¹H‰D$ èl5…Àt8H I‰L$ ÇEéóÿÿD‰ÁH‰ðéRýÿÿD‰öH‹”$¸ûÿÿÿéAïÿÿH‹…€D‹Ex¹L‹L$pÇElH‰E`‹EtH”EˆH‹D$`H‰D$(HElH‰D$ èí4…À„EïÿÿH §I‰L$ ÇEéòÿÿffff.„S¸þÿÿÿH‰ËHƒì H…ÉuHƒÄ [ÄH‹Q(H…ÒtéL‹A8M…ÀtàH‹I@AÿÐHÇC(1ÀëÍAWH‰ÈAVAUATUWVSHì¨H‹Y(L‹!‹IL‹PIƒì‹{,‹k0ƒéIƒêD‹{4I L‰ÖL‹s8‰|$4‰l$XH‰L$ ‹H‹l$4L‰t$IƒîL‰t$(E‰þD‹CD)ÊéAÁîI H)ÖDýH‰t$P¾‹S@H‰L$‹Kh‰÷L‹[XL‹k`Óç‰ùƒé‰L$‹KlÓæ‰ñƒé‰L$LAOÿ‰l$\H‹|$(D‰t$8AÁæHƒÁD‰öD‰t$A‰îE·ÉAÓæD‰ñƒé!ÑF K4‹¶ND·N¶ùÓê¶A)ø…Éu¼IƒÂEˆ L;T$sL;d$ ‚@ÿÿÿD‰ÁÁé‰ÎÁáI)ôA)ÈIt$D‰ÁH‰0IrH‰p‹t$ ƒÆD)æ‰p‹t$ÆD)Ö‰p¸D‰CDÓàƒè!ЉC@HĨ[^_]A\A]A^A_ĉÎE·Éƒæt/D9ÆvIƒÄD‰ÁAƒÀA¶<$Óçú‰ñ¿A)ðÓçƒï!×ÓêAùAƒø†L‹L$L!ÑIt¶N·~ÓêA)ȶöÁuIöÁ@…sA¾ë öÁ@…bD‰ö·ÿÓæ‰ñƒé!Ñ<9It½¶N·~¶éÓê¶A)èöÁtȉÍ·ÿƒåD9Åv-IƒÄD‰ÁAƒÀA¶4$ÓæòD9ÅvIƒÄD‰ÁAƒÀA¶4$Óæò‰éA¾A)èAÓæAvÿ!ÖÓêD‰Ñ+L$Pþ9Άè‰õ)Í9l$Xs‹‹Ø…É…¸E…ÿH‹L$(…V‹|$4)ïHùA9é†<H|$A‰îA)éAÁîD‰´$ˆAÁæE…öD‰t$xH‰¼$€Iz„œL‹´$€ƒý—„$IƒÆL9÷Mr@—ÇL9´$€A—ÆD ÷@„¼$„]L‰¤$D‰Œ$˜1ÿL‹Œ$€D‹¤$ˆE1öóAo9AƒÆóAD:HƒÇE9æræ‹|$xL‹¤$D‹Œ$˜M4:HùL‰´$ˆA‰îD+t$x;l$xD‰´$€t6H‹¼$ˆAƒîL‰d$xHƒÇN47ëfHƒÇHƒÁL9÷D¶!Dˆ'uìL‹d$xƒí‰öMT*L‰ÑH)ñéfƒá t;Ç éýÿÿA¶t$D‰ÁIƒÄÓæAHAƒÀA¶4$ÓæòéŒýÿÿ„H íH‰H Çéºüÿÿf.„H=·H‰x Çéšüÿÿ‰öL‰ÑH)ñf¶qAƒéAˆr¶qHƒÁAˆr¶1IƒÂAƒùAˆ2wØE…É„JüÿÿHq¶IIƒÂAƒùAˆ …1üÿÿ¶NIƒÂAˆ é!üÿÿfD¶qAƒéAˆr¶qHƒÁAˆr¶1IƒÂAˆ2AƒùwØëžA9ïƒ ‹|$\L‹t$()ïD)ýIþA9é‰l$x†H|$A)éÁ퉬$€Áå…퉬$ˆH‰¼$Iz„ƒ|$xH‹¬$—„$˜HƒÅH9ïIj@—ÇH9¬$@—Å ï@„¼$˜„ÞL‰¤$˜L‹¤$1ÿ1íóAo<ƒÅóAD:HƒÇ;¬$€r㋼$ˆL‹¤$˜I,:Iþ‹¼$ˆH‰¬$‹l$x+¬$ˆ9|$x‰¬$€t=‹¬$€H‹¼$ƒíHƒÇH,/H‰¬$€ëHƒÇIƒÆA¶.@ˆ/H;¼$€uç‹l$xƒíE9ÏI|*ƒõIêE)ùƒ|$<Ij„þAƒÿMr—D$xH;l$h@—ÅL9t$A—ÆD õ@„l$x„ÑL‹t$1É1íóAoƒÅóAD HƒÁ;l$8ræE‰úD+T$Dˆ¼$°AÁïH‹T$pDˆ¼$±‹MA¸D‰T$8D‰\$@èdkÿÿD‹\$@D‹T$8‰EÇEE1ÿ1öéþÿÿƒþ†aþÿÿéŠþÿÿ„‹EöÄ„?ƒþw3E…í„\òÿÿ‰ñë E…í„e¶AƒíHƒÇÓâƒÁA׃ùv߉ηUD9ú„ôL†ìL‰C ÇEéLñÿÿD‰ÐA¾M‰âA‰Äéòÿÿ‹EöÄ„lE…í„åñÿÿE1ÉL‰d$hfDD‰ÈAƒÁ¶H‹E H…ÀD¶âtL‹@0M…Àt‹MH;H8s ‰ÈƒÁAˆ‰MHE…ätE9érÁöED‰d$XL‹d$h…Ñ‹D$XE)ÍE‰ÉLÏ…À…oñÿÿ‹EÇEéìþÿÿ‹EöÄ„ûE…í„KñÿÿE1ÉL‰d$hD‰ÈAƒÁ¶H‹E H…ÀD¶âtL‹@ M…Àt‹MH;H(s ‰ÈƒÁAˆ‰MHE…ätE9érÁöED‰d$XL‹d$h…q‹T$XE)ÍE‰ÉLÏ…Ò…Ûðÿÿ‹EÇEHÇEéÎþÿÿ‹E‰Ââ…Ò„µ‹MHA9ÍA‰ÉEFÍE…É„‘H‹U E‰ÈL‰„$˜H…ÒteL‹BM…ÀL‰D$XtW‹B‹RL‹„$˜D‰L$HD‰T$8D‰\$@)ÈA ‰L$h‰Ñ)Á9T$h‰ÀH‰úLGÁH‹L$XHÁèn¢‹ED‹\$@D‹T$8D‹L$HöÄ…€H¼$˜D)MHE)Í‹MH…É…ðÿÿ‹EÇEHÇEéþÿÿD‰ÐA¾ýÿÿÿM‰âA‰Äéßïÿÿ‹U…Ò„âƒþw2E…턽ïÿÿ‰ñë fE…í„o¶AƒíHƒÇÓàƒÁAǃùv߉ÎAÿ‹„sH‹E ÇEH…ÀtÇ@@ÿÿÿÿ€â„zD‰úD‰ø¹ÁâÁèâÿÿ1Ò÷ñ…Ò…TD‰øƒàƒø„‚HKéH‰S ÇEéYîÿÿ@E…Û„ïÿÿ‹EHAƒëAˆ$IƒÄÇEé1îÿÿ‹Eé'ûÿÿ@D‰Ð‰ÎM‰âA‰ÄéàîÿÿÇE ² éÿìÿÿƒè€1Òé’ïÿÿ‰ò‹MA‰ðH÷ÚHSèd_ÿÿéKïÿÿƒú„kïÿÿ1Ò@éeïÿÿ‹q…ö…Hìÿÿé¬ìÿÿH‹U H…Ò„ ýÿÿHÇB0éüüÿÿE‰Ô‰ÎL‹T$hébîÿÿH‹U H…Ò„týÿÿHÇB égýÿÿ‰Îé8îÿÿE‰ÉL‰âL)ÊD‹MHD‰ÈE9ÙHJEGËE‰ÈD)ÈE)ËAÁè‰EHD‰ÀÁàAƒù‰D$XID$—D$hH9—ÀI9Ì—Á È„D$h„Ù‹L$X…É„Í1À1ÉfDóoƒÁóAHƒÀA9Èwé‹L$XE‰ÈD+D$XHÊD;L$XI t$HJAƒèNëHƒÁ¶ˆHƒÀL9ÁH‰Êuë‹UHAƒéOd …Ò…œìÿÿéZþÿÿ‹U4A9цA)Ñ‹U,D)ÊHU8‹EHA9ÁDGÈé ÿÿÿ1öE1ÿH‹U H…ÒtÁø ÇB@ƒà‰B|$T‰D$$‡±ƒþ”D$?|$P‡°D‹D$ÇD$ ÿÿÿÿ1ÀE1äÇD$ @‰éL‹Œ$øE1ÛD(á‰Î‹L$ E·IA·Ê9L$åL‹l$0H‹L$(E·ÒG¶\UF·Q‰éA¹A½D)áA‰ÇAÓáD‰ÁAÓåD‰áE‰ÎAÓïD‰éD‰l$A÷ÞD)É„F,9DñN,«Eˆ]AˆufE‰UF, E…íußMÿA¹AÓáA…ÁD‰ÉtÑé…Áuú…É„=DIÿA!ÁA A‰éƒD$ B·LL`ƒéf…ÉfB‰LL`u9ý„µ‹L$ L‹”$øA· J·,J9l$ƒïþÿÿ‹t$$!Æ;t$ „ßþÿÿE…äDDd$A‰èE)àG A9ùsFE‰ÉD‰ÁAºF·LL`AÓâE)ÊGLE…ÒD‰ÑëE‰ÊÉAƒÁF·TT`D)Ñ…É~ AƒÀD9ÏwáA¹D‰ÁAÓáDL$|$T‡^|$P‡oL‹œ$è‹L$M‹H‹‰ñL EˆŠL‹¬$è¶L$M‹]CˆL M‹UH‰Ù‰t$ L)ÑHÁùfC‰L éþÿÿ1ÀéÇþÿÿf„E1ÒA»`é&þÿÿ·D$bAºA)Âé[ûÿÿƒþÇD$ÿÿÿÿ¸ED$L sÝL¬Ý‰D$HßÛIEÁH‰D$0HÜIEÂH‰D$(éýÿÿ€|$>¸„?ýÿÿéŒúÿÿ€|$?¸„@ýÿÿéwúÿÿ…Àt‰ÀHƒÆ@@ˆpfÇ@‹D$H‹´$èD‹T$L‹Œ$ðHÁàHE‰1Àé6úÿÿ¿éNúÿÿ¿ éDúÿÿ€|$>„—þÿÿ¸é úÿÿ¿ é%úÿÿ€|$?„†þÿÿëß¿ éúÿÿ¿ éúÿÿ¿ éúùÿÿƒÿu…ö…1ûÿÿƒÈÿéÃùÿÿ¿éÛùÿÿ¿éÑùÿÿ¿éÇùÿÿ¿é½ùÿÿ¿é³ùÿÿ¿½éÛùÿÿ¿éšùÿÿ¿éùÿÿ½é½ùÿÿAWMcØEÀAVAUATUWVSHƒìF‹¼™¨ ‹œMc÷A9À‰D$ N,²~Ié‹€IcÀD‹Œ¨ IcÁD·‚D‰ÀfE9Urg„}DD9D$ F‰Œ™¨ Œ¦LcØD9D$ ~¼A@HcðD‹Œ±¨ Icð‹´±¨ McáHcîF·¢·<ªfA9úr¤tLA‰úfE9UA‰ñD‰Às™F‰¼™¨ HƒÄ[^_]A\A]A^A_ÃIcñ¶œ1¤B8œ1¤‡jÿÿÿëÉDB¶¼!¤@:¼)¤DGÎAGÀé8ÿÿÿfLcØëŸff.„AWAVI‰ÖAUATUWVSH‰ËHƒìXH‹BH‹2‹hL‹ÇœÇ =…íŽkH‰ò¿ÿÿÿÿ1Àë6D‹»œƤHƒÂHƒÁƒÇ‰»œHcÿ‰„»¨ ‰ÇƒÀ9ètfƒ:uɃÀfÇBHƒÁHƒÂ9èuåM…Àu>éŽf.„McäB‰”£¨ fÇHcÒƒ«Æ„¤A·D)ƒD‹£œAƒüwAƒÄ1À1ÒƒÿD‰£œ°ƒÇHcljúHÁàë¢1É1À1ÒMcäB‰„£¨ fǃ«Æ„¤D‹£œAƒü"AƒÄƒÿD‰£œ½GHcЉÇH •ë±A‰~AÑüfDE‰àH‰òH‰ÙèRýÿÿAƒìuìHcÕ‹ƒœL$–ëƒÅHcЃèLc«¬ ‹”“¨ ‰ƒœA¸H‰Ù‰“¬ H‰òè ýÿÿ‹ƒ Lcƒ¬ PÿƒèJ †‰ƒ H˜HcÒD‰¬“¨ J®D‰„ƒ¨ ·ffA‰$F¶„¤F¶Œ+¤EPAAE8ÁLcÅABÂIƒÄBˆ„¤f‰iA¸f‰jH‰Ù‰«¬ H‰òèyüÿÿ‹ƒœƒø-ÿÿÿ‹ƒ Hc“¬ M‹ƒè‰ƒ H˜‰”ƒ¨ I‹FA‹NL‹8L‹`D‹p‹@fǃˆ fÇƒŠ fǃŒ fÇƒŽ fǃ fǃ’ fǃ” fǃ– fǃ˜ fǃš fǃœ fǃž fǃ  fǃ¢ fǃ¤ fǃ¦ fAÇD‹“ ‰T$(ƒÂú<‰T$$”E1íM…ÿA‰Ñ„¿‰|$,f.„IcÑ‹¼“¨ Lc×IÁâK,·UA·TƒÂ9Ð}AƒÅ‰Â9ùf‰U|CLcÚfBƒ„[ˆ E1ÛA9þ D)÷HcÿE‹¼·}A¯×“C·TA¯×“AƒÁAù=…xÿÿÿ‹T$$+T$(‹|$,Â<E…í„ÔD`ÿLcØMcôM‰÷F·Œsˆ D‰åM‰úfE…ÉuƒíLcÕF·ŒSˆ fE…ÉtëƒÅAƒéAƒíHcífF‰ŒSˆ fƒ„kˆ fBƒ¬[ˆ E…í§…ÀtjF·Œ[ˆ €E…ÉtHƒêHcꋬ«¨ 9é|êHcíI,¨D·UD9ÐtA‰ÃE)ÓE‰ÚD·]E¯ÓD“f‰EAƒéE…Éu¸ƒètLcØë™·ƒˆ Àf‰D$2fƒŠ Àf‰D$4fƒŒ Àf‰D$6fƒŽ Àf‰D$8fƒ Àf‰D$:fƒ’ Àf‰D$fƒ– Àf‰D$@fƒ˜ Àf‰D$Bfƒš Àf‰D$Dfƒœ Àf‰D$Ffƒž Àf‰D$Hfƒ  Àf‰D$Jfƒ¢ Àf‰D$Lfƒ¤ Àƒÿÿf‰D$NtR‰ÿH,½1ÿfD·T>…Òt.Hc·\D0·ËƒÃf‰\D01Ûf‰ÈÑéƒà ؃êuïÑëf‰>HƒÇH9ïuÀHƒÄX[^_]A\A]A^A_ÉÕë E1ÉAE· A¯Ñ“ƒÅý=tRHcÕD‹Œ“¨ IcÑMA·RA·TƒÂ9Ð}AƒÅ‰ÂD9ÉfA‰R|ÁLcÚfBƒ„[ˆ E9ΚE)ñMcÉG‹ Œë‘‹T$$+T$(Â<é`ýÿÿƒÏÿéêùÿÿfffff.„AWH‰ÈAVAUATUWVSHƒì·rƒþEÒAƒÂƒþÉჃÁE…ÀˆöE‰À1ÿE1ÉN,…A»ÿÿÿÿ»EA·l:A9È}9î„çE9Ðþ‹ˆD·LcæëmF·t˜D‹x(E‰óAÓãD‰ùE ÚL‹XfD‰Eˆ D¶˜AOL‹PAƒÇEˆ D‹˜‰ÙD‰x(D)ÙAÓþCLðAƒèE‰òfD‰°‰ˆt@Mœ$¨A‰ÞF·L˜E)ÎA9ÎŒvÿÿÿF·\˜AÓãDÉE ÚAƒè‰ˆfD‰uÀ…í„Ö9î„A‰óAº¹E1ÉHƒÇL9ï„Ήîéìþÿÿf„…ö„ÈA9ó„LcÖ‹ˆA‰ÛI¨F·DE)ÃD9ÙŽ*F·TL‹pE‰ÓAÓãD‰ÙD‹X(f ˆE‰Üf‰ˆCˆ &AKD¶°L‹`AƒÃEˆ4 D‰X(‰ÙD‹˜D)ÙAÓúD‰Ñf‰ˆCLð‰ˆD·€æ A‰ÛE)ÃA9Ë{D· ä D‹p(E‰ãAÓãD‰ñE ÚL‹XfD‰Eˆ D¶˜ANL‹PAƒÆEˆ D‹˜‰ÙD‰p(D)ÙAÓüCLðE‰âfD‰ ‰ˆƒùŽåAƒéD‹`(E·ÉE‰ÈAÓàD‰áE ÂL‹@fD‰EˆD¶AL$L‹@AƒÄEˆD‹€‰ÙD‰`(D)ÁAƒèAÓù…íD‰€fD‰ˆ…0þÿÿfDHƒÇE1ÉA‰óL9ïAº¹Š…2þÿÿHƒÄ[^_]A\A]A^A_ÃAƒø †D·ˆê ‹ˆA‰ÚE)ÊD9Ñ޹D·è L‹pE‰ÓAÓãD‰ÙD‹X(f ˆE‰Üf‰ˆCˆ &AKD¶°L‹`AƒÃEˆ4 D‰X(‰ÙD‹˜D)ÙAÓúD‰Ñf‰ˆCLðƒù ‰ˆŽpAƒèD‹`(E·ÀE‰ÁAÓáD‰áE ÊL‹HfD‰Eˆ D¶AL$L‹HAƒÄEˆ D‹ˆ‰ÙD‰`(D)ÉAƒé AÓøD‰ˆfD‰€éèüÿÿfDE‰Áéûüÿÿ„A‰ëAº¹E1ÉéÝüÿÿf.„AƒéE·ÉAÓáƒÁE щˆfD‰ˆéŽüÿÿD·˜ä AÓãDÁE Ú‰ˆfD‰éÊýÿÿ„D·ˆî ‹ˆA‰ÚE)ÊD9Ñ޳D·ì L‹pE‰ÓAÓãD‰ÙD‹X(f ˆE‰Üf‰ˆCˆ &AKD¶°L‹`AƒÃEˆ4 D‰X(‰ÙD‹˜D)ÙAÓúD‰Ñf‰ˆCLð‰ˆƒù ŽAƒè D‹`(E·ÀE‰ÁAÓáD‰áE ÊL‹HfD‰Eˆ D¶AL$L‹HAƒÄEˆ D‹ˆ‰ÙD‰`(D)ÉAƒé AÓøD‰ˆfD‰€ébûÿÿF·TAÓâfD A ‰ˆfD‰éüÿÿ„‹ˆD·E‰Áéüûÿÿf.„D·è AÓâfD A ƒù ‰ˆfD‰ýÿÿAƒèE·ÀAÓàƒÁE ЉˆfD‰€éÀúÿÿAƒè E·ÀAÓàƒÁE ЉˆfD‰€éœúÿÿf.„D·ì AÓâfD A ‰ˆfD‰é‘þÿÿfDAVH‰ÈAUATUWVS‹‰ô…ÉuMD·˜‹ˆ·š¾‰÷)ß9ÏŒ·’ÓâÙ[^_]A\A Ó‰ˆA]fD‰˜A^ˈD·˜E1ÉAºéƒHcöD‰×H4²·^)ß9ψ·6D‹`(‰÷ÓçD‰áA ûH‹xfD‰˜Dˆ¶¨E\$H‹xD‰ÑAƒÄBˆ,‹¸D‰`()ùÓþL;ðA‰óf‰°‰ˆD;ˆôƒ"ÿÿÿH‹˜øD‰ÎH‹¸èAƒÁ·s¶47…Û„XÿÿÿH-ÏHcþD¶d=D‰ÕA¼$‰ÿH<ºD·oD)í9ͧD·7‹h(D‰÷Óç‰éA ûH‹xfD‰˜DˆD¶˜MH‹xƒÅDˆ‹¸D‰Ñ‰h()ùAÓþAL=ðE‰ófD‰°‰ˆH-¢ÔD‰çD‹d½E…ätyH-Õ+t½D‰×D)ç9Ï<·öD‹p(‰÷ÓçA ûH‹xD‰ñfD‰˜Dˆ¶¨E^H‹xD‰ÑAƒÆBˆ,D‹¨D‰p(D)éÓþCL,ðA‰óf‰°‰ˆƒëûÿ‡H=æË‰Þ¶47‰öE‰ÔI<°·oA)ìA9ÌGD·'D‹p(D‰çÓçD‰ñA ûH‹xfD‰˜DˆD¶˜ANH‹xAƒÆDˆ‹¸D‰ÑD‰p()ùAÓüL=ðE‰ãfD‰ ‰ˆH=~Ô‹<·…ÿuW‹ˆD·˜éúýÿÿ@D·7AÓæDéE ó‰ˆfD‰˜é—þÿÿ·6ÓæÙA ó‰ˆfD‰˜é¹ýÿÿH-™Ô+\µD‰Ö)þ9Ψ·ÛH‹h‰ÞÓæA ó‹p(fD‰˜‰ñDˆ\ D¶˜NH‹hƒÆDˆ\ ‹¨D‰Ñ‰p()éÓûL/ðA‰Ûf‰˜‰ˆé>ýÿÿ„·?ÓçéA û‰ˆfD‰˜éþþÿÿ‰ÞH=WÊÁîÆ‰ö¶47écþÿÿ·ÛÓãùA Û‰ˆfD‰˜éÙüÿÿ·öÓæDáA ó‰ˆfD‰˜éþÿÿfD·‚‹P(DJD‰ÇÓç‰ÑƒÂA ûH‹xfD‰˜Dˆ¶¨‰ñH‹xBˆ,‰P(‹\ð)ÑAÓø‰˜fD‰€[^_]A\A]A^Ä‹SƒøŽÄ‹A(D·‘L‹I‰ÃEˆD¶‘XL‹IƒÀEˆ‰A(‹A(L‹IE‰ÃfÇÇfAÁë‰ÃEˆL‹QXE‰ÁA÷ÑEˆL‹YDPD‰ÃfAÁé÷ÓCˆL‹YDPƒÀE…ÀGˆ ‰A(t.LJEXÿOëIƒÁ¶L‹QA‰ÀƒÀM9ÙCˆ‰A(L‰Êuà[Ã…ÀŽbÿÿÿ‹A(D·‘L‹I‰ÃƒÀEˆ‰A(éBÿÿÿ@H¼HƒìfÇÇH‰@ Hä~H‰P H° H‰X Hè~H‰h H¤ H‰p Hì~H‰€ 1ÀfÇ„¼HƒÀH=xuêf1À€fÇ„° HƒÀHƒøxuì0Àf.„fÇ„¤ HƒÀHƒøLuìfǼÇÇÇÇôHƒÄÃfDSH‰È‹‰ƒù !E·ÉAÓáfD ˆƒÁ[‰ˆH‰ÁéÐýÿÿE·ÉD‹P(L‹XD‰ËÓã‰Ùf ˆD‰Óf‰ˆAˆ AJ¶˜L‹XAƒÂAˆ D‰P(¹D‹[D)ÑAƒê AÓùD‰H‰ÁfD‰ˆé_ýÿÿffffff.„Hƒì‹ƒøt4ƒø~*‹A(D·‰L‹A‰ÂƒÀEˆ fÁ©ƒ©‰A(HƒÄËA(D·‰L‹A‰ÂEˆ D¶‰PL‹AƒÀEˆ ‰A(fÇÇHƒÄÀSH‰È‹‰ƒù ŽpA¹‹X(L‹@D‰ÊÓâ‰Ñf ˆ‰Úf‰ˆAˆ SD¶€H‹HƒÃDˆ‹¹‰X()ÑAÓùJóE‰ÈfD‰ˆ‰ˆ·ÓÌA¹D‰Ë)Ó9ÙŽ’D·¶ÌL‹PD‰ÛÓãA Ø‹X(fD‰€‰ÙEˆ D¶KL‹@ƒÃEˆD‹D‰É‰X(BTðD)ÑAÓûƒúE‰ØfD‰˜‰tMƒú~"‹P(H‹X‰ÑƒÂDˆ fÁ¨ƒ¨‰P([ÃD· $̉AÓáE ȃúfD‰€u³‹P(H‹X‰ÑDˆ D¶€JH‹XƒÂDˆ ‰P(fǀǀ[ÃA¸AÓàfD €ƒÁ‰ˆfD‰€éÎþÿÿfDAUATUD‰ÅWD‰ÏVH‰ÖSH‰ËHƒì(D‹¬E…ÀŽ˜L‹AƒxH„šH“@ H‰ÙL£¼è„èÿÿH“X H‰Ùèuèÿÿ·‹¾‹ƒH HcЃùfÇ„“ÂÿÿEÒAƒÂƒùEÉAáƒAƒÁ…Àˆ§‰À1ÒA»ÿÿÿÿL,…1Àë9fLcÉfB„‹¤ E…ÀtdA9È„ÜA‰ËAºA¹1ÀHƒÂL9êt[D‰ÁƒÀE·DD9È}A9ÈtáD9Ð|±…É„D9Ùt HcÁfƒ„ƒ¤ fƒƒä E…ÀuœHƒÂ1ÀA‰ËL9êAºA¹Šu¥·‹² ‹ƒ` L£° HcЃùfÇ„“¶ ÿÿEÒAƒÂƒùEÉAáƒAƒÁ…Àˆ¬‰À1ÒA»ÿÿÿÿL,…1Àë>€LcÉfB„‹¤ E…ÀtdA9È„(A‰ËAºA¹1ÀHƒÂL9êt[D‰ÁƒÀE·DA9Á~A9ÈtáA9±…É„ÙD9Ùt HcÁfƒ„ƒ¤ fƒƒä E…ÀuœHƒÂ1ÀA‰ËL9êAºA¹Šu¥H“p H‰Ùè’æÿÿfƒ»â A¹…Ùfƒ»ª A±…Èfƒ»Þ A±…·fƒ»® A±…¦fƒ»Ú A±…•fƒ»² A± …„fƒ»Ö A± uwfƒ»¶ A± ujfƒ»Ò A± u]fƒ»º A± uPfƒ»Î A±uCfƒ»¾ A±u6fƒ»Ê A±u)fƒ»Â A±ufƒ»Æ A±ufƒ»¦ EÉAƒÁ‹“AƒÁCID‹“‰ƒƒÀ ƒÂ ÁèÁê9ÐCÂM9Á†9Â…˜‹‹ƒù ÑG·ÀÓàf ƒƒÁ‰‹L…ÈHþÃH‰Ùè¶òÿÿ1À@fÇ„¼HƒÀH=xuêf1À€fÇ„° HƒÀHƒøxuì0Àf.„fÇ„¤ HƒÀHƒøLuì…ÿfǃ¼ǃǃǃǃôtN‹ƒƒøŽ1‹C(·³H‹K‰Â@ˆ4¶³PH‹KƒÀ@ˆ4‰C(fǃǃHƒÄ([^_]A\A]Ãø #fƒƒè éüÿÿE‰ÃAºA¹1Àéüÿÿfƒƒì éóûÿÿ€ƒø #fƒƒè éÊüÿÿE‰ÃAºA¹1ÀéÓüÿÿfƒƒì é§üÿÿƒ»°„[þÿÿ‹‹ƒù G·ÀÓàf ƒƒÁ‰‹f‰ƒD‹ƒH ƒù D‹£` APŽ‚A°ÿÿÿ‹S(H‹k·öA‰òAÓâ‰ÑD Ðf‰ƒˆD B¶«L‹SƒÂ¹Aˆ,‰S(‹“)ÑÓþJõ‰ðf‰³‰‹ƒù Žü‹S(A·ôH‹kA‰òAÓâD ЉÑf‰ƒˆD B¶«L‹SƒÂ¹Aˆ,‰S(‹“)ÑÓþJõ‰ðf‰³‰‹ƒù ŽyAQüH‹k·Ò‰ÖÓæ‹K( ðf‰ƒ‰ÎDQƒÁˆD5¶«H‹sBˆ,‹ƒ‰K(¹)ÁÓú‰Ñf‰‹Hô‰‹H-ÆAƒéH ÆLÍA¹ëz¶0L‹[HƒÀ·´³¦ A‰òAÓâD ÒD‹S(f‰“D‰ÑAˆ D¶›ARH‹KAƒÂDˆ‹“D‰ÉD‰S()уê ÓþH9艓f‰³t:·“‹‹ƒù ‚¶0HƒÀ·´³¦ ÓæƒÁ òH9艋f‰“uÆH³¼H«° H‰ÙH‰òè1èÿÿE‰àH‰êH‰Ùè#èÿÿI‰èH‰òH‰Ùèåîÿÿé*üÿÿH…ö„Üûÿÿ‹‹ƒù ·ÇÓàf ƒƒÁ‰‹A‰èH‰òH‰ÙèUóÿÿéêûÿÿUA¹‰ÐéŠûÿÿ¸ ºÀÿóë@ÑêöÂtfƒ¹¼… HƒÁƒèuâHºÿÿÿÿH…“à¸u.fƒ»ðu$1ÀëHƒÀH=€„Ñfƒ¼<tå¸A‰@Héé÷ÿÿW‹C(H‹k·Ò‰ÖD@Óæ‰ñf ‹‰ÆƒÀf‰‹ˆL5¹¶«H‹sBˆ,‰C(‹ƒ)Áƒè Óú‰ƒf‰“éãúÿÿG‹S(H‹k·À‰ÆDBÓæ‰ñf ‹‰ÖƒÂf‰‹ˆL5¹¶«H‹sBˆ,‰S(‹“)ÑÓø‰Áf‰‹Jó‰‹é)üÿÿ·×L‹K‰ÐÓà‰Á‹C(f ‹A‰Àf‰‹Cˆ HD¶‹L‹CƒÀEˆ ‰C(¹‹ƒ)Áƒè Óú‰ƒf‰“é4þÿÿ…ÀŽóúÿÿ‹C(·³H‹K‰ÂƒÀ@ˆ4‰C(éÔúÿÿAQü·ÒÓâƒÁ ‰‹f‰“éÂüÿÿA·ÔÓâƒÁ Љ‹f‰ƒéAüÿÿfê·ÒÓâƒÁ Љ‹f‰ƒé½ûÿÿ1Àé?þÿÿf1Àé7þÿÿHƒì‹ôL‹‘øA‰ÁƒÀ…ÒfC‰JL‹‘èGˆ ‰ôtoL X¼E‰ÀƒêƒG¶fBƒ„Àúÿw4L-º‰ÒA¶HcÒfƒ„‘° ‹‘ðƒê9ДÀHƒÄ¶ÀÃ@ÁêÂëÁDE‰ÀfBƒ„¼ëÇHì˜H‰œ$€H‰´$ˆHt$ H‰¼$‹H‰ÓH0ÄL‰D$ H‰L$0A¸XH‰ñD‰L$(‰D$8HÇD$PHÇD$Xèý®ÿÿ…À‰Çt'‰øH‹œ$€H‹´$ˆH‹¼$HĘÃDºH‰ñèC°ÿÿƒø‰Çu‹D$Íÿÿ‰Çë³H‰ñè2Íÿÿƒÿtƒÿûu¡ƒ|$(¸ýÿÿÿDøë’¿ýÿÿÿë‹HƒìH…ÃHƒÄÃHƒì¸eHƒÄÃf¸H´oHƒì)ÈH˜H‹ÂHƒÄÃD‰ÁHƒì¯ÊHƒÄé]dffff.„HƒìH‰ÑHƒÄéXdSH‰ËHƒì0H‹ ‘áèlHƒøÿH‰D$(tv¹èdH‹ páèKH‹ láH‰D$(è:HT$(LD$ H‰ÙH‰D$ ècdH‹L$(H‰Ãè&H‹L$ H‰*áè¹H‰!áè@éeÿÿÿSH‰ÓHƒì ‹BöÄ@u‹R$9S(~öÄ u#HcC$H‹ˆ ‹S$ƒÂ‰S$HƒÄ [Ãf.„H‹è L‹S$ƒÂ‰S$HƒÄ [Ãf„AVAUATUH‰ÍW‰×1ÒVSL‰ÃHƒì@Ld$HЃàH)ÐHƒøu£Æ,HƒÆëšf.„‹C…À~*ø)ð…À~"HÿH‰ðHTfDÆ0HƒÀH9ÐuôHtH9þ„f‹S …Ò~Yú)ò…Ò‰S ~N‹C©Àtƒê‰S ‹S…ÒˆÝöÄu1‹S Jÿ…Ò‰K ~$€H‰Ú¹ èƒûÿÿ‹C Pÿ…À‰S æ‹C¨€t_Æ-HƒÆH9þv1HƒîH‰Ú¾èQûÿÿH9÷rì‹C Pÿ…À‰S ~H‰Ú¹ è2ûÿÿ‹C Pÿ…À‰S æHeè[^_ÉÃH‰þé”þÿÿ@öÄt+Æ+HƒÆëšf‰ðºVUUU÷ê‰ðÁø)ÂÖé þÿÿf„¨@„pÿÿÿÆ HƒÆédÿÿÿ‰Ââú…ÿÿÿ‹S Jÿ…Ò‰K Ž4ÿÿÿ€Æ0‹C HƒÆPÿ…À‰S ìéÿÿÿ€I‰ÈI÷ØéßýÿÿD‹K…É„þÿÿÆ0HƒÆéƒþÿÿf„UA‰É¸AºH‰åAUATWH‰×VL‰ÆSH‰ÓHƒì(ƒùoD‹^•ÁDDÐ0ÀD¶Á¶ÉƒÁE…ÛIFFÅAÂöF t fƒ~ …‹F A9ÂAMÂH˜HƒÀHƒàðèù÷ÿÿH…ÿLl$ „D‰ÈL‰ïƒà ‰ÚD!ÂA‰ÒAR0ˆHƒÇ€ú9~ AƒÂ7A ÂDˆWÿHÓëH…ÛuÖI9ý„΋F…ÀŽOD‰é)ø…ÀŽ?XÿH‰øHT@Æ0HƒÀH9ÐuôH|L9ï„(D‹f ‰ø)ÈA9ÄŽåA)ÄE…äD‰f ~"AƒùotöF t AƒìE…ä~D‹FE…ÀˆA\$ÿAƒùotöF t DˆÆG0HƒÇA\$ÿE…ä~0öF u%A‰Ü„AƒìH‰ò¹ è¿øÿÿAD$…ÀæA\$ÿL9ïvHƒïH‰ò¾èøÿÿI9ýrìE…ä~ƒëH‰ò¹ è€øÿÿC…ÀéHeØ[^_A\A]ÉÃD‰ÐºVUUU÷êD‰ÐÁø)ÂAÒéeþÿÿfÇF ÿÿÿÿ»þÿÿÿA¼ÿÿÿÿé7ÿÿÿf„AƒùotzL9ïD‰é…ØþÿÿD‹VE…Ò„ËþÿÿÆ0HƒÇé¿þÿÿD‹F%=…æþÿÿAƒìH‰øJT'Æ0HƒÀH9ÐuôJ|'»þÿÿÿA¼ÿÿÿÿé½þÿÿL‰ïfÿ÷ÿÿé&þÿÿöF t€Æ0HƒÇétÿÿÿfffff.„UH‰åHƒìPH‰]àH‰uèH‰ËH‰}ðL‰eøƒyý„›·Qf…ÒtbHcCH‰æHƒÀHƒàðèsõÿÿ·SH|$ LEØÇEØH‰ùè²-…À~ND$8f.„¾H‰ÚHƒÇè÷ÿÿD‰à)ø…ÀèH‰ôëH‰Ú¹.èóöÿÿH‹]àH‹uèH‹}ðL‹eøÉÃH‰Ú¹.èÓöÿÿëÉÇEØè4CH‹HMÞLMØA¸èþ/…À~·UÞf‰S‰Cé3ÿÿÿ·Sëò@ATUL‰ÍW‰ÏVH‰ÖSD‰ÃHƒì E…ÀŽbA‹I A9È}+D)ÁA‰I …Éx ‹E9È})Á…ɉM ~…ÀŽæƒé‰M ë ÇE ÿÿÿÿ¹ÿÿÿÿ…Û~ öE …x‹M …É~…ÿ„ƒé…ɉM t ‹EöÄ„…ÿ…9‹EöÄ…¨@…g‹U …Ò~‹E%=„ …ÛŽ3Le ¿VUUU¶¹0„Àt¾ÈHƒÆH‰êèõÿÿƒëu[‹E…ÀŽ=H‰éèõýÿÿ…Û‹Et,é;f„¶¹0„Àt¾ÈHƒÆH‰êèUõÿÿ‹EPÿ…À‰UØHƒÄ [^_]A\ÃöE t'fƒ} t ‰Ø÷ï‰ØÁø)ÂR9Ó„*f.„…ÛPÿÿÿékÿÿÿ‹E©À…ÝþÿÿöÄ…êþÿÿƒé‰M H‰ê¹ èÓôÿÿ‹E Pÿ…À‰U æ…ÿ„ÇþÿÿH‰ê¹-è±ôÿÿéÉþÿÿfƒ} „}þÿÿDCºVUUUD‰ÀAÁø÷êD)ƒê…ÒŽ]þÿÿ…Ééyþÿÿ„…ÉŽƒêƒé…Òî‰M é5þÿÿfDöE …¹þÿÿ…Û„ìþÿÿ؉Ef„H‰ê¹0è#ôÿÿƒÃxîéÄþÿÿf„A‹I …ÉŽ¢ýÿÿƒéA‰I éšýÿÿ„I‰èºL‰áè@ôÿÿéËþÿÿH‰ê¹+èÎóÿÿéæýÿÿf„ƒê‰U f.„H‰ê¹0è£óÿÿ‹E Pÿ…À‰U æ…ÛÍýÿÿH‰ê¹0èóÿÿéäýÿÿH‰ê¹ èoóÿÿé‡ýÿÿf.„öE „$ýÿÿfDéýÿÿ‰M éDýÿÿWAxÿA¸gfffI‰Ò‰øVHc÷A÷è‰ø¿SÁøL‰ËA‰ÐHƒì AÁøA)Àt#A¹gfffDD‰ÀAÁøƒÇA÷éÁúD)ÂA‰Ðuè‹C,‹S 9ÇLøƒÇ9úVÇC ÿÿÿÿI‰ÙL‰ÒA¸è.üÿÿ‹K‹C,H‰ÚÉÀ‰C‰Kƒá ƒÉEèžòÿÿ‹C H‰ÚH‰ñ|ÿ‰{ è‰õÿÿHƒÄ [^_Ã)ú‰S ëªf„HƒìxH‰\$`H‰t$hH‰ÓH‰|$pD‹BH‹1‹yE…Àx{AƒÀH‰t$@H‹D$@HT$0‰|$HLL$X¹H‰D$0H‹D$HH‰D$8HD$\H‰D$ è,ñÿÿD‹D$XH‰ÆAø€ÿÿt=‹L$\I‰ÙH‰Âè¬þÿÿH‰ñèÔ-H‹\$`H‹t$hH‹|$pHƒÄxÃÇBA¸éwÿÿÿ‹L$\I‰ØH‰ÂèôÿÿëÁffff.„WVSH‰ÓHƒì`D‹BH‹1‹yE…Àˆ“H‰t$@H‹D$@HT$0‰|$HLL$X¹H‰D$0H‹D$HH‰D$8HD$\H‰D$ èhðÿÿD‹D$XH‰ÆAø€ÿÿtY‹L$\I‰ÙH‰Âè˜úÿÿëfDH‰Ú¹ èñÿÿ‹C Pÿ…À‰S æH‰ñèî,HƒÄ`[^_ÃfDÇBA¸é[ÿÿÿ‹L$\I‰ØH‰Âè?óÿÿH‰ñè·,HƒÄ`[^_Ãffffff.„WVSH‰ÓHƒìpD‹BH‹1‹yAƒøŒ2„ H‰t$PH‹D$PHT$@‰|$XLL$h¹H‰D$@H‹D$XH‰D$HHD$lH‰D$ èqïÿÿD‹D$hH‰ÆAø€ÿÿ„üAƒøý|v‹CA9ÀnöC …ÖH‰ñD‰D$8èÿ;D‹D$8D)À…À‰CˆÕ‹L$lI‰ÙH‰òèeùÿÿëH‰Ú¹ èãïÿÿ‹C Pÿ…À‰S æH‰ñè¾+HƒÄp[^_ÃfDöC uLH‰ñD‰D$8è•;D‹D$8ƒè‰C‹L$lI‰ÙH‰òèSüÿÿH‰ñè{+HƒÄp[^_ÃÇBA¸éâþÿÿƒkëÆ„ÇBA¸éÂþÿÿD)À‰Cé?ÿÿÿ‹L$lI‰ØH‰Âè¡ñÿÿ뜋S …ÒŽ ÿÿÿЉC éÿÿÿf.„AUATUWVSH‰ÓHƒìhÛ)ÙÀÛ|$@Ùå›ßà%E=„Ê·|$H‰ùစ&Ùå›ßàÝØ%E=„¸fçÿ„H‹T$@fïÿ?‹CƒøwGH…Òx „HÒyûH‰Öº)ÂHÑî •ºHÓâHòˆDHÒ¹)ÁÁáHÓêH…Ò„_D‹SHl$ H‰îD‰ÐE‰Ñƒà AáA‰Àë/‹K…É~ƒé‰KHÁê…ÀtYƒø ~bƒÀ7D ÀˆHƒÆH…Ò„Ž‰Ðƒà9ÐuÈH9îwE…Éu D‹kE…í~Æ.HƒÆHƒúvHÑêƒïHƒúwô1Ò…Àu§H9îw D‹cE…äxªƒÀ0ëŸJ€éÎþÿÿH‹T$@1ÿHƒú„éþÿÿ¿ÀÿÿŒÞþÿÿ¸Àÿÿ‰ÇƒèHÒyöéÊþÿÿH9D‹k E‰ÓA¼E…펊‹S‰ðD¿Ï)èE‰ÓA¼ …ÒD‰ÒOÁâÀƒúºgfffEÀFDD‰ÈAÁù÷êÁú‰ÑD)Ét!A¹gffff‰ÈÁùAƒÀA÷éAƒÄÁú)ʉÑuçE9ÅŽCE)ÅAâD‰k „ME¿äAöÀ…-A÷Ã…iAƒã@…qH‰Ú¹0è˜ìÿÿ‹KH‰Úƒá ƒÉXè‡ìÿÿ‹C …À~*öC t$ƒè‰C @H‰Ú¹0ècìÿÿ‹C Pÿ…À‰S æH9îLl$^w#ëIf.„·C f…Àf‰D$^…~H9îv(Hƒî¾ƒù.t^ƒù,tØH‰ÚèìÿÿëàH‰Ú¹0èìÿÿ‹CPÿ…À‰Sæ‹KH‰Úƒá ƒÉPèãëÿÿDc KÀH¿ÏH‰ÚèÌîÿÿHƒÄh[^_]A\A]ÃH‰Ùè'ôÿÿë‡DI‰ØºL‰éèìÿÿémÿÿÿÇC ÿÿÿÿéÅþÿÿH‰Ú¹-è‚ëÿÿéØþÿÿAEÿE…í‰C Ž£þÿÿH‰Ú¹ è`ëÿÿ‹C Pÿ…À‰S æD‹[E¿äé€þÿÿH‰Ú¹+è9ëÿÿéþÿÿH‰Ú¹ è'ëÿÿé}þÿÿƒÇé·üÿÿÝØI‰ÐHe—1Éèwíÿÿé6ÿÿÿHV—I‰Øècíÿÿé"ÿÿÿD‹SHl$ …À~HuHEÆD$ .Æ0éfýÿÿ‹CëâA÷ÂHuH‰ètãëÔDAWAVAUA‰ÍAå`ATUWD‰ÇVH‰ÖSL‰ËHì¸H‹¬$ è}6‹H â–‰D$Dèã6H…À„’¾¸ƒê0ƒú‡~H”$¨‰¼$˜H‰t$pD‰l$xÇD$|ÿÿÿÿH|$pÇ„$€ÿÿÿÿÇ„$„ýÿÿÿL5“–fÇ„$ˆÇ„$ŒfÇ„$Ç„$”‰„$œ¶H‰T$PH”$®H‰T$HHT$`H‰T$0D‰ê€Î‰T$\H”$ H‰T$8@¾È…É„¥HƒÃƒù%…ÊD‰l$xÇ„$€ÿÿÿÿLW ÇD$|ÿÿÿÿ¶H‰ÞE1ÿE1ä„Àt^¾Èƒè HƒÆõÿÿ¶é6ýÿÿfD‹D$xH‰óƒÈ ¨‰D$x„ùH‹ELe‹PH‹‰T$hH‰D$`H‹L$0H‰úL‰åè#ôÿÿ¶éëüÿÿAƒïH‰èÇ„$€ÿÿÿÿAƒÿ†Ê‹H‹L$8I‰øºHƒÅH‰óˆ„$ è½çÿÿ¶é¥üÿÿDL$x€Aƒÿ„Aƒÿ„mHcEAƒÿHUH‰„$ „ÆAƒÿH‰Õ„)H‹Œ$ H‰úH‰óèêèÿÿ¶éBüÿÿfAƒÿ„¨Aƒÿ„GHE‹mAƒÿH‰¬$ „ˆAƒÿH‰Å„èƒùut¤H‹”$ I‰øH‰óè>ëÿÿ¶éæûÿÿfD‹D$xH‰óƒÈ ¨‰D$x„ H‹ELe‹PH‹‰T$hH‰D$`H‹L$0H‰úL‰åè3öÿÿ¶é›ûÿÿƒL$xA¼¶éÈûÿÿ„Aƒü†¶A¼é¨ûÿÿ„E…ä…òûÿÿL$x¶é‡ûÿÿ€E…ä…ÒûÿÿL$x¶égûÿÿ€M…Òt¥E…ä”ÀAƒü…-‹MHU…ÉA‰ ˆ†¶H‰ÕE1Òé+ûÿÿE…ä…}ûÿÿL‰T$(L$xÇ„$¨èÕ0L‹L$PA¸H‹PH‹L$H蜅ÀL‹T$(~·”$®f‰”$‰„$Œ¶éÄúÿÿ@H‰úH‰óèäÿÿ¶émúÿÿE…ä…ÿúÿÿL$x¶é”úÿÿ@E…ä…âúÿÿƒL$x@¶ézúÿÿf.„‹D$xH‰ó¨…ýÿÿÝELeÛ|$`éýÿÿÇ„$€ÿÿÿÿ‹EH‹L$HH]I‰øºH‰ÝH‰óf‰„$®èÞãÿÿ¶éÖùÿÿfD‹D$xH‰ó¨…÷ýÿÿÝELeÛ|$`éþýÿÿE…ä…ýùÿÿL$x¶é×ùÿÿ€‹D$xH‰ó¨…×ûÿÿÝELeÛ|$`éÞûÿÿ‹D$xH‰ó¨…üûÿÿÝELeÛ|$`éüÿÿ¶<6„€<3„A¿A¼élùÿÿH]H‹mHH…íHDèH‰éè./H‰é‰ÂI‰øèãÿÿH‰Ý¶H‰óéóøÿÿAƒü¸DDàé_ùÿÿ„À…Ëýÿÿ¶E1ÒA¼éùÿÿ€~4„²A¿A¼éîøÿÿH‹E‹”$”HƒÅH‰óˆ¶éŽøÿÿH‹EHƒÅH‰„$ ésüÿÿH‹EHƒÅH‰„$ éüÿÿÇ„$€LW¶A¼釸ÿÿƒé0A‰ ¶éyøÿÿ€~2…tÿÿÿHƒÆA¿A¼¶éWøÿÿHcEHƒÅH‰„$ é¥ûÿÿH‹E‹”$”HƒÅH‰óf‰¶éå÷ÿÿ‹UHƒÅH‰”$ éËûÿÿ‹D$\Ç„$€‰D$xéùøÿÿH‰ú¹%èLáÿÿ¶é¤÷ÿÿH¿„$ H‰ÕH‰„$ é.ûÿÿ·”$ H‰ÅH‰”$ émûÿÿ„Àt~L$x÷\$|H‰Õ¶E1ÒE1äé’÷ÿÿHc”$”H‹EH‰óHƒÅH‰¶é4÷ÿÿH¾„$ H‰„$ éÁúÿÿ¶„$ H‰„$ éûÿÿHƒÆA¿A¼¶é1÷ÿÿÇ„$€ÿÿÿÿéèûÿÿHìH‰œ$ØH‰´$àL‰ÃH‰¼$èH‰¬$ðH‰ÎL‰¤$øL‰´$E1äL‰¬$L‰¼$‰×f´$ÀA‹L‰ÍA‰ÆƒàAƒæÏƒøE‰1wHމÀHc‚Hÿâf.„I‰ÆA¶VÿIFÿ€ú9…’L9àuæAƒÂAÆ$0º1Azˆ» L‰éèå AÆHƒ¼$XH‹Œ$P‰9t H‹„$XL‰0 ]L‰àfo´$ÀH‹œ$ØH‹´$àH‹¼$èH‹¬$ðL‹¤$øL‹¬$L‹´$L‹¼$HÄÃf.„D‹1ÉAƒø ~¸ ÀƒÁA9ÀöD‰D$0è<D‹D$0I‰ÅMUA@ÿL‰ÒÁøH˜L ƒH‰Ø‹HƒÀ‰ HƒÂI9ÁsïL)ÒHÁêBÿHcÒIT•f.„D‹ HE…É…TƒèHƒêƒøÿuåAÇEÇD$hL‰éD‰D$0èØ(…À‰„$¼A‰ûD‹D$0…ñE‹}E…ÿ…˜L‰éèŒH‹Œ$PH‹”$XA¸ÇH FŒèÔI‰ÄéžþÿÿH‹”$PH &ŒA¸Ç€ÿÿH‹”$Xè¤I‰ÄénþÿÿH‹„$PH‹”$XH å‹A¸Ç€ÿÿètI‰Äé>þÿÿH”$¼L‰éD‰D$0D‰\$8èâ$‹L$hòD$(D‹\$8H‹T$(D‹D$0AD ÿH‰ÑI‰ÒHÁé Aƒâÿáÿÿò*ÈÉð?I‰ÉIÁá M ÊA‰ÁL‰T$(AÁùòD$(D‰Ê1Âò\u‹D)Êê5…ÒòY z‹òYb‹òXb‹òXÁ~ò*ÊòY `‹òXÁò,ÐfWöf.ð‰T$dvò*Êf.Èztƒl$d‰ÂAƒâÿÇ„$¤ÁâÊHÁâ I Òƒ|$dL‰Òw7LcL$dH ŒL‰T$(òL$(òBÉf.Á†çƒl$dÇ„$¤‹L$hÇ„$€ƒé)Á‰L$pˆùD‹d$dE…äˆÇ‹L$dL$pÇ„$œ‰Œ$ ƒ¼$@ ‡ÿƒ¼$@Žüƒ¬$@1Àƒ¼$@„y óƒ¼$@„ òA*ÀE1ÉÇ„$¨Ç„$¬ÿÿÿÿA¿ÿÿÿÿÇ„$HòYŠò,ȃÁ‰Œ$¼H‰T$HD‰D$0DˆL$PL‰T$@D‰\$8èI‰Ä‹F H‹T$HD‹D$0D¶L$PL‹T$@D‹\$8ƒèƒø‰D$|t!¸MD$|Aƒæ‰D$|t ¸+D$|‰D$|E„É„<‹D$| D$d….‹Œ$¤L‰T$(Ç„$¼òd$(…É„mE…ÿŽdò`‰f.ĆR‹”$¬…ÒŽÓò G‰‹Œ$¬AºÿÿÿÿòYÌf(ÁòL$(H‹T$(òY'‰òX'‰òD$(L‹L$(L‰ÈAƒáÿHÁè -@HÁà I Á‹„$¨…À„Ÿ QÿH܉L‰L$(òÿˆÇ„$¼HcÒòT$(ò^Ðò,ÁMt$ò\Âò*ЃÀ0Aˆ$ò\Êf.Á‡ò-€ˆf(Õò\Ñf.‡)úÿÿ‹„$¼ƒÀ9Á‰„$¼ŽáòUˆë.f(Õò\Ñf.‡ñùÿÿ‹„$¼ƒÀ9Á‰„$¼Ž©òYËòYÃò,Áò*ЃÀ0AˆIƒÆò\Êf.Áv±f.Ίù…óAz1ÛéÉùÿÿfD‰ÂL‰éèÖ"‹„$¼D‹D$0)D$hDéìúÿÿH˜A‰MÁáA½D…ƒð)Á‰L$hé«úÿÿÇ„$@þ=÷–À¶Àéùüÿÿƒ¼$@„dƒ¼$@…ÿüÿÿÇ„$¨‹L$dŒ$HA‰Ï‰Œ$¬AƒÇE…ÿD‰¼$¼ŽP AƒÿD‰ùA–ÁA!ÁéüüÿÿÇ„$¤éüÿÿf(ÄòXÄòX ‡òD$(L‹L$(L‰ÈHÁè ˆÀüL‰ÈƒàÿHÁá H ÈE…ÿI‰Á…S f(ÄH‰D$(òL$(ò\̆f.Á‡A ò†HÇ„$HÇ„$ˆfWÊf.ȇ\òd$(H‹T$(E…ۈɋD$d;F¼HcÈHP‡E…ÿòÈ‹„$HÁè„À„°E…ÿ… òY7†H‰T$(òD$(HÇ„$HÇ„$ˆf.Ѓҋ|$dƒÇMt$AÆ$11ö» H‹Œ$èHƒ¼$ˆ„¡÷ÿÿH;´$ˆ…BH‹Œ$ˆèsé÷ÿÿD‹´$¨E…ö„ÍD+D$h‹VD‰ÙA@D)Á9щ„$¼|ƒ¼$@„nƒ¼$@„`A)ÓE…ÿAC‰„$¼~ƒ¼$@~ A9ÇŒXD‹„$œD‹´$€f.„¹D‰D$0„$€D$pèÆD‹D$0H‰„$ˆD‹\$pE…Û~'E…ö~"D9t$p‹D$pAOÆ)„$€)D$p‰„$¼A)ÆD‹”$œE…Ò~hD‹Œ$¨E…É„E…À~BH‹Œ$ˆD‰ÂD‰D$0è L‰êH‰ÁH‰„$ˆèmL‰éH‰D$Pè0H‹D$PD‹D$0I‰Å‹”$œD)Â…Å¹è ‹Œ$ H‰„$…É~‹”$ H‰Áè7H‰„$ƒ¼$@Ç„$œŽ:‹”$ ¾…ÒtH‹”$‹BƒèH˜½t‚ƒö+t$p‹”$€ƒîƒæ‰´$¼‰ð…Ò~L‰éèI‰Å‹„$¼‹T$p…Ò~H‹Œ$èãH‰„$‹„$¤…À…|E…ÿă¼$@޶E…ÿu0H‹Œ$E1ÀºèkL‰éH‰ÂH‰„$èx…À.ýÿÿ‹¼$HM‰æ1ö»÷ßé.ýÿÿ„‹L$d)Œ$€Ç„$ ÷Ù‰Œ$œé/øÿÿ÷ÙÇD$p‰Œ$€éñ÷ÿÿfDD‹„$œD‹´$€HÇ„$ˆé¶ýÿÿD‹œ$¨E…Û„B6…Ò~H‹Œ$ˆèÙH‰„$ˆD‹”$œL‹„$ˆE…Ò…”M‰æL‰d$pH‰\$hH‰¬$€Ç„$¼L‰ÃH‹´$ˆD‰|$`H‹¬$D‹¤$@é²L‰ù‰D$PèÔ‹D$P‰ÁD áuD‹D$|E…À„J…ÿˆ}D çuH‹L$hö„j…À\¶D$\AˆIƒÆ‹T$`9”$¼„ŠE1ÀL‰éº èËH9ÞI‰Å„H‰ñE1Àº è¯H‰ÙE1Àº H‰ÆèœH‰Ãƒ„$¼H‰êL‰éèH‰òƒÀ0L‰é‰D$\è”H‰ÚH‰é‰Çè×I‰Ç¸E‹OE…É…ÿÿÿL‰úL‰éègéÿÿÿfH‰ñE1Àº è0H‰ÆH‰Ã넃¼$@D‹„$œD‹´$€ŽÂûÿÿAGÿ9„$œŒD‹„$œA)ÀE…ÿD‰¼$¼D‰øD‹´$€‰ŠûÿÿE)þÇ„$¼1Àéuûÿÿ‹”$œL‰éè–I‰Åé+üÿÿH…ö„µúÿÿH‰ñè-é¨úÿÿÇ„$¨D‹Œ$H¹E…ÉOŒ$Hƒù‰Œ$H‰Œ$¼A–Á‰Œ$¬A‰ÏA!ÁéîõÿÿÇ„$¨ë´Ç„$¨é—øÿÿH‹”$L‰éè0…À‰lüÿÿE1ÀL‰éº ƒl$dèóƒ¼$¨I‰ÅD‹¼$¬„>üÿÿH‹Œ$ˆE1Àº èÅH‰„$ˆéüÿÿ„H‰T$(Ç„$¼Mt$òD$(f(Èò^Êò,Áò*ÈP0Aˆ$òYÊò\Áf.Æ‹|‹”$¼A9ׄŠò$f(æë‹”$¼A9ׄlf(ȃ‰”$¼òYËf(Áò^Âò,Àò*ÀP0AˆIƒÆòYÂò\Èf(Áf.Îz²f.Ìu¬‹|$d1ÛƒÇéŸðÿÿƒ|$h…»úÿÿ‹FƒÀ9ÇŽ­úÿÿƒ„$€ƒD$pÇ„$œéúÿÿÇ„$¼M‰æH‹œ$ëL‰éE1Àº 莃„$¼I‰ÅH‰ÚL‰éè x0Aˆ>IƒÆD;¼$¼Æ1ö‹T$|…Ò„¨ƒ|$|„ÒAƒ}é>I‰ÆA¶VÿIFÿ€ú9…xL9àuæAÆ$1‹|$d» ƒÇéøÿÿAƒÿÇ„$¼¹A–ÁA!ÁéŸóÿÿ+„$œE1À„$ „$œéìüÿÿD‹|$|E…ÿ„›ƒ|$|„‹|$d»ƒÇé[ïÿÿf(ÌD‰ùE1Òétôÿÿ¿HÇ„$HÇ„$ˆé\÷ÿÿL‰L$(DqÿH7~ò\$(H‰T$(McöÇ„$¼òBYðM‰æòD$(ò}ëDòYƒÀ‰„$¼f(Èò,Á…Àt ò*Àò\Èf(ÁƒÀ0Aˆ‹„$¼IƒÆ9ÈuÅò í|f(ÓòXÑf.‡^îÿÿò\Ëf.Ȇ!öÿÿf.Æz„«D‰T$d»ëDI‰ÆA€~ÿ0IFÿtò‹|$dƒÇéIîÿÿ‹L$|‹|$\I‰ØL‹d$pH‹¬$€…É„NAƒ}Ž8ƒ|$|„ML‰„$ˆL‹¼$A‰øH‹œ$ˆL‰çëFEˆH‰ÙE1Àº IƒÆè)H9ÞL‰éº HDðE1ÀI‰ÄèL‰úH‰ÁI‰Åè‘ D@0L‰ãH‰ÚL‰ùD‰D$0è …ÀD‹D$0¡Aƒø9I‰üH‰œ$ˆD‰Ç„ãƒÇ» Aˆ>‹|$dIƒÆƒÇé¤õÿÿL‰éºèÑH‹”$H‰ÁI‰Å讃øIýÿÿu @€ç…=ýÿÿAƒ}Ž£»ë €I‰ÆA€~ÿ0IFÿtò‹|$dƒÇé<õÿÿHÇ„$HÇ„$ˆéÙ÷ÿÿòXÀD‹T$df.‡™ìÿÿf.ÐŠì…æ¨»„LþÿÿéwìÿÿA‹Hè‹ H‹”$ˆHHH‰ÆHcBHƒÂL…èºH‰ñèêI‰Àé*øÿÿƒÂ» ˆ‹|$dƒÇé’ôÿÿƒ|$|„™øÿÿ‹|$\I‰ØL‹d$pH‹¬$€ƒÿ9„†ƒÇAˆ>‹|$dIƒÆH‰œ$ˆ» ƒÇéGôÿÿ‹|$\L‹d$pH‹¬$€H‰œ$ˆéÑûÿÿAƒ}…½ýÿÿ…À£1ÛAƒ}Ž L‰„$ˆ»é@þÿÿA‹E1Û…À„–þÿÿé²ûÿÿL‰„$ˆAÆ9IƒÆéûÿÿƒÂéyëÿÿH‹T$hö…¨÷ÿÿ‰ø‹|$\I‰ØL‹d$pH‹¬$€ƒÿ9tº…ÀŽçƒÇ» Aˆ>‹|$dIƒÆL‰„$ˆƒÇésóÿÿL‰éºL‰D$0è›H‹”$H‰ÁI‰ÅèxƒøL‹D$0~iƒÿ9„WÿÿÿƒÇ» éÿÿÿD‹T$dé±êÿÿAz»éÓêÿÿ»éiüÿÿD‰T$d1Ûé]üÿÿAƒ}¸L‰„$ˆEØé/ýÿÿ…~ùÿÿéëùÿÿ» …¼þÿÿ@öÇ„²þÿÿé}ÿÿÿ1ÛAƒ}…Pýÿÿé\ýÿÿAƒ}»ÿÿÿAƒ}Û÷ÓƒãéÿÿÿHƒìXE…ÀD‰Àf‰T$hufúÿwRˆ¸HƒÄXÃHT$LD‰L$(H‰L$ ÇD$LHÇD$0A¹H‰T$8LD$h1Ò‰Áÿº²…Àt‹T$L…Òtµè‘Ç*¸ÿÿÿÿë£@HƒìHH‹Õ²H…ÉH‰\$0H‰|$@H\$ H‰t$8‰×‹0HEÙÿ !·×H‰ÙA‰ÀA‰ñè?ÿÿÿH‹\$0H˜H‹t$8H‹|$@HƒÄHÃf„AVI‰ÖAUATUL‰ÅWV1öSH‰ËHƒì0ÿÑ I‹>A‰ÅH‹T²H…ÿD‹ tAH…ÛtiH…íufëNH˜HÃHÆ€{ÿtEHƒÇH9õv7·E‰áE‰èH‰Ùè¶þÿÿ…ÀÔHÇÆÿÿÿÿHƒÄ0H‰ð[^_]A\A]A^Ãf„I‰>ëàIÇHƒîëÓH…íH\$ uëÇfHcЃèH˜HÖ€| t H9õv®HƒÇ·E‰áE‰èH‰ÙèDþÿÿ…ÀÐëŒHƒîëHƒìxH‰l$p1íH…ÒH‰\$XH‰t$`H‰ÓH‰|$hH‰Î‹¼$ u$‰èH‹\$XH‹t$`H‹|$hH‹l$pHƒÄxÃf„M…À½þÿÿÿtÒA‹‰D$@AǶ„À„‘ƒ¼$¨†€|$@t;LD$@ˆD$AÇD$(H‰L$ A¹º‰ùÿ/°…À„œ½éiÿÿÿL‰D$8L‰L$0¶Ð‰ùÿð¯…ÀL‹D$8L‹L$0t*Iƒøv|ÇD$(H‰t$ A¹I‰Øë fÇ1íéÿÿÿ…ÿu¶½f‰éÿÿÿÇD$(H‰t$ A¹I‰Øº‰ùÿ™¯…Àt ½é×þÿÿèÖƒÍÿÇ*éÄþÿÿ¶Aˆé¹þÿÿffff.„HƒìxH‹°H…ÉH‰\$XH\$NH‰t$`H‰|$hH‰l$pL‰ÏHEÙ‹(H‰ÖL‰D$8fÇD$Nÿ;L‹D$8L g…H…ÿH‰òH‰Ù‰l$(LEωD$ èþÿÿH‹\$XH˜H‹t$`H‹|$hH‹l$pHƒÄxÃf.„AWAVL5…AUATUL‰ÅWH‰×VH‰ÎSHƒìHM…ÉMEñ1ÛÿÁA‰ÅH‹G¯H…ÿD‹ t[H‹H…ÒtSH…ötbH…íuëGHcÈH‰ÊHHËH9ÝH‰v#HƒÆI‰èM‰ñH‰ñI)ØD‰d$(D‰l$ èhýÿÿ…ÀÉ…Àu H9ësHÇHƒÄHH‰Ø[^_]A\A]A^A_ÃH…ífÇD$>D‰æL|$>uëÖf.„H˜H‰ÂHHÃH9ÝH‰v¹M‰ñI‰ðL‰ùD‰d$(D‰l$ èõüÿÿ…ÀÑë›ffffff.„HƒìhH‹e®H‰\$HH‰t$PH‰ËH‰|$XH‰ÖL‰ÇH‰l$`fÇD$>‹(ÿ©L ÒƒH…ÿHL$>I‰ðH‰Ú‰l$(LEωD$ èƒüÿÿH‹\$HH˜H‹t$PH‹|$XH‹l$`HƒÄhÃS1ÛHƒì ƒù~¸ÀƒÃP9Ê|ô‰Ù蜉HƒÀHƒÄ [ÃVH‰ÖSH‰ËD‰ÁHƒì(è¼ÿÿÿ¶ H‰Â„ɈtHƒÃ¶ HƒÂHƒÃ„Ɉ uïH…ötH‰HƒÄ([^Ãfff.„HƒìHAü‹IüºÓâ‰HH‰Á‰P HƒÄéfff.„Hƒìx1ÀL‰d$XI‰ÌH‰\$8H‰t$@H‰|$HH‰ÑH‰l$PL‰l$`L‰t$hL‰|$p‹rA;t$YƒîHZIl$LcÆIƒÀF‹L‚G‹l„J|‚1ÒAƒÁD‰èA÷ñ…ÀA‰Å‰D$,„ŠA‰ÇI‰ÚI‰éE1ö1ÒE‹A‹IƒÂM¯ßOM‰ÞAƒãÿL)ØIÁî H)ÐH‰ÂA‰IƒÁHÁê ƒâL9×sÇG‹T„E…Òu6K„HBH9Ås$D‹JE…ÉtëDD‹E…Àu HƒèƒîH9ÅrìA‰t$H‰ÊL‰áè|…ÀxAƒÅH‰é1ÒD‰l$,f.„D‹‹HƒÃL)ÀH)ÐH‰Â‰HƒÁHÁê ƒâH9ßsÜHcÆHƒÀA‹\„…Ûu3I„HBH9Ås!‹J…ÉtëfD‹…Òu HƒèƒîH9ÅrîA‰t$‹D$,H‹\$8H‹t$@H‹|$HH‹l$PL‹d$XL‹l$`L‹t$hL‹|$pHƒÄxÃHƒì8‹ºH‰\$(H‰t$0‰Î‹…Àu ‰5ú€‰ØH‹t$0H‹\$(HƒÄ8Ãf„è˾ÿÿHdpH‰Áÿ3ªH…Àt‰ñÿÐÇ\‰²€ë¶ÇJë¤@SHƒì ‹5…Òu‹‹€HƒÄ [ÃDèk¾ÿÿHpH‰ÁÿÓ©H…ÀH‰Ãt#ÿЉ[€1ÒH…Û•‰íHƒÄ [À‹:€ëÝVS‰ËHƒì(‹:€ƒøt@…Àuh°ð‡(€…ÀuPH 5€H‹5~©ÿÖH M€ÿÖH |è÷¨ÿÿÇõHcÛH€H›H ÐH‹ü¨HƒÄ([^ÿàƒøt5‹ÉƒøuH‹5}©D¹ÿÖ‹«ƒøtîƒøt¬HƒÄ([^ÃÇë™fDS¸Hƒì ð‡wƒøt HƒÄ [Ã@H‹y¨H rÿÓHƒÄ H H‰Ø[ÿàffffff.„Hƒìƒ=-tHƒÄÃHcÉH4H‰H ÐH‹…¨HƒÄÿàffffff.„Hƒì8H‰\$ ‰Ë1ÉH‰t$(H‰|$0è”þÿÿƒû HHHcÓH‹<ÐH…ÿtnH‹H‰ Ðë9‰Ù¾ÓæFÿH˜H …'HÁé‰ÉHÁáè H…ÀH‰Çt‰_‰w 1ÉèCÿÿÿÇGÇGH‰øH‹\$ H‹t$(H‹|$0HƒÄ8ÉپH‹=àÓæFÿH‰úH˜H …'HH)ÂHÁéH‰Ð‰ÉHÁøHH= ‡sÿÿÿHÏH‰œéwÿÿÿ€SH‰ËHƒì H…ÉtCƒy -1Éè–ýÿÿHcSHK~H‹ ÐH‰ H‰ÐHƒÄ [1Éé„þÿÿ@HƒÄ [éN fDHƒÄ [Ãf.„UHAHcÒWH‰ÏVSIcØHƒì(‹q1ÉfD‹(ƒÁH¯êH,+H‰ë‰(HƒÀHÁë 9ÎâH…Ût;w }HcƃƉ\‡‰wHƒÄ(H‰ø[^_]ËOƒÁè4þÿÿH…ÀH‰Åt&HHHcGHWL…è³ H‰ùH‰ïèÿÿÿë®1ÿë·fS‰Ë¹Hƒì èïýÿÿH…Àt ‰XÇ@HƒÄ [Ãf.„AVAUATI‰ÔUWVSH‰ËHƒì ‹i‹z9ý} ‰èH‰Ó‰ýI‰Ì‰Ç1Ét=;s ŸÁKè’ýÿÿH…À„ÀHcÖHHLLL9ÉsH‰ÊDÇHƒÂI9ÑwñHcÿMD$HcíMt¼LSLl«M9ðsTI‰ÌE‹IƒÀE…Ût:E‰ÛL‰âL‰Ñ1ÿf„‹‹*HƒÁI¯ÛHëHûH‰ß‰HƒÂHÁï I9Íw܉:M9ÆvIƒÄ믅ö~A‹YüIQü…Ût ëHƒê‹ …Éuƒî…öï‰pHƒÄ [^_]A\A]A^Ãf.„U‰ÐWV‰ÖSH‰ËHƒì(ƒà…†Áþ…ötsH‹=z{H…ÿué”H‰Ç@öÆu7ÑþtUH‹H…Àuë¹èûÿÿH‹/H…í„’¹H‰ïèüÿÿ@öÆtËfH‰úH‰ÙèeþÿÿH…ÀH‰ÅtfH‰ÙH‰ëè"ýÿÿÑþu«HƒÄ(H‰Ø[^_]ÃèE1ÀHcÐHêk‹èZýÿÿH…ÀH‰Ã…Vÿÿÿëιè’úÿÿH‹=ËzH…ÿt5¹èŒûÿÿéJÿÿÿ1Ûë¥H‰úH‰ùèèýÿÿH…ÀH‰ÅH‰tæHÇéLÿÿÿ¹qè—ýÿÿH…ÀH‰ÇH‰zztÁHÇë©ffffff.„ATU‰ÕÁýW‰×VSH‰ËHƒì ‹s‹C ‹It59Æ~ ÀƒÁ9Æ÷è=ûÿÿH…ÀI‰Ä„€…íHP~ƒíHD¨ÇHƒÂH9ÂuñIT¬HcCƒçHkLTƒtZ¸ E1É)øD‹E‰ùAÓà‰ÁE ÈD‰D‹MHƒÅHƒÂAÓéI9êwÛAƒùD‰ ƒÞÿƒîH‰ÙA‰t$è±ûÿÿHƒÄ L‰à[^_]A\ËEHƒÅ‰HƒÂI9êwîëËfff.„S‹AD‹JD)Èu6McÉLAN JL JT f.„HƒêHƒé‹9uI9Èrí[ÃÀƒÈ[Ã@WVH‰ÖSH‰ËHƒì èžÿÿÿƒø„ÕŒñ1ÿ‹KèúÿÿH…À„®D‹C‰xHKH~IcÐLT“HcVHXL\–1ÒfD‹1D‹HƒÇHƒÁL)ÎH)ÖH‰ò‰3HƒÃHÁê ƒâI9ûwØI9ÊH‰ßI‰Év.‹1HƒÁH)ÖH‰ò‰3HƒÃHÁê ƒâI9ÊwâI÷ÑKHÁêH\—‹{üHSü…ÿu@HƒêAƒè‹2…ötòD‰@HƒÄ [^_ÃfD1Éè9ùÿÿH…ÀtæÇ@Ç@HƒÄ [^_ÃH‰Ø¿H‰óH‰Æéþþÿÿff.„VLQSHƒìHcAH\¹ D‹CLKA½Àƒð)Áƒø ‰ C¹ D‰ÂE1Û)ÁÓêÊð?HÁâ M9ÊsE‹YüAÓëHAÓàE ØI ÐL‰D$òD$HƒÄ[^Ã1ÒM9Ês‹I‰Ùƒè t?» ‰Á‰Ö)ÃAÓà‰ÙAÈð?ÓîD ÆE1ÀHÁæ M9ÑvE‹AüAÓèA‰Ó‰ÁAÓãE ØI ðëžAÈð?‰ÒIÁà I ÐëŒff.„HƒìX¹H‰\$8H‰t$@òD$(H‰|$HH‰l$PH‰ÓL‰ÇH‹t$(èí÷ÿÿH…ÀtI‰ðIÁè D‰ÂAàÿÿÿâÿÿAÁè‰ÑÉE…ÀEÑ…ötkD¼ÎD‰ÉÓîE…É„™¹ ‰ÕD)ÉÓå‰é ñ‰HD‰ÉÓêƒú‰PÒƒÂE…À‰PtKG„Íûÿÿº5D)ÊD‰‰H‹\$8H‹t$@H‹|$HH‹l$PHƒÄXüÊÇ@ÓêE…ÀDI ‰PºuµHcÊÁâAé2½LˆD‰ ƒñ)ʉë¬D‰péwÿÿÿ„HƒìH‰È¶ „ɈtHƒÂ¶ HƒÀHƒÂ„ɈuïHƒÄÃUH‰ÈWHy‰ÑÁùVI‰øSHƒì‹X9Ù}wHcÉHcÛHƒÁƒâH\˜LˆIjt{D‹\ˆ¾ ‰ÑIƒÂ )ÖAÓëL9Óv3E‹ ‰ñAÓá‰ÑE ÙE‰E‹IƒÂIƒÀAÓëL9ÓwÝH)ëHSûHÁêLDIPE…ÛE‰LEÂI)øIÁøE…ÀD‰@uÇ@HƒÄ[^_]ÃH9ëH‰êvØ‹ HƒÂA‰IƒÀH9ÓwîH÷ÕHTHÁêLDë°ff.„HƒìHcAHQLD1ÀL9ÂsD‹IE…Étë‹ …ÉuHƒÂƒÀ I9ÐwîHƒÄËI¼ÉHƒÄÈÃHƒìH‹U~‹HƒÄÃfffff.„Hƒì8H‰\$(H‰t$0è-²ÿÿH…ÀH‰Ãt5H^eH‰ÁH‹5ŒÿÖH…ÀH‰Ø t6H‹\$(H‹t$0HƒÄ8ÿàfDHYH‹\$(H‹t$0H‰¨ HƒÄ8ëBfHeH‰ÙÿÖH…ÀH‰º}tÈHQÿÿÿH‹\$(H‹t$0H‰p HƒÄ8é7ÿÿÿ€Hƒì(1Ò¹èº.H‰ÁèH…ÀtHHHƒÄ(éù1ÀHƒÄ(Ãÿ%2žÿ%ªÿ%²ÿ%žÿ%"žÿ%"žÿ%Âÿ%:žÿ%Jžÿ%Šÿ%jÿ%žÿ%Úÿ%‚ÿ%jÿ%Rÿ%ÿ%Zÿ%ÿ%bÿ%ºÿ%bÿ%Êÿ%Zÿ%jÿ%Zÿ%²ÿ%zÿ%‚ÿ%ÿ%Bœÿ%bœÿ%Rœÿ%ª›ÿ%º›ÿ%Š›ÿ%Š›ÿ%ª›ÿ%Ò›ÿ%Ú›ÿ%Ú›ÿ%Ú›ÿ%Ú›ÿ%ò›ÿ%:›ÿ%Ò›ÿ%š›ÿ%›ÿ%›ÿ%b›ÿ%úšÿ%B›ÿ%›ÿ%J›ÿ%²›ÿ%B›ÿ%"›ÿ%úšÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2èbà%èbà%èb à%èb0+èb 0+èb€€0+èb €0+èb €0+èb 0+èb ­éb@²éb ±éb@³éb@´éb¶´ébÆ´ébÑ´ébÒ´ébÝ´ébê´ébõ´éb µébµébÑ´ébÿÿÿÿÿÿÿÿòèb¸Wéb@Åéb`Àéb@ÿÿÿÀ? ÊébàTéb2¢ß-™+Í] ÒfÔÿÿ1.2.8–0w,aîºQ ™Ämôjp5¥c飕dž2ˆÛ¤¸ÜyéÕàˆÙÒ—+L¶ ½|±~-¸ç‘¿d·ò °jHq¹óÞA¾„}ÔÚëäÝmQµÔôÇ…ÓƒV˜lÀ¨kdzùbýìÉeŠO\Ùlcc=úõ È n;^iLäA`Õrqg¢Ñäjm ¨Zjz Ïäÿ “'® ±ž}D“ðÒ£‡hòþÂi]Wb÷Ëge€q6lçknvÔþà+Ó‰ZzÚÌJÝgoß¹ùùホC¾·Õް`è£ÖÖ~“Ñ¡ÄÂØ8RòßOñg»ÑgW¼¦Ýµ?K6²HÚ+ ØL ¯öJ6`zAÃï`ßUßg¨ïŽn1y¾iFŒ³a˃f¼ Òo%6âhR•w ÌG »¹"/&U¾;ºÅ( ½²’Z´+j³\§ÿ×Â1Ïе‹žÙ,®Þ[°Âd›&òc윣ju “m© œ?6ë…grW‚J¿•z¸â®+±{8¶ ›ŽÒ’ ¾Õå·ïÜ|!ßÛ ÔÒÓ†BâÔñø³ÝhnƒÚ;[&¹öáw°owG·æZˆpjÿÊ;f\ ÿžei®bøÓÿkaEÏlxâ  îÒ ×TƒN³9a&g§÷`ÐMGiIÛwn>JjÑ®ÜZÖÙf ß@ð;Ø7S®¼©Åž»ÞϲGéÿµ0ò½½ŠÂºÊ0“³S¦£´$6к“×Í)WÞT¿gÙ#.zf³¸JaÄh]”+o*7¾ ´¡Ž ÃßZï-A1‚b62ÃS-+ÅldEôw}†§ZVÇ–AOŠÙÈI»ÂÑŠèïúËÙôã Oµ¬M~®µŽ-ƒžÏ˜‡QÂJ#ÙSÓpôx’AïaU×®.æµ7×µ˜–„ƒY˜‚©›Ûú-°šË6©]]wællÿß?AÔžZÍ¢$„•㟌 F²§aw©¾¦áèñçÐóè$ƒÞÃe²ÅÚª®]]ëŸFD(Ìkoiýpv®k19ïZ* ,  m8ó6Fß²]ÆqTpí0ekô÷ó*»¶Â1¢u‘‰4 û¼Ÿº„yÞ©%8ï²<ÿyós¾Hèj}ÅA<*ÞXOyðD~bé‡-OÂÆTÛŠ”@»ƒè#¦ÂÙ8¿ Å 8Lô»!§– Ζ Ì\H1×E‹búnÊSáwT]»ºl £Ö?ˆ—–‘P˜×Þ©ÌÇÒúáì“Ëúõ\×bræykÞµT@Ÿ„OYX#Úp8$›A#=§kýeæZæ|% ËWd8ÐN£®‘⟊!̧3`ý¼*¯á$­îÐ?´-ƒŸl² †«$HÉêSÐ)F~ûhweâöy?/·H$6t 5*ò¼SK³HRpÞey1ï~`þóæç¿Âýþ|‘ÐÕ= ËÌú6Šƒ»‘šxT¼±9e§¨K˜ƒ; ©˜"Éúµ ˆË®O]ï_lôFÍ?ÙmŒÂtCZó#AêÁplÁ€AwØG×6—æ-ŽÅµ¥„„¼ŠAq[»Zh˜èwCÙÙlZO-_~6 œ-'Ý>˜¹S1ƒ b®‹ÑSµ’ÅôÝWôïÄ”§ÂïÕ–Ùöé¼®¨·kÞ1œ*ï*…íykʬHpÓo]ø.*Fáá6Þf ÅcTèT"eóMåó²¤Â©g‘„0& Ÿ)¸®ÅäùŸÞý:ÌóÖ{ýèϼk©€ýZ²™> Ÿ²8„«°$,ñ52F*sw1´ápHõÐkQ6ƒFzw²]cN×úËæáÒ̵Ìù„×àJ–¯ #¶Èp ‰A»„F]#l8Ä?1…(B˜Og©T~ÀúyUËbLÅ8^ô#˜§³Ü–ªTåZ1Oü™bbרSyÎOáIV~úP•-×{ÔÌbŠ-R»–4‘è»ÐÙ ìó~^­ÂeGn‘Hl/ Suè6:© #jT$+e?äy§–¥H¼f‘¤'*нà¼Ëò¡ÐëbÞýÀ#ïæÙ½á¼üЧ ?ƒŠ&~²‘?¹$ÐpøËi;FæBzwý[µkeÜôZ~Å7 Sîv8H÷±® ¸ðŸ¡3Ì?Šrý$“7jÂnÔ„Y¾Fܨ ëÂ˲|…O¸Q;ÑÖ…— áïU dù S“Ø -ž =G\ p£&GÉäw¢)`¬ /›aíÂß«õµiÈò5ÿ˜÷¦&±‘LsZ<#0þzޏMäzàFM8×,9Ž’É;¹ø :<îD? „†>R:À(ôq-Ãv³,šÈõ.­¢7/Àšp÷çXq®Ys™3Ür%“w+OQvrñtE›Õux܉~O¶K }!bÏ|¤t€y“BxÊ zýÊÆ{°.¼l‡D~mÞú8oéúnl†µk[ìwjR1h58ói¯b?mcf«+aQÁé`Ôצeã½ddº"fiàg Ë×H¡INSKyu‘JücÞOË N’·ZL¥Ý˜M˜šÄF¯ðGöN@EÁ$‚DD2ÍAsX@*æIBŒ‹CPhñTg3U>¼uW Ö·VŒÀøS»ª:Râ|PÕ~¾Qè9âZßS [†ífY±‡¤X4‘ë]û)\ZEo^m/­_€5á·q÷àîϱâÙ¥sã\³<ækÙþç2g¸å zä8J&ï äîVž¢ìaô`íäâ/èÓˆíéŠ6«ë½\iêð¸ýÇÒÑüžl—þ©Uÿ,úzØûBÄžùu®\øHéóƒÂò&=„ðWFñ”A ô£+Ëõú•÷ÍÿOö`]xÙW7ºØ‰üÚ9ã>Û¼õqÞ‹Ÿ³ßÒ!õÝåK7ÜØ k×ïf©Ö¶ØïÔ²-Õ¤bÐ3ΠÑjpæÓ]$Òþ^Å'”œÄ~*ÚÆI@ÇÌVWÂû<•â‚ÓÁ•èÀ¨¯MËŸÅÊÆ{ÉÈñ ÉtDÌCm†ÍÓÀÏ-¹Î@–¯‘wüm.B+’(铜>¦–«Td—òê"•Å€à”øÇ¼ŸÏ­~ž–8œ¡yú$oµ˜w™J»1›}Ñóš05‰_KŒ^á Ži‹Ï쀊Û÷B‹‚I‰µ#ƈˆdšƒ¿X‚æ°€ÑÚÜTÌ“„c¦Q…:‡ rÕ† Ðâ©—º ¨Îfªùn¤«|xë®K)¯¬o­%Æ­¬ñ§/ë3¦vUu¤A?·¥Ä)ø óC:¡ªý|£—¾¢Ðsĵç´¾§@¶‰Í‚· ÛͲ;±³bI±Ue‹°h"×»_HºöS¸1œ‘¹´ŠÞ¼ƒà½Ú^Z¿í4˜¾eg¼¸‹È ªî¯µW—b2ðÞ7Ü_k%¹8×ï(´ÅŠO}dà½o‡׸¿ÖJÝØjò3wßàVcXŸWPú0¥èŸúqø¬BÈÀ{ß­§ÇgCru&oÎÍp­•-û·¤?žÐ‡'èÏBs¢¬ ưÉGz>¯2 [ÈŽµg; Ї²i8P/ _ì—âðY…‡—å=ч†e´à:ÝZOÏ?(3w†äêãwXR Øí@h¿Qø¡ø+ðÄŸ—H*0"ZOWžâöoI“õÇ}§@ÕÀümNП5+·#Å–Ÿ *'Gýº| A’ô÷èH¨=X›X?¨#¶1Ó÷¡‰jÏv¨Ê¬á¾„`ÃÒp ^·æY¸©ô<ßL…çÂÑà€~i/Ë{kHwâ ËÇh±s)ÇaL ¸Ùõ˜oDÿÓü~Pfî7ÚVM'¹(@¶Æï°¤£ˆ °Û×g9‘xÒ+ôn“÷&;fšƒˆ?/‘íX“)T`D´1ø ߨMºÏñ¦ìß’þ‰¸.Fg›Tp'ì»HðqÞ/LÉ0€ùÛUçEcœ ?kùǃÓh6ÁrŠyË7]ä®Pá\@ÿTN%˜èösˆ‹®ï7ø@‚'>¼$é!AxU™¯×à‹Ê°\3;¶Yí^ÑåU°~PGÕìÿl!;b F‡Úçé2È‚ŽŽpÔží(±ùQ_Vä‚:1X:ƒ §æn3Á† m¦:µ¤á@½Á†ü/)IJNõ¯óv"2–žŠx¾+˜Ù— KÉôx.®HÀÀýÒ¥fAj^–÷y9*O—–Ÿ]òñ#åkM`~×õŽÑbçë¶Þ_RŽ Â7éµzÙFh¼!¼Ðê1߈Vc0aùÖ"žj𽦽ØÁ¿6n´­S šNrÿ)Î¥†{·táÇÍÙ’¨¾¬*F8#v¥€ufÆØz`þ®Ïr›ÉsÊ"ñ¤WG–ï©9­ýÌ^EîMvc‰ñÎ&DÜèAødQy/ù4“AÚ±&S¿ÖšëéÆù³Œ¡E bðiL¡¾Q›<Û6'„5™’–Pþ..™¹T&üÞèžq]Œwá4Î.6©«IŠEæ? ƒ»v‘àãö\[ýYéI˜>Uñ!‚lDa>Ԫ΋ÆÏ©7~8AÖ]&Ãn³‰v|ÖîÊÄoÖY ±¡áäóy¨K×i˲w«\¡Â¹9Æ~€þ©œå™$ 6 6nQާf†ÂqÚ>,Þo,I¹Ó”ð •渱{I £.±H>ÒC-YnûÃöÛ馑gQ©°ÌzÎ t”a¹fñÞw0–îa,™ QºmÄpjôéc¥5žd•£Ûˆ2yܸ¤àÕé—ÒÙˆ ¶L+~±|½ç¸-¿‘·dj° òó¹qH„¾AÞÚÔ}mÝäëôÔµQƒÓ…Çl˜Vdk¨ÀýbùzŠeÉì\OclÙú=c õ;n ÈLi^Õ`Aä¢gqr<äÑKÔGÒ …ý¥ µk5µ¨úB²˜lÛ»ÉÖ¬¼ù@2ØlãEß\uÜÖ Ï«Ñ=Y&Ù0¬QÞ:È×Q€¿Ða!´ôµV³Ä#Ϻ•™¸½¥(¸ž_ˆÆ Ù²± é$/o|‡XhLÁa«¶f-=vÜAÛq˜Ò ¼ïÕ*q±…‰¶µŸ¿ä¥è¸Ô3xÉ¢ù4– ¨Žá˜j »m=-‘dl—æc\kkQôlab…e0ØòbNl•í¥{‚ôÁõÄWe°ÙÆ·éP‹¾¸êü¹ˆ|bÝßÚ-IŒÓ|óûÔLeM²aX:µQΣ¼tÔ»0âJߥA=ؕפÑÄmÓÖôûCiéj4nÙü­gˆFÚ`¸ÐD-s3åª L_Ý |ÉPq<'Aª¾ É †Whµ% o…³¹fÔ ÎaäŸ^Þù)Ùɘ°Ð˜"Çר´Y³=.´ ·½\;Àºl­í¸ƒ š¿³¶¶â t±ÒšêÕG9Òw¯Û&s܃ãc ”d;„ mj>zjZ¨äÏ “ ÿ ®'}ž±ð“D‡£ÒòhiÂþ÷bW]€egËl6qnkçþÔv‰Ó+àÚzZgÝJÌù¹ßo޾ïù·¾C`°ŽÕÖÖ£è¡Ñ“~8ØÂÄOßòRÑ»gñ¦¼Wg?µÝH²6KØ +Ú¯ L6JöAz`ß`ïègßU1nŽïFi¾yËa³Œ¼fƒ%oÒ Rhâ6Ì w•» G"¹U&/ź;¾²½ (+´Z’\³jÂ×ÿ§µÐÏ1,Ùž‹[Þ®›d°ìcò&uj£œm“ œ ©ë6?rg…W•¿J‚â¸z{±+® ¶8’ÒŽ›åÕ¾ |Üï· Ûß!†ÓÒÔñÔâBhݳøÚƒn¾Íö¹&[o°wá·GwˆZæÿjpf;Ê \ežÿøb®iakÿÓlÏE  âx× ÒîNƒT9³Â§g&aÐ`÷IiGM>nwÛ®ÑjJÙÖZÜ@ß f7Ø;𩼮SÞ»žÅG²Ï0µÿé½½òʺŠS³“0$´£¦ºÐ6ÍדTÞW)#Ùg¿³fz.ÄaJ¸]h*o+”´ ¾7Ã Ž¡Zß-ï1A26b‚+-SÃdlÅ}wôEVZ§†OA–ÇÈÙŠÑ»IúïèŠãôÙˬµO µ®~Mžƒ-އ˜ÏJÂQSÙ#xôpÓaïA’.®×U7µæ˜µ×ƒ„–‚˜Y›©°-úÛ©6Ëšæw]]ÿllÔA?ßÍZž•„$¢ŒŸã§²F ¾©wañèá¦èóÐçÃÞƒ$ÚŲe]]®ªDFŸëokÌ(vpýi91k® *Zï  ,8mßF6óÆ]²ípTqôke0»*ó÷¢1¶‰‘u 4Ÿ¼û„º%©Þy<²ï8sóyÿjèH¾AÅ}XÞ*<ðyOéb~DÂO-‡ÛTÆ”Š»@¦#胿8ÙÂ8 Å !»ôL –§–Î\Ì E×1Hnúb‹wáSʺ»]T£ lˆ?Ö‘–—ÞטPÇÌ©ìáúÒõúË“rb×\kyæ@TµÞYO„ŸX#$8pÚ=#A›eýk§|æZæWË %NÐ8d‘®£ŠŸâ3§Ì!*¼ý`­$᯴?Ð-† ²lÉH$«ÐSêû~F)âewh/?yö6$H· t*5KS¼òRH³yeÞp`~ï1çæóþþý¿ÕБ|ÌË =ƒŠ6úš‘»±¼Tx¨§e9;ƒ˜K"˜© µúɮˈ_ï]OFôlmÙ?ÍtÂŒóZCêA#ÁlpÁØwA€—6×GŽ-極ż„„qAŠhZ»[Cwè˜ZlÙÙ-O 6~_'-œ>ݹ˜ ƒ1S‹®b’µSÑÝôÅÄïôWï§”öÙ–Õ®¼é·¨œ1Þk…*ï*ÊkyíÓpH¬ø]oáF*.fÞ6áÅ TèTcMóe"²óå©Â¤0„‘g)Ÿ &äÅ®¸ýÞŸùÖóÌ:Ïèý{€©k¼™²Zý²Ÿ >«„8,$°5ñ*F21wsHpá´QkÐõzFƒ6c]²wËú×NÒáæù̵Ìàׄ¯–J¶#  pÈ„»A‰#]F8l1?Ä(…gO˜B~T©UyúÀLbË8Ř#ô^³§ª–ÜåTüO1Z×bb™ÎySØIáOPú~V{×-•bÌÔ-Š4–»R»è‘ ÙÐ^~óìGe­lH‘nuS /:6è# ©$Tj?e+–§yä¼H¥¤‘f½Š*'ò˼àëСÀýÞbÙæï#¼á½ §Ðü&Šƒ??‘²~pÐ$¹iËøBæF;[ýwzÜekµÅ~ZôîS 7÷H8v¸ ®±¡ŸðŠ?Ì3“$ýrÂj7„ÔnF¾Y ¨ÜËÂë|²O…Q¸Ñ; —…Ö Uïá ùdØ“S ž- \G=&£päÉG¢w`)/ ¬ía›«ßÂiµõ5òÈ÷˜ÿ±&¦sL‘†„ <À:R=Pe6^X7œ}o5ÚÃ64©1W¿„0•Õ³2Ókê3Ý$kå%©§'ï1þ&-[É#bML" '{ æ™"!$ó*x´(+ºÞ)ü`F(> q-qô,³vÃ.õÈš/7¢­pšÀqXç÷sY®rÜ3™w“%vQO+tñruÕ›E~‰ÜxK¶O} |Ïb!y€t¤xB“z Ê{ÆÊýl¼.°m~D‡o8úÞnúékµ†ljwì[h1Rió85b¯cm?a+«f`éÁQe¦×Ôdd½ãf"ºgàiH×Ë I¡KSNJ‘uyOÞcüN ËLZ·’M˜Ý¥FÄš˜Gð¯E@NöD‚$ÁAÍ2D@XsBIæ*C‹ŒTñhPU3gWu¼>V·Ö SøÀŒR:ª»P|âQ¾~ÕZâ9è[ SßYfí†X¤‡±]ë‘4\)û^oEZ_­/má5€à÷q·â±Ïîãs¥Ùæ<³\çþÙkå¸g2äz ï&J8îä 좞Ví`ôaè/âäéíˆÓë«6Šêi\½ý¸ðüÑÒÇþ—lžÿU©ú,ûØzùžÄBø\®uóéHòƒð„=&ñFWô A”õË+£÷•úöOÿÍÙx]`غ7WÚü‰Û>ã9Þqõ¼ß³Ÿ‹Ýõ!ÒÜ7Kå×k ØÖ©fïÔïØ¶Õ-²Ðb¤Ñ Î3ÓæpjÒ$]Å^þÄœ”'ÆÚ*~Ç@IÂWVÌÕ<ûÁÓ‚¢Àè•ËM¯¨ÊÅŸÈÉ{ÆÉ ñÌDt͆mCÏÀÓι-‘¯–@müw’+B.“é(–¦>œ—dT«•"êò”à€ÅŸ¼Çøž~­Ïœ8–úy¡˜µo$™w›1»JšóÑ}‰50ŒK_Ž á^Ï‹iŠ€ì‹B÷Û‰I‚ˆÆ#µƒšdˆ‚X¿€°æÜÚÑ„“ÌT…Q¦c‡:†Õr ©âР¨ º—ªfΫ¤nù®ëx|¯)K­o¬¬­Æ%§ñ¦3ë/¤uUv¥·?A ø)Ä¡:Có£|ýª¢¾—µÄsдç¶@§¾·‚͉²ÍÛ ³±;±Ib°‹eU»×"hºH_¸Sö¹‘œ1¼ÞŠ´½àƒ¿Z^Ú¾˜4í¸¼geª È‹µ¯îb—W7Þð2%k_Ü×8¹Å´(ï}OŠo½àdׇJÖ¿¸òjØÝàßw3XcVPWŸè¥0úúŸB¬øqß{ÀÈgǧ­urCÍÎo&•­p-?¤·û‡ОÏè'¢sB°Æ ¬zGÉ 2¯>ŽÈ[ ;gµ²‡Ð/P8i—ì_ …Yðâ=å—‡e†‡ÑÝ:à´ÏOZw3(?êä†RXwã@íØ øQ¿hð+ø¡H—ŸÄZ"0*âžWOIoöÇõ“Õ@§}müÀ5ŸÐN#·+Ÿ–Å'* ºýGA |ô’¨Hè÷›X=#¨?X1¶‰¡÷ÓvÏj¬Ê¨¾áÃ`„^ pÒæ·ô©¸YLß<ÑÂç…i~€à{Ë/ÃwHkË ¢s±hÇaÇ)Ù¸ LDo˜õüÓÿîfP~VÚ7¹'M¶@(¤°ïÆ ˆ£Û°9g×+Òx‘“nô;&÷ƒšf‘/?ˆ)“Xí´D`T ø1M¨ß¦ñϺþ’ßìF.¸‰T›gì'pqðH»ÉL/ÞÛù€0cEçUk? œÓƒÇùÁ6hyŠrä]7Ë\áP®NTÿ@öè˜%®‹ˆs7ï‚@ø¼>'!é$™UxA‹àׯ3\°ÊíY¶;UåÑ^GP~°ÿìÕb;!lÚ‡F È2éçpŽŽ‚(ížÔQù±‚äV_:X1:§ ƒ3næ †Áµ:¦m½@á¤ü†ÁI)/¯õNJ2"vóŠž–˜+¾x —ÙxôÉKÀH®.ÒýÀjAf¥÷–^O*9y]Ÿ–—å#ñòMkõ×~`çbÑŽ_Þ¶ë ŽRzµé7hFÙм!¼ˆß1ê0cV"Öùašjž½¦½¿ÁØ­´n6 SrNš¥Î)ÿ·{†Çát’ÙÍ*¬¾¨8F€¥v#ØÆfu`zrÏ®þÊsÉ›W¤ñ"ï–Gý­9©E^ÌvMîÎñ‰cÜD&døAèù/yQA“4S&±ÚëšÖ¿³ùÆé E¡Œðb¡Li<›Q¾„'6Û–’™5..þP&T¹™žèÞüŒ]q4áw©6.ΊI«?æE»ƒ ãà‘v[\öIéYýñU>˜l‚!Ô>aDƋΪ~7©ÏÖA8nÃ&]|v‰³ÄÊîÖYÖoᡱ óäK¨yËi׫w²¹Â¡\~Æ9œ©þ€$™å6 6 ŽQn†f§>ÚqÂ,oÞ,”Ó¹I ð±¸æ•£ I{±.CÒ>HûnY-éÛöÃQg‘¦Ì°©t Îzf¹a”Þñ deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler %s|ÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿ ËþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿüÊþÿHÊþÿìÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿÜÊþÿHÊþÿHÊþÿHÊþÿHÊþÿ¼ÊþÿHÊþÿ¬ÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿHÊþÿœÊþÿHÊþÿHÊþÿHÊþÿHÊþÿŒÊþÿÌÊþÿout of memory%s%s%s: out of memory1.2.8compressed data errorunexpected end of fileinternal error: inflate stream corruptrequested length does not fit in intout of room to push charactersout of memory1.2.8internal error: deflate stream corruptrequested length does not fit in intinvalid block typeinvalid stored block lengthstoo many length or distance symbolsinvalid code lengths setinvalid bit length repeatinvalid code -- missing end-of-blockinvalid literal/lengths setinvalid distances setinvalid literal/length codeinvalid distance codeinvalid distance too far backÀìþÿÔêþÿìþÿÔêþÿÔêþÿpìþÿÔêþÿÔêþÿÔêþÿ@ëþÿÔêþÿÔêþÿÔêþÿÔêþÿÔêþÿÔêþÿÔêþÿëþÿëþÿ     A@!  @a`10  Á@`Psp0 À `  €@ àX ;x8 Ðh( °ˆH ðTã+t4 È d$ ¨„D è\ ˜S|< Øl, ¸ ŒL øR£#r2 Ä b" ¤‚B äZ ”Cz: Ôj* ´ ŠJ ôV@3v6 Ìf& ¬†F ì ^ œc~> Ün. ¼ŽN ü`Qƒq1  a! ¢A âY ’;y9 Òi) ² ‰I òU+u5 Ê e% ª…E ê] šS}= Úm- º M úSÃ#s3 Æ c# ¦ƒC æ[ –C{; Ök+ ¶ ‹K öW@3w7 Îg' ®‡G î _ žc? Þo/ ¾O þ`Psp0 Á ` ¡€@ áX ‘;x8 Ñh( ±ˆH ñTã+t4 É d$ ©„D é\ ™S|< Ùl, ¹ ŒL ùR£#r2 Å b" ¥‚B åZ •Cz: Õj* µ ŠJ õV@3v6 Íf& ­†F í ^ c~> Ýn. ½ŽN ý`Qƒq1 à a! £A ãY “;y9 Ói) ³ ‰I óU+u5 Ë e% «…E ë] ›S}= Ûm- » M ûSÃ#s3 Ç c# §ƒC ç[ —C{; ×k+ · ‹K ÷W@3w7 Ïg' ¯‡G ï _ Ÿc? ßo/ ¿O ÿinvalid distance too far backinvalid distance codeinvalid literal/length codeincorrect header checkunknown compression methodinvalid window sizeunknown header flags setheader crc mismatchinvalid block typeinvalid stored block lengthstoo many length or distance symbolsinvalid code lengths setinvalid bit length repeatinvalid code -- missing end-of-blockinvalid literal/lengths setinvalid distances setinvalid literal/length codeinvalid distance codeinvalid distance too far backincorrect data checkincorrect length checkMÿÿÐÿÿ£ÿÿ–ÿÿ0ÿÿ^ÿÿÃÿÿ)ÿÿ¬ÿÿiÿÿÛÿÿÿÿïÿÿÿÿÿÿ–ÿÿ0 ÿÿÆ ÿÿÉÿÿ ÿÿ ÿÿ´ÿÿÿÿÿÿfÿÿ ÿÿâ ÿÿ· ÿÿÿÿ9ÿÿ˜ÿÿ     A@!  @a`10  Á@`Psp0 À `  €@ àX ;x8 Ðh( °ˆH ðTã+t4 È d$ ¨„D è\ ˜S|< Øl, ¸ ŒL øR£#r2 Ä b" ¤‚B äZ ”Cz: Ôj* ´ ŠJ ôV@3v6 Ìf& ¬†F ì ^ œc~> Ün. ¼ŽN ü`Qƒq1  a! ¢A âY ’;y9 Òi) ² ‰I òU+u5 Ê e% ª…E ê] šS}= Úm- º M úSÃ#s3 Æ c# ¦ƒC æ[ –C{; Ök+ ¶ ‹K öW@3w7 Îg' ®‡G î _ žc? Þo/ ¾O þ`Psp0 Á ` ¡€@ áX ‘;x8 Ñh( ±ˆH ñTã+t4 É d$ ©„D é\ ™S|< Ùl, ¹ ŒL ùR£#r2 Å b" ¥‚B åZ •Cz: Õj* µ ŠJ õV@3v6 Íf& ­†F í ^ c~> Ýn. ½ŽN ý`Qƒq1 à a! £A ãY “;y9 Ói) ³ ‰I óU+u5 Ë e% «…E ë] ›S}= Ûm- » M ûSÃ#s3 Ç c# §ƒC ç[ —C{; ×k+ · ‹K ÷W@3w7 Ïg' ¯‡G ï _ Ÿc? ßo/ ¿O ÿ inflate 1.2.8 Copyright 1995-2013 Mark Adler @@ !1AaÁ  0@`HN #+3;CScsƒ£Ãã   ŒLÌ,¬lìœ\Ü<¼|ü‚BÂ"¢bâ’RÒ2²rò ŠJÊ*ªjêšZÚ:ºzú†FÆ&¦fæ–VÖ6¶vöŽNÎ.®nîž^Þ>¾~þAÁ!¡aá‘QÑ1±qñ ‰IÉ)©ié™YÙ9¹yù…EÅ%¥eå•UÕ5µuõ MÍ-­mí]Ý=½}ý  “ “ S S Ó Ó 3 3 ³ ³ s s ó ó  ‹ ‹ K K Ë Ë + + « « k k ë ë   › › [ [ Û Û ; ; » » { { û û   ‡ ‡ G G Ç Ç ' ' § § g g ç ç   — — W W × × 7 7 · · w w ÷ ÷    O O Ï Ï / / ¯ ¯ o o ï ï   Ÿ Ÿ _ _ ß ß ? ? ¿ ¿   ÿ ÿ @ `P0pH(hX8xD$dT4tƒCÃ#£cã            (08@P`p€ Àà   0@`€À€  0@`1.2.81.2.8need dictionarystream endfile errorstream errordata errorinsufficient memorybuffer errorincompatible versionMingw-w64 runtime failure: Address %p has no image-section VirtualQuery failed for %d bytes at address %p VirtualProtect failed with code 0x%x Unknown pseudo relocation protocol version %d. Unknown pseudo relocation bit size %d. .pdatamsvcrt.dll(null)NaNInf(null)PRINTF_EXPONENT_DIGITSˆoÿÿ.jÿÿ.jÿÿkoÿÿ.jÿÿXoÿÿ.jÿÿínÿÿ.jÿÿ.jÿÿ¸nÿÿ˜nÿÿ.jÿÿxnÿÿXnÿÿ.jÿÿ(pÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿpÿÿ.jÿÿÈoÿÿ.jÿÿ¨oÿÿhpÿÿHpÿÿ.jÿÿˆpÿÿ.jÿÿ.jÿÿ=nÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ¬pÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ˜mÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿ.jÿÿømÿÿ.jÿÿílÿÿ8mÿÿ¨lÿÿ]lÿÿlÿÿìkÿÿ8mÿÿØkÿÿ.jÿÿ¨kÿÿˆkÿÿHkÿÿ˜mÿÿkÿÿ.jÿÿ.jÿÿØjÿÿØkÿÿ˜mÿÿ.jÿÿ.jÿÿ˜mÿÿ.jÿÿØkÿÿInfinityNaN0”sÿÿÀrÿÿÀrÿÿôsÿÿÄsÿÿø?aCoc§‡Ò?³È`‹(ŠÆ?ûyŸPDÓ?ú}-”<2ZGUDÓ?ð?$@@@@€à?_set_output_format_get_output_format€à7yÃACnµµ¸“Fõù?éO8M20ùHw‚Z<¿sÝOu¼‰Ø—²Òœ<3§¨Õ#öI9=§ôDý¥2—ŒÏº[%Co¬d(È ð?$@Y@@@ˆÃ@jø@€„.AÐcA„×—AeÍÍA _ BèvH7B¢”mB@åœ0¢BļÖB4&õk C€à7yÃAC Ø…W4vCÈNgmÁ«C=‘`äXáC@Œµx¯DPïâÖäKD’ÕMÏð€D}___lc_codepage_func__lc_codepage°íQ4ãNN(à`á˜âpPÀаp€@=0<WP Q°TpOÐ:;9@8À5 :à;`€^ðbpY0pp{ðoÐ]PbbzPlÀl`nðaa]°]`^àywÐw@jÐ^à`p_ z@að`0m0xu ¡ð}`ð|Ã0¾¾ð¿ ž ŸÀÄ  0œ€›0¿0ÀÐÂÄ@ð@ñ0ñ ñ>ãFãVãhãqã{ã‰ããã­ãµãÂãÎãÙãçãôãäää+ä<äQäbänä|ä…ää˜ä¢ä¬äµä½äÃäËäÓäÚäâäéäòäýäå ååå&å-å4å=åDåMåYå`åiårå|å„åŒå˜å§å¸åÄåÏåäåõåæææ)æ6æDæUæjævæ‡æ˜æ£æªæ»æ  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMzlib1.dlladler32adler32_combineadler32_combine64compresscompress2compressBoundcrc32crc32_combinecrc32_combine64deflatedeflateBounddeflateCopydeflateEnddeflateInit2_deflateInit_deflateParamsdeflatePendingdeflatePrimedeflateResetdeflateResetKeepdeflateSetDictionarydeflateSetHeaderdeflateTuneget_crc_tablegzbuffergzclearerrgzclosegzclose_rgzclose_wgzdirectgzdopengzeofgzerrorgzflushgzgetcgzgetc_gzgetsgzoffsetgzoffset64gzopengzopen64gzopen_wgzprintfgzputcgzputsgzreadgzrewindgzseekgzseek64gzsetparamsgztellgztell64gzungetcgzvprintfgzwriteinflateinflateBackinflateBackEndinflateBackInit_inflateCopyinflateEndinflateGetDictionaryinflateGetHeaderinflateInit2_inflateInit_inflateMarkinflatePrimeinflateResetinflateReset2inflateResetKeepinflateSetDictionaryinflateSyncinflateSyncPointinflateUndermineuncompresszErrorzlibCompileFlagszlibVersionPð ø`ò8ñÀøHó`ñHùpópôˆô ô´ôÊôàôðôõõ0õ@õ\õpõˆõ˜õ®õÈõÞõòõ ö ö>öFöZöhö„ö–ö¦ö¼öÆöÎöÖöàöîöüö ÷÷$÷0÷8÷D÷N÷X÷f÷p÷x÷€÷Š÷’÷š÷¤÷²÷¼÷Æ÷Ð÷Ú÷æ÷ð÷ú÷øøø$øpôˆô ô´ôÊôàôðôõõ0õ@õ\õpõˆõ˜õ®õÈõÞõòõ ö ö>öFöZöhö„ö–ö¦ö¼öÆöÎöÖöàöîöüö ÷÷$÷0÷8÷D÷N÷X÷f÷p÷x÷€÷Š÷’÷š÷¤÷²÷¼÷Æ÷Ð÷Ú÷æ÷ð÷ú÷øøø$øØDeleteCriticalSectionøEnterCriticalSectionÍGetCurrentProcessÎGetCurrentProcessIdÒGetCurrentThreadIdGetLastError$GetModuleHandleAVGetProcAddressŠGetSystemTimeAsFileTime¥GetTickCountùInitializeCriticalSectionIsDBCSLeadByteExKLeaveCriticalSectionQLoadLibraryWzMultiByteToWideChar»QueryPerformanceCounterRtlAddFunctionTableRtlCaptureContext RtlLookupFunctionEntryRtlVirtualUnwindŸSetUnhandledExceptionFilter¬SleepºTerminateProcessÁTlsGetValueÎUnhandledExceptionFilterìVirtualProtectîVirtualQueryWideCharToMultiByte_close6_open<_readi_writeN__dllonexitS__iob_func[__mb_cur_maxx_amsg_exit¼_errno_initterm‚_lock‹_lseeki64'_onexitÑ_unlockî_vsnprintfY_wopenabort˜atoiœcallocºfputc¿freeÏgetenvòlocaleconvùmallocÿmemchrmemcpymemsetsetlocalesignal*strchr0strerror3strlen6strncmpkwcslen{wcstombsððððððððððððððððððððððððððððKERNEL32.dllððððmsvcrt.dll(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ð(ðmsvcrt.dllèbòèb`òèb@êbHêbÀéb0êb¯íQ€¯íQ0€¯íQ HX ,,4VS_VERSION_INFO½ïþ?ŒStringFileInfoh040904E4dFileDescriptionzlib data compression library,FileVersion1.2.84 InternalNamezlib1.dll|,LegalCopyright(C) 1995-2013 Jean-loup Gailly & Mark Adler< OriginalFilenamezlib1.dll*ProductNamezlib0ProductVersion1.2.8x0CommentsFor more information visit http://www.zlib.net/DVarFileInfo$Translation ä`H  ( 8 H X h x ˆ ˜   ¨ À È è ¡¡¡¡ ¡(¡0¡8¡@¡H¡p¡€¡¡˜¡à¡ð¡ 0 8     tcl8.6.5/compat/zlib/win64/zdll.lib0000644000175000017500000003567012663660065016431 0ustar sergeisergei! / 1368452078 0 2992 ` Ÿê @;R;R 0 0!`!`2P2P4T4T$¤$¤ ú ú#Ð#Ð"–"–%€%€ ’ ’"þ"þ#h#h%%8p8p4º4º8à8à3î3î74747œ7œ6Ì6Ì6f6f5*5*2²2²33:æ:æÎÎ22––::,,(¦(¦&N&N/ú/ú.n.n1î1î-F-F1Š1Š. . *ð*ð-ª-ª*,*,1&1&)Ê)Ê/4/4.Ð.Ð0`0`+R+R))(B(B'''z'z'Þ'Þ)h)h&²&²,~,~/–/–0Â0Â+¶+¶bbÆÆ––þþøø^^".".!Æ!Æ5þ5þ5–5–3‚3‚*Ž*Ž:„:„9F9F%æ%æ9²9²88$8$8,â,â__IMPORT_DESCRIPTOR_zlib1__NULL_IMPORT_DESCRIPTORzlib1_NULL_THUNK_DATA__imp_zlibVersionzlibVersion__imp_deflatedeflate__imp_deflateEnddeflateEnd__imp_inflateinflate__imp_inflateEndinflateEnd__imp_deflateSetDictionarydeflateSetDictionary__imp_deflateCopydeflateCopy__imp_deflateResetdeflateReset__imp_deflateParamsdeflateParams__imp_deflateTunedeflateTune__imp_deflateBounddeflateBound__imp_deflatePendingdeflatePending__imp_deflatePrimedeflatePrime__imp_deflateSetHeaderdeflateSetHeader__imp_inflateSetDictionaryinflateSetDictionary__imp_inflateGetDictionaryinflateGetDictionary__imp_inflateSyncinflateSync__imp_inflateCopyinflateCopy__imp_inflateResetinflateReset__imp_inflateReset2inflateReset2__imp_inflatePrimeinflatePrime__imp_inflateMarkinflateMark__imp_inflateGetHeaderinflateGetHeader__imp_inflateBackinflateBack__imp_inflateBackEndinflateBackEnd__imp_zlibCompileFlagszlibCompileFlags__imp_compresscompress__imp_compress2compress2__imp_compressBoundcompressBound__imp_uncompressuncompress__imp_gzopengzopen__imp_gzdopengzdopen__imp_gzbuffergzbuffer__imp_gzsetparamsgzsetparams__imp_gzreadgzread__imp_gzwritegzwrite__imp_gzprintfgzprintf__imp_gzvprintfgzvprintf__imp_gzputsgzputs__imp_gzgetsgzgets__imp_gzputcgzputc__imp_gzgetcgzgetc__imp_gzungetcgzungetc__imp_gzflushgzflush__imp_gzseekgzseek__imp_gzrewindgzrewind__imp_gztellgztell__imp_gzoffsetgzoffset__imp_gzeofgzeof__imp_gzdirectgzdirect__imp_gzclosegzclose__imp_gzclose_rgzclose_r__imp_gzclose_wgzclose_w__imp_gzerrorgzerror__imp_gzclearerrgzclearerr__imp_gzopen64gzopen64__imp_gzseek64gzseek64__imp_gztell64gztell64__imp_gzoffset64gzoffset64__imp_adler32_combine64adler32_combine64__imp_crc32_combine64crc32_combine64__imp_adler32adler32__imp_crc32crc32__imp_adler32_combineadler32_combine__imp_crc32_combinecrc32_combine__imp_deflateInit_deflateInit___imp_deflateInit2_deflateInit2___imp_inflateInit_inflateInit___imp_inflateInit2_inflateInit2___imp_inflateBackInit_inflateBackInit___imp_gzgetc_gzgetc___imp_zErrorzError__imp_inflateSyncPointinflateSyncPoint__imp_get_crc_tableget_crc_table__imp_inflateUndermineinflateUndermine__imp_inflateResetKeepinflateResetKeep__imp_deflateResetKeepdeflateResetKeep__imp_gzopen_wgzopen_w/ 1368452078 0 3002 ` Qê @R;0 `!P2T4¤$ú Ð#–"€%’ þ"h#%p8º4à8î347œ7Ì6f6*5²23æ:Î2–:,¦(N&ú/n.î1F-Š1 .ð*ª-,*&1Ê)4/Ð.`0R+)B('z'Þ'h)²&~,–/Â0¶+bÆ–þø^."Æ!þ5–5‚3Ž*„:F9æ%²988$â,ŸAC? BD@ FE  P  M$:6785#49/-J+3>";Q(,*&10<%2=.)'IHGOLN!KAC? BD@ FE  P  M$:6785#49/-J+3>";Q(,*&10<%2=.)'IHGOLN!K__IMPORT_DESCRIPTOR_zlib1__NULL_IMPORT_DESCRIPTOR__imp_adler32__imp_adler32_combine__imp_adler32_combine64__imp_compress__imp_compress2__imp_compressBound__imp_crc32__imp_crc32_combine__imp_crc32_combine64__imp_deflate__imp_deflateBound__imp_deflateCopy__imp_deflateEnd__imp_deflateInit2___imp_deflateInit___imp_deflateParams__imp_deflatePending__imp_deflatePrime__imp_deflateReset__imp_deflateResetKeep__imp_deflateSetDictionary__imp_deflateSetHeader__imp_deflateTune__imp_get_crc_table__imp_gzbuffer__imp_gzclearerr__imp_gzclose__imp_gzclose_r__imp_gzclose_w__imp_gzdirect__imp_gzdopen__imp_gzeof__imp_gzerror__imp_gzflush__imp_gzgetc__imp_gzgetc___imp_gzgets__imp_gzoffset__imp_gzoffset64__imp_gzopen__imp_gzopen64__imp_gzopen_w__imp_gzprintf__imp_gzputc__imp_gzputs__imp_gzread__imp_gzrewind__imp_gzseek__imp_gzseek64__imp_gzsetparams__imp_gztell__imp_gztell64__imp_gzungetc__imp_gzvprintf__imp_gzwrite__imp_inflate__imp_inflateBack__imp_inflateBackEnd__imp_inflateBackInit___imp_inflateCopy__imp_inflateEnd__imp_inflateGetDictionary__imp_inflateGetHeader__imp_inflateInit2___imp_inflateInit___imp_inflateMark__imp_inflatePrime__imp_inflateReset__imp_inflateReset2__imp_inflateResetKeep__imp_inflateSetDictionary__imp_inflateSync__imp_inflateSyncPoint__imp_inflateUndermine__imp_uncompress__imp_zError__imp_zlibCompileFlags__imp_zlibVersionadler32adler32_combineadler32_combine64compresscompress2compressBoundcrc32crc32_combinecrc32_combine64deflatedeflateBounddeflateCopydeflateEnddeflateInit2_deflateInit_deflateParamsdeflatePendingdeflatePrimedeflateResetdeflateResetKeepdeflateSetDictionarydeflateSetHeaderdeflateTuneget_crc_tablegzbuffergzclearerrgzclosegzclose_rgzclose_wgzdirectgzdopengzeofgzerrorgzflushgzgetcgzgetc_gzgetsgzoffsetgzoffset64gzopengzopen64gzopen_wgzprintfgzputcgzputsgzreadgzrewindgzseekgzseek64gzsetparamsgztellgztell64gzungetcgzvprintfgzwriteinflateinflateBackinflateBackEndinflateBackInit_inflateCopyinflateEndinflateGetDictionaryinflateGetHeaderinflateInit2_inflateInit_inflateMarkinflatePrimeinflateResetinflateReset2inflateResetKeepinflateSetDictionaryinflateSyncinflateSyncPointinflateUndermineuncompresszErrorzlibCompileFlagszlibVersionzlib1_NULL_THUNK_DATAzlib1.dll/ 1368452078 0 485 ` d†îëQ.debug$S?Œ@B.idata$2Ëß@0À.idata$6 ýß@ À zlib1.dll'Ð 'ÆMicrosoft (R) LINK zlib1.dll@comp.id'ÆËÿÿ.idata$2@Àh.idata$6.idata$4@Àh.idata$5@Àh7N__IMPORT_DESCRIPTOR_zlib1__NULL_IMPORT_DESCRIPTORzlib1_NULL_THUNK_DATA zlib1.dll/ 1368452078 0 248 ` d†îëQ·.debug$S?d@B.idata$3£@0À zlib1.dll'Ð 'ÆMicrosoft (R) LINK@comp.id'ÆËÿÿ__NULL_IMPORT_DESCRIPTORzlib1.dll/ 1368452078 0 282 ` d†îëQÛ.debug$S?Œ@B.idata$5Ë@@À.idata$4Ó@@À zlib1.dll'Ð 'ÆMicrosoft (R) LINK@comp.id'ÆËÿÿzlib1_NULL_THUNK_DATAzlib1.dll/ 1368452078 0 38 ` ÿÿd†îëQadler32zlib1.dllzlib1.dll/ 1368452078 0 46 ` ÿÿd†îëQadler32_combinezlib1.dllzlib1.dll/ 1368452078 0 48 ` ÿÿd†îëQadler32_combine64zlib1.dllzlib1.dll/ 1368452078 0 39 ` ÿÿd†îëQcompresszlib1.dll zlib1.dll/ 1368452078 0 40 ` ÿÿd†îëQcompress2zlib1.dllzlib1.dll/ 1368452078 0 44 ` ÿÿd†îëQcompressBoundzlib1.dllzlib1.dll/ 1368452078 0 36 ` ÿÿd†îëQcrc32zlib1.dllzlib1.dll/ 1368452078 0 44 ` ÿÿd†îëQcrc32_combinezlib1.dllzlib1.dll/ 1368452078 0 46 ` ÿÿd†îëQcrc32_combine64zlib1.dllzlib1.dll/ 1368452078 0 38 ` ÿÿd†îëQ deflatezlib1.dllzlib1.dll/ 1368452078 0 43 ` ÿÿd†îëQ deflateBoundzlib1.dll zlib1.dll/ 1368452078 0 42 ` ÿÿd†îëQ deflateCopyzlib1.dllzlib1.dll/ 1368452078 0 41 ` ÿÿd†îëQ deflateEndzlib1.dll zlib1.dll/ 1368452078 0 44 ` ÿÿd†îëQ deflateInit2_zlib1.dllzlib1.dll/ 1368452078 0 43 ` ÿÿd†îëQdeflateInit_zlib1.dll zlib1.dll/ 1368452078 0 44 ` ÿÿd†îëQdeflateParamszlib1.dllzlib1.dll/ 1368452078 0 45 ` ÿÿd†îëQdeflatePendingzlib1.dll zlib1.dll/ 1368452078 0 43 ` ÿÿd†îëQdeflatePrimezlib1.dll zlib1.dll/ 1368452078 0 43 ` ÿÿd†îëQdeflateResetzlib1.dll zlib1.dll/ 1368452078 0 47 ` ÿÿd†îëQdeflateResetKeepzlib1.dll zlib1.dll/ 1368452078 0 51 ` ÿÿd†îëQdeflateSetDictionaryzlib1.dll zlib1.dll/ 1368452078 0 47 ` ÿÿd†îëQdeflateSetHeaderzlib1.dll zlib1.dll/ 1368452078 0 42 ` ÿÿd†îëQdeflateTunezlib1.dllzlib1.dll/ 1368452078 0 44 ` ÿÿd†îëQget_crc_tablezlib1.dllzlib1.dll/ 1368452078 0 39 ` ÿÿd†îëQgzbufferzlib1.dll zlib1.dll/ 1368452078 0 41 ` ÿÿd†îëQgzclearerrzlib1.dll zlib1.dll/ 1368452078 0 38 ` ÿÿd†îëQgzclosezlib1.dllzlib1.dll/ 1368452078 0 40 ` ÿÿd†îëQgzclose_rzlib1.dllzlib1.dll/ 1368452078 0 40 ` ÿÿd†îëQgzclose_wzlib1.dllzlib1.dll/ 1368452078 0 39 ` ÿÿd†îëQgzdirectzlib1.dll zlib1.dll/ 1368452078 0 38 ` ÿÿd†îëQgzdopenzlib1.dllzlib1.dll/ 1368452078 0 36 ` ÿÿd†îëQgzeofzlib1.dllzlib1.dll/ 1368452078 0 38 ` ÿÿd†îëQ gzerrorzlib1.dllzlib1.dll/ 1368452078 0 38 ` ÿÿd†îëQ!gzflushzlib1.dllzlib1.dll/ 1368452078 0 37 ` ÿÿd†îëQ"gzgetczlib1.dll zlib1.dll/ 1368452078 0 38 ` ÿÿd†îëQ#gzgetc_zlib1.dllzlib1.dll/ 1368452078 0 37 ` ÿÿd†îëQ$gzgetszlib1.dll zlib1.dll/ 1368452078 0 39 ` ÿÿd†îëQ%gzoffsetzlib1.dll zlib1.dll/ 1368452078 0 41 ` ÿÿd†îëQ&gzoffset64zlib1.dll zlib1.dll/ 1368452078 0 37 ` ÿÿd†îëQ'gzopenzlib1.dll zlib1.dll/ 1368452078 0 39 ` ÿÿd†îëQ(gzopen64zlib1.dll zlib1.dll/ 1368452078 0 39 ` ÿÿd†îëQ)gzopen_wzlib1.dll zlib1.dll/ 1368452078 0 39 ` ÿÿd†îëQ*gzprintfzlib1.dll zlib1.dll/ 1368452078 0 37 ` ÿÿd†îëQ+gzputczlib1.dll zlib1.dll/ 1368452078 0 37 ` ÿÿd†îëQ,gzputszlib1.dll zlib1.dll/ 1368452078 0 37 ` ÿÿd†îëQ-gzreadzlib1.dll zlib1.dll/ 1368452078 0 39 ` ÿÿd†îëQ.gzrewindzlib1.dll zlib1.dll/ 1368452078 0 37 ` ÿÿd†îëQ/gzseekzlib1.dll zlib1.dll/ 1368452078 0 39 ` ÿÿd†îëQ0gzseek64zlib1.dll zlib1.dll/ 1368452078 0 42 ` ÿÿd†îëQ1gzsetparamszlib1.dllzlib1.dll/ 1368452078 0 37 ` ÿÿd†îëQ2gztellzlib1.dll zlib1.dll/ 1368452078 0 39 ` ÿÿd†îëQ3gztell64zlib1.dll zlib1.dll/ 1368452078 0 39 ` ÿÿd†îëQ4gzungetczlib1.dll zlib1.dll/ 1368452078 0 40 ` ÿÿd†îëQ5gzvprintfzlib1.dllzlib1.dll/ 1368452078 0 38 ` ÿÿd†îëQ6gzwritezlib1.dllzlib1.dll/ 1368452078 0 38 ` ÿÿd†îëQ7inflatezlib1.dllzlib1.dll/ 1368452078 0 42 ` ÿÿd†îëQ8inflateBackzlib1.dllzlib1.dll/ 1368452078 0 45 ` ÿÿd†îëQ9inflateBackEndzlib1.dll zlib1.dll/ 1368452078 0 47 ` ÿÿd†îëQ:inflateBackInit_zlib1.dll zlib1.dll/ 1368452078 0 42 ` ÿÿd†îëQ;inflateCopyzlib1.dllzlib1.dll/ 1368452078 0 41 ` ÿÿd†îëQ<inflateEndzlib1.dll zlib1.dll/ 1368452078 0 51 ` ÿÿd†îëQ=inflateGetDictionaryzlib1.dll zlib1.dll/ 1368452078 0 47 ` ÿÿd†îëQ>inflateGetHeaderzlib1.dll zlib1.dll/ 1368452078 0 44 ` ÿÿd†îëQ?inflateInit2_zlib1.dllzlib1.dll/ 1368452078 0 43 ` ÿÿd†îëQ@inflateInit_zlib1.dll zlib1.dll/ 1368452078 0 42 ` ÿÿd†îëQAinflateMarkzlib1.dllzlib1.dll/ 1368452078 0 43 ` ÿÿd†îëQBinflatePrimezlib1.dll zlib1.dll/ 1368452078 0 43 ` ÿÿd†îëQCinflateResetzlib1.dll zlib1.dll/ 1368452078 0 44 ` ÿÿd†îëQDinflateReset2zlib1.dllzlib1.dll/ 1368452078 0 47 ` ÿÿd†îëQEinflateResetKeepzlib1.dll zlib1.dll/ 1368452078 0 51 ` ÿÿd†îëQFinflateSetDictionaryzlib1.dll zlib1.dll/ 1368452078 0 42 ` ÿÿd†îëQGinflateSynczlib1.dllzlib1.dll/ 1368452078 0 47 ` ÿÿd†îëQHinflateSyncPointzlib1.dll zlib1.dll/ 1368452078 0 47 ` ÿÿd†îëQIinflateUnderminezlib1.dll zlib1.dll/ 1368452078 0 41 ` ÿÿd†îëQJuncompresszlib1.dll zlib1.dll/ 1368452078 0 37 ` ÿÿd†îëQKzErrorzlib1.dll zlib1.dll/ 1368452078 0 47 ` ÿÿd†îëQLzlibCompileFlagszlib1.dll zlib1.dll/ 1368452078 0 42 ` ÿÿd†îëQMzlibVersionzlib1.dlltcl8.6.5/compat/zlib/win64/libz.dll.a0000644000175000017500000013343212663660065016643 0ustar sergeisergei! / 1371036826 0 0 0 2946 ` ž Æ ~~¬¬èè..jj¦¦ÔÔ  "X"X$Š$Š&º&º(ê(ê++-H-H/z/z1¶1¶3þ3þ6*6*8X8X:”:”<Ì<Ì>ú>úAAC.C.ETETGpGpIŒIŒK¦K¦MÔMÔOðOðR R T&T&V@V@XZXZZtZt\\^¬^¬`È`Èbâbâeeg*g*iDiDk^k^mxmxo’o’q¬q¬sÀsÀuÚuÚwöwözz|B|B~\~\€ˆ€ˆ‚¤‚¤„Ö„Ö‡‡‰@‰@‹ˆ‹ˆÄÄôô’$’$”\”\–Ž–Ž˜¾˜¾šðšðŸJŸJ¡z¡z£”£”¥Î¥Î¨¨ªª¬F¬F®l®l°ˆ°ˆ²Æ²Æµµzlib1_dll_iname_head_zlib1_dllzlibVersion__imp_zlibVersionzlibCompileFlags__imp_zlibCompileFlagszError__imp_zErroruncompress__imp_uncompressinflateUndermine__imp_inflateUndermineinflateSyncPoint__imp_inflateSyncPointinflateSync__imp_inflateSyncinflateSetDictionary__imp_inflateSetDictionaryinflateResetKeep__imp_inflateResetKeepinflateReset2__imp_inflateReset2inflateReset__imp_inflateResetinflatePrime__imp_inflatePrimeinflateMark__imp_inflateMarkinflateInit___imp_inflateInit_inflateInit2___imp_inflateInit2_inflateGetHeader__imp_inflateGetHeaderinflateGetDictionary__imp_inflateGetDictionaryinflateEnd__imp_inflateEndinflateCopy__imp_inflateCopyinflateBackInit___imp_inflateBackInit_inflateBackEnd__imp_inflateBackEndinflateBack__imp_inflateBackinflate__imp_inflategzwrite__imp_gzwritegzvprintf__imp_gzvprintfgzungetc__imp_gzungetcgztell64__imp_gztell64gztell__imp_gztellgzsetparams__imp_gzsetparamsgzseek64__imp_gzseek64gzseek__imp_gzseekgzrewind__imp_gzrewindgzread__imp_gzreadgzputs__imp_gzputsgzputc__imp_gzputcgzprintf__imp_gzprintfgzopen_w__imp_gzopen_wgzopen64__imp_gzopen64gzopen__imp_gzopengzoffset64__imp_gzoffset64gzoffset__imp_gzoffsetgzgets__imp_gzgetsgzgetc___imp_gzgetc_gzgetc__imp_gzgetcgzflush__imp_gzflushgzerror__imp_gzerrorgzeof__imp_gzeofgzdopen__imp_gzdopengzdirect__imp_gzdirectgzclose_w__imp_gzclose_wgzclose_r__imp_gzclose_rgzclose__imp_gzclosegzclearerr__imp_gzclearerrgzbuffer__imp_gzbufferget_crc_table__imp_get_crc_tabledeflateTune__imp_deflateTunedeflateSetHeader__imp_deflateSetHeaderdeflateSetDictionary__imp_deflateSetDictionarydeflateResetKeep__imp_deflateResetKeepdeflateReset__imp_deflateResetdeflatePrime__imp_deflatePrimedeflatePending__imp_deflatePendingdeflateParams__imp_deflateParamsdeflateInit___imp_deflateInit_deflateInit2___imp_deflateInit2_deflateEnd__imp_deflateEnddeflateCopy__imp_deflateCopydeflateBound__imp_deflateBounddeflate__imp_deflatecrc32_combine64__imp_crc32_combine64crc32_combine__imp_crc32_combinecrc32__imp_crc32compressBound__imp_compressBoundcompress2__imp_compress2compress__imp_compressadler32_combine64__imp_adler32_combine64adler32_combine__imp_adler32_combineadler32__imp_adler32d000079.o/ 1371036826 1007 513 644 260 ` d†¨.idata$4Œ0À.idata$5”0À.idata$7 œ0Àzlib1.dll.idata$4.idata$5.idata$7zlib1_dll_inamed000000.o/ 1371036826 1007 513 644 316 ` d†¾.idata$2Œ 0À.idata$50À.idata$40À .idata$2.idata$5.idata$4$_head_zlib1_dllzlib1_dll_inamed000078.o/ 1371036826 1007 513 644 498 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%MzlibVersion.text.idata$7.idata$5.idata$4.idata$6"2zlibVersion__imp_zlibVersion_head_zlib1_dlld000077.o/ 1371036826 1007 513 644 512 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%LzlibCompileFlags.text.idata$7.idata$5.idata$4.idata$6,<zlibCompileFlags__imp_zlibCompileFlags_head_zlib1_dlld000076.o/ 1371036826 1007 513 644 477 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%KzError.text.idata$7.idata$5.idata$4.idata$6zError!__imp_zError_head_zlib1_dll d000075.o/ 1371036826 1007 513 644 496 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%Juncompress.text.idata$7.idata$5.idata$4.idata$6 0uncompress__imp_uncompress_head_zlib1_dlld000074.o/ 1371036826 1007 513 644 512 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%IinflateUndermine.text.idata$7.idata$5.idata$4.idata$6,<inflateUndermine__imp_inflateUndermine_head_zlib1_dlld000073.o/ 1371036826 1007 513 644 512 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%HinflateSyncPoint.text.idata$7.idata$5.idata$4.idata$6,<inflateSyncPoint__imp_inflateSyncPoint_head_zlib1_dlld000072.o/ 1371036826 1007 513 644 498 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%GinflateSync.text.idata$7.idata$5.idata$4.idata$6"2inflateSync__imp_inflateSync_head_zlib1_dlld000071.o/ 1371036826 1007 513 644 524 ` d†8.textÜ 0`.idata$7ä0À.idata$5è$0À.idata$4ð.0À.idata$6ø0Àÿ%FinflateSetDictionary.text.idata$7.idata$5.idata$4.idata$64DinflateSetDictionary__imp_inflateSetDictionary_head_zlib1_dlld000070.o/ 1371036826 1007 513 644 512 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%EinflateResetKeep.text.idata$7.idata$5.idata$4.idata$6,<inflateResetKeep__imp_inflateResetKeep_head_zlib1_dlld000069.o/ 1371036826 1007 513 644 502 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%DinflateReset2.text.idata$7.idata$5.idata$4.idata$6&6inflateReset2__imp_inflateReset2_head_zlib1_dlld000068.o/ 1371036826 1007 513 644 500 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%CinflateReset.text.idata$7.idata$5.idata$4.idata$6$4inflateReset__imp_inflateReset_head_zlib1_dlld000067.o/ 1371036826 1007 513 644 500 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%BinflatePrime.text.idata$7.idata$5.idata$4.idata$6$4inflatePrime__imp_inflatePrime_head_zlib1_dlld000066.o/ 1371036826 1007 513 644 498 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%AinflateMark.text.idata$7.idata$5.idata$4.idata$6"2inflateMark__imp_inflateMark_head_zlib1_dlld000065.o/ 1371036826 1007 513 644 500 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%@inflateInit_.text.idata$7.idata$5.idata$4.idata$6$4inflateInit___imp_inflateInit__head_zlib1_dlld000064.o/ 1371036826 1007 513 644 502 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%?inflateInit2_.text.idata$7.idata$5.idata$4.idata$6&6inflateInit2___imp_inflateInit2__head_zlib1_dlld000063.o/ 1371036826 1007 513 644 512 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%>inflateGetHeader.text.idata$7.idata$5.idata$4.idata$6,<inflateGetHeader__imp_inflateGetHeader_head_zlib1_dlld000062.o/ 1371036826 1007 513 644 524 ` d†8.textÜ 0`.idata$7ä0À.idata$5è$0À.idata$4ð.0À.idata$6ø0Àÿ%=inflateGetDictionary.text.idata$7.idata$5.idata$4.idata$64DinflateGetDictionary__imp_inflateGetDictionary_head_zlib1_dlld000061.o/ 1371036826 1007 513 644 496 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%<inflateEnd.text.idata$7.idata$5.idata$4.idata$6 0inflateEnd__imp_inflateEnd_head_zlib1_dlld000060.o/ 1371036826 1007 513 644 498 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%;inflateCopy.text.idata$7.idata$5.idata$4.idata$6"2inflateCopy__imp_inflateCopy_head_zlib1_dlld000059.o/ 1371036826 1007 513 644 512 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%:inflateBackInit_.text.idata$7.idata$5.idata$4.idata$6,<inflateBackInit___imp_inflateBackInit__head_zlib1_dlld000058.o/ 1371036826 1007 513 644 508 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%9inflateBackEnd.text.idata$7.idata$5.idata$4.idata$6(8inflateBackEnd__imp_inflateBackEnd_head_zlib1_dlld000057.o/ 1371036826 1007 513 644 498 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%8inflateBack.text.idata$7.idata$5.idata$4.idata$6"2inflateBack__imp_inflateBack_head_zlib1_dlld000056.o/ 1371036826 1007 513 644 478 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%7inflate.text.idata$7.idata$5.idata$4.idata$6inflate"__imp_inflate_head_zlib1_dlld000055.o/ 1371036826 1007 513 644 478 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%6gzwrite.text.idata$7.idata$5.idata$4.idata$6gzwrite"__imp_gzwrite_head_zlib1_dlld000054.o/ 1371036826 1007 513 644 490 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%5gzvprintf.text.idata$7.idata$5.idata$4.idata$6.gzvprintf__imp_gzvprintf_head_zlib1_dlld000053.o/ 1371036826 1007 513 644 479 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%4gzungetc.text.idata$7.idata$5.idata$4.idata$6gzungetc#__imp_gzungetc_head_zlib1_dll d000052.o/ 1371036826 1007 513 644 479 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%3gztell64.text.idata$7.idata$5.idata$4.idata$6gztell64#__imp_gztell64_head_zlib1_dll d000051.o/ 1371036826 1007 513 644 477 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%2gztell.text.idata$7.idata$5.idata$4.idata$6gztell!__imp_gztell_head_zlib1_dll d000050.o/ 1371036826 1007 513 644 498 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%1gzsetparams.text.idata$7.idata$5.idata$4.idata$6"2gzsetparams__imp_gzsetparams_head_zlib1_dlld000049.o/ 1371036826 1007 513 644 479 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%0gzseek64.text.idata$7.idata$5.idata$4.idata$6gzseek64#__imp_gzseek64_head_zlib1_dll d000048.o/ 1371036826 1007 513 644 477 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%/gzseek.text.idata$7.idata$5.idata$4.idata$6gzseek!__imp_gzseek_head_zlib1_dll d000047.o/ 1371036826 1007 513 644 479 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%.gzrewind.text.idata$7.idata$5.idata$4.idata$6gzrewind#__imp_gzrewind_head_zlib1_dll d000046.o/ 1371036826 1007 513 644 477 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%-gzread.text.idata$7.idata$5.idata$4.idata$6gzread!__imp_gzread_head_zlib1_dll d000045.o/ 1371036826 1007 513 644 477 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%,gzputs.text.idata$7.idata$5.idata$4.idata$6gzputs!__imp_gzputs_head_zlib1_dll d000044.o/ 1371036826 1007 513 644 477 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%+gzputc.text.idata$7.idata$5.idata$4.idata$6gzputc!__imp_gzputc_head_zlib1_dll d000043.o/ 1371036826 1007 513 644 479 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%*gzprintf.text.idata$7.idata$5.idata$4.idata$6gzprintf#__imp_gzprintf_head_zlib1_dll d000042.o/ 1371036826 1007 513 644 479 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%)gzopen_w.text.idata$7.idata$5.idata$4.idata$6gzopen_w#__imp_gzopen_w_head_zlib1_dll d000041.o/ 1371036826 1007 513 644 479 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%(gzopen64.text.idata$7.idata$5.idata$4.idata$6gzopen64#__imp_gzopen64_head_zlib1_dll d000040.o/ 1371036826 1007 513 644 477 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%'gzopen.text.idata$7.idata$5.idata$4.idata$6gzopen!__imp_gzopen_head_zlib1_dll d000039.o/ 1371036826 1007 513 644 496 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%&gzoffset64.text.idata$7.idata$5.idata$4.idata$6 0gzoffset64__imp_gzoffset64_head_zlib1_dlld000038.o/ 1371036826 1007 513 644 479 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%%gzoffset.text.idata$7.idata$5.idata$4.idata$6gzoffset#__imp_gzoffset_head_zlib1_dll d000037.o/ 1371036826 1007 513 644 477 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%$gzgets.text.idata$7.idata$5.idata$4.idata$6gzgets!__imp_gzgets_head_zlib1_dll d000036.o/ 1371036826 1007 513 644 478 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%#gzgetc_.text.idata$7.idata$5.idata$4.idata$6gzgetc_"__imp_gzgetc__head_zlib1_dlld000035.o/ 1371036826 1007 513 644 477 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%"gzgetc.text.idata$7.idata$5.idata$4.idata$6gzgetc!__imp_gzgetc_head_zlib1_dll d000034.o/ 1371036826 1007 513 644 478 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%!gzflush.text.idata$7.idata$5.idata$4.idata$6gzflush"__imp_gzflush_head_zlib1_dlld000033.o/ 1371036826 1007 513 644 478 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ% gzerror.text.idata$7.idata$5.idata$4.idata$6gzerror"__imp_gzerror_head_zlib1_dlld000032.o/ 1371036826 1007 513 644 472 ` d†(.textÜ 0`.idata$7ä 0À.idata$5è0À.idata$4ð0À.idata$6ø0Àÿ%gzeof.text.idata$7.idata$5.idata$4.idata$6gzeof __imp_gzeof_head_zlib1_dlld000031.o/ 1371036826 1007 513 644 478 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%gzdopen.text.idata$7.idata$5.idata$4.idata$6gzdopen"__imp_gzdopen_head_zlib1_dlld000030.o/ 1371036826 1007 513 644 479 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%gzdirect.text.idata$7.idata$5.idata$4.idata$6gzdirect#__imp_gzdirect_head_zlib1_dll d000029.o/ 1371036826 1007 513 644 490 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%gzclose_w.text.idata$7.idata$5.idata$4.idata$6.gzclose_w__imp_gzclose_w_head_zlib1_dlld000028.o/ 1371036826 1007 513 644 490 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%gzclose_r.text.idata$7.idata$5.idata$4.idata$6.gzclose_r__imp_gzclose_r_head_zlib1_dlld000027.o/ 1371036826 1007 513 644 478 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%gzclose.text.idata$7.idata$5.idata$4.idata$6gzclose"__imp_gzclose_head_zlib1_dlld000026.o/ 1371036826 1007 513 644 496 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%gzclearerr.text.idata$7.idata$5.idata$4.idata$6 0gzclearerr__imp_gzclearerr_head_zlib1_dlld000025.o/ 1371036826 1007 513 644 479 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%gzbuffer.text.idata$7.idata$5.idata$4.idata$6gzbuffer#__imp_gzbuffer_head_zlib1_dll d000024.o/ 1371036826 1007 513 644 502 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%get_crc_table.text.idata$7.idata$5.idata$4.idata$6&6get_crc_table__imp_get_crc_table_head_zlib1_dlld000023.o/ 1371036826 1007 513 644 498 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%deflateTune.text.idata$7.idata$5.idata$4.idata$6"2deflateTune__imp_deflateTune_head_zlib1_dlld000022.o/ 1371036826 1007 513 644 512 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%deflateSetHeader.text.idata$7.idata$5.idata$4.idata$6,<deflateSetHeader__imp_deflateSetHeader_head_zlib1_dlld000021.o/ 1371036826 1007 513 644 524 ` d†8.textÜ 0`.idata$7ä0À.idata$5è$0À.idata$4ð.0À.idata$6ø0Àÿ%deflateSetDictionary.text.idata$7.idata$5.idata$4.idata$64DdeflateSetDictionary__imp_deflateSetDictionary_head_zlib1_dlld000020.o/ 1371036826 1007 513 644 512 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%deflateResetKeep.text.idata$7.idata$5.idata$4.idata$6,<deflateResetKeep__imp_deflateResetKeep_head_zlib1_dlld000019.o/ 1371036826 1007 513 644 500 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%deflateReset.text.idata$7.idata$5.idata$4.idata$6$4deflateReset__imp_deflateReset_head_zlib1_dlld000018.o/ 1371036826 1007 513 644 500 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%deflatePrime.text.idata$7.idata$5.idata$4.idata$6$4deflatePrime__imp_deflatePrime_head_zlib1_dlld000017.o/ 1371036826 1007 513 644 508 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%deflatePending.text.idata$7.idata$5.idata$4.idata$6(8deflatePending__imp_deflatePending_head_zlib1_dlld000016.o/ 1371036826 1007 513 644 502 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%deflateParams.text.idata$7.idata$5.idata$4.idata$6&6deflateParams__imp_deflateParams_head_zlib1_dlld000015.o/ 1371036826 1007 513 644 500 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%deflateInit_.text.idata$7.idata$5.idata$4.idata$6$4deflateInit___imp_deflateInit__head_zlib1_dlld000014.o/ 1371036826 1007 513 644 502 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ% deflateInit2_.text.idata$7.idata$5.idata$4.idata$6&6deflateInit2___imp_deflateInit2__head_zlib1_dlld000013.o/ 1371036826 1007 513 644 496 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ% deflateEnd.text.idata$7.idata$5.idata$4.idata$6 0deflateEnd__imp_deflateEnd_head_zlib1_dlld000012.o/ 1371036826 1007 513 644 498 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ% deflateCopy.text.idata$7.idata$5.idata$4.idata$6"2deflateCopy__imp_deflateCopy_head_zlib1_dlld000011.o/ 1371036826 1007 513 644 500 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ% deflateBound.text.idata$7.idata$5.idata$4.idata$6$4deflateBound__imp_deflateBound_head_zlib1_dlld000010.o/ 1371036826 1007 513 644 478 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ% deflate.text.idata$7.idata$5.idata$4.idata$6deflate"__imp_deflate_head_zlib1_dlld000009.o/ 1371036826 1007 513 644 510 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%crc32_combine64.text.idata$7.idata$5.idata$4.idata$6*:crc32_combine64__imp_crc32_combine64_head_zlib1_dlld000008.o/ 1371036826 1007 513 644 502 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%crc32_combine.text.idata$7.idata$5.idata$4.idata$6&6crc32_combine__imp_crc32_combine_head_zlib1_dlld000007.o/ 1371036826 1007 513 644 472 ` d†(.textÜ 0`.idata$7ä 0À.idata$5è0À.idata$4ð0À.idata$6ø0Àÿ%crc32.text.idata$7.idata$5.idata$4.idata$6crc32 __imp_crc32_head_zlib1_dlld000006.o/ 1371036826 1007 513 644 502 ` d†0.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð&0À.idata$6ø0Àÿ%compressBound.text.idata$7.idata$5.idata$4.idata$6&6compressBound__imp_compressBound_head_zlib1_dlld000005.o/ 1371036826 1007 513 644 490 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%compress2.text.idata$7.idata$5.idata$4.idata$6.compress2__imp_compress2_head_zlib1_dlld000004.o/ 1371036826 1007 513 644 479 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%compress.text.idata$7.idata$5.idata$4.idata$6compress#__imp_compress_head_zlib1_dll d000003.o/ 1371036826 1007 513 644 514 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%adler32_combine64.text.idata$7.idata$5.idata$4.idata$6.>adler32_combine64__imp_adler32_combine64_head_zlib1_dlld000002.o/ 1371036826 1007 513 644 510 ` d†4.textÜ  0`.idata$7ä0À.idata$5è 0À.idata$4ð*0À.idata$6ø0Àÿ%adler32_combine.text.idata$7.idata$5.idata$4.idata$6*:adler32_combine__imp_adler32_combine_head_zlib1_dlld000001.o/ 1371036826 1007 513 644 478 ` d†,.textÜ 0`.idata$7ä0À.idata$5è0À.idata$4ð"0À.idata$6 ø0Àÿ%adler32.text.idata$7.idata$5.idata$4.idata$6adler32"__imp_adler32_head_zlib1_dlltcl8.6.5/compat/zlib/gzlib.c0000644000175000017500000004003712663660065015271 0ustar sergeisergei/* gzlib.c -- zlib functions common to reading and writing gzip files * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" #if defined(_WIN32) && !defined(__BORLANDC__) # define LSEEK _lseeki64 #else #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 # define LSEEK lseek64 #else # define LSEEK lseek #endif #endif /* Local functions */ local void gz_reset OF((gz_statep)); local gzFile gz_open OF((const void *, int, const char *)); #if defined UNDER_CE /* Map the Windows error number in ERROR to a locale-dependent error message string and return a pointer to it. Typically, the values for ERROR come from GetLastError. The string pointed to shall not be modified by the application, but may be overwritten by a subsequent call to gz_strwinerror The gz_strwinerror function does not change the current setting of GetLastError. */ char ZLIB_INTERNAL *gz_strwinerror (error) DWORD error; { static char buf[1024]; wchar_t *msgbuf; DWORD lasterr = GetLastError(); DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error, 0, /* Default language */ (LPVOID)&msgbuf, 0, NULL); if (chars != 0) { /* If there is an \r\n appended, zap it. */ if (chars >= 2 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { chars -= 2; msgbuf[chars] = 0; } if (chars > sizeof (buf) - 1) { chars = sizeof (buf) - 1; msgbuf[chars] = 0; } wcstombs(buf, msgbuf, chars + 1); LocalFree(msgbuf); } else { sprintf(buf, "unknown win32 error (%ld)", error); } SetLastError(lasterr); return buf; } #endif /* UNDER_CE */ /* Reset gzip file state */ local void gz_reset(state) gz_statep state; { state->x.have = 0; /* no output data available */ if (state->mode == GZ_READ) { /* for reading ... */ state->eof = 0; /* not at end of file */ state->past = 0; /* have not read past end yet */ state->how = LOOK; /* look for gzip header */ } state->seek = 0; /* no seek request pending */ gz_error(state, Z_OK, NULL); /* clear error */ state->x.pos = 0; /* no uncompressed data yet */ state->strm.avail_in = 0; /* no input data yet */ } /* Open a gzip file either by name or file descriptor. */ local gzFile gz_open(path, fd, mode) const void *path; int fd; const char *mode; { gz_statep state; size_t len; int oflag; #ifdef O_CLOEXEC int cloexec = 0; #endif #ifdef O_EXCL int exclusive = 0; #endif /* check input */ if (path == NULL) return NULL; /* allocate gzFile structure to return */ state = (gz_statep)malloc(sizeof(gz_state)); if (state == NULL) return NULL; state->size = 0; /* no buffers allocated yet */ state->want = GZBUFSIZE; /* requested buffer size */ state->msg = NULL; /* no error message yet */ /* interpret mode */ state->mode = GZ_NONE; state->level = Z_DEFAULT_COMPRESSION; state->strategy = Z_DEFAULT_STRATEGY; state->direct = 0; while (*mode) { if (*mode >= '0' && *mode <= '9') state->level = *mode - '0'; else switch (*mode) { case 'r': state->mode = GZ_READ; break; #ifndef NO_GZCOMPRESS case 'w': state->mode = GZ_WRITE; break; case 'a': state->mode = GZ_APPEND; break; #endif case '+': /* can't read and write at the same time */ free(state); return NULL; case 'b': /* ignore -- will request binary anyway */ break; #ifdef O_CLOEXEC case 'e': cloexec = 1; break; #endif #ifdef O_EXCL case 'x': exclusive = 1; break; #endif case 'f': state->strategy = Z_FILTERED; break; case 'h': state->strategy = Z_HUFFMAN_ONLY; break; case 'R': state->strategy = Z_RLE; break; case 'F': state->strategy = Z_FIXED; break; case 'T': state->direct = 1; break; default: /* could consider as an error, but just ignore */ ; } mode++; } /* must provide an "r", "w", or "a" */ if (state->mode == GZ_NONE) { free(state); return NULL; } /* can't force transparent read */ if (state->mode == GZ_READ) { if (state->direct) { free(state); return NULL; } state->direct = 1; /* for empty file */ } /* save the path name for error messages */ #ifdef _WIN32 if (fd == -2) { len = wcstombs(NULL, path, 0); if (len == (size_t)-1) len = 0; } else #endif len = strlen((const char *)path); state->path = (char *)malloc(len + 1); if (state->path == NULL) { free(state); return NULL; } #ifdef _WIN32 if (fd == -2) if (len) wcstombs(state->path, path, len + 1); else *(state->path) = 0; else #endif #if !defined(NO_snprintf) && !defined(NO_vsnprintf) snprintf(state->path, len + 1, "%s", (const char *)path); #else strcpy(state->path, path); #endif /* compute the flags for open() */ oflag = #ifdef O_LARGEFILE O_LARGEFILE | #endif #ifdef O_BINARY O_BINARY | #endif #ifdef O_CLOEXEC (cloexec ? O_CLOEXEC : 0) | #endif (state->mode == GZ_READ ? O_RDONLY : (O_WRONLY | O_CREAT | #ifdef O_EXCL (exclusive ? O_EXCL : 0) | #endif (state->mode == GZ_WRITE ? O_TRUNC : O_APPEND))); /* open the file with the appropriate flags (or just use fd) */ state->fd = fd > -1 ? fd : ( #ifdef _WIN32 fd == -2 ? _wopen(path, oflag, 0666) : #endif open((const char *)path, oflag, 0666)); if (state->fd == -1) { free(state->path); free(state); return NULL; } if (state->mode == GZ_APPEND) state->mode = GZ_WRITE; /* simplify later checks */ /* save the current position for rewinding (only if reading) */ if (state->mode == GZ_READ) { state->start = LSEEK(state->fd, 0, SEEK_CUR); if (state->start == -1) state->start = 0; } /* initialize stream */ gz_reset(state); /* return stream */ return (gzFile)state; } /* -- see zlib.h -- */ gzFile ZEXPORT gzopen(path, mode) const char *path; const char *mode; { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ gzFile ZEXPORT gzopen64(path, mode) const char *path; const char *mode; { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ gzFile ZEXPORT gzdopen(fd, mode) int fd; const char *mode; { char *path; /* identifier for error messages */ gzFile gz; if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) return NULL; #if !defined(NO_snprintf) && !defined(NO_vsnprintf) snprintf(path, 7 + 3 * sizeof(int), "", fd); /* for debugging */ #else sprintf(path, "", fd); /* for debugging */ #endif gz = gz_open(path, fd, mode); free(path); return gz; } /* -- see zlib.h -- */ #ifdef _WIN32 gzFile ZEXPORT gzopen_w(path, mode) const wchar_t *path; const char *mode; { return gz_open(path, -2, mode); } #endif /* -- see zlib.h -- */ int ZEXPORT gzbuffer(file, size) gzFile file; unsigned size; { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* make sure we haven't already allocated memory */ if (state->size != 0) return -1; /* check and set requested size */ if (size < 2) size = 2; /* need two bytes to check magic header */ state->want = size; return 0; } /* -- see zlib.h -- */ int ZEXPORT gzrewind(file) gzFile file; { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* back up and start over */ if (LSEEK(state->fd, state->start, SEEK_SET) == -1) return -1; gz_reset(state); return 0; } /* -- see zlib.h -- */ z_off64_t ZEXPORT gzseek64(file, offset, whence) gzFile file; z_off64_t offset; int whence; { unsigned n; z_off64_t ret; gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* check that there's no error */ if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; /* can only seek from start or relative to current position */ if (whence != SEEK_SET && whence != SEEK_CUR) return -1; /* normalize offset to a SEEK_CUR specification */ if (whence == SEEK_SET) offset -= state->x.pos; else if (state->seek) offset += state->skip; state->seek = 0; /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && state->x.pos + offset >= 0) { ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); if (ret == -1) return -1; state->x.have = 0; state->eof = 0; state->past = 0; state->seek = 0; gz_error(state, Z_OK, NULL); state->strm.avail_in = 0; state->x.pos += offset; return state->x.pos; } /* calculate skip amount, rewinding if needed for back seek when reading */ if (offset < 0) { if (state->mode != GZ_READ) /* writing -- can't go backwards */ return -1; offset += state->x.pos; if (offset < 0) /* before start of file! */ return -1; if (gzrewind(file) == -1) /* rewind, then skip to offset */ return -1; } /* if reading, skip what's in output buffer (one less gzgetc() check) */ if (state->mode == GZ_READ) { n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? (unsigned)offset : state->x.have; state->x.have -= n; state->x.next += n; state->x.pos += n; offset -= n; } /* request skip (if not zero) */ if (offset) { state->seek = 1; state->skip = offset; } return state->x.pos + offset; } /* -- see zlib.h -- */ z_off_t ZEXPORT gzseek(file, offset, whence) gzFile file; z_off_t offset; int whence; { z_off64_t ret; ret = gzseek64(file, (z_off64_t)offset, whence); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ z_off64_t ZEXPORT gztell64(file) gzFile file; { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* return position */ return state->x.pos + (state->seek ? state->skip : 0); } /* -- see zlib.h -- */ z_off_t ZEXPORT gztell(file) gzFile file; { z_off64_t ret; ret = gztell64(file); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ z_off64_t ZEXPORT gzoffset64(file) gzFile file; { z_off64_t offset; gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* compute and return effective offset in file */ offset = LSEEK(state->fd, 0, SEEK_CUR); if (offset == -1) return -1; if (state->mode == GZ_READ) /* reading */ offset -= state->strm.avail_in; /* don't count buffered input */ return offset; } /* -- see zlib.h -- */ z_off_t ZEXPORT gzoffset(file) gzFile file; { z_off64_t ret; ret = gzoffset64(file); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ int ZEXPORT gzeof(file) gzFile file; { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return 0; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return 0; /* return end-of-file state */ return state->mode == GZ_READ ? state->past : 0; } /* -- see zlib.h -- */ const char * ZEXPORT gzerror(file, errnum) gzFile file; int *errnum; { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return NULL; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return NULL; /* return error information */ if (errnum != NULL) *errnum = state->err; return state->err == Z_MEM_ERROR ? "out of memory" : (state->msg == NULL ? "" : state->msg); } /* -- see zlib.h -- */ void ZEXPORT gzclearerr(file) gzFile file; { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return; /* clear error and end-of-file */ if (state->mode == GZ_READ) { state->eof = 0; state->past = 0; } gz_error(state, Z_OK, NULL); } /* Create an error message in allocated memory and set state->err and state->msg accordingly. Free any previous error message already there. Do not try to free or allocate space if the error is Z_MEM_ERROR (out of memory). Simply save the error message as a static string. If there is an allocation failure constructing the error message, then convert the error to out of memory. */ void ZLIB_INTERNAL gz_error(state, err, msg) gz_statep state; int err; const char *msg; { /* free previously allocated message and clear */ if (state->msg != NULL) { if (state->err != Z_MEM_ERROR) free(state->msg); state->msg = NULL; } /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ if (err != Z_OK && err != Z_BUF_ERROR) state->x.have = 0; /* set error code, and if no message, then done */ state->err = err; if (msg == NULL) return; /* for an out of memory error, return literal string when requested */ if (err == Z_MEM_ERROR) return; /* construct error message with path */ if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { state->err = Z_MEM_ERROR; return; } #if !defined(NO_snprintf) && !defined(NO_vsnprintf) snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, "%s%s%s", state->path, ": ", msg); #else strcpy(state->msg, state->path); strcat(state->msg, ": "); strcat(state->msg, msg); #endif return; } #ifndef INT_MAX /* portably return maximum value for an int (when limits.h presumed not available) -- we need to do this to cover cases where 2's complement not used, since C standard permits 1's complement and sign-bit representations, otherwise we could just use ((unsigned)-1) >> 1 */ unsigned ZLIB_INTERNAL gz_intmax() { unsigned p, q; p = 1; do { q = p; p <<= 1; p++; } while (p > q); return q >> 1; } #endif tcl8.6.5/compat/zlib/crc32.h0000644000175000017500000007354212663660065015112 0ustar sergeisergei/* crc32.h -- tables for rapid CRC calculation * Generated automatically by crc32.c */ local const z_crc_t FAR crc_table[TBLS][256] = { { 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, 0x2d02ef8dUL #ifdef BYFOUR }, { 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, 0x9324fd72UL }, { 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, 0xbe9834edUL }, { 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, 0xde0506f1UL }, { 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, 0x8def022dUL }, { 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, 0x72fd2493UL }, { 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, 0xed3498beUL }, { 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, 0xf10605deUL #endif } }; tcl8.6.5/compat/zlib/make_vms.com0000644000175000017500000006344212663660065016325 0ustar sergeisergei$! make libz under VMS written by $! Martin P.J. Zinser $! $! In case of problems with the install you might contact me at $! zinser@zinser.no-ip.info(preferred) or $! martin.zinser@eurexchange.com (work) $! $! Make procedure history for Zlib $! $!------------------------------------------------------------------------------ $! Version history $! 0.01 20060120 First version to receive a number $! 0.02 20061008 Adapt to new Makefile.in $! 0.03 20091224 Add support for large file check $! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite $! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in $! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples $! subdir path, update module search in makefile.in $! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned $! shared image creation $! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared $! image $! 0.09 20120305 SMS. P1 sets builder ("MMK", "MMS", " " (built-in)). $! "" -> automatic, preference: MMK, MMS, built-in. $! $ on error then goto err_exit $! $ true = 1 $ false = 0 $ tmpnam = "temp_" + f$getjpi("","pid") $ tt = tmpnam + ".txt" $ tc = tmpnam + ".c" $ th = tmpnam + ".h" $ define/nolog tconfig 'th' $ its_decc = false $ its_vaxc = false $ its_gnuc = false $ s_case = False $! $! Setup variables holding "config" information $! $ Make = "''p1'" $ name = "Zlib" $ version = "?.?.?" $ v_string = "ZLIB_VERSION" $ v_file = "zlib.h" $ ccopt = "/include = []" $ lopts = "" $ dnsrl = "" $ aconf_in_file = "zconf.h.in#zconf.h_in#zconf_h.in" $ conf_check_string = "" $ linkonly = false $ optfile = name + ".opt" $ mapfile = name + ".map" $ libdefs = "" $ vax = f$getsyi("HW_MODEL").lt.1024 $ axp = f$getsyi("HW_MODEL").ge.1024 .and. f$getsyi("HW_MODEL").lt.4096 $ ia64 = f$getsyi("HW_MODEL").ge.4096 $! $! 2012-03-05 SMS. $! Why is this needed? And if it is needed, why not simply ".not. vax"? $! $!!! if axp .or. ia64 then set proc/parse=extended $! $ whoami = f$parse(f$environment("Procedure"),,,,"NO_CONCEAL") $ mydef = F$parse(whoami,,,"DEVICE") $ mydir = f$parse(whoami,,,"DIRECTORY") - "][" $ myproc = f$parse(whoami,,,"Name") + f$parse(whoami,,,"type") $! $! Check for MMK/MMS $! $ if (Make .eqs. "") $ then $ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS" $ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK" $ else $ Make = f$edit( Make, "trim") $ endif $! $ gosub find_version $! $ open/write topt tmp.opt $ open/write optf 'optfile' $! $ gosub check_opts $! $! Look for the compiler used $! $ gosub check_compiler $ close topt $ close optf $! $ if its_decc $ then $ ccopt = "/prefix=all" + ccopt $ if f$trnlnm("SYS") .eqs. "" $ then $ if axp $ then $ define sys sys$library: $ else $ ccopt = "/decc" + ccopt $ define sys decc$library_include: $ endif $ endif $! $! 2012-03-05 SMS. $! Why /NAMES = AS_IS? Why not simply ".not. vax"? And why not on VAX? $! $ if axp .or. ia64 $ then $ ccopt = ccopt + "/name=as_is/opt=(inline=speed)" $ s_case = true $ endif $ endif $ if its_vaxc .or. its_gnuc $ then $ if f$trnlnm("SYS").eqs."" then define sys sys$library: $ endif $! $! Build a fake configure input header $! $ open/write conf_hin config.hin $ write conf_hin "#undef _LARGEFILE64_SOURCE" $ close conf_hin $! $! $ i = 0 $FIND_ACONF: $ fname = f$element(i,"#",aconf_in_file) $ if fname .eqs. "#" then goto AMISS_ERR $ if f$search(fname) .eqs. "" $ then $ i = i + 1 $ goto find_aconf $ endif $ open/read/err=aconf_err aconf_in 'fname' $ open/write aconf zconf.h $ACONF_LOOP: $ read/end_of_file=aconf_exit aconf_in line $ work = f$edit(line, "compress,trim") $ if f$extract(0,6,work) .nes. "#undef" $ then $ if f$extract(0,12,work) .nes. "#cmakedefine" $ then $ write aconf line $ endif $ else $ cdef = f$element(1," ",work) $ gosub check_config $ endif $ goto aconf_loop $ACONF_EXIT: $ write aconf "" $ write aconf "/* VMS specifics added by make_vms.com: */" $ write aconf "#define VMS 1" $ write aconf "#include " $ write aconf "#include " $ write aconf "#ifdef _LARGEFILE" $ write aconf "# define off64_t __off64_t" $ write aconf "# define fopen64 fopen" $ write aconf "# define fseeko64 fseeko" $ write aconf "# define lseek64 lseek" $ write aconf "# define ftello64 ftell" $ write aconf "#endif" $ write aconf "#if !defined( __VAX) && (__CRTL_VER >= 70312000)" $ write aconf "# define HAVE_VSNPRINTF" $ write aconf "#endif" $ close aconf_in $ close aconf $ if f$search("''th'") .nes. "" then delete 'th';* $! Build the thing plain or with mms $! $ write sys$output "Compiling Zlib sources ..." $ if make.eqs."" $ then $ if (f$search( "example.obj;*") .nes. "") then delete example.obj;* $ if (f$search( "minigzip.obj;*") .nes. "") then delete minigzip.obj;* $ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" - adler32.c zlib.h zconf.h $ CALL MAKE compress.OBJ "CC ''CCOPT' compress" - compress.c zlib.h zconf.h $ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" - crc32.c zlib.h zconf.h $ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" - deflate.c deflate.h zutil.h zlib.h zconf.h $ CALL MAKE gzclose.OBJ "CC ''CCOPT' gzclose" - gzclose.c zutil.h zlib.h zconf.h $ CALL MAKE gzlib.OBJ "CC ''CCOPT' gzlib" - gzlib.c zutil.h zlib.h zconf.h $ CALL MAKE gzread.OBJ "CC ''CCOPT' gzread" - gzread.c zutil.h zlib.h zconf.h $ CALL MAKE gzwrite.OBJ "CC ''CCOPT' gzwrite" - gzwrite.c zutil.h zlib.h zconf.h $ CALL MAKE infback.OBJ "CC ''CCOPT' infback" - infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h $ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" - inffast.c zutil.h zlib.h zconf.h inffast.h $ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" - inflate.c zutil.h zlib.h zconf.h infblock.h $ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" - inftrees.c zutil.h zlib.h zconf.h inftrees.h $ CALL MAKE trees.OBJ "CC ''CCOPT' trees" - trees.c deflate.h zutil.h zlib.h zconf.h $ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" - uncompr.c zlib.h zconf.h $ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" - zutil.c zutil.h zlib.h zconf.h $ write sys$output "Building Zlib ..." $ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ $ write sys$output "Building example..." $ CALL MAKE example.OBJ "CC ''CCOPT' [.test]example" - [.test]example.c zlib.h zconf.h $ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb $ write sys$output "Building minigzip..." $ CALL MAKE minigzip.OBJ "CC ''CCOPT' [.test]minigzip" - [.test]minigzip.c zlib.h zconf.h $ call make minigzip.exe - "LINK minigzip,libz.olb/lib" - minigzip.obj libz.olb $ else $ gosub crea_mms $ write sys$output "Make ''name' ''version' with ''Make' " $ 'make' $ endif $! $! Create shareable image $! $ gosub crea_olist $ write sys$output "Creating libzshr.exe" $ call map_2_shopt 'mapfile' 'optfile' $ LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,'optfile'/opt $ write sys$output "Zlib build completed" $ delete/nolog tmp.opt;* $ exit $AMISS_ERR: $ write sys$output "No source for config.hin found." $ write sys$output "Tried any of ''aconf_in_file'" $ goto err_exit $CC_ERR: $ write sys$output "C compiler required to build ''name'" $ goto err_exit $ERR_EXIT: $ set message/facil/ident/sever/text $ close/nolog optf $ close/nolog topt $ close/nolog aconf_in $ close/nolog aconf $ close/nolog out $ close/nolog min $ close/nolog mod $ close/nolog h_in $ write sys$output "Exiting..." $ exit 2 $! $! $MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES $ V = 'F$Verify(0) $! P1 = What we are trying to make $! P2 = Command to make it $! P3 - P8 What it depends on $ $ If F$Search(P1) .Eqs. "" Then Goto Makeit $ Time = F$CvTime(F$File(P1,"RDT")) $arg=3 $Loop: $ Argument = P'arg $ If Argument .Eqs. "" Then Goto Exit $ El=0 $Loop2: $ File = F$Element(El," ",Argument) $ If File .Eqs. " " Then Goto Endl $ AFile = "" $Loop3: $ OFile = AFile $ AFile = F$Search(File) $ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl $ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit $ Goto Loop3 $NextEL: $ El = El + 1 $ Goto Loop2 $EndL: $ arg=arg+1 $ If arg .Le. 8 Then Goto Loop $ Goto Exit $ $Makeit: $ VV=F$VERIFY(0) $ write sys$output P2 $ 'P2 $ VV='F$Verify(VV) $Exit: $ If V Then Set Verify $ENDSUBROUTINE $!------------------------------------------------------------------------------ $! $! Check command line options and set symbols accordingly $! $!------------------------------------------------------------------------------ $! Version history $! 0.01 20041206 First version to receive a number $! 0.02 20060126 Add new "HELP" target $ CHECK_OPTS: $ i = 1 $ OPT_LOOP: $ if i .lt. 9 $ then $ cparm = f$edit(p'i',"upcase") $! $! Check if parameter actually contains something $! $ if f$edit(cparm,"trim") .nes. "" $ then $ if cparm .eqs. "DEBUG" $ then $ ccopt = ccopt + "/noopt/deb" $ lopts = lopts + "/deb" $ endif $ if f$locate("CCOPT=",cparm) .lt. f$length(cparm) $ then $ start = f$locate("=",cparm) + 1 $ len = f$length(cparm) - start $ ccopt = ccopt + f$extract(start,len,cparm) $ if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) - then s_case = true $ endif $ if cparm .eqs. "LINK" then linkonly = true $ if f$locate("LOPTS=",cparm) .lt. f$length(cparm) $ then $ start = f$locate("=",cparm) + 1 $ len = f$length(cparm) - start $ lopts = lopts + f$extract(start,len,cparm) $ endif $ if f$locate("CC=",cparm) .lt. f$length(cparm) $ then $ start = f$locate("=",cparm) + 1 $ len = f$length(cparm) - start $ cc_com = f$extract(start,len,cparm) if (cc_com .nes. "DECC") .and. - (cc_com .nes. "VAXC") .and. - (cc_com .nes. "GNUC") $ then $ write sys$output "Unsupported compiler choice ''cc_com' ignored" $ write sys$output "Use DECC, VAXC, or GNUC instead" $ else $ if cc_com .eqs. "DECC" then its_decc = true $ if cc_com .eqs. "VAXC" then its_vaxc = true $ if cc_com .eqs. "GNUC" then its_gnuc = true $ endif $ endif $ if f$locate("MAKE=",cparm) .lt. f$length(cparm) $ then $ start = f$locate("=",cparm) + 1 $ len = f$length(cparm) - start $ mmks = f$extract(start,len,cparm) $ if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS") $ then $ make = mmks $ else $ write sys$output "Unsupported make choice ''mmks' ignored" $ write sys$output "Use MMK or MMS instead" $ endif $ endif $ if cparm .eqs. "HELP" then gosub bhelp $ endif $ i = i + 1 $ goto opt_loop $ endif $ return $!------------------------------------------------------------------------------ $! $! Look for the compiler used $! $! Version history $! 0.01 20040223 First version to receive a number $! 0.02 20040229 Save/set value of decc$no_rooted_search_lists $! 0.03 20060202 Extend handling of GNU C $! 0.04 20090402 Compaq -> hp $CHECK_COMPILER: $ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) $ then $ its_decc = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE") .nes. "") $ its_vaxc = .not. its_decc .and. (F$Search("SYS$System:VAXC.Exe") .nes. "") $ its_gnuc = .not. (its_decc .or. its_vaxc) .and. (f$trnlnm("gnu_cc") .nes. "") $ endif $! $! Exit if no compiler available $! $ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) $ then goto CC_ERR $ else $ if its_decc $ then $ write sys$output "CC compiler check ... hp C" $ if f$trnlnm("decc$no_rooted_search_lists") .nes. "" $ then $ dnrsl = f$trnlnm("decc$no_rooted_search_lists") $ endif $ define/nolog decc$no_rooted_search_lists 1 $ else $ if its_vaxc then write sys$output "CC compiler check ... VAX C" $ if its_gnuc $ then $ write sys$output "CC compiler check ... GNU C" $ if f$trnlnm(topt) then write topt "gnu_cc:[000000]gcclib.olb/lib" $ if f$trnlnm(optf) then write optf "gnu_cc:[000000]gcclib.olb/lib" $ cc = "gcc" $ endif $ if f$trnlnm(topt) then write topt "sys$share:vaxcrtl.exe/share" $ if f$trnlnm(optf) then write optf "sys$share:vaxcrtl.exe/share" $ endif $ endif $ return $!------------------------------------------------------------------------------ $! $! If MMS/MMK are available dump out the descrip.mms if required $! $CREA_MMS: $ write sys$output "Creating descrip.mms..." $ create descrip.mms $ open/append out descrip.mms $ copy sys$input: out $ deck # descrip.mms: MMS description file for building zlib on VMS # written by Martin P.J. Zinser # OBJS = adler32.obj, compress.obj, crc32.obj, gzclose.obj, gzlib.obj\ gzread.obj, gzwrite.obj, uncompr.obj, infback.obj\ deflate.obj, trees.obj, zutil.obj, inflate.obj, \ inftrees.obj, inffast.obj $ eod $ write out "CFLAGS=", ccopt $ write out "LOPTS=", lopts $ write out "all : example.exe minigzip.exe libz.olb" $ copy sys$input: out $ deck @ write sys$output " Example applications available" libz.olb : libz.olb($(OBJS)) @ write sys$output " libz available" example.exe : example.obj libz.olb link $(LOPTS) example,libz.olb/lib minigzip.exe : minigzip.obj libz.olb link $(LOPTS) minigzip,libz.olb/lib clean : delete *.obj;*,libz.olb;*,*.opt;*,*.exe;* # Other dependencies. adler32.obj : adler32.c zutil.h zlib.h zconf.h compress.obj : compress.c zlib.h zconf.h crc32.obj : crc32.c zutil.h zlib.h zconf.h deflate.obj : deflate.c deflate.h zutil.h zlib.h zconf.h example.obj : [.test]example.c zlib.h zconf.h gzclose.obj : gzclose.c zutil.h zlib.h zconf.h gzlib.obj : gzlib.c zutil.h zlib.h zconf.h gzread.obj : gzread.c zutil.h zlib.h zconf.h gzwrite.obj : gzwrite.c zutil.h zlib.h zconf.h inffast.obj : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h inflate.obj : inflate.c zutil.h zlib.h zconf.h inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h minigzip.obj : [.test]minigzip.c zlib.h zconf.h trees.obj : trees.c deflate.h zutil.h zlib.h zconf.h uncompr.obj : uncompr.c zlib.h zconf.h zutil.obj : zutil.c zutil.h zlib.h zconf.h infback.obj : infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h $ eod $ close out $ return $!------------------------------------------------------------------------------ $! $! Read list of core library sources from makefile.in and create options $! needed to build shareable image $! $CREA_OLIST: $ open/read min makefile.in $ open/write mod modules.opt $ src_check_list = "OBJZ =#OBJG =" $MRLOOP: $ read/end=mrdone min rec $ i = 0 $SRC_CHECK_LOOP: $ src_check = f$element(i, "#", src_check_list) $ i = i+1 $ if src_check .eqs. "#" then goto mrloop $ if (f$extract(0,6,rec) .nes. src_check) then goto src_check_loop $ rec = rec - src_check $ gosub extra_filnam $ if (f$element(1,"\",rec) .eqs. "\") then goto mrloop $MRSLOOP: $ read/end=mrdone min rec $ gosub extra_filnam $ if (f$element(1,"\",rec) .nes. "\") then goto mrsloop $MRDONE: $ close min $ close mod $ return $!------------------------------------------------------------------------------ $! $! Take record extracted in crea_olist and split it into single filenames $! $EXTRA_FILNAM: $ myrec = f$edit(rec - "\", "trim,compress") $ i = 0 $FELOOP: $ srcfil = f$element(i," ", myrec) $ if (srcfil .nes. " ") $ then $ write mod f$parse(srcfil,,,"NAME"), ".obj" $ i = i + 1 $ goto feloop $ endif $ return $!------------------------------------------------------------------------------ $! $! Find current Zlib version number $! $FIND_VERSION: $ open/read h_in 'v_file' $hloop: $ read/end=hdone h_in rec $ rec = f$edit(rec,"TRIM") $ if (f$extract(0,1,rec) .nes. "#") then goto hloop $ rec = f$edit(rec - "#", "TRIM") $ if f$element(0," ",rec) .nes. "define" then goto hloop $ if f$element(1," ",rec) .eqs. v_string $ then $ version = 'f$element(2," ",rec)' $ goto hdone $ endif $ goto hloop $hdone: $ close h_in $ return $!------------------------------------------------------------------------------ $! $CHECK_CONFIG: $! $ in_ldef = f$locate(cdef,libdefs) $ if (in_ldef .lt. f$length(libdefs)) $ then $ write aconf "#define ''cdef' 1" $ libdefs = f$extract(0,in_ldef,libdefs) + - f$extract(in_ldef + f$length(cdef) + 1, - f$length(libdefs) - in_ldef - f$length(cdef) - 1, - libdefs) $ else $ if (f$type('cdef') .eqs. "INTEGER") $ then $ write aconf "#define ''cdef' ", 'cdef' $ else $ if (f$type('cdef') .eqs. "STRING") $ then $ write aconf "#define ''cdef' ", """", '''cdef'', """" $ else $ gosub check_cc_def $ endif $ endif $ endif $ return $!------------------------------------------------------------------------------ $! $! Check if this is a define relating to the properties of the C/C++ $! compiler $! $ CHECK_CC_DEF: $ if (cdef .eqs. "_LARGEFILE64_SOURCE") $ then $ copy sys$input: 'tc' $ deck #include "tconfig" #define _LARGEFILE #include int main(){ FILE *fp; fp = fopen("temp.txt","r"); fseeko(fp,1,SEEK_SET); fclose(fp); } $ eod $ test_inv = false $ comm_h = false $ gosub cc_prop_check $ return $ endif $ write aconf "/* ", line, " */" $ return $!------------------------------------------------------------------------------ $! $! Check for properties of C/C++ compiler $! $! Version history $! 0.01 20031020 First version to receive a number $! 0.02 20031022 Added logic for defines with value $! 0.03 20040309 Make sure local config file gets not deleted $! 0.04 20041230 Also write include for configure run $! 0.05 20050103 Add processing of "comment defines" $CC_PROP_CHECK: $ cc_prop = true $ is_need = false $ is_need = (f$extract(0,4,cdef) .eqs. "NEED") .or. (test_inv .eq. true) $ if f$search(th) .eqs. "" then create 'th' $ set message/nofac/noident/nosever/notext $ on error then continue $ cc 'tmpnam' $ if .not. ($status) then cc_prop = false $ on error then continue $! The headers might lie about the capabilities of the RTL $ link 'tmpnam',tmp.opt/opt $ if .not. ($status) then cc_prop = false $ set message/fac/ident/sever/text $ on error then goto err_exit $ delete/nolog 'tmpnam'.*;*/exclude='th' $ if (cc_prop .and. .not. is_need) .or. - (.not. cc_prop .and. is_need) $ then $ write sys$output "Checking for ''cdef'... yes" $ if f$type('cdef_val'_yes) .nes. "" $ then $ if f$type('cdef_val'_yes) .eqs. "INTEGER" - then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_yes) $ if f$type('cdef_val'_yes) .eqs. "STRING" - then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_yes) $ else $ call write_config f$fao("#define !AS 1",cdef) $ endif $ if (cdef .eqs. "HAVE_FSEEKO") .or. (cdef .eqs. "_LARGE_FILES") .or. - (cdef .eqs. "_LARGEFILE64_SOURCE") then - call write_config f$string("#define _LARGEFILE 1") $ else $ write sys$output "Checking for ''cdef'... no" $ if (comm_h) $ then call write_config f$fao("/* !AS */",line) $ else $ if f$type('cdef_val'_no) .nes. "" $ then $ if f$type('cdef_val'_no) .eqs. "INTEGER" - then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_no) $ if f$type('cdef_val'_no) .eqs. "STRING" - then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_no) $ else $ call write_config f$fao("#undef !AS",cdef) $ endif $ endif $ endif $ return $!------------------------------------------------------------------------------ $! $! Check for properties of C/C++ compiler with multiple result values $! $! Version history $! 0.01 20040127 First version $! 0.02 20050103 Reconcile changes from cc_prop up to version 0.05 $CC_MPROP_CHECK: $ cc_prop = true $ i = 1 $ idel = 1 $ MT_LOOP: $ if f$type(result_'i') .eqs. "STRING" $ then $ set message/nofac/noident/nosever/notext $ on error then continue $ cc 'tmpnam'_'i' $ if .not. ($status) then cc_prop = false $ on error then continue $! The headers might lie about the capabilities of the RTL $ link 'tmpnam'_'i',tmp.opt/opt $ if .not. ($status) then cc_prop = false $ set message/fac/ident/sever/text $ on error then goto err_exit $ delete/nolog 'tmpnam'_'i'.*;* $ if (cc_prop) $ then $ write sys$output "Checking for ''cdef'... ", mdef_'i' $ if f$type(mdef_'i') .eqs. "INTEGER" - then call write_config f$fao("#define !AS !UL",cdef,mdef_'i') $ if f$type('cdef_val'_yes) .eqs. "STRING" - then call write_config f$fao("#define !AS !AS",cdef,mdef_'i') $ goto msym_clean $ else $ i = i + 1 $ goto mt_loop $ endif $ endif $ write sys$output "Checking for ''cdef'... no" $ call write_config f$fao("#undef !AS",cdef) $ MSYM_CLEAN: $ if (idel .le. msym_max) $ then $ delete/sym mdef_'idel' $ idel = idel + 1 $ goto msym_clean $ endif $ return $!------------------------------------------------------------------------------ $! $! Write configuration to both permanent and temporary config file $! $! Version history $! 0.01 20031029 First version to receive a number $! $WRITE_CONFIG: SUBROUTINE $ write aconf 'p1' $ open/append confh 'th' $ write confh 'p1' $ close confh $ENDSUBROUTINE $!------------------------------------------------------------------------------ $! $! Analyze the project map file and create the symbol vector for a shareable $! image from it $! $! Version history $! 0.01 20120128 First version $! 0.02 20120226 Add pre-load logic $! $ MAP_2_SHOPT: Subroutine $! $ SAY := "WRITE_ SYS$OUTPUT" $! $ IF F$SEARCH("''P1'") .EQS. "" $ THEN $ SAY "MAP_2_SHOPT-E-NOSUCHFILE: Error, inputfile ''p1' not available" $ goto exit_m2s $ ENDIF $ IF "''P2'" .EQS. "" $ THEN $ SAY "MAP_2_SHOPT: Error, no output file provided" $ goto exit_m2s $ ENDIF $! $ module1 = "deflate#deflateEnd#deflateInit_#deflateParams#deflateSetDictionary" $ module2 = "gzclose#gzerror#gzgetc#gzgets#gzopen#gzprintf#gzputc#gzputs#gzread" $ module3 = "gzseek#gztell#inflate#inflateEnd#inflateInit_#inflateSetDictionary" $ module4 = "inflateSync#uncompress#zlibVersion#compress" $ open/read map 'p1 $ if axp .or. ia64 $ then $ open/write aopt a.opt $ open/write bopt b.opt $ write aopt " CASE_SENSITIVE=YES" $ write bopt "SYMBOL_VECTOR= (-" $ mod_sym_num = 1 $ MOD_SYM_LOOP: $ if f$type(module'mod_sym_num') .nes. "" $ then $ mod_in = 0 $ MOD_SYM_IN: $ shared_proc = f$element(mod_in, "#", module'mod_sym_num') $ if shared_proc .nes. "#" $ then $ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- f$edit(shared_proc,"upcase"),shared_proc) $ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) $ mod_in = mod_in + 1 $ goto mod_sym_in $ endif $ mod_sym_num = mod_sym_num + 1 $ goto mod_sym_loop $ endif $MAP_LOOP: $ read/end=map_end map line $ if (f$locate("{",line).lt. f$length(line)) .or. - (f$locate("global:", line) .lt. f$length(line)) $ then $ proc = true $ goto map_loop $ endif $ if f$locate("}",line).lt. f$length(line) then proc = false $ if f$locate("local:", line) .lt. f$length(line) then proc = false $ if proc $ then $ shared_proc = f$edit(line,"collapse") $ chop_semi = f$locate(";", shared_proc) $ if chop_semi .lt. f$length(shared_proc) then - shared_proc = f$extract(0, chop_semi, shared_proc) $ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- f$edit(shared_proc,"upcase"),shared_proc) $ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) $ endif $ goto map_loop $MAP_END: $ close/nolog aopt $ close/nolog bopt $ open/append libopt 'p2' $ open/read aopt a.opt $ open/read bopt b.opt $ALOOP: $ read/end=aloop_end aopt line $ write libopt line $ goto aloop $ALOOP_END: $ close/nolog aopt $ sv = "" $BLOOP: $ read/end=bloop_end bopt svn $ if (svn.nes."") $ then $ if (sv.nes."") then write libopt sv $ sv = svn $ endif $ goto bloop $BLOOP_END: $ write libopt f$extract(0,f$length(sv)-2,sv), "-" $ write libopt ")" $ close/nolog bopt $ delete/nolog/noconf a.opt;*,b.opt;* $ else $ if vax $ then $ open/append libopt 'p2' $ mod_sym_num = 1 $ VMOD_SYM_LOOP: $ if f$type(module'mod_sym_num') .nes. "" $ then $ mod_in = 0 $ VMOD_SYM_IN: $ shared_proc = f$element(mod_in, "#", module'mod_sym_num') $ if shared_proc .nes. "#" $ then $ write libopt f$fao("UNIVERSAL=!AS",- f$edit(shared_proc,"upcase")) $ mod_in = mod_in + 1 $ goto vmod_sym_in $ endif $ mod_sym_num = mod_sym_num + 1 $ goto vmod_sym_loop $ endif $VMAP_LOOP: $ read/end=vmap_end map line $ if (f$locate("{",line).lt. f$length(line)) .or. - (f$locate("global:", line) .lt. f$length(line)) $ then $ proc = true $ goto vmap_loop $ endif $ if f$locate("}",line).lt. f$length(line) then proc = false $ if f$locate("local:", line) .lt. f$length(line) then proc = false $ if proc $ then $ shared_proc = f$edit(line,"collapse") $ chop_semi = f$locate(";", shared_proc) $ if chop_semi .lt. f$length(shared_proc) then - shared_proc = f$extract(0, chop_semi, shared_proc) $ write libopt f$fao("UNIVERSAL=!AS",- f$edit(shared_proc,"upcase")) $ endif $ goto vmap_loop $VMAP_END: $ else $ write sys$output "Unknown Architecture (Not VAX, AXP, or IA64)" $ write sys$output "No options file created" $ endif $ endif $ EXIT_M2S: $ close/nolog map $ close/nolog libopt $ endsubroutine tcl8.6.5/compat/zlib/zutil.c0000644000175000017500000001636612663660065015341 0ustar sergeisergei/* zutil.c -- target dependent utility functions for the compression library * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" #ifndef Z_SOLO # include "gzguts.h" #endif #ifndef NO_DUMMY_DECL struct internal_state {int dummy;}; /* for buggy compilers */ #endif z_const char * const z_errmsg[10] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ "", /* Z_OK 0 */ "file error", /* Z_ERRNO (-1) */ "stream error", /* Z_STREAM_ERROR (-2) */ "data error", /* Z_DATA_ERROR (-3) */ "insufficient memory", /* Z_MEM_ERROR (-4) */ "buffer error", /* Z_BUF_ERROR (-5) */ "incompatible version",/* Z_VERSION_ERROR (-6) */ ""}; const char * ZEXPORT zlibVersion() { return ZLIB_VERSION; } uLong ZEXPORT zlibCompileFlags() { uLong flags; flags = 0; switch ((int)(sizeof(uInt))) { case 2: break; case 4: flags += 1; break; case 8: flags += 2; break; default: flags += 3; } switch ((int)(sizeof(uLong))) { case 2: break; case 4: flags += 1 << 2; break; case 8: flags += 2 << 2; break; default: flags += 3 << 2; } switch ((int)(sizeof(voidpf))) { case 2: break; case 4: flags += 1 << 4; break; case 8: flags += 2 << 4; break; default: flags += 3 << 4; } switch ((int)(sizeof(z_off_t))) { case 2: break; case 4: flags += 1 << 6; break; case 8: flags += 2 << 6; break; default: flags += 3 << 6; } #ifdef DEBUG flags += 1 << 8; #endif #if defined(ASMV) || defined(ASMINF) flags += 1 << 9; #endif #ifdef ZLIB_WINAPI flags += 1 << 10; #endif #ifdef BUILDFIXED flags += 1 << 12; #endif #ifdef DYNAMIC_CRC_TABLE flags += 1 << 13; #endif #ifdef NO_GZCOMPRESS flags += 1L << 16; #endif #ifdef NO_GZIP flags += 1L << 17; #endif #ifdef PKZIP_BUG_WORKAROUND flags += 1L << 20; #endif #ifdef FASTEST flags += 1L << 21; #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifdef NO_vsnprintf flags += 1L << 25; # ifdef HAS_vsprintf_void flags += 1L << 26; # endif # else # ifdef HAS_vsnprintf_void flags += 1L << 26; # endif # endif #else flags += 1L << 24; # ifdef NO_snprintf flags += 1L << 25; # ifdef HAS_sprintf_void flags += 1L << 26; # endif # else # ifdef HAS_snprintf_void flags += 1L << 26; # endif # endif #endif return flags; } #ifdef DEBUG # ifndef verbose # define verbose 0 # endif int ZLIB_INTERNAL z_verbose = verbose; void ZLIB_INTERNAL z_error (m) char *m; { fprintf(stderr, "%s\n", m); exit(1); } #endif /* exported to allow conversion of error code to string for compress() and * uncompress() */ const char * ZEXPORT zError(err) int err; { return ERR_MSG(err); } #if defined(_WIN32_WCE) /* The Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. */ int errno = 0; #endif #ifndef HAVE_MEMCPY void ZLIB_INTERNAL zmemcpy(dest, source, len) Bytef* dest; const Bytef* source; uInt len; { if (len == 0) return; do { *dest++ = *source++; /* ??? to be unrolled */ } while (--len != 0); } int ZLIB_INTERNAL zmemcmp(s1, s2, len) const Bytef* s1; const Bytef* s2; uInt len; { uInt j; for (j = 0; j < len; j++) { if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; } return 0; } void ZLIB_INTERNAL zmemzero(dest, len) Bytef* dest; uInt len; { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ } while (--len != 0); } #endif #ifndef Z_SOLO #ifdef SYS16BIT #ifdef __TURBOC__ /* Turbo C in 16-bit mode */ # define MY_ZCALLOC /* Turbo C malloc() does not allow dynamic allocation of 64K bytes * and farmalloc(64K) returns a pointer with an offset of 8, so we * must fix the pointer. Warning: the pointer must be put back to its * original form in order to free it, use zcfree(). */ #define MAX_PTR 10 /* 10*64K = 640K */ local int next_ptr = 0; typedef struct ptr_table_s { voidpf org_ptr; voidpf new_ptr; } ptr_table; local ptr_table table[MAX_PTR]; /* This table is used to remember the original form of pointers * to large buffers (64K). Such pointers are normalized with a zero offset. * Since MSDOS is not a preemptive multitasking OS, this table is not * protected from concurrent access. This hack doesn't work anyway on * a protected system like OS/2. Use Microsoft C instead. */ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) { voidpf buf = opaque; /* just to make some compilers happy */ ulg bsize = (ulg)items*size; /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ if (bsize < 65520L) { buf = farmalloc(bsize); if (*(ush*)&buf != 0) return buf; } else { buf = farmalloc(bsize + 16L); } if (buf == NULL || next_ptr >= MAX_PTR) return NULL; table[next_ptr].org_ptr = buf; /* Normalize the pointer to seg:0 */ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; *(ush*)&buf = 0; table[next_ptr++].new_ptr = buf; return buf; } void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { int n; if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; } /* Find the original pointer */ for (n = 0; n < next_ptr; n++) { if (ptr != table[n].new_ptr) continue; farfree(table[n].org_ptr); while (++n < next_ptr) { table[n-1] = table[n]; } next_ptr--; return; } ptr = opaque; /* just to make some compilers happy */ Assert(0, "zcfree: ptr not found"); } #endif /* __TURBOC__ */ #ifdef M_I86 /* Microsoft C in 16-bit mode */ # define MY_ZCALLOC #if (!defined(_MSC_VER) || (_MSC_VER <= 600)) # define _halloc halloc # define _hfree hfree #endif voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) { if (opaque) opaque = 0; /* to make compiler happy */ return _halloc((long)items, size); } void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { if (opaque) opaque = 0; /* to make compiler happy */ _hfree(ptr); } #endif /* M_I86 */ #endif /* SYS16BIT */ #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC extern voidp malloc OF((uInt size)); extern voidp calloc OF((uInt items, uInt size)); extern void free OF((voidpf ptr)); #endif voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) voidpf opaque; unsigned items; unsigned size; { if (opaque) items += size - size; /* make compiler happy */ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } void ZLIB_INTERNAL zcfree (opaque, ptr) voidpf opaque; voidpf ptr; { free(ptr); if (opaque) return; /* make compiler happy */ } #endif /* MY_ZCALLOC */ #endif /* !Z_SOLO */ tcl8.6.5/compat/zlib/doc/0000755000175000017500000000000012665173607014562 5ustar sergeisergeitcl8.6.5/compat/zlib/doc/txtvsbin.txt0000644000175000017500000001211112663653206017174 0ustar sergeisergeiA Fast Method for Identifying Plain Text Files ============================================== Introduction ------------ Given a file coming from an unknown source, it is sometimes desirable to find out whether the format of that file is plain text. Although this may appear like a simple task, a fully accurate detection of the file type requires heavy-duty semantic analysis on the file contents. It is, however, possible to obtain satisfactory results by employing various heuristics. Previous versions of PKZip and other zip-compatible compression tools were using a crude detection scheme: if more than 80% (4/5) of the bytes found in a certain buffer are within the range [7..127], the file is labeled as plain text, otherwise it is labeled as binary. A prominent limitation of this scheme is the restriction to Latin-based alphabets. Other alphabets, like Greek, Cyrillic or Asian, make extensive use of the bytes within the range [128..255], and texts using these alphabets are most often misidentified by this scheme; in other words, the rate of false negatives is sometimes too high, which means that the recall is low. Another weakness of this scheme is a reduced precision, due to the false positives that may occur when binary files containing large amounts of textual characters are misidentified as plain text. In this article we propose a new, simple detection scheme that features a much increased precision and a near-100% recall. This scheme is designed to work on ASCII, Unicode and other ASCII-derived alphabets, and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.) and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings (UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however. The Algorithm ------------- The algorithm works by dividing the set of bytecodes [0..255] into three categories: - The white list of textual bytecodes: 9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255. - The gray list of tolerated bytecodes: 7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC). - The black list of undesired, non-textual bytecodes: 0 (NUL) to 6, 14 to 31. If a file contains at least one byte that belongs to the white list and no byte that belongs to the black list, then the file is categorized as plain text; otherwise, it is categorized as binary. (The boundary case, when the file is empty, automatically falls into the latter category.) Rationale --------- The idea behind this algorithm relies on two observations. The first observation is that, although the full range of 7-bit codes [0..127] is properly specified by the ASCII standard, most control characters in the range [0..31] are not used in practice. The only widely-used, almost universally-portable control codes are 9 (TAB), 10 (LF) and 13 (CR). There are a few more control codes that are recognized on a reduced range of platforms and text viewers/editors: 7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these codes are rarely (if ever) used alone, without being accompanied by some printable text. Even the newer, portable text formats such as XML avoid using control characters outside the list mentioned here. The second observation is that most of the binary files tend to contain control characters, especially 0 (NUL). Even though the older text detection schemes observe the presence of non-ASCII codes from the range [128..255], the precision rarely has to suffer if this upper range is labeled as textual, because the files that are genuinely binary tend to contain both control characters and codes from the upper range. On the other hand, the upper range needs to be labeled as textual, because it is used by virtually all ASCII extensions. In particular, this range is used for encoding non-Latin scripts. Since there is no counting involved, other than simply observing the presence or the absence of some byte values, the algorithm produces consistent results, regardless what alphabet encoding is being used. (If counting were involved, it could be possible to obtain different results on a text encoded, say, using ISO-8859-16 versus UTF-8.) There is an extra category of plain text files that are "polluted" with one or more black-listed codes, either by mistake or by peculiar design considerations. In such cases, a scheme that tolerates a small fraction of black-listed codes would provide an increased recall (i.e. more true positives). This, however, incurs a reduced precision overall, since false positives are more likely to appear in binary files that contain large chunks of textual data. Furthermore, "polluted" plain text should be regarded as binary by general-purpose text detection schemes, because general-purpose text processing algorithms might not be applicable. Under this premise, it is safe to say that our detection method provides a near-100% recall. Experiments have been run on many files coming from various platforms and applications. We tried plain text files, system logs, source code, formatted office documents, compiled object code, etc. The results confirm the optimistic assumptions about the capabilities of this algorithm. -- Cosmin Truta Last updated: 2006-May-28 tcl8.6.5/compat/zlib/doc/algorithm.txt0000644000175000017500000002216712663660065017316 0ustar sergeisergei1. Compression algorithm (deflate) The deflation algorithm used by gzip (also zip and zlib) is a variation of LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in the input data. The second occurrence of a string is replaced by a pointer to the previous string, in the form of a pair (distance, length). Distances are limited to 32K bytes, and lengths are limited to 258 bytes. When a string does not occur anywhere in the previous 32K bytes, it is emitted as a sequence of literal bytes. (In this description, `string' must be taken as an arbitrary sequence of bytes, and is not restricted to printable characters.) Literals or match lengths are compressed with one Huffman tree, and match distances are compressed with another tree. The trees are stored in a compact form at the start of each block. The blocks can have any size (except that the compressed data for one block must fit in available memory). A block is terminated when deflate() determines that it would be useful to start another block with fresh trees. (This is somewhat similar to the behavior of LZW-based _compress_.) Duplicated strings are found using a hash table. All input strings of length 3 are inserted in the hash table. A hash index is computed for the next 3 bytes. If the hash chain for this index is not empty, all strings in the chain are compared with the current input string, and the longest match is selected. The hash chains are searched starting with the most recent strings, to favor small distances and thus take advantage of the Huffman encoding. The hash chains are singly linked. There are no deletions from the hash chains, the algorithm simply discards matches that are too old. To avoid a worst-case situation, very long hash chains are arbitrarily truncated at a certain length, determined by a runtime option (level parameter of deflateInit). So deflate() does not always find the longest possible match but generally finds a match which is long enough. deflate() also defers the selection of matches with a lazy evaluation mechanism. After a match of length N has been found, deflate() searches for a longer match at the next input byte. If a longer match is found, the previous match is truncated to a length of one (thus producing a single literal byte) and the process of lazy evaluation begins again. Otherwise, the original match is kept, and the next match search is attempted only N steps later. The lazy match evaluation is also subject to a runtime parameter. If the current match is long enough, deflate() reduces the search for a longer match, thus speeding up the whole process. If compression ratio is more important than speed, deflate() attempts a complete second search even if the first match is already long enough. The lazy match evaluation is not performed for the fastest compression modes (level parameter 1 to 3). For these fast modes, new strings are inserted in the hash table only when no match was found, or when the match is not too long. This degrades the compression ratio but saves time since there are both fewer insertions and fewer searches. 2. Decompression algorithm (inflate) 2.1 Introduction The key question is how to represent a Huffman code (or any prefix code) so that you can decode fast. The most important characteristic is that shorter codes are much more common than longer codes, so pay attention to decoding the short codes fast, and let the long codes take longer to decode. inflate() sets up a first level table that covers some number of bits of input less than the length of longest code. It gets that many bits from the stream, and looks it up in the table. The table will tell if the next code is that many bits or less and how many, and if it is, it will tell the value, else it will point to the next level table for which inflate() grabs more bits and tries to decode a longer code. How many bits to make the first lookup is a tradeoff between the time it takes to decode and the time it takes to build the table. If building the table took no time (and if you had infinite memory), then there would only be a first level table to cover all the way to the longest code. However, building the table ends up taking a lot longer for more bits since short codes are replicated many times in such a table. What inflate() does is simply to make the number of bits in the first table a variable, and then to set that variable for the maximum speed. For inflate, which has 286 possible codes for the literal/length tree, the size of the first table is nine bits. Also the distance trees have 30 possible values, and the size of the first table is six bits. Note that for each of those cases, the table ended up one bit longer than the ``average'' code length, i.e. the code length of an approximately flat code which would be a little more than eight bits for 286 symbols and a little less than five bits for 30 symbols. 2.2 More details on the inflate table lookup Ok, you want to know what this cleverly obfuscated inflate tree actually looks like. You are correct that it's not a Huffman tree. It is simply a lookup table for the first, let's say, nine bits of a Huffman symbol. The symbol could be as short as one bit or as long as 15 bits. If a particular symbol is shorter than nine bits, then that symbol's translation is duplicated in all those entries that start with that symbol's bits. For example, if the symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a symbol is nine bits long, it appears in the table once. If the symbol is longer than nine bits, then that entry in the table points to another similar table for the remaining bits. Again, there are duplicated entries as needed. The idea is that most of the time the symbol will be short and there will only be one table look up. (That's whole idea behind data compression in the first place.) For the less frequent long symbols, there will be two lookups. If you had a compression method with really long symbols, you could have as many levels of lookups as is efficient. For inflate, two is enough. So a table entry either points to another table (in which case nine bits in the above example are gobbled), or it contains the translation for the symbol and the number of bits to gobble. Then you start again with the next ungobbled bit. You may wonder: why not just have one lookup table for how ever many bits the longest symbol is? The reason is that if you do that, you end up spending more time filling in duplicate symbol entries than you do actually decoding. At least for deflate's output that generates new trees every several 10's of kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code would take too long if you're only decoding several thousand symbols. At the other extreme, you could make a new table for every bit in the code. In fact, that's essentially a Huffman tree. But then you spend too much time traversing the tree while decoding, even for short symbols. So the number of bits for the first lookup table is a trade of the time to fill out the table vs. the time spent looking at the second level and above of the table. Here is an example, scaled down: The code being decoded, with 10 symbols, from 1 to 6 bits long: A: 0 B: 10 C: 1100 D: 11010 E: 11011 F: 11100 G: 11101 H: 11110 I: 111110 J: 111111 Let's make the first table three bits long (eight entries): 000: A,1 001: A,1 010: A,1 011: A,1 100: B,2 101: B,2 110: -> table X (gobble 3 bits) 111: -> table Y (gobble 3 bits) Each entry is what the bits decode as and how many bits that is, i.e. how many bits to gobble. Or the entry points to another table, with the number of bits to gobble implicit in the size of the table. Table X is two bits long since the longest code starting with 110 is five bits long: 00: C,1 01: C,1 10: D,2 11: E,2 Table Y is three bits long since the longest code starting with 111 is six bits long: 000: F,2 001: F,2 010: G,2 011: G,2 100: H,2 101: H,2 110: I,3 111: J,3 So what we have here are three tables with a total of 20 entries that had to be constructed. That's compared to 64 entries for a single table. Or compared to 16 entries for a Huffman tree (six two entry tables and one four entry table). Assuming that the code ideally represents the probability of the symbols, it takes on the average 1.25 lookups per symbol. That's compared to one lookup for the single table, or 1.66 lookups per symbol for the Huffman tree. There, I think that gives you a picture of what's going on. For inflate, the meaning of a particular symbol is often more than just a letter. It can be a byte (a "literal"), or it can be either a length or a distance which indicates a base value and a number of bits to fetch after the code that is added to the base value. Or it might be the special end-of-block code. The data structures created in inftrees.c try to encode all that information compactly in the tables. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu References: [LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, pp. 337-343. ``DEFLATE Compressed Data Format Specification'' available in http://tools.ietf.org/html/rfc1951 tcl8.6.5/compat/zlib/doc/rfc1951.txt0000644000175000017500000011012012663653206016404 0ustar sergeisergei Network Working Group P. Deutsch Request for Comments: 1951 Aladdin Enterprises Category: Informational May 1996 DEFLATE Compressed Data Format Specification version 1.3 Status of This Memo This memo provides information for the Internet community. This memo does not specify an Internet standard of any kind. Distribution of this memo is unlimited. IESG Note: The IESG takes no position on the validity of any Intellectual Property Rights statements contained in this document. Notices Copyright (c) 1996 L. Peter Deutsch Permission is granted to copy and distribute this document for any purpose and without charge, including translations into other languages and incorporation into compilations, provided that the copyright notice and this notice are preserved, and that any substantive changes or deletions from the original are clearly marked. A pointer to the latest version of this and related documentation in HTML format can be found at the URL . Abstract This specification defines a lossless compressed data format that compresses data using a combination of the LZ77 algorithm and Huffman coding, with efficiency comparable to the best currently available general-purpose compression methods. The data can be produced or consumed, even for an arbitrarily long sequentially presented input data stream, using only an a priori bounded amount of intermediate storage. The format can be implemented readily in a manner not covered by patents. Deutsch Informational [Page 1] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 Table of Contents 1. Introduction ................................................... 2 1.1. Purpose ................................................... 2 1.2. Intended audience ......................................... 3 1.3. Scope ..................................................... 3 1.4. Compliance ................................................ 3 1.5. Definitions of terms and conventions used ................ 3 1.6. Changes from previous versions ............................ 4 2. Compressed representation overview ............................. 4 3. Detailed specification ......................................... 5 3.1. Overall conventions ....................................... 5 3.1.1. Packing into bytes .................................. 5 3.2. Compressed block format ................................... 6 3.2.1. Synopsis of prefix and Huffman coding ............... 6 3.2.2. Use of Huffman coding in the "deflate" format ....... 7 3.2.3. Details of block format ............................. 9 3.2.4. Non-compressed blocks (BTYPE=00) ................... 11 3.2.5. Compressed blocks (length and distance codes) ...... 11 3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13 3.3. Compliance ............................................... 14 4. Compression algorithm details ................................. 14 5. References .................................................... 16 6. Security Considerations ....................................... 16 7. Source code ................................................... 16 8. Acknowledgements .............................................. 16 9. Author's Address .............................................. 17 1. Introduction 1.1. Purpose The purpose of this specification is to define a lossless compressed data format that: * Is independent of CPU type, operating system, file system, and character set, and hence can be used for interchange; * Can be produced or consumed, even for an arbitrarily long sequentially presented input data stream, using only an a priori bounded amount of intermediate storage, and hence can be used in data communications or similar structures such as Unix filters; * Compresses data with efficiency comparable to the best currently available general-purpose compression methods, and in particular considerably better than the "compress" program; * Can be implemented readily in a manner not covered by patents, and hence can be practiced freely; Deutsch Informational [Page 2] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 * Is compatible with the file format produced by the current widely used gzip utility, in that conforming decompressors will be able to read data produced by the existing gzip compressor. The data format defined by this specification does not attempt to: * Allow random access to compressed data; * Compress specialized data (e.g., raster graphics) as well as the best currently available specialized algorithms. A simple counting argument shows that no lossless compression algorithm can compress every possible input data set. For the format defined here, the worst case expansion is 5 bytes per 32K- byte block, i.e., a size increase of 0.015% for large data sets. English text usually compresses by a factor of 2.5 to 3; executable files usually compress somewhat less; graphical data such as raster images may compress much more. 1.2. Intended audience This specification is intended for use by implementors of software to compress data into "deflate" format and/or decompress data from "deflate" format. The text of the specification assumes a basic background in programming at the level of bits and other primitive data representations. Familiarity with the technique of Huffman coding is helpful but not required. 1.3. Scope The specification specifies a method for representing a sequence of bytes as a (usually shorter) sequence of bits, and a method for packing the latter bit sequence into bytes. 1.4. Compliance Unless otherwise indicated below, a compliant decompressor must be able to accept and decompress any data set that conforms to all the specifications presented here; a compliant compressor must produce data sets that conform to all the specifications presented here. 1.5. Definitions of terms and conventions used Byte: 8 bits stored or transmitted as a unit (same as an octet). For this specification, a byte is exactly 8 bits, even on machines Deutsch Informational [Page 3] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 which store a character on a number of bits different from eight. See below, for the numbering of bits within a byte. String: a sequence of arbitrary bytes. 1.6. Changes from previous versions There have been no technical changes to the deflate format since version 1.1 of this specification. In version 1.2, some terminology was changed. Version 1.3 is a conversion of the specification to RFC style. 2. Compressed representation overview A compressed data set consists of a series of blocks, corresponding to successive blocks of input data. The block sizes are arbitrary, except that non-compressible blocks are limited to 65,535 bytes. Each block is compressed using a combination of the LZ77 algorithm and Huffman coding. The Huffman trees for each block are independent of those for previous or subsequent blocks; the LZ77 algorithm may use a reference to a duplicated string occurring in a previous block, up to 32K input bytes before. Each block consists of two parts: a pair of Huffman code trees that describe the representation of the compressed data part, and a compressed data part. (The Huffman trees themselves are compressed using Huffman encoding.) The compressed data consists of a series of elements of two types: literal bytes (of strings that have not been detected as duplicated within the previous 32K input bytes), and pointers to duplicated strings, where a pointer is represented as a pair . The representation used in the "deflate" format limits distances to 32K bytes and lengths to 258 bytes, but does not limit the size of a block, except for uncompressible blocks, which are limited as noted above. Each type of value (literals, distances, and lengths) in the compressed data is represented using a Huffman code, using one code tree for literals and lengths and a separate code tree for distances. The code trees for each block appear in a compact form just before the compressed data for that block. Deutsch Informational [Page 4] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 3. Detailed specification 3.1. Overall conventions In the diagrams below, a box like this: +---+ | | <-- the vertical bars might be missing +---+ represents one byte; a box like this: +==============+ | | +==============+ represents a variable number of bytes. Bytes stored within a computer do not have a "bit order", since they are always treated as a unit. However, a byte considered as an integer between 0 and 255 does have a most- and least- significant bit, and since we write numbers with the most- significant digit on the left, we also write bytes with the most- significant bit on the left. In the diagrams below, we number the bits of a byte so that bit 0 is the least-significant bit, i.e., the bits are numbered: +--------+ |76543210| +--------+ Within a computer, a number may occupy multiple bytes. All multi-byte numbers in the format described here are stored with the least-significant byte first (at the lower memory address). For example, the decimal number 520 is stored as: 0 1 +--------+--------+ |00001000|00000010| +--------+--------+ ^ ^ | | | + more significant byte = 2 x 256 + less significant byte = 8 3.1.1. Packing into bytes This document does not address the issue of the order in which bits of a byte are transmitted on a bit-sequential medium, since the final data format described here is byte- rather than Deutsch Informational [Page 5] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 bit-oriented. However, we describe the compressed block format in below, as a sequence of data elements of various bit lengths, not a sequence of bytes. We must therefore specify how to pack these data elements into bytes to form the final compressed byte sequence: * Data elements are packed into bytes in order of increasing bit number within the byte, i.e., starting with the least-significant bit of the byte. * Data elements other than Huffman codes are packed starting with the least-significant bit of the data element. * Huffman codes are packed starting with the most- significant bit of the code. In other words, if one were to print out the compressed data as a sequence of bytes, starting with the first byte at the *right* margin and proceeding to the *left*, with the most- significant bit of each byte on the left as usual, one would be able to parse the result from right to left, with fixed-width elements in the correct MSB-to-LSB order and Huffman codes in bit-reversed order (i.e., with the first bit of the code in the relative LSB position). 3.2. Compressed block format 3.2.1. Synopsis of prefix and Huffman coding Prefix coding represents symbols from an a priori known alphabet by bit sequences (codes), one code for each symbol, in a manner such that different symbols may be represented by bit sequences of different lengths, but a parser can always parse an encoded string unambiguously symbol-by-symbol. We define a prefix code in terms of a binary tree in which the two edges descending from each non-leaf node are labeled 0 and 1 and in which the leaf nodes correspond one-for-one with (are labeled with) the symbols of the alphabet; then the code for a symbol is the sequence of 0's and 1's on the edges leading from the root to the leaf labeled with that symbol. For example: Deutsch Informational [Page 6] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 /\ Symbol Code 0 1 ------ ---- / \ A 00 /\ B B 1 0 1 C 011 / \ D 010 A /\ 0 1 / \ D C A parser can decode the next symbol from an encoded input stream by walking down the tree from the root, at each step choosing the edge corresponding to the next input bit. Given an alphabet with known symbol frequencies, the Huffman algorithm allows the construction of an optimal prefix code (one which represents strings with those symbol frequencies using the fewest bits of any possible prefix codes for that alphabet). Such a code is called a Huffman code. (See reference [1] in Chapter 5, references for additional information on Huffman codes.) Note that in the "deflate" format, the Huffman codes for the various alphabets must not exceed certain maximum code lengths. This constraint complicates the algorithm for computing code lengths from symbol frequencies. Again, see Chapter 5, references for details. 3.2.2. Use of Huffman coding in the "deflate" format The Huffman codes used for each alphabet in the "deflate" format have two additional rules: * All codes of a given bit length have lexicographically consecutive values, in the same order as the symbols they represent; * Shorter codes lexicographically precede longer codes. Deutsch Informational [Page 7] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 We could recode the example above to follow this rule as follows, assuming that the order of the alphabet is ABCD: Symbol Code ------ ---- A 10 B 0 C 110 D 111 I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are lexicographically consecutive. Given this rule, we can define the Huffman code for an alphabet just by giving the bit lengths of the codes for each symbol of the alphabet in order; this is sufficient to determine the actual codes. In our example, the code is completely defined by the sequence of bit lengths (2, 1, 3, 3). The following algorithm generates the codes as integers, intended to be read from most- to least-significant bit. The code lengths are initially in tree[I].Len; the codes are produced in tree[I].Code. 1) Count the number of codes for each code length. Let bl_count[N] be the number of codes of length N, N >= 1. 2) Find the numerical value of the smallest code for each code length: code = 0; bl_count[0] = 0; for (bits = 1; bits <= MAX_BITS; bits++) { code = (code + bl_count[bits-1]) << 1; next_code[bits] = code; } 3) Assign numerical values to all codes, using consecutive values for all codes of the same length with the base values determined at step 2. Codes that are never used (which have a bit length of zero) must not be assigned a value. for (n = 0; n <= max_code; n++) { len = tree[n].Len; if (len != 0) { tree[n].Code = next_code[len]; next_code[len]++; } Deutsch Informational [Page 8] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 } Example: Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3, 3, 2, 4, 4). After step 1, we have: N bl_count[N] - ----------- 2 1 3 5 4 2 Step 2 computes the following next_code values: N next_code[N] - ------------ 1 0 2 0 3 2 4 14 Step 3 produces the following code values: Symbol Length Code ------ ------ ---- A 3 010 B 3 011 C 3 100 D 3 101 E 3 110 F 2 00 G 4 1110 H 4 1111 3.2.3. Details of block format Each block of compressed data begins with 3 header bits containing the following data: first bit BFINAL next 2 bits BTYPE Note that the header bits do not necessarily begin on a byte boundary, since a block does not necessarily occupy an integral number of bytes. Deutsch Informational [Page 9] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 BFINAL is set if and only if this is the last block of the data set. BTYPE specifies how the data are compressed, as follows: 00 - no compression 01 - compressed with fixed Huffman codes 10 - compressed with dynamic Huffman codes 11 - reserved (error) The only difference between the two compressed cases is how the Huffman codes for the literal/length and distance alphabets are defined. In all cases, the decoding algorithm for the actual data is as follows: do read block header from input stream. if stored with no compression skip any remaining bits in current partially processed byte read LEN and NLEN (see next section) copy LEN bytes of data to output otherwise if compressed with dynamic Huffman codes read representation of code trees (see subsection below) loop (until end of block code recognized) decode literal/length value from input stream if value < 256 copy value (literal byte) to output stream otherwise if value = end of block (256) break from loop otherwise (value = 257..285) decode distance from input stream move backwards distance bytes in the output stream, and copy length bytes from this position to the output stream. end loop while not last block Note that a duplicated string reference may refer to a string in a previous block; i.e., the backward distance may cross one or more block boundaries. However a distance cannot refer past the beginning of the output stream. (An application using a Deutsch Informational [Page 10] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 preset dictionary might discard part of the output stream; a distance can refer to that part of the output stream anyway) Note also that the referenced string may overlap the current position; for example, if the last 2 bytes decoded have values X and Y, a string reference with adds X,Y,X,Y,X to the output stream. We now specify each compression method in turn. 3.2.4. Non-compressed blocks (BTYPE=00) Any bits of input up to the next byte boundary are ignored. The rest of the block consists of the following information: 0 1 2 3 4... +---+---+---+---+================================+ | LEN | NLEN |... LEN bytes of literal data...| +---+---+---+---+================================+ LEN is the number of data bytes in the block. NLEN is the one's complement of LEN. 3.2.5. Compressed blocks (length and distance codes) As noted above, encoded data blocks in the "deflate" format consist of sequences of symbols drawn from three conceptually distinct alphabets: either literal bytes, from the alphabet of byte values (0..255), or pairs, where the length is drawn from (3..258) and the distance is drawn from (1..32,768). In fact, the literal and length alphabets are merged into a single alphabet (0..285), where values 0..255 represent literal bytes, the value 256 indicates end-of-block, and values 257..285 represent length codes (possibly in conjunction with extra bits following the symbol code) as follows: Deutsch Informational [Page 11] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 Extra Extra Extra Code Bits Length(s) Code Bits Lengths Code Bits Length(s) ---- ---- ------ ---- ---- ------- ---- ---- ------- 257 0 3 267 1 15,16 277 4 67-82 258 0 4 268 1 17,18 278 4 83-98 259 0 5 269 2 19-22 279 4 99-114 260 0 6 270 2 23-26 280 4 115-130 261 0 7 271 2 27-30 281 5 131-162 262 0 8 272 2 31-34 282 5 163-194 263 0 9 273 3 35-42 283 5 195-226 264 0 10 274 3 43-50 284 5 227-257 265 1 11,12 275 3 51-58 285 0 258 266 1 13,14 276 3 59-66 The extra bits should be interpreted as a machine integer stored with the most-significant bit first, e.g., bits 1110 represent the value 14. Extra Extra Extra Code Bits Dist Code Bits Dist Code Bits Distance ---- ---- ---- ---- ---- ------ ---- ---- -------- 0 0 1 10 4 33-48 20 9 1025-1536 1 0 2 11 4 49-64 21 9 1537-2048 2 0 3 12 5 65-96 22 10 2049-3072 3 0 4 13 5 97-128 23 10 3073-4096 4 1 5,6 14 6 129-192 24 11 4097-6144 5 1 7,8 15 6 193-256 25 11 6145-8192 6 2 9-12 16 7 257-384 26 12 8193-12288 7 2 13-16 17 7 385-512 27 12 12289-16384 8 3 17-24 18 8 513-768 28 13 16385-24576 9 3 25-32 19 8 769-1024 29 13 24577-32768 3.2.6. Compression with fixed Huffman codes (BTYPE=01) The Huffman codes for the two alphabets are fixed, and are not represented explicitly in the data. The Huffman code lengths for the literal/length alphabet are: Lit Value Bits Codes --------- ---- ----- 0 - 143 8 00110000 through 10111111 144 - 255 9 110010000 through 111111111 256 - 279 7 0000000 through 0010111 280 - 287 8 11000000 through 11000111 Deutsch Informational [Page 12] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 The code lengths are sufficient to generate the actual codes, as described above; we show the codes in the table for added clarity. Literal/length values 286-287 will never actually occur in the compressed data, but participate in the code construction. Distance codes 0-31 are represented by (fixed-length) 5-bit codes, with possible additional bits as shown in the table shown in Paragraph 3.2.5, above. Note that distance codes 30- 31 will never actually occur in the compressed data. 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) The Huffman codes for the two alphabets appear in the block immediately after the header bits and before the actual compressed data, first the literal/length code and then the distance code. Each code is defined by a sequence of code lengths, as discussed in Paragraph 3.2.2, above. For even greater compactness, the code length sequences themselves are compressed using a Huffman code. The alphabet for code lengths is as follows: 0 - 15: Represent code lengths of 0 - 15 16: Copy the previous code length 3 - 6 times. The next 2 bits indicate repeat length (0 = 3, ... , 3 = 6) Example: Codes 8, 16 (+2 bits 11), 16 (+2 bits 10) will expand to 12 code lengths of 8 (1 + 6 + 5) 17: Repeat a code length of 0 for 3 - 10 times. (3 bits of length) 18: Repeat a code length of 0 for 11 - 138 times (7 bits of length) A code length of 0 indicates that the corresponding symbol in the literal/length or distance alphabet will not occur in the block, and should not participate in the Huffman code construction algorithm given earlier. If only one distance code is used, it is encoded using one bit, not zero bits; in this case there is a single code length of one, with one unused code. One distance code of zero bits means that there are no distance codes used at all (the data is all literals). We can now define the format of the block: 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) Deutsch Informational [Page 13] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 (HCLEN + 4) x 3 bits: code lengths for the code length alphabet given just above, in the order: 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 These code lengths are interpreted as 3-bit integers (0-7); as above, a code length of 0 means the corresponding symbol (literal/length or distance code length) is not used. HLIT + 257 code lengths for the literal/length alphabet, encoded using the code length Huffman code HDIST + 1 code lengths for the distance alphabet, encoded using the code length Huffman code The actual compressed data of the block, encoded using the literal/length and distance Huffman codes The literal/length symbol 256 (end of data), encoded using the literal/length Huffman code The code length repeat codes can cross from HLIT + 257 to the HDIST + 1 code lengths. In other words, all code lengths form a single sequence of HLIT + HDIST + 258 values. 3.3. Compliance A compressor may limit further the ranges of values specified in the previous section and still be compliant; for example, it may limit the range of backward pointers to some value smaller than 32K. Similarly, a compressor may limit the size of blocks so that a compressible block fits in memory. A compliant decompressor must accept the full range of possible values defined in the previous section, and must accept blocks of arbitrary size. 4. Compression algorithm details While it is the intent of this document to define the "deflate" compressed data format without reference to any particular compression algorithm, the format is related to the compressed formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below); since many variations of LZ77 are patented, it is strongly recommended that the implementor of a compressor follow the general algorithm presented here, which is known not to be patented per se. The material in this section is not part of the definition of the Deutsch Informational [Page 14] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 specification per se, and a compressor need not follow it in order to be compliant. The compressor terminates a block when it determines that starting a new block with fresh trees would be useful, or when the block size fills up the compressor's block buffer. The compressor uses a chained hash table to find duplicated strings, using a hash function that operates on 3-byte sequences. At any given point during compression, let XYZ be the next 3 input bytes to be examined (not necessarily all different, of course). First, the compressor examines the hash chain for XYZ. If the chain is empty, the compressor simply writes out X as a literal byte and advances one byte in the input. If the hash chain is not empty, indicating that the sequence XYZ (or, if we are unlucky, some other 3 bytes with the same hash function value) has occurred recently, the compressor compares all strings on the XYZ hash chain with the actual input data sequence starting at the current point, and selects the longest match. The compressor searches the hash chains starting with the most recent strings, to favor small distances and thus take advantage of the Huffman encoding. The hash chains are singly linked. There are no deletions from the hash chains; the algorithm simply discards matches that are too old. To avoid a worst-case situation, very long hash chains are arbitrarily truncated at a certain length, determined by a run-time parameter. To improve overall compression, the compressor optionally defers the selection of matches ("lazy matching"): after a match of length N has been found, the compressor searches for a longer match starting at the next input byte. If it finds a longer match, it truncates the previous match to a length of one (thus producing a single literal byte) and then emits the longer match. Otherwise, it emits the original match, and, as described above, advances N bytes before continuing. Run-time parameters also control this "lazy match" procedure. If compression ratio is most important, the compressor attempts a complete second search regardless of the length of the first match. In the normal case, if the current match is "long enough", the compressor reduces the search for a longer match, thus speeding up the process. If speed is most important, the compressor inserts new strings in the hash table only when no match was found, or when the match is not "too long". This degrades the compression ratio but saves time since there are both fewer insertions and fewer searches. Deutsch Informational [Page 15] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 5. References [1] Huffman, D. A., "A Method for the Construction of Minimum Redundancy Codes", Proceedings of the Institute of Radio Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101. [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data Compression", IEEE Transactions on Information Theory, Vol. 23, No. 3, pp. 337-343. [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources, available in ftp://ftp.uu.net/pub/archiving/zip/doc/ [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources, available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/ [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169. [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes," Comm. ACM, 33,4, April 1990, pp. 449-459. 6. Security Considerations Any data compression method involves the reduction of redundancy in the data. Consequently, any corruption of the data is likely to have severe effects and be difficult to correct. Uncompressed text, on the other hand, will probably still be readable despite the presence of some corrupted bytes. It is recommended that systems using this data format provide some means of validating the integrity of the compressed data. See reference [3], for example. 7. Source code Source code for a C language implementation of a "deflate" compliant compressor and decompressor is available within the zlib package at ftp://ftp.uu.net/pub/archiving/zip/zlib/. 8. Acknowledgements Trademarks cited in this document are the property of their respective owners. Phil Katz designed the deflate format. Jean-Loup Gailly and Mark Adler wrote the related software described in this specification. Glenn Randers-Pehrson converted this document to RFC and HTML format. Deutsch Informational [Page 16] RFC 1951 DEFLATE Compressed Data Format Specification May 1996 9. Author's Address L. Peter Deutsch Aladdin Enterprises 203 Santa Margarita Ave. Menlo Park, CA 94025 Phone: (415) 322-0103 (AM only) FAX: (415) 322-1734 EMail: Questions about the technical content of this specification can be sent by email to: Jean-Loup Gailly and Mark Adler Editorial comments on this specification can be sent by email to: L. Peter Deutsch and Glenn Randers-Pehrson Deutsch Informational [Page 17] tcl8.6.5/compat/zlib/doc/rfc1952.txt0000644000175000017500000006071512663653206016423 0ustar sergeisergei Network Working Group P. Deutsch Request for Comments: 1952 Aladdin Enterprises Category: Informational May 1996 GZIP file format specification version 4.3 Status of This Memo This memo provides information for the Internet community. This memo does not specify an Internet standard of any kind. Distribution of this memo is unlimited. IESG Note: The IESG takes no position on the validity of any Intellectual Property Rights statements contained in this document. Notices Copyright (c) 1996 L. Peter Deutsch Permission is granted to copy and distribute this document for any purpose and without charge, including translations into other languages and incorporation into compilations, provided that the copyright notice and this notice are preserved, and that any substantive changes or deletions from the original are clearly marked. A pointer to the latest version of this and related documentation in HTML format can be found at the URL . Abstract This specification defines a lossless compressed data format that is compatible with the widely used GZIP utility. The format includes a cyclic redundancy check value for detecting data corruption. The format presently uses the DEFLATE method of compression but can be easily extended to use other compression methods. The format can be implemented readily in a manner not covered by patents. Deutsch Informational [Page 1] RFC 1952 GZIP File Format Specification May 1996 Table of Contents 1. Introduction ................................................... 2 1.1. Purpose ................................................... 2 1.2. Intended audience ......................................... 3 1.3. Scope ..................................................... 3 1.4. Compliance ................................................ 3 1.5. Definitions of terms and conventions used ................. 3 1.6. Changes from previous versions ............................ 3 2. Detailed specification ......................................... 4 2.1. Overall conventions ....................................... 4 2.2. File format ............................................... 5 2.3. Member format ............................................. 5 2.3.1. Member header and trailer ........................... 6 2.3.1.1. Extra field ................................... 8 2.3.1.2. Compliance .................................... 9 3. References .................................................. 9 4. Security Considerations .................................... 10 5. Acknowledgements ........................................... 10 6. Author's Address ........................................... 10 7. Appendix: Jean-Loup Gailly's gzip utility .................. 11 8. Appendix: Sample CRC Code .................................. 11 1. Introduction 1.1. Purpose The purpose of this specification is to define a lossless compressed data format that: * Is independent of CPU type, operating system, file system, and character set, and hence can be used for interchange; * Can compress or decompress a data stream (as opposed to a randomly accessible file) to produce another data stream, using only an a priori bounded amount of intermediate storage, and hence can be used in data communications or similar structures such as Unix filters; * Compresses data with efficiency comparable to the best currently available general-purpose compression methods, and in particular considerably better than the "compress" program; * Can be implemented readily in a manner not covered by patents, and hence can be practiced freely; * Is compatible with the file format produced by the current widely used gzip utility, in that conforming decompressors will be able to read data produced by the existing gzip compressor. Deutsch Informational [Page 2] RFC 1952 GZIP File Format Specification May 1996 The data format defined by this specification does not attempt to: * Provide random access to compressed data; * Compress specialized data (e.g., raster graphics) as well as the best currently available specialized algorithms. 1.2. Intended audience This specification is intended for use by implementors of software to compress data into gzip format and/or decompress data from gzip format. The text of the specification assumes a basic background in programming at the level of bits and other primitive data representations. 1.3. Scope The specification specifies a compression method and a file format (the latter assuming only that a file can store a sequence of arbitrary bytes). It does not specify any particular interface to a file system or anything about character sets or encodings (except for file names and comments, which are optional). 1.4. Compliance Unless otherwise indicated below, a compliant decompressor must be able to accept and decompress any file that conforms to all the specifications presented here; a compliant compressor must produce files that conform to all the specifications presented here. The material in the appendices is not part of the specification per se and is not relevant to compliance. 1.5. Definitions of terms and conventions used byte: 8 bits stored or transmitted as a unit (same as an octet). (For this specification, a byte is exactly 8 bits, even on machines which store a character on a number of bits different from 8.) See below for the numbering of bits within a byte. 1.6. Changes from previous versions There have been no technical changes to the gzip format since version 4.1 of this specification. In version 4.2, some terminology was changed, and the sample CRC code was rewritten for clarity and to eliminate the requirement for the caller to do pre- and post-conditioning. Version 4.3 is a conversion of the specification to RFC style. Deutsch Informational [Page 3] RFC 1952 GZIP File Format Specification May 1996 2. Detailed specification 2.1. Overall conventions In the diagrams below, a box like this: +---+ | | <-- the vertical bars might be missing +---+ represents one byte; a box like this: +==============+ | | +==============+ represents a variable number of bytes. Bytes stored within a computer do not have a "bit order", since they are always treated as a unit. However, a byte considered as an integer between 0 and 255 does have a most- and least- significant bit, and since we write numbers with the most- significant digit on the left, we also write bytes with the most- significant bit on the left. In the diagrams below, we number the bits of a byte so that bit 0 is the least-significant bit, i.e., the bits are numbered: +--------+ |76543210| +--------+ This document does not address the issue of the order in which bits of a byte are transmitted on a bit-sequential medium, since the data format described here is byte- rather than bit-oriented. Within a computer, a number may occupy multiple bytes. All multi-byte numbers in the format described here are stored with the least-significant byte first (at the lower memory address). For example, the decimal number 520 is stored as: 0 1 +--------+--------+ |00001000|00000010| +--------+--------+ ^ ^ | | | + more significant byte = 2 x 256 + less significant byte = 8 Deutsch Informational [Page 4] RFC 1952 GZIP File Format Specification May 1996 2.2. File format A gzip file consists of a series of "members" (compressed data sets). The format of each member is specified in the following section. The members simply appear one after another in the file, with no additional information before, between, or after them. 2.3. Member format Each member has the following structure: +---+---+---+---+---+---+---+---+---+---+ |ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->) +---+---+---+---+---+---+---+---+---+---+ (if FLG.FEXTRA set) +---+---+=================================+ | XLEN |...XLEN bytes of "extra field"...| (more-->) +---+---+=================================+ (if FLG.FNAME set) +=========================================+ |...original file name, zero-terminated...| (more-->) +=========================================+ (if FLG.FCOMMENT set) +===================================+ |...file comment, zero-terminated...| (more-->) +===================================+ (if FLG.FHCRC set) +---+---+ | CRC16 | +---+---+ +=======================+ |...compressed blocks...| (more-->) +=======================+ 0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | CRC32 | ISIZE | +---+---+---+---+---+---+---+---+ Deutsch Informational [Page 5] RFC 1952 GZIP File Format Specification May 1996 2.3.1. Member header and trailer ID1 (IDentification 1) ID2 (IDentification 2) These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139 (0x8b, \213), to identify the file as being in gzip format. CM (Compression Method) This identifies the compression method used in the file. CM = 0-7 are reserved. CM = 8 denotes the "deflate" compression method, which is the one customarily used by gzip and which is documented elsewhere. FLG (FLaGs) This flag byte is divided into individual bits as follows: bit 0 FTEXT bit 1 FHCRC bit 2 FEXTRA bit 3 FNAME bit 4 FCOMMENT bit 5 reserved bit 6 reserved bit 7 reserved If FTEXT is set, the file is probably ASCII text. This is an optional indication, which the compressor may set by checking a small amount of the input data to see whether any non-ASCII characters are present. In case of doubt, FTEXT is cleared, indicating binary data. For systems which have different file formats for ascii text and binary data, the decompressor can use FTEXT to choose the appropriate format. We deliberately do not specify the algorithm used to set this bit, since a compressor always has the option of leaving it cleared and a decompressor always has the option of ignoring it and letting some other program handle issues of data conversion. If FHCRC is set, a CRC16 for the gzip header is present, immediately before the compressed data. The CRC16 consists of the two least significant bytes of the CRC32 for all bytes of the gzip header up to and not including the CRC16. [The FHCRC bit was never set by versions of gzip up to 1.2.4, even though it was documented with a different meaning in gzip 1.2.4.] If FEXTRA is set, optional extra fields are present, as described in a following section. Deutsch Informational [Page 6] RFC 1952 GZIP File Format Specification May 1996 If FNAME is set, an original file name is present, terminated by a zero byte. The name must consist of ISO 8859-1 (LATIN-1) characters; on operating systems using EBCDIC or any other character set for file names, the name must be translated to the ISO LATIN-1 character set. This is the original name of the file being compressed, with any directory components removed, and, if the file being compressed is on a file system with case insensitive names, forced to lower case. There is no original file name if the data was compressed from a source other than a named file; for example, if the source was stdin on a Unix system, there is no file name. If FCOMMENT is set, a zero-terminated file comment is present. This comment is not interpreted; it is only intended for human consumption. The comment must consist of ISO 8859-1 (LATIN-1) characters. Line breaks should be denoted by a single line feed character (10 decimal). Reserved FLG bits must be zero. MTIME (Modification TIME) This gives the most recent modification time of the original file being compressed. The time is in Unix format, i.e., seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this may cause problems for MS-DOS and other systems that use local rather than Universal time.) If the compressed data did not come from a file, MTIME is set to the time at which compression started. MTIME = 0 means no time stamp is available. XFL (eXtra FLags) These flags are available for use by specific compression methods. The "deflate" method (CM = 8) sets these flags as follows: XFL = 2 - compressor used maximum compression, slowest algorithm XFL = 4 - compressor used fastest algorithm OS (Operating System) This identifies the type of file system on which compression took place. This may be useful in determining end-of-line convention for text files. The currently defined values are as follows: Deutsch Informational [Page 7] RFC 1952 GZIP File Format Specification May 1996 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32) 1 - Amiga 2 - VMS (or OpenVMS) 3 - Unix 4 - VM/CMS 5 - Atari TOS 6 - HPFS filesystem (OS/2, NT) 7 - Macintosh 8 - Z-System 9 - CP/M 10 - TOPS-20 11 - NTFS filesystem (NT) 12 - QDOS 13 - Acorn RISCOS 255 - unknown XLEN (eXtra LENgth) If FLG.FEXTRA is set, this gives the length of the optional extra field. See below for details. CRC32 (CRC-32) This contains a Cyclic Redundancy Check value of the uncompressed data computed according to CRC-32 algorithm used in the ISO 3309 standard and in section 8.1.1.6.2 of ITU-T recommendation V.42. (See http://www.iso.ch for ordering ISO documents. See gopher://info.itu.ch for an online version of ITU-T V.42.) ISIZE (Input SIZE) This contains the size of the original (uncompressed) input data modulo 2^32. 2.3.1.1. Extra field If the FLG.FEXTRA bit is set, an "extra field" is present in the header, with total length XLEN bytes. It consists of a series of subfields, each of the form: +---+---+---+---+==================================+ |SI1|SI2| LEN |... LEN bytes of subfield data ...| +---+---+---+---+==================================+ SI1 and SI2 provide a subfield ID, typically two ASCII letters with some mnemonic value. Jean-Loup Gailly is maintaining a registry of subfield IDs; please send him any subfield ID you wish to use. Subfield IDs with SI2 = 0 are reserved for future use. The following IDs are currently defined: Deutsch Informational [Page 8] RFC 1952 GZIP File Format Specification May 1996 SI1 SI2 Data ---------- ---------- ---- 0x41 ('A') 0x70 ('P') Apollo file type information LEN gives the length of the subfield data, excluding the 4 initial bytes. 2.3.1.2. Compliance A compliant compressor must produce files with correct ID1, ID2, CM, CRC32, and ISIZE, but may set all the other fields in the fixed-length part of the header to default values (255 for OS, 0 for all others). The compressor must set all reserved bits to zero. A compliant decompressor must check ID1, ID2, and CM, and provide an error indication if any of these have incorrect values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC at least so it can skip over the optional fields if they are present. It need not examine any other part of the header or trailer; in particular, a decompressor may ignore FTEXT and OS and always produce binary output, and still be compliant. A compliant decompressor must give an error indication if any reserved bit is non-zero, since such a bit could indicate the presence of a new field that would cause subsequent data to be interpreted incorrectly. 3. References [1] "Information Processing - 8-bit single-byte coded graphic character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987). The ISO 8859-1 (Latin-1) character set is a superset of 7-bit ASCII. Files defining this character set are available as iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/ [2] ISO 3309 [3] ITU-T recommendation V.42 [4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", available in ftp://ftp.uu.net/pub/archiving/zip/doc/ [5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/ [6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table Look-Up", Communications of the ACM, 31(8), pp.1008-1013. Deutsch Informational [Page 9] RFC 1952 GZIP File Format Specification May 1996 [7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal, pp.118-133. [8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt, describing the CRC concept. 4. Security Considerations Any data compression method involves the reduction of redundancy in the data. Consequently, any corruption of the data is likely to have severe effects and be difficult to correct. Uncompressed text, on the other hand, will probably still be readable despite the presence of some corrupted bytes. It is recommended that systems using this data format provide some means of validating the integrity of the compressed data, such as by setting and checking the CRC-32 check value. 5. Acknowledgements Trademarks cited in this document are the property of their respective owners. Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler, the related software described in this specification. Glenn Randers-Pehrson converted this document to RFC and HTML format. 6. Author's Address L. Peter Deutsch Aladdin Enterprises 203 Santa Margarita Ave. Menlo Park, CA 94025 Phone: (415) 322-0103 (AM only) FAX: (415) 322-1734 EMail: Questions about the technical content of this specification can be sent by email to: Jean-Loup Gailly and Mark Adler Editorial comments on this specification can be sent by email to: L. Peter Deutsch and Glenn Randers-Pehrson Deutsch Informational [Page 10] RFC 1952 GZIP File Format Specification May 1996 7. Appendix: Jean-Loup Gailly's gzip utility The most widely used implementation of gzip compression, and the original documentation on which this specification is based, were created by Jean-Loup Gailly . Since this implementation is a de facto standard, we mention some more of its features here. Again, the material in this section is not part of the specification per se, and implementations need not follow it to be compliant. When compressing or decompressing a file, gzip preserves the protection, ownership, and modification time attributes on the local file system, since there is no provision for representing protection attributes in the gzip file format itself. Since the file format includes a modification time, the gzip decompressor provides a command line switch that assigns the modification time from the file, rather than the local modification time of the compressed input, to the decompressed output. 8. Appendix: Sample CRC Code The following sample code represents a practical implementation of the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42 for a formal specification.) The sample code is in the ANSI C programming language. Non C users may find it easier to read with these hints: & Bitwise AND operator. ^ Bitwise exclusive-OR operator. >> Bitwise right shift operator. When applied to an unsigned quantity, as here, right shift inserts zero bit(s) at the left. ! Logical NOT operator. ++ "n++" increments the variable n. 0xNNN 0x introduces a hexadecimal (base 16) constant. Suffix L indicates a long value (at least 32 bits). /* Table of CRCs of all 8-bit messages. */ unsigned long crc_table[256]; /* Flag: has the table been computed? Initially false. */ int crc_table_computed = 0; /* Make the table for a fast CRC. */ void make_crc_table(void) { unsigned long c; Deutsch Informational [Page 11] RFC 1952 GZIP File Format Specification May 1996 int n, k; for (n = 0; n < 256; n++) { c = (unsigned long) n; for (k = 0; k < 8; k++) { if (c & 1) { c = 0xedb88320L ^ (c >> 1); } else { c = c >> 1; } } crc_table[n] = c; } crc_table_computed = 1; } /* Update a running crc with the bytes buf[0..len-1] and return the updated crc. The crc should be initialized to zero. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the caller. Usage example: unsigned long crc = 0L; while (read_buffer(buffer, length) != EOF) { crc = update_crc(crc, buffer, length); } if (crc != original_crc) error(); */ unsigned long update_crc(unsigned long crc, unsigned char *buf, int len) { unsigned long c = crc ^ 0xffffffffL; int n; if (!crc_table_computed) make_crc_table(); for (n = 0; n < len; n++) { c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); } return c ^ 0xffffffffL; } /* Return the CRC of the bytes buf[0..len-1]. */ unsigned long crc(unsigned char *buf, int len) { return update_crc(0L, buf, len); } Deutsch Informational [Page 12] tcl8.6.5/compat/zlib/doc/rfc1950.txt0000644000175000017500000005002612663653206016413 0ustar sergeisergei Network Working Group P. Deutsch Request for Comments: 1950 Aladdin Enterprises Category: Informational J-L. Gailly Info-ZIP May 1996 ZLIB Compressed Data Format Specification version 3.3 Status of This Memo This memo provides information for the Internet community. This memo does not specify an Internet standard of any kind. Distribution of this memo is unlimited. IESG Note: The IESG takes no position on the validity of any Intellectual Property Rights statements contained in this document. Notices Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly Permission is granted to copy and distribute this document for any purpose and without charge, including translations into other languages and incorporation into compilations, provided that the copyright notice and this notice are preserved, and that any substantive changes or deletions from the original are clearly marked. A pointer to the latest version of this and related documentation in HTML format can be found at the URL . Abstract This specification defines a lossless compressed data format. The data can be produced or consumed, even for an arbitrarily long sequentially presented input data stream, using only an a priori bounded amount of intermediate storage. The format presently uses the DEFLATE compression method but can be easily extended to use other compression methods. It can be implemented readily in a manner not covered by patents. This specification also defines the ADLER-32 checksum (an extension and improvement of the Fletcher checksum), used for detection of data corruption, and provides an algorithm for computing it. Deutsch & Gailly Informational [Page 1] RFC 1950 ZLIB Compressed Data Format Specification May 1996 Table of Contents 1. Introduction ................................................... 2 1.1. Purpose ................................................... 2 1.2. Intended audience ......................................... 3 1.3. Scope ..................................................... 3 1.4. Compliance ................................................ 3 1.5. Definitions of terms and conventions used ................ 3 1.6. Changes from previous versions ............................ 3 2. Detailed specification ......................................... 3 2.1. Overall conventions ....................................... 3 2.2. Data format ............................................... 4 2.3. Compliance ................................................ 7 3. References ..................................................... 7 4. Source code .................................................... 8 5. Security Considerations ........................................ 8 6. Acknowledgements ............................................... 8 7. Authors' Addresses ............................................. 8 8. Appendix: Rationale ............................................ 9 9. Appendix: Sample code ..........................................10 1. Introduction 1.1. Purpose The purpose of this specification is to define a lossless compressed data format that: * Is independent of CPU type, operating system, file system, and character set, and hence can be used for interchange; * Can be produced or consumed, even for an arbitrarily long sequentially presented input data stream, using only an a priori bounded amount of intermediate storage, and hence can be used in data communications or similar structures such as Unix filters; * Can use a number of different compression methods; * Can be implemented readily in a manner not covered by patents, and hence can be practiced freely. The data format defined by this specification does not attempt to allow random access to compressed data. Deutsch & Gailly Informational [Page 2] RFC 1950 ZLIB Compressed Data Format Specification May 1996 1.2. Intended audience This specification is intended for use by implementors of software to compress data into zlib format and/or decompress data from zlib format. The text of the specification assumes a basic background in programming at the level of bits and other primitive data representations. 1.3. Scope The specification specifies a compressed data format that can be used for in-memory compression of a sequence of arbitrary bytes. 1.4. Compliance Unless otherwise indicated below, a compliant decompressor must be able to accept and decompress any data set that conforms to all the specifications presented here; a compliant compressor must produce data sets that conform to all the specifications presented here. 1.5. Definitions of terms and conventions used byte: 8 bits stored or transmitted as a unit (same as an octet). (For this specification, a byte is exactly 8 bits, even on machines which store a character on a number of bits different from 8.) See below, for the numbering of bits within a byte. 1.6. Changes from previous versions Version 3.1 was the first public release of this specification. In version 3.2, some terminology was changed and the Adler-32 sample code was rewritten for clarity. In version 3.3, the support for a preset dictionary was introduced, and the specification was converted to RFC style. 2. Detailed specification 2.1. Overall conventions In the diagrams below, a box like this: +---+ | | <-- the vertical bars might be missing +---+ Deutsch & Gailly Informational [Page 3] RFC 1950 ZLIB Compressed Data Format Specification May 1996 represents one byte; a box like this: +==============+ | | +==============+ represents a variable number of bytes. Bytes stored within a computer do not have a "bit order", since they are always treated as a unit. However, a byte considered as an integer between 0 and 255 does have a most- and least- significant bit, and since we write numbers with the most- significant digit on the left, we also write bytes with the most- significant bit on the left. In the diagrams below, we number the bits of a byte so that bit 0 is the least-significant bit, i.e., the bits are numbered: +--------+ |76543210| +--------+ Within a computer, a number may occupy multiple bytes. All multi-byte numbers in the format described here are stored with the MOST-significant byte first (at the lower memory address). For example, the decimal number 520 is stored as: 0 1 +--------+--------+ |00000010|00001000| +--------+--------+ ^ ^ | | | + less significant byte = 8 + more significant byte = 2 x 256 2.2. Data format A zlib stream has the following structure: 0 1 +---+---+ |CMF|FLG| (more-->) +---+---+ Deutsch & Gailly Informational [Page 4] RFC 1950 ZLIB Compressed Data Format Specification May 1996 (if FLG.FDICT set) 0 1 2 3 +---+---+---+---+ | DICTID | (more-->) +---+---+---+---+ +=====================+---+---+---+---+ |...compressed data...| ADLER32 | +=====================+---+---+---+---+ Any data which may appear after ADLER32 are not part of the zlib stream. CMF (Compression Method and flags) This byte is divided into a 4-bit compression method and a 4- bit information field depending on the compression method. bits 0 to 3 CM Compression method bits 4 to 7 CINFO Compression info CM (Compression method) This identifies the compression method used in the file. CM = 8 denotes the "deflate" compression method with a window size up to 32K. This is the method used by gzip and PNG (see references [1] and [2] in Chapter 3, below, for the reference documents). CM = 15 is reserved. It might be used in a future version of this specification to indicate the presence of an extra field before the compressed data. CINFO (Compression info) For CM = 8, CINFO is the base-2 logarithm of the LZ77 window size, minus eight (CINFO=7 indicates a 32K window size). Values of CINFO above 7 are not allowed in this version of the specification. CINFO is not defined in this specification for CM not equal to 8. FLG (FLaGs) This flag byte is divided as follows: bits 0 to 4 FCHECK (check bits for CMF and FLG) bit 5 FDICT (preset dictionary) bits 6 to 7 FLEVEL (compression level) The FCHECK value must be such that CMF and FLG, when viewed as a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG), is a multiple of 31. Deutsch & Gailly Informational [Page 5] RFC 1950 ZLIB Compressed Data Format Specification May 1996 FDICT (Preset dictionary) If FDICT is set, a DICT dictionary identifier is present immediately after the FLG byte. The dictionary is a sequence of bytes which are initially fed to the compressor without producing any compressed output. DICT is the Adler-32 checksum of this sequence of bytes (see the definition of ADLER32 below). The decompressor can use this identifier to determine which dictionary has been used by the compressor. FLEVEL (Compression level) These flags are available for use by specific compression methods. The "deflate" method (CM = 8) sets these flags as follows: 0 - compressor used fastest algorithm 1 - compressor used fast algorithm 2 - compressor used default algorithm 3 - compressor used maximum compression, slowest algorithm The information in FLEVEL is not needed for decompression; it is there to indicate if recompression might be worthwhile. compressed data For compression method 8, the compressed data is stored in the deflate compressed data format as described in the document "DEFLATE Compressed Data Format Specification" by L. Peter Deutsch. (See reference [3] in Chapter 3, below) Other compressed data formats are not specified in this version of the zlib specification. ADLER32 (Adler-32 checksum) This contains a checksum value of the uncompressed data (excluding any dictionary data) computed according to Adler-32 algorithm. This algorithm is a 32-bit extension and improvement of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 standard. See references [4] and [5] in Chapter 3, below) Adler-32 is composed of two sums accumulated per byte: s1 is the sum of all bytes, s2 is the sum of all s1 values. Both sums are done modulo 65521. s1 is initialized to 1, s2 to zero. The Adler-32 checksum is stored as s2*65536 + s1 in most- significant-byte first (network) order. Deutsch & Gailly Informational [Page 6] RFC 1950 ZLIB Compressed Data Format Specification May 1996 2.3. Compliance A compliant compressor must produce streams with correct CMF, FLG and ADLER32, but need not support preset dictionaries. When the zlib data format is used as part of another standard data format, the compressor may use only preset dictionaries that are specified by this other data format. If this other format does not use the preset dictionary feature, the compressor must not set the FDICT flag. A compliant decompressor must check CMF, FLG, and ADLER32, and provide an error indication if any of these have incorrect values. A compliant decompressor must give an error indication if CM is not one of the values defined in this specification (only the value 8 is permitted in this version), since another value could indicate the presence of new features that would cause subsequent data to be interpreted incorrectly. A compliant decompressor must give an error indication if FDICT is set and DICTID is not the identifier of a known preset dictionary. A decompressor may ignore FLEVEL and still be compliant. When the zlib data format is being used as a part of another standard format, a compliant decompressor must support all the preset dictionaries specified by the other format. When the other format does not use the preset dictionary feature, a compliant decompressor must reject any stream in which the FDICT flag is set. 3. References [1] Deutsch, L.P.,"GZIP Compressed Data Format Specification", available in ftp://ftp.uu.net/pub/archiving/zip/doc/ [2] Thomas Boutell, "PNG (Portable Network Graphics) specification", available in ftp://ftp.uu.net/graphics/png/documents/ [3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", available in ftp://ftp.uu.net/pub/archiving/zip/doc/ [4] Fletcher, J. G., "An Arithmetic Checksum for Serial Transmissions," IEEE Transactions on Communications, Vol. COM-30, No. 1, January 1982, pp. 247-252. [5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms," November, 1993, pp. 144, 145. (Available from gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073. Deutsch & Gailly Informational [Page 7] RFC 1950 ZLIB Compressed Data Format Specification May 1996 4. Source code Source code for a C language implementation of a "zlib" compliant library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/. 5. Security Considerations A decoder that fails to check the ADLER32 checksum value may be subject to undetected data corruption. 6. Acknowledgements Trademarks cited in this document are the property of their respective owners. Jean-Loup Gailly and Mark Adler designed the zlib format and wrote the related software described in this specification. Glenn Randers-Pehrson converted this document to RFC and HTML format. 7. Authors' Addresses L. Peter Deutsch Aladdin Enterprises 203 Santa Margarita Ave. Menlo Park, CA 94025 Phone: (415) 322-0103 (AM only) FAX: (415) 322-1734 EMail: Jean-Loup Gailly EMail: Questions about the technical content of this specification can be sent by email to Jean-Loup Gailly and Mark Adler Editorial comments on this specification can be sent by email to L. Peter Deutsch and Glenn Randers-Pehrson Deutsch & Gailly Informational [Page 8] RFC 1950 ZLIB Compressed Data Format Specification May 1996 8. Appendix: Rationale 8.1. Preset dictionaries A preset dictionary is specially useful to compress short input sequences. The compressor can take advantage of the dictionary context to encode the input in a more compact manner. The decompressor can be initialized with the appropriate context by virtually decompressing a compressed version of the dictionary without producing any output. However for certain compression algorithms such as the deflate algorithm this operation can be achieved without actually performing any decompression. The compressor and the decompressor must use exactly the same dictionary. The dictionary may be fixed or may be chosen among a certain number of predefined dictionaries, according to the kind of input data. The decompressor can determine which dictionary has been chosen by the compressor by checking the dictionary identifier. This document does not specify the contents of predefined dictionaries, since the optimal dictionaries are application specific. Standard data formats using this feature of the zlib specification must precisely define the allowed dictionaries. 8.2. The Adler-32 algorithm The Adler-32 algorithm is much faster than the CRC32 algorithm yet still provides an extremely low probability of undetected errors. The modulo on unsigned long accumulators can be delayed for 5552 bytes, so the modulo operation time is negligible. If the bytes are a, b, c, the second sum is 3a + 2b + c + 3, and so is position and order sensitive, unlike the first sum, which is just a checksum. That 65521 is prime is important to avoid a possible large class of two-byte errors that leave the check unchanged. (The Fletcher checksum uses 255, which is not prime and which also makes the Fletcher check insensitive to single byte changes 0 <-> 255.) The sum s1 is initialized to 1 instead of zero to make the length of the sequence part of s2, so that the length does not have to be checked separately. (Any sequence of zeroes has a Fletcher checksum of zero.) Deutsch & Gailly Informational [Page 9] RFC 1950 ZLIB Compressed Data Format Specification May 1996 9. Appendix: Sample code The following C code computes the Adler-32 checksum of a data buffer. It is written for clarity, not for speed. The sample code is in the ANSI C programming language. Non C users may find it easier to read with these hints: & Bitwise AND operator. >> Bitwise right shift operator. When applied to an unsigned quantity, as here, right shift inserts zero bit(s) at the left. << Bitwise left shift operator. Left shift inserts zero bit(s) at the right. ++ "n++" increments the variable n. % modulo operator: a % b is the remainder of a divided by b. #define BASE 65521 /* largest prime smaller than 65536 */ /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. The Adler-32 checksum should be initialized to 1. Usage example: unsigned long adler = 1L; while (read_buffer(buffer, length) != EOF) { adler = update_adler32(adler, buffer, length); } if (adler != original_adler) error(); */ unsigned long update_adler32(unsigned long adler, unsigned char *buf, int len) { unsigned long s1 = adler & 0xffff; unsigned long s2 = (adler >> 16) & 0xffff; int n; for (n = 0; n < len; n++) { s1 = (s1 + buf[n]) % BASE; s2 = (s2 + s1) % BASE; } return (s2 << 16) + s1; } /* Return the adler32 of the bytes buf[0..len-1] */ Deutsch & Gailly Informational [Page 10] RFC 1950 ZLIB Compressed Data Format Specification May 1996 unsigned long adler32(unsigned char *buf, int len) { return update_adler32(1L, buf, len); } Deutsch & Gailly Informational [Page 11] tcl8.6.5/compat/zlib/zconf.h0000644000175000017500000003622412663660065015311 0ustar sergeisergei/* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #ifndef ZCONF_H #define ZCONF_H /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * Even better than compiling with -DZ_PREFIX would be to use configure to set * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET /* all linked symbols */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align # define _tr_flush_bits z__tr_flush_bits # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block # define _tr_tally z__tr_tally # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 # ifndef Z_SOLO # define compress z_compress # define compress2 z_compress2 # define compressBound z_compressBound # endif # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams # define deflatePending z_deflatePending # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset # define deflateResetKeep z_deflateResetKeep # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table # ifndef Z_SOLO # define gz_error z_gz_error # define gz_intmax z_gz_intmax # define gz_strwinerror z_gz_strwinerror # define gzbuffer z_gzbuffer # define gzclearerr z_gzclearerr # define gzclose z_gzclose # define gzclose_r z_gzclose_r # define gzclose_w z_gzclose_w # define gzdirect z_gzdirect # define gzdopen z_gzdopen # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush # define gzgetc z_gzgetc # define gzgetc_ z_gzgetc_ # define gzgets z_gzgets # define gzoffset z_gzoffset # define gzoffset64 z_gzoffset64 # define gzopen z_gzopen # define gzopen64 z_gzopen64 # ifdef _WIN32 # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf # define gzvprintf z_gzvprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread # define gzrewind z_gzrewind # define gzseek z_gzseek # define gzseek64 z_gzseek64 # define gzsetparams z_gzsetparams # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc # define gzwrite z_gzwrite # endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd # define inflateBackInit_ z_inflateBackInit_ # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd # define inflateGetHeader z_inflateGetHeader # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 # define inflateSetDictionary z_inflateSetDictionary # define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine # define inflateResetKeep z_inflateResetKeep # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # ifndef Z_SOLO # define uncompress z_uncompress # endif # define zError z_zError # ifndef Z_SOLO # define zcalloc z_zcalloc # define zcfree z_zcfree # endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion /* all zlib typedefs in zlib.h and zconf.h */ # define Byte z_Byte # define Bytef z_Bytef # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func # ifndef Z_SOLO # define gzFile z_gzFile # endif # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func # define intf z_intf # define out_func z_out_func # define uInt z_uInt # define uIntf z_uIntf # define uLong z_uLong # define uLongf z_uLongf # define voidp z_voidp # define voidpc z_voidpc # define voidpf z_voidpf /* all zlib structs in zlib.h and zconf.h */ # define gz_header_s z_gz_header_s # define internal_state z_internal_state #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) # define OS2 #endif #if defined(_WINDOWS) && !defined(WINDOWS) # define WINDOWS #endif #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) # ifndef WIN32 # define WIN32 # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # ifndef SYS16BIT # define SYS16BIT # endif # endif #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #ifdef SYS16BIT # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #ifdef __STDC_VERSION__ # ifndef STDC # define STDC # endif # if __STDC_VERSION__ >= 199901L # ifndef STDC99 # define STDC99 # endif # endif #endif #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) # define STDC #endif #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) # define STDC #endif #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) # define STDC #endif #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) # define STDC #endif #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ # define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const /* note: need a more gentle solution here */ # endif #endif #if defined(ZLIB_CONST) && !defined(z_const) # define z_const const #else # define z_const #endif /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) # define NO_DUMMY_DECL #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus a few kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif #ifndef Z_ARG /* function prototypes for stdarg */ # if defined(STDC) || defined(Z_HAVE_STDARG_H) # define Z_ARG(args) args # else # define Z_ARG(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #ifdef SYS16BIT # if defined(M_I86SM) || defined(M_I86MM) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR _far # else # define FAR far # endif # endif # if (defined(__SMALL__) || defined(__MEDIUM__)) /* Turbo C small or medium model */ # define SMALL_MEDIUM # ifdef __BORLANDC__ # define FAR _far # else # define FAR far # endif # endif #endif #if defined(WINDOWS) || defined(WIN32) /* If building or using zlib as a DLL, define ZLIB_DLL. * This is not mandatory, but it offers a little performance increase. */ # ifdef ZLIB_DLL # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) # ifdef ZLIB_INTERNAL # define ZEXTERN extern __declspec(dllexport) # else # define ZEXTERN extern __declspec(dllimport) # endif # endif # endif /* ZLIB_DLL */ /* If building or using zlib with the WINAPI/WINAPIV calling convention, * define ZLIB_WINAPI. * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 # define ZEXPORTVA WINAPIV # else # define ZEXPORTVA FAR CDECL # endif # endif #endif #if defined (__BEOS__) # ifdef ZLIB_DLL # ifdef ZLIB_INTERNAL # define ZEXPORT __declspec(dllexport) # define ZEXPORTVA __declspec(dllexport) # else # define ZEXPORT __declspec(dllimport) # define ZEXPORTVA __declspec(dllimport) # endif # endif #endif #ifndef ZEXTERN # define ZEXTERN extern #endif #ifndef ZEXPORT # define ZEXPORT #endif #ifndef ZEXPORTVA # define ZEXPORTVA #endif #ifndef FAR # define FAR #endif #if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void const *voidpc; typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte const *voidpc; typedef Byte FAR *voidpf; typedef Byte *voidp; #endif #if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) # include # if (UINT_MAX == 0xffffffffUL) # define Z_U4 unsigned # elif (ULONG_MAX == 0xffffffffUL) # define Z_U4 unsigned long # elif (USHRT_MAX == 0xffffffffUL) # define Z_U4 unsigned short # endif #endif #ifdef Z_U4 typedef Z_U4 z_crc_t; #else typedef unsigned long z_crc_t; #endif #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif #ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_STDARG_H #endif #ifdef STDC # ifndef Z_SOLO # include /* for off_t */ # endif #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO # include /* for va_list */ # endif #endif #ifdef _WIN32 # ifndef Z_SOLO # include /* for wchar_t */ # endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even * though the former does not conform to the LFS document), but considering * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ #if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif #if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) # define Z_HAVE_UNISTD_H #endif #ifndef Z_SOLO # if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ # endif # ifndef z_off_t # define z_off_t off_t # endif # endif #endif #if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 # define Z_LFS64 #endif #if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) # define Z_LARGE64 #endif #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) # define Z_WANT64 #endif #if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t # define z_off_t long #endif #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else # if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) # define z_off64_t __int64 # else # define z_off64_t z_off_t # endif #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) #pragma map(deflateInit_,"DEIN") #pragma map(deflateInit2_,"DEIN2") #pragma map(deflateEnd,"DEEND") #pragma map(deflateBound,"DEBND") #pragma map(inflateInit_,"ININ") #pragma map(inflateInit2_,"ININ2") #pragma map(inflateEnd,"INEND") #pragma map(inflateSync,"INSY") #pragma map(inflateSetDictionary,"INSEDI") #pragma map(compressBound,"CMBND") #pragma map(inflate_table,"INTABL") #pragma map(inflate_fast,"INFA") #pragma map(inflate_copyright,"INCOPY") #endif #endif /* ZCONF_H */ tcl8.6.5/compat/zlib/gzwrite.c0000644000175000017500000003750712663660065015665 0ustar sergeisergei/* gzwrite.c -- zlib functions for writing gzip files * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" /* Local functions */ local int gz_init OF((gz_statep)); local int gz_comp OF((gz_statep, int)); local int gz_zero OF((gz_statep, z_off64_t)); /* Initialize state for writing a gzip file. Mark initialization by setting state->size to non-zero. Return -1 on failure or 0 on success. */ local int gz_init(state) gz_statep state; { int ret; z_streamp strm = &(state->strm); /* allocate input buffer */ state->in = (unsigned char *)malloc(state->want); if (state->in == NULL) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } /* only need output buffer and deflate state if compressing */ if (!state->direct) { /* allocate output buffer */ state->out = (unsigned char *)malloc(state->want); if (state->out == NULL) { free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } /* allocate deflate memory, set up for gzip compression */ strm->zalloc = Z_NULL; strm->zfree = Z_NULL; strm->opaque = Z_NULL; ret = deflateInit2(strm, state->level, Z_DEFLATED, MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); if (ret != Z_OK) { free(state->out); free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } } /* mark state as initialized */ state->size = state->want; /* initialize write buffer if compressing */ if (!state->direct) { strm->avail_out = state->size; strm->next_out = state->out; state->x.next = strm->next_out; } return 0; } /* Compress whatever is at avail_in and next_in and write to the output file. Return -1 if there is an error writing to the output file, otherwise 0. flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, then the deflate() state is reset to start a new gzip stream. If gz->direct is true, then simply write to the output file without compressing, and ignore flush. */ local int gz_comp(state, flush) gz_statep state; int flush; { int ret, got; unsigned have; z_streamp strm = &(state->strm); /* allocate memory if this is the first time through */ if (state->size == 0 && gz_init(state) == -1) return -1; /* write directly if requested */ if (state->direct) { got = write(state->fd, strm->next_in, strm->avail_in); if (got < 0 || (unsigned)got != strm->avail_in) { gz_error(state, Z_ERRNO, zstrerror()); return -1; } strm->avail_in = 0; return 0; } /* run deflate() on provided input until it produces no more output */ ret = Z_OK; do { /* write out current buffer contents if full, or if flushing, but if doing Z_FINISH then don't write until we get to Z_STREAM_END */ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { have = (unsigned)(strm->next_out - state->x.next); if (have && ((got = write(state->fd, state->x.next, have)) < 0 || (unsigned)got != have)) { gz_error(state, Z_ERRNO, zstrerror()); return -1; } if (strm->avail_out == 0) { strm->avail_out = state->size; strm->next_out = state->out; } state->x.next = strm->next_out; } /* compress */ have = strm->avail_out; ret = deflate(strm, flush); if (ret == Z_STREAM_ERROR) { gz_error(state, Z_STREAM_ERROR, "internal error: deflate stream corrupt"); return -1; } have -= strm->avail_out; } while (have); /* if that completed a deflate stream, allow another to start */ if (flush == Z_FINISH) deflateReset(strm); /* all done, no errors */ return 0; } /* Compress len zeros to output. Return -1 on error, 0 on success. */ local int gz_zero(state, len) gz_statep state; z_off64_t len; { int first; unsigned n; z_streamp strm = &(state->strm); /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return -1; /* compress len zeros (len guaranteed > 0) */ first = 1; while (len) { n = GT_OFF(state->size) || (z_off64_t)state->size > len ? (unsigned)len : state->size; if (first) { memset(state->in, 0, n); first = 0; } strm->avail_in = n; strm->next_in = state->in; state->x.pos += n; if (gz_comp(state, Z_NO_FLUSH) == -1) return -1; len -= n; } return 0; } /* -- see zlib.h -- */ int ZEXPORT gzwrite(file, buf, len) gzFile file; voidpc buf; unsigned len; { unsigned put = len; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return 0; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids the flaw in the interface) */ if ((int)len < 0) { gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); return 0; } /* if len is zero, avoid unnecessary operations */ if (len == 0) return 0; /* allocate memory if this is the first time through */ if (state->size == 0 && gz_init(state) == -1) return 0; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return 0; } /* for small len, copy to input buffer, otherwise compress directly */ if (len < state->size) { /* copy to input buffer, compress when full */ do { unsigned have, copy; if (strm->avail_in == 0) strm->next_in = state->in; have = (unsigned)((strm->next_in + strm->avail_in) - state->in); copy = state->size - have; if (copy > len) copy = len; memcpy(state->in + have, buf, copy); strm->avail_in += copy; state->x.pos += copy; buf = (const char *)buf + copy; len -= copy; if (len && gz_comp(state, Z_NO_FLUSH) == -1) return 0; } while (len); } else { /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* directly compress user buffer to file */ strm->avail_in = len; strm->next_in = (z_const Bytef *)buf; state->x.pos += len; if (gz_comp(state, Z_NO_FLUSH) == -1) return 0; } /* input was all buffered or compressed (put will fit in int) */ return (int)put; } /* -- see zlib.h -- */ int ZEXPORT gzputc(file, c) gzFile file; int c; { unsigned have; unsigned char buf[1]; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return -1; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return -1; } /* try writing to input buffer for speed (state->size == 0 if buffer not initialized) */ if (state->size) { if (strm->avail_in == 0) strm->next_in = state->in; have = (unsigned)((strm->next_in + strm->avail_in) - state->in); if (have < state->size) { state->in[have] = c; strm->avail_in++; state->x.pos++; return c & 0xff; } } /* no room in buffer or not initialized, use gz_write() */ buf[0] = c; if (gzwrite(file, buf, 1) != 1) return -1; return c & 0xff; } /* -- see zlib.h -- */ int ZEXPORT gzputs(file, str) gzFile file; const char *str; { int ret; unsigned len; /* write string */ len = (unsigned)strlen(str); ret = gzwrite(file, str, len); return ret == 0 && len != 0 ? -1 : ret; } #if defined(STDC) || defined(Z_HAVE_STDARG_H) #include /* -- see zlib.h -- */ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { int size, len; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) return 0; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return 0; } /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* do the printf() into the input buffer, put length in len */ size = (int)(state->size); state->in[size - 1] = 0; #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void (void)vsprintf((char *)(state->in), format, va); for (len = 0; len < size; len++) if (state->in[len] == 0) break; # else len = vsprintf((char *)(state->in), format, va); # endif #else # ifdef HAS_vsnprintf_void (void)vsnprintf((char *)(state->in), size, format, va); len = strlen((char *)(state->in)); # else len = vsnprintf((char *)(state->in), size, format, va); # endif #endif /* check that printf() results fit in buffer */ if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) return 0; /* update buffer and position, defer compression until needed */ strm->avail_in = (unsigned)len; strm->next_in = state->in; state->x.pos += len; return len; } int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) { va_list va; int ret; va_start(va, format); ret = gzvprintf(file, format, va); va_end(va); return ret; } #else /* !STDC && !Z_HAVE_STDARG_H */ /* -- see zlib.h -- */ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) gzFile file; const char *format; int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; { int size, len; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that can really pass pointer in ints */ if (sizeof(int) != sizeof(void *)) return 0; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) return 0; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return 0; } /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* do the printf() into the input buffer, put length in len */ size = (int)(state->size); state->in[size - 1] = 0; #ifdef NO_snprintf # ifdef HAS_sprintf_void sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); for (len = 0; len < size; len++) if (state->in[len] == 0) break; # else len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #else # ifdef HAS_snprintf_void snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); len = strlen((char *)(state->in)); # else len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #endif /* check that printf() results fit in buffer */ if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) return 0; /* update buffer and position, defer compression until needed */ strm->avail_in = (unsigned)len; strm->next_in = state->in; state->x.pos += len; return len; } #endif /* -- see zlib.h -- */ int ZEXPORT gzflush(file, flush) gzFile file; int flush; { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return Z_STREAM_ERROR; /* check flush parameter */ if (flush < 0 || flush > Z_FINISH) return Z_STREAM_ERROR; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return -1; } /* compress remaining data with requested flush */ gz_comp(state, flush); return state->err; } /* -- see zlib.h -- */ int ZEXPORT gzsetparams(file, level, strategy) gzFile file; int level; int strategy; { gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return Z_STREAM_ERROR; /* if no change is requested, then do nothing */ if (level == state->level && strategy == state->strategy) return Z_OK; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return -1; } /* change compression parameters for subsequent input */ if (state->size) { /* flush previous input with previous parameters before changing */ if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) return state->err; deflateParams(strm, level, strategy); } state->level = level; state->strategy = strategy; return Z_OK; } /* -- see zlib.h -- */ int ZEXPORT gzclose_w(file) gzFile file; { int ret = Z_OK; gz_statep state; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're writing */ if (state->mode != GZ_WRITE) return Z_STREAM_ERROR; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) ret = state->err; } /* flush, free memory, and close file */ if (gz_comp(state, Z_FINISH) == -1) ret = state->err; if (state->size) { if (!state->direct) { (void)deflateEnd(&(state->strm)); free(state->out); } free(state->in); } gz_error(state, Z_OK, NULL); free(state->path); if (close(state->fd) == -1) ret = Z_ERRNO; free(state); return ret; } tcl8.6.5/compat/zlib/zlib.h0000644000175000017500000025351312663660065015134 0ustar sergeisergei/* zlib.h -- interface of the 'zlib' general purpose compression library version 1.2.8, April 28th, 2013 Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef ZLIB_H #define ZLIB_H #include "zconf.h" #ifdef __cplusplus extern "C" { #endif #define ZLIB_VERSION "1.2.8" #define ZLIB_VERNUM 0x1280 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 #define ZLIB_VER_REVISION 8 #define ZLIB_VER_SUBREVISION 0 /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms will be added later and will have the same stream interface. Compression can be done in a single step if the buffers are large enough, or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. The compressed data format used by default by the in-memory functions is the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped around a deflate stream, which is itself documented in RFC 1951. The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. This library can optionally read and write gzip streams in memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- file compression on file systems, has a larger header than zlib to maintain directory information, and uses a different, slower check method than zlib. The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total number of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total number of bytes output so far */ z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: binary or text */ uLong adler; /* adler32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* gzip header information passed to and from zlib routines. See RFC 1952 for more details on the meanings of these fields. */ typedef struct gz_header_s { int text; /* true if compressed data believed to be text */ uLong time; /* modification time */ int xflags; /* extra flags (not used when writing a gzip file) */ int os; /* operating system */ Bytef *extra; /* pointer to extra field or Z_NULL if none */ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ uInt extra_max; /* space at extra (only when reading header) */ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ uInt name_max; /* space at name (only when reading header) */ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ uInt comm_max; /* space at comment (only when reading header) */ int hcrc; /* true if there was or will be a header crc */ int done; /* true when done reading gzip header (not used when writing a gzip file) */ } gz_header; typedef gz_header FAR *gz_headerp; /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The opaque value provided by the application will be passed as the first parameter for calls of zalloc and zfree. This can be useful for custom memory management. The compression library attaches no meaning to the opaque value. zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be thread safe. On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers returned by zalloc for objects of exactly 65536 bytes *must* have their offset normalized to zero. The default allocation function provided by this library ensures this (see zutil.c). To reduce memory requirements and avoid any allocation of 64K objects, at the expense of compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use in the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 #define Z_BLOCK 5 #define Z_TREES 6 /* Allowed flush values; see deflate() and inflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative values * are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_RLE 3 #define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 /* Possible values of the data_type field (though see inflate()) */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ /* basic functions */ ZEXTERN const char * ZEXPORT zlibVersion OF((void)); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level, or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary (in interactive applications). Some output may be provided even if flush is not set. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to maximize compression. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular avail_in is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. This completes the current deflate block and follows it with an empty stored block that is three bits plus filler bits to the next byte, followed by four bytes (00 00 ff ff). If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the output buffer, but the output is not aligned to a byte boundary. All of the input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output in order for the decompressor to finish the block before the empty fixed code block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to seven bits of the current block are held to be written as the next byte after the next deflate block is completed. In this case, the decompressor may not be provided enough bits at this point in order to complete decompression of the data provided so far to the compressor. It may need to wait for the next block to be emitted. This is for advanced applications that need to control the emission of deflate blocks. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out is greater than six to avoid repeated flush markers due to avail_out == 0 on return. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space; if deflate returns with Z_OK, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd. Z_FINISH can be used immediately after deflateInit if all the compression is to be done in a single step. In this case, avail_out must be at least the value returned by deflateBound (see below). Then deflate is guaranteed to return Z_STREAM_END. If not enough output space is provided, deflate will not return Z_STREAM_END, and it must be called again as described above. deflate() sets strm->adler to the adler32 checksum of all input read so far (that is, total_in bytes). deflate() may update strm->data_type if it can make a good guess about the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and deflate() can be called again with more input and more output space to continue compressing. */ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded). In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. If next_in is not Z_NULL and avail_in is large enough (the exact value depends on the compression method), inflateInit determines the compression method from the zlib header and allocates all data structures accordingly; otherwise the allocation will be deferred to the first call of inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. inflate performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in is updated and processing will resume at this point for the next call of inflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much output as possible to the output buffer. Z_BLOCK requests that inflate() stop if and when it gets to the next deflate block boundary. When decoding the zlib or gzip format, this will cause inflate() to return immediately after the header and before the first block. When doing a raw inflate, inflate() will go ahead and process the first block, and will return when it gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. Also to assist in this, on return inflate() will set strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or decoding the complete header up to just before the first byte of the deflate stream. The end-of-block will not be indicated until all of the uncompressed data from that block has been written to strm->next_out. The number of unused bits may in general be greater than seven, except when bit 7 of data_type is set, in which case the number of unused bits will be less than eight. data_type is set as noted here every time inflate() returns for all flush options, and so can be used to determine the amount of currently consumed input in bits. The Z_TREES option behaves as Z_BLOCK does, but it also returns when the end of each deflate block header is reached, before any actual data in that block is decoded. This allows the caller to determine the length of the deflate block header for later use in random access within a deflate block. 256 is added to the value of strm->data_type when inflate() returns immediately after reaching the end of the deflate block header. inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all of the uncompressed data for the operation to complete. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The use of Z_FINISH is not required to perform an inflation in one step. However it may be used to inform inflate that a faster approach can be used for the single inflate() call. Z_FINISH also informs inflate to not maintain a sliding window if the stream completes, which reduces inflate's memory footprint. If the stream does not complete, either because not all of the stream is provided or not enough output space is provided, then a sliding window will be allocated and inflate() can be called again to continue the operation as if Z_NO_FLUSH had been used. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the first call. So the effects of the flush parameter in this implementation are on the return value of inflate() as noted below, when inflate() returns early when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of memory for a sliding window when Z_FINISH is used. If a preset dictionary is needed after this call (see inflateSetDictionary below), inflate sets strm->adler to the Adler-32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed adler32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip header is not retained, so applications that need that information should instead use raw inflate, see inflateInit2() below, or inflateBack() and perform their own processing of the gzip header and trailer. When processing gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output producted so far. The CRC-32 is checked against the gzip trailer. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check value), Z_STREAM_ERROR if the stream structure was inconsistent (for example next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no progress is possible or if there was not enough room in the output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial recovery of the data is desired. */ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent. In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* Advanced functions */ /* The following functions are needed only in some special applications. */ /* ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy)); This is another version of deflateInit with more compression options. The fields next_in, zalloc, zfree and opaque must be initialized before by the caller. The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. Larger values of this parameter result in better compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data with no zlib header or trailer, and will not compute an adler32 check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no header crc, and the operating system will be set to 255 (unknown). If a gzip stream is being written, strm->adler is a crc32 instead of an adler32. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory for optimal speed. The default value is 8. See zconf.h for total memory usage as a function of windowBits and memLevel. The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no string match), or Z_RLE to limit match distances to one (run-length encoding). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of Z_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit2 does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength)); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. When using the zlib format, this function must be called immediately after deflateInit, deflateInit2 or deflateReset, and before any call of deflate. When doing raw deflate, this function must be called either before any call of deflate, or immediately after the completion of a deflate block, i.e. after all input has been consumed and all output has been delivered when using any of the flush options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The compressor and decompressor must use exactly the same dictionary (see inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size provided in deflateInit or deflateInit2. Thus the strings most likely to be useful should be put at the end of the dictionary, not at the front. In addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. Upon return of this function, strm->adler is set to the adler32 value of the dictionary; the decompressor may later use this value to determine which dictionary has been used by the compressor. (The adler32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the adler32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream or if not at a block boundary for raw deflate). deflateSetDictionary does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal compression state which can be quite large, so this strategy is slow and can consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate all the internal compression state. The stream will keep the same compression level and any other attributes that may have been set by deflateInit2. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int level, int strategy)); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2. This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression level is changed, the input available so far is compressed with the old level (and may be flushed); the new level will take effect only at the next call of deflate(). Before the call of deflateParams, the stream state must be set as for a call of deflate(), since the currently available input may have to be compressed and flushed. In particular, strm->avail_out must be non-zero. deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if strm->avail_out was zero. */ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain)); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for searching for the best matching string, and even then only by the most fanatic optimizer trying to squeeze out the last compressed bit for their specific input data. Read the deflate.c source code for the meaning of the max_lazy, good_length, nice_length, and max_chain parameters. deflateTune() can be called after deflateInit() or deflateInit2(), and returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, uLong sourceLen)); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be called before deflate(). If that first deflate() call is provided the sourceLen input bytes, an output buffer allocated to the size returned by deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed to return Z_STREAM_END. Note that it is possible for the compressed size to be larger than the value returned by deflateBound() if flush options other than Z_FINISH or Z_NO_FLUSH are used. */ ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, unsigned *pending, int *bits)); /* deflatePending() returns the number of bytes and bits of output that have been generated, but not yet provided in the available output. The bytes not provided would be due to the available output space having being consumed. The number of bits of output not provided are between 0 and 7, where they await more bits to join them in order to fill out a full byte. If pending or bits are Z_NULL, then those values are not set. deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, int bits, int value)); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits leftover from a previous deflate stream when appending to it. As such, this function can only be used for raw deflate, and must be used before the first deflate() call after a deflateInit2() or deflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the output. deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, gz_headerp head)); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called after deflateInit2() or deflateReset() and before the first call of deflate(). The text, time, os, extra field, name, and comment information in the provided gz_header structure are written to the gzip header (xflag is ignored -- the extra flags are set according to the compression level). The caller must assure that, if not Z_NULL, name and comment are terminated with a zero byte, and that if extra is not Z_NULL, that extra_len bytes are available there. If hcrc is true, a gzip header crc is included. Note that the current versions of the command-line version of gzip (up through version 1.3.x) do not support header crc's, and will report that it is a "multi-part gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, the time set to zero, and os set to 255, with no extra, name, or comment fields. The gzip header is returned to the default state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, int windowBits)); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. The default value is 15 if inflateInit is used instead. windowBits must be greater than or equal to the windowBits value provided to deflateInit2() while compressing, or it must be equal to 15 if deflateInit2() was not used. If a compressed stream with a larger window size is given as input, inflate() will return with the error code Z_DATA_ERROR instead of trying to allocate a larger window. windowBits can also be zero to request that inflate use the window size in the zlib header of the compressed stream. windowBits can also be -8..-15 for raw inflate. In this case, -windowBits determines the window size. inflate() will then process raw deflate data, not looking for a zlib or gzip header, not generating a check value, and not looking for any check values for comparison at the end of the stream. This is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is recommended that a check value such as an adler32 or a crc32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. windowBits can also be greater than 15 for optional gzip decoding. Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a crc32 instead of an adler32. inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit2 does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit2() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength)); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the adler32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called at any time to set the dictionary. If the provided dictionary is smaller than the window and there is already data in the window, then the provided dictionary will amend what's there. The application must insure that the dictionary that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the expected one (incorrect adler32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, Bytef *dictionary, uInt *dictLength)); /* Returns the sliding dictionary being maintained by inflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If inflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. Similary, if dictLength is Z_NULL, then it is not set. inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. */ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); /* Skips invalid compressed data until a possible full flush point (see above for the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. inflateSync searches for a 00 00 FF FF pattern in the compressed data. All full flush points have this pattern, but not all occurrences of this pattern are full flush points. inflateSync returns Z_OK if a possible full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the success case, the application may save the current current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when randomly accessing a large stream. The first pass through the stream can periodically record the inflate state, allowing restarting inflate at those points when randomly accessing the stream. inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate all the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, int windowBits)); /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted the same as it is for inflateInit2. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if the windowBits parameter is invalid. */ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, int bits, int value)); /* This function inserts bits in the inflate input stream. The intent is that this function is used to start inflating at a bit position in the middle of a byte. The provided bits will be used before any bytes are used from next_in. This function should only be used with raw inflate, and should be used before the first inflate() call after inflateInit2() or inflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the input. If bits is negative, then the input stream bit buffer is emptied. Then inflatePrime() can be called again to put bits in the buffer. This is used to clear out bits leftover after feeding inflate a block description prior to feeding inflate codes. inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); /* This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the return value down 16 bits. If the upper value is -1 and the lower value is zero, then inflate() is currently decoding information outside of a block. If the upper value is -1 and the lower value is non-zero, then inflate is in the middle of a stored block, with the lower value equaling the number of bytes from the input remaining to copy. If the upper value is not -1, then it is the number of bits back from the current bit position in the input of the code (literal or length/distance pair) currently being processed. In that case the lower value is the number of bytes already emitted for that code. A code is being processed if inflate is waiting for more input to complete decoding of the code, or if it has completed decoding but is waiting for more output space to write the literal or match data. inflateMark() is used to mark locations in the input data for random access, which may be at bit positions, and to note those cases where the output of a code may span boundaries of random access blocks. The current location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. inflateMark returns the value noted above or -1 << 16 if the provided source stream state was inconsistent. */ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, gz_headerp head)); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after inflateInit2() or inflateReset(), and before the first call of inflate(). As inflate() processes the gzip stream, head->done is zero until the header is completed, at which time head->done is set to one. If a zlib stream is being decoded, then head->done is set to -1 to indicate that there will be no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be used to force inflate() to return immediately after header processing is complete and before any actual data is decompressed. The text, time, xflags, and os fields are filled in with the gzip header contents. hcrc is set to true if there is a header CRC. (The header CRC was valid if done is set to one.) If extra is not Z_NULL, then extra_max contains the maximum number of bytes to write to extra. Once done is true, extra_len contains the actual extra field length, and extra contains the extra field, or that field truncated if extra_max is less than extra_len. If name is not Z_NULL, then up to name_max characters are written there, terminated with a zero unless the length is greater than name_max. If comment is not Z_NULL, then up to comm_max characters are written there, terminated with a zero unless the length is greater than comm_max. When any of extra, name, or comment are not Z_NULL and the respective field is not present in the header, then that field is set to Z_NULL to signal its absence. This allows the use of deflateSetHeader() with the returned structure to duplicate the header. However if those fields are set to allocated memory, then the application will need to save those pointers elsewhere so that they can be eventually freed. If inflateGetHeader is not used, then the header information is simply discarded. The header is always checked for validity, including the header CRC if present. inflateReset() will reset the process to discard the header information. The application would need to call inflateGetHeader() again to retrieve the header from the next gzip stream. inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, unsigned char FAR *window)); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized before the call. If zalloc and zfree are Z_NULL, then the default library- derived memory allocation routines are used. windowBits is the base two logarithm of the window size, in the range 8..15. window is a caller supplied buffer of that size. Except for special applications where it is assured that deflate was used with small window sizes, windowBits must be 15 and a 32K byte window must be supplied to be able to decompress general deflate streams. See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ typedef unsigned (*in_func) OF((void FAR *, z_const unsigned char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)); /* inflateBack() does a raw inflate with a single call using a call-back interface for input and output. This is potentially more efficient than inflate() for file i/o applications, in that it avoids copying between the output and the sliding window by simply making the window itself the output buffer. inflate() can be faster on modern CPUs when used with large buffers. inflateBack() trusts the application to not change the output buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. inflateBack() may then be used multiple times to inflate a complete, raw deflate stream with each call. inflateBackEnd() is then called to free the allocated state. A raw deflate stream is one with no zlib or gzip header or trailer. This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only the raw deflate stream to decompress. This is different from the normal behavior of inflate(), which expects either a zlib or gzip header and trailer around the deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those routines until it reads a complete deflate stream and writes out all of the uncompressed data, or until it encounters an error. The function's parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If there is no input available, in() must return zero--buf is ignored in that case--and inflateBack() will return a buffer error. inflateBack() will call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() should return zero on success, or non-zero on failure. If out() returns non-zero, inflateBack() will return with an error. Neither in() nor out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). For convenience, inflateBack() can be provided input on the first call by setting strm->next_in and strm->avail_in. If that input is exhausted, then in() will be called. Therefore strm->next_in must be initialized before calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in must also be initialized, and then if strm->avail_in is not zero, input will initially be taken from strm->next_in[0 .. strm->avail_in - 1]. The in_desc and out_desc parameters of inflateBack() is passed as the first parameter of in() and out() respectively when they are called. These descriptors can be optionally used to pass any information that the caller- supplied in() and out() functions need to do their job. On return, inflateBack() will set strm->next_in and strm->avail_in to pass back any unused input that was provided by the last in() call. The return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR if in() or out() returned an error, Z_DATA_ERROR if there was a format error in the deflate stream (in which case strm->msg is set to indicate the nature of the error), or Z_STREAM_ERROR if the stream was not properly initialized. In the case of Z_BUF_ERROR, an input or output error can be distinguished using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); /* All memory allocated by inflateBackInit() is freed. inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream state was inconsistent. */ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: 1.0: size of uInt 3.2: size of uLong 5.4: size of voidpf (pointer) 7.6: size of z_off_t Compiler, assembler, and debug options: 8: DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) One-time table building (smaller code, but not thread-safe if true): 12: BUILDFIXED -- build static block decoding tables when needed 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed 14,15: 0 (reserved) Library content (indicates missing functionality): 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking deflate code when not needed) 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect and decode gzip streams (to avoid linking crc code) 18-19: 0 (reserved) Operation variations (changes in library functionality): 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate 21: FASTEST -- deflate algorithm with only one, lowest compression level 22,23: 0 (reserved) The sprintf variant used by gzprintf (zero is best): 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! 26: 0 = returns value, 1 = void -- 1 means inferred string length returned Remainder: 27-31: 0 (reserved) */ #ifndef Z_SOLO /* utility functions */ /* The following utility functions are implemented on top of the basic stream-oriented functions. To simplify the interface, some default options are assumed (compression level and memory usage, standard memory allocation functions). The source code of these utility functions can be modified if you need special options. */ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed buffer. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed buffer. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the uncompressed buffer. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In the case where there is not enough room, uncompress() will fill the output buffer with the uncompressed data up to that point. */ /* gzip file access functions */ /* This library supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio, using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. */ typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); Opens a gzip (.gz) file for reading or writing. The mode parameter is as in fopen ("rb" or "wb") but can also include a compression level ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of deflateInit2 for more information about the strategy parameter.) 'T' will request transparent writing or appending with no compression and not using the gzip format. "a" can be used instead of "w" to request that the gzip stream that will be written be appended to the file. "+" will result in an error, since reading and writing to the same gzip file is not supported. The addition of "x" when writing will create the file exclusively, which fails if the file already exists. On systems that support it, the addition of "e" when reading or writing will set the flag to close the file on an execve() call. These functions, as well as gzip, will read and decode a sequence of gzip streams in a file. The append function of gzopen() can be used to create such a file. (Also see gzflush() for another way to do this.) When appending, gzopen does not test whether the file begins with a gzip stream, nor does it look for the end of the gzip streams to begin appending. gzopen will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this case gzread will directly read from the file without decompression. When reading, this will be detected automatically by looking for the magic two- byte gzip header. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). errno can be checked to determine if the reason gzopen failed was that the file could not be opened. */ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); /* gzdopen associates a gzFile with the file descriptor fd. File descriptors are obtained from calls like open, dup, creat, pipe or fileno (if the file has been previously opened with fopen). The mode parameter is as in gzopen. The next call of gzclose on the returned gzFile will also close the file descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since gzdopen does not close fd if it fails. If you are using fileno() to get the file descriptor from a FILE *, then you will have to use dup() to avoid double-close()ing the file descriptor. Both gzclose() and fclose() will close the associated file descriptor, so they need to have different file descriptors. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided), or if fd is -1. The file descriptor is not used until the next gz* read, write, seek, or close operation, so gzdopen will not detect if fd is invalid (unless fd is -1). */ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); /* Set the internal buffer size used by this library's functions. The default buffer size is 8192 bytes. This function must be called after gzopen() or gzdopen(), and before any other calls that read or write the file. The buffer memory allocation is always deferred to the first read or write. Two buffers are allocated, either both of the specified size when writing, or one of the specified size and the other twice that size when reading. A larger buffer size of, for example, 64K or 128K bytes will noticeably increase the speed of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). gzbuffer() returns 0 on success, or -1 on failure, such as being called too late. */ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* Dynamically update the compression level or strategy. See the description of deflateInit2 for the meaning of these parameters. gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not opened for writing. */ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* Reads the given number of uncompressed bytes from the compressed file. If the input file is not in gzip format, gzread copies the given number of bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue to read, looking for another gzip stream. Any number of gzip streams may be concatenated in the input file, and will all be decompressed by gzread(). If something other than a gzip stream is encountered after a gzip stream, that remaining trailing garbage is ignored (and no error is returned). gzread can be used to read a gzip file that is being concurrently written. Upon reaching the end of the input, gzread will return with the available data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then gzclearerr can be used to clear the end of file indicator in order to permit gzread to be tried again. Z_OK indicates that a gzip stream was completed on the last gzread. Z_BUF_ERROR indicates that the input file ended in the middle of a gzip stream. Note that gzread does not return -1 in the event of an incomplete gzip stream. This error is deferred until gzclose(), which will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip stream. Alternatively, gzerror can be used before gzclose to detect this case. gzread returns the number of uncompressed bytes actually read, less than len for end of file, or -1 for error. */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); /* Writes the given number of uncompressed bytes into the compressed file. gzwrite returns the number of uncompressed bytes written or 0 in case of error. */ ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* Converts, formats, and writes the arguments to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of uncompressed bytes actually written, or 0 in case of error. The number of uncompressed bytes written is limited to 8191, or one less than the buffer size given to gzbuffer(). The caller should assure that this limit is not exceeded. If it is exceeded, then gzprintf() will return an error (0) with nothing written. In this case, there may also be a buffer overflow with unpredictable consequences, which is possible only if zlib was compiled with the insecure functions sprintf() or vsprintf() because the secure snprintf() or vsnprintf() functions were not available. This can be determined using zlibCompileFlags(). */ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); /* Writes the given null-terminated string to the compressed file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. */ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); /* Reads bytes from the compressed file until len-1 characters are read, or a newline character is read and transferred to buf, or an end-of-file condition is encountered. If any characters are read or if len == 1, the string is terminated with a null character. If no characters are read due to an end-of-file or len < 1, then the buffer is left untouched. gzgets returns buf which is a null-terminated string, or it returns NULL for end-of-file or in case of error. If there was an error, the contents at buf are indeterminate. */ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); /* Writes c, converted to an unsigned char, into the compressed file. gzputc returns the value that was written, or -1 in case of error. */ ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); /* Reads one byte from the compressed file. gzgetc returns this byte or -1 in case of end of file or error. This is implemented as a macro for speed. As such, it does not do all of the checking the other functions do. I.e. it does not check to see if file is NULL, nor whether the structure file points to has been clobbered or not. */ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); /* Push one character back onto the stream to be read as the first character on the next read. At least one character of push-back is allowed. gzungetc() returns the character pushed, or -1 on failure. gzungetc() will fail if c is -1, and may fail if a character has been pushed but not read yet. If gzungetc is used immediately after gzopen or gzdopen, at least the output buffer size of pushed characters is allowed. (See gzbuffer above.) The pushed character will be discarded if the stream is repositioned with gzseek() or gzrewind(). */ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); /* Flushes all pending output into the compressed file. The parameter flush is as in the deflate() function. The return value is the zlib error number (see function gzerror below). gzflush is only permitted when writing. If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such concatented gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. */ /* ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence)); Sets the starting position for the next gzread or gzwrite on the given compressed file. The offset represents a number of bytes in the uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new starting position. gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); /* Rewinds the given file. This function is supported only for reading. gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) */ /* ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); Returns the starting position for the next gzread or gzwrite on the given compressed file. This position represents a number of bytes in the uncompressed data stream, and is zero when starting, even if appending or reading a gzip stream from the middle of a file using gzdopen(). gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ /* ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); Returns the current offset in the file being read or written. This offset includes the count of bytes that precede the gzip stream, for example when appending or when using gzdopen() for reading. When reading, the offset does not include as yet unused buffered input. This information can be used for a progress indicator. On error, gzoffset() returns -1. */ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); /* Returns true (1) if the end-of-file indicator has been set while reading, false (0) otherwise. Note that the end-of-file indicator is set only if the read tried to go past the end of the input, but came up short. Therefore, just like feof(), gzeof() may return false even if there is no more data to read, in the event that the last read request was for the exact number of bytes remaining in the input file. This will happen if the input file size is an exact multiple of the buffer size. If gzeof() returns true, then the read functions will return no more data, unless the end-of-file indicator is reset by gzclearerr() and the input file has grown since the previous end of file was detected. */ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); /* Returns true (1) if file is being copied directly while reading, or false (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. If gzdirect() is used immediately after gzopen() or gzdopen() it will cause buffers to be allocated to allow reading the file to determine if it is a gzip file. Therefore if gzbuffer() is used, it should be called before gzdirect(). When writing, gzdirect() returns true (1) if transparent writing was requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: gzdirect() is not needed when writing. Transparent writing must be explicitly requested, so the application already knows the answer. When linking statically, using gzdirect() will include all of the zlib code for gzip file reading and decompression, which may not be desired.) */ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); /* Flushes all pending output if necessary, closes the compressed file and deallocates the (de)compression state. Note that once file is closed, you cannot call gzerror with file, since its structures have been deallocated. gzclose must not be called more than once on the same file, just as free must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the last read ended in the middle of a gzip stream, or Z_OK on success. */ ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); /* Same as gzclose(), but gzclose_r() is only for use when reading, and gzclose_w() is only for use when writing or appending. The advantage to using these instead of gzclose() is that they avoid linking in zlib compression or decompression code that is not used when only reading or only writing respectively. If gzclose() is used, then both compression and decompression code will be included the application when linking to a static zlib library. */ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); /* Returns the error message for the last error which occurred on the given compressed file. errnum is set to zlib error number. If an error occurred in the file system and not in the compression library, errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. The application must not modify the returned string. Future calls to this function may invalidate the previously returned string. If file is closed, then the string previously returned by gzerror will no longer be available. gzerror() should be used to distinguish errors from end-of-file for those functions above that do not distinguish those cases in their return values. */ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); /* Clears the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip file that is being written concurrently. */ #endif /* !Z_SOLO */ /* checksum functions */ /* These functions are not related to compression but are exported anyway because they might be useful in applications using the compression library. */ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. If buf is Z_NULL, this function returns the required initial value for the checksum. An Adler-32 checksum is almost as reliable as a CRC32 but can be computed much faster. Usage example: uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); */ /* ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, z_off_t len2)); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note that the z_off_t type (like off_t) is a signed integer. If len2 is negative, the result has no meaning or utility. */ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. If buf is Z_NULL, this function returns the required initial value for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); */ /* ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and len2. */ /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, const char *version, int stream_size)); ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)); #define deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ (int)sizeof(z_stream)) #define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, (int)sizeof(z_stream)) #ifndef Z_SOLO /* gzgetc() macro and its supporting function and exposed data structure. Note * that the real internal state is much larger than the exposed structure. * This abbreviated structure exposes just enough for the gzgetc() macro. The * user should not mess with these exposed elements, since their names or * behavior could change in the future, perhaps even capriciously. They can * only be used by the gzgetc() macro. You have been warned. */ struct gzFile_s { unsigned have; unsigned char *next; z_off64_t pos; }; ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef z_gzgetc # define z_gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) #else # define gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) #endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if * both are true, the application gets the *64 functions, and the regular * functions are changed to 64 bits) -- in case these are set on systems * without large file support, _LFS64_LARGEFILE must also be true */ #ifdef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); #endif #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) # ifdef Z_PREFIX_SET # define z_gzopen z_gzopen64 # define z_gzseek z_gzseek64 # define z_gztell z_gztell64 # define z_gzoffset z_gzoffset64 # define z_adler32_combine z_adler32_combine64 # define z_crc32_combine z_crc32_combine64 # else # define gzopen gzopen64 # define gzseek gzseek64 # define gztell gztell64 # define gzoffset gzoffset64 # define adler32_combine adler32_combine64 # define crc32_combine crc32_combine64 # endif # ifndef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); # endif #else ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); #endif #else /* Z_SOLO */ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); #endif /* !Z_SOLO */ /* hack for buggy compilers */ #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) struct internal_state {int dummy;}; #endif /* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); #if defined(_WIN32) && !defined(Z_SOLO) ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, const char *mode)); #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, const char *format, va_list va)); # endif #endif #ifdef __cplusplus } #endif #endif /* ZLIB_H */ tcl8.6.5/compat/zlib/zconf.h.in0000644000175000017500000003622412663660065015716 0ustar sergeisergei/* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #ifndef ZCONF_H #define ZCONF_H /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * Even better than compiling with -DZ_PREFIX would be to use configure to set * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET /* all linked symbols */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align # define _tr_flush_bits z__tr_flush_bits # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block # define _tr_tally z__tr_tally # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 # ifndef Z_SOLO # define compress z_compress # define compress2 z_compress2 # define compressBound z_compressBound # endif # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams # define deflatePending z_deflatePending # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset # define deflateResetKeep z_deflateResetKeep # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table # ifndef Z_SOLO # define gz_error z_gz_error # define gz_intmax z_gz_intmax # define gz_strwinerror z_gz_strwinerror # define gzbuffer z_gzbuffer # define gzclearerr z_gzclearerr # define gzclose z_gzclose # define gzclose_r z_gzclose_r # define gzclose_w z_gzclose_w # define gzdirect z_gzdirect # define gzdopen z_gzdopen # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush # define gzgetc z_gzgetc # define gzgetc_ z_gzgetc_ # define gzgets z_gzgets # define gzoffset z_gzoffset # define gzoffset64 z_gzoffset64 # define gzopen z_gzopen # define gzopen64 z_gzopen64 # ifdef _WIN32 # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf # define gzvprintf z_gzvprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread # define gzrewind z_gzrewind # define gzseek z_gzseek # define gzseek64 z_gzseek64 # define gzsetparams z_gzsetparams # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc # define gzwrite z_gzwrite # endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd # define inflateBackInit_ z_inflateBackInit_ # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd # define inflateGetHeader z_inflateGetHeader # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 # define inflateSetDictionary z_inflateSetDictionary # define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine # define inflateResetKeep z_inflateResetKeep # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # ifndef Z_SOLO # define uncompress z_uncompress # endif # define zError z_zError # ifndef Z_SOLO # define zcalloc z_zcalloc # define zcfree z_zcfree # endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion /* all zlib typedefs in zlib.h and zconf.h */ # define Byte z_Byte # define Bytef z_Bytef # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func # ifndef Z_SOLO # define gzFile z_gzFile # endif # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func # define intf z_intf # define out_func z_out_func # define uInt z_uInt # define uIntf z_uIntf # define uLong z_uLong # define uLongf z_uLongf # define voidp z_voidp # define voidpc z_voidpc # define voidpf z_voidpf /* all zlib structs in zlib.h and zconf.h */ # define gz_header_s z_gz_header_s # define internal_state z_internal_state #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) # define OS2 #endif #if defined(_WINDOWS) && !defined(WINDOWS) # define WINDOWS #endif #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) # ifndef WIN32 # define WIN32 # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # ifndef SYS16BIT # define SYS16BIT # endif # endif #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #ifdef SYS16BIT # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #ifdef __STDC_VERSION__ # ifndef STDC # define STDC # endif # if __STDC_VERSION__ >= 199901L # ifndef STDC99 # define STDC99 # endif # endif #endif #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) # define STDC #endif #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) # define STDC #endif #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) # define STDC #endif #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) # define STDC #endif #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ # define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const /* note: need a more gentle solution here */ # endif #endif #if defined(ZLIB_CONST) && !defined(z_const) # define z_const const #else # define z_const #endif /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) # define NO_DUMMY_DECL #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus a few kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif #ifndef Z_ARG /* function prototypes for stdarg */ # if defined(STDC) || defined(Z_HAVE_STDARG_H) # define Z_ARG(args) args # else # define Z_ARG(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #ifdef SYS16BIT # if defined(M_I86SM) || defined(M_I86MM) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR _far # else # define FAR far # endif # endif # if (defined(__SMALL__) || defined(__MEDIUM__)) /* Turbo C small or medium model */ # define SMALL_MEDIUM # ifdef __BORLANDC__ # define FAR _far # else # define FAR far # endif # endif #endif #if defined(WINDOWS) || defined(WIN32) /* If building or using zlib as a DLL, define ZLIB_DLL. * This is not mandatory, but it offers a little performance increase. */ # ifdef ZLIB_DLL # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) # ifdef ZLIB_INTERNAL # define ZEXTERN extern __declspec(dllexport) # else # define ZEXTERN extern __declspec(dllimport) # endif # endif # endif /* ZLIB_DLL */ /* If building or using zlib with the WINAPI/WINAPIV calling convention, * define ZLIB_WINAPI. * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 # define ZEXPORTVA WINAPIV # else # define ZEXPORTVA FAR CDECL # endif # endif #endif #if defined (__BEOS__) # ifdef ZLIB_DLL # ifdef ZLIB_INTERNAL # define ZEXPORT __declspec(dllexport) # define ZEXPORTVA __declspec(dllexport) # else # define ZEXPORT __declspec(dllimport) # define ZEXPORTVA __declspec(dllimport) # endif # endif #endif #ifndef ZEXTERN # define ZEXTERN extern #endif #ifndef ZEXPORT # define ZEXPORT #endif #ifndef ZEXPORTVA # define ZEXPORTVA #endif #ifndef FAR # define FAR #endif #if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void const *voidpc; typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte const *voidpc; typedef Byte FAR *voidpf; typedef Byte *voidp; #endif #if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) # include # if (UINT_MAX == 0xffffffffUL) # define Z_U4 unsigned # elif (ULONG_MAX == 0xffffffffUL) # define Z_U4 unsigned long # elif (USHRT_MAX == 0xffffffffUL) # define Z_U4 unsigned short # endif #endif #ifdef Z_U4 typedef Z_U4 z_crc_t; #else typedef unsigned long z_crc_t; #endif #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif #ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_STDARG_H #endif #ifdef STDC # ifndef Z_SOLO # include /* for off_t */ # endif #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO # include /* for va_list */ # endif #endif #ifdef _WIN32 # ifndef Z_SOLO # include /* for wchar_t */ # endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even * though the former does not conform to the LFS document), but considering * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ #if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif #if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) # define Z_HAVE_UNISTD_H #endif #ifndef Z_SOLO # if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ # endif # ifndef z_off_t # define z_off_t off_t # endif # endif #endif #if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 # define Z_LFS64 #endif #if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) # define Z_LARGE64 #endif #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) # define Z_WANT64 #endif #if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t # define z_off_t long #endif #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else # if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) # define z_off64_t __int64 # else # define z_off64_t z_off_t # endif #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) #pragma map(deflateInit_,"DEIN") #pragma map(deflateInit2_,"DEIN2") #pragma map(deflateEnd,"DEEND") #pragma map(deflateBound,"DEBND") #pragma map(inflateInit_,"ININ") #pragma map(inflateInit2_,"ININ2") #pragma map(inflateEnd,"INEND") #pragma map(inflateSync,"INSY") #pragma map(inflateSetDictionary,"INSEDI") #pragma map(compressBound,"CMBND") #pragma map(inflate_table,"INTABL") #pragma map(inflate_fast,"INFA") #pragma map(inflate_copyright,"INCOPY") #endif #endif /* ZCONF_H */ tcl8.6.5/compat/zlib/gzread.c0000644000175000017500000004440612663660065015442 0ustar sergeisergei/* gzread.c -- zlib functions for reading gzip files * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" /* Local functions */ local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); local int gz_avail OF((gz_statep)); local int gz_look OF((gz_statep)); local int gz_decomp OF((gz_statep)); local int gz_fetch OF((gz_statep)); local int gz_skip OF((gz_statep, z_off64_t)); /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from state->fd, and update state->eof, state->err, and state->msg as appropriate. This function needs to loop on read(), since read() is not guaranteed to read the number of bytes requested, depending on the type of descriptor. */ local int gz_load(state, buf, len, have) gz_statep state; unsigned char *buf; unsigned len; unsigned *have; { int ret; *have = 0; do { ret = read(state->fd, buf + *have, len - *have); if (ret <= 0) break; *have += ret; } while (*have < len); if (ret < 0) { gz_error(state, Z_ERRNO, zstrerror()); return -1; } if (ret == 0) state->eof = 1; return 0; } /* Load up input buffer and set eof flag if last data loaded -- return -1 on error, 0 otherwise. Note that the eof flag is set when the end of the input file is reached, even though there may be unused data in the buffer. Once that data has been used, no more attempts will be made to read the file. If strm->avail_in != 0, then the current data is moved to the beginning of the input buffer, and then the remainder of the buffer is loaded with the available data from the input file. */ local int gz_avail(state) gz_statep state; { unsigned got; z_streamp strm = &(state->strm); if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; if (state->eof == 0) { if (strm->avail_in) { /* copy what's there to the start */ unsigned char *p = state->in; unsigned const char *q = strm->next_in; unsigned n = strm->avail_in; do { *p++ = *q++; } while (--n); } if (gz_load(state, state->in + strm->avail_in, state->size - strm->avail_in, &got) == -1) return -1; strm->avail_in += got; strm->next_in = state->in; } return 0; } /* Look for gzip header, set up for inflate or copy. state->x.have must be 0. If this is the first time in, allocate required memory. state->how will be left unchanged if there is no more input data available, will be set to COPY if there is no gzip header and direct copying will be performed, or it will be set to GZIP for decompression. If direct copying, then leftover input data from the input buffer will be copied to the output buffer. In that case, all further file reads will be directly to either the output buffer or a user buffer. If decompressing, the inflate state will be initialized. gz_look() will return 0 on success or -1 on failure. */ local int gz_look(state) gz_statep state; { z_streamp strm = &(state->strm); /* allocate read buffers and inflate memory */ if (state->size == 0) { /* allocate buffers */ state->in = (unsigned char *)malloc(state->want); state->out = (unsigned char *)malloc(state->want << 1); if (state->in == NULL || state->out == NULL) { if (state->out != NULL) free(state->out); if (state->in != NULL) free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } state->size = state->want; /* allocate inflate memory */ state->strm.zalloc = Z_NULL; state->strm.zfree = Z_NULL; state->strm.opaque = Z_NULL; state->strm.avail_in = 0; state->strm.next_in = Z_NULL; if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ free(state->out); free(state->in); state->size = 0; gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } } /* get at least the magic bytes in the input buffer */ if (strm->avail_in < 2) { if (gz_avail(state) == -1) return -1; if (strm->avail_in == 0) return 0; } /* look for gzip magic bytes -- if there, do gzip decoding (note: there is a logical dilemma here when considering the case of a partially written gzip file, to wit, if a single 31 byte is written, then we cannot tell whether this is a single-byte file, or just a partially written gzip file -- for here we assume that if a gzip file is being written, then the header will be written in a single operation, so that reading a single byte is sufficient indication that it is not a gzip file) */ if (strm->avail_in > 1 && strm->next_in[0] == 31 && strm->next_in[1] == 139) { inflateReset(strm); state->how = GZIP; state->direct = 0; return 0; } /* no gzip header -- if we were decoding gzip before, then this is trailing garbage. Ignore the trailing garbage and finish. */ if (state->direct == 0) { strm->avail_in = 0; state->eof = 1; state->x.have = 0; return 0; } /* doing raw i/o, copy any leftover input to output -- this assumes that the output buffer is larger than the input buffer, which also assures space for gzungetc() */ state->x.next = state->out; if (strm->avail_in) { memcpy(state->x.next, strm->next_in, strm->avail_in); state->x.have = strm->avail_in; strm->avail_in = 0; } state->how = COPY; state->direct = 1; return 0; } /* Decompress from input to the provided next_out and avail_out in the state. On return, state->x.have and state->x.next point to the just decompressed data. If the gzip stream completes, state->how is reset to LOOK to look for the next gzip stream or raw data, once state->x.have is depleted. Returns 0 on success, -1 on failure. */ local int gz_decomp(state) gz_statep state; { int ret = Z_OK; unsigned had; z_streamp strm = &(state->strm); /* fill output buffer up to end of deflate stream */ had = strm->avail_out; do { /* get more input for inflate() */ if (strm->avail_in == 0 && gz_avail(state) == -1) return -1; if (strm->avail_in == 0) { gz_error(state, Z_BUF_ERROR, "unexpected end of file"); break; } /* decompress and handle errors */ ret = inflate(strm, Z_NO_FLUSH); if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { gz_error(state, Z_STREAM_ERROR, "internal error: inflate stream corrupt"); return -1; } if (ret == Z_MEM_ERROR) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ gz_error(state, Z_DATA_ERROR, strm->msg == NULL ? "compressed data error" : strm->msg); return -1; } } while (strm->avail_out && ret != Z_STREAM_END); /* update available output */ state->x.have = had - strm->avail_out; state->x.next = strm->next_out - state->x.have; /* if the gzip stream completed successfully, look for another */ if (ret == Z_STREAM_END) state->how = LOOK; /* good decompression */ return 0; } /* Fetch data and put it in the output buffer. Assumes state->x.have is 0. Data is either copied from the input file or decompressed from the input file depending on state->how. If state->how is LOOK, then a gzip header is looked for to determine whether to copy or decompress. Returns -1 on error, otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the end of the input file has been reached and all data has been processed. */ local int gz_fetch(state) gz_statep state; { z_streamp strm = &(state->strm); do { switch(state->how) { case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ if (gz_look(state) == -1) return -1; if (state->how == LOOK) return 0; break; case COPY: /* -> COPY */ if (gz_load(state, state->out, state->size << 1, &(state->x.have)) == -1) return -1; state->x.next = state->out; return 0; case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ strm->avail_out = state->size << 1; strm->next_out = state->out; if (gz_decomp(state) == -1) return -1; } } while (state->x.have == 0 && (!state->eof || strm->avail_in)); return 0; } /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ local int gz_skip(state, len) gz_statep state; z_off64_t len; { unsigned n; /* skip over len bytes or reach end-of-file, whichever comes first */ while (len) /* skip over whatever is in output buffer */ if (state->x.have) { n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? (unsigned)len : state->x.have; state->x.have -= n; state->x.next += n; state->x.pos += n; len -= n; } /* output buffer empty -- return if we're at the end of the input */ else if (state->eof && state->strm.avail_in == 0) break; /* need more data to skip -- load up output buffer */ else { /* get more output, looking for header if required */ if (gz_fetch(state) == -1) return -1; } return 0; } /* -- see zlib.h -- */ int ZEXPORT gzread(file, buf, len) gzFile file; voidp buf; unsigned len; { unsigned got, n; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids the flaw in the interface) */ if ((int)len < 0) { gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); return -1; } /* if len is zero, avoid unnecessary operations */ if (len == 0) return 0; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return -1; } /* get len bytes to buf, or less than len if at the end */ got = 0; do { /* first just try copying data from the output buffer */ if (state->x.have) { n = state->x.have > len ? len : state->x.have; memcpy(buf, state->x.next, n); state->x.next += n; state->x.have -= n; } /* output buffer empty -- return if we're at the end of the input */ else if (state->eof && strm->avail_in == 0) { state->past = 1; /* tried to read past end */ break; } /* need output data -- for small len or new stream load up our output buffer */ else if (state->how == LOOK || len < (state->size << 1)) { /* get more output, looking for header if required */ if (gz_fetch(state) == -1) return -1; continue; /* no progress yet -- go back to copy above */ /* the copy above assures that we will leave with space in the output buffer, allowing at least one gzungetc() to succeed */ } /* large len -- read directly into user buffer */ else if (state->how == COPY) { /* read directly */ if (gz_load(state, (unsigned char *)buf, len, &n) == -1) return -1; } /* large len -- decompress directly into user buffer */ else { /* state->how == GZIP */ strm->avail_out = len; strm->next_out = (unsigned char *)buf; if (gz_decomp(state) == -1) return -1; n = state->x.have; state->x.have = 0; } /* update progress */ len -= n; buf = (char *)buf + n; got += n; state->x.pos += n; } while (len); /* return number of bytes read into user buffer (will fit in int) */ return (int)got; } /* -- see zlib.h -- */ #ifdef Z_PREFIX_SET # undef z_gzgetc #else # undef gzgetc #endif int ZEXPORT gzgetc(file) gzFile file; { int ret; unsigned char buf[1]; gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* try output buffer (no need to check for skip request) */ if (state->x.have) { state->x.have--; state->x.pos++; return *(state->x.next)++; } /* nothing there -- try gzread() */ ret = gzread(file, buf, 1); return ret < 1 ? -1 : buf[0]; } int ZEXPORT gzgetc_(file) gzFile file; { return gzgetc(file); } /* -- see zlib.h -- */ int ZEXPORT gzungetc(c, file) int c; gzFile file; { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return -1; } /* can't push EOF */ if (c < 0) return -1; /* if output buffer empty, put byte at end (allows more pushing) */ if (state->x.have == 0) { state->x.have = 1; state->x.next = state->out + (state->size << 1) - 1; state->x.next[0] = c; state->x.pos--; state->past = 0; return c; } /* if no room, give up (must have already done a gzungetc()) */ if (state->x.have == (state->size << 1)) { gz_error(state, Z_DATA_ERROR, "out of room to push characters"); return -1; } /* slide output data if needed and insert byte before existing data */ if (state->x.next == state->out) { unsigned char *src = state->out + state->x.have; unsigned char *dest = state->out + (state->size << 1); while (src > state->out) *--dest = *--src; state->x.next = dest; } state->x.have++; state->x.next--; state->x.next[0] = c; state->x.pos--; state->past = 0; return c; } /* -- see zlib.h -- */ char * ZEXPORT gzgets(file, buf, len) gzFile file; char *buf; int len; { unsigned left, n; char *str; unsigned char *eol; gz_statep state; /* check parameters and get internal structure */ if (file == NULL || buf == NULL || len < 1) return NULL; state = (gz_statep)file; /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return NULL; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return NULL; } /* copy output bytes up to new line or len - 1, whichever comes first -- append a terminating zero to the string (we don't check for a zero in the contents, let the user worry about that) */ str = buf; left = (unsigned)len - 1; if (left) do { /* assure that something is in the output buffer */ if (state->x.have == 0 && gz_fetch(state) == -1) return NULL; /* error */ if (state->x.have == 0) { /* end of file */ state->past = 1; /* read past end */ break; /* return what we have */ } /* look for end-of-line in current output buffer */ n = state->x.have > left ? left : state->x.have; eol = (unsigned char *)memchr(state->x.next, '\n', n); if (eol != NULL) n = (unsigned)(eol - state->x.next) + 1; /* copy through end-of-line, or remainder if not found */ memcpy(buf, state->x.next, n); state->x.have -= n; state->x.next += n; state->x.pos += n; left -= n; buf += n; } while (left && eol == NULL); /* return terminated string, or if nothing, end of file */ if (buf == str) return NULL; buf[0] = 0; return str; } /* -- see zlib.h -- */ int ZEXPORT gzdirect(file) gzFile file; { gz_statep state; /* get internal structure */ if (file == NULL) return 0; state = (gz_statep)file; /* if the state is not known, but we can find out, then do so (this is mainly for right after a gzopen() or gzdopen()) */ if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) (void)gz_look(state); /* return 1 if transparent, 0 if processing a gzip stream */ return state->direct; } /* -- see zlib.h -- */ int ZEXPORT gzclose_r(file) gzFile file; { int ret, err; gz_statep state; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're reading */ if (state->mode != GZ_READ) return Z_STREAM_ERROR; /* free memory and close file */ if (state->size) { inflateEnd(&(state->strm)); free(state->out); free(state->in); } err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; gz_error(state, Z_OK, NULL); free(state->path); ret = close(state->fd); free(state); return ret ? Z_ERRNO : err; } tcl8.6.5/compat/zlib/contrib/0000755000175000017500000000000012665173607015455 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/README.contrib0000644000175000017500000000615712663660064020001 0ustar sergeisergeiAll files under this contrib directory are UNSUPPORTED. There were provided by users of zlib and were not tested by the authors of zlib. Use at your own risk. Please contact the authors of the contributions for help about these, not the zlib authors. Thanks. ada/ by Dmitriy Anisimkov Support for Ada See http://zlib-ada.sourceforge.net/ amd64/ by Mikhail Teterin asm code for AMD64 See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393 asm686/ by Brian Raiter asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax See http://www.muppetlabs.com/~breadbox/software/assembly.html blast/ by Mark Adler Decompressor for output of PKWare Data Compression Library (DCL) delphi/ by Cosmin Truta Support for Delphi and C++ Builder dotzlib/ by Henrik Ravn Support for Microsoft .Net and Visual C++ .Net gcc_gvmat64/by Gilles Vollant GCC Version of x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to replace longest_match() and inflate_fast() infback9/ by Mark Adler Unsupported diffs to infback to decode the deflate64 format inflate86/ by Chris Anderson Tuned x86 gcc asm code to replace inflate_fast() iostream/ by Kevin Ruland A C++ I/O streams interface to the zlib gz* functions iostream2/ by Tyge Løvset Another C++ I/O streams interface iostream3/ by Ludwig Schwardt and Kevin Ruland Yet another C++ I/O streams interface masmx64/ by Gilles Vollant x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to replace longest_match() and inflate_fast(), also masm x86 64-bits translation of Chris Anderson inflate_fast() masmx86/ by Gilles Vollant x86 asm code to replace longest_match() and inflate_fast(), for Visual C++ and MASM (32 bits). Based on Brian Raiter (asm686) and Chris Anderson (inflate86) minizip/ by Gilles Vollant Mini zip and unzip based on zlib Includes Zip64 support by Mathias Svensson See http://www.winimage.com/zLibDll/unzip.html pascal/ by Bob Dellaca et al. Support for Pascal puff/ by Mark Adler Small, low memory usage inflate. Also serves to provide an unambiguous description of the deflate format. testzlib/ by Gilles Vollant Example of the use of zlib untgz/ by Pedro A. Aranda Gutierrez A very simple tar.gz file extractor using zlib vstudio/ by Gilles Vollant Building a minizip-enhanced zlib with Microsoft Visual Studio Includes vc11 from kreuzerkrieg and vc12 from davispuh tcl8.6.5/compat/zlib/contrib/gcc_gvmat64/0000755000175000017500000000000012665173607017561 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/gcc_gvmat64/gvmat64.S0000644000175000017500000004003512663653206021173 0ustar sergeisergei/* ;uInt longest_match_x64( ; deflate_state *s, ; IPos cur_match); // current match ; gvmat64.S -- Asm portion of the optimized longest_match for 32 bits x86_64 ; (AMD64 on Athlon 64, Opteron, Phenom ; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) ; this file is translation from gvmat64.asm to GCC 4.x (for Linux, Mac XCode) ; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. ; ; File written by Gilles Vollant, by converting to assembly the longest_match ; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. ; and by taking inspiration on asm686 with masm, optimised assembly code ; from Brian Raiter, written 1998 ; ; This software is provided 'as-is', without any express or implied ; warranty. In no event will the authors be held liable for any damages ; arising from the use of this software. ; ; Permission is granted to anyone to use this software for any purpose, ; including commercial applications, and to alter it and redistribute it ; freely, subject to the following restrictions: ; ; 1. The origin of this software must not be misrepresented; you must not ; claim that you wrote the original software. If you use this software ; in a product, an acknowledgment in the product documentation would be ; appreciated but is not required. ; 2. Altered source versions must be plainly marked as such, and must not be ; misrepresented as being the original software ; 3. This notice may not be removed or altered from any source distribution. ; ; http://www.zlib.net ; http://www.winimage.com/zLibDll ; http://www.muppetlabs.com/~breadbox/software/assembly.html ; ; to compile this file for zLib, I use option: ; gcc -c -arch x86_64 gvmat64.S ;uInt longest_match(s, cur_match) ; deflate_state *s; ; IPos cur_match; // current match / ; ; with XCode for Mac, I had strange error with some jump on intel syntax ; this is why BEFORE_JMP and AFTER_JMP are used */ #define BEFORE_JMP .att_syntax #define AFTER_JMP .intel_syntax noprefix #ifndef NO_UNDERLINE # define match_init _match_init # define longest_match _longest_match #endif .intel_syntax noprefix .globl match_init, longest_match .text longest_match: #define LocalVarsSize 96 /* ; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 ; free register : r14,r15 ; register can be saved : rsp */ #define chainlenwmask (rsp + 8 - LocalVarsSize) #define nicematch (rsp + 16 - LocalVarsSize) #define save_rdi (rsp + 24 - LocalVarsSize) #define save_rsi (rsp + 32 - LocalVarsSize) #define save_rbx (rsp + 40 - LocalVarsSize) #define save_rbp (rsp + 48 - LocalVarsSize) #define save_r12 (rsp + 56 - LocalVarsSize) #define save_r13 (rsp + 64 - LocalVarsSize) #define save_r14 (rsp + 72 - LocalVarsSize) #define save_r15 (rsp + 80 - LocalVarsSize) /* ; all the +4 offsets are due to the addition of pending_buf_size (in zlib ; in the deflate_state structure since the asm code was first written ; (if you compile with zlib 1.0.4 or older, remove the +4). ; Note : these value are good with a 8 bytes boundary pack structure */ #define MAX_MATCH 258 #define MIN_MATCH 3 #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* ;;; Offsets for fields in the deflate_state structure. These numbers ;;; are calculated from the definition of deflate_state, with the ;;; assumption that the compiler will dword-align the fields. (Thus, ;;; changing the definition of deflate_state could easily cause this ;;; program to crash horribly, without so much as a warning at ;;; compile time. Sigh.) ; all the +zlib1222add offsets are due to the addition of fields ; in zlib in the deflate_state structure since the asm code was first written ; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). ; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). ; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). */ /* you can check the structure offset by running #include #include #include "deflate.h" void print_depl() { deflate_state ds; deflate_state *s=&ds; printf("size pointer=%u\n",(int)sizeof(void*)); printf("#define dsWSize %u\n",(int)(((char*)&(s->w_size))-((char*)s))); printf("#define dsWMask %u\n",(int)(((char*)&(s->w_mask))-((char*)s))); printf("#define dsWindow %u\n",(int)(((char*)&(s->window))-((char*)s))); printf("#define dsPrev %u\n",(int)(((char*)&(s->prev))-((char*)s))); printf("#define dsMatchLen %u\n",(int)(((char*)&(s->match_length))-((char*)s))); printf("#define dsPrevMatch %u\n",(int)(((char*)&(s->prev_match))-((char*)s))); printf("#define dsStrStart %u\n",(int)(((char*)&(s->strstart))-((char*)s))); printf("#define dsMatchStart %u\n",(int)(((char*)&(s->match_start))-((char*)s))); printf("#define dsLookahead %u\n",(int)(((char*)&(s->lookahead))-((char*)s))); printf("#define dsPrevLen %u\n",(int)(((char*)&(s->prev_length))-((char*)s))); printf("#define dsMaxChainLen %u\n",(int)(((char*)&(s->max_chain_length))-((char*)s))); printf("#define dsGoodMatch %u\n",(int)(((char*)&(s->good_match))-((char*)s))); printf("#define dsNiceMatch %u\n",(int)(((char*)&(s->nice_match))-((char*)s))); } */ #define dsWSize 68 #define dsWMask 76 #define dsWindow 80 #define dsPrev 96 #define dsMatchLen 144 #define dsPrevMatch 148 #define dsStrStart 156 #define dsMatchStart 160 #define dsLookahead 164 #define dsPrevLen 168 #define dsMaxChainLen 172 #define dsGoodMatch 188 #define dsNiceMatch 192 #define window_size [ rcx + dsWSize] #define WMask [ rcx + dsWMask] #define window_ad [ rcx + dsWindow] #define prev_ad [ rcx + dsPrev] #define strstart [ rcx + dsStrStart] #define match_start [ rcx + dsMatchStart] #define Lookahead [ rcx + dsLookahead] //; 0ffffffffh on infozip #define prev_length [ rcx + dsPrevLen] #define max_chain_length [ rcx + dsMaxChainLen] #define good_match [ rcx + dsGoodMatch] #define nice_match [ rcx + dsNiceMatch] /* ; windows: ; parameter 1 in rcx(deflate state s), param 2 in rdx (cur match) ; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and ; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp ; ; All registers must be preserved across the call, except for ; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. ; ; gcc on macosx-linux: ; see http://www.x86-64.org/documentation/abi-0.99.pdf ; param 1 in rdi, param 2 in rsi ; rbx, rsp, rbp, r12 to r15 must be preserved ;;; Save registers that the compiler may be using, and adjust esp to ;;; make room for our stack frame. ;;; Retrieve the function arguments. r8d will hold cur_match ;;; throughout the entire function. edx will hold the pointer to the ;;; deflate_state structure during the function's setup (before ;;; entering the main loop. ; ms: parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) ; mac: param 1 in rdi, param 2 rsi ; this clear high 32 bits of r8, which can be garbage in both r8 and rdx */ mov [save_rbx],rbx mov [save_rbp],rbp mov rcx,rdi mov r8d,esi mov [save_r12],r12 mov [save_r13],r13 mov [save_r14],r14 mov [save_r15],r15 //;;; uInt wmask = s->w_mask; //;;; unsigned chain_length = s->max_chain_length; //;;; if (s->prev_length >= s->good_match) { //;;; chain_length >>= 2; //;;; } mov edi, prev_length mov esi, good_match mov eax, WMask mov ebx, max_chain_length cmp edi, esi jl LastMatchGood shr ebx, 2 LastMatchGood: //;;; chainlen is decremented once beforehand so that the function can //;;; use the sign flag instead of the zero flag for the exit test. //;;; It is then shifted into the high word, to make room for the wmask //;;; value, which it will always accompany. dec ebx shl ebx, 16 or ebx, eax //;;; on zlib only //;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; mov eax, nice_match mov [chainlenwmask], ebx mov r10d, Lookahead cmp r10d, eax cmovnl r10d, eax mov [nicematch],r10d //;;; register Bytef *scan = s->window + s->strstart; mov r10, window_ad mov ebp, strstart lea r13, [r10 + rbp] //;;; Determine how many bytes the scan ptr is off from being //;;; dword-aligned. mov r9,r13 neg r13 and r13,3 //;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? //;;; s->strstart - (IPos)MAX_DIST(s) : NIL; mov eax, window_size sub eax, MIN_LOOKAHEAD xor edi,edi sub ebp, eax mov r11d, prev_length cmovng ebp,edi //;;; int best_len = s->prev_length; //;;; Store the sum of s->window + best_len in esi locally, and in esi. lea rsi,[r10+r11] //;;; register ush scan_start = *(ushf*)scan; //;;; register ush scan_end = *(ushf*)(scan+best_len-1); //;;; Posf *prev = s->prev; movzx r12d,word ptr [r9] movzx ebx, word ptr [r9 + r11 - 1] mov rdi, prev_ad //;;; Jump into the main loop. mov edx, [chainlenwmask] cmp bx,word ptr [rsi + r8 - 1] jz LookupLoopIsZero LookupLoop1: and r8d, edx movzx r8d, word ptr [rdi + r8*2] cmp r8d, ebp jbe LeaveNow sub edx, 0x00010000 BEFORE_JMP js LeaveNow AFTER_JMP LoopEntry1: cmp bx,word ptr [rsi + r8 - 1] BEFORE_JMP jz LookupLoopIsZero AFTER_JMP LookupLoop2: and r8d, edx movzx r8d, word ptr [rdi + r8*2] cmp r8d, ebp BEFORE_JMP jbe LeaveNow AFTER_JMP sub edx, 0x00010000 BEFORE_JMP js LeaveNow AFTER_JMP LoopEntry2: cmp bx,word ptr [rsi + r8 - 1] BEFORE_JMP jz LookupLoopIsZero AFTER_JMP LookupLoop4: and r8d, edx movzx r8d, word ptr [rdi + r8*2] cmp r8d, ebp BEFORE_JMP jbe LeaveNow AFTER_JMP sub edx, 0x00010000 BEFORE_JMP js LeaveNow AFTER_JMP LoopEntry4: cmp bx,word ptr [rsi + r8 - 1] BEFORE_JMP jnz LookupLoop1 jmp LookupLoopIsZero AFTER_JMP /* ;;; do { ;;; match = s->window + cur_match; ;;; if (*(ushf*)(match+best_len-1) != scan_end || ;;; *(ushf*)match != scan_start) continue; ;;; [...] ;;; } while ((cur_match = prev[cur_match & wmask]) > limit ;;; && --chain_length != 0); ;;; ;;; Here is the inner loop of the function. The function will spend the ;;; majority of its time in this loop, and majority of that time will ;;; be spent in the first ten instructions. ;;; ;;; Within this loop: ;;; ebx = scanend ;;; r8d = curmatch ;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) ;;; esi = windowbestlen - i.e., (window + bestlen) ;;; edi = prev ;;; ebp = limit */ .balign 16 LookupLoop: and r8d, edx movzx r8d, word ptr [rdi + r8*2] cmp r8d, ebp BEFORE_JMP jbe LeaveNow AFTER_JMP sub edx, 0x00010000 BEFORE_JMP js LeaveNow AFTER_JMP LoopEntry: cmp bx,word ptr [rsi + r8 - 1] BEFORE_JMP jnz LookupLoop1 AFTER_JMP LookupLoopIsZero: cmp r12w, word ptr [r10 + r8] BEFORE_JMP jnz LookupLoop1 AFTER_JMP //;;; Store the current value of chainlen. mov [chainlenwmask], edx /* ;;; Point edi to the string under scrutiny, and esi to the string we ;;; are hoping to match it up with. In actuality, esi and edi are ;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is ;;; initialized to -(MAX_MATCH_8 - scanalign). */ lea rsi,[r8+r10] mov rdx, 0xfffffffffffffef8 //; -(MAX_MATCH_8) lea rsi, [rsi + r13 + 0x0108] //;MAX_MATCH_8] lea rdi, [r9 + r13 + 0x0108] //;MAX_MATCH_8] prefetcht1 [rsi+rdx] prefetcht1 [rdi+rdx] /* ;;; Test the strings for equality, 8 bytes at a time. At the end, ;;; adjust rdx so that it is offset to the exact byte that mismatched. ;;; ;;; We already know at this point that the first three bytes of the ;;; strings match each other, and they can be safely passed over before ;;; starting the compare loop. So what this code does is skip over 0-3 ;;; bytes, as much as necessary in order to dword-align the edi ;;; pointer. (rsi will still be misaligned three times out of four.) ;;; ;;; It should be confessed that this loop usually does not represent ;;; much of the total running time. Replacing it with a more ;;; straightforward "rep cmpsb" would not drastically degrade ;;; performance. */ LoopCmps: mov rax, [rsi + rdx] xor rax, [rdi + rdx] jnz LeaveLoopCmps mov rax, [rsi + rdx + 8] xor rax, [rdi + rdx + 8] jnz LeaveLoopCmps8 mov rax, [rsi + rdx + 8+8] xor rax, [rdi + rdx + 8+8] jnz LeaveLoopCmps16 add rdx,8+8+8 BEFORE_JMP jnz LoopCmps jmp LenMaximum AFTER_JMP LeaveLoopCmps16: add rdx,8 LeaveLoopCmps8: add rdx,8 LeaveLoopCmps: test eax, 0x0000FFFF jnz LenLower test eax,0xffffffff jnz LenLower32 add rdx,4 shr rax,32 or ax,ax BEFORE_JMP jnz LenLower AFTER_JMP LenLower32: shr eax,16 add rdx,2 LenLower: sub al, 1 adc rdx, 0 //;;; Calculate the length of the match. If it is longer than MAX_MATCH, //;;; then automatically accept it as the best possible match and leave. lea rax, [rdi + rdx] sub rax, r9 cmp eax, MAX_MATCH BEFORE_JMP jge LenMaximum AFTER_JMP /* ;;; If the length of the match is not longer than the best match we ;;; have so far, then forget it and return to the lookup loop. ;/////////////////////////////////// */ cmp eax, r11d jg LongerMatch lea rsi,[r10+r11] mov rdi, prev_ad mov edx, [chainlenwmask] BEFORE_JMP jmp LookupLoop AFTER_JMP /* ;;; s->match_start = cur_match; ;;; best_len = len; ;;; if (len >= nice_match) break; ;;; scan_end = *(ushf*)(scan+best_len-1); */ LongerMatch: mov r11d, eax mov match_start, r8d cmp eax, [nicematch] BEFORE_JMP jge LeaveNow AFTER_JMP lea rsi,[r10+rax] movzx ebx, word ptr [r9 + rax - 1] mov rdi, prev_ad mov edx, [chainlenwmask] BEFORE_JMP jmp LookupLoop AFTER_JMP //;;; Accept the current string, with the maximum possible length. LenMaximum: mov r11d,MAX_MATCH mov match_start, r8d //;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; //;;; return s->lookahead; LeaveNow: mov eax, Lookahead cmp r11d, eax cmovng eax, r11d //;;; Restore the stack and return from whence we came. // mov rsi,[save_rsi] // mov rdi,[save_rdi] mov rbx,[save_rbx] mov rbp,[save_rbp] mov r12,[save_r12] mov r13,[save_r13] mov r14,[save_r14] mov r15,[save_r15] ret 0 //; please don't remove this string ! //; Your can freely use gvmat64 in any free or commercial app //; but it is far better don't remove the string in the binary! // db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 match_init: ret 0 tcl8.6.5/compat/zlib/contrib/delphi/0000755000175000017500000000000012665173607016722 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/delphi/zlibd32.mak0000644000175000017500000000447012663660064020666 0ustar sergeisergei# Makefile for zlib # For use with Delphi and C++ Builder under Win32 # Updated for zlib 1.2.x by Cosmin Truta # ------------ Borland C++ ------------ # This project uses the Delphi (fastcall/register) calling convention: LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl CC = bcc32 LD = bcc32 AR = tlib # do not use "-pr" in CFLAGS CFLAGS = -a -d -k- -O2 $(LOC) LDFLAGS = # variables ZLIB_LIB = zlib.lib OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj # targets all: $(ZLIB_LIB) example.exe minigzip.exe .c.obj: $(CC) -c $(CFLAGS) $*.c adler32.obj: adler32.c zlib.h zconf.h compress.obj: compress.c zlib.h zconf.h crc32.obj: crc32.c zlib.h zconf.h crc32.h deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h gzread.obj: gzread.c zlib.h zconf.h gzguts.h gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h uncompr.obj: uncompr.c zlib.h zconf.h zutil.obj: zutil.c zutil.h zlib.h zconf.h example.obj: test/example.c zlib.h zconf.h minigzip.obj: test/minigzip.c zlib.h zconf.h # For the sake of the old Borland make, # the command line is cut to fit in the MS-DOS 128 byte limit: $(ZLIB_LIB): $(OBJ1) $(OBJ2) -del $(ZLIB_LIB) $(AR) $(ZLIB_LIB) $(OBJP1) $(AR) $(ZLIB_LIB) $(OBJP2) # testing test: example.exe minigzip.exe example echo hello world | minigzip | minigzip -d example.exe: example.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) minigzip.exe: minigzip.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) # cleanup clean: -del *.obj -del *.exe -del *.lib -del *.tds -del zlib.bak -del foo.gz tcl8.6.5/compat/zlib/contrib/delphi/ZLib.pas0000644000175000017500000004003412663660064020264 0ustar sergeisergei{*******************************************************} { } { Borland Delphi Supplemental Components } { ZLIB Data Compression Interface Unit } { } { Copyright (c) 1997,99 Borland Corporation } { } {*******************************************************} { Updated for zlib 1.2.x by Cosmin Truta } unit ZLib; interface uses SysUtils, Classes; type TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl; TFree = procedure (AppData, Block: Pointer); cdecl; // Internal structure. Ignore. TZStreamRec = packed record next_in: PChar; // next input byte avail_in: Integer; // number of bytes available at next_in total_in: Longint; // total nb of input bytes read so far next_out: PChar; // next output byte should be put here avail_out: Integer; // remaining free space at next_out total_out: Longint; // total nb of bytes output so far msg: PChar; // last error message, NULL if no error internal: Pointer; // not visible by applications zalloc: TAlloc; // used to allocate the internal state zfree: TFree; // used to free the internal state AppData: Pointer; // private data object passed to zalloc and zfree data_type: Integer; // best guess about the data type: ascii or binary adler: Longint; // adler32 value of the uncompressed data reserved: Longint; // reserved for future use end; // Abstract ancestor class TCustomZlibStream = class(TStream) private FStrm: TStream; FStrmPos: Integer; FOnProgress: TNotifyEvent; FZRec: TZStreamRec; FBuffer: array [Word] of Char; protected procedure Progress(Sender: TObject); dynamic; property OnProgress: TNotifyEvent read FOnProgress write FOnProgress; constructor Create(Strm: TStream); end; { TCompressionStream compresses data on the fly as data is written to it, and stores the compressed data to another stream. TCompressionStream is write-only and strictly sequential. Reading from the stream will raise an exception. Using Seek to move the stream pointer will raise an exception. Output data is cached internally, written to the output stream only when the internal output buffer is full. All pending output data is flushed when the stream is destroyed. The Position property returns the number of uncompressed bytes of data that have been written to the stream so far. CompressionRate returns the on-the-fly percentage by which the original data has been compressed: (1 - (CompressedBytes / UncompressedBytes)) * 100 If raw data size = 100 and compressed data size = 25, the CompressionRate is 75% The OnProgress event is called each time the output buffer is filled and written to the output stream. This is useful for updating a progress indicator when you are writing a large chunk of data to the compression stream in a single call.} TCompressionLevel = (clNone, clFastest, clDefault, clMax); TCompressionStream = class(TCustomZlibStream) private function GetCompressionRate: Single; public constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream); destructor Destroy; override; function Read(var Buffer; Count: Longint): Longint; override; function Write(const Buffer; Count: Longint): Longint; override; function Seek(Offset: Longint; Origin: Word): Longint; override; property CompressionRate: Single read GetCompressionRate; property OnProgress; end; { TDecompressionStream decompresses data on the fly as data is read from it. Compressed data comes from a separate source stream. TDecompressionStream is read-only and unidirectional; you can seek forward in the stream, but not backwards. The special case of setting the stream position to zero is allowed. Seeking forward decompresses data until the requested position in the uncompressed data has been reached. Seeking backwards, seeking relative to the end of the stream, requesting the size of the stream, and writing to the stream will raise an exception. The Position property returns the number of bytes of uncompressed data that have been read from the stream so far. The OnProgress event is called each time the internal input buffer of compressed data is exhausted and the next block is read from the input stream. This is useful for updating a progress indicator when you are reading a large chunk of data from the decompression stream in a single call.} TDecompressionStream = class(TCustomZlibStream) public constructor Create(Source: TStream); destructor Destroy; override; function Read(var Buffer; Count: Longint): Longint; override; function Write(const Buffer; Count: Longint): Longint; override; function Seek(Offset: Longint; Origin: Word): Longint; override; property OnProgress; end; { CompressBuf compresses data, buffer to buffer, in one call. In: InBuf = ptr to compressed data InBytes = number of bytes in InBuf Out: OutBuf = ptr to newly allocated buffer containing decompressed data OutBytes = number of bytes in OutBuf } procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; out OutBuf: Pointer; out OutBytes: Integer); { DecompressBuf decompresses data, buffer to buffer, in one call. In: InBuf = ptr to compressed data InBytes = number of bytes in InBuf OutEstimate = zero, or est. size of the decompressed data Out: OutBuf = ptr to newly allocated buffer containing decompressed data OutBytes = number of bytes in OutBuf } procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); { DecompressToUserBuf decompresses data, buffer to buffer, in one call. In: InBuf = ptr to compressed data InBytes = number of bytes in InBuf Out: OutBuf = ptr to user-allocated buffer to contain decompressed data BufSize = number of bytes in OutBuf } procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; const OutBuf: Pointer; BufSize: Integer); const zlib_version = '1.2.8'; type EZlibError = class(Exception); ECompressionError = class(EZlibError); EDecompressionError = class(EZlibError); implementation uses ZLibConst; const Z_NO_FLUSH = 0; Z_PARTIAL_FLUSH = 1; Z_SYNC_FLUSH = 2; Z_FULL_FLUSH = 3; Z_FINISH = 4; Z_OK = 0; Z_STREAM_END = 1; Z_NEED_DICT = 2; Z_ERRNO = (-1); Z_STREAM_ERROR = (-2); Z_DATA_ERROR = (-3); Z_MEM_ERROR = (-4); Z_BUF_ERROR = (-5); Z_VERSION_ERROR = (-6); Z_NO_COMPRESSION = 0; Z_BEST_SPEED = 1; Z_BEST_COMPRESSION = 9; Z_DEFAULT_COMPRESSION = (-1); Z_FILTERED = 1; Z_HUFFMAN_ONLY = 2; Z_RLE = 3; Z_DEFAULT_STRATEGY = 0; Z_BINARY = 0; Z_ASCII = 1; Z_UNKNOWN = 2; Z_DEFLATED = 8; {$L adler32.obj} {$L compress.obj} {$L crc32.obj} {$L deflate.obj} {$L infback.obj} {$L inffast.obj} {$L inflate.obj} {$L inftrees.obj} {$L trees.obj} {$L uncompr.obj} {$L zutil.obj} procedure adler32; external; procedure compressBound; external; procedure crc32; external; procedure deflateInit2_; external; procedure deflateParams; external; function _malloc(Size: Integer): Pointer; cdecl; begin Result := AllocMem(Size); end; procedure _free(Block: Pointer); cdecl; begin FreeMem(Block); end; procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl; begin FillChar(P^, count, B); end; procedure _memcpy(dest, source: Pointer; count: Integer); cdecl; begin Move(source^, dest^, count); end; // deflate compresses data function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar; recsize: Integer): Integer; external; function deflate(var strm: TZStreamRec; flush: Integer): Integer; external; function deflateEnd(var strm: TZStreamRec): Integer; external; // inflate decompresses data function inflateInit_(var strm: TZStreamRec; version: PChar; recsize: Integer): Integer; external; function inflate(var strm: TZStreamRec; flush: Integer): Integer; external; function inflateEnd(var strm: TZStreamRec): Integer; external; function inflateReset(var strm: TZStreamRec): Integer; external; function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl; begin // GetMem(Result, Items*Size); Result := AllocMem(Items * Size); end; procedure zlibFreeMem(AppData, Block: Pointer); cdecl; begin FreeMem(Block); end; {function zlibCheck(code: Integer): Integer; begin Result := code; if code < 0 then raise EZlibError.Create('error'); //!! end;} function CCheck(code: Integer): Integer; begin Result := code; if code < 0 then raise ECompressionError.Create('error'); //!! end; function DCheck(code: Integer): Integer; begin Result := code; if code < 0 then raise EDecompressionError.Create('error'); //!! end; procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; out OutBuf: Pointer; out OutBytes: Integer); var strm: TZStreamRec; P: Pointer; begin FillChar(strm, sizeof(strm), 0); strm.zalloc := zlibAllocMem; strm.zfree := zlibFreeMem; OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255; GetMem(OutBuf, OutBytes); try strm.next_in := InBuf; strm.avail_in := InBytes; strm.next_out := OutBuf; strm.avail_out := OutBytes; CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm))); try while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do begin P := OutBuf; Inc(OutBytes, 256); ReallocMem(OutBuf, OutBytes); strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); strm.avail_out := 256; end; finally CCheck(deflateEnd(strm)); end; ReallocMem(OutBuf, strm.total_out); OutBytes := strm.total_out; except FreeMem(OutBuf); raise end; end; procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); var strm: TZStreamRec; P: Pointer; BufInc: Integer; begin FillChar(strm, sizeof(strm), 0); strm.zalloc := zlibAllocMem; strm.zfree := zlibFreeMem; BufInc := (InBytes + 255) and not 255; if OutEstimate = 0 then OutBytes := BufInc else OutBytes := OutEstimate; GetMem(OutBuf, OutBytes); try strm.next_in := InBuf; strm.avail_in := InBytes; strm.next_out := OutBuf; strm.avail_out := OutBytes; DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); try while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do begin P := OutBuf; Inc(OutBytes, BufInc); ReallocMem(OutBuf, OutBytes); strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); strm.avail_out := BufInc; end; finally DCheck(inflateEnd(strm)); end; ReallocMem(OutBuf, strm.total_out); OutBytes := strm.total_out; except FreeMem(OutBuf); raise end; end; procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; const OutBuf: Pointer; BufSize: Integer); var strm: TZStreamRec; begin FillChar(strm, sizeof(strm), 0); strm.zalloc := zlibAllocMem; strm.zfree := zlibFreeMem; strm.next_in := InBuf; strm.avail_in := InBytes; strm.next_out := OutBuf; strm.avail_out := BufSize; DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); try if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then raise EZlibError.CreateRes(@sTargetBufferTooSmall); finally DCheck(inflateEnd(strm)); end; end; // TCustomZlibStream constructor TCustomZLibStream.Create(Strm: TStream); begin inherited Create; FStrm := Strm; FStrmPos := Strm.Position; FZRec.zalloc := zlibAllocMem; FZRec.zfree := zlibFreeMem; end; procedure TCustomZLibStream.Progress(Sender: TObject); begin if Assigned(FOnProgress) then FOnProgress(Sender); end; // TCompressionStream constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel; Dest: TStream); const Levels: array [TCompressionLevel] of ShortInt = (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION); begin inherited Create(Dest); FZRec.next_out := FBuffer; FZRec.avail_out := sizeof(FBuffer); CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec))); end; destructor TCompressionStream.Destroy; begin FZRec.next_in := nil; FZRec.avail_in := 0; try if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END) and (FZRec.avail_out = 0) do begin FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); FZRec.next_out := FBuffer; FZRec.avail_out := sizeof(FBuffer); end; if FZRec.avail_out < sizeof(FBuffer) then FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out); finally deflateEnd(FZRec); end; inherited Destroy; end; function TCompressionStream.Read(var Buffer; Count: Longint): Longint; begin raise ECompressionError.CreateRes(@sInvalidStreamOp); end; function TCompressionStream.Write(const Buffer; Count: Longint): Longint; begin FZRec.next_in := @Buffer; FZRec.avail_in := Count; if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; while (FZRec.avail_in > 0) do begin CCheck(deflate(FZRec, 0)); if FZRec.avail_out = 0 then begin FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); FZRec.next_out := FBuffer; FZRec.avail_out := sizeof(FBuffer); FStrmPos := FStrm.Position; Progress(Self); end; end; Result := Count; end; function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint; begin if (Offset = 0) and (Origin = soFromCurrent) then Result := FZRec.total_in else raise ECompressionError.CreateRes(@sInvalidStreamOp); end; function TCompressionStream.GetCompressionRate: Single; begin if FZRec.total_in = 0 then Result := 0 else Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0; end; // TDecompressionStream constructor TDecompressionStream.Create(Source: TStream); begin inherited Create(Source); FZRec.next_in := FBuffer; FZRec.avail_in := 0; DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec))); end; destructor TDecompressionStream.Destroy; begin FStrm.Seek(-FZRec.avail_in, 1); inflateEnd(FZRec); inherited Destroy; end; function TDecompressionStream.Read(var Buffer; Count: Longint): Longint; begin FZRec.next_out := @Buffer; FZRec.avail_out := Count; if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; while (FZRec.avail_out > 0) do begin if FZRec.avail_in = 0 then begin FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer)); if FZRec.avail_in = 0 then begin Result := Count - FZRec.avail_out; Exit; end; FZRec.next_in := FBuffer; FStrmPos := FStrm.Position; Progress(Self); end; CCheck(inflate(FZRec, 0)); end; Result := Count; end; function TDecompressionStream.Write(const Buffer; Count: Longint): Longint; begin raise EDecompressionError.CreateRes(@sInvalidStreamOp); end; function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint; var I: Integer; Buf: array [0..4095] of Char; begin if (Offset = 0) and (Origin = soFromBeginning) then begin DCheck(inflateReset(FZRec)); FZRec.next_in := FBuffer; FZRec.avail_in := 0; FStrm.Position := 0; FStrmPos := 0; end else if ( (Offset >= 0) and (Origin = soFromCurrent)) or ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then begin if Origin = soFromBeginning then Dec(Offset, FZRec.total_out); if Offset > 0 then begin for I := 1 to Offset div sizeof(Buf) do ReadBuffer(Buf, sizeof(Buf)); ReadBuffer(Buf, Offset mod sizeof(Buf)); end; end else raise EDecompressionError.CreateRes(@sInvalidStreamOp); Result := FZRec.total_out; end; end. tcl8.6.5/compat/zlib/contrib/delphi/ZLibConst.pas0000644000175000017500000000027212663653131021270 0ustar sergeisergeiunit ZLibConst; interface resourcestring sTargetBufferTooSmall = 'ZLib error: target buffer may be too small'; sInvalidStreamOp = 'Invalid stream operation'; implementation end. tcl8.6.5/compat/zlib/contrib/delphi/readme.txt0000644000175000017500000000470412663653131020716 0ustar sergeisergei Overview ======== This directory contains an update to the ZLib interface unit, distributed by Borland as a Delphi supplemental component. The original ZLib unit is Copyright (c) 1997,99 Borland Corp., and is based on zlib version 1.0.4. There are a series of bugs and security problems associated with that old zlib version, and we recommend the users to update their ZLib unit. Summary of modifications ======================== - Improved makefile, adapted to zlib version 1.2.1. - Some field types from TZStreamRec are changed from Integer to Longint, for consistency with the zlib.h header, and for 64-bit readiness. - The zlib_version constant is updated. - The new Z_RLE strategy has its corresponding symbolic constant. - The allocation and deallocation functions and function types (TAlloc, TFree, zlibAllocMem and zlibFreeMem) are now cdecl, and _malloc and _free are added as C RTL stubs. As a result, the original C sources of zlib can be compiled out of the box, and linked to the ZLib unit. Suggestions for improvements ============================ Currently, the ZLib unit provides only a limited wrapper around the zlib library, and much of the original zlib functionality is missing. Handling compressed file formats like ZIP/GZIP or PNG cannot be implemented without having this functionality. Applications that handle these formats are either using their own, duplicated code, or not using the ZLib unit at all. Here are a few suggestions: - Checksum class wrappers around adler32() and crc32(), similar to the Java classes that implement the java.util.zip.Checksum interface. - The ability to read and write raw deflate streams, without the zlib stream header and trailer. Raw deflate streams are used in the ZIP file format. - The ability to read and write gzip streams, used in the GZIP file format, and normally produced by the gzip program. - The ability to select a different compression strategy, useful to PNG and MNG image compression, and to multimedia compression in general. Besides the compression level TCompressionLevel = (clNone, clFastest, clDefault, clMax); which, in fact, could have used the 'z' prefix and avoided TColor-like symbols TCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax); there could be a compression strategy TCompressionStrategy = (zsDefault, zsFiltered, zsHuffmanOnly, zsRle); - ZIP and GZIP stream handling via TStreams. -- Cosmin Truta tcl8.6.5/compat/zlib/contrib/dotzlib/0000755000175000017500000000000012666034667017127 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib.build0000644000175000017500000000222712663653206021453 0ustar sergeisergei A .Net wrapper library around ZLib1.dll tcl8.6.5/compat/zlib/contrib/dotzlib/readme.txt0000644000175000017500000000446612663653206021130 0ustar sergeisergeiThis directory contains a .Net wrapper class library for the ZLib1.dll The wrapper includes support for inflating/deflating memory buffers, .Net streaming wrappers for the gz streams part of zlib, and wrappers for the checksum parts of zlib. See DotZLib/UnitTests.cs for examples. Directory structure: -------------------- LICENSE_1_0.txt - License file. readme.txt - This file. DotZLib.chm - Class library documentation DotZLib.build - NAnt build file DotZLib.sln - Microsoft Visual Studio 2003 solution file DotZLib\*.cs - Source files for the class library Unit tests: ----------- The file DotZLib/UnitTests.cs contains unit tests for use with NUnit 2.1 or higher. To include unit tests in the build, define nunit before building. Build instructions: ------------------- 1. Using Visual Studio.Net 2003: Open DotZLib.sln in VS.Net and build from there. Output file (DotZLib.dll) will be found ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on you are building the release or debug version of the library. Check DotZLib/UnitTests.cs for instructions on how to include unit tests in the build. 2. Using NAnt: Open a command prompt with access to the build environment and run nant in the same directory as the DotZLib.build file. You can define 2 properties on the nant command-line to control the build: debug={true|false} to toggle between release/debug builds (default=true). nunit={true|false} to include or esclude unit tests (default=true). Also the target clean will remove binaries. Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on whether you are building the release or debug version of the library. Examples: nant -D:debug=false -D:nunit=false will build a release mode version of the library without unit tests. nant will build a debug version of the library with unit tests nant clean will remove all previously built files. --------------------------------- Copyright (c) Henrik Ravn 2004 Use, modification and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) tcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib/0000755000175000017500000000000012665173607020433 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib/CodecBase.cs0000644000175000017500000001427712663653206022601 0ustar sergeisergei// // © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // using System; using System.Runtime.InteropServices; namespace DotZLib { /// /// Implements the common functionality needed for all s /// public abstract class CodecBase : Codec, IDisposable { #region Data members /// /// Instance of the internal zlib buffer structure that is /// passed to all functions in the zlib dll /// internal ZStream _ztream = new ZStream(); /// /// True if the object instance has been disposed, false otherwise /// protected bool _isDisposed = false; /// /// The size of the internal buffers /// protected const int kBufferSize = 16384; private byte[] _outBuffer = new byte[kBufferSize]; private byte[] _inBuffer = new byte[kBufferSize]; private GCHandle _hInput; private GCHandle _hOutput; private uint _checksum = 0; #endregion /// /// Initializes a new instance of the CodeBase class. /// public CodecBase() { try { _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned); _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned); } catch (Exception) { CleanUp(false); throw; } } #region Codec Members /// /// Occurs when more processed data are available. /// public event DataAvailableHandler DataAvailable; /// /// Fires the event /// protected void OnDataAvailable() { if (_ztream.total_out > 0) { if (DataAvailable != null) DataAvailable( _outBuffer, 0, (int)_ztream.total_out); resetOutput(); } } /// /// Adds more data to the codec to be processed. /// /// Byte array containing the data to be added to the codec /// Adding data may, or may not, raise the DataAvailable event public void Add(byte[] data) { Add(data,0,data.Length); } /// /// Adds more data to the codec to be processed. /// /// Byte array containing the data to be added to the codec /// The index of the first byte to add from data /// The number of bytes to add /// Adding data may, or may not, raise the DataAvailable event /// This must be implemented by a derived class public abstract void Add(byte[] data, int offset, int count); /// /// Finishes up any pending data that needs to be processed and handled. /// /// This must be implemented by a derived class public abstract void Finish(); /// /// Gets the checksum of the data that has been added so far /// public uint Checksum { get { return _checksum; } } #endregion #region Destructor & IDisposable stuff /// /// Destroys this instance /// ~CodecBase() { CleanUp(false); } /// /// Releases any unmanaged resources and calls the method of the derived class /// public void Dispose() { CleanUp(true); } /// /// Performs any codec specific cleanup /// /// This must be implemented by a derived class protected abstract void CleanUp(); // performs the release of the handles and calls the dereived CleanUp() private void CleanUp(bool isDisposing) { if (!_isDisposed) { CleanUp(); if (_hInput.IsAllocated) _hInput.Free(); if (_hOutput.IsAllocated) _hOutput.Free(); _isDisposed = true; } } #endregion #region Helper methods /// /// Copies a number of bytes to the internal codec buffer - ready for proccesing /// /// The byte array that contains the data to copy /// The index of the first byte to copy /// The number of bytes to copy from data protected void copyInput(byte[] data, int startIndex, int count) { Array.Copy(data, startIndex, _inBuffer,0, count); _ztream.next_in = _hInput.AddrOfPinnedObject(); _ztream.total_in = 0; _ztream.avail_in = (uint)count; } /// /// Resets the internal output buffers to a known state - ready for processing /// protected void resetOutput() { _ztream.total_out = 0; _ztream.avail_out = kBufferSize; _ztream.next_out = _hOutput.AddrOfPinnedObject(); } /// /// Updates the running checksum property /// /// The new checksum value protected void setChecksum(uint newSum) { _checksum = newSum; } #endregion } } tcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs0000644000175000017500000000430612663653206023657 0ustar sergeisergei// // © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // using System; using System.Diagnostics; namespace DotZLib { /// /// This class implements a circular buffer /// internal class CircularBuffer { #region Private data private int _capacity; private int _head; private int _tail; private int _size; private byte[] _buffer; #endregion public CircularBuffer(int capacity) { Debug.Assert( capacity > 0 ); _buffer = new byte[capacity]; _capacity = capacity; _head = 0; _tail = 0; _size = 0; } public int Size { get { return _size; } } public int Put(byte[] source, int offset, int count) { Debug.Assert( count > 0 ); int trueCount = Math.Min(count, _capacity - Size); for (int i = 0; i < trueCount; ++i) _buffer[(_tail+i) % _capacity] = source[offset+i]; _tail += trueCount; _tail %= _capacity; _size += trueCount; return trueCount; } public bool Put(byte b) { if (Size == _capacity) // no room return false; _buffer[_tail++] = b; _tail %= _capacity; ++_size; return true; } public int Get(byte[] destination, int offset, int count) { int trueCount = Math.Min(count,Size); for (int i = 0; i < trueCount; ++i) destination[offset + i] = _buffer[(_head+i) % _capacity]; _head += trueCount; _head %= _capacity; _size -= trueCount; return trueCount; } public int Get() { if (Size == 0) return -1; int result = (int)_buffer[_head++ % _capacity]; --_size; return result; } } } tcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib/DotZLib.cs0000644000175000017500000002330712663653206022272 0ustar sergeisergei// // © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // using System; using System.IO; using System.Runtime.InteropServices; using System.Text; namespace DotZLib { #region Internal types /// /// Defines constants for the various flush types used with zlib /// internal enum FlushTypes { None, Partial, Sync, Full, Finish, Block } #region ZStream structure // internal mapping of the zlib zstream structure for marshalling [StructLayoutAttribute(LayoutKind.Sequential, Pack=4, Size=0, CharSet=CharSet.Ansi)] internal struct ZStream { public IntPtr next_in; public uint avail_in; public uint total_in; public IntPtr next_out; public uint avail_out; public uint total_out; [MarshalAs(UnmanagedType.LPStr)] string msg; uint state; uint zalloc; uint zfree; uint opaque; int data_type; public uint adler; uint reserved; } #endregion #endregion #region Public enums /// /// Defines constants for the available compression levels in zlib /// public enum CompressLevel : int { /// /// The default compression level with a reasonable compromise between compression and speed /// Default = -1, /// /// No compression at all. The data are passed straight through. /// None = 0, /// /// The maximum compression rate available. /// Best = 9, /// /// The fastest available compression level. /// Fastest = 1 } #endregion #region Exception classes /// /// The exception that is thrown when an error occurs on the zlib dll /// public class ZLibException : ApplicationException { /// /// Initializes a new instance of the class with a specified /// error message and error code /// /// The zlib error code that caused the exception /// A message that (hopefully) describes the error public ZLibException(int errorCode, string msg) : base(String.Format("ZLib error {0} {1}", errorCode, msg)) { } /// /// Initializes a new instance of the class with a specified /// error code /// /// The zlib error code that caused the exception public ZLibException(int errorCode) : base(String.Format("ZLib error {0}", errorCode)) { } } #endregion #region Interfaces /// /// Declares methods and properties that enables a running checksum to be calculated /// public interface ChecksumGenerator { /// /// Gets the current value of the checksum /// uint Value { get; } /// /// Clears the current checksum to 0 /// void Reset(); /// /// Updates the current checksum with an array of bytes /// /// The data to update the checksum with void Update(byte[] data); /// /// Updates the current checksum with part of an array of bytes /// /// The data to update the checksum with /// Where in data to start updating /// The number of bytes from data to use /// The sum of offset and count is larger than the length of data /// data is a null reference /// Offset or count is negative. void Update(byte[] data, int offset, int count); /// /// Updates the current checksum with the data from a string /// /// The string to update the checksum with /// The characters in the string are converted by the UTF-8 encoding void Update(string data); /// /// Updates the current checksum with the data from a string, using a specific encoding /// /// The string to update the checksum with /// The encoding to use void Update(string data, Encoding encoding); } /// /// Represents the method that will be called from a codec when new data /// are available. /// /// The byte array containing the processed data /// The index of the first processed byte in data /// The number of processed bytes available /// On return from this method, the data may be overwritten, so grab it while you can. /// You cannot assume that startIndex will be zero. /// public delegate void DataAvailableHandler(byte[] data, int startIndex, int count); /// /// Declares methods and events for implementing compressors/decompressors /// public interface Codec { /// /// Occurs when more processed data are available. /// event DataAvailableHandler DataAvailable; /// /// Adds more data to the codec to be processed. /// /// Byte array containing the data to be added to the codec /// Adding data may, or may not, raise the DataAvailable event void Add(byte[] data); /// /// Adds more data to the codec to be processed. /// /// Byte array containing the data to be added to the codec /// The index of the first byte to add from data /// The number of bytes to add /// Adding data may, or may not, raise the DataAvailable event void Add(byte[] data, int offset, int count); /// /// Finishes up any pending data that needs to be processed and handled. /// void Finish(); /// /// Gets the checksum of the data that has been added so far /// uint Checksum { get; } } #endregion #region Classes /// /// Encapsulates general information about the ZLib library /// public class Info { #region DLL imports [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern uint zlibCompileFlags(); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern string zlibVersion(); #endregion #region Private stuff private uint _flags; // helper function that unpacks a bitsize mask private static int bitSize(uint bits) { switch (bits) { case 0: return 16; case 1: return 32; case 2: return 64; } return -1; } #endregion /// /// Constructs an instance of the Info class. /// public Info() { _flags = zlibCompileFlags(); } /// /// True if the library is compiled with debug info /// public bool HasDebugInfo { get { return 0 != (_flags & 0x100); } } /// /// True if the library is compiled with assembly optimizations /// public bool UsesAssemblyCode { get { return 0 != (_flags & 0x200); } } /// /// Gets the size of the unsigned int that was compiled into Zlib /// public int SizeOfUInt { get { return bitSize(_flags & 3); } } /// /// Gets the size of the unsigned long that was compiled into Zlib /// public int SizeOfULong { get { return bitSize((_flags >> 2) & 3); } } /// /// Gets the size of the pointers that were compiled into Zlib /// public int SizeOfPointer { get { return bitSize((_flags >> 4) & 3); } } /// /// Gets the size of the z_off_t type that was compiled into Zlib /// public int SizeOfOffset { get { return bitSize((_flags >> 6) & 3); } } /// /// Gets the version of ZLib as a string, e.g. "1.2.1" /// public static string Version { get { return zlibVersion(); } } } #endregion } tcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib/GZipStream.cs0000644000175000017500000002563212663653206023013 0ustar sergeisergei// // © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // using System; using System.IO; using System.Runtime.InteropServices; namespace DotZLib { /// /// Implements a compressed , in GZip (.gz) format. /// public class GZipStream : Stream, IDisposable { #region Dll Imports [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] private static extern IntPtr gzopen(string name, string mode); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int gzclose(IntPtr gzFile); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int gzwrite(IntPtr gzFile, int data, int length); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int gzread(IntPtr gzFile, int data, int length); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int gzgetc(IntPtr gzFile); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int gzputc(IntPtr gzFile, int c); #endregion #region Private data private IntPtr _gzFile; private bool _isDisposed = false; private bool _isWriting; #endregion #region Constructors /// /// Creates a new file as a writeable GZipStream /// /// The name of the compressed file to create /// The compression level to use when adding data /// If an error occurred in the internal zlib function public GZipStream(string fileName, CompressLevel level) { _isWriting = true; _gzFile = gzopen(fileName, String.Format("wb{0}", (int)level)); if (_gzFile == IntPtr.Zero) throw new ZLibException(-1, "Could not open " + fileName); } /// /// Opens an existing file as a readable GZipStream /// /// The name of the file to open /// If an error occurred in the internal zlib function public GZipStream(string fileName) { _isWriting = false; _gzFile = gzopen(fileName, "rb"); if (_gzFile == IntPtr.Zero) throw new ZLibException(-1, "Could not open " + fileName); } #endregion #region Access properties /// /// Returns true of this stream can be read from, false otherwise /// public override bool CanRead { get { return !_isWriting; } } /// /// Returns false. /// public override bool CanSeek { get { return false; } } /// /// Returns true if this tsream is writeable, false otherwise /// public override bool CanWrite { get { return _isWriting; } } #endregion #region Destructor & IDispose stuff /// /// Destroys this instance /// ~GZipStream() { cleanUp(false); } /// /// Closes the external file handle /// public void Dispose() { cleanUp(true); } // Does the actual closing of the file handle. private void cleanUp(bool isDisposing) { if (!_isDisposed) { gzclose(_gzFile); _isDisposed = true; } } #endregion #region Basic reading and writing /// /// Attempts to read a number of bytes from the stream. /// /// The destination data buffer /// The index of the first destination byte in buffer /// The number of bytes requested /// The number of bytes read /// If buffer is null /// If count or offset are negative /// If offset + count is > buffer.Length /// If this stream is not readable. /// If this stream has been disposed. public override int Read(byte[] buffer, int offset, int count) { if (!CanRead) throw new NotSupportedException(); if (buffer == null) throw new ArgumentNullException(); if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); if ((offset+count) > buffer.Length) throw new ArgumentException(); if (_isDisposed) throw new ObjectDisposedException("GZipStream"); GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); int result; try { result = gzread(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); if (result < 0) throw new IOException(); } finally { h.Free(); } return result; } /// /// Attempts to read a single byte from the stream. /// /// The byte that was read, or -1 in case of error or End-Of-File public override int ReadByte() { if (!CanRead) throw new NotSupportedException(); if (_isDisposed) throw new ObjectDisposedException("GZipStream"); return gzgetc(_gzFile); } /// /// Writes a number of bytes to the stream /// /// /// /// /// If buffer is null /// If count or offset are negative /// If offset + count is > buffer.Length /// If this stream is not writeable. /// If this stream has been disposed. public override void Write(byte[] buffer, int offset, int count) { if (!CanWrite) throw new NotSupportedException(); if (buffer == null) throw new ArgumentNullException(); if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); if ((offset+count) > buffer.Length) throw new ArgumentException(); if (_isDisposed) throw new ObjectDisposedException("GZipStream"); GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); try { int result = gzwrite(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); if (result < 0) throw new IOException(); } finally { h.Free(); } } /// /// Writes a single byte to the stream /// /// The byte to add to the stream. /// If this stream is not writeable. /// If this stream has been disposed. public override void WriteByte(byte value) { if (!CanWrite) throw new NotSupportedException(); if (_isDisposed) throw new ObjectDisposedException("GZipStream"); int result = gzputc(_gzFile, (int)value); if (result < 0) throw new IOException(); } #endregion #region Position & length stuff /// /// Not supported. /// /// /// Always thrown public override void SetLength(long value) { throw new NotSupportedException(); } /// /// Not suppported. /// /// /// /// /// Always thrown public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } /// /// Flushes the GZipStream. /// /// In this implementation, this method does nothing. This is because excessive /// flushing may degrade the achievable compression rates. public override void Flush() { // left empty on purpose } /// /// Gets/sets the current position in the GZipStream. Not suppported. /// /// In this implementation this property is not supported /// Always thrown public override long Position { get { throw new NotSupportedException(); } set { throw new NotSupportedException(); } } /// /// Gets the size of the stream. Not suppported. /// /// In this implementation this property is not supported /// Always thrown public override long Length { get { throw new NotSupportedException(); } } #endregion } } tcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs0000644000175000017500000000470412663653206023356 0ustar sergeisergeiusing System.Reflection; using System.Runtime.CompilerServices; // // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. // [assembly: AssemblyTitle("DotZLib")] [assembly: AssemblyDescription(".Net bindings for ZLib compression dll 1.2.x")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Henrik Ravn")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("(c) 2004 by Henrik Ravn")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.*")] // // In order to sign your assembly you must specify a key to use. Refer to the // Microsoft .NET Framework documentation for more information on assembly signing. // // Use the attributes below to control which key is used for signing. // // Notes: // (*) If no key is specified, the assembly is not signed. // (*) KeyName refers to a key that has been installed in the Crypto Service // Provider (CSP) on your machine. KeyFile refers to a file which contains // a key. // (*) If the KeyFile and the KeyName values are both specified, the // following processing occurs: // (1) If the KeyName can be found in the CSP, that key is used. // (2) If the KeyName does not exist and the KeyFile does exist, the key // in the KeyFile is installed into the CSP and used. // (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. // When specifying the KeyFile, the location of the KeyFile should be // relative to the project output directory which is // %Project Directory%\obj\. For example, if your KeyFile is // located in the project directory, you would specify the AssemblyKeyFile // attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] // (*) Delay Signing is an advanced option - see the Microsoft .NET Framework // documentation for more information on this. // [assembly: AssemblyDelaySign(false)] [assembly: AssemblyKeyFile("")] [assembly: AssemblyKeyName("")] tcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs0000644000175000017500000001700412663660064022722 0ustar sergeisergei// // © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // using System; using System.Collections; using System.IO; // uncomment the define below to include unit tests //#define nunit #if nunit using NUnit.Framework; // Unit tests for the DotZLib class library // ---------------------------------------- // // Use this with NUnit 2 from http://www.nunit.org // namespace DotZLibTests { using DotZLib; // helper methods internal class Utils { public static bool byteArrEqual( byte[] lhs, byte[] rhs ) { if (lhs.Length != rhs.Length) return false; for (int i = lhs.Length-1; i >= 0; --i) if (lhs[i] != rhs[i]) return false; return true; } } [TestFixture] public class CircBufferTests { #region Circular buffer tests [Test] public void SinglePutGet() { CircularBuffer buf = new CircularBuffer(10); Assert.AreEqual( 0, buf.Size ); Assert.AreEqual( -1, buf.Get() ); Assert.IsTrue(buf.Put( 1 )); Assert.AreEqual( 1, buf.Size ); Assert.AreEqual( 1, buf.Get() ); Assert.AreEqual( 0, buf.Size ); Assert.AreEqual( -1, buf.Get() ); } [Test] public void BlockPutGet() { CircularBuffer buf = new CircularBuffer(10); byte[] arr = {1,2,3,4,5,6,7,8,9,10}; Assert.AreEqual( 10, buf.Put(arr,0,10) ); Assert.AreEqual( 10, buf.Size ); Assert.IsFalse( buf.Put(11) ); Assert.AreEqual( 1, buf.Get() ); Assert.IsTrue( buf.Put(11) ); byte[] arr2 = (byte[])arr.Clone(); Assert.AreEqual( 9, buf.Get(arr2,1,9) ); Assert.IsTrue( Utils.byteArrEqual(arr,arr2) ); } #endregion } [TestFixture] public class ChecksumTests { #region CRC32 Tests [Test] public void CRC32_Null() { CRC32Checksum crc32 = new CRC32Checksum(); Assert.AreEqual( 0, crc32.Value ); crc32 = new CRC32Checksum(1); Assert.AreEqual( 1, crc32.Value ); crc32 = new CRC32Checksum(556); Assert.AreEqual( 556, crc32.Value ); } [Test] public void CRC32_Data() { CRC32Checksum crc32 = new CRC32Checksum(); byte[] data = { 1,2,3,4,5,6,7 }; crc32.Update(data); Assert.AreEqual( 0x70e46888, crc32.Value ); crc32 = new CRC32Checksum(); crc32.Update("penguin"); Assert.AreEqual( 0x0e5c1a120, crc32.Value ); crc32 = new CRC32Checksum(1); crc32.Update("penguin"); Assert.AreEqual(0x43b6aa94, crc32.Value); } #endregion #region Adler tests [Test] public void Adler_Null() { AdlerChecksum adler = new AdlerChecksum(); Assert.AreEqual(0, adler.Value); adler = new AdlerChecksum(1); Assert.AreEqual( 1, adler.Value ); adler = new AdlerChecksum(556); Assert.AreEqual( 556, adler.Value ); } [Test] public void Adler_Data() { AdlerChecksum adler = new AdlerChecksum(1); byte[] data = { 1,2,3,4,5,6,7 }; adler.Update(data); Assert.AreEqual( 0x5b001d, adler.Value ); adler = new AdlerChecksum(); adler.Update("penguin"); Assert.AreEqual(0x0bcf02f6, adler.Value ); adler = new AdlerChecksum(1); adler.Update("penguin"); Assert.AreEqual(0x0bd602f7, adler.Value); } #endregion } [TestFixture] public class InfoTests { #region Info tests [Test] public void Info_Version() { Info info = new Info(); Assert.AreEqual("1.2.8", Info.Version); Assert.AreEqual(32, info.SizeOfUInt); Assert.AreEqual(32, info.SizeOfULong); Assert.AreEqual(32, info.SizeOfPointer); Assert.AreEqual(32, info.SizeOfOffset); } #endregion } [TestFixture] public class DeflateInflateTests { #region Deflate tests [Test] public void Deflate_Init() { using (Deflater def = new Deflater(CompressLevel.Default)) { } } private ArrayList compressedData = new ArrayList(); private uint adler1; private ArrayList uncompressedData = new ArrayList(); private uint adler2; public void CDataAvail(byte[] data, int startIndex, int count) { for (int i = 0; i < count; ++i) compressedData.Add(data[i+startIndex]); } [Test] public void Deflate_Compress() { compressedData.Clear(); byte[] testData = new byte[35000]; for (int i = 0; i < testData.Length; ++i) testData[i] = 5; using (Deflater def = new Deflater((CompressLevel)5)) { def.DataAvailable += new DataAvailableHandler(CDataAvail); def.Add(testData); def.Finish(); adler1 = def.Checksum; } } #endregion #region Inflate tests [Test] public void Inflate_Init() { using (Inflater inf = new Inflater()) { } } private void DDataAvail(byte[] data, int startIndex, int count) { for (int i = 0; i < count; ++i) uncompressedData.Add(data[i+startIndex]); } [Test] public void Inflate_Expand() { uncompressedData.Clear(); using (Inflater inf = new Inflater()) { inf.DataAvailable += new DataAvailableHandler(DDataAvail); inf.Add((byte[])compressedData.ToArray(typeof(byte))); inf.Finish(); adler2 = inf.Checksum; } Assert.AreEqual( adler1, adler2 ); } #endregion } [TestFixture] public class GZipStreamTests { #region GZipStream test [Test] public void GZipStream_WriteRead() { using (GZipStream gzOut = new GZipStream("gzstream.gz", CompressLevel.Best)) { BinaryWriter writer = new BinaryWriter(gzOut); writer.Write("hi there"); writer.Write(Math.PI); writer.Write(42); } using (GZipStream gzIn = new GZipStream("gzstream.gz")) { BinaryReader reader = new BinaryReader(gzIn); string s = reader.ReadString(); Assert.AreEqual("hi there",s); double d = reader.ReadDouble(); Assert.AreEqual(Math.PI, d); int i = reader.ReadInt32(); Assert.AreEqual(42,i); } } #endregion } } #endif tcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib/Inflater.cs0000644000175000017500000000723412663653206022530 0ustar sergeisergei// // © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // using System; using System.Diagnostics; using System.Runtime.InteropServices; namespace DotZLib { /// /// Implements a data decompressor, using the inflate algorithm in the ZLib dll /// public class Inflater : CodecBase { #region Dll imports [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] private static extern int inflateInit_(ref ZStream sz, string vs, int size); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int inflate(ref ZStream sz, int flush); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int inflateReset(ref ZStream sz); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int inflateEnd(ref ZStream sz); #endregion /// /// Constructs an new instance of the Inflater /// public Inflater() : base() { int retval = inflateInit_(ref _ztream, Info.Version, Marshal.SizeOf(_ztream)); if (retval != 0) throw new ZLibException(retval, "Could not initialize inflater"); resetOutput(); } /// /// Adds more data to the codec to be processed. /// /// Byte array containing the data to be added to the codec /// The index of the first byte to add from data /// The number of bytes to add /// Adding data may, or may not, raise the DataAvailable event public override void Add(byte[] data, int offset, int count) { if (data == null) throw new ArgumentNullException(); if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); if ((offset+count) > data.Length) throw new ArgumentException(); int total = count; int inputIndex = offset; int err = 0; while (err >= 0 && inputIndex < total) { copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); err = inflate(ref _ztream, (int)FlushTypes.None); if (err == 0) while (_ztream.avail_out == 0) { OnDataAvailable(); err = inflate(ref _ztream, (int)FlushTypes.None); } inputIndex += (int)_ztream.total_in; } setChecksum( _ztream.adler ); } /// /// Finishes up any pending data that needs to be processed and handled. /// public override void Finish() { int err; do { err = inflate(ref _ztream, (int)FlushTypes.Finish); OnDataAvailable(); } while (err == 0); setChecksum( _ztream.adler ); inflateReset(ref _ztream); resetOutput(); } /// /// Closes the internal zlib inflate stream /// protected override void CleanUp() { inflateEnd(ref _ztream); } } } tcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs0000644000175000017500000001755012663653206023352 0ustar sergeisergei// // © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // using System; using System.Runtime.InteropServices; using System.Text; namespace DotZLib { #region ChecksumGeneratorBase /// /// Implements the common functionality needed for all s /// /// public abstract class ChecksumGeneratorBase : ChecksumGenerator { /// /// The value of the current checksum /// protected uint _current; /// /// Initializes a new instance of the checksum generator base - the current checksum is /// set to zero /// public ChecksumGeneratorBase() { _current = 0; } /// /// Initializes a new instance of the checksum generator basewith a specified value /// /// The value to set the current checksum to public ChecksumGeneratorBase(uint initialValue) { _current = initialValue; } /// /// Resets the current checksum to zero /// public void Reset() { _current = 0; } /// /// Gets the current checksum value /// public uint Value { get { return _current; } } /// /// Updates the current checksum with part of an array of bytes /// /// The data to update the checksum with /// Where in data to start updating /// The number of bytes from data to use /// The sum of offset and count is larger than the length of data /// data is a null reference /// Offset or count is negative. /// All the other Update methods are implmeneted in terms of this one. /// This is therefore the only method a derived class has to implement public abstract void Update(byte[] data, int offset, int count); /// /// Updates the current checksum with an array of bytes. /// /// The data to update the checksum with public void Update(byte[] data) { Update(data, 0, data.Length); } /// /// Updates the current checksum with the data from a string /// /// The string to update the checksum with /// The characters in the string are converted by the UTF-8 encoding public void Update(string data) { Update(Encoding.UTF8.GetBytes(data)); } /// /// Updates the current checksum with the data from a string, using a specific encoding /// /// The string to update the checksum with /// The encoding to use public void Update(string data, Encoding encoding) { Update(encoding.GetBytes(data)); } } #endregion #region CRC32 /// /// Implements a CRC32 checksum generator /// public sealed class CRC32Checksum : ChecksumGeneratorBase { #region DLL imports [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern uint crc32(uint crc, int data, uint length); #endregion /// /// Initializes a new instance of the CRC32 checksum generator /// public CRC32Checksum() : base() {} /// /// Initializes a new instance of the CRC32 checksum generator with a specified value /// /// The value to set the current checksum to public CRC32Checksum(uint initialValue) : base(initialValue) {} /// /// Updates the current checksum with part of an array of bytes /// /// The data to update the checksum with /// Where in data to start updating /// The number of bytes from data to use /// The sum of offset and count is larger than the length of data /// data is a null reference /// Offset or count is negative. public override void Update(byte[] data, int offset, int count) { if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); if ((offset+count) > data.Length) throw new ArgumentException(); GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); try { _current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); } finally { hData.Free(); } } } #endregion #region Adler /// /// Implements a checksum generator that computes the Adler checksum on data /// public sealed class AdlerChecksum : ChecksumGeneratorBase { #region DLL imports [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern uint adler32(uint adler, int data, uint length); #endregion /// /// Initializes a new instance of the Adler checksum generator /// public AdlerChecksum() : base() {} /// /// Initializes a new instance of the Adler checksum generator with a specified value /// /// The value to set the current checksum to public AdlerChecksum(uint initialValue) : base(initialValue) {} /// /// Updates the current checksum with part of an array of bytes /// /// The data to update the checksum with /// Where in data to start updating /// The number of bytes from data to use /// The sum of offset and count is larger than the length of data /// data is a null reference /// Offset or count is negative. public override void Update(byte[] data, int offset, int count) { if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); if ((offset+count) > data.Length) throw new ArgumentException(); GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); try { _current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); } finally { hData.Free(); } } } #endregion }tcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib/Deflater.cs0000644000175000017500000000763012663653206022512 0ustar sergeisergei// // © Copyright Henrik Ravn 2004 // // Use, modification and distribution are subject to the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // using System; using System.Diagnostics; using System.Runtime.InteropServices; namespace DotZLib { /// /// Implements a data compressor, using the deflate algorithm in the ZLib dll /// public sealed class Deflater : CodecBase { #region Dll imports [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] private static extern int deflateInit_(ref ZStream sz, int level, string vs, int size); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int deflate(ref ZStream sz, int flush); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int deflateReset(ref ZStream sz); [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] private static extern int deflateEnd(ref ZStream sz); #endregion /// /// Constructs an new instance of the Deflater /// /// The compression level to use for this Deflater public Deflater(CompressLevel level) : base() { int retval = deflateInit_(ref _ztream, (int)level, Info.Version, Marshal.SizeOf(_ztream)); if (retval != 0) throw new ZLibException(retval, "Could not initialize deflater"); resetOutput(); } /// /// Adds more data to the codec to be processed. /// /// Byte array containing the data to be added to the codec /// The index of the first byte to add from data /// The number of bytes to add /// Adding data may, or may not, raise the DataAvailable event public override void Add(byte[] data, int offset, int count) { if (data == null) throw new ArgumentNullException(); if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); if ((offset+count) > data.Length) throw new ArgumentException(); int total = count; int inputIndex = offset; int err = 0; while (err >= 0 && inputIndex < total) { copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); while (err >= 0 && _ztream.avail_in > 0) { err = deflate(ref _ztream, (int)FlushTypes.None); if (err == 0) while (_ztream.avail_out == 0) { OnDataAvailable(); err = deflate(ref _ztream, (int)FlushTypes.None); } inputIndex += (int)_ztream.total_in; } } setChecksum( _ztream.adler ); } /// /// Finishes up any pending data that needs to be processed and handled. /// public override void Finish() { int err; do { err = deflate(ref _ztream, (int)FlushTypes.Finish); OnDataAvailable(); } while (err == 0); setChecksum( _ztream.adler ); deflateReset(ref _ztream); resetOutput(); } /// /// Closes the internal zlib deflate stream /// protected override void CleanUp() { deflateEnd(ref _ztream); } } } tcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj0000644000175000017500000001242412663653131023160 0ustar sergeisergei tcl8.6.5/compat/zlib/contrib/dotzlib/DotZLib.sln0000644000175000017500000000161312663653131021143 0ustar sergeisergeiMicrosoft Visual Studio Solution File, Format Version 8.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotZLib", "DotZLib\DotZLib.csproj", "{BB1EE0B1-1808-46CB-B786-949D91117FC5}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug Release = Release EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {BB1EE0B1-1808-46CB-B786-949D91117FC5}.Debug.ActiveCfg = Debug|.NET {BB1EE0B1-1808-46CB-B786-949D91117FC5}.Debug.Build.0 = Debug|.NET {BB1EE0B1-1808-46CB-B786-949D91117FC5}.Release.ActiveCfg = Release|.NET {BB1EE0B1-1808-46CB-B786-949D91117FC5}.Release.Build.0 = Release|.NET EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection GlobalSection(ExtensibilityAddIns) = postSolution EndGlobalSection EndGlobal tcl8.6.5/compat/zlib/contrib/dotzlib/LICENSE_1_0.txt0000644000175000017500000000251712663653131021404 0ustar sergeisergeiBoost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.tcl8.6.5/compat/zlib/contrib/iostream2/0000755000175000017500000000000012665173607017362 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/iostream2/zstream.h0000644000175000017500000002210312663660064021212 0ustar sergeisergei/* * * Copyright (c) 1997 * Christian Michelsen Research AS * Advanced Computing * Fantoftvegen 38, 5036 BERGEN, Norway * http://www.cmr.no * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Christian Michelsen Research AS makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * */ #ifndef ZSTREAM__H #define ZSTREAM__H /* * zstream.h - C++ interface to the 'zlib' general purpose compression library * $Id: zstream.h 1.1 1997-06-25 12:00:56+02 tyge Exp tyge $ */ #include #include #include #include "zlib.h" #if defined(_WIN32) # include # include # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) #else # define SET_BINARY_MODE(file) #endif class zstringlen { public: zstringlen(class izstream&); zstringlen(class ozstream&, const char*); size_t value() const { return val.word; } private: struct Val { unsigned char byte; size_t word; } val; }; // ----------------------------- izstream ----------------------------- class izstream { public: izstream() : m_fp(0) {} izstream(FILE* fp) : m_fp(0) { open(fp); } izstream(const char* name) : m_fp(0) { open(name); } ~izstream() { close(); } /* Opens a gzip (.gz) file for reading. * open() can be used to read a file which is not in gzip format; * in this case read() will directly read from the file without * decompression. errno can be checked to distinguish two error * cases (if errno is zero, the zlib error is Z_MEM_ERROR). */ void open(const char* name) { if (m_fp) close(); m_fp = ::gzopen(name, "rb"); } void open(FILE* fp) { SET_BINARY_MODE(fp); if (m_fp) close(); m_fp = ::gzdopen(fileno(fp), "rb"); } /* Flushes all pending input if necessary, closes the compressed file * and deallocates all the (de)compression state. The return value is * the zlib error number (see function error() below). */ int close() { int r = ::gzclose(m_fp); m_fp = 0; return r; } /* Binary read the given number of bytes from the compressed file. */ int read(void* buf, size_t len) { return ::gzread(m_fp, buf, len); } /* Returns the error message for the last error which occurred on the * given compressed file. errnum is set to zlib error number. If an * error occurred in the file system and not in the compression library, * errnum is set to Z_ERRNO and the application may consult errno * to get the exact error code. */ const char* error(int* errnum) { return ::gzerror(m_fp, errnum); } gzFile fp() { return m_fp; } private: gzFile m_fp; }; /* * Binary read the given (array of) object(s) from the compressed file. * If the input file was not in gzip format, read() copies the objects number * of bytes into the buffer. * returns the number of uncompressed bytes actually read * (0 for end of file, -1 for error). */ template inline int read(izstream& zs, T* x, Items items) { return ::gzread(zs.fp(), x, items*sizeof(T)); } /* * Binary input with the '>' operator. */ template inline izstream& operator>(izstream& zs, T& x) { ::gzread(zs.fp(), &x, sizeof(T)); return zs; } inline zstringlen::zstringlen(izstream& zs) { zs > val.byte; if (val.byte == 255) zs > val.word; else val.word = val.byte; } /* * Read length of string + the string with the '>' operator. */ inline izstream& operator>(izstream& zs, char* x) { zstringlen len(zs); ::gzread(zs.fp(), x, len.value()); x[len.value()] = '\0'; return zs; } inline char* read_string(izstream& zs) { zstringlen len(zs); char* x = new char[len.value()+1]; ::gzread(zs.fp(), x, len.value()); x[len.value()] = '\0'; return x; } // ----------------------------- ozstream ----------------------------- class ozstream { public: ozstream() : m_fp(0), m_os(0) { } ozstream(FILE* fp, int level = Z_DEFAULT_COMPRESSION) : m_fp(0), m_os(0) { open(fp, level); } ozstream(const char* name, int level = Z_DEFAULT_COMPRESSION) : m_fp(0), m_os(0) { open(name, level); } ~ozstream() { close(); } /* Opens a gzip (.gz) file for writing. * The compression level parameter should be in 0..9 * errno can be checked to distinguish two error cases * (if errno is zero, the zlib error is Z_MEM_ERROR). */ void open(const char* name, int level = Z_DEFAULT_COMPRESSION) { char mode[4] = "wb\0"; if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; if (m_fp) close(); m_fp = ::gzopen(name, mode); } /* open from a FILE pointer. */ void open(FILE* fp, int level = Z_DEFAULT_COMPRESSION) { SET_BINARY_MODE(fp); char mode[4] = "wb\0"; if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; if (m_fp) close(); m_fp = ::gzdopen(fileno(fp), mode); } /* Flushes all pending output if necessary, closes the compressed file * and deallocates all the (de)compression state. The return value is * the zlib error number (see function error() below). */ int close() { if (m_os) { ::gzwrite(m_fp, m_os->str(), m_os->pcount()); delete[] m_os->str(); delete m_os; m_os = 0; } int r = ::gzclose(m_fp); m_fp = 0; return r; } /* Binary write the given number of bytes into the compressed file. */ int write(const void* buf, size_t len) { return ::gzwrite(m_fp, (voidp) buf, len); } /* Flushes all pending output into the compressed file. The parameter * _flush is as in the deflate() function. The return value is the zlib * error number (see function gzerror below). flush() returns Z_OK if * the flush_ parameter is Z_FINISH and all output could be flushed. * flush() should be called only when strictly necessary because it can * degrade compression. */ int flush(int _flush) { os_flush(); return ::gzflush(m_fp, _flush); } /* Returns the error message for the last error which occurred on the * given compressed file. errnum is set to zlib error number. If an * error occurred in the file system and not in the compression library, * errnum is set to Z_ERRNO and the application may consult errno * to get the exact error code. */ const char* error(int* errnum) { return ::gzerror(m_fp, errnum); } gzFile fp() { return m_fp; } ostream& os() { if (m_os == 0) m_os = new ostrstream; return *m_os; } void os_flush() { if (m_os && m_os->pcount()>0) { ostrstream* oss = new ostrstream; oss->fill(m_os->fill()); oss->flags(m_os->flags()); oss->precision(m_os->precision()); oss->width(m_os->width()); ::gzwrite(m_fp, m_os->str(), m_os->pcount()); delete[] m_os->str(); delete m_os; m_os = oss; } } private: gzFile m_fp; ostrstream* m_os; }; /* * Binary write the given (array of) object(s) into the compressed file. * returns the number of uncompressed bytes actually written * (0 in case of error). */ template inline int write(ozstream& zs, const T* x, Items items) { return ::gzwrite(zs.fp(), (voidp) x, items*sizeof(T)); } /* * Binary output with the '<' operator. */ template inline ozstream& operator<(ozstream& zs, const T& x) { ::gzwrite(zs.fp(), (voidp) &x, sizeof(T)); return zs; } inline zstringlen::zstringlen(ozstream& zs, const char* x) { val.byte = 255; val.word = ::strlen(x); if (val.word < 255) zs < (val.byte = val.word); else zs < val; } /* * Write length of string + the string with the '<' operator. */ inline ozstream& operator<(ozstream& zs, const char* x) { zstringlen len(zs, x); ::gzwrite(zs.fp(), (voidp) x, len.value()); return zs; } #ifdef _MSC_VER inline ozstream& operator<(ozstream& zs, char* const& x) { return zs < (const char*) x; } #endif /* * Ascii write with the << operator; */ template inline ostream& operator<<(ozstream& zs, const T& x) { zs.os_flush(); return zs.os() << x; } #endif tcl8.6.5/compat/zlib/contrib/iostream2/zstream_test.cpp0000644000175000017500000000130712663653131022604 0ustar sergeisergei#include "zstream.h" #include #include #include void main() { char h[256] = "Hello"; char* g = "Goodbye"; ozstream out("temp.gz"); out < "This works well" < h < g; out.close(); izstream in("temp.gz"); // read it back char *x = read_string(in), *y = new char[256], z[256]; in > y > z; in.close(); cout << x << endl << y << endl << z << endl; out.open("temp.gz"); // try ascii output; zcat temp.gz to see the results out << setw(50) << setfill('#') << setprecision(20) << x << endl << y << endl << z << endl; out << z << endl << y << endl << x << endl; out << 1.1234567890123456789 << endl; delete[] x; delete[] y; } tcl8.6.5/compat/zlib/contrib/testzlib/0000755000175000017500000000000012665173607017315 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/testzlib/testzlib.txt0000644000175000017500000000031512663653131021706 0ustar sergeisergeiTo build testzLib with Visual Studio 2005: copy to a directory file from : - root of zLib tree - contrib/testzlib - contrib/masmx86 - contrib/masmx64 - contrib/vstudio/vc7 and open testzlib8.slntcl8.6.5/compat/zlib/contrib/testzlib/testzlib.c0000644000175000017500000001673312663660064021327 0ustar sergeisergei#include #include #include #include "zlib.h" void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B) { R->HighPart = A.HighPart - B.HighPart; if (A.LowPart >= B.LowPart) R->LowPart = A.LowPart - B.LowPart; else { R->LowPart = A.LowPart - B.LowPart; R->HighPart --; } } #ifdef _M_X64 // see http://msdn2.microsoft.com/library/twchhe95(en-us,vs.80).aspx for __rdtsc unsigned __int64 __rdtsc(void); void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) { // printf("rdtsc = %I64x\n",__rdtsc()); pbeginTime64->QuadPart=__rdtsc(); } LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) { LARGE_INTEGER LIres; unsigned _int64 res=__rdtsc()-((unsigned _int64)(beginTime64.QuadPart)); LIres.QuadPart=res; // printf("rdtsc = %I64x\n",__rdtsc()); return LIres; } #else #ifdef _M_IX86 void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) { DWORD dwEdx,dwEax; _asm { rdtsc mov dwEax,eax mov dwEdx,edx } pbeginTime64->LowPart=dwEax; pbeginTime64->HighPart=dwEdx; } void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) { myGetRDTSC32(pbeginTime64); } LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) { LARGE_INTEGER LIres,endTime64; myGetRDTSC32(&endTime64); LIres.LowPart=LIres.HighPart=0; MyDoMinus64(&LIres,endTime64,beginTime64); return LIres; } #else void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) { } void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) { } LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) { LARGE_INTEGER lr; lr.QuadPart=0; return lr; } #endif #endif void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf) { if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64))) { pbeginTime64->LowPart = GetTickCount(); pbeginTime64->HighPart = 0; } } DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) { LARGE_INTEGER endTime64,ticksPerSecond,ticks; DWORDLONG ticksShifted,tickSecShifted; DWORD dwLog=16+0; DWORD dwRet; if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64))) dwRet = (GetTickCount() - beginTime64.LowPart)*1; else { MyDoMinus64(&ticks,endTime64,beginTime64); QueryPerformanceFrequency(&ticksPerSecond); { ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog); tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog); } dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted)); dwRet *=1; } return dwRet; } int ReadFileMemory(const char* filename,long* plFileSize,unsigned char** pFilePtr) { FILE* stream; unsigned char* ptr; int retVal=1; stream=fopen(filename, "rb"); if (stream==NULL) return 0; fseek(stream,0,SEEK_END); *plFileSize=ftell(stream); fseek(stream,0,SEEK_SET); ptr=malloc((*plFileSize)+1); if (ptr==NULL) retVal=0; else { if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize)) retVal=0; } fclose(stream); *pFilePtr=ptr; return retVal; } int main(int argc, char *argv[]) { int BlockSizeCompress=0x8000; int BlockSizeUncompress=0x8000; int cprLevel=Z_DEFAULT_COMPRESSION ; long lFileSize; unsigned char* FilePtr; long lBufferSizeCpr; long lBufferSizeUncpr; long lCompressedSize=0; unsigned char* CprPtr; unsigned char* UncprPtr; long lSizeCpr,lSizeUncpr; DWORD dwGetTick,dwMsecQP; LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc; if (argc<=1) { printf("run TestZlib [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n"); return 0; } if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0) { printf("error reading %s\n",argv[1]); return 1; } else printf("file %s read, %u bytes\n",argv[1],lFileSize); if (argc>=3) BlockSizeCompress=atol(argv[2]); if (argc>=4) BlockSizeUncompress=atol(argv[3]); if (argc>=5) cprLevel=(int)atol(argv[4]); lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200; lBufferSizeUncpr = lBufferSizeCpr; CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); BeginCountPerfCounter(&li_qp,TRUE); dwGetTick=GetTickCount(); BeginCountRdtsc(&li_rdtsc); { z_stream zcpr; int ret=Z_OK; long lOrigToDo = lFileSize; long lOrigDone = 0; int step=0; memset(&zcpr,0,sizeof(z_stream)); deflateInit(&zcpr,cprLevel); zcpr.next_in = FilePtr; zcpr.next_out = CprPtr; do { long all_read_before = zcpr.total_in; zcpr.avail_in = min(lOrigToDo,BlockSizeCompress); zcpr.avail_out = BlockSizeCompress; ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH); lOrigDone += (zcpr.total_in-all_read_before); lOrigToDo -= (zcpr.total_in-all_read_before); step++; } while (ret==Z_OK); lSizeCpr=zcpr.total_out; deflateEnd(&zcpr); dwGetTick=GetTickCount()-dwGetTick; dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); printf("total compress size = %u, in %u step\n",lSizeCpr,step); printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); } CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr); UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress); BeginCountPerfCounter(&li_qp,TRUE); dwGetTick=GetTickCount(); BeginCountRdtsc(&li_rdtsc); { z_stream zcpr; int ret=Z_OK; long lOrigToDo = lSizeCpr; long lOrigDone = 0; int step=0; memset(&zcpr,0,sizeof(z_stream)); inflateInit(&zcpr); zcpr.next_in = CprPtr; zcpr.next_out = UncprPtr; do { long all_read_before = zcpr.total_in; zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress); zcpr.avail_out = BlockSizeUncompress; ret=inflate(&zcpr,Z_SYNC_FLUSH); lOrigDone += (zcpr.total_in-all_read_before); lOrigToDo -= (zcpr.total_in-all_read_before); step++; } while (ret==Z_OK); lSizeUncpr=zcpr.total_out; inflateEnd(&zcpr); dwGetTick=GetTickCount()-dwGetTick; dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); printf("uncpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); printf("uncpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); } if (lSizeUncpr==lFileSize) { if (memcmp(FilePtr,UncprPtr,lFileSize)==0) printf("compare ok\n"); } return 0; } tcl8.6.5/compat/zlib/contrib/masmx64/0000755000175000017500000000000012665173607016754 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/masmx64/inffasx64.asm0000644000175000017500000002452712663653206021274 0ustar sergeisergei; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding ; version for AMD64 on Windows using Microsoft C compiler ; ; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c ; inffasx64.asm is called by inffas8664.c, which contain more info. ; to compile this file, I use option ; ml64.exe /Flinffasx64 /c /Zi inffasx64.asm ; with Microsoft Macro Assembler (x64) for AMD64 ; ; This file compile with Microsoft Macro Assembler (x64) for AMD64 ; ; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK ; ; (you can get Windows WDK with ml64 for AMD64 from ; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) ; .code inffas8664fnc PROC ; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and ; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp ; ; All registers must be preserved across the call, except for ; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch. mov [rsp-8],rsi mov [rsp-16],rdi mov [rsp-24],r12 mov [rsp-32],r13 mov [rsp-40],r14 mov [rsp-48],r15 mov [rsp-56],rbx mov rax,rcx mov [rax+8], rbp ; /* save regs rbp and rsp */ mov [rax], rsp mov rsp, rax ; /* make rsp point to &ar */ mov rsi, [rsp+16] ; /* rsi = in */ mov rdi, [rsp+32] ; /* rdi = out */ mov r9, [rsp+24] ; /* r9 = last */ mov r10, [rsp+48] ; /* r10 = end */ mov rbp, [rsp+64] ; /* rbp = lcode */ mov r11, [rsp+72] ; /* r11 = dcode */ mov rdx, [rsp+80] ; /* rdx = hold */ mov ebx, [rsp+88] ; /* ebx = bits */ mov r12d, [rsp+100] ; /* r12d = lmask */ mov r13d, [rsp+104] ; /* r13d = dmask */ ; /* r14d = len */ ; /* r15d = dist */ cld cmp r10, rdi je L_one_time ; /* if only one decode left */ cmp r9, rsi jne L_do_loop L_one_time: mov r8, r12 ; /* r8 = lmask */ cmp bl, 32 ja L_get_length_code_one_time lodsd ; /* eax = *(uint *)in++ */ mov cl, bl ; /* cl = bits, needs it for shifting */ add bl, 32 ; /* bits += 32 */ shl rax, cl or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ jmp L_get_length_code_one_time ALIGN 4 L_while_test: cmp r10, rdi jbe L_break_loop cmp r9, rsi jbe L_break_loop L_do_loop: mov r8, r12 ; /* r8 = lmask */ cmp bl, 32 ja L_get_length_code ; /* if (32 < bits) */ lodsd ; /* eax = *(uint *)in++ */ mov cl, bl ; /* cl = bits, needs it for shifting */ add bl, 32 ; /* bits += 32 */ shl rax, cl or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ L_get_length_code: and r8, rdx ; /* r8 &= hold */ mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ mov cl, ah ; /* cl = this.bits */ sub bl, ah ; /* bits -= this.bits */ shr rdx, cl ; /* hold >>= this.bits */ test al, al jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ mov r8, r12 ; /* r8 = lmask */ shr eax, 16 ; /* output this.val char */ stosb L_get_length_code_one_time: and r8, rdx ; /* r8 &= hold */ mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ L_dolen: mov cl, ah ; /* cl = this.bits */ sub bl, ah ; /* bits -= this.bits */ shr rdx, cl ; /* hold >>= this.bits */ test al, al jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ shr eax, 16 ; /* output this.val char */ stosb jmp L_while_test ALIGN 4 L_test_for_length_base: mov r14d, eax ; /* len = this */ shr r14d, 16 ; /* len = this.val */ mov cl, al test al, 16 jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */ and cl, 15 ; /* op &= 15 */ jz L_decode_distance ; /* if (!op) */ L_add_bits_to_len: sub bl, cl xor eax, eax inc eax shl eax, cl dec eax and eax, edx ; /* eax &= hold */ shr rdx, cl add r14d, eax ; /* len += hold & mask[op] */ L_decode_distance: mov r8, r13 ; /* r8 = dmask */ cmp bl, 32 ja L_get_distance_code ; /* if (32 < bits) */ lodsd ; /* eax = *(uint *)in++ */ mov cl, bl ; /* cl = bits, needs it for shifting */ add bl, 32 ; /* bits += 32 */ shl rax, cl or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ L_get_distance_code: and r8, rdx ; /* r8 &= hold */ mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */ L_dodist: mov r15d, eax ; /* dist = this */ shr r15d, 16 ; /* dist = this.val */ mov cl, ah sub bl, ah ; /* bits -= this.bits */ shr rdx, cl ; /* hold >>= this.bits */ mov cl, al ; /* cl = this.op */ test al, 16 ; /* if ((op & 16) == 0) */ jz L_test_for_second_level_dist and cl, 15 ; /* op &= 15 */ jz L_check_dist_one L_add_bits_to_dist: sub bl, cl xor eax, eax inc eax shl eax, cl dec eax ; /* (1 << op) - 1 */ and eax, edx ; /* eax &= hold */ shr rdx, cl add r15d, eax ; /* dist += hold & ((1 << op) - 1) */ L_check_window: mov r8, rsi ; /* save in so from can use it's reg */ mov rax, rdi sub rax, [rsp+40] ; /* nbytes = out - beg */ cmp eax, r15d jb L_clip_window ; /* if (dist > nbytes) 4.2% */ mov ecx, r14d ; /* ecx = len */ mov rsi, rdi sub rsi, r15 ; /* from = out - dist */ sar ecx, 1 jnc L_copy_two ; /* if len % 2 == 0 */ rep movsw mov al, [rsi] mov [rdi], al inc rdi mov rsi, r8 ; /* move in back to %rsi, toss from */ jmp L_while_test L_copy_two: rep movsw mov rsi, r8 ; /* move in back to %rsi, toss from */ jmp L_while_test ALIGN 4 L_check_dist_one: cmp r15d, 1 ; /* if dist 1, is a memset */ jne L_check_window cmp [rsp+40], rdi ; /* if out == beg, outside window */ je L_check_window mov ecx, r14d ; /* ecx = len */ mov al, [rdi-1] mov ah, al sar ecx, 1 jnc L_set_two mov [rdi], al inc rdi L_set_two: rep stosw jmp L_while_test ALIGN 4 L_test_for_second_level_length: test al, 64 jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */ xor eax, eax inc eax shl eax, cl dec eax and eax, edx ; /* eax &= hold */ add eax, r14d ; /* eax += len */ mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/ jmp L_dolen ALIGN 4 L_test_for_second_level_dist: test al, 64 jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */ xor eax, eax inc eax shl eax, cl dec eax and eax, edx ; /* eax &= hold */ add eax, r15d ; /* eax += dist */ mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/ jmp L_dodist ALIGN 4 L_clip_window: mov ecx, eax ; /* ecx = nbytes */ mov eax, [rsp+92] ; /* eax = wsize, prepare for dist cmp */ neg ecx ; /* nbytes = -nbytes */ cmp eax, r15d jb L_invalid_distance_too_far ; /* if (dist > wsize) */ add ecx, r15d ; /* nbytes = dist - nbytes */ cmp dword ptr [rsp+96], 0 jne L_wrap_around_window ; /* if (write != 0) */ mov rsi, [rsp+56] ; /* from = window */ sub eax, ecx ; /* eax -= nbytes */ add rsi, rax ; /* from += wsize - nbytes */ mov eax, r14d ; /* eax = len */ cmp r14d, ecx jbe L_do_copy ; /* if (nbytes >= len) */ sub eax, ecx ; /* eax -= nbytes */ rep movsb mov rsi, rdi sub rsi, r15 ; /* from = &out[ -dist ] */ jmp L_do_copy ALIGN 4 L_wrap_around_window: mov eax, [rsp+96] ; /* eax = write */ cmp ecx, eax jbe L_contiguous_in_window ; /* if (write >= nbytes) */ mov esi, [rsp+92] ; /* from = wsize */ add rsi, [rsp+56] ; /* from += window */ add rsi, rax ; /* from += write */ sub rsi, rcx ; /* from -= nbytes */ sub ecx, eax ; /* nbytes -= write */ mov eax, r14d ; /* eax = len */ cmp eax, ecx jbe L_do_copy ; /* if (nbytes >= len) */ sub eax, ecx ; /* len -= nbytes */ rep movsb mov rsi, [rsp+56] ; /* from = window */ mov ecx, [rsp+96] ; /* nbytes = write */ cmp eax, ecx jbe L_do_copy ; /* if (nbytes >= len) */ sub eax, ecx ; /* len -= nbytes */ rep movsb mov rsi, rdi sub rsi, r15 ; /* from = out - dist */ jmp L_do_copy ALIGN 4 L_contiguous_in_window: mov rsi, [rsp+56] ; /* rsi = window */ add rsi, rax sub rsi, rcx ; /* from += write - nbytes */ mov eax, r14d ; /* eax = len */ cmp eax, ecx jbe L_do_copy ; /* if (nbytes >= len) */ sub eax, ecx ; /* len -= nbytes */ rep movsb mov rsi, rdi sub rsi, r15 ; /* from = out - dist */ jmp L_do_copy ; /* if (nbytes >= len) */ ALIGN 4 L_do_copy: mov ecx, eax ; /* ecx = len */ rep movsb mov rsi, r8 ; /* move in back to %esi, toss from */ jmp L_while_test L_test_for_end_of_block: test al, 32 jz L_invalid_literal_length_code mov dword ptr [rsp+116], 1 jmp L_break_loop_with_status L_invalid_literal_length_code: mov dword ptr [rsp+116], 2 jmp L_break_loop_with_status L_invalid_distance_code: mov dword ptr [rsp+116], 3 jmp L_break_loop_with_status L_invalid_distance_too_far: mov dword ptr [rsp+116], 4 jmp L_break_loop_with_status L_break_loop: mov dword ptr [rsp+116], 0 L_break_loop_with_status: ; /* put in, out, bits, and hold back into ar and pop esp */ mov [rsp+16], rsi ; /* in */ mov [rsp+32], rdi ; /* out */ mov [rsp+88], ebx ; /* bits */ mov [rsp+80], rdx ; /* hold */ mov rax, [rsp] ; /* restore rbp and rsp */ mov rbp, [rsp+8] mov rsp, rax mov rsi,[rsp-8] mov rdi,[rsp-16] mov r12,[rsp-24] mov r13,[rsp-32] mov r14,[rsp-40] mov r15,[rsp-48] mov rbx,[rsp-56] ret 0 ; : ; : "m" (ar) ; : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", ; "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" ; ); inffas8664fnc ENDP ;_TEXT ENDS END tcl8.6.5/compat/zlib/contrib/masmx64/gvmat64.asm0000644000175000017500000004007312663653206020746 0ustar sergeisergei;uInt longest_match_x64( ; deflate_state *s, ; IPos cur_match); /* current match */ ; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86_64 ; (AMD64 on Athlon 64, Opteron, Phenom ; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) ; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. ; ; File written by Gilles Vollant, by converting to assembly the longest_match ; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. ; ; and by taking inspiration on asm686 with masm, optimised assembly code ; from Brian Raiter, written 1998 ; ; This software is provided 'as-is', without any express or implied ; warranty. In no event will the authors be held liable for any damages ; arising from the use of this software. ; ; Permission is granted to anyone to use this software for any purpose, ; including commercial applications, and to alter it and redistribute it ; freely, subject to the following restrictions: ; ; 1. The origin of this software must not be misrepresented; you must not ; claim that you wrote the original software. If you use this software ; in a product, an acknowledgment in the product documentation would be ; appreciated but is not required. ; 2. Altered source versions must be plainly marked as such, and must not be ; misrepresented as being the original software ; 3. This notice may not be removed or altered from any source distribution. ; ; ; ; http://www.zlib.net ; http://www.winimage.com/zLibDll ; http://www.muppetlabs.com/~breadbox/software/assembly.html ; ; to compile this file for infozip Zip, I use option: ; ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm ; ; to compile this file for zLib, I use option: ; ml64.exe /Flgvmat64 /c /Zi gvmat64.asm ; Be carrefull to adapt zlib1222add below to your version of zLib ; (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change ; value of zlib1222add later) ; ; This file compile with Microsoft Macro Assembler (x64) for AMD64 ; ; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK ; ; (you can get Windows WDK with ml64 for AMD64 from ; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) ; ;uInt longest_match(s, cur_match) ; deflate_state *s; ; IPos cur_match; /* current match */ .code longest_match PROC ;LocalVarsSize equ 88 LocalVarsSize equ 72 ; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 ; free register : r14,r15 ; register can be saved : rsp chainlenwmask equ rsp + 8 - LocalVarsSize ; high word: current chain len ; low word: s->wmask ;window equ rsp + xx - LocalVarsSize ; local copy of s->window ; stored in r10 ;windowbestlen equ rsp + xx - LocalVarsSize ; s->window + bestlen , use r10+r11 ;scanstart equ rsp + xx - LocalVarsSize ; first two bytes of string ; stored in r12w ;scanend equ rsp + xx - LocalVarsSize ; last two bytes of string use ebx ;scanalign equ rsp + xx - LocalVarsSize ; dword-misalignment of string r13 ;bestlen equ rsp + xx - LocalVarsSize ; size of best match so far -> r11d ;scan equ rsp + xx - LocalVarsSize ; ptr to string wanting match -> r9 IFDEF INFOZIP ELSE nicematch equ (rsp + 16 - LocalVarsSize) ; a good enough match size ENDIF save_rdi equ rsp + 24 - LocalVarsSize save_rsi equ rsp + 32 - LocalVarsSize save_rbx equ rsp + 40 - LocalVarsSize save_rbp equ rsp + 48 - LocalVarsSize save_r12 equ rsp + 56 - LocalVarsSize save_r13 equ rsp + 64 - LocalVarsSize ;save_r14 equ rsp + 72 - LocalVarsSize ;save_r15 equ rsp + 80 - LocalVarsSize ; summary of register usage ; scanend ebx ; scanendw bx ; chainlenwmask edx ; curmatch rsi ; curmatchd esi ; windowbestlen r8 ; scanalign r9 ; scanalignd r9d ; window r10 ; bestlen r11 ; bestlend r11d ; scanstart r12d ; scanstartw r12w ; scan r13 ; nicematch r14d ; limit r15 ; limitd r15d ; prev rcx ; all the +4 offsets are due to the addition of pending_buf_size (in zlib ; in the deflate_state structure since the asm code was first written ; (if you compile with zlib 1.0.4 or older, remove the +4). ; Note : these value are good with a 8 bytes boundary pack structure MAX_MATCH equ 258 MIN_MATCH equ 3 MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) ;;; Offsets for fields in the deflate_state structure. These numbers ;;; are calculated from the definition of deflate_state, with the ;;; assumption that the compiler will dword-align the fields. (Thus, ;;; changing the definition of deflate_state could easily cause this ;;; program to crash horribly, without so much as a warning at ;;; compile time. Sigh.) ; all the +zlib1222add offsets are due to the addition of fields ; in zlib in the deflate_state structure since the asm code was first written ; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). ; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). ; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). IFDEF INFOZIP _DATA SEGMENT COMM window_size:DWORD ; WMask ; 7fff COMM window:BYTE:010040H COMM prev:WORD:08000H ; MatchLen : unused ; PrevMatch : unused COMM strstart:DWORD COMM match_start:DWORD ; Lookahead : ignore COMM prev_length:DWORD ; PrevLen COMM max_chain_length:DWORD COMM good_match:DWORD COMM nice_match:DWORD prev_ad equ OFFSET prev window_ad equ OFFSET window nicematch equ nice_match _DATA ENDS WMask equ 07fffh ELSE IFNDEF zlib1222add zlib1222add equ 8 ENDIF dsWSize equ 56+zlib1222add+(zlib1222add/2) dsWMask equ 64+zlib1222add+(zlib1222add/2) dsWindow equ 72+zlib1222add dsPrev equ 88+zlib1222add dsMatchLen equ 128+zlib1222add dsPrevMatch equ 132+zlib1222add dsStrStart equ 140+zlib1222add dsMatchStart equ 144+zlib1222add dsLookahead equ 148+zlib1222add dsPrevLen equ 152+zlib1222add dsMaxChainLen equ 156+zlib1222add dsGoodMatch equ 172+zlib1222add dsNiceMatch equ 176+zlib1222add window_size equ [ rcx + dsWSize] WMask equ [ rcx + dsWMask] window_ad equ [ rcx + dsWindow] prev_ad equ [ rcx + dsPrev] strstart equ [ rcx + dsStrStart] match_start equ [ rcx + dsMatchStart] Lookahead equ [ rcx + dsLookahead] ; 0ffffffffh on infozip prev_length equ [ rcx + dsPrevLen] max_chain_length equ [ rcx + dsMaxChainLen] good_match equ [ rcx + dsGoodMatch] nice_match equ [ rcx + dsNiceMatch] ENDIF ; parameter 1 in r8(deflate state s), param 2 in rdx (cur match) ; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and ; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp ; ; All registers must be preserved across the call, except for ; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. ;;; Save registers that the compiler may be using, and adjust esp to ;;; make room for our stack frame. ;;; Retrieve the function arguments. r8d will hold cur_match ;;; throughout the entire function. edx will hold the pointer to the ;;; deflate_state structure during the function's setup (before ;;; entering the main loop. ; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) ; this clear high 32 bits of r8, which can be garbage in both r8 and rdx mov [save_rdi],rdi mov [save_rsi],rsi mov [save_rbx],rbx mov [save_rbp],rbp IFDEF INFOZIP mov r8d,ecx ELSE mov r8d,edx ENDIF mov [save_r12],r12 mov [save_r13],r13 ; mov [save_r14],r14 ; mov [save_r15],r15 ;;; uInt wmask = s->w_mask; ;;; unsigned chain_length = s->max_chain_length; ;;; if (s->prev_length >= s->good_match) { ;;; chain_length >>= 2; ;;; } mov edi, prev_length mov esi, good_match mov eax, WMask mov ebx, max_chain_length cmp edi, esi jl LastMatchGood shr ebx, 2 LastMatchGood: ;;; chainlen is decremented once beforehand so that the function can ;;; use the sign flag instead of the zero flag for the exit test. ;;; It is then shifted into the high word, to make room for the wmask ;;; value, which it will always accompany. dec ebx shl ebx, 16 or ebx, eax ;;; on zlib only ;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; IFDEF INFOZIP mov [chainlenwmask], ebx ; on infozip nice_match = [nice_match] ELSE mov eax, nice_match mov [chainlenwmask], ebx mov r10d, Lookahead cmp r10d, eax cmovnl r10d, eax mov [nicematch],r10d ENDIF ;;; register Bytef *scan = s->window + s->strstart; mov r10, window_ad mov ebp, strstart lea r13, [r10 + rbp] ;;; Determine how many bytes the scan ptr is off from being ;;; dword-aligned. mov r9,r13 neg r13 and r13,3 ;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? ;;; s->strstart - (IPos)MAX_DIST(s) : NIL; IFDEF INFOZIP mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1)) ELSE mov eax, window_size sub eax, MIN_LOOKAHEAD ENDIF xor edi,edi sub ebp, eax mov r11d, prev_length cmovng ebp,edi ;;; int best_len = s->prev_length; ;;; Store the sum of s->window + best_len in esi locally, and in esi. lea rsi,[r10+r11] ;;; register ush scan_start = *(ushf*)scan; ;;; register ush scan_end = *(ushf*)(scan+best_len-1); ;;; Posf *prev = s->prev; movzx r12d,word ptr [r9] movzx ebx, word ptr [r9 + r11 - 1] mov rdi, prev_ad ;;; Jump into the main loop. mov edx, [chainlenwmask] cmp bx,word ptr [rsi + r8 - 1] jz LookupLoopIsZero LookupLoop1: and r8d, edx movzx r8d, word ptr [rdi + r8*2] cmp r8d, ebp jbe LeaveNow sub edx, 00010000h js LeaveNow LoopEntry1: cmp bx,word ptr [rsi + r8 - 1] jz LookupLoopIsZero LookupLoop2: and r8d, edx movzx r8d, word ptr [rdi + r8*2] cmp r8d, ebp jbe LeaveNow sub edx, 00010000h js LeaveNow LoopEntry2: cmp bx,word ptr [rsi + r8 - 1] jz LookupLoopIsZero LookupLoop4: and r8d, edx movzx r8d, word ptr [rdi + r8*2] cmp r8d, ebp jbe LeaveNow sub edx, 00010000h js LeaveNow LoopEntry4: cmp bx,word ptr [rsi + r8 - 1] jnz LookupLoop1 jmp LookupLoopIsZero ;;; do { ;;; match = s->window + cur_match; ;;; if (*(ushf*)(match+best_len-1) != scan_end || ;;; *(ushf*)match != scan_start) continue; ;;; [...] ;;; } while ((cur_match = prev[cur_match & wmask]) > limit ;;; && --chain_length != 0); ;;; ;;; Here is the inner loop of the function. The function will spend the ;;; majority of its time in this loop, and majority of that time will ;;; be spent in the first ten instructions. ;;; ;;; Within this loop: ;;; ebx = scanend ;;; r8d = curmatch ;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) ;;; esi = windowbestlen - i.e., (window + bestlen) ;;; edi = prev ;;; ebp = limit LookupLoop: and r8d, edx movzx r8d, word ptr [rdi + r8*2] cmp r8d, ebp jbe LeaveNow sub edx, 00010000h js LeaveNow LoopEntry: cmp bx,word ptr [rsi + r8 - 1] jnz LookupLoop1 LookupLoopIsZero: cmp r12w, word ptr [r10 + r8] jnz LookupLoop1 ;;; Store the current value of chainlen. mov [chainlenwmask], edx ;;; Point edi to the string under scrutiny, and esi to the string we ;;; are hoping to match it up with. In actuality, esi and edi are ;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is ;;; initialized to -(MAX_MATCH_8 - scanalign). lea rsi,[r8+r10] mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8) lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8] lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8] prefetcht1 [rsi+rdx] prefetcht1 [rdi+rdx] ;;; Test the strings for equality, 8 bytes at a time. At the end, ;;; adjust rdx so that it is offset to the exact byte that mismatched. ;;; ;;; We already know at this point that the first three bytes of the ;;; strings match each other, and they can be safely passed over before ;;; starting the compare loop. So what this code does is skip over 0-3 ;;; bytes, as much as necessary in order to dword-align the edi ;;; pointer. (rsi will still be misaligned three times out of four.) ;;; ;;; It should be confessed that this loop usually does not represent ;;; much of the total running time. Replacing it with a more ;;; straightforward "rep cmpsb" would not drastically degrade ;;; performance. LoopCmps: mov rax, [rsi + rdx] xor rax, [rdi + rdx] jnz LeaveLoopCmps mov rax, [rsi + rdx + 8] xor rax, [rdi + rdx + 8] jnz LeaveLoopCmps8 mov rax, [rsi + rdx + 8+8] xor rax, [rdi + rdx + 8+8] jnz LeaveLoopCmps16 add rdx,8+8+8 jnz short LoopCmps jmp short LenMaximum LeaveLoopCmps16: add rdx,8 LeaveLoopCmps8: add rdx,8 LeaveLoopCmps: test eax, 0000FFFFh jnz LenLower test eax,0ffffffffh jnz LenLower32 add rdx,4 shr rax,32 or ax,ax jnz LenLower LenLower32: shr eax,16 add rdx,2 LenLower: sub al, 1 adc rdx, 0 ;;; Calculate the length of the match. If it is longer than MAX_MATCH, ;;; then automatically accept it as the best possible match and leave. lea rax, [rdi + rdx] sub rax, r9 cmp eax, MAX_MATCH jge LenMaximum ;;; If the length of the match is not longer than the best match we ;;; have so far, then forget it and return to the lookup loop. ;/////////////////////////////////// cmp eax, r11d jg LongerMatch lea rsi,[r10+r11] mov rdi, prev_ad mov edx, [chainlenwmask] jmp LookupLoop ;;; s->match_start = cur_match; ;;; best_len = len; ;;; if (len >= nice_match) break; ;;; scan_end = *(ushf*)(scan+best_len-1); LongerMatch: mov r11d, eax mov match_start, r8d cmp eax, [nicematch] jge LeaveNow lea rsi,[r10+rax] movzx ebx, word ptr [r9 + rax - 1] mov rdi, prev_ad mov edx, [chainlenwmask] jmp LookupLoop ;;; Accept the current string, with the maximum possible length. LenMaximum: mov r11d,MAX_MATCH mov match_start, r8d ;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; ;;; return s->lookahead; LeaveNow: IFDEF INFOZIP mov eax,r11d ELSE mov eax, Lookahead cmp r11d, eax cmovng eax, r11d ENDIF ;;; Restore the stack and return from whence we came. mov rsi,[save_rsi] mov rdi,[save_rdi] mov rbx,[save_rbx] mov rbp,[save_rbp] mov r12,[save_r12] mov r13,[save_r13] ; mov r14,[save_r14] ; mov r15,[save_r15] ret 0 ; please don't remove this string ! ; Your can freely use gvmat64 in any free or commercial app ; but it is far better don't remove the string in the binary! db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 longest_match ENDP match_init PROC ret 0 match_init ENDP END tcl8.6.5/compat/zlib/contrib/masmx64/bld_ml64.bat0000644000175000017500000000012612663653131021037 0ustar sergeisergeiml64.exe /Flinffasx64 /c /Zi inffasx64.asm ml64.exe /Flgvmat64 /c /Zi gvmat64.asm tcl8.6.5/compat/zlib/contrib/masmx64/readme.txt0000644000175000017500000000232512663653206020750 0ustar sergeisergeiSummary ------- This directory contains ASM implementations of the functions longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t), for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits. gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits assembly optimized version from Jean-loup Gailly original longest_match function inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing original function from Mark Adler Use instructions ---------------- Assemble the .asm files using MASM and put the object files into the zlib source directory. You can also get object files here: http://www.winimage.com/zLibDll/zlib124_masm_obj.zip define ASMV and ASMINF in your project. Include inffas8664.c in your source tree, and inffasx64.obj and gvmat64.obj as object to link. Build instructions ------------------ run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe) ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK You can get Windows 2003 server DDK with ml64 and cl for AMD64 from http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price) tcl8.6.5/compat/zlib/contrib/masmx64/inffas8664.c0000644000175000017500000001663112663653206020721 0ustar sergeisergei/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding * version for AMD64 on Windows using Microsoft C compiler * * Copyright (C) 1995-2003 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Copyright (C) 2003 Chris Anderson * Please use the copyright conditions above. * * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant * * inffas8664.c call function inffas8664fnc in inffasx64.asm * inffasx64.asm is automatically convert from AMD64 portion of inffas86.c * * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also * slightly quicker on x86 systems because, instead of using rep movsb to copy * data, it uses rep movsw, which moves data in 2-byte chunks instead of single * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates * from http://fedora.linux.duke.edu/fc1_x86_64 * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, * when decompressing mozilla-source-1.3.tar.gz. * * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at * the moment. I have successfully compiled and tested this code with gcc2.96, * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX * enabled. I will attempt to merge the MMX code into this version. Newer * versions of this and inffast.S can be found at * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ * */ #include #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" /* Mark Adler's comments from inffast.c: */ /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is available, an end-of-block is encountered, or a data error is encountered. When large enough input and output buffers are supplied to inflate(), for example, a 16K input buffer and a 64K output buffer, more than 95% of the inflate execution time is spent in this routine. Entry assumptions: state->mode == LEN strm->avail_in >= 6 strm->avail_out >= 258 start >= strm->avail_out state->bits < 8 On return, state->mode is one of: LEN -- ran out of enough output space or enough available input TYPE -- reached end of block code, inflate() to interpret next block BAD -- error in block data Notes: - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, and 13 bits for the distance extra. This totals 48 bits, or six bytes. Therefore if strm->avail_in >= 6, then there is enough input to avoid checking for available input while decoding. - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ typedef struct inffast_ar { /* 64 32 x86 x86_64 */ /* ar offset register */ /* 0 0 */ void *esp; /* esp save */ /* 8 4 */ void *ebp; /* ebp save */ /* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ /* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ /* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ /* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ /* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ /* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ /* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ /* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ /* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */ /* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ /* 92 48 */ unsigned wsize; /* window size */ /* 96 52 */ unsigned write; /* window write index */ /*100 56 */ unsigned lmask; /* r12 mask for lcode */ /*104 60 */ unsigned dmask; /* r13 mask for dcode */ /*108 64 */ unsigned len; /* r14 match length */ /*112 68 */ unsigned dist; /* r15 match distance */ /*116 72 */ unsigned status; /* set when state chng*/ } type_ar; #ifdef ASMINF void inflate_fast(strm, start) z_streamp strm; unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; type_ar ar; void inffas8664fnc(struct inffast_ar * par); #if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64)) #define PAD_AVAIL_IN 6 #define PAD_AVAIL_OUT 258 #else #define PAD_AVAIL_IN 5 #define PAD_AVAIL_OUT 257 #endif /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; ar.in = strm->next_in; ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); ar.out = strm->next_out; ar.beg = ar.out - (start - strm->avail_out); ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); ar.wsize = state->wsize; ar.write = state->wnext; ar.window = state->window; ar.hold = state->hold; ar.bits = state->bits; ar.lcode = state->lencode; ar.dcode = state->distcode; ar.lmask = (1U << state->lenbits) - 1; ar.dmask = (1U << state->distbits) - 1; /* decode literals and length/distances until end-of-block or not enough input data or output space */ /* align in on 1/2 hold size boundary */ while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { ar.hold += (unsigned long)*ar.in++ << ar.bits; ar.bits += 8; } inffas8664fnc(&ar); if (ar.status > 1) { if (ar.status == 2) strm->msg = "invalid literal/length code"; else if (ar.status == 3) strm->msg = "invalid distance code"; else strm->msg = "invalid distance too far back"; state->mode = BAD; } else if ( ar.status == 1 ) { state->mode = TYPE; } /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ ar.len = ar.bits >> 3; ar.in -= ar.len; ar.bits -= ar.len << 3; ar.hold &= (1U << ar.bits) - 1; /* update state and return */ strm->next_in = ar.in; strm->next_out = ar.out; strm->avail_in = (unsigned)(ar.in < ar.last ? PAD_AVAIL_IN + (ar.last - ar.in) : PAD_AVAIL_IN - (ar.in - ar.last)); strm->avail_out = (unsigned)(ar.out < ar.end ? PAD_AVAIL_OUT + (ar.end - ar.out) : PAD_AVAIL_OUT - (ar.out - ar.end)); state->hold = (unsigned long)ar.hold; state->bits = ar.bits; return; } #endif tcl8.6.5/compat/zlib/contrib/untgz/0000755000175000017500000000000012665173607016624 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/untgz/Makefile.msc0000644000175000017500000000043112663653131021034 0ustar sergeisergeiCC=cl CFLAGS=-MD untgz.exe: untgz.obj ..\..\zlib.lib $(CC) $(CFLAGS) untgz.obj ..\..\zlib.lib untgz.obj: untgz.c ..\..\zlib.h $(CC) $(CFLAGS) -c -I..\.. untgz.c ..\..\zlib.lib: cd ..\.. $(MAKE) -f win32\makefile.msc cd contrib\untgz clean: -del untgz.obj -del untgz.exe tcl8.6.5/compat/zlib/contrib/untgz/Makefile0000644000175000017500000000035212663653131020255 0ustar sergeisergeiCC=cc CFLAGS=-g untgz: untgz.o ../../libz.a $(CC) $(CFLAGS) -o untgz untgz.o -L../.. -lz untgz.o: untgz.c ../../zlib.h $(CC) $(CFLAGS) -c -I../.. untgz.c ../../libz.a: cd ../..; ./configure; make clean: rm -f untgz untgz.o *~ tcl8.6.5/compat/zlib/contrib/untgz/untgz.c0000644000175000017500000004023612663653131020135 0ustar sergeisergei/* * untgz.c -- Display contents and extract files from a gzip'd TAR file * * written by Pedro A. Aranda Gutierrez * adaptation to Unix by Jean-loup Gailly * various fixes by Cosmin Truta */ #include #include #include #include #include #include "zlib.h" #ifdef unix # include #else # include # include #endif #ifdef WIN32 #include # ifndef F_OK # define F_OK 0 # endif # define mkdir(dirname,mode) _mkdir(dirname) # ifdef _MSC_VER # define access(path,mode) _access(path,mode) # define chmod(path,mode) _chmod(path,mode) # define strdup(str) _strdup(str) # endif #else # include #endif /* values used in typeflag field */ #define REGTYPE '0' /* regular file */ #define AREGTYPE '\0' /* regular file */ #define LNKTYPE '1' /* link */ #define SYMTYPE '2' /* reserved */ #define CHRTYPE '3' /* character special */ #define BLKTYPE '4' /* block special */ #define DIRTYPE '5' /* directory */ #define FIFOTYPE '6' /* FIFO special */ #define CONTTYPE '7' /* reserved */ /* GNU tar extensions */ #define GNUTYPE_DUMPDIR 'D' /* file names from dumped directory */ #define GNUTYPE_LONGLINK 'K' /* long link name */ #define GNUTYPE_LONGNAME 'L' /* long file name */ #define GNUTYPE_MULTIVOL 'M' /* continuation of file from another volume */ #define GNUTYPE_NAMES 'N' /* file name that does not fit into main hdr */ #define GNUTYPE_SPARSE 'S' /* sparse file */ #define GNUTYPE_VOLHDR 'V' /* tape/volume header */ /* tar header */ #define BLOCKSIZE 512 #define SHORTNAMESIZE 100 struct tar_header { /* byte offset */ char name[100]; /* 0 */ char mode[8]; /* 100 */ char uid[8]; /* 108 */ char gid[8]; /* 116 */ char size[12]; /* 124 */ char mtime[12]; /* 136 */ char chksum[8]; /* 148 */ char typeflag; /* 156 */ char linkname[100]; /* 157 */ char magic[6]; /* 257 */ char version[2]; /* 263 */ char uname[32]; /* 265 */ char gname[32]; /* 297 */ char devmajor[8]; /* 329 */ char devminor[8]; /* 337 */ char prefix[155]; /* 345 */ /* 500 */ }; union tar_buffer { char buffer[BLOCKSIZE]; struct tar_header header; }; struct attr_item { struct attr_item *next; char *fname; int mode; time_t time; }; enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID }; char *TGZfname OF((const char *)); void TGZnotfound OF((const char *)); int getoct OF((char *, int)); char *strtime OF((time_t *)); int setfiletime OF((char *, time_t)); void push_attr OF((struct attr_item **, char *, int, time_t)); void restore_attr OF((struct attr_item **)); int ExprMatch OF((char *, char *)); int makedir OF((char *)); int matchname OF((int, int, char **, char *)); void error OF((const char *)); int tar OF((gzFile, int, int, int, char **)); void help OF((int)); int main OF((int, char **)); char *prog; const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL }; /* return the file name of the TGZ archive */ /* or NULL if it does not exist */ char *TGZfname (const char *arcname) { static char buffer[1024]; int origlen,i; strcpy(buffer,arcname); origlen = strlen(buffer); for (i=0; TGZsuffix[i]; i++) { strcpy(buffer+origlen,TGZsuffix[i]); if (access(buffer,F_OK) == 0) return buffer; } return NULL; } /* error message for the filename */ void TGZnotfound (const char *arcname) { int i; fprintf(stderr,"%s: Couldn't find ",prog); for (i=0;TGZsuffix[i];i++) fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n", arcname, TGZsuffix[i]); exit(1); } /* convert octal digits to int */ /* on error return -1 */ int getoct (char *p,int width) { int result = 0; char c; while (width--) { c = *p++; if (c == 0) break; if (c == ' ') continue; if (c < '0' || c > '7') return -1; result = result * 8 + (c - '0'); } return result; } /* convert time_t to string */ /* use the "YYYY/MM/DD hh:mm:ss" format */ char *strtime (time_t *t) { struct tm *local; static char result[32]; local = localtime(t); sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d", local->tm_year+1900, local->tm_mon+1, local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec); return result; } /* set file time */ int setfiletime (char *fname,time_t ftime) { #ifdef WIN32 static int isWinNT = -1; SYSTEMTIME st; FILETIME locft, modft; struct tm *loctm; HANDLE hFile; int result; loctm = localtime(&ftime); if (loctm == NULL) return -1; st.wYear = (WORD)loctm->tm_year + 1900; st.wMonth = (WORD)loctm->tm_mon + 1; st.wDayOfWeek = (WORD)loctm->tm_wday; st.wDay = (WORD)loctm->tm_mday; st.wHour = (WORD)loctm->tm_hour; st.wMinute = (WORD)loctm->tm_min; st.wSecond = (WORD)loctm->tm_sec; st.wMilliseconds = 0; if (!SystemTimeToFileTime(&st, &locft) || !LocalFileTimeToFileTime(&locft, &modft)) return -1; if (isWinNT < 0) isWinNT = (GetVersion() < 0x80000000) ? 1 : 0; hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0), NULL); if (hFile == INVALID_HANDLE_VALUE) return -1; result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1; CloseHandle(hFile); return result; #else struct utimbuf settime; settime.actime = settime.modtime = ftime; return utime(fname,&settime); #endif } /* push file attributes */ void push_attr(struct attr_item **list,char *fname,int mode,time_t time) { struct attr_item *item; item = (struct attr_item *)malloc(sizeof(struct attr_item)); if (item == NULL) error("Out of memory"); item->fname = strdup(fname); item->mode = mode; item->time = time; item->next = *list; *list = item; } /* restore file attributes */ void restore_attr(struct attr_item **list) { struct attr_item *item, *prev; for (item = *list; item != NULL; ) { setfiletime(item->fname,item->time); chmod(item->fname,item->mode); prev = item; item = item->next; free(prev); } *list = NULL; } /* match regular expression */ #define ISSPECIAL(c) (((c) == '*') || ((c) == '/')) int ExprMatch (char *string,char *expr) { while (1) { if (ISSPECIAL(*expr)) { if (*expr == '/') { if (*string != '\\' && *string != '/') return 0; string ++; expr++; } else if (*expr == '*') { if (*expr ++ == 0) return 1; while (*++string != *expr) if (*string == 0) return 0; } } else { if (*string != *expr) return 0; if (*expr++ == 0) return 1; string++; } } } /* recursive mkdir */ /* abort on ENOENT; ignore other errors like "directory already exists" */ /* return 1 if OK */ /* 0 on error */ int makedir (char *newdir) { char *buffer = strdup(newdir); char *p; int len = strlen(buffer); if (len <= 0) { free(buffer); return 0; } if (buffer[len-1] == '/') { buffer[len-1] = '\0'; } if (mkdir(buffer, 0755) == 0) { free(buffer); return 1; } p = buffer+1; while (1) { char hold; while(*p && *p != '\\' && *p != '/') p++; hold = *p; *p = 0; if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT)) { fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer); free(buffer); return 0; } if (hold == 0) break; *p++ = hold; } free(buffer); return 1; } int matchname (int arg,int argc,char **argv,char *fname) { if (arg == argc) /* no arguments given (untgz tgzarchive) */ return 1; while (arg < argc) if (ExprMatch(fname,argv[arg++])) return 1; return 0; /* ignore this for the moment being */ } /* tar file list or extract */ int tar (gzFile in,int action,int arg,int argc,char **argv) { union tar_buffer buffer; int len; int err; int getheader = 1; int remaining = 0; FILE *outfile = NULL; char fname[BLOCKSIZE]; int tarmode; time_t tartime; struct attr_item *attributes = NULL; if (action == TGZ_LIST) printf(" date time size file\n" " ---------- -------- --------- -------------------------------------\n"); while (1) { len = gzread(in, &buffer, BLOCKSIZE); if (len < 0) error(gzerror(in, &err)); /* * Always expect complete blocks to process * the tar information. */ if (len != BLOCKSIZE) { action = TGZ_INVALID; /* force error exit */ remaining = 0; /* force I/O cleanup */ } /* * If we have to get a tar header */ if (getheader >= 1) { /* * if we met the end of the tar * or the end-of-tar block, * we are done */ if (len == 0 || buffer.header.name[0] == 0) break; tarmode = getoct(buffer.header.mode,8); tartime = (time_t)getoct(buffer.header.mtime,12); if (tarmode == -1 || tartime == (time_t)-1) { buffer.header.name[0] = 0; action = TGZ_INVALID; } if (getheader == 1) { strncpy(fname,buffer.header.name,SHORTNAMESIZE); if (fname[SHORTNAMESIZE-1] != 0) fname[SHORTNAMESIZE] = 0; } else { /* * The file name is longer than SHORTNAMESIZE */ if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0) error("bad long name"); getheader = 1; } /* * Act according to the type flag */ switch (buffer.header.typeflag) { case DIRTYPE: if (action == TGZ_LIST) printf(" %s %s\n",strtime(&tartime),fname); if (action == TGZ_EXTRACT) { makedir(fname); push_attr(&attributes,fname,tarmode,tartime); } break; case REGTYPE: case AREGTYPE: remaining = getoct(buffer.header.size,12); if (remaining == -1) { action = TGZ_INVALID; break; } if (action == TGZ_LIST) printf(" %s %9d %s\n",strtime(&tartime),remaining,fname); else if (action == TGZ_EXTRACT) { if (matchname(arg,argc,argv,fname)) { outfile = fopen(fname,"wb"); if (outfile == NULL) { /* try creating directory */ char *p = strrchr(fname, '/'); if (p != NULL) { *p = '\0'; makedir(fname); *p = '/'; outfile = fopen(fname,"wb"); } } if (outfile != NULL) printf("Extracting %s\n",fname); else fprintf(stderr, "%s: Couldn't create %s",prog,fname); } else outfile = NULL; } getheader = 0; break; case GNUTYPE_LONGLINK: case GNUTYPE_LONGNAME: remaining = getoct(buffer.header.size,12); if (remaining < 0 || remaining >= BLOCKSIZE) { action = TGZ_INVALID; break; } len = gzread(in, fname, BLOCKSIZE); if (len < 0) error(gzerror(in, &err)); if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining) { action = TGZ_INVALID; break; } getheader = 2; break; default: if (action == TGZ_LIST) printf(" %s <---> %s\n",strtime(&tartime),fname); break; } } else { unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining; if (outfile != NULL) { if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes) { fprintf(stderr, "%s: Error writing %s -- skipping\n",prog,fname); fclose(outfile); outfile = NULL; remove(fname); } } remaining -= bytes; } if (remaining == 0) { getheader = 1; if (outfile != NULL) { fclose(outfile); outfile = NULL; if (action != TGZ_INVALID) push_attr(&attributes,fname,tarmode,tartime); } } /* * Abandon if errors are found */ if (action == TGZ_INVALID) { error("broken archive"); break; } } /* * Restore file modes and time stamps */ restore_attr(&attributes); if (gzclose(in) != Z_OK) error("failed gzclose"); return 0; } /* ============================================================ */ void help(int exitval) { printf("untgz version 0.2.1\n" " using zlib version %s\n\n", zlibVersion()); printf("Usage: untgz file.tgz extract all files\n" " untgz file.tgz fname ... extract selected files\n" " untgz -l file.tgz list archive contents\n" " untgz -h display this help\n"); exit(exitval); } void error(const char *msg) { fprintf(stderr, "%s: %s\n", prog, msg); exit(1); } /* ============================================================ */ #if defined(WIN32) && defined(__GNUC__) int _CRT_glob = 0; /* disable argument globbing in MinGW */ #endif int main(int argc,char **argv) { int action = TGZ_EXTRACT; int arg = 1; char *TGZfile; gzFile *f; prog = strrchr(argv[0],'\\'); if (prog == NULL) { prog = strrchr(argv[0],'/'); if (prog == NULL) { prog = strrchr(argv[0],':'); if (prog == NULL) prog = argv[0]; else prog++; } else prog++; } else prog++; if (argc == 1) help(0); if (strcmp(argv[arg],"-l") == 0) { action = TGZ_LIST; if (argc == ++arg) help(0); } else if (strcmp(argv[arg],"-h") == 0) { help(0); } if ((TGZfile = TGZfname(argv[arg])) == NULL) TGZnotfound(argv[arg]); ++arg; if ((action == TGZ_LIST) && (arg != argc)) help(1); /* * Process the TGZ file */ switch(action) { case TGZ_LIST: case TGZ_EXTRACT: f = gzopen(TGZfile,"rb"); if (f == NULL) { fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile); return 1; } exit(tar(f, action, arg, argc, argv)); break; default: error("Unknown option"); exit(1); } return 0; } tcl8.6.5/compat/zlib/contrib/minizip/0000755000175000017500000000000012665173607017134 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/minizip/MiniZip64_Changes.txt0000644000175000017500000000015512663653206023053 0ustar sergeisergei MiniZip 1.1 was derrived from MiniZip at version 1.01f Change in 1.0 (Okt 2009) - **TODO - Add history** tcl8.6.5/compat/zlib/contrib/minizip/mztools.c0000644000175000017500000001772212663660064021014 0ustar sergeisergei/* Additional tools for Minizip Code: Xavier Roche '2004 License: Same as ZLIB (www.gzip.org) */ /* Code */ #include #include #include #include "zlib.h" #include "unzip.h" #define READ_8(adr) ((unsigned char)*(adr)) #define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) #define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) #define WRITE_8(buff, n) do { \ *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ } while(0) #define WRITE_16(buff, n) do { \ WRITE_8((unsigned char*)(buff), n); \ WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ } while(0) #define WRITE_32(buff, n) do { \ WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ } while(0) extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) const char* file; const char* fileOut; const char* fileOutTmp; uLong* nRecovered; uLong* bytesRecovered; { int err = Z_OK; FILE* fpZip = fopen(file, "rb"); FILE* fpOut = fopen(fileOut, "wb"); FILE* fpOutCD = fopen(fileOutTmp, "wb"); if (fpZip != NULL && fpOut != NULL) { int entries = 0; uLong totalBytes = 0; char header[30]; char filename[1024]; char extra[1024]; int offset = 0; int offsetCD = 0; while ( fread(header, 1, 30, fpZip) == 30 ) { int currentOffset = offset; /* File entry */ if (READ_32(header) == 0x04034b50) { unsigned int version = READ_16(header + 4); unsigned int gpflag = READ_16(header + 6); unsigned int method = READ_16(header + 8); unsigned int filetime = READ_16(header + 10); unsigned int filedate = READ_16(header + 12); unsigned int crc = READ_32(header + 14); /* crc */ unsigned int cpsize = READ_32(header + 18); /* compressed size */ unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ unsigned int fnsize = READ_16(header + 26); /* file name length */ unsigned int extsize = READ_16(header + 28); /* extra field length */ filename[0] = extra[0] = '\0'; /* Header */ if (fwrite(header, 1, 30, fpOut) == 30) { offset += 30; } else { err = Z_ERRNO; break; } /* Filename */ if (fnsize > 0) { if (fnsize < sizeof(filename)) { if (fread(filename, 1, fnsize, fpZip) == fnsize) { if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { offset += fnsize; } else { err = Z_ERRNO; break; } } else { err = Z_ERRNO; break; } } else { err = Z_ERRNO; break; } } else { err = Z_STREAM_ERROR; break; } /* Extra field */ if (extsize > 0) { if (extsize < sizeof(extra)) { if (fread(extra, 1, extsize, fpZip) == extsize) { if (fwrite(extra, 1, extsize, fpOut) == extsize) { offset += extsize; } else { err = Z_ERRNO; break; } } else { err = Z_ERRNO; break; } } else { err = Z_ERRNO; break; } } /* Data */ { int dataSize = cpsize; if (dataSize == 0) { dataSize = uncpsize; } if (dataSize > 0) { char* data = malloc(dataSize); if (data != NULL) { if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { offset += dataSize; totalBytes += dataSize; } else { err = Z_ERRNO; } } else { err = Z_ERRNO; } free(data); if (err != Z_OK) { break; } } else { err = Z_MEM_ERROR; break; } } } /* Central directory entry */ { char header[46]; char* comment = ""; int comsize = (int) strlen(comment); WRITE_32(header, 0x02014b50); WRITE_16(header + 4, version); WRITE_16(header + 6, version); WRITE_16(header + 8, gpflag); WRITE_16(header + 10, method); WRITE_16(header + 12, filetime); WRITE_16(header + 14, filedate); WRITE_32(header + 16, crc); WRITE_32(header + 20, cpsize); WRITE_32(header + 24, uncpsize); WRITE_16(header + 28, fnsize); WRITE_16(header + 30, extsize); WRITE_16(header + 32, comsize); WRITE_16(header + 34, 0); /* disk # */ WRITE_16(header + 36, 0); /* int attrb */ WRITE_32(header + 38, 0); /* ext attrb */ WRITE_32(header + 42, currentOffset); /* Header */ if (fwrite(header, 1, 46, fpOutCD) == 46) { offsetCD += 46; /* Filename */ if (fnsize > 0) { if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { offsetCD += fnsize; } else { err = Z_ERRNO; break; } } else { err = Z_STREAM_ERROR; break; } /* Extra field */ if (extsize > 0) { if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { offsetCD += extsize; } else { err = Z_ERRNO; break; } } /* Comment field */ if (comsize > 0) { if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { offsetCD += comsize; } else { err = Z_ERRNO; break; } } } else { err = Z_ERRNO; break; } } /* Success */ entries++; } else { break; } } /* Final central directory */ { int entriesZip = entries; char header[22]; char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; int comsize = (int) strlen(comment); if (entriesZip > 0xffff) { entriesZip = 0xffff; } WRITE_32(header, 0x06054b50); WRITE_16(header + 4, 0); /* disk # */ WRITE_16(header + 6, 0); /* disk # */ WRITE_16(header + 8, entriesZip); /* hack */ WRITE_16(header + 10, entriesZip); /* hack */ WRITE_32(header + 12, offsetCD); /* size of CD */ WRITE_32(header + 16, offset); /* offset to CD */ WRITE_16(header + 20, comsize); /* comment */ /* Header */ if (fwrite(header, 1, 22, fpOutCD) == 22) { /* Comment field */ if (comsize > 0) { if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { err = Z_ERRNO; } } } else { err = Z_ERRNO; } } /* Final merge (file + central directory) */ fclose(fpOutCD); if (err == Z_OK) { fpOutCD = fopen(fileOutTmp, "rb"); if (fpOutCD != NULL) { int nRead; char buffer[8192]; while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { err = Z_ERRNO; break; } } fclose(fpOutCD); } } /* Close */ fclose(fpZip); fclose(fpOut); /* Wipe temporary file */ (void)remove(fileOutTmp); /* Number of recovered entries */ if (err == Z_OK) { if (nRecovered != NULL) { *nRecovered = entries; } if (bytesRecovered != NULL) { *bytesRecovered = totalBytes; } } } else { err = Z_STREAM_ERROR; } return err; } tcl8.6.5/compat/zlib/contrib/minizip/mztools.h0000644000175000017500000000130412663660064021006 0ustar sergeisergei/* Additional tools for Minizip Code: Xavier Roche '2004 License: Same as ZLIB (www.gzip.org) */ #ifndef _zip_tools_H #define _zip_tools_H #ifdef __cplusplus extern "C" { #endif #ifndef _ZLIB_H #include "zlib.h" #endif #include "unzip.h" /* Repair a ZIP file (missing central directory) file: file to recover fileOut: output file after recovery fileOutTmp: temporary file name used for recovery */ extern int ZEXPORT unzRepair(const char* file, const char* fileOut, const char* fileOutTmp, uLong* nRecovered, uLong* bytesRecovered); #ifdef __cplusplus } #endif #endif tcl8.6.5/compat/zlib/contrib/minizip/Makefile.am0000644000175000017500000000146212663660064021167 0ustar sergeisergeilib_LTLIBRARIES = libminizip.la if COND_DEMOS bin_PROGRAMS = miniunzip minizip endif zlib_top_srcdir = $(top_srcdir)/../.. zlib_top_builddir = $(top_builddir)/../.. AM_CPPFLAGS = -I$(zlib_top_srcdir) AM_LDFLAGS = -L$(zlib_top_builddir) if WIN32 iowin32_src = iowin32.c iowin32_h = iowin32.h endif libminizip_la_SOURCES = \ ioapi.c \ mztools.c \ unzip.c \ zip.c \ ${iowin32_src} libminizip_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0 -lz minizip_includedir = $(includedir)/minizip minizip_include_HEADERS = \ crypt.h \ ioapi.h \ mztools.h \ unzip.h \ zip.h \ ${iowin32_h} pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = minizip.pc EXTRA_PROGRAMS = miniunzip minizip miniunzip_SOURCES = miniunz.c miniunzip_LDADD = libminizip.la minizip_SOURCES = minizip.c minizip_LDADD = libminizip.la -lz tcl8.6.5/compat/zlib/contrib/minizip/unzip.h0000644000175000017500000003774012663660064020461 0ustar sergeisergei/* unzip.h -- IO for uncompress .zip files using zlib Version 1.1, February 14h, 2010 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications of Unzip for Zip64 Copyright (C) 2007-2008 Even Rouault Modifications for Zip64 support on both zip and unzip Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt --------------------------------------------------------------------------------- Condition of use and distribution are the same than zlib : This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. --------------------------------------------------------------------------------- Changes See header of unzip64.c */ #ifndef _unz64_H #define _unz64_H #ifdef __cplusplus extern "C" { #endif #ifndef _ZLIB_H #include "zlib.h" #endif #ifndef _ZLIBIOAPI_H #include "ioapi.h" #endif #ifdef HAVE_BZIP2 #include "bzlib.h" #endif #define Z_BZIP2ED 12 #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) /* like the STRICT of WIN32, we define a pointer that cannot be converted from (void*) without cast */ typedef struct TagunzFile__ { int unused; } unzFile__; typedef unzFile__ *unzFile; #else typedef voidp unzFile; #endif #define UNZ_OK (0) #define UNZ_END_OF_LIST_OF_FILE (-100) #define UNZ_ERRNO (Z_ERRNO) #define UNZ_EOF (0) #define UNZ_PARAMERROR (-102) #define UNZ_BADZIPFILE (-103) #define UNZ_INTERNALERROR (-104) #define UNZ_CRCERROR (-105) /* tm_unz contain date/time info */ typedef struct tm_unz_s { uInt tm_sec; /* seconds after the minute - [0,59] */ uInt tm_min; /* minutes after the hour - [0,59] */ uInt tm_hour; /* hours since midnight - [0,23] */ uInt tm_mday; /* day of the month - [1,31] */ uInt tm_mon; /* months since January - [0,11] */ uInt tm_year; /* years - [1980..2044] */ } tm_unz; /* unz_global_info structure contain global data about the ZIPfile These data comes from the end of central dir */ typedef struct unz_global_info64_s { ZPOS64_T number_entry; /* total number of entries in the central dir on this disk */ uLong size_comment; /* size of the global comment of the zipfile */ } unz_global_info64; typedef struct unz_global_info_s { uLong number_entry; /* total number of entries in the central dir on this disk */ uLong size_comment; /* size of the global comment of the zipfile */ } unz_global_info; /* unz_file_info contain information about a file in the zipfile */ typedef struct unz_file_info64_s { uLong version; /* version made by 2 bytes */ uLong version_needed; /* version needed to extract 2 bytes */ uLong flag; /* general purpose bit flag 2 bytes */ uLong compression_method; /* compression method 2 bytes */ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ uLong crc; /* crc-32 4 bytes */ ZPOS64_T compressed_size; /* compressed size 8 bytes */ ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ uLong size_filename; /* filename length 2 bytes */ uLong size_file_extra; /* extra field length 2 bytes */ uLong size_file_comment; /* file comment length 2 bytes */ uLong disk_num_start; /* disk number start 2 bytes */ uLong internal_fa; /* internal file attributes 2 bytes */ uLong external_fa; /* external file attributes 4 bytes */ tm_unz tmu_date; } unz_file_info64; typedef struct unz_file_info_s { uLong version; /* version made by 2 bytes */ uLong version_needed; /* version needed to extract 2 bytes */ uLong flag; /* general purpose bit flag 2 bytes */ uLong compression_method; /* compression method 2 bytes */ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ uLong crc; /* crc-32 4 bytes */ uLong compressed_size; /* compressed size 4 bytes */ uLong uncompressed_size; /* uncompressed size 4 bytes */ uLong size_filename; /* filename length 2 bytes */ uLong size_file_extra; /* extra field length 2 bytes */ uLong size_file_comment; /* file comment length 2 bytes */ uLong disk_num_start; /* disk number start 2 bytes */ uLong internal_fa; /* internal file attributes 2 bytes */ uLong external_fa; /* external file attributes 4 bytes */ tm_unz tmu_date; } unz_file_info; extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, const char* fileName2, int iCaseSensitivity)); /* Compare two filename (fileName1,fileName2). If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp) If iCaseSenisivity = 0, case sensitivity is defaut of your operating system (like 1 on Unix, 2 on Windows) */ extern unzFile ZEXPORT unzOpen OF((const char *path)); extern unzFile ZEXPORT unzOpen64 OF((const void *path)); /* Open a Zip file. path contain the full pathname (by example, on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer "zlib/zlib113.zip". If the zipfile cannot be opened (file don't exist or in not valid), the return value is NULL. Else, the return value is a unzFile Handle, usable with other function of this unzip package. the "64" function take a const void* pointer, because the path is just the value passed to the open64_file_func callback. Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* does not describe the reality */ extern unzFile ZEXPORT unzOpen2 OF((const char *path, zlib_filefunc_def* pzlib_filefunc_def)); /* Open a Zip file, like unzOpen, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, zlib_filefunc64_def* pzlib_filefunc_def)); /* Open a Zip file, like unz64Open, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ extern int ZEXPORT unzClose OF((unzFile file)); /* Close a ZipFile opened with unzOpen. If there is files inside the .Zip opened with unzOpenCurrentFile (see later), these files MUST be closed with unzCloseCurrentFile before call unzClose. return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, unz_global_info *pglobal_info)); extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, unz_global_info64 *pglobal_info)); /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalComment OF((unzFile file, char *szComment, uLong uSizeBuf)); /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ /***************************************************************************/ /* Unzip package allow you browse the directory of the zipfile */ extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ extern int ZEXPORT unzGoToNextFile OF((unzFile file)); /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ extern int ZEXPORT unzLocateFile OF((unzFile file, const char *szFileName, int iCaseSensitivity)); /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzStringFileNameCompare return value : UNZ_OK if the file is found. It becomes the current file. UNZ_END_OF_LIST_OF_FILE if the file is not found */ /* ****************************************** */ /* Ryan supplied functions */ /* unz_file_info contain information about a file in the zipfile */ typedef struct unz_file_pos_s { uLong pos_in_zip_directory; /* offset in zip file directory */ uLong num_of_file; /* # of file */ } unz_file_pos; extern int ZEXPORT unzGetFilePos( unzFile file, unz_file_pos* file_pos); extern int ZEXPORT unzGoToFilePos( unzFile file, unz_file_pos* file_pos); typedef struct unz64_file_pos_s { ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ ZPOS64_T num_of_file; /* # of file */ } unz64_file_pos; extern int ZEXPORT unzGetFilePos64( unzFile file, unz64_file_pos* file_pos); extern int ZEXPORT unzGoToFilePos64( unzFile file, const unz64_file_pos* file_pos); /* ****************************************** */ extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, unz_file_info64 *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)); extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, unz_file_info *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)); /* Get Info about the current file if pfile_info!=NULL, the *pfile_info structure will contain somes info about the current file if szFileName!=NULL, the filemane string will be copied in szFileName (fileNameBufferSize is the size of the buffer) if extraField!=NULL, the extra field information will be copied in extraField (extraFieldBufferSize is the size of the buffer). This is the Central-header version of the extra field if szComment!=NULL, the comment string of the file will be copied in szComment (commentBufferSize is the size of the buffer) */ /** Addition for GDAL : START */ extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); /** Addition for GDAL : END */ /***************************************************************************/ /* for reading the content of the current zipfile, you can open it, read data from it, and close it (you can close it before reading all the file) */ extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); /* Open for reading data the current file in the zipfile. If there is no error, the return value is UNZ_OK. */ extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, const char* password)); /* Open for reading data the current file in the zipfile. password is a crypting password If there is no error, the return value is UNZ_OK. */ extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, int* method, int* level, int raw)); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 *method will receive method of compression, *level will receive level of compression note : you can set level parameter as NULL (if you did not want known level, but you CANNOT set method parameter as NULL */ extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, int* method, int* level, int raw, const char* password)); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 *method will receive method of compression, *level will receive level of compression note : you can set level parameter as NULL (if you did not want known level, but you CANNOT set method parameter as NULL */ extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); /* Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ extern int ZEXPORT unzReadCurrentFile OF((unzFile file, voidp buf, unsigned len)); /* Read bytes from the current file (opened by unzOpenCurrentFile) buf contain buffer where data must be copied len the size of buf. return the number of byte copied if somes bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ extern z_off_t ZEXPORT unztell OF((unzFile file)); extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); /* Give the current position in uncompressed data */ extern int ZEXPORT unzeof OF((unzFile file)); /* return 1 if the end of file was reached, 0 elsewhere */ extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, voidp buf, unsigned len)); /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is more info in the local-header version than in the central-header) if buf==NULL, it return the size of the local extra field if buf!=NULL, len is the size of the buffer, the extra header is copied in buf. the return value is the number of bytes copied in buf, or (if <0) the error code */ /***************************************************************************/ /* Get the current file offset */ extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); extern uLong ZEXPORT unzGetOffset (unzFile file); /* Set the current file offset */ extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); #ifdef __cplusplus } #endif #endif /* _unz64_H */ tcl8.6.5/compat/zlib/contrib/minizip/iowin32.c0000644000175000017500000003350412663660064020573 0ustar sergeisergei/* iowin32.c -- IO base function header for compress/uncompress .zip Version 1.1, February 14h, 2010 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt */ #include #include "zlib.h" #include "ioapi.h" #include "iowin32.h" #ifndef INVALID_HANDLE_VALUE #define INVALID_HANDLE_VALUE (0xFFFFFFFF) #endif #ifndef INVALID_SET_FILE_POINTER #define INVALID_SET_FILE_POINTER ((DWORD)-1) #endif #if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API))) #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) #define IOWIN32_USING_WINRT_API 1 #endif #endif voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); uLong ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); ZPOS64_T ZCALLBACK win32_tell64_file_func OF((voidpf opaque, voidpf stream)); long ZCALLBACK win32_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); int ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream)); int ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream)); typedef struct { HANDLE hf; int error; } WIN32FILE_IOWIN; static void win32_translate_open_mode(int mode, DWORD* lpdwDesiredAccess, DWORD* lpdwCreationDisposition, DWORD* lpdwShareMode, DWORD* lpdwFlagsAndAttributes) { *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0; if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) { *lpdwDesiredAccess = GENERIC_READ; *lpdwCreationDisposition = OPEN_EXISTING; *lpdwShareMode = FILE_SHARE_READ; } else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) { *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; *lpdwCreationDisposition = OPEN_EXISTING; } else if (mode & ZLIB_FILEFUNC_MODE_CREATE) { *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; *lpdwCreationDisposition = CREATE_ALWAYS; } } static voidpf win32_build_iowin(HANDLE hFile) { voidpf ret=NULL; if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) { WIN32FILE_IOWIN w32fiow; w32fiow.hf = hFile; w32fiow.error = 0; ret = malloc(sizeof(WIN32FILE_IOWIN)); if (ret==NULL) CloseHandle(hFile); else *((WIN32FILE_IOWIN*)ret) = w32fiow; } return ret; } voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); #ifdef IOWIN32_USING_WINRT_API #ifdef UNICODE if ((filename!=NULL) && (dwDesiredAccess != 0)) hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); #else if ((filename!=NULL) && (dwDesiredAccess != 0)) { WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); } #endif #else if ((filename!=NULL) && (dwDesiredAccess != 0)) hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); #endif return win32_build_iowin(hFile); } voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); #ifdef IOWIN32_USING_WINRT_API if ((filename!=NULL) && (dwDesiredAccess != 0)) { WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); } #else if ((filename!=NULL) && (dwDesiredAccess != 0)) hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); #endif return win32_build_iowin(hFile); } voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); #ifdef IOWIN32_USING_WINRT_API if ((filename!=NULL) && (dwDesiredAccess != 0)) hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition,NULL); #else if ((filename!=NULL) && (dwDesiredAccess != 0)) hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); #endif return win32_build_iowin(hFile); } voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); #ifdef IOWIN32_USING_WINRT_API #ifdef UNICODE if ((filename!=NULL) && (dwDesiredAccess != 0)) hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); #else if ((filename!=NULL) && (dwDesiredAccess != 0)) { WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); } #endif #else if ((filename!=NULL) && (dwDesiredAccess != 0)) hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); #endif return win32_build_iowin(hFile); } uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) { uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; if (hFile != NULL) { if (!ReadFile(hFile, buf, size, &ret, NULL)) { DWORD dwErr = GetLastError(); if (dwErr == ERROR_HANDLE_EOF) dwErr = 0; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; } } return ret; } uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) { uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; if (hFile != NULL) { if (!WriteFile(hFile, buf, size, &ret, NULL)) { DWORD dwErr = GetLastError(); if (dwErr == ERROR_HANDLE_EOF) dwErr = 0; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; } } return ret; } static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) { #ifdef IOWIN32_USING_WINRT_API return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod); #else LONG lHigh = pos.HighPart; DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, FILE_CURRENT); BOOL fOk = TRUE; if (dwNewPos == 0xFFFFFFFF) if (GetLastError() != NO_ERROR) fOk = FALSE; if ((newPos != NULL) && (fOk)) { newPos->LowPart = dwNewPos; newPos->HighPart = lHigh; } return fOk; #endif } long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) { long ret=-1; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; if (hFile != NULL) { LARGE_INTEGER pos; pos.QuadPart = 0; if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) { DWORD dwErr = GetLastError(); ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ret = -1; } else ret=(long)pos.LowPart; } return ret; } ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) { ZPOS64_T ret= (ZPOS64_T)-1; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream)->hf; if (hFile) { LARGE_INTEGER pos; pos.QuadPart = 0; if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) { DWORD dwErr = GetLastError(); ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ret = (ZPOS64_T)-1; } else ret=pos.QuadPart; } return ret; } long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin) { DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; long ret=-1; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR : dwMoveMethod = FILE_CURRENT; break; case ZLIB_FILEFUNC_SEEK_END : dwMoveMethod = FILE_END; break; case ZLIB_FILEFUNC_SEEK_SET : dwMoveMethod = FILE_BEGIN; break; default: return -1; } if (hFile != NULL) { LARGE_INTEGER pos; pos.QuadPart = offset; if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) { DWORD dwErr = GetLastError(); ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ret = -1; } else ret=0; } return ret; } long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) { DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; long ret=-1; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream)->hf; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR : dwMoveMethod = FILE_CURRENT; break; case ZLIB_FILEFUNC_SEEK_END : dwMoveMethod = FILE_END; break; case ZLIB_FILEFUNC_SEEK_SET : dwMoveMethod = FILE_BEGIN; break; default: return -1; } if (hFile) { LARGE_INTEGER pos; pos.QuadPart = offset; if (!MySetFilePointerEx(hFile, pos, NULL, FILE_CURRENT)) { DWORD dwErr = GetLastError(); ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ret = -1; } else ret=0; } return ret; } int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) { int ret=-1; if (stream!=NULL) { HANDLE hFile; hFile = ((WIN32FILE_IOWIN*)stream) -> hf; if (hFile != NULL) { CloseHandle(hFile); ret=0; } free(stream); } return ret; } int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) { int ret=-1; if (stream!=NULL) { ret = ((WIN32FILE_IOWIN*)stream) -> error; } return ret; } void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen_file = win32_open_file_func; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell_file = win32_tell_file_func; pzlib_filefunc_def->zseek_file = win32_seek_file_func; pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_func; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } tcl8.6.5/compat/zlib/contrib/minizip/iowin32.h0000644000175000017500000000152312663653206020574 0ustar sergeisergei/* iowin32.h -- IO base function header for compress/uncompress .zip Version 1.1, February 14h, 2010 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt */ #include #ifdef __cplusplus extern "C" { #endif void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def)); void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def)); void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def)); #ifdef __cplusplus } #endif tcl8.6.5/compat/zlib/contrib/minizip/miniunz.c0000644000175000017500000004254312663660064020775 0ustar sergeisergei/* miniunz.c Version 1.1, February 14h, 2010 sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications of Unzip for Zip64 Copyright (C) 2007-2008 Even Rouault Modifications for Zip64 support on both zip and unzip Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) */ #if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) #ifndef __USE_FILE_OFFSET64 #define __USE_FILE_OFFSET64 #endif #ifndef __USE_LARGEFILE64 #define __USE_LARGEFILE64 #endif #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #endif #ifndef _FILE_OFFSET_BIT #define _FILE_OFFSET_BIT 64 #endif #endif #ifdef __APPLE__ // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) ftello(stream) #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) #else #define FOPEN_FUNC(filename, mode) fopen64(filename, mode) #define FTELLO_FUNC(stream) ftello64(stream) #define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) #endif #include #include #include #include #include #include #ifdef _WIN32 # include # include #else # include # include #endif #include "unzip.h" #define CASESENSITIVITY (0) #define WRITEBUFFERSIZE (8192) #define MAXFILENAME (256) #ifdef _WIN32 #define USEWIN32IOAPI #include "iowin32.h" #endif /* mini unzip, demo of unzip package usage : Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT if it exists */ /* change_file_date : change the date/time of a file filename : the filename of the file where date/time must be modified dosdate : the new date at the MSDos format (4 bytes) tmu_date : the SAME new date at the tm_unz format */ void change_file_date(filename,dosdate,tmu_date) const char *filename; uLong dosdate; tm_unz tmu_date; { #ifdef _WIN32 HANDLE hFile; FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE, 0,NULL,OPEN_EXISTING,0,NULL); GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); LocalFileTimeToFileTime(&ftLocal,&ftm); SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); CloseHandle(hFile); #else #ifdef unix || __APPLE__ struct utimbuf ut; struct tm newdate; newdate.tm_sec = tmu_date.tm_sec; newdate.tm_min=tmu_date.tm_min; newdate.tm_hour=tmu_date.tm_hour; newdate.tm_mday=tmu_date.tm_mday; newdate.tm_mon=tmu_date.tm_mon; if (tmu_date.tm_year > 1900) newdate.tm_year=tmu_date.tm_year - 1900; else newdate.tm_year=tmu_date.tm_year ; newdate.tm_isdst=-1; ut.actime=ut.modtime=mktime(&newdate); utime(filename,&ut); #endif #endif } /* mymkdir and change_file_date are not 100 % portable As I don't know well Unix, I wait feedback for the unix portion */ int mymkdir(dirname) const char* dirname; { int ret=0; #ifdef _WIN32 ret = _mkdir(dirname); #elif unix ret = mkdir (dirname,0775); #elif __APPLE__ ret = mkdir (dirname,0775); #endif return ret; } int makedir (newdir) char *newdir; { char *buffer ; char *p; int len = (int)strlen(newdir); if (len <= 0) return 0; buffer = (char*)malloc(len+1); if (buffer==NULL) { printf("Error allocating memory\n"); return UNZ_INTERNALERROR; } strcpy(buffer,newdir); if (buffer[len-1] == '/') { buffer[len-1] = '\0'; } if (mymkdir(buffer) == 0) { free(buffer); return 1; } p = buffer+1; while (1) { char hold; while(*p && *p != '\\' && *p != '/') p++; hold = *p; *p = 0; if ((mymkdir(buffer) == -1) && (errno == ENOENT)) { printf("couldn't create directory %s\n",buffer); free(buffer); return 0; } if (hold == 0) break; *p++ = hold; } free(buffer); return 1; } void do_banner() { printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); } void do_help() { printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ " -e Extract without pathname (junk paths)\n" \ " -x Extract with pathname\n" \ " -v list files\n" \ " -l list files\n" \ " -d directory to extract into\n" \ " -o overwrite files without prompting\n" \ " -p extract crypted file using password\n\n"); } void Display64BitsSize(ZPOS64_T n, int size_char) { /* to avoid compatibility problem , we do here the conversion */ char number[21]; int offset=19; int pos_string = 19; number[20]=0; for (;;) { number[offset]=(char)((n%10)+'0'); if (number[offset] != '0') pos_string=offset; n/=10; if (offset==0) break; offset--; } { int size_display_string = 19-pos_string; while (size_char > size_display_string) { size_char--; printf(" "); } } printf("%s",&number[pos_string]); } int do_list(uf) unzFile uf; { uLong i; unz_global_info64 gi; int err; err = unzGetGlobalInfo64(uf,&gi); if (err!=UNZ_OK) printf("error %d with zipfile in unzGetGlobalInfo \n",err); printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); for (i=0;i0) ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size); /* display a '*' if the file is crypted */ if ((file_info.flag & 1) != 0) charCrypt='*'; if (file_info.compression_method==0) string_method="Stored"; else if (file_info.compression_method==Z_DEFLATED) { uInt iLevel=(uInt)((file_info.flag & 0x6)/2); if (iLevel==0) string_method="Defl:N"; else if (iLevel==1) string_method="Defl:X"; else if ((iLevel==2) || (iLevel==3)) string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ } else if (file_info.compression_method==Z_BZIP2ED) { string_method="BZip2 "; } else string_method="Unkn. "; Display64BitsSize(file_info.uncompressed_size,7); printf(" %6s%c",string_method,charCrypt); Display64BitsSize(file_info.compressed_size,7); printf(" %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", ratio, (uLong)file_info.tmu_date.tm_mon + 1, (uLong)file_info.tmu_date.tm_mday, (uLong)file_info.tmu_date.tm_year % 100, (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, (uLong)file_info.crc,filename_inzip); if ((i+1)='a') && (rep<='z')) rep -= 0x20; } while ((rep!='Y') && (rep!='N') && (rep!='A')); } if (rep == 'N') skip = 1; if (rep == 'A') *popt_overwrite=1; } if ((skip==0) && (err==UNZ_OK)) { fout=FOPEN_FUNC(write_filename,"wb"); /* some zipfile don't contain directory alone before file */ if ((fout==NULL) && ((*popt_extract_without_path)==0) && (filename_withoutpath!=(char*)filename_inzip)) { char c=*(filename_withoutpath-1); *(filename_withoutpath-1)='\0'; makedir(write_filename); *(filename_withoutpath-1)=c; fout=FOPEN_FUNC(write_filename,"wb"); } if (fout==NULL) { printf("error opening %s\n",write_filename); } } if (fout!=NULL) { printf(" extracting: %s\n",write_filename); do { err = unzReadCurrentFile(uf,buf,size_buf); if (err<0) { printf("error %d with zipfile in unzReadCurrentFile\n",err); break; } if (err>0) if (fwrite(buf,err,1,fout)!=1) { printf("error in writing extracted file\n"); err=UNZ_ERRNO; break; } } while (err>0); if (fout) fclose(fout); if (err==0) change_file_date(write_filename,file_info.dosDate, file_info.tmu_date); } if (err==UNZ_OK) { err = unzCloseCurrentFile (uf); if (err!=UNZ_OK) { printf("error %d with zipfile in unzCloseCurrentFile\n",err); } } else unzCloseCurrentFile(uf); /* don't lose the error */ } free(buf); return err; } int do_extract(uf,opt_extract_without_path,opt_overwrite,password) unzFile uf; int opt_extract_without_path; int opt_overwrite; const char* password; { uLong i; unz_global_info64 gi; int err; FILE* fout=NULL; err = unzGetGlobalInfo64(uf,&gi); if (err!=UNZ_OK) printf("error %d with zipfile in unzGetGlobalInfo \n",err); for (i=0;i insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME minizip - create ZIP archives .SH SYNOPSIS .B minizip .RI [ -o ] zipfile [ " files" ... ] .SH DESCRIPTION .B minizip is a simple tool which allows the creation of compressed file archives in the ZIP format used by the MS-DOS utility PKZIP. It was written as a demonstration of the .IR zlib (3) library and therefore lack many of the features of the .IR zip (1) program. .SH OPTIONS The first argument supplied is the name of the ZIP archive to create or .RI -o in which case it is ignored and the second argument treated as the name of the ZIP file. If the ZIP file already exists it will be overwritten. .PP Subsequent arguments specify a list of files to place in the ZIP archive. If none are specified then an empty archive will be created. .SH SEE ALSO .BR miniunzip (1), .BR zlib (3), .BR zip (1). .SH AUTHOR This program was written by Gilles Vollant. This manual page was written by Mark Brown . tcl8.6.5/compat/zlib/contrib/minizip/make_vms.com0000644000175000017500000000160512663653206021434 0ustar sergeisergei$ if f$search("ioapi.h_orig") .eqs. "" then copy ioapi.h ioapi.h_orig $ open/write zdef vmsdefs.h $ copy sys$input: zdef $ deck #define unix #define fill_zlib_filefunc64_32_def_from_filefunc32 fillzffunc64from #define Write_Zip64EndOfCentralDirectoryLocator Write_Zip64EoDLocator #define Write_Zip64EndOfCentralDirectoryRecord Write_Zip64EoDRecord #define Write_EndOfCentralDirectoryRecord Write_EoDRecord $ eod $ close zdef $ copy vmsdefs.h,ioapi.h_orig ioapi.h $ cc/include=[--]/prefix=all ioapi.c $ cc/include=[--]/prefix=all miniunz.c $ cc/include=[--]/prefix=all unzip.c $ cc/include=[--]/prefix=all minizip.c $ cc/include=[--]/prefix=all zip.c $ link miniunz,unzip,ioapi,[--]libz.olb/lib $ link minizip,zip,ioapi,[--]libz.olb/lib $ mcr []minizip test minizip_info.txt $ mcr []miniunz -l test.zip $ rename minizip_info.txt; minizip_info.txt_old $ mcr []miniunz test.zip $ delete test.zip;* $exit tcl8.6.5/compat/zlib/contrib/minizip/minizip.c0000644000175000017500000003527212663660064020764 0ustar sergeisergei/* minizip.c Version 1.1, February 14h, 2010 sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications of Unzip for Zip64 Copyright (C) 2007-2008 Even Rouault Modifications for Zip64 support on both zip and unzip Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) */ #if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) #ifndef __USE_FILE_OFFSET64 #define __USE_FILE_OFFSET64 #endif #ifndef __USE_LARGEFILE64 #define __USE_LARGEFILE64 #endif #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #endif #ifndef _FILE_OFFSET_BIT #define _FILE_OFFSET_BIT 64 #endif #endif #ifdef __APPLE__ // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) ftello(stream) #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) #else #define FOPEN_FUNC(filename, mode) fopen64(filename, mode) #define FTELLO_FUNC(stream) ftello64(stream) #define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) #endif #include #include #include #include #include #include #ifdef _WIN32 # include # include #else # include # include # include # include #endif #include "zip.h" #ifdef _WIN32 #define USEWIN32IOAPI #include "iowin32.h" #endif #define WRITEBUFFERSIZE (16384) #define MAXFILENAME (256) #ifdef _WIN32 uLong filetime(f, tmzip, dt) char *f; /* name of file to get info on */ tm_zip *tmzip; /* return value: access, modific. and creation times */ uLong *dt; /* dostime */ { int ret = 0; { FILETIME ftLocal; HANDLE hFind; WIN32_FIND_DATAA ff32; hFind = FindFirstFileA(f,&ff32); if (hFind != INVALID_HANDLE_VALUE) { FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); FindClose(hFind); ret = 1; } } return ret; } #else #ifdef unix || __APPLE__ uLong filetime(f, tmzip, dt) char *f; /* name of file to get info on */ tm_zip *tmzip; /* return value: access, modific. and creation times */ uLong *dt; /* dostime */ { int ret=0; struct stat s; /* results of stat() */ struct tm* filedate; time_t tm_t=0; if (strcmp(f,"-")!=0) { char name[MAXFILENAME+1]; int len = strlen(f); if (len > MAXFILENAME) len = MAXFILENAME; strncpy(name, f,MAXFILENAME-1); /* strncpy doesnt append the trailing NULL, of the string is too long. */ name[ MAXFILENAME ] = '\0'; if (name[len - 1] == '/') name[len - 1] = '\0'; /* not all systems allow stat'ing a file with / appended */ if (stat(name,&s)==0) { tm_t = s.st_mtime; ret = 1; } } filedate = localtime(&tm_t); tmzip->tm_sec = filedate->tm_sec; tmzip->tm_min = filedate->tm_min; tmzip->tm_hour = filedate->tm_hour; tmzip->tm_mday = filedate->tm_mday; tmzip->tm_mon = filedate->tm_mon ; tmzip->tm_year = filedate->tm_year; return ret; } #else uLong filetime(f, tmzip, dt) char *f; /* name of file to get info on */ tm_zip *tmzip; /* return value: access, modific. and creation times */ uLong *dt; /* dostime */ { return 0; } #endif #endif int check_exist_file(filename) const char* filename; { FILE* ftestexist; int ret = 1; ftestexist = FOPEN_FUNC(filename,"rb"); if (ftestexist==NULL) ret = 0; else fclose(ftestexist); return ret; } void do_banner() { printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n"); printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n"); } void do_help() { printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \ " -o Overwrite existing file.zip\n" \ " -a Append to existing file.zip\n" \ " -0 Store only\n" \ " -1 Compress faster\n" \ " -9 Compress better\n\n" \ " -j exclude path. store only the file name.\n\n"); } /* calculate the CRC32 of a file, because to encrypt a file, we need known the CRC32 of the file before */ int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) { unsigned long calculate_crc=0; int err=ZIP_OK; FILE * fin = FOPEN_FUNC(filenameinzip,"rb"); unsigned long size_read = 0; unsigned long total_read = 0; if (fin==NULL) { err = ZIP_ERRNO; } if (err == ZIP_OK) do { err = ZIP_OK; size_read = (int)fread(buf,1,size_buf,fin); if (size_read < size_buf) if (feof(fin)==0) { printf("error in reading %s\n",filenameinzip); err = ZIP_ERRNO; } if (size_read>0) calculate_crc = crc32(calculate_crc,buf,size_read); total_read += size_read; } while ((err == ZIP_OK) && (size_read>0)); if (fin) fclose(fin); *result_crc=calculate_crc; printf("file %s crc %lx\n", filenameinzip, calculate_crc); return err; } int isLargeFile(const char* filename) { int largeFile = 0; ZPOS64_T pos = 0; FILE* pFile = FOPEN_FUNC(filename, "rb"); if(pFile != NULL) { int n = FSEEKO_FUNC(pFile, 0, SEEK_END); pos = FTELLO_FUNC(pFile); printf("File : %s is %lld bytes\n", filename, pos); if(pos >= 0xffffffff) largeFile = 1; fclose(pFile); } return largeFile; } int main(argc,argv) int argc; char *argv[]; { int i; int opt_overwrite=0; int opt_compress_level=Z_DEFAULT_COMPRESSION; int opt_exclude_path=0; int zipfilenamearg = 0; char filename_try[MAXFILENAME+16]; int zipok; int err=0; int size_buf=0; void* buf=NULL; const char* password=NULL; do_banner(); if (argc==1) { do_help(); return 0; } else { for (i=1;i='0') && (c<='9')) opt_compress_level = c-'0'; if ((c=='j') || (c=='J')) opt_exclude_path = 1; if (((c=='p') || (c=='P')) && (i+1='a') && (rep<='z')) rep -= 0x20; } while ((rep!='Y') && (rep!='N') && (rep!='A')); if (rep=='N') zipok = 0; if (rep=='A') opt_overwrite = 2; } } if (zipok==1) { zipFile zf; int errclose; # ifdef USEWIN32IOAPI zlib_filefunc64_def ffunc; fill_win32_filefunc64A(&ffunc); zf = zipOpen2_64(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc); # else zf = zipOpen64(filename_try,(opt_overwrite==2) ? 2 : 0); # endif if (zf == NULL) { printf("error opening %s\n",filename_try); err= ZIP_ERRNO; } else printf("creating %s\n",filename_try); for (i=zipfilenamearg+1;(i='0') || (argv[i][1]<='9'))) && (strlen(argv[i]) == 2))) { FILE * fin; int size_read; const char* filenameinzip = argv[i]; const char *savefilenameinzip; zip_fileinfo zi; unsigned long crcFile=0; int zip64 = 0; zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; zi.dosDate = 0; zi.internal_fa = 0; zi.external_fa = 0; filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); /* err = zipOpenNewFileInZip(zf,filenameinzip,&zi, NULL,0,NULL,0,NULL / * comment * /, (opt_compress_level != 0) ? Z_DEFLATED : 0, opt_compress_level); */ if ((password != NULL) && (err==ZIP_OK)) err = getFileCrc(filenameinzip,buf,size_buf,&crcFile); zip64 = isLargeFile(filenameinzip); /* The path name saved, should not include a leading slash. */ /*if it did, windows/xp and dynazip couldn't read the zip file. */ savefilenameinzip = filenameinzip; while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' ) { savefilenameinzip++; } /*should the zip file contain any path at all?*/ if( opt_exclude_path ) { const char *tmpptr; const char *lastslash = 0; for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++) { if( *tmpptr == '\\' || *tmpptr == '/') { lastslash = tmpptr; } } if( lastslash != NULL ) { savefilenameinzip = lastslash+1; // base filename follows last slash. } } /**/ err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi, NULL,0,NULL,0,NULL /* comment*/, (opt_compress_level != 0) ? Z_DEFLATED : 0, opt_compress_level,0, /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, password,crcFile, zip64); if (err != ZIP_OK) printf("error in opening %s in zipfile\n",filenameinzip); else { fin = FOPEN_FUNC(filenameinzip,"rb"); if (fin==NULL) { err=ZIP_ERRNO; printf("error in opening %s for reading\n",filenameinzip); } } if (err == ZIP_OK) do { err = ZIP_OK; size_read = (int)fread(buf,1,size_buf,fin); if (size_read < size_buf) if (feof(fin)==0) { printf("error in reading %s\n",filenameinzip); err = ZIP_ERRNO; } if (size_read>0) { err = zipWriteInFileInZip (zf,buf,size_read); if (err<0) { printf("error in writing %s in the zipfile\n", filenameinzip); } } } while ((err == ZIP_OK) && (size_read>0)); if (fin) fclose(fin); if (err<0) err=ZIP_ERRNO; else { err = zipCloseFileInZip(zf); if (err!=ZIP_OK) printf("error in closing %s in the zipfile\n", filenameinzip); } } } errclose = zipClose(zf,NULL); if (errclose != ZIP_OK) printf("error in closing %s\n",filename_try); } else { do_help(); } free(buf); return 0; } tcl8.6.5/compat/zlib/contrib/minizip/ioapi.h0000644000175000017500000001561312663660064020410 0ustar sergeisergei/* ioapi.h -- IO base function header for compress/uncompress .zip part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt Changes Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. More if/def section may be needed to support other platforms Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. (but you should use iowin32.c for windows instead) */ #ifndef _ZLIBIOAPI64_H #define _ZLIBIOAPI64_H #if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) // Linux needs this to support file operation on files larger then 4+GB // But might need better if/def to select just the platforms that needs them. #ifndef __USE_FILE_OFFSET64 #define __USE_FILE_OFFSET64 #endif #ifndef __USE_LARGEFILE64 #define __USE_LARGEFILE64 #endif #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #endif #ifndef _FILE_OFFSET_BIT #define _FILE_OFFSET_BIT 64 #endif #endif #include #include #include "zlib.h" #if defined(USE_FILE32API) #define fopen64 fopen #define ftello64 ftell #define fseeko64 fseek #else #ifdef __FreeBSD__ #define fopen64 fopen #define ftello64 ftello #define fseeko64 fseeko #endif #ifdef _MSC_VER #define fopen64 fopen #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) #define ftello64 _ftelli64 #define fseeko64 _fseeki64 #else // old MSC #define ftello64 ftell #define fseeko64 fseek #endif #endif #endif /* #ifndef ZPOS64_T #ifdef _WIN32 #define ZPOS64_T fpos_t #else #include #define ZPOS64_T uint64_t #endif #endif */ #ifdef HAVE_MINIZIP64_CONF_H #include "mz64conf.h" #endif /* a type choosen by DEFINE */ #ifdef HAVE_64BIT_INT_CUSTOM typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; #else #ifdef HAS_STDINT_H #include "stdint.h" typedef uint64_t ZPOS64_T; #else /* Maximum unsigned 32-bit value used as placeholder for zip64 */ #define MAXU32 0xffffffff #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 ZPOS64_T; #else typedef unsigned long long int ZPOS64_T; #endif #endif #endif #ifdef __cplusplus extern "C" { #endif #define ZLIB_FILEFUNC_SEEK_CUR (1) #define ZLIB_FILEFUNC_SEEK_END (2) #define ZLIB_FILEFUNC_SEEK_SET (0) #define ZLIB_FILEFUNC_MODE_READ (1) #define ZLIB_FILEFUNC_MODE_WRITE (2) #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) #define ZLIB_FILEFUNC_MODE_EXISTING (4) #define ZLIB_FILEFUNC_MODE_CREATE (8) #ifndef ZCALLBACK #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) #define ZCALLBACK CALLBACK #else #define ZCALLBACK #endif #endif typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); /* here is the "old" 32 bits structure structure */ typedef struct zlib_filefunc_def_s { open_file_func zopen_file; read_file_func zread_file; write_file_func zwrite_file; tell_file_func ztell_file; seek_file_func zseek_file; close_file_func zclose_file; testerror_file_func zerror_file; voidpf opaque; } zlib_filefunc_def; typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); typedef struct zlib_filefunc64_def_s { open64_file_func zopen64_file; read_file_func zread_file; write_file_func zwrite_file; tell64_file_func ztell64_file; seek64_file_func zseek64_file; close_file_func zclose_file; testerror_file_func zerror_file; voidpf opaque; } zlib_filefunc64_def; void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); /* now internal definition, only for zip.c and unzip.h */ typedef struct zlib_filefunc64_32_def_s { zlib_filefunc64_def zfile_func64; open_file_func zopen32_file; tell_file_func ztell32_file; seek_file_func zseek32_file; } zlib_filefunc64_32_def; #define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) #define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) //#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) //#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); #define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) #define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) #define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) #ifdef __cplusplus } #endif #endif tcl8.6.5/compat/zlib/contrib/minizip/miniunzip.10000644000175000017500000000350512663660064021237 0ustar sergeisergei.\" Hey, EMACS: -*- nroff -*- .TH miniunzip 1 "Nov 7, 2001" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME miniunzip - uncompress and examine ZIP archives .SH SYNOPSIS .B miniunzip .RI [ -exvlo ] zipfile [ files_to_extract ] [-d tempdir] .SH DESCRIPTION .B minizip is a simple tool which allows the extraction of compressed file archives in the ZIP format used by the MS-DOS utility PKZIP. It was written as a demonstration of the .IR zlib (3) library and therefore lack many of the features of the .IR unzip (1) program. .SH OPTIONS A number of options are supported. With the exception of .BI \-d\ tempdir these must be supplied before any other arguments and are: .TP .BI \-l\ ,\ \-\-v List the files in the archive without extracting them. .TP .B \-o Overwrite files without prompting for confirmation. .TP .B \-x Extract files (default). .PP The .I zipfile argument is the name of the archive to process. The next argument can be used to specify a single file to extract from the archive. Lastly, the following option can be specified at the end of the command-line: .TP .BI \-d\ tempdir Extract the archive in the directory .I tempdir rather than the current directory. .SH SEE ALSO .BR minizip (1), .BR zlib (3), .BR unzip (1). .SH AUTHOR This program was written by Gilles Vollant. This manual page was written by Mark Brown . The -d tempdir option was added by Dirk Eddelbuettel . tcl8.6.5/compat/zlib/contrib/minizip/unzip.c0000644000175000017500000021261612663660064020451 0ustar sergeisergei/* unzip.c -- IO for uncompress .zip files using zlib Version 1.1, February 14h, 2010 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications of Unzip for Zip64 Copyright (C) 2007-2008 Even Rouault Modifications for Zip64 support on both zip and unzip Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt ------------------------------------------------------------------------------------ Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of compatibility with older software. The following is from the original crypt.c. Code woven in by Terry Thorsen 1/2003. Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] The encryption/decryption parts of this source code (as opposed to the non-echoing password parts) were originally written in Europe. The whole source package can be freely distributed, including from the USA. (Prior to January 2000, re-export from the US was a violation of US law.) This encryption code is a direct transcription of the algorithm from Roger Schlafly, described by Phil Katz in the file appnote.txt. This file (appnote.txt) is distributed with the PKZIP program (even in the version without encryption capabilities). ------------------------------------------------------------------------------------ Changes in unzip.c 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* 2007-2008 - Even Rouault - Remove old C style function prototypes 2007-2008 - Even Rouault - Add unzip support for ZIP64 Copyright (C) 2007-2008 Even Rouault Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G should only read the compressed/uncompressed size from the Zip64 format if the size from normal header was 0xFFFFFFFF Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) Patch created by Daniel Borca Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson */ #include #include #include #ifndef NOUNCRYPT #define NOUNCRYPT #endif #include "zlib.h" #include "unzip.h" #ifdef STDC # include # include # include #endif #ifdef NO_ERRNO_H extern int errno; #else # include #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ #ifndef CASESENSITIVITYDEFAULT_NO # if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) # define CASESENSITIVITYDEFAULT_NO # endif #endif #ifndef UNZ_BUFSIZE #define UNZ_BUFSIZE (16384) #endif #ifndef UNZ_MAXFILENAMEINZIP #define UNZ_MAXFILENAMEINZIP (256) #endif #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif #ifndef TRYFREE # define TRYFREE(p) {if (p) free(p);} #endif #define SIZECENTRALDIRITEM (0x2e) #define SIZEZIPLOCALHEADER (0x1e) const char unz_copyright[] = " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; /* unz_file_info_interntal contain internal info about a file in zipfile*/ typedef struct unz_file_info64_internal_s { ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ } unz_file_info64_internal; /* file_in_zip_read_info_s contain internal information about a file in zipfile, when reading and decompress it */ typedef struct { char *read_buffer; /* internal buffer for compressed data */ z_stream stream; /* zLib stream structure for inflate */ #ifdef HAVE_BZIP2 bz_stream bstream; /* bzLib stream structure for bziped */ #endif ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ uLong stream_initialised; /* flag set if stream structure is initialised*/ ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ uInt size_local_extrafield;/* size of the local extra field */ ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ ZPOS64_T total_out_64; uLong crc32; /* crc32 of all data uncompressed */ uLong crc32_wait; /* crc32 we must obtain after decompress all */ ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ zlib_filefunc64_32_def z_filefunc; voidpf filestream; /* io structore of the zipfile */ uLong compression_method; /* compression method (0==store) */ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ int raw; } file_in_zip64_read_info_s; /* unz64_s contain internal information about the zipfile */ typedef struct { zlib_filefunc64_32_def z_filefunc; int is64bitOpenFunction; voidpf filestream; /* io structore of the zipfile */ unz_global_info64 gi; /* public global information */ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ ZPOS64_T num_file; /* number of the current file in the zipfile*/ ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ ZPOS64_T central_pos; /* position of the beginning of the central dir*/ ZPOS64_T size_central_dir; /* size of the central directory */ ZPOS64_T offset_central_dir; /* offset of start of central directory with respect to the starting disk number */ unz_file_info64 cur_file_info; /* public info about the current file in zip*/ unz_file_info64_internal cur_file_info_internal; /* private info about it*/ file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current file if we are decompressing it */ int encrypted; int isZip64; # ifndef NOUNCRYPT unsigned long keys[3]; /* keys defining the pseudo-random sequence */ const z_crc_t* pcrc_32_tab; # endif } unz64_s; #ifndef NOUNCRYPT #include "crypt.h" #endif /* =========================================================================== Read a byte from a gz_stream; update next_in and avail_in. Return EOF for end of file. IN assertion: the stream s has been sucessfully opened for reading. */ local int unz64local_getByte OF(( const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) { unsigned char c; int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); if (err==1) { *pi = (int)c; return UNZ_OK; } else { if (ZERROR64(*pzlib_filefunc_def,filestream)) return UNZ_ERRNO; else return UNZ_EOF; } } /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ local int unz64local_getShort OF(( const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX) { uLong x ; int i = 0; int err; err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x = (uLong)i; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((uLong)i)<<8; if (err==UNZ_OK) *pX = x; else *pX = 0; return err; } local int unz64local_getLong OF(( const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX) { uLong x ; int i = 0; int err; err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x = (uLong)i; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((uLong)i)<<8; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((uLong)i)<<16; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<24; if (err==UNZ_OK) *pX = x; else *pX = 0; return err; } local int unz64local_getLong64 OF(( const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) { ZPOS64_T x ; int i = 0; int err; err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x = (ZPOS64_T)i; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<8; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<16; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<24; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<32; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<40; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<48; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<56; if (err==UNZ_OK) *pX = x; else *pX = 0; return err; } /* My own strcmpi / strcasecmp */ local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) { for (;;) { char c1=*(fileName1++); char c2=*(fileName2++); if ((c1>='a') && (c1<='z')) c1 -= 0x20; if ((c2>='a') && (c2<='z')) c2 -= 0x20; if (c1=='\0') return ((c2=='\0') ? 0 : -1); if (c2=='\0') return 1; if (c1c2) return 1; } } #ifdef CASESENSITIVITYDEFAULT_NO #define CASESENSITIVITYDEFAULTVALUE 2 #else #define CASESENSITIVITYDEFAULTVALUE 1 #endif #ifndef STRCMPCASENOSENTIVEFUNCTION #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal #endif /* Compare two filename (fileName1,fileName2). If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp) If iCaseSenisivity = 0, case sensitivity is defaut of your operating system (like 1 on Unix, 2 on Windows) */ extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity) { if (iCaseSensitivity==0) iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; if (iCaseSensitivity==1) return strcmp(fileName1,fileName2); return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); } #ifndef BUFREADCOMMENT #define BUFREADCOMMENT (0x400) #endif /* Locate the Central directory of a zipfile (at the end, just before the global comment) */ local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ ZPOS64_T uPosFound=0; if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) return 0; uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) return 0; uBackRead = 4; while (uBackReaduMaxBack) uBackRead = uMaxBack; else uBackRead+=BUFREADCOMMENT; uReadPos = uSizeFile-uBackRead ; uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) break; if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) break; for (i=(int)uReadSize-3; (i--)>0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) { uPosFound = uReadPos+i; break; } if (uPosFound!=0) break; } TRYFREE(buf); return uPosFound; } /* Locate the Central directory 64 of a zipfile (at the end, just before the global comment) */ local ZPOS64_T unz64local_SearchCentralDir64 OF(( const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ ZPOS64_T uPosFound=0; uLong uL; ZPOS64_T relativeOffset; if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) return 0; uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) return 0; uBackRead = 4; while (uBackReaduMaxBack) uBackRead = uMaxBack; else uBackRead+=BUFREADCOMMENT; uReadPos = uSizeFile-uBackRead ; uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) break; if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) break; for (i=(int)uReadSize-3; (i--)>0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) { uPosFound = uReadPos+i; break; } if (uPosFound!=0) break; } TRYFREE(buf); if (uPosFound == 0) return 0; /* Zip64 end of central directory locator */ if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) return 0; /* the signature, already checked */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return 0; /* number of the disk with the start of the zip64 end of central directory */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return 0; if (uL != 0) return 0; /* relative offset of the zip64 end of central directory record */ if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) return 0; /* total number of disks */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return 0; if (uL != 1) return 0; /* Goto end of central directory record */ if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) return 0; /* the signature */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return 0; if (uL != 0x06064b50) return 0; return relativeOffset; } /* Open a Zip file. path contain the full pathname (by example, on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer "zlib/zlib114.zip". If the zipfile cannot be opened (file doesn't exist or in not valid), the return value is NULL. Else, the return value is a unzFile Handle, usable with other function of this unzip package. */ local unzFile unzOpenInternal (const void *path, zlib_filefunc64_32_def* pzlib_filefunc64_32_def, int is64bitOpenFunction) { unz64_s us; unz64_s *s; ZPOS64_T central_pos; uLong uL; uLong number_disk; /* number of the current dist, used for spaning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used for spaning ZIP, unsupported, always 0*/ ZPOS64_T number_entry_CD; /* total number of entries in the central dir (same than number_entry on nospan) */ int err=UNZ_OK; if (unz_copyright[0]!=' ') return NULL; us.z_filefunc.zseek32_file = NULL; us.z_filefunc.ztell32_file = NULL; if (pzlib_filefunc64_32_def==NULL) fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); else us.z_filefunc = *pzlib_filefunc64_32_def; us.is64bitOpenFunction = is64bitOpenFunction; us.filestream = ZOPEN64(us.z_filefunc, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING); if (us.filestream==NULL) return NULL; central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); if (central_pos) { uLong uS; ZPOS64_T uL64; us.isZip64 = 1; if (ZSEEK64(us.z_filefunc, us.filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) err=UNZ_ERRNO; /* the signature, already checked */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; /* size of zip64 end of central directory record */ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) err=UNZ_ERRNO; /* version made by */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) err=UNZ_ERRNO; /* version needed to extract */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) err=UNZ_ERRNO; /* number of this disk */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) err=UNZ_ERRNO; /* number of the disk with the start of the central directory */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central directory on this disk */ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central directory */ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) err=UNZ_ERRNO; if ((number_entry_CD!=us.gi.number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=UNZ_BADZIPFILE; /* size of the central directory */ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) err=UNZ_ERRNO; /* offset of start of central directory with respect to the starting disk number */ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) err=UNZ_ERRNO; us.gi.size_comment = 0; } else { central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); if (central_pos==0) err=UNZ_ERRNO; us.isZip64 = 0; if (ZSEEK64(us.z_filefunc, us.filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) err=UNZ_ERRNO; /* the signature, already checked */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; /* number of this disk */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) err=UNZ_ERRNO; /* number of the disk with the start of the central directory */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central dir on this disk */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; us.gi.number_entry = uL; /* total number of entries in the central dir */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; number_entry_CD = uL; if ((number_entry_CD!=us.gi.number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=UNZ_BADZIPFILE; /* size of the central directory */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; us.size_central_dir = uL; /* offset of start of central directory with respect to the starting disk number */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; us.offset_central_dir = uL; /* zipfile comment length */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) err=UNZ_ERRNO; } if ((central_pospfile_in_zip_read!=NULL) unzCloseCurrentFile(file); ZCLOSE64(s->z_filefunc, s->filestream); TRYFREE(s); return UNZ_OK; } /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) { unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; *pglobal_info=s->gi; return UNZ_OK; } extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) { unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; /* to do : check if number_entry is not truncated */ pglobal_info32->number_entry = (uLong)s->gi.number_entry; pglobal_info32->size_comment = s->gi.size_comment; return UNZ_OK; } /* Translate date/time from Dos format to tm_unz (readable more easilty) */ local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) { ZPOS64_T uDate; uDate = (ZPOS64_T)(ulDosDate>>16); ptm->tm_mday = (uInt)(uDate&0x1f) ; ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; } /* Get Info about the current file in the zipfile, with internal only info */ local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, unz_file_info64 *pfile_info, unz_file_info64_internal *pfile_info_internal, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)); local int unz64local_GetCurrentFileInfoInternal (unzFile file, unz_file_info64 *pfile_info, unz_file_info64_internal *pfile_info_internal, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize) { unz64_s* s; unz_file_info64 file_info; unz_file_info64_internal file_info_internal; int err=UNZ_OK; uLong uMagic; long lSeek=0; uLong uL; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; if (ZSEEK64(s->z_filefunc, s->filestream, s->pos_in_central_dir+s->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET)!=0) err=UNZ_ERRNO; /* we check the magic */ if (err==UNZ_OK) { if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) err=UNZ_ERRNO; else if (uMagic!=0x02014b50) err=UNZ_BADZIPFILE; } if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) err=UNZ_ERRNO; unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) err=UNZ_ERRNO; file_info.compressed_size = uL; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) err=UNZ_ERRNO; file_info.uncompressed_size = uL; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) err=UNZ_ERRNO; // relative offset of local header if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) err=UNZ_ERRNO; file_info_internal.offset_curfile = uL; lSeek+=file_info.size_filename; if ((err==UNZ_OK) && (szFileName!=NULL)) { uLong uSizeRead ; if (file_info.size_filename0) && (fileNameBufferSize>0)) if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) err=UNZ_ERRNO; lSeek -= uSizeRead; } // Read extrafield if ((err==UNZ_OK) && (extraField!=NULL)) { ZPOS64_T uSizeRead ; if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) err=UNZ_ERRNO; lSeek += file_info.size_file_extra - (uLong)uSizeRead; } else lSeek += file_info.size_file_extra; if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) { uLong acc = 0; // since lSeek now points to after the extra field we need to move back lSeek -= file_info.size_file_extra; if (lSeek!=0) { if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } while(acc < file_info.size_file_extra) { uLong headerId; uLong dataSize; if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) err=UNZ_ERRNO; /* ZIP64 extra fields */ if (headerId == 0x0001) { uLong uL; if(file_info.uncompressed_size == MAXU32) { if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) err=UNZ_ERRNO; } if(file_info.compressed_size == MAXU32) { if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) err=UNZ_ERRNO; } if(file_info_internal.offset_curfile == MAXU32) { /* Relative Header offset */ if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) err=UNZ_ERRNO; } if(file_info.disk_num_start == MAXU32) { /* Disk Start Number */ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) err=UNZ_ERRNO; } } else { if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) err=UNZ_ERRNO; } acc += 2 + 2 + dataSize; } } if ((err==UNZ_OK) && (szComment!=NULL)) { uLong uSizeRead ; if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } if ((file_info.size_file_comment>0) && (commentBufferSize>0)) if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) err=UNZ_ERRNO; lSeek+=file_info.size_file_comment - uSizeRead; } else lSeek+=file_info.size_file_comment; if ((err==UNZ_OK) && (pfile_info!=NULL)) *pfile_info=file_info; if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) *pfile_info_internal=file_info_internal; return err; } /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, unz_file_info64 * pfile_info, char * szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char* szComment, uLong commentBufferSize) { return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, szFileName,fileNameBufferSize, extraField,extraFieldBufferSize, szComment,commentBufferSize); } extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, unz_file_info * pfile_info, char * szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char* szComment, uLong commentBufferSize) { int err; unz_file_info64 file_info64; err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, szFileName,fileNameBufferSize, extraField,extraFieldBufferSize, szComment,commentBufferSize); if ((err==UNZ_OK) && (pfile_info != NULL)) { pfile_info->version = file_info64.version; pfile_info->version_needed = file_info64.version_needed; pfile_info->flag = file_info64.flag; pfile_info->compression_method = file_info64.compression_method; pfile_info->dosDate = file_info64.dosDate; pfile_info->crc = file_info64.crc; pfile_info->size_filename = file_info64.size_filename; pfile_info->size_file_extra = file_info64.size_file_extra; pfile_info->size_file_comment = file_info64.size_file_comment; pfile_info->disk_num_start = file_info64.disk_num_start; pfile_info->internal_fa = file_info64.internal_fa; pfile_info->external_fa = file_info64.external_fa; pfile_info->tmu_date = file_info64.tmu_date, pfile_info->compressed_size = (uLong)file_info64.compressed_size; pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; } return err; } /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ extern int ZEXPORT unzGoToFirstFile (unzFile file) { int err=UNZ_OK; unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; s->pos_in_central_dir=s->offset_central_dir; s->num_file=0; err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ extern int ZEXPORT unzGoToNextFile (unzFile file) { unz64_s* s; int err; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; if (!s->current_file_ok) return UNZ_END_OF_LIST_OF_FILE; if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ if (s->num_file+1==s->gi.number_entry) return UNZ_END_OF_LIST_OF_FILE; s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; s->num_file++; err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzStringFileNameCompare return value : UNZ_OK if the file is found. It becomes the current file. UNZ_END_OF_LIST_OF_FILE if the file is not found */ extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) { unz64_s* s; int err; /* We remember the 'current' position in the file so that we can jump * back there if we fail. */ unz_file_info64 cur_file_infoSaved; unz_file_info64_internal cur_file_info_internalSaved; ZPOS64_T num_fileSaved; ZPOS64_T pos_in_central_dirSaved; if (file==NULL) return UNZ_PARAMERROR; if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) return UNZ_PARAMERROR; s=(unz64_s*)file; if (!s->current_file_ok) return UNZ_END_OF_LIST_OF_FILE; /* Save the current state */ num_fileSaved = s->num_file; pos_in_central_dirSaved = s->pos_in_central_dir; cur_file_infoSaved = s->cur_file_info; cur_file_info_internalSaved = s->cur_file_info_internal; err = unzGoToFirstFile(file); while (err == UNZ_OK) { char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; err = unzGetCurrentFileInfo64(file,NULL, szCurrentFileName,sizeof(szCurrentFileName)-1, NULL,0,NULL,0); if (err == UNZ_OK) { if (unzStringFileNameCompare(szCurrentFileName, szFileName,iCaseSensitivity)==0) return UNZ_OK; err = unzGoToNextFile(file); } } /* We failed, so restore the state of the 'current file' to where we * were. */ s->num_file = num_fileSaved ; s->pos_in_central_dir = pos_in_central_dirSaved ; s->cur_file_info = cur_file_infoSaved; s->cur_file_info_internal = cur_file_info_internalSaved; return err; } /* /////////////////////////////////////////// // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) // I need random access // // Further optimization could be realized by adding an ability // to cache the directory in memory. The goal being a single // comprehensive file read to put the file I need in a memory. */ /* typedef struct unz_file_pos_s { ZPOS64_T pos_in_zip_directory; // offset in file ZPOS64_T num_of_file; // # of file } unz_file_pos; */ extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) { unz64_s* s; if (file==NULL || file_pos==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; if (!s->current_file_ok) return UNZ_END_OF_LIST_OF_FILE; file_pos->pos_in_zip_directory = s->pos_in_central_dir; file_pos->num_of_file = s->num_file; return UNZ_OK; } extern int ZEXPORT unzGetFilePos( unzFile file, unz_file_pos* file_pos) { unz64_file_pos file_pos64; int err = unzGetFilePos64(file,&file_pos64); if (err==UNZ_OK) { file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; file_pos->num_of_file = (uLong)file_pos64.num_of_file; } return err; } extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) { unz64_s* s; int err; if (file==NULL || file_pos==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; /* jump to the right spot */ s->pos_in_central_dir = file_pos->pos_in_zip_directory; s->num_file = file_pos->num_of_file; /* set the current file */ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); /* return results */ s->current_file_ok = (err == UNZ_OK); return err; } extern int ZEXPORT unzGoToFilePos( unzFile file, unz_file_pos* file_pos) { unz64_file_pos file_pos64; if (file_pos == NULL) return UNZ_PARAMERROR; file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; file_pos64.num_of_file = file_pos->num_of_file; return unzGoToFilePos64(file,&file_pos64); } /* // Unzip Helper Functions - should be here? /////////////////////////////////////////// */ /* Read the local header of the current zipfile Check the coherency of the local header and info in the end of central directory about this file store in *piSizeVar the size of extra info in local header (filename and size of extra field data) */ local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, ZPOS64_T * poffset_local_extrafield, uInt * psize_local_extrafield) { uLong uMagic,uData,uFlags; uLong size_filename; uLong size_extra_field; int err=UNZ_OK; *piSizeVar = 0; *poffset_local_extrafield = 0; *psize_local_extrafield = 0; if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (err==UNZ_OK) { if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) err=UNZ_ERRNO; else if (uMagic!=0x04034b50) err=UNZ_BADZIPFILE; } if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) err=UNZ_ERRNO; /* else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) err=UNZ_BADZIPFILE; */ if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) err=UNZ_BADZIPFILE; if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && /* #ifdef HAVE_BZIP2 */ (s->cur_file_info.compression_method!=Z_BZIP2ED) && /* #endif */ (s->cur_file_info.compression_method!=Z_DEFLATED)) err=UNZ_BADZIPFILE; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ err=UNZ_ERRNO; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ err=UNZ_ERRNO; else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ err=UNZ_ERRNO; else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) err=UNZ_ERRNO; else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) err=UNZ_BADZIPFILE; *piSizeVar += (uInt)size_filename; if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) err=UNZ_ERRNO; *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_filename; *psize_local_extrafield = (uInt)size_extra_field; *piSizeVar += (uInt)size_extra_field; return err; } /* Open for reading data the current file in the zipfile. If there is no error and the file is opened, the return value is UNZ_OK. */ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, int* level, int raw, const char* password) { int err=UNZ_OK; uInt iSizeVar; unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ uInt size_local_extrafield; /* size of the local extra field */ # ifndef NOUNCRYPT char source[12]; # else if (password != NULL) return UNZ_PARAMERROR; # endif if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; if (!s->current_file_ok) return UNZ_PARAMERROR; if (s->pfile_in_zip_read != NULL) unzCloseCurrentFile(file); if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) return UNZ_BADZIPFILE; pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); if (pfile_in_zip_read_info==NULL) return UNZ_INTERNALERROR; pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; pfile_in_zip_read_info->pos_local_extrafield=0; pfile_in_zip_read_info->raw=raw; if (pfile_in_zip_read_info->read_buffer==NULL) { TRYFREE(pfile_in_zip_read_info); return UNZ_INTERNALERROR; } pfile_in_zip_read_info->stream_initialised=0; if (method!=NULL) *method = (int)s->cur_file_info.compression_method; if (level!=NULL) { *level = 6; switch (s->cur_file_info.flag & 0x06) { case 6 : *level = 1; break; case 4 : *level = 2; break; case 2 : *level = 9; break; } } if ((s->cur_file_info.compression_method!=0) && /* #ifdef HAVE_BZIP2 */ (s->cur_file_info.compression_method!=Z_BZIP2ED) && /* #endif */ (s->cur_file_info.compression_method!=Z_DEFLATED)) err=UNZ_BADZIPFILE; pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; pfile_in_zip_read_info->crc32=0; pfile_in_zip_read_info->total_out_64=0; pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; pfile_in_zip_read_info->filestream=s->filestream; pfile_in_zip_read_info->z_filefunc=s->z_filefunc; pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; pfile_in_zip_read_info->stream.total_out = 0; if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) { #ifdef HAVE_BZIP2 pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; pfile_in_zip_read_info->bstream.bzfree = (free_func)0; pfile_in_zip_read_info->bstream.opaque = (voidpf)0; pfile_in_zip_read_info->bstream.state = (voidpf)0; pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; pfile_in_zip_read_info->stream.zfree = (free_func)0; pfile_in_zip_read_info->stream.opaque = (voidpf)0; pfile_in_zip_read_info->stream.next_in = (voidpf)0; pfile_in_zip_read_info->stream.avail_in = 0; err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); if (err == Z_OK) pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; else { TRYFREE(pfile_in_zip_read_info); return err; } #else pfile_in_zip_read_info->raw=1; #endif } else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) { pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; pfile_in_zip_read_info->stream.zfree = (free_func)0; pfile_in_zip_read_info->stream.opaque = (voidpf)0; pfile_in_zip_read_info->stream.next_in = 0; pfile_in_zip_read_info->stream.avail_in = 0; err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); if (err == Z_OK) pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; else { TRYFREE(pfile_in_zip_read_info); return err; } /* windowBits is passed < 0 to tell that there is no zlib header. * Note that in this case inflate *requires* an extra "dummy" byte * after the compressed stream in order to complete decompression and * return Z_STREAM_END. * In unzip, i don't wait absolutely Z_STREAM_END because I known the * size of both compressed and uncompressed data */ } pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size ; pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size ; pfile_in_zip_read_info->pos_in_zipfile = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar; pfile_in_zip_read_info->stream.avail_in = (uInt)0; s->pfile_in_zip_read = pfile_in_zip_read_info; s->encrypted = 0; # ifndef NOUNCRYPT if (password != NULL) { int i; s->pcrc_32_tab = get_crc_table(); init_keys(password,s->keys,s->pcrc_32_tab); if (ZSEEK64(s->z_filefunc, s->filestream, s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile, SEEK_SET)!=0) return UNZ_INTERNALERROR; if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) return UNZ_INTERNALERROR; for (i = 0; i<12; i++) zdecode(s->keys,s->pcrc_32_tab,source[i]); s->pfile_in_zip_read->pos_in_zipfile+=12; s->encrypted=1; } # endif return UNZ_OK; } extern int ZEXPORT unzOpenCurrentFile (unzFile file) { return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); } extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) { return unzOpenCurrentFile3(file, NULL, NULL, 0, password); } extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) { return unzOpenCurrentFile3(file, method, level, raw, NULL); } /** Addition for GDAL : START */ extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; s=(unz64_s*)file; if (file==NULL) return 0; //UNZ_PARAMERROR; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return 0; //UNZ_PARAMERROR; return pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile; } /** Addition for GDAL : END */ /* Read bytes from the current file. buf contain buffer where data must be copied len the size of buf. return the number of byte copied if somes bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) { int err=UNZ_OK; uInt iRead = 0; unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if (pfile_in_zip_read_info->read_buffer == NULL) return UNZ_END_OF_LIST_OF_FILE; if (len==0) return 0; pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; pfile_in_zip_read_info->stream.avail_out = (uInt)len; if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && (!(pfile_in_zip_read_info->raw))) pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed; if ((len>pfile_in_zip_read_info->rest_read_compressed+ pfile_in_zip_read_info->stream.avail_in) && (pfile_in_zip_read_info->raw)) pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_compressed+ pfile_in_zip_read_info->stream.avail_in; while (pfile_in_zip_read_info->stream.avail_out>0) { if ((pfile_in_zip_read_info->stream.avail_in==0) && (pfile_in_zip_read_info->rest_read_compressed>0)) { uInt uReadThis = UNZ_BUFSIZE; if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; if (uReadThis == 0) return UNZ_EOF; if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (ZREAD64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->read_buffer, uReadThis)!=uReadThis) return UNZ_ERRNO; # ifndef NOUNCRYPT if(s->encrypted) { uInt i; for(i=0;iread_buffer[i] = zdecode(s->keys,s->pcrc_32_tab, pfile_in_zip_read_info->read_buffer[i]); } # endif pfile_in_zip_read_info->pos_in_zipfile += uReadThis; pfile_in_zip_read_info->rest_read_compressed-=uReadThis; pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->read_buffer; pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; } if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) { uInt uDoCopy,i ; if ((pfile_in_zip_read_info->stream.avail_in == 0) && (pfile_in_zip_read_info->rest_read_compressed == 0)) return (iRead==0) ? UNZ_EOF : iRead; if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in) uDoCopy = pfile_in_zip_read_info->stream.avail_out ; else uDoCopy = pfile_in_zip_read_info->stream.avail_in ; for (i=0;istream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i); pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, pfile_in_zip_read_info->stream.next_out, uDoCopy); pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; pfile_in_zip_read_info->stream.avail_in -= uDoCopy; pfile_in_zip_read_info->stream.avail_out -= uDoCopy; pfile_in_zip_read_info->stream.next_out += uDoCopy; pfile_in_zip_read_info->stream.next_in += uDoCopy; pfile_in_zip_read_info->stream.total_out += uDoCopy; iRead += uDoCopy; } else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) { #ifdef HAVE_BZIP2 uLong uTotalOutBefore,uTotalOutAfter; const Bytef *bufBefore; uLong uOutThis; pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; pfile_in_zip_read_info->bstream.total_in_hi32 = 0; pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; pfile_in_zip_read_info->bstream.total_out_hi32 = 0; uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; uOutThis = uTotalOutAfter-uTotalOutBefore; pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; if (err==BZ_STREAM_END) return (iRead==0) ? UNZ_EOF : iRead; if (err!=BZ_OK) break; #endif } // end Z_BZIP2ED else { ZPOS64_T uTotalOutBefore,uTotalOutAfter; const Bytef *bufBefore; ZPOS64_T uOutThis; int flush=Z_SYNC_FLUSH; uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; bufBefore = pfile_in_zip_read_info->stream.next_out; /* if ((pfile_in_zip_read_info->rest_read_uncompressed == pfile_in_zip_read_info->stream.avail_out) && (pfile_in_zip_read_info->rest_read_compressed == 0)) flush = Z_FINISH; */ err=inflate(&pfile_in_zip_read_info->stream,flush); if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) err = Z_DATA_ERROR; uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; uOutThis = uTotalOutAfter-uTotalOutBefore; pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); if (err==Z_STREAM_END) return (iRead==0) ? UNZ_EOF : iRead; if (err!=Z_OK) break; } } if (err==Z_OK) return iRead; return err; } /* Give the current position in uncompressed data */ extern z_off_t ZEXPORT unztell (unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; return (z_off_t)pfile_in_zip_read_info->stream.total_out; } extern ZPOS64_T ZEXPORT unztell64 (unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return (ZPOS64_T)-1; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return (ZPOS64_T)-1; return pfile_in_zip_read_info->total_out_64; } /* return 1 if the end of file was reached, 0 elsewhere */ extern int ZEXPORT unzeof (unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if (pfile_in_zip_read_info->rest_read_uncompressed == 0) return 1; else return 0; } /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is more info in the local-header version than in the central-header) if buf==NULL, it return the size of the local extra field that can be read if buf!=NULL, len is the size of the buffer, the extra header is copied in buf. the return value is the number of bytes copied in buf, or (if <0) the error code */ extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; uInt read_now; ZPOS64_T size_to_read; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; size_to_read = (pfile_in_zip_read_info->size_local_extrafield - pfile_in_zip_read_info->pos_local_extrafield); if (buf==NULL) return (int)size_to_read; if (len>size_to_read) read_now = (uInt)size_to_read; else read_now = (uInt)len ; if (read_now==0) return 0; if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield, ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (ZREAD64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, buf,read_now)!=read_now) return UNZ_ERRNO; return (int)read_now; } /* Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ extern int ZEXPORT unzCloseCurrentFile (unzFile file) { int err=UNZ_OK; unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && (!pfile_in_zip_read_info->raw)) { if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) err=UNZ_CRCERROR; } TRYFREE(pfile_in_zip_read_info->read_buffer); pfile_in_zip_read_info->read_buffer = NULL; if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) inflateEnd(&pfile_in_zip_read_info->stream); #ifdef HAVE_BZIP2 else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); #endif pfile_in_zip_read_info->stream_initialised = 0; TRYFREE(pfile_in_zip_read_info); s->pfile_in_zip_read=NULL; return err; } /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) { unz64_s* s; uLong uReadThis ; if (file==NULL) return (int)UNZ_PARAMERROR; s=(unz64_s*)file; uReadThis = uSizeBuf; if (uReadThis>s->gi.size_comment) uReadThis = s->gi.size_comment; if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (uReadThis>0) { *szComment='\0'; if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) return UNZ_ERRNO; } if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) *(szComment+s->gi.size_comment)='\0'; return (int)uReadThis; } /* Additions by RX '2004 */ extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) { unz64_s* s; if (file==NULL) return 0; //UNZ_PARAMERROR; s=(unz64_s*)file; if (!s->current_file_ok) return 0; if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) if (s->num_file==s->gi.number_entry) return 0; return s->pos_in_central_dir; } extern uLong ZEXPORT unzGetOffset (unzFile file) { ZPOS64_T offset64; if (file==NULL) return 0; //UNZ_PARAMERROR; offset64 = unzGetOffset64(file); return (uLong)offset64; } extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) { unz64_s* s; int err; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; s->pos_in_central_dir = pos; s->num_file = s->gi.number_entry; /* hack */ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) { return unzSetOffset64(file,pos); } tcl8.6.5/compat/zlib/contrib/minizip/MiniZip64_info.txt0000644000175000017500000000575012663653206022444 0ustar sergeisergeiMiniZip - Copyright (c) 1998-2010 - by Gilles Vollant - version 1.1 64 bits from Mathias Svensson Introduction --------------------- MiniZip 1.1 is built from MiniZip 1.0 by Gilles Vollant ( http://www.winimage.com/zLibDll/minizip.html ) When adding ZIP64 support into minizip it would result into risk of breaking compatibility with minizip 1.0. All possible work was done for compatibility. Background --------------------- When adding ZIP64 support Mathias Svensson found that Even Rouault have added ZIP64 support for unzip.c into minizip for a open source project called gdal ( http://www.gdal.org/ ) That was used as a starting point. And after that ZIP64 support was added to zip.c some refactoring and code cleanup was also done. Changed from MiniZip 1.0 to MiniZip 1.1 --------------------------------------- * Added ZIP64 support for unzip ( by Even Rouault ) * Added ZIP64 support for zip ( by Mathias Svensson ) * Reverted some changed that Even Rouault did. * Bunch of patches received from Gulles Vollant that he received for MiniZip from various users. * Added unzip patch for BZIP Compression method (patch create by Daniel Borca) * Added BZIP Compress method for zip * Did some refactoring and code cleanup Credits Gilles Vollant - Original MiniZip author Even Rouault - ZIP64 unzip Support Daniel Borca - BZip Compression method support in unzip Mathias Svensson - ZIP64 zip support Mathias Svensson - BZip Compression method support in zip Resources ZipLayout http://result42.com/projects/ZipFileLayout Command line tool for Windows that shows the layout and information of the headers in a zip archive. Used when debugging and validating the creation of zip files using MiniZip64 ZIP App Note http://www.pkware.com/documents/casestudies/APPNOTE.TXT Zip File specification Notes. * To be able to use BZip compression method in zip64.c or unzip64.c the BZIP2 lib is needed and HAVE_BZIP2 need to be defined. License ---------------------------------------------------------- Condition of use and distribution are the same than zlib : This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. ---------------------------------------------------------- tcl8.6.5/compat/zlib/contrib/minizip/configure.ac0000644000175000017500000000142212663660064021415 0ustar sergeisergei# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_INIT([minizip], [1.2.8], [bugzilla.redhat.com]) AC_CONFIG_SRCDIR([minizip.c]) AM_INIT_AUTOMAKE([foreign]) LT_INIT AC_MSG_CHECKING([whether to build example programs]) AC_ARG_ENABLE([demos], AC_HELP_STRING([--enable-demos], [build example programs])) AM_CONDITIONAL([COND_DEMOS], [test "$enable_demos" = yes]) if test "$enable_demos" = yes then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi case "${host}" in *-mingw* | mingw*) WIN32="yes" ;; *) ;; esac AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"]) AC_SUBST([HAVE_UNISTD_H], [0]) AC_CHECK_HEADER([unistd.h], [HAVE_UNISTD_H=1], []) AC_CONFIG_FILES([Makefile minizip.pc]) AC_OUTPUT tcl8.6.5/compat/zlib/contrib/minizip/zip.h0000644000175000017500000003600612663653206020110 0ustar sergeisergei/* zip.h -- IO on .zip files using zlib Version 1.1, February 14h, 2010 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt --------------------------------------------------------------------------- Condition of use and distribution are the same than zlib : This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. --------------------------------------------------------------------------- Changes See header of zip.h */ #ifndef _zip12_H #define _zip12_H #ifdef __cplusplus extern "C" { #endif //#define HAVE_BZIP2 #ifndef _ZLIB_H #include "zlib.h" #endif #ifndef _ZLIBIOAPI_H #include "ioapi.h" #endif #ifdef HAVE_BZIP2 #include "bzlib.h" #endif #define Z_BZIP2ED 12 #if defined(STRICTZIP) || defined(STRICTZIPUNZIP) /* like the STRICT of WIN32, we define a pointer that cannot be converted from (void*) without cast */ typedef struct TagzipFile__ { int unused; } zipFile__; typedef zipFile__ *zipFile; #else typedef voidp zipFile; #endif #define ZIP_OK (0) #define ZIP_EOF (0) #define ZIP_ERRNO (Z_ERRNO) #define ZIP_PARAMERROR (-102) #define ZIP_BADZIPFILE (-103) #define ZIP_INTERNALERROR (-104) #ifndef DEF_MEM_LEVEL # if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 # else # define DEF_MEM_LEVEL MAX_MEM_LEVEL # endif #endif /* default memLevel */ /* tm_zip contain date/time info */ typedef struct tm_zip_s { uInt tm_sec; /* seconds after the minute - [0,59] */ uInt tm_min; /* minutes after the hour - [0,59] */ uInt tm_hour; /* hours since midnight - [0,23] */ uInt tm_mday; /* day of the month - [1,31] */ uInt tm_mon; /* months since January - [0,11] */ uInt tm_year; /* years - [1980..2044] */ } tm_zip; typedef struct { tm_zip tmz_date; /* date in understandable format */ uLong dosDate; /* if dos_date == 0, tmu_date is used */ /* uLong flag; */ /* general purpose bit flag 2 bytes */ uLong internal_fa; /* internal file attributes 2 bytes */ uLong external_fa; /* external file attributes 4 bytes */ } zip_fileinfo; typedef const char* zipcharpc; #define APPEND_STATUS_CREATE (0) #define APPEND_STATUS_CREATEAFTER (1) #define APPEND_STATUS_ADDINZIP (2) extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); /* Create a zipfile. pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on an Unix computer "zlib/zlib113.zip". if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip will be created at the end of the file. (useful if the file contain a self extractor code) if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will add files in existing zip (be sure you don't add file that doesn't exist) If the zipfile cannot be opened, the return value is NULL. Else, the return value is a zipFile Handle, usable with other function of this zip package. */ /* Note : there is no delete function into a zipfile. If you want delete file into a zipfile, you must open a zipfile, and create another Of couse, you can use RAW reading and writing to copy the file you did not want delte */ extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc_def)); extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def)); extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level)); extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int zip64)); /* Open a file in the ZIP for writing. filename : the filename in zip (if NULL, '-' without quote will be used *zipfi contain supplemental information if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local contains the extrafield data the the local header if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global contains the extrafield data the the local header if comment != NULL, comment contain the comment string method contain the compression method (0 for store, Z_DEFLATED for deflate) level contain the level of compression (can be Z_DEFAULT_COMPRESSION) zip64 is set to 1 if a zip64 extended information block should be added to the local file header. this MUST be '1' if the uncompressed size is >= 0xffffffff. */ extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw)); extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int zip64)); /* Same than zipOpenNewFileInZip, except if raw=1, we write raw file */ extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel, int strategy, const char* password, uLong crcForCrypting)); extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel, int strategy, const char* password, uLong crcForCrypting, int zip64 )); /* Same than zipOpenNewFileInZip2, except windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 password : crypting password (NULL for no crypting) crcForCrypting : crc of file to compress (needed for crypting) */ extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel, int strategy, const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase )); extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel, int strategy, const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase, int zip64 )); /* Same than zipOpenNewFileInZip4, except versionMadeBy : value for Version made by field flag : value for flag field (compression level info will be added) */ extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, const void* buf, unsigned len)); /* Write data in the zipfile */ extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); /* Close the current file in the zipfile */ extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, uLong uncompressed_size, uLong crc32)); extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, ZPOS64_T uncompressed_size, uLong crc32)); /* Close the current file in the zipfile, for file opened with parameter raw=1 in zipOpenNewFileInZip2 uncompressed_size and crc32 are value for the uncompressed size */ extern int ZEXPORT zipClose OF((zipFile file, const char* global_comment)); /* Close the zipfile */ extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); /* zipRemoveExtraInfoBlock - Added by Mathias Svensson Remove extra information block from a extra information data for the local file header or central directory header It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode. 0x0001 is the signature header for the ZIP64 extra information blocks usage. Remove ZIP64 Extra information from a central director extra field data zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001); Remove ZIP64 Extra information from a Local File Header extra field data zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001); */ #ifdef __cplusplus } #endif #endif /* _zip64_H */ tcl8.6.5/compat/zlib/contrib/minizip/crypt.h0000644000175000017500000001117712663660064020451 0ustar sergeisergei/* crypt.h -- base code for crypt/uncrypt ZIPfile Version 1.01e, February 12th, 2005 Copyright (C) 1998-2005 Gilles Vollant This code is a modified version of crypting code in Infozip distribution The encryption/decryption parts of this source code (as opposed to the non-echoing password parts) were originally written in Europe. The whole source package can be freely distributed, including from the USA. (Prior to January 2000, re-export from the US was a violation of US law.) This encryption code is a direct transcription of the algorithm from Roger Schlafly, described by Phil Katz in the file appnote.txt. This file (appnote.txt) is distributed with the PKZIP program (even in the version without encryption capabilities). If you don't need crypting in your application, just define symbols NOCRYPT and NOUNCRYPT. This code support the "Traditional PKWARE Encryption". The new AES encryption added on Zip format by Winzip (see the page http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong Encryption is not supported. */ #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) /*********************************************************************** * Return the next byte in the pseudo-random sequence */ static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) { unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an * unpredictable manner on 16-bit systems; not a problem * with any known compiler so far, though */ temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); } /*********************************************************************** * Update the encryption keys with the next byte of plain text */ static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) { (*(pkeys+0)) = CRC32((*(pkeys+0)), c); (*(pkeys+1)) += (*(pkeys+0)) & 0xff; (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; { register int keyshift = (int)((*(pkeys+1)) >> 24); (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); } return c; } /*********************************************************************** * Initialize the encryption keys and the random header according to * the given password. */ static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) { *(pkeys+0) = 305419896L; *(pkeys+1) = 591751049L; *(pkeys+2) = 878082192L; while (*passwd != '\0') { update_keys(pkeys,pcrc_32_tab,(int)*passwd); passwd++; } } #define zdecode(pkeys,pcrc_32_tab,c) \ (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) #define zencode(pkeys,pcrc_32_tab,c,t) \ (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED #define RAND_HEAD_LEN 12 /* "last resort" source for second part of crypt seed pattern */ # ifndef ZCR_SEED2 # define ZCR_SEED2 3141592654UL /* use PI as default pattern */ # endif static int crypthead(const char* passwd, /* password string */ unsigned char* buf, /* where to write header */ int bufSize, unsigned long* pkeys, const z_crc_t* pcrc_32_tab, unsigned long crcForCrypting) { int n; /* index in random header */ int t; /* temporary */ int c; /* random byte */ unsigned char header[RAND_HEAD_LEN-2]; /* random header */ static unsigned calls = 0; /* ensure different random header each time */ if (bufSize> 7) & 0xff; header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); } /* Encrypt random header (last two bytes is high word of crc) */ init_keys(passwd, pkeys, pcrc_32_tab); for (n = 0; n < RAND_HEAD_LEN-2; n++) { buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); } buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); return n; } #endif tcl8.6.5/compat/zlib/contrib/minizip/Makefile0000644000175000017500000000071112663653131020564 0ustar sergeisergeiCC=cc CFLAGS=-O -I../.. UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a .c.o: $(CC) -c $(CFLAGS) $*.c all: miniunz minizip miniunz: $(UNZ_OBJS) $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS) minizip: $(ZIP_OBJS) $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) test: miniunz minizip ./minizip test readme.txt ./miniunz -l test.zip mv readme.txt readme.old ./miniunz test.zip clean: /bin/rm -f *.o *~ minizip miniunz tcl8.6.5/compat/zlib/contrib/minizip/zip.c0000644000175000017500000020047212663660064020103 0ustar sergeisergei/* zip.c -- IO on .zip files using zlib Version 1.1, February 14h, 2010 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt Changes Oct-2009 - Mathias Svensson - Remove old C style function prototypes Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data It is used when recreting zip archive with RAW when deleting items from a zip. ZIP64 data is automaticly added to items that needs it, and existing ZIP64 data need to be removed. Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer */ #include #include #include #include #include "zlib.h" #include "zip.h" #ifdef STDC # include # include # include #endif #ifdef NO_ERRNO_H extern int errno; #else # include #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ #ifndef VERSIONMADEBY # define VERSIONMADEBY (0x0) /* platform depedent */ #endif #ifndef Z_BUFSIZE #define Z_BUFSIZE (64*1024) //(16384) #endif #ifndef Z_MAXFILENAMEINZIP #define Z_MAXFILENAMEINZIP (256) #endif #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif #ifndef TRYFREE # define TRYFREE(p) {if (p) free(p);} #endif /* #define SIZECENTRALDIRITEM (0x2e) #define SIZEZIPLOCALHEADER (0x1e) */ /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ // NOT sure that this work on ALL platform #define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef DEF_MEM_LEVEL #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif #endif const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; #define SIZEDATA_INDATABLOCK (4096-(4*4)) #define LOCALHEADERMAGIC (0x04034b50) #define CENTRALHEADERMAGIC (0x02014b50) #define ENDHEADERMAGIC (0x06054b50) #define ZIP64ENDHEADERMAGIC (0x6064b50) #define ZIP64ENDLOCHEADERMAGIC (0x7064b50) #define FLAG_LOCALHEADER_OFFSET (0x06) #define CRC_LOCALHEADER_OFFSET (0x0e) #define SIZECENTRALHEADER (0x2e) /* 46 */ typedef struct linkedlist_datablock_internal_s { struct linkedlist_datablock_internal_s* next_datablock; uLong avail_in_this_block; uLong filled_in_this_block; uLong unused; /* for future use and alignement */ unsigned char data[SIZEDATA_INDATABLOCK]; } linkedlist_datablock_internal; typedef struct linkedlist_data_s { linkedlist_datablock_internal* first_block; linkedlist_datablock_internal* last_block; } linkedlist_data; typedef struct { z_stream stream; /* zLib stream structure for inflate */ #ifdef HAVE_BZIP2 bz_stream bstream; /* bzLib stream structure for bziped */ #endif int stream_initialised; /* 1 is stream is initialised */ uInt pos_in_buffered_data; /* last written byte in buffered_data */ ZPOS64_T pos_local_header; /* offset of the local header of the file currenty writing */ char* central_header; /* central header data for the current file */ uLong size_centralExtra; uLong size_centralheader; /* size of the central header for cur file */ uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ uLong flag; /* flag of the file currently writing */ int method; /* compression method of file currenty wr.*/ int raw; /* 1 for directly writing raw data */ Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ uLong dosDate; uLong crc32; int encrypt; int zip64; /* Add ZIP64 extened information in the extra field */ ZPOS64_T pos_zip64extrainfo; ZPOS64_T totalCompressedData; ZPOS64_T totalUncompressedData; #ifndef NOCRYPT unsigned long keys[3]; /* keys defining the pseudo-random sequence */ const z_crc_t* pcrc_32_tab; int crypt_header_size; #endif } curfile64_info; typedef struct { zlib_filefunc64_32_def z_filefunc; voidpf filestream; /* io structore of the zipfile */ linkedlist_data central_dir;/* datablock with central dir in construction*/ int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ curfile64_info ci; /* info on the file curretly writing */ ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ ZPOS64_T add_position_when_writting_offset; ZPOS64_T number_entry; #ifndef NO_ADDFILEINEXISTINGZIP char *globalcomment; #endif } zip64_internal; #ifndef NOCRYPT #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED #include "crypt.h" #endif local linkedlist_datablock_internal* allocate_new_datablock() { linkedlist_datablock_internal* ldi; ldi = (linkedlist_datablock_internal*) ALLOC(sizeof(linkedlist_datablock_internal)); if (ldi!=NULL) { ldi->next_datablock = NULL ; ldi->filled_in_this_block = 0 ; ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; } return ldi; } local void free_datablock(linkedlist_datablock_internal* ldi) { while (ldi!=NULL) { linkedlist_datablock_internal* ldinext = ldi->next_datablock; TRYFREE(ldi); ldi = ldinext; } } local void init_linkedlist(linkedlist_data* ll) { ll->first_block = ll->last_block = NULL; } local void free_linkedlist(linkedlist_data* ll) { free_datablock(ll->first_block); ll->first_block = ll->last_block = NULL; } local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) { linkedlist_datablock_internal* ldi; const unsigned char* from_copy; if (ll==NULL) return ZIP_INTERNALERROR; if (ll->last_block == NULL) { ll->first_block = ll->last_block = allocate_new_datablock(); if (ll->first_block == NULL) return ZIP_INTERNALERROR; } ldi = ll->last_block; from_copy = (unsigned char*)buf; while (len>0) { uInt copy_this; uInt i; unsigned char* to_copy; if (ldi->avail_in_this_block==0) { ldi->next_datablock = allocate_new_datablock(); if (ldi->next_datablock == NULL) return ZIP_INTERNALERROR; ldi = ldi->next_datablock ; ll->last_block = ldi; } if (ldi->avail_in_this_block < len) copy_this = (uInt)ldi->avail_in_this_block; else copy_this = (uInt)len; to_copy = &(ldi->data[ldi->filled_in_this_block]); for (i=0;ifilled_in_this_block += copy_this; ldi->avail_in_this_block -= copy_this; from_copy += copy_this ; len -= copy_this; } return ZIP_OK; } /****************************************************************************/ #ifndef NO_ADDFILEINEXISTINGZIP /* =========================================================================== Inputs a long in LSB order to the given file nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) */ local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) { unsigned char buf[8]; int n; for (n = 0; n < nbByte; n++) { buf[n] = (unsigned char)(x & 0xff); x >>= 8; } if (x != 0) { /* data overflow - hack for ZIP64 (X Roche) */ for (n = 0; n < nbByte; n++) { buf[n] = 0xff; } } if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) return ZIP_ERRNO; else return ZIP_OK; } local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) { unsigned char* buf=(unsigned char*)dest; int n; for (n = 0; n < nbByte; n++) { buf[n] = (unsigned char)(x & 0xff); x >>= 8; } if (x != 0) { /* data overflow - hack for ZIP64 */ for (n = 0; n < nbByte; n++) { buf[n] = 0xff; } } } /****************************************************************************/ local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) { uLong year = (uLong)ptm->tm_year; if (year>=1980) year-=1980; else if (year>=80) year-=80; return (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); } /****************************************************************************/ local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) { unsigned char c; int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); if (err==1) { *pi = (int)c; return ZIP_OK; } else { if (ZERROR64(*pzlib_filefunc_def,filestream)) return ZIP_ERRNO; else return ZIP_EOF; } } /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { uLong x ; int i = 0; int err; err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x = (uLong)i; if (err==ZIP_OK) err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<8; if (err==ZIP_OK) *pX = x; else *pX = 0; return err; } local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) { uLong x ; int i = 0; int err; err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x = (uLong)i; if (err==ZIP_OK) err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<8; if (err==ZIP_OK) err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<16; if (err==ZIP_OK) err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<24; if (err==ZIP_OK) *pX = x; else *pX = 0; return err; } local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) { ZPOS64_T x; int i = 0; int err; err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x = (ZPOS64_T)i; if (err==ZIP_OK) err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((ZPOS64_T)i)<<8; if (err==ZIP_OK) err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((ZPOS64_T)i)<<16; if (err==ZIP_OK) err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((ZPOS64_T)i)<<24; if (err==ZIP_OK) err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((ZPOS64_T)i)<<32; if (err==ZIP_OK) err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((ZPOS64_T)i)<<40; if (err==ZIP_OK) err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((ZPOS64_T)i)<<48; if (err==ZIP_OK) err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((ZPOS64_T)i)<<56; if (err==ZIP_OK) *pX = x; else *pX = 0; return err; } #ifndef BUFREADCOMMENT #define BUFREADCOMMENT (0x400) #endif /* Locate the Central directory of a zipfile (at the end, just before the global comment) */ local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ ZPOS64_T uPosFound=0; if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) return 0; uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) return 0; uBackRead = 4; while (uBackReaduMaxBack) uBackRead = uMaxBack; else uBackRead+=BUFREADCOMMENT; uReadPos = uSizeFile-uBackRead ; uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) break; if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) break; for (i=(int)uReadSize-3; (i--)>0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) { uPosFound = uReadPos+i; break; } if (uPosFound!=0) break; } TRYFREE(buf); return uPosFound; } /* Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before the global comment) */ local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ ZPOS64_T uPosFound=0; uLong uL; ZPOS64_T relativeOffset; if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) return 0; uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) return 0; uBackRead = 4; while (uBackReaduMaxBack) uBackRead = uMaxBack; else uBackRead+=BUFREADCOMMENT; uReadPos = uSizeFile-uBackRead ; uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) break; if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) break; for (i=(int)uReadSize-3; (i--)>0;) { // Signature "0x07064b50" Zip64 end of central directory locater if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) { uPosFound = uReadPos+i; break; } } if (uPosFound!=0) break; } TRYFREE(buf); if (uPosFound == 0) return 0; /* Zip64 end of central directory locator */ if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) return 0; /* the signature, already checked */ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return 0; /* number of the disk with the start of the zip64 end of central directory */ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return 0; if (uL != 0) return 0; /* relative offset of the zip64 end of central directory record */ if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) return 0; /* total number of disks */ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return 0; if (uL != 1) return 0; /* Goto Zip64 end of central directory record */ if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) return 0; /* the signature */ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return 0; if (uL != 0x06064b50) // signature of 'Zip64 end of central directory' return 0; return relativeOffset; } int LoadCentralDirectoryRecord(zip64_internal* pziinit) { int err=ZIP_OK; ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ ZPOS64_T size_central_dir; /* size of the central directory */ ZPOS64_T offset_central_dir; /* offset of start of central directory */ ZPOS64_T central_pos; uLong uL; uLong number_disk; /* number of the current dist, used for spaning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used for spaning ZIP, unsupported, always 0*/ ZPOS64_T number_entry; ZPOS64_T number_entry_CD; /* total number of entries in the central dir (same than number_entry on nospan) */ uLong VersionMadeBy; uLong VersionNeeded; uLong size_comment; int hasZIP64Record = 0; // check first if we find a ZIP64 record central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); if(central_pos > 0) { hasZIP64Record = 1; } else if(central_pos == 0) { central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream); } /* disable to allow appending to empty ZIP archive if (central_pos==0) err=ZIP_ERRNO; */ if(hasZIP64Record) { ZPOS64_T sizeEndOfCentralDirectory; if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) err=ZIP_ERRNO; /* the signature, already checked */ if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) err=ZIP_ERRNO; /* size of zip64 end of central directory record */ if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK) err=ZIP_ERRNO; /* version made by */ if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK) err=ZIP_ERRNO; /* version needed to extract */ if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK) err=ZIP_ERRNO; /* number of this disk */ if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) err=ZIP_ERRNO; /* number of the disk with the start of the central directory */ if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) err=ZIP_ERRNO; /* total number of entries in the central directory on this disk */ if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK) err=ZIP_ERRNO; /* total number of entries in the central directory */ if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK) err=ZIP_ERRNO; if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=ZIP_BADZIPFILE; /* size of the central directory */ if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK) err=ZIP_ERRNO; /* offset of start of central directory with respect to the starting disk number */ if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) err=ZIP_ERRNO; // TODO.. // read the comment from the standard central header. size_comment = 0; } else { // Read End of central Directory info if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) err=ZIP_ERRNO; /* the signature, already checked */ if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) err=ZIP_ERRNO; /* number of this disk */ if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) err=ZIP_ERRNO; /* number of the disk with the start of the central directory */ if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) err=ZIP_ERRNO; /* total number of entries in the central dir on this disk */ number_entry = 0; if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) err=ZIP_ERRNO; else number_entry = uL; /* total number of entries in the central dir */ number_entry_CD = 0; if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) err=ZIP_ERRNO; else number_entry_CD = uL; if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=ZIP_BADZIPFILE; /* size of the central directory */ size_central_dir = 0; if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) err=ZIP_ERRNO; else size_central_dir = uL; /* offset of start of central directory with respect to the starting disk number */ offset_central_dir = 0; if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) err=ZIP_ERRNO; else offset_central_dir = uL; /* zipfile global comment length */ if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK) err=ZIP_ERRNO; } if ((central_posz_filefunc, pziinit->filestream); return ZIP_ERRNO; } if (size_comment>0) { pziinit->globalcomment = (char*)ALLOC(size_comment+1); if (pziinit->globalcomment) { size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment); pziinit->globalcomment[size_comment]=0; } } byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); pziinit->add_position_when_writting_offset = byte_before_the_zipfile; { ZPOS64_T size_central_dir_to_read = size_central_dir; size_t buf_size = SIZEDATA_INDATABLOCK; void* buf_read = (void*)ALLOC(buf_size); if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) err=ZIP_ERRNO; while ((size_central_dir_to_read>0) && (err==ZIP_OK)) { ZPOS64_T read_this = SIZEDATA_INDATABLOCK; if (read_this > size_central_dir_to_read) read_this = size_central_dir_to_read; if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this) err=ZIP_ERRNO; if (err==ZIP_OK) err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); size_central_dir_to_read-=read_this; } TRYFREE(buf_read); } pziinit->begin_pos = byte_before_the_zipfile; pziinit->number_entry = number_entry_CD; if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) err=ZIP_ERRNO; return err; } #endif /* !NO_ADDFILEINEXISTINGZIP*/ /************************************************************/ extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) { zip64_internal ziinit; zip64_internal* zi; int err=ZIP_OK; ziinit.z_filefunc.zseek32_file = NULL; ziinit.z_filefunc.ztell32_file = NULL; if (pzlib_filefunc64_32_def==NULL) fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); else ziinit.z_filefunc = *pzlib_filefunc64_32_def; ziinit.filestream = ZOPEN64(ziinit.z_filefunc, pathname, (append == APPEND_STATUS_CREATE) ? (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); if (ziinit.filestream == NULL) return NULL; if (append == APPEND_STATUS_CREATEAFTER) ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream); ziinit.in_opened_file_inzip = 0; ziinit.ci.stream_initialised = 0; ziinit.number_entry = 0; ziinit.add_position_when_writting_offset = 0; init_linkedlist(&(ziinit.central_dir)); zi = (zip64_internal*)ALLOC(sizeof(zip64_internal)); if (zi==NULL) { ZCLOSE64(ziinit.z_filefunc,ziinit.filestream); return NULL; } /* now we add file in a zipfile */ # ifndef NO_ADDFILEINEXISTINGZIP ziinit.globalcomment = NULL; if (append == APPEND_STATUS_ADDINZIP) { // Read and Cache Central Directory Records err = LoadCentralDirectoryRecord(&ziinit); } if (globalcomment) { *globalcomment = ziinit.globalcomment; } # endif /* !NO_ADDFILEINEXISTINGZIP*/ if (err != ZIP_OK) { # ifndef NO_ADDFILEINEXISTINGZIP TRYFREE(ziinit.globalcomment); # endif /* !NO_ADDFILEINEXISTINGZIP*/ TRYFREE(zi); return NULL; } else { *zi = ziinit; return (zipFile)zi; } } extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) { if (pzlib_filefunc32_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); } else return zipOpen3(pathname, append, globalcomment, NULL); } extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) { if (pzlib_filefunc_def != NULL) { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; zlib_filefunc64_32_def_fill.ztell32_file = NULL; zlib_filefunc64_32_def_fill.zseek32_file = NULL; return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); } else return zipOpen3(pathname, append, globalcomment, NULL); } extern zipFile ZEXPORT zipOpen (const char* pathname, int append) { return zipOpen3((const void*)pathname,append,NULL,NULL); } extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) { return zipOpen3(pathname,append,NULL,NULL); } int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) { /* write the local header */ int err; uInt size_filename = (uInt)strlen(filename); uInt size_extrafield = size_extrafield_local; err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4); if (err==ZIP_OK) { if(zi->ci.zip64) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ else err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ } if (err==ZIP_OK) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); if (err==ZIP_OK) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); if (err==ZIP_OK) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later if (err==ZIP_OK) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ if (err==ZIP_OK) { if(zi->ci.zip64) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ else err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ } if (err==ZIP_OK) { if(zi->ci.zip64) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ else err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ } if (err==ZIP_OK) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); if(zi->ci.zip64) { size_extrafield += 20; } if (err==ZIP_OK) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2); if ((err==ZIP_OK) && (size_filename > 0)) { if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) err = ZIP_ERRNO; } if ((err==ZIP_OK) && (size_extrafield_local > 0)) { if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) err = ZIP_ERRNO; } if ((err==ZIP_OK) && (zi->ci.zip64)) { // write the Zip64 extended info short HeaderID = 1; short DataSize = 16; ZPOS64_T CompressedSize = 0; ZPOS64_T UncompressedSize = 0; // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); } return err; } /* NOTE. When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped before calling this function it can be done with zipRemoveExtraInfoBlock It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize unnecessary allocations. */ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits,int memLevel, int strategy, const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase, int zip64) { zip64_internal* zi; uInt size_filename; uInt size_comment; uInt i; int err = ZIP_OK; # ifdef NOCRYPT (crcForCrypting); if (password != NULL) return ZIP_PARAMERROR; # endif if (file == NULL) return ZIP_PARAMERROR; #ifdef HAVE_BZIP2 if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) return ZIP_PARAMERROR; #else if ((method!=0) && (method!=Z_DEFLATED)) return ZIP_PARAMERROR; #endif zi = (zip64_internal*)file; if (zi->in_opened_file_inzip == 1) { err = zipCloseFileInZip (file); if (err != ZIP_OK) return err; } if (filename==NULL) filename="-"; if (comment==NULL) size_comment = 0; else size_comment = (uInt)strlen(comment); size_filename = (uInt)strlen(filename); if (zipfi == NULL) zi->ci.dosDate = 0; else { if (zipfi->dosDate != 0) zi->ci.dosDate = zipfi->dosDate; else zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); } zi->ci.flag = flagBase; if ((level==8) || (level==9)) zi->ci.flag |= 2; if (level==2) zi->ci.flag |= 4; if (level==1) zi->ci.flag |= 6; if (password != NULL) zi->ci.flag |= 1; zi->ci.crc32 = 0; zi->ci.method = method; zi->ci.encrypt = 0; zi->ci.stream_initialised = 0; zi->ci.pos_in_buffered_data = 0; zi->ci.raw = raw; zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); zi->ci.size_centralExtra = size_extrafield_global; zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); /* version info */ zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ if (zipfi==NULL) zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); else zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); if (zipfi==NULL) zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); else zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); if(zi->ci.pos_local_header >= 0xffffffff) zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); else zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset,4); for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = *(((const char*)extrafield_global)+i); for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ size_extrafield_global+i) = *(comment+i); if (zi->ci.central_header == NULL) return ZIP_INTERNALERROR; zi->ci.zip64 = zip64; zi->ci.totalCompressedData = 0; zi->ci.totalUncompressedData = 0; zi->ci.pos_zip64extrainfo = 0; err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local); #ifdef HAVE_BZIP2 zi->ci.bstream.avail_in = (uInt)0; zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; zi->ci.bstream.total_in_hi32 = 0; zi->ci.bstream.total_in_lo32 = 0; zi->ci.bstream.total_out_hi32 = 0; zi->ci.bstream.total_out_lo32 = 0; #endif zi->ci.stream.avail_in = (uInt)0; zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; zi->ci.stream.total_in = 0; zi->ci.stream.total_out = 0; zi->ci.stream.data_type = Z_BINARY; #ifdef HAVE_BZIP2 if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) #else if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) #endif { if(zi->ci.method == Z_DEFLATED) { zi->ci.stream.zalloc = (alloc_func)0; zi->ci.stream.zfree = (free_func)0; zi->ci.stream.opaque = (voidpf)0; if (windowBits>0) windowBits = -windowBits; err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); if (err==Z_OK) zi->ci.stream_initialised = Z_DEFLATED; } else if(zi->ci.method == Z_BZIP2ED) { #ifdef HAVE_BZIP2 // Init BZip stuff here zi->ci.bstream.bzalloc = 0; zi->ci.bstream.bzfree = 0; zi->ci.bstream.opaque = (voidpf)0; err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35); if(err == BZ_OK) zi->ci.stream_initialised = Z_BZIP2ED; #endif } } # ifndef NOCRYPT zi->ci.crypt_header_size = 0; if ((err==Z_OK) && (password != NULL)) { unsigned char bufHead[RAND_HEAD_LEN]; unsigned int sizeHead; zi->ci.encrypt = 1; zi->ci.pcrc_32_tab = get_crc_table(); /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); zi->ci.crypt_header_size = sizeHead; if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) err = ZIP_ERRNO; } # endif if (err==Z_OK) zi->in_opened_file_inzip = 1; return err; } extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits,int memLevel, int strategy, const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase) { return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel, strategy, password, crcForCrypting, versionMadeBy, flagBase, 0); } extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits,int memLevel, int strategy, const char* password, uLong crcForCrypting) { return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel, strategy, password, crcForCrypting, VERSIONMADEBY, 0, 0); } extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits,int memLevel, int strategy, const char* password, uLong crcForCrypting, int zip64) { return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel, strategy, password, crcForCrypting, VERSIONMADEBY, 0, zip64); } extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw) { return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, 0); } extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int raw, int zip64) { return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, zip64); } extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void*extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level, int zip64) { return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, zip64); } extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, uInt size_extrafield_local, const void*extrafield_global, uInt size_extrafield_global, const char* comment, int method, int level) { return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, 0); } local int zip64FlushWriteBuffer(zip64_internal* zi) { int err=ZIP_OK; if (zi->ci.encrypt != 0) { #ifndef NOCRYPT uInt i; int t; for (i=0;ici.pos_in_buffered_data;i++) zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t); #endif } if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data) err = ZIP_ERRNO; zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data; #ifdef HAVE_BZIP2 if(zi->ci.method == Z_BZIP2ED) { zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32; zi->ci.bstream.total_in_lo32 = 0; zi->ci.bstream.total_in_hi32 = 0; } else #endif { zi->ci.totalUncompressedData += zi->ci.stream.total_in; zi->ci.stream.total_in = 0; } zi->ci.pos_in_buffered_data = 0; return err; } extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) { zip64_internal* zi; int err=ZIP_OK; if (file == NULL) return ZIP_PARAMERROR; zi = (zip64_internal*)file; if (zi->in_opened_file_inzip == 0) return ZIP_PARAMERROR; zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len); #ifdef HAVE_BZIP2 if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw)) { zi->ci.bstream.next_in = (void*)buf; zi->ci.bstream.avail_in = len; err = BZ_RUN_OK; while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0)) { if (zi->ci.bstream.avail_out == 0) { if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) err = ZIP_ERRNO; zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; } if(err != BZ_RUN_OK) break; if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) { uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; // uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN); zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ; } } if(err == BZ_RUN_OK) err = ZIP_OK; } else #endif { zi->ci.stream.next_in = (Bytef*)buf; zi->ci.stream.avail_in = len; while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) { if (zi->ci.stream.avail_out == 0) { if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) err = ZIP_ERRNO; zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; } if(err != ZIP_OK) break; if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) { uLong uTotalOutBefore = zi->ci.stream.total_out; err=deflate(&zi->ci.stream, Z_NO_FLUSH); if(uTotalOutBefore > zi->ci.stream.total_out) { int bBreak = 0; bBreak++; } zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; } else { uInt copy_this,i; if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) copy_this = zi->ci.stream.avail_in; else copy_this = zi->ci.stream.avail_out; for (i = 0; i < copy_this; i++) *(((char*)zi->ci.stream.next_out)+i) = *(((const char*)zi->ci.stream.next_in)+i); { zi->ci.stream.avail_in -= copy_this; zi->ci.stream.avail_out-= copy_this; zi->ci.stream.next_in+= copy_this; zi->ci.stream.next_out+= copy_this; zi->ci.stream.total_in+= copy_this; zi->ci.stream.total_out+= copy_this; zi->ci.pos_in_buffered_data += copy_this; } } }// while(...) } return err; } extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) { return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); } extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) { zip64_internal* zi; ZPOS64_T compressed_size; uLong invalidValue = 0xffffffff; short datasize = 0; int err=ZIP_OK; if (file == NULL) return ZIP_PARAMERROR; zi = (zip64_internal*)file; if (zi->in_opened_file_inzip == 0) return ZIP_PARAMERROR; zi->ci.stream.avail_in = 0; if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) { while (err==ZIP_OK) { uLong uTotalOutBefore; if (zi->ci.stream.avail_out == 0) { if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) err = ZIP_ERRNO; zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; zi->ci.stream.next_out = zi->ci.buffered_data; } uTotalOutBefore = zi->ci.stream.total_out; err=deflate(&zi->ci.stream, Z_FINISH); zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; } } else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) { #ifdef HAVE_BZIP2 err = BZ_FINISH_OK; while (err==BZ_FINISH_OK) { uLong uTotalOutBefore; if (zi->ci.bstream.avail_out == 0) { if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) err = ZIP_ERRNO; zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; } uTotalOutBefore = zi->ci.bstream.total_out_lo32; err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH); if(err == BZ_STREAM_END) err = Z_STREAM_END; zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore); } if(err == BZ_FINISH_OK) err = ZIP_OK; #endif } if (err==Z_STREAM_END) err=ZIP_OK; /* this is normal */ if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) { if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO) err = ZIP_ERRNO; } if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) { int tmp_err = deflateEnd(&zi->ci.stream); if (err == ZIP_OK) err = tmp_err; zi->ci.stream_initialised = 0; } #ifdef HAVE_BZIP2 else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) { int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream); if (err==ZIP_OK) err = tmperr; zi->ci.stream_initialised = 0; } #endif if (!zi->ci.raw) { crc32 = (uLong)zi->ci.crc32; uncompressed_size = zi->ci.totalUncompressedData; } compressed_size = zi->ci.totalCompressedData; # ifndef NOCRYPT compressed_size += zi->ci.crypt_header_size; # endif // update Current Item crc and sizes, if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) { /*version Made by*/ zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2); /*version needed*/ zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2); } zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ if(compressed_size >= 0xffffffff) zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/ else zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ /// set internal file attributes field if (zi->ci.stream.data_type == Z_ASCII) zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); if(uncompressed_size >= 0xffffffff) zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/ else zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ // Add ZIP64 extra info field for uncompressed size if(uncompressed_size >= 0xffffffff) datasize += 8; // Add ZIP64 extra info field for compressed size if(compressed_size >= 0xffffffff) datasize += 8; // Add ZIP64 extra info field for relative offset to local file header of current file if(zi->ci.pos_local_header >= 0xffffffff) datasize += 8; if(datasize > 0) { char* p = NULL; if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) { // we can not write more data to the buffer that we have room for. return ZIP_BADZIPFILE; } p = zi->ci.central_header + zi->ci.size_centralheader; // Add Extra Information Header for 'ZIP64 information' zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID p += 2; zip64local_putValue_inmemory(p, datasize, 2); // DataSize p += 2; if(uncompressed_size >= 0xffffffff) { zip64local_putValue_inmemory(p, uncompressed_size, 8); p += 8; } if(compressed_size >= 0xffffffff) { zip64local_putValue_inmemory(p, compressed_size, 8); p += 8; } if(zi->ci.pos_local_header >= 0xffffffff) { zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8); p += 8; } // Update how much extra free space we got in the memory buffer // and increase the centralheader size so the new ZIP64 fields are included // ( 4 below is the size of HeaderID and DataSize field ) zi->ci.size_centralExtraFree -= datasize + 4; zi->ci.size_centralheader += datasize + 4; // Update the extra info size field zi->ci.size_centralExtra += datasize + 4; zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2); } if (err==ZIP_OK) err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader); free(zi->ci.central_header); if (err==ZIP_OK) { // Update the LocalFileHeader with the new values. ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) err = ZIP_ERRNO; if (err==ZIP_OK) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff ) { if(zi->ci.pos_zip64extrainfo > 0) { // Update the size in the ZIP64 extended field. if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0) err = ZIP_ERRNO; if (err==ZIP_OK) /* compressed size, unknown */ err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8); if (err==ZIP_OK) /* uncompressed size, unknown */ err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); } else err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal } else { if (err==ZIP_OK) /* compressed size, unknown */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); if (err==ZIP_OK) /* uncompressed size, unknown */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); } if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) err = ZIP_ERRNO; } zi->number_entry ++; zi->in_opened_file_inzip = 0; return err; } extern int ZEXPORT zipCloseFileInZip (zipFile file) { return zipCloseFileInZipRaw (file,0,0); } int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) { int err = ZIP_OK; ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset; err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); /*num disks*/ if (err==ZIP_OK) /* number of the disk with the start of the central directory */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /*relative offset*/ if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8); /*total disks*/ /* Do not support spawning of disk so always say 1 here*/ if (err==ZIP_OK) /* number of the disk with the start of the central directory */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4); return err; } int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; uLong Zip64DataSize = 44; err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ? if (err==ZIP_OK) /* version made by */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); if (err==ZIP_OK) /* version needed */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); if (err==ZIP_OK) /* number of this disk */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); if (err==ZIP_OK) /* number of the disk with the start of the central directory */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); if (err==ZIP_OK) /* total number of entries in the central dir */ err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); if (err==ZIP_OK) /* size of the central directory */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8); if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ { ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); } return err; } int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) { int err = ZIP_OK; /*signature*/ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); if (err==ZIP_OK) /* number of this disk */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); if (err==ZIP_OK) /* number of the disk with the start of the central directory */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ { { if(zi->number_entry >= 0xFFFF) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record else err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); } } if (err==ZIP_OK) /* total number of entries in the central dir */ { if(zi->number_entry >= 0xFFFF) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record else err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); } if (err==ZIP_OK) /* size of the central directory */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ { ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; if(pos >= 0xffffffff) { err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); } else err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); } return err; } int Write_GlobalComment(zip64_internal* zi, const char* global_comment) { int err = ZIP_OK; uInt size_global_comment = 0; if(global_comment != NULL) size_global_comment = (uInt)strlen(global_comment); err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); if (err == ZIP_OK && size_global_comment > 0) { if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment) err = ZIP_ERRNO; } return err; } extern int ZEXPORT zipClose (zipFile file, const char* global_comment) { zip64_internal* zi; int err = 0; uLong size_centraldir = 0; ZPOS64_T centraldir_pos_inzip; ZPOS64_T pos; if (file == NULL) return ZIP_PARAMERROR; zi = (zip64_internal*)file; if (zi->in_opened_file_inzip == 1) { err = zipCloseFileInZip (file); } #ifndef NO_ADDFILEINEXISTINGZIP if (global_comment==NULL) global_comment = zi->globalcomment; #endif centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); if (err==ZIP_OK) { linkedlist_datablock_internal* ldi = zi->central_dir.first_block; while (ldi!=NULL) { if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) { if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block) err = ZIP_ERRNO; } size_centraldir += ldi->filled_in_this_block; ldi = ldi->next_datablock; } } free_linkedlist(&(zi->central_dir)); pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; if(pos >= 0xffffffff || zi->number_entry > 0xFFFF) { ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos); } if (err==ZIP_OK) err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); if(err == ZIP_OK) err = Write_GlobalComment(zi, global_comment); if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0) if (err == ZIP_OK) err = ZIP_ERRNO; #ifndef NO_ADDFILEINEXISTINGZIP TRYFREE(zi->globalcomment); #endif TRYFREE(zi); return err; } extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) { char* p = pData; int size = 0; char* pNewHeader; char* pTmp; short header; short dataSize; int retVal = ZIP_OK; if(pData == NULL || *dataLen < 4) return ZIP_PARAMERROR; pNewHeader = (char*)ALLOC(*dataLen); pTmp = pNewHeader; while(p < (pData + *dataLen)) { header = *(short*)p; dataSize = *(((short*)p)+1); if( header == sHeader ) // Header found. { p += dataSize + 4; // skip it. do not copy to temp buffer } else { // Extra Info block should not be removed, So copy it to the temp buffer. memcpy(pTmp, p, dataSize + 4); p += dataSize + 4; size += dataSize + 4; } } if(size < *dataLen) { // clean old extra info block. memset(pData,0, *dataLen); // copy the new extra info block over the old if(size > 0) memcpy(pData, pNewHeader, size); // set the new extra info size *dataLen = size; retVal = ZIP_OK; } else retVal = ZIP_ERRNO; TRYFREE(pNewHeader); return retVal; } tcl8.6.5/compat/zlib/contrib/minizip/minizip.pc.in0000644000175000017500000000040712663660064021541 0ustar sergeisergeiprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@/minizip Name: minizip Description: Minizip zip file manipulation library Requires: Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lminizip Libs.private: -lz Cflags: -I${includedir} tcl8.6.5/compat/zlib/contrib/minizip/ioapi.c0000644000175000017500000002004112663660064020372 0ustar sergeisergei/* ioapi.h -- IO base function header for compress/uncompress .zip part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt */ #if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS))) #define _CRT_SECURE_NO_WARNINGS #endif #if defined(__APPLE__) || defined(IOAPI_NO_64) // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) ftello(stream) #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) #else #define FOPEN_FUNC(filename, mode) fopen64(filename, mode) #define FTELLO_FUNC(stream) ftello64(stream) #define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) #endif #include "ioapi.h" voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) { if (pfilefunc->zfile_func64.zopen64_file != NULL) return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); else { return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); } } long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) { if (pfilefunc->zfile_func64.zseek64_file != NULL) return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); else { uLong offsetTruncated = (uLong)offset; if (offsetTruncated != offset) return -1; else return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); } } ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) { if (pfilefunc->zfile_func64.zseek64_file != NULL) return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); else { uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); if ((tell_uLong) == MAXU32) return (ZPOS64_T)-1; else return tell_uLong; } } void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) { p_filefunc64_32->zfile_func64.zopen64_file = NULL; p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; p_filefunc64_32->zfile_func64.ztell64_file = NULL; p_filefunc64_32->zfile_func64.zseek64_file = NULL; p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; } static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) mode_fopen = "rb"; else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) mode_fopen = "r+b"; else if (mode & ZLIB_FILEFUNC_MODE_CREATE) mode_fopen = "wb"; if ((filename!=NULL) && (mode_fopen != NULL)) file = fopen(filename, mode_fopen); return file; } static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) mode_fopen = "rb"; else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) mode_fopen = "r+b"; else if (mode & ZLIB_FILEFUNC_MODE_CREATE) mode_fopen = "wb"; if ((filename!=NULL) && (mode_fopen != NULL)) file = FOPEN_FUNC((const char*)filename, mode_fopen); return file; } static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) { uLong ret; ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); return ret; } static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) { uLong ret; ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); return ret; } static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) { long ret; ret = ftell((FILE *)stream); return ret; } static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) { ZPOS64_T ret; ret = FTELLO_FUNC((FILE *)stream); return ret; } static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) { int fseek_origin=0; long ret; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR : fseek_origin = SEEK_CUR; break; case ZLIB_FILEFUNC_SEEK_END : fseek_origin = SEEK_END; break; case ZLIB_FILEFUNC_SEEK_SET : fseek_origin = SEEK_SET; break; default: return -1; } ret = 0; if (fseek((FILE *)stream, offset, fseek_origin) != 0) ret = -1; return ret; } static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) { int fseek_origin=0; long ret; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR : fseek_origin = SEEK_CUR; break; case ZLIB_FILEFUNC_SEEK_END : fseek_origin = SEEK_END; break; case ZLIB_FILEFUNC_SEEK_SET : fseek_origin = SEEK_SET; break; default: return -1; } ret = 0; if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0) ret = -1; return ret; } static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) { int ret; ret = fclose((FILE *)stream); return ret; } static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) { int ret; ret = ferror((FILE *)stream); return ret; } void fill_fopen_filefunc (pzlib_filefunc_def) zlib_filefunc_def* pzlib_filefunc_def; { pzlib_filefunc_def->zopen_file = fopen_file_func; pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func; pzlib_filefunc_def->ztell_file = ftell_file_func; pzlib_filefunc_def->zseek_file = fseek_file_func; pzlib_filefunc_def->zclose_file = fclose_file_func; pzlib_filefunc_def->zerror_file = ferror_file_func; pzlib_filefunc_def->opaque = NULL; } void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = fopen64_file_func; pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func; pzlib_filefunc_def->ztell64_file = ftell64_file_func; pzlib_filefunc_def->zseek64_file = fseek64_file_func; pzlib_filefunc_def->zclose_file = fclose_file_func; pzlib_filefunc_def->zerror_file = ferror_file_func; pzlib_filefunc_def->opaque = NULL; } tcl8.6.5/compat/zlib/contrib/vstudio/0000755000175000017500000000000012665173607017152 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/vstudio/vc10/0000755000175000017500000000000012665173607017723 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/vstudio/vc10/zlibvc.sln0000644000175000017500000002365112663653206021735 0ustar sergeisergei Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Itanium = Debug|Itanium Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Itanium = Release|Itanium Release|Win32 = Release|Win32 Release|x64 = Release|x64 ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.Build.0 = Debug|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.Build.0 = Release|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.Build.0 = Debug|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.Build.0 = Release|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.Build.0 = Debug|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.Build.0 = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.Build.0 = Debug|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.Build.0 = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal tcl8.6.5/compat/zlib/contrib/vstudio/vc10/zlib.rc0000644000175000017500000000166412663660064021214 0ustar sergeisergei#include #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE FILEVERSION 1,2,8,0 PRODUCTVERSION 1,2,8,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0 // not used BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" //language ID = U.S. English, char set = Windows, Multilingual BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" VALUE "FileVersion", "1.2.8\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1252 END END tcl8.6.5/compat/zlib/contrib/vstudio/vc10/testzlib.vcxproj0000644000175000017500000006526012663653206023205 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 ReleaseWithoutAsm Itanium ReleaseWithoutAsm Win32 ReleaseWithoutAsm x64 Release Itanium Release Win32 Release x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} testzlib Win32Proj Application MultiByte true Application MultiByte true Application MultiByte Application MultiByte true Application MultiByte true Application MultiByte Application true Application true Application <_ProjectFileVersion>10.0.30128.1 x86\TestZlib$(Configuration)\ x86\TestZlib$(Configuration)\Tmp\ true false x86\TestZlib$(Configuration)\ x86\TestZlib$(Configuration)\Tmp\ false false x86\TestZlib$(Configuration)\ x86\TestZlib$(Configuration)\Tmp\ false false x64\TestZlib$(Configuration)\ x64\TestZlib$(Configuration)\Tmp\ false ia64\TestZlib$(Configuration)\ ia64\TestZlib$(Configuration)\Tmp\ true false x64\TestZlib$(Configuration)\ x64\TestZlib$(Configuration)\Tmp\ false ia64\TestZlib$(Configuration)\ ia64\TestZlib$(Configuration)\Tmp\ false false x64\TestZlib$(Configuration)\ x64\TestZlib$(Configuration)\Tmp\ false ia64\TestZlib$(Configuration)\ ia64\TestZlib$(Configuration)\Tmp\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..;%(AdditionalIncludeDirectories) ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreadedDebug false AssemblyAndSourceCode $(IntDir) Level3 EditAndContinue ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) $(OutDir)testzlib.exe true $(OutDir)testzlib.pdb Console false MachineX86 MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreaded false true $(IntDir) Level3 ProgramDatabase $(OutDir)testzlib.exe true Console true true false MachineX86 MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreaded false true $(IntDir) Level3 ProgramDatabase ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) $(OutDir)testzlib.exe true Console true true false MachineX86 ..\..\..;%(AdditionalIncludeDirectories) ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDebugDLL false $(IntDir) ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) Itanium Disabled ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false AssemblyAndSourceCode $(IntDir) Level3 ProgramDatabase $(OutDir)testzlib.exe true $(OutDir)testzlib.pdb Console MachineIA64 ..\..\..;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDLL false $(IntDir) %(AdditionalDependencies) Itanium MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase $(OutDir)testzlib.exe true Console true true MachineIA64 ..\..\..;%(AdditionalIncludeDirectories) ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDLL false $(IntDir) ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) Itanium MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase $(OutDir)testzlib.exe true Console true true MachineIA64 true true true true true true tcl8.6.5/compat/zlib/contrib/vstudio/vc10/minizip.vcxproj0000644000175000017500000004416512663653206023025 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 Release Itanium Release Win32 Release x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} Win32Proj Application MultiByte Application MultiByte Application MultiByte Application MultiByte Application MultiByte Application MultiByte <_ProjectFileVersion>10.0.30128.1 x86\MiniZip$(Configuration)\ x86\MiniZip$(Configuration)\Tmp\ true false x86\MiniZip$(Configuration)\ x86\MiniZip$(Configuration)\Tmp\ false x64\$(Configuration)\ x64\$(Configuration)\ true false ia64\$(Configuration)\ ia64\$(Configuration)\ true false x64\$(Configuration)\ x64\$(Configuration)\ false ia64\$(Configuration)\ ia64\$(Configuration)\ false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreadedDebug false $(IntDir) Level3 EditAndContinue x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true $(OutDir)minizip.pdb Console false MachineX86 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreaded false true $(IntDir) Level3 ProgramDatabase x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true Console true true false MachineX86 X64 Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true $(OutDir)minizip.pdb Console MachineX64 Itanium Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true $(OutDir)minizip.pdb Console MachineIA64 X64 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true Console true true MachineX64 Itanium MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true Console true true MachineIA64 {8fd826f8-3739-44e6-8cc8-997122e53b8d} tcl8.6.5/compat/zlib/contrib/vstudio/vc10/miniunz.vcxproj0000644000175000017500000004503112663653206023030 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 Release Itanium Release Win32 Release x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A} Win32Proj Application MultiByte Application MultiByte Application MultiByte Application MultiByte Application MultiByte Application MultiByte <_ProjectFileVersion>10.0.30128.1 x86\MiniUnzip$(Configuration)\ x86\MiniUnzip$(Configuration)\Tmp\ true false x86\MiniUnzip$(Configuration)\ x86\MiniUnzip$(Configuration)\Tmp\ false false x64\MiniUnzip$(Configuration)\ x64\MiniUnzip$(Configuration)\Tmp\ true false ia64\MiniUnzip$(Configuration)\ ia64\MiniUnzip$(Configuration)\Tmp\ true false x64\MiniUnzip$(Configuration)\ x64\MiniUnzip$(Configuration)\Tmp\ false false ia64\MiniUnzip$(Configuration)\ ia64\MiniUnzip$(Configuration)\Tmp\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreadedDebug false $(IntDir) Level3 EditAndContinue x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true $(OutDir)miniunz.pdb Console false MachineX86 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreaded false true $(IntDir) Level3 ProgramDatabase x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true Console true true false MachineX86 X64 Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true $(OutDir)miniunz.pdb Console MachineX64 Itanium Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true $(OutDir)miniunz.pdb Console MachineIA64 X64 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true Console true true MachineX64 Itanium MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true Console true true MachineIA64 {8fd826f8-3739-44e6-8cc8-997122e53b8d} tcl8.6.5/compat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters0000644000175000017500000000472212663653206024644 0ustar sergeisergei {174213f6-7f66-4ae8-a3a8-a1e0a1e6ffdd} Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files tcl8.6.5/compat/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters0000644000175000017500000000163112663653206024475 0ustar sergeisergei {048af943-022b-4db6-beeb-a54c34774ee2} cpp;c;cxx;def;odl;idl;hpj;bat;asm {c1d600d2-888f-4aea-b73e-8b0dd9befa0c} h;hpp;hxx;hm;inl;inc {0844199a-966b-4f19-81db-1e0125e141b9} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe Source Files tcl8.6.5/compat/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters0000644000175000017500000000163112663653206024463 0ustar sergeisergei {c0419b40-bf50-40da-b153-ff74215b79de} cpp;c;cxx;def;odl;idl;hpj;bat;asm {bb87b070-735b-478e-92ce-7383abb2f36c} h;hpp;hxx;hm;inl;inc {f46ab6a6-548f-43cb-ae96-681abb5bd5db} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe Source Files tcl8.6.5/compat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj0000644000175000017500000011646312663660065022641 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 ReleaseWithoutAsm Itanium ReleaseWithoutAsm Win32 ReleaseWithoutAsm x64 Release Itanium Release Win32 Release x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D} DynamicLibrary false true DynamicLibrary false true DynamicLibrary false DynamicLibrary false true DynamicLibrary false true DynamicLibrary false DynamicLibrary false true DynamicLibrary false true DynamicLibrary false <_ProjectFileVersion>10.0.30128.1 x86\ZlibDll$(Configuration)\ x86\ZlibDll$(Configuration)\Tmp\ true false x86\ZlibDll$(Configuration)\ x86\ZlibDll$(Configuration)\Tmp\ false false x86\ZlibDll$(Configuration)\ x86\ZlibDll$(Configuration)\Tmp\ false false x64\ZlibDll$(Configuration)\ x64\ZlibDll$(Configuration)\Tmp\ true false ia64\ZlibDll$(Configuration)\ ia64\ZlibDll$(Configuration)\Tmp\ true false x64\ZlibDll$(Configuration)\ x64\ZlibDll$(Configuration)\Tmp\ false false ia64\ZlibDll$(Configuration)\ ia64\ZlibDll$(Configuration)\Tmp\ false false x64\ZlibDll$(Configuration)\ x64\ZlibDll$(Configuration)\Tmp\ false false ia64\ZlibDll$(Configuration)\ ia64\ZlibDll$(Configuration)\Tmp\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset zlibwapid zlibwapi zlibwapi zlibwapid zlibwapi zlibwapi _DEBUG;%(PreprocessorDefinitions) true true Win32 $(OutDir)zlibvc.tlb Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) MultiThreadedDebug false $(IntDir)zlibvc.pch $(IntDir) $(IntDir) $(OutDir) Level3 true EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) true .\zlibvc.def true true Windows false cd ..\..\masmx86 bld_ml32.bat NDEBUG;%(PreprocessorDefinitions) true true Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) true false .\zlibvc.def true Windows false NDEBUG;%(PreprocessorDefinitions) true true Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) true MultiThreaded false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) true false .\zlibvc.def true Windows false cd ..\..\masmx86 bld_ml32.bat _DEBUG;%(PreprocessorDefinitions) true true X64 $(OutDir)zlibvc.tlb Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch $(IntDir) $(IntDir) $(OutDir) Level3 true ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x040c ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) true .\zlibvc.def true true Windows MachineX64 cd ..\..\masmx64 bld_ml64.bat _DEBUG;%(PreprocessorDefinitions) true true Itanium $(OutDir)zlibvc.tlb Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch $(IntDir) $(IntDir) $(OutDir) Level3 true ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x040c $(OutDir)zlibwapi.dll true .\zlibvc.def true $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineIA64 NDEBUG;%(PreprocessorDefinitions) true true X64 $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c true false .\zlibvc.def true Windows MachineX64 NDEBUG;%(PreprocessorDefinitions) true true Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineIA64 NDEBUG;%(PreprocessorDefinitions) true true X64 $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) true false .\zlibvc.def true Windows MachineX64 cd ..\..\masmx64 bld_ml64.bat NDEBUG;%(PreprocessorDefinitions) true true Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineIA64 true true true true true true %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) tcl8.6.5/compat/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj0000644000175000017500000004511612663660064023677 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 Release Itanium Release Win32 Release x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A} Win32Proj Application MultiByte Application MultiByte Application MultiByte Application MultiByte Application MultiByte Application MultiByte <_ProjectFileVersion>10.0.30128.1 x86\TestZlibDll$(Configuration)\ x86\TestZlibDll$(Configuration)\Tmp\ true false x86\TestZlibDll$(Configuration)\ x86\TestZlibDll$(Configuration)\Tmp\ false false x64\TestZlibDll$(Configuration)\ x64\TestZlibDll$(Configuration)\Tmp\ true false ia64\TestZlibDll$(Configuration)\ ia64\TestZlibDll$(Configuration)\Tmp\ true false x64\TestZlibDll$(Configuration)\ x64\TestZlibDll$(Configuration)\Tmp\ false false ia64\TestZlibDll$(Configuration)\ ia64\TestZlibDll$(Configuration)\Tmp\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreadedDebug false $(IntDir) Level3 EditAndContinue x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true $(OutDir)testzlib.pdb Console false MachineX86 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreaded false true $(IntDir) Level3 ProgramDatabase x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true Console true true false MachineX86 X64 Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true $(OutDir)testzlib.pdb Console MachineX64 Itanium Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true $(OutDir)testzlib.pdb Console MachineIA64 X64 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true Console true true MachineX64 Itanium MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true Console true true MachineIA64 {8fd826f8-3739-44e6-8cc8-997122e53b8d} tcl8.6.5/compat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters0000644000175000017500000000770712663653206024307 0ustar sergeisergei {07934a85-8b61-443d-a0ee-b2eedb74f3cd} cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90 {1d99675b-433d-4a21-9e50-ed4ab8b19762} h;hpp;hxx;hm;inl;fi;fd {431c0958-fa71-44d0-9084-2d19d100c0cc} ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files Header Files tcl8.6.5/compat/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters0000644000175000017500000000413312663653206024644 0ustar sergeisergei {c1f6a2e3-5da5-4955-8653-310d3efe05a9} cpp;c;cxx;def;odl;idl;hpj;bat;asm {c2aaffdc-2c95-4d6f-8466-4bec5890af2c} h;hpp;hxx;hm;inl;inc {c274fe07-05f2-461c-964b-f6341e4e7eb5} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files tcl8.6.5/compat/zlib/contrib/vstudio/vc10/zlibvc.def0000644000175000017500000001514412663660064021675 0ustar sergeisergeiLIBRARY ; zlib data compression and ZIP file I/O library VERSION 1.2.8 EXPORTS adler32 @1 compress @2 crc32 @3 deflate @4 deflateCopy @5 deflateEnd @6 deflateInit2_ @7 deflateInit_ @8 deflateParams @9 deflateReset @10 deflateSetDictionary @11 gzclose @12 gzdopen @13 gzerror @14 gzflush @15 gzopen @16 gzread @17 gzwrite @18 inflate @19 inflateEnd @20 inflateInit2_ @21 inflateInit_ @22 inflateReset @23 inflateSetDictionary @24 inflateSync @25 uncompress @26 zlibVersion @27 gzprintf @28 gzputc @29 gzgetc @30 gzseek @31 gzrewind @32 gztell @33 gzeof @34 gzsetparams @35 zError @36 inflateSyncPoint @37 get_crc_table @38 compress2 @39 gzputs @40 gzgets @41 inflateCopy @42 inflateBackInit_ @43 inflateBack @44 inflateBackEnd @45 compressBound @46 deflateBound @47 gzclearerr @48 gzungetc @49 zlibCompileFlags @50 deflatePrime @51 deflatePending @52 unzOpen @61 unzClose @62 unzGetGlobalInfo @63 unzGetCurrentFileInfo @64 unzGoToFirstFile @65 unzGoToNextFile @66 unzOpenCurrentFile @67 unzReadCurrentFile @68 unzOpenCurrentFile3 @69 unztell @70 unzeof @71 unzCloseCurrentFile @72 unzGetGlobalComment @73 unzStringFileNameCompare @74 unzLocateFile @75 unzGetLocalExtrafield @76 unzOpen2 @77 unzOpenCurrentFile2 @78 unzOpenCurrentFilePassword @79 zipOpen @80 zipOpenNewFileInZip @81 zipWriteInFileInZip @82 zipCloseFileInZip @83 zipClose @84 zipOpenNewFileInZip2 @86 zipCloseFileInZipRaw @87 zipOpen2 @88 zipOpenNewFileInZip3 @89 unzGetFilePos @100 unzGoToFilePos @101 fill_win32_filefunc @110 ; zlibwapi v1.2.4 added: fill_win32_filefunc64 @111 fill_win32_filefunc64A @112 fill_win32_filefunc64W @113 unzOpen64 @120 unzOpen2_64 @121 unzGetGlobalInfo64 @122 unzGetCurrentFileInfo64 @124 unzGetCurrentFileZStreamPos64 @125 unztell64 @126 unzGetFilePos64 @127 unzGoToFilePos64 @128 zipOpen64 @130 zipOpen2_64 @131 zipOpenNewFileInZip64 @132 zipOpenNewFileInZip2_64 @133 zipOpenNewFileInZip3_64 @134 zipOpenNewFileInZip4_64 @135 zipCloseFileInZipRaw64 @136 ; zlib1 v1.2.4 added: adler32_combine @140 crc32_combine @142 deflateSetHeader @144 deflateTune @145 gzbuffer @146 gzclose_r @147 gzclose_w @148 gzdirect @149 gzoffset @150 inflateGetHeader @156 inflateMark @157 inflatePrime @158 inflateReset2 @159 inflateUndermine @160 ; zlib1 v1.2.6 added: gzgetc_ @161 inflateResetKeep @163 deflateResetKeep @164 ; zlib1 v1.2.7 added: gzopen_w @165 ; zlib1 v1.2.8 added: inflateGetDictionary @166 gzvprintf @167 tcl8.6.5/compat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj0000644000175000017500000006655412663660064023210 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 ReleaseWithoutAsm Itanium ReleaseWithoutAsm Win32 ReleaseWithoutAsm x64 Release Itanium Release Win32 Release x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} StaticLibrary false StaticLibrary false StaticLibrary false StaticLibrary false StaticLibrary false StaticLibrary false StaticLibrary false StaticLibrary false StaticLibrary false <_ProjectFileVersion>10.0.30128.1 x86\ZlibStat$(Configuration)\ x86\ZlibStat$(Configuration)\Tmp\ x86\ZlibStat$(Configuration)\ x86\ZlibStat$(Configuration)\Tmp\ x86\ZlibStat$(Configuration)\ x86\ZlibStat$(Configuration)\Tmp\ x64\ZlibStat$(Configuration)\ x64\ZlibStat$(Configuration)\Tmp\ ia64\ZlibStat$(Configuration)\ ia64\ZlibStat$(Configuration)\Tmp\ x64\ZlibStat$(Configuration)\ x64\ZlibStat$(Configuration)\Tmp\ ia64\ZlibStat$(Configuration)\ ia64\ZlibStat$(Configuration)\Tmp\ x64\ZlibStat$(Configuration)\ x64\ZlibStat$(Configuration)\Tmp\ ia64\ZlibStat$(Configuration)\ ia64\ZlibStat$(Configuration)\Tmp\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreadedDebug false $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true OldStyle 0x040c /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true cd ..\..\masmx86 bld_ml32.bat OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) true MultiThreaded false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) $(OutDir)zlibstat.lib true cd ..\..\masmx86 bld_ml32.bat OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true X64 Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true OldStyle 0x040c /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true cd ..\..\masmx64 bld_ml64.bat Itanium Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true OldStyle 0x040c /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true X64 OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) $(OutDir)zlibstat.lib true cd ..\..\masmx64 bld_ml64.bat Itanium OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true X64 OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true Itanium OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true true true true true true true tcl8.6.5/compat/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters0000644000175000017500000000163312663653206025342 0ustar sergeisergei {fa61a89f-93fc-4c89-b29e-36224b7592f4} cpp;c;cxx;def;odl;idl;hpj;bat;asm {d4b85da0-2ba2-4934-b57f-e2584e3848ee} h;hpp;hxx;hm;inl;inc {e573e075-00bd-4a7d-bd67-a8cc9bfc5aca} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe Source Files tcl8.6.5/compat/zlib/contrib/vstudio/readme.txt0000644000175000017500000000472012663660064021147 0ustar sergeisergeiBuilding instructions for the DLL versions of Zlib 1.2.8 ======================================================== This directory contains projects that build zlib and minizip using Microsoft Visual C++ 9.0/10.0. You don't need to build these projects yourself. You can download the binaries from: http://www.winimage.com/zLibDll More information can be found at this site. Build instructions for Visual Studio 2008 (32 bits or 64 bits) -------------------------------------------------------------- - Uncompress current zlib, including all contrib/* files - Compile assembly code (with Visual Studio Command Prompt) by running: bld_ml64.bat (in contrib\masmx64) bld_ml32.bat (in contrib\masmx86) - Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008 - Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32" Build instructions for Visual Studio 2010 (32 bits or 64 bits) -------------------------------------------------------------- - Uncompress current zlib, including all contrib/* files - Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010 Build instructions for Visual Studio 2012 (32 bits or 64 bits) -------------------------------------------------------------- - Uncompress current zlib, including all contrib/* files - Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012 Important --------- - To use zlibwapi.dll in your application, you must define the macro ZLIB_WINAPI when compiling your application's source files. Additional notes ---------------- - This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built by Gilles Vollant from the zlib 1.1.x sources, and distributed at http://www.winimage.com/zLibDll It uses the WINAPI calling convention for the exported functions, and includes the minizip functionality. If your application needs that particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll. - The new DLL was renamed because there exist several incompatible versions of zlib.dll on the Internet. - There is also an official DLL build of zlib, named zlib1.dll. This one is exporting the functions using the CDECL convention. See the file win32\DLL_FAQ.txt found in this zlib distribution. - There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol has a slightly different effect. To avoid compatibility problems, do not define it here. Gilles Vollant info@winimage.com tcl8.6.5/compat/zlib/contrib/vstudio/vc11/0000755000175000017500000000000012665173607017724 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/vstudio/vc11/zlibvc.sln0000644000175000017500000002053312663660065021733 0ustar sergeisergei Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Itanium = Debug|Itanium Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Itanium = Release|Itanium Release|Win32 = Release|Win32 Release|x64 = Release|x64 ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal tcl8.6.5/compat/zlib/contrib/vstudio/vc11/zlib.rc0000644000175000017500000000166412663660065021216 0ustar sergeisergei#include #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE FILEVERSION 1,2,8,0 PRODUCTVERSION 1,2,8,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0 // not used BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" //language ID = U.S. English, char set = Windows, Multilingual BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" VALUE "FileVersion", "1.2.8\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1252 END END tcl8.6.5/compat/zlib/contrib/vstudio/vc11/testzlib.vcxproj0000644000175000017500000006567712663660065023223 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 ReleaseWithoutAsm Itanium ReleaseWithoutAsm Win32 ReleaseWithoutAsm x64 Release Itanium Release Win32 Release x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} testzlib Win32Proj Application MultiByte true v110 Application MultiByte true v110 Application Unicode v110 Application MultiByte true Application MultiByte true Application MultiByte Application true v110 Application true v110 Application v110 <_ProjectFileVersion>10.0.30128.1 x86\TestZlib$(Configuration)\ x86\TestZlib$(Configuration)\Tmp\ true false x86\TestZlib$(Configuration)\ x86\TestZlib$(Configuration)\Tmp\ false false x86\TestZlib$(Configuration)\ x86\TestZlib$(Configuration)\Tmp\ false false x64\TestZlib$(Configuration)\ x64\TestZlib$(Configuration)\Tmp\ false ia64\TestZlib$(Configuration)\ ia64\TestZlib$(Configuration)\Tmp\ true false x64\TestZlib$(Configuration)\ x64\TestZlib$(Configuration)\Tmp\ false ia64\TestZlib$(Configuration)\ ia64\TestZlib$(Configuration)\Tmp\ false false x64\TestZlib$(Configuration)\ x64\TestZlib$(Configuration)\Tmp\ false ia64\TestZlib$(Configuration)\ ia64\TestZlib$(Configuration)\Tmp\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..;%(AdditionalIncludeDirectories) ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false AssemblyAndSourceCode $(IntDir) Level3 ProgramDatabase ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) $(OutDir)testzlib.exe true $(OutDir)testzlib.pdb Console false MachineX86 MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreaded false true $(IntDir) Level3 ProgramDatabase $(OutDir)testzlib.exe true Console true true false MachineX86 MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreaded false true $(IntDir) Level3 ProgramDatabase ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) $(OutDir)testzlib.exe true Console true true false MachineX86 ..\..\..;%(AdditionalIncludeDirectories) ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDebugDLL false $(IntDir) ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) Itanium Disabled ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false AssemblyAndSourceCode $(IntDir) Level3 ProgramDatabase $(OutDir)testzlib.exe true $(OutDir)testzlib.pdb Console MachineIA64 ..\..\..;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDLL false $(IntDir) %(AdditionalDependencies) Itanium MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase $(OutDir)testzlib.exe true Console true true MachineIA64 ..\..\..;%(AdditionalIncludeDirectories) ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) Default MultiThreadedDLL false $(IntDir) ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) Itanium MaxSpeed OnlyExplicitInline true ..\..\..;%(AdditionalIncludeDirectories) ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase $(OutDir)testzlib.exe true Console true true MachineIA64 true true true true true true tcl8.6.5/compat/zlib/contrib/vstudio/vc11/minizip.vcxproj0000644000175000017500000004445212663660065023026 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 Release Itanium Release Win32 Release x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} Win32Proj Application MultiByte v110 Application Unicode v110 Application MultiByte Application MultiByte Application MultiByte v110 Application MultiByte v110 <_ProjectFileVersion>10.0.30128.1 x86\MiniZip$(Configuration)\ x86\MiniZip$(Configuration)\Tmp\ true false x86\MiniZip$(Configuration)\ x86\MiniZip$(Configuration)\Tmp\ false x64\$(Configuration)\ x64\$(Configuration)\ true false ia64\$(Configuration)\ ia64\$(Configuration)\ true false x64\$(Configuration)\ x64\$(Configuration)\ false ia64\$(Configuration)\ ia64\$(Configuration)\ false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true $(OutDir)minizip.pdb Console false MachineX86 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreaded false true $(IntDir) Level3 ProgramDatabase x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true Console true true false MachineX86 X64 Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true $(OutDir)minizip.pdb Console MachineX64 Itanium Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true $(OutDir)minizip.pdb Console MachineIA64 X64 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true Console true true MachineX64 Itanium MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)minizip.exe true Console true true MachineIA64 {8fd826f8-3739-44e6-8cc8-997122e53b8d} tcl8.6.5/compat/zlib/contrib/vstudio/vc11/miniunz.vcxproj0000644000175000017500000004531612663660065023040 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 Release Itanium Release Win32 Release x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A} Win32Proj Application MultiByte v110 Application Unicode v110 Application MultiByte Application MultiByte Application MultiByte v110 Application MultiByte v110 <_ProjectFileVersion>10.0.30128.1 x86\MiniUnzip$(Configuration)\ x86\MiniUnzip$(Configuration)\Tmp\ true false x86\MiniUnzip$(Configuration)\ x86\MiniUnzip$(Configuration)\Tmp\ false false x64\MiniUnzip$(Configuration)\ x64\MiniUnzip$(Configuration)\Tmp\ true false ia64\MiniUnzip$(Configuration)\ ia64\MiniUnzip$(Configuration)\Tmp\ true false x64\MiniUnzip$(Configuration)\ x64\MiniUnzip$(Configuration)\Tmp\ false false ia64\MiniUnzip$(Configuration)\ ia64\MiniUnzip$(Configuration)\Tmp\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true $(OutDir)miniunz.pdb Console false MachineX86 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreaded false true $(IntDir) Level3 ProgramDatabase x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true Console true true false MachineX86 X64 Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true $(OutDir)miniunz.pdb Console MachineX64 Itanium Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true $(OutDir)miniunz.pdb Console MachineIA64 X64 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true Console true true MachineX64 Itanium MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)miniunz.exe true Console true true MachineIA64 {8fd826f8-3739-44e6-8cc8-997122e53b8d} tcl8.6.5/compat/zlib/contrib/vstudio/vc11/zlibvc.vcxproj0000644000175000017500000012204012663660065022626 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 ReleaseWithoutAsm Itanium ReleaseWithoutAsm Win32 ReleaseWithoutAsm x64 Release Itanium Release Win32 Release x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D} DynamicLibrary false true v110 DynamicLibrary false true v110 DynamicLibrary false v110 Unicode DynamicLibrary false true DynamicLibrary false true DynamicLibrary false DynamicLibrary false true v110 DynamicLibrary false true v110 DynamicLibrary false v110 <_ProjectFileVersion>10.0.30128.1 x86\ZlibDll$(Configuration)\ x86\ZlibDll$(Configuration)\Tmp\ true false x86\ZlibDll$(Configuration)\ x86\ZlibDll$(Configuration)\Tmp\ false false x86\ZlibDll$(Configuration)\ x86\ZlibDll$(Configuration)\Tmp\ false false x64\ZlibDll$(Configuration)\ x64\ZlibDll$(Configuration)\Tmp\ true false ia64\ZlibDll$(Configuration)\ ia64\ZlibDll$(Configuration)\Tmp\ true false x64\ZlibDll$(Configuration)\ x64\ZlibDll$(Configuration)\Tmp\ false false ia64\ZlibDll$(Configuration)\ ia64\ZlibDll$(Configuration)\Tmp\ false false x64\ZlibDll$(Configuration)\ x64\ZlibDll$(Configuration)\Tmp\ false false ia64\ZlibDll$(Configuration)\ ia64\ZlibDll$(Configuration)\Tmp\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset zlibwapi zlibwapi zlibwapi zlibwapi zlibwapi zlibwapi _DEBUG;%(PreprocessorDefinitions) true true Win32 $(OutDir)zlibvc.tlb Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch $(IntDir) $(IntDir) $(OutDir) Level3 true ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) $(OutDir)zlibwapi.dll true .\zlibvc.def true $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows false $(OutDir)zlibwapi.lib cd ..\..\masmx86 bld_ml32.bat NDEBUG;%(PreprocessorDefinitions) true true Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows false $(OutDir)zlibwapi.lib NDEBUG;%(PreprocessorDefinitions) true true Win32 $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) true MultiThreaded false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c /MACHINE:I386 %(AdditionalOptions) ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows false $(OutDir)zlibwapi.lib cd ..\..\masmx86 bld_ml32.bat _DEBUG;%(PreprocessorDefinitions) true true X64 $(OutDir)zlibvc.tlb Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch $(IntDir) $(IntDir) $(OutDir) Level3 true ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x040c ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) $(OutDir)zlibwapi.dll true .\zlibvc.def true $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineX64 cd ..\..\contrib\masmx64 bld_ml64.bat _DEBUG;%(PreprocessorDefinitions) true true Itanium $(OutDir)zlibvc.tlb Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibvc.pch $(IntDir) $(IntDir) $(OutDir) Level3 true ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x040c $(OutDir)zlibwapi.dll true .\zlibvc.def true $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineIA64 NDEBUG;%(PreprocessorDefinitions) true true X64 $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineX64 NDEBUG;%(PreprocessorDefinitions) true true Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineIA64 NDEBUG;%(PreprocessorDefinitions) true true X64 $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineX64 cd ..\..\masmx64 bld_ml64.bat NDEBUG;%(PreprocessorDefinitions) true true Itanium $(OutDir)zlibvc.tlb OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibvc.pch All $(IntDir) $(IntDir) $(OutDir) Level3 true NDEBUG;%(PreprocessorDefinitions) 0x040c $(OutDir)zlibwapi.dll true false .\zlibvc.def $(OutDir)zlibwapi.pdb true $(OutDir)zlibwapi.map Windows $(OutDir)zlibwapi.lib MachineIA64 true true true true true true %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) %(AdditionalIncludeDirectories) ZLIB_INTERNAL;%(PreprocessorDefinitions) tcl8.6.5/compat/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj0000644000175000017500000004540312663660065023700 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 Release Itanium Release Win32 Release x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A} Win32Proj Application MultiByte v110 Application Unicode v110 Application MultiByte Application MultiByte Application MultiByte v110 Application MultiByte v110 <_ProjectFileVersion>10.0.30128.1 x86\TestZlibDll$(Configuration)\ x86\TestZlibDll$(Configuration)\Tmp\ true false x86\TestZlibDll$(Configuration)\ x86\TestZlibDll$(Configuration)\Tmp\ false false x64\TestZlibDll$(Configuration)\ x64\TestZlibDll$(Configuration)\Tmp\ true false ia64\TestZlibDll$(Configuration)\ ia64\TestZlibDll$(Configuration)\Tmp\ true false x64\TestZlibDll$(Configuration)\ x64\TestZlibDll$(Configuration)\Tmp\ false false ia64\TestZlibDll$(Configuration)\ ia64\TestZlibDll$(Configuration)\Tmp\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true $(OutDir)testzlib.pdb Console false MachineX86 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Default MultiThreaded false true $(IntDir) Level3 ProgramDatabase x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true Console true true false MachineX86 X64 Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true $(OutDir)testzlib.pdb Console MachineX64 Itanium Disabled ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL false $(IntDir) Level3 ProgramDatabase ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true $(OutDir)testzlib.pdb Console MachineIA64 X64 MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true Console true true MachineX64 Itanium MaxSpeed OnlyExplicitInline true ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) true Default MultiThreadedDLL false true $(IntDir) Level3 ProgramDatabase ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) $(OutDir)testzlibdll.exe true Console true true MachineIA64 {8fd826f8-3739-44e6-8cc8-997122e53b8d} tcl8.6.5/compat/zlib/contrib/vstudio/vc11/zlibvc.def0000644000175000017500000001514412663660065021677 0ustar sergeisergeiLIBRARY ; zlib data compression and ZIP file I/O library VERSION 1.2.8 EXPORTS adler32 @1 compress @2 crc32 @3 deflate @4 deflateCopy @5 deflateEnd @6 deflateInit2_ @7 deflateInit_ @8 deflateParams @9 deflateReset @10 deflateSetDictionary @11 gzclose @12 gzdopen @13 gzerror @14 gzflush @15 gzopen @16 gzread @17 gzwrite @18 inflate @19 inflateEnd @20 inflateInit2_ @21 inflateInit_ @22 inflateReset @23 inflateSetDictionary @24 inflateSync @25 uncompress @26 zlibVersion @27 gzprintf @28 gzputc @29 gzgetc @30 gzseek @31 gzrewind @32 gztell @33 gzeof @34 gzsetparams @35 zError @36 inflateSyncPoint @37 get_crc_table @38 compress2 @39 gzputs @40 gzgets @41 inflateCopy @42 inflateBackInit_ @43 inflateBack @44 inflateBackEnd @45 compressBound @46 deflateBound @47 gzclearerr @48 gzungetc @49 zlibCompileFlags @50 deflatePrime @51 deflatePending @52 unzOpen @61 unzClose @62 unzGetGlobalInfo @63 unzGetCurrentFileInfo @64 unzGoToFirstFile @65 unzGoToNextFile @66 unzOpenCurrentFile @67 unzReadCurrentFile @68 unzOpenCurrentFile3 @69 unztell @70 unzeof @71 unzCloseCurrentFile @72 unzGetGlobalComment @73 unzStringFileNameCompare @74 unzLocateFile @75 unzGetLocalExtrafield @76 unzOpen2 @77 unzOpenCurrentFile2 @78 unzOpenCurrentFilePassword @79 zipOpen @80 zipOpenNewFileInZip @81 zipWriteInFileInZip @82 zipCloseFileInZip @83 zipClose @84 zipOpenNewFileInZip2 @86 zipCloseFileInZipRaw @87 zipOpen2 @88 zipOpenNewFileInZip3 @89 unzGetFilePos @100 unzGoToFilePos @101 fill_win32_filefunc @110 ; zlibwapi v1.2.4 added: fill_win32_filefunc64 @111 fill_win32_filefunc64A @112 fill_win32_filefunc64W @113 unzOpen64 @120 unzOpen2_64 @121 unzGetGlobalInfo64 @122 unzGetCurrentFileInfo64 @124 unzGetCurrentFileZStreamPos64 @125 unztell64 @126 unzGetFilePos64 @127 unzGoToFilePos64 @128 zipOpen64 @130 zipOpen2_64 @131 zipOpenNewFileInZip64 @132 zipOpenNewFileInZip2_64 @133 zipOpenNewFileInZip3_64 @134 zipOpenNewFileInZip4_64 @135 zipCloseFileInZipRaw64 @136 ; zlib1 v1.2.4 added: adler32_combine @140 crc32_combine @142 deflateSetHeader @144 deflateTune @145 gzbuffer @146 gzclose_r @147 gzclose_w @148 gzdirect @149 gzoffset @150 inflateGetHeader @156 inflateMark @157 inflatePrime @158 inflateReset2 @159 inflateUndermine @160 ; zlib1 v1.2.6 added: gzgetc_ @161 inflateResetKeep @163 deflateResetKeep @164 ; zlib1 v1.2.7 added: gzopen_w @165 ; zlib1 v1.2.8 added: inflateGetDictionary @166 gzvprintf @167 tcl8.6.5/compat/zlib/contrib/vstudio/vc11/zlibstat.vcxproj0000644000175000017500000006642712663660065023211 0ustar sergeisergei Debug Itanium Debug Win32 Debug x64 ReleaseWithoutAsm Itanium ReleaseWithoutAsm Win32 ReleaseWithoutAsm x64 Release Itanium Release Win32 Release x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} StaticLibrary false v110 StaticLibrary false v110 StaticLibrary false v110 Unicode StaticLibrary false StaticLibrary false StaticLibrary false StaticLibrary false v110 StaticLibrary false v110 StaticLibrary false v110 <_ProjectFileVersion>10.0.30128.1 x86\ZlibStat$(Configuration)\ x86\ZlibStat$(Configuration)\Tmp\ x86\ZlibStat$(Configuration)\ x86\ZlibStat$(Configuration)\Tmp\ x86\ZlibStat$(Configuration)\ x86\ZlibStat$(Configuration)\Tmp\ x64\ZlibStat$(Configuration)\ x64\ZlibStat$(Configuration)\Tmp\ ia64\ZlibStat$(Configuration)\ ia64\ZlibStat$(Configuration)\Tmp\ x64\ZlibStat$(Configuration)\ x64\ZlibStat$(Configuration)\Tmp\ ia64\ZlibStat$(Configuration)\ ia64\ZlibStat$(Configuration)\Tmp\ x64\ZlibStat$(Configuration)\ x64\ZlibStat$(Configuration)\Tmp\ ia64\ZlibStat$(Configuration)\ ia64\ZlibStat$(Configuration)\Tmp\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true OldStyle 0x040c /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) true MultiThreaded false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) $(OutDir)zlibstat.lib true OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true X64 Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true OldStyle 0x040c /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true Itanium Disabled ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL false $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true OldStyle 0x040c /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true X64 OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) $(OutDir)zlibstat.lib true Itanium OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true X64 OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true Itanium OnlyExplicitInline ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) true MultiThreadedDLL false true $(IntDir)zlibstat.pch $(IntDir) $(IntDir) $(OutDir) Level3 true 0x040c /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) $(OutDir)zlibstat.lib true true true true true true true tcl8.6.5/compat/zlib/contrib/vstudio/vc9/0000755000175000017500000000000012665173607017653 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/vstudio/vc9/testzlib.vcproj0000644000175000017500000004500712663653206022742 0ustar sergeisergei tcl8.6.5/compat/zlib/contrib/vstudio/vc9/minizip.vcproj0000644000175000017500000003072112663653206022556 0ustar sergeisergei tcl8.6.5/compat/zlib/contrib/vstudio/vc9/zlibvc.sln0000644000175000017500000002456412663653206021671 0ustar sergeisergei Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestZlibDll", "testzlibdll.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" ProjectSection(ProjectDependencies) = postProject {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" ProjectSection(ProjectDependencies) = postProject {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" ProjectSection(ProjectDependencies) = postProject {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Itanium = Debug|Itanium Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Itanium = Release|Itanium Release|Win32 = Release|Win32 Release|x64 = Release|x64 ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.Build.0 = Debug|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.Build.0 = Release|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.Build.0 = Debug|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.Build.0 = Release|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.Build.0 = Debug|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.Build.0 = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.Build.0 = Debug|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.Build.0 = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal tcl8.6.5/compat/zlib/contrib/vstudio/vc9/zlib.rc0000644000175000017500000000166412663660065021145 0ustar sergeisergei#include #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE FILEVERSION 1,2,8,0 PRODUCTVERSION 1,2,8,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0 // not used BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" //language ID = U.S. English, char set = Windows, Multilingual BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" VALUE "FileVersion", "1.2.8\0" VALUE "InternalName", "zlib\0" VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1252 END END tcl8.6.5/compat/zlib/contrib/vstudio/vc9/testzlibdll.vcproj0000644000175000017500000003126212663653206023434 0ustar sergeisergei tcl8.6.5/compat/zlib/contrib/vstudio/vc9/zlibstat.vcproj0000644000175000017500000004611412663653206022736 0ustar sergeisergei tcl8.6.5/compat/zlib/contrib/vstudio/vc9/miniunz.vcproj0000644000175000017500000003121312663653206022565 0ustar sergeisergei tcl8.6.5/compat/zlib/contrib/vstudio/vc9/zlibvc.vcproj0000644000175000017500000006657412663653206022407 0ustar sergeisergei tcl8.6.5/compat/zlib/contrib/vstudio/vc9/zlibvc.def0000644000175000017500000001514412663660065021626 0ustar sergeisergeiLIBRARY ; zlib data compression and ZIP file I/O library VERSION 1.2.8 EXPORTS adler32 @1 compress @2 crc32 @3 deflate @4 deflateCopy @5 deflateEnd @6 deflateInit2_ @7 deflateInit_ @8 deflateParams @9 deflateReset @10 deflateSetDictionary @11 gzclose @12 gzdopen @13 gzerror @14 gzflush @15 gzopen @16 gzread @17 gzwrite @18 inflate @19 inflateEnd @20 inflateInit2_ @21 inflateInit_ @22 inflateReset @23 inflateSetDictionary @24 inflateSync @25 uncompress @26 zlibVersion @27 gzprintf @28 gzputc @29 gzgetc @30 gzseek @31 gzrewind @32 gztell @33 gzeof @34 gzsetparams @35 zError @36 inflateSyncPoint @37 get_crc_table @38 compress2 @39 gzputs @40 gzgets @41 inflateCopy @42 inflateBackInit_ @43 inflateBack @44 inflateBackEnd @45 compressBound @46 deflateBound @47 gzclearerr @48 gzungetc @49 zlibCompileFlags @50 deflatePrime @51 deflatePending @52 unzOpen @61 unzClose @62 unzGetGlobalInfo @63 unzGetCurrentFileInfo @64 unzGoToFirstFile @65 unzGoToNextFile @66 unzOpenCurrentFile @67 unzReadCurrentFile @68 unzOpenCurrentFile3 @69 unztell @70 unzeof @71 unzCloseCurrentFile @72 unzGetGlobalComment @73 unzStringFileNameCompare @74 unzLocateFile @75 unzGetLocalExtrafield @76 unzOpen2 @77 unzOpenCurrentFile2 @78 unzOpenCurrentFilePassword @79 zipOpen @80 zipOpenNewFileInZip @81 zipWriteInFileInZip @82 zipCloseFileInZip @83 zipClose @84 zipOpenNewFileInZip2 @86 zipCloseFileInZipRaw @87 zipOpen2 @88 zipOpenNewFileInZip3 @89 unzGetFilePos @100 unzGoToFilePos @101 fill_win32_filefunc @110 ; zlibwapi v1.2.4 added: fill_win32_filefunc64 @111 fill_win32_filefunc64A @112 fill_win32_filefunc64W @113 unzOpen64 @120 unzOpen2_64 @121 unzGetGlobalInfo64 @122 unzGetCurrentFileInfo64 @124 unzGetCurrentFileZStreamPos64 @125 unztell64 @126 unzGetFilePos64 @127 unzGoToFilePos64 @128 zipOpen64 @130 zipOpen2_64 @131 zipOpenNewFileInZip64 @132 zipOpenNewFileInZip2_64 @133 zipOpenNewFileInZip3_64 @134 zipOpenNewFileInZip4_64 @135 zipCloseFileInZipRaw64 @136 ; zlib1 v1.2.4 added: adler32_combine @140 crc32_combine @142 deflateSetHeader @144 deflateTune @145 gzbuffer @146 gzclose_r @147 gzclose_w @148 gzdirect @149 gzoffset @150 inflateGetHeader @156 inflateMark @157 inflatePrime @158 inflateReset2 @159 inflateUndermine @160 ; zlib1 v1.2.6 added: gzgetc_ @161 inflateResetKeep @163 deflateResetKeep @164 ; zlib1 v1.2.7 added: gzopen_w @165 ; zlib1 v1.2.8 added: inflateGetDictionary @166 gzvprintf @167 tcl8.6.5/compat/zlib/contrib/iostream/0000755000175000017500000000000012665173607017300 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/iostream/zfstream.cpp0000644000175000017500000001177012663653131021636 0ustar sergeisergei #include "zfstream.h" gzfilebuf::gzfilebuf() : file(NULL), mode(0), own_file_descriptor(0) { } gzfilebuf::~gzfilebuf() { sync(); if ( own_file_descriptor ) close(); } gzfilebuf *gzfilebuf::open( const char *name, int io_mode ) { if ( is_open() ) return NULL; char char_mode[10]; char *p = char_mode; if ( io_mode & ios::in ) { mode = ios::in; *p++ = 'r'; } else if ( io_mode & ios::app ) { mode = ios::app; *p++ = 'a'; } else { mode = ios::out; *p++ = 'w'; } if ( io_mode & ios::binary ) { mode |= ios::binary; *p++ = 'b'; } // Hard code the compression level if ( io_mode & (ios::out|ios::app )) { *p++ = '9'; } // Put the end-of-string indicator *p = '\0'; if ( (file = gzopen(name, char_mode)) == NULL ) return NULL; own_file_descriptor = 1; return this; } gzfilebuf *gzfilebuf::attach( int file_descriptor, int io_mode ) { if ( is_open() ) return NULL; char char_mode[10]; char *p = char_mode; if ( io_mode & ios::in ) { mode = ios::in; *p++ = 'r'; } else if ( io_mode & ios::app ) { mode = ios::app; *p++ = 'a'; } else { mode = ios::out; *p++ = 'w'; } if ( io_mode & ios::binary ) { mode |= ios::binary; *p++ = 'b'; } // Hard code the compression level if ( io_mode & (ios::out|ios::app )) { *p++ = '9'; } // Put the end-of-string indicator *p = '\0'; if ( (file = gzdopen(file_descriptor, char_mode)) == NULL ) return NULL; own_file_descriptor = 0; return this; } gzfilebuf *gzfilebuf::close() { if ( is_open() ) { sync(); gzclose( file ); file = NULL; } return this; } int gzfilebuf::setcompressionlevel( int comp_level ) { return gzsetparams(file, comp_level, -2); } int gzfilebuf::setcompressionstrategy( int comp_strategy ) { return gzsetparams(file, -2, comp_strategy); } streampos gzfilebuf::seekoff( streamoff off, ios::seek_dir dir, int which ) { return streampos(EOF); } int gzfilebuf::underflow() { // If the file hasn't been opened for reading, error. if ( !is_open() || !(mode & ios::in) ) return EOF; // if a buffer doesn't exists, allocate one. if ( !base() ) { if ( (allocate()) == EOF ) return EOF; setp(0,0); } else { if ( in_avail() ) return (unsigned char) *gptr(); if ( out_waiting() ) { if ( flushbuf() == EOF ) return EOF; } } // Attempt to fill the buffer. int result = fillbuf(); if ( result == EOF ) { // disable get area setg(0,0,0); return EOF; } return (unsigned char) *gptr(); } int gzfilebuf::overflow( int c ) { if ( !is_open() || !(mode & ios::out) ) return EOF; if ( !base() ) { if ( allocate() == EOF ) return EOF; setg(0,0,0); } else { if (in_avail()) { return EOF; } if (out_waiting()) { if (flushbuf() == EOF) return EOF; } } int bl = blen(); setp( base(), base() + bl); if ( c != EOF ) { *pptr() = c; pbump(1); } return 0; } int gzfilebuf::sync() { if ( !is_open() ) return EOF; if ( out_waiting() ) return flushbuf(); return 0; } int gzfilebuf::flushbuf() { int n; char *q; q = pbase(); n = pptr() - q; if ( gzwrite( file, q, n) < n ) return EOF; setp(0,0); return 0; } int gzfilebuf::fillbuf() { int required; char *p; p = base(); required = blen(); int t = gzread( file, p, required ); if ( t <= 0) return EOF; setg( base(), base(), base()+t); return t; } gzfilestream_common::gzfilestream_common() : ios( gzfilestream_common::rdbuf() ) { } gzfilestream_common::~gzfilestream_common() { } void gzfilestream_common::attach( int fd, int io_mode ) { if ( !buffer.attach( fd, io_mode) ) clear( ios::failbit | ios::badbit ); else clear(); } void gzfilestream_common::open( const char *name, int io_mode ) { if ( !buffer.open( name, io_mode ) ) clear( ios::failbit | ios::badbit ); else clear(); } void gzfilestream_common::close() { if ( !buffer.close() ) clear( ios::failbit | ios::badbit ); } gzfilebuf *gzfilestream_common::rdbuf() { return &buffer; } gzifstream::gzifstream() : ios( gzfilestream_common::rdbuf() ) { clear( ios::badbit ); } gzifstream::gzifstream( const char *name, int io_mode ) : ios( gzfilestream_common::rdbuf() ) { gzfilestream_common::open( name, io_mode ); } gzifstream::gzifstream( int fd, int io_mode ) : ios( gzfilestream_common::rdbuf() ) { gzfilestream_common::attach( fd, io_mode ); } gzifstream::~gzifstream() { } gzofstream::gzofstream() : ios( gzfilestream_common::rdbuf() ) { clear( ios::badbit ); } gzofstream::gzofstream( const char *name, int io_mode ) : ios( gzfilestream_common::rdbuf() ) { gzfilestream_common::open( name, io_mode ); } gzofstream::gzofstream( int fd, int io_mode ) : ios( gzfilestream_common::rdbuf() ) { gzfilestream_common::attach( fd, io_mode ); } gzofstream::~gzofstream() { } tcl8.6.5/compat/zlib/contrib/iostream/test.cpp0000644000175000017500000000101612663653131020752 0ustar sergeisergei #include "zfstream.h" int main() { // Construct a stream object with this filebuffer. Anything sent // to this stream will go to standard out. gzofstream os( 1, ios::out ); // This text is getting compressed and sent to stdout. // To prove this, run 'test | zcat'. os << "Hello, Mommy" << endl; os << setcompressionlevel( Z_NO_COMPRESSION ); os << "hello, hello, hi, ho!" << endl; setcompressionlevel( os, Z_DEFAULT_COMPRESSION ) << "I'm compressing again" << endl; os.close(); return 0; } tcl8.6.5/compat/zlib/contrib/iostream/zfstream.h0000644000175000017500000000464312663653131021304 0ustar sergeisergei #ifndef zfstream_h #define zfstream_h #include #include "zlib.h" class gzfilebuf : public streambuf { public: gzfilebuf( ); virtual ~gzfilebuf(); gzfilebuf *open( const char *name, int io_mode ); gzfilebuf *attach( int file_descriptor, int io_mode ); gzfilebuf *close(); int setcompressionlevel( int comp_level ); int setcompressionstrategy( int comp_strategy ); inline int is_open() const { return (file !=NULL); } virtual streampos seekoff( streamoff, ios::seek_dir, int ); virtual int sync(); protected: virtual int underflow(); virtual int overflow( int = EOF ); private: gzFile file; short mode; short own_file_descriptor; int flushbuf(); int fillbuf(); }; class gzfilestream_common : virtual public ios { friend class gzifstream; friend class gzofstream; friend gzofstream &setcompressionlevel( gzofstream &, int ); friend gzofstream &setcompressionstrategy( gzofstream &, int ); public: virtual ~gzfilestream_common(); void attach( int fd, int io_mode ); void open( const char *name, int io_mode ); void close(); protected: gzfilestream_common(); private: gzfilebuf *rdbuf(); gzfilebuf buffer; }; class gzifstream : public gzfilestream_common, public istream { public: gzifstream(); gzifstream( const char *name, int io_mode = ios::in ); gzifstream( int fd, int io_mode = ios::in ); virtual ~gzifstream(); }; class gzofstream : public gzfilestream_common, public ostream { public: gzofstream(); gzofstream( const char *name, int io_mode = ios::out ); gzofstream( int fd, int io_mode = ios::out ); virtual ~gzofstream(); }; template class gzomanip { friend gzofstream &operator<<(gzofstream &, const gzomanip &); public: gzomanip(gzofstream &(*f)(gzofstream &, T), T v) : func(f), val(v) { } private: gzofstream &(*func)(gzofstream &, T); T val; }; template gzofstream &operator<<(gzofstream &s, const gzomanip &m) { return (*m.func)(s, m.val); } inline gzofstream &setcompressionlevel( gzofstream &s, int l ) { (s.rdbuf())->setcompressionlevel(l); return s; } inline gzofstream &setcompressionstrategy( gzofstream &s, int l ) { (s.rdbuf())->setcompressionstrategy(l); return s; } inline gzomanip setcompressionlevel(int l) { return gzomanip(&setcompressionlevel,l); } inline gzomanip setcompressionstrategy(int l) { return gzomanip(&setcompressionstrategy,l); } #endif tcl8.6.5/compat/zlib/contrib/iostream3/0000755000175000017500000000000012665173607017363 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/iostream3/zfstream.cc0000644000175000017500000003220712663653131021522 0ustar sergeisergei/* * A C++ I/O streams interface to the zlib gz* functions * * by Ludwig Schwardt * original version by Kevin Ruland * * This version is standard-compliant and compatible with gcc 3.x. */ #include "zfstream.h" #include // for strcpy, strcat, strlen (mode strings) #include // for BUFSIZ // Internal buffer sizes (default and "unbuffered" versions) #define BIGBUFSIZE BUFSIZ #define SMALLBUFSIZE 1 /*****************************************************************************/ // Default constructor gzfilebuf::gzfilebuf() : file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false), buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true) { // No buffers to start with this->disable_buffer(); } // Destructor gzfilebuf::~gzfilebuf() { // Sync output buffer and close only if responsible for file // (i.e. attached streams should be left open at this stage) this->sync(); if (own_fd) this->close(); // Make sure internal buffer is deallocated this->disable_buffer(); } // Set compression level and strategy int gzfilebuf::setcompression(int comp_level, int comp_strategy) { return gzsetparams(file, comp_level, comp_strategy); } // Open gzipped file gzfilebuf* gzfilebuf::open(const char *name, std::ios_base::openmode mode) { // Fail if file already open if (this->is_open()) return NULL; // Don't support simultaneous read/write access (yet) if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) return NULL; // Build mode string for gzopen and check it [27.8.1.3.2] char char_mode[6] = "\0\0\0\0\0"; if (!this->open_mode(mode, char_mode)) return NULL; // Attempt to open file if ((file = gzopen(name, char_mode)) == NULL) return NULL; // On success, allocate internal buffer and set flags this->enable_buffer(); io_mode = mode; own_fd = true; return this; } // Attach to gzipped file gzfilebuf* gzfilebuf::attach(int fd, std::ios_base::openmode mode) { // Fail if file already open if (this->is_open()) return NULL; // Don't support simultaneous read/write access (yet) if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) return NULL; // Build mode string for gzdopen and check it [27.8.1.3.2] char char_mode[6] = "\0\0\0\0\0"; if (!this->open_mode(mode, char_mode)) return NULL; // Attempt to attach to file if ((file = gzdopen(fd, char_mode)) == NULL) return NULL; // On success, allocate internal buffer and set flags this->enable_buffer(); io_mode = mode; own_fd = false; return this; } // Close gzipped file gzfilebuf* gzfilebuf::close() { // Fail immediately if no file is open if (!this->is_open()) return NULL; // Assume success gzfilebuf* retval = this; // Attempt to sync and close gzipped file if (this->sync() == -1) retval = NULL; if (gzclose(file) < 0) retval = NULL; // File is now gone anyway (postcondition [27.8.1.3.8]) file = NULL; own_fd = false; // Destroy internal buffer if it exists this->disable_buffer(); return retval; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Convert int open mode to mode string bool gzfilebuf::open_mode(std::ios_base::openmode mode, char* c_mode) const { bool testb = mode & std::ios_base::binary; bool testi = mode & std::ios_base::in; bool testo = mode & std::ios_base::out; bool testt = mode & std::ios_base::trunc; bool testa = mode & std::ios_base::app; // Check for valid flag combinations - see [27.8.1.3.2] (Table 92) // Original zfstream hardcoded the compression level to maximum here... // Double the time for less than 1% size improvement seems // excessive though - keeping it at the default level // To change back, just append "9" to the next three mode strings if (!testi && testo && !testt && !testa) strcpy(c_mode, "w"); if (!testi && testo && !testt && testa) strcpy(c_mode, "a"); if (!testi && testo && testt && !testa) strcpy(c_mode, "w"); if (testi && !testo && !testt && !testa) strcpy(c_mode, "r"); // No read/write mode yet // if (testi && testo && !testt && !testa) // strcpy(c_mode, "r+"); // if (testi && testo && testt && !testa) // strcpy(c_mode, "w+"); // Mode string should be empty for invalid combination of flags if (strlen(c_mode) == 0) return false; if (testb) strcat(c_mode, "b"); return true; } // Determine number of characters in internal get buffer std::streamsize gzfilebuf::showmanyc() { // Calls to underflow will fail if file not opened for reading if (!this->is_open() || !(io_mode & std::ios_base::in)) return -1; // Make sure get area is in use if (this->gptr() && (this->gptr() < this->egptr())) return std::streamsize(this->egptr() - this->gptr()); else return 0; } // Fill get area from gzipped file gzfilebuf::int_type gzfilebuf::underflow() { // If something is left in the get area by chance, return it // (this shouldn't normally happen, as underflow is only supposed // to be called when gptr >= egptr, but it serves as error check) if (this->gptr() && (this->gptr() < this->egptr())) return traits_type::to_int_type(*(this->gptr())); // If the file hasn't been opened for reading, produce error if (!this->is_open() || !(io_mode & std::ios_base::in)) return traits_type::eof(); // Attempt to fill internal buffer from gzipped file // (buffer must be guaranteed to exist...) int bytes_read = gzread(file, buffer, buffer_size); // Indicates error or EOF if (bytes_read <= 0) { // Reset get area this->setg(buffer, buffer, buffer); return traits_type::eof(); } // Make all bytes read from file available as get area this->setg(buffer, buffer, buffer + bytes_read); // Return next character in get area return traits_type::to_int_type(*(this->gptr())); } // Write put area to gzipped file gzfilebuf::int_type gzfilebuf::overflow(int_type c) { // Determine whether put area is in use if (this->pbase()) { // Double-check pointer range if (this->pptr() > this->epptr() || this->pptr() < this->pbase()) return traits_type::eof(); // Add extra character to buffer if not EOF if (!traits_type::eq_int_type(c, traits_type::eof())) { *(this->pptr()) = traits_type::to_char_type(c); this->pbump(1); } // Number of characters to write to file int bytes_to_write = this->pptr() - this->pbase(); // Overflow doesn't fail if nothing is to be written if (bytes_to_write > 0) { // If the file hasn't been opened for writing, produce error if (!this->is_open() || !(io_mode & std::ios_base::out)) return traits_type::eof(); // If gzipped file won't accept all bytes written to it, fail if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write) return traits_type::eof(); // Reset next pointer to point to pbase on success this->pbump(-bytes_to_write); } } // Write extra character to file if not EOF else if (!traits_type::eq_int_type(c, traits_type::eof())) { // If the file hasn't been opened for writing, produce error if (!this->is_open() || !(io_mode & std::ios_base::out)) return traits_type::eof(); // Impromptu char buffer (allows "unbuffered" output) char_type last_char = traits_type::to_char_type(c); // If gzipped file won't accept this character, fail if (gzwrite(file, &last_char, 1) != 1) return traits_type::eof(); } // If you got here, you have succeeded (even if c was EOF) // The return value should therefore be non-EOF if (traits_type::eq_int_type(c, traits_type::eof())) return traits_type::not_eof(c); else return c; } // Assign new buffer std::streambuf* gzfilebuf::setbuf(char_type* p, std::streamsize n) { // First make sure stuff is sync'ed, for safety if (this->sync() == -1) return NULL; // If buffering is turned off on purpose via setbuf(0,0), still allocate one... // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at // least a buffer of size 1 (very inefficient though, therefore make it bigger?) // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems) if (!p || !n) { // Replace existing buffer (if any) with small internal buffer this->disable_buffer(); buffer = NULL; buffer_size = 0; own_buffer = true; this->enable_buffer(); } else { // Replace existing buffer (if any) with external buffer this->disable_buffer(); buffer = p; buffer_size = n; own_buffer = false; this->enable_buffer(); } return this; } // Write put area to gzipped file (i.e. ensures that put area is empty) int gzfilebuf::sync() { return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // Allocate internal buffer void gzfilebuf::enable_buffer() { // If internal buffer required, allocate one if (own_buffer && !buffer) { // Check for buffered vs. "unbuffered" if (buffer_size > 0) { // Allocate internal buffer buffer = new char_type[buffer_size]; // Get area starts empty and will be expanded by underflow as need arises this->setg(buffer, buffer, buffer); // Setup entire internal buffer as put area. // The one-past-end pointer actually points to the last element of the buffer, // so that overflow(c) can safely add the extra character c to the sequence. // These pointers remain in place for the duration of the buffer this->setp(buffer, buffer + buffer_size - 1); } else { // Even in "unbuffered" case, (small?) get buffer is still required buffer_size = SMALLBUFSIZE; buffer = new char_type[buffer_size]; this->setg(buffer, buffer, buffer); // "Unbuffered" means no put buffer this->setp(0, 0); } } else { // If buffer already allocated, reset buffer pointers just to make sure no // stale chars are lying around this->setg(buffer, buffer, buffer); this->setp(buffer, buffer + buffer_size - 1); } } // Destroy internal buffer void gzfilebuf::disable_buffer() { // If internal buffer exists, deallocate it if (own_buffer && buffer) { // Preserve unbuffered status by zeroing size if (!this->pbase()) buffer_size = 0; delete[] buffer; buffer = NULL; this->setg(0, 0, 0); this->setp(0, 0); } else { // Reset buffer pointers to initial state if external buffer exists this->setg(buffer, buffer, buffer); if (buffer) this->setp(buffer, buffer + buffer_size - 1); else this->setp(0, 0); } } /*****************************************************************************/ // Default constructor initializes stream buffer gzifstream::gzifstream() : std::istream(NULL), sb() { this->init(&sb); } // Initialize stream buffer and open file gzifstream::gzifstream(const char* name, std::ios_base::openmode mode) : std::istream(NULL), sb() { this->init(&sb); this->open(name, mode); } // Initialize stream buffer and attach to file gzifstream::gzifstream(int fd, std::ios_base::openmode mode) : std::istream(NULL), sb() { this->init(&sb); this->attach(fd, mode); } // Open file and go into fail() state if unsuccessful void gzifstream::open(const char* name, std::ios_base::openmode mode) { if (!sb.open(name, mode | std::ios_base::in)) this->setstate(std::ios_base::failbit); else this->clear(); } // Attach to file and go into fail() state if unsuccessful void gzifstream::attach(int fd, std::ios_base::openmode mode) { if (!sb.attach(fd, mode | std::ios_base::in)) this->setstate(std::ios_base::failbit); else this->clear(); } // Close file void gzifstream::close() { if (!sb.close()) this->setstate(std::ios_base::failbit); } /*****************************************************************************/ // Default constructor initializes stream buffer gzofstream::gzofstream() : std::ostream(NULL), sb() { this->init(&sb); } // Initialize stream buffer and open file gzofstream::gzofstream(const char* name, std::ios_base::openmode mode) : std::ostream(NULL), sb() { this->init(&sb); this->open(name, mode); } // Initialize stream buffer and attach to file gzofstream::gzofstream(int fd, std::ios_base::openmode mode) : std::ostream(NULL), sb() { this->init(&sb); this->attach(fd, mode); } // Open file and go into fail() state if unsuccessful void gzofstream::open(const char* name, std::ios_base::openmode mode) { if (!sb.open(name, mode | std::ios_base::out)) this->setstate(std::ios_base::failbit); else this->clear(); } // Attach to file and go into fail() state if unsuccessful void gzofstream::attach(int fd, std::ios_base::openmode mode) { if (!sb.attach(fd, mode | std::ios_base::out)) this->setstate(std::ios_base::failbit); else this->clear(); } // Close file void gzofstream::close() { if (!sb.close()) this->setstate(std::ios_base::failbit); } tcl8.6.5/compat/zlib/contrib/iostream3/test.cc0000644000175000017500000000272212663653131020645 0ustar sergeisergei/* * Test program for gzifstream and gzofstream * * by Ludwig Schwardt * original version by Kevin Ruland */ #include "zfstream.h" #include // for cout int main() { gzofstream outf; gzifstream inf; char buf[80]; outf.open("test1.txt.gz"); outf << "The quick brown fox sidestepped the lazy canine\n" << 1.3 << "\nPlan " << 9 << std::endl; outf.close(); std::cout << "Wrote the following message to 'test1.txt.gz' (check with zcat or zless):\n" << "The quick brown fox sidestepped the lazy canine\n" << 1.3 << "\nPlan " << 9 << std::endl; std::cout << "\nReading 'test1.txt.gz' (buffered) produces:\n"; inf.open("test1.txt.gz"); while (inf.getline(buf,80,'\n')) { std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n"; } inf.close(); outf.rdbuf()->pubsetbuf(0,0); outf.open("test2.txt.gz"); outf << setcompression(Z_NO_COMPRESSION) << "The quick brown fox sidestepped the lazy canine\n" << 1.3 << "\nPlan " << 9 << std::endl; outf.close(); std::cout << "\nWrote the same message to 'test2.txt.gz' in uncompressed form"; std::cout << "\nReading 'test2.txt.gz' (unbuffered) produces:\n"; inf.rdbuf()->pubsetbuf(0,0); inf.open("test2.txt.gz"); while (inf.getline(buf,80,'\n')) { std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n"; } inf.close(); return 0; } tcl8.6.5/compat/zlib/contrib/iostream3/TODO0000644000175000017500000000075312663653131020051 0ustar sergeisergeiPossible upgrades to gzfilebuf: - The ability to do putback (e.g. putbackfail) - The ability to seek (zlib supports this, but could be slow/tricky) - Simultaneous read/write access (does it make sense?) - Support for ios_base::ate open mode - Locale support? - Check public interface to see which calls give problems (due to dependence on library internals) - Override operator<<(ostream&, gzfilebuf*) to allow direct copying of stream buffer to stream ( i.e. os << is.rdbuf(); ) tcl8.6.5/compat/zlib/contrib/iostream3/zfstream.h0000644000175000017500000002772012663653131021370 0ustar sergeisergei/* * A C++ I/O streams interface to the zlib gz* functions * * by Ludwig Schwardt * original version by Kevin Ruland * * This version is standard-compliant and compatible with gcc 3.x. */ #ifndef ZFSTREAM_H #define ZFSTREAM_H #include // not iostream, since we don't need cin/cout #include #include "zlib.h" /*****************************************************************************/ /** * @brief Gzipped file stream buffer class. * * This class implements basic_filebuf for gzipped files. It doesn't yet support * seeking (allowed by zlib but slow/limited), putback and read/write access * (tricky). Otherwise, it attempts to be a drop-in replacement for the standard * file streambuf. */ class gzfilebuf : public std::streambuf { public: // Default constructor. gzfilebuf(); // Destructor. virtual ~gzfilebuf(); /** * @brief Set compression level and strategy on the fly. * @param comp_level Compression level (see zlib.h for allowed values) * @param comp_strategy Compression strategy (see zlib.h for allowed values) * @return Z_OK on success, Z_STREAM_ERROR otherwise. * * Unfortunately, these parameters cannot be modified separately, as the * previous zfstream version assumed. Since the strategy is seldom changed, * it can default and setcompression(level) then becomes like the old * setcompressionlevel(level). */ int setcompression(int comp_level, int comp_strategy = Z_DEFAULT_STRATEGY); /** * @brief Check if file is open. * @return True if file is open. */ bool is_open() const { return (file != NULL); } /** * @brief Open gzipped file. * @param name File name. * @param mode Open mode flags. * @return @c this on success, NULL on failure. */ gzfilebuf* open(const char* name, std::ios_base::openmode mode); /** * @brief Attach to already open gzipped file. * @param fd File descriptor. * @param mode Open mode flags. * @return @c this on success, NULL on failure. */ gzfilebuf* attach(int fd, std::ios_base::openmode mode); /** * @brief Close gzipped file. * @return @c this on success, NULL on failure. */ gzfilebuf* close(); protected: /** * @brief Convert ios open mode int to mode string used by zlib. * @return True if valid mode flag combination. */ bool open_mode(std::ios_base::openmode mode, char* c_mode) const; /** * @brief Number of characters available in stream buffer. * @return Number of characters. * * This indicates number of characters in get area of stream buffer. * These characters can be read without accessing the gzipped file. */ virtual std::streamsize showmanyc(); /** * @brief Fill get area from gzipped file. * @return First character in get area on success, EOF on error. * * This actually reads characters from gzipped file to stream * buffer. Always buffered. */ virtual int_type underflow(); /** * @brief Write put area to gzipped file. * @param c Extra character to add to buffer contents. * @return Non-EOF on success, EOF on error. * * This actually writes characters in stream buffer to * gzipped file. With unbuffered output this is done one * character at a time. */ virtual int_type overflow(int_type c = traits_type::eof()); /** * @brief Installs external stream buffer. * @param p Pointer to char buffer. * @param n Size of external buffer. * @return @c this on success, NULL on failure. * * Call setbuf(0,0) to enable unbuffered output. */ virtual std::streambuf* setbuf(char_type* p, std::streamsize n); /** * @brief Flush stream buffer to file. * @return 0 on success, -1 on error. * * This calls underflow(EOF) to do the job. */ virtual int sync(); // // Some future enhancements // // virtual int_type uflow(); // virtual int_type pbackfail(int_type c = traits_type::eof()); // virtual pos_type // seekoff(off_type off, // std::ios_base::seekdir way, // std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out); // virtual pos_type // seekpos(pos_type sp, // std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out); private: /** * @brief Allocate internal buffer. * * This function is safe to call multiple times. It will ensure * that a proper internal buffer exists if it is required. If the * buffer already exists or is external, the buffer pointers will be * reset to their original state. */ void enable_buffer(); /** * @brief Destroy internal buffer. * * This function is safe to call multiple times. It will ensure * that the internal buffer is deallocated if it exists. In any * case, it will also reset the buffer pointers. */ void disable_buffer(); /** * Underlying file pointer. */ gzFile file; /** * Mode in which file was opened. */ std::ios_base::openmode io_mode; /** * @brief True if this object owns file descriptor. * * This makes the class responsible for closing the file * upon destruction. */ bool own_fd; /** * @brief Stream buffer. * * For simplicity this remains allocated on the free store for the * entire life span of the gzfilebuf object, unless replaced by setbuf. */ char_type* buffer; /** * @brief Stream buffer size. * * Defaults to system default buffer size (typically 8192 bytes). * Modified by setbuf. */ std::streamsize buffer_size; /** * @brief True if this object owns stream buffer. * * This makes the class responsible for deleting the buffer * upon destruction. */ bool own_buffer; }; /*****************************************************************************/ /** * @brief Gzipped file input stream class. * * This class implements ifstream for gzipped files. Seeking and putback * is not supported yet. */ class gzifstream : public std::istream { public: // Default constructor gzifstream(); /** * @brief Construct stream on gzipped file to be opened. * @param name File name. * @param mode Open mode flags (forced to contain ios::in). */ explicit gzifstream(const char* name, std::ios_base::openmode mode = std::ios_base::in); /** * @brief Construct stream on already open gzipped file. * @param fd File descriptor. * @param mode Open mode flags (forced to contain ios::in). */ explicit gzifstream(int fd, std::ios_base::openmode mode = std::ios_base::in); /** * Obtain underlying stream buffer. */ gzfilebuf* rdbuf() const { return const_cast(&sb); } /** * @brief Check if file is open. * @return True if file is open. */ bool is_open() { return sb.is_open(); } /** * @brief Open gzipped file. * @param name File name. * @param mode Open mode flags (forced to contain ios::in). * * Stream will be in state good() if file opens successfully; * otherwise in state fail(). This differs from the behavior of * ifstream, which never sets the state to good() and therefore * won't allow you to reuse the stream for a second file unless * you manually clear() the state. The choice is a matter of * convenience. */ void open(const char* name, std::ios_base::openmode mode = std::ios_base::in); /** * @brief Attach to already open gzipped file. * @param fd File descriptor. * @param mode Open mode flags (forced to contain ios::in). * * Stream will be in state good() if attach succeeded; otherwise * in state fail(). */ void attach(int fd, std::ios_base::openmode mode = std::ios_base::in); /** * @brief Close gzipped file. * * Stream will be in state fail() if close failed. */ void close(); private: /** * Underlying stream buffer. */ gzfilebuf sb; }; /*****************************************************************************/ /** * @brief Gzipped file output stream class. * * This class implements ofstream for gzipped files. Seeking and putback * is not supported yet. */ class gzofstream : public std::ostream { public: // Default constructor gzofstream(); /** * @brief Construct stream on gzipped file to be opened. * @param name File name. * @param mode Open mode flags (forced to contain ios::out). */ explicit gzofstream(const char* name, std::ios_base::openmode mode = std::ios_base::out); /** * @brief Construct stream on already open gzipped file. * @param fd File descriptor. * @param mode Open mode flags (forced to contain ios::out). */ explicit gzofstream(int fd, std::ios_base::openmode mode = std::ios_base::out); /** * Obtain underlying stream buffer. */ gzfilebuf* rdbuf() const { return const_cast(&sb); } /** * @brief Check if file is open. * @return True if file is open. */ bool is_open() { return sb.is_open(); } /** * @brief Open gzipped file. * @param name File name. * @param mode Open mode flags (forced to contain ios::out). * * Stream will be in state good() if file opens successfully; * otherwise in state fail(). This differs from the behavior of * ofstream, which never sets the state to good() and therefore * won't allow you to reuse the stream for a second file unless * you manually clear() the state. The choice is a matter of * convenience. */ void open(const char* name, std::ios_base::openmode mode = std::ios_base::out); /** * @brief Attach to already open gzipped file. * @param fd File descriptor. * @param mode Open mode flags (forced to contain ios::out). * * Stream will be in state good() if attach succeeded; otherwise * in state fail(). */ void attach(int fd, std::ios_base::openmode mode = std::ios_base::out); /** * @brief Close gzipped file. * * Stream will be in state fail() if close failed. */ void close(); private: /** * Underlying stream buffer. */ gzfilebuf sb; }; /*****************************************************************************/ /** * @brief Gzipped file output stream manipulator class. * * This class defines a two-argument manipulator for gzofstream. It is used * as base for the setcompression(int,int) manipulator. */ template class gzomanip2 { public: // Allows insertor to peek at internals template friend gzofstream& operator<<(gzofstream&, const gzomanip2&); // Constructor gzomanip2(gzofstream& (*f)(gzofstream&, T1, T2), T1 v1, T2 v2); private: // Underlying manipulator function gzofstream& (*func)(gzofstream&, T1, T2); // Arguments for manipulator function T1 val1; T2 val2; }; /*****************************************************************************/ // Manipulator function thunks through to stream buffer inline gzofstream& setcompression(gzofstream &gzs, int l, int s = Z_DEFAULT_STRATEGY) { (gzs.rdbuf())->setcompression(l, s); return gzs; } // Manipulator constructor stores arguments template inline gzomanip2::gzomanip2(gzofstream &(*f)(gzofstream &, T1, T2), T1 v1, T2 v2) : func(f), val1(v1), val2(v2) { } // Insertor applies underlying manipulator function to stream template inline gzofstream& operator<<(gzofstream& s, const gzomanip2& m) { return (*m.func)(s, m.val1, m.val2); } // Insert this onto stream to simplify setting of compression level inline gzomanip2 setcompression(int l, int s = Z_DEFAULT_STRATEGY) { return gzomanip2(&setcompression, l, s); } #endif // ZFSTREAM_H tcl8.6.5/compat/zlib/contrib/iostream3/README0000644000175000017500000000272212663653131020237 0ustar sergeisergeiThese classes provide a C++ stream interface to the zlib library. It allows you to do things like: gzofstream outf("blah.gz"); outf << "These go into the gzip file " << 123 << endl; It does this by deriving a specialized stream buffer for gzipped files, which is the way Stroustrup would have done it. :-> The gzifstream and gzofstream classes were originally written by Kevin Ruland and made available in the zlib contrib/iostream directory. The older version still compiles under gcc 2.xx, but not under gcc 3.xx, which sparked the development of this version. The new classes are as standard-compliant as possible, closely following the approach of the standard library's fstream classes. It compiles under gcc versions 3.2 and 3.3, but not under gcc 2.xx. This is mainly due to changes in the standard library naming scheme. The new version of gzifstream/gzofstream/gzfilebuf differs from the previous one in the following respects: - added showmanyc - added setbuf, with support for unbuffered output via setbuf(0,0) - a few bug fixes of stream behavior - gzipped output file opened with default compression level instead of maximum level - setcompressionlevel()/strategy() members replaced by single setcompression() The code is provided "as is", with the permission to use, copy, modify, distribute and sell it for any purpose without fee. Ludwig Schwardt DSP Lab Electrical & Electronic Engineering Department University of Stellenbosch South Africa tcl8.6.5/compat/zlib/contrib/ada/0000755000175000017500000000000012665173607016202 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/ada/zlib-thin.ads0000644000175000017500000003671312663660064020601 0ustar sergeisergei---------------------------------------------------------------- -- ZLib for Ada thick binding. -- -- -- -- Copyright (C) 2002-2003 Dmitriy Anisimkov -- -- -- -- Open source license information is in the zlib.ads file. -- ---------------------------------------------------------------- -- $Id: zlib-thin.ads,v 1.11 2004/07/23 06:33:11 vagul Exp $ with Interfaces.C.Strings; with System; private package ZLib.Thin is -- From zconf.h MAX_MEM_LEVEL : constant := 9; -- zconf.h:105 -- zconf.h:105 MAX_WBITS : constant := 15; -- zconf.h:115 -- 32K LZ77 window -- zconf.h:115 SEEK_SET : constant := 8#0000#; -- zconf.h:244 -- Seek from beginning of file. -- zconf.h:244 SEEK_CUR : constant := 1; -- zconf.h:245 -- Seek from current position. -- zconf.h:245 SEEK_END : constant := 2; -- zconf.h:246 -- Set file pointer to EOF plus "offset" -- zconf.h:246 type Byte is new Interfaces.C.unsigned_char; -- 8 bits -- zconf.h:214 type UInt is new Interfaces.C.unsigned; -- 16 bits or more -- zconf.h:216 type Int is new Interfaces.C.int; type ULong is new Interfaces.C.unsigned_long; -- 32 bits or more -- zconf.h:217 subtype Chars_Ptr is Interfaces.C.Strings.chars_ptr; type ULong_Access is access ULong; type Int_Access is access Int; subtype Voidp is System.Address; -- zconf.h:232 subtype Byte_Access is Voidp; Nul : constant Voidp := System.Null_Address; -- end from zconf Z_NO_FLUSH : constant := 8#0000#; -- zlib.h:125 -- zlib.h:125 Z_PARTIAL_FLUSH : constant := 1; -- zlib.h:126 -- will be removed, use -- Z_SYNC_FLUSH instead -- zlib.h:126 Z_SYNC_FLUSH : constant := 2; -- zlib.h:127 -- zlib.h:127 Z_FULL_FLUSH : constant := 3; -- zlib.h:128 -- zlib.h:128 Z_FINISH : constant := 4; -- zlib.h:129 -- zlib.h:129 Z_OK : constant := 8#0000#; -- zlib.h:132 -- zlib.h:132 Z_STREAM_END : constant := 1; -- zlib.h:133 -- zlib.h:133 Z_NEED_DICT : constant := 2; -- zlib.h:134 -- zlib.h:134 Z_ERRNO : constant := -1; -- zlib.h:135 -- zlib.h:135 Z_STREAM_ERROR : constant := -2; -- zlib.h:136 -- zlib.h:136 Z_DATA_ERROR : constant := -3; -- zlib.h:137 -- zlib.h:137 Z_MEM_ERROR : constant := -4; -- zlib.h:138 -- zlib.h:138 Z_BUF_ERROR : constant := -5; -- zlib.h:139 -- zlib.h:139 Z_VERSION_ERROR : constant := -6; -- zlib.h:140 -- zlib.h:140 Z_NO_COMPRESSION : constant := 8#0000#; -- zlib.h:145 -- zlib.h:145 Z_BEST_SPEED : constant := 1; -- zlib.h:146 -- zlib.h:146 Z_BEST_COMPRESSION : constant := 9; -- zlib.h:147 -- zlib.h:147 Z_DEFAULT_COMPRESSION : constant := -1; -- zlib.h:148 -- zlib.h:148 Z_FILTERED : constant := 1; -- zlib.h:151 -- zlib.h:151 Z_HUFFMAN_ONLY : constant := 2; -- zlib.h:152 -- zlib.h:152 Z_DEFAULT_STRATEGY : constant := 8#0000#; -- zlib.h:153 -- zlib.h:153 Z_BINARY : constant := 8#0000#; -- zlib.h:156 -- zlib.h:156 Z_ASCII : constant := 1; -- zlib.h:157 -- zlib.h:157 Z_UNKNOWN : constant := 2; -- zlib.h:158 -- zlib.h:158 Z_DEFLATED : constant := 8; -- zlib.h:161 -- zlib.h:161 Z_NULL : constant := 8#0000#; -- zlib.h:164 -- for initializing zalloc, zfree, opaque -- zlib.h:164 type gzFile is new Voidp; -- zlib.h:646 type Z_Stream is private; type Z_Streamp is access all Z_Stream; -- zlib.h:89 type alloc_func is access function (Opaque : Voidp; Items : UInt; Size : UInt) return Voidp; -- zlib.h:63 type free_func is access procedure (opaque : Voidp; address : Voidp); function zlibVersion return Chars_Ptr; function Deflate (strm : Z_Streamp; flush : Int) return Int; function DeflateEnd (strm : Z_Streamp) return Int; function Inflate (strm : Z_Streamp; flush : Int) return Int; function InflateEnd (strm : Z_Streamp) return Int; function deflateSetDictionary (strm : Z_Streamp; dictionary : Byte_Access; dictLength : UInt) return Int; function deflateCopy (dest : Z_Streamp; source : Z_Streamp) return Int; -- zlib.h:478 function deflateReset (strm : Z_Streamp) return Int; -- zlib.h:495 function deflateParams (strm : Z_Streamp; level : Int; strategy : Int) return Int; -- zlib.h:506 function inflateSetDictionary (strm : Z_Streamp; dictionary : Byte_Access; dictLength : UInt) return Int; -- zlib.h:548 function inflateSync (strm : Z_Streamp) return Int; -- zlib.h:565 function inflateReset (strm : Z_Streamp) return Int; -- zlib.h:580 function compress (dest : Byte_Access; destLen : ULong_Access; source : Byte_Access; sourceLen : ULong) return Int; -- zlib.h:601 function compress2 (dest : Byte_Access; destLen : ULong_Access; source : Byte_Access; sourceLen : ULong; level : Int) return Int; -- zlib.h:615 function uncompress (dest : Byte_Access; destLen : ULong_Access; source : Byte_Access; sourceLen : ULong) return Int; function gzopen (path : Chars_Ptr; mode : Chars_Ptr) return gzFile; function gzdopen (fd : Int; mode : Chars_Ptr) return gzFile; function gzsetparams (file : gzFile; level : Int; strategy : Int) return Int; function gzread (file : gzFile; buf : Voidp; len : UInt) return Int; function gzwrite (file : in gzFile; buf : in Voidp; len : in UInt) return Int; function gzprintf (file : in gzFile; format : in Chars_Ptr) return Int; function gzputs (file : in gzFile; s : in Chars_Ptr) return Int; function gzgets (file : gzFile; buf : Chars_Ptr; len : Int) return Chars_Ptr; function gzputc (file : gzFile; char : Int) return Int; function gzgetc (file : gzFile) return Int; function gzflush (file : gzFile; flush : Int) return Int; function gzseek (file : gzFile; offset : Int; whence : Int) return Int; function gzrewind (file : gzFile) return Int; function gztell (file : gzFile) return Int; function gzeof (file : gzFile) return Int; function gzclose (file : gzFile) return Int; function gzerror (file : gzFile; errnum : Int_Access) return Chars_Ptr; function adler32 (adler : ULong; buf : Byte_Access; len : UInt) return ULong; function crc32 (crc : ULong; buf : Byte_Access; len : UInt) return ULong; function deflateInit (strm : Z_Streamp; level : Int; version : Chars_Ptr; stream_size : Int) return Int; function deflateInit2 (strm : Z_Streamp; level : Int; method : Int; windowBits : Int; memLevel : Int; strategy : Int; version : Chars_Ptr; stream_size : Int) return Int; function Deflate_Init (strm : Z_Streamp; level : Int; method : Int; windowBits : Int; memLevel : Int; strategy : Int) return Int; pragma Inline (Deflate_Init); function inflateInit (strm : Z_Streamp; version : Chars_Ptr; stream_size : Int) return Int; function inflateInit2 (strm : in Z_Streamp; windowBits : in Int; version : in Chars_Ptr; stream_size : in Int) return Int; function inflateBackInit (strm : in Z_Streamp; windowBits : in Int; window : in Byte_Access; version : in Chars_Ptr; stream_size : in Int) return Int; -- Size of window have to be 2**windowBits. function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int; pragma Inline (Inflate_Init); function zError (err : Int) return Chars_Ptr; function inflateSyncPoint (z : Z_Streamp) return Int; function get_crc_table return ULong_Access; -- Interface to the available fields of the z_stream structure. -- The application must update next_in and avail_in when avail_in has -- dropped to zero. It must update next_out and avail_out when avail_out -- has dropped to zero. The application must initialize zalloc, zfree and -- opaque before calling the init function. procedure Set_In (Strm : in out Z_Stream; Buffer : in Voidp; Size : in UInt); pragma Inline (Set_In); procedure Set_Out (Strm : in out Z_Stream; Buffer : in Voidp; Size : in UInt); pragma Inline (Set_Out); procedure Set_Mem_Func (Strm : in out Z_Stream; Opaque : in Voidp; Alloc : in alloc_func; Free : in free_func); pragma Inline (Set_Mem_Func); function Last_Error_Message (Strm : in Z_Stream) return String; pragma Inline (Last_Error_Message); function Avail_Out (Strm : in Z_Stream) return UInt; pragma Inline (Avail_Out); function Avail_In (Strm : in Z_Stream) return UInt; pragma Inline (Avail_In); function Total_In (Strm : in Z_Stream) return ULong; pragma Inline (Total_In); function Total_Out (Strm : in Z_Stream) return ULong; pragma Inline (Total_Out); function inflateCopy (dest : in Z_Streamp; Source : in Z_Streamp) return Int; function compressBound (Source_Len : in ULong) return ULong; function deflateBound (Strm : in Z_Streamp; Source_Len : in ULong) return ULong; function gzungetc (C : in Int; File : in gzFile) return Int; function zlibCompileFlags return ULong; private type Z_Stream is record -- zlib.h:68 Next_In : Voidp := Nul; -- next input byte Avail_In : UInt := 0; -- number of bytes available at next_in Total_In : ULong := 0; -- total nb of input bytes read so far Next_Out : Voidp := Nul; -- next output byte should be put there Avail_Out : UInt := 0; -- remaining free space at next_out Total_Out : ULong := 0; -- total nb of bytes output so far msg : Chars_Ptr; -- last error message, NULL if no error state : Voidp; -- not visible by applications zalloc : alloc_func := null; -- used to allocate the internal state zfree : free_func := null; -- used to free the internal state opaque : Voidp; -- private data object passed to -- zalloc and zfree data_type : Int; -- best guess about the data type: -- ascii or binary adler : ULong; -- adler32 value of the uncompressed -- data reserved : ULong; -- reserved for future use end record; pragma Convention (C, Z_Stream); pragma Import (C, zlibVersion, "zlibVersion"); pragma Import (C, Deflate, "deflate"); pragma Import (C, DeflateEnd, "deflateEnd"); pragma Import (C, Inflate, "inflate"); pragma Import (C, InflateEnd, "inflateEnd"); pragma Import (C, deflateSetDictionary, "deflateSetDictionary"); pragma Import (C, deflateCopy, "deflateCopy"); pragma Import (C, deflateReset, "deflateReset"); pragma Import (C, deflateParams, "deflateParams"); pragma Import (C, inflateSetDictionary, "inflateSetDictionary"); pragma Import (C, inflateSync, "inflateSync"); pragma Import (C, inflateReset, "inflateReset"); pragma Import (C, compress, "compress"); pragma Import (C, compress2, "compress2"); pragma Import (C, uncompress, "uncompress"); pragma Import (C, gzopen, "gzopen"); pragma Import (C, gzdopen, "gzdopen"); pragma Import (C, gzsetparams, "gzsetparams"); pragma Import (C, gzread, "gzread"); pragma Import (C, gzwrite, "gzwrite"); pragma Import (C, gzprintf, "gzprintf"); pragma Import (C, gzputs, "gzputs"); pragma Import (C, gzgets, "gzgets"); pragma Import (C, gzputc, "gzputc"); pragma Import (C, gzgetc, "gzgetc"); pragma Import (C, gzflush, "gzflush"); pragma Import (C, gzseek, "gzseek"); pragma Import (C, gzrewind, "gzrewind"); pragma Import (C, gztell, "gztell"); pragma Import (C, gzeof, "gzeof"); pragma Import (C, gzclose, "gzclose"); pragma Import (C, gzerror, "gzerror"); pragma Import (C, adler32, "adler32"); pragma Import (C, crc32, "crc32"); pragma Import (C, deflateInit, "deflateInit_"); pragma Import (C, inflateInit, "inflateInit_"); pragma Import (C, deflateInit2, "deflateInit2_"); pragma Import (C, inflateInit2, "inflateInit2_"); pragma Import (C, zError, "zError"); pragma Import (C, inflateSyncPoint, "inflateSyncPoint"); pragma Import (C, get_crc_table, "get_crc_table"); -- since zlib 1.2.0: pragma Import (C, inflateCopy, "inflateCopy"); pragma Import (C, compressBound, "compressBound"); pragma Import (C, deflateBound, "deflateBound"); pragma Import (C, gzungetc, "gzungetc"); pragma Import (C, zlibCompileFlags, "zlibCompileFlags"); pragma Import (C, inflateBackInit, "inflateBackInit_"); -- I stopped binding the inflateBack routines, becouse realize that -- it does not support zlib and gzip headers for now, and have no -- symmetric deflateBack routines. -- ZLib-Ada is symmetric regarding deflate/inflate data transformation -- and has a similar generic callback interface for the -- deflate/inflate transformation based on the regular Deflate/Inflate -- routines. -- pragma Import (C, inflateBack, "inflateBack"); -- pragma Import (C, inflateBackEnd, "inflateBackEnd"); end ZLib.Thin; tcl8.6.5/compat/zlib/contrib/ada/zlib.ads0000644000175000017500000003243212663660064017633 0ustar sergeisergei------------------------------------------------------------------------------ -- ZLib for Ada thick binding. -- -- -- -- Copyright (C) 2002-2004 Dmitriy Anisimkov -- -- -- -- This library is free software; you can redistribute it and/or modify -- -- it under the terms of the GNU General Public License as published by -- -- the Free Software Foundation; either version 2 of the License, or (at -- -- your option) any later version. -- -- -- -- This library is distributed in the hope that it will be useful, but -- -- WITHOUT ANY WARRANTY; without even the implied warranty of -- -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- -- General Public License for more details. -- -- -- -- You should have received a copy of the GNU General Public License -- -- along with this library; if not, write to the Free Software Foundation, -- -- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -- -- -- -- As a special exception, if other files instantiate generics from this -- -- unit, or you link this unit with other files to produce an executable, -- -- this unit does not by itself cause the resulting executable to be -- -- covered by the GNU General Public License. This exception does not -- -- however invalidate any other reasons why the executable file might be -- -- covered by the GNU Public License. -- ------------------------------------------------------------------------------ -- $Id: zlib.ads,v 1.26 2004/09/06 06:53:19 vagul Exp $ with Ada.Streams; with Interfaces; package ZLib is ZLib_Error : exception; Status_Error : exception; type Compression_Level is new Integer range -1 .. 9; type Flush_Mode is private; type Compression_Method is private; type Window_Bits_Type is new Integer range 8 .. 15; type Memory_Level_Type is new Integer range 1 .. 9; type Unsigned_32 is new Interfaces.Unsigned_32; type Strategy_Type is private; type Header_Type is (None, Auto, Default, GZip); -- Header type usage have a some limitation for inflate. -- See comment for Inflate_Init. subtype Count is Ada.Streams.Stream_Element_Count; Default_Memory_Level : constant Memory_Level_Type := 8; Default_Window_Bits : constant Window_Bits_Type := 15; ---------------------------------- -- Compression method constants -- ---------------------------------- Deflated : constant Compression_Method; -- Only one method allowed in this ZLib version --------------------------------- -- Compression level constants -- --------------------------------- No_Compression : constant Compression_Level := 0; Best_Speed : constant Compression_Level := 1; Best_Compression : constant Compression_Level := 9; Default_Compression : constant Compression_Level := -1; -------------------------- -- Flush mode constants -- -------------------------- No_Flush : constant Flush_Mode; -- Regular way for compression, no flush Partial_Flush : constant Flush_Mode; -- Will be removed, use Z_SYNC_FLUSH instead Sync_Flush : constant Flush_Mode; -- All pending output is flushed to the output buffer and the output -- is aligned on a byte boundary, so that the decompressor can get all -- input data available so far. (In particular avail_in is zero after the -- call if enough output space has been provided before the call.) -- Flushing may degrade compression for some compression algorithms and so -- it should be used only when necessary. Block_Flush : constant Flush_Mode; -- Z_BLOCK requests that inflate() stop -- if and when it get to the next deflate block boundary. When decoding the -- zlib or gzip format, this will cause inflate() to return immediately -- after the header and before the first block. When doing a raw inflate, -- inflate() will go ahead and process the first block, and will return -- when it gets to the end of that block, or when it runs out of data. Full_Flush : constant Flush_Mode; -- All output is flushed as with SYNC_FLUSH, and the compression state -- is reset so that decompression can restart from this point if previous -- compressed data has been damaged or if random access is desired. Using -- Full_Flush too often can seriously degrade the compression. Finish : constant Flush_Mode; -- Just for tell the compressor that input data is complete. ------------------------------------ -- Compression strategy constants -- ------------------------------------ -- RLE stategy could be used only in version 1.2.0 and later. Filtered : constant Strategy_Type; Huffman_Only : constant Strategy_Type; RLE : constant Strategy_Type; Default_Strategy : constant Strategy_Type; Default_Buffer_Size : constant := 4096; type Filter_Type is tagged limited private; -- The filter is for compression and for decompression. -- The usage of the type is depend of its initialization. function Version return String; pragma Inline (Version); -- Return string representation of the ZLib version. procedure Deflate_Init (Filter : in out Filter_Type; Level : in Compression_Level := Default_Compression; Strategy : in Strategy_Type := Default_Strategy; Method : in Compression_Method := Deflated; Window_Bits : in Window_Bits_Type := Default_Window_Bits; Memory_Level : in Memory_Level_Type := Default_Memory_Level; Header : in Header_Type := Default); -- Compressor initialization. -- When Header parameter is Auto or Default, then default zlib header -- would be provided for compressed data. -- When Header is GZip, then gzip header would be set instead of -- default header. -- When Header is None, no header would be set for compressed data. procedure Inflate_Init (Filter : in out Filter_Type; Window_Bits : in Window_Bits_Type := Default_Window_Bits; Header : in Header_Type := Default); -- Decompressor initialization. -- Default header type mean that ZLib default header is expecting in the -- input compressed stream. -- Header type None mean that no header is expecting in the input stream. -- GZip header type mean that GZip header is expecting in the -- input compressed stream. -- Auto header type mean that header type (GZip or Native) would be -- detected automatically in the input stream. -- Note that header types parameter values None, GZip and Auto are -- supported for inflate routine only in ZLib versions 1.2.0.2 and later. -- Deflate_Init is supporting all header types. function Is_Open (Filter : in Filter_Type) return Boolean; pragma Inline (Is_Open); -- Is the filter opened for compression or decompression. procedure Close (Filter : in out Filter_Type; Ignore_Error : in Boolean := False); -- Closing the compression or decompressor. -- If stream is closing before the complete and Ignore_Error is False, -- The exception would be raised. generic with procedure Data_In (Item : out Ada.Streams.Stream_Element_Array; Last : out Ada.Streams.Stream_Element_Offset); with procedure Data_Out (Item : in Ada.Streams.Stream_Element_Array); procedure Generic_Translate (Filter : in out Filter_Type; In_Buffer_Size : in Integer := Default_Buffer_Size; Out_Buffer_Size : in Integer := Default_Buffer_Size); -- Compress/decompress data fetch from Data_In routine and pass the result -- to the Data_Out routine. User should provide Data_In and Data_Out -- for compression/decompression data flow. -- Compression or decompression depend on Filter initialization. function Total_In (Filter : in Filter_Type) return Count; pragma Inline (Total_In); -- Returns total number of input bytes read so far function Total_Out (Filter : in Filter_Type) return Count; pragma Inline (Total_Out); -- Returns total number of bytes output so far function CRC32 (CRC : in Unsigned_32; Data : in Ada.Streams.Stream_Element_Array) return Unsigned_32; pragma Inline (CRC32); -- Compute CRC32, it could be necessary for make gzip format procedure CRC32 (CRC : in out Unsigned_32; Data : in Ada.Streams.Stream_Element_Array); pragma Inline (CRC32); -- Compute CRC32, it could be necessary for make gzip format ------------------------------------------------- -- Below is more complex low level routines. -- ------------------------------------------------- procedure Translate (Filter : in out Filter_Type; In_Data : in Ada.Streams.Stream_Element_Array; In_Last : out Ada.Streams.Stream_Element_Offset; Out_Data : out Ada.Streams.Stream_Element_Array; Out_Last : out Ada.Streams.Stream_Element_Offset; Flush : in Flush_Mode); -- Compress/decompress the In_Data buffer and place the result into -- Out_Data. In_Last is the index of last element from In_Data accepted by -- the Filter. Out_Last is the last element of the received data from -- Filter. To tell the filter that incoming data are complete put the -- Flush parameter to Finish. function Stream_End (Filter : in Filter_Type) return Boolean; pragma Inline (Stream_End); -- Return the true when the stream is complete. procedure Flush (Filter : in out Filter_Type; Out_Data : out Ada.Streams.Stream_Element_Array; Out_Last : out Ada.Streams.Stream_Element_Offset; Flush : in Flush_Mode); pragma Inline (Flush); -- Flushing the data from the compressor. generic with procedure Write (Item : in Ada.Streams.Stream_Element_Array); -- User should provide this routine for accept -- compressed/decompressed data. Buffer_Size : in Ada.Streams.Stream_Element_Offset := Default_Buffer_Size; -- Buffer size for Write user routine. procedure Write (Filter : in out Filter_Type; Item : in Ada.Streams.Stream_Element_Array; Flush : in Flush_Mode := No_Flush); -- Compress/Decompress data from Item to the generic parameter procedure -- Write. Output buffer size could be set in Buffer_Size generic parameter. generic with procedure Read (Item : out Ada.Streams.Stream_Element_Array; Last : out Ada.Streams.Stream_Element_Offset); -- User should provide data for compression/decompression -- thru this routine. Buffer : in out Ada.Streams.Stream_Element_Array; -- Buffer for keep remaining data from the previous -- back read. Rest_First, Rest_Last : in out Ada.Streams.Stream_Element_Offset; -- Rest_First have to be initialized to Buffer'Last + 1 -- Rest_Last have to be initialized to Buffer'Last -- before usage. Allow_Read_Some : in Boolean := False; -- Is it allowed to return Last < Item'Last before end of data. procedure Read (Filter : in out Filter_Type; Item : out Ada.Streams.Stream_Element_Array; Last : out Ada.Streams.Stream_Element_Offset; Flush : in Flush_Mode := No_Flush); -- Compress/Decompress data from generic parameter procedure Read to the -- Item. User should provide Buffer and initialized Rest_First, Rest_Last -- indicators. If Allow_Read_Some is True, Read routines could return -- Last < Item'Last only at end of stream. private use Ada.Streams; pragma Assert (Ada.Streams.Stream_Element'Size = 8); pragma Assert (Ada.Streams.Stream_Element'Modulus = 2**8); type Flush_Mode is new Integer range 0 .. 5; type Compression_Method is new Integer range 8 .. 8; type Strategy_Type is new Integer range 0 .. 3; No_Flush : constant Flush_Mode := 0; Partial_Flush : constant Flush_Mode := 1; Sync_Flush : constant Flush_Mode := 2; Full_Flush : constant Flush_Mode := 3; Finish : constant Flush_Mode := 4; Block_Flush : constant Flush_Mode := 5; Filtered : constant Strategy_Type := 1; Huffman_Only : constant Strategy_Type := 2; RLE : constant Strategy_Type := 3; Default_Strategy : constant Strategy_Type := 0; Deflated : constant Compression_Method := 8; type Z_Stream; type Z_Stream_Access is access all Z_Stream; type Filter_Type is tagged limited record Strm : Z_Stream_Access; Compression : Boolean; Stream_End : Boolean; Header : Header_Type; CRC : Unsigned_32; Offset : Stream_Element_Offset; -- Offset for gzip header/footer output. end record; end ZLib; tcl8.6.5/compat/zlib/contrib/ada/zlib.adb0000644000175000017500000004766012663660064017623 0ustar sergeisergei---------------------------------------------------------------- -- ZLib for Ada thick binding. -- -- -- -- Copyright (C) 2002-2004 Dmitriy Anisimkov -- -- -- -- Open source license information is in the zlib.ads file. -- ---------------------------------------------------------------- -- $Id: zlib.adb,v 1.31 2004/09/06 06:53:19 vagul Exp $ with Ada.Exceptions; with Ada.Unchecked_Conversion; with Ada.Unchecked_Deallocation; with Interfaces.C.Strings; with ZLib.Thin; package body ZLib is use type Thin.Int; type Z_Stream is new Thin.Z_Stream; type Return_Code_Enum is (OK, STREAM_END, NEED_DICT, ERRNO, STREAM_ERROR, DATA_ERROR, MEM_ERROR, BUF_ERROR, VERSION_ERROR); type Flate_Step_Function is access function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int; pragma Convention (C, Flate_Step_Function); type Flate_End_Function is access function (Ctrm : in Thin.Z_Streamp) return Thin.Int; pragma Convention (C, Flate_End_Function); type Flate_Type is record Step : Flate_Step_Function; Done : Flate_End_Function; end record; subtype Footer_Array is Stream_Element_Array (1 .. 8); Simple_GZip_Header : constant Stream_Element_Array (1 .. 10) := (16#1f#, 16#8b#, -- Magic header 16#08#, -- Z_DEFLATED 16#00#, -- Flags 16#00#, 16#00#, 16#00#, 16#00#, -- Time 16#00#, -- XFlags 16#03# -- OS code ); -- The simplest gzip header is not for informational, but just for -- gzip format compatibility. -- Note that some code below is using assumption -- Simple_GZip_Header'Last > Footer_Array'Last, so do not make -- Simple_GZip_Header'Last <= Footer_Array'Last. Return_Code : constant array (Thin.Int range <>) of Return_Code_Enum := (0 => OK, 1 => STREAM_END, 2 => NEED_DICT, -1 => ERRNO, -2 => STREAM_ERROR, -3 => DATA_ERROR, -4 => MEM_ERROR, -5 => BUF_ERROR, -6 => VERSION_ERROR); Flate : constant array (Boolean) of Flate_Type := (True => (Step => Thin.Deflate'Access, Done => Thin.DeflateEnd'Access), False => (Step => Thin.Inflate'Access, Done => Thin.InflateEnd'Access)); Flush_Finish : constant array (Boolean) of Flush_Mode := (True => Finish, False => No_Flush); procedure Raise_Error (Stream : in Z_Stream); pragma Inline (Raise_Error); procedure Raise_Error (Message : in String); pragma Inline (Raise_Error); procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int); procedure Free is new Ada.Unchecked_Deallocation (Z_Stream, Z_Stream_Access); function To_Thin_Access is new Ada.Unchecked_Conversion (Z_Stream_Access, Thin.Z_Streamp); procedure Translate_GZip (Filter : in out Filter_Type; In_Data : in Ada.Streams.Stream_Element_Array; In_Last : out Ada.Streams.Stream_Element_Offset; Out_Data : out Ada.Streams.Stream_Element_Array; Out_Last : out Ada.Streams.Stream_Element_Offset; Flush : in Flush_Mode); -- Separate translate routine for make gzip header. procedure Translate_Auto (Filter : in out Filter_Type; In_Data : in Ada.Streams.Stream_Element_Array; In_Last : out Ada.Streams.Stream_Element_Offset; Out_Data : out Ada.Streams.Stream_Element_Array; Out_Last : out Ada.Streams.Stream_Element_Offset; Flush : in Flush_Mode); -- translate routine without additional headers. ----------------- -- Check_Error -- ----------------- procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is use type Thin.Int; begin if Code /= Thin.Z_OK then Raise_Error (Return_Code_Enum'Image (Return_Code (Code)) & ": " & Last_Error_Message (Stream)); end if; end Check_Error; ----------- -- Close -- ----------- procedure Close (Filter : in out Filter_Type; Ignore_Error : in Boolean := False) is Code : Thin.Int; begin if not Ignore_Error and then not Is_Open (Filter) then raise Status_Error; end if; Code := Flate (Filter.Compression).Done (To_Thin_Access (Filter.Strm)); if Ignore_Error or else Code = Thin.Z_OK then Free (Filter.Strm); else declare Error_Message : constant String := Last_Error_Message (Filter.Strm.all); begin Free (Filter.Strm); Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Return_Code_Enum'Image (Return_Code (Code)) & ": " & Error_Message); end; end if; end Close; ----------- -- CRC32 -- ----------- function CRC32 (CRC : in Unsigned_32; Data : in Ada.Streams.Stream_Element_Array) return Unsigned_32 is use Thin; begin return Unsigned_32 (crc32 (ULong (CRC), Data'Address, Data'Length)); end CRC32; procedure CRC32 (CRC : in out Unsigned_32; Data : in Ada.Streams.Stream_Element_Array) is begin CRC := CRC32 (CRC, Data); end CRC32; ------------------ -- Deflate_Init -- ------------------ procedure Deflate_Init (Filter : in out Filter_Type; Level : in Compression_Level := Default_Compression; Strategy : in Strategy_Type := Default_Strategy; Method : in Compression_Method := Deflated; Window_Bits : in Window_Bits_Type := Default_Window_Bits; Memory_Level : in Memory_Level_Type := Default_Memory_Level; Header : in Header_Type := Default) is use type Thin.Int; Win_Bits : Thin.Int := Thin.Int (Window_Bits); begin if Is_Open (Filter) then raise Status_Error; end if; -- We allow ZLib to make header only in case of default header type. -- Otherwise we would either do header by ourselfs, or do not do -- header at all. if Header = None or else Header = GZip then Win_Bits := -Win_Bits; end if; -- For the GZip CRC calculation and make headers. if Header = GZip then Filter.CRC := 0; Filter.Offset := Simple_GZip_Header'First; else Filter.Offset := Simple_GZip_Header'Last + 1; end if; Filter.Strm := new Z_Stream; Filter.Compression := True; Filter.Stream_End := False; Filter.Header := Header; if Thin.Deflate_Init (To_Thin_Access (Filter.Strm), Level => Thin.Int (Level), method => Thin.Int (Method), windowBits => Win_Bits, memLevel => Thin.Int (Memory_Level), strategy => Thin.Int (Strategy)) /= Thin.Z_OK then Raise_Error (Filter.Strm.all); end if; end Deflate_Init; ----------- -- Flush -- ----------- procedure Flush (Filter : in out Filter_Type; Out_Data : out Ada.Streams.Stream_Element_Array; Out_Last : out Ada.Streams.Stream_Element_Offset; Flush : in Flush_Mode) is No_Data : Stream_Element_Array := (1 .. 0 => 0); Last : Stream_Element_Offset; begin Translate (Filter, No_Data, Last, Out_Data, Out_Last, Flush); end Flush; ----------------------- -- Generic_Translate -- ----------------------- procedure Generic_Translate (Filter : in out ZLib.Filter_Type; In_Buffer_Size : in Integer := Default_Buffer_Size; Out_Buffer_Size : in Integer := Default_Buffer_Size) is In_Buffer : Stream_Element_Array (1 .. Stream_Element_Offset (In_Buffer_Size)); Out_Buffer : Stream_Element_Array (1 .. Stream_Element_Offset (Out_Buffer_Size)); Last : Stream_Element_Offset; In_Last : Stream_Element_Offset; In_First : Stream_Element_Offset; Out_Last : Stream_Element_Offset; begin Main : loop Data_In (In_Buffer, Last); In_First := In_Buffer'First; loop Translate (Filter => Filter, In_Data => In_Buffer (In_First .. Last), In_Last => In_Last, Out_Data => Out_Buffer, Out_Last => Out_Last, Flush => Flush_Finish (Last < In_Buffer'First)); if Out_Buffer'First <= Out_Last then Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last)); end if; exit Main when Stream_End (Filter); -- The end of in buffer. exit when In_Last = Last; In_First := In_Last + 1; end loop; end loop Main; end Generic_Translate; ------------------ -- Inflate_Init -- ------------------ procedure Inflate_Init (Filter : in out Filter_Type; Window_Bits : in Window_Bits_Type := Default_Window_Bits; Header : in Header_Type := Default) is use type Thin.Int; Win_Bits : Thin.Int := Thin.Int (Window_Bits); procedure Check_Version; -- Check the latest header types compatibility. procedure Check_Version is begin if Version <= "1.1.4" then Raise_Error ("Inflate header type " & Header_Type'Image (Header) & " incompatible with ZLib version " & Version); end if; end Check_Version; begin if Is_Open (Filter) then raise Status_Error; end if; case Header is when None => Check_Version; -- Inflate data without headers determined -- by negative Win_Bits. Win_Bits := -Win_Bits; when GZip => Check_Version; -- Inflate gzip data defined by flag 16. Win_Bits := Win_Bits + 16; when Auto => Check_Version; -- Inflate with automatic detection -- of gzip or native header defined by flag 32. Win_Bits := Win_Bits + 32; when Default => null; end case; Filter.Strm := new Z_Stream; Filter.Compression := False; Filter.Stream_End := False; Filter.Header := Header; if Thin.Inflate_Init (To_Thin_Access (Filter.Strm), Win_Bits) /= Thin.Z_OK then Raise_Error (Filter.Strm.all); end if; end Inflate_Init; ------------- -- Is_Open -- ------------- function Is_Open (Filter : in Filter_Type) return Boolean is begin return Filter.Strm /= null; end Is_Open; ----------------- -- Raise_Error -- ----------------- procedure Raise_Error (Message : in String) is begin Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message); end Raise_Error; procedure Raise_Error (Stream : in Z_Stream) is begin Raise_Error (Last_Error_Message (Stream)); end Raise_Error; ---------- -- Read -- ---------- procedure Read (Filter : in out Filter_Type; Item : out Ada.Streams.Stream_Element_Array; Last : out Ada.Streams.Stream_Element_Offset; Flush : in Flush_Mode := No_Flush) is In_Last : Stream_Element_Offset; Item_First : Ada.Streams.Stream_Element_Offset := Item'First; V_Flush : Flush_Mode := Flush; begin pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1); pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last); loop if Rest_Last = Buffer'First - 1 then V_Flush := Finish; elsif Rest_First > Rest_Last then Read (Buffer, Rest_Last); Rest_First := Buffer'First; if Rest_Last < Buffer'First then V_Flush := Finish; end if; end if; Translate (Filter => Filter, In_Data => Buffer (Rest_First .. Rest_Last), In_Last => In_Last, Out_Data => Item (Item_First .. Item'Last), Out_Last => Last, Flush => V_Flush); Rest_First := In_Last + 1; exit when Stream_End (Filter) or else Last = Item'Last or else (Last >= Item'First and then Allow_Read_Some); Item_First := Last + 1; end loop; end Read; ---------------- -- Stream_End -- ---------------- function Stream_End (Filter : in Filter_Type) return Boolean is begin if Filter.Header = GZip and Filter.Compression then return Filter.Stream_End and then Filter.Offset = Footer_Array'Last + 1; else return Filter.Stream_End; end if; end Stream_End; -------------- -- Total_In -- -------------- function Total_In (Filter : in Filter_Type) return Count is begin return Count (Thin.Total_In (To_Thin_Access (Filter.Strm).all)); end Total_In; --------------- -- Total_Out -- --------------- function Total_Out (Filter : in Filter_Type) return Count is begin return Count (Thin.Total_Out (To_Thin_Access (Filter.Strm).all)); end Total_Out; --------------- -- Translate -- --------------- procedure Translate (Filter : in out Filter_Type; In_Data : in Ada.Streams.Stream_Element_Array; In_Last : out Ada.Streams.Stream_Element_Offset; Out_Data : out Ada.Streams.Stream_Element_Array; Out_Last : out Ada.Streams.Stream_Element_Offset; Flush : in Flush_Mode) is begin if Filter.Header = GZip and then Filter.Compression then Translate_GZip (Filter => Filter, In_Data => In_Data, In_Last => In_Last, Out_Data => Out_Data, Out_Last => Out_Last, Flush => Flush); else Translate_Auto (Filter => Filter, In_Data => In_Data, In_Last => In_Last, Out_Data => Out_Data, Out_Last => Out_Last, Flush => Flush); end if; end Translate; -------------------- -- Translate_Auto -- -------------------- procedure Translate_Auto (Filter : in out Filter_Type; In_Data : in Ada.Streams.Stream_Element_Array; In_Last : out Ada.Streams.Stream_Element_Offset; Out_Data : out Ada.Streams.Stream_Element_Array; Out_Last : out Ada.Streams.Stream_Element_Offset; Flush : in Flush_Mode) is use type Thin.Int; Code : Thin.Int; begin if not Is_Open (Filter) then raise Status_Error; end if; if Out_Data'Length = 0 and then In_Data'Length = 0 then raise Constraint_Error; end if; Set_Out (Filter.Strm.all, Out_Data'Address, Out_Data'Length); Set_In (Filter.Strm.all, In_Data'Address, In_Data'Length); Code := Flate (Filter.Compression).Step (To_Thin_Access (Filter.Strm), Thin.Int (Flush)); if Code = Thin.Z_STREAM_END then Filter.Stream_End := True; else Check_Error (Filter.Strm.all, Code); end if; In_Last := In_Data'Last - Stream_Element_Offset (Avail_In (Filter.Strm.all)); Out_Last := Out_Data'Last - Stream_Element_Offset (Avail_Out (Filter.Strm.all)); end Translate_Auto; -------------------- -- Translate_GZip -- -------------------- procedure Translate_GZip (Filter : in out Filter_Type; In_Data : in Ada.Streams.Stream_Element_Array; In_Last : out Ada.Streams.Stream_Element_Offset; Out_Data : out Ada.Streams.Stream_Element_Array; Out_Last : out Ada.Streams.Stream_Element_Offset; Flush : in Flush_Mode) is Out_First : Stream_Element_Offset; procedure Add_Data (Data : in Stream_Element_Array); -- Add data to stream from the Filter.Offset till necessary, -- used for add gzip headr/footer. procedure Put_32 (Item : in out Stream_Element_Array; Data : in Unsigned_32); pragma Inline (Put_32); -------------- -- Add_Data -- -------------- procedure Add_Data (Data : in Stream_Element_Array) is Data_First : Stream_Element_Offset renames Filter.Offset; Data_Last : Stream_Element_Offset; Data_Len : Stream_Element_Offset; -- -1 Out_Len : Stream_Element_Offset; -- -1 begin Out_First := Out_Last + 1; if Data_First > Data'Last then return; end if; Data_Len := Data'Last - Data_First; Out_Len := Out_Data'Last - Out_First; if Data_Len <= Out_Len then Out_Last := Out_First + Data_Len; Data_Last := Data'Last; else Out_Last := Out_Data'Last; Data_Last := Data_First + Out_Len; end if; Out_Data (Out_First .. Out_Last) := Data (Data_First .. Data_Last); Data_First := Data_Last + 1; Out_First := Out_Last + 1; end Add_Data; ------------ -- Put_32 -- ------------ procedure Put_32 (Item : in out Stream_Element_Array; Data : in Unsigned_32) is D : Unsigned_32 := Data; begin for J in Item'First .. Item'First + 3 loop Item (J) := Stream_Element (D and 16#FF#); D := Shift_Right (D, 8); end loop; end Put_32; begin Out_Last := Out_Data'First - 1; if not Filter.Stream_End then Add_Data (Simple_GZip_Header); Translate_Auto (Filter => Filter, In_Data => In_Data, In_Last => In_Last, Out_Data => Out_Data (Out_First .. Out_Data'Last), Out_Last => Out_Last, Flush => Flush); CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last)); end if; if Filter.Stream_End and then Out_Last <= Out_Data'Last then -- This detection method would work only when -- Simple_GZip_Header'Last > Footer_Array'Last if Filter.Offset = Simple_GZip_Header'Last + 1 then Filter.Offset := Footer_Array'First; end if; declare Footer : Footer_Array; begin Put_32 (Footer, Filter.CRC); Put_32 (Footer (Footer'First + 4 .. Footer'Last), Unsigned_32 (Total_In (Filter))); Add_Data (Footer); end; end if; end Translate_GZip; ------------- -- Version -- ------------- function Version return String is begin return Interfaces.C.Strings.Value (Thin.zlibVersion); end Version; ----------- -- Write -- ----------- procedure Write (Filter : in out Filter_Type; Item : in Ada.Streams.Stream_Element_Array; Flush : in Flush_Mode := No_Flush) is Buffer : Stream_Element_Array (1 .. Buffer_Size); In_Last : Stream_Element_Offset; Out_Last : Stream_Element_Offset; In_First : Stream_Element_Offset := Item'First; begin if Item'Length = 0 and Flush = No_Flush then return; end if; loop Translate (Filter => Filter, In_Data => Item (In_First .. Item'Last), In_Last => In_Last, Out_Data => Buffer, Out_Last => Out_Last, Flush => Flush); if Out_Last >= Buffer'First then Write (Buffer (1 .. Out_Last)); end if; exit when In_Last = Item'Last or Stream_End (Filter); In_First := In_Last + 1; end loop; end Write; end ZLib; tcl8.6.5/compat/zlib/contrib/ada/zlib-thin.adb0000644000175000017500000000640112663660064020547 0ustar sergeisergei---------------------------------------------------------------- -- ZLib for Ada thick binding. -- -- -- -- Copyright (C) 2002-2003 Dmitriy Anisimkov -- -- -- -- Open source license information is in the zlib.ads file. -- ---------------------------------------------------------------- -- $Id: zlib-thin.adb,v 1.8 2003/12/14 18:27:31 vagul Exp $ package body ZLib.Thin is ZLIB_VERSION : constant Chars_Ptr := zlibVersion; Z_Stream_Size : constant Int := Z_Stream'Size / System.Storage_Unit; -------------- -- Avail_In -- -------------- function Avail_In (Strm : in Z_Stream) return UInt is begin return Strm.Avail_In; end Avail_In; --------------- -- Avail_Out -- --------------- function Avail_Out (Strm : in Z_Stream) return UInt is begin return Strm.Avail_Out; end Avail_Out; ------------------ -- Deflate_Init -- ------------------ function Deflate_Init (strm : Z_Streamp; level : Int; method : Int; windowBits : Int; memLevel : Int; strategy : Int) return Int is begin return deflateInit2 (strm, level, method, windowBits, memLevel, strategy, ZLIB_VERSION, Z_Stream_Size); end Deflate_Init; ------------------ -- Inflate_Init -- ------------------ function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int is begin return inflateInit2 (strm, windowBits, ZLIB_VERSION, Z_Stream_Size); end Inflate_Init; ------------------------ -- Last_Error_Message -- ------------------------ function Last_Error_Message (Strm : in Z_Stream) return String is use Interfaces.C.Strings; begin if Strm.msg = Null_Ptr then return ""; else return Value (Strm.msg); end if; end Last_Error_Message; ------------ -- Set_In -- ------------ procedure Set_In (Strm : in out Z_Stream; Buffer : in Voidp; Size : in UInt) is begin Strm.Next_In := Buffer; Strm.Avail_In := Size; end Set_In; ------------------ -- Set_Mem_Func -- ------------------ procedure Set_Mem_Func (Strm : in out Z_Stream; Opaque : in Voidp; Alloc : in alloc_func; Free : in free_func) is begin Strm.opaque := Opaque; Strm.zalloc := Alloc; Strm.zfree := Free; end Set_Mem_Func; ------------- -- Set_Out -- ------------- procedure Set_Out (Strm : in out Z_Stream; Buffer : in Voidp; Size : in UInt) is begin Strm.Next_Out := Buffer; Strm.Avail_Out := Size; end Set_Out; -------------- -- Total_In -- -------------- function Total_In (Strm : in Z_Stream) return ULong is begin return Strm.Total_In; end Total_In; --------------- -- Total_Out -- --------------- function Total_Out (Strm : in Z_Stream) return ULong is begin return Strm.Total_Out; end Total_Out; end ZLib.Thin; tcl8.6.5/compat/zlib/contrib/ada/zlib-streams.adb0000644000175000017500000001355412663660064021272 0ustar sergeisergei---------------------------------------------------------------- -- ZLib for Ada thick binding. -- -- -- -- Copyright (C) 2002-2003 Dmitriy Anisimkov -- -- -- -- Open source license information is in the zlib.ads file. -- ---------------------------------------------------------------- -- $Id: zlib-streams.adb,v 1.10 2004/05/31 10:53:40 vagul Exp $ with Ada.Unchecked_Deallocation; package body ZLib.Streams is ----------- -- Close -- ----------- procedure Close (Stream : in out Stream_Type) is procedure Free is new Ada.Unchecked_Deallocation (Stream_Element_Array, Buffer_Access); begin if Stream.Mode = Out_Stream or Stream.Mode = Duplex then -- We should flush the data written by the writer. Flush (Stream, Finish); Close (Stream.Writer); end if; if Stream.Mode = In_Stream or Stream.Mode = Duplex then Close (Stream.Reader); Free (Stream.Buffer); end if; end Close; ------------ -- Create -- ------------ procedure Create (Stream : out Stream_Type; Mode : in Stream_Mode; Back : in Stream_Access; Back_Compressed : in Boolean; Level : in Compression_Level := Default_Compression; Strategy : in Strategy_Type := Default_Strategy; Header : in Header_Type := Default; Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset := Default_Buffer_Size; Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset := Default_Buffer_Size) is subtype Buffer_Subtype is Stream_Element_Array (1 .. Read_Buffer_Size); procedure Init_Filter (Filter : in out Filter_Type; Compress : in Boolean); ----------------- -- Init_Filter -- ----------------- procedure Init_Filter (Filter : in out Filter_Type; Compress : in Boolean) is begin if Compress then Deflate_Init (Filter, Level, Strategy, Header => Header); else Inflate_Init (Filter, Header => Header); end if; end Init_Filter; begin Stream.Back := Back; Stream.Mode := Mode; if Mode = Out_Stream or Mode = Duplex then Init_Filter (Stream.Writer, Back_Compressed); Stream.Buffer_Size := Write_Buffer_Size; else Stream.Buffer_Size := 0; end if; if Mode = In_Stream or Mode = Duplex then Init_Filter (Stream.Reader, not Back_Compressed); Stream.Buffer := new Buffer_Subtype; Stream.Rest_First := Stream.Buffer'Last + 1; Stream.Rest_Last := Stream.Buffer'Last; end if; end Create; ----------- -- Flush -- ----------- procedure Flush (Stream : in out Stream_Type; Mode : in Flush_Mode := Sync_Flush) is Buffer : Stream_Element_Array (1 .. Stream.Buffer_Size); Last : Stream_Element_Offset; begin loop Flush (Stream.Writer, Buffer, Last, Mode); Ada.Streams.Write (Stream.Back.all, Buffer (1 .. Last)); exit when Last < Buffer'Last; end loop; end Flush; ------------- -- Is_Open -- ------------- function Is_Open (Stream : Stream_Type) return Boolean is begin return Is_Open (Stream.Reader) or else Is_Open (Stream.Writer); end Is_Open; ---------- -- Read -- ---------- procedure Read (Stream : in out Stream_Type; Item : out Stream_Element_Array; Last : out Stream_Element_Offset) is procedure Read (Item : out Stream_Element_Array; Last : out Stream_Element_Offset); ---------- -- Read -- ---------- procedure Read (Item : out Stream_Element_Array; Last : out Stream_Element_Offset) is begin Ada.Streams.Read (Stream.Back.all, Item, Last); end Read; procedure Read is new ZLib.Read (Read => Read, Buffer => Stream.Buffer.all, Rest_First => Stream.Rest_First, Rest_Last => Stream.Rest_Last); begin Read (Stream.Reader, Item, Last); end Read; ------------------- -- Read_Total_In -- ------------------- function Read_Total_In (Stream : in Stream_Type) return Count is begin return Total_In (Stream.Reader); end Read_Total_In; -------------------- -- Read_Total_Out -- -------------------- function Read_Total_Out (Stream : in Stream_Type) return Count is begin return Total_Out (Stream.Reader); end Read_Total_Out; ----------- -- Write -- ----------- procedure Write (Stream : in out Stream_Type; Item : in Stream_Element_Array) is procedure Write (Item : in Stream_Element_Array); ----------- -- Write -- ----------- procedure Write (Item : in Stream_Element_Array) is begin Ada.Streams.Write (Stream.Back.all, Item); end Write; procedure Write is new ZLib.Write (Write => Write, Buffer_Size => Stream.Buffer_Size); begin Write (Stream.Writer, Item, No_Flush); end Write; -------------------- -- Write_Total_In -- -------------------- function Write_Total_In (Stream : in Stream_Type) return Count is begin return Total_In (Stream.Writer); end Write_Total_In; --------------------- -- Write_Total_Out -- --------------------- function Write_Total_Out (Stream : in Stream_Type) return Count is begin return Total_Out (Stream.Writer); end Write_Total_Out; end ZLib.Streams; tcl8.6.5/compat/zlib/contrib/ada/readme.txt0000644000175000017500000000420212663653131020167 0ustar sergeisergei ZLib for Ada thick binding (ZLib.Ada) Release 1.3 ZLib.Ada is a thick binding interface to the popular ZLib data compression library, available at http://www.gzip.org/zlib/. It provides Ada-style access to the ZLib C library. Here are the main changes since ZLib.Ada 1.2: - Attension: ZLib.Read generic routine have a initialization requirement for Read_Last parameter now. It is a bit incompartible with previous version, but extends functionality, we could use new parameters Allow_Read_Some and Flush now. - Added Is_Open routines to ZLib and ZLib.Streams packages. - Add pragma Assert to check Stream_Element is 8 bit. - Fix extraction to buffer with exact known decompressed size. Error reported by Steve Sangwine. - Fix definition of ULong (changed to unsigned_long), fix regression on 64 bits computers. Patch provided by Pascal Obry. - Add Status_Error exception definition. - Add pragma Assertion that Ada.Streams.Stream_Element size is 8 bit. How to build ZLib.Ada under GNAT You should have the ZLib library already build on your computer, before building ZLib.Ada. Make the directory of ZLib.Ada sources current and issue the command: gnatmake test -largs -L -lz Or use the GNAT project file build for GNAT 3.15 or later: gnatmake -Pzlib.gpr -L How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2 1. Make a project with all *.ads and *.adb files from the distribution. 2. Build the libz.a library from the ZLib C sources. 3. Rename libz.a to z.lib. 4. Add the library z.lib to the project. 5. Add the libc.lib library from the ObjectAda distribution to the project. 6. Build the executable using test.adb as a main procedure. How to use ZLib.Ada The source files test.adb and read.adb are small demo programs that show the main functionality of ZLib.Ada. The routines from the package specifications are commented. Homepage: http://zlib-ada.sourceforge.net/ Author: Dmitriy Anisimkov Contributors: Pascal Obry , Steve Sangwine tcl8.6.5/compat/zlib/contrib/ada/buffer_demo.adb0000644000175000017500000000720512663660064021127 0ustar sergeisergei---------------------------------------------------------------- -- ZLib for Ada thick binding. -- -- -- -- Copyright (C) 2002-2004 Dmitriy Anisimkov -- -- -- -- Open source license information is in the zlib.ads file. -- ---------------------------------------------------------------- -- -- $Id: buffer_demo.adb,v 1.3 2004/09/06 06:55:35 vagul Exp $ -- This demo program provided by Dr Steve Sangwine -- -- Demonstration of a problem with Zlib-Ada (already fixed) when a buffer -- of exactly the correct size is used for decompressed data, and the last -- few bytes passed in to Zlib are checksum bytes. -- This program compresses a string of text, and then decompresses the -- compressed text into a buffer of the same size as the original text. with Ada.Streams; use Ada.Streams; with Ada.Text_IO; with ZLib; use ZLib; procedure Buffer_Demo is EOL : Character renames ASCII.LF; Text : constant String := "Four score and seven years ago our fathers brought forth," & EOL & "upon this continent, a new nation, conceived in liberty," & EOL & "and dedicated to the proposition that `all men are created equal'."; Source : Stream_Element_Array (1 .. Text'Length); for Source'Address use Text'Address; begin Ada.Text_IO.Put (Text); Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line ("Uncompressed size : " & Positive'Image (Text'Length) & " bytes"); declare Compressed_Data : Stream_Element_Array (1 .. Text'Length); L : Stream_Element_Offset; begin Compress : declare Compressor : Filter_Type; I : Stream_Element_Offset; begin Deflate_Init (Compressor); -- Compress the whole of T at once. Translate (Compressor, Source, I, Compressed_Data, L, Finish); pragma Assert (I = Source'Last); Close (Compressor); Ada.Text_IO.Put_Line ("Compressed size : " & Stream_Element_Offset'Image (L) & " bytes"); end Compress; -- Now we decompress the data, passing short blocks of data to Zlib -- (because this demonstrates the problem - the last block passed will -- contain checksum information and there will be no output, only a -- check inside Zlib that the checksum is correct). Decompress : declare Decompressor : Filter_Type; Uncompressed_Data : Stream_Element_Array (1 .. Text'Length); Block_Size : constant := 4; -- This makes sure that the last block contains -- only Adler checksum data. P : Stream_Element_Offset := Compressed_Data'First - 1; O : Stream_Element_Offset; begin Inflate_Init (Decompressor); loop Translate (Decompressor, Compressed_Data (P + 1 .. Stream_Element_Offset'Min (P + Block_Size, L)), P, Uncompressed_Data (Total_Out (Decompressor) + 1 .. Uncompressed_Data'Last), O, No_Flush); Ada.Text_IO.Put_Line ("Total in : " & Count'Image (Total_In (Decompressor)) & ", out : " & Count'Image (Total_Out (Decompressor))); exit when P = L; end loop; Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line ("Decompressed text matches original text : " & Boolean'Image (Uncompressed_Data = Source)); end Decompress; end; end Buffer_Demo; tcl8.6.5/compat/zlib/contrib/ada/read.adb0000644000175000017500000001023012663660064017555 0ustar sergeisergei---------------------------------------------------------------- -- ZLib for Ada thick binding. -- -- -- -- Copyright (C) 2002-2003 Dmitriy Anisimkov -- -- -- -- Open source license information is in the zlib.ads file. -- ---------------------------------------------------------------- -- $Id: read.adb,v 1.8 2004/05/31 10:53:40 vagul Exp $ -- Test/demo program for the generic read interface. with Ada.Numerics.Discrete_Random; with Ada.Streams; with Ada.Text_IO; with ZLib; procedure Read is use Ada.Streams; ------------------------------------ -- Test configuration parameters -- ------------------------------------ File_Size : Stream_Element_Offset := 100_000; Continuous : constant Boolean := False; -- If this constant is True, the test would be repeated again and again, -- with increment File_Size for every iteration. Header : constant ZLib.Header_Type := ZLib.Default; -- Do not use Header other than Default in ZLib versions 1.1.4 and older. Init_Random : constant := 8; -- We are using the same random sequence, in case of we catch bug, -- so we would be able to reproduce it. -- End -- Pack_Size : Stream_Element_Offset; Offset : Stream_Element_Offset; Filter : ZLib.Filter_Type; subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#; package Random_Elements is new Ada.Numerics.Discrete_Random (Visible_Symbols); Gen : Random_Elements.Generator; Period : constant Stream_Element_Offset := 200; -- Period constant variable for random generator not to be very random. -- Bigger period, harder random. Read_Buffer : Stream_Element_Array (1 .. 2048); Read_First : Stream_Element_Offset; Read_Last : Stream_Element_Offset; procedure Reset; procedure Read (Item : out Stream_Element_Array; Last : out Stream_Element_Offset); -- this procedure is for generic instantiation of -- ZLib.Read -- reading data from the File_In. procedure Read is new ZLib.Read (Read, Read_Buffer, Rest_First => Read_First, Rest_Last => Read_Last); ---------- -- Read -- ---------- procedure Read (Item : out Stream_Element_Array; Last : out Stream_Element_Offset) is begin Last := Stream_Element_Offset'Min (Item'Last, Item'First + File_Size - Offset); for J in Item'First .. Last loop if J < Item'First + Period then Item (J) := Random_Elements.Random (Gen); else Item (J) := Item (J - Period); end if; Offset := Offset + 1; end loop; end Read; ----------- -- Reset -- ----------- procedure Reset is begin Random_Elements.Reset (Gen, Init_Random); Pack_Size := 0; Offset := 1; Read_First := Read_Buffer'Last + 1; Read_Last := Read_Buffer'Last; end Reset; begin Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version); loop for Level in ZLib.Compression_Level'Range loop Ada.Text_IO.Put ("Level =" & ZLib.Compression_Level'Image (Level)); -- Deflate using generic instantiation. ZLib.Deflate_Init (Filter, Level, Header => Header); Reset; Ada.Text_IO.Put (Stream_Element_Offset'Image (File_Size) & " ->"); loop declare Buffer : Stream_Element_Array (1 .. 1024); Last : Stream_Element_Offset; begin Read (Filter, Buffer, Last); Pack_Size := Pack_Size + Last - Buffer'First + 1; exit when Last < Buffer'Last; end; end loop; Ada.Text_IO.Put_Line (Stream_Element_Offset'Image (Pack_Size)); ZLib.Close (Filter); end loop; exit when not Continuous; File_Size := File_Size + 1; end loop; end Read; tcl8.6.5/compat/zlib/contrib/ada/zlib.gpr0000644000175000017500000000077712663653131017660 0ustar sergeisergeiproject Zlib is for Languages use ("Ada"); for Source_Dirs use ("."); for Object_Dir use "."; for Main use ("test.adb", "mtest.adb", "read.adb", "buffer_demo"); package Compiler is for Default_Switches ("ada") use ("-gnatwcfilopru", "-gnatVcdfimorst", "-gnatyabcefhiklmnoprst"); end Compiler; package Linker is for Default_Switches ("ada") use ("-lz"); end Linker; package Builder is for Default_Switches ("ada") use ("-s", "-gnatQ"); end Builder; end Zlib; tcl8.6.5/compat/zlib/contrib/ada/mtest.adb0000644000175000017500000001056312663660064020007 0ustar sergeisergei---------------------------------------------------------------- -- ZLib for Ada thick binding. -- -- -- -- Copyright (C) 2002-2003 Dmitriy Anisimkov -- -- -- -- Open source license information is in the zlib.ads file. -- ---------------------------------------------------------------- -- Continuous test for ZLib multithreading. If the test would fail -- we should provide thread safe allocation routines for the Z_Stream. -- -- $Id: mtest.adb,v 1.4 2004/07/23 07:49:54 vagul Exp $ with ZLib; with Ada.Streams; with Ada.Numerics.Discrete_Random; with Ada.Text_IO; with Ada.Exceptions; with Ada.Task_Identification; procedure MTest is use Ada.Streams; use ZLib; Stop : Boolean := False; pragma Atomic (Stop); subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#; package Random_Elements is new Ada.Numerics.Discrete_Random (Visible_Symbols); task type Test_Task; task body Test_Task is Buffer : Stream_Element_Array (1 .. 100_000); Gen : Random_Elements.Generator; Buffer_First : Stream_Element_Offset; Compare_First : Stream_Element_Offset; Deflate : Filter_Type; Inflate : Filter_Type; procedure Further (Item : in Stream_Element_Array); procedure Read_Buffer (Item : out Ada.Streams.Stream_Element_Array; Last : out Ada.Streams.Stream_Element_Offset); ------------- -- Further -- ------------- procedure Further (Item : in Stream_Element_Array) is procedure Compare (Item : in Stream_Element_Array); ------------- -- Compare -- ------------- procedure Compare (Item : in Stream_Element_Array) is Next_First : Stream_Element_Offset := Compare_First + Item'Length; begin if Buffer (Compare_First .. Next_First - 1) /= Item then raise Program_Error; end if; Compare_First := Next_First; end Compare; procedure Compare_Write is new ZLib.Write (Write => Compare); begin Compare_Write (Inflate, Item, No_Flush); end Further; ----------------- -- Read_Buffer -- ----------------- procedure Read_Buffer (Item : out Ada.Streams.Stream_Element_Array; Last : out Ada.Streams.Stream_Element_Offset) is Buff_Diff : Stream_Element_Offset := Buffer'Last - Buffer_First; Next_First : Stream_Element_Offset; begin if Item'Length <= Buff_Diff then Last := Item'Last; Next_First := Buffer_First + Item'Length; Item := Buffer (Buffer_First .. Next_First - 1); Buffer_First := Next_First; else Last := Item'First + Buff_Diff; Item (Item'First .. Last) := Buffer (Buffer_First .. Buffer'Last); Buffer_First := Buffer'Last + 1; end if; end Read_Buffer; procedure Translate is new Generic_Translate (Data_In => Read_Buffer, Data_Out => Further); begin Random_Elements.Reset (Gen); Buffer := (others => 20); Main : loop for J in Buffer'Range loop Buffer (J) := Random_Elements.Random (Gen); Deflate_Init (Deflate); Inflate_Init (Inflate); Buffer_First := Buffer'First; Compare_First := Buffer'First; Translate (Deflate); if Compare_First /= Buffer'Last + 1 then raise Program_Error; end if; Ada.Text_IO.Put_Line (Ada.Task_Identification.Image (Ada.Task_Identification.Current_Task) & Stream_Element_Offset'Image (J) & ZLib.Count'Image (Total_Out (Deflate))); Close (Deflate); Close (Inflate); exit Main when Stop; end loop; end loop Main; exception when E : others => Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (E)); Stop := True; end Test_Task; Test : array (1 .. 4) of Test_Task; pragma Unreferenced (Test); Dummy : Character; begin Ada.Text_IO.Get_Immediate (Dummy); Stop := True; end MTest; tcl8.6.5/compat/zlib/contrib/ada/test.adb0000644000175000017500000003157412663660064017637 0ustar sergeisergei---------------------------------------------------------------- -- ZLib for Ada thick binding. -- -- -- -- Copyright (C) 2002-2003 Dmitriy Anisimkov -- -- -- -- Open source license information is in the zlib.ads file. -- ---------------------------------------------------------------- -- $Id: test.adb,v 1.17 2003/08/12 12:13:30 vagul Exp $ -- The program has a few aims. -- 1. Test ZLib.Ada95 thick binding functionality. -- 2. Show the example of use main functionality of the ZLib.Ada95 binding. -- 3. Build this program automatically compile all ZLib.Ada95 packages under -- GNAT Ada95 compiler. with ZLib.Streams; with Ada.Streams.Stream_IO; with Ada.Numerics.Discrete_Random; with Ada.Text_IO; with Ada.Calendar; procedure Test is use Ada.Streams; use Stream_IO; ------------------------------------ -- Test configuration parameters -- ------------------------------------ File_Size : Count := 100_000; Continuous : constant Boolean := False; Header : constant ZLib.Header_Type := ZLib.Default; -- ZLib.None; -- ZLib.Auto; -- ZLib.GZip; -- Do not use Header other then Default in ZLib versions 1.1.4 -- and older. Strategy : constant ZLib.Strategy_Type := ZLib.Default_Strategy; Init_Random : constant := 10; -- End -- In_File_Name : constant String := "testzlib.in"; -- Name of the input file Z_File_Name : constant String := "testzlib.zlb"; -- Name of the compressed file. Out_File_Name : constant String := "testzlib.out"; -- Name of the decompressed file. File_In : File_Type; File_Out : File_Type; File_Back : File_Type; File_Z : ZLib.Streams.Stream_Type; Filter : ZLib.Filter_Type; Time_Stamp : Ada.Calendar.Time; procedure Generate_File; -- Generate file of spetsified size with some random data. -- The random data is repeatable, for the good compression. procedure Compare_Streams (Left, Right : in out Root_Stream_Type'Class); -- The procedure compearing data in 2 streams. -- It is for compare data before and after compression/decompression. procedure Compare_Files (Left, Right : String); -- Compare files. Based on the Compare_Streams. procedure Copy_Streams (Source, Target : in out Root_Stream_Type'Class; Buffer_Size : in Stream_Element_Offset := 1024); -- Copying data from one stream to another. It is for test stream -- interface of the library. procedure Data_In (Item : out Stream_Element_Array; Last : out Stream_Element_Offset); -- this procedure is for generic instantiation of -- ZLib.Generic_Translate. -- reading data from the File_In. procedure Data_Out (Item : in Stream_Element_Array); -- this procedure is for generic instantiation of -- ZLib.Generic_Translate. -- writing data to the File_Out. procedure Stamp; -- Store the timestamp to the local variable. procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count); -- Print the time statistic with the message. procedure Translate is new ZLib.Generic_Translate (Data_In => Data_In, Data_Out => Data_Out); -- This procedure is moving data from File_In to File_Out -- with compression or decompression, depend on initialization of -- Filter parameter. ------------------- -- Compare_Files -- ------------------- procedure Compare_Files (Left, Right : String) is Left_File, Right_File : File_Type; begin Open (Left_File, In_File, Left); Open (Right_File, In_File, Right); Compare_Streams (Stream (Left_File).all, Stream (Right_File).all); Close (Left_File); Close (Right_File); end Compare_Files; --------------------- -- Compare_Streams -- --------------------- procedure Compare_Streams (Left, Right : in out Ada.Streams.Root_Stream_Type'Class) is Left_Buffer, Right_Buffer : Stream_Element_Array (0 .. 16#FFF#); Left_Last, Right_Last : Stream_Element_Offset; begin loop Read (Left, Left_Buffer, Left_Last); Read (Right, Right_Buffer, Right_Last); if Left_Last /= Right_Last then Ada.Text_IO.Put_Line ("Compare error :" & Stream_Element_Offset'Image (Left_Last) & " /= " & Stream_Element_Offset'Image (Right_Last)); raise Constraint_Error; elsif Left_Buffer (0 .. Left_Last) /= Right_Buffer (0 .. Right_Last) then Ada.Text_IO.Put_Line ("ERROR: IN and OUT files is not equal."); raise Constraint_Error; end if; exit when Left_Last < Left_Buffer'Last; end loop; end Compare_Streams; ------------------ -- Copy_Streams -- ------------------ procedure Copy_Streams (Source, Target : in out Ada.Streams.Root_Stream_Type'Class; Buffer_Size : in Stream_Element_Offset := 1024) is Buffer : Stream_Element_Array (1 .. Buffer_Size); Last : Stream_Element_Offset; begin loop Read (Source, Buffer, Last); Write (Target, Buffer (1 .. Last)); exit when Last < Buffer'Last; end loop; end Copy_Streams; ------------- -- Data_In -- ------------- procedure Data_In (Item : out Stream_Element_Array; Last : out Stream_Element_Offset) is begin Read (File_In, Item, Last); end Data_In; -------------- -- Data_Out -- -------------- procedure Data_Out (Item : in Stream_Element_Array) is begin Write (File_Out, Item); end Data_Out; ------------------- -- Generate_File -- ------------------- procedure Generate_File is subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#; package Random_Elements is new Ada.Numerics.Discrete_Random (Visible_Symbols); Gen : Random_Elements.Generator; Buffer : Stream_Element_Array := (1 .. 77 => 16#20#) & 10; Buffer_Count : constant Count := File_Size / Buffer'Length; -- Number of same buffers in the packet. Density : constant Count := 30; -- from 0 to Buffer'Length - 2; procedure Fill_Buffer (J, D : in Count); -- Change the part of the buffer. ----------------- -- Fill_Buffer -- ----------------- procedure Fill_Buffer (J, D : in Count) is begin for K in 0 .. D loop Buffer (Stream_Element_Offset ((J + K) mod (Buffer'Length - 1) + 1)) := Random_Elements.Random (Gen); end loop; end Fill_Buffer; begin Random_Elements.Reset (Gen, Init_Random); Create (File_In, Out_File, In_File_Name); Fill_Buffer (1, Buffer'Length - 2); for J in 1 .. Buffer_Count loop Write (File_In, Buffer); Fill_Buffer (J, Density); end loop; -- fill remain size. Write (File_In, Buffer (1 .. Stream_Element_Offset (File_Size - Buffer'Length * Buffer_Count))); Flush (File_In); Close (File_In); end Generate_File; --------------------- -- Print_Statistic -- --------------------- procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count) is use Ada.Calendar; use Ada.Text_IO; package Count_IO is new Integer_IO (ZLib.Count); Curr_Dur : Duration := Clock - Time_Stamp; begin Put (Msg); Set_Col (20); Ada.Text_IO.Put ("size ="); Count_IO.Put (Data_Size, Width => Stream_IO.Count'Image (File_Size)'Length); Put_Line (" duration =" & Duration'Image (Curr_Dur)); end Print_Statistic; ----------- -- Stamp -- ----------- procedure Stamp is begin Time_Stamp := Ada.Calendar.Clock; end Stamp; begin Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version); loop Generate_File; for Level in ZLib.Compression_Level'Range loop Ada.Text_IO.Put_Line ("Level =" & ZLib.Compression_Level'Image (Level)); -- Test generic interface. Open (File_In, In_File, In_File_Name); Create (File_Out, Out_File, Z_File_Name); Stamp; -- Deflate using generic instantiation. ZLib.Deflate_Init (Filter => Filter, Level => Level, Strategy => Strategy, Header => Header); Translate (Filter); Print_Statistic ("Generic compress", ZLib.Total_Out (Filter)); ZLib.Close (Filter); Close (File_In); Close (File_Out); Open (File_In, In_File, Z_File_Name); Create (File_Out, Out_File, Out_File_Name); Stamp; -- Inflate using generic instantiation. ZLib.Inflate_Init (Filter, Header => Header); Translate (Filter); Print_Statistic ("Generic decompress", ZLib.Total_Out (Filter)); ZLib.Close (Filter); Close (File_In); Close (File_Out); Compare_Files (In_File_Name, Out_File_Name); -- Test stream interface. -- Compress to the back stream. Open (File_In, In_File, In_File_Name); Create (File_Back, Out_File, Z_File_Name); Stamp; ZLib.Streams.Create (Stream => File_Z, Mode => ZLib.Streams.Out_Stream, Back => ZLib.Streams.Stream_Access (Stream (File_Back)), Back_Compressed => True, Level => Level, Strategy => Strategy, Header => Header); Copy_Streams (Source => Stream (File_In).all, Target => File_Z); -- Flushing internal buffers to the back stream. ZLib.Streams.Flush (File_Z, ZLib.Finish); Print_Statistic ("Write compress", ZLib.Streams.Write_Total_Out (File_Z)); ZLib.Streams.Close (File_Z); Close (File_In); Close (File_Back); -- Compare reading from original file and from -- decompression stream. Open (File_In, In_File, In_File_Name); Open (File_Back, In_File, Z_File_Name); ZLib.Streams.Create (Stream => File_Z, Mode => ZLib.Streams.In_Stream, Back => ZLib.Streams.Stream_Access (Stream (File_Back)), Back_Compressed => True, Header => Header); Stamp; Compare_Streams (Stream (File_In).all, File_Z); Print_Statistic ("Read decompress", ZLib.Streams.Read_Total_Out (File_Z)); ZLib.Streams.Close (File_Z); Close (File_In); Close (File_Back); -- Compress by reading from compression stream. Open (File_Back, In_File, In_File_Name); Create (File_Out, Out_File, Z_File_Name); ZLib.Streams.Create (Stream => File_Z, Mode => ZLib.Streams.In_Stream, Back => ZLib.Streams.Stream_Access (Stream (File_Back)), Back_Compressed => False, Level => Level, Strategy => Strategy, Header => Header); Stamp; Copy_Streams (Source => File_Z, Target => Stream (File_Out).all); Print_Statistic ("Read compress", ZLib.Streams.Read_Total_Out (File_Z)); ZLib.Streams.Close (File_Z); Close (File_Out); Close (File_Back); -- Decompress to decompression stream. Open (File_In, In_File, Z_File_Name); Create (File_Back, Out_File, Out_File_Name); ZLib.Streams.Create (Stream => File_Z, Mode => ZLib.Streams.Out_Stream, Back => ZLib.Streams.Stream_Access (Stream (File_Back)), Back_Compressed => False, Header => Header); Stamp; Copy_Streams (Source => Stream (File_In).all, Target => File_Z); Print_Statistic ("Write decompress", ZLib.Streams.Write_Total_Out (File_Z)); ZLib.Streams.Close (File_Z); Close (File_In); Close (File_Back); Compare_Files (In_File_Name, Out_File_Name); end loop; Ada.Text_IO.Put_Line (Count'Image (File_Size) & " Ok."); exit when not Continuous; File_Size := File_Size + 1; end loop; end Test; tcl8.6.5/compat/zlib/contrib/ada/zlib-streams.ads0000644000175000017500000001035212663660064021304 0ustar sergeisergei---------------------------------------------------------------- -- ZLib for Ada thick binding. -- -- -- -- Copyright (C) 2002-2003 Dmitriy Anisimkov -- -- -- -- Open source license information is in the zlib.ads file. -- ---------------------------------------------------------------- -- $Id: zlib-streams.ads,v 1.12 2004/05/31 10:53:40 vagul Exp $ package ZLib.Streams is type Stream_Mode is (In_Stream, Out_Stream, Duplex); type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class; type Stream_Type is new Ada.Streams.Root_Stream_Type with private; procedure Read (Stream : in out Stream_Type; Item : out Ada.Streams.Stream_Element_Array; Last : out Ada.Streams.Stream_Element_Offset); procedure Write (Stream : in out Stream_Type; Item : in Ada.Streams.Stream_Element_Array); procedure Flush (Stream : in out Stream_Type; Mode : in Flush_Mode := Sync_Flush); -- Flush the written data to the back stream, -- all data placed to the compressor is flushing to the Back stream. -- Should not be used untill necessary, becouse it is decreasing -- compression. function Read_Total_In (Stream : in Stream_Type) return Count; pragma Inline (Read_Total_In); -- Return total number of bytes read from back stream so far. function Read_Total_Out (Stream : in Stream_Type) return Count; pragma Inline (Read_Total_Out); -- Return total number of bytes read so far. function Write_Total_In (Stream : in Stream_Type) return Count; pragma Inline (Write_Total_In); -- Return total number of bytes written so far. function Write_Total_Out (Stream : in Stream_Type) return Count; pragma Inline (Write_Total_Out); -- Return total number of bytes written to the back stream. procedure Create (Stream : out Stream_Type; Mode : in Stream_Mode; Back : in Stream_Access; Back_Compressed : in Boolean; Level : in Compression_Level := Default_Compression; Strategy : in Strategy_Type := Default_Strategy; Header : in Header_Type := Default; Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset := Default_Buffer_Size; Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset := Default_Buffer_Size); -- Create the Comression/Decompression stream. -- If mode is In_Stream then Write operation is disabled. -- If mode is Out_Stream then Read operation is disabled. -- If Back_Compressed is true then -- Data written to the Stream is compressing to the Back stream -- and data read from the Stream is decompressed data from the Back stream. -- If Back_Compressed is false then -- Data written to the Stream is decompressing to the Back stream -- and data read from the Stream is compressed data from the Back stream. -- !!! When the Need_Header is False ZLib-Ada is using undocumented -- ZLib 1.1.4 functionality to do not create/wait for ZLib headers. function Is_Open (Stream : Stream_Type) return Boolean; procedure Close (Stream : in out Stream_Type); private use Ada.Streams; type Buffer_Access is access all Stream_Element_Array; type Stream_Type is new Root_Stream_Type with record Mode : Stream_Mode; Buffer : Buffer_Access; Rest_First : Stream_Element_Offset; Rest_Last : Stream_Element_Offset; -- Buffer for Read operation. -- We need to have this buffer in the record -- becouse not all read data from back stream -- could be processed during the read operation. Buffer_Size : Stream_Element_Offset; -- Buffer size for write operation. -- We do not need to have this buffer -- in the record becouse all data could be -- processed in the write operation. Back : Stream_Access; Reader : Filter_Type; Writer : Filter_Type; end record; end ZLib.Streams; tcl8.6.5/compat/zlib/contrib/puff/0000755000175000017500000000000012665173607016415 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/puff/puff.c0000644000175000017500000011177612663660064017532 0ustar sergeisergei/* * puff.c * Copyright (C) 2002-2013 Mark Adler * For conditions of distribution and use, see copyright notice in puff.h * version 2.3, 21 Jan 2013 * * puff.c is a simple inflate written to be an unambiguous way to specify the * deflate format. It is not written for speed but rather simplicity. As a * side benefit, this code might actually be useful when small code is more * important than speed, such as bootstrap applications. For typical deflate * data, zlib's inflate() is about four times as fast as puff(). zlib's * inflate compiles to around 20K on my machine, whereas puff.c compiles to * around 4K on my machine (a PowerPC using GNU cc). If the faster decode() * function here is used, then puff() is only twice as slow as zlib's * inflate(). * * All dynamically allocated memory comes from the stack. The stack required * is less than 2K bytes. This code is compatible with 16-bit int's and * assumes that long's are at least 32 bits. puff.c uses the short data type, * assumed to be 16 bits, for arrays in order to to conserve memory. The code * works whether integers are stored big endian or little endian. * * In the comments below are "Format notes" that describe the inflate process * and document some of the less obvious aspects of the format. This source * code is meant to supplement RFC 1951, which formally describes the deflate * format: * * http://www.zlib.org/rfc-deflate.html */ /* * Change history: * * 1.0 10 Feb 2002 - First version * 1.1 17 Feb 2002 - Clarifications of some comments and notes * - Update puff() dest and source pointers on negative * errors to facilitate debugging deflators * - Remove longest from struct huffman -- not needed * - Simplify offs[] index in construct() * - Add input size and checking, using longjmp() to * maintain easy readability * - Use short data type for large arrays * - Use pointers instead of long to specify source and * destination sizes to avoid arbitrary 4 GB limits * 1.2 17 Mar 2002 - Add faster version of decode(), doubles speed (!), * but leave simple version for readabilty * - Make sure invalid distances detected if pointers * are 16 bits * - Fix fixed codes table error * - Provide a scanning mode for determining size of * uncompressed data * 1.3 20 Mar 2002 - Go back to lengths for puff() parameters [Gailly] * - Add a puff.h file for the interface * - Add braces in puff() for else do [Gailly] * - Use indexes instead of pointers for readability * 1.4 31 Mar 2002 - Simplify construct() code set check * - Fix some comments * - Add FIXLCODES #define * 1.5 6 Apr 2002 - Minor comment fixes * 1.6 7 Aug 2002 - Minor format changes * 1.7 3 Mar 2003 - Added test code for distribution * - Added zlib-like license * 1.8 9 Jan 2004 - Added some comments on no distance codes case * 1.9 21 Feb 2008 - Fix bug on 16-bit integer architectures [Pohland] * - Catch missing end-of-block symbol error * 2.0 25 Jul 2008 - Add #define to permit distance too far back * - Add option in TEST code for puff to write the data * - Add option in TEST code to skip input bytes * - Allow TEST code to read from piped stdin * 2.1 4 Apr 2010 - Avoid variable initialization for happier compilers * - Avoid unsigned comparisons for even happier compilers * 2.2 25 Apr 2010 - Fix bug in variable initializations [Oberhumer] * - Add const where appropriate [Oberhumer] * - Split if's and ?'s for coverage testing * - Break out test code to separate file * - Move NIL to puff.h * - Allow incomplete code only if single code length is 1 * - Add full code coverage test to Makefile * 2.3 21 Jan 2013 - Check for invalid code length codes in dynamic blocks */ #include /* for setjmp(), longjmp(), and jmp_buf */ #include "puff.h" /* prototype for puff() */ #define local static /* for local function definitions */ /* * Maximums for allocations and loops. It is not useful to change these -- * they are fixed by the deflate format. */ #define MAXBITS 15 /* maximum bits in a code */ #define MAXLCODES 286 /* maximum number of literal/length codes */ #define MAXDCODES 30 /* maximum number of distance codes */ #define MAXCODES (MAXLCODES+MAXDCODES) /* maximum codes lengths to read */ #define FIXLCODES 288 /* number of fixed literal/length codes */ /* input and output state */ struct state { /* output state */ unsigned char *out; /* output buffer */ unsigned long outlen; /* available space at out */ unsigned long outcnt; /* bytes written to out so far */ /* input state */ const unsigned char *in; /* input buffer */ unsigned long inlen; /* available input at in */ unsigned long incnt; /* bytes read so far */ int bitbuf; /* bit buffer */ int bitcnt; /* number of bits in bit buffer */ /* input limit error return state for bits() and decode() */ jmp_buf env; }; /* * Return need bits from the input stream. This always leaves less than * eight bits in the buffer. bits() works properly for need == 0. * * Format notes: * * - Bits are stored in bytes from the least significant bit to the most * significant bit. Therefore bits are dropped from the bottom of the bit * buffer, using shift right, and new bytes are appended to the top of the * bit buffer, using shift left. */ local int bits(struct state *s, int need) { long val; /* bit accumulator (can use up to 20 bits) */ /* load at least need bits into val */ val = s->bitbuf; while (s->bitcnt < need) { if (s->incnt == s->inlen) longjmp(s->env, 1); /* out of input */ val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */ s->bitcnt += 8; } /* drop need bits and update buffer, always zero to seven bits left */ s->bitbuf = (int)(val >> need); s->bitcnt -= need; /* return need bits, zeroing the bits above that */ return (int)(val & ((1L << need) - 1)); } /* * Process a stored block. * * Format notes: * * - After the two-bit stored block type (00), the stored block length and * stored bytes are byte-aligned for fast copying. Therefore any leftover * bits in the byte that has the last bit of the type, as many as seven, are * discarded. The value of the discarded bits are not defined and should not * be checked against any expectation. * * - The second inverted copy of the stored block length does not have to be * checked, but it's probably a good idea to do so anyway. * * - A stored block can have zero length. This is sometimes used to byte-align * subsets of the compressed data for random access or partial recovery. */ local int stored(struct state *s) { unsigned len; /* length of stored block */ /* discard leftover bits from current byte (assumes s->bitcnt < 8) */ s->bitbuf = 0; s->bitcnt = 0; /* get length and check against its one's complement */ if (s->incnt + 4 > s->inlen) return 2; /* not enough input */ len = s->in[s->incnt++]; len |= s->in[s->incnt++] << 8; if (s->in[s->incnt++] != (~len & 0xff) || s->in[s->incnt++] != ((~len >> 8) & 0xff)) return -2; /* didn't match complement! */ /* copy len bytes from in to out */ if (s->incnt + len > s->inlen) return 2; /* not enough input */ if (s->out != NIL) { if (s->outcnt + len > s->outlen) return 1; /* not enough output space */ while (len--) s->out[s->outcnt++] = s->in[s->incnt++]; } else { /* just scanning */ s->outcnt += len; s->incnt += len; } /* done with a valid stored block */ return 0; } /* * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of * each length, which for a canonical code are stepped through in order. * symbol[] are the symbol values in canonical order, where the number of * entries is the sum of the counts in count[]. The decoding process can be * seen in the function decode() below. */ struct huffman { short *count; /* number of symbols of each length */ short *symbol; /* canonically ordered symbols */ }; /* * Decode a code from the stream s using huffman table h. Return the symbol or * a negative value if there is an error. If all of the lengths are zero, i.e. * an empty code, or if the code is incomplete and an invalid code is received, * then -10 is returned after reading MAXBITS bits. * * Format notes: * * - The codes as stored in the compressed data are bit-reversed relative to * a simple integer ordering of codes of the same lengths. Hence below the * bits are pulled from the compressed data one at a time and used to * build the code value reversed from what is in the stream in order to * permit simple integer comparisons for decoding. A table-based decoding * scheme (as used in zlib) does not need to do this reversal. * * - The first code for the shortest length is all zeros. Subsequent codes of * the same length are simply integer increments of the previous code. When * moving up a length, a zero bit is appended to the code. For a complete * code, the last code of the longest length will be all ones. * * - Incomplete codes are handled by this decoder, since they are permitted * in the deflate format. See the format notes for fixed() and dynamic(). */ #ifdef SLOW local int decode(struct state *s, const struct huffman *h) { int len; /* current number of bits in code */ int code; /* len bits being decoded */ int first; /* first code of length len */ int count; /* number of codes of length len */ int index; /* index of first code of length len in symbol table */ code = first = index = 0; for (len = 1; len <= MAXBITS; len++) { code |= bits(s, 1); /* get next bit */ count = h->count[len]; if (code - count < first) /* if length len, return symbol */ return h->symbol[index + (code - first)]; index += count; /* else update for next length */ first += count; first <<= 1; code <<= 1; } return -10; /* ran out of codes */ } /* * A faster version of decode() for real applications of this code. It's not * as readable, but it makes puff() twice as fast. And it only makes the code * a few percent larger. */ #else /* !SLOW */ local int decode(struct state *s, const struct huffman *h) { int len; /* current number of bits in code */ int code; /* len bits being decoded */ int first; /* first code of length len */ int count; /* number of codes of length len */ int index; /* index of first code of length len in symbol table */ int bitbuf; /* bits from stream */ int left; /* bits left in next or left to process */ short *next; /* next number of codes */ bitbuf = s->bitbuf; left = s->bitcnt; code = first = index = 0; len = 1; next = h->count + 1; while (1) { while (left--) { code |= bitbuf & 1; bitbuf >>= 1; count = *next++; if (code - count < first) { /* if length len, return symbol */ s->bitbuf = bitbuf; s->bitcnt = (s->bitcnt - len) & 7; return h->symbol[index + (code - first)]; } index += count; /* else update for next length */ first += count; first <<= 1; code <<= 1; len++; } left = (MAXBITS+1) - len; if (left == 0) break; if (s->incnt == s->inlen) longjmp(s->env, 1); /* out of input */ bitbuf = s->in[s->incnt++]; if (left > 8) left = 8; } return -10; /* ran out of codes */ } #endif /* SLOW */ /* * Given the list of code lengths length[0..n-1] representing a canonical * Huffman code for n symbols, construct the tables required to decode those * codes. Those tables are the number of codes of each length, and the symbols * sorted by length, retaining their original order within each length. The * return value is zero for a complete code set, negative for an over- * subscribed code set, and positive for an incomplete code set. The tables * can be used if the return value is zero or positive, but they cannot be used * if the return value is negative. If the return value is zero, it is not * possible for decode() using that table to return an error--any stream of * enough bits will resolve to a symbol. If the return value is positive, then * it is possible for decode() using that table to return an error for received * codes past the end of the incomplete lengths. * * Not used by decode(), but used for error checking, h->count[0] is the number * of the n symbols not in the code. So n - h->count[0] is the number of * codes. This is useful for checking for incomplete codes that have more than * one symbol, which is an error in a dynamic block. * * Assumption: for all i in 0..n-1, 0 <= length[i] <= MAXBITS * This is assured by the construction of the length arrays in dynamic() and * fixed() and is not verified by construct(). * * Format notes: * * - Permitted and expected examples of incomplete codes are one of the fixed * codes and any code with a single symbol which in deflate is coded as one * bit instead of zero bits. See the format notes for fixed() and dynamic(). * * - Within a given code length, the symbols are kept in ascending order for * the code bits definition. */ local int construct(struct huffman *h, const short *length, int n) { int symbol; /* current symbol when stepping through length[] */ int len; /* current length when stepping through h->count[] */ int left; /* number of possible codes left of current length */ short offs[MAXBITS+1]; /* offsets in symbol table for each length */ /* count number of codes of each length */ for (len = 0; len <= MAXBITS; len++) h->count[len] = 0; for (symbol = 0; symbol < n; symbol++) (h->count[length[symbol]])++; /* assumes lengths are within bounds */ if (h->count[0] == n) /* no codes! */ return 0; /* complete, but decode() will fail */ /* check for an over-subscribed or incomplete set of lengths */ left = 1; /* one possible code of zero length */ for (len = 1; len <= MAXBITS; len++) { left <<= 1; /* one more bit, double codes left */ left -= h->count[len]; /* deduct count from possible codes */ if (left < 0) return left; /* over-subscribed--return negative */ } /* left > 0 means incomplete */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h->count[len]; /* * put symbols in table sorted by length, by symbol order within each * length */ for (symbol = 0; symbol < n; symbol++) if (length[symbol] != 0) h->symbol[offs[length[symbol]]++] = symbol; /* return zero for complete set, positive for incomplete set */ return left; } /* * Decode literal/length and distance codes until an end-of-block code. * * Format notes: * * - Compressed data that is after the block type if fixed or after the code * description if dynamic is a combination of literals and length/distance * pairs terminated by and end-of-block code. Literals are simply Huffman * coded bytes. A length/distance pair is a coded length followed by a * coded distance to represent a string that occurs earlier in the * uncompressed data that occurs again at the current location. * * - Literals, lengths, and the end-of-block code are combined into a single * code of up to 286 symbols. They are 256 literals (0..255), 29 length * symbols (257..285), and the end-of-block symbol (256). * * - There are 256 possible lengths (3..258), and so 29 symbols are not enough * to represent all of those. Lengths 3..10 and 258 are in fact represented * by just a length symbol. Lengths 11..257 are represented as a symbol and * some number of extra bits that are added as an integer to the base length * of the length symbol. The number of extra bits is determined by the base * length symbol. These are in the static arrays below, lens[] for the base * lengths and lext[] for the corresponding number of extra bits. * * - The reason that 258 gets its own symbol is that the longest length is used * often in highly redundant files. Note that 258 can also be coded as the * base value 227 plus the maximum extra value of 31. While a good deflate * should never do this, it is not an error, and should be decoded properly. * * - If a length is decoded, including its extra bits if any, then it is * followed a distance code. There are up to 30 distance symbols. Again * there are many more possible distances (1..32768), so extra bits are added * to a base value represented by the symbol. The distances 1..4 get their * own symbol, but the rest require extra bits. The base distances and * corresponding number of extra bits are below in the static arrays dist[] * and dext[]. * * - Literal bytes are simply written to the output. A length/distance pair is * an instruction to copy previously uncompressed bytes to the output. The * copy is from distance bytes back in the output stream, copying for length * bytes. * * - Distances pointing before the beginning of the output data are not * permitted. * * - Overlapped copies, where the length is greater than the distance, are * allowed and common. For example, a distance of one and a length of 258 * simply copies the last byte 258 times. A distance of four and a length of * twelve copies the last four bytes three times. A simple forward copy * ignoring whether the length is greater than the distance or not implements * this correctly. You should not use memcpy() since its behavior is not * defined for overlapped arrays. You should not use memmove() or bcopy() * since though their behavior -is- defined for overlapping arrays, it is * defined to do the wrong thing in this case. */ local int codes(struct state *s, const struct huffman *lencode, const struct huffman *distcode) { int symbol; /* decoded symbol */ int len; /* length for copy */ unsigned dist; /* distance for copy */ static const short lens[29] = { /* Size base for length codes 257..285 */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; static const short lext[29] = { /* Extra bits for length codes 257..285 */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; static const short dists[30] = { /* Offset base for distance codes 0..29 */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; static const short dext[30] = { /* Extra bits for distance codes 0..29 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; /* decode literals and length/distance pairs */ do { symbol = decode(s, lencode); if (symbol < 0) return symbol; /* invalid symbol */ if (symbol < 256) { /* literal: symbol is the byte */ /* write out the literal */ if (s->out != NIL) { if (s->outcnt == s->outlen) return 1; s->out[s->outcnt] = symbol; } s->outcnt++; } else if (symbol > 256) { /* length */ /* get and compute length */ symbol -= 257; if (symbol >= 29) return -10; /* invalid fixed code */ len = lens[symbol] + bits(s, lext[symbol]); /* get and check distance */ symbol = decode(s, distcode); if (symbol < 0) return symbol; /* invalid symbol */ dist = dists[symbol] + bits(s, dext[symbol]); #ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (dist > s->outcnt) return -11; /* distance too far back */ #endif /* copy length bytes from distance bytes back */ if (s->out != NIL) { if (s->outcnt + len > s->outlen) return 1; while (len--) { s->out[s->outcnt] = #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR dist > s->outcnt ? 0 : #endif s->out[s->outcnt - dist]; s->outcnt++; } } else s->outcnt += len; } } while (symbol != 256); /* end of block symbol */ /* done with a valid fixed or dynamic block */ return 0; } /* * Process a fixed codes block. * * Format notes: * * - This block type can be useful for compressing small amounts of data for * which the size of the code descriptions in a dynamic block exceeds the * benefit of custom codes for that block. For fixed codes, no bits are * spent on code descriptions. Instead the code lengths for literal/length * codes and distance codes are fixed. The specific lengths for each symbol * can be seen in the "for" loops below. * * - The literal/length code is complete, but has two symbols that are invalid * and should result in an error if received. This cannot be implemented * simply as an incomplete code since those two symbols are in the "middle" * of the code. They are eight bits long and the longest literal/length\ * code is nine bits. Therefore the code must be constructed with those * symbols, and the invalid symbols must be detected after decoding. * * - The fixed distance codes also have two invalid symbols that should result * in an error if received. Since all of the distance codes are the same * length, this can be implemented as an incomplete code. Then the invalid * codes are detected while decoding. */ local int fixed(struct state *s) { static int virgin = 1; static short lencnt[MAXBITS+1], lensym[FIXLCODES]; static short distcnt[MAXBITS+1], distsym[MAXDCODES]; static struct huffman lencode, distcode; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { int symbol; short lengths[FIXLCODES]; /* construct lencode and distcode */ lencode.count = lencnt; lencode.symbol = lensym; distcode.count = distcnt; distcode.symbol = distsym; /* literal/length table */ for (symbol = 0; symbol < 144; symbol++) lengths[symbol] = 8; for (; symbol < 256; symbol++) lengths[symbol] = 9; for (; symbol < 280; symbol++) lengths[symbol] = 7; for (; symbol < FIXLCODES; symbol++) lengths[symbol] = 8; construct(&lencode, lengths, FIXLCODES); /* distance table */ for (symbol = 0; symbol < MAXDCODES; symbol++) lengths[symbol] = 5; construct(&distcode, lengths, MAXDCODES); /* do this just once */ virgin = 0; } /* decode data until end-of-block code */ return codes(s, &lencode, &distcode); } /* * Process a dynamic codes block. * * Format notes: * * - A dynamic block starts with a description of the literal/length and * distance codes for that block. New dynamic blocks allow the compressor to * rapidly adapt to changing data with new codes optimized for that data. * * - The codes used by the deflate format are "canonical", which means that * the actual bits of the codes are generated in an unambiguous way simply * from the number of bits in each code. Therefore the code descriptions * are simply a list of code lengths for each symbol. * * - The code lengths are stored in order for the symbols, so lengths are * provided for each of the literal/length symbols, and for each of the * distance symbols. * * - If a symbol is not used in the block, this is represented by a zero as * as the code length. This does not mean a zero-length code, but rather * that no code should be created for this symbol. There is no way in the * deflate format to represent a zero-length code. * * - The maximum number of bits in a code is 15, so the possible lengths for * any code are 1..15. * * - The fact that a length of zero is not permitted for a code has an * interesting consequence. Normally if only one symbol is used for a given * code, then in fact that code could be represented with zero bits. However * in deflate, that code has to be at least one bit. So for example, if * only a single distance base symbol appears in a block, then it will be * represented by a single code of length one, in particular one 0 bit. This * is an incomplete code, since if a 1 bit is received, it has no meaning, * and should result in an error. So incomplete distance codes of one symbol * should be permitted, and the receipt of invalid codes should be handled. * * - It is also possible to have a single literal/length code, but that code * must be the end-of-block code, since every dynamic block has one. This * is not the most efficient way to create an empty block (an empty fixed * block is fewer bits), but it is allowed by the format. So incomplete * literal/length codes of one symbol should also be permitted. * * - If there are only literal codes and no lengths, then there are no distance * codes. This is represented by one distance code with zero bits. * * - The list of up to 286 length/literal lengths and up to 30 distance lengths * are themselves compressed using Huffman codes and run-length encoding. In * the list of code lengths, a 0 symbol means no code, a 1..15 symbol means * that length, and the symbols 16, 17, and 18 are run-length instructions. * Each of 16, 17, and 18 are follwed by extra bits to define the length of * the run. 16 copies the last length 3 to 6 times. 17 represents 3 to 10 * zero lengths, and 18 represents 11 to 138 zero lengths. Unused symbols * are common, hence the special coding for zero lengths. * * - The symbols for 0..18 are Huffman coded, and so that code must be * described first. This is simply a sequence of up to 19 three-bit values * representing no code (0) or the code length for that symbol (1..7). * * - A dynamic block starts with three fixed-size counts from which is computed * the number of literal/length code lengths, the number of distance code * lengths, and the number of code length code lengths (ok, you come up with * a better name!) in the code descriptions. For the literal/length and * distance codes, lengths after those provided are considered zero, i.e. no * code. The code length code lengths are received in a permuted order (see * the order[] array below) to make a short code length code length list more * likely. As it turns out, very short and very long codes are less likely * to be seen in a dynamic code description, hence what may appear initially * to be a peculiar ordering. * * - Given the number of literal/length code lengths (nlen) and distance code * lengths (ndist), then they are treated as one long list of nlen + ndist * code lengths. Therefore run-length coding can and often does cross the * boundary between the two sets of lengths. * * - So to summarize, the code description at the start of a dynamic block is * three counts for the number of code lengths for the literal/length codes, * the distance codes, and the code length codes. This is followed by the * code length code lengths, three bits each. This is used to construct the * code length code which is used to read the remainder of the lengths. Then * the literal/length code lengths and distance lengths are read as a single * set of lengths using the code length codes. Codes are constructed from * the resulting two sets of lengths, and then finally you can start * decoding actual compressed data in the block. * * - For reference, a "typical" size for the code description in a dynamic * block is around 80 bytes. */ local int dynamic(struct state *s) { int nlen, ndist, ncode; /* number of lengths in descriptor */ int index; /* index of lengths[] */ int err; /* construct() return value */ short lengths[MAXCODES]; /* descriptor code lengths */ short lencnt[MAXBITS+1], lensym[MAXLCODES]; /* lencode memory */ short distcnt[MAXBITS+1], distsym[MAXDCODES]; /* distcode memory */ struct huffman lencode, distcode; /* length and distance codes */ static const short order[19] = /* permutation of code length codes */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; /* construct lencode and distcode */ lencode.count = lencnt; lencode.symbol = lensym; distcode.count = distcnt; distcode.symbol = distsym; /* get number of lengths in each table, check lengths */ nlen = bits(s, 5) + 257; ndist = bits(s, 5) + 1; ncode = bits(s, 4) + 4; if (nlen > MAXLCODES || ndist > MAXDCODES) return -3; /* bad counts */ /* read code length code lengths (really), missing lengths are zero */ for (index = 0; index < ncode; index++) lengths[order[index]] = bits(s, 3); for (; index < 19; index++) lengths[order[index]] = 0; /* build huffman table for code lengths codes (use lencode temporarily) */ err = construct(&lencode, lengths, 19); if (err != 0) /* require complete code set here */ return -4; /* read length/literal and distance code length tables */ index = 0; while (index < nlen + ndist) { int symbol; /* decoded value */ int len; /* last length to repeat */ symbol = decode(s, &lencode); if (symbol < 0) return symbol; /* invalid symbol */ if (symbol < 16) /* length in 0..15 */ lengths[index++] = symbol; else { /* repeat instruction */ len = 0; /* assume repeating zeros */ if (symbol == 16) { /* repeat last length 3..6 times */ if (index == 0) return -5; /* no last length! */ len = lengths[index - 1]; /* last length */ symbol = 3 + bits(s, 2); } else if (symbol == 17) /* repeat zero 3..10 times */ symbol = 3 + bits(s, 3); else /* == 18, repeat zero 11..138 times */ symbol = 11 + bits(s, 7); if (index + symbol > nlen + ndist) return -6; /* too many lengths! */ while (symbol--) /* repeat last or zero symbol times */ lengths[index++] = len; } } /* check for end-of-block code -- there better be one! */ if (lengths[256] == 0) return -9; /* build huffman table for literal/length codes */ err = construct(&lencode, lengths, nlen); if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1])) return -7; /* incomplete code ok only for single length 1 code */ /* build huffman table for distance codes */ err = construct(&distcode, lengths + nlen, ndist); if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1])) return -8; /* incomplete code ok only for single length 1 code */ /* decode data until end-of-block code */ return codes(s, &lencode, &distcode); } /* * Inflate source to dest. On return, destlen and sourcelen are updated to the * size of the uncompressed data and the size of the deflate data respectively. * On success, the return value of puff() is zero. If there is an error in the * source data, i.e. it is not in the deflate format, then a negative value is * returned. If there is not enough input available or there is not enough * output space, then a positive error is returned. In that case, destlen and * sourcelen are not updated to facilitate retrying from the beginning with the * provision of more input data or more output space. In the case of invalid * inflate data (a negative error), the dest and source pointers are updated to * facilitate the debugging of deflators. * * puff() also has a mode to determine the size of the uncompressed output with * no output written. For this dest must be (unsigned char *)0. In this case, * the input value of *destlen is ignored, and on return *destlen is set to the * size of the uncompressed output. * * The return codes are: * * 2: available inflate data did not terminate * 1: output space exhausted before completing inflate * 0: successful inflate * -1: invalid block type (type == 3) * -2: stored block length did not match one's complement * -3: dynamic block code description: too many length or distance codes * -4: dynamic block code description: code lengths codes incomplete * -5: dynamic block code description: repeat lengths with no first length * -6: dynamic block code description: repeat more than specified lengths * -7: dynamic block code description: invalid literal/length code lengths * -8: dynamic block code description: invalid distance code lengths * -9: dynamic block code description: missing end-of-block code * -10: invalid literal/length or distance code in fixed or dynamic block * -11: distance is too far back in fixed or dynamic block * * Format notes: * * - Three bits are read for each block to determine the kind of block and * whether or not it is the last block. Then the block is decoded and the * process repeated if it was not the last block. * * - The leftover bits in the last byte of the deflate data after the last * block (if it was a fixed or dynamic block) are undefined and have no * expected values to check. */ int puff(unsigned char *dest, /* pointer to destination pointer */ unsigned long *destlen, /* amount of output space */ const unsigned char *source, /* pointer to source data pointer */ unsigned long *sourcelen) /* amount of input available */ { struct state s; /* input/output state */ int last, type; /* block information */ int err; /* return value */ /* initialize output state */ s.out = dest; s.outlen = *destlen; /* ignored if dest is NIL */ s.outcnt = 0; /* initialize input state */ s.in = source; s.inlen = *sourcelen; s.incnt = 0; s.bitbuf = 0; s.bitcnt = 0; /* return if bits() or decode() tries to read past available input */ if (setjmp(s.env) != 0) /* if came back here via longjmp() */ err = 2; /* then skip do-loop, return error */ else { /* process blocks until last block or error */ do { last = bits(&s, 1); /* one if last block */ type = bits(&s, 2); /* block type 0..3 */ err = type == 0 ? stored(&s) : (type == 1 ? fixed(&s) : (type == 2 ? dynamic(&s) : -1)); /* type == 3, invalid */ if (err != 0) break; /* return with error */ } while (!last); } /* update the lengths and return */ if (err <= 0) { *destlen = s.outcnt; *sourcelen = s.incnt; } return err; } tcl8.6.5/compat/zlib/contrib/puff/puff.h0000644000175000017500000000260712663660064017527 0ustar sergeisergei/* puff.h Copyright (C) 2002-2013 Mark Adler, all rights reserved version 2.3, 21 Jan 2013 This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Mark Adler madler@alumni.caltech.edu */ /* * See puff.c for purpose and usage. */ #ifndef NIL # define NIL ((unsigned char *)0) /* for no output option */ #endif int puff(unsigned char *dest, /* pointer to destination pointer */ unsigned long *destlen, /* amount of output space */ const unsigned char *source, /* pointer to source data pointer */ unsigned long *sourcelen); /* amount of input available */ tcl8.6.5/compat/zlib/contrib/puff/pufftest.c0000644000175000017500000001146512663660064020424 0ustar sergeisergei/* * pufftest.c * Copyright (C) 2002-2013 Mark Adler * For conditions of distribution and use, see copyright notice in puff.h * version 2.3, 21 Jan 2013 */ /* Example of how to use puff(). Usage: puff [-w] [-f] [-nnn] file ... | puff [-w] [-f] [-nnn] where file is the input file with deflate data, nnn is the number of bytes of input to skip before inflating (e.g. to skip a zlib or gzip header), and -w is used to write the decompressed data to stdout. -f is for coverage testing, and causes pufftest to fail with not enough output space (-f does a write like -w, so -w is not required). */ #include #include #include "puff.h" #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) # include # include # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) #else # define SET_BINARY_MODE(file) #endif #define local static /* Return size times approximately the cube root of 2, keeping the result as 1, 3, or 5 times a power of 2 -- the result is always > size, until the result is the maximum value of an unsigned long, where it remains. This is useful to keep reallocations less than ~33% over the actual data. */ local size_t bythirds(size_t size) { int n; size_t m; m = size; for (n = 0; m; n++) m >>= 1; if (n < 3) return size + 1; n -= 3; m = size >> n; m += m == 6 ? 2 : 1; m <<= n; return m > size ? m : (size_t)(-1); } /* Read the input file *name, or stdin if name is NULL, into allocated memory. Reallocate to larger buffers until the entire file is read in. Return a pointer to the allocated data, or NULL if there was a memory allocation failure. *len is the number of bytes of data read from the input file (even if load() returns NULL). If the input file was empty or could not be opened or read, *len is zero. */ local void *load(const char *name, size_t *len) { size_t size; void *buf, *swap; FILE *in; *len = 0; buf = malloc(size = 4096); if (buf == NULL) return NULL; in = name == NULL ? stdin : fopen(name, "rb"); if (in != NULL) { for (;;) { *len += fread((char *)buf + *len, 1, size - *len, in); if (*len < size) break; size = bythirds(size); if (size == *len || (swap = realloc(buf, size)) == NULL) { free(buf); buf = NULL; break; } buf = swap; } fclose(in); } return buf; } int main(int argc, char **argv) { int ret, put = 0, fail = 0; unsigned skip = 0; char *arg, *name = NULL; unsigned char *source = NULL, *dest; size_t len = 0; unsigned long sourcelen, destlen; /* process arguments */ while (arg = *++argv, --argc) if (arg[0] == '-') { if (arg[1] == 'w' && arg[2] == 0) put = 1; else if (arg[1] == 'f' && arg[2] == 0) fail = 1, put = 1; else if (arg[1] >= '0' && arg[1] <= '9') skip = (unsigned)atoi(arg + 1); else { fprintf(stderr, "invalid option %s\n", arg); return 3; } } else if (name != NULL) { fprintf(stderr, "only one file name allowed\n"); return 3; } else name = arg; source = load(name, &len); if (source == NULL) { fprintf(stderr, "memory allocation failure\n"); return 4; } if (len == 0) { fprintf(stderr, "could not read %s, or it was empty\n", name == NULL ? "" : name); free(source); return 3; } if (skip >= len) { fprintf(stderr, "skip request of %d leaves no input\n", skip); free(source); return 3; } /* test inflate data with offset skip */ len -= skip; sourcelen = (unsigned long)len; ret = puff(NIL, &destlen, source + skip, &sourcelen); if (ret) fprintf(stderr, "puff() failed with return code %d\n", ret); else { fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen); if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n", len - sourcelen); } /* if requested, inflate again and write decompressd data to stdout */ if (put && ret == 0) { if (fail) destlen >>= 1; dest = malloc(destlen); if (dest == NULL) { fprintf(stderr, "memory allocation failure\n"); free(source); return 4; } puff(dest, &destlen, source + skip, &sourcelen); SET_BINARY_MODE(stdout); fwrite(dest, 1, destlen, stdout); free(dest); } /* clean up */ free(source); return ret; } tcl8.6.5/compat/zlib/contrib/puff/zeros.raw0000644000175000017500000000472512663660064020276 0ustar sergeisergeib`£`Œ‚Q0 FÁ(£`Œ‚Q0 FÁ(£`Œ‚Q0 FÁ(£`Œ‚Q0 FÁ(£`Œ‚Q0¤€ 8⿲$‚þ¿nG 0 öÿíÜ€ ëF(ì_Àtcl8.6.5/compat/zlib/contrib/puff/Makefile0000644000175000017500000000355312663660064020057 0ustar sergeisergeiCFLAGS=-O puff: puff.o pufftest.o puff.o: puff.h pufftest.o: puff.h test: puff puff zeros.raw puft: puff.c puff.h pufftest.o cc -fprofile-arcs -ftest-coverage -o puft puff.c pufftest.o # puff full coverage test (should say 100%) cov: puft @rm -f *.gcov *.gcda @puft -w zeros.raw 2>&1 | cat > /dev/null @echo '04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 @echo '00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 @echo '00 00 00 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 254 @echo '00 01 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 @echo '01 01 00 fe ff 0a' | xxd -r -p | puft -f 2>&1 | cat > /dev/null @echo '02 7e ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 @echo '02' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 @echo '04 80 49 92 24 49 92 24 71 ff ff 93 11 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 249 @echo '04 c0 81 08 00 00 00 00 20 7f eb 0b 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 @echo '0b 00 00' | xxd -r -p | puft -f 2>&1 | cat > /dev/null @echo '1a 07' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 @echo '0c c0 81 00 00 00 00 00 90 ff 6b 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 245 @puft -f zeros.raw 2>&1 | cat > /dev/null @echo 'fc 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 253 @echo '04 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 252 @echo '04 00 24 49' | xxd -r -p | puft 2> /dev/null || test $$? -eq 251 @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 84' | xxd -r -p | puft 2> /dev/null || test $$? -eq 248 @echo '04 00 24 e9 ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 250 @echo '04 00 24 e9 ff 6d' | xxd -r -p | puft 2> /dev/null || test $$? -eq 247 @gcov -n puff.c clean: rm -f puff puft *.o *.gc* tcl8.6.5/compat/zlib/contrib/puff/README0000644000175000017500000000600412663653131017266 0ustar sergeisergeiPuff -- A Simple Inflate 3 Mar 2003 Mark Adler madler@alumni.caltech.edu What this is -- puff.c provides the routine puff() to decompress the deflate data format. It does so more slowly than zlib, but the code is about one-fifth the size of the inflate code in zlib, and written to be very easy to read. Why I wrote this -- puff.c was written to document the deflate format unambiguously, by virtue of being working C code. It is meant to supplement RFC 1951, which formally describes the deflate format. I have received many questions on details of the deflate format, and I hope that reading this code will answer those questions. puff.c is heavily commented with details of the deflate format, especially those little nooks and cranies of the format that might not be obvious from a specification. puff.c may also be useful in applications where code size or memory usage is a very limited resource, and speed is not as important. How to use it -- Well, most likely you should just be reading puff.c and using zlib for actual applications, but if you must ... Include puff.h in your code, which provides this prototype: int puff(unsigned char *dest, /* pointer to destination pointer */ unsigned long *destlen, /* amount of output space */ unsigned char *source, /* pointer to source data pointer */ unsigned long *sourcelen); /* amount of input available */ Then you can call puff() to decompress a deflate stream that is in memory in its entirety at source, to a sufficiently sized block of memory for the decompressed data at dest. puff() is the only external symbol in puff.c The only C library functions that puff.c needs are setjmp() and longjmp(), which are used to simplify error checking in the code to improve readabilty. puff.c does no memory allocation, and uses less than 2K bytes off of the stack. If destlen is not enough space for the uncompressed data, then inflate will return an error without writing more than destlen bytes. Note that this means that in order to decompress the deflate data successfully, you need to know the size of the uncompressed data ahead of time. If needed, puff() can determine the size of the uncompressed data with no output space. This is done by passing dest equal to (unsigned char *)0. Then the initial value of *destlen is ignored and *destlen is set to the length of the uncompressed data. So if the size of the uncompressed data is not known, then two passes of puff() can be used--first to determine the size, and second to do the actual inflation after allocating the appropriate memory. Not pretty, but it works. (This is one of the reasons you should be using zlib.) The deflate format is self-terminating. If the deflate stream does not end in *sourcelen bytes, puff() will return an error without reading at or past endsource. On return, *sourcelen is updated to the amount of input data consumed, and *destlen is updated to the size of the uncompressed data. See the comments in puff.c for the possible return codes for puff(). tcl8.6.5/compat/zlib/contrib/pascal/0000755000175000017500000000000012665173607016720 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/pascal/zlibd32.mak0000644000175000017500000000447012663660064020664 0ustar sergeisergei# Makefile for zlib # For use with Delphi and C++ Builder under Win32 # Updated for zlib 1.2.x by Cosmin Truta # ------------ Borland C++ ------------ # This project uses the Delphi (fastcall/register) calling convention: LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl CC = bcc32 LD = bcc32 AR = tlib # do not use "-pr" in CFLAGS CFLAGS = -a -d -k- -O2 $(LOC) LDFLAGS = # variables ZLIB_LIB = zlib.lib OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj # targets all: $(ZLIB_LIB) example.exe minigzip.exe .c.obj: $(CC) -c $(CFLAGS) $*.c adler32.obj: adler32.c zlib.h zconf.h compress.obj: compress.c zlib.h zconf.h crc32.obj: crc32.c zlib.h zconf.h crc32.h deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h gzread.obj: gzread.c zlib.h zconf.h gzguts.h gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h uncompr.obj: uncompr.c zlib.h zconf.h zutil.obj: zutil.c zutil.h zlib.h zconf.h example.obj: test/example.c zlib.h zconf.h minigzip.obj: test/minigzip.c zlib.h zconf.h # For the sake of the old Borland make, # the command line is cut to fit in the MS-DOS 128 byte limit: $(ZLIB_LIB): $(OBJ1) $(OBJ2) -del $(ZLIB_LIB) $(AR) $(ZLIB_LIB) $(OBJP1) $(AR) $(ZLIB_LIB) $(OBJP2) # testing test: example.exe minigzip.exe example echo hello world | minigzip | minigzip -d example.exe: example.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) minigzip.exe: minigzip.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) # cleanup clean: -del *.obj -del *.exe -del *.lib -del *.tds -del zlib.bak -del foo.gz tcl8.6.5/compat/zlib/contrib/pascal/readme.txt0000644000175000017500000000567412663653131020723 0ustar sergeisergei This directory contains a Pascal (Delphi, Kylix) interface to the zlib data compression library. Directory listing ================= zlibd32.mak makefile for Borland C++ example.pas usage example of zlib zlibpas.pas the Pascal interface to zlib readme.txt this file Compatibility notes =================== - Although the name "zlib" would have been more normal for the zlibpas unit, this name is already taken by Borland's ZLib unit. This is somehow unfortunate, because that unit is not a genuine interface to the full-fledged zlib functionality, but a suite of class wrappers around zlib streams. Other essential features, such as checksums, are missing. It would have been more appropriate for that unit to have a name like "ZStreams", or something similar. - The C and zlib-supplied types int, uInt, long, uLong, etc. are translated directly into Pascal types of similar sizes (Integer, LongInt, etc.), to avoid namespace pollution. In particular, there is no conversion of unsigned int into a Pascal unsigned integer. The Word type is non-portable and has the same size (16 bits) both in a 16-bit and in a 32-bit environment, unlike Integer. Even if there is a 32-bit Cardinal type, there is no real need for unsigned int in zlib under a 32-bit environment. - Except for the callbacks, the zlib function interfaces are assuming the calling convention normally used in Pascal (__pascal for DOS and Windows16, __fastcall for Windows32). Since the cdecl keyword is used, the old Turbo Pascal does not work with this interface. - The gz* function interfaces are not translated, to avoid interfacing problems with the C runtime library. Besides, gzprintf(gzFile file, const char *format, ...) cannot be translated into Pascal. Legal issues ============ The zlibpas interface is: Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler. Copyright (C) 1998 by Bob Dellaca. Copyright (C) 2003 by Cosmin Truta. The example program is: Copyright (C) 1995-2003 by Jean-loup Gailly. Copyright (C) 1998,1999,2000 by Jacques Nomssi Nzali. Copyright (C) 2003 by Cosmin Truta. This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. tcl8.6.5/compat/zlib/contrib/pascal/example.pas0000644000175000017500000003650712663653131021064 0ustar sergeisergei(* example.c -- usage example of the zlib compression library * Copyright (C) 1995-2003 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h * * Pascal translation * Copyright (C) 1998 by Jacques Nomssi Nzali. * For conditions of distribution and use, see copyright notice in readme.txt * * Adaptation to the zlibpas interface * Copyright (C) 2003 by Cosmin Truta. * For conditions of distribution and use, see copyright notice in readme.txt *) program example; {$DEFINE TEST_COMPRESS} {DO NOT $DEFINE TEST_GZIO} {$DEFINE TEST_DEFLATE} {$DEFINE TEST_INFLATE} {$DEFINE TEST_FLUSH} {$DEFINE TEST_SYNC} {$DEFINE TEST_DICT} uses SysUtils, zlibpas; const TESTFILE = 'foo.gz'; (* "hello world" would be more standard, but the repeated "hello" * stresses the compression code better, sorry... *) const hello: PChar = 'hello, hello!'; const dictionary: PChar = 'hello'; var dictId: LongInt; (* Adler32 value of the dictionary *) procedure CHECK_ERR(err: Integer; msg: String); begin if err <> Z_OK then begin WriteLn(msg, ' error: ', err); Halt(1); end; end; procedure EXIT_ERR(const msg: String); begin WriteLn('Error: ', msg); Halt(1); end; (* =========================================================================== * Test compress and uncompress *) {$IFDEF TEST_COMPRESS} procedure test_compress(compr: Pointer; comprLen: LongInt; uncompr: Pointer; uncomprLen: LongInt); var err: Integer; len: LongInt; begin len := StrLen(hello)+1; err := compress(compr, comprLen, hello, len); CHECK_ERR(err, 'compress'); StrCopy(PChar(uncompr), 'garbage'); err := uncompress(uncompr, uncomprLen, compr, comprLen); CHECK_ERR(err, 'uncompress'); if StrComp(PChar(uncompr), hello) <> 0 then EXIT_ERR('bad uncompress') else WriteLn('uncompress(): ', PChar(uncompr)); end; {$ENDIF} (* =========================================================================== * Test read/write of .gz files *) {$IFDEF TEST_GZIO} procedure test_gzio(const fname: PChar; (* compressed file name *) uncompr: Pointer; uncomprLen: LongInt); var err: Integer; len: Integer; zfile: gzFile; pos: LongInt; begin len := StrLen(hello)+1; zfile := gzopen(fname, 'wb'); if zfile = NIL then begin WriteLn('gzopen error'); Halt(1); end; gzputc(zfile, 'h'); if gzputs(zfile, 'ello') <> 4 then begin WriteLn('gzputs err: ', gzerror(zfile, err)); Halt(1); end; {$IFDEF GZ_FORMAT_STRING} if gzprintf(zfile, ', %s!', 'hello') <> 8 then begin WriteLn('gzprintf err: ', gzerror(zfile, err)); Halt(1); end; {$ELSE} if gzputs(zfile, ', hello!') <> 8 then begin WriteLn('gzputs err: ', gzerror(zfile, err)); Halt(1); end; {$ENDIF} gzseek(zfile, 1, SEEK_CUR); (* add one zero byte *) gzclose(zfile); zfile := gzopen(fname, 'rb'); if zfile = NIL then begin WriteLn('gzopen error'); Halt(1); end; StrCopy(PChar(uncompr), 'garbage'); if gzread(zfile, uncompr, uncomprLen) <> len then begin WriteLn('gzread err: ', gzerror(zfile, err)); Halt(1); end; if StrComp(PChar(uncompr), hello) <> 0 then begin WriteLn('bad gzread: ', PChar(uncompr)); Halt(1); end else WriteLn('gzread(): ', PChar(uncompr)); pos := gzseek(zfile, -8, SEEK_CUR); if (pos <> 6) or (gztell(zfile) <> pos) then begin WriteLn('gzseek error, pos=', pos, ', gztell=', gztell(zfile)); Halt(1); end; if gzgetc(zfile) <> ' ' then begin WriteLn('gzgetc error'); Halt(1); end; if gzungetc(' ', zfile) <> ' ' then begin WriteLn('gzungetc error'); Halt(1); end; gzgets(zfile, PChar(uncompr), uncomprLen); uncomprLen := StrLen(PChar(uncompr)); if uncomprLen <> 7 then (* " hello!" *) begin WriteLn('gzgets err after gzseek: ', gzerror(zfile, err)); Halt(1); end; if StrComp(PChar(uncompr), hello + 6) <> 0 then begin WriteLn('bad gzgets after gzseek'); Halt(1); end else WriteLn('gzgets() after gzseek: ', PChar(uncompr)); gzclose(zfile); end; {$ENDIF} (* =========================================================================== * Test deflate with small buffers *) {$IFDEF TEST_DEFLATE} procedure test_deflate(compr: Pointer; comprLen: LongInt); var c_stream: z_stream; (* compression stream *) err: Integer; len: LongInt; begin len := StrLen(hello)+1; c_stream.zalloc := NIL; c_stream.zfree := NIL; c_stream.opaque := NIL; err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION); CHECK_ERR(err, 'deflateInit'); c_stream.next_in := hello; c_stream.next_out := compr; while (c_stream.total_in <> len) and (c_stream.total_out < comprLen) do begin c_stream.avail_out := 1; { force small buffers } c_stream.avail_in := 1; err := deflate(c_stream, Z_NO_FLUSH); CHECK_ERR(err, 'deflate'); end; (* Finish the stream, still forcing small buffers: *) while TRUE do begin c_stream.avail_out := 1; err := deflate(c_stream, Z_FINISH); if err = Z_STREAM_END then break; CHECK_ERR(err, 'deflate'); end; err := deflateEnd(c_stream); CHECK_ERR(err, 'deflateEnd'); end; {$ENDIF} (* =========================================================================== * Test inflate with small buffers *) {$IFDEF TEST_INFLATE} procedure test_inflate(compr: Pointer; comprLen : LongInt; uncompr: Pointer; uncomprLen : LongInt); var err: Integer; d_stream: z_stream; (* decompression stream *) begin StrCopy(PChar(uncompr), 'garbage'); d_stream.zalloc := NIL; d_stream.zfree := NIL; d_stream.opaque := NIL; d_stream.next_in := compr; d_stream.avail_in := 0; d_stream.next_out := uncompr; err := inflateInit(d_stream); CHECK_ERR(err, 'inflateInit'); while (d_stream.total_out < uncomprLen) and (d_stream.total_in < comprLen) do begin d_stream.avail_out := 1; (* force small buffers *) d_stream.avail_in := 1; err := inflate(d_stream, Z_NO_FLUSH); if err = Z_STREAM_END then break; CHECK_ERR(err, 'inflate'); end; err := inflateEnd(d_stream); CHECK_ERR(err, 'inflateEnd'); if StrComp(PChar(uncompr), hello) <> 0 then EXIT_ERR('bad inflate') else WriteLn('inflate(): ', PChar(uncompr)); end; {$ENDIF} (* =========================================================================== * Test deflate with large buffers and dynamic change of compression level *) {$IFDEF TEST_DEFLATE} procedure test_large_deflate(compr: Pointer; comprLen: LongInt; uncompr: Pointer; uncomprLen: LongInt); var c_stream: z_stream; (* compression stream *) err: Integer; begin c_stream.zalloc := NIL; c_stream.zfree := NIL; c_stream.opaque := NIL; err := deflateInit(c_stream, Z_BEST_SPEED); CHECK_ERR(err, 'deflateInit'); c_stream.next_out := compr; c_stream.avail_out := Integer(comprLen); (* At this point, uncompr is still mostly zeroes, so it should compress * very well: *) c_stream.next_in := uncompr; c_stream.avail_in := Integer(uncomprLen); err := deflate(c_stream, Z_NO_FLUSH); CHECK_ERR(err, 'deflate'); if c_stream.avail_in <> 0 then EXIT_ERR('deflate not greedy'); (* Feed in already compressed data and switch to no compression: *) deflateParams(c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); c_stream.next_in := compr; c_stream.avail_in := Integer(comprLen div 2); err := deflate(c_stream, Z_NO_FLUSH); CHECK_ERR(err, 'deflate'); (* Switch back to compressing mode: *) deflateParams(c_stream, Z_BEST_COMPRESSION, Z_FILTERED); c_stream.next_in := uncompr; c_stream.avail_in := Integer(uncomprLen); err := deflate(c_stream, Z_NO_FLUSH); CHECK_ERR(err, 'deflate'); err := deflate(c_stream, Z_FINISH); if err <> Z_STREAM_END then EXIT_ERR('deflate should report Z_STREAM_END'); err := deflateEnd(c_stream); CHECK_ERR(err, 'deflateEnd'); end; {$ENDIF} (* =========================================================================== * Test inflate with large buffers *) {$IFDEF TEST_INFLATE} procedure test_large_inflate(compr: Pointer; comprLen: LongInt; uncompr: Pointer; uncomprLen: LongInt); var err: Integer; d_stream: z_stream; (* decompression stream *) begin StrCopy(PChar(uncompr), 'garbage'); d_stream.zalloc := NIL; d_stream.zfree := NIL; d_stream.opaque := NIL; d_stream.next_in := compr; d_stream.avail_in := Integer(comprLen); err := inflateInit(d_stream); CHECK_ERR(err, 'inflateInit'); while TRUE do begin d_stream.next_out := uncompr; (* discard the output *) d_stream.avail_out := Integer(uncomprLen); err := inflate(d_stream, Z_NO_FLUSH); if err = Z_STREAM_END then break; CHECK_ERR(err, 'large inflate'); end; err := inflateEnd(d_stream); CHECK_ERR(err, 'inflateEnd'); if d_stream.total_out <> 2 * uncomprLen + comprLen div 2 then begin WriteLn('bad large inflate: ', d_stream.total_out); Halt(1); end else WriteLn('large_inflate(): OK'); end; {$ENDIF} (* =========================================================================== * Test deflate with full flush *) {$IFDEF TEST_FLUSH} procedure test_flush(compr: Pointer; var comprLen : LongInt); var c_stream: z_stream; (* compression stream *) err: Integer; len: Integer; begin len := StrLen(hello)+1; c_stream.zalloc := NIL; c_stream.zfree := NIL; c_stream.opaque := NIL; err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION); CHECK_ERR(err, 'deflateInit'); c_stream.next_in := hello; c_stream.next_out := compr; c_stream.avail_in := 3; c_stream.avail_out := Integer(comprLen); err := deflate(c_stream, Z_FULL_FLUSH); CHECK_ERR(err, 'deflate'); Inc(PByteArray(compr)^[3]); (* force an error in first compressed block *) c_stream.avail_in := len - 3; err := deflate(c_stream, Z_FINISH); if err <> Z_STREAM_END then CHECK_ERR(err, 'deflate'); err := deflateEnd(c_stream); CHECK_ERR(err, 'deflateEnd'); comprLen := c_stream.total_out; end; {$ENDIF} (* =========================================================================== * Test inflateSync() *) {$IFDEF TEST_SYNC} procedure test_sync(compr: Pointer; comprLen: LongInt; uncompr: Pointer; uncomprLen : LongInt); var err: Integer; d_stream: z_stream; (* decompression stream *) begin StrCopy(PChar(uncompr), 'garbage'); d_stream.zalloc := NIL; d_stream.zfree := NIL; d_stream.opaque := NIL; d_stream.next_in := compr; d_stream.avail_in := 2; (* just read the zlib header *) err := inflateInit(d_stream); CHECK_ERR(err, 'inflateInit'); d_stream.next_out := uncompr; d_stream.avail_out := Integer(uncomprLen); inflate(d_stream, Z_NO_FLUSH); CHECK_ERR(err, 'inflate'); d_stream.avail_in := Integer(comprLen-2); (* read all compressed data *) err := inflateSync(d_stream); (* but skip the damaged part *) CHECK_ERR(err, 'inflateSync'); err := inflate(d_stream, Z_FINISH); if err <> Z_DATA_ERROR then EXIT_ERR('inflate should report DATA_ERROR'); (* Because of incorrect adler32 *) err := inflateEnd(d_stream); CHECK_ERR(err, 'inflateEnd'); WriteLn('after inflateSync(): hel', PChar(uncompr)); end; {$ENDIF} (* =========================================================================== * Test deflate with preset dictionary *) {$IFDEF TEST_DICT} procedure test_dict_deflate(compr: Pointer; comprLen: LongInt); var c_stream: z_stream; (* compression stream *) err: Integer; begin c_stream.zalloc := NIL; c_stream.zfree := NIL; c_stream.opaque := NIL; err := deflateInit(c_stream, Z_BEST_COMPRESSION); CHECK_ERR(err, 'deflateInit'); err := deflateSetDictionary(c_stream, dictionary, StrLen(dictionary)); CHECK_ERR(err, 'deflateSetDictionary'); dictId := c_stream.adler; c_stream.next_out := compr; c_stream.avail_out := Integer(comprLen); c_stream.next_in := hello; c_stream.avail_in := StrLen(hello)+1; err := deflate(c_stream, Z_FINISH); if err <> Z_STREAM_END then EXIT_ERR('deflate should report Z_STREAM_END'); err := deflateEnd(c_stream); CHECK_ERR(err, 'deflateEnd'); end; {$ENDIF} (* =========================================================================== * Test inflate with a preset dictionary *) {$IFDEF TEST_DICT} procedure test_dict_inflate(compr: Pointer; comprLen: LongInt; uncompr: Pointer; uncomprLen: LongInt); var err: Integer; d_stream: z_stream; (* decompression stream *) begin StrCopy(PChar(uncompr), 'garbage'); d_stream.zalloc := NIL; d_stream.zfree := NIL; d_stream.opaque := NIL; d_stream.next_in := compr; d_stream.avail_in := Integer(comprLen); err := inflateInit(d_stream); CHECK_ERR(err, 'inflateInit'); d_stream.next_out := uncompr; d_stream.avail_out := Integer(uncomprLen); while TRUE do begin err := inflate(d_stream, Z_NO_FLUSH); if err = Z_STREAM_END then break; if err = Z_NEED_DICT then begin if d_stream.adler <> dictId then EXIT_ERR('unexpected dictionary'); err := inflateSetDictionary(d_stream, dictionary, StrLen(dictionary)); end; CHECK_ERR(err, 'inflate with dict'); end; err := inflateEnd(d_stream); CHECK_ERR(err, 'inflateEnd'); if StrComp(PChar(uncompr), hello) <> 0 then EXIT_ERR('bad inflate with dict') else WriteLn('inflate with dictionary: ', PChar(uncompr)); end; {$ENDIF} var compr, uncompr: Pointer; comprLen, uncomprLen: LongInt; begin if zlibVersion^ <> ZLIB_VERSION[1] then EXIT_ERR('Incompatible zlib version'); WriteLn('zlib version: ', zlibVersion); WriteLn('zlib compile flags: ', Format('0x%x', [zlibCompileFlags])); comprLen := 10000 * SizeOf(Integer); (* don't overflow on MSDOS *) uncomprLen := comprLen; GetMem(compr, comprLen); GetMem(uncompr, uncomprLen); if (compr = NIL) or (uncompr = NIL) then EXIT_ERR('Out of memory'); (* compr and uncompr are cleared to avoid reading uninitialized * data and to ensure that uncompr compresses well. *) FillChar(compr^, comprLen, 0); FillChar(uncompr^, uncomprLen, 0); {$IFDEF TEST_COMPRESS} WriteLn('** Testing compress'); test_compress(compr, comprLen, uncompr, uncomprLen); {$ENDIF} {$IFDEF TEST_GZIO} WriteLn('** Testing gzio'); if ParamCount >= 1 then test_gzio(ParamStr(1), uncompr, uncomprLen) else test_gzio(TESTFILE, uncompr, uncomprLen); {$ENDIF} {$IFDEF TEST_DEFLATE} WriteLn('** Testing deflate with small buffers'); test_deflate(compr, comprLen); {$ENDIF} {$IFDEF TEST_INFLATE} WriteLn('** Testing inflate with small buffers'); test_inflate(compr, comprLen, uncompr, uncomprLen); {$ENDIF} {$IFDEF TEST_DEFLATE} WriteLn('** Testing deflate with large buffers'); test_large_deflate(compr, comprLen, uncompr, uncomprLen); {$ENDIF} {$IFDEF TEST_INFLATE} WriteLn('** Testing inflate with large buffers'); test_large_inflate(compr, comprLen, uncompr, uncomprLen); {$ENDIF} {$IFDEF TEST_FLUSH} WriteLn('** Testing deflate with full flush'); test_flush(compr, comprLen); {$ENDIF} {$IFDEF TEST_SYNC} WriteLn('** Testing inflateSync'); test_sync(compr, comprLen, uncompr, uncomprLen); {$ENDIF} comprLen := uncomprLen; {$IFDEF TEST_DICT} WriteLn('** Testing deflate and inflate with preset dictionary'); test_dict_deflate(compr, comprLen); test_dict_inflate(compr, comprLen, uncompr, uncomprLen); {$ENDIF} FreeMem(compr, comprLen); FreeMem(uncompr, uncomprLen); end. tcl8.6.5/compat/zlib/contrib/pascal/zlibpas.pas0000644000175000017500000002361612663660064021075 0ustar sergeisergei(* zlibpas -- Pascal interface to the zlib data compression library * * Copyright (C) 2003 Cosmin Truta. * Derived from original sources by Bob Dellaca. * For conditions of distribution and use, see copyright notice in readme.txt *) unit zlibpas; interface const ZLIB_VERSION = '1.2.8'; ZLIB_VERNUM = $1280; type alloc_func = function(opaque: Pointer; items, size: Integer): Pointer; cdecl; free_func = procedure(opaque, address: Pointer); cdecl; in_func = function(opaque: Pointer; var buf: PByte): Integer; cdecl; out_func = function(opaque: Pointer; buf: PByte; size: Integer): Integer; cdecl; z_streamp = ^z_stream; z_stream = packed record next_in: PChar; (* next input byte *) avail_in: Integer; (* number of bytes available at next_in *) total_in: LongInt; (* total nb of input bytes read so far *) next_out: PChar; (* next output byte should be put there *) avail_out: Integer; (* remaining free space at next_out *) total_out: LongInt; (* total nb of bytes output so far *) msg: PChar; (* last error message, NULL if no error *) state: Pointer; (* not visible by applications *) zalloc: alloc_func; (* used to allocate the internal state *) zfree: free_func; (* used to free the internal state *) opaque: Pointer; (* private data object passed to zalloc and zfree *) data_type: Integer; (* best guess about the data type: ascii or binary *) adler: LongInt; (* adler32 value of the uncompressed data *) reserved: LongInt; (* reserved for future use *) end; gz_headerp = ^gz_header; gz_header = packed record text: Integer; (* true if compressed data believed to be text *) time: LongInt; (* modification time *) xflags: Integer; (* extra flags (not used when writing a gzip file) *) os: Integer; (* operating system *) extra: PChar; (* pointer to extra field or Z_NULL if none *) extra_len: Integer; (* extra field length (valid if extra != Z_NULL) *) extra_max: Integer; (* space at extra (only when reading header) *) name: PChar; (* pointer to zero-terminated file name or Z_NULL *) name_max: Integer; (* space at name (only when reading header) *) comment: PChar; (* pointer to zero-terminated comment or Z_NULL *) comm_max: Integer; (* space at comment (only when reading header) *) hcrc: Integer; (* true if there was or will be a header crc *) done: Integer; (* true when done reading gzip header *) end; (* constants *) const Z_NO_FLUSH = 0; Z_PARTIAL_FLUSH = 1; Z_SYNC_FLUSH = 2; Z_FULL_FLUSH = 3; Z_FINISH = 4; Z_BLOCK = 5; Z_TREES = 6; Z_OK = 0; Z_STREAM_END = 1; Z_NEED_DICT = 2; Z_ERRNO = -1; Z_STREAM_ERROR = -2; Z_DATA_ERROR = -3; Z_MEM_ERROR = -4; Z_BUF_ERROR = -5; Z_VERSION_ERROR = -6; Z_NO_COMPRESSION = 0; Z_BEST_SPEED = 1; Z_BEST_COMPRESSION = 9; Z_DEFAULT_COMPRESSION = -1; Z_FILTERED = 1; Z_HUFFMAN_ONLY = 2; Z_RLE = 3; Z_FIXED = 4; Z_DEFAULT_STRATEGY = 0; Z_BINARY = 0; Z_TEXT = 1; Z_ASCII = 1; Z_UNKNOWN = 2; Z_DEFLATED = 8; (* basic functions *) function zlibVersion: PChar; function deflateInit(var strm: z_stream; level: Integer): Integer; function deflate(var strm: z_stream; flush: Integer): Integer; function deflateEnd(var strm: z_stream): Integer; function inflateInit(var strm: z_stream): Integer; function inflate(var strm: z_stream; flush: Integer): Integer; function inflateEnd(var strm: z_stream): Integer; (* advanced functions *) function deflateInit2(var strm: z_stream; level, method, windowBits, memLevel, strategy: Integer): Integer; function deflateSetDictionary(var strm: z_stream; const dictionary: PChar; dictLength: Integer): Integer; function deflateCopy(var dest, source: z_stream): Integer; function deflateReset(var strm: z_stream): Integer; function deflateParams(var strm: z_stream; level, strategy: Integer): Integer; function deflateTune(var strm: z_stream; good_length, max_lazy, nice_length, max_chain: Integer): Integer; function deflateBound(var strm: z_stream; sourceLen: LongInt): LongInt; function deflatePending(var strm: z_stream; var pending: Integer; var bits: Integer): Integer; function deflatePrime(var strm: z_stream; bits, value: Integer): Integer; function deflateSetHeader(var strm: z_stream; head: gz_header): Integer; function inflateInit2(var strm: z_stream; windowBits: Integer): Integer; function inflateSetDictionary(var strm: z_stream; const dictionary: PChar; dictLength: Integer): Integer; function inflateSync(var strm: z_stream): Integer; function inflateCopy(var dest, source: z_stream): Integer; function inflateReset(var strm: z_stream): Integer; function inflateReset2(var strm: z_stream; windowBits: Integer): Integer; function inflatePrime(var strm: z_stream; bits, value: Integer): Integer; function inflateMark(var strm: z_stream): LongInt; function inflateGetHeader(var strm: z_stream; var head: gz_header): Integer; function inflateBackInit(var strm: z_stream; windowBits: Integer; window: PChar): Integer; function inflateBack(var strm: z_stream; in_fn: in_func; in_desc: Pointer; out_fn: out_func; out_desc: Pointer): Integer; function inflateBackEnd(var strm: z_stream): Integer; function zlibCompileFlags: LongInt; (* utility functions *) function compress(dest: PChar; var destLen: LongInt; const source: PChar; sourceLen: LongInt): Integer; function compress2(dest: PChar; var destLen: LongInt; const source: PChar; sourceLen: LongInt; level: Integer): Integer; function compressBound(sourceLen: LongInt): LongInt; function uncompress(dest: PChar; var destLen: LongInt; const source: PChar; sourceLen: LongInt): Integer; (* checksum functions *) function adler32(adler: LongInt; const buf: PChar; len: Integer): LongInt; function adler32_combine(adler1, adler2, len2: LongInt): LongInt; function crc32(crc: LongInt; const buf: PChar; len: Integer): LongInt; function crc32_combine(crc1, crc2, len2: LongInt): LongInt; (* various hacks, don't look :) *) function deflateInit_(var strm: z_stream; level: Integer; const version: PChar; stream_size: Integer): Integer; function inflateInit_(var strm: z_stream; const version: PChar; stream_size: Integer): Integer; function deflateInit2_(var strm: z_stream; level, method, windowBits, memLevel, strategy: Integer; const version: PChar; stream_size: Integer): Integer; function inflateInit2_(var strm: z_stream; windowBits: Integer; const version: PChar; stream_size: Integer): Integer; function inflateBackInit_(var strm: z_stream; windowBits: Integer; window: PChar; const version: PChar; stream_size: Integer): Integer; implementation {$L adler32.obj} {$L compress.obj} {$L crc32.obj} {$L deflate.obj} {$L infback.obj} {$L inffast.obj} {$L inflate.obj} {$L inftrees.obj} {$L trees.obj} {$L uncompr.obj} {$L zutil.obj} function adler32; external; function adler32_combine; external; function compress; external; function compress2; external; function compressBound; external; function crc32; external; function crc32_combine; external; function deflate; external; function deflateBound; external; function deflateCopy; external; function deflateEnd; external; function deflateInit_; external; function deflateInit2_; external; function deflateParams; external; function deflatePending; external; function deflatePrime; external; function deflateReset; external; function deflateSetDictionary; external; function deflateSetHeader; external; function deflateTune; external; function inflate; external; function inflateBack; external; function inflateBackEnd; external; function inflateBackInit_; external; function inflateCopy; external; function inflateEnd; external; function inflateGetHeader; external; function inflateInit_; external; function inflateInit2_; external; function inflateMark; external; function inflatePrime; external; function inflateReset; external; function inflateReset2; external; function inflateSetDictionary; external; function inflateSync; external; function uncompress; external; function zlibCompileFlags; external; function zlibVersion; external; function deflateInit(var strm: z_stream; level: Integer): Integer; begin Result := deflateInit_(strm, level, ZLIB_VERSION, sizeof(z_stream)); end; function deflateInit2(var strm: z_stream; level, method, windowBits, memLevel, strategy: Integer): Integer; begin Result := deflateInit2_(strm, level, method, windowBits, memLevel, strategy, ZLIB_VERSION, sizeof(z_stream)); end; function inflateInit(var strm: z_stream): Integer; begin Result := inflateInit_(strm, ZLIB_VERSION, sizeof(z_stream)); end; function inflateInit2(var strm: z_stream; windowBits: Integer): Integer; begin Result := inflateInit2_(strm, windowBits, ZLIB_VERSION, sizeof(z_stream)); end; function inflateBackInit(var strm: z_stream; windowBits: Integer; window: PChar): Integer; begin Result := inflateBackInit_(strm, windowBits, window, ZLIB_VERSION, sizeof(z_stream)); end; function _malloc(Size: Integer): Pointer; cdecl; begin GetMem(Result, Size); end; procedure _free(Block: Pointer); cdecl; begin FreeMem(Block); end; procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl; begin FillChar(P^, count, B); end; procedure _memcpy(dest, source: Pointer; count: Integer); cdecl; begin Move(source^, dest^, count); end; end. tcl8.6.5/compat/zlib/contrib/inflate86/0000755000175000017500000000000012665173607017255 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/inflate86/inffast.S0000644000175000017500000012353212663653131021032 0ustar sergeisergei/* * inffast.S is a hand tuned assembler version of: * * inffast.c -- fast decoding * Copyright (C) 1995-2003 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Copyright (C) 2003 Chris Anderson * Please use the copyright conditions above. * * This version (Jan-23-2003) of inflate_fast was coded and tested under * GNU/Linux on a pentium 3, using the gcc-3.2 compiler distribution. On that * machine, I found that gzip style archives decompressed about 20% faster than * the gcc-3.2 -O3 -fomit-frame-pointer compiled version. Your results will * depend on how large of a buffer is used for z_stream.next_in & next_out * (8K-32K worked best for my 256K cpu cache) and how much overhead there is in * stream processing I/O and crc32/addler32. In my case, this routine used * 70% of the cpu time and crc32 used 20%. * * I am confident that this version will work in the general case, but I have * not tested a wide variety of datasets or a wide variety of platforms. * * Jan-24-2003 -- Added -DUSE_MMX define for slightly faster inflating. * It should be a runtime flag instead of compile time flag... * * Jan-26-2003 -- Added runtime check for MMX support with cpuid instruction. * With -DUSE_MMX, only MMX code is compiled. With -DNO_MMX, only non-MMX code * is compiled. Without either option, runtime detection is enabled. Runtime * detection should work on all modern cpus and the recomended algorithm (flip * ID bit on eflags and then use the cpuid instruction) is used in many * multimedia applications. Tested under win2k with gcc-2.95 and gas-2.12 * distributed with cygwin3. Compiling with gcc-2.95 -c inffast.S -o * inffast.obj generates a COFF object which can then be linked with MSVC++ * compiled code. Tested under FreeBSD 4.7 with gcc-2.95. * * Jan-28-2003 -- Tested Athlon XP... MMX mode is slower than no MMX (and * slower than compiler generated code). Adjusted cpuid check to use the MMX * code only for Pentiums < P4 until I have more data on the P4. Speed * improvment is only about 15% on the Athlon when compared with code generated * with MSVC++. Not sure yet, but I think the P4 will also be slower using the * MMX mode because many of it's x86 ALU instructions execute in .5 cycles and * have less latency than MMX ops. Added code to buffer the last 11 bytes of * the input stream since the MMX code grabs bits in chunks of 32, which * differs from the inffast.c algorithm. I don't think there would have been * read overruns where a page boundary was crossed (a segfault), but there * could have been overruns when next_in ends on unaligned memory (unintialized * memory read). * * Mar-13-2003 -- P4 MMX is slightly slower than P4 NO_MMX. I created a C * version of the non-MMX code so that it doesn't depend on zstrm and zstate * structure offsets which are hard coded in this file. This was last tested * with zlib-1.2.0 which is currently in beta testing, newer versions of this * and inffas86.c can be found at http://www.eetbeetee.com/zlib/ and * http://www.charm.net/~christop/zlib/ */ /* * if you have underscore linking problems (_inflate_fast undefined), try * using -DGAS_COFF */ #if ! defined( GAS_COFF ) && ! defined( GAS_ELF ) #if defined( WIN32 ) || defined( __CYGWIN__ ) #define GAS_COFF /* windows object format */ #else #define GAS_ELF #endif #endif /* ! GAS_COFF && ! GAS_ELF */ #if defined( GAS_COFF ) /* coff externals have underscores */ #define inflate_fast _inflate_fast #define inflate_fast_use_mmx _inflate_fast_use_mmx #endif /* GAS_COFF */ .file "inffast.S" .globl inflate_fast .text .align 4,0 .L_invalid_literal_length_code_msg: .string "invalid literal/length code" .align 4,0 .L_invalid_distance_code_msg: .string "invalid distance code" .align 4,0 .L_invalid_distance_too_far_msg: .string "invalid distance too far back" #if ! defined( NO_MMX ) .align 4,0 .L_mask: /* mask[N] = ( 1 << N ) - 1 */ .long 0 .long 1 .long 3 .long 7 .long 15 .long 31 .long 63 .long 127 .long 255 .long 511 .long 1023 .long 2047 .long 4095 .long 8191 .long 16383 .long 32767 .long 65535 .long 131071 .long 262143 .long 524287 .long 1048575 .long 2097151 .long 4194303 .long 8388607 .long 16777215 .long 33554431 .long 67108863 .long 134217727 .long 268435455 .long 536870911 .long 1073741823 .long 2147483647 .long 4294967295 #endif /* NO_MMX */ .text /* * struct z_stream offsets, in zlib.h */ #define next_in_strm 0 /* strm->next_in */ #define avail_in_strm 4 /* strm->avail_in */ #define next_out_strm 12 /* strm->next_out */ #define avail_out_strm 16 /* strm->avail_out */ #define msg_strm 24 /* strm->msg */ #define state_strm 28 /* strm->state */ /* * struct inflate_state offsets, in inflate.h */ #define mode_state 0 /* state->mode */ #define wsize_state 32 /* state->wsize */ #define write_state 40 /* state->write */ #define window_state 44 /* state->window */ #define hold_state 48 /* state->hold */ #define bits_state 52 /* state->bits */ #define lencode_state 68 /* state->lencode */ #define distcode_state 72 /* state->distcode */ #define lenbits_state 76 /* state->lenbits */ #define distbits_state 80 /* state->distbits */ /* * inflate_fast's activation record */ #define local_var_size 64 /* how much local space for vars */ #define strm_sp 88 /* first arg: z_stream * (local_var_size + 24) */ #define start_sp 92 /* second arg: unsigned int (local_var_size + 28) */ /* * offsets for local vars on stack */ #define out 60 /* unsigned char* */ #define window 56 /* unsigned char* */ #define wsize 52 /* unsigned int */ #define write 48 /* unsigned int */ #define in 44 /* unsigned char* */ #define beg 40 /* unsigned char* */ #define buf 28 /* char[ 12 ] */ #define len 24 /* unsigned int */ #define last 20 /* unsigned char* */ #define end 16 /* unsigned char* */ #define dcode 12 /* code* */ #define lcode 8 /* code* */ #define dmask 4 /* unsigned int */ #define lmask 0 /* unsigned int */ /* * typedef enum inflate_mode consts, in inflate.h */ #define INFLATE_MODE_TYPE 11 /* state->mode flags enum-ed in inflate.h */ #define INFLATE_MODE_BAD 26 #if ! defined( USE_MMX ) && ! defined( NO_MMX ) #define RUN_TIME_MMX #define CHECK_MMX 1 #define DO_USE_MMX 2 #define DONT_USE_MMX 3 .globl inflate_fast_use_mmx .data .align 4,0 inflate_fast_use_mmx: /* integer flag for run time control 1=check,2=mmx,3=no */ .long CHECK_MMX #if defined( GAS_ELF ) /* elf info */ .type inflate_fast_use_mmx,@object .size inflate_fast_use_mmx,4 #endif #endif /* RUN_TIME_MMX */ #if defined( GAS_COFF ) /* coff info: scl 2 = extern, type 32 = function */ .def inflate_fast; .scl 2; .type 32; .endef #endif .text .align 32,0x90 inflate_fast: pushl %edi pushl %esi pushl %ebp pushl %ebx pushf /* save eflags (strm_sp, state_sp assumes this is 32 bits) */ subl $local_var_size, %esp cld #define strm_r %esi #define state_r %edi movl strm_sp(%esp), strm_r movl state_strm(strm_r), state_r /* in = strm->next_in; * out = strm->next_out; * last = in + strm->avail_in - 11; * beg = out - (start - strm->avail_out); * end = out + (strm->avail_out - 257); */ movl avail_in_strm(strm_r), %edx movl next_in_strm(strm_r), %eax addl %eax, %edx /* avail_in += next_in */ subl $11, %edx /* avail_in -= 11 */ movl %eax, in(%esp) movl %edx, last(%esp) movl start_sp(%esp), %ebp movl avail_out_strm(strm_r), %ecx movl next_out_strm(strm_r), %ebx subl %ecx, %ebp /* start -= avail_out */ negl %ebp /* start = -start */ addl %ebx, %ebp /* start += next_out */ subl $257, %ecx /* avail_out -= 257 */ addl %ebx, %ecx /* avail_out += out */ movl %ebx, out(%esp) movl %ebp, beg(%esp) movl %ecx, end(%esp) /* wsize = state->wsize; * write = state->write; * window = state->window; * hold = state->hold; * bits = state->bits; * lcode = state->lencode; * dcode = state->distcode; * lmask = ( 1 << state->lenbits ) - 1; * dmask = ( 1 << state->distbits ) - 1; */ movl lencode_state(state_r), %eax movl distcode_state(state_r), %ecx movl %eax, lcode(%esp) movl %ecx, dcode(%esp) movl $1, %eax movl lenbits_state(state_r), %ecx shll %cl, %eax decl %eax movl %eax, lmask(%esp) movl $1, %eax movl distbits_state(state_r), %ecx shll %cl, %eax decl %eax movl %eax, dmask(%esp) movl wsize_state(state_r), %eax movl write_state(state_r), %ecx movl window_state(state_r), %edx movl %eax, wsize(%esp) movl %ecx, write(%esp) movl %edx, window(%esp) movl hold_state(state_r), %ebp movl bits_state(state_r), %ebx #undef strm_r #undef state_r #define in_r %esi #define from_r %esi #define out_r %edi movl in(%esp), in_r movl last(%esp), %ecx cmpl in_r, %ecx ja .L_align_long /* if in < last */ addl $11, %ecx /* ecx = &in[ avail_in ] */ subl in_r, %ecx /* ecx = avail_in */ movl $12, %eax subl %ecx, %eax /* eax = 12 - avail_in */ leal buf(%esp), %edi rep movsb /* memcpy( buf, in, avail_in ) */ movl %eax, %ecx xorl %eax, %eax rep stosb /* memset( &buf[ avail_in ], 0, 12 - avail_in ) */ leal buf(%esp), in_r /* in = buf */ movl in_r, last(%esp) /* last = in, do just one iteration */ jmp .L_is_aligned /* align in_r on long boundary */ .L_align_long: testl $3, in_r jz .L_is_aligned xorl %eax, %eax movb (in_r), %al incl in_r movl %ebx, %ecx addl $8, %ebx shll %cl, %eax orl %eax, %ebp jmp .L_align_long .L_is_aligned: movl out(%esp), out_r #if defined( NO_MMX ) jmp .L_do_loop #endif #if defined( USE_MMX ) jmp .L_init_mmx #endif /*** Runtime MMX check ***/ #if defined( RUN_TIME_MMX ) .L_check_mmx: cmpl $DO_USE_MMX, inflate_fast_use_mmx je .L_init_mmx ja .L_do_loop /* > 2 */ pushl %eax pushl %ebx pushl %ecx pushl %edx pushf movl (%esp), %eax /* copy eflags to eax */ xorl $0x200000, (%esp) /* try toggling ID bit of eflags (bit 21) * to see if cpu supports cpuid... * ID bit method not supported by NexGen but * bios may load a cpuid instruction and * cpuid may be disabled on Cyrix 5-6x86 */ popf pushf popl %edx /* copy new eflags to edx */ xorl %eax, %edx /* test if ID bit is flipped */ jz .L_dont_use_mmx /* not flipped if zero */ xorl %eax, %eax cpuid cmpl $0x756e6547, %ebx /* check for GenuineIntel in ebx,ecx,edx */ jne .L_dont_use_mmx cmpl $0x6c65746e, %ecx jne .L_dont_use_mmx cmpl $0x49656e69, %edx jne .L_dont_use_mmx movl $1, %eax cpuid /* get cpu features */ shrl $8, %eax andl $15, %eax cmpl $6, %eax /* check for Pentium family, is 0xf for P4 */ jne .L_dont_use_mmx testl $0x800000, %edx /* test if MMX feature is set (bit 23) */ jnz .L_use_mmx jmp .L_dont_use_mmx .L_use_mmx: movl $DO_USE_MMX, inflate_fast_use_mmx jmp .L_check_mmx_pop .L_dont_use_mmx: movl $DONT_USE_MMX, inflate_fast_use_mmx .L_check_mmx_pop: popl %edx popl %ecx popl %ebx popl %eax jmp .L_check_mmx #endif /*** Non-MMX code ***/ #if defined ( NO_MMX ) || defined( RUN_TIME_MMX ) #define hold_r %ebp #define bits_r %bl #define bitslong_r %ebx .align 32,0x90 .L_while_test: /* while (in < last && out < end) */ cmpl out_r, end(%esp) jbe .L_break_loop /* if (out >= end) */ cmpl in_r, last(%esp) jbe .L_break_loop .L_do_loop: /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out * * do { * if (bits < 15) { * hold |= *((unsigned short *)in)++ << bits; * bits += 16 * } * this = lcode[hold & lmask] */ cmpb $15, bits_r ja .L_get_length_code /* if (15 < bits) */ xorl %eax, %eax lodsw /* al = *(ushort *)in++ */ movb bits_r, %cl /* cl = bits, needs it for shifting */ addb $16, bits_r /* bits += 16 */ shll %cl, %eax orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ .L_get_length_code: movl lmask(%esp), %edx /* edx = lmask */ movl lcode(%esp), %ecx /* ecx = lcode */ andl hold_r, %edx /* edx &= hold */ movl (%ecx,%edx,4), %eax /* eax = lcode[hold & lmask] */ .L_dolen: /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out * * dolen: * bits -= this.bits; * hold >>= this.bits */ movb %ah, %cl /* cl = this.bits */ subb %ah, bits_r /* bits -= this.bits */ shrl %cl, hold_r /* hold >>= this.bits */ /* check if op is a literal * if (op == 0) { * PUP(out) = this.val; * } */ testb %al, %al jnz .L_test_for_length_base /* if (op != 0) 45.7% */ shrl $16, %eax /* output this.val char */ stosb jmp .L_while_test .L_test_for_length_base: /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = len * * else if (op & 16) { * len = this.val * op &= 15 * if (op) { * if (op > bits) { * hold |= *((unsigned short *)in)++ << bits; * bits += 16 * } * len += hold & mask[op]; * bits -= op; * hold >>= op; * } */ #define len_r %edx movl %eax, len_r /* len = this */ shrl $16, len_r /* len = this.val */ movb %al, %cl testb $16, %al jz .L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ andb $15, %cl /* op &= 15 */ jz .L_save_len /* if (!op) */ cmpb %cl, bits_r jae .L_add_bits_to_len /* if (op <= bits) */ movb %cl, %ch /* stash op in ch, freeing cl */ xorl %eax, %eax lodsw /* al = *(ushort *)in++ */ movb bits_r, %cl /* cl = bits, needs it for shifting */ addb $16, bits_r /* bits += 16 */ shll %cl, %eax orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ movb %ch, %cl /* move op back to ecx */ .L_add_bits_to_len: movl $1, %eax shll %cl, %eax decl %eax subb %cl, bits_r andl hold_r, %eax /* eax &= hold */ shrl %cl, hold_r addl %eax, len_r /* len += hold & mask[op] */ .L_save_len: movl len_r, len(%esp) /* save len */ #undef len_r .L_decode_distance: /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = dist * * if (bits < 15) { * hold |= *((unsigned short *)in)++ << bits; * bits += 16 * } * this = dcode[hold & dmask]; * dodist: * bits -= this.bits; * hold >>= this.bits; * op = this.op; */ cmpb $15, bits_r ja .L_get_distance_code /* if (15 < bits) */ xorl %eax, %eax lodsw /* al = *(ushort *)in++ */ movb bits_r, %cl /* cl = bits, needs it for shifting */ addb $16, bits_r /* bits += 16 */ shll %cl, %eax orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ .L_get_distance_code: movl dmask(%esp), %edx /* edx = dmask */ movl dcode(%esp), %ecx /* ecx = dcode */ andl hold_r, %edx /* edx &= hold */ movl (%ecx,%edx,4), %eax /* eax = dcode[hold & dmask] */ #define dist_r %edx .L_dodist: movl %eax, dist_r /* dist = this */ shrl $16, dist_r /* dist = this.val */ movb %ah, %cl subb %ah, bits_r /* bits -= this.bits */ shrl %cl, hold_r /* hold >>= this.bits */ /* if (op & 16) { * dist = this.val * op &= 15 * if (op > bits) { * hold |= *((unsigned short *)in)++ << bits; * bits += 16 * } * dist += hold & mask[op]; * bits -= op; * hold >>= op; */ movb %al, %cl /* cl = this.op */ testb $16, %al /* if ((op & 16) == 0) */ jz .L_test_for_second_level_dist andb $15, %cl /* op &= 15 */ jz .L_check_dist_one cmpb %cl, bits_r jae .L_add_bits_to_dist /* if (op <= bits) 97.6% */ movb %cl, %ch /* stash op in ch, freeing cl */ xorl %eax, %eax lodsw /* al = *(ushort *)in++ */ movb bits_r, %cl /* cl = bits, needs it for shifting */ addb $16, bits_r /* bits += 16 */ shll %cl, %eax orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ movb %ch, %cl /* move op back to ecx */ .L_add_bits_to_dist: movl $1, %eax shll %cl, %eax decl %eax /* (1 << op) - 1 */ subb %cl, bits_r andl hold_r, %eax /* eax &= hold */ shrl %cl, hold_r addl %eax, dist_r /* dist += hold & ((1 << op) - 1) */ jmp .L_check_window .L_check_window: /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist * %ecx = nbytes * * nbytes = out - beg; * if (dist <= nbytes) { * from = out - dist; * do { * PUP(out) = PUP(from); * } while (--len > 0) { * } */ movl in_r, in(%esp) /* save in so from can use it's reg */ movl out_r, %eax subl beg(%esp), %eax /* nbytes = out - beg */ cmpl dist_r, %eax jb .L_clip_window /* if (dist > nbytes) 4.2% */ movl len(%esp), %ecx movl out_r, from_r subl dist_r, from_r /* from = out - dist */ subl $3, %ecx movb (from_r), %al movb %al, (out_r) movb 1(from_r), %al movb 2(from_r), %dl addl $3, from_r movb %al, 1(out_r) movb %dl, 2(out_r) addl $3, out_r rep movsb movl in(%esp), in_r /* move in back to %esi, toss from */ jmp .L_while_test .align 16,0x90 .L_check_dist_one: cmpl $1, dist_r jne .L_check_window cmpl out_r, beg(%esp) je .L_check_window decl out_r movl len(%esp), %ecx movb (out_r), %al subl $3, %ecx movb %al, 1(out_r) movb %al, 2(out_r) movb %al, 3(out_r) addl $4, out_r rep stosb jmp .L_while_test .align 16,0x90 .L_test_for_second_level_length: /* else if ((op & 64) == 0) { * this = lcode[this.val + (hold & mask[op])]; * } */ testb $64, %al jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ movl $1, %eax shll %cl, %eax decl %eax andl hold_r, %eax /* eax &= hold */ addl %edx, %eax /* eax += this.val */ movl lcode(%esp), %edx /* edx = lcode */ movl (%edx,%eax,4), %eax /* eax = lcode[val + (hold&mask[op])] */ jmp .L_dolen .align 16,0x90 .L_test_for_second_level_dist: /* else if ((op & 64) == 0) { * this = dcode[this.val + (hold & mask[op])]; * } */ testb $64, %al jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ movl $1, %eax shll %cl, %eax decl %eax andl hold_r, %eax /* eax &= hold */ addl %edx, %eax /* eax += this.val */ movl dcode(%esp), %edx /* edx = dcode */ movl (%edx,%eax,4), %eax /* eax = dcode[val + (hold&mask[op])] */ jmp .L_dodist .align 16,0x90 .L_clip_window: /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist * %ecx = nbytes * * else { * if (dist > wsize) { * invalid distance * } * from = window; * nbytes = dist - nbytes; * if (write == 0) { * from += wsize - nbytes; */ #define nbytes_r %ecx movl %eax, nbytes_r movl wsize(%esp), %eax /* prepare for dist compare */ negl nbytes_r /* nbytes = -nbytes */ movl window(%esp), from_r /* from = window */ cmpl dist_r, %eax jb .L_invalid_distance_too_far /* if (dist > wsize) */ addl dist_r, nbytes_r /* nbytes = dist - nbytes */ cmpl $0, write(%esp) jne .L_wrap_around_window /* if (write != 0) */ subl nbytes_r, %eax addl %eax, from_r /* from += wsize - nbytes */ /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist * %ecx = nbytes, %eax = len * * if (nbytes < len) { * len -= nbytes; * do { * PUP(out) = PUP(from); * } while (--nbytes); * from = out - dist; * } * } */ #define len_r %eax movl len(%esp), len_r cmpl nbytes_r, len_r jbe .L_do_copy1 /* if (nbytes >= len) */ subl nbytes_r, len_r /* len -= nbytes */ rep movsb movl out_r, from_r subl dist_r, from_r /* from = out - dist */ jmp .L_do_copy1 cmpl nbytes_r, len_r jbe .L_do_copy1 /* if (nbytes >= len) */ subl nbytes_r, len_r /* len -= nbytes */ rep movsb movl out_r, from_r subl dist_r, from_r /* from = out - dist */ jmp .L_do_copy1 .L_wrap_around_window: /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist * %ecx = nbytes, %eax = write, %eax = len * * else if (write < nbytes) { * from += wsize + write - nbytes; * nbytes -= write; * if (nbytes < len) { * len -= nbytes; * do { * PUP(out) = PUP(from); * } while (--nbytes); * from = window; * nbytes = write; * if (nbytes < len) { * len -= nbytes; * do { * PUP(out) = PUP(from); * } while(--nbytes); * from = out - dist; * } * } * } */ #define write_r %eax movl write(%esp), write_r cmpl write_r, nbytes_r jbe .L_contiguous_in_window /* if (write >= nbytes) */ addl wsize(%esp), from_r addl write_r, from_r subl nbytes_r, from_r /* from += wsize + write - nbytes */ subl write_r, nbytes_r /* nbytes -= write */ #undef write_r movl len(%esp), len_r cmpl nbytes_r, len_r jbe .L_do_copy1 /* if (nbytes >= len) */ subl nbytes_r, len_r /* len -= nbytes */ rep movsb movl window(%esp), from_r /* from = window */ movl write(%esp), nbytes_r /* nbytes = write */ cmpl nbytes_r, len_r jbe .L_do_copy1 /* if (nbytes >= len) */ subl nbytes_r, len_r /* len -= nbytes */ rep movsb movl out_r, from_r subl dist_r, from_r /* from = out - dist */ jmp .L_do_copy1 .L_contiguous_in_window: /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist * %ecx = nbytes, %eax = write, %eax = len * * else { * from += write - nbytes; * if (nbytes < len) { * len -= nbytes; * do { * PUP(out) = PUP(from); * } while (--nbytes); * from = out - dist; * } * } */ #define write_r %eax addl write_r, from_r subl nbytes_r, from_r /* from += write - nbytes */ #undef write_r movl len(%esp), len_r cmpl nbytes_r, len_r jbe .L_do_copy1 /* if (nbytes >= len) */ subl nbytes_r, len_r /* len -= nbytes */ rep movsb movl out_r, from_r subl dist_r, from_r /* from = out - dist */ .L_do_copy1: /* regs: %esi = from, %esi = in, %ebp = hold, %bl = bits, %edi = out * %eax = len * * while (len > 0) { * PUP(out) = PUP(from); * len--; * } * } * } while (in < last && out < end); */ #undef nbytes_r #define in_r %esi movl len_r, %ecx rep movsb movl in(%esp), in_r /* move in back to %esi, toss from */ jmp .L_while_test #undef len_r #undef dist_r #endif /* NO_MMX || RUN_TIME_MMX */ /*** MMX code ***/ #if defined( USE_MMX ) || defined( RUN_TIME_MMX ) .align 32,0x90 .L_init_mmx: emms #undef bits_r #undef bitslong_r #define bitslong_r %ebp #define hold_mm %mm0 movd %ebp, hold_mm movl %ebx, bitslong_r #define used_mm %mm1 #define dmask2_mm %mm2 #define lmask2_mm %mm3 #define lmask_mm %mm4 #define dmask_mm %mm5 #define tmp_mm %mm6 movd lmask(%esp), lmask_mm movq lmask_mm, lmask2_mm movd dmask(%esp), dmask_mm movq dmask_mm, dmask2_mm pxor used_mm, used_mm movl lcode(%esp), %ebx /* ebx = lcode */ jmp .L_do_loop_mmx .align 32,0x90 .L_while_test_mmx: /* while (in < last && out < end) */ cmpl out_r, end(%esp) jbe .L_break_loop /* if (out >= end) */ cmpl in_r, last(%esp) jbe .L_break_loop .L_do_loop_mmx: psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ cmpl $32, bitslong_r ja .L_get_length_code_mmx /* if (32 < bits) */ movd bitslong_r, tmp_mm movd (in_r), %mm7 addl $4, in_r psllq tmp_mm, %mm7 addl $32, bitslong_r por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ .L_get_length_code_mmx: pand hold_mm, lmask_mm movd lmask_mm, %eax movq lmask2_mm, lmask_mm movl (%ebx,%eax,4), %eax /* eax = lcode[hold & lmask] */ .L_dolen_mmx: movzbl %ah, %ecx /* ecx = this.bits */ movd %ecx, used_mm subl %ecx, bitslong_r /* bits -= this.bits */ testb %al, %al jnz .L_test_for_length_base_mmx /* if (op != 0) 45.7% */ shrl $16, %eax /* output this.val char */ stosb jmp .L_while_test_mmx .L_test_for_length_base_mmx: #define len_r %edx movl %eax, len_r /* len = this */ shrl $16, len_r /* len = this.val */ testb $16, %al jz .L_test_for_second_level_length_mmx /* if ((op & 16) == 0) 8% */ andl $15, %eax /* op &= 15 */ jz .L_decode_distance_mmx /* if (!op) */ psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ movd %eax, used_mm movd hold_mm, %ecx subl %eax, bitslong_r andl .L_mask(,%eax,4), %ecx addl %ecx, len_r /* len += hold & mask[op] */ .L_decode_distance_mmx: psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ cmpl $32, bitslong_r ja .L_get_dist_code_mmx /* if (32 < bits) */ movd bitslong_r, tmp_mm movd (in_r), %mm7 addl $4, in_r psllq tmp_mm, %mm7 addl $32, bitslong_r por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ .L_get_dist_code_mmx: movl dcode(%esp), %ebx /* ebx = dcode */ pand hold_mm, dmask_mm movd dmask_mm, %eax movq dmask2_mm, dmask_mm movl (%ebx,%eax,4), %eax /* eax = dcode[hold & lmask] */ .L_dodist_mmx: #define dist_r %ebx movzbl %ah, %ecx /* ecx = this.bits */ movl %eax, dist_r shrl $16, dist_r /* dist = this.val */ subl %ecx, bitslong_r /* bits -= this.bits */ movd %ecx, used_mm testb $16, %al /* if ((op & 16) == 0) */ jz .L_test_for_second_level_dist_mmx andl $15, %eax /* op &= 15 */ jz .L_check_dist_one_mmx .L_add_bits_to_dist_mmx: psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ movd %eax, used_mm /* save bit length of current op */ movd hold_mm, %ecx /* get the next bits on input stream */ subl %eax, bitslong_r /* bits -= op bits */ andl .L_mask(,%eax,4), %ecx /* ecx = hold & mask[op] */ addl %ecx, dist_r /* dist += hold & mask[op] */ .L_check_window_mmx: movl in_r, in(%esp) /* save in so from can use it's reg */ movl out_r, %eax subl beg(%esp), %eax /* nbytes = out - beg */ cmpl dist_r, %eax jb .L_clip_window_mmx /* if (dist > nbytes) 4.2% */ movl len_r, %ecx movl out_r, from_r subl dist_r, from_r /* from = out - dist */ subl $3, %ecx movb (from_r), %al movb %al, (out_r) movb 1(from_r), %al movb 2(from_r), %dl addl $3, from_r movb %al, 1(out_r) movb %dl, 2(out_r) addl $3, out_r rep movsb movl in(%esp), in_r /* move in back to %esi, toss from */ movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ jmp .L_while_test_mmx .align 16,0x90 .L_check_dist_one_mmx: cmpl $1, dist_r jne .L_check_window_mmx cmpl out_r, beg(%esp) je .L_check_window_mmx decl out_r movl len_r, %ecx movb (out_r), %al subl $3, %ecx movb %al, 1(out_r) movb %al, 2(out_r) movb %al, 3(out_r) addl $4, out_r rep stosb movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ jmp .L_while_test_mmx .align 16,0x90 .L_test_for_second_level_length_mmx: testb $64, %al jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ andl $15, %eax psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ movd hold_mm, %ecx andl .L_mask(,%eax,4), %ecx addl len_r, %ecx movl (%ebx,%ecx,4), %eax /* eax = lcode[hold & lmask] */ jmp .L_dolen_mmx .align 16,0x90 .L_test_for_second_level_dist_mmx: testb $64, %al jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ andl $15, %eax psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ movd hold_mm, %ecx andl .L_mask(,%eax,4), %ecx movl dcode(%esp), %eax /* ecx = dcode */ addl dist_r, %ecx movl (%eax,%ecx,4), %eax /* eax = lcode[hold & lmask] */ jmp .L_dodist_mmx .align 16,0x90 .L_clip_window_mmx: #define nbytes_r %ecx movl %eax, nbytes_r movl wsize(%esp), %eax /* prepare for dist compare */ negl nbytes_r /* nbytes = -nbytes */ movl window(%esp), from_r /* from = window */ cmpl dist_r, %eax jb .L_invalid_distance_too_far /* if (dist > wsize) */ addl dist_r, nbytes_r /* nbytes = dist - nbytes */ cmpl $0, write(%esp) jne .L_wrap_around_window_mmx /* if (write != 0) */ subl nbytes_r, %eax addl %eax, from_r /* from += wsize - nbytes */ cmpl nbytes_r, len_r jbe .L_do_copy1_mmx /* if (nbytes >= len) */ subl nbytes_r, len_r /* len -= nbytes */ rep movsb movl out_r, from_r subl dist_r, from_r /* from = out - dist */ jmp .L_do_copy1_mmx cmpl nbytes_r, len_r jbe .L_do_copy1_mmx /* if (nbytes >= len) */ subl nbytes_r, len_r /* len -= nbytes */ rep movsb movl out_r, from_r subl dist_r, from_r /* from = out - dist */ jmp .L_do_copy1_mmx .L_wrap_around_window_mmx: #define write_r %eax movl write(%esp), write_r cmpl write_r, nbytes_r jbe .L_contiguous_in_window_mmx /* if (write >= nbytes) */ addl wsize(%esp), from_r addl write_r, from_r subl nbytes_r, from_r /* from += wsize + write - nbytes */ subl write_r, nbytes_r /* nbytes -= write */ #undef write_r cmpl nbytes_r, len_r jbe .L_do_copy1_mmx /* if (nbytes >= len) */ subl nbytes_r, len_r /* len -= nbytes */ rep movsb movl window(%esp), from_r /* from = window */ movl write(%esp), nbytes_r /* nbytes = write */ cmpl nbytes_r, len_r jbe .L_do_copy1_mmx /* if (nbytes >= len) */ subl nbytes_r, len_r /* len -= nbytes */ rep movsb movl out_r, from_r subl dist_r, from_r /* from = out - dist */ jmp .L_do_copy1_mmx .L_contiguous_in_window_mmx: #define write_r %eax addl write_r, from_r subl nbytes_r, from_r /* from += write - nbytes */ #undef write_r cmpl nbytes_r, len_r jbe .L_do_copy1_mmx /* if (nbytes >= len) */ subl nbytes_r, len_r /* len -= nbytes */ rep movsb movl out_r, from_r subl dist_r, from_r /* from = out - dist */ .L_do_copy1_mmx: #undef nbytes_r #define in_r %esi movl len_r, %ecx rep movsb movl in(%esp), in_r /* move in back to %esi, toss from */ movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ jmp .L_while_test_mmx #undef hold_r #undef bitslong_r #endif /* USE_MMX || RUN_TIME_MMX */ /*** USE_MMX, NO_MMX, and RUNTIME_MMX from here on ***/ .L_invalid_distance_code: /* else { * strm->msg = "invalid distance code"; * state->mode = BAD; * } */ movl $.L_invalid_distance_code_msg, %ecx movl $INFLATE_MODE_BAD, %edx jmp .L_update_stream_state .L_test_for_end_of_block: /* else if (op & 32) { * state->mode = TYPE; * break; * } */ testb $32, %al jz .L_invalid_literal_length_code /* if ((op & 32) == 0) */ movl $0, %ecx movl $INFLATE_MODE_TYPE, %edx jmp .L_update_stream_state .L_invalid_literal_length_code: /* else { * strm->msg = "invalid literal/length code"; * state->mode = BAD; * } */ movl $.L_invalid_literal_length_code_msg, %ecx movl $INFLATE_MODE_BAD, %edx jmp .L_update_stream_state .L_invalid_distance_too_far: /* strm->msg = "invalid distance too far back"; * state->mode = BAD; */ movl in(%esp), in_r /* from_r has in's reg, put in back */ movl $.L_invalid_distance_too_far_msg, %ecx movl $INFLATE_MODE_BAD, %edx jmp .L_update_stream_state .L_update_stream_state: /* set strm->msg = %ecx, strm->state->mode = %edx */ movl strm_sp(%esp), %eax testl %ecx, %ecx /* if (msg != NULL) */ jz .L_skip_msg movl %ecx, msg_strm(%eax) /* strm->msg = msg */ .L_skip_msg: movl state_strm(%eax), %eax /* state = strm->state */ movl %edx, mode_state(%eax) /* state->mode = edx (BAD | TYPE) */ jmp .L_break_loop .align 32,0x90 .L_break_loop: /* * Regs: * * bits = %ebp when mmx, and in %ebx when non-mmx * hold = %hold_mm when mmx, and in %ebp when non-mmx * in = %esi * out = %edi */ #if defined( USE_MMX ) || defined( RUN_TIME_MMX ) #if defined( RUN_TIME_MMX ) cmpl $DO_USE_MMX, inflate_fast_use_mmx jne .L_update_next_in #endif /* RUN_TIME_MMX */ movl %ebp, %ebx .L_update_next_in: #endif #define strm_r %eax #define state_r %edx /* len = bits >> 3; * in -= len; * bits -= len << 3; * hold &= (1U << bits) - 1; * state->hold = hold; * state->bits = bits; * strm->next_in = in; * strm->next_out = out; */ movl strm_sp(%esp), strm_r movl %ebx, %ecx movl state_strm(strm_r), state_r shrl $3, %ecx subl %ecx, in_r shll $3, %ecx subl %ecx, %ebx movl out_r, next_out_strm(strm_r) movl %ebx, bits_state(state_r) movl %ebx, %ecx leal buf(%esp), %ebx cmpl %ebx, last(%esp) jne .L_buf_not_used /* if buf != last */ subl %ebx, in_r /* in -= buf */ movl next_in_strm(strm_r), %ebx movl %ebx, last(%esp) /* last = strm->next_in */ addl %ebx, in_r /* in += strm->next_in */ movl avail_in_strm(strm_r), %ebx subl $11, %ebx addl %ebx, last(%esp) /* last = &strm->next_in[ avail_in - 11 ] */ .L_buf_not_used: movl in_r, next_in_strm(strm_r) movl $1, %ebx shll %cl, %ebx decl %ebx #if defined( USE_MMX ) || defined( RUN_TIME_MMX ) #if defined( RUN_TIME_MMX ) cmpl $DO_USE_MMX, inflate_fast_use_mmx jne .L_update_hold #endif /* RUN_TIME_MMX */ psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ movd hold_mm, %ebp emms .L_update_hold: #endif /* USE_MMX || RUN_TIME_MMX */ andl %ebx, %ebp movl %ebp, hold_state(state_r) #define last_r %ebx /* strm->avail_in = in < last ? 11 + (last - in) : 11 - (in - last) */ movl last(%esp), last_r cmpl in_r, last_r jbe .L_last_is_smaller /* if (in >= last) */ subl in_r, last_r /* last -= in */ addl $11, last_r /* last += 11 */ movl last_r, avail_in_strm(strm_r) jmp .L_fixup_out .L_last_is_smaller: subl last_r, in_r /* in -= last */ negl in_r /* in = -in */ addl $11, in_r /* in += 11 */ movl in_r, avail_in_strm(strm_r) #undef last_r #define end_r %ebx .L_fixup_out: /* strm->avail_out = out < end ? 257 + (end - out) : 257 - (out - end)*/ movl end(%esp), end_r cmpl out_r, end_r jbe .L_end_is_smaller /* if (out >= end) */ subl out_r, end_r /* end -= out */ addl $257, end_r /* end += 257 */ movl end_r, avail_out_strm(strm_r) jmp .L_done .L_end_is_smaller: subl end_r, out_r /* out -= end */ negl out_r /* out = -out */ addl $257, out_r /* out += 257 */ movl out_r, avail_out_strm(strm_r) #undef end_r #undef strm_r #undef state_r .L_done: addl $local_var_size, %esp popf popl %ebx popl %ebp popl %esi popl %edi ret #if defined( GAS_ELF ) /* elf info */ .type inflate_fast,@function .size inflate_fast,.-inflate_fast #endif tcl8.6.5/compat/zlib/contrib/inflate86/inffas86.c0000644000175000017500000011724012663653206021046 0ustar sergeisergei/* inffas86.c is a hand tuned assembler version of * * inffast.c -- fast decoding * Copyright (C) 1995-2003 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Copyright (C) 2003 Chris Anderson * Please use the copyright conditions above. * * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also * slightly quicker on x86 systems because, instead of using rep movsb to copy * data, it uses rep movsw, which moves data in 2-byte chunks instead of single * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates * from http://fedora.linux.duke.edu/fc1_x86_64 * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, * when decompressing mozilla-source-1.3.tar.gz. * * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at * the moment. I have successfully compiled and tested this code with gcc2.96, * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX * enabled. I will attempt to merge the MMX code into this version. Newer * versions of this and inffast.S can be found at * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" /* Mark Adler's comments from inffast.c: */ /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is available, an end-of-block is encountered, or a data error is encountered. When large enough input and output buffers are supplied to inflate(), for example, a 16K input buffer and a 64K output buffer, more than 95% of the inflate execution time is spent in this routine. Entry assumptions: state->mode == LEN strm->avail_in >= 6 strm->avail_out >= 258 start >= strm->avail_out state->bits < 8 On return, state->mode is one of: LEN -- ran out of enough output space or enough available input TYPE -- reached end of block code, inflate() to interpret next block BAD -- error in block data Notes: - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, and 13 bits for the distance extra. This totals 48 bits, or six bytes. Therefore if strm->avail_in >= 6, then there is enough input to avoid checking for available input while decoding. - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ void inflate_fast(strm, start) z_streamp strm; unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; struct inffast_ar { /* 64 32 x86 x86_64 */ /* ar offset register */ /* 0 0 */ void *esp; /* esp save */ /* 8 4 */ void *ebp; /* ebp save */ /* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ /* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ /* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ /* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ /* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ /* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ /* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ /* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ /* 80 40 */ unsigned long hold; /* edx rdx local strm->hold */ /* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ /* 92 48 */ unsigned wsize; /* window size */ /* 96 52 */ unsigned write; /* window write index */ /*100 56 */ unsigned lmask; /* r12 mask for lcode */ /*104 60 */ unsigned dmask; /* r13 mask for dcode */ /*108 64 */ unsigned len; /* r14 match length */ /*112 68 */ unsigned dist; /* r15 match distance */ /*116 72 */ unsigned status; /* set when state chng*/ } ar; #if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) #define PAD_AVAIL_IN 6 #define PAD_AVAIL_OUT 258 #else #define PAD_AVAIL_IN 5 #define PAD_AVAIL_OUT 257 #endif /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; ar.in = strm->next_in; ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); ar.out = strm->next_out; ar.beg = ar.out - (start - strm->avail_out); ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); ar.wsize = state->wsize; ar.write = state->wnext; ar.window = state->window; ar.hold = state->hold; ar.bits = state->bits; ar.lcode = state->lencode; ar.dcode = state->distcode; ar.lmask = (1U << state->lenbits) - 1; ar.dmask = (1U << state->distbits) - 1; /* decode literals and length/distances until end-of-block or not enough input data or output space */ /* align in on 1/2 hold size boundary */ while (((unsigned long)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { ar.hold += (unsigned long)*ar.in++ << ar.bits; ar.bits += 8; } #if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) __asm__ __volatile__ ( " leaq %0, %%rax\n" " movq %%rbp, 8(%%rax)\n" /* save regs rbp and rsp */ " movq %%rsp, (%%rax)\n" " movq %%rax, %%rsp\n" /* make rsp point to &ar */ " movq 16(%%rsp), %%rsi\n" /* rsi = in */ " movq 32(%%rsp), %%rdi\n" /* rdi = out */ " movq 24(%%rsp), %%r9\n" /* r9 = last */ " movq 48(%%rsp), %%r10\n" /* r10 = end */ " movq 64(%%rsp), %%rbp\n" /* rbp = lcode */ " movq 72(%%rsp), %%r11\n" /* r11 = dcode */ " movq 80(%%rsp), %%rdx\n" /* rdx = hold */ " movl 88(%%rsp), %%ebx\n" /* ebx = bits */ " movl 100(%%rsp), %%r12d\n" /* r12d = lmask */ " movl 104(%%rsp), %%r13d\n" /* r13d = dmask */ /* r14d = len */ /* r15d = dist */ " cld\n" " cmpq %%rdi, %%r10\n" " je .L_one_time\n" /* if only one decode left */ " cmpq %%rsi, %%r9\n" " je .L_one_time\n" " jmp .L_do_loop\n" ".L_one_time:\n" " movq %%r12, %%r8\n" /* r8 = lmask */ " cmpb $32, %%bl\n" " ja .L_get_length_code_one_time\n" " lodsl\n" /* eax = *(uint *)in++ */ " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ " addb $32, %%bl\n" /* bits += 32 */ " shlq %%cl, %%rax\n" " orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ " jmp .L_get_length_code_one_time\n" ".align 32,0x90\n" ".L_while_test:\n" " cmpq %%rdi, %%r10\n" " jbe .L_break_loop\n" " cmpq %%rsi, %%r9\n" " jbe .L_break_loop\n" ".L_do_loop:\n" " movq %%r12, %%r8\n" /* r8 = lmask */ " cmpb $32, %%bl\n" " ja .L_get_length_code\n" /* if (32 < bits) */ " lodsl\n" /* eax = *(uint *)in++ */ " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ " addb $32, %%bl\n" /* bits += 32 */ " shlq %%cl, %%rax\n" " orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ ".L_get_length_code:\n" " andq %%rdx, %%r8\n" /* r8 &= hold */ " movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ " movb %%ah, %%cl\n" /* cl = this.bits */ " subb %%ah, %%bl\n" /* bits -= this.bits */ " shrq %%cl, %%rdx\n" /* hold >>= this.bits */ " testb %%al, %%al\n" " jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ " movq %%r12, %%r8\n" /* r8 = lmask */ " shrl $16, %%eax\n" /* output this.val char */ " stosb\n" ".L_get_length_code_one_time:\n" " andq %%rdx, %%r8\n" /* r8 &= hold */ " movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ ".L_dolen:\n" " movb %%ah, %%cl\n" /* cl = this.bits */ " subb %%ah, %%bl\n" /* bits -= this.bits */ " shrq %%cl, %%rdx\n" /* hold >>= this.bits */ " testb %%al, %%al\n" " jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ " shrl $16, %%eax\n" /* output this.val char */ " stosb\n" " jmp .L_while_test\n" ".align 32,0x90\n" ".L_test_for_length_base:\n" " movl %%eax, %%r14d\n" /* len = this */ " shrl $16, %%r14d\n" /* len = this.val */ " movb %%al, %%cl\n" " testb $16, %%al\n" " jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ " andb $15, %%cl\n" /* op &= 15 */ " jz .L_decode_distance\n" /* if (!op) */ ".L_add_bits_to_len:\n" " subb %%cl, %%bl\n" " xorl %%eax, %%eax\n" " incl %%eax\n" " shll %%cl, %%eax\n" " decl %%eax\n" " andl %%edx, %%eax\n" /* eax &= hold */ " shrq %%cl, %%rdx\n" " addl %%eax, %%r14d\n" /* len += hold & mask[op] */ ".L_decode_distance:\n" " movq %%r13, %%r8\n" /* r8 = dmask */ " cmpb $32, %%bl\n" " ja .L_get_distance_code\n" /* if (32 < bits) */ " lodsl\n" /* eax = *(uint *)in++ */ " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ " addb $32, %%bl\n" /* bits += 32 */ " shlq %%cl, %%rax\n" " orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ ".L_get_distance_code:\n" " andq %%rdx, %%r8\n" /* r8 &= hold */ " movl (%%r11,%%r8,4), %%eax\n" /* eax = dcode[hold & dmask] */ ".L_dodist:\n" " movl %%eax, %%r15d\n" /* dist = this */ " shrl $16, %%r15d\n" /* dist = this.val */ " movb %%ah, %%cl\n" " subb %%ah, %%bl\n" /* bits -= this.bits */ " shrq %%cl, %%rdx\n" /* hold >>= this.bits */ " movb %%al, %%cl\n" /* cl = this.op */ " testb $16, %%al\n" /* if ((op & 16) == 0) */ " jz .L_test_for_second_level_dist\n" " andb $15, %%cl\n" /* op &= 15 */ " jz .L_check_dist_one\n" ".L_add_bits_to_dist:\n" " subb %%cl, %%bl\n" " xorl %%eax, %%eax\n" " incl %%eax\n" " shll %%cl, %%eax\n" " decl %%eax\n" /* (1 << op) - 1 */ " andl %%edx, %%eax\n" /* eax &= hold */ " shrq %%cl, %%rdx\n" " addl %%eax, %%r15d\n" /* dist += hold & ((1 << op) - 1) */ ".L_check_window:\n" " movq %%rsi, %%r8\n" /* save in so from can use it's reg */ " movq %%rdi, %%rax\n" " subq 40(%%rsp), %%rax\n" /* nbytes = out - beg */ " cmpl %%r15d, %%eax\n" " jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ " movl %%r14d, %%ecx\n" /* ecx = len */ " movq %%rdi, %%rsi\n" " subq %%r15, %%rsi\n" /* from = out - dist */ " sarl %%ecx\n" " jnc .L_copy_two\n" /* if len % 2 == 0 */ " rep movsw\n" " movb (%%rsi), %%al\n" " movb %%al, (%%rdi)\n" " incq %%rdi\n" " movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ " jmp .L_while_test\n" ".L_copy_two:\n" " rep movsw\n" " movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ " jmp .L_while_test\n" ".align 32,0x90\n" ".L_check_dist_one:\n" " cmpl $1, %%r15d\n" /* if dist 1, is a memset */ " jne .L_check_window\n" " cmpq %%rdi, 40(%%rsp)\n" /* if out == beg, outside window */ " je .L_check_window\n" " movl %%r14d, %%ecx\n" /* ecx = len */ " movb -1(%%rdi), %%al\n" " movb %%al, %%ah\n" " sarl %%ecx\n" " jnc .L_set_two\n" " movb %%al, (%%rdi)\n" " incq %%rdi\n" ".L_set_two:\n" " rep stosw\n" " jmp .L_while_test\n" ".align 32,0x90\n" ".L_test_for_second_level_length:\n" " testb $64, %%al\n" " jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ " xorl %%eax, %%eax\n" " incl %%eax\n" " shll %%cl, %%eax\n" " decl %%eax\n" " andl %%edx, %%eax\n" /* eax &= hold */ " addl %%r14d, %%eax\n" /* eax += len */ " movl (%%rbp,%%rax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ " jmp .L_dolen\n" ".align 32,0x90\n" ".L_test_for_second_level_dist:\n" " testb $64, %%al\n" " jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ " xorl %%eax, %%eax\n" " incl %%eax\n" " shll %%cl, %%eax\n" " decl %%eax\n" " andl %%edx, %%eax\n" /* eax &= hold */ " addl %%r15d, %%eax\n" /* eax += dist */ " movl (%%r11,%%rax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ " jmp .L_dodist\n" ".align 32,0x90\n" ".L_clip_window:\n" " movl %%eax, %%ecx\n" /* ecx = nbytes */ " movl 92(%%rsp), %%eax\n" /* eax = wsize, prepare for dist cmp */ " negl %%ecx\n" /* nbytes = -nbytes */ " cmpl %%r15d, %%eax\n" " jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ " addl %%r15d, %%ecx\n" /* nbytes = dist - nbytes */ " cmpl $0, 96(%%rsp)\n" " jne .L_wrap_around_window\n" /* if (write != 0) */ " movq 56(%%rsp), %%rsi\n" /* from = window */ " subl %%ecx, %%eax\n" /* eax -= nbytes */ " addq %%rax, %%rsi\n" /* from += wsize - nbytes */ " movl %%r14d, %%eax\n" /* eax = len */ " cmpl %%ecx, %%r14d\n" " jbe .L_do_copy\n" /* if (nbytes >= len) */ " subl %%ecx, %%eax\n" /* eax -= nbytes */ " rep movsb\n" " movq %%rdi, %%rsi\n" " subq %%r15, %%rsi\n" /* from = &out[ -dist ] */ " jmp .L_do_copy\n" ".align 32,0x90\n" ".L_wrap_around_window:\n" " movl 96(%%rsp), %%eax\n" /* eax = write */ " cmpl %%eax, %%ecx\n" " jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ " movl 92(%%rsp), %%esi\n" /* from = wsize */ " addq 56(%%rsp), %%rsi\n" /* from += window */ " addq %%rax, %%rsi\n" /* from += write */ " subq %%rcx, %%rsi\n" /* from -= nbytes */ " subl %%eax, %%ecx\n" /* nbytes -= write */ " movl %%r14d, %%eax\n" /* eax = len */ " cmpl %%ecx, %%eax\n" " jbe .L_do_copy\n" /* if (nbytes >= len) */ " subl %%ecx, %%eax\n" /* len -= nbytes */ " rep movsb\n" " movq 56(%%rsp), %%rsi\n" /* from = window */ " movl 96(%%rsp), %%ecx\n" /* nbytes = write */ " cmpl %%ecx, %%eax\n" " jbe .L_do_copy\n" /* if (nbytes >= len) */ " subl %%ecx, %%eax\n" /* len -= nbytes */ " rep movsb\n" " movq %%rdi, %%rsi\n" " subq %%r15, %%rsi\n" /* from = out - dist */ " jmp .L_do_copy\n" ".align 32,0x90\n" ".L_contiguous_in_window:\n" " movq 56(%%rsp), %%rsi\n" /* rsi = window */ " addq %%rax, %%rsi\n" " subq %%rcx, %%rsi\n" /* from += write - nbytes */ " movl %%r14d, %%eax\n" /* eax = len */ " cmpl %%ecx, %%eax\n" " jbe .L_do_copy\n" /* if (nbytes >= len) */ " subl %%ecx, %%eax\n" /* len -= nbytes */ " rep movsb\n" " movq %%rdi, %%rsi\n" " subq %%r15, %%rsi\n" /* from = out - dist */ " jmp .L_do_copy\n" /* if (nbytes >= len) */ ".align 32,0x90\n" ".L_do_copy:\n" " movl %%eax, %%ecx\n" /* ecx = len */ " rep movsb\n" " movq %%r8, %%rsi\n" /* move in back to %esi, toss from */ " jmp .L_while_test\n" ".L_test_for_end_of_block:\n" " testb $32, %%al\n" " jz .L_invalid_literal_length_code\n" " movl $1, 116(%%rsp)\n" " jmp .L_break_loop_with_status\n" ".L_invalid_literal_length_code:\n" " movl $2, 116(%%rsp)\n" " jmp .L_break_loop_with_status\n" ".L_invalid_distance_code:\n" " movl $3, 116(%%rsp)\n" " jmp .L_break_loop_with_status\n" ".L_invalid_distance_too_far:\n" " movl $4, 116(%%rsp)\n" " jmp .L_break_loop_with_status\n" ".L_break_loop:\n" " movl $0, 116(%%rsp)\n" ".L_break_loop_with_status:\n" /* put in, out, bits, and hold back into ar and pop esp */ " movq %%rsi, 16(%%rsp)\n" /* in */ " movq %%rdi, 32(%%rsp)\n" /* out */ " movl %%ebx, 88(%%rsp)\n" /* bits */ " movq %%rdx, 80(%%rsp)\n" /* hold */ " movq (%%rsp), %%rax\n" /* restore rbp and rsp */ " movq 8(%%rsp), %%rbp\n" " movq %%rax, %%rsp\n" : : "m" (ar) : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" ); #elif ( defined( __GNUC__ ) || defined( __ICC ) ) && defined( __i386 ) __asm__ __volatile__ ( " leal %0, %%eax\n" " movl %%esp, (%%eax)\n" /* save esp, ebp */ " movl %%ebp, 4(%%eax)\n" " movl %%eax, %%esp\n" " movl 8(%%esp), %%esi\n" /* esi = in */ " movl 16(%%esp), %%edi\n" /* edi = out */ " movl 40(%%esp), %%edx\n" /* edx = hold */ " movl 44(%%esp), %%ebx\n" /* ebx = bits */ " movl 32(%%esp), %%ebp\n" /* ebp = lcode */ " cld\n" " jmp .L_do_loop\n" ".align 32,0x90\n" ".L_while_test:\n" " cmpl %%edi, 24(%%esp)\n" /* out < end */ " jbe .L_break_loop\n" " cmpl %%esi, 12(%%esp)\n" /* in < last */ " jbe .L_break_loop\n" ".L_do_loop:\n" " cmpb $15, %%bl\n" " ja .L_get_length_code\n" /* if (15 < bits) */ " xorl %%eax, %%eax\n" " lodsw\n" /* al = *(ushort *)in++ */ " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ " addb $16, %%bl\n" /* bits += 16 */ " shll %%cl, %%eax\n" " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ ".L_get_length_code:\n" " movl 56(%%esp), %%eax\n" /* eax = lmask */ " andl %%edx, %%eax\n" /* eax &= hold */ " movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */ ".L_dolen:\n" " movb %%ah, %%cl\n" /* cl = this.bits */ " subb %%ah, %%bl\n" /* bits -= this.bits */ " shrl %%cl, %%edx\n" /* hold >>= this.bits */ " testb %%al, %%al\n" " jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ " shrl $16, %%eax\n" /* output this.val char */ " stosb\n" " jmp .L_while_test\n" ".align 32,0x90\n" ".L_test_for_length_base:\n" " movl %%eax, %%ecx\n" /* len = this */ " shrl $16, %%ecx\n" /* len = this.val */ " movl %%ecx, 64(%%esp)\n" /* save len */ " movb %%al, %%cl\n" " testb $16, %%al\n" " jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ " andb $15, %%cl\n" /* op &= 15 */ " jz .L_decode_distance\n" /* if (!op) */ " cmpb %%cl, %%bl\n" " jae .L_add_bits_to_len\n" /* if (op <= bits) */ " movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ " xorl %%eax, %%eax\n" " lodsw\n" /* al = *(ushort *)in++ */ " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ " addb $16, %%bl\n" /* bits += 16 */ " shll %%cl, %%eax\n" " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ " movb %%ch, %%cl\n" /* move op back to ecx */ ".L_add_bits_to_len:\n" " subb %%cl, %%bl\n" " xorl %%eax, %%eax\n" " incl %%eax\n" " shll %%cl, %%eax\n" " decl %%eax\n" " andl %%edx, %%eax\n" /* eax &= hold */ " shrl %%cl, %%edx\n" " addl %%eax, 64(%%esp)\n" /* len += hold & mask[op] */ ".L_decode_distance:\n" " cmpb $15, %%bl\n" " ja .L_get_distance_code\n" /* if (15 < bits) */ " xorl %%eax, %%eax\n" " lodsw\n" /* al = *(ushort *)in++ */ " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ " addb $16, %%bl\n" /* bits += 16 */ " shll %%cl, %%eax\n" " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ ".L_get_distance_code:\n" " movl 60(%%esp), %%eax\n" /* eax = dmask */ " movl 36(%%esp), %%ecx\n" /* ecx = dcode */ " andl %%edx, %%eax\n" /* eax &= hold */ " movl (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */ ".L_dodist:\n" " movl %%eax, %%ebp\n" /* dist = this */ " shrl $16, %%ebp\n" /* dist = this.val */ " movb %%ah, %%cl\n" " subb %%ah, %%bl\n" /* bits -= this.bits */ " shrl %%cl, %%edx\n" /* hold >>= this.bits */ " movb %%al, %%cl\n" /* cl = this.op */ " testb $16, %%al\n" /* if ((op & 16) == 0) */ " jz .L_test_for_second_level_dist\n" " andb $15, %%cl\n" /* op &= 15 */ " jz .L_check_dist_one\n" " cmpb %%cl, %%bl\n" " jae .L_add_bits_to_dist\n" /* if (op <= bits) 97.6% */ " movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ " xorl %%eax, %%eax\n" " lodsw\n" /* al = *(ushort *)in++ */ " movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ " addb $16, %%bl\n" /* bits += 16 */ " shll %%cl, %%eax\n" " orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ " movb %%ch, %%cl\n" /* move op back to ecx */ ".L_add_bits_to_dist:\n" " subb %%cl, %%bl\n" " xorl %%eax, %%eax\n" " incl %%eax\n" " shll %%cl, %%eax\n" " decl %%eax\n" /* (1 << op) - 1 */ " andl %%edx, %%eax\n" /* eax &= hold */ " shrl %%cl, %%edx\n" " addl %%eax, %%ebp\n" /* dist += hold & ((1 << op) - 1) */ ".L_check_window:\n" " movl %%esi, 8(%%esp)\n" /* save in so from can use it's reg */ " movl %%edi, %%eax\n" " subl 20(%%esp), %%eax\n" /* nbytes = out - beg */ " cmpl %%ebp, %%eax\n" " jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ " movl 64(%%esp), %%ecx\n" /* ecx = len */ " movl %%edi, %%esi\n" " subl %%ebp, %%esi\n" /* from = out - dist */ " sarl %%ecx\n" " jnc .L_copy_two\n" /* if len % 2 == 0 */ " rep movsw\n" " movb (%%esi), %%al\n" " movb %%al, (%%edi)\n" " incl %%edi\n" " movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ " movl 32(%%esp), %%ebp\n" /* ebp = lcode */ " jmp .L_while_test\n" ".L_copy_two:\n" " rep movsw\n" " movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ " movl 32(%%esp), %%ebp\n" /* ebp = lcode */ " jmp .L_while_test\n" ".align 32,0x90\n" ".L_check_dist_one:\n" " cmpl $1, %%ebp\n" /* if dist 1, is a memset */ " jne .L_check_window\n" " cmpl %%edi, 20(%%esp)\n" " je .L_check_window\n" /* out == beg, if outside window */ " movl 64(%%esp), %%ecx\n" /* ecx = len */ " movb -1(%%edi), %%al\n" " movb %%al, %%ah\n" " sarl %%ecx\n" " jnc .L_set_two\n" " movb %%al, (%%edi)\n" " incl %%edi\n" ".L_set_two:\n" " rep stosw\n" " movl 32(%%esp), %%ebp\n" /* ebp = lcode */ " jmp .L_while_test\n" ".align 32,0x90\n" ".L_test_for_second_level_length:\n" " testb $64, %%al\n" " jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ " xorl %%eax, %%eax\n" " incl %%eax\n" " shll %%cl, %%eax\n" " decl %%eax\n" " andl %%edx, %%eax\n" /* eax &= hold */ " addl 64(%%esp), %%eax\n" /* eax += len */ " movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ " jmp .L_dolen\n" ".align 32,0x90\n" ".L_test_for_second_level_dist:\n" " testb $64, %%al\n" " jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ " xorl %%eax, %%eax\n" " incl %%eax\n" " shll %%cl, %%eax\n" " decl %%eax\n" " andl %%edx, %%eax\n" /* eax &= hold */ " addl %%ebp, %%eax\n" /* eax += dist */ " movl 36(%%esp), %%ecx\n" /* ecx = dcode */ " movl (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ " jmp .L_dodist\n" ".align 32,0x90\n" ".L_clip_window:\n" " movl %%eax, %%ecx\n" " movl 48(%%esp), %%eax\n" /* eax = wsize */ " negl %%ecx\n" /* nbytes = -nbytes */ " movl 28(%%esp), %%esi\n" /* from = window */ " cmpl %%ebp, %%eax\n" " jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ " addl %%ebp, %%ecx\n" /* nbytes = dist - nbytes */ " cmpl $0, 52(%%esp)\n" " jne .L_wrap_around_window\n" /* if (write != 0) */ " subl %%ecx, %%eax\n" " addl %%eax, %%esi\n" /* from += wsize - nbytes */ " movl 64(%%esp), %%eax\n" /* eax = len */ " cmpl %%ecx, %%eax\n" " jbe .L_do_copy\n" /* if (nbytes >= len) */ " subl %%ecx, %%eax\n" /* len -= nbytes */ " rep movsb\n" " movl %%edi, %%esi\n" " subl %%ebp, %%esi\n" /* from = out - dist */ " jmp .L_do_copy\n" ".align 32,0x90\n" ".L_wrap_around_window:\n" " movl 52(%%esp), %%eax\n" /* eax = write */ " cmpl %%eax, %%ecx\n" " jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ " addl 48(%%esp), %%esi\n" /* from += wsize */ " addl %%eax, %%esi\n" /* from += write */ " subl %%ecx, %%esi\n" /* from -= nbytes */ " subl %%eax, %%ecx\n" /* nbytes -= write */ " movl 64(%%esp), %%eax\n" /* eax = len */ " cmpl %%ecx, %%eax\n" " jbe .L_do_copy\n" /* if (nbytes >= len) */ " subl %%ecx, %%eax\n" /* len -= nbytes */ " rep movsb\n" " movl 28(%%esp), %%esi\n" /* from = window */ " movl 52(%%esp), %%ecx\n" /* nbytes = write */ " cmpl %%ecx, %%eax\n" " jbe .L_do_copy\n" /* if (nbytes >= len) */ " subl %%ecx, %%eax\n" /* len -= nbytes */ " rep movsb\n" " movl %%edi, %%esi\n" " subl %%ebp, %%esi\n" /* from = out - dist */ " jmp .L_do_copy\n" ".align 32,0x90\n" ".L_contiguous_in_window:\n" " addl %%eax, %%esi\n" " subl %%ecx, %%esi\n" /* from += write - nbytes */ " movl 64(%%esp), %%eax\n" /* eax = len */ " cmpl %%ecx, %%eax\n" " jbe .L_do_copy\n" /* if (nbytes >= len) */ " subl %%ecx, %%eax\n" /* len -= nbytes */ " rep movsb\n" " movl %%edi, %%esi\n" " subl %%ebp, %%esi\n" /* from = out - dist */ " jmp .L_do_copy\n" /* if (nbytes >= len) */ ".align 32,0x90\n" ".L_do_copy:\n" " movl %%eax, %%ecx\n" " rep movsb\n" " movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ " movl 32(%%esp), %%ebp\n" /* ebp = lcode */ " jmp .L_while_test\n" ".L_test_for_end_of_block:\n" " testb $32, %%al\n" " jz .L_invalid_literal_length_code\n" " movl $1, 72(%%esp)\n" " jmp .L_break_loop_with_status\n" ".L_invalid_literal_length_code:\n" " movl $2, 72(%%esp)\n" " jmp .L_break_loop_with_status\n" ".L_invalid_distance_code:\n" " movl $3, 72(%%esp)\n" " jmp .L_break_loop_with_status\n" ".L_invalid_distance_too_far:\n" " movl 8(%%esp), %%esi\n" " movl $4, 72(%%esp)\n" " jmp .L_break_loop_with_status\n" ".L_break_loop:\n" " movl $0, 72(%%esp)\n" ".L_break_loop_with_status:\n" /* put in, out, bits, and hold back into ar and pop esp */ " movl %%esi, 8(%%esp)\n" /* save in */ " movl %%edi, 16(%%esp)\n" /* save out */ " movl %%ebx, 44(%%esp)\n" /* save bits */ " movl %%edx, 40(%%esp)\n" /* save hold */ " movl 4(%%esp), %%ebp\n" /* restore esp, ebp */ " movl (%%esp), %%esp\n" : : "m" (ar) : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi" ); #elif defined( _MSC_VER ) && ! defined( _M_AMD64 ) __asm { lea eax, ar mov [eax], esp /* save esp, ebp */ mov [eax+4], ebp mov esp, eax mov esi, [esp+8] /* esi = in */ mov edi, [esp+16] /* edi = out */ mov edx, [esp+40] /* edx = hold */ mov ebx, [esp+44] /* ebx = bits */ mov ebp, [esp+32] /* ebp = lcode */ cld jmp L_do_loop ALIGN 4 L_while_test: cmp [esp+24], edi jbe L_break_loop cmp [esp+12], esi jbe L_break_loop L_do_loop: cmp bl, 15 ja L_get_length_code /* if (15 < bits) */ xor eax, eax lodsw /* al = *(ushort *)in++ */ mov cl, bl /* cl = bits, needs it for shifting */ add bl, 16 /* bits += 16 */ shl eax, cl or edx, eax /* hold |= *((ushort *)in)++ << bits */ L_get_length_code: mov eax, [esp+56] /* eax = lmask */ and eax, edx /* eax &= hold */ mov eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */ L_dolen: mov cl, ah /* cl = this.bits */ sub bl, ah /* bits -= this.bits */ shr edx, cl /* hold >>= this.bits */ test al, al jnz L_test_for_length_base /* if (op != 0) 45.7% */ shr eax, 16 /* output this.val char */ stosb jmp L_while_test ALIGN 4 L_test_for_length_base: mov ecx, eax /* len = this */ shr ecx, 16 /* len = this.val */ mov [esp+64], ecx /* save len */ mov cl, al test al, 16 jz L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ and cl, 15 /* op &= 15 */ jz L_decode_distance /* if (!op) */ cmp bl, cl jae L_add_bits_to_len /* if (op <= bits) */ mov ch, cl /* stash op in ch, freeing cl */ xor eax, eax lodsw /* al = *(ushort *)in++ */ mov cl, bl /* cl = bits, needs it for shifting */ add bl, 16 /* bits += 16 */ shl eax, cl or edx, eax /* hold |= *((ushort *)in)++ << bits */ mov cl, ch /* move op back to ecx */ L_add_bits_to_len: sub bl, cl xor eax, eax inc eax shl eax, cl dec eax and eax, edx /* eax &= hold */ shr edx, cl add [esp+64], eax /* len += hold & mask[op] */ L_decode_distance: cmp bl, 15 ja L_get_distance_code /* if (15 < bits) */ xor eax, eax lodsw /* al = *(ushort *)in++ */ mov cl, bl /* cl = bits, needs it for shifting */ add bl, 16 /* bits += 16 */ shl eax, cl or edx, eax /* hold |= *((ushort *)in)++ << bits */ L_get_distance_code: mov eax, [esp+60] /* eax = dmask */ mov ecx, [esp+36] /* ecx = dcode */ and eax, edx /* eax &= hold */ mov eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */ L_dodist: mov ebp, eax /* dist = this */ shr ebp, 16 /* dist = this.val */ mov cl, ah sub bl, ah /* bits -= this.bits */ shr edx, cl /* hold >>= this.bits */ mov cl, al /* cl = this.op */ test al, 16 /* if ((op & 16) == 0) */ jz L_test_for_second_level_dist and cl, 15 /* op &= 15 */ jz L_check_dist_one cmp bl, cl jae L_add_bits_to_dist /* if (op <= bits) 97.6% */ mov ch, cl /* stash op in ch, freeing cl */ xor eax, eax lodsw /* al = *(ushort *)in++ */ mov cl, bl /* cl = bits, needs it for shifting */ add bl, 16 /* bits += 16 */ shl eax, cl or edx, eax /* hold |= *((ushort *)in)++ << bits */ mov cl, ch /* move op back to ecx */ L_add_bits_to_dist: sub bl, cl xor eax, eax inc eax shl eax, cl dec eax /* (1 << op) - 1 */ and eax, edx /* eax &= hold */ shr edx, cl add ebp, eax /* dist += hold & ((1 << op) - 1) */ L_check_window: mov [esp+8], esi /* save in so from can use it's reg */ mov eax, edi sub eax, [esp+20] /* nbytes = out - beg */ cmp eax, ebp jb L_clip_window /* if (dist > nbytes) 4.2% */ mov ecx, [esp+64] /* ecx = len */ mov esi, edi sub esi, ebp /* from = out - dist */ sar ecx, 1 jnc L_copy_two rep movsw mov al, [esi] mov [edi], al inc edi mov esi, [esp+8] /* move in back to %esi, toss from */ mov ebp, [esp+32] /* ebp = lcode */ jmp L_while_test L_copy_two: rep movsw mov esi, [esp+8] /* move in back to %esi, toss from */ mov ebp, [esp+32] /* ebp = lcode */ jmp L_while_test ALIGN 4 L_check_dist_one: cmp ebp, 1 /* if dist 1, is a memset */ jne L_check_window cmp [esp+20], edi je L_check_window /* out == beg, if outside window */ mov ecx, [esp+64] /* ecx = len */ mov al, [edi-1] mov ah, al sar ecx, 1 jnc L_set_two mov [edi], al /* memset out with from[-1] */ inc edi L_set_two: rep stosw mov ebp, [esp+32] /* ebp = lcode */ jmp L_while_test ALIGN 4 L_test_for_second_level_length: test al, 64 jnz L_test_for_end_of_block /* if ((op & 64) != 0) */ xor eax, eax inc eax shl eax, cl dec eax and eax, edx /* eax &= hold */ add eax, [esp+64] /* eax += len */ mov eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/ jmp L_dolen ALIGN 4 L_test_for_second_level_dist: test al, 64 jnz L_invalid_distance_code /* if ((op & 64) != 0) */ xor eax, eax inc eax shl eax, cl dec eax and eax, edx /* eax &= hold */ add eax, ebp /* eax += dist */ mov ecx, [esp+36] /* ecx = dcode */ mov eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/ jmp L_dodist ALIGN 4 L_clip_window: mov ecx, eax mov eax, [esp+48] /* eax = wsize */ neg ecx /* nbytes = -nbytes */ mov esi, [esp+28] /* from = window */ cmp eax, ebp jb L_invalid_distance_too_far /* if (dist > wsize) */ add ecx, ebp /* nbytes = dist - nbytes */ cmp dword ptr [esp+52], 0 jne L_wrap_around_window /* if (write != 0) */ sub eax, ecx add esi, eax /* from += wsize - nbytes */ mov eax, [esp+64] /* eax = len */ cmp eax, ecx jbe L_do_copy /* if (nbytes >= len) */ sub eax, ecx /* len -= nbytes */ rep movsb mov esi, edi sub esi, ebp /* from = out - dist */ jmp L_do_copy ALIGN 4 L_wrap_around_window: mov eax, [esp+52] /* eax = write */ cmp ecx, eax jbe L_contiguous_in_window /* if (write >= nbytes) */ add esi, [esp+48] /* from += wsize */ add esi, eax /* from += write */ sub esi, ecx /* from -= nbytes */ sub ecx, eax /* nbytes -= write */ mov eax, [esp+64] /* eax = len */ cmp eax, ecx jbe L_do_copy /* if (nbytes >= len) */ sub eax, ecx /* len -= nbytes */ rep movsb mov esi, [esp+28] /* from = window */ mov ecx, [esp+52] /* nbytes = write */ cmp eax, ecx jbe L_do_copy /* if (nbytes >= len) */ sub eax, ecx /* len -= nbytes */ rep movsb mov esi, edi sub esi, ebp /* from = out - dist */ jmp L_do_copy ALIGN 4 L_contiguous_in_window: add esi, eax sub esi, ecx /* from += write - nbytes */ mov eax, [esp+64] /* eax = len */ cmp eax, ecx jbe L_do_copy /* if (nbytes >= len) */ sub eax, ecx /* len -= nbytes */ rep movsb mov esi, edi sub esi, ebp /* from = out - dist */ jmp L_do_copy ALIGN 4 L_do_copy: mov ecx, eax rep movsb mov esi, [esp+8] /* move in back to %esi, toss from */ mov ebp, [esp+32] /* ebp = lcode */ jmp L_while_test L_test_for_end_of_block: test al, 32 jz L_invalid_literal_length_code mov dword ptr [esp+72], 1 jmp L_break_loop_with_status L_invalid_literal_length_code: mov dword ptr [esp+72], 2 jmp L_break_loop_with_status L_invalid_distance_code: mov dword ptr [esp+72], 3 jmp L_break_loop_with_status L_invalid_distance_too_far: mov esi, [esp+4] mov dword ptr [esp+72], 4 jmp L_break_loop_with_status L_break_loop: mov dword ptr [esp+72], 0 L_break_loop_with_status: /* put in, out, bits, and hold back into ar and pop esp */ mov [esp+8], esi /* save in */ mov [esp+16], edi /* save out */ mov [esp+44], ebx /* save bits */ mov [esp+40], edx /* save hold */ mov ebp, [esp+4] /* restore esp, ebp */ mov esp, [esp] } #else #error "x86 architecture not defined" #endif if (ar.status > 1) { if (ar.status == 2) strm->msg = "invalid literal/length code"; else if (ar.status == 3) strm->msg = "invalid distance code"; else strm->msg = "invalid distance too far back"; state->mode = BAD; } else if ( ar.status == 1 ) { state->mode = TYPE; } /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ ar.len = ar.bits >> 3; ar.in -= ar.len; ar.bits -= ar.len << 3; ar.hold &= (1U << ar.bits) - 1; /* update state and return */ strm->next_in = ar.in; strm->next_out = ar.out; strm->avail_in = (unsigned)(ar.in < ar.last ? PAD_AVAIL_IN + (ar.last - ar.in) : PAD_AVAIL_IN - (ar.in - ar.last)); strm->avail_out = (unsigned)(ar.out < ar.end ? PAD_AVAIL_OUT + (ar.end - ar.out) : PAD_AVAIL_OUT - (ar.out - ar.end)); state->hold = ar.hold; state->bits = ar.bits; return; } tcl8.6.5/compat/zlib/contrib/masmx86/0000755000175000017500000000000012665173607016760 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/masmx86/bld_ml32.bat0000644000175000017500000000013412663653206021040 0ustar sergeisergeiml /coff /Zi /c /Flmatch686.lst match686.asm ml /coff /Zi /c /Flinffas32.lst inffas32.asm tcl8.6.5/compat/zlib/contrib/masmx86/inffas32.asm0000644000175000017500000004001012663660064021064 0ustar sergeisergei;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding ; * ; * inffas32.asm is derivated from inffas86.c, with translation of assembly code ; * ; * Copyright (C) 1995-2003 Mark Adler ; * For conditions of distribution and use, see copyright notice in zlib.h ; * ; * Copyright (C) 2003 Chris Anderson ; * Please use the copyright conditions above. ; * ; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from ; * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at ; * the moment. I have successfully compiled and tested this code with gcc2.96, ; * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S ; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX ; * enabled. I will attempt to merge the MMX code into this version. Newer ; * versions of this and inffast.S can be found at ; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ ; * ; * 2005 : modification by Gilles Vollant ; */ ; For Visual C++ 4.x and higher and ML 6.x and higher ; ml.exe is in directory \MASM611C of Win95 DDK ; ml.exe is also distributed in http://www.masm32.com/masmdl.htm ; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/ ; ; ; compile with command line option ; ml /coff /Zi /c /Flinffas32.lst inffas32.asm ; if you define NO_GZIP (see inflate.h), compile with ; ml /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm ; zlib122sup is 0 fort zlib 1.2.2.1 and lower ; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head ; in inflate_state in inflate.h) zlib1222sup equ 8 IFDEF GUNZIP INFLATE_MODE_TYPE equ 11 INFLATE_MODE_BAD equ 26 ELSE IFNDEF NO_GUNZIP INFLATE_MODE_TYPE equ 11 INFLATE_MODE_BAD equ 26 ELSE INFLATE_MODE_TYPE equ 3 INFLATE_MODE_BAD equ 17 ENDIF ENDIF ; 75 "inffast.S" ;FILE "inffast.S" ;;;GLOBAL _inflate_fast ;;;SECTION .text .586p .mmx name inflate_fast_x86 .MODEL FLAT _DATA segment inflate_fast_use_mmx: dd 1 _TEXT segment ALIGN 4 db 'Fast decoding Code from Chris Anderson' db 0 ALIGN 4 invalid_literal_length_code_msg: db 'invalid literal/length code' db 0 ALIGN 4 invalid_distance_code_msg: db 'invalid distance code' db 0 ALIGN 4 invalid_distance_too_far_msg: db 'invalid distance too far back' db 0 ALIGN 4 inflate_fast_mask: dd 0 dd 1 dd 3 dd 7 dd 15 dd 31 dd 63 dd 127 dd 255 dd 511 dd 1023 dd 2047 dd 4095 dd 8191 dd 16383 dd 32767 dd 65535 dd 131071 dd 262143 dd 524287 dd 1048575 dd 2097151 dd 4194303 dd 8388607 dd 16777215 dd 33554431 dd 67108863 dd 134217727 dd 268435455 dd 536870911 dd 1073741823 dd 2147483647 dd 4294967295 mode_state equ 0 ;/* state->mode */ wsize_state equ (32+zlib1222sup) ;/* state->wsize */ write_state equ (36+4+zlib1222sup) ;/* state->write */ window_state equ (40+4+zlib1222sup) ;/* state->window */ hold_state equ (44+4+zlib1222sup) ;/* state->hold */ bits_state equ (48+4+zlib1222sup) ;/* state->bits */ lencode_state equ (64+4+zlib1222sup) ;/* state->lencode */ distcode_state equ (68+4+zlib1222sup) ;/* state->distcode */ lenbits_state equ (72+4+zlib1222sup) ;/* state->lenbits */ distbits_state equ (76+4+zlib1222sup) ;/* state->distbits */ ;;SECTION .text ; 205 "inffast.S" ;GLOBAL inflate_fast_use_mmx ;SECTION .data ; GLOBAL inflate_fast_use_mmx:object ;.size inflate_fast_use_mmx, 4 ; 226 "inffast.S" ;SECTION .text ALIGN 4 _inflate_fast proc near .FPO (16, 4, 0, 0, 1, 0) push edi push esi push ebp push ebx pushfd sub esp,64 cld mov esi, [esp+88] mov edi, [esi+28] mov edx, [esi+4] mov eax, [esi+0] add edx,eax sub edx,11 mov [esp+44],eax mov [esp+20],edx mov ebp, [esp+92] mov ecx, [esi+16] mov ebx, [esi+12] sub ebp,ecx neg ebp add ebp,ebx sub ecx,257 add ecx,ebx mov [esp+60],ebx mov [esp+40],ebp mov [esp+16],ecx ; 285 "inffast.S" mov eax, [edi+lencode_state] mov ecx, [edi+distcode_state] mov [esp+8],eax mov [esp+12],ecx mov eax,1 mov ecx, [edi+lenbits_state] shl eax,cl dec eax mov [esp+0],eax mov eax,1 mov ecx, [edi+distbits_state] shl eax,cl dec eax mov [esp+4],eax mov eax, [edi+wsize_state] mov ecx, [edi+write_state] mov edx, [edi+window_state] mov [esp+52],eax mov [esp+48],ecx mov [esp+56],edx mov ebp, [edi+hold_state] mov ebx, [edi+bits_state] ; 321 "inffast.S" mov esi, [esp+44] mov ecx, [esp+20] cmp ecx,esi ja L_align_long add ecx,11 sub ecx,esi mov eax,12 sub eax,ecx lea edi, [esp+28] rep movsb mov ecx,eax xor eax,eax rep stosb lea esi, [esp+28] mov [esp+20],esi jmp L_is_aligned L_align_long: test esi,3 jz L_is_aligned xor eax,eax mov al, [esi] inc esi mov ecx,ebx add ebx,8 shl eax,cl or ebp,eax jmp L_align_long L_is_aligned: mov edi, [esp+60] ; 366 "inffast.S" L_check_mmx: cmp dword ptr [inflate_fast_use_mmx],2 je L_init_mmx ja L_do_loop push eax push ebx push ecx push edx pushfd mov eax, [esp] xor dword ptr [esp],0200000h popfd pushfd pop edx xor edx,eax jz L_dont_use_mmx xor eax,eax cpuid cmp ebx,0756e6547h jne L_dont_use_mmx cmp ecx,06c65746eh jne L_dont_use_mmx cmp edx,049656e69h jne L_dont_use_mmx mov eax,1 cpuid shr eax,8 and eax,15 cmp eax,6 jne L_dont_use_mmx test edx,0800000h jnz L_use_mmx jmp L_dont_use_mmx L_use_mmx: mov dword ptr [inflate_fast_use_mmx],2 jmp L_check_mmx_pop L_dont_use_mmx: mov dword ptr [inflate_fast_use_mmx],3 L_check_mmx_pop: pop edx pop ecx pop ebx pop eax jmp L_check_mmx ; 426 "inffast.S" ALIGN 4 L_do_loop: ; 437 "inffast.S" cmp bl,15 ja L_get_length_code xor eax,eax lodsw mov cl,bl add bl,16 shl eax,cl or ebp,eax L_get_length_code: mov edx, [esp+0] mov ecx, [esp+8] and edx,ebp mov eax, [ecx+edx*4] L_dolen: mov cl,ah sub bl,ah shr ebp,cl test al,al jnz L_test_for_length_base shr eax,16 stosb L_while_test: cmp [esp+16],edi jbe L_break_loop cmp [esp+20],esi ja L_do_loop jmp L_break_loop L_test_for_length_base: ; 502 "inffast.S" mov edx,eax shr edx,16 mov cl,al test al,16 jz L_test_for_second_level_length and cl,15 jz L_save_len cmp bl,cl jae L_add_bits_to_len mov ch,cl xor eax,eax lodsw mov cl,bl add bl,16 shl eax,cl or ebp,eax mov cl,ch L_add_bits_to_len: mov eax,1 shl eax,cl dec eax sub bl,cl and eax,ebp shr ebp,cl add edx,eax L_save_len: mov [esp+24],edx L_decode_distance: ; 549 "inffast.S" cmp bl,15 ja L_get_distance_code xor eax,eax lodsw mov cl,bl add bl,16 shl eax,cl or ebp,eax L_get_distance_code: mov edx, [esp+4] mov ecx, [esp+12] and edx,ebp mov eax, [ecx+edx*4] L_dodist: mov edx,eax shr edx,16 mov cl,ah sub bl,ah shr ebp,cl ; 584 "inffast.S" mov cl,al test al,16 jz L_test_for_second_level_dist and cl,15 jz L_check_dist_one cmp bl,cl jae L_add_bits_to_dist mov ch,cl xor eax,eax lodsw mov cl,bl add bl,16 shl eax,cl or ebp,eax mov cl,ch L_add_bits_to_dist: mov eax,1 shl eax,cl dec eax sub bl,cl and eax,ebp shr ebp,cl add edx,eax jmp L_check_window L_check_window: ; 625 "inffast.S" mov [esp+44],esi mov eax,edi sub eax, [esp+40] cmp eax,edx jb L_clip_window mov ecx, [esp+24] mov esi,edi sub esi,edx sub ecx,3 mov al, [esi] mov [edi],al mov al, [esi+1] mov dl, [esi+2] add esi,3 mov [edi+1],al mov [edi+2],dl add edi,3 rep movsb mov esi, [esp+44] jmp L_while_test ALIGN 4 L_check_dist_one: cmp edx,1 jne L_check_window cmp [esp+40],edi je L_check_window dec edi mov ecx, [esp+24] mov al, [edi] sub ecx,3 mov [edi+1],al mov [edi+2],al mov [edi+3],al add edi,4 rep stosb jmp L_while_test ALIGN 4 L_test_for_second_level_length: test al,64 jnz L_test_for_end_of_block mov eax,1 shl eax,cl dec eax and eax,ebp add eax,edx mov edx, [esp+8] mov eax, [edx+eax*4] jmp L_dolen ALIGN 4 L_test_for_second_level_dist: test al,64 jnz L_invalid_distance_code mov eax,1 shl eax,cl dec eax and eax,ebp add eax,edx mov edx, [esp+12] mov eax, [edx+eax*4] jmp L_dodist ALIGN 4 L_clip_window: ; 721 "inffast.S" mov ecx,eax mov eax, [esp+52] neg ecx mov esi, [esp+56] cmp eax,edx jb L_invalid_distance_too_far add ecx,edx cmp dword ptr [esp+48],0 jne L_wrap_around_window sub eax,ecx add esi,eax ; 749 "inffast.S" mov eax, [esp+24] cmp eax,ecx jbe L_do_copy1 sub eax,ecx rep movsb mov esi,edi sub esi,edx jmp L_do_copy1 cmp eax,ecx jbe L_do_copy1 sub eax,ecx rep movsb mov esi,edi sub esi,edx jmp L_do_copy1 L_wrap_around_window: ; 793 "inffast.S" mov eax, [esp+48] cmp ecx,eax jbe L_contiguous_in_window add esi, [esp+52] add esi,eax sub esi,ecx sub ecx,eax mov eax, [esp+24] cmp eax,ecx jbe L_do_copy1 sub eax,ecx rep movsb mov esi, [esp+56] mov ecx, [esp+48] cmp eax,ecx jbe L_do_copy1 sub eax,ecx rep movsb mov esi,edi sub esi,edx jmp L_do_copy1 L_contiguous_in_window: ; 836 "inffast.S" add esi,eax sub esi,ecx mov eax, [esp+24] cmp eax,ecx jbe L_do_copy1 sub eax,ecx rep movsb mov esi,edi sub esi,edx L_do_copy1: ; 862 "inffast.S" mov ecx,eax rep movsb mov esi, [esp+44] jmp L_while_test ; 878 "inffast.S" ALIGN 4 L_init_mmx: emms movd mm0,ebp mov ebp,ebx ; 896 "inffast.S" movd mm4,dword ptr [esp+0] movq mm3,mm4 movd mm5,dword ptr [esp+4] movq mm2,mm5 pxor mm1,mm1 mov ebx, [esp+8] jmp L_do_loop_mmx ALIGN 4 L_do_loop_mmx: psrlq mm0,mm1 cmp ebp,32 ja L_get_length_code_mmx movd mm6,ebp movd mm7,dword ptr [esi] add esi,4 psllq mm7,mm6 add ebp,32 por mm0,mm7 L_get_length_code_mmx: pand mm4,mm0 movd eax,mm4 movq mm4,mm3 mov eax, [ebx+eax*4] L_dolen_mmx: movzx ecx,ah movd mm1,ecx sub ebp,ecx test al,al jnz L_test_for_length_base_mmx shr eax,16 stosb L_while_test_mmx: cmp [esp+16],edi jbe L_break_loop cmp [esp+20],esi ja L_do_loop_mmx jmp L_break_loop L_test_for_length_base_mmx: mov edx,eax shr edx,16 test al,16 jz L_test_for_second_level_length_mmx and eax,15 jz L_decode_distance_mmx psrlq mm0,mm1 movd mm1,eax movd ecx,mm0 sub ebp,eax and ecx, [inflate_fast_mask+eax*4] add edx,ecx L_decode_distance_mmx: psrlq mm0,mm1 cmp ebp,32 ja L_get_dist_code_mmx movd mm6,ebp movd mm7,dword ptr [esi] add esi,4 psllq mm7,mm6 add ebp,32 por mm0,mm7 L_get_dist_code_mmx: mov ebx, [esp+12] pand mm5,mm0 movd eax,mm5 movq mm5,mm2 mov eax, [ebx+eax*4] L_dodist_mmx: movzx ecx,ah mov ebx,eax shr ebx,16 sub ebp,ecx movd mm1,ecx test al,16 jz L_test_for_second_level_dist_mmx and eax,15 jz L_check_dist_one_mmx L_add_bits_to_dist_mmx: psrlq mm0,mm1 movd mm1,eax movd ecx,mm0 sub ebp,eax and ecx, [inflate_fast_mask+eax*4] add ebx,ecx L_check_window_mmx: mov [esp+44],esi mov eax,edi sub eax, [esp+40] cmp eax,ebx jb L_clip_window_mmx mov ecx,edx mov esi,edi sub esi,ebx sub ecx,3 mov al, [esi] mov [edi],al mov al, [esi+1] mov dl, [esi+2] add esi,3 mov [edi+1],al mov [edi+2],dl add edi,3 rep movsb mov esi, [esp+44] mov ebx, [esp+8] jmp L_while_test_mmx ALIGN 4 L_check_dist_one_mmx: cmp ebx,1 jne L_check_window_mmx cmp [esp+40],edi je L_check_window_mmx dec edi mov ecx,edx mov al, [edi] sub ecx,3 mov [edi+1],al mov [edi+2],al mov [edi+3],al add edi,4 rep stosb mov ebx, [esp+8] jmp L_while_test_mmx ALIGN 4 L_test_for_second_level_length_mmx: test al,64 jnz L_test_for_end_of_block and eax,15 psrlq mm0,mm1 movd ecx,mm0 and ecx, [inflate_fast_mask+eax*4] add ecx,edx mov eax, [ebx+ecx*4] jmp L_dolen_mmx ALIGN 4 L_test_for_second_level_dist_mmx: test al,64 jnz L_invalid_distance_code and eax,15 psrlq mm0,mm1 movd ecx,mm0 and ecx, [inflate_fast_mask+eax*4] mov eax, [esp+12] add ecx,ebx mov eax, [eax+ecx*4] jmp L_dodist_mmx ALIGN 4 L_clip_window_mmx: mov ecx,eax mov eax, [esp+52] neg ecx mov esi, [esp+56] cmp eax,ebx jb L_invalid_distance_too_far add ecx,ebx cmp dword ptr [esp+48],0 jne L_wrap_around_window_mmx sub eax,ecx add esi,eax cmp edx,ecx jbe L_do_copy1_mmx sub edx,ecx rep movsb mov esi,edi sub esi,ebx jmp L_do_copy1_mmx cmp edx,ecx jbe L_do_copy1_mmx sub edx,ecx rep movsb mov esi,edi sub esi,ebx jmp L_do_copy1_mmx L_wrap_around_window_mmx: mov eax, [esp+48] cmp ecx,eax jbe L_contiguous_in_window_mmx add esi, [esp+52] add esi,eax sub esi,ecx sub ecx,eax cmp edx,ecx jbe L_do_copy1_mmx sub edx,ecx rep movsb mov esi, [esp+56] mov ecx, [esp+48] cmp edx,ecx jbe L_do_copy1_mmx sub edx,ecx rep movsb mov esi,edi sub esi,ebx jmp L_do_copy1_mmx L_contiguous_in_window_mmx: add esi,eax sub esi,ecx cmp edx,ecx jbe L_do_copy1_mmx sub edx,ecx rep movsb mov esi,edi sub esi,ebx L_do_copy1_mmx: mov ecx,edx rep movsb mov esi, [esp+44] mov ebx, [esp+8] jmp L_while_test_mmx ; 1174 "inffast.S" L_invalid_distance_code: mov ecx, invalid_distance_code_msg mov edx,INFLATE_MODE_BAD jmp L_update_stream_state L_test_for_end_of_block: test al,32 jz L_invalid_literal_length_code mov ecx,0 mov edx,INFLATE_MODE_TYPE jmp L_update_stream_state L_invalid_literal_length_code: mov ecx, invalid_literal_length_code_msg mov edx,INFLATE_MODE_BAD jmp L_update_stream_state L_invalid_distance_too_far: mov esi, [esp+44] mov ecx, invalid_distance_too_far_msg mov edx,INFLATE_MODE_BAD jmp L_update_stream_state L_update_stream_state: mov eax, [esp+88] test ecx,ecx jz L_skip_msg mov [eax+24],ecx L_skip_msg: mov eax, [eax+28] mov [eax+mode_state],edx jmp L_break_loop ALIGN 4 L_break_loop: ; 1243 "inffast.S" cmp dword ptr [inflate_fast_use_mmx],2 jne L_update_next_in mov ebx,ebp L_update_next_in: ; 1266 "inffast.S" mov eax, [esp+88] mov ecx,ebx mov edx, [eax+28] shr ecx,3 sub esi,ecx shl ecx,3 sub ebx,ecx mov [eax+12],edi mov [edx+bits_state],ebx mov ecx,ebx lea ebx, [esp+28] cmp [esp+20],ebx jne L_buf_not_used sub esi,ebx mov ebx, [eax+0] mov [esp+20],ebx add esi,ebx mov ebx, [eax+4] sub ebx,11 add [esp+20],ebx L_buf_not_used: mov [eax+0],esi mov ebx,1 shl ebx,cl dec ebx cmp dword ptr [inflate_fast_use_mmx],2 jne L_update_hold psrlq mm0,mm1 movd ebp,mm0 emms L_update_hold: and ebp,ebx mov [edx+hold_state],ebp mov ebx, [esp+20] cmp ebx,esi jbe L_last_is_smaller sub ebx,esi add ebx,11 mov [eax+4],ebx jmp L_fixup_out L_last_is_smaller: sub esi,ebx neg esi add esi,11 mov [eax+4],esi L_fixup_out: mov ebx, [esp+16] cmp ebx,edi jbe L_end_is_smaller sub ebx,edi add ebx,257 mov [eax+16],ebx jmp L_done L_end_is_smaller: sub edi,ebx neg edi add edi,257 mov [eax+16],edi L_done: add esp,64 popfd pop ebx pop ebp pop esi pop edi ret _inflate_fast endp _TEXT ends end tcl8.6.5/compat/zlib/contrib/masmx86/match686.asm0000644000175000017500000003672112663660064021027 0ustar sergeisergei; match686.asm -- Asm portion of the optimized longest_match for 32 bits x86 ; Copyright (C) 1995-1996 Jean-loup Gailly, Brian Raiter and Gilles Vollant. ; File written by Gilles Vollant, by converting match686.S from Brian Raiter ; for MASM. This is as assembly version of longest_match ; from Jean-loup Gailly in deflate.c ; ; http://www.zlib.net ; http://www.winimage.com/zLibDll ; http://www.muppetlabs.com/~breadbox/software/assembly.html ; ; For Visual C++ 4.x and higher and ML 6.x and higher ; ml.exe is distributed in ; http://www.microsoft.com/downloads/details.aspx?FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 ; ; this file contain two implementation of longest_match ; ; this longest_match was written by Brian raiter (1998), optimized for Pentium Pro ; (and the faster known version of match_init on modern Core 2 Duo and AMD Phenom) ; ; for using an assembly version of longest_match, you need define ASMV in project ; ; compile the asm file running ; ml /coff /Zi /c /Flmatch686.lst match686.asm ; and do not include match686.obj in your project ; ; note: contrib of zLib 1.2.3 and earlier contained both a deprecated version for ; Pentium (prior Pentium Pro) and this version for Pentium Pro and modern processor ; with autoselect (with cpu detection code) ; if you want support the old pentium optimization, you can still use these version ; ; this file is not optimized for old pentium, but it compatible with all x86 32 bits ; processor (starting 80386) ; ; ; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2 ;uInt longest_match(s, cur_match) ; deflate_state *s; ; IPos cur_match; /* current match */ NbStack equ 76 cur_match equ dword ptr[esp+NbStack-0] str_s equ dword ptr[esp+NbStack-4] ; 5 dword on top (ret,ebp,esi,edi,ebx) adrret equ dword ptr[esp+NbStack-8] pushebp equ dword ptr[esp+NbStack-12] pushedi equ dword ptr[esp+NbStack-16] pushesi equ dword ptr[esp+NbStack-20] pushebx equ dword ptr[esp+NbStack-24] chain_length equ dword ptr [esp+NbStack-28] limit equ dword ptr [esp+NbStack-32] best_len equ dword ptr [esp+NbStack-36] window equ dword ptr [esp+NbStack-40] prev equ dword ptr [esp+NbStack-44] scan_start equ word ptr [esp+NbStack-48] wmask equ dword ptr [esp+NbStack-52] match_start_ptr equ dword ptr [esp+NbStack-56] nice_match equ dword ptr [esp+NbStack-60] scan equ dword ptr [esp+NbStack-64] windowlen equ dword ptr [esp+NbStack-68] match_start equ dword ptr [esp+NbStack-72] strend equ dword ptr [esp+NbStack-76] NbStackAdd equ (NbStack-24) .386p name gvmatch .MODEL FLAT ; all the +zlib1222add offsets are due to the addition of fields ; in zlib in the deflate_state structure since the asm code was first written ; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). ; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). ; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). zlib1222add equ 8 ; Note : these value are good with a 8 bytes boundary pack structure dep_chain_length equ 74h+zlib1222add dep_window equ 30h+zlib1222add dep_strstart equ 64h+zlib1222add dep_prev_length equ 70h+zlib1222add dep_nice_match equ 88h+zlib1222add dep_w_size equ 24h+zlib1222add dep_prev equ 38h+zlib1222add dep_w_mask equ 2ch+zlib1222add dep_good_match equ 84h+zlib1222add dep_match_start equ 68h+zlib1222add dep_lookahead equ 6ch+zlib1222add _TEXT segment IFDEF NOUNDERLINE public longest_match public match_init ELSE public _longest_match public _match_init ENDIF MAX_MATCH equ 258 MIN_MATCH equ 3 MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) MAX_MATCH equ 258 MIN_MATCH equ 3 MIN_LOOKAHEAD equ (MAX_MATCH + MIN_MATCH + 1) MAX_MATCH_8_ equ ((MAX_MATCH + 7) AND 0FFF0h) ;;; stack frame offsets chainlenwmask equ esp + 0 ; high word: current chain len ; low word: s->wmask window equ esp + 4 ; local copy of s->window windowbestlen equ esp + 8 ; s->window + bestlen scanstart equ esp + 16 ; first two bytes of string scanend equ esp + 12 ; last two bytes of string scanalign equ esp + 20 ; dword-misalignment of string nicematch equ esp + 24 ; a good enough match size bestlen equ esp + 28 ; size of best match so far scan equ esp + 32 ; ptr to string wanting match LocalVarsSize equ 36 ; saved ebx byte esp + 36 ; saved edi byte esp + 40 ; saved esi byte esp + 44 ; saved ebp byte esp + 48 ; return address byte esp + 52 deflatestate equ esp + 56 ; the function arguments curmatch equ esp + 60 ;;; Offsets for fields in the deflate_state structure. These numbers ;;; are calculated from the definition of deflate_state, with the ;;; assumption that the compiler will dword-align the fields. (Thus, ;;; changing the definition of deflate_state could easily cause this ;;; program to crash horribly, without so much as a warning at ;;; compile time. Sigh.) dsWSize equ 36+zlib1222add dsWMask equ 44+zlib1222add dsWindow equ 48+zlib1222add dsPrev equ 56+zlib1222add dsMatchLen equ 88+zlib1222add dsPrevMatch equ 92+zlib1222add dsStrStart equ 100+zlib1222add dsMatchStart equ 104+zlib1222add dsLookahead equ 108+zlib1222add dsPrevLen equ 112+zlib1222add dsMaxChainLen equ 116+zlib1222add dsGoodMatch equ 132+zlib1222add dsNiceMatch equ 136+zlib1222add ;;; match686.asm -- Pentium-Pro-optimized version of longest_match() ;;; Written for zlib 1.1.2 ;;; Copyright (C) 1998 Brian Raiter ;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html ;;; ;; ;; This software is provided 'as-is', without any express or implied ;; warranty. In no event will the authors be held liable for any damages ;; arising from the use of this software. ;; ;; Permission is granted to anyone to use this software for any purpose, ;; including commercial applications, and to alter it and redistribute it ;; freely, subject to the following restrictions: ;; ;; 1. The origin of this software must not be misrepresented; you must not ;; claim that you wrote the original software. If you use this software ;; in a product, an acknowledgment in the product documentation would be ;; appreciated but is not required. ;; 2. Altered source versions must be plainly marked as such, and must not be ;; misrepresented as being the original software ;; 3. This notice may not be removed or altered from any source distribution. ;; ;GLOBAL _longest_match, _match_init ;SECTION .text ;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch) ;_longest_match: IFDEF NOUNDERLINE longest_match proc near ELSE _longest_match proc near ENDIF .FPO (9, 4, 0, 0, 1, 0) ;;; Save registers that the compiler may be using, and adjust esp to ;;; make room for our stack frame. push ebp push edi push esi push ebx sub esp, LocalVarsSize ;;; Retrieve the function arguments. ecx will hold cur_match ;;; throughout the entire function. edx will hold the pointer to the ;;; deflate_state structure during the function's setup (before ;;; entering the main loop. mov edx, [deflatestate] mov ecx, [curmatch] ;;; uInt wmask = s->w_mask; ;;; unsigned chain_length = s->max_chain_length; ;;; if (s->prev_length >= s->good_match) { ;;; chain_length >>= 2; ;;; } mov eax, [edx + dsPrevLen] mov ebx, [edx + dsGoodMatch] cmp eax, ebx mov eax, [edx + dsWMask] mov ebx, [edx + dsMaxChainLen] jl LastMatchGood shr ebx, 2 LastMatchGood: ;;; chainlen is decremented once beforehand so that the function can ;;; use the sign flag instead of the zero flag for the exit test. ;;; It is then shifted into the high word, to make room for the wmask ;;; value, which it will always accompany. dec ebx shl ebx, 16 or ebx, eax mov [chainlenwmask], ebx ;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; mov eax, [edx + dsNiceMatch] mov ebx, [edx + dsLookahead] cmp ebx, eax jl LookaheadLess mov ebx, eax LookaheadLess: mov [nicematch], ebx ;;; register Bytef *scan = s->window + s->strstart; mov esi, [edx + dsWindow] mov [window], esi mov ebp, [edx + dsStrStart] lea edi, [esi + ebp] mov [scan], edi ;;; Determine how many bytes the scan ptr is off from being ;;; dword-aligned. mov eax, edi neg eax and eax, 3 mov [scanalign], eax ;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? ;;; s->strstart - (IPos)MAX_DIST(s) : NIL; mov eax, [edx + dsWSize] sub eax, MIN_LOOKAHEAD sub ebp, eax jg LimitPositive xor ebp, ebp LimitPositive: ;;; int best_len = s->prev_length; mov eax, [edx + dsPrevLen] mov [bestlen], eax ;;; Store the sum of s->window + best_len in esi locally, and in esi. add esi, eax mov [windowbestlen], esi ;;; register ush scan_start = *(ushf*)scan; ;;; register ush scan_end = *(ushf*)(scan+best_len-1); ;;; Posf *prev = s->prev; movzx ebx, word ptr [edi] mov [scanstart], ebx movzx ebx, word ptr [edi + eax - 1] mov [scanend], ebx mov edi, [edx + dsPrev] ;;; Jump into the main loop. mov edx, [chainlenwmask] jmp short LoopEntry align 4 ;;; do { ;;; match = s->window + cur_match; ;;; if (*(ushf*)(match+best_len-1) != scan_end || ;;; *(ushf*)match != scan_start) continue; ;;; [...] ;;; } while ((cur_match = prev[cur_match & wmask]) > limit ;;; && --chain_length != 0); ;;; ;;; Here is the inner loop of the function. The function will spend the ;;; majority of its time in this loop, and majority of that time will ;;; be spent in the first ten instructions. ;;; ;;; Within this loop: ;;; ebx = scanend ;;; ecx = curmatch ;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) ;;; esi = windowbestlen - i.e., (window + bestlen) ;;; edi = prev ;;; ebp = limit LookupLoop: and ecx, edx movzx ecx, word ptr [edi + ecx*2] cmp ecx, ebp jbe LeaveNow sub edx, 00010000h js LeaveNow LoopEntry: movzx eax, word ptr [esi + ecx - 1] cmp eax, ebx jnz LookupLoop mov eax, [window] movzx eax, word ptr [eax + ecx] cmp eax, [scanstart] jnz LookupLoop ;;; Store the current value of chainlen. mov [chainlenwmask], edx ;;; Point edi to the string under scrutiny, and esi to the string we ;;; are hoping to match it up with. In actuality, esi and edi are ;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is ;;; initialized to -(MAX_MATCH_8 - scanalign). mov esi, [window] mov edi, [scan] add esi, ecx mov eax, [scanalign] mov edx, 0fffffef8h; -(MAX_MATCH_8) lea edi, [edi + eax + 0108h] ;MAX_MATCH_8] lea esi, [esi + eax + 0108h] ;MAX_MATCH_8] ;;; Test the strings for equality, 8 bytes at a time. At the end, ;;; adjust edx so that it is offset to the exact byte that mismatched. ;;; ;;; We already know at this point that the first three bytes of the ;;; strings match each other, and they can be safely passed over before ;;; starting the compare loop. So what this code does is skip over 0-3 ;;; bytes, as much as necessary in order to dword-align the edi ;;; pointer. (esi will still be misaligned three times out of four.) ;;; ;;; It should be confessed that this loop usually does not represent ;;; much of the total running time. Replacing it with a more ;;; straightforward "rep cmpsb" would not drastically degrade ;;; performance. LoopCmps: mov eax, [esi + edx] xor eax, [edi + edx] jnz LeaveLoopCmps mov eax, [esi + edx + 4] xor eax, [edi + edx + 4] jnz LeaveLoopCmps4 add edx, 8 jnz LoopCmps jmp short LenMaximum LeaveLoopCmps4: add edx, 4 LeaveLoopCmps: test eax, 0000FFFFh jnz LenLower add edx, 2 shr eax, 16 LenLower: sub al, 1 adc edx, 0 ;;; Calculate the length of the match. If it is longer than MAX_MATCH, ;;; then automatically accept it as the best possible match and leave. lea eax, [edi + edx] mov edi, [scan] sub eax, edi cmp eax, MAX_MATCH jge LenMaximum ;;; If the length of the match is not longer than the best match we ;;; have so far, then forget it and return to the lookup loop. mov edx, [deflatestate] mov ebx, [bestlen] cmp eax, ebx jg LongerMatch mov esi, [windowbestlen] mov edi, [edx + dsPrev] mov ebx, [scanend] mov edx, [chainlenwmask] jmp LookupLoop ;;; s->match_start = cur_match; ;;; best_len = len; ;;; if (len >= nice_match) break; ;;; scan_end = *(ushf*)(scan+best_len-1); LongerMatch: mov ebx, [nicematch] mov [bestlen], eax mov [edx + dsMatchStart], ecx cmp eax, ebx jge LeaveNow mov esi, [window] add esi, eax mov [windowbestlen], esi movzx ebx, word ptr [edi + eax - 1] mov edi, [edx + dsPrev] mov [scanend], ebx mov edx, [chainlenwmask] jmp LookupLoop ;;; Accept the current string, with the maximum possible length. LenMaximum: mov edx, [deflatestate] mov dword ptr [bestlen], MAX_MATCH mov [edx + dsMatchStart], ecx ;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; ;;; return s->lookahead; LeaveNow: mov edx, [deflatestate] mov ebx, [bestlen] mov eax, [edx + dsLookahead] cmp ebx, eax jg LookaheadRet mov eax, ebx LookaheadRet: ;;; Restore the stack and return from whence we came. add esp, LocalVarsSize pop ebx pop esi pop edi pop ebp ret ; please don't remove this string ! ; Your can freely use match686 in any free or commercial app if you don't remove the string in the binary! db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah IFDEF NOUNDERLINE longest_match endp ELSE _longest_match endp ENDIF IFDEF NOUNDERLINE match_init proc near ret match_init endp ELSE _match_init proc near ret _match_init endp ENDIF _TEXT ends end tcl8.6.5/compat/zlib/contrib/masmx86/readme.txt0000644000175000017500000000155112663653206020754 0ustar sergeisergei Summary ------- This directory contains ASM implementations of the functions longest_match() and inflate_fast(). Use instructions ---------------- Assemble using MASM, and copy the object files into the zlib source directory, then run the appropriate makefile, as suggested below. You can donwload MASM from here: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 You can also get objects files here: http://www.winimage.com/zLibDll/zlib124_masm_obj.zip Build instructions ------------------ * With Microsoft C and MASM: nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" * With Borland C and TASM: make -f win32/Makefile.bor LOCAL_ZLIB="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" OBJPA="+match686c.obj+match686.obj+inffas32.obj" tcl8.6.5/compat/zlib/contrib/infback9/0000755000175000017500000000000012665173607017143 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/infback9/inftree9.h0000644000175000017500000000552512663653206021044 0ustar sergeisergei/* inftree9.h -- header to use inftree9.c * Copyright (C) 1995-2008 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* Structure for decoding tables. Each entry provides either the information needed to do the operation requested by the code that indexed that table entry, or it provides a pointer to another table that indexes more bits of the code. op indicates whether the entry is a pointer to another table, a literal, a length or distance, an end-of-block, or an invalid code. For a table pointer, the low four bits of op is the number of index bits of that table. For a length or distance, the low four bits of op is the number of extra bits to get after the code. bits is the number of bits in this code or part of the code to drop off of the bit buffer. val is the actual byte to output in the case of a literal, the base length or distance, or the offset from the current table to the next table. Each entry is four bytes. */ typedef struct { unsigned char op; /* operation, extra bits, table bits */ unsigned char bits; /* bits in this part of the code */ unsigned short val; /* offset in table or code value */ } code; /* op values as set by inflate_table(): 00000000 - literal 0000tttt - table link, tttt != 0 is the number of table index bits 100eeeee - length or distance, eeee is the number of extra bits 01100000 - end of block 01000000 - invalid code */ /* Maximum size of the dynamic table. The maximum number of code structures is 1446, which is the sum of 852 for literal/length codes and 594 for distance codes. These values were found by exhaustive searches using the program examples/enough.c found in the zlib distribtution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns returns 852, and "enough 32 6 15" for distance codes returns 594. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in infback9.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ #define ENOUGH_LENS 852 #define ENOUGH_DISTS 594 #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) /* Type of code to build for inflate_table9() */ typedef enum { CODES, LENS, DISTS } codetype; extern int inflate_table9 OF((codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work)); tcl8.6.5/compat/zlib/contrib/infback9/inftree9.c0000644000175000017500000003213412663660064021033 0ustar sergeisergei/* inftree9.c -- generate Huffman trees for efficient decoding * Copyright (C) 1995-2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftree9.h" #define MAXBITS 15 const char inflate9_copyright[] = " inflate9 1.2.8 Copyright 1995-2013 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* Build a set of tables to decode the provided canonical Huffman code. The code lengths are lens[0..codes-1]. The result starts at *table, whose indices are 0..2^bits-1. work is a writable array of at least lens shorts, which is used as a work area. type is the type of code to be generated, CODES, LENS, or DISTS. On return, zero is success, -1 is an invalid code, and +1 means that ENOUGH isn't enough. table on return points to the next available entry's address. bits is the requested root table index bits, and on return it is the actual root table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ int inflate_table9(type, lens, codes, table, bits, work) codetype type; unsigned short FAR *lens; unsigned codes; code FAR * FAR *table; unsigned FAR *bits; unsigned short FAR *work; { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ unsigned root; /* number of index bits for root table */ unsigned curr; /* number of index bits for current table */ unsigned drop; /* code bits to drop for sub-table */ int left; /* number of prefix codes available */ unsigned used; /* code entries in table used */ unsigned huff; /* Huffman code */ unsigned incr; /* for incrementing code, index */ unsigned fill; /* index for replicating entries */ unsigned low; /* low bits for current root entry */ unsigned mask; /* mask for low root bits */ code this; /* table entry for duplication */ code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ int end; /* use base and extra for symbol > end */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 3, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, 133, 133, 133, 133, 144, 72, 78}; static const unsigned short dbase[32] = { /* Distance codes 0..31 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153}; static const unsigned short dext[32] = { /* Distance codes 0..31 extra */ 128, 128, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, 133, 133, 134, 134, 135, 135, 136, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141, 142, 142}; /* Process a set of code lengths to create a canonical Huffman code. The code lengths are lens[0..codes-1]. Each length corresponds to the symbols 0..codes-1. The Huffman code is generated by first sorting the symbols by length from short to long, and retaining the symbol order for codes with equal lengths. Then the code starts with all zero bits for the first code of the shortest length, and the codes are integer increments for the same length, and zeros are appended as the length increases. For the deflate format, these bits are stored backwards from their more natural integer increment ordering, and so when the decoding tables are built in the large loop below, the integer codes are incremented backwards. This routine assumes, but does not check, that all of the entries in lens[] are in the range 0..MAXBITS. The caller must assure this. 1..MAXBITS is interpreted as that code length. zero means that that symbol does not occur in this code. The codes are sorted by computing a count of codes for each length, creating from that a table of starting indices for each length in the sorted table, and then entering the symbols in order in the sorted table. The sorted table is work[], with that space being provided by the caller. The length counts are used for other purposes as well, i.e. finding the minimum and maximum length codes, determining if there are any codes at all, checking for a valid set of lengths, and looking ahead at length counts to determine sub-table sizes when building the decoding tables. */ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ for (len = 0; len <= MAXBITS; len++) count[len] = 0; for (sym = 0; sym < codes; sym++) count[lens[sym]]++; /* bound code lengths, force root to be within code lengths */ root = *bits; for (max = MAXBITS; max >= 1; max--) if (count[max] != 0) break; if (root > max) root = max; if (max == 0) return -1; /* no codes! */ for (min = 1; min <= MAXBITS; min++) if (count[min] != 0) break; if (root < min) root = min; /* check for an over-subscribed or incomplete set of lengths */ left = 1; for (len = 1; len <= MAXBITS; len++) { left <<= 1; left -= count[len]; if (left < 0) return -1; /* over-subscribed */ } if (left > 0 && (type == CODES || max != 1)) return -1; /* incomplete set */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + count[len]; /* sort symbols by length, by symbol order within each length */ for (sym = 0; sym < codes; sym++) if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; /* Create and fill in decoding tables. In this loop, the table being filled is at next and has curr index bits. The code being used is huff with length len. That code is converted to an index by dropping drop bits off of the bottom. For codes where len is less than drop + curr, those top drop + curr - len bits are incremented through all values to fill the table with replicated entries. root is the number of index bits for the root table. When len exceeds root, sub-tables are created pointed to by the root entry with an index of the low root bits of huff. This is saved in low to check for when a new sub-table should be started. drop is zero when the root table is being filled, and drop is root when sub-tables are being filled. When a new sub-table is needed, it is necessary to look ahead in the code lengths to determine what size sub-table is needed. The length counts are used for this, and so count[] is decremented as codes are entered in the tables. used keeps track of how many table entries have been allocated from the provided *table space. It is checked for LENS and DIST tables against the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in the initial root table size constants. See the comments in inftree9.h for more information. sym increments through all symbols, and the loop terminates when all codes of length max, i.e. all codes, have been processed. This routine permits incomplete codes, so another loop after this one fills in the rest of the decoding tables with invalid code markers. */ /* set up for code type */ switch (type) { case CODES: base = extra = work; /* dummy value--not used */ end = 19; break; case LENS: base = lbase; base -= 257; extra = lext; extra -= 257; end = 256; break; default: /* DISTS */ base = dbase; extra = dext; end = -1; } /* initialize state for loop */ huff = 0; /* starting code */ sym = 0; /* starting code symbol */ len = min; /* starting code length */ next = *table; /* current table to fill in */ curr = root; /* current table index bits */ drop = 0; /* current bits to drop from code for index */ low = (unsigned)(-1); /* trigger new sub-table when len > root */ used = 1U << root; /* use root table entries */ mask = used - 1; /* mask for comparing low */ /* check available table space */ if ((type == LENS && used >= ENOUGH_LENS) || (type == DISTS && used >= ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ for (;;) { /* create table entry */ this.bits = (unsigned char)(len - drop); if ((int)(work[sym]) < end) { this.op = (unsigned char)0; this.val = work[sym]; } else if ((int)(work[sym]) > end) { this.op = (unsigned char)(extra[work[sym]]); this.val = base[work[sym]]; } else { this.op = (unsigned char)(32 + 64); /* end of block */ this.val = 0; } /* replicate for those indices with low len bits equal to huff */ incr = 1U << (len - drop); fill = 1U << curr; do { fill -= incr; next[(huff >> drop) + fill] = this; } while (fill != 0); /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; /* go to next symbol, update count, len */ sym++; if (--(count[len]) == 0) { if (len == max) break; len = lens[work[sym]]; } /* create new sub-table if needed */ if (len > root && (huff & mask) != low) { /* if first time, transition to sub-tables */ if (drop == 0) drop = root; /* increment past last table */ next += 1U << curr; /* determine length of next table */ curr = len - drop; left = (int)(1 << curr); while (curr + drop < max) { left -= count[curr + drop]; if (left <= 0) break; curr++; left <<= 1; } /* check for enough space */ used += 1U << curr; if ((type == LENS && used >= ENOUGH_LENS) || (type == DISTS && used >= ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ low = huff & mask; (*table)[low].op = (unsigned char)curr; (*table)[low].bits = (unsigned char)root; (*table)[low].val = (unsigned short)(next - *table); } } /* Fill in rest of table for incomplete codes. This loop is similar to the loop above in incrementing huff for table indices. It is assumed that len is equal to curr + drop, so there is no loop needed to increment through high index bits. When the current sub-table is filled, the loop drops back to the root table to fill in any remaining entries there. */ this.op = (unsigned char)64; /* invalid code marker */ this.bits = (unsigned char)(len - drop); this.val = (unsigned short)0; while (huff != 0) { /* when done with sub-table, drop back to root table */ if (drop != 0 && (huff & mask) != low) { drop = 0; len = root; next = *table; curr = root; this.bits = (unsigned char)len; } /* put invalid code marker in table */ next[huff >> drop] = this; /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; } /* set return parameters */ *table += used; *bits = root; return 0; } tcl8.6.5/compat/zlib/contrib/infback9/infback9.h0000644000175000017500000000307212663653131020775 0ustar sergeisergei/* infback9.h -- header for using inflateBack9 functions * Copyright (C) 2003 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * This header file and associated patches provide a decoder for PKWare's * undocumented deflate64 compression method (method 9). Use with infback9.c, * inftree9.h, inftree9.c, and inffix9.h. These patches are not supported. * This should be compiled with zlib, since it uses zutil.h and zutil.o. * This code has not yet been tested on 16-bit architectures. See the * comments in zlib.h for inflateBack() usage. These functions are used * identically, except that there is no windowBits parameter, and a 64K * window must be provided. Also if int's are 16 bits, then a zero for * the third parameter of the "out" function actually means 65536UL. * zlib.h must be included before this header file. */ #ifdef __cplusplus extern "C" { #endif ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)); ZEXTERN int ZEXPORT inflateBack9End OF((z_stream FAR *strm)); ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm, unsigned char FAR *window, const char *version, int stream_size)); #define inflateBack9Init(strm, window) \ inflateBack9Init_((strm), (window), \ ZLIB_VERSION, sizeof(z_stream)) #ifdef __cplusplus } #endif tcl8.6.5/compat/zlib/contrib/infback9/inflate9.h0000644000175000017500000000370712663653131021027 0ustar sergeisergei/* inflate9.h -- internal inflate state definition * Copyright (C) 1995-2003 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* Possible inflate modes between inflate() calls */ typedef enum { TYPE, /* i: waiting for type bits, including last-flag bit */ STORED, /* i: waiting for stored size (length and complement) */ TABLE, /* i: waiting for dynamic block table lengths */ LEN, /* i: waiting for length/lit code */ DONE, /* finished check, done -- remain here until reset */ BAD /* got a data error -- remain here until reset */ } inflate_mode; /* State transitions between above modes - (most modes can go to the BAD mode -- not shown for clarity) Read deflate blocks: TYPE -> STORED or TABLE or LEN or DONE STORED -> TYPE TABLE -> LENLENS -> CODELENS -> LEN Read deflate codes: LEN -> LEN or TYPE */ /* state maintained between inflate() calls. Approximately 7K bytes. */ struct inflate_state { /* sliding window */ unsigned char FAR *window; /* allocated sliding window, if needed */ /* dynamic table building */ unsigned ncode; /* number of code length code lengths */ unsigned nlen; /* number of length code lengths */ unsigned ndist; /* number of distance code lengths */ unsigned have; /* number of code lengths in lens[] */ code FAR *next; /* next available space in codes[] */ unsigned short lens[320]; /* temporary storage for code lengths */ unsigned short work[288]; /* work area for code table building */ code codes[ENOUGH]; /* space for code tables */ }; tcl8.6.5/compat/zlib/contrib/infback9/infback9.c0000644000175000017500000005217512663660064021003 0ustar sergeisergei/* infback9.c -- inflate deflate64 data using a call-back interface * Copyright (C) 1995-2008 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "infback9.h" #include "inftree9.h" #include "inflate9.h" #define WSIZE 65536UL /* strm provides memory allocation functions in zalloc and zfree, or Z_NULL to use the library memory allocation functions. window is a user-supplied window and output buffer that is 64K bytes. */ int ZEXPORT inflateBack9Init_(strm, window, version, stream_size) z_stream FAR *strm; unsigned char FAR *window; const char *version; int stream_size; { struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL || window == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { strm->zalloc = zcalloc; strm->opaque = (voidpf)0; } if (strm->zfree == (free_func)0) strm->zfree = zcfree; state = (struct inflate_state FAR *)ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (voidpf)state; state->window = window; return Z_OK; } /* Build and output length and distance decoding tables for fixed code decoding. */ #ifdef MAKEFIXED #include void makefixed9(void) { unsigned sym, bits, low, size; code *next, *lenfix, *distfix; struct inflate_state state; code fixed[544]; /* literal/length table */ sym = 0; while (sym < 144) state.lens[sym++] = 8; while (sym < 256) state.lens[sym++] = 9; while (sym < 280) state.lens[sym++] = 7; while (sym < 288) state.lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table9(LENS, state.lens, 288, &(next), &(bits), state.work); /* distance table */ sym = 0; while (sym < 32) state.lens[sym++] = 5; distfix = next; bits = 5; inflate_table9(DISTS, state.lens, 32, &(next), &(bits), state.work); /* write tables */ puts(" /* inffix9.h -- table for decoding deflate64 fixed codes"); puts(" * Generated automatically by makefixed9()."); puts(" */"); puts(""); puts(" /* WARNING: this file should *not* be used by applications."); puts(" It is part of the implementation of this library and is"); puts(" subject to change. Applications should only use zlib.h."); puts(" */"); puts(""); size = 1U << 9; printf(" static const code lenfix[%u] = {", size); low = 0; for (;;) { if ((low % 6) == 0) printf("\n "); printf("{%u,%u,%d}", lenfix[low].op, lenfix[low].bits, lenfix[low].val); if (++low == size) break; putchar(','); } puts("\n };"); size = 1U << 5; printf("\n static const code distfix[%u] = {", size); low = 0; for (;;) { if ((low % 5) == 0) printf("\n "); printf("{%u,%u,%d}", distfix[low].op, distfix[low].bits, distfix[low].val); if (++low == size) break; putchar(','); } puts("\n };"); } #endif /* MAKEFIXED */ /* Macros for inflateBack(): */ /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Assure that some input is available. If input is requested, but denied, then return a Z_BUF_ERROR from inflateBack(). */ #define PULL() \ do { \ if (have == 0) { \ have = in(in_desc, &next); \ if (have == 0) { \ next = Z_NULL; \ ret = Z_BUF_ERROR; \ goto inf_leave; \ } \ } \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflateBack() with an error if there is no input available. */ #define PULLBYTE() \ do { \ PULL(); \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflateBack() with an error. */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n <= 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* Assure that some output space is available, by writing out the window if it's full. If the write fails, return from inflateBack() with a Z_BUF_ERROR. */ #define ROOM() \ do { \ if (left == 0) { \ put = window; \ left = WSIZE; \ wrap = 1; \ if (out(out_desc, put, (unsigned)left)) { \ ret = Z_BUF_ERROR; \ goto inf_leave; \ } \ } \ } while (0) /* strm provides the memory allocation functions and window buffer on input, and provides information on the unused input on return. For Z_DATA_ERROR returns, strm will also provide an error message. in() and out() are the call-back input and output functions. When inflateBack() needs more input, it calls in(). When inflateBack() has filled the window with output, or when it completes with data in the window, it calls out() to write out the data. The application must not change the provided input until in() is called again or inflateBack() returns. The application must not change the window/output buffer until inflateBack() returns. in() and out() are called with a descriptor parameter provided in the inflateBack() call. This parameter can be a structure that provides the information required to do the read or write, as well as accumulated information on the input and output such as totals and check values. in() should return zero on failure. out() should return non-zero on failure. If either in() or out() fails, than inflateBack() returns a Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it was in() or out() that caused in the error. Otherwise, inflateBack() returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format error, or Z_MEM_ERROR if it could not allocate memory for the state. inflateBack() can also return Z_STREAM_ERROR if the input parameters are not correct, i.e. strm is Z_NULL or the state was not initialized. */ int ZEXPORT inflateBack9(strm, in, in_desc, out, out_desc) z_stream FAR *strm; in_func in; void FAR *in_desc; out_func out; void FAR *out_desc; { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have; /* available input */ unsigned long left; /* available output */ inflate_mode mode; /* current inflate mode */ int lastblock; /* true if processing last block */ int wrap; /* true if the window has wrapped */ unsigned char FAR *window; /* allocated sliding window, if needed */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned extra; /* extra bits needed */ unsigned long length; /* literal or length of data to copy */ unsigned long offset; /* distance back to copy string from */ unsigned long copy; /* number of stored or match bytes to copy */ unsigned char FAR *from; /* where to copy match bytes from */ code const FAR *lencode; /* starting table for length/literal codes */ code const FAR *distcode; /* starting table for distance codes */ unsigned lenbits; /* index bits for lencode */ unsigned distbits; /* index bits for distcode */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; #include "inffix9.h" /* Check that the strm exists and that the state was initialized */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* Reset the state */ strm->msg = Z_NULL; mode = TYPE; lastblock = 0; wrap = 0; window = state->window; next = strm->next_in; have = next != Z_NULL ? strm->avail_in : 0; hold = 0; bits = 0; put = window; left = WSIZE; lencode = Z_NULL; distcode = Z_NULL; /* Inflate until end of block marked as last */ for (;;) switch (mode) { case TYPE: /* determine and dispatch block type */ if (lastblock) { BYTEBITS(); mode = DONE; break; } NEEDBITS(3); lastblock = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", lastblock ? " (last)" : "")); mode = STORED; break; case 1: /* fixed block */ lencode = lenfix; lenbits = 9; distcode = distfix; distbits = 5; Tracev((stderr, "inflate: fixed codes block%s\n", lastblock ? " (last)" : "")); mode = LEN; /* decode codes */ break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", lastblock ? " (last)" : "")); mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; mode = BAD; } DROPBITS(2); break; case STORED: /* get and verify stored block length */ BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; mode = BAD; break; } length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %lu\n", length)); INITBITS(); /* copy stored block from input to output */ while (length != 0) { copy = length; PULL(); ROOM(); if (copy > have) copy = have; if (copy > left) copy = left; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; length -= copy; } Tracev((stderr, "inflate: stored end\n")); mode = TYPE; break; case TABLE: /* get dynamic table entries descriptor */ NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); if (state->nlen > 286) { strm->msg = (char *)"too many length symbols"; mode = BAD; break; } Tracev((stderr, "inflate: table sizes ok\n")); /* get code length code lengths (not a typo) */ state->have = 0; while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; lencode = (code const FAR *)(state->next); lenbits = 7; ret = inflate_table9(CODES, state->lens, 19, &(state->next), &(lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); /* get length and distance code code lengths */ state->have = 0; while (state->have < state->nlen + state->ndist) { for (;;) { here = lencode[BITS(lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; mode = BAD; break; } len = (unsigned)(state->lens[state->have - 1]); copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (mode == BAD) break; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { strm->msg = (char *)"invalid code -- missing end-of-block"; mode = BAD; break; } /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftree9.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; lencode = (code const FAR *)(state->next); lenbits = 9; ret = inflate_table9(LENS, state->lens, state->nlen, &(state->next), &(lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; mode = BAD; break; } distcode = (code const FAR *)(state->next); distbits = 6; ret = inflate_table9(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); mode = LEN; case LEN: /* get a literal, length, or end-of-block code */ for (;;) { here = lencode[BITS(lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); length = (unsigned)here.val; /* process literal */ if (here.op == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); ROOM(); *put++ = (unsigned char)(length); left--; mode = LEN; break; } /* process end of block */ if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); mode = TYPE; break; } /* invalid code */ if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; mode = BAD; break; } /* length code -- get extra bits, if any */ extra = (unsigned)(here.op) & 31; if (extra != 0) { NEEDBITS(extra); length += BITS(extra); DROPBITS(extra); } Tracevv((stderr, "inflate: length %lu\n", length)); /* get distance code */ for (;;) { here = distcode[BITS(distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); if (here.op & 64) { strm->msg = (char *)"invalid distance code"; mode = BAD; break; } offset = (unsigned)here.val; /* get distance extra bits, if any */ extra = (unsigned)(here.op) & 15; if (extra != 0) { NEEDBITS(extra); offset += BITS(extra); DROPBITS(extra); } if (offset > WSIZE - (wrap ? 0: left)) { strm->msg = (char *)"invalid distance too far back"; mode = BAD; break; } Tracevv((stderr, "inflate: distance %lu\n", offset)); /* copy match from window to output */ do { ROOM(); copy = WSIZE - offset; if (copy < left) { from = put + copy; copy = left - copy; } else { from = put - offset; copy = left; } if (copy > length) copy = length; length -= copy; left -= copy; do { *put++ = *from++; } while (--copy); } while (length != 0); break; case DONE: /* inflate stream terminated properly -- write leftover output */ ret = Z_STREAM_END; if (left < WSIZE) { if (out(out_desc, window, (unsigned)(WSIZE - left))) ret = Z_BUF_ERROR; } goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; default: /* can't happen, but makes compilers happy */ ret = Z_STREAM_ERROR; goto inf_leave; } /* Return unused input */ inf_leave: strm->next_in = next; strm->avail_in = have; return ret; } int ZEXPORT inflateBack9End(strm) z_stream FAR *strm; { if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } tcl8.6.5/compat/zlib/contrib/infback9/inffix9.h0000644000175000017500000001470712663653131020672 0ustar sergeisergei /* inffix9.h -- table for decoding deflate64 fixed codes * Generated automatically by makefixed9(). */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of this library and is subject to change. Applications should only use zlib.h. */ static const code lenfix[512] = { {96,7,0},{0,8,80},{0,8,16},{132,8,115},{130,7,31},{0,8,112}, {0,8,48},{0,9,192},{128,7,10},{0,8,96},{0,8,32},{0,9,160}, {0,8,0},{0,8,128},{0,8,64},{0,9,224},{128,7,6},{0,8,88}, {0,8,24},{0,9,144},{131,7,59},{0,8,120},{0,8,56},{0,9,208}, {129,7,17},{0,8,104},{0,8,40},{0,9,176},{0,8,8},{0,8,136}, {0,8,72},{0,9,240},{128,7,4},{0,8,84},{0,8,20},{133,8,227}, {131,7,43},{0,8,116},{0,8,52},{0,9,200},{129,7,13},{0,8,100}, {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232}, {128,7,8},{0,8,92},{0,8,28},{0,9,152},{132,7,83},{0,8,124}, {0,8,60},{0,9,216},{130,7,23},{0,8,108},{0,8,44},{0,9,184}, {0,8,12},{0,8,140},{0,8,76},{0,9,248},{128,7,3},{0,8,82}, {0,8,18},{133,8,163},{131,7,35},{0,8,114},{0,8,50},{0,9,196}, {129,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},{0,8,130}, {0,8,66},{0,9,228},{128,7,7},{0,8,90},{0,8,26},{0,9,148}, {132,7,67},{0,8,122},{0,8,58},{0,9,212},{130,7,19},{0,8,106}, {0,8,42},{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244}, {128,7,5},{0,8,86},{0,8,22},{65,8,0},{131,7,51},{0,8,118}, {0,8,54},{0,9,204},{129,7,15},{0,8,102},{0,8,38},{0,9,172}, {0,8,6},{0,8,134},{0,8,70},{0,9,236},{128,7,9},{0,8,94}, {0,8,30},{0,9,156},{132,7,99},{0,8,126},{0,8,62},{0,9,220}, {130,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{133,8,131}, {130,7,31},{0,8,113},{0,8,49},{0,9,194},{128,7,10},{0,8,97}, {0,8,33},{0,9,162},{0,8,1},{0,8,129},{0,8,65},{0,9,226}, {128,7,6},{0,8,89},{0,8,25},{0,9,146},{131,7,59},{0,8,121}, {0,8,57},{0,9,210},{129,7,17},{0,8,105},{0,8,41},{0,9,178}, {0,8,9},{0,8,137},{0,8,73},{0,9,242},{128,7,4},{0,8,85}, {0,8,21},{144,8,3},{131,7,43},{0,8,117},{0,8,53},{0,9,202}, {129,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133}, {0,8,69},{0,9,234},{128,7,8},{0,8,93},{0,8,29},{0,9,154}, {132,7,83},{0,8,125},{0,8,61},{0,9,218},{130,7,23},{0,8,109}, {0,8,45},{0,9,186},{0,8,13},{0,8,141},{0,8,77},{0,9,250}, {128,7,3},{0,8,83},{0,8,19},{133,8,195},{131,7,35},{0,8,115}, {0,8,51},{0,9,198},{129,7,11},{0,8,99},{0,8,35},{0,9,166}, {0,8,3},{0,8,131},{0,8,67},{0,9,230},{128,7,7},{0,8,91}, {0,8,27},{0,9,150},{132,7,67},{0,8,123},{0,8,59},{0,9,214}, {130,7,19},{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139}, {0,8,75},{0,9,246},{128,7,5},{0,8,87},{0,8,23},{77,8,0}, {131,7,51},{0,8,119},{0,8,55},{0,9,206},{129,7,15},{0,8,103}, {0,8,39},{0,9,174},{0,8,7},{0,8,135},{0,8,71},{0,9,238}, {128,7,9},{0,8,95},{0,8,31},{0,9,158},{132,7,99},{0,8,127}, {0,8,63},{0,9,222},{130,7,27},{0,8,111},{0,8,47},{0,9,190}, {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80}, {0,8,16},{132,8,115},{130,7,31},{0,8,112},{0,8,48},{0,9,193}, {128,7,10},{0,8,96},{0,8,32},{0,9,161},{0,8,0},{0,8,128}, {0,8,64},{0,9,225},{128,7,6},{0,8,88},{0,8,24},{0,9,145}, {131,7,59},{0,8,120},{0,8,56},{0,9,209},{129,7,17},{0,8,104}, {0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},{0,9,241}, {128,7,4},{0,8,84},{0,8,20},{133,8,227},{131,7,43},{0,8,116}, {0,8,52},{0,9,201},{129,7,13},{0,8,100},{0,8,36},{0,9,169}, {0,8,4},{0,8,132},{0,8,68},{0,9,233},{128,7,8},{0,8,92}, {0,8,28},{0,9,153},{132,7,83},{0,8,124},{0,8,60},{0,9,217}, {130,7,23},{0,8,108},{0,8,44},{0,9,185},{0,8,12},{0,8,140}, {0,8,76},{0,9,249},{128,7,3},{0,8,82},{0,8,18},{133,8,163}, {131,7,35},{0,8,114},{0,8,50},{0,9,197},{129,7,11},{0,8,98}, {0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, {128,7,7},{0,8,90},{0,8,26},{0,9,149},{132,7,67},{0,8,122}, {0,8,58},{0,9,213},{130,7,19},{0,8,106},{0,8,42},{0,9,181}, {0,8,10},{0,8,138},{0,8,74},{0,9,245},{128,7,5},{0,8,86}, {0,8,22},{65,8,0},{131,7,51},{0,8,118},{0,8,54},{0,9,205}, {129,7,15},{0,8,102},{0,8,38},{0,9,173},{0,8,6},{0,8,134}, {0,8,70},{0,9,237},{128,7,9},{0,8,94},{0,8,30},{0,9,157}, {132,7,99},{0,8,126},{0,8,62},{0,9,221},{130,7,27},{0,8,110}, {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253}, {96,7,0},{0,8,81},{0,8,17},{133,8,131},{130,7,31},{0,8,113}, {0,8,49},{0,9,195},{128,7,10},{0,8,97},{0,8,33},{0,9,163}, {0,8,1},{0,8,129},{0,8,65},{0,9,227},{128,7,6},{0,8,89}, {0,8,25},{0,9,147},{131,7,59},{0,8,121},{0,8,57},{0,9,211}, {129,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},{0,8,137}, {0,8,73},{0,9,243},{128,7,4},{0,8,85},{0,8,21},{144,8,3}, {131,7,43},{0,8,117},{0,8,53},{0,9,203},{129,7,13},{0,8,101}, {0,8,37},{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235}, {128,7,8},{0,8,93},{0,8,29},{0,9,155},{132,7,83},{0,8,125}, {0,8,61},{0,9,219},{130,7,23},{0,8,109},{0,8,45},{0,9,187}, {0,8,13},{0,8,141},{0,8,77},{0,9,251},{128,7,3},{0,8,83}, {0,8,19},{133,8,195},{131,7,35},{0,8,115},{0,8,51},{0,9,199}, {129,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, {0,8,67},{0,9,231},{128,7,7},{0,8,91},{0,8,27},{0,9,151}, {132,7,67},{0,8,123},{0,8,59},{0,9,215},{130,7,19},{0,8,107}, {0,8,43},{0,9,183},{0,8,11},{0,8,139},{0,8,75},{0,9,247}, {128,7,5},{0,8,87},{0,8,23},{77,8,0},{131,7,51},{0,8,119}, {0,8,55},{0,9,207},{129,7,15},{0,8,103},{0,8,39},{0,9,175}, {0,8,7},{0,8,135},{0,8,71},{0,9,239},{128,7,9},{0,8,95}, {0,8,31},{0,9,159},{132,7,99},{0,8,127},{0,8,63},{0,9,223}, {130,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143}, {0,8,79},{0,9,255} }; static const code distfix[32] = { {128,5,1},{135,5,257},{131,5,17},{139,5,4097},{129,5,5}, {137,5,1025},{133,5,65},{141,5,16385},{128,5,3},{136,5,513}, {132,5,33},{140,5,8193},{130,5,9},{138,5,2049},{134,5,129}, {142,5,32769},{128,5,2},{135,5,385},{131,5,25},{139,5,6145}, {129,5,7},{137,5,1537},{133,5,97},{141,5,24577},{128,5,4}, {136,5,769},{132,5,49},{140,5,12289},{130,5,13},{138,5,3073}, {134,5,193},{142,5,49153} }; tcl8.6.5/compat/zlib/contrib/infback9/README0000644000175000017500000000006312663653131020013 0ustar sergeisergeiSee infback9.h for what this is and how to use it. tcl8.6.5/compat/zlib/contrib/amd64/0000755000175000017500000000000012665173607016370 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/amd64/amd64-match.S0000644000175000017500000003020212663653206020512 0ustar sergeisergei/* * match.S -- optimized version of longest_match() * based on the similar work by Gilles Vollant, and Brian Raiter, written 1998 * * This is free software; you can redistribute it and/or modify it * under the terms of the BSD License. Use by owners of Che Guevarra * parafernalia is prohibited, where possible, and highly discouraged * elsewhere. */ #ifndef NO_UNDERLINE # define match_init _match_init # define longest_match _longest_match #endif #define scanend ebx #define scanendw bx #define chainlenwmask edx /* high word: current chain len low word: s->wmask */ #define curmatch rsi #define curmatchd esi #define windowbestlen r8 #define scanalign r9 #define scanalignd r9d #define window r10 #define bestlen r11 #define bestlend r11d #define scanstart r12d #define scanstartw r12w #define scan r13 #define nicematch r14d #define limit r15 #define limitd r15d #define prev rcx /* * The 258 is a "magic number, not a parameter -- changing it * breaks the hell loose */ #define MAX_MATCH (258) #define MIN_MATCH (3) #define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) #define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) /* stack frame offsets */ #define LocalVarsSize (112) #define _chainlenwmask ( 8-LocalVarsSize)(%rsp) #define _windowbestlen (16-LocalVarsSize)(%rsp) #define save_r14 (24-LocalVarsSize)(%rsp) #define save_rsi (32-LocalVarsSize)(%rsp) #define save_rbx (40-LocalVarsSize)(%rsp) #define save_r12 (56-LocalVarsSize)(%rsp) #define save_r13 (64-LocalVarsSize)(%rsp) #define save_r15 (80-LocalVarsSize)(%rsp) .globl match_init, longest_match /* * On AMD64 the first argument of a function (in our case -- the pointer to * deflate_state structure) is passed in %rdi, hence our offsets below are * all off of that. */ /* you can check the structure offset by running #include #include #include "deflate.h" void print_depl() { deflate_state ds; deflate_state *s=&ds; printf("size pointer=%u\n",(int)sizeof(void*)); printf("#define dsWSize (%3u)(%%rdi)\n",(int)(((char*)&(s->w_size))-((char*)s))); printf("#define dsWMask (%3u)(%%rdi)\n",(int)(((char*)&(s->w_mask))-((char*)s))); printf("#define dsWindow (%3u)(%%rdi)\n",(int)(((char*)&(s->window))-((char*)s))); printf("#define dsPrev (%3u)(%%rdi)\n",(int)(((char*)&(s->prev))-((char*)s))); printf("#define dsMatchLen (%3u)(%%rdi)\n",(int)(((char*)&(s->match_length))-((char*)s))); printf("#define dsPrevMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_match))-((char*)s))); printf("#define dsStrStart (%3u)(%%rdi)\n",(int)(((char*)&(s->strstart))-((char*)s))); printf("#define dsMatchStart (%3u)(%%rdi)\n",(int)(((char*)&(s->match_start))-((char*)s))); printf("#define dsLookahead (%3u)(%%rdi)\n",(int)(((char*)&(s->lookahead))-((char*)s))); printf("#define dsPrevLen (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_length))-((char*)s))); printf("#define dsMaxChainLen (%3u)(%%rdi)\n",(int)(((char*)&(s->max_chain_length))-((char*)s))); printf("#define dsGoodMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->good_match))-((char*)s))); printf("#define dsNiceMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->nice_match))-((char*)s))); } */ /* to compile for XCode 3.2 on MacOSX x86_64 - run "gcc -g -c -DXCODE_MAC_X64_STRUCTURE amd64-match.S" */ #ifndef CURRENT_LINX_XCODE_MAC_X64_STRUCTURE #define dsWSize ( 68)(%rdi) #define dsWMask ( 76)(%rdi) #define dsWindow ( 80)(%rdi) #define dsPrev ( 96)(%rdi) #define dsMatchLen (144)(%rdi) #define dsPrevMatch (148)(%rdi) #define dsStrStart (156)(%rdi) #define dsMatchStart (160)(%rdi) #define dsLookahead (164)(%rdi) #define dsPrevLen (168)(%rdi) #define dsMaxChainLen (172)(%rdi) #define dsGoodMatch (188)(%rdi) #define dsNiceMatch (192)(%rdi) #else #ifndef STRUCT_OFFSET # define STRUCT_OFFSET (0) #endif #define dsWSize ( 56 + STRUCT_OFFSET)(%rdi) #define dsWMask ( 64 + STRUCT_OFFSET)(%rdi) #define dsWindow ( 72 + STRUCT_OFFSET)(%rdi) #define dsPrev ( 88 + STRUCT_OFFSET)(%rdi) #define dsMatchLen (136 + STRUCT_OFFSET)(%rdi) #define dsPrevMatch (140 + STRUCT_OFFSET)(%rdi) #define dsStrStart (148 + STRUCT_OFFSET)(%rdi) #define dsMatchStart (152 + STRUCT_OFFSET)(%rdi) #define dsLookahead (156 + STRUCT_OFFSET)(%rdi) #define dsPrevLen (160 + STRUCT_OFFSET)(%rdi) #define dsMaxChainLen (164 + STRUCT_OFFSET)(%rdi) #define dsGoodMatch (180 + STRUCT_OFFSET)(%rdi) #define dsNiceMatch (184 + STRUCT_OFFSET)(%rdi) #endif .text /* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ longest_match: /* * Retrieve the function arguments. %curmatch will hold cur_match * throughout the entire function (passed via rsi on amd64). * rdi will hold the pointer to the deflate_state (first arg on amd64) */ mov %rsi, save_rsi mov %rbx, save_rbx mov %r12, save_r12 mov %r13, save_r13 mov %r14, save_r14 mov %r15, save_r15 /* uInt wmask = s->w_mask; */ /* unsigned chain_length = s->max_chain_length; */ /* if (s->prev_length >= s->good_match) { */ /* chain_length >>= 2; */ /* } */ movl dsPrevLen, %eax movl dsGoodMatch, %ebx cmpl %ebx, %eax movl dsWMask, %eax movl dsMaxChainLen, %chainlenwmask jl LastMatchGood shrl $2, %chainlenwmask LastMatchGood: /* chainlen is decremented once beforehand so that the function can */ /* use the sign flag instead of the zero flag for the exit test. */ /* It is then shifted into the high word, to make room for the wmask */ /* value, which it will always accompany. */ decl %chainlenwmask shll $16, %chainlenwmask orl %eax, %chainlenwmask /* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ movl dsNiceMatch, %eax movl dsLookahead, %ebx cmpl %eax, %ebx jl LookaheadLess movl %eax, %ebx LookaheadLess: movl %ebx, %nicematch /* register Bytef *scan = s->window + s->strstart; */ mov dsWindow, %window movl dsStrStart, %limitd lea (%limit, %window), %scan /* Determine how many bytes the scan ptr is off from being */ /* dword-aligned. */ mov %scan, %scanalign negl %scanalignd andl $3, %scanalignd /* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ /* s->strstart - (IPos)MAX_DIST(s) : NIL; */ movl dsWSize, %eax subl $MIN_LOOKAHEAD, %eax xorl %ecx, %ecx subl %eax, %limitd cmovng %ecx, %limitd /* int best_len = s->prev_length; */ movl dsPrevLen, %bestlend /* Store the sum of s->window + best_len in %windowbestlen locally, and in memory. */ lea (%window, %bestlen), %windowbestlen mov %windowbestlen, _windowbestlen /* register ush scan_start = *(ushf*)scan; */ /* register ush scan_end = *(ushf*)(scan+best_len-1); */ /* Posf *prev = s->prev; */ movzwl (%scan), %scanstart movzwl -1(%scan, %bestlen), %scanend mov dsPrev, %prev /* Jump into the main loop. */ movl %chainlenwmask, _chainlenwmask jmp LoopEntry .balign 16 /* do { * match = s->window + cur_match; * if (*(ushf*)(match+best_len-1) != scan_end || * *(ushf*)match != scan_start) continue; * [...] * } while ((cur_match = prev[cur_match & wmask]) > limit * && --chain_length != 0); * * Here is the inner loop of the function. The function will spend the * majority of its time in this loop, and majority of that time will * be spent in the first ten instructions. */ LookupLoop: andl %chainlenwmask, %curmatchd movzwl (%prev, %curmatch, 2), %curmatchd cmpl %limitd, %curmatchd jbe LeaveNow subl $0x00010000, %chainlenwmask js LeaveNow LoopEntry: cmpw -1(%windowbestlen, %curmatch), %scanendw jne LookupLoop cmpw %scanstartw, (%window, %curmatch) jne LookupLoop /* Store the current value of chainlen. */ movl %chainlenwmask, _chainlenwmask /* %scan is the string under scrutiny, and %prev to the string we */ /* are hoping to match it up with. In actuality, %esi and %edi are */ /* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ /* initialized to -(MAX_MATCH_8 - scanalign). */ mov $(-MAX_MATCH_8), %rdx lea (%curmatch, %window), %windowbestlen lea MAX_MATCH_8(%windowbestlen, %scanalign), %windowbestlen lea MAX_MATCH_8(%scan, %scanalign), %prev /* the prefetching below makes very little difference... */ prefetcht1 (%windowbestlen, %rdx) prefetcht1 (%prev, %rdx) /* * Test the strings for equality, 8 bytes at a time. At the end, * adjust %rdx so that it is offset to the exact byte that mismatched. * * It should be confessed that this loop usually does not represent * much of the total running time. Replacing it with a more * straightforward "rep cmpsb" would not drastically degrade * performance -- unrolling it, for example, makes no difference. */ #undef USE_SSE /* works, but is 6-7% slower, than non-SSE... */ LoopCmps: #ifdef USE_SSE /* Preload the SSE registers */ movdqu (%windowbestlen, %rdx), %xmm1 movdqu (%prev, %rdx), %xmm2 pcmpeqb %xmm2, %xmm1 movdqu 16(%windowbestlen, %rdx), %xmm3 movdqu 16(%prev, %rdx), %xmm4 pcmpeqb %xmm4, %xmm3 movdqu 32(%windowbestlen, %rdx), %xmm5 movdqu 32(%prev, %rdx), %xmm6 pcmpeqb %xmm6, %xmm5 movdqu 48(%windowbestlen, %rdx), %xmm7 movdqu 48(%prev, %rdx), %xmm8 pcmpeqb %xmm8, %xmm7 /* Check the comparisions' results */ pmovmskb %xmm1, %rax notw %ax bsfw %ax, %ax jnz LeaveLoopCmps /* this is the only iteration of the loop with a possibility of having incremented rdx by 0x108 (each loop iteration add 16*4 = 0x40 and (0x40*4)+8=0x108 */ add $8, %rdx jz LenMaximum add $8, %rdx pmovmskb %xmm3, %rax notw %ax bsfw %ax, %ax jnz LeaveLoopCmps add $16, %rdx pmovmskb %xmm5, %rax notw %ax bsfw %ax, %ax jnz LeaveLoopCmps add $16, %rdx pmovmskb %xmm7, %rax notw %ax bsfw %ax, %ax jnz LeaveLoopCmps add $16, %rdx jmp LoopCmps LeaveLoopCmps: add %rax, %rdx #else mov (%windowbestlen, %rdx), %rax xor (%prev, %rdx), %rax jnz LeaveLoopCmps mov 8(%windowbestlen, %rdx), %rax xor 8(%prev, %rdx), %rax jnz LeaveLoopCmps8 mov 16(%windowbestlen, %rdx), %rax xor 16(%prev, %rdx), %rax jnz LeaveLoopCmps16 add $24, %rdx jnz LoopCmps jmp LenMaximum # if 0 /* * This three-liner is tantalizingly simple, but bsf is a slow instruction, * and the complicated alternative down below is quite a bit faster. Sad... */ LeaveLoopCmps: bsf %rax, %rax /* find the first non-zero bit */ shrl $3, %eax /* divide by 8 to get the byte */ add %rax, %rdx # else LeaveLoopCmps16: add $8, %rdx LeaveLoopCmps8: add $8, %rdx LeaveLoopCmps: testl $0xFFFFFFFF, %eax /* Check the first 4 bytes */ jnz Check16 add $4, %rdx shr $32, %rax Check16: testw $0xFFFF, %ax jnz LenLower add $2, %rdx shrl $16, %eax LenLower: subb $1, %al adc $0, %rdx # endif #endif /* Calculate the length of the match. If it is longer than MAX_MATCH, */ /* then automatically accept it as the best possible match and leave. */ lea (%prev, %rdx), %rax sub %scan, %rax cmpl $MAX_MATCH, %eax jge LenMaximum /* If the length of the match is not longer than the best match we */ /* have so far, then forget it and return to the lookup loop. */ cmpl %bestlend, %eax jg LongerMatch mov _windowbestlen, %windowbestlen mov dsPrev, %prev movl _chainlenwmask, %edx jmp LookupLoop /* s->match_start = cur_match; */ /* best_len = len; */ /* if (len >= nice_match) break; */ /* scan_end = *(ushf*)(scan+best_len-1); */ LongerMatch: movl %eax, %bestlend movl %curmatchd, dsMatchStart cmpl %nicematch, %eax jge LeaveNow lea (%window, %bestlen), %windowbestlen mov %windowbestlen, _windowbestlen movzwl -1(%scan, %rax), %scanend mov dsPrev, %prev movl _chainlenwmask, %chainlenwmask jmp LookupLoop /* Accept the current string, with the maximum possible length. */ LenMaximum: movl $MAX_MATCH, %bestlend movl %curmatchd, dsMatchStart /* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ /* return s->lookahead; */ LeaveNow: movl dsLookahead, %eax cmpl %eax, %bestlend cmovngl %bestlend, %eax LookaheadRet: /* Restore the registers and return from whence we came. */ mov save_rsi, %rsi mov save_rbx, %rbx mov save_r12, %r12 mov save_r13, %r13 mov save_r14, %r14 mov save_r15, %r15 ret match_init: ret tcl8.6.5/compat/zlib/contrib/asm686/0000755000175000017500000000000012665173607016501 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/asm686/match.S0000644000175000017500000002417512663660064017726 0ustar sergeisergei/* match.S -- x86 assembly version of the zlib longest_match() function. * Optimized for the Intel 686 chips (PPro and later). * * Copyright (C) 1998, 2007 Brian Raiter * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef NO_UNDERLINE #define match_init _match_init #define longest_match _longest_match #endif #define MAX_MATCH (258) #define MIN_MATCH (3) #define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) #define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) /* stack frame offsets */ #define chainlenwmask 0 /* high word: current chain len */ /* low word: s->wmask */ #define window 4 /* local copy of s->window */ #define windowbestlen 8 /* s->window + bestlen */ #define scanstart 16 /* first two bytes of string */ #define scanend 12 /* last two bytes of string */ #define scanalign 20 /* dword-misalignment of string */ #define nicematch 24 /* a good enough match size */ #define bestlen 28 /* size of best match so far */ #define scan 32 /* ptr to string wanting match */ #define LocalVarsSize (36) /* saved ebx 36 */ /* saved edi 40 */ /* saved esi 44 */ /* saved ebp 48 */ /* return address 52 */ #define deflatestate 56 /* the function arguments */ #define curmatch 60 /* All the +zlib1222add offsets are due to the addition of fields * in zlib in the deflate_state structure since the asm code was first written * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). */ #define zlib1222add (8) #define dsWSize (36+zlib1222add) #define dsWMask (44+zlib1222add) #define dsWindow (48+zlib1222add) #define dsPrev (56+zlib1222add) #define dsMatchLen (88+zlib1222add) #define dsPrevMatch (92+zlib1222add) #define dsStrStart (100+zlib1222add) #define dsMatchStart (104+zlib1222add) #define dsLookahead (108+zlib1222add) #define dsPrevLen (112+zlib1222add) #define dsMaxChainLen (116+zlib1222add) #define dsGoodMatch (132+zlib1222add) #define dsNiceMatch (136+zlib1222add) .file "match.S" .globl match_init, longest_match .text /* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ .cfi_sections .debug_frame longest_match: .cfi_startproc /* Save registers that the compiler may be using, and adjust %esp to */ /* make room for our stack frame. */ pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset ebp, -8 pushl %edi .cfi_def_cfa_offset 12 pushl %esi .cfi_def_cfa_offset 16 pushl %ebx .cfi_def_cfa_offset 20 subl $LocalVarsSize, %esp .cfi_def_cfa_offset LocalVarsSize+20 /* Retrieve the function arguments. %ecx will hold cur_match */ /* throughout the entire function. %edx will hold the pointer to the */ /* deflate_state structure during the function's setup (before */ /* entering the main loop). */ movl deflatestate(%esp), %edx movl curmatch(%esp), %ecx /* uInt wmask = s->w_mask; */ /* unsigned chain_length = s->max_chain_length; */ /* if (s->prev_length >= s->good_match) { */ /* chain_length >>= 2; */ /* } */ movl dsPrevLen(%edx), %eax movl dsGoodMatch(%edx), %ebx cmpl %ebx, %eax movl dsWMask(%edx), %eax movl dsMaxChainLen(%edx), %ebx jl LastMatchGood shrl $2, %ebx LastMatchGood: /* chainlen is decremented once beforehand so that the function can */ /* use the sign flag instead of the zero flag for the exit test. */ /* It is then shifted into the high word, to make room for the wmask */ /* value, which it will always accompany. */ decl %ebx shll $16, %ebx orl %eax, %ebx movl %ebx, chainlenwmask(%esp) /* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ movl dsNiceMatch(%edx), %eax movl dsLookahead(%edx), %ebx cmpl %eax, %ebx jl LookaheadLess movl %eax, %ebx LookaheadLess: movl %ebx, nicematch(%esp) /* register Bytef *scan = s->window + s->strstart; */ movl dsWindow(%edx), %esi movl %esi, window(%esp) movl dsStrStart(%edx), %ebp lea (%esi,%ebp), %edi movl %edi, scan(%esp) /* Determine how many bytes the scan ptr is off from being */ /* dword-aligned. */ movl %edi, %eax negl %eax andl $3, %eax movl %eax, scanalign(%esp) /* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ /* s->strstart - (IPos)MAX_DIST(s) : NIL; */ movl dsWSize(%edx), %eax subl $MIN_LOOKAHEAD, %eax subl %eax, %ebp jg LimitPositive xorl %ebp, %ebp LimitPositive: /* int best_len = s->prev_length; */ movl dsPrevLen(%edx), %eax movl %eax, bestlen(%esp) /* Store the sum of s->window + best_len in %esi locally, and in %esi. */ addl %eax, %esi movl %esi, windowbestlen(%esp) /* register ush scan_start = *(ushf*)scan; */ /* register ush scan_end = *(ushf*)(scan+best_len-1); */ /* Posf *prev = s->prev; */ movzwl (%edi), %ebx movl %ebx, scanstart(%esp) movzwl -1(%edi,%eax), %ebx movl %ebx, scanend(%esp) movl dsPrev(%edx), %edi /* Jump into the main loop. */ movl chainlenwmask(%esp), %edx jmp LoopEntry .balign 16 /* do { * match = s->window + cur_match; * if (*(ushf*)(match+best_len-1) != scan_end || * *(ushf*)match != scan_start) continue; * [...] * } while ((cur_match = prev[cur_match & wmask]) > limit * && --chain_length != 0); * * Here is the inner loop of the function. The function will spend the * majority of its time in this loop, and majority of that time will * be spent in the first ten instructions. * * Within this loop: * %ebx = scanend * %ecx = curmatch * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) * %esi = windowbestlen - i.e., (window + bestlen) * %edi = prev * %ebp = limit */ LookupLoop: andl %edx, %ecx movzwl (%edi,%ecx,2), %ecx cmpl %ebp, %ecx jbe LeaveNow subl $0x00010000, %edx js LeaveNow LoopEntry: movzwl -1(%esi,%ecx), %eax cmpl %ebx, %eax jnz LookupLoop movl window(%esp), %eax movzwl (%eax,%ecx), %eax cmpl scanstart(%esp), %eax jnz LookupLoop /* Store the current value of chainlen. */ movl %edx, chainlenwmask(%esp) /* Point %edi to the string under scrutiny, and %esi to the string we */ /* are hoping to match it up with. In actuality, %esi and %edi are */ /* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ /* initialized to -(MAX_MATCH_8 - scanalign). */ movl window(%esp), %esi movl scan(%esp), %edi addl %ecx, %esi movl scanalign(%esp), %eax movl $(-MAX_MATCH_8), %edx lea MAX_MATCH_8(%edi,%eax), %edi lea MAX_MATCH_8(%esi,%eax), %esi /* Test the strings for equality, 8 bytes at a time. At the end, * adjust %edx so that it is offset to the exact byte that mismatched. * * We already know at this point that the first three bytes of the * strings match each other, and they can be safely passed over before * starting the compare loop. So what this code does is skip over 0-3 * bytes, as much as necessary in order to dword-align the %edi * pointer. (%esi will still be misaligned three times out of four.) * * It should be confessed that this loop usually does not represent * much of the total running time. Replacing it with a more * straightforward "rep cmpsb" would not drastically degrade * performance. */ LoopCmps: movl (%esi,%edx), %eax xorl (%edi,%edx), %eax jnz LeaveLoopCmps movl 4(%esi,%edx), %eax xorl 4(%edi,%edx), %eax jnz LeaveLoopCmps4 addl $8, %edx jnz LoopCmps jmp LenMaximum LeaveLoopCmps4: addl $4, %edx LeaveLoopCmps: testl $0x0000FFFF, %eax jnz LenLower addl $2, %edx shrl $16, %eax LenLower: subb $1, %al adcl $0, %edx /* Calculate the length of the match. If it is longer than MAX_MATCH, */ /* then automatically accept it as the best possible match and leave. */ lea (%edi,%edx), %eax movl scan(%esp), %edi subl %edi, %eax cmpl $MAX_MATCH, %eax jge LenMaximum /* If the length of the match is not longer than the best match we */ /* have so far, then forget it and return to the lookup loop. */ movl deflatestate(%esp), %edx movl bestlen(%esp), %ebx cmpl %ebx, %eax jg LongerMatch movl windowbestlen(%esp), %esi movl dsPrev(%edx), %edi movl scanend(%esp), %ebx movl chainlenwmask(%esp), %edx jmp LookupLoop /* s->match_start = cur_match; */ /* best_len = len; */ /* if (len >= nice_match) break; */ /* scan_end = *(ushf*)(scan+best_len-1); */ LongerMatch: movl nicematch(%esp), %ebx movl %eax, bestlen(%esp) movl %ecx, dsMatchStart(%edx) cmpl %ebx, %eax jge LeaveNow movl window(%esp), %esi addl %eax, %esi movl %esi, windowbestlen(%esp) movzwl -1(%edi,%eax), %ebx movl dsPrev(%edx), %edi movl %ebx, scanend(%esp) movl chainlenwmask(%esp), %edx jmp LookupLoop /* Accept the current string, with the maximum possible length. */ LenMaximum: movl deflatestate(%esp), %edx movl $MAX_MATCH, bestlen(%esp) movl %ecx, dsMatchStart(%edx) /* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ /* return s->lookahead; */ LeaveNow: movl deflatestate(%esp), %edx movl bestlen(%esp), %ebx movl dsLookahead(%edx), %eax cmpl %eax, %ebx jg LookaheadRet movl %ebx, %eax LookaheadRet: /* Restore the stack and return from whence we came. */ addl $LocalVarsSize, %esp .cfi_def_cfa_offset 20 popl %ebx .cfi_def_cfa_offset 16 popl %esi .cfi_def_cfa_offset 12 popl %edi .cfi_def_cfa_offset 8 popl %ebp .cfi_def_cfa_offset 4 .cfi_endproc match_init: ret tcl8.6.5/compat/zlib/contrib/asm686/README.6860000644000175000017500000000312612663653206017701 0ustar sergeisergeiThis is a patched version of zlib, modified to use Pentium-Pro-optimized assembly code in the deflation algorithm. The files changed/added by this patch are: README.686 match.S The speedup that this patch provides varies, depending on whether the compiler used to build the original version of zlib falls afoul of the PPro's speed traps. My own tests show a speedup of around 10-20% at the default compression level, and 20-30% using -9, against a version compiled using gcc 2.7.2.3. Your mileage may vary. Note that this code has been tailored for the PPro/PII in particular, and will not perform particuarly well on a Pentium. If you are using an assembler other than GNU as, you will have to translate match.S to use your assembler's syntax. (Have fun.) Brian Raiter breadbox@muppetlabs.com April, 1998 Added for zlib 1.1.3: The patches come from http://www.muppetlabs.com/~breadbox/software/assembly.html To compile zlib with this asm file, copy match.S to the zlib directory then do: CFLAGS="-O3 -DASMV" ./configure make OBJA=match.o Update: I've been ignoring these assembly routines for years, believing that gcc's generated code had caught up with it sometime around gcc 2.95 and the major rearchitecting of the Pentium 4. However, I recently learned that, despite what I believed, this code still has some life in it. On the Pentium 4 and AMD64 chips, it continues to run about 8% faster than the code produced by gcc 4.1. In acknowledgement of its continuing usefulness, I've altered the license to match that of the rest of zlib. Share and Enjoy! Brian Raiter breadbox@muppetlabs.com April, 2007 tcl8.6.5/compat/zlib/contrib/blast/0000755000175000017500000000000012665173607016562 5ustar sergeisergeitcl8.6.5/compat/zlib/contrib/blast/blast.c0000644000175000017500000004224412663660064020035 0ustar sergeisergei/* blast.c * Copyright (C) 2003, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in blast.h * version 1.2, 24 Oct 2012 * * blast.c decompresses data compressed by the PKWare Compression Library. * This function provides functionality similar to the explode() function of * the PKWare library, hence the name "blast". * * This decompressor is based on the excellent format description provided by * Ben Rudiak-Gould in comp.compression on August 13, 2001. Interestingly, the * example Ben provided in the post is incorrect. The distance 110001 should * instead be 111000. When corrected, the example byte stream becomes: * * 00 04 82 24 25 8f 80 7f * * which decompresses to "AIAIAIAIAIAIA" (without the quotes). */ /* * Change history: * * 1.0 12 Feb 2003 - First version * 1.1 16 Feb 2003 - Fixed distance check for > 4 GB uncompressed data * 1.2 24 Oct 2012 - Add note about using binary mode in stdio * - Fix comparisons of differently signed integers */ #include /* for setjmp(), longjmp(), and jmp_buf */ #include "blast.h" /* prototype for blast() */ #define local static /* for local function definitions */ #define MAXBITS 13 /* maximum code length */ #define MAXWIN 4096 /* maximum window size */ /* input and output state */ struct state { /* input state */ blast_in infun; /* input function provided by user */ void *inhow; /* opaque information passed to infun() */ unsigned char *in; /* next input location */ unsigned left; /* available input at in */ int bitbuf; /* bit buffer */ int bitcnt; /* number of bits in bit buffer */ /* input limit error return state for bits() and decode() */ jmp_buf env; /* output state */ blast_out outfun; /* output function provided by user */ void *outhow; /* opaque information passed to outfun() */ unsigned next; /* index of next write location in out[] */ int first; /* true to check distances (for first 4K) */ unsigned char out[MAXWIN]; /* output buffer and sliding window */ }; /* * Return need bits from the input stream. This always leaves less than * eight bits in the buffer. bits() works properly for need == 0. * * Format notes: * * - Bits are stored in bytes from the least significant bit to the most * significant bit. Therefore bits are dropped from the bottom of the bit * buffer, using shift right, and new bytes are appended to the top of the * bit buffer, using shift left. */ local int bits(struct state *s, int need) { int val; /* bit accumulator */ /* load at least need bits into val */ val = s->bitbuf; while (s->bitcnt < need) { if (s->left == 0) { s->left = s->infun(s->inhow, &(s->in)); if (s->left == 0) longjmp(s->env, 1); /* out of input */ } val |= (int)(*(s->in)++) << s->bitcnt; /* load eight bits */ s->left--; s->bitcnt += 8; } /* drop need bits and update buffer, always zero to seven bits left */ s->bitbuf = val >> need; s->bitcnt -= need; /* return need bits, zeroing the bits above that */ return val & ((1 << need) - 1); } /* * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of * each length, which for a canonical code are stepped through in order. * symbol[] are the symbol values in canonical order, where the number of * entries is the sum of the counts in count[]. The decoding process can be * seen in the function decode() below. */ struct huffman { short *count; /* number of symbols of each length */ short *symbol; /* canonically ordered symbols */ }; /* * Decode a code from the stream s using huffman table h. Return the symbol or * a negative value if there is an error. If all of the lengths are zero, i.e. * an empty code, or if the code is incomplete and an invalid code is received, * then -9 is returned after reading MAXBITS bits. * * Format notes: * * - The codes as stored in the compressed data are bit-reversed relative to * a simple integer ordering of codes of the same lengths. Hence below the * bits are pulled from the compressed data one at a time and used to * build the code value reversed from what is in the stream in order to * permit simple integer comparisons for decoding. * * - The first code for the shortest length is all ones. Subsequent codes of * the same length are simply integer decrements of the previous code. When * moving up a length, a one bit is appended to the code. For a complete * code, the last code of the longest length will be all zeros. To support * this ordering, the bits pulled during decoding are inverted to apply the * more "natural" ordering starting with all zeros and incrementing. */ local int decode(struct state *s, struct huffman *h) { int len; /* current number of bits in code */ int code; /* len bits being decoded */ int first; /* first code of length len */ int count; /* number of codes of length len */ int index; /* index of first code of length len in symbol table */ int bitbuf; /* bits from stream */ int left; /* bits left in next or left to process */ short *next; /* next number of codes */ bitbuf = s->bitbuf; left = s->bitcnt; code = first = index = 0; len = 1; next = h->count + 1; while (1) { while (left--) { code |= (bitbuf & 1) ^ 1; /* invert code */ bitbuf >>= 1; count = *next++; if (code < first + count) { /* if length len, return symbol */ s->bitbuf = bitbuf; s->bitcnt = (s->bitcnt - len) & 7; return h->symbol[index + (code - first)]; } index += count; /* else update for next length */ first += count; first <<= 1; code <<= 1; len++; } left = (MAXBITS+1) - len; if (left == 0) break; if (s->left == 0) { s->left = s->infun(s->inhow, &(s->in)); if (s->left == 0) longjmp(s->env, 1); /* out of input */ } bitbuf = *(s->in)++; s->left--; if (left > 8) left = 8; } return -9; /* ran out of codes */ } /* * Given a list of repeated code lengths rep[0..n-1], where each byte is a * count (high four bits + 1) and a code length (low four bits), generate the * list of code lengths. This compaction reduces the size of the object code. * Then given the list of code lengths length[0..n-1] representing a canonical * Huffman code for n symbols, construct the tables required to decode those * codes. Those tables are the number of codes of each length, and the symbols * sorted by length, retaining their original order within each length. The * return value is zero for a complete code set, negative for an over- * subscribed code set, and positive for an incomplete code set. The tables * can be used if the return value is zero or positive, but they cannot be used * if the return value is negative. If the return value is zero, it is not * possible for decode() using that table to return an error--any stream of * enough bits will resolve to a symbol. If the return value is positive, then * it is possible for decode() using that table to return an error for received * codes past the end of the incomplete lengths. */ local int construct(struct huffman *h, const unsigned char *rep, int n) { int symbol; /* current symbol when stepping through length[] */ int len; /* current length when stepping through h->count[] */ int left; /* number of possible codes left of current length */ short offs[MAXBITS+1]; /* offsets in symbol table for each length */ short length[256]; /* code lengths */ /* convert compact repeat counts into symbol bit length list */ symbol = 0; do { len = *rep++; left = (len >> 4) + 1; len &= 15; do { length[symbol++] = len; } while (--left); } while (--n); n = symbol; /* count number of codes of each length */ for (len = 0; len <= MAXBITS; len++) h->count[len] = 0; for (symbol = 0; symbol < n; symbol++) (h->count[length[symbol]])++; /* assumes lengths are within bounds */ if (h->count[0] == n) /* no codes! */ return 0; /* complete, but decode() will fail */ /* check for an over-subscribed or incomplete set of lengths */ left = 1; /* one possible code of zero length */ for (len = 1; len <= MAXBITS; len++) { left <<= 1; /* one more bit, double codes left */ left -= h->count[len]; /* deduct count from possible codes */ if (left < 0) return left; /* over-subscribed--return negative */ } /* left > 0 means incomplete */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h->count[len]; /* * put symbols in table sorted by length, by symbol order within each * length */ for (symbol = 0; symbol < n; symbol++) if (length[symbol] != 0) h->symbol[offs[length[symbol]]++] = symbol; /* return zero for complete set, positive for incomplete set */ return left; } /* * Decode PKWare Compression Library stream. * * Format notes: * * - First byte is 0 if literals are uncoded or 1 if they are coded. Second * byte is 4, 5, or 6 for the number of extra bits in the distance code. * This is the base-2 logarithm of the dictionary size minus six. * * - Compressed data is a combination of literals and length/distance pairs * terminated by an end code. Literals are either Huffman coded or * uncoded bytes. A length/distance pair is a coded length followed by a * coded distance to represent a string that occurs earlier in the * uncompressed data that occurs again at the current location. * * - A bit preceding a literal or length/distance pair indicates which comes * next, 0 for literals, 1 for length/distance. * * - If literals are uncoded, then the next eight bits are the literal, in the * normal bit order in th stream, i.e. no bit-reversal is needed. Similarly, * no bit reversal is needed for either the length extra bits or the distance * extra bits. * * - Literal bytes are simply written to the output. A length/distance pair is * an instruction to copy previously uncompressed bytes to the output. The * copy is from distance bytes back in the output stream, copying for length * bytes. * * - Distances pointing before the beginning of the output data are not * permitted. * * - Overlapped copies, where the length is greater than the distance, are * allowed and common. For example, a distance of one and a length of 518 * simply copies the last byte 518 times. A distance of four and a length of * twelve copies the last four bytes three times. A simple forward copy * ignoring whether the length is greater than the distance or not implements * this correctly. */ local int decomp(struct state *s) { int lit; /* true if literals are coded */ int dict; /* log2(dictionary size) - 6 */ int symbol; /* decoded symbol, extra bits for distance */ int len; /* length for copy */ unsigned dist; /* distance for copy */ int copy; /* copy counter */ unsigned char *from, *to; /* copy pointers */ static int virgin = 1; /* build tables once */ static short litcnt[MAXBITS+1], litsym[256]; /* litcode memory */ static short lencnt[MAXBITS+1], lensym[16]; /* lencode memory */ static short distcnt[MAXBITS+1], distsym[64]; /* distcode memory */ static struct huffman litcode = {litcnt, litsym}; /* length code */ static struct huffman lencode = {lencnt, lensym}; /* length code */ static struct huffman distcode = {distcnt, distsym};/* distance code */ /* bit lengths of literal codes */ static const unsigned char litlen[] = { 11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 10, 8, 12, 10, 12, 10, 8, 23, 8, 9, 7, 6, 7, 8, 7, 6, 55, 8, 23, 24, 12, 11, 7, 9, 11, 12, 6, 7, 22, 5, 7, 24, 6, 11, 9, 6, 7, 22, 7, 11, 38, 7, 9, 8, 25, 11, 8, 11, 9, 12, 8, 12, 5, 38, 5, 38, 5, 11, 7, 5, 6, 21, 6, 10, 53, 8, 7, 24, 10, 27, 44, 253, 253, 253, 252, 252, 252, 13, 12, 45, 12, 45, 12, 61, 12, 45, 44, 173}; /* bit lengths of length codes 0..15 */ static const unsigned char lenlen[] = {2, 35, 36, 53, 38, 23}; /* bit lengths of distance codes 0..63 */ static const unsigned char distlen[] = {2, 20, 53, 230, 247, 151, 248}; static const short base[16] = { /* base for length codes */ 3, 2, 4, 5, 6, 7, 8, 9, 10, 12, 16, 24, 40, 72, 136, 264}; static const char extra[16] = { /* extra bits for length codes */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8}; /* set up decoding tables (once--might not be thread-safe) */ if (virgin) { construct(&litcode, litlen, sizeof(litlen)); construct(&lencode, lenlen, sizeof(lenlen)); construct(&distcode, distlen, sizeof(distlen)); virgin = 0; } /* read header */ lit = bits(s, 8); if (lit > 1) return -1; dict = bits(s, 8); if (dict < 4 || dict > 6) return -2; /* decode literals and length/distance pairs */ do { if (bits(s, 1)) { /* get length */ symbol = decode(s, &lencode); len = base[symbol] + bits(s, extra[symbol]); if (len == 519) break; /* end code */ /* get distance */ symbol = len == 2 ? 2 : dict; dist = decode(s, &distcode) << symbol; dist += bits(s, symbol); dist++; if (s->first && dist > s->next) return -3; /* distance too far back */ /* copy length bytes from distance bytes back */ do { to = s->out + s->next; from = to - dist; copy = MAXWIN; if (s->next < dist) { from += copy; copy = dist; } copy -= s->next; if (copy > len) copy = len; len -= copy; s->next += copy; do { *to++ = *from++; } while (--copy); if (s->next == MAXWIN) { if (s->outfun(s->outhow, s->out, s->next)) return 1; s->next = 0; s->first = 0; } } while (len != 0); } else { /* get literal and write it */ symbol = lit ? decode(s, &litcode) : bits(s, 8); s->out[s->next++] = symbol; if (s->next == MAXWIN) { if (s->outfun(s->outhow, s->out, s->next)) return 1; s->next = 0; s->first = 0; } } } while (1); return 0; } /* See comments in blast.h */ int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow) { struct state s; /* input/output state */ int err; /* return value */ /* initialize input state */ s.infun = infun; s.inhow = inhow; s.left = 0; s.bitbuf = 0; s.bitcnt = 0; /* initialize output state */ s.outfun = outfun; s.outhow = outhow; s.next = 0; s.first = 1; /* return if bits() or decode() tries to read past available input */ if (setjmp(s.env) != 0) /* if came back here via longjmp(), */ err = 2; /* then skip decomp(), return error */ else err = decomp(&s); /* decompress */ /* write any leftover output and update the error code if needed */ if (err != 1 && s.next && s.outfun(s.outhow, s.out, s.next) && err == 0) err = 1; return err; } #ifdef TEST /* Example of how to use blast() */ #include #include #define CHUNK 16384 local unsigned inf(void *how, unsigned char **buf) { static unsigned char hold[CHUNK]; *buf = hold; return fread(hold, 1, CHUNK, (FILE *)how); } local int outf(void *how, unsigned char *buf, unsigned len) { return fwrite(buf, 1, len, (FILE *)how) != len; } /* Decompress a PKWare Compression Library stream from stdin to stdout */ int main(void) { int ret, n; /* decompress to stdout */ ret = blast(inf, stdin, outf, stdout); if (ret != 0) fprintf(stderr, "blast error: %d\n", ret); /* see if there are any leftover bytes */ n = 0; while (getchar() != EOF) n++; if (n) fprintf(stderr, "blast warning: %d unused bytes of input\n", n); /* return blast() error code */ return ret; } #endif tcl8.6.5/compat/zlib/contrib/blast/blast.h0000644000175000017500000000655112663660064020043 0ustar sergeisergei/* blast.h -- interface for blast.c Copyright (C) 2003, 2012 Mark Adler version 1.2, 24 Oct 2012 This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Mark Adler madler@alumni.caltech.edu */ /* * blast() decompresses the PKWare Data Compression Library (DCL) compressed * format. It provides the same functionality as the explode() function in * that library. (Note: PKWare overused the "implode" verb, and the format * used by their library implode() function is completely different and * incompatible with the implode compression method supported by PKZIP.) * * The binary mode for stdio functions should be used to assure that the * compressed data is not corrupted when read or written. For example: * fopen(..., "rb") and fopen(..., "wb"). */ typedef unsigned (*blast_in)(void *how, unsigned char **buf); typedef int (*blast_out)(void *how, unsigned char *buf, unsigned len); /* Definitions for input/output functions passed to blast(). See below for * what the provided functions need to do. */ int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow); /* Decompress input to output using the provided infun() and outfun() calls. * On success, the return value of blast() is zero. If there is an error in * the source data, i.e. it is not in the proper format, then a negative value * is returned. If there is not enough input available or there is not enough * output space, then a positive error is returned. * * The input function is invoked: len = infun(how, &buf), where buf is set by * infun() to point to the input buffer, and infun() returns the number of * available bytes there. If infun() returns zero, then blast() returns with * an input error. (blast() only asks for input if it needs it.) inhow is for * use by the application to pass an input descriptor to infun(), if desired. * * The output function is invoked: err = outfun(how, buf, len), where the bytes * to be written are buf[0..len-1]. If err is not zero, then blast() returns * with an output error. outfun() is always called with len <= 4096. outhow * is for use by the application to pass an output descriptor to outfun(), if * desired. * * The return codes are: * * 2: ran out of input before completing decompression * 1: output error before completing decompression * 0: successful decompression * -1: literal flag not zero or one * -2: dictionary size not in 4..6 * -3: distance is too far back * * At the bottom of blast.c is an example program that uses blast() that can be * compiled to produce a command-line decompression filter by defining TEST. */ tcl8.6.5/compat/zlib/contrib/blast/test.txt0000644000175000017500000000001512663653131020267 0ustar sergeisergeiAIAIAIAIAIAIAtcl8.6.5/compat/zlib/contrib/blast/test.pk0000644000175000017500000000001012663653131020055 0ustar sergeisergei‚$%€tcl8.6.5/compat/zlib/contrib/blast/Makefile0000644000175000017500000000017712663653131020220 0ustar sergeisergeiblast: blast.c blast.h cc -DTEST -o blast blast.c test: blast blast < test.pk | cmp - test.txt clean: rm -f blast blast.o tcl8.6.5/compat/zlib/contrib/blast/README0000644000175000017500000000011212663653131017425 0ustar sergeisergeiRead blast.h for purpose and usage. Mark Adler madler@alumni.caltech.edu tcl8.6.5/compat/zlib/zlib.pc.cmakein0000644000175000017500000000044612663660065016710 0ustar sergeisergeiprefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=@INSTALL_LIB_DIR@ sharedlibdir=@INSTALL_LIB_DIR@ includedir=@INSTALL_INC_DIR@ Name: zlib Description: zlib compression library Version: @VERSION@ Requires: Libs: -L${libdir} -L${sharedlibdir} -lz Cflags: -I${includedir} tcl8.6.5/compat/zlib/infback.c0000644000175000017500000005426512663660065015567 0ustar sergeisergei/* infback.c -- inflate using a call-back interface * Copyright (C) 1995-2011 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* This code is largely copied from inflate.c. Normally either infback.o or inflate.o would be linked into an application--not both. The interface with inffast.c is retained so that optimized assembler-coded versions of inflate_fast() can be used with either inflate.c or infback.c. */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" /* function prototypes */ local void fixedtables OF((struct inflate_state FAR *state)); /* strm provides memory allocation functions in zalloc and zfree, or Z_NULL to use the library memory allocation functions. windowBits is in the range 8..15, and window is a user-supplied window and output buffer that is 2**windowBits bytes. */ int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) z_streamp strm; int windowBits; unsigned char FAR *window; const char *version; int stream_size; { struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL || window == Z_NULL || windowBits < 8 || windowBits > 15) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; #endif } if (strm->zfree == (free_func)0) #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zfree = zcfree; #endif state = (struct inflate_state FAR *)ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->dmax = 32768U; state->wbits = windowBits; state->wsize = 1U << windowBits; state->window = window; state->wnext = 0; state->whave = 0; return Z_OK; } /* Return state with length and distance decoding tables and index sizes set to fixed code decoding. Normally this returns fixed tables from inffixed.h. If BUILDFIXED is defined, then instead this routine builds the tables the first time it's called, and returns those tables the first time and thereafter. This reduces the size of the code by about 2K bytes, in exchange for a little execution time. However, BUILDFIXED should not be used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ local void fixedtables(state) struct inflate_state FAR *state; { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { unsigned sym, bits; static code *next; /* literal/length table */ sym = 0; while (sym < 144) state->lens[sym++] = 8; while (sym < 256) state->lens[sym++] = 9; while (sym < 280) state->lens[sym++] = 7; while (sym < 288) state->lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); /* distance table */ sym = 0; while (sym < 32) state->lens[sym++] = 5; distfix = next; bits = 5; inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); /* do this just once */ virgin = 0; } #else /* !BUILDFIXED */ # include "inffixed.h" #endif /* BUILDFIXED */ state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; state->distbits = 5; } /* Macros for inflateBack(): */ /* Load returned state from inflate_fast() */ #define LOAD() \ do { \ put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ hold = state->hold; \ bits = state->bits; \ } while (0) /* Set state from registers for inflate_fast() */ #define RESTORE() \ do { \ strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = next; \ strm->avail_in = have; \ state->hold = hold; \ state->bits = bits; \ } while (0) /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Assure that some input is available. If input is requested, but denied, then return a Z_BUF_ERROR from inflateBack(). */ #define PULL() \ do { \ if (have == 0) { \ have = in(in_desc, &next); \ if (have == 0) { \ next = Z_NULL; \ ret = Z_BUF_ERROR; \ goto inf_leave; \ } \ } \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflateBack() with an error if there is no input available. */ #define PULLBYTE() \ do { \ PULL(); \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflateBack() with an error. */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* Assure that some output space is available, by writing out the window if it's full. If the write fails, return from inflateBack() with a Z_BUF_ERROR. */ #define ROOM() \ do { \ if (left == 0) { \ put = state->window; \ left = state->wsize; \ state->whave = left; \ if (out(out_desc, put, left)) { \ ret = Z_BUF_ERROR; \ goto inf_leave; \ } \ } \ } while (0) /* strm provides the memory allocation functions and window buffer on input, and provides information on the unused input on return. For Z_DATA_ERROR returns, strm will also provide an error message. in() and out() are the call-back input and output functions. When inflateBack() needs more input, it calls in(). When inflateBack() has filled the window with output, or when it completes with data in the window, it calls out() to write out the data. The application must not change the provided input until in() is called again or inflateBack() returns. The application must not change the window/output buffer until inflateBack() returns. in() and out() are called with a descriptor parameter provided in the inflateBack() call. This parameter can be a structure that provides the information required to do the read or write, as well as accumulated information on the input and output such as totals and check values. in() should return zero on failure. out() should return non-zero on failure. If either in() or out() fails, than inflateBack() returns a Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it was in() or out() that caused in the error. Otherwise, inflateBack() returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format error, or Z_MEM_ERROR if it could not allocate memory for the state. inflateBack() can also return Z_STREAM_ERROR if the input parameters are not correct, i.e. strm is Z_NULL or the state was not initialized. */ int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) z_streamp strm; in_func in; void FAR *in_desc; out_func out; void FAR *out_desc; { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char FAR *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; /* Check that the strm exists and that the state was initialized */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* Reset the state */ strm->msg = Z_NULL; state->mode = TYPE; state->last = 0; state->whave = 0; next = strm->next_in; have = next != Z_NULL ? strm->avail_in : 0; hold = 0; bits = 0; put = state->window; left = state->wsize; /* Inflate until end of block marked as last */ for (;;) switch (state->mode) { case TYPE: /* determine and dispatch block type */ if (state->last) { BYTEBITS(); state->mode = DONE; break; } NEEDBITS(3); state->last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); state->mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN; /* decode codes */ break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); state->mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); break; case STORED: /* get and verify stored block length */ BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } state->length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state->length)); INITBITS(); /* copy stored block from input to output */ while (state->length != 0) { copy = state->length; PULL(); ROOM(); if (copy > have) copy = have; if (copy > left) copy = left; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state->length -= copy; } Tracev((stderr, "inflate: stored end\n")); state->mode = TYPE; break; case TABLE: /* get dynamic table entries descriptor */ NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); /* get code length code lengths (not a typo) */ state->have = 0; while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); /* get length and distance code code lengths */ state->have = 0; while (state->have < state->nlen + state->ndist) { for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } len = (unsigned)(state->lens[state->have - 1]); copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state->mode == BAD) break; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { strm->msg = (char *)"invalid code -- missing end-of-block"; state->mode = BAD; break; } /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } state->distcode = (code const FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN; case LEN: /* use inflate_fast() if we have enough input and output */ if (have >= 6 && left >= 258) { RESTORE(); if (state->whave < state->wsize) state->whave = state->wsize - left; inflate_fast(strm, state->wsize); LOAD(); break; } /* get a literal, length, or end-of-block code */ for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); state->length = (unsigned)here.val; /* process literal */ if (here.op == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); ROOM(); *put++ = (unsigned char)(state->length); left--; state->mode = LEN; break; } /* process end of block */ if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } /* invalid code */ if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } /* length code -- get extra bits, if any */ state->extra = (unsigned)(here.op) & 15; if (state->extra != 0) { NEEDBITS(state->extra); state->length += BITS(state->extra); DROPBITS(state->extra); } Tracevv((stderr, "inflate: length %u\n", state->length)); /* get distance code */ for (;;) { here = state->distcode[BITS(state->distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); if (here.op & 64) { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; /* get distance extra bits, if any */ state->extra = (unsigned)(here.op) & 15; if (state->extra != 0) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); } if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } Tracevv((stderr, "inflate: distance %u\n", state->offset)); /* copy match from window to output */ do { ROOM(); copy = state->wsize - state->offset; if (copy < left) { from = put + copy; copy = left - copy; } else { from = put - state->offset; copy = left; } if (copy > state->length) copy = state->length; state->length -= copy; left -= copy; do { *put++ = *from++; } while (--copy); } while (state->length != 0); break; case DONE: /* inflate stream terminated properly -- write leftover output */ ret = Z_STREAM_END; if (left < state->wsize) { if (out(out_desc, state->window, state->wsize - left)) ret = Z_BUF_ERROR; } goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; default: /* can't happen, but makes compilers happy */ ret = Z_STREAM_ERROR; goto inf_leave; } /* Return unused input */ inf_leave: strm->next_in = next; strm->avail_in = have; return ret; } int ZEXPORT inflateBackEnd(strm) z_streamp strm; { if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } tcl8.6.5/compat/zlib/deflate.h0000644000175000017500000003074612663660065015601 0ustar sergeisergei/* deflate.h -- internal compression state * Copyright (C) 1995-2012 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id$ */ #ifndef DEFLATE_H #define DEFLATE_H #include "zutil.h" /* define NO_GZIP when compiling if you want to disable gzip header and trailer creation by deflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip encoding should be left enabled. */ #ifndef NO_GZIP # define GZIP #endif /* =========================================================================== * Internal compression state. */ #define LENGTH_CODES 29 /* number of length codes, not counting the special END_BLOCK code */ #define LITERALS 256 /* number of literal bytes 0..255 */ #define L_CODES (LITERALS+1+LENGTH_CODES) /* number of Literal or Length codes, including the END_BLOCK code */ #define D_CODES 30 /* number of distance codes */ #define BL_CODES 19 /* number of codes used to transfer the bit lengths */ #define HEAP_SIZE (2*L_CODES+1) /* maximum heap size */ #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ #define Buf_size 16 /* size of bit buffer in bi_buf */ #define INIT_STATE 42 #define EXTRA_STATE 69 #define NAME_STATE 73 #define COMMENT_STATE 91 #define HCRC_STATE 103 #define BUSY_STATE 113 #define FINISH_STATE 666 /* Stream status */ /* Data structure describing a single value and its code string. */ typedef struct ct_data_s { union { ush freq; /* frequency count */ ush code; /* bit string */ } fc; union { ush dad; /* father node in Huffman tree */ ush len; /* length of bit string */ } dl; } FAR ct_data; #define Freq fc.freq #define Code fc.code #define Dad dl.dad #define Len dl.len typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; typedef Pos FAR Posf; typedef unsigned IPos; /* A Pos is an index in the character window. We use short instead of int to * save space in the various tables. IPos is used only for parameter passing. */ typedef struct internal_state { z_streamp strm; /* pointer back to this zlib stream */ int status; /* as the name implies */ Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ uInt pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ uInt gzindex; /* where in extra, name, or comment */ Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ uInt w_size; /* LZ77 window size (32K by default) */ uInt w_bits; /* log2(w_size) (8..16) */ uInt w_mask; /* w_size - 1 */ Bytef *window; /* Sliding window. Input bytes are read into the second half of the window, * and move to the first half later to keep a dictionary of at least wSize * bytes. With this organization, matches are limited to a distance of * wSize-MAX_MATCH bytes, but this ensures that IO is always * performed with a length multiple of the block size. Also, it limits * the window size to 64K, which is quite useful on MSDOS. * To do: use the user input buffer as sliding window. */ ulg window_size; /* Actual size of window: 2*wSize, except when the user input buffer * is directly used as sliding window. */ Posf *prev; /* Link to older string with same hash index. To limit the size of this * array to 64K, this link is maintained only for the last 32K strings. * An index in this array is thus a window index modulo 32K. */ Posf *head; /* Heads of the hash chains or NIL. */ uInt ins_h; /* hash index of string to be inserted */ uInt hash_size; /* number of elements in hash table */ uInt hash_bits; /* log2(hash_size) */ uInt hash_mask; /* hash_size-1 */ uInt hash_shift; /* Number of bits by which ins_h must be shifted at each input * step. It must be such that after MIN_MATCH steps, the oldest * byte no longer takes part in the hash key, that is: * hash_shift * MIN_MATCH >= hash_bits */ long block_start; /* Window position at the beginning of the current output block. Gets * negative when the window is moved backwards. */ uInt match_length; /* length of best match */ IPos prev_match; /* previous match */ int match_available; /* set if previous match exists */ uInt strstart; /* start of string to insert */ uInt match_start; /* start of matching string */ uInt lookahead; /* number of valid bytes ahead in window */ uInt prev_length; /* Length of the best match at previous step. Matches not greater than this * are discarded. This is used in the lazy match evaluation. */ uInt max_chain_length; /* To speed up deflation, hash chains are never searched beyond this * length. A higher limit improves compression ratio but degrades the * speed. */ uInt max_lazy_match; /* Attempt to find a better match only when the current match is strictly * smaller than this value. This mechanism is used only for compression * levels >= 4. */ # define max_insert_length max_lazy_match /* Insert new strings in the hash table only if the match length is not * greater than this length. This saves time but degrades compression. * max_insert_length is used only for compression levels <= 3. */ int level; /* compression level (1..9) */ int strategy; /* favor or force Huffman coding*/ uInt good_match; /* Use a faster search when the previous match is longer than this */ int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ /* Didn't use ct_data typedef below to suppress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ struct tree_desc_s l_desc; /* desc. for literal tree */ struct tree_desc_s d_desc; /* desc. for distance tree */ struct tree_desc_s bl_desc; /* desc. for bit length tree */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ int heap_len; /* number of elements in the heap */ int heap_max; /* element of largest frequency */ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. * The same heap array is used to build all trees. */ uch depth[2*L_CODES+1]; /* Depth of each subtree used as tie breaker for trees of equal frequency */ uchf *l_buf; /* buffer for literals or lengths */ uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for * limiting lit_bufsize to 64K: * - frequencies can be kept in 16 bit counters * - if compression is not successful for the first block, all input * data is still in the window so we can still emit a stored block even * when input comes from standard input. (This can also be done for * all blocks if lit_bufsize is not greater than 32K.) * - if compression is not successful for a file smaller than 64K, we can * even emit a stored file instead of a stored block (saving 5 bytes). * This is applicable only for zip (not gzip or zlib). * - creating new Huffman trees less frequently may not provide fast * adaptation to changes in the input data statistics. (Take for * example a binary file with poorly compressible code followed by * a highly compressible string table.) Smaller buffer sizes give * fast adaptation but have of course the overhead of transmitting * trees more frequently. * - I can't count above 4 */ uInt last_lit; /* running index in l_buf */ ushf *d_buf; /* Buffer for distances. To simplify the code, d_buf and l_buf have * the same number of elements. To use different lengths, an extra flag * array would be necessary. */ ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ uInt matches; /* number of string matches in current block */ uInt insert; /* bytes at end of window left to insert */ #ifdef DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif ush bi_buf; /* Output buffer. bits are inserted starting at the bottom (least * significant bits). */ int bi_valid; /* Number of valid bits in bi_buf. All bits above the last valid bit * are always zero. */ ulg high_water; /* High water mark offset in window for initialized bytes -- bytes above * this are set to zero in order to avoid memory check warnings when * longest match routines access bytes past the input. This is then * updated to the new high water mark. */ } FAR deflate_state; /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ #define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */ #define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) /* In order to simplify the code, particularly on 16 bit machines, match * distances are limited to MAX_DIST instead of WSIZE. */ #define WIN_INIT MAX_MATCH /* Number of bytes after end of data in window to initialize in order to avoid memory checker errors from longest match routines */ /* in trees.c */ void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, int last)); void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, int last)); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and * must not have side effects. _dist_code[256] and _dist_code[257] are never * used. */ #ifndef DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) extern uch ZLIB_INTERNAL _length_code[]; extern uch ZLIB_INTERNAL _dist_code[]; #else extern const uch ZLIB_INTERNAL _length_code[]; extern const uch ZLIB_INTERNAL _dist_code[]; #endif # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->d_buf[s->last_lit] = 0; \ s->l_buf[s->last_lit++] = cc; \ s->dyn_ltree[cc].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (length); \ ush dist = (distance); \ s->d_buf[s->last_lit] = dist; \ s->l_buf[s->last_lit++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ flush = _tr_tally(s, distance, length) #endif #endif /* DEFLATE_H */ tcl8.6.5/compat/zlib/configure0000755000175000017500000006274212663660064015733 0ustar sergeisergei#!/bin/sh # configure script for zlib. # # Normally configure builds both a static and a shared library. # If you want to build just a static library, use: ./configure --static # # To impose specific compiler or flags or install directory, use for example: # prefix=$HOME CC=cc CFLAGS="-O4" ./configure # or for csh/tcsh users: # (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) # Incorrect settings of CC or CFLAGS may prevent creating a shared library. # If you have problems, try without defining CC and CFLAGS before reporting # an error. # start off configure.log echo -------------------- >> configure.log echo $0 $* >> configure.log date >> configure.log # set command prefix for cross-compilation if [ -n "${CHOST}" ]; then uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`" CROSS_PREFIX="${CHOST}-" fi # destination name for static library STATICLIB=libz.a # extract zlib version numbers from zlib.h VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h` VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < zlib.h` VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h` VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < zlib.h` # establish commands for library building if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then AR=${AR-"${CROSS_PREFIX}ar"} test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log else AR=${AR-"ar"} test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log fi ARFLAGS=${ARFLAGS-"rc"} if "${CROSS_PREFIX}ranlib" --version >/dev/null 2>/dev/null || test $? -lt 126; then RANLIB=${RANLIB-"${CROSS_PREFIX}ranlib"} test -n "${CROSS_PREFIX}" && echo Using ${RANLIB} | tee -a configure.log else RANLIB=${RANLIB-"ranlib"} fi if "${CROSS_PREFIX}nm" --version >/dev/null 2>/dev/null || test $? -lt 126; then NM=${NM-"${CROSS_PREFIX}nm"} test -n "${CROSS_PREFIX}" && echo Using ${NM} | tee -a configure.log else NM=${NM-"nm"} fi # set defaults before processing command line options LDCONFIG=${LDCONFIG-"ldconfig"} LDSHAREDLIBC="${LDSHAREDLIBC--lc}" ARCHS= prefix=${prefix-/usr/local} exec_prefix=${exec_prefix-'${prefix}'} libdir=${libdir-'${exec_prefix}/lib'} sharedlibdir=${sharedlibdir-'${libdir}'} includedir=${includedir-'${prefix}/include'} mandir=${mandir-'${prefix}/share/man'} shared_ext='.so' shared=1 solo=0 cover=0 zprefix=0 zconst=0 build64=0 gcc=0 old_cc="$CC" old_cflags="$CFLAGS" OBJC='$(OBJZ) $(OBJG)' PIC_OBJC='$(PIC_OBJZ) $(PIC_OBJG)' # leave this script, optionally in a bad way leave() { if test "$*" != "0"; then echo "** $0 aborting." | tee -a configure.log fi rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version echo -------------------- >> configure.log echo >> configure.log echo >> configure.log exit $1 } # process command line options while test $# -ge 1 do case "$1" in -h* | --help) echo 'usage:' | tee -a configure.log echo ' configure [--const] [--zprefix] [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log echo ' [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log exit 0 ;; -p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;; -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;; -l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;; --sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;; -i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;; -u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;; -p* | --prefix) prefix="$2"; shift; shift ;; -e* | --eprefix) exec_prefix="$2"; shift; shift ;; -l* | --libdir) libdir="$2"; shift; shift ;; -i* | --includedir) includedir="$2"; shift; shift ;; -s* | --shared | --enable-shared) shared=1; shift ;; -t | --static) shared=0; shift ;; --solo) solo=1; shift ;; --cover) cover=1; shift ;; -z* | --zprefix) zprefix=1; shift ;; -6* | --64) build64=1; shift ;; -a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;; --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;; --localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;; -c* | --const) zconst=1; shift ;; *) echo "unknown option: $1" | tee -a configure.log echo "$0 --help for help" | tee -a configure.log leave 1;; esac done # temporary file name test=ztest$$ # put arguments in log, also put test file in log if used in arguments show() { case "$*" in *$test.c*) echo === $test.c === >> configure.log cat $test.c >> configure.log echo === >> configure.log;; esac echo $* >> configure.log } # check for gcc vs. cc and set compile and link flags based on the system identified by uname cat > $test.c <&1` in *gcc*) gcc=1 ;; esac show $cc -c $test.c if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then echo ... using gcc >> configure.log CC="$cc" CFLAGS="${CFLAGS--O3} ${ARCHS}" SFLAGS="${CFLAGS--O3} -fPIC" LDFLAGS="${LDFLAGS} ${ARCHS}" if test $build64 -eq 1; then CFLAGS="${CFLAGS} -m64" SFLAGS="${SFLAGS} -m64" fi if test "${ZLIBGCCWARN}" = "YES"; then if test "$zconst" -eq 1; then CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -pedantic -DZLIB_CONST" else CFLAGS="${CFLAGS} -Wall -Wextra -pedantic" fi fi if test -z "$uname"; then uname=`(uname -s || echo unknown) 2>/dev/null` fi case "$uname" in Linux* | linux* | GNU | GNU/* | solaris*) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map"} ;; *BSD | *bsd* | DragonFly) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map"} LDCONFIG="ldconfig -m" ;; CYGWIN* | Cygwin* | cygwin* | OS/2*) EXE='.exe' ;; MINGW* | mingw*) # temporary bypass rm -f $test.[co] $test $test$shared_ext echo "Please use win32/Makefile.gcc instead." | tee -a configure.log leave 1 LDSHARED=${LDSHARED-"$cc -shared"} LDSHAREDLIBC="" EXE='.exe' ;; QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 # (alain.bonnefoy@icbt.com) LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;; HP-UX*) LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} case `(uname -m || echo unknown) 2>/dev/null` in ia64) shared_ext='.so' SHAREDLIB='libz.so' ;; *) shared_ext='.sl' SHAREDLIB='libz.sl' ;; esac ;; Darwin* | darwin*) shared_ext='.dylib' SHAREDLIB=libz$shared_ext SHAREDLIBV=libz.$VER$shared_ext SHAREDLIBM=libz.$VER1$shared_ext LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} if libtool -V 2>&1 | grep Apple > /dev/null; then AR="libtool" else AR="/usr/bin/libtool" fi ARFLAGS="-o" ;; *) LDSHARED=${LDSHARED-"$cc -shared"} ;; esac else # find system name and corresponding cc options CC=${CC-cc} gcc=0 echo ... using $CC >> configure.log if test -z "$uname"; then uname=`(uname -sr || echo unknown) 2>/dev/null` fi case "$uname" in HP-UX*) SFLAGS=${CFLAGS-"-O +z"} CFLAGS=${CFLAGS-"-O"} # LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"} LDSHARED=${LDSHARED-"ld -b"} case `(uname -m || echo unknown) 2>/dev/null` in ia64) shared_ext='.so' SHAREDLIB='libz.so' ;; *) shared_ext='.sl' SHAREDLIB='libz.sl' ;; esac ;; IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} CFLAGS=${CFLAGS-"-ansi -O2"} LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"} CFLAGS=${CFLAGS-"-O -std1"} LDFLAGS="${LDFLAGS} -Wl,-rpath,." LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"} ;; OSF1*) SFLAGS=${CFLAGS-"-O -std1"} CFLAGS=${CFLAGS-"-O -std1"} LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; QNX*) SFLAGS=${CFLAGS-"-4 -O"} CFLAGS=${CFLAGS-"-4 -O"} LDSHARED=${LDSHARED-"cc"} RANLIB=${RANLIB-"true"} AR="cc" ARFLAGS="-A" ;; SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "} CFLAGS=${CFLAGS-"-O3"} LDSHARED=${LDSHARED-"cc -dy -KPIC -G"} ;; SunOS\ 5* | solaris*) LDSHARED=${LDSHARED-"cc -G -h libz$shared_ext.$VER1"} SFLAGS=${CFLAGS-"-fast -KPIC"} CFLAGS=${CFLAGS-"-fast"} if test $build64 -eq 1; then # old versions of SunPRO/Workshop/Studio don't support -m64, # but newer ones do. Check for it. flag64=`$CC -flags | egrep -- '^-m64'` if test x"$flag64" != x"" ; then CFLAGS="${CFLAGS} -m64" SFLAGS="${SFLAGS} -m64" else case `(uname -m || echo unknown) 2>/dev/null` in i86*) SFLAGS="$SFLAGS -xarch=amd64" CFLAGS="$CFLAGS -xarch=amd64" ;; *) SFLAGS="$SFLAGS -xarch=v9" CFLAGS="$CFLAGS -xarch=v9" ;; esac fi fi ;; SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} CFLAGS=${CFLAGS-"-O2"} LDSHARED=${LDSHARED-"ld"} ;; SunStudio\ 9*) SFLAGS=${CFLAGS-"-fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"} CFLAGS=${CFLAGS-"-fast -xtarget=ultra3 -xarch=v9b"} LDSHARED=${LDSHARED-"cc -xarch=v9b"} ;; UNIX_System_V\ 4.2.0) SFLAGS=${CFLAGS-"-KPIC -O"} CFLAGS=${CFLAGS-"-O"} LDSHARED=${LDSHARED-"cc -G"} ;; UNIX_SV\ 4.2MP) SFLAGS=${CFLAGS-"-Kconform_pic -O"} CFLAGS=${CFLAGS-"-O"} LDSHARED=${LDSHARED-"cc -G"} ;; OpenUNIX\ 5) SFLAGS=${CFLAGS-"-KPIC -O"} CFLAGS=${CFLAGS-"-O"} LDSHARED=${LDSHARED-"cc -G"} ;; AIX*) # Courtesy of dbakker@arrayasolutions.com SFLAGS=${CFLAGS-"-O -qmaxmem=8192"} CFLAGS=${CFLAGS-"-O -qmaxmem=8192"} LDSHARED=${LDSHARED-"xlc -G"} ;; # send working options for other systems to zlib@gzip.org *) SFLAGS=${CFLAGS-"-O"} CFLAGS=${CFLAGS-"-O"} LDSHARED=${LDSHARED-"cc -shared"} ;; esac fi # destination names for shared library if not defined above SHAREDLIB=${SHAREDLIB-"libz$shared_ext"} SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"} SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"} echo >> configure.log # define functions for testing compiler and library characteristics and logging the results cat > $test.c </dev/null; then try() { show $* test "`( $* ) 2>&1 | tee -a configure.log`" = "" } echo - using any output from compiler to indicate an error >> configure.log else try() { show $* ( $* ) >> configure.log 2>&1 ret=$? if test $ret -ne 0; then echo "(exit code "$ret")" >> configure.log fi return $ret } fi tryboth() { show $* got=`( $* ) 2>&1` ret=$? printf %s "$got" >> configure.log if test $ret -ne 0; then return $ret fi test "$got" = "" } cat > $test.c << EOF int foo() { return 0; } EOF echo "Checking for obsessive-compulsive compiler options..." >> configure.log if try $CC -c $CFLAGS $test.c; then : else echo "Compiler error reporting is too harsh for $0 (perhaps remove -Werror)." | tee -a configure.log leave 1 fi echo >> configure.log # see if shared library build supported cat > $test.c <> configure.log show "$NM $test.o | grep _hello" if test "`$NM $test.o | grep _hello | tee -a configure.log`" = ""; then CPP="$CPP -DNO_UNDERLINE" echo Checking for underline in external names... No. | tee -a configure.log else echo Checking for underline in external names... Yes. | tee -a configure.log fi ;; esac echo >> configure.log # check for large file support, and if none, check for fseeko() cat > $test.c < off64_t dummy = 0; EOF if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1" SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1" ALL="${ALL} all64" TEST="${TEST} test64" echo "Checking for off64_t... Yes." | tee -a configure.log echo "Checking for fseeko... Yes." | tee -a configure.log else echo "Checking for off64_t... No." | tee -a configure.log echo >> configure.log cat > $test.c < int main(void) { fseeko(NULL, 0, 0); return 0; } EOF if try $CC $CFLAGS -o $test $test.c; then echo "Checking for fseeko... Yes." | tee -a configure.log else CFLAGS="${CFLAGS} -DNO_FSEEKO" SFLAGS="${SFLAGS} -DNO_FSEEKO" echo "Checking for fseeko... No." | tee -a configure.log fi fi echo >> configure.log # check for strerror() for use by gz* functions cat > $test.c < #include int main() { return strlen(strerror(errno)); } EOF if try $CC $CFLAGS -o $test $test.c; then echo "Checking for strerror... Yes." | tee -a configure.log else CFLAGS="${CFLAGS} -DNO_STRERROR" SFLAGS="${SFLAGS} -DNO_STRERROR" echo "Checking for strerror... No." | tee -a configure.log fi # copy clean zconf.h for subsequent edits cp -p zconf.h.in zconf.h echo >> configure.log # check for unistd.h and save result in zconf.h cat > $test.c < int main() { return 0; } EOF if try $CC -c $CFLAGS $test.c; then sed < zconf.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be/ 1\1 was/" > zconf.temp.h mv zconf.temp.h zconf.h echo "Checking for unistd.h... Yes." | tee -a configure.log else echo "Checking for unistd.h... No." | tee -a configure.log fi echo >> configure.log # check for stdarg.h and save result in zconf.h cat > $test.c < int main() { return 0; } EOF if try $CC -c $CFLAGS $test.c; then sed < zconf.h "/^#ifdef HAVE_STDARG_H.* may be/s/def HAVE_STDARG_H\(.*\) may be/ 1\1 was/" > zconf.temp.h mv zconf.temp.h zconf.h echo "Checking for stdarg.h... Yes." | tee -a configure.log else echo "Checking for stdarg.h... No." | tee -a configure.log fi # if the z_ prefix was requested, save that in zconf.h if test $zprefix -eq 1; then sed < zconf.h "/#ifdef Z_PREFIX.* may be/s/def Z_PREFIX\(.*\) may be/ 1\1 was/" > zconf.temp.h mv zconf.temp.h zconf.h echo >> configure.log echo "Using z_ prefix on all symbols." | tee -a configure.log fi # if --solo compilation was requested, save that in zconf.h and remove gz stuff from object lists if test $solo -eq 1; then sed '/#define ZCONF_H/a\ #define Z_SOLO ' < zconf.h > zconf.temp.h mv zconf.temp.h zconf.h OBJC='$(OBJZ)' PIC_OBJC='$(PIC_OBJZ)' fi # if code coverage testing was requested, use older gcc if defined, e.g. "gcc-4.2" on Mac OS X if test $cover -eq 1; then CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage" if test -n "$GCC_CLASSIC"; then CC=$GCC_CLASSIC fi fi echo >> configure.log # conduct a series of tests to resolve eight possible cases of using "vs" or "s" printf functions # (using stdarg or not), with or without "n" (proving size of buffer), and with or without a # return value. The most secure result is vsnprintf() with a return value. snprintf() with a # return value is secure as well, but then gzprintf() will be limited to 20 arguments. cat > $test.c < #include #include "zconf.h" int main() { #ifndef STDC choke me #endif return 0; } EOF if try $CC -c $CFLAGS $test.c; then echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()." | tee -a configure.log echo >> configure.log cat > $test.c < #include int mytest(const char *fmt, ...) { char buf[20]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); return 0; } int main() { return (mytest("Hello%d\n", 1)); } EOF if try $CC $CFLAGS -o $test $test.c; then echo "Checking for vsnprintf() in stdio.h... Yes." | tee -a configure.log echo >> configure.log cat >$test.c < #include int mytest(const char *fmt, ...) { int n; char buf[20]; va_list ap; va_start(ap, fmt); n = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); return n; } int main() { return (mytest("Hello%d\n", 1)); } EOF if try $CC -c $CFLAGS $test.c; then echo "Checking for return value of vsnprintf()... Yes." | tee -a configure.log else CFLAGS="$CFLAGS -DHAS_vsnprintf_void" SFLAGS="$SFLAGS -DHAS_vsnprintf_void" echo "Checking for return value of vsnprintf()... No." | tee -a configure.log echo " WARNING: apparently vsnprintf() does not return a value. zlib" | tee -a configure.log echo " can build but will be open to possible string-format security" | tee -a configure.log echo " vulnerabilities." | tee -a configure.log fi else CFLAGS="$CFLAGS -DNO_vsnprintf" SFLAGS="$SFLAGS -DNO_vsnprintf" echo "Checking for vsnprintf() in stdio.h... No." | tee -a configure.log echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" | tee -a configure.log echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log echo " vulnerabilities." | tee -a configure.log echo >> configure.log cat >$test.c < #include int mytest(const char *fmt, ...) { int n; char buf[20]; va_list ap; va_start(ap, fmt); n = vsprintf(buf, fmt, ap); va_end(ap); return n; } int main() { return (mytest("Hello%d\n", 1)); } EOF if try $CC -c $CFLAGS $test.c; then echo "Checking for return value of vsprintf()... Yes." | tee -a configure.log else CFLAGS="$CFLAGS -DHAS_vsprintf_void" SFLAGS="$SFLAGS -DHAS_vsprintf_void" echo "Checking for return value of vsprintf()... No." | tee -a configure.log echo " WARNING: apparently vsprintf() does not return a value. zlib" | tee -a configure.log echo " can build but will be open to possible string-format security" | tee -a configure.log echo " vulnerabilities." | tee -a configure.log fi fi else echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()." | tee -a configure.log echo >> configure.log cat >$test.c < int mytest() { char buf[20]; snprintf(buf, sizeof(buf), "%s", "foo"); return 0; } int main() { return (mytest()); } EOF if try $CC $CFLAGS -o $test $test.c; then echo "Checking for snprintf() in stdio.h... Yes." | tee -a configure.log echo >> configure.log cat >$test.c < int mytest() { char buf[20]; return snprintf(buf, sizeof(buf), "%s", "foo"); } int main() { return (mytest()); } EOF if try $CC -c $CFLAGS $test.c; then echo "Checking for return value of snprintf()... Yes." | tee -a configure.log else CFLAGS="$CFLAGS -DHAS_snprintf_void" SFLAGS="$SFLAGS -DHAS_snprintf_void" echo "Checking for return value of snprintf()... No." | tee -a configure.log echo " WARNING: apparently snprintf() does not return a value. zlib" | tee -a configure.log echo " can build but will be open to possible string-format security" | tee -a configure.log echo " vulnerabilities." | tee -a configure.log fi else CFLAGS="$CFLAGS -DNO_snprintf" SFLAGS="$SFLAGS -DNO_snprintf" echo "Checking for snprintf() in stdio.h... No." | tee -a configure.log echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" | tee -a configure.log echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log echo " vulnerabilities." | tee -a configure.log echo >> configure.log cat >$test.c < int mytest() { char buf[20]; return sprintf(buf, "%s", "foo"); } int main() { return (mytest()); } EOF if try $CC -c $CFLAGS $test.c; then echo "Checking for return value of sprintf()... Yes." | tee -a configure.log else CFLAGS="$CFLAGS -DHAS_sprintf_void" SFLAGS="$SFLAGS -DHAS_sprintf_void" echo "Checking for return value of sprintf()... No." | tee -a configure.log echo " WARNING: apparently sprintf() does not return a value. zlib" | tee -a configure.log echo " can build but will be open to possible string-format security" | tee -a configure.log echo " vulnerabilities." | tee -a configure.log fi fi fi # see if we can hide zlib internal symbols that are linked between separate source files if test "$gcc" -eq 1; then echo >> configure.log cat > $test.c <> configure.log echo ALL = $ALL >> configure.log echo AR = $AR >> configure.log echo ARFLAGS = $ARFLAGS >> configure.log echo CC = $CC >> configure.log echo CFLAGS = $CFLAGS >> configure.log echo CPP = $CPP >> configure.log echo EXE = $EXE >> configure.log echo LDCONFIG = $LDCONFIG >> configure.log echo LDFLAGS = $LDFLAGS >> configure.log echo LDSHARED = $LDSHARED >> configure.log echo LDSHAREDLIBC = $LDSHAREDLIBC >> configure.log echo OBJC = $OBJC >> configure.log echo PIC_OBJC = $PIC_OBJC >> configure.log echo RANLIB = $RANLIB >> configure.log echo SFLAGS = $SFLAGS >> configure.log echo SHAREDLIB = $SHAREDLIB >> configure.log echo SHAREDLIBM = $SHAREDLIBM >> configure.log echo SHAREDLIBV = $SHAREDLIBV >> configure.log echo STATICLIB = $STATICLIB >> configure.log echo TEST = $TEST >> configure.log echo VER = $VER >> configure.log echo Z_U4 = $Z_U4 >> configure.log echo exec_prefix = $exec_prefix >> configure.log echo includedir = $includedir >> configure.log echo libdir = $libdir >> configure.log echo mandir = $mandir >> configure.log echo prefix = $prefix >> configure.log echo sharedlibdir = $sharedlibdir >> configure.log echo uname = $uname >> configure.log # udpate Makefile with the configure results sed < Makefile.in " /^CC *=/s#=.*#=$CC# /^CFLAGS *=/s#=.*#=$CFLAGS# /^SFLAGS *=/s#=.*#=$SFLAGS# /^LDFLAGS *=/s#=.*#=$LDFLAGS# /^LDSHARED *=/s#=.*#=$LDSHARED# /^CPP *=/s#=.*#=$CPP# /^STATICLIB *=/s#=.*#=$STATICLIB# /^SHAREDLIB *=/s#=.*#=$SHAREDLIB# /^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# /^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# /^AR *=/s#=.*#=$AR# /^ARFLAGS *=/s#=.*#=$ARFLAGS# /^RANLIB *=/s#=.*#=$RANLIB# /^LDCONFIG *=/s#=.*#=$LDCONFIG# /^LDSHAREDLIBC *=/s#=.*#=$LDSHAREDLIBC# /^EXE *=/s#=.*#=$EXE# /^prefix *=/s#=.*#=$prefix# /^exec_prefix *=/s#=.*#=$exec_prefix# /^libdir *=/s#=.*#=$libdir# /^sharedlibdir *=/s#=.*#=$sharedlibdir# /^includedir *=/s#=.*#=$includedir# /^mandir *=/s#=.*#=$mandir# /^OBJC *=/s#=.*#= $OBJC# /^PIC_OBJC *=/s#=.*#= $PIC_OBJC# /^all: */s#:.*#: $ALL# /^test: */s#:.*#: $TEST# " > Makefile # create zlib.pc with the configure results sed < zlib.pc.in " /^CC *=/s#=.*#=$CC# /^CFLAGS *=/s#=.*#=$CFLAGS# /^CPP *=/s#=.*#=$CPP# /^LDSHARED *=/s#=.*#=$LDSHARED# /^STATICLIB *=/s#=.*#=$STATICLIB# /^SHAREDLIB *=/s#=.*#=$SHAREDLIB# /^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# /^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# /^AR *=/s#=.*#=$AR# /^ARFLAGS *=/s#=.*#=$ARFLAGS# /^RANLIB *=/s#=.*#=$RANLIB# /^EXE *=/s#=.*#=$EXE# /^prefix *=/s#=.*#=$prefix# /^exec_prefix *=/s#=.*#=$exec_prefix# /^libdir *=/s#=.*#=$libdir# /^sharedlibdir *=/s#=.*#=$sharedlibdir# /^includedir *=/s#=.*#=$includedir# /^mandir *=/s#=.*#=$mandir# /^LDFLAGS *=/s#=.*#=$LDFLAGS# " | sed -e " s/\@VERSION\@/$VER/g; " > zlib.pc # done leave 0 tcl8.6.5/compat/zlib/adler32.c0000644000175000017500000001155012663660064015413 0ustar sergeisergei/* adler32.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" #define local static local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); #define BASE 65521 /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); /* use NO_DIVIDE if your processor does not do division in hardware -- try it both ways to see which is faster */ #ifdef NO_DIVIDE /* note that this assumes BASE is 65521, where 65536 % 65521 == 15 (thank you to John Reiser for pointing this out) */ # define CHOP(a) \ do { \ unsigned long tmp = a >> 16; \ a &= 0xffffUL; \ a += (tmp << 4) - tmp; \ } while (0) # define MOD28(a) \ do { \ CHOP(a); \ if (a >= BASE) a -= BASE; \ } while (0) # define MOD(a) \ do { \ CHOP(a); \ MOD28(a); \ } while (0) # define MOD63(a) \ do { /* this assumes a is not negative */ \ z_off64_t tmp = a >> 32; \ a &= 0xffffffffL; \ a += (tmp << 8) - (tmp << 5) + tmp; \ tmp = a >> 16; \ a &= 0xffffL; \ a += (tmp << 4) - tmp; \ tmp = a >> 16; \ a &= 0xffffL; \ a += (tmp << 4) - tmp; \ if (a >= BASE) a -= BASE; \ } while (0) #else # define MOD(a) a %= BASE # define MOD28(a) a %= BASE # define MOD63(a) a %= BASE #endif /* ========================================================================= */ uLong ZEXPORT adler32(adler, buf, len) uLong adler; const Bytef *buf; uInt len; { unsigned long sum2; unsigned n; /* split Adler-32 into component sums */ sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; /* in case user likes doing a byte at a time, keep it fast */ if (len == 1) { adler += buf[0]; if (adler >= BASE) adler -= BASE; sum2 += adler; if (sum2 >= BASE) sum2 -= BASE; return adler | (sum2 << 16); } /* initial Adler-32 value (deferred check for len == 1 speed) */ if (buf == Z_NULL) return 1L; /* in case short lengths are provided, keep it somewhat fast */ if (len < 16) { while (len--) { adler += *buf++; sum2 += adler; } if (adler >= BASE) adler -= BASE; MOD28(sum2); /* only added so many BASE's */ return adler | (sum2 << 16); } /* do length NMAX blocks -- requires just one modulo operation */ while (len >= NMAX) { len -= NMAX; n = NMAX / 16; /* NMAX is divisible by 16 */ do { DO16(buf); /* 16 sums unrolled */ buf += 16; } while (--n); MOD(adler); MOD(sum2); } /* do remaining bytes (less than NMAX, still just one modulo) */ if (len) { /* avoid modulos if none remaining */ while (len >= 16) { len -= 16; DO16(buf); buf += 16; } while (len--) { adler += *buf++; sum2 += adler; } MOD(adler); MOD(sum2); } /* return recombined sums */ return adler | (sum2 << 16); } /* ========================================================================= */ local uLong adler32_combine_(adler1, adler2, len2) uLong adler1; uLong adler2; z_off64_t len2; { unsigned long sum1; unsigned long sum2; unsigned rem; /* for negative len, return invalid adler32 as a clue for debugging */ if (len2 < 0) return 0xffffffffUL; /* the derivation of this formula is left as an exercise for the reader */ MOD63(len2); /* assumes len2 >= 0 */ rem = (unsigned)len2; sum1 = adler1 & 0xffff; sum2 = rem * sum1; MOD(sum2); sum1 += (adler2 & 0xffff) + BASE - 1; sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; if (sum1 >= BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE; if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); if (sum2 >= BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } /* ========================================================================= */ uLong ZEXPORT adler32_combine(adler1, adler2, len2) uLong adler1; uLong adler2; z_off_t len2; { return adler32_combine_(adler1, adler2, len2); } uLong ZEXPORT adler32_combine64(adler1, adler2, len2) uLong adler1; uLong adler2; z_off64_t len2; { return adler32_combine_(adler1, adler2, len2); } tcl8.6.5/compat/zlib/msdos/0000755000175000017500000000000012665173607015142 5ustar sergeisergeitcl8.6.5/compat/zlib/msdos/Makefile.msc0000644000175000017500000000555412663660065017371 0ustar sergeisergei# Makefile for zlib # Microsoft C 5.1 or later # Last updated: 19-Mar-2003 # To use, do "make makefile.msc" # To compile in small model, set below: MODEL=S # If you wish to reduce the memory requirements (default 256K for big # objects plus a few K), you can add to the LOC macro below: # -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 # See zconf.h for details about the memory requirements. # ------------- Microsoft C 5.1 and later ------------- # Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) # should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added # to the declaration of LOC here: LOC = $(LOCAL_ZLIB) # Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. CPU_TYP = 0 # Memory model: one of S, M, C, L (small, medium, compact, large) MODEL=L CC=cl CFLAGS=-nologo -A$(MODEL) -G$(CPU_TYP) -W3 -Oait -Gs $(LOC) #-Ox generates bad code with MSC 5.1 LIB_CFLAGS=-Zl $(CFLAGS) LD=link LDFLAGS=/noi/e/st:0x1500/noe/farcall/packcode # "/farcall/packcode" are only useful for `large code' memory models # but should be a "no-op" for small code models. # variables ZLIB_LIB = zlib_$(MODEL).lib OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj # targets all: $(ZLIB_LIB) example.exe minigzip.exe .c.obj: $(CC) -c $(LIB_CFLAGS) $*.c adler32.obj: adler32.c zlib.h zconf.h compress.obj: compress.c zlib.h zconf.h crc32.obj: crc32.c zlib.h zconf.h crc32.h deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h gzread.obj: gzread.c zlib.h zconf.h gzguts.h gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h uncompr.obj: uncompr.c zlib.h zconf.h zutil.obj: zutil.c zutil.h zlib.h zconf.h example.obj: test/example.c zlib.h zconf.h $(CC) -c $(CFLAGS) $*.c minigzip.obj: test/minigzip.c zlib.h zconf.h $(CC) -c $(CFLAGS) $*.c # the command line is cut to fit in the MS-DOS 128 byte limit: $(ZLIB_LIB): $(OBJ1) $(OBJ2) if exist $(ZLIB_LIB) del $(ZLIB_LIB) lib $(ZLIB_LIB) $(OBJ1); lib $(ZLIB_LIB) $(OBJ2); example.exe: example.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) example.obj,,,$(ZLIB_LIB); minigzip.exe: minigzip.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) minigzip.obj,,,$(ZLIB_LIB); test: example.exe minigzip.exe example echo hello world | minigzip | minigzip -d clean: -del *.obj -del *.lib -del *.exe -del *.map -del zlib_*.bak -del foo.gz tcl8.6.5/compat/zlib/msdos/Makefile.dj20000644000175000017500000000506712663653206017264 0ustar sergeisergei# Makefile for zlib. Modified for djgpp v2.0 by F. J. Donahoe, 3/15/96. # Copyright (C) 1995-1998 Jean-loup Gailly. # For conditions of distribution and use, see copyright notice in zlib.h # To compile, or to compile and test, type: # # make -fmakefile.dj2; make test -fmakefile.dj2 # # To install libz.a, zconf.h and zlib.h in the djgpp directories, type: # # make install -fmakefile.dj2 # # after first defining LIBRARY_PATH and INCLUDE_PATH in djgpp.env as # in the sample below if the pattern of the DJGPP distribution is to # be followed. Remember that, while 'es around <=> are ignored in # makefiles, they are *not* in batch files or in djgpp.env. # - - - - - # [make] # INCLUDE_PATH=%\>;INCLUDE_PATH%%\DJDIR%\include # LIBRARY_PATH=%\>;LIBRARY_PATH%%\DJDIR%\lib # BUTT=-m486 # - - - - - # Alternately, these variables may be defined below, overriding the values # in djgpp.env, as # INCLUDE_PATH=c:\usr\include # LIBRARY_PATH=c:\usr\lib CC=gcc #CFLAGS=-MMD -O #CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 #CFLAGS=-MMD -g -DDEBUG CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -Wstrict-prototypes -Wmissing-prototypes # If cp.exe is available, replace "copy /Y" with "cp -fp" . CP=copy /Y # If gnu install.exe is available, replace $(CP) with ginstall. INSTALL=$(CP) # The default value of RM is "rm -f." If "rm.exe" is found, comment out: RM=del LDLIBS=-L. -lz LD=$(CC) -s -o LDSHARED=$(CC) INCL=zlib.h zconf.h LIBS=libz.a AR=ar rcs prefix=/usr/local exec_prefix = $(prefix) OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o OBJA = # to use the asm code: make OBJA=match.o TEST_OBJS = example.o minigzip.o all: example.exe minigzip.exe check: test test: all ./example echo hello world | .\minigzip | .\minigzip -d %.o : %.c $(CC) $(CFLAGS) -c $< -o $@ libz.a: $(OBJS) $(OBJA) $(AR) $@ $(OBJS) $(OBJA) %.exe : %.o $(LIBS) $(LD) $@ $< $(LDLIBS) # INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env . .PHONY : uninstall clean install: $(INCL) $(LIBS) -@if not exist $(INCLUDE_PATH)\nul mkdir $(INCLUDE_PATH) -@if not exist $(LIBRARY_PATH)\nul mkdir $(LIBRARY_PATH) $(INSTALL) zlib.h $(INCLUDE_PATH) $(INSTALL) zconf.h $(INCLUDE_PATH) $(INSTALL) libz.a $(LIBRARY_PATH) uninstall: $(RM) $(INCLUDE_PATH)\zlib.h $(RM) $(INCLUDE_PATH)\zconf.h $(RM) $(LIBRARY_PATH)\libz.a clean: $(RM) *.d $(RM) *.o $(RM) *.exe $(RM) libz.a $(RM) foo.gz DEPS := $(wildcard *.d) ifneq ($(DEPS),) include $(DEPS) endif tcl8.6.5/compat/zlib/msdos/Makefile.tc0000644000175000017500000000514112663660065017205 0ustar sergeisergei# Makefile for zlib # Turbo C 2.01, Turbo C++ 1.01 # Last updated: 15-Mar-2003 # To use, do "make -fmakefile.tc" # To compile in small model, set below: MODEL=s # WARNING: the small model is supported but only for small values of # MAX_WBITS and MAX_MEM_LEVEL. For example: # -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 # If you wish to reduce the memory requirements (default 256K for big # objects plus a few K), you can add to CFLAGS below: # -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 # See zconf.h for details about the memory requirements. # ------------ Turbo C 2.01, Turbo C++ 1.01 ------------ MODEL=l CC=tcc LD=tcc AR=tlib # CFLAGS=-O2 -G -Z -m$(MODEL) -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 CFLAGS=-O2 -G -Z -m$(MODEL) LDFLAGS=-m$(MODEL) -f- # variables ZLIB_LIB = zlib_$(MODEL).lib OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj # targets all: $(ZLIB_LIB) example.exe minigzip.exe .c.obj: $(CC) -c $(CFLAGS) $*.c adler32.obj: adler32.c zlib.h zconf.h compress.obj: compress.c zlib.h zconf.h crc32.obj: crc32.c zlib.h zconf.h crc32.h deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h gzread.obj: gzread.c zlib.h zconf.h gzguts.h gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h uncompr.obj: uncompr.c zlib.h zconf.h zutil.obj: zutil.c zutil.h zlib.h zconf.h example.obj: test/example.c zlib.h zconf.h minigzip.obj: test/minigzip.c zlib.h zconf.h # the command line is cut to fit in the MS-DOS 128 byte limit: $(ZLIB_LIB): $(OBJ1) $(OBJ2) -del $(ZLIB_LIB) $(AR) $(ZLIB_LIB) $(OBJP1) $(AR) $(ZLIB_LIB) $(OBJP2) example.exe: example.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) minigzip.exe: minigzip.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) test: example.exe minigzip.exe example echo hello world | minigzip | minigzip -d clean: -del *.obj -del *.lib -del *.exe -del zlib_*.bak -del foo.gz tcl8.6.5/compat/zlib/msdos/Makefile.bor0000644000175000017500000000603212663660065017361 0ustar sergeisergei# Makefile for zlib # Borland C++ # Last updated: 15-Mar-2003 # To use, do "make -fmakefile.bor" # To compile in small model, set below: MODEL=s # WARNING: the small model is supported but only for small values of # MAX_WBITS and MAX_MEM_LEVEL. For example: # -DMAX_WBITS=11 -DDEF_WBITS=11 -DMAX_MEM_LEVEL=3 # If you wish to reduce the memory requirements (default 256K for big # objects plus a few K), you can add to the LOC macro below: # -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 # See zconf.h for details about the memory requirements. # ------------ Turbo C++, Borland C++ ------------ # Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) # should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added # to the declaration of LOC here: LOC = $(LOCAL_ZLIB) # type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. CPU_TYP = 0 # memory model: one of s, m, c, l (small, medium, compact, large) MODEL=l # replace bcc with tcc for Turbo C++ 1.0, with bcc32 for the 32 bit version CC=bcc LD=bcc AR=tlib # compiler flags # replace "-O2" by "-O -G -a -d" for Turbo C++ 1.0 CFLAGS=-O2 -Z -m$(MODEL) $(LOC) LDFLAGS=-m$(MODEL) -f- # variables ZLIB_LIB = zlib_$(MODEL).lib OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj # targets all: $(ZLIB_LIB) example.exe minigzip.exe .c.obj: $(CC) -c $(CFLAGS) $*.c adler32.obj: adler32.c zlib.h zconf.h compress.obj: compress.c zlib.h zconf.h crc32.obj: crc32.c zlib.h zconf.h crc32.h deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h gzread.obj: gzread.c zlib.h zconf.h gzguts.h gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h uncompr.obj: uncompr.c zlib.h zconf.h zutil.obj: zutil.c zutil.h zlib.h zconf.h example.obj: test/example.c zlib.h zconf.h minigzip.obj: test/minigzip.c zlib.h zconf.h # the command line is cut to fit in the MS-DOS 128 byte limit: $(ZLIB_LIB): $(OBJ1) $(OBJ2) -del $(ZLIB_LIB) $(AR) $(ZLIB_LIB) $(OBJP1) $(AR) $(ZLIB_LIB) $(OBJP2) example.exe: example.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) minigzip.exe: minigzip.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) test: example.exe minigzip.exe example echo hello world | minigzip | minigzip -d clean: -del *.obj -del *.lib -del *.exe -del zlib_*.bak -del foo.gz tcl8.6.5/compat/zlib/msdos/Makefile.emx0000644000175000017500000000264212663653206017372 0ustar sergeisergei# Makefile for zlib. Modified for emx 0.9c by Chr. Spieler, 6/17/98. # Copyright (C) 1995-1998 Jean-loup Gailly. # For conditions of distribution and use, see copyright notice in zlib.h # To compile, or to compile and test, type: # # make -fmakefile.emx; make test -fmakefile.emx # CC=gcc #CFLAGS=-MMD -O #CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 #CFLAGS=-MMD -g -DDEBUG CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -Wstrict-prototypes -Wmissing-prototypes # If cp.exe is available, replace "copy /Y" with "cp -fp" . CP=copy /Y # If gnu install.exe is available, replace $(CP) with ginstall. INSTALL=$(CP) # The default value of RM is "rm -f." If "rm.exe" is found, comment out: RM=del LDLIBS=-L. -lzlib LD=$(CC) -s -o LDSHARED=$(CC) INCL=zlib.h zconf.h LIBS=zlib.a AR=ar rcs prefix=/usr/local exec_prefix = $(prefix) OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o TEST_OBJS = example.o minigzip.o all: example.exe minigzip.exe test: all ./example echo hello world | .\minigzip | .\minigzip -d %.o : %.c $(CC) $(CFLAGS) -c $< -o $@ zlib.a: $(OBJS) $(AR) $@ $(OBJS) %.exe : %.o $(LIBS) $(LD) $@ $< $(LDLIBS) .PHONY : clean clean: $(RM) *.d $(RM) *.o $(RM) *.exe $(RM) zlib.a $(RM) foo.gz DEPS := $(wildcard *.d) ifneq ($(DEPS),) include $(DEPS) endif tcl8.6.5/compat/zlib/zconf.h.cmakein0000644000175000017500000003630712663660065016721 0ustar sergeisergei/* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #ifndef ZCONF_H #define ZCONF_H #cmakedefine Z_PREFIX #cmakedefine Z_HAVE_UNISTD_H /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * Even better than compiling with -DZ_PREFIX would be to use configure to set * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET /* all linked symbols */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align # define _tr_flush_bits z__tr_flush_bits # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block # define _tr_tally z__tr_tally # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 # ifndef Z_SOLO # define compress z_compress # define compress2 z_compress2 # define compressBound z_compressBound # endif # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams # define deflatePending z_deflatePending # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset # define deflateResetKeep z_deflateResetKeep # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table # ifndef Z_SOLO # define gz_error z_gz_error # define gz_intmax z_gz_intmax # define gz_strwinerror z_gz_strwinerror # define gzbuffer z_gzbuffer # define gzclearerr z_gzclearerr # define gzclose z_gzclose # define gzclose_r z_gzclose_r # define gzclose_w z_gzclose_w # define gzdirect z_gzdirect # define gzdopen z_gzdopen # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush # define gzgetc z_gzgetc # define gzgetc_ z_gzgetc_ # define gzgets z_gzgets # define gzoffset z_gzoffset # define gzoffset64 z_gzoffset64 # define gzopen z_gzopen # define gzopen64 z_gzopen64 # ifdef _WIN32 # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf # define gzvprintf z_gzvprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread # define gzrewind z_gzrewind # define gzseek z_gzseek # define gzseek64 z_gzseek64 # define gzsetparams z_gzsetparams # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc # define gzwrite z_gzwrite # endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd # define inflateBackInit_ z_inflateBackInit_ # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd # define inflateGetHeader z_inflateGetHeader # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 # define inflateSetDictionary z_inflateSetDictionary # define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine # define inflateResetKeep z_inflateResetKeep # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # ifndef Z_SOLO # define uncompress z_uncompress # endif # define zError z_zError # ifndef Z_SOLO # define zcalloc z_zcalloc # define zcfree z_zcfree # endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion /* all zlib typedefs in zlib.h and zconf.h */ # define Byte z_Byte # define Bytef z_Bytef # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func # ifndef Z_SOLO # define gzFile z_gzFile # endif # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func # define intf z_intf # define out_func z_out_func # define uInt z_uInt # define uIntf z_uIntf # define uLong z_uLong # define uLongf z_uLongf # define voidp z_voidp # define voidpc z_voidpc # define voidpf z_voidpf /* all zlib structs in zlib.h and zconf.h */ # define gz_header_s z_gz_header_s # define internal_state z_internal_state #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) # define OS2 #endif #if defined(_WINDOWS) && !defined(WINDOWS) # define WINDOWS #endif #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) # ifndef WIN32 # define WIN32 # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # ifndef SYS16BIT # define SYS16BIT # endif # endif #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #ifdef SYS16BIT # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #ifdef __STDC_VERSION__ # ifndef STDC # define STDC # endif # if __STDC_VERSION__ >= 199901L # ifndef STDC99 # define STDC99 # endif # endif #endif #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) # define STDC #endif #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) # define STDC #endif #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) # define STDC #endif #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) # define STDC #endif #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ # define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const /* note: need a more gentle solution here */ # endif #endif #if defined(ZLIB_CONST) && !defined(z_const) # define z_const const #else # define z_const #endif /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) # define NO_DUMMY_DECL #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus a few kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif #ifndef Z_ARG /* function prototypes for stdarg */ # if defined(STDC) || defined(Z_HAVE_STDARG_H) # define Z_ARG(args) args # else # define Z_ARG(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #ifdef SYS16BIT # if defined(M_I86SM) || defined(M_I86MM) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR _far # else # define FAR far # endif # endif # if (defined(__SMALL__) || defined(__MEDIUM__)) /* Turbo C small or medium model */ # define SMALL_MEDIUM # ifdef __BORLANDC__ # define FAR _far # else # define FAR far # endif # endif #endif #if defined(WINDOWS) || defined(WIN32) /* If building or using zlib as a DLL, define ZLIB_DLL. * This is not mandatory, but it offers a little performance increase. */ # ifdef ZLIB_DLL # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) # ifdef ZLIB_INTERNAL # define ZEXTERN extern __declspec(dllexport) # else # define ZEXTERN extern __declspec(dllimport) # endif # endif # endif /* ZLIB_DLL */ /* If building or using zlib with the WINAPI/WINAPIV calling convention, * define ZLIB_WINAPI. * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 # define ZEXPORTVA WINAPIV # else # define ZEXPORTVA FAR CDECL # endif # endif #endif #if defined (__BEOS__) # ifdef ZLIB_DLL # ifdef ZLIB_INTERNAL # define ZEXPORT __declspec(dllexport) # define ZEXPORTVA __declspec(dllexport) # else # define ZEXPORT __declspec(dllimport) # define ZEXPORTVA __declspec(dllimport) # endif # endif #endif #ifndef ZEXTERN # define ZEXTERN extern #endif #ifndef ZEXPORT # define ZEXPORT #endif #ifndef ZEXPORTVA # define ZEXPORTVA #endif #ifndef FAR # define FAR #endif #if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void const *voidpc; typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte const *voidpc; typedef Byte FAR *voidpf; typedef Byte *voidp; #endif #if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) # include # if (UINT_MAX == 0xffffffffUL) # define Z_U4 unsigned # elif (ULONG_MAX == 0xffffffffUL) # define Z_U4 unsigned long # elif (USHRT_MAX == 0xffffffffUL) # define Z_U4 unsigned short # endif #endif #ifdef Z_U4 typedef Z_U4 z_crc_t; #else typedef unsigned long z_crc_t; #endif #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif #ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_STDARG_H #endif #ifdef STDC # ifndef Z_SOLO # include /* for off_t */ # endif #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO # include /* for va_list */ # endif #endif #ifdef _WIN32 # ifndef Z_SOLO # include /* for wchar_t */ # endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even * though the former does not conform to the LFS document), but considering * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ #if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif #if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) # define Z_HAVE_UNISTD_H #endif #ifndef Z_SOLO # if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ # endif # ifndef z_off_t # define z_off_t off_t # endif # endif #endif #if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 # define Z_LFS64 #endif #if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) # define Z_LARGE64 #endif #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) # define Z_WANT64 #endif #if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t # define z_off_t long #endif #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else # if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) # define z_off64_t __int64 # else # define z_off64_t z_off_t # endif #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) #pragma map(deflateInit_,"DEIN") #pragma map(deflateInit2_,"DEIN2") #pragma map(deflateEnd,"DEEND") #pragma map(deflateBound,"DEBND") #pragma map(inflateInit_,"ININ") #pragma map(inflateInit2_,"ININ2") #pragma map(inflateEnd,"INEND") #pragma map(inflateSync,"INSY") #pragma map(inflateSetDictionary,"INSEDI") #pragma map(compressBound,"CMBND") #pragma map(inflate_table,"INTABL") #pragma map(inflate_fast,"INFA") #pragma map(inflate_copyright,"INCOPY") #endif #endif /* ZCONF_H */ tcl8.6.5/compat/zlib/inffast.c0000644000175000017500000003221712663660065015615 0ustar sergeisergei/* inffast.c -- fast decoding * Copyright (C) 1995-2008, 2010, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" #ifndef ASMINF /* Allow machine dependent optimization for post-increment or pre-increment. Based on testing to date, Pre-increment preferred for: - PowerPC G3 (Adler) - MIPS R5000 (Randers-Pehrson) Post-increment preferred for: - none No measurable difference: - Pentium III (Anderson) - M68060 (Nikl) */ #ifdef POSTINC # define OFF 0 # define PUP(a) *(a)++ #else # define OFF 1 # define PUP(a) *++(a) #endif /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is available, an end-of-block is encountered, or a data error is encountered. When large enough input and output buffers are supplied to inflate(), for example, a 16K input buffer and a 64K output buffer, more than 95% of the inflate execution time is spent in this routine. Entry assumptions: state->mode == LEN strm->avail_in >= 6 strm->avail_out >= 258 start >= strm->avail_out state->bits < 8 On return, state->mode is one of: LEN -- ran out of enough output space or enough available input TYPE -- reached end of block code, inflate() to interpret next block BAD -- error in block data Notes: - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, and 13 bits for the distance extra. This totals 48 bits, or six bytes. Therefore if strm->avail_in >= 6, then there is enough input to avoid checking for available input while decoding. - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ void ZLIB_INTERNAL inflate_fast(strm, start) z_streamp strm; unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; z_const unsigned char FAR *in; /* local strm->next_in */ z_const unsigned char FAR *last; /* have enough input while in < last */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ #ifdef INFLATE_STRICT unsigned dmax; /* maximum distance from zlib header */ #endif unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ unsigned long hold; /* local strm->hold */ unsigned bits; /* local strm->bits */ code const FAR *lcode; /* local strm->lencode */ code const FAR *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ code here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ unsigned char FAR *from; /* where to copy match from */ /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; in = strm->next_in - OFF; last = in + (strm->avail_in - 5); out = strm->next_out - OFF; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT dmax = state->dmax; #endif wsize = state->wsize; whave = state->whave; wnext = state->wnext; window = state->window; hold = state->hold; bits = state->bits; lcode = state->lencode; dcode = state->distcode; lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { if (bits < 15) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; hold += (unsigned long)(PUP(in)) << bits; bits += 8; } here = lcode[hold & lmask]; dolen: op = (unsigned)(here.bits); hold >>= op; bits -= op; op = (unsigned)(here.op); if (op == 0) { /* literal */ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); PUP(out) = (unsigned char)(here.val); } else if (op & 16) { /* length base */ len = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); hold >>= op; bits -= op; } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; hold += (unsigned long)(PUP(in)) << bits; bits += 8; } here = dcode[hold & dmask]; dodist: op = (unsigned)(here.bits); hold >>= op; bits -= op; op = (unsigned)(here.op); if (op & 16) { /* distance base */ dist = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; } } dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT if (dist > dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif hold >>= op; bits -= op; Tracevv((stderr, "inflate: distance %u\n", dist)); op = (unsigned)(out - beg); /* max distance in output */ if (dist > op) { /* see if copy from window */ op = dist - op; /* distance back in window */ if (op > whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { PUP(out) = 0; } while (--len); continue; } len -= op - whave; do { PUP(out) = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { PUP(out) = PUP(from); } while (--len); continue; } #endif } from = window - OFF; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } else if (wnext < op) { /* wrap around window */ from += wsize + wnext - op; op -= wnext; if (op < len) { /* some from end of window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = window - OFF; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } } else { /* contiguous in window */ from += wnext - op; if (op < len) { /* some from window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { PUP(out) = PUP(from); PUP(out) = PUP(from); PUP(out) = PUP(from); len -= 3; } if (len) { PUP(out) = PUP(from); if (len > 1) PUP(out) = PUP(from); } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ PUP(out) = PUP(from); PUP(out) = PUP(from); PUP(out) = PUP(from); len -= 3; } while (len > 2); if (len) { PUP(out) = PUP(from); if (len > 1) PUP(out) = PUP(from); } } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode[here.val + (hold & ((1U << op) - 1))]; goto dodist; } else { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } } else if ((op & 64) == 0) { /* 2nd level length code */ here = lcode[here.val + (hold & ((1U << op) - 1))]; goto dolen; } else if (op & 32) { /* end-of-block */ Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } else { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } } while (in < last && out < end); /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ len = bits >> 3; in -= len; bits -= len << 3; hold &= (1U << bits) - 1; /* update state and return */ strm->next_in = in + OFF; strm->next_out = out + OFF; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); state->hold = hold; state->bits = bits; return; } /* inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - Using bit fields for code structure - Different op definition to avoid & for extra bits (do & for table bits) - Three separate decoding do-loops for direct, window, and wnext == 0 - Special case for distance > 1 copies to do overlapped load and store copy - Explicit branch predictions (based on measured branch probabilities) - Deferring match copy and interspersed it with decoding subsequent codes - Swapping literal/length else - Swapping window/direct else - Larger unrolled copy loops (three is about right) - Moving len -= 3 statement into middle of loop */ #endif /* !ASMINF */ tcl8.6.5/compat/zlib/watcom/0000755000175000017500000000000012665173607015307 5ustar sergeisergeitcl8.6.5/compat/zlib/watcom/watcom_l.mak0000644000175000017500000000257712663653206017615 0ustar sergeisergei# Makefile for zlib # OpenWatcom large model # Last updated: 28-Dec-2005 # To use, do "wmake -f watcom_l.mak" C_SOURCE = adler32.c compress.c crc32.c deflate.c & gzclose.c gzlib.c gzread.c gzwrite.c & infback.c inffast.c inflate.c inftrees.c & trees.c uncompr.c zutil.c OBJS = adler32.obj compress.obj crc32.obj deflate.obj & gzclose.obj gzlib.obj gzread.obj gzwrite.obj & infback.obj inffast.obj inflate.obj inftrees.obj & trees.obj uncompr.obj zutil.obj CC = wcc LINKER = wcl CFLAGS = -zq -ml -s -bt=dos -oilrtfm -fr=nul -wx ZLIB_LIB = zlib_l.lib .C.OBJ: $(CC) $(CFLAGS) $[@ all: $(ZLIB_LIB) example.exe minigzip.exe $(ZLIB_LIB): $(OBJS) wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj example.exe: $(ZLIB_LIB) example.obj $(LINKER) -fe=example.exe example.obj $(ZLIB_LIB) minigzip.exe: $(ZLIB_LIB) minigzip.obj $(LINKER) -fe=minigzip.exe minigzip.obj $(ZLIB_LIB) clean: .SYMBOLIC del *.obj del $(ZLIB_LIB) @echo Cleaning done tcl8.6.5/compat/zlib/watcom/watcom_f.mak0000644000175000017500000000263712663653206017604 0ustar sergeisergei# Makefile for zlib # OpenWatcom flat model # Last updated: 28-Dec-2005 # To use, do "wmake -f watcom_f.mak" C_SOURCE = adler32.c compress.c crc32.c deflate.c & gzclose.c gzlib.c gzread.c gzwrite.c & infback.c inffast.c inflate.c inftrees.c & trees.c uncompr.c zutil.c OBJS = adler32.obj compress.obj crc32.obj deflate.obj & gzclose.obj gzlib.obj gzread.obj gzwrite.obj & infback.obj inffast.obj inflate.obj inftrees.obj & trees.obj uncompr.obj zutil.obj CC = wcc386 LINKER = wcl386 CFLAGS = -zq -mf -3r -fp3 -s -bt=dos -oilrtfm -fr=nul -wx ZLIB_LIB = zlib_f.lib .C.OBJ: $(CC) $(CFLAGS) $[@ all: $(ZLIB_LIB) example.exe minigzip.exe $(ZLIB_LIB): $(OBJS) wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj example.exe: $(ZLIB_LIB) example.obj $(LINKER) -ldos32a -fe=example.exe example.obj $(ZLIB_LIB) minigzip.exe: $(ZLIB_LIB) minigzip.obj $(LINKER) -ldos32a -fe=minigzip.exe minigzip.obj $(ZLIB_LIB) clean: .SYMBOLIC del *.obj del $(ZLIB_LIB) @echo Cleaning done tcl8.6.5/compat/zlib/gzclose.c0000644000175000017500000000124612663653206015626 0ustar sergeisergei/* gzclose.c -- zlib gzclose() function * Copyright (C) 2004, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" /* gzclose() is in a separate file so that it is linked in only if it is used. That way the other gzclose functions can be used instead to avoid linking in unneeded compression or decompression routines. */ int ZEXPORT gzclose(file) gzFile file; { #ifndef NO_GZCOMPRESS gz_statep state; if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); #else return gzclose_r(file); #endif } tcl8.6.5/compat/zlib/test/0000755000175000017500000000000012665173607014774 5ustar sergeisergeitcl8.6.5/compat/zlib/test/minigzip.c0000644000175000017500000003662412663660065016776 0ustar sergeisergei/* minigzip.c -- simulate gzip using the zlib compression library * Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* * minigzip is a minimal implementation of the gzip utility. This is * only an example of using zlib and isn't meant to replace the * full-featured gzip. No attempt is made to deal with file systems * limiting names to 14 or 8+3 characters, etc... Error checking is * very limited. So use minigzip only for testing; use gzip for the * real thing. On MSDOS, use only on file names without extension * or in pipe mode. */ /* @(#) $Id$ */ #include "zlib.h" #include #ifdef STDC # include # include #endif #ifdef USE_MMAP # include # include # include #endif #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) # include # include # ifdef UNDER_CE # include # endif # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) #else # define SET_BINARY_MODE(file) #endif #ifdef _MSC_VER # define snprintf _snprintf #endif #ifdef VMS # define unlink delete # define GZ_SUFFIX "-gz" #endif #ifdef RISCOS # define unlink remove # define GZ_SUFFIX "-gz" # define fileno(file) file->__file #endif #if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os # include /* for fileno */ #endif #if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) #ifndef WIN32 /* unlink already in stdio.h for WIN32 */ extern int unlink OF((const char *)); #endif #endif #if defined(UNDER_CE) # include # define perror(s) pwinerror(s) /* Map the Windows error number in ERROR to a locale-dependent error message string and return a pointer to it. Typically, the values for ERROR come from GetLastError. The string pointed to shall not be modified by the application, but may be overwritten by a subsequent call to strwinerror The strwinerror function does not change the current setting of GetLastError. */ static char *strwinerror (error) DWORD error; { static char buf[1024]; wchar_t *msgbuf; DWORD lasterr = GetLastError(); DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error, 0, /* Default language */ (LPVOID)&msgbuf, 0, NULL); if (chars != 0) { /* If there is an \r\n appended, zap it. */ if (chars >= 2 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { chars -= 2; msgbuf[chars] = 0; } if (chars > sizeof (buf) - 1) { chars = sizeof (buf) - 1; msgbuf[chars] = 0; } wcstombs(buf, msgbuf, chars + 1); LocalFree(msgbuf); } else { sprintf(buf, "unknown win32 error (%ld)", error); } SetLastError(lasterr); return buf; } static void pwinerror (s) const char *s; { if (s && *s) fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); else fprintf(stderr, "%s\n", strwinerror(GetLastError ())); } #endif /* UNDER_CE */ #ifndef GZ_SUFFIX # define GZ_SUFFIX ".gz" #endif #define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) #define BUFLEN 16384 #define MAX_NAME_LEN 1024 #ifdef MAXSEG_64K # define local static /* Needed for systems with limitation on stack size. */ #else # define local #endif #ifdef Z_SOLO /* for Z_SOLO, create simplified gz* functions using deflate and inflate */ #if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE) # include /* for unlink() */ #endif void *myalloc OF((void *, unsigned, unsigned)); void myfree OF((void *, void *)); void *myalloc(q, n, m) void *q; unsigned n, m; { q = Z_NULL; return calloc(n, m); } void myfree(q, p) void *q, *p; { q = Z_NULL; free(p); } typedef struct gzFile_s { FILE *file; int write; int err; char *msg; z_stream strm; } *gzFile; gzFile gzopen OF((const char *, const char *)); gzFile gzdopen OF((int, const char *)); gzFile gz_open OF((const char *, int, const char *)); gzFile gzopen(path, mode) const char *path; const char *mode; { return gz_open(path, -1, mode); } gzFile gzdopen(fd, mode) int fd; const char *mode; { return gz_open(NULL, fd, mode); } gzFile gz_open(path, fd, mode) const char *path; int fd; const char *mode; { gzFile gz; int ret; gz = malloc(sizeof(struct gzFile_s)); if (gz == NULL) return NULL; gz->write = strchr(mode, 'w') != NULL; gz->strm.zalloc = myalloc; gz->strm.zfree = myfree; gz->strm.opaque = Z_NULL; if (gz->write) ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0); else { gz->strm.next_in = 0; gz->strm.avail_in = Z_NULL; ret = inflateInit2(&(gz->strm), 15 + 16); } if (ret != Z_OK) { free(gz); return NULL; } gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") : fopen(path, gz->write ? "wb" : "rb"); if (gz->file == NULL) { gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm)); free(gz); return NULL; } gz->err = 0; gz->msg = ""; return gz; } int gzwrite OF((gzFile, const void *, unsigned)); int gzwrite(gz, buf, len) gzFile gz; const void *buf; unsigned len; { z_stream *strm; unsigned char out[BUFLEN]; if (gz == NULL || !gz->write) return 0; strm = &(gz->strm); strm->next_in = (void *)buf; strm->avail_in = len; do { strm->next_out = out; strm->avail_out = BUFLEN; (void)deflate(strm, Z_NO_FLUSH); fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); } while (strm->avail_out == 0); return len; } int gzread OF((gzFile, void *, unsigned)); int gzread(gz, buf, len) gzFile gz; void *buf; unsigned len; { int ret; unsigned got; unsigned char in[1]; z_stream *strm; if (gz == NULL || gz->write) return 0; if (gz->err) return 0; strm = &(gz->strm); strm->next_out = (void *)buf; strm->avail_out = len; do { got = fread(in, 1, 1, gz->file); if (got == 0) break; strm->next_in = in; strm->avail_in = 1; ret = inflate(strm, Z_NO_FLUSH); if (ret == Z_DATA_ERROR) { gz->err = Z_DATA_ERROR; gz->msg = strm->msg; return 0; } if (ret == Z_STREAM_END) inflateReset(strm); } while (strm->avail_out); return len - strm->avail_out; } int gzclose OF((gzFile)); int gzclose(gz) gzFile gz; { z_stream *strm; unsigned char out[BUFLEN]; if (gz == NULL) return Z_STREAM_ERROR; strm = &(gz->strm); if (gz->write) { strm->next_in = Z_NULL; strm->avail_in = 0; do { strm->next_out = out; strm->avail_out = BUFLEN; (void)deflate(strm, Z_FINISH); fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); } while (strm->avail_out == 0); deflateEnd(strm); } else inflateEnd(strm); fclose(gz->file); free(gz); return Z_OK; } const char *gzerror OF((gzFile, int *)); const char *gzerror(gz, err) gzFile gz; int *err; { *err = gz->err; return gz->msg; } #endif char *prog; void error OF((const char *msg)); void gz_compress OF((FILE *in, gzFile out)); #ifdef USE_MMAP int gz_compress_mmap OF((FILE *in, gzFile out)); #endif void gz_uncompress OF((gzFile in, FILE *out)); void file_compress OF((char *file, char *mode)); void file_uncompress OF((char *file)); int main OF((int argc, char *argv[])); /* =========================================================================== * Display error message and exit */ void error(msg) const char *msg; { fprintf(stderr, "%s: %s\n", prog, msg); exit(1); } /* =========================================================================== * Compress input to output then close both files. */ void gz_compress(in, out) FILE *in; gzFile out; { local char buf[BUFLEN]; int len; int err; #ifdef USE_MMAP /* Try first compressing with mmap. If mmap fails (minigzip used in a * pipe), use the normal fread loop. */ if (gz_compress_mmap(in, out) == Z_OK) return; #endif for (;;) { len = (int)fread(buf, 1, sizeof(buf), in); if (ferror(in)) { perror("fread"); exit(1); } if (len == 0) break; if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); } fclose(in); if (gzclose(out) != Z_OK) error("failed gzclose"); } #ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ /* Try compressing the input file at once using mmap. Return Z_OK if * if success, Z_ERRNO otherwise. */ int gz_compress_mmap(in, out) FILE *in; gzFile out; { int len; int err; int ifd = fileno(in); caddr_t buf; /* mmap'ed buffer for the entire input file */ off_t buf_len; /* length of the input file */ struct stat sb; /* Determine the size of the file, needed for mmap: */ if (fstat(ifd, &sb) < 0) return Z_ERRNO; buf_len = sb.st_size; if (buf_len <= 0) return Z_ERRNO; /* Now do the actual mmap: */ buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); if (buf == (caddr_t)(-1)) return Z_ERRNO; /* Compress the whole file at once: */ len = gzwrite(out, (char *)buf, (unsigned)buf_len); if (len != (int)buf_len) error(gzerror(out, &err)); munmap(buf, buf_len); fclose(in); if (gzclose(out) != Z_OK) error("failed gzclose"); return Z_OK; } #endif /* USE_MMAP */ /* =========================================================================== * Uncompress input to output then close both files. */ void gz_uncompress(in, out) gzFile in; FILE *out; { local char buf[BUFLEN]; int len; int err; for (;;) { len = gzread(in, buf, sizeof(buf)); if (len < 0) error (gzerror(in, &err)); if (len == 0) break; if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { error("failed fwrite"); } } if (fclose(out)) error("failed fclose"); if (gzclose(in) != Z_OK) error("failed gzclose"); } /* =========================================================================== * Compress the given file: create a corresponding .gz file and remove the * original. */ void file_compress(file, mode) char *file; char *mode; { local char outfile[MAX_NAME_LEN]; FILE *in; gzFile out; if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { fprintf(stderr, "%s: filename too long\n", prog); exit(1); } #if !defined(NO_snprintf) && !defined(NO_vsnprintf) snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX); #else strcpy(outfile, file); strcat(outfile, GZ_SUFFIX); #endif in = fopen(file, "rb"); if (in == NULL) { perror(file); exit(1); } out = gzopen(outfile, mode); if (out == NULL) { fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); exit(1); } gz_compress(in, out); unlink(file); } /* =========================================================================== * Uncompress the given file and remove the original. */ void file_uncompress(file) char *file; { local char buf[MAX_NAME_LEN]; char *infile, *outfile; FILE *out; gzFile in; size_t len = strlen(file); if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { fprintf(stderr, "%s: filename too long\n", prog); exit(1); } #if !defined(NO_snprintf) && !defined(NO_vsnprintf) snprintf(buf, sizeof(buf), "%s", file); #else strcpy(buf, file); #endif if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { infile = file; outfile = buf; outfile[len-3] = '\0'; } else { outfile = file; infile = buf; #if !defined(NO_snprintf) && !defined(NO_vsnprintf) snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX); #else strcat(infile, GZ_SUFFIX); #endif } in = gzopen(infile, "rb"); if (in == NULL) { fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); exit(1); } out = fopen(outfile, "wb"); if (out == NULL) { perror(file); exit(1); } gz_uncompress(in, out); unlink(infile); } /* =========================================================================== * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] * -c : write to standard output * -d : decompress * -f : compress with Z_FILTERED * -h : compress with Z_HUFFMAN_ONLY * -r : compress with Z_RLE * -1 to -9 : compression level */ int main(argc, argv) int argc; char *argv[]; { int copyout = 0; int uncompr = 0; gzFile file; char *bname, outmode[20]; #if !defined(NO_snprintf) && !defined(NO_vsnprintf) snprintf(outmode, sizeof(outmode), "%s", "wb6 "); #else strcpy(outmode, "wb6 "); #endif prog = argv[0]; bname = strrchr(argv[0], '/'); if (bname) bname++; else bname = argv[0]; argc--, argv++; if (!strcmp(bname, "gunzip")) uncompr = 1; else if (!strcmp(bname, "zcat")) copyout = uncompr = 1; while (argc > 0) { if (strcmp(*argv, "-c") == 0) copyout = 1; else if (strcmp(*argv, "-d") == 0) uncompr = 1; else if (strcmp(*argv, "-f") == 0) outmode[3] = 'f'; else if (strcmp(*argv, "-h") == 0) outmode[3] = 'h'; else if (strcmp(*argv, "-r") == 0) outmode[3] = 'R'; else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && (*argv)[2] == 0) outmode[2] = (*argv)[1]; else break; argc--, argv++; } if (outmode[3] == ' ') outmode[3] = 0; if (argc == 0) { SET_BINARY_MODE(stdin); SET_BINARY_MODE(stdout); if (uncompr) { file = gzdopen(fileno(stdin), "rb"); if (file == NULL) error("can't gzdopen stdin"); gz_uncompress(file, stdout); } else { file = gzdopen(fileno(stdout), outmode); if (file == NULL) error("can't gzdopen stdout"); gz_compress(stdin, file); } } else { if (copyout) { SET_BINARY_MODE(stdout); } do { if (uncompr) { if (copyout) { file = gzopen(*argv, "rb"); if (file == NULL) fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); else gz_uncompress(file, stdout); } else { file_uncompress(*argv); } } else { if (copyout) { FILE * in = fopen(*argv, "rb"); if (in == NULL) { perror(*argv); } else { file = gzdopen(fileno(stdout), outmode); if (file == NULL) error("can't gzdopen stdout"); gz_compress(in, file); } } else { file_compress(*argv, outmode); } } } while (argv++, --argc); } return 0; } tcl8.6.5/compat/zlib/test/infcover.c0000644000175000017500000006017412663660065016760 0ustar sergeisergei/* infcover.c -- test zlib's inflate routines with full code coverage * Copyright (C) 2011 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* to use, do: ./configure --cover && make cover */ #include #include #include #include #include "zlib.h" /* get definition of internal structure so we can mess with it (see pull()), and so we can call inflate_trees() (see cover5()) */ #define ZLIB_INTERNAL #include "inftrees.h" #include "inflate.h" #define local static /* -- memory tracking routines -- */ /* These memory tracking routines are provided to zlib and track all of zlib's allocations and deallocations, check for LIFO operations, keep a current and high water mark of total bytes requested, optionally set a limit on the total memory that can be allocated, and when done check for memory leaks. They are used as follows: z_stream strm; mem_setup(&strm) initializes the memory tracking and sets the zalloc, zfree, and opaque members of strm to use memory tracking for all zlib operations on strm mem_limit(&strm, limit) sets a limit on the total bytes requested -- a request that exceeds this limit will result in an allocation failure (returns NULL) -- setting the limit to zero means no limit, which is the default after mem_setup() mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used mem_high(&strm, "msg") prints to stderr "msg" and the high water mark mem_done(&strm, "msg") ends memory tracking, releases all allocations for the tracking as well as leaked zlib blocks, if any. If there was anything unusual, such as leaked blocks, non-FIFO frees, or frees of addresses not allocated, then "msg" and information about the problem is printed to stderr. If everything is normal, nothing is printed. mem_done resets the strm members to Z_NULL to use the default memory allocation routines on the next zlib initialization using strm. */ /* these items are strung together in a linked list, one for each allocation */ struct mem_item { void *ptr; /* pointer to allocated memory */ size_t size; /* requested size of allocation */ struct mem_item *next; /* pointer to next item in list, or NULL */ }; /* this structure is at the root of the linked list, and tracks statistics */ struct mem_zone { struct mem_item *first; /* pointer to first item in list, or NULL */ size_t total, highwater; /* total allocations, and largest total */ size_t limit; /* memory allocation limit, or 0 if no limit */ int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */ }; /* memory allocation routine to pass to zlib */ local void *mem_alloc(void *mem, unsigned count, unsigned size) { void *ptr; struct mem_item *item; struct mem_zone *zone = mem; size_t len = count * (size_t)size; /* induced allocation failure */ if (zone == NULL || (zone->limit && zone->total + len > zone->limit)) return NULL; /* perform allocation using the standard library, fill memory with a non-zero value to make sure that the code isn't depending on zeros */ ptr = malloc(len); if (ptr == NULL) return NULL; memset(ptr, 0xa5, len); /* create a new item for the list */ item = malloc(sizeof(struct mem_item)); if (item == NULL) { free(ptr); return NULL; } item->ptr = ptr; item->size = len; /* insert item at the beginning of the list */ item->next = zone->first; zone->first = item; /* update the statistics */ zone->total += item->size; if (zone->total > zone->highwater) zone->highwater = zone->total; /* return the allocated memory */ return ptr; } /* memory free routine to pass to zlib */ local void mem_free(void *mem, void *ptr) { struct mem_item *item, *next; struct mem_zone *zone = mem; /* if no zone, just do a free */ if (zone == NULL) { free(ptr); return; } /* point next to the item that matches ptr, or NULL if not found -- remove the item from the linked list if found */ next = zone->first; if (next) { if (next->ptr == ptr) zone->first = next->next; /* first one is it, remove from list */ else { do { /* search the linked list */ item = next; next = item->next; } while (next != NULL && next->ptr != ptr); if (next) { /* if found, remove from linked list */ item->next = next->next; zone->notlifo++; /* not a LIFO free */ } } } /* if found, update the statistics and free the item */ if (next) { zone->total -= next->size; free(next); } /* if not found, update the rogue count */ else zone->rogue++; /* in any case, do the requested free with the standard library function */ free(ptr); } /* set up a controlled memory allocation space for monitoring, set the stream parameters to the controlled routines, with opaque pointing to the space */ local void mem_setup(z_stream *strm) { struct mem_zone *zone; zone = malloc(sizeof(struct mem_zone)); assert(zone != NULL); zone->first = NULL; zone->total = 0; zone->highwater = 0; zone->limit = 0; zone->notlifo = 0; zone->rogue = 0; strm->opaque = zone; strm->zalloc = mem_alloc; strm->zfree = mem_free; } /* set a limit on the total memory allocation, or 0 to remove the limit */ local void mem_limit(z_stream *strm, size_t limit) { struct mem_zone *zone = strm->opaque; zone->limit = limit; } /* show the current total requested allocations in bytes */ local void mem_used(z_stream *strm, char *prefix) { struct mem_zone *zone = strm->opaque; fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total); } /* show the high water allocation in bytes */ local void mem_high(z_stream *strm, char *prefix) { struct mem_zone *zone = strm->opaque; fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater); } /* release the memory allocation zone -- if there are any surprises, notify */ local void mem_done(z_stream *strm, char *prefix) { int count = 0; struct mem_item *item, *next; struct mem_zone *zone = strm->opaque; /* show high water mark */ mem_high(strm, prefix); /* free leftover allocations and item structures, if any */ item = zone->first; while (item != NULL) { free(item->ptr); next = item->next; free(item); item = next; count++; } /* issue alerts about anything unexpected */ if (count || zone->total) fprintf(stderr, "** %s: %lu bytes in %d blocks not freed\n", prefix, zone->total, count); if (zone->notlifo) fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo); if (zone->rogue) fprintf(stderr, "** %s: %d frees not recognized\n", prefix, zone->rogue); /* free the zone and delete from the stream */ free(zone); strm->opaque = Z_NULL; strm->zalloc = Z_NULL; strm->zfree = Z_NULL; } /* -- inflate test routines -- */ /* Decode a hexadecimal string, set *len to length, in[] to the bytes. This decodes liberally, in that hex digits can be adjacent, in which case two in a row writes a byte. Or they can delimited by any non-hex character, where the delimiters are ignored except when a single hex digit is followed by a delimiter in which case that single digit writes a byte. The returned data is allocated and must eventually be freed. NULL is returned if out of memory. If the length is not needed, then len can be NULL. */ local unsigned char *h2b(const char *hex, unsigned *len) { unsigned char *in; unsigned next, val; in = malloc((strlen(hex) + 1) >> 1); if (in == NULL) return NULL; next = 0; val = 1; do { if (*hex >= '0' && *hex <= '9') val = (val << 4) + *hex - '0'; else if (*hex >= 'A' && *hex <= 'F') val = (val << 4) + *hex - 'A' + 10; else if (*hex >= 'a' && *hex <= 'f') val = (val << 4) + *hex - 'a' + 10; else if (val != 1 && val < 32) /* one digit followed by delimiter */ val += 240; /* make it look like two digits */ if (val > 255) { /* have two digits */ in[next++] = val & 0xff; /* save the decoded byte */ val = 1; /* start over */ } } while (*hex++); /* go through the loop with the terminating null */ if (len != NULL) *len = next; in = reallocf(in, next); return in; } /* generic inflate() run, where hex is the hexadecimal input data, what is the text to include in an error message, step is how much input data to feed inflate() on each call, or zero to feed it all, win is the window bits parameter to inflateInit2(), len is the size of the output buffer, and err is the error code expected from the first inflate() call (the second inflate() call is expected to return Z_STREAM_END). If win is 47, then header information is collected with inflateGetHeader(). If a zlib stream is looking for a dictionary, then an empty dictionary is provided. inflate() is run until all of the input data is consumed. */ local void inf(char *hex, char *what, unsigned step, int win, unsigned len, int err) { int ret; unsigned have; unsigned char *in, *out; z_stream strm, copy; gz_header head; mem_setup(&strm); strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit2(&strm, win); if (ret != Z_OK) { mem_done(&strm, what); return; } out = malloc(len); assert(out != NULL); if (win == 47) { head.extra = out; head.extra_max = len; head.name = out; head.name_max = len; head.comment = out; head.comm_max = len; ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK); } in = h2b(hex, &have); assert(in != NULL); if (step == 0 || step > have) step = have; strm.avail_in = step; have -= step; strm.next_in = in; do { strm.avail_out = len; strm.next_out = out; ret = inflate(&strm, Z_NO_FLUSH); assert(err == 9 || ret == err); if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT) break; if (ret == Z_NEED_DICT) { ret = inflateSetDictionary(&strm, in, 1); assert(ret == Z_DATA_ERROR); mem_limit(&strm, 1); ret = inflateSetDictionary(&strm, out, 0); assert(ret == Z_MEM_ERROR); mem_limit(&strm, 0); ((struct inflate_state *)strm.state)->mode = DICT; ret = inflateSetDictionary(&strm, out, 0); assert(ret == Z_OK); ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR); } ret = inflateCopy(©, &strm); assert(ret == Z_OK); ret = inflateEnd(©); assert(ret == Z_OK); err = 9; /* don't care next time around */ have += strm.avail_in; strm.avail_in = step > have ? have : step; have -= strm.avail_in; } while (strm.avail_in); free(in); free(out); ret = inflateReset2(&strm, -8); assert(ret == Z_OK); ret = inflateEnd(&strm); assert(ret == Z_OK); mem_done(&strm, what); } /* cover all of the lines in inflate.c up to inflate() */ local void cover_support(void) { int ret; z_stream strm; mem_setup(&strm); strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit(&strm); assert(ret == Z_OK); mem_used(&strm, "inflate init"); ret = inflatePrime(&strm, 5, 31); assert(ret == Z_OK); ret = inflatePrime(&strm, -1, 0); assert(ret == Z_OK); ret = inflateSetDictionary(&strm, Z_NULL, 0); assert(ret == Z_STREAM_ERROR); ret = inflateEnd(&strm); assert(ret == Z_OK); mem_done(&strm, "prime"); inf("63 0", "force window allocation", 0, -15, 1, Z_OK); inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK); inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK); inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END); inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); mem_setup(&strm); strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream)); assert(ret == Z_VERSION_ERROR); mem_done(&strm, "wrong version"); strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit(&strm); assert(ret == Z_OK); ret = inflateEnd(&strm); assert(ret == Z_OK); fputs("inflate built-in memory routines\n", stderr); } /* cover all inflate() header and trailer cases and code after inflate() */ local void cover_wrap(void) { int ret; z_stream strm, copy; unsigned char dict[257]; ret = inflate(Z_NULL, 0); assert(ret == Z_STREAM_ERROR); ret = inflateEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); ret = inflateCopy(Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR); fputs("inflate bad parameters\n", stderr); inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR); inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR); inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR); inf("8 99", "set window size from header", 0, 0, 0, Z_OK); inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR); inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END); inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, Z_DATA_ERROR); inf("1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length", 0, 47, 0, Z_STREAM_END); inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR); inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT); inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK); mem_setup(&strm); strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit2(&strm, -8); strm.avail_in = 2; strm.next_in = (void *)"\x63"; strm.avail_out = 1; strm.next_out = (void *)&ret; mem_limit(&strm, 1); ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); mem_limit(&strm, 0); memset(dict, 0, 257); ret = inflateSetDictionary(&strm, dict, 257); assert(ret == Z_OK); mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256); ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK); strm.avail_in = 2; strm.next_in = (void *)"\x80"; ret = inflateSync(&strm); assert(ret == Z_DATA_ERROR); ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR); strm.avail_in = 4; strm.next_in = (void *)"\0\0\xff\xff"; ret = inflateSync(&strm); assert(ret == Z_OK); (void)inflateSyncPoint(&strm); ret = inflateCopy(©, &strm); assert(ret == Z_MEM_ERROR); mem_limit(&strm, 0); ret = inflateUndermine(&strm, 1); assert(ret == Z_DATA_ERROR); (void)inflateMark(&strm); ret = inflateEnd(&strm); assert(ret == Z_OK); mem_done(&strm, "miscellaneous, force memory errors"); } /* input and output functions for inflateBack() */ local unsigned pull(void *desc, unsigned char **buf) { static unsigned int next = 0; static unsigned char dat[] = {0x63, 0, 2, 0}; struct inflate_state *state; if (desc == Z_NULL) { next = 0; return 0; /* no input (already provided at next_in) */ } state = (void *)((z_stream *)desc)->state; if (state != Z_NULL) state->mode = SYNC; /* force an otherwise impossible situation */ return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0; } local int push(void *desc, unsigned char *buf, unsigned len) { buf += len; return desc != Z_NULL; /* force error if desc not null */ } /* cover inflateBack() up to common deflate data cases and after those */ local void cover_back(void) { int ret; z_stream strm; unsigned char win[32768]; ret = inflateBackInit_(Z_NULL, 0, win, 0, 0); assert(ret == Z_VERSION_ERROR); ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR); ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR); ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); fputs("inflateBack bad parameters\n", stderr); mem_setup(&strm); ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); strm.avail_in = 2; strm.next_in = (void *)"\x03"; ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); assert(ret == Z_STREAM_END); /* force output error */ strm.avail_in = 3; strm.next_in = (void *)"\x63\x00"; ret = inflateBack(&strm, pull, Z_NULL, push, &strm); assert(ret == Z_BUF_ERROR); /* force mode error by mucking with state */ ret = inflateBack(&strm, pull, &strm, push, Z_NULL); assert(ret == Z_STREAM_ERROR); ret = inflateBackEnd(&strm); assert(ret == Z_OK); mem_done(&strm, "inflateBack bad state"); ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); ret = inflateBackEnd(&strm); assert(ret == Z_OK); fputs("inflateBack built-in memory routines\n", stderr); } /* do a raw inflate of data in hexadecimal with both inflate and inflateBack */ local int try(char *hex, char *id, int err) { int ret; unsigned len, size; unsigned char *in, *out, *win; char *prefix; z_stream strm; /* convert to hex */ in = h2b(hex, &len); assert(in != NULL); /* allocate work areas */ size = len << 3; out = malloc(size); assert(out != NULL); win = malloc(32768); assert(win != NULL); prefix = malloc(strlen(id) + 6); assert(prefix != NULL); /* first with inflate */ strcpy(prefix, id); strcat(prefix, "-late"); mem_setup(&strm); strm.avail_in = 0; strm.next_in = Z_NULL; ret = inflateInit2(&strm, err < 0 ? 47 : -15); assert(ret == Z_OK); strm.avail_in = len; strm.next_in = in; do { strm.avail_out = size; strm.next_out = out; ret = inflate(&strm, Z_TREES); assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR); if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT) break; } while (strm.avail_in || strm.avail_out == 0); if (err) { assert(ret == Z_DATA_ERROR); assert(strcmp(id, strm.msg) == 0); } inflateEnd(&strm); mem_done(&strm, prefix); /* then with inflateBack */ if (err >= 0) { strcpy(prefix, id); strcat(prefix, "-back"); mem_setup(&strm); ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); strm.avail_in = len; strm.next_in = in; ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); assert(ret != Z_STREAM_ERROR); if (err) { assert(ret == Z_DATA_ERROR); assert(strcmp(id, strm.msg) == 0); } inflateBackEnd(&strm); mem_done(&strm, prefix); } /* clean up */ free(prefix); free(win); free(out); free(in); return ret; } /* cover deflate data cases in both inflate() and inflateBack() */ local void cover_inflate(void) { try("0 0 0 0 0", "invalid stored block lengths", 1); try("3 0", "fixed", 0); try("6", "invalid block type", 1); try("1 1 0 fe ff 0", "stored", 0); try("fc 0 0", "too many length or distance symbols", 1); try("4 0 fe ff", "invalid code lengths set", 1); try("4 0 24 49 0", "invalid bit length repeat", 1); try("4 0 24 e9 ff ff", "invalid bit length repeat", 1); try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1); try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0", "invalid literal/lengths set", 1); try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1); try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1); try("2 7e ff ff", "invalid distance code", 1); try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1); /* also trailer mismatch just in inflate() */ try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1); try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", "incorrect length check", -1); try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0); try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", "long code", 0); try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0); try("ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c", "long distance and extra", 0); try("ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 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 0 0 0 6", "window end", 0); inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, Z_STREAM_END); inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK); } /* cover remaining lines in inftrees.c */ local void cover_trees(void) { int ret; unsigned bits; unsigned short lens[16], work[16]; code *next, table[ENOUGH_DISTS]; /* we need to call inflate_table() directly in order to manifest not- enough errors, since zlib insures that enough is always enough */ for (bits = 0; bits < 15; bits++) lens[bits] = (unsigned short)(bits + 1); lens[15] = 15; next = table; bits = 15; ret = inflate_table(DISTS, lens, 16, &next, &bits, work); assert(ret == 1); next = table; bits = 1; ret = inflate_table(DISTS, lens, 16, &next, &bits, work); assert(ret == 1); fputs("inflate_table not enough errors\n", stderr); } /* cover remaining inffast.c decoding and window copying */ local void cover_fast(void) { inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68" " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR); inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49" " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, Z_DATA_ERROR); inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, Z_DATA_ERROR); inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, Z_DATA_ERROR); inf("d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0", "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR); inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK); inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", "contiguous and wrap around window", 6, -8, 259, Z_OK); inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, Z_STREAM_END); } int main(void) { fprintf(stderr, "%s\n", zlibVersion()); cover_support(); cover_wrap(); cover_back(); cover_inflate(); cover_trees(); cover_fast(); return 0; } tcl8.6.5/compat/zlib/test/example.c0000644000175000017500000004072712663660065016602 0ustar sergeisergei/* example.c -- usage example of the zlib compression library * Copyright (C) 1995-2006, 2011 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zlib.h" #include #ifdef STDC # include # include #endif #if defined(VMS) || defined(RISCOS) # define TESTFILE "foo-gz" #else # define TESTFILE "foo.gz" #endif #define CHECK_ERR(err, msg) { \ if (err != Z_OK) { \ fprintf(stderr, "%s error: %d\n", msg, err); \ exit(1); \ } \ } z_const char hello[] = "hello, hello!"; /* "hello world" would be more standard, but the repeated "hello" * stresses the compression code better, sorry... */ const char dictionary[] = "hello"; uLong dictId; /* Adler32 value of the dictionary */ void test_deflate OF((Byte *compr, uLong comprLen)); void test_inflate OF((Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)); void test_large_deflate OF((Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)); void test_large_inflate OF((Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)); void test_flush OF((Byte *compr, uLong *comprLen)); void test_sync OF((Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)); void test_dict_deflate OF((Byte *compr, uLong comprLen)); void test_dict_inflate OF((Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)); int main OF((int argc, char *argv[])); #ifdef Z_SOLO void *myalloc OF((void *, unsigned, unsigned)); void myfree OF((void *, void *)); void *myalloc(q, n, m) void *q; unsigned n, m; { q = Z_NULL; return calloc(n, m); } void myfree(void *q, void *p) { q = Z_NULL; free(p); } static alloc_func zalloc = myalloc; static free_func zfree = myfree; #else /* !Z_SOLO */ static alloc_func zalloc = (alloc_func)0; static free_func zfree = (free_func)0; void test_compress OF((Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)); void test_gzio OF((const char *fname, Byte *uncompr, uLong uncomprLen)); /* =========================================================================== * Test compress() and uncompress() */ void test_compress(compr, comprLen, uncompr, uncomprLen) Byte *compr, *uncompr; uLong comprLen, uncomprLen; { int err; uLong len = (uLong)strlen(hello)+1; err = compress(compr, &comprLen, (const Bytef*)hello, len); CHECK_ERR(err, "compress"); strcpy((char*)uncompr, "garbage"); err = uncompress(uncompr, &uncomprLen, compr, comprLen); CHECK_ERR(err, "uncompress"); if (strcmp((char*)uncompr, hello)) { fprintf(stderr, "bad uncompress\n"); exit(1); } else { printf("uncompress(): %s\n", (char *)uncompr); } } /* =========================================================================== * Test read/write of .gz files */ void test_gzio(fname, uncompr, uncomprLen) const char *fname; /* compressed file name */ Byte *uncompr; uLong uncomprLen; { #ifdef NO_GZCOMPRESS fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); #else int err; int len = (int)strlen(hello)+1; gzFile file; z_off_t pos; file = gzopen(fname, "wb"); if (file == NULL) { fprintf(stderr, "gzopen error\n"); exit(1); } gzputc(file, 'h'); if (gzputs(file, "ello") != 4) { fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); exit(1); } if (gzprintf(file, ", %s!", "hello") != 8) { fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); exit(1); } gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ gzclose(file); file = gzopen(fname, "rb"); if (file == NULL) { fprintf(stderr, "gzopen error\n"); exit(1); } strcpy((char*)uncompr, "garbage"); if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); exit(1); } if (strcmp((char*)uncompr, hello)) { fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); exit(1); } else { printf("gzread(): %s\n", (char*)uncompr); } pos = gzseek(file, -8L, SEEK_CUR); if (pos != 6 || gztell(file) != pos) { fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", (long)pos, (long)gztell(file)); exit(1); } if (gzgetc(file) != ' ') { fprintf(stderr, "gzgetc error\n"); exit(1); } if (gzungetc(' ', file) != ' ') { fprintf(stderr, "gzungetc error\n"); exit(1); } gzgets(file, (char*)uncompr, (int)uncomprLen); if (strlen((char*)uncompr) != 7) { /* " hello!" */ fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); exit(1); } if (strcmp((char*)uncompr, hello + 6)) { fprintf(stderr, "bad gzgets after gzseek\n"); exit(1); } else { printf("gzgets() after gzseek: %s\n", (char*)uncompr); } gzclose(file); #endif } #endif /* Z_SOLO */ /* =========================================================================== * Test deflate() with small buffers */ void test_deflate(compr, comprLen) Byte *compr; uLong comprLen; { z_stream c_stream; /* compression stream */ int err; uLong len = (uLong)strlen(hello)+1; c_stream.zalloc = zalloc; c_stream.zfree = zfree; c_stream.opaque = (voidpf)0; err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); CHECK_ERR(err, "deflateInit"); c_stream.next_in = (z_const unsigned char *)hello; c_stream.next_out = compr; while (c_stream.total_in != len && c_stream.total_out < comprLen) { c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ err = deflate(&c_stream, Z_NO_FLUSH); CHECK_ERR(err, "deflate"); } /* Finish the stream, still forcing small buffers: */ for (;;) { c_stream.avail_out = 1; err = deflate(&c_stream, Z_FINISH); if (err == Z_STREAM_END) break; CHECK_ERR(err, "deflate"); } err = deflateEnd(&c_stream); CHECK_ERR(err, "deflateEnd"); } /* =========================================================================== * Test inflate() with small buffers */ void test_inflate(compr, comprLen, uncompr, uncomprLen) Byte *compr, *uncompr; uLong comprLen, uncomprLen; { int err; z_stream d_stream; /* decompression stream */ strcpy((char*)uncompr, "garbage"); d_stream.zalloc = zalloc; d_stream.zfree = zfree; d_stream.opaque = (voidpf)0; d_stream.next_in = compr; d_stream.avail_in = 0; d_stream.next_out = uncompr; err = inflateInit(&d_stream); CHECK_ERR(err, "inflateInit"); while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ err = inflate(&d_stream, Z_NO_FLUSH); if (err == Z_STREAM_END) break; CHECK_ERR(err, "inflate"); } err = inflateEnd(&d_stream); CHECK_ERR(err, "inflateEnd"); if (strcmp((char*)uncompr, hello)) { fprintf(stderr, "bad inflate\n"); exit(1); } else { printf("inflate(): %s\n", (char *)uncompr); } } /* =========================================================================== * Test deflate() with large buffers and dynamic change of compression level */ void test_large_deflate(compr, comprLen, uncompr, uncomprLen) Byte *compr, *uncompr; uLong comprLen, uncomprLen; { z_stream c_stream; /* compression stream */ int err; c_stream.zalloc = zalloc; c_stream.zfree = zfree; c_stream.opaque = (voidpf)0; err = deflateInit(&c_stream, Z_BEST_SPEED); CHECK_ERR(err, "deflateInit"); c_stream.next_out = compr; c_stream.avail_out = (uInt)comprLen; /* At this point, uncompr is still mostly zeroes, so it should compress * very well: */ c_stream.next_in = uncompr; c_stream.avail_in = (uInt)uncomprLen; err = deflate(&c_stream, Z_NO_FLUSH); CHECK_ERR(err, "deflate"); if (c_stream.avail_in != 0) { fprintf(stderr, "deflate not greedy\n"); exit(1); } /* Feed in already compressed data and switch to no compression: */ deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); c_stream.next_in = compr; c_stream.avail_in = (uInt)comprLen/2; err = deflate(&c_stream, Z_NO_FLUSH); CHECK_ERR(err, "deflate"); /* Switch back to compressing mode: */ deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); c_stream.next_in = uncompr; c_stream.avail_in = (uInt)uncomprLen; err = deflate(&c_stream, Z_NO_FLUSH); CHECK_ERR(err, "deflate"); err = deflate(&c_stream, Z_FINISH); if (err != Z_STREAM_END) { fprintf(stderr, "deflate should report Z_STREAM_END\n"); exit(1); } err = deflateEnd(&c_stream); CHECK_ERR(err, "deflateEnd"); } /* =========================================================================== * Test inflate() with large buffers */ void test_large_inflate(compr, comprLen, uncompr, uncomprLen) Byte *compr, *uncompr; uLong comprLen, uncomprLen; { int err; z_stream d_stream; /* decompression stream */ strcpy((char*)uncompr, "garbage"); d_stream.zalloc = zalloc; d_stream.zfree = zfree; d_stream.opaque = (voidpf)0; d_stream.next_in = compr; d_stream.avail_in = (uInt)comprLen; err = inflateInit(&d_stream); CHECK_ERR(err, "inflateInit"); for (;;) { d_stream.next_out = uncompr; /* discard the output */ d_stream.avail_out = (uInt)uncomprLen; err = inflate(&d_stream, Z_NO_FLUSH); if (err == Z_STREAM_END) break; CHECK_ERR(err, "large inflate"); } err = inflateEnd(&d_stream); CHECK_ERR(err, "inflateEnd"); if (d_stream.total_out != 2*uncomprLen + comprLen/2) { fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); exit(1); } else { printf("large_inflate(): OK\n"); } } /* =========================================================================== * Test deflate() with full flush */ void test_flush(compr, comprLen) Byte *compr; uLong *comprLen; { z_stream c_stream; /* compression stream */ int err; uInt len = (uInt)strlen(hello)+1; c_stream.zalloc = zalloc; c_stream.zfree = zfree; c_stream.opaque = (voidpf)0; err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); CHECK_ERR(err, "deflateInit"); c_stream.next_in = (z_const unsigned char *)hello; c_stream.next_out = compr; c_stream.avail_in = 3; c_stream.avail_out = (uInt)*comprLen; err = deflate(&c_stream, Z_FULL_FLUSH); CHECK_ERR(err, "deflate"); compr[3]++; /* force an error in first compressed block */ c_stream.avail_in = len - 3; err = deflate(&c_stream, Z_FINISH); if (err != Z_STREAM_END) { CHECK_ERR(err, "deflate"); } err = deflateEnd(&c_stream); CHECK_ERR(err, "deflateEnd"); *comprLen = c_stream.total_out; } /* =========================================================================== * Test inflateSync() */ void test_sync(compr, comprLen, uncompr, uncomprLen) Byte *compr, *uncompr; uLong comprLen, uncomprLen; { int err; z_stream d_stream; /* decompression stream */ strcpy((char*)uncompr, "garbage"); d_stream.zalloc = zalloc; d_stream.zfree = zfree; d_stream.opaque = (voidpf)0; d_stream.next_in = compr; d_stream.avail_in = 2; /* just read the zlib header */ err = inflateInit(&d_stream); CHECK_ERR(err, "inflateInit"); d_stream.next_out = uncompr; d_stream.avail_out = (uInt)uncomprLen; inflate(&d_stream, Z_NO_FLUSH); CHECK_ERR(err, "inflate"); d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ err = inflateSync(&d_stream); /* but skip the damaged part */ CHECK_ERR(err, "inflateSync"); err = inflate(&d_stream, Z_FINISH); if (err != Z_DATA_ERROR) { fprintf(stderr, "inflate should report DATA_ERROR\n"); /* Because of incorrect adler32 */ exit(1); } err = inflateEnd(&d_stream); CHECK_ERR(err, "inflateEnd"); printf("after inflateSync(): hel%s\n", (char *)uncompr); } /* =========================================================================== * Test deflate() with preset dictionary */ void test_dict_deflate(compr, comprLen) Byte *compr; uLong comprLen; { z_stream c_stream; /* compression stream */ int err; c_stream.zalloc = zalloc; c_stream.zfree = zfree; c_stream.opaque = (voidpf)0; err = deflateInit(&c_stream, Z_BEST_COMPRESSION); CHECK_ERR(err, "deflateInit"); err = deflateSetDictionary(&c_stream, (const Bytef*)dictionary, (int)sizeof(dictionary)); CHECK_ERR(err, "deflateSetDictionary"); dictId = c_stream.adler; c_stream.next_out = compr; c_stream.avail_out = (uInt)comprLen; c_stream.next_in = (z_const unsigned char *)hello; c_stream.avail_in = (uInt)strlen(hello)+1; err = deflate(&c_stream, Z_FINISH); if (err != Z_STREAM_END) { fprintf(stderr, "deflate should report Z_STREAM_END\n"); exit(1); } err = deflateEnd(&c_stream); CHECK_ERR(err, "deflateEnd"); } /* =========================================================================== * Test inflate() with a preset dictionary */ void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) Byte *compr, *uncompr; uLong comprLen, uncomprLen; { int err; z_stream d_stream; /* decompression stream */ strcpy((char*)uncompr, "garbage"); d_stream.zalloc = zalloc; d_stream.zfree = zfree; d_stream.opaque = (voidpf)0; d_stream.next_in = compr; d_stream.avail_in = (uInt)comprLen; err = inflateInit(&d_stream); CHECK_ERR(err, "inflateInit"); d_stream.next_out = uncompr; d_stream.avail_out = (uInt)uncomprLen; for (;;) { err = inflate(&d_stream, Z_NO_FLUSH); if (err == Z_STREAM_END) break; if (err == Z_NEED_DICT) { if (d_stream.adler != dictId) { fprintf(stderr, "unexpected dictionary"); exit(1); } err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, (int)sizeof(dictionary)); } CHECK_ERR(err, "inflate with dict"); } err = inflateEnd(&d_stream); CHECK_ERR(err, "inflateEnd"); if (strcmp((char*)uncompr, hello)) { fprintf(stderr, "bad inflate with dict\n"); exit(1); } else { printf("inflate with dictionary: %s\n", (char *)uncompr); } } /* =========================================================================== * Usage: example [output.gz [input.gz]] */ int main(argc, argv) int argc; char *argv[]; { Byte *compr, *uncompr; uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ uLong uncomprLen = comprLen; static const char* myVersion = ZLIB_VERSION; if (zlibVersion()[0] != myVersion[0]) { fprintf(stderr, "incompatible zlib version\n"); exit(1); } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { fprintf(stderr, "warning: different zlib version\n"); } printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); compr = (Byte*)calloc((uInt)comprLen, 1); uncompr = (Byte*)calloc((uInt)uncomprLen, 1); /* compr and uncompr are cleared to avoid reading uninitialized * data and to ensure that uncompr compresses well. */ if (compr == Z_NULL || uncompr == Z_NULL) { printf("out of memory\n"); exit(1); } #ifdef Z_SOLO argc = strlen(argv[0]); #else test_compress(compr, comprLen, uncompr, uncomprLen); test_gzio((argc > 1 ? argv[1] : TESTFILE), uncompr, uncomprLen); #endif test_deflate(compr, comprLen); test_inflate(compr, comprLen, uncompr, uncomprLen); test_large_deflate(compr, comprLen, uncompr, uncomprLen); test_large_inflate(compr, comprLen, uncompr, uncomprLen); test_flush(compr, &comprLen); test_sync(compr, comprLen, uncompr, uncomprLen); comprLen = uncomprLen; test_dict_deflate(compr, comprLen); test_dict_inflate(compr, comprLen, uncompr, uncomprLen); free(compr); free(uncompr); return 0; } tcl8.6.5/compat/zlib/inffixed.h0000644000175000017500000001427412663660065015767 0ustar sergeisergei /* inffixed.h -- table for decoding fixed codes * Generated automatically by makefixed(). */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of this library and is subject to change. Applications should only use zlib.h. */ static const code lenfix[512] = { {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, {0,9,255} }; static const code distfix[32] = { {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, {22,5,193},{64,5,0} }; tcl8.6.5/compat/zlib/gzguts.h0000644000175000017500000001463012663660065015512 0ustar sergeisergei/* gzguts.h -- zlib internal header definitions for gz* operations * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #ifdef _LARGEFILE64_SOURCE # ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE 1 # endif # ifdef _FILE_OFFSET_BITS # undef _FILE_OFFSET_BITS # endif #endif #ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL #endif #include #include "zlib.h" #ifdef STDC # include # include # include #endif #include #ifdef _WIN32 # include #endif #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) # include #endif #ifdef WINAPI_FAMILY # define open _open # define read _read # define write _write # define close _close #endif #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif #if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #if defined(__CYGWIN__) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #ifndef HAVE_VSNPRINTF # ifdef MSDOS /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), but for now we just assume it doesn't. */ # define NO_vsnprintf # endif # ifdef __TURBOC__ # define NO_vsnprintf # endif # ifdef WIN32 /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ # if !defined(vsnprintf) && !defined(NO_vsnprintf) # if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) # define vsnprintf _vsnprintf # endif # endif # endif # ifdef __SASC # define NO_vsnprintf # endif # ifdef VMS # define NO_vsnprintf # endif # ifdef __OS400__ # define NO_vsnprintf # endif # ifdef __MVS__ # define NO_vsnprintf # endif #endif /* unlike snprintf (which is required in C99, yet still not supported by Microsoft more than a decade later!), _snprintf does not guarantee null termination of the result -- however this is only used in gzlib.c where the result is assured to fit in the space provided */ #ifdef _MSC_VER # define snprintf _snprintf #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ /* gz* functions always use library allocation functions */ #ifndef STDC extern voidp malloc OF((uInt size)); extern void free OF((voidpf ptr)); #endif /* get errno and strerror definition */ #if defined UNDER_CE # include # define zstrerror() gz_strwinerror((DWORD)GetLastError()) #else # ifndef NO_STRERROR # include # define zstrerror() strerror(errno) # else # define zstrerror() "stdio error (consult errno)" # endif #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); #endif /* default memLevel */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default i/o buffer size -- double this for output when reading (this and twice this must be able to fit in an unsigned type) */ #define GZBUFSIZE 8192 /* gzip modes, also provide a little integrity check on the passed structure */ #define GZ_NONE 0 #define GZ_READ 7247 #define GZ_WRITE 31153 #define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ /* values for gz_state how */ #define LOOK 0 /* look for a gzip header */ #define COPY 1 /* copy input directly */ #define GZIP 2 /* decompress a gzip stream */ /* internal gzip file state data structure */ typedef struct { /* exposed contents for gzgetc() macro */ struct gzFile_s x; /* "x" for exposed */ /* x.have: number of bytes available at x.next */ /* x.next: next output data to deliver or write */ /* x.pos: current position in uncompressed data */ /* used for both reading and writing */ int mode; /* see gzip modes above */ int fd; /* file descriptor */ char *path; /* path or fd for error messages */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ unsigned char *in; /* input buffer */ unsigned char *out; /* output buffer (double-sized when reading) */ int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ int how; /* 0: get header, 1: copy, 2: decompress */ z_off64_t start; /* where the gzip data started, for rewinding */ int eof; /* true if end of input file reached */ int past; /* true if read requested past end */ /* just for writing */ int level; /* compression level */ int strategy; /* compression strategy */ /* seek request */ z_off64_t skip; /* amount to skip (already rewound if backwards) */ int seek; /* true if seek request pending */ /* error information */ int err; /* error code */ char *msg; /* error message */ /* zlib inflate or deflate stream */ z_stream strm; /* stream structure in-place (not a pointer) */ } gz_state; typedef gz_state FAR *gz_statep; /* shared functions */ void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); #if defined UNDER_CE char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); #endif /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t value -- needed when comparing unsigned to z_off64_t, which is signed (possible z_off64_t types off_t, off64_t, and long are all signed) */ #ifdef INT_MAX # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) #else unsigned ZLIB_INTERNAL gz_intmax OF((void)); # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) #endif tcl8.6.5/compat/zlib/inffast.h0000644000175000017500000000065312663653206015620 0ustar sergeisergei/* inffast.h -- header to use inffast.c * Copyright (C) 1995-2003, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); tcl8.6.5/compat/zlib/zlib.30000644000175000017500000001021412663660065015034 0ustar sergeisergei.TH ZLIB 3 "28 Apr 2013" .SH NAME zlib \- compression/decompression library .SH SYNOPSIS [see .I zlib.h for full description] .SH DESCRIPTION The .I zlib library is a general purpose data compression library. The code is thread safe, assuming that the standard library functions used are thread safe, such as memory allocation routines. It provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms may be added later with the same stream interface. .LP Compression can be done in a single step if the buffers are large enough or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. .LP The library also supports reading and writing files in .IR gzip (1) (.gz) format with an interface similar to that of stdio. .LP The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in the case of corrupted input. .LP All functions of the compression library are documented in the file .IR zlib.h . The distribution source includes examples of use of the library in the files .I test/example.c and .IR test/minigzip.c, as well as other examples in the .IR examples/ directory. .LP Changes to this version are documented in the file .I ChangeLog that accompanies the source. .LP .I zlib is available in Java using the java.util.zip package: .IP http://java.sun.com/developer/technicalArticles/Programming/compression/ .LP A Perl interface to .IR zlib , written by Paul Marquess (pmqs@cpan.org), is available at CPAN (Comprehensive Perl Archive Network) sites, including: .IP http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .LP A Python interface to .IR zlib , written by A.M. Kuchling (amk@magnet.com), is available in Python 1.5 and later versions: .IP http://docs.python.org/library/zlib.html .LP .I zlib is built into .IR tcl: .IP http://wiki.tcl.tk/4610 .LP An experimental package to read and write files in .zip format, written on top of .I zlib by Gilles Vollant (info@winimage.com), is available at: .IP http://www.winimage.com/zLibDll/minizip.html and also in the .I contrib/minizip directory of the main .I zlib source distribution. .SH "SEE ALSO" The .I zlib web site can be found at: .IP http://zlib.net/ .LP The data format used by the zlib library is described by RFC (Request for Comments) 1950 to 1952 in the files: .IP http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format) .br http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format) .br http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format) .LP Mark Nelson wrote an article about .I zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at: .IP http://marknelson.us/1997/01/01/zlib-engine/ .SH "REPORTING PROBLEMS" Before reporting a problem, please check the .I zlib web site to verify that you have the latest version of .IR zlib ; otherwise, obtain the latest version and see if the problem still exists. Please read the .I zlib FAQ at: .IP http://zlib.net/zlib_faq.html .LP before asking for help. Send questions and/or comments to zlib@gzip.org, or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). .SH AUTHORS Version 1.2.8 Copyright (C) 1995-2013 Jean-loup Gailly (jloup@gzip.org) and Mark Adler (madler@alumni.caltech.edu). .LP This software is provided "as-is," without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. See the distribution directory with respect to requirements governing redistribution. The deflate format used by .I zlib was defined by Phil Katz. The deflate and .I zlib specifications were written by L. Peter Deutsch. Thanks to all the people who reported problems and suggested various improvements in .IR zlib ; who are too numerous to cite here. .LP UNIX manual page by R. P. C. Rodgers, U.S. National Library of Medicine (rodgers@nlm.nih.gov). .\" end of man page tcl8.6.5/compat/zlib/zlib.map0000644000175000017500000000225012663660065015450 0ustar sergeisergeiZLIB_1.2.0 { global: compressBound; deflateBound; inflateBack; inflateBackEnd; inflateBackInit_; inflateCopy; local: deflate_copyright; inflate_copyright; inflate_fast; inflate_table; zcalloc; zcfree; z_errmsg; gz_error; gz_intmax; _*; }; ZLIB_1.2.0.2 { gzclearerr; gzungetc; zlibCompileFlags; } ZLIB_1.2.0; ZLIB_1.2.0.8 { deflatePrime; } ZLIB_1.2.0.2; ZLIB_1.2.2 { adler32_combine; crc32_combine; deflateSetHeader; inflateGetHeader; } ZLIB_1.2.0.8; ZLIB_1.2.2.3 { deflateTune; gzdirect; } ZLIB_1.2.2; ZLIB_1.2.2.4 { inflatePrime; } ZLIB_1.2.2.3; ZLIB_1.2.3.3 { adler32_combine64; crc32_combine64; gzopen64; gzseek64; gztell64; inflateUndermine; } ZLIB_1.2.2.4; ZLIB_1.2.3.4 { inflateReset2; inflateMark; } ZLIB_1.2.3.3; ZLIB_1.2.3.5 { gzbuffer; gzoffset; gzoffset64; gzclose_r; gzclose_w; } ZLIB_1.2.3.4; ZLIB_1.2.5.1 { deflatePending; } ZLIB_1.2.3.5; ZLIB_1.2.5.2 { deflateResetKeep; gzgetc_; inflateResetKeep; } ZLIB_1.2.5.1; ZLIB_1.2.7.1 { inflateGetDictionary; gzvprintf; } ZLIB_1.2.5.2; tcl8.6.5/compat/zlib/Makefile0000644000175000017500000000014412663653206015450 0ustar sergeisergeiall: -@echo "Please use ./configure first. Thank you." distclean: make -f Makefile.in distclean tcl8.6.5/compat/zlib/old/0000755000175000017500000000000012665173607014573 5ustar sergeisergeitcl8.6.5/compat/zlib/old/os2/0000755000175000017500000000000012665173607015276 5ustar sergeisergeitcl8.6.5/compat/zlib/old/os2/Makefile.os20000644000175000017500000001001012663653131017421 0ustar sergeisergei# Makefile for zlib under OS/2 using GCC (PGCC) # For conditions of distribution and use, see copyright notice in zlib.h # To compile and test, type: # cp Makefile.os2 .. # cd .. # make -f Makefile.os2 test # This makefile will build a static library z.lib, a shared library # z.dll and a import library zdll.lib. You can use either z.lib or # zdll.lib by specifying either -lz or -lzdll on gcc's command line CC=gcc -Zomf -s CFLAGS=-O6 -Wall #CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 #CFLAGS=-g -DDEBUG #CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ # -Wstrict-prototypes -Wmissing-prototypes #################### BUG WARNING: ##################### ## infcodes.c hits a bug in pgcc-1.0, so you have to use either ## -O# where # <= 4 or one of (-fno-ommit-frame-pointer or -fno-force-mem) ## This bug is reportedly fixed in pgcc >1.0, but this was not tested CFLAGS+=-fno-force-mem LDFLAGS=-s -L. -lzdll -Zcrtdll LDSHARED=$(CC) -s -Zomf -Zdll -Zcrtdll VER=1.1.0 ZLIB=z.lib SHAREDLIB=z.dll SHAREDLIBIMP=zdll.lib LIBS=$(ZLIB) $(SHAREDLIB) $(SHAREDLIBIMP) AR=emxomfar cr IMPLIB=emximp RANLIB=echo TAR=tar SHELL=bash prefix=/usr/local exec_prefix = $(prefix) OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o TEST_OBJS = example.o minigzip.o DISTFILES = README INDEX ChangeLog configure Make*[a-z0-9] *.[ch] descrip.mms \ algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ nt/Makefile.nt nt/zlib.dnt contrib/README.contrib contrib/*.txt \ contrib/asm386/*.asm contrib/asm386/*.c \ contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/iostream/*.cpp \ contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 all: example.exe minigzip.exe test: all @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ echo hello world | ./minigzip | ./minigzip -d || \ echo ' *** minigzip test FAILED ***' ; \ if ./example; then \ echo ' *** zlib test OK ***'; \ else \ echo ' *** zlib test FAILED ***'; \ fi $(ZLIB): $(OBJS) $(AR) $@ $(OBJS) -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 $(SHAREDLIB): $(OBJS) os2/z.def $(LDSHARED) -o $@ $^ $(SHAREDLIBIMP): os2/z.def $(IMPLIB) -o $@ $^ example.exe: example.o $(LIBS) $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) minigzip.exe: minigzip.o $(LIBS) $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) clean: rm -f *.o *~ example minigzip libz.a libz.so* foo.gz distclean: clean zip: mv Makefile Makefile~; cp -p Makefile.in Makefile rm -f test.c ztest*.c v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ zip -ul9 zlib$$v $(DISTFILES) mv Makefile~ Makefile dist: mv Makefile Makefile~; cp -p Makefile.in Makefile rm -f test.c ztest*.c d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ rm -f $$d.tar.gz; \ if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ files=""; \ for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ cd ..; \ GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ if test ! -d $$d; then rm -f $$d; fi mv Makefile~ Makefile tags: etags *.[ch] depend: makedepend -- $(CFLAGS) -- *.[ch] # DO NOT DELETE THIS LINE -- make depend depends on it. adler32.o: zlib.h zconf.h compress.o: zlib.h zconf.h crc32.o: zlib.h zconf.h deflate.o: deflate.h zutil.h zlib.h zconf.h example.o: zlib.h zconf.h gzio.o: zutil.h zlib.h zconf.h infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h infcodes.o: zutil.h zlib.h zconf.h infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h inffast.o: zutil.h zlib.h zconf.h inftrees.h inffast.o: infblock.h infcodes.h infutil.h inffast.h inflate.o: zutil.h zlib.h zconf.h infblock.h inftrees.o: zutil.h zlib.h zconf.h inftrees.h infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h minigzip.o: zlib.h zconf.h trees.o: deflate.h zutil.h zlib.h zconf.h trees.h uncompr.o: zlib.h zconf.h zutil.o: zutil.h zlib.h zconf.h tcl8.6.5/compat/zlib/old/os2/zlib.def0000644000175000017500000000141212663653131016705 0ustar sergeisergei; ; Slightly modified version of ../nt/zlib.dnt :-) ; LIBRARY Z DESCRIPTION "Zlib compression library for OS/2" CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE MULTIPLE EXPORTS adler32 compress crc32 deflate deflateCopy deflateEnd deflateInit2_ deflateInit_ deflateParams deflateReset deflateSetDictionary gzclose gzdopen gzerror gzflush gzopen gzread gzwrite inflate inflateEnd inflateInit2_ inflateInit_ inflateReset inflateSetDictionary inflateSync uncompress zlibVersion gzprintf gzputc gzgetc gzseek gzrewind gztell gzeof gzsetparams zError inflateSyncPoint get_crc_table compress2 gzputs gzgets tcl8.6.5/compat/zlib/old/descrip.mms0000644000175000017500000000301112663653131016726 0ustar sergeisergei# descrip.mms: MMS description file for building zlib on VMS # written by Martin P.J. Zinser cc_defs = c_deb = .ifdef __DECC__ pref = /prefix=all .endif OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\ deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\ inftrees.obj, infcodes.obj, infutil.obj, inffast.obj CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF) all : example.exe minigzip.exe @ write sys$output " Example applications available" libz.olb : libz.olb($(OBJS)) @ write sys$output " libz available" example.exe : example.obj libz.olb link example,libz.olb/lib minigzip.exe : minigzip.obj libz.olb link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib clean : delete *.obj;*,libz.olb;* # Other dependencies. adler32.obj : zutil.h zlib.h zconf.h compress.obj : zlib.h zconf.h crc32.obj : zutil.h zlib.h zconf.h deflate.obj : deflate.h zutil.h zlib.h zconf.h example.obj : zlib.h zconf.h gzio.obj : zutil.h zlib.h zconf.h infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h inflate.obj : zutil.h zlib.h zconf.h infblock.h inftrees.obj : zutil.h zlib.h zconf.h inftrees.h infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h minigzip.obj : zlib.h zconf.h trees.obj : deflate.h zutil.h zlib.h zconf.h uncompr.obj : zlib.h zconf.h zutil.obj : zutil.h zlib.h zconf.h tcl8.6.5/compat/zlib/old/visual-basic.txt0000644000175000017500000001365412663653131017720 0ustar sergeisergeiSee below some functions declarations for Visual Basic. Frequently Asked Question: Q: Each time I use the compress function I get the -5 error (not enough room in the output buffer). A: Make sure that the length of the compressed buffer is passed by reference ("as any"), not by value ("as long"). Also check that before the call of compress this length is equal to the total size of the compressed buffer and not zero. From: "Jon Caruana" Subject: Re: How to port zlib declares to vb? Date: Mon, 28 Oct 1996 18:33:03 -0600 Got the answer! (I haven't had time to check this but it's what I got, and looks correct): He has the following routines working: compress uncompress gzopen gzwrite gzread gzclose Declares follow: (Quoted from Carlos Rios , in Vb4 form) #If Win16 Then 'Use Win16 calls. Declare Function compress Lib "ZLIB.DLL" (ByVal compr As String, comprLen As Any, ByVal buf As String, ByVal buflen As Long) As Integer Declare Function uncompress Lib "ZLIB.DLL" (ByVal uncompr As String, uncomprLen As Any, ByVal compr As String, ByVal lcompr As Long) As Integer Declare Function gzopen Lib "ZLIB.DLL" (ByVal filePath As String, ByVal mode As String) As Long Declare Function gzread Lib "ZLIB.DLL" (ByVal file As Long, ByVal uncompr As String, ByVal uncomprLen As Integer) As Integer Declare Function gzwrite Lib "ZLIB.DLL" (ByVal file As Long, ByVal uncompr As String, ByVal uncomprLen As Integer) As Integer Declare Function gzclose Lib "ZLIB.DLL" (ByVal file As Long) As Integer #Else Declare Function compress Lib "ZLIB32.DLL" (ByVal compr As String, comprLen As Any, ByVal buf As String, ByVal buflen As Long) As Integer Declare Function uncompress Lib "ZLIB32.DLL" (ByVal uncompr As String, uncomprLen As Any, ByVal compr As String, ByVal lcompr As Long) As Long Declare Function gzopen Lib "ZLIB32.DLL" (ByVal file As String, ByVal mode As String) As Long Declare Function gzread Lib "ZLIB32.DLL" (ByVal file As Long, ByVal uncompr As String, ByVal uncomprLen As Long) As Long Declare Function gzwrite Lib "ZLIB32.DLL" (ByVal file As Long, ByVal uncompr As String, ByVal uncomprLen As Long) As Long Declare Function gzclose Lib "ZLIB32.DLL" (ByVal file As Long) As Long #End If -Jon Caruana jon-net@usa.net Microsoft Sitebuilder Network Level 1 Member - HTML Writer's Guild Member Here is another example from Michael that he says conforms to the VB guidelines, and that solves the problem of not knowing the uncompressed size by storing it at the end of the file: 'Calling the functions: 'bracket meaning: [optional] {Range of possible values} 'Call subCompressFile( [, , [level of compression {1..9}]]) 'Call subUncompressFile() Option Explicit Private lngpvtPcnSml As Long 'Stores value for 'lngPercentSmaller' Private Const SUCCESS As Long = 0 Private Const strFilExt As String = ".cpr" Private Declare Function lngfncCpr Lib "zlib.dll" Alias "compress2" (ByRef dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long, ByVal level As Integer) As Long Private Declare Function lngfncUcp Lib "zlib.dll" Alias "uncompress" (ByRef dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long) As Long Public Sub subCompressFile(ByVal strargOriFilPth As String, Optional ByVal strargCprFilPth As String, Optional ByVal intLvl As Integer = 9) Dim strCprPth As String Dim lngOriSiz As Long Dim lngCprSiz As Long Dim bytaryOri() As Byte Dim bytaryCpr() As Byte lngOriSiz = FileLen(strargOriFilPth) ReDim bytaryOri(lngOriSiz - 1) Open strargOriFilPth For Binary Access Read As #1 Get #1, , bytaryOri() Close #1 strCprPth = IIf(strargCprFilPth = "", strargOriFilPth, strargCprFilPth) 'Select file path and name strCprPth = strCprPth & IIf(Right(strCprPth, Len(strFilExt)) = strFilExt, "", strFilExt) 'Add file extension if not exists lngCprSiz = (lngOriSiz * 1.01) + 12 'Compression needs temporary a bit more space then original file size ReDim bytaryCpr(lngCprSiz - 1) If lngfncCpr(bytaryCpr(0), lngCprSiz, bytaryOri(0), lngOriSiz, intLvl) = SUCCESS Then lngpvtPcnSml = (1# - (lngCprSiz / lngOriSiz)) * 100 ReDim Preserve bytaryCpr(lngCprSiz - 1) Open strCprPth For Binary Access Write As #1 Put #1, , bytaryCpr() Put #1, , lngOriSiz 'Add the the original size value to the end (last 4 bytes) Close #1 Else MsgBox "Compression error" End If Erase bytaryCpr Erase bytaryOri End Sub Public Sub subUncompressFile(ByVal strargFilPth As String) Dim bytaryCpr() As Byte Dim bytaryOri() As Byte Dim lngOriSiz As Long Dim lngCprSiz As Long Dim strOriPth As String lngCprSiz = FileLen(strargFilPth) ReDim bytaryCpr(lngCprSiz - 1) Open strargFilPth For Binary Access Read As #1 Get #1, , bytaryCpr() Close #1 'Read the original file size value: lngOriSiz = bytaryCpr(lngCprSiz - 1) * (2 ^ 24) _ + bytaryCpr(lngCprSiz - 2) * (2 ^ 16) _ + bytaryCpr(lngCprSiz - 3) * (2 ^ 8) _ + bytaryCpr(lngCprSiz - 4) ReDim Preserve bytaryCpr(lngCprSiz - 5) 'Cut of the original size value ReDim bytaryOri(lngOriSiz - 1) If lngfncUcp(bytaryOri(0), lngOriSiz, bytaryCpr(0), lngCprSiz) = SUCCESS Then strOriPth = Left(strargFilPth, Len(strargFilPth) - Len(strFilExt)) Open strOriPth For Binary Access Write As #1 Put #1, , bytaryOri() Close #1 Else MsgBox "Uncompression error" End If Erase bytaryCpr Erase bytaryOri End Sub Public Property Get lngPercentSmaller() As Long lngPercentSmaller = lngpvtPcnSml End Property tcl8.6.5/compat/zlib/old/Makefile.riscos0000644000175000017500000000726712663653131017541 0ustar sergeisergei# Project: zlib_1_03 # Patched for zlib 1.1.2 rw@shadow.org.uk 19980430 # test works out-of-the-box, installs `somewhere' on demand # Toolflags: CCflags = -c -depend !Depend -IC: -g -throwback -DRISCOS -fah C++flags = -c -depend !Depend -IC: -throwback Linkflags = -aif -c++ -o $@ ObjAsmflags = -throwback -NoCache -depend !Depend CMHGflags = LibFileflags = -c -l -o $@ Squeezeflags = -o $@ # change the line below to where _you_ want the library installed. libdest = lib:zlib # Final targets: @.lib: @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \ @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \ @.o.uncompr @.o.zutil LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \ @.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \ @.o.trees @.o.uncompr @.o.zutil test: @.minigzip @.example @.lib @copy @.lib @.libc A~C~DF~L~N~P~Q~RS~TV @echo running tests: hang on. @/@.minigzip -f -9 libc @/@.minigzip -d libc-gz @/@.minigzip -f -1 libc @/@.minigzip -d libc-gz @/@.minigzip -h -9 libc @/@.minigzip -d libc-gz @/@.minigzip -h -1 libc @/@.minigzip -d libc-gz @/@.minigzip -9 libc @/@.minigzip -d libc-gz @/@.minigzip -1 libc @/@.minigzip -d libc-gz @diff @.lib @.libc @echo that should have reported '@.lib and @.libc identical' if you have diff. @/@.example @.fred @.fred @echo that will have given lots of hello!'s. @.minigzip: @.o.minigzip @.lib C:o.Stubs Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs @.example: @.o.example @.lib C:o.Stubs Link $(Linkflags) @.o.example @.lib C:o.Stubs install: @.lib cdir $(libdest) cdir $(libdest).h @copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV @copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV @copy @.lib $(libdest).lib A~C~DF~L~N~P~Q~RS~TV @echo okay, installed zlib in $(libdest) clean:; remove @.minigzip remove @.example remove @.libc -wipe @.o.* F~r~cV remove @.fred # User-editable dependencies: .c.o: cc $(ccflags) -o $@ $< # Static dependencies: # Dynamic dependencies: o.example: c.example o.example: h.zlib o.example: h.zconf o.minigzip: c.minigzip o.minigzip: h.zlib o.minigzip: h.zconf o.adler32: c.adler32 o.adler32: h.zlib o.adler32: h.zconf o.compress: c.compress o.compress: h.zlib o.compress: h.zconf o.crc32: c.crc32 o.crc32: h.zlib o.crc32: h.zconf o.deflate: c.deflate o.deflate: h.deflate o.deflate: h.zutil o.deflate: h.zlib o.deflate: h.zconf o.gzio: c.gzio o.gzio: h.zutil o.gzio: h.zlib o.gzio: h.zconf o.infblock: c.infblock o.infblock: h.zutil o.infblock: h.zlib o.infblock: h.zconf o.infblock: h.infblock o.infblock: h.inftrees o.infblock: h.infcodes o.infblock: h.infutil o.infcodes: c.infcodes o.infcodes: h.zutil o.infcodes: h.zlib o.infcodes: h.zconf o.infcodes: h.inftrees o.infcodes: h.infblock o.infcodes: h.infcodes o.infcodes: h.infutil o.infcodes: h.inffast o.inffast: c.inffast o.inffast: h.zutil o.inffast: h.zlib o.inffast: h.zconf o.inffast: h.inftrees o.inffast: h.infblock o.inffast: h.infcodes o.inffast: h.infutil o.inffast: h.inffast o.inflate: c.inflate o.inflate: h.zutil o.inflate: h.zlib o.inflate: h.zconf o.inflate: h.infblock o.inftrees: c.inftrees o.inftrees: h.zutil o.inftrees: h.zlib o.inftrees: h.zconf o.inftrees: h.inftrees o.inftrees: h.inffixed o.infutil: c.infutil o.infutil: h.zutil o.infutil: h.zlib o.infutil: h.zconf o.infutil: h.infblock o.infutil: h.inftrees o.infutil: h.infcodes o.infutil: h.infutil o.trees: c.trees o.trees: h.deflate o.trees: h.zutil o.trees: h.zlib o.trees: h.zconf o.trees: h.trees o.uncompr: c.uncompr o.uncompr: h.zlib o.uncompr: h.zconf o.zutil: c.zutil o.zutil: h.zutil o.zutil: h.zlib o.zutil: h.zconf tcl8.6.5/compat/zlib/old/README0000644000175000017500000000020512663653131015441 0ustar sergeisergeiThis directory contains files that have not been updated for zlib 1.2.x (Volunteers are encouraged to help clean this up. Thanks.) tcl8.6.5/compat/zlib/old/Makefile.emx0000644000175000017500000000265312663660065017026 0ustar sergeisergei# Makefile for zlib. Modified for emx/rsxnt by Chr. Spieler, 6/16/98. # Copyright (C) 1995-1998 Jean-loup Gailly. # For conditions of distribution and use, see copyright notice in zlib.h # To compile, or to compile and test, type: # # make -fmakefile.emx; make test -fmakefile.emx # CC=gcc -Zwin32 #CFLAGS=-MMD -O #CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 #CFLAGS=-MMD -g -DDEBUG CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -Wstrict-prototypes -Wmissing-prototypes # If cp.exe is available, replace "copy /Y" with "cp -fp" . CP=copy /Y # If gnu install.exe is available, replace $(CP) with ginstall. INSTALL=$(CP) # The default value of RM is "rm -f." If "rm.exe" is found, comment out: RM=del LDLIBS=-L. -lzlib LD=$(CC) -s -o LDSHARED=$(CC) INCL=zlib.h zconf.h LIBS=zlib.a AR=ar rcs prefix=/usr/local exec_prefix = $(prefix) OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \ gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o TEST_OBJS = example.o minigzip.o all: example.exe minigzip.exe test: all ./example echo hello world | .\minigzip | .\minigzip -d %.o : %.c $(CC) $(CFLAGS) -c $< -o $@ zlib.a: $(OBJS) $(AR) $@ $(OBJS) %.exe : %.o $(LIBS) $(LD) $@ $< $(LDLIBS) .PHONY : clean clean: $(RM) *.d $(RM) *.o $(RM) *.exe $(RM) zlib.a $(RM) foo.gz DEPS := $(wildcard *.d) ifneq ($(DEPS),) include $(DEPS) endif tcl8.6.5/compat/zlib/trees.h0000644000175000017500000002043012663653206015303 0ustar sergeisergei/* header created automatically with -DGEN_TREES_H */ local const ct_data static_ltree[L_CODES+2] = { {{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, {{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, {{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, {{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, {{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, {{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, {{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, {{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, {{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, {{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, {{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, {{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, {{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, {{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, {{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, {{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, {{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, {{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, {{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, {{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, {{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, {{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, {{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, {{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, {{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, {{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, {{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, {{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, {{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, {{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, {{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, {{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, {{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, {{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, {{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, {{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, {{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, {{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, {{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, {{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, {{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, {{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, {{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, {{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, {{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, {{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, {{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, {{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, {{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, {{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, {{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, {{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, {{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, {{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, {{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, {{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, {{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, {{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} }; local const ct_data static_dtree[D_CODES] = { {{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, {{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, {{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, {{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, {{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, {{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} }; const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 }; const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 }; local const int base_length[LENGTH_CODES] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 }; local const int base_dist[D_CODES] = { 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 }; tcl8.6.5/compat/zlib/inftrees.h0000644000175000017500000000556012663653206016007 0ustar sergeisergei/* inftrees.h -- header to use inftrees.c * Copyright (C) 1995-2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* Structure for decoding tables. Each entry provides either the information needed to do the operation requested by the code that indexed that table entry, or it provides a pointer to another table that indexes more bits of the code. op indicates whether the entry is a pointer to another table, a literal, a length or distance, an end-of-block, or an invalid code. For a table pointer, the low four bits of op is the number of index bits of that table. For a length or distance, the low four bits of op is the number of extra bits to get after the code. bits is the number of bits in this code or part of the code to drop off of the bit buffer. val is the actual byte to output in the case of a literal, the base length or distance, or the offset from the current table to the next table. Each entry is four bytes. */ typedef struct { unsigned char op; /* operation, extra bits, table bits */ unsigned char bits; /* bits in this part of the code */ unsigned short val; /* offset in table or code value */ } code; /* op values as set by inflate_table(): 00000000 - literal 0000tttt - table link, tttt != 0 is the number of table index bits 0001eeee - length or distance, eeee is the number of extra bits 01100000 - end of block 01000000 - invalid code */ /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program examples/enough.c found in the zlib distribtution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns returns 852, and "enough 30 6 15" for distance codes returns 592. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ #define ENOUGH_LENS 852 #define ENOUGH_DISTS 592 #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) /* Type of code to build for inflate_table() */ typedef enum { CODES, LENS, DISTS } codetype; int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work)); tcl8.6.5/compat/zlib/zlib2ansi0000644000175000017500000000746712663653206015647 0ustar sergeisergei#!/usr/bin/perl # Transform K&R C function definitions into ANSI equivalent. # # Author: Paul Marquess # Version: 1.0 # Date: 3 October 2006 # TODO # # Asumes no function pointer parameters. unless they are typedefed. # Assumes no literal strings that look like function definitions # Assumes functions start at the beginning of a line use strict; use warnings; local $/; $_ = <>; my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments my $d1 = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ; my $decl = qr{ $sp (?: \w+ $sp )+ $d1 }xo ; my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ; while (s/^ ( # Start $1 ( # Start $2 .*? # Minimal eat content ( ^ \w [\w\s\*]+ ) # $3 -- function name \s* # optional whitespace ) # $2 - Matched up to before parameter list \( \s* # Literal "(" + optional whitespace ( [^\)]+ ) # $4 - one or more anythings except ")" \s* \) # optional whitespace surrounding a Literal ")" ( (?: $dList )+ ) # $5 $sp ^ { # literal "{" at start of line ) # Remember to $1 //xsom ) { my $all = $1 ; my $prefix = $2; my $param_list = $4 ; my $params = $5; StripComments($params); StripComments($param_list); $param_list =~ s/^\s+//; $param_list =~ s/\s+$//; my $i = 0 ; my %pList = map { $_ => $i++ } split /\s*,\s*/, $param_list; my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ; my @params = split /\s*;\s*/, $params; my @outParams = (); foreach my $p (@params) { if ($p =~ /,/) { my @bits = split /\s*,\s*/, $p; my $first = shift @bits; $first =~ s/^\s*//; push @outParams, $first; $first =~ /^(\w+\s*)/; my $type = $1 ; push @outParams, map { $type . $_ } @bits; } else { $p =~ s/^\s+//; push @outParams, $p; } } my %tmp = map { /$pMatch/; $_ => $pList{$1} } @outParams ; @outParams = map { " $_" } sort { $tmp{$a} <=> $tmp{$b} } @outParams ; print $prefix ; print "(\n" . join(",\n", @outParams) . ")\n"; print "{" ; } # Output any trailing code. print ; exit 0; sub StripComments { no warnings; # Strip C & C++ coments # From the perlfaq $_[0] =~ s{ /\* ## Start of /* ... */ comment [^*]*\*+ ## Non-* followed by 1-or-more *'s ( [^/*][^*]*\*+ )* ## 0-or-more things which don't start with / ## but do end with '*' / ## End of /* ... */ comment | ## OR C++ Comment // ## Start of C++ comment // [^\n]* ## followed by 0-or-more non end of line characters | ## OR various things which aren't comments: ( " ## Start of " ... " string ( \\. ## Escaped char | ## OR [^"\\] ## Non "\ )* " ## End of " ... " string | ## OR ' ## Start of ' ... ' string ( \\. ## Escaped char | ## OR [^'\\] ## Non '\ )* ' ## End of ' ... ' string | ## OR . ## Anything other char [^/"'\\]* ## Chars which doesn't start a comment, string or escape ) }{$2}gxs; } tcl8.6.5/compat/zlib/inftrees.c0000644000175000017500000003134412663660065016002 0ustar sergeisergei/* inftrees.c -- generate Huffman trees for efficient decoding * Copyright (C) 1995-2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #define MAXBITS 15 const char inflate_copyright[] = " inflate 1.2.8 Copyright 1995-2013 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* Build a set of tables to decode the provided canonical Huffman code. The code lengths are lens[0..codes-1]. The result starts at *table, whose indices are 0..2^bits-1. work is a writable array of at least lens shorts, which is used as a work area. type is the type of code to be generated, CODES, LENS, or DISTS. On return, zero is success, -1 is an invalid code, and +1 means that ENOUGH isn't enough. table on return points to the next available entry's address. bits is the requested root table index bits, and on return it is the actual root table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) codetype type; unsigned short FAR *lens; unsigned codes; code FAR * FAR *table; unsigned FAR *bits; unsigned short FAR *work; { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ unsigned root; /* number of index bits for root table */ unsigned curr; /* number of index bits for current table */ unsigned drop; /* code bits to drop for sub-table */ int left; /* number of prefix codes available */ unsigned used; /* code entries in table used */ unsigned huff; /* Huffman code */ unsigned incr; /* for incrementing code, index */ unsigned fill; /* index for replicating entries */ unsigned low; /* low bits for current root entry */ unsigned mask; /* mask for low root bits */ code here; /* table entry for duplication */ code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ int end; /* use base and extra for symbol > end */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0}; static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64}; /* Process a set of code lengths to create a canonical Huffman code. The code lengths are lens[0..codes-1]. Each length corresponds to the symbols 0..codes-1. The Huffman code is generated by first sorting the symbols by length from short to long, and retaining the symbol order for codes with equal lengths. Then the code starts with all zero bits for the first code of the shortest length, and the codes are integer increments for the same length, and zeros are appended as the length increases. For the deflate format, these bits are stored backwards from their more natural integer increment ordering, and so when the decoding tables are built in the large loop below, the integer codes are incremented backwards. This routine assumes, but does not check, that all of the entries in lens[] are in the range 0..MAXBITS. The caller must assure this. 1..MAXBITS is interpreted as that code length. zero means that that symbol does not occur in this code. The codes are sorted by computing a count of codes for each length, creating from that a table of starting indices for each length in the sorted table, and then entering the symbols in order in the sorted table. The sorted table is work[], with that space being provided by the caller. The length counts are used for other purposes as well, i.e. finding the minimum and maximum length codes, determining if there are any codes at all, checking for a valid set of lengths, and looking ahead at length counts to determine sub-table sizes when building the decoding tables. */ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ for (len = 0; len <= MAXBITS; len++) count[len] = 0; for (sym = 0; sym < codes; sym++) count[lens[sym]]++; /* bound code lengths, force root to be within code lengths */ root = *bits; for (max = MAXBITS; max >= 1; max--) if (count[max] != 0) break; if (root > max) root = max; if (max == 0) { /* no symbols to code at all */ here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)1; here.val = (unsigned short)0; *(*table)++ = here; /* make a table to force an error */ *(*table)++ = here; *bits = 1; return 0; /* no symbols, but wait for decoding to report error */ } for (min = 1; min < max; min++) if (count[min] != 0) break; if (root < min) root = min; /* check for an over-subscribed or incomplete set of lengths */ left = 1; for (len = 1; len <= MAXBITS; len++) { left <<= 1; left -= count[len]; if (left < 0) return -1; /* over-subscribed */ } if (left > 0 && (type == CODES || max != 1)) return -1; /* incomplete set */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + count[len]; /* sort symbols by length, by symbol order within each length */ for (sym = 0; sym < codes; sym++) if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; /* Create and fill in decoding tables. In this loop, the table being filled is at next and has curr index bits. The code being used is huff with length len. That code is converted to an index by dropping drop bits off of the bottom. For codes where len is less than drop + curr, those top drop + curr - len bits are incremented through all values to fill the table with replicated entries. root is the number of index bits for the root table. When len exceeds root, sub-tables are created pointed to by the root entry with an index of the low root bits of huff. This is saved in low to check for when a new sub-table should be started. drop is zero when the root table is being filled, and drop is root when sub-tables are being filled. When a new sub-table is needed, it is necessary to look ahead in the code lengths to determine what size sub-table is needed. The length counts are used for this, and so count[] is decremented as codes are entered in the tables. used keeps track of how many table entries have been allocated from the provided *table space. It is checked for LENS and DIST tables against the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in the initial root table size constants. See the comments in inftrees.h for more information. sym increments through all symbols, and the loop terminates when all codes of length max, i.e. all codes, have been processed. This routine permits incomplete codes, so another loop after this one fills in the rest of the decoding tables with invalid code markers. */ /* set up for code type */ switch (type) { case CODES: base = extra = work; /* dummy value--not used */ end = 19; break; case LENS: base = lbase; base -= 257; extra = lext; extra -= 257; end = 256; break; default: /* DISTS */ base = dbase; extra = dext; end = -1; } /* initialize state for loop */ huff = 0; /* starting code */ sym = 0; /* starting code symbol */ len = min; /* starting code length */ next = *table; /* current table to fill in */ curr = root; /* current table index bits */ drop = 0; /* current bits to drop from code for index */ low = (unsigned)(-1); /* trigger new sub-table when len > root */ used = 1U << root; /* use root table entries */ mask = used - 1; /* mask for comparing low */ /* check available table space */ if ((type == LENS && used > ENOUGH_LENS) || (type == DISTS && used > ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); if ((int)(work[sym]) < end) { here.op = (unsigned char)0; here.val = work[sym]; } else if ((int)(work[sym]) > end) { here.op = (unsigned char)(extra[work[sym]]); here.val = base[work[sym]]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ here.val = 0; } /* replicate for those indices with low len bits equal to huff */ incr = 1U << (len - drop); fill = 1U << curr; min = fill; /* save offset to next table */ do { fill -= incr; next[(huff >> drop) + fill] = here; } while (fill != 0); /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; /* go to next symbol, update count, len */ sym++; if (--(count[len]) == 0) { if (len == max) break; len = lens[work[sym]]; } /* create new sub-table if needed */ if (len > root && (huff & mask) != low) { /* if first time, transition to sub-tables */ if (drop == 0) drop = root; /* increment past last table */ next += min; /* here min is 1 << curr */ /* determine length of next table */ curr = len - drop; left = (int)(1 << curr); while (curr + drop < max) { left -= count[curr + drop]; if (left <= 0) break; curr++; left <<= 1; } /* check for enough space */ used += 1U << curr; if ((type == LENS && used > ENOUGH_LENS) || (type == DISTS && used > ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ low = huff & mask; (*table)[low].op = (unsigned char)curr; (*table)[low].bits = (unsigned char)root; (*table)[low].val = (unsigned short)(next - *table); } } /* fill in remaining table entry if code is incomplete (guaranteed to have at most one remaining entry, since if the code is incomplete, the maximum code length that was allowed to get this far is one bit) */ if (huff != 0) { here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)(len - drop); here.val = (unsigned short)0; next[huff] = here; } /* set return parameters */ *table += used; *bits = root; return 0; } tcl8.6.5/compat/zlib/crc32.c0000644000175000017500000003156612663660065015105 0ustar sergeisergei/* crc32.c -- compute the CRC-32 of a data stream * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing * tables for updating the shift register in one step with three exclusive-ors * instead of four steps with four exclusive-ors. This results in about a * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. */ /* @(#) $Id$ */ /* Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore protection on the static variables used to control the first-use generation of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should first call get_crc_table() to initialize the tables before allowing more than one thread to use crc32(). DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. */ #ifdef MAKECRCH # include # ifndef DYNAMIC_CRC_TABLE # define DYNAMIC_CRC_TABLE # endif /* !DYNAMIC_CRC_TABLE */ #endif /* MAKECRCH */ #include "zutil.h" /* for STDC and FAR definitions */ #define local static /* Definitions for doing the crc four data bytes at a time. */ #if !defined(NOBYFOUR) && defined(Z_U4) # define BYFOUR #endif #ifdef BYFOUR local unsigned long crc32_little OF((unsigned long, const unsigned char FAR *, unsigned)); local unsigned long crc32_big OF((unsigned long, const unsigned char FAR *, unsigned)); # define TBLS 8 #else # define TBLS 1 #endif /* BYFOUR */ /* Local functions for crc concatenation */ local unsigned long gf2_matrix_times OF((unsigned long *mat, unsigned long vec)); local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); #ifdef DYNAMIC_CRC_TABLE local volatile int crc_table_empty = 1; local z_crc_t FAR crc_table[TBLS][256]; local void make_crc_table OF((void)); #ifdef MAKECRCH local void write_table OF((FILE *, const z_crc_t FAR *)); #endif /* MAKECRCH */ /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x (which is shifting right by one and adding x^32 mod p if the bit shifted out is a one). We start with the highest power (least significant bit) of q and repeat for all eight bits of q. The first table is simply the CRC of all possible eight bit values. This is all the information needed to generate CRCs on data a byte at a time for all combinations of CRC register values and incoming bytes. The remaining tables allow for word-at-a-time CRC calculation for both big-endian and little- endian machines, where a word is four bytes. */ local void make_crc_table() { z_crc_t c; int n, k; z_crc_t poly; /* polynomial exclusive-or pattern */ /* terms of polynomial defining this crc (except x^32): */ static volatile int first = 1; /* flag to limit concurrent making */ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; /* See if another task is already doing this (not thread-safe, but better than nothing -- significantly reduces duration of vulnerability in case the advice about DYNAMIC_CRC_TABLE is ignored) */ if (first) { first = 0; /* make exclusive-or pattern from polynomial (0xedb88320UL) */ poly = 0; for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) poly |= (z_crc_t)1 << (31 - p[n]); /* generate a crc for every 8-bit value */ for (n = 0; n < 256; n++) { c = (z_crc_t)n; for (k = 0; k < 8; k++) c = c & 1 ? poly ^ (c >> 1) : c >> 1; crc_table[0][n] = c; } #ifdef BYFOUR /* generate crc for each value followed by one, two, and three zeros, and then the byte reversal of those as well as the first table */ for (n = 0; n < 256; n++) { c = crc_table[0][n]; crc_table[4][n] = ZSWAP32(c); for (k = 1; k < 4; k++) { c = crc_table[0][c & 0xff] ^ (c >> 8); crc_table[k][n] = c; crc_table[k + 4][n] = ZSWAP32(c); } } #endif /* BYFOUR */ crc_table_empty = 0; } else { /* not first */ /* wait for the other guy to finish (not efficient, but rare) */ while (crc_table_empty) ; } #ifdef MAKECRCH /* write out CRC tables to crc32.h */ { FILE *out; out = fopen("crc32.h", "w"); if (out == NULL) return; fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); fprintf(out, "local const z_crc_t FAR "); fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); write_table(out, crc_table[0]); # ifdef BYFOUR fprintf(out, "#ifdef BYFOUR\n"); for (k = 1; k < 8; k++) { fprintf(out, " },\n {\n"); write_table(out, crc_table[k]); } fprintf(out, "#endif\n"); # endif /* BYFOUR */ fprintf(out, " }\n};\n"); fclose(out); } #endif /* MAKECRCH */ } #ifdef MAKECRCH local void write_table(out, table) FILE *out; const z_crc_t FAR *table; { int n; for (n = 0; n < 256; n++) fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", (unsigned long)(table[n]), n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); } #endif /* MAKECRCH */ #else /* !DYNAMIC_CRC_TABLE */ /* ======================================================================== * Tables of CRC-32s of all single-byte values, made by make_crc_table(). */ #include "crc32.h" #endif /* DYNAMIC_CRC_TABLE */ /* ========================================================================= * This function can be used by asm versions of crc32() */ const z_crc_t FAR * ZEXPORT get_crc_table() { #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ return (const z_crc_t FAR *)crc_table; } /* ========================================================================= */ #define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 /* ========================================================================= */ unsigned long ZEXPORT crc32(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; uInt len; { if (buf == Z_NULL) return 0UL; #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ #ifdef BYFOUR if (sizeof(void *) == sizeof(ptrdiff_t)) { z_crc_t endian; endian = 1; if (*((unsigned char *)(&endian))) return crc32_little(crc, buf, len); else return crc32_big(crc, buf, len); } #endif /* BYFOUR */ crc = crc ^ 0xffffffffUL; while (len >= 8) { DO8; len -= 8; } if (len) do { DO1; } while (--len); return crc ^ 0xffffffffUL; } #ifdef BYFOUR /* ========================================================================= */ #define DOLIT4 c ^= *buf4++; \ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 /* ========================================================================= */ local unsigned long crc32_little(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; unsigned len; { register z_crc_t c; register const z_crc_t FAR *buf4; c = (z_crc_t)crc; c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); len--; } buf4 = (const z_crc_t FAR *)(const void FAR *)buf; while (len >= 32) { DOLIT32; len -= 32; } while (len >= 4) { DOLIT4; len -= 4; } buf = (const unsigned char FAR *)buf4; if (len) do { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); } while (--len); c = ~c; return (unsigned long)c; } /* ========================================================================= */ #define DOBIG4 c ^= *++buf4; \ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 /* ========================================================================= */ local unsigned long crc32_big(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; unsigned len; { register z_crc_t c; register const z_crc_t FAR *buf4; c = ZSWAP32((z_crc_t)crc); c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); len--; } buf4 = (const z_crc_t FAR *)(const void FAR *)buf; buf4--; while (len >= 32) { DOBIG32; len -= 32; } while (len >= 4) { DOBIG4; len -= 4; } buf4++; buf = (const unsigned char FAR *)buf4; if (len) do { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); } while (--len); c = ~c; return (unsigned long)(ZSWAP32(c)); } #endif /* BYFOUR */ #define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ /* ========================================================================= */ local unsigned long gf2_matrix_times(mat, vec) unsigned long *mat; unsigned long vec; { unsigned long sum; sum = 0; while (vec) { if (vec & 1) sum ^= *mat; vec >>= 1; mat++; } return sum; } /* ========================================================================= */ local void gf2_matrix_square(square, mat) unsigned long *square; unsigned long *mat; { int n; for (n = 0; n < GF2_DIM; n++) square[n] = gf2_matrix_times(mat, mat[n]); } /* ========================================================================= */ local uLong crc32_combine_(crc1, crc2, len2) uLong crc1; uLong crc2; z_off64_t len2; { int n; unsigned long row; unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ /* degenerate case (also disallow negative lengths) */ if (len2 <= 0) return crc1; /* put operator for one zero bit in odd */ odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ row = 1; for (n = 1; n < GF2_DIM; n++) { odd[n] = row; row <<= 1; } /* put operator for two zero bits in even */ gf2_matrix_square(even, odd); /* put operator for four zero bits in odd */ gf2_matrix_square(odd, even); /* apply len2 zeros to crc1 (first square will put the operator for one zero byte, eight zero bits, in even) */ do { /* apply zeros operator for this bit of len2 */ gf2_matrix_square(even, odd); if (len2 & 1) crc1 = gf2_matrix_times(even, crc1); len2 >>= 1; /* if no more bits set, then done */ if (len2 == 0) break; /* another iteration of the loop with odd and even swapped */ gf2_matrix_square(odd, even); if (len2 & 1) crc1 = gf2_matrix_times(odd, crc1); len2 >>= 1; /* if no more bits set, then done */ } while (len2 != 0); /* return combined crc */ crc1 ^= crc2; return crc1; } /* ========================================================================= */ uLong ZEXPORT crc32_combine(crc1, crc2, len2) uLong crc1; uLong crc2; z_off_t len2; { return crc32_combine_(crc1, crc2, len2); } uLong ZEXPORT crc32_combine64(crc1, crc2, len2) uLong crc1; uLong crc2; z_off64_t len2; { return crc32_combine_(crc1, crc2, len2); } tcl8.6.5/compat/zlib/inflate.c0000644000175000017500000015041012663660065015601 0ustar sergeisergei/* inflate.c -- zlib decompression * Copyright (C) 1995-2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * Change history: * * 1.2.beta0 24 Nov 2002 * - First version -- complete rewrite of inflate to simplify code, avoid * creation of window when not needed, minimize use of window when it is * needed, make inffast.c even faster, implement gzip decoding, and to * improve code readability and style over the previous zlib inflate code * * 1.2.beta1 25 Nov 2002 * - Use pointers for available input and output checking in inffast.c * - Remove input and output counters in inffast.c * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 * - Remove unnecessary second byte pull from length extra in inffast.c * - Unroll direct copy to three copies per loop in inffast.c * * 1.2.beta2 4 Dec 2002 * - Change external routine names to reduce potential conflicts * - Correct filename to inffixed.h for fixed tables in inflate.c * - Make hbuf[] unsigned char to match parameter type in inflate.c * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) * to avoid negation problem on Alphas (64 bit) in inflate.c * * 1.2.beta3 22 Dec 2002 * - Add comments on state->bits assertion in inffast.c * - Add comments on op field in inftrees.h * - Fix bug in reuse of allocated window after inflateReset() * - Remove bit fields--back to byte structure for speed * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths * - Change post-increments to pre-increments in inflate_fast(), PPC biased? * - Add compile time option, POSTINC, to use post-increments instead (Intel?) * - Make MATCH copy in inflate() much faster for when inflate_fast() not used * - Use local copies of stream next and avail values, as well as local bit * buffer and bit count in inflate()--for speed when inflate_fast() not used * * 1.2.beta4 1 Jan 2003 * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings * - Move a comment on output buffer sizes from inffast.c to inflate.c * - Add comments in inffast.c to introduce the inflate_fast() routine * - Rearrange window copies in inflate_fast() for speed and simplification * - Unroll last copy for window match in inflate_fast() * - Use local copies of window variables in inflate_fast() for speed * - Pull out common wnext == 0 case for speed in inflate_fast() * - Make op and len in inflate_fast() unsigned for consistency * - Add FAR to lcode and dcode declarations in inflate_fast() * - Simplified bad distance check in inflate_fast() * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new * source file infback.c to provide a call-back interface to inflate for * programs like gzip and unzip -- uses window as output buffer to avoid * window copying * * 1.2.beta5 1 Jan 2003 * - Improved inflateBack() interface to allow the caller to provide initial * input in strm. * - Fixed stored blocks bug in inflateBack() * * 1.2.beta6 4 Jan 2003 * - Added comments in inffast.c on effectiveness of POSTINC * - Typecasting all around to reduce compiler warnings * - Changed loops from while (1) or do {} while (1) to for (;;), again to * make compilers happy * - Changed type of window in inflateBackInit() to unsigned char * * * 1.2.beta7 27 Jan 2003 * - Changed many types to unsigned or unsigned short to avoid warnings * - Added inflateCopy() function * * 1.2.0 9 Mar 2003 * - Changed inflateBack() interface to provide separate opaque descriptors * for the in() and out() functions * - Changed inflateBack() argument and in_func typedef to swap the length * and buffer address return values for the input function * - Check next_in and next_out for Z_NULL on entry to inflate() * * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" #ifdef MAKEFIXED # ifndef BUILDFIXED # define BUILDFIXED # endif #endif /* function prototypes */ local void fixedtables OF((struct inflate_state FAR *state)); local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, unsigned copy)); #ifdef BUILDFIXED void makefixed OF((void)); #endif local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, unsigned len)); int ZEXPORT inflateResetKeep(strm) z_streamp strm; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; if (state->wrap) /* to support ill-conceived Java test suite */ strm->adler = state->wrap & 1; state->mode = HEAD; state->last = 0; state->havedict = 0; state->dmax = 32768U; state->head = Z_NULL; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; state->sane = 1; state->back = -1; Tracev((stderr, "inflate: reset\n")); return Z_OK; } int ZEXPORT inflateReset(strm) z_streamp strm; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; state->wsize = 0; state->whave = 0; state->wnext = 0; return inflateResetKeep(strm); } int ZEXPORT inflateReset2(strm, windowBits) z_streamp strm; int windowBits; { int wrap; struct inflate_state FAR *state; /* get the state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* extract wrap request from windowBits parameter */ if (windowBits < 0) { wrap = 0; windowBits = -windowBits; } else { wrap = (windowBits >> 4) + 1; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; #endif } /* set number of window bits, free window if different */ if (windowBits && (windowBits < 8 || windowBits > 15)) return Z_STREAM_ERROR; if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { ZFREE(strm, state->window); state->window = Z_NULL; } /* update state and reset the rest of it */ state->wrap = wrap; state->wbits = (unsigned)windowBits; return inflateReset(strm); } int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) z_streamp strm; int windowBits; const char *version; int stream_size; { int ret; struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; #endif } if (strm->zfree == (free_func)0) #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zfree = zcfree; #endif state = (struct inflate_state FAR *) ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->window = Z_NULL; ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); strm->state = Z_NULL; } return ret; } int ZEXPORT inflateInit_(strm, version, stream_size) z_streamp strm; const char *version; int stream_size; { return inflateInit2_(strm, DEF_WBITS, version, stream_size); } int ZEXPORT inflatePrime(strm, bits, value) z_streamp strm; int bits; int value; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; state->bits = 0; return Z_OK; } if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; state->hold += value << state->bits; state->bits += bits; return Z_OK; } /* Return state with length and distance decoding tables and index sizes set to fixed code decoding. Normally this returns fixed tables from inffixed.h. If BUILDFIXED is defined, then instead this routine builds the tables the first time it's called, and returns those tables the first time and thereafter. This reduces the size of the code by about 2K bytes, in exchange for a little execution time. However, BUILDFIXED should not be used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ local void fixedtables(state) struct inflate_state FAR *state; { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { unsigned sym, bits; static code *next; /* literal/length table */ sym = 0; while (sym < 144) state->lens[sym++] = 8; while (sym < 256) state->lens[sym++] = 9; while (sym < 280) state->lens[sym++] = 7; while (sym < 288) state->lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); /* distance table */ sym = 0; while (sym < 32) state->lens[sym++] = 5; distfix = next; bits = 5; inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); /* do this just once */ virgin = 0; } #else /* !BUILDFIXED */ # include "inffixed.h" #endif /* BUILDFIXED */ state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; state->distbits = 5; } #ifdef MAKEFIXED #include /* Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also defines BUILDFIXED, so the tables are built on the fly. makefixed() writes those tables to stdout, which would be piped to inffixed.h. A small program can simply call makefixed to do this: void makefixed(void); int main(void) { makefixed(); return 0; } Then that can be linked with zlib built with MAKEFIXED defined and run: a.out > inffixed.h */ void makefixed() { unsigned low, size; struct inflate_state state; fixedtables(&state); puts(" /* inffixed.h -- table for decoding fixed codes"); puts(" * Generated automatically by makefixed()."); puts(" */"); puts(""); puts(" /* WARNING: this file should *not* be used by applications."); puts(" It is part of the implementation of this library and is"); puts(" subject to change. Applications should only use zlib.h."); puts(" */"); puts(""); size = 1U << 9; printf(" static const code lenfix[%u] = {", size); low = 0; for (;;) { if ((low % 7) == 0) printf("\n "); printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, state.lencode[low].bits, state.lencode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); size = 1U << 5; printf("\n static const code distfix[%u] = {", size); low = 0; for (;;) { if ((low % 6) == 0) printf("\n "); printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, state.distcode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); } #endif /* MAKEFIXED */ /* Update the window with the last wsize (normally 32K) bytes written before returning. If window does not exist yet, create it. This is only called when a window is already in use, or when output has been written during this inflate call, but the end of the deflate stream has not been reached yet. It is also called to create a window for dictionary data when a dictionary is loaded. Providing output buffers larger than 32K to inflate() should provide a speed advantage, since only the last 32K of output is copied to the sliding window upon return from inflate(), and since all distances after the first 32K of output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ local int updatewindow(strm, end, copy) z_streamp strm; const Bytef *end; unsigned copy; { struct inflate_state FAR *state; unsigned dist; state = (struct inflate_state FAR *)strm->state; /* if it hasn't been done already, allocate space for the window */ if (state->window == Z_NULL) { state->window = (unsigned char FAR *) ZALLOC(strm, 1U << state->wbits, sizeof(unsigned char)); if (state->window == Z_NULL) return 1; } /* if window not in use yet, initialize */ if (state->wsize == 0) { state->wsize = 1U << state->wbits; state->wnext = 0; state->whave = 0; } /* copy state->wsize or less output bytes into the circular window */ if (copy >= state->wsize) { zmemcpy(state->window, end - state->wsize, state->wsize); state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; if (dist > copy) dist = copy; zmemcpy(state->window + state->wnext, end - copy, dist); copy -= dist; if (copy) { zmemcpy(state->window, end - copy, copy); state->wnext = copy; state->whave = state->wsize; } else { state->wnext += dist; if (state->wnext == state->wsize) state->wnext = 0; if (state->whave < state->wsize) state->whave += dist; } } return 0; } /* Macros for inflate(): */ /* check function to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP # define UPDATE(check, buf, len) \ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) #else # define UPDATE(check, buf, len) adler32(check, buf, len) #endif /* check macros for header crc */ #ifdef GUNZIP # define CRC2(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ check = crc32(check, hbuf, 2); \ } while (0) # define CRC4(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ hbuf[2] = (unsigned char)((word) >> 16); \ hbuf[3] = (unsigned char)((word) >> 24); \ check = crc32(check, hbuf, 4); \ } while (0) #endif /* Load registers with state in inflate() for speed */ #define LOAD() \ do { \ put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ hold = state->hold; \ bits = state->bits; \ } while (0) /* Restore state from registers in inflate() */ #define RESTORE() \ do { \ strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = next; \ strm->avail_in = have; \ state->hold = hold; \ state->bits = bits; \ } while (0) /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflate() if there is no input available. */ #define PULLBYTE() \ do { \ if (have == 0) goto inf_leave; \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflate(). */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is structured roughly as follows: for (;;) switch (state) { ... case STATEn: if (not enough input data or output space to make progress) return; ... make progress ... state = STATEm; break; ... } so when inflate() is called again, the same case is attempted again, and if the appropriate resources are provided, the machine proceeds to the next state. The NEEDBITS() macro is usually the way the state evaluates whether it can proceed or should return. NEEDBITS() does the return if the requested bits are not available. The typical use of the BITS macros is: NEEDBITS(n); ... do something with BITS(n) ... DROPBITS(n); where NEEDBITS(n) either returns from inflate() if there isn't enough input left to load n bits into the accumulator, or it continues. BITS(n) gives the low n bits in the accumulator. When done, DROPBITS(n) drops the low n bits off the accumulator. INITBITS() clears the accumulator and sets the number of available bits to zero. BYTEBITS() discards just enough bits to put the accumulator on a byte boundary. After BYTEBITS() and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return if there is no input available. The decoding of variable length codes uses PULLBYTE() directly in order to pull just enough bytes to decode the next code, and no more. Some states loop until they get enough input, making sure that enough state information is maintained to continue the loop where it left off if NEEDBITS() returns in the loop. For example, want, need, and keep would all have to actually be part of the saved state in case NEEDBITS() returns: case STATEw: while (want < need) { NEEDBITS(n); keep[want++] = BITS(n); DROPBITS(n); } state = STATEx; case STATEx: As shown above, if the next state is also the next case, then the break is omitted. A state may also return if there is not enough output space available to complete that state. Those states are copying stored data, writing a literal byte, and copying a matching string. When returning, a "goto inf_leave" is used to update the total counters, update the check value, and determine whether any progress has been made during that inflate() call in order to return the proper return code. Progress is defined as a change in either strm->avail_in or strm->avail_out. When there is a window, goto inf_leave will update the window with the last output written. If a goto inf_leave occurs in the middle of decompression and there is no window currently, goto inf_leave will create one and copy output to the window for the next call of inflate(). In this implementation, the flush parameter of inflate() only affects the return code (per zlib.h). inflate() always writes as much as possible to strm->next_out, given the space available and the provided input--the effect documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers the allocation of and copying into a sliding window until necessary, which provides the effect documented in zlib.h for Z_FINISH when the entire input stream available. So the only thing the flush parameter actually does is: when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it will return Z_BUF_ERROR if it has not reached the end of the stream. */ int ZEXPORT inflate(strm, flush) z_streamp strm; int flush; { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned in, out; /* save starting available input and output */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char FAR *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ #ifdef GUNZIP unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ #endif static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ LOAD(); in = have; out = left; ret = Z_OK; for (;;) switch (state->mode) { case HEAD: if (state->wrap == 0) { state->mode = TYPEDO; break; } NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); state->mode = FLAGS; break; } state->flags = 0; /* expect zlib header */ if (state->head != Z_NULL) state->head->done = -1; if (!(state->wrap & 1) || /* check if zlib header allowed */ #else if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { strm->msg = (char *)"incorrect header check"; state->mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } DROPBITS(4); len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; else if (len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; } state->dmax = 1U << len; Tracev((stderr, "inflate: zlib header ok\n")); strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = hold & 0x200 ? DICTID : TYPE; INITBITS(); break; #ifdef GUNZIP case FLAGS: NEEDBITS(16); state->flags = (int)(hold); if ((state->flags & 0xff) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } if (state->flags & 0xe000) { strm->msg = (char *)"unknown header flags set"; state->mode = BAD; break; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = TIME; case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; if (state->flags & 0x0200) CRC4(state->check, hold); INITBITS(); state->mode = OS; case OS: NEEDBITS(16); if (state->head != Z_NULL) { state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; case EXLEN: if (state->flags & 0x0400) { NEEDBITS(16); state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) state->head->extra = Z_NULL; state->mode = EXTRA; case EXTRA: if (state->flags & 0x0400) { copy = state->length; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && state->head->extra != Z_NULL) { len = state->head->extra_len - state->length; zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; state->length -= copy; } if (state->length) goto inf_leave; } state->length = 0; state->mode = NAME; case NAME: if (state->flags & 0x0800) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) state->head->name[state->length++] = len; } while (len && copy < have); if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->name = Z_NULL; state->length = 0; state->mode = COMMENT; case COMMENT: if (state->flags & 0x1000) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) state->head->comment[state->length++] = len; } while (len && copy < have); if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->comment = Z_NULL; state->mode = HCRC; case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); if (hold != (state->check & 0xffff)) { strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; } INITBITS(); } if (state->head != Z_NULL) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } strm->adler = state->check = crc32(0L, Z_NULL, 0); state->mode = TYPE; break; #endif case DICTID: NEEDBITS(32); strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; case DICT: if (state->havedict == 0) { RESTORE(); return Z_NEED_DICT; } strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = TYPE; case TYPE: if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; case TYPEDO: if (state->last) { BYTEBITS(); state->mode = CHECK; break; } NEEDBITS(3); state->last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); state->mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN_; /* decode codes */ if (flush == Z_TREES) { DROPBITS(2); goto inf_leave; } break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); state->mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); break; case STORED: BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } state->length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state->length)); INITBITS(); state->mode = COPY_; if (flush == Z_TREES) goto inf_leave; case COPY_: state->mode = COPY; case COPY: copy = state->length; if (copy) { if (copy > have) copy = have; if (copy > left) copy = left; if (copy == 0) goto inf_leave; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state->length -= copy; break; } Tracev((stderr, "inflate: stored end\n")); state->mode = TYPE; break; case TABLE: NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); state->have = 0; state->mode = LENLENS; case LENLENS: while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; state->lencode = (const code FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); state->have = 0; state->mode = CODELENS; case CODELENS: while (state->have < state->nlen + state->ndist) { for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } len = state->lens[state->have - 1]; copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state->mode == BAD) break; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { strm->msg = (char *)"invalid code -- missing end-of-block"; state->mode = BAD; break; } /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; state->lencode = (const code FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } state->distcode = (const code FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN_; if (flush == Z_TREES) goto inf_leave; case LEN_: state->mode = LEN; case LEN: if (have >= 6 && left >= 258) { RESTORE(); inflate_fast(strm, out); LOAD(); if (state->mode == TYPE) state->back = -1; break; } state->back = 0; for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; state->length = (unsigned)here.val; if ((int)(here.op) == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); state->mode = LIT; break; } if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state->back = -1; state->mode = TYPE; break; } if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } state->extra = (unsigned)(here.op) & 15; state->mode = LENEXT; case LENEXT: if (state->extra) { NEEDBITS(state->extra); state->length += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } Tracevv((stderr, "inflate: length %u\n", state->length)); state->was = state->length; state->mode = DIST; case DIST: for (;;) { here = state->distcode[BITS(state->distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; if (here.op & 64) { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; state->extra = (unsigned)(here.op) & 15; state->mode = DISTEXT; case DISTEXT: if (state->extra) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } #ifdef INFLATE_STRICT if (state->offset > state->dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; case MATCH: if (left == 0) goto inf_leave; copy = out - left; if (state->offset > copy) { /* copy from window */ copy = state->offset - copy; if (copy > state->whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR Trace((stderr, "inflate.c too far\n")); copy -= state->whave; if (copy > state->length) copy = state->length; if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = 0; } while (--copy); if (state->length == 0) state->mode = LEN; break; #endif } if (copy > state->wnext) { copy -= state->wnext; from = state->window + (state->wsize - copy); } else from = state->window + (state->wnext - copy); if (copy > state->length) copy = state->length; } else { /* copy from output */ from = put - state->offset; copy = state->length; } if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = *from++; } while (--copy); if (state->length == 0) state->mode = LEN; break; case LIT: if (left == 0) goto inf_leave; *put++ = (unsigned char)(state->length); left--; state->mode = LEN; break; case CHECK: if (state->wrap) { NEEDBITS(32); out -= left; strm->total_out += out; state->total += out; if (out) strm->adler = state->check = UPDATE(state->check, put - out, out); out = left; if (( #ifdef GUNZIP state->flags ? hold : #endif ZSWAP32(hold)) != state->check) { strm->msg = (char *)"incorrect data check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: check matches trailer\n")); } #ifdef GUNZIP state->mode = LENGTH; case LENGTH: if (state->wrap && state->flags) { NEEDBITS(32); if (hold != (state->total & 0xffffffffUL)) { strm->msg = (char *)"incorrect length check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: length matches trailer\n")); } #endif state->mode = DONE; case DONE: ret = Z_STREAM_END; goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; case MEM: return Z_MEM_ERROR; case SYNC: default: return Z_STREAM_ERROR; } /* Return from inflate(), updating the total counts and the check value. If there was no progress during the inflate() call, return a buffer error. Call updatewindow() to create and/or update the window state. Note: a memory error from inflate() is non-recoverable. */ inf_leave: RESTORE(); if (state->wsize || (out != strm->avail_out && state->mode < BAD && (state->mode < CHECK || flush != Z_FINISH))) if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { state->mode = MEM; return Z_MEM_ERROR; } in -= strm->avail_in; out -= strm->avail_out; strm->total_in += in; strm->total_out += out; state->total += out; if (state->wrap && out) strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); strm->data_type = state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) ret = Z_BUF_ERROR; return ret; } int ZEXPORT inflateEnd(strm) z_streamp strm; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) z_streamp strm; Bytef *dictionary; uInt *dictLength; { struct inflate_state FAR *state; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* copy dictionary */ if (state->whave && dictionary != Z_NULL) { zmemcpy(dictionary, state->window + state->wnext, state->whave - state->wnext); zmemcpy(dictionary + state->whave - state->wnext, state->window, state->wnext); } if (dictLength != Z_NULL) *dictLength = state->whave; return Z_OK; } int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; { struct inflate_state FAR *state; unsigned long dictid; int ret; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; /* check for correct dictionary identifier */ if (state->mode == DICT) { dictid = adler32(0L, Z_NULL, 0); dictid = adler32(dictid, dictionary, dictLength); if (dictid != state->check) return Z_DATA_ERROR; } /* copy dictionary to window using updatewindow(), which will amend the existing dictionary if appropriate */ ret = updatewindow(strm, dictionary + dictLength, dictLength); if (ret) { state->mode = MEM; return Z_MEM_ERROR; } state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; } int ZEXPORT inflateGetHeader(strm, head) z_streamp strm; gz_headerp head; { struct inflate_state FAR *state; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; /* save header structure */ state->head = head; head->done = 0; return Z_OK; } /* Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found or when out of input. When called, *have is the number of pattern bytes found in order so far, in 0..3. On return *have is updated to the new state. If on return *have equals four, then the pattern was found and the return value is how many bytes were read including the last byte of the pattern. If *have is less than four, then the pattern has not been found yet and the return value is len. In the latter case, syncsearch() can be called again with more data and the *have state. *have is initialized to zero for the first call. */ local unsigned syncsearch(have, buf, len) unsigned FAR *have; const unsigned char FAR *buf; unsigned len; { unsigned got; unsigned next; got = *have; next = 0; while (next < len && got < 4) { if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) got++; else if (buf[next]) got = 0; else got = 4 - got; next++; } *have = got; return next; } int ZEXPORT inflateSync(strm) z_streamp strm; { unsigned len; /* number of bytes to look at or looked at */ unsigned long in, out; /* temporary to save total_in and total_out */ unsigned char buf[4]; /* to restore bit buffer to byte string */ struct inflate_state FAR *state; /* check parameters */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; /* if first time, start search in bit buffer */ if (state->mode != SYNC) { state->mode = SYNC; state->hold <<= state->bits & 7; state->bits -= state->bits & 7; len = 0; while (state->bits >= 8) { buf[len++] = (unsigned char)(state->hold); state->hold >>= 8; state->bits -= 8; } state->have = 0; syncsearch(&(state->have), buf, len); } /* search available input */ len = syncsearch(&(state->have), strm->next_in, strm->avail_in); strm->avail_in -= len; strm->next_in += len; strm->total_in += len; /* return no joy or set up to restart inflate() on a new block */ if (state->have != 4) return Z_DATA_ERROR; in = strm->total_in; out = strm->total_out; inflateReset(strm); strm->total_in = in; strm->total_out = out; state->mode = TYPE; return Z_OK; } /* Returns true if inflate is currently at the end of a block generated by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored block. When decompressing, PPP checks that at the end of input packet, inflate is waiting for these length bytes. */ int ZEXPORT inflateSyncPoint(strm) z_streamp strm; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; return state->mode == STORED && state->bits == 0; } int ZEXPORT inflateCopy(dest, source) z_streamp dest; z_streamp source; { struct inflate_state FAR *state; struct inflate_state FAR *copy; unsigned char FAR *window; unsigned wsize; /* check input */ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)source->state; /* allocate space */ copy = (struct inflate_state FAR *) ZALLOC(source, 1, sizeof(struct inflate_state)); if (copy == Z_NULL) return Z_MEM_ERROR; window = Z_NULL; if (state->window != Z_NULL) { window = (unsigned char FAR *) ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); if (window == Z_NULL) { ZFREE(source, copy); return Z_MEM_ERROR; } } /* copy state */ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); copy->distcode = copy->codes + (state->distcode - state->codes); } copy->next = copy->codes + (state->next - state->codes); if (window != Z_NULL) { wsize = 1U << state->wbits; zmemcpy(window, state->window, wsize); } copy->window = window; dest->state = (struct internal_state FAR *)copy; return Z_OK; } int ZEXPORT inflateUndermine(strm, subvert) z_streamp strm; int subvert; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; state->sane = !subvert; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR return Z_OK; #else state->sane = 1; return Z_DATA_ERROR; #endif } long ZEXPORT inflateMark(strm) z_streamp strm; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; state = (struct inflate_state FAR *)strm->state; return ((long)(state->back) << 16) + (state->mode == COPY ? state->length : (state->mode == MATCH ? state->was - state->length : 0)); } tcl8.6.5/compat/zlib/CMakeLists.txt0000644000175000017500000001764212663660064016563 0ustar sergeisergeicmake_minimum_required(VERSION 2.4.4) set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) project(zlib C) set(VERSION "1.2.8") option(ASM686 "Enable building i686 assembly implementation") option(AMD64 "Enable building amd64 assembly implementation") set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") include(CheckTypeSize) include(CheckFunctionExists) include(CheckIncludeFile) include(CheckCSourceCompiles) enable_testing() check_include_file(sys/types.h HAVE_SYS_TYPES_H) check_include_file(stdint.h HAVE_STDINT_H) check_include_file(stddef.h HAVE_STDDEF_H) # # Check to see if we have large file support # set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) # We add these other definitions here because CheckTypeSize.cmake # in CMake 2.4.x does not automatically do so and we want # compatibility with CMake 2.4.x. if(HAVE_SYS_TYPES_H) list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) endif() if(HAVE_STDINT_H) list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) endif() if(HAVE_STDDEF_H) list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) endif() check_type_size(off64_t OFF64_T) if(HAVE_OFF64_T) add_definitions(-D_LARGEFILE64_SOURCE=1) endif() set(CMAKE_REQUIRED_DEFINITIONS) # clear variable # # Check for fseeko # check_function_exists(fseeko HAVE_FSEEKO) if(NOT HAVE_FSEEKO) add_definitions(-DNO_FSEEKO) endif() # # Check for unistd.h # check_include_file(unistd.h Z_HAVE_UNISTD_H) if(MSVC) set(CMAKE_DEBUG_POSTFIX "d") add_definitions(-D_CRT_SECURE_NO_DEPRECATE) add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) endif() if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) # If we're doing an out of source build and the user has a zconf.h # in their source tree... if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) message(STATUS "Renaming") message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") message(STATUS "to 'zconf.h.included' because this file is included with zlib") message(STATUS "but CMake generates it automatically in the build directory.") file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) endif() endif() set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein ${ZLIB_PC} @ONLY) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) #============================================================================ # zlib #============================================================================ set(ZLIB_PUBLIC_HDRS ${CMAKE_CURRENT_BINARY_DIR}/zconf.h zlib.h ) set(ZLIB_PRIVATE_HDRS crc32.h deflate.h gzguts.h inffast.h inffixed.h inflate.h inftrees.h trees.h zutil.h ) set(ZLIB_SRCS adler32.c compress.c crc32.c deflate.c gzclose.c gzlib.c gzread.c gzwrite.c inflate.c infback.c inftrees.c inffast.c trees.c uncompr.c zutil.c ) if(NOT MINGW) set(ZLIB_DLL_SRCS win32/zlib1.rc # If present will override custom build rule below. ) endif() if(CMAKE_COMPILER_IS_GNUCC) if(ASM686) set(ZLIB_ASMS contrib/asm686/match.S) elseif (AMD64) set(ZLIB_ASMS contrib/amd64/amd64-match.S) endif () if(ZLIB_ASMS) add_definitions(-DASMV) set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE) endif() endif() if(MSVC) if(ASM686) ENABLE_LANGUAGE(ASM_MASM) set(ZLIB_ASMS contrib/masmx86/inffas32.asm contrib/masmx86/match686.asm ) elseif (AMD64) ENABLE_LANGUAGE(ASM_MASM) set(ZLIB_ASMS contrib/masmx64/gvmat64.asm contrib/masmx64/inffasx64.asm ) endif() if(ZLIB_ASMS) add_definitions(-DASMV -DASMINF) endif() endif() # parse the full version number from zlib.h and include in ZLIB_FULL_VERSION file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) if(MINGW) # This gets us DLL resource information when compiling on MinGW. if(NOT CMAKE_RC_COMPILER) set(CMAKE_RC_COMPILER windres.exe) endif() add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj COMMAND ${CMAKE_RC_COMPILER} -D GCC_WINDRES -I ${CMAKE_CURRENT_SOURCE_DIR} -I ${CMAKE_CURRENT_BINARY_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) endif(MINGW) add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) set_target_properties(zlib PROPERTIES SOVERSION 1) if(NOT CYGWIN) # This property causes shared libraries on Linux to have the full version # encoded into their final filename. We disable this on Cygwin because # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll # seems to be the default. # # This has no effect with MSVC, on that platform the version info for # the DLL comes from the resource file win32/zlib1.rc set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION}) endif() if(UNIX) # On unix-like platforms the library is almost always called libz set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) if(NOT APPLE) set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") endif() elseif(BUILD_SHARED_LIBS AND WIN32) # Creates zlib1.dll when building shared library version set_target_properties(zlib PROPERTIES SUFFIX "1.dll") endif() if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) install(TARGETS zlib zlibstatic RUNTIME DESTINATION "${INSTALL_BIN_DIR}" ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) endif() if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}") endif() if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3") endif() if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}") endif() #============================================================================ # Example binaries #============================================================================ add_executable(example test/example.c) target_link_libraries(example zlib) add_test(example example) add_executable(minigzip test/minigzip.c) target_link_libraries(minigzip zlib) if(HAVE_OFF64_T) add_executable(example64 test/example.c) target_link_libraries(example64 zlib) set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") add_test(example64 example64) add_executable(minigzip64 test/minigzip.c) target_link_libraries(minigzip64 zlib) set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") endif() tcl8.6.5/compat/zlib/zlib.3.pdf0000644000175000017500000002103612663660065015610 0ustar sergeisergei%PDF-1.4 %Çì¢ 5 0 obj <> stream xœ¥Zɒܸ½÷Wà6¬ˆ.\äËôH²C²6KŽðtÏÍbWqšE–¸¨§uðØŸât&6‚µH3vèÐ¥"˜Häòòe¢>“2â?ó·Ø]¬>&dÓ_„dsñù‚©‡Äü)vä§kXâ×÷úFN’("×» ‘¥T§Njàç7¯~º Ä킸O‹ë_áí Þ¦™D"&×o.‚wWo_.~ðÃ÷KÆÉõÔ@Y_ëêŽü‡ínß•}_µÍj]zÿ#ð¼Cé,Îhœ€Rðê’Ó(U¯çy:Ú{ÉC‰k—,¦)®>ýãÝûŸ^}ÒKu nú²ÔYhžrFÓ8ËôŽ7JÑEt»øåúõÅ2¤‚\ž4S‘f©^Ü·(ŽÓ$ÅU) Á~‘yÖÝã³P?HS÷@Yä&뚬˾èK&i&"¨öØâµóü¨,d”¥™wÖ/?=ÿøêÃõ«÷ïÎ÷z{tÚrá´W‡½ÌR›‡Î#^ Ù9—°„†,äæh4Œô骞ädS6e·€S„,Šƒ¼&ûN+Â`ßö%YçCNŽbÏÎÒ”&òÜŽàt´)èÅ&GÐkglÁöÕ(Ø–°×º$ Ø°íÊ|Mú\9\Ì$¾—q{ï ý^yIòItL¥ – ïÇ]Õl”‘E4I\ÐÓ,ÎÔëÃ6`Ã’ôCÞ¬óní"=°(áß°k&2fµ±òîǦÀ éÉØ—k’wå¹ã0Á©Æ›Œr#ÎÓûç9µÉXlIÞ“]¹k•ª½ËcIešØã?å¾É…Y¢ÄÔu[ä¨,éÚq¨šRm &T)•HšJë½W“(NÃÉ­ƒ:RÄ3ÊYæâzß©´Ã]í–‰”jÏ/䩚¥§¼ZûŒ‚—œöÅ´¥Zb´¼€‘9L9óÏ$³4¦±°‡¹¬¼¼‡ÌfTSÔãÔJ6ÖW1§BJfc ib‘ix"Ŷ,,£Y*£à¡'í=†–*‡4#Ãu<ÂFL9ª‚ŒÙ@ƵL§íõòãË‚G°Ï‚²S§ÖûxùBhY8;º)å’M‘-ôã~ÜïÛŽ Êv§) Ú¦~"mSÎpaWÛvMnƒuùï|©"‚£Åây‘Áj(Ww Ž#³`H šw$¯7--œ+ãIP ÛÄw®NcÑ›´gÜšû ¤$)Š J½N9„'€Þë5XµÎØâ„êLÏw˜î”;åi¨ÂB`Q.Øgi@µß˜Œ(‹'`gTr>Ï=yCî2Ñ4&é!ŽjܦܓJ»GA9 MÌ㽂àÔs¶ä±F‚®WøQçݦ$eÓŽ›-ù{ÝirÊB›’O&%ÁX`x’äïÊ} Yƒœº¶1JN%],ã0¤L‚Wް|@Sy¯£JOi³Ã±¤M¤ËÁ¯¬ÒC0ɤÖ„åû}]Ú¹*4öAüÀPÀ4BÀ &8œÄÍãªjöI€+4dÿ¸+•¾køä6°1¸@"&9Ê´ ú=x#³¼_–©eø¸ÌiÑN:t ¼ÁsÄήmÚýp!MCù­:<˜pU·o‰N½Å2 5Ñz‚5ÕDŒ{œ¥~û¯Z¡¨a"Ž>°TRæ€nóµÚЇŒ2iÁmÀàÌ·Ý|…¿*#æ±§%W¥Ó¾ƒdTNë0pèt U*» 0½„ £  RaWA „¸d";†–¨B ÁØëª]XCh»‡4ÓSöŽÒo™;I]ÜÙ÷×-Ø­iÐ >0¼¼Ñ•N­Â•Sž—J½_ƒ`‰'OWâjÓmÚ‚“ê²ÓÕ“ÅJ’„Ä‘ÖÒ>ûx‘ŽÎÂq°€­1©lñÈ$Ã⡳²é+À¦xòuiRË0™y¿’“h§Â €êàyF#Á°®Õ%aÛŽõš4¥a.\UÃHÐ0¶l"øRúÒxbAWXÊ£žGöžåH$ý†MÉ|?ô~c³› © $-KEÐ ^I`À-AV&GüB{mg2 ‘fÜ#**,1ØÏ£jö„ýPÁ uº‚Й¨Þ u&—Ð/Åg¹2„iäHæ$aÝcÖIɇ¤?hRÁ噿(†HKº#AãÉsRžE±W Kˆ;ÍÏDb¹nH ¹ÒÐUœQAxߎ]¡'À ¡˜Pš¦‚Y¤FŽ9X*œEó[¾Û#šGí–9—Þ”Äñ7 ¾u4“Åú“Eô‘¶²VF­‹«´0kÍC$ÆÜÚ²þDû–q>“-H¥XXbQè B\Êqï4܉ž<.PÇ0J‚a«7pš"]OàTsªÒ•2kbm•ƒÆÙ)œ3ty”¿M±§šò]ËZ4µ‰JáC/­«®,†Öø ÅSs«xî’¥B÷e6Åô ž¤n@cU&Ê1KyÏgÈAIäð"·{j±oÚÍ\{ }›f ªå¦sÞT¥†bÞßHSèá>Kž@¦3op²{—“!±ŸãœÎ<ájî;ÀÇ9¨¦wºÍ{ÔŠp¾¶Nå  ‘°;Oæ_0Óá|ô+œkœ‘bà¡+‚“Üó R@„šBÌàUŠìc-È7å3Cª!2£Ð7ÖvöÏV«ƒ ¡EŽ¿³[@û±¡à«Õz^5ow\GŽã×§ö§n÷e·ÊbÛ+­¯ ª ŒôŽWÆ  D–c­b;=¬üš&‘î(!\Š…g«~ÛÏ¥G%caR›¾:¶ã—À.ô0£™…ªáUH lh€J`„Í™œv^ÈB‡;¹üòÑ·ìdW@»Ð¹l.±¶Ÿ¼SñR9EfMÞæÝ笇~÷¹ÿ±€|¤m·¹]\’ãì‰c(Tß‹•;ª.{¹vƒY9ÿüÂéÖ4¸z›>w\KH4XìM8Êm Ül–ZÀ‹zÎŽ%ýp;vf8âUWlçB9ö *¿ó‰¤&åðhŽM_ð>è¡0W>³Ù=èªè¶â1YÈ ¨OeÞŽGžiàŽ ;ˆN¤p_æpj}µú'ºnõêýÒöËËŸ!ÜT6ÀÑ™Ò`)â3™€,:IÝBç*tÿö5PGl¤36Œ¡íX\¨»­g¨ëõ¿+Òh®˜k&®|×ÅnN‡§Êô©è[Jþª{'à c±­ˆo¡ä>ü¸Ë7M9 й路5Ä<û.ZžŒSD>(«:Ç—Îy£Rõ£z 5ÙÌÅuMî5¸û®¼±A¥º×µSfÝk—ÁGµ£ “‰ðA›` Úœï­N1ÌK·Ã®>À·%K°ÕýýÕ8tcñ©´ŽUâqH‡Lyh±f(êgsÉKí&¡8NŽÇê¡¢ðV0qmìØo1ÔD[ŒF·A\uÙGÅà7¨V¤Bú“«ÃC¹óÂë®öræˆ}£J1r+5˜ö' H‚ì|¨"~¯ý"±·pl6¸4n‰Ohúzbv¨%ð­ë¯§³B.í¸ÿ!YˆJØaîZš3seêM%âLï|÷DþâòÊ#Þ1m­×T5õïÊÒê€v·¶^šIZˆ·C©Pç ΕªæÞÅrûã#P}ÈÓrŠôóé* Æÿ¦~Q5Ê(†³´‰öøø¸†öÓIãZÅ“¾¾©î^ÔµjL°/QÎMR ÂLS•Y*>ԔʴsePŸÜ@crzÑ6øýÎí2Kè£ÿ¥“í7›×¡ýô2Ï<©îòª9 ¶ÌƒçLþßšà›¾wºòÓöGsŽz&zâò?Mý{Η/ÉÕ›Oïz¤ï]ü‡9; s¯ä?Îg!Ü›rwóÉ•7Çì6d3¦ƒS¶#úØOu!<Ž.3`0³9¨G+{¹áÈY4 ëÔ%¢-&4äçðÃŒ1UE+EÝ£ ™quVWa®®NÃf¬¡+¸°»ºÖ¶£P€Ÿ:ïV„±tÚ=qÁÞc%)„„RHÏ¿3®&,1|–ú?}ô™–Hje~<>ð"„ñþvAX&CKa–<ŽhÉy¬Ã îu»½ª<'KîжµWs«r˜ü­*.&÷ª»/Ô¦· ¯Œ·… ÷3 ‰„ òª†/u]à l‘v«&ŸK³dŽ ÿƒšì”šxé4LÃ73û´Ê¥êçßTN/ù¿•ã§”ÃÁÏ Yx`¾Ôµ-g4xc e¡A"*w€ˆr6]³$fÞö®àn ¼·`¢Ç&‹¥Pƒ$¨ö–äwí8Ý#”'éàÇxŸ ¬óÍ-n$;ñk‹)M3ìQ²ÈÈ¾Ö òšÈ‚,’Ù8 4šè¨ÕçE7ÛoŽÜEõ‹î¹[Λ ½SWLH¬ï~0Ék¤öž:è_Ÿ~ßóÌØ‘&¯ÿdUPLDD”%Ì \fW×sÃv?{kvï<µgÞº74$£ücˆY—b‰Ò.=f1S?pùÓ%[2Sx–ZE%€øjß2¡ã[#Ÿá7/¯/þÿþ ú’ZCendstream endobj 6 0 obj 3483 endobj 14 0 obj <> stream xœ}WÛrãD}÷WLñ$Sñd® ^ö²,d/dÍ¥H(J±'¶XYr$9Æû ðÏtÏE²½ åTÅÖÌôtŸ>}ºõ@å„á'ü_l&—׆¬º #«ÉÄ»Eþ-6äÙ6dø`~?ñg81‚¥È|3‘yF5|ÛO’ß®^=»Mäí” ß¦ó?'°w&S2_Nf‚¦Òm]÷ýö«ËËMÑ’µ­º¦¦»î’ç¹¹dÿ>VåÝÌÖ«²¶—häò:h®Ñ‹šä)ÍÐ(Cƒ7Éõ‹wo¯§‚QÆt2õæ%y7ü|ûìêÅë÷Óßçß….͸@ É3{wpE gD³4Í2çkÓZÒÚmÓâÅiªM6î1þú¾¬W¤ Û¶¹s·rÓÊn.ȶ²EgÉbmÎIU g.ME°”|èÑ:s œ •æaam}øœÅ€—Æ„U„ ×g˜N8{”©üØÊÞY9º8Ï™@ö‘®/«ŠX‡¸)Í㥕]ï²ÈæÊÝÓL‡Uúîz¦éaÒ—º'uk‹¥CYfŠ e,¨þSÖBµ¦ù9°À‚ì WP“4ÖàŒSåkðÛ§äÇÁ'àšÙ ¶Šþ+gJ@eâ ƒ0ÜD•q·)”#ZÛÞ=ùã~*YR<Ðu¿©<'$„ÓÉ]IÓ1zéi’Pt°æÑJ wKÖ¶Ú:S«Ë5cX ›¾?ÅUކ…7l!¡;È5d·Ãô^‚ÕE³Ùغï°Ñó'«åv*µ¿–6íê‚À¶ÛÄEß ¿”õ²ñŠÃ4UƒÐì»±.²˜° ¡ß\]!Ç´GÊs Ô®} <²ùyjrOÀ¦ªŠº‡;ËÚ#€'š'û².7ÅÊNyôœ¿ÒXóZ…|«ù ìO1ÒT¤2ªÑü»·×ï?O#A’"ý~¶Çbªd¬57æùäË„L=o¶®MiªE*Î%î·Z;-’œÊÌäg¶n’Ûä9 ÍKσÿÞõ¬jv[ò²Ü€ÒŸø3ä Kšæ Ža ¿.ÚÀ“¹Ð„2{ÃÓ1œ Ô2¶ŸdYÙ6dSS9Æ›l \{RT»M]ÒEQõv±¦v¹Ã\ «ÜWŒ(Å(æ_Þ$óuÙ‘®¹ï÷SèND :<aqe*OË¥]’/ŠnVvn_&òäâ ²/ûu³ë! ‹¢ìà˜ÍUDÃ'—+IÇ Ék'ùmë!ºœrh81<„°µCtJSΆ™Éõ5 B†òàžAß—ÞO.%sO Ýþ¸µêÔlÿnO\ó–-eä,`¢e¤Ä¦p’$ršªô×%¹ s[f†";œu妽”n˜Ô§ ;ÃZ‚³/<%§$”ƒÌ&Ýò¸Èå@IPü@jûw=xm`°Ã$˜ÞsK S¶.+òCÑt:Édƒ< yíÌÏ‘}GÐ׳  RU‹³ O&g-ãúM‚¬*ÿ^¾%ï½ü¸öhÉ>–ÈQÙ÷¶†üo´g”00õéhëp5•Øgx†3îô9Ö-ÛÃXýÝõH¶WÃaÖã«}žQ²‹úƒ ¯Ddkxå ûu^Zf*èeˆŸOˆ!w+ \ ôÅì¼»ZÙìºÐ ’zÝžÖL©Ã,ù_ò9‘ø2-ë³4AjÓì²t:€û6å øùTƒP`뛆Ô.}\çÉnc[ˆ¡[à‹ ê8µ$~TÉh.b[üéÍ«_¡ÞŽŽÙ‚´†dÈa÷ÃÜ?èÜázʹ39&›KPAy>åØñëõH,EÁ6ËL_®QÆ¡’ÕH’‹qL‚ÁJOœhòx,Çœ„¥7ÇgÌpƒå>ÅHrˆîª¼óÂm`°b£þM.‚ä˜ÅWŠÑ4”× Ž xuØ›}ç¥Öø¤®6´.×4ÚMŠ'qZDè L†JBC:À÷é¶%8hy4­%øäÅ|ò#|þ”B3©endstream endobj 15 0 obj 1968 endobj 4 0 obj <> /Contents 5 0 R >> endobj 13 0 obj <> /Contents 14 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 13 0 R ] /Count 2 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 11 0 obj <> endobj 12 0 obj <> endobj 16 0 obj <> endobj 17 0 obj <> endobj 10 0 obj <> endobj 9 0 obj <> endobj 8 0 obj <> endobj 18 0 obj <> endobj 19 0 obj <>stream 2013-04-28T16:03:13-07:00 2013-04-28T16:03:13-07:00 groff version 1.19.2 Untitled endstream endobj 2 0 obj <>endobj xref 0 20 0000000000 65535 f 0000006037 00000 n 0000008027 00000 n 0000005971 00000 n 0000005649 00000 n 0000000015 00000 n 0000003568 00000 n 0000006102 00000 n 0000006445 00000 n 0000006376 00000 n 0000006303 00000 n 0000006143 00000 n 0000006173 00000 n 0000005809 00000 n 0000003588 00000 n 0000005628 00000 n 0000006223 00000 n 0000006253 00000 n 0000006525 00000 n 0000006604 00000 n trailer << /Size 20 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 8181 %%EOF tcl8.6.5/compat/zlib/uncompr.c0000644000175000017500000000372312663660065015646 0ustar sergeisergei/* uncompr.c -- decompress a memory buffer * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #define ZLIB_INTERNAL #include "zlib.h" /* =========================================================================== Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the compressed buffer. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted. */ int ZEXPORT uncompress (dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; uLong sourceLen; { z_stream stream; int err; stream.next_in = (z_const Bytef *)source; stream.avail_in = (uInt)sourceLen; /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; stream.next_out = dest; stream.avail_out = (uInt)*destLen; if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; err = inflateInit(&stream); if (err != Z_OK) return err; err = inflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { inflateEnd(&stream); if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) return Z_DATA_ERROR; return err; } *destLen = stream.total_out; err = inflateEnd(&stream); return err; } tcl8.6.5/compat/zlib/trees.c0000644000175000017500000012633712663660065015314 0ustar sergeisergei/* trees.c -- output deflated data using Huffman coding * Copyright (C) 1995-2012 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process uses several Huffman trees. The more * common source values are represented by shorter bit sequences. * * Each code tree is stored in a compressed form which is itself * a Huffman encoding of the lengths of all the code strings (in * ascending order by source values). The actual code strings are * reconstructed from the lengths in the inflate process, as described * in the deflate specification. * * REFERENCES * * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc * * Storer, James A. * Data Compression: Methods and Theory, pp. 49-50. * Computer Science Press, 1988. ISBN 0-7167-8156-5. * * Sedgewick, R. * Algorithms, p290. * Addison-Wesley, 1983. ISBN 0-201-06672-6. */ /* @(#) $Id$ */ /* #define GEN_TREES_H */ #include "deflate.h" #ifdef DEBUG # include #endif /* =========================================================================== * Constants */ #define MAX_BL_BITS 7 /* Bit length codes must not exceed MAX_BL_BITS bits */ #define END_BLOCK 256 /* end of block literal code */ #define REP_3_6 16 /* repeat previous bit length 3-6 times (2 bits of repeat count) */ #define REPZ_3_10 17 /* repeat a zero length 3-10 times (3 bits of repeat count) */ #define REPZ_11_138 18 /* repeat a zero length 11-138 times (7 bits of repeat count) */ local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; local const int extra_dbits[D_CODES] /* extra bits for each distance code */ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; local const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; /* The lengths of the bit length codes are sent in order of decreasing * probability, to avoid transmitting the lengths for unused bit length codes. */ /* =========================================================================== * Local data. These are initialized only once. */ #define DIST_CODE_LEN 512 /* see definition of array dist_code below */ #if defined(GEN_TREES_H) || !defined(STDC) /* non ANSI compilers may not accept trees.h */ local ct_data static_ltree[L_CODES+2]; /* The static literal tree. Since the bit lengths are imposed, there is no * need for the L_CODES extra codes used during heap construction. However * The codes 286 and 287 are needed to build a canonical tree (see _tr_init * below). */ local ct_data static_dtree[D_CODES]; /* The static distance tree. (Actually a trivial tree since all codes use * 5 bits.) */ uch _dist_code[DIST_CODE_LEN]; /* Distance codes. The first 256 values correspond to the distances * 3 .. 258, the last 256 values correspond to the top 8 bits of * the 15 bit distances. */ uch _length_code[MAX_MATCH-MIN_MATCH+1]; /* length code for each normalized match length (0 == MIN_MATCH) */ local int base_length[LENGTH_CODES]; /* First normalized length for each code (0 = MIN_MATCH) */ local int base_dist[D_CODES]; /* First normalized distance for each code (0 = distance of 1) */ #else # include "trees.h" #endif /* GEN_TREES_H */ struct static_tree_desc_s { const ct_data *static_tree; /* static tree or NULL */ const intf *extra_bits; /* extra bits for each code or NULL */ int extra_base; /* base index for extra_bits */ int elems; /* max number of elements in the tree */ int max_length; /* max bit length for the codes */ }; local static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; local static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; local static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== * Local (static) routines in this file. */ local void tr_static_init OF((void)); local void init_block OF((deflate_state *s)); local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); local void build_tree OF((deflate_state *s, tree_desc *desc)); local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); local int build_bl_tree OF((deflate_state *s)); local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, int blcodes)); local void compress_block OF((deflate_state *s, const ct_data *ltree, const ct_data *dtree)); local int detect_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); local void bi_flush OF((deflate_state *s)); local void copy_block OF((deflate_state *s, charf *buf, unsigned len, int header)); #ifdef GEN_TREES_H local void gen_trees_header OF((void)); #endif #ifndef DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ #else /* DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } #endif /* =========================================================================== * Output a short LSB first on the stream. * IN assertion: there is enough room in pendingBuf. */ #define put_short(s, w) { \ put_byte(s, (uch)((w) & 0xff)); \ put_byte(s, (uch)((ush)(w) >> 8)); \ } /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ #ifdef DEBUG local void send_bits OF((deflate_state *s, int value, int length)); local void send_bits(s, value, length) deflate_state *s; int value; /* value to send */ int length; /* number of bits */ { Tracevv((stderr," l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); s->bits_sent += (ulg)length; /* If not enough room in bi_buf, use (valid) bits from bi_buf and * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) * unused bits in value. */ if (s->bi_valid > (int)Buf_size - length) { s->bi_buf |= (ush)value << s->bi_valid; put_short(s, s->bi_buf); s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); s->bi_valid += length - Buf_size; } else { s->bi_buf |= (ush)value << s->bi_valid; s->bi_valid += length; } } #else /* !DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ int val = value;\ s->bi_buf |= (ush)val << s->bi_valid;\ put_short(s, s->bi_buf);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ s->bi_valid += len - Buf_size;\ } else {\ s->bi_buf |= (ush)(value) << s->bi_valid;\ s->bi_valid += len;\ }\ } #endif /* DEBUG */ /* the arguments must not have side effects */ /* =========================================================================== * Initialize the various 'constant' tables. */ local void tr_static_init() { #if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ int bits; /* bit counter */ int length; /* length value */ int code; /* code value */ int dist; /* distance index */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ if (static_init_done) return; /* For some embedded targets, global variables are not initialized: */ #ifdef NO_INIT_GLOBAL_POINTERS static_l_desc.static_tree = static_ltree; static_l_desc.extra_bits = extra_lbits; static_d_desc.static_tree = static_dtree; static_d_desc.extra_bits = extra_dbits; static_bl_desc.extra_bits = extra_blbits; #endif /* Initialize the mapping length (0..255) -> length code (0..28) */ length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; for (n = 0; n < (1< dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { _dist_code[256 + dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: 256+dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; n = 0; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; /* Codes 286 and 287 do not exist, but we must include them in the * tree construction to get a canonical Huffman tree (longest code * all ones) */ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); /* The static distance tree is trivial: */ for (n = 0; n < D_CODES; n++) { static_dtree[n].Len = 5; static_dtree[n].Code = bi_reverse((unsigned)n, 5); } static_init_done = 1; # ifdef GEN_TREES_H gen_trees_header(); # endif #endif /* defined(GEN_TREES_H) || !defined(STDC) */ } /* =========================================================================== * Genererate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef DEBUG # include # endif # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ ((i) % (width) == (width)-1 ? ",\n" : ", ")) void gen_trees_header() { FILE *header = fopen("trees.h", "w"); int i; Assert (header != NULL, "Can't open trees.h"); fprintf(header, "/* header created automatically with -DGEN_TREES_H */\n\n"); fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); for (i = 0; i < L_CODES+2; i++) { fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); } fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); } fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); for (i = 0; i < DIST_CODE_LEN; i++) { fprintf(header, "%2u%s", _dist_code[i], SEPARATOR(i, DIST_CODE_LEN-1, 20)); } fprintf(header, "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { fprintf(header, "%2u%s", _length_code[i], SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); } fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); for (i = 0; i < LENGTH_CODES; i++) { fprintf(header, "%1u%s", base_length[i], SEPARATOR(i, LENGTH_CODES-1, 20)); } fprintf(header, "local const int base_dist[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "%5u%s", base_dist[i], SEPARATOR(i, D_CODES-1, 10)); } fclose(header); } #endif /* GEN_TREES_H */ /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ void ZLIB_INTERNAL _tr_init(s) deflate_state *s; { tr_static_init(); s->l_desc.dyn_tree = s->dyn_ltree; s->l_desc.stat_desc = &static_l_desc; s->d_desc.dyn_tree = s->dyn_dtree; s->d_desc.stat_desc = &static_d_desc; s->bl_desc.dyn_tree = s->bl_tree; s->bl_desc.stat_desc = &static_bl_desc; s->bi_buf = 0; s->bi_valid = 0; #ifdef DEBUG s->compressed_len = 0L; s->bits_sent = 0L; #endif /* Initialize the first block of the first file: */ init_block(s); } /* =========================================================================== * Initialize a new block. */ local void init_block(s) deflate_state *s; { int n; /* iterates over tree elements */ /* Initialize the trees. */ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; s->dyn_ltree[END_BLOCK].Freq = 1; s->opt_len = s->static_len = 0L; s->last_lit = s->matches = 0; } #define SMALLEST 1 /* Index within the heap array of least frequent node in the Huffman tree */ /* =========================================================================== * Remove the smallest element from the heap and recreate the heap with * one less element. Updates heap and heap_len. */ #define pqremove(s, tree, top) \ {\ top = s->heap[SMALLEST]; \ s->heap[SMALLEST] = s->heap[s->heap_len--]; \ pqdownheap(s, tree, SMALLEST); \ } /* =========================================================================== * Compares to subtrees, using the tree depth as tie breaker when * the subtrees have equal frequency. This minimizes the worst case length. */ #define smaller(tree, n, m, depth) \ (tree[n].Freq < tree[m].Freq || \ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) /* =========================================================================== * Restore the heap property by moving down the tree starting at node k, * exchanging a node with the smallest of its two sons if necessary, stopping * when the heap property is re-established (each father smaller than its * two sons). */ local void pqdownheap(s, tree, k) deflate_state *s; ct_data *tree; /* the tree to restore */ int k; /* node to move down */ { int v = s->heap[k]; int j = k << 1; /* left son of k */ while (j <= s->heap_len) { /* Set j to the smallest of the two sons: */ if (j < s->heap_len && smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ if (smaller(tree, v, s->heap[j], s->depth)) break; /* Exchange v with the smallest son */ s->heap[k] = s->heap[j]; k = j; /* And continue down the tree, setting j to the left son of k */ j <<= 1; } s->heap[k] = v; } /* =========================================================================== * Compute the optimal bit lengths for a tree and update the total bit length * for the current block. * IN assertion: the fields freq and dad are set, heap[heap_max] and * above are the tree nodes sorted by increasing frequency. * OUT assertions: the field len is set to the optimal bit length, the * array bl_count contains the frequencies for each bit length. * The length opt_len is updated; static_len is also updated if stree is * not null. */ local void gen_bitlen(s, desc) deflate_state *s; tree_desc *desc; /* the tree descriptor */ { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; const ct_data *stree = desc->stat_desc->static_tree; const intf *extra = desc->stat_desc->extra_bits; int base = desc->stat_desc->extra_base; int max_length = desc->stat_desc->max_length; int h; /* heap index */ int n, m; /* iterate over the tree elements */ int bits; /* bit length */ int xbits; /* extra bits */ ush f; /* frequency */ int overflow = 0; /* number of elements with bit length too large */ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; /* In a first pass, compute the optimal bit lengths (which may * overflow in the case of the bit length tree). */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ for (h = s->heap_max+1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; tree[n].Len = (ush)bits; /* We overwrite tree[n].Dad which is no longer needed */ if (n > max_code) continue; /* not a leaf node */ s->bl_count[bits]++; xbits = 0; if (n >= base) xbits = extra[n-base]; f = tree[n].Freq; s->opt_len += (ulg)f * (bits + xbits); if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); } if (overflow == 0) return; Trace((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ do { bits = max_length-1; while (s->bl_count[bits] == 0) bits--; s->bl_count[bits]--; /* move one leaf down the tree */ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] */ overflow -= 2; } while (overflow > 0); /* Now recompute all bit lengths, scanning in increasing frequency. * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all * lengths instead of fixing only the wrong ones. This idea is taken * from 'ar' written by Haruhiko Okumura.) */ for (bits = max_length; bits != 0; bits--) { n = s->bl_count[bits]; while (n != 0) { m = s->heap[--h]; if (m > max_code) continue; if ((unsigned) tree[m].Len != (unsigned) bits) { Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); s->opt_len += ((long)bits - (long)tree[m].Len) *(long)tree[m].Freq; tree[m].Len = (ush)bits; } n--; } } } /* =========================================================================== * Generate the codes for a given tree and bit counts (which need not be * optimal). * IN assertion: the array bl_count contains the bit length statistics for * the given tree and the field len is set for all tree elements. * OUT assertion: the field code is set for all tree elements of non * zero code length. */ local void gen_codes (tree, max_code, bl_count) ct_data *tree; /* the tree to decorate */ int max_code; /* largest code with non zero frequency */ ushf *bl_count; /* number of codes at each bit length */ { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ ush code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ /* The distribution counts are first used to generate the code values * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { next_code[bits] = code = (code + bl_count[bits-1]) << 1; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. */ Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; const ct_data *stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; int n, m; /* iterate over heap elements */ int max_code = -1; /* largest code with non zero frequency */ int node; /* new node being created */ /* Construct the initial heap, with least frequent element in * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. * heap[0] is not used. */ s->heap_len = 0, s->heap_max = HEAP_SIZE; for (n = 0; n < elems; n++) { if (tree[n].Freq != 0) { s->heap[++(s->heap_len)] = max_code = n; s->depth[n] = 0; } else { tree[n].Len = 0; } } /* The pkzip format requires that at least one distance code exists, * and that at least one bit should be sent even if there is only one * possible code. So to avoid special checks later on we force at least * two codes of non zero frequency. */ while (s->heap_len < 2) { node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); tree[node].Freq = 1; s->depth[node] = 0; s->opt_len--; if (stree) s->static_len -= stree[node].Len; /* node is 0 or 1 so it does not have extra bits */ } desc->max_code = max_code; /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); /* Construct the Huffman tree by repeatedly combining the least two * frequent nodes. */ node = elems; /* next internal node of the tree */ do { pqremove(s, tree, n); /* n = node of least frequency */ m = s->heap[SMALLEST]; /* m = node of next least frequency */ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ s->heap[--(s->heap_max)] = m; /* Create a new node father of n and m */ tree[node].Freq = tree[n].Freq + tree[m].Freq; s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? s->depth[n] : s->depth[m]) + 1); tree[n].Dad = tree[m].Dad = (ush)node; #ifdef DUMP_BL_TREE if (tree == s->bl_tree) { fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); } #endif /* and insert the new node in the heap */ s->heap[SMALLEST] = node++; pqdownheap(s, tree, SMALLEST); } while (s->heap_len >= 2); s->heap[--(s->heap_max)] = s->heap[SMALLEST]; /* At this point, the fields freq and dad are set. We can now * generate the bit lengths. */ gen_bitlen(s, (tree_desc *)desc); /* The field len is now set, we can generate the bit codes */ gen_codes ((ct_data *)tree, max_code, s->bl_count); } /* =========================================================================== * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ local void scan_tree (s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; tree[max_code+1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { s->bl_tree[curlen].Freq += count; } else if (curlen != 0) { if (curlen != prevlen) s->bl_tree[curlen].Freq++; s->bl_tree[REP_3_6].Freq++; } else if (count <= 10) { s->bl_tree[REPZ_3_10].Freq++; } else { s->bl_tree[REPZ_11_138].Freq++; } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ local void send_tree (s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ /* tree[max_code+1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { do { send_code(s, curlen, s->bl_tree); } while (--count != 0); } else if (curlen != 0) { if (curlen != prevlen) { send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); } else if (count <= 10) { send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); } else { send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ local int build_bl_tree(s) deflate_state *s; { int max_blindex; /* index of last bit length code of non zero freq */ /* Determine the bit length frequencies for literal and distance trees */ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); /* Build the bit length tree: */ build_tree(s, (tree_desc *)(&(s->bl_desc))); /* opt_len now includes the length of the tree representations, except * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format * requires that at least 4 bit length codes be sent. (appnote.txt says * 3 but the actual value used is 4.) */ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ s->opt_len += 3*(max_blindex+1) + 5+5+4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); return max_blindex; } /* =========================================================================== * Send the header for a block using dynamic Huffman trees: the counts, the * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ local void send_all_trees(s, lcodes, dcodes, blcodes) deflate_state *s; int lcodes, dcodes, blcodes; /* number of codes for each tree */ { int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ send_bits(s, dcodes-1, 5); send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } /* =========================================================================== * Send a stored block */ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) deflate_state *s; charf *buf; /* input block */ ulg stored_len; /* length of input block */ int last; /* one if this is the last block for a file */ { send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ #ifdef DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; #endif copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } /* =========================================================================== * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) */ void ZLIB_INTERNAL _tr_flush_bits(s) deflate_state *s; { bi_flush(s); } /* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. */ void ZLIB_INTERNAL _tr_align(s) deflate_state *s; { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); } /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and output the encoded block to the zip file. */ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) deflate_state *s; charf *buf; /* input block, or NULL if too old */ ulg stored_len; /* length of input block */ int last; /* one if this is the last block for a file */ { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex = 0; /* index of last bit length code of non zero freq */ /* Build the Huffman trees unless a stored block is forced */ if (s->level > 0) { /* Check if the file is binary or text */ if (s->strm->data_type == Z_UNKNOWN) s->strm->data_type = detect_data_type(s); /* Construct the literal and distance trees */ build_tree(s, (tree_desc *)(&(s->l_desc))); Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, s->static_len)); build_tree(s, (tree_desc *)(&(s->d_desc))); Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, s->static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ /* Build the bit length tree for the above two trees, and get the index * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute the block lengths in bytes. */ opt_lenb = (s->opt_len+3+7)>>3; static_lenb = (s->static_len+3+7)>>3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->last_lit)); if (static_lenb <= opt_lenb) opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ } #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else if (stored_len+4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since * the last block flush, because compression would have been * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * transform a block into a stored block. */ _tr_stored_block(s, buf, stored_len, last); #ifdef FORCE_STATIC } else if (static_lenb >= 0) { /* force static trees */ #else } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { #endif send_bits(s, (STATIC_TREES<<1)+last, 3); compress_block(s, (const ct_data *)static_ltree, (const ct_data *)static_dtree); #ifdef DEBUG s->compressed_len += 3 + s->static_len; #endif } else { send_bits(s, (DYN_TREES<<1)+last, 3); send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); compress_block(s, (const ct_data *)s->dyn_ltree, (const ct_data *)s->dyn_dtree); #ifdef DEBUG s->compressed_len += 3 + s->opt_len; #endif } Assert (s->compressed_len == s->bits_sent, "bad compressed size"); /* The above check is made mod 2^32, for files larger than 512 MB * and uLong implemented on 32 bits. */ init_block(s); if (last) { bi_windup(s); #ifdef DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, s->compressed_len-7*last)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ int ZLIB_INTERNAL _tr_tally (s, dist, lc) deflate_state *s; unsigned dist; /* distance of matched string */ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ { s->d_buf[s->last_lit] = (ush)dist; s->l_buf[s->last_lit++] = (uch)lc; if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; } else { s->matches++; /* Here, lc is the match length - MIN_MATCH */ dist--; /* dist = match distance - 1 */ Assert((ush)dist < (ush)MAX_DIST(s) && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } #ifdef TRUNCATE_BLOCK /* Try to guess if it is profitable to stop the current block here */ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { /* Compute an upper bound for the compressed length */ ulg out_length = (ulg)s->last_lit*8L; ulg in_length = (ulg)((long)s->strstart - s->block_start); int dcode; for (dcode = 0; dcode < D_CODES; dcode++) { out_length += (ulg)s->dyn_dtree[dcode].Freq * (5L+extra_dbits[dcode]); } out_length >>= 3; Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", s->last_lit, in_length, out_length, 100L - out_length*100L/in_length)); if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; } #endif return (s->last_lit == s->lit_bufsize-1); /* We avoid equality with lit_bufsize because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to * 64K-1 bytes. */ } /* =========================================================================== * Send the block data compressed using the given Huffman trees */ local void compress_block(s, ltree, dtree) deflate_state *s; const ct_data *ltree; /* literal tree */ const ct_data *dtree; /* distance tree */ { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ unsigned lx = 0; /* running index in l_buf */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ if (s->last_lit != 0) do { dist = s->d_buf[lx]; lc = s->l_buf[lx++]; if (dist == 0) { send_code(s, lc, ltree); /* send a literal byte */ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { /* Here, lc is the match length - MIN_MATCH */ code = _length_code[lc]; send_code(s, code+LITERALS+1, ltree); /* send the length code */ extra = extra_lbits[code]; if (extra != 0) { lc -= base_length[code]; send_bits(s, lc, extra); /* send the extra length bits */ } dist--; /* dist is now the match distance - 1 */ code = d_code(dist); Assert (code < D_CODES, "bad d_code"); send_code(s, code, dtree); /* send the distance code */ extra = extra_dbits[code]; if (extra != 0) { dist -= base_dist[code]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, "pendingBuf overflow"); } while (lx < s->last_lit); send_code(s, END_BLOCK, ltree); } /* =========================================================================== * Check if the data type is TEXT or BINARY, using the following algorithm: * - TEXT if the two conditions below are satisfied: * a) There are no non-portable control characters belonging to the * "black list" (0..6, 14..25, 28..31). * b) There is at least one printable character belonging to the * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). * - BINARY otherwise. * - The following partially-portable control characters form a * "gray list" that is ignored in this detection algorithm: * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). * IN assertion: the fields Freq of dyn_ltree are set. */ local int detect_data_type(s) deflate_state *s; { /* black_mask is the bit mask of black-listed bytes * set bits 0..6, 14..25, and 28..31 * 0xf3ffc07f = binary 11110011111111111100000001111111 */ unsigned long black_mask = 0xf3ffc07fUL; int n; /* Check for non-textual ("black-listed") bytes. */ for (n = 0; n <= 31; n++, black_mask >>= 1) if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) return Z_BINARY; /* Check for textual ("white-listed") bytes. */ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 || s->dyn_ltree[13].Freq != 0) return Z_TEXT; for (n = 32; n < LITERALS; n++) if (s->dyn_ltree[n].Freq != 0) return Z_TEXT; /* There are no "black-listed" or "white-listed" bytes: * this stream either is empty or has tolerated ("gray-listed") bytes only. */ return Z_BINARY; } /* =========================================================================== * Reverse the first len bits of a code, using straightforward code (a faster * method would use a table) * IN assertion: 1 <= len <= 15 */ local unsigned bi_reverse(code, len) unsigned code; /* the value to invert */ int len; /* its bit length */ { register unsigned res = 0; do { res |= code & 1; code >>= 1, res <<= 1; } while (--len > 0); return res >> 1; } /* =========================================================================== * Flush the bit buffer, keeping at most 7 bits in it. */ local void bi_flush(s) deflate_state *s; { if (s->bi_valid == 16) { put_short(s, s->bi_buf); s->bi_buf = 0; s->bi_valid = 0; } else if (s->bi_valid >= 8) { put_byte(s, (Byte)s->bi_buf); s->bi_buf >>= 8; s->bi_valid -= 8; } } /* =========================================================================== * Flush the bit buffer and align the output on a byte boundary */ local void bi_windup(s) deflate_state *s; { if (s->bi_valid > 8) { put_short(s, s->bi_buf); } else if (s->bi_valid > 0) { put_byte(s, (Byte)s->bi_buf); } s->bi_buf = 0; s->bi_valid = 0; #ifdef DEBUG s->bits_sent = (s->bits_sent+7) & ~7; #endif } /* =========================================================================== * Copy a stored block, storing first the length and its * one's complement if requested. */ local void copy_block(s, buf, len, header) deflate_state *s; charf *buf; /* the input data */ unsigned len; /* its length */ int header; /* true if block header must be written */ { bi_windup(s); /* align on byte boundary */ if (header) { put_short(s, (ush)len); put_short(s, (ush)~len); #ifdef DEBUG s->bits_sent += 2*16; #endif } #ifdef DEBUG s->bits_sent += (ulg)len<<3; #endif while (len--) { put_byte(s, *buf++); } } tcl8.6.5/compat/zlib/Makefile.in0000644000175000017500000002143112663660064016057 0ustar sergeisergei# Makefile for zlib # Copyright (C) 1995-2013 Jean-loup Gailly, Mark Adler # For conditions of distribution and use, see copyright notice in zlib.h # To compile and test, type: # ./configure; make test # Normally configure builds both a static and a shared library. # If you want to build just a static library, use: ./configure --static # To use the asm code, type: # cp contrib/asm?86/match.S ./match.S # make LOC=-DASMV OBJA=match.o # To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: # make install # To install in $HOME instead of /usr/local, use: # make install prefix=$HOME CC=cc CFLAGS=-O #CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 #CFLAGS=-g -DDEBUG #CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ # -Wstrict-prototypes -Wmissing-prototypes SFLAGS=-O LDFLAGS= TEST_LDFLAGS=-L. libz.a LDSHARED=$(CC) CPP=$(CC) -E STATICLIB=libz.a SHAREDLIB=libz.so SHAREDLIBV=libz.so.1.2.8 SHAREDLIBM=libz.so.1 LIBS=$(STATICLIB) $(SHAREDLIBV) AR=ar ARFLAGS=rc RANLIB=ranlib LDCONFIG=ldconfig LDSHAREDLIBC=-lc TAR=tar SHELL=/bin/sh EXE= prefix = /usr/local exec_prefix = ${prefix} libdir = ${exec_prefix}/lib sharedlibdir = ${libdir} includedir = ${prefix}/include mandir = ${prefix}/share/man man3dir = ${mandir}/man3 pkgconfigdir = ${libdir}/pkgconfig OBJZ = adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o OBJG = compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o OBJC = $(OBJZ) $(OBJG) PIC_OBJZ = adler32.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo PIC_OBJG = compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG) # to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo OBJA = PIC_OBJA = OBJS = $(OBJC) $(OBJA) PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA) all: static shared static: example$(EXE) minigzip$(EXE) shared: examplesh$(EXE) minigzipsh$(EXE) all64: example64$(EXE) minigzip64$(EXE) check: test test: all teststatic testshared teststatic: static @TMPST=tmpst_$$; \ if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \ echo ' *** zlib test OK ***'; \ else \ echo ' *** zlib test FAILED ***'; false; \ fi; \ rm -f $$TMPST testshared: shared @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ TMPSH=tmpsh_$$; \ if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \ echo ' *** zlib shared test OK ***'; \ else \ echo ' *** zlib shared test FAILED ***'; false; \ fi; \ rm -f $$TMPSH test64: all64 @TMP64=tmp64_$$; \ if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \ echo ' *** zlib 64-bit test OK ***'; \ else \ echo ' *** zlib 64-bit test FAILED ***'; false; \ fi; \ rm -f $$TMP64 infcover.o: test/infcover.c zlib.h zconf.h $(CC) $(CFLAGS) -I. -c -o $@ test/infcover.c infcover: infcover.o libz.a $(CC) $(CFLAGS) -o $@ infcover.o libz.a cover: infcover rm -f *.gcda ./infcover gcov inf*.c libz.a: $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 match.o: match.S $(CPP) match.S > _match.s $(CC) -c _match.s mv _match.o match.o rm -f _match.s match.lo: match.S $(CPP) match.S > _match.s $(CC) -c -fPIC _match.s mv _match.o match.lo rm -f _match.s example.o: test/example.c zlib.h zconf.h $(CC) $(CFLAGS) -I. -c -o $@ test/example.c minigzip.o: test/minigzip.c zlib.h zconf.h $(CC) $(CFLAGS) -I. -c -o $@ test/minigzip.c example64.o: test/example.c zlib.h zconf.h $(CC) $(CFLAGS) -I. -D_FILE_OFFSET_BITS=64 -c -o $@ test/example.c minigzip64.o: test/minigzip.c zlib.h zconf.h $(CC) $(CFLAGS) -I. -D_FILE_OFFSET_BITS=64 -c -o $@ test/minigzip.c .SUFFIXES: .lo .c.lo: -@mkdir objs 2>/dev/null || test -d objs $(CC) $(SFLAGS) -DPIC -c -o objs/$*.o $< -@mv objs/$*.o $@ placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a $(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS) rm -f $(SHAREDLIB) $(SHAREDLIBM) ln -s $@ $(SHAREDLIB) ln -s $@ $(SHAREDLIBM) -@rmdir objs example$(EXE): example.o $(STATICLIB) $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS) minigzip$(EXE): minigzip.o $(STATICLIB) $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS) examplesh$(EXE): example.o $(SHAREDLIBV) $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV) minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV) example64$(EXE): example64.o $(STATICLIB) $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS) minigzip64$(EXE): minigzip64.o $(STATICLIB) $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS) install-libs: $(LIBS) -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi -@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi -@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi cp $(STATICLIB) $(DESTDIR)$(libdir) chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB) -@($(RANLIB) $(DESTDIR)$(libdir)/libz.a || true) >/dev/null 2>&1 -@if test -n "$(SHAREDLIBV)"; then \ cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir); \ echo "cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)"; \ chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ echo "chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV)"; \ rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB); \ ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ ($(LDCONFIG) || true) >/dev/null 2>&1; \ fi cp zlib.3 $(DESTDIR)$(man3dir) chmod 644 $(DESTDIR)$(man3dir)/zlib.3 cp zlib.pc $(DESTDIR)$(pkgconfigdir) chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc # The ranlib in install is needed on NeXTSTEP which checks file times # ldconfig is for Linux install: install-libs -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi cp zlib.h zconf.h $(DESTDIR)$(includedir) chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h uninstall: cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h cd $(DESTDIR)$(libdir) && rm -f libz.a; \ if test -n "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \ rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \ fi cd $(DESTDIR)$(man3dir) && rm -f zlib.3 cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc docs: zlib.3.pdf zlib.3.pdf: zlib.3 groff -mandoc -f H -T ps zlib.3 | ps2pdf - zlib.3.pdf zconf.h.cmakein: zconf.h.in -@ TEMPFILE=zconfh_$$; \ echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_PREFIX\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\ sed -f $$TEMPFILE zconf.h.in > zconf.h.cmakein &&\ touch -r zconf.h.in zconf.h.cmakein &&\ rm $$TEMPFILE zconf: zconf.h.in cp -p zconf.h.in zconf.h mostlyclean: clean clean: rm -f *.o *.lo *~ \ example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ example64$(EXE) minigzip64$(EXE) \ infcover \ libz.* foo.gz so_locations \ _match.s maketree contrib/infback9/*.o rm -rf objs rm -f *.gcda *.gcno *.gcov rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov maintainer-clean: distclean distclean: clean zconf zconf.h.cmakein docs rm -f Makefile zlib.pc configure.log -@rm -f .DS_Store -@printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile -@printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile -@touch -r Makefile.in Makefile tags: etags *.[ch] depend: makedepend -- $(CFLAGS) -- *.[ch] # DO NOT DELETE THIS LINE -- make depend depends on it. adler32.o zutil.o: zutil.h zlib.h zconf.h gzclose.o gzlib.o gzread.o gzwrite.o: zlib.h zconf.h gzguts.h compress.o example.o minigzip.o uncompr.o: zlib.h zconf.h crc32.o: zutil.h zlib.h zconf.h crc32.h deflate.o: deflate.h zutil.h zlib.h zconf.h infback.o inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inffixed.h inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inftrees.o: zutil.h zlib.h zconf.h inftrees.h trees.o: deflate.h zutil.h zlib.h zconf.h trees.h adler32.lo zutil.lo: zutil.h zlib.h zconf.h gzclose.lo gzlib.lo gzread.lo gzwrite.lo: zlib.h zconf.h gzguts.h compress.lo example.lo minigzip.lo uncompr.lo: zlib.h zconf.h crc32.lo: zutil.h zlib.h zconf.h crc32.h deflate.lo: deflate.h zutil.h zlib.h zconf.h infback.lo inflate.lo: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inffixed.h inffast.lo: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inftrees.lo: zutil.h zlib.h zconf.h inftrees.h trees.lo: deflate.h zutil.h zlib.h zconf.h trees.h tcl8.6.5/compat/zlib/treebuild.xml0000644000175000017500000000607712663660065016525 0ustar sergeisergei zip compression library tcl8.6.5/compat/zlib/README0000644000175000017500000001210112663660064014664 0ustar sergeisergeiZLIB DATA COMPRESSION LIBRARY zlib 1.2.8 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). All functions of the compression library are documented in the file zlib.h (volunteer to write man pages welcome, contact zlib@gzip.org). A usage example of the library is given in the file test/example.c which also tests that the library is working correctly. Another example is given in the file test/minigzip.c. The compression library itself is composed of all source files in the root directory. To compile all files and run the test program, follow the instructions given at the top of Makefile.in. In short "./configure; make test", and if that goes well, "make install" should work for most flavors of Unix. For Windows, use one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use make_vms.com. Questions about zlib should be sent to , or to Gilles Vollant for the Windows DLL version. The zlib home page is http://zlib.net/ . Before reporting a problem, please check this site to verify that you have the latest version of zlib; otherwise get the latest version and check whether the problem still exists or not. PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at http://marknelson.us/1997/01/01/zlib-engine/ . The changes made in version 1.2.8 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . zlib is available in Java using the java.util.zip package, documented at http://java.sun.com/developer/technicalArticles/Programming/compression/ . A Perl interface to zlib written by Paul Marquess is available at CPAN (Comprehensive Perl Archive Network) sites, including http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . A Python interface to zlib written by A.M. Kuchling is available in Python 1.5 and later versions, see http://docs.python.org/library/zlib.html . zlib is built into tcl: http://wiki.tcl.tk/4610 . An experimental package to read and write files in .zip format, written on top of zlib by Gilles Vollant , is available in the contrib/minizip directory of zlib. Notes for some targets: - For Windows DLL versions, please see win32/DLL_FAQ.txt - For 64-bit Irix, deflate.c must be compiled without any optimization. With -O, one libpng test fails. The test works in 32 bit mode (with the -n32 compiler flag). The compiler bug has been reported to SGI. - zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works when compiled with cc. - On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is necessary to get gzprintf working correctly. This is done by configure. - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with other compilers. Use "make test" to check your compiler. - gzdopen is not supported on RISCOS or BEOS. - For PalmOs, see http://palmzlib.sourceforge.net/ Acknowledgments: The deflate format used by zlib was defined by Phil Katz. The deflate and zlib specifications were written by L. Peter Deutsch. Thanks to all the people who reported problems and suggested various improvements in zlib; they are too numerous to cite here. Copyright notice: (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu If you use the zlib library in a product, we would appreciate *not* receiving lengthy legal documents to sign. The sources are provided for free but without warranty of any kind. The library has been entirely written by Jean-loup Gailly and Mark Adler; it does not include third-party code. If you redistribute modified sources, we would appreciate that you include in the file ChangeLog history information documenting your changes. Please read the FAQ for more information on the distribution of modified source versions. tcl8.6.5/compat/zlib/win32/0000755000175000017500000000000012665173607014757 5ustar sergeisergeitcl8.6.5/compat/zlib/win32/zlib1.rc0000644000175000017500000000216212663660065016324 0ustar sergeisergei#include #include "../zlib.h" #ifdef GCC_WINDRES VS_VERSION_INFO VERSIONINFO #else VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE #endif FILEVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 PRODUCTVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #ifdef _DEBUG FILEFLAGS 1 #else FILEFLAGS 0 #endif FILEOS VOS__WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0 // not used BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" //language ID = U.S. English, char set = Windows, Multilingual BEGIN VALUE "FileDescription", "zlib data compression library\0" VALUE "FileVersion", ZLIB_VERSION "\0" VALUE "InternalName", "zlib1.dll\0" VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0" VALUE "OriginalFilename", "zlib1.dll\0" VALUE "ProductName", "zlib\0" VALUE "ProductVersion", ZLIB_VERSION "\0" VALUE "Comments", "For more information visit http://www.zlib.net/\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1252 END END tcl8.6.5/compat/zlib/win32/zlib1.dll0000755000175000017500000032200012663660065016472 0ustar sergeisergeiMZÿÿ¸@€º´ Í!¸LÍ!This program cannot be run in DOS mode. $PEL  ßQà# 2 @Pèb   ÀÇР„øðDÑô.text´02```.data€P6@0À.rdataÄJ`L8@`@.bss„ °€`À.edataÇÀ„@0@.idata ÐŒ@0À.CRT,à”@0À.tls ð–@0À.rsrc„˜@0À.relocøœ@0BU‰åSƒìÇ$€èý,‰Ã‰$èSÔ…Û£h½éb£d½éb¸tÇ0ÀƒÄ[]ÃfU‰åVSƒì‹U …Òux‹°éb1À…Ò~cƒê‹ˆÑéb‰°ébët&Ç$èÿÓƒìÇD$ÇD$Ç$l½ébèh-ƒì …ÀuÑ¡p½ébƒø„ÖÇ$è_,¸eø[^] ƒú¸uíd¡‹5ˆÑéb‹Xë9Ø„Ç$èÿÖƒìÇD$‰\$Ç$l½ébèò,ƒì …ÀuÍ1Û¡p½ébƒø„¡p½éb…À„Сp½ébƒø„ö…Ûuð‡l½éb¡ð¥éb…Àt‹UÇD$‰T$‹U‰$ÿÐƒì ƒ°éb¸eø[^] ¡h½éb‰$èÐÒ…À‰ÃtA¡d½éb‰$è½Ò‰Æƒî9ów‹…ÀtóƒîÿÐ9óvñ‰$è]+Çd½ébÇh½ébÇp½éb1Àð‡l½éb¸eø[^] »éÿÿÿÇD$àébÇ$àébÇp½ébè+é ÿÿÿÇ$èç*éüþÿÿÇD$àébÇ$àébèÞ*Çp½ébéçþÿÿ´&U‰åƒì8…Ò‰]ô‰Ã‰uø‰Ö‰}ü‰M䉋Uà‹GV WV)Ð)V…À‰G…'ÿÿÿ‹G‰G‹‹@…À…!ÿÿÿ1ÀƒÄ,[^_]Ãf1É…Àx‹K8Á‰T$‰L$ÇD$ ‰$è=¢‹3‹Cl‹~‰C\‰<$è ‹W9VFV…Ò…¼‹‹x…ÿt£‹Stƒú‡Ýþÿÿv‰Øè9ðÿÿ‹St‹M …Ò”À…Ʉ̈́À„¸þÿÿƒ} ǃ´„¿‹Kl¸‹S\9ÑŽMÿÿÿ)Ñ0À…Òx‹C8ЉL$‰D$ÇD$ ‰$è’¡‹3‹Cl‹~‰C\‰<$èoŸ‹W9VFV…Ò…ú‹ƒx•À¶Àéòþÿÿ‹F ‹O‰T$‰Uà‰$‰L$èã ‹Uà‹GV WV)Ð)V…À‰G… ÿÿÿ‹G‰Géÿÿÿ„À„ëýÿÿéŸþÿÿ‹S\1É‹Cl)Ð…Òx‹K8щD$‰L$ÇD$ ‰$èà ‹3‹Cl‹~‰C\‰<$轞‹W9VFV…Òu‹ƒxÀƒÀéEþÿÿ‹F ‹O‰T$‰Uà‰$‰L$è6 ‹Uà‹GV WV)Ð)V…À‰Gu¼‹G‰Gë´‹F ‹O‰T$‰Uà‰$‰L$èú ‹Uà‹GV WV)Ð)V…À‰G…Îþÿÿ‹G‰GéÃþÿÿU¸þÿÿÿ‰åƒìx‰]ô‹]‰}ü‹U‰uø‹} …Ûu‹]ô‹uø‹}ü‰ì]Ãf…ÿ‹su‹]ô¸þÿÿÿ‹uø‹}ü‰ì]Ã…ötê‹Nƒù‰MÄtɃù„R‹Nt¸þÿÿÿ…Éu´ƒ}Ä„K‹F,ÇF9Âr‹MÄ…É„S)Â׉‹C‹ ‰S‰;‰EÀ‰ð‰M¼èÃíÿÿ‹~tƒÿ‰}̆±‰]¸‹VX‹N8‹~T‹Fl‰Uä‹V@‹]̉Mà‹N4‰}Ü‹~D‰EÈ‹FH‰UØ‹Uȃë‰MÔ‰}Љ]¤‰u t&¶Mä‹]à‹}Ћu Óà¶L‹]Ø1È#EÜ G‹}Ô‰FH·1!×f‰4{f‰ƒÂƒm¤uÆ‹UÌ‹}È‹u D:þ‰Fl‰ðÇFtèíÿÿ‹Ntƒù‰ṀYÿÿÿ‹]¸‹}Ì‹EÌFl‹UÀ‹MĉFl‰F\‹E¼‰¾´ÇFtÇFxÇF`ÇFh‰1À‰S‰Nénþÿÿƒ~*…dþÿÿéŸþÿÿ‰T$‰|$‹C0‰U´‰$è¸áÿÿ‹U´‰C0é”þÿÿ‹FL‹NDfÇDAþDþ‰U´‰D$ÇD$‰ $èÍ ‹F,ÇFl‹U´ÇF\dž´ébþÿÿfU¸þÿÿÿ‰åƒì‰]ø‹]‰uü…Ûu ‹]ø‹uü‰ì]Ës…ötï‹K …Étè‹S$…Òtá‹FÇCÇCÇCÇC,‰F‹FÇFƒø|>uAÇFqÇD$ÇD$Ç$èÓàÿÿ‰C0ÇF(‰4$èÁ™1Àérÿÿÿ÷؉FƒøÇF*uºÇD$ÇD$Ç$è-èÿÿë¸t&¼'U¸þÿÿÿ‰åƒì‰]ø‹]‰uü…Ûu ‹]ø‹uü‰ì]Ës…ötï‹K …Étè‹S$…Òtá‹FÇCÇCÇCÇC,‰F‹FÇFƒøŒì…ëÇFqÇD$ÇD$Ç$èëßÿÿ‰C0ÇF(‰4$èÙ˜‹[‹C,‹SLÀ‰C<‹CDfÇDPþTþ‰T$ÇD$‰$èñ‹ƒ„ÇClÇC\ÇCt@Áâ‚ €éb·’ €éb·Hǃ´ÇCx‰“Œ·P·@‰‹€ÇC`‰“‰C|ÇChÇCHèõ¬1ÀéÀþÿÿ÷؉FƒøÇF*… ÿÿÿÇD$ÇD$Ç$è—æÿÿéÿÿÿfU¸þÿÿÿ‰å‹U…Òu]ËR…Òt÷ƒzuñ‹E ‰B1À]ô&U¸þÿÿÿ‰å‹US‹M‹] …Òu []ô&‹R…Òtï…Ût‹B‰1À…Étà‹’¼‰[]Ãë U¸þÿÿÿ‰åƒì(‹U‰]ô‹] ‰uø‰}ü…Òu‹]ô‹uø‹}ü‰ì]Ãt&‹r…ötç‹V°ûƒÂ9–¤r׋–¼¿¸)×9ûNû‰ùÓà‰Ñƒè#E‰–¼Óàf †¸‰4$è|˜‰ùÓ})ûuº1Àëë U¸þÿÿÿ‰å‹U…Òu]ËR…Òt÷‹E ‰‚Œ‹E‰‚€‹E‰‚‹E‰B|1À]ÃvU‰åWVSƒì‹U ‹Mr‰ðÁè\B?Áè…ɉEð„ã‹I…Ʉ؋Aƒø„»ƒøtƒøÀ÷Ѓàƒy0t|EðƒÄ[^_]ËA‰Eì‹]츅ÛtÝ‹]ì‹{…ÿt‹CƒÀ‹}ì‹_…Ût‰×¶ƒÀƒÃ„Òuó‰ú‹}ì‹_$…Ût‰×¶ƒÀƒÃ„Òuó‰ú‹}ì‹,X…ÿEÃy0…„ÿÿÿƒyP…zÿÿÿ‰ÑƒÄÁé 41‰ÑÁéÎÁê[^_]ÃylÀƒàüƒÀ éCÿÿÿ‹EðƒÄ[^_ƒÀ]ÃU¸þÿÿÿ‰åƒìX‰]ô‹]‰}ü‹} ‰uø…Ûu‹]ô‹uø‹}ü‰ì]Ãt&ƒÿ‹s~‹]ô¸þÿÿÿ‹uø‹}ü‰ì]Ã…ötê…ÿxÌ‹S …Ò„í‹…À„Ùƒÿ‹F•EÓ…7‹K…É„æ‹V(ƒø*‰‰~(‰Uà„êƒøE„ÒƒøI„ƒø[„ƒøg„¢‹N…É…¥‹C…Àu01Òƒÿ”ÂÒ ?)Ñ‹UàÒ‰Uä1Òƒ}àÂÒ)Uä;MäŽM‹Vúš„U…Àta‹†ˆƒø„¸ƒø„’‹†„‰|$‰4$@ÿ…¨€ébPþƒú†Wƒøt…À…²‹{1À…ÿ…ºþÿÿÇF(ÿÿÿÿé®þÿÿ‹Ft…Àu˜1À…ÿ„þÿÿúšu†1À€}Ó…‰þÿÿ‹V°…ÒŽ|þÿÿƒú„Y ‹S0‹F‹~‰ÑÁꈋVÁéˆL‹S0‹~âÿÿ‰ÑÁéˆL‹NˆTƒÀ‰F‰Øèaèÿÿ‹F…À~÷؉F1Àƒ~”Àéþÿÿƒø…wÿÿÿƒÿ„!ƒÿft)ÇD$ ÇD$ÇD$‰4$蔃ÿ„í‰Øèþçÿÿƒ{…-ÿÿÿÇF(ÿÿÿÿ1Àé´ýÿÿ‰Øèßçÿÿ‹S…Òtä‹Cé|þÿÿƒ~„á ‹F01ÉÁà ƒ¾ˆˆÿÿ޶ Ñ‹Vl‰ÈƒÈ ÇFq…Òº…BEȉÈ÷â‰È‹N)ÐÑèÁè‰ÂÁâ)‹FƒÂ‰UÜÁꈶUÜ‹NˆTP‰V‹Vl…ÒtI‹K0‰ÊÁê‰Uä‰Ê‹NÁêˆT‹V¶MäˆL‹S0‹Nâÿÿ‰UÜÁêˆT‹N¶U܈TƒÀ‰FÇD$ÇD$Ç$è Ùÿÿ‰C0‹Fé%ýÿÿ‹V‹B‰UÔ…À„ù ‹N ‹F‰MÜ·J‰Eä‰MØ‹MÜ9M؆܉}؉ы}Üë2t&‹I‹V¶ 9ˆ ‹VƒÀ‹~ ‰F·JƒÇ‰~ 9ù†Ÿ‰Ñ9F u΋z,…ÿt ;E䇣‹{‰<$è“‹W9SFS…Òu‹~;~ ‰}ä„܉ø‹N‹~ 댋C ‹O‰T$‰Uȉ$‰L$ès‹UÈ‹GS WS)Ð)S…À‰Gu³‹G‰Gë«…À„ýÿÿ¡|¥éb‰C¸ûÿÿÿé¤ûÿÿ‹}Ø‹J,…Ét 9Eä‚ú ‹B9F „¯‹FéþûÿÿÇFšéüÿÿ‹V‹B‰Ñ…À„@ ‹V‰}܉Uä‰Ðë#‹Q‹~ ‹N¶:ƒÇ‰~ ˆƒÀ„Ò‰FtG‹N9F uØ‹I,…Ét 9Eä‚"‹{‰<$èó‘‹W9SFS…Òu>‹N;N ‰Mä„ò ‰È‹N뙋}Ü1É‹V‹R,…Òt 9Eä‚À …É„o‹FéOûÿÿ‹K ‹G‰T$‰Uȉ $‰D$è>ÿ‹UÈ‹GS WS)Ð)S…À‰GuŽ‹G‰Gë†+Eä‰D$‹EäF‰D$‹C0‰$è_Þÿÿ‰C0é9þÿÿ¶@šéb‰]؉}܉Uä‹FtëufÇF`‹Vl…Ò… ‹N8¶‹† ‹Ž¤fÇA‹Ž˜ˆ¶ÒƒÀfƒ„–”1É‹–œ‰† ƒê9ЋFt‹Vl”ÁƒèƒÂ‰Ft‰Vl…É…–=w†‰ðèÿàÿÿ‹UÜ‹Ft…Ò„‘…À„~ƒøÇF`‡`ÿÿÿ‹N8‹Vlécÿÿÿ‹N8\ÿ‰]Ô¶;‰}à‹}Ô¶8_…Dÿÿÿ¶9}à…7ÿÿÿ‹]Ô‹}Ô¶[ƒÇ9]à…!ÿÿÿœ‰]Ìëj_‰]Ô¶_9]àuj_‰]Ô¶_9]àu[_‰]Ô¶_9]àuL_‰]Ô¶_9]àu=_‰]Ô¶_9]àu._‰]Ô¶_9]àuƒÇ¶9]àu;}Ìs_‰]Ô¶_9]àt‡‹}Ô»+]Ìß9lj~`†]‰F`‰Ç‹† Wý‹Ž¤fÇA‹Ž˜ˆ¶Ò‹}ä¶’@œébƒÀ1ɉ† fƒ„¾ˆ fƒ„–˜‹–œƒê9ЋV`‹Ft”ÁÇF`)ÐVl‰Ft‰Vlébþÿÿ‹F\1É)Â…Àx‹N8Á‰T$‰L$ÇD$ ‰4$è‘‹‹Fl‹{‰F\‰<$è쎋W9SFS…Ò…9‹‹@…À…–ýÿÿ‹]Ø1À‹}Üéþøÿÿƒ{„øÿÿ¡p¥éb‰C¸þÿÿÿéÂ÷ÿÿ‹V‹B,…ÀtZ‹FH;N ‰M܇»¶K0‹Vˆ ‹K0‹VÁéˆL‹M܉NÇD$ÇD$Ç$è_Ûÿÿ‰C0ÇFqéú÷ÿÿÇFqéî÷ÿÿ‹V‹B$‰Ñ…À„‹F‰}܉Eäë#‹Q$‹~ ‹N¶:ƒÇ‰~ ˆƒÀ„Ò‰FtG‹N9F uØ‹I,…Ét 9Eä‚á‹{‰<$èÖ‹W9SFS…Òu=‹V;V ‰Uä„å‹N‰Ð뙋}Ü1É‹V‹R,…Òt 9Eä‚ë…ÉtG‹Fvé<÷ÿÿ‹K ‹G‰T$‰Uȉ $‰D$è"û‹UÈ‹GS WS)Ð)S…À‰Gu‹G‰Gë‡ÇFg‹VéŸþÿÿÇF ‹VÇF[éùþÿÿ‰]ä‰}à‹Ftëd‹V8‹FlÇF`‹Ž¤¶‹– fÇQ‹Ž˜ˆ¶À‹žœfƒ„†”ƒÂ‹Ft‹Nlƒë‰– ƒèƒÁ9Ú‰Ft‰Nl„·…Àu˜‰ðèÝÿÿ‹^t…ÛuŠ‹}à1À‹]ä…ÿ„×öÿÿƒÿdž´„ ƒ¾ ¸„²öÿÿ‹V\1É‹Fl)Ð…Òx‹N8щD$‰L$ÇD$ ‰4$èYŽ‹‹Fl‹Q‰F\‰Mĉ$‰UÈè0Œ‹UÈ‹MÄ‹B9AFA…À‰Eä…m‹ƒx•À¶ÀéBöÿÿ‹F\1Ò)Á…Àx‹V8‰T$‰L$ÇD$ ‰4$èì‹‹Fl‹{‰F\‰<$èÉ‹‹W9SFS…Òu]‹‹H…É…Šþÿÿ‹]ä1À‹}àéßõÿÿ‹C ‹O‰T$‰Uȉ$‰L$è8ù‹UÈ‹GS WS)Ð)S…À‰G…üÿÿ‹G‰Gé„üÿÿ‹C ‹O‰T$‰Uȉ$‰L$èõø‹UÈ‹GS WS)Ð)S…À‰G…kÿÿÿ‹G‰Gé`ÿÿÿ‹]Ø‹}Üéwþÿÿ=‡dúÿÿé3üÿÿ+Eä‰D$‹EäF‰D$‹C0‰$èô×ÿÿ‰C0éûüÿÿ+Eä‰D$‹EäF‰D$‹C0‰$èÐ×ÿÿ‰C0éºøÿÿÇF ÇFIéUøÿÿ‹†„ƒøŽ;öÿÿƒø±@Ž0öÿÿƒø±€¸ÀEÈéöÿÿ‹V\1É‹Fl)Ð…Òx‹N8щD$‰L$ÇD$ ‰4$è^Œ‹‹Fl‹Q‰F\‰Mĉ$‰UÈè5Š‹UÈ‹MÄ‹B9AFA…À‰Eä…æ‹ƒxÀƒÀéHôÿÿ‹}Ø‹V‹Eäéy÷ÿÿ‹F‹K0‹Vˆ ‹S0‹NÁêˆT·K2‹VˆL¶K3‹VˆL‹K‹VˆL‹S‹NÁêˆT·K ‹VˆL¶K ‹VˆLƒÀ‰Fé}ôÿÿÇD$ÇD$Ç$è‰Öÿÿ‹N‹V‰MÔ‰C0Æ ‹VÆD ‹‹VÆD ‹VƒÁ‰Mä‰N…Ò„û‹EäFƒ:‰EÜ•Àƒz,É÷уáƒzÉ÷уáƒzÉ÷уáÁƒz$Ò÷Òƒâ‹M܈‹V‹Eä‹N‹RˆT‹V‹N‹RÁêˆT‹V‹N·RˆT‹V‹N¶RˆT‹EÔ‹V‹Ž„ƒÀƒù ‰U争Ftƒ¾ˆºŽ3‹M䈋V‹N‹R ˆTP‰V‹Vƒzt#‹R‹NˆT‹V‹N‹RÁêˆT‹VƒÀ‰Fƒz,t‹F‰D$‹F‰D$‹C0‰$è8Õÿÿ‹V‰C0ÇF ÇFEéƒôÿÿÇFgébùÿÿÇF[éÆùÿÿ+Eä‰D$‹EäF‰D$‹C0‰Mĉ$èèÔÿÿ‹MĉC0éöÿÿ‰ØèÛÿÿ‹FP;V ‰U܇nñÿÿé'ùÿÿ+Eä‰D$‹EäF‰D$‹C0‰Mĉ$è Ôÿÿ‹MĉC0éëùÿÿÇFIé)õÿÿ+Eä‰D$‹EäF‰D$‹C0‰$èmÔÿÿ‹V‰C0éßôÿÿ=š…¾ðÿÿéŒøÿÿƒÿ‡Ÿ÷ÿÿéöÿÿ‹A ‰Eà‹B‰D$‹Eä‰D$‹Eà‰$èÅô‹MÄ‹UÈ‹EäA B)AA‹B+Eä…À‰B…Õüÿÿ‹B‰BéÊüÿÿ‹}ܹ‹Eäé õÿÿ‹}ܹ‹Eäéùÿÿ‰4$è<‡éòÿÿ€}Ó„©ðÿÿéôÿÿ‹A ‰Eà‹B‰D$‹Eä‰D$‹Eà‰$è9ô‹MÄ‹UÈ‹EäA B)AA‹B+Eä…À‰B…Núÿÿ‹B‰BéCúÿÿƒéžÂÁâé¿ýÿÿ‹V‹EÔÆD‹VÆD‹VÆD‹VÆD‹VÆD‹EÔ‹V‹Ž„ƒÀƒù ‰U争Ftƒ¾ˆº ƒéžÂÁâ‹M䈋VÆD ƒÀ‰FÇFqé‚ïÿÿ‹VL‹FDfÇDPþTþ‰T$ÇD$‰$è[óƒ~t…äðÿÿÇFlÇF\dž´éÇðÿÿ¶¿U¸þÿÿÿ‰åƒìH‹U‰]ô‹] ‰uø‰}ü…Òu‹]ô‹uø‹}ü‰ì]Ãt&‹z…ÿtçƒûÿt ƒû v ¸þÿÿÿëÖ»‹EÁè„Àuêƒ}¸þÿÿÿ¼k‡„ ‹€¨€éb‰Eä‹E9‡ˆtx1ÀƒzuM9Ÿ„t7‰Ÿ„kÛ “ €éb·J‰€·‹ €éb‰Œ·J·R‰‰W|‹U‰—ˆéLÿÿÿÇD$‰$èŽíÿÿƒøûužƒºDÂëkË ‹uä1À9±¨€éb…tÿÿÿéwÿÿÿfU¸þÿÿÿ‰åƒì‰]ø‹]‰uü…Ûu ‹]ø‹uü‰ì]ËS…Òtï‹rƒþEtƒþ*…Œ¶‹B…Àt‰D$‹C(‰$ÿS$‹S‹BD…Àt‰D$‹C(‰$ÿS$‹S‹B@…Àt‰D$‹C(‰$ÿS$‹S‹B8…Àt‰D$‹C(‰$ÿS$‹S‰T$‹C(‰$ÿS$1Àƒþq•ÀÇCD@ý‹]ø‹uü‰ì]Ãþ[„qÿÿÿƒþI„hÿÿÿƒþq„_ÿÿÿƒþg„Vÿÿÿþš…"ÿÿÿéEÿÿÿt&U‰åƒìH‹U‹E ‰]ô‹M‰uø‹]‰Uà‹U ‰Eä‹E‰}ü‹u$‹}…Ò‰Eܸúÿÿÿu ‹]ô‹uø‹}ü‰ì]Ãþ8t‹]ô¸úÿÿÿ‹uø‹}ü‰ì]À:1ué…Û°þtÑ‹C ÇC…ÀtK‹s$…öt;ƒ}äÿ¸EEä…ɉEäx!ƒùº~ƒé²‹Eàƒèƒøv&¸þÿÿÿë‡÷Ù1ÒëèÇC$°Üèbë¼ÇC ÜèbÇC(륃ÿuÕƒùЃùf~Ƀ}ä ËEäÁè„Àu¹ƒ}ܳ‹EÜÁè„Àu©ƒù¸ DÈÇD$ÄÇD$‹C(‰U؉MÔ‰$ÿS ‹UØ‹MÔ…À‰Æ„<f¿‰CÓç‰H0‹Mà‰Pº‰Ç@‰x,GÿƒÁ‰F4‹EàÓâ‰NP‰Ñƒé‰VL1Ò‰NTƒÀ ¹÷ñ‰FXÇD$‰|$‹C(‰$ÿS ‰F8ÇD$‹F,‰D$‹C(‰$ÿS ‰F@ÇD$‹FL‰D$‹C(‰$ÿS ºdžÀ‰FD‹EàƒÀ‰ÁÓ≖œ‰T$ÇD$‹C(‰$ÿS ‹–œƒ~8 •‰N ‰Ft]ƒ~@tWƒ~DtQ…ÀtM‰ÑƒáþR Ð‰Ž¤‹M䉆˜‹EÜÆF$‰Ž„‰†ˆ‹uø‰]‹}ü‹]ô‰ì]éØåÿÿ¸üÿÿÿé·ýÿÿ¡x¥ébÇFš‰C‰$ègüÿÿ¸üÿÿÿé–ýÿÿ¶¼'U¸úÿÿÿ‰åƒì(‹U‰]ô‹M‰uø‹]‰}ü‹u …Òu ‹]ô‹uø‹}ü‰ì]Ãù8t‹]ô¸úÿÿÿ‹uø‹}ü‰ì]À:1ué…Û°þtÑ‹K ÇC…É„…‹S$…Ò„nƒþÿtƒþ ޏþÿÿÿ럾ÇD$ÄÇD$‹C(‰$ÿS …À‰Ç„ƒ‰C‰Ç@Ç@Ç@0Ç@,€Ç@4ÿÇ@PÇ@L€Ç@TÿÇ@XÇD$ÇD$€‹C(‰$ÿS ‰G8ÇD$‹G,‰D$‹C(‰$ÿS ‰G@ÇD$‹GL‰D$‹C(‰$ÿS LJÀLJœ@‰GDÇD$ÇD$@‹C(‰$ÿS ‹—œƒ8 •‰O ‰G„‚ƒ@t|ƒDtv…Àtr‰ÑƒáþR Љ¤‰‡˜‰·„LJˆÆG$‹uø‰]‹}ü‹]ô‰ì]éÂãÿÿÇC$°Üèbé†þÿÿÇC ÜèbÇC(éhþÿÿ‰ðÁè„À…tþÿÿé{þÿÿ¡x¥ébÇGš‰C‰$è*úÿÿ¸üÿÿÿéôýÿÿ¸üÿÿÿéêýÿÿ¶U‰åƒì8‹U ‰]ô‹]‰uø‰}ü…Òu¸þÿÿÿ‹]ô‹uø‹}ü‰ì]Ãt&…Ûtå‹B‰Eä‹uä¸þÿÿÿ…ötØ‹‰‹B‰C‹B‰C‹B ‰C ‹B‰C‹B‰C‹B‰C‹B‰C‹B ‰C ‹J$‰K$‹J(‰K(‹r,‰s,‹r0‰s0‹R4‰S4‰ $ÇD$ÄÇD$ÿЉEà‹Mà¸üÿÿÿ…É„^ÿÿÿ‹U๱‹uä‰S‰×ó¥‹Eà‰ÇD$‹@,‰D$‹C(‰$ÿS ‹Mà‰A8ÇD$‹A,‰D$‹C(‰$ÿS ‹uà‰F@ÇD$‹FL‰D$‹C(‰$ÿS ‰FDÇD$‹†œ‰D$‹C(‰$ÿS ‹}à‰Æ‰G‹G8…À„ä‹W@…Ò„Ù‹D…ÿ„Î…ö„Æ‹Uà‹]ä‹J,‹S8‰$ɉL$‰T$èˆê‹}à‹S@‹O,‹G@‰T$ɉL$‰$èjê‹OL‹SD‹GDɉL$‰T$‰$èOê‹S‹O ‹G‰T$‰L$‰$è6ê‹W‹CÐ+C‰G‹‡œ‰Á@ƒáþ‰ø”Ή‡ ô‰‡$ ô‰‡0 1À‰·¤‰—˜éÞýÿÿ‰$èÈ÷ÿÿ¸üÿÿÿéÌýÿÿU‰åƒì‹E…Àtx Ot ‰EÉéÁ Éé ¸þÿÿÿÉÃU‰åƒìE‰D$ ‹E‰D$‹E ‰D$‹E‰$èÚžÉô&U‰åS‰Ãƒì‹@P…Àtƒ{Lüt‰$è2éÇCPÇCLƒÄ[]ô&¼'U‰åW1ÿVS‰Ãƒì,…ÀuƒÄ,‰ø[^_]Ãt&‰Uà‰MÜÇ$ŒèÎè‹Uà‹MÜ…À‰ÆtÓÇ@Ç@ Ç@PÇ@ Ç@<ÿÿÿÿÇ@@Ç@(¶„ÀtJÇEä‰×ë¾Àƒè0‰F<ƒÁ¶„À„ÈPЀú váƒè+ÿÿÿt&ÇF@é.ÿÿÿt&‹F ‰ú…À„Sÿÿÿ=O„øƒúþ„]‰$‰Uàè¤ç‹Uà‰Áx‰Uà‰M܉<$è^ç‹Uà‹MÜ…À‰F„ ÿÿÿƒúþ„¤‰Uà‰\$ ÇD$ éb‰|$‰$è¹ýÿÿ‹Uà‹N ¸€ùOt1ƒ}äÀ%üÿÿ‡ƒ}äÿçüÿÿÇÏ€ù±yEÇ…Òxq‰Vƒùt`ùO„ØÇ‰ð‰÷ÇFHèwýÿÿÇFÇFXéµýÿÿt&…Éu_Æénÿÿÿt&‹F(…À…EþÿÿÇF(éñþÿÿÇF ±y룃úþ„ÈÇD$¶‰D$‰$è—›‰Âƒúÿ‰V„öýÿÿ‹N é_ÿÿÿ‰Uà‰|$‰\$‰$èbæ‹Uàéüþÿÿ‰UàÇD$‰\$Ç$è?æ‹Uàƒøÿ‰Átzxé‰þÿÿÇD$ ÇD$ÇD$‰$èæƒøÿ‰F0tV‹F Ç=O…òþÿÿÇF4ÇF8ÇF,éØþÿÿÇD$¶‰D$‰$ÿèÑéb‰Âé2ÿÿÿ¿1Éé þÿÿÇF0ë¡´&¼'Uºÿÿÿÿ‰åƒì‹M ‹EÉéIüÿÿ‰ö¼'Uºÿÿÿÿ‰åƒì‹M ‹EÉé)üÿÿ‰ö¼'U‰åƒì(‰uø‹u‰}ü1ÿ‰]ôƒþÿu‰ø‹]ô‹uø‹}ü‰ì]ÃÇ$èìä…À‰Ãt߉t$ ÇD$\‚ébÇD$‰$èZûÿÿ‹M ‰ò‰Øè¾ûÿÿ‰$‰ÇèÄäë«fUºþÿÿÿ‰åƒì‹M ‹EÉé™ûÿÿ‰ö¼'U¸ÿÿÿÿ‰å‹US‹M …Òu[]ËZ û±ytûOuê‹Z¸ÿÿÿÿ…ÛuÞƒù¸FÈ0À‰Jë̉ö¼'U¸ÿÿÿÿ‰åSƒì‹]…Ûu ƒÄ[]ô&{ Ouê‹SLƒúût…ÒuÞÇD$ ‹C0‰ÂÁú‰D$‰T$‹C‰$è(äƒÂ‰ÁtG{ OÇuÇC4ÇC8ÇC,‰ØÇCHèoúÿÿ1ÀÇCÇCXémÿÿÿƒÈÿƒÁu±é`ÿÿÿ¶¼'U‰åƒì(‰]ô‹]‰uø‹u ‰}ü¿ÿÿÿÿ…Ûu‰ø‹]ô‹uø‹}ü‰ì]Ãv‹C =O•Â=±yt„ÒuØ‹KLƒùût …É¿ÿÿÿÿuǃÏÿƒ}w¾ƒ}u>+s=OÇCHt8…öˆÁ{ O„•…öt ÇCH‰sD‹{÷ézÿÿÿƒ{Ht¿sD뺃{,u‰ðCx»ÇD$ ‰ðƒÏÿ+ÇD$‰D$‹C‰$èÞâƒÀ„3ÿÿÿljØÇC4ÇC8ÇCHè3ùÿÿ‹{ÇCX÷‰{éýþÿÿ‹…Òx9Ö‰Ð}‰ð)Â)ƉCCéLÿÿÿƒÏÿ„Ò…ÓþÿÿsˆÊþÿÿ‰$èäýÿÿƒÀ…ÿÿÿé´þÿÿ¶U‰åƒìÉé„þÿÿt&U¸ÿÿÿÿ‰å‹U…Òu]ËJ ù±yu1À‹JƒzHt‹BDÈ]ÃfùOtä]öU¸ÿÿÿÿ‰å‹U…Òu]ËJ ù±yu1À‹JƒzHt‹BDÈ]ÃfùOtä]öU¸ÿÿÿÿ‰åSƒì‹]…Ûu ƒÄ[]ô&‹S ú±ytúOuàÇD$ ÇD$ÇD$‹C‰$èjáƒøÿt¸{ Ou¯+CX몴&U¸ÿÿÿÿ‰åSƒì‹]…Ûu ƒÄ[]ô&‹S ú±ytúOuàÇD$ ÇD$ÇD$‹C‰$èúàƒøÿt¸{ Ou¯+CX몴&U1À‰å‹U…Òt‹J ù±yu 1ÀùOt]ÃùOuö1ÀùOuì‹B8]öU1À‰å‹US‹M …Òu[]ËZ û±yu$…Ét‹BL‰ƒzLü¸d‚ébtÞ‹BPºr‚éb[]…ÀDÂÃûOtÔëÄt&U‰åƒì‹E…Àt!‹P ú±yuúOtÉéªöÿÿúOtêÉÃÇ@4Ç@8ÉéŒöÿÿ¶¿U‰åƒìH‰]ô‹]‰uø‹u‰}ü‹} ‹CP…Àtƒ{Lüt‰$è£ßÇCPƒÿût…ÿ……ö‰{Ltuƒÿütp‹S‰$‰Uäè•߉4$‰Çè‹ßD‰$èOß‹Uä…À‰Ç‰CPtc‰$‰Uäèh߉4$‰Ãè^ß‹Uä‰t$ÇD$s‚ébÇD$v‚éb‰T$ ‰<$D‰D$è“õÿÿ‹]ô‹uø‹}ü‰ì]öÇéfÿÿÿt&ÇCLüÿÿÿ‹]ô‹uø‹}ü‰ì]ÃU‰åƒì8‰]ô‰Ã‰uøpT‰}ü‹H…É„†‹KXƒù‰Ï†`‹CT€8„-‹C(…ÀtB‹C$‹ST‰|$‰C‰T$‰$è‡Þ‹CXÇC,ÇCXÇC(‰1À‹]ô‹uø‹}ü‰ì]ÃÇCX‹uø1ÀÇC4‹}üÇ‹]ô‰ì]Ëx‰<$èމ‰C ?‰Uä‰$èýÝ‹Uä…Ò‰C$„è…À„÷‰{ÇCtÇCxÇC|ÇCXÇCTÇD$ 8ÇD$Ž‚ébÇD$‰4$èa-…À„øþÿÿ‹C$‰$èžÝ‹C ‰$è“ÝÇCÇD$€‚ébÇD$üÿÿÿ‰$è¤ýÿÿ¸ÿÿÿÿéÿÿÿ€x‹…Éþÿÿ‰4$èè*1ÀÇC,ÇC(éèþÿÿ‹SLƒúûuH‹S4…ÒtO1À…ÿ„Ïþÿÿƒÿ‡~þÿÿ¿é€þÿÿ…Àt‡‰$è Ý‹S …Ò„tÿÿÿ‰$èøÜégÿÿÿ…Ò¸ÿÿÿÿt¯éŠþÿÿ…Ét‹ST‹C ¶ˆ‹KX‹S1ÿ)ÊK ëÇ9úv4‰Ð)ø‰D$9‰D$‹C‰Uä‰Mà‰$èÝ‘‹Uä‹MàƒøÏuÇC4‹C {X‰CT‰{XéHÿÿÿÿÈÑéb‹‰$è¬ÜÇD$ÿÿÿÿ‰$‰D$èˆüÿÿƒÈÿéõýÿÿU‰åWV‰ÆS1Ûƒì,xT‹@d‰Eäë#ƒøþt<ƒøü„ºƒøý„Öƒû‹Fdt{…Àtw‹VX…Òt>ÇD$‰<$èî-ƒø‰Ãu¿ÇD$Ä‚ébÇD$þÿÿÿ‰4$èüÿÿ¸ÿÿÿÿƒÄ,[^_]Ãf‹FLƒøû…§‹F4…À„®ÇD$ª‚ébÇD$ûÿÿÿ‰4$èÑûÿÿ‹Fd‹Uä)‰Ð÷ØF`‰‰F1Àƒûu¬ÇF,ƒÄ,[^_]ô&‰4$ÇD$€‚ébÇD$üÿÿÿèˆûÿÿƒÄ,¸ÿÿÿÿ[^_]ËFlº”‚éb‰4$ÇD$ýÿÿÿ…ÀD‰D$èZûÿÿƒÄ,¸ÿÿÿÿ[^_]Ã…À„Qÿÿÿ¸ÿÿÿÿé1ÿÿÿ‹V‹F ‰}؉߉Uà1Ò‰E܉Óë t&Ã9]àvK‹Eà)؉D$‹EÜ؉D$‹F‰$èƒø׉ډû‹}Øu)ÇF4VX‹F …Ò‰VX‰FT„êþÿÿéþÿÿ‰Ú‰û‹}ØëÞÿÈÑéb‹‰$èÅÚÇD$ÿÿÿÿ‰4$‰D$è¡úÿÿƒÈÿéþÿÿ‰ö¼'U‰åWVS‰Ãƒì‹C,ƒøtUƒøt/…Àu‰Øèmûÿÿƒøÿt9‹C,…Àt‹;…ÿu‹s4…ötÏ‹KX…ÉuÈ1Àëq‹CÀ‰Cd‹C$‰C`‰Øè´ýÿÿƒøÿuθÿÿÿÿëP‹s1À‹{$Çöë¶9Ɖv(‰ò)‰D$‹C‰T$‰$èúŽƒøÙuÇC4‹C$‰C1ÀƒÄ[^_]ÃÿÈÑéb‹‰$èÐÙÇD$ÿÿÿÿ‰$‰D$è¬ùÿÿƒÈÿëÏ´&U‰åV‰ÖS‰Ã1À…Òuë>|@9ð<)ƉÂ1ÀSS‰…öt7‹ƒøuá‹K4…Ét‹SX…Òt"‰ØèËþÿÿƒøÿuÛ¸ÿÿÿÿ[^]Éò)ð1öëÂt&1À[^]Ãv¼'U¸ÿÿÿÿ‰åƒì8‰]ô‹]‰uø‹u‰}ü…Ûu‹]ô‹uø‹}ü‰ì]Ãt&{ Ouå‹SLƒúû…"ƒþŒŸ¸tÉ‹SH…Ò…iÇEàëp´&‹C4…Àt ‹{X…ÿ„ ‹C,…À„ç‹SÒ9Ö‚Úƒøtj‹E ‰sd‰C`‰Øèüÿÿƒøÿ„΋;‹E Ç)þ8}à{‰U …ö„¼‹;…ÿt‘‹C9þFþ‰|$)þ‰D$‹E ‰$èØ‹E {);8뿉Ú1ÿ‰óëÇ9ûv?‹u ‰Ø)ø‰Eä‰D$þ‰t$‹B‰U܉$è‹U܃øЉӉòuVÇC4‹uäérÿÿÿ‹E ‰Þ‰Ó)þ8éaÿÿÿ…Ò„Öþÿÿéªþÿÿ‰Øè%ýÿÿƒÀf…KÿÿÿƒÈÿéþÿÿÇC8‹EàéþÿÿÿÈÑéb‹‰$è“×ÇD$ÿÿÿÿ‰$‰D$èo÷ÿÿƒÈÿéUþÿÿ‹SD‰ØÇCHè¶ýÿÿ‰ÂƒÈÿƒÂ…xþÿÿé1þÿÿÇD$ì‚ébÇD$ýÿÿÿ‰$è+÷ÿÿƒÈÿéþÿÿvU¸ÿÿÿÿ‰åƒì(‹U…ÒuÉÃz Ouõ‹JLƒùûu‹…Àt‹JƒèƒB‰¶ƒÁ‰JÉÃ…ÉtßÉÃEô‰$ÇD$‰D$è‘ýÿÿ‰ÂƒÈÿ…Ò~ª¶EôÉÃfU¸ÿÿÿÿ‰åƒì(‹U…ÒuÉÃz Ouõ‹JLƒùûu‹…Àt‹JƒèƒB‰¶ƒÁ‰JÉÃ…ÉtßÉÃEô‰$ÇD$‰D$è!ýÿÿ‰ÂƒÈÿ…Ò~ª¶EôÉÃfU‰åƒì‰uü‹u ‰]ø‹]…öu»ÿÿÿÿ‰Ø‹uü‹]ø‰ì]Ã~ Ouæ‹FLƒøûu?‹NH…Éu>…ÛxÓ‹…ÉtL‹VÒ9Ñ„…‹F;F$t\Pÿƒ‰VˆXÿÇF8ƒn뤅Àt½ë™‹VD‰ðÇFHèüÿÿƒÀtƒëª‹FÇDÿF$‰FˆÇF8ƒnéaÿÿÿ 9Èsƒéƒê¶ˆ9N$rð‰V‰ÐëƒÇD$ƒébƒËÿÇD$ýÿÿÿ‰4$èJõÿÿé ÿÿÿt&U‰åƒì8‰]ô‹] ‰uø‹u‰}ü‹}…Ûu1À‹]ô‹uø‹}ü‰ì]Ãt&…ötè1À…ÿ~ä~ OuÛ‹VLƒúû…ƒ~H…Ë1Àƒï‰}ät»‹‰]à‰]Ü…À„†‹]ä;Eä‹~ÇD$ F؉\$‰<$èÅÔ…À‰Ât‰Ã)ûƒÃ‹Eà‰U؉\$‰|$‰$èjÔ‹^^]à)Ø‹UØ)]ä‰t…Òtš‹]Ü1À9]à„?ÿÿÿ‹EàÆ‰Øé2ÿÿÿ…Ò„[ÿÿÿé%ÿÿÿ‰ðt&è«ùÿÿƒÀ„ÿÿÿ‹…À…[ÿÿÿ‹]ÜÇF8ë°‹VD‰ðÇFHèkúÿÿ‰Â1ÀƒÂ…ÿÿÿé×þÿÿ‰ö¼'U1À‰åSƒì‹]…Ût { Ot ‹C(ƒÄ[]ËS,…Òuð‹…Àuê‰Øèºôÿÿëá´&U‰åƒì(‰]ô‹]‰uø¾þÿÿÿ‰}ü…Ûu‰ð‹]ô‹uø‹}ü‰ì]ö{ Ouâ‹K…ÉuS1Àƒ{LûÇD$ÇD$•À‰Æ‰$t¶ûèIóÿÿ‹C‰$èÓ‹C‰$èGˆ‰$‰ÇèùÒ…ÿ¸ÿÿÿÿEðëˆCT‰$è2B‹C$‰$è×Ò‹C ‰$èÌÒëŠU‰åƒì8‰]ô‰Ã‰uø‰}ü‹x‰<$è”Ò…À‰Æ‰C „Ä‹C(…Àt‰{1À‹]ô‹uø‹}ü‰ì]É<$èfÒ…À‰C$„º‹C@ÇCtÇCxÇC|‰D$‹C<ÇD$8ÇD$BƒébÇD$‰D$CTÇD$ ÇD$‰$èáÿÿ…Àu(‹S(‹C…Ò‰Cu ‰Cd‹C$‰C`‰C‹]ô1À‹uø‹}ü‰ì]ËC$‰$èÞÑ‹C ‰$èÓÑÇD$4ƒébÇD$üÿÿÿ‰$èëñÿÿ¸ÿÿÿÿé&ÿÿÿ‰4$ëÔ¶¿U‰åW‰×VS‰Ãƒì,pT‹@…À„‹K(…É…K‹Kd1À…ÿ‰Ê„”…Ét ƒø…Þ‹C‹S`)Â…ð…É„°‹C`‰C‰Mä‰|$‰4$è“Ìÿÿƒøþ„Z‹Kd;Mäu·1Òƒÿ„)ƒÄ,‰Ð[^_]ËC‰Cd‹C$‰C`‹{d‰CÇD$‰4$èKÌÿÿƒøþ„‹Sd9ú„Ý…Ò‰×uÖ‹C‹{`)Çtº‰D$‹C‰|$‰$膅Àˆþ9ø…ö‹Sd…Òt‹C`ë—‹K‹C$‰Kd‰C`éBÿÿÿ´&ƒÿ‰Mä„5ÿÿÿ‹C‹S`)„ÿÿÿ¶‰D$‹C‰T$‰Uà‰$è–…‹Uà…Àˆ‘9Ð…‰‹Kdéßþÿÿ‹CX‰D$‹CT‰D$‹C‰$èb……Àxd;CXu_1ÒÇCX‰ÐƒÄ,[^_]Ã1ÒƒÄ,‰Ð[^_]É4$‰Uàè3Çÿÿ‹UàƒÄ,[^_‰Ð]öÇD$HƒébÇD$þÿÿÿ‰$èèïÿÿºÿÿÿÿé—þÿÿÿÈÑéb‹‰$èÞÏÇD$ÿÿÿÿ‰$‰D$èºïÿÿºÿÿÿÿéiþÿÿ‰Øè¹üÿÿºÿÿÿÿƒøÿ…æýÿÿéOþÿÿ¶U‰åW‰×V‰ÆSƒì‹PX…Òuz…ÿ¸tm‹^…Ûx/9û+…Àu-‹F 1Ò^‰^X‰FT‰ðèýÿÿƒøÿt,)ßt6‹^1À…ÛyÑ…À‰ûtÓ‹F ‰\$ÇD$‰$èÏ뺸ÿÿÿÿƒÄ[^_]ÃÄ1À[^_]Ã0Àëé1Òè+ýÿÿ‰Â¸ÿÿÿÿƒúÿ…oÿÿÿëЉö¼'U‰åƒì8‰]ô‹]‰uø1ö‰}ü…Ût { ±yt‰ð‹]ô‹uø‹}ü‰ì]ËKL…Éuê‹uƒþŒÑtÜ‹S…Ò„ã‹CH…À…õ‹E;Csp‰uä‰Ç‹CX…ÀtG‹KT‹S ‹s)Ð)Æ‹U 9þG÷‰t$‰$‰T$è&ÎsXs)÷u‹uä‹]ô‹}ü‰ð‹uø‰ì]ËS ‰Ñ‰STëµ1Ò‰ØèGüÿÿƒøÿtxu ë•‹KX…Ét1Ò‰Øè-üÿÿ1öƒøÿ„3ÿÿÿ‹E1ö‹U C‰CX‰Ø‰ST1ÒèüÿÿƒøÿEué ÿÿÿÇD$pƒéb1öÇD$ýÿÿÿ‰$è²íÿÿéîþÿÿ‰Øè¶úÿÿƒøÿv… ÿÿÿ1öéÔþÿÿv‹{XÇCH‹KD…ÿuh…É„òþÿÿ¸‰Ï‰uä‹s…öx*9÷|&…Àu&‹C 1Òs‰sX‰CT‰Øèyûÿÿƒøÿtª)÷t!1ÀëωþëÖ‹C ‰t$ÇD$‰$è ÍëÁ‹uäé’þÿÿ1҉؉Màè;ûÿÿ‹MàƒÀu„1öé=þÿÿ¶¿U‰åƒì8‰]ô‹]‰uø¾ÿÿÿÿ‰}ü‹} …Ûu‰ð‹]ô‹uø‹}ü‰ì]Ãv{ ±yuå‹SL…ÒuÞ‹CH…Àuj‹K…Ét3‹SX…Òt$‹C ST‰Ö)Æ9ñv‰ø‰þˆæÿƒCXƒC륋C ‰CTë׉øƒÎÿˆEçEççÿÇD$‰D$‰$èjýÿÿƒèD÷émÿÿÿ‹SD‰ØÇCHèžüÿÿƒÀu€éRÿÿÿt&U‰åƒì‰uü‹u ‰]ø‰4$èùˉt$‰Ã‰D$‹E‰$èýÿÿ…Ût …ÀºÿÿÿÿD‹]ø‹uü‰ì]ö¿U‰åƒì(‰]ô‹]‰uø¾ÿÿÿÿ‰}ü…Ût 1ö{ ±yt‰ð‹]ô‹uø‹}ü‰ì]ËSL…Òuê‹C…Àtm‹{H…ÿ…„‹KX…Ét1Ò‰Øè¢ùÿÿ1öƒøÿtÁ‹{‹C ÆD8ÿ‹E‰|$‰D$ ‹E ‰D$‹C ‰$ÿäÑéb9ø‰Æ}-…À~)‹C €|8ÿu‰sX‰CTsévÿÿÿ‰Øè)øÿÿƒøÿu‡éeÿÿÿ1ö‹]ô‰ð‹}ü‹uø‰ì]ËsXÇCH‹{D…öuf…ÿ¸„^ÿÿÿ‹s…öx39þ/…Àu1‹C 1Òs‰sX‰CT‰Øèìøÿÿƒøÿt¨)÷„-ÿÿÿ‹s1À…öyÍ…À‰þtÏ‹C ‰t$ÇD$‰$èqÊë¶1Ò‰Øè®øÿÿ1öƒÀuŠéÈþÿÿfU‰åƒìE‰D$‹E ‰D$‹E‰$èþÿÿÉÃë U¸ÿÿÿÿ‰åSƒì‹]…Ûu ƒÄ[]ô&{ ±yt ƒÄ¸þÿÿÿ[]ËKL°þ…ÉuÖƒ} wЃ{Hu‹U ‰Øèøÿÿ‹CL뻋SD‰ØÇCHèGúÿÿ‰ÂƒÈÿƒÂuÖëžt&¼'U¸þÿÿÿ‰åƒì(‰]ô‹]‰uø‹u ‰}ü‹}…Ûu‹]ô‹uø‹}ü‰ì]Ãf{ ±yuè‹KL…Éuá9s t)‰ØèÛÿÿ…ÀubÇF 1À‹]ô‹uø‹}ü‰ì]Ã> uµ‰MäÇD$ÇD$Ç$ègÿÿ‹Mä‰|$‰L$‰$èòfÿÿ‹Mä‰Â¸ýÿÿÿ9V…pÿÿÿëǸüÿÿÿé^ÿÿÿ¶¼'U¸þÿÿÿ‰å‹U‹M …Òu]ËR…Òt÷öBtð‰J 1ÀÇA0]ÃU¸þÿÿÿ‰åƒì$‹U‰]ô‰uø‰}ü…Òu ‹]ô‹uø‹}ü‰ì]ËZ…Ûtì‹B…À‰EÜu ƒ{<¸ûÿÿÿv׃;„ó‹{<¾‹C8ljùƒçøƒáÓà1Ƀÿ‰C8‰{<†~ƒï‰}àÁïMðt=ñˆƒÁÁè9ñuôw‹}à1ɉC8‰]àƒç‰{<1ÿëv¸)ȃø‰Á–ÀƒÇ„Àt,9÷s(¶\=ðƒùÀ÷Ð8Ãt „ÛtÒ¸1ÉëØƒÁƒù–ÀëÍ‹]à‰Æ‰Kh‹‰Eà‰ð„À„G‹uÜ…ö„<1À‰×‰Æët&¸)ȃø‰Á–ÀƒÆ„Àt:9uÜv5‹Eàƒù¶0À÷Ð8Ât„Òtϸ1ÉëÕ¶ƒÁƒù–ÀëÄt&‰ð‰ú‹u܉Kh)Ɖr‹uàƉ2‹rƃù‰r¸ýÿÿÿ…þÿÿ‹C‹JÇC(ÇC,…ÀÇC0ÇCÇBÇBÇBtƒà‰B0ƒ0‰Cl‰CP‰CL1ÀÇCÇC ÇC€ÇC ÇC8ÇC<ǃÀǃÄÿÿÿÿ‰r‰JÇ éÞýÿÿv‹Khƒù–À‰Æéªþÿÿ1Àéÿÿÿ‰ö¼'U¸þÿÿÿ‰å‹U…Òu]ËR…Òt÷1Àƒ: uð1Àƒz<]”ÀöU‰åƒì8‰uø‹u ‰]ô‰}ü…öu»þÿÿÿ‰Ø‹uø‹]ô‹}ü‰ì]ö‹E…Àtß‹F»þÿÿÿ…À‰EätÕ‹F …Àt΋~$…ÿtÇÇD$̳üÇD$‹V(‰$ÿÐ…À‰Eàt¦‹Uäƒz4„ìÇD$‹J$¸Óà‰D$‹F(‰$ÿV …À‰EÜ„­‹}¹ó¥‹}à‹uäf¹óó¥‹Eä‹PL09Âr4‹MäÁ¼9Êw'‹Mà)‹uäÁú”‘0‰QL‹VP)ÂÁú”‘0‰QP‹}ä‹Mà‹Wl)ÂÁúƒ}Ü„‘0‰Alt ‹O$¸‹W4‹uÜÓà‰D$‰T$‰4$èýŠ‹}à1Û‹EÜ‹U‰G4‰zéÂþÿÿ‹Mà‰L$‹F(‰$ÿV$é­þÿÿÇEÜé2ÿÿÿ¶U¸þÿÿÿ‰å‹U…Òt‹R…Òt Ç‚À°ý]ö¿U¸ÿÿ‰å‹US…Òu[]ËR…Òtö‹‚Ä‹ Áàƒùt 1Ûƒùt[]ËZ@ëõt&‹šÈ+Z@ëæU‰åWVSì‹MÇEÔÇEØÇEÜ…ÉÇEàÇEäÇEèÇEìÇEðt‹] 1À·CƒÀfƒDUÔ9Áwï‹E·}ò‹f…ÿ‰E¬…Ûfƒ}ð…9fƒ}î…=fƒ}ì…Xfƒ}ê…kfƒ}è…~fƒ}æ…dfƒ}ä…¡fƒ}â…‡fƒ}à…¸fƒ}Þ…žfƒ}Ü…„fƒ}Ú…Éfƒ}Ø…¯fƒ}Ö…‹U‹PÆ@Æ@Æ@@ÆB‹M‹]fÇ@ƒÀfÇB‰1ÀÇÄ[^_]ÃÇ…|ÿÿÿt&fƒ}Ö…gº‹…|ÿÿÿë fƒ|UÔ…cƒÂ9Ârí·uÖ»¸ÿÿÿÿ)óx©4·]ظÿÿÿÿ)Þx™·]Ú46)ÞxŽ·]Ü46)Þxƒ·]Þ46)Þˆtÿÿÿ·]à46)Þˆeÿÿÿ·]âö)ÞˆWÿÿÿ·]äö)ÞˆIÿÿÿ·]æö)Þˆ;ÿÿÿ·]èö)Þˆ-ÿÿÿ·]êö)Þˆÿÿÿ·]ìö)Þˆÿÿÿ·]îö)Þˆÿÿÿ·]ðö)Þˆõþÿÿö·ß)ÞƒþŒåþÿÿ…Ó·EÖfÇE¶f‰E¸fEØf‰EºfEÚf‰E¼fEÜf‰E¾fEÞf‰EÀfEàf‰EÂfEâf‰EÄfEäf‰EÆfEæf‰EÈfEèf‰EÊfEêf‰EÌfEìf‰EÎfEîf‰EÐfEð…Éf‰EÒt>‹} 1À‰U¨´&·Gf…Òt·Ò‹]·tU´f‰s·\U´ƒÃf‰\U´ƒÀ9ÁwÔ‹U¨‹]…Û…Í‹}Ç…xÿÿÿ‰½hÿÿÿ‰½lÿÿÿ‹M‹E¬9…|ÿÿÿF…|ÿÿÿ‹ ÇE„9ÂC‰MŒ‰ÁÓe„‹]„‰E€ƒëƒ}‰pÿÿÿ”…gÿÿÿ}„T‡Áƒ}”…fÿÿÿ}„P‡À‹}‹E€‰U¤1ÒÇ…tÿÿÿÿÿÿÿ‰}œ‰û‰E˜ÇE ·3¶M¤*M ÆE“·Æ9…xÿÿÿˆM¬"¾ÆE“`}‹hÿÿÿ‹lÿÿÿ¶ A·4CˆM“‹M¤»¿+M ‰UˆÓã¶M˜‰Ø÷؉E°Óç‹M°‰}”‰ø‰×)ØÁá‰M¨¶M Óï‹M” ‹}Œ)Ù ‰ß¶]“t&ˆ¶U¬f‰qˆQE°M¨8…Òuæ‹M¤»‹UˆƒéÓã…Ó‰ÙtÑé…Ñuú…É„BAÿ!Ћ}¤·D}Ôƒèf…Àf‰D}Ôu‹…|ÿÿÿ9Ç„¹‹Mœ‹] ·A·C‰E¤‹E¤9E€ƒç‹µpÿÿÿ!Ö;µtÿÿÿ„Ó‹M …É‹M€EM )ȉÃË;|ÿÿÿ‰M ‰E˜sJ¶M˜¸Óà·L]Ô)È…À~4‹}˜‹] ‰U°‰úL‹½|ÿÿÿë·\MÔÀƒÁ)Ø…À~ƒÂ9Ïwé‰U˜‹U°¶M˜¸ÓàE„}„T‡Y}„P‡r‹}Œ µ‹]”<Ÿ‹]‰}Œ‹¶]˜ˆ°‹}¶]€‹ˆ\‹‹EŒ‰µtÿÿÿ)ØÁøf‰D ƒEœ‹]œé÷ýÿÿ´&1Òé¿þÿÿ·EÖ»)Ãé¦ûÿÿƒ}¸Ç…xÿÿÿÿÿÿÿE…xÿÿÿÇ…hÿÿÿ@™ébÇ…lÿÿÿ€™éb‰…xÿÿÿ¸¾—ébE…hÿÿÿ‰…hÿÿÿ¸þ—ébE…lÿÿÿ‰…lÿÿÿéïüÿÿ€½gÿÿÿ¸„-ýÿÿéÛúÿÿ€½fÿÿÿ¸„.ýÿÿéÄúÿÿ…Òt‹}Œ—Æ@¶U¬fÇ@ˆP‹M„‹]‹}‹E€‰1ÀéŒúÿÿÇ…|ÿÿÿé—úÿÿÇ…|ÿÿÿ éˆúÿÿ€½gÿÿÿ„šþÿÿ¸éWúÿÿÇ…|ÿÿÿ ébúÿÿ€½fÿÿÿ„þÿÿëØÇ…|ÿÿÿ éDúÿÿÇ…|ÿÿÿ é5úÿÿÇ…|ÿÿÿ é&úÿÿƒ½|ÿÿÿu ƒ}…ûÿÿƒÈÿéñùÿÿÇ…|ÿÿÿéüùÿÿÇ…|ÿÿÿéíùÿÿÇ…|ÿÿÿéÞùÿÿÇ…|ÿÿÿéÏùÿÿÇ…|ÿÿÿéÀùÿÿÇ…|ÿÿÿºé×ùÿÿÇ…|ÿÿÿéùÿÿÇ…|ÿÿÿéŽùÿÿºé¯ùÿÿU‰åWVSƒì$‹˜P¹ÔɉUì‹T¸ 9Ù‰]ð‰Uܪ‹uì‰}Ô4–‰uàëH¶‹”ˆ\ ‹]ì‰Mз“f‰]Ú‹uà·}Úf9>rot‹}ЋuÔ ?9Mð‰T° Œ§ÇÔ‰}Ô9Mð~¹‹”ˆ` q‹}시ˆ\ ‰uз<—‰]è‰Þf‰}Ú‹}ì·Ÿf9]ÚrtF‹uàf‰]Ú·}Ú‹Uè‰MÐf9>s‘‹}Ô‹U܉T¸ ƒÄ$[^_]Ë]ܶŒX8ŒX‡iÿÿÿëÔt&¶¼X‰û:œ0XFMÐGÖ‰MÐé5ÿÿÿ‹UܿԉT¸ ƒÄ$[^_]Ãt&¼'U‰åWVS‰ÃƒìX‹‰UĉE¬‹B‹p ‹8ǃPǃT=…öŽ)ÇE¨ÿÿÿÿ1À¹ÿÿÿÿ‹U¬‰}Ðë*v‹‹PÆ„Xy‰„‹` ‰ÁƒÀ9ð‰»Ptfƒ<‚uÒfÇD‚ƒÀ9ðuë‹}ЉM¨…ÿ„Þ‰uЋu¨ë*‰”‹\ ‹M¬fǃ«¨Æ„X·D)ƒ¬‹‹Pƒù ƒÁ1À1Òƒþ‰‹P¹ƒÆµ‰ò뫉u¨‹uЋE¨‹}ĉG‰ÏÑÿ¶‹U¬‰ù‰Øè¤ýÿÿƒïuP‹}¬ët&ƒÆ‹“` ¹‰UЋ”ƒ\ ƒè‰ƒP‰Ø‰“` ‰úè`ýÿÿ‹ƒ` ‹“T‹MЉ„“T ‰Œ“X Jþ‹UЉ‹T ‡‰MÈ—‰UÌ·‹MÌff‰·¶„X‹Uж”XˆE¼¶M¼‰ÐƒÁƒÀˆMжM¼8ʶUÐB‰úˆ„3X‹MÈ‹EÌf‰q¹f‰p‰Ø‰³` èÃüÿÿ‹ƒPƒø$ÿÿÿ‹ƒT‹}Ä‹MÄ‹uÄPÿ‰“T‹“` ‹ ‰”ƒX ‹G‹v‰MÈ‹x‹‰uÌ‹p‹@‰}¸‰M´‰u°‰EЋEÈǃ< ǃ@ ǃD ǃH ǃL ǃP ǃT ǃX fÇD‹“T‰U¤ƒÂú<‰U …É„þ‹}¤ƒP‰E¼ÇEÀ´»` v‹‹EÈ •‰Mœ‹MÈMœ·y·D¸‰EăÀ9EÐ}ƒEÀ‹EÐ9UÌf‰A|Gfƒ„C< 9U¸ÇEÄ ‹}°+U¸‹<—‰}Ä·EÄ‹}´‹Mœ¯Âƒ¨·DEįƒ¬ƒÆ;u¼…tÿÿÿ‹E ‹UÀ+E¤<…Ò„Ö‹MЋUЉE¼¹—±˜‹MÀƒê‰UÄ·T{ ‹EÄf…Òuvƒè·”C< f…Òtðƒêƒéfƒ„C> f‰”C< fƒls …É¿ƒ}ЋE¼tn¶‹uз”s< t&…Òt@ƒè‹Œƒ\ 9MÌ|í‹}È ·q9uÐt‹}Ð)÷‰þ·9¯÷³¨·uÐf‰qƒê…ÒuÀ‹}Ä…ÿ‰}Ðt ‰úƒê‰UÄ똷ƒ< Àf‰EÖfƒ> Àf‰EØfƒ@ Àf‰EÚfƒB Àf‰EÜfƒD Àf‰EÞfƒF Àf‰EàfƒH Àf‰EâfƒJ Àf‰EäfƒL Àf‰EæfƒN Àf‰EèfƒP Àf‰EêfƒR Àf‰EìfƒT Àf‰EîfƒV Àf‰EðfƒX Àƒ}¨ÿf‰Eòt?‹}¬1ö·T·…Òt)·DUÔ1۷ȃÀf‰DUԉȃà ØÑéƒêuïÑëf‰·ƒÆ;u¨~ƃÄX[^_]ËU¨ë‰„»\ ‹}¬fǃ«¨Æ„X‹‹Pƒù y1À1Ƀú‰»PÄB …‰Â붉U¨‰Ðé/ûÿÿ‹M¤³P‰uĉÆÇEÀ‰]´¼‹` ë!ÇE¼·E¼¯Â‹U´‚¨ƒÇ;}ÄtE‹ –·A·D†ƒÀ9EÐ}ƒEÀ‹EÐ9UÌf‰A|Ò‹]´fƒ„C< 9U¸¨‹]°+U¸‹“‰]¼ë¡‹]´éýÿÿÇE¨ÿÿÿÿé&úÿÿt&U‰åWVSƒì‰UÜ·R‰MØ‹}؃úöƒÆƒúÉჃÁ…ÿ‰UèˆË¿ÿÿÿÿ1ÛÇEä‰}ð‹Uä‹}Ü·T—‰UàS9Ê} ‹}à9}脉9òõ‹]è‰Ö‹ˆ¼·¸¸Ü‰]ðëaf‹]ð·\˜ ‰]ìÓã‰Ù‹X ù‹xf‰ˆ¸ˆ ¶ˆ¹‹xˆLƒÃ‹}ì‰X‹˜¼¹)ÙÓÿƒî‰ùf‰ˆ¸Lð‰ˆ¼t3‹]ð·T˜»)Ó9Ë|Ž‹]ð·\˜ ÓãÑ ßƒîf‰¸¸‰ˆ¼uÍ‹Mà…É„³‹}à9}è„Ç‹Mè¾1Û‰Mð¹ƒEä‹}ä9}ØŒ§‹}à‰}èéâþÿÿ‹uè…ö„Ÿ‹uè9uð„Ø‰ò‹ˆ¼¾œ·|)þ9ñŽ‘·T ‰Uð‰Ö·¸Óæ‹H ò‹pf‰¸ˆ¶¹‹pˆTƒÁ‹Uð‰H¹+ˆ¼Óú‰Öf‰¸‹¼Lð‰ˆ¼·¸¾ º)ú9Ê·¼ ‰UðÓâ‹H Öf‰°¸f‰uì‹p¶U숶¹‹pˆTƒÁ‹Uð‰H¹+ˆ¼Óú‰Öf‰¸‹¼Lð‰ˆ¼ƒùŽ‘ƒë‹P·Û‰ßÓç þ‹x‰ñf‰°¸ˆ ¶ˆ¹‹pˆLƒÂ¹‰P‹¼)уêÓû‹Màf‰˜¸‰¼…É…NþÿÿƒEä1Û‹Uè¾¹Š‹}ä9}؉UðYþÿÿƒÄ[^_]öƒú 9·¸Â »‹ˆ¼)û9ÙŽ;·˜À ‰ÞÓæ·ˆ¸‰]ð‹X ñ‹pf‰ˆ¸ˆ ¶ˆ¹‹pˆLƒÃ‹uð‰X‹˜¼¹)ÙÓþ‰ñf‰ˆ¸Lðƒù ‰ˆ¼Žýƒê·ú‹P‰ûÓã‹H óf‰˜¸ˆ¶ˆ¹‹XˆL‹˜¼¹ƒÂ‰P)Ùƒë Óÿf‰¸¸‰˜¼é0ýÿÿ‰ÓéRýÿÿ´&‰}ð¾¹1Ûé7ýÿÿSý·ÒÓâƒÁ òf‰¸‰ˆ¼éïüÿÿ·¼ Óâù Öf‰°¸‰ˆ¼é(þÿÿ·¸Æ »‹ˆ¼)û9ÙŽr·˜Ä ‰ÞÓæ·ˆ¸‰]ð‹X ñ‹pf‰ˆ¸ˆ ¶ˆ¹‹pˆLƒÃ‹uð‰X‹˜¼¹)ÙÓþ‰ñf‰ˆ¸Lð‰ˆ¼ƒù Žéƒê ·ú‹P‰ûÓã‹H óf‰˜¸ˆ¶ˆ¹‹XˆL‹˜¼¹ƒÂ‰P)Ùƒë Óÿf‰¸¸‰˜¼é÷ûÿÿt&·T Óâ‰Öf °¸ ‰ˆ¼f‰°¸é¬üÿÿ‹ˆ¼‰Ó·°¸é˜üÿÿ´&·˜À Óã‰Þf °¸ ƒù f‰°¸‰ˆ¼þÿÿƒê·ÚÓãƒÁ óf‰˜¸‰ˆ¼éhûÿÿ¶ƒê ·ÚÓãƒÁ óf‰˜¸‰ˆ¼éCûÿÿ·˜Ä Óã‰Þf °¸ ‰ˆ¼f‰°¸éÇþÿÿ‰ö¼'U‰åWVSƒì ‹¸ ‰Uä‰MÜ…ÿuM‹ˆ¼·¸¸‹]ä·“»‰Þ)Ö9Ό‹]ä·³ÓæÑ þf‰°¸‰ˆ¼ƒÄ [^_]ˈ¼1Ò·¸¸醶‹uä4ž»‰uì·v)ó9Ët‹]ì·‰]ðÓã‰Ù‹X ù‹xf‰ˆ¸ˆ ‹x¶ˆ¹ˆLƒÃ‹}ð‰X‹˜¼¹)ÙÓÿ‰ùf‰ˆ¸L3ð‰ˆ¼; ƒ&ÿÿÿ‹˜¤·S‰]싘˜‹u춃…ö‰]Ø„Xÿÿÿ¶³@œéb‹]ä‰u蜳·s‰]Ô‰uà¾+uà9Κ·‹p‰]ðÓã‹H ߉ûf‰¸¸ˆ¶˜¹‹xˆ\‹˜¼ƒÁ‹uð‹}à‰H¹)ÙÓþLðf‰uðf‰°¸‰ˆ¼‹}苽`¢éb…Ûtv‹uØ+4½à¢éb¿)ß9Ï ·ö‰÷Óç·Mð‰uè‹p ù‹xf‰ˆ¸ˆ 7¶ˆ¹‹xˆL7‹¸¼‰ñ‹uèƒÁ‰H¹)ùÓþL;ðf‰uðf‰°¸‰ˆ¼‹}ìƒïÿÿ‰}ì‡k¶·@šéb‹]Ü<³·_‰]à»+]à9Ë#·?‰}èÓç‰ù·}ð Ï‹Hf‰}ð¶]ðf‰¸¸‹xˆ¶˜¹‹xˆ\‹¸¼ƒÁ‹]è‰H¹)ùÓûf‰]ðf‰˜¸‹]àL;ð‰ˆ¼‹µ`£éb…ÛuR‹ˆ¼·¸¸éþÿÿ·ÓãMà ßf‰}ðf‰¸¸‰ˆ¼é þÿÿ‹]ì·Óãñ ßf‰¸¸‰ˆ¼éÆýÿÿf‹}ì+<µà£éb¾)Þ9Î|·ÿ‹p‰}ìÓç‰ù‹xf Mðf‰ˆ¸ˆ 7‹x¶ˆ¹ˆL7ƒÆ¹‰p‹°¼‹}ì)ñéOýÿÿ·?·]ðÓçMà ûf‰]ðf‰˜¸‰ˆ¼éÿÿÿ‰ûÁë¶³@›ébé‹þÿÿ·ÿÓçÙf }ð‰ˆ¼f‰¸¸éýÿÿ·öÓæÙf uð·uð‰ˆ¼f‰°¸é1þÿÿ‹uä·¶‰uðÓæ‰ñ‹p ù‹xf‰ˆ¸ˆ 7¶ˆ¹‹xˆL7ƒÆ‹}ð‰p‹°¼‰Ù)ñÓÿT2ðf‰¸¸‰¼ƒÄ [^_]ô&¼'U‰åW‰ÏVSƒì‹ˆ¼ƒùަ‹H¶˜¸‹pˆ¶˜¹‹pˆ\ƒÁ‰H‹X‰ù‹pfÇ€¸Ç€¼ˆ ‰þfÁî‰ñ‹pf‰}ðˆL‹p‰ù÷шL·Mð‹p÷ÑfÁéˆLƒÃ…ÿ‰Xt#‰}ð1ö‰×t&¶7ƒÆ‹HˆƒÃ9uð‰XuèƒÄ[^_]Ã…ÉŽvÿÿÿ‹H¶˜¸‹pˆƒÁ‰Hé[ÿÿÿ¶¼'U‰å‹U‚”‰‚ ‚ˆ ‰‚$ ‚| ‰‚0 1ÀÇ‚ PébÇ‚, PébÇ‚8 (PébfÇ‚¸Ç‚¼vfÇ„‚”ƒÀ=uìf1ÀfÇ„‚ˆ ƒÀƒøuî0Àt&fÇ„‚| ƒÀƒøuîfÇ‚”Ç‚¬Ç‚¨Ç‚°Ç‚ ]Ãt&¼'U‰åƒì‹E‰]ô‹U ‰}ü‹]‰uø‹}‹ˆ¼ƒù *·ÿÓçƒÁf ¸¸‰ˆ¼‹uø‰Ù‹}ü‹]ô‰ì]éâýÿÿf·ÿ‰þÓæ·ˆ¸‰}ð‹x ñ‹pf‰ˆ¸ˆ 7¶ˆ¹‹xˆL7‰ñ‹°¼‹}ðƒÁ‰H¹)ñƒî Óÿf‰¸¸‰°¼ëŽvU‰å‹ES‹¼ƒút.ƒú~%‹P·˜¸‹HˆƒÂfÁ¨¸ƒ¨¼‰P[]ËP·˜¸‹Hˆ¶˜¹‹Hˆ\ƒÂ‰PfÇ€¸Ç€¼[]öU‰åWVSƒì‹E‹ˆ¼ƒù ŽM¾‹X‰òÓâ‰Ñ‹Pf ˆ¸f‰ˆ¸ˆ ¶ˆ¹‹PˆL‹¼¹ƒÃ‰X)ÑÓþJó‰óf‰°¸‰ˆ¼·B¡éb¾‰÷)×9ùކ·=@¡éb‰}ðÓç‹H û‹xf‰˜¸ˆ9¶ˆ¹‹XˆL;ƒÇ‹]ð‰x‹¸¼‰ñ)ùÓûT:ð‰Ùƒúf‰ˆ¸‰¼tMƒú~‹P‹HˆƒÂfÁ¨¸ƒ¨¼‰PƒÄ[^_]Ãf·5@¡éb‰¼Óæ óƒúf‰˜¸u³‹P‹Hˆ¶˜¹‹Hˆ\ƒÂ‰PfÇ€¸Ç€¼ƒÄ[^_]ûÓãƒÁf ˜¸‰ˆ¼f‰˜¸éçþÿÿt&U‰åWVSƒì‹]‹³„…öŽ ‹ ƒy,„“ ‰ØèMêÿÿ“$ ‰Øè@êÿÿ“”‹ƒ ‰Uä·“–‰EìƒúɃÁƒúÿ烃Ç…À‰MðfÇ„ƒšÿÿˆ—ÇEèÿÿÿÿ1À1ɉ}àë1f„“| …öt`9Ö„š‰Uè1ÀÇEðÇEàƒÁ9Mì|X‰ò‹}äƒÀ;Eà·t}9Ötâ;Eð|¶…Ò„J;Uèt fƒ„“| fƒƒ¼ …öu 1ÀƒÁ9Mì‰UèÇEðÇEàŠ}¨“ˆ ‹ƒ( ‰Uä·“Š ‰EìƒúɃÁƒúÿ烃Ç…À‰MðfÇ„ƒŽ ÿÿˆœÇEèÿÿÿÿ1À1ɉ}àë2f„“| …ötd9Ö„õ‰Uè1ÀÇEðÇEàƒÁ9Mì|\‰ò‹}äƒÀ9Eà·t~9Ötâ9Eð¶…Òt&„¡;Uèt fƒ„“| fƒƒ¼ …öuœ1ÀƒÁ9Mì‰UèÇEðÇEàŠ}¤‰Ø“0 èxèÿÿ¸fƒ»º …Åfƒ»‚ °…µfƒ»¶ °…¥fƒ»† °…•fƒ»² °……fƒ»Š ° uyfƒ»® ° umfƒ»Ž ° uafƒ»ª ° uUfƒ»’ ° uIfƒ»¦ °u=fƒ»– °u1fƒ»¢ °u%fƒ»š °ufƒ»ž °u fƒ»~ ÀƒÀ‹“¨ƒÀ‰Eð@D‹“¬‰ƒ¨ƒÀ ÁèƒÂ Áê9ÐC‹MƒÁ9Á†Ä9Â…x‹‹¼ƒù u·EƒÀ·ÀÓàƒÁf ƒ¸‰‹¼¹À¡ébº@éb‰Øèžóÿÿ1ÀfÇ„ƒ”ƒÀ=uìf1Àt&fÇ„ƒˆ ƒÀƒøuî0ÀfÇ„ƒ| ƒÀƒøuî‹Efǃ”ǃ¬ǃ¨…Àǃ°ǃ tF‹ƒ¼ƒøŽÔ‹C‹S·‹¸ˆ ‹S¶‹¹ˆLƒÀ‰Cfǃ¸ǃ¼ƒÄ[^_]Ãt&ƒø %fƒƒÀ éZüÿÿ‰uè1ÀÇEðÇEàéaüÿÿfƒƒÄ é5üÿÿƒø %fƒƒÀ éÿüÿÿ‰uè1ÀÇEðÇEàéýÿÿfƒƒÄ éÚüÿÿƒ»ˆ„{þÿÿ‹‹¼ƒù P·EƒÀ·ÀÓàƒÁf ƒ¸‰‹¼f‰ƒ¸‹“ ‹»( ‰UìƒÂƒù ‰}èŽé‹uì‹Sî·ö‰÷Óç‹K øf‰ƒ¸ˆ¶ƒ¹‹KˆD‹»¼ƒÂ¹‰S‰ò)ùÓúOõ‰Ðƒù f‰“¸‰‹¼ެ·uè‰òÓâ‹K ЋSf‰ƒ¸ˆ¶ƒ¹‹KˆD‹»¼ƒÂ¹‰S‰ò)ùÓúOõ‰Ðƒù f‰“¸‰‹¼Žs‹uð‹Sƒî·ö‰÷Óç‹K øf‰ƒ¸ˆ¶ƒ¹‹KˆD‹»¼¹‰ðƒÂ‰S)ùÓøOô‰Âf‰ƒ¸‰‹¼1Àëm¶°8¢ébƒÀ·¼³~ ‰þÓæ‹K ò‹sf‰“¸ˆ1¶‹¹‹SˆL2‹“¼¹ƒÆ‰s)уê Óÿ;Eðf‰»¸‰“¼t=‹‹¼·“¸ƒù ޶°8¢ébƒÀ·´³~ ÓæƒÁ Ö;Eðf‰³¸‰‹¼uËMì»”‰Ø‰ú³ˆ è*êÿÿ‹Mè‰ò‰Øèêÿÿ‰ñ‰ú‰Øè#ðÿÿé€üÿÿ‹M …É„1üÿÿ‹‹¼ƒù n·EÓàƒÁf ƒ¸‰‹¼‹M‰Ø‹U èQôÿÿé>üÿÿ‹UÇEðƒÂ‰ÐéØûÿÿ1ÀºÀÿóëÑêöÂtfƒ¼ƒ”…öƒÀƒø uâfƒ»¸ºu4fƒ»¼u*fƒ»Èu ëƒÀ=„»fƒ¼ƒ”t纉Q,é|øÿÿ‹U‹sƒÂ·Ò‰ÐÓà‰Á‹Cf ‹¸f‰‹¸ˆ ¶³¹‹{‰ñˆLƒÀ¹‰C‹ƒ¼)Áƒè Óúf‰“¸‰ƒ¼éGûÿÿ‹E‹SƒÀ·À‰ÆÓæ‰ñ‹sf ‹¸f‰‹¸ˆ ¶‹¹‹sˆLƒÂ¹‰S‹“¼)ÑÓø‰Áf‰‹¸J󉋼ésüÿÿ·u‹C‰òÓâ‹Kf “¸f‰“¸ˆ‹K¶“¹ˆTƒÀ¹‰C‹ƒ¼)Áƒè Óþf‰³¸‰ƒ¼éQþÿÿ…ÀŽHûÿÿ‹C‹S·‹¸ˆ ƒÀ‰Cé-ûÿÿfê·ÒÓâƒÁ Ѓù f‰ƒ¸‰‹¼Tüÿÿ·UèÓâƒÁ Ѓù f‰ƒ¸‰‹¼üÿÿ·Uðƒê·ÒÓâƒÁ Âf‰“¸‰‹¼éÀüÿÿ1ÒéNþÿÿ¶¿U‰å‹EV‹M S‹]‹ ‹°¤f‰ V‹°˜ˆƒÂ…ɉ t\¶›@œébqÿƒ€°fƒ„˜˜þÿv*Áî¶Ž@›ébfƒ„ˆˆ ‹€œ[^]ƒè9”À¶ÀÃf¶‰?šébë×´&fƒ„˜”ëÎU‰åƒìh‹E‰}ü‹} ‰]ô‰uøu°‰E°‹E‰E´‹E‰E¼‹ÇEÐÇEÔÇD$8‰EÀÇD$À¤éb‰4$èαÿÿ…À‰Ãt‰Ø‹uø‹]ô‹}ü‰ì]ÃÇD$‰4$è ³ÿÿƒø‰Ãu‹Eĉ‰4$èUÐÿÿ‰Ãëɉ4$èIÐÿÿƒûtƒûûu·ƒ}´¸ýÿÿÿDØë©»ýÿÿÿë¢U¸à¤éb‰å]öU¸U‰å]öU¸‰å+E]‹…`¥ébö¿U‰åƒì‹E¯E ‰EÉéj`v¼'U‰åƒì‹E ‰EÉé^`ffffffffU‰åWVSƒìT‹E‹U‹@‰Ñ‰E ‹‹R‹} ‰E°Tû‰U´‹Q ‹I‹w8‰U¸‰Ë+] ” ÿþÿÿ‹OL‰UÀ‹W(‰]¼»‰uЉMÈ‹OP‰UØ‹W0‰UÜ‹W4‰UÄ‹W<‰UÔ‰MÌ‹OT‰ßÓç‰ù‹} ƒé‰Mà‹OXÓã‰Ùƒé¨‰Mät!‰Ñt&¶ƒÀ‰E°ÓãƒÁÞ¨‰uЉMÔuæE¨‰ ‰h‰Ä‹t$‹|$‹T$(‹\$,‹l$ üët&9|$†w9t$ †m€ûw 1Àf­ˆÙ€ÃÓà ‹D$8!ЋD…ˆá(ãÓê„ÀuÁèªëÀ‰ÁÁé‰L$@ˆÁ¨„ €át%8ËsˆÍ1Àf­ˆÙ€ÃÓà ˆé(Ë1À@ÓàH!ÐÓêD$@€ûw 1Àf­ˆÙ€ÃÓà ‹D$<‹L$$!Ћ‰ÅÁíˆá(ãÓêˆÁ¨„Ï€átj8ËsˆÍ1Àf­ˆÙ€ÃÓà ˆé(Ë1À@ÓàH!ÐÓêʼnt$‰ø+D$9肵‹L$@‰þ)îÑùsf󥊈G‹t$‹l$ éôþÿÿfó¥‹t$‹l$ éäþÿÿt&ƒýu´9|$t®‹L$@ŠGÿˆÄÑùsˆGfó«‹l$ é¹þÿÿë¨@…é1À@ÓàH!ÐD$@‹D…é³þÿÿv¨@…á1À@ÓàH!Ðè‹L$$‹éþþÿÿf‰Á‹D$0÷Ù‹t$9è‚¿éƒ|$4u#)ÈÆ‹D$@9Èvw)Èó¤‰þ)îëm¶¼'‹D$49Áv8t$0Æ)Î)Á‹D$@9ÈvF)Èó¤‹t$‹L$49Èv6)Èó¤‰þ)îë,¶¿Æ)΋D$@9Èv)Èó¤‰þ)îë v¼'‰Áó¤‹t$‹l$ é¯ýÿÿ¨ t ÇD$Hë*ÇD$Hë ÇD$Hë‹t$ÇD$HëÇD$H‰t$‰|$‰\$,‰T$(‹l$‹$$‹Eðƒø†ˆƒø„Œ‹Mƒøº¼¥éb¸Ò¥ébEЉQ‹] Ç‹uÔ‹]‹}‰òÁê‰ÐÁâ÷Ø)Öº‰ñÓâ‹M´E°ƒê#UЃÁ‰)Á‹E‹]¸‰H‹EÀ‰_ ‹M)Ø‹] ‰A‰S8‰s<ƒÄT[^_]Ãuž‹} Ç ë“‹EÇ@ ¥ébé{ÿÿÿUWVSƒì$‹T$8‹L$<‹Bx‹šŒ9Ø‹B4‹Z||ÁëKÁã É$‹‚‹Zt9Ã|‰Ã‰\$‹r8‰t$‹jl<.‰|$ ‰ø÷؃à‰D$‹B,-)Å1í‹Bx‰D$Ɖt$·‰\$·\ÿ‰\$ ‹z@‹$ë!Ñ· O9é†àêˆÔ·Dÿ9ØuÝ‹D$·;D$uω$‹t$‹|$ ΋D$ºøþÿÿ¼´‹3u‹D3DuƒÂuéëqƒÂ©ÿÿuƒÂÁè,ƒÒ‹|$ )ø=}L‹T$8‹\$9Ø‹t$‹z@‹\$ ‹$éNÿÿÿ‹\$‰D$‰Jp9Ø}-‹t$Ɖt$·\ÿ‹z@‰\$ ‹$é!ÿÿÿ‹T$8ÇD$‰Jp‹T$8‹\$‹Bt9É؃Ä$[^_]ÃU‰åSƒì$¡h½éb‹]‰$艃øÿ‰EôtxÇ$èZ¡h½éb‰$èh‰Eô¡d½éb‰$èX‰$‰EðEð‰D$Eô‰D$è_Z‰Ã‹Eô‰$èB£h½éb‹Eð‰$è2Ç$£d½ébè9Z‰ØƒÄ$[]É$ÿÜÑébƒÄ$‰Ã‰Ø[]öU‰åƒì‹E‰$è?ÿÿÿɃøÀÃU‰åƒì‹E …Àtƒøt¸É t&‹U‰D$‹E‰T$‰$èŠ ¸É U‰åSƒì‹E ƒ=HPébt ÇHPébƒøtƒøt:ƒÄ¸[] »(àébû(àébtæ‹…ÀtÿЃÃû(àébuíƒÄ¸[] ‹EÇD$‰D$‹E‰$è ëªvU1À‰å]ÃU‰å‹E]ô&U‰å‹E]ÃU‰åSƒì¡ÐÑébÇD$ô¥éb] ƒÀ@‰$è‹E‰\$‰D$¡ÐÑébƒÀ@‰$è3èÎX´&¼'U‰åWVS‰Ãƒìl…ɉU ‰M¤u eô[^_]Ãv‹ °éb…Éޱ¡°éb1ö‹P9Úw‹xW9Ó‚ƒÆƒÀ 9ñá‰$èÔ …À„‚ÿÿÿ1Û1ö}àëfƒÆƒÃ ;5°éb!ÿÿÿ¡°ébØ‹…ÒtáUÄÇD$‰T$‹@‰$ÿœÑébƒì …À„M¡°éb‰|$ ‹‰D$‹EЉD$‹Eĉ$ÿ˜Ñébƒì듡̪éb…Àu»Ðªébt&‹;…ÿ…&ÿÿÿ‹s…ö…ÿÿÿ‹Cƒø…ƒÃ 9Ú†‡þÿÿ¶S¸èb‹ Cƒú‹±èbtBƒú ttƒútÇEä‰T$Ç$À¦ébèºûÿÿ¶8÷Ç€t!Ïÿÿÿ)Ïïèb47‰uäë(·8÷Ç€u])Ïïèbƒú47‰uät^ƒú t#ƒúu+¹Uäè´ûÿÿë‹)Êêèbò‰Uä¹Uäè–ûÿÿƒÃ ¸Äªéb9؇BÿÿÿéxþÿÿÏÿÿ)Ïïèb47‰uä¹Uäè`ûÿÿëȰéb‹C‰D$‹C‹@Ç$0¦éb‰D$èëúÿÿ‰D$Ç$Œ¦ébèÛúÿÿU‰åƒì¡DPéb‹…ÀtÿСDPébP‹@‰DPéb…ÀuéÉöU‰åSƒì‹ @ébƒûÿt"…Ût ÿ @ébƒëuôÇ$°éèbèbùÿÿƒÄ[]Ã1Ûë‰ÃC‹… @éb…ÒuðëȶU‰åƒì‹ $°éb…ÉtÉÃÇ$°ébÉë‘U‰åƒìH¡tPéb‰]ô‰uø‰}ü=Næ@»ÇEàÇEät÷Ћ]ô‹uø‹}ü£xPéb‰ì]ÃvEà‰$ÿdÑéb‹Eä‹}à‰EÔƒìÿPÑéb‰ÆÿTÑéb‰ÃÿhÑéb‰EÐE؉$ÿ€Ñéb3}Ô3}Ø3}Ü1÷ƒì1ß3}ЉøÿNæ@»÷Ðt‰=tPéb‹]ô‹uø‹}ü£xPéb‰ì]ø°¿D¿Oæ@»ëÜU‰åƒì(‹EU‰±ébÇ ³éb ÀÇ$³éb£ø°éb£,³éb‹EÇ$£ì°éb¡tPéb‰Eð¡xPéb‰Eôÿ„ÑébƒìÇ$ì¦ébÿ”ÑébƒìÿLÑébÇD$ À‰$ÿŒÑébƒìèùQU‰åWVSƒì¡€³éb…Àueô[^_]öÇ$„³ébÿHÑéb‹œ³ébƒì…Ût/‹=XÑéb‹‰$ÿÑébƒì‰Æÿ×…Àu …öt‹C‰4$ÿЋ[…Ûu×Ç$„³ébÿtÑébƒìeô[^_]Ãë U‰åSƒì¡€³éb…Àu1À‹]üÉÃÇD$ Ç$è=Q‰Ã¸ÿÿÿÿ…ÛtÜ‹EÇ$„³éb‰‹E ‰CÿHÑéb¡œ³éb‰œ³éb‰CƒìÇ$„³ébÿtÑéb1Àƒì럶¼'U‰åSƒì¡€³éb‹]…Àu 1À‹]üÉöÇ$„³ébÿHÑéb‹œ³ébƒì…Òt‹9Øu ëF‹9Ùt ‰Â‹B…ÀuñÇ$„³ébÿtÑébƒì1À‹]üÉËH‰J‰$èúOÇ$„³ébÿtÑébƒìëÙ‹B£œ³éb‰ÐëÚ¶¿U‰åƒì‹E ƒøtBrƒøuè6þÿÿ¸ÉÃè*þÿÿ¡€³ébƒøuêÇ€³ébÇ$„³ébÿDÑébƒìëÎt&¡€³éb…ÀtÇ€³éb¸ÉöÇ$„³ébÿlÑébƒìë×U1À‰å‹Uf:MZt]ÃR<:PEuó1Àfz ]”Àô&U1À‰å‹UVS‹] R<·r·J…öt%·ÉD 1ÒëƒÀ(‹H 9ÙwH9Ër ƒÂ9òrè1À[^]Ãt&¼'U‰åƒì8‰uø‹u‰]ô1Û‰}ü‰4$èÄNƒøv‰Ø‹uø‹]ô‹}ü‰ì]Ãf=èbMZuæ¡<èb¸èbPEèbuÏfz uÇ·J·B…ɉMät¸·À1ÿ\ëƒÃ(ÇD$‰t$‰$èµN…Àt’ƒÇ;}ärÝ1Ûë†t&U1À‰åƒìf=èbMZtÉË<èbºèbPEŠèbuæfy uÞ‹EÇ$èb-èb‰D$èÃþÿÿÉÃ1Àf=èbMZU‰åt]Ë<èbºèbPEŠèbuæfy uÞ·A]ô&U1À‰åƒìf=èbMZ‰$‹U‰t$t ‹$‹t$‰ì]Ë <èb¹èbPE±èbuÝf~ uÕ·^·N…ÛtÉ·ÉD1ÉëƒÀ(ö@' t…Òt°ƒêƒÁ9Ùré1Àë¢t&1Àf=èbMZU‰åt]Ë<èbºèbPEŠèbuæfy ºèb]DÂöU‰åS1Ûƒìf=èbMZt ‰ØƒÄ[]Ãt&¡<èb¸èbPEèbuÝfz uÕ‹EÇ$èb-èb‰D$èiýÿÿ…Àt¹‹X$ƒÄ÷ÓÁë‰Ø[]Ãt&U‰åƒì‰]ô1Ûf=èbMZ‰uø‹u‰}üt‰Ø‹uø‹]ô‹}ü‰ì]Ãf¡<èb¸èbPEèbuØfz uЋ¸€èb…ÿtƉ|$Ç$èbèçüÿÿ…Àt²Çèbë …ö~ƒîƒÇ‹W…Òuï‹G …Àuè1Û뎻èb_ ë„t&U‰åSƒì¡¤³éb…Àt9‹]üÉöP€úCt€úcu$¶P€úRt€úru¶P€úTtK€úttFƒê0€ú v>‰Ø‰$Xè ÿÿÿ…ÀtH¶€úMt€úmuâ¶P€úSt€úsuÔ¶P€úVt™€úvt”‰Øëĉ$ÿ\Ñéb…ÀQ£¤³éb…tÿÿÿt&Ç$ô¦ébÿxÑébƒì£¤³ébéVÿÿÿQL$=réƒ -=wë)Áƒ ‰à‰Ì‹‹@PÃÿ%¬Ñébÿ%°Ñébÿ%¨Ñébÿ%´ÑébffffffU¸‰å] U¸‰å] U‰åƒìÉéÄJU‰åƒì(E‰D$‹E ÇD$Ç$`‰D$ ‹E‰D$è±ÉÃU‰åƒì(‹EÇD$Ç$`‰D$‹E ‰D$ ‹E‰D$èqÉÃU‰Â‰åSƒìD‹E‰EØ‹E ‰EÜ‹E‰Eà‹EÛm؉EäÙå›ßàÝØ·ÀöÄtöÄtÇEô¿Eà1ÉëöÄuT¿Eà1ÉÇEô%€‹] ‰Eð‰D$‹E‰T$‰L$Ç$LPéb‰D$‹E‰D$Eô‰D$ E؉D$èƒÄD[]ÃöÄ@tÇEô¿Eà¹Ã¿ÿÿë¢ÇEô1É1Àëš¿EàÇEô‰Ááÿé>@éwÿÿÿ´&¼'U‰åSƒì$‹JöÅ@u‹Z 9Z$~€å u‹‹J ˆ ‹Z ƒÃ‰Z ƒÄ$[]Ë ‰Uô‰$‰L$èDI‹Uô‹Z ƒÃ‰Z ƒÄ$[]Ãv¼'U‰åWV‰ÖS‰ËƒìLUÔ‰EÄEä‰D$ÇD$‰$è63‹C …Àx9ÆOð‹C9Æ)ð…À‰C~ öC„Œ‰÷…ÿ‰]À~G‹UÄEä‰D$·‰D$EÔ‰$èç2…À‰Ã~%1ö¾D5ԃƋUÀèÿÿÿ‰Ø)ð…ÀèƒïƒEÄ…ÿ¹‹]Àë´&‰Ú¸ èäþÿÿ‹CPÿ…À‰SçƒÄL[^_]ÃÇCÿÿÿÿéwÿÿÿvƒè‰C‰Ú¸ è®þÿÿ‹CPÿ…À‰SuçéPÿÿÿ¶¿U‰åW‰×VS‰Ëƒì‰Eä‹A …Àx9ÂOø‹C9Ç}^)ø…À‰C~öCt^…ÿt61ö‹Uä¾2‰ÚƒÆèGþÿÿ9þuë‹CPÿ…À‰S~¶‰Ú¸ è$þÿÿ‹CPÿ…À‰SçƒÄ[^_]ÃÇCÿÿÿÿ먶ƒè‰C‰Ú¸ èîýÿÿ‹CPÿ…À‰Suçëë U‰åƒì…À‰]ø‰Ã‰uü‰Öt‰$èÔF‰Â‰ñ‰Ø‹uü‹]ø‰ì]éÿÿÿº» §ébëât&U‰åWVSƒì,…ÀÇA ÿÿÿÿt?‹yEäÆEä-uå‰EÔƒç 1Û¶ƒàß øˆƒÃƒûuì‹EÔV+UÔèµþÿÿƒÄ,[^_]Ëy÷ÇtEäÆEä+uå‰EÔë·v÷Ç@tEäÆEä uå‰EÔëEä‰EÔ‰Æë“ë U‰åW1ÿV‰ÖS‰Ãƒì<‰EØ‹A ‰UÜ…À‹AIy ƒÇöĉEàt fƒy…Ù‹A9ÇMǃÀƒàðè¦úÿÿD$ƒàðöEà€‰Eät‹}Ü…ÿˆ‹Eà$‰A‰ð‹}ä Ø„–¶‰$‰t$ÇD$ ÇD$ ‰MÔèQFƒÀ0ˆƒÇ‰$‰t$ÇD$ ÇD$ è}G‹MԉÉР؉Öt@9}ä„öAt¡fƒytš‰ø+Eä‰ÂÁúÁêЃà)ЃøuÆ,ƒÇévÿÿÿ¶‹Q …Ò~Uä)ú…Ò~1ÀÆ0ƒÀ9ÐuõÇ;}ä„Z‹Q…Ò~\Uä)ú…Ò‰Q~P‹A©Àtƒê‰Q‹Q …ÒˆÚöÄu3‹QZÿ…Ò‰Y~&‰Ë¶‰Ú¸ èdûÿÿ‹CPÿ…À‰Sç‰Ù‹A¨€t^Æ-ƒÇ;}äv‹uä‰Ëƒï‰Ú¾è1ûÿÿ9þrï‰Ù‹APÿ…À‰Q~‰Ë‰Ú¸ èûÿÿ‹CPÿ…À‰Sçeô[^_]Ë}äéƒþÿÿvöÄt"Æ+ƒÇë›v‰øºVUUU÷ê‰øÁø)Â×éþÿÿ¨@„yÿÿÿÆ ƒÇénÿÿÿ¶‰Ââú…ÿÿÿ‹QZÿ…Ò‰YŽ9ÿÿÿÆ0‹AƒÇPÿ…À‰Qíéÿÿÿv‹]Ø‹uÜ÷ÛƒÖ÷ÞéÛýÿÿ‹Y …Û„›þÿÿÆ0ƒÇéþÿÿ´&U‰åW‰ÏV‰ÖS»ƒì,ƒøo‰Eظ‰MÔ•ÁDضÁ‰UÜʼnÁ‰Uä‹U1ÀƒÁƒz IB ÃöBt fƒz…•‹U‹B9ÃLØCƒàðèÏ÷ÿÿ‹UÔD$ƒàð U܉Eà„¶UØ‹]àƒâ ˆUܶUä!òB0ˆƒÃ<9~ ƒÂ7 U܈Sÿ­þ1ÀÓïöÁ E÷Eø‰ø ðuÏ9]à„Ò‹E‹P …ÒŽDUà)Ú…ÒŽ71Àt&Æ0ƒÀ9ÐuõÃ;]à„~‹U‰Ø+Eà‹z9ÇŽî)Ç…ÿ‰z~$ƒ}Øot‹UöBtƒï…ÿ~ ‹E‹P …Òˆ wÿƒ}Øot‹Eö@t ¶UØÆC0ˆƒÃwÿ…ÿ~/‹Eö@…ɉ÷‰Þ‹]¸ ƒï‰Úè±øÿÿG…Àê‰ówÿ;]àv'‰}ä‹}‰uØ‹uàt&ƒë‰ú¾èƒøÿÿ9Þrï‹}ä‹uØ…ÿ~‹]f¸ ƒî‰ÚèaøÿÿF…Àêeô[^_]Ãf‰ØºVUUU÷ê‰ØÁø)ÂÓéTþÿÿ‹E¾þÿÿÿ¿ÿÿÿÿÇ@ÿÿÿÿé)ÿÿÿƒ}Øo…Óþÿÿ‹UöB„ÆþÿÿÆ0ƒÃé»þÿÿwÿéQÿÿÿ¶‹U‹B%=…àþÿÿ1ÀÆ0ƒÀ9øuõû¾þÿÿÿ¿ÿÿÿÿéÅþÿÿ‹E‹H …É„tþÿÿÆ0ƒÃéiþÿÿ‹]à‹Ubÿ÷ÿÿéþÿÿU‰åWV‰ÆSƒì<ƒxý„›·Pf…Òth‹F‰eЃÀƒàðèaõÿÿD$ƒàð‰EÔEàÇEà‰D$·F‰D$‹UÔ‰$èö*…À‰Ç~@1Û‹UÔ¾‰òƒÃè÷ÿÿ‰ø)Ø…Àç‹eÐeô[^_]Éò¸.èþöÿÿeô[^_]ö‰ò¸.èäöÿÿëÍfÇEàèd@Uà‰T$ ÇD$‹‰D$Eæ‰$è$-…À~·Uæf‰V‰Fé)ÿÿÿ·Vëòv¼'U‰åW‰ÏV‰ÖSƒì…É‹]‰EäŽE‹K9Ï}.)ù‰K…Éx%‹C 9È})Á…ɉK~!…ÀŽ®ƒé‰Kët&ÇCÿÿÿÿ¹ÿÿÿÿ…ÿ~ öC…k‹K…É~!‹Uä…Ò„ƒé…ɉKt ‹CöÄ„‹Eä…À…'‹CöÄ…ç¨@…/‹S…Ò~‹C%=„Ö…ÿŽõC‰E䶸0„Òt¾ÂƒÆ‰ÚèžõÿÿƒïuL‹C …ÀŽ.‰Øè÷ýÿÿ…ÿ‹C t!é-¶¸0„Òt¾ÂƒÆ‰Úèbõÿÿ‹C Pÿ…À‰S ÚƒÄ[^_]ÃöCt'fƒ{t ¸VUUU÷ï‰øÁø)ÂR9Ç„ ´&…ÿaÿÿÿézÿÿÿv‹C©À…îþÿÿöÄ…ûþÿÿƒé‰Kv‰Ú¸ èäôÿÿ‹CPÿ…À‰Sç‹Eä…À„Ùþÿÿ‰Ú¸-èÀôÿÿéÜþÿÿfƒ{„ŠþÿÿGºVUUU‰Eà÷ê‹EàÁø)ƒê…ÒŽjþÿÿ…Éé‰þÿÿ´&…ÉŽíƒêƒé…Òî‰KéCþÿÿ¶öC…Èþÿÿ…ÿ„ïþÿÿø‰C ‰Ú¸0è=ôÿÿƒÇxïéÑþÿÿv‹K…É޼ýÿÿƒé‰Kéµýÿÿ‹Eä‰Ùºèkôÿÿéæþÿÿ¶‰Ú¸+èôóÿÿéþÿÿƒê‰S‰Ú¸0èÝóÿÿ‹CPÿ…À‰Sç…ÿ þÿÿ‰Ú¸0è¼óÿÿéþÿÿ´&‰Ú¸ è¤óÿÿéÀýÿÿöC„aýÿÿt&é>ýÿÿ‰Ké…ýÿÿvU‰åWVyÿ¹gfffS‰þƒì,‰û‰E䉸‰Uà÷鉸Áø¿Áþ‰ÑÁù)Át¸gfffƒÇ÷éÁùÁú)ʉÑuê‹U‹B(9ÇLø‰Ð‹RƒÇ9ú_‹UÇBÿÿÿÿ‹E¹‹Uà‰$‹Eäènüÿÿ‹U‹B(‰B ‹B À‰Bƒà ƒÈEèßòÿÿ‹U‹B‰ÑDÿ‰B‰Ø‰òè×õÿÿƒÄ,[^_]Ã)ú‰P뤴&U‰åV‰ÆSƒì@‹@ …ÀxuƒÀ‹U‹M ‰D$‹]‰Uà‹EàUô‰Mä‰]è‰T$Uð‰$‹Eä‰T$‰D$‹Eè‰D$‹Eì‰D$ ¸ècñÿÿ‹Mðù€ÿÿ‰Ãt*‰Â‹Eô‰4$è¹þÿÿ‰$èá*ƒÄ@[^]ÃÇF ¸뀉‹Eô‰ñè€ôÿÿ‰$è¸*ƒÄ@[^]ÃU‰åVS‰Ãƒì@‹@ …ÀˆƒÛm‰D$UôÛ}à‹Eà‰T$Uð‰T$‰$‹Eä‰D$‹Eè‰D$‹Eì‰D$ ¸è¾ðÿÿ‹Mðù€ÿÿ‰ÆtQ‰Â‹Eô‰$èûÿÿëf‰Ú¸ è„ñÿÿ‹CPÿ…À‰Sç‰4$è*ƒÄ@[^]ÃÇC ¸élÿÿÿ´&‰Â‹Eô‰Ùè´óÿÿ‰4$èì)ƒÄ@[^]Ãt&U‰åWVS‰ÃƒìL‹@ ƒøŒ „æÛm‰D$UäÛ}ЋEЉT$Uà‰T$‰$‹EÔ‰D$‹E؉D$‹E܉D$ ¸èæïÿÿ‹}àÿ€ÿÿ‰Æ„Õƒÿý|`‹C 9ÇYöC…°‰4$èÇ9)ø…À‰C ˆº‹Eä‰ù‰ò‰$èûùÿÿë ‰Ú¸ è}ðÿÿ‹CPÿ…À‰Sç‰4$è)ƒÄL[^_]ÃöCu>‰4$èr9ƒè‰C ‹Eä‰ù‰ò‰$è½üÿÿ‰4$èå(ƒÄL[^_]ÃÇC ¸é ÿÿÿƒk ëʶÇC ¸éìþÿÿ)ø‰C é[ÿÿÿt&‰Â‹Eä‰ÙèTòÿÿë¥f‹S…ÒŽ;ÿÿÿЉCé1ÿÿÿt&¼'U‰åWVS‰Ãƒì\ÛmÙÀÛ}ÐÙå›ßà%E=„‡·UØ‰Öæ€…ŠÙå›ßàÝØ%E=„tfâÿ„tfêÿ?‹MÔf‰Už‹UЋs ƒþ‰u¬‡”…Éx·Ež¤ÑÒ…Éyöf‰Ež‰Ö‰Ï¬Î¹+M¬1ÀÑï‰}´1ÿÁá‰u°¾¥÷ÓæöÁ EþEðu°}´‹u´…öˆÒ‹E°‹U´¤ÂÀ‰E°‰U´‹}´º1À+U¬‹u° •­þÓïöÁ E÷Eø‰ò‰ù‰Ï ׄÀ‹{u¸‰u°‰]¬‰}¤¶E¤ç‰} ƒà ˆE¨ë‰$ÇD$ÇD$ èP9þ‰Ã„¶‰4$ÇD$ÇD$ è.‰<$ÇD$ÇD$ ‰Æè‰ÇƒEä‹E¸‰$‰D$èωt$‰$ƒÀ0‰E°è}‹U¸‰|$‰$‰E´èۉ¸‹J …É…ùþÿÿ‰T$‰•xÿÿÿ‰$èG‹•xÿÿÿéÜþÿÿ‹E‹UŒÇE”‰EÈé;üÿÿ´&‰4$ÇD$ÇD$ èx‰Æ‰Çé]ÿÿÿ‹Mƒ}‹UŒ‰MÈŽßûÿÿ‹E¤ƒè9EŒŒ_‹UŒ)‹E¤‹M…À‰Eä‰Mȉ·ûÿÿ)Á1À‰MÈÇEäé¤ûÿÿ‹U¬…Ò„Üøÿÿ‹M¬‰ $è«éÌøÿÿ¶ÙÀ‹M¤ØÁØ ©ébÝ]ÈmÌ@…É…LÙÀØ%©ébÝEÈÙÉÛé‡HÙÉÙàßéÝØÇE¸ÇE”‡EýÿÿéË÷ÿÿÇE€‹M…ɹOMƒù‰M‰Mä–Á!Á‹E‰…|ÿÿÿ‰E¤éçõÿÿ´&ÇE€é?úÿÿÇE€ë·‹M¸‰•xÿÿÿ‰$‰L$èÖ‹•xÿÿÿ…À‰üÿÿƒmĉ$ÇD$ÇD$ è‹•xÿÿÿƒ}€‰Ã‹…|ÿÿÿ‰E¤„æûÿÿ‹M”ÇD$ÇD$ ‰ $èæ‹•xÿÿÿ‰E”é½ûÿÿÝE¸ÙÀØòÙ}ÖÇEä·EÖ´ f‰EÔÙmÔÛ]ÐÙmÖ‹EЉEÐP0ÛEÐØÊˆW‰UÈÞéÙîÙÉÛéÝÙ‹‹Uä9U¤„¿‰]ÀÙ©éb‹]¤‹MÈë ‹Uä9Ó„šƒÂÜɉUäÙÁØóÙmÔÛ]ÐÙmÖ‹EЉEÐP0ÛEÐØËˆƒÁÞêÙîÙÊÛêÝÚzÁu¿ÝØÝØÝØ‹UÄ‹]À‰MÈÇEÀƒÂ‰U´éßöÿÿƒ}¨…júÿÿ‹U‹BƒÀ9E ŽXúÿÿƒEƒE ÇEœéDúÿÿ‰}ȉ}À‹}¤‰u´‹uÈÇEäë$¶‰$ÇD$ÇD$ 訃Eä‰Ã‹U¸‰$‰T$èc ƒÀ0ˆƒÆ;}äƉuÈ‹}À‹u´‰E°ÇE¬‹U˜…Ò„âƒ}˜„ƒ{Ž‚‹MÈë‰Á¶QÿAÿ€ú9…±9øuê‰MÈÆ1‹EÄÇEÀ ƒÀ‰E´éÆõÿÿ‹UŒ‰$‰T$è‰Ãé5ùÿÿƒ}¤ÇEä–Á!Á¸é^óÿÿ+EŒ1ÒEˆEŒé–üÿÿ‰$‰D$èB‰ÃéøøÿÿÝØ‹]À‰MÈ‹U˜…Ò„šÝØÝ؃}˜„ê‹EÄÇEÀƒÀ‰E´éfõÿÿÙÀ‹M¤ÇE”éÁóÿÿÝØÝØÝØÇE´ÇE¸ÇE”éõôÿÿÝEÈÙ}ÖÜ Í¸©ébÇEä·EÖÝE¸´ ‰]¸Ù©ébÙˉûf‰EÔët&ØÊƒÀ‰EäÙÀÙmÔÛUÐÙmÖ‹EÐ…Àt ÝÙ‰EÐÛEÐÞéëÝØƒÀ0ˆ‹EäƒÃ9ÈuÉÝÚÙÉÙ©ébÙÂØÁÙʉ]È‹]¸ÛêÝÚwLÞâÙÉßé†ïóÿÿÝÙÙîÙÉßéÝØz„1‹M”ÇEÀ‹EȉMÄë‰Ð€xÿ0Pÿtõ‰EÈ‹EăÀ‰E´ébôÿÿÝØÝØÝØÝØëÝØÝØ‹MÈéÄøÿÿ‹M˜‰ú‰u¬‹}¨‹u …É„Xƒ{ŽDƒ}˜„]‰}À‹}¬‰u´‰Öëmt&‹UȶE°ˆƒÂ‰Uȉ4$ÇD$ÇD$ è9÷‰$ÇD$ÇD$ Dø‰…xÿÿÿèö‹M¸‰L$‰Ã‰$èµ ‹•xÿÿÿ‰ÖƒÀ0‰E°‹E¸‰t$‰$èX…À„ƒ}°9‰}¬‹}À‰u”‹u´„̃E°ÇEÀ ‹UȶE°ˆ‹Mă‰UȃÁ‰M´é.óÿÿ‰$ÇD$è‹M¸‰L$‰Ã‰$èõƒøýÿÿu öE°…üüÿÿƒ{ŽDÇEÀ‹EÈë‰Ð€xÿ0Pÿtõ‹MĉEȃÁ‰M´éÆòÿÿØÀ‹UÄÛé‰U”‡‡þÿÿÙÉßéÝØŠe…_¨ÇEÀ…jþÿÿ‹EÈé:þÿÿ‹B‰$èº H ‰Â‰MÈ‹M”‹AƒÁ ‰L$‰•xÿÿÿ…‰D$‹Eȉ$è©‹•xÿÿÿÇD$‰$è3‰ÂéŸ÷ÿÿƒÂ‰MȈ‹UÄÇEÀ ƒÂ‰U´éòÿÿƒ}˜„â÷ÿÿƒ}°9‰ú‰u¬‹}¨‹u to¶E°‹MȃÀˆ‹EăÁ‰MȉU”ÇEÀ ƒÀ‰E´éÒñÿÿ‰ú‹}¨‰u¬‹u ‰U”é¤ûÿÿƒ{…²ýÿÿ…ÀõÇEÀƒ{Žš‰U”ÇEÀéBþÿÿ‰U”‹EÈÆ9ƒÀ‰Áé…ûÿÿ‹CÇEÀ…À…lûÿÿ‹EÈé€þÿÿ‰MȃÂéöÿÿÝØÝÙÝÙ‰UÈëÝØÝÙÙîÙÉßéÝØŠÞ…Ø‹U”ÇEÀƒÂ‰U´éFñÿÿ‹Uö…¿öÿÿƒ}°9‰ú‰u¬‹}¨‹u „oÿÿÿƒ}´Ž$ƒE°ÇEÀ ‹MȶE°ˆ‹EăÁ‰MȉU”ƒÀ‰E´éÇðÿÿÝØÝØÝØÝØ‰ÑéYõÿÿ‰•xÿÿÿ‰$ÇD$èš‹M¸‰L$‰Ã‰$èy‹•xÿÿÿƒøŽ˜ƒ}°9„ëþÿÿƒE°ÇEÀ éÂþÿÿ‹MĉM”‹MÈéûôÿÿ‹M”ÇEÀƒÁ‰M´énðÿÿÇEÀ‹EÈéãûÿÿ‹U”ÇEÀ‹EȉUÄéÎûÿÿ…åøÿÿÝØÝØ‹MÄÇEÀƒÁ‰M´é+ðÿÿƒ{¸DEÀ‰U”‰EÀéŸüÿÿÇEÀ …7þÿÿöE°„-þÿÿéLÿÿÿƒ{ÇEÀÖþÿÿƒ{É÷уá‰MÀéÃþÿÿƒ{ÇEÀ…«üÿÿé,þÿÿU‰åƒìH…Éf‰UäufúÿwZˆ¸ÉÃfUô‰T$‹U‰D$EäÇEôÇD$‰T$ÇD$ ‰D$ÇD$‰ $ÿ Ñébƒì …Àt‹Uô…Òt­è”Ç*¸ÿÿÿÿÉÃë U‰åƒì8‹E‰]ô]ã‰}ü·} ‰uø…ÀEØ¡ÀÑéb‹0ÿpPéb‰ú‰4$‰Á‰Øè7ÿÿÿ‹]ô‹uø‹}ü‰ì]Ãv¼'U‰åW1ÿVSƒì<‹]ÿpPéb‰EÔ¡ÀÑéb‹‰EЋE ‹0…öt;…Ûth‹M…Éuë9ÃÇ€{ÿt?ƒÆ9}v'‹Eз‹MÔ‰$‰ØèÄþÿÿ…À׿ÿÿÿÿƒÄ<‰ø[^_]ËE ‰0ƒÄ<‰ø[^_]ËE ƒïǃÄ<‰ø[^_]Ë]…ÛtÈ]ãëÇ€|ât!9}vµƒÆ‹Eз‹MÔ‰$‰ØèZþÿÿ…ÀØë”ƒïë“U‰åƒìX‰uø1ö…Ò‰]ô‰Ã‰}ü‹}u‰ð‹]ô‹uø‹}ü‰ì]ô&…ɾþÿÿÿtዉEäǶ„À„¡ƒ}†§€}ätGˆEåEäÇD$‰\$ÇD$ ‰D$‹E ÇD$‰$ÿ|Ñébƒì…À„¸¾étÿÿÿ¶À‰D$‹E ‰UÔ‰MЉ$ÿpÑéb‹UÔ‹MЃì…Àt4ƒù†’ÇD$‰\$ÇD$ ‰T$ëŽfÇ1öéÿÿÿt&‹E …Àu¶¾f‰éÿÿÿ‹E ÇD$‰\$ÇD$ ‰T$ÇD$‰$ÿ|Ñébƒì…Àt ¾éÆþÿÿèïƒÎÿÇ*é³þÿÿ¶ˆé©þÿÿë U‰åƒì8‹E‰]ô]æ‰uø‹u‰}ü…ÀEØ¡ÀÑébfÇEæ‹8ÿpPéb…öº°³ébEÖ‹M‰$‹U ‰|$‰D$‰Øè.þÿÿ‹]ô‹uø‹}ü‰ì]ÃU‰åWVSƒì<‹EÇEÔ¬³éb‹u ‹}…ÀDEÔ1Û‰EÔÿpPéb…ö‰EÌ¡ÀÑéb‹‰EÐt]‹…ÒtW…ÿt]‹E…Àut&ëF‹ÃÂ9]‰v'ƒÇ‹EЋM‰D$‹EÌ)Ù‰D$‹EÔ‰$‰øèžýÿÿ…ÀÌ…Àu;]vsǃÄ<‰Ø[^_]ËM}æfÇEæ…Éuëä‹ÃÂ9]‰v׋EЋMЉD$‹ẺD$‹EÔ‰$‰øèAýÿÿ…ÀÑë³t&¼'U‰åƒì(¡ÀÑéb‰]ø‹]‰uüfÇEö‹0ÿpPéb…Ûº¨³ébEÓ‰$‹U‰t$‰Á‰L$‹M Eöèéüÿÿ‹]ø‹uü‰ì]ÃU‰åS1Ûƒì‹Mƒù~¸ÀƒÃP9Ê|ô‰$覉ƒÄƒÀ[]Ãt&¼'U‰åVSƒì‹E‹]‹u ‰$è§ÿÿÿ¶ „Ɉ‰ÂtƒÃ¶ ƒÂƒÃ„Ɉ uñ…öt‰ƒÄ[^]ö¼'U‰åƒì‹U‹JüBüºÓâ‰H‰P‰EÉéÛt&¼'U‰åWVSƒìl‹E ‹M‹P1À;QÒ‹] BÿƒÂ‹M ‰E¼‹E ƒÃ‰]°‹]L‘‰MÀ‹LƒÃ‰]¸‹]ƒÁ‹D“1Ò÷ñ…À‰EĉE´„Ç‹]°‹M¸ÇEÈÇEÌÇEàÇEä‹EÄ÷#‹1ÇE܉E ‹EÈE ‰U¤‹UÌU¤ƒÃ‹U¤1ÿ‰Ð1Ò‰UÌ‹U ‰EȉUØ+uØ}Ü+uà}äÇE䉸ƒà‰Eà‰1ƒÁ9]Às£‹E¼‹MƒÀ‹|…ÿu79E¸s&‹0…öu ‹M¸‹U¼ë t&‹…Ûu ƒèƒê9Árð‰U¼‹E¼‹]‰C‹U ‹M‰T$‰ $è‚…Àˆ¦‹]Ä1ö‰uä‹M¸‹u°‹}ÀƒÃ‰]´1Û‰]à‹1҃ƉUÜ1Ò‰EØ‹]Ø‹ÇEÔ‰]Ð+EÐUÔ+EàUäÇEä‰Óƒã‰]à‰ƒÁ9÷s¾‹E¼‹UƒÀ‹|‚…ÿu7‚9E¸s&‹0…öu ‹M¸‹U¼ë t&‹…Ûu ƒèƒê9Árð‰U¼‹]¼‹M‰Y‹E´ƒÄl[^_]ÃU‰åƒì¡hPéb‰]ø‹´³éb‰uü‹u…Àu‰5´³éb‰Ø‹uü‹]ø‰ì]Ãè+ÂÿÿÇD$©éb‰$ÿ`Ñébƒì…Àt#‰4$ÿЋuüÇhPéb£´³éb‰Ø‹]ø‰ì]ÃvÇhPébë¢t&U‰åSƒì‹dPéb…Òu¡´³éb‹]üÉÃt&è»ÁÿÿÇD$+©éb‰$ÿ`Ñébƒì…À‰ÃtÿУ´³éb1Ò…Û‹]ü•‰dPébÉá´³ébëçU‰åVS‰Ãƒì¡Ä³ébƒøtE…Àuh°ð‡ijéb…ÀuQ‹5lÑébÇ$à³ébÿÖƒìÇ$ø³ébÿÖƒìÇ$ 0ébèA³ÿÿÇijéb[Åà³éb‰$ÿHÑébƒìeø[^]Ãøt7¡Ä³ébƒøu!‹5ˆÑébt&Ç$ÿ֡ijébƒìƒøtêƒøt®eø[^]ÃÇijébë›fU¸‰åSƒìð‡ijébƒøu‹DÑébÇ$à³ébÿÓƒìÇ$ø³ébÿÓƒì‹]üÉÃt&U‰åƒìƒ=ijébtÉÃ@Åà³éb‰$ÿtÑébƒìÉô&U1À‰åƒì(‰}ü‹}‰]ô‰uøè·þÿÿƒÿ ‹4½ ´éb…ötY‹‰½ ´ébë*»‰ùÓãÁèÁà‰$è® …À‰Æt‰~‰^1ÀèkÿÿÿÇFÇF ‰ð‹]ô‹uø‹}ü‰ì]Ë5lPéb»‰ùÓãÁè‰òê`´ébÁúú w–Æ£lPébët&U‰åSƒì‹]…ÛtBƒ{ ,1Àèõýÿÿ‹C‹… ´éb‰‰… ´ébƒÄ1À[]éÖþÿÿ¶ƒÄ[]é ¶ƒÄ[]Ãv¼'U1ɉåWVSƒì<‹E‹}‹]‹@ƒÇ‰ÞÁþ‰EØ‹E ‰}Ô‰ÂÁú‰Eà‰Uä‹}Ô‹‹}䝸÷eàú‹}ÔØò1ö‰Ó‰ƒÁ9MØÙ‰ð Ðt‹U‹}Ø;z}‹UØ‹}‰ÐƒÀ‰\—‰G‹EƒÄ<[^_]ËBƒÀ‰$èJþÿÿ…À‰Çt3‹UH ‹BƒÂ ‰T$‰ $…‰D$èA ‹E‰$èÖþÿÿ‰}ëœÇE르&U‰åƒìÇ$èîýÿÿ…Àt ‹UÇ@‰PÉÃt&¼'U‰åWVSƒì\‹u‹U ‹~‹Z9ß} ‰ø‰ß‰Ã‰ð‰Ö‰Â;F‰EÈŸÀ¶ÀF‰U¸‰$èŽýÿÿ‹U¸…À‰EÄ„þƒÀ‹MȉEЋEÄLˆ9MЉM¼s‹EЉ}à‹}¼‰ÁǃÀ9Çwó‹}à‰MÐJTšF9Ñt¾‰EÀ‰uÔ‰M؉UÌsr‹EØ‹ƒEØ…À‰EÜtT‹MЋ]ÀÇEàÇEä‹EÜ1ÿ÷#‹1‰E°‹Eàu°‰U´‹Uä}´E°U´ƒÃ‹U´‰Ð1Ò‰Uä‹U°‰Eà‰ƒÁ9]Ôw‰‹MØ9MÌvƒEÐ뎋uÈ…ö~(‹U¼‹E¼‹Züƒè…Ûu‹UÈë ƒè‹…Éuƒê…Òð‰UÈ‹EÈ‹MĉA‹EăÄ\[^_]ô&U‰åWVSƒì,‹] ‹}‰Øƒà…„Áû…Ûts‹5À³éb…öu镉ÆöÃu9ÑûtY‹…Àuï°èøúÿÿ‹…Ò„š¸‰Uäèáûÿÿ‹UäöÉÖtδ&‰t$‰<$è$þÿÿ…Àth‰<$‰Eäè¥üÿÿ‹EäÑû‰Çu§ƒÄ,‰ø[^_]Ë…tªéb‰<$ÇD$‰D$è×üÿÿ…À‰Ç…Wÿÿÿëϸèqúÿÿ‹5À³éb…öt2¸è]ûÿÿéJÿÿÿ1ÿ먉t$‰4$è¨ýÿÿ…À‰Â‰tèÇéGÿÿÿÇ$qèYýÿÿ…À‰Æ£À³ébtÆÇ믶U‰åWVSƒì,‹E‹u ‰Á‹P‹@‰óÁû|‹A9Ç~ ÀƒÂ9Ç÷‰$èûÿÿ…À‰E䄉ƒÀ…Û~1Òt&ǃÂ9Úuò‹]äD“‹]‹U‹KƒÂƒæ‰uÜL‹‰MàtW¹ )ñ1ö‰}؉Ïf‹¶MÜÓã‰ù ó‰‹2ƒÀƒÂÓî9Uàwã‹}؃þ‰0ƒßÿ‹]äƒï‹E‰{‰$è4ûÿÿ‹EäƒÄ,[^_]Ë]à¶‹ ƒÂ‰ƒÀ9ÓwòëÈU‰åƒì ‰t$‹M‹u ‰$‰|$‹A‹V)Ðu"<•YT9L>ƒéƒê‹192u9Órð‹$‹t$‹|$‰ì]ÃÀ‹$ƒÈ‹t$‹|$‰ì]Ãv¼'U‰åWVSƒìL‹u‹] ‰4$‰\$èuÿÿÿƒø„ŒF1ÿ‹F‰$è©ùÿÿ…À‰EЄì‰x ‹FV‰UØ‹}Ð1Ò‹M؉Uät†‰EÌ‹CƒÇ‰uÈs‰MĉuÀDƒ‰EÔ1À‰Eàf‹]Ä1É‹uÀ‹‹1ö)Úñ+UàMäƒEÀƒEĉȃà‰Eà‹EÀÇE䉃Ç9EÔwÄ‹UÄ‹Eà‰UØ‹MØ9MÈ‹Uäv9‹]È÷щ}àÙÁéƒÁ‰MÔ1É‹}Ø1ö‹‹}à)ÃÖ1Ò‰ðƒà‰ƒÁ;MÔuß<‹_üGü…Ûu‹Ũèƒê‹…Étô‰UÌ‹UÌ‹EЉP‹EЃÄL[^_]ô&Ç$è”øÿÿ…À‰EÐtÛÇ@Ç@‹EЃÄL[^_]Ãt&‰ð¿‰Þ‰Ãé¬þÿÿU¹ ‰åƒì0‹E‰uø‰}ü‹} ‰]ôP‰Uä‹PT‹‰Ö½Ãƒð)Áƒø ‰F¹ ‰Þ)ÁÓîÎð?‰uì1ö9UäÇEès‹rüÓîH‹}üÓã Þ‹]ô‰uè‹uøÝEè‰ì]Ãt&1ÿ9Uäs‹züƒîƒè tP‰Áº Óã)ÂËð?‰Ñ‰]Ô‰ûÓë‹MÔÇEè Ù1Û;uä‰Mìv‹^ü‰ÑÓë‰Á‹uøÓç û‹}ü‰]è‹]ôÝEè‰ì]ÃËð?‹uø‰]ì‹]ô‰}è‹}üÝEè‰ì]ÃfU‰åƒìHÝE‰]ôÝ]à‰uø‰}üÇ$è?÷ÿÿ…À„‚‹]ä‹}à‰Úãÿÿÿâÿÿ‰ÑÁëÉ…ÛEÑ…ÿtg¼÷‰ñÓï…ö‰}Ô„ÇEà ‰×)uà¶MàÓç‹MÔ Ï‰ñ‰xÓêƒú‰P҃…ۉPt@‹M”Íûÿÿ‹}‰º5)ò‰‹]ô‹uø‹}ü‰ì]üÊÓê…Û‰Pq ºÇ@uÀ‹Mî2‹}‰1½LÁâƒñ)ʉ‹]ô‹uø‹}ü‰ì]Ãv‹}Ô‰xévÿÿÿt&U‰å‹U ‹E¶ „ɈtƒÂ¶ ƒÀƒÂ„Ɉuñ]ÃU‰åWVSƒì‹u‹M ‹}‹V‰ËÁûƒÇ‰ø9Ó‹T–ƒÃ‰UðƒÂƒá‰Uäžr‰M섇‹MìÇEè )Mè‹M‹\™¶MìÓëJ9Mäv=‹Eð)ЃèÁèƒÀ‰Eð1Àf‹T†¶MèÓâ¶Mì Ú‰‡‹\†ƒÀÓë;Eðuß‹uD†P…Û‰E‹M)øÁø…À‰AuÇAƒÄ[^_]Ã9uävÝ‹Eð÷Ò 1ÀÁéƒÁ‹†‰‡ƒÀ9Èuó‹UD‚ë·t&U‰å‹MS‹AQ\1À9Úsƒyt ë‹ …ÉuƒÂƒÀ 9Ówð[]ËI¼ÉÈ[]á`½ébU‰å]‹Ãt&U‰åƒì‰]ø‰uüèµÿÿ…À‰Ãt*‹5`ÑébÇD$ ªéb‰$ÿÖƒì…À£pPébt ‹]ø‹uü‰ì]ÿà‹]ø‹uüÇpPébÐ<éb‰ì]ë:ÇD$´ªéb‰$ÿÖƒì…À£`½ébtÒ‹]ø‹uüÇpPéb0<éb‰ì]éiÿÿÿ‰ö¼'U‰åƒìÇD$Ç$èÞÇD$.‰$èÖ‰Â1À…Òt ƒÂ‰$èËÉÃÿ%Òébÿ%ÄÑébÿ%üÑébÿ%ÌÑébÿ%Òébÿ%Òébÿ%$Òébÿ%0Òébÿ%ØÑébÿ%ÈÑébÿ% Òébÿ% Òébÿ%äÑébÿ%ÔÑébÿ%¼Ñébÿ%àÑébÿ%ìÑébÿ%ôÑébÿ%(Òébÿ%øÑébÿ%Òébÿ%Òébÿ%,Òébÿ%Òébÿ%Òébÿ%ðÑébU‰å‹E‹U ‹Mð±]ô&¼'U‰å‹E‹U ‹Mð±] U‰åƒì(‰}ü‹}‹E‰]ô‹M‹] …ÿ‰uø‰E܉ΉEä‰Úu9ÙvG÷ñ‰Ð‹]ô1Ò‹uø‹}ü‰ì]Ã9ßwL½Çƒð‰EàuQ;Mä‡Ý‰Ú‹]ä)Ëú‰]ä‹Eä‹]ô‹uø‹}ü‰ì]Ã…Éu ¸1Ò÷ñ‰Á‰Ø1Ò÷ñ‹Eä÷ñ량ڋuø‹]ô‹}ü‰ì]öMà‰ø¿ +}à‰òÓà‰ùÓê¶Mà ‹E܉Uä‰ÚÓæ‰ùÓê¶Mà‰uØÓã‰ùÓè¶Mà Ø‹]Ü÷uäÓã‰]܉Ó÷æ‰Ö‰Â9ó‰ñr39EÜr*‹EÜ)Ð˶Mà‰Ú‹uøÓè‰ù‹}üÓâ¶Mà Љڋ]ô‰ì]ÓêÃ9óuÒ‰ñ‰Â+UØMäëÆ9ß‚ÿÿÿvéÿÿÿU‰åƒì(‹E‰uø‹M‹u‰]ô‹] …À‰}ü‰Ï‰uàu29ÙwX…Éu ¸1Ò÷ñ‰Á‰Ø1Ò÷ñ‰Ã‰ð÷ñ‰Ú‰Æ‰ð‹]ô‹uø‹}ü‰ì]Ã1Ò1ö9Øwé½Ðƒò‰Uäu7;Màv9؉òsÓ1Ò¾ëÊv‰Ú‰ð‹]ô÷ñ‰Æ‹}ü1Ò‰ð‹uø‰ì]ô&¶Mä‰Â¸ +Eä‰þÓâ‰ÁÓî¶Mä Ö‰Ú‰uÜ‹uàÓç‰ÁÓê¶MäÓã‰ÁÓî Þ‰ð÷u܉ӉÆ÷ç9Ór‹}à¶MäÓç9Çs9Óuƒî‰ð‹]ô1Ò‹uø‹}ü‰ì]ÃU‰åƒìèÔþÿÇ$àèbèÙ¢ÿÿÉÃÿÿÿÿ€@ébÿÿÿÿ@éb`¢ébÀ¡éb`£éb`¤ébÿÿÿÿÿÿÿÿ°@éb@ÿÿÿÀ?`´éb@<ébNæ@»±¿Dlibgcj-11.dll_Jv_RegisterClasses1.2.8–0w,aîºQ ™Ämôjp5¥c飕dž2ˆÛ¤¸ÜyéÕàˆÙÒ—+L¶ ½|±~-¸ç‘¿d·ò °jHq¹óÞA¾„}ÔÚëäÝmQµÔôÇ…ÓƒV˜lÀ¨kdzùbýìÉeŠO\Ùlcc=úõ È n;^iLäA`Õrqg¢Ñäjm ¨Zjz Ïäÿ “'® ±ž}D“ðÒ£‡hòþÂi]Wb÷Ëge€q6lçknvÔþà+Ó‰ZzÚÌJÝgoß¹ùùホC¾·Õް`è£ÖÖ~“Ñ¡ÄÂØ8RòßOñg»ÑgW¼¦Ýµ?K6²HÚ+ ØL ¯öJ6`zAÃï`ßUßg¨ïŽn1y¾iFŒ³a˃f¼ Òo%6âhR•w ÌG »¹"/&U¾;ºÅ( ½²’Z´+j³\§ÿ×Â1Ïе‹žÙ,®Þ[°Âd›&òc윣ju “m© œ?6ë…grW‚J¿•z¸â®+±{8¶ ›ŽÒ’ ¾Õå·ïÜ|!ßÛ ÔÒÓ†BâÔñø³ÝhnƒÚ;[&¹öáw°owG·æZˆpjÿÊ;f\ ÿžei®bøÓÿkaEÏlxâ  îÒ ×TƒN³9a&g§÷`ÐMGiIÛwn>JjÑ®ÜZÖÙf ß@ð;Ø7S®¼©Åž»ÞϲGéÿµ0ò½½ŠÂºÊ0“³S¦£´$6к“×Í)WÞT¿gÙ#.zf³¸JaÄh]”+o*7¾ ´¡Ž ÃßZï-A1‚b62ÃS-+ÅldEôw}†§ZVÇ–AOŠÙÈI»ÂÑŠèïúËÙôã Oµ¬M~®µŽ-ƒžÏ˜‡QÂJ#ÙSÓpôx’AïaU×®.æµ7×µ˜–„ƒY˜‚©›Ûú-°šË6©]]wællÿß?AÔžZÍ¢$„•㟌 F²§aw©¾¦áèñçÐóè$ƒÞÃe²ÅÚª®]]ëŸFD(Ìkoiýpv®k19ïZ* ,  m8ó6Fß²]ÆqTpí0ekô÷ó*»¶Â1¢u‘‰4 û¼Ÿº„yÞ©%8ï²<ÿyós¾Hèj}ÅA<*ÞXOyðD~bé‡-OÂÆTÛŠ”@»ƒè#¦ÂÙ8¿ Å 8Lô»!§– Ζ Ì\H1×E‹búnÊSáwT]»ºl £Ö?ˆ—–‘P˜×Þ©ÌÇÒúáì“Ëúõ\×bræykÞµT@Ÿ„OYX#Úp8$›A#=§kýeæZæ|% ËWd8ÐN£®‘⟊!̧3`ý¼*¯á$­îÐ?´-ƒŸl² †«$HÉêSÐ)F~ûhweâöy?/·H$6t 5*ò¼SK³HRpÞey1ï~`þóæç¿Âýþ|‘ÐÕ= ËÌú6Šƒ»‘šxT¼±9e§¨K˜ƒ; ©˜"Éúµ ˆË®O]ï_lôFÍ?ÙmŒÂtCZó#AêÁplÁ€AwØG×6—æ-ŽÅµ¥„„¼ŠAq[»Zh˜èwCÙÙlZO-_~6 œ-'Ý>˜¹S1ƒ b®‹ÑSµ’ÅôÝWôïÄ”§ÂïÕ–Ùöé¼®¨·kÞ1œ*ï*…íykʬHpÓo]ø.*Fáá6Þf ÅcTèT"eóMåó²¤Â©g‘„0& Ÿ)¸®ÅäùŸÞý:ÌóÖ{ýèϼk©€ýZ²™> Ÿ²8„«°$,ñ52F*sw1´ápHõÐkQ6ƒFzw²]cN×úËæáÒ̵Ìù„×àJ–¯ #¶Èp ‰A»„F]#l8Ä?1…(B˜Og©T~ÀúyUËbLÅ8^ô#˜§³Ü–ªTåZ1Oü™bbרSyÎOáIV~úP•-×{ÔÌbŠ-R»–4‘è»ÐÙ ìó~^­ÂeGn‘Hl/ Suè6:© #jT$+e?äy§–¥H¼f‘¤'*нà¼Ëò¡ÐëbÞýÀ#ïæÙ½á¼üЧ ?ƒŠ&~²‘?¹$ÐpøËi;FæBzwý[µkeÜôZ~Å7 Sîv8H÷±® ¸ðŸ¡3Ì?Šrý$“7jÂnÔ„Y¾Fܨ ëÂ˲|…O¸Q;ÑÖ…— áïU dù S“Ø -ž =G\ p£&GÉäw¢)`¬ /›aíÂß«õµiÈò5ÿ˜÷¦&±‘LsZ<#0þzޏMäzàFM8×,9Ž’É;¹ø :<îD? „†>R:À(ôq-Ãv³,šÈõ.­¢7/Àšp÷çXq®Ys™3Ür%“w+OQvrñtE›Õux܉~O¶K }!bÏ|¤t€y“BxÊ zýÊÆ{°.¼l‡D~mÞú8oéúnl†µk[ìwjR1h58ói¯b?mcf«+aQÁé`Ôצeã½ddº"fiàg Ë×H¡INSKyu‘JücÞOË N’·ZL¥Ý˜M˜šÄF¯ðGöN@EÁ$‚DD2ÍAsX@*æIBŒ‹CPhñTg3U>¼uW Ö·VŒÀøS»ª:Râ|PÕ~¾Qè9âZßS [†ífY±‡¤X4‘ë]û)\ZEo^m/­_€5á·q÷àîϱâÙ¥sã\³<ækÙþç2g¸å zä8J&ï äîVž¢ìaô`íäâ/èÓˆíéŠ6«ë½\iêð¸ýÇÒÑüžl—þ©Uÿ,úzØûBÄžùu®\øHéóƒÂò&=„ðWFñ”A ô£+Ëõú•÷ÍÿOö`]xÙW7ºØ‰üÚ9ã>Û¼õqÞ‹Ÿ³ßÒ!õÝåK7ÜØ k×ïf©Ö¶ØïÔ²-Õ¤bÐ3ΠÑjpæÓ]$Òþ^Å'”œÄ~*ÚÆI@ÇÌVWÂû<•â‚ÓÁ•èÀ¨¯MËŸÅÊÆ{ÉÈñ ÉtDÌCm†ÍÓÀÏ-¹Î@–¯‘wüm.B+’(铜>¦–«Td—òê"•Å€à”øÇ¼ŸÏ­~ž–8œ¡yú$oµ˜w™J»1›}Ñóš05‰_KŒ^á Ži‹Ï쀊Û÷B‹‚I‰µ#ƈˆdšƒ¿X‚æ°€ÑÚÜTÌ“„c¦Q…:‡ rÕ† Ðâ©—º ¨Îfªùn¤«|xë®K)¯¬o­%Æ­¬ñ§/ë3¦vUu¤A?·¥Ä)ø óC:¡ªý|£—¾¢Ðsĵç´¾§@¶‰Í‚· ÛͲ;±³bI±Ue‹°h"×»_HºöS¸1œ‘¹´ŠÞ¼ƒà½Ú^Z¿í4˜¾eg¼¸‹È ªî¯µW—b2ðÞ7Ü_k%¹8×ï(´ÅŠO}dà½o‡׸¿ÖJÝØjò3wßàVcXŸWPú0¥èŸúqø¬BÈÀ{ß­§ÇgCru&oÎÍp­•-û·¤?žÐ‡'èÏBs¢¬ ưÉGz>¯2 [ÈŽµg; Ї²i8P/ _ì—âðY…‡—å=ч†e´à:ÝZOÏ?(3w†äêãwXR Øí@h¿Qø¡ø+ðÄŸ—H*0"ZOWžâöoI“õÇ}§@ÕÀümNП5+·#Å–Ÿ *'Gýº| A’ô÷èH¨=X›X?¨#¶1Ó÷¡‰jÏv¨Ê¬á¾„`ÃÒp ^·æY¸©ô<ßL…çÂÑà€~i/Ë{kHwâ ËÇh±s)ÇaL ¸Ùõ˜oDÿÓü~Pfî7ÚVM'¹(@¶Æï°¤£ˆ °Û×g9‘xÒ+ôn“÷&;fšƒˆ?/‘íX“)T`D´1ø ߨMºÏñ¦ìß’þ‰¸.Fg›Tp'ì»HðqÞ/LÉ0€ùÛUçEcœ ?kùǃÓh6ÁrŠyË7]ä®Pá\@ÿTN%˜èösˆ‹®ï7ø@‚'>¼$é!AxU™¯×à‹Ê°\3;¶Yí^ÑåU°~PGÕìÿl!;b F‡Úçé2È‚ŽŽpÔží(±ùQ_Vä‚:1X:ƒ §æn3Á† m¦:µ¤á@½Á†ü/)IJNõ¯óv"2–žŠx¾+˜Ù— KÉôx.®HÀÀýÒ¥fAj^–÷y9*O—–Ÿ]òñ#åkM`~×õŽÑbçë¶Þ_RŽ Â7éµzÙFh¼!¼Ðê1߈Vc0aùÖ"žj𽦽ØÁ¿6n´­S šNrÿ)Î¥†{·táÇÍÙ’¨¾¬*F8#v¥€ufÆØz`þ®Ïr›ÉsÊ"ñ¤WG–ï©9­ýÌ^EîMvc‰ñÎ&DÜèAødQy/ù4“AÚ±&S¿ÖšëéÆù³Œ¡E bðiL¡¾Q›<Û6'„5™’–Pþ..™¹T&üÞèžq]Œwá4Î.6©«IŠEæ? ƒ»v‘àãö\[ýYéI˜>Uñ!‚lDa>Ԫ΋ÆÏ©7~8AÖ]&Ãn³‰v|ÖîÊÄoÖY ±¡áäóy¨K×i˲w«\¡Â¹9Æ~€þ©œå™$ 6 6nQާf†ÂqÚ>,Þo,I¹Ó”ð •渱{I £.±H>ÒC-YnûÃöÛ馑gQ©°ÌzÎ t”a¹fñÞw0–îa,™ QºmÄpjôéc¥5žd•£Ûˆ2yܸ¤àÕé—ÒÙˆ ¶L+~±|½ç¸-¿‘·dj° òó¹qH„¾AÞÚÔ}mÝäëôÔµQƒÓ…Çl˜Vdk¨ÀýbùzŠeÉì\OclÙú=c õ;n ÈLi^Õ`Aä¢gqr<äÑKÔGÒ …ý¥ µk5µ¨úB²˜lÛ»ÉÖ¬¼ù@2ØlãEß\uÜÖ Ï«Ñ=Y&Ù0¬QÞ:È×Q€¿Ða!´ôµV³Ä#Ϻ•™¸½¥(¸ž_ˆÆ Ù²± é$/o|‡XhLÁa«¶f-=vÜAÛq˜Ò ¼ïÕ*q±…‰¶µŸ¿ä¥è¸Ô3xÉ¢ù4– ¨Žá˜j »m=-‘dl—æc\kkQôlab…e0ØòbNl•í¥{‚ôÁõÄWe°ÙÆ·éP‹¾¸êü¹ˆ|bÝßÚ-IŒÓ|óûÔLeM²aX:µQΣ¼tÔ»0âJߥA=ؕפÑÄmÓÖôûCiéj4nÙü­gˆFÚ`¸ÐD-s3åª L_Ý |ÉPq<'Aª¾ É †Whµ% o…³¹fÔ ÎaäŸ^Þù)Ùɘ°Ð˜"Çר´Y³=.´ ·½\;Àºl­í¸ƒ š¿³¶¶â t±ÒšêÕG9Òw¯Û&s܃ãc ”d;„ mj>zjZ¨äÏ “ ÿ ®'}ž±ð“D‡£ÒòhiÂþ÷bW]€egËl6qnkçþÔv‰Ó+àÚzZgÝJÌù¹ßo޾ïù·¾C`°ŽÕÖÖ£è¡Ñ“~8ØÂÄOßòRÑ»gñ¦¼Wg?µÝH²6KØ +Ú¯ L6JöAz`ß`ïègßU1nŽïFi¾yËa³Œ¼fƒ%oÒ Rhâ6Ì w•» G"¹U&/ź;¾²½ (+´Z’\³jÂ×ÿ§µÐÏ1,Ùž‹[Þ®›d°ìcò&uj£œm“ œ ©ë6?rg…W•¿J‚â¸z{±+® ¶8’ÒŽ›åÕ¾ |Üï· Ûß!†ÓÒÔñÔâBhݳøÚƒn¾Íö¹&[o°wá·GwˆZæÿjpf;Ê \ežÿøb®iakÿÓlÏE  âx× ÒîNƒT9³Â§g&aÐ`÷IiGM>nwÛ®ÑjJÙÖZÜ@ß f7Ø;𩼮SÞ»žÅG²Ï0µÿé½½òʺŠS³“0$´£¦ºÐ6ÍדTÞW)#Ùg¿³fz.ÄaJ¸]h*o+”´ ¾7Ã Ž¡Zß-ï1A26b‚+-SÃdlÅ}wôEVZ§†OA–ÇÈÙŠÑ»IúïèŠãôÙˬµO µ®~Mžƒ-އ˜ÏJÂQSÙ#xôpÓaïA’.®×U7µæ˜µ×ƒ„–‚˜Y›©°-úÛ©6Ëšæw]]ÿllÔA?ßÍZž•„$¢ŒŸã§²F ¾©wañèá¦èóÐçÃÞƒ$ÚŲe]]®ªDFŸëokÌ(vpýi91k® *Zï  ,8mßF6óÆ]²ípTqôke0»*ó÷¢1¶‰‘u 4Ÿ¼û„º%©Þy<²ï8sóyÿjèH¾AÅ}XÞ*<ðyOéb~DÂO-‡ÛTÆ”Š»@¦#胿8ÙÂ8 Å !»ôL –§–Î\Ì E×1Hnúb‹wáSʺ»]T£ lˆ?Ö‘–—ÞטPÇÌ©ìáúÒõúË“rb×\kyæ@TµÞYO„ŸX#$8pÚ=#A›eýk§|æZæWË %NÐ8d‘®£ŠŸâ3§Ì!*¼ý`­$᯴?Ð-† ²lÉH$«ÐSêû~F)âewh/?yö6$H· t*5KS¼òRH³yeÞp`~ï1çæóþþý¿ÕБ|ÌË =ƒŠ6úš‘»±¼Tx¨§e9;ƒ˜K"˜© µúɮˈ_ï]OFôlmÙ?ÍtÂŒóZCêA#ÁlpÁØwA€—6×GŽ-極ż„„qAŠhZ»[Cwè˜ZlÙÙ-O 6~_'-œ>ݹ˜ ƒ1S‹®b’µSÑÝôÅÄïôWï§”öÙ–Õ®¼é·¨œ1Þk…*ï*ÊkyíÓpH¬ø]oáF*.fÞ6áÅ TèTcMóe"²óå©Â¤0„‘g)Ÿ &äÅ®¸ýÞŸùÖóÌ:Ïèý{€©k¼™²Zý²Ÿ >«„8,$°5ñ*F21wsHpá´QkÐõzFƒ6c]²wËú×NÒáæù̵Ìàׄ¯–J¶#  pÈ„»A‰#]F8l1?Ä(…gO˜B~T©UyúÀLbË8Ř#ô^³§ª–ÜåTüO1Z×bb™ÎySØIáOPú~V{×-•bÌÔ-Š4–»R»è‘ ÙÐ^~óìGe­lH‘nuS /:6è# ©$Tj?e+–§yä¼H¥¤‘f½Š*'ò˼àëСÀýÞbÙæï#¼á½ §Ðü&Šƒ??‘²~pÐ$¹iËøBæF;[ýwzÜekµÅ~ZôîS 7÷H8v¸ ®±¡ŸðŠ?Ì3“$ýrÂj7„ÔnF¾Y ¨ÜËÂë|²O…Q¸Ñ; —…Ö Uïá ùdØ“S ž- \G=&£päÉG¢w`)/ ¬ía›«ßÂiµõ5òÈ÷˜ÿ±&¦sL‘†„ <À:R=Pe6^X7œ}o5ÚÃ64©1W¿„0•Õ³2Ókê3Ý$kå%©§'ï1þ&-[É#bML" '{ æ™"!$ó*x´(+ºÞ)ü`F(> q-qô,³vÃ.õÈš/7¢­pšÀqXç÷sY®rÜ3™w“%vQO+tñruÕ›E~‰ÜxK¶O} |Ïb!y€t¤xB“z Ê{ÆÊýl¼.°m~D‡o8úÞnúékµ†ljwì[h1Rió85b¯cm?a+«f`éÁQe¦×Ôdd½ãf"ºgàiH×Ë I¡KSNJ‘uyOÞcüN ËLZ·’M˜Ý¥FÄš˜Gð¯E@NöD‚$ÁAÍ2D@XsBIæ*C‹ŒTñhPU3gWu¼>V·Ö SøÀŒR:ª»P|âQ¾~ÕZâ9è[ SßYfí†X¤‡±]ë‘4\)û^oEZ_­/má5€à÷q·â±Ïîãs¥Ùæ<³\çþÙkå¸g2äz ï&J8îä 좞Ví`ôaè/âäéíˆÓë«6Šêi\½ý¸ðüÑÒÇþ—lžÿU©ú,ûØzùžÄBø\®uóéHòƒð„=&ñFWô A”õË+£÷•úöOÿÍÙx]`غ7WÚü‰Û>ã9Þqõ¼ß³Ÿ‹Ýõ!ÒÜ7Kå×k ØÖ©fïÔïØ¶Õ-²Ðb¤Ñ Î3ÓæpjÒ$]Å^þÄœ”'ÆÚ*~Ç@IÂWVÌÕ<ûÁÓ‚¢Àè•ËM¯¨ÊÅŸÈÉ{ÆÉ ñÌDt͆mCÏÀÓι-‘¯–@müw’+B.“é(–¦>œ—dT«•"êò”à€ÅŸ¼Çøž~­Ïœ8–úy¡˜µo$™w›1»JšóÑ}‰50ŒK_Ž á^Ï‹iŠ€ì‹B÷Û‰I‚ˆÆ#µƒšdˆ‚X¿€°æÜÚÑ„“ÌT…Q¦c‡:†Õr ©âР¨ º—ªfΫ¤nù®ëx|¯)K­o¬¬­Æ%§ñ¦3ë/¤uUv¥·?A ø)Ä¡:Có£|ýª¢¾—µÄsдç¶@§¾·‚͉²ÍÛ ³±;±Ib°‹eU»×"hºH_¸Sö¹‘œ1¼ÞŠ´½àƒ¿Z^Ú¾˜4í¸¼geª È‹µ¯îb—W7Þð2%k_Ü×8¹Å´(ï}OŠo½àdׇJÖ¿¸òjØÝàßw3XcVPWŸè¥0úúŸB¬øqß{ÀÈgǧ­urCÍÎo&•­p-?¤·û‡ОÏè'¢sB°Æ ¬zGÉ 2¯>ŽÈ[ ;gµ²‡Ð/P8i—ì_ …Yðâ=å—‡e†‡ÑÝ:à´ÏOZw3(?êä†RXwã@íØ øQ¿hð+ø¡H—ŸÄZ"0*âžWOIoöÇõ“Õ@§}müÀ5ŸÐN#·+Ÿ–Å'* ºýGA |ô’¨Hè÷›X=#¨?X1¶‰¡÷ÓvÏj¬Ê¨¾áÃ`„^ pÒæ·ô©¸YLß<ÑÂç…i~€à{Ë/ÃwHkË ¢s±hÇaÇ)Ù¸ LDo˜õüÓÿîfP~VÚ7¹'M¶@(¤°ïÆ ˆ£Û°9g×+Òx‘“nô;&÷ƒšf‘/?ˆ)“Xí´D`T ø1M¨ß¦ñϺþ’ßìF.¸‰T›gì'pqðH»ÉL/ÞÛù€0cEçUk? œÓƒÇùÁ6hyŠrä]7Ë\áP®NTÿ@öè˜%®‹ˆs7ï‚@ø¼>'!é$™UxA‹àׯ3\°ÊíY¶;UåÑ^GP~°ÿìÕb;!lÚ‡F È2éçpŽŽ‚(ížÔQù±‚äV_:X1:§ ƒ3næ †Áµ:¦m½@á¤ü†ÁI)/¯õNJ2"vóŠž–˜+¾x —ÙxôÉKÀH®.ÒýÀjAf¥÷–^O*9y]Ÿ–—å#ñòMkõ×~`çbÑŽ_Þ¶ë ŽRzµé7hFÙм!¼ˆß1ê0cV"Öùašjž½¦½¿ÁØ­´n6 SrNš¥Î)ÿ·{†Çát’ÙÍ*¬¾¨8F€¥v#ØÆfu`zrÏ®þÊsÉ›W¤ñ"ï–Gý­9©E^ÌvMîÎñ‰cÜD&døAèù/yQA“4S&±ÚëšÖ¿³ùÆé E¡Œðb¡Li<›Q¾„'6Û–’™5..þP&T¹™žèÞüŒ]q4áw©6.ΊI«?æE»ƒ ãà‘v[\öIéYýñU>˜l‚!Ô>aDƋΪ~7©ÏÖA8nÃ&]|v‰³ÄÊîÖYÖoᡱ óäK¨yËi׫w²¹Â¡\~Æ9œ©þ€$™å6 6 ŽQn†f§>ÚqÂ,oÞ,”Ó¹I ð±¸æ•£ I{±.CÒ>HûnY-éÛöÃQg‘¦Ì°©t Îzf¹a”Þñ deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler .èbP#èbP#èb P#èb(èb (èb€€(èb €(èb €(èb (èb%sÐTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèb`UèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbPUèbšTèb@UèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèb0UèbšTèbšTèbšTèbšTèbUèbšTèbUèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbšTèbðTèbšTèbšTèbšTèbšTèbàTèb Uèbout of memory: %s%s%sout of memory1.2.8compressed data errorunexpected end of fileinternal error: inflate stream corruptrequested length does not fit in intout of room to push charactersout of memory1.2.8internal error: deflate stream corruptrequested length does not fit in intinvalid block typeinvalid stored block lengthstoo many length or distance symbolsinvalid code lengths setinvalid bit length repeatinvalid code -- missing end-of-blockinvalid literal/lengths setinvalid distances setinvalid literal/length codeinvalid distance codeinvalid distance too far backPyèbywèb£xèbywèbywèbyèbywèbywèbywèbÒwèbywèbywèbywèbywèbywèbywèbywèb°wèb wèb     A@!  @a`10  Á@`Psp0 À `  €@ àX ;x8 Ðh( °ˆH ðTã+t4 È d$ ¨„D è\ ˜S|< Øl, ¸ ŒL øR£#r2 Ä b" ¤‚B äZ ”Cz: Ôj* ´ ŠJ ôV@3v6 Ìf& ¬†F ì ^ œc~> Ün. ¼ŽN ü`Qƒq1  a! ¢A âY ’;y9 Òi) ² ‰I òU+u5 Ê e% ª…E ê] šS}= Úm- º M úSÃ#s3 Æ c# ¦ƒC æ[ –C{; Ök+ ¶ ‹K öW@3w7 Îg' ®‡G î _ žc? Þo/ ¾O þ`Psp0 Á ` ¡€@ áX ‘;x8 Ñh( ±ˆH ñTã+t4 É d$ ©„D é\ ™S|< Ùl, ¹ ŒL ùR£#r2 Å b" ¥‚B åZ •Cz: Õj* µ ŠJ õV@3v6 Íf& ­†F í ^ c~> Ýn. ½ŽN ý`Qƒq1 à a! £A ãY “;y9 Ói) ³ ‰I óU+u5 Ë e% «…E ë] ›S}= Ûm- » M ûSÃ#s3 Ç c# §ƒC ç[ —C{; ×k+ · ‹K ÷W@3w7 Ïg' ¯‡G ï _ Ÿc? ßo/ ¿O ÿincorrect header checkunknown compression methodinvalid window sizeunknown header flags setheader crc mismatchinvalid block typeinvalid stored block lengthstoo many length or distance symbolsinvalid code lengths setinvalid bit length repeatinvalid code -- missing end-of-blockinvalid literal/lengths setinvalid distances setinvalid literal/length codeinvalid distance codeinvalid distance too far backincorrect data checkincorrect length check{žèb¿èbqœèb@Ÿèb¢èbS¡èbš èbûŸèbPŸèbmèbæèb"‘èbïèb?’èb¸’èbÁ’èbÙ™èbušèbj›èb¹–èb–èbÕ“èbN”èb“èb‰“èb¾Ÿèb…˜èbf™èbéŸèbA¡èbgœèb     A@!  @a`10  Á@`Psp0 À `  €@ àX ;x8 Ðh( °ˆH ðTã+t4 È d$ ¨„D è\ ˜S|< Øl, ¸ ŒL øR£#r2 Ä b" ¤‚B äZ ”Cz: Ôj* ´ ŠJ ôV@3v6 Ìf& ¬†F ì ^ œc~> Ün. ¼ŽN ü`Qƒq1  a! ¢A âY ’;y9 Òi) ² ‰I òU+u5 Ê e% ª…E ê] šS}= Úm- º M úSÃ#s3 Æ c# ¦ƒC æ[ –C{; Ök+ ¶ ‹K öW@3w7 Îg' ®‡G î _ žc? Þo/ ¾O þ`Psp0 Á ` ¡€@ áX ‘;x8 Ñh( ±ˆH ñTã+t4 É d$ ©„D é\ ™S|< Ùl, ¹ ŒL ùR£#r2 Å b" ¥‚B åZ •Cz: Õj* µ ŠJ õV@3v6 Íf& ­†F í ^ c~> Ýn. ½ŽN ý`Qƒq1 à a! £A ãY “;y9 Ói) ³ ‰I óU+u5 Ë e% «…E ë] ›S}= Ûm- » M ûSÃ#s3 Ç c# §ƒC ç[ —C{; ×k+ · ‹K ÷W@3w7 Ïg' ¯‡G ï _ Ÿc? ßo/ ¿O ÿ inflate 1.2.8 Copyright 1995-2013 Mark Adler @@ !1AaÁ  0@`HN #+3;CScsƒ£Ãã   ŒLÌ,¬lìœ\Ü<¼|ü‚BÂ"¢bâ’RÒ2²rò ŠJÊ*ªjêšZÚ:ºzú†FÆ&¦fæ–VÖ6¶vöŽNÎ.®nîž^Þ>¾~þAÁ!¡aá‘QÑ1±qñ ‰IÉ)©ié™YÙ9¹yù…EÅ%¥eå•UÕ5µuõ MÍ-­mí]Ý=½}ý  “ “ S S Ó Ó 3 3 ³ ³ s s ó ó  ‹ ‹ K K Ë Ë + + « « k k ë ë   › › [ [ Û Û ; ; » » { { û û   ‡ ‡ G G Ç Ç ' ' § § g g ç ç   — — W W × × 7 7 · · w w ÷ ÷    O O Ï Ï / / ¯ ¯ o o ï ï   Ÿ Ÿ _ _ ß ß ? ? ¿ ¿   ÿ ÿ @ `P0pH(hX8xD$dT4tƒCÃ#£cã            (08@P`p€ Àà   0@`€À€  0@`1.2.81.2.8need dictionarystream endfile errorstream errordata errorinsufficient memorybuffer errorincompatible versionæ¤ébö¤éb¥éb¥éb ¥éb¥éb%¥éb9¥ébF¥éb¥ébinvalid literal/length codeinvalid distance codeinvalid distance too far backÐãèbMingw-w64 runtime failure: Address %p has no image-section VirtualQuery failed for %d bytes at address %p VirtualProtect failed with code 0x%x Unknown pseudo relocation protocol version %d. Unknown pseudo relocation bit size %d. ³éb@°ébmsvcrt.dll(null)NaNInf(null)PRINTF_EXPONENT_DIGITSéb… éb… ébréb… éb`éb… ébéb… éb… ébÇéb°éb… éb—ébéb… éb0éb… éb… éb… éb… éb… éb… éb… éb… éb… éb… éb… éb… éb… éb… éb… éb… ébéb… ébÐéb… éb¤ébrébGéb… éb éb… éb… ébpéb… éb… éb… éb… éb… éb… ébÂéb… éb… éb… éb… ébÐ éb… éb… éb… éb… éb… éb… éb… éb… éb0éb… éb0 ébp ébð éb° ébp ébD ébp éb0 éb… éb ébè éb° ébÐ ébp éb… éb… ébD éb0 ébÐ éb… éb… ébÐ éb… éb0 ébInfinityNaN0òéb5éb5ébXéb%ébÀ?aCoc§‡Ò?³È`‹(ŠÆ?ûyŸPDÓ?ú}-”<2ZGUDÓ?€? A@@à@ @?_set_output_format_get_output_format€à7yÃACnµµ¸“Fõù?éO8M20ùHw‚Z<¿sÝOu¼‰Ø—²Òœ<3§¨Õ#öI9=§ôDý¥2—ŒÏº[%Co¬d(È ð?$@Y@@@ˆÃ@jø@€„.AÐcA„×—AeÍÍA _ BèvH7B¢”mB@åœ0¢BļÖB4&õk C€à7yÃAC Ø…W4vCÈNgmÁ«C=‘`äXáC@Œµx¯DPïâÖäKD’ÕMÏð€D}___lc_codepage_func__lc_codepage ßQ4ÃNN(À`Á˜Âð€Pà  °€8`7Q K LÐNJ06€6p43`16 7€€X]pS iPt`iðWp\°\s0f fh\[°WÐW`Xàr`p0q dÐX[YsP[[g€qpnÐvpˆàuð°p¬Ð¬0®ÐŒ° ²Ž°Š`‹Š`­`®À°p²ÛpÜ`ÜPÜ>ÃFÃVÃhÃqÃ{ÉÃÃíõÃÂÃÎÃÙÃçÃôÃÄÄÄ+Ä<ÄQÄbÄnÄ|Ä…ÄĘĢĬĵĽÄÃÄËÄÓÄÚÄâÄéÄòÄýÄÅ ÅÅÅ&Å-Å4Å=ÅDÅMÅYÅ`ÅiÅrÅ|ńŌŘŧŸÅÄÅÏÅäÅõÅÆÆÆ)Æ6ÆDÆUÆjÆvÆ‡Æ˜Æ£ÆªÆ»Æ  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMzlib1.dlladler32adler32_combineadler32_combine64compresscompress2compressBoundcrc32crc32_combinecrc32_combine64deflatedeflateBounddeflateCopydeflateEnddeflateInit2_deflateInit_deflateParamsdeflatePendingdeflatePrimedeflateResetdeflateResetKeepdeflateSetDictionarydeflateSetHeaderdeflateTuneget_crc_tablegzbuffergzclearerrgzclosegzclose_rgzclose_wgzdirectgzdopengzeofgzerrorgzflushgzgetcgzgetc_gzgetsgzoffsetgzoffset64gzopengzopen64gzopen_wgzprintfgzputcgzputsgzreadgzrewindgzseekgzseek64gzsetparamsgztellgztell64gzungetcgzvprintfgzwriteinflateinflateBackinflateBackEndinflateBackInit_inflateCopyinflateEndinflateGetDictionaryinflateGetHeaderinflateInit2_inflateInit_inflateMarkinflatePrimeinflateResetinflateReset2inflateResetKeepinflateSetDictionaryinflateSyncinflateSyncPointinflateUndermineuncompresszErrorzlibCompileFlagszlibVersionPÐðÕDÑ´ÐÖ¨ÑÈДּÑ8ÒPÒhÒ|Ò’Ò¨Ò¸ÒÌÒÞÒøÒÓ$Ó8ÓPÓ`ÓvÓÓ®Ó¶ÓÊÓØÓôÓÔÔ,Ô6Ô>ÔFÔPÔ^ÔnÔ|Ô†Ô’ÔšÔ¢Ô®Ô¸ÔÂÔÐÔÚÔâÔêÔôÔüÔÕÕÕ&Õ0Õ:ÕDÕPÕZÕfÕpÕzÕ„Õ8ÒPÒhÒ|Ò’Ò¨Ò¸ÒÌÒÞÒøÒÓ$Ó8ÓPÓ`ÓvÓÓ®Ó¶ÓÊÓØÓôÓÔÔ,Ô6Ô>ÔFÔPÔ^ÔnÔ|Ô†Ô’ÔšÔ¢Ô®Ô¸ÔÂÔÐÔÚÔâÔêÔôÔüÔÕÕÕ&Õ0Õ:ÕDÕPÕZÕfÕpÕzÕ„ÕÔDeleteCriticalSectionïEnterCriticalSectionÄGetCurrentProcessÅGetCurrentProcessIdÉGetCurrentThreadIdGetLastErrorGetModuleHandleAEGetProcAddress{GetSystemTimeAsFileTime—GetTickCountëInitializeCriticalSectionIsDBCSLeadByteEx&LeaveCriticalSection,LoadLibraryWUMultiByteToWideChar“QueryPerformanceCountergSetUnhandledExceptionFiltertSleep‚TerminateProcess‰TlsGetValue–UnhandledExceptionFilter¶VirtualProtect¹VirtualQueryÚWideCharToMultiByte_close6_open<_readh_write8__dllonexitF__mb_cur_max_amsg_exitÑ_errno2_initterm6_iob˜_lock _lseeki647_onexitê_unlock_vsnprintft_wopen©abort²atoi¶callocÒfputc×freeçgetenv localeconvmallocmemchrmemcpymemset1setlocale>strchrDstrerrorGstrlenJstrncmp€wcslenwcstombsÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐÐKERNEL32.dllÐÐÐÐmsvcrt.dll(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ðmsvcrt.dllèbÐãèbãèbðébðéb°ébàébžßQ€žßQ0€žßQ HX,,4VS_VERSION_INFO½ïþ?ŒStringFileInfoh040904E4dFileDescriptionzlib data compression library,FileVersion1.2.84 InternalNamezlib1.dll|,LegalCopyright(C) 1995-2013 Jean-loup Gailly & Mark Adler< OriginalFilenamezlib1.dll*ProductNamezlib0ProductVersion1.2.8x0CommentsFor more information visit http://www.zlib.net/DVarFileInfo$Translation ä¤ 0%0Q0`0f00 0Ù011&131G1L1p1„1—1Å1Ï1Ù1æ12 22:2A2L2z2…2Æ2K4—4¢4¨4¾4Ç4Õ4p9-:‚<Ö< =0=:=A=X=g=q=x==ž=¨=¯=Æ=Õ=ß=æ=>>> >7>F>P>W>n>}>Š>‘>«>µ>¼>Ã> ?*?1?8?r? î34.6÷89 ;0j5q5º9é<<>@ 0Ë0{:¨:¹:;Û<ä<£>P$±0½0à0½4×5‚728Ü<æ<í=õ=[?˜?`(¦0-1k1·1Ù12‚3¿56ï7à:Q;T=t=ˆ?p$ 2S6g6—7]:‹:þ:U;j;¹>Î>Ü>û>€ Ì1Ý3L7y7ñ7V8==r>‚>ë?Æ3Ê9¼:ï:.?¯? ,j6‘6Ÿ6 7ä8ü8¿9×9ï90:Þ:‡;í;<<2,>6>Ð$u001â4ç4¤78';L;s;Ö;R<<à,|001È2ì2ü2/3F3\3Ü3å34 44ˆ44®4ò4ÿ495a5j5—5ë5666*6@6½6Ç6Ù6õ6 7"7B7H7X7_7l7x7‚7’77Á7É7è7ó78&8D8N8W8‘8Ÿ8½8Û8ö8$9>9Y9t9ˆ9œ9·9Ä9Ð9é9ù9: :8:D:W:…:˜:ª:²:º:É:î:ü:;$;.;7;<;K;P;X;a;k;q;z;‹;ª;Ã;É;Ï;Ü;ç; <<8œ>¢>¬> ???'?;?@?U?d?j?t?›?º?À?Ê?ðH0$0*040A0\0q0w00•0š0Î0ñ0÷011 1/1R1h1ê1ò12 22V2^2f2n2¨3†69(9³9(;<Å0 3g3m3s3|3Œ3ß3j4G5Y5_5}5„5Í5â5"6s6š6 8@8s89>S>³? TÕ1î1=2­7ÿ78@8H89Ë9O:®:¼:Ã:ÿ:; ;ç;þ;<?? ?9?B?W?`?r?‰?’?©?²?Â?Ò?Ù?ë?ý?0Œ000&010?0H0\0g0z0”0¯0º0Á0Í0è0÷0111>1”1¯1Å1ñ1ú1Ã4A5q5¼51 '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig/zlib.pc uninstall: -if [ "$(SHARED_MODE)" = "1" ]; then \ $(RM) '$(DESTDIR)$(BINARY_PATH)'/$(SHAREDLIB); \ $(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(IMPLIB); \ fi -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zlib.h -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zconf.h -$(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(STATICLIB) clean: -$(RM) $(STATICLIB) -$(RM) $(SHAREDLIB) -$(RM) $(IMPLIB) -$(RM) *.o -$(RM) *.exe -$(RM) foo.gz adler32.o: zlib.h zconf.h compress.o: zlib.h zconf.h crc32.o: crc32.h zlib.h zconf.h deflate.o: deflate.h zutil.h zlib.h zconf.h gzclose.o: zlib.h zconf.h gzguts.h gzlib.o: zlib.h zconf.h gzguts.h gzread.o: zlib.h zconf.h gzguts.h gzwrite.o: zlib.h zconf.h gzguts.h inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h inftrees.o: zutil.h zlib.h zconf.h inftrees.h trees.o: deflate.h zutil.h zlib.h zconf.h trees.h uncompr.o: zlib.h zconf.h zutil.o: zutil.h zlib.h zconf.h tcl8.6.5/compat/zlib/win32/USAGE.txt0000644000175000017500000000551712663653206016370 0ustar sergeisergei Installing ZLIB1.DLL ==================== Copy ZLIB1.DLL to the SYSTEM or the SYSTEM32 directory. Using ZLIB1.DLL with Microsoft Visual C++ ========================================= 1. Install the supplied header files "zlib.h" and "zconf.h" into a directory found in the INCLUDE path list. 2. Install the supplied library file "zdll.lib" into a directory found in the LIB path list. 3. Add "zdll.lib" to your project. Using ZLIB1.DLL with gcc/MinGW ============================== 1. Install the supplied header files "zlib.h" and "zconf.h" into the INCLUDE directory. 2. Copy the supplied library file "zdll.lib" to "libzdll.a": cp lib/zdll.lib lib/libzdll.a OR 2' Build the import library from the supplied "zlib.def": dlltool -D zlib1.dll -d lib/zlib.def -l lib/libzdll.a 3. Install "libzdll.a" into the LIB directory. 4. Add "libzdll.a" to your project, or use the -lzdll option. Using ZLIB1.DLL with gcc/Cygwin =============================== ZLIB1.DLL is not designed to work with Cygwin. The Cygwin system has its own DLL build of zlib, named CYGZ.DLL. Using ZLIB1.DLL with Borland C++ ================================ 1. Install the supplied header files "zlib.h" and "zconf.h" into a directory found in the INCLUDE path list. 2. Build the import library using the IMPLIB tool: implib -a -c -f lib\zdllbor.lib zlib1.dll OR 2' Convert the supplied library file "zdll.lib" to OMF format, using the COFF2OMF tool: coff2omf lib\zdll.lib lib\zdllbor.lib 3. Install "zdllbor.lib" into a directory found in the LIB path list. 4. Add "zdllbor.lib" to your project. Notes: - The modules that are linked with "zdllbor.lib" must be compiled using a 4-byte alignment (option -a): bcc32 -a -c myprog.c bcc32 myprog.obj zdllbor.lib - If you wish, you may use "zlib1.lib" instead of "zdllbor.lib". Rebuilding ZLIB1.DLL ==================== Depending on your build environment, use the appropriate makefile from the win32/ directory, found in the zlib source distribution. Your custom build has to comply with the requirements stated in DLL_FAQ.txt, including (but not limited to) the following: - It must be built from an unaltered zlib source distribution. - It must be linked to MSVCRT.DLL. - The macros that compile out certain portions of the zlib code (such as NO_GZCOMPRESS, NO_GZIP) must not be enabled. - The ZLIB_WINAPI macro must not be enabled. Furthermore, it has to run successfully with the test suite found in this package. It is recommended, however, to use the supplied ZLIB1.DLL, instead of rebuilding it yourself. You should rebuild it only if you have a special reason. tcl8.6.5/compat/zlib/win32/zdll.lib0000644000175000017500000003645212663660065016423 0ustar sergeisergei! / 1368449285 0 3148 ` Ÿ"Dx<Â<Â!p!p"¤"¤3²3²5¼5¼%ì%ì"<"<%%#Ü#Ü&È&È!Ô!Ô$F$F$°$°&\&\9Þ9Þ6"6":N:N5T5T8 8 9988887Ð7Ð6’6’444~4~.>__IMPORT_DESCRIPTOR_zlib1__NULL_IMPORT_DESCRIPTORzlib1_NULL_THUNK_DATA__imp__zlibVersion_zlibVersion__imp__deflate_deflate__imp__deflateEnd_deflateEnd__imp__inflate_inflate__imp__inflateEnd_inflateEnd__imp__deflateSetDictionary_deflateSetDictionary__imp__deflateCopy_deflateCopy__imp__deflateReset_deflateReset__imp__deflateParams_deflateParams__imp__deflateTune_deflateTune__imp__deflateBound_deflateBound__imp__deflatePending_deflatePending__imp__deflatePrime_deflatePrime__imp__deflateSetHeader_deflateSetHeader__imp__inflateSetDictionary_inflateSetDictionary__imp__inflateGetDictionary_inflateGetDictionary__imp__inflateSync_inflateSync__imp__inflateCopy_inflateCopy__imp__inflateReset_inflateReset__imp__inflateReset2_inflateReset2__imp__inflatePrime_inflatePrime__imp__inflateMark_inflateMark__imp__inflateGetHeader_inflateGetHeader__imp__inflateBack_inflateBack__imp__inflateBackEnd_inflateBackEnd__imp__zlibCompileFlags_zlibCompileFlags__imp__compress_compress__imp__compress2_compress2__imp__compressBound_compressBound__imp__uncompress_uncompress__imp__gzopen_gzopen__imp__gzdopen_gzdopen__imp__gzbuffer_gzbuffer__imp__gzsetparams_gzsetparams__imp__gzread_gzread__imp__gzwrite_gzwrite__imp__gzprintf_gzprintf__imp__gzvprintf_gzvprintf__imp__gzputs_gzputs__imp__gzgets_gzgets__imp__gzputc_gzputc__imp__gzgetc_gzgetc__imp__gzungetc_gzungetc__imp__gzflush_gzflush__imp__gzseek_gzseek__imp__gzrewind_gzrewind__imp__gztell_gztell__imp__gzoffset_gzoffset__imp__gzeof_gzeof__imp__gzdirect_gzdirect__imp__gzclose_gzclose__imp__gzclose_r_gzclose_r__imp__gzclose_w_gzclose_w__imp__gzerror_gzerror__imp__gzclearerr_gzclearerr__imp__gzopen64_gzopen64__imp__gzseek64_gzseek64__imp__gztell64_gztell64__imp__gzoffset64_gzoffset64__imp__adler32_combine64_adler32_combine64__imp__crc32_combine64_crc32_combine64__imp__adler32_adler32__imp__crc32_crc32__imp__adler32_combine_adler32_combine__imp__crc32_combine_crc32_combine__imp__deflateInit__deflateInit___imp__deflateInit2__deflateInit2___imp__inflateInit__inflateInit___imp__inflateInit2__inflateInit2___imp__inflateBackInit__inflateBackInit___imp__gzgetc__gzgetc___imp__zError_zError__imp__inflateSyncPoint_inflateSyncPoint__imp__get_crc_table_get_crc_table__imp__inflateUndermine_inflateUndermine__imp__inflateResetKeep_inflateResetKeep__imp__deflateResetKeep_deflateResetKeep__imp__gzopen_w_gzopen_w/ 1368449285 0 3158 ` Q"DxÂ<p!¤"²3¼5ì%<"%Ü#È&Ô!F$°$\&Þ9"6N:T5 8988Ð7’64~4V<hÎŽ;x-ø)š'V1Ê/N3¢.è2h/L,/†+„2"+0,0¾1®,\*”)d(È(.)¾*þ'Ú-ò0 2-–!Æ8 *š t# #h7þ6è4è+ô;¶:0'";r9€%>.ŸAC? BD@ FE  P  M$:6785#49/-J+3>";Q(,*&10<%2=.)'IHGOLN!KAC? BD@ FE  P  M$:6785#49/-J+3>";Q(,*&10<%2=.)'IHGOLN!K__IMPORT_DESCRIPTOR_zlib1__NULL_IMPORT_DESCRIPTOR__imp__adler32__imp__adler32_combine__imp__adler32_combine64__imp__compress__imp__compress2__imp__compressBound__imp__crc32__imp__crc32_combine__imp__crc32_combine64__imp__deflate__imp__deflateBound__imp__deflateCopy__imp__deflateEnd__imp__deflateInit2___imp__deflateInit___imp__deflateParams__imp__deflatePending__imp__deflatePrime__imp__deflateReset__imp__deflateResetKeep__imp__deflateSetDictionary__imp__deflateSetHeader__imp__deflateTune__imp__get_crc_table__imp__gzbuffer__imp__gzclearerr__imp__gzclose__imp__gzclose_r__imp__gzclose_w__imp__gzdirect__imp__gzdopen__imp__gzeof__imp__gzerror__imp__gzflush__imp__gzgetc__imp__gzgetc___imp__gzgets__imp__gzoffset__imp__gzoffset64__imp__gzopen__imp__gzopen64__imp__gzopen_w__imp__gzprintf__imp__gzputc__imp__gzputs__imp__gzread__imp__gzrewind__imp__gzseek__imp__gzseek64__imp__gzsetparams__imp__gztell__imp__gztell64__imp__gzungetc__imp__gzvprintf__imp__gzwrite__imp__inflate__imp__inflateBack__imp__inflateBackEnd__imp__inflateBackInit___imp__inflateCopy__imp__inflateEnd__imp__inflateGetDictionary__imp__inflateGetHeader__imp__inflateInit2___imp__inflateInit___imp__inflateMark__imp__inflatePrime__imp__inflateReset__imp__inflateReset2__imp__inflateResetKeep__imp__inflateSetDictionary__imp__inflateSync__imp__inflateSyncPoint__imp__inflateUndermine__imp__uncompress__imp__zError__imp__zlibCompileFlags__imp__zlibVersion_adler32_adler32_combine_adler32_combine64_compress_compress2_compressBound_crc32_crc32_combine_crc32_combine64_deflate_deflateBound_deflateCopy_deflateEnd_deflateInit2__deflateInit__deflateParams_deflatePending_deflatePrime_deflateReset_deflateResetKeep_deflateSetDictionary_deflateSetHeader_deflateTune_get_crc_table_gzbuffer_gzclearerr_gzclose_gzclose_r_gzclose_w_gzdirect_gzdopen_gzeof_gzerror_gzflush_gzgetc_gzgetc__gzgets_gzoffset_gzoffset64_gzopen_gzopen64_gzopen_w_gzprintf_gzputc_gzputs_gzread_gzrewind_gzseek_gzseek64_gzsetparams_gztell_gztell64_gzungetc_gzvprintf_gzwrite_inflate_inflateBack_inflateBackEnd_inflateBackInit__inflateCopy_inflateEnd_inflateGetDictionary_inflateGetHeader_inflateInit2__inflateInit__inflateMark_inflatePrime_inflateReset_inflateReset2_inflateResetKeep_inflateSetDictionary_inflateSync_inflateSyncPoint_inflateUndermine_uncompress_zError_zlibCompileFlags_zlibVersionzlib1_NULL_THUNK_DATAzlib1.dll/ 1368449285 0 485 ` LáQ.debug$S?Œ@B.idata$2Ëß@0À.idata$6 ýß@ À zlib1.dll' 'ÆMicrosoft (R) LINK zlib1.dll@comp.id'ÆËÿÿ.idata$2@Àh.idata$6.idata$4@Àh.idata$5@Àh7N__IMPORT_DESCRIPTOR_zlib1__NULL_IMPORT_DESCRIPTORzlib1_NULL_THUNK_DATA zlib1.dll/ 1368449285 0 248 ` LáQ·.debug$S?d@B.idata$3£@0À zlib1.dll' 'ÆMicrosoft (R) LINK@comp.id'ÆËÿÿ__NULL_IMPORT_DESCRIPTORzlib1.dll/ 1368449285 0 274 ` LáQÓ.debug$S?Œ@B.idata$5Ë@0À.idata$4Ï@0À zlib1.dll' 'ÆMicrosoft (R) LINK@comp.id'ÆËÿÿzlib1_NULL_THUNK_DATAzlib1.dll/ 1368449285 0 39 ` ÿÿLáQ_adler32zlib1.dll zlib1.dll/ 1368449285 0 47 ` ÿÿLáQ_adler32_combinezlib1.dll zlib1.dll/ 1368449285 0 49 ` ÿÿLáQ_adler32_combine64zlib1.dll zlib1.dll/ 1368449285 0 40 ` ÿÿLáQ_compresszlib1.dllzlib1.dll/ 1368449285 0 41 ` ÿÿLáQ_compress2zlib1.dll zlib1.dll/ 1368449285 0 45 ` ÿÿLáQ_compressBoundzlib1.dll zlib1.dll/ 1368449285 0 37 ` ÿÿLáQ_crc32zlib1.dll zlib1.dll/ 1368449285 0 45 ` ÿÿLáQ_crc32_combinezlib1.dll zlib1.dll/ 1368449285 0 47 ` ÿÿLáQ_crc32_combine64zlib1.dll zlib1.dll/ 1368449285 0 39 ` ÿÿLáQ _deflatezlib1.dll zlib1.dll/ 1368449285 0 44 ` ÿÿLáQ _deflateBoundzlib1.dllzlib1.dll/ 1368449285 0 43 ` ÿÿLáQ _deflateCopyzlib1.dll zlib1.dll/ 1368449285 0 42 ` ÿÿLáQ _deflateEndzlib1.dllzlib1.dll/ 1368449285 0 45 ` ÿÿLáQ _deflateInit2_zlib1.dll zlib1.dll/ 1368449285 0 44 ` ÿÿLáQ_deflateInit_zlib1.dllzlib1.dll/ 1368449285 0 45 ` ÿÿLáQ_deflateParamszlib1.dll zlib1.dll/ 1368449285 0 46 ` ÿÿLáQ_deflatePendingzlib1.dllzlib1.dll/ 1368449285 0 44 ` ÿÿLáQ_deflatePrimezlib1.dllzlib1.dll/ 1368449285 0 44 ` ÿÿLáQ_deflateResetzlib1.dllzlib1.dll/ 1368449285 0 48 ` ÿÿLáQ_deflateResetKeepzlib1.dllzlib1.dll/ 1368449285 0 52 ` ÿÿLáQ _deflateSetDictionaryzlib1.dllzlib1.dll/ 1368449285 0 48 ` ÿÿLáQ_deflateSetHeaderzlib1.dllzlib1.dll/ 1368449285 0 43 ` ÿÿLáQ_deflateTunezlib1.dll zlib1.dll/ 1368449285 0 45 ` ÿÿLáQ_get_crc_tablezlib1.dll zlib1.dll/ 1368449285 0 40 ` ÿÿLáQ_gzbufferzlib1.dllzlib1.dll/ 1368449285 0 42 ` ÿÿLáQ_gzclearerrzlib1.dllzlib1.dll/ 1368449285 0 39 ` ÿÿLáQ_gzclosezlib1.dll zlib1.dll/ 1368449285 0 41 ` ÿÿLáQ_gzclose_rzlib1.dll zlib1.dll/ 1368449285 0 41 ` ÿÿLáQ_gzclose_wzlib1.dll zlib1.dll/ 1368449285 0 40 ` ÿÿLáQ_gzdirectzlib1.dllzlib1.dll/ 1368449285 0 39 ` ÿÿLáQ_gzdopenzlib1.dll zlib1.dll/ 1368449285 0 37 ` ÿÿLáQ_gzeofzlib1.dll zlib1.dll/ 1368449285 0 39 ` ÿÿLáQ _gzerrorzlib1.dll zlib1.dll/ 1368449285 0 39 ` ÿÿLáQ!_gzflushzlib1.dll zlib1.dll/ 1368449285 0 38 ` ÿÿLáQ"_gzgetczlib1.dllzlib1.dll/ 1368449285 0 39 ` ÿÿLáQ#_gzgetc_zlib1.dll zlib1.dll/ 1368449285 0 38 ` ÿÿLáQ$_gzgetszlib1.dllzlib1.dll/ 1368449285 0 40 ` ÿÿLáQ%_gzoffsetzlib1.dllzlib1.dll/ 1368449285 0 42 ` ÿÿLáQ&_gzoffset64zlib1.dllzlib1.dll/ 1368449285 0 38 ` ÿÿLáQ'_gzopenzlib1.dllzlib1.dll/ 1368449285 0 40 ` ÿÿLáQ(_gzopen64zlib1.dllzlib1.dll/ 1368449285 0 40 ` ÿÿLáQ)_gzopen_wzlib1.dllzlib1.dll/ 1368449285 0 40 ` ÿÿLáQ*_gzprintfzlib1.dllzlib1.dll/ 1368449285 0 38 ` ÿÿLáQ+_gzputczlib1.dllzlib1.dll/ 1368449285 0 38 ` ÿÿLáQ,_gzputszlib1.dllzlib1.dll/ 1368449285 0 38 ` ÿÿLáQ-_gzreadzlib1.dllzlib1.dll/ 1368449285 0 40 ` ÿÿLáQ._gzrewindzlib1.dllzlib1.dll/ 1368449285 0 38 ` ÿÿLáQ/_gzseekzlib1.dllzlib1.dll/ 1368449285 0 40 ` ÿÿLáQ0_gzseek64zlib1.dllzlib1.dll/ 1368449285 0 43 ` ÿÿLáQ1_gzsetparamszlib1.dll zlib1.dll/ 1368449285 0 38 ` ÿÿLáQ2_gztellzlib1.dllzlib1.dll/ 1368449285 0 40 ` ÿÿLáQ3_gztell64zlib1.dllzlib1.dll/ 1368449285 0 40 ` ÿÿLáQ4_gzungetczlib1.dllzlib1.dll/ 1368449285 0 41 ` ÿÿLáQ5_gzvprintfzlib1.dll zlib1.dll/ 1368449285 0 39 ` ÿÿLáQ6_gzwritezlib1.dll zlib1.dll/ 1368449285 0 39 ` ÿÿLáQ7_inflatezlib1.dll zlib1.dll/ 1368449285 0 43 ` ÿÿLáQ8_inflateBackzlib1.dll zlib1.dll/ 1368449285 0 46 ` ÿÿLáQ9_inflateBackEndzlib1.dllzlib1.dll/ 1368449285 0 48 ` ÿÿLáQ:_inflateBackInit_zlib1.dllzlib1.dll/ 1368449285 0 43 ` ÿÿLáQ;_inflateCopyzlib1.dll zlib1.dll/ 1368449285 0 42 ` ÿÿLáQ<_inflateEndzlib1.dllzlib1.dll/ 1368449285 0 52 ` ÿÿLáQ =_inflateGetDictionaryzlib1.dllzlib1.dll/ 1368449285 0 48 ` ÿÿLáQ>_inflateGetHeaderzlib1.dllzlib1.dll/ 1368449285 0 45 ` ÿÿLáQ?_inflateInit2_zlib1.dll zlib1.dll/ 1368449285 0 44 ` ÿÿLáQ@_inflateInit_zlib1.dllzlib1.dll/ 1368449285 0 43 ` ÿÿLáQA_inflateMarkzlib1.dll zlib1.dll/ 1368449285 0 44 ` ÿÿLáQB_inflatePrimezlib1.dllzlib1.dll/ 1368449285 0 44 ` ÿÿLáQC_inflateResetzlib1.dllzlib1.dll/ 1368449285 0 45 ` ÿÿLáQD_inflateReset2zlib1.dll zlib1.dll/ 1368449285 0 48 ` ÿÿLáQE_inflateResetKeepzlib1.dllzlib1.dll/ 1368449285 0 52 ` ÿÿLáQ F_inflateSetDictionaryzlib1.dllzlib1.dll/ 1368449285 0 43 ` ÿÿLáQG_inflateSynczlib1.dll zlib1.dll/ 1368449285 0 48 ` ÿÿLáQH_inflateSyncPointzlib1.dllzlib1.dll/ 1368449285 0 48 ` ÿÿLáQI_inflateUnderminezlib1.dllzlib1.dll/ 1368449285 0 42 ` ÿÿLáQJ_uncompresszlib1.dllzlib1.dll/ 1368449285 0 38 ` ÿÿLáQK_zErrorzlib1.dllzlib1.dll/ 1368449285 0 48 ` ÿÿLáQL_zlibCompileFlagszlib1.dllzlib1.dll/ 1368449285 0 43 ` ÿÿLáQM_zlibVersionzlib1.dll tcl8.6.5/compat/zlib/win32/DLL_FAQ.txt0000644000175000017500000004300112663653206016614 0ustar sergeisergei Frequently Asked Questions about ZLIB1.DLL This document describes the design, the rationale, and the usage of the official DLL build of zlib, named ZLIB1.DLL. If you have general questions about zlib, you should see the file "FAQ" found in the zlib distribution, or at the following location: http://www.gzip.org/zlib/zlib_faq.html 1. What is ZLIB1.DLL, and how can I get it? - ZLIB1.DLL is the official build of zlib as a DLL. (Please remark the character '1' in the name.) Pointers to a precompiled ZLIB1.DLL can be found in the zlib web site at: http://www.zlib.net/ Applications that link to ZLIB1.DLL can rely on the following specification: * The exported symbols are exclusively defined in the source files "zlib.h" and "zlib.def", found in an official zlib source distribution. * The symbols are exported by name, not by ordinal. * The exported names are undecorated. * The calling convention of functions is "C" (CDECL). * The ZLIB1.DLL binary is linked to MSVCRT.DLL. The archive in which ZLIB1.DLL is bundled contains compiled test programs that must run with a valid build of ZLIB1.DLL. It is recommended to download the prebuilt DLL from the zlib web site, instead of building it yourself, to avoid potential incompatibilities that could be introduced by your compiler and build settings. If you do build the DLL yourself, please make sure that it complies with all the above requirements, and it runs with the precompiled test programs, bundled with the original ZLIB1.DLL distribution. If, for any reason, you need to build an incompatible DLL, please use a different file name. 2. Why did you change the name of the DLL to ZLIB1.DLL? What happened to the old ZLIB.DLL? - The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required compilation settings that were incompatible to those used by a static build. The DLL settings were supposed to be enabled by defining the macro ZLIB_DLL, before including "zlib.h". Incorrect handling of this macro was silently accepted at build time, resulting in two major problems: * ZLIB_DLL was missing from the old makefile. When building the DLL, not all people added it to the build options. In consequence, incompatible incarnations of ZLIB.DLL started to circulate around the net. * When switching from using the static library to using the DLL, applications had to define the ZLIB_DLL macro and to recompile all the sources that contained calls to zlib functions. Failure to do so resulted in creating binaries that were unable to run with the official ZLIB.DLL build. The only possible solution that we could foresee was to make a binary-incompatible change in the DLL interface, in order to remove the dependency on the ZLIB_DLL macro, and to release the new DLL under a different name. We chose the name ZLIB1.DLL, where '1' indicates the major zlib version number. We hope that we will not have to break the binary compatibility again, at least not as long as the zlib-1.x series will last. There is still a ZLIB_DLL macro, that can trigger a more efficient build and use of the DLL, but compatibility no longer dependents on it. 3. Can I build ZLIB.DLL from the new zlib sources, and replace an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier? - In principle, you can do it by assigning calling convention keywords to the macros ZEXPORT and ZEXPORTVA. In practice, it depends on what you mean by "an old ZLIB.DLL", because the old DLL exists in several mutually-incompatible versions. You have to find out first what kind of calling convention is being used in your particular ZLIB.DLL build, and to use the same one in the new build. If you don't know what this is all about, you might be better off if you would just leave the old DLL intact. 4. Can I compile my application using the new zlib interface, and link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier? - The official answer is "no"; the real answer depends again on what kind of ZLIB.DLL you have. Even if you are lucky, this course of action is unreliable. If you rebuild your application and you intend to use a newer version of zlib (post- 1.1.4), it is strongly recommended to link it to the new ZLIB1.DLL. 5. Why are the zlib symbols exported by name, and not by ordinal? - Although exporting symbols by ordinal is a little faster, it is risky. Any single glitch in the maintenance or use of the DEF file that contains the ordinals can result in incompatible builds and frustrating crashes. Simply put, the benefits of exporting symbols by ordinal do not justify the risks. Technically, it should be possible to maintain ordinals in the DEF file, and still export the symbols by name. Ordinals exist in every DLL, and even if the dynamic linking performed at the DLL startup is searching for names, ordinals serve as hints, for a faster name lookup. However, if the DEF file contains ordinals, the Microsoft linker automatically builds an implib that will cause the executables linked to it to use those ordinals, and not the names. It is interesting to notice that the GNU linker for Win32 does not suffer from this problem. It is possible to avoid the DEF file if the exported symbols are accompanied by a "__declspec(dllexport)" attribute in the source files. You can do this in zlib by predefining the ZLIB_DLL macro. 6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling convention. Why not use the STDCALL convention? STDCALL is the standard convention in Win32, and I need it in my Visual Basic project! (For readability, we use CDECL to refer to the convention triggered by the "__cdecl" keyword, STDCALL to refer to the convention triggered by "__stdcall", and FASTCALL to refer to the convention triggered by "__fastcall".) - Most of the native Windows API functions (without varargs) use indeed the WINAPI convention (which translates to STDCALL in Win32), but the standard C functions use CDECL. If a user application is intrinsically tied to the Windows API (e.g. it calls native Windows API functions such as CreateFile()), sometimes it makes sense to decorate its own functions with WINAPI. But if ANSI C or POSIX portability is a goal (e.g. it calls standard C functions such as fopen()), it is not a sound decision to request the inclusion of , or to use non-ANSI constructs, for the sole purpose to make the user functions STDCALL-able. The functionality offered by zlib is not in the category of "Windows functionality", but is more like "C functionality". Technically, STDCALL is not bad; in fact, it is slightly faster than CDECL, and it works with variable-argument functions, just like CDECL. It is unfortunate that, in spite of using STDCALL in the Windows API, it is not the default convention used by the C compilers that run under Windows. The roots of the problem reside deep inside the unsafety of the K&R-style function prototypes, where the argument types are not specified; but that is another story for another day. The remaining fact is that CDECL is the default convention. Even if an explicit convention is hard-coded into the function prototypes inside C headers, problems may appear. The necessity to expose the convention in users' callbacks is one of these problems. The calling convention issues are also important when using zlib in other programming languages. Some of them, like Ada (GNAT) and Fortran (GNU G77), have C bindings implemented initially on Unix, and relying on the C calling convention. On the other hand, the pre- .NET versions of Microsoft Visual Basic require STDCALL, while Borland Delphi prefers, although it does not require, FASTCALL. In fairness to all possible uses of zlib outside the C programming language, we choose the default "C" convention. Anyone interested in different bindings or conventions is encouraged to maintain specialized projects. The "contrib/" directory from the zlib distribution already holds a couple of foreign bindings, such as Ada, C++, and Delphi. 7. I need a DLL for my Visual Basic project. What can I do? - Define the ZLIB_WINAPI macro before including "zlib.h", when building both the DLL and the user application (except that you don't need to define anything when using the DLL in Visual Basic). The ZLIB_WINAPI macro will switch on the WINAPI (STDCALL) convention. The name of this DLL must be different than the official ZLIB1.DLL. Gilles Vollant has contributed a build named ZLIBWAPI.DLL, with the ZLIB_WINAPI macro turned on, and with the minizip functionality built in. For more information, please read the notes inside "contrib/vstudio/readme.txt", found in the zlib distribution. 8. I need to use zlib in my Microsoft .NET project. What can I do? - Henrik Ravn has contributed a .NET wrapper around zlib. Look into contrib/dotzlib/, inside the zlib distribution. 9. If my application uses ZLIB1.DLL, should I link it to MSVCRT.DLL? Why? - It is not required, but it is recommended to link your application to MSVCRT.DLL, if it uses ZLIB1.DLL. The executables (.EXE, .DLL, etc.) that are involved in the same process and are using the C run-time library (i.e. they are calling standard C functions), must link to the same library. There are several libraries in the Win32 system: CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc. Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that depend on it should also be linked to MSVCRT.DLL. 10. Why are you saying that ZLIB1.DLL and my application should be linked to the same C run-time (CRT) library? I linked my application and my DLLs to different C libraries (e.g. my application to a static library, and my DLLs to MSVCRT.DLL), and everything works fine. - If a user library invokes only pure Win32 API (accessible via and the related headers), its DLL build will work in any context. But if this library invokes standard C API, things get more complicated. There is a single Win32 library in a Win32 system. Every function in this library resides in a single DLL module, that is safe to call from anywhere. On the other hand, there are multiple versions of the C library, and each of them has its own separate internal state. Standalone executables and user DLLs that call standard C functions must link to a C run-time (CRT) library, be it static or shared (DLL). Intermixing occurs when an executable (not necessarily standalone) and a DLL are linked to different CRTs, and both are running in the same process. Intermixing multiple CRTs is possible, as long as their internal states are kept intact. The Microsoft Knowledge Base articles KB94248 "HOWTO: Use the C Run-Time" and KB140584 "HOWTO: Link with the Correct C Run-Time (CRT) Library" mention the potential problems raised by intermixing. If intermixing works for you, it's because your application and DLLs are avoiding the corruption of each of the CRTs' internal states, maybe by careful design, or maybe by fortune. Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such as those provided by Borland, raises similar problems. 11. Why are you linking ZLIB1.DLL to MSVCRT.DLL? - MSVCRT.DLL exists on every Windows 95 with a new service pack installed, or with Microsoft Internet Explorer 4 or later, and on all other Windows 4.x or later (Windows 98, Windows NT 4, or later). It is freely distributable; if not present in the system, it can be downloaded from Microsoft or from other software provider for free. The fact that MSVCRT.DLL does not exist on a virgin Windows 95 is not so problematic. Windows 95 is scarcely found nowadays, Microsoft ended its support a long time ago, and many recent applications from various vendors, including Microsoft, do not even run on it. Furthermore, no serious user should run Windows 95 without a proper update installed. 12. Why are you not linking ZLIB1.DLL to <> ? - We considered and abandoned the following alternatives: * Linking ZLIB1.DLL to a static C library (LIBC.LIB, or LIBCMT.LIB) is not a good option. People are using the DLL mainly to save disk space. If you are linking your program to a static C library, you may as well consider linking zlib in statically, too. * Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because CRTDLL.DLL is present on every Win32 installation. Unfortunately, it has a series of problems: it does not work properly with Microsoft's C++ libraries, it does not provide support for 64-bit file offsets, (and so on...), and Microsoft discontinued its support a long time ago. * Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied with the Microsoft .NET platform, and Visual C++ 7.0/7.1, raises problems related to the status of ZLIB1.DLL as a system component. According to the Microsoft Knowledge Base article KB326922 "INFO: Redistribution of the Shared C Runtime Component in Visual C++ .NET", MSVCR70.DLL and MSVCR71.DLL are not supposed to function as system DLLs, because they may clash with MSVCRT.DLL. Instead, the application's installer is supposed to put these DLLs (if needed) in the application's private directory. If ZLIB1.DLL depends on a non-system runtime, it cannot function as a redistributable system component. * Linking ZLIB1.DLL to non-Microsoft runtimes, such as Borland's, or Cygwin's, raises problems related to the reliable presence of these runtimes on Win32 systems. It's easier to let the DLL build of zlib up to the people who distribute these runtimes, and who may proceed as explained in the answer to Question 14. 13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL, how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0 (Visual Studio .NET) or newer? - Due to the problems explained in the Microsoft Knowledge Base article KB326922 (see the previous answer), the C runtime that comes with the VC7 environment is no longer considered a system component. That is, it should not be assumed that this runtime exists, or may be installed in a system directory. Since ZLIB1.DLL is supposed to be a system component, it may not depend on a non-system component. In order to link ZLIB1.DLL and your application to MSVCRT.DLL in VC7, you need the library of Visual C++ 6.0 or older. If you don't have this library at hand, it's probably best not to use ZLIB1.DLL. We are hoping that, in the future, Microsoft will provide a way to build applications linked to a proper system runtime, from the Visual C++ environment. Until then, you have a couple of alternatives, such as linking zlib in statically. If your application requires dynamic linking, you may proceed as explained in the answer to Question 14. 14. I need to link my own DLL build to a CRT different than MSVCRT.DLL. What can I do? - Feel free to rebuild the DLL from the zlib sources, and link it the way you want. You should, however, clearly state that your build is unofficial. You should give it a different file name, and/or install it in a private directory that can be accessed by your application only, and is not visible to the others (i.e. it's neither in the PATH, nor in the SYSTEM or SYSTEM32 directories). Otherwise, your build may clash with applications that link to the official build. For example, in Cygwin, zlib is linked to the Cygwin runtime CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL. 15. May I include additional pieces of code that I find useful, link them in ZLIB1.DLL, and export them? - No. A legitimate build of ZLIB1.DLL must not include code that does not originate from the official zlib source code. But you can make your own private DLL build, under a different file name, as suggested in the previous answer. For example, zlib is a part of the VCL library, distributed with Borland Delphi and C++ Builder. The DLL build of VCL is a redistributable file, named VCLxx.DLL. 16. May I remove some functionality out of ZLIB1.DLL, by enabling macros like NO_GZCOMPRESS or NO_GZIP at compile time? - No. A legitimate build of ZLIB1.DLL must provide the complete zlib functionality, as implemented in the official zlib source code. But you can make your own private DLL build, under a different file name, as suggested in the previous answer. 17. I made my own ZLIB1.DLL build. Can I test it for compliance? - We prefer that you download the official DLL from the zlib web site. If you need something peculiar from this DLL, you can send your suggestion to the zlib mailing list. However, in case you do rebuild the DLL yourself, you can run it with the test programs found in the DLL distribution. Running these test programs is not a guarantee of compliance, but a failure can imply a detected problem. ** This document is written and maintained by Cosmin Truta tcl8.6.5/compat/zlib/win32/VisualC.txt0000644000175000017500000000016512663653131017061 0ustar sergeisergei To build zlib using the Microsoft Visual C++ environment, use the appropriate project from the projects/ directory. tcl8.6.5/compat/zlib/win32/README-WIN32.txt0000644000175000017500000001140412663660065017252 0ustar sergeisergeiZLIB DATA COMPRESSION LIBRARY zlib 1.2.8 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). All functions of the compression library are documented in the file zlib.h (volunteer to write man pages welcome, contact zlib@gzip.org). Two compiled examples are distributed in this package, example and minigzip. The example_d and minigzip_d flavors validate that the zlib1.dll file is working correctly. Questions about zlib should be sent to . The zlib home page is http://zlib.net/ . Before reporting a problem, please check this site to verify that you have the latest version of zlib; otherwise get the latest version and check whether the problem still exists or not. PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. Manifest: The package zlib-1.2.8-win32-x86.zip will contain the following files: README-WIN32.txt This document ChangeLog Changes since previous zlib packages DLL_FAQ.txt Frequently asked questions about zlib1.dll zlib.3.pdf Documentation of this library in Adobe Acrobat format example.exe A statically-bound example (using zlib.lib, not the dll) example.pdb Symbolic information for debugging example.exe example_d.exe A zlib1.dll bound example (using zdll.lib) example_d.pdb Symbolic information for debugging example_d.exe minigzip.exe A statically-bound test program (using zlib.lib, not the dll) minigzip.pdb Symbolic information for debugging minigzip.exe minigzip_d.exe A zlib1.dll bound test program (using zdll.lib) minigzip_d.pdb Symbolic information for debugging minigzip_d.exe zlib.h Install these files into the compilers' INCLUDE path to zconf.h compile programs which use zlib.lib or zdll.lib zdll.lib Install these files into the compilers' LIB path if linking zdll.exp a compiled program to the zlib1.dll binary zlib.lib Install these files into the compilers' LIB path to link zlib zlib.pdb into compiled programs, without zlib1.dll runtime dependency (zlib.pdb provides debugging info to the compile time linker) zlib1.dll Install this binary shared library into the system PATH, or the program's runtime directory (where the .exe resides) zlib1.pdb Install in the same directory as zlib1.dll, in order to debug an application crash using WinDbg or similar tools. All .pdb files above are entirely optional, but are very useful to a developer attempting to diagnose program misbehavior or a crash. Many additional important files for developers can be found in the zlib127.zip source package available from http://zlib.net/ - review that package's README file for details. Acknowledgments: The deflate format used by zlib was defined by Phil Katz. The deflate and zlib specifications were written by L. Peter Deutsch. Thanks to all the people who reported problems and suggested various improvements in zlib; they are too numerous to cite here. Copyright notice: (C) 1995-2012 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu If you use the zlib library in a product, we would appreciate *not* receiving lengthy legal documents to sign. The sources are provided for free but without warranty of any kind. The library has been entirely written by Jean-loup Gailly and Mark Adler; it does not include third-party code. If you redistribute modified sources, we would appreciate that you include in the file ChangeLog history information documenting your changes. Please read the FAQ for more information on the distribution of modified source versions. tcl8.6.5/compat/zlib/win32/README.txt0000644000175000017500000000356512663660065016463 0ustar sergeisergei What's here =========== The official ZLIB1.DLL Source ====== zlib version 1.2.8 available at http://www.gzip.org/zlib/ Specification and rationale =========================== See the accompanying DLL_FAQ.txt Usage ===== See the accompanying USAGE.txt Build info ========== Contributed by Jan Nijtmans. Compiler: i686-w64-mingw32-gcc (GCC) 4.5.3 Library: mingw64-i686-runtime/headers: 3.0b_svn5747-1 Build commands: i686-w64-mingw32-gcc -c -DASMV contrib/asm686/match.S i686-w64-mingw32-gcc -c -DASMINF -I. -O3 contrib/inflate86/inffas86.c make -f win32/Makefile.gcc PREFIX=i686-w64-mingw32- LOC="-mms-bitfields -DASMV -DASMINF" OBJA="inffas86.o match.o" Finally, from VS commandline (VS2005 or higher): lib -machine:X86 -name:zlib1.dll -def:zlib.def -out:zdll.lib Copyright notice ================ Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu tcl8.6.5/compat/zlib/win32/Makefile.bor0000644000175000017500000000503312663660065017176 0ustar sergeisergei# Makefile for zlib # Borland C++ for Win32 # # Usage: # make -f win32/Makefile.bor # make -f win32/Makefile.bor LOCAL_ZLIB=-DASMV OBJA=match.obj OBJPA=+match.obj # ------------ Borland C++ ------------ # Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) # should be added to the environment via "set LOCAL_ZLIB=-DFOO" or # added to the declaration of LOC here: LOC = $(LOCAL_ZLIB) CC = bcc32 AS = bcc32 LD = bcc32 AR = tlib CFLAGS = -a -d -k- -O2 $(LOC) ASFLAGS = $(LOC) LDFLAGS = $(LOC) # variables ZLIB_LIB = zlib.lib OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj #OBJA = OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj #OBJPA= # targets all: $(ZLIB_LIB) example.exe minigzip.exe .c.obj: $(CC) -c $(CFLAGS) $< .asm.obj: $(AS) -c $(ASFLAGS) $< adler32.obj: adler32.c zlib.h zconf.h compress.obj: compress.c zlib.h zconf.h crc32.obj: crc32.c zlib.h zconf.h crc32.h deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h gzread.obj: gzread.c zlib.h zconf.h gzguts.h gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ inffast.h inffixed.h inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h uncompr.obj: uncompr.c zlib.h zconf.h zutil.obj: zutil.c zutil.h zlib.h zconf.h example.obj: test/example.c zlib.h zconf.h minigzip.obj: test/minigzip.c zlib.h zconf.h # For the sake of the old Borland make, # the command line is cut to fit in the MS-DOS 128 byte limit: $(ZLIB_LIB): $(OBJ1) $(OBJ2) $(OBJA) -del $(ZLIB_LIB) $(AR) $(ZLIB_LIB) $(OBJP1) $(AR) $(ZLIB_LIB) $(OBJP2) $(AR) $(ZLIB_LIB) $(OBJPA) # testing test: example.exe minigzip.exe example echo hello world | minigzip | minigzip -d example.exe: example.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) minigzip.exe: minigzip.obj $(ZLIB_LIB) $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) # cleanup clean: -del $(ZLIB_LIB) -del *.obj -del *.exe -del *.tds -del zlib.bak -del foo.gz tcl8.6.5/compat/zlib/win32/zlib.def0000644000175000017500000000255712663660065016405 0ustar sergeisergei; zlib data compression library EXPORTS ; basic functions zlibVersion deflate deflateEnd inflate inflateEnd ; advanced functions deflateSetDictionary deflateCopy deflateReset deflateParams deflateTune deflateBound deflatePending deflatePrime deflateSetHeader inflateSetDictionary inflateGetDictionary inflateSync inflateCopy inflateReset inflateReset2 inflatePrime inflateMark inflateGetHeader inflateBack inflateBackEnd zlibCompileFlags ; utility functions compress compress2 compressBound uncompress gzopen gzdopen gzbuffer gzsetparams gzread gzwrite gzprintf gzvprintf gzputs gzgets gzputc gzgetc gzungetc gzflush gzseek gzrewind gztell gzoffset gzeof gzdirect gzclose gzclose_r gzclose_w gzerror gzclearerr ; large file functions gzopen64 gzseek64 gztell64 gzoffset64 adler32_combine64 crc32_combine64 ; checksum functions adler32 crc32 adler32_combine crc32_combine ; various hacks, don't look :) deflateInit_ deflateInit2_ inflateInit_ inflateInit2_ inflateBackInit_ gzgetc_ zError inflateSyncPoint get_crc_table inflateUndermine inflateResetKeep deflateResetKeep gzopen_w tcl8.6.5/compat/zlib/FAQ0000644000175000017500000004027512663660064014353 0ustar sergeisergei Frequently Asked Questions about zlib If your question is not there, please check the zlib home page http://zlib.net/ which may have more recent information. The lastest zlib FAQ is at http://zlib.net/zlib_faq.html 1. Is zlib Y2K-compliant? Yes. zlib doesn't handle dates. 2. Where can I get a Windows DLL version? The zlib sources can be compiled without change to produce a DLL. See the file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the precompiled DLL are found in the zlib web site at http://zlib.net/ . 3. Where can I get a Visual Basic interface to zlib? See * http://marknelson.us/1997/01/01/zlib-engine/ * win32/DLL_FAQ.txt in the zlib distribution 4. compress() returns Z_BUF_ERROR. Make sure that before the call of compress(), the length of the compressed buffer is equal to the available size of the compressed buffer and not zero. For Visual Basic, check that this parameter is passed by reference ("as any"), not by value ("as long"). 5. deflate() or inflate() returns Z_BUF_ERROR. Before making the call, make sure that avail_in and avail_out are not zero. When setting the parameter flush equal to Z_FINISH, also make sure that avail_out is big enough to allow processing all pending input. Note that a Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be made with more input or output space. A Z_BUF_ERROR may in fact be unavoidable depending on how the functions are used, since it is not possible to tell whether or not there is more output pending when strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a heavily annotated example. 6. Where's the zlib documentation (man pages, etc.)? It's in zlib.h . Examples of zlib usage are in the files test/example.c and test/minigzip.c, with more in examples/ . 7. Why don't you use GNU autoconf or libtool or ...? Because we would like to keep zlib as a very small and simple package. zlib is rather portable and doesn't need much configuration. 8. I found a bug in zlib. Most of the time, such problems are due to an incorrect usage of zlib. Please try to reproduce the problem with a small program and send the corresponding source to us at zlib@gzip.org . Do not send multi-megabyte data files without prior agreement. 9. Why do I get "undefined reference to gzputc"? If "make test" produces something like example.o(.text+0x154): undefined reference to `gzputc' check that you don't have old files libz.* in /usr/lib, /usr/local/lib or /usr/X11R6/lib. Remove any old versions, then do "make install". 10. I need a Delphi interface to zlib. See the contrib/delphi directory in the zlib distribution. 11. Can zlib handle .zip archives? Not by itself, no. See the directory contrib/minizip in the zlib distribution. 12. Can zlib handle .Z files? No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt the code of uncompress on your own. 13. How can I make a Unix shared library? By default a shared (and a static) library is built for Unix. So: make distclean ./configure make 14. How do I install a shared zlib library on Unix? After the above, then: make install However, many flavors of Unix come with a shared zlib already installed. Before going to the trouble of compiling a shared version of zlib and trying to install it, you may want to check if it's already there! If you can #include , it's there. The -lz option will probably link to it. You can check the version at the top of zlib.h or with the ZLIB_VERSION symbol defined in zlib.h . 15. I have a question about OttoPDF. We are not the authors of OttoPDF. The real author is on the OttoPDF web site: Joel Hainley, jhainley@myndkryme.com. 16. Can zlib decode Flate data in an Adobe PDF file? Yes. See http://www.pdflib.com/ . To modify PDF forms, see http://sourceforge.net/projects/acroformtool/ . 17. Why am I getting this "register_frame_info not found" error on Solaris? After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib generates an error such as: ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: symbol __register_frame_info: referenced symbol not found The symbol __register_frame_info is not part of zlib, it is generated by the C compiler (cc or gcc). You must recompile applications using zlib which have this problem. This problem is specific to Solaris. See http://www.sunfreeware.com for Solaris versions of zlib and applications using zlib. 18. Why does gzip give an error on a file I make with compress/deflate? The compress and deflate functions produce data in the zlib format, which is different and incompatible with the gzip format. The gz* functions in zlib on the other hand use the gzip format. Both the zlib and gzip formats use the same compressed data format internally, but have different headers and trailers around the compressed data. 19. Ok, so why are there two different formats? The gzip format was designed to retain the directory information about a single file, such as the name and last modification date. The zlib format on the other hand was designed for in-memory and communication channel applications, and has a much more compact header and trailer and uses a faster integrity check than gzip. 20. Well that's nice, but how do I make a gzip file in memory? You can request that deflate write the gzip format instead of the zlib format using deflateInit2(). You can also request that inflate decode the gzip format using inflateInit2(). Read zlib.h for more details. 21. Is zlib thread-safe? Yes. However any library routines that zlib uses and any application- provided memory allocation routines must also be thread-safe. zlib's gz* functions use stdio library routines, and most of zlib's functions use the library memory allocation routines by default. zlib's *Init* functions allow for the application to provide custom memory allocation routines. Of course, you should only operate on any given zlib or gzip stream from a single thread at a time. 22. Can I use zlib in my commercial application? Yes. Please read the license in zlib.h. 23. Is zlib under the GNU license? No. Please read the license in zlib.h. 24. The license says that altered source versions must be "plainly marked". So what exactly do I need to do to meet that requirement? You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In particular, the final version number needs to be changed to "f", and an identification string should be appended to ZLIB_VERSION. Version numbers x.x.x.f are reserved for modifications to zlib by others than the zlib maintainers. For example, if the version of the base zlib you are altering is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also update the version strings in deflate.c and inftrees.c. For altered source distributions, you should also note the origin and nature of the changes in zlib.h, as well as in ChangeLog and README, along with the dates of the alterations. The origin should include at least your name (or your company's name), and an email address to contact for help or issues with the library. Note that distributing a compiled zlib library along with zlib.h and zconf.h is also a source distribution, and so you should change ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes in zlib.h as you would for a full source distribution. 25. Will zlib work on a big-endian or little-endian architecture, and can I exchange compressed data between them? Yes and yes. 26. Will zlib work on a 64-bit machine? Yes. It has been tested on 64-bit machines, and has no dependence on any data types being limited to 32-bits in length. If you have any difficulties, please provide a complete problem report to zlib@gzip.org 27. Will zlib decompress data from the PKWare Data Compression Library? No. The PKWare DCL uses a completely different compressed data format than does PKZIP and zlib. However, you can look in zlib's contrib/blast directory for a possible solution to your problem. 28. Can I access data randomly in a compressed stream? No, not without some preparation. If when compressing you periodically use Z_FULL_FLUSH, carefully write all the pending data at those points, and keep an index of those locations, then you can start decompression at those points. You have to be careful to not use Z_FULL_FLUSH too often, since it can significantly degrade compression. Alternatively, you can scan a deflate stream once to generate an index, and then use that index for random access. See examples/zran.c . 29. Does zlib work on MVS, OS/390, CICS, etc.? It has in the past, but we have not heard of any recent evidence. There were working ports of zlib 1.1.4 to MVS, but those links no longer work. If you know of recent, successful applications of zlib on these operating systems, please let us know. Thanks. 30. Is there some simpler, easier to read version of inflate I can look at to understand the deflate format? First off, you should read RFC 1951. Second, yes. Look in zlib's contrib/puff directory. 31. Does zlib infringe on any patents? As far as we know, no. In fact, that was originally the whole point behind zlib. Look here for some more information: http://www.gzip.org/#faq11 32. Can zlib work with greater than 4 GB of data? Yes. inflate() and deflate() will process any amount of data correctly. Each call of inflate() or deflate() is limited to input and output chunks of the maximum value that can be stored in the compiler's "unsigned int" type, but there is no limit to the number of chunks. Note however that the strm.total_in and strm_total_out counters may be limited to 4 GB. These counters are provided as a convenience and are not used internally by inflate() or deflate(). The application can easily set up its own counters updated after each call of inflate() or deflate() to count beyond 4 GB. compress() and uncompress() may be limited to 4 GB, since they operate in a single call. gzseek() and gztell() may be limited to 4 GB depending on how zlib is compiled. See the zlibCompileFlags() function in zlib.h. The word "may" appears several times above since there is a 4 GB limit only if the compiler's "long" type is 32 bits. If the compiler's "long" type is 64 bits, then the limit is 16 exabytes. 33. Does zlib have any security vulnerabilities? The only one that we are aware of is potentially in gzprintf(). If zlib is compiled to use sprintf() or vsprintf(), then there is no protection against a buffer overflow of an 8K string space (or other value as set by gzbuffer()), other than the caller of gzprintf() assuring that the output will not exceed 8K. On the other hand, if zlib is compiled to use snprintf() or vsnprintf(), which should normally be the case, then there is no vulnerability. The ./configure script will display warnings if an insecure variation of sprintf() will be used by gzprintf(). Also the zlibCompileFlags() function will return information on what variant of sprintf() is used by gzprintf(). If you don't have snprintf() or vsnprintf() and would like one, you can find a portable implementation here: http://www.ijs.si/software/snprintf/ Note that you should be using the most recent version of zlib. Versions 1.1.3 and before were subject to a double-free vulnerability, and versions 1.2.1 and 1.2.2 were subject to an access exception when decompressing invalid compressed data. 34. Is there a Java version of zlib? Probably what you want is to use zlib in Java. zlib is already included as part of the Java SDK in the java.util.zip package. If you really want a version of zlib written in the Java language, look on the zlib home page for links: http://zlib.net/ . 35. I get this or that compiler or source-code scanner warning when I crank it up to maximally-pedantic. Can't you guys write proper code? Many years ago, we gave up attempting to avoid warnings on every compiler in the universe. It just got to be a waste of time, and some compilers were downright silly as well as contradicted each other. So now, we simply make sure that the code always works. 36. Valgrind (or some similar memory access checker) says that deflate is performing a conditional jump that depends on an uninitialized value. Isn't that a bug? No. That is intentional for performance reasons, and the output of deflate is not affected. This only started showing up recently since zlib 1.2.x uses malloc() by default for allocations, whereas earlier versions used calloc(), which zeros out the allocated memory. Even though the code was correct, versions 1.2.4 and later was changed to not stimulate these checkers. 37. Will zlib read the (insert any ancient or arcane format here) compressed data format? Probably not. Look in the comp.compression FAQ for pointers to various formats and associated software. 38. How can I encrypt/decrypt zip files with zlib? zlib doesn't support encryption. The original PKZIP encryption is very weak and can be broken with freely available programs. To get strong encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib compression. For PKZIP compatible "encryption", look at http://www.info-zip.org/ 39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? "gzip" is the gzip format, and "deflate" is the zlib format. They should probably have called the second one "zlib" instead to avoid confusion with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 correctly points to the zlib specification in RFC 1950 for the "deflate" transfer encoding, there have been reports of servers and browsers that incorrectly produce or expect raw deflate data per the deflate specification in RFC 1951, most notably Microsoft. So even though the "deflate" transfer encoding using the zlib format would be the more efficient approach (and in fact exactly what the zlib format was designed for), using the "gzip" transfer encoding is probably more reliable due to an unfortunate choice of name on the part of the HTTP 1.1 authors. Bottom line: use the gzip format for HTTP 1.1 encoding. 40. Does zlib support the new "Deflate64" format introduced by PKWare? No. PKWare has apparently decided to keep that format proprietary, since they have not documented it as they have previous compression formats. In any case, the compression improvements are so modest compared to other more modern approaches, that it's not worth the effort to implement. 41. I'm having a problem with the zip functions in zlib, can you help? There are no zip functions in zlib. You are probably using minizip by Giles Vollant, which is found in the contrib directory of zlib. It is not part of zlib. In fact none of the stuff in contrib is part of zlib. The files in there are not supported by the zlib authors. You need to contact the authors of the respective contribution for help. 42. The match.asm code in contrib is under the GNU General Public License. Since it's part of zlib, doesn't that mean that all of zlib falls under the GNU GPL? No. The files in contrib are not part of zlib. They were contributed by other authors and are provided as a convenience to the user within the zlib distribution. Each item in contrib has its own license. 43. Is zlib subject to export controls? What is its ECCN? zlib is not subject to export controls, and so is classified as EAR99. 44. Can you please sign these lengthy legal documents and fax them back to us so that we can use your software in our product? No. Go away. Shoo. tcl8.6.5/compat/fake-rfc2553.c0000644000175000017500000001617112663660064015220 0ustar sergeisergei/* * Copyright (C) 2000-2003 Damien Miller. All rights reserved. * Copyright (C) 1999 WIDE Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Pseudo-implementation of RFC2553 name / address resolution functions * * But these functions are not implemented correctly. The minimum subset * is implemented for ssh use only. For example, this routine assumes * that ai_family is AF_INET. Don't use it for another purpose. */ #include "tclInt.h" TCL_DECLARE_MUTEX(netdbMutex) #ifndef HAVE_GETNAMEINFO #ifndef HAVE_STRLCPY static size_t strlcpy(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } #endif int fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { struct sockaddr_in *sin = (struct sockaddr_in *)sa; struct hostent *hp; char tmpserv[16]; if (sa->sa_family != AF_UNSPEC && sa->sa_family != AF_INET) return (EAI_FAMILY); if (serv != NULL) { snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port)); if (strlcpy(serv, tmpserv, servlen) >= servlen) return (EAI_MEMORY); } if (host != NULL) { if (flags & NI_NUMERICHOST) { size_t len; Tcl_MutexLock(&netdbMutex); len = strlcpy(host, inet_ntoa(sin->sin_addr), hostlen); Tcl_MutexUnlock(&netdbMutex); if (len >= hostlen) { return (EAI_MEMORY); } else { return (0); } } else { int ret; Tcl_MutexLock(&netdbMutex); hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), AF_INET); if (hp == NULL) { ret = EAI_NODATA; } else if (strlcpy(host, hp->h_name, hostlen) >= hostlen) { ret = EAI_MEMORY; } else { ret = 0; } Tcl_MutexUnlock(&netdbMutex); return ret; } } return (0); } #endif /* !HAVE_GETNAMEINFO */ #ifndef HAVE_GAI_STRERROR const char * fake_gai_strerror(int err) { switch (err) { case EAI_NODATA: return ("no address associated with name"); case EAI_MEMORY: return ("memory allocation failure."); case EAI_NONAME: return ("nodename nor servname provided, or not known"); case EAI_FAMILY: return ("ai_family not supported"); default: return ("unknown/invalid error."); } } #endif /* !HAVE_GAI_STRERROR */ #ifndef HAVE_FREEADDRINFO void fake_freeaddrinfo(struct addrinfo *ai) { struct addrinfo *next; for(; ai != NULL;) { next = ai->ai_next; free(ai); ai = next; } } #endif /* !HAVE_FREEADDRINFO */ #ifndef HAVE_GETADDRINFO static struct addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints) { struct addrinfo *ai; ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in)); if (ai == NULL) return (NULL); memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in)); ai->ai_addr = (struct sockaddr *)(ai + 1); /* XXX -- ssh doesn't use sa_len */ ai->ai_addrlen = sizeof(struct sockaddr_in); ai->ai_addr->sa_family = ai->ai_family = AF_INET; ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; /* XXX: the following is not generally correct, but does what we want */ if (hints->ai_socktype) ai->ai_socktype = hints->ai_socktype; else ai->ai_socktype = SOCK_STREAM; if (hints->ai_protocol) ai->ai_protocol = hints->ai_protocol; return (ai); } int fake_getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { struct hostent *hp; struct servent *sp; struct in_addr in; int i; long int port; u_long addr; port = 0; if (hints && hints->ai_family != AF_UNSPEC && hints->ai_family != AF_INET) return (EAI_FAMILY); if (servname != NULL) { char *cp; port = strtol(servname, &cp, 10); if (port > 0 && port <= 65535 && *cp == '\0') port = htons((unsigned short)port); else if ((sp = getservbyname(servname, NULL)) != NULL) port = sp->s_port; else port = 0; } if (hints && hints->ai_flags & AI_PASSIVE) { addr = htonl(0x00000000); if (hostname && inet_aton(hostname, &in) != 0) addr = in.s_addr; *res = malloc_ai(port, addr, hints); if (*res == NULL) return (EAI_MEMORY); return (0); } if (!hostname) { *res = malloc_ai(port, htonl(0x7f000001), hints); if (*res == NULL) return (EAI_MEMORY); return (0); } if (inet_aton(hostname, &in)) { *res = malloc_ai(port, in.s_addr, hints); if (*res == NULL) return (EAI_MEMORY); return (0); } /* Don't try DNS if AI_NUMERICHOST is set */ if (hints && hints->ai_flags & AI_NUMERICHOST) return (EAI_NONAME); Tcl_MutexLock(&netdbMutex); hp = gethostbyname(hostname); if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { struct addrinfo *cur, *prev; cur = prev = *res = NULL; for (i = 0; hp->h_addr_list[i]; i++) { struct in_addr *in = (struct in_addr *)hp->h_addr_list[i]; cur = malloc_ai(port, in->s_addr, hints); if (cur == NULL) { if (*res != NULL) freeaddrinfo(*res); Tcl_MutexUnlock(&netdbMutex); return (EAI_MEMORY); } if (prev) prev->ai_next = cur; else *res = cur; prev = cur; } Tcl_MutexUnlock(&netdbMutex); return (0); } Tcl_MutexUnlock(&netdbMutex); return (EAI_NODATA); } #endif /* !HAVE_GETADDRINFO */ tcl8.6.5/compat/strtoul.c0000644000175000017500000001154712663660064014741 0ustar sergeisergei/* * strtoul.c -- * * Source code for the "strtoul" library procedure. * * Copyright (c) 1988 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * The table below is used to convert from ASCII digits to a numerical * equivalent. It maps from '0' through 'z' to integers (100 for non-digit * characters). */ static const char cvtIn[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* '0' - '9' */ 100, 100, 100, 100, 100, 100, 100, /* punctuation */ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'A' - 'Z' */ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 100, 100, 100, 100, 100, 100, /* punctuation */ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'a' - 'z' */ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35}; /* *---------------------------------------------------------------------- * * strtoul -- * * Convert an ASCII string into an integer. * * Results: * The return value is the integer equivalent of string. If endPtr is * non-NULL, then *endPtr is filled in with the character after the last * one that was part of the integer. If string doesn't contain a valid * integer value, then zero is returned and *endPtr is set to string. * * Side effects: * None. * *---------------------------------------------------------------------- */ unsigned long int strtoul( const char *string, /* String of ASCII digits, possibly preceded * by white space. For bases greater than 10, * either lower- or upper-case digits may be * used. */ char **endPtr, /* Where to store address of terminating * character, or NULL. */ int base) /* Base for conversion. Must be less than 37. * If 0, then the base is chosen from the * leading characters of string: "0x" means * hex, "0" means octal, anything else means * decimal. */ { register const char *p; register unsigned long int result = 0; register unsigned digit; int anyDigits = 0; int negative=0; int overflow=0; /* * Skip any leading blanks. */ p = string; while (isspace(UCHAR(*p))) { p += 1; } if (*p == '-') { negative = 1; p += 1; } else { if (*p == '+') { p += 1; } } /* * If no base was provided, pick one from the leading characters of the * string. */ if (base == 0) { if (*p == '0') { p += 1; if ((*p == 'x') || (*p == 'X')) { p += 1; base = 16; } else { /* * Must set anyDigits here, otherwise "0" produces a "no * digits" error. */ anyDigits = 1; base = 8; } } else { base = 10; } } else if (base == 16) { /* * Skip a leading "0x" from hex numbers. */ if ((p[0] == '0') && ((p[1] == 'x') || (p[1] == 'X'))) { p += 2; } } /* * Sorry this code is so messy, but speed seems important. Do different * things for base 8, 10, 16, and other. */ if (base == 8) { unsigned long maxres = ULONG_MAX >> 3; for ( ; ; p += 1) { digit = *p - '0'; if (digit > 7) { break; } if (result > maxres) { overflow = 1; } result = (result << 3); if (digit > (ULONG_MAX - result)) { overflow = 1; } result += digit; anyDigits = 1; } } else if (base == 10) { unsigned long maxres = ULONG_MAX / 10; for ( ; ; p += 1) { digit = *p - '0'; if (digit > 9) { break; } if (result > maxres) { overflow = 1; } result *= 10; if (digit > (ULONG_MAX - result)) { overflow = 1; } result += digit; anyDigits = 1; } } else if (base == 16) { unsigned long maxres = ULONG_MAX >> 4; for ( ; ; p += 1) { digit = *p - '0'; if (digit > ('z' - '0')) { break; } digit = cvtIn[digit]; if (digit > 15) { break; } if (result > maxres) { overflow = 1; } result = (result << 4); if (digit > (ULONG_MAX - result)) { overflow = 1; } result += digit; anyDigits = 1; } } else if (base >= 2 && base <= 36) { unsigned long maxres = ULONG_MAX / base; for ( ; ; p += 1) { digit = *p - '0'; if (digit > ('z' - '0')) { break; } digit = cvtIn[digit]; if (digit >= ( (unsigned) base )) { break; } if (result > maxres) { overflow = 1; } result *= base; if (digit > (ULONG_MAX - result)) { overflow = 1; } result += digit; anyDigits = 1; } } /* * See if there were any digits at all. */ if (!anyDigits) { p = string; } if (endPtr != 0) { /* unsafe, but required by the strtoul prototype */ *endPtr = (char *) p; } if (overflow) { errno = ERANGE; return ULONG_MAX; } if (negative) { return -result; } return result; } tcl8.6.5/compat/memcmp.c0000644000175000017500000000262012663653206014473 0ustar sergeisergei/* * memcmp.c -- * * Source code for the "memcmp" library routine. * * Copyright (c) 1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclPort.h" /* * Here is the prototype just in case it is not included in tclPort.h. */ int memcmp(const void *s1, const void *s2, size_t n); /* *---------------------------------------------------------------------- * * memcmp -- * * Compares two bytes sequences. * * Results: * Compares its arguments, looking at the first n bytes (each interpreted * as an unsigned char), and returns an integer less than, equal to, or * greater than 0, according as s1 is less than, equal to, or greater * than s2 when taken to be unsigned 8 bit numbers. * * Side effects: * None. * *---------------------------------------------------------------------- */ int memcmp( const void *s1, /* First string. */ const void *s2, /* Second string. */ size_t n) /* Length to compare. */ { const unsigned char *ptr1 = (const unsigned char *) s1; const unsigned char *ptr2 = (const unsigned char *) s2; for ( ; n-- ; ptr1++, ptr2++) { unsigned char u1 = *ptr1, u2 = *ptr2; if (u1 != u2) { return (u1-u2); } } return 0; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ tcl8.6.5/compat/waitpid.c0000644000175000017500000001077012663660064014663 0ustar sergeisergei/* * waitpid.c -- * * This procedure emulates the POSIX waitpid kernel call on BSD systems * that don't have waitpid but do have wait3. This code is based on a * prototype version written by Mark Diekhans and Karl Lehenbauer. * * Copyright (c) 1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclPort.h" #ifndef pid_t #define pid_t int #endif /* * A linked list of the following structures is used to keep track of * processes for which we received notification from the kernel, but the * application hasn't waited for them yet (this can happen because wait may * not return the process we really want). We save the information here until * the application finally does wait for the process. */ typedef struct WaitInfo { pid_t pid; /* Pid of process that exited. */ WAIT_STATUS_TYPE status; /* Status returned when child exited or * suspended. */ struct WaitInfo *nextPtr; /* Next in list of exited processes. */ } WaitInfo; static WaitInfo *deadList = NULL; /* First in list of all dead processes. */ /* *---------------------------------------------------------------------- * * waitpid -- * * This procedure emulates the functionality of the POSIX waitpid kernel * call, using the BSD wait3 kernel call. Note: it doesn't emulate * absolutely all of the waitpid functionality, in that it doesn't * support pid's of 0 or < -1. * * Results: * -1 is returned if there is an error in the wait kernel call. Otherwise * the pid of an exited or suspended process is returned and *statusPtr * is set to the status value of the process. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef waitpid # undef waitpid #endif pid_t waitpid( pid_t pid, /* The pid to wait on. Must be -1 or greater * than zero. */ int *statusPtr, /* Where to store wait status for the * process. */ int options) /* OR'ed combination of WNOHANG and * WUNTRACED. */ { register WaitInfo *waitPtr, *prevPtr; pid_t result; WAIT_STATUS_TYPE status; if ((pid < -1) || (pid == 0)) { errno = EINVAL; return -1; } /* * See if there's a suitable process that has already stopped or exited. * If so, remove it from the list of exited processes and return its * information. */ for (waitPtr = deadList, prevPtr = NULL; waitPtr != NULL; prevPtr = waitPtr, waitPtr = waitPtr->nextPtr) { if ((pid != waitPtr->pid) && (pid != -1)) { continue; } if (!(options & WUNTRACED) && (WIFSTOPPED(waitPtr->status))) { continue; } result = waitPtr->pid; *statusPtr = *((int *) &waitPtr->status); if (prevPtr == NULL) { deadList = waitPtr->nextPtr; } else { prevPtr->nextPtr = waitPtr->nextPtr; } ckfree((char *) waitPtr); return result; } /* * Wait for any process to stop or exit. If it's an acceptable one then * return it to the caller; otherwise store information about it in the * list of exited processes and try again. On systems that have only wait * but not wait3, there are several situations we can't handle, but we do * the best we can (e.g. can still handle some combinations of options by * invoking wait instead of wait3). */ while (1) { #if NO_WAIT3 if (options & WNOHANG) { return 0; } if (options != 0) { errno = EINVAL; return -1; } result = wait(&status); #else result = wait3(&status, options, 0); #endif if ((result == -1) && (errno == EINTR)) { continue; } if (result <= 0) { return result; } if ((pid != result) && (pid != -1)) { goto saveInfo; } if (!(options & WUNTRACED) && (WIFSTOPPED(status))) { goto saveInfo; } *statusPtr = *((int *) &status); return result; /* * Can't return this info to caller. Save it in the list of stopped or * exited processes. Tricky point: first check for an existing entry * for the process and overwrite it if it exists (e.g. a previously * stopped process might now be dead). */ saveInfo: for (waitPtr = deadList; waitPtr != NULL; waitPtr = waitPtr->nextPtr) { if (waitPtr->pid == result) { waitPtr->status = status; goto waitAgain; } } waitPtr = (WaitInfo *) ckalloc(sizeof(WaitInfo)); waitPtr->pid = result; waitPtr->status = status; waitPtr->nextPtr = deadList; deadList = waitPtr; waitAgain: continue; } } tcl8.6.5/compat/fake-rfc2553.h0000644000175000017500000001216112663660064015220 0ustar sergeisergei/* * Copyright (C) 2000-2003 Damien Miller. All rights reserved. * Copyright (C) 1999 WIDE Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Pseudo-implementation of RFC2553 name / address resolution functions * * But these functions are not implemented correctly. The minimum subset * is implemented for ssh use only. For example, this routine assumes * that ai_family is AF_INET. Don't use it for another purpose. */ #ifndef _FAKE_RFC2553_H #define _FAKE_RFC2553_H /* * First, socket and INET6 related definitions */ #ifndef HAVE_STRUCT_SOCKADDR_STORAGE # define _SS_MAXSIZE 128 /* Implementation specific max size */ # define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) struct sockaddr_storage { struct sockaddr ss_sa; char __ss_pad2[_SS_PADSIZE]; }; # define ss_family ss_sa.sa_family #endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ #ifndef IN6_IS_ADDR_LOOPBACK # define IN6_IS_ADDR_LOOPBACK(a) \ (((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \ ((uint32_t *)(a))[2] == 0 && ((uint32_t *)(a))[3] == htonl(1)) #endif /* !IN6_IS_ADDR_LOOPBACK */ #ifndef HAVE_STRUCT_IN6_ADDR struct in6_addr { uint8_t s6_addr[16]; }; #endif /* !HAVE_STRUCT_IN6_ADDR */ #ifndef HAVE_STRUCT_SOCKADDR_IN6 struct sockaddr_in6 { unsigned short sin6_family; uint16_t sin6_port; uint32_t sin6_flowinfo; struct in6_addr sin6_addr; uint32_t sin6_scope_id; }; #endif /* !HAVE_STRUCT_SOCKADDR_IN6 */ #ifndef AF_INET6 /* Define it to something that should never appear */ #define AF_INET6 AF_MAX #endif /* * Next, RFC2553 name / address resolution API */ #ifndef NI_NUMERICHOST # define NI_NUMERICHOST (1) #endif #ifndef NI_NAMEREQD # define NI_NAMEREQD (1<<1) #endif #ifndef NI_NUMERICSERV # define NI_NUMERICSERV (1<<2) #endif #ifndef AI_PASSIVE # define AI_PASSIVE (1) #endif #ifndef AI_CANONNAME # define AI_CANONNAME (1<<1) #endif #ifndef AI_NUMERICHOST # define AI_NUMERICHOST (1<<2) #endif #ifndef NI_MAXSERV # define NI_MAXSERV 32 #endif /* !NI_MAXSERV */ #ifndef NI_MAXHOST # define NI_MAXHOST 1025 #endif /* !NI_MAXHOST */ #ifndef EAI_NODATA # define EAI_NODATA (INT_MAX - 1) #endif #ifndef EAI_MEMORY # define EAI_MEMORY (INT_MAX - 2) #endif #ifndef EAI_NONAME # define EAI_NONAME (INT_MAX - 3) #endif #ifndef EAI_SYSTEM # define EAI_SYSTEM (INT_MAX - 4) #endif #ifndef EAI_FAMILY # define EAI_FAMILY (INT_MAX - 5) #endif #ifndef EAI_SERVICE # define EAI_SERVICE -8 /* SERVICE not supported for `ai_socktype'. */ #endif #ifndef HAVE_STRUCT_ADDRINFO struct addrinfo { int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ size_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for hostname */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ }; #endif /* !HAVE_STRUCT_ADDRINFO */ #ifndef HAVE_GETADDRINFO #ifdef getaddrinfo # undef getaddrinfo #endif #define getaddrinfo(a,b,c,d) (fake_getaddrinfo(a,b,c,d)) int getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); #endif /* !HAVE_GETADDRINFO */ #ifndef HAVE_GAI_STRERROR #define gai_strerror(a) (fake_gai_strerror(a)) const char *gai_strerror(int); #endif /* !HAVE_GAI_STRERROR */ #ifndef HAVE_FREEADDRINFO #define freeaddrinfo(a) (fake_freeaddrinfo(a)) void freeaddrinfo(struct addrinfo *); #endif /* !HAVE_FREEADDRINFO */ #ifndef HAVE_GETNAMEINFO #define getnameinfo(a,b,c,d,e,f,g) (fake_getnameinfo(a,b,c,d,e,f,g)) int getnameinfo(const struct sockaddr *, size_t, char *, size_t, char *, size_t, int); #endif /* !HAVE_GETNAMEINFO */ #endif /* !_FAKE_RFC2553_H */ tcl8.6.5/compat/float.h0000644000175000017500000000100612663653206014324 0ustar sergeisergei/* * float.h -- * * This is a dummy header file to #include in Tcl when there * is no float.h in /usr/include. Right now this file is empty: * Tcl contains #ifdefs to deal with the lack of definitions; * all it needs is for the #include statement to work. * * Copyright (c) 1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ tcl8.6.5/compat/license.terms0000644000175000017500000000431712663660066015556 0ustar sergeisergeiThis software is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. tcl8.6.5/compat/stdlib.h0000644000175000017500000000261412663653206014506 0ustar sergeisergei/* * stdlib.h -- * * Declares facilities exported by the "stdlib" portion of the C library. * This file isn't complete in the ANSI-C sense; it only declares things * that are needed by Tcl. This file is needed even on many systems with * their own stdlib.h (e.g. SunOS) because not all stdlib.h files declare * all the procedures needed here (such as strtod). * * Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _STDLIB #define _STDLIB extern void abort(void); extern double atof(const char *string); extern int atoi(const char *string); extern long atol(const char *string); extern char * calloc(unsigned int numElements, unsigned int size); extern void exit(int status); extern int free(char *blockPtr); extern char * getenv(const char *name); extern char * malloc(unsigned int numBytes); extern void qsort(void *base, int n, int size, int (*compar)( const void *element1, const void *element2)); extern char * realloc(char *ptr, unsigned int numBytes); extern double strtod(const char *string, char **endPtr); extern long strtol(const char *string, char **endPtr, int base); extern unsigned long strtoul(const char *string, char **endPtr, int base); #endif /* _STDLIB */ tcl8.6.5/compat/fixstrtod.c0000644000175000017500000000150012663660064015237 0ustar sergeisergei/* * fixstrtod.c -- * * Source code for the "fixstrtod" procedure. This procedure is * used in place of strtod under Solaris 2.4, in order to fix * a bug where the "end" pointer gets set incorrectly. * * Copyright (c) 1995 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include #undef strtod /* * Declare strtod explicitly rather than including stdlib.h, since in * somes systems (e.g. SunOS 4.1.4) stdlib.h doesn't declare strtod. */ extern double strtod(char *, char **); double fixstrtod( char *string, char **endPtr) { double d; d = strtod(string, endPtr); if ((endPtr != NULL) && (*endPtr != string) && ((*endPtr)[-1] == 0)) { *endPtr -= 1; } return d; } tcl8.6.5/compat/dlfcn.h0000644000175000017500000000301512663660064014307 0ustar sergeisergei/* * dlfcn.h -- * * This file provides a replacement for the header file "dlfcn.h" * on systems where dlfcn.h is missing. It's primary use is for * AIX, where Tcl emulates the dl library. * * This file is subject to the following copyright notice, which is * different from the notice used elsewhere in Tcl but rougly * equivalent in meaning. * * Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH * Not derived from licensed software. * * Permission is granted to freely use, copy, modify, and redistribute * this software, provided that the author is not construed to be liable * for any results of using the software, alterations are clearly marked * as such, and this notice is not modified. */ /* * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH * 30159 Hannover, Germany */ #ifndef __dlfcn_h__ #define __dlfcn_h__ #ifdef __cplusplus extern "C" { #endif /* * Mode flags for the dlopen routine. */ #define RTLD_LAZY 1 /* lazy function call binding */ #define RTLD_NOW 2 /* immediate function call binding */ #define RTLD_GLOBAL 0x100 /* allow symbols to be global */ /* * To be able to intialize, a library may provide a dl_info structure * that contains functions to be called to initialize and terminate. */ struct dl_info { void (*init) (void); void (*fini) (void); }; void *dlopen (const char *path, int mode); void *dlsym (void *handle, const char *symbol); char *dlerror (void); int dlclose (void *handle); #ifdef __cplusplus } #endif #endif /* __dlfcn_h__ */ tcl8.6.5/compat/strtol.c0000644000175000017500000000354212663660064014550 0ustar sergeisergei/* * strtol.c -- * * Source code for the "strtol" library procedure. * * Copyright (c) 1988 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* *---------------------------------------------------------------------- * * strtol -- * * Convert an ASCII string into an integer. * * Results: * The return value is the integer equivalent of string. If endPtr is * non-NULL, then *endPtr is filled in with the character after the last * one that was part of the integer. If string doesn't contain a valid * integer value, then zero is returned and *endPtr is set to string. * * Side effects: * None. * *---------------------------------------------------------------------- */ long int strtol( const char *string, /* String of ASCII digits, possibly preceded * by white space. For bases greater than 10, * either lower- or upper-case digits may be * used. */ char **endPtr, /* Where to store address of terminating * character, or NULL. */ int base) /* Base for conversion. Must be less than 37. * If 0, then the base is chosen from the * leading characters of string: "0x" means * hex, "0" means octal, anything else means * decimal. */ { register const char *p; long result; /* * Skip any leading blanks. */ p = string; while (isspace(UCHAR(*p))) { p += 1; } /* * Check for a sign. */ if (*p == '-') { p += 1; result = -(strtoul(p, endPtr, base)); } else { if (*p == '+') { p += 1; } result = strtoul(p, endPtr, base); } if ((result == 0) && (endPtr != 0) && (*endPtr == p)) { *endPtr = (char *) string; } return result; } tcl8.6.5/compat/strstr.c0000644000175000017500000000305512663660064014561 0ustar sergeisergei/* * strstr.c -- * * Source code for the "strstr" library routine. * * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tcl.h" #ifndef NULL #define NULL 0 #endif /* *---------------------------------------------------------------------- * * strstr -- * * Locate the first instance of a substring in a string. * * Results: * If string contains substring, the return value is the location of the * first matching instance of substring in string. If string doesn't * contain substring, the return value is 0. Matching is done on an exact * character-for-character basis with no wildcards or special characters. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * strstr( register char *string, /* String to search. */ char *substring) /* Substring to try to find in string. */ { register char *a, *b; /* * First scan quickly through the two strings looking for a * single-character match. When it's found, then compare the rest of the * substring. */ b = substring; if (*b == 0) { return string; } for ( ; *string != 0; string += 1) { if (*string != *b) { continue; } a = string; while (1) { if (*b == 0) { return string; } if (*a++ != *b++) { break; } } b = substring; } return NULL; } tcl8.6.5/compat/opendir.c0000644000175000017500000000400712663660064014656 0ustar sergeisergei/* * opendir.c -- * * This file provides dirent-style directory-reading procedures for V7 * Unix systems that don't have such procedures. The origin of this code * is unclear, but it seems to have come originally from Larry Wall. */ #include "tclInt.h" #undef DIRSIZ #define DIRSIZ(dp) \ ((sizeof(struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) /* * open a directory. */ DIR * opendir( char *name) { register DIR *dirp; register int fd; char *myname; myname = ((*name == '\0') ? "." : name); if ((fd = open(myname, 0, 0)) == -1) { return NULL; } dirp = (DIR *) ckalloc(sizeof(DIR)); if (dirp == NULL) { /* unreachable? */ close(fd); return NULL; } dirp->dd_fd = fd; dirp->dd_loc = 0; return dirp; } /* * read an old style directory entry and present it as a new one */ #ifndef pyr #define ODIRSIZ 14 struct olddirect { ino_t od_ino; char od_name[ODIRSIZ]; }; #else /* a Pyramid in the ATT universe */ #define ODIRSIZ 248 struct olddirect { long od_ino; short od_fill1, od_fill2; char od_name[ODIRSIZ]; }; #endif /* * get next entry in a directory. */ struct dirent * readdir( register DIR *dirp) { register struct olddirect *dp; static struct dirent dir; for (;;) { if (dirp->dd_loc == 0) { dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); if (dirp->dd_size <= 0) { return NULL; } } if (dirp->dd_loc >= dirp->dd_size) { dirp->dd_loc = 0; continue; } dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc); dirp->dd_loc += sizeof(struct olddirect); if (dp->od_ino == 0) { continue; } dir.d_ino = dp->od_ino; strncpy(dir.d_name, dp->od_name, ODIRSIZ); dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */ dir.d_namlen = strlen(dir.d_name); dir.d_reclen = DIRSIZ(&dir); return &dir; } } /* * close a directory. */ void closedir( register DIR *dirp) { close(dirp->dd_fd); dirp->dd_fd = -1; dirp->dd_loc = 0; ckfree((char *) dirp); } tcl8.6.5/compat/mkstemp.c0000644000175000017500000000331012663660064014672 0ustar sergeisergei/* * mkstemp.c -- * * Source code for the "mkstemp" library routine. * * Copyright (c) 2009 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include #include #include #include /* *---------------------------------------------------------------------- * * mkstemp -- * * Create an open temporary file from a template. * * Results: * A file descriptor, or -1 (with errno set) in the case of an error. * * Side effects: * The template is updated to contain the real filename. * *---------------------------------------------------------------------- */ int mkstemp( char *template) /* Template for filename. */ { static const char alphanumerics[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; register char *a, *b; int fd, count, alphanumericsLen = strlen(alphanumerics); /* == 62 */ a = template + strlen(template); while (a > template && *(a-1) == 'X') { a--; } if (a == template) { errno = ENOENT; return -1; } /* * We'll only try up to 10 times; after that, we're suffering from enemy * action and should let the caller know. */ count = 10; do { /* * Replace the X's in the original template with random alphanumeric * digits. */ for (b=a ; *b ; b++) { float r = rand() / ((float) RAND_MAX); *b = alphanumerics[(int)(r * alphanumericsLen)]; } /* * Template is now realized; try to open (with correct options). */ fd = open(template, O_RDWR|O_CREAT|O_EXCL, 0600); } while (fd == -1 && errno == EEXIST && --count > 0); return fd; } tcl8.6.5/compat/string.h0000644000175000017500000000411112663660064014525 0ustar sergeisergei/* * string.h -- * * Declarations of ANSI C library procedures for string handling. * * Copyright (c) 1991-1993 The Regents of the University of California. * Copyright (c) 1994-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. */ #ifndef _STRING #define _STRING /* * The following #include is needed to define size_t. (This used to include * sys/stdtypes.h but that doesn't exist on older versions of SunOS, e.g. * 4.0.2, so I'm trying sys/types.h now.... hopefully it exists everywhere) */ #include #ifdef __APPLE__ extern void * memchr(const void *s, int c, size_t n); #else extern char * memchr(const void *s, int c, size_t n); #endif extern int memcmp(const void *s1, const void *s2, size_t n); extern char * memcpy(void *t, const void *f, size_t n); #ifdef NO_MEMMOVE #define memmove(d,s,n) (bcopy((s), (d), (n))) #else extern char * memmove(void *t, const void *f, size_t n); #endif extern char * memset(void *s, int c, size_t n); extern int strcasecmp(const char *s1, const char *s2); extern char * strcat(char *dst, const char *src); extern char * strchr(const char *string, int c); extern int strcmp(const char *s1, const char *s2); extern char * strcpy(char *dst, const char *src); extern size_t strcspn(const char *string, const char *chars); extern char * strdup(const char *string); extern char * strerror(int error); extern size_t strlen(const char *string); extern int strncasecmp(const char *s1, const char *s2, size_t n); extern char * strncat(char *dst, const char *src, size_t numChars); extern int strncmp(const char *s1, const char *s2, size_t nChars); extern char * strncpy(char *dst, const char *src, size_t numChars); extern char * strpbrk(const char *string, const char *chars); extern char * strrchr(const char *string, int c); extern size_t strspn(const char *string, const char *chars); extern char * strstr(const char *string, const char *substring); extern char * strtok(char *s, const char *delim); #endif /* _STRING */ tcl8.6.5/compat/gettod.c0000644000175000017500000000106212663660064014502 0ustar sergeisergei/* * gettod.c -- * * This file provides the gettimeofday function on systems * that only have the System V ftime function. * * Copyright (c) 1995 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclPort.h" #include #undef timezone int gettimeofday( struct timeval *tp, struct timezone *tz) { struct timeb t; ftime(&t); tp->tv_sec = t.time; tp->tv_usec = t. millitm * 1000; return 0; } tcl8.6.5/compat/strtod.c0000644000175000017500000001326012663660064014536 0ustar sergeisergei/* * strtod.c -- * * Source code for the "strtod" library procedure. * * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef NULL #define NULL 0 #endif static const int maxExponent = 511; /* Largest possible base 10 exponent. Any * exponent larger than this will already * produce underflow or overflow, so there's * no need to worry about additional digits. */ static const double powersOf10[] = { /* Table giving binary powers of 10. Entry */ 10., /* is 10^2^i. Used to convert decimal */ 100., /* exponents into floating-point numbers. */ 1.0e4, 1.0e8, 1.0e16, 1.0e32, 1.0e64, 1.0e128, 1.0e256 }; /* *---------------------------------------------------------------------- * * strtod -- * * This procedure converts a floating-point number from an ASCII * decimal representation to internal double-precision format. * * Results: * The return value is the double-precision floating-point * representation of the characters in string. If endPtr isn't * NULL, then *endPtr is filled in with the address of the * next character after the last one that was part of the * floating-point number. * * Side effects: * None. * *---------------------------------------------------------------------- */ double strtod( const char *string, /* A decimal ASCII floating-point number, * optionally preceded by white space. Must * have form "-I.FE-X", where I is the integer * part of the mantissa, F is the fractional * part of the mantissa, and X is the * exponent. Either of the signs may be "+", * "-", or omitted. Either I or F may be * omitted, or both. The decimal point isn't * necessary unless F is present. The "E" may * actually be an "e". E and X may both be * omitted (but not just one). */ char **endPtr) /* If non-NULL, store terminating character's * address here. */ { int sign, expSign = FALSE; double fraction, dblExp; const double *d; register const char *p; register int c; int exp = 0; /* Exponent read from "EX" field. */ int fracExp = 0; /* Exponent that derives from the fractional * part. Under normal circumstatnces, it is * the negative of the number of digits in F. * However, if I is very long, the last digits * of I get dropped (otherwise a long I with a * large negative exponent could cause an * unnecessary overflow on I alone). In this * case, fracExp is incremented one for each * dropped digit. */ int mantSize; /* Number of digits in mantissa. */ int decPt; /* Number of mantissa digits BEFORE decimal * point. */ const char *pExp; /* Temporarily holds location of exponent in * string. */ /* * Strip off leading blanks and check for a sign. */ p = string; while (isspace(UCHAR(*p))) { p += 1; } if (*p == '-') { sign = TRUE; p += 1; } else { if (*p == '+') { p += 1; } sign = FALSE; } /* * Count the number of digits in the mantissa (including the decimal * point), and also locate the decimal point. */ decPt = -1; for (mantSize = 0; ; mantSize += 1) { c = *p; if (!isdigit(c)) { if ((c != '.') || (decPt >= 0)) { break; } decPt = mantSize; } p += 1; } /* * Now suck up the digits in the mantissa. Use two integers to collect 9 * digits each (this is faster than using floating-point). If the mantissa * has more than 18 digits, ignore the extras, since they can't affect the * value anyway. */ pExp = p; p -= mantSize; if (decPt < 0) { decPt = mantSize; } else { mantSize -= 1; /* One of the digits was the point. */ } if (mantSize > 18) { fracExp = decPt - 18; mantSize = 18; } else { fracExp = decPt - mantSize; } if (mantSize == 0) { fraction = 0.0; p = string; goto done; } else { int frac1, frac2; frac1 = 0; for ( ; mantSize > 9; mantSize -= 1) { c = *p; p += 1; if (c == '.') { c = *p; p += 1; } frac1 = 10*frac1 + (c - '0'); } frac2 = 0; for (; mantSize > 0; mantSize -= 1) { c = *p; p += 1; if (c == '.') { c = *p; p += 1; } frac2 = 10*frac2 + (c - '0'); } fraction = (1.0e9 * frac1) + frac2; } /* * Skim off the exponent. */ p = pExp; if ((*p == 'E') || (*p == 'e')) { p += 1; if (*p == '-') { expSign = TRUE; p += 1; } else { if (*p == '+') { p += 1; } expSign = FALSE; } if (!isdigit(UCHAR(*p))) { p = pExp; goto done; } while (isdigit(UCHAR(*p))) { exp = exp * 10 + (*p - '0'); p += 1; } } if (expSign) { exp = fracExp - exp; } else { exp = fracExp + exp; } /* * Generate a floating-point number that represents the exponent. Do this * by processing the exponent one bit at a time to combine many powers of * 2 of 10. Then combine the exponent with the fraction. */ if (exp < 0) { expSign = TRUE; exp = -exp; } else { expSign = FALSE; } if (exp > maxExponent) { exp = maxExponent; errno = ERANGE; } dblExp = 1.0; for (d = powersOf10; exp != 0; exp >>= 1, ++d) { if (exp & 01) { dblExp *= *d; } } if (expSign) { fraction /= dblExp; } else { fraction *= dblExp; } done: if (endPtr != NULL) { *endPtr = (char *) p; } if (sign) { return -fraction; } return fraction; } tcl8.6.5/compat/strncasecmp.c0000644000175000017500000001005312663660064015536 0ustar sergeisergei/* * strncasecmp.c -- * * Source code for the "strncasecmp" library routine. * * Copyright (c) 1988-1993 The Regents of the University of California. * 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. */ #include "tclPort.h" /* * This array is designed for mapping upper and lower case letter together for * a case independent comparison. The mappings are based upon ASCII character * sequences. */ static const unsigned char charmap[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xe1, 0xe2, 0xe3, 0xe4, 0xc5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, }; /* * Here are the prototypes just in case they are not included in tclPort.h. */ int strncasecmp(const char *s1, const char *s2, size_t n); int strcasecmp(const char *s1, const char *s2); /* *---------------------------------------------------------------------- * * strcasecmp -- * * Compares two strings, ignoring case differences. * * Results: * Compares two null-terminated strings s1 and s2, returning -1, 0, or 1 * if s1 is lexicographically less than, equal to, or greater than s2. * * Side effects: * None. * *---------------------------------------------------------------------- */ int strcasecmp( const char *s1, /* First string. */ const char *s2) /* Second string. */ { unsigned char u1, u2; for ( ; ; s1++, s2++) { u1 = (unsigned char) *s1; u2 = (unsigned char) *s2; if ((u1 == '\0') || (charmap[u1] != charmap[u2])) { break; } } return charmap[u1] - charmap[u2]; } /* *---------------------------------------------------------------------- * * strncasecmp -- * * Compares two strings, ignoring case differences. * * Results: * Compares up to length chars of s1 and s2, returning -1, 0, or 1 if s1 * is lexicographically less than, equal to, or greater than s2 over * those characters. * * Side effects: * None. * *---------------------------------------------------------------------- */ int strncasecmp( const char *s1, /* First string. */ const char *s2, /* Second string. */ size_t length) /* Maximum number of characters to compare * (stop earlier if the end of either string * is reached). */ { unsigned char u1, u2; for (; length != 0; length--, s1++, s2++) { u1 = (unsigned char) *s1; u2 = (unsigned char) *s2; if (charmap[u1] != charmap[u2]) { return charmap[u1] - charmap[u2]; } if (u1 == '\0') { return 0; } } return 0; } tcl8.6.5/compat/dirent2.h0000644000175000017500000000237112663660064014574 0ustar sergeisergei/* * dirent.h -- * * Declarations of a library of directory-reading procedures * in the POSIX style ("struct dirent"). * * Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _DIRENT #define _DIRENT /* * Dirent structure, which holds information about a single * directory entry. */ #define MAXNAMLEN 255 #define DIRBLKSIZ 512 struct dirent { long d_ino; /* Inode number of entry */ short d_reclen; /* Length of this record */ short d_namlen; /* Length of string in d_name */ char d_name[MAXNAMLEN + 1]; /* Name must be no longer than this */ }; /* * State that keeps track of the reading of a directory (clients * should never look inside this structure; the fields should * only be accessed by the library procedures). */ typedef struct _dirdesc { int dd_fd; long dd_loc; long dd_size; char dd_buf[DIRBLKSIZ]; } DIR; /* * Procedures defined for reading directories: */ extern void closedir (DIR *dirp); extern DIR * opendir (char *name); extern struct dirent * readdir (DIR *dirp); #endif /* _DIRENT */ tcl8.6.5/compat/README0000644000175000017500000000057612663653206013741 0ustar sergeisergeiThis directory contains various header and code files that are used make Tcl compatible with various releases of UNIX and UNIX-like systems. Typically, files from this directory are used to compile Tcl when a system doesn't contain the corresponding files or when they are known to be incorrect. When the whole world becomes POSIX- compliant this directory should be unnecessary. tcl8.6.5/ChangeLog.20070000644000175000017500000067231112663653131013736 0ustar sergeisergei2007-12-31 Donal K. Fellows * doc/dict.n: Clarified meaning of dictionary values following discussion on comp.lang.tcl. 2007-12-26 Miguel Sofer * generic/tclCmdIL.c: More [lsort] data handling streamlines. The function MergeSort is gone, essentially inlined into Tcl_LsortObjCmd. It is not a straight inlining, two loops over all lists elements where merged in the process: the linked list elements are now built and merged into the temporary sublists in the same pass. 2007-12-25 Miguel Sofer * generic/tclCmdIL.c: More [lsort] data handling streamlines. Extra mem reqs of latest patches removed, restored to previous mem profile. Improved -unique handling, now eliminating repeated elems immediately instead of marking them to avoid reinsertion at the end. 2007-12-23 Jeff Hobbs * generic/tclCompCmds.c (TclCompileRegexpCmd): TCL_REG_NOSUB cannot * tests/regexp.test (regexp-22.2): be used because it * tests/regexpComp.test: [Bug 1857126] disallows backrefs. 2007-12-21 Miguel Sofer * generic/tclCmdIL.c: Speed patch for lsort. [Patch 1856994] 2007-12-21 Miguel Sofer * generic/tclCmdIL.c (Tcl_LsortObjCmd, Tcl_LsearchObjCmd): Avoid calling SelectObjFromSublist when there are no sublists. 2007-12-21 Miguel Sofer * generic/tclCmdIL.c (Tcl_LsortObjCmd): Preallocate a listObj of sufficient length for the sorted list instead of growing it. Second commit replaces calls to Tcl_ListObjAppenElement with direct access to the internal rep. 2007-12-19 Don Porter *** 8.5.0 TAGGED FOR RELEASE *** * changes: Updated for 8.5.0 release. 2007-12-19 Jeff Hobbs * generic/tclCompCmds.c (TclCompileSwitchCmd): update switch -regexp * tests/switch.test-14.*: compilation to pass the cflags to INST_REGEXP (changed on 12-07). Added tests for switch -regexp compilation (need more). [Bug 1854399] 2007-12-18 Don Porter * changes: Updated for 8.5.0 release. 2007-12-18 Donal K. Fellows * generic/regguts.h, generic/regc_color.c, generic/regc_nfa.c: Fixes for problems created when processing regular expressions that generate very large automata. An enormous number of thanks to Will Drewry , Tavis Ormandy , and Tom Lane from the Postgresql crowd for their help in tracking these problems down. [Bug 1810264] 2007-12-17 Don Porter * changes: Updated for 8.5.0 release. 2007-12-17 Miguel Sofer * generic/tclAlloc.c: * generic/tclExecute.c: * generic/tclInt.h: * generic/tclThreadAlloc.c: Fix alignment for memory returned by TclStackAlloc; insure that all memory allocators align to 16-byte boundaries on 64 bit platforms [Bug 1851832, 1851524] 2007-12-14 Jeff Hobbs * generic/tclIOUtil.c (FsAddMountsToGlobResult): fix the tail conversion of vfs mounts. [Bug 1602539] * win/README: updated notes 2007-12-14 Pat Thoyts * tests/winFile.test: Fixed tests for win2k with long machine name 2007-12-14 Pat Thoyts * win/nmakehlp.c: Support compilation with MSVC9 for AMD64. * win/makefile.vc: 2007-12-13 Donal K. Fellows * doc/trace.n: Clarified documentation of enterstep and leavestep traces, including adding example. [Bug 614282, 1701540, 1755984] 2007-12-12 Don Porter * doc/IntObj.3: Update docs for the Tcl_GetBignumAndClearObj() -> Tcl_TakeBignumFromObj() revision [TIP 298]. Added docs for the Tcl_InitBignumFromDouble() routine. [Bug 1446971] * changes: Updated for 8.5.0 release. 2007-12-10 Jeff Hobbs * generic/tclUtil.c (TclReToGlob): reduce escapes in conversion when not necessary * generic/tclInt.decls: move TclByteArrayMatch and TclReToGlob * generic/tclIntDecls.h: to tclInt.h from stubs. * generic/tclStubInit.c: Add flags var to TclByteArrayMatch for * generic/tclInt.h: future extensibility * generic/tcl.h: define TCL_MATCH_EXACT doc for Tcl_StringCaseMatch. * doc/StrMatch.3: It is compatible with existing usage. * generic/tclExecute.c (INST_STR_MATCH): flag for TclByteArrayMatch * generic/tclUtil.c (TclByteArrayMatch, TclStringMatchObj): * generic/tclRegexp.c (Tcl_RegExpExecObj): * generic/tclCmdMZ.c (StringMatchCmd): Use TclStringMatchObj * tests/string.test (11.9.* 11.10.*): more tests 2007-12-10 Joe English * doc/string.n, doc/UniCharIsAlpha.3: Fix markup errors. * doc/CrtCommand.3, doc/CrtMathFnc.3, doc/FileSystem.3, * doc/GetStdChan.3, doc/OpenFileChnl.3, doc/SetChanErr.3, * doc/eval.n, doc/filename.n: Consistency: Move "KEYWORDS" section after "SEE ALSO". 2007-12-10 Daniel Steffen * tools/genStubs.tcl: fix numerous issues handling 'macosx', 'aqua' or 'x11' entries interleaved with 'unix' entries [Bug 1834288]; add genStubs::export command [Tk FR 1716117]; cleanup formatting. * generic/tcl.decls: use new genstubs 'export' command to * generic/tclInt.decls: mark exported symbols not in stubs * generic/tclTomMath.decls: table [Tk FR 1716117]; cleanup formatting. * generic/tclDecls.h: regen with new genStubs.tcl. * generic/tclIntDecls.h: [Bug 1834288] * generic/tclIntPlatDecls.h: * generic/tclPlatDecls.h: * generic/tclStubInit.c: 2007-12-09 Jeff Hobbs * tests/io.test, tests/chanio.test (io-73.1): Make sure to invalidate * generic/tclIO.c (SetChannelFromAny): internal rep only after validating channel rep. [Bug 1847044] 2007-12-08 Donal K. Fellows * doc/expr.n, doc/mathop.n: Improved the documentation of the operators. [Bug 1823622] * generic/tclBasic.c (builtInCmds): Corrected list of hidden and * doc/interp.n (SAFE INTERPRETERS): exposed commands so that the documentation and reality now match. [Bug 1662436] 2007-12-07 Jeff Hobbs * generic/tclExecute.c (TclExecuteByteCode INST_REGEXP): * generic/tclCompCmds.c (TclCompileRegexpCmd): Pass correct RE compile flags at compile time, and use TCL_REG_NOSUB. * generic/tclIOCmd.c (FinalizeIOCmdTSD, Tcl_PutsObjCmd): cache stdout channel object for [puts $str] calls. 2007-12-06 Don Porter * README: Remove mention of dead comp.lang.tcl.announce newsgroup. [Bug 1846433] * unix/README: Mention the stub library created by `make` and warn about the effect of embedded paths in the installed binaries. Thanks to Larry Virden. [Bug 1794084] * doc/AddErrInfo.3: Documentation for the new routines in TIP 270. * doc/Interp.3: * doc/StringObj.3: 2007-12-06 Don Porter * doc/namespace.n: Documentation for zero-argument form of [namespace import] (TIP 261) [Bug 1596416] 2007-12-06 Jeff Hobbs * generic/tclInt.h: add TclGetChannelFromObj decl (TclMatchIsTrivial): simplify TclMatchIsTrivial to remove ] check. 2007-12-06 Donal K. Fellows * generic/tclBasic.c (Tcl_CreateInterp): Simplify the setting up of * generic/tclIOCmd.c (TclInitChanCmd): the [chan] ensemble. This * library/init.tcl: gets rid of quite a bit of code and makes it possible to understand the whole with less effort. * generic/tclCompCmds.c (TclCompileEnsemble): Ensure that the right number of tokens are copied. [Bug 1845320] * generic/tclNamesp.c (TclMakeEnsemble): Added missing release of a DString. [Bug 1845397] 2007-12-05 Jeff Hobbs * generic/tclIO.h: Create Tcl_Obj for Tcl channels to reduce * generic/tclIO.c: overhead in lookup by Tcl_GetChannel. New * generic/tclIOCmd.c: TclGetChannelFromObj for internal use. * generic/tclIO.c (WriteBytes, WriteChars): add opt check to avoid EOL translation when not linebuffered or using lf. [Bug 1845092] 2007-12-05 Miguel Sofer * tests/stack.test: made the tests for stack overflow not care about which mechanism caused the error (interp's recursion limit or C-stack depth detector). 2007-12-05 Jeff Hobbs * win/configure, win/tcl.m4 (LIBS_GUI): mingw needs -lole32 -loleaut32 but not msvc for Tk's [send]. [Bug 1844749] 2007-12-05 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LsearchObjCmd): Prevent shimmering crash when -exact and -integer/-real are mixed. [Bug 1844789] 2007-12-03 Donal K. Fellows * unix/tclUnixChan.c (CreateSocketAddress): Add extra #ifdef-fery to make code compile on BSD 5. [Bug 1618235, again] 2007-12-03 Don Porter * library/tcltest/tcltest.tcl: Bump tcltest to version 2.3.0 so that * library/tcltest/pkgIndex.tcl: we release a stable tcltest with a * unix/Makefile.in: stable Tcl. * win/Makefile.in: 2007-12-03 Jeff Hobbs * win/configure, win/tcl.m4 (LIBS_GUI): remove ole32.lib oleaut32.lib 2007-12-03 Donal K. Fellows * generic/tclCompCmds.c (TclCompileSwitchCmd): Adjusted the [switch] * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): command so that when passed two arguments, no check for options are performed. This is OK since in the two-arg case, detecting an option would definitely lead to a syntax error. [Patch 1836519] 2007-11-29 Jeff Hobbs * win/makefile.vc: add ws2_32.lib to baselibs * win/configure, win/tcl.m4: add ws2_32.lib / -lws2_32 to build. * win/tclWinSock.c: remove dyn loading of winsock, assume that it is always available now. 2007-11-29 Don Porter * generic/tclWinSock.c (InitializeHostName): Correct error in buffer length tracking. After gethostname() writes into a buffer, convert only the written string to internal encoding, not the whole buffer. 2007-11-28 Don Porter * generic/tclConfig.c: Corrected failure of the [::foo::pkgconfig] command to clean up registered configuration data when the query command is deleted from the interp. [Bug 983501] * generic/tclNamesp.c (Tcl_SetEnsembleMappingDict): Added checks that the dict value passed in is in the format required to make the internals of ensembles work. [Bug 1436096] * generic/tclIO.c: Simplify test and improve accuracy of error message in latest changes. 2007-11-28 Pat Thoyts * generic/tclIO.c: -eofchar must support no eofchar. 2007-11-27 Miguel Sofer * generic/tclBasic.c: remove unneeded call in Tcl_CreateInterp, add comments. 2007-11-27 Don Porter * win/tclWinSock.c: Add mising encoding conversion of the [info hostname] value from the system encoding to Tcl's internal encoding. * doc/chan.n: "Fix" the limitation on channel -eofchar * doc/fconfigure.n: values to single byte characters by * generic/tclIO.c: documenting it and making it fail loudly. * tests/chan.test: Thanks to Stuart Cassoff for contributing the fix. [Bug 800753] 2007-11-26 Miguel Sofer * generic/tclBasic.c: * generic/tclInt.h: * unix/tclUnixInit.c: * unix/tclUnixThrd.c: Fix stack checking via workaround for bug in glibc's pthread_attr_get_np, patch from [Bug 1815573]. Many thanks to Sergei Golovan (aka Teo) for detecting the bug and helping diagnose and develop the fix. 2007-11-24 Donal K. Fellows * generic/tclCompCmds.c (TclCompileDictAppendCmd): Fix bug in [dict append] compiler which caused strange stack corruption. [Bug 1837392] 2007-11-23 Andreas Kupries * generic/tclIORChan.c: Fixed a problem with reflected channels. 'chan postevent' is defined to work only from within the interpreter containing the handler command. Sensible, we want only handler commands to use it. It identifies the channel by handle. The channel moves to a different interpreter or thread. The interpreter containing the handler command doesn't know the channel any longer. 'chan postevent' fails, not finding the channel any longer. Uhm. Fixed by creating a second per-interpreter channel table, just for reflected channels, where each interpreter remembers for which reflected channels it has the handler command. This info does not move with the channel itself. The table is updated by 'chan create', and used by 'chan postevent'. * tests/ioCmd.test: Updated the testsuite. 2007-11-23 Jeff Hobbs * generic/tclVar.c (Tcl_ArrayObjCmd): handle the right data for * tests/var.test (var-14.2): [array names $var -glob $ptn] 2007-11-23 Donal K. Fellows * generic/tclCmdMZ.c (String*Cmd, TclInitStringCmd): Rebuilt [string] * generic/tclCompCmds.c (TclCompileString*Cmd): as an ensemble. 2007-11-22 Donal K. Fellows * generic/tclDictObj.c (Dict*Cmd,TclInitDictCmd): Rebuilt the [dict] * generic/tclCompCmds.c (TclCompileDict*Cmd): command as an ensemble. 2007-11-22 Donal K. Fellows * generic/tclCmdMZ.c (Tcl_StringObjCmd): Rewrote the [string] and * generic/tclDictObj.c (Tcl_DictObjCmd): [dict] implementations to be ready for conversion to ensembles. * tests/string.test (string-12.22): Flag shimmering bug found in [string range]. 2007-11-21 Donal K. Fellows * generic/tclCompCmds.c (TclCompileEnsemble): Rewrote the ensemble compiler to remove many of the limitations. Can now compile scripts that use unique prefixes of subcommands, and which have mappings of a command to multiple words (provided the first is a compilable command of course). 2007-11-21 Donal K. Fellows * generic/tclNamesp.c (TclMakeEnsemble): Factor out the code to set up a core ensemble from a table of information about subcommands, ready for reuse within the core. * generic/various: Start to return more useful Error codes, currently mainly on assorted lookup failures. 2007-11-20 Donal K. Fellows * generic/tclDictObj.c: Changed the underlying implementation of the hash table used in dictionaries to additionally keep all entries in the hash table in a linked list, which is only ever added to at the end. This makes iteration over all entries in the dictionary in key insertion order a trivial operation, and so cleans up a great deal of complexity relating to dictionary representation and stability of iteration order. ***POTENTIAL INCOMPATIBILITY*** For any code that depended on the (strange) old iteration order. * generic/tclConfig.c (QueryConfigObjCmd): Correct usage of Tcl_WrongNumArgs. 2007-11-19 Don Porter *** 8.5b3 TAGGED FOR RELEASE *** * README: Bump version number to 8.5b3. * generic/tcl.h: * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf (2.59) * win/configure: * changes: Updated for 8.5b3 release. 2007-11-19 Kevin Kenny * library/tzdata/Africa/Cairo: * library/tzdata/America/Campo_Grande: * library/tzdata/America/Caracas: * library/tzdata/America/Cuiaba: * library/tzdata/America/Havana: * library/tzdata/America/Sao_Paulo: * library/tzdata/Asia/Damascus: * library/tzdata/Asia/Gaza: * library/tzdata/Asia/Tehran: Olson's tzdata2007i imported. 2007-11-18 Daniel Steffen * generic/tclExecute.c (TclExecuteByteCode:INST_EXIST_*): Fix read traces not firing on non-existent array elements. [Bug 1833522] 2007-11-16 Donal K. Fellows * generic/tclCmdIL.c (TclInitInfoCmd): Rename the implementation commands for [info] to be something more "expected". * generic/tclCompCmds.c (TclCompileInfoExistsCmd): Compiler for the [info exists] subcommand. (TclCompileEnsemble): Cleaned up version of ensemble compiler that was in TclCompileInfoCmd, but which is now much more generally applicable. * generic/tclInt.h (ENSEMBLE_COMPILE): Added flag to allow for cleaner turning on and off of ensemble bytecode compilation. * generic/tclCompile.c (TclCompileScript): Add the cmdPtr to the list of arguments passed to command compilers. 2007-11-15 Don Porter * generic/regc_nfa.c: Fixed infinite loop in the regexp compiler. [Bug 1810038] * generic/regc_nfa.c: Corrected looping logic in fixempties() to avoid wasting time walking a list of dead states. [Bug 1832612] 2007-11-15 Donal K. Fellows * generic/tclNamesp.c (NamespaceEnsembleCmd): Must pass a non-NULL interp to Tcl_SetEnsemble* functions. * doc/re_syntax.n: Try to make this easier to read. It's still a very difficult manual page! * unix/tcl.m4 (SC_CONFIG_CFLAGS): Allow people to turn off the -rpath option to their linker if they so desire. This is a configuration only recommended for (some) vendors. Relates to [Patch 1231022]. 2007-11-15 Pat Thoyts * win/tclWin32Dll.c: Prefer UINT_PTR to DWORD_PTR when casting pointers to integer types for greater portability. [Bug 1831253] 2007-11-15 Daniel Steffen * macosx/Tcl.xcodeproj/project.pbxproj: add new chanio.test. * macosx/Tcl.xcode/project.pbxproj: 2007-11-14 Donal K. Fellows * generic/tclCompile.c (TclCompileScript): Ensure that we get our count in our INST_START_CMD calls right, even when there's a failure to compile a command directly. * generic/tclNamesp.c (Tcl_SetEnsembleSubcommandList) (Tcl_SetEnsembleMappingDict): Special code to make sure that * generic/tclCmdIL.c (TclInitInfoCmd): [info exists] is compiled right while not allowing changes to the ensemble to cause havok. * generic/tclCompCmds.c (TclCompileInfoCmd): Simple compiler for the [info] command that only handles [info exists]. * generic/tclExecute.c (TclExecuteByteCode:INST_EXIST_*): New instructions to allow the testing of whether a variable exists. 2007-11-14 Andreas Kupries * tests/chanio.test: New file. This is essentially a duplicate of 'io.test', with all channel commands converted to their 'chan xxx' notation. * tests/io.test: Fixed typo in test description. 2007-11-14 Donal K. Fellows * generic/regc*.c: Eliminate multi-char collating element code completely. Simplifies the code quite a bit. If people still want the full code, it will remain on the 8.4 branch. [Bug 1831425] 2007-11-13 Jeff Hobbs * generic/tclCompCmds.c (TclCompileRegexpCmd): clean up comments, only free dstring on OK from TclReToGlob. (TclCompileSwitchCmd): simplify TclReToGlob usage. 2007-11-14 Donal K. Fellows * generic/regc*.c: #ifdef/comment out the code that deals with multi-character collating elements, which have never been supported. Cuts the memory consumption of the RE compiler. [Bug 1831425] 2007-11-13 Donal K. Fellows * generic/tclCompCmds.c (TclCompileSwitchCmd, TclCompileRegexpCmd): Extend [switch] compiler to handle regular expressions as long as things are not too complex. Fix [regexp] compiler so that non-trivial literal regexps get fed to INST_REGEXP. * doc/mathop.n: Clarify definitions of some operations. 2007-11-13 Miguel Sofer * unix/tclUnixInit.c: the TCL_NO_STACK_CHECK was being incorrectly undefined here; this should be set (or not) in the compile options, it is used elsewhere and needs to be consistent. 2007-11-13 Pat Thoyts * unix/tcl.m4: Added autoconf goo to detect and make use of * unix/configure.in: getaddrinfo and friends. * unix/configure: (regenerated) 2007-11-13 Donal K. Fellows * unix/tclUnixCompat.c (TclpGetHostByName): The six-argument form of getaddressbyname_r() uses the fifth argument to indicate whether the lookup succeeded or not on at least one platform. [Bug 1618235] 2007-11-13 Don Porter * generic/regcomp.c: Convert optst() from expensive no-op to a cheap no-op. 2007-11-13 Donal K. Fellows * unix/tclUnixChan.c (CreateSocketAddress): Rewrote to use the thread-safe version of gethostbyname() by forward-porting the code used in 8.4, and added rudimentary support for getaddrinfo() (not enabled by default, as no autoconf-ery written). Part of fix for [Bug 1618235]. 2007-11-12 Jeff Hobbs * generic/tclGet.c (Tcl_Get, Tcl_GetInt): revert use of TclGet* macros due to compiler warning. These cases won't save time either. * generic/tclUtil.c (TclReToGlob): add more comments, set interp result if specified on error. 2007-11-12 Miguel Sofer * generic/tclBasic.c: New macro TclResetResult, new iPtr * generic/tclExecute.c: flag bit INTERP_RESULT_UNCLEAN: * generic/tclInt.h: shortcut for Tcl_ResetResult for the * generic/tclProc.c: "normal" case: TCL_OK, no return * generic/tclResult.c: options, no errorCode nor errorInfo, * generic/tclStubLib.c: return at normal level. [Patch * generic/tclUtil.c: 1830184] THIS PATCH WAS REVERTED: initial (mis)measurements overstated the perfomance wins, which turn out to be tiny. Not worth the complication. 2007-11-11 Jeff Hobbs * generic/tclCompCmds.c, generic/tclCompile.c, generic/tclCompile.h: * generic/tclExecute.c, generic/tclInt.decls, generic/tclIntDecls.h: * generic/tclRegexp.c, generic/tclRegexp.h: Add INST_REGEXP and fully * generic/tclStubInit.c, generic/tclUtil.c: compiled [regexp] for the * tests/regexpComp.test: [Bug 1830166] simple cases. Also added TclReToGlob function to convert RE to glob patterns and use these in the possible cases. 2007-11-11 Miguel Sofer * generic/tclResult.c (ResetObjResult): clarify the logic. * generic/tclBasic.c: Increased usage of macros to detect * generic/tclBinary.c: and take advantage of objTypes. Added * generic/tclClock.c: macros TclGet(Int|Long)FromObj, * generic/tclCmdAH.c: TclGetIntForIndexM & TclListObjLength, * generic/tclCmdIL.c: modified TclListObjGetElements. * generic/tclCmdMZ.c: * generic/tclCompCmds.c: The TclGetInt* macros are only a * generic/tclCompExpr.c: shortcut on platforms where 'long' is * generic/tclCompile.c: 'int'; it may be worthwhile to extend * generic/tclDictObj.c: their functionality to other cases. * generic/tclExecute.c: * generic/tclGet.c: As this patch touches many files it * generic/tclIO.c: has been recorded as [Patch 1830038] * generic/tclIOCmd.c: in order to facilitate reviewing. * generic/tclIOGT.c: * generic/tclIndexObj.c: * generic/tclInt.h: * generic/tclInterp.c: * generic/tclListObj.c: * generic/tclLiteral.c: * generic/tclNamesp.c: * generic/tclObj.c: * generic/tclParse.c: * generic/tclProc.c: * generic/tclRegexp.c: * generic/tclResult.c: * generic/tclScan.c: * generic/tclStringObj.c: * generic/tclUtil.c: * generic/tclVar.c: 2007-11-11 Daniel Steffen * unix/tclUnixTime.c (TclpWideClicksToNanoseconds): Fix issues with * generic/tclInt.h: int64_t overflow. * generic/tclBasic.c: Fix stack check failure case if stack grows up * unix/tclUnixInit.c: Simplify non-crosscompiled case. * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 2007-11-10 Miguel Sofer * generic/tclExecute.c: Fast path for INST_LIST_INDEX when the index is not a list. * generic/tclBasic.c: * unix/configure.in: * unix/tclUnixInit.c: Detect stack grwoth direction at compile time, only fall to runtime detection when crosscompiling. * unix/configure: autoconf 2.61 * generic/tclBasic.c: * generic/tclInt.h: * tests/interp.test: * unix/tclUnixInit.c: * win/tclWin32Dll.c: Restore simpler behaviour for stack checking, not adaptive to stack size changes after a thread is launched. Consensus is that "nobody does that", and so it is not worth the cost. Improved failure comments (mistachkin). 2007-11-10 Kevin Kenny * win/tclWin32Dll.c: Rewrote the Windows stack checking algorithm to use information from VirtualQuery to determine the bound of the stack. This change fixes a bug where the guard page of the stack was never restored after an overflow. It also eliminates a nasty piece of assembly code for structured exception handling on mingw. It introduces an assumption that the stack is a single memory arena returned from VirtualAlloc, but the code in MSVCRT makes the same assumption, so it should be fairly safe. 2007-11-10 Miguel Sofer * generic/tclBasic.c: * generic/tclInt.h: * unix/tclUnixInit.c: * unix/tclUnixPort.h: * win/tclWin32Dll.c: Modify the stack checking algorithm to recheck in case of failure. The working assumptions are now that (a) a thread's stack is never moved, and (b) a thread's stack can grow but not shrink. Port to windows - could be more efficient, but is already cheaper than it was. 2007-11-09 Miguel Sofer * generic/tclResult.c (ResetObjResult): new shortcut. * generic/tclAsync.c: * generic/tclBasic.c: * generic/tclExecute.c: * generic/tclInt.h: * generic/tclUnixInit.c: * generic/tclUnixPort.h: New fields in interp (ekeko!) to cache TSD data that is accessed at each command invocation, access macros to replace Tcl_AsyncReady and TclpCheckStackSpace by much faster variants [Patch 1829248] 2007-11-09 Jeff Hobbs * generic/tclInt.decls, generic/tclIntDecls.h: Use unsigned char for * generic/tclExecute.c, generic/tclUtil.c: TclByteArrayMatch and don't allow a nocase option. [Bug 1828296] For INST_STR_MATCH, ignore pattern type for TclByteArrayMatch case. * generic/tclBinary.c (Tcl_GetByteArrayFromObj): check type before func jump (perf). 2007-11-07 Jeff Hobbs * generic/tclStubInit.c: Added TclByteArrayMatch * generic/tclInt.decls: for efficient glob * generic/tclIntDecls.h: matching of ByteArray * generic/tclUtil.c (TclByteArrayMatch): Tcl_Objs, used in * generic/tclExecute.c (TclExecuteByteCode): INST_STR_MATCH. [Bug 1827996] * generic/tclIO.c (TclGetsObjBinary): Add an efficient binary path for [gets]. (DoWriteChars): Special case for 1-byte channel write. 2007-11-06 Miguel Sofer * generic/tclEncoding.c: Version of the embedded iso8859-1 encoding handler that is faster (functions to do the encoding know exactly what they're doing instead of pulling it from a table, though the table itself has to be retained for use by shift encodings that depend on iso8859-1). [Patch 1826906], committing for dkf. 2007-11-05 Andreas Kupries * generic/tclConfig.c (Tcl_RegisterConfig): Modified to not extend the config database if the encoding provided by the user is not found (venc == NULL). Scripts expecting the data will error out, however we neither crash nor provide bogus information. See [Bug 983509] for more discussion. * unix/tclUnixChan.c (TtyGetOptionProc): Accepted [Patch 1823576] provided by Stuart Cassof . The patch adds the necessary utf/external conversions to the handling of the arguments of option -xchar which will allow the use of \0 and similar characters. 2007-11-03 Miguel Sofer * generic/tclTest.c (TestSetCmd2): * generic/tclVar.c (TclObjLookupVarEx): * tests/set.test (set-5.1): Fix error branch when array name looks like array element (code not normally exercised). 2007-11-01 Donal K. Fellows * tools/tcltk-man2html.tcl (output-directive): Convert .DS/.DE pairs into tables since that is now all that they are used for. * doc/RegExp.3: Clarified documentation of RE flags. [Bug 1167840] * doc/refchan.n: Adjust internal name to be consistent with the file name for reduced user confusion. After comment by Dan Steffen. * generic/tclCmdMZ.c (Tcl_StringObjCmd, UniCharIsAscii): Remember, the NUL character is in ASCII too. [Bug 1808258] * doc/file.n: Clarified use of [file normalize]. [Bug 1185154] 2007-10-30 Don Porter * generic/tcl.h: Bump version number to 8.5b2.1 to distinguish * library/init.tcl: CVS development snapshots from the 8.5b2 * unix/configure.in: release. * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf (2.59) * win/configure: 2007-10-30 Donal K. Fellows * doc/expr.n, doc/mathfunc.n: Improve documentation to try to make clearer what is going on. * doc/interp.n: Shorten the basic descriptive text for some interp subcommands so Solaris nroff doesn't truncate them. [Bug 1822268] 2007-10-30 Donal K. Fellows * tools/tcltk-man2html.tcl (output-widget-options): Enhance the HTML generator so that it can produce multi-line option descriptions. 2007-10-28 Miguel Sofer * generic/tclUtil.c (Tcl_ConcatObj): optimise for some of the concatenees being empty objs. [Bug 1447328] 2007-10-28 Donal K. Fellows * generic/tclEncoding.c (TclInitEncodingSubsystem): Hard code the iso8859-1 encoding, as it's needed for more than just text (especially binary encodings...) Note that other encodings rely on the encoding being a table encoding (!) so we can't use more efficient encoding mapping functions. 2007-10-27 Donal K. Fellows * generic/regc_lex.c (lexescape): Close off one of the problems mentioned in [Bug 1810264]. 2007-10-27 Miguel Sofer * generic/tclNamesp.c (Tcl_FindCommand): insure that FQ command names are searched from the global namespace, ie, bypassing resolvers of the current namespace. [Bug 1114355] * doc/apply.n: fixed example [Bug 1811791] * doc/namespace.n: improved example [Bug 1788984] * doc/AddErrInfo.3: typo [Bug 1715087] * doc/CrtMathFnc.3: fixed Tcl_ListMathFuncs entry [Bug 1672219] * generic/tclCompile.h: * generic/tclInt.h: moved declaration of TclSetCmdNameObj from tclCompile.h to tclInt.h, reverting linker [Bug 1821159] caused by commit of 2007-10-11 (both I and gcc missed one dep). * generic/tclVar.c: try to preserve Tcl_Objs when doing variable lookups by name, partially addressing [Bug 1793601]. 2007-10-27 Donal K. Fellows * tools/tcltk-man2html.tcl (make-man-pages, htmlize-text) (process-text): Make the man->HTML scraper work better. 2007-10-26 Don Porter *** 8.5b2 TAGGED FOR RELEASE *** * changes: Updated for 8.5b2 release. * doc/*.1: Revert doc changes that broke * doc/*.3: `make html` so we can get the release * doc/*.n: out the door. * README: Bump version number to 8.5b2. * generic/tcl.h: * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf (2.59) * win/configure: 2007-10-26 Donal K. Fellows * tools/man2help2.tcl, tools/man2tcl.c: Made some of the tooling code to do man->other formats work better with current manpage set. Long way still to go. 2007-10-25 Zoran Vasiljevic * generic/tclThread.c: Added TclpMasterLock/Unlock arround calls to ForgetSyncObject in Tcl_MutexFinalize and Tcl_ConditionFinalize to prevent from garbling the internal lists that track sync objects. [Bug 1726873] 2007-10-24 Donal K. Fellows * tools/man2html2.tcl (macro): Added support for converting the new macros into HTML. * doc/man.macros (QW,PQ,QR,MT): New macros that hide the ugly mess needed to get proper GOOBE quoting in the manual pages. * doc/*.n, doc/*.3, doc/*.1: Lots of changes to take advantage of the new macros. 2007-10-20 Miguel Sofer * generic/tclCompile.c: Fix comments. * generic/tclExecute.c: 2007-10-18 David Gravereaux * tools/mkdepend.tcl: sort the dep list for a more humanly readable output. 2007-10-18 Don Porter * generic/tclResult.c (TclMergeReturnOptions): Make sure any -code values get pulled out of the dictionary, even if they are integer valued. * generic/tclCompCmds.c (TclCompileReturnCmd): Added code to more optimally compile [return -level 0 $x] to "push $x". [RFE 1794073] * compat/tmpnam.c (removed): The routine tmpnam() is no longer * unix/Makefile.in: called by Tcl source code. Remove autogoo the * unix/configure.in: supplied a replacement version on systems * win/tcl.dsp: where the routine was not available. [RFE 1811848] * unix/configure: autoconf-2.59 * generic/tcl.h: Remove TCL_LL_MODIFIER_SIZE. [RFE 1811837] 2007-10-17 David Gravereaux * tools/mkdepend.tcl: Improved defense from malformed object list infile. 2007-10-17 Donal K. Fellows * tools/man2html2.tcl: Convert .DS/.DE into HTML tables, not preformatted text. 2007-10-17 Kevin B. Kenny * generic/tclCompExpr.c: Moved a misplaced declaration that blocked compilation on VC++. * generic/tclExecute.c: Silenced several VC++ compiler warnings about converting 'long' to 'unsigned short'. 2007-10-16 David Gravereaux * win/makefile.vc: removed old dependency cruft that is no longer needed. 2007-10-15 Don Porter * generic/tclIOCmd.c: Revise [open] so that it interprets leading zero strings passed as the "permissions" argument as octal numbers, even if Tcl itself no longer parses integers in that way. * unix/tclUnixFCmd.c: Revise the "-permissions" [file attribute] so that it interprets leading zero strings as octal numbers, even if Tcl itself no longer parses integers in that way. * generic/tclCompExpr.c: Corrections to code that produces * generic/tclUtil.c: extended "bad octal" error messages. * tests/cmdAH.test: Test revisions so that tests pass whether or * tests/cmdIL.test: not Tcl parses leading zero strings as octal. * tests/compExpr-old.test: * tests/compExpr.test: * tests/compile.test: * tests/expr-old.test: * tests/expr.test: * tests/incr.test: * tests/io.test: * tests/lindex.test: * tests/link.test: * tests/mathop.test: * tests/parseExpr.test: * tests/set.test: * tests/string.test: * tests/stringComp.test: 2007-10-15 David Gravereaux * tools/mkdepend.tcl: Produces usable output. Include path problem * win/makefile.vc: fixed. Never fight city hall when it comes to levels of quoting issues. 2007-10-15 Miguel Sofer * generic/tclParse.c (Tcl_ParseBraces): fix for possible read after the end of buffer. [Bug 1813528] (Joe Mistachkin) 2007-10-14 David Gravereaux * tools/mkdepend.tcl (new): Initial stab at generating automatic * win/makefile.vc: dependencies. 2007-10-12 Pat Thoyts * win/makefile.vc: Mine all version information from headers. * win/rules.vc: Sync tcl and tk and bring extension versions * win/nmakehlp.c: closer together. Try and avoid using tclsh to do substitutions as we may cross compile. * win/coffbase.txt: Added offsets for snack dlls. 2007-10-11 David Gravereaux * win/makefile.vc: Fixed my bad spelling mistakes from years back. Dedependency, duh! Rather funny. 2007-10-11 Don Porter * generic/tclCmdMZ.c: Correct [string is (wide)integer] failure * tests/string.test: to report correct failindex values for non-decimal integer strings. [Bug 1805887] * compat/strtoll.c (removed): The routines strtoll() and strtoull() * compat/strtoull.c (removed): are no longer called by the Tcl source * generic/tcl.h: code. (Their functionality has been replaced * unix/Makefile.in: by TclParseNumber().) Remove outdated comments * unix/configure.in: and mountains of configury autogoo that * unix/tclUnixPort.h: allegedly support the mythical systems where * win/Makefile.in: these routines might not have been available. * win/makefile.bc: * win/makefile.vc: * win/tclWinPort.h: * unix/configure: autoconf-2.59 2007-10-11 Miguel Sofer * generic/tclObj.c: remove superfluous #include of tclCompile.h 2007-10-08 George Peter Staplin * doc/Hash.3: Correct the valid usage of the flags member for the Tcl_HashKeyType. It should be 0 or more of the flags mentioned. 2007-10-02 Jeff Hobbs * generic/tcl.h (Tcl_DecrRefCount): Update change from 2006-05-29 to make macro more warning-robust in unbraced if code. 2007-10-02 Don Porter [core-stabilizer-branch] * README: Bump version number to 8.5.0 * generic/tcl.h: * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * unix/configure: autoconf (2.59) * win/configure: 2007-10-02 Andreas Kupries * library/tclIndex: Added 'tcl::tm::path' to the tclIndex. This fixes [Bug 1806422] reported by Don Porter. 2007-09-25 Donal K. Fellows * generic/tclProc.c (Tcl_DisassembleObjCmd): Define a command, ::tcl::unsupported::disassemble, which can disassemble procedures, lambdas and general scripts. * generic/tclCompile.c (TclDisassembleByteCodeObj): Split apart the code to print disassemblies of bytecode so that there is reusable code that spits it out in a Tcl_Obj and then that code is used when doing tracing. 2007-09-20 Don Porter *** 8.5b1 TAGGED FOR RELEASE *** * changes: updates for 8.5b1 release. 2007-09-19 Don Porter * README: Bump version number to 8.5b1 * generic/tcl.h: Merge from core-stabilizer-branch. * library/init.tcl: Stabilizing toward 8.5b1 release now done on * tools/tcl.wse.in: the HEAD. core-stabilizer-branch is now * unix/configure.in: suspended. * unix/tcl.spec: * win/configure.in: 2007-09-19 Pat Thoyts * generic/tclStubLib.: Replaced isdigit with internal implementation. 2007-09-18 Don Porter * generic/tclStubLib.c: Remove C library calls from Tcl_InitStubs() so * win/makefile.vc: that we don't need the C library linked in to libtclStub. 2007-09-17 Pat Thoyts * win/makefile.vc: Add crt flags for tclStubLib now it uses C-library functions. 2007-09-17 Joe English * tcl.m4: use '${CC} -shared' instead of 'ld -Bshareable' to build shared libraries on current NetBSDs. [Bug 1749251] * unix/configure: regenerated (autoconf-2.59). 2007-09-17 Don Porter * unix/Makefile.in: Update `make dist` so that tclDTrace.d is included in the source code distribution. * generic/tcl.h: Revised Tcl_InitStubs() to restore Tcl 8.4 * generic/tclPkg.c: source compatibility with callers of * generic/tclStubLib.c: Tcl_InitStubs(interp, TCL_VERSION, 1). [Bug 1578344] 2007-09-17 Donal K. Fellows * generic/tclTrace.c (Tcl_TraceObjCmd, TraceExecutionObjCmd) (TraceCommandObjCmd, TraceVariableObjCmd): Generate literal values * generic/tclNamesp.c (NamespaceCodeCmd): more efficiently using * generic/tclFCmd.c (CopyRenameOneFile): TclNewLiteralStringObj * generic/tclEvent.c (TclSetBgErrorHandler): macro. 2007-09-15 Daniel Steffen * unix/tcl.m4: replace all direct references to compiler by ${CC} to enable CC overriding at configure & make time; run check for visibility "hidden" with all compilers; quoting fixes from TEA tcl.m4. (SunOS-5.1x): replace direct use of '/usr/ccs/bin/ld' in SHLIB_LD by 'cc' compiler driver. * unix/configure: autoconf-2.59 2007-09-14 Donal K. Fellows * generic/tclBasic.c (Tcl_CreateObjCommand): Only invalidate along the namespace path once; that is enough. [Bug 1519940] 2007-09-14 Daniel Steffen * generic/tclDTrace.d (new file): Add DTrace provider for Tcl; allows * generic/tclCompile.h: tracing of proc and command entry & * generic/tclBasic.c: return, bytecode execution, object * generic/tclExecute.c: allocation and more; with * generic/tclInt.h: essentially zero cost when tracing * generic/tclObj.c: is inactive; enable with * generic/tclProc.c: --enable-dtrace configure arg * unix/Makefile.in: (disabled by default, will only * unix/configure.in: enable if DTrace is present). [Patch 1793984] * macosx/GNUmakefile: Enable DTrace support. * macosx/Tcl-Common.xcconfig: * macosx/Tcl.xcodeproj/project.pbxproj: * generic/tclCmdIL.c: Factor out core of InfoFrameCmd() into internal TclInfoFrame() for use by DTrace probes. * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 2007-09-12 Don Porter * unix/Makefile.in: Perform missing updates of the tcltest Tcl * win/Makefile.in: Module installed filename that should have been part of the bump to tcltest 2.3b1. Thanks Larry Virden. 2007-09-12 Pat Thoyts * win/makefile.vc, win/rules.vc, win/nmakehlp.c: Use nmakehlp to substitute values for tclConfig.sh (helps cross-compiling). 2007-09-11 Don Porter * library/tcltest/tcltest.tcl: Accept underscores and colons in * library/tcltest/pkgIndex.tcl: constraint names. Properly handle constraint expressions that return non-numeric boolean results like "false". Bump to tcltest 2.3b1. [Bug 1772989; RFE 1071322] * tests/info.test: Disable fragile tests. * doc/package.n: Restored the functioning of [package require * generic/tclPkg.c: -exact] to be compatible with Tcl 8.4. [Bug * tests/pkg.test: 1578344] 2007-09-11 Miguel Sofer * generic/tclCompCmds.c (TclCompileDictCmd-update): * generic/tclCompile.c (tclInstructionTable): * generic/tclExecute.c (INST_DICT_UPDATE_END): fix stack management in compiled [dict update]. [Bug 1786481] ***POTENTIAL INCOMPATIBILITY*** Scripts that were precompiled on earlier versions of 8.5 and use [dict update] will crash. Workaround: recompile. 2007-09-11 Kevin B. Kenny * generic/tclExecute.c: Corrected an off-by-one error in the setting of MaxBaseWide for certain powers. [Bug 1767293 - problem reported in comments when bug was reopened] 2007-09-10 Jeff Hobbs * generic/tclLink.c (Tcl_UpdateLinkedVar): guard against var being unlinked. [Bug 1740631] (maros) 2007-09-10 Miguel Sofer * generic/tclCompile.c: fix tclInstructionTable entry for dictUpdateEnd * generic/tclExecute.c: remove unneeded setting of 'cleanup' variable before jumping to checkForCatch. 2007-09-10 Don Porter * doc/package.n: Restored the document parallel syntax of the * generic/tclPkg.c: [package present] and [package require] * tests/pkg.test: commands. [Bug 1723675] 2007-09-09 Don Porter * generic/tclInt.h: Removed the "nsName" Tcl_ObjType from the * generic/tclNamesp.c: registered set. Revised the management of the * generic/tclObj.c: intrep of that Tcl_ObjType. Revised the * tests/obj.test: TclGetNamespaceFromObj() routine to return TCL_ERROR and write a consistent error message when a namespace is not found. [Bug 1588842. Patch 1686862] ***POTENTIAL INCOMPATIBILITY*** For callers of Tcl_GetObjType() on the name "nsName". * generic/tclExecute.c: Update TclGetNamespaceFromObj() callers. * generic/tclProc.c: * tests/apply.test: Updated tests to expect new consistent * tests/namespace-old.test: error message when a namespace is not * tests/namespace.test: found. * tests/upvar.test: * generic/tclCompCmds.c: Use the new INST_REVERSE instruction * tests/mathop.test: to correct the compiled versions of math operator commands. [Bug 1724437] * generic/tclCompile.c: New bytecode instruction INST_REVERSE to * generic/tclCompile.h: reverse the order of N items at the top of * generic/tclExecute.c: stack. * generic/tclCompCmds.c (TclCompilePowOpCmd): Make a separate routine to compile ** to account for its different associativity. 2007-09-08 Miguel Sofer * generic/tclVar.c (Tcl_SetVar2, TclPtrSetVar): [Bug 1710710] fixed correctly, reverted fix of 2007-05-01. 2007-09-08 Donal K. Fellows * generic/tclDictObj.c (DictUpdateCmd, DictWithCmd): Plug a hole that * generic/tclExecute.c (TEBC,INST_DICT_UPDATE_END): allowed a careful * tests/dict.test (dict-21.16,21.17,22.11): attacker to craft a dict containing a recursive link to itself, violating one of Tcl's fundamental datatype assumptions and causing a stack crash when the dict was converted to a string. [Bug 1786481] 2007-09-07 Don Porter * generic/tclEvent.c ([::tcl::Bgerror]): Corrections to Tcl's * tests/event.test: default [interp bgerror] handler so that when it falls back to a hidden [bgerror] in a safe interp, it gets the right error context data. [Bug 1790274] 2007-09-07 Miguel Sofer * generic/tclProc.c (TclInitCompiledLocals): the refCount of resolved variables was being managed without checking if they were Var or VarInHash: itcl [Bug 1790184] 2007-09-06 Don Porter * generic/tclResult.c (Tcl_GetReturnOptions): Take care that a * tests/init.test: non-TCL_ERROR code doesn't cause existing -errorinfo, -errorcode, and -errorline entries to be omitted. * generic/tclEvent.c: With -errorInfo no longer lost, generate more complete ::errorInfo when calling [bgerror] after a non-TCL_ERROR background exception. 2007-09-06 Don Porter * generic/tclInterp.c (Tcl_Init): Removed constraint on ability to define a custom [tclInit] before calling Tcl_Init(). Until now the custom command had to be a proc. Now it can be any command. * generic/tclInt.decls: New internal routine TclBackgroundException() * generic/tclEvent.c: that for the first time permits non-TCL_ERROR exceptions to trigger [interp bgerror] handling. Closes a gap in TIP 221. When falling back to [bgerror] (which is designed only to handle TCL_ERROR), convert exceptions into errors complaining about the exception. * generic/tclInterp.c: Convert Tcl_BackgroundError() callers to call * generic/tclIO.c: TclBackgroundException(). * generic/tclIOCmd.c: * generic/tclTimer.c: * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: 2007-09-06 Daniel Steffen * macosx/Tcl.xcode/project.pbxproj: discontinue unmaintained support * macosx/Tcl.xcode/default.pbxuser: for Xcode 1.5; replace by Xcode2 project for use on Tiger (with Tcl.xcodeproj to be used on Leopard). * macosx/Tcl.xcodeproj/project.pbxproj: updates for Xcode 2.5 and 3.0. * macosx/Tcl.xcodeproj/default.pbxuser: * macosx/Tcl.xcode/project.pbxproj: * macosx/Tcl.xcode/default.pbxuser: * macosx/Tcl-Common.xcconfig: * macosx/README: document project changes. 2007-09-05 Don Porter * generic/tclBasic.c: Removed support for the unmaintained * generic/tclExecute.c: -DTCL_GENERIC_ONLY configuration. [Bug * unix/Makefile.in: 1264623] 2007-09-04 Don Porter * unix/Makefile.in: It's unreliable to count on the release manager to remember to `make genstubs` before `make dist`. Let the Makefile remember the dependency for us. * unix/Makefile.in: Corrections to `make dist` dependencies to be sure that macosx/configure gets generated whenever it does not exist. 2007-09-03 Kevin B, Kenny * library/tzdata/Africa/Cairo: * library/tzdata/America/Grand_Turk: * library/tzdata/America/Port-au-Prince: * library/tzdata/America/Indiana/Petersburg: * library/tzdata/America/Indiana/Tell_City: * library/tzdata/America/Indiana/Vincennes: * library/tzdata/Antarctica/McMurdo: * library/tzdata/Australia/Adelaide: * library/tzdata/Australia/Broken_Hill: * library/tzdata/Australia/Currie: * library/tzdata/Australia/Hobart: * library/tzdata/Australia/Lord_Howe: * library/tzdata/Australia/Melbourne: * library/tzdata/Australia/Sydney: * library/tzdata/Pacific/Auckland: * library/tzdata/Pacific/Chatham: Olson's tzdata2007g. * generic/tclListObj.c (TclLindexFlat): * tests/lindex.test (lindex-17.[01]): Added code to detect the error when a script does [lindex {} end foo]; an overaggressive optimisation caused this call to return an empty object rather than an error. 2007-09-03 Daniel Steffen * generic/tclObj.c (TclInitObjSubsystem): restore registration of the "wideInt" Tcl_ObjType for compatibility with 8.4 extensions that access the tclWideIntType Tcl_ObjType; add setFromAnyProc for tclWideIntType. 2007-09-02 Donal K. Fellows * doc/lsearch.n: Added note that order of results with the -all option is that of the input list. It always was, but this makes it crystal. 2007-08-30 Don Porter * generic/tclCompile.c: Added fflush() calls following all callers of * generic/tclExecute.c: TclPrintByteCodeObj() so that tcl_traceCompile output is less likely to get mangled when writes to stdout interleave with other code. 2007-08-28 Don Porter * generic/tclCompExpr.c: Use a table lookup in ParseLexeme() to determine lexemes with single-byte representations. * generic/tclBasic.c: Used unions to better clarify overloading of * generic/tclCompExpr.c: the fields of the OpCmdInfo and * generic/tclCompile.h: TclOpCmdClientData structs. 2007-08-27 Don Porter * generic/tclCompExpr.c: Call TclCompileSyntaxError() when expression syntax errors are found when compiling expressions. With this in place, convert TclCompileExpr to return void, since there's no longer any need to report TCL_ERROR. * generic/tclCompile.c: Update callers. * generic/tclExecute.c: * generic/tclCompCmds.c: New routine TclCompileSyntaxError() * generic/tclCompile.h: to directly compile bytecodes that report a * generic/tclCompile.c: syntax error, rather than (ab)use a call to TclCompileReturnCmd. Also, undo the most recent commit that papered over some issues with that (ab)use. New routine produces a new opcode INST_SYNTAX, which is a minor variation of INST_RETURN_IMM. Also a bit of constification. * generic/tclCompile.c: Move the deallocation of local LiteralTable * generic/tclCompExpr.c: entries into TclFreeCompileEnv(). * generic/tclExecute.c: Update callers. * generic/tclCompExpr.c: Force numeric and boolean literals in expressions to register with their intreps intact, even if that means overwriting existing intreps in already registered literals. 2007-08-25 Kevin B. Kenny * generic/tclExecute.c (TclExecuteByteCode): Added code to handle * tests/expr.test (expr-23.48-53) integer exponentiation that results in 32- and 64-bit integer results, avoiding calls to wide integer exponentiation routines in this common case. [Bug 1767293] * library/clock.tcl (ParseClockScanFormat): Modified code to allow * tests/clock.test (clock-60.*): case-insensitive matching of time zone and month names. [Bug 1781282] 2007-08-24 Don Porter * generic/tclCompExpr.c: Register literals found in expressions * tests/compExpr.test: to restore literal sharing. Preserve numeric intreps when literals are created for the first time. Correct memleak in ExecConstantExprTree() and add test for the leak. 2007-08-24 Miguel Sofer * generic/tclCompile.c: replaced copy loop that tripped some compilers with memmove. [Bug 1780870] 2007-08-23 Don Porter * library/init.tcl ([auto_load_index]): Delete stray "]" that created an expr syntax error (masked by a [catch]). * generic/tclCompCmds.c (TclCompileReturnCmd): Added crash protection to handle callers other than TclCompileScript() failing to meet the initialization assumptions of the TIP 280 code in CompileWord(). * generic/tclCompExpr.c: Suppress the attempt to convert to numeric when pre-compiling a constant expresion indicates an error. 2007-08-22 Miguel Sofer * generic/tclExecute.c (TEBC): disable the new shortcut to frequent INSTs for debug builds. REVERTED (collision with alternative fix) 2007-08-21 Don Porter * generic/tclMain.c: Corrected the logic of dropping the last * tests/main.test: newline from an interactively typed command. [Bug 1775878] 2007-08-21 Pat Thoyts * tests/thread.test: thread-4.4: clear ::errorInfo in the thread as a message is left here from init.tcl on windows due to no tcl_pkgPath. 2007-08-20 Miguel Sofer * generic/tclExecute.c (INST_SUB): fix usage of the new macro for overflow detection in sums, adapt to subtraction. Lengthy comment added. 2007-08-19 Donal K. Fellows * generic/tclExecute.c (Overflowing, TclIncrObj, TclExecuteByteCode): Encapsulate Miguel's last change in a more mnemonic macro. 2007-08-19 Miguel Sofer * generic/tclExecute.c: changed the check for overflow in sums, reducing objsize, number of branches and cache misses (according to cachegrind). Non-overflow for s=a+b: previous ((a >= 0 || b >= 0 || s < 0) && (s >= 0 || b < 0 || a < 0)) now (((a^s) >= 0) || ((a^b) < 0)) This expresses: "a and s have the same sign or else a and b have different sign". 2007-08-19 Donal K. Fellows * doc/interp.n (RESOURCE LIMITS): Added text to better explain why time limits are described using absolute times. [Bug 1752148] 2007-08-16 Miguel Sofer * generic/tclVar.c: improved localVarNameType caching to leverage the new availability of Tcl_Obj in variable names, avoiding string comparisons to verify that the cached value is usable. * generic/tclExecute.c: check the two most frequent instructions before the switch. Reduces both runtime and obj size a tiny bit. 2007-08-16 Don Porter * generic/tclCompExpr.c: Added a "constant" field to the OpNode struct (again "free" due to alignment requirements) to mark those subexpressions that are completely known at compile time. Enhanced CompileExprTree() and its callers to precompute these constant subexpressions at compile time. This resolves the issue raised in [Bug 1564517]. 2007-08-15 Donal K. Fellows * generic/tclIOUtil.c (TclGetOpenModeEx): Only set the O_APPEND flag * tests/ioUtil.test (ioUtil-4.1): on a channel for the 'a' mode and not for 'a+'. [Bug 1773127] 2007-08-14 Miguel Sofer * generic/tclExecute.c (INST_INVOKE*): peephole opt, do not get the interp's result if it will be pushed/popped. 2007-08-14 Don Porter * generic/tclBasic.c: Use fully qualified variable names for * tests/thread.test: ::errorInfo and ::errorCode so that string * tests/trace.test: reported to variable traces are fully qualified in agreement with Tcl 8.4 operations. 2007-08-14 Daniel Steffen * unix/tclLoadDyld.c: use dlfcn API on Mac OS X 10.4 and later; fix issues with loading from memory on intel and 64bit; add debug messages * tests/load.test: add test load-10.1 for loading from vfs. * unix/dltest/pkga.c: whitespace & comment cleanup, remove * unix/dltest/pkgb.c: unused pkgf.c. * unix/dltest/pkgc.c: * unix/dltest/pkge.c: * unix/dltest/pkgf.c (removed): * unix/dltest/pkgua.c: * macosx/Tcl.xcodeproj/project.pbxproj: 2007-08-13 Don Porter * generic/tclExecute.c: Provide DECACHE/CACHE protection to the * tests/trace.test: Tcl_LogCommandInfo() call. [Bug 1773040] 2007-08-12 Miguel Sofer * generic/tclCmdMZ.c (Tcl_SplitObjCmd): use TclNewStringObj macro instead of calling the function. * generic/tcl_Obj.c (TclAllocateFreeObjects): remove unneeded memset to 0 of all allocated objects. 2007-08-10 Miguel Sofer * generic/tclInt.h: remove redundant ops in TclNewStringObj macro. 2007-08-10 Miguel Sofer * generic/tclInt.h: fix the TclSetVarNamespaceVar macro, was causing a leak. 2007-08-10 Don Porter * generic/tclCompExpr.c: Revise CompileExprTree() to use the OpNode mark field scheme of tree traversal. This eliminates the need to use magic values in the left and right fields for that purpose. Also stop abusing the left field within ParseExpr() to store the number of arguments in a parsed function call. CompileExprTree() now determines that for itself at compile time. Then reorder code to eliminate duplication. 2007-08-09 Miguel Sofer * generic/tclProc.c (TclCreateProc): better comments on the required varflag values when loading precompiled procs. * generic/tclExecute.c (INST_STORE_ARRAY): * tests/trace.test (trace-2.6): whole array write traces on compiled local variables were not firing. [Bug 1770591] 2007-08-08 Jeff Hobbs * generic/tclProc.c (InitLocalCache): reference firstLocalPtr via procPtr. codePtr->procPtr == NULL exposed by tbcload. 2007-08-08 Don Porter * generic/tclExecute.c: Corrected failure to compile/link in the -DNO_WIDE_TYPE configuration. * generic/tclExecute.c: Corrected improper use of bignum arguments to * tests/expr.test: *SHIFT operations. [Bug 1770224] 2007-08-07 Miguel Sofer * generic/tclInt.h: remove comments refering to VAR_SCALAR, as that flag bit does not exist any longer. * generic/tclProc.c (InitCompiledLocals): removed optimisation for non-resolved case, as the function is never called in that case. Renamed the function to InitResolvedLocals to calrify the point. * generic/tclInt.decls: Exporting via stubs to help xotcl adapt to * generic/tclInt.h: VarReform. * generic/tclIntDecls.h: * generic/tclStubInit.c: 2007-08-07 Daniel Steffen * generic/tclEnv.c: improve environ handling on Mac OS X (adapted * unix/tclUnixPort.h: from Apple changes in Darwin tcl-64). * unix/Makefile.in: add support for compile flags specific to object files linked directly into executables. * unix/configure.in (Darwin): only use -seg1addr flag when prebinding; use -mdynamic-no-pic flag for object files linked directly into exes; support overriding TCL_PACKAGE_PATH/TCL_MODULE_PATH in environment. * unix/configure: autoconf-2.59 2007-08-06 Don Porter * tests/parseExpr.test: Update source file name of expr parser code. * generic/tclCompExpr.c: Added a "mark" field to the OpNode struct, which is used to guide tree traversal. This field costs nothing since alignement requirements used the memory already. Rewrote ConvertTreeToTokens() to use the new field, which permitted consolidation of utility routines CopyTokens() and GenerateTokensForLiteral(). 2007-08-06 Kevin B. Kenny * generic/tclGetDate.y: Added a cast to the definition of YYFREE to silence compiler warnings. * generic/tclDate.c: Regenerated * win/tclWinTest.c: Added a cast to GetSecurityDescriptorDacl call to silence compiler warnings. 2007-08-04 Miguel Sofer * generic/tclInt.decls: Exporting via stubs to help itcl adapt to * generic/tclInt.h: VarReform. Added localCache initialization * generic/tclIntDecls.h: to TclInitCompiledLocals (which only exists * generic/tclProc.c: for itcl). * generic/tclStubInit.c: * generic/tclVar.c: 2007-08-01 Donal K. Fellows * library/word.tcl: Rewrote for greater efficiency. [Bug 1764318] 2007-08-01 Pat Thoyts * generic/tclInt.h: Added a TclOffset macro ala Tk_Offset to * generic/tclVar.c: abstract out 'offsetof' which may not be * generic/tclExceute.c: defined (eg: msvc6). 2007-08-01 Miguel Sofer * generic/tclVar.c (TclCleanupVar): fix [Bug 1765225], thx Larry Virden. 2007-07-31 Miguel Sofer * doc/Hash.3: * generic/tclHash.c: * generic/tclObj.c: * generic/tclThreadStorage.c: (changes part of the patch below) Stop Tcl_CreateHashVar from resetting hPtr->clientData to NULL after calling the allocEntryProc for a custom table. * generic/tcl.h: * generic/tclBasic.c: * generic/tclCmdIL.c: * generic/tclCompCmds.c: * generic/tclCompile.c: * generic/tclCompile.h: * generic/tclExecute.c: * generic/tclHash.c: * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclLiteral.c: * generic/tclNamesp.c: * generic/tclObj.c: * generic/tclProc.c: * generic/tclThreadStorage.c: * generic/tclTrace.c: * generic/tclVar.c: VarReform [Patch 1750051] *** POTENTIAL INCOMPATIBILITY *** (tclInt.h and tclCompile.h) Extensions that access internals defined in tclInt.h and/or tclCompile.h may lose both binary and source compatibility. The relevant changes are: 1. 'struct Var' is completely changed, all acceses to its internals (either direct or via the TclSetVar* and TclIsVar* macros) will malfunction. Var flag values and semantics changed too. 2. 'struct Bytecode' has an additional field that has to be initialised to NULL 3. 'struct Namespace' is larger, as the varTable is now one pointer larger than a Tcl_HashTable. Direct access to its fields will malfunction. 4. 'struct CallFrame' grew one more field (the second such growth with respect to Tcl8.4). 5. API change for the functions TclFindCompiledLocal, TclDeleteVars and many internal functions in tclVar.c Additionally, direct access to variable hash tables via the standard Tcl_Hash* interface is to be considered as deprecated. It still works in the present version, but will be broken by further specialisation of these hash tables. This concerns especially the table of array elements in an array, as well as the varTable field in the Namespace struct. 2007-07-31 Miguel Sofer * unix/configure.in: allow use of 'inline' in Tcl sources. [Patch * win/configure.in: 1754128] * win/makefile.vc: Regen with autoconf 2.61 2007-07-31 Donal K. Fellows * unix/tclUnixInit.c (TclpSetVariables): Use the thread-safe getpwuid replacement to fill the tcl_platform(user) field as it is not subject to spoofing. [Bug 681877] * unix/tclUnixCompat.c: Simplify the #ifdef logic. * unix/tclUnixChan.c (FileWatchProc): Fix test failures. 2007-07-30 Donal K. Fellows * unix/tclUnixChan.c (SET_BITS, CLEAR_BITS): Added macros to make this file clearer. 2007-07-24 Miguel Sofer * generic/tclBasic.c (TEOvI, GetCommandSource): * generic/tclExecute.c (TEBC, TclGetSrcInfoForCmd): * generic/tclInt.h: * generic/tclTrace.c (TclCheck(Interp|Execution)Traces): Removed the need for TEBC to inspect the command before calling TEOvI, leveraging the TIP 280 infrastructure. Moved the generation of a correct nul-terminated command string away from the trace code, back into TEOvI/GetCommandSource. 2007-07-20 Andreas Kupries * library/platform/platform.tcl: Fixed bug in 'platform::patterns' * library/platform/pkgIndex.tcl: where identifiers not matching * unix/Makefile.in: the special linux and solaris forms would not * win/Makefile.in: get 'tcl' as an acceptable platform added to * doc/platform.n: the result. Bumped package to version 1.0.3 and * doc/platform_shell.n: updated documentation and Makefiles. Also fixed bad version info in the documentation of platform::shell. 2007-07-19 Don Porter * generic/tclParse.c: In contexts where interp and parsePtr->interp might be different, be sure to use the latter for error reporting. Also pulled the interp argument back out of ParseTokens() since we already had a parsePtr->interp to work with. 2007-07-18 Don Porter * generic/tclCompExpr.c: Removed unused arguments and variables 2007-07-17 Don Porter * generic/tclCompExpr.c (ParseExpr): While adding comments to explain the operations of ParseExpr(), made significant revisions to the code so it would be easier to explain, and in the process made the code simpler and clearer as well. 2007-07-15 Don Porter * generic/tclCompExpr.c: More commentary. * tests/parseExpr.test: Several tests of syntax error messages to check that when expression substrings are truncated they leave visible the context relevant to the reported error. 2007-07-12 Don Porter * generic/tclCompExpr.c: Factored out, corrected, and commented common code for reporting syntax errors in LEAF elements. 2007-07-11 Miguel Sofer * generic/tclCompCmds.c (TclCompileWhileCmd): * generic/tclCompile.c (TclCompileScript): Corrected faulty avoidance of INST_START_CMD when the first opcode in a script is within a loop (as produced by 'while 1'), so that the corresponding command is properly counted. [Bug 1752146] 2007-07-11 Don Porter * generic/tclCompExpr.c: Added a "parseOnly" flag argument to ParseExpr() to indicate whether the caller is Tcl_ParseExpr(), with an end goal of filling a Tcl_Parse with Tcl_Tokens representing the parsed expression, or TclCompileExpr() with the goal of compiling and executing the expression. In the latter case, more aggressive conversion of QUOTED and BRACED lexeme to literals is done. In the former case, all such conversion is avoided, since Tcl_Token production would revert it anyway. This enables simplifications to the GenerateTokensForLiteral() routine as well. 2007-07-10 Don Porter * generic/tclCompExpr.c: Added a field for operator precedence to be stored directly in the parse tree. There's no memory cost to this addition, since that memory would have been lost to alignment issues anyway. Also, converted precedence definitions and lookup tables to use symbolic constants instead of raw number for improved readability, and continued extending/improving/correcting comments. Removed some unused counter variables. Renamed some variables for clarity and replaced some cryptic logic with more readable macros. 2007-07-09 Don Porter * generic/tclCompExpr.c: Revision so that the END lexeme never gets inserted into the parse tree. Later tree traversal never reaches it since its location in the tree is not variable. Starting and stopping with the START lexeme (node 0) is sufficient. Also finished lexeme code commentary. * generic/tclCompExpr.c: Added missing creation and return of the Tcl_Parse fields that indicate error conditions. [Bug 1749987] 2007-07-05 Don Porter * library/init.tcl (unknown): Corrected inconsistent error message in interactive [unknown] when empty command is invoked. [Bug 1743676] 2007-07-05 Miguel Sofer * generic/tclNamesp.c (SetNsNameFromAny): * generic/tclObj.c (SetCmdNameFromAny): Avoid unnecessary ckfree/ckalloc when the old structs can be reused. 2007-07-04 Miguel Sofer * generic/tclNamesp.c: Fix case where a FQ cmd or ns was being cached * generic/tclObj.c: in a different interp, tkcon. [Bug 1747512] 2007-07-03 Don Porter * generic/tclCompExpr.c: Revised #define values so that there is now more expansion room to define more BINARY operators. 2007-07-02 Donal K. Fellows * generic/tclHash.c (CompareStringKeys): Always use the strcmp() version; the operation is functionally equivalent, the speed is identical (up to measurement limitations), and yet the code is simpler. [FRQ 951168] 2007-07-02 Don Porter * generic/tcl.h: Removed TCL_PRESERVE_BINARY_COMPATIBILITY and * generic/tclHash.c: any code enabled when it is set to 0. We will * generic/tclStubInit.c: always want to preserve binary compat of the structs that appear in the interface through the 8.* series of releases, so it's pointless to drag around this never-enabled alternative. * generic/tclIO.c: Removed dead code. * unix/tclUnixChan.c: * generic/tclCompExpr.c: Removed dead code, old implementations * generic/tclEvent.c: of expr parsing and compiling, including the * generic/tclInt.h: routine TclFinalizeCompilation(). 2007-06-30 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LsortObjCmd): Plug a memory leak caused by a missing Tcl_DecrRefCount on an error path. [Bug 1717186] 2007-06-30 Zoran Vasiljevic * generic/tclThread.c: Prevent RemeberSyncObj() from growing the sync object lists by reusing already free'd slots, if possible. See discussion on Bug 1726873 for more information. 2007-06-29 Donal K. Fellows * doc/DictObj.3 (Tcl_DictObjDone): Improved documentation of this function to make it clearer how to use it. [Bug 1710795] 2007-06-29 Daniel Steffen * generic/tclAlloc.c: on Darwin, ensure memory allocated by * generic/tclThreadAlloc.c: the custom TclpAlloc()s is aligned to 16 byte boundaries (as is the case with the Darwin system malloc). * generic/tclGetDate.y: use ckalloc/ckfree instead of malloc/free. * generic/tclDate.c: bison 1.875e * generic/tclBasic.c (TclEvalEx): fix warnings. * macosx/Tcl.xcodeproj/project.pbxproj: better support for renamed tcl * macosx/Tcl.xcodeproj/default.pbxuser: source dir; add 10.5 SDK build * macosx/Tcl-Common.xcconfig: config; remove tclMathOp.c. * macosx/README: document Tcl.xcodeproj changes. 2007-06-28 Don Porter * generic/tclBasic.c: Removed dead code, including the * generic/tclExecute.c: entire file tclMathOp.c. * generic/tclInt.h: * generic/tclMathOp.c (removed): * generic/tclTestObj.c: * win/tclWinFile.c: * unix/Makefile.in: Updated to reflect deletion of tclMathOp.c. * win/Makefile.in: * win/makefile.bc: * win/makefile.vc: 2007-06-28 Pat Thoyts * generic/tclBasic.c: Silence constness warnings for TclStackFree * generic/tclCompCmds.c: when building with msvc. * generic/tclFCmd.c: * generic/tclIOCmd.c: * generic/tclTrace.c: 2007-06-28 Miguel Sofer * generic/tclVar.c (UnsetVarStruct): fix possible segfault. 2007-06-27 Don Porter * generic/tclTrace.c: Corrected broken trace reversal logic in * generic/tclTest.c: TclCheckInterpTraces that led to infinite loop * tests/trace.test: when multiple Tcl_CreateTrace traces were set and one of them did not fire due to level restrictions. [Bug 1743931] 2007-06-26 Don Porter * generic/tclBasic.c (TclEvalEx): Moved some arrays from the C stack to the Tcl stack. 2007-06-26 Miguel Sofer * generic/tclVar.c (UnsetVarStruct): more streamlining. 2007-06-25 Don Porter * generic/tclExecute.c: Safety checks to avoid crashes in the TclStack* routines when called with an incompletely initialized interp. [Bug 1743302] 2007-06-25 Miguel Sofer * generic/tclVar.c (UnsetVarStruct): fixing incomplete change, more streamlining. 2007-06-24 Miguel Sofer * generic/tclVar.c (TclDeleteCompiledLocalVars): removed inlining that ended up not really optimising (limited benchmarks). Now calling UnsetVarStruct (streamlined old code is #ifdef'ed out, in case better benchmarks do show a difference). * generic/tclVar.c (UnsetVarStruct): fixed a leak introduced in last commit. 2007-06-23 Miguel Sofer * generic/tclVar.c (UnsetVarStruct, TclDeleteVars): made the logic slightly clearer, eliminated some duplicated code. *** POTENTIAL INCOMPATIBILITY *** (tclInt.h and Var struct users) The core never builds VAR_LINK variable to have traces. Such a "monster", should one exist, will now have its unset traces called *before* it is unlinked. 2007-06-23 Daniel Steffen * macosx/tclMacOSXNotify.c (AtForkChild): don't call CoreFoundation APIs after fork() on systems where that would lead to an abort(). 2007-06-22 Don Porter * generic/tclExecute.c: Revised TclStackRealloc() signature to better * generic/tclInt.h: parallel (and fall back on) Tcl_Realloc. * generic/tclNamesp.c (TclResetShadowesCmdRefs): Replaced ckrealloc based allocations with TclStackRealloc allocations. * generic/tclCmdIL.c: More conversions to use TclStackAlloc. * generic/tclScan.c: 2007-06-21 Don Porter * generic/tclBasic.c: Move most instances of the Tcl_Parse struct * generic/tclCompExpr.c: off the C stack and onto the Tcl stack. This * generic/tclCompile.c: is a rather large struct (> 3kB). * generic/tclParse.c: 2007-06-21 Miguel Sofer * generic/tclBasic.c (TEOvI): Made sure that leave traces * generic/tclExecute.c (INST_INVOKE): that were created during * tests/trace.test (trace-36.2): execution of an originally untraced command do not fire [Bug 1740962], partial fix. 2007-06-21 Donal K. Fellows * generic/tcl.h, generic/tclCompile.h, generic/tclCompile.c: Remove references in comments to obsolete {expand} notation. [Bug 1740859] 2007-06-20 Miguel Sofer * generic/tclVar.c: streamline namespace vars deletion: only compute the variable's full name if the variable is traced. 2007-06-20 Don Porter * generic/tclInt.decls: Revised the interfaces of the routines * generic/tclExecute.c: TclStackAlloc and TclStackFree to make them easier for callers to use (or more precisely, harder to misuse). TclStackFree now takes a (void *) argument which is the pointer intended to be freed. TclStackFree will panic if that's not actually the memory the call will free. TSA/TSF also now tolerate receiving (interp == NULL), in which case they simply fall back to be calls to Tcl_Alloc/Tcl_Free. * generic/tclIntDecls.h: make genstubs * generic/tclBasic.c: Updated callers * generic/tclCmdAH.c: * generic/tclCmdIL.c: * generic/tclCompCmds.c: * generic/tclCompExpr.c: * generic/tclCompile.c: * generic/tclFCmd.c: * generic/tclFileName.c: * generic/tclIOCmd.c: * generic/tclIndexObj.c: * generic/tclInterp.c: * generic/tclNamesp.c: * generic/tclProc.c: * generic/tclTrace.c: * unix/tclUnixPipe.c: 2007-06-20 Jeff Hobbs * tools/tcltk-man2html.tcl: revamp of html doc output to use CSS, standardized headers, subheaders, dictionary sorting of names. 2007-06-18 Jeff Hobbs * tools/tcltk-man2html.tcl: clean up copyright merging and output. clean up coding constructs. 2007-06-18 Miguel Sofer * generic/tclCmdIL.c (InfoFrameCmd): * generic/tclCmdMZ.c (Tcl_SwitchObjCmd): * generic/tclCompile.c (TclInitCompileEnv): * generic/tclProc.c (Tcl_ProcObjCmd, SetLambdaFromAny): Moved the CmdFrame off the C stack and onto the Tcl stack. * generic/tclExecute.c (TEBC): Moved the CmdFrame off the C stack and onto the Tcl stack, between the catch and the execution stacks 2007-06-18 Don Porter * generic/tclBasic.c (TclEvalEx,TclEvalObjEx): Moved the CmdFrame off the C stack and onto the Tcl stack. 2007-06-17 Donal K. Fellows * generic/tclProc.c (TclObjInterpProcCore): Minor fixes to make * generic/tclExecute.c (TclExecuteByteCode): compilation debugging builds work again. [Bug 1738542] 2007-06-16 Donal K. Fellows * generic/tclProc.c (TclObjInterpProcCore): Use switch instead of a chain of if's for a modest performance gain and a little more clarity. 2007-06-15 Miguel Sofer * generic/tclCompCmds.c: Simplified [variable] compiler and executor. * generic/tclExecute.c: Missed updates to "there is always a valid frame". * generic/tclCompile.c: reverted TclEvalObjvInternal and INST_INVOKE * generic/tclExecute.c: to essentially what they were previous to the * generic/tclBasic.c: commit of 2007-04-03 [Patch 1693802] and the subsequent optimisations, as they break the new trace tests described below. * generic/trace.test: added tests 36 to 38 for dynamic trace creation and addition. These tests expose a change in dynamics due to a recent round of optimisations. The "correct" behaviour is not described in docs nor TIP 62. 2007-06-14 Miguel Sofer * generic/tclInt.decls: Modif to the internals of TclObjInterpProc * generic/tclInt.h: to reduce stack consumption and improve task * generic/tclIntDecls.h: separation. Changes the interface of * generic/tclProc.c: TclObjInterpProcCore (patching TclOO simultaneously). * generic/tclProc.c (TclObjInterpProcCore): simplified obj management in wrongNumArgs calls. 2007-06-14 Don Porter * generic/tclCompile.c: SetByteCodeFromAny() can no longer return any * generic/tclExecute.c: code other than TCL_OK, so remove code that * generic/tclProc.c: formerly handled exceptional codes. 2007-06-13 Miguel Sofer * generic/tclExecute.c (TclCompEvalObj): missed update to "there is always a valid frame". * generic/tclProc.c (TclObjInterpProcCore): call TEBC directly instead of going through TclCompEvalObj - no need to check the compilation's freshness, this has already been done. This improves speed and should also provide some relief to [Bug 1066755]. 2007-06-12 Donal K. Fellows * generic/tclBasic.c (Tcl_CreateInterp): Turn the [info] command into * generic/tclCmdIL.c (TclInitInfoCmd): an ensemble, making it easier for third-party code to plug into. * generic/tclIndexObj.c (Tcl_WrongNumArgs): * generic/tclNamesp.c, generic/tclInt.h (tclEnsembleCmdType): Make Tcl_WrongNumArgs do replacement correctly with ensembles and other sorts of complex replacement strategies. 2007-06-11 Miguel Sofer * generic/tclExecute.c: comments added to explain iPtr->numLevels management. * generic/tclNamesp.c: tweaks to Tcl_GetCommandFromObj and * generic/tclObj.c: TclGetNamespaceFromObj; modified the usage of structs ResolvedCmdName and ResolvedNsname so that the field refNsPtr is NULL for fully qualified names. 2007-06-10 Miguel Sofer * generic/tclBasic.c: Further TEOvI split, creating a new * generic/tclCompile.h: TclEvalObjvKnownCommand() function to handle * generic/tclExecute.c: commands that are already known and are not traced. INST_INVOKE now calls into this function instead of inlining parts of TEOvI. Same perf, better isolation. ***POTENTIAL INCOMPAT*** There is a subtle issue with the timing of execution traces that is changed here - first change appeared in my commit of 2007-04-03 [Patch 1693802], which caused some divergence between compiled and non-compiled code. ***THIS CHANGE IS UNDER REVIEW*** 2007-06-10 Jeff Hobbs * README: updated links. [Bug 1715081] * generic/tclExecute.c (TclExecuteByteCode): restore support for INST_CALL_BUILTIN_FUNC1 and INST_CALL_FUNC1 bytecodes to support 8.4- precompiled sources (math functions). [Bug 1720895] 2007-06-10 Miguel Sofer * generic/tclInt.h: * generic/tclNamesp.c: * generic/tclObj.c: * generic/tclvar.c: new macros TclGetCurrentNamespace() and TclGetGlobalNamespace(); Tcl_GetCommandFromObj and TclGetNamespaceFromObj rewritten to make the logic clearer; slightly faster too. 2007-06-09 Miguel Sofer * generic/tclExecute.c (INST_INVOKE): isolated two vars to the small block where they are actually used. * generic/tclObj.c (Tcl_GetCommandFromObj): rewritten to make the logic clearer; slightly faster too. * generic/tclBasic.c: Split TEOv in two, by separating a processor for non-TCL_OK returns. Also split TEOvI in a full version that handles non-existing and traced commands, and a separate shorter version for the regular case. * generic/tclBasic.c: Moved the generation of command strings for * generic/tclTrace.c: traces: previously in Tcl_EvalObjv(), now in TclCheck[Interp|Execution]Traces(). Also insured that the strings are properly NUL terminated at the correct length. [Bug 1693986] ***POTENTIAL INCOMPATIBILITY in internal API*** The functions TclCheckInterpTraces() and TclCheckExecutionTraces() (in internal stubs) used to be noops if the command string was NULL, this is not true anymore: if the command string is NULL, they generate an appropriate string from (objc,objv) and use it to call the traces. The caller might as well not call them with a NULL string if he was expecting a noop. * generic/tclBasic.c: Extend usage of TclLimitReady() and * generic/tclExecute.c: (new) TclLimitExceeded() macros. * generic/tclInt.h: * generic/tclInterp.c: * generic/tclInt.h: New TclCleanupCommandMacro for core usage. * generic/tclBasic.c: * generic/tclExecute.c: * generic/tclObj.c: 2007-06-09 Daniel Steffen * macosx/Tcl.xcodeproj/project.pbxproj: add new Tclsh-Info.plist.in. 2007-06-08 Donal K. Fellows * generic/tclCmdMZ.c (Tcl_StringObjCmd): Changed [string first] and * doc/string.n: [string last] so that they have clearer descriptions for those people who know the adage about needles and haystacks. This follows suggestions on comp.lang.tcl... 2007-06-06 Miguel Sofer * generic/tclParse.c: fix for uninit read. [Bug 1732414] 2007-06-06 Daniel Steffen * macosx/Tcl.xcodeproj/project.pbxproj: add settings for Fix&Continue. * unix/configure.in (Darwin): add plist for tclsh; link the * unix/Makefile.in (Darwin): Tcl and tclsh plists into * macosx/Tclsh-Info.plist.in (new): their binaries in all cases. * macosx/Tcl-Common.xcconfig: * unix/tcl.m4 (Darwin): fix CF checks in fat 32&64bit builds. * unix/configure: autoconf-2.59 2007-06-05 Don Porter * generic/tclBasic.c: Added interp flag value ERR_LEGACY_COPY to * generic/tclInt.h: control the timing with which the global * generic/tclNamesp.c: variables ::errorCode and ::errorInfo get * generic/tclProc.c: updated after an error. This keeps more * generic/tclResult.c: precise compatibility with Tcl 8.4. * tests/result.test (result-6.2): [Bug 1649062] 2007-06-05 Miguel Sofer * generic/tclInt.h: * generic/tclExecute.c: Tcl-stack reform, [Patch 1701202] 2007-06-03 Daniel Steffen * unix/Makefile.in: add datarootdir to silence autoconf-2.6x warning. 2007-05-30 Don Porter * generic/tclBasic.c: Removed code that dealt with * generic/tclCompile.c: TCL_TOKEN_EXPAND_WORD tokens representing * generic/tclCompile.h: expanded literal words. These sections were mostly in place to enable [info frame] to discover line information in expanded literals. Since the parser now generates a token for each post-expansion word referring to the right location in the original script string, [info frame] gets all the data it needs. * generic/tclInt.h: Revised the parser so that it never produces * generic/tclParse.c: TCL_TOKEN_EXPAND_WORD tokens when parsing an * tests/parse.test: expanded literal word; that is, something like {*}{x y z}. Instead, generate the series of TCL_TOKEN_SIMPLE_WORD tokens to represent the words that expansion of the literal string produces. [RFE 1725186] 2007-05-29 Jeff Hobbs * unix/tclUnixThrd.c (Tcl_JoinThread): fix for 64-bit handling of pthread_join exit return code storage. [Bug 1712723] 2007-05-22 Don Porter [core-stabilizer-branch] * unix/configure: autoconf-2.59 (FC6 fork) * win/configure: * README: Bump version number to 8.5b1 * generic/tcl.h: * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: 2007-05-18 Don Porter * unix/configure: autoconf-2.59 (FC6 fork) * win/configure: * README: Bump version number to 8.5a7 * generic/tcl.h: * library/init.tcl: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/configure.in: * generic/tclParse.c: Disable and remove the ALLOW_EXPAND sections * tests/info.test: that continued to support the deprecated * tests/mathop.test: {expand} syntax. Updated the few remaining users of that syntax in the test suite. 2007-05-17 Donal K. Fellows * generic/tclExecute.c (TclLimitReady): Created a macro version of Tcl_LimitReady just for TEBC, to reduce the amount of times that the bytecode engine calls out to external functions on the critical path. * generic/tclInterp.c (Tcl_LimitReady): Added note to remind anyone doing maintenance that there is a macro version to update. 2007-05-17 Daniel Steffen * generic/tcl.decls: workaround 'make checkstubs' failures from tclStubLib.c MODULE_SCOPE revert. [Bug 1716117] 2007-05-16 Joe English * generic/tclStubLib.c: Change Tcl_InitStubs(), tclStubsPtr, and the auxilliary stubs table pointers back to public visibility. These symbols need to be exported so that stub-enabled extensions may be statically linked into an extended tclsh or Big Wish with a dynamically-linked libtcl. [Bug 1716117] 2007-05-15 Don Porter * win/configure: autoconf-2.59 (FC6 fork) * library/reg/pkgIndex.tcl: Bump to registry 1.2.1 to account for * win/configure.in: [Bug 1682211] fix. * win/makefile.bc: * win/tclWinReg.c: 2007-05-11 Pat Thoyts * generic/tclInt.h: Removed TclEvalObjEx and TclGetSrcInfoForPc from tclInt.h now they are in the internal stubs table. 2007-05-09 Don Porter * generic/tclInt.h: TclFinalizeThreadAlloc() is always defined, so make sure it is also always declared (with MODULE_SCOPE). 2007-05-09 Daniel Steffen * generic/tclInt.h: fix warning when building threaded with -DPURIFY. * macosx/Tcl.xcodeproj/project.pbxproj: add 'DebugUnthreaded' & * macosx/Tcl.xcodeproj/default.pbxuser: 'DebugLeaks' configs and env var settings needed to run the 'leaks' tool. 2007-05-07 Don Porter [Tcl Bug 1706140] * generic/tclLink.c (LinkTraceProc): Update Tcl_VarTraceProcs so * generic/tclNamesp.c (Error*Read): they call Tcl_InterpDeleted() * generic/tclTrace.c (Trace*Proc): for themselves, and do not * generic/tclUtil.c (TclPrecTraceProc): rely on (frequently buggy) setting of the TCL_INTERP_DESTROYED flag by the trace core. * generic/tclVar.c: Update callers of TclCallVarTraces to not pass in the TCL_INTERP_DESTROYED flag. Also apply filters so that public routines only pass documented flag values down to lower level routines * generic/tclTrace.c (TclCallVarTraces): The setting of the TCL_INTERP_DESTROYED flag is now done entirely within the TclCallVarTraces routine, the only place it can be done right. 2007-05-06 Donal K. Fellows * generic/tclInt.h (ExtraFrameInfo): Create a new mechanism for * generic/tclCmdIL.c (InfoFrameCmd): conveying what information needs to be added to the results of [info frame] to replace the hack that was there before. * generic/tclProc.c (Tcl_ApplyObjCmd): Use the new mechanism for the [apply] command, the only part of Tcl itself that needs it (so far). * generic/tclInt.decls (TclEvalObjEx, TclGetSrcInfoForPc): Expose these two functions through the internal stubs table, necessary for extensions that need to integrate deeply with TIP#280. 2007-05-05 Donal K. Fellows * win/tclWinFile.c (TclpGetUserHome): Squelch type-pun warnings in * win/tclWinInit.c (TclpSetVariables): Win-specific code not found * win/tclWinReg.c (AppendSystemError): during earlier work on Unix. 2007-05-04 Kevin B. Kenny * generic/tclIO.c (TclFinalizeIOSubsystem): Added an initializer to silence a spurious gcc warning about use of an uninitialized variable. * tests/encoding.test: Modified so that encoding tests happen in a private namespace, to avoid polluting the global one. This problem was discovered when running the test suite '-singleproc 1 -skip exec.test' because the 'path' variable in encoding.test conflicted with the one in io.test. * tests/io.test: Made more of the working variables private to the namespace. 2007-05-02 Kevin B. Kenny * generic/tclTest.c (SimpleMatchInDirectory): Corrected a refcount imbalance that affected the filesystem-[147]* tests in the test suite. Thanks to Don Porter for the patch. [Bug 1710707] * generic/tclPathObj.c (Tcl_FSJoinPath, Tcl_FSGetNormalizedPath): Corrected several memory leaks that caused refcount imbalances resulting in memory leaks on Windows. Thanks to Joe Mistachkin for the patch. 2007-05-01 Miguel Sofer * generic/tclVar.c (TclPtrSetVar): fixed leak whenever newvaluePtr had refCount 0 and was used for appending (but not lappending). Thanks to mistachkin and kbk. [Bug 1710710] 2007-05-01 Kevin B. Kenny * generic/tclIO.c (DeleteChannelTable): Made changes so that DeleteChannelTable tries to close all open channels, not just the first. [Bug 1710285] * generic/tclThread.c (TclFinalizeSynchronization): Make sure that TSD blocks get freed on non-threaded builds. [Bug 1710825] * tests/utf.test (utf-25.1--utf-25.4): Modified tests to clean up after the 'testobj' extension to avoid spurious reports of memory leaks. 2007-05-01 Don Porter * generic/tclCmdMZ.c (STR_MAP): When [string map] has a pure dict map, a missing Tcl_DictObjDone() call led to a memleak. [Bug 1710709] 2007-04-30 Daniel Steffen * unix/Makefile.in: add 'tclsh' dependency to install targets that rely on tclsh, fixes parallel 'make install' from empty build dir. 2007-04-30 Andreas Kupries * generic/tclIO.c (FixLevelCode): Corrected reference count mismanagement of newlevel, newcode. Changed to allocate the Tcl_Obj's as late as possible, and only when actually needed. [Bug 1705778, leak K29] 2007-04-30 Kevin B. Kenny * generic/tclProc.c (Tcl_ProcObjCmd, SetLambdaFromAny): Corrected reference count mismanagement on the name of the source file in the TIP 280 code. [Bug 1705778, leak K02 among other manifestations] 2007-04-25 Donal K. Fellows *** 8.5a6 TAGGED FOR RELEASE *** * generic/tclProc.c (TclObjInterpProcCore): Only allocate objects for error message generation when associated with argument names that are really used. [Bug 1705778, leak K15] 2007-04-25 Kevin B. Kenny * generic/tclIOUtil.c (Tcl_FSChdir): Changed the memory management so that the path returned from Tcl_FSGetNativePath is not duplicated before being stored as the current directory, to avoid a memory leak. [Bug 1705778, leak K01 among other manifestations] 2007-04-25 Don Porter * generic/tclCompExpr.c (ParseExpr): Revised to be sure that an error return doesn't prevent all literals getting placed on the litList to be returned to the caller for freeing. Corrects some memleaks. [Bug 1705778, leak K23] 2007-04-25 Daniel Steffen * unix/Makefile.in (dist): add macosx/*.xcconfig files to src dist; copy license.terms to dist macosx dir; fix autoheader bits. 2007-04-24 Miguel Sofer * generic/tclListObj.c: reverting [Patch 738900] (committed on 2007-04-20). Causes some Tk test breakage of unknown importance, but the impact of the patch itself is likely to be so small that it does not warrant investigation at this time. 2007-04-24 Donal K. Fellows * generic/tclDictObj.c (DictKeysCmd): Rewrote so that the lock on the internal representation of a dict is only set when necessary. [Bug 1705778, leak K04] (DictFilterCmd): Added code to drop the lock in the trivial match case. [Bug 1705778, leak K05] 2007-04-24 Kevin B. Kenny * generic/tclBinary.c: Addressed several code paths where the error return from the 'binary format' command leaked the result buffer. * generic/tclListObj.c (TclLsetFlat): Fixed a bug where the new list under construction was leaked in the error case. [Bug 1705778, leaks K13 and K14] 2007-04-24 Jeff Hobbs * unix/Makefile.in (dist): add platform library package to src dist 2007-04-24 Don Porter * generic/tclCompExpr.c (ParseExpr): Memory leak in error case; the literal Tcl_Obj was not getting freed. [Bug 1705778, leak #1 (new)] * generic/tclNamesp.c (Tcl_DeleteNamespace): Corrected flaw in the flag marking scheme to be sure that global namespaces are freed when their interp is deleted. [Bug 1705778] 2007-04-24 Kevin B. Kenny * generic/tclExecute.c (TclExecuteByteCode): Plugged six memory leaks in bignum arithmetic. * generic/tclIOCmd.c (Tcl_ReadObjCmd): Plugged a leak of the buffer object if the physical read returned an error and the bypass area had no message. * generic/tclIORChan.c (TclChanCreateObjCmd): Plugged a leak of the return value from the "initialize" method of a channel handler. (All of the above under [Bug 1705778]) 2007-04-23 Daniel Steffen * generic/tclCkalloc.c: fix warnings from gcc build configured with * generic/tclCompile.c: --enable-64bit --enable-symbols=all. * generic/tclExecute.c: * unix/tclUnixFCmd.c: add workaround for crashing bug in fts_open() * unix/tclUnixInit.c: without FTS_NOSTAT on 64bit Darwin 8 or earlier. * unix/tclLoadDyld.c (TclpLoadMemory): fix (void*) arithmetic. * macosx/Tcl-Common.xcconfig: enable more warnings. * macosx/Tcl.xcodeproj/project.pbxproj: add 'DebugMemCompile' build configuration that calls configure with --enable-symbols=all; override configure check for __attribute__((__visibility__("hidden"))) in Debug configuration to restore availability of ZeroLink. * macosx/tclMacOSXNotify.c: fix warnings. * macosx/tclMacOSXFCmd.c: const fixes. * macosx/Tcl-Common.xcconfig: fix whitespace. * macosx/Tcl-Debug.xcconfig: * macosx/Tcl-Release.xcconfig: * macosx/README: * macosx/GNUmakefile: fix/add copyright and license refs. * macosx/tclMacOSXBundle.c: * macosx/Tcl-Info.plist.in: * macosx/Tcl.xcode/project.pbxproj: * macosx/Tcl.xcodeproj/project.pbxproj: * unix/configure.in: install license.terms into Tcl.framework. * unix/configure: autoconf-2.59 2007-04-23 Don Porter * generic/tclVar.c (UnsetVarStruct): Make sure the TCL_INTERP_DESTROYED flags gets passed to unset trace routines so they can respond appropriately. [Bug 1705778, leak #9] 2007-04-23 Miguel Sofer * generic/tclCompile.c (TclFreeCompileEnv): Tip 280's new field extCmdMapPtr was not being freed. [Bug 1705778, leak #1] 2007-04-23 Kevin B. Kenny * generic/tclCompCmds.c (TclCompileUpvarCmd): Plugged a memory leak in 'upvar' when compiling (a) upvar outside a proc, (b) upvar with a syntax error, or (c) upvar where the frame index is not known at compile time. * generic/tclCompExpr.c (ParseExpr): Plugged a memory leak when parsing expressions that contain syntax errors. * generic/tclEnv.c (ReplaceString): Clear memory correctly when growing the cache to avoid reads of uninitialised data. * generic/tclIORChan.c (TclChanCreateObjCmd, FreeReflectedChannel): Plugged two memory leaks. * generic/tclStrToD.c (AccumulateDecimalDigit): Fixed a mistake where we'd run beyond the end of the 'pow10_wide' array if a number begins with a string of more than 'maxpow10_wide' zeroes. * generic/tclTest.c (Testregexpobjcmd): Removed an invalid access beyond the end of 'objv' in 'testregexp -about'. All of these issues reported under [Bug 1705778] - detected with the existing test suite, no new regression tests required. 2007-04-22 Miguel Sofer * generic/tclVar.c (TclDeleteNamespaceVars): fixed access to freed memory detected by valgrind: Tcl_GetCurrentNamespace was being called after freeing root CallFrame (on interp deletion). 2007-04-20 Miguel Sofer * generic/tclListObj.c (SetListFromAny): avoid discarding internal reps of objects converted to singleton lists. [Patch 738900] 2007-04-20 Kevin B. Kenny * doc/clock.n: Corrected a silly error (transposed 'uppercase' and 'lowercase' in clock.n. [Bug 1656002] Clarified that [clock scan] does not recognize a locale's alternative calendar. Deleted an entirely superfluous (and also incorrect) remark about the effect of Daylight Saving Time on relative times in [clock scan]. [Bug 1582951] * library/clock.tcl: Corrected an error in skipping over the %Ey field on input. * library/msgs/ja.msg: * tools/loadICU.tcl: Corrected several localisation faults in the Japanese locale (most notably, incorrect dates for the Emperors' eras). Many thanks to SourceForge user 'nyademo' for pointing this out and developing a fix. [Bug 1637471] * generic/tclPathObj.c: Corrected a 'const'ness fault that caused bitter complaints from MSVC. * tests/clock.test (clock-40.1, clock-58.1, clock-59.1): Corrected a test case that depended on ":localtime" being able to handle dates prior to the Posix epoch. [Bug 1618445] Added a test case for the dates of the Japanese emperors. [Bug 1637471] Added a regression test for military time zone input conversion. [Bug 1586828] * generic/tclGetDate.y (MilitaryTable): Fixed an ancient bug where the military NZA time zones had the signs reversed. [Bug 1586828] * generic/tclDate.c: Regenerated. * doc/Notifier.3: Documented Tcl_SetNotifier and Tcl_ServiceModeHook. Quite against my better judgment. [Bug 414933] * generic/tclBasic.c, generic/tclCkalloc.c, generic/tclClock.c: * generic/tclCmdIL.c, generic/tclCmdMZ.c, generic/tclFCmd.c: * generic/tclFileName.c, generic/tclInterp.c, generic/tclIO.c: * generic/tclIOUtil.c, generic/tclNamesp.c, generic/tclObj.c: * generic/tclPathObj.c, generic/tclPipe.c, generic/tclPkg.c: * generic/tclResult.c, generic/tclTest.c, generic/tclTestObj.c: * generic/tclVar.c, unix/tclUnixChan.c, unix/tclUnixTest.c: * win/tclWinLoad.c, win/tclWinSerial.c: Replaced commas in varargs with string concatenation where possible. [Patch 1515234] * library/tzdata/America/Tegucigalpa: * library/tzdata/Asia/Damascus: Olson's tzdata 2007e. 2007-04-19 Donal K. Fellows * generic/regcomp.c, generic/regc_cvec.c, generic/regc_lex.c, * generic/regc_locale.c: Improve the const-correctness of the RE compiler. 2007-04-18 Miguel Sofer * generic/tclExecute.c (INST_LSHIFT): fixed a mistake introduced in version 1.266 ('=' became '=='), which effectively turned the block that handles native shifts into dead code. This explains why the testsuite did not pick this mistake. Rewrote to make the intention clear. * generic/tclInt.h (TclDecrRefCount): change the order of the branches, use empty 'if ; else' to handle use in unbraced outer if/else conditions (as already done in tcl.h) * generic/tclExecute.c: slight changes in Tcl_Obj management. 2007-04-17 Kevin B. Kenny * library/clock.tcl: Fixed the naming of ::tcl::clock::ReadZoneinfoFile because (yoicks!) it was in the global namespace. * doc/clock.n: Clarified the cases in which legacy time zone is recognized. [Bug 1656002] 2007-04-17 Miguel Sofer * generic/tclExecute.c: fixed checkInterp logic [Bug 1702212] 2007-04-16 Donal K. Fellows * various (including generic/tclTest.c): Complete the purge of K&R function definitions from manually-written code. 2007-04-15 Kevin B. Kenny * generic/tclCompCmds.c: added a cast to silence a compiler error on VC2005. * library/clock.tcl: Restored unique-prefix matching of keywords on the [clock] command. [Bug 1690041] * tests/clock.test: Added rudimentary test cases for unique-prefix matching of keywords. 2007-04-14 Miguel Sofer * generic/tclExecute.c: removed some code at INST_EXPAND_SKTOP that duplicates functionality already present at checkForCatch. 2007-04-12 Miguel Sofer * generic/tclExecute.c: new macros OBJ_AT_TOS, OBJ_UNDER_TOS, OBJ_AT_DEPTH(n) and CURR_DEPTH that remove all direct references to tosPtr from TEBC (after initialisation and the code at the label cleanupV_pushObjResultPtr). 2007-04-11 Miguel Sofer * generic/tclCompCmds.c: moved all exceptDepth management to the macros - the decreasing half was managed by hand. 2007-04-10 Donal K. Fellows * generic/tclInt.h (TclNewLiteralStringObj): New macro to make allocating literal string objects (i.e. objects whose value is a constant string) easier and more efficient, by allowing the omission of the length argument. Based on [Patch 1529526] (afredd) * generic/*.c: Make use of this (in many files). 2007-04-08 Miguel Sofer * generic/tclCompile (tclInstructionTable): Fixed bugs in description of dict instructions. 2007-04-07 Miguel Sofer * generic/tclCompile (tclInstructionTable): Fixed bug in description of INST_START_COMMAND. * generic/tclExecute.c (TEBC): Small code reduction. 2007-04-06 Miguel Sofer * generic/tclExecute.c (TEBC): * generic/tclNamespace.c (NsEnsembleImplementationCmd): * generic/tclProc.c (InitCompiledLocals, ObjInterpProcEx) (TclObjInterpProcCore, ProcCompileProc): Code reordering to reduce branching and improve branch prediction (assume that forward branches are typically not taken). 2007-04-03 Miguel Sofer * generic/tclExecute.c: INST_INVOKE optimisation. [Patch 1693802] 2007-04-03 Don Porter * generic/tclNamesp.c: Revised ErrorCodeRead and ErrorInfoRead trace routines so they guarantee the ::errorCode and ::errorInfo variable always appear to exist. [Bug 1693252] 2007-04-03 Miguel Sofer * generic/tclInt.decls: Moved TclGetNamespaceFromObj() to the * generic/tclInt.h: internal stubs table; regen. * generic/tclIntDecls.h: * generic/tclStubInit.c: 2007-04-02 Miguel Sofer * generic/tclBasic.c: Added bytecode compilers for the variable * generic/tclCompCmds.c: linking commands: 'global', 'variable', * generic/tclCompile.h: 'upvar', 'namespace upvar' [Patch 1688593] * generic/tclExecute.c: * generic/tclInt.h: * generic/tclVar.c: 2007-04-02 Don Porter * generic/tclBasic.c: Replace arrays on the C stack and ckalloc * generic/tclExecute.c: calls with TclStackAlloc calls to use memory * generic/tclFCmd.c: on Tcl's evaluation stack. * generic/tclFileName.c: * generic/tclIOCmd.c: * generic/tclIndexObj.c: * generic/tclInterp.c: * generic/tclNamesp.c: * generic/tclTrace.c: * unix/tclUnixPipe.c: 2007-04-01 Donal K. Fellows * generic/tclCompile.c (TclCompileScript, TclPrintInstruction): * generic/tclExecute.c (TclExecuteByteCode): Changed the definition of INST_START_CMD so that it knows how many commands start at the current location. This makes the interpreter command counter correct without requiring a large number of instructions to be issued. (See my change from 2007-01-19 for what triggered this.) 2007-03-30 Don Porter * generic/tclCompile.c: * generic/tclCompExpr.c: * generic/tclCompCmds.c: Replace arrays on the C stack and ckalloc calls with TclStackAlloc calls to use memory on Tcl's evaluation stack. * generic/tclCmdMZ.c: Revised [string to* $s $first $last] implementation to reduce number of allocs/copies. * tests/string.test: More [string reverse] tests. 2007-03-30 Miguel Sofer * generic/tclExecute.c: optimise the lookup of elements of indexed arrays. 2007-03-29 Miguel Sofer * generic/tclProc.c (Tcl_ApplyObjCmd): * tests/apply.test (9.3): Fixed Tcl_Obj leak on error return; an unneeded ref to lambdaPtr was being set and not released on an error return path. 2007-03-28 Don Porter * generic/tclCmdMZ.c (STR_REVERSE): Implement the actual [string reverse] command in terms of the new TclStringObjReverse() routine. * generic/tclInt.h (TclStringObjReverse): New internal routine * generic/tclStringObj.c (TclStringObjReverse): that implements the [string reverse] operation, making use of knowledge/surgery of the String intrep to minimize the number of allocs and copies needed to do the job. 2007-03-27 Don Porter * generic/tclCmdMZ.c (STR_MAP): Replace ckalloc calls with TclStackAlloc calls. 2007-03-24 Zoran Vasiljevic * win/tclWinThrd.c: Thread exit handler marks the current thread as un-initialized. This allows exit handlers that are registered later to re-initialize this subsystem in case they need to use some sync primitives (cond variables) from this file again. 2007-03-23 Miguel Sofer * generic/tclBasic.c (DeleteInterpProc): pop the root frame pointer before deleting the global namespace [Bug 1658572] 2007-03-23 Kevin B. Kenny * win/Makefile.in: Added code to keep a Cygwin path name from leaking into LIBRARY_DIR when doing 'make test' or 'make runtest'. 2007-03-22 Don Porter * generic/tclCmdAH.c (Tcl_ForeachObjCmd): Replaced arrays on the C stack and ckalloc calls with TclStackAlloc calls to use memory on Tcl's evaluation stack. * generic/tclExecute.c: Revised GrowEvaluationStack to take an argument specifying the growth required by the caller, so that a single reallocation / copy is the most that will ever be needed even when required growth is large. 2007-03-21 Don Porter * generic/tclExecute.c: More ckalloc -> ckrealloc conversions. * generic/tclLiteral.c: * generic/tclNamesp.c: * generic/tclParse.c: * generic/tclPreserve.c: * generic/tclStringObj.c: * generic/tclUtil.c: 2007-03-20 Don Porter * generic/tclEnv.c: Some more ckalloc -> ckrealloc replacements. * generic/tclLink.c: 2007-03-20 Kevin B. Kenny * generic/tclDate.c: Rebuilt, despite Donal Fellows's comment when committing it that no rebuild was required. * generic/tclGetDate.y: According to Donal Fellows, "Introduce modern formatting standards; no need for rebuild of tclDate.c." * library/tzdata/America/Cambridge_Bay: * library/tzdata/America/Havana: * library/tzdata/America/Inuvik: * library/tzdata/America/Iqaluit: * library/tzdata/America/Pangnirtung: * library/tzdata/America/Rankin_Inlet: * library/tzdata/America/Resolute: * library/tzdata/America/Yellowknife: * library/tzdata/Asia/Choibalsan: * library/tzdata/Asia/Dili: * library/tzdata/Asia/Hovd: * library/tzdata/Asia/Jakarta: * library/tzdata/Asia/Jayapura: * library/tzdata/Asia/Makassar: * library/tzdata/Asia/Pontianak: * library/tzdata/Asia/Ulaanbaatar: * library/tzdata/Europe/Istanbul: Upgraded to Olson's tzdata2007d. * generic/tclListObj.c (TclLsetList, TclLsetFlat): * tests/lset.test: Changes to deal with shared internal representation for lists passed to the [lset] command. Thanks to Don Porter for fixing this issue. [Bug 1677512] 2007-03-19 Don Porter * generic/tclCompile.c: Revise the various expansion routines for CompileEnv fields to use ckrealloc() where appropriate. * generic/tclBinary.c (Tcl_SetByteArrayLength): Replaced ckalloc() / memcpy() sequence with ckrealloc() call. * generic/tclBasic.c (Tcl_CreateMathFunc): Replaced some calls to * generic/tclEvent.c (Tcl_CreateThread): Tcl_Alloc() with calls * generic/tclObj.c (UpdateStringOfBignum): to ckalloc(), which * unix/tclUnixTime.c (SetTZIfNecessary): better supports memory * win/tclAppInit.c (setargv): debugging. 2007-03-19 Donal K. Fellows * doc/regsub.n: Corrected example so that it doesn't recommend potentially unsafe practice. Many thanks to Konstantin Kushnir for reporting this. 2007-03-17 Kevin B. Kenny * win/tclWinReg.c (GetKeyNames): Size the buffer for enumerating key names correctly, so that Unicode names exceeding 127 chars can be retrieved without crashing. [Bug 1682211] * tests/registry.test (registry-4.9): Added test case for the above bug. 2007-03-15 Mo DeJong * generic/tclIOUtil.c (Tcl_Stat): Reimplement workaround to avoid gcc warning by using local variables. When the macro argument is of type long long instead of long, the incorrect warning is not generated. 2007-03-15 Mo DeJong * win/Makefile.in: Fully qualify LIBRARY_DIR so that `make test` does not depend on working dir. 2007-03-15 Mo DeJong * tests/parse.test: Add two backslash newline parse tests. 2007-03-12 Don Porter * generic/tclExecute.c (INST_FOREACH_STEP4): Make private copy of * tests/foreach.test (foreach-10.1): value list to be assigned to variables so that shimmering of that list doesn't lead to invalid pointers. [Bug 1671087] * generic/tclEvent.c (HandleBgErrors): Make efficient private copy * tests/event.test (event-5.3): of the command prefix for the interp's background error handling command to avoid panics due to pointers to memory invalid after shimmering. [Bug 1670155] * generic/tclNamesp.c (NsEnsembleImplementationCmd): Make efficient * tests/namespace.test (namespace-42.8): private copy of the command prefix as we invoke the command appropriate to a particular subcommand of a particular ensemble to avoid panic due to shimmering of the List intrep. [Bug 1670091] * generic/tclVar.c (TclArraySet): Make efficient private copy of * tests/var.test (var-17.1): the "list" argument to [array set] to avoid crash due to shimmering invalidating pointers. [Bug 1669489] 2007-03-12 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LsortObjCmd): Fix problems with declaration positioning and memory leaks. [Bug 1679072] 2007-03-11 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LreverseObjCmd): Ensure that a list is correctly reversed even if its internal representation is shared without the object itself being shared. [Bug 1675044] 2007-03-10 Miguel Sofer * generic/tclCmdIL (Tcl_LsortObjCmd): changed fix to [Bug 1675116] to use the cheaper TclListObjCopy() instead of Tcl_DuplicateObj(). 2007-03-09 Andreas Kupries * library/platform/shell.tcl: Made more robust if an older platform * library/platform/pkgIndex.tcl: package is present in the inspected * unix/Makefile.in: shell. Package forget it to prevent errors. Bumped * win/Makefile.in: package version to 1.1.3, and updated the Makefiles installing it as Tcl Module. 2007-03-09 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LsortObjCmd): Handle tricky case with loss * tests/cmdIL.test (cmdIL-1.29): of list rep during sorting due to shimmering. [Bug 1675116] 2007-03-09 Kevin B. Kenny * library/clock.tcl (ReadZoneinfoFile): Added Y2038 compliance to the code for version-2 'zoneinfo' files. * tests/clock.test (clock-56.3): Added a test case for Y2038 and 'zoneinfo'. Modified test initialisation to use the 'loadTestedCommands' function of tcltest to bring in the correct path for the registry library. 2007-03-08 Don Porter * generic/tclListObj.c (TclLsetList): Rewrite so that the routine itself does not do any direct intrep surgery. Better isolates those things into the implementation of the "list" Tcl_ObjType. 2007-03-08 Donal K. Fellows * generic/tclListObj.c (TclLindexList, TclLindexFlat): Moved these functions to tclListObj.c from tclCmdIL.c to mirror the way that the equivalent functions for [lset]'s guts are arranged. 2007-03-08 Kevin B. Kenny * library/clock.tcl: Further tweaks to the Windows time zone table (restoring missing Mexican time zones). Added rudimentary handling of version-2 'zoneinfo' files. Update US DST rules so that zones such as 'EST5EDT' get the correct transition dates. * tests/clock.test: Added rudimentary test cases for 'zoneinfo' parsing. Adjusted several tests that depended on obsolete US DST transition rules. 2007-03-07 Daniel Steffen * macosx/tclMacOSXNotify.c: add spinlock debugging and sanity checks. * macosx/Tcl.xcodeproj/project.pbxproj: ensure gcc version used by * macosx/Tcl.xcodeproj/default.pbxuser: Xcode and configure/make are * macosx/Tcl-Common.xcconfig: consistent and independent of gcc_select default and CC env var; fixes for Xcode 3.0. * unix/tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in macosx-version-min check * unix/configure: autoconf-2.59 2007-03-07 Don Porter * generic/tclCmdIL.c (TclLindex*): Rewrites to make efficient private copies of the list and indexlist arguments, so we can operate on the list elements directly with no fear of shimmering effects. Replaces defensive coding schemes that are otherwise required. End result is that TclLindexList is entirely a wrapper around TclLindexFlat, which is now the core engine of all [lindex] operations. * generic/tclObj.c (Tcl_AppendAllObjTypes): Converted to simpler list validity test. 2007-03-07 Donal K. Fellows * generic/tclRegexp.c (TclRegAbout): Generate information about a regexp as a Tcl_Obj instead of as a string, which is more efficient. 2007-03-07 Kevin B. Kenny * library/clock.tcl: Adjusted Windows time zone table to handle new US DST rules by locale rather than as Posix time zone spec. * tests/clock.test (clock-39.6, clock-49.2, testclock::registry): Adjusted tests to simulate new US rules. * library/tzdata/America/Indiana/Winamac: * library/tzdata/Europe/Istanbul: * library/tzdata/Pacific/Easter: Olson's tzdata2007c. 2007-03-05 Andreas Kupries * library/platform/shell.tcl (::platform::shell::RUN): In the case of * library/platform/pkgIndex.tcl: a failure put the captured stderr * unix/Makefile.in: into the error message to aid in debugging. Bumped * win/Makefile.in: package version to 1.1.2, and updated the makefiles installing it as Tcl Module. 2007-03-03 Donal K. Fellows * generic/tclLink.c (LinkedVar): Added macro to conceal at least some of the pointer hackery. 2007-03-02 Don Porter * generic/tclCmdIL.c (Tcl_LreverseObjCmd): Added missing TclInvalidateStringRep() call when we directly manipulate the intrep of an unshared "list" Tcl_Obj. [Bug 1672585] * generic/tclCmdIL.c (Tcl_JoinObjCmd): Revised [join] implementation to append Tcl_Obj's instead of strings. [RFE 1669420] * generic/tclCmdIL.c (Info*Cmd): Code simplifications and optimizations. 2007-03-02 Donal K. Fellows * generic/tclCompile.c (TclPrintInstruction): Added a scheme to allow * generic/tclCompile.h (AuxDataPrintProc): aux-data to be printed * generic/tclCompCmds.c (Print*Info): out for debugging. For this to work, immediate operands referring to aux-data must be identified as such in the instruction descriptor table using OPERAND_AUX4 (all are always 4 bytes). * generic/tclExecute.c (TclExecuteByteCode): Rewrote the compiled * generic/tclCompCmds.c (TclCompileDictCmd): [dict update] so that it * generic/tclCompile.h (DictUpdateInfo): stores critical * tests/dict.test (dict-21.{14,15}): non-varying data in an aux-data value instead of a (shimmerable) literal. [Bug 1671001] 2007-03-01 Don Porter * generic/tclCmdIL.c (Tcl_LinsertObjCmd): Code simplifications and optimizations. * generic/tclCmdIL.c (Tcl_LreplaceObjCmd): Code simplifications and optimizations. * generic/tclCmdIL.c (Tcl_LrangeObjCmd): Rewrite in the same spirit; avoid shimmer effects rather than react to them. * generic/tclCmdAH.c (Tcl_ForeachObjCmd): Stop throwing away * tests/foreach.test (foreach-1.14): useful error information when loop variable sets fail. * generic/tclCmdIL.c (Tcl_LassignObjCmd): Rewrite to make an efficient private copy of the list argument, so we can operate on the list elements directly with no fear of shimmering effects. Replaces defensive coding schemes that are otherwise required. * generic/tclCmdAH.c (Tcl_ForeachObjCmd): Rewrite to make efficient private copies of the variable and value lists, so we can operate on them without any special shimmer defense coding schemes. 2007-03-01 Donal K. Fellows * generic/tclCompCmds.c (TclCompileForeachCmd): Prevent an unexpected * tests/foreach.test (foreach-9.1): infinite loop when the variable list is empty and the foreach is compiled. [Bug 1671138] 2007-02-26 Andreas Kupries * generic/tclIORChan.c (FreeReflectedChannel): Added the missing refcount release between NewRC and FreeRC for the channel handle object, spotted by Don Porter. [Bug 1667990] 2007-02-26 Don Porter * generic/tclCmdAH.c (Tcl_ForeachObjCmd): Removed surplus copying of the objv array that used to be a workaround for [Bug 404865]. That bug is long fixed. 2007-02-24 Don Porter * generic/tclBasic.c: Use new interface in Tcl_EvalObjEx so that the recounting logic of the List internal rep need not be repeated there. Better encapsulation of internal details. * generic/tclInt.h: New internal routine TclListObjCopy() used * generic/tclListObj.c: to efficiently do the equivalent of [lrange $list 0 end]. After some experience with this, might be a good candidate for exposure as a public interface. It's useful for callers of Tcl_ListObjGetElements() who want to control the ongoing validity of the returned objv pointer. 2007-02-22 Andreas Kupries * tests/pkg.test: Added tests for the case of an alpha package satisfying a require for the regular package, demonstrating a corner case specified in TIP#280. More notes in the comments to the test. 2007-02-20 Jan Nijtmans * generic/tclInt.decls: Added "const" specifiers in TclSockGetPort * generic/tclIntDecls.h: regenerated * generic/*.c: * unix/tclUnixChan.c * unix/tclUnixPipe.c * win/tclWinPipe.c * win/tclWinSock.c: Added many "const" specifiers in implementation. 2007-02-20 Don Porter * doc/tcltest.n: Typo fix. [Bug 1663539] 2007-02-20 Pat Thoyts * generic/tclFileName.c: Handle extended paths on Windows NT and * generic/tclPathObj.c: above. These have a \\?\ prefix. [Bug * win/tclWinFile.c: 1479814] * tests/winFCmd.test: Tests for extended path handling. 2007-02-19 Jeff Hobbs * unix/tcl.m4: use SHLIB_SUFFIX=".so" on HP-UX ia64 arch. * unix/configure: autoconf-2.59 * generic/tclIOUtil.c (Tcl_FSEvalFileEx): safe incr of objPtr ref. 2007-02-18 Donal K. Fellows * doc/chan.n, doc/clock.n, doc/eval.n, doc/exit.n, doc/expr.n: * doc/interp.n, doc/open.n, doc/platform_shell.n, doc/pwd.n: * doc/refchan.n, doc/regsub.n, doc/scan.n, doc/tclvars.n, doc/tm.n: * doc/unload.n: Apply [Bug 1610310] to fix typos. Thanks to Larry Virden for spotting them. * doc/interp.n: Partial fix of [Bug 1662436]; rest requires some policy decisions on what should and shouldn't be safe commands from the "new in 8.5" set. 2007-02-13 Kevin B. Kenny * tools/fix_tommath_h.tcl: Further tweaking for the x86-64. The change is to make 'mp_digit' be an 'unsigned int' on that platform; since we're using only 32 bits of it, there's no reason to make it a 64-bit 'unsigned long.' * generic/tclTomMath.h: Regenerated. 2007-02-13 Donal K. Fellows * doc/re_syntax.n: Corrected description of 'print' class [Bug 1614687] and enhanced description of 'graph' class. 2007-02-12 Kevin B. Kenny * tools/fix_tommath_h.tcl: Added code to patch out a check for __x86_64__ that caused Tommath to use __attributes(TI)__ for the mp_word type. Tetra-int's simply fail on too many gcc-glibc-OS combinations to be ready for shipment today, even if they work for some of us. This change allows reversion of das's change of 2006-08-18 that accomplised the same thing on Darwin. [Bugs 1601380, 1603737, 1609936, 1656265] * generic/tclTomMath.h: Regenerated. * library/tzdata/Africa/Asmara: * library/tzdata/Africa/Asmera: * library/tzdata/America/Nassau: * library/tzdata/Atlantic/Faeroe: * library/tzdata/Atlantic/Faroe: * library/tzdata/Australia/Eucla: * library/tzdata/Pacific/Easter: Rebuilt from Olson's tzdata2007b. 2007-02-09 Joe Mistachkin * win/nmakehlp.c: Properly cleanup after nmakehlp, including the * win/makefile.vc: vcX0.pch file. 2007-02-08 Jeff Hobbs * unix/tclUnixInit.c (TclpCheckStackSpace): do stack size checks with unsigned size_t to correctly validate stackSize in the 2^31+ range. [Bug 1654104] 2007-02-08 Don Porter * generic/tclNamesp.c: Corrected broken logic in Tcl_DeleteNamespace * tests/namespace.test: introduced in Patch 1577278 that caused [namespace delete ::] to be effective only at level #0. New test namespace-7.7 should prevent similar error in the future [Bug 1655305] 2007-02-06 Don Porter * generic/tclNamesp.c: Corrected broken implementation of the * tests/namespace.test: TclMatchIsTrivial optimization on [namespace children $namespace $pattern]. 2007-02-04 Daniel Steffen * unix/tcl.m4: use gcc4's __attribute__((__visibility__("hidden"))) if available to define MODULE_SCOPE effective on all platforms. * unix/configure.in: add caching to -pipe and zoneinfo checks. * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 2007-02-03 Joe Mistachkin * win/rules.vc: Fix platform specific file copy macros for downlevel Windows. 2007-01-29 Don Porter * generic/tclResult.c: Added optimization case to TclTransferResult to cover common case where there's big savings over the fully general path. Thanks to Peter MacDonald. [Bug 1626518] * generic/tclLink.c: Broken linked float logic corrected. Thanks to Andy Goth. [Bug 1602538] * doc/fcopy.n: Typo fix. [Bug 1630627] 2007-01-28 Daniel Steffen * macosx/Tcl.xcodeproj/project.pbxproj: extract build settings that * macosx/Tcl.xcodeproj/default.pbxuser: were common to multiple * macosx/Tcl-Common.xcconfig (new file): configurations into external * macosx/Tcl-Debug.xcconfig (new file): xcconfig files; add extra * macosx/Tcl-Release.xcconfig (new file): configurations for building with SDKs and 64bit; convert legacy jam-based 'Tcl' target to native target with single script phase; correct syntax of build setting references to use $() throughout. * macosx/README: document new Tcl.xcodeproj configurations; other minor updates/corrections. * generic/tcl.h: update location of version numbers in macosx files. * macosx/Tcl.xcode/project.pbxproj: restore 'tcltest' target to * macosx/Tcl.xcode/default.pbxuser: working order by replicating applicable changes to Tcl.xcodeproj since 2006-07-20. 2007-01-25 Daniel Steffen * unix/tcl.m4: integrate CPPFLAGS into CFLAGS as late as possible and move (rather than duplicate) -isysroot flags from CFLAGS to CPPFLAGS to avoid errors about multiple -isysroot flags from some older gcc builds. * unix/configure: autoconf-2.59 2007-01-22 Donal K. Fellows * compat/memcmp.c (memcmp): Reworked so that arithmetic is never performed upon void pointers, since that is illegal. [Bug 1631017] 2007-01-19 Donal K. Fellows * generic/tclCompile.c (TclCompileScript): Reduce the frequency with which we issue INST_START_CMD, making bytecode both more compact and somewhat faster. The optimized case is where we would otherwise be issuing a sequence of those instructions; in those cases, it is only ever the first one encountered that could possibly trigger. 2007-01-19 Joe Mistachkin * tools/man2tcl.c: Include stdlib.h for exit() and improve comment detection. * win/nmakehlp.c: Update usage. * win/makefile.vc: Properly build man2tcl.c for MSVC8. 2007-01-19 Daniel Steffen * macosx/tclMacOSXFCmd.c (TclMacOSXSetFileAttribute): on some versions of Mac OS X, truncate() fails on resource forks, in that case use open() with O_TRUNC instead. * macosx/tclMacOSXNotify.c: accommodate changes to prototypes of OSSpinLock(Un)Lock API. * macosx/Tcl.xcodeproj/project.pbxproj: ensure HOME and USER env vars * macosx/Tcl.xcodeproj/default.pbxuser: are defined when running testsuite from Xcode. * tests/env.test: add extra system env vars that need to be preserved on some Mac OS X versions for testsuite to work. * unix/Makefile.in: Move libtommath defines into configure.in to * unix/configure.in: avoid replicating them across multiple * macosx/Tcl.xcodeproj/project.pbxproj: buildsystems. * unix/tcl.m4: ensure CPPFLAGS env var is used when set. [Bug 1586861] (Darwin): add -isysroot and -mmacosx-version-min flags to CPPFLAGS when present in CFLAGS to avoid discrepancies between what headers configure sees during preprocessing tests and compiling tests. * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 2007-01-18 Donal K. Fellows * generic/tclCompile.c (TclCompileScript): Make sure that when parsing an expanded literal fails, a correct bytecode sequence is still issued. [Bug 1638414]. Also make sure that the start of the expansion bytecode sequence falls inside the span of bytecodes for a command. * tests/compile.test (compile-16.24): Added test for [Bug 1638414] 2007-01-17 Donal K. Fellows * generic/tclIO.c: Added macros to make usage of ChannelBuffers clearer. 2007-01-11 Joe English * win/tcl.m4(CFLAGS_WARNING): Remove "-Wconversion". This was removed from unix/tcl.m4 2004-07-16 but not from here. * win/configure: Regenerated. 2007-01-11 Pat Thoyts * win/makefile.vc: Fixes to work better on Win98. Read version numbers * win/nmakehlp.c: from package index file to avoid keeping numbers in * win/rules.vc: the makefile where they may become de-synchronized. 2007-01-10 Donal K. Fellows * generic/regcomp.c (compile, freev): Define a strategy for * generic/regexec.c (exec): managing the internal * generic/regguts.h (AllocVars, FreeVars): vars of the RE engine to * generic/regcustom.h (AllocVars, FreeVars): reduce C stack usage. This will make Tcl as a whole much less likely to run out of stack space... 2007-01-09 Donal K. Fellows * generic/tclCompCmds.c (TclCompileLindexCmd): * tests/lindex.test (lindex-9.2): Fix silly bug that ended up sometimes compiling list arguments in the wrong order. [Bug 1631364] 2007-01-03 Kevin B. Kenny * generic/tclDate.c: Regenerated to recover a lost fix from patthoyts. [Bug 1618523] 2006-12-26 Mo DeJong * generic/tclIO.c (Tcl_GetsObj): Avoid checking for for the LF in a possible CRLF sequence when EOF has already been found. 2006-12-26 Mo DeJong * generic/tclEncoding.c (EscapeFromUtfProc): Clear the TCL_ENCODING_END flag when end bytes are written. This fix keep this method from writing escape bytes for an encoding like iso2022-jp multiple times when the escape byte overlap with the end of the IO buffer. * tests/io.test: Add test for escape byte overlap issue. 2006-12-19 Donal K. Fellows * unix/tclUnixThrd.c (Tcl_GetAllocMutex, TclpNewAllocMutex): Add intermediate variables to shut up unwanted warnings. [Bug 1618838] 2006-12-19 Daniel Steffen * unix/tclUnixThrd.c (TclpInetNtoa): fix for 64 bit. * unix/tcl.m4 (Darwin): --enable-64bit: verify linking with 64bit -arch flag succeeds before enabling 64bit build. * unix/configure: autoconf-2.59 2006-12-17 Daniel Steffen * tests/macOSXLoad.test (new file): add testing of .bundle loading and * tests/load.test: unloading on Darwin (in addition * tests/unload.test: to existing tests of .dylib loading). * macosx/Tcl.xcodeproj/project.pbxproj: add building of dltest binaries so that testsuite run from Xcode can use them; fix testsuite run script * unix/configure.in: add support for building dltest binaries as * unix/dltest/Makefile.in: .bundle (in addition to .dylib) on Darwin. * unix/Makefile.in: add stub lib dependency to dltest target. * unix/configure: autoconf-2.59 * tests/append.test: fix cleanup failure when all tests are skipped. * tests/chan.test (chan-16.9): cleanup chan event handler to avoid causing error in event.test when running testsuite with -singleproc 1. * tests/info.test: add !singleTestInterp constraint to tests that fail when running testsuite with -singleproc 1. [Bug 1605269] 2006-12-14 Donal K. Fellows * doc/string.n: Fix example. [Bug 1615277] 2006-12-12 Don Porter * generic/tclCompExpr.c: Now that the new internal structs are in use to support operator commands, might as well make them the default for [expr] as well and avoid passing every parsed expression through the inefficient Tcl_Token array format. This addresses most issues in [RFE 1517602]. Assuming no performance disasters result from this, much dead code supporting the other implementation might now be removed. * generic/tclBasic.c: Final step routing all direct evaluation forms * generic/tclCompExpr.c: of the operator commands through TEBC, * generic/tclCompile.h: dropping all the routines in tclMathOp.c. * generic/tclMathOp.c: Still needs Engineering Manual attention. 2006-12-11 Don Porter * generic/tclBasic.c: Another step with all sorting operator * generic/tclCompExpr.c: commands now routing through TEBC via * generic/tclCompile.h: TclSortingOpCmd(). 2006-12-08 Don Porter * generic/tclBasic.c: Another step down the path of re-using * generic/tclCompExpr.c: TclExecuteByteCode to implement the TIP 174 * generic/tclCompile.h: commands instead of using a mass of code * generic/tclMathOp.c: duplication. Now all operator commands that * tests/mathop.test: demand exactly one operation are implemented via TclSingleOpCmd and a call to TEBC. * generic/tclCompExpr.c: Revised implementation of TclInvertOpCmd to * generic/tclMathOp.c: perform a bytecode compile / execute sequence. This demonstrates a path toward avoiding mountains of code duplication in tclMathOp.c and tclExecute.c. * generic/tclCompile.h: Change TclExecuteByteCode() from static to * generic/tclExecute.c: MODULE_SCOPE so all files including tclCompile.h may call it. * generic/tclMathOp.c: More revisions to make tests pass. * tests/mathop.test: 2006-12-08 Donal K. Fellows * generic/tclNamesp.c (TclTeardownNamespace): Ensure that dying namespaces unstitch themselves from their referents. [Bug 1571056] (NsEnsembleImplementationCmd): Silence GCC warning. * tests/mathop.test: Full tests for & | and ^ operators 2006-12-08 Daniel Steffen * library/tcltest/tcltest.tcl: use [info frame] for "-verbose line". 2006-12-07 Don Porter * generic/tclCompCmds.c: Additional commits correct most * generic/tclExecute.c: failing tests illustrating bugs * generic/tclMathOp.c: uncovered in [Patch 1578137]. * generic/tclBasic.c: Biggest source of TIP 174 failures was that the commands were not [namespace export]ed from the ::tcl::mathop namespace. More bits from [Patch 1578137] correct that. * tests/mathop.test: Commmitted several new tests from Peter Spjuth found in [Patch 1578137]. Many failures now demonstrate issues to fix in the TIP 174 implementation. 2006-12-07 Donal K. Fellows * tests/mathop.test: Added tests for ! ~ eq operators. * generic/tclMathOp.c (TclInvertOpCmd): Add in check for non-integral numeric values. * generic/tclCompCmds.c (CompileCompareOpCmd): Factor out the code generation for the chained comparison operators. 2006-12-07 Pat Thoyts * tests/exec.test: Fixed line endings (caused win32 problems). 2006-12-06 Don Porter * generic/tclCompCmds.c: Revised and consolidated into utility * tests/mathop.test: routines some of routines that compile the new TIP 174 commands. This corrects some known bugs. More to come. 2006-12-06 Kevin B. Kenny * tests/expr.test (expr-47.12): Improved error reporting in hopes of having more information to pursue [Bug 1609936]. 2006-12-05 Andreas Kupries TIP#291 IMPLEMENTATION * generic/tclBasic.c: Define tcl_platform element for pointerSize. * doc/tclvars.n: * win/Makefile.in: Added installation instructions for the platform * win/makefile.vc: package. Added the platform package. * win/makefile.bc: * unix/Makefile.in: * tests/platform.test: * tests/safe.test: * library/platform/platform.tcl: * library/platform/shell.tcl: * library/platform/pkgIndex.tcl: * doc/platform.n: * doc/platform_shell.n: 2006-12-05 Don Porter * generic/tclPkg.c: When no requirements are supplied to a * tests/pkg.test: [package require $pkg] and [package unknown] is invoked to find a satisfying package, pass the requirement argument "0-" (which means all versions are acceptable). This permits a registered [package unknown] command to call [package vsatisfies $testVersion {*}$args] without any special handling of the empty $args case. This fixes/avoids a bug in [::tcl::tm::UnknownHandler] that was causing old TM versions to be provided in preference to newer TM versions. Thanks to Julian Noble for discovering the issue. 2006-12-04 Donal K. Fellows TIP#267 IMPLEMENTATION * generic/tclIOCmd.c (Tcl_ExecObjCmd): Added -ignorestderr option, * tests/exec.test, doc/exec.n: loosely from [Patch 1476191] 2006-12-04 Don Porter * generic/tclCompExpr.c: Added implementation for the CompileExprTree() routine that can produce expression bytecode directly from internal structures with no need to pass through the Tcl_Token array representation. Still disabled by default. #undef USE_EXPR_TOKENS to try it out. 2006-12-03 Don Porter * generic/tclCompExpr.c: Added expr parsing routines that produce a different set of internal structures representing the parsed expression, as well as routines that go on to convert those structures into the traditional Tcl_Token array format. Use of these routines is currently disabled. #undef PARSE_DIRECT_EXPR_TOKENS to enable them. These routines will only become really useful when more routines that compile directly from the new internal structures are completed. 2006-12-02 Donal K. Fellows * doc/file.n: Clarification of [file pathtype] docs. [Bug 1606454] 2006-12-01 Kevin B. Kenny * libtommath/bn_mp_add.c: Corrected the effects of a * libtommath/bn_mp_div.c: bollixed 'cvs merge' operation * libtommath/bncore.c: that inadvertently committed some * libtommath/tommath_class.h: half-developed code. TIP#299 IMPLEMENTATION * doc/mathfunc.n: Added isqrt() function to docs * generic/tclBasic.c: Added isqrt() math function (ExprIsqrtFunc) * tests/expr.test (expr-47.*): Added tests for isqrt() * tests/info.test (info-20.2): Added isqrt() to expected math funcs. 2006-12-01 Don Porter * tests/chan.test: Correct timing sensitivity in new test. [Bug 1606860] TIP#287 IMPLEMENTATION * doc/chan.n: New subcommand [chan pending]. * generic/tclBasic.c: Thanks to Michael Cleverly for proposal * generic/tclInt.h: and implementation. * generic/tclIOCmd.c: * library/init.tcl: * tests/chan.test: * tests/ioCmd.test: TIP#298 IMPLEMENTATION * generic/tcl.decls: Tcl_GetBignumAndClearObj -> Tcl_TakeBignumFromObj * generic/tclObj.c: * generic/tclDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclExecute.c: Update callers. * generic/tclMathOp.c: 2006-11-30 Kevin B. Kenny * library/tzdata: Olson's tzdata2006p. * libtommath/bn_mp_sqrt.c: Fixed a bug where the initial approximation to the square root could be on the wrong side, causing failure of convergence. 2006-11-29 Don Porter * generic/tclBasic.c (Tcl_AppendObjToErrorInfo): Added Tcl_DecrRefCount() on the objPtr argument to plug memory leaks. This makes the routine a consumer, which makes it easiest to use. 2006-11-28 Andreas Kupries * generic/tclBasic.c: TIP #280 implementation. * generic/tclCmdAH.c: * generic/tclCmdIL.c: * generic/tclCmdMZ.c: * generic/tclCompCmds.c: * generic/tclCompExpr.c: * generic/tclCompile.c: * generic/tclCompile.h: * generic/tclExecute.c: * generic/tclIOUtil.c: * generic/tclInt.h: * generic/tclInterp.c: * generic/tclNamesp.c: * generic/tclObj.c: * generic/tclProc.c: * tests/compile.test: * tests/info.test: * tests/platform.test: * tests/safe.test: 2006-11-27 Kevin B. Kenny * unix/tclUnixChan.c (TclUnixWaitForFile): * tests/event.test (event-14.*): Corrected a bug where TclUnixWaitForFile would present select() with the wrong mask on an LP64 machine if a fd number exceeds 32. Thanks to Jean-Luc Fontaine for reporting and diagnosing. [Bug 1602208] 2006-11-27 Don Porter * generic/tclExecute.c (TclIncrObj): Correct failure to detect floating-point increment values. Thanks to William Coleda [Bug 1602991] 2006-11-26 Donal K. Fellows * tests/mathop.test, doc/mathop.n: More bits and pieces of the TIP#174 implementation. Note that the test suite is not yet complete. 2006-11-26 Daniel Steffen * unix/tcl.m4 (Linux): --enable-64bit support. [Patch 1597389] * unix/configure: autoconf-2.59 [Bug 1230558] 2006-11-25 Donal K. Fellows TIP#174 IMPLEMENTATION * generic/tclMathOp.c (new file): Completed the implementation of the interpreted versions of all the tcl::mathop commands. Moved to a new file to make tclCompCmds.c more focused in purpose. 2006-11-23 Donal K. Fellows * generic/tclCompCmds.c (Tcl*OpCmd, TclCompile*OpCmd): * generic/tclBasic.c (Tcl_CreateInterp): Partial implementation of TIP#174; the commands are compiled, but (mostly) not interpreted yet. 2006-11-22 Donal K. Fellows TIP#269 IMPLEMENTATION * generic/tclCmdMZ.c (Tcl_StringObjCmd): Implementation of the [string * tests/string.test (string-25.*): is list] command, based on * doc/string.n: work by Joe Mistachkin, with enhancements by Donal Fellows for better failindex behaviour. 2006-11-22 Don Porter * tools/genWinImage.tcl (removed): Removed two files used in * win/README.binary (removed): production of binary distributions for Windows, a task we no longer perform. [Bug 1476980] * generic/tcl.h: Remove mention of win/README.binary in comment * generic/tcl.h: Moved TCL_REG_BOSONLY #define from tcl.h to * generic/tclInt.h: tclInt.h. Only know user is Expect, which already #include's tclInt.h. No need to continue greater exposure. [Bug 926500] 2006-11-20 Donal K. Fellows * generic/tclBasic.c (Tcl_CreateInterp, TclHideUnsafeCommands): * library/init.tcl: Refactored the [chan] command's guts so that it does not use aliases to global commands, making the code more robust. 2006-11-17 Don Porter * generic/tclExecute.c (INST_EXPON): Corrected crash on [expr 2**(1<<63)]. Was operating on cleared bignum Tcl_Obj. 2006-11-16 Donal K. Fellows * doc/apply.n, doc/chan.n: Added examples. 2006-11-15 Don Porter TIP#270 IMPLEMENTATION * generic/tcl.decls: New public routines Tcl_ObjPrintf, * generic/tclStringObj.c: Tcl_AppendObjToErrorInfo, Tcl_Format, * generic/tclInt.h: Tcl_AppendLimitedToObj, Tcl_AppendFormatToObj and Tcl_AppendPrintfToObj. Former internal versions removed. * generic/tclDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclBasic.c: Updated callers. * generic/tclCkalloc.c: * generic/tclCmdAH.c: * generic/tclCmdIL.c: * generic/tclCmdMZ.c: * generic/tclCompExpr.c: * generic/tclCompile.c: * generic/tclDictObj.c: * generic/tclExecute.c: * generic/tclIORChan.c: * generic/tclIOUtil.c: * generic/tclMain.c: * generic/tclNamesp.c: * generic/tclObj.c: * generic/tclPkg.c: * generic/tclProc.c: * generic/tclStrToD.c: * generic/tclTimer.c: * generic/tclUtil.c: * unix/tclUnixFCmd.c: * tools/genStubs.tcl: Updated script to no longer produce the _ANSI_ARGS_ wrapper in generated declarations. Also revised to accept variadic prototypes with more than one fixed argument. (This is possible since TCL_VARARGS and its limitations are no longer in use). * generic/tcl.h: Some reordering so that macro definitions do not interfere with the now _ANSI_ARGS_-less stub declarations. * generic/tclDecls.h: make genstubs * generic/tclIntDecls.h: * generic/tclIntPlatDecls.h: * generic/tclPlatDecls.h: * generic/tclTomMathDecls.h: 2006-11-15 Donal K. Fellows * doc/ChnlStack.3, doc/CrtObjCmd.3, doc/GetIndex.3, doc/OpenTcp.3: * doc/chan.n, doc/fconfigure.n, doc/fcopy.n, doc/foreach.n: * doc/history.n, doc/http.n, doc/library.n, doc/lindex.n: * doc/lrepeat.n, doc/lreverse.n, doc/pkgMkIndex.n, doc/re_syntax.n: Convert \fP to \fR so that man-page scrapers have an easier time. 2006-11-14 Don Porter TIP#261 IMPLEMENTATION * generic/tclNamesp.c: [namespace import] with 0 arguments introspects the list of imported commands. 2006-11-13 Kevin B. Kenny * generic/tclThreadStorage.c (Tcl_InitThreadStorage): (Tcl_FinalizeThreadStorage): Silence a compiler warning about presenting a volatile pointer to 'memset'. 2006-11-13 Don Porter * generic/tclIO.c: When [gets] on a binary channel needs to use the "iso8859-1" encoding, save a copy of that encoding per-thread to avoid repeated freeing and re-loading of it from the file system. This replaces the cached copy of this encoding that the platform initialization code used to keep in pre-8.5 releases. 2006-11-13 Daniel Steffen * generic/tclCompExpr.c: Fix gcc warnings about 'cast to/from * generic/tclEncoding.c: pointer from/to integer of different * generic/tclEvent.c: size' on 64-bit platforms by casting * generic/tclExecute.c: to intermediate types * generic/tclHash.c: intptr_t/uintptr_t via new PTR2INT(), * generic/tclIO.c: INT2PTR(), PTR2UINT() and UINT2PTR() * generic/tclInt.h: macros. [Patch 1592791] * generic/tclProc.c: * generic/tclTest.c: * generic/tclThreadStorage.c: * generic/tclTimer.c: * generic/tclUtil.c: * unix/configure.in: * unix/tclUnixChan.c: * unix/tclUnixPipe.c: * unix/tclUnixPort.h: * unix/tclUnixTest.c: * unix/tclUnixThrd.c: * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 2006-11-12 Donal K. Fellows * generic/tclInt.h, generic/tclInt.decls: Transfer TclPtrMakeUpvar and TclObjLookupVar to the internal stubs table. 2006-11-10 Daniel Steffen * tests/fCmd.test (fCmd-6.26): fix failure when env(HOME) path contains symlinks. * macosx/Tcl.xcodeproj/project.pbxproj: remove tclParseExpr.c; when running testsuite from inside Xcdoe, skip stack-3.1 (it only fails under those circumstances). * unix/tcl.m4 (Darwin): suppress linker arch warnings when building universal for both 32 & 64 bit and no 64bit CoreFoundation is available; sync with tk tcl.m4 change. * unix/configure.in: whitespace. * unix/configure: autoconf-2.59 2006-11-09 Don Porter * generic/tclParseExpr.c (removed): Moved all the code of * generic/tclCompExpr.c: tclParseExpr.c into tclCompExpr.c. * unix/Makefile.in: This sets the stage for expr compiling to work * win/Makefile.in: directly with the full parse tree structures, * win/makefile.bc: and not have to pass through the information * win/makefile.vc: lossy format of an array of Tcl_Tokens. * win/tcl.dsp: 2006-11-09 Donal K. Fellows TIP#272 IMPLEMENTATION * generic/tclCmdMZ.c (Tcl_StringObjCmd): Implementation of the * tests/string.test, tests/stringComp.test: [string reverse] command * doc/string.n: from TIP#272. * generic/tclCmdIL.c (Tcl_LreverseObjCmd): Implementation of the * generic/tclBasic.c, generic/tclInt.h: [lreverse] command from * tests/cmdIL.test (cmdIL-7.*): TIP#272. * doc/lreverse.n: 2006-11-08 Donal K. Fellows * generic/tclIO.c, generic/tclPkg.c: Style & clarity rewrites. 2006-11-07 Andreas Kupries * unix/tclUnixFCmd.c (CopyFile): Added code to fall back to a hardwired default block size should the filesystem report a bogus value. [Bug 1586470] 2006-11-04 Don Porter * generic/tclStringObj.c: Changed Tcl_ObjPrintf() response to an invalid format specifier string. No longer panics; now produces an error message as output. TIP#274 IMPLEMENTATION * generic/tclParseExpr.c: Exponentiation operator is now right * tests/expr.test: associative. [Patch 1556802] 2006-11-03 Miguel Sofer * generic/tclBasic.c (TEOVI): fix por possible leak of a Command in the presence of execution traces that delete it. * generic/tclBasic.c (TEOVI): * tests/trace.test (trace-21.11): fix for [Bug 1590232], execution traces may cause a second command resolution in the wrong namespace. 2006-11-03 Donal K. Fellows * tests/event.test (event-11.5): Rewrote tests to stop Tcl from * tests/io.test (multiple tests): opening sockets that are * tests/ioCmd.test (iocmd-15.1,16,17): reachable from outside hosts * tests/iogt.test (__echo_srv__.tcl): where not necessary. This is * tests/socket.test (multiple tests): noticably annoying on some * tests/unixInit.test (unixInit-1.2): systems (e.g., Windows). 2006-11-02 Daniel Steffen * macosx/Tcl.xcodeproj/project.pbxproj: check autoconf/autoheader exit status and stop build if they fail. 2006-11-02 Jeff Hobbs * doc/ParseCmd.3, doc/Tcl.n, doc/eval.n, doc/exec.n: * doc/fconfigure.n, doc/interp.n, doc/unknown.n: * library/auto.tcl, library/init.tcl, library/package.tcl: * library/safe.tcl, library/tm.tcl, library/msgcat/msgcat.tcl: * tests/all.tcl, tests/basic.test, tests/cmdInfo.test: * tests/compile.test, tests/encoding.test, tests/execute.test: * tests/fCmd.test, tests/http.test, tests/init.test: * tests/interp.test, tests/io.test, tests/ioUtil.test: * tests/iogt.test, tests/namespace-old.test, tests/namespace.test: * tests/parse.test, tests/pkg.test, tests/pkgMkIndex.test: * tests/proc.test, tests/reg.test, tests/trace.test: * tests/upvar.test, tests/winConsole.test, tests/winFCmd.test: * tools/tclZIC.tcl: * generic/tclParse.c (Tcl_ParseCommand): Replace {expand} with {*} officially (TIP #293). Leave -DALLOW_EXPAND=0|1 option to keep {expand} syntax for transition users. [Bug 1589629] 2006-11-02 Donal K. Fellows * generic/tclBasic.c, generic/tclInterp.c, generic/tclProc.c: Silence warnings from gcc over signed/unsigned and TclStackAlloc(). * generic/tclCmdMZ.c: Update to more compact and clearer coding style. 2006-11-02 Don Porter * generic/tclCmdAH.c: Further revisions to produce the routines * generic/tclInt.h: TclFormat() and TclAppendFormatToObj() that * generic/tclNamesp.c: accept (objc, objv) arguments rather than * generic/tclStringObj.c: any varargs stuff. * generic/tclBasic.c: Further revised TclAppendPrintToObj() and * generic/tclCkalloc.c: TclObjPrintf() routines to panic when unable * generic/tclCmdAH.c: to complete their formatting operations, * generic/tclCmdIL.c: rather than report an error message. This * generic/tclCmdMZ.c: means an interp argument for error message * generic/tclDictObj.c: recording is no longer needed, further * generic/tclExecute.c: simplifying the interface for callers. * generic/tclIORChan.c: * generic/tclIOUtil.c: * generic/tclInt.h: * generic/tclMain.c: * generic/tclNamesp.c: * generic/tclParseExpr.c: * generic/tclPkg.c: * generic/tclProc.c: * generic/tclStringObj.c: * generic/tclTimer.c: * generic/tclUtil.c: * unix/tclUnixFCmd.c: 2006-11-02 Donal K. Fellows * tests/winPipe.test (winpipe-4.[2345]): Made robust when run in directory with spaces in its name. * generic/tclCmdAH.c: Clean up uses of cast NULLs. * generic/tclInterp.c (AliasObjCmd): Added more explanatory comments. * generic/tclBasic.c (TclEvalObjvInternal): Rewrote so that comments are relevant and informative once more. Also made the unknown handler processing use the Tcl execution stack for working space, and not the general heap. 2006-11-01 Daniel Steffen * unix/tclUnixPort.h: ensure MODULE_SCOPE is defined before use, so that tclPort.h can once again be included without tclInt.h. * generic/tclEnv.c (Darwin): mark _environ symbol as unexported even when MODULE_SCOPE != __private_extern__. 2006-10-31 Don Porter * generic/tclBasic.c: Refactored and renamed the routines * generic/tclCkalloc.c: TclObjPrintf, TclFormatObj, and * generic/tclCmdAH.c: TclFormatToErrorInfo to a new set of routines * generic/tclCmdIL.c: TclAppendPrintfToObj, TclAppendFormatToObj, * generic/tclCmdMZ.c: TclObjPrintf, and TclObjFormat, with the * generic/tclDictObj.c: intent of making the latter list, plus * generic/tclExecute.c: TclAppendLimitedToObj and * generic/tclIORChan.c: TclAppendObjToErrorInfo, public via a revised * generic/tclIOUtil.c: TIP 270. * generic/tclInt.h: * generic/tclMain.c: * generic/tclNamesp.c: * generic/tclParseExpr.c: * generic/tclPkg.c: * generic/tclProc.c: * generic/tclStringObj.c: * generic/tclTimer.c: * generic/tclUtil.c: * unix/tclUnixFCmd.c: 2006-10-31 Miguel Sofer * generic/tclBasic.c, generic/tcl.h, generic/tclInterp.c: * generic/tclNamesp.c: removing the flag bit TCL_EVAL_NOREWRITE, the last remnant of the callObjc/v fiasco. It is not needed, as it is now always set and checked or'ed with TCL_EVAL_INVOKE. 2006-10-31 Pat Thoyts * win/rules.vc: Fix for [Bug 1582769] - options conflict with VC2003. 2006-10-31 Donal K. Fellows * generic/tclBasic.c, generic/tclNamesp.c, generic/tclProc.c: * generic/tclInt.h: Removed the callObjc and callObjv fields from the Interp structure. They did not function correctly and made other parts of the core amazingly complex, resulting in a substantive change to [info level] behaviour. [Bug 1587618] * library/clock.tcl: Removed use of [info level 0] for calculating the command name as used by the user and replace with a literal. What's there now is sucky, but at least appears to be right to most users. * tests/namespace.test (namespace-42.7,namespace-47.1): Reverted changes to these tests. * tests/info.test (info-9.11,info-9.12): Added knownBug constraint since these tests require a different behaviour of [info level] than is possible because of other dependencies. 2006-10-30 Jeff Hobbs * tools/tcltk-man2html.tcl (option-toc): handle any kind of options defined toc section (needed for ttk docs) 2006-10-30 Miguel Sofer * generic/tclBasic.c (TEOVI): insured that the interp's callObjc/v fields are restored after traces run, as they be spoiled. This was causing a segfault in tcllib's profiler tests. 2006-10-30 Don Porter * generic/tclExecute.c (INST_MOD): Corrected improper testing of the * tests/expr.test: sign of bignums when applying Tcl's division rules. Thanks to Peter Spjuth. [Bug 1585704] 2006-10-29 Miguel Sofer * generic/tclNamesp.c (EnsembleImplementationCmd): * tests/namespace.test (47.7-8): reverted a wrong "optimisation" that completely broke snit; added two tests. 2006-10-28 Donal K. Fellows * generic/tclProc.c (ObjInterpProcEx, TclObjInterpProcCore): Split the core of procedures to make it easier to build procedure-like code without going through horrible contortions. This is the last critical component to make advanced OO systems workable as simple loadable extensions. TOIPC is now in the internal stub table. (MakeProcError, MakeLambdaError): Refactored ProcessProcResultCode to be simpler, some of which goes to TclObjInterpProcCore, and the rest of which is now in these far simpler routines which just do errorInfo stack generation for different types of procedure-like entity. * tests/apply.test (apply-5.1): Updated to expect the more informative form of message. 2006-10-27 Donal K. Fellows * generic/tclVar.c (HasLocalVars): New macro to make various bits and pieces cleaner. * generic/tclNamesp.c (TclSetNsPath): Expose SetNsPath() through internal stubs table with semi-external name. * generic/tclInt.h (CallFrame): Add a field for handling context data for extensions (like object systems) that should be tied to a call frame (and not a command or interpreter). * generic/tclBasic.c (TclRenameCommand): Change to take CONST args; they were only ever used in a constant way anyway, so this appears to be a spot that was missed during TIP#27 work. 2006-10-26 Miguel Sofer * generic/tclProc.c (SetLambdaFromAny): minor change, eliminate redundant call to Tcl_GetString (thanks aku). * generic/tclInterp.c (ApplyObjCmd): * generic/tclNamesp.c (EnsembleImplementationCmd): replaced ckalloc (heap) with TclStackAlloc (execution stack). 2006-10-24 Miguel Sofer * tests/info.test (info-9.11-12): tests for [Bug 1577492] * tests/apply.test (apply-4.3-5): tests for [Bug 1574835] * generic/tclProc.c (ObjInterpProcEx): disable itcl hacks for calls from ApplyObjCmd (islambda==1), as they mess apply's error messages [Bug 1583266] 2006-10-23 Miguel Sofer * generic/tclProc.c (ApplyObjCmd): fix wrong#args for apply by using the ensemble rewrite engine. [Bug 1574835] * generic/tclInterp.c (AliasObjCmd): previous commit missed usage of TCL_EVAL_NOREWRITE for aliases. * generic/tclBasic.c (TclEvalObjvInternal): removed redundant check for ensembles. [Bug 1577628] * library/clock.tcl (format, scan): corrected wrong # args messages to * tests/clock.test (3.1, 34.1): make use of the new rewrite capabilities of [info level] * generic/tcl.h: Lets TEOV update the iPtr->callObj[cv] new * generic/tclBasic.c: fields, except when the flag bit * generic/tclInt.h: TCL_EVAL_NOREWRITE is present. These values * generic/tclNamesp.c: are used by Tcl_PushCallFrame to initialise * generic/tclProc.c: the frame's obj[cv] fields, and allows * tests/namespace.test: [info level] to know and use ensemble rewrites. [Bug 1577492] ***POTENTIAL INCOMPATIBILITY*** The return value from [info level 0] on interp alias calls is changed: previously returned the target command (including curried values), now returns the source - what was actually called. 2006-10-23 Miguel Sofer * generic/tcl.h: Modified the Tcl call stack so there is * generic/tclBasic.c: always a valid CallFrame, even at level 0 * generic/tclCmdIL.c: [Patch 1577278]. Most of the changes * generic/tclInt.h: involve removing tests for a NULL * generic/tclNamesp.c: iPtr->(var)framePtr. There is now a * generic/tclObj.c: CallFrame pushed at interp creation with a * generic/tclProc.c: pointer to it stored in iPtr->rootFramePtr. * generic/tclTrace.c: A second unused field in Interp is * generic/tclVar.c: hijacked to enable further functionality, currently unused (but with several FRQs depending on it). ***POTENTIAL INCOMPATIBILITY*** Any user that includes tclInt.h and needs to determine if it is running at level 0 should change (iPtr->varFramePtr == NULL) to (iPtr->varFramePtr == iPtr->rootFramePtr). 2006-10-23 Don Porter * README: Bump version number to 8.5a6 * generic/tcl.h: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/README.binary: * win/configure.in: * unix/configure: autoconf-2.59 * win/configure: 2006-10-21 Miguel Sofer * generic/tcl.h, generic/tclHash.c: Tcl_FindHashEntry now calls Tcl_CreateHashEntry with a newPtr set to NULL: this would have caused a segfault previously and eliminates duplicated code. A macro has been added to tcl.h (only used when TCL_PRESERVE_BINARY_COMPATABALITY is not set - i.e., not by default). 2006-10-20 Reinhard Max * unix/configure.in: Added autodetection for OS-supplied timezone * unix/Makefile.in: files and configure switches to override the * unix/configure: detected default. 2006-10-20 Daniel Steffen *** 8.5a5 TAGGED FOR RELEASE *** * tools/tcltk-man2html.tcl: add support for alpha & beta versions to useversion glob pattern. [Bug 1579941] 2006-10-18 Don Porter * changes: 8.5a5 release date set * doc/Encoding.3: Missing doc updates (mostly Table of * doc/Ensemble.3: Contents) exposed by `make checkdoc` * doc/FileSystem.3: * doc/GetTime.3: * doc/PkgRequire.3: 2006-10-17 Miguel Sofer * generic/tclInterp.c (ApplyObjCmd): fixed bad error in 2006-10-12 commit: interp released too early. Spotted by mistachkin. 2006-10-16 Miguel Sofer * tclProc.c (SetLambdaFromAny): * tests/apply.test (9.1-9.2): plugged intrep leak [Bug 1578454], found by mjanssen. 2006-10-16 Andreas Kupries * generic/tclBasic.c: Moved TIP#219 cleanup to DeleteInterpProc. 2006-10-16 Daniel Steffen * changes: updates for 8.5a5 release. * unix/tclUnixThrd.c (TclpThreadGetStackSize): Darwin: fix for main thread, where pthread_get_stacksize_np() returns incorrect info. * macosx/GNUmakefile: don't redo prebinding of non-prebound binaires. 2006-10-16 Don Porter * generic/tclPkg.c (ExactRequirement): Plugged memory leak. Also changed Tcl_Alloc()/Tcl_Free() calls to ckalloc()/ckfree() for easier memory debugging in the future. [Bug 1568373] * library/tcltest/tcltest.tcl: Revise tcltest bump to 2.3a1. * library/tcltest/pkgIndex.tcl: This permits more features to be * unix/Makefile.in: added to tcltest before we reach version 2.3.0 * win/Makefile.in: best timed to match the release of Tcl 8.5.0. * win/makefile.vc: This also serves as a demo of TIP 268 features 2006-10-13 Colin McCormack * win/tclWinFile.c: corrected erroneous attempt to protect against NULL return from Tcl_FSGetNormalizedPath per [Bug 1548263] causing [Bug 1575837]. * win/tclWinFile.c: alfredd supplied patch to fix [Bug 1575837] 2006-10-13 Daniel Steffen * unix/tclUnixThrd.c (TclpThreadGetStackSize): on Darwin, use * unix/tcl.m4: pthread_get_stacksize_np() API to get thread stack size * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 2006-10-12 Miguel Sofer * generic/tclInterp.c (ApplyObjCmd): * tests/interp.test (interp-14.5-10): made [interp alias] use the ensemble rewrite machinery to produce better error messages [Bug 1576006] 2006-10-12 David Gravereaux * win/nmakehlp.c: Replaced all wnsprintf() calls with snprintf(). wnsprintf was not in my shwlapi header file (VC++6) 2006-10-11 Don Porter * generic/tclPkg.c (Tcl_PackageRequireEx): Corrected crash when argument version=NULL passed in. 2006-10-10 Don Porter * changes: Updates for 8.5a5 release. * generic/tclNamespace.c (TclTeardownNamespace): After the commandPathSourceList of a namespace is cleared, set the commandPathSourceList to NULL so we don't try to walk the list a second time, possibly after it is freed. [Bug 1566526] * tests/namespace.test (namespace-51.16): Added test. 2006-10-09 Miguel Sofer * doc/UpVar.3: brough the docs in accordance to the code. Ever since 8.0, Tcl_UpVar(2)? accepts TCL_NAMESPACE_ONLY as a flag value, and var-3.4 tests for proper behaviour. The docs only allowed 0 and TCL_GLOBAL_ONLY. [Bug 1574099] 2006-10-09 Miguel Sofer * tests/*.test: updated all tests to refer explicitly to the global variables ::errorInfo, ::errorCode, ::env and ::tcl_platform: many were relying on the alternative lookup in the global namespace, that feature is tested specifically in namespace and variable tests. The modified testfiles are: apply.test, basic.test, case.test, cmdIL.test, cmdMZ.test, compExpr-old.test, error.test, eval.test, event.test, expr.test, fileSystem.test, for.test, http.test, if.test, incr-old.test, incr.test, interp.test, io.test, ioCmd.test, load.test, misc.test, namespace.test, parse.test, parseOld.test, pkg.test, proc-old.test, set.test, switch.test, tcltest.test, thread.test, var.test, while-old.test, while.test. 2006-10-06 Pat Thoyts * win/rules.vc: [Bug 1571954] avoid /RTCc flag with MSVC8 2006-10-06 Pat Thoyts * doc/binary.n: TIP #275: Support unsigned values in binary * generic/tclBinary.c: command. Tests and documentation updated. * tests/binary.test: 2006-10-05 Andreas Kupries * library/tm.tcl: Fixed bug in TIP #189 implementation, now allowing '_' in module names. 2006-10-05 Jeff Hobbs * library/http/http.tcl (http::geturl): only do geturl url rfc 3986 validity checking if $::http::strict is true (default true for 8.5). [Bug 1560506] * generic/tcl.h: note limitation on changing Tcl_UniChar size * generic/tclEncoding.c (UtfToUnicodeProc, UnicodeToUtfProc): * tests/encoding.test (encoding-16.1): fix alignment issues in unicode <> utf conversion procs. [Bug 1122671] 2006-10-05 Miguel Sofer * generic/tclVar.c (Tcl_LappendObjCmd): * tests/append.test(4.21-22): fix for longstanding [Bug 1570718], lappending nothing to non-list. Reported by lvirden 2006-10-04 Kevin B. Kenny * tzdata/: Olson's tzdata2006m. 2006-10-01 Kevin B. Kenny * tests/clock.test (clock-49.2): Removed a locale dependency that caused a spurious failure in the German locale. [Bug 1567956] 2006-10-01 Miguel Sofer * doc/Eval.3 (TclEvalObjv): added note on refCount management for the elements of objv. [Bug 730244] 2006-10-01 Pat Thoyts * win/tclWinFile.c: Handle possible missing define. * win/tclWinFile.c (TclpUtime): [Bug 1420432] file mtime fails for * tests/cmdAH.test: directories on windows * tests/winFile.test: Handle Msys environment a little differently in getuser function. [Bug 1567956] 2006-09-30 Miguel Sofer * generic/tclUtil.c (Tcl_SplitList): optimisation, [Patch 1344747] by dgp. * generic/tclInt.decls: * generic/tclInt.h: * generic/tclIntDecls.h: * generic/tclObj.c: * generic/tclStubInit.c: added an internal function TclObjBeingDeleted to provide info as to the reason for the loss of an internal rep. [FR 1512138] * generic/tclCompile.c: * generic/tclHistory.c: * generic/tclInt.h: * generic/tclProc.c: made Tcl_RecordAndEvalObj not call "history" if it has been redefined to an empty proc, in order to reduce the noise when debugging [FR 1190441]. Moved TclCompileNoOp from tclProc.c to tclCompile.c 2006-09-28 Andreas Kupries * generic/tclPkg.c (CompareVersions): Bugfix. Check string lengths * tests/pkg.test: before comparison. The shorter string is the smaller number. Added testcases as well. Interestingly all existing test cases for vcompare compared numbers of the same length with each other. [Bug 1563836] 2006-09-28 Miguel Sofer * generic/tclIO.c (Tcl_GetsObj): added two test'n'panic guards for possible NULL derefs, [Bug 1566382] and coverity #33. 2006-09-27 Don Porter * generic/tclExecute.c: Corrected error in INST_LSHIFT in the * tests/expr.test: calculation done to determine whether a shift in the (long int) type is possible. The calculation had literal value "1" where it needed a value "1L" to compute the correct result. Error detected via testing with the math::bigfloat package [Bug 1567222] * generic/tclPkg.c (CompareVersion): Flatten strcmp() results to {-1, 0, 1} to match expectations of CompareVersion() callers. 2006-09-27 Miguel Sofer * generic/regc_color.c (singleton): * generic/regc_cvec.c (addmcce): * generic/regcomp.c (compile, dovec): the static function addmcce does nothing when called with two NULL pointers; the only call is by compile with two NULL pointers (regcomp.c #includes regc_cvec.c). Large parts (all?) the code for mcce (multi character collating element) that we do not use is ifdef'ed out with the macro REGEXP_MCCE_ENABLE. This silences coverity bugs 7, 16, 80 * generic/regc_color.c (uncolorchain): * generic/regc_nfa.c (freearc): changed tests and asserts to equivalent formulation, designed to avoid an explicit comparison to NULL and satisfy coverity that 6 and 9 are not bugs. 2006-09-27 Andreas Kupries * tests/pkg.test: Added test for version comparison at the 32bit boundary. [Bug 1563836] * generic/tclPkg.c: Rewrote CompareVersion to perform string comparison instead of numeric. This breaks through the 32bit limit on version numbers. See code for details (handling of leading zeros, signs, etc.). un-CONSTed some arguments of CompareVersions, RequirementSatisfied, and AllRequirementsSatisfied. The new compare modifies the string (temporary string terminators). All callers use heap-allocated ver-intreps, so we are good with that. [Bug 1563836] 2006-09-27 Miguel Sofer * generic/tclFileName.c (TclGlob): added a panic for a call with TCL_GLOBMODE_TAILS and pathPrefix==NULL. This would cause a segfault, as found by coverity #26. 2006-09-26 Kevin B. Kenny * doc/Encoding.3: Added covariant 'const' qualifier for the * generic/tcl.decls: Tcl_EncodingType argument to * generic/tclEncoding.c: Tcl_CreateEncoding. [Further TIP#27 work.] * generic/tclDecls.h: Reran 'make genstubs'. 2006-09-26 Pat Thoyts * win/makefile.vc: Additional compiler flags and amd64 support. * win/nmakehlp.c: * win/rules.vc: 2006-09-26 Don Porter * generic/tcl.h: As 2006-09-22 commit from Donal K. Fellows demonstrates, "#define NULL 0" is just wrong, and as a quotable chat figure observed, "If NULL isn't defined, we're not using a C compiler" Improper fallback definition of NULL removed. 2006-09-25 Pat Thoyts * generic/tcl.h: More fixing which struct stat to refer to. * generic/tclGetDate.y: Some casts from time_t to int required. * generic/tclTimer.c: Tcl_Time structure members are longs. * win/makefile.vc: Support for varying compiler options * win/rules.vc: and build to platform-specific subdirs. 2006-09-25 Andreas Kupries * generic/tclIO.c (Tcl_StackChannel): Fixed [Bug 1564642], aka coverity #51. Extended loop condition, added checking for NULL to prevent seg.fault. 2006-09-25 Andreas Kupries * doc/package.n: Fixed nits reported by Daniel Steffen in the TIP#268 changes. 2006-09-25 Kevin B. Kenny * generic/tclNotify.c (Tcl_DeleteEvents): Simplified the code in hopes of making the invariants clearer and proving to Coverity that the event queue memory is managed correctly. 2006-09-25 Donal K. Fellows * generic/tclNotify.c (Tcl_DeleteEvents): Make it clear what happens when the event queue is mismanaged. [Bug 1564677], coverity bug #10. 2006-09-24 Miguel Sofer * generic/tclParse.c (Tcl_ParseCommand): also return an error if start==NULL and numBytes<0. This is coverity's bug #20 * generic/tclStringObj.c (STRING_SIZE): fix allocation for 0-length strings. This is coverity's bugs #54-5 2006-09-22 Andreas Kupries * generic/tclInt.h: Moved TIP#268's field 'packagePrefer' to the end of the structure, for better backward compatibility. 2006-09-22 Andreas Kupries TIP#268 IMPLEMENTATION * generic/tclDecls.h: Regenerated from tcl.decls. * generic/tclStubInit.c: * doc/PkgRequire.3: Documentation of extended API, extended testsuite. * doc/package.n: * tests/pkg.test: * generic/tcl.decls: Implementation. * generic/tclBasic.c: * generic/tclConfig.c: * generic/tclInt.h: * generic/tclPkg.c: * generic/tclTest.c: * generic/tclTomMathInterface.c: * library/init.tcl: * library/package.tcl: * library/tm.tcl: 2006-09-22 Donal K. Fellows * generic/tclThreadTest.c (TclCreateThread): Use NULL instead of 0 as end-of-strings marker to Tcl_AppendResult; the difference matters on 64-bit machines. [Bug 1562528] 2006-09-21 Don Porter * generic/tclUtil.c: Dropped ParseInteger() routine. TclParseNumber covers the task just fine. 2006-09-19 Donal K. Fellows * generic/tclEvent.c (Tcl_VwaitObjCmd): Rewrite so that an exceeded limit trapped in a vwait cannot cause a dangerous dangling trace. 2006-09-19 Don Porter * generic/tclExecute.c (INST_EXPON): Native type overflow detection * tests/expr.test: was completely broken. Falling back on use of bignums for all non-trivial ** calculations until native-type-constrained special cases can be done carefully and correctly. [Bug 1561260] 2006-09-15 Jeff Hobbs * library/http/http.tcl: Change " " -> "+" url encoding mapping * library/http/pkgIndex.tcl: to " " -> "%20" as per RFC 3986. * tests/http.test (http-5.1): bump http to 2.5.3 * unix/Makefile.in: * win/Makefile.in: 2006-09-12 Andreas Kupries * unix/configure.in (HAVE_MTSAFE_GETHOST*): Modified to recognize HP-UX 11.00 and beyond as having mt-safe implementations of the gethost functions. * unix/configure: Regenerated, using autoconf 2.59 * unix/tclUnixCompat.c (PadBuffer): Fixed bug in calculation of the increment needed to align the pointer, and added documentation explaining why the macro is implemented as it is. 2006-09-11 Pat Thoyts * win/rules.vc: Updated to install http, tcltest and msgcat as * win/makefile.vc: Tcl Modules (as per Makefile.in). * win/makefile.vc: Added tommath_(super)class headers. 2006-09-11 Andreas Kupries * unix/Makefile.in (install-libraries): Fixed typo tcltest 2.3.9 -> 2.3.0. 2006-09-11 Daniel Steffen * unix/tclUnixCompat.c: make compatLock static and only declare it when it will actually be used; #ifdef parts of TSD that are not always needed; adjust #ifdefs to cover all possible cases; fix whitespace. 2006-09-11 Andreas Kupries * tests/msgcat.test: Bumped version in auxiliary files as well. * doc/msgcat.n: 2006-09-11 Kevin B. Kenny * unix/Makefile.in: Bumped msgcat version to 1.4.2 to be * win/Makefile.in: consistent with dgp's commits of 2006-09-10. 2006-09-11 Don Porter * library/msgcat/msgcat.tcl: Removed some unneeded [uplevel]s. 2006-09-10 Don Porter * generic/tclExecute.c: Corrected INST_EXPON flaw that treated * tests/expr.test: $x**1 as $x**3. [Bug 1555371] * doc/tcltest.n: Bump to version tcltest 2.3.0 to * library/tcltest/pkgIndex.tcl: account for new "-verbose line" * library/tcltest/tcltest.tcl: feature. * unix/Makefile.in: * win/Makefile.in: * win/makefile.bc: * win/makefile.vc: * library/msgcat/msgcat.tcl: Bump to version msgcat 1.4.2 to * library/msgcat/pkgIndex.tcl: account for modifications. 2006-09-10 Daniel Steffen * library/msgcat/msgcat.tcl (msgcat::Init): on Darwin, add fallback of * tests/msgcat.test: default msgcat locale to * unix/tclUnixInit.c (TclpSetVariables): current CFLocale identifier if available (via private ::tcl::mac::locale global, set at interp init when on Mac OS X 10.3 or later with CoreFoundation). * library/tcltest/tcltest.tcl: add 'line' verbose level: prints source * doc/tcltest.n: file line information of failing tests. * macosx/Tcl.xcodeproj/project.pbxproj: add new tclUnixCompat.c file; revise tests target to use new tcltest 'line' verbose level. * unix/configure.in: add descriptions to new AC_DEFINEs for MT-safe. * unix/tcl.m4: add caching to new SC_TCL_* macros for MT-safe wrappers * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 2006-09-08 Zoran Vasiljevic * unix/tclUnixCompat.c: Added fallback to gethostbyname() and gethostbyaddr() if the implementation is known to be MT-safe (currently for Darwin 6 or later only). * unix/configure.in: Assume gethostbyname() and gethostbyaddr() are MT-safe starting with Darwin 6 (Mac OSX 10.2). * unix/configure: Regenerated with autoconf V2.59 2006-09-08 Andreas Kupries * unix/tclUnixCompat.c: Fixed conditions for CopyArray/CopyString, and CopyHostent. Also fixed bad var names in TclpGetHostByName. 2006-09-07 Zoran Vasiljevic * unix/tclUnixCompat.c: Added fallback to MT-unsafe library calls if TCL_THREADS is not defined. Fixed alignment of arrays copied by CopyArray() to be on the sizeof(char *) boundary. 2006-09-07 Zoran Vasiljevic * unix/tclUnixChan.c: Rewritten MT-safe wrappers to return ptrs to * unix/tclUnixCompat.c: TSD storage making them all look like their * unix/tclUnixFCmd.c: MT-unsafe pendants API-wise. * unix/tclUnixPort.h: * unix/tclUnixSock.c: 2006-09-06 Zoran Vasiljevic * unix/tclUnixChan.c: Added TCL_THREADS ifdef'ed usage of MT-safe * unix/tclUnixFCmd.c: calls like: getpwuid, getpwnam, getgrgid, * unix/tclUnixSock.c: getgrnam, gethostbyname and gethostbyaddr. * unix/tclUnixPort.h: See [Bug 999544] * unix/Makefile.in: * unix/configure.in: * unix/tcl.m4: * unix/configure: Regenerated. * unix/tclUnixCompat.c: New file containing MT-safe implementation of some library calls. 2006-09-04 Don Porter * generic/tclCompExpr.c: Removed much complexity that is no longer needed. * tests/main.text (Tcl_Main-4.4): Test corrected to not be timing sensitive to the Bug 1481986 fix. [Bug 1550858] 2006-09-04 Jeff Hobbs * doc/package.n: correct package example 2006-08-31 Don Porter * generic/tclCompExpr.c: Corrected flawed logic for disabling the INST_TRY_CVT_TO_NUMERIC instruction at the end of an expression when function arguments contain operators. [Bug 1541274] * tests/expr-old.test: The remaining failing tests reported in * tests/expr.test: [Bug 1381715] are all new in Tcl 8.5, so there's really no issue of compatibility with Tcl 8.4 result to deal with. Fixed by updating tests to expect 8.5 results. 2006-08-29 Don Porter * generic/tclParseExpr.c: Dropped the old expr parser. 2006-08-30 Jeff Hobbs * generic/tclBasic.c (Tcl_CreateInterp): init iPtr->threadId * win/tclWinChan.c [Bug 819667] Improve logic for identifying COM ports. * generic/tclIOGT.c (ExecuteCallback): * generic/tclPkg.c (Tcl_PkgRequireEx): replace Tcl_GlobalEval(Obj) with more efficient Tcl_Eval(Obj)Ex * unix/Makefile.in (valgrindshell): add valgrindshell target and update default VALGRINDARGS. User can override, or add to it with VALGRIND_OPTS env var. * generic/tclFileName.c (DoGlob): match incrs with decrs. 2006-08-29 Don Porter * generic/tclParseExpr.c: Use the "parent" field of orphan ExprNodes to store the closure of left pointers. This lets us avoid repeated re-scanning leftward for the left boundary of subexpressions, which in worst case led to near O(N^2) runtime. 2006-08-29 Joe Mistachkin * unix/tclUnixInit.c: Fixed the issue (typo) that was causing * unix/tclUnixThrd.c (TclpThreadGetStackSize): stack.test to fail on FreeBSD (and possibly other Unix platforms). 2006-08-29 Colin McCormack * generic/tclIOUtil.c: Added test for NULL return from * generic/tclPathObj.c: Tcl_FSGetNormalizedPath which was causing * unix/tclUnixFile.c: segv's per [Bug 1548263] * win/tclWinFCmd.c: * win/tclWinFile.c: 2006-08-28 Kevin B. Kenny * library/tzdata/America/Havana: Regenerated from Olson's * library/tzdata/America/Tegucigalpa: tzdata2006k. * library/tzdata/Asia/Gaza: 2006-08-28 Don Porter * generic/tclStringObj.c: Revised ObjPrintfVA to take care to * generic/tclParseExpr.c: copy only whole characters when doing %s formatting. This relieves callers of TclObjPrintf() and TclFormatToErrorInfo() from needing to fix arguments to character boundaries. Tcl_ParseExpr() simplified by taking advantage. [Bug 1547786] * generic/tclStringObj.c: Corrected TclFormatObj's failure to count up the number of arguments required by examining the format string. [Bug 1547681] 2006-08-27 Joe Mistachkin * generic/tclClock.c (ClockClicksObjCmd): Fix nested macro breakage with TCL_MEM_DEBUG enabled. [Bug 1547662] 2006-08-26 Miguel Sofer * doc/namespace.n: * generic/tclNamesp.c: * tests/upvar.test: bugfix, docs clarification and new tests for [namespace upvar] as follow up to [Bug 1546833], reported by Will Duquette. 2006-08-24 Kevin B. Kenny * library/tzdata: Regenerated, including several new files, from Olson's tzdata2006j. * library/clock.tcl: * tests/clock.test: Removed an early testing hack that allowed loading 'registry' from the build tree rather than an installed one. This is a workaround for [Bug 15232730], which remains open because it's a symptom of a deeper underlying problem. 2006-08-23 Don Porter * generic/tclParseExpr.c: Minimal collection of new tests * tests/parseExpr.test: testing the error messages of the new expr parser. Several bug fixes and code simplifications that appeared during that effort. 2006-08-21 Don Porter * generic/tclIOUtil.c: Revisions to complete the thread finalization of the cwdPathPtr. [Bug 1536142] * generic/tclParseExpr.c: Revised mistaken call to TclCheckBadOctal(), so both [expr 08] and [expr 08z] have same additional info in error message. * tests/compExpr-old.test: Update existing tests to not fail with * tests/compExpr.test: the new expr parser. * tests/compile.test: * tests/expr-old.test: * tests/expr.test: * tests/for.test: * tests/if.test: * tests/parseExpr.test: * tests/while.test: 2006-08-21 Donal K. Fellows * win/Makefile.in (gdb): Make this target work so that debugging an msys build is possible. 2006-08-21 Daniel Steffen * macosx/tclMacOSXNotify.c (Tcl_WaitForEvent): if the run loop is already running (e.g. if Tcl_WaitForEvent was called recursively), re-run it in a custom run loop mode containing only the source for the notifier thread, otherwise wakeups from other sources added to the common run loop modes might get lost. * unix/tclUnixNotfy.c (Tcl_WaitForEvent): 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 on that platform. [Bug 1457797] * generic/tclClock.c (ClockClicksObjCmd): add support for Darwin * generic/tclCmdMZ.c (Tcl_TimeObjCmd): nanosecond resolution timer * generic/tclInt.h: to [clock clicks] and [time] * unix/configure.in (Darwin): when TCL_WIDE_CLICKS defined * unix/tclUnixTime.c (TclpGetWideClicks, TclpWideClicksToNanoseconds): * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 * unix/tclUnixPort.h (Darwin): override potentially faulty configure detection of termios availability in all cases, since termios is known to be present on all Mac OS X releases since 10.0. [Bug 497147] 2006-08-18 Daniel Steffen * unix/tcl.m4 (Darwin): add support for --enable-64bit on x86_64, for universal builds including x86_64, for 64-bit CoreFoundation on Leopard and for use of -mmacosx-version-min instead of MACOSX_DEPLOYMENT_TARGET * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 * generic/tcl.h: add fixes for building on Leopard and * unix/tclUnixPort.h: support for 64-bit CoreFoundation on Leopard * macosx/tclMacOSXFCmd.c: * unix/tclUnixPort.h: on Darwin x86_64, disable use of vfork as it causes execve to fail intermittently. (rdar://4685553) * generic/tclTomMath.h: on Darwin 64-bit, for now disable use of 128-bit arithmetic through __attribute__ ((mode(TI))), as it leads to link errors due to missing fallbacks. (rdar://4685527) * macosx/Tcl.xcodeproj/project.pbxproj: add x86_64 to universal build, switch native release targets to use DWARF with dSYM, Xcode 3.0 changes * macosx/README: updates for x86_64 and Xcode 2.4. * macosx/Tcl.xcodeproj/default.pbxuser: add test suite target that * macosx/Tcl.xcodeproj/project.pbxproj: runs the tcl test suite at build time and shows clickable test suite errors in the GUI build window. * tests/macOSXFCmd.test: fix use of deprecated resource fork paths. * unix/tclUnixInit.c (TclpInitLibraryPath): move code that is only needed when TCL_LIBRARY is defined to run only in that case. * generic/tclLink.c (LinkTraceProc): fix 64-bit signed-with-unsigned comparison warning from gcc4 -Wextra. * unix/tclUnixChan.c (TclUnixWaitForFile): with timeout < 0, if select() returns early (e.g. due to a signal), call it again instead of returning a timeout result. Fixes intermittent event-13.8 failures. 2006-08-17 Don Porter * generic/tclCompile.c: Revised the new set of expression * generic/tclParseExpr.c: parse error messages. 2006-08-16 Don Porter * generic/tclParseExpr.c: Replace PrecedenceOf() function with prec[] static array. 2006-08-14 Donal K. Fellows * library/clock.tcl (::tcl::clock::add): Added missing braces to clockval validation code. Pointed out on comp.lang.tcl. 2006-08-11 Donal K. Fellows * generic/tclNamesp.c: Improvements in buffer management to make namespace creation faster. Plus selected other minor improvements to code quality. [Patch 1352382] 2006-08-10 Donal K. Fellows Misc patches to make code more efficient. [Bug 1530474] (afredd) * generic/*.c, macosx/tclMacOSXNotify.c, unix/tclUnixNotfy.c, * win/tclWinThrd.c: Tidy up invokations of Tcl_Panic() to promote string constant sharing and consistent style. * generic/tclBasic.c (Tcl_CreateInterp): More efficient handling of * generic/tclClock.c (TclClockInit): registration of commands not in global namespace. * generic/tclVar.c (Tcl_UnsetObjCmd): Remove unreachable clause. 2006-08-09 Don Porter * generic/tclEncoding.c: Replace buffer copy in for loop with call to memcpy(). Thanks to afredd. [Patch 1530262] 2006-08-09 Donal K. Fellows * generic/tclCmdIL.c (Tcl_LassignObjCmd): Make the wrong#args message a bit more consistent with those used elsewhere. [Bug 1534628] * generic/tclDictObj.c (DictForCmd): Stop crash when attempting to iterate over an invalid dictionary. [Bug 1531184] * doc/ParseCmd.3, doc/expr.n, doc/set.n, doc/subst.n, doc/switch.n: * doc/tclvars.n: Ensure that uses of [expr] in documentation examples are also good style (with braces) unless otherwise necessary. [Bug 1526581] 2006-08-03 Daniel Steffen * unix/tclUnixPipe.c (TclpCreateProcess): for USE_VFORK: ensure standard channels are initialized before vfork() so that the child doesn't potentially corrupt global state in the parent's address space * tests/compExpr-old.test: add 'oldExprParser' constraint to all tests * tests/compExpr.test: that depend on the exact format of the * tests/compile.test: error messages of the pre-2006-07-05 * tests/expr-old.test: expression parser. The constraint is on by * tests/expr.test: default (i.e those tests still fail), but * tests/for.test: can be turned off by passing '-constraints * tests/if.test: newExprParser' to tcltest, which will skip * tests/parseExpr.test: the 196 failing tests in the testsuite that * tests/while.test: are caused by the new expression parser error messages. 2006-07-31 Kevin B. Kenny * generic/tclClock.c (ConvertLocalToUTCUsingC): Corrected a regression that caused dates before 1969 to be one day off in the :localtime time zone if TZ is not set. [Bug 1531530] 2006-07-30 Kevin B. Kenny * generic/tclClock.c (GetJulianDayFromEraYearMonthDay): Corrected several errors in converting dates before the Common Era [Bug 1426279] * library/clock.tcl: Corrected syntax errors in generated code for %EC %Ey, and %W format groups [Bug 1505383]. Corrected a bug in cache management for format strings containing [glob] metacharacters [Bug 1494664]. Corrected several errors in formatting/scanning of years prior to the Common Era, and added the missing %EE format group to indicate the era. * tools/makeTestCases.tcl: Added code to make sure that %U and %V format groups are included in the tests. (The code depends on %U and %V formatting working correctly when 'makeTestCases.tcl' is run, rather than making a completely independent check.) Added tests for [glob] metacharacters in strings. Added tests for years prior to the Common Era. * tests/clock.test: Rebuilt with new test cases for all the above. 2006-07-30 Joe English * doc/AppInit.3: Fix typo [Bug 1496886] 2006-07-26 Don Porter * generic/tclExecute.c: Corrected flawed overflow detection in * tests/expr.test: INST_EXPON that caused [expr 2**64] to return 0 instead of the same value as [expr 1<<64]. 2006-07-24 Don Porter * win/tclWinSock.c: Correct un-initialized Tcl_DString. Thanks to afredd. [Bug 1518166] 2006-07-21 Miguel Sofer * generic/tclExecute.c: * tests/execute.test (execute-9.1): dgp's fix for [Bug 1522803]. 2006-07-20 Daniel Steffen * macosx/tclMacOSXNotify.c (Tcl_InitNotifier, Tcl_WaitForEvent): create notifier thread lazily upon first call to Tcl_WaitForEvent() rather than in Tcl_InitNotifier(). Allows calling exeve() in processes where the event loop has not yet been run (Darwin's execve() fails in processes with more than one thread), in particular allows embedders to call fork() followed by execve(), previously the pthread_atfork() child handler's call to Tcl_InitNotifier() would immediately recreate the notifier thread in the child after a fork. * macosx/tclMacOSXFCmd.c (TclMacOSXCopyFileAttributes): add support * macosx/tclMacOSXNotify.c (Tcl_InitNotifier): for weakly * unix/tclUnixInit.c (Tcl_GetEncodingNameFromEnvironment): importing symbols not available on OSX 10.2 or 10.3, enables binaires built on later OSX versions to run on earlier ones. * macosx/Tcl.xcodeproj/project.pbxproj: enable weak-linking; turn on extra warnings. * macosx/README: document how to enable weak-linking; cleanup. * unix/tclUnixPort.h: add support for weak-linking; conditionalize AvailabilityMacros.h inclusion; only disable realpath on 10.2 or earlier when threads are enabled. * unix/tclLoadDyld.c (TclpLoadMemoryGetBuffer): change runtime Darwin * unix/tclUnixInit.c (TclpInitPlatform): release check to use global initialized once * unix/tclUnixFCmd.c (DoRenameFile, TclpObjNormalizePath): add runtime Darwin release check to determine if realpath is threadsafe. * unix/configure.in: add check on Darwin for compiler support of weak * unix/tcl.m4: import and for AvailabilityMacros.h header; move Darwin specific checks & defines that are only relevant to the tcl build out of tcl.m4; restrict framework option to Darwin; clean up quoting and help messages. * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 * generic/regc_locale.c (cclass): * generic/tclExecute.c (TclExecuteByteCode): * generic/tclIOCmd.c (Tcl_ExecObjCmd): * generic/tclListObj.c (NewListIntRep): * generic/tclObj.c (Tcl_GetLongFromObj, Tcl_GetWideIntFromObj) (FreeBignum, Tcl_SetBignumObj): * generic/tclParseExpr.c (Tcl_ParseExpr): * generic/tclStrToD.c (TclParseNumber): * generic/tclStringObj.c (TclAppendFormattedObjs): * unix/tclLoadDyld.c (TclpLoadMemory): * unix/tclUnixPipe.c (TclpCreateProcess): fix signed-with-unsigned comparison and other warnings from gcc4 -Wextra. 2006-07-13 Andreas Kupries * unix/tclUnixPort.h: Added the inclusion of . The missing header caused the upcoming #if conditions to wrongly exclude realpath, causing file normalize to ignore symbolic links in the path. 2006-07-11 Zoran Vasiljevic * generic/tclAsync.c: Made Tcl_AsyncDelete() more tolerant when called after all thread TSD has been garbage-collected. 2006-07-05 Don Porter * generic/tclParseExpr.c: Completely new expression parser that builds a parse tree instead of operating with deep recursion. This corrects reports of stack-blowing crashes parsing long expressions [Bug 906201] and replaces a fundamentally O(N^2) algorithm with an O(N) one [RFE 903765]. The new parser is better able to generate error messages that clearly report both the nature and context of the syntax error [Bugs 1029267, 1381715]. For now, the code for the old parser is still present and can be activated with a "#define OLD_EXPR_PARSER 1". This is for the sake of a clean implementation patch, and for ease of benchmarking. The new parser is non-recursive, so much lighter in stack consumption, but it does use more heap, so there may be cases where parsing of long expressions that succeeded with the old parser will lead to out of memory panics with the new one. There are still more improvements possible on that point, though significant progress may require changes to the Tcl_Token specifications documented for the public Tcl_Parse*() routines. ***POTENTIAL INCOMPATIBILITY*** for any callers that rely on the exact (usually terrible) error messages generated by the old parser. This includes a large number of tests in the test suite. * generic/tclInt.h: Replaced TclParseWhiteSpace() with * generic/tclParse.c: TclParseAllWhiteSpace() which is what * generic/tclParseExpr.c: all the callers really needed. Breaking whitespace runs at newlines is useful only to the command parsing function, and it can call the file scoped routine ParseWhiteSpace() to do that. * tests/expr-old.test: Removed knownBug constraints that masked * tests/expr.test: failures due to revised error messages. * tests/parseExpr.test: 2006-06-20 Don Porter * generic/tclIOUtil.c: Changed default configuration to * generic/tclInt.decls: #undef USE_OBSOLETE_FS_HOOKS which disables * generic/tclTest.c: access to the Tcl 8.3 internal routines for hooking into filesystem operations. Everyone ought to have migrated to Tcl_Filesystems by now. ***POTENTIAL INCOMPATIBILITY*** for any code still stuck in the pre-Tcl_Filesystem era. * generic/tclIntDecls.h: make genstubs * generic/tclStubInit.c: * generic/tclStrToD.c: Removed dead code that permitted disabling of recognition of the new 0b and 0o numeric formats. * generic/tclExecute.c: Removed dead code that implemented alternative * generic/tclObj.c: design where numeric values did not automatically narrow to the smallest Tcl_ObjType required to hold them * generic/tclCmdAH.c: Removed dead code that was old implementation of [format]. 2006-06-14 Daniel Steffen * unix/tclUnixPort.h (Darwin): support MAC_OS_X_VERSION_MAX_ALLOWED define from AvailabilityMacros.h: override configure detection and only use API available in the indicated OS version or earlier. 2006-06-14 Donal K. Fellows * doc/format.n, doc/scan.n: Added examples for converting between characters and their numeric interpretations following user prompting. 2006-06-13 Donal K. Fellows * unix/tclLoadDl.c (TclpDlopen): Workaround for a compiler bug in Sun Forte 6. [Bug 1503729] 2006-06-06 Don Porter * doc/GetStdChan.3: Added recommendation that each call to Tcl_SetStdChannel() be accompanied by a call to Tcl_RegisterChannel(). 2006-06-05 Donal K. Fellows * doc/Alloc.3: Added documentation of promise that Tcl_Realloc(NULL,x) is the same as Tcl_Alloc(x), as discussed in comp.lang.tcl. Also fixed nonsense sentence to say something meaningful. 2006-05-29 Jeff Hobbs * generic/tcl.h (Tcl_DecrRefCount): use if/else construct to allow placement in unbraced outer if/else conditions. (jcw) 2006-05-27 Daniel Steffen * macosx/tclMacOSXNotify.c: implemented pthread_atfork() handler that * unix/tcl.m4 (Darwin): recreates CoreFoundation state and notifier thread in the child after a fork(). Note that pthread_atfork is available starting with Tiger only. Because vfork() is used by the core on Darwin, [exec]/[open] are not affected by this fix, only extensions or embedders that call fork() directly (such as TclX). However, this only makes fork() safe from corefoundation tcl with --disable-threads; as on all platforms, forked children may deadlock in threaded tcl due to the potential for stale locked mutexes in the child. [Patch 923072] * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 2006-05-24 Donal K. Fellows * unix/tcl.m4 (SC_CONFIG_SYSTEM): Fixed quoting of command script to awk; it was a rarely used branch, but it was wrong. [Bug 1494160] 2006-05-23 Donal K. Fellows * doc/chan.n, doc/refchan.n: Tighten up the documentation to follow a slightly more consistent style with regard to argument capitalization. 2006-05-13 Don Porter * generic/tclProc.c (ProcCompileProc): When a bump of the compile epoch forces the re-compile of a proc body, take care not to overwrite any Proc struct that may be referred to on the active call stack. Note that the fix will not be effective for code that calls the private routine TclProcCompileProc() directly. [Bug 1482718] 2006-05-13 Daniel Steffen * generic/tclEvent.c (HandleBgErrors): fix leak. [Coverity issue 86] 2006-05-05 Don Porter * generic/tclMain.c (Tcl_Main): Corrected flaw that required * tests/main.test: (Tcl_Main-4.5): processing of one interactive command before passing control to the loop routine registered with Tcl_SetMainLoop(). [Bug 1481986] 2006-05-04 Don Porter * README: Bump version number to 8.5a5 * generic/tcl.h: * tools/tcl.wse.in: * unix/configure.in: * unix/tcl.spec: * win/README.binary: * win/configure.in: * unix/configure: autoconf-2.59 * win/configure: * generic/tclBasic.c (ExprSrandFunc): Restore acceptance of wide/big * doc/mathfunc.n: integer values by srand(). [Bug 1480509] 2006-04-26 Don Porter *** 8.5a4 TAGGED FOR RELEASE *** * changes: Updates for another RC. * generic/tclBinary.c: Revised the handling of the Q and q format * generic/tclInt.h: specifiers for [binary] to account for the * generic/tclStrToD.c: "middle endian" floating point format used in Nokia N770. 2006-04-25 Don Porter * doc/DoubleObj.3: More doc updates for TIP 237. * doc/expr.n: * doc/format.n: * doc/mathfunc.n: * doc/scan.n: * doc/string.n: * generic/tclScan.c: [scan $s %u] is documented to accept only * tests/scan.test: decimal formatted integers. Fixed to match. 2006-04-19 Kevin B. Kenny * generic/tclStrToD.c: Added code to support the "middle endian" floating point format used in the Nokia N770's software-based floating point. Thanks to Bruce Johnson for reporting this bug, originally on http://wiki.tcl.tk/15408. * library/clock.tcl: Fixed a bug with Daylight Saving Time and Posix time zone specifiers reported by Martin Lemburg in http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/9a8b15a4dfc0b7a0 (and not at SourceForge). * tests/clock.test: Added test case for the above bug. 2006-04-18 Donal K. Fellows * doc/IntObj.3: Minor review fixes, including better documentation of the behaviour of Tcl_GetBignumAndClearObj. 2006-04-17 Don Porter * doc/IntObj.3: Documentation changes to account for TIP 237 changes. * doc/Object.3: [Bug 1446971] 2006-04-12 Donal K. Fellows * generic/regc_locale.c (cclass): Redefined the meaning of [:print:] to be exactly UNICODE letters, numbers, punctuation, symbols and spaces (*not* whitespace). [Bug 1376892] 2006-04-11 Don Porter * generic/tclTrace.c: Stop some interference between enter traces * tests/trace.test: and enterstep traces. [Bug 1458266] 2006-04-07 Don Porter * generic/tclPathObj.c: Yet another revised fix for the [Bug 1379287] * tests/fileSystem.test: family of path normalization bugs. 2006-04-06 Jeff Hobbs * generic/tclRegexp.c (FinalizeRegexp): full reset data to indicate readiness for reinitialization. 2006-04-06 Don Porter * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): It seems there * tests/indexObj.test: are extensions that rely on the prior behavior * doc/GetIndex.3: that the empty string cannot succeed as a unique prefix matcher, so I'm restoring Donal Fellows's solution. Added mention of this detail to the documentation. [Bug 1464039] * tests/compExpr-old.test: Updated testmathfunctions constraint * tests/compExpr.test: to post-TIP-232 world. * tests/expr-old.test: * tests/expr.test: * tests/info.test: * tests/indexObj.test: Corrected other test errors revealed by * tests/upvar.test: testing outside the tcltest application. * generic/tclPathObj.c: Revised fix for the [Bug 1379287] family of path normalization bugs. 2006-04-06 Daniel Steffen * unix/tcl.m4: removed TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING define on Darwin. [Bug 1457515] * unix/configure: autoconf-2.59 * unix/tclConfig.h.in: autoheader-2.59 2006-04-05 Don Porter * win/tclWinInit.c: More careful calls to Tcl_DStringSetLength() * win/tclWinSock.c: to avoid creating invalid DString states. Bump * win/tclWinDde.c: to version 1.3.2. [RFE 1366195] * library/dde/pkgIndex.tcl: * library/reg/pkgIndex.tcl: Bump to registry 1.2 because * win/tclWinReg.c: Registry_Unload() is a new public routine * win/Makefile.in: compared to the 1.1.* releases. * win/configure.in: Bump package version numbers. * win/configure: autoconf 2.59 2006-04-05 Donal K. Fellows * generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Allow empty strings to be matched by the Tcl_GetIndexFromObj machinery, in the same manner as any other key. [Bug 1464039] 2006-04-03 Andreas Kupries * generic/tclIO.c (ReadChars): Added check, panic and commentary to a piece of code which relies on BUFFER_PADDING to create enough space at the beginning of each buffer for the insertion of partial multibyte data at the beginning of a buffer. Commentary explains why this code is OK, and the panic is as a precaution if someone twiddled the BUFFER_PADDING into uselessness. * generic/tclIO.c (ReadChars): Temporarily suppress the use of TCL_ENCODING_END set when EOF was reached while the buffer we are converting is not truly the last buffer in the queue. Together with the Utf bug below it was possible to completely wreck the buffer data structures, eventually crashing Tcl. [Bug 1462248] * generic/tclEncoding.c (UtfToUtfProc): Stop accessing memory beyond the end of the input buffer when TCL_ENCODING_END is set and the last bytes of the buffer start a multi-byte sequence. This bug contributed to [Bug 1462248]. 2006-03-30 Miguel Sofer * generic/tclExecute.c: remove unused var and silence gcc warning 2006-03-29 Jeff Hobbs * win/Makefile.in: convert _NATIVE paths to use / to avoid ".\" path-as-escape issue. 2006-03-29 Don Porter * changes: Updates for another RC. * generic/tclPathObj.c: More fixes for path normalization when /../ * tests/fileSystem.test: tries to go beyond root.[Bug 1379287] * generic/tclExecute.c: Revised INST_MOD implementation to do calculations in native types as much as possible, moving to mp_ints only when necessary. 2006-03-28 Jeff Hobbs * win/tclWinPipe.c (TclpCreateProcess): change panics to Tcl errors and do proper refcounting of noe objPtr. [Bug 1194429] * unix/tcl.m4, win/tcl.m4: []-quote AC_DEFUN functions. 2006-03-28 Daniel Steffen * macosx/Tcl.xcode/default.pbxuser: add '-singleproc 1' cli arg to * macosx/Tcl.xcodeproj/default.pbxuser: tcltest to ease test debugging * macosx/Tcl.xcode/project.pbxproj: removed $prefix/share from * macosx/Tcl.xcodeproj/project.pbxproj: TCL_PACKAGE_PATH as per change to unix/configure.in of 2006-03-13. * unix/tclUnixFCmd.c (TclpObjNormalizePath): deal with *BSD/Darwin realpath() converting relative paths into absolute paths [Bug 1064247] 2006-03-28 Vince Darley * generic/tclIOUtil.c: fix to nativeFilesystemRecord comparisons (lesser part of [Bug 1064247]) 2006-03-27 Pat Thoyts * win/tclWinTest.c: Fixes for [Bug 1456373] (mingw-gcc issue) 2006-03-27 Andreas Kupries * doc/CrtChannel.3: Added TCL_CHANNEL_VERSION_5, made it the * generic/tcl.h: version where the "truncateProc" is defined at, * generic/tclIO.c: and moved all channel drivers of Tcl to v5. * generic/tclIOGT.c, generic/tclIORChan.c, unix/tclUnixChan.c: * unix/tclUnixPipe.c, win/tclWinChan.c, win/tclWinConsole.c: * win/tclWinPipe.c, win/tclWinSerial.c, win/tclWinSock.c: 2006-03-27 Don Porter * generic/tclExecute.c: Merge INST_MOD computation in with the INST_?SHIFT instructions, which also operate only on two integral values. Also corrected flaw that made INST_BITNOT of wide values require mp_int calculations. Also corrected type that missed optimized handling of the tclBooleanType by the TclGetBooleanFromObj macro. * changes: Updates for another RC. 2006-03-25 Don Porter * generic/tclExecute.c: Corrections to INST_EXPON detection of overflow to use mp_int calculations. 2006-03-24 Kevin B. Kenny * generic/tclExecute.c (TclExecuteByteCode): Added a couple of missing casts to 'int' that were affecting compilablity on VC6. 2006-03-24 Don Porter * generic/tclEncoding.c: Reverted latest change [Bug 506653] since it reportedly killed test performance on Windows. * generic/tclExecute.c: Revised INST_EXPON implementation to do calculations in native types as much as possible, moving to mp_ints only when necessary. 2006-03-23 Don Porter * generic/tclExecute.c: Merged INST_EXPON handling in with the other binary operators that operate on all number types (INST_ADD, etc.). * tests/env.test: With case preserved (see 2006-03-21 commit) be sure to do case-insensitive filtering. [Bug 1457065] 2006-03-23 Reinhard Max * unix/tcl.spec: Cleaned up and completed the spec file. An RPM can now be built from the tcl source distribution with "rpmbuild -tb " 2006-03-22 Reinhard Max * tests/stack.test: Run the stack tests in subshells, so that they are reported as failed tests rather than bugs in the test suite if the recursion causes a segfault. 2006-03-21 Don Porter * changes: Updates for another RC. * generic/tclStrToD.c: One of the branches of AccumulateDecimalDigit * tests/parseExpr.test: did not. [Bug 1451233] * tests/env.test: Preserve case of saved env vars. [Bug 1409272] 2006-03-21 Daniel Steffen * generic/tclInt.decls: implement globbing for HFS creator & type * macosx/tclMacOSXFCmd.c:codes and 'hidden' flag, as documented in * tests/macOSXFCmd.test: glob.n; objectified OSType handling in [glob] * unix/tclUnixFile.c: and [file attributes]; fix globbing for hidden files with pattern==NULL arg. [Bug 823329] * generic/tclIntPlatDecls.h: * generic/tclStubInit.c: make genstubs 2006-03-20 Andreas Kupries * win/Makefile.in (install-libraries): Generate tcl8/8.4 directory under Windows as well (cygwin Makefile). Related entry: 2006-03-07, dgp. This moved the installation of http from 8.2 to 8.4, partially. A fix of the required directory creation was done for unix on Mar 10, without entry in the Changelog. This entry is for the fix of the directory creation under Windows. * unix/installManPage: There is always one even more broken "sed". Moved the # comment starting character in the sed script to the beginning of their respective lines. The AIX sed will not recognize them as comments otherwise :( The actual text stays indented for better association with the commands they belong to. 2006-03-20 Donal K. Fellows * tests/cmdAH.test, tests/fCmd.test, tests/unixFCmd.test: * tests/winFCmd.test: Cleanup of some test constraint handling, and a few other minor issues. 2006-03-18 Vince Darley * generic/tclFileName.c: * doc/FileSystem.3: * tests/fileName.test: Fix to [Bug 1084705] so that 'glob -nocomplain' finally agrees with its documentation and doesn't swallow genuine errors. ***POTENTIAL INCOMPATIBILITY*** for scripts that assumed '-nocomplain' removes the need for 'catch' to deal with non-understood path names. Small optimisation to implementation of pattern==NULL case of TclGlob, and clarification to the documentation. [Tclvfs bug 1405317] 2006-03-18 Vince Darley * tests/fCmd.test: added knownBug test case for [Bug 1394972] * tests/winFCmd.test: * tests/tcltest.test: corrected tests to better account for behaviour of writable/non-writable directories on Windows 2000/XP. This, with the previous patches, closes [Bug 1193497] 2006-03-17 Andreas Kupries * doc/chan.n: Updated with documentation for the commands 'chan create' and 'chan postevent' (TIP #219). * doc/refchan.n: New file. Documentation of the command handler API for reflected channels (TIP #219). 2006-03-17 Joe Mistachkin * unix/tclUnixPort.h: Include pthread.h prior to pthread_np.h [Bug 1444692] * win/tclWinTest.c: Corrected typo of 'initializeMutex' that prevented successful compilation. 2006-03-16 Andreas Kupries * doc/open.n: Documented the changed behaviour of 'a'ppend mode. * tests/io.test (io-43.1 io-44.[1234]): Rewritten to be self-contained with regard to setup and cleanup. [Bug 681793] * generic/tclIOUtil.c (TclGetOpenMode): Added the flag O_APPEND to the list of POSIX modes used when opening a file for 'a'ppend. This enables the proper automatic seek-to-end-on-write by the OS. See [Bug 680143] for longer discussion. * tests/ioCmd.test (iocmd-13.7.*): Extended the testsuite to check the new handling of 'a'. 2006-03-15 Andreas Kupries * tests/socket.test: Extended the timeout in socket-11.11 from 10 to 40 seconds to allow for really slow machines. Also extended actual/expected results with value of variable 'done' to make it clearer when a test fails due to a timeout. [Bug 792159] 2006-03-15 Vince Darley * win/fCmd.test: add proper test constraints so the new tests don't run on Unix. 2006-03-14 Andreas Kupries * generic/tclPipe.c (TclCreatePipeline): Modified the processing of pipebars to fail if the last bar is followed only by redirections. [Bug 768659] 2006-03-14 Andreas Kupries * doc/fconfigure.n: Clarified that -translation is binary is reported as lf when queried, because it is identical to lf, except for the special additional behaviour when setting it. [Bug 666770] 2006-03-14 Andreas Kupries * doc/clock.n: Removed double-quotes around section title NAME; not needed. * unix/installManpage: Reverted part to handle double-quotes in section NAME, chokes older sed installations. 2006-03-14 Andreas Kupries * library/tm.tcl (::tcl::tm::Defaults): Fixed handling of environment variable TCLX.y_TM_PATH, bad variable reference. Thanks to Julian Noble. [Bug 1448251] 2006-03-14 Vince Darley * win/tclWinFile.c: updated patch to deal with 'file writable' issues on Windows XP/2000. * generic/tclTest.c: * unix/tclUnixTest.c: * win/tclWinTest.c: * tests/fCmd.test: updated test suite to deal with correct permissions setting and differences between XP/2000 and 95/98 3 tests still fail; to be dealt with shortly 2006-03-13 Don Porter * generic/tclEncoding.c: Report error when an escape encoding is missing one of its sub-encodings. [Bug 506653] * unix/configure.in: Revert change from 2005-07-26 that sometimes * unix/configure: added $prefix/share to the tcl_pkgPath. See [Patch 1231015]. autoconf-2.59. 2006-03-10 Miguel Sofer * generic/tclProc.c (ObjInterpProcEx): * tests/apply.test (apply-5.1): Fix [apply] error messages so that they quote the lambda expression. [Bug 1447355] 2006-03-10 Zoran Vasiljevic -- Summary of changes fixing [Bug 1437595] -- * generic/tclEvent.c: Cosmetic touches and identation * generic/tclInt.h: Added TclpFinalizeSockets() call. * generic/tclIO.c: Calls TclpFinalizeSockets() as part of the TclFinalizeIOSubsystem(). * unix/tclUnixSock.c: Added no-op TclpFinalizeSockets(). * win/tclWinPipe.c, win/tclWinSock.c: Finalization of sockets/pipes is now solely done in TclpFinalizeSockets() and TclpFinalizePipes() and not over the thread-exit handler, because the order of actions the Tcl generic core will impose may result in cores/hangs if the thread exit handler tears down corresponding subsystem(s) too early. 2006-03-10 Vince Darley * win/tclWinFile.c: previous patch breaks tests, so removed. 2006-03-09 Vince Darley * win/tclWinFile.c: fix to 'file writable' in certain XP directories. Thanks to fvogel and jfg. [Patch 1344540] Modified patch to make use of existing use of getSecurityProc. 2006-03-08 Don Porter * generic/tclExecute.c: Complete missing bit of TIP 215 implementation * tests/incr.test: 2006-03-07 Joe English * unix/tcl.m4: Set SHLIB_LD_FLAGS='${LIBS}' on NetBSD, as per the other *BSD variants. [Bug 1334613] * unix/configure: Regenerated. 2006-03-07 Don Porter * changes: Update in prep. for 8.5a4 release. * unix/Makefile.in: Package http 2.5.2 requires Tcl 8.4, so the * win/Makefile.in: *.tm installation has to be placed in an "8.4" directory, not an "8.2" directory. 2006-03-06 Don Porter * generic/tclBasic.c: Revised handling of TCL_EVAL_* flags to * tests/parse.test: simplify TclEvalObjvInternal and to correct the auto-loading of alias targets (parse-8.12). [Bug 1444291] 2006-03-03 Don Porter * generic/tclPathObj.c: Revised yesterday's fix for [Bug 1379287] to work on Windows. * generic/tclObj.c: Compatibility support for existing code that calls Tcl_GetObjType("boolean"). 2006-03-02 Don Porter * generic/tclPathObj.c: Fix for failed normalization of paths * tests/fileSystem.test: with /../ that lead back to the root of the filesystem, like /foo/.. [Bug 1379287] 2006-03-01 Reinhard Max * unix/installManPage: Fix the script for manpages that have quotes around the .SH arguments, as doctools produces them. [Bug 1292145] Some minor cleanups and improvements. 2006-02-28 Don Porter * generic/tclBasic.c: Corrections to be sure that TCL_EVAL_GLOBAL * tests/namespace.test: evaluations act the same as [uplevel #0] * tests/parse.test: evaluations, even when execution traces or * tests/trace.test: invocations of [::unknown] are present. [Bug 1439836] 2006-02-22 Don Porter * generic/tclBasic.c: Corrected a few bugs in how [namespace * tests/namespace.test: unknown] interacts with TCL_EVAL_* flags. [Patch 958222] 2006-02-17 Don Porter * generic/tclIORChan.c: Revised error message generation and handling * tests/ioCmd.test: of exceptional return codes in the channel reflection layer. [Bug 1372348] 2006-02-16 Don Porter * generic/tclIndexObj.c: Disallow the "ambiguous" error message * tests/indexObj.test: when TCL_EXACT matching is requested. * tests/ioCmd.test: 2006-02-15 Don Porter * generic/tclIO.c: Made several routines tolerant of * generic/tclIORChan.c: interp == NULL arguments. [Bug 1380662] * generic/tclIOUtil.c: 2006-02-09 Don Porter TIP#215 IMPLEMENTATION * doc/incr.n: Revised [incr] to auto-initialize when varName * generic/tclExecute.c: argument is unset. [Patch 1413115] * generic/tclVar.c: * tests/compile.test: * tests/incr-old.test: * tests/incr.test: * tests/set.test: * tests/main.test (Tcl_Main-6.7): Improved robustness of command auto-completion test. [Bug 1422736] 2006-02-08 Donal K. Fellows * doc/Encoding.3, doc/encoding.n: Updates due to review at request of Don Porter. Mostly minor changes. 2006-02-08 Don Porter TIP#258 IMPLEMENTATION * doc/Encoding.3: New subcommand [encoding dirs]. * doc/encoding.n: New routine Tcl_GetEncodingNameFromEnvironment * generic/tcl.decls: Made public: * generic/tclBasic.c: TclGetEncodingFromObj * generic/tclCmdAH.c: -> Tcl_GetEncodingFromObj * generic/tclEncoding.c:TclGetEncodingSearchPath * generic/tclInt.decls: -> Tcl_GetEncodingSearchPath * generic/tclInt.h: TclSetEncodingSearchPath * generic/tclTest.c: -> Tcl_SetEncodingSearchPath * library/init.tcl: Removed commands: * tests/cmdAH.test: [tcl::unsupported::EncodingDirs] * tests/encoding.test: [testencoding path] (Tcltest) * unix/tclUnixInit.c: [Patch 1413934] * win/tclWinInit.c: * generic/tclDecls.h: make genstubs * generic/tclIntDecls.h: * generic/tclStubInit.c: 2006-02-01 Miguel Sofer * generic/tclProc.c: minor improvements to [apply] * tests/apply.test: new tests; apply-5.1 currently fails to indicate missing work in error reporting 2006-02-01 Don Porter TIP#194 IMPLEMENTATION * doc/apply.n: (New file) New command [apply]. [Patch 944803] * doc/uplevel.n: * generic/tclBasic.c: * generic/tclInt.h: * generic/tclProc.c: * tests/apply.test: (New file) * tests/proc-old.test: * tests/proc.test: TIP#181 IMPLEMENTATION * doc/Namespace.3: New command [namespace unknown]. New public C * doc/namespace.n: routines Tcl_(Get|Set)NamespaceUnknownHandler. * doc/unknown.n: [Patch 958222] * generic/tcl.decls: * generic/tclBasic.c: * generic/tclInt.h: * generic/tclNamesp.c: * tests/namespace.test: * generic/tclDecls.h: make genstubs * generic/tclStubInit.c: TIP#250 IMPLEMENTATION * doc/namespace.n: New command [namespace upvar]. [Patch 1275435] * generic/tclInt.h: * generic/tclNamesp.c: * generic/tclVar.c: * tests/namespace.test: * tests/upvar.test: 2006-01-26 Donal K. Fellows * doc/dict.n: Fixed silly bug in example. Thanks to Heiner Marxen for catching this! [Bug 1415725] 2006-01-26 Donal K. Fellows * unix/tclUnixChan.c (TclpOpenFileChannel): Tidy up and comment the mess to do with setting up serial channels. This (deliberately) breaks a broken FreeBSD port, indicates what we're really doing, and reduces the amount of conditional compilation sections for better maintenance. 2006-01-25 Donal K. Fellows * unix/tclUnixInit.c (TclpInitPlatform): Improved conditions on when to update the FP rounding mode on FreeBSD, taken from FreeBSD port. 2006-01-23 Donal K. Fellows * tests/string.test (string-12.21): Added test for [Bug 1410553] based on original bug report. 2006-01-23 Miguel Sofer * generic/tclStringObj.c: fixed incorrect handling of internal rep in Tcl_GetRange. Thanks to twylite and Peter Spjuth. [Bug 1410553] * generic/tclProc.c: fixed args handling for precompiled bodies [Bug 1412695]; thanks to Uwe Traum. 2006-01-16 Reinhard Max * generic/tclPipe.c (FileForRedirect): Prevent nameString from being freed without having been initialized. * tests/exec.test: Added a test for the above. 2006-01-12 Zoran Vasiljevic * generic/tclPathObj.c (Tcl_FSGetInternalRep): backported patch from core-8-4-branch. A freed pointer has been overwritten causing all sorts of coredumps. 2006-01-12 Vince Darley * win/tclWinFile.c: fix to sharing violation [Bug 1366227] 2006-01-11 Don Porter * generic/tclBasic.c: Moved Tcl_LogCommandInfo from tclBasic.c to * generic/tclNamesp.c: tclNamesp.c to get access to identifier with * tests/error.test (error-7.0): file scope. Added check for traces on ::errorInfo, and when present fall back to contruction of the stack trace in the variable so that write trace notification timings are compatible with earlier Tcl releases. This reduces, but does not completely eliminate the ***POTENTIAL INCOMPATIBILITY*** created by the 2004-10-15 commit. [Bug 1397843] 2006-01-10 Daniel Steffen * unix/configure: add caching, use AC_CACHE_CHECK instead of * unix/configure.in: AC_CACHE_VAL where possible, consistent message * unix/tcl.m4: quoting, sync relevant tclconfig/tcl.m4 changes and gratuitous formatting differences, fix SC_CONFIG_MANPAGES with default argument, Darwin improvements to SC_LOAD_*CONFIG. 2006-01-09 Don Porter * generic/tclNamesp.c (NamespaceInscopeCmd): [namespace inscope] * tests/namespace.test: commands were not reported by [info level]. [Bug 1400572] 2006-01-09 Donal K. Fellows * generic/tclTrace.c: Stop exporting the guts of the trace command; nothing outside this file needs to see it. [Bug 971336] 2006-01-05 Donal K. Fellows * unix/tcl.m4 (TCL_CONFIG_SYSTEM): Factor out the code to determine the operating system version number, as it was replicated in several places. 2006-01-04 David Gravereaux * win/tclAppInit.c: WIN32 native console signal handler removed. This was found to be interfering with TWAPI extension one. IMO, special services such as signal handlers should best be done with extensions to the core after discussions on c.l.t. about Roy Terry's tclsh children of a real windows service shell. ****************************************************************** *** CHANGELOG ENTRIES FOR 2005 IN "ChangeLog.2005" *** *** CHANGELOG ENTRIES FOR 2004 IN "ChangeLog.2004" *** *** CHANGELOG ENTRIES FOR 2003 IN "ChangeLog.2003" *** *** CHANGELOG ENTRIES FOR 2002 IN "ChangeLog.2002" *** *** CHANGELOG ENTRIES FOR 2001 IN "ChangeLog.2001" *** *** CHANGELOG ENTRIES FOR 2000 IN "ChangeLog.2000" *** *** CHANGELOG ENTRIES FOR 1999 AND EARLIER IN "ChangeLog.1999" *** ****************************************************************** tcl8.6.5/library/0000755000175000017500000000000012665173607013236 5ustar sergeisergeitcl8.6.5/library/tm.tcl0000644000175000017500000002656112664107404014363 0ustar sergeisergei# -*- tcl -*- # # Searching for Tcl Modules. Defines a procedure, declares it as the primary # command for finding packages, however also uses the former 'package unknown' # command as a fallback. # # Locates all possible packages in a directory via a less restricted glob. The # targeted directory is derived from the name of the requested package, i.e. # the TM scan will look only at directories which can contain the requested # package. It will register all packages it found in the directory so that # future requests have a higher chance of being fulfilled by the ifneeded # database without having to come to us again. # # We do not remember where we have been and simply rescan targeted directories # when invoked again. The reasoning is this: # # - The only way we get back to the same directory is if someone is trying to # [package require] something that wasn't there on the first scan. # # Either # 1) It is there now: If we rescan, you get it; if not you don't. # # This covers the possibility that the application asked for a package # late, and the package was actually added to the installation after the # application was started. It shoukld still be able to find it. # # 2) It still is not there: Either way, you don't get it, but the rescan # takes time. This is however an error case and we dont't care that much # about it # # 3) It was there the first time; but for some reason a "package forget" has # been run, and "package" doesn't know about it anymore. # # This can be an indication that the application wishes to reload some # functionality. And should work as well. # # Note that this also strikes a balance between doing a glob targeting a # single package, and thus most likely requiring multiple globs of the same # directory when the application is asking for many packages, and trying to # glob for _everything_ in all subdirectories when looking for a package, # which comes with a heavy startup cost. # # We scan for regular packages only if no satisfying module was found. namespace eval ::tcl::tm { # Default paths. None yet. variable paths {} # The regex pattern a file name has to match to make it a Tcl Module. set pkgpattern {^([_[:alpha:]][:_[:alnum:]]*)-([[:digit:]].*)[.]tm$} # Export the public API namespace export path namespace ensemble create -command path -subcommands {add remove list} } # ::tcl::tm::path implementations -- # # Public API to the module path. See specification. # # Arguments # cmd - The subcommand to execute # args - The paths to add/remove. Must not appear querying the # path with 'list'. # # Results # No result for subcommands 'add' and 'remove'. A list of paths for # 'list'. # # Sideeffects # The subcommands 'add' and 'remove' manipulate the list of paths to # search for Tcl Modules. The subcommand 'list' has no sideeffects. proc ::tcl::tm::add {args} { # PART OF THE ::tcl::tm::path ENSEMBLE # # The path is added at the head to the list of module paths. # # The command enforces the restriction that no path may be an ancestor # directory of any other path on the list. If the new path violates this # restriction an error wil be raised. # # If the path is already present as is no error will be raised and no # action will be taken. variable paths # We use a copy of the path as source during validation, and extend it as # well. Because we not only have to detect if the new paths are bogus with # respect to the existing paths, but also between themselves. Otherwise we # can still add bogus paths, by specifying them in a single call. This # makes the use of the new paths simpler as well, a trivial assignment of # the collected paths to the official state var. set newpaths $paths foreach p $args { if {$p in $newpaths} { # Ignore a path already on the list. continue } # Search for paths which are subdirectories of the new one. If there # are any then the new path violates the restriction about ancestors. set pos [lsearch -glob $newpaths ${p}/*] # Cannot use "in", we need the position for the message. if {$pos >= 0} { return -code error \ "$p is ancestor of existing module path [lindex $newpaths $pos]." } # Now look for existing paths which are ancestors of the new one. This # reverse question forces us to loop over the existing paths, as each # element is the pattern, not the new path :( foreach ep $newpaths { if {[string match ${ep}/* $p]} { return -code error \ "$p is subdirectory of existing module path $ep." } } set newpaths [linsert $newpaths 0 $p] } # The validation of the input is complete and successful, and everything # in newpaths is either an old path, or added. We can now extend the # official list of paths, a simple assignment is sufficient. set paths $newpaths return } proc ::tcl::tm::remove {args} { # PART OF THE ::tcl::tm::path ENSEMBLE # # Removes the path from the list of module paths. The command is silently # ignored if the path is not on the list. variable paths foreach p $args { set pos [lsearch -exact $paths $p] if {$pos >= 0} { set paths [lreplace $paths $pos $pos] } } } proc ::tcl::tm::list {} { # PART OF THE ::tcl::tm::path ENSEMBLE variable paths return $paths } # ::tcl::tm::UnknownHandler -- # # Unknown handler for Tcl Modules, i.e. packages in module form. # # Arguments # original - Original [package unknown] procedure. # name - Name of desired package. # version - Version of desired package. Can be the # empty string. # exact - Either -exact or ommitted. # # Name, version, and exact are used to determine satisfaction. The # original is called iff no satisfaction was achieved. The name is also # used to compute the directory to target in the search. # # Results # None. # # Sideeffects # May populate the package ifneeded database with additional provide # scripts. proc ::tcl::tm::UnknownHandler {original name args} { # Import the list of paths to search for packages in module form. # Import the pattern used to check package names in detail. variable paths variable pkgpattern # Without paths to search we can do nothing. (Except falling back to the # regular search). if {[llength $paths]} { set pkgpath [string map {:: /} $name] set pkgroot [file dirname $pkgpath] if {$pkgroot eq "."} { set pkgroot "" } # We don't remember a copy of the paths while looping. Tcl Modules are # unable to change the list while we are searching for them. This also # simplifies the loop, as we cannot get additional directories while # iterating over the list. A simple foreach is sufficient. set satisfied 0 foreach path $paths { if {![interp issafe] && ![file exists $path]} { continue } set currentsearchpath [file join $path $pkgroot] if {![interp issafe] && ![file exists $currentsearchpath]} { continue } set strip [llength [file split $path]] # We can't use glob in safe interps, so enclose the following in a # catch statement, where we get the module files out of the # subdirectories. In other words, Tcl Modules are not-functional # in such an interpreter. This is the same as for the command # "tclPkgUnknown", i.e. the search for regular packages. catch { # We always look for _all_ possible modules in the current # path, to get the max result out of the glob. foreach file [glob -nocomplain -directory $currentsearchpath *.tm] { set pkgfilename [join [lrange [file split $file] $strip end] ::] if {![regexp -- $pkgpattern $pkgfilename --> pkgname pkgversion]} { # Ignore everything not matching our pattern for # package names. continue } try { package vcompare $pkgversion 0 } on error {} { # Ignore everything where the version part is not # acceptable to "package vcompare". continue } if {[package ifneeded $pkgname $pkgversion] ne {}} { # There's already a provide script registered for # this version of this package. Since all units of # code claiming to be the same version of the same # package ought to be identical, just stick with # the one we already have. continue } # We have found a candidate, generate a "provide script" # for it, and remember it. Note that we are using ::list # to do this; locally [list] means something else without # the namespace specifier. # NOTE. When making changes to the format of the provide # command generated below CHECK that the 'LOCATE' # procedure in core file 'platform/shell.tcl' still # understands it, or, if not, update its implementation # appropriately. # # Right now LOCATE's implementation assumes that the path # of the package file is the last element in the list. package ifneeded $pkgname $pkgversion \ "[::list package provide $pkgname $pkgversion];[::list source -encoding utf-8 $file]" # We abort in this unknown handler only if we got a # satisfying candidate for the requested package. # Otherwise we still have to fallback to the regular # package search to complete the processing. if {($pkgname eq $name) && [package vsatisfies $pkgversion {*}$args]} { set satisfied 1 # We do not abort the loop, and keep adding provide # scripts for every candidate in the directory, just # remember to not fall back to the regular search # anymore. } } } } if {$satisfied} { return } } # Fallback to previous command, if existing. See comment above about # ::list... if {[llength $original]} { uplevel 1 $original [::linsert $args 0 $name] } } # ::tcl::tm::Defaults -- # # Determines the default search paths. # # Arguments # None # # Results # None. # # Sideeffects # May add paths to the list of defaults. proc ::tcl::tm::Defaults {} { global env tcl_platform lassign [split [info tclversion] .] major minor set exe [file normalize [info nameofexecutable]] # Note that we're using [::list], not [list] because [list] means # something other than [::list] in this namespace. roots [::list \ [file dirname [info library]] \ [file join [file dirname [file dirname $exe]] lib] \ ] if {$tcl_platform(platform) eq "windows"} { set sep ";" } else { set sep ":" } for {set n $minor} {$n >= 0} {incr n -1} { foreach ev [::list \ TCL${major}.${n}_TM_PATH \ TCL${major}_${n}_TM_PATH \ ] { if {![info exists env($ev)]} continue foreach p [split $env($ev) $sep] { path add $p } } } return } # ::tcl::tm::roots -- # # Public API to the module path. See specification. # # Arguments # paths - List of 'root' paths to derive search paths from. # # Results # No result. # # Sideeffects # Calls 'path add' to paths to the list of module search paths. proc ::tcl::tm::roots {paths} { regexp {^(\d+)\.(\d+)} [package present Tcl] - major minor foreach pa $paths { set p [file join $pa tcl$major] for {set n $minor} {$n >= 0} {incr n -1} { set px [file join $p ${major}.${n}] if {![interp issafe]} {set px [file normalize $px]} path add $px } set px [file join $p site-tcl] if {![interp issafe]} {set px [file normalize $px]} path add $px } return } # Initialization. Set up the default paths, then insert the new handler into # the chain. if {![interp issafe]} {::tcl::tm::Defaults} tcl8.6.5/library/safe.tcl0000644000175000017500000010123712664107766014666 0ustar sergeisergei# safe.tcl -- # # This file provide a safe loading/sourcing mechanism for safe interpreters. # It implements a virtual path mecanism to hide the real pathnames from the # slave. It runs in a master interpreter and sets up data structure and # aliases that will be invoked when used from a slave interpreter. # # See the safe.n man page for details. # # Copyright (c) 1996-1997 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. # # The implementation is based on namespaces. These naming conventions are # followed: # Private procs starts with uppercase. # Public procs are exported and starts with lowercase # # Needed utilities package package require opt 0.4.1 # Create the safe namespace namespace eval ::safe { # Exported API: namespace export interpCreate interpInit interpConfigure interpDelete \ interpAddToAccessPath interpFindInAccessPath setLogCmd } # Helper function to resolve the dual way of specifying staticsok (either # by -noStatics or -statics 0) proc ::safe::InterpStatics {} { foreach v {Args statics noStatics} { upvar $v $v } set flag [::tcl::OptProcArgGiven -noStatics] if {$flag && (!$noStatics == !$statics) && ([::tcl::OptProcArgGiven -statics])} { return -code error\ "conflicting values given for -statics and -noStatics" } if {$flag} { return [expr {!$noStatics}] } else { return $statics } } # Helper function to resolve the dual way of specifying nested loading # (either by -nestedLoadOk or -nested 1) proc ::safe::InterpNested {} { foreach v {Args nested nestedLoadOk} { upvar $v $v } set flag [::tcl::OptProcArgGiven -nestedLoadOk] # note that the test here is the opposite of the "InterpStatics" one # (it is not -noNested... because of the wanted default value) if {$flag && (!$nestedLoadOk != !$nested) && ([::tcl::OptProcArgGiven -nested])} { return -code error\ "conflicting values given for -nested and -nestedLoadOk" } if {$flag} { # another difference with "InterpStatics" return $nestedLoadOk } else { return $nested } } #### # # API entry points that needs argument parsing : # #### # Interface/entry point function and front end for "Create" proc ::safe::interpCreate {args} { set Args [::tcl::OptKeyParse ::safe::interpCreate $args] InterpCreate $slave $accessPath \ [InterpStatics] [InterpNested] $deleteHook } proc ::safe::interpInit {args} { set Args [::tcl::OptKeyParse ::safe::interpIC $args] if {![::interp exists $slave]} { return -code error "\"$slave\" is not an interpreter" } InterpInit $slave $accessPath \ [InterpStatics] [InterpNested] $deleteHook } # Check that the given slave is "one of us" proc ::safe::CheckInterp {slave} { namespace upvar ::safe S$slave state if {![info exists state] || ![::interp exists $slave]} { return -code error \ "\"$slave\" is not an interpreter managed by ::safe::" } } # Interface/entry point function and front end for "Configure". This code # is awfully pedestrian because it would need more coupling and support # between the way we store the configuration values in safe::interp's and # the Opt package. Obviously we would like an OptConfigure to avoid # duplicating all this code everywhere. # -> TODO (the app should share or access easily the program/value stored # by opt) # This is even more complicated by the boolean flags with no values that # we had the bad idea to support for the sake of user simplicity in # create/init but which makes life hard in configure... # So this will be hopefully written and some integrated with opt1.0 # (hopefully for tcl8.1 ?) proc ::safe::interpConfigure {args} { switch [llength $args] { 1 { # If we have exactly 1 argument the semantic is to return all # the current configuration. We still call OptKeyParse though # we know that "slave" is our given argument because it also # checks for the "-help" option. set Args [::tcl::OptKeyParse ::safe::interpIC $args] CheckInterp $slave namespace upvar ::safe S$slave state return [join [list \ [list -accessPath $state(access_path)] \ [list -statics $state(staticsok)] \ [list -nested $state(nestedok)] \ [list -deleteHook $state(cleanupHook)]]] } 2 { # If we have exactly 2 arguments the semantic is a "configure # get" lassign $args slave arg # get the flag sub program (we 'know' about Opt's internal # representation of data) set desc [lindex [::tcl::OptKeyGetDesc ::safe::interpIC] 2] set hits [::tcl::OptHits desc $arg] if {$hits > 1} { return -code error [::tcl::OptAmbigous $desc $arg] } elseif {$hits == 0} { return -code error [::tcl::OptFlagUsage $desc $arg] } CheckInterp $slave namespace upvar ::safe S$slave state set item [::tcl::OptCurDesc $desc] set name [::tcl::OptName $item] switch -exact -- $name { -accessPath { return [list -accessPath $state(access_path)] } -statics { return [list -statics $state(staticsok)] } -nested { return [list -nested $state(nestedok)] } -deleteHook { return [list -deleteHook $state(cleanupHook)] } -noStatics { # it is most probably a set in fact but we would need # then to jump to the set part and it is not *sure* # that it is a set action that the user want, so force # it to use the unambigous -statics ?value? instead: return -code error\ "ambigous query (get or set -noStatics ?)\ use -statics instead" } -nestedLoadOk { return -code error\ "ambigous query (get or set -nestedLoadOk ?)\ use -nested instead" } default { return -code error "unknown flag $name (bug)" } } } default { # Otherwise we want to parse the arguments like init and # create did set Args [::tcl::OptKeyParse ::safe::interpIC $args] CheckInterp $slave namespace upvar ::safe S$slave state # Get the current (and not the default) values of whatever has # not been given: if {![::tcl::OptProcArgGiven -accessPath]} { set doreset 1 set accessPath $state(access_path) } else { set doreset 0 } if { ![::tcl::OptProcArgGiven -statics] && ![::tcl::OptProcArgGiven -noStatics] } then { set statics $state(staticsok) } else { set statics [InterpStatics] } if { [::tcl::OptProcArgGiven -nested] || [::tcl::OptProcArgGiven -nestedLoadOk] } then { set nested [InterpNested] } else { set nested $state(nestedok) } if {![::tcl::OptProcArgGiven -deleteHook]} { set deleteHook $state(cleanupHook) } # we can now reconfigure : InterpSetConfig $slave $accessPath $statics $nested $deleteHook # auto_reset the slave (to completly synch the new access_path) if {$doreset} { if {[catch {::interp eval $slave {auto_reset}} msg]} { Log $slave "auto_reset failed: $msg" } else { Log $slave "successful auto_reset" NOTICE } } } } } #### # # Functions that actually implements the exported APIs # #### # # safe::InterpCreate : doing the real job # # This procedure creates a safe slave and initializes it with the safe # base aliases. # NB: slave name must be simple alphanumeric string, no spaces, no (), no # {},... {because the state array is stored as part of the name} # # Returns the slave name. # # Optional Arguments : # + slave name : if empty, generated name will be used # + access_path: path list controlling where load/source can occur, # if empty: the master auto_path will be used. # + staticsok : flag, if 0 :no static package can be loaded (load {} Xxx) # if 1 :static packages are ok. # + nestedok: flag, if 0 :no loading to sub-sub interps (load xx xx sub) # if 1 : multiple levels are ok. # use the full name and no indent so auto_mkIndex can find us proc ::safe::InterpCreate { slave access_path staticsok nestedok deletehook } { # Create the slave. if {$slave ne ""} { ::interp create -safe $slave } else { # empty argument: generate slave name set slave [::interp create -safe] } Log $slave "Created" NOTICE # Initialize it. (returns slave name) InterpInit $slave $access_path $staticsok $nestedok $deletehook } # # InterpSetConfig (was setAccessPath) : # Sets up slave virtual auto_path and corresponding structure within # the master. Also sets the tcl_library in the slave to be the first # directory in the path. # NB: If you change the path after the slave has been initialized you # probably need to call "auto_reset" in the slave in order that it gets # the right auto_index() array values. proc ::safe::InterpSetConfig {slave access_path staticsok nestedok deletehook} { global auto_path # determine and store the access path if empty if {$access_path eq ""} { set access_path $auto_path # Make sure that tcl_library is in auto_path and at the first # position (needed by setAccessPath) set where [lsearch -exact $access_path [info library]] if {$where == -1} { # not found, add it. set access_path [linsert $access_path 0 [info library]] Log $slave "tcl_library was not in auto_path,\ added it to slave's access_path" NOTICE } elseif {$where != 0} { # not first, move it first set access_path [linsert \ [lreplace $access_path $where $where] \ 0 [info library]] Log $slave "tcl_libray was not in first in auto_path,\ moved it to front of slave's access_path" NOTICE } # Add 1st level sub dirs (will searched by auto loading from tcl # code in the slave using glob and thus fail, so we add them here # so by default it works the same). set access_path [AddSubDirs $access_path] } Log $slave "Setting accessPath=($access_path) staticsok=$staticsok\ nestedok=$nestedok deletehook=($deletehook)" NOTICE namespace upvar ::safe S$slave state # clear old autopath if it existed # build new one # Extend the access list with the paths used to look for Tcl Modules. # We save the virtual form separately as well, as syncing it with the # slave has to be defered until the necessary commands are present for # setup. set norm_access_path {} set slave_access_path {} set map_access_path {} set remap_access_path {} set slave_tm_path {} set i 0 foreach dir $access_path { set token [PathToken $i] lappend slave_access_path $token lappend map_access_path $token $dir lappend remap_access_path $dir $token lappend norm_access_path [file normalize $dir] incr i } set morepaths [::tcl::tm::list] while {[llength $morepaths]} { set addpaths $morepaths set morepaths {} foreach dir $addpaths { # Prevent the addition of dirs on the tm list to the # result if they are already known. if {[dict exists $remap_access_path $dir]} { continue } set token [PathToken $i] lappend access_path $dir lappend slave_access_path $token lappend map_access_path $token $dir lappend remap_access_path $dir $token lappend norm_access_path [file normalize $dir] lappend slave_tm_path $token incr i # [Bug 2854929] # Recursively find deeper paths which may contain # modules. Required to handle modules with names like # 'platform::shell', which translate into # 'platform/shell-X.tm', i.e arbitrarily deep # subdirectories. lappend morepaths {*}[glob -nocomplain -directory $dir -type d *] } } set state(access_path) $access_path set state(access_path,map) $map_access_path set state(access_path,remap) $remap_access_path set state(access_path,norm) $norm_access_path set state(access_path,slave) $slave_access_path set state(tm_path_slave) $slave_tm_path set state(staticsok) $staticsok set state(nestedok) $nestedok set state(cleanupHook) $deletehook SyncAccessPath $slave } # # # FindInAccessPath: # Search for a real directory and returns its virtual Id (including the # "$") proc ::safe::interpFindInAccessPath {slave path} { namespace upvar ::safe S$slave state if {![dict exists $state(access_path,remap) $path]} { return -code error "$path not found in access path $access_path" } return [dict get $state(access_path,remap) $path] } # # addToAccessPath: # add (if needed) a real directory to access path and return its # virtual token (including the "$"). proc ::safe::interpAddToAccessPath {slave path} { # first check if the directory is already in there # (inlined interpFindInAccessPath). namespace upvar ::safe S$slave state if {[dict exists $state(access_path,remap) $path]} { return [dict get $state(access_path,remap) $path] } # new one, add it: set token [PathToken [llength $state(access_path)]] lappend state(access_path) $path lappend state(access_path,slave) $token lappend state(access_path,map) $token $path lappend state(access_path,remap) $path $token lappend state(access_path,norm) [file normalize $path] SyncAccessPath $slave return $token } # This procedure applies the initializations to an already existing # interpreter. It is useful when you want to install the safe base aliases # into a preexisting safe interpreter. proc ::safe::InterpInit { slave access_path staticsok nestedok deletehook } { # Configure will generate an access_path when access_path is empty. InterpSetConfig $slave $access_path $staticsok $nestedok $deletehook # NB we need to add [namespace current], aliases are always absolute # paths. # These aliases let the slave load files to define new commands # This alias lets the slave use the encoding names, convertfrom, # convertto, and system, but not "encoding system " to set the # system encoding. # Handling Tcl Modules, we need a restricted form of Glob. # This alias interposes on the 'exit' command and cleanly terminates # the slave. foreach {command alias} { source AliasSource load AliasLoad encoding AliasEncoding exit interpDelete glob AliasGlob } { ::interp alias $slave $command {} [namespace current]::$alias $slave } # This alias lets the slave have access to a subset of the 'file' # command functionality. ::interp expose $slave file foreach subcommand {dirname extension rootname tail} { ::interp alias $slave ::tcl::file::$subcommand {} \ ::safe::AliasFileSubcommand $slave $subcommand } foreach subcommand { atime attributes copy delete executable exists isdirectory isfile link lstat mtime mkdir nativename normalize owned readable readlink rename size stat tempfile type volumes writable } { ::interp alias $slave ::tcl::file::$subcommand {} \ ::safe::BadSubcommand $slave file $subcommand } # Subcommands of info foreach {subcommand alias} { nameofexecutable AliasExeName } { ::interp alias $slave ::tcl::info::$subcommand \ {} [namespace current]::$alias $slave } # The allowed slave variables already have been set by Tcl_MakeSafe(3) # Source init.tcl and tm.tcl into the slave, to get auto_load and # other procedures defined: if {[catch {::interp eval $slave { source [file join $tcl_library init.tcl] }} msg opt]} { Log $slave "can't source init.tcl ($msg)" return -options $opt "can't source init.tcl into slave $slave ($msg)" } if {[catch {::interp eval $slave { source [file join $tcl_library tm.tcl] }} msg opt]} { Log $slave "can't source tm.tcl ($msg)" return -options $opt "can't source tm.tcl into slave $slave ($msg)" } # Sync the paths used to search for Tcl modules. This can be done only # now, after tm.tcl was loaded. namespace upvar ::safe S$slave state if {[llength $state(tm_path_slave)] > 0} { ::interp eval $slave [list \ ::tcl::tm::add {*}[lreverse $state(tm_path_slave)]] } return $slave } # Add (only if needed, avoid duplicates) 1 level of sub directories to an # existing path list. Also removes non directories from the returned # list. proc ::safe::AddSubDirs {pathList} { set res {} foreach dir $pathList { if {[file isdirectory $dir]} { # check that we don't have it yet as a children of a previous # dir if {$dir ni $res} { lappend res $dir } foreach sub [glob -directory $dir -nocomplain *] { if {[file isdirectory $sub] && ($sub ni $res)} { # new sub dir, add it ! lappend res $sub } } } } return $res } # This procedure deletes a safe slave managed by Safe Tcl and cleans up # associated state: proc ::safe::interpDelete {slave} { Log $slave "About to delete" NOTICE namespace upvar ::safe S$slave state # If the slave has a cleanup hook registered, call it. Check the # existance because we might be called to delete an interp which has # not been registered with us at all if {[info exists state(cleanupHook)]} { set hook $state(cleanupHook) if {[llength $hook]} { # remove the hook now, otherwise if the hook calls us somehow, # we'll loop unset state(cleanupHook) try { {*}$hook $slave } on error err { Log $slave "Delete hook error ($err)" } } } # Discard the global array of state associated with the slave, and # delete the interpreter. if {[info exists state]} { unset state } # if we have been called twice, the interp might have been deleted # already if {[::interp exists $slave]} { ::interp delete $slave Log $slave "Deleted" NOTICE } return } # Set (or get) the logging mecanism proc ::safe::setLogCmd {args} { variable Log set la [llength $args] if {$la == 0} { return $Log } elseif {$la == 1} { set Log [lindex $args 0] } else { set Log $args } if {$Log eq ""} { # Disable logging completely. Calls to it will be compiled out # of all users. proc ::safe::Log {args} {} } else { # Activate logging, define proper command. proc ::safe::Log {slave msg {type ERROR}} { variable Log {*}$Log "$type for slave $slave : $msg" return } } } # ------------------- END OF PUBLIC METHODS ------------ # # Sets the slave auto_path to the master recorded value. Also sets # tcl_library to the first token of the virtual path. # proc ::safe::SyncAccessPath {slave} { namespace upvar ::safe S$slave state set slave_access_path $state(access_path,slave) ::interp eval $slave [list set auto_path $slave_access_path] Log $slave "auto_path in $slave has been set to $slave_access_path"\ NOTICE # This code assumes that info library is the first element in the # list of auto_path's. See -> InterpSetConfig for the code which # ensures this condition. ::interp eval $slave [list \ set tcl_library [lindex $slave_access_path 0]] } # Returns the virtual token for directory number N. proc ::safe::PathToken {n} { # We need to have a ":" in the token string so [file join] on the # mac won't turn it into a relative path. return "\$p(:$n:)" ;# Form tested by case 7.2 } # # translate virtual path into real path # proc ::safe::TranslatePath {slave path} { namespace upvar ::safe S$slave state # somehow strip the namespaces 'functionality' out (the danger is that # we would strip valid macintosh "../" queries... : if {[string match "*::*" $path] || [string match "*..*" $path]} { return -code error "invalid characters in path $path" } # Use a cached map instead of computed local vars and subst. return [string map $state(access_path,map) $path] } # file name control (limit access to files/resources that should be a # valid tcl source file) proc ::safe::CheckFileName {slave file} { # This used to limit what can be sourced to ".tcl" and forbid files # with more than 1 dot and longer than 14 chars, but I changed that # for 8.4 as a safe interp has enough internal protection already to # allow sourcing anything. - hobbs if {![file exists $file]} { # don't tell the file path return -code error "no such file or directory" } if {![file readable $file]} { # don't tell the file path return -code error "not readable" } } # AliasFileSubcommand handles selected subcommands of [file] in safe # interpreters that are *almost* safe. In particular, it just acts to # prevent discovery of what home directories exist. proc ::safe::AliasFileSubcommand {slave subcommand name} { if {[string match ~* $name]} { set name ./$name } tailcall ::interp invokehidden $slave tcl:file:$subcommand $name } # AliasGlob is the target of the "glob" alias in safe interpreters. proc ::safe::AliasGlob {slave args} { Log $slave "GLOB ! $args" NOTICE set cmd {} set at 0 array set got { -directory 0 -nocomplain 0 -join 0 -tails 0 -- 0 } if {$::tcl_platform(platform) eq "windows"} { set dirPartRE {^(.*)[\\/]([^\\/]*)$} } else { set dirPartRE {^(.*)/([^/]*)$} } set dir {} set virtualdir {} while {$at < [llength $args]} { switch -glob -- [set opt [lindex $args $at]] { -nocomplain - -- - -join - -tails { lappend cmd $opt set got($opt) 1 incr at } -types - -type { lappend cmd -types [lindex $args [incr at]] incr at } -directory { if {$got($opt)} { return -code error \ {"-directory" cannot be used with "-path"} } set got($opt) 1 set virtualdir [lindex $args [incr at]] incr at } pkgIndex.tcl { # Oops, this is globbing a subdirectory in regular package # search. That is not wanted. Abort, handler does catch # already (because glob was not defined before). See # package.tcl, lines 484ff in tclPkgUnknown. return -code error "unknown command glob" } -* { Log $slave "Safe base rejecting glob option '$opt'" return -code error "Safe base rejecting glob option '$opt'" } default { break } } if {$got(--)} break } # Get the real path from the virtual one and check that the path is in the # access path of that slave. Done after basic argument processing so that # we know if -nocomplain is set. if {$got(-directory)} { try { set dir [TranslatePath $slave $virtualdir] DirInAccessPath $slave $dir } on error msg { Log $slave $msg if {$got(-nocomplain)} return return -code error "permission denied" } lappend cmd -directory $dir } # Apply the -join semantics ourselves if {$got(-join)} { set args [lreplace $args $at end [join [lrange $args $at end] "/"]] } # Process remaining pattern arguments set firstPattern [llength $cmd] foreach opt [lrange $args $at end] { if {![regexp $dirPartRE $opt -> thedir thefile]} { set thedir . } elseif {[string match ~* $thedir]} { set thedir ./$thedir } if {$thedir eq "*" && ($thefile eq "pkgIndex.tcl" || $thefile eq "*.tm")} { set mapped 0 foreach d [glob -directory [TranslatePath $slave $virtualdir] \ -types d -tails *] { catch { DirInAccessPath $slave \ [TranslatePath $slave [file join $virtualdir $d]] lappend cmd [file join $d $thefile] set mapped 1 } } if {$mapped} continue } try { DirInAccessPath $slave [TranslatePath $slave \ [file join $virtualdir $thedir]] } on error msg { Log $slave $msg if {$got(-nocomplain)} continue return -code error "permission denied" } lappend cmd $opt } Log $slave "GLOB = $cmd" NOTICE if {$got(-nocomplain) && [llength $cmd] eq $firstPattern} { return } try { set entries [::interp invokehidden $slave glob {*}$cmd] } on error msg { Log $slave $msg return -code error "script error" } Log $slave "GLOB < $entries" NOTICE # Translate path back to what the slave should see. set res {} set l [string length $dir] foreach p $entries { if {[string equal -length $l $dir $p]} { set p [string replace $p 0 [expr {$l-1}] $virtualdir] } lappend res $p } Log $slave "GLOB > $res" NOTICE return $res } # AliasSource is the target of the "source" alias in safe interpreters. proc ::safe::AliasSource {slave args} { set argc [llength $args] # Extended for handling of Tcl Modules to allow not only "source # filename", but "source -encoding E filename" as well. if {[lindex $args 0] eq "-encoding"} { incr argc -2 set encoding [lindex $args 1] set at 2 if {$encoding eq "identity"} { Log $slave "attempt to use the identity encoding" return -code error "permission denied" } } else { set at 0 set encoding {} } if {$argc != 1} { set msg "wrong # args: should be \"source ?-encoding E? fileName\"" Log $slave "$msg ($args)" return -code error $msg } set file [lindex $args $at] # get the real path from the virtual one. if {[catch { set realfile [TranslatePath $slave $file] } msg]} { Log $slave $msg return -code error "permission denied" } # check that the path is in the access path of that slave if {[catch { FileInAccessPath $slave $realfile } msg]} { Log $slave $msg return -code error "permission denied" } # do the checks on the filename : if {[catch { CheckFileName $slave $realfile } msg]} { Log $slave "$realfile:$msg" return -code error $msg } # Passed all the tests, lets source it. Note that we do this all manually # because we want to control [info script] in the slave so information # doesn't leak so much. [Bug 2913625] set old [::interp eval $slave {info script}] set replacementMsg "script error" set code [catch { set f [open $realfile] fconfigure $f -eofchar \032 if {$encoding ne ""} { fconfigure $f -encoding $encoding } set contents [read $f] close $f ::interp eval $slave [list info script $file] } msg opt] if {$code == 0} { set code [catch {::interp eval $slave $contents} msg opt] set replacementMsg $msg } catch {interp eval $slave [list info script $old]} # Note that all non-errors are fine result codes from [source], so we must # take a little care to do it properly. [Bug 2923613] if {$code == 1} { Log $slave $msg return -code error $replacementMsg } return -code $code -options $opt $msg } # AliasLoad is the target of the "load" alias in safe interpreters. proc ::safe::AliasLoad {slave file args} { set argc [llength $args] if {$argc > 2} { set msg "load error: too many arguments" Log $slave "$msg ($argc) {$file $args}" return -code error $msg } # package name (can be empty if file is not). set package [lindex $args 0] namespace upvar ::safe S$slave state # Determine where to load. load use a relative interp path and {} # means self, so we can directly and safely use passed arg. set target [lindex $args 1] if {$target ne ""} { # we will try to load into a sub sub interp; check that we want to # authorize that. if {!$state(nestedok)} { Log $slave "loading to a sub interp (nestedok)\ disabled (trying to load $package 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" Log $slave $msg return -code error $msg } if {!$state(staticsok)} { Log $slave "static packages loading disabled\ (trying to load $package to $target)" return -code error "permission denied (static package)" } } else { # file loading # get the real path from the virtual one. try { set file [TranslatePath $slave $file] } on error msg { Log $slave $msg return -code error "permission denied" } # check the translated path try { FileInAccessPath $slave $file } on error msg { Log $slave $msg return -code error "permission denied (path)" } } try { return [::interp invokehidden $slave load $file $package $target] } on error msg { Log $slave $msg return -code error $msg } } # FileInAccessPath raises an error if the file is not found in the list of # directories contained in the (master side recorded) slave's access path. # the security here relies on "file dirname" answering the proper # result... needs checking ? proc ::safe::FileInAccessPath {slave file} { namespace upvar ::safe S$slave state set access_path $state(access_path) if {[file isdirectory $file]} { return -code error "\"$file\": is a directory" } set parent [file dirname $file] # Normalize paths for comparison since lsearch knows nothing of # potential pathname anomalies. set norm_parent [file normalize $parent] namespace upvar ::safe S$slave state if {$norm_parent ni $state(access_path,norm)} { return -code error "\"$file\": not in access_path" } } proc ::safe::DirInAccessPath {slave dir} { namespace upvar ::safe S$slave state set access_path $state(access_path) if {[file isfile $dir]} { return -code error "\"$dir\": is a file" } # Normalize paths for comparison since lsearch knows nothing of # potential pathname anomalies. set norm_dir [file normalize $dir] namespace upvar ::safe S$slave state if {$norm_dir ni $state(access_path,norm)} { return -code error "\"$dir\": not in access_path" } } # This procedure is used to report an attempt to use an unsafe member of an # ensemble command. proc ::safe::BadSubcommand {slave command subcommand args} { set msg "not allowed to invoke subcommand $subcommand of $command" Log $slave $msg return -code error -errorcode {TCL SAFE SUBCOMMAND} $msg } # AliasEncoding is the target of the "encoding" alias in safe interpreters. proc ::safe::AliasEncoding {slave option args} { # Note that [encoding dirs] is not supported in safe slaves at all set subcommands {convertfrom convertto names system} try { set option [tcl::prefix match -error [list -level 1 -errorcode \ [list TCL LOOKUP INDEX option $option]] $subcommands $option] # Special case: [encoding system] ok, but [encoding system foo] not if {$option eq "system" && [llength $args]} { return -code error -errorcode {TCL WRONGARGS} \ "wrong # args: should be \"encoding system\"" } } on error {msg options} { Log $slave $msg return -options $options $msg } tailcall ::interp invokehidden $slave encoding $option {*}$args } # Various minor hiding of platform features. [Bug 2913625] proc ::safe::AliasExeName {slave} { return "" } proc ::safe::Setup {} { #### # # Setup the arguments parsing # #### # Share the descriptions set temp [::tcl::OptKeyRegister { {-accessPath -list {} "access path for the slave"} {-noStatics "prevent loading of statically linked pkgs"} {-statics true "loading of statically linked pkgs"} {-nestedLoadOk "allow nested loading"} {-nested false "nested loading"} {-deleteHook -script {} "delete hook"} }] # create case (slave is optional) ::tcl::OptKeyRegister { {?slave? -name {} "name of the slave (optional)"} } ::safe::interpCreate # adding the flags sub programs to the command program (relying on Opt's # internal implementation details) lappend ::tcl::OptDesc(::safe::interpCreate) $::tcl::OptDesc($temp) # init and configure (slave is needed) ::tcl::OptKeyRegister { {slave -name {} "name of the slave"} } ::safe::interpIC # adding the flags sub programs to the command program (relying on Opt's # internal implementation details) lappend ::tcl::OptDesc(::safe::interpIC) $::tcl::OptDesc($temp) # temp not needed anymore ::tcl::OptKeyDelete $temp #### # # Default: No logging. # #### setLogCmd {} # Log eventually. # To enable error logging, set Log to {puts stderr} for instance, # via setLogCmd. return } namespace eval ::safe { # internal variables # Log command, set via 'setLogCmd'. Logging is disabled when empty. variable Log {} # The package maintains a state array per slave interp under its # control. The name of this array is S. This array is # brought into scope where needed, using 'namespace upvar'. The S # prefix is used to avoid that a slave interp called "Log" smashes # the "Log" variable. # # The array's elements are: # # access_path : List of paths accessible to the slave. # access_path,norm : Ditto, in normalized form. # access_path,slave : Ditto, as the path tokens as seen by the slave. # access_path,map : dict ( token -> path ) # access_path,remap : dict ( path -> token ) # tm_path_slave : List of TM root directories, as tokens seen by the slave. # staticsok : Value of option -statics # nestedok : Value of option -nested # cleanupHook : Value of option -deleteHook } ::safe::Setup tcl8.6.5/library/reg/0000755000175000017500000000000012665173607014013 5ustar sergeisergeitcl8.6.5/library/reg/pkgIndex.tcl0000755000175000017500000000053112663660066016270 0ustar sergeisergeiif {([info commands ::tcl::pkgconfig] eq "") || ([info sharedlibextension] ne ".dll")} return if {[::tcl::pkgconfig get debug]} { package ifneeded registry 1.3.1 \ [list load [file join $dir tclreg13g.dll] registry] } else { package ifneeded registry 1.3.1 \ [list load [file join $dir tclreg13.dll] registry] } tcl8.6.5/library/encoding/0000755000175000017500000000000012665173607015024 5ustar sergeisergeitcl8.6.5/library/encoding/euc-kr.enc0000644000175000017500000026733611555560473016720 0ustar sergeisergei# Encoding file: euc-kr, multi-byte M 003F 0 90 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030003001300200B72025202600A8300300AD20152225FF3C223C20182019 201C201D3014301530083009300A300B300C300D300E300F3010301100B100D7 00F7226022642265221E223400B0203220332103212BFFE0FFE1FFE526422640 222022A52312220222072261225200A7203B2606260525CB25CF25CE25C725C6 25A125A025B325B225BD25BC219221902191219321943013226A226B221A223D 221D2235222B222C2208220B2286228722822283222A222922272228FFE20000 A2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000021D221D42200220300B4FF5E02C702D802DD02DA02D900B802DB00A100BF 02D0222E2211220F00A42109203025C125C025B725B626642660266126652667 2663229925C825A325D025D1259225A425A525A825A725A625A92668260F260E 261C261E00B62020202121952197219921962198266D2669266A266C327F321C 211633C7212233C233D821210000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF01FF02FF03FF04FF05FF06FF07FF08FF09FF0AFF0BFF0CFF0DFF0EFF0F FF10FF11FF12FF13FF14FF15FF16FF17FF18FF19FF1AFF1BFF1CFF1DFF1EFF1F FF20FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2F FF30FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3AFF3BFFE6FF3DFF3EFF3F FF40FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5AFF5BFF5CFF5DFFE30000 A4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000313131323133313431353136313731383139313A313B313C313D313E313F 3140314131423143314431453146314731483149314A314B314C314D314E314F 3150315131523153315431553156315731583159315A315B315C315D315E315F 3160316131623163316431653166316731683169316A316B316C316D316E316F 3170317131723173317431753176317731783179317A317B317C317D317E317F 3180318131823183318431853186318731883189318A318B318C318D318E0000 A5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000217021712172217321742175217621772178217900000000000000000000 2160216121622163216421652166216721682169000000000000000000000000 0000039103920393039403950396039703980399039A039B039C039D039E039F 03A003A103A303A403A503A603A703A803A90000000000000000000000000000 000003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C303C403C503C603C703C803C90000000000000000000000000000 A6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000025002502250C251025182514251C252C25242534253C25012503250F2513 251B251725232533252B253B254B2520252F25282537253F251D253025252538 254225122511251A251925162515250E250D251E251F25212522252625272529 252A252D252E25312532253525362539253A253D253E25402541254325442545 2546254725482549254A00000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00003395339633972113339833C433A333A433A533A63399339A339B339C339D 339E339F33A033A133A233CA338D338E338F33CF3388338933C833A733A833B0 33B133B233B333B433B533B633B733B833B93380338133823383338433BA33BB 33BC33BD33BE33BF33903391339233933394212633C033C1338A338B338C33D6 33C533AD33AE33AF33DB33A933AA33AB33AC33DD33D033D333C333C933DC33C6 0000000000000000000000000000000000000000000000000000000000000000 A8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000C600D000AA0126000001320000013F014100D8015200BA00DE0166014A 00003260326132623263326432653266326732683269326A326B326C326D326E 326F3270327132723273327432753276327732783279327A327B24D024D124D2 24D324D424D524D624D724D824D924DA24DB24DC24DD24DE24DF24E024E124E2 24E324E424E524E624E724E824E9246024612462246324642465246624672468 2469246A246B246C246D246E00BD2153215400BC00BE215B215C215D215E0000 A9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000E6011100F001270131013301380140014200F8015300DF00FE0167014B 01493200320132023203320432053206320732083209320A320B320C320D320E 320F3210321132123213321432153216321732183219321A321B249C249D249E 249F24A024A124A224A324A424A524A624A724A824A924AA24AB24AC24AD24AE 24AF24B024B124B224B324B424B5247424752476247724782479247A247B247C 247D247E247F24802481248200B900B200B32074207F20812082208320840000 AA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000304130423043304430453046304730483049304A304B304C304D304E304F 3050305130523053305430553056305730583059305A305B305C305D305E305F 3060306130623063306430653066306730683069306A306B306C306D306E306F 3070307130723073307430753076307730783079307A307B307C307D307E307F 3080308130823083308430853086308730883089308A308B308C308D308E308F 3090309130923093000000000000000000000000000000000000000000000000 AB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF 30B030B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF 30C030C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF 30D030D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000000 AC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000004100411041204130414041504010416041704180419041A041B041C041D 041E041F0420042104220423042404250426042704280429042A042B042C042D 042E042F00000000000000000000000000000000000000000000000000000000 000004300431043204330434043504510436043704380439043A043B043C043D 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000000000 B0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000AC00AC01AC04AC07AC08AC09AC0AAC10AC11AC12AC13AC14AC15AC16AC17 AC19AC1AAC1BAC1CAC1DAC20AC24AC2CAC2DAC2FAC30AC31AC38AC39AC3CAC40 AC4BAC4DAC54AC58AC5CAC70AC71AC74AC77AC78AC7AAC80AC81AC83AC84AC85 AC86AC89AC8AAC8BAC8CAC90AC94AC9CAC9DAC9FACA0ACA1ACA8ACA9ACAAACAC ACAFACB0ACB8ACB9ACBBACBCACBDACC1ACC4ACC8ACCCACD5ACD7ACE0ACE1ACE4 ACE7ACE8ACEAACECACEFACF0ACF1ACF3ACF5ACF6ACFCACFDAD00AD04AD060000 B1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000AD0CAD0DAD0FAD11AD18AD1CAD20AD29AD2CAD2DAD34AD35AD38AD3CAD44 AD45AD47AD49AD50AD54AD58AD61AD63AD6CAD6DAD70AD73AD74AD75AD76AD7B AD7CAD7DAD7FAD81AD82AD88AD89AD8CAD90AD9CAD9DADA4ADB7ADC0ADC1ADC4 ADC8ADD0ADD1ADD3ADDCADE0ADE4ADF8ADF9ADFCADFFAE00AE01AE08AE09AE0B AE0DAE14AE30AE31AE34AE37AE38AE3AAE40AE41AE43AE45AE46AE4AAE4CAE4D AE4EAE50AE54AE56AE5CAE5DAE5FAE60AE61AE65AE68AE69AE6CAE70AE780000 B2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000AE79AE7BAE7CAE7DAE84AE85AE8CAEBCAEBDAEBEAEC0AEC4AECCAECDAECF AED0AED1AED8AED9AEDCAEE8AEEBAEEDAEF4AEF8AEFCAF07AF08AF0DAF10AF2C AF2DAF30AF32AF34AF3CAF3DAF3FAF41AF42AF43AF48AF49AF50AF5CAF5DAF64 AF65AF79AF80AF84AF88AF90AF91AF95AF9CAFB8AFB9AFBCAFC0AFC7AFC8AFC9 AFCBAFCDAFCEAFD4AFDCAFE8AFE9AFF0AFF1AFF4AFF8B000B001B004B00CB010 B014B01CB01DB028B044B045B048B04AB04CB04EB053B054B055B057B0590000 B3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B05DB07CB07DB080B084B08CB08DB08FB091B098B099B09AB09CB09FB0A0 B0A1B0A2B0A8B0A9B0ABB0ACB0ADB0AEB0AFB0B1B0B3B0B4B0B5B0B8B0BCB0C4 B0C5B0C7B0C8B0C9B0D0B0D1B0D4B0D8B0E0B0E5B108B109B10BB10CB110B112 B113B118B119B11BB11CB11DB123B124B125B128B12CB134B135B137B138B139 B140B141B144B148B150B151B154B155B158B15CB160B178B179B17CB180B182 B188B189B18BB18DB192B193B194B198B19CB1A8B1CCB1D0B1D4B1DCB1DD0000 B4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B1DFB1E8B1E9B1ECB1F0B1F9B1FBB1FDB204B205B208B20BB20CB214B215 B217B219B220B234B23CB258B25CB260B268B269B274B275B27CB284B285B289 B290B291B294B298B299B29AB2A0B2A1B2A3B2A5B2A6B2AAB2ACB2B0B2B4B2C8 B2C9B2CCB2D0B2D2B2D8B2D9B2DBB2DDB2E2B2E4B2E5B2E6B2E8B2EBB2ECB2ED B2EEB2EFB2F3B2F4B2F5B2F7B2F8B2F9B2FAB2FBB2FFB300B301B304B308B310 B311B313B314B315B31CB354B355B356B358B35BB35CB35EB35FB364B3650000 B5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B367B369B36BB36EB370B371B374B378B380B381B383B384B385B38CB390 B394B3A0B3A1B3A8B3ACB3C4B3C5B3C8B3CBB3CCB3CEB3D0B3D4B3D5B3D7B3D9 B3DBB3DDB3E0B3E4B3E8B3FCB410B418B41CB420B428B429B42BB434B450B451 B454B458B460B461B463B465B46CB480B488B49DB4A4B4A8B4ACB4B5B4B7B4B9 B4C0B4C4B4C8B4D0B4D5B4DCB4DDB4E0B4E3B4E4B4E6B4ECB4EDB4EFB4F1B4F8 B514B515B518B51BB51CB524B525B527B528B529B52AB530B531B534B5380000 B6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B540B541B543B544B545B54BB54CB54DB550B554B55CB55DB55FB560B561 B5A0B5A1B5A4B5A8B5AAB5ABB5B0B5B1B5B3B5B4B5B5B5BBB5BCB5BDB5C0B5C4 B5CCB5CDB5CFB5D0B5D1B5D8B5ECB610B611B614B618B625B62CB634B648B664 B668B69CB69DB6A0B6A4B6ABB6ACB6B1B6D4B6F0B6F4B6F8B700B701B705B728 B729B72CB72FB730B738B739B73BB744B748B74CB754B755B760B764B768B770 B771B773B775B77CB77DB780B784B78CB78DB78FB790B791B792B796B7970000 B7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B798B799B79CB7A0B7A8B7A9B7ABB7ACB7ADB7B4B7B5B7B8B7C7B7C9B7EC B7EDB7F0B7F4B7FCB7FDB7FFB800B801B807B808B809B80CB810B818B819B81B B81DB824B825B828B82CB834B835B837B838B839B840B844B851B853B85CB85D B860B864B86CB86DB86FB871B878B87CB88DB8A8B8B0B8B4B8B8B8C0B8C1B8C3 B8C5B8CCB8D0B8D4B8DDB8DFB8E1B8E8B8E9B8ECB8F0B8F8B8F9B8FBB8FDB904 B918B920B93CB93DB940B944B94CB94FB951B958B959B95CB960B968B9690000 B8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B96BB96DB974B975B978B97CB984B985B987B989B98AB98DB98EB9ACB9AD B9B0B9B4B9BCB9BDB9BFB9C1B9C8B9C9B9CCB9CEB9CFB9D0B9D1B9D2B9D8B9D9 B9DBB9DDB9DEB9E1B9E3B9E4B9E5B9E8B9ECB9F4B9F5B9F7B9F8B9F9B9FABA00 BA01BA08BA15BA38BA39BA3CBA40BA42BA48BA49BA4BBA4DBA4EBA53BA54BA55 BA58BA5CBA64BA65BA67BA68BA69BA70BA71BA74BA78BA83BA84BA85BA87BA8C BAA8BAA9BAABBAACBAB0BAB2BAB8BAB9BABBBABDBAC4BAC8BAD8BAD9BAFC0000 B9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BB00BB04BB0DBB0FBB11BB18BB1CBB20BB29BB2BBB34BB35BB36BB38BB3B BB3CBB3DBB3EBB44BB45BB47BB49BB4DBB4FBB50BB54BB58BB61BB63BB6CBB88 BB8CBB90BBA4BBA8BBACBBB4BBB7BBC0BBC4BBC8BBD0BBD3BBF8BBF9BBFCBBFF BC00BC02BC08BC09BC0BBC0CBC0DBC0FBC11BC14BC15BC16BC17BC18BC1BBC1C BC1DBC1EBC1FBC24BC25BC27BC29BC2DBC30BC31BC34BC38BC40BC41BC43BC44 BC45BC49BC4CBC4DBC50BC5DBC84BC85BC88BC8BBC8CBC8EBC94BC95BC970000 BA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BC99BC9ABCA0BCA1BCA4BCA7BCA8BCB0BCB1BCB3BCB4BCB5BCBCBCBDBCC0 BCC4BCCDBCCFBCD0BCD1BCD5BCD8BCDCBCF4BCF5BCF6BCF8BCFCBD04BD05BD07 BD09BD10BD14BD24BD2CBD40BD48BD49BD4CBD50BD58BD59BD64BD68BD80BD81 BD84BD87BD88BD89BD8ABD90BD91BD93BD95BD99BD9ABD9CBDA4BDB0BDB8BDD4 BDD5BDD8BDDCBDE9BDF0BDF4BDF8BE00BE03BE05BE0CBE0DBE10BE14BE1CBE1D BE1FBE44BE45BE48BE4CBE4EBE54BE55BE57BE59BE5ABE5BBE60BE61BE640000 BB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BE68BE6ABE70BE71BE73BE74BE75BE7BBE7CBE7DBE80BE84BE8CBE8DBE8F BE90BE91BE98BE99BEA8BED0BED1BED4BED7BED8BEE0BEE3BEE4BEE5BEECBF01 BF08BF09BF18BF19BF1BBF1CBF1DBF40BF41BF44BF48BF50BF51BF55BF94BFB0 BFC5BFCCBFCDBFD0BFD4BFDCBFDFBFE1C03CC051C058C05CC060C068C069C090 C091C094C098C0A0C0A1C0A3C0A5C0ACC0ADC0AFC0B0C0B3C0B4C0B5C0B6C0BC C0BDC0BFC0C0C0C1C0C5C0C8C0C9C0CCC0D0C0D8C0D9C0DBC0DCC0DDC0E40000 BC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C0E5C0E8C0ECC0F4C0F5C0F7C0F9C100C104C108C110C115C11CC11DC11E C11FC120C123C124C126C127C12CC12DC12FC130C131C136C138C139C13CC140 C148C149C14BC14CC14DC154C155C158C15CC164C165C167C168C169C170C174 C178C185C18CC18DC18EC190C194C196C19CC19DC19FC1A1C1A5C1A8C1A9C1AC C1B0C1BDC1C4C1C8C1CCC1D4C1D7C1D8C1E0C1E4C1E8C1F0C1F1C1F3C1FCC1FD C200C204C20CC20DC20FC211C218C219C21CC21FC220C228C229C22BC22D0000 BD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C22FC231C232C234C248C250C251C254C258C260C265C26CC26DC270C274 C27CC27DC27FC281C288C289C290C298C29BC29DC2A4C2A5C2A8C2ACC2ADC2B4 C2B5C2B7C2B9C2DCC2DDC2E0C2E3C2E4C2EBC2ECC2EDC2EFC2F1C2F6C2F8C2F9 C2FBC2FCC300C308C309C30CC30DC313C314C315C318C31CC324C325C328C329 C345C368C369C36CC370C372C378C379C37CC37DC384C388C38CC3C0C3D8C3D9 C3DCC3DFC3E0C3E2C3E8C3E9C3EDC3F4C3F5C3F8C408C410C424C42CC4300000 BE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C434C43CC43DC448C464C465C468C46CC474C475C479C480C494C49CC4B8 C4BCC4E9C4F0C4F1C4F4C4F8C4FAC4FFC500C501C50CC510C514C51CC528C529 C52CC530C538C539C53BC53DC544C545C548C549C54AC54CC54DC54EC553C554 C555C557C558C559C55DC55EC560C561C564C568C570C571C573C574C575C57C C57DC580C584C587C58CC58DC58FC591C595C597C598C59CC5A0C5A9C5B4C5B5 C5B8C5B9C5BBC5BCC5BDC5BEC5C4C5C5C5C6C5C7C5C8C5C9C5CAC5CCC5CE0000 BF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C5D0C5D1C5D4C5D8C5E0C5E1C5E3C5E5C5ECC5EDC5EEC5F0C5F4C5F6C5F7 C5FCC5FDC5FEC5FFC600C601C605C606C607C608C60CC610C618C619C61BC61C C624C625C628C62CC62DC62EC630C633C634C635C637C639C63BC640C641C644 C648C650C651C653C654C655C65CC65DC660C66CC66FC671C678C679C67CC680 C688C689C68BC68DC694C695C698C69CC6A4C6A5C6A7C6A9C6B0C6B1C6B4C6B8 C6B9C6BAC6C0C6C1C6C3C6C5C6CCC6CDC6D0C6D4C6DCC6DDC6E0C6E1C6E80000 C0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C6E9C6ECC6F0C6F8C6F9C6FDC704C705C708C70CC714C715C717C719C720 C721C724C728C730C731C733C735C737C73CC73DC740C744C74AC74CC74DC74F C751C752C753C754C755C756C757C758C75CC760C768C76BC774C775C778C77C C77DC77EC783C784C785C787C788C789C78AC78EC790C791C794C796C797C798 C79AC7A0C7A1C7A3C7A4C7A5C7A6C7ACC7ADC7B0C7B4C7BCC7BDC7BFC7C0C7C1 C7C8C7C9C7CCC7CEC7D0C7D8C7DDC7E4C7E8C7ECC800C801C804C808C80A0000 C1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C810C811C813C815C816C81CC81DC820C824C82CC82DC82FC831C838C83C C840C848C849C84CC84DC854C870C871C874C878C87AC880C881C883C885C886 C887C88BC88CC88DC894C89DC89FC8A1C8A8C8BCC8BDC8C4C8C8C8CCC8D4C8D5 C8D7C8D9C8E0C8E1C8E4C8F5C8FCC8FDC900C904C905C906C90CC90DC90FC911 C918C92CC934C950C951C954C958C960C961C963C96CC970C974C97CC988C989 C98CC990C998C999C99BC99DC9C0C9C1C9C4C9C7C9C8C9CAC9D0C9D1C9D30000 C2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C9D5C9D6C9D9C9DAC9DCC9DDC9E0C9E2C9E4C9E7C9ECC9EDC9EFC9F0C9F1 C9F8C9F9C9FCCA00CA08CA09CA0BCA0CCA0DCA14CA18CA29CA4CCA4DCA50CA54 CA5CCA5DCA5FCA60CA61CA68CA7DCA84CA98CABCCABDCAC0CAC4CACCCACDCACF CAD1CAD3CAD8CAD9CAE0CAECCAF4CB08CB10CB14CB18CB20CB21CB41CB48CB49 CB4CCB50CB58CB59CB5DCB64CB78CB79CB9CCBB8CBD4CBE4CBE7CBE9CC0CCC0D CC10CC14CC1CCC1DCC21CC22CC27CC28CC29CC2CCC2ECC30CC38CC39CC3B0000 C3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CC3CCC3DCC3ECC44CC45CC48CC4CCC54CC55CC57CC58CC59CC60CC64CC66 CC68CC70CC75CC98CC99CC9CCCA0CCA8CCA9CCABCCACCCADCCB4CCB5CCB8CCBC CCC4CCC5CCC7CCC9CCD0CCD4CCE4CCECCCF0CD01CD08CD09CD0CCD10CD18CD19 CD1BCD1DCD24CD28CD2CCD39CD5CCD60CD64CD6CCD6DCD6FCD71CD78CD88CD94 CD95CD98CD9CCDA4CDA5CDA7CDA9CDB0CDC4CDCCCDD0CDE8CDECCDF0CDF8CDF9 CDFBCDFDCE04CE08CE0CCE14CE19CE20CE21CE24CE28CE30CE31CE33CE350000 C4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CE58CE59CE5CCE5FCE60CE61CE68CE69CE6BCE6DCE74CE75CE78CE7CCE84 CE85CE87CE89CE90CE91CE94CE98CEA0CEA1CEA3CEA4CEA5CEACCEADCEC1CEE4 CEE5CEE8CEEBCEECCEF4CEF5CEF7CEF8CEF9CF00CF01CF04CF08CF10CF11CF13 CF15CF1CCF20CF24CF2CCF2DCF2FCF30CF31CF38CF54CF55CF58CF5CCF64CF65 CF67CF69CF70CF71CF74CF78CF80CF85CF8CCFA1CFA8CFB0CFC4CFE0CFE1CFE4 CFE8CFF0CFF1CFF3CFF5CFFCD000D004D011D018D02DD034D035D038D03C0000 C5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D044D045D047D049D050D054D058D060D06CD06DD070D074D07CD07DD081 D0A4D0A5D0A8D0ACD0B4D0B5D0B7D0B9D0C0D0C1D0C4D0C8D0C9D0D0D0D1D0D3 D0D4D0D5D0DCD0DDD0E0D0E4D0ECD0EDD0EFD0F0D0F1D0F8D10DD130D131D134 D138D13AD140D141D143D144D145D14CD14DD150D154D15CD15DD15FD161D168 D16CD17CD184D188D1A0D1A1D1A4D1A8D1B0D1B1D1B3D1B5D1BAD1BCD1C0D1D8 D1F4D1F8D207D209D210D22CD22DD230D234D23CD23DD23FD241D248D25C0000 C6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D264D280D281D284D288D290D291D295D29CD2A0D2A4D2ACD2B1D2B8D2B9 D2BCD2BFD2C0D2C2D2C8D2C9D2CBD2D4D2D8D2DCD2E4D2E5D2F0D2F1D2F4D2F8 D300D301D303D305D30CD30DD30ED310D314D316D31CD31DD31FD320D321D325 D328D329D32CD330D338D339D33BD33CD33DD344D345D37CD37DD380D384D38C D38DD38FD390D391D398D399D39CD3A0D3A8D3A9D3ABD3ADD3B4D3B8D3BCD3C4 D3C5D3C8D3C9D3D0D3D8D3E1D3E3D3ECD3EDD3F0D3F4D3FCD3FDD3FFD4010000 C7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D408D41DD440D444D45CD460D464D46DD46FD478D479D47CD47FD480D482 D488D489D48BD48DD494D4A9D4CCD4D0D4D4D4DCD4DFD4E8D4ECD4F0D4F8D4FB D4FDD504D508D50CD514D515D517D53CD53DD540D544D54CD54DD54FD551D558 D559D55CD560D565D568D569D56BD56DD574D575D578D57CD584D585D587D588 D589D590D5A5D5C8D5C9D5CCD5D0D5D2D5D8D5D9D5DBD5DDD5E4D5E5D5E8D5EC D5F4D5F5D5F7D5F9D600D601D604D608D610D611D613D614D615D61CD6200000 C8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D624D62DD638D639D63CD640D645D648D649D64BD64DD651D654D655D658 D65CD667D669D670D671D674D683D685D68CD68DD690D694D69DD69FD6A1D6A8 D6ACD6B0D6B9D6BBD6C4D6C5D6C8D6CCD6D1D6D4D6D7D6D9D6E0D6E4D6E8D6F0 D6F5D6FCD6FDD700D704D711D718D719D71CD720D728D729D72BD72DD734D735 D738D73CD744D747D749D750D751D754D756D757D758D759D760D761D763D765 D769D76CD770D774D77CD77DD781D788D789D78CD790D798D799D79BD79D0000 CA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F3D4F73504750F952A053EF547554E556095AC15BB6668767B667B767EF 6B4C73C275C27A3C82DB8304885788888A368CC88DCF8EFB8FE699D5523B5374 5404606A61646BBC73CF811A89BA89D295A34F83520A58BE597859E65E725E79 61C763C0674667EC687F6F97764E770B78F57A087AFF7C21809D826E82718AEB 95934E6B559D66F76E3478A37AED845B8910874E97A852D8574E582A5D4C611F 61BE6221656267D16A446E1B751875B376E377B07D3A90AF945194529F950000 CB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000053235CAC753280DB92409598525B580859DC5CA15D175EB75F3A5F4A6177 6C5F757A75867CE07D737DB17F8C81548221859189418B1B92FC964D9C474ECB 4EF7500B51F1584F6137613E6168653969EA6F1175A5768676D67B8782A584CB F90093A7958B55805BA25751F9017CB37FB991B5502853BB5C455DE862D2636E 64DA64E76E2070AC795B8DDD8E1EF902907D924592F84E7E4EF650655DFE5EFA 61066957817186548E4793759A2B4E5E5091677068405109528D52926AA20000 CC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077BC92109ED452AB602F8FF2504861A963ED64CA683C6A846FC0818889A1 96945805727D72AC75047D797E6D80A9898B8B7490639D5162896C7A6F547D50 7F3A8A23517C614A7B9D8B199257938C4EAC4FD3501E50BE510652C152CD537F 577058835E9A5F91617661AC64CE656C666F66BB66F468976D87708570F1749F 74A574CA75D9786C78EC7ADF7AF67D457D938015803F811B83968B668F159015 93E1980398389A5A9BE84FC25553583A59515B635C4660B86212684268B00000 CD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000068E86EAA754C767878CE7A3D7CFB7E6B7E7C8A088AA18C3F968E9DC453E4 53E9544A547156FA59D15B645C3B5EAB62F765376545657266A067AF69C16CBD 75FC7690777E7A3F7F94800380A1818F82E682FD83F085C1883188B48AA5F903 8F9C932E96C798679AD89F1354ED659B66F2688F7A408C379D6056F057645D11 660668B168CD6EFE7428889E9BE46C68F9049AA84F9B516C5171529F5B545DE5 6050606D62F163A7653B73D97A7A86A38CA2978F4E325BE16208679C74DC0000 CE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000079D183D38A878AB28DE8904E934B98465ED369E885FF90EDF90551A05B98 5BEC616368FA6B3E704C742F74D87BA17F5083C589C08CAB95DC9928522E605D 62EC90024F8A5149532158D95EE366E06D38709A72C273D67B5080F1945B5366 639B7F6B4E565080584A58DE602A612762D069D09B415B8F7D1880B18F5F4EA4 50D154AC55AC5B0C5DA05DE7652A654E68216A4B72E1768E77EF7D5E7FF981A0 854E86DF8F038F4E90CA99039A559BAB4E184E454E5D4EC74FF1517752FE0000 CF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000534053E353E5548E5614577557A25BC75D875ED061FC62D8655167B867E9 69CB6B506BC66BEC6C426E9D707872D77396740377BF77E97A767D7F800981FC 8205820A82DF88628B338CFC8EC0901190B1926492B699D29A459CE99DD79F9C 570B5C4083CA97A097AB9EB4541B7A987FA488D98ECD90E158005C4863987A9F 5BAE5F137A797AAE828E8EAC5026523852F85377570862F363726B0A6DC37737 53A5735785688E7695D5673A6AC36F708A6D8ECC994BF90666776B788CB40000 D0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009B3CF90753EB572D594E63C669FB73EA78457ABA7AC57CFE8475898F8D73 903595A852FB574775477B6083CC921EF9086A58514B524B5287621F68D86975 969950C552A452E461C365A4683969FF747E7B4B82B983EB89B28B398FD19949 F9094ECA599764D266116A8E7434798179BD82A9887E887F895FF90A93264F0B 53CA602562716C727D1A7D664E98516277DC80AF4F014F0E5176518055DC5668 573B57FA57FC5914594759935BC45C905D0E5DF15E7E5FCC628065D765E30000 D1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000671E671F675E68CB68C46A5F6B3A6C236C7D6C826DC773987426742A7482 74A37578757F788178EF794179477948797A7B957D007DBA7F888006802D808C 8A188B4F8C488D779321932498E299519A0E9A0F9A659E927DCA4F76540962EE 685491D155AB513AF90BF90C5A1C61E6F90D62CF62FFF90EF90FF910F911F912 F91390A3F914F915F916F917F9188AFEF919F91AF91BF91C6696F91D7156F91E F91F96E3F920634F637A5357F921678F69606E73F9227537F923F924F9250000 D2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007D0DF926F927887256CA5A18F928F929F92AF92BF92C4E43F92D51675948 67F08010F92E59735E74649A79CA5FF5606C62C8637B5BE75BD752AAF92F5974 5F296012F930F931F9327459F933F934F935F936F937F93899D1F939F93AF93B F93CF93DF93EF93FF940F941F942F9436FC3F944F94581BF8FB260F1F946F947 8166F948F9495C3FF94AF94BF94CF94DF94EF94FF950F9515AE98A25677B7D10 F952F953F954F955F956F95780FDF958F9595C3C6CE5533F6EBA591A83360000 D3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E394EB64F4655AE571858C75F5665B765E66A806BB56E4D77ED7AEF7C1E 7DDE86CB88929132935B64BB6FBE737A75B890545556574D61BA64D466C76DE1 6E5B6F6D6FB975F0804381BD854189838AC78B5A931F6C9375537B548E0F905D 5510580258585E626207649E68E075767CD687B39EE84EE35788576E59275C0D 5CB15E365F85623464E173B381FA888B8CB8968A9EDB5B855FB760B350125200 52305716583558575C0E5C605CF65D8B5EA65F9260BC63116389641768430000 D4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000068F96AC26DD86E216ED46FE471FE76DC777979B17A3B840489A98CED8DF3 8E4890039014905390FD934D967697DC6BD27006725872A27368776379BF7BE4 7E9B8B8058A960C7656665FD66BE6C8C711E71C98C5A98134E6D7A814EDD51AC 51CD52D5540C61A76771685068DF6D1E6F7C75BC77B37AE580F484639285515C 6597675C679375D87AC78373F95A8C469017982D5C6F81C0829A9041906F920D 5F975D9D6A5971C8767B7B4985E48B0491279A30558761F6F95B76697F850000 D5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000863F87BA88F8908FF95C6D1B70D973DE7D61843DF95D916A99F1F95E4E82 53756B046B12703E721B862D9E1E524C8FA35D5064E5652C6B166FEB7C437E9C 85CD896489BD62C981D8881F5ECA67176D6A72FC7405746F878290DE4F865D0D 5FA0840A51B763A075654EAE5006516951C968816A117CAE7CB17CE7826F8AD2 8F1B91CF4FB6513752F554425EEC616E623E65C56ADA6FFE792A85DC882395AD 9A629A6A9E979ECE529B66C66B77701D792B8F6297426190620065236F230000 D6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000714974897DF4806F84EE8F269023934A51BD521752A36D0C70C888C25EC9 65826BAE6FC27C3E73754EE44F3656F9F95F5CBA5DBA601C73B27B2D7F9A7FCE 8046901E923496F6974898189F614F8B6FA779AE91B496B752DEF960648864C4 6AD36F5E7018721076E780018606865C8DEF8F0597329B6F9DFA9E75788C797F 7DA083C993049E7F9E938AD658DF5F046727702774CF7C60807E512170287262 78CA8CC28CDA8CF496F74E8650DA5BEE5ED6659971CE764277AD804A84FC0000 D7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000907C9B279F8D58D85A415C626A136DDA6F0F763B7D2F7E37851E893893E4 964B528965D267F369B46D416E9C700F7409746075597624786B8B2C985E516D 622E96784F96502B5D196DEA7DB88F2A5F8B61446817F961968652D2808B51DC 51CC695E7A1C7DBE83F196754FDA52295398540F550E5C6560A7674E68A86D6C 728172F874067483F96275E27C6C7F797FB8838988CF88E191CC91D096E29BC9 541D6F7E71D0749885FA8EAA96A39C579E9F67976DCB743381E89716782C0000 D8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007ACB7B207C926469746A75F278BC78E899AC9B549EBB5BDE5E556F20819C 83AB90884E07534D5A295DD25F4E6162633D666966FC6EFF6F2B7063779E842C 8513883B8F1399459C3B551C62B9672B6CAB8309896A977A4EA159845FD85FD9 671B7DB27F548292832B83BD8F1E909957CB59B95A925BD06627679A68856BCF 71647F758CB78CE390819B4581088C8A964C9A409EA55B5F6C13731B76F276DF 840C51AA8993514D519552C968C96C94770477207DBF7DEC97629EB56EC50000 D9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000851151A5540D547D660E669D69276E9F76BF7791831784C2879F91699298 9CF488824FAE519252DF59C65E3D61556478647966AE67D06A216BCD6BDB725F 72617441773877DB801782BC83058B008B288C8C67286C90726776EE77667A46 9DA96B7F6C92592267268499536F589359995EDF63CF663467736E3A732B7AD7 82D7932852D95DEB61AE61CB620A62C764AB65E069596B666BCB712173F7755D 7E46821E8302856A8AA38CBF97279D6158A89ED85011520E543B554F65870000 DA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006C767D0A7D0B805E868A958096EF52FF6C95726954735A9A5C3E5D4B5F4C 5FAE672A68B669636E3C6E4477097C737F8E85878B0E8FF797619EF45CB760B6 610D61AB654F65FB65FC6C116CEF739F73C97DE195945BC6871C8B10525D535A 62CD640F64B267346A386CCA73C0749E7B947C957E1B818A823685848FEB96F9 99C14F34534A53CD53DB62CC642C6500659169C36CEE6F5873ED7554762276E4 76FC78D078FB792C7D46822C87E08FD4981298EF52C362D464A56E246F510000 DB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000767C8DCB91B192629AEE9B435023508D574A59A85C285E475F77623F653E 65B965C16609678B699C6EC278C57D2180AA8180822B82B384A1868C8A2A8B17 90A696329F90500D4FF3F96357F95F9862DC6392676F6E43711976C380CC80DA 88F488F589198CE08F29914D966A4F2F4F705E1B67CF6822767D767E9B445E61 6A0A716971D4756AF9647E41854385E998DC4F107B4F7F7095A551E15E0668B5 6C3E6C4E6CDB72AF7BC483036CD5743A50FB528858C164D86A9774A776560000 DC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000078A7861795E29739F965535E5F018B8A8FA88FAF908A522577A59C499F08 4E19500251755C5B5E77661E663A67C468C570B3750175C579C97ADD8F279920 9A084FDD582158315BF6666E6B656D116E7A6F7D73E4752B83E988DC89138B5C 8F144F0F50D55310535C5B935FA9670D798F8179832F8514890789868F398F3B 99A59C12672C4E764FF859495C015CEF5CF0636768D270FD71A2742B7E2B84EC 8702902292D29CF34E0D4ED84FEF50855256526F5426549057E0592B5A660000 DD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005B5A5B755BCC5E9CF9666276657765A76D6E6EA572367B267C3F7F368150 8151819A8240829983A98A038CA08CE68CFB8D748DBA90E891DC961C964499D9 9CE7531752065429567458B35954596E5FFF61A4626E66106C7E711A76C67C89 7CDE7D1B82AC8CC196F0F9674F5B5F175F7F62C25D29670B68DA787C7E439D6C 4E1550995315532A535159835A625E8760B2618A624962796590678769A76BD4 6BD66BD76BD86CB8F968743575FA7812789179D579D87C837DCB7FE180A50000 DE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000813E81C283F2871A88E88AB98B6C8CBB9119975E98DB9F3B56AC5B2A5F6C 658C6AB36BAF6D5C6FF17015725D73AD8CA78CD3983B61916C3780589A014E4D 4E8B4E9B4ED54F3A4F3C4F7F4FDF50FF53F253F8550655E356DB58EB59625A11 5BEB5BFA5C045DF35E2B5F99601D6368659C65AF67F667FB68AD6B7B6C996CD7 6E23700973457802793E7940796079C17BE97D177D728086820D838E84D186C7 88DF8A508A5E8B1D8CDC8D668FAD90AA98FC99DF9E9D524AF9696714F96A0000 DF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005098522A5C7165636C5573CA7523759D7B97849C917897304E7764926BBA 715E85A94E09F96B674968EE6E17829F8518886B63F76F81921298AF4E0A50B7 50CF511F554655AA56175B405C195CE05E385E8A5EA05EC260F368516A616E58 723D724072C076F879657BB17FD488F389F48A738C618CDE971C585E74BD8CFD 55C7F96C7A617D2282727272751F7525F96D7B19588558FB5DBC5E8F5EB65F90 60556292637F654D669166D966F8681668F27280745E7B6E7D6E7DD67F720000 E0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000080E5821285AF897F8A93901D92E49ECD9F205915596D5E2D60DC66146673 67906C506DC56F5F77F378A984C691CB932B4ED950CA514855845B0B5BA36247 657E65CB6E32717D74017444748774BF766C79AA7DDA7E557FA8817A81B38239 861A87EC8A758DE3907892919425994D9BAE53685C5169546CC46D296E2B820C 859B893B8A2D8AAA96EA9F67526166B96BB27E9687FE8D0D9583965D651D6D89 71EEF96E57CE59D35BAC602760FA6210661F665F732973F976DB77017B6C0000 E1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008056807281658AA091924E1652E26B726D177A057B397D30F96F8CB053EC 562F58515BB55C0F5C115DE2624063836414662D68B36CBC6D886EAF701F70A4 71D27526758F758E76197B117BE07C2B7D207D39852C856D86078A34900D9061 90B592B797F69A374FD75C6C675F6D917C9F7E8C8B168D16901F5B6B5DFD640D 84C0905C98E173875B8B609A677E6DDE8A1F8AA69001980C5237F9707051788E 9396887091D74FEE53D755FD56DA578258FD5AC25B885CAB5CC05E2561010000 E2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000620D624B6388641C653665786A396B8A6C346D196F3171E772E973787407 74B27626776179C07A577AEA7CB97D8F7DAC7E617F9E81298331849084DA85EA 88968AB08B908F3890429083916C929692B9968B96A796A896D6970098089996 9AD39B1A53D4587E59195B705BBF6DD16F5A719F742174B9808583FD5DE15F87 5FAA604265EC6812696F6A536B896D356DF373E376FE77AC7B4D7D148123821C 834084F485638A628AC49187931E980699B4620C88538FF092655D075D270000 E3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005D69745F819D87686FD562FE7FD2893689724E1E4E5850E752DD5347627F 66077E698805965E4F8D5319563659CB5AA45C385C4E5C4D5E025F11604365BD 662F664267BE67F4731C77E2793A7FC5849484CD89968A668A698AE18C558C7A 57F45BD45F0F606F62ED690D6B966E5C71847BD287558B588EFE98DF98FE4F38 4F814FE1547B5A205BB8613C65B0666871FC7533795E7D33814E81E3839885AA 85CE87038A0A8EAB8F9BF9718FC559315BA45BE660895BE95C0B5FC36C810000 E4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9726DF1700B751A82AF8AF64EC05341F97396D96C0F4E9E4FC45152555E 5A255CE86211725982BD83AA86FE88598A1D963F96C599139D099D5D580A5CB3 5DBD5E4460E1611563E16A026E2591029354984E9C109F775B895CB86309664F 6848773C96C1978D98549B9F65A18B018ECB95BC55355CA95DD65EB56697764C 83F495C758D362BC72CE9D284EF0592E600F663B6B8379E79D26539354C057C3 5D16611B66D66DAF788D827E969897445384627C63966DB27E0A814B984D0000 E5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006AFB7F4C9DAF9E1A4E5F503B51B6591C60F963F66930723A8036F97491CE 5F31F975F9767D0482E5846F84BB85E58E8DF9774F6FF978F97958E45B436059 63DA6518656D6698F97A694A6A236D0B7001716C75D2760D79B37A70F97B7F8A F97C8944F97D8B9391C0967DF97E990A57045FA165BC6F01760079A68A9E99AD 9B5A9F6C510461B662916A8D81C6504358305F6671098A008AFA5B7C86164FFA 513C56B4594463A96DF95DAA696D51864E884F59F97FF980F9815982F9820000 E6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9836B5F6C5DF98474B57916F9858207824583398F3F8F5DF9869918F987 F988F9894EA6F98A57DF5F796613F98BF98C75AB7E798B6FF98D90069A5B56A5 582759F85A1F5BB4F98E5EF6F98FF9906350633BF991693D6C876CBF6D8E6D93 6DF56F14F99270DF71367159F99371C371D5F994784F786FF9957B757DE3F996 7E2FF997884D8EDFF998F999F99A925BF99B9CF6F99CF99DF99E60856D85F99F 71B1F9A0F9A195B153ADF9A2F9A3F9A467D3F9A5708E71307430827682D20000 E7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9A695BB9AE59E7D66C4F9A771C18449F9A8F9A9584BF9AAF9AB5DB85F71 F9AC6620668E697969AE6C386CF36E366F416FDA701B702F715071DF7370F9AD 745BF9AE74D476C87A4E7E93F9AFF9B082F18A608FCEF9B19348F9B29719F9B3 F9B44E42502AF9B5520853E166F36C6D6FCA730A777F7A6282AE85DD8602F9B6 88D48A638B7D8C6BF9B792B3F9B8971398104E944F0D4FC950B25348543E5433 55DA586258BA59675A1B5BE4609FF9B961CA655665FF666468A76C5A6FB30000 E8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000070CF71AC73527B7D87088AA49C329F075C4B6C8373447389923A6EAB7465 761F7A697E15860A514058C564C174EE751576707FC1909596CD99546E2674E6 7AA97AAA81E586D987788A1B5A495B8C5B9B68A169006D6373A97413742C7897 7DE97FEB81188155839E8C4C962E981166F05F8065FA67896C6A738B502D5A03 6B6A77EE59165D6C5DCD7325754FF9BAF9BB50E551F9582F592D599659DA5BE5 F9BCF9BD5DA262D76416649364FEF9BE66DCF9BF6A48F9C071FF7464F9C10000 E9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A887AAF7E477E5E80008170F9C287EF89818B209059F9C390809952617E 6B326D747E1F89258FB14FD150AD519752C757C758895BB95EB8614269956D8C 6E676EB6719474627528752C8073833884C98E0A939493DEF9C44E8E4F515076 512A53C853CB53F35B875BD35C24611A618265F4725B7397744076C279507991 79B97D067FBD828B85D5865E8FC2904790F591EA968596E896E952D65F6765ED 6631682F715C7A3690C1980A4E91F9C56A526B9E6F907189801882B885530000 EA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000904B969596F297FB851A9B314E90718A96C45143539F54E15713571257A3 5A9B5AC45BC36028613F63F46C856D396E726E907230733F745782D188818F45 9060F9C6966298589D1B67088D8A925E4F4D504950DE5371570D59D45A015C09 617066906E2D7232744B7DEF80C3840E8466853F875F885B89188B02905597CB 9B4F4E734F915112516AF9C7552F55A95B7A5BA55E7C5E7D5EBE60A060DF6108 610963C465386709F9C867D467DAF9C9696169626CB96D27F9CA6E38F9CB0000 EB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006FE173367337F9CC745C7531F9CD7652F9CEF9CF7DAD81FE843888D58A98 8ADB8AED8E308E42904A903E907A914991C9936EF9D0F9D15809F9D26BD38089 80B2F9D3F9D45141596B5C39F9D5F9D66F6473A780E48D07F9D79217958FF9D8 F9D9F9DAF9DB807F620E701C7D68878DF9DC57A0606961476BB78ABE928096B1 4E59541F6DEB852D967097F398EE63D66CE3909151DD61C981BA9DF94F9D501A 51005B9C610F61FF64EC69056BC5759177E37FA98264858F87FB88638ABC0000 EC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008B7091AB4E8C4EE54F0AF9DDF9DE593759E8F9DF5DF25F1B5F5B6021F9E0 F9E1F9E2F9E3723E73E5F9E4757075CDF9E579FBF9E6800C8033808482E18351 F9E7F9E88CBD8CB39087F9E9F9EA98F4990CF9EBF9EC703776CA7FCA7FCC7FFC 8B1A4EBA4EC152035370F9ED54BD56E059FB5BC55F155FCD6E6EF9EEF9EF7D6A 8335F9F086938A8DF9F1976D9777F9F2F9F34E004F5A4F7E58F965E56EA29038 93B099B94EFB58EC598A59D96041F9F4F9F57A14F9F6834F8CC3516553440000 ED 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9F7F9F8F9F94ECD52695B5582BF4ED4523A54A859C959FF5B505B575B5C 606361486ECB7099716E738674F775B578C17D2B800581EA8328851785C98AEE 8CC796CC4F5C52FA56BC65AB6628707C70B872357DBD828D914C96C09D725B71 68E76B986F7A76DE5C9166AB6F5B7BB47C2A883696DC4E084ED75320583458BB 58EF596C5C075E335E845F35638C66B267566A1F6AA36B0C6F3F7246F9FA7350 748B7AE07CA7817881DF81E7838A846C8523859485CF88DD8D1391AC95770000 EE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000969C518D54C957285BB0624D6750683D68936E3D6ED3707D7E2188C18CA1 8F099F4B9F4E722D7B8F8ACD931A4F474F4E5132548059D05E9562B56775696E 6A176CAE6E1A72D9732A75BD7BB87D3582E783F9845785F78A5B8CAF8E879019 90B896CE9F5F52E3540A5AE15BC2645865756EF472C4F9FB76847A4D7B1B7C4D 7E3E7FDF837B8B2B8CCA8D648DE18E5F8FEA8FF9906993D14F434F7A50B35168 5178524D526A5861587C59605C085C555EDB609B623068136BBF6C086FB10000 EF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000714E742075307538755176727B4C7B8B7BAD7BC67E8F8A6E8F3E8F49923F 92939322942B96FB985A986B991E5207622A62986D5976647ACA7BC07D765360 5CBE5E976F3870B97C9897119B8E9EDE63A5647A87764E014E954EAD505C5075 544859C35B9A5E405EAD5EF75F8160C5633A653F657465CC6676667867FE6968 6A896B636C406DC06DE86E1F6E5E701E70A1738E73FD753A775B7887798E7A0B 7A7D7CBE7D8E82478A028AEA8C9E912D914A91D8926692CC9320970697560000 F0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000975C98029F0E52365291557C58245E1D5F1F608C63D068AF6FDF796D7B2C 81CD85BA88FD8AF88E44918D9664969B973D984C9F4A4FCE514651CB52A95632 5F145F6B63AA64CD65E9664166FA66F9671D689D68D769FD6F156F6E716771E5 722A74AA773A7956795A79DF7A207A957C977CDF7D447E70808785FB86A48A54 8ABF8D998E819020906D91E3963B96D59CE565CF7C078DB393C35B585C0A5352 62D9731D50275B975F9E60B0616B68D56DD9742E7A2E7D427D9C7E31816B0000 F1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008E2A8E35937E94184F5057505DE65EA7632B7F6A4E3B4F4F4F8F505A59DD 80C4546A546855FE594F5B995DDE5EDA665D673167F1682A6CE86D326E4A6F8D 70B773E075877C4C7D027D2C7DA2821F86DB8A3B8A858D708E8A8F339031914E 9152944499D07AF97CA54FCA510151C657C85BEF5CFB66596A3D6D5A6E966FEC 710C756F7AE388229021907596CB99FF83014E2D4EF2884691CD537D6ADB696B 6C41847A589E618E66FE62EF70DD751175C77E5284B88B498D084E4B53EA0000 F2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000054AB573057405FD763016307646F652F65E8667A679D67B36B626C606C9A 6F2C77E57825794979577D1980A2810281F3829D82B787188A8CF9FC8D048DBE 907276F47A197A377E548077550755D45875632F64226649664B686D699B6B84 6D256EB173CD746874A1755B75B976E1771E778B79E67E097E1D81FB852F8897 8A3A8CD18EEB8FB0903293AD9663967397074F8453F159EA5AC95E19684E74C6 75BE79E97A9281A386ED8CEA8DCC8FED659F6715F9FD57F76F577DDD8F2F0000 F3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000093F696C65FB561F26F844E144F98501F53C955DF5D6F5DEE6B216B6478CB 7B9AF9FE8E498ECA906E6349643E77407A84932F947F9F6A64B06FAF71E674A8 74DA7AC47C127E827CB27E988B9A8D0A947D9910994C52395BDF64E6672D7D2E 50ED53C358796158615961FA65AC7AD98B928B9650095021527555315A3C5EE0 5F706134655E660C663666A269CD6EC46F32731676217A938139825983D684BC 50B557F05BC05BE85F6963A178267DB583DC852191C791F5518A67F57B560000 F4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008CAC51C459BB60BD8655501CF9FF52545C3A617D621A62D364F265A56ECC 7620810A8E60965F96BB4EDF5343559859295DDD64C56CC96DFA73947A7F821B 85A68CE48E10907791E795E1962197C651F854F255865FB964A46F887DB48F1F 8F4D943550C95C166CBE6DFB751B77BB7C3D7C648A798AC2581E59BE5E166377 7252758A776B8ADC8CBC8F125EF366746DF8807D83C18ACB97519BD6FA005243 66FF6D956EEF7DE08AE6902E905E9AD4521D527F54E86194628462DB68A20000 F5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006912695A6A3570927126785D7901790E79D27A0D8096827882D583498549 8C828D859162918B91AE4FC356D171ED77D7870089F85BF85FD6675190A853E2 585A5BF560A4618164607E3D80708525928364AE50AC5D146700589C62BD63A8 690E69786A1E6E6B76BA79CB82BB84298ACF8DA88FFD9112914B919C93109318 939A96DB9A369C0D4E11755C795D7AFA7B517BC97E2E84C48E598E748EF89010 6625693F744351FA672E9EDC51455FE06C9687F2885D887760B481B584030000 F6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008D0553D6543956345A365C31708A7FE0805A810681ED8DA391899A5F9DF2 50744EC453A060FB6E2C5C644F88502455E45CD95E5F606568946CBB6DC471BE 75D475F476617A1A7A497DC77DFB7F6E81F486A98F1C96C999B39F52524752C5 98ED89AA4E0367D26F064FB55BE267956C886D78741B782791DD937C87C479E4 7A315FEB4ED654A4553E58AE59A560F0625362D6673669558235964099B199DD 502C53535544577CFA016258FA0264E2666B67DD6FC16FEF742274388A170000 F7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000094385451560657665F48619A6B4E705870AD7DBB8A95596A812B63A27708 803D8CAA5854642D69BB5B955E116E6FFA038569514C53F0592A6020614B6B86 6C706CF07B1E80CE82D48DC690B098B1FA0464C76FA464916504514E5410571F 8A0E615F6876FA0575DB7B527D71901A580669CC817F892A9000983950785957 59AC6295900F9B2A615D727995D657615A465DF4628A64AD64FA67776CE26D3E 722C743678347F7782AD8DDB981752245742677F724874E38CA98FA692110000 F8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000962A516B53ED634C4F695504609665576C9B6D7F724C72FD7A1789878C9D 5F6D6F8E70F981A8610E4FBF504F624172477BC77DE87FE9904D97AD9A198CB6 576A5E7367B0840D8A5554205B165E635EE25F0A658380BA853D9589965B4F48 5305530D530F548654FA57035E036016629B62B16355FA066CE16D6675B17832 80DE812F82DE846184B2888D8912900B92EA98FD9B915E4566B466DD70117206 FA074FF5527D5F6A615367536A196F0274E2796888688C7998C798C49A430000 F9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000054C17A1F69538AF78C4A98A899AE5F7C62AB75B276AE88AB907F96425339 5F3C5FC56CCC73CC7562758B7B4682FE999D4E4F903C4E0B4F5553A6590F5EC8 66306CB37455837787668CC09050971E9C1558D15B7886508B149DB45BD26068 608D65F16C576F226FA3701A7F557FF095919592965097D352728F4451FD542B 54B85563558A6ABB6DB57DD88266929C96779E79540854C876D286E495A495D4 965C4EA24F0959EE5AE65DF760526297676D68416C866E2F7F38809B822A0000 FA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FA08FA0998054EA5505554B35793595A5B695BB361C869776D77702387F9 89E38A728AE7908299ED9AB852BE683850165E78674F8347884C4EAB541156AE 73E6911597FF9909995799995653589F865B8A3161B26AF6737B8ED26B4796AA 9A57595572008D6B97694FD45CF45F2661F8665B6CEB70AB738473B973FE7729 774D7D437D627E2382378852FA0A8CE29249986F5B517A74884098015ACC4FE0 5354593E5CFD633E6D7972F98105810783A292CF98304EA851445211578B0000 FB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F626CC26ECE7005705070AF719273E97469834A87A28861900890A293A3 99A8516E5F5760E0616766B385598E4A91AF978B4E4E4E92547C58D558FA597D 5CB55F2762366248660A66676BEB6D696DCF6E566EF86F946FE06FE9705D72D0 7425745A74E07693795C7CCA7E1E80E182A6846B84BF864E865F87748B778C6A 93AC9800986560D1621691775A5A660F6DF76E3E743F9B425FFD60DA7B0F54C4 5F186C5E6CD36D2A70D87D0586798A0C9D3B5316548C5B056A3A706B75750000 FC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000798D79BE82B183EF8A718B418CA89774FA0B64F4652B78BA78BB7A6B4E38 559A59505BA65E7B60A363DB6B61666568536E19716574B07D0890849A699C25 6D3B6ED1733E8C4195CA51F05E4C5FA8604D60F66130614C6643664469A56CC1 6E5F6EC96F62714C749C76877BC17C27835287579051968D9EC3532F56DE5EFB 5F8A6062609461F7666667036A9C6DEE6FAE7070736A7E6A81BE833486D48AA8 8CC4528373725B966A6B940454EE56865B5D6548658566C9689F6D8D6DC60000 FD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000723B80B491759A4D4FAF5019539A540E543C558955C55E3F5F8C673D7166 73DD900552DB52F3586458CE7104718F71FB85B08A13668885A855A76684714A 8431534955996BC15F595FBD63EE668971478AF18F1D9EBE4F11643A70CB7566 866760648B4E9DF8514751F653086D3680F89ED166156B23709875D554035C79 7D078A166B206B3D6B46543860706D3D7FD5820850D651DE559C566B56CD59EC 5B095E0C619961986231665E66E6719971B971BA72A779A77A007FB28A700000 tcl8.6.5/library/encoding/cp861.enc0000644000175000017500000000210211555560473016345 0ustar sergeisergei# Encoding file: cp861, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C700FC00E900E200E400E000E500E700EA00EB00E800D000F000DE00C400C5 00C900E600C600F400F600FE00FB00DD00FD00D600DC00F800A300D820A70192 00E100ED00F300FA00C100CD00D300DA00BF231000AC00BD00BC00A100AB00BB 259125922593250225242561256225562555256325512557255D255C255B2510 25142534252C251C2500253C255E255F255A25542569256625602550256C2567 2568256425652559255825522553256B256A2518250C25882584258C25902580 03B100DF039303C003A303C300B503C403A6039803A903B4221E03C603B52229 226100B1226522642320232100F7224800B0221900B7221A207F00B225A000A0 tcl8.6.5/library/encoding/jis0212.enc0000644000175000017500000021247611555560473016617 0ustar sergeisergei# Encoding file: jis0212, double-byte D 2244 0 68 22 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000002D8 02C700B802D902DD00AF02DB02DA007E03840385000000000000000000000000 0000000000A100A600BF00000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000BA00AA00A900AE2122 00A4211600000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 26 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000038603880389038A03AA0000038C0000038E03AB0000038F000000000000 000003AC03AD03AE03AF03CA039003CC03C203CD03CB03B003CE000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 27 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000004020403040404050406040704080409040A040B040C040E040F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000004520453045404550456045704580459045A045B045C045E045F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 29 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000C60110000001260000013200000141013F0000014A00D8015200000166 00DE000000000000000000000000000000000000000000000000000000000000 000000E6011100F00127013101330138014201400149014B00F8015300DF0167 00FE000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 2A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000C100C000C400C2010201CD0100010400C500C301060108010C00C7010A 010E00C900C800CB00CA011A0116011201180000011C011E01220120012400CD 00CC00CF00CE01CF0130012A012E0128013401360139013D013B014301470145 00D100D300D200D600D401D10150014C00D5015401580156015A015C0160015E 0164016200DA00D900DC00DB016C01D30170016A0172016E016801D701DB01D9 01D5017400DD017801760179017D017B00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 2B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000E100E000E400E2010301CE0101010500E500E301070109010D00E7010B 010F00E900E800EB00EA011B01170113011901F5011D011F00000121012500ED 00EC00EF00EE01D00000012B012F012901350137013A013E013C014401480146 00F100F300F200F600F401D20151014D00F5015501590157015B015D0161015F 0165016300FA00F900FC00FB016D01D40171016B0173016F016901D801DC01DA 01D6017500FD00FF0177017A017E017C00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 30 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E024E044E054E0C4E124E1F4E234E244E284E2B4E2E4E2F4E304E354E40 4E414E444E474E514E5A4E5C4E634E684E694E744E754E794E7F4E8D4E964E97 4E9D4EAF4EB94EC34ED04EDA4EDB4EE04EE14EE24EE84EEF4EF14EF34EF54EFD 4EFE4EFF4F004F024F034F084F0B4F0C4F124F154F164F174F194F2E4F314F60 4F334F354F374F394F3B4F3E4F404F424F484F494F4B4F4C4F524F544F564F58 4F5F4F634F6A4F6C4F6E4F714F774F784F794F7A4F7D4F7E4F814F824F840000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 31 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F854F894F8A4F8C4F8E4F904F924F934F944F974F994F9A4F9E4F9F4FB2 4FB74FB94FBB4FBC4FBD4FBE4FC04FC14FC54FC64FC84FC94FCB4FCC4FCD4FCF 4FD24FDC4FE04FE24FF04FF24FFC4FFD4FFF5000500150045007500A500C500E 5010501350175018501B501C501D501E50225027502E50305032503350355040 5041504250455046504A504C504E50515052505350575059505F506050625063 50665067506A506D50705071503B5081508350845086508A508E508F50900000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 32 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005092509350945096509B509C509E509F50A050A150A250AA50AF50B050B9 50BA50BD50C050C350C450C750CC50CE50D050D350D450D850DC50DD50DF50E2 50E450E650E850E950EF50F150F650FA50FE5103510651075108510B510C510D 510E50F2511051175119511B511C511D511E512351275128512C512D512F5131 513351345135513851395142514A514F5153515551575158515F51645166517E 51835184518B518E5198519D51A151A351AD51B851BA51BC51BE51BF51C20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 33 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000051C851CF51D151D251D351D551D851DE51E251E551EE51F251F351F451F7 5201520252055212521352155216521852225228523152325235523C52455249 525552575258525A525C525F526052615266526E527752785279528052825285 528A528C52935295529652975298529A529C52A452A552A652A752AF52B052B6 52B752B852BA52BB52BD52C052C452C652C852CC52CF52D152D452D652DB52DC 52E152E552E852E952EA52EC52F052F152F452F652F753005303530A530B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 34 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000530C531153135318531B531C531E531F5325532753285329532B532C532D 533053325335533C533D533E5342534C534B5359535B536153635365536C536D 53725379537E538353875388538E539353945399539D53A153A453AA53AB53AF 53B253B453B553B753B853BA53BD53C053C553CF53D253D353D553DA53DD53DE 53E053E653E753F554025413541A542154275428542A542F5431543454355443 54445447544D544F545E54625464546654675469546B546D546E5474547F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 35 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000054815483548554885489548D549154955496549C549F54A154A654A754A9 54AA54AD54AE54B154B754B954BA54BB54BF54C654CA54CD54CE54E054EA54EC 54EF54F654FC54FE54FF55005501550555085509550C550D550E5515552A552B 553255355536553B553C553D554155475549554A554D555055515558555A555B 555E5560556155645566557F5581558255865588558E558F5591559255935594 559755A355A455AD55B255BF55C155C355C655C955CB55CC55CE55D155D20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 36 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000055D355D755D855DB55DE55E255E955F655FF56055608560A560D560E560F 5610561156125619562C56305633563556375639563B563C563D563F56405641 5643564456465649564B564D564F5654565E566056615662566356665669566D 566F567156725675568456855688568B568C56955699569A569D569E569F56A6 56A756A856A956AB56AC56AD56B156B356B756BE56C556C956CA56CB56CF56D0 56CC56CD56D956DC56DD56DF56E156E456E556E656E756E856F156EB56ED0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 37 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000056F656F7570157025707570A570C57115715571A571B571D572057225723 572457255729572A572C572E572F57335734573D573E573F57455746574C574D 57525762576557675768576B576D576E576F5770577157735774577557775779 577A577B577C577E57815783578C579457975799579A579C579D579E579F57A1 579557A757A857A957AC57B857BD57C757C857CC57CF57D557DD57DE57E457E6 57E757E957ED57F057F557F657F857FD57FE57FF580358045808580957E10000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 38 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000580C580D581B581E581F582058265827582D58325839583F5849584C584D 584F58505855585F58615864586758685878587C587F58805881588758885889 588A588C588D588F589058945896589D58A058A158A258A658A958B158B258C4 58BC58C258C858CD58CE58D058D258D458D658DA58DD58E158E258E958F35905 5906590B590C5912591359148641591D5921592359245928592F593059335935 5936593F59435946595259535959595B595D595E595F59615963596B596D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 39 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000596F5972597559765979597B597C598B598C598E599259955997599F59A4 59A759AD59AE59AF59B059B359B759BA59BC59C159C359C459C859CA59CD59D2 59DD59DE59DF59E359E459E759EE59EF59F159F259F459F75A005A045A0C5A0D 5A0E5A125A135A1E5A235A245A275A285A2A5A2D5A305A445A455A475A485A4C 5A505A555A5E5A635A655A675A6D5A775A7A5A7B5A7E5A8B5A905A935A965A99 5A9C5A9E5A9F5AA05AA25AA75AAC5AB15AB25AB35AB55AB85ABA5ABB5ABF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005AC45AC65AC85ACF5ADA5ADC5AE05AE55AEA5AEE5AF55AF65AFD5B005B01 5B085B175B345B195B1B5B1D5B215B255B2D5B385B415B4B5B4C5B525B565B5E 5B685B6E5B6F5B7C5B7D5B7E5B7F5B815B845B865B8A5B8E5B905B915B935B94 5B965BA85BA95BAC5BAD5BAF5BB15BB25BB75BBA5BBC5BC05BC15BCD5BCF5BD6 5BD75BD85BD95BDA5BE05BEF5BF15BF45BFD5C0C5C175C1E5C1F5C235C265C29 5C2B5C2C5C2E5C305C325C355C365C595C5A5C5C5C625C635C675C685C690000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C6D5C705C745C755C7A5C7B5C7C5C7D5C875C885C8A5C8F5C925C9D5C9F 5CA05CA25CA35CA65CAA5CB25CB45CB55CBA5CC95CCB5CD25CDD5CD75CEE5CF1 5CF25CF45D015D065D0D5D125D2B5D235D245D265D275D315D345D395D3D5D3F 5D425D435D465D485D555D515D595D4A5D5F5D605D615D625D645D6A5D6D5D70 5D795D7A5D7E5D7F5D815D835D885D8A5D925D935D945D955D995D9B5D9F5DA0 5DA75DAB5DB05DB45DB85DB95DC35DC75DCB5DD05DCE5DD85DD95DE05DE40000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005DE95DF85DF95E005E075E0D5E125E145E155E185E1F5E205E2E5E285E32 5E355E3E5E4B5E505E495E515E565E585E5B5E5C5E5E5E685E6A5E6B5E6C5E6D 5E6E5E705E805E8B5E8E5EA25EA45EA55EA85EAA5EAC5EB15EB35EBD5EBE5EBF 5EC65ECC5ECB5ECE5ED15ED25ED45ED55EDC5EDE5EE55EEB5F025F065F075F08 5F0E5F195F1C5F1D5F215F225F235F245F285F2B5F2C5F2E5F305F345F365F3B 5F3D5F3F5F405F445F455F475F4D5F505F545F585F5B5F605F635F645F670000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F6F5F725F745F755F785F7A5F7D5F7E5F895F8D5F8F5F965F9C5F9D5FA2 5FA75FAB5FA45FAC5FAF5FB05FB15FB85FC45FC75FC85FC95FCB5FD05FD15FD2 5FD35FD45FDE5FE15FE25FE85FE95FEA5FEC5FED5FEE5FEF5FF25FF35FF65FFA 5FFC6007600A600D6013601460176018601A601F6024602D6033603560406047 60486049604C6051605460566057605D606160676071607E607F608260866088 608A608E6091609360956098609D609E60A260A460A560A860B060B160B70000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000060BB60BE60C260C460C860C960CA60CB60CE60CF60D460D560D960DB60DD 60DE60E260E560F260F560F860FC60FD61026107610A610C6110611161126113 6114611661176119611C611E6122612A612B6130613161356136613761396141 614561466149615E6160616C61726178617B617C617F6180618161836184618B 618D6192619361976198619C619D619F61A061A561A861AA61AD61B861B961BC 61C061C161C261CE61CF61D561DC61DD61DE61DF61E161E261E761E961E50000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000061EC61ED61EF620162036204620762136215621C62206222622362276229 622B6239623D6242624362446246624C62506251625262546256625A625C6264 626D626F6273627A627D628D628E628F629062A662A862B362B662B762BA62BE 62BF62C462CE62D562D662DA62EA62F262F462FC62FD63036304630A630B630D 63106313631663186329632A632D633563366339633C63416342634363446346 634A634B634E6352635363546358635B63656366636C636D6371637463750000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 40 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006378637C637D637F638263846387638A6390639463956399639A639E63A4 63A663AD63AE63AF63BD63C163C563C863CE63D163D363D463D563DC63E063E5 63EA63EC63F263F363F563F863F96409640A6410641264146418641E64206422 642464256429642A642F64306435643D643F644B644F6451645264536454645A 645B645C645D645F646064616463646D64736474647B647D64856487648F6490 649164986499649B649D649F64A164A364A664A864AC64B364BD64BE64BF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 41 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000064C464C964CA64CB64CC64CE64D064D164D564D764E464E564E964EA64ED 64F064F564F764FB64FF6501650465086509650A650F6513651465166519651B 651E651F652265266529652E6531653A653C653D654365476549655065526554 655F65606567656B657A657D65816585658A659265956598659D65A065A365A6 65AE65B265B365B465BF65C265C865C965CE65D065D465D665D865DF65F065F2 65F465F565F965FE65FF6600660466086609660D6611661266156616661D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 42 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000661E662166226623662466266629662A662B662C662E6630663166336639 6637664066456646664A664C6651664E665766586659665B665C6660666166FB 666A666B666C667E66736675667F667766786679667B6680667C668B668C668D 669066926699669A669B669C669F66A066A466AD66B166B266B566BB66BF66C0 66C266C366C866CC66CE66CF66D466DB66DF66E866EB66EC66EE66FA67056707 670E67136719671C672067226733673E674567476748674C67546755675D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 43 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006766676C676E67746776677B67816784678E678F67916793679667986799 679B67B067B167B267B567BB67BC67BD67F967C067C267C367C567C867C967D2 67D767D967DC67E167E667F067F267F667F7685268146819681D681F68286827 682C682D682F683068316833683B683F68446845684A684C685568576858685B 686B686E686F68706871687268756879687A687B687C68826884688668886896 6898689A689C68A168A368A568A968AA68AE68B268BB68C568C868CC68CF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 44 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000068D068D168D368D668D968DC68DD68E568E868EA68EB68EC68ED68F068F1 68F568F668FB68FC68FD69066909690A69106911691369166917693169336935 6938693B694269456949694E6957695B696369646965696669686969696C6970 69716972697A697B697F6980698D69926996699869A169A569A669A869AB69AD 69AF69B769B869BA69BC69C569C869D169D669D769E269E569EE69EF69F169F3 69F569FE6A006A016A036A0F6A116A156A1A6A1D6A206A246A286A306A320000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 45 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006A346A376A3B6A3E6A3F6A456A466A496A4A6A4E6A506A516A526A556A56 6A5B6A646A676A6A6A716A736A7E6A816A836A866A876A896A8B6A916A9B6A9D 6A9E6A9F6AA56AAB6AAF6AB06AB16AB46ABD6ABE6ABF6AC66AC96AC86ACC6AD0 6AD46AD56AD66ADC6ADD6AE46AE76AEC6AF06AF16AF26AFC6AFD6B026B036B06 6B076B096B0F6B106B116B176B1B6B1E6B246B286B2B6B2C6B2F6B356B366B3B 6B3F6B466B4A6B4D6B526B566B586B5D6B606B676B6B6B6E6B706B756B7D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 46 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006B7E6B826B856B976B9B6B9F6BA06BA26BA36BA86BA96BAC6BAD6BAE6BB0 6BB86BB96BBD6BBE6BC36BC46BC96BCC6BD66BDA6BE16BE36BE66BE76BEE6BF1 6BF76BF96BFF6C026C046C056C096C0D6C0E6C106C126C196C1F6C266C276C28 6C2C6C2E6C336C356C366C3A6C3B6C3F6C4A6C4B6C4D6C4F6C526C546C596C5B 6C5C6C6B6C6D6C6F6C746C766C786C796C7B6C856C866C876C896C946C956C97 6C986C9C6C9F6CB06CB26CB46CC26CC66CCD6CCF6CD06CD16CD26CD46CD60000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 47 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006CDA6CDC6CE06CE76CE96CEB6CEC6CEE6CF26CF46D046D076D0A6D0E6D0F 6D116D136D1A6D266D276D286C676D2E6D2F6D316D396D3C6D3F6D576D5E6D5F 6D616D656D676D6F6D706D7C6D826D876D916D926D946D966D976D986DAA6DAC 6DB46DB76DB96DBD6DBF6DC46DC86DCA6DCE6DCF6DD66DDB6DDD6DDF6DE06DE2 6DE56DE96DEF6DF06DF46DF66DFC6E006E046E1E6E226E276E326E366E396E3B 6E3C6E446E456E486E496E4B6E4F6E516E526E536E546E576E5C6E5D6E5E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006E626E636E686E736E7B6E7D6E8D6E936E996EA06EA76EAD6EAE6EB16EB3 6EBB6EBF6EC06EC16EC36EC76EC86ECA6ECD6ECE6ECF6EEB6EED6EEE6EF96EFB 6EFD6F046F086F0A6F0C6F0D6F166F186F1A6F1B6F266F296F2A6F2F6F306F33 6F366F3B6F3C6F2D6F4F6F516F526F536F576F596F5A6F5D6F5E6F616F626F68 6F6C6F7D6F7E6F836F876F886F8B6F8C6F8D6F906F926F936F946F966F9A6F9F 6FA06FA56FA66FA76FA86FAE6FAF6FB06FB56FB66FBC6FC56FC76FC86FCA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 49 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006FDA6FDE6FE86FE96FF06FF56FF96FFC6FFD7000700570067007700D7017 70207023702F703470377039703C7043704470487049704A704B70547055705D 705E704E70647065706C706E70757076707E7081708570867094709570967097 7098709B70A470AB70B070B170B470B770CA70D170D370D470D570D670D870DC 70E470FA71037104710571067107710B710C710F711E7120712B712D712F7130 713171387141714571467147714A714B715071527157715A715C715E71600000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000071687179718071857187718C7192719A719B71A071A271AF71B071B271B3 71BA71BF71C071C171C471CB71CC71D371D671D971DA71DC71F871FE72007207 7208720972137217721A721D721F7224722B722F723472387239724172427243 7245724E724F7250725372557256725A725C725E726072637268726B726E726F 727172777278727B727C727F72847289728D728E7293729B72A872AD72AE72B1 72B472BE72C172C772C972CC72D572D672D872DF72E572F372F472FA72FB0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000072FE7302730473057307730B730D7312731373187319731E732273247327 7328732C733173327335733A733B733D7343734D7350735273567358735D735E 735F7360736673677369736B736C736E736F737173777379737C738073817383 73857386738E73907393739573977398739C739E739F73A073A273A573A673AA 73AB73AD73B573B773B973BC73BD73BF73C573C673C973CB73CC73CF73D273D3 73D673D973DD73E173E373E673E773E973F473F573F773F973FA73FB73FD0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000073FF7400740174047407740A7411741A741B7424742674287429742A742B 742C742D742E742F74307431743974407443744474467447744B744D74517452 7457745D7462746674677468746B746D746E7471747274807481748574867487 7489748F74907491749274987499749A749C749F74A074A174A374A674A874A9 74AA74AB74AE74AF74B174B274B574B974BB74BF74C874C974CC74D074D374D8 74DA74DB74DE74DF74E474E874EA74EB74EF74F474FA74FB74FC74FF75060000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075127516751775207521752475277529752A752F75367539753D753E753F 7540754375477548754E755075527557755E755F7561756F75717579757A757B 757C757D757E7581758575907592759375957599759C75A275A475B475BA75BF 75C075C175C475C675CC75CE75CF75D775DC75DF75E075E175E475E775EC75EE 75EF75F175F9760076027603760476077608760A760C760F7612761376157616 7619761B761C761D761E7623762576267629762D763276337635763876390000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000763A763C764A764076417643764476457649764B76557659765F76647665 766D766E766F7671767476817685768C768D7695769B769C769D769F76A076A2 76A376A476A576A676A776A876AA76AD76BD76C176C576C976CB76CC76CE76D4 76D976E076E676E876EC76F076F176F676F976FC77007706770A770E77127714 771577177719771A771C77227728772D772E772F7734773577367739773D773E 774277457746774A774D774E774F775277567757775C775E775F776077620000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077647767776A776C7770777277737774777A777D77807784778C778D7794 77957796779A779F77A277A777AA77AE77AF77B177B577BE77C377C977D177D2 77D577D977DE77DF77E077E477E677EA77EC77F077F177F477F877FB78057806 7809780D780E7811781D782178227823782D782E783078357837784378447847 7848784C784E7852785C785E78607861786378647868786A786E787A787E788A 788F7894789878A1789D789E789F78A478A878AC78AD78B078B178B278B30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 50 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000078BB78BD78BF78C778C878C978CC78CE78D278D378D578D678E478DB78DF 78E078E178E678EA78F278F3790078F678F778FA78FB78FF7906790C7910791A 791C791E791F7920792579277929792D793179347935793B793D793F79447945 7946794A794B794F795179547958795B795C79677969796B79727979797B797C 797E798B798C799179937994799579967998799B799C79A179A879A979AB79AF 79B179B479B879BB79C279C479C779C879CA79CF79D479D679DA79DD79DE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 51 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000079E079E279E579EA79EB79ED79F179F879FC7A027A037A077A097A0A7A0C 7A117A157A1B7A1E7A217A277A2B7A2D7A2F7A307A347A357A387A397A3A7A44 7A457A477A487A4C7A557A567A597A5C7A5D7A5F7A607A657A677A6A7A6D7A75 7A787A7E7A807A827A857A867A8A7A8B7A907A917A947A9E7AA07AA37AAC7AB3 7AB57AB97ABB7ABC7AC67AC97ACC7ACE7AD17ADB7AE87AE97AEB7AEC7AF17AF4 7AFB7AFD7AFE7B077B147B1F7B237B277B297B2A7B2B7B2D7B2E7B2F7B300000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 52 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007B317B347B3D7B3F7B407B417B477B4E7B557B607B647B667B697B6A7B6D 7B6F7B727B737B777B847B897B8E7B907B917B967B9B7B9E7BA07BA57BAC7BAF 7BB07BB27BB57BB67BBA7BBB7BBC7BBD7BC27BC57BC87BCA7BD47BD67BD77BD9 7BDA7BDB7BE87BEA7BF27BF47BF57BF87BF97BFA7BFC7BFE7C017C027C037C04 7C067C097C0B7C0C7C0E7C0F7C197C1B7C207C257C267C287C2C7C317C337C34 7C367C397C3A7C467C4A7C557C517C527C537C597C5A7C5B7C5C7C5D7C5E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 53 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007C617C637C677C697C6D7C6E7C707C727C797C7C7C7D7C867C877C8F7C94 7C9E7CA07CA67CB07CB67CB77CBA7CBB7CBC7CBF7CC47CC77CC87CC97CCD7CCF 7CD37CD47CD57CD77CD97CDA7CDD7CE67CE97CEB7CF57D037D077D087D097D0F 7D117D127D137D167D1D7D1E7D237D267D2A7D2D7D317D3C7D3D7D3E7D407D41 7D477D487D4D7D517D537D577D597D5A7D5C7D5D7D657D677D6A7D707D787D7A 7D7B7D7F7D817D827D837D857D867D887D8B7D8C7D8D7D917D967D977D9D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007D9E7DA67DA77DAA7DB37DB67DB77DB97DC27DC37DC47DC57DC67DCC7DCD 7DCE7DD77DD97E007DE27DE57DE67DEA7DEB7DED7DF17DF57DF67DF97DFA7E08 7E107E117E157E177E1C7E1D7E207E277E287E2C7E2D7E2F7E337E367E3F7E44 7E457E477E4E7E507E527E587E5F7E617E627E657E6B7E6E7E6F7E737E787E7E 7E817E867E877E8A7E8D7E917E957E987E9A7E9D7E9E7F3C7F3B7F3D7F3E7F3F 7F437F447F477F4F7F527F537F5B7F5C7F5D7F617F637F647F657F667F6D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 55 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007F717F7D7F7E7F7F7F807F8B7F8D7F8F7F907F917F967F977F9C7FA17FA2 7FA67FAA7FAD7FB47FBC7FBF7FC07FC37FC87FCE7FCF7FDB7FDF7FE37FE57FE8 7FEC7FEE7FEF7FF27FFA7FFD7FFE7FFF80078008800A800D800E800F80118013 80148016801D801E801F802080248026802C802E80308034803580378039803A 803C803E80408044806080648066806D8071807580818088808E809C809E80A6 80A780AB80B880B980C880CD80CF80D280D480D580D780D880E080ED80EE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 56 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000080F080F280F380F680F980FA80FE8103810B811681178118811C811E8120 81248127812C81308135813A813C81458147814A814C81528157816081618167 81688169816D816F817781818190818481858186818B818E81968198819B819E 81A281AE81B281B481BB81CB81C381C581CA81CE81CF81D581D781DB81DD81DE 81E181E481EB81EC81F081F181F281F581F681F881F981FD81FF82008203820F 821382148219821A821D82218222822882328234823A82438244824582460000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 57 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000824B824E824F82518256825C826082638267826D8274827B827D827F8280 82818283828482878289828A828E8291829482968298829A829B82A082A182A3 82A482A782A882A982AA82AE82B082B282B482B782BA82BC82BE82BF82C682D0 82D582DA82E082E282E482E882EA82ED82EF82F682F782FD82FE830083018307 8308830A830B8354831B831D831E831F83218322832C832D832E833083338337 833A833C833D8342834383448347834D834E8351835583568357837083780000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 58 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000837D837F8380838283848386838D83928394839583988399839B839C839D 83A683A783A983AC83BE83BF83C083C783C983CF83D083D183D483DD835383E8 83EA83F683F883F983FC84018406840A840F84118415841983AD842F84398445 84478448844A844D844F84518452845684588459845A845C8460846484658467 846A84708473847484768478847C847D84818485849284938495849E84A684A8 84A984AA84AF84B184B484BA84BD84BE84C084C284C784C884CC84CF84D30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 59 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000084DC84E784EA84EF84F084F184F284F7853284FA84FB84FD850285038507 850C850E8510851C851E85228523852485258527852A852B852F853385348536 853F8546854F855085518552855385568559855C855D855E855F856085618562 8564856B856F8579857A857B857D857F8581858585868589858B858C858F8593 8598859D859F85A085A285A585A785B485B685B785B885BC85BD85BE85BF85C2 85C785CA85CB85CE85AD85D885DA85DF85E085E685E885ED85F385F685FC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000085FF860086048605860D860E86108611861286188619861B861E86218627 862986368638863A863C863D864086428646865286538656865786588659865D 866086618662866386648669866C866F867586768677867A868D869186968698 869A869C86A186A686A786A886AD86B186B386B486B586B786B886B986BF86C0 86C186C386C586D186D286D586D786DA86DC86E086E386E586E7868886FA86FC 86FD870487058707870B870E870F8710871387148719871E871F872187230000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008728872E872F873187328739873A873C873D873E874087438745874D8758 875D876187648765876F87718772877B8783878487858786878787888789878B 878C879087938795879787988799879E87A087A387A787AC87AD87AE87B187B5 87BE87BF87C187C887C987CA87CE87D587D687D987DA87DC87DF87E287E387E4 87EA87EB87ED87F187F387F887FA87FF8801880388068809880A880B88108819 8812881388148818881A881B881C881E881F8828882D882E8830883288350000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000883A883C88418843884588488849884A884B884E8851885588568858885A 885C885F88608864886988718879887B88808898889A889B889C889F88A088A8 88AA88BA88BD88BE88C088CA88CB88CC88CD88CE88D188D288D388DB88DE88E7 88EF88F088F188F588F789018906890D890E890F8915891689188919891A891C 892089268927892889308931893289358939893A893E89408942894589468949 894F89528957895A895B895C896189628963896B896E897089738975897A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000897B897C897D8989898D899089948995899B899C899F89A089A589B089B4 89B589B689B789BC89D489D589D689D789D889E589E989EB89ED89F189F389F6 89F989FD89FF8A048A058A078A0F8A118A128A148A158A1E8A208A228A248A26 8A2B8A2C8A2F8A358A378A3D8A3E8A408A438A458A478A498A4D8A4E8A538A56 8A578A588A5C8A5D8A618A658A678A758A768A778A798A7A8A7B8A7E8A7F8A80 8A838A868A8B8A8F8A908A928A968A978A998A9F8AA78AA98AAE8AAF8AB30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008AB68AB78ABB8ABE8AC38AC68AC88AC98ACA8AD18AD38AD48AD58AD78ADD 8ADF8AEC8AF08AF48AF58AF68AFC8AFF8B058B068B0B8B118B1C8B1E8B1F8B0A 8B2D8B308B378B3C8B428B438B448B458B468B488B528B538B548B598B4D8B5E 8B638B6D8B768B788B798B7C8B7E8B818B848B858B8B8B8D8B8F8B948B958B9C 8B9E8B9F8C388C398C3D8C3E8C458C478C498C4B8C4F8C518C538C548C578C58 8C5B8C5D8C598C638C648C668C688C698C6D8C738C758C768C7B8C7E8C860000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008C878C8B8C908C928C938C998C9B8C9C8CA48CB98CBA8CC58CC68CC98CCB 8CCF8CD68CD58CD98CDD8CE18CE88CEC8CEF8CF08CF28CF58CF78CF88CFE8CFF 8D018D038D098D128D178D1B8D658D698D6C8D6E8D7F8D828D848D888D8D8D90 8D918D958D9E8D9F8DA08DA68DAB8DAC8DAF8DB28DB58DB78DB98DBB8DC08DC5 8DC68DC78DC88DCA8DCE8DD18DD48DD58DD78DD98DE48DE58DE78DEC8DF08DBC 8DF18DF28DF48DFD8E018E048E058E068E0B8E118E148E168E208E218E220000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 60 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008E238E268E278E318E338E368E378E388E398E3D8E408E418E4B8E4D8E4E 8E4F8E548E5B8E5C8E5D8E5E8E618E628E698E6C8E6D8E6F8E708E718E798E7A 8E7B8E828E838E898E908E928E958E9A8E9B8E9D8E9E8EA28EA78EA98EAD8EAE 8EB38EB58EBA8EBB8EC08EC18EC38EC48EC78ECF8ED18ED48EDC8EE88EEE8EF0 8EF18EF78EF98EFA8EED8F008F028F078F088F0F8F108F168F178F188F1E8F20 8F218F238F258F278F288F2C8F2D8F2E8F348F358F368F378F3A8F408F410000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 61 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008F438F478F4F8F518F528F538F548F558F588F5D8F5E8F658F9D8FA08FA1 8FA48FA58FA68FB58FB68FB88FBE8FC08FC18FC68FCA8FCB8FCD8FD08FD28FD3 8FD58FE08FE38FE48FE88FEE8FF18FF58FF68FFB8FFE900290049008900C9018 901B90289029902F902A902C902D903390349037903F90439044904C905B905D 906290669067906C90709074907990859088908B908C908E9090909590979098 9099909B90A090A190A290A590B090B290B390B490B690BD90CC90BE90C30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 62 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000090C490C590C790C890D590D790D890D990DC90DD90DF90E590D290F690EB 90EF90F090F490FE90FF91009104910591069108910D91109114911691179118 911A911C911E912091259122912391279129912E912F91319134913691379139 913A913C913D914391479148914F915391579159915A915B916191649167916D 91749179917A917B9181918391859186918A918E91919193919491959198919E 91A191A691A891AC91AD91AE91B091B191B291B391B691BB91BC91BD91BF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 63 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000091C291C391C591D391D491D791D991DA91DE91E491E591E991EA91EC91ED 91EE91EF91F091F191F791F991FB91FD9200920192049205920692079209920A 920C92109212921392169218921C921D92239224922592269228922E922F9230 92339235923692389239923A923C923E92409242924392469247924A924D924E 924F925192589259925C925D926092619265926792689269926E926F92709275 9276927792789279927B927C927D927F92889289928A928D928E929292970000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 64 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009299929F92A092A492A592A792A892AB92AF92B292B692B892BA92BB92BC 92BD92BF92C092C192C292C392C592C692C792C892CB92CC92CD92CE92D092D3 92D592D792D892D992DC92DD92DF92E092E192E392E592E792E892EC92EE92F0 92F992FB92FF930093029308930D931193149315931C931D931E931F93219324 932593279329932A933393349336933793479348934993509351935293559357 9358935A935E9364936593679369936A936D936F937093719373937493760000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 65 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000937A937D937F9380938193829388938A938B938D938F939293959398939B 939E93A193A393A493A693A893AB93B493B593B693BA93A993C193C493C593C6 93C793C993CA93CB93CC93CD93D393D993DC93DE93DF93E293E693E793F993F7 93F893FA93FB93FD94019402940494089409940D940E940F941594169417941F 942E942F9431943294339434943B943F943D944394459448944A944C94559459 945C945F946194639468946B946D946E946F9471947294849483957895790000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 66 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000957E95849588958C958D958E959D959E959F95A195A695A995AB95AC95B4 95B695BA95BD95BF95C695C895C995CB95D095D195D295D395D995DA95DD95DE 95DF95E095E495E6961D961E9622962496259626962C96319633963796389639 963A963C963D9641965296549656965796589661966E9674967B967C967E967F 9681968296839684968996919696969A969D969F96A496A596A696A996AE96AF 96B396BA96CA96D25DB296D896DA96DD96DE96DF96E996EF96F196FA97020000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 67 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000970397059709971A971B971D97219722972397289731973397419743974A 974E974F975597579758975A975B97639767976A976E9773977697779778977B 977D977F978097899795979697979799979A979E979F97A297AC97AE97B197B2 97B597B697B897B997BA97BC97BE97BF97C197C497C597C797C997CA97CC97CD 97CE97D097D197D497D797D897D997DD97DE97E097DB97E197E497EF97F197F4 97F797F897FA9807980A9819980D980E98149816981C981E9820982398260000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 68 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000982B982E982F98309832983398359825983E98449847984A985198529853 985698579859985A9862986398659866986A986C98AB98AD98AE98B098B498B7 98B898BA98BB98BF98C298C598C898CC98E198E398E598E698E798EA98F398F6 9902990799089911991599169917991A991B991C991F992299269927992B9931 99329933993499359939993A993B993C99409941994699479948994D994E9954 99589959995B995C995E995F9960999B999D999F99A699B099B199B299B50000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 69 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000099B999BA99BD99BF99C399C999D399D499D999DA99DC99DE99E799EA99EB 99EC99F099F499F599F999FD99FE9A029A039A049A0B9A0C9A109A119A169A1E 9A209A229A239A249A279A2D9A2E9A339A359A369A389A479A419A449A4A9A4B 9A4C9A4E9A519A549A569A5D9AAA9AAC9AAE9AAF9AB29AB49AB59AB69AB99ABB 9ABE9ABF9AC19AC39AC69AC89ACE9AD09AD29AD59AD69AD79ADB9ADC9AE09AE4 9AE59AE79AE99AEC9AF29AF39AF59AF99AFA9AFD9AFF9B009B019B029B030000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009B049B059B089B099B0B9B0C9B0D9B0E9B109B129B169B199B1B9B1C9B20 9B269B2B9B2D9B339B349B359B379B399B3A9B3D9B489B4B9B4C9B559B569B57 9B5B9B5E9B619B639B659B669B689B6A9B6B9B6C9B6D9B6E9B739B759B779B78 9B799B7F9B809B849B859B869B879B899B8A9B8B9B8D9B8F9B909B949B9A9B9D 9B9E9BA69BA79BA99BAC9BB09BB19BB29BB79BB89BBB9BBC9BBE9BBF9BC19BC7 9BC89BCE9BD09BD79BD89BDD9BDF9BE59BE79BEA9BEB9BEF9BF39BF79BF80000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009BF99BFA9BFD9BFF9C009C029C0B9C0F9C119C169C189C199C1A9C1C9C1E 9C229C239C269C279C289C299C2A9C319C359C369C379C3D9C419C439C449C45 9C499C4A9C4E9C4F9C509C539C549C569C589C5B9C5D9C5E9C5F9C639C699C6A 9C5C9C6B9C689C6E9C709C729C759C779C7B9CE69CF29CF79CF99D0B9D029D11 9D179D189D1C9D1D9D1E9D2F9D309D329D339D349D3A9D3C9D459D3D9D429D43 9D479D4A9D539D549D5F9D639D629D659D699D6A9D6B9D709D769D779D7B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009D7C9D7E9D839D849D869D8A9D8D9D8E9D929D939D959D969D979D989DA1 9DAA9DAC9DAE9DB19DB59DB99DBC9DBF9DC39DC79DC99DCA9DD49DD59DD69DD7 9DDA9DDE9DDF9DE09DE59DE79DE99DEB9DEE9DF09DF39DF49DFE9E0A9E029E07 9E0E9E109E119E129E159E169E199E1C9E1D9E7A9E7B9E7C9E809E829E839E84 9E859E879E8E9E8F9E969E989E9B9E9E9EA49EA89EAC9EAE9EAF9EB09EB39EB4 9EB59EC69EC89ECB9ED59EDF9EE49EE79EEC9EED9EEE9EF09EF19EF29EF50000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009EF89EFF9F029F039F099F0F9F109F119F129F149F169F179F199F1A9F1B 9F1F9F229F269F2A9F2B9F2F9F319F329F349F379F399F3A9F3C9F3D9F3F9F41 9F439F449F459F469F479F539F559F569F579F589F5A9F5D9F5E9F689F699F6D 9F6E9F6F9F709F719F739F759F7A9F7D9F8F9F909F919F929F949F969F979F9E 9FA19FA29FA39FA5000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 tcl8.6.5/library/encoding/cp1255.enc0000644000175000017500000000210311555560473016424 0ustar sergeisergei# Encoding file: cp1255, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 20AC0081201A0192201E20262020202102C62030008A2039008C008D008E008F 009020182019201C201D20222013201402DC2122009A203A009C009D009E009F 00A000A100A200A320AA00A500A600A700A800A900D700AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B900F700BB00BC00BD00BE00BF 05B005B105B205B305B405B505B605B705B805B9000005BB05BC05BD05BE05BF 05C005C105C205C305F005F105F205F305F40000000000000000000000000000 05D005D105D205D305D405D505D605D705D805D905DA05DB05DC05DD05DE05DF 05E005E105E205E305E405E505E605E705E805E905EA00000000200E200F0000 tcl8.6.5/library/encoding/big5.enc0000644000175000017500000026531111555560473016347 0ustar sergeisergei# Encoding file: big5, multi-byte M 003F 0 89 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3000FF0C30013002FF0E2022FF1BFF1AFF1FFF01FE3020262025FE50FF64FE52 00B7FE54FE55FE56FE57FF5C2013FE312014FE33FFFDFE34FE4FFF08FF09FE35 FE36FF5BFF5DFE37FE3830143015FE39FE3A30103011FE3BFE3C300A300BFE3D FE3E30083009FE3FFE40300C300DFE41FE42300E300FFE43FE44FE59FE5A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FE5BFE5CFE5DFE5E20182019201C201D301D301E20352032FF03FF06FF0A 203B00A7300325CB25CF25B325B225CE2606260525C725C625A125A025BD25BC 32A32105203EFFFDFF3FFFFDFE49FE4AFE4DFE4EFE4BFE4CFE5FFE60FE61FF0B FF0D00D700F700B1221AFF1CFF1EFF1D226622672260221E22522261FE62FE63 FE64FE65FE66223C2229222A22A52220221F22BF33D233D1222B222E22352234 26402642264126092191219321902192219621972199219822252223FFFD0000 A2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FFFDFF0FFF3CFF0400A5301200A200A3FF05FF2021032109FE69FE6AFE6B33D5 339C339D339E33CE33A1338E338F33C400B05159515B515E515D5161516355E7 74E97CCE25812582258325842585258625872588258F258E258D258C258B258A 2589253C2534252C2524251C2594250025022595250C251025142518256D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000256E2570256F2550255E256A256125E225E325E525E4257125722573FF10 FF11FF12FF13FF14FF15FF16FF17FF18FF192160216121622163216421652166 216721682169302130223023302430253026302730283029FFFD5344FFFDFF21 FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2FFF30FF31 FF32FF33FF34FF35FF36FF37FF38FF39FF3AFF41FF42FF43FF44FF45FF46FF47 FF48FF49FF4AFF4BFF4CFF4DFF4EFF4FFF50FF51FF52FF53FF54FF55FF560000 A3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FF57FF58FF59FF5A039103920393039403950396039703980399039A039B039C 039D039E039F03A003A103A303A403A503A603A703A803A903B103B203B303B4 03B503B603B703B803B903BA03BB03BC03BD03BE03BF03C003C103C303C403C5 03C603C703C803C931053106310731083109310A310B310C310D310E310F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00003110311131123113311431153116311731183119311A311B311C311D311E 311F312031213122312331243125312631273128312902D902C902CA02C702CB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E004E594E014E034E434E5D4E864E8C4EBA513F5165516B51E052005201529B 53155341535C53C84E094E0B4E084E0A4E2B4E3851E14E454E484E5F4E5E4E8E 4EA15140520352FA534353C953E3571F58EB5915592759735B505B515B535BF8 5C0F5C225C385C715DDD5DE55DF15DF25DF35DFE5E725EFE5F0B5F13624D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E114E104E0D4E2D4E304E394E4B5C394E884E914E954E924E944EA24EC1 4EC04EC34EC64EC74ECD4ECA4ECB4EC4514351415167516D516E516C519751F6 52065207520852FB52FE52FF53165339534853475345535E538453CB53CA53CD 58EC5929592B592A592D5B545C115C245C3A5C6F5DF45E7B5EFF5F145F155FC3 62086236624B624E652F6587659765A465B965E566F0670867286B206B626B79 6BCB6BD46BDB6C0F6C34706B722A7236723B72477259725B72AC738B4E190000 A5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E164E154E144E184E3B4E4D4E4F4E4E4EE54ED84ED44ED54ED64ED74EE34EE4 4ED94EDE514551445189518A51AC51F951FA51F8520A52A0529F530553065317 531D4EDF534A534953615360536F536E53BB53EF53E453F353EC53EE53E953E8 53FC53F853F553EB53E653EA53F253F153F053E553ED53FB56DB56DA59160000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000592E5931597459765B555B835C3C5DE85DE75DE65E025E035E735E7C5F01 5F185F175FC5620A625362546252625165A565E6672E672C672A672B672D6B63 6BCD6C116C106C386C416C406C3E72AF7384738974DC74E67518751F75287529 7530753175327533758B767D76AE76BF76EE77DB77E277F3793A79BE7A747ACB 4E1E4E1F4E524E534E694E994EA44EA64EA54EFF4F094F194F0A4F154F0D4F10 4F114F0F4EF24EF64EFB4EF04EF34EFD4F014F0B514951475146514851680000 A6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5171518D51B0521752115212520E521652A3530853215320537053715409540F 540C540A54105401540B54045411540D54085403540E5406541256E056DE56DD 573357305728572D572C572F57295919591A59375938598459785983597D5979 598259815B575B585B875B885B855B895BFA5C165C795DDE5E065E765E740000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F0F5F1B5FD95FD6620E620C620D62106263625B6258653665E965E865EC 65ED66F266F36709673D6734673167356B216B646B7B6C166C5D6C576C596C5F 6C606C506C556C616C5B6C4D6C4E7070725F725D767E7AF97C737CF87F367F8A 7FBD80018003800C80128033807F8089808B808C81E381EA81F381FC820C821B 821F826E8272827E866B8840884C8863897F96214E324EA84F4D4F4F4F474F57 4F5E4F344F5B4F554F304F504F514F3D4F3A4F384F434F544F3C4F464F630000 A7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4F5C4F604F2F4F4E4F364F594F5D4F484F5A514C514B514D517551B651B75225 52245229522A522852AB52A952AA52AC532353735375541D542D541E543E5426 544E542754465443543354485442541B5429544A5439543B5438542E54355436 5420543C54405431542B541F542C56EA56F056E456EB574A57515740574D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005747574E573E5750574F573B58EF593E599D599259A8599E59A359995996 598D59A45993598A59A55B5D5B5C5B5A5B5B5B8C5B8B5B8F5C2C5C405C415C3F 5C3E5C905C915C945C8C5DEB5E0C5E8F5E875E8A5EF75F045F1F5F645F625F77 5F795FD85FCC5FD75FCD5FF15FEB5FF85FEA6212621162846297629662806276 6289626D628A627C627E627962736292626F6298626E62956293629162866539 653B653865F166F4675F674E674F67506751675C6756675E6749674667600000 A8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 675367576B656BCF6C426C5E6C996C816C886C896C856C9B6C6A6C7A6C906C70 6C8C6C686C966C926C7D6C836C726C7E6C746C866C766C8D6C946C986C827076 707C707D707872627261726072C472C27396752C752B75377538768276EF77E3 79C179C079BF7A767CFB7F5580968093809D8098809B809A80B2826F82920000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000828B828D898B89D28A008C378C468C558C9D8D648D708DB38EAB8ECA8F9B 8FB08FC28FC68FC58FC45DE1909190A290AA90A690A3914991C691CC9632962E 9631962A962C4E264E564E734E8B4E9B4E9E4EAB4EAC4F6F4F9D4F8D4F734F7F 4F6C4F9B4F8B4F864F834F704F754F884F694F7B4F964F7E4F8F4F914F7A5154 51525155516951775176517851BD51FD523B52385237523A5230522E52365241 52BE52BB5352535453535351536653775378537953D653D453D7547354750000 A9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5496547854955480547B5477548454925486547C549054715476548C549A5462 5468548B547D548E56FA57835777576A5769576157665764577C591C59495947 59485944595459BE59BB59D459B959AE59D159C659D059CD59CB59D359CA59AF 59B359D259C55B5F5B645B635B975B9A5B985B9C5B995B9B5C1A5C485C450000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C465CB75CA15CB85CA95CAB5CB15CB35E185E1A5E165E155E1B5E115E78 5E9A5E975E9C5E955E965EF65F265F275F295F805F815F7F5F7C5FDD5FE05FFD 5FF55FFF600F6014602F60356016602A6015602160276029602B601B62166215 623F623E6240627F62C962CC62C462BF62C262B962D262DB62AB62D362D462CB 62C862A862BD62BC62D062D962C762CD62B562DA62B162D862D662D762C662AC 62CE653E65A765BC65FA66146613660C66066602660E6600660F6615660A0000 AA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6607670D670B676D678B67956771679C677367776787679D6797676F6770677F 6789677E67906775679A6793677C676A67726B236B666B676B7F6C136C1B6CE3 6CE86CF36CB16CCC6CE56CB36CBD6CBE6CBC6CE26CAB6CD56CD36CB86CC46CB9 6CC16CAE6CD76CC56CF16CBF6CBB6CE16CDB6CCA6CAC6CEF6CDC6CD66CE00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007095708E7092708A7099722C722D723872487267726972C072CE72D972D7 72D073A973A8739F73AB73A5753D759D7599759A768476C276F276F477E577FD 793E7940794179C979C87A7A7A797AFA7CFE7F547F8C7F8B800580BA80A580A2 80B180A180AB80A980B480AA80AF81E581FE820D82B3829D829982AD82BD829F 82B982B182AC82A582AF82B882A382B082BE82B7864E8671521D88688ECB8FCE 8FD48FD190B590B890B190B691C791D195779580961C9640963F963B96440000 AB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 964296B996E89752975E4E9F4EAD4EAE4FE14FB54FAF4FBF4FE04FD14FCF4FDD 4FC34FB64FD84FDF4FCA4FD74FAE4FD04FC44FC24FDA4FCE4FDE4FB751575192 519151A0524E5243524A524D524C524B524752C752C952C352C1530D5357537B 539A53DB54AC54C054A854CE54C954B854A654B354C754C254BD54AA54C10000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000054C454C854AF54AB54B154BB54A954A754BF56FF5782578B57A057A357A2 57CE57AE579359555951594F594E595059DC59D859FF59E359E85A0359E559EA 59DA59E65A0159FB5B695BA35BA65BA45BA25BA55C015C4E5C4F5C4D5C4B5CD9 5CD25DF75E1D5E255E1F5E7D5EA05EA65EFA5F085F2D5F655F885F855F8A5F8B 5F875F8C5F896012601D60206025600E6028604D60706068606260466043606C 606B606A6064624162DC6316630962FC62ED630162EE62FD630762F162F70000 AC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 62EF62EC62FE62F463116302653F654565AB65BD65E26625662D66206627662F 661F66286631662466F767FF67D367F167D467D067EC67B667AF67F567E967EF 67C467D167B467DA67E567B867CF67DE67F367B067D967E267DD67D26B6A6B83 6B866BB56BD26BD76C1F6CC96D0B6D326D2A6D416D256D0C6D316D1E6D170000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D3B6D3D6D3E6D366D1B6CF56D396D276D386D296D2E6D356D0E6D2B70AB 70BA70B370AC70AF70AD70B870AE70A472307272726F727472E972E072E173B7 73CA73BB73B273CD73C073B3751A752D754F754C754E754B75AB75A475A575A2 75A3767876867687768876C876C676C376C5770176F976F87709770B76FE76FC 770777DC78027814780C780D794679497948794779B979BA79D179D279CB7A7F 7A817AFF7AFD7C7D7D027D057D007D097D077D047D067F387F8E7FBF80040000 AD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8010800D8011803680D680E580DA80C380C480CC80E180DB80CE80DE80E480DD 81F4822282E78303830582E382DB82E6830482E58302830982D282D782F18301 82DC82D482D182DE82D382DF82EF830686508679867B867A884D886B898189D4 8A088A028A038C9E8CA08D748D738DB48ECD8ECC8FF08FE68FE28FEA8FE50000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008FED8FEB8FE48FE890CA90CE90C190C3914B914A91CD95829650964B964C 964D9762976997CB97ED97F3980198A898DB98DF999699994E584EB3500C500D 50234FEF502650254FF8502950165006503C501F501A501250114FFA50005014 50284FF15021500B501950184FF34FEE502D502A4FFE502B5009517C51A451A5 51A251CD51CC51C651CB5256525C5254525B525D532A537F539F539D53DF54E8 55105501553754FC54E554F2550654FA551454E954ED54E1550954EE54EA0000 AE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54E65527550754FD550F5703570457C257D457CB57C35809590F59575958595A 5A115A185A1C5A1F5A1B5A1359EC5A205A235A295A255A0C5A095B6B5C585BB0 5BB35BB65BB45BAE5BB55BB95BB85C045C515C555C505CED5CFD5CFB5CEA5CE8 5CF05CF65D015CF45DEE5E2D5E2B5EAB5EAD5EA75F315F925F915F9060590000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006063606560506055606D6069606F6084609F609A608D6094608C60856096 624762F3630862FF634E633E632F635563426346634F6349633A6350633D632A 632B6328634D634C65486549659965C165C566426649664F66436652664C6645 664166F867146715671768216838684868466853683968426854682968B36817 684C6851683D67F468506840683C6843682A68456813681868416B8A6B896BB7 6C236C276C286C266C246CF06D6A6D956D886D876D666D786D776D596D930000 AF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6D6C6D896D6E6D5A6D746D696D8C6D8A6D796D856D656D9470CA70D870E470D9 70C870CF7239727972FC72F972FD72F872F7738673ED740973EE73E073EA73DE 7554755D755C755A755975BE75C575C775B275B375BD75BC75B975C275B8768B 76B076CA76CD76CE7729771F7720772877E9783078277838781D783478370000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007825782D7820781F7832795579507960795F7956795E795D7957795A79E4 79E379E779DF79E679E979D87A847A887AD97B067B117C897D217D177D0B7D0A 7D207D227D147D107D157D1A7D1C7D0D7D197D1B7F3A7F5F7F947FC57FC18006 8018801580198017803D803F80F1810280F0810580ED80F4810680F880F38108 80FD810A80FC80EF81ED81EC82008210822A822B8228822C82BB832B83528354 834A83388350834983358334834F833283398336831783408331832883430000 B0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8654868A86AA869386A486A9868C86A3869C8870887788818882887D88798A18 8A108A0E8A0C8A158A0A8A178A138A168A0F8A118C488C7A8C798CA18CA28D77 8EAC8ED28ED48ECF8FB1900190068FF790008FFA8FF490038FFD90058FF89095 90E190DD90E29152914D914C91D891DD91D791DC91D995839662966396610000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000965B965D96649658965E96BB98E299AC9AA89AD89B259B329B3C4E7E507A 507D505C50475043504C505A504950655076504E5055507550745077504F500F 506F506D515C519551F0526A526F52D252D952D852D55310530F5319533F5340 533E53C366FC5546556A55665544555E55615543554A55315556554F5555552F 55645538552E555C552C55635533554155575708570B570957DF5805580A5806 57E057E457FA5802583557F757F9592059625A365A415A495A665A6A5A400000 B1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5A3C5A625A5A5A465A4A5B705BC75BC55BC45BC25BBF5BC65C095C085C075C60 5C5C5C5D5D075D065D0E5D1B5D165D225D115D295D145D195D245D275D175DE2 5E385E365E335E375EB75EB85EB65EB55EBE5F355F375F575F6C5F695F6B5F97 5F995F9E5F985FA15FA05F9C607F60A3608960A060A860CB60B460E660BD0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000060C560BB60B560DC60BC60D860D560C660DF60B860DA60C7621A621B6248 63A063A76372639663A263A563776367639863AA637163A963896383639B636B 63A863846388639963A163AC6392638F6380637B63696368637A655D65566551 65596557555F654F655865556554659C659B65AC65CF65CB65CC65CE665D665A 666466686666665E66F952D7671B688168AF68A2689368B5687F687668B168A7 689768B0688368C468AD688668856894689D68A8689F68A168826B326BBA0000 B2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6BEB6BEC6C2B6D8E6DBC6DF36DD96DB26DE16DCC6DE46DFB6DFA6E056DC76DCB 6DAF6DD16DAE6DDE6DF96DB86DF76DF56DC56DD26E1A6DB56DDA6DEB6DD86DEA 6DF16DEE6DE86DC66DC46DAA6DEC6DBF6DE670F97109710A70FD70EF723D727D 7281731C731B73167313731973877405740A7403740673FE740D74E074F60000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000074F7751C75227565756675627570758F75D475D575B575CA75CD768E76D4 76D276DB7737773E773C77367738773A786B7843784E79657968796D79FB7A92 7A957B207B287B1B7B2C7B267B197B1E7B2E7C927C977C957D467D437D717D2E 7D397D3C7D407D307D337D447D2F7D427D327D317F3D7F9E7F9A7FCC7FCE7FD2 801C804A8046812F81168123812B81298130812482028235823782368239838E 839E8398837883A2839683BD83AB8392838A8393838983A08377837B837C0000 B3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 838683A786555F6A86C786C086B686C486B586C686CB86B186AF86C98853889E 888888AB88928896888D888B8993898F8A2A8A1D8A238A258A318A2D8A1F8A1B 8A228C498C5A8CA98CAC8CAB8CA88CAA8CA78D678D668DBE8DBA8EDB8EDF9019 900D901A90179023901F901D90109015901E9020900F90229016901B90140000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000090E890ED90FD915791CE91F591E691E391E791ED91E99589966A96759673 96789670967496769677966C96C096EA96E97AE07ADF980298039B5A9CE59E75 9E7F9EA59EBB50A2508D508550995091508050965098509A670051F152725274 5275526952DE52DD52DB535A53A5557B558055A7557C558A559D55985582559C 55AA55945587558B558355B355AE559F553E55B2559A55BB55AC55B1557E5589 55AB5599570D582F582A58345824583058315821581D582058F958FA59600000 B4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5A775A9A5A7F5A925A9B5AA75B735B715BD25BCC5BD35BD05C0A5C0B5C315D4C 5D505D345D475DFD5E455E3D5E405E435E7E5ECA5EC15EC25EC45F3C5F6D5FA9 5FAA5FA860D160E160B260B660E0611C612360FA611560F060FB60F4616860F1 610E60F6610961006112621F624963A3638C63CF63C063E963C963C663CD0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000063D263E363D063E163D663ED63EE637663F463EA63DB645263DA63F9655E 6566656265636591659065AF666E667066746676666F6691667A667E667766FE 66FF671F671D68FA68D568E068D868D7690568DF68F568EE68E768F968D268F2 68E368CB68CD690D6912690E68C968DA696E68FB6B3E6B3A6B3D6B986B966BBC 6BEF6C2E6C2F6C2C6E2F6E386E546E216E326E676E4A6E206E256E236E1B6E5B 6E586E246E566E6E6E2D6E266E6F6E346E4D6E3A6E2C6E436E1D6E3E6ECB0000 B5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6E896E196E4E6E636E446E726E696E5F7119711A7126713071217136716E711C 724C728472807336732573347329743A742A743374227425743574367434742F 741B7426742875257526756B756A75E275DB75E375D975D875DE75E0767B767C 7696769376B476DC774F77ED785D786C786F7A0D7A087A0B7A057A007A980000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A977A967AE57AE37B497B567B467B507B527B547B4D7B4B7B4F7B517C9F 7CA57D5E7D507D687D557D2B7D6E7D727D617D667D627D707D7355847FD47FD5 800B8052808581558154814B8151814E81398146813E814C815381748212821C 83E9840383F8840D83E083C5840B83C183EF83F183F48457840A83F0840C83CC 83FD83F283CA8438840E840483DC840783D483DF865B86DF86D986ED86D486DB 86E486D086DE885788C188C288B1898389968A3B8A608A558A5E8A3C8A410000 B6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8A548A5B8A508A468A348A3A8A368A568C618C828CAF8CBC8CB38CBD8CC18CBB 8CC08CB48CB78CB68CBF8CB88D8A8D858D818DCE8DDD8DCB8DDA8DD18DCC8DDB 8DC68EFB8EF88EFC8F9C902E90359031903890329036910290F5910990FE9163 916591CF9214921592239209921E920D9210920792119594958F958B95910000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000095939592958E968A968E968B967D96859686968D9672968496C196C596C4 96C696C796EF96F297CC98059806980898E798EA98EF98E998F298ED99AE99AD 9EC39ECD9ED14E8250AD50B550B250B350C550BE50AC50B750BB50AF50C7527F 5277527D52DF52E652E452E252E3532F55DF55E855D355E655CE55DC55C755D1 55E355E455EF55DA55E155C555C655E555C957125713585E585158585857585A 5854586B584C586D584A58625852584B59675AC15AC95ACC5ABE5ABD5ABC0000 B7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5AB35AC25AB25D695D6F5E4C5E795EC95EC85F125F595FAC5FAE611A610F6148 611F60F3611B60F961016108614E614C6144614D613E61346127610D61066137 622162226413643E641E642A642D643D642C640F641C6414640D643664166417 6406656C659F65B06697668966876688669666846698668D67036994696D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000695A697769606954697569306982694A6968696B695E695369796986695D 6963695B6B476B726BC06BBF6BD36BFD6EA26EAF6ED36EB66EC26E906E9D6EC7 6EC56EA56E986EBC6EBA6EAB6ED16E966E9C6EC46ED46EAA6EA76EB4714E7159 7169716471497167715C716C7166714C7165715E714671687156723A72527337 7345733F733E746F745A7455745F745E7441743F7459745B745C757675787600 75F0760175F275F175FA75FF75F475F376DE76DF775B776B7766775E77630000 B8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7779776A776C775C77657768776277EE788E78B078977898788C7889787C7891 7893787F797A797F7981842C79BD7A1C7A1A7A207A147A1F7A1E7A9F7AA07B77 7BC07B607B6E7B677CB17CB37CB57D937D797D917D817D8F7D5B7F6E7F697F6A 7F727FA97FA87FA480568058808680848171817081788165816E8173816B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008179817A81668205824784828477843D843184758466846B8449846C845B 843C8435846184638469846D8446865E865C865F86F9871387088707870086FE 86FB870287038706870A885988DF88D488D988DC88D888DD88E188CA88D588D2 899C89E38A6B8A728A738A668A698A708A878A7C8A638AA08A718A858A6D8A62 8A6E8A6C8A798A7B8A3E8A688C628C8A8C898CCA8CC78CC88CC48CB28CC38CC2 8CC58DE18DDF8DE88DEF8DF38DFA8DEA8DE48DE68EB28F038F098EFE8F0A0000 B9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8F9F8FB2904B904A905390429054903C905590509047904F904E904D9051903E 904191129117916C916A916991C9923792579238923D9240923E925B924B9264 925192349249924D92459239923F925A959896989694969596CD96CB96C996CA 96F796FB96F996F6975697749776981098119813980A9812980C98FC98F40000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000098FD98FE99B399B199B49AE19CE99E829F0E9F139F2050E750EE50E550D6 50ED50DA50D550CF50D150F150CE50E9516251F352835282533153AD55FE5600 561B561755FD561456065609560D560E55F75616561F5608561055F657185716 5875587E58835893588A58795885587D58FD592559225924596A59695AE15AE6 5AE95AD75AD65AD85AE35B755BDE5BE75BE15BE55BE65BE85BE25BE45BDF5C0D 5C625D845D875E5B5E635E555E575E545ED35ED65F0A5F465F705FB961470000 BA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 613F614B617761626163615F615A61586175622A64876458645464A46478645F 647A645164676434646D647B657265A165D765D666A266A8669D699C69A86995 69C169AE69D369CB699B69B769BB69AB69B469D069CD69AD69CC69A669C369A3 6B496B4C6C336F336F146EFE6F136EF46F296F3E6F206F2C6F0F6F026F220000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006EFF6EEF6F066F316F386F326F236F156F2B6F2F6F886F2A6EEC6F016EF2 6ECC6EF771947199717D718A71847192723E729272967344735074647463746A 7470746D750475917627760D760B7609761376E176E37784777D777F776178C1 789F78A778B378A978A3798E798F798D7A2E7A317AAA7AA97AED7AEF7BA17B95 7B8B7B757B977B9D7B947B8F7BB87B877B847CB97CBD7CBE7DBB7DB07D9C7DBD 7DBE7DA07DCA7DB47DB27DB17DBA7DA27DBF7DB57DB87DAD7DD27DC77DAC0000 BB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7F707FE07FE17FDF805E805A808781508180818F8188818A817F818281E781FA 82078214821E824B84C984BF84C684C48499849E84B2849C84CB84B884C084D3 849084BC84D184CA873F871C873B872287258734871887558737872988F38902 88F488F988F888FD88E8891A88EF8AA68A8C8A9E8AA38A8D8AA18A938AA40000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008AAA8AA58AA88A988A918A9A8AA78C6A8C8D8C8C8CD38CD18CD28D6B8D99 8D958DFC8F148F128F158F138FA390609058905C90639059905E9062905D905B 91199118911E917591789177917492789280928592989296927B9293929C92A8 927C929195A195A895A995A395A595A49699969C969B96CC96D29700977C9785 97F69817981898AF98B199039905990C990999C19AAF9AB09AE69B419B429CF4 9CF69CF39EBC9F3B9F4A5104510050FB50F550F9510251085109510551DC0000 BC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 528752885289528D528A52F053B2562E563B56395632563F563456295653564E 565756745636562F56305880589F589E58B3589C58AE58A958A6596D5B095AFB 5B0B5AF55B0C5B085BEE5BEC5BE95BEB5C645C655D9D5D945E625E5F5E615EE2 5EDA5EDF5EDD5EE35EE05F485F715FB75FB561766167616E615D615561820000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000617C6170616B617E61A7619061AB618E61AC619A61A4619461AE622E6469 646F6479649E64B26488649064B064A56493649564A9649264AE64AD64AB649A 64AC649964A264B365756577657866AE66AB66B466B16A236A1F69E86A016A1E 6A1969FD6A216A136A0A69F36A026A0569ED6A116B506B4E6BA46BC56BC66F3F 6F7C6F846F516F666F546F866F6D6F5B6F786F6E6F8E6F7A6F706F646F976F58 6ED56F6F6F606F5F719F71AC71B171A87256729B734E73577469748B74830000 BD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 747E7480757F76207629761F7624762676217622769A76BA76E4778E7787778C 7791778B78CB78C578BA78CA78BE78D578BC78D07A3F7A3C7A407A3D7A377A3B 7AAF7AAE7BAD7BB17BC47BB47BC67BC77BC17BA07BCC7CCA7DE07DF47DEF7DFB 7DD87DEC7DDD7DE87DE37DDA7DDE7DE97D9E7DD97DF27DF97F757F777FAF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007FE98026819B819C819D81A0819A81988517853D851A84EE852C852D8513 851185238521851484EC852584FF850687828774877687608766877887688759 8757874C8753885B885D89108907891289138915890A8ABC8AD28AC78AC48A95 8ACB8AF88AB28AC98AC28ABF8AB08AD68ACD8AB68AB98ADB8C4C8C4E8C6C8CE0 8CDE8CE68CE48CEC8CED8CE28CE38CDC8CEA8CE18D6D8D9F8DA38E2B8E108E1D 8E228E0F8E298E1F8E218E1E8EBA8F1D8F1B8F1F8F298F268F2A8F1C8F1E0000 BE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8F259069906E9068906D90779130912D9127913191879189918B918392C592BB 92B792EA92AC92E492C192B392BC92D292C792F092B295AD95B1970497069707 97099760978D978B978F9821982B981C98B3990A99139912991899DD99D099DF 99DB99D199D599D299D99AB79AEE9AEF9B279B459B449B779B6F9D069D090000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009D039EA99EBE9ECE58A89F5251125118511451105115518051AA51DD5291 529352F35659566B5679566956645678566A566856655671566F566C56625676 58C158BE58C758C5596E5B1D5B345B785BF05C0E5F4A61B2619161A9618A61CD 61B661BE61CA61C8623064C564C164CB64BB64BC64DA64C464C764C264CD64BF 64D264D464BE657466C666C966B966C466C766B86A3D6A386A3A6A596A6B6A58 6A396A446A626A616A4B6A476A356A5F6A486B596B776C056FC26FB16FA10000 BF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6FC36FA46FC16FA76FB36FC06FB96FB66FA66FA06FB471BE71C971D071D271C8 71D571B971CE71D971DC71C371C47368749C74A37498749F749E74E2750C750D 76347638763A76E776E577A0779E779F77A578E878DA78EC78E779A67A4D7A4E 7A467A4C7A4B7ABA7BD97C117BC97BE47BDB7BE17BE97BE67CD57CD67E0A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007E117E087E1B7E237E1E7E1D7E097E107F797FB27FF07FF17FEE802881B3 81A981A881FB820882588259854A855985488568856985438549856D856A855E 8783879F879E87A2878D8861892A89328925892B892189AA89A68AE68AFA8AEB 8AF18B008ADC8AE78AEE8AFE8B018B028AF78AED8AF38AF68AFC8C6B8C6D8C93 8CF48E448E318E348E428E398E358F3B8F2F8F388F338FA88FA6907590749078 9072907C907A913491929320933692F89333932F932292FC932B9304931A0000 C0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9310932693219315932E931995BB96A796A896AA96D5970E97119716970D9713 970F975B975C9766979898309838983B9837982D9839982499109928991E991B 9921991A99ED99E299F19AB89ABC9AFB9AED9B289B919D159D239D269D289D12 9D1B9ED89ED49F8D9F9C512A511F5121513252F5568E56805690568556870000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000568F58D558D358D158CE5B305B2A5B245B7A5C375C685DBC5DBA5DBD5DB8 5E6B5F4C5FBD61C961C261C761E661CB6232623464CE64CA64D864E064F064E6 64EC64F164E264ED6582658366D966D66A806A946A846AA26A9C6ADB6AA36A7E 6A976A906AA06B5C6BAE6BDA6C086FD86FF16FDF6FE06FDB6FE46FEB6FEF6F80 6FEC6FE16FE96FD56FEE6FF071E771DF71EE71E671E571ED71EC71F471E07235 72467370737274A974B074A674A876467642764C76EA77B377AA77B077AC0000 C1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 77A777AD77EF78F778FA78F478EF790179A779AA7A577ABF7C077C0D7BFE7BF7 7C0C7BE07CE07CDC7CDE7CE27CDF7CD97CDD7E2E7E3E7E467E377E327E437E2B 7E3D7E317E457E417E347E397E487E357E3F7E2F7F447FF37FFC807180728070 806F807381C681C381BA81C281C081BF81BD81C981BE81E88209827185AA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008584857E859C8591859485AF859B858785A8858A866787C087D187B387D2 87C687AB87BB87BA87C887CB893B893689448938893D89AC8B0E8B178B198B1B 8B0A8B208B1D8B048B108C418C3F8C738CFA8CFD8CFC8CF88CFB8DA88E498E4B 8E488E4A8F448F3E8F428F458F3F907F907D9084908190829080913991A3919E 919C934D938293289375934A9365934B9318937E936C935B9370935A935495CA 95CB95CC95C895C696B196B896D6971C971E97A097D3984698B699359A010000 C2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 99FF9BAE9BAB9BAA9BAD9D3B9D3F9E8B9ECF9EDE9EDC9EDD9EDB9F3E9F4B53E2 569556AE58D958D85B385F5D61E3623364F464F264FE650664FA64FB64F765B7 66DC67266AB36AAC6AC36ABB6AB86AC26AAE6AAF6B5F6B786BAF7009700B6FFE 70066FFA7011700F71FB71FC71FE71F87377737574A774BF7515765676580000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000765277BD77BF77BB77BC790E79AE7A617A627A607AC47AC57C2B7C277C2A 7C1E7C237C217CE77E547E557E5E7E5A7E617E527E597F487FF97FFB80778076 81CD81CF820A85CF85A985CD85D085C985B085BA85B985A687EF87EC87F287E0 898689B289F48B288B398B2C8B2B8C508D058E598E638E668E648E5F8E558EC0 8F498F4D90879083908891AB91AC91D09394938A939693A293B393AE93AC93B0 9398939A939795D495D695D095D596E296DC96D996DB96DE972497A397A60000 C3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 97AD97F9984D984F984C984E985398BA993E993F993D992E99A59A0E9AC19B03 9B069B4F9B4E9B4D9BCA9BC99BFD9BC89BC09D519D5D9D609EE09F159F2C5133 56A558DE58DF58E25BF59F905EEC61F261F761F661F56500650F66E066DD6AE5 6ADD6ADA6AD3701B701F7028701A701D701570187206720D725872A273780000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000737A74BD74CA74E375877586765F766177C7791979B17A6B7A697C3E7C3F 7C387C3D7C377C407E6B7E6D7E797E697E6A7F857E737FB67FB97FB881D885E9 85DD85EA85D585E485E585F787FB8805880D87F987FE8960895F8956895E8B41 8B5C8B588B498B5A8B4E8B4F8B468B598D088D0A8E7C8E728E878E768E6C8E7A 8E748F548F4E8FAD908A908B91B191AE93E193D193DF93C393C893DC93DD93D6 93E293CD93D893E493D793E895DC96B496E3972A9727976197DC97FB985E0000 C4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9858985B98BC994599499A169A199B0D9BE89BE79BD69BDB9D899D619D729D6A 9D6C9E929E979E939EB452F856A856B756B656B456BC58E45B405B435B7D5BF6 5DC961F861FA65186514651966E667276AEC703E703070327210737B74CF7662 76657926792A792C792B7AC77AF67C4C7C437C4D7CEF7CF08FAE7E7D7E7C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007E827F4C800081DA826685FB85F9861185FA8606860B8607860A88148815 896489BA89F88B708B6C8B668B6F8B5F8B6B8D0F8D0D8E898E818E858E8291B4 91CB9418940393FD95E1973098C49952995199A89A2B9A309A379A359C139C0D 9E799EB59EE89F2F9F5F9F639F615137513856C156C056C259145C6C5DCD61FC 61FE651D651C659566E96AFB6B046AFA6BB2704C721B72A774D674D4766977D3 7C507E8F7E8C7FBC8617862D861A882388228821881F896A896C89BD8B740000 C5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8B778B7D8D138E8A8E8D8E8B8F5F8FAF91BA942E94339435943A94389432942B 95E297389739973297FF9867986599579A459A439A409A3E9ACF9B549B519C2D 9C259DAF9DB49DC29DB89E9D9EEF9F199F5C9F669F67513C513B56C856CA56C9 5B7F5DD45DD25F4E61FF65246B0A6B6170517058738074E4758A766E766C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000079B37C607C5F807E807D81DF8972896F89FC8B808D168D178E918E938F61 9148944494519452973D973E97C397C1986B99559A559A4D9AD29B1A9C499C31 9C3E9C3B9DD39DD79F349F6C9F6A9F9456CC5DD662006523652B652A66EC6B10 74DA7ACA7C647C637C657E937E967E9481E28638863F88318B8A9090908F9463 946094649768986F995C9A5A9A5B9A579AD39AD49AD19C549C579C569DE59E9F 9EF456D158E9652C705E7671767277D77F507F888836883988628B938B920000 C6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8B9682778D1B91C0946A97429748974497C698709A5F9B229B589C5F9DF99DFA 9E7C9E7D9F079F779F725EF36B1670637C6C7C6E883B89C08EA191C194729470 9871995E9AD69B239ECC706477DA8B9A947797C99A629A657E9C8B9C8EAA91C5 947D947E947C9C779C789EF78C54947F9E1A72289A6A9B319E1B9E1E7C720000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030FE309D309E3005304130423043304430453046304730483049304A304B 304C304D304E304F3050305130523053305430553056305730583059305A305B 305C305D305E305F3060306130623063306430653066306730683069306A306B 306C306D306E306F3070307130723073307430753076307730783079307A307B 307C307D307E307F3080308130823083308430853086308730883089308A308B 308C308D308E308F309030913092309330A130A230A330A430A530A630A70000 C7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 30A830A930AA30AB30AC30AD30AE30AF30B030B130B230B330B430B530B630B7 30B830B930BA30BB30BC30BD30BE30BF30C030C130C230C330C430C530C630C7 30C830C930CA30CB30CC30CD30CE30CF30D030D130D230D330D430D530D630D7 30D830D930DA30DB30DC30DD30DE30DF30E030E130E230E330E430E530E60000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030E730E830E930EA30EB30EC30ED30EE30EF30F030F130F230F330F430F5 30F60414041504010416041704180419041A041B041C04230424042504260427 04280429042A042B042C042D042E042F04300431043204330434043504510436 043704380439043A043B043C043D043E043F0440044104420443044404450446 044704480449044A044B044C044D044E044F2460246124622463246424652466 246724682469247424752476247724782479247A247B247C247D000000000000 C9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E424E5C51F5531A53824E074E0C4E474E8D56D7FA0C5C6E5F734E0F51874E0E 4E2E4E934EC24EC94EC8519852FC536C53B957205903592C5C105DFF65E16BB3 6BCC6C14723F4E314E3C4EE84EDC4EE94EE14EDD4EDA520C531C534C57225723 5917592F5B815B845C125C3B5C745C735E045E805E825FC9620962506C150000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006C366C436C3F6C3B72AE72B0738A79B8808A961E4F0E4F184F2C4EF54F14 4EF14F004EF74F084F1D4F024F054F224F134F044EF44F1251B1521352095210 52A65322531F534D538A540756E156DF572E572A5734593C5980597C5985597B 597E5977597F5B565C155C255C7C5C7A5C7B5C7E5DDF5E755E845F025F1A5F74 5FD55FD45FCF625C625E626462616266626262596260625A626565EF65EE673E 67396738673B673A673F673C67336C186C466C526C5C6C4F6C4A6C546C4B0000 CA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6C4C7071725E72B472B5738E752A767F7A757F518278827C8280827D827F864D 897E909990979098909B909496229624962096234F564F3B4F624F494F534F64 4F3E4F674F524F5F4F414F584F2D4F334F3F4F61518F51B9521C521E522152AD 52AE530953635372538E538F54305437542A545454455419541C542554180000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000543D544F544154285424544756EE56E756E557415745574C5749574B5752 5906594059A6599859A05997598E59A25990598F59A759A15B8E5B925C285C2A 5C8D5C8F5C885C8B5C895C925C8A5C865C935C955DE05E0A5E0E5E8B5E895E8C 5E885E8D5F055F1D5F785F765FD25FD15FD05FED5FE85FEE5FF35FE15FE45FE3 5FFA5FEF5FF75FFB60005FF4623A6283628C628E628F629462876271627B627A 6270628162886277627D62726274653765F065F465F365F265F5674567470000 CB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 67596755674C6748675D674D675A674B6BD06C196C1A6C786C676C6B6C846C8B 6C8F6C716C6F6C696C9A6C6D6C876C956C9C6C666C736C656C7B6C8E7074707A 726372BF72BD72C372C672C172BA72C573957397739373947392753A75397594 75957681793D80348095809980908092809C8290828F8285828E829182930000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000828A828382848C788FC98FBF909F90A190A5909E90A790A096309628962F 962D4E334F984F7C4F854F7D4F804F874F764F744F894F844F774F4C4F974F6A 4F9A4F794F814F784F904F9C4F944F9E4F924F824F954F6B4F6E519E51BC51BE 5235523252335246523152BC530A530B533C539253945487547F548154915482 5488546B547A547E5465546C54745466548D546F546154605498546354675464 56F756F9576F5772576D576B57715770577657805775577B5773577457620000 CC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5768577D590C594559B559BA59CF59CE59B259CC59C159B659BC59C359D659B1 59BD59C059C859B459C75B625B655B935B955C445C475CAE5CA45CA05CB55CAF 5CA85CAC5C9F5CA35CAD5CA25CAA5CA75C9D5CA55CB65CB05CA65E175E145E19 5F285F225F235F245F545F825F7E5F7D5FDE5FE5602D602660196032600B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006034600A60176033601A601E602C6022600D6010602E60136011600C6009 601C6214623D62AD62B462D162BE62AA62B662CA62AE62B362AF62BB62A962B0 62B8653D65A865BB660965FC66046612660865FB6603660B660D660565FD6611 661066F6670A6785676C678E67926776677B6798678667846774678D678C677A 679F679167996783677D67816778677967946B256B806B7E6BDE6C1D6C936CEC 6CEB6CEE6CD96CB66CD46CAD6CE76CB76CD06CC26CBA6CC36CC66CED6CF20000 CD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6CD26CDD6CB46C8A6C9D6C806CDE6CC06D306CCD6CC76CB06CF96CCF6CE96CD1 709470987085709370867084709170967082709A7083726A72D672CB72D872C9 72DC72D272D472DA72CC72D173A473A173AD73A673A273A073AC739D74DD74E8 753F7540753E758C759876AF76F376F176F076F577F877FC77F977FB77FA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077F77942793F79C57A787A7B7AFB7C757CFD8035808F80AE80A380B880B5 80AD822082A082C082AB829A8298829B82B582A782AE82BC829E82BA82B482A8 82A182A982C282A482C382B682A28670866F866D866E8C568FD28FCB8FD38FCD 8FD68FD58FD790B290B490AF90B390B09639963D963C963A96434FCD4FC54FD3 4FB24FC94FCB4FC14FD44FDC4FD94FBB4FB34FDB4FC74FD64FBA4FC04FB94FEC 5244524952C052C2533D537C539753965399539854BA54A154AD54A554CF0000 CE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54C3830D54B754AE54D654B654C554C654A0547054BC54A254BE547254DE54B0 57B5579E579F57A4578C5797579D579B57945798578F579957A5579A579558F4 590D595359E159DE59EE5A0059F159DD59FA59FD59FC59F659E459F259F759DB 59E959F359F559E059FE59F459ED5BA85C4C5CD05CD85CCC5CD75CCB5CDB0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005CDE5CDA5CC95CC75CCA5CD65CD35CD45CCF5CC85CC65CCE5CDF5CF85DF9 5E215E225E235E205E245EB05EA45EA25E9B5EA35EA55F075F2E5F565F866037 603960546072605E6045605360476049605B604C60406042605F602460446058 6066606E6242624362CF630D630B62F5630E630362EB62F9630F630C62F862F6 63006313631462FA631562FB62F06541654365AA65BF6636662166326635661C 662666226633662B663A661D66346639662E670F671067C167F267C867BA0000 CF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 67DC67BB67F867D867C067B767C567EB67E467DF67B567CD67B367F767F667EE 67E367C267B967CE67E767F067B267FC67C667ED67CC67AE67E667DB67FA67C9 67CA67C367EA67CB6B286B826B846BB66BD66BD86BE06C206C216D286D346D2D 6D1F6D3C6D3F6D126D0A6CDA6D336D046D196D3A6D1A6D116D006D1D6D420000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D016D186D376D036D0F6D406D076D206D2C6D086D226D096D1070B7709F 70BE70B170B070A170B470B570A972417249724A726C72707273726E72CA72E4 72E872EB72DF72EA72E672E3738573CC73C273C873C573B973B673B573B473EB 73BF73C773BE73C373C673B873CB74EC74EE752E7547754875A775AA767976C4 7708770377047705770A76F776FB76FA77E777E878067811781278057810780F 780E780978037813794A794C794B7945794479D579CD79CF79D679CE7A800000 D0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7A7E7AD17B007B017C7A7C787C797C7F7C807C817D037D087D017F587F917F8D 7FBE8007800E800F8014803780D880C780E080D180C880C280D080C580E380D9 80DC80CA80D580C980CF80D780E680CD81FF8221829482D982FE82F9830782E8 830082D5833A82EB82D682F482EC82E182F282F5830C82FB82F682F082EA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000082E482E082FA82F382ED86778674867C86738841884E8867886A886989D3 8A048A078D728FE38FE18FEE8FE090F190BD90BF90D590C590BE90C790CB90C8 91D491D39654964F96519653964A964E501E50055007501350225030501B4FF5 4FF450335037502C4FF64FF75017501C502050275035502F5031500E515A5194 519351CA51C451C551C851CE5261525A5252525E525F5255526252CD530E539E 552654E25517551254E754F354E4551A54FF5504550854EB5511550554F10000 D1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 550A54FB54F754F854E0550E5503550B5701570257CC583257D557D257BA57C6 57BD57BC57B857B657BF57C757D057B957C1590E594A5A195A165A2D5A2E5A15 5A0F5A175A0A5A1E5A335B6C5BA75BAD5BAC5C035C565C545CEC5CFF5CEE5CF1 5CF75D005CF95E295E285EA85EAE5EAA5EAC5F335F305F67605D605A60670000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000604160A26088608060926081609D60836095609B60976087609C608E6219 624662F263106356632C634463456336634363E46339634B634A633C63296341 6334635863546359632D63476333635A63516338635763406348654A654665C6 65C365C465C2664A665F6647665167126713681F681A684968326833683B684B 684F68166831681C6835682B682D682F684E68446834681D6812681468266828 682E684D683A682568206B2C6B2F6B2D6B316B346B6D80826B886BE66BE40000 D2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6BE86BE36BE26BE76C256D7A6D636D646D766D0D6D616D926D586D626D6D6D6F 6D916D8D6DEF6D7F6D866D5E6D676D606D976D706D7C6D5F6D826D986D2F6D68 6D8B6D7E6D806D846D166D836D7B6D7D6D756D9070DC70D370D170DD70CB7F39 70E270D770D270DE70E070D470CD70C570C670C770DA70CE70E1724272780000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000072777276730072FA72F472FE72F672F372FB730173D373D973E573D673BC 73E773E373E973DC73D273DB73D473DD73DA73D773D873E874DE74DF74F474F5 7521755B755F75B075C175BB75C475C075BF75B675BA768A76C9771D771B7710 771377127723771177157719771A772277277823782C78227835782F7828782E 782B782178297833782A78317954795B794F795C79537952795179EB79EC79E0 79EE79ED79EA79DC79DE79DD7A867A897A857A8B7A8C7A8A7A877AD87B100000 D3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7B047B137B057B0F7B087B0A7B0E7B097B127C847C917C8A7C8C7C887C8D7C85 7D1E7D1D7D117D0E7D187D167D137D1F7D127D0F7D0C7F5C7F617F5E7F607F5D 7F5B7F967F927FC37FC27FC08016803E803980FA80F280F980F5810180FB8100 8201822F82258333832D83448319835183258356833F83418326831C83220000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008342834E831B832A8308833C834D8316832483208337832F832983478345 834C8353831E832C834B832783488653865286A286A88696868D8691869E8687 86978686868B869A868586A5869986A186A786958698868E869D869086948843 8844886D88758876887288808871887F886F8883887E8874887C8A128C478C57 8C7B8CA48CA38D768D788DB58DB78DB68ED18ED38FFE8FF590028FFF8FFB9004 8FFC8FF690D690E090D990DA90E390DF90E590D890DB90D790DC90E491500000 D4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 914E914F91D591E291DA965C965F96BC98E39ADF9B2F4E7F5070506A5061505E 50605053504B505D50725048504D5041505B504A506250155045505F5069506B 5063506450465040506E50735057505151D0526B526D526C526E52D652D3532D 539C55755576553C554D55505534552A55515562553655355530555255450000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000550C55325565554E55395548552D553B5540554B570A570757FB581457E2 57F657DC57F4580057ED57FD580857F8580B57F357CF580757EE57E357F257E5 57EC57E1580E57FC581057E75801580C57F157E957F0580D5804595C5A605A58 5A555A675A5E5A385A355A6D5A505A5F5A655A6C5A535A645A575A435A5D5A52 5A445A5B5A485A8E5A3E5A4D5A395A4C5A705A695A475A515A565A425A5C5B72 5B6E5BC15BC05C595D1E5D0B5D1D5D1A5D205D0C5D285D0D5D265D255D0F0000 D5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5D305D125D235D1F5D2E5E3E5E345EB15EB45EB95EB25EB35F365F385F9B5F96 5F9F608A6090608660BE60B060BA60D360D460CF60E460D960DD60C860B160DB 60B760CA60BF60C360CD60C063326365638A6382637D63BD639E63AD639D6397 63AB638E636F63876390636E63AF6375639C636D63AE637C63A4633B639F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006378638563816391638D6370655365CD66656661665B6659665C66626718 687968876890689C686D686E68AE68AB6956686F68A368AC68A96875687468B2 688F68776892687C686B687268AA68806871687E689B6896688B68A0688968A4 6878687B6891688C688A687D6B366B336B376B386B916B8F6B8D6B8E6B8C6C2A 6DC06DAB6DB46DB36E746DAC6DE96DE26DB76DF66DD46E006DC86DE06DDF6DD6 6DBE6DE56DDC6DDD6DDB6DF46DCA6DBD6DED6DF06DBA6DD56DC26DCF6DC90000 D6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6DD06DF26DD36DFD6DD76DCD6DE36DBB70FA710D70F7711770F4710C70F07104 70F3711070FC70FF71067113710070F870F6710B7102710E727E727B727C727F 731D7317730773117318730A730872FF730F731E738873F673F873F574047401 73FD7407740073FA73FC73FF740C740B73F474087564756375CE75D275CF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075CB75CC75D175D0768F768976D37739772F772D7731773277347733773D 7725773B7735784878527849784D784A784C782678457850796479677969796A 7963796B796179BB79FA79F879F679F77A8F7A947A907B357B477B347B257B30 7B227B247B337B187B2A7B1D7B317B2B7B2D7B2F7B327B387B1A7B237C947C98 7C967CA37D357D3D7D387D367D3A7D457D2C7D297D417D477D3E7D3F7D4A7D3B 7D287F637F957F9C7F9D7F9B7FCA7FCB7FCD7FD07FD17FC77FCF7FC9801F0000 D7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 801E801B804780438048811881258119811B812D811F812C811E812181158127 811D8122821182388233823A823482328274839083A383A8838D837A837383A4 8374838F8381839583998375839483A9837D8383838C839D839B83AA838B837E 83A583AF8388839783B0837F83A6838783AE8376839A8659865686BF86B70000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000086C286C186C586BA86B086C886B986B386B886CC86B486BB86BC86C386BD 86BE88528889889588A888A288AA889A889188A1889F889888A78899889B8897 88A488AC888C8893888E898289D689D989D58A308A278A2C8A1E8C398C3B8C5C 8C5D8C7D8CA58D7D8D7B8D798DBC8DC28DB98DBF8DC18ED88EDE8EDD8EDC8ED7 8EE08EE19024900B9011901C900C902190EF90EA90F090F490F290F390D490EB 90EC90E991569158915A9153915591EC91F491F191F391F891E491F991EA0000 D8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 91EB91F791E891EE957A95869588967C966D966B9671966F96BF976A980498E5 9997509B50955094509E508B50A35083508C508E509D5068509C509250825087 515F51D45312531153A453A7559155A855A555AD5577564555A255935588558F 55B5558155A3559255A4557D558C55A6557F559555A1558E570C582958370000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005819581E58275823582857F558485825581C581B5833583F5836582E5839 5838582D582C583B59615AAF5A945A9F5A7A5AA25A9E5A785AA65A7C5AA55AAC 5A955AAE5A375A845A8A5A975A835A8B5AA95A7B5A7D5A8C5A9C5A8F5A935A9D 5BEA5BCD5BCB5BD45BD15BCA5BCE5C0C5C305D375D435D6B5D415D4B5D3F5D35 5D515D4E5D555D335D3A5D525D3D5D315D595D425D395D495D385D3C5D325D36 5D405D455E445E415F585FA65FA55FAB60C960B960CC60E260CE60C461140000 D9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 60F2610A6116610560F5611360F860FC60FE60C161036118611D611060FF6104 610B624A639463B163B063CE63E563E863EF63C3649D63F363CA63E063F663D5 63F263F5646163DF63BE63DD63DC63C463D863D363C263C763CC63CB63C863F0 63D763D965326567656A6564655C65686565658C659D659E65AE65D065D20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000667C666C667B668066716679666A66726701690C68D3690468DC692A68EC 68EA68F1690F68D668F768EB68E468F66913691068F368E1690768CC69086970 68B4691168EF68C6691468F868D068FD68FC68E8690B690A691768CE68C868DD 68DE68E668F468D1690668D468E96915692568C76B396B3B6B3F6B3C6B946B97 6B996B956BBD6BF06BF26BF36C306DFC6E466E476E1F6E496E886E3C6E3D6E45 6E626E2B6E3F6E416E5D6E736E1C6E336E4B6E406E516E3B6E036E2E6E5E0000 DA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6E686E5C6E616E316E286E606E716E6B6E396E226E306E536E656E276E786E64 6E776E556E796E526E666E356E366E5A7120711E712F70FB712E713171237125 71227132711F7128713A711B724B725A7288728972867285728B7312730B7330 73227331733373277332732D732673237335730C742E742C7430742B74160000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000741A7421742D743174247423741D74297420743274FB752F756F756C75E7 75DA75E175E675DD75DF75E475D77695769276DA774677477744774D7745774A 774E774B774C77DE77EC786078647865785C786D7871786A786E787078697868 785E786279747973797279707A027A0A7A037A0C7A047A997AE67AE47B4A7B3B 7B447B487B4C7B4E7B407B587B457CA27C9E7CA87CA17D587D6F7D637D537D56 7D677D6A7D4F7D6D7D5C7D6B7D527D547D697D517D5F7D4E7F3E7F3F7F650000 DB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7F667FA27FA07FA17FD78051804F805080FE80D48143814A8152814F8147813D 814D813A81E681EE81F781F881F98204823C823D823F8275833B83CF83F98423 83C083E8841283E783E483FC83F6841083C683C883EB83E383BF840183DD83E5 83D883FF83E183CB83CE83D683F583C98409840F83DE8411840683C283F30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000083D583FA83C783D183EA841383C383EC83EE83C483FB83D783E2841B83DB 83FE86D886E286E686D386E386DA86EA86DD86EB86DC86EC86E986D786E886D1 88488856885588BA88D788B988B888C088BE88B688BC88B788BD88B2890188C9 89958998899789DD89DA89DB8A4E8A4D8A398A598A408A578A588A448A458A52 8A488A518A4A8A4C8A4F8C5F8C818C808CBA8CBE8CB08CB98CB58D848D808D89 8DD88DD38DCD8DC78DD68DDC8DCF8DD58DD98DC88DD78DC58EEF8EF78EFA0000 DC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8EF98EE68EEE8EE58EF58EE78EE88EF68EEB8EF18EEC8EF48EE9902D9034902F 9106912C910490FF90FC910890F990FB9101910091079105910391619164915F 916291609201920A92259203921A9226920F920C9200921291FF91FD92069204 92279202921C92249219921792059216957B958D958C95909687967E96880000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000096899683968096C296C896C396F196F0976C9770976E980798A998EB9CE6 9EF94E834E844EB650BD50BF50C650AE50C450CA50B450C850C250B050C150BA 50B150CB50C950B650B851D7527A5278527B527C55C355DB55CC55D055CB55CA 55DD55C055D455C455E955BF55D2558D55CF55D555E255D655C855F255CD55D9 55C25714585358685864584F584D5849586F5855584E585D58595865585B583D 5863587158FC5AC75AC45ACB5ABA5AB85AB15AB55AB05ABF5AC85ABB5AC60000 DD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5AB75AC05ACA5AB45AB65ACD5AB95A905BD65BD85BD95C1F5C335D715D635D4A 5D655D725D6C5D5E5D685D675D625DF05E4F5E4E5E4A5E4D5E4B5EC55ECC5EC6 5ECB5EC75F405FAF5FAD60F76149614A612B614561366132612E6146612F614F 612961406220916862236225622463C563F163EB641064126409642064240000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000064336443641F641564186439643764226423640C64266430642864416435 642F640A641A644064256427640B63E7641B642E6421640E656F659265D36686 668C66956690668B668A66996694667867206966695F6938694E69626971693F 6945696A6939694269576959697A694869496935696C6933693D696568F06978 693469696940696F69446976695869416974694C693B694B6937695C694F6951 69326952692F697B693C6B466B456B436B426B486B416B9BFA0D6BFB6BFC0000 DE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6BF96BF76BF86E9B6ED66EC86E8F6EC06E9F6E936E946EA06EB16EB96EC66ED2 6EBD6EC16E9E6EC96EB76EB06ECD6EA66ECF6EB26EBE6EC36EDC6ED86E996E92 6E8E6E8D6EA46EA16EBF6EB36ED06ECA6E976EAE6EA371477154715271637160 7141715D716271727178716A7161714271587143714B7170715F715071530000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007144714D715A724F728D728C72917290728E733C7342733B733A7340734A 73497444744A744B7452745174577440744F7450744E74427446744D745474E1 74FF74FE74FD751D75797577698375EF760F760375F775FE75FC75F975F87610 75FB75F675ED75F575FD769976B576DD7755775F776077527756775A77697767 77547759776D77E07887789A7894788F788478957885788678A1788378797899 78807896787B797C7982797D79797A117A187A197A127A177A157A227A130000 DF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7A1B7A107AA37AA27A9E7AEB7B667B647B6D7B747B697B727B657B737B717B70 7B617B787B767B637CB27CB47CAF7D887D867D807D8D7D7F7D857D7A7D8E7D7B 7D837D7C7D8C7D947D847D7D7D927F6D7F6B7F677F687F6C7FA67FA57FA77FDB 7FDC8021816481608177815C8169815B816281726721815E81768167816F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000081448161821D8249824482408242824584F1843F845684768479848F848D 846584518440848684678430844D847D845A845984748473845D8507845E8437 843A8434847A8443847884328445842983D9844B842F8442842D845F84708439 844E844C8452846F84C5848E843B8447843684338468847E8444842B84608454 846E8450870B870486F7870C86FA86D686F5874D86F8870E8709870186F6870D 870588D688CB88CD88CE88DE88DB88DA88CC88D08985899B89DF89E589E40000 E0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 89E189E089E289DC89E68A768A868A7F8A618A3F8A778A828A848A758A838A81 8A748A7A8C3C8C4B8C4A8C658C648C668C868C848C858CCC8D688D698D918D8C 8D8E8D8F8D8D8D938D948D908D928DF08DE08DEC8DF18DEE8DD08DE98DE38DE2 8DE78DF28DEB8DF48F068EFF8F018F008F058F078F088F028F0B9052903F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000090449049903D9110910D910F911191169114910B910E916E916F92489252 9230923A926692339265925E9283922E924A9246926D926C924F92609267926F 92369261927092319254926392509272924E9253924C92569232959F959C959E 959B969296939691969796CE96FA96FD96F896F59773977797789772980F980D 980E98AC98F698F999AF99B299B099B59AAD9AAB9B5B9CEA9CED9CE79E809EFD 50E650D450D750E850F350DB50EA50DD50E450D350EC50F050EF50E350E00000 E1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 51D85280528152E952EB533053AC56275615560C561255FC560F561C56015613 560255FA561D560455FF55F95889587C5890589858865881587F5874588B587A 58875891588E587658825888587B5894588F58FE596B5ADC5AEE5AE55AD55AEA 5ADA5AED5AEB5AF35AE25AE05ADB5AEC5ADE5ADD5AD95AE85ADF5B775BE00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005BE35C635D825D805D7D5D865D7A5D815D775D8A5D895D885D7E5D7C5D8D 5D795D7F5E585E595E535ED85ED15ED75ECE5EDC5ED55ED95ED25ED45F445F43 5F6F5FB6612C61286141615E61716173615261536172616C618061746154617A 615B6165613B616A6161615662296227622B642B644D645B645D647464766472 6473647D6475646664A6644E6482645E645C644B645364606450647F643F646C 646B645964656477657365A066A166A0669F67056704672269B169B669C90000 E2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 69A069CE699669B069AC69BC69916999698E69A7698D69A969BE69AF69BF69C4 69BD69A469D469B969CA699A69CF69B3699369AA69A1699E69D96997699069C2 69B569A569C66B4A6B4D6B4B6B9E6B9F6BA06BC36BC46BFE6ECE6EF56EF16F03 6F256EF86F376EFB6F2E6F096F4E6F196F1A6F276F186F3B6F126EED6F0A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006F366F736EF96EEE6F2D6F406F306F3C6F356EEB6F076F0E6F436F056EFD 6EF66F396F1C6EFC6F3A6F1F6F0D6F1E6F086F21718771907189718071857182 718F717B718671817197724472537297729572937343734D7351734C74627473 7471747574727467746E750075027503757D759076167608760C76157611760A 761476B87781777C77857782776E7780776F777E778378B278AA78B478AD78A8 787E78AB789E78A578A078AC78A278A47998798A798B79967995799479930000 E3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 79977988799279907A2B7A4A7A307A2F7A287A267AA87AAB7AAC7AEE7B887B9C 7B8A7B917B907B967B8D7B8C7B9B7B8E7B857B9852847B997BA47B827CBB7CBF 7CBC7CBA7DA77DB77DC27DA37DAA7DC17DC07DC57D9D7DCE7DC47DC67DCB7DCC 7DAF7DB97D967DBC7D9F7DA67DAE7DA97DA17DC97F737FE27FE37FE57FDE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008024805D805C8189818681838187818D818C818B8215849784A484A1849F 84BA84CE84C284AC84AE84AB84B984B484C184CD84AA849A84B184D0849D84A7 84BB84A2849484C784CC849B84A984AF84A884D6849884B684CF84A084D784D4 84D284DB84B084918661873387238728876B8740872E871E87218719871B8743 872C8741873E874687208732872A872D873C8712873A87318735874287268727 87388724871A8730871188F788E788F188F288FA88FE88EE88FC88F688FB0000 E4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 88F088EC88EB899D89A1899F899E89E989EB89E88AAB8A998A8B8A928A8F8A96 8C3D8C688C698CD58CCF8CD78D968E098E028DFF8E0D8DFD8E0A8E038E078E06 8E058DFE8E008E048F108F118F0E8F0D9123911C91209122911F911D911A9124 9121911B917A91729179917392A592A49276929B927A92A0929492AA928D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000092A6929A92AB92799297927F92A392EE928E9282929592A2927D928892A1 928A9286928C929992A7927E928792A9929D928B922D969E96A196FF9758977D 977A977E978397809782977B97849781977F97CE97CD981698AD98AE99029900 9907999D999C99C399B999BB99BA99C299BD99C79AB19AE39AE79B3E9B3F9B60 9B619B5F9CF19CF29CF59EA750FF5103513050F85106510750F650FE510B510C 50FD510A528B528C52F152EF56485642564C56355641564A5649564656580000 E5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 565A56405633563D562C563E5638562A563A571A58AB589D58B158A058A358AF 58AC58A558A158FF5AFF5AF45AFD5AF75AF65B035AF85B025AF95B015B075B05 5B0F5C675D995D975D9F5D925DA25D935D955DA05D9C5DA15D9A5D9E5E695E5D 5E605E5C7DF35EDB5EDE5EE15F495FB2618B6183617961B161B061A261890000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000619B619361AF61AD619F619261AA61A1618D616661B3622D646E64706496 64A064856497649C648F648B648A648C64A3649F646864B164986576657A6579 657B65B265B366B566B066A966B266B766AA66AF6A006A066A1769E569F86A15 69F169E46A2069FF69EC69E26A1B6A1D69FE6A2769F269EE6A1469F769E76A40 6A0869E669FB6A0D69FC69EB6A096A046A186A256A0F69F66A266A0769F46A16 6B516BA56BA36BA26BA66C016C006BFF6C026F416F266F7E6F876FC66F920000 E6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6F8D6F896F8C6F626F4F6F856F5A6F966F766F6C6F826F556F726F526F506F57 6F946F936F5D6F006F616F6B6F7D6F676F906F536F8B6F696F7F6F956F636F77 6F6A6F7B71B271AF719B71B071A0719A71A971B5719D71A5719E71A471A171AA 719C71A771B37298729A73587352735E735F7360735D735B7361735A73590000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000736274877489748A74867481747D74857488747C747975087507757E7625 761E7619761D761C7623761A7628761B769C769D769E769B778D778F77897788 78CD78BB78CF78CC78D178CE78D478C878C378C478C9799A79A179A0799C79A2 799B6B767A397AB27AB47AB37BB77BCB7BBE7BAC7BCE7BAF7BB97BCA7BB57CC5 7CC87CCC7CCB7DF77DDB7DEA7DE77DD77DE17E037DFA7DE67DF67DF17DF07DEE 7DDF7F767FAC7FB07FAD7FED7FEB7FEA7FEC7FE67FE88064806781A3819F0000 E7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 819E819581A2819981978216824F825382528250824E82518524853B850F8500 8529850E8509850D851F850A8527851C84FB852B84FA8508850C84F4852A84F2 851584F784EB84F384FC851284EA84E9851684FE8528851D852E850284FD851E 84F68531852684E784E884F084EF84F9851885208530850B8519852F86620000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000875687638764877787E1877387588754875B87528761875A8751875E876D 876A8750874E875F875D876F876C877A876E875C8765874F877B877587628767 8769885A8905890C8914890B891789188919890689168911890E890989A289A4 89A389ED89F089EC8ACF8AC68AB88AD38AD18AD48AD58ABB8AD78ABE8AC08AC5 8AD88AC38ABA8ABD8AD98C3E8C4D8C8F8CE58CDF8CD98CE88CDA8CDD8CE78DA0 8D9C8DA18D9B8E208E238E258E248E2E8E158E1B8E168E118E198E268E270000 E8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8E148E128E188E138E1C8E178E1A8F2C8F248F188F1A8F208F238F168F179073 9070906F9067906B912F912B9129912A91329126912E91859186918A91819182 9184918092D092C392C492C092D992B692CF92F192DF92D892E992D792DD92CC 92EF92C292E892CA92C892CE92E692CD92D592C992E092DE92E792D192D30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000092B592E192C692B4957C95AC95AB95AE95B096A496A296D3970597089702 975A978A978E978897D097CF981E981D9826982998289820981B982798B29908 98FA9911991499169917991599DC99CD99CF99D399D499CE99C999D699D899CB 99D799CC9AB39AEC9AEB9AF39AF29AF19B469B439B679B749B719B669B769B75 9B709B689B649B6C9CFC9CFA9CFD9CFF9CF79D079D009CF99CFB9D089D059D04 9E839ED39F0F9F10511C51135117511A511151DE533453E156705660566E0000 E9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 567356665663566D5672565E5677571C571B58C858BD58C958BF58BA58C258BC 58C65B175B195B1B5B215B145B135B105B165B285B1A5B205B1E5BEF5DAC5DB1 5DA95DA75DB55DB05DAE5DAA5DA85DB25DAD5DAF5DB45E675E685E665E6F5EE9 5EE75EE65EE85EE55F4B5FBC619D61A8619661C561B461C661C161CC61BA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000061BF61B8618C64D764D664D064CF64C964BD648964C364DB64F364D96533 657F657C65A266C866BE66C066CA66CB66CF66BD66BB66BA66CC67236A346A66 6A496A676A326A686A3E6A5D6A6D6A766A5B6A516A286A5A6A3B6A3F6A416A6A 6A646A506A4F6A546A6F6A696A606A3C6A5E6A566A556A4D6A4E6A466B556B54 6B566BA76BAA6BAB6BC86BC76C046C036C066FAD6FCB6FA36FC76FBC6FCE6FC8 6F5E6FC46FBD6F9E6FCA6FA870046FA56FAE6FBA6FAC6FAA6FCF6FBF6FB80000 EA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6FA26FC96FAB6FCD6FAF6FB26FB071C571C271BF71B871D671C071C171CB71D4 71CA71C771CF71BD71D871BC71C671DA71DB729D729E736973667367736C7365 736B736A747F749A74A074947492749574A1750B7580762F762D7631763D7633 763C76357632763076BB76E6779A779D77A1779C779B77A277A3779577990000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000779778DD78E978E578EA78DE78E378DB78E178E278ED78DF78E079A47A44 7A487A477AB67AB87AB57AB17AB77BDE7BE37BE77BDD7BD57BE57BDA7BE87BF9 7BD47BEA7BE27BDC7BEB7BD87BDF7CD27CD47CD77CD07CD17E127E217E177E0C 7E1F7E207E137E0E7E1C7E157E1A7E227E0B7E0F7E167E0D7E147E257E247F43 7F7B7F7C7F7A7FB17FEF802A8029806C81B181A681AE81B981B581AB81B081AC 81B481B281B781A781F282558256825785568545856B854D8553856185580000 EB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 854085468564854185628544855185478563853E855B8571854E856E85758555 85678560858C8566855D85548565856C866386658664879B878F879787938792 87888781879687988779878787A3878587908791879D87848794879C879A8789 891E89268930892D892E89278931892289298923892F892C891F89F18AE00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008AE28AF28AF48AF58ADD8B148AE48ADF8AF08AC88ADE8AE18AE88AFF8AEF 8AFB8C918C928C908CF58CEE8CF18CF08CF38D6C8D6E8DA58DA78E338E3E8E38 8E408E458E368E3C8E3D8E418E308E3F8EBD8F368F2E8F358F328F398F378F34 90769079907B908690FA913391359136919391909191918D918F9327931E9308 931F9306930F937A9338933C931B9323931293019346932D930E930D92CB931D 92FA9325931392F992F793349302932492FF932993399335932A9314930C0000 EC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 930B92FE9309930092FB931695BC95CD95BE95B995BA95B695BF95B595BD96A9 96D4970B9712971097999797979497F097F89835982F98329924991F99279929 999E99EE99EC99E599E499F099E399EA99E999E79AB99ABF9AB49ABB9AF69AFA 9AF99AF79B339B809B859B879B7C9B7E9B7B9B829B939B929B909B7A9B950000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009B7D9B889D259D179D209D1E9D149D299D1D9D189D229D109D199D1F9E88 9E869E879EAE9EAD9ED59ED69EFA9F129F3D51265125512251245120512952F4 5693568C568D568656845683567E5682567F568158D658D458CF58D25B2D5B25 5B325B235B2C5B275B265B2F5B2E5B7B5BF15BF25DB75E6C5E6A5FBE5FBB61C3 61B561BC61E761E061E561E461E861DE64EF64E964E364EB64E464E865816580 65B665DA66D26A8D6A966A816AA56A896A9F6A9B6AA16A9E6A876A936A8E0000 ED 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A956A836AA86AA46A916A7F6AA66A9A6A856A8C6A926B5B6BAD6C096FCC6FA9 6FF46FD46FE36FDC6FED6FE76FE66FDE6FF26FDD6FE26FE871E171F171E871F2 71E471F071E27373736E736F749774B274AB749074AA74AD74B174A574AF7510 75117512750F7584764376487649764776A476E977B577AB77B277B777B60000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077B477B177A877F078F378FD790278FB78FC78F2790578F978FE790479AB 79A87A5C7A5B7A567A587A547A5A7ABE7AC07AC17C057C0F7BF27C007BFF7BFB 7C0E7BF47C0B7BF37C027C097C037C017BF87BFD7C067BF07BF17C107C0A7CE8 7E2D7E3C7E427E3398487E387E2A7E497E407E477E297E4C7E307E3B7E367E44 7E3A7F457F7F7F7E7F7D7FF47FF2802C81BB81C481CC81CA81C581C781BC81E9 825B825A825C85838580858F85A7859585A0858B85A3857B85A4859A859E0000 EE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8577857C858985A1857A85788557858E85968586858D8599859D858185A28582 858885858579857685988590859F866887BE87AA87AD87C587B087AC87B987B5 87BC87AE87C987C387C287CC87B787AF87C487CA87B487B687BF87B887BD87DE 87B289358933893C893E894189528937894289AD89AF89AE89F289F38B1E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008B188B168B118B058B0B8B228B0F8B128B158B078B0D8B088B068B1C8B13 8B1A8C4F8C708C728C718C6F8C958C948CF98D6F8E4E8E4D8E538E508E4C8E47 8F438F409085907E9138919A91A2919B9199919F91A1919D91A093A1938393AF 936493569347937C9358935C93769349935093519360936D938F934C936A9379 935793559352934F93719377937B9361935E936393679380934E935995C795C0 95C995C395C595B796AE96B096AC9720971F9718971D9719979A97A1979C0000 EF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 979E979D97D597D497F198419844984A9849984598439925992B992C992A9933 9932992F992D99319930999899A399A19A0299FA99F499F799F999F899F699FB 99FD99FE99FC9A039ABE9AFE9AFD9B019AFC9B489B9A9BA89B9E9B9B9BA69BA1 9BA59BA49B869BA29BA09BAF9D339D419D679D369D2E9D2F9D319D389D300000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009D459D429D439D3E9D379D409D3D7FF59D2D9E8A9E899E8D9EB09EC89EDA 9EFB9EFF9F249F239F229F549FA05131512D512E5698569C5697569A569D5699 59705B3C5C695C6A5DC05E6D5E6E61D861DF61ED61EE61F161EA61F061EB61D6 61E964FF650464FD64F86501650364FC659465DB66DA66DB66D86AC56AB96ABD 6AE16AC66ABA6AB66AB76AC76AB46AAD6B5E6BC96C0B7007700C700D70017005 7014700E6FFF70006FFB70266FFC6FF7700A720171FF71F9720371FD73760000 F0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 74B874C074B574C174BE74B674BB74C275147513765C76647659765076537657 765A76A676BD76EC77C277BA78FF790C79137914790979107912791179AD79AC 7A5F7C1C7C297C197C207C1F7C2D7C1D7C267C287C227C257C307E5C7E507E56 7E637E587E627E5F7E517E607E577E537FB57FB37FF77FF8807581D181D20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000081D0825F825E85B485C685C085C385C285B385B585BD85C785C485BF85CB 85CE85C885C585B185B685D2862485B885B785BE866987E787E687E287DB87EB 87EA87E587DF87F387E487D487DC87D387ED87D887E387A487D787D9880187F4 87E887DD8953894B894F894C89468950895189498B2A8B278B238B338B308B35 8B478B2F8B3C8B3E8B318B258B378B268B368B2E8B248B3B8B3D8B3A8C428C75 8C998C988C978CFE8D048D028D008E5C8E628E608E578E568E5E8E658E670000 F1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8E5B8E5A8E618E5D8E698E548F468F478F488F4B9128913A913B913E91A891A5 91A791AF91AA93B5938C939293B7939B939D938993A7938E93AA939E93A69395 93889399939F938D93B1939193B293A493A893B493A393A595D295D395D196B3 96D796DA5DC296DF96D896DD97239722972597AC97AE97A897AB97A497AA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000097A297A597D797D997D697D897FA98509851985298B89941993C993A9A0F 9A0B9A099A0D9A049A119A0A9A059A079A069AC09ADC9B089B049B059B299B35 9B4A9B4C9B4B9BC79BC69BC39BBF9BC19BB59BB89BD39BB69BC49BB99BBD9D5C 9D539D4F9D4A9D5B9D4B9D599D569D4C9D579D529D549D5F9D589D5A9E8E9E8C 9EDF9F019F009F169F259F2B9F2A9F299F289F4C9F5551345135529652F753B4 56AB56AD56A656A756AA56AC58DA58DD58DB59125B3D5B3E5B3F5DC35E700000 F2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5FBF61FB65076510650D6509650C650E658465DE65DD66DE6AE76AE06ACC6AD1 6AD96ACB6ADF6ADC6AD06AEB6ACF6ACD6ADE6B606BB06C0C7019702770207016 702B702170227023702970177024701C702A720C720A72077202720572A572A6 72A472A372A174CB74C574B774C37516766077C977CA77C477F1791D791B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007921791C7917791E79B07A677A687C337C3C7C397C2C7C3B7CEC7CEA7E76 7E757E787E707E777E6F7E7A7E727E747E687F4B7F4A7F837F867FB77FFD7FFE 807881D781D582648261826385EB85F185ED85D985E185E885DA85D785EC85F2 85F885D885DF85E385DC85D185F085E685EF85DE85E2880087FA880387F687F7 8809880C880B880687FC880887FF880A88028962895A895B89578961895C8958 895D8959898889B789B689F68B508B488B4A8B408B538B568B548B4B8B550000 F3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8B518B428B528B578C438C778C768C9A8D068D078D098DAC8DAA8DAD8DAB8E6D 8E788E738E6A8E6F8E7B8EC28F528F518F4F8F508F538FB49140913F91B091AD 93DE93C793CF93C293DA93D093F993EC93CC93D993A993E693CA93D493EE93E3 93D593C493CE93C093D293E7957D95DA95DB96E19729972B972C972897260000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000097B397B797B697DD97DE97DF985C9859985D985798BF98BD98BB98BE9948 9947994399A699A79A1A9A159A259A1D9A249A1B9A229A209A279A239A1E9A1C 9A149AC29B0B9B0A9B0E9B0C9B379BEA9BEB9BE09BDE9BE49BE69BE29BF09BD4 9BD79BEC9BDC9BD99BE59BD59BE19BDA9D779D819D8A9D849D889D719D809D78 9D869D8B9D8C9D7D9D6B9D749D759D709D699D859D739D7B9D829D6F9D799D7F 9D879D689E949E919EC09EFC9F2D9F409F419F4D9F569F579F58533756B20000 F4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 56B556B358E35B455DC65DC75EEE5EEF5FC05FC161F9651765166515651365DF 66E866E366E46AF36AF06AEA6AE86AF96AF16AEE6AEF703C7035702F70377034 703170427038703F703A70397040703B703370417213721472A8737D737C74BA 76AB76AA76BE76ED77CC77CE77CF77CD77F27925792379277928792479290000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000079B27A6E7A6C7A6D7AF77C497C487C4A7C477C457CEE7E7B7E7E7E817E80 7FBA7FFF807981DB81D9820B82688269862285FF860185FE861B860085F68604 86098605860C85FD8819881088118817881388168963896689B989F78B608B6A 8B5D8B688B638B658B678B6D8DAE8E868E888E848F598F568F578F558F588F5A 908D9143914191B791B591B291B3940B941393FB9420940F941493FE94159410 94289419940D93F5940093F79407940E9416941293FA940993F8940A93FF0000 F5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 93FC940C93F69411940695DE95E095DF972E972F97B997BB97FD97FE98609862 9863985F98C198C29950994E9959994C994B99539A329A349A319A2C9A2A9A36 9A299A2E9A389A2D9AC79ACA9AC69B109B129B119C0B9C089BF79C059C129BF8 9C409C079C0E9C069C179C149C099D9F9D999DA49D9D9D929D989D909D9B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009DA09D949D9C9DAA9D979DA19D9A9DA29DA89D9E9DA39DBF9DA99D969DA6 9DA79E999E9B9E9A9EE59EE49EE79EE69F309F2E9F5B9F609F5E9F5D9F599F91 513A51395298529756C356BD56BE5B485B475DCB5DCF5EF161FD651B6B026AFC 6B036AF86B0070437044704A7048704970457046721D721A7219737E7517766A 77D0792D7931792F7C547C537CF27E8A7E877E887E8B7E867E8D7F4D7FBB8030 81DD8618862A8626861F8623861C86198627862E862186208629861E86250000 F6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8829881D881B88208824881C882B884A896D8969896E896B89FA8B798B788B45 8B7A8B7B8D108D148DAF8E8E8E8C8F5E8F5B8F5D91469144914591B9943F943B 94369429943D943C94309439942A9437942C9440943195E595E495E39735973A 97BF97E1986498C998C698C0995899569A399A3D9A469A449A429A419A3A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009A3F9ACD9B159B179B189B169B3A9B529C2B9C1D9C1C9C2C9C239C289C29 9C249C219DB79DB69DBC9DC19DC79DCA9DCF9DBE9DC59DC39DBB9DB59DCE9DB9 9DBA9DAC9DC89DB19DAD9DCC9DB39DCD9DB29E7A9E9C9EEB9EEE9EED9F1B9F18 9F1A9F319F4E9F659F649F924EB956C656C556CB59715B4B5B4C5DD55DD15EF2 65216520652665226B0B6B086B096C0D7055705670577052721E721F72A9737F 74D874D574D974D7766D76AD793579B47A707A717C577C5C7C597C5B7C5A0000 F7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7CF47CF17E917F4F7F8781DE826B863486358633862C86328636882C88288826 882A8825897189BF89BE89FB8B7E8B848B828B868B858B7F8D158E958E948E9A 8E928E908E968E978F608F629147944C9450944A944B944F9447944594489449 9446973F97E3986A986998CB9954995B9A4E9A539A549A4C9A4F9A489A4A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009A499A529A509AD09B199B2B9B3B9B569B559C469C489C3F9C449C399C33 9C419C3C9C379C349C329C3D9C369DDB9DD29DDE9DDA9DCB9DD09DDC9DD19DDF 9DE99DD99DD89DD69DF59DD59DDD9EB69EF09F359F339F329F429F6B9F959FA2 513D529958E858E759725B4D5DD8882F5F4F62016203620465296525659666EB 6B116B126B0F6BCA705B705A7222738273817383767077D47C677C667E95826C 863A86408639863C8631863B863E88308832882E883389768974897389FE0000 F8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8B8C8B8E8B8B8B888C458D198E988F648F6391BC94629455945D9457945E97C4 97C598009A569A599B1E9B1F9B209C529C589C509C4A9C4D9C4B9C559C599C4C 9C4E9DFB9DF79DEF9DE39DEB9DF89DE49DF69DE19DEE9DE69DF29DF09DE29DEC 9DF49DF39DE89DED9EC29ED09EF29EF39F069F1C9F389F379F369F439F4F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009F719F709F6E9F6F56D356CD5B4E5C6D652D66ED66EE6B13705F7061705D 7060722374DB74E577D5793879B779B67C6A7E977F89826D8643883888378835 884B8B948B958E9E8E9F8EA08E9D91BE91BD91C2946B9468946996E597469743 974797C797E59A5E9AD59B599C639C679C669C629C5E9C609E029DFE9E079E03 9E069E059E009E019E099DFF9DFD9E049EA09F1E9F469F749F759F7656D4652E 65B86B186B196B176B1A7062722672AA77D877D979397C697C6B7CF67E9A0000 F9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7E987E9B7E9981E081E18646864786488979897A897C897B89FF8B988B998EA5 8EA48EA3946E946D946F9471947397499872995F9C689C6E9C6D9E0B9E0D9E10 9E0F9E129E119EA19EF59F099F479F789F7B9F7A9F79571E70667C6F883C8DB2 8EA691C394749478947694759A609C749C739C719C759E149E139EF69F0A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009FA4706870657CF7866A883E883D883F8B9E8C9C8EA98EC9974B98739874 98CC996199AB9A649A669A679B249E159E179F4862076B1E7227864C8EA89482 948094819A699A689B2E9E197229864B8B9F94839C799EB776759A6B9C7A9E1D 7069706A9EA49F7E9F499F980000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 tcl8.6.5/library/encoding/cp864.enc0000644000175000017500000000210211555560473016350 0ustar sergeisergei# Encoding file: cp864, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 00200021002200230024066A0026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00B000B72219221A259225002502253C2524252C251C25342510250C25142518 03B2221E03C600B100BD00BC224800AB00BBFEF7FEF8009B009CFEFBFEFC009F 00A000ADFE8200A300A4FE8400000000FE8EFE8FFE95FE99060CFE9DFEA1FEA5 0660066106620663066406650666066706680669FED1061BFEB1FEB5FEB9061F 00A2FE80FE81FE83FE85FECAFE8BFE8DFE91FE93FE97FE9BFE9FFEA3FEA7FEA9 FEABFEADFEAFFEB3FEB7FEBBFEBFFEC1FEC5FECBFECF00A600AC00F700D7FEC9 0640FED3FED7FEDBFEDFFEE3FEE7FEEBFEEDFEEFFEF3FEBDFECCFECEFECDFEE1 FE7D0651FEE5FEE9FEECFEF0FEF2FED0FED5FEF5FEF6FEDDFED9FEF125A00000 tcl8.6.5/library/encoding/cp860.enc0000644000175000017500000000210211555560473016344 0ustar sergeisergei# Encoding file: cp860, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C700FC00E900E200E300E000C100E700EA00CA00E800CD00D400EC00C300C2 00C900C000C800F400F500F200DA00F900CC00D500DC00A200A300D920A700D3 00E100ED00F300FA00F100D100AA00BA00BF00D200AC00BD00BC00A100AB00BB 259125922593250225242561256225562555256325512557255D255C255B2510 25142534252C251C2500253C255E255F255A25542569256625602550256C2567 2568256425652559255825522553256B256A2518250C25882584258C25902580 03B100DF039303C003A303C300B503C403A6039803A903B4221E03C603B52229 226100B1226522642320232100F7224800B0221900B7221A207F00B225A000A0 tcl8.6.5/library/encoding/gb1988.enc0000644000175000017500000000210311555560473016427 0ustar sergeisergei# Encoding file: gb1988, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 002000210022002300A500250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D203E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 tcl8.6.5/library/encoding/macThai.enc0000644000175000017500000000210411555560473017054 0ustar sergeisergei# Encoding file: macThai, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00AB00BB2026F88CF88FF892F895F898F88BF88EF891F894F897201C201DF899 FFFD2022F884F889F885F886F887F888F88AF88DF890F893F89620182019FFFD 00A00E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F 0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F 0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F 0E300E310E320E330E340E350E360E370E380E390E3AFEFF200B201320140E3F 0E400E410E420E430E440E450E460E470E480E490E4A0E4B0E4C0E4D21220E4F 0E500E510E520E530E540E550E560E570E580E5900AE00A9FFFDFFFDFFFDFFFD tcl8.6.5/library/encoding/euc-jp.enc0000644000175000017500000024115111555560473016700 0ustar sergeisergei# Encoding file: euc-jp, multi-byte M 003F 0 79 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D0000008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000300030013002FF0CFF0E30FBFF1AFF1BFF1FFF01309B309C00B4FF4000A8 FF3EFFE3FF3F30FD30FE309D309E30034EDD30053006300730FC20152010FF0F FF3C301C2016FF5C2026202520182019201C201DFF08FF0930143015FF3BFF3D FF5BFF5D30083009300A300B300C300D300E300F30103011FF0B221200B100D7 00F7FF1D2260FF1CFF1E22662267221E22342642264000B0203220332103FFE5 FF0400A200A3FF05FF03FF06FF0AFF2000A72606260525CB25CF25CE25C70000 A2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000025C625A125A025B325B225BD25BC203B3012219221902191219330130000 00000000000000000000000000000000000000002208220B2286228722822283 222A2229000000000000000000000000000000002227222800AC21D221D42200 220300000000000000000000000000000000000000000000222022A523122202 220722612252226A226B221A223D221D2235222B222C00000000000000000000 00000000212B2030266F266D266A2020202100B6000000000000000025EF0000 A3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FF10FF11FF12FF13FF14FF15FF16FF17FF18FF19000000000000000000000000 0000FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2F FF30FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3A00000000000000000000 0000FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5A00000000000000000000 A4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000304130423043304430453046304730483049304A304B304C304D304E304F 3050305130523053305430553056305730583059305A305B305C305D305E305F 3060306130623063306430653066306730683069306A306B306C306D306E306F 3070307130723073307430753076307730783079307A307B307C307D307E307F 3080308130823083308430853086308730883089308A308B308C308D308E308F 3090309130923093000000000000000000000000000000000000000000000000 A5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF 30B030B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF 30C030C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF 30D030D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000000 A6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000039103920393039403950396039703980399039A039B039C039D039E039F 03A003A103A303A403A503A603A703A803A90000000000000000000000000000 000003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C303C403C503C603C703C803C90000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000004100411041204130414041504010416041704180419041A041B041C041D 041E041F0420042104220423042404250426042704280429042A042B042C042D 042E042F00000000000000000000000000000000000000000000000000000000 000004300431043204330434043504510436043704380439043A043B043C043D 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000000000 A8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000025002502250C251025182514251C252C25242534253C25012503250F2513 251B251725232533252B253B254B2520252F25282537253F251D253025252538 2542000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 B0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E9C55165A03963F54C0611B632859F690228475831C7A5060AA63E16E25 65ED846682A69BF56893572765A162715B9B59D0867B98F47D627DBE9B8E6216 7C9F88B75B895EB563096697684895C7978D674F4EE54F0A4F4D4F9D504956F2 593759D45A015C0960DF610F61706613690570BA754F757079FB7DAD7DEF80C3 840E88638B029055907A533B4E954EA557DF80B290C178EF4E0058F16EA29038 7A328328828B9C2F5141537054BD54E156E059FB5F1598F26DEB80E4852D0000 B1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009662967096A097FB540B53F35B8770CF7FBD8FC296E8536F9D5C7ABA4E11 789381FC6E26561855046B1D851A9C3B59E553A96D6674DC958F56424E91904B 96F2834F990C53E155B65B305F71662066F368046C386CF36D29745B76C87A4E 983482F1885B8A6092ED6DB275AB76CA99C560A68B018D8A95B2698E53AD5186 5712583059445BB45EF6602863A963F46CBF6F14708E7114715971D5733F7E01 827682D185979060925B9D1B586965BC6C5A752551F9592E59655F805FDC0000 B2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000062BC65FA6A2A6B276BB4738B7FC189569D2C9D0E9EC45CA16C96837B5104 5C4B61B681C6687672614E594FFA537860696E297A4F97F34E0B53164EEE4F55 4F3D4FA14F7352A053EF5609590F5AC15BB65BE179D16687679C67B66B4C6CB3 706B73C2798D79BE7A3C7B8782B182DB8304837783EF83D387668AB256298CA8 8FE6904E971E868A4FC45CE862117259753B81E582BD86FE8CC096C5991399D5 4ECB4F1A89E356DE584A58CA5EFB5FEB602A6094606261D0621262D065390000 B3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009B41666668B06D777070754C76867D7582A587F9958B968E8C9D51F152BE 591654B35BB35D16616869826DAF788D84CB88578A7293A79AB86D6C99A886D9 57A367FF86CE920E5283568754045ED362E164B9683C68386BBB737278BA7A6B 899A89D28D6B8F0390ED95A3969497695B665CB3697D984D984E639B7B206A2B 6A7F68B69C0D6F5F5272559D607062EC6D3B6E076ED1845B89108F444E149C39 53F6691B6A3A9784682A515C7AC384B291DC938C565B9D286822830584310000 B4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007CA5520882C574E64E7E4F8351A05BD2520A52D852E75DFB559A582A59E6 5B8C5B985BDB5E725E7960A3611F616361BE63DB656267D1685368FA6B3E6B53 6C576F226F976F4574B0751876E3770B7AFF7BA17C217DE97F367FF0809D8266 839E89B38ACC8CAB908494519593959195A2966597D3992882184E38542B5CB8 5DCC73A9764C773C5CA97FEB8D0B96C19811985498584F014F0E5371559C5668 57FA59475B095BC45C905E0C5E7E5FCC63EE673A65D765E2671F68CB68C40000 B5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006A5F5E306BC56C176C7D757F79485B637A007D005FBD898F8A188CB48D77 8ECC8F1D98E29A0E9B3C4E80507D510059935B9C622F628064EC6B3A72A07591 79477FA987FB8ABC8B7063AC83CA97A05409540355AB68546A588A7078276775 9ECD53745BA2811A865090064E184E454EC74F1153CA54385BAE5F1360256551 673D6C426C726CE3707874037A767AAE7B087D1A7CFE7D6665E7725B53BB5C45 5DE862D262E063196E20865A8A318DDD92F86F0179A69B5A4EA84EAB4EAC0000 B6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F9B4FA050D151477AF6517151F653545321537F53EB55AC58835CE15F37 5F4A602F6050606D631F65596A4B6CC172C272ED77EF80F881058208854E90F7 93E197FF99579A5A4EF051DD5C2D6681696D5C4066F26975738968507C8150C5 52E457475DFE932665A46B236B3D7434798179BD7B4B7DCA82B983CC887F895F 8B398FD191D1541F92804E5D503653E5533A72D7739677E982E68EAF99C699C8 99D25177611A865E55B07A7A50765BD3904796854E326ADB91E75C515C480000 B7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000063987A9F6C9397748F617AAA718A96887C8268177E706851936C52F2541B 85AB8A137FA48ECD90E15366888879414FC250BE521151445553572D73EA578B 59515F625F8460756176616761A963B2643A656C666F68426E1375667A3D7CFB 7D4C7D997E4B7F6B830E834A86CD8A088A638B668EFD981A9D8F82B88FCE9BE8 5287621F64836FC09699684150916B206C7A6F547A747D5088408A2367084EF6 503950265065517C5238526355A7570F58055ACC5EFA61B261F862F363720000 B8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000691C6A29727D72AC732E7814786F7D79770C80A9898B8B198CE28ED29063 9375967A98559A139E785143539F53B35E7B5F266E1B6E90738473FE7D438237 8A008AFA96504E4E500B53E4547C56FA59D15B645DF15EAB5F276238654567AF 6E5672D07CCA88B480A180E183F0864E8A878DE8923796C798679F134E944E92 4F0D53485449543E5A2F5F8C5FA1609F68A76A8E745A78818A9E8AA48B779190 4E5E9BC94EA44F7C4FAF501950165149516C529F52B952FE539A53E354110000 B9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000540E5589575157A2597D5B545B5D5B8F5DE55DE75DF75E785E835E9A5EB7 5F186052614C629762D863A7653B6602664366F4676D6821689769CB6C5F6D2A 6D696E2F6E9D75327687786C7A3F7CE07D057D187D5E7DB18015800380AF80B1 8154818F822A8352884C88618B1B8CA28CFC90CA91759271783F92FC95A4964D 980599999AD89D3B525B52AB53F7540858D562F76FE08C6A8F5F9EB9514B523B 544A56FD7A4091779D609ED273446F09817075115FFD60DA9AA872DB8FBC0000 BA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006B6498034ECA56F0576458BE5A5A606861C7660F6606683968B16DF775D5 7D3A826E9B424E9B4F5053C955065D6F5DE65DEE67FB6C99747378028A509396 88DF57505EA7632B50B550AC518D670054C9585E59BB5BB05F69624D63A1683D 6B736E08707D91C7728078157826796D658E7D3083DC88C18F09969B52645728 67507F6A8CA151B45742962A583A698A80B454B25D0E57FC78959DFA4F5C524A 548B643E6628671467F57A847B567D22932F685C9BAD7B395319518A52370000 BB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005BDF62F664AE64E6672D6BBA85A996D176909BD6634C93069BAB76BF6652 4E09509853C25C7160E864926563685F71E673CA75237B977E8286958B838CDB 9178991065AC66AB6B8B4ED54ED44F3A4F7F523A53F853F255E356DB58EB59CB 59C959FF5B505C4D5E025E2B5FD7601D6307652F5B5C65AF65BD65E8679D6B62 6B7B6C0F7345794979C17CF87D197D2B80A2810281F389968A5E8A698A668A8C 8AEE8CC78CDC96CC98FC6B6F4E8B4F3C4F8D51505B575BFA6148630166420000 BC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006B216ECB6CBB723E74BD75D478C1793A800C803381EA84948F9E6C509E7F 5F0F8B589D2B7AFA8EF85B8D96EB4E0353F157F759315AC95BA460896E7F6F06 75BE8CEA5B9F85007BE0507267F4829D5C61854A7E1E820E51995C0463688D66 659C716E793E7D1780058B1D8ECA906E86C790AA501F52FA5C3A6753707C7235 914C91C8932B82E55BC25F3160F94E3B53D65B88624B67316B8A72E973E07A2E 816B8DA391529996511253D7546A5BFF63886A397DAC970056DA53CE54680000 BD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005B975C315DDE4FEE610162FE6D3279C079CB7D427E4D7FD281ED821F8490 884689728B908E748F2F9031914B916C96C6919C4EC04F4F514553415F93620E 67D46C416E0B73637E2691CD928353D459195BBF6DD1795D7E2E7C9B587E719F 51FA88538FF04FCA5CFB662577AC7AE3821C99FF51C65FAA65EC696F6B896DF3 6E966F6476FE7D145DE190759187980651E6521D6240669166D96E1A5EB67DD2 7F7266F885AF85F78AF852A953D959735E8F5F90605592E4966450B7511F0000 BE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000052DD5320534753EC54E8554655315617596859BE5A3C5BB55C065C0F5C11 5C1A5E845E8A5EE05F70627F628462DB638C63776607660C662D6676677E68A2 6A1F6A356CBC6D886E096E58713C7126716775C77701785D7901796579F07AE0 7B117CA77D39809683D6848B8549885D88F38A1F8A3C8A548A738C618CDE91A4 9266937E9418969C97984E0A4E084E1E4E575197527057CE583458CC5B225E38 60C564FE676167566D4472B675737A6384B88B7291B89320563157F498FE0000 BF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000062ED690D6B9671ED7E548077827289E698DF87558FB15C3B4F384FE14FB5 55075A205BDD5BE95FC3614E632F65B0664B68EE699B6D786DF1753375B9771F 795E79E67D3381E382AF85AA89AA8A3A8EAB8F9B903291DD97074EBA4EC15203 587558EC5C0B751A5C3D814E8A0A8FC59663976D7B258ACF9808916256F353A8 9017543957825E2563A86C34708A77617C8B7FE088709042915493109318968F 745E9AC45D075D69657067A28DA896DB636E6749691983C5981796C088FE0000 C0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006F84647A5BF84E16702C755D662F51C4523652E259D35F8160276210653F 6574661F667468F268166B636E057272751F76DB7CBE805658F088FD897F8AA0 8A938ACB901D91929752975965897A0E810696BB5E2D60DC621A65A566146790 77F37A4D7C4D7E3E810A8CAC8D648DE18E5F78A9520762D963A5644262988A2D 7A837BC08AAC96EA7D76820C87494ED95148534353605BA35C025C165DDD6226 624764B0681368346CC96D456D1767D36F5C714E717D65CB7A7F7BAD7DDA0000 C1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007E4A7FA8817A821B823985A68A6E8CCE8DF59078907792AD929195839BAE 524D55846F387136516879857E5581B37CCE564C58515CA863AA66FE66FD695A 72D9758F758E790E795679DF7C977D207D4486078A34963B90619F2050E75275 53CC53E2500955AA58EE594F723D5B8B5C64531D60E360F3635C6383633F63BB 64CD65E966F95DE369CD69FD6F1571E54E8975E976F87A937CDF7DCF7D9C8061 83498358846C84BC85FB88C58D709001906D9397971C9A1250CF5897618E0000 C2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000081D385358D0890204FC3507452475373606F6349675F6E2C8DB3901F4FD7 5C5E8CCA65CF7D9A53528896517663C35B585B6B5C0A640D6751905C4ED6591A 592A6C708A51553E581559A560F0625367C182356955964099C49A284F535806 5BFE80105CB15E2F5F856020614B623466FF6CF06EDE80CE817F82D4888B8CB8 9000902E968A9EDB9BDB4EE353F059277B2C918D984C9DF96EDD702753535544 5B856258629E62D36CA26FEF74228A1794386FC18AFE833851E786F853EA0000 C3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000053E94F4690548FB0596A81315DFD7AEA8FBF68DA8C3772F89C486A3D8AB0 4E3953585606576662C563A265E66B4E6DE16E5B70AD77ED7AEF7BAA7DBB803D 80C686CB8A95935B56E358C75F3E65AD66966A806BB575378AC7502477E55730 5F1B6065667A6C6075F47A1A7F6E81F48718904599B37BC9755C7AF97B5184C4 901079E97A9283365AE177404E2D4EF25B995FE062BD663C67F16CE8866B8877 8A3B914E92F399D06A177026732A82E784578CAF4E01514651CB558B5BF50000 C4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005E165E335E815F145F355F6B5FB461F2631166A2671D6F6E7252753A773A 80748139817887768ABF8ADC8D858DF3929A957798029CE552C5635776F46715 6C8873CD8CC393AE96736D25589C690E69CC8FFD939A75DB901A585A680263B4 69FB4F436F2C67D88FBB85267DB49354693F6F70576A58F75B2C7D2C722A540A 91E39DB44EAD4F4E505C507552438C9E544858245B9A5E1D5E955EAD5EF75F1F 608C62B5633A63D068AF6C407887798E7A0B7DE082478A028AE68E4490130000 C5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000090B8912D91D89F0E6CE5645864E265756EF476847B1B906993D16EBA54F2 5FB964A48F4D8FED92445178586B59295C555E976DFB7E8F751C8CBC8EE2985B 70B94F1D6BBF6FB1753096FB514E54105835585759AC5C605F926597675C6E21 767B83DF8CED901490FD934D7825783A52AA5EA6571F597460125012515A51AC 51CD520055105854585859575B955CF65D8B60BC6295642D6771684368BC68DF 76D76DD86E6F6D9B706F71C85F5375D879777B497B547B527CD67D7152300000 C6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008463856985E48A0E8B048C468E0F9003900F94199676982D9A3095D850CD 52D5540C58025C0E61A7649E6D1E77B37AE580F48404905392855CE09D07533F 5F975FB36D9C7279776379BF7BE46BD272EC8AAD68036A6151F87A8169345C4A 9CF682EB5BC59149701E56785C6F60C765666C8C8C5A90419813545166C7920D 594890A351854E4D51EA85998B0E7058637A934B696299B47E04757753576960 8EDF96E36C5D4E8C5C3C5F108FE953028CD1808986795EFF65E54E7351650000 C7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000059825C3F97EE4EFB598A5FCD8A8D6FE179B079625BE78471732B71B15E74 5FF5637B649A71C37C984E435EFC4E4B57DC56A260A96FC37D0D80FD813381BF 8FB2899786A45DF4628A64AD898767776CE26D3E743678345A467F7582AD99AC 4FF35EC362DD63926557676F76C3724C80CC80BA8F29914D500D57F95A926885 6973716472FD8CB758F28CE0966A9019877F79E477E784294F2F5265535A62CD 67CF6CCA767D7B947C95823685848FEB66DD6F2072067E1B83AB99C19EA60000 C8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000051FD7BB178727BB880877B486AE85E61808C75517560516B92626E8C767A 91979AEA4F107F70629C7B4F95A59CE9567A585986E496BC4F345224534A53CD 53DB5E06642C6591677F6C3E6C4E724872AF73ED75547E41822C85E98CA97BC4 91C67169981298EF633D6669756A76E478D0854386EE532A5351542659835E87 5F7C60B26249627962AB65906BD46CCC75B276AE789179D87DCB7F7780A588AB 8AB98CBB907F975E98DB6A0B7C3850995C3E5FAE67876BD8743577097F8E0000 C9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009F3B67CA7A175339758B9AED5F66819D83F180985F3C5FC575627B46903C 686759EB5A9B7D10767E8B2C4FF55F6A6A196C376F0274E2796888688A558C79 5EDF63CF75C579D282D7932892F2849C86ED9C2D54C15F6C658C6D5C70158CA7 8CD3983B654F74F64E0D4ED857E0592B5A665BCC51A85E035E9C601662766577 65A7666E6D6E72367B268150819A82998B5C8CA08CE68D74961C96444FAE64AB 6B66821E8461856A90E85C01695398A8847A85574F0F526F5FA95E45670D0000 CA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000798F8179890789866DF55F1762556CB84ECF72699B925206543B567458B3 61A4626E711A596E7C897CDE7D1B96F06587805E4E194F75517558405E635E73 5F0A67C44E26853D9589965B7C73980150FB58C1765678A7522577A585117B86 504F590972477BC77DE88FBA8FD4904D4FBF52C95A295F0197AD4FDD821792EA 570363556B69752B88DC8F147A4252DF58936155620A66AE6BCD7C3F83E95023 4FF853055446583159495B9D5CF05CEF5D295E9662B16367653E65B9670B0000 CB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006CD56CE170F978327E2B80DE82B3840C84EC870289128A2A8C4A90A692D2 98FD9CF39D6C4E4F4EA1508D5256574A59A85E3D5FD85FD9623F66B4671B67D0 68D251927D2180AA81A88B008C8C8CBF927E96325420982C531750D5535C58A8 64B26734726777667A4691E652C36CA16B8658005E4C5954672C7FFB51E176C6 646978E89B549EBB57CB59B96627679A6BCE54E969D95E55819C67959BAA67FE 9C52685D4EA64FE353C862B9672B6CAB8FC44FAD7E6D9EBF4E0761626E800000 CC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006F2B85135473672A9B455DF37B955CAC5BC6871C6E4A84D17A1481085999 7C8D6C11772052D959227121725F77DB97279D61690B5A7F5A1851A5540D547D 660E76DF8FF792989CF459EA725D6EC5514D68C97DBF7DEC97629EBA64786A21 830259845B5F6BDB731B76F27DB280178499513267289ED976EE676252FF9905 5C24623B7C7E8CB0554F60B67D0B958053014E5F51B6591C723A803691CE5F25 77E253845F797D0485AC8A338E8D975667F385AE9453610961086CB976520000 CD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008AED8F38552F4F51512A52C753CB5BA55E7D60A0618263D6670967DA6E67 6D8C733673377531795088D58A98904A909190F596C4878D59154E884F594E0E 8A898F3F981050AD5E7C59965BB95EB863DA63FA64C166DC694A69D86D0B6EB6 719475287AAF7F8A8000844984C989818B218E0A9065967D990A617E62916B32 6C836D747FCC7FFC6DC07F8587BA88F8676583B1983C96F76D1B7D61843D916A 4E7153755D506B046FEB85CD862D89A75229540F5C65674E68A8740674830000 CE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075E288CF88E191CC96E296785F8B73877ACB844E63A0756552896D416E9C 74097559786B7C9296867ADC9F8D4FB6616E65C5865C4E864EAE50DA4E2151CC 5BEE659968816DBC731F764277AD7A1C7CE7826F8AD2907C91CF96759818529B 7DD1502B539867976DCB71D0743381E88F2A96A39C579E9F746058416D997D2F 985E4EE44F364F8B51B752B15DBA601C73B2793C82D3923496B796F6970A9E97 9F6266A66B74521752A370C888C25EC9604B61906F2371497C3E7DF4806F0000 CF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000084EE9023932C54429B6F6AD370898CC28DEF973252B45A415ECA5F046717 697C69946D6A6F0F726272FC7BED8001807E874B90CE516D9E937984808B9332 8AD6502D548C8A716B6A8CC4810760D167A09DF24E994E989C108A6B85C18568 69006E7E78978155000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 D0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F0C4E104E154E2A4E314E364E3C4E3F4E424E564E584E824E858C6B4E8A 82125F0D4E8E4E9E4E9F4EA04EA24EB04EB34EB64ECE4ECD4EC44EC64EC24ED7 4EDE4EED4EDF4EF74F094F5A4F304F5B4F5D4F574F474F764F884F8F4F984F7B 4F694F704F914F6F4F864F9651184FD44FDF4FCE4FD84FDB4FD14FDA4FD04FE4 4FE5501A50285014502A502550054F1C4FF650215029502C4FFE4FEF50115006 504350476703505550505048505A5056506C50785080509A508550B450B20000 D1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000050C950CA50B350C250D650DE50E550ED50E350EE50F950F5510951015102 511651155114511A5121513A5137513C513B513F51405152514C515451627AF8 5169516A516E5180518256D8518C5189518F519151935195519651A451A651A2 51A951AA51AB51B351B151B251B051B551BD51C551C951DB51E0865551E951ED 51F051F551FE5204520B5214520E5227522A522E52335239524F5244524B524C 525E5254526A527452695273527F527D528D529452925271528852918FA80000 D2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008FA752AC52AD52BC52B552C152CD52D752DE52E352E698ED52E052F352F5 52F852F9530653087538530D5310530F5315531A5323532F5331533353385340 534653454E175349534D51D6535E5369536E5918537B53775382539653A053A6 53A553AE53B053B653C37C1296D953DF66FC71EE53EE53E853ED53FA5401543D 5440542C542D543C542E54365429541D544E548F5475548E545F547154775470 5492547B5480547654845490548654C754A254B854A554AC54C454C854A80000 D3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000054AB54C254A454BE54BC54D854E554E6550F551454FD54EE54ED54FA54E2 553955405563554C552E555C55455556555755385533555D5599558054AF558A 559F557B557E5598559E55AE557C558355A9558755A855DA55C555DF55C455DC 55E455D4561455F7561655FE55FD561B55F9564E565071DF5634563656325638 566B5664562F566C566A56865680568A56A05694568F56A556AE56B656B456C2 56BC56C156C356C056C856CE56D156D356D756EE56F9570056FF570457090000 D4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005708570B570D57135718571655C7571C572657375738574E573B5740574F 576957C057885761577F5789579357A057B357A457AA57B057C357C657D457D2 57D3580A57D657E3580B5819581D587258215862584B58706BC05852583D5879 588558B9589F58AB58BA58DE58BB58B858AE58C558D358D158D758D958D858E5 58DC58E458DF58EF58FA58F958FB58FC58FD5902590A5910591B68A65925592C 592D59325938593E7AD259555950594E595A5958596259605967596C59690000 D5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000059785981599D4F5E4FAB59A359B259C659E859DC598D59D959DA5A255A1F 5A115A1C5A095A1A5A405A6C5A495A355A365A625A6A5A9A5ABC5ABE5ACB5AC2 5ABD5AE35AD75AE65AE95AD65AFA5AFB5B0C5B0B5B165B325AD05B2A5B365B3E 5B435B455B405B515B555B5A5B5B5B655B695B705B735B755B7865885B7A5B80 5B835BA65BB85BC35BC75BC95BD45BD05BE45BE65BE25BDE5BE55BEB5BF05BF6 5BF35C055C075C085C0D5C135C205C225C285C385C395C415C465C4E5C530000 D6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C505C4F5B715C6C5C6E4E625C765C795C8C5C915C94599B5CAB5CBB5CB6 5CBC5CB75CC55CBE5CC75CD95CE95CFD5CFA5CED5D8C5CEA5D0B5D155D175D5C 5D1F5D1B5D115D145D225D1A5D195D185D4C5D525D4E5D4B5D6C5D735D765D87 5D845D825DA25D9D5DAC5DAE5DBD5D905DB75DBC5DC95DCD5DD35DD25DD65DDB 5DEB5DF25DF55E0B5E1A5E195E115E1B5E365E375E445E435E405E4E5E575E54 5E5F5E625E645E475E755E765E7A9EBC5E7F5EA05EC15EC25EC85ED05ECF0000 D7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005ED65EE35EDD5EDA5EDB5EE25EE15EE85EE95EEC5EF15EF35EF05EF45EF8 5EFE5F035F095F5D5F5C5F0B5F115F165F295F2D5F385F415F485F4C5F4E5F2F 5F515F565F575F595F615F6D5F735F775F835F825F7F5F8A5F885F915F875F9E 5F995F985FA05FA85FAD5FBC5FD65FFB5FE45FF85FF15FDD60B35FFF60216060 601960106029600E6031601B6015602B6026600F603A605A6041606A6077605F 604A6046604D6063604360646042606C606B60596081608D60E76083609A0000 D8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006084609B60966097609260A7608B60E160B860E060D360B45FF060BD60C6 60B560D8614D6115610660F660F7610060F460FA6103612160FB60F1610D610E 6147613E61286127614A613F613C612C6134613D614261446173617761586159 615A616B6174616F61656171615F615D6153617561996196618761AC6194619A 618A619161AB61AE61CC61CA61C961F761C861C361C661BA61CB7F7961CD61E6 61E361F661FA61F461FF61FD61FC61FE620062086209620D620C6214621B0000 D9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000621E6221622A622E6230623262336241624E625E6263625B62606268627C 62826289627E62926293629662D46283629462D762D162BB62CF62FF62C664D4 62C862DC62CC62CA62C262C7629B62C9630C62EE62F163276302630862EF62F5 6350633E634D641C634F6396638E638063AB637663A3638F6389639F63B5636B 636963BE63E963C063C663E363C963D263F663C4641664346406641364266436 651D64176428640F6467646F6476644E652A6495649364A564A9648864BC0000 DA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000064DA64D264C564C764BB64D864C264F164E7820964E064E162AC64E364EF 652C64F664F464F264FA650064FD6518651C650565246523652B653465356537 65366538754B654865566555654D6558655E655D65726578658265838B8A659B 659F65AB65B765C365C665C165C465CC65D265DB65D965E065E165F16772660A 660365FB6773663566366634661C664F664466496641665E665D666466676668 665F6662667066836688668E668966846698669D66C166B966C966BE66BC0000 DB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000066C466B866D666DA66E0663F66E666E966F066F566F7670F6716671E6726 67279738672E673F67366741673867376746675E676067596763676467896770 67A9677C676A678C678B67A667A1678567B767EF67B467EC67B367E967B867E4 67DE67DD67E267EE67B967CE67C667E76A9C681E684668296840684D6832684E 68B3682B685968636877687F689F688F68AD6894689D689B68836AAE68B96874 68B568A068BA690F688D687E690168CA690868D86922692668E1690C68CD0000 DC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000068D468E768D569366912690468D768E3692568F968E068EF6928692A691A 6923692168C669796977695C6978696B6954697E696E69396974693D69596930 6961695E695D6981696A69B269AE69D069BF69C169D369BE69CE5BE869CA69DD 69BB69C369A76A2E699169A0699C699569B469DE69E86A026A1B69FF6B0A69F9 69F269E76A0569B16A1E69ED6A1469EB6A0A6A126AC16A236A136A446A0C6A72 6A366A786A476A626A596A666A486A386A226A906A8D6AA06A846AA26AA30000 DD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006A9786176ABB6AC36AC26AB86AB36AAC6ADE6AD16ADF6AAA6ADA6AEA6AFB 6B0586166AFA6B126B169B316B1F6B386B3776DC6B3998EE6B476B436B496B50 6B596B546B5B6B5F6B616B786B796B7F6B806B846B836B8D6B986B956B9E6BA4 6BAA6BAB6BAF6BB26BB16BB36BB76BBC6BC66BCB6BD36BDF6BEC6BEB6BF36BEF 9EBE6C086C136C146C1B6C246C236C5E6C556C626C6A6C826C8D6C9A6C816C9B 6C7E6C686C736C926C906CC46CF16CD36CBD6CD76CC56CDD6CAE6CB16CBE0000 DE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006CBA6CDB6CEF6CD96CEA6D1F884D6D366D2B6D3D6D386D196D356D336D12 6D0C6D636D936D646D5A6D796D596D8E6D956FE46D856DF96E156E0A6DB56DC7 6DE66DB86DC66DEC6DDE6DCC6DE86DD26DC56DFA6DD96DE46DD56DEA6DEE6E2D 6E6E6E2E6E196E726E5F6E3E6E236E6B6E2B6E766E4D6E1F6E436E3A6E4E6E24 6EFF6E1D6E386E826EAA6E986EC96EB76ED36EBD6EAF6EC46EB26ED46ED56E8F 6EA56EC26E9F6F416F11704C6EEC6EF86EFE6F3F6EF26F316EEF6F326ECC0000 DF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006F3E6F136EF76F866F7A6F786F816F806F6F6F5B6FF36F6D6F826F7C6F58 6F8E6F916FC26F666FB36FA36FA16FA46FB96FC66FAA6FDF6FD56FEC6FD46FD8 6FF16FEE6FDB7009700B6FFA70117001700F6FFE701B701A6F74701D7018701F 7030703E7032705170637099709270AF70F170AC70B870B370AE70DF70CB70DD 70D9710970FD711C711971657155718871667162714C7156716C718F71FB7184 719571A871AC71D771B971BE71D271C971D471CE71E071EC71E771F571FC0000 E0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000071F971FF720D7210721B7228722D722C72307232723B723C723F72407246 724B72587274727E7282728172877292729672A272A772B972B272C372C672C4 72CE72D272E272E072E172F972F7500F7317730A731C7316731D7334732F7329 7325733E734E734F9ED87357736A7368737073787375737B737A73C873B373CE 73BB73C073E573EE73DE74A27405746F742573F87432743A7455743F745F7459 7441745C746974707463746A7476747E748B749E74A774CA74CF74D473F10000 E1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000074E074E374E774E974EE74F274F074F174F874F7750475037505750C750E 750D75157513751E7526752C753C7544754D754A7549755B7546755A75697564 7567756B756D75787576758675877574758A758975827594759A759D75A575A3 75C275B375C375B575BD75B875BC75B175CD75CA75D275D975E375DE75FE75FF 75FC760175F075FA75F275F3760B760D7609761F762776207621762276247634 7630763B764776487646765C76587661766276687669766A7667766C76700000 E2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000767276767678767C768076837688768B768E769676937699769A76B076B4 76B876B976BA76C276CD76D676D276DE76E176E576E776EA862F76FB77087707 770477297724771E77257726771B773777387747775A7768776B775B7765777F 777E7779778E778B779177A0779E77B077B677B977BF77BC77BD77BB77C777CD 77D777DA77DC77E377EE77FC780C781279267820792A7845788E78747886787C 789A788C78A378B578AA78AF78D178C678CB78D478BE78BC78C578CA78EC0000 E3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000078E778DA78FD78F47907791279117919792C792B794079607957795F795A 79557953797A797F798A799D79A79F4B79AA79AE79B379B979BA79C979D579E7 79EC79E179E37A087A0D7A187A197A207A1F79807A317A3B7A3E7A377A437A57 7A497A617A627A699F9D7A707A797A7D7A887A977A957A987A967AA97AC87AB0 7AB67AC57AC47ABF90837AC77ACA7ACD7ACF7AD57AD37AD97ADA7ADD7AE17AE2 7AE67AED7AF07B027B0F7B0A7B067B337B187B197B1E7B357B287B367B500000 E4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007B7A7B047B4D7B0B7B4C7B457B757B657B747B677B707B717B6C7B6E7B9D 7B987B9F7B8D7B9C7B9A7B8B7B927B8F7B5D7B997BCB7BC17BCC7BCF7BB47BC6 7BDD7BE97C117C147BE67BE57C607C007C077C137BF37BF77C177C0D7BF67C23 7C277C2A7C1F7C377C2B7C3D7C4C7C437C547C4F7C407C507C587C5F7C647C56 7C657C6C7C757C837C907CA47CAD7CA27CAB7CA17CA87CB37CB27CB17CAE7CB9 7CBD7CC07CC57CC27CD87CD27CDC7CE29B3B7CEF7CF27CF47CF67CFA7D060000 E5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007D027D1C7D157D0A7D457D4B7D2E7D327D3F7D357D467D737D567D4E7D72 7D687D6E7D4F7D637D937D897D5B7D8F7D7D7D9B7DBA7DAE7DA37DB57DC77DBD 7DAB7E3D7DA27DAF7DDC7DB87D9F7DB07DD87DDD7DE47DDE7DFB7DF27DE17E05 7E0A7E237E217E127E317E1F7E097E0B7E227E467E667E3B7E357E397E437E37 7E327E3A7E677E5D7E567E5E7E597E5A7E797E6A7E697E7C7E7B7E837DD57E7D 8FAE7E7F7E887E897E8C7E927E907E937E947E967E8E7E9B7E9C7F387F3A0000 E6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007F457F4C7F4D7F4E7F507F517F557F547F587F5F7F607F687F697F677F78 7F827F867F837F887F877F8C7F947F9E7F9D7F9A7FA37FAF7FB27FB97FAE7FB6 7FB88B717FC57FC67FCA7FD57FD47FE17FE67FE97FF37FF998DC80068004800B 801280188019801C80218028803F803B804A804680528058805A805F80628068 80738072807080768079807D807F808480868085809B8093809A80AD519080AC 80DB80E580D980DD80C480DA80D6810980EF80F1811B81298123812F814B0000 E7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000968B8146813E8153815180FC8171816E81658166817481838188818A8180 818281A0819581A481A3815F819381A981B081B581BE81B881BD81C081C281BA 81C981CD81D181D981D881C881DA81DF81E081E781FA81FB81FE820182028205 8207820A820D821082168229822B82388233824082598258825D825A825F8264 82628268826A826B822E827182778278827E828D829282AB829F82BB82AC82E1 82E382DF82D282F482F382FA8393830382FB82F982DE830682DC830982D90000 E8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000833583348316833283318340833983508345832F832B831783188385839A 83AA839F83A283968323838E8387838A837C83B58373837583A0838983A883F4 841383EB83CE83FD840383D8840B83C183F7840783E083F2840D8422842083BD 8438850683FB846D842A843C855A84848477846B84AD846E848284698446842C 846F8479843584CA846284B984BF849F84D984CD84BB84DA84D084C184C684D6 84A1852184FF84F485178518852C851F8515851484FC85408563855885480000 E9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000085418602854B8555858085A485888591858A85A8856D8594859B85EA8587 859C8577857E859085C985BA85CF85B985D085D585DD85E585DC85F9860A8613 860B85FE85FA86068622861A8630863F864D4E558654865F86678671869386A3 86A986AA868B868C86B686AF86C486C686B086C9882386AB86D486DE86E986EC 86DF86DB86EF8712870687088700870386FB87118709870D86F9870A8734873F 8737873B87258729871A8760875F8778874C874E877487578768876E87590000 EA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000087538763876A880587A2879F878287AF87CB87BD87C087D096D687AB87C4 87B387C787C687BB87EF87F287E0880F880D87FE87F687F7880E87D288118816 8815882288218831883688398827883B8844884288528859885E8862886B8881 887E889E8875887D88B5887288828897889288AE889988A2888D88A488B088BF 88B188C388C488D488D888D988DD88F9890288FC88F488E888F28904890C890A 89138943891E8925892A892B89418944893B89368938894C891D8960895E0000 EB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000089668964896D896A896F89748977897E89838988898A8993899889A189A9 89A689AC89AF89B289BA89BD89BF89C089DA89DC89DD89E789F489F88A038A16 8A108A0C8A1B8A1D8A258A368A418A5B8A528A468A488A7C8A6D8A6C8A628A85 8A828A848AA88AA18A918AA58AA68A9A8AA38AC48ACD8AC28ADA8AEB8AF38AE7 8AE48AF18B148AE08AE28AF78ADE8ADB8B0C8B078B1A8AE18B168B108B178B20 8B3397AB8B268B2B8B3E8B288B418B4C8B4F8B4E8B498B568B5B8B5A8B6B0000 EC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008B5F8B6C8B6F8B748B7D8B808B8C8B8E8B928B938B968B998B9A8C3A8C41 8C3F8C488C4C8C4E8C508C558C628C6C8C788C7A8C828C898C858C8A8C8D8C8E 8C948C7C8C98621D8CAD8CAA8CBD8CB28CB38CAE8CB68CC88CC18CE48CE38CDA 8CFD8CFA8CFB8D048D058D0A8D078D0F8D0D8D109F4E8D138CCD8D148D168D67 8D6D8D718D738D818D998DC28DBE8DBA8DCF8DDA8DD68DCC8DDB8DCB8DEA8DEB 8DDF8DE38DFC8E088E098DFF8E1D8E1E8E108E1F8E428E358E308E348E4A0000 ED 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008E478E498E4C8E508E488E598E648E608E2A8E638E558E768E728E7C8E81 8E878E858E848E8B8E8A8E938E918E948E998EAA8EA18EAC8EB08EC68EB18EBE 8EC58EC88ECB8EDB8EE38EFC8EFB8EEB8EFE8F0A8F058F158F128F198F138F1C 8F1F8F1B8F0C8F268F338F3B8F398F458F428F3E8F4C8F498F468F4E8F578F5C 8F628F638F648F9C8F9F8FA38FAD8FAF8FB78FDA8FE58FE28FEA8FEF90878FF4 90058FF98FFA901190159021900D901E9016900B90279036903590398FF80000 EE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000904F905090519052900E9049903E90569058905E9068906F907696A89072 9082907D90819080908A9089908F90A890AF90B190B590E290E4624890DB9102 9112911991329130914A9156915891639165916991739172918B9189918291A2 91AB91AF91AA91B591B491BA91C091C191C991CB91D091D691DF91E191DB91FC 91F591F6921E91FF9214922C92159211925E925792459249926492489295923F 924B9250929C92969293929B925A92CF92B992B792E9930F92FA9344932E0000 EF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000093199322931A9323933A9335933B935C9360937C936E935693B093AC93AD 939493B993D693D793E893E593D893C393DD93D093C893E4941A941494139403 940794109436942B94359421943A944194529444945B94609462945E946A9229 947094759477947D945A947C947E9481947F95829587958A9594959695989599 95A095A895A795AD95BC95BB95B995BE95CA6FF695C395CD95CC95D595D495D6 95DC95E195E595E296219628962E962F9642964C964F964B9677965C965E0000 F0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000965D965F96669672966C968D96989695969796AA96A796B196B296B096B4 96B696B896B996CE96CB96C996CD894D96DC970D96D596F99704970697089713 970E9711970F971697199724972A97309739973D973E97449746974897429749 975C976097649766976852D2976B977197799785977C9781977A9786978B978F 9790979C97A897A697A397B397B497C397C697C897CB97DC97ED9F4F97F27ADF 97F697F5980F980C9838982498219837983D9846984F984B986B986F98700000 F1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000098719874987398AA98AF98B198B698C498C398C698E998EB990399099912 991499189921991D991E99249920992C992E993D993E9942994999459950994B 99519952994C99559997999899A599AD99AE99BC99DF99DB99DD99D899D199ED 99EE99F199F299FB99F89A019A0F9A0599E29A199A2B9A379A459A429A409A43 9A3E9A559A4D9A5B9A579A5F9A629A659A649A699A6B9A6A9AAD9AB09ABC9AC0 9ACF9AD19AD39AD49ADE9ADF9AE29AE39AE69AEF9AEB9AEE9AF49AF19AF70000 F2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009AFB9B069B189B1A9B1F9B229B239B259B279B289B299B2A9B2E9B2F9B32 9B449B439B4F9B4D9B4E9B519B589B749B939B839B919B969B979B9F9BA09BA8 9BB49BC09BCA9BB99BC69BCF9BD19BD29BE39BE29BE49BD49BE19C3A9BF29BF1 9BF09C159C149C099C139C0C9C069C089C129C0A9C049C2E9C1B9C259C249C21 9C309C479C329C469C3E9C5A9C609C679C769C789CE79CEC9CF09D099D089CEB 9D039D069D2A9D269DAF9D239D1F9D449D159D129D419D3F9D3E9D469D480000 F3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009D5D9D5E9D649D519D509D599D729D899D879DAB9D6F9D7A9D9A9DA49DA9 9DB29DC49DC19DBB9DB89DBA9DC69DCF9DC29DD99DD39DF89DE69DED9DEF9DFD 9E1A9E1B9E1E9E759E799E7D9E819E889E8B9E8C9E929E959E919E9D9EA59EA9 9EB89EAA9EAD97619ECC9ECE9ECF9ED09ED49EDC9EDE9EDD9EE09EE59EE89EEF 9EF49EF69EF79EF99EFB9EFC9EFD9F079F0876B79F159F219F2C9F3E9F4A9F52 9F549F639F5F9F609F619F669F679F6C9F6A9F779F729F769F959F9C9FA00000 F4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000582F69C79059746451DC7199000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 R A1C1 301C FF5E A1C2 2016 2225 A1DD 2212 FF0D A1F1 00A2 FFE0 A1F2 00A3 FFE1 A2CC 00AC FFE2 tcl8.6.5/library/encoding/iso2022-kr.enc0000644000175000017500000000016311555560473017223 0ustar sergeisergei# Encoding file: iso2022-kr, escape-driven E name iso2022-kr init \x1b$)C final {} iso8859-1 \x0f ksc5601 \x0e tcl8.6.5/library/encoding/iso8859-9.enc0000644000175000017500000000210611555560473017006 0ustar sergeisergei# Encoding file: iso8859-9, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF 00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF 011E00D100D200D300D400D500D600D700D800D900DA00DB00DC0130015E00DF 00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF 011F00F100F200F300F400F500F600F700F800F900FA00FB00FC0131015F00FF tcl8.6.5/library/encoding/jis0208.enc0000644000175000017500000023510512663660066016616 0ustar sergeisergei# Encoding file: jis0208, double-byte D 2129 0 77 21 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000300030013002FF0CFF0E30FBFF1AFF1BFF1FFF01309B309C00B4FF4000A8 FF3EFFE3FF3F30FD30FE309D309E30034EDD30053006300730FC20152010FF0F FF3C301C2016FF5C2026202520182019201C201DFF08FF0930143015FF3BFF3D FF5BFF5D30083009300A300B300C300D300E300F30103011FF0B221200B100D7 00F7FF1D2260FF1CFF1E22662267221E22342642264000B0203220332103FFE5 FF0400A200A3FF05FF03FF06FF0AFF2000A72606260525CB25CF25CE25C70000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 22 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000025C625A125A025B325B225BD25BC203B3012219221902191219330130000 00000000000000000000000000000000000000002208220B2286228722822283 222A2229000000000000000000000000000000002227222800AC21D221D42200 220300000000000000000000000000000000000000000000222022A523122202 220722612252226A226B221A223D221D2235222B222C00000000000000000000 00000000212B2030266F266D266A2020202100B6000000000000000025EF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 23 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FF10FF11FF12FF13FF14FF15FF16FF17FF18FF19000000000000000000000000 0000FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2F FF30FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3A00000000000000000000 0000FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5A00000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 24 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000304130423043304430453046304730483049304A304B304C304D304E304F 3050305130523053305430553056305730583059305A305B305C305D305E305F 3060306130623063306430653066306730683069306A306B306C306D306E306F 3070307130723073307430753076307730783079307A307B307C307D307E307F 3080308130823083308430853086308730883089308A308B308C308D308E308F 3090309130923093000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 25 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF 30B030B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF 30C030C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF 30D030D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 26 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000039103920393039403950396039703980399039A039B039C039D039E039F 03A003A103A303A403A503A603A703A803A90000000000000000000000000000 000003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C303C403C503C603C703C803C90000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 27 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000004100411041204130414041504010416041704180419041A041B041C041D 041E041F0420042104220423042404250426042704280429042A042B042C042D 042E042F00000000000000000000000000000000000000000000000000000000 000004300431043204330434043504510436043704380439043A043B043C043D 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 28 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000025002502250C251025182514251C252C25242534253C25012503250F2513 251B251725232533252B253B254B2520252F25282537253F251D253025252538 2542000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 30 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E9C55165A03963F54C0611B632859F690228475831C7A5060AA63E16E25 65ED846682A69BF56893572765A162715B9B59D0867B98F47D627DBE9B8E6216 7C9F88B75B895EB563096697684895C7978D674F4EE54F0A4F4D4F9D504956F2 593759D45A015C0960DF610F61706613690570BA754F757079FB7DAD7DEF80C3 840E88638B029055907A533B4E954EA557DF80B290C178EF4E0058F16EA29038 7A328328828B9C2F5141537054BD54E156E059FB5F1598F26DEB80E4852D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 31 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009662967096A097FB540B53F35B8770CF7FBD8FC296E8536F9D5C7ABA4E11 789381FC6E26561855046B1D851A9C3B59E553A96D6674DC958F56424E91904B 96F2834F990C53E155B65B305F71662066F368046C386CF36D29745B76C87A4E 983482F1885B8A6092ED6DB275AB76CA99C560A68B018D8A95B2698E53AD5186 5712583059445BB45EF6602863A963F46CBF6F14708E7114715971D5733F7E01 827682D185979060925B9D1B586965BC6C5A752551F9592E59655F805FDC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 32 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000062BC65FA6A2A6B276BB4738B7FC189569D2C9D0E9EC45CA16C96837B5104 5C4B61B681C6687672614E594FFA537860696E297A4F97F34E0B53164EEE4F55 4F3D4FA14F7352A053EF5609590F5AC15BB65BE179D16687679C67B66B4C6CB3 706B73C2798D79BE7A3C7B8782B182DB8304837783EF83D387668AB256298CA8 8FE6904E971E868A4FC45CE862117259753B81E582BD86FE8CC096C5991399D5 4ECB4F1A89E356DE584A58CA5EFB5FEB602A6094606261D0621262D065390000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 33 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009B41666668B06D777070754C76867D7582A587F9958B968E8C9D51F152BE 591654B35BB35D16616869826DAF788D84CB88578A7293A79AB86D6C99A886D9 57A367FF86CE920E5283568754045ED362E164B9683C68386BBB737278BA7A6B 899A89D28D6B8F0390ED95A3969497695B665CB3697D984D984E639B7B206A2B 6A7F68B69C0D6F5F5272559D607062EC6D3B6E076ED1845B89108F444E149C39 53F6691B6A3A9784682A515C7AC384B291DC938C565B9D286822830584310000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 34 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007CA5520882C574E64E7E4F8351A05BD2520A52D852E75DFB559A582A59E6 5B8C5B985BDB5E725E7960A3611F616361BE63DB656267D1685368FA6B3E6B53 6C576F226F976F4574B0751876E3770B7AFF7BA17C217DE97F367FF0809D8266 839E89B38ACC8CAB908494519593959195A2966597D3992882184E38542B5CB8 5DCC73A9764C773C5CA97FEB8D0B96C19811985498584F014F0E5371559C5668 57FA59475B095BC45C905E0C5E7E5FCC63EE673A65D765E2671F68CB68C40000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 35 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006A5F5E306BC56C176C7D757F79485B637A007D005FBD898F8A188CB48D77 8ECC8F1D98E29A0E9B3C4E80507D510059935B9C622F628064EC6B3A72A07591 79477FA987FB8ABC8B7063AC83CA97A05409540355AB68546A588A7078276775 9ECD53745BA2811A865090064E184E454EC74F1153CA54385BAE5F1360256551 673D6C426C726CE3707874037A767AAE7B087D1A7CFE7D6665E7725B53BB5C45 5DE862D262E063196E20865A8A318DDD92F86F0179A69B5A4EA84EAB4EAC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 36 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F9B4FA050D151477AF6517151F653545321537F53EB55AC58835CE15F37 5F4A602F6050606D631F65596A4B6CC172C272ED77EF80F881058208854E90F7 93E197FF99579A5A4EF051DD5C2D6681696D5C4066F26975738968507C8150C5 52E457475DFE932665A46B236B3D7434798179BD7B4B7DCA82B983CC887F895F 8B398FD191D1541F92804E5D503653E5533A72D7739677E982E68EAF99C699C8 99D25177611A865E55B07A7A50765BD3904796854E326ADB91E75C515C480000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 37 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000063987A9F6C9397748F617AAA718A96887C8268177E706851936C52F2541B 85AB8A137FA48ECD90E15366888879414FC250BE521151445553572D73EA578B 59515F625F8460756176616761A963B2643A656C666F68426E1375667A3D7CFB 7D4C7D997E4B7F6B830E834A86CD8A088A638B668EFD981A9D8F82B88FCE9BE8 5287621F64836FC09699684150916B206C7A6F547A747D5088408A2367084EF6 503950265065517C5238526355A7570F58055ACC5EFA61B261F862F363720000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 38 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000691C6A29727D72AC732E7814786F7D79770C80A9898B8B198CE28ED29063 9375967A98559A139E785143539F53B35E7B5F266E1B6E90738473FE7D438237 8A008AFA96504E4E500B53E4547C56FA59D15B645DF15EAB5F276238654567AF 6E5672D07CCA88B480A180E183F0864E8A878DE8923796C798679F134E944E92 4F0D53485449543E5A2F5F8C5FA1609F68A76A8E745A78818A9E8AA48B779190 4E5E9BC94EA44F7C4FAF501950165149516C529F52B952FE539A53E354110000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 39 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000540E5589575157A2597D5B545B5D5B8F5DE55DE75DF75E785E835E9A5EB7 5F186052614C629762D863A7653B6602664366F4676D6821689769CB6C5F6D2A 6D696E2F6E9D75327687786C7A3F7CE07D057D187D5E7DB18015800380AF80B1 8154818F822A8352884C88618B1B8CA28CFC90CA91759271783F92FC95A4964D 980599999AD89D3B525B52AB53F7540858D562F76FE08C6A8F5F9EB9514B523B 544A56FD7A4091779D609ED273446F09817075115FFD60DA9AA872DB8FBC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006B6498034ECA56F0576458BE5A5A606861C7660F6606683968B16DF775D5 7D3A826E9B424E9B4F5053C955065D6F5DE65DEE67FB6C99747378028A509396 88DF57505EA7632B50B550AC518D670054C9585E59BB5BB05F69624D63A1683D 6B736E08707D91C7728078157826796D658E7D3083DC88C18F09969B52645728 67507F6A8CA151B45742962A583A698A80B454B25D0E57FC78959DFA4F5C524A 548B643E6628671467F57A847B567D22932F685C9BAD7B395319518A52370000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005BDF62F664AE64E6672D6BBA85A996D176909BD6634C93069BAB76BF6652 4E09509853C25C7160E864926563685F71E673CA75237B977E8286958B838CDB 9178991065AC66AB6B8B4ED54ED44F3A4F7F523A53F853F255E356DB58EB59CB 59C959FF5B505C4D5E025E2B5FD7601D6307652F5B5C65AF65BD65E8679D6B62 6B7B6C0F7345794979C17CF87D197D2B80A2810281F389968A5E8A698A668A8C 8AEE8CC78CDC96CC98FC6B6F4E8B4F3C4F8D51505B575BFA6148630166420000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006B216ECB6CBB723E74BD75D478C1793A800C803381EA84948F9E6C509E7F 5F0F8B589D2B7AFA8EF85B8D96EB4E0353F157F759315AC95BA460896E7F6F06 75BE8CEA5B9F85007BE0507267F4829D5C61854A7E1E820E51995C0463688D66 659C716E793E7D1780058B1D8ECA906E86C790AA501F52FA5C3A6753707C7235 914C91C8932B82E55BC25F3160F94E3B53D65B88624B67316B8A72E973E07A2E 816B8DA391529996511253D7546A5BFF63886A397DAC970056DA53CE54680000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005B975C315DDE4FEE610162FE6D3279C079CB7D427E4D7FD281ED821F8490 884689728B908E748F2F9031914B916C96C6919C4EC04F4F514553415F93620E 67D46C416E0B73637E2691CD928353D459195BBF6DD1795D7E2E7C9B587E719F 51FA88538FF04FCA5CFB662577AC7AE3821C99FF51C65FAA65EC696F6B896DF3 6E966F6476FE7D145DE190759187980651E6521D6240669166D96E1A5EB67DD2 7F7266F885AF85F78AF852A953D959735E8F5F90605592E4966450B7511F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000052DD5320534753EC54E8554655315617596859BE5A3C5BB55C065C0F5C11 5C1A5E845E8A5EE05F70627F628462DB638C63776607660C662D6676677E68A2 6A1F6A356CBC6D886E096E58713C7126716775C77701785D7901796579F07AE0 7B117CA77D39809683D6848B8549885D88F38A1F8A3C8A548A738C618CDE91A4 9266937E9418969C97984E0A4E084E1E4E575197527057CE583458CC5B225E38 60C564FE676167566D4472B675737A6384B88B7291B89320563157F498FE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000062ED690D6B9671ED7E548077827289E698DF87558FB15C3B4F384FE14FB5 55075A205BDD5BE95FC3614E632F65B0664B68EE699B6D786DF1753375B9771F 795E79E67D3381E382AF85AA89AA8A3A8EAB8F9B903291DD97074EBA4EC15203 587558EC5C0B751A5C3D814E8A0A8FC59663976D7B258ACF9808916256F353A8 9017543957825E2563A86C34708A77617C8B7FE088709042915493109318968F 745E9AC45D075D69657067A28DA896DB636E6749691983C5981796C088FE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 40 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006F84647A5BF84E16702C755D662F51C4523652E259D35F8160276210653F 6574661F667468F268166B636E057272751F76DB7CBE805658F088FD897F8AA0 8A938ACB901D91929752975965897A0E810696BB5E2D60DC621A65A566146790 77F37A4D7C4D7E3E810A8CAC8D648DE18E5F78A9520762D963A5644262988A2D 7A837BC08AAC96EA7D76820C87494ED95148534353605BA35C025C165DDD6226 624764B0681368346CC96D456D1767D36F5C714E717D65CB7A7F7BAD7DDA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 41 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007E4A7FA8817A821B823985A68A6E8CCE8DF59078907792AD929195839BAE 524D55846F387136516879857E5581B37CCE564C58515CA863AA66FE66FD695A 72D9758F758E790E795679DF7C977D207D4486078A34963B90619F2050E75275 53CC53E2500955AA58EE594F723D5B8B5C64531D60E360F3635C6383633F63BB 64CD65E966F95DE369CD69FD6F1571E54E8975E976F87A937CDF7DCF7D9C8061 83498358846C84BC85FB88C58D709001906D9397971C9A1250CF5897618E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 42 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000081D385358D0890204FC3507452475373606F6349675F6E2C8DB3901F4FD7 5C5E8CCA65CF7D9A53528896517663C35B585B6B5C0A640D6751905C4ED6591A 592A6C708A51553E581559A560F0625367C182356955964099C49A284F535806 5BFE80105CB15E2F5F856020614B623466FF6CF06EDE80CE817F82D4888B8CB8 9000902E968A9EDB9BDB4EE353F059277B2C918D984C9DF96EDD702753535544 5B856258629E62D36CA26FEF74228A1794386FC18AFE833851E786F853EA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 43 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000053E94F4690548FB0596A81315DFD7AEA8FBF68DA8C3772F89C486A3D8AB0 4E3953585606576662C563A265E66B4E6DE16E5B70AD77ED7AEF7BAA7DBB803D 80C686CB8A95935B56E358C75F3E65AD66966A806BB575378AC7502477E55730 5F1B6065667A6C6075F47A1A7F6E81F48718904599B37BC9755C7AF97B5184C4 901079E97A9283365AE177404E2D4EF25B995FE062BD663C67F16CE8866B8877 8A3B914E92F399D06A177026732A82E784578CAF4E01514651CB558B5BF50000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 44 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005E165E335E815F145F355F6B5FB461F2631166A2671D6F6E7252753A773A 80748139817887768ABF8ADC8D858DF3929A957798029CE552C5635776F46715 6C8873CD8CC393AE96736D25589C690E69CC8FFD939A75DB901A585A680263B4 69FB4F436F2C67D88FBB85267DB49354693F6F70576A58F75B2C7D2C722A540A 91E39DB44EAD4F4E505C507552438C9E544858245B9A5E1D5E955EAD5EF75F1F 608C62B5633A63D068AF6C407887798E7A0B7DE082478A028AE68E4490130000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 45 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000090B8912D91D89F0E6CE5645864E265756EF476847B1B906993D16EBA54F2 5FB964A48F4D8FED92445178586B59295C555E976DFB7E8F751C8CBC8EE2985B 70B94F1D6BBF6FB1753096FB514E54105835585759AC5C605F926597675C6E21 767B83DF8CED901490FD934D7825783A52AA5EA6571F597460125012515A51AC 51CD520055105854585859575B955CF65D8B60BC6295642D6771684368BC68DF 76D76DD86E6F6D9B706F71C85F5375D879777B497B547B527CD67D7152300000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 46 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008463856985E48A0E8B048C468E0F9003900F94199676982D9A3095D850CD 52D5540C58025C0E61A7649E6D1E77B37AE580F48404905392855CE09D07533F 5F975FB36D9C7279776379BF7BE46BD272EC8AAD68036A6151F87A8169345C4A 9CF682EB5BC59149701E56785C6F60C765666C8C8C5A90419813545166C7920D 594890A351854E4D51EA85998B0E7058637A934B696299B47E04757753576960 8EDF96E36C5D4E8C5C3C5F108FE953028CD1808986795EFF65E54E7351650000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 47 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000059825C3F97EE4EFB598A5FCD8A8D6FE179B079625BE78471732B71B15E74 5FF5637B649A71C37C984E435EFC4E4B57DC56A260A96FC37D0D80FD813381BF 8FB2899786A45DF4628A64AD898767776CE26D3E743678345A467F7582AD99AC 4FF35EC362DD63926557676F76C3724C80CC80BA8F29914D500D57F95A926885 6973716472FD8CB758F28CE0966A9019877F79E477E784294F2F5265535A62CD 67CF6CCA767D7B947C95823685848FEB66DD6F2072067E1B83AB99C19EA60000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000051FD7BB178727BB880877B486AE85E61808C75517560516B92626E8C767A 91979AEA4F107F70629C7B4F95A59CE9567A585986E496BC4F345224534A53CD 53DB5E06642C6591677F6C3E6C4E724872AF73ED75547E41822C85E98CA97BC4 91C67169981298EF633D6669756A76E478D0854386EE532A5351542659835E87 5F7C60B26249627962AB65906BD46CCC75B276AE789179D87DCB7F7780A588AB 8AB98CBB907F975E98DB6A0B7C3850995C3E5FAE67876BD8743577097F8E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 49 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009F3B67CA7A175339758B9AED5F66819D83F180985F3C5FC575627B46903C 686759EB5A9B7D10767E8B2C4FF55F6A6A196C376F0274E2796888688A558C79 5EDF63CF75C579D282D7932892F2849C86ED9C2D54C15F6C658C6D5C70158CA7 8CD3983B654F74F64E0D4ED857E0592B5A665BCC51A85E035E9C601662766577 65A7666E6D6E72367B268150819A82998B5C8CA08CE68D74961C96444FAE64AB 6B66821E8461856A90E85C01695398A8847A85574F0F526F5FA95E45670D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000798F8179890789866DF55F1762556CB84ECF72699B925206543B567458B3 61A4626E711A596E7C897CDE7D1B96F06587805E4E194F75517558405E635E73 5F0A67C44E26853D9589965B7C73980150FB58C1765678A7522577A585117B86 504F590972477BC77DE88FBA8FD4904D4FBF52C95A295F0197AD4FDD821792EA 570363556B69752B88DC8F147A4252DF58936155620A66AE6BCD7C3F83E95023 4FF853055446583159495B9D5CF05CEF5D295E9662B16367653E65B9670B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006CD56CE170F978327E2B80DE82B3840C84EC870289128A2A8C4A90A692D2 98FD9CF39D6C4E4F4EA1508D5256574A59A85E3D5FD85FD9623F66B4671B67D0 68D251927D2180AA81A88B008C8C8CBF927E96325420982C531750D5535C58A8 64B26734726777667A4691E652C36CA16B8658005E4C5954672C7FFB51E176C6 646978E89B549EBB57CB59B96627679A6BCE54E969D95E55819C67959BAA67FE 9C52685D4EA64FE353C862B9672B6CAB8FC44FAD7E6D9EBF4E0761626E800000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006F2B85135473672A9B455DF37B955CAC5BC6871C6E4A84D17A1481085999 7C8D6C11772052D959227121725F77DB97279D61690B5A7F5A1851A5540D547D 660E76DF8FF792989CF459EA725D6EC5514D68C97DBF7DEC97629EBA64786A21 830259845B5F6BDB731B76F27DB280178499513267289ED976EE676252FF9905 5C24623B7C7E8CB0554F60B67D0B958053014E5F51B6591C723A803691CE5F25 77E253845F797D0485AC8A338E8D975667F385AE9453610961086CB976520000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008AED8F38552F4F51512A52C753CB5BA55E7D60A0618263D6670967DA6E67 6D8C733673377531795088D58A98904A909190F596C4878D59154E884F594E0E 8A898F3F981050AD5E7C59965BB95EB863DA63FA64C166DC694A69D86D0B6EB6 719475287AAF7F8A8000844984C989818B218E0A9065967D990A617E62916B32 6C836D747FCC7FFC6DC07F8587BA88F8676583B1983C96F76D1B7D61843D916A 4E7153755D506B046FEB85CD862D89A75229540F5C65674E68A8740674830000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075E288CF88E191CC96E296785F8B73877ACB844E63A0756552896D416E9C 74097559786B7C9296867ADC9F8D4FB6616E65C5865C4E864EAE50DA4E2151CC 5BEE659968816DBC731F764277AD7A1C7CE7826F8AD2907C91CF96759818529B 7DD1502B539867976DCB71D0743381E88F2A96A39C579E9F746058416D997D2F 985E4EE44F364F8B51B752B15DBA601C73B2793C82D3923496B796F6970A9E97 9F6266A66B74521752A370C888C25EC9604B61906F2371497C3E7DF4806F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000084EE9023932C54429B6F6AD370898CC28DEF973252B45A415ECA5F046717 697C69946D6A6F0F726272FC7BED8001807E874B90CE516D9E937984808B9332 8AD6502D548C8A716B6A8CC4810760D167A09DF24E994E989C108A6B85C18568 69006E7E78978155000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 50 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F0C4E104E154E2A4E314E364E3C4E3F4E424E564E584E824E858C6B4E8A 82125F0D4E8E4E9E4E9F4EA04EA24EB04EB34EB64ECE4ECD4EC44EC64EC24ED7 4EDE4EED4EDF4EF74F094F5A4F304F5B4F5D4F574F474F764F884F8F4F984F7B 4F694F704F914F6F4F864F9651184FD44FDF4FCE4FD84FDB4FD14FDA4FD04FE4 4FE5501A50285014502A502550054F1C4FF650215029502C4FFE4FEF50115006 504350476703505550505048505A5056506C50785080509A508550B450B20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 51 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000050C950CA50B350C250D650DE50E550ED50E350EE50F950F5510951015102 511651155114511A5121513A5137513C513B513F51405152514C515451627AF8 5169516A516E5180518256D8518C5189518F519151935195519651A451A651A2 51A951AA51AB51B351B151B251B051B551BD51C551C951DB51E0865551E951ED 51F051F551FE5204520B5214520E5227522A522E52335239524F5244524B524C 525E5254526A527452695273527F527D528D529452925271528852918FA80000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 52 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008FA752AC52AD52BC52B552C152CD52D752DE52E352E698ED52E052F352F5 52F852F9530653087538530D5310530F5315531A5323532F5331533353385340 534653454E175349534D51D6535E5369536E5918537B53775382539653A053A6 53A553AE53B053B653C37C1296D953DF66FC71EE53EE53E853ED53FA5401543D 5440542C542D543C542E54365429541D544E548F5475548E545F547154775470 5492547B5480547654845490548654C754A254B854A554AC54C454C854A80000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 53 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000054AB54C254A454BE54BC54D854E554E6550F551454FD54EE54ED54FA54E2 553955405563554C552E555C55455556555755385533555D5599558054AF558A 559F557B557E5598559E55AE557C558355A9558755A855DA55C555DF55C455DC 55E455D4561455F7561655FE55FD561B55F9564E565071DF5634563656325638 566B5664562F566C566A56865680568A56A05694568F56A556AE56B656B456C2 56BC56C156C356C056C856CE56D156D356D756EE56F9570056FF570457090000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005708570B570D57135718571655C7571C572657375738574E573B5740574F 576957C057885761577F5789579357A057B357A457AA57B057C357C657D457D2 57D3580A57D657E3580B5819581D587258215862584B58706BC05852583D5879 588558B9589F58AB58BA58DE58BB58B858AE58C558D358D158D758D958D858E5 58DC58E458DF58EF58FA58F958FB58FC58FD5902590A5910591B68A65925592C 592D59325938593E7AD259555950594E595A5958596259605967596C59690000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 55 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000059785981599D4F5E4FAB59A359B259C659E859DC598D59D959DA5A255A1F 5A115A1C5A095A1A5A405A6C5A495A355A365A625A6A5A9A5ABC5ABE5ACB5AC2 5ABD5AE35AD75AE65AE95AD65AFA5AFB5B0C5B0B5B165B325AD05B2A5B365B3E 5B435B455B405B515B555B5A5B5B5B655B695B705B735B755B7865885B7A5B80 5B835BA65BB85BC35BC75BC95BD45BD05BE45BE65BE25BDE5BE55BEB5BF05BF6 5BF35C055C075C085C0D5C135C205C225C285C385C395C415C465C4E5C530000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 56 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C505C4F5B715C6C5C6E4E625C765C795C8C5C915C94599B5CAB5CBB5CB6 5CBC5CB75CC55CBE5CC75CD95CE95CFD5CFA5CED5D8C5CEA5D0B5D155D175D5C 5D1F5D1B5D115D145D225D1A5D195D185D4C5D525D4E5D4B5D6C5D735D765D87 5D845D825DA25D9D5DAC5DAE5DBD5D905DB75DBC5DC95DCD5DD35DD25DD65DDB 5DEB5DF25DF55E0B5E1A5E195E115E1B5E365E375E445E435E405E4E5E575E54 5E5F5E625E645E475E755E765E7A9EBC5E7F5EA05EC15EC25EC85ED05ECF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 57 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005ED65EE35EDD5EDA5EDB5EE25EE15EE85EE95EEC5EF15EF35EF05EF45EF8 5EFE5F035F095F5D5F5C5F0B5F115F165F295F2D5F385F415F485F4C5F4E5F2F 5F515F565F575F595F615F6D5F735F775F835F825F7F5F8A5F885F915F875F9E 5F995F985FA05FA85FAD5FBC5FD65FFB5FE45FF85FF15FDD60B35FFF60216060 601960106029600E6031601B6015602B6026600F603A605A6041606A6077605F 604A6046604D6063604360646042606C606B60596081608D60E76083609A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 58 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006084609B60966097609260A7608B60E160B860E060D360B45FF060BD60C6 60B560D8614D6115610660F660F7610060F460FA6103612160FB60F1610D610E 6147613E61286127614A613F613C612C6134613D614261446173617761586159 615A616B6174616F61656171615F615D6153617561996196618761AC6194619A 618A619161AB61AE61CC61CA61C961F761C861C361C661BA61CB7F7961CD61E6 61E361F661FA61F461FF61FD61FC61FE620062086209620D620C6214621B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 59 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000621E6221622A622E6230623262336241624E625E6263625B62606268627C 62826289627E62926293629662D46283629462D762D162BB62CF62FF62C664D4 62C862DC62CC62CA62C262C7629B62C9630C62EE62F163276302630862EF62F5 6350633E634D641C634F6396638E638063AB637663A3638F6389639F63B5636B 636963BE63E963C063C663E363C963D263F663C4641664346406641364266436 651D64176428640F6467646F6476644E652A6495649364A564A9648864BC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000064DA64D264C564C764BB64D864C264F164E7820964E064E162AC64E364EF 652C64F664F464F264FA650064FD6518651C650565246523652B653465356537 65366538754B654865566555654D6558655E655D65726578658265838B8A659B 659F65AB65B765C365C665C165C465CC65D265DB65D965E065E165F16772660A 660365FB6773663566366634661C664F664466496641665E665D666466676668 665F6662667066836688668E668966846698669D66C166B966C966BE66BC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000066C466B866D666DA66E0663F66E666E966F066F566F7670F6716671E6726 67279738672E673F67366741673867376746675E676067596763676467896770 67A9677C676A678C678B67A667A1678567B767EF67B467EC67B367E967B867E4 67DE67DD67E267EE67B967CE67C667E76A9C681E684668296840684D6832684E 68B3682B685968636877687F689F688F68AD6894689D689B68836AAE68B96874 68B568A068BA690F688D687E690168CA690868D86922692668E1690C68CD0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000068D468E768D569366912690468D768E3692568F968E068EF6928692A691A 6923692168C669796977695C6978696B6954697E696E69396974693D69596930 6961695E695D6981696A69B269AE69D069BF69C169D369BE69CE5BE869CA69DD 69BB69C369A76A2E699169A0699C699569B469DE69E86A026A1B69FF6B0A69F9 69F269E76A0569B16A1E69ED6A1469EB6A0A6A126AC16A236A136A446A0C6A72 6A366A786A476A626A596A666A486A386A226A906A8D6AA06A846AA26AA30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006A9786176ABB6AC36AC26AB86AB36AAC6ADE6AD16ADF6AAA6ADA6AEA6AFB 6B0586166AFA6B126B169B316B1F6B386B3776DC6B3998EE6B476B436B496B50 6B596B546B5B6B5F6B616B786B796B7F6B806B846B836B8D6B986B956B9E6BA4 6BAA6BAB6BAF6BB26BB16BB36BB76BBC6BC66BCB6BD36BDF6BEC6BEB6BF36BEF 9EBE6C086C136C146C1B6C246C236C5E6C556C626C6A6C826C8D6C9A6C816C9B 6C7E6C686C736C926C906CC46CF16CD36CBD6CD76CC56CDD6CAE6CB16CBE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006CBA6CDB6CEF6CD96CEA6D1F884D6D366D2B6D3D6D386D196D356D336D12 6D0C6D636D936D646D5A6D796D596D8E6D956FE46D856DF96E156E0A6DB56DC7 6DE66DB86DC66DEC6DDE6DCC6DE86DD26DC56DFA6DD96DE46DD56DEA6DEE6E2D 6E6E6E2E6E196E726E5F6E3E6E236E6B6E2B6E766E4D6E1F6E436E3A6E4E6E24 6EFF6E1D6E386E826EAA6E986EC96EB76ED36EBD6EAF6EC46EB26ED46ED56E8F 6EA56EC26E9F6F416F11704C6EEC6EF86EFE6F3F6EF26F316EEF6F326ECC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006F3E6F136EF76F866F7A6F786F816F806F6F6F5B6FF36F6D6F826F7C6F58 6F8E6F916FC26F666FB36FA36FA16FA46FB96FC66FAA6FDF6FD56FEC6FD46FD8 6FF16FEE6FDB7009700B6FFA70117001700F6FFE701B701A6F74701D7018701F 7030703E7032705170637099709270AF70F170AC70B870B370AE70DF70CB70DD 70D9710970FD711C711971657155718871667162714C7156716C718F71FB7184 719571A871AC71D771B971BE71D271C971D471CE71E071EC71E771F571FC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 60 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000071F971FF720D7210721B7228722D722C72307232723B723C723F72407246 724B72587274727E7282728172877292729672A272A772B972B272C372C672C4 72CE72D272E272E072E172F972F7500F7317730A731C7316731D7334732F7329 7325733E734E734F9ED87357736A7368737073787375737B737A73C873B373CE 73BB73C073E573EE73DE74A27405746F742573F87432743A7455743F745F7459 7441745C746974707463746A7476747E748B749E74A774CA74CF74D473F10000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 61 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000074E074E374E774E974EE74F274F074F174F874F7750475037505750C750E 750D75157513751E7526752C753C7544754D754A7549755B7546755A75697564 7567756B756D75787576758675877574758A758975827594759A759D75A575A3 75C275B375C375B575BD75B875BC75B175CD75CA75D275D975E375DE75FE75FF 75FC760175F075FA75F275F3760B760D7609761F762776207621762276247634 7630763B764776487646765C76587661766276687669766A7667766C76700000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 62 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000767276767678767C768076837688768B768E769676937699769A76B076B4 76B876B976BA76C276CD76D676D276DE76E176E576E776EA862F76FB77087707 770477297724771E77257726771B773777387747775A7768776B775B7765777F 777E7779778E778B779177A0779E77B077B677B977BF77BC77BD77BB77C777CD 77D777DA77DC77E377EE77FC780C781279267820792A7845788E78747886787C 789A788C78A378B578AA78AF78D178C678CB78D478BE78BC78C578CA78EC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 63 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000078E778DA78FD78F47907791279117919792C792B794079607957795F795A 79557953797A797F798A799D79A79F4B79AA79AE79B379B979BA79C979D579E7 79EC79E179E37A087A0D7A187A197A207A1F79807A317A3B7A3E7A377A437A57 7A497A617A627A699F9D7A707A797A7D7A887A977A957A987A967AA97AC87AB0 7AB67AC57AC47ABF90837AC77ACA7ACD7ACF7AD57AD37AD97ADA7ADD7AE17AE2 7AE67AED7AF07B027B0F7B0A7B067B337B187B197B1E7B357B287B367B500000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 64 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007B7A7B047B4D7B0B7B4C7B457B757B657B747B677B707B717B6C7B6E7B9D 7B987B9F7B8D7B9C7B9A7B8B7B927B8F7B5D7B997BCB7BC17BCC7BCF7BB47BC6 7BDD7BE97C117C147BE67BE57C607C007C077C137BF37BF77C177C0D7BF67C23 7C277C2A7C1F7C377C2B7C3D7C4C7C437C547C4F7C407C507C587C5F7C647C56 7C657C6C7C757C837C907CA47CAD7CA27CAB7CA17CA87CB37CB27CB17CAE7CB9 7CBD7CC07CC57CC27CD87CD27CDC7CE29B3B7CEF7CF27CF47CF67CFA7D060000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 65 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007D027D1C7D157D0A7D457D4B7D2E7D327D3F7D357D467D737D567D4E7D72 7D687D6E7D4F7D637D937D897D5B7D8F7D7D7D9B7DBA7DAE7DA37DB57DC77DBD 7DAB7E3D7DA27DAF7DDC7DB87D9F7DB07DD87DDD7DE47DDE7DFB7DF27DE17E05 7E0A7E237E217E127E317E1F7E097E0B7E227E467E667E3B7E357E397E437E37 7E327E3A7E677E5D7E567E5E7E597E5A7E797E6A7E697E7C7E7B7E837DD57E7D 8FAE7E7F7E887E897E8C7E927E907E937E947E967E8E7E9B7E9C7F387F3A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 66 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007F457F4C7F4D7F4E7F507F517F557F547F587F5F7F607F687F697F677F78 7F827F867F837F887F877F8C7F947F9E7F9D7F9A7FA37FAF7FB27FB97FAE7FB6 7FB88B717FC57FC67FCA7FD57FD47FE17FE67FE97FF37FF998DC80068004800B 801280188019801C80218028803F803B804A804680528058805A805F80628068 80738072807080768079807D807F808480868085809B8093809A80AD519080AC 80DB80E580D980DD80C480DA80D6810980EF80F1811B81298123812F814B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 67 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000968B8146813E8153815180FC8171816E81658166817481838188818A8180 818281A0819581A481A3815F819381A981B081B581BE81B881BD81C081C281BA 81C981CD81D181D981D881C881DA81DF81E081E781FA81FB81FE820182028205 8207820A820D821082168229822B82388233824082598258825D825A825F8264 82628268826A826B822E827182778278827E828D829282AB829F82BB82AC82E1 82E382DF82D282F482F382FA8393830382FB82F982DE830682DC830982D90000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 68 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000833583348316833283318340833983508345832F832B831783188385839A 83AA839F83A283968323838E8387838A837C83B58373837583A0838983A883F4 841383EB83CE83FD840383D8840B83C183F7840783E083F2840D8422842083BD 8438850683FB846D842A843C855A84848477846B84AD846E848284698446842C 846F8479843584CA846284B984BF849F84D984CD84BB84DA84D084C184C684D6 84A1852184FF84F485178518852C851F8515851484FC85408563855885480000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 69 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000085418602854B8555858085A485888591858A85A8856D8594859B85EA8587 859C8577857E859085C985BA85CF85B985D085D585DD85E585DC85F9860A8613 860B85FE85FA86068622861A8630863F864D4E558654865F86678671869386A3 86A986AA868B868C86B686AF86C486C686B086C9882386AB86D486DE86E986EC 86DF86DB86EF8712870687088700870386FB87118709870D86F9870A8734873F 8737873B87258729871A8760875F8778874C874E877487578768876E87590000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000087538763876A880587A2879F878287AF87CB87BD87C087D096D687AB87C4 87B387C787C687BB87EF87F287E0880F880D87FE87F687F7880E87D288118816 8815882288218831883688398827883B8844884288528859885E8862886B8881 887E889E8875887D88B5887288828897889288AE889988A2888D88A488B088BF 88B188C388C488D488D888D988DD88F9890288FC88F488E888F28904890C890A 89138943891E8925892A892B89418944893B89368938894C891D8960895E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000089668964896D896A896F89748977897E89838988898A8993899889A189A9 89A689AC89AF89B289BA89BD89BF89C089DA89DC89DD89E789F489F88A038A16 8A108A0C8A1B8A1D8A258A368A418A5B8A528A468A488A7C8A6D8A6C8A628A85 8A828A848AA88AA18A918AA58AA68A9A8AA38AC48ACD8AC28ADA8AEB8AF38AE7 8AE48AF18B148AE08AE28AF78ADE8ADB8B0C8B078B1A8AE18B168B108B178B20 8B3397AB8B268B2B8B3E8B288B418B4C8B4F8B4E8B498B568B5B8B5A8B6B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008B5F8B6C8B6F8B748B7D8B808B8C8B8E8B928B938B968B998B9A8C3A8C41 8C3F8C488C4C8C4E8C508C558C628C6C8C788C7A8C828C898C858C8A8C8D8C8E 8C948C7C8C98621D8CAD8CAA8CBD8CB28CB38CAE8CB68CC88CC18CE48CE38CDA 8CFD8CFA8CFB8D048D058D0A8D078D0F8D0D8D109F4E8D138CCD8D148D168D67 8D6D8D718D738D818D998DC28DBE8DBA8DCF8DDA8DD68DCC8DDB8DCB8DEA8DEB 8DDF8DE38DFC8E088E098DFF8E1D8E1E8E108E1F8E428E358E308E348E4A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008E478E498E4C8E508E488E598E648E608E2A8E638E558E768E728E7C8E81 8E878E858E848E8B8E8A8E938E918E948E998EAA8EA18EAC8EB08EC68EB18EBE 8EC58EC88ECB8EDB8EE38EFC8EFB8EEB8EFE8F0A8F058F158F128F198F138F1C 8F1F8F1B8F0C8F268F338F3B8F398F458F428F3E8F4C8F498F468F4E8F578F5C 8F628F638F648F9C8F9F8FA38FAD8FAF8FB78FDA8FE58FE28FEA8FEF90878FF4 90058FF98FFA901190159021900D901E9016900B90279036903590398FF80000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000904F905090519052900E9049903E90569058905E9068906F907696A89072 9082907D90819080908A9089908F90A890AF90B190B590E290E4624890DB9102 9112911991329130914A9156915891639165916991739172918B9189918291A2 91AB91AF91AA91B591B491BA91C091C191C991CB91D091D691DF91E191DB91FC 91F591F6921E91FF9214922C92159211925E925792459249926492489295923F 924B9250929C92969293929B925A92CF92B992B792E9930F92FA9344932E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000093199322931A9323933A9335933B935C9360937C936E935693B093AC93AD 939493B993D693D793E893E593D893C393DD93D093C893E4941A941494139403 940794109436942B94359421943A944194529444945B94609462945E946A9229 947094759477947D945A947C947E9481947F95829587958A9594959695989599 95A095A895A795AD95BC95BB95B995BE95CA6FF695C395CD95CC95D595D495D6 95DC95E195E595E296219628962E962F9642964C964F964B9677965C965E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 70 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000965D965F96669672966C968D96989695969796AA96A796B196B296B096B4 96B696B896B996CE96CB96C996CD894D96DC970D96D596F99704970697089713 970E9711970F971697199724972A97309739973D973E97449746974897429749 975C976097649766976852D2976B977197799785977C9781977A9786978B978F 9790979C97A897A697A397B397B497C397C697C897CB97DC97ED9F4F97F27ADF 97F697F5980F980C9838982498219837983D9846984F984B986B986F98700000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 71 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000098719874987398AA98AF98B198B698C498C398C698E998EB990399099912 991499189921991D991E99249920992C992E993D993E9942994999459950994B 99519952994C99559997999899A599AD99AE99BC99DF99DB99DD99D899D199ED 99EE99F199F299FB99F89A019A0F9A0599E29A199A2B9A379A459A429A409A43 9A3E9A559A4D9A5B9A579A5F9A629A659A649A699A6B9A6A9AAD9AB09ABC9AC0 9ACF9AD19AD39AD49ADE9ADF9AE29AE39AE69AEF9AEB9AEE9AF49AF19AF70000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 72 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009AFB9B069B189B1A9B1F9B229B239B259B279B289B299B2A9B2E9B2F9B32 9B449B439B4F9B4D9B4E9B519B589B749B939B839B919B969B979B9F9BA09BA8 9BB49BC09BCA9BB99BC69BCF9BD19BD29BE39BE29BE49BD49BE19C3A9BF29BF1 9BF09C159C149C099C139C0C9C069C089C129C0A9C049C2E9C1B9C259C249C21 9C309C479C329C469C3E9C5A9C609C679C769C789CE79CEC9CF09D099D089CEB 9D039D069D2A9D269DAF9D239D1F9D449D159D129D419D3F9D3E9D469D480000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 73 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009D5D9D5E9D649D519D509D599D729D899D879DAB9D6F9D7A9D9A9DA49DA9 9DB29DC49DC19DBB9DB89DBA9DC69DCF9DC29DD99DD39DF89DE69DED9DEF9DFD 9E1A9E1B9E1E9E759E799E7D9E819E889E8B9E8C9E929E959E919E9D9EA59EA9 9EB89EAA9EAD97619ECC9ECE9ECF9ED09ED49EDC9EDE9EDD9EE09EE59EE89EEF 9EF49EF69EF79EF99EFB9EFC9EFD9F079F0876B79F159F219F2C9F3E9F4A9F52 9F549F639F5F9F609F619F669F679F6C9F6A9F779F729F769F959F9C9FA00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 74 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000582F69C79059746451DC7199000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 R 2141 301C FF5E 2142 2016 2225 215D 2212 FF0D 2171 00A2 FFE0 2172 00A3 FFE1 224C 00AC FFE2 tcl8.6.5/library/encoding/shiftjis.enc0000644000175000017500000012160611555560473017342 0ustar sergeisergei# Encoding file: shiftjis, multi-byte M 003F 0 40 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080000000000000000000850086008700000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 81 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 300030013002FF0CFF0E30FBFF1AFF1BFF1FFF01309B309C00B4FF4000A8FF3E FFE3FF3F30FD30FE309D309E30034EDD30053006300730FC20152010FF0FFF3C 301C2016FF5C2026202520182019201C201DFF08FF0930143015FF3BFF3DFF5B FF5D30083009300A300B300C300D300E300F30103011FF0B221200B100D70000 00F7FF1D2260FF1CFF1E22662267221E22342642264000B0203220332103FFE5 FF0400A200A3FF05FF03FF06FF0AFF2000A72606260525CB25CF25CE25C725C6 25A125A025B325B225BD25BC203B301221922190219121933013000000000000 000000000000000000000000000000002208220B2286228722822283222A2229 000000000000000000000000000000002227222800AC21D221D4220022030000 0000000000000000000000000000000000000000222022A52312220222072261 2252226A226B221A223D221D2235222B222C0000000000000000000000000000 212B2030266F266D266A2020202100B6000000000000000025EF000000000000 82 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000FF10 FF11FF12FF13FF14FF15FF16FF17FF18FF190000000000000000000000000000 FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2FFF30 FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3A000000000000000000000000 0000FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5A00000000000000003041 30423043304430453046304730483049304A304B304C304D304E304F30503051 30523053305430553056305730583059305A305B305C305D305E305F30603061 30623063306430653066306730683069306A306B306C306D306E306F30703071 30723073307430753076307730783079307A307B307C307D307E307F30803081 30823083308430853086308730883089308A308B308C308D308E308F30903091 3092309300000000000000000000000000000000000000000000000000000000 83 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 30A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF30B0 30B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF30C0 30C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF30D0 30D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF0000 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000391 03920393039403950396039703980399039A039B039C039D039E039F03A003A1 03A303A403A503A603A703A803A90000000000000000000000000000000003B1 03B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF03C003C1 03C303C403C503C603C703C803C9000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 84 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 04100411041204130414041504010416041704180419041A041B041C041D041E 041F0420042104220423042404250426042704280429042A042B042C042D042E 042F000000000000000000000000000000000000000000000000000000000000 04300431043204330434043504510436043704380439043A043B043C043D0000 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000002500 2502250C251025182514251C252C25242534253C25012503250F2513251B2517 25232533252B253B254B2520252F25282537253F251D25302525253825420000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 88 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000004E9C 55165A03963F54C0611B632859F690228475831C7A5060AA63E16E2565ED8466 82A69BF56893572765A162715B9B59D0867B98F47D627DBE9B8E62167C9F88B7 5B895EB563096697684895C7978D674F4EE54F0A4F4D4F9D504956F2593759D4 5A015C0960DF610F61706613690570BA754F757079FB7DAD7DEF80C3840E8863 8B029055907A533B4E954EA557DF80B290C178EF4E0058F16EA290387A328328 828B9C2F5141537054BD54E156E059FB5F1598F26DEB80E4852D000000000000 89 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9662967096A097FB540B53F35B8770CF7FBD8FC296E8536F9D5C7ABA4E117893 81FC6E26561855046B1D851A9C3B59E553A96D6674DC958F56424E91904B96F2 834F990C53E155B65B305F71662066F368046C386CF36D29745B76C87A4E9834 82F1885B8A6092ED6DB275AB76CA99C560A68B018D8A95B2698E53AD51860000 5712583059445BB45EF6602863A963F46CBF6F14708E7114715971D5733F7E01 827682D185979060925B9D1B586965BC6C5A752551F9592E59655F805FDC62BC 65FA6A2A6B276BB4738B7FC189569D2C9D0E9EC45CA16C96837B51045C4B61B6 81C6687672614E594FFA537860696E297A4F97F34E0B53164EEE4F554F3D4FA1 4F7352A053EF5609590F5AC15BB65BE179D16687679C67B66B4C6CB3706B73C2 798D79BE7A3C7B8782B182DB8304837783EF83D387668AB256298CA88FE6904E 971E868A4FC45CE862117259753B81E582BD86FE8CC096C5991399D54ECB4F1A 89E356DE584A58CA5EFB5FEB602A6094606261D0621262D06539000000000000 8A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9B41666668B06D777070754C76867D7582A587F9958B968E8C9D51F152BE5916 54B35BB35D16616869826DAF788D84CB88578A7293A79AB86D6C99A886D957A3 67FF86CE920E5283568754045ED362E164B9683C68386BBB737278BA7A6B899A 89D28D6B8F0390ED95A3969497695B665CB3697D984D984E639B7B206A2B0000 6A7F68B69C0D6F5F5272559D607062EC6D3B6E076ED1845B89108F444E149C39 53F6691B6A3A9784682A515C7AC384B291DC938C565B9D286822830584317CA5 520882C574E64E7E4F8351A05BD2520A52D852E75DFB559A582A59E65B8C5B98 5BDB5E725E7960A3611F616361BE63DB656267D1685368FA6B3E6B536C576F22 6F976F4574B0751876E3770B7AFF7BA17C217DE97F367FF0809D8266839E89B3 8ACC8CAB908494519593959195A2966597D3992882184E38542B5CB85DCC73A9 764C773C5CA97FEB8D0B96C19811985498584F014F0E5371559C566857FA5947 5B095BC45C905E0C5E7E5FCC63EE673A65D765E2671F68CB68C4000000000000 8B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A5F5E306BC56C176C7D757F79485B637A007D005FBD898F8A188CB48D778ECC 8F1D98E29A0E9B3C4E80507D510059935B9C622F628064EC6B3A72A075917947 7FA987FB8ABC8B7063AC83CA97A05409540355AB68546A588A70782767759ECD 53745BA2811A865090064E184E454EC74F1153CA54385BAE5F13602565510000 673D6C426C726CE3707874037A767AAE7B087D1A7CFE7D6665E7725B53BB5C45 5DE862D262E063196E20865A8A318DDD92F86F0179A69B5A4EA84EAB4EAC4F9B 4FA050D151477AF6517151F653545321537F53EB55AC58835CE15F375F4A602F 6050606D631F65596A4B6CC172C272ED77EF80F881058208854E90F793E197FF 99579A5A4EF051DD5C2D6681696D5C4066F26975738968507C8150C552E45747 5DFE932665A46B236B3D7434798179BD7B4B7DCA82B983CC887F895F8B398FD1 91D1541F92804E5D503653E5533A72D7739677E982E68EAF99C699C899D25177 611A865E55B07A7A50765BD3904796854E326ADB91E75C515C48000000000000 8C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 63987A9F6C9397748F617AAA718A96887C8268177E706851936C52F2541B85AB 8A137FA48ECD90E15366888879414FC250BE521151445553572D73EA578B5951 5F625F8460756176616761A963B2643A656C666F68426E1375667A3D7CFB7D4C 7D997E4B7F6B830E834A86CD8A088A638B668EFD981A9D8F82B88FCE9BE80000 5287621F64836FC09699684150916B206C7A6F547A747D5088408A2367084EF6 503950265065517C5238526355A7570F58055ACC5EFA61B261F862F36372691C 6A29727D72AC732E7814786F7D79770C80A9898B8B198CE28ED290639375967A 98559A139E785143539F53B35E7B5F266E1B6E90738473FE7D4382378A008AFA 96504E4E500B53E4547C56FA59D15B645DF15EAB5F276238654567AF6E5672D0 7CCA88B480A180E183F0864E8A878DE8923796C798679F134E944E924F0D5348 5449543E5A2F5F8C5FA1609F68A76A8E745A78818A9E8AA48B7791904E5E9BC9 4EA44F7C4FAF501950165149516C529F52B952FE539A53E35411000000000000 8D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 540E5589575157A2597D5B545B5D5B8F5DE55DE75DF75E785E835E9A5EB75F18 6052614C629762D863A7653B6602664366F4676D6821689769CB6C5F6D2A6D69 6E2F6E9D75327687786C7A3F7CE07D057D187D5E7DB18015800380AF80B18154 818F822A8352884C88618B1B8CA28CFC90CA91759271783F92FC95A4964D0000 980599999AD89D3B525B52AB53F7540858D562F76FE08C6A8F5F9EB9514B523B 544A56FD7A4091779D609ED273446F09817075115FFD60DA9AA872DB8FBC6B64 98034ECA56F0576458BE5A5A606861C7660F6606683968B16DF775D57D3A826E 9B424E9B4F5053C955065D6F5DE65DEE67FB6C99747378028A50939688DF5750 5EA7632B50B550AC518D670054C9585E59BB5BB05F69624D63A1683D6B736E08 707D91C7728078157826796D658E7D3083DC88C18F09969B5264572867507F6A 8CA151B45742962A583A698A80B454B25D0E57FC78959DFA4F5C524A548B643E 6628671467F57A847B567D22932F685C9BAD7B395319518A5237000000000000 8E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5BDF62F664AE64E6672D6BBA85A996D176909BD6634C93069BAB76BF66524E09 509853C25C7160E864926563685F71E673CA75237B977E8286958B838CDB9178 991065AC66AB6B8B4ED54ED44F3A4F7F523A53F853F255E356DB58EB59CB59C9 59FF5B505C4D5E025E2B5FD7601D6307652F5B5C65AF65BD65E8679D6B620000 6B7B6C0F7345794979C17CF87D197D2B80A2810281F389968A5E8A698A668A8C 8AEE8CC78CDC96CC98FC6B6F4E8B4F3C4F8D51505B575BFA6148630166426B21 6ECB6CBB723E74BD75D478C1793A800C803381EA84948F9E6C509E7F5F0F8B58 9D2B7AFA8EF85B8D96EB4E0353F157F759315AC95BA460896E7F6F0675BE8CEA 5B9F85007BE0507267F4829D5C61854A7E1E820E51995C0463688D66659C716E 793E7D1780058B1D8ECA906E86C790AA501F52FA5C3A6753707C7235914C91C8 932B82E55BC25F3160F94E3B53D65B88624B67316B8A72E973E07A2E816B8DA3 91529996511253D7546A5BFF63886A397DAC970056DA53CE5468000000000000 8F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5B975C315DDE4FEE610162FE6D3279C079CB7D427E4D7FD281ED821F84908846 89728B908E748F2F9031914B916C96C6919C4EC04F4F514553415F93620E67D4 6C416E0B73637E2691CD928353D459195BBF6DD1795D7E2E7C9B587E719F51FA 88538FF04FCA5CFB662577AC7AE3821C99FF51C65FAA65EC696F6B896DF30000 6E966F6476FE7D145DE190759187980651E6521D6240669166D96E1A5EB67DD2 7F7266F885AF85F78AF852A953D959735E8F5F90605592E4966450B7511F52DD 5320534753EC54E8554655315617596859BE5A3C5BB55C065C0F5C115C1A5E84 5E8A5EE05F70627F628462DB638C63776607660C662D6676677E68A26A1F6A35 6CBC6D886E096E58713C7126716775C77701785D7901796579F07AE07B117CA7 7D39809683D6848B8549885D88F38A1F8A3C8A548A738C618CDE91A49266937E 9418969C97984E0A4E084E1E4E575197527057CE583458CC5B225E3860C564FE 676167566D4472B675737A6384B88B7291B89320563157F498FE000000000000 90 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 62ED690D6B9671ED7E548077827289E698DF87558FB15C3B4F384FE14FB55507 5A205BDD5BE95FC3614E632F65B0664B68EE699B6D786DF1753375B9771F795E 79E67D3381E382AF85AA89AA8A3A8EAB8F9B903291DD97074EBA4EC152035875 58EC5C0B751A5C3D814E8A0A8FC59663976D7B258ACF9808916256F353A80000 9017543957825E2563A86C34708A77617C8B7FE088709042915493109318968F 745E9AC45D075D69657067A28DA896DB636E6749691983C5981796C088FE6F84 647A5BF84E16702C755D662F51C4523652E259D35F8160276210653F6574661F 667468F268166B636E057272751F76DB7CBE805658F088FD897F8AA08A938ACB 901D91929752975965897A0E810696BB5E2D60DC621A65A56614679077F37A4D 7C4D7E3E810A8CAC8D648DE18E5F78A9520762D963A5644262988A2D7A837BC0 8AAC96EA7D76820C87494ED95148534353605BA35C025C165DDD6226624764B0 681368346CC96D456D1767D36F5C714E717D65CB7A7F7BAD7DDA000000000000 91 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7E4A7FA8817A821B823985A68A6E8CCE8DF59078907792AD929195839BAE524D 55846F387136516879857E5581B37CCE564C58515CA863AA66FE66FD695A72D9 758F758E790E795679DF7C977D207D4486078A34963B90619F2050E7527553CC 53E2500955AA58EE594F723D5B8B5C64531D60E360F3635C6383633F63BB0000 64CD65E966F95DE369CD69FD6F1571E54E8975E976F87A937CDF7DCF7D9C8061 83498358846C84BC85FB88C58D709001906D9397971C9A1250CF5897618E81D3 85358D0890204FC3507452475373606F6349675F6E2C8DB3901F4FD75C5E8CCA 65CF7D9A53528896517663C35B585B6B5C0A640D6751905C4ED6591A592A6C70 8A51553E581559A560F0625367C182356955964099C49A284F5358065BFE8010 5CB15E2F5F856020614B623466FF6CF06EDE80CE817F82D4888B8CB89000902E 968A9EDB9BDB4EE353F059277B2C918D984C9DF96EDD7027535355445B856258 629E62D36CA26FEF74228A1794386FC18AFE833851E786F853EA000000000000 92 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 53E94F4690548FB0596A81315DFD7AEA8FBF68DA8C3772F89C486A3D8AB04E39 53585606576662C563A265E66B4E6DE16E5B70AD77ED7AEF7BAA7DBB803D80C6 86CB8A95935B56E358C75F3E65AD66966A806BB575378AC7502477E557305F1B 6065667A6C6075F47A1A7F6E81F48718904599B37BC9755C7AF97B5184C40000 901079E97A9283365AE177404E2D4EF25B995FE062BD663C67F16CE8866B8877 8A3B914E92F399D06A177026732A82E784578CAF4E01514651CB558B5BF55E16 5E335E815F145F355F6B5FB461F2631166A2671D6F6E7252753A773A80748139 817887768ABF8ADC8D858DF3929A957798029CE552C5635776F467156C8873CD 8CC393AE96736D25589C690E69CC8FFD939A75DB901A585A680263B469FB4F43 6F2C67D88FBB85267DB49354693F6F70576A58F75B2C7D2C722A540A91E39DB4 4EAD4F4E505C507552438C9E544858245B9A5E1D5E955EAD5EF75F1F608C62B5 633A63D068AF6C407887798E7A0B7DE082478A028AE68E449013000000000000 93 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 90B8912D91D89F0E6CE5645864E265756EF476847B1B906993D16EBA54F25FB9 64A48F4D8FED92445178586B59295C555E976DFB7E8F751C8CBC8EE2985B70B9 4F1D6BBF6FB1753096FB514E54105835585759AC5C605F926597675C6E21767B 83DF8CED901490FD934D7825783A52AA5EA6571F597460125012515A51AC0000 51CD520055105854585859575B955CF65D8B60BC6295642D6771684368BC68DF 76D76DD86E6F6D9B706F71C85F5375D879777B497B547B527CD67D7152308463 856985E48A0E8B048C468E0F9003900F94199676982D9A3095D850CD52D5540C 58025C0E61A7649E6D1E77B37AE580F48404905392855CE09D07533F5F975FB3 6D9C7279776379BF7BE46BD272EC8AAD68036A6151F87A8169345C4A9CF682EB 5BC59149701E56785C6F60C765666C8C8C5A90419813545166C7920D594890A3 51854E4D51EA85998B0E7058637A934B696299B47E047577535769608EDF96E3 6C5D4E8C5C3C5F108FE953028CD1808986795EFF65E54E735165000000000000 94 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 59825C3F97EE4EFB598A5FCD8A8D6FE179B079625BE78471732B71B15E745FF5 637B649A71C37C984E435EFC4E4B57DC56A260A96FC37D0D80FD813381BF8FB2 899786A45DF4628A64AD898767776CE26D3E743678345A467F7582AD99AC4FF3 5EC362DD63926557676F76C3724C80CC80BA8F29914D500D57F95A9268850000 6973716472FD8CB758F28CE0966A9019877F79E477E784294F2F5265535A62CD 67CF6CCA767D7B947C95823685848FEB66DD6F2072067E1B83AB99C19EA651FD 7BB178727BB880877B486AE85E61808C75517560516B92626E8C767A91979AEA 4F107F70629C7B4F95A59CE9567A585986E496BC4F345224534A53CD53DB5E06 642C6591677F6C3E6C4E724872AF73ED75547E41822C85E98CA97BC491C67169 981298EF633D6669756A76E478D0854386EE532A5351542659835E875F7C60B2 6249627962AB65906BD46CCC75B276AE789179D87DCB7F7780A588AB8AB98CBB 907F975E98DB6A0B7C3850995C3E5FAE67876BD8743577097F8E000000000000 95 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9F3B67CA7A175339758B9AED5F66819D83F180985F3C5FC575627B46903C6867 59EB5A9B7D10767E8B2C4FF55F6A6A196C376F0274E2796888688A558C795EDF 63CF75C579D282D7932892F2849C86ED9C2D54C15F6C658C6D5C70158CA78CD3 983B654F74F64E0D4ED857E0592B5A665BCC51A85E035E9C6016627665770000 65A7666E6D6E72367B268150819A82998B5C8CA08CE68D74961C96444FAE64AB 6B66821E8461856A90E85C01695398A8847A85574F0F526F5FA95E45670D798F 8179890789866DF55F1762556CB84ECF72699B925206543B567458B361A4626E 711A596E7C897CDE7D1B96F06587805E4E194F75517558405E635E735F0A67C4 4E26853D9589965B7C73980150FB58C1765678A7522577A585117B86504F5909 72477BC77DE88FBA8FD4904D4FBF52C95A295F0197AD4FDD821792EA57036355 6B69752B88DC8F147A4252DF58936155620A66AE6BCD7C3F83E950234FF85305 5446583159495B9D5CF05CEF5D295E9662B16367653E65B9670B000000000000 96 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6CD56CE170F978327E2B80DE82B3840C84EC870289128A2A8C4A90A692D298FD 9CF39D6C4E4F4EA1508D5256574A59A85E3D5FD85FD9623F66B4671B67D068D2 51927D2180AA81A88B008C8C8CBF927E96325420982C531750D5535C58A864B2 6734726777667A4691E652C36CA16B8658005E4C5954672C7FFB51E176C60000 646978E89B549EBB57CB59B96627679A6BCE54E969D95E55819C67959BAA67FE 9C52685D4EA64FE353C862B9672B6CAB8FC44FAD7E6D9EBF4E0761626E806F2B 85135473672A9B455DF37B955CAC5BC6871C6E4A84D17A14810859997C8D6C11 772052D959227121725F77DB97279D61690B5A7F5A1851A5540D547D660E76DF 8FF792989CF459EA725D6EC5514D68C97DBF7DEC97629EBA64786A2183025984 5B5F6BDB731B76F27DB280178499513267289ED976EE676252FF99055C24623B 7C7E8CB0554F60B67D0B958053014E5F51B6591C723A803691CE5F2577E25384 5F797D0485AC8A338E8D975667F385AE9453610961086CB9765200000000FF5E 97 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8AED8F38552F4F51512A52C753CB5BA55E7D60A0618263D6670967DA6E676D8C 733673377531795088D58A98904A909190F596C4878D59154E884F594E0E8A89 8F3F981050AD5E7C59965BB95EB863DA63FA64C166DC694A69D86D0B6EB67194 75287AAF7F8A8000844984C989818B218E0A9065967D990A617E62916B320000 6C836D747FCC7FFC6DC07F8587BA88F8676583B1983C96F76D1B7D61843D916A 4E7153755D506B046FEB85CD862D89A75229540F5C65674E68A87406748375E2 88CF88E191CC96E296785F8B73877ACB844E63A0756552896D416E9C74097559 786B7C9296867ADC9F8D4FB6616E65C5865C4E864EAE50DA4E2151CC5BEE6599 68816DBC731F764277AD7A1C7CE7826F8AD2907C91CF96759818529B7DD1502B 539867976DCB71D0743381E88F2A96A39C579E9F746058416D997D2F985E4EE4 4F364F8B51B752B15DBA601C73B2793C82D3923496B796F6970A9E979F6266A6 6B74521752A370C888C25EC9604B61906F2371497C3E7DF4806F000000000000 98 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 84EE9023932C54429B6F6AD370898CC28DEF973252B45A415ECA5F046717697C 69946D6A6F0F726272FC7BED8001807E874B90CE516D9E937984808B93328AD6 502D548C8A716B6A8CC4810760D167A09DF24E994E989C108A6B85C185686900 6E7E789781550000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000005F0C 4E104E154E2A4E314E364E3C4E3F4E424E564E584E824E858C6B4E8A82125F0D 4E8E4E9E4E9F4EA04EA24EB04EB34EB64ECE4ECD4EC44EC64EC24ED74EDE4EED 4EDF4EF74F094F5A4F304F5B4F5D4F574F474F764F884F8F4F984F7B4F694F70 4F914F6F4F864F9651184FD44FDF4FCE4FD84FDB4FD14FDA4FD04FE44FE5501A 50285014502A502550054F1C4FF650215029502C4FFE4FEF5011500650435047 6703505550505048505A5056506C50785080509A508550B450B2000000000000 99 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 50C950CA50B350C250D650DE50E550ED50E350EE50F950F55109510151025116 51155114511A5121513A5137513C513B513F51405152514C515451627AF85169 516A516E5180518256D8518C5189518F519151935195519651A451A651A251A9 51AA51AB51B351B151B251B051B551BD51C551C951DB51E0865551E951ED0000 51F051F551FE5204520B5214520E5227522A522E52335239524F5244524B524C 525E5254526A527452695273527F527D528D529452925271528852918FA88FA7 52AC52AD52BC52B552C152CD52D752DE52E352E698ED52E052F352F552F852F9 530653087538530D5310530F5315531A5323532F533153335338534053465345 4E175349534D51D6535E5369536E5918537B53775382539653A053A653A553AE 53B053B653C37C1296D953DF66FC71EE53EE53E853ED53FA5401543D5440542C 542D543C542E54365429541D544E548F5475548E545F5471547754705492547B 5480547654845490548654C754A254B854A554AC54C454C854A8000000000000 9A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54AB54C254A454BE54BC54D854E554E6550F551454FD54EE54ED54FA54E25539 55405563554C552E555C55455556555755385533555D5599558054AF558A559F 557B557E5598559E55AE557C558355A9558755A855DA55C555DF55C455DC55E4 55D4561455F7561655FE55FD561B55F9564E565071DF56345636563256380000 566B5664562F566C566A56865680568A56A05694568F56A556AE56B656B456C2 56BC56C156C356C056C856CE56D156D356D756EE56F9570056FF570457095708 570B570D57135718571655C7571C572657375738574E573B5740574F576957C0 57885761577F5789579357A057B357A457AA57B057C357C657D457D257D3580A 57D657E3580B5819581D587258215862584B58706BC05852583D5879588558B9 589F58AB58BA58DE58BB58B858AE58C558D358D158D758D958D858E558DC58E4 58DF58EF58FA58F958FB58FC58FD5902590A5910591B68A65925592C592D5932 5938593E7AD259555950594E595A5958596259605967596C5969000000000000 9B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 59785981599D4F5E4FAB59A359B259C659E859DC598D59D959DA5A255A1F5A11 5A1C5A095A1A5A405A6C5A495A355A365A625A6A5A9A5ABC5ABE5ACB5AC25ABD 5AE35AD75AE65AE95AD65AFA5AFB5B0C5B0B5B165B325AD05B2A5B365B3E5B43 5B455B405B515B555B5A5B5B5B655B695B705B735B755B7865885B7A5B800000 5B835BA65BB85BC35BC75BC95BD45BD05BE45BE65BE25BDE5BE55BEB5BF05BF6 5BF35C055C075C085C0D5C135C205C225C285C385C395C415C465C4E5C535C50 5C4F5B715C6C5C6E4E625C765C795C8C5C915C94599B5CAB5CBB5CB65CBC5CB7 5CC55CBE5CC75CD95CE95CFD5CFA5CED5D8C5CEA5D0B5D155D175D5C5D1F5D1B 5D115D145D225D1A5D195D185D4C5D525D4E5D4B5D6C5D735D765D875D845D82 5DA25D9D5DAC5DAE5DBD5D905DB75DBC5DC95DCD5DD35DD25DD65DDB5DEB5DF2 5DF55E0B5E1A5E195E115E1B5E365E375E445E435E405E4E5E575E545E5F5E62 5E645E475E755E765E7A9EBC5E7F5EA05EC15EC25EC85ED05ECF000000000000 9C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5ED65EE35EDD5EDA5EDB5EE25EE15EE85EE95EEC5EF15EF35EF05EF45EF85EFE 5F035F095F5D5F5C5F0B5F115F165F295F2D5F385F415F485F4C5F4E5F2F5F51 5F565F575F595F615F6D5F735F775F835F825F7F5F8A5F885F915F875F9E5F99 5F985FA05FA85FAD5FBC5FD65FFB5FE45FF85FF15FDD60B35FFF602160600000 601960106029600E6031601B6015602B6026600F603A605A6041606A6077605F 604A6046604D6063604360646042606C606B60596081608D60E76083609A6084 609B60966097609260A7608B60E160B860E060D360B45FF060BD60C660B560D8 614D6115610660F660F7610060F460FA6103612160FB60F1610D610E6147613E 61286127614A613F613C612C6134613D614261446173617761586159615A616B 6174616F61656171615F615D6153617561996196618761AC6194619A618A6191 61AB61AE61CC61CA61C961F761C861C361C661BA61CB7F7961CD61E661E361F6 61FA61F461FF61FD61FC61FE620062086209620D620C6214621B000000000000 9D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 621E6221622A622E6230623262336241624E625E6263625B62606268627C6282 6289627E62926293629662D46283629462D762D162BB62CF62FF62C664D462C8 62DC62CC62CA62C262C7629B62C9630C62EE62F163276302630862EF62F56350 633E634D641C634F6396638E638063AB637663A3638F6389639F63B5636B0000 636963BE63E963C063C663E363C963D263F663C4641664346406641364266436 651D64176428640F6467646F6476644E652A6495649364A564A9648864BC64DA 64D264C564C764BB64D864C264F164E7820964E064E162AC64E364EF652C64F6 64F464F264FA650064FD6518651C650565246523652B65346535653765366538 754B654865566555654D6558655E655D65726578658265838B8A659B659F65AB 65B765C365C665C165C465CC65D265DB65D965E065E165F16772660A660365FB 6773663566366634661C664F664466496641665E665D666466676668665F6662 667066836688668E668966846698669D66C166B966C966BE66BC000000000000 9E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 66C466B866D666DA66E0663F66E666E966F066F566F7670F6716671E67266727 9738672E673F67366741673867376746675E67606759676367646789677067A9 677C676A678C678B67A667A1678567B767EF67B467EC67B367E967B867E467DE 67DD67E267EE67B967CE67C667E76A9C681E684668296840684D6832684E0000 68B3682B685968636877687F689F688F68AD6894689D689B68836AAE68B96874 68B568A068BA690F688D687E690168CA690868D86922692668E1690C68CD68D4 68E768D569366912690468D768E3692568F968E068EF6928692A691A69236921 68C669796977695C6978696B6954697E696E69396974693D695969306961695E 695D6981696A69B269AE69D069BF69C169D369BE69CE5BE869CA69DD69BB69C3 69A76A2E699169A0699C699569B469DE69E86A026A1B69FF6B0A69F969F269E7 6A0569B16A1E69ED6A1469EB6A0A6A126AC16A236A136A446A0C6A726A366A78 6A476A626A596A666A486A386A226A906A8D6AA06A846AA26AA3000000000000 9F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A9786176ABB6AC36AC26AB86AB36AAC6ADE6AD16ADF6AAA6ADA6AEA6AFB6B05 86166AFA6B126B169B316B1F6B386B3776DC6B3998EE6B476B436B496B506B59 6B546B5B6B5F6B616B786B796B7F6B806B846B836B8D6B986B956B9E6BA46BAA 6BAB6BAF6BB26BB16BB36BB76BBC6BC66BCB6BD36BDF6BEC6BEB6BF36BEF0000 9EBE6C086C136C146C1B6C246C236C5E6C556C626C6A6C826C8D6C9A6C816C9B 6C7E6C686C736C926C906CC46CF16CD36CBD6CD76CC56CDD6CAE6CB16CBE6CBA 6CDB6CEF6CD96CEA6D1F884D6D366D2B6D3D6D386D196D356D336D126D0C6D63 6D936D646D5A6D796D596D8E6D956FE46D856DF96E156E0A6DB56DC76DE66DB8 6DC66DEC6DDE6DCC6DE86DD26DC56DFA6DD96DE46DD56DEA6DEE6E2D6E6E6E2E 6E196E726E5F6E3E6E236E6B6E2B6E766E4D6E1F6E436E3A6E4E6E246EFF6E1D 6E386E826EAA6E986EC96EB76ED36EBD6EAF6EC46EB26ED46ED56E8F6EA56EC2 6E9F6F416F11704C6EEC6EF86EFE6F3F6EF26F316EEF6F326ECC000000000000 E0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6F3E6F136EF76F866F7A6F786F816F806F6F6F5B6FF36F6D6F826F7C6F586F8E 6F916FC26F666FB36FA36FA16FA46FB96FC66FAA6FDF6FD56FEC6FD46FD86FF1 6FEE6FDB7009700B6FFA70117001700F6FFE701B701A6F74701D7018701F7030 703E7032705170637099709270AF70F170AC70B870B370AE70DF70CB70DD0000 70D9710970FD711C711971657155718871667162714C7156716C718F71FB7184 719571A871AC71D771B971BE71D271C971D471CE71E071EC71E771F571FC71F9 71FF720D7210721B7228722D722C72307232723B723C723F72407246724B7258 7274727E7282728172877292729672A272A772B972B272C372C672C472CE72D2 72E272E072E172F972F7500F7317730A731C7316731D7334732F73297325733E 734E734F9ED87357736A7368737073787375737B737A73C873B373CE73BB73C0 73E573EE73DE74A27405746F742573F87432743A7455743F745F74597441745C 746974707463746A7476747E748B749E74A774CA74CF74D473F1000000000000 E1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 74E074E374E774E974EE74F274F074F174F874F7750475037505750C750E750D 75157513751E7526752C753C7544754D754A7549755B7546755A756975647567 756B756D75787576758675877574758A758975827594759A759D75A575A375C2 75B375C375B575BD75B875BC75B175CD75CA75D275D975E375DE75FE75FF0000 75FC760175F075FA75F275F3760B760D7609761F762776207621762276247634 7630763B764776487646765C76587661766276687669766A7667766C76707672 76767678767C768076837688768B768E769676937699769A76B076B476B876B9 76BA76C276CD76D676D276DE76E176E576E776EA862F76FB7708770777047729 7724771E77257726771B773777387747775A7768776B775B7765777F777E7779 778E778B779177A0779E77B077B677B977BF77BC77BD77BB77C777CD77D777DA 77DC77E377EE77FC780C781279267820792A7845788E78747886787C789A788C 78A378B578AA78AF78D178C678CB78D478BE78BC78C578CA78EC000000000000 E2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 78E778DA78FD78F47907791279117919792C792B794079607957795F795A7955 7953797A797F798A799D79A79F4B79AA79AE79B379B979BA79C979D579E779EC 79E179E37A087A0D7A187A197A207A1F79807A317A3B7A3E7A377A437A577A49 7A617A627A699F9D7A707A797A7D7A887A977A957A987A967AA97AC87AB00000 7AB67AC57AC47ABF90837AC77ACA7ACD7ACF7AD57AD37AD97ADA7ADD7AE17AE2 7AE67AED7AF07B027B0F7B0A7B067B337B187B197B1E7B357B287B367B507B7A 7B047B4D7B0B7B4C7B457B757B657B747B677B707B717B6C7B6E7B9D7B987B9F 7B8D7B9C7B9A7B8B7B927B8F7B5D7B997BCB7BC17BCC7BCF7BB47BC67BDD7BE9 7C117C147BE67BE57C607C007C077C137BF37BF77C177C0D7BF67C237C277C2A 7C1F7C377C2B7C3D7C4C7C437C547C4F7C407C507C587C5F7C647C567C657C6C 7C757C837C907CA47CAD7CA27CAB7CA17CA87CB37CB27CB17CAE7CB97CBD7CC0 7CC57CC27CD87CD27CDC7CE29B3B7CEF7CF27CF47CF67CFA7D06000000000000 E3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7D027D1C7D157D0A7D457D4B7D2E7D327D3F7D357D467D737D567D4E7D727D68 7D6E7D4F7D637D937D897D5B7D8F7D7D7D9B7DBA7DAE7DA37DB57DC77DBD7DAB 7E3D7DA27DAF7DDC7DB87D9F7DB07DD87DDD7DE47DDE7DFB7DF27DE17E057E0A 7E237E217E127E317E1F7E097E0B7E227E467E667E3B7E357E397E437E370000 7E327E3A7E677E5D7E567E5E7E597E5A7E797E6A7E697E7C7E7B7E837DD57E7D 8FAE7E7F7E887E897E8C7E927E907E937E947E967E8E7E9B7E9C7F387F3A7F45 7F4C7F4D7F4E7F507F517F557F547F587F5F7F607F687F697F677F787F827F86 7F837F887F877F8C7F947F9E7F9D7F9A7FA37FAF7FB27FB97FAE7FB67FB88B71 7FC57FC67FCA7FD57FD47FE17FE67FE97FF37FF998DC80068004800B80128018 8019801C80218028803F803B804A804680528058805A805F8062806880738072 807080768079807D807F808480868085809B8093809A80AD519080AC80DB80E5 80D980DD80C480DA80D6810980EF80F1811B81298123812F814B000000000000 E4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 968B8146813E8153815180FC8171816E81658166817481838188818A81808182 81A0819581A481A3815F819381A981B081B581BE81B881BD81C081C281BA81C9 81CD81D181D981D881C881DA81DF81E081E781FA81FB81FE8201820282058207 820A820D821082168229822B82388233824082598258825D825A825F82640000 82628268826A826B822E827182778278827E828D829282AB829F82BB82AC82E1 82E382DF82D282F482F382FA8393830382FB82F982DE830682DC830982D98335 83348316833283318340833983508345832F832B831783188385839A83AA839F 83A283968323838E8387838A837C83B58373837583A0838983A883F4841383EB 83CE83FD840383D8840B83C183F7840783E083F2840D8422842083BD84388506 83FB846D842A843C855A84848477846B84AD846E848284698446842C846F8479 843584CA846284B984BF849F84D984CD84BB84DA84D084C184C684D684A18521 84FF84F485178518852C851F8515851484FC8540856385588548000000000000 E5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 85418602854B8555858085A485888591858A85A8856D8594859B85EA8587859C 8577857E859085C985BA85CF85B985D085D585DD85E585DC85F9860A8613860B 85FE85FA86068622861A8630863F864D4E558654865F86678671869386A386A9 86AA868B868C86B686AF86C486C686B086C9882386AB86D486DE86E986EC0000 86DF86DB86EF8712870687088700870386FB87118709870D86F9870A8734873F 8737873B87258729871A8760875F8778874C874E877487578768876E87598753 8763876A880587A2879F878287AF87CB87BD87C087D096D687AB87C487B387C7 87C687BB87EF87F287E0880F880D87FE87F687F7880E87D28811881688158822 88218831883688398827883B8844884288528859885E8862886B8881887E889E 8875887D88B5887288828897889288AE889988A2888D88A488B088BF88B188C3 88C488D488D888D988DD88F9890288FC88F488E888F28904890C890A89138943 891E8925892A892B89418944893B89368938894C891D8960895E000000000000 E6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 89668964896D896A896F89748977897E89838988898A8993899889A189A989A6 89AC89AF89B289BA89BD89BF89C089DA89DC89DD89E789F489F88A038A168A10 8A0C8A1B8A1D8A258A368A418A5B8A528A468A488A7C8A6D8A6C8A628A858A82 8A848AA88AA18A918AA58AA68A9A8AA38AC48ACD8AC28ADA8AEB8AF38AE70000 8AE48AF18B148AE08AE28AF78ADE8ADB8B0C8B078B1A8AE18B168B108B178B20 8B3397AB8B268B2B8B3E8B288B418B4C8B4F8B4E8B498B568B5B8B5A8B6B8B5F 8B6C8B6F8B748B7D8B808B8C8B8E8B928B938B968B998B9A8C3A8C418C3F8C48 8C4C8C4E8C508C558C628C6C8C788C7A8C828C898C858C8A8C8D8C8E8C948C7C 8C98621D8CAD8CAA8CBD8CB28CB38CAE8CB68CC88CC18CE48CE38CDA8CFD8CFA 8CFB8D048D058D0A8D078D0F8D0D8D109F4E8D138CCD8D148D168D678D6D8D71 8D738D818D998DC28DBE8DBA8DCF8DDA8DD68DCC8DDB8DCB8DEA8DEB8DDF8DE3 8DFC8E088E098DFF8E1D8E1E8E108E1F8E428E358E308E348E4A000000000000 E7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8E478E498E4C8E508E488E598E648E608E2A8E638E558E768E728E7C8E818E87 8E858E848E8B8E8A8E938E918E948E998EAA8EA18EAC8EB08EC68EB18EBE8EC5 8EC88ECB8EDB8EE38EFC8EFB8EEB8EFE8F0A8F058F158F128F198F138F1C8F1F 8F1B8F0C8F268F338F3B8F398F458F428F3E8F4C8F498F468F4E8F578F5C0000 8F628F638F648F9C8F9F8FA38FAD8FAF8FB78FDA8FE58FE28FEA8FEF90878FF4 90058FF98FFA901190159021900D901E9016900B90279036903590398FF8904F 905090519052900E9049903E90569058905E9068906F907696A890729082907D 90819080908A9089908F90A890AF90B190B590E290E4624890DB910291129119 91329130914A9156915891639165916991739172918B9189918291A291AB91AF 91AA91B591B491BA91C091C191C991CB91D091D691DF91E191DB91FC91F591F6 921E91FF9214922C92159211925E925792459249926492489295923F924B9250 929C92969293929B925A92CF92B992B792E9930F92FA9344932E000000000000 E8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 93199322931A9323933A9335933B935C9360937C936E935693B093AC93AD9394 93B993D693D793E893E593D893C393DD93D093C893E4941A9414941394039407 94109436942B94359421943A944194529444945B94609462945E946A92299470 94759477947D945A947C947E9481947F95829587958A95949596959895990000 95A095A895A795AD95BC95BB95B995BE95CA6FF695C395CD95CC95D595D495D6 95DC95E195E595E296219628962E962F9642964C964F964B9677965C965E965D 965F96669672966C968D96989695969796AA96A796B196B296B096B496B696B8 96B996CE96CB96C996CD894D96DC970D96D596F99704970697089713970E9711 970F971697199724972A97309739973D973E97449746974897429749975C9760 97649766976852D2976B977197799785977C9781977A9786978B978F9790979C 97A897A697A397B397B497C397C697C897CB97DC97ED9F4F97F27ADF97F697F5 980F980C9838982498219837983D9846984F984B986B986F9870000000000000 E9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 98719874987398AA98AF98B198B698C498C398C698E998EB9903990999129914 99189921991D991E99249920992C992E993D993E9942994999459950994B9951 9952994C99559997999899A599AD99AE99BC99DF99DB99DD99D899D199ED99EE 99F199F299FB99F89A019A0F9A0599E29A199A2B9A379A459A429A409A430000 9A3E9A559A4D9A5B9A579A5F9A629A659A649A699A6B9A6A9AAD9AB09ABC9AC0 9ACF9AD19AD39AD49ADE9ADF9AE29AE39AE69AEF9AEB9AEE9AF49AF19AF79AFB 9B069B189B1A9B1F9B229B239B259B279B289B299B2A9B2E9B2F9B329B449B43 9B4F9B4D9B4E9B519B589B749B939B839B919B969B979B9F9BA09BA89BB49BC0 9BCA9BB99BC69BCF9BD19BD29BE39BE29BE49BD49BE19C3A9BF29BF19BF09C15 9C149C099C139C0C9C069C089C129C0A9C049C2E9C1B9C259C249C219C309C47 9C329C469C3E9C5A9C609C679C769C789CE79CEC9CF09D099D089CEB9D039D06 9D2A9D269DAF9D239D1F9D449D159D129D419D3F9D3E9D469D48000000000000 EA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9D5D9D5E9D649D519D509D599D729D899D879DAB9D6F9D7A9D9A9DA49DA99DB2 9DC49DC19DBB9DB89DBA9DC69DCF9DC29DD99DD39DF89DE69DED9DEF9DFD9E1A 9E1B9E1E9E759E799E7D9E819E889E8B9E8C9E929E959E919E9D9EA59EA99EB8 9EAA9EAD97619ECC9ECE9ECF9ED09ED49EDC9EDE9EDD9EE09EE59EE89EEF0000 9EF49EF69EF79EF99EFB9EFC9EFD9F079F0876B79F159F219F2C9F3E9F4A9F52 9F549F639F5F9F609F619F669F679F6C9F6A9F779F729F769F959F9C9FA0582F 69C79059746451DC719900000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 R 8160 301C FF5E 8161 2016 2225 817C 2212 FF0D 8191 00A2 FFE0 8192 00A3 FFE1 81CA 00AC FFE2 tcl8.6.5/library/encoding/cp950.enc0000644000175000017500000026326711555560473016371 0ustar sergeisergei# Encoding file: cp950, multi-byte M 003F 0 88 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3000FF0C30013002FF0E2027FF1BFF1AFF1FFF01FE3020262025FE50FE51FE52 00B7FE54FE55FE56FE57FF5C2013FE312014FE332574FE34FE4FFF08FF09FE35 FE36FF5BFF5DFE37FE3830143015FE39FE3A30103011FE3BFE3C300A300BFE3D FE3E30083009FE3FFE40300C300DFE41FE42300E300FFE43FE44FE59FE5A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FE5BFE5CFE5DFE5E20182019201C201D301D301E20352032FF03FF06FF0A 203B00A7300325CB25CF25B325B225CE2606260525C725C625A125A025BD25BC 32A3210500AFFFE3FF3F02CDFE49FE4AFE4DFE4EFE4BFE4CFE5FFE60FE61FF0B FF0D00D700F700B1221AFF1CFF1EFF1D226622672260221E22522261FE62FE63 FE64FE65FE66FF5E2229222A22A52220221F22BF33D233D1222B222E22352234 26402642229522992191219321902192219621972199219822252223FF0F0000 A2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FF3C2215FE68FF04FFE53012FFE0FFE1FF05FF2021032109FE69FE6AFE6B33D5 339C339D339E33CE33A1338E338F33C400B05159515B515E515D5161516355E7 74E97CCE25812582258325842585258625872588258F258E258D258C258B258A 2589253C2534252C2524251C2594250025022595250C251025142518256D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000256E2570256F2550255E256A256125E225E325E525E4257125722573FF10 FF11FF12FF13FF14FF15FF16FF17FF18FF192160216121622163216421652166 216721682169302130223023302430253026302730283029534153445345FF21 FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2FFF30FF31 FF32FF33FF34FF35FF36FF37FF38FF39FF3AFF41FF42FF43FF44FF45FF46FF47 FF48FF49FF4AFF4BFF4CFF4DFF4EFF4FFF50FF51FF52FF53FF54FF55FF560000 A3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FF57FF58FF59FF5A039103920393039403950396039703980399039A039B039C 039D039E039F03A003A103A303A403A503A603A703A803A903B103B203B303B4 03B503B603B703B803B903BA03BB03BC03BD03BE03BF03C003C103C303C403C5 03C603C703C803C931053106310731083109310A310B310C310D310E310F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00003110311131123113311431153116311731183119311A311B311C311D311E 311F312031213122312331243125312631273128312902D902C902CA02C702CB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000020AC00000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E004E594E014E034E434E5D4E864E8C4EBA513F5165516B51E052005201529B 53155341535C53C84E094E0B4E084E0A4E2B4E3851E14E454E484E5F4E5E4E8E 4EA15140520352FA534353C953E3571F58EB5915592759735B505B515B535BF8 5C0F5C225C385C715DDD5DE55DF15DF25DF35DFE5E725EFE5F0B5F13624D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E114E104E0D4E2D4E304E394E4B5C394E884E914E954E924E944EA24EC1 4EC04EC34EC64EC74ECD4ECA4ECB4EC4514351415167516D516E516C519751F6 52065207520852FB52FE52FF53165339534853475345535E538453CB53CA53CD 58EC5929592B592A592D5B545C115C245C3A5C6F5DF45E7B5EFF5F145F155FC3 62086236624B624E652F6587659765A465B965E566F0670867286B206B626B79 6BCB6BD46BDB6C0F6C34706B722A7236723B72477259725B72AC738B4E190000 A5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E164E154E144E184E3B4E4D4E4F4E4E4EE54ED84ED44ED54ED64ED74EE34EE4 4ED94EDE514551445189518A51AC51F951FA51F8520A52A0529F530553065317 531D4EDF534A534953615360536F536E53BB53EF53E453F353EC53EE53E953E8 53FC53F853F553EB53E653EA53F253F153F053E553ED53FB56DB56DA59160000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000592E5931597459765B555B835C3C5DE85DE75DE65E025E035E735E7C5F01 5F185F175FC5620A625362546252625165A565E6672E672C672A672B672D6B63 6BCD6C116C106C386C416C406C3E72AF7384738974DC74E67518751F75287529 7530753175327533758B767D76AE76BF76EE77DB77E277F3793A79BE7A747ACB 4E1E4E1F4E524E534E694E994EA44EA64EA54EFF4F094F194F0A4F154F0D4F10 4F114F0F4EF24EF64EFB4EF04EF34EFD4F014F0B514951475146514851680000 A6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5171518D51B0521752115212520E521652A3530853215320537053715409540F 540C540A54105401540B54045411540D54085403540E5406541256E056DE56DD 573357305728572D572C572F57295919591A59375938598459785983597D5979 598259815B575B585B875B885B855B895BFA5C165C795DDE5E065E765E740000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F0F5F1B5FD95FD6620E620C620D62106263625B6258653665E965E865EC 65ED66F266F36709673D6734673167356B216B646B7B6C166C5D6C576C596C5F 6C606C506C556C616C5B6C4D6C4E7070725F725D767E7AF97C737CF87F367F8A 7FBD80018003800C80128033807F8089808B808C81E381EA81F381FC820C821B 821F826E8272827E866B8840884C8863897F96214E324EA84F4D4F4F4F474F57 4F5E4F344F5B4F554F304F504F514F3D4F3A4F384F434F544F3C4F464F630000 A7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4F5C4F604F2F4F4E4F364F594F5D4F484F5A514C514B514D517551B651B75225 52245229522A522852AB52A952AA52AC532353735375541D542D541E543E5426 544E542754465443543354485442541B5429544A5439543B5438542E54355436 5420543C54405431542B541F542C56EA56F056E456EB574A57515740574D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005747574E573E5750574F573B58EF593E599D599259A8599E59A359995996 598D59A45993598A59A55B5D5B5C5B5A5B5B5B8C5B8B5B8F5C2C5C405C415C3F 5C3E5C905C915C945C8C5DEB5E0C5E8F5E875E8A5EF75F045F1F5F645F625F77 5F795FD85FCC5FD75FCD5FF15FEB5FF85FEA6212621162846297629662806276 6289626D628A627C627E627962736292626F6298626E62956293629162866539 653B653865F166F4675F674E674F67506751675C6756675E6749674667600000 A8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 675367576B656BCF6C426C5E6C996C816C886C896C856C9B6C6A6C7A6C906C70 6C8C6C686C966C926C7D6C836C726C7E6C746C866C766C8D6C946C986C827076 707C707D707872627261726072C472C27396752C752B75377538768276EF77E3 79C179C079BF7A767CFB7F5580968093809D8098809B809A80B2826F82920000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000828B828D898B89D28A008C378C468C558C9D8D648D708DB38EAB8ECA8F9B 8FB08FC28FC68FC58FC45DE1909190A290AA90A690A3914991C691CC9632962E 9631962A962C4E264E564E734E8B4E9B4E9E4EAB4EAC4F6F4F9D4F8D4F734F7F 4F6C4F9B4F8B4F864F834F704F754F884F694F7B4F964F7E4F8F4F914F7A5154 51525155516951775176517851BD51FD523B52385237523A5230522E52365241 52BE52BB5352535453535351536653775378537953D653D453D7547354750000 A9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5496547854955480547B5477548454925486547C549054715476548C549A5462 5468548B547D548E56FA57835777576A5769576157665764577C591C59495947 59485944595459BE59BB59D459B959AE59D159C659D059CD59CB59D359CA59AF 59B359D259C55B5F5B645B635B975B9A5B985B9C5B995B9B5C1A5C485C450000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C465CB75CA15CB85CA95CAB5CB15CB35E185E1A5E165E155E1B5E115E78 5E9A5E975E9C5E955E965EF65F265F275F295F805F815F7F5F7C5FDD5FE05FFD 5FF55FFF600F6014602F60356016602A6015602160276029602B601B62166215 623F623E6240627F62C962CC62C462BF62C262B962D262DB62AB62D362D462CB 62C862A862BD62BC62D062D962C762CD62B562DA62B162D862D662D762C662AC 62CE653E65A765BC65FA66146613660C66066602660E6600660F6615660A0000 AA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6607670D670B676D678B67956771679C677367776787679D6797676F6770677F 6789677E67906775679A6793677C676A67726B236B666B676B7F6C136C1B6CE3 6CE86CF36CB16CCC6CE56CB36CBD6CBE6CBC6CE26CAB6CD56CD36CB86CC46CB9 6CC16CAE6CD76CC56CF16CBF6CBB6CE16CDB6CCA6CAC6CEF6CDC6CD66CE00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007095708E7092708A7099722C722D723872487267726972C072CE72D972D7 72D073A973A8739F73AB73A5753D759D7599759A768476C276F276F477E577FD 793E7940794179C979C87A7A7A797AFA7CFE7F547F8C7F8B800580BA80A580A2 80B180A180AB80A980B480AA80AF81E581FE820D82B3829D829982AD82BD829F 82B982B182AC82A582AF82B882A382B082BE82B7864E8671521D88688ECB8FCE 8FD48FD190B590B890B190B691C791D195779580961C9640963F963B96440000 AB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 964296B996E89752975E4E9F4EAD4EAE4FE14FB54FAF4FBF4FE04FD14FCF4FDD 4FC34FB64FD84FDF4FCA4FD74FAE4FD04FC44FC24FDA4FCE4FDE4FB751575192 519151A0524E5243524A524D524C524B524752C752C952C352C1530D5357537B 539A53DB54AC54C054A854CE54C954B854A654B354C754C254BD54AA54C10000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000054C454C854AF54AB54B154BB54A954A754BF56FF5782578B57A057A357A2 57CE57AE579359555951594F594E595059DC59D859FF59E359E85A0359E559EA 59DA59E65A0159FB5B695BA35BA65BA45BA25BA55C015C4E5C4F5C4D5C4B5CD9 5CD25DF75E1D5E255E1F5E7D5EA05EA65EFA5F085F2D5F655F885F855F8A5F8B 5F875F8C5F896012601D60206025600E6028604D60706068606260466043606C 606B606A6064624162DC6316630962FC62ED630162EE62FD630762F162F70000 AC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 62EF62EC62FE62F463116302653F654565AB65BD65E26625662D66206627662F 661F66286631662466F767FF67D367F167D467D067EC67B667AF67F567E967EF 67C467D167B467DA67E567B867CF67DE67F367B067D967E267DD67D26B6A6B83 6B866BB56BD26BD76C1F6CC96D0B6D326D2A6D416D256D0C6D316D1E6D170000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D3B6D3D6D3E6D366D1B6CF56D396D276D386D296D2E6D356D0E6D2B70AB 70BA70B370AC70AF70AD70B870AE70A472307272726F727472E972E072E173B7 73CA73BB73B273CD73C073B3751A752D754F754C754E754B75AB75A475A575A2 75A3767876867687768876C876C676C376C5770176F976F87709770B76FE76FC 770777DC78027814780C780D794679497948794779B979BA79D179D279CB7A7F 7A817AFF7AFD7C7D7D027D057D007D097D077D047D067F387F8E7FBF80040000 AD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8010800D8011803680D680E580DA80C380C480CC80E180DB80CE80DE80E480DD 81F4822282E78303830582E382DB82E6830482E58302830982D282D782F18301 82DC82D482D182DE82D382DF82EF830686508679867B867A884D886B898189D4 8A088A028A038C9E8CA08D748D738DB48ECD8ECC8FF08FE68FE28FEA8FE50000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008FED8FEB8FE48FE890CA90CE90C190C3914B914A91CD95829650964B964C 964D9762976997CB97ED97F3980198A898DB98DF999699994E584EB3500C500D 50234FEF502650254FF8502950165006503C501F501A501250114FFA50005014 50284FF15021500B501950184FF34FEE502D502A4FFE502B5009517C51A451A5 51A251CD51CC51C651CB5256525C5254525B525D532A537F539F539D53DF54E8 55105501553754FC54E554F2550654FA551454E954ED54E1550954EE54EA0000 AE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54E65527550754FD550F5703570457C257D457CB57C35809590F59575958595A 5A115A185A1C5A1F5A1B5A1359EC5A205A235A295A255A0C5A095B6B5C585BB0 5BB35BB65BB45BAE5BB55BB95BB85C045C515C555C505CED5CFD5CFB5CEA5CE8 5CF05CF65D015CF45DEE5E2D5E2B5EAB5EAD5EA75F315F925F915F9060590000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006063606560506055606D6069606F6084609F609A608D6094608C60856096 624762F3630862FF634E633E632F635563426346634F6349633A6350633D632A 632B6328634D634C65486549659965C165C566426649664F66436652664C6645 664166F867146715671768216838684868466853683968426854682968B36817 684C6851683D67F468506840683C6843682A68456813681868416B8A6B896BB7 6C236C276C286C266C246CF06D6A6D956D886D876D666D786D776D596D930000 AF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6D6C6D896D6E6D5A6D746D696D8C6D8A6D796D856D656D9470CA70D870E470D9 70C870CF7239727972FC72F972FD72F872F7738673ED740973EE73E073EA73DE 7554755D755C755A755975BE75C575C775B275B375BD75BC75B975C275B8768B 76B076CA76CD76CE7729771F7720772877E9783078277838781D783478370000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007825782D7820781F7832795579507960795F7956795E795D7957795A79E4 79E379E779DF79E679E979D87A847A887AD97B067B117C897D217D177D0B7D0A 7D207D227D147D107D157D1A7D1C7D0D7D197D1B7F3A7F5F7F947FC57FC18006 8018801580198017803D803F80F1810280F0810580ED80F4810680F880F38108 80FD810A80FC80EF81ED81EC82008210822A822B8228822C82BB832B83528354 834A83388350834983358334834F833283398336831783408331832883430000 B0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8654868A86AA869386A486A9868C86A3869C8870887788818882887D88798A18 8A108A0E8A0C8A158A0A8A178A138A168A0F8A118C488C7A8C798CA18CA28D77 8EAC8ED28ED48ECF8FB1900190068FF790008FFA8FF490038FFD90058FF89095 90E190DD90E29152914D914C91D891DD91D791DC91D995839662966396610000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000965B965D96649658965E96BB98E299AC9AA89AD89B259B329B3C4E7E507A 507D505C50475043504C505A504950655076504E5055507550745077504F500F 506F506D515C519551F0526A526F52D252D952D852D55310530F5319533F5340 533E53C366FC5546556A55665544555E55615543554A55315556554F5555552F 55645538552E555C552C55635533554155575708570B570957DF5805580A5806 57E057E457FA5802583557F757F9592059625A365A415A495A665A6A5A400000 B1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5A3C5A625A5A5A465A4A5B705BC75BC55BC45BC25BBF5BC65C095C085C075C60 5C5C5C5D5D075D065D0E5D1B5D165D225D115D295D145D195D245D275D175DE2 5E385E365E335E375EB75EB85EB65EB55EBE5F355F375F575F6C5F695F6B5F97 5F995F9E5F985FA15FA05F9C607F60A3608960A060A860CB60B460E660BD0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000060C560BB60B560DC60BC60D860D560C660DF60B860DA60C7621A621B6248 63A063A76372639663A263A563776367639863AA637163A963896383639B636B 63A863846388639963A163AC6392638F6380637B63696368637A655D65566551 65596557555F654F655865556554659C659B65AC65CF65CB65CC65CE665D665A 666466686666665E66F952D7671B688168AF68A2689368B5687F687668B168A7 689768B0688368C468AD688668856894689D68A8689F68A168826B326BBA0000 B2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6BEB6BEC6C2B6D8E6DBC6DF36DD96DB26DE16DCC6DE46DFB6DFA6E056DC76DCB 6DAF6DD16DAE6DDE6DF96DB86DF76DF56DC56DD26E1A6DB56DDA6DEB6DD86DEA 6DF16DEE6DE86DC66DC46DAA6DEC6DBF6DE670F97109710A70FD70EF723D727D 7281731C731B73167313731973877405740A7403740673FE740D74E074F60000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000074F7751C75227565756675627570758F75D475D575B575CA75CD768E76D4 76D276DB7737773E773C77367738773A786B7843784E79657968796D79FB7A92 7A957B207B287B1B7B2C7B267B197B1E7B2E7C927C977C957D467D437D717D2E 7D397D3C7D407D307D337D447D2F7D427D327D317F3D7F9E7F9A7FCC7FCE7FD2 801C804A8046812F81168123812B81298130812482028235823782368239838E 839E8398837883A2839683BD83AB8392838A8393838983A08377837B837C0000 B3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 838683A786555F6A86C786C086B686C486B586C686CB86B186AF86C98853889E 888888AB88928896888D888B8993898F8A2A8A1D8A238A258A318A2D8A1F8A1B 8A228C498C5A8CA98CAC8CAB8CA88CAA8CA78D678D668DBE8DBA8EDB8EDF9019 900D901A90179023901F901D90109015901E9020900F90229016901B90140000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000090E890ED90FD915791CE91F591E691E391E791ED91E99589966A96759673 96789670967496769677966C96C096EA96E97AE07ADF980298039B5A9CE59E75 9E7F9EA59EBB50A2508D508550995091508050965098509A670051F152725274 5275526952DE52DD52DB535A53A5557B558055A7557C558A559D55985582559C 55AA55945587558B558355B355AE559F553E55B2559A55BB55AC55B1557E5589 55AB5599570D582F582A58345824583058315821581D582058F958FA59600000 B4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5A775A9A5A7F5A925A9B5AA75B735B715BD25BCC5BD35BD05C0A5C0B5C315D4C 5D505D345D475DFD5E455E3D5E405E435E7E5ECA5EC15EC25EC45F3C5F6D5FA9 5FAA5FA860D160E160B260B660E0611C612360FA611560F060FB60F4616860F1 610E60F6610961006112621F624963A3638C63CF63C063E963C963C663CD0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000063D263E363D063E163D663ED63EE637663F463EA63DB645263DA63F9655E 6566656265636591659065AF666E667066746676666F6691667A667E667766FE 66FF671F671D68FA68D568E068D868D7690568DF68F568EE68E768F968D268F2 68E368CB68CD690D6912690E68C968DA696E68FB6B3E6B3A6B3D6B986B966BBC 6BEF6C2E6C2F6C2C6E2F6E386E546E216E326E676E4A6E206E256E236E1B6E5B 6E586E246E566E6E6E2D6E266E6F6E346E4D6E3A6E2C6E436E1D6E3E6ECB0000 B5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6E896E196E4E6E636E446E726E696E5F7119711A7126713071217136716E711C 724C728472807336732573347329743A742A743374227425743574367434742F 741B7426742875257526756B756A75E275DB75E375D975D875DE75E0767B767C 7696769376B476DC774F77ED785D786C786F7A0D7A087A0B7A057A007A980000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A977A967AE57AE37B497B567B467B507B527B547B4D7B4B7B4F7B517C9F 7CA57D5E7D507D687D557D2B7D6E7D727D617D667D627D707D7355847FD47FD5 800B8052808581558154814B8151814E81398146813E814C815381748212821C 83E9840383F8840D83E083C5840B83C183EF83F183F48457840A83F0840C83CC 83FD83F283CA8438840E840483DC840783D483DF865B86DF86D986ED86D486DB 86E486D086DE885788C188C288B1898389968A3B8A608A558A5E8A3C8A410000 B6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8A548A5B8A508A468A348A3A8A368A568C618C828CAF8CBC8CB38CBD8CC18CBB 8CC08CB48CB78CB68CBF8CB88D8A8D858D818DCE8DDD8DCB8DDA8DD18DCC8DDB 8DC68EFB8EF88EFC8F9C902E90359031903890329036910290F5910990FE9163 916591CF9214921592239209921E920D9210920792119594958F958B95910000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000095939592958E968A968E968B967D96859686968D9672968496C196C596C4 96C696C796EF96F297CC98059806980898E798EA98EF98E998F298ED99AE99AD 9EC39ECD9ED14E8250AD50B550B250B350C550BE50AC50B750BB50AF50C7527F 5277527D52DF52E652E452E252E3532F55DF55E855D355E655CE55DC55C755D1 55E355E455EF55DA55E155C555C655E555C957125713585E585158585857585A 5854586B584C586D584A58625852584B59675AC15AC95ACC5ABE5ABD5ABC0000 B7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5AB35AC25AB25D695D6F5E4C5E795EC95EC85F125F595FAC5FAE611A610F6148 611F60F3611B60F961016108614E614C6144614D613E61346127610D61066137 622162226413643E641E642A642D643D642C640F641C6414640D643664166417 6406656C659F65B06697668966876688669666846698668D67036994696D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000695A697769606954697569306982694A6968696B695E695369796986695D 6963695B6B476B726BC06BBF6BD36BFD6EA26EAF6ED36EB66EC26E906E9D6EC7 6EC56EA56E986EBC6EBA6EAB6ED16E966E9C6EC46ED46EAA6EA76EB4714E7159 7169716471497167715C716C7166714C7165715E714671687156723A72527337 7345733F733E746F745A7455745F745E7441743F7459745B745C757675787600 75F0760175F275F175FA75FF75F475F376DE76DF775B776B7766775E77630000 B8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7779776A776C775C77657768776277EE788E78B078977898788C7889787C7891 7893787F797A797F7981842C79BD7A1C7A1A7A207A147A1F7A1E7A9F7AA07B77 7BC07B607B6E7B677CB17CB37CB57D937D797D917D817D8F7D5B7F6E7F697F6A 7F727FA97FA87FA480568058808680848171817081788165816E8173816B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008179817A81668205824784828477843D843184758466846B8449846C845B 843C8435846184638469846D8446865E865C865F86F9871387088707870086FE 86FB870287038706870A885988DF88D488D988DC88D888DD88E188CA88D588D2 899C89E38A6B8A728A738A668A698A708A878A7C8A638AA08A718A858A6D8A62 8A6E8A6C8A798A7B8A3E8A688C628C8A8C898CCA8CC78CC88CC48CB28CC38CC2 8CC58DE18DDF8DE88DEF8DF38DFA8DEA8DE48DE68EB28F038F098EFE8F0A0000 B9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8F9F8FB2904B904A905390429054903C905590509047904F904E904D9051903E 904191129117916C916A916991C9923792579238923D9240923E925B924B9264 925192349249924D92459239923F925A959896989694969596CD96CB96C996CA 96F796FB96F996F6975697749776981098119813980A9812980C98FC98F40000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000098FD98FE99B399B199B49AE19CE99E829F0E9F139F2050E750EE50E550D6 50ED50DA50D550CF50D150F150CE50E9516251F352835282533153AD55FE5600 561B561755FD561456065609560D560E55F75616561F5608561055F657185716 5875587E58835893588A58795885587D58FD592559225924596A59695AE15AE6 5AE95AD75AD65AD85AE35B755BDE5BE75BE15BE55BE65BE85BE25BE45BDF5C0D 5C625D845D875E5B5E635E555E575E545ED35ED65F0A5F465F705FB961470000 BA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 613F614B617761626163615F615A61586175622A64876458645464A46478645F 647A645164676434646D647B657265A165D765D666A266A8669D699C69A86995 69C169AE69D369CB699B69B769BB69AB69B469D069CD69AD69CC69A669C369A3 6B496B4C6C336F336F146EFE6F136EF46F296F3E6F206F2C6F0F6F026F220000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006EFF6EEF6F066F316F386F326F236F156F2B6F2F6F886F2A6EEC6F016EF2 6ECC6EF771947199717D718A71847192723E729272967344735074647463746A 7470746D750475917627760D760B7609761376E176E37784777D777F776178C1 789F78A778B378A978A3798E798F798D7A2E7A317AAA7AA97AED7AEF7BA17B95 7B8B7B757B977B9D7B947B8F7BB87B877B847CB97CBD7CBE7DBB7DB07D9C7DBD 7DBE7DA07DCA7DB47DB27DB17DBA7DA27DBF7DB57DB87DAD7DD27DC77DAC0000 BB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7F707FE07FE17FDF805E805A808781508180818F8188818A817F818281E781FA 82078214821E824B84C984BF84C684C48499849E84B2849C84CB84B884C084D3 849084BC84D184CA873F871C873B872287258734871887558737872988F38902 88F488F988F888FD88E8891A88EF8AA68A8C8A9E8AA38A8D8AA18A938AA40000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008AAA8AA58AA88A988A918A9A8AA78C6A8C8D8C8C8CD38CD18CD28D6B8D99 8D958DFC8F148F128F158F138FA390609058905C90639059905E9062905D905B 91199118911E917591789177917492789280928592989296927B9293929C92A8 927C929195A195A895A995A395A595A49699969C969B96CC96D29700977C9785 97F69817981898AF98B199039905990C990999C19AAF9AB09AE69B419B429CF4 9CF69CF39EBC9F3B9F4A5104510050FB50F550F9510251085109510551DC0000 BC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 528752885289528D528A52F053B2562E563B56395632563F563456295653564E 565756745636562F56305880589F589E58B3589C58AE58A958A6596D5B095AFB 5B0B5AF55B0C5B085BEE5BEC5BE95BEB5C645C655D9D5D945E625E5F5E615EE2 5EDA5EDF5EDD5EE35EE05F485F715FB75FB561766167616E615D615561820000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000617C6170616B617E61A7619061AB618E61AC619A61A4619461AE622E6469 646F6479649E64B26488649064B064A56493649564A9649264AE64AD64AB649A 64AC649964A264B365756577657866AE66AB66B466B16A236A1F69E86A016A1E 6A1969FD6A216A136A0A69F36A026A0569ED6A116B506B4E6BA46BC56BC66F3F 6F7C6F846F516F666F546F866F6D6F5B6F786F6E6F8E6F7A6F706F646F976F58 6ED56F6F6F606F5F719F71AC71B171A87256729B734E73577469748B74830000 BD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 747E7480757F76207629761F7624762676217622769A76BA76E4778E7787778C 7791778B78CB78C578BA78CA78BE78D578BC78D07A3F7A3C7A407A3D7A377A3B 7AAF7AAE7BAD7BB17BC47BB47BC67BC77BC17BA07BCC7CCA7DE07DF47DEF7DFB 7DD87DEC7DDD7DE87DE37DDA7DDE7DE97D9E7DD97DF27DF97F757F777FAF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007FE98026819B819C819D81A0819A81988517853D851A84EE852C852D8513 851185238521851484EC852584FF850687828774877687608766877887688759 8757874C8753885B885D89108907891289138915890A8ABC8AD28AC78AC48A95 8ACB8AF88AB28AC98AC28ABF8AB08AD68ACD8AB68AB98ADB8C4C8C4E8C6C8CE0 8CDE8CE68CE48CEC8CED8CE28CE38CDC8CEA8CE18D6D8D9F8DA38E2B8E108E1D 8E228E0F8E298E1F8E218E1E8EBA8F1D8F1B8F1F8F298F268F2A8F1C8F1E0000 BE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8F259069906E9068906D90779130912D9127913191879189918B918392C592BB 92B792EA92AC92E492C192B392BC92D292C792F092B295AD95B1970497069707 97099760978D978B978F9821982B981C98B3990A99139912991899DD99D099DF 99DB99D199D599D299D99AB79AEE9AEF9B279B459B449B779B6F9D069D090000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009D039EA99EBE9ECE58A89F5251125118511451105115518051AA51DD5291 529352F35659566B5679566956645678566A566856655671566F566C56625676 58C158BE58C758C5596E5B1D5B345B785BF05C0E5F4A61B2619161A9618A61CD 61B661BE61CA61C8623064C564C164CB64BB64BC64DA64C464C764C264CD64BF 64D264D464BE657466C666C966B966C466C766B86A3D6A386A3A6A596A6B6A58 6A396A446A626A616A4B6A476A356A5F6A486B596B776C056FC26FB16FA10000 BF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6FC36FA46FC16FA76FB36FC06FB96FB66FA66FA06FB471BE71C971D071D271C8 71D571B971CE71D971DC71C371C47368749C74A37498749F749E74E2750C750D 76347638763A76E776E577A0779E779F77A578E878DA78EC78E779A67A4D7A4E 7A467A4C7A4B7ABA7BD97C117BC97BE47BDB7BE17BE97BE67CD57CD67E0A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007E117E087E1B7E237E1E7E1D7E097E107F797FB27FF07FF17FEE802881B3 81A981A881FB820882588259854A855985488568856985438549856D856A855E 8783879F879E87A2878D8861892A89328925892B892189AA89A68AE68AFA8AEB 8AF18B008ADC8AE78AEE8AFE8B018B028AF78AED8AF38AF68AFC8C6B8C6D8C93 8CF48E448E318E348E428E398E358F3B8F2F8F388F338FA88FA6907590749078 9072907C907A913491929320933692F89333932F932292FC932B9304931A0000 C0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9310932693219315932E931995BB96A796A896AA96D5970E97119716970D9713 970F975B975C9766979898309838983B9837982D9839982499109928991E991B 9921991A99ED99E299F19AB89ABC9AFB9AED9B289B919D159D239D269D289D12 9D1B9ED89ED49F8D9F9C512A511F5121513252F5568E56805690568556870000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000568F58D558D358D158CE5B305B2A5B245B7A5C375C685DBC5DBA5DBD5DB8 5E6B5F4C5FBD61C961C261C761E661CB6232623464CE64CA64D864E064F064E6 64EC64F164E264ED6582658366D966D66A806A946A846AA26A9C6ADB6AA36A7E 6A976A906AA06B5C6BAE6BDA6C086FD86FF16FDF6FE06FDB6FE46FEB6FEF6F80 6FEC6FE16FE96FD56FEE6FF071E771DF71EE71E671E571ED71EC71F471E07235 72467370737274A974B074A674A876467642764C76EA77B377AA77B077AC0000 C1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 77A777AD77EF78F778FA78F478EF790179A779AA7A577ABF7C077C0D7BFE7BF7 7C0C7BE07CE07CDC7CDE7CE27CDF7CD97CDD7E2E7E3E7E467E377E327E437E2B 7E3D7E317E457E417E347E397E487E357E3F7E2F7F447FF37FFC807180728070 806F807381C681C381BA81C281C081BF81BD81C981BE81E88209827185AA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008584857E859C8591859485AF859B858785A8858A866787C087D187B387D2 87C687AB87BB87BA87C887CB893B893689448938893D89AC8B0E8B178B198B1B 8B0A8B208B1D8B048B108C418C3F8C738CFA8CFD8CFC8CF88CFB8DA88E498E4B 8E488E4A8F448F3E8F428F458F3F907F907D9084908190829080913991A3919E 919C934D938293289375934A9365934B9318937E936C935B9370935A935495CA 95CB95CC95C895C696B196B896D6971C971E97A097D3984698B699359A010000 C2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 99FF9BAE9BAB9BAA9BAD9D3B9D3F9E8B9ECF9EDE9EDC9EDD9EDB9F3E9F4B53E2 569556AE58D958D85B385F5D61E3623364F464F264FE650664FA64FB64F765B7 66DC67266AB36AAC6AC36ABB6AB86AC26AAE6AAF6B5F6B786BAF7009700B6FFE 70066FFA7011700F71FB71FC71FE71F87377737574A774BF7515765676580000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000765277BD77BF77BB77BC790E79AE7A617A627A607AC47AC57C2B7C277C2A 7C1E7C237C217CE77E547E557E5E7E5A7E617E527E597F487FF97FFB80778076 81CD81CF820A85CF85A985CD85D085C985B085BA85B985A687EF87EC87F287E0 898689B289F48B288B398B2C8B2B8C508D058E598E638E668E648E5F8E558EC0 8F498F4D90879083908891AB91AC91D09394938A939693A293B393AE93AC93B0 9398939A939795D495D695D095D596E296DC96D996DB96DE972497A397A60000 C3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 97AD97F9984D984F984C984E985398BA993E993F993D992E99A59A0E9AC19B03 9B069B4F9B4E9B4D9BCA9BC99BFD9BC89BC09D519D5D9D609EE09F159F2C5133 56A558DE58DF58E25BF59F905EEC61F261F761F661F56500650F66E066DD6AE5 6ADD6ADA6AD3701B701F7028701A701D701570187206720D725872A273780000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000737A74BD74CA74E375877586765F766177C7791979B17A6B7A697C3E7C3F 7C387C3D7C377C407E6B7E6D7E797E697E6A7F857E737FB67FB97FB881D885E9 85DD85EA85D585E485E585F787FB8805880D87F987FE8960895F8956895E8B41 8B5C8B588B498B5A8B4E8B4F8B468B598D088D0A8E7C8E728E878E768E6C8E7A 8E748F548F4E8FAD908A908B91B191AE93E193D193DF93C393C893DC93DD93D6 93E293CD93D893E493D793E895DC96B496E3972A9727976197DC97FB985E0000 C4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9858985B98BC994599499A169A199B0D9BE89BE79BD69BDB9D899D619D729D6A 9D6C9E929E979E939EB452F856A856B756B656B456BC58E45B405B435B7D5BF6 5DC961F861FA65186514651966E667276AEC703E703070327210737B74CF7662 76657926792A792C792B7AC77AF67C4C7C437C4D7CEF7CF08FAE7E7D7E7C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007E827F4C800081DA826685FB85F9861185FA8606860B8607860A88148815 896489BA89F88B708B6C8B668B6F8B5F8B6B8D0F8D0D8E898E818E858E8291B4 91CB9418940393FD95E1973098C49952995199A89A2B9A309A379A359C139C0D 9E799EB59EE89F2F9F5F9F639F615137513856C156C056C259145C6C5DCD61FC 61FE651D651C659566E96AFB6B046AFA6BB2704C721B72A774D674D4766977D3 7C507E8F7E8C7FBC8617862D861A882388228821881F896A896C89BD8B740000 C5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8B778B7D8D138E8A8E8D8E8B8F5F8FAF91BA942E94339435943A94389432942B 95E297389739973297FF9867986599579A459A439A409A3E9ACF9B549B519C2D 9C259DAF9DB49DC29DB89E9D9EEF9F199F5C9F669F67513C513B56C856CA56C9 5B7F5DD45DD25F4E61FF65246B0A6B6170517058738074E4758A766E766C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000079B37C607C5F807E807D81DF8972896F89FC8B808D168D178E918E938F61 9148944494519452973D973E97C397C1986B99559A559A4D9AD29B1A9C499C31 9C3E9C3B9DD39DD79F349F6C9F6A9F9456CC5DD662006523652B652A66EC6B10 74DA7ACA7C647C637C657E937E967E9481E28638863F88318B8A9090908F9463 946094649768986F995C9A5A9A5B9A579AD39AD49AD19C549C579C569DE59E9F 9EF456D158E9652C705E7671767277D77F507F888836883988628B938B920000 C6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8B9682778D1B91C0946A97429748974497C698709A5F9B229B589C5F9DF99DFA 9E7C9E7D9F079F779F725EF36B1670637C6C7C6E883B89C08EA191C194729470 9871995E9AD69B239ECC706477DA8B9A947797C99A629A657E9C8B9C8EAA91C5 947D947E947C9C779C789EF78C54947F9E1A72289A6A9B319E1B9E1E7C720000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 C9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E424E5C51F5531A53824E074E0C4E474E8D56D7FA0C5C6E5F734E0F51874E0E 4E2E4E934EC24EC94EC8519852FC536C53B957205903592C5C105DFF65E16BB3 6BCC6C14723F4E314E3C4EE84EDC4EE94EE14EDD4EDA520C531C534C57225723 5917592F5B815B845C125C3B5C745C735E045E805E825FC9620962506C150000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006C366C436C3F6C3B72AE72B0738A79B8808A961E4F0E4F184F2C4EF54F14 4EF14F004EF74F084F1D4F024F054F224F134F044EF44F1251B1521352095210 52A65322531F534D538A540756E156DF572E572A5734593C5980597C5985597B 597E5977597F5B565C155C255C7C5C7A5C7B5C7E5DDF5E755E845F025F1A5F74 5FD55FD45FCF625C625E626462616266626262596260625A626565EF65EE673E 67396738673B673A673F673C67336C186C466C526C5C6C4F6C4A6C546C4B0000 CA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6C4C7071725E72B472B5738E752A767F7A757F518278827C8280827D827F864D 897E909990979098909B909496229624962096234F564F3B4F624F494F534F64 4F3E4F674F524F5F4F414F584F2D4F334F3F4F61518F51B9521C521E522152AD 52AE530953635372538E538F54305437542A545454455419541C542554180000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000543D544F544154285424544756EE56E756E557415745574C5749574B5752 5906594059A6599859A05997598E59A25990598F59A759A15B8E5B925C285C2A 5C8D5C8F5C885C8B5C895C925C8A5C865C935C955DE05E0A5E0E5E8B5E895E8C 5E885E8D5F055F1D5F785F765FD25FD15FD05FED5FE85FEE5FF35FE15FE45FE3 5FFA5FEF5FF75FFB60005FF4623A6283628C628E628F629462876271627B627A 6270628162886277627D62726274653765F065F465F365F265F5674567470000 CB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 67596755674C6748675D674D675A674B6BD06C196C1A6C786C676C6B6C846C8B 6C8F6C716C6F6C696C9A6C6D6C876C956C9C6C666C736C656C7B6C8E7074707A 726372BF72BD72C372C672C172BA72C573957397739373947392753A75397594 75957681793D80348095809980908092809C8290828F8285828E829182930000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000828A828382848C788FC98FBF909F90A190A5909E90A790A096309628962F 962D4E334F984F7C4F854F7D4F804F874F764F744F894F844F774F4C4F974F6A 4F9A4F794F814F784F904F9C4F944F9E4F924F824F954F6B4F6E519E51BC51BE 5235523252335246523152BC530A530B533C539253945487547F548154915482 5488546B547A547E5465546C54745466548D546F546154605498546354675464 56F756F9576F5772576D576B57715770577657805775577B5773577457620000 CC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5768577D590C594559B559BA59CF59CE59B259CC59C159B659BC59C359D659B1 59BD59C059C859B459C75B625B655B935B955C445C475CAE5CA45CA05CB55CAF 5CA85CAC5C9F5CA35CAD5CA25CAA5CA75C9D5CA55CB65CB05CA65E175E145E19 5F285F225F235F245F545F825F7E5F7D5FDE5FE5602D602660196032600B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006034600A60176033601A601E602C6022600D6010602E60136011600C6009 601C6214623D62AD62B462D162BE62AA62B662CA62AE62B362AF62BB62A962B0 62B8653D65A865BB660965FC66046612660865FB6603660B660D660565FD6611 661066F6670A6785676C678E67926776677B6798678667846774678D678C677A 679F679167996783677D67816778677967946B256B806B7E6BDE6C1D6C936CEC 6CEB6CEE6CD96CB66CD46CAD6CE76CB76CD06CC26CBA6CC36CC66CED6CF20000 CD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6CD26CDD6CB46C8A6C9D6C806CDE6CC06D306CCD6CC76CB06CF96CCF6CE96CD1 709470987085709370867084709170967082709A7083726A72D672CB72D872C9 72DC72D272D472DA72CC72D173A473A173AD73A673A273A073AC739D74DD74E8 753F7540753E758C759876AF76F376F176F076F577F877FC77F977FB77FA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077F77942793F79C57A787A7B7AFB7C757CFD8035808F80AE80A380B880B5 80AD822082A082C082AB829A8298829B82B582A782AE82BC829E82BA82B482A8 82A182A982C282A482C382B682A28670866F866D866E8C568FD28FCB8FD38FCD 8FD68FD58FD790B290B490AF90B390B09639963D963C963A96434FCD4FC54FD3 4FB24FC94FCB4FC14FD44FDC4FD94FBB4FB34FDB4FC74FD64FBA4FC04FB94FEC 5244524952C052C2533D537C539753965399539854BA54A154AD54A554CF0000 CE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54C3830D54B754AE54D654B654C554C654A0547054BC54A254BE547254DE54B0 57B5579E579F57A4578C5797579D579B57945798578F579957A5579A579558F4 590D595359E159DE59EE5A0059F159DD59FA59FD59FC59F659E459F259F759DB 59E959F359F559E059FE59F459ED5BA85C4C5CD05CD85CCC5CD75CCB5CDB0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005CDE5CDA5CC95CC75CCA5CD65CD35CD45CCF5CC85CC65CCE5CDF5CF85DF9 5E215E225E235E205E245EB05EA45EA25E9B5EA35EA55F075F2E5F565F866037 603960546072605E6045605360476049605B604C60406042605F602460446058 6066606E6242624362CF630D630B62F5630E630362EB62F9630F630C62F862F6 63006313631462FA631562FB62F06541654365AA65BF6636662166326635661C 662666226633662B663A661D66346639662E670F671067C167F267C867BA0000 CF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 67DC67BB67F867D867C067B767C567EB67E467DF67B567CD67B367F767F667EE 67E367C267B967CE67E767F067B267FC67C667ED67CC67AE67E667DB67FA67C9 67CA67C367EA67CB6B286B826B846BB66BD66BD86BE06C206C216D286D346D2D 6D1F6D3C6D3F6D126D0A6CDA6D336D046D196D3A6D1A6D116D006D1D6D420000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D016D186D376D036D0F6D406D076D206D2C6D086D226D096D1070B7709F 70BE70B170B070A170B470B570A972417249724A726C72707273726E72CA72E4 72E872EB72DF72EA72E672E3738573CC73C273C873C573B973B673B573B473EB 73BF73C773BE73C373C673B873CB74EC74EE752E7547754875A775AA767976C4 7708770377047705770A76F776FB76FA77E777E878067811781278057810780F 780E780978037813794A794C794B7945794479D579CD79CF79D679CE7A800000 D0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7A7E7AD17B007B017C7A7C787C797C7F7C807C817D037D087D017F587F917F8D 7FBE8007800E800F8014803780D880C780E080D180C880C280D080C580E380D9 80DC80CA80D580C980CF80D780E680CD81FF8221829482D982FE82F9830782E8 830082D5833A82EB82D682F482EC82E182F282F5830C82FB82F682F082EA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000082E482E082FA82F382ED86778674867C86738841884E8867886A886989D3 8A048A078D728FE38FE18FEE8FE090F190BD90BF90D590C590BE90C790CB90C8 91D491D39654964F96519653964A964E501E50055007501350225030501B4FF5 4FF450335037502C4FF64FF75017501C502050275035502F5031500E515A5194 519351CA51C451C551C851CE5261525A5252525E525F5255526252CD530E539E 552654E25517551254E754F354E4551A54FF5504550854EB5511550554F10000 D1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 550A54FB54F754F854E0550E5503550B5701570257CC583257D557D257BA57C6 57BD57BC57B857B657BF57C757D057B957C1590E594A5A195A165A2D5A2E5A15 5A0F5A175A0A5A1E5A335B6C5BA75BAD5BAC5C035C565C545CEC5CFF5CEE5CF1 5CF75D005CF95E295E285EA85EAE5EAA5EAC5F335F305F67605D605A60670000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000604160A26088608060926081609D60836095609B60976087609C608E6219 624662F263106356632C634463456336634363E46339634B634A633C63296341 6334635863546359632D63476333635A63516338635763406348654A654665C6 65C365C465C2664A665F6647665167126713681F681A684968326833683B684B 684F68166831681C6835682B682D682F684E68446834681D6812681468266828 682E684D683A682568206B2C6B2F6B2D6B316B346B6D80826B886BE66BE40000 D2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6BE86BE36BE26BE76C256D7A6D636D646D766D0D6D616D926D586D626D6D6D6F 6D916D8D6DEF6D7F6D866D5E6D676D606D976D706D7C6D5F6D826D986D2F6D68 6D8B6D7E6D806D846D166D836D7B6D7D6D756D9070DC70D370D170DD70CB7F39 70E270D770D270DE70E070D470CD70C570C670C770DA70CE70E1724272780000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000072777276730072FA72F472FE72F672F372FB730173D373D973E573D673BC 73E773E373E973DC73D273DB73D473DD73DA73D773D873E874DE74DF74F474F5 7521755B755F75B075C175BB75C475C075BF75B675BA768A76C9771D771B7710 771377127723771177157719771A772277277823782C78227835782F7828782E 782B782178297833782A78317954795B794F795C79537952795179EB79EC79E0 79EE79ED79EA79DC79DE79DD7A867A897A857A8B7A8C7A8A7A877AD87B100000 D3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7B047B137B057B0F7B087B0A7B0E7B097B127C847C917C8A7C8C7C887C8D7C85 7D1E7D1D7D117D0E7D187D167D137D1F7D127D0F7D0C7F5C7F617F5E7F607F5D 7F5B7F967F927FC37FC27FC08016803E803980FA80F280F980F5810180FB8100 8201822F82258333832D83448319835183258356833F83418326831C83220000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008342834E831B832A8308833C834D8316832483208337832F832983478345 834C8353831E832C834B832783488653865286A286A88696868D8691869E8687 86978686868B869A868586A5869986A186A786958698868E869D869086948843 8844886D88758876887288808871887F886F8883887E8874887C8A128C478C57 8C7B8CA48CA38D768D788DB58DB78DB68ED18ED38FFE8FF590028FFF8FFB9004 8FFC8FF690D690E090D990DA90E390DF90E590D890DB90D790DC90E491500000 D4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 914E914F91D591E291DA965C965F96BC98E39ADF9B2F4E7F5070506A5061505E 50605053504B505D50725048504D5041505B504A506250155045505F5069506B 5063506450465040506E50735057505151D0526B526D526C526E52D652D3532D 539C55755576553C554D55505534552A55515562553655355530555255450000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000550C55325565554E55395548552D553B5540554B570A570757FB581457E2 57F657DC57F4580057ED57FD580857F8580B57F357CF580757EE57E357F257E5 57EC57E1580E57FC581057E75801580C57F157E957F0580D5804595C5A605A58 5A555A675A5E5A385A355A6D5A505A5F5A655A6C5A535A645A575A435A5D5A52 5A445A5B5A485A8E5A3E5A4D5A395A4C5A705A695A475A515A565A425A5C5B72 5B6E5BC15BC05C595D1E5D0B5D1D5D1A5D205D0C5D285D0D5D265D255D0F0000 D5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5D305D125D235D1F5D2E5E3E5E345EB15EB45EB95EB25EB35F365F385F9B5F96 5F9F608A6090608660BE60B060BA60D360D460CF60E460D960DD60C860B160DB 60B760CA60BF60C360CD60C063326365638A6382637D63BD639E63AD639D6397 63AB638E636F63876390636E63AF6375639C636D63AE637C63A4633B639F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006378638563816391638D6370655365CD66656661665B6659665C66626718 687968876890689C686D686E68AE68AB6956686F68A368AC68A96875687468B2 688F68776892687C686B687268AA68806871687E689B6896688B68A0688968A4 6878687B6891688C688A687D6B366B336B376B386B916B8F6B8D6B8E6B8C6C2A 6DC06DAB6DB46DB36E746DAC6DE96DE26DB76DF66DD46E006DC86DE06DDF6DD6 6DBE6DE56DDC6DDD6DDB6DF46DCA6DBD6DED6DF06DBA6DD56DC26DCF6DC90000 D6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6DD06DF26DD36DFD6DD76DCD6DE36DBB70FA710D70F7711770F4710C70F07104 70F3711070FC70FF71067113710070F870F6710B7102710E727E727B727C727F 731D7317730773117318730A730872FF730F731E738873F673F873F574047401 73FD7407740073FA73FC73FF740C740B73F474087564756375CE75D275CF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075CB75CC75D175D0768F768976D37739772F772D7731773277347733773D 7725773B7735784878527849784D784A784C782678457850796479677969796A 7963796B796179BB79FA79F879F679F77A8F7A947A907B357B477B347B257B30 7B227B247B337B187B2A7B1D7B317B2B7B2D7B2F7B327B387B1A7B237C947C98 7C967CA37D357D3D7D387D367D3A7D457D2C7D297D417D477D3E7D3F7D4A7D3B 7D287F637F957F9C7F9D7F9B7FCA7FCB7FCD7FD07FD17FC77FCF7FC9801F0000 D7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 801E801B804780438048811881258119811B812D811F812C811E812181158127 811D8122821182388233823A823482328274839083A383A8838D837A837383A4 8374838F8381839583998375839483A9837D8383838C839D839B83AA838B837E 83A583AF8388839783B0837F83A6838783AE8376839A8659865686BF86B70000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000086C286C186C586BA86B086C886B986B386B886CC86B486BB86BC86C386BD 86BE88528889889588A888A288AA889A889188A1889F889888A78899889B8897 88A488AC888C8893888E898289D689D989D58A308A278A2C8A1E8C398C3B8C5C 8C5D8C7D8CA58D7D8D7B8D798DBC8DC28DB98DBF8DC18ED88EDE8EDD8EDC8ED7 8EE08EE19024900B9011901C900C902190EF90EA90F090F490F290F390D490EB 90EC90E991569158915A9153915591EC91F491F191F391F891E491F991EA0000 D8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 91EB91F791E891EE957A95869588967C966D966B9671966F96BF976A980498E5 9997509B50955094509E508B50A35083508C508E509D5068509C509250825087 515F51D45312531153A453A7559155A855A555AD5577564555A255935588558F 55B5558155A3559255A4557D558C55A6557F559555A1558E570C582958370000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005819581E58275823582857F558485825581C581B5833583F5836582E5839 5838582D582C583B59615AAF5A945A9F5A7A5AA25A9E5A785AA65A7C5AA55AAC 5A955AAE5A375A845A8A5A975A835A8B5AA95A7B5A7D5A8C5A9C5A8F5A935A9D 5BEA5BCD5BCB5BD45BD15BCA5BCE5C0C5C305D375D435D6B5D415D4B5D3F5D35 5D515D4E5D555D335D3A5D525D3D5D315D595D425D395D495D385D3C5D325D36 5D405D455E445E415F585FA65FA55FAB60C960B960CC60E260CE60C461140000 D9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 60F2610A6116610560F5611360F860FC60FE60C161036118611D611060FF6104 610B624A639463B163B063CE63E563E863EF63C3649D63F363CA63E063F663D5 63F263F5646163DF63BE63DD63DC63C463D863D363C263C763CC63CB63C863F0 63D763D965326567656A6564655C65686565658C659D659E65AE65D065D20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000667C666C667B668066716679666A66726701690C68D3690468DC692A68EC 68EA68F1690F68D668F768EB68E468F66913691068F368E1690768CC69086970 68B4691168EF68C6691468F868D068FD68FC68E8690B690A691768CE68C868DD 68DE68E668F468D1690668D468E96915692568C76B396B3B6B3F6B3C6B946B97 6B996B956BBD6BF06BF26BF36C306DFC6E466E476E1F6E496E886E3C6E3D6E45 6E626E2B6E3F6E416E5D6E736E1C6E336E4B6E406E516E3B6E036E2E6E5E0000 DA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6E686E5C6E616E316E286E606E716E6B6E396E226E306E536E656E276E786E64 6E776E556E796E526E666E356E366E5A7120711E712F70FB712E713171237125 71227132711F7128713A711B724B725A7288728972867285728B7312730B7330 73227331733373277332732D732673237335730C742E742C7430742B74160000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000741A7421742D743174247423741D74297420743274FB752F756F756C75E7 75DA75E175E675DD75DF75E475D77695769276DA774677477744774D7745774A 774E774B774C77DE77EC786078647865785C786D7871786A786E787078697868 785E786279747973797279707A027A0A7A037A0C7A047A997AE67AE47B4A7B3B 7B447B487B4C7B4E7B407B587B457CA27C9E7CA87CA17D587D6F7D637D537D56 7D677D6A7D4F7D6D7D5C7D6B7D527D547D697D517D5F7D4E7F3E7F3F7F650000 DB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7F667FA27FA07FA17FD78051804F805080FE80D48143814A8152814F8147813D 814D813A81E681EE81F781F881F98204823C823D823F8275833B83CF83F98423 83C083E8841283E783E483FC83F6841083C683C883EB83E383BF840183DD83E5 83D883FF83E183CB83CE83D683F583C98409840F83DE8411840683C283F30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000083D583FA83C783D183EA841383C383EC83EE83C483FB83D783E2841B83DB 83FE86D886E286E686D386E386DA86EA86DD86EB86DC86EC86E986D786E886D1 88488856885588BA88D788B988B888C088BE88B688BC88B788BD88B2890188C9 89958998899789DD89DA89DB8A4E8A4D8A398A598A408A578A588A448A458A52 8A488A518A4A8A4C8A4F8C5F8C818C808CBA8CBE8CB08CB98CB58D848D808D89 8DD88DD38DCD8DC78DD68DDC8DCF8DD58DD98DC88DD78DC58EEF8EF78EFA0000 DC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8EF98EE68EEE8EE58EF58EE78EE88EF68EEB8EF18EEC8EF48EE9902D9034902F 9106912C910490FF90FC910890F990FB9101910091079105910391619164915F 916291609201920A92259203921A9226920F920C9200921291FF91FD92069204 92279202921C92249219921792059216957B958D958C95909687967E96880000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000096899683968096C296C896C396F196F0976C9770976E980798A998EB9CE6 9EF94E834E844EB650BD50BF50C650AE50C450CA50B450C850C250B050C150BA 50B150CB50C950B650B851D7527A5278527B527C55C355DB55CC55D055CB55CA 55DD55C055D455C455E955BF55D2558D55CF55D555E255D655C855F255CD55D9 55C25714585358685864584F584D5849586F5855584E585D58595865585B583D 5863587158FC5AC75AC45ACB5ABA5AB85AB15AB55AB05ABF5AC85ABB5AC60000 DD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5AB75AC05ACA5AB45AB65ACD5AB95A905BD65BD85BD95C1F5C335D715D635D4A 5D655D725D6C5D5E5D685D675D625DF05E4F5E4E5E4A5E4D5E4B5EC55ECC5EC6 5ECB5EC75F405FAF5FAD60F76149614A612B614561366132612E6146612F614F 612961406220916862236225622463C563F163EB641064126409642064240000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000064336443641F641564186439643764226423640C64266430642864416435 642F640A641A644064256427640B63E7641B642E6421640E656F659265D36686 668C66956690668B668A66996694667867206966695F6938694E69626971693F 6945696A6939694269576959697A694869496935696C6933693D696568F06978 693469696940696F69446976695869416974694C693B694B6937695C694F6951 69326952692F697B693C6B466B456B436B426B486B416B9BFA0D6BFB6BFC0000 DE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6BF96BF76BF86E9B6ED66EC86E8F6EC06E9F6E936E946EA06EB16EB96EC66ED2 6EBD6EC16E9E6EC96EB76EB06ECD6EA66ECF6EB26EBE6EC36EDC6ED86E996E92 6E8E6E8D6EA46EA16EBF6EB36ED06ECA6E976EAE6EA371477154715271637160 7141715D716271727178716A7161714271587143714B7170715F715071530000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007144714D715A724F728D728C72917290728E733C7342733B733A7340734A 73497444744A744B7452745174577440744F7450744E74427446744D745474E1 74FF74FE74FD751D75797577698375EF760F760375F775FE75FC75F975F87610 75FB75F675ED75F575FD769976B576DD7755775F776077527756775A77697767 77547759776D77E07887789A7894788F788478957885788678A1788378797899 78807896787B797C7982797D79797A117A187A197A127A177A157A227A130000 DF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7A1B7A107AA37AA27A9E7AEB7B667B647B6D7B747B697B727B657B737B717B70 7B617B787B767B637CB27CB47CAF7D887D867D807D8D7D7F7D857D7A7D8E7D7B 7D837D7C7D8C7D947D847D7D7D927F6D7F6B7F677F687F6C7FA67FA57FA77FDB 7FDC8021816481608177815C8169815B816281726721815E81768167816F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000081448161821D8249824482408242824584F1843F845684768479848F848D 846584518440848684678430844D847D845A845984748473845D8507845E8437 843A8434847A8443847884328445842983D9844B842F8442842D845F84708439 844E844C8452846F84C5848E843B8447843684338468847E8444842B84608454 846E8450870B870486F7870C86FA86D686F5874D86F8870E8709870186F6870D 870588D688CB88CD88CE88DE88DB88DA88CC88D08985899B89DF89E589E40000 E0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 89E189E089E289DC89E68A768A868A7F8A618A3F8A778A828A848A758A838A81 8A748A7A8C3C8C4B8C4A8C658C648C668C868C848C858CCC8D688D698D918D8C 8D8E8D8F8D8D8D938D948D908D928DF08DE08DEC8DF18DEE8DD08DE98DE38DE2 8DE78DF28DEB8DF48F068EFF8F018F008F058F078F088F028F0B9052903F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000090449049903D9110910D910F911191169114910B910E916E916F92489252 9230923A926692339265925E9283922E924A9246926D926C924F92609267926F 92369261927092319254926392509272924E9253924C92569232959F959C959E 959B969296939691969796CE96FA96FD96F896F59773977797789772980F980D 980E98AC98F698F999AF99B299B099B59AAD9AAB9B5B9CEA9CED9CE79E809EFD 50E650D450D750E850F350DB50EA50DD50E450D350EC50F050EF50E350E00000 E1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 51D85280528152E952EB533053AC56275615560C561255FC560F561C56015613 560255FA561D560455FF55F95889587C5890589858865881587F5874588B587A 58875891588E587658825888587B5894588F58FE596B5ADC5AEE5AE55AD55AEA 5ADA5AED5AEB5AF35AE25AE05ADB5AEC5ADE5ADD5AD95AE85ADF5B775BE00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005BE35C635D825D805D7D5D865D7A5D815D775D8A5D895D885D7E5D7C5D8D 5D795D7F5E585E595E535ED85ED15ED75ECE5EDC5ED55ED95ED25ED45F445F43 5F6F5FB6612C61286141615E61716173615261536172616C618061746154617A 615B6165613B616A6161615662296227622B642B644D645B645D647464766472 6473647D6475646664A6644E6482645E645C644B645364606450647F643F646C 646B645964656477657365A066A166A0669F67056704672269B169B669C90000 E2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 69A069CE699669B069AC69BC69916999698E69A7698D69A969BE69AF69BF69C4 69BD69A469D469B969CA699A69CF69B3699369AA69A1699E69D96997699069C2 69B569A569C66B4A6B4D6B4B6B9E6B9F6BA06BC36BC46BFE6ECE6EF56EF16F03 6F256EF86F376EFB6F2E6F096F4E6F196F1A6F276F186F3B6F126EED6F0A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006F366F736EF96EEE6F2D6F406F306F3C6F356EEB6F076F0E6F436F056EFD 6EF66F396F1C6EFC6F3A6F1F6F0D6F1E6F086F21718771907189718071857182 718F717B718671817197724472537297729572937343734D7351734C74627473 7471747574727467746E750075027503757D759076167608760C76157611760A 761476B87781777C77857782776E7780776F777E778378B278AA78B478AD78A8 787E78AB789E78A578A078AC78A278A47998798A798B79967995799479930000 E3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 79977988799279907A2B7A4A7A307A2F7A287A267AA87AAB7AAC7AEE7B887B9C 7B8A7B917B907B967B8D7B8C7B9B7B8E7B857B9852847B997BA47B827CBB7CBF 7CBC7CBA7DA77DB77DC27DA37DAA7DC17DC07DC57D9D7DCE7DC47DC67DCB7DCC 7DAF7DB97D967DBC7D9F7DA67DAE7DA97DA17DC97F737FE27FE37FE57FDE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008024805D805C8189818681838187818D818C818B8215849784A484A1849F 84BA84CE84C284AC84AE84AB84B984B484C184CD84AA849A84B184D0849D84A7 84BB84A2849484C784CC849B84A984AF84A884D6849884B684CF84A084D784D4 84D284DB84B084918661873387238728876B8740872E871E87218719871B8743 872C8741873E874687208732872A872D873C8712873A87318735874287268727 87388724871A8730871188F788E788F188F288FA88FE88EE88FC88F688FB0000 E4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 88F088EC88EB899D89A1899F899E89E989EB89E88AAB8A998A8B8A928A8F8A96 8C3D8C688C698CD58CCF8CD78D968E098E028DFF8E0D8DFD8E0A8E038E078E06 8E058DFE8E008E048F108F118F0E8F0D9123911C91209122911F911D911A9124 9121911B917A91729179917392A592A49276929B927A92A0929492AA928D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000092A6929A92AB92799297927F92A392EE928E9282929592A2927D928892A1 928A9286928C929992A7927E928792A9929D928B922D969E96A196FF9758977D 977A977E978397809782977B97849781977F97CE97CD981698AD98AE99029900 9907999D999C99C399B999BB99BA99C299BD99C79AB19AE39AE79B3E9B3F9B60 9B619B5F9CF19CF29CF59EA750FF5103513050F85106510750F650FE510B510C 50FD510A528B528C52F152EF56485642564C56355641564A5649564656580000 E5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 565A56405633563D562C563E5638562A563A571A58AB589D58B158A058A358AF 58AC58A558A158FF5AFF5AF45AFD5AF75AF65B035AF85B025AF95B015B075B05 5B0F5C675D995D975D9F5D925DA25D935D955DA05D9C5DA15D9A5D9E5E695E5D 5E605E5C7DF35EDB5EDE5EE15F495FB2618B6183617961B161B061A261890000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000619B619361AF61AD619F619261AA61A1618D616661B3622D646E64706496 64A064856497649C648F648B648A648C64A3649F646864B164986576657A6579 657B65B265B366B566B066A966B266B766AA66AF6A006A066A1769E569F86A15 69F169E46A2069FF69EC69E26A1B6A1D69FE6A2769F269EE6A1469F769E76A40 6A0869E669FB6A0D69FC69EB6A096A046A186A256A0F69F66A266A0769F46A16 6B516BA56BA36BA26BA66C016C006BFF6C026F416F266F7E6F876FC66F920000 E6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6F8D6F896F8C6F626F4F6F856F5A6F966F766F6C6F826F556F726F526F506F57 6F946F936F5D6F006F616F6B6F7D6F676F906F536F8B6F696F7F6F956F636F77 6F6A6F7B71B271AF719B71B071A0719A71A971B5719D71A5719E71A471A171AA 719C71A771B37298729A73587352735E735F7360735D735B7361735A73590000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000736274877489748A74867481747D74857488747C747975087507757E7625 761E7619761D761C7623761A7628761B769C769D769E769B778D778F77897788 78CD78BB78CF78CC78D178CE78D478C878C378C478C9799A79A179A0799C79A2 799B6B767A397AB27AB47AB37BB77BCB7BBE7BAC7BCE7BAF7BB97BCA7BB57CC5 7CC87CCC7CCB7DF77DDB7DEA7DE77DD77DE17E037DFA7DE67DF67DF17DF07DEE 7DDF7F767FAC7FB07FAD7FED7FEB7FEA7FEC7FE67FE88064806781A3819F0000 E7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 819E819581A2819981978216824F825382528250824E82518524853B850F8500 8529850E8509850D851F850A8527851C84FB852B84FA8508850C84F4852A84F2 851584F784EB84F384FC851284EA84E9851684FE8528851D852E850284FD851E 84F68531852684E784E884F084EF84F9851885208530850B8519852F86620000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000875687638764877787E1877387588754875B87528761875A8751875E876D 876A8750874E875F875D876F876C877A876E875C8765874F877B877587628767 8769885A8905890C8914890B891789188919890689168911890E890989A289A4 89A389ED89F089EC8ACF8AC68AB88AD38AD18AD48AD58ABB8AD78ABE8AC08AC5 8AD88AC38ABA8ABD8AD98C3E8C4D8C8F8CE58CDF8CD98CE88CDA8CDD8CE78DA0 8D9C8DA18D9B8E208E238E258E248E2E8E158E1B8E168E118E198E268E270000 E8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8E148E128E188E138E1C8E178E1A8F2C8F248F188F1A8F208F238F168F179073 9070906F9067906B912F912B9129912A91329126912E91859186918A91819182 9184918092D092C392C492C092D992B692CF92F192DF92D892E992D792DD92CC 92EF92C292E892CA92C892CE92E692CD92D592C992E092DE92E792D192D30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000092B592E192C692B4957C95AC95AB95AE95B096A496A296D3970597089702 975A978A978E978897D097CF981E981D9826982998289820981B982798B29908 98FA9911991499169917991599DC99CD99CF99D399D499CE99C999D699D899CB 99D799CC9AB39AEC9AEB9AF39AF29AF19B469B439B679B749B719B669B769B75 9B709B689B649B6C9CFC9CFA9CFD9CFF9CF79D079D009CF99CFB9D089D059D04 9E839ED39F0F9F10511C51135117511A511151DE533453E156705660566E0000 E9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 567356665663566D5672565E5677571C571B58C858BD58C958BF58BA58C258BC 58C65B175B195B1B5B215B145B135B105B165B285B1A5B205B1E5BEF5DAC5DB1 5DA95DA75DB55DB05DAE5DAA5DA85DB25DAD5DAF5DB45E675E685E665E6F5EE9 5EE75EE65EE85EE55F4B5FBC619D61A8619661C561B461C661C161CC61BA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000061BF61B8618C64D764D664D064CF64C964BD648964C364DB64F364D96533 657F657C65A266C866BE66C066CA66CB66CF66BD66BB66BA66CC67236A346A66 6A496A676A326A686A3E6A5D6A6D6A766A5B6A516A286A5A6A3B6A3F6A416A6A 6A646A506A4F6A546A6F6A696A606A3C6A5E6A566A556A4D6A4E6A466B556B54 6B566BA76BAA6BAB6BC86BC76C046C036C066FAD6FCB6FA36FC76FBC6FCE6FC8 6F5E6FC46FBD6F9E6FCA6FA870046FA56FAE6FBA6FAC6FAA6FCF6FBF6FB80000 EA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6FA26FC96FAB6FCD6FAF6FB26FB071C571C271BF71B871D671C071C171CB71D4 71CA71C771CF71BD71D871BC71C671DA71DB729D729E736973667367736C7365 736B736A747F749A74A074947492749574A1750B7580762F762D7631763D7633 763C76357632763076BB76E6779A779D77A1779C779B77A277A3779577990000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000779778DD78E978E578EA78DE78E378DB78E178E278ED78DF78E079A47A44 7A487A477AB67AB87AB57AB17AB77BDE7BE37BE77BDD7BD57BE57BDA7BE87BF9 7BD47BEA7BE27BDC7BEB7BD87BDF7CD27CD47CD77CD07CD17E127E217E177E0C 7E1F7E207E137E0E7E1C7E157E1A7E227E0B7E0F7E167E0D7E147E257E247F43 7F7B7F7C7F7A7FB17FEF802A8029806C81B181A681AE81B981B581AB81B081AC 81B481B281B781A781F282558256825785568545856B854D8553856185580000 EB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 854085468564854185628544855185478563853E855B8571854E856E85758555 85678560858C8566855D85548565856C866386658664879B878F879787938792 87888781879687988779878787A3878587908791879D87848794879C879A8789 891E89268930892D892E89278931892289298923892F892C891F89F18AE00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008AE28AF28AF48AF58ADD8B148AE48ADF8AF08AC88ADE8AE18AE88AFF8AEF 8AFB8C918C928C908CF58CEE8CF18CF08CF38D6C8D6E8DA58DA78E338E3E8E38 8E408E458E368E3C8E3D8E418E308E3F8EBD8F368F2E8F358F328F398F378F34 90769079907B908690FA913391359136919391909191918D918F9327931E9308 931F9306930F937A9338933C931B9323931293019346932D930E930D92CB931D 92FA9325931392F992F793349302932492FF932993399335932A9314930C0000 EC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 930B92FE9309930092FB931695BC95CD95BE95B995BA95B695BF95B595BD96A9 96D4970B9712971097999797979497F097F89835982F98329924991F99279929 999E99EE99EC99E599E499F099E399EA99E999E79AB99ABF9AB49ABB9AF69AFA 9AF99AF79B339B809B859B879B7C9B7E9B7B9B829B939B929B909B7A9B950000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009B7D9B889D259D179D209D1E9D149D299D1D9D189D229D109D199D1F9E88 9E869E879EAE9EAD9ED59ED69EFA9F129F3D51265125512251245120512952F4 5693568C568D568656845683567E5682567F568158D658D458CF58D25B2D5B25 5B325B235B2C5B275B265B2F5B2E5B7B5BF15BF25DB75E6C5E6A5FBE5FBB61C3 61B561BC61E761E061E561E461E861DE64EF64E964E364EB64E464E865816580 65B665DA66D26A8D6A966A816AA56A896A9F6A9B6AA16A9E6A876A936A8E0000 ED 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A956A836AA86AA46A916A7F6AA66A9A6A856A8C6A926B5B6BAD6C096FCC6FA9 6FF46FD46FE36FDC6FED6FE76FE66FDE6FF26FDD6FE26FE871E171F171E871F2 71E471F071E27373736E736F749774B274AB749074AA74AD74B174A574AF7510 75117512750F7584764376487649764776A476E977B577AB77B277B777B60000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077B477B177A877F078F378FD790278FB78FC78F2790578F978FE790479AB 79A87A5C7A5B7A567A587A547A5A7ABE7AC07AC17C057C0F7BF27C007BFF7BFB 7C0E7BF47C0B7BF37C027C097C037C017BF87BFD7C067BF07BF17C107C0A7CE8 7E2D7E3C7E427E3398487E387E2A7E497E407E477E297E4C7E307E3B7E367E44 7E3A7F457F7F7F7E7F7D7FF47FF2802C81BB81C481CC81CA81C581C781BC81E9 825B825A825C85838580858F85A7859585A0858B85A3857B85A4859A859E0000 EE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8577857C858985A1857A85788557858E85968586858D8599859D858185A28582 858885858579857685988590859F866887BE87AA87AD87C587B087AC87B987B5 87BC87AE87C987C387C287CC87B787AF87C487CA87B487B687BF87B887BD87DE 87B289358933893C893E894189528937894289AD89AF89AE89F289F38B1E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008B188B168B118B058B0B8B228B0F8B128B158B078B0D8B088B068B1C8B13 8B1A8C4F8C708C728C718C6F8C958C948CF98D6F8E4E8E4D8E538E508E4C8E47 8F438F409085907E9138919A91A2919B9199919F91A1919D91A093A1938393AF 936493569347937C9358935C93769349935093519360936D938F934C936A9379 935793559352934F93719377937B9361935E936393679380934E935995C795C0 95C995C395C595B796AE96B096AC9720971F9718971D9719979A97A1979C0000 EF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 979E979D97D597D497F198419844984A9849984598439925992B992C992A9933 9932992F992D99319930999899A399A19A0299FA99F499F799F999F899F699FB 99FD99FE99FC9A039ABE9AFE9AFD9B019AFC9B489B9A9BA89B9E9B9B9BA69BA1 9BA59BA49B869BA29BA09BAF9D339D419D679D369D2E9D2F9D319D389D300000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009D459D429D439D3E9D379D409D3D7FF59D2D9E8A9E899E8D9EB09EC89EDA 9EFB9EFF9F249F239F229F549FA05131512D512E5698569C5697569A569D5699 59705B3C5C695C6A5DC05E6D5E6E61D861DF61ED61EE61F161EA61F061EB61D6 61E964FF650464FD64F86501650364FC659465DB66DA66DB66D86AC56AB96ABD 6AE16AC66ABA6AB66AB76AC76AB46AAD6B5E6BC96C0B7007700C700D70017005 7014700E6FFF70006FFB70266FFC6FF7700A720171FF71F9720371FD73760000 F0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 74B874C074B574C174BE74B674BB74C275147513765C76647659765076537657 765A76A676BD76EC77C277BA78FF790C79137914790979107912791179AD79AC 7A5F7C1C7C297C197C207C1F7C2D7C1D7C267C287C227C257C307E5C7E507E56 7E637E587E627E5F7E517E607E577E537FB57FB37FF77FF8807581D181D20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000081D0825F825E85B485C685C085C385C285B385B585BD85C785C485BF85CB 85CE85C885C585B185B685D2862485B885B785BE866987E787E687E287DB87EB 87EA87E587DF87F387E487D487DC87D387ED87D887E387A487D787D9880187F4 87E887DD8953894B894F894C89468950895189498B2A8B278B238B338B308B35 8B478B2F8B3C8B3E8B318B258B378B268B368B2E8B248B3B8B3D8B3A8C428C75 8C998C988C978CFE8D048D028D008E5C8E628E608E578E568E5E8E658E670000 F1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8E5B8E5A8E618E5D8E698E548F468F478F488F4B9128913A913B913E91A891A5 91A791AF91AA93B5938C939293B7939B939D938993A7938E93AA939E93A69395 93889399939F938D93B1939193B293A493A893B493A393A595D295D395D196B3 96D796DA5DC296DF96D896DD97239722972597AC97AE97A897AB97A497AA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000097A297A597D797D997D697D897FA98509851985298B89941993C993A9A0F 9A0B9A099A0D9A049A119A0A9A059A079A069AC09ADC9B089B049B059B299B35 9B4A9B4C9B4B9BC79BC69BC39BBF9BC19BB59BB89BD39BB69BC49BB99BBD9D5C 9D539D4F9D4A9D5B9D4B9D599D569D4C9D579D529D549D5F9D589D5A9E8E9E8C 9EDF9F019F009F169F259F2B9F2A9F299F289F4C9F5551345135529652F753B4 56AB56AD56A656A756AA56AC58DA58DD58DB59125B3D5B3E5B3F5DC35E700000 F2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5FBF61FB65076510650D6509650C650E658465DE65DD66DE6AE76AE06ACC6AD1 6AD96ACB6ADF6ADC6AD06AEB6ACF6ACD6ADE6B606BB06C0C7019702770207016 702B702170227023702970177024701C702A720C720A72077202720572A572A6 72A472A372A174CB74C574B774C37516766077C977CA77C477F1791D791B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007921791C7917791E79B07A677A687C337C3C7C397C2C7C3B7CEC7CEA7E76 7E757E787E707E777E6F7E7A7E727E747E687F4B7F4A7F837F867FB77FFD7FFE 807881D781D582648261826385EB85F185ED85D985E185E885DA85D785EC85F2 85F885D885DF85E385DC85D185F085E685EF85DE85E2880087FA880387F687F7 8809880C880B880687FC880887FF880A88028962895A895B89578961895C8958 895D8959898889B789B689F68B508B488B4A8B408B538B568B548B4B8B550000 F3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8B518B428B528B578C438C778C768C9A8D068D078D098DAC8DAA8DAD8DAB8E6D 8E788E738E6A8E6F8E7B8EC28F528F518F4F8F508F538FB49140913F91B091AD 93DE93C793CF93C293DA93D093F993EC93CC93D993A993E693CA93D493EE93E3 93D593C493CE93C093D293E7957D95DA95DB96E19729972B972C972897260000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000097B397B797B697DD97DE97DF985C9859985D985798BF98BD98BB98BE9948 9947994399A699A79A1A9A159A259A1D9A249A1B9A229A209A279A239A1E9A1C 9A149AC29B0B9B0A9B0E9B0C9B379BEA9BEB9BE09BDE9BE49BE69BE29BF09BD4 9BD79BEC9BDC9BD99BE59BD59BE19BDA9D779D819D8A9D849D889D719D809D78 9D869D8B9D8C9D7D9D6B9D749D759D709D699D859D739D7B9D829D6F9D799D7F 9D879D689E949E919EC09EFC9F2D9F409F419F4D9F569F579F58533756B20000 F4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 56B556B358E35B455DC65DC75EEE5EEF5FC05FC161F9651765166515651365DF 66E866E366E46AF36AF06AEA6AE86AF96AF16AEE6AEF703C7035702F70377034 703170427038703F703A70397040703B703370417213721472A8737D737C74BA 76AB76AA76BE76ED77CC77CE77CF77CD77F27925792379277928792479290000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000079B27A6E7A6C7A6D7AF77C497C487C4A7C477C457CEE7E7B7E7E7E817E80 7FBA7FFF807981DB81D9820B82688269862285FF860185FE861B860085F68604 86098605860C85FD8819881088118817881388168963896689B989F78B608B6A 8B5D8B688B638B658B678B6D8DAE8E868E888E848F598F568F578F558F588F5A 908D9143914191B791B591B291B3940B941393FB9420940F941493FE94159410 94289419940D93F5940093F79407940E9416941293FA940993F8940A93FF0000 F5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 93FC940C93F69411940695DE95E095DF972E972F97B997BB97FD97FE98609862 9863985F98C198C29950994E9959994C994B99539A329A349A319A2C9A2A9A36 9A299A2E9A389A2D9AC79ACA9AC69B109B129B119C0B9C089BF79C059C129BF8 9C409C079C0E9C069C179C149C099D9F9D999DA49D9D9D929D989D909D9B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009DA09D949D9C9DAA9D979DA19D9A9DA29DA89D9E9DA39DBF9DA99D969DA6 9DA79E999E9B9E9A9EE59EE49EE79EE69F309F2E9F5B9F609F5E9F5D9F599F91 513A51395298529756C356BD56BE5B485B475DCB5DCF5EF161FD651B6B026AFC 6B036AF86B0070437044704A7048704970457046721D721A7219737E7517766A 77D0792D7931792F7C547C537CF27E8A7E877E887E8B7E867E8D7F4D7FBB8030 81DD8618862A8626861F8623861C86198627862E862186208629861E86250000 F6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8829881D881B88208824881C882B884A896D8969896E896B89FA8B798B788B45 8B7A8B7B8D108D148DAF8E8E8E8C8F5E8F5B8F5D91469144914591B9943F943B 94369429943D943C94309439942A9437942C9440943195E595E495E39735973A 97BF97E1986498C998C698C0995899569A399A3D9A469A449A429A419A3A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009A3F9ACD9B159B179B189B169B3A9B529C2B9C1D9C1C9C2C9C239C289C29 9C249C219DB79DB69DBC9DC19DC79DCA9DCF9DBE9DC59DC39DBB9DB59DCE9DB9 9DBA9DAC9DC89DB19DAD9DCC9DB39DCD9DB29E7A9E9C9EEB9EEE9EED9F1B9F18 9F1A9F319F4E9F659F649F924EB956C656C556CB59715B4B5B4C5DD55DD15EF2 65216520652665226B0B6B086B096C0D7055705670577052721E721F72A9737F 74D874D574D974D7766D76AD793579B47A707A717C577C5C7C597C5B7C5A0000 F7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7CF47CF17E917F4F7F8781DE826B863486358633862C86328636882C88288826 882A8825897189BF89BE89FB8B7E8B848B828B868B858B7F8D158E958E948E9A 8E928E908E968E978F608F629147944C9450944A944B944F9447944594489449 9446973F97E3986A986998CB9954995B9A4E9A539A549A4C9A4F9A489A4A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009A499A529A509AD09B199B2B9B3B9B569B559C469C489C3F9C449C399C33 9C419C3C9C379C349C329C3D9C369DDB9DD29DDE9DDA9DCB9DD09DDC9DD19DDF 9DE99DD99DD89DD69DF59DD59DDD9EB69EF09F359F339F329F429F6B9F959FA2 513D529958E858E759725B4D5DD8882F5F4F62016203620465296525659666EB 6B116B126B0F6BCA705B705A7222738273817383767077D47C677C667E95826C 863A86408639863C8631863B863E88308832882E883389768974897389FE0000 F8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8B8C8B8E8B8B8B888C458D198E988F648F6391BC94629455945D9457945E97C4 97C598009A569A599B1E9B1F9B209C529C589C509C4A9C4D9C4B9C559C599C4C 9C4E9DFB9DF79DEF9DE39DEB9DF89DE49DF69DE19DEE9DE69DF29DF09DE29DEC 9DF49DF39DE89DED9EC29ED09EF29EF39F069F1C9F389F379F369F439F4F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009F719F709F6E9F6F56D356CD5B4E5C6D652D66ED66EE6B13705F7061705D 7060722374DB74E577D5793879B779B67C6A7E977F89826D8643883888378835 884B8B948B958E9E8E9F8EA08E9D91BE91BD91C2946B9468946996E597469743 974797C797E59A5E9AD59B599C639C679C669C629C5E9C609E029DFE9E079E03 9E069E059E009E019E099DFF9DFD9E049EA09F1E9F469F749F759F7656D4652E 65B86B186B196B176B1A7062722672AA77D877D979397C697C6B7CF67E9A0000 F9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7E987E9B7E9981E081E18646864786488979897A897C897B89FF8B988B998EA5 8EA48EA3946E946D946F9471947397499872995F9C689C6E9C6D9E0B9E0D9E10 9E0F9E129E119EA19EF59F099F479F789F7B9F7A9F79571E70667C6F883C8DB2 8EA691C394749478947694759A609C749C739C719C759E149E139EF69F0A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009FA4706870657CF7866A883E883D883F8B9E8C9C8EA98EC9974B98739874 98CC996199AB9A649A669A679B249E159E179F4862076B1E7227864C8EA89482 948094819A699A689B2E9E197229864B8B9F94839C799EB776759A6B9C7A9E1D 7069706A9EA49F7E9F499F98788192B988CF58BB60527CA75AFA255425662557 2560256C2563255A2569255D255225642555255E256A256125582567255B2553 25652556255F256B256225592568255C25512550256D256E2570256F25930000 tcl8.6.5/library/encoding/cp866.enc0000644000175000017500000000210211555560473016352 0ustar sergeisergei# Encoding file: cp866, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0410041104120413041404150416041704180419041A041B041C041D041E041F 0420042104220423042404250426042704280429042A042B042C042D042E042F 0430043104320433043404350436043704380439043A043B043C043D043E043F 259125922593250225242561256225562555256325512557255D255C255B2510 25142534252C251C2500253C255E255F255A25542569256625602550256C2567 2568256425652559255825522553256B256A2518250C25882584258C25902580 0440044104420443044404450446044704480449044A044B044C044D044E044F 040104510404045404070457040E045E00B0221900B7221A211600A425A000A0 tcl8.6.5/library/encoding/cp850.enc0000644000175000017500000000210211555560473016343 0ustar sergeisergei# Encoding file: cp850, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C700FC00E900E200E400E000E500E700EA00EB00E800EF00EE00EC00C400C5 00C900E600C600F400F600F200FB00F900FF00D600DC00F800A300D800D70192 00E100ED00F300FA00F100D100AA00BA00BF00AE00AC00BD00BC00A100AB00BB 2591259225932502252400C100C200C000A9256325512557255D00A200A52510 25142534252C251C2500253C00E300C3255A25542569256625602550256C00A4 00F000D000CA00CB00C8013100CD00CE00CF2518250C2588258400A600CC2580 00D300DF00D400D200F500D500B500FE00DE00DA00DB00D900FD00DD00AF00B4 00AD00B1201700BE00B600A700F700B800B000A800B700B900B300B225A000A0 tcl8.6.5/library/encoding/ebcdic.enc0000644000175000017500000000203611555560473016723 0ustar sergeisergeiS 006F 0 1 00 0000000100020003008500090086007F0087008D008E000B000C000D000E000F 0010001100120013008F000A0008009700180019009C009D001C001D001E001F 0080008100820083008400920017001B00880089008A008B008C000500060007 0090009100160093009400950096000400980099009A009B00140015009E001A 002000A000E200E400E000E100E300E500E700F10060002E003C0028002B007C 002600E900EA00EB00E800ED00EE00EF00EC00DF00210024002A0029003B009F 002D002F00C200C400C000C100C300C500C700D1005E002C0025005F003E003F 00F800C900CA00CB00C800CD00CE00CF00CC00A8003A002300400027003D0022 00D800610062006300640065006600670068006900AB00BB00F000FD00FE00B1 00B0006A006B006C006D006E006F00700071007200AA00BA00E600B800C600A4 00B500AF0073007400750076007700780079007A00A100BF00D000DD00DE00AE 00A200A300A500B700A900A700B600BC00BD00BE00AC005B005C005D00B400D7 00F900410042004300440045004600470048004900AD00F400F600F200F300F5 00A6004A004B004C004D004E004F00500051005200B900FB00FC00DB00FA00FF 00D900F70053005400550056005700580059005A00B200D400D600D200D300D5 003000310032003300340035003600370038003900B3007B00DC007D00DA007E tcl8.6.5/library/encoding/cp863.enc0000644000175000017500000000210211555560473016347 0ustar sergeisergei# Encoding file: cp863, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C700FC00E900E200C200E000B600E700EA00EB00E800EF00EE201700C000A7 00C900C800CA00F400CB00CF00FB00F900A400D400DC00A200A300D900DB0192 00A600B400F300FA00A800B800B300AF00CE231000AC00BD00BC00BE00AB00BB 259125922593250225242561256225562555256325512557255D255C255B2510 25142534252C251C2500253C255E255F255A25542569256625602550256C2567 2568256425652559255825522553256B256A2518250C25882584258C25902580 03B100DF039303C003A303C300B503C403A6039803A903B4221E03C603B52229 226100B1226522642320232100F7224800B0221900B7221A207F00B225A000A0 tcl8.6.5/library/encoding/symbol.enc0000644000175000017500000000210311555560473017012 0ustar sergeisergei# Encoding file: symbol, single-byte S 003F 1 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002122000023220300250026220D002800292217002B002C2212002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 22450391039203A70394039503A603930397039903D1039A039B039C039D039F 03A0039803A103A303A403A503C203A9039E03A80396005B2234005D22A5005F F8E503B103B203C703B403B503C603B303B703B903D503BA03BB03BC03BD03BF 03C003B803C103C303C403C503D603C903BE03C803B6007B007C007D223C007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 000003D2203222642044221E0192266326662665266021942190219121922193 00B000B12033226500D7221D2202202200F72260226122482026F8E6F8E721B5 21352111211C21182297229522052229222A2283228722842282228622082209 2220220700AE00A92122220F221A22C500AC2227222821D421D021D121D221D3 22C42329F8E8F8E9F8EA2211F8EBF8ECF8EDF8EEF8EFF8F0F8F1F8F2F8F3F8F4 F8FF232A222B2320F8F52321F8F6F8F7F8F8F8F9F8FAF8FBF8FCF8FDF8FE0000 tcl8.6.5/library/encoding/cp437.enc0000644000175000017500000000210211555560473016344 0ustar sergeisergei# Encoding file: cp437, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C700FC00E900E200E400E000E500E700EA00EB00E800EF00EE00EC00C400C5 00C900E600C600F400F600F200FB00F900FF00D600DC00A200A300A520A70192 00E100ED00F300FA00F100D100AA00BA00BF231000AC00BD00BC00A100AB00BB 259125922593250225242561256225562555256325512557255D255C255B2510 25142534252C251C2500253C255E255F255A25542569256625602550256C2567 2568256425652559255825522553256B256A2518250C25882584258C25902580 03B100DF039303C003A303C300B503C403A6039803A903B4221E03C603B52229 226100B1226522642320232100F7224800B0221900B7221A207F00B225A000A0 tcl8.6.5/library/encoding/iso8859-14.enc0000644000175000017500000000210711555560473017063 0ustar sergeisergei# Encoding file: iso8859-14, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A01E021E0300A3010A010B1E0A00A71E8000A91E821E0B1EF200AD00AE0178 1E1E1E1F012001211E401E4100B61E561E811E571E831E601EF31E841E851E61 00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF 017400D100D200D300D400D500D61E6A00D800D900DA00DB00DC00DD017600DF 00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF 017500F100F200F300F400F500F61E6B00F800F900FA00FB00FC00FD017700FF tcl8.6.5/library/encoding/macTurkish.enc0000644000175000017500000000210711555560473017623 0ustar sergeisergei# Encoding file: macTurkish, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C400C500C700C900D100D600DC00E100E000E200E400E300E500E700E900E8 00EA00EB00ED00EC00EE00EF00F100F300F200F400F600F500FA00F900FB00FC 202000B000A200A300A7202200B600DF00AE00A9212200B400A8226000C600D8 221E00B12264226500A500B522022211220F03C0222B00AA00BA03A900E600F8 00BF00A100AC221A01922248220600AB00BB202600A000C000C300D501520153 20132014201C201D2018201900F725CA00FF0178011E011F01300131015E015F 202100B7201A201E203000C200CA00C100CB00C800CD00CE00CF00CC00D300D4 F8FF00D200DA00DB00D9F8A002C602DC00AF02D802D902DA00B802DD02DB02C7 tcl8.6.5/library/encoding/euc-cn.enc0000644000175000017500000024710611555560473016675 0ustar sergeisergei# Encoding file: euc-cn, multi-byte M 003F 0 82 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030003001300230FB02C902C700A8300330052015FF5E2225202620182019 201C201D3014301530083009300A300B300C300D300E300F3016301730103011 00B100D700F72236222722282211220F222A222922082237221A22A522252220 23122299222B222E2261224C2248223D221D2260226E226F22642265221E2235 22342642264000B0203220332103FF0400A4FFE0FFE1203000A7211626062605 25CB25CF25CE25C725C625A125A025B325B2203B219221902191219330130000 A2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000024882489248A248B248C248D248E248F2490249124922493249424952496 249724982499249A249B247424752476247724782479247A247B247C247D247E 247F248024812482248324842485248624872460246124622463246424652466 2467246824690000000032203221322232233224322532263227322832290000 00002160216121622163216421652166216721682169216A216B000000000000 A3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF01FF02FF03FFE5FF05FF06FF07FF08FF09FF0AFF0BFF0CFF0DFF0EFF0F FF10FF11FF12FF13FF14FF15FF16FF17FF18FF19FF1AFF1BFF1CFF1DFF1EFF1F FF20FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2F FF30FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3AFF3BFF3CFF3DFF3EFF3F FF40FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5AFF5BFF5CFF5DFFE30000 A4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000304130423043304430453046304730483049304A304B304C304D304E304F 3050305130523053305430553056305730583059305A305B305C305D305E305F 3060306130623063306430653066306730683069306A306B306C306D306E306F 3070307130723073307430753076307730783079307A307B307C307D307E307F 3080308130823083308430853086308730883089308A308B308C308D308E308F 3090309130923093000000000000000000000000000000000000000000000000 A5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF 30B030B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF 30C030C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF 30D030D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000000 A6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000039103920393039403950396039703980399039A039B039C039D039E039F 03A003A103A303A403A503A603A703A803A90000000000000000000000000000 000003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C303C403C503C603C703C803C90000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000004100411041204130414041504010416041704180419041A041B041C041D 041E041F0420042104220423042404250426042704280429042A042B042C042D 042E042F00000000000000000000000000000000000000000000000000000000 000004300431043204330434043504510436043704380439043A043B043C043D 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000000000 A8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000010100E101CE00E0011300E9011B00E8012B00ED01D000EC014D00F301D2 00F2016B00FA01D400F901D601D801DA01DC00FC00EA00000000000000000000 0000000000000000000031053106310731083109310A310B310C310D310E310F 3110311131123113311431153116311731183119311A311B311C311D311E311F 3120312131223123312431253126312731283129000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000002500250125022503250425052506250725082509250A250B 250C250D250E250F2510251125122513251425152516251725182519251A251B 251C251D251E251F2520252125222523252425252526252725282529252A252B 252C252D252E252F2530253125322533253425352536253725382539253A253B 253C253D253E253F2540254125422543254425452546254725482549254A254B 0000000000000000000000000000000000000000000000000000000000000000 B0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000554A963F57C3632854CE550954C07691764C853C77EE827E788D72319698 978D6C285B894FFA630966975CB880FA684880AE660276CE51F9655671AC7FF1 888450B2596561CA6FB382AD634C625253ED54277B06516B75A45DF462D48DCB 9776628A8019575D97387F627238767D67CF767E64464F708D2562DC7A176591 73ED642C6273822C9881677F7248626E62CC4F3474E3534A529E7ECA90A65E2E 6886699C81807ED168D278C5868C9551508D8C2482DE80DE5305891252650000 B1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000858496F94FDD582199715B9D62B162A566B48C799C8D7206676F789160B2 535153178F8880CC8D1D94A1500D72C8590760EB711988AB595482EF672C7B28 5D297EF7752D6CF58E668FF8903C9F3B6BD491197B145F7C78A784D6853D6BD5 6BD96BD65E015E8775F995ED655D5F0A5FC58F9F58C181C2907F965B97AD8FB9 7F168D2C62414FBF53D8535E8FA88FA98FAB904D68075F6A819888689CD6618B 522B762A5F6C658C6FD26EE85BBE6448517551B067C44E1979C9997C70B30000 B2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075C55E7673BB83E064AD62E894B56CE2535A52C3640F94C27B944F2F5E1B 82368116818A6E246CCA9A736355535C54FA886557E04E0D5E036B657C3F90E8 601664E6731C88C16750624D8D22776C8E2991C75F6983DC8521991053C28695 6B8B60ED60E8707F82CD82314ED36CA785CF64CD7CD969FD66F9834953957B56 4FA7518C6D4B5C428E6D63D253C9832C833667E578B4643D5BDF5C945DEE8BE7 62C667F48C7A640063BA8749998B8C177F2094F24EA7961098A4660C73160000 B3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000573A5C1D5E38957F507F80A05382655E7545553150218D856284949E671D 56326F6E5DE2543570928F66626F64A463A35F7B6F8890F481E38FB05C186668 5FF16C8996488D81886C649179F057CE6A59621054484E587A0B60E96F848BDA 627F901E9A8B79E4540375F4630153196C608FDF5F1B9A70803B9F7F4F885C3A 8D647FC565A570BD514551B2866B5D075BA062BD916C75748E0C7A2061017B79 4EC77EF877854E1181ED521D51FA6A7153A88E87950496CF6EC19664695A0000 B4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000784050A877D7641089E6590463E35DDD7A7F693D4F20823955984E3275AE 7A975E625E8A95EF521B5439708A6376952457826625693F918755076DF37EAF 882262337EF075B5832878C196CC8F9E614874F78BCD6B64523A8D506B21806A 847156F153064ECE4E1B51D17C97918B7C074FC38E7F7BE17A9C64675D1450AC 810676017CB96DEC7FE067515B585BF878CB64AE641363AA632B9519642D8FBE 7B5476296253592754466B7950A362345E266B864EE38D37888B5F85902E0000 B5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006020803D62C54E39535590F863B880C665E66C2E4F4660EE6DE18BDE5F39 86CB5F536321515A83616863520063638E4850125C9B79775BFC52307A3B60BC 905376D75FB75F9776848E6C706F767B7B4977AA51F3909358244F4E6EF48FEA 654C7B1B72C46DA47FDF5AE162B55E95573084827B2C5E1D5F1F90127F1498A0 63826EC7789870B95178975B57AB75354F4375385E9760E659606DC06BBF7889 53FC96D551CB52016389540A94938C038DCC7239789F87768FED8C0D53E00000 B6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E0176EF53EE948998769F0E952D5B9A8BA24E224E1C51AC846361C252A8 680B4F97606B51BB6D1E515C6296659796618C46901775D890FD77636BD2728A 72EC8BFB583577798D4C675C9540809A5EA66E2159927AEF77ED953B6BB565AD 7F0E58065151961F5BF958A954288E726566987F56E4949D76FE9041638754C6 591A593A579B8EB267358DFA8235524160F0581586FE5CE89E454FC4989D8BB9 5A2560765384627C904F9102997F6069800C513F80335C1499756D314E8C0000 B7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008D3053D17F5A7B4F4F104E4F96006CD573D085E95E06756A7FFB6A0A77FE 94927E4151E170E653CD8FD483038D2972AF996D6CDB574A82B365B980AA623F 963259A84EFF8BBF7EBA653E83F2975E556198DE80A5532A8BFD542080BA5E9F 6CB88D3982AC915A54296C1B52067EB7575F711A6C7E7C89594B4EFD5FFF6124 7CAA4E305C0167AB87025CF0950B98CE75AF70FD902251AF7F1D8BBD594951E4 4F5B5426592B657780A45B75627662C28F905E456C1F7B264F0F4FD8670D0000 B8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D6E6DAA798F88B15F17752B629A8F854FEF91DC65A7812F81515E9C8150 8D74526F89868D4B590D50854ED8961C723681798D1F5BCC8BA3964459877F1A 54905676560E8BE565396982949976D66E895E727518674667D17AFF809D8D76 611F79C665628D635188521A94A27F38809B7EB25C976E2F67607BD9768B9AD8 818F7F947CD5641E95507A3F544A54E56B4C640162089E3D80F3759952729769 845B683C86E49601969494EC4E2A54047ED968398DDF801566F45E9A7FB90000 B9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000057C2803F68975DE5653B529F606D9F9A4F9B8EAC516C5BAB5F135DE96C5E 62F18D21517194A952FE6C9F82DF72D757A267848D2D591F8F9C83C754957B8D 4F306CBD5B6459D19F1353E486CA9AA88C3780A16545987E56FA96C7522E74DC 52505BE1630289024E5662D0602A68FA51735B9851A089C27BA199867F5060EF 704C8D2F51495E7F901B747089C4572D78455F529F9F95FA8F689B3C8BE17678 684267DC8DEA8D35523D8F8A6EDA68CD950590ED56FD679C88F98FC754C80000 BA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009AB85B696D776C264EA55BB39A87916361A890AF97E9542B6DB55BD251FD 558A7F557FF064BC634D65F161BE608D710A6C576C49592F676D822A58D5568E 8C6A6BEB90DD597D801753F76D695475559D837783CF683879BE548C4F555408 76D28C8996026CB36DB88D6B89109E648D3A563F9ED175D55F8872E0606854FC 4EA86A2A886160528F7054C470D886799E3F6D2A5B8F5F187EA255894FAF7334 543C539A5019540E547C4E4E5FFD745A58F6846B80E1877472D07CCA6E560000 BB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F27864E552C62A44E926CAA623782B154D7534E733E6ED1753B52125316 8BDD69D05F8A60006DEE574F6B2273AF68538FD87F13636260A3552475EA8C62 71156DA35BA65E7B8352614C9EC478FA87577C27768751F060F6714C66435E4C 604D8C0E707063258F895FBD606286D456DE6BC160946167534960E066668D3F 79FD4F1A70E96C478BB38BF27ED88364660F5A5A9B426D516DF78C416D3B4F19 706B83B7621660D1970D8D27797851FB573E57FA673A75787A3D79EF7B950000 BC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000808C99658FF96FC08BA59E2159EC7EE97F095409678168D88F917C4D96C6 53CA602575BE6C7253735AC97EA7632451E0810A5DF184DF628051805B634F0E 796D524260B86D4E5BC45BC28BA18BB065E25FCC964559937EE77EAA560967B7 59394F735BB652A0835A988A8D3E753294BE50477A3C4EF767B69A7E5AC16B7C 76D1575A5C167B3A95F4714E517C80A9827059787F04832768C067EC78B17877 62E363617B804FED526A51CF835069DB92748DF58D3189C1952E7BAD4EF60000 BD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000506582305251996F6E106E856DA75EFA50F559DC5C066D466C5F7586848B 686859568BB253209171964D854969127901712680F64EA490CA6D479A845A07 56BC640594F077EB4FA5811A72E189D2997A7F347EDE527F655991758F7F8F83 53EB7A9663ED63A5768679F888579636622A52AB8282685467706377776B7AED 6D017ED389E359D0621285C982A5754C501F4ECB75A58BEB5C4A5DFE7B4B65A4 91D14ECA6D25895F7D2795264EC58C288FDB9773664B79818FD170EC6D780000 BE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C3D52B283465162830E775B66769CB84EAC60CA7CBE7CB37ECF4E958B66 666F988897595883656C955C5F8475C997567ADF7ADE51C070AF7A9863EA7A76 7EA0739697ED4E4570784E5D915253A9655165E781FC8205548E5C31759A97A0 62D872D975BD5C459A7983CA5C40548077E94E3E6CAE805A62D2636E5DE85177 8DDD8E1E952F4FF153E560E770AC526763509E435A1F5026773753777EE26485 652B628963985014723589C951B38BC07EDD574783CC94A7519B541B5CFB0000 BF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004FCA7AE36D5A90E19A8F55805496536154AF5F0063E9697751EF6168520A 582A52D8574E780D770B5EB761777CE0625B62974EA27095800362F770E49760 577782DB67EF68F578D5989779D158F354B353EF6E34514B523B5BA28BFE80AF 554357A660735751542D7A7A60505B5463A762A053E362635BC767AF54ED7A9F 82E691775E9388E4593857AE630E8DE880EF57577B774FA95FEB5BBD6B3E5321 7B5072C2684677FF773665F751B54E8F76D45CBF7AA58475594E9B4150800000 C0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000998861276E8357646606634656F062EC62695ED39614578362C955878721 814A8FA3556683B167658D5684DD5A6A680F62E67BEE961151706F9C8C3063FD 89C861D27F0670C26EE57405699472FC5ECA90CE67176D6A635E52B372628001 4F6C59E5916A70D96D9D52D24E5096F7956D857E78CA7D2F5121579264C2808B 7C7B6CEA68F1695E51B7539868A872819ECE7BF172F879BB6F137406674E91CC 9CA4793C83898354540F68174E3D538952B1783E5386522950884F8B4FD00000 C1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075E27ACB7C926CA596B6529B748354E94FE9805483B28FDE95705EC9601C 6D9F5E18655B813894FE604B70BC7EC37CAE51C968817CB1826F4E248F8691CF 667E4EAE8C0564A9804A50DA759771CE5BE58FBD6F664E86648295635ED66599 521788C270C852A3730E7433679778F797164E3490BB9CDE6DCB51DB8D41541D 62CE73B283F196F69F8494C34F367F9A51CC707596755CAD988653E64EE46E9C 740969B4786B998F7559521876246D4167F3516D9F99804B54997B3C7ABF0000 C2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009686578462E29647697C5A0464027BD36F0F964B82A6536298855E907089 63B35364864F9C819E93788C97328DEF8D429E7F6F5E79845F559646622E9A74 541594DD4FA365C55C655C617F1586516C2F5F8B73876EE47EFF5CE6631B5B6A 6EE653754E7163A0756562A18F6E4F264ED16CA67EB68BBA841D87BA7F57903B 95237BA99AA188F8843D6D1B9A867EDC59889EBB739B780186829A6C9A82561B 541757CB4E709EA653568FC881097792999286EE6EE1851366FC61626F2B0000 C3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008C298292832B76F26C135FD983BD732B8305951A6BDB77DB94C6536F8302 51925E3D8C8C8D384E4873AB679A68859176970971646CA177095A9295416BCF 7F8E66275BD059B95A9A95E895F74EEC840C84996AAC76DF9530731B68A65B5F 772F919A97617CDC8FF78C1C5F257C7379D889C56CCC871C5BC65E4268C97720 7EF55195514D52C95A297F05976282D763CF778485D079D26E3A5E9959998511 706D6C1162BF76BF654F60AF95FD660E879F9E2394ED540D547D8C2C64780000 C4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000647986116A21819C78E864699B5462B9672B83AB58A89ED86CAB6F205BDE 964C8C0B725F67D062C772614EA959C66BCD589366AE5E5552DF6155672876EE 776672677A4662FF54EA545094A090A35A1C7EB36C164E435976801059485357 753796BE56CA63208111607C95F96DD65462998151855AE980FD59AE9713502A 6CE55C3C62DF4F60533F817B90066EBA852B62C85E7478BE64B5637B5FF55A18 917F9E1F5C3F634F80425B7D556E954A954D6D8560A867E072DE51DD5B810000 C5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000062E76CDE725B626D94AE7EBD81136D53519C5F04597452AA601259736696 8650759F632A61E67CEF8BFA54E66B279E256BB485D5545550766CA4556A8DB4 722C5E156015743662CD6392724C5F986E436D3E65006F5876D878D076FC7554 522453DB4E535E9E65C1802A80D6629B5486522870AE888D8DD16CE1547880DA 57F988F48D54966A914D4F696C9B55B776C6783062A870F96F8E5F6D84EC68DA 787C7BF781A8670B9E4F636778B0576F78129739627962AB528874356BD70000 C6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005564813E75B276AE533975DE50FB5C418B6C7BC7504F72479A9798D86F02 74E27968648777A562FC98918D2B54C180584E52576A82F9840D5E7351ED74F6 8BC45C4F57616CFC98875A4678349B448FEB7C955256625194FA4EC683868461 83E984B257D467345703666E6D668C3166DD7011671F6B3A6816621A59BB4E03 51C46F0667D26C8F517668CB59476B6775665D0E81109F5065D7794879419A91 8D775C824E5E4F01542F5951780C56686C148FC45F036C7D6CE38BAB63900000 C7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000060706D3D72756266948E94C553438FC17B7E4EDF8C264E7E9ED494B194B3 524D6F5C90636D458C3458115D4C6B206B4967AA545B81547F8C589985375F3A 62A26A47953965726084686577A74E544FA85DE7979864AC7FD85CED4FCF7A8D 520783044E14602F7A8394A64FB54EB279E6743452E482B964D279BD5BDD6C81 97528F7B6C22503E537F6E0564CE66746C3060C598778BF75E86743C7A7779CB 4E1890B174036C4256DA914B6CC58D8B533A86C666F28EAF5C489A716E200000 C8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000053D65A369F8B8DA353BB570898A76743919B6CC9516875CA62F372AC5238 529D7F3A7094763853749E4A69B7786E96C088D97FA4713671C3518967D374E4 58E4651856B78BA9997662707ED560F970ED58EC4EC14EBA5FCD97E74EFB8BA4 5203598A7EAB62544ECD65E5620E833884C98363878D71946EB65BB97ED25197 63C967D480898339881551125B7A59828FB14E736C5D516589258F6F962E854A 745E951095F06DA682E55F3164926D128428816E9CC3585E8D5B4E0953C10000 C9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F1E6563685155D34E2764149A9A626B5AC2745F82726DA968EE50E7838E 7802674052396C997EB150BB5565715E7B5B665273CA82EB67495C715220717D 886B95EA965564C58D6181B355846C5562477F2E58924F2455468D4F664C4E0A 5C1A88F368A2634E7A0D70E7828D52FA97F65C1154E890B57ECD59628D4A86C7 820C820D8D6664445C0461516D89793E8BBE78377533547B4F388EAB6DF15A20 7EC5795E6C885BA15A76751A80BE614E6E1758F0751F7525727253477EF30000 CA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000770176DB526980DC57235E08593172EE65BD6E7F8BD75C388671534177F3 62FE65F64EC098DF86805B9E8BC653F277E24F7F5C4E9A7659CB5F0F793A58EB 4E1667FF4E8B62ED8A93901D52BF662F55DC566C90024ED54F8D91CA99706C0F 5E0260435BA489C68BD56536624B99965B885BFF6388552E53D77626517D852C 67A268B36B8A62928F9353D482126DD1758F4E668D4E5B70719F85AF669166D9 7F7287009ECD9F205C5E672F8FF06811675F620D7AD658855EB665706F310000 CB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000060555237800D6454887075295E05681362F4971C53CC723D8C016C347761 7A0E542E77AC987A821C8BF47855671470C165AF64955636601D79C153F84E1D 6B7B80865BFA55E356DB4F3A4F3C99725DF3677E80386002988290015B8B8BBC 8BF5641C825864DE55FD82CF91654FD77D20901F7C9F50F358516EAF5BBF8BC9 80839178849C7B97867D968B968F7EE59AD3788E5C817A57904296A7795F5B59 635F7B0B84D168AD55067F2974107D2295016240584C4ED65B83597958540000 CC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000736D631E8E4B8E0F80CE82D462AC53F06CF0915E592A60016C70574D644A 8D2A762B6EE9575B6A8075F06F6D8C2D8C0857666BEF889278B363A253F970AD 6C645858642A580268E0819B55107CD650188EBA6DCC8D9F70EB638F6D9B6ED4 7EE68404684390036DD896768BA85957727985E4817E75BC8A8A68AF52548E22 951163D098988E44557C4F5366FF568F60D56D9552435C4959296DFB586B7530 751C606C82148146631167618FE2773A8DF38D3494C15E165385542C70C30000 CD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006C405EF7505C4EAD5EAD633A8247901A6850916E77B3540C94DC5F647AE5 687663457B527EDF75DB507762955934900F51F879C37A8156FE5F9290146D82 5C60571F541051546E4D56E263A89893817F8715892A9000541E5C6F81C062D6 625881319E3596409A6E9A7C692D59A562D3553E631654C786D96D3C5A0374E6 889C6B6A59168C4C5F2F6E7E73A9987D4E3870F75B8C7897633D665A769660CB 5B9B5A494E0781556C6A738B4EA167897F515F8065FA671B5FD859845A010000 CE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005DCD5FAE537197E68FDD684556F4552F60DF4E3A6F4D7EF482C7840E59D4 4F1F4F2A5C3E7EAC672A851A5473754F80C355829B4F4F4D6E2D8C135C096170 536B761F6E29868A658795FB7EB9543B7A337D0A95EE55E17FC174EE631D8717 6DA17A9D621165A1536763E16C835DEB545C94A84E4C6C618BEC5C4B65E0829C 68A7543E54346BCB6B664E9463425348821E4F0D4FAE575E620A96FE66647269 52FF52A1609F8BEF661471996790897F785277FD6670563B54389521727A0000 CF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A00606F5E0C6089819D591560DC718470EF6EAA6C5072806A8488AD5E2D 4E605AB3559C94E36D177CFB9699620F7EC6778E867E5323971E8F9666875CE1 4FA072ED4E0B53A6590F54136380952851484ED99C9C7EA454B88D2488548237 95F26D8E5F265ACC663E966973B0732E53BF817A99857FA15BAA967796507EBF 76F853A2957699997BB189446E584E617FD479658BE660F354CD4EAB98795DF7 6A6150CF54118C618427785D9704524A54EE56A395006D885BB56DC666530000 D0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C0F5B5D6821809655787B11654869544E9B6B47874E978B534F631F643A 90AA659C80C18C10519968B0537887F961C86CC46CFB8C225C5185AA82AF950C 6B238F9B65B05FFB5FC34FE18845661F8165732960FA51745211578B5F6290A2 884C91925E78674F602759D3514451F680F853086C7996C4718A4F114FEE7F9E 673D55C5950879C088967EE3589F620C9700865A5618987B5F908BB884C49157 53D965ED5E8F755C60647D6E5A7F7EEA7EED8F6955A75BA360AC65CB73840000 D1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009009766377297EDA9774859B5B667A7496EA884052CB718F5FAA65EC8BE2 5BFB9A6F5DE16B896C5B8BAD8BAF900A8FC5538B62BC9E269E2D54404E2B82BD 7259869C5D1688596DAF96C554D14E9A8BB6710954BD960970DF6DF976D04E25 781487125CA95EF68A00989C960E708E6CBF594463A9773C884D6F1482735830 71D5538C781A96C155015F6671305BB48C1A9A8C6B83592E9E2F79E76768626C 4F6F75A17F8A6D0B96336C274EF075D2517B68376F3E90808170599674760000 D2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000064475C2790657A918C2359DA54AC8200836F898180006930564E80367237 91CE51B64E5F987563964E1A53F666F3814B591C6DB24E0058F9533B63D694F1 4F9D4F0A886398905937905779FB4EEA80F075916C825B9C59E85F5D69058681 501A5DF24E5977E34EE5827A6291661390915C794EBF5F7981C69038808475AB 4EA688D4610F6BC55FC64E4976CA6EA28BE38BAE8C0A8BD15F027FFC7FCC7ECE 8335836B56E06BB797F3963459FB541F94F66DEB5BC5996E5C395F1596900000 D3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000537082F16A315A749E705E947F2883B984248425836787478FCE8D6276C8 5F719896786C662054DF62E54F6381C375C85EB896CD8E0A86F9548F6CF36D8C 6C38607F52C775285E7D4F1860A05FE75C24753190AE94C072B96CB96E389149 670953CB53F34F5191C98BF153C85E7C8FC26DE44E8E76C26986865E611A8206 4F594FDE903E9C7C61096E1D6E1496854E885A3196E84E0E5C7F79B95B878BED 7FBD738957DF828B90C15401904755BB5CEA5FA161086B3272F180B28A890000 D4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D745BD388D598848C6B9A6D9E336E0A51A4514357A38881539F63F48F95 56ED54585706733F6E907F188FDC82D1613F6028966266F07EA68D8A8DC394A5 5CB37CA4670860A6960580184E9190E75300966851418FD08574915D665597F5 5B55531D78386742683D54C9707E5BB08F7D518D572854B1651266828D5E8D43 810F846C906D7CDF51FF85FB67A365E96FA186A48E81566A90207682707671E5 8D2362E952196CFD8D3C600E589E618E66FE8D60624E55B36E23672D8F670000 D5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000094E195F87728680569A8548B4E4D70B88BC86458658B5B857A84503A5BE8 77BB6BE18A797C986CBE76CF65A98F975D2D5C5586386808536062187AD96E5B 7EFD6A1F7AE05F706F335F20638C6DA867564E085E108D264ED780C07634969C 62DB662D627E6CBC8D7571677F695146808753EC906E629854F286F08F998005 951785178FD96D5973CD659F771F7504782781FB8D1E94884FA6679575B98BCA 9707632F9547963584B8632377415F8172F04E896014657462EF6B63653F0000 D6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005E2775C790D18BC1829D679D652F5431871877E580A281026C414E4B7EC7 804C76F4690D6B966267503C4F84574063076B628DBE53EA65E87EB85FD7631A 63B781F381F47F6E5E1C5CD95236667A79E97A1A8D28709975D46EDE6CBB7A92 4E2D76C55FE0949F88777EC879CD80BF91CD4EF24F17821F54685DDE6D328BCC 7CA58F7480985E1A549276B15B99663C9AA473E0682A86DB6731732A8BF88BDB 90107AF970DB716E62C477A956314E3B845767F152A986C08D2E94F87B510000 D7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F4F6CE8795D9A7B6293722A62FD4E1378168F6C64B08D5A7BC668695E84 88C55986649E58EE72B6690E95258FFD8D5857607F008C0651C6634962D95353 684C74228301914C55447740707C6D4A517954A88D4459FF6ECB6DC45B5C7D2B 4ED47C7D6ED35B5081EA6E0D5B579B0368D58E2A5B977EFC603B7EB590B98D70 594F63CD79DF8DB3535265CF79568BC5963B7EC494BB7E825634918967007F6A 5C0A907566285DE64F5067DE505A4F5C57505EA7000000000000000000000000 D8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E8D4E0C51404E105EFF53454E154E984E1E9B325B6C56694E2879BA4E3F 53154E47592D723B536E6C1056DF80E499976BD3777E9F174E364E9F9F104E5C 4E694E9382885B5B556C560F4EC4538D539D53A353A553AE97658D5D531A53F5 5326532E533E8D5C5366536352025208520E522D5233523F5240524C525E5261 525C84AF527D528252815290529351827F544EBB4EC34EC94EC24EE84EE14EEB 4EDE4F1B4EF34F224F644EF54F254F274F094F2B4F5E4F6765384F5A4F5D0000 D9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F5F4F574F324F3D4F764F744F914F894F834F8F4F7E4F7B4FAA4F7C4FAC 4F944FE64FE84FEA4FC54FDA4FE34FDC4FD14FDF4FF85029504C4FF3502C500F 502E502D4FFE501C500C50255028507E504350555048504E506C507B50A550A7 50A950BA50D6510650ED50EC50E650EE5107510B4EDD6C3D4F584F654FCE9FA0 6C467C74516E5DFD9EC999985181591452F9530D8A07531051EB591951554EA0 51564EB3886E88A44EB5811488D279805B3488037FB851AB51B151BD51BC0000 DA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000051C7519651A251A58BA08BA68BA78BAA8BB48BB58BB78BC28BC38BCB8BCF 8BCE8BD28BD38BD48BD68BD88BD98BDC8BDF8BE08BE48BE88BE98BEE8BF08BF3 8BF68BF98BFC8BFF8C008C028C048C078C0C8C0F8C118C128C148C158C168C19 8C1B8C188C1D8C1F8C208C218C258C278C2A8C2B8C2E8C2F8C328C338C358C36 5369537A961D962296219631962A963D963C964296499654965F9667966C9672 96749688968D969796B09097909B909D909990AC90A190B490B390B690BA0000 DB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000090B890B090CF90C590BE90D090C490C790D390E690E290DC90D790DB90EB 90EF90FE91049122911E91239131912F913991439146520D594252A252AC52AD 52BE54FF52D052D652F053DF71EE77CD5EF451F551FC9B2F53B65F01755A5DEF 574C57A957A1587E58BC58C558D15729572C572A57335739572E572F575C573B 574257695785576B5786577C577B5768576D5776577357AD57A4578C57B257CF 57A757B4579357A057D557D857DA57D957D257B857F457EF57F857E457DD0000 DC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000580B580D57FD57ED5800581E5819584458205865586C58815889589A5880 99A89F1961FF8279827D827F828F828A82A88284828E82918297829982AB82B8 82BE82B082C882CA82E3829882B782AE82CB82CC82C182A982B482A182AA829F 82C482CE82A482E1830982F782E4830F830782DC82F482D282D8830C82FB82D3 8311831A83068314831582E082D5831C8351835B835C83088392833C83348331 839B835E832F834F83478343835F834083178360832D833A8333836683650000 DD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008368831B8369836C836A836D836E83B0837883B383B483A083AA8393839C 8385837C83B683A9837D83B8837B8398839E83A883BA83BC83C1840183E583D8 58078418840B83DD83FD83D6841C84388411840683D483DF840F840383F883F9 83EA83C583C0842683F083E1845C8451845A8459847384878488847A84898478 843C844684698476848C848E8431846D84C184CD84D084E684BD84D384CA84BF 84BA84E084A184B984B4849784E584E3850C750D853884F08539851F853A0000 DE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008556853B84FF84FC8559854885688564855E857A77A285438572857B85A4 85A88587858F857985AE859C858585B985B785B085D385C185DC85FF86278605 86298616863C5EFE5F08593C594180375955595A5958530F5C225C255C2C5C34 624C626A629F62BB62CA62DA62D762EE632262F66339634B634363AD63F66371 637A638E63B4636D63AC638A636963AE63BC63F263F863E063FF63C463DE63CE 645263C663BE64456441640B641B6420640C64266421645E6484646D64960000 DF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000647A64B764B8649964BA64C064D064D764E464E265096525652E5F0B5FD2 75195F11535F53F153FD53E953E853FB541254165406544B5452545354545456 54435421545754595423543254825494547754715464549A549B548454765466 549D54D054AD54C254B454D254A754A654D354D4547254A354D554BB54BF54CC 54D954DA54DC54A954AA54A454DD54CF54DE551B54E7552054FD551454F35522 5523550F55115527552A5567558F55B55549556D55415555553F5550553C0000 E0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005537555655755576557755335530555C558B55D2558355B155B955885581 559F557E55D65591557B55DF55BD55BE5594559955EA55F755C9561F55D155EB 55EC55D455E655DD55C455EF55E555F255F355CC55CD55E855F555E48F94561E 5608560C56015624562355FE56005627562D565856395657562C564D56625659 565C564C5654568656645671566B567B567C5685569356AF56D456D756DD56E1 56F556EB56F956FF5704570A5709571C5E0F5E195E145E115E315E3B5E3C0000 E1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005E375E445E545E5B5E5E5E615C8C5C7A5C8D5C905C965C885C985C995C91 5C9A5C9C5CB55CA25CBD5CAC5CAB5CB15CA35CC15CB75CC45CD25CE45CCB5CE5 5D025D035D275D265D2E5D245D1E5D065D1B5D585D3E5D345D3D5D6C5D5B5D6F 5D5D5D6B5D4B5D4A5D695D745D825D995D9D8C735DB75DC55F735F775F825F87 5F895F8C5F955F995F9C5FA85FAD5FB55FBC88625F6172AD72B072B472B772B8 72C372C172CE72CD72D272E872EF72E972F272F472F7730172F3730372FA0000 E2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000072FB731773137321730A731E731D7315732273397325732C733873317350 734D73577360736C736F737E821B592598E7592459029963996799689969996A 996B996C99749977997D998099849987998A998D999099919993999499955E80 5E915E8B5E965EA55EA05EB95EB55EBE5EB38D535ED25ED15EDB5EE85EEA81BA 5FC45FC95FD65FCF60035FEE60045FE15FE45FFE600560065FEA5FED5FF86019 60356026601B600F600D6029602B600A603F602160786079607B607A60420000 E3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000606A607D6096609A60AD609D60836092608C609B60EC60BB60B160DD60D8 60C660DA60B4612061266115612360F46100610E612B614A617561AC619461A7 61B761D461F55FDD96B395E995EB95F195F395F595F695FC95FE960396049606 9608960A960B960C960D960F96129615961696179619961A4E2C723F62156C35 6C546C5C6C4A6CA36C856C906C946C8C6C686C696C746C766C866CA96CD06CD4 6CAD6CF76CF86CF16CD76CB26CE06CD66CFA6CEB6CEE6CB16CD36CEF6CFE0000 E4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D396D276D0C6D436D486D076D046D196D0E6D2B6D4D6D2E6D356D1A6D4F 6D526D546D336D916D6F6D9E6DA06D5E6D936D946D5C6D606D7C6D636E1A6DC7 6DC56DDE6E0E6DBF6DE06E116DE66DDD6DD96E166DAB6E0C6DAE6E2B6E6E6E4E 6E6B6EB26E5F6E866E536E546E326E256E446EDF6EB16E986EE06F2D6EE26EA5 6EA76EBD6EBB6EB76ED76EB46ECF6E8F6EC26E9F6F626F466F476F246F156EF9 6F2F6F366F4B6F746F2A6F096F296F896F8D6F8C6F786F726F7C6F7A6FD10000 E5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006FC96FA76FB96FB66FC26FE16FEE6FDE6FE06FEF701A7023701B70397035 704F705E5B805B845B955B935BA55BB8752F9A9E64345BE45BEE89305BF08E47 8B078FB68FD38FD58FE58FEE8FE48FE98FE68FF38FE890059004900B90269011 900D9016902190359036902D902F9044905190529050906890589062905B66B9 9074907D908290889083908B5F505F575F565F585C3B54AB5C505C595B715C63 5C667FBC5F2A5F295F2D82745F3C9B3B5C6E59815983598D59A959AA59A30000 E6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000599759CA59AB599E59A459D259B259AF59D759BE5A055A0659DD5A0859E3 59D859F95A0C5A095A325A345A115A235A135A405A675A4A5A555A3C5A625A75 80EC5AAA5A9B5A775A7A5ABE5AEB5AB25AD25AD45AB85AE05AE35AF15AD65AE6 5AD85ADC5B095B175B165B325B375B405C155C1C5B5A5B655B735B515B535B62 9A759A779A789A7A9A7F9A7D9A809A819A859A889A8A9A909A929A939A969A98 9A9B9A9C9A9D9A9F9AA09AA29AA39AA59AA77E9F7EA17EA37EA57EA87EA90000 E7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007EAD7EB07EBE7EC07EC17EC27EC97ECB7ECC7ED07ED47ED77EDB7EE07EE1 7EE87EEB7EEE7EEF7EF17EF27F0D7EF67EFA7EFB7EFE7F017F027F037F077F08 7F0B7F0C7F0F7F117F127F177F197F1C7F1B7F1F7F217F227F237F247F257F26 7F277F2A7F2B7F2C7F2D7F2F7F307F317F327F337F355E7A757F5DDB753E9095 738E739173AE73A2739F73CF73C273D173B773B373C073C973C873E573D9987C 740A73E973E773DE73BA73F2740F742A745B7426742574287430742E742C0000 E8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000741B741A7441745C7457745574597477746D747E749C748E748074817487 748B749E74A874A9749074A774D274BA97EA97EB97EC674C6753675E67486769 67A56787676A6773679867A7677567A8679E67AD678B6777677C67F0680967D8 680A67E967B0680C67D967B567DA67B367DD680067C367B867E2680E67C167FD 6832683368606861684E6862684468646883681D68556866684168676840683E 684A6849682968B5688F687468776893686B68C2696E68FC691F692068F90000 E9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000692468F0690B6901695768E369106971693969606942695D6984696B6980 69986978693469CC6987698869CE6989696669636979699B69A769BB69AB69AD 69D469B169C169CA69DF699569E0698D69FF6A2F69ED6A176A186A6569F26A44 6A3E6AA06A506A5B6A356A8E6A796A3D6A286A586A7C6A916A906AA96A976AAB 733773526B816B826B876B846B926B936B8D6B9A6B9B6BA16BAA8F6B8F6D8F71 8F728F738F758F768F788F778F798F7A8F7C8F7E8F818F828F848F878F8B0000 EA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008F8D8F8E8F8F8F988F9A8ECE620B6217621B621F6222622162256224622C 81E774EF74F474FF750F75117513653465EE65EF65F0660A6619677266036615 6600708566F7661D66346631663666358006665F66546641664F665666616657 66776684668C66A7669D66BE66DB66DC66E666E98D328D338D368D3B8D3D8D40 8D458D468D488D498D478D4D8D558D5989C789CA89CB89CC89CE89CF89D089D1 726E729F725D7266726F727E727F7284728B728D728F72926308633263B00000 EB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000643F64D880046BEA6BF36BFD6BF56BF96C056C076C066C0D6C156C186C19 6C1A6C216C296C246C2A6C3265356555656B724D72527256723086625216809F 809C809380BC670A80BD80B180AB80AD80B480B780E780E880E980EA80DB80C2 80C480D980CD80D7671080DD80EB80F180F480ED810D810E80F280FC67158112 8C5A8136811E812C811881328148814C815381748159815A817181608169817C 817D816D8167584D5AB58188818281916ED581A381AA81CC672681CA81BB0000 EC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000081C181A66B246B376B396B436B466B5998D198D298D398D598D998DA6BB3 5F406BC289F365909F51659365BC65C665C465C365CC65CE65D265D67080709C 7096709D70BB70C070B770AB70B170E870CA711071137116712F71317173715C 716871457172714A7178717A719871B371B571A871A071E071D471E771F9721D 7228706C7118716671B9623E623D624362486249793B794079467949795B795C 7953795A796279577960796F7967797A7985798A799A79A779B35FD15FD00000 ED 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000603C605D605A606760416059606360AB6106610D615D61A9619D61CB61D1 62068080807F6C936CF66DFC77F677F87800780978177818781165AB782D781C 781D7839783A783B781F783C7825782C78237829784E786D7856785778267850 7847784C786A789B7893789A7887789C78A178A378B278B978A578D478D978C9 78EC78F2790578F479137924791E79349F9B9EF99EFB9EFC76F17704770D76F9 77077708771A77227719772D7726773577387750775177477743775A77680000 EE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077627765777F778D777D7780778C7791779F77A077B077B577BD753A7540 754E754B7548755B7572757975837F587F617F5F8A487F687F747F717F797F81 7F7E76CD76E58832948594869487948B948A948C948D948F9490949494979495 949A949B949C94A394A494AB94AA94AD94AC94AF94B094B294B494B694B794B8 94B994BA94BC94BD94BF94C494C894C994CA94CB94CC94CD94CE94D094D194D2 94D594D694D794D994D894DB94DE94DF94E094E294E494E594E794E894EA0000 EF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000094E994EB94EE94EF94F394F494F594F794F994FC94FD94FF950395029506 95079509950A950D950E950F951295139514951595169518951B951D951E951F 9522952A952B9529952C953195329534953695379538953C953E953F95429535 9544954595469549954C954E954F9552955395549556955795589559955B955E 955F955D95619562956495659566956795689569956A956B956C956F95719572 9573953A77E777EC96C979D579ED79E379EB7A065D477A037A027A1E7A140000 F0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A397A377A519ECF99A57A707688768E7693769976A474DE74E0752C9E20 9E229E289E299E2A9E2B9E2C9E329E319E369E389E379E399E3A9E3E9E419E42 9E449E469E479E489E499E4B9E4C9E4E9E519E559E579E5A9E5B9E5C9E5E9E63 9E669E679E689E699E6A9E6B9E6C9E719E6D9E7375927594759675A0759D75AC 75A375B375B475B875C475B175B075C375C275D675CD75E375E875E675E475EB 75E7760375F175FC75FF761076007605760C7617760A76257618761576190000 F1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000761B763C762276207640762D7630763F76357643763E7633764D765E7654 765C7656766B766F7FCA7AE67A787A797A807A867A887A957AA67AA07AAC7AA8 7AAD7AB3886488698872887D887F888288A288C688B788BC88C988E288CE88E3 88E588F1891A88FC88E888FE88F0892189198913891B890A8934892B89368941 8966897B758B80E576B276B477DC801280148016801C80208022802580268027 802980288031800B803580438046804D80528069807189839878988098830000 F2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009889988C988D988F9894989A989B989E989F98A198A298A598A6864D8654 866C866E867F867A867C867B86A8868D868B86AC869D86A786A386AA869386A9 86B686C486B586CE86B086BA86B186AF86C986CF86B486E986F186F286ED86F3 86D0871386DE86F486DF86D886D18703870786F88708870A870D87098723873B 871E8725872E871A873E87488734873187298737873F87828722877D877E877B 87608770874C876E878B87538763877C876487598765879387AF87A887D20000 F3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000087C68788878587AD8797878387AB87E587AC87B587B387CB87D387BD87D1 87C087CA87DB87EA87E087EE8816881387FE880A881B88218839883C7F367F42 7F447F4582107AFA7AFD7B087B037B047B157B0A7B2B7B0F7B477B387B2A7B19 7B2E7B317B207B257B247B337B3E7B1E7B587B5A7B457B757B4C7B5D7B607B6E 7B7B7B627B727B717B907BA67BA77BB87BAC7B9D7BA87B857BAA7B9C7BA27BAB 7BB47BD17BC17BCC7BDD7BDA7BE57BE67BEA7C0C7BFE7BFC7C0F7C167C0B0000 F4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007C1F7C2A7C267C387C417C4081FE82018202820481EC8844822182228223 822D822F8228822B8238823B82338234823E82448249824B824F825A825F8268 887E8885888888D888DF895E7F9D7F9F7FA77FAF7FB07FB27C7C65497C917C9D 7C9C7C9E7CA27CB27CBC7CBD7CC17CC77CCC7CCD7CC87CC57CD77CE8826E66A8 7FBF7FCE7FD57FE57FE17FE67FE97FEE7FF37CF87D777DA67DAE7E477E9B9EB8 9EB48D738D848D948D918DB18D678D6D8C478C49914A9150914E914F91640000 F5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009162916191709169916F917D917E917291749179918C91859190918D9191 91A291A391AA91AD91AE91AF91B591B491BA8C559E7E8DB88DEB8E058E598E69 8DB58DBF8DBC8DBA8DC48DD68DD78DDA8DDE8DCE8DCF8DDB8DC68DEC8DF78DF8 8DE38DF98DFB8DE48E098DFD8E148E1D8E1F8E2C8E2E8E238E2F8E3A8E408E39 8E358E3D8E318E498E418E428E518E528E4A8E708E768E7C8E6F8E748E858E8F 8E948E908E9C8E9E8C788C828C8A8C858C988C94659B89D689DE89DA89DC0000 F6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000089E589EB89EF8A3E8B26975396E996F396EF970697019708970F970E972A 972D9730973E9F809F839F859F869F879F889F899F8A9F8C9EFE9F0B9F0D96B9 96BC96BD96CE96D277BF96E0928E92AE92C8933E936A93CA938F943E946B9C7F 9C829C859C869C879C887A239C8B9C8E9C909C919C929C949C959C9A9C9B9C9E 9C9F9CA09CA19CA29CA39CA59CA69CA79CA89CA99CAB9CAD9CAE9CB09CB19CB2 9CB39CB49CB59CB69CB79CBA9CBB9CBC9CBD9CC49CC59CC69CC79CCA9CCB0000 F7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009CCC9CCD9CCE9CCF9CD09CD39CD49CD59CD79CD89CD99CDC9CDD9CDF9CE2 977C978597919792979497AF97AB97A397B297B49AB19AB09AB79E589AB69ABA 9ABC9AC19AC09AC59AC29ACB9ACC9AD19B459B439B479B499B489B4D9B5198E8 990D992E995599549ADF9AE19AE69AEF9AEB9AFB9AED9AF99B089B0F9B139B1F 9B239EBD9EBE7E3B9E829E879E889E8B9E9293D69E9D9E9F9EDB9EDC9EDD9EE0 9EDF9EE29EE99EE79EE59EEA9EEF9F229F2C9F2F9F399F379F3D9F3E9F440000 tcl8.6.5/library/encoding/cp855.enc0000644000175000017500000000210211555560473016350 0ustar sergeisergei# Encoding file: cp855, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0452040204530403045104010454040404550405045604060457040704580408 04590409045A040A045B040B045C040C045E040E045F040F044E042E044A042A 0430041004310411044604260434041404350415044404240433041300AB00BB 259125922593250225240445042504380418256325512557255D043904192510 25142534252C251C2500253C043A041A255A25542569256625602550256C00A4 043B041B043C041C043D041D043E041E043F2518250C25882584041F044F2580 042F044004200441042104420422044304230436041604320412044C042C2116 00AD044B042B0437041704480428044D042D044904290447042700A725A000A0 tcl8.6.5/library/encoding/ascii.enc0000644000175000017500000000210211555560473016574 0ustar sergeisergei# Encoding file: ascii, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 tcl8.6.5/library/encoding/cp874.enc0000644000175000017500000000210211555560473016351 0ustar sergeisergei# Encoding file: cp874, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 20AC008100820083008420260086008700880089008A008B008C008D008E008F 009020182019201C201D20222013201400980099009A009B009C009D009E009F 00A00E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F 0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F 0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F 0E300E310E320E330E340E350E360E370E380E390E3A00000000000000000E3F 0E400E410E420E430E440E450E460E470E480E490E4A0E4B0E4C0E4D0E4E0E4F 0E500E510E520E530E540E550E560E570E580E590E5A0E5B0000000000000000 tcl8.6.5/library/encoding/cp1256.enc0000644000175000017500000000210311555560473016425 0ustar sergeisergei# Encoding file: cp1256, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 20AC067E201A0192201E20262020202102C62030067920390152068606980688 06AF20182019201C201D20222013201406A921220691203A0153200C200D06BA 00A0060C00A200A300A400A500A600A700A800A906BE00AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B9061B00BB00BC00BD00BE061F 06C1062106220623062406250626062706280629062A062B062C062D062E062F 063006310632063306340635063600D7063706380639063A0640064106420643 00E0064400E2064506460647064800E700E800E900EA00EB0649064A00EE00EF 064B064C064D064E00F4064F065000F7065100F9065200FB00FC200E200F06D2 tcl8.6.5/library/encoding/cp869.enc0000644000175000017500000000210211555560473016355 0ustar sergeisergei# Encoding file: cp869, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850386008700B700AC00A620182019038820150389 038A03AA038C00930094038E03AB00A9038F00B200B303AC00A303AD03AE03AF 03CA039003CC03CD039103920393039403950396039700BD0398039900AB00BB 25912592259325022524039A039B039C039D256325512557255D039E039F2510 25142534252C251C2500253C03A003A1255A25542569256625602550256C03A3 03A403A503A603A703A803A903B103B203B32518250C2588258403B403B52580 03B603B703B803B903BA03BB03BC03BD03BE03BF03C003C103C303C203C40384 00AD00B103C503C603C700A703C8038500B000A803C903CB03B003CE25A000A0 tcl8.6.5/library/encoding/cp737.enc0000644000175000017500000000210211555560473016347 0ustar sergeisergei# Encoding file: cp737, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 039103920393039403950396039703980399039A039B039C039D039E039F03A0 03A103A303A403A503A603A703A803A903B103B203B303B403B503B603B703B8 03B903BA03BB03BC03BD03BE03BF03C003C103C303C203C403C503C603C703C8 259125922593250225242561256225562555256325512557255D255C255B2510 25142534252C251C2500253C255E255F255A25542569256625602550256C2567 2568256425652559255825522553256B256A2518250C25882584258C25902580 03C903AC03AD03AE03CA03AF03CC03CD03CB03CE038603880389038A038C038E 038F00B12265226403AA03AB00F7224800B0221900B7221A207F00B225A000A0 tcl8.6.5/library/encoding/macCyrillic.enc0000644000175000017500000000211011555560473017736 0ustar sergeisergei# Encoding file: macCyrillic, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0410041104120413041404150416041704180419041A041B041C041D041E041F 0420042104220423042404250426042704280429042A042B042C042D042E042F 202000B0049000A300A7202200B6040600AE00A9212204020452226004030453 221E00B122642265045600B504910408040404540407045704090459040A045A 0458040500AC221A01922248220600AB00BB202600A0040B045B040C045C0455 20132014201C201D2018201900F7201E040E045E040F045F211604010451044F 0430043104320433043404350436043704380439043A043B043C043D043E043F 0440044104420443044404450446044704480449044A044B044C044D044E20AC tcl8.6.5/library/encoding/iso8859-6.enc0000644000175000017500000000210611555560473017003 0ustar sergeisergei# Encoding file: iso8859-6, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A000000000000000A40000000000000000000000000000060C00AD00000000 00000000000000000000000000000000000000000000061B000000000000061F 0000062106220623062406250626062706280629062A062B062C062D062E062F 0630063106320633063406350636063706380639063A00000000000000000000 0640064106420643064406450646064706480649064A064B064C064D064E064F 0650065106520000000000000000000000000000000000000000000000000000 tcl8.6.5/library/encoding/iso8859-2.enc0000644000175000017500000000210611555560473016777 0ustar sergeisergei# Encoding file: iso8859-2, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A0010402D8014100A4013D015A00A700A80160015E0164017900AD017D017B 00B0010502DB014200B4013E015B02C700B80161015F0165017A02DD017E017C 015400C100C2010200C40139010600C7010C00C9011800CB011A00CD00CE010E 01100143014700D300D4015000D600D70158016E00DA017000DC00DD016200DF 015500E100E2010300E4013A010700E7010D00E9011900EB011B00ED00EE010F 01110144014800F300F4015100F600F70159016F00FA017100FC00FD016302D9 tcl8.6.5/library/encoding/iso2022.enc0000644000175000017500000000034211555560473016610 0ustar sergeisergei# Encoding file: iso2022, escape-driven E name iso2022 init {} final {} iso8859-1 \x1b(B jis0201 \x1b(J gb1988 \x1b(T jis0208 \x1b$B jis0208 \x1b$@ jis0212 \x1b$(D gb2312 \x1b$A ksc5601 \x1b$(C jis0208 \x1b&@\x1b$B tcl8.6.5/library/encoding/macRomania.enc0000644000175000017500000000210711555560473017560 0ustar sergeisergei# Encoding file: macRomania, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C400C500C700C900D100D600DC00E100E000E200E400E300E500E700E900E8 00EA00EB00ED00EC00EE00EF00F100F300F200F400F600F500FA00F900FB00FC 202000B000A200A300A7202200B600DF00AE00A9212200B400A822600102015E 221E00B12264226500A500B522022211220F03C0222B00AA00BA21260103015F 00BF00A100AC221A01922248220600AB00BB202600A000C000C300D501520153 20132014201C201D2018201900F725CA00FF0178204400A42039203A01620163 202100B7201A201E203000C200CA00C100CB00C800CD00CE00CF00CC00D300D4 F8FF00D200DA00DB00D9013102C602DC00AF02D802D902DA00B802DD02DB02C7 tcl8.6.5/library/encoding/gb2312-raw.enc0000644000175000017500000024506411555560473017213 0ustar sergeisergei# Encoding file: gb2312, double-byte D 233F 0 81 21 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030003001300230FB02C902C700A8300330052015FF5E2225202620182019 201C201D3014301530083009300A300B300C300D300E300F3016301730103011 00B100D700F72236222722282211220F222A222922082237221A22A522252220 23122299222B222E2261224C2248223D221D2260226E226F22642265221E2235 22342642264000B0203220332103FF0400A4FFE0FFE1203000A7211626062605 25CB25CF25CE25C725C625A125A025B325B2203B219221902191219330130000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 22 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000024882489248A248B248C248D248E248F2490249124922493249424952496 249724982499249A249B247424752476247724782479247A247B247C247D247E 247F248024812482248324842485248624872460246124622463246424652466 2467246824690000000032203221322232233224322532263227322832290000 00002160216121622163216421652166216721682169216A216B000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 23 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF01FF02FF03FFE5FF05FF06FF07FF08FF09FF0AFF0BFF0CFF0DFF0EFF0F FF10FF11FF12FF13FF14FF15FF16FF17FF18FF19FF1AFF1BFF1CFF1DFF1EFF1F FF20FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2F FF30FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3AFF3BFF3CFF3DFF3EFF3F FF40FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5AFF5BFF5CFF5DFFE30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 24 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000304130423043304430453046304730483049304A304B304C304D304E304F 3050305130523053305430553056305730583059305A305B305C305D305E305F 3060306130623063306430653066306730683069306A306B306C306D306E306F 3070307130723073307430753076307730783079307A307B307C307D307E307F 3080308130823083308430853086308730883089308A308B308C308D308E308F 3090309130923093000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 25 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF 30B030B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF 30C030C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF 30D030D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 26 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000039103920393039403950396039703980399039A039B039C039D039E039F 03A003A103A303A403A503A603A703A803A90000000000000000000000000000 000003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C303C403C503C603C703C803C90000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 27 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000004100411041204130414041504010416041704180419041A041B041C041D 041E041F0420042104220423042404250426042704280429042A042B042C042D 042E042F00000000000000000000000000000000000000000000000000000000 000004300431043204330434043504510436043704380439043A043B043C043D 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 28 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000010100E101CE00E0011300E9011B00E8012B00ED01D000EC014D00F301D2 00F2016B00FA01D400F901D601D801DA01DC00FC00EA00000000000000000000 0000000000000000000031053106310731083109310A310B310C310D310E310F 3110311131123113311431153116311731183119311A311B311C311D311E311F 3120312131223123312431253126312731283129000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 29 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000002500250125022503250425052506250725082509250A250B 250C250D250E250F2510251125122513251425152516251725182519251A251B 251C251D251E251F2520252125222523252425252526252725282529252A252B 252C252D252E252F2530253125322533253425352536253725382539253A253B 253C253D253E253F2540254125422543254425452546254725482549254A254B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 30 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000554A963F57C3632854CE550954C07691764C853C77EE827E788D72319698 978D6C285B894FFA630966975CB880FA684880AE660276CE51F9655671AC7FF1 888450B2596561CA6FB382AD634C625253ED54277B06516B75A45DF462D48DCB 9776628A8019575D97387F627238767D67CF767E64464F708D2562DC7A176591 73ED642C6273822C9881677F7248626E62CC4F3474E3534A529E7ECA90A65E2E 6886699C81807ED168D278C5868C9551508D8C2482DE80DE5305891252650000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 31 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000858496F94FDD582199715B9D62B162A566B48C799C8D7206676F789160B2 535153178F8880CC8D1D94A1500D72C8590760EB711988AB595482EF672C7B28 5D297EF7752D6CF58E668FF8903C9F3B6BD491197B145F7C78A784D6853D6BD5 6BD96BD65E015E8775F995ED655D5F0A5FC58F9F58C181C2907F965B97AD8FB9 7F168D2C62414FBF53D8535E8FA88FA98FAB904D68075F6A819888689CD6618B 522B762A5F6C658C6FD26EE85BBE6448517551B067C44E1979C9997C70B30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 32 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075C55E7673BB83E064AD62E894B56CE2535A52C3640F94C27B944F2F5E1B 82368116818A6E246CCA9A736355535C54FA886557E04E0D5E036B657C3F90E8 601664E6731C88C16750624D8D22776C8E2991C75F6983DC8521991053C28695 6B8B60ED60E8707F82CD82314ED36CA785CF64CD7CD969FD66F9834953957B56 4FA7518C6D4B5C428E6D63D253C9832C833667E578B4643D5BDF5C945DEE8BE7 62C667F48C7A640063BA8749998B8C177F2094F24EA7961098A4660C73160000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 33 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000573A5C1D5E38957F507F80A05382655E7545553150218D856284949E671D 56326F6E5DE2543570928F66626F64A463A35F7B6F8890F481E38FB05C186668 5FF16C8996488D81886C649179F057CE6A59621054484E587A0B60E96F848BDA 627F901E9A8B79E4540375F4630153196C608FDF5F1B9A70803B9F7F4F885C3A 8D647FC565A570BD514551B2866B5D075BA062BD916C75748E0C7A2061017B79 4EC77EF877854E1181ED521D51FA6A7153A88E87950496CF6EC19664695A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 34 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000784050A877D7641089E6590463E35DDD7A7F693D4F20823955984E3275AE 7A975E625E8A95EF521B5439708A6376952457826625693F918755076DF37EAF 882262337EF075B5832878C196CC8F9E614874F78BCD6B64523A8D506B21806A 847156F153064ECE4E1B51D17C97918B7C074FC38E7F7BE17A9C64675D1450AC 810676017CB96DEC7FE067515B585BF878CB64AE641363AA632B9519642D8FBE 7B5476296253592754466B7950A362345E266B864EE38D37888B5F85902E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 35 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006020803D62C54E39535590F863B880C665E66C2E4F4660EE6DE18BDE5F39 86CB5F536321515A83616863520063638E4850125C9B79775BFC52307A3B60BC 905376D75FB75F9776848E6C706F767B7B4977AA51F3909358244F4E6EF48FEA 654C7B1B72C46DA47FDF5AE162B55E95573084827B2C5E1D5F1F90127F1498A0 63826EC7789870B95178975B57AB75354F4375385E9760E659606DC06BBF7889 53FC96D551CB52016389540A94938C038DCC7239789F87768FED8C0D53E00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 36 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E0176EF53EE948998769F0E952D5B9A8BA24E224E1C51AC846361C252A8 680B4F97606B51BB6D1E515C6296659796618C46901775D890FD77636BD2728A 72EC8BFB583577798D4C675C9540809A5EA66E2159927AEF77ED953B6BB565AD 7F0E58065151961F5BF958A954288E726566987F56E4949D76FE9041638754C6 591A593A579B8EB267358DFA8235524160F0581586FE5CE89E454FC4989D8BB9 5A2560765384627C904F9102997F6069800C513F80335C1499756D314E8C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 37 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008D3053D17F5A7B4F4F104E4F96006CD573D085E95E06756A7FFB6A0A77FE 94927E4151E170E653CD8FD483038D2972AF996D6CDB574A82B365B980AA623F 963259A84EFF8BBF7EBA653E83F2975E556198DE80A5532A8BFD542080BA5E9F 6CB88D3982AC915A54296C1B52067EB7575F711A6C7E7C89594B4EFD5FFF6124 7CAA4E305C0167AB87025CF0950B98CE75AF70FD902251AF7F1D8BBD594951E4 4F5B5426592B657780A45B75627662C28F905E456C1F7B264F0F4FD8670D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 38 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D6E6DAA798F88B15F17752B629A8F854FEF91DC65A7812F81515E9C8150 8D74526F89868D4B590D50854ED8961C723681798D1F5BCC8BA3964459877F1A 54905676560E8BE565396982949976D66E895E727518674667D17AFF809D8D76 611F79C665628D635188521A94A27F38809B7EB25C976E2F67607BD9768B9AD8 818F7F947CD5641E95507A3F544A54E56B4C640162089E3D80F3759952729769 845B683C86E49601969494EC4E2A54047ED968398DDF801566F45E9A7FB90000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 39 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000057C2803F68975DE5653B529F606D9F9A4F9B8EAC516C5BAB5F135DE96C5E 62F18D21517194A952FE6C9F82DF72D757A267848D2D591F8F9C83C754957B8D 4F306CBD5B6459D19F1353E486CA9AA88C3780A16545987E56FA96C7522E74DC 52505BE1630289024E5662D0602A68FA51735B9851A089C27BA199867F5060EF 704C8D2F51495E7F901B747089C4572D78455F529F9F95FA8F689B3C8BE17678 684267DC8DEA8D35523D8F8A6EDA68CD950590ED56FD679C88F98FC754C80000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009AB85B696D776C264EA55BB39A87916361A890AF97E9542B6DB55BD251FD 558A7F557FF064BC634D65F161BE608D710A6C576C49592F676D822A58D5568E 8C6A6BEB90DD597D801753F76D695475559D837783CF683879BE548C4F555408 76D28C8996026CB36DB88D6B89109E648D3A563F9ED175D55F8872E0606854FC 4EA86A2A886160528F7054C470D886799E3F6D2A5B8F5F187EA255894FAF7334 543C539A5019540E547C4E4E5FFD745A58F6846B80E1877472D07CCA6E560000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F27864E552C62A44E926CAA623782B154D7534E733E6ED1753B52125316 8BDD69D05F8A60006DEE574F6B2273AF68538FD87F13636260A3552475EA8C62 71156DA35BA65E7B8352614C9EC478FA87577C27768751F060F6714C66435E4C 604D8C0E707063258F895FBD606286D456DE6BC160946167534960E066668D3F 79FD4F1A70E96C478BB38BF27ED88364660F5A5A9B426D516DF78C416D3B4F19 706B83B7621660D1970D8D27797851FB573E57FA673A75787A3D79EF7B950000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000808C99658FF96FC08BA59E2159EC7EE97F095409678168D88F917C4D96C6 53CA602575BE6C7253735AC97EA7632451E0810A5DF184DF628051805B634F0E 796D524260B86D4E5BC45BC28BA18BB065E25FCC964559937EE77EAA560967B7 59394F735BB652A0835A988A8D3E753294BE50477A3C4EF767B69A7E5AC16B7C 76D1575A5C167B3A95F4714E517C80A9827059787F04832768C067EC78B17877 62E363617B804FED526A51CF835069DB92748DF58D3189C1952E7BAD4EF60000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000506582305251996F6E106E856DA75EFA50F559DC5C066D466C5F7586848B 686859568BB253209171964D854969127901712680F64EA490CA6D479A845A07 56BC640594F077EB4FA5811A72E189D2997A7F347EDE527F655991758F7F8F83 53EB7A9663ED63A5768679F888579636622A52AB8282685467706377776B7AED 6D017ED389E359D0621285C982A5754C501F4ECB75A58BEB5C4A5DFE7B4B65A4 91D14ECA6D25895F7D2795264EC58C288FDB9773664B79818FD170EC6D780000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C3D52B283465162830E775B66769CB84EAC60CA7CBE7CB37ECF4E958B66 666F988897595883656C955C5F8475C997567ADF7ADE51C070AF7A9863EA7A76 7EA0739697ED4E4570784E5D915253A9655165E781FC8205548E5C31759A97A0 62D872D975BD5C459A7983CA5C40548077E94E3E6CAE805A62D2636E5DE85177 8DDD8E1E952F4FF153E560E770AC526763509E435A1F5026773753777EE26485 652B628963985014723589C951B38BC07EDD574783CC94A7519B541B5CFB0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004FCA7AE36D5A90E19A8F55805496536154AF5F0063E9697751EF6168520A 582A52D8574E780D770B5EB761777CE0625B62974EA27095800362F770E49760 577782DB67EF68F578D5989779D158F354B353EF6E34514B523B5BA28BFE80AF 554357A660735751542D7A7A60505B5463A762A053E362635BC767AF54ED7A9F 82E691775E9388E4593857AE630E8DE880EF57577B774FA95FEB5BBD6B3E5321 7B5072C2684677FF773665F751B54E8F76D45CBF7AA58475594E9B4150800000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 40 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000998861276E8357646606634656F062EC62695ED39614578362C955878721 814A8FA3556683B167658D5684DD5A6A680F62E67BEE961151706F9C8C3063FD 89C861D27F0670C26EE57405699472FC5ECA90CE67176D6A635E52B372628001 4F6C59E5916A70D96D9D52D24E5096F7956D857E78CA7D2F5121579264C2808B 7C7B6CEA68F1695E51B7539868A872819ECE7BF172F879BB6F137406674E91CC 9CA4793C83898354540F68174E3D538952B1783E5386522950884F8B4FD00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 41 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075E27ACB7C926CA596B6529B748354E94FE9805483B28FDE95705EC9601C 6D9F5E18655B813894FE604B70BC7EC37CAE51C968817CB1826F4E248F8691CF 667E4EAE8C0564A9804A50DA759771CE5BE58FBD6F664E86648295635ED66599 521788C270C852A3730E7433679778F797164E3490BB9CDE6DCB51DB8D41541D 62CE73B283F196F69F8494C34F367F9A51CC707596755CAD988653E64EE46E9C 740969B4786B998F7559521876246D4167F3516D9F99804B54997B3C7ABF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 42 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009686578462E29647697C5A0464027BD36F0F964B82A6536298855E907089 63B35364864F9C819E93788C97328DEF8D429E7F6F5E79845F559646622E9A74 541594DD4FA365C55C655C617F1586516C2F5F8B73876EE47EFF5CE6631B5B6A 6EE653754E7163A0756562A18F6E4F264ED16CA67EB68BBA841D87BA7F57903B 95237BA99AA188F8843D6D1B9A867EDC59889EBB739B780186829A6C9A82561B 541757CB4E709EA653568FC881097792999286EE6EE1851366FC61626F2B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 43 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008C298292832B76F26C135FD983BD732B8305951A6BDB77DB94C6536F8302 51925E3D8C8C8D384E4873AB679A68859176970971646CA177095A9295416BCF 7F8E66275BD059B95A9A95E895F74EEC840C84996AAC76DF9530731B68A65B5F 772F919A97617CDC8FF78C1C5F257C7379D889C56CCC871C5BC65E4268C97720 7EF55195514D52C95A297F05976282D763CF778485D079D26E3A5E9959998511 706D6C1162BF76BF654F60AF95FD660E879F9E2394ED540D547D8C2C64780000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 44 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000647986116A21819C78E864699B5462B9672B83AB58A89ED86CAB6F205BDE 964C8C0B725F67D062C772614EA959C66BCD589366AE5E5552DF6155672876EE 776672677A4662FF54EA545094A090A35A1C7EB36C164E435976801059485357 753796BE56CA63208111607C95F96DD65462998151855AE980FD59AE9713502A 6CE55C3C62DF4F60533F817B90066EBA852B62C85E7478BE64B5637B5FF55A18 917F9E1F5C3F634F80425B7D556E954A954D6D8560A867E072DE51DD5B810000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 45 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000062E76CDE725B626D94AE7EBD81136D53519C5F04597452AA601259736696 8650759F632A61E67CEF8BFA54E66B279E256BB485D5545550766CA4556A8DB4 722C5E156015743662CD6392724C5F986E436D3E65006F5876D878D076FC7554 522453DB4E535E9E65C1802A80D6629B5486522870AE888D8DD16CE1547880DA 57F988F48D54966A914D4F696C9B55B776C6783062A870F96F8E5F6D84EC68DA 787C7BF781A8670B9E4F636778B0576F78129739627962AB528874356BD70000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 46 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005564813E75B276AE533975DE50FB5C418B6C7BC7504F72479A9798D86F02 74E27968648777A562FC98918D2B54C180584E52576A82F9840D5E7351ED74F6 8BC45C4F57616CFC98875A4678349B448FEB7C955256625194FA4EC683868461 83E984B257D467345703666E6D668C3166DD7011671F6B3A6816621A59BB4E03 51C46F0667D26C8F517668CB59476B6775665D0E81109F5065D7794879419A91 8D775C824E5E4F01542F5951780C56686C148FC45F036C7D6CE38BAB63900000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 47 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000060706D3D72756266948E94C553438FC17B7E4EDF8C264E7E9ED494B194B3 524D6F5C90636D458C3458115D4C6B206B4967AA545B81547F8C589985375F3A 62A26A47953965726084686577A74E544FA85DE7979864AC7FD85CED4FCF7A8D 520783044E14602F7A8394A64FB54EB279E6743452E482B964D279BD5BDD6C81 97528F7B6C22503E537F6E0564CE66746C3060C598778BF75E86743C7A7779CB 4E1890B174036C4256DA914B6CC58D8B533A86C666F28EAF5C489A716E200000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000053D65A369F8B8DA353BB570898A76743919B6CC9516875CA62F372AC5238 529D7F3A7094763853749E4A69B7786E96C088D97FA4713671C3518967D374E4 58E4651856B78BA9997662707ED560F970ED58EC4EC14EBA5FCD97E74EFB8BA4 5203598A7EAB62544ECD65E5620E833884C98363878D71946EB65BB97ED25197 63C967D480898339881551125B7A59828FB14E736C5D516589258F6F962E854A 745E951095F06DA682E55F3164926D128428816E9CC3585E8D5B4E0953C10000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 49 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F1E6563685155D34E2764149A9A626B5AC2745F82726DA968EE50E7838E 7802674052396C997EB150BB5565715E7B5B665273CA82EB67495C715220717D 886B95EA965564C58D6181B355846C5562477F2E58924F2455468D4F664C4E0A 5C1A88F368A2634E7A0D70E7828D52FA97F65C1154E890B57ECD59628D4A86C7 820C820D8D6664445C0461516D89793E8BBE78377533547B4F388EAB6DF15A20 7EC5795E6C885BA15A76751A80BE614E6E1758F0751F7525727253477EF30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000770176DB526980DC57235E08593172EE65BD6E7F8BD75C388671534177F3 62FE65F64EC098DF86805B9E8BC653F277E24F7F5C4E9A7659CB5F0F793A58EB 4E1667FF4E8B62ED8A93901D52BF662F55DC566C90024ED54F8D91CA99706C0F 5E0260435BA489C68BD56536624B99965B885BFF6388552E53D77626517D852C 67A268B36B8A62928F9353D482126DD1758F4E668D4E5B70719F85AF669166D9 7F7287009ECD9F205C5E672F8FF06811675F620D7AD658855EB665706F310000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000060555237800D6454887075295E05681362F4971C53CC723D8C016C347761 7A0E542E77AC987A821C8BF47855671470C165AF64955636601D79C153F84E1D 6B7B80865BFA55E356DB4F3A4F3C99725DF3677E80386002988290015B8B8BBC 8BF5641C825864DE55FD82CF91654FD77D20901F7C9F50F358516EAF5BBF8BC9 80839178849C7B97867D968B968F7EE59AD3788E5C817A57904296A7795F5B59 635F7B0B84D168AD55067F2974107D2295016240584C4ED65B83597958540000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000736D631E8E4B8E0F80CE82D462AC53F06CF0915E592A60016C70574D644A 8D2A762B6EE9575B6A8075F06F6D8C2D8C0857666BEF889278B363A253F970AD 6C645858642A580268E0819B55107CD650188EBA6DCC8D9F70EB638F6D9B6ED4 7EE68404684390036DD896768BA85957727985E4817E75BC8A8A68AF52548E22 951163D098988E44557C4F5366FF568F60D56D9552435C4959296DFB586B7530 751C606C82148146631167618FE2773A8DF38D3494C15E165385542C70C30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006C405EF7505C4EAD5EAD633A8247901A6850916E77B3540C94DC5F647AE5 687663457B527EDF75DB507762955934900F51F879C37A8156FE5F9290146D82 5C60571F541051546E4D56E263A89893817F8715892A9000541E5C6F81C062D6 625881319E3596409A6E9A7C692D59A562D3553E631654C786D96D3C5A0374E6 889C6B6A59168C4C5F2F6E7E73A9987D4E3870F75B8C7897633D665A769660CB 5B9B5A494E0781556C6A738B4EA167897F515F8065FA671B5FD859845A010000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005DCD5FAE537197E68FDD684556F4552F60DF4E3A6F4D7EF482C7840E59D4 4F1F4F2A5C3E7EAC672A851A5473754F80C355829B4F4F4D6E2D8C135C096170 536B761F6E29868A658795FB7EB9543B7A337D0A95EE55E17FC174EE631D8717 6DA17A9D621165A1536763E16C835DEB545C94A84E4C6C618BEC5C4B65E0829C 68A7543E54346BCB6B664E9463425348821E4F0D4FAE575E620A96FE66647269 52FF52A1609F8BEF661471996790897F785277FD6670563B54389521727A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A00606F5E0C6089819D591560DC718470EF6EAA6C5072806A8488AD5E2D 4E605AB3559C94E36D177CFB9699620F7EC6778E867E5323971E8F9666875CE1 4FA072ED4E0B53A6590F54136380952851484ED99C9C7EA454B88D2488548237 95F26D8E5F265ACC663E966973B0732E53BF817A99857FA15BAA967796507EBF 76F853A2957699997BB189446E584E617FD479658BE660F354CD4EAB98795DF7 6A6150CF54118C618427785D9704524A54EE56A395006D885BB56DC666530000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 50 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C0F5B5D6821809655787B11654869544E9B6B47874E978B534F631F643A 90AA659C80C18C10519968B0537887F961C86CC46CFB8C225C5185AA82AF950C 6B238F9B65B05FFB5FC34FE18845661F8165732960FA51745211578B5F6290A2 884C91925E78674F602759D3514451F680F853086C7996C4718A4F114FEE7F9E 673D55C5950879C088967EE3589F620C9700865A5618987B5F908BB884C49157 53D965ED5E8F755C60647D6E5A7F7EEA7EED8F6955A75BA360AC65CB73840000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 51 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009009766377297EDA9774859B5B667A7496EA884052CB718F5FAA65EC8BE2 5BFB9A6F5DE16B896C5B8BAD8BAF900A8FC5538B62BC9E269E2D54404E2B82BD 7259869C5D1688596DAF96C554D14E9A8BB6710954BD960970DF6DF976D04E25 781487125CA95EF68A00989C960E708E6CBF594463A9773C884D6F1482735830 71D5538C781A96C155015F6671305BB48C1A9A8C6B83592E9E2F79E76768626C 4F6F75A17F8A6D0B96336C274EF075D2517B68376F3E90808170599674760000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 52 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000064475C2790657A918C2359DA54AC8200836F898180006930564E80367237 91CE51B64E5F987563964E1A53F666F3814B591C6DB24E0058F9533B63D694F1 4F9D4F0A886398905937905779FB4EEA80F075916C825B9C59E85F5D69058681 501A5DF24E5977E34EE5827A6291661390915C794EBF5F7981C69038808475AB 4EA688D4610F6BC55FC64E4976CA6EA28BE38BAE8C0A8BD15F027FFC7FCC7ECE 8335836B56E06BB797F3963459FB541F94F66DEB5BC5996E5C395F1596900000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 53 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000537082F16A315A749E705E947F2883B984248425836787478FCE8D6276C8 5F719896786C662054DF62E54F6381C375C85EB896CD8E0A86F9548F6CF36D8C 6C38607F52C775285E7D4F1860A05FE75C24753190AE94C072B96CB96E389149 670953CB53F34F5191C98BF153C85E7C8FC26DE44E8E76C26986865E611A8206 4F594FDE903E9C7C61096E1D6E1496854E885A3196E84E0E5C7F79B95B878BED 7FBD738957DF828B90C15401904755BB5CEA5FA161086B3272F180B28A890000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D745BD388D598848C6B9A6D9E336E0A51A4514357A38881539F63F48F95 56ED54585706733F6E907F188FDC82D1613F6028966266F07EA68D8A8DC394A5 5CB37CA4670860A6960580184E9190E75300966851418FD08574915D665597F5 5B55531D78386742683D54C9707E5BB08F7D518D572854B1651266828D5E8D43 810F846C906D7CDF51FF85FB67A365E96FA186A48E81566A90207682707671E5 8D2362E952196CFD8D3C600E589E618E66FE8D60624E55B36E23672D8F670000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 55 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000094E195F87728680569A8548B4E4D70B88BC86458658B5B857A84503A5BE8 77BB6BE18A797C986CBE76CF65A98F975D2D5C5586386808536062187AD96E5B 7EFD6A1F7AE05F706F335F20638C6DA867564E085E108D264ED780C07634969C 62DB662D627E6CBC8D7571677F695146808753EC906E629854F286F08F998005 951785178FD96D5973CD659F771F7504782781FB8D1E94884FA6679575B98BCA 9707632F9547963584B8632377415F8172F04E896014657462EF6B63653F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 56 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005E2775C790D18BC1829D679D652F5431871877E580A281026C414E4B7EC7 804C76F4690D6B966267503C4F84574063076B628DBE53EA65E87EB85FD7631A 63B781F381F47F6E5E1C5CD95236667A79E97A1A8D28709975D46EDE6CBB7A92 4E2D76C55FE0949F88777EC879CD80BF91CD4EF24F17821F54685DDE6D328BCC 7CA58F7480985E1A549276B15B99663C9AA473E0682A86DB6731732A8BF88BDB 90107AF970DB716E62C477A956314E3B845767F152A986C08D2E94F87B510000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 57 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F4F6CE8795D9A7B6293722A62FD4E1378168F6C64B08D5A7BC668695E84 88C55986649E58EE72B6690E95258FFD8D5857607F008C0651C6634962D95353 684C74228301914C55447740707C6D4A517954A88D4459FF6ECB6DC45B5C7D2B 4ED47C7D6ED35B5081EA6E0D5B579B0368D58E2A5B977EFC603B7EB590B98D70 594F63CD79DF8DB3535265CF79568BC5963B7EC494BB7E825634918967007F6A 5C0A907566285DE64F5067DE505A4F5C57505EA7000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 58 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E8D4E0C51404E105EFF53454E154E984E1E9B325B6C56694E2879BA4E3F 53154E47592D723B536E6C1056DF80E499976BD3777E9F174E364E9F9F104E5C 4E694E9382885B5B556C560F4EC4538D539D53A353A553AE97658D5D531A53F5 5326532E533E8D5C5366536352025208520E522D5233523F5240524C525E5261 525C84AF527D528252815290529351827F544EBB4EC34EC94EC24EE84EE14EEB 4EDE4F1B4EF34F224F644EF54F254F274F094F2B4F5E4F6765384F5A4F5D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 59 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F5F4F574F324F3D4F764F744F914F894F834F8F4F7E4F7B4FAA4F7C4FAC 4F944FE64FE84FEA4FC54FDA4FE34FDC4FD14FDF4FF85029504C4FF3502C500F 502E502D4FFE501C500C50255028507E504350555048504E506C507B50A550A7 50A950BA50D6510650ED50EC50E650EE5107510B4EDD6C3D4F584F654FCE9FA0 6C467C74516E5DFD9EC999985181591452F9530D8A07531051EB591951554EA0 51564EB3886E88A44EB5811488D279805B3488037FB851AB51B151BD51BC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000051C7519651A251A58BA08BA68BA78BAA8BB48BB58BB78BC28BC38BCB8BCF 8BCE8BD28BD38BD48BD68BD88BD98BDC8BDF8BE08BE48BE88BE98BEE8BF08BF3 8BF68BF98BFC8BFF8C008C028C048C078C0C8C0F8C118C128C148C158C168C19 8C1B8C188C1D8C1F8C208C218C258C278C2A8C2B8C2E8C2F8C328C338C358C36 5369537A961D962296219631962A963D963C964296499654965F9667966C9672 96749688968D969796B09097909B909D909990AC90A190B490B390B690BA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000090B890B090CF90C590BE90D090C490C790D390E690E290DC90D790DB90EB 90EF90FE91049122911E91239131912F913991439146520D594252A252AC52AD 52BE54FF52D052D652F053DF71EE77CD5EF451F551FC9B2F53B65F01755A5DEF 574C57A957A1587E58BC58C558D15729572C572A57335739572E572F575C573B 574257695785576B5786577C577B5768576D5776577357AD57A4578C57B257CF 57A757B4579357A057D557D857DA57D957D257B857F457EF57F857E457DD0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000580B580D57FD57ED5800581E5819584458205865586C58815889589A5880 99A89F1961FF8279827D827F828F828A82A88284828E82918297829982AB82B8 82BE82B082C882CA82E3829882B782AE82CB82CC82C182A982B482A182AA829F 82C482CE82A482E1830982F782E4830F830782DC82F482D282D8830C82FB82D3 8311831A83068314831582E082D5831C8351835B835C83088392833C83348331 839B835E832F834F83478343835F834083178360832D833A8333836683650000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008368831B8369836C836A836D836E83B0837883B383B483A083AA8393839C 8385837C83B683A9837D83B8837B8398839E83A883BA83BC83C1840183E583D8 58078418840B83DD83FD83D6841C84388411840683D483DF840F840383F883F9 83EA83C583C0842683F083E1845C8451845A8459847384878488847A84898478 843C844684698476848C848E8431846D84C184CD84D084E684BD84D384CA84BF 84BA84E084A184B984B4849784E584E3850C750D853884F08539851F853A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008556853B84FF84FC8559854885688564855E857A77A285438572857B85A4 85A88587858F857985AE859C858585B985B785B085D385C185DC85FF86278605 86298616863C5EFE5F08593C594180375955595A5958530F5C225C255C2C5C34 624C626A629F62BB62CA62DA62D762EE632262F66339634B634363AD63F66371 637A638E63B4636D63AC638A636963AE63BC63F263F863E063FF63C463DE63CE 645263C663BE64456441640B641B6420640C64266421645E6484646D64960000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000647A64B764B8649964BA64C064D064D764E464E265096525652E5F0B5FD2 75195F11535F53F153FD53E953E853FB541254165406544B5452545354545456 54435421545754595423543254825494547754715464549A549B548454765466 549D54D054AD54C254B454D254A754A654D354D4547254A354D554BB54BF54CC 54D954DA54DC54A954AA54A454DD54CF54DE551B54E7552054FD551454F35522 5523550F55115527552A5567558F55B55549556D55415555553F5550553C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 60 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005537555655755576557755335530555C558B55D2558355B155B955885581 559F557E55D65591557B55DF55BD55BE5594559955EA55F755C9561F55D155EB 55EC55D455E655DD55C455EF55E555F255F355CC55CD55E855F555E48F94561E 5608560C56015624562355FE56005627562D565856395657562C564D56625659 565C564C5654568656645671566B567B567C5685569356AF56D456D756DD56E1 56F556EB56F956FF5704570A5709571C5E0F5E195E145E115E315E3B5E3C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 61 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005E375E445E545E5B5E5E5E615C8C5C7A5C8D5C905C965C885C985C995C91 5C9A5C9C5CB55CA25CBD5CAC5CAB5CB15CA35CC15CB75CC45CD25CE45CCB5CE5 5D025D035D275D265D2E5D245D1E5D065D1B5D585D3E5D345D3D5D6C5D5B5D6F 5D5D5D6B5D4B5D4A5D695D745D825D995D9D8C735DB75DC55F735F775F825F87 5F895F8C5F955F995F9C5FA85FAD5FB55FBC88625F6172AD72B072B472B772B8 72C372C172CE72CD72D272E872EF72E972F272F472F7730172F3730372FA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 62 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000072FB731773137321730A731E731D7315732273397325732C733873317350 734D73577360736C736F737E821B592598E7592459029963996799689969996A 996B996C99749977997D998099849987998A998D999099919993999499955E80 5E915E8B5E965EA55EA05EB95EB55EBE5EB38D535ED25ED15EDB5EE85EEA81BA 5FC45FC95FD65FCF60035FEE60045FE15FE45FFE600560065FEA5FED5FF86019 60356026601B600F600D6029602B600A603F602160786079607B607A60420000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 63 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000606A607D6096609A60AD609D60836092608C609B60EC60BB60B160DD60D8 60C660DA60B4612061266115612360F46100610E612B614A617561AC619461A7 61B761D461F55FDD96B395E995EB95F195F395F595F695FC95FE960396049606 9608960A960B960C960D960F96129615961696179619961A4E2C723F62156C35 6C546C5C6C4A6CA36C856C906C946C8C6C686C696C746C766C866CA96CD06CD4 6CAD6CF76CF86CF16CD76CB26CE06CD66CFA6CEB6CEE6CB16CD36CEF6CFE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 64 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D396D276D0C6D436D486D076D046D196D0E6D2B6D4D6D2E6D356D1A6D4F 6D526D546D336D916D6F6D9E6DA06D5E6D936D946D5C6D606D7C6D636E1A6DC7 6DC56DDE6E0E6DBF6DE06E116DE66DDD6DD96E166DAB6E0C6DAE6E2B6E6E6E4E 6E6B6EB26E5F6E866E536E546E326E256E446EDF6EB16E986EE06F2D6EE26EA5 6EA76EBD6EBB6EB76ED76EB46ECF6E8F6EC26E9F6F626F466F476F246F156EF9 6F2F6F366F4B6F746F2A6F096F296F896F8D6F8C6F786F726F7C6F7A6FD10000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 65 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006FC96FA76FB96FB66FC26FE16FEE6FDE6FE06FEF701A7023701B70397035 704F705E5B805B845B955B935BA55BB8752F9A9E64345BE45BEE89305BF08E47 8B078FB68FD38FD58FE58FEE8FE48FE98FE68FF38FE890059004900B90269011 900D9016902190359036902D902F9044905190529050906890589062905B66B9 9074907D908290889083908B5F505F575F565F585C3B54AB5C505C595B715C63 5C667FBC5F2A5F295F2D82745F3C9B3B5C6E59815983598D59A959AA59A30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 66 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000599759CA59AB599E59A459D259B259AF59D759BE5A055A0659DD5A0859E3 59D859F95A0C5A095A325A345A115A235A135A405A675A4A5A555A3C5A625A75 80EC5AAA5A9B5A775A7A5ABE5AEB5AB25AD25AD45AB85AE05AE35AF15AD65AE6 5AD85ADC5B095B175B165B325B375B405C155C1C5B5A5B655B735B515B535B62 9A759A779A789A7A9A7F9A7D9A809A819A859A889A8A9A909A929A939A969A98 9A9B9A9C9A9D9A9F9AA09AA29AA39AA59AA77E9F7EA17EA37EA57EA87EA90000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 67 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007EAD7EB07EBE7EC07EC17EC27EC97ECB7ECC7ED07ED47ED77EDB7EE07EE1 7EE87EEB7EEE7EEF7EF17EF27F0D7EF67EFA7EFB7EFE7F017F027F037F077F08 7F0B7F0C7F0F7F117F127F177F197F1C7F1B7F1F7F217F227F237F247F257F26 7F277F2A7F2B7F2C7F2D7F2F7F307F317F327F337F355E7A757F5DDB753E9095 738E739173AE73A2739F73CF73C273D173B773B373C073C973C873E573D9987C 740A73E973E773DE73BA73F2740F742A745B7426742574287430742E742C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 68 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000741B741A7441745C7457745574597477746D747E749C748E748074817487 748B749E74A874A9749074A774D274BA97EA97EB97EC674C6753675E67486769 67A56787676A6773679867A7677567A8679E67AD678B6777677C67F0680967D8 680A67E967B0680C67D967B567DA67B367DD680067C367B867E2680E67C167FD 6832683368606861684E6862684468646883681D68556866684168676840683E 684A6849682968B5688F687468776893686B68C2696E68FC691F692068F90000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 69 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000692468F0690B6901695768E369106971693969606942695D6984696B6980 69986978693469CC6987698869CE6989696669636979699B69A769BB69AB69AD 69D469B169C169CA69DF699569E0698D69FF6A2F69ED6A176A186A6569F26A44 6A3E6AA06A506A5B6A356A8E6A796A3D6A286A586A7C6A916A906AA96A976AAB 733773526B816B826B876B846B926B936B8D6B9A6B9B6BA16BAA8F6B8F6D8F71 8F728F738F758F768F788F778F798F7A8F7C8F7E8F818F828F848F878F8B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008F8D8F8E8F8F8F988F9A8ECE620B6217621B621F6222622162256224622C 81E774EF74F474FF750F75117513653465EE65EF65F0660A6619677266036615 6600708566F7661D66346631663666358006665F66546641664F665666616657 66776684668C66A7669D66BE66DB66DC66E666E98D328D338D368D3B8D3D8D40 8D458D468D488D498D478D4D8D558D5989C789CA89CB89CC89CE89CF89D089D1 726E729F725D7266726F727E727F7284728B728D728F72926308633263B00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000643F64D880046BEA6BF36BFD6BF56BF96C056C076C066C0D6C156C186C19 6C1A6C216C296C246C2A6C3265356555656B724D72527256723086625216809F 809C809380BC670A80BD80B180AB80AD80B480B780E780E880E980EA80DB80C2 80C480D980CD80D7671080DD80EB80F180F480ED810D810E80F280FC67158112 8C5A8136811E812C811881328148814C815381748159815A817181608169817C 817D816D8167584D5AB58188818281916ED581A381AA81CC672681CA81BB0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000081C181A66B246B376B396B436B466B5998D198D298D398D598D998DA6BB3 5F406BC289F365909F51659365BC65C665C465C365CC65CE65D265D67080709C 7096709D70BB70C070B770AB70B170E870CA711071137116712F71317173715C 716871457172714A7178717A719871B371B571A871A071E071D471E771F9721D 7228706C7118716671B9623E623D624362486249793B794079467949795B795C 7953795A796279577960796F7967797A7985798A799A79A779B35FD15FD00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000603C605D605A606760416059606360AB6106610D615D61A9619D61CB61D1 62068080807F6C936CF66DFC77F677F87800780978177818781165AB782D781C 781D7839783A783B781F783C7825782C78237829784E786D7856785778267850 7847784C786A789B7893789A7887789C78A178A378B278B978A578D478D978C9 78EC78F2790578F479137924791E79349F9B9EF99EFB9EFC76F17704770D76F9 77077708771A77227719772D7726773577387750775177477743775A77680000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077627765777F778D777D7780778C7791779F77A077B077B577BD753A7540 754E754B7548755B7572757975837F587F617F5F8A487F687F747F717F797F81 7F7E76CD76E58832948594869487948B948A948C948D948F9490949494979495 949A949B949C94A394A494AB94AA94AD94AC94AF94B094B294B494B694B794B8 94B994BA94BC94BD94BF94C494C894C994CA94CB94CC94CD94CE94D094D194D2 94D594D694D794D994D894DB94DE94DF94E094E294E494E594E794E894EA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000094E994EB94EE94EF94F394F494F594F794F994FC94FD94FF950395029506 95079509950A950D950E950F951295139514951595169518951B951D951E951F 9522952A952B9529952C953195329534953695379538953C953E953F95429535 9544954595469549954C954E954F9552955395549556955795589559955B955E 955F955D95619562956495659566956795689569956A956B956C956F95719572 9573953A77E777EC96C979D579ED79E379EB7A065D477A037A027A1E7A140000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 70 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A397A377A519ECF99A57A707688768E7693769976A474DE74E0752C9E20 9E229E289E299E2A9E2B9E2C9E329E319E369E389E379E399E3A9E3E9E419E42 9E449E469E479E489E499E4B9E4C9E4E9E519E559E579E5A9E5B9E5C9E5E9E63 9E669E679E689E699E6A9E6B9E6C9E719E6D9E7375927594759675A0759D75AC 75A375B375B475B875C475B175B075C375C275D675CD75E375E875E675E475EB 75E7760375F175FC75FF761076007605760C7617760A76257618761576190000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 71 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000761B763C762276207640762D7630763F76357643763E7633764D765E7654 765C7656766B766F7FCA7AE67A787A797A807A867A887A957AA67AA07AAC7AA8 7AAD7AB3886488698872887D887F888288A288C688B788BC88C988E288CE88E3 88E588F1891A88FC88E888FE88F0892189198913891B890A8934892B89368941 8966897B758B80E576B276B477DC801280148016801C80208022802580268027 802980288031800B803580438046804D80528069807189839878988098830000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 72 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009889988C988D988F9894989A989B989E989F98A198A298A598A6864D8654 866C866E867F867A867C867B86A8868D868B86AC869D86A786A386AA869386A9 86B686C486B586CE86B086BA86B186AF86C986CF86B486E986F186F286ED86F3 86D0871386DE86F486DF86D886D18703870786F88708870A870D87098723873B 871E8725872E871A873E87488734873187298737873F87828722877D877E877B 87608770874C876E878B87538763877C876487598765879387AF87A887D20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 73 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000087C68788878587AD8797878387AB87E587AC87B587B387CB87D387BD87D1 87C087CA87DB87EA87E087EE8816881387FE880A881B88218839883C7F367F42 7F447F4582107AFA7AFD7B087B037B047B157B0A7B2B7B0F7B477B387B2A7B19 7B2E7B317B207B257B247B337B3E7B1E7B587B5A7B457B757B4C7B5D7B607B6E 7B7B7B627B727B717B907BA67BA77BB87BAC7B9D7BA87B857BAA7B9C7BA27BAB 7BB47BD17BC17BCC7BDD7BDA7BE57BE67BEA7C0C7BFE7BFC7C0F7C167C0B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 74 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007C1F7C2A7C267C387C417C4081FE82018202820481EC8844822182228223 822D822F8228822B8238823B82338234823E82448249824B824F825A825F8268 887E8885888888D888DF895E7F9D7F9F7FA77FAF7FB07FB27C7C65497C917C9D 7C9C7C9E7CA27CB27CBC7CBD7CC17CC77CCC7CCD7CC87CC57CD77CE8826E66A8 7FBF7FCE7FD57FE57FE17FE67FE97FEE7FF37CF87D777DA67DAE7E477E9B9EB8 9EB48D738D848D948D918DB18D678D6D8C478C49914A9150914E914F91640000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 75 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009162916191709169916F917D917E917291749179918C91859190918D9191 91A291A391AA91AD91AE91AF91B591B491BA8C559E7E8DB88DEB8E058E598E69 8DB58DBF8DBC8DBA8DC48DD68DD78DDA8DDE8DCE8DCF8DDB8DC68DEC8DF78DF8 8DE38DF98DFB8DE48E098DFD8E148E1D8E1F8E2C8E2E8E238E2F8E3A8E408E39 8E358E3D8E318E498E418E428E518E528E4A8E708E768E7C8E6F8E748E858E8F 8E948E908E9C8E9E8C788C828C8A8C858C988C94659B89D689DE89DA89DC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 76 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000089E589EB89EF8A3E8B26975396E996F396EF970697019708970F970E972A 972D9730973E9F809F839F859F869F879F889F899F8A9F8C9EFE9F0B9F0D96B9 96BC96BD96CE96D277BF96E0928E92AE92C8933E936A93CA938F943E946B9C7F 9C829C859C869C879C887A239C8B9C8E9C909C919C929C949C959C9A9C9B9C9E 9C9F9CA09CA19CA29CA39CA59CA69CA79CA89CA99CAB9CAD9CAE9CB09CB19CB2 9CB39CB49CB59CB69CB79CBA9CBB9CBC9CBD9CC49CC59CC69CC79CCA9CCB0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 77 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009CCC9CCD9CCE9CCF9CD09CD39CD49CD59CD79CD89CD99CDC9CDD9CDF9CE2 977C978597919792979497AF97AB97A397B297B49AB19AB09AB79E589AB69ABA 9ABC9AC19AC09AC59AC29ACB9ACC9AD19B459B439B479B499B489B4D9B5198E8 990D992E995599549ADF9AE19AE69AEF9AEB9AFB9AED9AF99B089B0F9B139B1F 9B239EBD9EBE7E3B9E829E879E889E8B9E9293D69E9D9E9F9EDB9EDC9EDD9EE0 9EDF9EE29EE99EE79EE59EEA9EEF9F229F2C9F2F9F399F379F3D9F3E9F440000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 tcl8.6.5/library/encoding/macRoman.enc0000644000175000017500000000210511555560473017244 0ustar sergeisergei# Encoding file: macRoman, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C400C500C700C900D100D600DC00E100E000E200E400E300E500E700E900E8 00EA00EB00ED00EC00EE00EF00F100F300F200F400F600F500FA00F900FB00FC 202000B000A200A300A7202200B600DF00AE00A9212200B400A8226000C600D8 221E00B12264226500A500B522022211220F03C0222B00AA00BA03A900E600F8 00BF00A100AC221A01922248220600AB00BB202600A000C000C300D501520153 20132014201C201D2018201900F725CA00FF0178204420AC2039203AFB01FB02 202100B7201A201E203000C200CA00C100CB00C800CD00CE00CF00CC00D300D4 F8FF00D200DA00DB00D9013102C602DC00AF02D802D902DA00B802DD02DB02C7 tcl8.6.5/library/encoding/cp1253.enc0000644000175000017500000000210311555560473016422 0ustar sergeisergei# Encoding file: cp1253, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 20AC0081201A0192201E20262020202100882030008A2039008C008D008E008F 009020182019201C201D20222013201400982122009A203A009C009D009E009F 00A00385038600A300A400A500A600A700A800A9000000AB00AC00AD00AE2015 00B000B100B200B3038400B500B600B703880389038A00BB038C00BD038E038F 0390039103920393039403950396039703980399039A039B039C039D039E039F 03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF 03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C203C303C403C503C603C703C803C903CA03CB03CC03CD03CE0000 tcl8.6.5/library/encoding/tis-620.enc0000644000175000017500000000210311555560473016611 0ustar sergeisergei# Encoding file: tis-620, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F 0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F 0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F 0E300E310E320E330E340E350E360E370E380E390E3A00000000000000000E3F 0E400E410E420E430E440E450E460E470E480E490E4A0E4B0E4C0E4D0E4E0E4F 0E500E510E520E530E540E550E560E570E580E590E5A0E5B0000000000000000tcl8.6.5/library/encoding/cp949.enc0000644000175000017500000037656711555560473016411 0ustar sergeisergei# Encoding file: cp949, multi-byte M 003F 0 125 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 81 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000AC02AC03AC05AC06AC0BAC0CAC0DAC0EAC0FAC18AC1EAC1FAC21AC22AC23 AC25AC26AC27AC28AC29AC2AAC2BAC2EAC32AC33AC3400000000000000000000 0000AC35AC36AC37AC3AAC3BAC3DAC3EAC3FAC41AC42AC43AC44AC45AC46AC47 AC48AC49AC4AAC4CAC4EAC4FAC50AC51AC52AC53AC5500000000000000000000 0000AC56AC57AC59AC5AAC5BAC5DAC5EAC5FAC60AC61AC62AC63AC64AC65AC66 AC67AC68AC69AC6AAC6BAC6CAC6DAC6EAC6FAC72AC73AC75AC76AC79AC7BAC7C AC7DAC7EAC7FAC82AC87AC88AC8DAC8EAC8FAC91AC92AC93AC95AC96AC97AC98 AC99AC9AAC9BAC9EACA2ACA3ACA4ACA5ACA6ACA7ACABACADACAEACB1ACB2ACB3 ACB4ACB5ACB6ACB7ACBAACBEACBFACC0ACC2ACC3ACC5ACC6ACC7ACC9ACCAACCB ACCDACCEACCFACD0ACD1ACD2ACD3ACD4ACD6ACD8ACD9ACDAACDBACDCACDDACDE ACDFACE2ACE3ACE5ACE6ACE9ACEBACEDACEEACF2ACF4ACF7ACF8ACF9ACFAACFB ACFEACFFAD01AD02AD03AD05AD07AD08AD09AD0AAD0BAD0EAD10AD12AD130000 82 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000AD14AD15AD16AD17AD19AD1AAD1BAD1DAD1EAD1FAD21AD22AD23AD24AD25 AD26AD27AD28AD2AAD2BAD2EAD2FAD30AD31AD32AD3300000000000000000000 0000AD36AD37AD39AD3AAD3BAD3DAD3EAD3FAD40AD41AD42AD43AD46AD48AD4A AD4BAD4CAD4DAD4EAD4FAD51AD52AD53AD55AD56AD5700000000000000000000 0000AD59AD5AAD5BAD5CAD5DAD5EAD5FAD60AD62AD64AD65AD66AD67AD68AD69 AD6AAD6BAD6EAD6FAD71AD72AD77AD78AD79AD7AAD7EAD80AD83AD84AD85AD86 AD87AD8AAD8BAD8DAD8EAD8FAD91AD92AD93AD94AD95AD96AD97AD98AD99AD9A AD9BAD9EAD9FADA0ADA1ADA2ADA3ADA5ADA6ADA7ADA8ADA9ADAAADABADACADAD ADAEADAFADB0ADB1ADB2ADB3ADB4ADB5ADB6ADB8ADB9ADBAADBBADBCADBDADBE ADBFADC2ADC3ADC5ADC6ADC7ADC9ADCAADCBADCCADCDADCEADCFADD2ADD4ADD5 ADD6ADD7ADD8ADD9ADDAADDBADDDADDEADDFADE1ADE2ADE3ADE5ADE6ADE7ADE8 ADE9ADEAADEBADECADEDADEEADEFADF0ADF1ADF2ADF3ADF4ADF5ADF6ADF70000 83 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000ADFAADFBADFDADFEAE02AE03AE04AE05AE06AE07AE0AAE0CAE0EAE0FAE10 AE11AE12AE13AE15AE16AE17AE18AE19AE1AAE1BAE1C00000000000000000000 0000AE1DAE1EAE1FAE20AE21AE22AE23AE24AE25AE26AE27AE28AE29AE2AAE2B AE2CAE2DAE2EAE2FAE32AE33AE35AE36AE39AE3BAE3C00000000000000000000 0000AE3DAE3EAE3FAE42AE44AE47AE48AE49AE4BAE4FAE51AE52AE53AE55AE57 AE58AE59AE5AAE5BAE5EAE62AE63AE64AE66AE67AE6AAE6BAE6DAE6EAE6FAE71 AE72AE73AE74AE75AE76AE77AE7AAE7EAE7FAE80AE81AE82AE83AE86AE87AE88 AE89AE8AAE8BAE8DAE8EAE8FAE90AE91AE92AE93AE94AE95AE96AE97AE98AE99 AE9AAE9BAE9CAE9DAE9EAE9FAEA0AEA1AEA2AEA3AEA4AEA5AEA6AEA7AEA8AEA9 AEAAAEABAEACAEADAEAEAEAFAEB0AEB1AEB2AEB3AEB4AEB5AEB6AEB7AEB8AEB9 AEBAAEBBAEBFAEC1AEC2AEC3AEC5AEC6AEC7AEC8AEC9AECAAECBAECEAED2AED3 AED4AED5AED6AED7AEDAAEDBAEDDAEDEAEDFAEE0AEE1AEE2AEE3AEE4AEE50000 84 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000AEE6AEE7AEE9AEEAAEECAEEEAEEFAEF0AEF1AEF2AEF3AEF5AEF6AEF7AEF9 AEFAAEFBAEFDAEFEAEFFAF00AF01AF02AF03AF04AF0500000000000000000000 0000AF06AF09AF0AAF0BAF0CAF0EAF0FAF11AF12AF13AF14AF15AF16AF17AF18 AF19AF1AAF1BAF1CAF1DAF1EAF1FAF20AF21AF22AF2300000000000000000000 0000AF24AF25AF26AF27AF28AF29AF2AAF2BAF2EAF2FAF31AF33AF35AF36AF37 AF38AF39AF3AAF3BAF3EAF40AF44AF45AF46AF47AF4AAF4BAF4CAF4DAF4EAF4F AF51AF52AF53AF54AF55AF56AF57AF58AF59AF5AAF5BAF5EAF5FAF60AF61AF62 AF63AF66AF67AF68AF69AF6AAF6BAF6CAF6DAF6EAF6FAF70AF71AF72AF73AF74 AF75AF76AF77AF78AF7AAF7BAF7CAF7DAF7EAF7FAF81AF82AF83AF85AF86AF87 AF89AF8AAF8BAF8CAF8DAF8EAF8FAF92AF93AF94AF96AF97AF98AF99AF9AAF9B AF9DAF9EAF9FAFA0AFA1AFA2AFA3AFA4AFA5AFA6AFA7AFA8AFA9AFAAAFABAFAC AFADAFAEAFAFAFB0AFB1AFB2AFB3AFB4AFB5AFB6AFB7AFBAAFBBAFBDAFBE0000 85 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000AFBFAFC1AFC2AFC3AFC4AFC5AFC6AFCAAFCCAFCFAFD0AFD1AFD2AFD3AFD5 AFD6AFD7AFD8AFD9AFDAAFDBAFDDAFDEAFDFAFE0AFE100000000000000000000 0000AFE2AFE3AFE4AFE5AFE6AFE7AFEAAFEBAFECAFEDAFEEAFEFAFF2AFF3AFF5 AFF6AFF7AFF9AFFAAFFBAFFCAFFDAFFEAFFFB002B00300000000000000000000 0000B005B006B007B008B009B00AB00BB00DB00EB00FB011B012B013B015B016 B017B018B019B01AB01BB01EB01FB020B021B022B023B024B025B026B027B029 B02AB02BB02CB02DB02EB02FB030B031B032B033B034B035B036B037B038B039 B03AB03BB03CB03DB03EB03FB040B041B042B043B046B047B049B04BB04DB04F B050B051B052B056B058B05AB05BB05CB05EB05FB060B061B062B063B064B065 B066B067B068B069B06AB06BB06CB06DB06EB06FB070B071B072B073B074B075 B076B077B078B079B07AB07BB07EB07FB081B082B083B085B086B087B088B089 B08AB08BB08EB090B092B093B094B095B096B097B09BB09DB09EB0A3B0A40000 86 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B0A5B0A6B0A7B0AAB0B0B0B2B0B6B0B7B0B9B0BAB0BBB0BDB0BEB0BFB0C0 B0C1B0C2B0C3B0C6B0CAB0CBB0CCB0CDB0CEB0CFB0D200000000000000000000 0000B0D3B0D5B0D6B0D7B0D9B0DAB0DBB0DCB0DDB0DEB0DFB0E1B0E2B0E3B0E4 B0E6B0E7B0E8B0E9B0EAB0EBB0ECB0EDB0EEB0EFB0F000000000000000000000 0000B0F1B0F2B0F3B0F4B0F5B0F6B0F7B0F8B0F9B0FAB0FBB0FCB0FDB0FEB0FF B100B101B102B103B104B105B106B107B10AB10DB10EB10FB111B114B115B116 B117B11AB11EB11FB120B121B122B126B127B129B12AB12BB12DB12EB12FB130 B131B132B133B136B13AB13BB13CB13DB13EB13FB142B143B145B146B147B149 B14AB14BB14CB14DB14EB14FB152B153B156B157B159B15AB15BB15DB15EB15F B161B162B163B164B165B166B167B168B169B16AB16BB16CB16DB16EB16FB170 B171B172B173B174B175B176B177B17AB17BB17DB17EB17FB181B183B184B185 B186B187B18AB18CB18EB18FB190B191B195B196B197B199B19AB19BB19D0000 87 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B19EB19FB1A0B1A1B1A2B1A3B1A4B1A5B1A6B1A7B1A9B1AAB1ABB1ACB1AD B1AEB1AFB1B0B1B1B1B2B1B3B1B4B1B5B1B6B1B7B1B800000000000000000000 0000B1B9B1BAB1BBB1BCB1BDB1BEB1BFB1C0B1C1B1C2B1C3B1C4B1C5B1C6B1C7 B1C8B1C9B1CAB1CBB1CDB1CEB1CFB1D1B1D2B1D3B1D500000000000000000000 0000B1D6B1D7B1D8B1D9B1DAB1DBB1DEB1E0B1E1B1E2B1E3B1E4B1E5B1E6B1E7 B1EAB1EBB1EDB1EEB1EFB1F1B1F2B1F3B1F4B1F5B1F6B1F7B1F8B1FAB1FCB1FE B1FFB200B201B202B203B206B207B209B20AB20DB20EB20FB210B211B212B213 B216B218B21AB21BB21CB21DB21EB21FB221B222B223B224B225B226B227B228 B229B22AB22BB22CB22DB22EB22FB230B231B232B233B235B236B237B238B239 B23AB23BB23DB23EB23FB240B241B242B243B244B245B246B247B248B249B24A B24BB24CB24DB24EB24FB250B251B252B253B254B255B256B257B259B25AB25B B25DB25EB25FB261B262B263B264B265B266B267B26AB26BB26CB26DB26E0000 88 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B26FB270B271B272B273B276B277B278B279B27AB27BB27DB27EB27FB280 B281B282B283B286B287B288B28AB28BB28CB28DB28E00000000000000000000 0000B28FB292B293B295B296B297B29BB29CB29DB29EB29FB2A2B2A4B2A7B2A8 B2A9B2ABB2ADB2AEB2AFB2B1B2B2B2B3B2B5B2B6B2B700000000000000000000 0000B2B8B2B9B2BAB2BBB2BCB2BDB2BEB2BFB2C0B2C1B2C2B2C3B2C4B2C5B2C6 B2C7B2CAB2CBB2CDB2CEB2CFB2D1B2D3B2D4B2D5B2D6B2D7B2DAB2DCB2DEB2DF B2E0B2E1B2E3B2E7B2E9B2EAB2F0B2F1B2F2B2F6B2FCB2FDB2FEB302B303B305 B306B307B309B30AB30BB30CB30DB30EB30FB312B316B317B318B319B31AB31B B31DB31EB31FB320B321B322B323B324B325B326B327B328B329B32AB32BB32C B32DB32EB32FB330B331B332B333B334B335B336B337B338B339B33AB33BB33C B33DB33EB33FB340B341B342B343B344B345B346B347B348B349B34AB34BB34C B34DB34EB34FB350B351B352B353B357B359B35AB35DB360B361B362B3630000 89 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B366B368B36AB36CB36DB36FB372B373B375B376B377B379B37AB37BB37C B37DB37EB37FB382B386B387B388B389B38AB38BB38D00000000000000000000 0000B38EB38FB391B392B393B395B396B397B398B399B39AB39BB39CB39DB39E B39FB3A2B3A3B3A4B3A5B3A6B3A7B3A9B3AAB3ABB3AD00000000000000000000 0000B3AEB3AFB3B0B3B1B3B2B3B3B3B4B3B5B3B6B3B7B3B8B3B9B3BAB3BBB3BC B3BDB3BEB3BFB3C0B3C1B3C2B3C3B3C6B3C7B3C9B3CAB3CDB3CFB3D1B3D2B3D3 B3D6B3D8B3DAB3DCB3DEB3DFB3E1B3E2B3E3B3E5B3E6B3E7B3E9B3EAB3EBB3EC B3EDB3EEB3EFB3F0B3F1B3F2B3F3B3F4B3F5B3F6B3F7B3F8B3F9B3FAB3FBB3FD B3FEB3FFB400B401B402B403B404B405B406B407B408B409B40AB40BB40CB40D B40EB40FB411B412B413B414B415B416B417B419B41AB41BB41DB41EB41FB421 B422B423B424B425B426B427B42AB42CB42DB42EB42FB430B431B432B433B435 B436B437B438B439B43AB43BB43CB43DB43EB43FB440B441B442B443B4440000 8A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B445B446B447B448B449B44AB44BB44CB44DB44EB44FB452B453B455B456 B457B459B45AB45BB45CB45DB45EB45FB462B464B46600000000000000000000 0000B467B468B469B46AB46BB46DB46EB46FB470B471B472B473B474B475B476 B477B478B479B47AB47BB47CB47DB47EB47FB481B48200000000000000000000 0000B483B484B485B486B487B489B48AB48BB48CB48DB48EB48FB490B491B492 B493B494B495B496B497B498B499B49AB49BB49CB49EB49FB4A0B4A1B4A2B4A3 B4A5B4A6B4A7B4A9B4AAB4ABB4ADB4AEB4AFB4B0B4B1B4B2B4B3B4B4B4B6B4B8 B4BAB4BBB4BCB4BDB4BEB4BFB4C1B4C2B4C3B4C5B4C6B4C7B4C9B4CAB4CBB4CC B4CDB4CEB4CFB4D1B4D2B4D3B4D4B4D6B4D7B4D8B4D9B4DAB4DBB4DEB4DFB4E1 B4E2B4E5B4E7B4E8B4E9B4EAB4EBB4EEB4F0B4F2B4F3B4F4B4F5B4F6B4F7B4F9 B4FAB4FBB4FCB4FDB4FEB4FFB500B501B502B503B504B505B506B507B508B509 B50AB50BB50CB50DB50EB50FB510B511B512B513B516B517B519B51AB51D0000 8B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B51EB51FB520B521B522B523B526B52BB52CB52DB52EB52FB532B533B535 B536B537B539B53AB53BB53CB53DB53EB53FB542B54600000000000000000000 0000B547B548B549B54AB54EB54FB551B552B553B555B556B557B558B559B55A B55BB55EB562B563B564B565B566B567B568B569B56A00000000000000000000 0000B56BB56CB56DB56EB56FB570B571B572B573B574B575B576B577B578B579 B57AB57BB57CB57DB57EB57FB580B581B582B583B584B585B586B587B588B589 B58AB58BB58CB58DB58EB58FB590B591B592B593B594B595B596B597B598B599 B59AB59BB59CB59DB59EB59FB5A2B5A3B5A5B5A6B5A7B5A9B5ACB5ADB5AEB5AF B5B2B5B6B5B7B5B8B5B9B5BAB5BEB5BFB5C1B5C2B5C3B5C5B5C6B5C7B5C8B5C9 B5CAB5CBB5CEB5D2B5D3B5D4B5D5B5D6B5D7B5D9B5DAB5DBB5DCB5DDB5DEB5DF B5E0B5E1B5E2B5E3B5E4B5E5B5E6B5E7B5E8B5E9B5EAB5EBB5EDB5EEB5EFB5F0 B5F1B5F2B5F3B5F4B5F5B5F6B5F7B5F8B5F9B5FAB5FBB5FCB5FDB5FEB5FF0000 8C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B600B601B602B603B604B605B606B607B608B609B60AB60BB60CB60DB60E B60FB612B613B615B616B617B619B61AB61BB61CB61D00000000000000000000 0000B61EB61FB620B621B622B623B624B626B627B628B629B62AB62BB62DB62E B62FB630B631B632B633B635B636B637B638B639B63A00000000000000000000 0000B63BB63CB63DB63EB63FB640B641B642B643B644B645B646B647B649B64A B64BB64CB64DB64EB64FB650B651B652B653B654B655B656B657B658B659B65A B65BB65CB65DB65EB65FB660B661B662B663B665B666B667B669B66AB66BB66C B66DB66EB66FB670B671B672B673B674B675B676B677B678B679B67AB67BB67C B67DB67EB67FB680B681B682B683B684B685B686B687B688B689B68AB68BB68C B68DB68EB68FB690B691B692B693B694B695B696B697B698B699B69AB69BB69E B69FB6A1B6A2B6A3B6A5B6A6B6A7B6A8B6A9B6AAB6ADB6AEB6AFB6B0B6B2B6B3 B6B4B6B5B6B6B6B7B6B8B6B9B6BAB6BBB6BCB6BDB6BEB6BFB6C0B6C1B6C20000 8D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B6C3B6C4B6C5B6C6B6C7B6C8B6C9B6CAB6CBB6CCB6CDB6CEB6CFB6D0B6D1 B6D2B6D3B6D5B6D6B6D7B6D8B6D9B6DAB6DBB6DCB6DD00000000000000000000 0000B6DEB6DFB6E0B6E1B6E2B6E3B6E4B6E5B6E6B6E7B6E8B6E9B6EAB6EBB6EC B6EDB6EEB6EFB6F1B6F2B6F3B6F5B6F6B6F7B6F9B6FA00000000000000000000 0000B6FBB6FCB6FDB6FEB6FFB702B703B704B706B707B708B709B70AB70BB70C B70DB70EB70FB710B711B712B713B714B715B716B717B718B719B71AB71BB71C B71DB71EB71FB720B721B722B723B724B725B726B727B72AB72BB72DB72EB731 B732B733B734B735B736B737B73AB73CB73DB73EB73FB740B741B742B743B745 B746B747B749B74AB74BB74DB74EB74FB750B751B752B753B756B757B758B759 B75AB75BB75CB75DB75EB75FB761B762B763B765B766B767B769B76AB76BB76C B76DB76EB76FB772B774B776B777B778B779B77AB77BB77EB77FB781B782B783 B785B786B787B788B789B78AB78BB78EB793B794B795B79AB79BB79DB79E0000 8E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B79FB7A1B7A2B7A3B7A4B7A5B7A6B7A7B7AAB7AEB7AFB7B0B7B1B7B2B7B3 B7B6B7B7B7B9B7BAB7BBB7BCB7BDB7BEB7BFB7C0B7C100000000000000000000 0000B7C2B7C3B7C4B7C5B7C6B7C8B7CAB7CBB7CCB7CDB7CEB7CFB7D0B7D1B7D2 B7D3B7D4B7D5B7D6B7D7B7D8B7D9B7DAB7DBB7DCB7DD00000000000000000000 0000B7DEB7DFB7E0B7E1B7E2B7E3B7E4B7E5B7E6B7E7B7E8B7E9B7EAB7EBB7EE B7EFB7F1B7F2B7F3B7F5B7F6B7F7B7F8B7F9B7FAB7FBB7FEB802B803B804B805 B806B80AB80BB80DB80EB80FB811B812B813B814B815B816B817B81AB81CB81E B81FB820B821B822B823B826B827B829B82AB82BB82DB82EB82FB830B831B832 B833B836B83AB83BB83CB83DB83EB83FB841B842B843B845B846B847B848B849 B84AB84BB84CB84DB84EB84FB850B852B854B855B856B857B858B859B85AB85B B85EB85FB861B862B863B865B866B867B868B869B86AB86BB86EB870B872B873 B874B875B876B877B879B87AB87BB87DB87EB87FB880B881B882B883B8840000 8F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B885B886B887B888B889B88AB88BB88CB88EB88FB890B891B892B893B894 B895B896B897B898B899B89AB89BB89CB89DB89EB89F00000000000000000000 0000B8A0B8A1B8A2B8A3B8A4B8A5B8A6B8A7B8A9B8AAB8ABB8ACB8ADB8AEB8AF B8B1B8B2B8B3B8B5B8B6B8B7B8B9B8BAB8BBB8BCB8BD00000000000000000000 0000B8BEB8BFB8C2B8C4B8C6B8C7B8C8B8C9B8CAB8CBB8CDB8CEB8CFB8D1B8D2 B8D3B8D5B8D6B8D7B8D8B8D9B8DAB8DBB8DCB8DEB8E0B8E2B8E3B8E4B8E5B8E6 B8E7B8EAB8EBB8EDB8EEB8EFB8F1B8F2B8F3B8F4B8F5B8F6B8F7B8FAB8FCB8FE B8FFB900B901B902B903B905B906B907B908B909B90AB90BB90CB90DB90EB90F B910B911B912B913B914B915B916B917B919B91AB91BB91CB91DB91EB91FB921 B922B923B924B925B926B927B928B929B92AB92BB92CB92DB92EB92FB930B931 B932B933B934B935B936B937B938B939B93AB93BB93EB93FB941B942B943B945 B946B947B948B949B94AB94BB94DB94EB950B952B953B954B955B956B9570000 90 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B95AB95BB95DB95EB95FB961B962B963B964B965B966B967B96AB96CB96E B96FB970B971B972B973B976B977B979B97AB97BB97D00000000000000000000 0000B97EB97FB980B981B982B983B986B988B98BB98CB98FB990B991B992B993 B994B995B996B997B998B999B99AB99BB99CB99DB99E00000000000000000000 0000B99FB9A0B9A1B9A2B9A3B9A4B9A5B9A6B9A7B9A8B9A9B9AAB9ABB9AEB9AF B9B1B9B2B9B3B9B5B9B6B9B7B9B8B9B9B9BAB9BBB9BEB9C0B9C2B9C3B9C4B9C5 B9C6B9C7B9CAB9CBB9CDB9D3B9D4B9D5B9D6B9D7B9DAB9DCB9DFB9E0B9E2B9E6 B9E7B9E9B9EAB9EBB9EDB9EEB9EFB9F0B9F1B9F2B9F3B9F6B9FBB9FCB9FDB9FE B9FFBA02BA03BA04BA05BA06BA07BA09BA0ABA0BBA0CBA0DBA0EBA0FBA10BA11 BA12BA13BA14BA16BA17BA18BA19BA1ABA1BBA1CBA1DBA1EBA1FBA20BA21BA22 BA23BA24BA25BA26BA27BA28BA29BA2ABA2BBA2CBA2DBA2EBA2FBA30BA31BA32 BA33BA34BA35BA36BA37BA3ABA3BBA3DBA3EBA3FBA41BA43BA44BA45BA460000 91 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BA47BA4ABA4CBA4FBA50BA51BA52BA56BA57BA59BA5ABA5BBA5DBA5EBA5F BA60BA61BA62BA63BA66BA6ABA6BBA6CBA6DBA6EBA6F00000000000000000000 0000BA72BA73BA75BA76BA77BA79BA7ABA7BBA7CBA7DBA7EBA7FBA80BA81BA82 BA86BA88BA89BA8ABA8BBA8DBA8EBA8FBA90BA91BA9200000000000000000000 0000BA93BA94BA95BA96BA97BA98BA99BA9ABA9BBA9CBA9DBA9EBA9FBAA0BAA1 BAA2BAA3BAA4BAA5BAA6BAA7BAAABAADBAAEBAAFBAB1BAB3BAB4BAB5BAB6BAB7 BABABABCBABEBABFBAC0BAC1BAC2BAC3BAC5BAC6BAC7BAC9BACABACBBACCBACD BACEBACFBAD0BAD1BAD2BAD3BAD4BAD5BAD6BAD7BADABADBBADCBADDBADEBADF BAE0BAE1BAE2BAE3BAE4BAE5BAE6BAE7BAE8BAE9BAEABAEBBAECBAEDBAEEBAEF BAF0BAF1BAF2BAF3BAF4BAF5BAF6BAF7BAF8BAF9BAFABAFBBAFDBAFEBAFFBB01 BB02BB03BB05BB06BB07BB08BB09BB0ABB0BBB0CBB0EBB10BB12BB13BB14BB15 BB16BB17BB19BB1ABB1BBB1DBB1EBB1FBB21BB22BB23BB24BB25BB26BB270000 92 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BB28BB2ABB2CBB2DBB2EBB2FBB30BB31BB32BB33BB37BB39BB3ABB3FBB40 BB41BB42BB43BB46BB48BB4ABB4BBB4CBB4EBB51BB5200000000000000000000 0000BB53BB55BB56BB57BB59BB5ABB5BBB5CBB5DBB5EBB5FBB60BB62BB64BB65 BB66BB67BB68BB69BB6ABB6BBB6DBB6EBB6FBB70BB7100000000000000000000 0000BB72BB73BB74BB75BB76BB77BB78BB79BB7ABB7BBB7CBB7DBB7EBB7FBB80 BB81BB82BB83BB84BB85BB86BB87BB89BB8ABB8BBB8DBB8EBB8FBB91BB92BB93 BB94BB95BB96BB97BB98BB99BB9ABB9BBB9CBB9DBB9EBB9FBBA0BBA1BBA2BBA3 BBA5BBA6BBA7BBA9BBAABBABBBADBBAEBBAFBBB0BBB1BBB2BBB3BBB5BBB6BBB8 BBB9BBBABBBBBBBCBBBDBBBEBBBFBBC1BBC2BBC3BBC5BBC6BBC7BBC9BBCABBCB BBCCBBCDBBCEBBCFBBD1BBD2BBD4BBD5BBD6BBD7BBD8BBD9BBDABBDBBBDCBBDD BBDEBBDFBBE0BBE1BBE2BBE3BBE4BBE5BBE6BBE7BBE8BBE9BBEABBEBBBECBBED BBEEBBEFBBF0BBF1BBF2BBF3BBF4BBF5BBF6BBF7BBFABBFBBBFDBBFEBC010000 93 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BC03BC04BC05BC06BC07BC0ABC0EBC10BC12BC13BC19BC1ABC20BC21BC22 BC23BC26BC28BC2ABC2BBC2CBC2EBC2FBC32BC33BC3500000000000000000000 0000BC36BC37BC39BC3ABC3BBC3CBC3DBC3EBC3FBC42BC46BC47BC48BC4ABC4B BC4EBC4FBC51BC52BC53BC54BC55BC56BC57BC58BC5900000000000000000000 0000BC5ABC5BBC5CBC5EBC5FBC60BC61BC62BC63BC64BC65BC66BC67BC68BC69 BC6ABC6BBC6CBC6DBC6EBC6FBC70BC71BC72BC73BC74BC75BC76BC77BC78BC79 BC7ABC7BBC7CBC7DBC7EBC7FBC80BC81BC82BC83BC86BC87BC89BC8ABC8DBC8F BC90BC91BC92BC93BC96BC98BC9BBC9CBC9DBC9EBC9FBCA2BCA3BCA5BCA6BCA9 BCAABCABBCACBCADBCAEBCAFBCB2BCB6BCB7BCB8BCB9BCBABCBBBCBEBCBFBCC1 BCC2BCC3BCC5BCC6BCC7BCC8BCC9BCCABCCBBCCCBCCEBCD2BCD3BCD4BCD6BCD7 BCD9BCDABCDBBCDDBCDEBCDFBCE0BCE1BCE2BCE3BCE4BCE5BCE6BCE7BCE8BCE9 BCEABCEBBCECBCEDBCEEBCEFBCF0BCF1BCF2BCF3BCF7BCF9BCFABCFBBCFD0000 94 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BCFEBCFFBD00BD01BD02BD03BD06BD08BD0ABD0BBD0CBD0DBD0EBD0FBD11 BD12BD13BD15BD16BD17BD18BD19BD1ABD1BBD1CBD1D00000000000000000000 0000BD1EBD1FBD20BD21BD22BD23BD25BD26BD27BD28BD29BD2ABD2BBD2DBD2E BD2FBD30BD31BD32BD33BD34BD35BD36BD37BD38BD3900000000000000000000 0000BD3ABD3BBD3CBD3DBD3EBD3FBD41BD42BD43BD44BD45BD46BD47BD4ABD4B BD4DBD4EBD4FBD51BD52BD53BD54BD55BD56BD57BD5ABD5BBD5CBD5DBD5EBD5F BD60BD61BD62BD63BD65BD66BD67BD69BD6ABD6BBD6CBD6DBD6EBD6FBD70BD71 BD72BD73BD74BD75BD76BD77BD78BD79BD7ABD7BBD7CBD7DBD7EBD7FBD82BD83 BD85BD86BD8BBD8CBD8DBD8EBD8FBD92BD94BD96BD97BD98BD9BBD9DBD9EBD9F BDA0BDA1BDA2BDA3BDA5BDA6BDA7BDA8BDA9BDAABDABBDACBDADBDAEBDAFBDB1 BDB2BDB3BDB4BDB5BDB6BDB7BDB9BDBABDBBBDBCBDBDBDBEBDBFBDC0BDC1BDC2 BDC3BDC4BDC5BDC6BDC7BDC8BDC9BDCABDCBBDCCBDCDBDCEBDCFBDD0BDD10000 95 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BDD2BDD3BDD6BDD7BDD9BDDABDDBBDDDBDDEBDDFBDE0BDE1BDE2BDE3BDE4 BDE5BDE6BDE7BDE8BDEABDEBBDECBDEDBDEEBDEFBDF100000000000000000000 0000BDF2BDF3BDF5BDF6BDF7BDF9BDFABDFBBDFCBDFDBDFEBDFFBE01BE02BE04 BE06BE07BE08BE09BE0ABE0BBE0EBE0FBE11BE12BE1300000000000000000000 0000BE15BE16BE17BE18BE19BE1ABE1BBE1EBE20BE21BE22BE23BE24BE25BE26 BE27BE28BE29BE2ABE2BBE2CBE2DBE2EBE2FBE30BE31BE32BE33BE34BE35BE36 BE37BE38BE39BE3ABE3BBE3CBE3DBE3EBE3FBE40BE41BE42BE43BE46BE47BE49 BE4ABE4BBE4DBE4FBE50BE51BE52BE53BE56BE58BE5CBE5DBE5EBE5FBE62BE63 BE65BE66BE67BE69BE6BBE6CBE6DBE6EBE6FBE72BE76BE77BE78BE79BE7ABE7E BE7FBE81BE82BE83BE85BE86BE87BE88BE89BE8ABE8BBE8EBE92BE93BE94BE95 BE96BE97BE9ABE9BBE9CBE9DBE9EBE9FBEA0BEA1BEA2BEA3BEA4BEA5BEA6BEA7 BEA9BEAABEABBEACBEADBEAEBEAFBEB0BEB1BEB2BEB3BEB4BEB5BEB6BEB70000 96 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BEB8BEB9BEBABEBBBEBCBEBDBEBEBEBFBEC0BEC1BEC2BEC3BEC4BEC5BEC6 BEC7BEC8BEC9BECABECBBECCBECDBECEBECFBED2BED300000000000000000000 0000BED5BED6BED9BEDABEDBBEDCBEDDBEDEBEDFBEE1BEE2BEE6BEE7BEE8BEE9 BEEABEEBBEEDBEEEBEEFBEF0BEF1BEF2BEF3BEF4BEF500000000000000000000 0000BEF6BEF7BEF8BEF9BEFABEFBBEFCBEFDBEFEBEFFBF00BF02BF03BF04BF05 BF06BF07BF0ABF0BBF0CBF0DBF0EBF0FBF10BF11BF12BF13BF14BF15BF16BF17 BF1ABF1EBF1FBF20BF21BF22BF23BF24BF25BF26BF27BF28BF29BF2ABF2BBF2C BF2DBF2EBF2FBF30BF31BF32BF33BF34BF35BF36BF37BF38BF39BF3ABF3BBF3C BF3DBF3EBF3FBF42BF43BF45BF46BF47BF49BF4ABF4BBF4CBF4DBF4EBF4FBF52 BF53BF54BF56BF57BF58BF59BF5ABF5BBF5CBF5DBF5EBF5FBF60BF61BF62BF63 BF64BF65BF66BF67BF68BF69BF6ABF6BBF6CBF6DBF6EBF6FBF70BF71BF72BF73 BF74BF75BF76BF77BF78BF79BF7ABF7BBF7CBF7DBF7EBF7FBF80BF81BF820000 97 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BF83BF84BF85BF86BF87BF88BF89BF8ABF8BBF8CBF8DBF8EBF8FBF90BF91 BF92BF93BF95BF96BF97BF98BF99BF9ABF9BBF9CBF9D00000000000000000000 0000BF9EBF9FBFA0BFA1BFA2BFA3BFA4BFA5BFA6BFA7BFA8BFA9BFAABFABBFAC BFADBFAEBFAFBFB1BFB2BFB3BFB4BFB5BFB6BFB7BFB800000000000000000000 0000BFB9BFBABFBBBFBCBFBDBFBEBFBFBFC0BFC1BFC2BFC3BFC4BFC6BFC7BFC8 BFC9BFCABFCBBFCEBFCFBFD1BFD2BFD3BFD5BFD6BFD7BFD8BFD9BFDABFDBBFDD BFDEBFE0BFE2BFE3BFE4BFE5BFE6BFE7BFE8BFE9BFEABFEBBFECBFEDBFEEBFEF BFF0BFF1BFF2BFF3BFF4BFF5BFF6BFF7BFF8BFF9BFFABFFBBFFCBFFDBFFEBFFF C000C001C002C003C004C005C006C007C008C009C00AC00BC00CC00DC00EC00F C010C011C012C013C014C015C016C017C018C019C01AC01BC01CC01DC01EC01F C020C021C022C023C024C025C026C027C028C029C02AC02BC02CC02DC02EC02F C030C031C032C033C034C035C036C037C038C039C03AC03BC03DC03EC03F0000 98 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C040C041C042C043C044C045C046C047C048C049C04AC04BC04CC04DC04E C04FC050C052C053C054C055C056C057C059C05AC05B00000000000000000000 0000C05DC05EC05FC061C062C063C064C065C066C067C06AC06BC06CC06DC06E C06FC070C071C072C073C074C075C076C077C078C07900000000000000000000 0000C07AC07BC07CC07DC07EC07FC080C081C082C083C084C085C086C087C088 C089C08AC08BC08CC08DC08EC08FC092C093C095C096C097C099C09AC09BC09C C09DC09EC09FC0A2C0A4C0A6C0A7C0A8C0A9C0AAC0ABC0AEC0B1C0B2C0B7C0B8 C0B9C0BAC0BBC0BEC0C2C0C3C0C4C0C6C0C7C0CAC0CBC0CDC0CEC0CFC0D1C0D2 C0D3C0D4C0D5C0D6C0D7C0DAC0DEC0DFC0E0C0E1C0E2C0E3C0E6C0E7C0E9C0EA C0EBC0EDC0EEC0EFC0F0C0F1C0F2C0F3C0F6C0F8C0FAC0FBC0FCC0FDC0FEC0FF C101C102C103C105C106C107C109C10AC10BC10CC10DC10EC10FC111C112C113 C114C116C117C118C119C11AC11BC121C122C125C128C129C12AC12BC12E0000 99 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C132C133C134C135C137C13AC13BC13DC13EC13FC141C142C143C144C145 C146C147C14AC14EC14FC150C151C152C153C156C15700000000000000000000 0000C159C15AC15BC15DC15EC15FC160C161C162C163C166C16AC16BC16CC16D C16EC16FC171C172C173C175C176C177C179C17AC17B00000000000000000000 0000C17CC17DC17EC17FC180C181C182C183C184C186C187C188C189C18AC18B C18FC191C192C193C195C197C198C199C19AC19BC19EC1A0C1A2C1A3C1A4C1A6 C1A7C1AAC1ABC1ADC1AEC1AFC1B1C1B2C1B3C1B4C1B5C1B6C1B7C1B8C1B9C1BA C1BBC1BCC1BEC1BFC1C0C1C1C1C2C1C3C1C5C1C6C1C7C1C9C1CAC1CBC1CDC1CE C1CFC1D0C1D1C1D2C1D3C1D5C1D6C1D9C1DAC1DBC1DCC1DDC1DEC1DFC1E1C1E2 C1E3C1E5C1E6C1E7C1E9C1EAC1EBC1ECC1EDC1EEC1EFC1F2C1F4C1F5C1F6C1F7 C1F8C1F9C1FAC1FBC1FEC1FFC201C202C203C205C206C207C208C209C20AC20B C20EC210C212C213C214C215C216C217C21AC21BC21DC21EC221C222C2230000 9A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C224C225C226C227C22AC22CC22EC230C233C235C236C237C238C239C23A C23BC23CC23DC23EC23FC240C241C242C243C244C24500000000000000000000 0000C246C247C249C24AC24BC24CC24DC24EC24FC252C253C255C256C257C259 C25AC25BC25CC25DC25EC25FC261C262C263C264C26600000000000000000000 0000C267C268C269C26AC26BC26EC26FC271C272C273C275C276C277C278C279 C27AC27BC27EC280C282C283C284C285C286C287C28AC28BC28CC28DC28EC28F C291C292C293C294C295C296C297C299C29AC29CC29EC29FC2A0C2A1C2A2C2A3 C2A6C2A7C2A9C2AAC2ABC2AEC2AFC2B0C2B1C2B2C2B3C2B6C2B8C2BAC2BBC2BC C2BDC2BEC2BFC2C0C2C1C2C2C2C3C2C4C2C5C2C6C2C7C2C8C2C9C2CAC2CBC2CC C2CDC2CEC2CFC2D0C2D1C2D2C2D3C2D4C2D5C2D6C2D7C2D8C2D9C2DAC2DBC2DE C2DFC2E1C2E2C2E5C2E6C2E7C2E8C2E9C2EAC2EEC2F0C2F2C2F3C2F4C2F5C2F7 C2FAC2FDC2FEC2FFC301C302C303C304C305C306C307C30AC30BC30EC30F0000 9B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C310C311C312C316C317C319C31AC31BC31DC31EC31FC320C321C322C323 C326C327C32AC32BC32CC32DC32EC32FC330C331C33200000000000000000000 0000C333C334C335C336C337C338C339C33AC33BC33CC33DC33EC33FC340C341 C342C343C344C346C347C348C349C34AC34BC34CC34D00000000000000000000 0000C34EC34FC350C351C352C353C354C355C356C357C358C359C35AC35BC35C C35DC35EC35FC360C361C362C363C364C365C366C367C36AC36BC36DC36EC36F C371C373C374C375C376C377C37AC37BC37EC37FC380C381C382C383C385C386 C387C389C38AC38BC38DC38EC38FC390C391C392C393C394C395C396C397C398 C399C39AC39BC39CC39DC39EC39FC3A0C3A1C3A2C3A3C3A4C3A5C3A6C3A7C3A8 C3A9C3AAC3ABC3ACC3ADC3AEC3AFC3B0C3B1C3B2C3B3C3B4C3B5C3B6C3B7C3B8 C3B9C3BAC3BBC3BCC3BDC3BEC3BFC3C1C3C2C3C3C3C4C3C5C3C6C3C7C3C8C3C9 C3CAC3CBC3CCC3CDC3CEC3CFC3D0C3D1C3D2C3D3C3D4C3D5C3D6C3D7C3DA0000 9C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C3DBC3DDC3DEC3E1C3E3C3E4C3E5C3E6C3E7C3EAC3EBC3ECC3EEC3EFC3F0 C3F1C3F2C3F3C3F6C3F7C3F9C3FAC3FBC3FCC3FDC3FE00000000000000000000 0000C3FFC400C401C402C403C404C405C406C407C409C40AC40BC40CC40DC40E C40FC411C412C413C414C415C416C417C418C419C41A00000000000000000000 0000C41BC41CC41DC41EC41FC420C421C422C423C425C426C427C428C429C42A C42BC42DC42EC42FC431C432C433C435C436C437C438C439C43AC43BC43EC43F C440C441C442C443C444C445C446C447C449C44AC44BC44CC44DC44EC44FC450 C451C452C453C454C455C456C457C458C459C45AC45BC45CC45DC45EC45FC460 C461C462C463C466C467C469C46AC46BC46DC46EC46FC470C471C472C473C476 C477C478C47AC47BC47CC47DC47EC47FC481C482C483C484C485C486C487C488 C489C48AC48BC48CC48DC48EC48FC490C491C492C493C495C496C497C498C499 C49AC49BC49DC49EC49FC4A0C4A1C4A2C4A3C4A4C4A5C4A6C4A7C4A8C4A90000 9D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C4AAC4ABC4ACC4ADC4AEC4AFC4B0C4B1C4B2C4B3C4B4C4B5C4B6C4B7C4B9 C4BAC4BBC4BDC4BEC4BFC4C0C4C1C4C2C4C3C4C4C4C500000000000000000000 0000C4C6C4C7C4C8C4C9C4CAC4CBC4CCC4CDC4CEC4CFC4D0C4D1C4D2C4D3C4D4 C4D5C4D6C4D7C4D8C4D9C4DAC4DBC4DCC4DDC4DEC4DF00000000000000000000 0000C4E0C4E1C4E2C4E3C4E4C4E5C4E6C4E7C4E8C4EAC4EBC4ECC4EDC4EEC4EF C4F2C4F3C4F5C4F6C4F7C4F9C4FBC4FCC4FDC4FEC502C503C504C505C506C507 C508C509C50AC50BC50DC50EC50FC511C512C513C515C516C517C518C519C51A C51BC51DC51EC51FC520C521C522C523C524C525C526C527C52AC52BC52DC52E C52FC531C532C533C534C535C536C537C53AC53CC53EC53FC540C541C542C543 C546C547C54BC54FC550C551C552C556C55AC55BC55CC55FC562C563C565C566 C567C569C56AC56BC56CC56DC56EC56FC572C576C577C578C579C57AC57BC57E C57FC581C582C583C585C586C588C589C58AC58BC58EC590C592C593C5940000 9E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C596C599C59AC59BC59DC59EC59FC5A1C5A2C5A3C5A4C5A5C5A6C5A7C5A8 C5AAC5ABC5ACC5ADC5AEC5AFC5B0C5B1C5B2C5B3C5B600000000000000000000 0000C5B7C5BAC5BFC5C0C5C1C5C2C5C3C5CBC5CDC5CFC5D2C5D3C5D5C5D6C5D7 C5D9C5DAC5DBC5DCC5DDC5DEC5DFC5E2C5E4C5E6C5E700000000000000000000 0000C5E8C5E9C5EAC5EBC5EFC5F1C5F2C5F3C5F5C5F8C5F9C5FAC5FBC602C603 C604C609C60AC60BC60DC60EC60FC611C612C613C614C615C616C617C61AC61D C61EC61FC620C621C622C623C626C627C629C62AC62BC62FC631C632C636C638 C63AC63CC63DC63EC63FC642C643C645C646C647C649C64AC64BC64CC64DC64E C64FC652C656C657C658C659C65AC65BC65EC65FC661C662C663C664C665C666 C667C668C669C66AC66BC66DC66EC670C672C673C674C675C676C677C67AC67B C67DC67EC67FC681C682C683C684C685C686C687C68AC68CC68EC68FC690C691 C692C693C696C697C699C69AC69BC69DC69EC69FC6A0C6A1C6A2C6A3C6A60000 9F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C6A8C6AAC6ABC6ACC6ADC6AEC6AFC6B2C6B3C6B5C6B6C6B7C6BBC6BCC6BD C6BEC6BFC6C2C6C4C6C6C6C7C6C8C6C9C6CAC6CBC6CE00000000000000000000 0000C6CFC6D1C6D2C6D3C6D5C6D6C6D7C6D8C6D9C6DAC6DBC6DEC6DFC6E2C6E3 C6E4C6E5C6E6C6E7C6EAC6EBC6EDC6EEC6EFC6F1C6F200000000000000000000 0000C6F3C6F4C6F5C6F6C6F7C6FAC6FBC6FCC6FEC6FFC700C701C702C703C706 C707C709C70AC70BC70DC70EC70FC710C711C712C713C716C718C71AC71BC71C C71DC71EC71FC722C723C725C726C727C729C72AC72BC72CC72DC72EC72FC732 C734C736C738C739C73AC73BC73EC73FC741C742C743C745C746C747C748C749 C74BC74EC750C759C75AC75BC75DC75EC75FC761C762C763C764C765C766C767 C769C76AC76CC76DC76EC76FC770C771C772C773C776C777C779C77AC77BC77F C780C781C782C786C78BC78CC78DC78FC792C793C795C799C79BC79CC79DC79E C79FC7A2C7A7C7A8C7A9C7AAC7ABC7AEC7AFC7B1C7B2C7B3C7B5C7B6C7B70000 A0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C7B8C7B9C7BAC7BBC7BEC7C2C7C3C7C4C7C5C7C6C7C7C7CAC7CBC7CDC7CF C7D1C7D2C7D3C7D4C7D5C7D6C7D7C7D9C7DAC7DBC7DC00000000000000000000 0000C7DEC7DFC7E0C7E1C7E2C7E3C7E5C7E6C7E7C7E9C7EAC7EBC7EDC7EEC7EF C7F0C7F1C7F2C7F3C7F4C7F5C7F6C7F7C7F8C7F9C7FA00000000000000000000 0000C7FBC7FCC7FDC7FEC7FFC802C803C805C806C807C809C80BC80CC80DC80E C80FC812C814C817C818C819C81AC81BC81EC81FC821C822C823C825C826C827 C828C829C82AC82BC82EC830C832C833C834C835C836C837C839C83AC83BC83D C83EC83FC841C842C843C844C845C846C847C84AC84BC84EC84FC850C851C852 C853C855C856C857C858C859C85AC85BC85CC85DC85EC85FC860C861C862C863 C864C865C866C867C868C869C86AC86BC86CC86DC86EC86FC872C873C875C876 C877C879C87BC87CC87DC87EC87FC882C884C888C889C88AC88EC88FC890C891 C892C893C895C896C897C898C899C89AC89BC89CC89EC8A0C8A2C8A3C8A40000 A1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C8A5C8A6C8A7C8A9C8AAC8ABC8ACC8ADC8AEC8AFC8B0C8B1C8B2C8B3C8B4 C8B5C8B6C8B7C8B8C8B9C8BAC8BBC8BEC8BFC8C0C8C100000000000000000000 0000C8C2C8C3C8C5C8C6C8C7C8C9C8CAC8CBC8CDC8CEC8CFC8D0C8D1C8D2C8D3 C8D6C8D8C8DAC8DBC8DCC8DDC8DEC8DFC8E2C8E3C8E500000000000000000000 0000C8E6C8E7C8E8C8E9C8EAC8EBC8ECC8EDC8EEC8EFC8F0C8F1C8F2C8F3C8F4 C8F6C8F7C8F8C8F9C8FAC8FBC8FEC8FFC901C902C903C907C908C909C90AC90B C90E30003001300200B72025202600A8300300AD20152225FF3C223C20182019 201C201D3014301530083009300A300B300C300D300E300F3010301100B100D7 00F7226022642265221E223400B0203220332103212BFFE0FFE1FFE526422640 222022A52312220222072261225200A7203B2606260525CB25CF25CE25C725C6 25A125A025B325B225BD25BC219221902191219321943013226A226B221A223D 221D2235222B222C2208220B2286228722822283222A222922272228FFE20000 A2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C910C912C913C914C915C916C917C919C91AC91BC91CC91DC91EC91FC920 C921C922C923C924C925C926C927C928C929C92AC92B00000000000000000000 0000C92DC92EC92FC930C931C932C933C935C936C937C938C939C93AC93BC93C C93DC93EC93FC940C941C942C943C944C945C946C94700000000000000000000 0000C948C949C94AC94BC94CC94DC94EC94FC952C953C955C956C957C959C95A C95BC95CC95DC95EC95FC962C964C965C966C967C968C969C96AC96BC96DC96E C96F21D221D42200220300B4FF5E02C702D802DD02DA02D900B802DB00A100BF 02D0222E2211220F00A42109203025C125C025B725B626642660266126652667 2663229925C825A325D025D1259225A425A525A825A725A625A92668260F260E 261C261E00B62020202121952197219921962198266D2669266A266C327F321C 211633C7212233C233D8212120AC00AE00000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C971C972C973C975C976C977C978C979C97AC97BC97DC97EC97FC980C981 C982C983C984C985C986C987C98AC98BC98DC98EC98F00000000000000000000 0000C991C992C993C994C995C996C997C99AC99CC99EC99FC9A0C9A1C9A2C9A3 C9A4C9A5C9A6C9A7C9A8C9A9C9AAC9ABC9ACC9ADC9AE00000000000000000000 0000C9AFC9B0C9B1C9B2C9B3C9B4C9B5C9B6C9B7C9B8C9B9C9BAC9BBC9BCC9BD C9BEC9BFC9C2C9C3C9C5C9C6C9C9C9CBC9CCC9CDC9CEC9CFC9D2C9D4C9D7C9D8 C9DBFF01FF02FF03FF04FF05FF06FF07FF08FF09FF0AFF0BFF0CFF0DFF0EFF0F FF10FF11FF12FF13FF14FF15FF16FF17FF18FF19FF1AFF1BFF1CFF1DFF1EFF1F FF20FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2F FF30FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3AFF3BFFE6FF3DFF3EFF3F FF40FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5AFF5BFF5CFF5DFFE30000 A4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C9DEC9DFC9E1C9E3C9E5C9E6C9E8C9E9C9EAC9EBC9EEC9F2C9F3C9F4C9F5 C9F6C9F7C9FAC9FBC9FDC9FEC9FFCA01CA02CA03CA0400000000000000000000 0000CA05CA06CA07CA0ACA0ECA0FCA10CA11CA12CA13CA15CA16CA17CA19CA1A CA1BCA1CCA1DCA1ECA1FCA20CA21CA22CA23CA24CA2500000000000000000000 0000CA26CA27CA28CA2ACA2BCA2CCA2DCA2ECA2FCA30CA31CA32CA33CA34CA35 CA36CA37CA38CA39CA3ACA3BCA3CCA3DCA3ECA3FCA40CA41CA42CA43CA44CA45 CA46313131323133313431353136313731383139313A313B313C313D313E313F 3140314131423143314431453146314731483149314A314B314C314D314E314F 3150315131523153315431553156315731583159315A315B315C315D315E315F 3160316131623163316431653166316731683169316A316B316C316D316E316F 3170317131723173317431753176317731783179317A317B317C317D317E317F 3180318131823183318431853186318731883189318A318B318C318D318E0000 A5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CA47CA48CA49CA4ACA4BCA4ECA4FCA51CA52CA53CA55CA56CA57CA58CA59 CA5ACA5BCA5ECA62CA63CA64CA65CA66CA67CA69CA6A00000000000000000000 0000CA6BCA6CCA6DCA6ECA6FCA70CA71CA72CA73CA74CA75CA76CA77CA78CA79 CA7ACA7BCA7CCA7ECA7FCA80CA81CA82CA83CA85CA8600000000000000000000 0000CA87CA88CA89CA8ACA8BCA8CCA8DCA8ECA8FCA90CA91CA92CA93CA94CA95 CA96CA97CA99CA9ACA9BCA9CCA9DCA9ECA9FCAA0CAA1CAA2CAA3CAA4CAA5CAA6 CAA7217021712172217321742175217621772178217900000000000000000000 2160216121622163216421652166216721682169000000000000000000000000 0000039103920393039403950396039703980399039A039B039C039D039E039F 03A003A103A303A403A503A603A703A803A90000000000000000000000000000 000003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C303C403C503C603C703C803C90000000000000000000000000000 A6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CAA8CAA9CAAACAABCAACCAADCAAECAAFCAB0CAB1CAB2CAB3CAB4CAB5CAB6 CAB7CAB8CAB9CABACABBCABECABFCAC1CAC2CAC3CAC500000000000000000000 0000CAC6CAC7CAC8CAC9CACACACBCACECAD0CAD2CAD4CAD5CAD6CAD7CADACADB CADCCADDCADECADFCAE1CAE2CAE3CAE4CAE5CAE6CAE700000000000000000000 0000CAE8CAE9CAEACAEBCAEDCAEECAEFCAF0CAF1CAF2CAF3CAF5CAF6CAF7CAF8 CAF9CAFACAFBCAFCCAFDCAFECAFFCB00CB01CB02CB03CB04CB05CB06CB07CB09 CB0A25002502250C251025182514251C252C25242534253C25012503250F2513 251B251725232533252B253B254B2520252F25282537253F251D253025252538 254225122511251A251925162515250E250D251E251F25212522252625272529 252A252D252E25312532253525362539253A253D253E25402541254325442545 2546254725482549254A00000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CB0BCB0CCB0DCB0ECB0FCB11CB12CB13CB15CB16CB17CB19CB1ACB1BCB1C CB1DCB1ECB1FCB22CB23CB24CB25CB26CB27CB28CB2900000000000000000000 0000CB2ACB2BCB2CCB2DCB2ECB2FCB30CB31CB32CB33CB34CB35CB36CB37CB38 CB39CB3ACB3BCB3CCB3DCB3ECB3FCB40CB42CB43CB4400000000000000000000 0000CB45CB46CB47CB4ACB4BCB4DCB4ECB4FCB51CB52CB53CB54CB55CB56CB57 CB5ACB5BCB5CCB5ECB5FCB60CB61CB62CB63CB65CB66CB67CB68CB69CB6ACB6B CB6C3395339633972113339833C433A333A433A533A63399339A339B339C339D 339E339F33A033A133A233CA338D338E338F33CF3388338933C833A733A833B0 33B133B233B333B433B533B633B733B833B93380338133823383338433BA33BB 33BC33BD33BE33BF33903391339233933394212633C033C1338A338B338C33D6 33C533AD33AE33AF33DB33A933AA33AB33AC33DD33D033D333C333C933DC33C6 0000000000000000000000000000000000000000000000000000000000000000 A8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CB6DCB6ECB6FCB70CB71CB72CB73CB74CB75CB76CB77CB7ACB7BCB7CCB7D CB7ECB7FCB80CB81CB82CB83CB84CB85CB86CB87CB8800000000000000000000 0000CB89CB8ACB8BCB8CCB8DCB8ECB8FCB90CB91CB92CB93CB94CB95CB96CB97 CB98CB99CB9ACB9BCB9DCB9ECB9FCBA0CBA1CBA2CBA300000000000000000000 0000CBA4CBA5CBA6CBA7CBA8CBA9CBAACBABCBACCBADCBAECBAFCBB0CBB1CBB2 CBB3CBB4CBB5CBB6CBB7CBB9CBBACBBBCBBCCBBDCBBECBBFCBC0CBC1CBC2CBC3 CBC400C600D000AA0126000001320000013F014100D8015200BA00DE0166014A 00003260326132623263326432653266326732683269326A326B326C326D326E 326F3270327132723273327432753276327732783279327A327B24D024D124D2 24D324D424D524D624D724D824D924DA24DB24DC24DD24DE24DF24E024E124E2 24E324E424E524E624E724E824E9246024612462246324642465246624672468 2469246A246B246C246D246E00BD2153215400BC00BE215B215C215D215E0000 A9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CBC5CBC6CBC7CBC8CBC9CBCACBCBCBCCCBCDCBCECBCFCBD0CBD1CBD2CBD3 CBD5CBD6CBD7CBD8CBD9CBDACBDBCBDCCBDDCBDECBDF00000000000000000000 0000CBE0CBE1CBE2CBE3CBE5CBE6CBE8CBEACBEBCBECCBEDCBEECBEFCBF0CBF1 CBF2CBF3CBF4CBF5CBF6CBF7CBF8CBF9CBFACBFBCBFC00000000000000000000 0000CBFDCBFECBFFCC00CC01CC02CC03CC04CC05CC06CC07CC08CC09CC0ACC0B CC0ECC0FCC11CC12CC13CC15CC16CC17CC18CC19CC1ACC1BCC1ECC1FCC20CC23 CC2400E6011100F001270131013301380140014200F8015300DF00FE0167014B 01493200320132023203320432053206320732083209320A320B320C320D320E 320F3210321132123213321432153216321732183219321A321B249C249D249E 249F24A024A124A224A324A424A524A624A724A824A924AA24AB24AC24AD24AE 24AF24B024B124B224B324B424B5247424752476247724782479247A247B247C 247D247E247F24802481248200B900B200B32074207F20812082208320840000 AA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CC25CC26CC2ACC2BCC2DCC2FCC31CC32CC33CC34CC35CC36CC37CC3ACC3F CC40CC41CC42CC43CC46CC47CC49CC4ACC4BCC4DCC4E00000000000000000000 0000CC4FCC50CC51CC52CC53CC56CC5ACC5BCC5CCC5DCC5ECC5FCC61CC62CC63 CC65CC67CC69CC6ACC6BCC6CCC6DCC6ECC6FCC71CC7200000000000000000000 0000CC73CC74CC76CC77CC78CC79CC7ACC7BCC7CCC7DCC7ECC7FCC80CC81CC82 CC83CC84CC85CC86CC87CC88CC89CC8ACC8BCC8CCC8DCC8ECC8FCC90CC91CC92 CC93304130423043304430453046304730483049304A304B304C304D304E304F 3050305130523053305430553056305730583059305A305B305C305D305E305F 3060306130623063306430653066306730683069306A306B306C306D306E306F 3070307130723073307430753076307730783079307A307B307C307D307E307F 3080308130823083308430853086308730883089308A308B308C308D308E308F 3090309130923093000000000000000000000000000000000000000000000000 AB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CC94CC95CC96CC97CC9ACC9BCC9DCC9ECC9FCCA1CCA2CCA3CCA4CCA5CCA6 CCA7CCAACCAECCAFCCB0CCB1CCB2CCB3CCB6CCB7CCB900000000000000000000 0000CCBACCBBCCBDCCBECCBFCCC0CCC1CCC2CCC3CCC6CCC8CCCACCCBCCCCCCCD CCCECCCFCCD1CCD2CCD3CCD5CCD6CCD7CCD8CCD9CCDA00000000000000000000 0000CCDBCCDCCCDDCCDECCDFCCE0CCE1CCE2CCE3CCE5CCE6CCE7CCE8CCE9CCEA CCEBCCEDCCEECCEFCCF1CCF2CCF3CCF4CCF5CCF6CCF7CCF8CCF9CCFACCFBCCFC CCFD30A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF 30B030B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF 30C030C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF 30D030D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000000 AC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CCFECCFFCD00CD02CD03CD04CD05CD06CD07CD0ACD0BCD0DCD0ECD0FCD11 CD12CD13CD14CD15CD16CD17CD1ACD1CCD1ECD1FCD2000000000000000000000 0000CD21CD22CD23CD25CD26CD27CD29CD2ACD2BCD2DCD2ECD2FCD30CD31CD32 CD33CD34CD35CD36CD37CD38CD3ACD3BCD3CCD3DCD3E00000000000000000000 0000CD3FCD40CD41CD42CD43CD44CD45CD46CD47CD48CD49CD4ACD4BCD4CCD4D CD4ECD4FCD50CD51CD52CD53CD54CD55CD56CD57CD58CD59CD5ACD5BCD5DCD5E CD5F04100411041204130414041504010416041704180419041A041B041C041D 041E041F0420042104220423042404250426042704280429042A042B042C042D 042E042F00000000000000000000000000000000000000000000000000000000 000004300431043204330434043504510436043704380439043A043B043C043D 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000000000 AD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CD61CD62CD63CD65CD66CD67CD68CD69CD6ACD6BCD6ECD70CD72CD73CD74 CD75CD76CD77CD79CD7ACD7BCD7CCD7DCD7ECD7FCD8000000000000000000000 0000CD81CD82CD83CD84CD85CD86CD87CD89CD8ACD8BCD8CCD8DCD8ECD8FCD90 CD91CD92CD93CD96CD97CD99CD9ACD9BCD9DCD9ECD9F00000000000000000000 0000CDA0CDA1CDA2CDA3CDA6CDA8CDAACDABCDACCDADCDAECDAFCDB1CDB2CDB3 CDB4CDB5CDB6CDB7CDB8CDB9CDBACDBBCDBCCDBDCDBECDBFCDC0CDC1CDC2CDC3 CDC5000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 AE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CDC6CDC7CDC8CDC9CDCACDCBCDCDCDCECDCFCDD1CDD2CDD3CDD4CDD5CDD6 CDD7CDD8CDD9CDDACDDBCDDCCDDDCDDECDDFCDE0CDE100000000000000000000 0000CDE2CDE3CDE4CDE5CDE6CDE7CDE9CDEACDEBCDEDCDEECDEFCDF1CDF2CDF3 CDF4CDF5CDF6CDF7CDFACDFCCDFECDFFCE00CE01CE0200000000000000000000 0000CE03CE05CE06CE07CE09CE0ACE0BCE0DCE0ECE0FCE10CE11CE12CE13CE15 CE16CE17CE18CE1ACE1BCE1CCE1DCE1ECE1FCE22CE23CE25CE26CE27CE29CE2A CE2B000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 AF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CE2CCE2DCE2ECE2FCE32CE34CE36CE37CE38CE39CE3ACE3BCE3CCE3DCE3E CE3FCE40CE41CE42CE43CE44CE45CE46CE47CE48CE4900000000000000000000 0000CE4ACE4BCE4CCE4DCE4ECE4FCE50CE51CE52CE53CE54CE55CE56CE57CE5A CE5BCE5DCE5ECE62CE63CE64CE65CE66CE67CE6ACE6C00000000000000000000 0000CE6ECE6FCE70CE71CE72CE73CE76CE77CE79CE7ACE7BCE7DCE7ECE7FCE80 CE81CE82CE83CE86CE88CE8ACE8BCE8CCE8DCE8ECE8FCE92CE93CE95CE96CE97 CE99000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 B0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CE9ACE9BCE9CCE9DCE9ECE9FCEA2CEA6CEA7CEA8CEA9CEAACEABCEAECEAF CEB0CEB1CEB2CEB3CEB4CEB5CEB6CEB7CEB8CEB9CEBA00000000000000000000 0000CEBBCEBCCEBDCEBECEBFCEC0CEC2CEC3CEC4CEC5CEC6CEC7CEC8CEC9CECA CECBCECCCECDCECECECFCED0CED1CED2CED3CED4CED500000000000000000000 0000CED6CED7CED8CED9CEDACEDBCEDCCEDDCEDECEDFCEE0CEE1CEE2CEE3CEE6 CEE7CEE9CEEACEEDCEEECEEFCEF0CEF1CEF2CEF3CEF6CEFACEFBCEFCCEFDCEFE CEFFAC00AC01AC04AC07AC08AC09AC0AAC10AC11AC12AC13AC14AC15AC16AC17 AC19AC1AAC1BAC1CAC1DAC20AC24AC2CAC2DAC2FAC30AC31AC38AC39AC3CAC40 AC4BAC4DAC54AC58AC5CAC70AC71AC74AC77AC78AC7AAC80AC81AC83AC84AC85 AC86AC89AC8AAC8BAC8CAC90AC94AC9CAC9DAC9FACA0ACA1ACA8ACA9ACAAACAC ACAFACB0ACB8ACB9ACBBACBCACBDACC1ACC4ACC8ACCCACD5ACD7ACE0ACE1ACE4 ACE7ACE8ACEAACECACEFACF0ACF1ACF3ACF5ACF6ACFCACFDAD00AD04AD060000 B1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CF02CF03CF05CF06CF07CF09CF0ACF0BCF0CCF0DCF0ECF0FCF12CF14CF16 CF17CF18CF19CF1ACF1BCF1DCF1ECF1FCF21CF22CF2300000000000000000000 0000CF25CF26CF27CF28CF29CF2ACF2BCF2ECF32CF33CF34CF35CF36CF37CF39 CF3ACF3BCF3CCF3DCF3ECF3FCF40CF41CF42CF43CF4400000000000000000000 0000CF45CF46CF47CF48CF49CF4ACF4BCF4CCF4DCF4ECF4FCF50CF51CF52CF53 CF56CF57CF59CF5ACF5BCF5DCF5ECF5FCF60CF61CF62CF63CF66CF68CF6ACF6B CF6CAD0CAD0DAD0FAD11AD18AD1CAD20AD29AD2CAD2DAD34AD35AD38AD3CAD44 AD45AD47AD49AD50AD54AD58AD61AD63AD6CAD6DAD70AD73AD74AD75AD76AD7B AD7CAD7DAD7FAD81AD82AD88AD89AD8CAD90AD9CAD9DADA4ADB7ADC0ADC1ADC4 ADC8ADD0ADD1ADD3ADDCADE0ADE4ADF8ADF9ADFCADFFAE00AE01AE08AE09AE0B AE0DAE14AE30AE31AE34AE37AE38AE3AAE40AE41AE43AE45AE46AE4AAE4CAE4D AE4EAE50AE54AE56AE5CAE5DAE5FAE60AE61AE65AE68AE69AE6CAE70AE780000 B2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CF6DCF6ECF6FCF72CF73CF75CF76CF77CF79CF7ACF7BCF7CCF7DCF7ECF7F CF81CF82CF83CF84CF86CF87CF88CF89CF8ACF8BCF8D00000000000000000000 0000CF8ECF8FCF90CF91CF92CF93CF94CF95CF96CF97CF98CF99CF9ACF9BCF9C CF9DCF9ECF9FCFA0CFA2CFA3CFA4CFA5CFA6CFA7CFA900000000000000000000 0000CFAACFABCFACCFADCFAECFAFCFB1CFB2CFB3CFB4CFB5CFB6CFB7CFB8CFB9 CFBACFBBCFBCCFBDCFBECFBFCFC0CFC1CFC2CFC3CFC5CFC6CFC7CFC8CFC9CFCA CFCBAE79AE7BAE7CAE7DAE84AE85AE8CAEBCAEBDAEBEAEC0AEC4AECCAECDAECF AED0AED1AED8AED9AEDCAEE8AEEBAEEDAEF4AEF8AEFCAF07AF08AF0DAF10AF2C AF2DAF30AF32AF34AF3CAF3DAF3FAF41AF42AF43AF48AF49AF50AF5CAF5DAF64 AF65AF79AF80AF84AF88AF90AF91AF95AF9CAFB8AFB9AFBCAFC0AFC7AFC8AFC9 AFCBAFCDAFCEAFD4AFDCAFE8AFE9AFF0AFF1AFF4AFF8B000B001B004B00CB010 B014B01CB01DB028B044B045B048B04AB04CB04EB053B054B055B057B0590000 B3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CFCCCFCDCFCECFCFCFD0CFD1CFD2CFD3CFD4CFD5CFD6CFD7CFD8CFD9CFDA CFDBCFDCCFDDCFDECFDFCFE2CFE3CFE5CFE6CFE7CFE900000000000000000000 0000CFEACFEBCFECCFEDCFEECFEFCFF2CFF4CFF6CFF7CFF8CFF9CFFACFFBCFFD CFFECFFFD001D002D003D005D006D007D008D009D00A00000000000000000000 0000D00BD00CD00DD00ED00FD010D012D013D014D015D016D017D019D01AD01B D01CD01DD01ED01FD020D021D022D023D024D025D026D027D028D029D02AD02B D02CB05DB07CB07DB080B084B08CB08DB08FB091B098B099B09AB09CB09FB0A0 B0A1B0A2B0A8B0A9B0ABB0ACB0ADB0AEB0AFB0B1B0B3B0B4B0B5B0B8B0BCB0C4 B0C5B0C7B0C8B0C9B0D0B0D1B0D4B0D8B0E0B0E5B108B109B10BB10CB110B112 B113B118B119B11BB11CB11DB123B124B125B128B12CB134B135B137B138B139 B140B141B144B148B150B151B154B155B158B15CB160B178B179B17CB180B182 B188B189B18BB18DB192B193B194B198B19CB1A8B1CCB1D0B1D4B1DCB1DD0000 B4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D02ED02FD030D031D032D033D036D037D039D03AD03BD03DD03ED03FD040 D041D042D043D046D048D04AD04BD04CD04DD04ED04F00000000000000000000 0000D051D052D053D055D056D057D059D05AD05BD05CD05DD05ED05FD061D062 D063D064D065D066D067D068D069D06AD06BD06ED06F00000000000000000000 0000D071D072D073D075D076D077D078D079D07AD07BD07ED07FD080D082D083 D084D085D086D087D088D089D08AD08BD08CD08DD08ED08FD090D091D092D093 D094B1DFB1E8B1E9B1ECB1F0B1F9B1FBB1FDB204B205B208B20BB20CB214B215 B217B219B220B234B23CB258B25CB260B268B269B274B275B27CB284B285B289 B290B291B294B298B299B29AB2A0B2A1B2A3B2A5B2A6B2AAB2ACB2B0B2B4B2C8 B2C9B2CCB2D0B2D2B2D8B2D9B2DBB2DDB2E2B2E4B2E5B2E6B2E8B2EBB2ECB2ED B2EEB2EFB2F3B2F4B2F5B2F7B2F8B2F9B2FAB2FBB2FFB300B301B304B308B310 B311B313B314B315B31CB354B355B356B358B35BB35CB35EB35FB364B3650000 B5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D095D096D097D098D099D09AD09BD09CD09DD09ED09FD0A0D0A1D0A2D0A3 D0A6D0A7D0A9D0AAD0ABD0ADD0AED0AFD0B0D0B1D0B200000000000000000000 0000D0B3D0B6D0B8D0BAD0BBD0BCD0BDD0BED0BFD0C2D0C3D0C5D0C6D0C7D0CA D0CBD0CCD0CDD0CED0CFD0D2D0D6D0D7D0D8D0D9D0DA00000000000000000000 0000D0DBD0DED0DFD0E1D0E2D0E3D0E5D0E6D0E7D0E8D0E9D0EAD0EBD0EED0F2 D0F3D0F4D0F5D0F6D0F7D0F9D0FAD0FBD0FCD0FDD0FED0FFD100D101D102D103 D104B367B369B36BB36EB370B371B374B378B380B381B383B384B385B38CB390 B394B3A0B3A1B3A8B3ACB3C4B3C5B3C8B3CBB3CCB3CEB3D0B3D4B3D5B3D7B3D9 B3DBB3DDB3E0B3E4B3E8B3FCB410B418B41CB420B428B429B42BB434B450B451 B454B458B460B461B463B465B46CB480B488B49DB4A4B4A8B4ACB4B5B4B7B4B9 B4C0B4C4B4C8B4D0B4D5B4DCB4DDB4E0B4E3B4E4B4E6B4ECB4EDB4EFB4F1B4F8 B514B515B518B51BB51CB524B525B527B528B529B52AB530B531B534B5380000 B6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D105D106D107D108D109D10AD10BD10CD10ED10FD110D111D112D113D114 D115D116D117D118D119D11AD11BD11CD11DD11ED11F00000000000000000000 0000D120D121D122D123D124D125D126D127D128D129D12AD12BD12CD12DD12E D12FD132D133D135D136D137D139D13BD13CD13DD13E00000000000000000000 0000D13FD142D146D147D148D149D14AD14BD14ED14FD151D152D153D155D156 D157D158D159D15AD15BD15ED160D162D163D164D165D166D167D169D16AD16B D16DB540B541B543B544B545B54BB54CB54DB550B554B55CB55DB55FB560B561 B5A0B5A1B5A4B5A8B5AAB5ABB5B0B5B1B5B3B5B4B5B5B5BBB5BCB5BDB5C0B5C4 B5CCB5CDB5CFB5D0B5D1B5D8B5ECB610B611B614B618B625B62CB634B648B664 B668B69CB69DB6A0B6A4B6ABB6ACB6B1B6D4B6F0B6F4B6F8B700B701B705B728 B729B72CB72FB730B738B739B73BB744B748B74CB754B755B760B764B768B770 B771B773B775B77CB77DB780B784B78CB78DB78FB790B791B792B796B7970000 B7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D16ED16FD170D171D172D173D174D175D176D177D178D179D17AD17BD17D D17ED17FD180D181D182D183D185D186D187D189D18A00000000000000000000 0000D18BD18CD18DD18ED18FD190D191D192D193D194D195D196D197D198D199 D19AD19BD19CD19DD19ED19FD1A2D1A3D1A5D1A6D1A700000000000000000000 0000D1A9D1AAD1ABD1ACD1ADD1AED1AFD1B2D1B4D1B6D1B7D1B8D1B9D1BBD1BD D1BED1BFD1C1D1C2D1C3D1C4D1C5D1C6D1C7D1C8D1C9D1CAD1CBD1CCD1CDD1CE D1CFB798B799B79CB7A0B7A8B7A9B7ABB7ACB7ADB7B4B7B5B7B8B7C7B7C9B7EC B7EDB7F0B7F4B7FCB7FDB7FFB800B801B807B808B809B80CB810B818B819B81B B81DB824B825B828B82CB834B835B837B838B839B840B844B851B853B85CB85D B860B864B86CB86DB86FB871B878B87CB88DB8A8B8B0B8B4B8B8B8C0B8C1B8C3 B8C5B8CCB8D0B8D4B8DDB8DFB8E1B8E8B8E9B8ECB8F0B8F8B8F9B8FBB8FDB904 B918B920B93CB93DB940B944B94CB94FB951B958B959B95CB960B968B9690000 B8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D1D0D1D1D1D2D1D3D1D4D1D5D1D6D1D7D1D9D1DAD1DBD1DCD1DDD1DED1DF D1E0D1E1D1E2D1E3D1E4D1E5D1E6D1E7D1E8D1E9D1EA00000000000000000000 0000D1EBD1ECD1EDD1EED1EFD1F0D1F1D1F2D1F3D1F5D1F6D1F7D1F9D1FAD1FB D1FCD1FDD1FED1FFD200D201D202D203D204D205D20600000000000000000000 0000D208D20AD20BD20CD20DD20ED20FD211D212D213D214D215D216D217D218 D219D21AD21BD21CD21DD21ED21FD220D221D222D223D224D225D226D227D228 D229B96BB96DB974B975B978B97CB984B985B987B989B98AB98DB98EB9ACB9AD B9B0B9B4B9BCB9BDB9BFB9C1B9C8B9C9B9CCB9CEB9CFB9D0B9D1B9D2B9D8B9D9 B9DBB9DDB9DEB9E1B9E3B9E4B9E5B9E8B9ECB9F4B9F5B9F7B9F8B9F9B9FABA00 BA01BA08BA15BA38BA39BA3CBA40BA42BA48BA49BA4BBA4DBA4EBA53BA54BA55 BA58BA5CBA64BA65BA67BA68BA69BA70BA71BA74BA78BA83BA84BA85BA87BA8C BAA8BAA9BAABBAACBAB0BAB2BAB8BAB9BABBBABDBAC4BAC8BAD8BAD9BAFC0000 B9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D22AD22BD22ED22FD231D232D233D235D236D237D238D239D23AD23BD23E D240D242D243D244D245D246D247D249D24AD24BD24C00000000000000000000 0000D24DD24ED24FD250D251D252D253D254D255D256D257D258D259D25AD25B D25DD25ED25FD260D261D262D263D265D266D267D26800000000000000000000 0000D269D26AD26BD26CD26DD26ED26FD270D271D272D273D274D275D276D277 D278D279D27AD27BD27CD27DD27ED27FD282D283D285D286D287D289D28AD28B D28CBB00BB04BB0DBB0FBB11BB18BB1CBB20BB29BB2BBB34BB35BB36BB38BB3B BB3CBB3DBB3EBB44BB45BB47BB49BB4DBB4FBB50BB54BB58BB61BB63BB6CBB88 BB8CBB90BBA4BBA8BBACBBB4BBB7BBC0BBC4BBC8BBD0BBD3BBF8BBF9BBFCBBFF BC00BC02BC08BC09BC0BBC0CBC0DBC0FBC11BC14BC15BC16BC17BC18BC1BBC1C BC1DBC1EBC1FBC24BC25BC27BC29BC2DBC30BC31BC34BC38BC40BC41BC43BC44 BC45BC49BC4CBC4DBC50BC5DBC84BC85BC88BC8BBC8CBC8EBC94BC95BC970000 BA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D28DD28ED28FD292D293D294D296D297D298D299D29AD29BD29DD29ED29F D2A1D2A2D2A3D2A5D2A6D2A7D2A8D2A9D2AAD2ABD2AD00000000000000000000 0000D2AED2AFD2B0D2B2D2B3D2B4D2B5D2B6D2B7D2BAD2BBD2BDD2BED2C1D2C3 D2C4D2C5D2C6D2C7D2CAD2CCD2CDD2CED2CFD2D0D2D100000000000000000000 0000D2D2D2D3D2D5D2D6D2D7D2D9D2DAD2DBD2DDD2DED2DFD2E0D2E1D2E2D2E3 D2E6D2E7D2E8D2E9D2EAD2EBD2ECD2EDD2EED2EFD2F2D2F3D2F5D2F6D2F7D2F9 D2FABC99BC9ABCA0BCA1BCA4BCA7BCA8BCB0BCB1BCB3BCB4BCB5BCBCBCBDBCC0 BCC4BCCDBCCFBCD0BCD1BCD5BCD8BCDCBCF4BCF5BCF6BCF8BCFCBD04BD05BD07 BD09BD10BD14BD24BD2CBD40BD48BD49BD4CBD50BD58BD59BD64BD68BD80BD81 BD84BD87BD88BD89BD8ABD90BD91BD93BD95BD99BD9ABD9CBDA4BDB0BDB8BDD4 BDD5BDD8BDDCBDE9BDF0BDF4BDF8BE00BE03BE05BE0CBE0DBE10BE14BE1CBE1D BE1FBE44BE45BE48BE4CBE4EBE54BE55BE57BE59BE5ABE5BBE60BE61BE640000 BB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D2FBD2FCD2FDD2FED2FFD302D304D306D307D308D309D30AD30BD30FD311 D312D313D315D317D318D319D31AD31BD31ED322D32300000000000000000000 0000D324D326D327D32AD32BD32DD32ED32FD331D332D333D334D335D336D337 D33AD33ED33FD340D341D342D343D346D347D348D34900000000000000000000 0000D34AD34BD34CD34DD34ED34FD350D351D352D353D354D355D356D357D358 D359D35AD35BD35CD35DD35ED35FD360D361D362D363D364D365D366D367D368 D369BE68BE6ABE70BE71BE73BE74BE75BE7BBE7CBE7DBE80BE84BE8CBE8DBE8F BE90BE91BE98BE99BEA8BED0BED1BED4BED7BED8BEE0BEE3BEE4BEE5BEECBF01 BF08BF09BF18BF19BF1BBF1CBF1DBF40BF41BF44BF48BF50BF51BF55BF94BFB0 BFC5BFCCBFCDBFD0BFD4BFDCBFDFBFE1C03CC051C058C05CC060C068C069C090 C091C094C098C0A0C0A1C0A3C0A5C0ACC0ADC0AFC0B0C0B3C0B4C0B5C0B6C0BC C0BDC0BFC0C0C0C1C0C5C0C8C0C9C0CCC0D0C0D8C0D9C0DBC0DCC0DDC0E40000 BC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D36AD36BD36CD36DD36ED36FD370D371D372D373D374D375D376D377D378 D379D37AD37BD37ED37FD381D382D383D385D386D38700000000000000000000 0000D388D389D38AD38BD38ED392D393D394D395D396D397D39AD39BD39DD39E D39FD3A1D3A2D3A3D3A4D3A5D3A6D3A7D3AAD3ACD3AE00000000000000000000 0000D3AFD3B0D3B1D3B2D3B3D3B5D3B6D3B7D3B9D3BAD3BBD3BDD3BED3BFD3C0 D3C1D3C2D3C3D3C6D3C7D3CAD3CBD3CCD3CDD3CED3CFD3D1D3D2D3D3D3D4D3D5 D3D6C0E5C0E8C0ECC0F4C0F5C0F7C0F9C100C104C108C110C115C11CC11DC11E C11FC120C123C124C126C127C12CC12DC12FC130C131C136C138C139C13CC140 C148C149C14BC14CC14DC154C155C158C15CC164C165C167C168C169C170C174 C178C185C18CC18DC18EC190C194C196C19CC19DC19FC1A1C1A5C1A8C1A9C1AC C1B0C1BDC1C4C1C8C1CCC1D4C1D7C1D8C1E0C1E4C1E8C1F0C1F1C1F3C1FCC1FD C200C204C20CC20DC20FC211C218C219C21CC21FC220C228C229C22BC22D0000 BD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D3D7D3D9D3DAD3DBD3DCD3DDD3DED3DFD3E0D3E2D3E4D3E5D3E6D3E7D3E8 D3E9D3EAD3EBD3EED3EFD3F1D3F2D3F3D3F5D3F6D3F700000000000000000000 0000D3F8D3F9D3FAD3FBD3FED400D402D403D404D405D406D407D409D40AD40B D40CD40DD40ED40FD410D411D412D413D414D415D41600000000000000000000 0000D417D418D419D41AD41BD41CD41ED41FD420D421D422D423D424D425D426 D427D428D429D42AD42BD42CD42DD42ED42FD430D431D432D433D434D435D436 D437C22FC231C232C234C248C250C251C254C258C260C265C26CC26DC270C274 C27CC27DC27FC281C288C289C290C298C29BC29DC2A4C2A5C2A8C2ACC2ADC2B4 C2B5C2B7C2B9C2DCC2DDC2E0C2E3C2E4C2EBC2ECC2EDC2EFC2F1C2F6C2F8C2F9 C2FBC2FCC300C308C309C30CC30DC313C314C315C318C31CC324C325C328C329 C345C368C369C36CC370C372C378C379C37CC37DC384C388C38CC3C0C3D8C3D9 C3DCC3DFC3E0C3E2C3E8C3E9C3EDC3F4C3F5C3F8C408C410C424C42CC4300000 BE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D438D439D43AD43BD43CD43DD43ED43FD441D442D443D445D446D447D448 D449D44AD44BD44CD44DD44ED44FD450D451D452D45300000000000000000000 0000D454D455D456D457D458D459D45AD45BD45DD45ED45FD461D462D463D465 D466D467D468D469D46AD46BD46CD46ED470D471D47200000000000000000000 0000D473D474D475D476D477D47AD47BD47DD47ED481D483D484D485D486D487 D48AD48CD48ED48FD490D491D492D493D495D496D497D498D499D49AD49BD49C D49DC434C43CC43DC448C464C465C468C46CC474C475C479C480C494C49CC4B8 C4BCC4E9C4F0C4F1C4F4C4F8C4FAC4FFC500C501C50CC510C514C51CC528C529 C52CC530C538C539C53BC53DC544C545C548C549C54AC54CC54DC54EC553C554 C555C557C558C559C55DC55EC560C561C564C568C570C571C573C574C575C57C C57DC580C584C587C58CC58DC58FC591C595C597C598C59CC5A0C5A9C5B4C5B5 C5B8C5B9C5BBC5BCC5BDC5BEC5C4C5C5C5C6C5C7C5C8C5C9C5CAC5CCC5CE0000 BF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D49ED49FD4A0D4A1D4A2D4A3D4A4D4A5D4A6D4A7D4A8D4AAD4ABD4ACD4AD D4AED4AFD4B0D4B1D4B2D4B3D4B4D4B5D4B6D4B7D4B800000000000000000000 0000D4B9D4BAD4BBD4BCD4BDD4BED4BFD4C0D4C1D4C2D4C3D4C4D4C5D4C6D4C7 D4C8D4C9D4CAD4CBD4CDD4CED4CFD4D1D4D2D4D3D4D500000000000000000000 0000D4D6D4D7D4D8D4D9D4DAD4DBD4DDD4DED4E0D4E1D4E2D4E3D4E4D4E5D4E6 D4E7D4E9D4EAD4EBD4EDD4EED4EFD4F1D4F2D4F3D4F4D4F5D4F6D4F7D4F9D4FA D4FCC5D0C5D1C5D4C5D8C5E0C5E1C5E3C5E5C5ECC5EDC5EEC5F0C5F4C5F6C5F7 C5FCC5FDC5FEC5FFC600C601C605C606C607C608C60CC610C618C619C61BC61C C624C625C628C62CC62DC62EC630C633C634C635C637C639C63BC640C641C644 C648C650C651C653C654C655C65CC65DC660C66CC66FC671C678C679C67CC680 C688C689C68BC68DC694C695C698C69CC6A4C6A5C6A7C6A9C6B0C6B1C6B4C6B8 C6B9C6BAC6C0C6C1C6C3C6C5C6CCC6CDC6D0C6D4C6DCC6DDC6E0C6E1C6E80000 C0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D4FED4FFD500D501D502D503D505D506D507D509D50AD50BD50DD50ED50F D510D511D512D513D516D518D519D51AD51BD51CD51D00000000000000000000 0000D51ED51FD520D521D522D523D524D525D526D527D528D529D52AD52BD52C D52DD52ED52FD530D531D532D533D534D535D536D53700000000000000000000 0000D538D539D53AD53BD53ED53FD541D542D543D545D546D547D548D549D54A D54BD54ED550D552D553D554D555D556D557D55AD55BD55DD55ED55FD561D562 D563C6E9C6ECC6F0C6F8C6F9C6FDC704C705C708C70CC714C715C717C719C720 C721C724C728C730C731C733C735C737C73CC73DC740C744C74AC74CC74DC74F C751C752C753C754C755C756C757C758C75CC760C768C76BC774C775C778C77C C77DC77EC783C784C785C787C788C789C78AC78EC790C791C794C796C797C798 C79AC7A0C7A1C7A3C7A4C7A5C7A6C7ACC7ADC7B0C7B4C7BCC7BDC7BFC7C0C7C1 C7C8C7C9C7CCC7CEC7D0C7D8C7DDC7E4C7E8C7ECC800C801C804C808C80A0000 C1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D564D566D567D56AD56CD56ED56FD570D571D572D573D576D577D579D57A D57BD57DD57ED57FD580D581D582D583D586D58AD58B00000000000000000000 0000D58CD58DD58ED58FD591D592D593D594D595D596D597D598D599D59AD59B D59CD59DD59ED59FD5A0D5A1D5A2D5A3D5A4D5A6D5A700000000000000000000 0000D5A8D5A9D5AAD5ABD5ACD5ADD5AED5AFD5B0D5B1D5B2D5B3D5B4D5B5D5B6 D5B7D5B8D5B9D5BAD5BBD5BCD5BDD5BED5BFD5C0D5C1D5C2D5C3D5C4D5C5D5C6 D5C7C810C811C813C815C816C81CC81DC820C824C82CC82DC82FC831C838C83C C840C848C849C84CC84DC854C870C871C874C878C87AC880C881C883C885C886 C887C88BC88CC88DC894C89DC89FC8A1C8A8C8BCC8BDC8C4C8C8C8CCC8D4C8D5 C8D7C8D9C8E0C8E1C8E4C8F5C8FCC8FDC900C904C905C906C90CC90DC90FC911 C918C92CC934C950C951C954C958C960C961C963C96CC970C974C97CC988C989 C98CC990C998C999C99BC99DC9C0C9C1C9C4C9C7C9C8C9CAC9D0C9D1C9D30000 C2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D5CAD5CBD5CDD5CED5CFD5D1D5D3D5D4D5D5D5D6D5D7D5DAD5DCD5DED5DF D5E0D5E1D5E2D5E3D5E6D5E7D5E9D5EAD5EBD5EDD5EE00000000000000000000 0000D5EFD5F0D5F1D5F2D5F3D5F6D5F8D5FAD5FBD5FCD5FDD5FED5FFD602D603 D605D606D607D609D60AD60BD60CD60DD60ED60FD61200000000000000000000 0000D616D617D618D619D61AD61BD61DD61ED61FD621D622D623D625D626D627 D628D629D62AD62BD62CD62ED62FD630D631D632D633D634D635D636D637D63A D63BC9D5C9D6C9D9C9DAC9DCC9DDC9E0C9E2C9E4C9E7C9ECC9EDC9EFC9F0C9F1 C9F8C9F9C9FCCA00CA08CA09CA0BCA0CCA0DCA14CA18CA29CA4CCA4DCA50CA54 CA5CCA5DCA5FCA60CA61CA68CA7DCA84CA98CABCCABDCAC0CAC4CACCCACDCACF CAD1CAD3CAD8CAD9CAE0CAECCAF4CB08CB10CB14CB18CB20CB21CB41CB48CB49 CB4CCB50CB58CB59CB5DCB64CB78CB79CB9CCBB8CBD4CBE4CBE7CBE9CC0CCC0D CC10CC14CC1CCC1DCC21CC22CC27CC28CC29CC2CCC2ECC30CC38CC39CC3B0000 C3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D63DD63ED63FD641D642D643D644D646D647D64AD64CD64ED64FD650D652 D653D656D657D659D65AD65BD65DD65ED65FD660D66100000000000000000000 0000D662D663D664D665D666D668D66AD66BD66CD66DD66ED66FD672D673D675 D676D677D678D679D67AD67BD67CD67DD67ED67FD68000000000000000000000 0000D681D682D684D686D687D688D689D68AD68BD68ED68FD691D692D693D695 D696D697D698D699D69AD69BD69CD69ED6A0D6A2D6A3D6A4D6A5D6A6D6A7D6A9 D6AACC3CCC3DCC3ECC44CC45CC48CC4CCC54CC55CC57CC58CC59CC60CC64CC66 CC68CC70CC75CC98CC99CC9CCCA0CCA8CCA9CCABCCACCCADCCB4CCB5CCB8CCBC CCC4CCC5CCC7CCC9CCD0CCD4CCE4CCECCCF0CD01CD08CD09CD0CCD10CD18CD19 CD1BCD1DCD24CD28CD2CCD39CD5CCD60CD64CD6CCD6DCD6FCD71CD78CD88CD94 CD95CD98CD9CCDA4CDA5CDA7CDA9CDB0CDC4CDCCCDD0CDE8CDECCDF0CDF8CDF9 CDFBCDFDCE04CE08CE0CCE14CE19CE20CE21CE24CE28CE30CE31CE33CE350000 C4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D6ABD6ADD6AED6AFD6B1D6B2D6B3D6B4D6B5D6B6D6B7D6B8D6BAD6BCD6BD D6BED6BFD6C0D6C1D6C2D6C3D6C6D6C7D6C9D6CAD6CB00000000000000000000 0000D6CDD6CED6CFD6D0D6D2D6D3D6D5D6D6D6D8D6DAD6DBD6DCD6DDD6DED6DF D6E1D6E2D6E3D6E5D6E6D6E7D6E9D6EAD6EBD6ECD6ED00000000000000000000 0000D6EED6EFD6F1D6F2D6F3D6F4D6F6D6F7D6F8D6F9D6FAD6FBD6FED6FFD701 D702D703D705D706D707D708D709D70AD70BD70CD70DD70ED70FD710D712D713 D714CE58CE59CE5CCE5FCE60CE61CE68CE69CE6BCE6DCE74CE75CE78CE7CCE84 CE85CE87CE89CE90CE91CE94CE98CEA0CEA1CEA3CEA4CEA5CEACCEADCEC1CEE4 CEE5CEE8CEEBCEECCEF4CEF5CEF7CEF8CEF9CF00CF01CF04CF08CF10CF11CF13 CF15CF1CCF20CF24CF2CCF2DCF2FCF30CF31CF38CF54CF55CF58CF5CCF64CF65 CF67CF69CF70CF71CF74CF78CF80CF85CF8CCFA1CFA8CFB0CFC4CFE0CFE1CFE4 CFE8CFF0CFF1CFF3CFF5CFFCD000D004D011D018D02DD034D035D038D03C0000 C5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D715D716D717D71AD71BD71DD71ED71FD721D722D723D724D725D726D727 D72AD72CD72ED72FD730D731D732D733D736D737D73900000000000000000000 0000D73AD73BD73DD73ED73FD740D741D742D743D745D746D748D74AD74BD74C D74DD74ED74FD752D753D755D75AD75BD75CD75DD75E00000000000000000000 0000D75FD762D764D766D767D768D76AD76BD76DD76ED76FD771D772D773D775 D776D777D778D779D77AD77BD77ED77FD780D782D783D784D785D786D787D78A D78BD044D045D047D049D050D054D058D060D06CD06DD070D074D07CD07DD081 D0A4D0A5D0A8D0ACD0B4D0B5D0B7D0B9D0C0D0C1D0C4D0C8D0C9D0D0D0D1D0D3 D0D4D0D5D0DCD0DDD0E0D0E4D0ECD0EDD0EFD0F0D0F1D0F8D10DD130D131D134 D138D13AD140D141D143D144D145D14CD14DD150D154D15CD15DD15FD161D168 D16CD17CD184D188D1A0D1A1D1A4D1A8D1B0D1B1D1B3D1B5D1BAD1BCD1C0D1D8 D1F4D1F8D207D209D210D22CD22DD230D234D23CD23DD23FD241D248D25C0000 C6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D78DD78ED78FD791D792D793D794D795D796D797D79AD79CD79ED79FD7A0 D7A1D7A2D7A30000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D264D280D281D284D288D290D291D295D29CD2A0D2A4D2ACD2B1D2B8D2B9 D2BCD2BFD2C0D2C2D2C8D2C9D2CBD2D4D2D8D2DCD2E4D2E5D2F0D2F1D2F4D2F8 D300D301D303D305D30CD30DD30ED310D314D316D31CD31DD31FD320D321D325 D328D329D32CD330D338D339D33BD33CD33DD344D345D37CD37DD380D384D38C D38DD38FD390D391D398D399D39CD3A0D3A8D3A9D3ABD3ADD3B4D3B8D3BCD3C4 D3C5D3C8D3C9D3D0D3D8D3E1D3E3D3ECD3EDD3F0D3F4D3FCD3FDD3FFD4010000 C7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D408D41DD440D444D45CD460D464D46DD46FD478D479D47CD47FD480D482 D488D489D48BD48DD494D4A9D4CCD4D0D4D4D4DCD4DFD4E8D4ECD4F0D4F8D4FB D4FDD504D508D50CD514D515D517D53CD53DD540D544D54CD54DD54FD551D558 D559D55CD560D565D568D569D56BD56DD574D575D578D57CD584D585D587D588 D589D590D5A5D5C8D5C9D5CCD5D0D5D2D5D8D5D9D5DBD5DDD5E4D5E5D5E8D5EC D5F4D5F5D5F7D5F9D600D601D604D608D610D611D613D614D615D61CD6200000 C8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D624D62DD638D639D63CD640D645D648D649D64BD64DD651D654D655D658 D65CD667D669D670D671D674D683D685D68CD68DD690D694D69DD69FD6A1D6A8 D6ACD6B0D6B9D6BBD6C4D6C5D6C8D6CCD6D1D6D4D6D7D6D9D6E0D6E4D6E8D6F0 D6F5D6FCD6FDD700D704D711D718D719D71CD720D728D729D72BD72DD734D735 D738D73CD744D747D749D750D751D754D756D757D758D759D760D761D763D765 D769D76CD770D774D77CD77DD781D788D789D78CD790D798D799D79BD79D0000 CA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F3D4F73504750F952A053EF547554E556095AC15BB6668767B667B767EF 6B4C73C275C27A3C82DB8304885788888A368CC88DCF8EFB8FE699D5523B5374 5404606A61646BBC73CF811A89BA89D295A34F83520A58BE597859E65E725E79 61C763C0674667EC687F6F97764E770B78F57A087AFF7C21809D826E82718AEB 95934E6B559D66F76E3478A37AED845B8910874E97A852D8574E582A5D4C611F 61BE6221656267D16A446E1B751875B376E377B07D3A90AF945194529F950000 CB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000053235CAC753280DB92409598525B580859DC5CA15D175EB75F3A5F4A6177 6C5F757A75867CE07D737DB17F8C81548221859189418B1B92FC964D9C474ECB 4EF7500B51F1584F6137613E6168653969EA6F1175A5768676D67B8782A584CB F90093A7958B55805BA25751F9017CB37FB991B5502853BB5C455DE862D2636E 64DA64E76E2070AC795B8DDD8E1EF902907D924592F84E7E4EF650655DFE5EFA 61066957817186548E4793759A2B4E5E5091677068405109528D52926AA20000 CC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077BC92109ED452AB602F8FF2504861A963ED64CA683C6A846FC0818889A1 96945805727D72AC75047D797E6D80A9898B8B7490639D5162896C7A6F547D50 7F3A8A23517C614A7B9D8B199257938C4EAC4FD3501E50BE510652C152CD537F 577058835E9A5F91617661AC64CE656C666F66BB66F468976D87708570F1749F 74A574CA75D9786C78EC7ADF7AF67D457D938015803F811B83968B668F159015 93E1980398389A5A9BE84FC25553583A59515B635C4660B86212684268B00000 CD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000068E86EAA754C767878CE7A3D7CFB7E6B7E7C8A088AA18C3F968E9DC453E4 53E9544A547156FA59D15B645C3B5EAB62F765376545657266A067AF69C16CBD 75FC7690777E7A3F7F94800380A1818F82E682FD83F085C1883188B48AA5F903 8F9C932E96C798679AD89F1354ED659B66F2688F7A408C379D6056F057645D11 660668B168CD6EFE7428889E9BE46C68F9049AA84F9B516C5171529F5B545DE5 6050606D62F163A7653B73D97A7A86A38CA2978F4E325BE16208679C74DC0000 CE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000079D183D38A878AB28DE8904E934B98465ED369E885FF90EDF90551A05B98 5BEC616368FA6B3E704C742F74D87BA17F5083C589C08CAB95DC9928522E605D 62EC90024F8A5149532158D95EE366E06D38709A72C273D67B5080F1945B5366 639B7F6B4E565080584A58DE602A612762D069D09B415B8F7D1880B18F5F4EA4 50D154AC55AC5B0C5DA05DE7652A654E68216A4B72E1768E77EF7D5E7FF981A0 854E86DF8F038F4E90CA99039A559BAB4E184E454E5D4EC74FF1517752FE0000 CF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000534053E353E5548E5614577557A25BC75D875ED061FC62D8655167B867E9 69CB6B506BC66BEC6C426E9D707872D77396740377BF77E97A767D7F800981FC 8205820A82DF88628B338CFC8EC0901190B1926492B699D29A459CE99DD79F9C 570B5C4083CA97A097AB9EB4541B7A987FA488D98ECD90E158005C4863987A9F 5BAE5F137A797AAE828E8EAC5026523852F85377570862F363726B0A6DC37737 53A5735785688E7695D5673A6AC36F708A6D8ECC994BF90666776B788CB40000 D0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009B3CF90753EB572D594E63C669FB73EA78457ABA7AC57CFE8475898F8D73 903595A852FB574775477B6083CC921EF9086A58514B524B5287621F68D86975 969950C552A452E461C365A4683969FF747E7B4B82B983EB89B28B398FD19949 F9094ECA599764D266116A8E7434798179BD82A9887E887F895FF90A93264F0B 53CA602562716C727D1A7D664E98516277DC80AF4F014F0E5176518055DC5668 573B57FA57FC5914594759935BC45C905D0E5DF15E7E5FCC628065D765E30000 D1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000671E671F675E68CB68C46A5F6B3A6C236C7D6C826DC773987426742A7482 74A37578757F788178EF794179477948797A7B957D007DBA7F888006802D808C 8A188B4F8C488D779321932498E299519A0E9A0F9A659E927DCA4F76540962EE 685491D155AB513AF90BF90C5A1C61E6F90D62CF62FFF90EF90FF910F911F912 F91390A3F914F915F916F917F9188AFEF919F91AF91BF91C6696F91D7156F91E F91F96E3F920634F637A5357F921678F69606E73F9227537F923F924F9250000 D2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007D0DF926F927887256CA5A18F928F929F92AF92BF92C4E43F92D51675948 67F08010F92E59735E74649A79CA5FF5606C62C8637B5BE75BD752AAF92F5974 5F296012F930F931F9327459F933F934F935F936F937F93899D1F939F93AF93B F93CF93DF93EF93FF940F941F942F9436FC3F944F94581BF8FB260F1F946F947 8166F948F9495C3FF94AF94BF94CF94DF94EF94FF950F9515AE98A25677B7D10 F952F953F954F955F956F95780FDF958F9595C3C6CE5533F6EBA591A83360000 D3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E394EB64F4655AE571858C75F5665B765E66A806BB56E4D77ED7AEF7C1E 7DDE86CB88929132935B64BB6FBE737A75B890545556574D61BA64D466C76DE1 6E5B6F6D6FB975F0804381BD854189838AC78B5A931F6C9375537B548E0F905D 5510580258585E626207649E68E075767CD687B39EE84EE35788576E59275C0D 5CB15E365F85623464E173B381FA888B8CB8968A9EDB5B855FB760B350125200 52305716583558575C0E5C605CF65D8B5EA65F9260BC63116389641768430000 D4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000068F96AC26DD86E216ED46FE471FE76DC777979B17A3B840489A98CED8DF3 8E4890039014905390FD934D967697DC6BD27006725872A27368776379BF7BE4 7E9B8B8058A960C7656665FD66BE6C8C711E71C98C5A98134E6D7A814EDD51AC 51CD52D5540C61A76771685068DF6D1E6F7C75BC77B37AE580F484639285515C 6597675C679375D87AC78373F95A8C469017982D5C6F81C0829A9041906F920D 5F975D9D6A5971C8767B7B4985E48B0491279A30558761F6F95B76697F850000 D5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000863F87BA88F8908FF95C6D1B70D973DE7D61843DF95D916A99F1F95E4E82 53756B046B12703E721B862D9E1E524C8FA35D5064E5652C6B166FEB7C437E9C 85CD896489BD62C981D8881F5ECA67176D6A72FC7405746F878290DE4F865D0D 5FA0840A51B763A075654EAE5006516951C968816A117CAE7CB17CE7826F8AD2 8F1B91CF4FB6513752F554425EEC616E623E65C56ADA6FFE792A85DC882395AD 9A629A6A9E979ECE529B66C66B77701D792B8F6297426190620065236F230000 D6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000714974897DF4806F84EE8F269023934A51BD521752A36D0C70C888C25EC9 65826BAE6FC27C3E73754EE44F3656F9F95F5CBA5DBA601C73B27B2D7F9A7FCE 8046901E923496F6974898189F614F8B6FA779AE91B496B752DEF960648864C4 6AD36F5E7018721076E780018606865C8DEF8F0597329B6F9DFA9E75788C797F 7DA083C993049E7F9E938AD658DF5F046727702774CF7C60807E512170287262 78CA8CC28CDA8CF496F74E8650DA5BEE5ED6659971CE764277AD804A84FC0000 D7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000907C9B279F8D58D85A415C626A136DDA6F0F763B7D2F7E37851E893893E4 964B528965D267F369B46D416E9C700F7409746075597624786B8B2C985E516D 622E96784F96502B5D196DEA7DB88F2A5F8B61446817F961968652D2808B51DC 51CC695E7A1C7DBE83F196754FDA52295398540F550E5C6560A7674E68A86D6C 728172F874067483F96275E27C6C7F797FB8838988CF88E191CC91D096E29BC9 541D6F7E71D0749885FA8EAA96A39C579E9F67976DCB743381E89716782C0000 D8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007ACB7B207C926469746A75F278BC78E899AC9B549EBB5BDE5E556F20819C 83AB90884E07534D5A295DD25F4E6162633D666966FC6EFF6F2B7063779E842C 8513883B8F1399459C3B551C62B9672B6CAB8309896A977A4EA159845FD85FD9 671B7DB27F548292832B83BD8F1E909957CB59B95A925BD06627679A68856BCF 71647F758CB78CE390819B4581088C8A964C9A409EA55B5F6C13731B76F276DF 840C51AA8993514D519552C968C96C94770477207DBF7DEC97629EB56EC50000 D9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000851151A5540D547D660E669D69276E9F76BF7791831784C2879F91699298 9CF488824FAE519252DF59C65E3D61556478647966AE67D06A216BCD6BDB725F 72617441773877DB801782BC83058B008B288C8C67286C90726776EE77667A46 9DA96B7F6C92592267268499536F589359995EDF63CF663467736E3A732B7AD7 82D7932852D95DEB61AE61CB620A62C764AB65E069596B666BCB712173F7755D 7E46821E8302856A8AA38CBF97279D6158A89ED85011520E543B554F65870000 DA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006C767D0A7D0B805E868A958096EF52FF6C95726954735A9A5C3E5D4B5F4C 5FAE672A68B669636E3C6E4477097C737F8E85878B0E8FF797619EF45CB760B6 610D61AB654F65FB65FC6C116CEF739F73C97DE195945BC6871C8B10525D535A 62CD640F64B267346A386CCA73C0749E7B947C957E1B818A823685848FEB96F9 99C14F34534A53CD53DB62CC642C6500659169C36CEE6F5873ED7554762276E4 76FC78D078FB792C7D46822C87E08FD4981298EF52C362D464A56E246F510000 DB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000767C8DCB91B192629AEE9B435023508D574A59A85C285E475F77623F653E 65B965C16609678B699C6EC278C57D2180AA8180822B82B384A1868C8A2A8B17 90A696329F90500D4FF3F96357F95F9862DC6392676F6E43711976C380CC80DA 88F488F589198CE08F29914D966A4F2F4F705E1B67CF6822767D767E9B445E61 6A0A716971D4756AF9647E41854385E998DC4F107B4F7F7095A551E15E0668B5 6C3E6C4E6CDB72AF7BC483036CD5743A50FB528858C164D86A9774A776560000 DC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000078A7861795E29739F965535E5F018B8A8FA88FAF908A522577A59C499F08 4E19500251755C5B5E77661E663A67C468C570B3750175C579C97ADD8F279920 9A084FDD582158315BF6666E6B656D116E7A6F7D73E4752B83E988DC89138B5C 8F144F0F50D55310535C5B935FA9670D798F8179832F8514890789868F398F3B 99A59C12672C4E764FF859495C015CEF5CF0636768D270FD71A2742B7E2B84EC 8702902292D29CF34E0D4ED84FEF50855256526F5426549057E0592B5A660000 DD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005B5A5B755BCC5E9CF9666276657765A76D6E6EA572367B267C3F7F368150 8151819A8240829983A98A038CA08CE68CFB8D748DBA90E891DC961C964499D9 9CE7531752065429567458B35954596E5FFF61A4626E66106C7E711A76C67C89 7CDE7D1B82AC8CC196F0F9674F5B5F175F7F62C25D29670B68DA787C7E439D6C 4E1550995315532A535159835A625E8760B2618A624962796590678769A76BD4 6BD66BD76BD86CB8F968743575FA7812789179D579D87C837DCB7FE180A50000 DE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000813E81C283F2871A88E88AB98B6C8CBB9119975E98DB9F3B56AC5B2A5F6C 658C6AB36BAF6D5C6FF17015725D73AD8CA78CD3983B61916C3780589A014E4D 4E8B4E9B4ED54F3A4F3C4F7F4FDF50FF53F253F8550655E356DB58EB59625A11 5BEB5BFA5C045DF35E2B5F99601D6368659C65AF67F667FB68AD6B7B6C996CD7 6E23700973457802793E7940796079C17BE97D177D728086820D838E84D186C7 88DF8A508A5E8B1D8CDC8D668FAD90AA98FC99DF9E9D524AF9696714F96A0000 DF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005098522A5C7165636C5573CA7523759D7B97849C917897304E7764926BBA 715E85A94E09F96B674968EE6E17829F8518886B63F76F81921298AF4E0A50B7 50CF511F554655AA56175B405C195CE05E385E8A5EA05EC260F368516A616E58 723D724072C076F879657BB17FD488F389F48A738C618CDE971C585E74BD8CFD 55C7F96C7A617D2282727272751F7525F96D7B19588558FB5DBC5E8F5EB65F90 60556292637F654D669166D966F8681668F27280745E7B6E7D6E7DD67F720000 E0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000080E5821285AF897F8A93901D92E49ECD9F205915596D5E2D60DC66146673 67906C506DC56F5F77F378A984C691CB932B4ED950CA514855845B0B5BA36247 657E65CB6E32717D74017444748774BF766C79AA7DDA7E557FA8817A81B38239 861A87EC8A758DE3907892919425994D9BAE53685C5169546CC46D296E2B820C 859B893B8A2D8AAA96EA9F67526166B96BB27E9687FE8D0D9583965D651D6D89 71EEF96E57CE59D35BAC602760FA6210661F665F732973F976DB77017B6C0000 E1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008056807281658AA091924E1652E26B726D177A057B397D30F96F8CB053EC 562F58515BB55C0F5C115DE2624063836414662D68B36CBC6D886EAF701F70A4 71D27526758F758E76197B117BE07C2B7D207D39852C856D86078A34900D9061 90B592B797F69A374FD75C6C675F6D917C9F7E8C8B168D16901F5B6B5DFD640D 84C0905C98E173875B8B609A677E6DDE8A1F8AA69001980C5237F9707051788E 9396887091D74FEE53D755FD56DA578258FD5AC25B885CAB5CC05E2561010000 E2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000620D624B6388641C653665786A396B8A6C346D196F3171E772E973787407 74B27626776179C07A577AEA7CB97D8F7DAC7E617F9E81298331849084DA85EA 88968AB08B908F3890429083916C929692B9968B96A796A896D6970098089996 9AD39B1A53D4587E59195B705BBF6DD16F5A719F742174B9808583FD5DE15F87 5FAA604265EC6812696F6A536B896D356DF373E376FE77AC7B4D7D148123821C 834084F485638A628AC49187931E980699B4620C88538FF092655D075D270000 E3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005D69745F819D87686FD562FE7FD2893689724E1E4E5850E752DD5347627F 66077E698805965E4F8D5319563659CB5AA45C385C4E5C4D5E025F11604365BD 662F664267BE67F4731C77E2793A7FC5849484CD89968A668A698AE18C558C7A 57F45BD45F0F606F62ED690D6B966E5C71847BD287558B588EFE98DF98FE4F38 4F814FE1547B5A205BB8613C65B0666871FC7533795E7D33814E81E3839885AA 85CE87038A0A8EAB8F9BF9718FC559315BA45BE660895BE95C0B5FC36C810000 E4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9726DF1700B751A82AF8AF64EC05341F97396D96C0F4E9E4FC45152555E 5A255CE86211725982BD83AA86FE88598A1D963F96C599139D099D5D580A5CB3 5DBD5E4460E1611563E16A026E2591029354984E9C109F775B895CB86309664F 6848773C96C1978D98549B9F65A18B018ECB95BC55355CA95DD65EB56697764C 83F495C758D362BC72CE9D284EF0592E600F663B6B8379E79D26539354C057C3 5D16611B66D66DAF788D827E969897445384627C63966DB27E0A814B984D0000 E5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006AFB7F4C9DAF9E1A4E5F503B51B6591C60F963F66930723A8036F97491CE 5F31F975F9767D0482E5846F84BB85E58E8DF9774F6FF978F97958E45B436059 63DA6518656D6698F97A694A6A236D0B7001716C75D2760D79B37A70F97B7F8A F97C8944F97D8B9391C0967DF97E990A57045FA165BC6F01760079A68A9E99AD 9B5A9F6C510461B662916A8D81C6504358305F6671098A008AFA5B7C86164FFA 513C56B4594463A96DF95DAA696D51864E884F59F97FF980F9815982F9820000 E6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9836B5F6C5DF98474B57916F9858207824583398F3F8F5DF9869918F987 F988F9894EA6F98A57DF5F796613F98BF98C75AB7E798B6FF98D90069A5B56A5 582759F85A1F5BB4F98E5EF6F98FF9906350633BF991693D6C876CBF6D8E6D93 6DF56F14F99270DF71367159F99371C371D5F994784F786FF9957B757DE3F996 7E2FF997884D8EDFF998F999F99A925BF99B9CF6F99CF99DF99E60856D85F99F 71B1F9A0F9A195B153ADF9A2F9A3F9A467D3F9A5708E71307430827682D20000 E7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9A695BB9AE59E7D66C4F9A771C18449F9A8F9A9584BF9AAF9AB5DB85F71 F9AC6620668E697969AE6C386CF36E366F416FDA701B702F715071DF7370F9AD 745BF9AE74D476C87A4E7E93F9AFF9B082F18A608FCEF9B19348F9B29719F9B3 F9B44E42502AF9B5520853E166F36C6D6FCA730A777F7A6282AE85DD8602F9B6 88D48A638B7D8C6BF9B792B3F9B8971398104E944F0D4FC950B25348543E5433 55DA586258BA59675A1B5BE4609FF9B961CA655665FF666468A76C5A6FB30000 E8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000070CF71AC73527B7D87088AA49C329F075C4B6C8373447389923A6EAB7465 761F7A697E15860A514058C564C174EE751576707FC1909596CD99546E2674E6 7AA97AAA81E586D987788A1B5A495B8C5B9B68A169006D6373A97413742C7897 7DE97FEB81188155839E8C4C962E981166F05F8065FA67896C6A738B502D5A03 6B6A77EE59165D6C5DCD7325754FF9BAF9BB50E551F9582F592D599659DA5BE5 F9BCF9BD5DA262D76416649364FEF9BE66DCF9BF6A48F9C071FF7464F9C10000 E9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A887AAF7E477E5E80008170F9C287EF89818B209059F9C390809952617E 6B326D747E1F89258FB14FD150AD519752C757C758895BB95EB8614269956D8C 6E676EB6719474627528752C8073833884C98E0A939493DEF9C44E8E4F515076 512A53C853CB53F35B875BD35C24611A618265F4725B7397744076C279507991 79B97D067FBD828B85D5865E8FC2904790F591EA968596E896E952D65F6765ED 6631682F715C7A3690C1980A4E91F9C56A526B9E6F907189801882B885530000 EA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000904B969596F297FB851A9B314E90718A96C45143539F54E15713571257A3 5A9B5AC45BC36028613F63F46C856D396E726E907230733F745782D188818F45 9060F9C6966298589D1B67088D8A925E4F4D504950DE5371570D59D45A015C09 617066906E2D7232744B7DEF80C3840E8466853F875F885B89188B02905597CB 9B4F4E734F915112516AF9C7552F55A95B7A5BA55E7C5E7D5EBE60A060DF6108 610963C465386709F9C867D467DAF9C9696169626CB96D27F9CA6E38F9CB0000 EB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006FE173367337F9CC745C7531F9CD7652F9CEF9CF7DAD81FE843888D58A98 8ADB8AED8E308E42904A903E907A914991C9936EF9D0F9D15809F9D26BD38089 80B2F9D3F9D45141596B5C39F9D5F9D66F6473A780E48D07F9D79217958FF9D8 F9D9F9DAF9DB807F620E701C7D68878DF9DC57A0606961476BB78ABE928096B1 4E59541F6DEB852D967097F398EE63D66CE3909151DD61C981BA9DF94F9D501A 51005B9C610F61FF64EC69056BC5759177E37FA98264858F87FB88638ABC0000 EC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008B7091AB4E8C4EE54F0AF9DDF9DE593759E8F9DF5DF25F1B5F5B6021F9E0 F9E1F9E2F9E3723E73E5F9E4757075CDF9E579FBF9E6800C8033808482E18351 F9E7F9E88CBD8CB39087F9E9F9EA98F4990CF9EBF9EC703776CA7FCA7FCC7FFC 8B1A4EBA4EC152035370F9ED54BD56E059FB5BC55F155FCD6E6EF9EEF9EF7D6A 8335F9F086938A8DF9F1976D9777F9F2F9F34E004F5A4F7E58F965E56EA29038 93B099B94EFB58EC598A59D96041F9F4F9F57A14F9F6834F8CC3516553440000 ED 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9F7F9F8F9F94ECD52695B5582BF4ED4523A54A859C959FF5B505B575B5C 606361486ECB7099716E738674F775B578C17D2B800581EA8328851785C98AEE 8CC796CC4F5C52FA56BC65AB6628707C70B872357DBD828D914C96C09D725B71 68E76B986F7A76DE5C9166AB6F5B7BB47C2A883696DC4E084ED75320583458BB 58EF596C5C075E335E845F35638C66B267566A1F6AA36B0C6F3F7246F9FA7350 748B7AE07CA7817881DF81E7838A846C8523859485CF88DD8D1391AC95770000 EE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000969C518D54C957285BB0624D6750683D68936E3D6ED3707D7E2188C18CA1 8F099F4B9F4E722D7B8F8ACD931A4F474F4E5132548059D05E9562B56775696E 6A176CAE6E1A72D9732A75BD7BB87D3582E783F9845785F78A5B8CAF8E879019 90B896CE9F5F52E3540A5AE15BC2645865756EF472C4F9FB76847A4D7B1B7C4D 7E3E7FDF837B8B2B8CCA8D648DE18E5F8FEA8FF9906993D14F434F7A50B35168 5178524D526A5861587C59605C085C555EDB609B623068136BBF6C086FB10000 EF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000714E742075307538755176727B4C7B8B7BAD7BC67E8F8A6E8F3E8F49923F 92939322942B96FB985A986B991E5207622A62986D5976647ACA7BC07D765360 5CBE5E976F3870B97C9897119B8E9EDE63A5647A87764E014E954EAD505C5075 544859C35B9A5E405EAD5EF75F8160C5633A653F657465CC6676667867FE6968 6A896B636C406DC06DE86E1F6E5E701E70A1738E73FD753A775B7887798E7A0B 7A7D7CBE7D8E82478A028AEA8C9E912D914A91D8926692CC9320970697560000 F0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000975C98029F0E52365291557C58245E1D5F1F608C63D068AF6FDF796D7B2C 81CD85BA88FD8AF88E44918D9664969B973D984C9F4A4FCE514651CB52A95632 5F145F6B63AA64CD65E9664166FA66F9671D689D68D769FD6F156F6E716771E5 722A74AA773A7956795A79DF7A207A957C977CDF7D447E70808785FB86A48A54 8ABF8D998E819020906D91E3963B96D59CE565CF7C078DB393C35B585C0A5352 62D9731D50275B975F9E60B0616B68D56DD9742E7A2E7D427D9C7E31816B0000 F1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008E2A8E35937E94184F5057505DE65EA7632B7F6A4E3B4F4F4F8F505A59DD 80C4546A546855FE594F5B995DDE5EDA665D673167F1682A6CE86D326E4A6F8D 70B773E075877C4C7D027D2C7DA2821F86DB8A3B8A858D708E8A8F339031914E 9152944499D07AF97CA54FCA510151C657C85BEF5CFB66596A3D6D5A6E966FEC 710C756F7AE388229021907596CB99FF83014E2D4EF2884691CD537D6ADB696B 6C41847A589E618E66FE62EF70DD751175C77E5284B88B498D084E4B53EA0000 F2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000054AB573057405FD763016307646F652F65E8667A679D67B36B626C606C9A 6F2C77E57825794979577D1980A2810281F3829D82B787188A8CF9FC8D048DBE 907276F47A197A377E548077550755D45875632F64226649664B686D699B6B84 6D256EB173CD746874A1755B75B976E1771E778B79E67E097E1D81FB852F8897 8A3A8CD18EEB8FB0903293AD9663967397074F8453F159EA5AC95E19684E74C6 75BE79E97A9281A386ED8CEA8DCC8FED659F6715F9FD57F76F577DDD8F2F0000 F3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000093F696C65FB561F26F844E144F98501F53C955DF5D6F5DEE6B216B6478CB 7B9AF9FE8E498ECA906E6349643E77407A84932F947F9F6A64B06FAF71E674A8 74DA7AC47C127E827CB27E988B9A8D0A947D9910994C52395BDF64E6672D7D2E 50ED53C358796158615961FA65AC7AD98B928B9650095021527555315A3C5EE0 5F706134655E660C663666A269CD6EC46F32731676217A938139825983D684BC 50B557F05BC05BE85F6963A178267DB583DC852191C791F5518A67F57B560000 F4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008CAC51C459BB60BD8655501CF9FF52545C3A617D621A62D364F265A56ECC 7620810A8E60965F96BB4EDF5343559859295DDD64C56CC96DFA73947A7F821B 85A68CE48E10907791E795E1962197C651F854F255865FB964A46F887DB48F1F 8F4D943550C95C166CBE6DFB751B77BB7C3D7C648A798AC2581E59BE5E166377 7252758A776B8ADC8CBC8F125EF366746DF8807D83C18ACB97519BD6FA005243 66FF6D956EEF7DE08AE6902E905E9AD4521D527F54E86194628462DB68A20000 F5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006912695A6A3570927126785D7901790E79D27A0D8096827882D583498549 8C828D859162918B91AE4FC356D171ED77D7870089F85BF85FD6675190A853E2 585A5BF560A4618164607E3D80708525928364AE50AC5D146700589C62BD63A8 690E69786A1E6E6B76BA79CB82BB84298ACF8DA88FFD9112914B919C93109318 939A96DB9A369C0D4E11755C795D7AFA7B517BC97E2E84C48E598E748EF89010 6625693F744351FA672E9EDC51455FE06C9687F2885D887760B481B584030000 F6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008D0553D6543956345A365C31708A7FE0805A810681ED8DA391899A5F9DF2 50744EC453A060FB6E2C5C644F88502455E45CD95E5F606568946CBB6DC471BE 75D475F476617A1A7A497DC77DFB7F6E81F486A98F1C96C999B39F52524752C5 98ED89AA4E0367D26F064FB55BE267956C886D78741B782791DD937C87C479E4 7A315FEB4ED654A4553E58AE59A560F0625362D6673669558235964099B199DD 502C53535544577CFA016258FA0264E2666B67DD6FC16FEF742274388A170000 F7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000094385451560657665F48619A6B4E705870AD7DBB8A95596A812B63A27708 803D8CAA5854642D69BB5B955E116E6FFA038569514C53F0592A6020614B6B86 6C706CF07B1E80CE82D48DC690B098B1FA0464C76FA464916504514E5410571F 8A0E615F6876FA0575DB7B527D71901A580669CC817F892A9000983950785957 59AC6295900F9B2A615D727995D657615A465DF4628A64AD64FA67776CE26D3E 722C743678347F7782AD8DDB981752245742677F724874E38CA98FA692110000 F8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000962A516B53ED634C4F695504609665576C9B6D7F724C72FD7A1789878C9D 5F6D6F8E70F981A8610E4FBF504F624172477BC77DE87FE9904D97AD9A198CB6 576A5E7367B0840D8A5554205B165E635EE25F0A658380BA853D9589965B4F48 5305530D530F548654FA57035E036016629B62B16355FA066CE16D6675B17832 80DE812F82DE846184B2888D8912900B92EA98FD9B915E4566B466DD70117206 FA074FF5527D5F6A615367536A196F0274E2796888688C7998C798C49A430000 F9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000054C17A1F69538AF78C4A98A899AE5F7C62AB75B276AE88AB907F96425339 5F3C5FC56CCC73CC7562758B7B4682FE999D4E4F903C4E0B4F5553A6590F5EC8 66306CB37455837787668CC09050971E9C1558D15B7886508B149DB45BD26068 608D65F16C576F226FA3701A7F557FF095919592965097D352728F4451FD542B 54B85563558A6ABB6DB57DD88266929C96779E79540854C876D286E495A495D4 965C4EA24F0959EE5AE65DF760526297676D68416C866E2F7F38809B822A0000 FA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FA08FA0998054EA5505554B35793595A5B695BB361C869776D77702387F9 89E38A728AE7908299ED9AB852BE683850165E78674F8347884C4EAB541156AE 73E6911597FF9909995799995653589F865B8A3161B26AF6737B8ED26B4796AA 9A57595572008D6B97694FD45CF45F2661F8665B6CEB70AB738473B973FE7729 774D7D437D627E2382378852FA0A8CE29249986F5B517A74884098015ACC4FE0 5354593E5CFD633E6D7972F98105810783A292CF98304EA851445211578B0000 FB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F626CC26ECE7005705070AF719273E97469834A87A28861900890A293A3 99A8516E5F5760E0616766B385598E4A91AF978B4E4E4E92547C58D558FA597D 5CB55F2762366248660A66676BEB6D696DCF6E566EF86F946FE06FE9705D72D0 7425745A74E07693795C7CCA7E1E80E182A6846B84BF864E865F87748B778C6A 93AC9800986560D1621691775A5A660F6DF76E3E743F9B425FFD60DA7B0F54C4 5F186C5E6CD36D2A70D87D0586798A0C9D3B5316548C5B056A3A706B75750000 FC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000798D79BE82B183EF8A718B418CA89774FA0B64F4652B78BA78BB7A6B4E38 559A59505BA65E7B60A363DB6B61666568536E19716574B07D0890849A699C25 6D3B6ED1733E8C4195CA51F05E4C5FA8604D60F66130614C6643664469A56CC1 6E5F6EC96F62714C749C76877BC17C27835287579051968D9EC3532F56DE5EFB 5F8A6062609461F7666667036A9C6DEE6FAE7070736A7E6A81BE833486D48AA8 8CC4528373725B966A6B940454EE56865B5D6548658566C9689F6D8D6DC60000 FD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000723B80B491759A4D4FAF5019539A540E543C558955C55E3F5F8C673D7166 73DD900552DB52F3586458CE7104718F71FB85B08A13668885A855A76684714A 8431534955996BC15F595FBD63EE668971478AF18F1D9EBE4F11643A70CB7566 866760648B4E9DF8514751F653086D3680F89ED166156B23709875D554035C79 7D078A166B206B3D6B46543860706D3D7FD5820850D651DE559C566B56CD59EC 5B095E0C619961986231665E66E6719971B971BA72A779A77A007FB28A700000 tcl8.6.5/library/encoding/macCroatian.enc0000644000175000017500000000211011555560473017724 0ustar sergeisergei# Encoding file: macCroatian, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C400C500C700C900D100D600DC00E100E000E200E400E300E500E700E900E8 00EA00EB00ED00EC00EE00EF00F100F300F200F400F600F500FA00F900FB00FC 202000B000A200A300A7202200B600DF00AE0160212200B400A82260017D00D8 221E00B122642265220600B522022211220F0161222B00AA00BA03A9017E00F8 00BF00A100AC221A01922248010600AB010C202600A000C000C300D501520153 01102014201C201D2018201900F725CAF8FF00A9204420AC2039203A00C600BB 201300B7201A201E203000C2010700C1010D00C800CD00CE00CF00CC00D300D4 011100D200DA00DB00D9013102C602DC00AF03C000CB02DA00B800CA00E602C7 tcl8.6.5/library/encoding/koi8-u.enc0000644000175000017500000000210311555560473016621 0ustar sergeisergei# Encoding file: koi8-u, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 25002502250C251025142518251C2524252C2534253C258025842588258C2590 259125922593232025A02219221A22482264226500A0232100B000B200B700F7 25502551255204510454255404560457255725582559255A255B0491255D255E 255F25602561040104032563040604072566256725682569256A0490256C00A9 044E0430043104460434043504440433044504380439043A043B043C043D043E 043F044F044004410442044304360432044C044B04370448044D04490447044A 042E0410041104260414041504240413042504180419041A041B041C041D041E 041F042F042004210422042304160412042C042B04170428042D04290427042A tcl8.6.5/library/encoding/cp862.enc0000644000175000017500000000210211555560473016346 0ustar sergeisergei# Encoding file: cp862, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 05D005D105D205D305D405D505D605D705D805D905DA05DB05DC05DD05DE05DF 05E005E105E205E305E405E505E605E705E805E905EA00A200A300A520A70192 00E100ED00F300FA00F100D100AA00BA00BF231000AC00BD00BC00A100AB00BB 259125922593250225242561256225562555256325512557255D255C255B2510 25142534252C251C2500253C255E255F255A25542569256625602550256C2567 2568256425652559255825522553256B256A2518250C25882584258C25902580 03B100DF039303C003A303C300B503C403A6039803A903B4221E03C603B52229 226100B1226522642320232100F7224800B0221900B7221A207F00B225A000A0 tcl8.6.5/library/encoding/gb12345.enc0000644000175000017500000025113311555560473016505 0ustar sergeisergei# Encoding file: gb12345, double-byte D 233F 0 83 21 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030003001300230FB02C902C700A8300330052015FF5E2225202620182019 201C201D3014301530083009300A300B300C300D300E300F3016301730103011 00B100D700F72236222722282211220F222A222922082237221A22A522252220 23122299222B222E2261224C2248223D221D2260226E226F22642265221E2235 22342642264000B0203220332103FF0400A4FFE0FFE1203000A7211626062605 25CB25CF25CE25C725C625A125A025B325B2203B219221902191219330130000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 22 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000024882489248A248B248C248D248E248F2490249124922493249424952496 249724982499249A249B247424752476247724782479247A247B247C247D247E 247F248024812482248324842485248624872460246124622463246424652466 2467246824690000000032203221322232233224322532263227322832290000 00002160216121622163216421652166216721682169216A216B000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 23 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF01FF02FF03FFE5FF05FF06FF07FF08FF09FF0AFF0BFF0CFF0DFF0EFF0F FF10FF11FF12FF13FF14FF15FF16FF17FF18FF19FF1AFF1BFF1CFF1DFF1EFF1F FF20FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2F FF30FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3AFF3BFF3CFF3DFF3EFF3F FF40FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5AFF5BFF5CFF5DFFE30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 24 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000304130423043304430453046304730483049304A304B304C304D304E304F 3050305130523053305430553056305730583059305A305B305C305D305E305F 3060306130623063306430653066306730683069306A306B306C306D306E306F 3070307130723073307430753076307730783079307A307B307C307D307E307F 3080308130823083308430853086308730883089308A308B308C308D308E308F 3090309130923093000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 25 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF 30B030B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF 30C030C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF 30D030D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 26 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000039103920393039403950396039703980399039A039B039C039D039E039F 03A003A103A303A403A503A603A703A803A90000000000000000000000000000 000003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C303C403C503C603C703C803C90000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 27 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000004100411041204130414041504010416041704180419041A041B041C041D 041E041F0420042104220423042404250426042704280429042A042B042C042D 042E042F00000000000000000000000000000000000000000000000000000000 000004300431043204330434043504510436043704380439043A043B043C043D 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 28 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000010100E101CE00E0011300E9011B00E8012B00ED01D000EC014D00F301D2 00F2016B00FA01D400F901D601D801DA01DC00FC00EA00000000000000000000 0000000000000000000031053106310731083109310A310B310C310D310E310F 3110311131123113311431153116311731183119311A311B311C311D311E311F 3120312131223123312431253126312731283129000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 29 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000002500250125022503250425052506250725082509250A250B 250C250D250E250F2510251125122513251425152516251725182519251A251B 251C251D251E251F2520252125222523252425252526252725282529252A252B 252C252D252E252F2530253125322533253425352536253725382539253A253B 253C253D253E253F2540254125422543254425452546254725482549254A254B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 30 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000554A963F57C3632854CE550954C0769A764C85F977EE827E7919611B9698 978D6C285B894FFA630966975CB880FA68489AAF660276CE51F9655671AC7FF1 895650B2596561CA6FB382AD634C625253ED54277B06516B75A45DF462D48DCB 9776628A801958E997387F777238767D67CF767E64FA4F70655762DC7A176591 73ED642C6273822C9812677F7248626E62CC4F3474E3534A8FA67D4690A65E6B 6886699C81807D8168D278C5868C938A508D8B1782DE80DE5305891252650000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 31 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000858496F94FDD582198FD5BF662B1583166B48C799B917206676F789160B2 535153178F2980CC8C9D92C7500D72FD5099618A711988AB595482EF672C7B28 5D297DB3752D6CF58E668FF8903C9F3B6BD491197B465F7C78A784D6853D7562 65836BD65E635E8775F99589655D5F0A5FC58F9F58C181C2907F965B97AD908A 7DE88CB662414FBF8B8A535E8FA88FAF8FAE904D6A195F6A819888689C49618B 522B765F5F6C658C70156FF18CD364EF517551B067C44E1979C9990570B30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 32 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075C55E7673BB83E064AD64A592626CE2535A52C3640F92517B944F2F5E1B 82368116818A6E246CCA99C16355535C54FA88DC57E04E0D5E036B657C3F90E8 601664E6731C88C16750624D8CA1776C8E2991C75F6983DC8521991053C38836 6B98615A615871E684BC825950096EC485CF64CD7CD969FD66F9834953A07B56 5074518C6E2C5C648E6D63D253C9832C833667E578B4643D5BDF5C945DEE8A6B 62C667F48C7A6519647B87EC995E8B927E8F93DF752395E1986B660C73160000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 33 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000583456175E389577511F81785EE0655E66A2553150218D8562849214671D 56326F6E5DE2543570928ECA626F64A463A35FB96F8890F481E38FB058756668 5FF16C8996738D81896F64917A3157CE6A59621054484E587A0B61F26F848AA0 627F901E9A0179E4540375F4630153196C6090725F1B99B3803B9F524F885C3A 8D647FC565A571BE5145885D87F25D075BF562BD916C75878E8A7A2061017C4C 4EC77DA27785919C81ED521D51FA6A7153A88E8792E496DB6EC19664695A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 34 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000790E513277D7641089F8865563E35DDD7A7F693D50B3823955984E327621 7A975E625E8A95D652755439708A6376931857826625693F918755076DF37D14 882262337DBD75B5832878C196CC8FAD614874F78A5E6B64523A8CDC6B218070 847156F153065F9E53E251D17C97918B7C074FC38EA57BE17AC464675D1450AC 810676017CB96DEC7FE067515B585BF878CB64AE641363AA632B932F642D9054 7B5476296253592754466B7950A362345E366B864EE38CB8888B5F85902E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 35 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006020803D64D44E3955AE913264A381BD65E66C2E4F46619A6DE18A955F48 86CB757664CB9EE885696A94520064178E4850125CF679B15C0E52307A3B60BC 905376D75FB75F9776848E6C71C8767B7B4977AA51F3912758244F4E6EF48FEA 65757B1B72C46ECC7FDF5AE162B55E95573084827B2C5E1D5F1F905E7DE0985B 63826EC778989EDE5178975B588A96FB4F4375385E9760E659606FB16BBF7889 53FC96D551CB52016389540A91E38ABF8DCC7239789F87768FED8ADC758A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 36 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E0176EF53EE91D898029F0E93205B9A8A024E22677151AC846361C252D5 68DF4F97606B51CD6D1E515C62969B2596618C46901775D890FD77636BD272A2 73688B80583577798CED675C934D809A5EA66E2159927AEF77ED935B6BB565B7 7DDE58065151968A5C0D58A956788E726566981356E4920D76FE9041638754C6 591A596A579B8EB267358DFA8235524160F058AE86FE5CE89D5D4FC4984D8A1B 5A2560E15384627C904F910299136069800C51528033723E990C6D314E8C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 37 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008CB3767C7F707B4F4F104E4F95A56CD573D085E95E06756A7FFB6A0A792C 91E97E4151E1716953CD8FD47BC48CA972AF98EF6CDB574A82B365B980AA623F 963259A84EFF8A2A7D21653E83F2975E556198DB80A5532A8AB9542080BA5EE2 6CB88CBB82AC915A54296C1B52067D1B58B3711A6C7E7C89596E4EFD5FFF61A4 7CDE8C505C01695387025CF092D298A8760B70FD902299AE7E2B8AF759499CF3 4F5B5426592B6577819A5B75627662C28F3B5E456C1F7B264F0F4FD8670D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 38 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D6E6DAA798F88B15F17752B64AB8F144FEF91DC65A7812F81515E9C8150 8D74526F89868CE65FA950854ED8961C723681798CA05BCC8A0396445A667E1B 54905676560E8A7265396982922384CB6E895E797518674667D17AFF809D8D95 611F79C665628D1B5CA1525B92FC7F38809B7DB15D176E2F67607BD9768B9AD8 818F7F947CD5641E93AC7A3F544A54E56B4C64F162089D3F80F3759952729769 845B683C86E495A39694927B500B54047D6668398DDF801566F45E9A7FB90000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 39 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000057C2803F68975DE5653B529F606D9F944F9B8EAC516C5BAB5F13978F6C5E 62F18CA25171920E52FE6E9D82DF72D757A269CB8CFC591F8F9C83C754957B8D 4F306CBD5B6459D19F1353E488319AA88C3780A16545986756FA96C7522E74DC 526E5BE1630289024E5662D0602A68FA95DC5B9851A089C07BA199287F506163 704C8CAB51495EE3901B7470898F572D78456B789F9C95A88ECC9B3C8A6D7678 68426AC38DEA8CB4528A8F256EDA68CD934B90ED570B679C88F9904E54C80000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009AB85B696D776C264EA55BB399ED916361A890AF97D3542B6DB55BD251FD 558A7F557FF064BC634D65F161BE608D710A6C576F22592F676D822A58D5568E 8C6A6BEB90DD597D8017865F6D695475559D837783CF683879BE548C4F555408 76D28C8995A16CB36DB88D6B89109DB48CC0563F9ED175D55F8872E0606854FC 4EA86A2A886160528F5F54C470D886799D3B6D2A5B8F5F187D0555894FAF7334 543C539A50195F8C547C4E4E5FFD745A58FA846B80E1877472D07CCA6E560000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F27864E552C8B774E926EEC623782B1562983EF733E6ED1756B52835316 8A7169D05F8A61F76DEE58DE6B6174B0685390847DE963DB60A3559A76138C62 71656E195BA65E7B8352614C9EC478FA87577C27768751F060F6714C66435E4C 604D8B0A707063EE8F1D5FBD606286D456DE6BC160946167534960E066668CC4 7A62670371F4532F8AF18AA87E6A8477660F5A5A9B426E3E6DF78C416D3B4F19 706B7372621660D1970D8CA8798D64CA573E57FA6A5F75787A3D7A4D7B950000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000808C99518FF96FC08B4F9DC459EC7E3E7DDD5409697568D88F2F7C4D96C6 53CA602575BE6C7253735AC97D1A64E05E7E810A5DF1858A628051805B634F0E 796D529160B86FDF5BC45BC28A088A1865E25FCC969B59937E7C7D00560967B7 593E4F735BB652A083A298308CC87532924050477A3C50F967B699D55AC16BB2 76E358055C167B8B9593714E517C80A9827159787DD87E6D6AA267EC78B19E7C 63C064BF7C215109526A51CF85A66ABB94528E108CE4898B93757BAD4EF60000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000050658266528D991E6F386FFA6F975EFA50F559DC5C076F3F6C5F75868523 69F3596C8B1B532091AC964D854969127901712681A04EA490CA6F869A555B0C 56BC652A927877EF50E5811A72E189D299037E737D5E527F655991758F4E8F03 53EB7A9663ED63A5768679F88857968E622A52AB7BC0685467706377776B7AED 6F547D5089E359D0621285C982A5754C501F4ECB75A58AA15C4A5DFE7B4B65A4 91D14ECA6D25895F7DCA932650C58B3990329773664979818FD171FC6D780000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000076E152C1834651628396775B66769BE84EAC9A5A7CBE7CB37D934E958B66 666F9838975C5883656C93E15F9175D997567ADF7AF651C870AF7A9863EA7A76 7CFE739697ED4E4570784E5D915253A96551820A81FC8205548E5C31759A97A0 62D872D975BD5C4599D283CA5C40548077E982096CAE805A62D264DA5DE85177 8DDD8E1E92F84FF153E561FC70AC528763509D515A1F5026773753777D796485 652B628963985014723589BA51B38A237D76574783CC921E8ECD541B5CFB0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004FCA7AE36D5A90E199FF55805496536154AF958B63E9697751F16168520A 582A52D8574E780D770B5EB761777CE0625B62974EA27095800362F770E49760 577782DB67EF68F578D5984679D16BBB54B353EF6E34514B523B5BA28AB280AF 554358BE61C75751542D7A7A60505B5463A7647353E362635BC767AF54ED7A9F 82E691775EAB89328A8757AE630E8DE880EF584A7B7751085FEB5BEC6B3E5321 7B5072C268467926773666E051B5866776D45DCB7ABA8475594E9B4150800000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 40 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000994B61276F7057646606634656F062EC64F45ED395CA578362C95587881F 81D88FA35566840A4F868CF485CD5A6A6B0465147C4395CC862D703E8B95652C 89BD61F67E9C721B6FEB7405699472FC5ECA90CE67176D6A648852DE72628001 4F6C59E5916A70D96F8752D26A0296F79433857E78CA7D2F512158D864C2808B 985E6CEA68F1695E51B7539868A872819ECE7C6C72F896E270557406674E88CF 9BC979AE83898354540F68179E9753B252F5792B6B77522950884F8B4FD00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 41 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075E27ACB7C92701D96B8529B748354E95006806F84EE9023942E5EC96190 6F237C3E658281C993C8620071497DF47CE751C968817CB1826F51698F1B91CF 667E4EAE8AD264A9804A50DA764271CE5BE5907C6F664E86648294105ED66599 521788C270C852A373757433679778F7971681E891309C576DCB51DB8CC3541D 62CE73B283F196F69F6192344F367F9A51CC974896755DBA981853E64EE46E9C 740969B4786B993E7559528976246D4167F3516D9F8D807E56A87C607ABF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 42 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000968658DF650F96B46A135A41645F7C0D6F0F964B860676E798715EEC7210 64C46EF7865C9B6F9E93788C97328DEF8CC29E7F6F5E798493329678622E9A62 541592C14FA365C55C655C627E37616E6C2F5F8B73876FFE7DD15DD265235B7F 706453754E8263A0756563848F2A502B4F966DEA7DB88AD6863F87BA7F85908F 947C7C6E9A3E88F8843D6D1B99F17D615ABD9EBB746A78BC879E99AC99E1561B 55CE57CB8CB79EA58CE390818109779E9945883B6EFF851366FC61626F2B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 43 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008B3E8292832B76F26C135FD983BD732B830593286BDB77DB925A536F8302 51925E3D8C8C8CBF9EBD73AB679A68859176970971646CA177095A9293826BCF 7F8E66275BD059B95A9A958060B65011840C84996AAC76DF9333731B59225B5F 772F919A97617CDC8FF78B0E5F4C7C7379D889936CCC871C5BC65E4268C97720 7DBF5195514D52C95A297DEC976282D763CF778485D079D26E3A5EDF59998511 6EC56C1162BF76BF654F61AB95A9660E879F9CF49298540D547D8B2C64780000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 44 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000647986116A21819C78E864699B5462B9672B83AB58A89ED86CAB6F205BDE 964C8B00725F67D062C77261755D59C66BCD589366AE5E5552DF6155672876EE 776672677A4662FF54EA5450920990A35A1C7D0D6C164E435976801059485357 753796E356CA6493816660F19B276DD65462991251855AE980FD59AE9713502A 6CE55C3C64EC4F60533F81A990066EBA852B62C85E7478BE6506637B5FF55A18 91C09CE55C3F634F80765B7D5699947793B36D8560A86AB8737051DD5BE70000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 45 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000064F06FD8725B626D92157D1081BF6FC38FB25F04597452AA601259736696 86507627632A61E67CEF8AFE54E66B509DD76BC685D5561450766F1A556A8DB4 722C5E156015743662CD6392724C5F986E436D3E65006F5876E478D076FC7554 522453DB4E539F9065C1802A80D6629B5486522870AE888D8DD16CE1547880DA 57F988F48CE0966A914D4F696C9B567476C6783062A870F96F8E5F6D84EC68DA 787C7BF781A8670B9D6C636778B0576F78129739627962AB528874356BD70000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 46 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005564813E75B276AE533975DE50FB5C418B6C7BC7504F72479A1998C46F02 74E27968648777A562FC983B8CA754C180584E52576A860B840D5E73619174F6 8A555C4F57616F5198175A4678349B448FEB7C95525664B292EA50D583868461 83E984B257D46A385703666E6D668B5C66DD7011671F6B3A68F2621A59BB4E03 51C46F0667D26C8F517668CB59476B6775665D0E81CD9F4A65D7794879419A0E 8D778C484E5E4F0155535951780C56686C238FC468C46C7D6CE38A1663900000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 47 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000060706D3D727D626691FA925B534390777C3D4EDF8B194E7E9ED493229257 524D6F5B90636DFA8B7458795D4C6B206B4969CD55C681547F8C58BB85945F3A 64366A47936C657260846A4B77A755AC50D15DE7979864AC7FF95CED4FCF7AC5 520783044E14602F7ACA6B3D4FB589AA79E6743452E482B964D279BD5BE26C81 97528F156C2B50BE537F6E0564CE66746C3060C598038ACB617674CA7AAE79CB 4E1890B174036C4256DA914B6CC58DA8534086C666F28EC05C489A456E200000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000053D65A369F728DA353BB570898746B0A919B6CC9516875CA62F372AC5238 52F87F3A7094763853749D7269B778BA96C088D97FA4713671C3518967D374E4 58E4651856B78B93995264FE7E5E60F971B158EC4EC14EBA5FCD97CC4EFB8A8D 5203598A7D0962544ECD65E5620E833884C969AE878D71946EB65BB97D685197 63C967D480898339881551125B7A59828FB14E736C5D516589258EDF962E854A 745E92ED958F6F6482E55F316492705185A9816E9C13585E8CFD4E0953C10000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 49 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000050986563685155D355AA64149A3763835AC2745F82726F8068EE50E7838E 78026BBA52396C997D1750BB5565715E7BE966EC73CA82EB67495C715220717D 886B9583965D64C58D0D81B355846C5562477E55589250B755468CDE664C4E0A 5C1A88F368A2634E7A0D71D2828D52FA97F65C1154E890B57D3959628CD286C7 820C63688D66651D5C0461FE6D89793E8A2D78377533547B4F388EAB6DF15A20 7D33795E6C885BE95B38751A814E614E6EF28072751F7525727253477E690000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000770176DB526952DD80565E2B5931734565BD6FD58A695C388671534177F3 62FE66424EC098DF87555BE68B5853F277E24F7F5C4E99DB59CB5F0F793A58EB 4E1667FF4E8B62ED8A93901D52E2662F55DC566C90694ED54F8D91CB98FE6C0F 5E0260435BA489968A666536624B99965B8858FD6388552E53D776267378852C 6A1E68B36B8A62928F3853D482126DD1758F66F88D165B70719F85AF669166D9 7F7287009ECD9F205C6C88538FF06A39675F620D7AEA58855EB665786F310000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000060555237800D6454887075295E25681362F4971C96D9723D8AB06C347761 7A0E542E77AC9806821C8AAC78A96714720D65AF64955636601D79C153F87D72 6B7B80865BFA55E356DB4F3A4F3C98FC5DF39B068073616B980C90015B8B8A1F 8AA6641C825864FB55FD860791654FD77D20901F7C9F50F358516EAF5BBF8A34 80859178849C7B9796D6968B96A87D8F9AD3788E6B727A57904296A7795F5B6B 640D7B0B84D168AD55067E2E74637D2293966240584C4ED65B83597958540000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000737A64BB8E4B8E0F80CE82D462AC81FA6CF0915E592A614B6C70574D6524 8CAA7671705858C76A8075F06F6D8B5A8AC757666BEF889278B363A2560670AD 6E6F5858642A580268E0819B55107CD650188EBA6DCC8D9F71D9638F6FE46ED4 7E278404684390036DD896768A0E5957727985E49A3075BC8B0468AF52548E22 92BB63D0984C8E44557C9AD466FF568F60D56D9552435C4959296DFB586B7530 751C606C821481466311689D8FE2773A8DF38CBC94355E165EF3807D70F40000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006C405EF7505C4EAD5EAD633A8247901A6850916E77B3540C92855F647AE5 687663457B527D7175DB50776295982D900F51F879C37A8157165F9290145857 5C60571F541051546E4D571863A8983D817F8715892A9000541E5C6F81C062D6 625881319D15964099B199DD6A6259A562D3553E631654C786D97AAA5A0374E6 896A6B6A59168C4C5F4E706373A998114E3870F75B8C7897633D665A769660CB 5B9B5A49842C81556C6A738B4EA167897DB25F8065FA671B5FD859845A010000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005DCD5FAE537197CB90556845570D552F60DF72326FF07DAD8466840E59D4 504950DE5C3E7DEF672A851A5473754F80C355829B4F4F4D6E2D8B025C096170 885B761F6E29868A6587805E7D0B543B7A697D0A554F55E17FC174EE64BE8778 6E267AA9621165A1536763E16C835DEB55DA93A270CF6C618AA35C4B7121856A 68A7543E54346BCB6B664E9463425348821E4F0D4FAE5862620A972766647269 52FF52D9609F8AA4661471996790897F785277FD6670563B5438932B72A70000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A00606F5E0C6089819D591560DC718470EF6EAA6C5072806A8489725E2D 7FD25AB3559C92916D177CFB969962327D30778E87665323971E8F4466875CFD 4FE072F94E0B53A6590F56876380934151484ED99BAE7E9654B88CE2929C8237 95916D8E5F265ACC986F96AA73FE737B7E23817A99217FA161B2967796507DAB 76F853A2947299997BB189446E5891097FD479658A7360F397FF4EAB98055DF7 6A6150CF54118C61856D785D9704524A54EE56C292B76D885BB56DC666C90000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 50 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C0F5B5D68218096562F7B11654869544E9B6B47874E978B5354633E643A 90AA659C81058AE75BEB68B0537887F961C86CC470098B1D5C5185AA82AF92C5 6B238F9B65B05FFB5FC34FE191C1661F8165732960FA82085211578B5F6290A2 884C91925E78674F602759D3514451F680F853086C7996C4718A4F114FEE7F9E 673D55C592B979C088967D89589F620C9700865A561898085F908A3184C49157 53D965ED5E8F755C60647D6E5A7F7DD27E8C8ED255A75BA361F865CB73840000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 51 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009078766C77297D629774859B5B787A7496EA884052DB718F5FAA65EC8A62 5C0B99B45DE16B896C5B8A138A0A905C8FC558D362BC9D099D2854404E2B82BD 7259869C5D1688596DAF96C5555E4E9E8A1D710954BD95B970DF6DF99E7D56B4 781487125CA95EF68A00985495BB708E6CBF594463A9773C884D6F1482775830 71D553AD786F96C155015F6671305BB48AFA9A576B83592E9D2679E7694A63DA 4F6F760D7F8A6D0B967D6C274EF07662990A6A236F3E90808170599674760000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 52 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006447582F90657A918B2159DA54AC820085E5898180006930564E8036723A 91CE51B64E5F98016396696D844966F3814B591C6DB24E0058F991AB63D692A5 4F9D4F0A886398245937907A79FB510080F075916C825B9C59E85F5D690587FB 501A5DF24E5977E34EE585DD6291661390915C7951045F7981C69038808475AB 4EA688D4610F6BC561B67FA976CA6EA28A638B708ABC8B6F5F027FFC7FCC7E79 8335852D56E06BB797F3967059FB541F92806DEB5BC598F25C395F1596B10000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 53 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000537082F16AFB5B309DF961C97E93746987A271DF719288058FCE8D0F76C8 5F717A4E786C662055B264C150AD81C376705EB896CD8E3486F9548F6CF36D8C 6C38607F52C775285E7D512A60A061825C24753190F5923E73366CB96E389149 670953CB53F34F5191C98A9853C85E7C8FC26DE44E8E76C26986865E611A8F3F 99184FDE903E9B5A61096E1D6F0196854E885A3196E882075DBC79B95B878A9E 7FBD738957DF828B9B315401904755BB5CEA5FA161086B32734480B28B7D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D745BD388D598108C6B99AD9D1B6DF551A4514357A38881539F63F48F45 571254E15713733F6E907DE3906082D198586028966266F07D048D8A8E8D9470 5CB37CA4670860A695B2801896F29116530096955141904B85F49196668897F5 5B55531D783896DC683D54C9707E5BB08F09518D572854B1652266AB8D0A8D1C 81DF846C906D7CDF947F85FB68D765E96FA186A48E81566A902076827AC871E5 8CAC64C752476FA48CCA600E589E618E66FE8D08624E55B36E23672D8ECB0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 55 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000935895987728680569A8548B4E4D70B88A5064589F4B5B857A8450B55BE8 77BB6C088A797C986CBE76DE65AC8F3E5D845C55863868E7536062307AD96E5B 7DBB6A1F7AE05F706F335F35638C6F3267564E085E338CEC4ED781397634969C 62DB662D627E6CBC8D9971677F695146808753EC906E629854F287C48F4D8005 937A851790196D5973CD659F771F7504782781FB8C9E91DD5075679575B98A3A 9707632F93AE966384B86399775C5F817319722D6014657462EF6B63653F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 56 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005E407665912D8B49829D679D652F5431871877E580A281026C414E4B7E54 807776F4690D6B9657F7503C4F84574063076B628DBE887965E87D195FD7646F 64F281F381F47F6E5E5F5CD95236667A79E97A1A8CEA709975D46EEF6CBB7A92 4E2D76C55FE0941888777D427A2E816B91CD4EF28846821F54685DDE6D328B05 7CA58EF880985E1A549276BA5B99665D9A5F73E0682A86DB6731732A8AF88A85 90107AF971ED716E62C477DA56D14E3B845767F152A986C08CAF94447BC90000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 57 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F4F6CE8795D99D06293722A62FD5C0878DA8F4964B08CFA7BC66A01838A 88DD599D649E58EF72C0690E93108FFD8D05589C7DB48AC46E96634962D95353 684C74228301914C55447740707C6FC1517954A88CC759FF6ECB6DC45B5C7D2B 4ED47C7D6ED35B5081EA6F2C5B579B0368D58E2A5B977D9C7E3D7E3191128D70 594F63CD79DF8DB3535265CF79568A5B963B7D44947D7E825634918967007F6A 5C0A907566285DE64F5067DE505A4F5C57505EA7000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 58 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E8D4E0C51404E105EFF53454E154E984E1E9B325B6C56694E2879BA4E3F 53154E47592D723B536E6C1056DF80E499976BD3777E9F174E364E9F9F104E5C 4E694E9382885B5B55C7560F4EC45399539D53B453A553AE97688D0B531A53F5 532D5331533E8CFE5366536352025208520E52445233528C5274524C525E5261 525C84AF527D528252815290529351827F544EBB4EC34EC94EC24EE84EE14EEB 4EDE50B44EF34F224F644EF5500050964F094F474F5E4F6765384F5A4F5D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 59 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F5F4F574F324F3D4F764F744F914F894F834F8F4F7E4F7B51154F7C5102 4F945114513C51374FC54FDA4FE34FDC4FD14FDF4FF85029504C4FF3502C500F 502E502D4FFE501C500C5025502850E8504350555048504E506C50C2513B5110 513A50BA50D6510650ED50EC50E650EE5107510B4EDD6C3D4F5850C94FCE9FA0 6C467CF4516E5DFD9ECC999856C5591452F9530D8A0753109CEC591951554EA0 51564EB3886E88A4893B81E088D279805B3488037FB851AB51B151BD51BC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000051C7519651A251A58A018A108A0C8A158B338A4E8A258A418A368A468A54 8A588A528A868A848A7F8A708A7C8A758A6C8A6E8ACD8AE28A618A9A8AA58A91 8A928ACF8AD18AC98ADB8AD78AC28AB68AF68AEB8B148B018AE48AED8AFC8AF3 8AE68AEE8ADE8B288B9C8B168B1A8B108B2B8B2D8B568B598B4E8B9E8B6B8B96 5369537A961D962296219631962A963D963C964296589654965F9689966C9672 96749688968D969796B09097909B913A9099911490A190B490B390B691340000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000090B890B090DF90C590BE913690C490C79106914890E290DC90D790DB90EB 90EF90FE91049122911E91239131912F91399143914682BB595052F152AC52AD 52BE54FF52D052D652F053DF71EE77CD5EF451F551FC9B2F53B65F01755A5DF0 574C580A57A1587E58BC58C558D15729572C572A573358D9572E572F58E2573B 5742576958E0576B58DA577C577B5768576D5776577357E157A4578C584F57CF 57A75816579357A057D55852581D586457D257B857F457EF57F857E457DD0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000580B580D57FD57ED5800581E5819584458205865586C58815889589A5880 99A89F1961FF8279827D827F828F828A82A88284828E8291858C829982AB8553 82BE82B085F682CA82E3829882B782AE83A7840784EF82A982B482A182AA829F 82C482E782A482E1830982F782E48622830782DC82F482D282D8830C82FB82D3 8526831A8306584B716282E082D5831C8351855884FD83088392833C83348331 839B854E832F834F8347834385888340831785BA832D833A833372966ECE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008541831B85CE855284C08452846483B083788494843583A083AA8393839C 8385837C859F83A9837D8555837B8398839E83A89DAF849383C1840183E583D8 58078418840B83DD83FD83D6841C84388411840683D483DF840F840383F883F9 83EA83C583C07E0883F083E1845C8451845A8459847385468488847A85628478 843C844684698476851E848E8431846D84C184CD84D09A4084BD84D384CA84BF 84BA863A84A184B984B4849793A38577850C750D853884F0861E851F85FA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008556853B84FF84FC8559854885688564855E857A77A285438604857B85A4 85A88587858F857985EA859C858585B985B785B0861A85C185DC85FF86278605 86298616863C5EFE5F08593C596980375955595A5958530F5C225C255C2C5C37 624C636B647662BB62CA62DA62D762EE649F62F66339634B634363AD63F66371 637A638E6451636D63AC638A636963AE645C63F263F863E064B363C463DE63CE 645263C663BE65046441640B641B6420640C64266421645E6516646D64960000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000647A64F764FC6499651B64C064D064D764E464E265096525652E5F0B5FD2 75195F11535F53F1563053E953E853FB541254165406544B563856C8545456A6 54435421550454BC5423543254825494547754715464549A5680548454765466 565D54D054AD54C254B4566054A754A6563555F6547254A3566654BB54BF54CC 567254DA568C54A954AA54A4566554CF54DE561C54E7562E54FD551454F355E9 5523550F55115527552A5616558F55B5554956C055415555553F5550553C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 60 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005537555655755576557755335530555C558B55D2558355B155B955885581 559F557E55D65591557B55DF560D56B35594559955EA55F755C9561F55D156C1 55EC55D455E655DD55C455EF55E555F2566F55CC55CD55E855F555E48F61561E 5608560C560156B6562355FE56005627562D565856395657562C564D56625659 5695564C5654568656645671566B567B567C5685569356AF56D456D756DD56E1 570756EB56F956FF5704570A5709571C5E435E195E145E115E6C5E585E570000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 61 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005E375E445E545E5B5E5E5E615C8C5C7A5C8D5C905D875C885CF45C995C91 5D505C9C5CB55CA25D2C5CAC5CAB5CB15CA35CC15CB75DA75CD25DA05CCB5D22 5D975D0D5D275D265D2E5D245D1E5D065D1B5DB85D3E5D345D3D5D6C5D5B5D6F 5D815D6B5D4B5D4A5D695D745D825D995D9D8C735DB75DD45F735F775F825F87 5F89540E5FA05F995F9C5FA85FAD5FB55FBC88625F6172AD72B072B473777341 72C372C172CE72CD72D272E8736A72E9733B72F472F7730172F3736B72FA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 62 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000072FB731773137380730A731E731D737C732273397325732C733873317350 734D73577360736C736F737E821B592598E75924590298E0993398E9993C98EA 98EB98ED98F4990999114F59991B9937993F994399489949994A994C99625E80 5EE15E8B5E965EA55EA05EB95EB55EBE5EB38CE15ED25ED15EDB5EE85EEA81BA 5FC45FC95FD661FA61AE5FEE616A5FE15FE4613E60B561345FEA5FED5FF86019 60356026601B600F600D6029602B600A61CC6021615F61E860FB613760420000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 63 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000606A60F26096609A6173609D60836092608C609B611C60BB60B160DD60D8 60C660DA60B4612061926115612360F46100610E612B614A617561AC619461A7 61B761D461F55FDD96B39582958695C8958E9594958C95E595AD95AB9B2E95AC 95BE95B69B2995BF95BD95BC95C395CB95D495D095D595DE4E2C723F62156C35 6C546C5C6C4A70436C856C906C946C8C6C686C696C746C766C866F596CD06CD4 6CAD702770186CF16CD76CB26CE06CD66FFC6CEB6CEE6CB16CD36CEF6D870000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 64 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D396D276D0C6D796E5E6D076D046D196D0E6D2B6FAE6D2E6D356D1A700F 6EF86F6F6D336D916D6F6DF66F7F6D5E6D936D946D5C6D606D7C6D636E1A6DC7 6DC56DDE70066DBF6DE06FA06DE66DDD6DD9700B6DAB6E0C6DAE6E2B6E6E6E4E 6E6B6EB26E5F6E866E536E546E326E256E4470676EB16E9870446F2D70056EA5 6EA76EBD6EBB6EB76F776EB46ECF6E8F6EC26E9F6F627020701F6F246F156EF9 6F2F6F3670326F746F2A6F096F296F896F8D6F8C6F786F726F7C6F7A70280000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 65 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006FC96FA76FB96FB66FC26FE16FEE6FDE6FE06FEF701A7023701B70397035 705D705E5B805B845B955B935BA55BB8752F9A2B64345BE45BEE89305BF08E47 8B078FB68FD38FD58FE58FEE8FE490878FE690158FE890059004900B90909011 900D9016902190359036902D902F9044905190529050906890589062905B66B9 9074907D908290889083908B5F505F575F565F585C3B54AB5C505C595B715C63 5C687FBC5F335F295F2D82745F3C9B3B5C6E59815983598D5AF55AD759A30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 66 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000599759CA5B00599E59A459D259B259AF59D759BE5A6D5B0859DD5B4C59E3 59D859F95A0C5A095AA75AFB5A115A235A135A405A675A4A5A555A3C5A625B0B 80EC5AAA5A9B5A775A7A5ABE5AEB5AB25B215B2A5AB85AE05AE35B195AD65AE6 5AD85ADC5B095B175B165B325B375B405C155C1C5B5A5B655B735B515B535B62 99D499DF99D99A369A5B99D199D89A4D9A4A99E29A6A9A0F9A0D9A059A429A2D 9A169A419A2E9A389A439A449A4F9A659A647CF97D067D027D077D087E8A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 67 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007D1C7D157D137D3A7D327D317E107D3C7D407D3F7D5D7D4E7D737D867D83 7D887DBE7DBA7DCB7DD47DC47D9E7DAC7DB97DA37DB07DC77DD97DD77DF97DF2 7E627DE67DF67DF17E0B7DE17E097E1D7E1F7E1E7E2D7E0A7E117E7D7E397E35 7E327E467E457E887E5A7E527E6E7E7E7E707E6F7E985E7A757F5DDB753E9095 738E74A3744B73A2739F73CF73C274CF73B773B373C073C973C873E573D9980A 740A73E973E773DE74BD743F7489742A745B7426742574287430742E742C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 68 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000741B741A7441745C74577455745974A6746D747E749C74D4748074817487 748B749E74A874A9749074A774DA74BA97D997DE97DC674C6753675E674869AA 6AEA6787676A677367986898677568D66A05689F678B6777677C67F06ADB67D8 6AF367E967B06AE867D967B567DA67B367DD680067C367B867E26ADF67C16A89 68326833690F6A48684E6968684469BF6883681D68556A3A68416A9C68406B12 684A6849682968B5688F687468776893686B6B1E696E68FC6ADD69E768F90000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 69 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006B0F68F0690B6901695768E369106971693969606942695D6B16696B6980 69986978693469CC6AEC6ADA69CE6AF8696669636979699B69A769BB69AB69AD 69D469B169C169CA6AB369956AE7698D69FF6AA369ED6A176A186A6569F26A44 6A3E6AA06A506A5B6A356A8E6AD36A3D6A286A586ADE6A916A906AA96A976AAB 733773526B816B826BA46B846B9E6BAE6B8D6BAB6B9B6BAF6BAA8ED48EDB8EF2 8EFB8F648EF98EFC8EEB8EE48F628EFA8EFE8F0A8F078F058F128F268F1E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008F1F8F1C8F338F468F548ECE62146227621B621F62226221622562246229 81E7750C74F474FF750F75117513653465EE65EF65F0660A66C7677266036615 6600708566F7661D66346631663666358006665F66C46641664F668966616657 66776684668C66D6669D66BE66DB66DC66E666E98CC18CB08CBA8CBD8D048CB2 8CC58D108CD18CDA8CD58CEB8CE78CFB899889AC89A189BF89A689AF89B289B7 726E729F725D7266726F727E727F7284728B728D728F72926308633263B00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000643F64D880046BEA6BF36BFD6BFF6BF96C056C0C6C066C0D6C156C186C19 6C1A6C216C2C6C246C2A6C3265356555656B725872527256723086625216809F 809C809380BC670A80BD80B180AB80AD80B480B76727815680E981DA80DB80C2 80C480D980CD80D7671080DD811B80F180F480ED81BE810E80F280FC67158112 8C5A8161811E812C811881328148814C815381748159815A817181608169817C 817D816D8167584D5AB58188818281CF6ED581A381AA81CC672681CA81BB0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000081C181A66B5F6B376B396B436B466B5998AE98AF98B698BC98C698C86BB3 5F408F4289F365909F4F659565BC65C665C465C365CC65CE65D265D6716C7152 7096719770BB70C070B770AB70B171C170CA7110711371DC712F71317173715C 716871457172714A7178717A719871B371B571A871A071E071D471E771F9721D 7228706C71FE716671B9623E623D624362486249793B794079467949795B795C 7953795A79B079577960798E7967797A79AA798A799A79A779B35FD15FD00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000061DF605D605A606760416059606361646106610D615D61A9619D61CB61E3 62078080807F6C936FA96DFC78EF77F878AD780978687818781165AB782D78B8 781D7839792A7931781F783C7825782C78237829784E786D786478FD78267850 7847784C786A78E77893789A788778E378A178A378B278B978A578D478D978C9 78EC78F2790578F479137924791E79349F959EF99EFB9EFC76F17704779876F9 77077708771A77227719772D772677357738775E77BC77477743775A77680000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077627765777F778D777D7780778C7791779F77A077B077B577BD753A7540 754E754B7548755B7572757975837F587F617F5F8A487F687F867F717F797F88 7F7E76CD76E5883291D291D391D491D991D791D591F791E791E4934691F591F9 9208922692459211921092019227920492259200923A9266923792339255923D 9238925E926C926D923F9460923092499248924D922E9239943892AC92A0927A 92AA92EE92CF940392E3943A92B192A693A7929692CC92A993F59293927F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000093A9929A931A92AB9283940B92A892A39412933892F193D792E592F092EF 92E892BC92DD92F69426942792C392DF92E6931293069369931B934093019315 932E934393079308931F93199365934793769354936493AA9370938493E493D8 9428938793CC939893B893BF93A693B093B5944C93E293DC93DD93CD93DE93C3 93C793D19414941D93F794659413946D9420947993F99419944A9432943F9454 9463937E77E777EC96C979D579ED79E379EB7A065D477A037A027A1E7A140000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 70 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A397A377A619ECF99A57A707688768E7693769976A474DE74E0752C9CE9 9CF69D079D069D239D879E159D1D9D1F9DE59D2F9DD99D309D429E1E9D539E1D 9D609D529DF39D5C9D619D939D6A9D6F9D899D989D9A9DC09DA59DA99DC29DBC 9E1A9DD39DDA9DEF9DE69DF29DF89E0C9DFA9E1B7592759476647658759D7667 75A375B375B475B875C475B175B075C375C2760275CD75E3764675E675E47647 75E7760375F175FC75FF761076007649760C761E760A7625763B761576190000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 71 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000761B763C762276207640762D7630766D76357643766E7633764D76697654 765C76567672766F7FCA7AE67A787A797A807A867A887A957AC77AA07AAC7AA8 7AB67AB3886488698872887D887F888288A2896088B788BC88C9893388CE895D 894788F1891A88FC88E888FE88F08921891989138938890A8964892B89368941 8966897B758B80E576B876B477DC801280148016801C8020802E80258026802C 802980288031800B803580438046807980528075807189839807980E980F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 72 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009821981C6F4198269837984E98539873986298599865986C9870864D8654 866C87E38806867A867C867B86A8868D868B8706869D86A786A386AA869386A9 86B686C486B5882386B086BA86B186AF86C987F686B486E986FA87EF86ED8784 86D0871386DE881086DF86D886D18703870786F88708870A870D87098723873B 871E8725872E871A873E87C88734873187298737873F87828722877D8811877B 87608770874C876E878B8753876387BB876487598765879387AF87CE87D20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 73 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000087C68788878587AD8797878387AB87E587AC87B587B387CB87D387BD87D1 87C087CA87DB87EA87E087EE8816881387FE880A881B88218839883C7F367F4C 7F447F4582107AFA7AFD7B087BE47B047B677B0A7B2B7B0F7B477B387B2A7B19 7B2E7B317B207B257B247B337C697B1E7B587BF37B457B757B4C7B8F7B607B6E 7B7B7B627B727B717B907C007BCB7BB87BAC7B9D7C5C7B857C1E7B9C7BA27C2B 7BB47C237BC17BCC7BDD7BDA7BE57BE67BEA7C0C7BFE7BFC7C0F7C6A7C0B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 74 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007C1F7C2A7C267C387C5F7C4081FE82018202820481EC8844822182228264 822D822F8228822B8238826B82338234823E82448249824B824F825A825F8268 887E88CA888888D888DF895E7F9D7FA57FA77FAF7FB07FB27C7C65497C917CF2 7CF67C9E7CA27CB27CBC7CBD7CDD7CC77CCC7CCD7CC87CC57CD77CE8826E66A8 7FBF7FCE7FD57FE57FE17FE67FE97FEE7FF37CF87E367DA67DAE7E477E9B9EA9 9EB48D738D848D948D918DB28D678D6D8C478C49914A9150914E914F91640000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 75 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009162916191709169916F91C591C3917291749179918C91859190918D9191 91A291A391AA91AD91AE91AF91B591B491BA8C559E7A8E898DEB8E058E598E69 8DB58DBF8DBC8DBA8E4C8DD68DD78DDA8E928DCE8DCF8DDB8DC68DEC8E7A8E55 8DE38E9A8E8B8DE48E098DFD8E148E1D8E1F8E938E2E8E238E918E3A8E408E39 8E358E3D8E318E498E418E428EA18E638E4A8E708E768E7C8E6F8E748E858EAA 8E948E908EA68E9E8C788C828C8A8C858C988C94659B89D689F489DA89DC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 76 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000089E589EB89F68A3E8B26975A96E9974296EF9706973D9708970F970E972A 97449730973E9F549F5F9F599F609F5C9F669F6C9F6A9F779EFD9EFF9F0996B9 96BC96BD96CE96D277BF8B8E928E947E92C893E8936A93CA938F943E946B9B77 9B749B819B839B8E9C787A4C9B929C5F9B909BAD9B9A9BAA9B9E9C6D9BAB9B9D 9C589BC19C7A9C319C399C239C379BC09BCA9BC79BFD9BD69BEA9BEB9BE19BE4 9BE79BDD9BE29BF09BDB9BF49BD49C5D9C089C109C0D9C129C099BFF9C200000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 77 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009C329C2D9C289C259C299C339C3E9C489C3B9C359C459C569C549C529C67 977C978597C397BD979497C997AB97A397B297B49AB19AB09AB79DBB9AB69ABA 9ABC9AC19AC09ACF9AC29AD69AD59AD19B459B439B589B4E9B489B4D9B519957 995C992E995599549ADF9AE19AE69AEF9AEB9AFB9AED9AF99B089B0F9B229B1F 9B234E489EBE7E3B9E829E879E889E8B9E9293D69E9D9E9F9EDB9EDC9EDD9EE0 9EDF9EE29EF79EE79EE59EF29EEF9F229F2C9F2F9F399F379F3D9F3E9F440000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 78 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000896C95C693365F4685147E94538251B24E119F635679515A6DC09F156597 56419AEE83034E3089075E727A4098B35E7F95A49B0D52128FF45F597A6B98E2 51E050A24EF7835085915118636E6372524B5938774F8721814A7E8D91CC66C6 5E1877AD9E7556C99EF46FDB61DE77C770309EB5884A95E282F951ED62514EC6 673497C67C647E3497A69EAF786E820D672F677E56CC53F098B16AAF7F4E6D82 7CF04E074FC27E6B9E7956AE9B1A846F53F690C179A67C72613F4E919AD20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 79 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075C796BB53EA7DFB88FD79CD78437B5151C6000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 tcl8.6.5/library/encoding/cp1252.enc0000644000175000017500000000210311555560473016421 0ustar sergeisergei# Encoding file: cp1252, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 20AC0081201A0192201E20262020202102C62030016020390152008D017D008F 009020182019201C201D20222013201402DC21220161203A0153009D017E0178 00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF 00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF 00D000D100D200D300D400D500D600D700D800D900DA00DB00DC00DD00DE00DF 00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF 00F000F100F200F300F400F500F600F700F800F900FA00FB00FC00FD00FE00FF tcl8.6.5/library/encoding/macIceland.enc0000644000175000017500000000210711555560473017531 0ustar sergeisergei# Encoding file: macIceland, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C400C500C700C900D100D600DC00E100E000E200E400E300E500E700E900E8 00EA00EB00ED00EC00EE00EF00F100F300F200F400F600F500FA00F900FB00FC 00DD00B000A200A300A7202200B600DF00AE00A9212200B400A8226000C600D8 221E00B12264226500A500B522022211220F03C0222B00AA00BA03A900E600F8 00BF00A100AC221A01922248220600AB00BB202600A000C000C300D501520153 20132014201C201D2018201900F725CA00FF0178204420AC00D000F000DE00FE 00FD00B7201A201E203000C200CA00C100CB00C800CD00CE00CF00CC00D300D4 F8FF00D200DA00DB00D9013102C602DC00AF02D802D902DA00B802DD02DB02C7 tcl8.6.5/library/encoding/cp852.enc0000644000175000017500000000210211555560473016345 0ustar sergeisergei# Encoding file: cp852, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C700FC00E900E200E4016F010700E7014200EB0150015100EE017900C40106 00C90139013A00F400F6013D013E015A015B00D600DC01640165014100D7010D 00E100ED00F300FA01040105017D017E0118011900AC017A010C015F00AB00BB 2591259225932502252400C100C2011A015E256325512557255D017B017C2510 25142534252C251C2500253C01020103255A25542569256625602550256C00A4 01110110010E00CB010F014700CD00CE011B2518250C258825840162016E2580 00D300DF00D401430144014801600161015400DA0155017000FD00DD016300B4 00AD02DD02DB02C702D800A700F700B800B000A802D901710158015925A000A0 tcl8.6.5/library/encoding/iso8859-3.enc0000644000175000017500000000210611555560473017000 0ustar sergeisergei# Encoding file: iso8859-3, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A0012602D800A300A40000012400A700A80130015E011E013400AD0000017B 00B0012700B200B300B400B5012500B700B80131015F011F013500BD0000017C 00C000C100C2000000C4010A010800C700C800C900CA00CB00CC00CD00CE00CF 000000D100D200D300D4012000D600D7011C00D900DA00DB00DC016C015C00DF 00E000E100E2000000E4010B010900E700E800E900EA00EB00EC00ED00EE00EF 000000F100F200F300F4012100F600F7011D00F900FA00FB00FC016D015D02D9 tcl8.6.5/library/encoding/jis0201.enc0000644000175000017500000000210411555560473016576 0ustar sergeisergei# Encoding file: jis0201, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D203E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 tcl8.6.5/library/encoding/gb2312.enc0000644000175000017500000024710611555560473016423 0ustar sergeisergei# Encoding file: euc-cn, multi-byte M 003F 0 82 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030003001300230FB02C902C700A8300330052015FF5E2225202620182019 201C201D3014301530083009300A300B300C300D300E300F3016301730103011 00B100D700F72236222722282211220F222A222922082237221A22A522252220 23122299222B222E2261224C2248223D221D2260226E226F22642265221E2235 22342642264000B0203220332103FF0400A4FFE0FFE1203000A7211626062605 25CB25CF25CE25C725C625A125A025B325B2203B219221902191219330130000 A2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000024882489248A248B248C248D248E248F2490249124922493249424952496 249724982499249A249B247424752476247724782479247A247B247C247D247E 247F248024812482248324842485248624872460246124622463246424652466 2467246824690000000032203221322232233224322532263227322832290000 00002160216121622163216421652166216721682169216A216B000000000000 A3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF01FF02FF03FFE5FF05FF06FF07FF08FF09FF0AFF0BFF0CFF0DFF0EFF0F FF10FF11FF12FF13FF14FF15FF16FF17FF18FF19FF1AFF1BFF1CFF1DFF1EFF1F FF20FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2F FF30FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3AFF3BFF3CFF3DFF3EFF3F FF40FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5AFF5BFF5CFF5DFFE30000 A4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000304130423043304430453046304730483049304A304B304C304D304E304F 3050305130523053305430553056305730583059305A305B305C305D305E305F 3060306130623063306430653066306730683069306A306B306C306D306E306F 3070307130723073307430753076307730783079307A307B307C307D307E307F 3080308130823083308430853086308730883089308A308B308C308D308E308F 3090309130923093000000000000000000000000000000000000000000000000 A5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF 30B030B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF 30C030C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF 30D030D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000000 A6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000039103920393039403950396039703980399039A039B039C039D039E039F 03A003A103A303A403A503A603A703A803A90000000000000000000000000000 000003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C303C403C503C603C703C803C90000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000004100411041204130414041504010416041704180419041A041B041C041D 041E041F0420042104220423042404250426042704280429042A042B042C042D 042E042F00000000000000000000000000000000000000000000000000000000 000004300431043204330434043504510436043704380439043A043B043C043D 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000000000 A8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000010100E101CE00E0011300E9011B00E8012B00ED01D000EC014D00F301D2 00F2016B00FA01D400F901D601D801DA01DC00FC00EA00000000000000000000 0000000000000000000031053106310731083109310A310B310C310D310E310F 3110311131123113311431153116311731183119311A311B311C311D311E311F 3120312131223123312431253126312731283129000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000002500250125022503250425052506250725082509250A250B 250C250D250E250F2510251125122513251425152516251725182519251A251B 251C251D251E251F2520252125222523252425252526252725282529252A252B 252C252D252E252F2530253125322533253425352536253725382539253A253B 253C253D253E253F2540254125422543254425452546254725482549254A254B 0000000000000000000000000000000000000000000000000000000000000000 B0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000554A963F57C3632854CE550954C07691764C853C77EE827E788D72319698 978D6C285B894FFA630966975CB880FA684880AE660276CE51F9655671AC7FF1 888450B2596561CA6FB382AD634C625253ED54277B06516B75A45DF462D48DCB 9776628A8019575D97387F627238767D67CF767E64464F708D2562DC7A176591 73ED642C6273822C9881677F7248626E62CC4F3474E3534A529E7ECA90A65E2E 6886699C81807ED168D278C5868C9551508D8C2482DE80DE5305891252650000 B1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000858496F94FDD582199715B9D62B162A566B48C799C8D7206676F789160B2 535153178F8880CC8D1D94A1500D72C8590760EB711988AB595482EF672C7B28 5D297EF7752D6CF58E668FF8903C9F3B6BD491197B145F7C78A784D6853D6BD5 6BD96BD65E015E8775F995ED655D5F0A5FC58F9F58C181C2907F965B97AD8FB9 7F168D2C62414FBF53D8535E8FA88FA98FAB904D68075F6A819888689CD6618B 522B762A5F6C658C6FD26EE85BBE6448517551B067C44E1979C9997C70B30000 B2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075C55E7673BB83E064AD62E894B56CE2535A52C3640F94C27B944F2F5E1B 82368116818A6E246CCA9A736355535C54FA886557E04E0D5E036B657C3F90E8 601664E6731C88C16750624D8D22776C8E2991C75F6983DC8521991053C28695 6B8B60ED60E8707F82CD82314ED36CA785CF64CD7CD969FD66F9834953957B56 4FA7518C6D4B5C428E6D63D253C9832C833667E578B4643D5BDF5C945DEE8BE7 62C667F48C7A640063BA8749998B8C177F2094F24EA7961098A4660C73160000 B3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000573A5C1D5E38957F507F80A05382655E7545553150218D856284949E671D 56326F6E5DE2543570928F66626F64A463A35F7B6F8890F481E38FB05C186668 5FF16C8996488D81886C649179F057CE6A59621054484E587A0B60E96F848BDA 627F901E9A8B79E4540375F4630153196C608FDF5F1B9A70803B9F7F4F885C3A 8D647FC565A570BD514551B2866B5D075BA062BD916C75748E0C7A2061017B79 4EC77EF877854E1181ED521D51FA6A7153A88E87950496CF6EC19664695A0000 B4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000784050A877D7641089E6590463E35DDD7A7F693D4F20823955984E3275AE 7A975E625E8A95EF521B5439708A6376952457826625693F918755076DF37EAF 882262337EF075B5832878C196CC8F9E614874F78BCD6B64523A8D506B21806A 847156F153064ECE4E1B51D17C97918B7C074FC38E7F7BE17A9C64675D1450AC 810676017CB96DEC7FE067515B585BF878CB64AE641363AA632B9519642D8FBE 7B5476296253592754466B7950A362345E266B864EE38D37888B5F85902E0000 B5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006020803D62C54E39535590F863B880C665E66C2E4F4660EE6DE18BDE5F39 86CB5F536321515A83616863520063638E4850125C9B79775BFC52307A3B60BC 905376D75FB75F9776848E6C706F767B7B4977AA51F3909358244F4E6EF48FEA 654C7B1B72C46DA47FDF5AE162B55E95573084827B2C5E1D5F1F90127F1498A0 63826EC7789870B95178975B57AB75354F4375385E9760E659606DC06BBF7889 53FC96D551CB52016389540A94938C038DCC7239789F87768FED8C0D53E00000 B6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E0176EF53EE948998769F0E952D5B9A8BA24E224E1C51AC846361C252A8 680B4F97606B51BB6D1E515C6296659796618C46901775D890FD77636BD2728A 72EC8BFB583577798D4C675C9540809A5EA66E2159927AEF77ED953B6BB565AD 7F0E58065151961F5BF958A954288E726566987F56E4949D76FE9041638754C6 591A593A579B8EB267358DFA8235524160F0581586FE5CE89E454FC4989D8BB9 5A2560765384627C904F9102997F6069800C513F80335C1499756D314E8C0000 B7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008D3053D17F5A7B4F4F104E4F96006CD573D085E95E06756A7FFB6A0A77FE 94927E4151E170E653CD8FD483038D2972AF996D6CDB574A82B365B980AA623F 963259A84EFF8BBF7EBA653E83F2975E556198DE80A5532A8BFD542080BA5E9F 6CB88D3982AC915A54296C1B52067EB7575F711A6C7E7C89594B4EFD5FFF6124 7CAA4E305C0167AB87025CF0950B98CE75AF70FD902251AF7F1D8BBD594951E4 4F5B5426592B657780A45B75627662C28F905E456C1F7B264F0F4FD8670D0000 B8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D6E6DAA798F88B15F17752B629A8F854FEF91DC65A7812F81515E9C8150 8D74526F89868D4B590D50854ED8961C723681798D1F5BCC8BA3964459877F1A 54905676560E8BE565396982949976D66E895E727518674667D17AFF809D8D76 611F79C665628D635188521A94A27F38809B7EB25C976E2F67607BD9768B9AD8 818F7F947CD5641E95507A3F544A54E56B4C640162089E3D80F3759952729769 845B683C86E49601969494EC4E2A54047ED968398DDF801566F45E9A7FB90000 B9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000057C2803F68975DE5653B529F606D9F9A4F9B8EAC516C5BAB5F135DE96C5E 62F18D21517194A952FE6C9F82DF72D757A267848D2D591F8F9C83C754957B8D 4F306CBD5B6459D19F1353E486CA9AA88C3780A16545987E56FA96C7522E74DC 52505BE1630289024E5662D0602A68FA51735B9851A089C27BA199867F5060EF 704C8D2F51495E7F901B747089C4572D78455F529F9F95FA8F689B3C8BE17678 684267DC8DEA8D35523D8F8A6EDA68CD950590ED56FD679C88F98FC754C80000 BA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009AB85B696D776C264EA55BB39A87916361A890AF97E9542B6DB55BD251FD 558A7F557FF064BC634D65F161BE608D710A6C576C49592F676D822A58D5568E 8C6A6BEB90DD597D801753F76D695475559D837783CF683879BE548C4F555408 76D28C8996026CB36DB88D6B89109E648D3A563F9ED175D55F8872E0606854FC 4EA86A2A886160528F7054C470D886799E3F6D2A5B8F5F187EA255894FAF7334 543C539A5019540E547C4E4E5FFD745A58F6846B80E1877472D07CCA6E560000 BB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F27864E552C62A44E926CAA623782B154D7534E733E6ED1753B52125316 8BDD69D05F8A60006DEE574F6B2273AF68538FD87F13636260A3552475EA8C62 71156DA35BA65E7B8352614C9EC478FA87577C27768751F060F6714C66435E4C 604D8C0E707063258F895FBD606286D456DE6BC160946167534960E066668D3F 79FD4F1A70E96C478BB38BF27ED88364660F5A5A9B426D516DF78C416D3B4F19 706B83B7621660D1970D8D27797851FB573E57FA673A75787A3D79EF7B950000 BC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000808C99658FF96FC08BA59E2159EC7EE97F095409678168D88F917C4D96C6 53CA602575BE6C7253735AC97EA7632451E0810A5DF184DF628051805B634F0E 796D524260B86D4E5BC45BC28BA18BB065E25FCC964559937EE77EAA560967B7 59394F735BB652A0835A988A8D3E753294BE50477A3C4EF767B69A7E5AC16B7C 76D1575A5C167B3A95F4714E517C80A9827059787F04832768C067EC78B17877 62E363617B804FED526A51CF835069DB92748DF58D3189C1952E7BAD4EF60000 BD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000506582305251996F6E106E856DA75EFA50F559DC5C066D466C5F7586848B 686859568BB253209171964D854969127901712680F64EA490CA6D479A845A07 56BC640594F077EB4FA5811A72E189D2997A7F347EDE527F655991758F7F8F83 53EB7A9663ED63A5768679F888579636622A52AB8282685467706377776B7AED 6D017ED389E359D0621285C982A5754C501F4ECB75A58BEB5C4A5DFE7B4B65A4 91D14ECA6D25895F7D2795264EC58C288FDB9773664B79818FD170EC6D780000 BE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C3D52B283465162830E775B66769CB84EAC60CA7CBE7CB37ECF4E958B66 666F988897595883656C955C5F8475C997567ADF7ADE51C070AF7A9863EA7A76 7EA0739697ED4E4570784E5D915253A9655165E781FC8205548E5C31759A97A0 62D872D975BD5C459A7983CA5C40548077E94E3E6CAE805A62D2636E5DE85177 8DDD8E1E952F4FF153E560E770AC526763509E435A1F5026773753777EE26485 652B628963985014723589C951B38BC07EDD574783CC94A7519B541B5CFB0000 BF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004FCA7AE36D5A90E19A8F55805496536154AF5F0063E9697751EF6168520A 582A52D8574E780D770B5EB761777CE0625B62974EA27095800362F770E49760 577782DB67EF68F578D5989779D158F354B353EF6E34514B523B5BA28BFE80AF 554357A660735751542D7A7A60505B5463A762A053E362635BC767AF54ED7A9F 82E691775E9388E4593857AE630E8DE880EF57577B774FA95FEB5BBD6B3E5321 7B5072C2684677FF773665F751B54E8F76D45CBF7AA58475594E9B4150800000 C0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000998861276E8357646606634656F062EC62695ED39614578362C955878721 814A8FA3556683B167658D5684DD5A6A680F62E67BEE961151706F9C8C3063FD 89C861D27F0670C26EE57405699472FC5ECA90CE67176D6A635E52B372628001 4F6C59E5916A70D96D9D52D24E5096F7956D857E78CA7D2F5121579264C2808B 7C7B6CEA68F1695E51B7539868A872819ECE7BF172F879BB6F137406674E91CC 9CA4793C83898354540F68174E3D538952B1783E5386522950884F8B4FD00000 C1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000075E27ACB7C926CA596B6529B748354E94FE9805483B28FDE95705EC9601C 6D9F5E18655B813894FE604B70BC7EC37CAE51C968817CB1826F4E248F8691CF 667E4EAE8C0564A9804A50DA759771CE5BE58FBD6F664E86648295635ED66599 521788C270C852A3730E7433679778F797164E3490BB9CDE6DCB51DB8D41541D 62CE73B283F196F69F8494C34F367F9A51CC707596755CAD988653E64EE46E9C 740969B4786B998F7559521876246D4167F3516D9F99804B54997B3C7ABF0000 C2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009686578462E29647697C5A0464027BD36F0F964B82A6536298855E907089 63B35364864F9C819E93788C97328DEF8D429E7F6F5E79845F559646622E9A74 541594DD4FA365C55C655C617F1586516C2F5F8B73876EE47EFF5CE6631B5B6A 6EE653754E7163A0756562A18F6E4F264ED16CA67EB68BBA841D87BA7F57903B 95237BA99AA188F8843D6D1B9A867EDC59889EBB739B780186829A6C9A82561B 541757CB4E709EA653568FC881097792999286EE6EE1851366FC61626F2B0000 C3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008C298292832B76F26C135FD983BD732B8305951A6BDB77DB94C6536F8302 51925E3D8C8C8D384E4873AB679A68859176970971646CA177095A9295416BCF 7F8E66275BD059B95A9A95E895F74EEC840C84996AAC76DF9530731B68A65B5F 772F919A97617CDC8FF78C1C5F257C7379D889C56CCC871C5BC65E4268C97720 7EF55195514D52C95A297F05976282D763CF778485D079D26E3A5E9959998511 706D6C1162BF76BF654F60AF95FD660E879F9E2394ED540D547D8C2C64780000 C4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000647986116A21819C78E864699B5462B9672B83AB58A89ED86CAB6F205BDE 964C8C0B725F67D062C772614EA959C66BCD589366AE5E5552DF6155672876EE 776672677A4662FF54EA545094A090A35A1C7EB36C164E435976801059485357 753796BE56CA63208111607C95F96DD65462998151855AE980FD59AE9713502A 6CE55C3C62DF4F60533F817B90066EBA852B62C85E7478BE64B5637B5FF55A18 917F9E1F5C3F634F80425B7D556E954A954D6D8560A867E072DE51DD5B810000 C5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000062E76CDE725B626D94AE7EBD81136D53519C5F04597452AA601259736696 8650759F632A61E67CEF8BFA54E66B279E256BB485D5545550766CA4556A8DB4 722C5E156015743662CD6392724C5F986E436D3E65006F5876D878D076FC7554 522453DB4E535E9E65C1802A80D6629B5486522870AE888D8DD16CE1547880DA 57F988F48D54966A914D4F696C9B55B776C6783062A870F96F8E5F6D84EC68DA 787C7BF781A8670B9E4F636778B0576F78129739627962AB528874356BD70000 C6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005564813E75B276AE533975DE50FB5C418B6C7BC7504F72479A9798D86F02 74E27968648777A562FC98918D2B54C180584E52576A82F9840D5E7351ED74F6 8BC45C4F57616CFC98875A4678349B448FEB7C955256625194FA4EC683868461 83E984B257D467345703666E6D668C3166DD7011671F6B3A6816621A59BB4E03 51C46F0667D26C8F517668CB59476B6775665D0E81109F5065D7794879419A91 8D775C824E5E4F01542F5951780C56686C148FC45F036C7D6CE38BAB63900000 C7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000060706D3D72756266948E94C553438FC17B7E4EDF8C264E7E9ED494B194B3 524D6F5C90636D458C3458115D4C6B206B4967AA545B81547F8C589985375F3A 62A26A47953965726084686577A74E544FA85DE7979864AC7FD85CED4FCF7A8D 520783044E14602F7A8394A64FB54EB279E6743452E482B964D279BD5BDD6C81 97528F7B6C22503E537F6E0564CE66746C3060C598778BF75E86743C7A7779CB 4E1890B174036C4256DA914B6CC58D8B533A86C666F28EAF5C489A716E200000 C8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000053D65A369F8B8DA353BB570898A76743919B6CC9516875CA62F372AC5238 529D7F3A7094763853749E4A69B7786E96C088D97FA4713671C3518967D374E4 58E4651856B78BA9997662707ED560F970ED58EC4EC14EBA5FCD97E74EFB8BA4 5203598A7EAB62544ECD65E5620E833884C98363878D71946EB65BB97ED25197 63C967D480898339881551125B7A59828FB14E736C5D516589258F6F962E854A 745E951095F06DA682E55F3164926D128428816E9CC3585E8D5B4E0953C10000 C9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F1E6563685155D34E2764149A9A626B5AC2745F82726DA968EE50E7838E 7802674052396C997EB150BB5565715E7B5B665273CA82EB67495C715220717D 886B95EA965564C58D6181B355846C5562477F2E58924F2455468D4F664C4E0A 5C1A88F368A2634E7A0D70E7828D52FA97F65C1154E890B57ECD59628D4A86C7 820C820D8D6664445C0461516D89793E8BBE78377533547B4F388EAB6DF15A20 7EC5795E6C885BA15A76751A80BE614E6E1758F0751F7525727253477EF30000 CA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000770176DB526980DC57235E08593172EE65BD6E7F8BD75C388671534177F3 62FE65F64EC098DF86805B9E8BC653F277E24F7F5C4E9A7659CB5F0F793A58EB 4E1667FF4E8B62ED8A93901D52BF662F55DC566C90024ED54F8D91CA99706C0F 5E0260435BA489C68BD56536624B99965B885BFF6388552E53D77626517D852C 67A268B36B8A62928F9353D482126DD1758F4E668D4E5B70719F85AF669166D9 7F7287009ECD9F205C5E672F8FF06811675F620D7AD658855EB665706F310000 CB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000060555237800D6454887075295E05681362F4971C53CC723D8C016C347761 7A0E542E77AC987A821C8BF47855671470C165AF64955636601D79C153F84E1D 6B7B80865BFA55E356DB4F3A4F3C99725DF3677E80386002988290015B8B8BBC 8BF5641C825864DE55FD82CF91654FD77D20901F7C9F50F358516EAF5BBF8BC9 80839178849C7B97867D968B968F7EE59AD3788E5C817A57904296A7795F5B59 635F7B0B84D168AD55067F2974107D2295016240584C4ED65B83597958540000 CC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000736D631E8E4B8E0F80CE82D462AC53F06CF0915E592A60016C70574D644A 8D2A762B6EE9575B6A8075F06F6D8C2D8C0857666BEF889278B363A253F970AD 6C645858642A580268E0819B55107CD650188EBA6DCC8D9F70EB638F6D9B6ED4 7EE68404684390036DD896768BA85957727985E4817E75BC8A8A68AF52548E22 951163D098988E44557C4F5366FF568F60D56D9552435C4959296DFB586B7530 751C606C82148146631167618FE2773A8DF38D3494C15E165385542C70C30000 CD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006C405EF7505C4EAD5EAD633A8247901A6850916E77B3540C94DC5F647AE5 687663457B527EDF75DB507762955934900F51F879C37A8156FE5F9290146D82 5C60571F541051546E4D56E263A89893817F8715892A9000541E5C6F81C062D6 625881319E3596409A6E9A7C692D59A562D3553E631654C786D96D3C5A0374E6 889C6B6A59168C4C5F2F6E7E73A9987D4E3870F75B8C7897633D665A769660CB 5B9B5A494E0781556C6A738B4EA167897F515F8065FA671B5FD859845A010000 CE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005DCD5FAE537197E68FDD684556F4552F60DF4E3A6F4D7EF482C7840E59D4 4F1F4F2A5C3E7EAC672A851A5473754F80C355829B4F4F4D6E2D8C135C096170 536B761F6E29868A658795FB7EB9543B7A337D0A95EE55E17FC174EE631D8717 6DA17A9D621165A1536763E16C835DEB545C94A84E4C6C618BEC5C4B65E0829C 68A7543E54346BCB6B664E9463425348821E4F0D4FAE575E620A96FE66647269 52FF52A1609F8BEF661471996790897F785277FD6670563B54389521727A0000 CF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A00606F5E0C6089819D591560DC718470EF6EAA6C5072806A8488AD5E2D 4E605AB3559C94E36D177CFB9699620F7EC6778E867E5323971E8F9666875CE1 4FA072ED4E0B53A6590F54136380952851484ED99C9C7EA454B88D2488548237 95F26D8E5F265ACC663E966973B0732E53BF817A99857FA15BAA967796507EBF 76F853A2957699997BB189446E584E617FD479658BE660F354CD4EAB98795DF7 6A6150CF54118C618427785D9704524A54EE56A395006D885BB56DC666530000 D0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005C0F5B5D6821809655787B11654869544E9B6B47874E978B534F631F643A 90AA659C80C18C10519968B0537887F961C86CC46CFB8C225C5185AA82AF950C 6B238F9B65B05FFB5FC34FE18845661F8165732960FA51745211578B5F6290A2 884C91925E78674F602759D3514451F680F853086C7996C4718A4F114FEE7F9E 673D55C5950879C088967EE3589F620C9700865A5618987B5F908BB884C49157 53D965ED5E8F755C60647D6E5A7F7EEA7EED8F6955A75BA360AC65CB73840000 D1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009009766377297EDA9774859B5B667A7496EA884052CB718F5FAA65EC8BE2 5BFB9A6F5DE16B896C5B8BAD8BAF900A8FC5538B62BC9E269E2D54404E2B82BD 7259869C5D1688596DAF96C554D14E9A8BB6710954BD960970DF6DF976D04E25 781487125CA95EF68A00989C960E708E6CBF594463A9773C884D6F1482735830 71D5538C781A96C155015F6671305BB48C1A9A8C6B83592E9E2F79E76768626C 4F6F75A17F8A6D0B96336C274EF075D2517B68376F3E90808170599674760000 D2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000064475C2790657A918C2359DA54AC8200836F898180006930564E80367237 91CE51B64E5F987563964E1A53F666F3814B591C6DB24E0058F9533B63D694F1 4F9D4F0A886398905937905779FB4EEA80F075916C825B9C59E85F5D69058681 501A5DF24E5977E34EE5827A6291661390915C794EBF5F7981C69038808475AB 4EA688D4610F6BC55FC64E4976CA6EA28BE38BAE8C0A8BD15F027FFC7FCC7ECE 8335836B56E06BB797F3963459FB541F94F66DEB5BC5996E5C395F1596900000 D3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000537082F16A315A749E705E947F2883B984248425836787478FCE8D6276C8 5F719896786C662054DF62E54F6381C375C85EB896CD8E0A86F9548F6CF36D8C 6C38607F52C775285E7D4F1860A05FE75C24753190AE94C072B96CB96E389149 670953CB53F34F5191C98BF153C85E7C8FC26DE44E8E76C26986865E611A8206 4F594FDE903E9C7C61096E1D6E1496854E885A3196E84E0E5C7F79B95B878BED 7FBD738957DF828B90C15401904755BB5CEA5FA161086B3272F180B28A890000 D4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D745BD388D598848C6B9A6D9E336E0A51A4514357A38881539F63F48F95 56ED54585706733F6E907F188FDC82D1613F6028966266F07EA68D8A8DC394A5 5CB37CA4670860A6960580184E9190E75300966851418FD08574915D665597F5 5B55531D78386742683D54C9707E5BB08F7D518D572854B1651266828D5E8D43 810F846C906D7CDF51FF85FB67A365E96FA186A48E81566A90207682707671E5 8D2362E952196CFD8D3C600E589E618E66FE8D60624E55B36E23672D8F670000 D5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000094E195F87728680569A8548B4E4D70B88BC86458658B5B857A84503A5BE8 77BB6BE18A797C986CBE76CF65A98F975D2D5C5586386808536062187AD96E5B 7EFD6A1F7AE05F706F335F20638C6DA867564E085E108D264ED780C07634969C 62DB662D627E6CBC8D7571677F695146808753EC906E629854F286F08F998005 951785178FD96D5973CD659F771F7504782781FB8D1E94884FA6679575B98BCA 9707632F9547963584B8632377415F8172F04E896014657462EF6B63653F0000 D6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005E2775C790D18BC1829D679D652F5431871877E580A281026C414E4B7EC7 804C76F4690D6B966267503C4F84574063076B628DBE53EA65E87EB85FD7631A 63B781F381F47F6E5E1C5CD95236667A79E97A1A8D28709975D46EDE6CBB7A92 4E2D76C55FE0949F88777EC879CD80BF91CD4EF24F17821F54685DDE6D328BCC 7CA58F7480985E1A549276B15B99663C9AA473E0682A86DB6731732A8BF88BDB 90107AF970DB716E62C477A956314E3B845767F152A986C08D2E94F87B510000 D7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F4F6CE8795D9A7B6293722A62FD4E1378168F6C64B08D5A7BC668695E84 88C55986649E58EE72B6690E95258FFD8D5857607F008C0651C6634962D95353 684C74228301914C55447740707C6D4A517954A88D4459FF6ECB6DC45B5C7D2B 4ED47C7D6ED35B5081EA6E0D5B579B0368D58E2A5B977EFC603B7EB590B98D70 594F63CD79DF8DB3535265CF79568BC5963B7EC494BB7E825634918967007F6A 5C0A907566285DE64F5067DE505A4F5C57505EA7000000000000000000000000 D8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E8D4E0C51404E105EFF53454E154E984E1E9B325B6C56694E2879BA4E3F 53154E47592D723B536E6C1056DF80E499976BD3777E9F174E364E9F9F104E5C 4E694E9382885B5B556C560F4EC4538D539D53A353A553AE97658D5D531A53F5 5326532E533E8D5C5366536352025208520E522D5233523F5240524C525E5261 525C84AF527D528252815290529351827F544EBB4EC34EC94EC24EE84EE14EEB 4EDE4F1B4EF34F224F644EF54F254F274F094F2B4F5E4F6765384F5A4F5D0000 D9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F5F4F574F324F3D4F764F744F914F894F834F8F4F7E4F7B4FAA4F7C4FAC 4F944FE64FE84FEA4FC54FDA4FE34FDC4FD14FDF4FF85029504C4FF3502C500F 502E502D4FFE501C500C50255028507E504350555048504E506C507B50A550A7 50A950BA50D6510650ED50EC50E650EE5107510B4EDD6C3D4F584F654FCE9FA0 6C467C74516E5DFD9EC999985181591452F9530D8A07531051EB591951554EA0 51564EB3886E88A44EB5811488D279805B3488037FB851AB51B151BD51BC0000 DA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000051C7519651A251A58BA08BA68BA78BAA8BB48BB58BB78BC28BC38BCB8BCF 8BCE8BD28BD38BD48BD68BD88BD98BDC8BDF8BE08BE48BE88BE98BEE8BF08BF3 8BF68BF98BFC8BFF8C008C028C048C078C0C8C0F8C118C128C148C158C168C19 8C1B8C188C1D8C1F8C208C218C258C278C2A8C2B8C2E8C2F8C328C338C358C36 5369537A961D962296219631962A963D963C964296499654965F9667966C9672 96749688968D969796B09097909B909D909990AC90A190B490B390B690BA0000 DB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000090B890B090CF90C590BE90D090C490C790D390E690E290DC90D790DB90EB 90EF90FE91049122911E91239131912F913991439146520D594252A252AC52AD 52BE54FF52D052D652F053DF71EE77CD5EF451F551FC9B2F53B65F01755A5DEF 574C57A957A1587E58BC58C558D15729572C572A57335739572E572F575C573B 574257695785576B5786577C577B5768576D5776577357AD57A4578C57B257CF 57A757B4579357A057D557D857DA57D957D257B857F457EF57F857E457DD0000 DC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000580B580D57FD57ED5800581E5819584458205865586C58815889589A5880 99A89F1961FF8279827D827F828F828A82A88284828E82918297829982AB82B8 82BE82B082C882CA82E3829882B782AE82CB82CC82C182A982B482A182AA829F 82C482CE82A482E1830982F782E4830F830782DC82F482D282D8830C82FB82D3 8311831A83068314831582E082D5831C8351835B835C83088392833C83348331 839B835E832F834F83478343835F834083178360832D833A8333836683650000 DD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008368831B8369836C836A836D836E83B0837883B383B483A083AA8393839C 8385837C83B683A9837D83B8837B8398839E83A883BA83BC83C1840183E583D8 58078418840B83DD83FD83D6841C84388411840683D483DF840F840383F883F9 83EA83C583C0842683F083E1845C8451845A8459847384878488847A84898478 843C844684698476848C848E8431846D84C184CD84D084E684BD84D384CA84BF 84BA84E084A184B984B4849784E584E3850C750D853884F08539851F853A0000 DE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008556853B84FF84FC8559854885688564855E857A77A285438572857B85A4 85A88587858F857985AE859C858585B985B785B085D385C185DC85FF86278605 86298616863C5EFE5F08593C594180375955595A5958530F5C225C255C2C5C34 624C626A629F62BB62CA62DA62D762EE632262F66339634B634363AD63F66371 637A638E63B4636D63AC638A636963AE63BC63F263F863E063FF63C463DE63CE 645263C663BE64456441640B641B6420640C64266421645E6484646D64960000 DF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000647A64B764B8649964BA64C064D064D764E464E265096525652E5F0B5FD2 75195F11535F53F153FD53E953E853FB541254165406544B5452545354545456 54435421545754595423543254825494547754715464549A549B548454765466 549D54D054AD54C254B454D254A754A654D354D4547254A354D554BB54BF54CC 54D954DA54DC54A954AA54A454DD54CF54DE551B54E7552054FD551454F35522 5523550F55115527552A5567558F55B55549556D55415555553F5550553C0000 E0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005537555655755576557755335530555C558B55D2558355B155B955885581 559F557E55D65591557B55DF55BD55BE5594559955EA55F755C9561F55D155EB 55EC55D455E655DD55C455EF55E555F255F355CC55CD55E855F555E48F94561E 5608560C56015624562355FE56005627562D565856395657562C564D56625659 565C564C5654568656645671566B567B567C5685569356AF56D456D756DD56E1 56F556EB56F956FF5704570A5709571C5E0F5E195E145E115E315E3B5E3C0000 E1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005E375E445E545E5B5E5E5E615C8C5C7A5C8D5C905C965C885C985C995C91 5C9A5C9C5CB55CA25CBD5CAC5CAB5CB15CA35CC15CB75CC45CD25CE45CCB5CE5 5D025D035D275D265D2E5D245D1E5D065D1B5D585D3E5D345D3D5D6C5D5B5D6F 5D5D5D6B5D4B5D4A5D695D745D825D995D9D8C735DB75DC55F735F775F825F87 5F895F8C5F955F995F9C5FA85FAD5FB55FBC88625F6172AD72B072B472B772B8 72C372C172CE72CD72D272E872EF72E972F272F472F7730172F3730372FA0000 E2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000072FB731773137321730A731E731D7315732273397325732C733873317350 734D73577360736C736F737E821B592598E7592459029963996799689969996A 996B996C99749977997D998099849987998A998D999099919993999499955E80 5E915E8B5E965EA55EA05EB95EB55EBE5EB38D535ED25ED15EDB5EE85EEA81BA 5FC45FC95FD65FCF60035FEE60045FE15FE45FFE600560065FEA5FED5FF86019 60356026601B600F600D6029602B600A603F602160786079607B607A60420000 E3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000606A607D6096609A60AD609D60836092608C609B60EC60BB60B160DD60D8 60C660DA60B4612061266115612360F46100610E612B614A617561AC619461A7 61B761D461F55FDD96B395E995EB95F195F395F595F695FC95FE960396049606 9608960A960B960C960D960F96129615961696179619961A4E2C723F62156C35 6C546C5C6C4A6CA36C856C906C946C8C6C686C696C746C766C866CA96CD06CD4 6CAD6CF76CF86CF16CD76CB26CE06CD66CFA6CEB6CEE6CB16CD36CEF6CFE0000 E4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006D396D276D0C6D436D486D076D046D196D0E6D2B6D4D6D2E6D356D1A6D4F 6D526D546D336D916D6F6D9E6DA06D5E6D936D946D5C6D606D7C6D636E1A6DC7 6DC56DDE6E0E6DBF6DE06E116DE66DDD6DD96E166DAB6E0C6DAE6E2B6E6E6E4E 6E6B6EB26E5F6E866E536E546E326E256E446EDF6EB16E986EE06F2D6EE26EA5 6EA76EBD6EBB6EB76ED76EB46ECF6E8F6EC26E9F6F626F466F476F246F156EF9 6F2F6F366F4B6F746F2A6F096F296F896F8D6F8C6F786F726F7C6F7A6FD10000 E5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006FC96FA76FB96FB66FC26FE16FEE6FDE6FE06FEF701A7023701B70397035 704F705E5B805B845B955B935BA55BB8752F9A9E64345BE45BEE89305BF08E47 8B078FB68FD38FD58FE58FEE8FE48FE98FE68FF38FE890059004900B90269011 900D9016902190359036902D902F9044905190529050906890589062905B66B9 9074907D908290889083908B5F505F575F565F585C3B54AB5C505C595B715C63 5C667FBC5F2A5F295F2D82745F3C9B3B5C6E59815983598D59A959AA59A30000 E6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000599759CA59AB599E59A459D259B259AF59D759BE5A055A0659DD5A0859E3 59D859F95A0C5A095A325A345A115A235A135A405A675A4A5A555A3C5A625A75 80EC5AAA5A9B5A775A7A5ABE5AEB5AB25AD25AD45AB85AE05AE35AF15AD65AE6 5AD85ADC5B095B175B165B325B375B405C155C1C5B5A5B655B735B515B535B62 9A759A779A789A7A9A7F9A7D9A809A819A859A889A8A9A909A929A939A969A98 9A9B9A9C9A9D9A9F9AA09AA29AA39AA59AA77E9F7EA17EA37EA57EA87EA90000 E7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007EAD7EB07EBE7EC07EC17EC27EC97ECB7ECC7ED07ED47ED77EDB7EE07EE1 7EE87EEB7EEE7EEF7EF17EF27F0D7EF67EFA7EFB7EFE7F017F027F037F077F08 7F0B7F0C7F0F7F117F127F177F197F1C7F1B7F1F7F217F227F237F247F257F26 7F277F2A7F2B7F2C7F2D7F2F7F307F317F327F337F355E7A757F5DDB753E9095 738E739173AE73A2739F73CF73C273D173B773B373C073C973C873E573D9987C 740A73E973E773DE73BA73F2740F742A745B7426742574287430742E742C0000 E8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000741B741A7441745C7457745574597477746D747E749C748E748074817487 748B749E74A874A9749074A774D274BA97EA97EB97EC674C6753675E67486769 67A56787676A6773679867A7677567A8679E67AD678B6777677C67F0680967D8 680A67E967B0680C67D967B567DA67B367DD680067C367B867E2680E67C167FD 6832683368606861684E6862684468646883681D68556866684168676840683E 684A6849682968B5688F687468776893686B68C2696E68FC691F692068F90000 E9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000692468F0690B6901695768E369106971693969606942695D6984696B6980 69986978693469CC6987698869CE6989696669636979699B69A769BB69AB69AD 69D469B169C169CA69DF699569E0698D69FF6A2F69ED6A176A186A6569F26A44 6A3E6AA06A506A5B6A356A8E6A796A3D6A286A586A7C6A916A906AA96A976AAB 733773526B816B826B876B846B926B936B8D6B9A6B9B6BA16BAA8F6B8F6D8F71 8F728F738F758F768F788F778F798F7A8F7C8F7E8F818F828F848F878F8B0000 EA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008F8D8F8E8F8F8F988F9A8ECE620B6217621B621F6222622162256224622C 81E774EF74F474FF750F75117513653465EE65EF65F0660A6619677266036615 6600708566F7661D66346631663666358006665F66546641664F665666616657 66776684668C66A7669D66BE66DB66DC66E666E98D328D338D368D3B8D3D8D40 8D458D468D488D498D478D4D8D558D5989C789CA89CB89CC89CE89CF89D089D1 726E729F725D7266726F727E727F7284728B728D728F72926308633263B00000 EB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000643F64D880046BEA6BF36BFD6BF56BF96C056C076C066C0D6C156C186C19 6C1A6C216C296C246C2A6C3265356555656B724D72527256723086625216809F 809C809380BC670A80BD80B180AB80AD80B480B780E780E880E980EA80DB80C2 80C480D980CD80D7671080DD80EB80F180F480ED810D810E80F280FC67158112 8C5A8136811E812C811881328148814C815381748159815A817181608169817C 817D816D8167584D5AB58188818281916ED581A381AA81CC672681CA81BB0000 EC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000081C181A66B246B376B396B436B466B5998D198D298D398D598D998DA6BB3 5F406BC289F365909F51659365BC65C665C465C365CC65CE65D265D67080709C 7096709D70BB70C070B770AB70B170E870CA711071137116712F71317173715C 716871457172714A7178717A719871B371B571A871A071E071D471E771F9721D 7228706C7118716671B9623E623D624362486249793B794079467949795B795C 7953795A796279577960796F7967797A7985798A799A79A779B35FD15FD00000 ED 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000603C605D605A606760416059606360AB6106610D615D61A9619D61CB61D1 62068080807F6C936CF66DFC77F677F87800780978177818781165AB782D781C 781D7839783A783B781F783C7825782C78237829784E786D7856785778267850 7847784C786A789B7893789A7887789C78A178A378B278B978A578D478D978C9 78EC78F2790578F479137924791E79349F9B9EF99EFB9EFC76F17704770D76F9 77077708771A77227719772D7726773577387750775177477743775A77680000 EE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077627765777F778D777D7780778C7791779F77A077B077B577BD753A7540 754E754B7548755B7572757975837F587F617F5F8A487F687F747F717F797F81 7F7E76CD76E58832948594869487948B948A948C948D948F9490949494979495 949A949B949C94A394A494AB94AA94AD94AC94AF94B094B294B494B694B794B8 94B994BA94BC94BD94BF94C494C894C994CA94CB94CC94CD94CE94D094D194D2 94D594D694D794D994D894DB94DE94DF94E094E294E494E594E794E894EA0000 EF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000094E994EB94EE94EF94F394F494F594F794F994FC94FD94FF950395029506 95079509950A950D950E950F951295139514951595169518951B951D951E951F 9522952A952B9529952C953195329534953695379538953C953E953F95429535 9544954595469549954C954E954F9552955395549556955795589559955B955E 955F955D95619562956495659566956795689569956A956B956C956F95719572 9573953A77E777EC96C979D579ED79E379EB7A065D477A037A027A1E7A140000 F0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A397A377A519ECF99A57A707688768E7693769976A474DE74E0752C9E20 9E229E289E299E2A9E2B9E2C9E329E319E369E389E379E399E3A9E3E9E419E42 9E449E469E479E489E499E4B9E4C9E4E9E519E559E579E5A9E5B9E5C9E5E9E63 9E669E679E689E699E6A9E6B9E6C9E719E6D9E7375927594759675A0759D75AC 75A375B375B475B875C475B175B075C375C275D675CD75E375E875E675E475EB 75E7760375F175FC75FF761076007605760C7617760A76257618761576190000 F1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000761B763C762276207640762D7630763F76357643763E7633764D765E7654 765C7656766B766F7FCA7AE67A787A797A807A867A887A957AA67AA07AAC7AA8 7AAD7AB3886488698872887D887F888288A288C688B788BC88C988E288CE88E3 88E588F1891A88FC88E888FE88F0892189198913891B890A8934892B89368941 8966897B758B80E576B276B477DC801280148016801C80208022802580268027 802980288031800B803580438046804D80528069807189839878988098830000 F2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009889988C988D988F9894989A989B989E989F98A198A298A598A6864D8654 866C866E867F867A867C867B86A8868D868B86AC869D86A786A386AA869386A9 86B686C486B586CE86B086BA86B186AF86C986CF86B486E986F186F286ED86F3 86D0871386DE86F486DF86D886D18703870786F88708870A870D87098723873B 871E8725872E871A873E87488734873187298737873F87828722877D877E877B 87608770874C876E878B87538763877C876487598765879387AF87A887D20000 F3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000087C68788878587AD8797878387AB87E587AC87B587B387CB87D387BD87D1 87C087CA87DB87EA87E087EE8816881387FE880A881B88218839883C7F367F42 7F447F4582107AFA7AFD7B087B037B047B157B0A7B2B7B0F7B477B387B2A7B19 7B2E7B317B207B257B247B337B3E7B1E7B587B5A7B457B757B4C7B5D7B607B6E 7B7B7B627B727B717B907BA67BA77BB87BAC7B9D7BA87B857BAA7B9C7BA27BAB 7BB47BD17BC17BCC7BDD7BDA7BE57BE67BEA7C0C7BFE7BFC7C0F7C167C0B0000 F4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007C1F7C2A7C267C387C417C4081FE82018202820481EC8844822182228223 822D822F8228822B8238823B82338234823E82448249824B824F825A825F8268 887E8885888888D888DF895E7F9D7F9F7FA77FAF7FB07FB27C7C65497C917C9D 7C9C7C9E7CA27CB27CBC7CBD7CC17CC77CCC7CCD7CC87CC57CD77CE8826E66A8 7FBF7FCE7FD57FE57FE17FE67FE97FEE7FF37CF87D777DA67DAE7E477E9B9EB8 9EB48D738D848D948D918DB18D678D6D8C478C49914A9150914E914F91640000 F5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009162916191709169916F917D917E917291749179918C91859190918D9191 91A291A391AA91AD91AE91AF91B591B491BA8C559E7E8DB88DEB8E058E598E69 8DB58DBF8DBC8DBA8DC48DD68DD78DDA8DDE8DCE8DCF8DDB8DC68DEC8DF78DF8 8DE38DF98DFB8DE48E098DFD8E148E1D8E1F8E2C8E2E8E238E2F8E3A8E408E39 8E358E3D8E318E498E418E428E518E528E4A8E708E768E7C8E6F8E748E858E8F 8E948E908E9C8E9E8C788C828C8A8C858C988C94659B89D689DE89DA89DC0000 F6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000089E589EB89EF8A3E8B26975396E996F396EF970697019708970F970E972A 972D9730973E9F809F839F859F869F879F889F899F8A9F8C9EFE9F0B9F0D96B9 96BC96BD96CE96D277BF96E0928E92AE92C8933E936A93CA938F943E946B9C7F 9C829C859C869C879C887A239C8B9C8E9C909C919C929C949C959C9A9C9B9C9E 9C9F9CA09CA19CA29CA39CA59CA69CA79CA89CA99CAB9CAD9CAE9CB09CB19CB2 9CB39CB49CB59CB69CB79CBA9CBB9CBC9CBD9CC49CC59CC69CC79CCA9CCB0000 F7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009CCC9CCD9CCE9CCF9CD09CD39CD49CD59CD79CD89CD99CDC9CDD9CDF9CE2 977C978597919792979497AF97AB97A397B297B49AB19AB09AB79E589AB69ABA 9ABC9AC19AC09AC59AC29ACB9ACC9AD19B459B439B479B499B489B4D9B5198E8 990D992E995599549ADF9AE19AE69AEF9AEB9AFB9AED9AF99B089B0F9B139B1F 9B239EBD9EBE7E3B9E829E879E889E8B9E9293D69E9D9E9F9EDB9EDC9EDD9EE0 9EDF9EE29EE99EE79EE59EEA9EEF9F229F2C9F2F9F399F379F3D9F3E9F440000 tcl8.6.5/library/encoding/cp1258.enc0000644000175000017500000000210311555560473016427 0ustar sergeisergei# Encoding file: cp1258, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 20AC0081201A0192201E20262020202102C62030008A20390152008D008E008F 009020182019201C201D20222013201402DC2122009A203A0153009D009E0178 00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF 00C000C100C2010200C400C500C600C700C800C900CA00CB030000CD00CE00CF 011000D1030900D300D401A000D600D700D800D900DA00DB00DC01AF030300DF 00E000E100E2010300E400E500E600E700E800E900EA00EB030100ED00EE00EF 011100F1032300F300F401A100F600F700F800F900FA00FB00FC01B020AB00FF tcl8.6.5/library/encoding/cp865.enc0000644000175000017500000000210211555560473016351 0ustar sergeisergei# Encoding file: cp865, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C700FC00E900E200E400E000E500E700EA00EB00E800EF00EE00EC00C400C5 00C900E600C600F400F600F200FB00F900FF00D600DC00F800A300D820A70192 00E100ED00F300FA00F100D100AA00BA00BF231000AC00BD00BC00A100AB00A4 259125922593250225242561256225562555256325512557255D255C255B2510 25142534252C251C2500253C255E255F255A25542569256625602550256C2567 2568256425652559255825522553256B256A2518250C25882584258C25902580 03B100DF039303C003A303C300B503C403A6039803A903B4221E03C603B52229 226100B1226522642320232100F7224800B0221900B7221A207F00B225A000A0 tcl8.6.5/library/encoding/macDingbats.enc0000644000175000017500000000211011555560473017717 0ustar sergeisergei# Encoding file: macDingbats, single-byte S 003F 1 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 00202701270227032704260E2706270727082709261B261E270C270D270E270F 2710271127122713271427152716271727182719271A271B271C271D271E271F 2720272127222723272427252726272726052729272A272B272C272D272E272F 2730273127322733273427352736273727382739273A273B273C273D273E273F 2740274127422743274427452746274727482749274A274B25CF274D25A0274F 27502751275225B225BC25C6275625D727582759275A275B275C275D275E007F F8D7F8D8F8D9F8DAF8DBF8DCF8DDF8DEF8DFF8E0F8E1F8E2F8E3F8E4008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 0000276127622763276427652766276726632666266526602460246124622463 2464246524662467246824692776277727782779277A277B277C277D277E277F 2780278127822783278427852786278727882789278A278B278C278D278E278F 2790279127922793279421922194219527982799279A279B279C279D279E279F 27A027A127A227A327A427A527A627A727A827A927AA27AB27AC27AD27AE27AF 000027B127B227B327B427B527B627B727B827B927BA27BB27BC27BD27BE0000 tcl8.6.5/library/encoding/koi8-r.enc0000644000175000017500000000210311555560473016616 0ustar sergeisergei# Encoding file: koi8-r, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 25002502250C251025142518251C2524252C2534253C258025842588258C2590 259125922593232025A02219221A22482264226500A0232100B000B200B700F7 25502551255204512553255425552556255725582559255A255B255C255D255E 255F25602561040125622563256425652566256725682569256A256B256C00A9 044E0430043104460434043504440433044504380439043A043B043C043D043E 043F044F044004410442044304360432044C044B04370448044D04490447044A 042E0410041104260414041504240413042504180419041A041B041C041D041E 041F042F042004210422042304160412042C042B04170428042D04290427042A tcl8.6.5/library/encoding/macUkraine.enc0000644000175000017500000000210711555560473017570 0ustar sergeisergei# Encoding file: macUkraine, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0410041104120413041404150416041704180419041A041B041C041D041E041F 0420042104220423042404250426042704280429042A042B042C042D042E042F 202000B0049000A300A7202200B6040600AE00A9212204020452226004030453 221E00B122642265045600B504910408040404540407045704090459040A045A 0458040500AC221A01922248220600AB00BB202600A0040B045B040C045C0455 20132014201C201D2018201900F7201E040E045E040F045F211604010451044F 0430043104320433043404350436043704380439043A043B043C043D043E043F 0440044104420443044404450446044704480449044A044B044C044D044E00A4 tcl8.6.5/library/encoding/macJapan.enc0000644000175000017500000013563411555560473017237 0ustar sergeisergei# Encoding file: macJapan, multi-byte M 003F 0 46 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00A0FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000A921222026 81 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 300030013002FF0CFF0E30FBFF1AFF1BFF1FFF01309B309C00B4FF4000A8FF3E 203EFF3F30FD30FE309D309E30034EDD30053006300730FC20142010FF0FFF3C 301C2016FF5C22EF202520182019201C201DFF08FF0930143015FF3BFF3DFF5B FF5D30083009300A300B300C300D300E300F30103011FF0B221200B100D70000 00F7FF1D2260FF1CFF1E22662267221E22342642264000B0203220332103FFE5 FF0400A200A3FF05FF03FF06FF0AFF2000A72606260525CB25CF25CE25C725C6 25A125A025B325B225BD25BC203B301221922190219121933013000000000000 000000000000000000000000000000002208220B2286228722822283222A2229 000000000000000000000000000000002227222800AC21D221D4220022030000 0000000000000000000000000000000000000000222022A52312220222072261 2252226A226B221A223D221D2235222B222C0000000000000000000000000000 212B2030266F266D266A2020202100B6000000000000000025EF000000000000 82 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000FF10 FF11FF12FF13FF14FF15FF16FF17FF18FF190000000000000000000000000000 FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2FFF30 FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3A000000000000000000000000 0000FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5A00000000000000003041 30423043304430453046304730483049304A304B304C304D304E304F30503051 30523053305430553056305730583059305A305B305C305D305E305F30603061 30623063306430653066306730683069306A306B306C306D306E306F30703071 30723073307430753076307730783079307A307B307C307D307E307F30803081 30823083308430853086308730883089308A308B308C308D308E308F30903091 3092309300000000000000000000000000000000000000000000000000000000 83 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 30A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF30B0 30B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF30C0 30C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF30D0 30D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF0000 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000391 03920393039403950396039703980399039A039B039C039D039E039F03A003A1 03A303A403A503A603A703A803A90000000000000000000000000000000003B1 03B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF03C003C1 03C303C403C503C603C703C803C9000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 84 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 04100411041204130414041504010416041704180419041A041B041C041D041E 041F0420042104220423042404250426042704280429042A042B042C042D042E 042F000000000000000000000000000000000000000000000000000000000000 04300431043204330434043504510436043704380439043A043B043C043D0000 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000002500 2502250C251025182514251C252C25242534253C25012503250F2513251B2517 25232533252B253B254B2520252F25282537253F251D25302525253825420000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 85 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 2460246124622463246424652466246724682469246A246B246C246D246E246F 2470247124722473000000000000000000000000000000000000000024742475 2476247724782479247A247B247C247D247E247F248024812482248324842485 2486248700000000000000000000000000000000000000002776277727780000 2779277A277B277C277D277E0000000000000000000000000000000000000000 0000F8A124882489248A248B248C248D248E248F249000000000000000002160 216121622163216421652166216721682169216A216BF8A2F8A3F8A400000000 0000000000002170217121722173217421752176217721782179217A217BF8A5 F8A6F8A700000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000249C249D249E249F24A0 24A124A224A324A424A524A624A724A824A924AA24AB24AC24AD24AE24AF24B0 24B124B224B324B424B500000000000000000000000000000000000000000000 86 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 339C339F339D33A033A4F8A833A133A5339E33A2338EF8A9338F33C433963397 F8AA339833B333B233B133B0210933D433CB3390338533863387F8AB00000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000211633CD2121F8AC2664 2667266126622660266326652666000000000000000000000000000000000000 0000000000003020260E30040000000000000000000000000000000000000000 0000000000000000000000000000261E261C261D261F21C621C421C5F8AD21E8 21E621E721E9F8AEF8AFF8B0F8B1000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 87 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3230322A322B322C322D322E322F32403237324232433239323A3231323E3234 3232323B323632333235323C323D323F32380000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000059275C0F32A432A532A632A732A832A93296329D3298329E63A732993349 3322334D3314331633053333334E330333363318331533273351334A33393357 330D334233233326333B332B00000000000000000000000000003300331E332A 3331334700000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000337E337D337C337B0000000000000000000000000000 0000000000000000000000000000000000000000337FF8B2F8B3000000000000 88 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 222E221F22BF0000000000000000000000000000000000000000000000000000 0000000000000000301DF8B40000000000000000000000000000000000000000 000000000000000000000000000000003094000030F730F830F930FA00000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000004E9C 55165A03963F54C0611B632859F690228475831C7A5060AA63E16E2565ED8466 82A69BF56893572765A162715B9B59D0867B98F47D627DBE9B8E62167C9F88B7 5B895EB563096697684895C7978D674F4EE54F0A4F4D4F9D504956F2593759D4 5A015C0960DF610F61706613690570BA754F757079FB7DAD7DEF80C3840E8863 8B029055907A533B4E954EA557DF80B290C178EF4E0058F16EA290387A328328 828B9C2F5141537054BD54E156E059FB5F1598F26DEB80E4852D000000000000 89 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9662967096A097FB540B53F35B8770CF7FBD8FC296E8536F9D5C7ABA4E117893 81FC6E26561855046B1D851A9C3B59E553A96D6674DC958F56424E91904B96F2 834F990C53E155B65B305F71662066F368046C386CF36D29745B76C87A4E9834 82F1885B8A6092ED6DB275AB76CA99C560A68B018D8A95B2698E53AD51860000 5712583059445BB45EF6602863A963F46CBF6F14708E7114715971D5733F7E01 827682D185979060925B9D1B586965BC6C5A752551F9592E59655F805FDC62BC 65FA6A2A6B276BB4738B7FC189569D2C9D0E9EC45CA16C96837B51045C4B61B6 81C6687672614E594FFA537860696E297A4F97F34E0B53164EEE4F554F3D4FA1 4F7352A053EF5609590F5AC15BB65BE179D16687679C67B66B4C6CB3706B73C2 798D79BE7A3C7B8782B182DB8304837783EF83D387668AB256298CA88FE6904E 971E868A4FC45CE862117259753B81E582BD86FE8CC096C5991399D54ECB4F1A 89E356DE584A58CA5EFB5FEB602A6094606261D0621262D06539000000000000 8A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9B41666668B06D777070754C76867D7582A587F9958B968E8C9D51F152BE5916 54B35BB35D16616869826DAF788D84CB88578A7293A79AB86D6C99A886D957A3 67FF86CE920E5283568754045ED362E164B9683C68386BBB737278BA7A6B899A 89D28D6B8F0390ED95A3969497695B665CB3697D984D984E639B7B206A2B0000 6A7F68B69C0D6F5F5272559D607062EC6D3B6E076ED1845B89108F444E149C39 53F6691B6A3A9784682A515C7AC384B291DC938C565B9D286822830584317CA5 520882C574E64E7E4F8351A05BD2520A52D852E75DFB559A582A59E65B8C5B98 5BDB5E725E7960A3611F616361BE63DB656267D1685368FA6B3E6B536C576F22 6F976F4574B0751876E3770B7AFF7BA17C217DE97F367FF0809D8266839E89B3 8ACC8CAB908494519593959195A2966597D3992882184E38542B5CB85DCC73A9 764C773C5CA97FEB8D0B96C19811985498584F014F0E5371559C566857FA5947 5B095BC45C905E0C5E7E5FCC63EE673A65D765E2671F68CB68C4000000000000 8B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A5F5E306BC56C176C7D757F79485B637A007D005FBD898F8A188CB48D778ECC 8F1D98E29A0E9B3C4E80507D510059935B9C622F628064EC6B3A72A075917947 7FA987FB8ABC8B7063AC83CA97A05409540355AB68546A588A70782767759ECD 53745BA2811A865090064E184E454EC74F1153CA54385BAE5F13602565510000 673D6C426C726CE3707874037A767AAE7B087D1A7CFE7D6665E7725B53BB5C45 5DE862D262E063196E20865A8A318DDD92F86F0179A69B5A4EA84EAB4EAC4F9B 4FA050D151477AF6517151F653545321537F53EB55AC58835CE15F375F4A602F 6050606D631F65596A4B6CC172C272ED77EF80F881058208854E90F793E197FF 99579A5A4EF051DD5C2D6681696D5C4066F26975738968507C8150C552E45747 5DFE932665A46B236B3D7434798179BD7B4B7DCA82B983CC887F895F8B398FD1 91D1541F92804E5D503653E5533A72D7739677E982E68EAF99C699C899D25177 611A865E55B07A7A50765BD3904796854E326ADB91E75C515C48000000000000 8C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 63987A9F6C9397748F617AAA718A96887C8268177E706851936C52F2541B85AB 8A137FA48ECD90E15366888879414FC250BE521151445553572D73EA578B5951 5F625F8460756176616761A963B2643A656C666F68426E1375667A3D7CFB7D4C 7D997E4B7F6B830E834A86CD8A088A638B668EFD981A9D8F82B88FCE9BE80000 5287621F64836FC09699684150916B206C7A6F547A747D5088408A2367084EF6 503950265065517C5238526355A7570F58055ACC5EFA61B261F862F36372691C 6A29727D72AC732E7814786F7D79770C80A9898B8B198CE28ED290639375967A 98559A139E785143539F53B35E7B5F266E1B6E90738473FE7D4382378A008AFA 96504E4E500B53E4547C56FA59D15B645DF15EAB5F276238654567AF6E5672D0 7CCA88B480A180E183F0864E8A878DE8923796C798679F134E944E924F0D5348 5449543E5A2F5F8C5FA1609F68A76A8E745A78818A9E8AA48B7791904E5E9BC9 4EA44F7C4FAF501950165149516C529F52B952FE539A53E35411000000000000 8D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 540E5589575157A2597D5B545B5D5B8F5DE55DE75DF75E785E835E9A5EB75F18 6052614C629762D863A7653B6602664366F4676D6821689769CB6C5F6D2A6D69 6E2F6E9D75327687786C7A3F7CE07D057D187D5E7DB18015800380AF80B18154 818F822A8352884C88618B1B8CA28CFC90CA91759271783F92FC95A4964D0000 980599999AD89D3B525B52AB53F7540858D562F76FE08C6A8F5F9EB9514B523B 544A56FD7A4091779D609ED273446F09817075115FFD60DA9AA872DB8FBC6B64 98034ECA56F0576458BE5A5A606861C7660F6606683968B16DF775D57D3A826E 9B424E9B4F5053C955065D6F5DE65DEE67FB6C99747378028A50939688DF5750 5EA7632B50B550AC518D670054C9585E59BB5BB05F69624D63A1683D6B736E08 707D91C7728078157826796D658E7D3083DC88C18F09969B5264572867507F6A 8CA151B45742962A583A698A80B454B25D0E57FC78959DFA4F5C524A548B643E 6628671467F57A847B567D22932F685C9BAD7B395319518A5237000000000000 8E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5BDF62F664AE64E6672D6BBA85A996D176909BD6634C93069BAB76BF66524E09 509853C25C7160E864926563685F71E673CA75237B977E8286958B838CDB9178 991065AC66AB6B8B4ED54ED44F3A4F7F523A53F853F255E356DB58EB59CB59C9 59FF5B505C4D5E025E2B5FD7601D6307652F5B5C65AF65BD65E8679D6B620000 6B7B6C0F7345794979C17CF87D197D2B80A2810281F389968A5E8A698A668A8C 8AEE8CC78CDC96CC98FC6B6F4E8B4F3C4F8D51505B575BFA6148630166426B21 6ECB6CBB723E74BD75D478C1793A800C803381EA84948F9E6C509E7F5F0F8B58 9D2B7AFA8EF85B8D96EB4E0353F157F759315AC95BA460896E7F6F0675BE8CEA 5B9F85007BE0507267F4829D5C61854A7E1E820E51995C0463688D66659C716E 793E7D1780058B1D8ECA906E86C790AA501F52FA5C3A6753707C7235914C91C8 932B82E55BC25F3160F94E3B53D65B88624B67316B8A72E973E07A2E816B8DA3 91529996511253D7546A5BFF63886A397DAC970056DA53CE5468000000000000 8F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5B975C315DDE4FEE610162FE6D3279C079CB7D427E4D7FD281ED821F84908846 89728B908E748F2F9031914B916C96C6919C4EC04F4F514553415F93620E67D4 6C416E0B73637E2691CD928353D459195BBF6DD1795D7E2E7C9B587E719F51FA 88538FF04FCA5CFB662577AC7AE3821C99FF51C65FAA65EC696F6B896DF30000 6E966F6476FE7D145DE190759187980651E6521D6240669166D96E1A5EB67DD2 7F7266F885AF85F78AF852A953D959735E8F5F90605592E4966450B7511F52DD 5320534753EC54E8554655315617596859BE5A3C5BB55C065C0F5C115C1A5E84 5E8A5EE05F70627F628462DB638C63776607660C662D6676677E68A26A1F6A35 6CBC6D886E096E58713C7126716775C77701785D7901796579F07AE07B117CA7 7D39809683D6848B8549885D88F38A1F8A3C8A548A738C618CDE91A49266937E 9418969C97984E0A4E084E1E4E575197527057CE583458CC5B225E3860C564FE 676167566D4472B675737A6384B88B7291B89320563157F498FE000000000000 90 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 62ED690D6B9671ED7E548077827289E698DF87558FB15C3B4F384FE14FB55507 5A205BDD5BE95FC3614E632F65B0664B68EE699B6D786DF1753375B9771F795E 79E67D3381E382AF85AA89AA8A3A8EAB8F9B903291DD97074EBA4EC152035875 58EC5C0B751A5C3D814E8A0A8FC59663976D7B258ACF9808916256F353A80000 9017543957825E2563A86C34708A77617C8B7FE088709042915493109318968F 745E9AC45D075D69657067A28DA896DB636E6749691983C5981796C088FE6F84 647A5BF84E16702C755D662F51C4523652E259D35F8160276210653F6574661F 667468F268166B636E057272751F76DB7CBE805658F088FD897F8AA08A938ACB 901D91929752975965897A0E810696BB5E2D60DC621A65A56614679077F37A4D 7C4D7E3E810A8CAC8D648DE18E5F78A9520762D963A5644262988A2D7A837BC0 8AAC96EA7D76820C87494ED95148534353605BA35C025C165DDD6226624764B0 681368346CC96D456D1767D36F5C714E717D65CB7A7F7BAD7DDA000000000000 91 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7E4A7FA8817A821B823985A68A6E8CCE8DF59078907792AD929195839BAE524D 55846F387136516879857E5581B37CCE564C58515CA863AA66FE66FD695A72D9 758F758E790E795679DF7C977D207D4486078A34963B90619F2050E7527553CC 53E2500955AA58EE594F723D5B8B5C64531D60E360F3635C6383633F63BB0000 64CD65E966F95DE369CD69FD6F1571E54E8975E976F87A937CDF7DCF7D9C8061 83498358846C84BC85FB88C58D709001906D9397971C9A1250CF5897618E81D3 85358D0890204FC3507452475373606F6349675F6E2C8DB3901F4FD75C5E8CCA 65CF7D9A53528896517663C35B585B6B5C0A640D6751905C4ED6591A592A6C70 8A51553E581559A560F0625367C182356955964099C49A284F5358065BFE8010 5CB15E2F5F856020614B623466FF6CF06EDE80CE817F82D4888B8CB89000902E 968A9EDB9BDB4EE353F059277B2C918D984C9DF96EDD7027535355445B856258 629E62D36CA26FEF74228A1794386FC18AFE833851E786F853EA000000000000 92 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 53E94F4690548FB0596A81315DFD7AEA8FBF68DA8C3772F89C486A3D8AB04E39 53585606576662C563A265E66B4E6DE16E5B70AD77ED7AEF7BAA7DBB803D80C6 86CB8A95935B56E358C75F3E65AD66966A806BB575378AC7502477E557305F1B 6065667A6C6075F47A1A7F6E81F48718904599B37BC9755C7AF97B5184C40000 901079E97A9283365AE177404E2D4EF25B995FE062BD663C67F16CE8866B8877 8A3B914E92F399D06A177026732A82E784578CAF4E01514651CB558B5BF55E16 5E335E815F145F355F6B5FB461F2631166A2671D6F6E7252753A773A80748139 817887768ABF8ADC8D858DF3929A957798029CE552C5635776F467156C8873CD 8CC393AE96736D25589C690E69CC8FFD939A75DB901A585A680263B469FB4F43 6F2C67D88FBB85267DB49354693F6F70576A58F75B2C7D2C722A540A91E39DB4 4EAD4F4E505C507552438C9E544858245B9A5E1D5E955EAD5EF75F1F608C62B5 633A63D068AF6C407887798E7A0B7DE082478A028AE68E449013000000000000 93 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 90B8912D91D89F0E6CE5645864E265756EF476847B1B906993D16EBA54F25FB9 64A48F4D8FED92445178586B59295C555E976DFB7E8F751C8CBC8EE2985B70B9 4F1D6BBF6FB1753096FB514E54105835585759AC5C605F926597675C6E21767B 83DF8CED901490FD934D7825783A52AA5EA6571F597460125012515A51AC0000 51CD520055105854585859575B955CF65D8B60BC6295642D6771684368BC68DF 76D76DD86E6F6D9B706F71C85F5375D879777B497B547B527CD67D7152308463 856985E48A0E8B048C468E0F9003900F94199676982D9A3095D850CD52D5540C 58025C0E61A7649E6D1E77B37AE580F48404905392855CE09D07533F5F975FB3 6D9C7279776379BF7BE46BD272EC8AAD68036A6151F87A8169345C4A9CF682EB 5BC59149701E56785C6F60C765666C8C8C5A90419813545166C7920D594890A3 51854E4D51EA85998B0E7058637A934B696299B47E047577535769608EDF96E3 6C5D4E8C5C3C5F108FE953028CD1808986795EFF65E54E735165000000000000 94 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 59825C3F97EE4EFB598A5FCD8A8D6FE179B079625BE78471732B71B15E745FF5 637B649A71C37C984E435EFC4E4B57DC56A260A96FC37D0D80FD813381BF8FB2 899786A45DF4628A64AD898767776CE26D3E743678345A467F7582AD99AC4FF3 5EC362DD63926557676F76C3724C80CC80BA8F29914D500D57F95A9268850000 6973716472FD8CB758F28CE0966A9019877F79E477E784294F2F5265535A62CD 67CF6CCA767D7B947C95823685848FEB66DD6F2072067E1B83AB99C19EA651FD 7BB178727BB880877B486AE85E61808C75517560516B92626E8C767A91979AEA 4F107F70629C7B4F95A59CE9567A585986E496BC4F345224534A53CD53DB5E06 642C6591677F6C3E6C4E724872AF73ED75547E41822C85E98CA97BC491C67169 981298EF633D6669756A76E478D0854386EE532A5351542659835E875F7C60B2 6249627962AB65906BD46CCC75B276AE789179D87DCB7F7780A588AB8AB98CBB 907F975E98DB6A0B7C3850995C3E5FAE67876BD8743577097F8E000000000000 95 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9F3B67CA7A175339758B9AED5F66819D83F180985F3C5FC575627B46903C6867 59EB5A9B7D10767E8B2C4FF55F6A6A196C376F0274E2796888688A558C795EDF 63CF75C579D282D7932892F2849C86ED9C2D54C15F6C658C6D5C70158CA78CD3 983B654F74F64E0D4ED857E0592B5A665BCC51A85E035E9C6016627665770000 65A7666E6D6E72367B268150819A82998B5C8CA08CE68D74961C96444FAE64AB 6B66821E8461856A90E85C01695398A8847A85574F0F526F5FA95E45670D798F 8179890789866DF55F1762556CB84ECF72699B925206543B567458B361A4626E 711A596E7C897CDE7D1B96F06587805E4E194F75517558405E635E735F0A67C4 4E26853D9589965B7C73980150FB58C1765678A7522577A585117B86504F5909 72477BC77DE88FBA8FD4904D4FBF52C95A295F0197AD4FDD821792EA57036355 6B69752B88DC8F147A4252DF58936155620A66AE6BCD7C3F83E950234FF85305 5446583159495B9D5CF05CEF5D295E9662B16367653E65B9670B000000000000 96 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6CD56CE170F978327E2B80DE82B3840C84EC870289128A2A8C4A90A692D298FD 9CF39D6C4E4F4EA1508D5256574A59A85E3D5FD85FD9623F66B4671B67D068D2 51927D2180AA81A88B008C8C8CBF927E96325420982C531750D5535C58A864B2 6734726777667A4691E652C36CA16B8658005E4C5954672C7FFB51E176C60000 646978E89B549EBB57CB59B96627679A6BCE54E969D95E55819C67959BAA67FE 9C52685D4EA64FE353C862B9672B6CAB8FC44FAD7E6D9EBF4E0761626E806F2B 85135473672A9B455DF37B955CAC5BC6871C6E4A84D17A14810859997C8D6C11 772052D959227121725F77DB97279D61690B5A7F5A1851A5540D547D660E76DF 8FF792989CF459EA725D6EC5514D68C97DBF7DEC97629EBA64786A2183025984 5B5F6BDB731B76F27DB280178499513267289ED976EE676252FF99055C24623B 7C7E8CB0554F60B67D0B958053014E5F51B6591C723A803691CE5F2577E25384 5F797D0485AC8A338E8D975667F385AE9453610961086CB97652000000000000 97 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8AED8F38552F4F51512A52C753CB5BA55E7D60A0618263D6670967DA6E676D8C 733673377531795088D58A98904A909190F596C4878D59154E884F594E0E8A89 8F3F981050AD5E7C59965BB95EB863DA63FA64C166DC694A69D86D0B6EB67194 75287AAF7F8A8000844984C989818B218E0A9065967D990A617E62916B320000 6C836D747FCC7FFC6DC07F8587BA88F8676583B1983C96F76D1B7D61843D916A 4E7153755D506B046FEB85CD862D89A75229540F5C65674E68A87406748375E2 88CF88E191CC96E296785F8B73877ACB844E63A0756552896D416E9C74097559 786B7C9296867ADC9F8D4FB6616E65C5865C4E864EAE50DA4E2151CC5BEE6599 68816DBC731F764277AD7A1C7CE7826F8AD2907C91CF96759818529B7DD1502B 539867976DCB71D0743381E88F2A96A39C579E9F746058416D997D2F985E4EE4 4F364F8B51B752B15DBA601C73B2793C82D3923496B796F6970A9E979F6266A6 6B74521752A370C888C25EC9604B61906F2371497C3E7DF4806F000000000000 98 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 84EE9023932C54429B6F6AD370898CC28DEF973252B45A415ECA5F046717697C 69946D6A6F0F726272FC7BED8001807E874B90CE516D9E937984808B93328AD6 502D548C8A716B6A8CC4810760D167A09DF24E994E989C108A6B85C185686900 6E7E789781550000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000005F0C 4E104E154E2A4E314E364E3C4E3F4E424E564E584E824E858C6B4E8A82125F0D 4E8E4E9E4E9F4EA04EA24EB04EB34EB64ECE4ECD4EC44EC64EC24ED74EDE4EED 4EDF4EF74F094F5A4F304F5B4F5D4F574F474F764F884F8F4F984F7B4F694F70 4F914F6F4F864F9651184FD44FDF4FCE4FD84FDB4FD14FDA4FD04FE44FE5501A 50285014502A502550054F1C4FF650215029502C4FFE4FEF5011500650435047 6703505550505048505A5056506C50785080509A508550B450B2000000000000 99 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 50C950CA50B350C250D650DE50E550ED50E350EE50F950F55109510151025116 51155114511A5121513A5137513C513B513F51405152514C515451627AF85169 516A516E5180518256D8518C5189518F519151935195519651A451A651A251A9 51AA51AB51B351B151B251B051B551BD51C551C951DB51E0865551E951ED0000 51F051F551FE5204520B5214520E5227522A522E52335239524F5244524B524C 525E5254526A527452695273527F527D528D529452925271528852918FA88FA7 52AC52AD52BC52B552C152CD52D752DE52E352E698ED52E052F352F552F852F9 530653087538530D5310530F5315531A5323532F533153335338534053465345 4E175349534D51D6535E5369536E5918537B53775382539653A053A653A553AE 53B053B653C37C1296D953DF66FC71EE53EE53E853ED53FA5401543D5440542C 542D543C542E54365429541D544E548F5475548E545F5471547754705492547B 5480547654845490548654C754A254B854A554AC54C454C854A8000000000000 9A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54AB54C254A454BE54BC54D854E554E6550F551454FD54EE54ED54FA54E25539 55405563554C552E555C55455556555755385533555D5599558054AF558A559F 557B557E5598559E55AE557C558355A9558755A855DA55C555DF55C455DC55E4 55D4561455F7561655FE55FD561B55F9564E565071DF56345636563256380000 566B5664562F566C566A56865680568A56A05694568F56A556AE56B656B456C2 56BC56C156C356C056C856CE56D156D356D756EE56F9570056FF570457095708 570B570D57135718571655C7571C572657375738574E573B5740574F576957C0 57885761577F5789579357A057B357A457AA57B057C357C657D457D257D3580A 57D657E3580B5819581D587258215862584B58706BC05852583D5879588558B9 589F58AB58BA58DE58BB58B858AE58C558D358D158D758D958D858E558DC58E4 58DF58EF58FA58F958FB58FC58FD5902590A5910591B68A65925592C592D5932 5938593E7AD259555950594E595A5958596259605967596C5969000000000000 9B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 59785981599D4F5E4FAB59A359B259C659E859DC598D59D959DA5A255A1F5A11 5A1C5A095A1A5A405A6C5A495A355A365A625A6A5A9A5ABC5ABE5ACB5AC25ABD 5AE35AD75AE65AE95AD65AFA5AFB5B0C5B0B5B165B325AD05B2A5B365B3E5B43 5B455B405B515B555B5A5B5B5B655B695B705B735B755B7865885B7A5B800000 5B835BA65BB85BC35BC75BC95BD45BD05BE45BE65BE25BDE5BE55BEB5BF05BF6 5BF35C055C075C085C0D5C135C205C225C285C385C395C415C465C4E5C535C50 5C4F5B715C6C5C6E4E625C765C795C8C5C915C94599B5CAB5CBB5CB65CBC5CB7 5CC55CBE5CC75CD95CE95CFD5CFA5CED5D8C5CEA5D0B5D155D175D5C5D1F5D1B 5D115D145D225D1A5D195D185D4C5D525D4E5D4B5D6C5D735D765D875D845D82 5DA25D9D5DAC5DAE5DBD5D905DB75DBC5DC95DCD5DD35DD25DD65DDB5DEB5DF2 5DF55E0B5E1A5E195E115E1B5E365E375E445E435E405E4E5E575E545E5F5E62 5E645E475E755E765E7A9EBC5E7F5EA05EC15EC25EC85ED05ECF000000000000 9C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5ED65EE35EDD5EDA5EDB5EE25EE15EE85EE95EEC5EF15EF35EF05EF45EF85EFE 5F035F095F5D5F5C5F0B5F115F165F295F2D5F385F415F485F4C5F4E5F2F5F51 5F565F575F595F615F6D5F735F775F835F825F7F5F8A5F885F915F875F9E5F99 5F985FA05FA85FAD5FBC5FD65FFB5FE45FF85FF15FDD60B35FFF602160600000 601960106029600E6031601B6015602B6026600F603A605A6041606A6077605F 604A6046604D6063604360646042606C606B60596081608D60E76083609A6084 609B60966097609260A7608B60E160B860E060D360B45FF060BD60C660B560D8 614D6115610660F660F7610060F460FA6103612160FB60F1610D610E6147613E 61286127614A613F613C612C6134613D614261446173617761586159615A616B 6174616F61656171615F615D6153617561996196618761AC6194619A618A6191 61AB61AE61CC61CA61C961F761C861C361C661BA61CB7F7961CD61E661E361F6 61FA61F461FF61FD61FC61FE620062086209620D620C6214621B000000000000 9D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 621E6221622A622E6230623262336241624E625E6263625B62606268627C6282 6289627E62926293629662D46283629462D762D162BB62CF62FF62C664D462C8 62DC62CC62CA62C262C7629B62C9630C62EE62F163276302630862EF62F56350 633E634D641C634F6396638E638063AB637663A3638F6389639F63B5636B0000 636963BE63E963C063C663E363C963D263F663C4641664346406641364266436 651D64176428640F6467646F6476644E652A6495649364A564A9648864BC64DA 64D264C564C764BB64D864C264F164E7820964E064E162AC64E364EF652C64F6 64F464F264FA650064FD6518651C650565246523652B65346535653765366538 754B654865566555654D6558655E655D65726578658265838B8A659B659F65AB 65B765C365C665C165C465CC65D265DB65D965E065E165F16772660A660365FB 6773663566366634661C664F664466496641665E665D666466676668665F6662 667066836688668E668966846698669D66C166B966C966BE66BC000000000000 9E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 66C466B866D666DA66E0663F66E666E966F066F566F7670F6716671E67266727 9738672E673F67366741673867376746675E67606759676367646789677067A9 677C676A678C678B67A667A1678567B767EF67B467EC67B367E967B867E467DE 67DD67E267EE67B967CE67C667E76A9C681E684668296840684D6832684E0000 68B3682B685968636877687F689F688F68AD6894689D689B68836AAE68B96874 68B568A068BA690F688D687E690168CA690868D86922692668E1690C68CD68D4 68E768D569366912690468D768E3692568F968E068EF6928692A691A69236921 68C669796977695C6978696B6954697E696E69396974693D695969306961695E 695D6981696A69B269AE69D069BF69C169D369BE69CE5BE869CA69DD69BB69C3 69A76A2E699169A0699C699569B469DE69E86A026A1B69FF6B0A69F969F269E7 6A0569B16A1E69ED6A1469EB6A0A6A126AC16A236A136A446A0C6A726A366A78 6A476A626A596A666A486A386A226A906A8D6AA06A846AA26AA3000000000000 9F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A9786176ABB6AC36AC26AB86AB36AAC6ADE6AD16ADF6AAA6ADA6AEA6AFB6B05 86166AFA6B126B169B316B1F6B386B3776DC6B3998EE6B476B436B496B506B59 6B546B5B6B5F6B616B786B796B7F6B806B846B836B8D6B986B956B9E6BA46BAA 6BAB6BAF6BB26BB16BB36BB76BBC6BC66BCB6BD36BDF6BEC6BEB6BF36BEF0000 9EBE6C086C136C146C1B6C246C236C5E6C556C626C6A6C826C8D6C9A6C816C9B 6C7E6C686C736C926C906CC46CF16CD36CBD6CD76CC56CDD6CAE6CB16CBE6CBA 6CDB6CEF6CD96CEA6D1F884D6D366D2B6D3D6D386D196D356D336D126D0C6D63 6D936D646D5A6D796D596D8E6D956FE46D856DF96E156E0A6DB56DC76DE66DB8 6DC66DEC6DDE6DCC6DE86DD26DC56DFA6DD96DE46DD56DEA6DEE6E2D6E6E6E2E 6E196E726E5F6E3E6E236E6B6E2B6E766E4D6E1F6E436E3A6E4E6E246EFF6E1D 6E386E826EAA6E986EC96EB76ED36EBD6EAF6EC46EB26ED46ED56E8F6EA56EC2 6E9F6F416F11704C6EEC6EF86EFE6F3F6EF26F316EEF6F326ECC000000000000 E0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6F3E6F136EF76F866F7A6F786F816F806F6F6F5B6FF36F6D6F826F7C6F586F8E 6F916FC26F666FB36FA36FA16FA46FB96FC66FAA6FDF6FD56FEC6FD46FD86FF1 6FEE6FDB7009700B6FFA70117001700F6FFE701B701A6F74701D7018701F7030 703E7032705170637099709270AF70F170AC70B870B370AE70DF70CB70DD0000 70D9710970FD711C711971657155718871667162714C7156716C718F71FB7184 719571A871AC71D771B971BE71D271C971D471CE71E071EC71E771F571FC71F9 71FF720D7210721B7228722D722C72307232723B723C723F72407246724B7258 7274727E7282728172877292729672A272A772B972B272C372C672C472CE72D2 72E272E072E172F972F7500F7317730A731C7316731D7334732F73297325733E 734E734F9ED87357736A7368737073787375737B737A73C873B373CE73BB73C0 73E573EE73DE74A27405746F742573F87432743A7455743F745F74597441745C 746974707463746A7476747E748B749E74A774CA74CF74D473F1000000000000 E1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 74E074E374E774E974EE74F274F074F174F874F7750475037505750C750E750D 75157513751E7526752C753C7544754D754A7549755B7546755A756975647567 756B756D75787576758675877574758A758975827594759A759D75A575A375C2 75B375C375B575BD75B875BC75B175CD75CA75D275D975E375DE75FE75FF0000 75FC760175F075FA75F275F3760B760D7609761F762776207621762276247634 7630763B764776487646765C76587661766276687669766A7667766C76707672 76767678767C768076837688768B768E769676937699769A76B076B476B876B9 76BA76C276CD76D676D276DE76E176E576E776EA862F76FB7708770777047729 7724771E77257726771B773777387747775A7768776B775B7765777F777E7779 778E778B779177A0779E77B077B677B977BF77BC77BD77BB77C777CD77D777DA 77DC77E377EE77FC780C781279267820792A7845788E78747886787C789A788C 78A378B578AA78AF78D178C678CB78D478BE78BC78C578CA78EC000000000000 E2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 78E778DA78FD78F47907791279117919792C792B794079607957795F795A7955 7953797A797F798A799D79A79F4B79AA79AE79B379B979BA79C979D579E779EC 79E179E37A087A0D7A187A197A207A1F79807A317A3B7A3E7A377A437A577A49 7A617A627A699F9D7A707A797A7D7A887A977A957A987A967AA97AC87AB00000 7AB67AC57AC47ABF90837AC77ACA7ACD7ACF7AD57AD37AD97ADA7ADD7AE17AE2 7AE67AED7AF07B027B0F7B0A7B067B337B187B197B1E7B357B287B367B507B7A 7B047B4D7B0B7B4C7B457B757B657B747B677B707B717B6C7B6E7B9D7B987B9F 7B8D7B9C7B9A7B8B7B927B8F7B5D7B997BCB7BC17BCC7BCF7BB47BC67BDD7BE9 7C117C147BE67BE57C607C007C077C137BF37BF77C177C0D7BF67C237C277C2A 7C1F7C377C2B7C3D7C4C7C437C547C4F7C407C507C587C5F7C647C567C657C6C 7C757C837C907CA47CAD7CA27CAB7CA17CA87CB37CB27CB17CAE7CB97CBD7CC0 7CC57CC27CD87CD27CDC7CE29B3B7CEF7CF27CF47CF67CFA7D06000000000000 E3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7D027D1C7D157D0A7D457D4B7D2E7D327D3F7D357D467D737D567D4E7D727D68 7D6E7D4F7D637D937D897D5B7D8F7D7D7D9B7DBA7DAE7DA37DB57DC77DBD7DAB 7E3D7DA27DAF7DDC7DB87D9F7DB07DD87DDD7DE47DDE7DFB7DF27DE17E057E0A 7E237E217E127E317E1F7E097E0B7E227E467E667E3B7E357E397E437E370000 7E327E3A7E677E5D7E567E5E7E597E5A7E797E6A7E697E7C7E7B7E837DD57E7D 8FAE7E7F7E887E897E8C7E927E907E937E947E967E8E7E9B7E9C7F387F3A7F45 7F4C7F4D7F4E7F507F517F557F547F587F5F7F607F687F697F677F787F827F86 7F837F887F877F8C7F947F9E7F9D7F9A7FA37FAF7FB27FB97FAE7FB67FB88B71 7FC57FC67FCA7FD57FD47FE17FE67FE97FF37FF998DC80068004800B80128018 8019801C80218028803F803B804A804680528058805A805F8062806880738072 807080768079807D807F808480868085809B8093809A80AD519080AC80DB80E5 80D980DD80C480DA80D6810980EF80F1811B81298123812F814B000000000000 E4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 968B8146813E8153815180FC8171816E81658166817481838188818A81808182 81A0819581A481A3815F819381A981B081B581BE81B881BD81C081C281BA81C9 81CD81D181D981D881C881DA81DF81E081E781FA81FB81FE8201820282058207 820A820D821082168229822B82388233824082598258825D825A825F82640000 82628268826A826B822E827182778278827E828D829282AB829F82BB82AC82E1 82E382DF82D282F482F382FA8393830382FB82F982DE830682DC830982D98335 83348316833283318340833983508345832F832B831783188385839A83AA839F 83A283968323838E8387838A837C83B58373837583A0838983A883F4841383EB 83CE83FD840383D8840B83C183F7840783E083F2840D8422842083BD84388506 83FB846D842A843C855A84848477846B84AD846E848284698446842C846F8479 843584CA846284B984BF849F84D984CD84BB84DA84D084C184C684D684A18521 84FF84F485178518852C851F8515851484FC8540856385588548000000000000 E5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 85418602854B8555858085A485888591858A85A8856D8594859B85EA8587859C 8577857E859085C985BA85CF85B985D085D585DD85E585DC85F9860A8613860B 85FE85FA86068622861A8630863F864D4E558654865F86678671869386A386A9 86AA868B868C86B686AF86C486C686B086C9882386AB86D486DE86E986EC0000 86DF86DB86EF8712870687088700870386FB87118709870D86F9870A8734873F 8737873B87258729871A8760875F8778874C874E877487578768876E87598753 8763876A880587A2879F878287AF87CB87BD87C087D096D687AB87C487B387C7 87C687BB87EF87F287E0880F880D87FE87F687F7880E87D28811881688158822 88218831883688398827883B8844884288528859885E8862886B8881887E889E 8875887D88B5887288828897889288AE889988A2888D88A488B088BF88B188C3 88C488D488D888D988DD88F9890288FC88F488E888F28904890C890A89138943 891E8925892A892B89418944893B89368938894C891D8960895E000000000000 E6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 89668964896D896A896F89748977897E89838988898A8993899889A189A989A6 89AC89AF89B289BA89BD89BF89C089DA89DC89DD89E789F489F88A038A168A10 8A0C8A1B8A1D8A258A368A418A5B8A528A468A488A7C8A6D8A6C8A628A858A82 8A848AA88AA18A918AA58AA68A9A8AA38AC48ACD8AC28ADA8AEB8AF38AE70000 8AE48AF18B148AE08AE28AF78ADE8ADB8B0C8B078B1A8AE18B168B108B178B20 8B3397AB8B268B2B8B3E8B288B418B4C8B4F8B4E8B498B568B5B8B5A8B6B8B5F 8B6C8B6F8B748B7D8B808B8C8B8E8B928B938B968B998B9A8C3A8C418C3F8C48 8C4C8C4E8C508C558C628C6C8C788C7A8C828C898C858C8A8C8D8C8E8C948C7C 8C98621D8CAD8CAA8CBD8CB28CB38CAE8CB68CC88CC18CE48CE38CDA8CFD8CFA 8CFB8D048D058D0A8D078D0F8D0D8D109F4E8D138CCD8D148D168D678D6D8D71 8D738D818D998DC28DBE8DBA8DCF8DDA8DD68DCC8DDB8DCB8DEA8DEB8DDF8DE3 8DFC8E088E098DFF8E1D8E1E8E108E1F8E428E358E308E348E4A000000000000 E7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8E478E498E4C8E508E488E598E648E608E2A8E638E558E768E728E7C8E818E87 8E858E848E8B8E8A8E938E918E948E998EAA8EA18EAC8EB08EC68EB18EBE8EC5 8EC88ECB8EDB8EE38EFC8EFB8EEB8EFE8F0A8F058F158F128F198F138F1C8F1F 8F1B8F0C8F268F338F3B8F398F458F428F3E8F4C8F498F468F4E8F578F5C0000 8F628F638F648F9C8F9F8FA38FAD8FAF8FB78FDA8FE58FE28FEA8FEF90878FF4 90058FF98FFA901190159021900D901E9016900B90279036903590398FF8904F 905090519052900E9049903E90569058905E9068906F907696A890729082907D 90819080908A9089908F90A890AF90B190B590E290E4624890DB910291129119 91329130914A9156915891639165916991739172918B9189918291A291AB91AF 91AA91B591B491BA91C091C191C991CB91D091D691DF91E191DB91FC91F591F6 921E91FF9214922C92159211925E925792459249926492489295923F924B9250 929C92969293929B925A92CF92B992B792E9930F92FA9344932E000000000000 E8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 93199322931A9323933A9335933B935C9360937C936E935693B093AC93AD9394 93B993D693D793E893E593D893C393DD93D093C893E4941A9414941394039407 94109436942B94359421943A944194529444945B94609462945E946A92299470 94759477947D945A947C947E9481947F95829587958A95949596959895990000 95A095A895A795AD95BC95BB95B995BE95CA6FF695C395CD95CC95D595D495D6 95DC95E195E595E296219628962E962F9642964C964F964B9677965C965E965D 965F96669672966C968D96989695969796AA96A796B196B296B096B496B696B8 96B996CE96CB96C996CD894D96DC970D96D596F99704970697089713970E9711 970F971697199724972A97309739973D973E97449746974897429749975C9760 97649766976852D2976B977197799785977C9781977A9786978B978F9790979C 97A897A697A397B397B497C397C697C897CB97DC97ED9F4F97F27ADF97F697F5 980F980C9838982498219837983D9846984F984B986B986F9870000000000000 E9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 98719874987398AA98AF98B198B698C498C398C698E998EB9903990999129914 99189921991D991E99249920992C992E993D993E9942994999459950994B9951 9952994C99559997999899A599AD99AE99BC99DF99DB99DD99D899D199ED99EE 99F199F299FB99F89A019A0F9A0599E29A199A2B9A379A459A429A409A430000 9A3E9A559A4D9A5B9A579A5F9A629A659A649A699A6B9A6A9AAD9AB09ABC9AC0 9ACF9AD19AD39AD49ADE9ADF9AE29AE39AE69AEF9AEB9AEE9AF49AF19AF79AFB 9B069B189B1A9B1F9B229B239B259B279B289B299B2A9B2E9B2F9B329B449B43 9B4F9B4D9B4E9B519B589B749B939B839B919B969B979B9F9BA09BA89BB49BC0 9BCA9BB99BC69BCF9BD19BD29BE39BE29BE49BD49BE19C3A9BF29BF19BF09C15 9C149C099C139C0C9C069C089C129C0A9C049C2E9C1B9C259C249C219C309C47 9C329C469C3E9C5A9C609C679C769C789CE79CEC9CF09D099D089CEB9D039D06 9D2A9D269DAF9D239D1F9D449D159D129D419D3F9D3E9D469D48000000000000 EA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9D5D9D5E9D649D519D509D599D729D899D879DAB9D6F9D7A9D9A9DA49DA99DB2 9DC49DC19DBB9DB89DBA9DC69DCF9DC29DD99DD39DF89DE69DED9DEF9DFD9E1A 9E1B9E1E9E759E799E7D9E819E889E8B9E8C9E929E959E919E9D9EA59EA99EB8 9EAA9EAD97619ECC9ECE9ECF9ED09ED49EDC9EDE9EDD9EE09EE59EE89EEF0000 9EF49EF69EF79EF99EFB9EFC9EFD9F079F0876B79F159F219F2C9F3E9F4A9F52 9F549F639F5F9F609F619F669F679F6C9F6A9F779F729F769F959F9C9FA0582F 69C79059746451DC719900000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 EB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F8B5F8B60000000000000000000000000000000000000000000000000000 F8B7FE33000000000000000000000000000000000000F8B8FE31F8B900000000 F8BAF8BBF8BCF8BDFE300000000000000000FE35FE36FE39FE3AF8BEF8BFFE37 FE38FE3FFE40FE3DFE3EFE41FE42FE43FE44FE3BFE3C00000000000000000000 0000F8C000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 EC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000F8C1 0000F8C20000F8C30000F8C40000F8C500000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F8C600000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F8C70000F8C80000F8C9000000000000000000000000F8CA000000000000 0000000000000000000000000000000000000000000000000000000000000000 ED 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 F8CB0000F8CC0000F8CD0000F8CE0000F8CF0000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000F8D00000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000F8D10000F8D20000F8D3000000000000000000000000F8D40000 00000000000000000000F8D5F8D6000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 tcl8.6.5/library/encoding/cp1254.enc0000644000175000017500000000210311555560473016423 0ustar sergeisergei# Encoding file: cp1254, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 20AC0081201A0192201E20262020202102C62030016020390152008D008E008F 009020182019201C201D20222013201402DC21220161203A0153009D009E0178 00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF 00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF 011E00D100D200D300D400D500D600D700D800D900DA00DB00DC0130015E00DF 00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF 011F00F100F200F300F400F500F600F700F800F900FA00FB00FC0131015F00FF tcl8.6.5/library/encoding/cp1257.enc0000644000175000017500000000210311555560473016426 0ustar sergeisergei# Encoding file: cp1257, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 20AC0081201A0083201E20262020202100882030008A2039008C00A802C700B8 009020182019201C201D20222013201400982122009A203A009C00AF02DB009F 00A0000000A200A300A4000000A600A700D800A9015600AB00AC00AD00AE00C6 00B000B100B200B300B400B500B600B700F800B9015700BB00BC00BD00BE00E6 0104012E0100010600C400C501180112010C00C90179011601220136012A013B 01600143014500D3014C00D500D600D701720141015A016A00DC017B017D00DF 0105012F0101010700E400E501190113010D00E9017A011701230137012B013C 01610144014600F3014D00F500F600F701730142015B016B00FC017C017E02D9 tcl8.6.5/library/encoding/iso8859-13.enc0000644000175000017500000000210711555560473017062 0ustar sergeisergei# Encoding file: iso8859-13, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A0201D00A200A300A4201E00A600A700D800A9015600AB00AC00AD00AE00C6 00B000B100B200B3201C00B500B600B700F800B9015700BB00BC00BD00BE00E6 0104012E0100010600C400C501180112010C00C90179011601220136012A013B 01600143014500D3014C00D500D600D701720141015A016A00DC017B017D00DF 0105012F0101010700E400E501190113010D00E9017A011701230137012B013C 01610144014600F3014D00F500F600F701730142015B016B00FC017C017E2019 tcl8.6.5/library/encoding/cp936.enc0000644000175000017500000040263511555560473016367 0ustar sergeisergei# Encoding file: cp936, multi-byte M 003F 0 127 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 20AC000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 81 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E024E044E054E064E0F4E124E174E1F4E204E214E234E264E294E2E4E2F4E31 4E334E354E374E3C4E404E414E424E444E464E4A4E514E554E574E5A4E5B4E62 4E634E644E654E674E684E6A4E6B4E6C4E6D4E6E4E6F4E724E744E754E764E77 4E784E794E7A4E7B4E7C4E7D4E7F4E804E814E824E834E844E854E874E8A0000 4E904E964E974E994E9C4E9D4E9E4EA34EAA4EAF4EB04EB14EB44EB64EB74EB8 4EB94EBC4EBD4EBE4EC84ECC4ECF4ED04ED24EDA4EDB4EDC4EE04EE24EE64EE7 4EE94EED4EEE4EEF4EF14EF44EF84EF94EFA4EFC4EFE4F004F024F034F044F05 4F064F074F084F0B4F0C4F124F134F144F154F164F1C4F1D4F214F234F284F29 4F2C4F2D4F2E4F314F334F354F374F394F3B4F3E4F3F4F404F414F424F444F45 4F474F484F494F4A4F4B4F4C4F524F544F564F614F624F664F684F6A4F6B4F6D 4F6E4F714F724F754F774F784F794F7A4F7D4F804F814F824F854F864F874F8A 4F8C4F8E4F904F924F934F954F964F984F994F9A4F9C4F9E4F9F4FA14FA20000 82 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4FA44FAB4FAD4FB04FB14FB24FB34FB44FB64FB74FB84FB94FBA4FBB4FBC4FBD 4FBE4FC04FC14FC24FC64FC74FC84FC94FCB4FCC4FCD4FD24FD34FD44FD54FD6 4FD94FDB4FE04FE24FE44FE54FE74FEB4FEC4FF04FF24FF44FF54FF64FF74FF9 4FFB4FFC4FFD4FFF5000500150025003500450055006500750085009500A0000 500B500E501050115013501550165017501B501D501E50205022502350245027 502B502F5030503150325033503450355036503750385039503B503D503F5040 504150425044504550465049504A504B504D5050505150525053505450565057 50585059505B505D505E505F506050615062506350645066506750685069506A 506B506D506E506F50705071507250735074507550785079507A507C507D5081 508250835084508650875089508A508B508C508E508F50905091509250935094 50955096509750985099509A509B509C509D509E509F50A050A150A250A450A6 50AA50AB50AD50AE50AF50B050B150B350B450B550B650B750B850B950BC0000 83 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 50BD50BE50BF50C050C150C250C350C450C550C650C750C850C950CA50CB50CC 50CD50CE50D050D150D250D350D450D550D750D850D950DB50DC50DD50DE50DF 50E050E150E250E350E450E550E850E950EA50EB50EF50F050F150F250F450F6 50F750F850F950FA50FC50FD50FE50FF51005101510251035104510551080000 5109510A510C510D510E510F511051115113511451155116511751185119511A 511B511C511D511E511F512051225123512451255126512751285129512A512B 512C512D512E512F5130513151325133513451355136513751385139513A513B 513C513D513E51425147514A514C514E514F515051525153515751585159515B 515D515E515F5160516151635164516651675169516A516F5172517A517E517F 5183518451865187518A518B518E518F51905191519351945198519A519D519E 519F51A151A351A651A751A851A951AA51AD51AE51B451B851B951BA51BE51BF 51C151C251C351C551C851CA51CD51CE51D051D251D351D451D551D651D70000 84 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 51D851D951DA51DC51DE51DF51E251E351E551E651E751E851E951EA51EC51EE 51F151F251F451F751FE520452055209520B520C520F5210521352145215521C 521E521F522152225223522552265227522A522C522F5231523252345235523C 523E524452455246524752485249524B524E524F525252535255525752580000 5259525A525B525D525F526052625263526452665268526B526C526D526E5270 52715273527452755276527752785279527A527B527C527E5280528352845285 528652875289528A528B528C528D528E528F5291529252945295529652975298 5299529A529C52A452A552A652A752AE52AF52B052B452B552B652B752B852B9 52BA52BB52BC52BD52C052C152C252C452C552C652C852CA52CC52CD52CE52CF 52D152D352D452D552D752D952DA52DB52DC52DD52DE52E052E152E252E352E5 52E652E752E852E952EA52EB52EC52ED52EE52EF52F152F252F352F452F552F6 52F752F852FB52FC52FD530153025303530453075309530A530B530C530E0000 85 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 53115312531353145318531B531C531E531F532253245325532753285329532B 532C532D532F533053315332533353345335533653375338533C533D53405342 53445346534B534C534D5350535453585359535B535D53655368536A536C536D 537253765379537B537C537D537E53805381538353875388538A538E538F0000 53905391539253935394539653975399539B539C539E53A053A153A453A753AA 53AB53AC53AD53AF53B053B153B253B353B453B553B753B853B953BA53BC53BD 53BE53C053C353C453C553C653C753CE53CF53D053D253D353D553DA53DC53DD 53DE53E153E253E753F453FA53FE53FF5400540254055407540B541454185419 541A541C542254245425542A5430543354365437543A543D543F544154425444 544554475449544C544D544E544F5451545A545D545E545F5460546154635465 54675469546A546B546C546D546E546F547054745479547A547E547F54815483 5485548754885489548A548D5491549354975498549C549E549F54A054A10000 86 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54A254A554AE54B054B254B554B654B754B954BA54BC54BE54C354C554CA54CB 54D654D854DB54E054E154E254E354E454EB54EC54EF54F054F154F454F554F6 54F754F854F954FB54FE550055025503550455055508550A550B550C550D550E 5512551355155516551755185519551A551C551D551E551F5521552555260000 55285529552B552D553255345535553655385539553A553B553D554055425545 55475548554B554C554D554E554F5551555255535554555755585559555A555B 555D555E555F55605562556355685569556B556F557055715572557355745579 557A557D557F55855586558C558D558E559055925593559555965597559A559B 559E55A055A155A255A355A455A555A655A855A955AA55AB55AC55AD55AE55AF 55B055B255B455B655B855BA55BC55BF55C055C155C255C355C655C755C855CA 55CB55CE55CF55D055D555D755D855D955DA55DB55DE55E055E255E755E955ED 55EE55F055F155F455F655F855F955FA55FB55FC55FF56025603560456050000 87 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 56065607560A560B560D561056115612561356145615561656175619561A561C 561D5620562156225625562656285629562A562B562E562F5630563356355637 5638563A563C563D563E5640564156425643564456455646564756485649564A 564B564F565056515652565356555656565A565B565D565E565F566056610000 5663566556665667566D566E566F56705672567356745675567756785679567A 567D567E567F56805681568256835684568756885689568A568B568C568D5690 56915692569456955696569756985699569A569B569C569D569E569F56A056A1 56A256A456A556A656A756A856A956AA56AB56AC56AD56AE56B056B156B256B3 56B456B556B656B856B956BA56BB56BD56BE56BF56C056C156C256C356C456C5 56C656C756C856C956CB56CC56CD56CE56CF56D056D156D256D356D556D656D8 56D956DC56E356E556E656E756E856E956EA56EC56EE56EF56F256F356F656F7 56F856FB56FC57005701570257055707570B570C570D570E570F571057110000 88 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 57125713571457155716571757185719571A571B571D571E5720572157225724 572557265727572B5731573257345735573657375738573C573D573F57415743 57445745574657485749574B5752575357545755575657585759576257635765 5767576C576E5770577157725774577557785779577A577D577E577F57800000 5781578757885789578A578D578E578F57905791579457955796579757985799 579A579C579D579E579F57A557A857AA57AC57AF57B057B157B357B557B657B7 57B957BA57BB57BC57BD57BE57BF57C057C157C457C557C657C757C857C957CA 57CC57CD57D057D157D357D657D757DB57DC57DE57E157E257E357E557E657E7 57E857E957EA57EB57EC57EE57F057F157F257F357F557F657F757FB57FC57FE 57FF580158035804580558085809580A580C580E580F58105812581358145816 58175818581A581B581C581D581F5822582358255826582758285829582B582C 582D582E582F58315832583358345836583758385839583A583B583C583D0000 89 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 583E583F584058415842584358455846584758485849584A584B584E584F5850 585258535855585658575859585A585B585C585D585F58605861586258635864 5866586758685869586A586D586E586F58705871587258735874587558765877 58785879587A587B587C587D587F58825884588658875888588A588B588C0000 588D588E588F5890589158945895589658975898589B589C589D58A058A158A2 58A358A458A558A658A758AA58AB58AC58AD58AE58AF58B058B158B258B358B4 58B558B658B758B858B958BA58BB58BD58BE58BF58C058C258C358C458C658C7 58C858C958CA58CB58CC58CD58CE58CF58D058D258D358D458D658D758D858D9 58DA58DB58DC58DD58DE58DF58E058E158E258E358E558E658E758E858E958EA 58ED58EF58F158F258F458F558F758F858FA58FB58FC58FD58FE58FF59005901 59035905590659085909590A590B590C590E591059115912591359175918591B 591D591E592059215922592359265928592C59305932593359355936593B0000 8A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 593D593E593F5940594359455946594A594C594D5950595259535959595B595C 595D595E595F5961596359645966596759685969596A596B596C596D596E596F 59705971597259755977597A597B597C597E597F598059855989598B598C598E 598F59905991599459955998599A599B599C599D599F59A059A159A259A60000 59A759AC59AD59B059B159B359B459B559B659B759B859BA59BC59BD59BF59C0 59C159C259C359C459C559C759C859C959CC59CD59CE59CF59D559D659D959DB 59DE59DF59E059E159E259E459E659E759E959EA59EB59ED59EE59EF59F059F1 59F259F359F459F559F659F759F859FA59FC59FD59FE5A005A025A0A5A0B5A0D 5A0E5A0F5A105A125A145A155A165A175A195A1A5A1B5A1D5A1E5A215A225A24 5A265A275A285A2A5A2B5A2C5A2D5A2E5A2F5A305A335A355A375A385A395A3A 5A3B5A3D5A3E5A3F5A415A425A435A445A455A475A485A4B5A4C5A4D5A4E5A4F 5A505A515A525A535A545A565A575A585A595A5B5A5C5A5D5A5E5A5F5A600000 8B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5A615A635A645A655A665A685A695A6B5A6C5A6D5A6E5A6F5A705A715A725A73 5A785A795A7B5A7C5A7D5A7E5A805A815A825A835A845A855A865A875A885A89 5A8A5A8B5A8C5A8D5A8E5A8F5A905A915A935A945A955A965A975A985A995A9C 5A9D5A9E5A9F5AA05AA15AA25AA35AA45AA55AA65AA75AA85AA95AAB5AAC0000 5AAD5AAE5AAF5AB05AB15AB45AB65AB75AB95ABA5ABB5ABC5ABD5ABF5AC05AC3 5AC45AC55AC65AC75AC85ACA5ACB5ACD5ACE5ACF5AD05AD15AD35AD55AD75AD9 5ADA5ADB5ADD5ADE5ADF5AE25AE45AE55AE75AE85AEA5AEC5AED5AEE5AEF5AF0 5AF25AF35AF45AF55AF65AF75AF85AF95AFA5AFB5AFC5AFD5AFE5AFF5B005B01 5B025B035B045B055B065B075B085B0A5B0B5B0C5B0D5B0E5B0F5B105B115B12 5B135B145B155B185B195B1A5B1B5B1C5B1D5B1E5B1F5B205B215B225B235B24 5B255B265B275B285B295B2A5B2B5B2C5B2D5B2E5B2F5B305B315B335B355B36 5B385B395B3A5B3B5B3C5B3D5B3E5B3F5B415B425B435B445B455B465B470000 8C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5B485B495B4A5B4B5B4C5B4D5B4E5B4F5B525B565B5E5B605B615B675B685B6B 5B6D5B6E5B6F5B725B745B765B775B785B795B7B5B7C5B7E5B7F5B825B865B8A 5B8D5B8E5B905B915B925B945B965B9F5BA75BA85BA95BAC5BAD5BAE5BAF5BB1 5BB25BB75BBA5BBB5BBC5BC05BC15BC35BC85BC95BCA5BCB5BCD5BCE5BCF0000 5BD15BD45BD55BD65BD75BD85BD95BDA5BDB5BDC5BE05BE25BE35BE65BE75BE9 5BEA5BEB5BEC5BED5BEF5BF15BF25BF35BF45BF55BF65BF75BFD5BFE5C005C02 5C035C055C075C085C0B5C0C5C0D5C0E5C105C125C135C175C195C1B5C1E5C1F 5C205C215C235C265C285C295C2A5C2B5C2D5C2E5C2F5C305C325C335C355C36 5C375C435C445C465C475C4C5C4D5C525C535C545C565C575C585C5A5C5B5C5C 5C5D5C5F5C625C645C675C685C695C6A5C6B5C6C5C6D5C705C725C735C745C75 5C765C775C785C7B5C7C5C7D5C7E5C805C835C845C855C865C875C895C8A5C8B 5C8E5C8F5C925C935C955C9D5C9E5C9F5CA05CA15CA45CA55CA65CA75CA80000 8D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5CAA5CAE5CAF5CB05CB25CB45CB65CB95CBA5CBB5CBC5CBE5CC05CC25CC35CC5 5CC65CC75CC85CC95CCA5CCC5CCD5CCE5CCF5CD05CD15CD35CD45CD55CD65CD7 5CD85CDA5CDB5CDC5CDD5CDE5CDF5CE05CE25CE35CE75CE95CEB5CEC5CEE5CEF 5CF15CF25CF35CF45CF55CF65CF75CF85CF95CFA5CFC5CFD5CFE5CFF5D000000 5D015D045D055D085D095D0A5D0B5D0C5D0D5D0F5D105D115D125D135D155D17 5D185D195D1A5D1C5D1D5D1F5D205D215D225D235D255D285D2A5D2B5D2C5D2F 5D305D315D325D335D355D365D375D385D395D3A5D3B5D3C5D3F5D405D415D42 5D435D445D455D465D485D495D4D5D4E5D4F5D505D515D525D535D545D555D56 5D575D595D5A5D5C5D5E5D5F5D605D615D625D635D645D655D665D675D685D6A 5D6D5D6E5D705D715D725D735D755D765D775D785D795D7A5D7B5D7C5D7D5D7E 5D7F5D805D815D835D845D855D865D875D885D895D8A5D8B5D8C5D8D5D8E5D8F 5D905D915D925D935D945D955D965D975D985D9A5D9B5D9C5D9E5D9F5DA00000 8E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5DA15DA25DA35DA45DA55DA65DA75DA85DA95DAA5DAB5DAC5DAD5DAE5DAF5DB0 5DB15DB25DB35DB45DB55DB65DB85DB95DBA5DBB5DBC5DBD5DBE5DBF5DC05DC1 5DC25DC35DC45DC65DC75DC85DC95DCA5DCB5DCC5DCE5DCF5DD05DD15DD25DD3 5DD45DD55DD65DD75DD85DD95DDA5DDC5DDF5DE05DE35DE45DEA5DEC5DED0000 5DF05DF55DF65DF85DF95DFA5DFB5DFC5DFF5E005E045E075E095E0A5E0B5E0D 5E0E5E125E135E175E1E5E1F5E205E215E225E235E245E255E285E295E2A5E2B 5E2C5E2F5E305E325E335E345E355E365E395E3A5E3E5E3F5E405E415E435E46 5E475E485E495E4A5E4B5E4D5E4E5E4F5E505E515E525E535E565E575E585E59 5E5A5E5C5E5D5E5F5E605E635E645E655E665E675E685E695E6A5E6B5E6C5E6D 5E6E5E6F5E705E715E755E775E795E7E5E815E825E835E855E885E895E8C5E8D 5E8E5E925E985E9B5E9D5EA15EA25EA35EA45EA85EA95EAA5EAB5EAC5EAE5EAF 5EB05EB15EB25EB45EBA5EBB5EBC5EBD5EBF5EC05EC15EC25EC35EC45EC50000 8F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5EC65EC75EC85ECB5ECC5ECD5ECE5ECF5ED05ED45ED55ED75ED85ED95EDA5EDC 5EDD5EDE5EDF5EE05EE15EE25EE35EE45EE55EE65EE75EE95EEB5EEC5EED5EEE 5EEF5EF05EF15EF25EF35EF55EF85EF95EFB5EFC5EFD5F055F065F075F095F0C 5F0D5F0E5F105F125F145F165F195F1A5F1C5F1D5F1E5F215F225F235F240000 5F285F2B5F2C5F2E5F305F325F335F345F355F365F375F385F3B5F3D5F3E5F3F 5F415F425F435F445F455F465F475F485F495F4A5F4B5F4C5F4D5F4E5F4F5F51 5F545F595F5A5F5B5F5C5F5E5F5F5F605F635F655F675F685F6B5F6E5F6F5F72 5F745F755F765F785F7A5F7D5F7E5F7F5F835F865F8D5F8E5F8F5F915F935F94 5F965F9A5F9B5F9D5F9E5F9F5FA05FA25FA35FA45FA55FA65FA75FA95FAB5FAC 5FAF5FB05FB15FB25FB35FB45FB65FB85FB95FBA5FBB5FBE5FBF5FC05FC15FC2 5FC75FC85FCA5FCB5FCE5FD35FD45FD55FDA5FDB5FDC5FDE5FDF5FE25FE35FE5 5FE65FE85FE95FEC5FEF5FF05FF25FF35FF45FF65FF75FF95FFA5FFC60070000 90 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 60086009600B600C60106011601360176018601A601E601F602260236024602C 602D602E603060316032603360346036603760386039603A603D603E60406044 60456046604760486049604A604C604E604F605160536054605660576058605B 605C605E605F6060606160656066606E60716072607460756077607E60800000 608160826085608660876088608A608B608E608F609060916093609560976098 6099609C609E60A160A260A460A560A760A960AA60AE60B060B360B560B660B7 60B960BA60BD60BE60BF60C060C160C260C360C460C760C860C960CC60CD60CE 60CF60D060D260D360D460D660D760D960DB60DE60E160E260E360E460E560EA 60F160F260F560F760F860FB60FC60FD60FE60FF61026103610461056107610A 610B610C611061116112611361146116611761186119611B611C611D611E6121 6122612561286129612A612C612D612E612F6130613161326133613461356136 613761386139613A613B613C613D613E61406141614261436144614561460000 91 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 61476149614B614D614F61506152615361546156615761586159615A615B615C 615E615F6160616161636164616561666169616A616B616C616D616E616F6171 617261736174617661786179617A617B617C617D617E617F6180618161826183 618461856186618761886189618A618C618D618F619061916192619361950000 6196619761986199619A619B619C619E619F61A061A161A261A361A461A561A6 61AA61AB61AD61AE61AF61B061B161B261B361B461B561B661B861B961BA61BB 61BC61BD61BF61C061C161C361C461C561C661C761C961CC61CD61CE61CF61D0 61D361D561D661D761D861D961DA61DB61DC61DD61DE61DF61E061E161E261E3 61E461E561E761E861E961EA61EB61EC61ED61EE61EF61F061F161F261F361F4 61F661F761F861F961FA61FB61FC61FD61FE6200620162026203620462056207 6209621362146219621C621D621E622062236226622762286229622B622D622F 6230623162326235623662386239623A623B623C6242624462456246624A0000 92 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 624F62506255625662576259625A625C625D625E625F62606261626262646265 6268627162726274627562776278627A627B627D628162826283628562866287 6288628B628C628D628E628F629062946299629C629D629E62A362A662A762A9 62AA62AD62AE62AF62B062B262B362B462B662B762B862BA62BE62C062C10000 62C362CB62CF62D162D562DD62DE62E062E162E462EA62EB62F062F262F562F8 62F962FA62FB63006303630463056306630A630B630C630D630F631063126313 63146315631763186319631C632663276329632C632D632E6330633163336334 6335633663376338633B633C633E633F63406341634463476348634A63516352 635363546356635763586359635A635B635C635D63606364636563666368636A 636B636C636F6370637263736374637563786379637C637D637E637F63816383 638463856386638B638D639163936394639563976399639A639B639C639D639E 639F63A163A463A663AB63AF63B163B263B563B663B963BB63BD63BF63C00000 93 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 63C163C263C363C563C763C863CA63CB63CC63D163D363D463D563D763D863D9 63DA63DB63DC63DD63DF63E263E463E563E663E763E863EB63EC63EE63EF63F0 63F163F363F563F763F963FA63FB63FC63FE640364046406640764086409640A 640D640E6411641264156416641764186419641A641D641F6422642364240000 6425642764286429642B642E642F643064316432643364356436643764386439 643B643C643E6440644264436449644B644C644D644E644F6450645164536455 645664576459645A645B645C645D645F64606461646264636464646564666468 646A646B646C646E646F64706471647264736474647564766477647B647C647D 647E647F648064816483648664886489648A648B648C648D648E648F64906493 649464976498649A649B649C649D649F64A064A164A264A364A564A664A764A8 64AA64AB64AF64B164B264B364B464B664B964BB64BD64BE64BF64C164C364C4 64C664C764C864C964CA64CB64CC64CF64D164D364D464D564D664D964DA0000 94 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 64DB64DC64DD64DF64E064E164E364E564E764E864E964EA64EB64EC64ED64EE 64EF64F064F164F264F364F464F564F664F764F864F964FA64FB64FC64FD64FE 64FF65016502650365046505650665076508650A650B650C650D650E650F6510 6511651365146515651665176519651A651B651C651D651E651F652065210000 6522652365246526652765286529652A652C652D65306531653265336537653A 653C653D6540654165426543654465466547654A654B654D654E655065526553 655465576558655A655C655F6560656165646565656765686569656A656D656E 656F657165736575657665786579657A657B657C657D657E657F658065816582 658365846585658665886589658A658D658E658F65926594659565966598659A 659D659E65A065A265A365A665A865AA65AC65AE65B165B265B365B465B565B6 65B765B865BA65BB65BE65BF65C065C265C765C865C965CA65CD65D065D165D3 65D465D565D865D965DA65DB65DC65DD65DE65DF65E165E365E465EA65EB0000 95 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 65F265F365F465F565F865F965FB65FC65FD65FE65FF66016604660566076608 6609660B660D661066116612661666176618661A661B661C661E662166226623 662466266629662A662B662C662E663066326633663766386639663A663B663D 663F66406642664466456646664766486649664A664D664E6650665166580000 6659665B665C665D665E666066626663666566676669666A666B666C666D6671 66726673667566786679667B667C667D667F6680668166836685668666886689 668A668B668D668E668F6690669266936694669566986699669A669B669C669E 669F66A066A166A266A366A466A566A666A966AA66AB66AC66AD66AF66B066B1 66B266B366B566B666B766B866BA66BB66BC66BD66BF66C066C166C266C366C4 66C566C666C766C866C966CA66CB66CC66CD66CE66CF66D066D166D266D366D4 66D566D666D766D866DA66DE66DF66E066E166E266E366E466E566E766E866EA 66EB66EC66ED66EE66EF66F166F566F666F866FA66FB66FD6701670267030000 96 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6704670567066707670C670E670F671167126713671667186719671A671C671E 67206721672267236724672567276729672E6730673267336736673767386739 673B673C673E673F6741674467456747674A674B674D67526754675567576758 6759675A675B675D67626763676467666767676B676C676E6771677467760000 67786779677A677B677D678067826783678567866788678A678C678D678E678F 679167926793679467966799679B679F67A067A167A467A667A967AC67AE67B1 67B267B467B967BA67BB67BC67BD67BE67BF67C067C267C567C667C767C867C9 67CA67CB67CC67CD67CE67D567D667D767DB67DF67E167E367E467E667E767E8 67EA67EB67ED67EE67F267F567F667F767F867F967FA67FB67FC67FE68016802 680368046806680D681068126814681568186819681A681B681C681E681F6820 6822682368246825682668276828682B682C682D682E682F6830683168346835 6836683A683B683F6847684B684D684F68526856685768586859685A685B0000 97 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 685C685D685E685F686A686C686D686E686F6870687168726873687568786879 687A687B687C687D687E687F688068826884688768886889688A688B688C688D 688E68906891689268946895689668986899689A689B689C689D689E689F68A0 68A168A368A468A568A968AA68AB68AC68AE68B168B268B468B668B768B80000 68B968BA68BB68BC68BD68BE68BF68C168C368C468C568C668C768C868CA68CC 68CE68CF68D068D168D368D468D668D768D968DB68DC68DD68DE68DF68E168E2 68E468E568E668E768E868E968EA68EB68EC68ED68EF68F268F368F468F668F7 68F868FB68FD68FE68FF69006902690369046906690769086909690A690C690F 69116913691469156916691769186919691A691B691C691D691E692169226923 69256926692769286929692A692B692C692E692F693169326933693569366937 6938693A693B693C693E694069416943694469456946694769486949694A694B 694C694D694E694F69506951695269536955695669586959695B695C695F0000 98 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6961696269646965696769686969696A696C696D696F69706972697369746975 6976697A697B697D697E697F698169836985698A698B698C698E698F69906991 69926993699669976999699A699D699E699F69A069A169A269A369A469A569A6 69A969AA69AC69AE69AF69B069B269B369B569B669B869B969BA69BC69BD0000 69BE69BF69C069C269C369C469C569C669C769C869C969CB69CD69CF69D169D2 69D369D569D669D769D869D969DA69DC69DD69DE69E169E269E369E469E569E6 69E769E869E969EA69EB69EC69EE69EF69F069F169F369F469F569F669F769F8 69F969FA69FB69FC69FE6A006A016A026A036A046A056A066A076A086A096A0B 6A0C6A0D6A0E6A0F6A106A116A126A136A146A156A166A196A1A6A1B6A1C6A1D 6A1E6A206A226A236A246A256A266A276A296A2B6A2C6A2D6A2E6A306A326A33 6A346A366A376A386A396A3A6A3B6A3C6A3F6A406A416A426A436A456A466A48 6A496A4A6A4B6A4C6A4D6A4E6A4F6A516A526A536A546A556A566A576A5A0000 99 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A5C6A5D6A5E6A5F6A606A626A636A646A666A676A686A696A6A6A6B6A6C6A6D 6A6E6A6F6A706A726A736A746A756A766A776A786A7A6A7B6A7D6A7E6A7F6A81 6A826A836A856A866A876A886A896A8A6A8B6A8C6A8D6A8F6A926A936A946A95 6A966A986A996A9A6A9B6A9C6A9D6A9E6A9F6AA16AA26AA36AA46AA56AA60000 6AA76AA86AAA6AAD6AAE6AAF6AB06AB16AB26AB36AB46AB56AB66AB76AB86AB9 6ABA6ABB6ABC6ABD6ABE6ABF6AC06AC16AC26AC36AC46AC56AC66AC76AC86AC9 6ACA6ACB6ACC6ACD6ACE6ACF6AD06AD16AD26AD36AD46AD56AD66AD76AD86AD9 6ADA6ADB6ADC6ADD6ADE6ADF6AE06AE16AE26AE36AE46AE56AE66AE76AE86AE9 6AEA6AEB6AEC6AED6AEE6AEF6AF06AF16AF26AF36AF46AF56AF66AF76AF86AF9 6AFA6AFB6AFC6AFD6AFE6AFF6B006B016B026B036B046B056B066B076B086B09 6B0A6B0B6B0C6B0D6B0E6B0F6B106B116B126B136B146B156B166B176B186B19 6B1A6B1B6B1C6B1D6B1E6B1F6B256B266B286B296B2A6B2B6B2C6B2D6B2E0000 9A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6B2F6B306B316B336B346B356B366B386B3B6B3C6B3D6B3F6B406B416B426B44 6B456B486B4A6B4B6B4D6B4E6B4F6B506B516B526B536B546B556B566B576B58 6B5A6B5B6B5C6B5D6B5E6B5F6B606B616B686B696B6B6B6C6B6D6B6E6B6F6B70 6B716B726B736B746B756B766B776B786B7A6B7D6B7E6B7F6B806B856B880000 6B8C6B8E6B8F6B906B916B946B956B976B986B996B9C6B9D6B9E6B9F6BA06BA2 6BA36BA46BA56BA66BA76BA86BA96BAB6BAC6BAD6BAE6BAF6BB06BB16BB26BB6 6BB86BB96BBA6BBB6BBC6BBD6BBE6BC06BC36BC46BC66BC76BC86BC96BCA6BCC 6BCE6BD06BD16BD86BDA6BDC6BDD6BDE6BDF6BE06BE26BE36BE46BE56BE66BE7 6BE86BE96BEC6BED6BEE6BF06BF16BF26BF46BF66BF76BF86BFA6BFB6BFC6BFE 6BFF6C006C016C026C036C046C086C096C0A6C0B6C0C6C0E6C126C176C1C6C1D 6C1E6C206C236C256C2B6C2C6C2D6C316C336C366C376C396C3A6C3B6C3C6C3E 6C3F6C436C446C456C486C4B6C4C6C4D6C4E6C4F6C516C526C536C566C580000 9B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6C596C5A6C626C636C656C666C676C6B6C6C6C6D6C6E6C6F6C716C736C756C77 6C786C7A6C7B6C7C6C7F6C806C846C876C8A6C8B6C8D6C8E6C916C926C956C96 6C976C986C9A6C9C6C9D6C9E6CA06CA26CA86CAC6CAF6CB06CB46CB56CB66CB7 6CBA6CC06CC16CC26CC36CC66CC76CC86CCB6CCD6CCE6CCF6CD16CD26CD80000 6CD96CDA6CDC6CDD6CDF6CE46CE66CE76CE96CEC6CED6CF26CF46CF96CFF6D00 6D026D036D056D066D086D096D0A6D0D6D0F6D106D116D136D146D156D166D18 6D1C6D1D6D1F6D206D216D226D236D246D266D286D296D2C6D2D6D2F6D306D34 6D366D376D386D3A6D3F6D406D426D446D496D4C6D506D556D566D576D586D5B 6D5D6D5F6D616D626D646D656D676D686D6B6D6C6D6D6D706D716D726D736D75 6D766D796D7A6D7B6D7D6D7E6D7F6D806D816D836D846D866D876D8A6D8B6D8D 6D8F6D906D926D966D976D986D996D9A6D9C6DA26DA56DAC6DAD6DB06DB16DB3 6DB46DB66DB76DB96DBA6DBB6DBC6DBD6DBE6DC16DC26DC36DC86DC96DCA0000 9C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6DCD6DCE6DCF6DD06DD26DD36DD46DD56DD76DDA6DDB6DDC6DDF6DE26DE36DE5 6DE76DE86DE96DEA6DED6DEF6DF06DF26DF46DF56DF66DF86DFA6DFD6DFE6DFF 6E006E016E026E036E046E066E076E086E096E0B6E0F6E126E136E156E186E19 6E1B6E1C6E1E6E1F6E226E266E276E286E2A6E2C6E2E6E306E316E336E350000 6E366E376E396E3B6E3C6E3D6E3E6E3F6E406E416E426E456E466E476E486E49 6E4A6E4B6E4C6E4F6E506E516E526E556E576E596E5A6E5C6E5D6E5E6E606E61 6E626E636E646E656E666E676E686E696E6A6E6C6E6D6E6F6E706E716E726E73 6E746E756E766E776E786E796E7A6E7B6E7C6E7D6E806E816E826E846E876E88 6E8A6E8B6E8C6E8D6E8E6E916E926E936E946E956E966E976E996E9A6E9B6E9D 6E9E6EA06EA16EA36EA46EA66EA86EA96EAB6EAC6EAD6EAE6EB06EB36EB56EB8 6EB96EBC6EBE6EBF6EC06EC36EC46EC56EC66EC86EC96ECA6ECC6ECD6ECE6ED0 6ED26ED66ED86ED96EDB6EDC6EDD6EE36EE76EEA6EEB6EEC6EED6EEE6EEF0000 9D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6EF06EF16EF26EF36EF56EF66EF76EF86EFA6EFB6EFC6EFD6EFE6EFF6F006F01 6F036F046F056F076F086F0A6F0B6F0C6F0D6F0E6F106F116F126F166F176F18 6F196F1A6F1B6F1C6F1D6F1E6F1F6F216F226F236F256F266F276F286F2C6F2E 6F306F326F346F356F376F386F396F3A6F3B6F3C6F3D6F3F6F406F416F420000 6F436F446F456F486F496F4A6F4C6F4E6F4F6F506F516F526F536F546F556F56 6F576F596F5A6F5B6F5D6F5F6F606F616F636F646F656F676F686F696F6A6F6B 6F6C6F6F6F706F716F736F756F766F776F796F7B6F7D6F7E6F7F6F806F816F82 6F836F856F866F876F8A6F8B6F8F6F906F916F926F936F946F956F966F976F98 6F996F9A6F9B6F9D6F9E6F9F6FA06FA26FA36FA46FA56FA66FA86FA96FAA6FAB 6FAC6FAD6FAE6FAF6FB06FB16FB26FB46FB56FB76FB86FBA6FBB6FBC6FBD6FBE 6FBF6FC16FC36FC46FC56FC66FC76FC86FCA6FCB6FCC6FCD6FCE6FCF6FD06FD3 6FD46FD56FD66FD76FD86FD96FDA6FDB6FDC6FDD6FDF6FE26FE36FE46FE50000 9E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6FE66FE76FE86FE96FEA6FEB6FEC6FED6FF06FF16FF26FF36FF46FF56FF66FF7 6FF86FF96FFA6FFB6FFC6FFD6FFE6FFF70007001700270037004700570067007 70087009700A700B700C700D700E700F70107012701370147015701670177018 7019701C701D701E701F702070217022702470257026702770287029702A0000 702B702C702D702E702F70307031703270337034703670377038703A703B703C 703D703E703F7040704170427043704470457046704770487049704A704B704D 704E7050705170527053705470557056705770587059705A705B705C705D705F 7060706170627063706470657066706770687069706A706E7071707270737074 70777079707A707B707D7081708270837084708670877088708B708C708D708F 70907091709370977098709A709B709E709F70A070A170A270A370A470A570A6 70A770A870A970AA70B070B270B470B570B670BA70BE70BF70C470C570C670C7 70C970CB70CC70CD70CE70CF70D070D170D270D370D470D570D670D770DA0000 9F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 70DC70DD70DE70E070E170E270E370E570EA70EE70F070F170F270F370F470F5 70F670F870FA70FB70FC70FE70FF710071017102710371047105710671077108 710B710C710D710E710F7111711271147117711B711C711D711E711F71207121 7122712371247125712771287129712A712B712C712D712E7132713371340000 7135713771387139713A713B713C713D713E713F714071417142714371447146 714771487149714B714D714F7150715171527153715471557156715771587159 715A715B715D715F716071617162716371657169716A716B716C716D716F7170 717171747175717671777179717B717C717E717F718071817182718371857186 718771887189718B718C718D718E7190719171927193719571967197719A719B 719C719D719E71A171A271A371A471A571A671A771A971AA71AB71AD71AE71AF 71B071B171B271B471B671B771B871BA71BB71BC71BD71BE71BF71C071C171C2 71C471C571C671C771C871C971CA71CB71CC71CD71CF71D071D171D271D30000 A0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 71D671D771D871D971DA71DB71DC71DD71DE71DF71E171E271E371E471E671E8 71E971EA71EB71EC71ED71EF71F071F171F271F371F471F571F671F771F871FA 71FB71FC71FD71FE71FF720072017202720372047205720772087209720A720B 720C720D720E720F7210721172127213721472157216721772187219721A0000 721B721C721E721F722072217222722372247225722672277229722B722D722E 722F723272337234723A723C723E72407241724272437244724572467249724A 724B724E724F7250725172537254725572577258725A725C725E726072637264 72657268726A726B726C726D7270727172737274727672777278727B727C727D 7282728372857286728772887289728C728E7290729172937294729572967297 72987299729A729B729C729D729E72A072A172A272A372A472A572A672A772A8 72A972AA72AB72AE72B172B272B372B572BA72BB72BC72BD72BE72BF72C072C5 72C672C772C972CA72CB72CC72CF72D172D372D472D572D672D872DA72DB0000 A1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030003001300200B702C902C700A8300330052014FF5E2016202620182019 201C201D3014301530083009300A300B300C300D300E300F3016301730103011 00B100D700F72236222722282211220F222A222922082237221A22A522252220 23122299222B222E2261224C2248223D221D2260226E226F22642265221E2235 22342642264000B0203220332103FF0400A4FFE0FFE1203000A7211626062605 25CB25CF25CE25C725C625A125A025B325B2203B219221902191219330130000 A2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000217021712172217321742175217621772178217900000000000000000000 000024882489248A248B248C248D248E248F2490249124922493249424952496 249724982499249A249B247424752476247724782479247A247B247C247D247E 247F248024812482248324842485248624872460246124622463246424652466 2467246824690000000032203221322232233224322532263227322832290000 00002160216121622163216421652166216721682169216A216B000000000000 A3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF01FF02FF03FFE5FF05FF06FF07FF08FF09FF0AFF0BFF0CFF0DFF0EFF0F FF10FF11FF12FF13FF14FF15FF16FF17FF18FF19FF1AFF1BFF1CFF1DFF1EFF1F FF20FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2F FF30FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3AFF3BFF3CFF3DFF3EFF3F FF40FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5AFF5BFF5CFF5DFFE30000 A4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000304130423043304430453046304730483049304A304B304C304D304E304F 3050305130523053305430553056305730583059305A305B305C305D305E305F 3060306130623063306430653066306730683069306A306B306C306D306E306F 3070307130723073307430753076307730783079307A307B307C307D307E307F 3080308130823083308430853086308730883089308A308B308C308D308E308F 3090309130923093000000000000000000000000000000000000000000000000 A5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF 30B030B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF 30C030C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF 30D030D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000000 A6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000039103920393039403950396039703980399039A039B039C039D039E039F 03A003A103A303A403A503A603A703A803A90000000000000000000000000000 000003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C303C403C503C603C703C803C90000000000000000000000000000 FE35FE36FE39FE3AFE3FFE40FE3DFE3EFE41FE42FE43FE4400000000FE3BFE3C FE37FE38FE310000FE33FE340000000000000000000000000000000000000000 A7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000004100411041204130414041504010416041704180419041A041B041C041D 041E041F0420042104220423042404250426042704280429042A042B042C042D 042E042F00000000000000000000000000000000000000000000000000000000 000004300431043204330434043504510436043704380439043A043B043C043D 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000000000 A8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 02CA02CB02D920132015202520352105210921962197219821992215221F2223 22522266226722BF2550255125522553255425552556255725582559255A255B 255C255D255E255F2560256125622563256425652566256725682569256A256B 256C256D256E256F257025712572257325812582258325842585258625870000 25882589258A258B258C258D258E258F25932594259525BC25BD25E225E325E4 25E5260922953012301D301E0000000000000000000000000000000000000000 0000010100E101CE00E0011300E9011B00E8012B00ED01D000EC014D00F301D2 00F2016B00FA01D400F901D601D801DA01DC00FC00EA02510000014401480000 0261000000000000000031053106310731083109310A310B310C310D310E310F 3110311131123113311431153116311731183119311A311B311C311D311E311F 3120312131223123312431253126312731283129000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 A9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 30213022302330243025302630273028302932A3338E338F339C339D339E33A1 33C433CE33D133D233D5FE30FFE2FFE400002121323100002010000000000000 30FC309B309C30FD30FE3006309D309EFE49FE4AFE4BFE4CFE4DFE4EFE4FFE50 FE51FE52FE54FE55FE56FE57FE59FE5AFE5BFE5CFE5DFE5EFE5FFE60FE610000 FE62FE63FE64FE65FE66FE68FE69FE6AFE6B0000000000000000000000000000 0000000000000000000000003007000000000000000000000000000000000000 00000000000000002500250125022503250425052506250725082509250A250B 250C250D250E250F2510251125122513251425152516251725182519251A251B 251C251D251E251F2520252125222523252425252526252725282529252A252B 252C252D252E252F2530253125322533253425352536253725382539253A253B 253C253D253E253F2540254125422543254425452546254725482549254A254B 0000000000000000000000000000000000000000000000000000000000000000 AA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 72DC72DD72DF72E272E372E472E572E672E772EA72EB72F572F672F972FD72FE 72FF73007302730473057306730773087309730B730C730D730F731073117312 731473187319731A731F732073237324732673277328732D732F733073327333 73357336733A733B733C733D7340734173427343734473457346734773480000 7349734A734B734C734E734F7351735373547355735673587359735A735B735C 735D735E735F736173627363736473657366736773687369736A736B736E7370 7371000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 AB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 73727373737473757376737773787379737A737B737C737D737F738073817382 7383738573867388738A738C738D738F73907392739373947395739773987399 739A739C739D739E73A073A173A373A473A573A673A773A873AA73AC73AD73B1 73B473B573B673B873B973BC73BD73BE73BF73C173C373C473C573C673C70000 73CB73CC73CE73D273D373D473D573D673D773D873DA73DB73DC73DD73DF73E1 73E273E373E473E673E873EA73EB73EC73EE73EF73F073F173F373F473F573F6 73F7000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 AC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 73F873F973FA73FB73FC73FD73FE73FF740074017402740474077408740B740C 740D740E741174127413741474157416741774187419741C741D741E741F7420 74217423742474277429742B742D742F74317432743774387439743A743B743D 743E743F744074427443744474457446744774487449744A744B744C744D0000 744E744F7450745174527453745474567458745D746074617462746374647465 7466746774687469746A746B746C746E746F7471747274737474747574787479 747A000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 AD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 747B747C747D747F748274847485748674887489748A748C748D748F74917492 7493749474957496749774987499749A749B749D749F74A074A174A274A374A4 74A574A674AA74AB74AC74AD74AE74AF74B074B174B274B374B474B574B674B7 74B874B974BB74BC74BD74BE74BF74C074C174C274C374C474C574C674C70000 74C874C974CA74CB74CC74CD74CE74CF74D074D174D374D474D574D674D774D8 74D974DA74DB74DD74DF74E174E574E774E874E974EA74EB74EC74ED74F074F1 74F2000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 AE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 74F374F574F874F974FA74FB74FC74FD74FE7500750175027503750575067507 75087509750A750B750C750E751075127514751575167517751B751D751E7520 752175227523752475267527752A752E753475367539753C753D753F75417542 75437544754675477549754A754D755075517552755375557556755775580000 755D755E755F75607561756275637564756775687569756B756C756D756E756F 757075717573757575767577757A757B757C757D757E75807581758275847585 7587000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 AF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 75887589758A758C758D758E7590759375957598759B759C759E75A275A675A7 75A875A975AA75AD75B675B775BA75BB75BF75C075C175C675CB75CC75CE75CF 75D075D175D375D775D975DA75DC75DD75DF75E075E175E575E975EC75ED75EE 75EF75F275F375F575F675F775F875FA75FB75FD75FE76027604760676070000 76087609760B760D760E760F76117612761376147616761A761C761D761E7621 762376277628762C762E762F76317632763676377639763A763B763D76417642 7644000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 B0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 76457646764776487649764A764B764E764F7650765176527653765576577658 7659765A765B765D765F766076617662766476657666766776687669766A766C 766D766E767076717672767376747675767676777679767A767C767F76807681 768376857689768A768C768D768F769076927694769576977698769A769B0000 769C769D769E769F76A076A176A276A376A576A676A776A876A976AA76AB76AC 76AD76AF76B076B376B576B676B776B876B976BA76BB76BC76BD76BE76C076C1 76C3554A963F57C3632854CE550954C07691764C853C77EE827E788D72319698 978D6C285B894FFA630966975CB880FA684880AE660276CE51F9655671AC7FF1 888450B2596561CA6FB382AD634C625253ED54277B06516B75A45DF462D48DCB 9776628A8019575D97387F627238767D67CF767E64464F708D2562DC7A176591 73ED642C6273822C9881677F7248626E62CC4F3474E3534A529E7ECA90A65E2E 6886699C81807ED168D278C5868C9551508D8C2482DE80DE5305891252650000 B1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 76C476C776C976CB76CC76D376D576D976DA76DC76DD76DE76E076E176E276E3 76E476E676E776E876E976EA76EB76EC76ED76F076F376F576F676F776FA76FB 76FD76FF77007702770377057706770A770C770E770F77107711771277137714 7715771677177718771B771C771D771E77217723772477257727772A772B0000 772C772E773077317732773377347739773B773D773E773F7742774477457746 77487749774A774B774C774D774E774F77527753775477557756775777587759 775C858496F94FDD582199715B9D62B162A566B48C799C8D7206676F789160B2 535153178F8880CC8D1D94A1500D72C8590760EB711988AB595482EF672C7B28 5D297EF7752D6CF58E668FF8903C9F3B6BD491197B145F7C78A784D6853D6BD5 6BD96BD65E015E8775F995ED655D5F0A5FC58F9F58C181C2907F965B97AD8FB9 7F168D2C62414FBF53D8535E8FA88FA98FAB904D68075F6A819888689CD6618B 522B762A5F6C658C6FD26EE85BBE6448517551B067C44E1979C9997C70B30000 B2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 775D775E775F7760776477677769776A776D776E776F77707771777277737774 7775777677777778777A777B777C7781778277837786778777887789778A778B 778F77907793779477957796779777987799779A779B779C779D779E77A177A3 77A477A677A877AB77AD77AE77AF77B177B277B477B677B777B877B977BA0000 77BC77BE77C077C177C277C377C477C577C677C777C877C977CA77CB77CC77CE 77CF77D077D177D277D377D477D577D677D877D977DA77DD77DE77DF77E077E1 77E475C55E7673BB83E064AD62E894B56CE2535A52C3640F94C27B944F2F5E1B 82368116818A6E246CCA9A736355535C54FA886557E04E0D5E036B657C3F90E8 601664E6731C88C16750624D8D22776C8E2991C75F6983DC8521991053C28695 6B8B60ED60E8707F82CD82314ED36CA785CF64CD7CD969FD66F9834953957B56 4FA7518C6D4B5C428E6D63D253C9832C833667E578B4643D5BDF5C945DEE8BE7 62C667F48C7A640063BA8749998B8C177F2094F24EA7961098A4660C73160000 B3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 77E677E877EA77EF77F077F177F277F477F577F777F977FA77FB77FC78037804 7805780678077808780A780B780E780F7810781378157819781B781E78207821 782278247828782A782B782E782F78317832783378357836783D783F78417842 78437844784678487849784A784B784D784F78517853785478587859785A0000 785B785C785E785F7860786178627863786478657866786778687869786F7870 78717872787378747875787678787879787A787B787D787E787F788078817882 7883573A5C1D5E38957F507F80A05382655E7545553150218D856284949E671D 56326F6E5DE2543570928F66626F64A463A35F7B6F8890F481E38FB05C186668 5FF16C8996488D81886C649179F057CE6A59621054484E587A0B60E96F848BDA 627F901E9A8B79E4540375F4630153196C608FDF5F1B9A70803B9F7F4F885C3A 8D647FC565A570BD514551B2866B5D075BA062BD916C75748E0C7A2061017B79 4EC77EF877854E1181ED521D51FA6A7153A88E87950496CF6EC19664695A0000 B4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7884788578867888788A788B788F789078927894789578967899789D789E78A0 78A278A478A678A878A978AA78AB78AC78AD78AE78AF78B578B678B778B878BA 78BB78BC78BD78BF78C078C278C378C478C678C778C878CC78CD78CE78CF78D1 78D278D378D678D778D878DA78DB78DC78DD78DE78DF78E078E178E278E30000 78E478E578E678E778E978EA78EB78ED78EE78EF78F078F178F378F578F678F8 78F978FB78FC78FD78FE78FF79007902790379047906790779087909790A790B 790C784050A877D7641089E6590463E35DDD7A7F693D4F20823955984E3275AE 7A975E625E8A95EF521B5439708A6376952457826625693F918755076DF37EAF 882262337EF075B5832878C196CC8F9E614874F78BCD6B64523A8D506B21806A 847156F153064ECE4E1B51D17C97918B7C074FC38E7F7BE17A9C64675D1450AC 810676017CB96DEC7FE067515B585BF878CB64AE641363AA632B9519642D8FBE 7B5476296253592754466B7950A362345E266B864EE38D37888B5F85902E0000 B5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 790D790E790F791079117912791479157916791779187919791A791B791C791D 791F792079217922792379257926792779287929792A792B792C792D792E792F 793079317932793379357936793779387939793D793F79427943794479457947 794A794B794C794D794E794F7950795179527954795579587959796179630000 796479667969796A796B796C796E79707971797279737974797579767979797B 797C797D797E797F798279837986798779887989798B798C798D798E79907991 79926020803D62C54E39535590F863B880C665E66C2E4F4660EE6DE18BDE5F39 86CB5F536321515A83616863520063638E4850125C9B79775BFC52307A3B60BC 905376D75FB75F9776848E6C706F767B7B4977AA51F3909358244F4E6EF48FEA 654C7B1B72C46DA47FDF5AE162B55E95573084827B2C5E1D5F1F90127F1498A0 63826EC7789870B95178975B57AB75354F4375385E9760E659606DC06BBF7889 53FC96D551CB52016389540A94938C038DCC7239789F87768FED8C0D53E00000 B6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7993799479957996799779987999799B799C799D799E799F79A079A179A279A3 79A479A579A679A879A979AA79AB79AC79AD79AE79AF79B079B179B279B479B5 79B679B779B879BC79BF79C279C479C579C779C879CA79CC79CE79CF79D079D3 79D479D679D779D979DA79DB79DC79DD79DE79E079E179E279E579E879EA0000 79EC79EE79F179F279F379F479F579F679F779F979FA79FC79FE79FF7A017A04 7A057A077A087A097A0A7A0C7A0F7A107A117A127A137A157A167A187A197A1B 7A1C4E0176EF53EE948998769F0E952D5B9A8BA24E224E1C51AC846361C252A8 680B4F97606B51BB6D1E515C6296659796618C46901775D890FD77636BD2728A 72EC8BFB583577798D4C675C9540809A5EA66E2159927AEF77ED953B6BB565AD 7F0E58065151961F5BF958A954288E726566987F56E4949D76FE9041638754C6 591A593A579B8EB267358DFA8235524160F0581586FE5CE89E454FC4989D8BB9 5A2560765384627C904F9102997F6069800C513F80335C1499756D314E8C0000 B7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7A1D7A1F7A217A227A247A257A267A277A287A297A2A7A2B7A2C7A2D7A2E7A2F 7A307A317A327A347A357A367A387A3A7A3E7A407A417A427A437A447A457A47 7A487A497A4A7A4B7A4C7A4D7A4E7A4F7A507A527A537A547A557A567A587A59 7A5A7A5B7A5C7A5D7A5E7A5F7A607A617A627A637A647A657A667A677A680000 7A697A6A7A6B7A6C7A6D7A6E7A6F7A717A727A737A757A7B7A7C7A7D7A7E7A82 7A857A877A897A8A7A8B7A8C7A8E7A8F7A907A937A947A997A9A7A9B7A9E7AA1 7AA28D3053D17F5A7B4F4F104E4F96006CD573D085E95E06756A7FFB6A0A77FE 94927E4151E170E653CD8FD483038D2972AF996D6CDB574A82B365B980AA623F 963259A84EFF8BBF7EBA653E83F2975E556198DE80A5532A8BFD542080BA5E9F 6CB88D3982AC915A54296C1B52067EB7575F711A6C7E7C89594B4EFD5FFF6124 7CAA4E305C0167AB87025CF0950B98CE75AF70FD902251AF7F1D8BBD594951E4 4F5B5426592B657780A45B75627662C28F905E456C1F7B264F0F4FD8670D0000 B8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7AA37AA47AA77AA97AAA7AAB7AAE7AAF7AB07AB17AB27AB47AB57AB67AB77AB8 7AB97ABA7ABB7ABC7ABD7ABE7AC07AC17AC27AC37AC47AC57AC67AC77AC87AC9 7ACA7ACC7ACD7ACE7ACF7AD07AD17AD27AD37AD47AD57AD77AD87ADA7ADB7ADC 7ADD7AE17AE27AE47AE77AE87AE97AEA7AEB7AEC7AEE7AF07AF17AF27AF30000 7AF47AF57AF67AF77AF87AFB7AFC7AFE7B007B017B027B057B077B097B0C7B0D 7B0E7B107B127B137B167B177B187B1A7B1C7B1D7B1F7B217B227B237B277B29 7B2D6D6E6DAA798F88B15F17752B629A8F854FEF91DC65A7812F81515E9C8150 8D74526F89868D4B590D50854ED8961C723681798D1F5BCC8BA3964459877F1A 54905676560E8BE565396982949976D66E895E727518674667D17AFF809D8D76 611F79C665628D635188521A94A27F38809B7EB25C976E2F67607BD9768B9AD8 818F7F947CD5641E95507A3F544A54E56B4C640162089E3D80F3759952729769 845B683C86E49601969494EC4E2A54047ED968398DDF801566F45E9A7FB90000 B9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7B2F7B307B327B347B357B367B377B397B3B7B3D7B3F7B407B417B427B437B44 7B467B487B4A7B4D7B4E7B537B557B577B597B5C7B5E7B5F7B617B637B647B65 7B667B677B687B697B6A7B6B7B6C7B6D7B6F7B707B737B747B767B787B7A7B7C 7B7D7B7F7B817B827B837B847B867B877B887B897B8A7B8B7B8C7B8E7B8F0000 7B917B927B937B967B987B997B9A7B9B7B9E7B9F7BA07BA37BA47BA57BAE7BAF 7BB07BB27BB37BB57BB67BB77BB97BBA7BBB7BBC7BBD7BBE7BBF7BC07BC27BC3 7BC457C2803F68975DE5653B529F606D9F9A4F9B8EAC516C5BAB5F135DE96C5E 62F18D21517194A952FE6C9F82DF72D757A267848D2D591F8F9C83C754957B8D 4F306CBD5B6459D19F1353E486CA9AA88C3780A16545987E56FA96C7522E74DC 52505BE1630289024E5662D0602A68FA51735B9851A089C27BA199867F5060EF 704C8D2F51495E7F901B747089C4572D78455F529F9F95FA8F689B3C8BE17678 684267DC8DEA8D35523D8F8A6EDA68CD950590ED56FD679C88F98FC754C80000 BA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7BC57BC87BC97BCA7BCB7BCD7BCE7BCF7BD07BD27BD47BD57BD67BD77BD87BDB 7BDC7BDE7BDF7BE07BE27BE37BE47BE77BE87BE97BEB7BEC7BED7BEF7BF07BF2 7BF37BF47BF57BF67BF87BF97BFA7BFB7BFD7BFF7C007C017C027C037C047C05 7C067C087C097C0A7C0D7C0E7C107C117C127C137C147C157C177C187C190000 7C1A7C1B7C1C7C1D7C1E7C207C217C227C237C247C257C287C297C2B7C2C7C2D 7C2E7C2F7C307C317C327C337C347C357C367C377C397C3A7C3B7C3C7C3D7C3E 7C429AB85B696D776C264EA55BB39A87916361A890AF97E9542B6DB55BD251FD 558A7F557FF064BC634D65F161BE608D710A6C576C49592F676D822A58D5568E 8C6A6BEB90DD597D801753F76D695475559D837783CF683879BE548C4F555408 76D28C8996026CB36DB88D6B89109E648D3A563F9ED175D55F8872E0606854FC 4EA86A2A886160528F7054C470D886799E3F6D2A5B8F5F187EA255894FAF7334 543C539A5019540E547C4E4E5FFD745A58F6846B80E1877472D07CCA6E560000 BB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7C437C447C457C467C477C487C497C4A7C4B7C4C7C4E7C4F7C507C517C527C53 7C547C557C567C577C587C597C5A7C5B7C5C7C5D7C5E7C5F7C607C617C627C63 7C647C657C667C677C687C697C6A7C6B7C6C7C6D7C6E7C6F7C707C717C727C75 7C767C777C787C797C7A7C7E7C7F7C807C817C827C837C847C857C867C870000 7C887C8A7C8B7C8C7C8D7C8E7C8F7C907C937C947C967C997C9A7C9B7CA07CA1 7CA37CA67CA77CA87CA97CAB7CAC7CAD7CAF7CB07CB47CB57CB67CB77CB87CBA 7CBB5F27864E552C62A44E926CAA623782B154D7534E733E6ED1753B52125316 8BDD69D05F8A60006DEE574F6B2273AF68538FD87F13636260A3552475EA8C62 71156DA35BA65E7B8352614C9EC478FA87577C27768751F060F6714C66435E4C 604D8C0E707063258F895FBD606286D456DE6BC160946167534960E066668D3F 79FD4F1A70E96C478BB38BF27ED88364660F5A5A9B426D516DF78C416D3B4F19 706B83B7621660D1970D8D27797851FB573E57FA673A75787A3D79EF7B950000 BC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7CBF7CC07CC27CC37CC47CC67CC97CCB7CCE7CCF7CD07CD17CD27CD37CD47CD8 7CDA7CDB7CDD7CDE7CE17CE27CE37CE47CE57CE67CE77CE97CEA7CEB7CEC7CED 7CEE7CF07CF17CF27CF37CF47CF57CF67CF77CF97CFA7CFC7CFD7CFE7CFF7D00 7D017D027D037D047D057D067D077D087D097D0B7D0C7D0D7D0E7D0F7D100000 7D117D127D137D147D157D167D177D187D197D1A7D1B7D1C7D1D7D1E7D1F7D21 7D237D247D257D267D287D297D2A7D2C7D2D7D2E7D307D317D327D337D347D35 7D36808C99658FF96FC08BA59E2159EC7EE97F095409678168D88F917C4D96C6 53CA602575BE6C7253735AC97EA7632451E0810A5DF184DF628051805B634F0E 796D524260B86D4E5BC45BC28BA18BB065E25FCC964559937EE77EAA560967B7 59394F735BB652A0835A988A8D3E753294BE50477A3C4EF767B69A7E5AC16B7C 76D1575A5C167B3A95F4714E517C80A9827059787F04832768C067EC78B17877 62E363617B804FED526A51CF835069DB92748DF58D3189C1952E7BAD4EF60000 BD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7D377D387D397D3A7D3B7D3C7D3D7D3E7D3F7D407D417D427D437D447D457D46 7D477D487D497D4A7D4B7D4C7D4D7D4E7D4F7D507D517D527D537D547D557D56 7D577D587D597D5A7D5B7D5C7D5D7D5E7D5F7D607D617D627D637D647D657D66 7D677D687D697D6A7D6B7D6C7D6D7D6F7D707D717D727D737D747D757D760000 7D787D797D7A7D7B7D7C7D7D7D7E7D7F7D807D817D827D837D847D857D867D87 7D887D897D8A7D8B7D8C7D8D7D8E7D8F7D907D917D927D937D947D957D967D97 7D98506582305251996F6E106E856DA75EFA50F559DC5C066D466C5F7586848B 686859568BB253209171964D854969127901712680F64EA490CA6D479A845A07 56BC640594F077EB4FA5811A72E189D2997A7F347EDE527F655991758F7F8F83 53EB7A9663ED63A5768679F888579636622A52AB8282685467706377776B7AED 6D017ED389E359D0621285C982A5754C501F4ECB75A58BEB5C4A5DFE7B4B65A4 91D14ECA6D25895F7D2795264EC58C288FDB9773664B79818FD170EC6D780000 BE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7D997D9A7D9B7D9C7D9D7D9E7D9F7DA07DA17DA27DA37DA47DA57DA77DA87DA9 7DAA7DAB7DAC7DAD7DAF7DB07DB17DB27DB37DB47DB57DB67DB77DB87DB97DBA 7DBB7DBC7DBD7DBE7DBF7DC07DC17DC27DC37DC47DC57DC67DC77DC87DC97DCA 7DCB7DCC7DCD7DCE7DCF7DD07DD17DD27DD37DD47DD57DD67DD77DD87DD90000 7DDA7DDB7DDC7DDD7DDE7DDF7DE07DE17DE27DE37DE47DE57DE67DE77DE87DE9 7DEA7DEB7DEC7DED7DEE7DEF7DF07DF17DF27DF37DF47DF57DF67DF77DF87DF9 7DFA5C3D52B283465162830E775B66769CB84EAC60CA7CBE7CB37ECF4E958B66 666F988897595883656C955C5F8475C997567ADF7ADE51C070AF7A9863EA7A76 7EA0739697ED4E4570784E5D915253A9655165E781FC8205548E5C31759A97A0 62D872D975BD5C459A7983CA5C40548077E94E3E6CAE805A62D2636E5DE85177 8DDD8E1E952F4FF153E560E770AC526763509E435A1F5026773753777EE26485 652B628963985014723589C951B38BC07EDD574783CC94A7519B541B5CFB0000 BF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7DFB7DFC7DFD7DFE7DFF7E007E017E027E037E047E057E067E077E087E097E0A 7E0B7E0C7E0D7E0E7E0F7E107E117E127E137E147E157E167E177E187E197E1A 7E1B7E1C7E1D7E1E7E1F7E207E217E227E237E247E257E267E277E287E297E2A 7E2B7E2C7E2D7E2E7E2F7E307E317E327E337E347E357E367E377E387E390000 7E3A7E3C7E3D7E3E7E3F7E407E427E437E447E457E467E487E497E4A7E4B7E4C 7E4D7E4E7E4F7E507E517E527E537E547E557E567E577E587E597E5A7E5B7E5C 7E5D4FCA7AE36D5A90E19A8F55805496536154AF5F0063E9697751EF6168520A 582A52D8574E780D770B5EB761777CE0625B62974EA27095800362F770E49760 577782DB67EF68F578D5989779D158F354B353EF6E34514B523B5BA28BFE80AF 554357A660735751542D7A7A60505B5463A762A053E362635BC767AF54ED7A9F 82E691775E9388E4593857AE630E8DE880EF57577B774FA95FEB5BBD6B3E5321 7B5072C2684677FF773665F751B54E8F76D45CBF7AA58475594E9B4150800000 C0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7E5E7E5F7E607E617E627E637E647E657E667E677E687E697E6A7E6B7E6C7E6D 7E6E7E6F7E707E717E727E737E747E757E767E777E787E797E7A7E7B7E7C7E7D 7E7E7E7F7E807E817E837E847E857E867E877E887E897E8A7E8B7E8C7E8D7E8E 7E8F7E907E917E927E937E947E957E967E977E987E997E9A7E9C7E9D7E9E0000 7EAE7EB47EBB7EBC7ED67EE47EEC7EF97F0A7F107F1E7F377F397F3B7F3C7F3D 7F3E7F3F7F407F417F437F467F477F487F497F4A7F4B7F4C7F4D7F4E7F4F7F52 7F53998861276E8357646606634656F062EC62695ED39614578362C955878721 814A8FA3556683B167658D5684DD5A6A680F62E67BEE961151706F9C8C3063FD 89C861D27F0670C26EE57405699472FC5ECA90CE67176D6A635E52B372628001 4F6C59E5916A70D96D9D52D24E5096F7956D857E78CA7D2F5121579264C2808B 7C7B6CEA68F1695E51B7539868A872819ECE7BF172F879BB6F137406674E91CC 9CA4793C83898354540F68174E3D538952B1783E5386522950884F8B4FD00000 C1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7F567F597F5B7F5C7F5D7F5E7F607F637F647F657F667F677F6B7F6C7F6D7F6F 7F707F737F757F767F777F787F7A7F7B7F7C7F7D7F7F7F807F827F837F847F85 7F867F877F887F897F8B7F8D7F8F7F907F917F927F937F957F967F977F987F99 7F9B7F9C7FA07FA27FA37FA57FA67FA87FA97FAA7FAB7FAC7FAD7FAE7FB10000 7FB37FB47FB57FB67FB77FBA7FBB7FBE7FC07FC27FC37FC47FC67FC77FC87FC9 7FCB7FCD7FCF7FD07FD17FD27FD37FD67FD77FD97FDA7FDB7FDC7FDD7FDE7FE2 7FE375E27ACB7C926CA596B6529B748354E94FE9805483B28FDE95705EC9601C 6D9F5E18655B813894FE604B70BC7EC37CAE51C968817CB1826F4E248F8691CF 667E4EAE8C0564A9804A50DA759771CE5BE58FBD6F664E86648295635ED66599 521788C270C852A3730E7433679778F797164E3490BB9CDE6DCB51DB8D41541D 62CE73B283F196F69F8494C34F367F9A51CC707596755CAD988653E64EE46E9C 740969B4786B998F7559521876246D4167F3516D9F99804B54997B3C7ABF0000 C2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7FE47FE77FE87FEA7FEB7FEC7FED7FEF7FF27FF47FF57FF67FF77FF87FF97FFA 7FFD7FFE7FFF8002800780088009800A800E800F80118013801A801B801D801E 801F802180238024802B802C802D802E802F8030803280348039803A803C803E 8040804180448045804780488049804E804F8050805180538055805680570000 8059805B805C805D805E805F806080618062806380648065806680678068806B 806C806D806E806F807080728073807480758076807780788079807A807B807C 807D9686578462E29647697C5A0464027BD36F0F964B82A6536298855E907089 63B35364864F9C819E93788C97328DEF8D429E7F6F5E79845F559646622E9A74 541594DD4FA365C55C655C617F1586516C2F5F8B73876EE47EFF5CE6631B5B6A 6EE653754E7163A0756562A18F6E4F264ED16CA67EB68BBA841D87BA7F57903B 95237BA99AA188F8843D6D1B9A867EDC59889EBB739B780186829A6C9A82561B 541757CB4E709EA653568FC881097792999286EE6EE1851366FC61626F2B0000 C3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 807E8081808280858088808A808D808E808F8090809180928094809580978099 809E80A380A680A780A880AC80B080B380B580B680B880B980BB80C580C780C8 80C980CA80CB80CF80D080D180D280D380D480D580D880DF80E080E280E380E6 80EE80F580F780F980FB80FE80FF8100810181038104810581078108810B0000 810C811581178119811B811C811D811F81208121812281238124812581268127 81288129812A812B812D812E813081338134813581378139813A813B813C813D 813F8C298292832B76F26C135FD983BD732B8305951A6BDB77DB94C6536F8302 51925E3D8C8C8D384E4873AB679A68859176970971646CA177095A9295416BCF 7F8E66275BD059B95A9A95E895F74EEC840C84996AAC76DF9530731B68A65B5F 772F919A97617CDC8FF78C1C5F257C7379D889C56CCC871C5BC65E4268C97720 7EF55195514D52C95A297F05976282D763CF778485D079D26E3A5E9959998511 706D6C1162BF76BF654F60AF95FD660E879F9E2394ED540D547D8C2C64780000 C4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 81408141814281438144814581478149814D814E814F8152815681578158815B 815C815D815E815F816181628163816481668168816A816B816C816F81728173 81758176817781788181818381848185818681878189818B818C818D818E8190 8192819381948195819681978199819A819E819F81A081A181A281A481A50000 81A781A981AB81AC81AD81AE81AF81B081B181B281B481B581B681B781B881B9 81BC81BD81BE81BF81C481C581C781C881C981CB81CD81CE81CF81D081D181D2 81D3647986116A21819C78E864699B5462B9672B83AB58A89ED86CAB6F205BDE 964C8C0B725F67D062C772614EA959C66BCD589366AE5E5552DF6155672876EE 776672677A4662FF54EA545094A090A35A1C7EB36C164E435976801059485357 753796BE56CA63208111607C95F96DD65462998151855AE980FD59AE9713502A 6CE55C3C62DF4F60533F817B90066EBA852B62C85E7478BE64B5637B5FF55A18 917F9E1F5C3F634F80425B7D556E954A954D6D8560A867E072DE51DD5B810000 C5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 81D481D581D681D781D881D981DA81DB81DC81DD81DE81DF81E081E181E281E4 81E581E681E881E981EB81EE81EF81F081F181F281F581F681F781F881F981FA 81FD81FF8203820782088209820A820B820E820F821182138215821682178218 8219821A821D822082248225822682278229822E8232823A823C823D823F0000 8240824182428243824582468248824A824C824D824E82508251825282538254 8255825682578259825B825C825D825E82608261826282638264826582668267 826962E76CDE725B626D94AE7EBD81136D53519C5F04597452AA601259736696 8650759F632A61E67CEF8BFA54E66B279E256BB485D5545550766CA4556A8DB4 722C5E156015743662CD6392724C5F986E436D3E65006F5876D878D076FC7554 522453DB4E535E9E65C1802A80D6629B5486522870AE888D8DD16CE1547880DA 57F988F48D54966A914D4F696C9B55B776C6783062A870F96F8E5F6D84EC68DA 787C7BF781A8670B9E4F636778B0576F78129739627962AB528874356BD70000 C6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 826A826B826C826D82718275827682778278827B827C82808281828382858286 82878289828C82908293829482958296829A829B829E82A082A282A382A782B2 82B582B682BA82BB82BC82BF82C082C282C382C582C682C982D082D682D982DA 82DD82E282E782E882E982EA82EC82ED82EE82F082F282F382F582F682F80000 82FA82FC82FD82FE82FF8300830A830B830D831083128313831683188319831D 831E831F83208321832283238324832583268329832A832E833083328337833B 833D5564813E75B276AE533975DE50FB5C418B6C7BC7504F72479A9798D86F02 74E27968648777A562FC98918D2B54C180584E52576A82F9840D5E7351ED74F6 8BC45C4F57616CFC98875A4678349B448FEB7C955256625194FA4EC683868461 83E984B257D467345703666E6D668C3166DD7011671F6B3A6816621A59BB4E03 51C46F0667D26C8F517668CB59476B6775665D0E81109F5065D7794879419A91 8D775C824E5E4F01542F5951780C56686C148FC45F036C7D6CE38BAB63900000 C7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 833E833F83418342834483458348834A834B834C834D834E8353835583568357 83588359835D836283708371837283738374837583768379837A837E837F8380 838183828383838483878388838A838B838C838D838F83908391839483958396 83978399839A839D839F83A183A283A383A483A583A683A783AC83AD83AE0000 83AF83B583BB83BE83BF83C283C383C483C683C883C983CB83CD83CE83D083D1 83D283D383D583D783D983DA83DB83DE83E283E383E483E683E783E883EB83EC 83ED60706D3D72756266948E94C553438FC17B7E4EDF8C264E7E9ED494B194B3 524D6F5C90636D458C3458115D4C6B206B4967AA545B81547F8C589985375F3A 62A26A47953965726084686577A74E544FA85DE7979864AC7FD85CED4FCF7A8D 520783044E14602F7A8394A64FB54EB279E6743452E482B964D279BD5BDD6C81 97528F7B6C22503E537F6E0564CE66746C3060C598778BF75E86743C7A7779CB 4E1890B174036C4256DA914B6CC58D8B533A86C666F28EAF5C489A716E200000 C8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 83EE83EF83F383F483F583F683F783FA83FB83FC83FE83FF8400840284058407 84088409840A84108412841384148415841684178419841A841B841E841F8420 8421842284238429842A842B842C842D842E842F843084328433843484358436 84378439843A843B843E843F8440844184428443844484458447844884490000 844A844B844C844D844E844F8450845284538454845584568458845D845E845F 8460846284648465846684678468846A846E846F84708472847484778479847B 847C53D65A369F8B8DA353BB570898A76743919B6CC9516875CA62F372AC5238 529D7F3A7094763853749E4A69B7786E96C088D97FA4713671C3518967D374E4 58E4651856B78BA9997662707ED560F970ED58EC4EC14EBA5FCD97E74EFB8BA4 5203598A7EAB62544ECD65E5620E833884C98363878D71946EB65BB97ED25197 63C967D480898339881551125B7A59828FB14E736C5D516589258F6F962E854A 745E951095F06DA682E55F3164926D128428816E9CC3585E8D5B4E0953C10000 C9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 847D847E847F848084818483848484858486848A848D848F8490849184928493 8494849584968498849A849B849D849E849F84A084A284A384A484A584A684A7 84A884A984AA84AB84AC84AD84AE84B084B184B384B584B684B784BB84BC84BE 84C084C284C384C584C684C784C884CB84CC84CE84CF84D284D484D584D70000 84D884D984DA84DB84DC84DE84E184E284E484E784E884E984EA84EB84ED84EE 84EF84F184F284F384F484F584F684F784F884F984FA84FB84FD84FE85008501 85024F1E6563685155D34E2764149A9A626B5AC2745F82726DA968EE50E7838E 7802674052396C997EB150BB5565715E7B5B665273CA82EB67495C715220717D 886B95EA965564C58D6181B355846C5562477F2E58924F2455468D4F664C4E0A 5C1A88F368A2634E7A0D70E7828D52FA97F65C1154E890B57ECD59628D4A86C7 820C820D8D6664445C0461516D89793E8BBE78377533547B4F388EAB6DF15A20 7EC5795E6C885BA15A76751A80BE614E6E1758F0751F7525727253477EF30000 CA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8503850485058506850785088509850A850B850D850E850F8510851285148515 851685188519851B851C851D851E852085228523852485258526852785288529 852A852D852E852F8530853185328533853485358536853E853F854085418542 8544854585468547854B854C854D854E854F8550855185528553855485550000 85578558855A855B855C855D855F85608561856285638565856685678569856A 856B856C856D856E856F8570857185738575857685778578857C857D857F8580 8581770176DB526980DC57235E08593172EE65BD6E7F8BD75C388671534177F3 62FE65F64EC098DF86805B9E8BC653F277E24F7F5C4E9A7659CB5F0F793A58EB 4E1667FF4E8B62ED8A93901D52BF662F55DC566C90024ED54F8D91CA99706C0F 5E0260435BA489C68BD56536624B99965B885BFF6388552E53D77626517D852C 67A268B36B8A62928F9353D482126DD1758F4E668D4E5B70719F85AF669166D9 7F7287009ECD9F205C5E672F8FF06811675F620D7AD658855EB665706F310000 CB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 85828583858685888589858A858B858C858D858E859085918592859385948595 8596859785988599859A859D859E859F85A085A185A285A385A585A685A785A9 85AB85AC85AD85B185B285B385B485B585B685B885BA85BB85BC85BD85BE85BF 85C085C285C385C485C585C685C785C885CA85CB85CC85CD85CE85D185D20000 85D485D685D785D885D985DA85DB85DD85DE85DF85E085E185E285E385E585E6 85E785E885EA85EB85EC85ED85EE85EF85F085F185F285F385F485F585F685F7 85F860555237800D6454887075295E05681362F4971C53CC723D8C016C347761 7A0E542E77AC987A821C8BF47855671470C165AF64955636601D79C153F84E1D 6B7B80865BFA55E356DB4F3A4F3C99725DF3677E80386002988290015B8B8BBC 8BF5641C825864DE55FD82CF91654FD77D20901F7C9F50F358516EAF5BBF8BC9 80839178849C7B97867D968B968F7EE59AD3788E5C817A57904296A7795F5B59 635F7B0B84D168AD55067F2974107D2295016240584C4ED65B83597958540000 CC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 85F985FA85FC85FD85FE860086018602860386048606860786088609860A860B 860C860D860E860F86108612861386148615861786188619861A861B861C861D 861E861F86208621862286238624862586268628862A862B862C862D862E862F 863086318632863386348635863686378639863A863B863D863E863F86400000 864186428643864486458646864786488649864A864B864C8652865386558656 865786588659865B865C865D865F866086618663866486658666866786688669 866A736D631E8E4B8E0F80CE82D462AC53F06CF0915E592A60016C70574D644A 8D2A762B6EE9575B6A8075F06F6D8C2D8C0857666BEF889278B363A253F970AD 6C645858642A580268E0819B55107CD650188EBA6DCC8D9F70EB638F6D9B6ED4 7EE68404684390036DD896768BA85957727985E4817E75BC8A8A68AF52548E22 951163D098988E44557C4F5366FF568F60D56D9552435C4959296DFB586B7530 751C606C82148146631167618FE2773A8DF38D3494C15E165385542C70C30000 CD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 866D866F86708672867386748675867686778678868386848685868686878688 8689868E868F86908691869286948696869786988699869A869B869E869F86A0 86A186A286A586A686AB86AD86AE86B286B386B786B886B986BB86BC86BD86BE 86BF86C186C286C386C586C886CC86CD86D286D386D586D686D786DA86DC0000 86DD86E086E186E286E386E586E686E786E886EA86EB86EC86EF86F586F686F7 86FA86FB86FC86FD86FF8701870487058706870B870C870E870F871087118714 87166C405EF7505C4EAD5EAD633A8247901A6850916E77B3540C94DC5F647AE5 687663457B527EDF75DB507762955934900F51F879C37A8156FE5F9290146D82 5C60571F541051546E4D56E263A89893817F8715892A9000541E5C6F81C062D6 625881319E3596409A6E9A7C692D59A562D3553E631654C786D96D3C5A0374E6 889C6B6A59168C4C5F2F6E7E73A9987D4E3870F75B8C7897633D665A769660CB 5B9B5A494E0781556C6A738B4EA167897F515F8065FA671B5FD859845A010000 CE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8719871B871D871F87208724872687278728872A872B872C872D872F87308732 87338735873687388739873A873C873D8740874187428743874487458746874A 874B874D874F8750875187528754875587568758875A875B875C875D875E875F 876187628766876787688769876A876B876C876D876F87718772877387750000 877787788779877A877F878087818784878687878789878A878C878E878F8790 8791879287948795879687988799879A879B879C879D879E87A087A187A287A3 87A45DCD5FAE537197E68FDD684556F4552F60DF4E3A6F4D7EF482C7840E59D4 4F1F4F2A5C3E7EAC672A851A5473754F80C355829B4F4F4D6E2D8C135C096170 536B761F6E29868A658795FB7EB9543B7A337D0A95EE55E17FC174EE631D8717 6DA17A9D621165A1536763E16C835DEB545C94A84E4C6C618BEC5C4B65E0829C 68A7543E54346BCB6B664E9463425348821E4F0D4FAE575E620A96FE66647269 52FF52A1609F8BEF661471996790897F785277FD6670563B54389521727A0000 CF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 87A587A687A787A987AA87AE87B087B187B287B487B687B787B887B987BB87BC 87BE87BF87C187C287C387C487C587C787C887C987CC87CD87CE87CF87D087D4 87D587D687D787D887D987DA87DC87DD87DE87DF87E187E287E387E487E687E7 87E887E987EB87EC87ED87EF87F087F187F287F387F487F587F687F787F80000 87FA87FB87FC87FD87FF880088018802880488058806880788088809880B880C 880D880E880F8810881188128814881788188819881A881C881D881E881F8820 88237A00606F5E0C6089819D591560DC718470EF6EAA6C5072806A8488AD5E2D 4E605AB3559C94E36D177CFB9699620F7EC6778E867E5323971E8F9666875CE1 4FA072ED4E0B53A6590F54136380952851484ED99C9C7EA454B88D2488548237 95F26D8E5F265ACC663E966973B0732E53BF817A99857FA15BAA967796507EBF 76F853A2957699997BB189446E584E617FD479658BE660F354CD4EAB98795DF7 6A6150CF54118C618427785D9704524A54EE56A395006D885BB56DC666530000 D0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 882488258826882788288829882A882B882C882D882E882F8830883188338834 8835883688378838883A883B883D883E883F8841884288438846884788488849 884A884B884E884F8850885188528853885588568858885A885B885C885D885E 885F886088668867886A886D886F8871887388748875887688788879887A0000 887B887C88808883888688878889888A888C888E888F88908891889388948895 889788988899889A889B889D889E889F88A088A188A388A588A688A788A888A9 88AA5C0F5B5D6821809655787B11654869544E9B6B47874E978B534F631F643A 90AA659C80C18C10519968B0537887F961C86CC46CFB8C225C5185AA82AF950C 6B238F9B65B05FFB5FC34FE18845661F8165732960FA51745211578B5F6290A2 884C91925E78674F602759D3514451F680F853086C7996C4718A4F114FEE7F9E 673D55C5950879C088967EE3589F620C9700865A5618987B5F908BB884C49157 53D965ED5E8F755C60647D6E5A7F7EEA7EED8F6955A75BA360AC65CB73840000 D1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 88AC88AE88AF88B088B288B388B488B588B688B888B988BA88BB88BD88BE88BF 88C088C388C488C788C888CA88CB88CC88CD88CF88D088D188D388D688D788DA 88DB88DC88DD88DE88E088E188E688E788E988EA88EB88EC88ED88EE88EF88F2 88F588F688F788FA88FB88FD88FF890089018903890489058906890789080000 8909890B890C890D890E890F891189148915891689178918891C891D891E891F 89208922892389248926892789288929892C892D892E892F8931893289338935 89379009766377297EDA9774859B5B667A7496EA884052CB718F5FAA65EC8BE2 5BFB9A6F5DE16B896C5B8BAD8BAF900A8FC5538B62BC9E269E2D54404E2B82BD 7259869C5D1688596DAF96C554D14E9A8BB6710954BD960970DF6DF976D04E25 781487125CA95EF68A00989C960E708E6CBF594463A9773C884D6F1482735830 71D5538C781A96C155015F6671305BB48C1A9A8C6B83592E9E2F79E76768626C 4F6F75A17F8A6D0B96336C274EF075D2517B68376F3E90808170599674760000 D2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 89388939893A893B893C893D893E893F89408942894389458946894789488949 894A894B894C894D894E894F8950895189528953895489558956895789588959 895A895B895C895D896089618962896389648965896789688969896A896B896C 896D896E896F8970897189728973897489758976897789788979897A897C0000 897D897E8980898289848985898789888989898A898B898C898D898E898F8990 899189928993899489958996899789988999899A899B899C899D899E899F89A0 89A164475C2790657A918C2359DA54AC8200836F898180006930564E80367237 91CE51B64E5F987563964E1A53F666F3814B591C6DB24E0058F9533B63D694F1 4F9D4F0A886398905937905779FB4EEA80F075916C825B9C59E85F5D69058681 501A5DF24E5977E34EE5827A6291661390915C794EBF5F7981C69038808475AB 4EA688D4610F6BC55FC64E4976CA6EA28BE38BAE8C0A8BD15F027FFC7FCC7ECE 8335836B56E06BB797F3963459FB541F94F66DEB5BC5996E5C395F1596900000 D3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 89A289A389A489A589A689A789A889A989AA89AB89AC89AD89AE89AF89B089B1 89B289B389B489B589B689B789B889B989BA89BB89BC89BD89BE89BF89C089C3 89CD89D389D489D589D789D889D989DB89DD89DF89E089E189E289E489E789E8 89E989EA89EC89ED89EE89F089F189F289F489F589F689F789F889F989FA0000 89FB89FC89FD89FE89FF8A018A028A038A048A058A068A088A098A0A8A0B8A0C 8A0D8A0E8A0F8A108A118A128A138A148A158A168A178A188A198A1A8A1B8A1C 8A1D537082F16A315A749E705E947F2883B984248425836787478FCE8D6276C8 5F719896786C662054DF62E54F6381C375C85EB896CD8E0A86F9548F6CF36D8C 6C38607F52C775285E7D4F1860A05FE75C24753190AE94C072B96CB96E389149 670953CB53F34F5191C98BF153C85E7C8FC26DE44E8E76C26986865E611A8206 4F594FDE903E9C7C61096E1D6E1496854E885A3196E84E0E5C7F79B95B878BED 7FBD738957DF828B90C15401904755BB5CEA5FA161086B3272F180B28A890000 D4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8A1E8A1F8A208A218A228A238A248A258A268A278A288A298A2A8A2B8A2C8A2D 8A2E8A2F8A308A318A328A338A348A358A368A378A388A398A3A8A3B8A3C8A3D 8A3F8A408A418A428A438A448A458A468A478A498A4A8A4B8A4C8A4D8A4E8A4F 8A508A518A528A538A548A558A568A578A588A598A5A8A5B8A5C8A5D8A5E0000 8A5F8A608A618A628A638A648A658A668A678A688A698A6A8A6B8A6C8A6D8A6E 8A6F8A708A718A728A738A748A758A768A778A788A7A8A7B8A7C8A7D8A7E8A7F 8A806D745BD388D598848C6B9A6D9E336E0A51A4514357A38881539F63F48F95 56ED54585706733F6E907F188FDC82D1613F6028966266F07EA68D8A8DC394A5 5CB37CA4670860A6960580184E9190E75300966851418FD08574915D665597F5 5B55531D78386742683D54C9707E5BB08F7D518D572854B1651266828D5E8D43 810F846C906D7CDF51FF85FB67A365E96FA186A48E81566A90207682707671E5 8D2362E952196CFD8D3C600E589E618E66FE8D60624E55B36E23672D8F670000 D5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8A818A828A838A848A858A868A878A888A8B8A8C8A8D8A8E8A8F8A908A918A92 8A948A958A968A978A988A998A9A8A9B8A9C8A9D8A9E8A9F8AA08AA18AA28AA3 8AA48AA58AA68AA78AA88AA98AAA8AAB8AAC8AAD8AAE8AAF8AB08AB18AB28AB3 8AB48AB58AB68AB78AB88AB98ABA8ABB8ABC8ABD8ABE8ABF8AC08AC18AC20000 8AC38AC48AC58AC68AC78AC88AC98ACA8ACB8ACC8ACD8ACE8ACF8AD08AD18AD2 8AD38AD48AD58AD68AD78AD88AD98ADA8ADB8ADC8ADD8ADE8ADF8AE08AE18AE2 8AE394E195F87728680569A8548B4E4D70B88BC86458658B5B857A84503A5BE8 77BB6BE18A797C986CBE76CF65A98F975D2D5C5586386808536062187AD96E5B 7EFD6A1F7AE05F706F335F20638C6DA867564E085E108D264ED780C07634969C 62DB662D627E6CBC8D7571677F695146808753EC906E629854F286F08F998005 951785178FD96D5973CD659F771F7504782781FB8D1E94884FA6679575B98BCA 9707632F9547963584B8632377415F8172F04E896014657462EF6B63653F0000 D6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8AE48AE58AE68AE78AE88AE98AEA8AEB8AEC8AED8AEE8AEF8AF08AF18AF28AF3 8AF48AF58AF68AF78AF88AF98AFA8AFB8AFC8AFD8AFE8AFF8B008B018B028B03 8B048B058B068B088B098B0A8B0B8B0C8B0D8B0E8B0F8B108B118B128B138B14 8B158B168B178B188B198B1A8B1B8B1C8B1D8B1E8B1F8B208B218B228B230000 8B248B258B278B288B298B2A8B2B8B2C8B2D8B2E8B2F8B308B318B328B338B34 8B358B368B378B388B398B3A8B3B8B3C8B3D8B3E8B3F8B408B418B428B438B44 8B455E2775C790D18BC1829D679D652F5431871877E580A281026C414E4B7EC7 804C76F4690D6B966267503C4F84574063076B628DBE53EA65E87EB85FD7631A 63B781F381F47F6E5E1C5CD95236667A79E97A1A8D28709975D46EDE6CBB7A92 4E2D76C55FE0949F88777EC879CD80BF91CD4EF24F17821F54685DDE6D328BCC 7CA58F7480985E1A549276B15B99663C9AA473E0682A86DB6731732A8BF88BDB 90107AF970DB716E62C477A956314E3B845767F152A986C08D2E94F87B510000 D7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8B468B478B488B498B4A8B4B8B4C8B4D8B4E8B4F8B508B518B528B538B548B55 8B568B578B588B598B5A8B5B8B5C8B5D8B5E8B5F8B608B618B628B638B648B65 8B678B688B698B6A8B6B8B6D8B6E8B6F8B708B718B728B738B748B758B768B77 8B788B798B7A8B7B8B7C8B7D8B7E8B7F8B808B818B828B838B848B858B860000 8B878B888B898B8A8B8B8B8C8B8D8B8E8B8F8B908B918B928B938B948B958B96 8B978B988B998B9A8B9B8B9C8B9D8B9E8B9F8BAC8BB18BBB8BC78BD08BEA8C09 8C1E4F4F6CE8795D9A7B6293722A62FD4E1378168F6C64B08D5A7BC668695E84 88C55986649E58EE72B6690E95258FFD8D5857607F008C0651C6634962D95353 684C74228301914C55447740707C6D4A517954A88D4459FF6ECB6DC45B5C7D2B 4ED47C7D6ED35B5081EA6E0D5B579B0368D58E2A5B977EFC603B7EB590B98D70 594F63CD79DF8DB3535265CF79568BC5963B7EC494BB7E825634918967007F6A 5C0A907566285DE64F5067DE505A4F5C57505EA7000000000000000000000000 D8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8C388C398C3A8C3B8C3C8C3D8C3E8C3F8C408C428C438C448C458C488C4A8C4B 8C4D8C4E8C4F8C508C518C528C538C548C568C578C588C598C5B8C5C8C5D8C5E 8C5F8C608C638C648C658C668C678C688C698C6C8C6D8C6E8C6F8C708C718C72 8C748C758C768C778C7B8C7C8C7D8C7E8C7F8C808C818C838C848C868C870000 8C888C8B8C8D8C8E8C8F8C908C918C928C938C958C968C978C998C9A8C9B8C9C 8C9D8C9E8C9F8CA08CA18CA28CA38CA48CA58CA68CA78CA88CA98CAA8CAB8CAC 8CAD4E8D4E0C51404E105EFF53454E154E984E1E9B325B6C56694E2879BA4E3F 53154E47592D723B536E6C1056DF80E499976BD3777E9F174E364E9F9F104E5C 4E694E9382885B5B556C560F4EC4538D539D53A353A553AE97658D5D531A53F5 5326532E533E8D5C5366536352025208520E522D5233523F5240524C525E5261 525C84AF527D528252815290529351827F544EBB4EC34EC94EC24EE84EE14EEB 4EDE4F1B4EF34F224F644EF54F254F274F094F2B4F5E4F6765384F5A4F5D0000 D9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8CAE8CAF8CB08CB18CB28CB38CB48CB58CB68CB78CB88CB98CBA8CBB8CBC8CBD 8CBE8CBF8CC08CC18CC28CC38CC48CC58CC68CC78CC88CC98CCA8CCB8CCC8CCD 8CCE8CCF8CD08CD18CD28CD38CD48CD58CD68CD78CD88CD98CDA8CDB8CDC8CDD 8CDE8CDF8CE08CE18CE28CE38CE48CE58CE68CE78CE88CE98CEA8CEB8CEC0000 8CED8CEE8CEF8CF08CF18CF28CF38CF48CF58CF68CF78CF88CF98CFA8CFB8CFC 8CFD8CFE8CFF8D008D018D028D038D048D058D068D078D088D098D0A8D0B8D0C 8D0D4F5F4F574F324F3D4F764F744F914F894F834F8F4F7E4F7B4FAA4F7C4FAC 4F944FE64FE84FEA4FC54FDA4FE34FDC4FD14FDF4FF85029504C4FF3502C500F 502E502D4FFE501C500C50255028507E504350555048504E506C507B50A550A7 50A950BA50D6510650ED50EC50E650EE5107510B4EDD6C3D4F584F654FCE9FA0 6C467C74516E5DFD9EC999985181591452F9530D8A07531051EB591951554EA0 51564EB3886E88A44EB5811488D279805B3488037FB851AB51B151BD51BC0000 DA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8D0E8D0F8D108D118D128D138D148D158D168D178D188D198D1A8D1B8D1C8D20 8D518D528D578D5F8D658D688D698D6A8D6C8D6E8D6F8D718D728D788D798D7A 8D7B8D7C8D7D8D7E8D7F8D808D828D838D868D878D888D898D8C8D8D8D8E8D8F 8D908D928D938D958D968D978D988D998D9A8D9B8D9C8D9D8D9E8DA08DA10000 8DA28DA48DA58DA68DA78DA88DA98DAA8DAB8DAC8DAD8DAE8DAF8DB08DB28DB6 8DB78DB98DBB8DBD8DC08DC18DC28DC58DC78DC88DC98DCA8DCD8DD08DD28DD3 8DD451C7519651A251A58BA08BA68BA78BAA8BB48BB58BB78BC28BC38BCB8BCF 8BCE8BD28BD38BD48BD68BD88BD98BDC8BDF8BE08BE48BE88BE98BEE8BF08BF3 8BF68BF98BFC8BFF8C008C028C048C078C0C8C0F8C118C128C148C158C168C19 8C1B8C188C1D8C1F8C208C218C258C278C2A8C2B8C2E8C2F8C328C338C358C36 5369537A961D962296219631962A963D963C964296499654965F9667966C9672 96749688968D969796B09097909B909D909990AC90A190B490B390B690BA0000 DB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8DD58DD88DD98DDC8DE08DE18DE28DE58DE68DE78DE98DED8DEE8DF08DF18DF2 8DF48DF68DFC8DFE8DFF8E008E018E028E038E048E068E078E088E0B8E0D8E0E 8E108E118E128E138E158E168E178E188E198E1A8E1B8E1C8E208E218E248E25 8E268E278E288E2B8E2D8E308E328E338E348E368E378E388E3B8E3C8E3E0000 8E3F8E438E458E468E4C8E4D8E4E8E4F8E508E538E548E558E568E578E588E5A 8E5B8E5C8E5D8E5E8E5F8E608E618E628E638E648E658E678E688E6A8E6B8E6E 8E7190B890B090CF90C590BE90D090C490C790D390E690E290DC90D790DB90EB 90EF90FE91049122911E91239131912F913991439146520D594252A252AC52AD 52BE54FF52D052D652F053DF71EE77CD5EF451F551FC9B2F53B65F01755A5DEF 574C57A957A1587E58BC58C558D15729572C572A57335739572E572F575C573B 574257695785576B5786577C577B5768576D5776577357AD57A4578C57B257CF 57A757B4579357A057D557D857DA57D957D257B857F457EF57F857E457DD0000 DC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8E738E758E778E788E798E7A8E7B8E7D8E7E8E808E828E838E848E868E888E89 8E8A8E8B8E8C8E8D8E8E8E918E928E938E958E968E978E988E998E9A8E9B8E9D 8E9F8EA08EA18EA28EA38EA48EA58EA68EA78EA88EA98EAA8EAD8EAE8EB08EB1 8EB38EB48EB58EB68EB78EB88EB98EBB8EBC8EBD8EBE8EBF8EC08EC18EC20000 8EC38EC48EC58EC68EC78EC88EC98ECA8ECB8ECC8ECD8ECF8ED08ED18ED28ED3 8ED48ED58ED68ED78ED88ED98EDA8EDB8EDC8EDD8EDE8EDF8EE08EE18EE28EE3 8EE4580B580D57FD57ED5800581E5819584458205865586C58815889589A5880 99A89F1961FF8279827D827F828F828A82A88284828E82918297829982AB82B8 82BE82B082C882CA82E3829882B782AE82CB82CC82C182A982B482A182AA829F 82C482CE82A482E1830982F782E4830F830782DC82F482D282D8830C82FB82D3 8311831A83068314831582E082D5831C8351835B835C83088392833C83348331 839B835E832F834F83478343835F834083178360832D833A8333836683650000 DD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8EE58EE68EE78EE88EE98EEA8EEB8EEC8EED8EEE8EEF8EF08EF18EF28EF38EF4 8EF58EF68EF78EF88EF98EFA8EFB8EFC8EFD8EFE8EFF8F008F018F028F038F04 8F058F068F078F088F098F0A8F0B8F0C8F0D8F0E8F0F8F108F118F128F138F14 8F158F168F178F188F198F1A8F1B8F1C8F1D8F1E8F1F8F208F218F228F230000 8F248F258F268F278F288F298F2A8F2B8F2C8F2D8F2E8F2F8F308F318F328F33 8F348F358F368F378F388F398F3A8F3B8F3C8F3D8F3E8F3F8F408F418F428F43 8F448368831B8369836C836A836D836E83B0837883B383B483A083AA8393839C 8385837C83B683A9837D83B8837B8398839E83A883BA83BC83C1840183E583D8 58078418840B83DD83FD83D6841C84388411840683D483DF840F840383F883F9 83EA83C583C0842683F083E1845C8451845A8459847384878488847A84898478 843C844684698476848C848E8431846D84C184CD84D084E684BD84D384CA84BF 84BA84E084A184B984B4849784E584E3850C750D853884F08539851F853A0000 DE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8F458F468F478F488F498F4A8F4B8F4C8F4D8F4E8F4F8F508F518F528F538F54 8F558F568F578F588F598F5A8F5B8F5C8F5D8F5E8F5F8F608F618F628F638F64 8F658F6A8F808F8C8F928F9D8FA08FA18FA28FA48FA58FA68FA78FAA8FAC8FAD 8FAE8FAF8FB28FB38FB48FB58FB78FB88FBA8FBB8FBC8FBF8FC08FC38FC60000 8FC98FCA8FCB8FCC8FCD8FCF8FD28FD68FD78FDA8FE08FE18FE38FE78FEC8FEF 8FF18FF28FF48FF58FF68FFA8FFB8FFC8FFE8FFF90079008900C900E90139015 90188556853B84FF84FC8559854885688564855E857A77A285438572857B85A4 85A88587858F857985AE859C858585B985B785B085D385C185DC85FF86278605 86298616863C5EFE5F08593C594180375955595A5958530F5C225C255C2C5C34 624C626A629F62BB62CA62DA62D762EE632262F66339634B634363AD63F66371 637A638E63B4636D63AC638A636963AE63BC63F263F863E063FF63C463DE63CE 645263C663BE64456441640B641B6420640C64266421645E6484646D64960000 DF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9019901C902390249025902790289029902A902B902C90309031903290339034 90379039903A903D903F904090439045904690489049904A904B904C904E9054 905590569059905A905C905D905E905F906090619064906690679069906A906B 906C906F90709071907290739076907790789079907A907B907C907E90810000 90849085908690879089908A908C908D908E908F90909092909490969098909A 909C909E909F90A090A490A590A790A890A990AB90AD90B290B790BC90BD90BF 90C0647A64B764B8649964BA64C064D064D764E464E265096525652E5F0B5FD2 75195F11535F53F153FD53E953E853FB541254165406544B5452545354545456 54435421545754595423543254825494547754715464549A549B548454765466 549D54D054AD54C254B454D254A754A654D354D4547254A354D554BB54BF54CC 54D954DA54DC54A954AA54A454DD54CF54DE551B54E7552054FD551454F35522 5523550F55115527552A5567558F55B55549556D55415555553F5550553C0000 E0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 90C290C390C690C890C990CB90CC90CD90D290D490D590D690D890D990DA90DE 90DF90E090E390E490E590E990EA90EC90EE90F090F190F290F390F590F690F7 90F990FA90FB90FC90FF91009101910391059106910791089109910A910B910C 910D910E910F911091119112911391149115911691179118911A911B911C0000 911D911F91209121912491259126912791289129912A912B912C912D912E9130 9132913391349135913691379138913A913B913C913D913E913F914091419142 91445537555655755576557755335530555C558B55D2558355B155B955885581 559F557E55D65591557B55DF55BD55BE5594559955EA55F755C9561F55D155EB 55EC55D455E655DD55C455EF55E555F255F355CC55CD55E855F555E48F94561E 5608560C56015624562355FE56005627562D565856395657562C564D56625659 565C564C5654568656645671566B567B567C5685569356AF56D456D756DD56E1 56F556EB56F956FF5704570A5709571C5E0F5E195E145E115E315E3B5E3C0000 E1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9145914791489151915391549155915691589159915B915C915F916091669167 9168916B916D9173917A917B917C9180918191829183918491869188918A918E 918F9193919491959196919791989199919C919D919E919F91A091A191A491A5 91A691A791A891A991AB91AC91B091B191B291B391B691B791B891B991BB0000 91BC91BD91BE91BF91C091C191C291C391C491C591C691C891CB91D091D291D3 91D491D591D691D791D891D991DA91DB91DD91DE91DF91E091E191E291E391E4 91E55E375E445E545E5B5E5E5E615C8C5C7A5C8D5C905C965C885C985C995C91 5C9A5C9C5CB55CA25CBD5CAC5CAB5CB15CA35CC15CB75CC45CD25CE45CCB5CE5 5D025D035D275D265D2E5D245D1E5D065D1B5D585D3E5D345D3D5D6C5D5B5D6F 5D5D5D6B5D4B5D4A5D695D745D825D995D9D8C735DB75DC55F735F775F825F87 5F895F8C5F955F995F9C5FA85FAD5FB55FBC88625F6172AD72B072B472B772B8 72C372C172CE72CD72D272E872EF72E972F272F472F7730172F3730372FA0000 E2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 91E691E791E891E991EA91EB91EC91ED91EE91EF91F091F191F291F391F491F5 91F691F791F891F991FA91FB91FC91FD91FE91FF920092019202920392049205 9206920792089209920A920B920C920D920E920F921092119212921392149215 9216921792189219921A921B921C921D921E921F922092219222922392240000 92259226922792289229922A922B922C922D922E922F92309231923292339234 92359236923792389239923A923B923C923D923E923F92409241924292439244 924572FB731773137321730A731E731D7315732273397325732C733873317350 734D73577360736C736F737E821B592598E7592459029963996799689969996A 996B996C99749977997D998099849987998A998D999099919993999499955E80 5E915E8B5E965EA55EA05EB95EB55EBE5EB38D535ED25ED15EDB5EE85EEA81BA 5FC45FC95FD65FCF60035FEE60045FE15FE45FFE600560065FEA5FED5FF86019 60356026601B600F600D6029602B600A603F602160786079607B607A60420000 E3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9246924792489249924A924B924C924D924E924F925092519252925392549255 9256925792589259925A925B925C925D925E925F926092619262926392649265 9266926792689269926A926B926C926D926E926F927092719272927392759276 927792789279927A927B927C927D927E927F9280928192829283928492850000 9286928792889289928A928B928C928D928F9290929192929293929492959296 929792989299929A929B929C929D929E929F92A092A192A292A392A492A592A6 92A7606A607D6096609A60AD609D60836092608C609B60EC60BB60B160DD60D8 60C660DA60B4612061266115612360F46100610E612B614A617561AC619461A7 61B761D461F55FDD96B395E995EB95F195F395F595F695FC95FE960396049606 9608960A960B960C960D960F96129615961696179619961A4E2C723F62156C35 6C546C5C6C4A6CA36C856C906C946C8C6C686C696C746C766C866CA96CD06CD4 6CAD6CF76CF86CF16CD76CB26CE06CD66CFA6CEB6CEE6CB16CD36CEF6CFE0000 E4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 92A892A992AA92AB92AC92AD92AF92B092B192B292B392B492B592B692B792B8 92B992BA92BB92BC92BD92BE92BF92C092C192C292C392C492C592C692C792C9 92CA92CB92CC92CD92CE92CF92D092D192D292D392D492D592D692D792D892D9 92DA92DB92DC92DD92DE92DF92E092E192E292E392E492E592E692E792E80000 92E992EA92EB92EC92ED92EE92EF92F092F192F292F392F492F592F692F792F8 92F992FA92FB92FC92FD92FE92FF930093019302930393049305930693079308 93096D396D276D0C6D436D486D076D046D196D0E6D2B6D4D6D2E6D356D1A6D4F 6D526D546D336D916D6F6D9E6DA06D5E6D936D946D5C6D606D7C6D636E1A6DC7 6DC56DDE6E0E6DBF6DE06E116DE66DDD6DD96E166DAB6E0C6DAE6E2B6E6E6E4E 6E6B6EB26E5F6E866E536E546E326E256E446EDF6EB16E986EE06F2D6EE26EA5 6EA76EBD6EBB6EB76ED76EB46ECF6E8F6EC26E9F6F626F466F476F246F156EF9 6F2F6F366F4B6F746F2A6F096F296F896F8D6F8C6F786F726F7C6F7A6FD10000 E5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 930A930B930C930D930E930F9310931193129313931493159316931793189319 931A931B931C931D931E931F9320932193229323932493259326932793289329 932A932B932C932D932E932F9330933193329333933493359336933793389339 933A933B933C933D933F93409341934293439344934593469347934893490000 934A934B934C934D934E934F9350935193529353935493559356935793589359 935A935B935C935D935E935F9360936193629363936493659366936793689369 936B6FC96FA76FB96FB66FC26FE16FEE6FDE6FE06FEF701A7023701B70397035 704F705E5B805B845B955B935BA55BB8752F9A9E64345BE45BEE89305BF08E47 8B078FB68FD38FD58FE58FEE8FE48FE98FE68FF38FE890059004900B90269011 900D9016902190359036902D902F9044905190529050906890589062905B66B9 9074907D908290889083908B5F505F575F565F585C3B54AB5C505C595B715C63 5C667FBC5F2A5F295F2D82745F3C9B3B5C6E59815983598D59A959AA59A30000 E6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 936C936D936E936F9370937193729373937493759376937793789379937A937B 937C937D937E937F9380938193829383938493859386938793889389938A938B 938C938D938E9390939193929393939493959396939793989399939A939B939C 939D939E939F93A093A193A293A393A493A593A693A793A893A993AA93AB0000 93AC93AD93AE93AF93B093B193B293B393B493B593B693B793B893B993BA93BB 93BC93BD93BE93BF93C093C193C293C393C493C593C693C793C893C993CB93CC 93CD599759CA59AB599E59A459D259B259AF59D759BE5A055A0659DD5A0859E3 59D859F95A0C5A095A325A345A115A235A135A405A675A4A5A555A3C5A625A75 80EC5AAA5A9B5A775A7A5ABE5AEB5AB25AD25AD45AB85AE05AE35AF15AD65AE6 5AD85ADC5B095B175B165B325B375B405C155C1C5B5A5B655B735B515B535B62 9A759A779A789A7A9A7F9A7D9A809A819A859A889A8A9A909A929A939A969A98 9A9B9A9C9A9D9A9F9AA09AA29AA39AA59AA77E9F7EA17EA37EA57EA87EA90000 E7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 93CE93CF93D093D193D293D393D493D593D793D893D993DA93DB93DC93DD93DE 93DF93E093E193E293E393E493E593E693E793E893E993EA93EB93EC93ED93EE 93EF93F093F193F293F393F493F593F693F793F893F993FA93FB93FC93FD93FE 93FF9400940194029403940494059406940794089409940A940B940C940D0000 940E940F9410941194129413941494159416941794189419941A941B941C941D 941E941F9420942194229423942494259426942794289429942A942B942C942D 942E7EAD7EB07EBE7EC07EC17EC27EC97ECB7ECC7ED07ED47ED77EDB7EE07EE1 7EE87EEB7EEE7EEF7EF17EF27F0D7EF67EFA7EFB7EFE7F017F027F037F077F08 7F0B7F0C7F0F7F117F127F177F197F1C7F1B7F1F7F217F227F237F247F257F26 7F277F2A7F2B7F2C7F2D7F2F7F307F317F327F337F355E7A757F5DDB753E9095 738E739173AE73A2739F73CF73C273D173B773B373C073C973C873E573D9987C 740A73E973E773DE73BA73F2740F742A745B7426742574287430742E742C0000 E8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 942F9430943194329433943494359436943794389439943A943B943C943D943F 9440944194429443944494459446944794489449944A944B944C944D944E944F 9450945194529453945494559456945794589459945A945B945C945D945E945F 9460946194629463946494659466946794689469946A946C946D946E946F0000 9470947194729473947494759476947794789479947A947B947C947D947E947F 9480948194829483948494919496949894C794CF94D394D494DA94E694FB951C 9520741B741A7441745C7457745574597477746D747E749C748E748074817487 748B749E74A874A9749074A774D274BA97EA97EB97EC674C6753675E67486769 67A56787676A6773679867A7677567A8679E67AD678B6777677C67F0680967D8 680A67E967B0680C67D967B567DA67B367DD680067C367B867E2680E67C167FD 6832683368606861684E6862684468646883681D68556866684168676840683E 684A6849682968B5688F687468776893686B68C2696E68FC691F692068F90000 E9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 95279533953D95439548954B9555955A9560956E95749575957795789579957A 957B957C957D957E9580958195829583958495859586958795889589958A958B 958C958D958E958F9590959195929593959495959596959795989599959A959B 959C959D959E959F95A095A195A295A395A495A595A695A795A895A995AA0000 95AB95AC95AD95AE95AF95B095B195B295B395B495B595B695B795B895B995BA 95BB95BC95BD95BE95BF95C095C195C295C395C495C595C695C795C895C995CA 95CB692468F0690B6901695768E369106971693969606942695D6984696B6980 69986978693469CC6987698869CE6989696669636979699B69A769BB69AB69AD 69D469B169C169CA69DF699569E0698D69FF6A2F69ED6A176A186A6569F26A44 6A3E6AA06A506A5B6A356A8E6A796A3D6A286A586A7C6A916A906AA96A976AAB 733773526B816B826B876B846B926B936B8D6B9A6B9B6BA16BAA8F6B8F6D8F71 8F728F738F758F768F788F778F798F7A8F7C8F7E8F818F828F848F878F8B0000 EA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 95CC95CD95CE95CF95D095D195D295D395D495D595D695D795D895D995DA95DB 95DC95DD95DE95DF95E095E195E295E395E495E595E695E795EC95FF96079613 9618961B961E96209623962496259626962796289629962B962C962D962F9630 963796389639963A963E96419643964A964E964F965196529653965696570000 96589659965A965C965D965E9660966396659666966B966D966E966F96709671 967396789679967A967B967C967D967E967F9680968196829683968496879689 968A8F8D8F8E8F8F8F988F9A8ECE620B6217621B621F6222622162256224622C 81E774EF74F474FF750F75117513653465EE65EF65F0660A6619677266036615 6600708566F7661D66346631663666358006665F66546641664F665666616657 66776684668C66A7669D66BE66DB66DC66E666E98D328D338D368D3B8D3D8D40 8D458D468D488D498D478D4D8D558D5989C789CA89CB89CC89CE89CF89D089D1 726E729F725D7266726F727E727F7284728B728D728F72926308633263B00000 EB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 968C968E96919692969396959696969A969B969D969E969F96A096A196A296A3 96A496A596A696A896A996AA96AB96AC96AD96AE96AF96B196B296B496B596B7 96B896BA96BB96BF96C296C396C896CA96CB96D096D196D396D496D696D796D8 96D996DA96DB96DC96DD96DE96DF96E196E296E396E496E596E696E796EB0000 96EC96ED96EE96F096F196F296F496F596F896FA96FB96FC96FD96FF97029703 9705970A970B970C97109711971297149715971797189719971A971B971D971F 9720643F64D880046BEA6BF36BFD6BF56BF96C056C076C066C0D6C156C186C19 6C1A6C216C296C246C2A6C3265356555656B724D72527256723086625216809F 809C809380BC670A80BD80B180AB80AD80B480B780E780E880E980EA80DB80C2 80C480D980CD80D7671080DD80EB80F180F480ED810D810E80F280FC67158112 8C5A8136811E812C811881328148814C815381748159815A817181608169817C 817D816D8167584D5AB58188818281916ED581A381AA81CC672681CA81BB0000 EC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 972197229723972497259726972797289729972B972C972E972F973197339734 973597369737973A973B973C973D973F97409741974297439744974597469747 97489749974A974B974C974D974E974F975097519754975597579758975A975C 975D975F97639764976697679768976A976B976C976D976E976F977097710000 97729775977797789779977A977B977D977E977F978097819782978397849786 978797889789978A978C978E978F979097939795979697979799979A979B979C 979D81C181A66B246B376B396B436B466B5998D198D298D398D598D998DA6BB3 5F406BC289F365909F51659365BC65C665C465C365CC65CE65D265D67080709C 7096709D70BB70C070B770AB70B170E870CA711071137116712F71317173715C 716871457172714A7178717A719871B371B571A871A071E071D471E771F9721D 7228706C7118716671B9623E623D624362486249793B794079467949795B795C 7953795A796279577960796F7967797A7985798A799A79A779B35FD15FD00000 ED 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 979E979F97A197A297A497A597A697A797A897A997AA97AC97AE97B097B197B3 97B597B697B797B897B997BA97BB97BC97BD97BE97BF97C097C197C297C397C4 97C597C697C797C897C997CA97CB97CC97CD97CE97CF97D097D197D297D397D4 97D597D697D797D897D997DA97DB97DC97DD97DE97DF97E097E197E297E30000 97E497E597E897EE97EF97F097F197F297F497F797F897F997FA97FB97FC97FD 97FE97FF9800980198029803980498059806980798089809980A980B980C980D 980E603C605D605A606760416059606360AB6106610D615D61A9619D61CB61D1 62068080807F6C936CF66DFC77F677F87800780978177818781165AB782D781C 781D7839783A783B781F783C7825782C78237829784E786D7856785778267850 7847784C786A789B7893789A7887789C78A178A378B278B978A578D478D978C9 78EC78F2790578F479137924791E79349F9B9EF99EFB9EFC76F17704770D76F9 77077708771A77227719772D7726773577387750775177477743775A77680000 EE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 980F9810981198129813981498159816981798189819981A981B981C981D981E 981F9820982198229823982498259826982798289829982A982B982C982D982E 982F9830983198329833983498359836983798389839983A983B983C983D983E 983F9840984198429843984498459846984798489849984A984B984C984D0000 984E984F9850985198529853985498559856985798589859985A985B985C985D 985E985F9860986198629863986498659866986798689869986A986B986C986D 986E77627765777F778D777D7780778C7791779F77A077B077B577BD753A7540 754E754B7548755B7572757975837F587F617F5F8A487F687F747F717F797F81 7F7E76CD76E58832948594869487948B948A948C948D948F9490949494979495 949A949B949C94A394A494AB94AA94AD94AC94AF94B094B294B494B694B794B8 94B994BA94BC94BD94BF94C494C894C994CA94CB94CC94CD94CE94D094D194D2 94D594D694D794D994D894DB94DE94DF94E094E294E494E594E794E894EA0000 EF 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 986F98709871987298739874988B988E98929895989998A398A898A998AA98AB 98AC98AD98AE98AF98B098B198B298B398B498B598B698B798B898B998BA98BB 98BC98BD98BE98BF98C098C198C298C398C498C598C698C798C898C998CA98CB 98CC98CD98CF98D098D498D698D798DB98DC98DD98E098E198E298E398E40000 98E598E698E998EA98EB98EC98ED98EE98EF98F098F198F298F398F498F598F6 98F798F898F998FA98FB98FC98FD98FE98FF9900990199029903990499059906 990794E994EB94EE94EF94F394F494F594F794F994FC94FD94FF950395029506 95079509950A950D950E950F951295139514951595169518951B951D951E951F 9522952A952B9529952C953195329534953695379538953C953E953F95429535 9544954595469549954C954E954F9552955395549556955795589559955B955E 955F955D95619562956495659566956795689569956A956B956C956F95719572 9573953A77E777EC96C979D579ED79E379EB7A065D477A037A027A1E7A140000 F0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 99089909990A990B990C990E990F991199129913991499159916991799189919 991A991B991C991D991E991F9920992199229923992499259926992799289929 992A992B992C992D992F9930993199329933993499359936993799389939993A 993B993C993D993E993F99409941994299439944994599469947994899490000 994A994B994C994D994E994F99509951995299539956995799589959995A995B 995C995D995E995F99609961996299649966997399789979997B997E99829983 99897A397A377A519ECF99A57A707688768E7693769976A474DE74E0752C9E20 9E229E289E299E2A9E2B9E2C9E329E319E369E389E379E399E3A9E3E9E419E42 9E449E469E479E489E499E4B9E4C9E4E9E519E559E579E5A9E5B9E5C9E5E9E63 9E669E679E689E699E6A9E6B9E6C9E719E6D9E7375927594759675A0759D75AC 75A375B375B475B875C475B175B075C375C275D675CD75E375E875E675E475EB 75E7760375F175FC75FF761076007605760C7617760A76257618761576190000 F1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 998C998E999A999B999C999D999E999F99A099A199A299A399A499A699A799A9 99AA99AB99AC99AD99AE99AF99B099B199B299B399B499B599B699B799B899B9 99BA99BB99BC99BD99BE99BF99C099C199C299C399C499C599C699C799C899C9 99CA99CB99CC99CD99CE99CF99D099D199D299D399D499D599D699D799D80000 99D999DA99DB99DC99DD99DE99DF99E099E199E299E399E499E599E699E799E8 99E999EA99EB99EC99ED99EE99EF99F099F199F299F399F499F599F699F799F8 99F9761B763C762276207640762D7630763F76357643763E7633764D765E7654 765C7656766B766F7FCA7AE67A787A797A807A867A887A957AA67AA07AAC7AA8 7AAD7AB3886488698872887D887F888288A288C688B788BC88C988E288CE88E3 88E588F1891A88FC88E888FE88F0892189198913891B890A8934892B89368941 8966897B758B80E576B276B477DC801280148016801C80208022802580268027 802980288031800B803580438046804D80528069807189839878988098830000 F2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 99FA99FB99FC99FD99FE99FF9A009A019A029A039A049A059A069A079A089A09 9A0A9A0B9A0C9A0D9A0E9A0F9A109A119A129A139A149A159A169A179A189A19 9A1A9A1B9A1C9A1D9A1E9A1F9A209A219A229A239A249A259A269A279A289A29 9A2A9A2B9A2C9A2D9A2E9A2F9A309A319A329A339A349A359A369A379A380000 9A399A3A9A3B9A3C9A3D9A3E9A3F9A409A419A429A439A449A459A469A479A48 9A499A4A9A4B9A4C9A4D9A4E9A4F9A509A519A529A539A549A559A569A579A58 9A599889988C988D988F9894989A989B989E989F98A198A298A598A6864D8654 866C866E867F867A867C867B86A8868D868B86AC869D86A786A386AA869386A9 86B686C486B586CE86B086BA86B186AF86C986CF86B486E986F186F286ED86F3 86D0871386DE86F486DF86D886D18703870786F88708870A870D87098723873B 871E8725872E871A873E87488734873187298737873F87828722877D877E877B 87608770874C876E878B87538763877C876487598765879387AF87A887D20000 F3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9A5A9A5B9A5C9A5D9A5E9A5F9A609A619A629A639A649A659A669A679A689A69 9A6A9A6B9A729A839A899A8D9A8E9A949A959A999AA69AA99AAA9AAB9AAC9AAD 9AAE9AAF9AB29AB39AB49AB59AB99ABB9ABD9ABE9ABF9AC39AC49AC69AC79AC8 9AC99ACA9ACD9ACE9ACF9AD09AD29AD49AD59AD69AD79AD99ADA9ADB9ADC0000 9ADD9ADE9AE09AE29AE39AE49AE59AE79AE89AE99AEA9AEC9AEE9AF09AF19AF2 9AF39AF49AF59AF69AF79AF89AFA9AFC9AFD9AFE9AFF9B009B019B029B049B05 9B0687C68788878587AD8797878387AB87E587AC87B587B387CB87D387BD87D1 87C087CA87DB87EA87E087EE8816881387FE880A881B88218839883C7F367F42 7F447F4582107AFA7AFD7B087B037B047B157B0A7B2B7B0F7B477B387B2A7B19 7B2E7B317B207B257B247B337B3E7B1E7B587B5A7B457B757B4C7B5D7B607B6E 7B7B7B627B727B717B907BA67BA77BB87BAC7B9D7BA87B857BAA7B9C7BA27BAB 7BB47BD17BC17BCC7BDD7BDA7BE57BE67BEA7C0C7BFE7BFC7C0F7C167C0B0000 F4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9B079B099B0A9B0B9B0C9B0D9B0E9B109B119B129B149B159B169B179B189B19 9B1A9B1B9B1C9B1D9B1E9B209B219B229B249B259B269B279B289B299B2A9B2B 9B2C9B2D9B2E9B309B319B339B349B359B369B379B389B399B3A9B3D9B3E9B3F 9B409B469B4A9B4B9B4C9B4E9B509B529B539B559B569B579B589B599B5A0000 9B5B9B5C9B5D9B5E9B5F9B609B619B629B639B649B659B669B679B689B699B6A 9B6B9B6C9B6D9B6E9B6F9B709B719B729B739B749B759B769B779B789B799B7A 9B7B7C1F7C2A7C267C387C417C4081FE82018202820481EC8844822182228223 822D822F8228822B8238823B82338234823E82448249824B824F825A825F8268 887E8885888888D888DF895E7F9D7F9F7FA77FAF7FB07FB27C7C65497C917C9D 7C9C7C9E7CA27CB27CBC7CBD7CC17CC77CCC7CCD7CC87CC57CD77CE8826E66A8 7FBF7FCE7FD57FE57FE17FE67FE97FEE7FF37CF87D777DA67DAE7E477E9B9EB8 9EB48D738D848D948D918DB18D678D6D8C478C49914A9150914E914F91640000 F5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9B7C9B7D9B7E9B7F9B809B819B829B839B849B859B869B879B889B899B8A9B8B 9B8C9B8D9B8E9B8F9B909B919B929B939B949B959B969B979B989B999B9A9B9B 9B9C9B9D9B9E9B9F9BA09BA19BA29BA39BA49BA59BA69BA79BA89BA99BAA9BAB 9BAC9BAD9BAE9BAF9BB09BB19BB29BB39BB49BB59BB69BB79BB89BB99BBA0000 9BBB9BBC9BBD9BBE9BBF9BC09BC19BC29BC39BC49BC59BC69BC79BC89BC99BCA 9BCB9BCC9BCD9BCE9BCF9BD09BD19BD29BD39BD49BD59BD69BD79BD89BD99BDA 9BDB9162916191709169916F917D917E917291749179918C91859190918D9191 91A291A391AA91AD91AE91AF91B591B491BA8C559E7E8DB88DEB8E058E598E69 8DB58DBF8DBC8DBA8DC48DD68DD78DDA8DDE8DCE8DCF8DDB8DC68DEC8DF78DF8 8DE38DF98DFB8DE48E098DFD8E148E1D8E1F8E2C8E2E8E238E2F8E3A8E408E39 8E358E3D8E318E498E418E428E518E528E4A8E708E768E7C8E6F8E748E858E8F 8E948E908E9C8E9E8C788C828C8A8C858C988C94659B89D689DE89DA89DC0000 F6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9BDC9BDD9BDE9BDF9BE09BE19BE29BE39BE49BE59BE69BE79BE89BE99BEA9BEB 9BEC9BED9BEE9BEF9BF09BF19BF29BF39BF49BF59BF69BF79BF89BF99BFA9BFB 9BFC9BFD9BFE9BFF9C009C019C029C039C049C059C069C079C089C099C0A9C0B 9C0C9C0D9C0E9C0F9C109C119C129C139C149C159C169C179C189C199C1A0000 9C1B9C1C9C1D9C1E9C1F9C209C219C229C239C249C259C269C279C289C299C2A 9C2B9C2C9C2D9C2E9C2F9C309C319C329C339C349C359C369C379C389C399C3A 9C3B89E589EB89EF8A3E8B26975396E996F396EF970697019708970F970E972A 972D9730973E9F809F839F859F869F879F889F899F8A9F8C9EFE9F0B9F0D96B9 96BC96BD96CE96D277BF96E0928E92AE92C8933E936A93CA938F943E946B9C7F 9C829C859C869C879C887A239C8B9C8E9C909C919C929C949C959C9A9C9B9C9E 9C9F9CA09CA19CA29CA39CA59CA69CA79CA89CA99CAB9CAD9CAE9CB09CB19CB2 9CB39CB49CB59CB69CB79CBA9CBB9CBC9CBD9CC49CC59CC69CC79CCA9CCB0000 F7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9C3C9C3D9C3E9C3F9C409C419C429C439C449C459C469C479C489C499C4A9C4B 9C4C9C4D9C4E9C4F9C509C519C529C539C549C559C569C579C589C599C5A9C5B 9C5C9C5D9C5E9C5F9C609C619C629C639C649C659C669C679C689C699C6A9C6B 9C6C9C6D9C6E9C6F9C709C719C729C739C749C759C769C779C789C799C7A0000 9C7B9C7D9C7E9C809C839C849C899C8A9C8C9C8F9C939C969C979C989C999C9D 9CAA9CAC9CAF9CB99CBE9CBF9CC09CC19CC29CC89CC99CD19CD29CDA9CDB9CE0 9CE19CCC9CCD9CCE9CCF9CD09CD39CD49CD59CD79CD89CD99CDC9CDD9CDF9CE2 977C978597919792979497AF97AB97A397B297B49AB19AB09AB79E589AB69ABA 9ABC9AC19AC09AC59AC29ACB9ACC9AD19B459B439B479B499B489B4D9B5198E8 990D992E995599549ADF9AE19AE69AEF9AEB9AFB9AED9AF99B089B0F9B139B1F 9B239EBD9EBE7E3B9E829E879E889E8B9E9293D69E9D9E9F9EDB9EDC9EDD9EE0 9EDF9EE29EE99EE79EE59EEA9EEF9F229F2C9F2F9F399F379F3D9F3E9F440000 F8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9CE39CE49CE59CE69CE79CE89CE99CEA9CEB9CEC9CED9CEE9CEF9CF09CF19CF2 9CF39CF49CF59CF69CF79CF89CF99CFA9CFB9CFC9CFD9CFE9CFF9D009D019D02 9D039D049D059D069D079D089D099D0A9D0B9D0C9D0D9D0E9D0F9D109D119D12 9D139D149D159D169D179D189D199D1A9D1B9D1C9D1D9D1E9D1F9D209D210000 9D229D239D249D259D269D279D289D299D2A9D2B9D2C9D2D9D2E9D2F9D309D31 9D329D339D349D359D369D379D389D399D3A9D3B9D3C9D3D9D3E9D3F9D409D41 9D42000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 F9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9D439D449D459D469D479D489D499D4A9D4B9D4C9D4D9D4E9D4F9D509D519D52 9D539D549D559D569D579D589D599D5A9D5B9D5C9D5D9D5E9D5F9D609D619D62 9D639D649D659D669D679D689D699D6A9D6B9D6C9D6D9D6E9D6F9D709D719D72 9D739D749D759D769D779D789D799D7A9D7B9D7C9D7D9D7E9D7F9D809D810000 9D829D839D849D859D869D879D889D899D8A9D8B9D8C9D8D9D8E9D8F9D909D91 9D929D939D949D959D969D979D989D999D9A9D9B9D9C9D9D9D9E9D9F9DA09DA1 9DA2000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9DA39DA49DA59DA69DA79DA89DA99DAA9DAB9DAC9DAD9DAE9DAF9DB09DB19DB2 9DB39DB49DB59DB69DB79DB89DB99DBA9DBB9DBC9DBD9DBE9DBF9DC09DC19DC2 9DC39DC49DC59DC69DC79DC89DC99DCA9DCB9DCC9DCD9DCE9DCF9DD09DD19DD2 9DD39DD49DD59DD69DD79DD89DD99DDA9DDB9DDC9DDD9DDE9DDF9DE09DE10000 9DE29DE39DE49DE59DE69DE79DE89DE99DEA9DEB9DEC9DED9DEE9DEF9DF09DF1 9DF29DF39DF49DF59DF69DF79DF89DF99DFA9DFB9DFC9DFD9DFE9DFF9E009E01 9E02000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9E039E049E059E069E079E089E099E0A9E0B9E0C9E0D9E0E9E0F9E109E119E12 9E139E149E159E169E179E189E199E1A9E1B9E1C9E1D9E1E9E249E279E2E9E30 9E349E3B9E3C9E409E4D9E509E529E539E549E569E599E5D9E5F9E609E619E62 9E659E6E9E6F9E729E749E759E769E779E789E799E7A9E7B9E7C9E7D9E800000 9E819E839E849E859E869E899E8A9E8C9E8D9E8E9E8F9E909E919E949E959E96 9E979E989E999E9A9E9B9E9C9E9E9EA09EA19EA29EA39EA49EA59EA79EA89EA9 9EAA000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9EAB9EAC9EAD9EAE9EAF9EB09EB19EB29EB39EB59EB69EB79EB99EBA9EBC9EBF 9EC09EC19EC29EC39EC59EC69EC79EC89ECA9ECB9ECC9ED09ED29ED39ED59ED6 9ED79ED99EDA9EDE9EE19EE39EE49EE69EE89EEB9EEC9EED9EEE9EF09EF19EF2 9EF39EF49EF59EF69EF79EF89EFA9EFD9EFF9F009F019F029F039F049F050000 9F069F079F089F099F0A9F0C9F0F9F119F129F149F159F169F189F1A9F1B9F1C 9F1D9F1E9F1F9F219F239F249F259F269F279F289F299F2A9F2B9F2D9F2E9F30 9F31000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FD 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9F329F339F349F359F369F389F3A9F3C9F3F9F409F419F429F439F459F469F47 9F489F499F4A9F4B9F4C9F4D9F4E9F4F9F529F539F549F559F569F579F589F59 9F5A9F5B9F5C9F5D9F5E9F5F9F609F619F629F639F649F659F669F679F689F69 9F6A9F6B9F6C9F6D9F6E9F6F9F709F719F729F739F749F759F769F779F780000 9F799F7A9F7B9F7C9F7D9F7E9F819F829F8D9F8E9F8F9F909F919F929F939F94 9F959F969F979F989F9C9F9D9F9E9FA19FA29FA39FA49FA5F92CF979F995F9E7 F9F1000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 FA0CFA0DFA0EFA0FFA11FA13FA14FA18FA1FFA20FA21FA23FA24FA27FA28FA29 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 tcl8.6.5/library/encoding/iso8859-8.enc0000644000175000017500000000210611555560473017005 0ustar sergeisergei# Encoding file: iso8859-8, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A0000000A200A300A400A500A600A700A800A900D700AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B900F700BB00BC00BD00BE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000002017 05D005D105D205D305D405D505D605D705D805D905DA05DB05DC05DD05DE05DF 05E005E105E205E305E405E505E605E705E805E905EA00000000200E200F0000 tcl8.6.5/library/encoding/iso8859-7.enc0000644000175000017500000000210611555560473017004 0ustar sergeisergei# Encoding file: iso8859-7, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A02018201900A30000000000A600A700A800A9000000AB00AC00AD00002015 00B000B100B200B303840385038600B703880389038A00BB038C00BD038E038F 0390039103920393039403950396039703980399039A039B039C039D039E039F 03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF 03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C203C303C403C503C603C703C803C903CA03CB03CC03CD03CE0000 tcl8.6.5/library/encoding/iso8859-15.enc0000644000175000017500000000210711555560473017064 0ustar sergeisergei# Encoding file: iso8859-15, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A000A100A200A320AC00A5016000A7016100A900AA00AB00AC00AD00AE00AF 00B000B100B200B3017D00B500B600B7017E00B900BA00BB01520153017800BF 00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF 00D000D100D200D300D400D500D600D700D800D900DA00DB00DC00DD00DE00DF 00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF 00F000F100F200F300F400F500F600F700F800F900FA00FB00FC00FD00FE00FF tcl8.6.5/library/encoding/dingbats.enc0000644000175000017500000000210511555560473017302 0ustar sergeisergei# Encoding file: dingbats, single-byte S 003F 1 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 00202701270227032704260E2706270727082709261B261E270C270D270E270F 2710271127122713271427152716271727182719271A271B271C271D271E271F 2720272127222723272427252726272726052729272A272B272C272D272E272F 2730273127322733273427352736273727382739273A273B273C273D273E273F 2740274127422743274427452746274727482749274A274B25CF274D25A0274F 27502751275225B225BC25C6275625D727582759275A275B275C275D275E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 0000276127622763276427652766276726632666266526602460246124622463 2464246524662467246824692776277727782779277A277B277C277D277E277F 2780278127822783278427852786278727882789278A278B278C278D278E278F 2790279127922793279421922194219527982799279A279B279C279D279E279F 27A027A127A227A327A427A527A627A727A827A927AA27AB27AC27AD27AE27AF 000027B127B227B327B427B527B627B727B827B927BA27BB27BC27BD27BE0000 tcl8.6.5/library/encoding/cp857.enc0000644000175000017500000000210211555560473016352 0ustar sergeisergei# Encoding file: cp857, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C700FC00E900E200E400E000E500E700EA00EB00E800EF00EE013100C400C5 00C900E600C600F400F600F200FB00F9013000D600DC00F800A300D8015E015F 00E100ED00F300FA00F100D1011E011F00BF00AE00AC00BD00BC00A100AB00BB 2591259225932502252400C100C200C000A9256325512557255D00A200A52510 25142534252C251C2500253C00E300C3255A25542569256625602550256C00A4 00BA00AA00CA00CB00C8000000CD00CE00CF2518250C2588258400A600CC2580 00D300DF00D400D200F500D500B5000000D700DA00DB00D900EC00FF00AF00B4 00AD00B1000000BE00B600A700F700B800B000A800B700B900B300B225A000A0 tcl8.6.5/library/encoding/cp1250.enc0000644000175000017500000000210311555560473016417 0ustar sergeisergei# Encoding file: cp1250, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 20AC0081201A0083201E2026202020210088203001602039015A0164017D0179 009020182019201C201D202220132014009821220161203A015B0165017E017A 00A002C702D8014100A4010400A600A700A800A9015E00AB00AC00AD00AE017B 00B000B102DB014200B400B500B600B700B80105015F00BB013D02DD013E017C 015400C100C2010200C40139010600C7010C00C9011800CB011A00CD00CE010E 01100143014700D300D4015000D600D70158016E00DA017000DC00DD016200DF 015500E100E2010300E4013A010700E7010D00E9011900EB011B00ED00EE010F 01110144014800F300F4015100F600F70159016F00FA017100FC00FD016302D9 tcl8.6.5/library/encoding/iso8859-10.enc0000644000175000017500000000210711555560473017057 0ustar sergeisergei# Encoding file: iso8859-10, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A0010401120122012A0128013600A7013B011001600166017D00AD016A014A 00B0010501130123012B0129013700B7013C011101610167017E2015016B014B 010000C100C200C300C400C500C6012E010C00C9011800CB011600CD00CE00CF 00D00145014C00D300D400D500D6016800D8017200DA00DB00DC00DD00DE00DF 010100E100E200E300E400E500E6012F010D00E9011900EB011700ED00EE00EF 00F00146014D00F300F400F500F6016900F8017300FA00FB00FC00FD00FE0138 tcl8.6.5/library/encoding/iso2022-jp.enc0000644000175000017500000000030011555560473017211 0ustar sergeisergei# Encoding file: iso2022-jp, escape-driven E name iso2022-jp init {} final {} ascii \x1b(B jis0201 \x1b(J jis0208 \x1b$B jis0208 \x1b$@ jis0212 \x1b$(D gb2312 \x1b$A ksc5601 \x1b$(C tcl8.6.5/library/encoding/cp775.enc0000644000175000017500000000210211555560473016351 0ustar sergeisergei# Encoding file: cp775, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 010600FC00E9010100E4012300E501070142011301560157012B017900C400C5 00C900E600C6014D00F6012200A2015A015B00D600DC00F800A300D800D700A4 0100012A00F3017B017C017A201D00A600A900AE00AC00BD00BC014100AB00BB 259125922593250225240104010C01180116256325512557255D012E01602510 25142534252C251C2500253C0172016A255A25542569256625602550256C017D 0105010D01190117012F01610173016B017E2518250C25882584258C25902580 00D300DF014C014300F500D500B5014401360137013B013C0146011201452019 00AD00B1201C00BE00B600A700F7201E00B0221900B700B900B300B225A000A0 tcl8.6.5/library/encoding/macCentEuro.enc0000644000175000017500000000211011555560473017710 0ustar sergeisergei# Encoding file: macCentEuro, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C40100010100C9010400D600DC00E10105010C00E4010D0106010700E90179 017A010E00ED010F01120113011600F3011700F400F600F500FA011A011B00FC 202000B0011800A300A7202200B600DF00AE00A92122011900A822600123012E 012F012A22642265012B0136220222110142013B013C013D013E0139013A0145 0146014300AC221A01440147220600AB00BB202600A00148015000D50151014C 20132014201C201D2018201900F725CA014D0154015501582039203A01590156 01570160201A201E0161015A015B00C10164016500CD017D017E016A00D300D4 016B016E00DA016F017001710172017300DD00FD0137017B0141017C012202C7 tcl8.6.5/library/encoding/iso8859-1.enc0000644000175000017500000000210611555560473016776 0ustar sergeisergei# Encoding file: iso8859-1, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF 00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF 00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF 00D000D100D200D300D400D500D600D700D800D900DA00DB00DC00DD00DE00DF 00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF 00F000F100F200F300F400F500F600F700F800F900FA00FB00FC00FD00FE00FF tcl8.6.5/library/encoding/ksc5601.enc0000644000175000017500000026531511555560473016621 0ustar sergeisergei# Encoding file: ksc5601, double-byte D 233F 0 89 21 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030003001300200B72025202600A8300300AD20152225FF3C223C20182019 201C201D3014301530083009300A300B300C300D300E300F3010301100B100D7 00F7226022642265221E223400B0203220332103212BFFE0FFE1FFE526422640 222022A52312220222072261225200A7203B2606260525CB25CF25CE25C725C6 25A125A025B325B225BD25BC219221902191219321943013226A226B221A223D 221D2235222B222C2208220B2286228722822283222A222922272228FFE20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 22 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000021D221D42200220300B4FF5E02C702D802DD02DA02D900B802DB00A100BF 02D0222E2211220F00A42109203025C125C025B725B626642660266126652667 2663229925C825A325D025D1259225A425A525A825A725A625A92668260F260E 261C261E00B62020202121952197219921962198266D2669266A266C327F321C 211633C7212233C233D821210000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 23 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF01FF02FF03FF04FF05FF06FF07FF08FF09FF0AFF0BFF0CFF0DFF0EFF0F FF10FF11FF12FF13FF14FF15FF16FF17FF18FF19FF1AFF1BFF1CFF1DFF1EFF1F FF20FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2F FF30FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3AFF3BFFE6FF3DFF3EFF3F FF40FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5AFF5BFF5CFF5DFFE30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 24 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000313131323133313431353136313731383139313A313B313C313D313E313F 3140314131423143314431453146314731483149314A314B314C314D314E314F 3150315131523153315431553156315731583159315A315B315C315D315E315F 3160316131623163316431653166316731683169316A316B316C316D316E316F 3170317131723173317431753176317731783179317A317B317C317D317E317F 3180318131823183318431853186318731883189318A318B318C318D318E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 25 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000217021712172217321742175217621772178217900000000000000000000 2160216121622163216421652166216721682169000000000000000000000000 0000039103920393039403950396039703980399039A039B039C039D039E039F 03A003A103A303A403A503A603A703A803A90000000000000000000000000000 000003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF 03C003C103C303C403C503C603C703C803C90000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 26 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000025002502250C251025182514251C252C25242534253C25012503250F2513 251B251725232533252B253B254B2520252F25282537253F251D253025252538 254225122511251A251925162515250E250D251E251F25212522252625272529 252A252D252E25312532253525362539253A253D253E25402541254325442545 2546254725482549254A00000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 27 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00003395339633972113339833C433A333A433A533A63399339A339B339C339D 339E339F33A033A133A233CA338D338E338F33CF3388338933C833A733A833B0 33B133B233B333B433B533B633B733B833B93380338133823383338433BA33BB 33BC33BD33BE33BF33903391339233933394212633C033C1338A338B338C33D6 33C533AD33AE33AF33DB33A933AA33AB33AC33DD33D033D333C333C933DC33C6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 28 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000C600D000AA0126000001320000013F014100D8015200BA00DE0166014A 00003260326132623263326432653266326732683269326A326B326C326D326E 326F3270327132723273327432753276327732783279327A327B24D024D124D2 24D324D424D524D624D724D824D924DA24DB24DC24DD24DE24DF24E024E124E2 24E324E424E524E624E724E824E9246024612462246324642465246624672468 2469246A246B246C246D246E00BD2153215400BC00BE215B215C215D215E0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 29 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000E6011100F001270131013301380140014200F8015300DF00FE0167014B 01493200320132023203320432053206320732083209320A320B320C320D320E 320F3210321132123213321432153216321732183219321A321B249C249D249E 249F24A024A124A224A324A424A524A624A724A824A924AA24AB24AC24AD24AE 24AF24B024B124B224B324B424B5247424752476247724782479247A247B247C 247D247E247F24802481248200B900B200B32074207F20812082208320840000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 2A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000304130423043304430453046304730483049304A304B304C304D304E304F 3050305130523053305430553056305730583059305A305B305C305D305E305F 3060306130623063306430653066306730683069306A306B306C306D306E306F 3070307130723073307430753076307730783079307A307B307C307D307E307F 3080308130823083308430853086308730883089308A308B308C308D308E308F 3090309130923093000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 2B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000030A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF 30B030B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF 30C030C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF 30D030D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 2C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000004100411041204130414041504010416041704180419041A041B041C041D 041E041F0420042104220423042404250426042704280429042A042B042C042D 042E042F00000000000000000000000000000000000000000000000000000000 000004300431043204330434043504510436043704380439043A043B043C043D 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 30 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000AC00AC01AC04AC07AC08AC09AC0AAC10AC11AC12AC13AC14AC15AC16AC17 AC19AC1AAC1BAC1CAC1DAC20AC24AC2CAC2DAC2FAC30AC31AC38AC39AC3CAC40 AC4BAC4DAC54AC58AC5CAC70AC71AC74AC77AC78AC7AAC80AC81AC83AC84AC85 AC86AC89AC8AAC8BAC8CAC90AC94AC9CAC9DAC9FACA0ACA1ACA8ACA9ACAAACAC ACAFACB0ACB8ACB9ACBBACBCACBDACC1ACC4ACC8ACCCACD5ACD7ACE0ACE1ACE4 ACE7ACE8ACEAACECACEFACF0ACF1ACF3ACF5ACF6ACFCACFDAD00AD04AD060000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 31 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000AD0CAD0DAD0FAD11AD18AD1CAD20AD29AD2CAD2DAD34AD35AD38AD3CAD44 AD45AD47AD49AD50AD54AD58AD61AD63AD6CAD6DAD70AD73AD74AD75AD76AD7B AD7CAD7DAD7FAD81AD82AD88AD89AD8CAD90AD9CAD9DADA4ADB7ADC0ADC1ADC4 ADC8ADD0ADD1ADD3ADDCADE0ADE4ADF8ADF9ADFCADFFAE00AE01AE08AE09AE0B AE0DAE14AE30AE31AE34AE37AE38AE3AAE40AE41AE43AE45AE46AE4AAE4CAE4D AE4EAE50AE54AE56AE5CAE5DAE5FAE60AE61AE65AE68AE69AE6CAE70AE780000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 32 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000AE79AE7BAE7CAE7DAE84AE85AE8CAEBCAEBDAEBEAEC0AEC4AECCAECDAECF AED0AED1AED8AED9AEDCAEE8AEEBAEEDAEF4AEF8AEFCAF07AF08AF0DAF10AF2C AF2DAF30AF32AF34AF3CAF3DAF3FAF41AF42AF43AF48AF49AF50AF5CAF5DAF64 AF65AF79AF80AF84AF88AF90AF91AF95AF9CAFB8AFB9AFBCAFC0AFC7AFC8AFC9 AFCBAFCDAFCEAFD4AFDCAFE8AFE9AFF0AFF1AFF4AFF8B000B001B004B00CB010 B014B01CB01DB028B044B045B048B04AB04CB04EB053B054B055B057B0590000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 33 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B05DB07CB07DB080B084B08CB08DB08FB091B098B099B09AB09CB09FB0A0 B0A1B0A2B0A8B0A9B0ABB0ACB0ADB0AEB0AFB0B1B0B3B0B4B0B5B0B8B0BCB0C4 B0C5B0C7B0C8B0C9B0D0B0D1B0D4B0D8B0E0B0E5B108B109B10BB10CB110B112 B113B118B119B11BB11CB11DB123B124B125B128B12CB134B135B137B138B139 B140B141B144B148B150B151B154B155B158B15CB160B178B179B17CB180B182 B188B189B18BB18DB192B193B194B198B19CB1A8B1CCB1D0B1D4B1DCB1DD0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 34 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B1DFB1E8B1E9B1ECB1F0B1F9B1FBB1FDB204B205B208B20BB20CB214B215 B217B219B220B234B23CB258B25CB260B268B269B274B275B27CB284B285B289 B290B291B294B298B299B29AB2A0B2A1B2A3B2A5B2A6B2AAB2ACB2B0B2B4B2C8 B2C9B2CCB2D0B2D2B2D8B2D9B2DBB2DDB2E2B2E4B2E5B2E6B2E8B2EBB2ECB2ED B2EEB2EFB2F3B2F4B2F5B2F7B2F8B2F9B2FAB2FBB2FFB300B301B304B308B310 B311B313B314B315B31CB354B355B356B358B35BB35CB35EB35FB364B3650000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 35 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B367B369B36BB36EB370B371B374B378B380B381B383B384B385B38CB390 B394B3A0B3A1B3A8B3ACB3C4B3C5B3C8B3CBB3CCB3CEB3D0B3D4B3D5B3D7B3D9 B3DBB3DDB3E0B3E4B3E8B3FCB410B418B41CB420B428B429B42BB434B450B451 B454B458B460B461B463B465B46CB480B488B49DB4A4B4A8B4ACB4B5B4B7B4B9 B4C0B4C4B4C8B4D0B4D5B4DCB4DDB4E0B4E3B4E4B4E6B4ECB4EDB4EFB4F1B4F8 B514B515B518B51BB51CB524B525B527B528B529B52AB530B531B534B5380000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 36 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B540B541B543B544B545B54BB54CB54DB550B554B55CB55DB55FB560B561 B5A0B5A1B5A4B5A8B5AAB5ABB5B0B5B1B5B3B5B4B5B5B5BBB5BCB5BDB5C0B5C4 B5CCB5CDB5CFB5D0B5D1B5D8B5ECB610B611B614B618B625B62CB634B648B664 B668B69CB69DB6A0B6A4B6ABB6ACB6B1B6D4B6F0B6F4B6F8B700B701B705B728 B729B72CB72FB730B738B739B73BB744B748B74CB754B755B760B764B768B770 B771B773B775B77CB77DB780B784B78CB78DB78FB790B791B792B796B7970000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 37 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B798B799B79CB7A0B7A8B7A9B7ABB7ACB7ADB7B4B7B5B7B8B7C7B7C9B7EC B7EDB7F0B7F4B7FCB7FDB7FFB800B801B807B808B809B80CB810B818B819B81B B81DB824B825B828B82CB834B835B837B838B839B840B844B851B853B85CB85D B860B864B86CB86DB86FB871B878B87CB88DB8A8B8B0B8B4B8B8B8C0B8C1B8C3 B8C5B8CCB8D0B8D4B8DDB8DFB8E1B8E8B8E9B8ECB8F0B8F8B8F9B8FBB8FDB904 B918B920B93CB93DB940B944B94CB94FB951B958B959B95CB960B968B9690000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 38 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000B96BB96DB974B975B978B97CB984B985B987B989B98AB98DB98EB9ACB9AD B9B0B9B4B9BCB9BDB9BFB9C1B9C8B9C9B9CCB9CEB9CFB9D0B9D1B9D2B9D8B9D9 B9DBB9DDB9DEB9E1B9E3B9E4B9E5B9E8B9ECB9F4B9F5B9F7B9F8B9F9B9FABA00 BA01BA08BA15BA38BA39BA3CBA40BA42BA48BA49BA4BBA4DBA4EBA53BA54BA55 BA58BA5CBA64BA65BA67BA68BA69BA70BA71BA74BA78BA83BA84BA85BA87BA8C BAA8BAA9BAABBAACBAB0BAB2BAB8BAB9BABBBABDBAC4BAC8BAD8BAD9BAFC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 39 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BB00BB04BB0DBB0FBB11BB18BB1CBB20BB29BB2BBB34BB35BB36BB38BB3B BB3CBB3DBB3EBB44BB45BB47BB49BB4DBB4FBB50BB54BB58BB61BB63BB6CBB88 BB8CBB90BBA4BBA8BBACBBB4BBB7BBC0BBC4BBC8BBD0BBD3BBF8BBF9BBFCBBFF BC00BC02BC08BC09BC0BBC0CBC0DBC0FBC11BC14BC15BC16BC17BC18BC1BBC1C BC1DBC1EBC1FBC24BC25BC27BC29BC2DBC30BC31BC34BC38BC40BC41BC43BC44 BC45BC49BC4CBC4DBC50BC5DBC84BC85BC88BC8BBC8CBC8EBC94BC95BC970000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BC99BC9ABCA0BCA1BCA4BCA7BCA8BCB0BCB1BCB3BCB4BCB5BCBCBCBDBCC0 BCC4BCCDBCCFBCD0BCD1BCD5BCD8BCDCBCF4BCF5BCF6BCF8BCFCBD04BD05BD07 BD09BD10BD14BD24BD2CBD40BD48BD49BD4CBD50BD58BD59BD64BD68BD80BD81 BD84BD87BD88BD89BD8ABD90BD91BD93BD95BD99BD9ABD9CBDA4BDB0BDB8BDD4 BDD5BDD8BDDCBDE9BDF0BDF4BDF8BE00BE03BE05BE0CBE0DBE10BE14BE1CBE1D BE1FBE44BE45BE48BE4CBE4EBE54BE55BE57BE59BE5ABE5BBE60BE61BE640000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000BE68BE6ABE70BE71BE73BE74BE75BE7BBE7CBE7DBE80BE84BE8CBE8DBE8F BE90BE91BE98BE99BEA8BED0BED1BED4BED7BED8BEE0BEE3BEE4BEE5BEECBF01 BF08BF09BF18BF19BF1BBF1CBF1DBF40BF41BF44BF48BF50BF51BF55BF94BFB0 BFC5BFCCBFCDBFD0BFD4BFDCBFDFBFE1C03CC051C058C05CC060C068C069C090 C091C094C098C0A0C0A1C0A3C0A5C0ACC0ADC0AFC0B0C0B3C0B4C0B5C0B6C0BC C0BDC0BFC0C0C0C1C0C5C0C8C0C9C0CCC0D0C0D8C0D9C0DBC0DCC0DDC0E40000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C0E5C0E8C0ECC0F4C0F5C0F7C0F9C100C104C108C110C115C11CC11DC11E C11FC120C123C124C126C127C12CC12DC12FC130C131C136C138C139C13CC140 C148C149C14BC14CC14DC154C155C158C15CC164C165C167C168C169C170C174 C178C185C18CC18DC18EC190C194C196C19CC19DC19FC1A1C1A5C1A8C1A9C1AC C1B0C1BDC1C4C1C8C1CCC1D4C1D7C1D8C1E0C1E4C1E8C1F0C1F1C1F3C1FCC1FD C200C204C20CC20DC20FC211C218C219C21CC21FC220C228C229C22BC22D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C22FC231C232C234C248C250C251C254C258C260C265C26CC26DC270C274 C27CC27DC27FC281C288C289C290C298C29BC29DC2A4C2A5C2A8C2ACC2ADC2B4 C2B5C2B7C2B9C2DCC2DDC2E0C2E3C2E4C2EBC2ECC2EDC2EFC2F1C2F6C2F8C2F9 C2FBC2FCC300C308C309C30CC30DC313C314C315C318C31CC324C325C328C329 C345C368C369C36CC370C372C378C379C37CC37DC384C388C38CC3C0C3D8C3D9 C3DCC3DFC3E0C3E2C3E8C3E9C3EDC3F4C3F5C3F8C408C410C424C42CC4300000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C434C43CC43DC448C464C465C468C46CC474C475C479C480C494C49CC4B8 C4BCC4E9C4F0C4F1C4F4C4F8C4FAC4FFC500C501C50CC510C514C51CC528C529 C52CC530C538C539C53BC53DC544C545C548C549C54AC54CC54DC54EC553C554 C555C557C558C559C55DC55EC560C561C564C568C570C571C573C574C575C57C C57DC580C584C587C58CC58DC58FC591C595C597C598C59CC5A0C5A9C5B4C5B5 C5B8C5B9C5BBC5BCC5BDC5BEC5C4C5C5C5C6C5C7C5C8C5C9C5CAC5CCC5CE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 3F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C5D0C5D1C5D4C5D8C5E0C5E1C5E3C5E5C5ECC5EDC5EEC5F0C5F4C5F6C5F7 C5FCC5FDC5FEC5FFC600C601C605C606C607C608C60CC610C618C619C61BC61C C624C625C628C62CC62DC62EC630C633C634C635C637C639C63BC640C641C644 C648C650C651C653C654C655C65CC65DC660C66CC66FC671C678C679C67CC680 C688C689C68BC68DC694C695C698C69CC6A4C6A5C6A7C6A9C6B0C6B1C6B4C6B8 C6B9C6BAC6C0C6C1C6C3C6C5C6CCC6CDC6D0C6D4C6DCC6DDC6E0C6E1C6E80000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 40 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C6E9C6ECC6F0C6F8C6F9C6FDC704C705C708C70CC714C715C717C719C720 C721C724C728C730C731C733C735C737C73CC73DC740C744C74AC74CC74DC74F C751C752C753C754C755C756C757C758C75CC760C768C76BC774C775C778C77C C77DC77EC783C784C785C787C788C789C78AC78EC790C791C794C796C797C798 C79AC7A0C7A1C7A3C7A4C7A5C7A6C7ACC7ADC7B0C7B4C7BCC7BDC7BFC7C0C7C1 C7C8C7C9C7CCC7CEC7D0C7D8C7DDC7E4C7E8C7ECC800C801C804C808C80A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 41 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C810C811C813C815C816C81CC81DC820C824C82CC82DC82FC831C838C83C C840C848C849C84CC84DC854C870C871C874C878C87AC880C881C883C885C886 C887C88BC88CC88DC894C89DC89FC8A1C8A8C8BCC8BDC8C4C8C8C8CCC8D4C8D5 C8D7C8D9C8E0C8E1C8E4C8F5C8FCC8FDC900C904C905C906C90CC90DC90FC911 C918C92CC934C950C951C954C958C960C961C963C96CC970C974C97CC988C989 C98CC990C998C999C99BC99DC9C0C9C1C9C4C9C7C9C8C9CAC9D0C9D1C9D30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 42 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000C9D5C9D6C9D9C9DAC9DCC9DDC9E0C9E2C9E4C9E7C9ECC9EDC9EFC9F0C9F1 C9F8C9F9C9FCCA00CA08CA09CA0BCA0CCA0DCA14CA18CA29CA4CCA4DCA50CA54 CA5CCA5DCA5FCA60CA61CA68CA7DCA84CA98CABCCABDCAC0CAC4CACCCACDCACF CAD1CAD3CAD8CAD9CAE0CAECCAF4CB08CB10CB14CB18CB20CB21CB41CB48CB49 CB4CCB50CB58CB59CB5DCB64CB78CB79CB9CCBB8CBD4CBE4CBE7CBE9CC0CCC0D CC10CC14CC1CCC1DCC21CC22CC27CC28CC29CC2CCC2ECC30CC38CC39CC3B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 43 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CC3CCC3DCC3ECC44CC45CC48CC4CCC54CC55CC57CC58CC59CC60CC64CC66 CC68CC70CC75CC98CC99CC9CCCA0CCA8CCA9CCABCCACCCADCCB4CCB5CCB8CCBC CCC4CCC5CCC7CCC9CCD0CCD4CCE4CCECCCF0CD01CD08CD09CD0CCD10CD18CD19 CD1BCD1DCD24CD28CD2CCD39CD5CCD60CD64CD6CCD6DCD6FCD71CD78CD88CD94 CD95CD98CD9CCDA4CDA5CDA7CDA9CDB0CDC4CDCCCDD0CDE8CDECCDF0CDF8CDF9 CDFBCDFDCE04CE08CE0CCE14CE19CE20CE21CE24CE28CE30CE31CE33CE350000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 44 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000CE58CE59CE5CCE5FCE60CE61CE68CE69CE6BCE6DCE74CE75CE78CE7CCE84 CE85CE87CE89CE90CE91CE94CE98CEA0CEA1CEA3CEA4CEA5CEACCEADCEC1CEE4 CEE5CEE8CEEBCEECCEF4CEF5CEF7CEF8CEF9CF00CF01CF04CF08CF10CF11CF13 CF15CF1CCF20CF24CF2CCF2DCF2FCF30CF31CF38CF54CF55CF58CF5CCF64CF65 CF67CF69CF70CF71CF74CF78CF80CF85CF8CCFA1CFA8CFB0CFC4CFE0CFE1CFE4 CFE8CFF0CFF1CFF3CFF5CFFCD000D004D011D018D02DD034D035D038D03C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 45 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D044D045D047D049D050D054D058D060D06CD06DD070D074D07CD07DD081 D0A4D0A5D0A8D0ACD0B4D0B5D0B7D0B9D0C0D0C1D0C4D0C8D0C9D0D0D0D1D0D3 D0D4D0D5D0DCD0DDD0E0D0E4D0ECD0EDD0EFD0F0D0F1D0F8D10DD130D131D134 D138D13AD140D141D143D144D145D14CD14DD150D154D15CD15DD15FD161D168 D16CD17CD184D188D1A0D1A1D1A4D1A8D1B0D1B1D1B3D1B5D1BAD1BCD1C0D1D8 D1F4D1F8D207D209D210D22CD22DD230D234D23CD23DD23FD241D248D25C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 46 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D264D280D281D284D288D290D291D295D29CD2A0D2A4D2ACD2B1D2B8D2B9 D2BCD2BFD2C0D2C2D2C8D2C9D2CBD2D4D2D8D2DCD2E4D2E5D2F0D2F1D2F4D2F8 D300D301D303D305D30CD30DD30ED310D314D316D31CD31DD31FD320D321D325 D328D329D32CD330D338D339D33BD33CD33DD344D345D37CD37DD380D384D38C D38DD38FD390D391D398D399D39CD3A0D3A8D3A9D3ABD3ADD3B4D3B8D3BCD3C4 D3C5D3C8D3C9D3D0D3D8D3E1D3E3D3ECD3EDD3F0D3F4D3FCD3FDD3FFD4010000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 47 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D408D41DD440D444D45CD460D464D46DD46FD478D479D47CD47FD480D482 D488D489D48BD48DD494D4A9D4CCD4D0D4D4D4DCD4DFD4E8D4ECD4F0D4F8D4FB D4FDD504D508D50CD514D515D517D53CD53DD540D544D54CD54DD54FD551D558 D559D55CD560D565D568D569D56BD56DD574D575D578D57CD584D585D587D588 D589D590D5A5D5C8D5C9D5CCD5D0D5D2D5D8D5D9D5DBD5DDD5E4D5E5D5E8D5EC D5F4D5F5D5F7D5F9D600D601D604D608D610D611D613D614D615D61CD6200000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 48 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D624D62DD638D639D63CD640D645D648D649D64BD64DD651D654D655D658 D65CD667D669D670D671D674D683D685D68CD68DD690D694D69DD69FD6A1D6A8 D6ACD6B0D6B9D6BBD6C4D6C5D6C8D6CCD6D1D6D4D6D7D6D9D6E0D6E4D6E8D6F0 D6F5D6FCD6FDD700D704D711D718D719D71CD720D728D729D72BD72DD734D735 D738D73CD744D747D749D750D751D754D756D757D758D759D760D761D763D765 D769D76CD770D774D77CD77DD781D788D789D78CD790D798D799D79BD79D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004F3D4F73504750F952A053EF547554E556095AC15BB6668767B667B767EF 6B4C73C275C27A3C82DB8304885788888A368CC88DCF8EFB8FE699D5523B5374 5404606A61646BBC73CF811A89BA89D295A34F83520A58BE597859E65E725E79 61C763C0674667EC687F6F97764E770B78F57A087AFF7C21809D826E82718AEB 95934E6B559D66F76E3478A37AED845B8910874E97A852D8574E582A5D4C611F 61BE6221656267D16A446E1B751875B376E377B07D3A90AF945194529F950000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000053235CAC753280DB92409598525B580859DC5CA15D175EB75F3A5F4A6177 6C5F757A75867CE07D737DB17F8C81548221859189418B1B92FC964D9C474ECB 4EF7500B51F1584F6137613E6168653969EA6F1175A5768676D67B8782A584CB F90093A7958B55805BA25751F9017CB37FB991B5502853BB5C455DE862D2636E 64DA64E76E2070AC795B8DDD8E1EF902907D924592F84E7E4EF650655DFE5EFA 61066957817186548E4793759A2B4E5E5091677068405109528D52926AA20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000077BC92109ED452AB602F8FF2504861A963ED64CA683C6A846FC0818889A1 96945805727D72AC75047D797E6D80A9898B8B7490639D5162896C7A6F547D50 7F3A8A23517C614A7B9D8B199257938C4EAC4FD3501E50BE510652C152CD537F 577058835E9A5F91617661AC64CE656C666F66BB66F468976D87708570F1749F 74A574CA75D9786C78EC7ADF7AF67D457D938015803F811B83968B668F159015 93E1980398389A5A9BE84FC25553583A59515B635C4660B86212684268B00000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000068E86EAA754C767878CE7A3D7CFB7E6B7E7C8A088AA18C3F968E9DC453E4 53E9544A547156FA59D15B645C3B5EAB62F765376545657266A067AF69C16CBD 75FC7690777E7A3F7F94800380A1818F82E682FD83F085C1883188B48AA5F903 8F9C932E96C798679AD89F1354ED659B66F2688F7A408C379D6056F057645D11 660668B168CD6EFE7428889E9BE46C68F9049AA84F9B516C5171529F5B545DE5 6050606D62F163A7653B73D97A7A86A38CA2978F4E325BE16208679C74DC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000079D183D38A878AB28DE8904E934B98465ED369E885FF90EDF90551A05B98 5BEC616368FA6B3E704C742F74D87BA17F5083C589C08CAB95DC9928522E605D 62EC90024F8A5149532158D95EE366E06D38709A72C273D67B5080F1945B5366 639B7F6B4E565080584A58DE602A612762D069D09B415B8F7D1880B18F5F4EA4 50D154AC55AC5B0C5DA05DE7652A654E68216A4B72E1768E77EF7D5E7FF981A0 854E86DF8F038F4E90CA99039A559BAB4E184E454E5D4EC74FF1517752FE0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 4F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000534053E353E5548E5614577557A25BC75D875ED061FC62D8655167B867E9 69CB6B506BC66BEC6C426E9D707872D77396740377BF77E97A767D7F800981FC 8205820A82DF88628B338CFC8EC0901190B1926492B699D29A459CE99DD79F9C 570B5C4083CA97A097AB9EB4541B7A987FA488D98ECD90E158005C4863987A9F 5BAE5F137A797AAE828E8EAC5026523852F85377570862F363726B0A6DC37737 53A5735785688E7695D5673A6AC36F708A6D8ECC994BF90666776B788CB40000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 50 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00009B3CF90753EB572D594E63C669FB73EA78457ABA7AC57CFE8475898F8D73 903595A852FB574775477B6083CC921EF9086A58514B524B5287621F68D86975 969950C552A452E461C365A4683969FF747E7B4B82B983EB89B28B398FD19949 F9094ECA599764D266116A8E7434798179BD82A9887E887F895FF90A93264F0B 53CA602562716C727D1A7D664E98516277DC80AF4F014F0E5176518055DC5668 573B57FA57FC5914594759935BC45C905D0E5DF15E7E5FCC628065D765E30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 51 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000671E671F675E68CB68C46A5F6B3A6C236C7D6C826DC773987426742A7482 74A37578757F788178EF794179477948797A7B957D007DBA7F888006802D808C 8A188B4F8C488D779321932498E299519A0E9A0F9A659E927DCA4F76540962EE 685491D155AB513AF90BF90C5A1C61E6F90D62CF62FFF90EF90FF910F911F912 F91390A3F914F915F916F917F9188AFEF919F91AF91BF91C6696F91D7156F91E F91F96E3F920634F637A5357F921678F69606E73F9227537F923F924F9250000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 52 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007D0DF926F927887256CA5A18F928F929F92AF92BF92C4E43F92D51675948 67F08010F92E59735E74649A79CA5FF5606C62C8637B5BE75BD752AAF92F5974 5F296012F930F931F9327459F933F934F935F936F937F93899D1F939F93AF93B F93CF93DF93EF93FF940F941F942F9436FC3F944F94581BF8FB260F1F946F947 8166F948F9495C3FF94AF94BF94CF94DF94EF94FF950F9515AE98A25677B7D10 F952F953F954F955F956F95780FDF958F9595C3C6CE5533F6EBA591A83360000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 53 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00004E394EB64F4655AE571858C75F5665B765E66A806BB56E4D77ED7AEF7C1E 7DDE86CB88929132935B64BB6FBE737A75B890545556574D61BA64D466C76DE1 6E5B6F6D6FB975F0804381BD854189838AC78B5A931F6C9375537B548E0F905D 5510580258585E626207649E68E075767CD687B39EE84EE35788576E59275C0D 5CB15E365F85623464E173B381FA888B8CB8968A9EDB5B855FB760B350125200 52305716583558575C0E5C605CF65D8B5EA65F9260BC63116389641768430000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000068F96AC26DD86E216ED46FE471FE76DC777979B17A3B840489A98CED8DF3 8E4890039014905390FD934D967697DC6BD27006725872A27368776379BF7BE4 7E9B8B8058A960C7656665FD66BE6C8C711E71C98C5A98134E6D7A814EDD51AC 51CD52D5540C61A76771685068DF6D1E6F7C75BC77B37AE580F484639285515C 6597675C679375D87AC78373F95A8C469017982D5C6F81C0829A9041906F920D 5F975D9D6A5971C8767B7B4985E48B0491279A30558761F6F95B76697F850000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 55 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000863F87BA88F8908FF95C6D1B70D973DE7D61843DF95D916A99F1F95E4E82 53756B046B12703E721B862D9E1E524C8FA35D5064E5652C6B166FEB7C437E9C 85CD896489BD62C981D8881F5ECA67176D6A72FC7405746F878290DE4F865D0D 5FA0840A51B763A075654EAE5006516951C968816A117CAE7CB17CE7826F8AD2 8F1B91CF4FB6513752F554425EEC616E623E65C56ADA6FFE792A85DC882395AD 9A629A6A9E979ECE529B66C66B77701D792B8F6297426190620065236F230000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 56 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000714974897DF4806F84EE8F269023934A51BD521752A36D0C70C888C25EC9 65826BAE6FC27C3E73754EE44F3656F9F95F5CBA5DBA601C73B27B2D7F9A7FCE 8046901E923496F6974898189F614F8B6FA779AE91B496B752DEF960648864C4 6AD36F5E7018721076E780018606865C8DEF8F0597329B6F9DFA9E75788C797F 7DA083C993049E7F9E938AD658DF5F046727702774CF7C60807E512170287262 78CA8CC28CDA8CF496F74E8650DA5BEE5ED6659971CE764277AD804A84FC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 57 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000907C9B279F8D58D85A415C626A136DDA6F0F763B7D2F7E37851E893893E4 964B528965D267F369B46D416E9C700F7409746075597624786B8B2C985E516D 622E96784F96502B5D196DEA7DB88F2A5F8B61446817F961968652D2808B51DC 51CC695E7A1C7DBE83F196754FDA52295398540F550E5C6560A7674E68A86D6C 728172F874067483F96275E27C6C7F797FB8838988CF88E191CC91D096E29BC9 541D6F7E71D0749885FA8EAA96A39C579E9F67976DCB743381E89716782C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 58 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007ACB7B207C926469746A75F278BC78E899AC9B549EBB5BDE5E556F20819C 83AB90884E07534D5A295DD25F4E6162633D666966FC6EFF6F2B7063779E842C 8513883B8F1399459C3B551C62B9672B6CAB8309896A977A4EA159845FD85FD9 671B7DB27F548292832B83BD8F1E909957CB59B95A925BD06627679A68856BCF 71647F758CB78CE390819B4581088C8A964C9A409EA55B5F6C13731B76F276DF 840C51AA8993514D519552C968C96C94770477207DBF7DEC97629EB56EC50000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 59 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000851151A5540D547D660E669D69276E9F76BF7791831784C2879F91699298 9CF488824FAE519252DF59C65E3D61556478647966AE67D06A216BCD6BDB725F 72617441773877DB801782BC83058B008B288C8C67286C90726776EE77667A46 9DA96B7F6C92592267268499536F589359995EDF63CF663467736E3A732B7AD7 82D7932852D95DEB61AE61CB620A62C764AB65E069596B666BCB712173F7755D 7E46821E8302856A8AA38CBF97279D6158A89ED85011520E543B554F65870000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006C767D0A7D0B805E868A958096EF52FF6C95726954735A9A5C3E5D4B5F4C 5FAE672A68B669636E3C6E4477097C737F8E85878B0E8FF797619EF45CB760B6 610D61AB654F65FB65FC6C116CEF739F73C97DE195945BC6871C8B10525D535A 62CD640F64B267346A386CCA73C0749E7B947C957E1B818A823685848FEB96F9 99C14F34534A53CD53DB62CC642C6500659169C36CEE6F5873ED7554762276E4 76FC78D078FB792C7D46822C87E08FD4981298EF52C362D464A56E246F510000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000767C8DCB91B192629AEE9B435023508D574A59A85C285E475F77623F653E 65B965C16609678B699C6EC278C57D2180AA8180822B82B384A1868C8A2A8B17 90A696329F90500D4FF3F96357F95F9862DC6392676F6E43711976C380CC80DA 88F488F589198CE08F29914D966A4F2F4F705E1B67CF6822767D767E9B445E61 6A0A716971D4756AF9647E41854385E998DC4F107B4F7F7095A551E15E0668B5 6C3E6C4E6CDB72AF7BC483036CD5743A50FB528858C164D86A9774A776560000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000078A7861795E29739F965535E5F018B8A8FA88FAF908A522577A59C499F08 4E19500251755C5B5E77661E663A67C468C570B3750175C579C97ADD8F279920 9A084FDD582158315BF6666E6B656D116E7A6F7D73E4752B83E988DC89138B5C 8F144F0F50D55310535C5B935FA9670D798F8179832F8514890789868F398F3B 99A59C12672C4E764FF859495C015CEF5CF0636768D270FD71A2742B7E2B84EC 8702902292D29CF34E0D4ED84FEF50855256526F5426549057E0592B5A660000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005B5A5B755BCC5E9CF9666276657765A76D6E6EA572367B267C3F7F368150 8151819A8240829983A98A038CA08CE68CFB8D748DBA90E891DC961C964499D9 9CE7531752065429567458B35954596E5FFF61A4626E66106C7E711A76C67C89 7CDE7D1B82AC8CC196F0F9674F5B5F175F7F62C25D29670B68DA787C7E439D6C 4E1550995315532A535159835A625E8760B2618A624962796590678769A76BD4 6BD66BD76BD86CB8F968743575FA7812789179D579D87C837DCB7FE180A50000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000813E81C283F2871A88E88AB98B6C8CBB9119975E98DB9F3B56AC5B2A5F6C 658C6AB36BAF6D5C6FF17015725D73AD8CA78CD3983B61916C3780589A014E4D 4E8B4E9B4ED54F3A4F3C4F7F4FDF50FF53F253F8550655E356DB58EB59625A11 5BEB5BFA5C045DF35E2B5F99601D6368659C65AF67F667FB68AD6B7B6C996CD7 6E23700973457802793E7940796079C17BE97D177D728086820D838E84D186C7 88DF8A508A5E8B1D8CDC8D668FAD90AA98FC99DF9E9D524AF9696714F96A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005098522A5C7165636C5573CA7523759D7B97849C917897304E7764926BBA 715E85A94E09F96B674968EE6E17829F8518886B63F76F81921298AF4E0A50B7 50CF511F554655AA56175B405C195CE05E385E8A5EA05EC260F368516A616E58 723D724072C076F879657BB17FD488F389F48A738C618CDE971C585E74BD8CFD 55C7F96C7A617D2282727272751F7525F96D7B19588558FB5DBC5E8F5EB65F90 60556292637F654D669166D966F8681668F27280745E7B6E7D6E7DD67F720000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 60 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000080E5821285AF897F8A93901D92E49ECD9F205915596D5E2D60DC66146673 67906C506DC56F5F77F378A984C691CB932B4ED950CA514855845B0B5BA36247 657E65CB6E32717D74017444748774BF766C79AA7DDA7E557FA8817A81B38239 861A87EC8A758DE3907892919425994D9BAE53685C5169546CC46D296E2B820C 859B893B8A2D8AAA96EA9F67526166B96BB27E9687FE8D0D9583965D651D6D89 71EEF96E57CE59D35BAC602760FA6210661F665F732973F976DB77017B6C0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 61 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008056807281658AA091924E1652E26B726D177A057B397D30F96F8CB053EC 562F58515BB55C0F5C115DE2624063836414662D68B36CBC6D886EAF701F70A4 71D27526758F758E76197B117BE07C2B7D207D39852C856D86078A34900D9061 90B592B797F69A374FD75C6C675F6D917C9F7E8C8B168D16901F5B6B5DFD640D 84C0905C98E173875B8B609A677E6DDE8A1F8AA69001980C5237F9707051788E 9396887091D74FEE53D755FD56DA578258FD5AC25B885CAB5CC05E2561010000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 62 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000620D624B6388641C653665786A396B8A6C346D196F3171E772E973787407 74B27626776179C07A577AEA7CB97D8F7DAC7E617F9E81298331849084DA85EA 88968AB08B908F3890429083916C929692B9968B96A796A896D6970098089996 9AD39B1A53D4587E59195B705BBF6DD16F5A719F742174B9808583FD5DE15F87 5FAA604265EC6812696F6A536B896D356DF373E376FE77AC7B4D7D148123821C 834084F485638A628AC49187931E980699B4620C88538FF092655D075D270000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 63 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005D69745F819D87686FD562FE7FD2893689724E1E4E5850E752DD5347627F 66077E698805965E4F8D5319563659CB5AA45C385C4E5C4D5E025F11604365BD 662F664267BE67F4731C77E2793A7FC5849484CD89968A668A698AE18C558C7A 57F45BD45F0F606F62ED690D6B966E5C71847BD287558B588EFE98DF98FE4F38 4F814FE1547B5A205BB8613C65B0666871FC7533795E7D33814E81E3839885AA 85CE87038A0A8EAB8F9BF9718FC559315BA45BE660895BE95C0B5FC36C810000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 64 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9726DF1700B751A82AF8AF64EC05341F97396D96C0F4E9E4FC45152555E 5A255CE86211725982BD83AA86FE88598A1D963F96C599139D099D5D580A5CB3 5DBD5E4460E1611563E16A026E2591029354984E9C109F775B895CB86309664F 6848773C96C1978D98549B9F65A18B018ECB95BC55355CA95DD65EB56697764C 83F495C758D362BC72CE9D284EF0592E600F663B6B8379E79D26539354C057C3 5D16611B66D66DAF788D827E969897445384627C63966DB27E0A814B984D0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 65 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006AFB7F4C9DAF9E1A4E5F503B51B6591C60F963F66930723A8036F97491CE 5F31F975F9767D0482E5846F84BB85E58E8DF9774F6FF978F97958E45B436059 63DA6518656D6698F97A694A6A236D0B7001716C75D2760D79B37A70F97B7F8A F97C8944F97D8B9391C0967DF97E990A57045FA165BC6F01760079A68A9E99AD 9B5A9F6C510461B662916A8D81C6504358305F6671098A008AFA5B7C86164FFA 513C56B4594463A96DF95DAA696D51864E884F59F97FF980F9815982F9820000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 66 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9836B5F6C5DF98474B57916F9858207824583398F3F8F5DF9869918F987 F988F9894EA6F98A57DF5F796613F98BF98C75AB7E798B6FF98D90069A5B56A5 582759F85A1F5BB4F98E5EF6F98FF9906350633BF991693D6C876CBF6D8E6D93 6DF56F14F99270DF71367159F99371C371D5F994784F786FF9957B757DE3F996 7E2FF997884D8EDFF998F999F99A925BF99B9CF6F99CF99DF99E60856D85F99F 71B1F9A0F9A195B153ADF9A2F9A3F9A467D3F9A5708E71307430827682D20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 67 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9A695BB9AE59E7D66C4F9A771C18449F9A8F9A9584BF9AAF9AB5DB85F71 F9AC6620668E697969AE6C386CF36E366F416FDA701B702F715071DF7370F9AD 745BF9AE74D476C87A4E7E93F9AFF9B082F18A608FCEF9B19348F9B29719F9B3 F9B44E42502AF9B5520853E166F36C6D6FCA730A777F7A6282AE85DD8602F9B6 88D48A638B7D8C6BF9B792B3F9B8971398104E944F0D4FC950B25348543E5433 55DA586258BA59675A1B5BE4609FF9B961CA655665FF666468A76C5A6FB30000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 68 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000070CF71AC73527B7D87088AA49C329F075C4B6C8373447389923A6EAB7465 761F7A697E15860A514058C564C174EE751576707FC1909596CD99546E2674E6 7AA97AAA81E586D987788A1B5A495B8C5B9B68A169006D6373A97413742C7897 7DE97FEB81188155839E8C4C962E981166F05F8065FA67896C6A738B502D5A03 6B6A77EE59165D6C5DCD7325754FF9BAF9BB50E551F9582F592D599659DA5BE5 F9BCF9BD5DA262D76416649364FEF9BE66DCF9BF6A48F9C071FF7464F9C10000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 69 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00007A887AAF7E477E5E80008170F9C287EF89818B209059F9C390809952617E 6B326D747E1F89258FB14FD150AD519752C757C758895BB95EB8614269956D8C 6E676EB6719474627528752C8073833884C98E0A939493DEF9C44E8E4F515076 512A53C853CB53F35B875BD35C24611A618265F4725B7397744076C279507991 79B97D067FBD828B85D5865E8FC2904790F591EA968596E896E952D65F6765ED 6631682F715C7A3690C1980A4E91F9C56A526B9E6F907189801882B885530000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000904B969596F297FB851A9B314E90718A96C45143539F54E15713571257A3 5A9B5AC45BC36028613F63F46C856D396E726E907230733F745782D188818F45 9060F9C6966298589D1B67088D8A925E4F4D504950DE5371570D59D45A015C09 617066906E2D7232744B7DEF80C3840E8466853F875F885B89188B02905597CB 9B4F4E734F915112516AF9C7552F55A95B7A5BA55E7C5E7D5EBE60A060DF6108 610963C465386709F9C867D467DAF9C9696169626CB96D27F9CA6E38F9CB0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006FE173367337F9CC745C7531F9CD7652F9CEF9CF7DAD81FE843888D58A98 8ADB8AED8E308E42904A903E907A914991C9936EF9D0F9D15809F9D26BD38089 80B2F9D3F9D45141596B5C39F9D5F9D66F6473A780E48D07F9D79217958FF9D8 F9D9F9DAF9DB807F620E701C7D68878DF9DC57A0606961476BB78ABE928096B1 4E59541F6DEB852D967097F398EE63D66CE3909151DD61C981BA9DF94F9D501A 51005B9C610F61FF64EC69056BC5759177E37FA98264858F87FB88638ABC0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008B7091AB4E8C4EE54F0AF9DDF9DE593759E8F9DF5DF25F1B5F5B6021F9E0 F9E1F9E2F9E3723E73E5F9E4757075CDF9E579FBF9E6800C8033808482E18351 F9E7F9E88CBD8CB39087F9E9F9EA98F4990CF9EBF9EC703776CA7FCA7FCC7FFC 8B1A4EBA4EC152035370F9ED54BD56E059FB5BC55F155FCD6E6EF9EEF9EF7D6A 8335F9F086938A8DF9F1976D9777F9F2F9F34E004F5A4F7E58F965E56EA29038 93B099B94EFB58EC598A59D96041F9F4F9F57A14F9F6834F8CC3516553440000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000F9F7F9F8F9F94ECD52695B5582BF4ED4523A54A859C959FF5B505B575B5C 606361486ECB7099716E738674F775B578C17D2B800581EA8328851785C98AEE 8CC796CC4F5C52FA56BC65AB6628707C70B872357DBD828D914C96C09D725B71 68E76B986F7A76DE5C9166AB6F5B7BB47C2A883696DC4E084ED75320583458BB 58EF596C5C075E335E845F35638C66B267566A1F6AA36B0C6F3F7246F9FA7350 748B7AE07CA7817881DF81E7838A846C8523859485CF88DD8D1391AC95770000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000969C518D54C957285BB0624D6750683D68936E3D6ED3707D7E2188C18CA1 8F099F4B9F4E722D7B8F8ACD931A4F474F4E5132548059D05E9562B56775696E 6A176CAE6E1A72D9732A75BD7BB87D3582E783F9845785F78A5B8CAF8E879019 90B896CE9F5F52E3540A5AE15BC2645865756EF472C4F9FB76847A4D7B1B7C4D 7E3E7FDF837B8B2B8CCA8D648DE18E5F8FEA8FF9906993D14F434F7A50B35168 5178524D526A5861587C59605C085C555EDB609B623068136BBF6C086FB10000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000714E742075307538755176727B4C7B8B7BAD7BC67E8F8A6E8F3E8F49923F 92939322942B96FB985A986B991E5207622A62986D5976647ACA7BC07D765360 5CBE5E976F3870B97C9897119B8E9EDE63A5647A87764E014E954EAD505C5075 544859C35B9A5E405EAD5EF75F8160C5633A653F657465CC6676667867FE6968 6A896B636C406DC06DE86E1F6E5E701E70A1738E73FD753A775B7887798E7A0B 7A7D7CBE7D8E82478A028AEA8C9E912D914A91D8926692CC9320970697560000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 70 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000975C98029F0E52365291557C58245E1D5F1F608C63D068AF6FDF796D7B2C 81CD85BA88FD8AF88E44918D9664969B973D984C9F4A4FCE514651CB52A95632 5F145F6B63AA64CD65E9664166FA66F9671D689D68D769FD6F156F6E716771E5 722A74AA773A7956795A79DF7A207A957C977CDF7D447E70808785FB86A48A54 8ABF8D998E819020906D91E3963B96D59CE565CF7C078DB393C35B585C0A5352 62D9731D50275B975F9E60B0616B68D56DD9742E7A2E7D427D9C7E31816B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 71 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008E2A8E35937E94184F5057505DE65EA7632B7F6A4E3B4F4F4F8F505A59DD 80C4546A546855FE594F5B995DDE5EDA665D673167F1682A6CE86D326E4A6F8D 70B773E075877C4C7D027D2C7DA2821F86DB8A3B8A858D708E8A8F339031914E 9152944499D07AF97CA54FCA510151C657C85BEF5CFB66596A3D6D5A6E966FEC 710C756F7AE388229021907596CB99FF83014E2D4EF2884691CD537D6ADB696B 6C41847A589E618E66FE62EF70DD751175C77E5284B88B498D084E4B53EA0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 72 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000054AB573057405FD763016307646F652F65E8667A679D67B36B626C606C9A 6F2C77E57825794979577D1980A2810281F3829D82B787188A8CF9FC8D048DBE 907276F47A197A377E548077550755D45875632F64226649664B686D699B6B84 6D256EB173CD746874A1755B75B976E1771E778B79E67E097E1D81FB852F8897 8A3A8CD18EEB8FB0903293AD9663967397074F8453F159EA5AC95E19684E74C6 75BE79E97A9281A386ED8CEA8DCC8FED659F6715F9FD57F76F577DDD8F2F0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 73 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000093F696C65FB561F26F844E144F98501F53C955DF5D6F5DEE6B216B6478CB 7B9AF9FE8E498ECA906E6349643E77407A84932F947F9F6A64B06FAF71E674A8 74DA7AC47C127E827CB27E988B9A8D0A947D9910994C52395BDF64E6672D7D2E 50ED53C358796158615961FA65AC7AD98B928B9650095021527555315A3C5EE0 5F706134655E660C663666A269CD6EC46F32731676217A938139825983D684BC 50B557F05BC05BE85F6963A178267DB583DC852191C791F5518A67F57B560000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 74 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008CAC51C459BB60BD8655501CF9FF52545C3A617D621A62D364F265A56ECC 7620810A8E60965F96BB4EDF5343559859295DDD64C56CC96DFA73947A7F821B 85A68CE48E10907791E795E1962197C651F854F255865FB964A46F887DB48F1F 8F4D943550C95C166CBE6DFB751B77BB7C3D7C648A798AC2581E59BE5E166377 7252758A776B8ADC8CBC8F125EF366746DF8807D83C18ACB97519BD6FA005243 66FF6D956EEF7DE08AE6902E905E9AD4521D527F54E86194628462DB68A20000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 75 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00006912695A6A3570927126785D7901790E79D27A0D8096827882D583498549 8C828D859162918B91AE4FC356D171ED77D7870089F85BF85FD6675190A853E2 585A5BF560A4618164607E3D80708525928364AE50AC5D146700589C62BD63A8 690E69786A1E6E6B76BA79CB82BB84298ACF8DA88FFD9112914B919C93109318 939A96DB9A369C0D4E11755C795D7AFA7B517BC97E2E84C48E598E748EF89010 6625693F744351FA672E9EDC51455FE06C9687F2885D887760B481B584030000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 76 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00008D0553D6543956345A365C31708A7FE0805A810681ED8DA391899A5F9DF2 50744EC453A060FB6E2C5C644F88502455E45CD95E5F606568946CBB6DC471BE 75D475F476617A1A7A497DC77DFB7F6E81F486A98F1C96C999B39F52524752C5 98ED89AA4E0367D26F064FB55BE267956C886D78741B782791DD937C87C479E4 7A315FEB4ED654A4553E58AE59A560F0625362D6673669558235964099B199DD 502C53535544577CFA016258FA0264E2666B67DD6FC16FEF742274388A170000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 77 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000094385451560657665F48619A6B4E705870AD7DBB8A95596A812B63A27708 803D8CAA5854642D69BB5B955E116E6FFA038569514C53F0592A6020614B6B86 6C706CF07B1E80CE82D48DC690B098B1FA0464C76FA464916504514E5410571F 8A0E615F6876FA0575DB7B527D71901A580669CC817F892A9000983950785957 59AC6295900F9B2A615D727995D657615A465DF4628A64AD64FA67776CE26D3E 722C743678347F7782AD8DDB981752245742677F724874E38CA98FA692110000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 78 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000962A516B53ED634C4F695504609665576C9B6D7F724C72FD7A1789878C9D 5F6D6F8E70F981A8610E4FBF504F624172477BC77DE87FE9904D97AD9A198CB6 576A5E7367B0840D8A5554205B165E635EE25F0A658380BA853D9589965B4F48 5305530D530F548654FA57035E036016629B62B16355FA066CE16D6675B17832 80DE812F82DE846184B2888D8912900B92EA98FD9B915E4566B466DD70117206 FA074FF5527D5F6A615367536A196F0274E2796888688C7998C798C49A430000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 79 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000054C17A1F69538AF78C4A98A899AE5F7C62AB75B276AE88AB907F96425339 5F3C5FC56CCC73CC7562758B7B4682FE999D4E4F903C4E0B4F5553A6590F5EC8 66306CB37455837787668CC09050971E9C1558D15B7886508B149DB45BD26068 608D65F16C576F226FA3701A7F557FF095919592965097D352728F4451FD542B 54B85563558A6ABB6DB57DD88266929C96779E79540854C876D286E495A495D4 965C4EA24F0959EE5AE65DF760526297676D68416C866E2F7F38809B822A0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FA08FA0998054EA5505554B35793595A5B695BB361C869776D77702387F9 89E38A728AE7908299ED9AB852BE683850165E78674F8347884C4EAB541156AE 73E6911597FF9909995799995653589F865B8A3161B26AF6737B8ED26B4796AA 9A57595572008D6B97694FD45CF45F2661F8665B6CEB70AB738473B973FE7729 774D7D437D627E2382378852FA0A8CE29249986F5B517A74884098015ACC4FE0 5354593E5CFD633E6D7972F98105810783A292CF98304EA851445211578B0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00005F626CC26ECE7005705070AF719273E97469834A87A28861900890A293A3 99A8516E5F5760E0616766B385598E4A91AF978B4E4E4E92547C58D558FA597D 5CB55F2762366248660A66676BEB6D696DCF6E566EF86F946FE06FE9705D72D0 7425745A74E07693795C7CCA7E1E80E182A6846B84BF864E865F87748B778C6A 93AC9800986560D1621691775A5A660F6DF76E3E743F9B425FFD60DA7B0F54C4 5F186C5E6CD36D2A70D87D0586798A0C9D3B5316548C5B056A3A706B75750000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000798D79BE82B183EF8A718B418CA89774FA0B64F4652B78BA78BB7A6B4E38 559A59505BA65E7B60A363DB6B61666568536E19716574B07D0890849A699C25 6D3B6ED1733E8C4195CA51F05E4C5FA8604D60F66130614C6643664469A56CC1 6E5F6EC96F62714C749C76877BC17C27835287579051968D9EC3532F56DE5EFB 5F8A6062609461F7666667036A9C6DEE6FAE7070736A7E6A81BE833486D48AA8 8CC4528373725B966A6B940454EE56865B5D6548658566C9689F6D8D6DC60000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000723B80B491759A4D4FAF5019539A540E543C558955C55E3F5F8C673D7166 73DD900552DB52F3586458CE7104718F71FB85B08A13668885A855A76684714A 8431534955996BC15F595FBD63EE668971478AF18F1D9EBE4F11643A70CB7566 866760648B4E9DF8514751F653086D3680F89ED166156B23709875D554035C79 7D078A166B206B3D6B46543860706D3D7FD5820850D651DE559C566B56CD59EC 5B095E0C619961986231665E66E6719971B971BA72A779A77A007FB28A700000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 tcl8.6.5/library/encoding/iso8859-16.enc0000644000175000017500000000210711555560473017065 0ustar sergeisergei# Encoding file: iso8859-16, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A001040105014120AC201E016000A7016100A9021800AB017900AD017A017B 00B000B1010C0142017D201D00B600B7017E010D021900BB015201530178017C 00C000C100C2010200C4010600C600C700C800C900CA00CB00CC00CD00CE00CF 0110014300D200D300D4015000D6015A017000D900DA00DB00DC0118021A00DF 00E000E100E2010300E4010700E600E700E800E900EA00EB00EC00ED00EE00EF 0111014400F200F300F4015100F6015B017100F900FA00FB00FC0119021B00FF tcl8.6.5/library/encoding/iso8859-4.enc0000644000175000017500000000210611555560473017001 0ustar sergeisergei# Encoding file: iso8859-4, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A001040138015600A40128013B00A700A8016001120122016600AD017D00AF 00B0010502DB015700B40129013C02C700B80161011301230167014A017E014B 010000C100C200C300C400C500C6012E010C00C9011800CB011600CD00CE012A 01100145014C013600D400D500D600D700D8017200DA00DB00DC0168016A00DF 010100E100E200E300E400E500E6012F010D00E9011900EB011700ED00EE012B 01110146014D013700F400F500F600F700F8017300FA00FB00FC0169016B02D9 tcl8.6.5/library/encoding/macGreek.enc0000644000175000017500000000210511555560473017225 0ustar sergeisergei# Encoding file: macGreek, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 00C400B900B200C900B300D600DC038500E000E200E4038400A800E700E900E8 00EA00EB00A3212200EE00EF202200BD203000F400F600A600AD00F900FB00FC 2020039303940398039B039E03A000DF00AE00A903A303AA00A7226000B000B7 039100B12264226500A503920395039603970399039A039C03A603AB03A803A9 03AC039D00AC039F03A1224803A400AB00BB202600A003A503A7038603880153 20132015201C201D2018201900F70389038A038C038E03AD03AE03AF03CC038F 03CD03B103B203C803B403B503C603B303B703B903BE03BA03BB03BC03BD03BF 03C003CE03C103C303C403B803C903C203C703C503B603CA03CB039003B0F8A0 tcl8.6.5/library/encoding/cp932.enc0000644000175000017500000013611711555560473016362 0ustar sergeisergei# Encoding file: cp932, multi-byte M 003F 0 46 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080000000000000000000850086000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 81 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 300030013002FF0CFF0E30FBFF1AFF1BFF1FFF01309B309C00B4FF4000A8FF3E FFE3FF3F30FD30FE309D309E30034EDD30053006300730FC20152010FF0FFF3C FF5E2225FF5C2026202520182019201C201DFF08FF0930143015FF3BFF3DFF5B FF5D30083009300A300B300C300D300E300F30103011FF0BFF0D00B100D70000 00F7FF1D2260FF1CFF1E22662267221E22342642264000B0203220332103FFE5 FF04FFE0FFE1FF05FF03FF06FF0AFF2000A72606260525CB25CF25CE25C725C6 25A125A025B325B225BD25BC203B301221922190219121933013000000000000 000000000000000000000000000000002208220B2286228722822283222A2229 0000000000000000000000000000000022272228FFE221D221D4220022030000 0000000000000000000000000000000000000000222022A52312220222072261 2252226A226B221A223D221D2235222B222C0000000000000000000000000000 212B2030266F266D266A2020202100B6000000000000000025EF000000000000 82 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000FF10 FF11FF12FF13FF14FF15FF16FF17FF18FF190000000000000000000000000000 FF21FF22FF23FF24FF25FF26FF27FF28FF29FF2AFF2BFF2CFF2DFF2EFF2FFF30 FF31FF32FF33FF34FF35FF36FF37FF38FF39FF3A000000000000000000000000 0000FF41FF42FF43FF44FF45FF46FF47FF48FF49FF4AFF4BFF4CFF4DFF4EFF4F FF50FF51FF52FF53FF54FF55FF56FF57FF58FF59FF5A00000000000000003041 30423043304430453046304730483049304A304B304C304D304E304F30503051 30523053305430553056305730583059305A305B305C305D305E305F30603061 30623063306430653066306730683069306A306B306C306D306E306F30703071 30723073307430753076307730783079307A307B307C307D307E307F30803081 30823083308430853086308730883089308A308B308C308D308E308F30903091 3092309300000000000000000000000000000000000000000000000000000000 83 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 30A130A230A330A430A530A630A730A830A930AA30AB30AC30AD30AE30AF30B0 30B130B230B330B430B530B630B730B830B930BA30BB30BC30BD30BE30BF30C0 30C130C230C330C430C530C630C730C830C930CA30CB30CC30CD30CE30CF30D0 30D130D230D330D430D530D630D730D830D930DA30DB30DC30DD30DE30DF0000 30E030E130E230E330E430E530E630E730E830E930EA30EB30EC30ED30EE30EF 30F030F130F230F330F430F530F6000000000000000000000000000000000391 03920393039403950396039703980399039A039B039C039D039E039F03A003A1 03A303A403A503A603A703A803A90000000000000000000000000000000003B1 03B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF03C003C1 03C303C403C503C603C703C803C9000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 84 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 04100411041204130414041504010416041704180419041A041B041C041D041E 041F0420042104220423042404250426042704280429042A042B042C042D042E 042F000000000000000000000000000000000000000000000000000000000000 04300431043204330434043504510436043704380439043A043B043C043D0000 043E043F0440044104420443044404450446044704480449044A044B044C044D 044E044F00000000000000000000000000000000000000000000000000002500 2502250C251025182514251C252C25242534253C25012503250F2513251B2517 25232533252B253B254B2520252F25282537253F251D25302525253825420000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 87 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 2460246124622463246424652466246724682469246A246B246C246D246E246F 2470247124722473216021612162216321642165216621672168216900003349 33143322334D331833273303333633513357330D33263323332B334A333B339C 339D339E338E338F33C433A100000000000000000000000000000000337B0000 301D301F211633CD212132A432A532A632A732A8323132323239337E337D337C 22522261222B222E2211221A22A52220221F22BF22352229222A000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 88 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000004E9C 55165A03963F54C0611B632859F690228475831C7A5060AA63E16E2565ED8466 82A69BF56893572765A162715B9B59D0867B98F47D627DBE9B8E62167C9F88B7 5B895EB563096697684895C7978D674F4EE54F0A4F4D4F9D504956F2593759D4 5A015C0960DF610F61706613690570BA754F757079FB7DAD7DEF80C3840E8863 8B029055907A533B4E954EA557DF80B290C178EF4E0058F16EA290387A328328 828B9C2F5141537054BD54E156E059FB5F1598F26DEB80E4852D000000000000 89 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9662967096A097FB540B53F35B8770CF7FBD8FC296E8536F9D5C7ABA4E117893 81FC6E26561855046B1D851A9C3B59E553A96D6674DC958F56424E91904B96F2 834F990C53E155B65B305F71662066F368046C386CF36D29745B76C87A4E9834 82F1885B8A6092ED6DB275AB76CA99C560A68B018D8A95B2698E53AD51860000 5712583059445BB45EF6602863A963F46CBF6F14708E7114715971D5733F7E01 827682D185979060925B9D1B586965BC6C5A752551F9592E59655F805FDC62BC 65FA6A2A6B276BB4738B7FC189569D2C9D0E9EC45CA16C96837B51045C4B61B6 81C6687672614E594FFA537860696E297A4F97F34E0B53164EEE4F554F3D4FA1 4F7352A053EF5609590F5AC15BB65BE179D16687679C67B66B4C6CB3706B73C2 798D79BE7A3C7B8782B182DB8304837783EF83D387668AB256298CA88FE6904E 971E868A4FC45CE862117259753B81E582BD86FE8CC096C5991399D54ECB4F1A 89E356DE584A58CA5EFB5FEB602A6094606261D0621262D06539000000000000 8A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9B41666668B06D777070754C76867D7582A587F9958B968E8C9D51F152BE5916 54B35BB35D16616869826DAF788D84CB88578A7293A79AB86D6C99A886D957A3 67FF86CE920E5283568754045ED362E164B9683C68386BBB737278BA7A6B899A 89D28D6B8F0390ED95A3969497695B665CB3697D984D984E639B7B206A2B0000 6A7F68B69C0D6F5F5272559D607062EC6D3B6E076ED1845B89108F444E149C39 53F6691B6A3A9784682A515C7AC384B291DC938C565B9D286822830584317CA5 520882C574E64E7E4F8351A05BD2520A52D852E75DFB559A582A59E65B8C5B98 5BDB5E725E7960A3611F616361BE63DB656267D1685368FA6B3E6B536C576F22 6F976F4574B0751876E3770B7AFF7BA17C217DE97F367FF0809D8266839E89B3 8ACC8CAB908494519593959195A2966597D3992882184E38542B5CB85DCC73A9 764C773C5CA97FEB8D0B96C19811985498584F014F0E5371559C566857FA5947 5B095BC45C905E0C5E7E5FCC63EE673A65D765E2671F68CB68C4000000000000 8B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A5F5E306BC56C176C7D757F79485B637A007D005FBD898F8A188CB48D778ECC 8F1D98E29A0E9B3C4E80507D510059935B9C622F628064EC6B3A72A075917947 7FA987FB8ABC8B7063AC83CA97A05409540355AB68546A588A70782767759ECD 53745BA2811A865090064E184E454EC74F1153CA54385BAE5F13602565510000 673D6C426C726CE3707874037A767AAE7B087D1A7CFE7D6665E7725B53BB5C45 5DE862D262E063196E20865A8A318DDD92F86F0179A69B5A4EA84EAB4EAC4F9B 4FA050D151477AF6517151F653545321537F53EB55AC58835CE15F375F4A602F 6050606D631F65596A4B6CC172C272ED77EF80F881058208854E90F793E197FF 99579A5A4EF051DD5C2D6681696D5C4066F26975738968507C8150C552E45747 5DFE932665A46B236B3D7434798179BD7B4B7DCA82B983CC887F895F8B398FD1 91D1541F92804E5D503653E5533A72D7739677E982E68EAF99C699C899D25177 611A865E55B07A7A50765BD3904796854E326ADB91E75C515C48000000000000 8C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 63987A9F6C9397748F617AAA718A96887C8268177E706851936C52F2541B85AB 8A137FA48ECD90E15366888879414FC250BE521151445553572D73EA578B5951 5F625F8460756176616761A963B2643A656C666F68426E1375667A3D7CFB7D4C 7D997E4B7F6B830E834A86CD8A088A638B668EFD981A9D8F82B88FCE9BE80000 5287621F64836FC09699684150916B206C7A6F547A747D5088408A2367084EF6 503950265065517C5238526355A7570F58055ACC5EFA61B261F862F36372691C 6A29727D72AC732E7814786F7D79770C80A9898B8B198CE28ED290639375967A 98559A139E785143539F53B35E7B5F266E1B6E90738473FE7D4382378A008AFA 96504E4E500B53E4547C56FA59D15B645DF15EAB5F276238654567AF6E5672D0 7CCA88B480A180E183F0864E8A878DE8923796C798679F134E944E924F0D5348 5449543E5A2F5F8C5FA1609F68A76A8E745A78818A9E8AA48B7791904E5E9BC9 4EA44F7C4FAF501950165149516C529F52B952FE539A53E35411000000000000 8D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 540E5589575157A2597D5B545B5D5B8F5DE55DE75DF75E785E835E9A5EB75F18 6052614C629762D863A7653B6602664366F4676D6821689769CB6C5F6D2A6D69 6E2F6E9D75327687786C7A3F7CE07D057D187D5E7DB18015800380AF80B18154 818F822A8352884C88618B1B8CA28CFC90CA91759271783F92FC95A4964D0000 980599999AD89D3B525B52AB53F7540858D562F76FE08C6A8F5F9EB9514B523B 544A56FD7A4091779D609ED273446F09817075115FFD60DA9AA872DB8FBC6B64 98034ECA56F0576458BE5A5A606861C7660F6606683968B16DF775D57D3A826E 9B424E9B4F5053C955065D6F5DE65DEE67FB6C99747378028A50939688DF5750 5EA7632B50B550AC518D670054C9585E59BB5BB05F69624D63A1683D6B736E08 707D91C7728078157826796D658E7D3083DC88C18F09969B5264572867507F6A 8CA151B45742962A583A698A80B454B25D0E57FC78959DFA4F5C524A548B643E 6628671467F57A847B567D22932F685C9BAD7B395319518A5237000000000000 8E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5BDF62F664AE64E6672D6BBA85A996D176909BD6634C93069BAB76BF66524E09 509853C25C7160E864926563685F71E673CA75237B977E8286958B838CDB9178 991065AC66AB6B8B4ED54ED44F3A4F7F523A53F853F255E356DB58EB59CB59C9 59FF5B505C4D5E025E2B5FD7601D6307652F5B5C65AF65BD65E8679D6B620000 6B7B6C0F7345794979C17CF87D197D2B80A2810281F389968A5E8A698A668A8C 8AEE8CC78CDC96CC98FC6B6F4E8B4F3C4F8D51505B575BFA6148630166426B21 6ECB6CBB723E74BD75D478C1793A800C803381EA84948F9E6C509E7F5F0F8B58 9D2B7AFA8EF85B8D96EB4E0353F157F759315AC95BA460896E7F6F0675BE8CEA 5B9F85007BE0507267F4829D5C61854A7E1E820E51995C0463688D66659C716E 793E7D1780058B1D8ECA906E86C790AA501F52FA5C3A6753707C7235914C91C8 932B82E55BC25F3160F94E3B53D65B88624B67316B8A72E973E07A2E816B8DA3 91529996511253D7546A5BFF63886A397DAC970056DA53CE5468000000000000 8F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5B975C315DDE4FEE610162FE6D3279C079CB7D427E4D7FD281ED821F84908846 89728B908E748F2F9031914B916C96C6919C4EC04F4F514553415F93620E67D4 6C416E0B73637E2691CD928353D459195BBF6DD1795D7E2E7C9B587E719F51FA 88538FF04FCA5CFB662577AC7AE3821C99FF51C65FAA65EC696F6B896DF30000 6E966F6476FE7D145DE190759187980651E6521D6240669166D96E1A5EB67DD2 7F7266F885AF85F78AF852A953D959735E8F5F90605592E4966450B7511F52DD 5320534753EC54E8554655315617596859BE5A3C5BB55C065C0F5C115C1A5E84 5E8A5EE05F70627F628462DB638C63776607660C662D6676677E68A26A1F6A35 6CBC6D886E096E58713C7126716775C77701785D7901796579F07AE07B117CA7 7D39809683D6848B8549885D88F38A1F8A3C8A548A738C618CDE91A49266937E 9418969C97984E0A4E084E1E4E575197527057CE583458CC5B225E3860C564FE 676167566D4472B675737A6384B88B7291B89320563157F498FE000000000000 90 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 62ED690D6B9671ED7E548077827289E698DF87558FB15C3B4F384FE14FB55507 5A205BDD5BE95FC3614E632F65B0664B68EE699B6D786DF1753375B9771F795E 79E67D3381E382AF85AA89AA8A3A8EAB8F9B903291DD97074EBA4EC152035875 58EC5C0B751A5C3D814E8A0A8FC59663976D7B258ACF9808916256F353A80000 9017543957825E2563A86C34708A77617C8B7FE088709042915493109318968F 745E9AC45D075D69657067A28DA896DB636E6749691983C5981796C088FE6F84 647A5BF84E16702C755D662F51C4523652E259D35F8160276210653F6574661F 667468F268166B636E057272751F76DB7CBE805658F088FD897F8AA08A938ACB 901D91929752975965897A0E810696BB5E2D60DC621A65A56614679077F37A4D 7C4D7E3E810A8CAC8D648DE18E5F78A9520762D963A5644262988A2D7A837BC0 8AAC96EA7D76820C87494ED95148534353605BA35C025C165DDD6226624764B0 681368346CC96D456D1767D36F5C714E717D65CB7A7F7BAD7DDA000000000000 91 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7E4A7FA8817A821B823985A68A6E8CCE8DF59078907792AD929195839BAE524D 55846F387136516879857E5581B37CCE564C58515CA863AA66FE66FD695A72D9 758F758E790E795679DF7C977D207D4486078A34963B90619F2050E7527553CC 53E2500955AA58EE594F723D5B8B5C64531D60E360F3635C6383633F63BB0000 64CD65E966F95DE369CD69FD6F1571E54E8975E976F87A937CDF7DCF7D9C8061 83498358846C84BC85FB88C58D709001906D9397971C9A1250CF5897618E81D3 85358D0890204FC3507452475373606F6349675F6E2C8DB3901F4FD75C5E8CCA 65CF7D9A53528896517663C35B585B6B5C0A640D6751905C4ED6591A592A6C70 8A51553E581559A560F0625367C182356955964099C49A284F5358065BFE8010 5CB15E2F5F856020614B623466FF6CF06EDE80CE817F82D4888B8CB89000902E 968A9EDB9BDB4EE353F059277B2C918D984C9DF96EDD7027535355445B856258 629E62D36CA26FEF74228A1794386FC18AFE833851E786F853EA000000000000 92 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 53E94F4690548FB0596A81315DFD7AEA8FBF68DA8C3772F89C486A3D8AB04E39 53585606576662C563A265E66B4E6DE16E5B70AD77ED7AEF7BAA7DBB803D80C6 86CB8A95935B56E358C75F3E65AD66966A806BB575378AC7502477E557305F1B 6065667A6C6075F47A1A7F6E81F48718904599B37BC9755C7AF97B5184C40000 901079E97A9283365AE177404E2D4EF25B995FE062BD663C67F16CE8866B8877 8A3B914E92F399D06A177026732A82E784578CAF4E01514651CB558B5BF55E16 5E335E815F145F355F6B5FB461F2631166A2671D6F6E7252753A773A80748139 817887768ABF8ADC8D858DF3929A957798029CE552C5635776F467156C8873CD 8CC393AE96736D25589C690E69CC8FFD939A75DB901A585A680263B469FB4F43 6F2C67D88FBB85267DB49354693F6F70576A58F75B2C7D2C722A540A91E39DB4 4EAD4F4E505C507552438C9E544858245B9A5E1D5E955EAD5EF75F1F608C62B5 633A63D068AF6C407887798E7A0B7DE082478A028AE68E449013000000000000 93 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 90B8912D91D89F0E6CE5645864E265756EF476847B1B906993D16EBA54F25FB9 64A48F4D8FED92445178586B59295C555E976DFB7E8F751C8CBC8EE2985B70B9 4F1D6BBF6FB1753096FB514E54105835585759AC5C605F926597675C6E21767B 83DF8CED901490FD934D7825783A52AA5EA6571F597460125012515A51AC0000 51CD520055105854585859575B955CF65D8B60BC6295642D6771684368BC68DF 76D76DD86E6F6D9B706F71C85F5375D879777B497B547B527CD67D7152308463 856985E48A0E8B048C468E0F9003900F94199676982D9A3095D850CD52D5540C 58025C0E61A7649E6D1E77B37AE580F48404905392855CE09D07533F5F975FB3 6D9C7279776379BF7BE46BD272EC8AAD68036A6151F87A8169345C4A9CF682EB 5BC59149701E56785C6F60C765666C8C8C5A90419813545166C7920D594890A3 51854E4D51EA85998B0E7058637A934B696299B47E047577535769608EDF96E3 6C5D4E8C5C3C5F108FE953028CD1808986795EFF65E54E735165000000000000 94 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 59825C3F97EE4EFB598A5FCD8A8D6FE179B079625BE78471732B71B15E745FF5 637B649A71C37C984E435EFC4E4B57DC56A260A96FC37D0D80FD813381BF8FB2 899786A45DF4628A64AD898767776CE26D3E743678345A467F7582AD99AC4FF3 5EC362DD63926557676F76C3724C80CC80BA8F29914D500D57F95A9268850000 6973716472FD8CB758F28CE0966A9019877F79E477E784294F2F5265535A62CD 67CF6CCA767D7B947C95823685848FEB66DD6F2072067E1B83AB99C19EA651FD 7BB178727BB880877B486AE85E61808C75517560516B92626E8C767A91979AEA 4F107F70629C7B4F95A59CE9567A585986E496BC4F345224534A53CD53DB5E06 642C6591677F6C3E6C4E724872AF73ED75547E41822C85E98CA97BC491C67169 981298EF633D6669756A76E478D0854386EE532A5351542659835E875F7C60B2 6249627962AB65906BD46CCC75B276AE789179D87DCB7F7780A588AB8AB98CBB 907F975E98DB6A0B7C3850995C3E5FAE67876BD8743577097F8E000000000000 95 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9F3B67CA7A175339758B9AED5F66819D83F180985F3C5FC575627B46903C6867 59EB5A9B7D10767E8B2C4FF55F6A6A196C376F0274E2796888688A558C795EDF 63CF75C579D282D7932892F2849C86ED9C2D54C15F6C658C6D5C70158CA78CD3 983B654F74F64E0D4ED857E0592B5A665BCC51A85E035E9C6016627665770000 65A7666E6D6E72367B268150819A82998B5C8CA08CE68D74961C96444FAE64AB 6B66821E8461856A90E85C01695398A8847A85574F0F526F5FA95E45670D798F 8179890789866DF55F1762556CB84ECF72699B925206543B567458B361A4626E 711A596E7C897CDE7D1B96F06587805E4E194F75517558405E635E735F0A67C4 4E26853D9589965B7C73980150FB58C1765678A7522577A585117B86504F5909 72477BC77DE88FBA8FD4904D4FBF52C95A295F0197AD4FDD821792EA57036355 6B69752B88DC8F147A4252DF58936155620A66AE6BCD7C3F83E950234FF85305 5446583159495B9D5CF05CEF5D295E9662B16367653E65B9670B000000000000 96 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6CD56CE170F978327E2B80DE82B3840C84EC870289128A2A8C4A90A692D298FD 9CF39D6C4E4F4EA1508D5256574A59A85E3D5FD85FD9623F66B4671B67D068D2 51927D2180AA81A88B008C8C8CBF927E96325420982C531750D5535C58A864B2 6734726777667A4691E652C36CA16B8658005E4C5954672C7FFB51E176C60000 646978E89B549EBB57CB59B96627679A6BCE54E969D95E55819C67959BAA67FE 9C52685D4EA64FE353C862B9672B6CAB8FC44FAD7E6D9EBF4E0761626E806F2B 85135473672A9B455DF37B955CAC5BC6871C6E4A84D17A14810859997C8D6C11 772052D959227121725F77DB97279D61690B5A7F5A1851A5540D547D660E76DF 8FF792989CF459EA725D6EC5514D68C97DBF7DEC97629EBA64786A2183025984 5B5F6BDB731B76F27DB280178499513267289ED976EE676252FF99055C24623B 7C7E8CB0554F60B67D0B958053014E5F51B6591C723A803691CE5F2577E25384 5F797D0485AC8A338E8D975667F385AE9453610961086CB97652000000000000 97 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8AED8F38552F4F51512A52C753CB5BA55E7D60A0618263D6670967DA6E676D8C 733673377531795088D58A98904A909190F596C4878D59154E884F594E0E8A89 8F3F981050AD5E7C59965BB95EB863DA63FA64C166DC694A69D86D0B6EB67194 75287AAF7F8A8000844984C989818B218E0A9065967D990A617E62916B320000 6C836D747FCC7FFC6DC07F8587BA88F8676583B1983C96F76D1B7D61843D916A 4E7153755D506B046FEB85CD862D89A75229540F5C65674E68A87406748375E2 88CF88E191CC96E296785F8B73877ACB844E63A0756552896D416E9C74097559 786B7C9296867ADC9F8D4FB6616E65C5865C4E864EAE50DA4E2151CC5BEE6599 68816DBC731F764277AD7A1C7CE7826F8AD2907C91CF96759818529B7DD1502B 539867976DCB71D0743381E88F2A96A39C579E9F746058416D997D2F985E4EE4 4F364F8B51B752B15DBA601C73B2793C82D3923496B796F6970A9E979F6266A6 6B74521752A370C888C25EC9604B61906F2371497C3E7DF4806F000000000000 98 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 84EE9023932C54429B6F6AD370898CC28DEF973252B45A415ECA5F046717697C 69946D6A6F0F726272FC7BED8001807E874B90CE516D9E937984808B93328AD6 502D548C8A716B6A8CC4810760D167A09DF24E994E989C108A6B85C185686900 6E7E789781550000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000005F0C 4E104E154E2A4E314E364E3C4E3F4E424E564E584E824E858C6B4E8A82125F0D 4E8E4E9E4E9F4EA04EA24EB04EB34EB64ECE4ECD4EC44EC64EC24ED74EDE4EED 4EDF4EF74F094F5A4F304F5B4F5D4F574F474F764F884F8F4F984F7B4F694F70 4F914F6F4F864F9651184FD44FDF4FCE4FD84FDB4FD14FDA4FD04FE44FE5501A 50285014502A502550054F1C4FF650215029502C4FFE4FEF5011500650435047 6703505550505048505A5056506C50785080509A508550B450B2000000000000 99 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 50C950CA50B350C250D650DE50E550ED50E350EE50F950F55109510151025116 51155114511A5121513A5137513C513B513F51405152514C515451627AF85169 516A516E5180518256D8518C5189518F519151935195519651A451A651A251A9 51AA51AB51B351B151B251B051B551BD51C551C951DB51E0865551E951ED0000 51F051F551FE5204520B5214520E5227522A522E52335239524F5244524B524C 525E5254526A527452695273527F527D528D529452925271528852918FA88FA7 52AC52AD52BC52B552C152CD52D752DE52E352E698ED52E052F352F552F852F9 530653087538530D5310530F5315531A5323532F533153335338534053465345 4E175349534D51D6535E5369536E5918537B53775382539653A053A653A553AE 53B053B653C37C1296D953DF66FC71EE53EE53E853ED53FA5401543D5440542C 542D543C542E54365429541D544E548F5475548E545F5471547754705492547B 5480547654845490548654C754A254B854A554AC54C454C854A8000000000000 9A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 54AB54C254A454BE54BC54D854E554E6550F551454FD54EE54ED54FA54E25539 55405563554C552E555C55455556555755385533555D5599558054AF558A559F 557B557E5598559E55AE557C558355A9558755A855DA55C555DF55C455DC55E4 55D4561455F7561655FE55FD561B55F9564E565071DF56345636563256380000 566B5664562F566C566A56865680568A56A05694568F56A556AE56B656B456C2 56BC56C156C356C056C856CE56D156D356D756EE56F9570056FF570457095708 570B570D57135718571655C7571C572657375738574E573B5740574F576957C0 57885761577F5789579357A057B357A457AA57B057C357C657D457D257D3580A 57D657E3580B5819581D587258215862584B58706BC05852583D5879588558B9 589F58AB58BA58DE58BB58B858AE58C558D358D158D758D958D858E558DC58E4 58DF58EF58FA58F958FB58FC58FD5902590A5910591B68A65925592C592D5932 5938593E7AD259555950594E595A5958596259605967596C5969000000000000 9B 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 59785981599D4F5E4FAB59A359B259C659E859DC598D59D959DA5A255A1F5A11 5A1C5A095A1A5A405A6C5A495A355A365A625A6A5A9A5ABC5ABE5ACB5AC25ABD 5AE35AD75AE65AE95AD65AFA5AFB5B0C5B0B5B165B325AD05B2A5B365B3E5B43 5B455B405B515B555B5A5B5B5B655B695B705B735B755B7865885B7A5B800000 5B835BA65BB85BC35BC75BC95BD45BD05BE45BE65BE25BDE5BE55BEB5BF05BF6 5BF35C055C075C085C0D5C135C205C225C285C385C395C415C465C4E5C535C50 5C4F5B715C6C5C6E4E625C765C795C8C5C915C94599B5CAB5CBB5CB65CBC5CB7 5CC55CBE5CC75CD95CE95CFD5CFA5CED5D8C5CEA5D0B5D155D175D5C5D1F5D1B 5D115D145D225D1A5D195D185D4C5D525D4E5D4B5D6C5D735D765D875D845D82 5DA25D9D5DAC5DAE5DBD5D905DB75DBC5DC95DCD5DD35DD25DD65DDB5DEB5DF2 5DF55E0B5E1A5E195E115E1B5E365E375E445E435E405E4E5E575E545E5F5E62 5E645E475E755E765E7A9EBC5E7F5EA05EC15EC25EC85ED05ECF000000000000 9C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 5ED65EE35EDD5EDA5EDB5EE25EE15EE85EE95EEC5EF15EF35EF05EF45EF85EFE 5F035F095F5D5F5C5F0B5F115F165F295F2D5F385F415F485F4C5F4E5F2F5F51 5F565F575F595F615F6D5F735F775F835F825F7F5F8A5F885F915F875F9E5F99 5F985FA05FA85FAD5FBC5FD65FFB5FE45FF85FF15FDD60B35FFF602160600000 601960106029600E6031601B6015602B6026600F603A605A6041606A6077605F 604A6046604D6063604360646042606C606B60596081608D60E76083609A6084 609B60966097609260A7608B60E160B860E060D360B45FF060BD60C660B560D8 614D6115610660F660F7610060F460FA6103612160FB60F1610D610E6147613E 61286127614A613F613C612C6134613D614261446173617761586159615A616B 6174616F61656171615F615D6153617561996196618761AC6194619A618A6191 61AB61AE61CC61CA61C961F761C861C361C661BA61CB7F7961CD61E661E361F6 61FA61F461FF61FD61FC61FE620062086209620D620C6214621B000000000000 9D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 621E6221622A622E6230623262336241624E625E6263625B62606268627C6282 6289627E62926293629662D46283629462D762D162BB62CF62FF62C664D462C8 62DC62CC62CA62C262C7629B62C9630C62EE62F163276302630862EF62F56350 633E634D641C634F6396638E638063AB637663A3638F6389639F63B5636B0000 636963BE63E963C063C663E363C963D263F663C4641664346406641364266436 651D64176428640F6467646F6476644E652A6495649364A564A9648864BC64DA 64D264C564C764BB64D864C264F164E7820964E064E162AC64E364EF652C64F6 64F464F264FA650064FD6518651C650565246523652B65346535653765366538 754B654865566555654D6558655E655D65726578658265838B8A659B659F65AB 65B765C365C665C165C465CC65D265DB65D965E065E165F16772660A660365FB 6773663566366634661C664F664466496641665E665D666466676668665F6662 667066836688668E668966846698669D66C166B966C966BE66BC000000000000 9E 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 66C466B866D666DA66E0663F66E666E966F066F566F7670F6716671E67266727 9738672E673F67366741673867376746675E67606759676367646789677067A9 677C676A678C678B67A667A1678567B767EF67B467EC67B367E967B867E467DE 67DD67E267EE67B967CE67C667E76A9C681E684668296840684D6832684E0000 68B3682B685968636877687F689F688F68AD6894689D689B68836AAE68B96874 68B568A068BA690F688D687E690168CA690868D86922692668E1690C68CD68D4 68E768D569366912690468D768E3692568F968E068EF6928692A691A69236921 68C669796977695C6978696B6954697E696E69396974693D695969306961695E 695D6981696A69B269AE69D069BF69C169D369BE69CE5BE869CA69DD69BB69C3 69A76A2E699169A0699C699569B469DE69E86A026A1B69FF6B0A69F969F269E7 6A0569B16A1E69ED6A1469EB6A0A6A126AC16A236A136A446A0C6A726A366A78 6A476A626A596A666A486A386A226A906A8D6AA06A846AA26AA3000000000000 9F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6A9786176ABB6AC36AC26AB86AB36AAC6ADE6AD16ADF6AAA6ADA6AEA6AFB6B05 86166AFA6B126B169B316B1F6B386B3776DC6B3998EE6B476B436B496B506B59 6B546B5B6B5F6B616B786B796B7F6B806B846B836B8D6B986B956B9E6BA46BAA 6BAB6BAF6BB26BB16BB36BB76BBC6BC66BCB6BD36BDF6BEC6BEB6BF36BEF0000 9EBE6C086C136C146C1B6C246C236C5E6C556C626C6A6C826C8D6C9A6C816C9B 6C7E6C686C736C926C906CC46CF16CD36CBD6CD76CC56CDD6CAE6CB16CBE6CBA 6CDB6CEF6CD96CEA6D1F884D6D366D2B6D3D6D386D196D356D336D126D0C6D63 6D936D646D5A6D796D596D8E6D956FE46D856DF96E156E0A6DB56DC76DE66DB8 6DC66DEC6DDE6DCC6DE86DD26DC56DFA6DD96DE46DD56DEA6DEE6E2D6E6E6E2E 6E196E726E5F6E3E6E236E6B6E2B6E766E4D6E1F6E436E3A6E4E6E246EFF6E1D 6E386E826EAA6E986EC96EB76ED36EBD6EAF6EC46EB26ED46ED56E8F6EA56EC2 6E9F6F416F11704C6EEC6EF86EFE6F3F6EF26F316EEF6F326ECC000000000000 E0 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6F3E6F136EF76F866F7A6F786F816F806F6F6F5B6FF36F6D6F826F7C6F586F8E 6F916FC26F666FB36FA36FA16FA46FB96FC66FAA6FDF6FD56FEC6FD46FD86FF1 6FEE6FDB7009700B6FFA70117001700F6FFE701B701A6F74701D7018701F7030 703E7032705170637099709270AF70F170AC70B870B370AE70DF70CB70DD0000 70D9710970FD711C711971657155718871667162714C7156716C718F71FB7184 719571A871AC71D771B971BE71D271C971D471CE71E071EC71E771F571FC71F9 71FF720D7210721B7228722D722C72307232723B723C723F72407246724B7258 7274727E7282728172877292729672A272A772B972B272C372C672C472CE72D2 72E272E072E172F972F7500F7317730A731C7316731D7334732F73297325733E 734E734F9ED87357736A7368737073787375737B737A73C873B373CE73BB73C0 73E573EE73DE74A27405746F742573F87432743A7455743F745F74597441745C 746974707463746A7476747E748B749E74A774CA74CF74D473F1000000000000 E1 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 74E074E374E774E974EE74F274F074F174F874F7750475037505750C750E750D 75157513751E7526752C753C7544754D754A7549755B7546755A756975647567 756B756D75787576758675877574758A758975827594759A759D75A575A375C2 75B375C375B575BD75B875BC75B175CD75CA75D275D975E375DE75FE75FF0000 75FC760175F075FA75F275F3760B760D7609761F762776207621762276247634 7630763B764776487646765C76587661766276687669766A7667766C76707672 76767678767C768076837688768B768E769676937699769A76B076B476B876B9 76BA76C276CD76D676D276DE76E176E576E776EA862F76FB7708770777047729 7724771E77257726771B773777387747775A7768776B775B7765777F777E7779 778E778B779177A0779E77B077B677B977BF77BC77BD77BB77C777CD77D777DA 77DC77E377EE77FC780C781279267820792A7845788E78747886787C789A788C 78A378B578AA78AF78D178C678CB78D478BE78BC78C578CA78EC000000000000 E2 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 78E778DA78FD78F47907791279117919792C792B794079607957795F795A7955 7953797A797F798A799D79A79F4B79AA79AE79B379B979BA79C979D579E779EC 79E179E37A087A0D7A187A197A207A1F79807A317A3B7A3E7A377A437A577A49 7A617A627A699F9D7A707A797A7D7A887A977A957A987A967AA97AC87AB00000 7AB67AC57AC47ABF90837AC77ACA7ACD7ACF7AD57AD37AD97ADA7ADD7AE17AE2 7AE67AED7AF07B027B0F7B0A7B067B337B187B197B1E7B357B287B367B507B7A 7B047B4D7B0B7B4C7B457B757B657B747B677B707B717B6C7B6E7B9D7B987B9F 7B8D7B9C7B9A7B8B7B927B8F7B5D7B997BCB7BC17BCC7BCF7BB47BC67BDD7BE9 7C117C147BE67BE57C607C007C077C137BF37BF77C177C0D7BF67C237C277C2A 7C1F7C377C2B7C3D7C4C7C437C547C4F7C407C507C587C5F7C647C567C657C6C 7C757C837C907CA47CAD7CA27CAB7CA17CA87CB37CB27CB17CAE7CB97CBD7CC0 7CC57CC27CD87CD27CDC7CE29B3B7CEF7CF27CF47CF67CFA7D06000000000000 E3 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7D027D1C7D157D0A7D457D4B7D2E7D327D3F7D357D467D737D567D4E7D727D68 7D6E7D4F7D637D937D897D5B7D8F7D7D7D9B7DBA7DAE7DA37DB57DC77DBD7DAB 7E3D7DA27DAF7DDC7DB87D9F7DB07DD87DDD7DE47DDE7DFB7DF27DE17E057E0A 7E237E217E127E317E1F7E097E0B7E227E467E667E3B7E357E397E437E370000 7E327E3A7E677E5D7E567E5E7E597E5A7E797E6A7E697E7C7E7B7E837DD57E7D 8FAE7E7F7E887E897E8C7E927E907E937E947E967E8E7E9B7E9C7F387F3A7F45 7F4C7F4D7F4E7F507F517F557F547F587F5F7F607F687F697F677F787F827F86 7F837F887F877F8C7F947F9E7F9D7F9A7FA37FAF7FB27FB97FAE7FB67FB88B71 7FC57FC67FCA7FD57FD47FE17FE67FE97FF37FF998DC80068004800B80128018 8019801C80218028803F803B804A804680528058805A805F8062806880738072 807080768079807D807F808480868085809B8093809A80AD519080AC80DB80E5 80D980DD80C480DA80D6810980EF80F1811B81298123812F814B000000000000 E4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 968B8146813E8153815180FC8171816E81658166817481838188818A81808182 81A0819581A481A3815F819381A981B081B581BE81B881BD81C081C281BA81C9 81CD81D181D981D881C881DA81DF81E081E781FA81FB81FE8201820282058207 820A820D821082168229822B82388233824082598258825D825A825F82640000 82628268826A826B822E827182778278827E828D829282AB829F82BB82AC82E1 82E382DF82D282F482F382FA8393830382FB82F982DE830682DC830982D98335 83348316833283318340833983508345832F832B831783188385839A83AA839F 83A283968323838E8387838A837C83B58373837583A0838983A883F4841383EB 83CE83FD840383D8840B83C183F7840783E083F2840D8422842083BD84388506 83FB846D842A843C855A84848477846B84AD846E848284698446842C846F8479 843584CA846284B984BF849F84D984CD84BB84DA84D084C184C684D684A18521 84FF84F485178518852C851F8515851484FC8540856385588548000000000000 E5 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 85418602854B8555858085A485888591858A85A8856D8594859B85EA8587859C 8577857E859085C985BA85CF85B985D085D585DD85E585DC85F9860A8613860B 85FE85FA86068622861A8630863F864D4E558654865F86678671869386A386A9 86AA868B868C86B686AF86C486C686B086C9882386AB86D486DE86E986EC0000 86DF86DB86EF8712870687088700870386FB87118709870D86F9870A8734873F 8737873B87258729871A8760875F8778874C874E877487578768876E87598753 8763876A880587A2879F878287AF87CB87BD87C087D096D687AB87C487B387C7 87C687BB87EF87F287E0880F880D87FE87F687F7880E87D28811881688158822 88218831883688398827883B8844884288528859885E8862886B8881887E889E 8875887D88B5887288828897889288AE889988A2888D88A488B088BF88B188C3 88C488D488D888D988DD88F9890288FC88F488E888F28904890C890A89138943 891E8925892A892B89418944893B89368938894C891D8960895E000000000000 E6 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 89668964896D896A896F89748977897E89838988898A8993899889A189A989A6 89AC89AF89B289BA89BD89BF89C089DA89DC89DD89E789F489F88A038A168A10 8A0C8A1B8A1D8A258A368A418A5B8A528A468A488A7C8A6D8A6C8A628A858A82 8A848AA88AA18A918AA58AA68A9A8AA38AC48ACD8AC28ADA8AEB8AF38AE70000 8AE48AF18B148AE08AE28AF78ADE8ADB8B0C8B078B1A8AE18B168B108B178B20 8B3397AB8B268B2B8B3E8B288B418B4C8B4F8B4E8B498B568B5B8B5A8B6B8B5F 8B6C8B6F8B748B7D8B808B8C8B8E8B928B938B968B998B9A8C3A8C418C3F8C48 8C4C8C4E8C508C558C628C6C8C788C7A8C828C898C858C8A8C8D8C8E8C948C7C 8C98621D8CAD8CAA8CBD8CB28CB38CAE8CB68CC88CC18CE48CE38CDA8CFD8CFA 8CFB8D048D058D0A8D078D0F8D0D8D109F4E8D138CCD8D148D168D678D6D8D71 8D738D818D998DC28DBE8DBA8DCF8DDA8DD68DCC8DDB8DCB8DEA8DEB8DDF8DE3 8DFC8E088E098DFF8E1D8E1E8E108E1F8E428E358E308E348E4A000000000000 E7 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 8E478E498E4C8E508E488E598E648E608E2A8E638E558E768E728E7C8E818E87 8E858E848E8B8E8A8E938E918E948E998EAA8EA18EAC8EB08EC68EB18EBE8EC5 8EC88ECB8EDB8EE38EFC8EFB8EEB8EFE8F0A8F058F158F128F198F138F1C8F1F 8F1B8F0C8F268F338F3B8F398F458F428F3E8F4C8F498F468F4E8F578F5C0000 8F628F638F648F9C8F9F8FA38FAD8FAF8FB78FDA8FE58FE28FEA8FEF90878FF4 90058FF98FFA901190159021900D901E9016900B90279036903590398FF8904F 905090519052900E9049903E90569058905E9068906F907696A890729082907D 90819080908A9089908F90A890AF90B190B590E290E4624890DB910291129119 91329130914A9156915891639165916991739172918B9189918291A291AB91AF 91AA91B591B491BA91C091C191C991CB91D091D691DF91E191DB91FC91F591F6 921E91FF9214922C92159211925E925792459249926492489295923F924B9250 929C92969293929B925A92CF92B992B792E9930F92FA9344932E000000000000 E8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 93199322931A9323933A9335933B935C9360937C936E935693B093AC93AD9394 93B993D693D793E893E593D893C393DD93D093C893E4941A9414941394039407 94109436942B94359421943A944194529444945B94609462945E946A92299470 94759477947D945A947C947E9481947F95829587958A95949596959895990000 95A095A895A795AD95BC95BB95B995BE95CA6FF695C395CD95CC95D595D495D6 95DC95E195E595E296219628962E962F9642964C964F964B9677965C965E965D 965F96669672966C968D96989695969796AA96A796B196B296B096B496B696B8 96B996CE96CB96C996CD894D96DC970D96D596F99704970697089713970E9711 970F971697199724972A97309739973D973E97449746974897429749975C9760 97649766976852D2976B977197799785977C9781977A9786978B978F9790979C 97A897A697A397B397B497C397C697C897CB97DC97ED9F4F97F27ADF97F697F5 980F980C9838982498219837983D9846984F984B986B986F9870000000000000 E9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 98719874987398AA98AF98B198B698C498C398C698E998EB9903990999129914 99189921991D991E99249920992C992E993D993E9942994999459950994B9951 9952994C99559997999899A599AD99AE99BC99DF99DB99DD99D899D199ED99EE 99F199F299FB99F89A019A0F9A0599E29A199A2B9A379A459A429A409A430000 9A3E9A559A4D9A5B9A579A5F9A629A659A649A699A6B9A6A9AAD9AB09ABC9AC0 9ACF9AD19AD39AD49ADE9ADF9AE29AE39AE69AEF9AEB9AEE9AF49AF19AF79AFB 9B069B189B1A9B1F9B229B239B259B279B289B299B2A9B2E9B2F9B329B449B43 9B4F9B4D9B4E9B519B589B749B939B839B919B969B979B9F9BA09BA89BB49BC0 9BCA9BB99BC69BCF9BD19BD29BE39BE29BE49BD49BE19C3A9BF29BF19BF09C15 9C149C099C139C0C9C069C089C129C0A9C049C2E9C1B9C259C249C219C309C47 9C329C469C3E9C5A9C609C679C769C789CE79CEC9CF09D099D089CEB9D039D06 9D2A9D269DAF9D239D1F9D449D159D129D419D3F9D3E9D469D48000000000000 EA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9D5D9D5E9D649D519D509D599D729D899D879DAB9D6F9D7A9D9A9DA49DA99DB2 9DC49DC19DBB9DB89DBA9DC69DCF9DC29DD99DD39DF89DE69DED9DEF9DFD9E1A 9E1B9E1E9E759E799E7D9E819E889E8B9E8C9E929E959E919E9D9EA59EA99EB8 9EAA9EAD97619ECC9ECE9ECF9ED09ED49EDC9EDE9EDD9EE09EE59EE89EEF0000 9EF49EF69EF79EF99EFB9EFC9EFD9F079F0876B79F159F219F2C9F3E9F4A9F52 9F549F639F5F9F609F619F669F679F6C9F6A9F779F729F769F959F9C9FA0582F 69C79059746451DC719900000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 ED 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 7E8A891C9348928884DC4FC970BB663168C892F966FB5F454E284EE14EFC4F00 4F034F394F564F924F8A4F9A4F944FCD504050224FFF501E5046507050425094 50F450D8514A5164519D51BE51EC5215529C52A652C052DB5300530753245372 539353B253DDFA0E549C548A54A954FF55865759576557AC57C857C7FA0F0000 FA10589E58B2590B5953595B595D596359A459BA5B565BC0752F5BD85BEC5C1E 5CA65CBA5CF55D275D53FA115D425D6D5DB85DB95DD05F215F345F675FB75FDE 605D6085608A60DE60D5612060F26111613761306198621362A663F56460649D 64CE654E66006615663B6609662E661E6624666566576659FA126673669966A0 66B266BF66FA670EF929676667BB685267C06801684468CFFA136968FA146998 69E26A306A6B6A466A736A7E6AE26AE46BD66C3F6C5C6C866C6F6CDA6D046D87 6D6F6D966DAC6DCF6DF86DF26DFC6E396E5C6E276E3C6EBF6F886FB56FF57005 70077028708570AB710F7104715C71467147FA1571C171FE72B1000000000000 EE 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 72BE7324FA16737773BD73C973D673E373D2740773F57426742A7429742E7462 7489749F7501756F7682769C769E769B76A6FA17774652AF7821784E7864787A 7930FA18FA19FA1A7994FA1B799B7AD17AE7FA1C7AEB7B9EFA1D7D487D5C7DB7 7DA07DD67E527F477FA1FA1E83018362837F83C783F6844884B4855385590000 856BFA1F85B0FA20FA21880788F58A128A378A798AA78ABE8ADFFA228AF68B53 8B7F8CF08CF48D128D76FA238ECFFA24FA25906790DEFA269115912791DA91D7 91DE91ED91EE91E491E592069210920A923A9240923C924E9259925192399267 92A79277927892E792D792D992D0FA2792D592E092D39325932192FBFA28931E 92FF931D93029370935793A493C693DE93F89431944594489592F9DCFA29969D 96AF9733973B9743974D974F9751975598579865FA2AFA2B9927FA2C999E9A4E 9AD99ADC9B759B729B8F9BB19BBB9C009D709D6BFA2D9E199ED1000000002170 217121722173217421752176217721782179FFE2FFE4FF07FF02000000000000 FA 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 2170217121722173217421752176217721782179216021612162216321642165 2166216721682169FFE2FFE4FF07FF0232312116212122357E8A891C93489288 84DC4FC970BB663168C892F966FB5F454E284EE14EFC4F004F034F394F564F92 4F8A4F9A4F944FCD504050224FFF501E504650705042509450F450D8514A0000 5164519D51BE51EC5215529C52A652C052DB5300530753245372539353B253DD FA0E549C548A54A954FF55865759576557AC57C857C7FA0FFA10589E58B2590B 5953595B595D596359A459BA5B565BC0752F5BD85BEC5C1E5CA65CBA5CF55D27 5D53FA115D425D6D5DB85DB95DD05F215F345F675FB75FDE605D6085608A60DE 60D5612060F26111613761306198621362A663F56460649D64CE654E66006615 663B6609662E661E6624666566576659FA126673669966A066B266BF66FA670E F929676667BB685267C06801684468CFFA136968FA14699869E26A306A6B6A46 6A736A7E6AE26AE46BD66C3F6C5C6C866C6F6CDA6D046D876D6F000000000000 FB 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 6D966DAC6DCF6DF86DF26DFC6E396E5C6E276E3C6EBF6F886FB56FF570057007 7028708570AB710F7104715C71467147FA1571C171FE72B172BE7324FA167377 73BD73C973D673E373D2740773F57426742A7429742E74627489749F7501756F 7682769C769E769B76A6FA17774652AF7821784E7864787A7930FA18FA190000 FA1A7994FA1B799B7AD17AE7FA1C7AEB7B9EFA1D7D487D5C7DB77DA07DD67E52 7F477FA1FA1E83018362837F83C783F6844884B485538559856BFA1F85B0FA20 FA21880788F58A128A378A798AA78ABE8ADFFA228AF68B538B7F8CF08CF48D12 8D76FA238ECFFA24FA25906790DEFA269115912791DA91D791DE91ED91EE91E4 91E592069210920A923A9240923C924E925992519239926792A79277927892E7 92D792D992D0FA2792D592E092D39325932192FBFA28931E92FF931D93029370 935793A493C693DE93F89431944594489592F9DCFA29969D96AF9733973B9743 974D974F9751975598579865FA2AFA2B9927FA2C999E9A4E9AD9000000000000 FC 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 9ADC9B759B729B8F9BB19BBB9C009D709D6BFA2D9E199ED10000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 R 8160 301C FF5E 8161 2016 2225 817C 2212 FF0D 8191 00A2 FFE0 8192 00A3 FFE1 81CA 00AC FFE2 81BE 222a 81BF 2229 81DA 2220 81DB 22a5 81DF 2261 81E0 2252 81E3 221a 81E6 2235 81E7 222b tcl8.6.5/library/encoding/cp1251.enc0000644000175000017500000000210311555560473016420 0ustar sergeisergei# Encoding file: cp1251, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 04020403201A0453201E20262020202120AC203004092039040A040C040B040F 045220182019201C201D202220132014009821220459203A045A045C045B045F 00A0040E045E040800A4049000A600A7040100A9040400AB00AC00AD00AE0407 00B000B104060456049100B500B600B704512116045400BB0458040504550457 0410041104120413041404150416041704180419041A041B041C041D041E041F 0420042104220423042404250426042704280429042A042B042C042D042E042F 0430043104320433043404350436043704380439043A043B043C043D043E043F 0440044104420443044404450446044704480449044A044B044C044D044E044F tcl8.6.5/library/encoding/iso8859-5.enc0000644000175000017500000000210611555560473017002 0ustar sergeisergei# Encoding file: iso8859-5, single-byte S 003F 0 1 00 0000000100020003000400050006000700080009000A000B000C000D000E000F 0010001100120013001400150016001700180019001A001B001C001D001E001F 0020002100220023002400250026002700280029002A002B002C002D002E002F 0030003100320033003400350036003700380039003A003B003C003D003E003F 0040004100420043004400450046004700480049004A004B004C004D004E004F 0050005100520053005400550056005700580059005A005B005C005D005E005F 0060006100620063006400650066006700680069006A006B006C006D006E006F 0070007100720073007400750076007700780079007A007B007C007D007E007F 0080008100820083008400850086008700880089008A008B008C008D008E008F 0090009100920093009400950096009700980099009A009B009C009D009E009F 00A0040104020403040404050406040704080409040A040B040C00AD040E040F 0410041104120413041404150416041704180419041A041B041C041D041E041F 0420042104220423042404250426042704280429042A042B042C042D042E042F 0430043104320433043404350436043704380439043A043B043C043D043E043F 0440044104420443044404450446044704480449044A044B044C044D044E044F 2116045104520453045404550456045704580459045A045B045C00A7045E045F tcl8.6.5/library/clock.tcl0000755000175000017500000037364612663660066015061 0ustar sergeisergei#---------------------------------------------------------------------- # # clock.tcl -- # # This file implements the portions of the [clock] ensemble that are # coded in Tcl. Refer to the users' manual to see the description of # the [clock] command and its subcommands. # # #---------------------------------------------------------------------- # # Copyright (c) 2004,2005,2006,2007 by Kevin B. Kenny # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # #---------------------------------------------------------------------- # We must have message catalogs that support the root locale, and we need # access to the Registry on Windows systems. uplevel \#0 { package require msgcat 1.6 if { $::tcl_platform(platform) eq {windows} } { if { [catch { package require registry 1.1 }] } { namespace eval ::tcl::clock [list variable NoRegistry {}] } } } # Put the library directory into the namespace for the ensemble so that the # library code can find message catalogs and time zone definition files. namespace eval ::tcl::clock \ [list variable LibDir [file dirname [info script]]] #---------------------------------------------------------------------- # # clock -- # # Manipulate times. # # The 'clock' command manipulates time. Refer to the user documentation for # the available subcommands and what they do. # #---------------------------------------------------------------------- namespace eval ::tcl::clock { # Export the subcommands namespace export format namespace export clicks namespace export microseconds namespace export milliseconds namespace export scan namespace export seconds namespace export add # Import the message catalog commands that we use. namespace import ::msgcat::mcload namespace import ::msgcat::mclocale namespace import ::msgcat::mc namespace import ::msgcat::mcpackagelocale } #---------------------------------------------------------------------- # # ::tcl::clock::Initialize -- # # Finish initializing the 'clock' subsystem # # Results: # None. # # Side effects: # Namespace variable in the 'clock' subsystem are initialized. # # The '::tcl::clock::Initialize' procedure initializes the namespace variables # and root locale message catalog for the 'clock' subsystem. It is broken # into a procedure rather than simply evaluated as a script so that it will be # able to use local variables, avoiding the dangers of 'creative writing' as # in Bug 1185933. # #---------------------------------------------------------------------- proc ::tcl::clock::Initialize {} { rename ::tcl::clock::Initialize {} variable LibDir # Define the Greenwich time zone proc InitTZData {} { variable TZData array unset TZData set TZData(:Etc/GMT) { {-9223372036854775808 0 0 GMT} } set TZData(:GMT) $TZData(:Etc/GMT) set TZData(:Etc/UTC) { {-9223372036854775808 0 0 UTC} } set TZData(:UTC) $TZData(:Etc/UTC) set TZData(:localtime) {} } InitTZData mcpackagelocale set {} ::msgcat::mcpackageconfig set mcfolder [file join $LibDir msgs] ::msgcat::mcpackageconfig set unknowncmd "" ::msgcat::mcpackageconfig set changecmd ChangeCurrentLocale # Define the message catalog for the root locale. ::msgcat::mcmset {} { AM {am} BCE {B.C.E.} CE {C.E.} DATE_FORMAT {%m/%d/%Y} DATE_TIME_FORMAT {%a %b %e %H:%M:%S %Y} DAYS_OF_WEEK_ABBREV { Sun Mon Tue Wed Thu Fri Sat } DAYS_OF_WEEK_FULL { Sunday Monday Tuesday Wednesday Thursday Friday Saturday } GREGORIAN_CHANGE_DATE 2299161 LOCALE_DATE_FORMAT {%m/%d/%Y} LOCALE_DATE_TIME_FORMAT {%a %b %e %H:%M:%S %Y} LOCALE_ERAS {} LOCALE_NUMERALS { 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 } LOCALE_TIME_FORMAT {%H:%M:%S} LOCALE_YEAR_FORMAT {%EC%Ey} MONTHS_ABBREV { Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec } MONTHS_FULL { January February March April May June July August September October November December } PM {pm} TIME_FORMAT {%H:%M:%S} TIME_FORMAT_12 {%I:%M:%S %P} TIME_FORMAT_24 {%H:%M} TIME_FORMAT_24_SECS {%H:%M:%S} } # Define a few Gregorian change dates for other locales. In most cases # the change date follows a language, because a nation's colonies changed # at the same time as the nation itself. In many cases, different # national boundaries existed; the dominating rule is to follow the # nation's capital. # Italy, Spain, Portugal, Poland ::msgcat::mcset it GREGORIAN_CHANGE_DATE 2299161 ::msgcat::mcset es GREGORIAN_CHANGE_DATE 2299161 ::msgcat::mcset pt GREGORIAN_CHANGE_DATE 2299161 ::msgcat::mcset pl GREGORIAN_CHANGE_DATE 2299161 # France, Austria ::msgcat::mcset fr GREGORIAN_CHANGE_DATE 2299227 # For Belgium, we follow Southern Netherlands; Liege Diocese changed # several weeks later. ::msgcat::mcset fr_BE GREGORIAN_CHANGE_DATE 2299238 ::msgcat::mcset nl_BE GREGORIAN_CHANGE_DATE 2299238 # Austria ::msgcat::mcset de_AT GREGORIAN_CHANGE_DATE 2299527 # Hungary ::msgcat::mcset hu GREGORIAN_CHANGE_DATE 2301004 # Germany, Norway, Denmark (Catholic Germany changed earlier) ::msgcat::mcset de_DE GREGORIAN_CHANGE_DATE 2342032 ::msgcat::mcset nb GREGORIAN_CHANGE_DATE 2342032 ::msgcat::mcset nn GREGORIAN_CHANGE_DATE 2342032 ::msgcat::mcset no GREGORIAN_CHANGE_DATE 2342032 ::msgcat::mcset da GREGORIAN_CHANGE_DATE 2342032 # Holland (Brabant, Gelderland, Flanders, Friesland, etc. changed at # various times) ::msgcat::mcset nl GREGORIAN_CHANGE_DATE 2342165 # Protestant Switzerland (Catholic cantons changed earlier) ::msgcat::mcset fr_CH GREGORIAN_CHANGE_DATE 2361342 ::msgcat::mcset it_CH GREGORIAN_CHANGE_DATE 2361342 ::msgcat::mcset de_CH GREGORIAN_CHANGE_DATE 2361342 # English speaking countries ::msgcat::mcset en GREGORIAN_CHANGE_DATE 2361222 # Sweden (had several changes onto and off of the Gregorian calendar) ::msgcat::mcset sv GREGORIAN_CHANGE_DATE 2361390 # Russia ::msgcat::mcset ru GREGORIAN_CHANGE_DATE 2421639 # Romania (Transylvania changed earler - perhaps de_RO should show the # earlier date?) ::msgcat::mcset ro GREGORIAN_CHANGE_DATE 2422063 # Greece ::msgcat::mcset el GREGORIAN_CHANGE_DATE 2423480 #------------------------------------------------------------------ # # CONSTANTS # #------------------------------------------------------------------ # Paths at which binary time zone data for the Olson libraries are known # to reside on various operating systems variable ZoneinfoPaths {} foreach path { /usr/share/zoneinfo /usr/share/lib/zoneinfo /usr/lib/zoneinfo /usr/local/etc/zoneinfo } { if { [file isdirectory $path] } { lappend ZoneinfoPaths $path } } # Define the directories for time zone data and message catalogs. variable DataDir [file join $LibDir tzdata] # Number of days in the months, in common years and leap years. variable DaysInRomanMonthInCommonYear \ { 31 28 31 30 31 30 31 31 30 31 30 31 } variable DaysInRomanMonthInLeapYear \ { 31 29 31 30 31 30 31 31 30 31 30 31 } variable DaysInPriorMonthsInCommonYear [list 0] variable DaysInPriorMonthsInLeapYear [list 0] set i 0 foreach j $DaysInRomanMonthInCommonYear { lappend DaysInPriorMonthsInCommonYear [incr i $j] } set i 0 foreach j $DaysInRomanMonthInLeapYear { lappend DaysInPriorMonthsInLeapYear [incr i $j] } # Another epoch (Hi, Jeff!) variable Roddenberry 1946 # Integer ranges variable MINWIDE -9223372036854775808 variable MAXWIDE 9223372036854775807 # Day before Leap Day variable FEB_28 58 # Translation table to map Windows TZI onto cities, so that the Olson # rules can apply. In some cases the mapping is ambiguous, so it's wise # to specify $::env(TCL_TZ) rather than simply depending on the system # time zone. # The keys are long lists of values obtained from the time zone # information in the Registry. In order, the list elements are: # Bias StandardBias DaylightBias # StandardDate.wYear StandardDate.wMonth StandardDate.wDayOfWeek # StandardDate.wDay StandardDate.wHour StandardDate.wMinute # StandardDate.wSecond StandardDate.wMilliseconds # DaylightDate.wYear DaylightDate.wMonth DaylightDate.wDayOfWeek # DaylightDate.wDay DaylightDate.wHour DaylightDate.wMinute # DaylightDate.wSecond DaylightDate.wMilliseconds # The values are the names of time zones where those rules apply. There # is considerable ambiguity in certain zones; an attempt has been made to # make a reasonable guess, but this table needs to be taken with a grain # of salt. variable WinZoneInfo [dict create {*}{ {-43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Kwajalein {-39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Midway {-36000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Honolulu {-32400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Anchorage {-28800 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Los_Angeles {-28800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Tijuana {-25200 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Denver {-25200 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Chihuahua {-25200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Phoenix {-21600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Regina {-21600 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Chicago {-21600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Mexico_City {-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/New_York {-18000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Indianapolis {-14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Caracas {-14400 0 3600 0 3 6 2 23 59 59 999 0 10 6 2 23 59 59 999} :America/Santiago {-14400 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Manaus {-14400 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} :America/Halifax {-12600 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/St_Johns {-10800 0 3600 0 2 0 2 2 0 0 0 0 10 0 3 2 0 0 0} :America/Sao_Paulo {-10800 0 3600 0 10 0 5 2 0 0 0 0 4 0 1 2 0 0 0} :America/Godthab {-10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :America/Buenos_Aires {-10800 0 3600 0 2 0 5 2 0 0 0 0 11 0 1 2 0 0 0} :America/Bahia {-10800 0 3600 0 3 0 2 2 0 0 0 0 10 0 1 2 0 0 0} :America/Montevideo {-7200 0 3600 0 9 0 5 2 0 0 0 0 3 0 5 2 0 0 0} :America/Noronha {-3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Atlantic/Azores {-3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Atlantic/Cape_Verde {0 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :UTC {0 0 3600 0 10 0 5 2 0 0 0 0 3 0 5 1 0 0 0} :Europe/London {3600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Kinshasa {3600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :CET {7200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Africa/Harare {7200 0 3600 0 9 4 5 23 59 59 0 0 4 4 5 23 59 59 0} :Africa/Cairo {7200 0 3600 0 10 0 5 4 0 0 0 0 3 0 5 3 0 0 0} :Europe/Helsinki {7200 0 3600 0 9 0 3 2 0 0 0 0 3 5 5 2 0 0 0} :Asia/Jerusalem {7200 0 3600 0 9 0 5 1 0 0 0 0 3 0 5 0 0 0 0} :Europe/Bucharest {7200 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Europe/Athens {7200 0 3600 0 9 5 5 1 0 0 0 0 3 4 5 0 0 0 0} :Asia/Amman {7200 0 3600 0 10 6 5 23 59 59 999 0 3 0 5 0 0 0 0} :Asia/Beirut {7200 0 -3600 0 4 0 1 2 0 0 0 0 9 0 1 2 0 0 0} :Africa/Windhoek {10800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Riyadh {10800 0 3600 0 10 0 1 4 0 0 0 0 4 0 1 3 0 0 0} :Asia/Baghdad {10800 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Europe/Moscow {12600 0 3600 0 9 2 4 2 0 0 0 0 3 0 1 2 0 0 0} :Asia/Tehran {14400 0 3600 0 10 0 5 5 0 0 0 0 3 0 5 4 0 0 0} :Asia/Baku {14400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Muscat {14400 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Tbilisi {16200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Kabul {18000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Karachi {18000 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Yekaterinburg {19800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Calcutta {20700 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Katmandu {21600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Dhaka {21600 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Novosibirsk {23400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Rangoon {25200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Bangkok {25200 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Krasnoyarsk {28800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Chongqing {28800 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Irkutsk {32400 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Asia/Tokyo {32400 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Yakutsk {34200 0 3600 0 3 0 5 3 0 0 0 0 10 0 5 2 0 0 0} :Australia/Adelaide {34200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Australia/Darwin {36000 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Australia/Brisbane {36000 0 3600 0 10 0 5 3 0 0 0 0 3 0 5 2 0 0 0} :Asia/Vladivostok {36000 0 3600 0 3 0 5 3 0 0 0 0 10 0 1 2 0 0 0} :Australia/Hobart {36000 0 3600 0 3 0 5 3 0 0 0 0 10 0 5 2 0 0 0} :Australia/Sydney {39600 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Noumea {43200 0 3600 0 3 0 3 3 0 0 0 0 10 0 1 2 0 0 0} :Pacific/Auckland {43200 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Fiji {46800 0 3600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} :Pacific/Tongatapu }] # Groups of fields that specify the date, priorities, and code bursts that # determine Julian Day Number given those groups. The code in [clock # scan] will choose the highest priority (lowest numbered) set of fields # that determines the date. variable DateParseActions { { seconds } 0 {} { julianDay } 1 {} { era century yearOfCentury month dayOfMonth } 2 { dict set date year [expr { 100 * [dict get $date century] + [dict get $date yearOfCentury] }] set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \ $changeover] } { era century yearOfCentury dayOfYear } 2 { dict set date year [expr { 100 * [dict get $date century] + [dict get $date yearOfCentury] }] set date [GetJulianDayFromEraYearDay $date[set date {}] \ $changeover] } { century yearOfCentury month dayOfMonth } 3 { dict set date era CE dict set date year [expr { 100 * [dict get $date century] + [dict get $date yearOfCentury] }] set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \ $changeover] } { century yearOfCentury dayOfYear } 3 { dict set date era CE dict set date year [expr { 100 * [dict get $date century] + [dict get $date yearOfCentury] }] set date [GetJulianDayFromEraYearDay $date[set date {}] \ $changeover] } { iso8601Century iso8601YearOfCentury iso8601Week dayOfWeek } 3 { dict set date era CE dict set date iso8601Year \ [expr { 100 * [dict get $date iso8601Century] + [dict get $date iso8601YearOfCentury] }] set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \ $changeover] } { yearOfCentury month dayOfMonth } 4 { set date [InterpretTwoDigitYear $date[set date {}] $baseTime] dict set date era CE set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \ $changeover] } { yearOfCentury dayOfYear } 4 { set date [InterpretTwoDigitYear $date[set date {}] $baseTime] dict set date era CE set date [GetJulianDayFromEraYearDay $date[set date {}] \ $changeover] } { iso8601YearOfCentury iso8601Week dayOfWeek } 4 { set date [InterpretTwoDigitYear \ $date[set date {}] $baseTime \ iso8601YearOfCentury iso8601Year] dict set date era CE set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \ $changeover] } { month dayOfMonth } 5 { set date [AssignBaseYear $date[set date {}] \ $baseTime $timeZone $changeover] set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \ $changeover] } { dayOfYear } 5 { set date [AssignBaseYear $date[set date {}] \ $baseTime $timeZone $changeover] set date [GetJulianDayFromEraYearDay $date[set date {}] \ $changeover] } { iso8601Week dayOfWeek } 5 { set date [AssignBaseIso8601Year $date[set date {}] \ $baseTime $timeZone $changeover] set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \ $changeover] } { dayOfMonth } 6 { set date [AssignBaseMonth $date[set date {}] \ $baseTime $timeZone $changeover] set date [GetJulianDayFromEraYearMonthDay $date[set date {}] \ $changeover] } { dayOfWeek } 7 { set date [AssignBaseWeek $date[set date {}] \ $baseTime $timeZone $changeover] set date [GetJulianDayFromEraYearWeekDay $date[set date {}] \ $changeover] } {} 8 { set date [AssignBaseJulianDay $date[set date {}] \ $baseTime $timeZone $changeover] } } # Groups of fields that specify time of day, priorities, and code that # processes them variable TimeParseActions { seconds 1 {} { hourAMPM minute second amPmIndicator } 2 { dict set date secondOfDay [InterpretHMSP $date] } { hour minute second } 2 { dict set date secondOfDay [InterpretHMS $date] } { hourAMPM minute amPmIndicator } 3 { dict set date second 0 dict set date secondOfDay [InterpretHMSP $date] } { hour minute } 3 { dict set date second 0 dict set date secondOfDay [InterpretHMS $date] } { hourAMPM amPmIndicator } 4 { dict set date minute 0 dict set date second 0 dict set date secondOfDay [InterpretHMSP $date] } { hour } 4 { dict set date minute 0 dict set date second 0 dict set date secondOfDay [InterpretHMS $date] } { } 5 { dict set date secondOfDay 0 } } # Legacy time zones, used primarily for parsing RFC822 dates. variable LegacyTimeZone [dict create \ gmt +0000 \ ut +0000 \ utc +0000 \ bst +0100 \ wet +0000 \ wat -0100 \ at -0200 \ nft -0330 \ nst -0330 \ ndt -0230 \ ast -0400 \ adt -0300 \ est -0500 \ edt -0400 \ cst -0600 \ cdt -0500 \ mst -0700 \ mdt -0600 \ pst -0800 \ pdt -0700 \ yst -0900 \ ydt -0800 \ hst -1000 \ hdt -0900 \ cat -1000 \ ahst -1000 \ nt -1100 \ idlw -1200 \ cet +0100 \ cest +0200 \ met +0100 \ mewt +0100 \ mest +0200 \ swt +0100 \ sst +0200 \ fwt +0100 \ fst +0200 \ eet +0200 \ eest +0300 \ bt +0300 \ it +0330 \ zp4 +0400 \ zp5 +0500 \ ist +0530 \ zp6 +0600 \ wast +0700 \ wadt +0800 \ jt +0730 \ cct +0800 \ jst +0900 \ kst +0900 \ cast +0930 \ jdt +1000 \ kdt +1000 \ cadt +1030 \ east +1000 \ eadt +1030 \ gst +1000 \ nzt +1200 \ nzst +1200 \ nzdt +1300 \ idle +1200 \ a +0100 \ b +0200 \ c +0300 \ d +0400 \ e +0500 \ f +0600 \ g +0700 \ h +0800 \ i +0900 \ k +1000 \ l +1100 \ m +1200 \ n -0100 \ o -0200 \ p -0300 \ q -0400 \ r -0500 \ s -0600 \ t -0700 \ u -0800 \ v -0900 \ w -1000 \ x -1100 \ y -1200 \ z +0000 \ ] # Caches variable LocaleNumeralCache {}; # Dictionary whose keys are locale # names and whose values are pairs # comprising regexes matching numerals # in the given locales and dictionaries # mapping the numerals to their numeric # values. # variable CachedSystemTimeZone; # If 'CachedSystemTimeZone' exists, # it contains the value of the # system time zone, as determined from # the environment. variable TimeZoneBad {}; # Dictionary whose keys are time zone # names and whose values are 1 if # the time zone is unknown and 0 # if it is known. variable TZData; # Array whose keys are time zone names # and whose values are lists of quads # comprising start time, UTC offset, # Daylight Saving Time indicator, and # time zone abbreviation. variable FormatProc; # Array mapping format group # and locale to the name of a procedure # that renders the given format } ::tcl::clock::Initialize #---------------------------------------------------------------------- # # clock format -- # # Formats a count of seconds since the Posix Epoch as a time of day. # # The 'clock format' command formats times of day for output. Refer to the # user documentation to see what it does. # #---------------------------------------------------------------------- proc ::tcl::clock::format { args } { variable FormatProc variable TZData lassign [ParseFormatArgs {*}$args] format locale timezone set locale [string tolower $locale] set clockval [lindex $args 0] # Get the data for time changes in the given zone if {$timezone eq ""} { set timezone [GetSystemTimeZone] } if {![info exists TZData($timezone)]} { if {[catch {SetupTimeZone $timezone} retval opts]} { dict unset opts -errorinfo return -options $opts $retval } } # Build a procedure to format the result. Cache the built procedure's name # in the 'FormatProc' array to avoid losing its internal representation, # which contains the name resolution. set procName formatproc'$format'$locale set procName [namespace current]::[string map {: {\:} \\ {\\}} $procName] if {[info exists FormatProc($procName)]} { set procName $FormatProc($procName) } else { set FormatProc($procName) \ [ParseClockFormatFormat $procName $format $locale] } return [$procName $clockval $timezone] } #---------------------------------------------------------------------- # # ParseClockFormatFormat -- # # Builds and caches a procedure that formats a time value. # # Parameters: # format -- Format string to use # locale -- Locale in which the format string is to be interpreted # # Results: # Returns the name of the newly-built procedure. # #---------------------------------------------------------------------- proc ::tcl::clock::ParseClockFormatFormat {procName format locale} { if {[namespace which $procName] ne {}} { return $procName } # Map away the locale-dependent composite format groups EnterLocale $locale # Change locale if a fresh locale has been given on the command line. try { return [ParseClockFormatFormat2 $format $locale $procName] } trap CLOCK {result opts} { dict unset opts -errorinfo return -options $opts $result } } proc ::tcl::clock::ParseClockFormatFormat2 {format locale procName} { set didLocaleEra 0 set didLocaleNumerals 0 set preFormatCode \ [string map [list @GREGORIAN_CHANGE_DATE@ \ [mc GREGORIAN_CHANGE_DATE]] \ { variable TZData set date [GetDateFields $clockval \ $TZData($timezone) \ @GREGORIAN_CHANGE_DATE@] }] set formatString {} set substituents {} set state {} set format [LocalizeFormat $locale $format] foreach char [split $format {}] { switch -exact -- $state { {} { if { [string equal % $char] } { set state percent } else { append formatString $char } } percent { # Character following a '%' character set state {} switch -exact -- $char { % { # A literal character, '%' append formatString %% } a { # Day of week, abbreviated append formatString %s append substituents \ [string map \ [list @DAYS_OF_WEEK_ABBREV@ \ [list [mc DAYS_OF_WEEK_ABBREV]]] \ { [lindex @DAYS_OF_WEEK_ABBREV@ \ [expr {[dict get $date dayOfWeek] \ % 7}]]}] } A { # Day of week, spelt out. append formatString %s append substituents \ [string map \ [list @DAYS_OF_WEEK_FULL@ \ [list [mc DAYS_OF_WEEK_FULL]]] \ { [lindex @DAYS_OF_WEEK_FULL@ \ [expr {[dict get $date dayOfWeek] \ % 7}]]}] } b - h { # Name of month, abbreviated. append formatString %s append substituents \ [string map \ [list @MONTHS_ABBREV@ \ [list [mc MONTHS_ABBREV]]] \ { [lindex @MONTHS_ABBREV@ \ [expr {[dict get $date month]-1}]]}] } B { # Name of month, spelt out append formatString %s append substituents \ [string map \ [list @MONTHS_FULL@ \ [list [mc MONTHS_FULL]]] \ { [lindex @MONTHS_FULL@ \ [expr {[dict get $date month]-1}]]}] } C { # Century number append formatString %02d append substituents \ { [expr {[dict get $date year] / 100}]} } d { # Day of month, with leading zero append formatString %02d append substituents { [dict get $date dayOfMonth]} } e { # Day of month, without leading zero append formatString %2d append substituents { [dict get $date dayOfMonth]} } E { # Format group in a locale-dependent # alternative era set state percentE if {!$didLocaleEra} { append preFormatCode \ [string map \ [list @LOCALE_ERAS@ \ [list [mc LOCALE_ERAS]]] \ { set date [GetLocaleEra \ $date[set date {}] \ @LOCALE_ERAS@]}] \n set didLocaleEra 1 } if {!$didLocaleNumerals} { append preFormatCode \ [list set localeNumerals \ [mc LOCALE_NUMERALS]] \n set didLocaleNumerals 1 } } g { # Two-digit year relative to ISO8601 # week number append formatString %02d append substituents \ { [expr { [dict get $date iso8601Year] % 100 }]} } G { # Four-digit year relative to ISO8601 # week number append formatString %02d append substituents { [dict get $date iso8601Year]} } H { # Hour in the 24-hour day, leading zero append formatString %02d append substituents \ { [expr { [dict get $date localSeconds] \ / 3600 % 24}]} } I { # Hour AM/PM, with leading zero append formatString %02d append substituents \ { [expr { ( ( ( [dict get $date localSeconds] \ % 86400 ) \ + 86400 \ - 3600 ) \ / 3600 ) \ % 12 + 1 }] } } j { # Day of year (001-366) append formatString %03d append substituents { [dict get $date dayOfYear]} } J { # Julian Day Number append formatString %07ld append substituents { [dict get $date julianDay]} } k { # Hour (0-23), no leading zero append formatString %2d append substituents \ { [expr { [dict get $date localSeconds] / 3600 % 24 }]} } l { # Hour (12-11), no leading zero append formatString %2d append substituents \ { [expr { ( ( ( [dict get $date localSeconds] % 86400 ) + 86400 - 3600 ) / 3600 ) % 12 + 1 }]} } m { # Month number, leading zero append formatString %02d append substituents { [dict get $date month]} } M { # Minute of the hour, leading zero append formatString %02d append substituents \ { [expr { [dict get $date localSeconds] / 60 % 60 }]} } n { # A literal newline append formatString \n } N { # Month number, no leading zero append formatString %2d append substituents { [dict get $date month]} } O { # A format group in the locale's # alternative numerals set state percentO if {!$didLocaleNumerals} { append preFormatCode \ [list set localeNumerals \ [mc LOCALE_NUMERALS]] \n set didLocaleNumerals 1 } } p { # Localized 'AM' or 'PM' indicator # converted to uppercase append formatString %s append preFormatCode \ [list set AM [string toupper [mc AM]]] \n \ [list set PM [string toupper [mc PM]]] \n append substituents \ { [expr {(([dict get $date localSeconds] % 86400) < 43200) ? $AM : $PM}]} } P { # Localized 'AM' or 'PM' indicator append formatString %s append preFormatCode \ [list set am [mc AM]] \n \ [list set pm [mc PM]] \n append substituents \ { [expr {(([dict get $date localSeconds] % 86400) < 43200) ? $am : $pm}]} } Q { # Hi, Jeff! append formatString %s append substituents { [FormatStarDate $date]} } s { # Seconds from the Posix Epoch append formatString %s append substituents { [dict get $date seconds]} } S { # Second of the minute, with # leading zero append formatString %02d append substituents \ { [expr { [dict get $date localSeconds] % 60 }]} } t { # A literal tab character append formatString \t } u { # Day of the week (1-Monday, 7-Sunday) append formatString %1d append substituents { [dict get $date dayOfWeek]} } U { # Week of the year (00-53). The # first Sunday of the year is the # first day of week 01 append formatString %02d append preFormatCode { set dow [dict get $date dayOfWeek] if { $dow == 7 } { set dow 0 } incr dow set UweekNumber \ [expr { ( [dict get $date dayOfYear] - $dow + 7 ) / 7 }] } append substituents { $UweekNumber} } V { # The ISO8601 week number append formatString %02d append substituents { [dict get $date iso8601Week]} } w { # Day of the week (0-Sunday, # 6-Saturday) append formatString %1d append substituents \ { [expr { [dict get $date dayOfWeek] % 7 }]} } W { # Week of the year (00-53). The first # Monday of the year is the first day # of week 01. append preFormatCode { set WweekNumber \ [expr { ( [dict get $date dayOfYear] - [dict get $date dayOfWeek] + 7 ) / 7 }] } append formatString %02d append substituents { $WweekNumber} } y { # The two-digit year of the century append formatString %02d append substituents \ { [expr { [dict get $date year] % 100 }]} } Y { # The four-digit year append formatString %04d append substituents { [dict get $date year]} } z { # The time zone as hours and minutes # east (+) or west (-) of Greenwich append formatString %s append substituents { [FormatNumericTimeZone \ [dict get $date tzOffset]]} } Z { # The name of the time zone append formatString %s append substituents { [dict get $date tzName]} } % { # A literal percent character append formatString %% } default { # An unknown escape sequence append formatString %% $char } } } percentE { # Character following %E set state {} switch -exact -- $char { E { append formatString %s append substituents { } \ [string map \ [list @BCE@ [list [mc BCE]] \ @CE@ [list [mc CE]]] \ {[dict get {BCE @BCE@ CE @CE@} \ [dict get $date era]]}] } C { # Locale-dependent era append formatString %s append substituents { [dict get $date localeEra]} } y { # Locale-dependent year of the era append preFormatCode { set y [dict get $date localeYear] if { $y >= 0 && $y < 100 } { set Eyear [lindex $localeNumerals $y] } else { set Eyear $y } } append formatString %s append substituents { $Eyear} } default { # Unknown %E format group append formatString %%E $char } } } percentO { # Character following %O set state {} switch -exact -- $char { d - e { # Day of the month in alternative # numerals append formatString %s append substituents \ { [lindex $localeNumerals \ [dict get $date dayOfMonth]]} } H - k { # Hour of the day in alternative # numerals append formatString %s append substituents \ { [lindex $localeNumerals \ [expr { [dict get $date localSeconds] / 3600 % 24 }]]} } I - l { # Hour (12-11) AM/PM in alternative # numerals append formatString %s append substituents \ { [lindex $localeNumerals \ [expr { ( ( ( [dict get $date localSeconds] % 86400 ) + 86400 - 3600 ) / 3600 ) % 12 + 1 }]]} } m { # Month number in alternative numerals append formatString %s append substituents \ { [lindex $localeNumerals [dict get $date month]]} } M { # Minute of the hour in alternative # numerals append formatString %s append substituents \ { [lindex $localeNumerals \ [expr { [dict get $date localSeconds] / 60 % 60 }]]} } S { # Second of the minute in alternative # numerals append formatString %s append substituents \ { [lindex $localeNumerals \ [expr { [dict get $date localSeconds] % 60 }]]} } u { # Day of the week (Monday=1,Sunday=7) # in alternative numerals append formatString %s append substituents \ { [lindex $localeNumerals \ [dict get $date dayOfWeek]]} } w { # Day of the week (Sunday=0,Saturday=6) # in alternative numerals append formatString %s append substituents \ { [lindex $localeNumerals \ [expr { [dict get $date dayOfWeek] % 7 }]]} } y { # Year of the century in alternative # numerals append formatString %s append substituents \ { [lindex $localeNumerals \ [expr { [dict get $date year] % 100 }]]} } default { # Unknown format group append formatString %%O $char } } } } } # Clean up any improperly terminated groups switch -exact -- $state { percent { append formatString %% } percentE { append retval %%E } percentO { append retval %%O } } proc $procName {clockval timezone} " $preFormatCode return \[::format [list $formatString] $substituents\] " # puts [list $procName [info args $procName] [info body $procName]] return $procName } #---------------------------------------------------------------------- # # clock scan -- # # Inputs a count of seconds since the Posix Epoch as a time of day. # # The 'clock format' command scans times of day on input. Refer to the user # documentation to see what it does. # #---------------------------------------------------------------------- proc ::tcl::clock::scan { args } { set format {} # Check the count of args if { [llength $args] < 1 || [llength $args] % 2 != 1 } { set cmdName "clock scan" return -code error \ -errorcode [list CLOCK wrongNumArgs] \ "wrong \# args: should be\ \"$cmdName string\ ?-base seconds?\ ?-format string? ?-gmt boolean?\ ?-locale LOCALE? ?-timezone ZONE?\"" } # Set defaults set base [clock seconds] set string [lindex $args 0] set format {} set gmt 0 set locale c set timezone [GetSystemTimeZone] # Pick up command line options. foreach { flag value } [lreplace $args 0 0] { set saw($flag) {} switch -exact -- $flag { -b - -ba - -bas - -base { set base $value } -f - -fo - -for - -form - -forma - -format { set format $value } -g - -gm - -gmt { set gmt $value } -l - -lo - -loc - -loca - -local - -locale { set locale [string tolower $value] } -t - -ti - -tim - -time - -timez - -timezo - -timezon - -timezone { set timezone $value } default { return -code error \ -errorcode [list CLOCK badOption $flag] \ "bad option \"$flag\",\ must be -base, -format, -gmt, -locale or -timezone" } } } # Check options for validity if { [info exists saw(-gmt)] && [info exists saw(-timezone)] } { return -code error \ -errorcode [list CLOCK gmtWithTimezone] \ "cannot use -gmt and -timezone in same call" } if { [catch { expr { wide($base) } } result] } { return -code error "expected integer but got \"$base\"" } if { ![string is boolean -strict $gmt] } { return -code error "expected boolean value but got \"$gmt\"" } elseif { $gmt } { set timezone :GMT } if { ![info exists saw(-format)] } { # Perhaps someday we'll localize the legacy code. Right now, it's not # localized. if { [info exists saw(-locale)] } { return -code error \ -errorcode [list CLOCK flagWithLegacyFormat] \ "legacy \[clock scan\] does not support -locale" } return [FreeScan $string $base $timezone $locale] } # Change locale if a fresh locale has been given on the command line. EnterLocale $locale try { # Map away the locale-dependent composite format groups set scanner [ParseClockScanFormat $format $locale] return [$scanner $string $base $timezone] } trap CLOCK {result opts} { # Conceal location of generation of expected errors dict unset opts -errorinfo return -options $opts $result } } #---------------------------------------------------------------------- # # FreeScan -- # # Scans a time in free format # # Parameters: # string - String containing the time to scan # base - Base time, expressed in seconds from the Epoch # timezone - Default time zone in which the time will be expressed # locale - (Unused) Name of the locale where the time will be scanned. # # Results: # Returns the date and time extracted from the string in seconds from # the epoch # #---------------------------------------------------------------------- proc ::tcl::clock::FreeScan { string base timezone locale } { variable TZData # Get the data for time changes in the given zone try { SetupTimeZone $timezone } on error {retval opts} { dict unset opts -errorinfo return -options $opts $retval } # Extract year, month and day from the base time for the parser to use as # defaults set date [GetDateFields $base $TZData($timezone) 2361222] dict set date secondOfDay [expr { [dict get $date localSeconds] % 86400 }] # Parse the date. The parser will return a list comprising date, time, # time zone, relative month/day/seconds, relative weekday, ordinal month. try { set scanned [Oldscan $string \ [dict get $date year] \ [dict get $date month] \ [dict get $date dayOfMonth]] lassign $scanned \ parseDate parseTime parseZone parseRel \ parseWeekday parseOrdinalMonth } on error message { return -code error \ "unable to convert date-time string \"$string\": $message" } # If the caller supplied a date in the string, update the 'date' dict with # the value. If the caller didn't specify a time with the date, default to # midnight. if { [llength $parseDate] > 0 } { lassign $parseDate y m d if { $y < 100 } { if { $y >= 39 } { incr y 1900 } else { incr y 2000 } } dict set date era CE dict set date year $y dict set date month $m dict set date dayOfMonth $d if { $parseTime eq {} } { set parseTime 0 } } # If the caller supplied a time zone in the string, it comes back as a # two-element list; the first element is the number of minutes east of # Greenwich, and the second is a Daylight Saving Time indicator (1 == yes, # 0 == no, -1 == unknown). We make it into a time zone indicator of # +-hhmm. if { [llength $parseZone] > 0 } { lassign $parseZone minEast dstFlag set timezone [FormatNumericTimeZone \ [expr { 60 * $minEast + 3600 * $dstFlag }]] SetupTimeZone $timezone } dict set date tzName $timezone # Assemble date, time, zone into seconds-from-epoch set date [GetJulianDayFromEraYearMonthDay $date[set date {}] 2361222] if { $parseTime ne {} } { dict set date secondOfDay $parseTime } elseif { [llength $parseWeekday] != 0 || [llength $parseOrdinalMonth] != 0 || ( [llength $parseRel] != 0 && ( [lindex $parseRel 0] != 0 || [lindex $parseRel 1] != 0 ) ) } { dict set date secondOfDay 0 } dict set date localSeconds [expr { -210866803200 + ( 86400 * wide([dict get $date julianDay]) ) + [dict get $date secondOfDay] }] dict set date tzName $timezone set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) 2361222] set seconds [dict get $date seconds] # Do relative times if { [llength $parseRel] > 0 } { lassign $parseRel relMonth relDay relSecond set seconds [add $seconds \ $relMonth months $relDay days $relSecond seconds \ -timezone $timezone -locale $locale] } # Do relative weekday if { [llength $parseWeekday] > 0 } { lassign $parseWeekday dayOrdinal dayOfWeek set date2 [GetDateFields $seconds $TZData($timezone) 2361222] dict set date2 era CE set jdwkday [WeekdayOnOrBefore $dayOfWeek [expr { [dict get $date2 julianDay] + 6 }]] incr jdwkday [expr { 7 * $dayOrdinal }] if { $dayOrdinal > 0 } { incr jdwkday -7 } dict set date2 secondOfDay \ [expr { [dict get $date2 localSeconds] % 86400 }] dict set date2 julianDay $jdwkday dict set date2 localSeconds [expr { -210866803200 + ( 86400 * wide([dict get $date2 julianDay]) ) + [dict get $date secondOfDay] }] dict set date2 tzName $timezone set date2 [ConvertLocalToUTC $date2[set date2 {}] $TZData($timezone) \ 2361222] set seconds [dict get $date2 seconds] } # Do relative month if { [llength $parseOrdinalMonth] > 0 } { lassign $parseOrdinalMonth monthOrdinal monthNumber if { $monthOrdinal > 0 } { set monthDiff [expr { $monthNumber - [dict get $date month] }] if { $monthDiff <= 0 } { incr monthDiff 12 } incr monthOrdinal -1 } else { set monthDiff [expr { [dict get $date month] - $monthNumber }] if { $monthDiff >= 0 } { incr monthDiff -12 } incr monthOrdinal } set seconds [add $seconds $monthOrdinal years $monthDiff months \ -timezone $timezone -locale $locale] } return $seconds } #---------------------------------------------------------------------- # # ParseClockScanFormat -- # # Parses a format string given to [clock scan -format] # # Parameters: # formatString - The format being parsed # locale - The current locale # # Results: # Constructs and returns a procedure that accepts the string being # scanned, the base time, and the time zone. The procedure will either # return the scanned time or else throw an error that should be rethrown # to the caller of [clock scan] # # Side effects: # The given procedure is defined in the ::tcl::clock namespace. Scan # procedures are not deleted once installed. # # Why do we parse dates by defining a procedure to parse them? The reason is # that by doing so, we have one convenient place to cache all the information: # the regular expressions that match the patterns (which will be compiled), # the code that assembles the date information, everything lands in one place. # In this way, when a given format is reused at run time, all the information # of how to apply it is available in a single place. # #---------------------------------------------------------------------- proc ::tcl::clock::ParseClockScanFormat {formatString locale} { # Check whether the format has been parsed previously, and return the # existing recognizer if it has. set procName scanproc'$formatString'$locale set procName [namespace current]::[string map {: {\:} \\ {\\}} $procName] if { [namespace which $procName] != {} } { return $procName } variable DateParseActions variable TimeParseActions # Localize the %x, %X, etc. groups set formatString [LocalizeFormat $locale $formatString] # Condense whitespace regsub -all {[[:space:]]+} $formatString { } formatString # Walk through the groups of the format string. In this loop, we # accumulate: # - a regular expression that matches the string, # - the count of capturing brackets in the regexp # - a set of code that post-processes the fields captured by the regexp, # - a dictionary whose keys are the names of fields that are present # in the format string. set re {^[[:space:]]*} set captureCount 0 set postcode {} set fieldSet [dict create] set fieldCount 0 set postSep {} set state {} foreach c [split $formatString {}] { switch -exact -- $state { {} { if { $c eq "%" } { set state % } elseif { $c eq " " } { append re {[[:space:]]+} } else { if { ! [string is alnum $c] } { append re "\\" } append re $c } } % { set state {} switch -exact -- $c { % { append re % } { } { append re "\[\[:space:\]\]*" } a - A { # Day of week, in words set l {} foreach \ i {7 1 2 3 4 5 6} \ abr [mc DAYS_OF_WEEK_ABBREV] \ full [mc DAYS_OF_WEEK_FULL] { dict set l [string tolower $abr] $i dict set l [string tolower $full] $i incr i } lassign [UniquePrefixRegexp $l] regex lookup append re ( $regex ) dict set fieldSet dayOfWeek [incr fieldCount] append postcode "dict set date dayOfWeek \[" \ "dict get " [list $lookup] " " \ \[ {string tolower $field} [incr captureCount] \] \ "\]\n" } b - B - h { # Name of month set i 0 set l {} foreach \ abr [mc MONTHS_ABBREV] \ full [mc MONTHS_FULL] { incr i dict set l [string tolower $abr] $i dict set l [string tolower $full] $i } lassign [UniquePrefixRegexp $l] regex lookup append re ( $regex ) dict set fieldSet month [incr fieldCount] append postcode "dict set date month \[" \ "dict get " [list $lookup] \ " " \[ {string tolower $field} \ [incr captureCount] \] \ "\]\n" } C { # Gregorian century append re \\s*(\\d\\d?) dict set fieldSet century [incr fieldCount] append postcode "dict set date century \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } d - e { # Day of month append re \\s*(\\d\\d?) dict set fieldSet dayOfMonth [incr fieldCount] append postcode "dict set date dayOfMonth \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } E { # Prefix for locale-specific codes set state %E } g { # ISO8601 2-digit year append re \\s*(\\d\\d) dict set fieldSet iso8601YearOfCentury \ [incr fieldCount] append postcode \ "dict set date iso8601YearOfCentury \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } G { # ISO8601 4-digit year append re \\s*(\\d\\d)(\\d\\d) dict set fieldSet iso8601Century [incr fieldCount] dict set fieldSet iso8601YearOfCentury \ [incr fieldCount] append postcode \ "dict set date iso8601Century \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" \ "dict set date iso8601YearOfCentury \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } H - k { # Hour of day append re \\s*(\\d\\d?) dict set fieldSet hour [incr fieldCount] append postcode "dict set date hour \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } I - l { # Hour, AM/PM append re \\s*(\\d\\d?) dict set fieldSet hourAMPM [incr fieldCount] append postcode "dict set date hourAMPM \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } j { # Day of year append re \\s*(\\d\\d?\\d?) dict set fieldSet dayOfYear [incr fieldCount] append postcode "dict set date dayOfYear \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } J { # Julian Day Number append re \\s*(\\d+) dict set fieldSet julianDay [incr fieldCount] append postcode "dict set date julianDay \[" \ "::scan \$field" [incr captureCount] " %ld" \ "\]\n" } m - N { # Month number append re \\s*(\\d\\d?) dict set fieldSet month [incr fieldCount] append postcode "dict set date month \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } M { # Minute append re \\s*(\\d\\d?) dict set fieldSet minute [incr fieldCount] append postcode "dict set date minute \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } n { # Literal newline append re \\n } O { # Prefix for locale numerics set state %O } p - P { # AM/PM indicator set l [list [string tolower [mc AM]] 0 \ [string tolower [mc PM]] 1] lassign [UniquePrefixRegexp $l] regex lookup append re ( $regex ) dict set fieldSet amPmIndicator [incr fieldCount] append postcode "dict set date amPmIndicator \[" \ "dict get " [list $lookup] " \[string tolower " \ "\$field" \ [incr captureCount] \ "\]\]\n" } Q { # Hi, Jeff! append re {Stardate\s+([-+]?\d+)(\d\d\d)[.](\d)} incr captureCount dict set fieldSet seconds [incr fieldCount] append postcode {dict set date seconds } \[ \ {ParseStarDate $field} [incr captureCount] \ { $field} [incr captureCount] \ { $field} [incr captureCount] \ \] \n } s { # Seconds from Posix Epoch # This next case is insanely difficult, because it's # problematic to determine whether the field is # actually within the range of a wide integer. append re {\s*([-+]?\d+)} dict set fieldSet seconds [incr fieldCount] append postcode {dict set date seconds } \[ \ {ScanWide $field} [incr captureCount] \] \n } S { # Second append re \\s*(\\d\\d?) dict set fieldSet second [incr fieldCount] append postcode "dict set date second \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } t { # Literal tab character append re \\t } u - w { # Day number within week, 0 or 7 == Sun # 1=Mon, 6=Sat append re \\s*(\\d) dict set fieldSet dayOfWeek [incr fieldCount] append postcode {::scan $field} [incr captureCount] \ { %d dow} \n \ { if { $dow == 0 } { set dow 7 } elseif { $dow > 7 } { return -code error \ -errorcode [list CLOCK badDayOfWeek] \ "day of week is greater than 7" } dict set date dayOfWeek $dow } } U { # Week of year. The first Sunday of # the year is the first day of week # 01. No scan rule uses this group. append re \\s*\\d\\d? } V { # Week of ISO8601 year append re \\s*(\\d\\d?) dict set fieldSet iso8601Week [incr fieldCount] append postcode "dict set date iso8601Week \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } W { # Week of the year (00-53). The first # Monday of the year is the first day # of week 01. No scan rule uses this # group. append re \\s*\\d\\d? } y { # Two-digit Gregorian year append re \\s*(\\d\\d?) dict set fieldSet yearOfCentury [incr fieldCount] append postcode "dict set date yearOfCentury \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } Y { # 4-digit Gregorian year append re \\s*(\\d\\d)(\\d\\d) dict set fieldSet century [incr fieldCount] dict set fieldSet yearOfCentury [incr fieldCount] append postcode \ "dict set date century \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" \ "dict set date yearOfCentury \[" \ "::scan \$field" [incr captureCount] " %d" \ "\]\n" } z - Z { # Time zone name append re {(?:([-+]\d\d(?::?\d\d(?::?\d\d)?)?)|([[:alnum:]]{1,4}))} dict set fieldSet tzName [incr fieldCount] append postcode \ {if } \{ { $field} [incr captureCount] \ { ne "" } \} { } \{ \n \ {dict set date tzName $field} \ $captureCount \n \ \} { else } \{ \n \ {dict set date tzName } \[ \ {ConvertLegacyTimeZone $field} \ [incr captureCount] \] \n \ \} \n \ } % { # Literal percent character append re % } default { append re % if { ! [string is alnum $c] } { append re \\ } append re $c } } } %E { switch -exact -- $c { C { # Locale-dependent era set d {} foreach triple [mc LOCALE_ERAS] { lassign $triple t symbol year dict set d [string tolower $symbol] $year } lassign [UniquePrefixRegexp $d] regex lookup append re (?: $regex ) } E { set l {} dict set l [string tolower [mc BCE]] BCE dict set l [string tolower [mc CE]] CE dict set l b.c.e. BCE dict set l c.e. CE dict set l b.c. BCE dict set l a.d. CE lassign [UniquePrefixRegexp $l] regex lookup append re ( $regex ) dict set fieldSet era [incr fieldCount] append postcode "dict set date era \["\ "dict get " [list $lookup] \ { } \[ {string tolower $field} \ [incr captureCount] \] \ "\]\n" } y { # Locale-dependent year of the era lassign [LocaleNumeralMatcher $locale] regex lookup append re $regex incr captureCount } default { append re %E if { ! [string is alnum $c] } { append re \\ } append re $c } } set state {} } %O { switch -exact -- $c { d - e { lassign [LocaleNumeralMatcher $locale] regex lookup append re $regex dict set fieldSet dayOfMonth [incr fieldCount] append postcode "dict set date dayOfMonth \[" \ "dict get " [list $lookup] " \$field" \ [incr captureCount] \ "\]\n" } H - k { lassign [LocaleNumeralMatcher $locale] regex lookup append re $regex dict set fieldSet hour [incr fieldCount] append postcode "dict set date hour \[" \ "dict get " [list $lookup] " \$field" \ [incr captureCount] \ "\]\n" } I - l { lassign [LocaleNumeralMatcher $locale] regex lookup append re $regex dict set fieldSet hourAMPM [incr fieldCount] append postcode "dict set date hourAMPM \[" \ "dict get " [list $lookup] " \$field" \ [incr captureCount] \ "\]\n" } m { lassign [LocaleNumeralMatcher $locale] regex lookup append re $regex dict set fieldSet month [incr fieldCount] append postcode "dict set date month \[" \ "dict get " [list $lookup] " \$field" \ [incr captureCount] \ "\]\n" } M { lassign [LocaleNumeralMatcher $locale] regex lookup append re $regex dict set fieldSet minute [incr fieldCount] append postcode "dict set date minute \[" \ "dict get " [list $lookup] " \$field" \ [incr captureCount] \ "\]\n" } S { lassign [LocaleNumeralMatcher $locale] regex lookup append re $regex dict set fieldSet second [incr fieldCount] append postcode "dict set date second \[" \ "dict get " [list $lookup] " \$field" \ [incr captureCount] \ "\]\n" } u - w { lassign [LocaleNumeralMatcher $locale] regex lookup append re $regex dict set fieldSet dayOfWeek [incr fieldCount] append postcode "set dow \[dict get " [list $lookup] \ { $field} [incr captureCount] \] \n \ { if { $dow == 0 } { set dow 7 } elseif { $dow > 7 } { return -code error \ -errorcode [list CLOCK badDayOfWeek] \ "day of week is greater than 7" } dict set date dayOfWeek $dow } } y { lassign [LocaleNumeralMatcher $locale] regex lookup append re $regex dict set fieldSet yearOfCentury [incr fieldCount] append postcode {dict set date yearOfCentury } \[ \ {dict get } [list $lookup] { $field} \ [incr captureCount] \] \n } default { append re %O if { ! [string is alnum $c] } { append re \\ } append re $c } } set state {} } } } # Clean up any unfinished format groups append re $state \\s*\$ # Build the procedure set procBody {} append procBody "variable ::tcl::clock::TZData" \n append procBody "if \{ !\[ regexp -nocase [list $re] \$string ->" for { set i 1 } { $i <= $captureCount } { incr i } { append procBody " " field $i } append procBody "\] \} \{" \n append procBody { return -code error -errorcode [list CLOCK badInputString] \ {input string does not match supplied format} } append procBody \}\n append procBody "set date \[dict create\]" \n append procBody {dict set date tzName $timeZone} \n append procBody $postcode append procBody [list set changeover [mc GREGORIAN_CHANGE_DATE]] \n # Set up the time zone before doing anything with a default base date # that might need a timezone to interpret it. if { ![dict exists $fieldSet seconds] && ![dict exists $fieldSet starDate] } { if { [dict exists $fieldSet tzName] } { append procBody { set timeZone [dict get $date tzName] } } append procBody { ::tcl::clock::SetupTimeZone $timeZone } } # Add code that gets Julian Day Number from the fields. append procBody [MakeParseCodeFromFields $fieldSet $DateParseActions] # Get time of day append procBody [MakeParseCodeFromFields $fieldSet $TimeParseActions] # Assemble seconds from the Julian day and second of the day. # Convert to local time unless epoch seconds or stardate are # being processed - they're always absolute if { ![dict exists $fieldSet seconds] && ![dict exists $fieldSet starDate] } { append procBody { if { [dict get $date julianDay] > 5373484 } { return -code error -errorcode [list CLOCK dateTooLarge] \ "requested date too large to represent" } dict set date localSeconds [expr { -210866803200 + ( 86400 * wide([dict get $date julianDay]) ) + [dict get $date secondOfDay] }] } # Finally, convert the date to local time append procBody { set date [::tcl::clock::ConvertLocalToUTC $date[set date {}] \ $TZData($timeZone) $changeover] } } # Return result append procBody {return [dict get $date seconds]} \n proc $procName { string baseTime timeZone } $procBody # puts [list proc $procName [list string baseTime timeZone] $procBody] return $procName } #---------------------------------------------------------------------- # # LocaleNumeralMatcher -- # # Composes a regexp that captures the numerals in the given locale, and # a dictionary to map them to conventional numerals. # # Parameters: # locale - Name of the current locale # # Results: # Returns a two-element list comprising the regexp and the dictionary. # # Side effects: # Caches the result. # #---------------------------------------------------------------------- proc ::tcl::clock::LocaleNumeralMatcher {l} { variable LocaleNumeralCache if { ![dict exists $LocaleNumeralCache $l] } { set d {} set i 0 set sep \( foreach n [mc LOCALE_NUMERALS] { dict set d $n $i regsub -all {[^[:alnum:]]} $n \\\\& subex append re $sep $subex set sep | incr i } append re \) dict set LocaleNumeralCache $l [list $re $d] } return [dict get $LocaleNumeralCache $l] } #---------------------------------------------------------------------- # # UniquePrefixRegexp -- # # Composes a regexp that performs unique-prefix matching. The RE # matches one of a supplied set of strings, or any unique prefix # thereof. # # Parameters: # data - List of alternating match-strings and values. # Match-strings with distinct values are considered # distinct. # # Results: # Returns a two-element list. The first is a regexp that matches any # unique prefix of any of the strings. The second is a dictionary whose # keys are match values from the regexp and whose values are the # corresponding values from 'data'. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::UniquePrefixRegexp { data } { # The 'successors' dictionary will contain, for each string that is a # prefix of any key, all characters that may follow that prefix. The # 'prefixMapping' dictionary will have keys that are prefixes of keys and # values that correspond to the keys. set prefixMapping [dict create] set successors [dict create {} {}] # Walk the key-value pairs foreach { key value } $data { # Construct all prefixes of the key; set prefix {} foreach char [split $key {}] { set oldPrefix $prefix dict set successors $oldPrefix $char {} append prefix $char # Put the prefixes in the 'prefixMapping' and 'successors' # dictionaries dict lappend prefixMapping $prefix $value if { ![dict exists $successors $prefix] } { dict set successors $prefix {} } } } # Identify those prefixes that designate unique values, and those that are # the full keys set uniquePrefixMapping {} dict for { key valueList } $prefixMapping { if { [llength $valueList] == 1 } { dict set uniquePrefixMapping $key [lindex $valueList 0] } } foreach { key value } $data { dict set uniquePrefixMapping $key $value } # Construct the re. return [list \ [MakeUniquePrefixRegexp $successors $uniquePrefixMapping {}] \ $uniquePrefixMapping] } #---------------------------------------------------------------------- # # MakeUniquePrefixRegexp -- # # Service procedure for 'UniquePrefixRegexp' that constructs a regular # expresison that matches the unique prefixes. # # Parameters: # successors - Dictionary whose keys are all prefixes # of keys passed to 'UniquePrefixRegexp' and whose # values are dictionaries whose keys are the characters # that may follow those prefixes. # uniquePrefixMapping - Dictionary whose keys are the unique # prefixes and whose values are not examined. # prefixString - Current prefix being processed. # # Results: # Returns a constructed regular expression that matches the set of # unique prefixes beginning with the 'prefixString'. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::MakeUniquePrefixRegexp { successors uniquePrefixMapping prefixString } { # Get the characters that may follow the current prefix string set schars [lsort -ascii [dict keys [dict get $successors $prefixString]]] if { [llength $schars] == 0 } { return {} } # If there is more than one successor character, or if the current prefix # is a unique prefix, surround the generated re with non-capturing # parentheses. set re {} if { [dict exists $uniquePrefixMapping $prefixString] || [llength $schars] > 1 } then { append re "(?:" } # Generate a regexp that matches the successors. set sep "" foreach { c } $schars { set nextPrefix $prefixString$c regsub -all {[^[:alnum:]]} $c \\\\& rechar append re $sep $rechar \ [MakeUniquePrefixRegexp \ $successors $uniquePrefixMapping $nextPrefix] set sep | } # If the current prefix is a unique prefix, make all following text # optional. Otherwise, if there is more than one successor character, # close the non-capturing parentheses. if { [dict exists $uniquePrefixMapping $prefixString] } { append re ")?" } elseif { [llength $schars] > 1 } { append re ")" } return $re } #---------------------------------------------------------------------- # # MakeParseCodeFromFields -- # # Composes Tcl code to extract the Julian Day Number from a dictionary # containing date fields. # # Parameters: # dateFields -- Dictionary whose keys are fields of the date, # and whose values are the rightmost positions # at which those fields appear. # parseActions -- List of triples: field set, priority, and # code to emit. Smaller priorities are better, and # the list must be in ascending order by priority # # Results: # Returns a burst of code that extracts the day number from the given # date. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::MakeParseCodeFromFields { dateFields parseActions } { set currPrio 999 set currFieldPos [list] set currCodeBurst { error "in ::tcl::clock::MakeParseCodeFromFields: can't happen" } foreach { fieldSet prio parseAction } $parseActions { # If we've found an answer that's better than any that follow, quit # now. if { $prio > $currPrio } { break } # Accumulate the field positions that are used in the current field # grouping. set fieldPos [list] set ok true foreach field $fieldSet { if { ! [dict exists $dateFields $field] } { set ok 0 break } lappend fieldPos [dict get $dateFields $field] } # Quit if we don't have a complete set of fields if { !$ok } { continue } # Determine whether the current answer is better than the last. set fPos [lsort -integer -decreasing $fieldPos] if { $prio == $currPrio } { foreach currPos $currFieldPos newPos $fPos { if { ![string is integer $newPos] || ![string is integer $currPos] || $newPos > $currPos } then { break } if { $newPos < $currPos } { set ok 0 break } } } if { !$ok } { continue } # Remember the best possibility for extracting date information set currPrio $prio set currFieldPos $fPos set currCodeBurst $parseAction } return $currCodeBurst } #---------------------------------------------------------------------- # # EnterLocale -- # # Switch [mclocale] to a given locale if necessary # # Parameters: # locale -- Desired locale # # Results: # Returns the locale that was previously current. # # Side effects: # Does [mclocale]. If necessary, loades the designated locale's files. # #---------------------------------------------------------------------- proc ::tcl::clock::EnterLocale { locale } { if { $locale eq {system} } { if { $::tcl_platform(platform) ne {windows} } { # On a non-windows platform, the 'system' locale is the same as # the 'current' locale set locale current } else { # On a windows platform, the 'system' locale is adapted from the # 'current' locale by applying the date and time formats from the # Control Panel. First, load the 'current' locale if it's not yet # loaded mcpackagelocale set [mclocale] # Make a new locale string for the system locale, and get the # Control Panel information set locale [mclocale]_windows if { ! [mcpackagelocale present $locale] } { LoadWindowsDateTimeFormats $locale } } } if { $locale eq {current}} { set locale [mclocale] } # Eventually load the locale mcpackagelocale set $locale } #---------------------------------------------------------------------- # # LoadWindowsDateTimeFormats -- # # Load the date/time formats from the Control Panel in Windows and # convert them so that they're usable by Tcl. # # Parameters: # locale - Name of the locale in whose message catalog # the converted formats are to be stored. # # Results: # None. # # Side effects: # Updates the given message catalog with the locale strings. # # Presumes that on entry, [mclocale] is set to the current locale, so that # default strings can be obtained if the Registry query fails. # #---------------------------------------------------------------------- proc ::tcl::clock::LoadWindowsDateTimeFormats { locale } { # Bail out if we can't find the Registry variable NoRegistry if { [info exists NoRegistry] } return if { ![catch { registry get "HKEY_CURRENT_USER\\Control Panel\\International" \ sShortDate } string] } { set quote {} set datefmt {} foreach { unquoted quoted } [split $string '] { append datefmt $quote [string map { dddd %A ddd %a dd %d d %e MMMM %B MMM %b MM %m M %N yyyy %Y yy %y y %y gg {} } $unquoted] if { $quoted eq {} } { set quote ' } else { set quote $quoted } } ::msgcat::mcset $locale DATE_FORMAT $datefmt } if { ![catch { registry get "HKEY_CURRENT_USER\\Control Panel\\International" \ sLongDate } string] } { set quote {} set ldatefmt {} foreach { unquoted quoted } [split $string '] { append ldatefmt $quote [string map { dddd %A ddd %a dd %d d %e MMMM %B MMM %b MM %m M %N yyyy %Y yy %y y %y gg {} } $unquoted] if { $quoted eq {} } { set quote ' } else { set quote $quoted } } ::msgcat::mcset $locale LOCALE_DATE_FORMAT $ldatefmt } if { ![catch { registry get "HKEY_CURRENT_USER\\Control Panel\\International" \ sTimeFormat } string] } { set quote {} set timefmt {} foreach { unquoted quoted } [split $string '] { append timefmt $quote [string map { HH %H H %k hh %I h %l mm %M m %M ss %S s %S tt %p t %p } $unquoted] if { $quoted eq {} } { set quote ' } else { set quote $quoted } } ::msgcat::mcset $locale TIME_FORMAT $timefmt } catch { ::msgcat::mcset $locale DATE_TIME_FORMAT "$datefmt $timefmt" } catch { ::msgcat::mcset $locale LOCALE_DATE_TIME_FORMAT "$ldatefmt $timefmt" } return } #---------------------------------------------------------------------- # # LocalizeFormat -- # # Map away locale-dependent format groups in a clock format. # # Parameters: # locale -- Current [mclocale] locale, supplied to avoid # an extra call # format -- Format supplied to [clock scan] or [clock format] # # Results: # Returns the string with locale-dependent composite format groups # substituted out. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::LocalizeFormat { locale format } { # message catalog key to cache this format set key FORMAT_$format if { [::msgcat::mcexists -exactlocale -exactnamespace $key] } { return [mc $key] } # Handle locale-dependent format groups by mapping them out of the format # string. Note that the order of the [string map] operations is # significant because later formats can refer to later ones; for example # %c can refer to %X, which in turn can refer to %T. set list { %% %% %D %m/%d/%Y %+ {%a %b %e %H:%M:%S %Z %Y} } lappend list %EY [string map $list [mc LOCALE_YEAR_FORMAT]] lappend list %T [string map $list [mc TIME_FORMAT_24_SECS]] lappend list %R [string map $list [mc TIME_FORMAT_24]] lappend list %r [string map $list [mc TIME_FORMAT_12]] lappend list %X [string map $list [mc TIME_FORMAT]] lappend list %EX [string map $list [mc LOCALE_TIME_FORMAT]] lappend list %x [string map $list [mc DATE_FORMAT]] lappend list %Ex [string map $list [mc LOCALE_DATE_FORMAT]] lappend list %c [string map $list [mc DATE_TIME_FORMAT]] lappend list %Ec [string map $list [mc LOCALE_DATE_TIME_FORMAT]] set format [string map $list $format] ::msgcat::mcset $locale $key $format return $format } #---------------------------------------------------------------------- # # FormatNumericTimeZone -- # # Formats a time zone as +hhmmss # # Parameters: # z - Time zone in seconds east of Greenwich # # Results: # Returns the time zone formatted in a numeric form # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::FormatNumericTimeZone { z } { if { $z < 0 } { set z [expr { - $z }] set retval - } else { set retval + } append retval [::format %02d [expr { $z / 3600 }]] set z [expr { $z % 3600 }] append retval [::format %02d [expr { $z / 60 }]] set z [expr { $z % 60 }] if { $z != 0 } { append retval [::format %02d $z] } return $retval } #---------------------------------------------------------------------- # # FormatStarDate -- # # Formats a date as a StarDate. # # Parameters: # date - Dictionary containing 'year', 'dayOfYear', and # 'localSeconds' fields. # # Results: # Returns the given date formatted as a StarDate. # # Side effects: # None. # # Jeff Hobbs put this in to support an atrocious pun about Tcl being # "Enterprise ready." Now we're stuck with it. # #---------------------------------------------------------------------- proc ::tcl::clock::FormatStarDate { date } { variable Roddenberry # Get day of year, zero based set doy [expr { [dict get $date dayOfYear] - 1 }] # Determine whether the year is a leap year set lp [IsGregorianLeapYear $date] # Convert day of year to a fractional year if { $lp } { set fractYear [expr { 1000 * $doy / 366 }] } else { set fractYear [expr { 1000 * $doy / 365 }] } # Put together the StarDate return [::format "Stardate %02d%03d.%1d" \ [expr { [dict get $date year] - $Roddenberry }] \ $fractYear \ [expr { [dict get $date localSeconds] % 86400 / ( 86400 / 10 ) }]] } #---------------------------------------------------------------------- # # ParseStarDate -- # # Parses a StarDate # # Parameters: # year - Year from the Roddenberry epoch # fractYear - Fraction of a year specifiying the day of year. # fractDay - Fraction of a day # # Results: # Returns a count of seconds from the Posix epoch. # # Side effects: # None. # # Jeff Hobbs put this in to support an atrocious pun about Tcl being # "Enterprise ready." Now we're stuck with it. # #---------------------------------------------------------------------- proc ::tcl::clock::ParseStarDate { year fractYear fractDay } { variable Roddenberry # Build a tentative date from year and fraction. set date [dict create \ gregorian 1 \ era CE \ year [expr { $year + $Roddenberry }] \ dayOfYear [expr { $fractYear * 365 / 1000 + 1 }]] set date [GetJulianDayFromGregorianEraYearDay $date[set date {}]] # Determine whether the given year is a leap year set lp [IsGregorianLeapYear $date] # Reconvert the fractional year according to whether the given year is a # leap year if { $lp } { dict set date dayOfYear \ [expr { $fractYear * 366 / 1000 + 1 }] } else { dict set date dayOfYear \ [expr { $fractYear * 365 / 1000 + 1 }] } dict unset date julianDay dict unset date gregorian set date [GetJulianDayFromGregorianEraYearDay $date[set date {}]] return [expr { 86400 * [dict get $date julianDay] - 210866803200 + ( 86400 / 10 ) * $fractDay }] } #---------------------------------------------------------------------- # # ScanWide -- # # Scans a wide integer from an input # # Parameters: # str - String containing a decimal wide integer # # Results: # Returns the string as a pure wide integer. Throws an error if the # string is misformatted or out of range. # #---------------------------------------------------------------------- proc ::tcl::clock::ScanWide { str } { set count [::scan $str {%ld %c} result junk] if { $count != 1 } { return -code error -errorcode [list CLOCK notAnInteger $str] \ "\"$str\" is not an integer" } if { [incr result 0] != $str } { return -code error -errorcode [list CLOCK integervalueTooLarge] \ "integer value too large to represent" } return $result } #---------------------------------------------------------------------- # # InterpretTwoDigitYear -- # # Given a date that contains only the year of the century, determines # the target value of a two-digit year. # # Parameters: # date - Dictionary containing fields of the date. # baseTime - Base time relative to which the date is expressed. # twoDigitField - Name of the field that stores the two-digit year. # Default is 'yearOfCentury' # fourDigitField - Name of the field that will receive the four-digit # year. Default is 'year' # # Results: # Returns the dictionary augmented with the four-digit year, stored in # the given key. # # Side effects: # None. # # The current rule for interpreting a two-digit year is that the year shall be # between 1937 and 2037, thus staying within the range of a 32-bit signed # value for time. This rule may change to a sliding window in future # versions, so the 'baseTime' parameter (which is currently ignored) is # provided in the procedure signature. # #---------------------------------------------------------------------- proc ::tcl::clock::InterpretTwoDigitYear { date baseTime { twoDigitField yearOfCentury } { fourDigitField year } } { set yr [dict get $date $twoDigitField] if { $yr <= 37 } { dict set date $fourDigitField [expr { $yr + 2000 }] } else { dict set date $fourDigitField [expr { $yr + 1900 }] } return $date } #---------------------------------------------------------------------- # # AssignBaseYear -- # # Places the number of the current year into a dictionary. # # Parameters: # date - Dictionary value to update # baseTime - Base time from which to extract the year, expressed # in seconds from the Posix epoch # timezone - the time zone in which the date is being scanned # changeover - the Julian Day on which the Gregorian calendar # was adopted in the target locale. # # Results: # Returns the dictionary with the current year assigned. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::AssignBaseYear { date baseTime timezone changeover } { variable TZData # Find the Julian Day Number corresponding to the base time, and # find the Gregorian year corresponding to that Julian Day. set date2 [GetDateFields $baseTime $TZData($timezone) $changeover] # Store the converted year dict set date era [dict get $date2 era] dict set date year [dict get $date2 year] return $date } #---------------------------------------------------------------------- # # AssignBaseIso8601Year -- # # Determines the base year in the ISO8601 fiscal calendar. # # Parameters: # date - Dictionary containing the fields of the date that # is to be augmented with the base year. # baseTime - Base time expressed in seconds from the Posix epoch. # timeZone - Target time zone # changeover - Julian Day of adoption of the Gregorian calendar in # the target locale. # # Results: # Returns the given date with "iso8601Year" set to the # base year. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::AssignBaseIso8601Year {date baseTime timeZone changeover} { variable TZData # Find the Julian Day Number corresponding to the base time set date2 [GetDateFields $baseTime $TZData($timeZone) $changeover] # Calculate the ISO8601 date and transfer the year dict set date era CE dict set date iso8601Year [dict get $date2 iso8601Year] return $date } #---------------------------------------------------------------------- # # AssignBaseMonth -- # # Places the number of the current year and month into a # dictionary. # # Parameters: # date - Dictionary value to update # baseTime - Time from which the year and month are to be # obtained, expressed in seconds from the Posix epoch. # timezone - Name of the desired time zone # changeover - Julian Day on which the Gregorian calendar was adopted. # # Results: # Returns the dictionary with the base year and month assigned. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::AssignBaseMonth {date baseTime timezone changeover} { variable TZData # Find the year and month corresponding to the base time set date2 [GetDateFields $baseTime $TZData($timezone) $changeover] dict set date era [dict get $date2 era] dict set date year [dict get $date2 year] dict set date month [dict get $date2 month] return $date } #---------------------------------------------------------------------- # # AssignBaseWeek -- # # Determines the base year and week in the ISO8601 fiscal calendar. # # Parameters: # date - Dictionary containing the fields of the date that # is to be augmented with the base year and week. # baseTime - Base time expressed in seconds from the Posix epoch. # changeover - Julian Day on which the Gregorian calendar was adopted # in the target locale. # # Results: # Returns the given date with "iso8601Year" set to the # base year and "iso8601Week" to the week number. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::AssignBaseWeek {date baseTime timeZone changeover} { variable TZData # Find the Julian Day Number corresponding to the base time set date2 [GetDateFields $baseTime $TZData($timeZone) $changeover] # Calculate the ISO8601 date and transfer the year dict set date era CE dict set date iso8601Year [dict get $date2 iso8601Year] dict set date iso8601Week [dict get $date2 iso8601Week] return $date } #---------------------------------------------------------------------- # # AssignBaseJulianDay -- # # Determines the base day for a time-of-day conversion. # # Parameters: # date - Dictionary that is to get the base day # baseTime - Base time expressed in seconds from the Posix epoch # changeover - Julian day on which the Gregorian calendar was # adpoted in the target locale. # # Results: # Returns the given dictionary augmented with a 'julianDay' field # that contains the base day. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::AssignBaseJulianDay { date baseTime timeZone changeover } { variable TZData # Find the Julian Day Number corresponding to the base time set date2 [GetDateFields $baseTime $TZData($timeZone) $changeover] dict set date julianDay [dict get $date2 julianDay] return $date } #---------------------------------------------------------------------- # # InterpretHMSP -- # # Interprets a time in the form "hh:mm:ss am". # # Parameters: # date -- Dictionary containing "hourAMPM", "minute", "second" # and "amPmIndicator" fields. # # Results: # Returns the number of seconds from local midnight. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::InterpretHMSP { date } { set hr [dict get $date hourAMPM] if { $hr == 12 } { set hr 0 } if { [dict get $date amPmIndicator] } { incr hr 12 } dict set date hour $hr return [InterpretHMS $date[set date {}]] } #---------------------------------------------------------------------- # # InterpretHMS -- # # Interprets a 24-hour time "hh:mm:ss" # # Parameters: # date -- Dictionary containing the "hour", "minute" and "second" # fields. # # Results: # Returns the given dictionary augmented with a "secondOfDay" # field containing the number of seconds from local midnight. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::InterpretHMS { date } { return [expr { ( [dict get $date hour] * 60 + [dict get $date minute] ) * 60 + [dict get $date second] }] } #---------------------------------------------------------------------- # # GetSystemTimeZone -- # # Determines the system time zone, which is the default for the # 'clock' command if no other zone is supplied. # # Parameters: # None. # # Results: # Returns the system time zone. # # Side effects: # Stores the sustem time zone in the 'CachedSystemTimeZone' # variable, since determining it may be an expensive process. # #---------------------------------------------------------------------- proc ::tcl::clock::GetSystemTimeZone {} { variable CachedSystemTimeZone variable TimeZoneBad if {[set result [getenv TCL_TZ]] ne {}} { set timezone $result } elseif {[set result [getenv TZ]] ne {}} { set timezone $result } if {![info exists timezone]} { # Cache the time zone only if it was detected by one of the # expensive methods. if { [info exists CachedSystemTimeZone] } { set timezone $CachedSystemTimeZone } elseif { $::tcl_platform(platform) eq {windows} } { set timezone [GuessWindowsTimeZone] } elseif { [file exists /etc/localtime] && ![catch {ReadZoneinfoFile \ Tcl/Localtime /etc/localtime}] } { set timezone :Tcl/Localtime } else { set timezone :localtime } set CachedSystemTimeZone $timezone } if { ![dict exists $TimeZoneBad $timezone] } { dict set TimeZoneBad $timezone [catch {SetupTimeZone $timezone}] } if { [dict get $TimeZoneBad $timezone] } { return :localtime } else { return $timezone } } #---------------------------------------------------------------------- # # ConvertLegacyTimeZone -- # # Given an alphanumeric time zone identifier and the system time zone, # convert the alphanumeric identifier to an unambiguous time zone. # # Parameters: # tzname - Name of the time zone to convert # # Results: # Returns a time zone name corresponding to tzname, but in an # unambiguous form, generally +hhmm. # # This procedure is implemented primarily to allow the parsing of RFC822 # date/time strings. Processing a time zone name on input is not recommended # practice, because there is considerable room for ambiguity; for instance, is # BST Brazilian Standard Time, or British Summer Time? # #---------------------------------------------------------------------- proc ::tcl::clock::ConvertLegacyTimeZone { tzname } { variable LegacyTimeZone set tzname [string tolower $tzname] if { ![dict exists $LegacyTimeZone $tzname] } { return -code error -errorcode [list CLOCK badTZName $tzname] \ "time zone \"$tzname\" not found" } return [dict get $LegacyTimeZone $tzname] } #---------------------------------------------------------------------- # # SetupTimeZone -- # # Given the name or specification of a time zone, sets up its in-memory # data. # # Parameters: # tzname - Name of a time zone # # Results: # Unless the time zone is ':localtime', sets the TZData array to contain # the lookup table for local<->UTC conversion. Returns an error if the # time zone cannot be parsed. # #---------------------------------------------------------------------- proc ::tcl::clock::SetupTimeZone { timezone } { variable TZData if {! [info exists TZData($timezone)] } { variable MINWIDE if { $timezone eq {:localtime} } { # Nothing to do, we'll convert using the localtime function } elseif { [regexp {^([-+])(\d\d)(?::?(\d\d)(?::?(\d\d))?)?} $timezone \ -> s hh mm ss] } then { # Make a fixed offset ::scan $hh %d hh if { $mm eq {} } { set mm 0 } else { ::scan $mm %d mm } if { $ss eq {} } { set ss 0 } else { ::scan $ss %d ss } set offset [expr { ( $hh * 60 + $mm ) * 60 + $ss }] if { $s eq {-} } { set offset [expr { - $offset }] } set TZData($timezone) [list [list $MINWIDE $offset -1 $timezone]] } elseif { [string index $timezone 0] eq {:} } { # Convert using a time zone file if { [catch { LoadTimeZoneFile [string range $timezone 1 end] }] && [catch { LoadZoneinfoFile [string range $timezone 1 end] }] } then { return -code error \ -errorcode [list CLOCK badTimeZone $timezone] \ "time zone \"$timezone\" not found" } } elseif { ![catch {ParsePosixTimeZone $timezone} tzfields] } { # This looks like a POSIX time zone - try to process it if { [catch {ProcessPosixTimeZone $tzfields} data opts] } { if { [lindex [dict get $opts -errorcode] 0] eq {CLOCK} } { dict unset opts -errorinfo } return -options $opts $data } else { set TZData($timezone) $data } } else { # We couldn't parse this as a POSIX time zone. Try again with a # time zone file - this time without a colon if { [catch { LoadTimeZoneFile $timezone }] && [catch { LoadZoneinfoFile $timezone } - opts] } { dict unset opts -errorinfo return -options $opts "time zone $timezone not found" } set TZData($timezone) $TZData(:$timezone) } } return } #---------------------------------------------------------------------- # # GuessWindowsTimeZone -- # # Determines the system time zone on windows. # # Parameters: # None. # # Results: # Returns a time zone specifier that corresponds to the system time zone # information found in the Registry. # # Bugs: # Fixed dates for DST change are unimplemented at present, because no # time zone information supplied with Windows actually uses them! # # On a Windows system where neither $env(TCL_TZ) nor $env(TZ) is specified, # GuessWindowsTimeZone looks in the Registry for the system time zone # information. It then attempts to find an entry in WinZoneInfo for a time # zone that uses the same rules. If it finds one, it returns it; otherwise, # it constructs a Posix-style time zone string and returns that. # #---------------------------------------------------------------------- proc ::tcl::clock::GuessWindowsTimeZone {} { variable WinZoneInfo variable NoRegistry variable TimeZoneBad if { [info exists NoRegistry] } { return :localtime } # Dredge time zone information out of the registry if { [catch { set rpath HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\TimeZoneInformation set data [list \ [expr { -60 * [registry get $rpath Bias] }] \ [expr { -60 * [registry get $rpath StandardBias] }] \ [expr { -60 \ * [registry get $rpath DaylightBias] }]] set stdtzi [registry get $rpath StandardStart] foreach ind {0 2 14 4 6 8 10 12} { binary scan $stdtzi @${ind}s val lappend data $val } set daytzi [registry get $rpath DaylightStart] foreach ind {0 2 14 4 6 8 10 12} { binary scan $daytzi @${ind}s val lappend data $val } }] } { # Missing values in the Registry - bail out return :localtime } # Make up a Posix time zone specifier if we can't find one. Check here # that the tzdata file exists, in case we're running in an environment # (e.g. starpack) where tzdata is incomplete. (Bug 1237907) if { [dict exists $WinZoneInfo $data] } { set tzname [dict get $WinZoneInfo $data] if { ! [dict exists $TimeZoneBad $tzname] } { dict set TimeZoneBad $tzname [catch {SetupTimeZone $tzname}] } } else { set tzname {} } if { $tzname eq {} || [dict get $TimeZoneBad $tzname] } { lassign $data \ bias stdBias dstBias \ stdYear stdMonth stdDayOfWeek stdDayOfMonth \ stdHour stdMinute stdSecond stdMillisec \ dstYear dstMonth dstDayOfWeek dstDayOfMonth \ dstHour dstMinute dstSecond dstMillisec set stdDelta [expr { $bias + $stdBias }] set dstDelta [expr { $bias + $dstBias }] if { $stdDelta <= 0 } { set stdSignum + set stdDelta [expr { - $stdDelta }] set dispStdSignum - } else { set stdSignum - set dispStdSignum + } set hh [::format %02d [expr { $stdDelta / 3600 }]] set mm [::format %02d [expr { ($stdDelta / 60 ) % 60 }]] set ss [::format %02d [expr { $stdDelta % 60 }]] set tzname {} append tzname < $dispStdSignum $hh $mm > $stdSignum $hh : $mm : $ss if { $stdMonth >= 0 } { if { $dstDelta <= 0 } { set dstSignum + set dstDelta [expr { - $dstDelta }] set dispDstSignum - } else { set dstSignum - set dispDstSignum + } set hh [::format %02d [expr { $dstDelta / 3600 }]] set mm [::format %02d [expr { ($dstDelta / 60 ) % 60 }]] set ss [::format %02d [expr { $dstDelta % 60 }]] append tzname < $dispDstSignum $hh $mm > $dstSignum $hh : $mm : $ss if { $dstYear == 0 } { append tzname ,M $dstMonth . $dstDayOfMonth . $dstDayOfWeek } else { # I have not been able to find any locale on which Windows # converts time zone on a fixed day of the year, hence don't # know how to interpret the fields. If someone can inform me, # I'd be glad to code it up. For right now, we bail out in # such a case. return :localtime } append tzname / [::format %02d $dstHour] \ : [::format %02d $dstMinute] \ : [::format %02d $dstSecond] if { $stdYear == 0 } { append tzname ,M $stdMonth . $stdDayOfMonth . $stdDayOfWeek } else { # I have not been able to find any locale on which Windows # converts time zone on a fixed day of the year, hence don't # know how to interpret the fields. If someone can inform me, # I'd be glad to code it up. For right now, we bail out in # such a case. return :localtime } append tzname / [::format %02d $stdHour] \ : [::format %02d $stdMinute] \ : [::format %02d $stdSecond] } dict set WinZoneInfo $data $tzname } return [dict get $WinZoneInfo $data] } #---------------------------------------------------------------------- # # LoadTimeZoneFile -- # # Load the data file that specifies the conversion between a # given time zone and Greenwich. # # Parameters: # fileName -- Name of the file to load # # Results: # None. # # Side effects: # TZData(:fileName) contains the time zone data # #---------------------------------------------------------------------- proc ::tcl::clock::LoadTimeZoneFile { fileName } { variable DataDir variable TZData if { [info exists TZData($fileName)] } { return } # Since an unsafe interp uses the [clock] command in the master, this code # is security sensitive. Make sure that the path name cannot escape the # given directory. if { ![regexp {^[[.-.][:alpha:]_]+(?:/[[.-.][:alpha:]_]+)*$} $fileName] } { return -code error \ -errorcode [list CLOCK badTimeZone $:fileName] \ "time zone \":$fileName\" not valid" } try { source -encoding utf-8 [file join $DataDir $fileName] } on error {} { return -code error \ -errorcode [list CLOCK badTimeZone :$fileName] \ "time zone \":$fileName\" not found" } return } #---------------------------------------------------------------------- # # LoadZoneinfoFile -- # # Loads a binary time zone information file in Olson format. # # Parameters: # fileName - Relative path name of the file to load. # # Results: # Returns an empty result normally; returns an error if no Olson file # was found or the file was malformed in some way. # # Side effects: # TZData(:fileName) contains the time zone data # #---------------------------------------------------------------------- proc ::tcl::clock::LoadZoneinfoFile { fileName } { variable ZoneinfoPaths # Since an unsafe interp uses the [clock] command in the master, this code # is security sensitive. Make sure that the path name cannot escape the # given directory. if { ![regexp {^[[.-.][:alpha:]_]+(?:/[[.-.][:alpha:]_]+)*$} $fileName] } { return -code error \ -errorcode [list CLOCK badTimeZone $:fileName] \ "time zone \":$fileName\" not valid" } foreach d $ZoneinfoPaths { set fname [file join $d $fileName] if { [file readable $fname] && [file isfile $fname] } { break } unset fname } ReadZoneinfoFile $fileName $fname } #---------------------------------------------------------------------- # # ReadZoneinfoFile -- # # Loads a binary time zone information file in Olson format. # # Parameters: # fileName - Name of the time zone (relative path name of the # file). # fname - Absolute path name of the file. # # Results: # Returns an empty result normally; returns an error if no Olson file # was found or the file was malformed in some way. # # Side effects: # TZData(:fileName) contains the time zone data # #---------------------------------------------------------------------- proc ::tcl::clock::ReadZoneinfoFile {fileName fname} { variable MINWIDE variable TZData if { ![file exists $fname] } { return -code error "$fileName not found" } if { [file size $fname] > 262144 } { return -code error "$fileName too big" } # Suck in all the data from the file set f [open $fname r] fconfigure $f -translation binary set d [read $f] close $f # The file begins with a magic number, sixteen reserved bytes, and then # six 4-byte integers giving counts of fileds in the file. binary scan $d a4a1x15IIIIII \ magic version nIsGMT nIsStd nLeap nTime nType nChar set seek 44 set ilen 4 set iformat I if { $magic != {TZif} } { return -code error "$fileName not a time zone information file" } if { $nType > 255 } { return -code error "$fileName contains too many time types" } # Accept only Posix-style zoneinfo. Sorry, 'leaps' bigots. if { $nLeap != 0 } { return -code error "$fileName contains leap seconds" } # In a version 2 file, we use the second part of the file, which contains # 64-bit transition times. if {$version eq "2"} { set seek [expr { 44 + 5 * $nTime + 6 * $nType + 4 * $nLeap + $nIsStd + $nIsGMT + $nChar }] binary scan $d @${seek}a4a1x15IIIIII \ magic version nIsGMT nIsStd nLeap nTime nType nChar if {$magic ne {TZif}} { return -code error "seek address $seek miscomputed, magic = $magic" } set iformat W set ilen 8 incr seek 44 } # Next come ${nTime} transition times, followed by ${nTime} time type # codes. The type codes are unsigned 1-byte quantities. We insert an # arbitrary start time in front of the transitions. binary scan $d @${seek}${iformat}${nTime}c${nTime} times tempCodes incr seek [expr { ($ilen + 1) * $nTime }] set times [linsert $times 0 $MINWIDE] set codes {} foreach c $tempCodes { lappend codes [expr { $c & 0xff }] } set codes [linsert $codes 0 0] # Next come ${nType} time type descriptions, each of which has an offset # (seconds east of GMT), a DST indicator, and an index into the # abbreviation text. for { set i 0 } { $i < $nType } { incr i } { binary scan $d @${seek}Icc gmtOff isDst abbrInd lappend types [list $gmtOff $isDst $abbrInd] incr seek 6 } # Next come $nChar characters of time zone name abbreviations, which are # null-terminated. # We build them up into a dictionary indexed by character index, because # that's what's in the indices above. binary scan $d @${seek}a${nChar} abbrs incr seek ${nChar} set abbrList [split $abbrs \0] set i 0 set abbrevs {} foreach a $abbrList { for {set j 0} {$j <= [string length $a]} {incr j} { dict set abbrevs $i [string range $a $j end] incr i } } # Package up a list of tuples, each of which contains transition time, # seconds east of Greenwich, DST flag and time zone abbreviation. set r {} set lastTime $MINWIDE foreach t $times c $codes { if { $t < $lastTime } { return -code error "$fileName has times out of order" } set lastTime $t lassign [lindex $types $c] gmtoff isDst abbrInd set abbrev [dict get $abbrevs $abbrInd] lappend r [list $t $gmtoff $isDst $abbrev] } # In a version 2 file, there is also a POSIX-style time zone description # at the very end of the file. To get to it, skip over nLeap leap second # values (8 bytes each), # nIsStd standard/DST indicators and nIsGMT UTC/local indicators. if {$version eq {2}} { set seek [expr {$seek + 8 * $nLeap + $nIsStd + $nIsGMT + 1}] set last [string first \n $d $seek] set posix [string range $d $seek [expr {$last-1}]] if {[llength $posix] > 0} { set posixFields [ParsePosixTimeZone $posix] foreach tuple [ProcessPosixTimeZone $posixFields] { lassign $tuple t gmtoff isDst abbrev if {$t > $lastTime} { lappend r $tuple } } } } set TZData(:$fileName) $r return } #---------------------------------------------------------------------- # # ParsePosixTimeZone -- # # Parses the TZ environment variable in Posix form # # Parameters: # tz Time zone specifier to be interpreted # # Results: # Returns a dictionary whose values contain the various pieces of the # time zone specification. # # Side effects: # None. # # Errors: # Throws an error if the syntax of the time zone is incorrect. # # The following keys are present in the dictionary: # stdName - Name of the time zone when Daylight Saving Time # is not in effect. # stdSignum - Sign (+, -, or empty) of the offset from Greenwich # to the given (non-DST) time zone. + and the empty # string denote zones west of Greenwich, - denotes east # of Greenwich; this is contrary to the ISO convention # but follows Posix. # stdHours - Hours part of the offset from Greenwich to the given # (non-DST) time zone. # stdMinutes - Minutes part of the offset from Greenwich to the # given (non-DST) time zone. Empty denotes zero. # stdSeconds - Seconds part of the offset from Greenwich to the # given (non-DST) time zone. Empty denotes zero. # dstName - Name of the time zone when DST is in effect, or the # empty string if the time zone does not observe Daylight # Saving Time. # dstSignum, dstHours, dstMinutes, dstSeconds - # Fields corresponding to stdSignum, stdHours, stdMinutes, # stdSeconds for the Daylight Saving Time version of the # time zone. If dstHours is empty, it is presumed to be 1. # startDayOfYear - The ordinal number of the day of the year on which # Daylight Saving Time begins. If this field is # empty, then DST begins on a given month-week-day, # as below. # startJ - The letter J, or an empty string. If a J is present in # this field, then startDayOfYear does not count February 29 # even in leap years. # startMonth - The number of the month in which Daylight Saving Time # begins, supplied if startDayOfYear is empty. If both # startDayOfYear and startMonth are empty, then US rules # are presumed. # startWeekOfMonth - The number of the week in the month in which # Daylight Saving Time begins, in the range 1-5. # 5 denotes the last week of the month even in a # 4-week month. # startDayOfWeek - The number of the day of the week (Sunday=0, # Saturday=6) on which Daylight Saving Time begins. # startHours - The hours part of the time of day at which Daylight # Saving Time begins. An empty string is presumed to be 2. # startMinutes - The minutes part of the time of day at which DST begins. # An empty string is presumed zero. # startSeconds - The seconds part of the time of day at which DST begins. # An empty string is presumed zero. # endDayOfYear, endJ, endMonth, endWeekOfMonth, endDayOfWeek, # endHours, endMinutes, endSeconds - # Specify the end of DST in the same way that the start* fields # specify the beginning of DST. # # This procedure serves only to break the time specifier into fields. No # attempt is made to canonicalize the fields or supply default values. # #---------------------------------------------------------------------- proc ::tcl::clock::ParsePosixTimeZone { tz } { if {[regexp -expanded -nocase -- { ^ # 1 - Standard time zone name ([[:alpha:]]+ | <[-+[:alnum:]]+>) # 2 - Standard time zone offset, signum ([-+]?) # 3 - Standard time zone offset, hours ([[:digit:]]{1,2}) (?: # 4 - Standard time zone offset, minutes : ([[:digit:]]{1,2}) (?: # 5 - Standard time zone offset, seconds : ([[:digit:]]{1,2} ) )? )? (?: # 6 - DST time zone name ([[:alpha:]]+ | <[-+[:alnum:]]+>) (?: (?: # 7 - DST time zone offset, signum ([-+]?) # 8 - DST time zone offset, hours ([[:digit:]]{1,2}) (?: # 9 - DST time zone offset, minutes : ([[:digit:]]{1,2}) (?: # 10 - DST time zone offset, seconds : ([[:digit:]]{1,2}) )? )? )? (?: , (?: # 11 - Optional J in n and Jn form 12 - Day of year ( J ? ) ( [[:digit:]]+ ) | M # 13 - Month number 14 - Week of month 15 - Day of week ( [[:digit:]] + ) [.] ( [[:digit:]] + ) [.] ( [[:digit:]] + ) ) (?: # 16 - Start time of DST - hours / ( [[:digit:]]{1,2} ) (?: # 17 - Start time of DST - minutes : ( [[:digit:]]{1,2} ) (?: # 18 - Start time of DST - seconds : ( [[:digit:]]{1,2} ) )? )? )? , (?: # 19 - Optional J in n and Jn form 20 - Day of year ( J ? ) ( [[:digit:]]+ ) | M # 21 - Month number 22 - Week of month 23 - Day of week ( [[:digit:]] + ) [.] ( [[:digit:]] + ) [.] ( [[:digit:]] + ) ) (?: # 24 - End time of DST - hours / ( [[:digit:]]{1,2} ) (?: # 25 - End time of DST - minutes : ( [[:digit:]]{1,2} ) (?: # 26 - End time of DST - seconds : ( [[:digit:]]{1,2} ) )? )? )? )? )? )? $ } $tz -> x(stdName) x(stdSignum) x(stdHours) x(stdMinutes) x(stdSeconds) \ x(dstName) x(dstSignum) x(dstHours) x(dstMinutes) x(dstSeconds) \ x(startJ) x(startDayOfYear) \ x(startMonth) x(startWeekOfMonth) x(startDayOfWeek) \ x(startHours) x(startMinutes) x(startSeconds) \ x(endJ) x(endDayOfYear) \ x(endMonth) x(endWeekOfMonth) x(endDayOfWeek) \ x(endHours) x(endMinutes) x(endSeconds)] } { # it's a good timezone return [array get x] } return -code error\ -errorcode [list CLOCK badTimeZone $tz] \ "unable to parse time zone specification \"$tz\"" } #---------------------------------------------------------------------- # # ProcessPosixTimeZone -- # # Handle a Posix time zone after it's been broken out into fields. # # Parameters: # z - Dictionary returned from 'ParsePosixTimeZone' # # Results: # Returns time zone information for the 'TZData' array. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::ProcessPosixTimeZone { z } { variable MINWIDE variable TZData # Determine the standard time zone name and seconds east of Greenwich set stdName [dict get $z stdName] if { [string index $stdName 0] eq {<} } { set stdName [string range $stdName 1 end-1] } if { [dict get $z stdSignum] eq {-} } { set stdSignum +1 } else { set stdSignum -1 } set stdHours [lindex [::scan [dict get $z stdHours] %d] 0] if { [dict get $z stdMinutes] ne {} } { set stdMinutes [lindex [::scan [dict get $z stdMinutes] %d] 0] } else { set stdMinutes 0 } if { [dict get $z stdSeconds] ne {} } { set stdSeconds [lindex [::scan [dict get $z stdSeconds] %d] 0] } else { set stdSeconds 0 } set stdOffset [expr { (($stdHours * 60 + $stdMinutes) * 60 + $stdSeconds) * $stdSignum }] set data [list [list $MINWIDE $stdOffset 0 $stdName]] # If there's no daylight zone, we're done set dstName [dict get $z dstName] if { $dstName eq {} } { return $data } if { [string index $dstName 0] eq {<} } { set dstName [string range $dstName 1 end-1] } # Determine the daylight name if { [dict get $z dstSignum] eq {-} } { set dstSignum +1 } else { set dstSignum -1 } if { [dict get $z dstHours] eq {} } { set dstOffset [expr { 3600 + $stdOffset }] } else { set dstHours [lindex [::scan [dict get $z dstHours] %d] 0] if { [dict get $z dstMinutes] ne {} } { set dstMinutes [lindex [::scan [dict get $z dstMinutes] %d] 0] } else { set dstMinutes 0 } if { [dict get $z dstSeconds] ne {} } { set dstSeconds [lindex [::scan [dict get $z dstSeconds] %d] 0] } else { set dstSeconds 0 } set dstOffset [expr { (($dstHours*60 + $dstMinutes) * 60 + $dstSeconds) * $dstSignum }] } # Fill in defaults for European or US DST rules # US start time is the second Sunday in March # EU start time is the last Sunday in March # US end time is the first Sunday in November. # EU end time is the last Sunday in October if { [dict get $z startDayOfYear] eq {} && [dict get $z startMonth] eq {} } then { if {($stdSignum * $stdHours>=0) && ($stdSignum * $stdHours<=12)} { # EU dict set z startWeekOfMonth 5 if {$stdHours>2} { dict set z startHours 2 } else { dict set z startHours [expr {$stdHours+1}] } } else { # US dict set z startWeekOfMonth 2 dict set z startHours 2 } dict set z startMonth 3 dict set z startDayOfWeek 0 dict set z startMinutes 0 dict set z startSeconds 0 } if { [dict get $z endDayOfYear] eq {} && [dict get $z endMonth] eq {} } then { if {($stdSignum * $stdHours>=0) && ($stdSignum * $stdHours<=12)} { # EU dict set z endMonth 10 dict set z endWeekOfMonth 5 if {$stdHours>2} { dict set z endHours 3 } else { dict set z endHours [expr {$stdHours+2}] } } else { # US dict set z endMonth 11 dict set z endWeekOfMonth 1 dict set z endHours 2 } dict set z endDayOfWeek 0 dict set z endMinutes 0 dict set z endSeconds 0 } # Put DST in effect in all years from 1916 to 2099. for { set y 1916 } { $y < 2100 } { incr y } { set startTime [DeterminePosixDSTTime $z start $y] incr startTime [expr { - wide($stdOffset) }] set endTime [DeterminePosixDSTTime $z end $y] incr endTime [expr { - wide($dstOffset) }] if { $startTime < $endTime } { lappend data \ [list $startTime $dstOffset 1 $dstName] \ [list $endTime $stdOffset 0 $stdName] } else { lappend data \ [list $endTime $stdOffset 0 $stdName] \ [list $startTime $dstOffset 1 $dstName] } } return $data } #---------------------------------------------------------------------- # # DeterminePosixDSTTime -- # # Determines the time that Daylight Saving Time starts or ends from a # Posix time zone specification. # # Parameters: # z - Time zone data returned from ParsePosixTimeZone. # Missing fields are expected to be filled in with # default values. # bound - The word 'start' or 'end' # y - The year for which the transition time is to be determined. # # Results: # Returns the transition time as a count of seconds from the epoch. The # time is relative to the wall clock, not UTC. # #---------------------------------------------------------------------- proc ::tcl::clock::DeterminePosixDSTTime { z bound y } { variable FEB_28 # Determine the start or end day of DST set date [dict create era CE year $y] set doy [dict get $z ${bound}DayOfYear] if { $doy ne {} } { # Time was specified as a day of the year if { [dict get $z ${bound}J] ne {} && [IsGregorianLeapYear $y] && ( $doy > $FEB_28 ) } { incr doy } dict set date dayOfYear $doy set date [GetJulianDayFromEraYearDay $date[set date {}] 2361222] } else { # Time was specified as a day of the week within a month dict set date month [dict get $z ${bound}Month] dict set date dayOfWeek [dict get $z ${bound}DayOfWeek] set dowim [dict get $z ${bound}WeekOfMonth] if { $dowim >= 5 } { set dowim -1 } dict set date dayOfWeekInMonth $dowim set date [GetJulianDayFromEraYearMonthWeekDay $date[set date {}] 2361222] } set jd [dict get $date julianDay] set seconds [expr { wide($jd) * wide(86400) - wide(210866803200) }] set h [dict get $z ${bound}Hours] if { $h eq {} } { set h 2 } else { set h [lindex [::scan $h %d] 0] } set m [dict get $z ${bound}Minutes] if { $m eq {} } { set m 0 } else { set m [lindex [::scan $m %d] 0] } set s [dict get $z ${bound}Seconds] if { $s eq {} } { set s 0 } else { set s [lindex [::scan $s %d] 0] } set tod [expr { ( $h * 60 + $m ) * 60 + $s }] return [expr { $seconds + $tod }] } #---------------------------------------------------------------------- # # GetLocaleEra -- # # Given local time expressed in seconds from the Posix epoch, # determine localized era and year within the era. # # Parameters: # date - Dictionary that must contain the keys, 'localSeconds', # whose value is expressed as the appropriate local time; # and 'year', whose value is the Gregorian year. # etable - Value of the LOCALE_ERAS key in the message catalogue # for the target locale. # # Results: # Returns the dictionary, augmented with the keys, 'localeEra' and # 'localeYear'. # #---------------------------------------------------------------------- proc ::tcl::clock::GetLocaleEra { date etable } { set index [BSearch $etable [dict get $date localSeconds]] if { $index < 0} { dict set date localeEra \ [::format %02d [expr { [dict get $date year] / 100 }]] dict set date localeYear [expr { [dict get $date year] % 100 }] } else { dict set date localeEra [lindex $etable $index 1] dict set date localeYear [expr { [dict get $date year] - [lindex $etable $index 2] }] } return $date } #---------------------------------------------------------------------- # # GetJulianDayFromEraYearDay -- # # Given a year, month and day on the Gregorian calendar, determines # the Julian Day Number beginning at noon on that date. # # Parameters: # date -- A dictionary in which the 'era', 'year', and # 'dayOfYear' slots are populated. The calendar in use # is determined by the date itself relative to: # changeover -- Julian day on which the Gregorian calendar was # adopted in the current locale. # # Results: # Returns the given dictionary augmented with a 'julianDay' key whose # value is the desired Julian Day Number, and a 'gregorian' key that # specifies whether the calendar is Gregorian (1) or Julian (0). # # Side effects: # None. # # Bugs: # This code needs to be moved to the C layer. # #---------------------------------------------------------------------- proc ::tcl::clock::GetJulianDayFromEraYearDay {date changeover} { # Get absolute year number from the civil year switch -exact -- [dict get $date era] { BCE { set year [expr { 1 - [dict get $date year] }] } CE { set year [dict get $date year] } } set ym1 [expr { $year - 1 }] # Try the Gregorian calendar first. dict set date gregorian 1 set jd [expr { 1721425 + [dict get $date dayOfYear] + ( 365 * $ym1 ) + ( $ym1 / 4 ) - ( $ym1 / 100 ) + ( $ym1 / 400 ) }] # If the date is before the Gregorian change, use the Julian calendar. if { $jd < $changeover } { dict set date gregorian 0 set jd [expr { 1721423 + [dict get $date dayOfYear] + ( 365 * $ym1 ) + ( $ym1 / 4 ) }] } dict set date julianDay $jd return $date } #---------------------------------------------------------------------- # # GetJulianDayFromEraYearMonthWeekDay -- # # Determines the Julian Day number corresponding to the nth given # day-of-the-week in a given month. # # Parameters: # date - Dictionary containing the keys, 'era', 'year', 'month' # 'weekOfMonth', 'dayOfWeek', and 'dayOfWeekInMonth'. # changeover - Julian Day of adoption of the Gregorian calendar # # Results: # Returns the given dictionary, augmented with a 'julianDay' key. # # Side effects: # None. # # Bugs: # This code needs to be moved to the C layer. # #---------------------------------------------------------------------- proc ::tcl::clock::GetJulianDayFromEraYearMonthWeekDay {date changeover} { # Come up with a reference day; either the zeroeth day of the given month # (dayOfWeekInMonth >= 0) or the seventh day of the following month # (dayOfWeekInMonth < 0) set date2 $date set week [dict get $date dayOfWeekInMonth] if { $week >= 0 } { dict set date2 dayOfMonth 0 } else { dict incr date2 month dict set date2 dayOfMonth 7 } set date2 [GetJulianDayFromEraYearMonthDay $date2[set date2 {}] \ $changeover] set wd0 [WeekdayOnOrBefore [dict get $date dayOfWeek] \ [dict get $date2 julianDay]] dict set date julianDay [expr { $wd0 + 7 * $week }] return $date } #---------------------------------------------------------------------- # # IsGregorianLeapYear -- # # Determines whether a given date represents a leap year in the # Gregorian calendar. # # Parameters: # date -- The date to test. The fields, 'era', 'year' and 'gregorian' # must be set. # # Results: # Returns 1 if the year is a leap year, 0 otherwise. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::IsGregorianLeapYear { date } { switch -exact -- [dict get $date era] { BCE { set year [expr { 1 - [dict get $date year]}] } CE { set year [dict get $date year] } } if { $year % 4 != 0 } { return 0 } elseif { ![dict get $date gregorian] } { return 1 } elseif { $year % 400 == 0 } { return 1 } elseif { $year % 100 == 0 } { return 0 } else { return 1 } } #---------------------------------------------------------------------- # # WeekdayOnOrBefore -- # # Determine the nearest day of week (given by the 'weekday' parameter, # Sunday==0) on or before a given Julian Day. # # Parameters: # weekday -- Day of the week # j -- Julian Day number # # Results: # Returns the Julian Day Number of the desired date. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::WeekdayOnOrBefore { weekday j } { set k [expr { ( $weekday + 6 ) % 7 }] return [expr { $j - ( $j - $k ) % 7 }] } #---------------------------------------------------------------------- # # BSearch -- # # Service procedure that does binary search in several places inside the # 'clock' command. # # Parameters: # list - List of lists, sorted in ascending order by the # first elements # key - Value to search for # # Results: # Returns the index of the greatest element in $list that is less than # or equal to $key. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::BSearch { list key } { if {[llength $list] == 0} { return -1 } if { $key < [lindex $list 0 0] } { return -1 } set l 0 set u [expr { [llength $list] - 1 }] while { $l < $u } { # At this point, we know that # $k >= [lindex $list $l 0] # Either $u == [llength $list] or else $k < [lindex $list $u+1 0] # We find the midpoint of the interval {l,u} rounded UP, compare # against it, and set l or u to maintain the invariant. Note that the # interval shrinks at each step, guaranteeing convergence. set m [expr { ( $l + $u + 1 ) / 2 }] if { $key >= [lindex $list $m 0] } { set l $m } else { set u [expr { $m - 1 }] } } return $l } #---------------------------------------------------------------------- # # clock add -- # # Adds an offset to a given time. # # Syntax: # clock add clockval ?count unit?... ?-option value? # # Parameters: # clockval -- Starting time value # count -- Amount of a unit of time to add # unit -- Unit of time to add, must be one of: # years year months month weeks week # days day hours hour minutes minute # seconds second # # Options: # -gmt BOOLEAN # (Deprecated) Flag synonymous with '-timezone :GMT' # -timezone ZONE # Name of the time zone in which calculations are to be done. # -locale NAME # Name of the locale in which calculations are to be done. # Used to determine the Gregorian change date. # # Results: # Returns the given time adjusted by the given offset(s) in # order. # # Notes: # It is possible that adding a number of months or years will adjust the # day of the month as well. For instance, the time at one month after # 31 January is either 28 or 29 February, because February has fewer # than 31 days. # #---------------------------------------------------------------------- proc ::tcl::clock::add { clockval args } { if { [llength $args] % 2 != 0 } { set cmdName "clock add" return -code error \ -errorcode [list CLOCK wrongNumArgs] \ "wrong \# args: should be\ \"$cmdName clockval ?number units?...\ ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?\"" } if { [catch { expr {wide($clockval)} } result] } { return -code error $result } set offsets {} set gmt 0 set locale c set timezone [GetSystemTimeZone] foreach { a b } $args { if { [string is integer -strict $a] } { lappend offsets $a $b } else { switch -exact -- $a { -g - -gm - -gmt { set gmt $b } -l - -lo - -loc - -loca - -local - -locale { set locale [string tolower $b] } -t - -ti - -tim - -time - -timez - -timezo - -timezon - -timezone { set timezone $b } default { throw [list CLOCK badOption $a] \ "bad option \"$a\",\ must be -gmt, -locale or -timezone" } } } } # Check options for validity if { [info exists saw(-gmt)] && [info exists saw(-timezone)] } { return -code error \ -errorcode [list CLOCK gmtWithTimezone] \ "cannot use -gmt and -timezone in same call" } if { [catch { expr { wide($clockval) } } result] } { return -code error "expected integer but got \"$clockval\"" } if { ![string is boolean -strict $gmt] } { return -code error "expected boolean value but got \"$gmt\"" } elseif { $gmt } { set timezone :GMT } EnterLocale $locale set changeover [mc GREGORIAN_CHANGE_DATE] if {[catch {SetupTimeZone $timezone} retval opts]} { dict unset opts -errorinfo return -options $opts $retval } try { foreach { quantity unit } $offsets { switch -exact -- $unit { years - year { set clockval [AddMonths [expr { 12 * $quantity }] \ $clockval $timezone $changeover] } months - month { set clockval [AddMonths $quantity $clockval $timezone \ $changeover] } weeks - week { set clockval [AddDays [expr { 7 * $quantity }] \ $clockval $timezone $changeover] } days - day { set clockval [AddDays $quantity $clockval $timezone \ $changeover] } hours - hour { set clockval [expr { 3600 * $quantity + $clockval }] } minutes - minute { set clockval [expr { 60 * $quantity + $clockval }] } seconds - second { set clockval [expr { $quantity + $clockval }] } default { throw [list CLOCK badUnit $unit] \ "unknown unit \"$unit\", must be \ years, months, weeks, days, hours, minutes or seconds" } } } return $clockval } trap CLOCK {result opts} { # Conceal the innards of [clock] when it's an expected error dict unset opts -errorinfo return -options $opts $result } } #---------------------------------------------------------------------- # # AddMonths -- # # Add a given number of months to a given clock value in a given # time zone. # # Parameters: # months - Number of months to add (may be negative) # clockval - Seconds since the epoch before the operation # timezone - Time zone in which the operation is to be performed # # Results: # Returns the new clock value as a number of seconds since # the epoch. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::AddMonths { months clockval timezone changeover } { variable DaysInRomanMonthInCommonYear variable DaysInRomanMonthInLeapYear variable TZData # Convert the time to year, month, day, and fraction of day. set date [GetDateFields $clockval $TZData($timezone) $changeover] dict set date secondOfDay [expr { [dict get $date localSeconds] % 86400 }] dict set date tzName $timezone # Add the requisite number of months set m [dict get $date month] incr m $months incr m -1 set delta [expr { $m / 12 }] set mm [expr { $m % 12 }] dict set date month [expr { $mm + 1 }] dict incr date year $delta # If the date doesn't exist in the current month, repair it if { [IsGregorianLeapYear $date] } { set hath [lindex $DaysInRomanMonthInLeapYear $mm] } else { set hath [lindex $DaysInRomanMonthInCommonYear $mm] } if { [dict get $date dayOfMonth] > $hath } { dict set date dayOfMonth $hath } # Reconvert to a number of seconds set date [GetJulianDayFromEraYearMonthDay \ $date[set date {}]\ $changeover] dict set date localSeconds [expr { -210866803200 + ( 86400 * wide([dict get $date julianDay]) ) + [dict get $date secondOfDay] }] set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) \ $changeover] return [dict get $date seconds] } #---------------------------------------------------------------------- # # AddDays -- # # Add a given number of days to a given clock value in a given time # zone. # # Parameters: # days - Number of days to add (may be negative) # clockval - Seconds since the epoch before the operation # timezone - Time zone in which the operation is to be performed # changeover - Julian Day on which the Gregorian calendar was adopted # in the target locale. # # Results: # Returns the new clock value as a number of seconds since the epoch. # # Side effects: # None. # #---------------------------------------------------------------------- proc ::tcl::clock::AddDays { days clockval timezone changeover } { variable TZData # Convert the time to Julian Day set date [GetDateFields $clockval $TZData($timezone) $changeover] dict set date secondOfDay [expr { [dict get $date localSeconds] % 86400 }] dict set date tzName $timezone # Add the requisite number of days dict incr date julianDay $days # Reconvert to a number of seconds dict set date localSeconds [expr { -210866803200 + ( 86400 * wide([dict get $date julianDay]) ) + [dict get $date secondOfDay] }] set date [ConvertLocalToUTC $date[set date {}] $TZData($timezone) \ $changeover] return [dict get $date seconds] } #---------------------------------------------------------------------- # # ChangeCurrentLocale -- # # The global locale was changed within msgcat. # Clears the buffered parse functions of the current locale. # # Parameters: # loclist (ignored) # # Results: # None. # # Side effects: # Buffered parse functions are cleared. # #---------------------------------------------------------------------- proc ::tcl::clock::ChangeCurrentLocale {args} { variable FormatProc variable LocaleNumeralCache variable CachedSystemTimeZone variable TimeZoneBad foreach p [info procs [namespace current]::scanproc'*'current] { rename $p {} } foreach p [info procs [namespace current]::formatproc'*'current] { rename $p {} } catch {array unset FormatProc *'current} set LocaleNumeralCache {} } #---------------------------------------------------------------------- # # ClearCaches -- # # Clears all caches to reclaim the memory used in [clock] # # Parameters: # None. # # Results: # None. # # Side effects: # Caches are cleared. # #---------------------------------------------------------------------- proc ::tcl::clock::ClearCaches {} { variable FormatProc variable LocaleNumeralCache variable CachedSystemTimeZone variable TimeZoneBad foreach p [info procs [namespace current]::scanproc'*] { rename $p {} } foreach p [info procs [namespace current]::formatproc'*] { rename $p {} } catch {unset FormatProc} set LocaleNumeralCache {} catch {unset CachedSystemTimeZone} set TimeZoneBad {} InitTZData } tcl8.6.5/library/word.tcl0000644000175000017500000001110212663660066014706 0ustar sergeisergei# word.tcl -- # # This file defines various procedures for computing word boundaries in # strings. This file is primarily needed so Tk text and entry widgets behave # properly for different platforms. # # Copyright (c) 1996 by Sun Microsystems, Inc. # Copyright (c) 1998 by Scritpics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # The following variables are used to determine which characters are # interpreted as white space. if {$::tcl_platform(platform) eq "windows"} { # Windows style - any but a unicode space char set ::tcl_wordchars {\S} set ::tcl_nonwordchars {\s} } else { # Motif style - any unicode word char (number, letter, or underscore) set ::tcl_wordchars {\w} set ::tcl_nonwordchars {\W} } # Arrange for caches of the real matcher REs to be kept, which enables the REs # themselves to be cached for greater performance (and somewhat greater # clarity too). namespace eval ::tcl { variable WordBreakRE array set WordBreakRE {} proc UpdateWordBreakREs args { # Ignores the arguments global tcl_wordchars tcl_nonwordchars variable WordBreakRE # To keep the RE strings short... set letter $tcl_wordchars set space $tcl_nonwordchars set WordBreakRE(after) "$letter$space|$space$letter" set WordBreakRE(before) "^.*($letter$space|$space$letter)" set WordBreakRE(end) "$space*$letter+$space" set WordBreakRE(next) "$letter*$space+$letter" set WordBreakRE(previous) "$space*($letter+)$space*\$" } # Initialize the cache UpdateWordBreakREs trace add variable ::tcl_wordchars write ::tcl::UpdateWordBreakREs trace add variable ::tcl_nonwordchars write ::tcl::UpdateWordBreakREs } # tcl_wordBreakAfter -- # # This procedure returns the index of the first word boundary after the # starting point in the given string, or -1 if there are no more boundaries in # the given string. The index returned refers to the first character of the # pair that comprises a boundary. # # Arguments: # str - String to search. # start - Index into string specifying starting point. proc tcl_wordBreakAfter {str start} { variable ::tcl::WordBreakRE set result {-1 -1} regexp -indices -start $start -- $WordBreakRE(after) $str result return [lindex $result 1] } # tcl_wordBreakBefore -- # # This procedure returns the index of the first word boundary before the # starting point in the given string, or -1 if there are no more boundaries in # the given string. The index returned refers to the second character of the # pair that comprises a boundary. # # Arguments: # str - String to search. # start - Index into string specifying starting point. proc tcl_wordBreakBefore {str start} { variable ::tcl::WordBreakRE set result {-1 -1} regexp -indices -- $WordBreakRE(before) [string range $str 0 $start] result return [lindex $result 1] } # tcl_endOfWord -- # # This procedure returns the index of the first end-of-word location after a # starting index in the given string. An end-of-word location is defined to be # the first whitespace character following the first non-whitespace character # after the starting point. Returns -1 if there are no more words after the # starting point. # # Arguments: # str - String to search. # start - Index into string specifying starting point. proc tcl_endOfWord {str start} { variable ::tcl::WordBreakRE set result {-1 -1} regexp -indices -start $start -- $WordBreakRE(end) $str result return [lindex $result 1] } # tcl_startOfNextWord -- # # This procedure returns the index of the first start-of-word location after a # starting index in the given string. A start-of-word location is defined to # be a non-whitespace character following a whitespace character. Returns -1 # if there are no more start-of-word locations after the starting point. # # Arguments: # str - String to search. # start - Index into string specifying starting point. proc tcl_startOfNextWord {str start} { variable ::tcl::WordBreakRE set result {-1 -1} regexp -indices -start $start -- $WordBreakRE(next) $str result return [lindex $result 1] } # tcl_startOfPreviousWord -- # # This procedure returns the index of the first start-of-word location before # a starting index in the given string. # # Arguments: # str - String to search. # start - Index into string specifying starting point. proc tcl_startOfPreviousWord {str start} { variable ::tcl::WordBreakRE set word {-1 -1} regexp -indices -- $WordBreakRE(previous) [string range $str 0 $start-1] \ result word return [lindex $word 0] } tcl8.6.5/library/dde/0000755000175000017500000000000012665173607013772 5ustar sergeisergeitcl8.6.5/library/dde/pkgIndex.tcl0000644000175000017500000000045112663660066016245 0ustar sergeisergeiif {([info commands ::tcl::pkgconfig] eq "") || ([info sharedlibextension] ne ".dll")} return if {[::tcl::pkgconfig get debug]} { package ifneeded dde 1.4.0 [list load [file join $dir tcldde14g.dll] dde] } else { package ifneeded dde 1.4.0 [list load [file join $dir tcldde14.dll] dde] } tcl8.6.5/library/platform/0000755000175000017500000000000012665173607015062 5ustar sergeisergeitcl8.6.5/library/platform/pkgIndex.tcl0000644000175000017500000000024512663660066017336 0ustar sergeisergeipackage ifneeded platform 1.0.14 [list source [file join $dir platform.tcl]] package ifneeded platform::shell 1.1.4 [list source [file join $dir shell.tcl]] tcl8.6.5/library/platform/platform.tcl0000644000175000017500000002343412663660066017416 0ustar sergeisergei# -*- tcl -*- # ### ### ### ######### ######### ######### ## Overview # Heuristics to assemble a platform identifier from publicly available # information. The identifier describes the platform of the currently # running tcl shell. This is a mixture of the runtime environment and # of build-time properties of the executable itself. # # Examples: # <1> A tcl shell executing on a x86_64 processor, but having a # wordsize of 4 was compiled for the x86 environment, i.e. 32 # bit, and loaded packages have to match that, and not the # actual cpu. # # <2> The hp/solaris 32/64 bit builds of the core cannot be # distinguished by looking at tcl_platform. As packages have to # match the 32/64 information we have to look in more places. In # this case we inspect the executable itself (magic numbers, # i.e. fileutil::magic::filetype). # # The basic information used comes out of the 'os' and 'machine' # entries of the 'tcl_platform' array. A number of general and # os/machine specific transformation are applied to get a canonical # result. # # General # Only the first element of 'os' is used - we don't care whether we # are on "Windows NT" or "Windows XP" or whatever. # # Machine specific # % arm* -> arm # % sun4* -> sparc # % intel -> ix86 # % i*86* -> ix86 # % Power* -> powerpc # % x86_64 + wordSize 4 => x86 code # # OS specific # % AIX are always powerpc machines # % HP-UX 9000/800 etc means parisc # % linux has to take glibc version into account # % sunos -> solaris, and keep version number # # NOTE: A platform like linux glibc 2.3, which can use glibc 2.2 stuff # has to provide all possible allowed platform identifiers when # searching search. Ditto a solaris 2.8 platform can use solaris 2.6 # packages. Etc. This is handled by the other procedure, see below. # ### ### ### ######### ######### ######### ## Requirements namespace eval ::platform {} # ### ### ### ######### ######### ######### ## Implementation # -- platform::generic # # Assembles an identifier for the generic platform. It leaves out # details like kernel version, libc version, etc. proc ::platform::generic {} { global tcl_platform set plat [string tolower [lindex $tcl_platform(os) 0]] set cpu $tcl_platform(machine) switch -glob -- $cpu { sun4* { set cpu sparc } intel - i*86* { set cpu ix86 } x86_64 { if {$tcl_platform(wordSize) == 4} { # See Example <1> at the top of this file. set cpu ix86 } } "Power*" { set cpu powerpc } "arm*" { set cpu arm } ia64 { if {$tcl_platform(wordSize) == 4} { append cpu _32 } } } switch -glob -- $plat { cygwin* { set plat cygwin } windows { if {$tcl_platform(platform) == "unix"} { set plat cygwin } else { set plat win32 } if {$cpu eq "amd64"} { # Do not check wordSize, win32-x64 is an IL32P64 platform. set cpu x86_64 } } sunos { set plat solaris if {[string match "ix86" $cpu]} { if {$tcl_platform(wordSize) == 8} { set cpu x86_64 } } elseif {![string match "ia64*" $cpu]} { # sparc if {$tcl_platform(wordSize) == 8} { append cpu 64 } } } darwin { set plat macosx # Correctly identify the cpu when running as a 64bit # process on a machine with a 32bit kernel if {$cpu eq "ix86"} { if {$tcl_platform(wordSize) == 8} { set cpu x86_64 } } } aix { set cpu powerpc if {$tcl_platform(wordSize) == 8} { append cpu 64 } } hp-ux { set plat hpux if {![string match "ia64*" $cpu]} { set cpu parisc if {$tcl_platform(wordSize) == 8} { append cpu 64 } } } osf1 { set plat tru64 } } return "${plat}-${cpu}" } # -- platform::identify # # Assembles an identifier for the exact platform, by extending the # generic identifier. I.e. it adds in details like kernel version, # libc version, etc., if they are relevant for the loading of # packages on the platform. proc ::platform::identify {} { global tcl_platform set id [generic] regexp {^([^-]+)-([^-]+)$} $id -> plat cpu switch -- $plat { solaris { regsub {^5} $tcl_platform(osVersion) 2 text append plat $text return "${plat}-${cpu}" } macosx { set major [lindex [split $tcl_platform(osVersion) .] 0] if {$major > 8} { incr major -4 append plat 10.$major return "${plat}-${cpu}" } } linux { # Look for the libc*.so and determine its version # (libc5/6, libc6 further glibc 2.X) set v unknown # Determine in which directory to look. /lib, or /lib64. # For that we use the tcl_platform(wordSize). # # We could use the 'cpu' info, per the equivalence below, # that however would be restricted to intel. And this may # be a arm, mips, etc. system. The wordsize is more # fundamental. # # ix86 <=> (wordSize == 4) <=> 32 bit ==> /lib # x86_64 <=> (wordSize == 8) <=> 64 bit ==> /lib64 # # Do not look into /lib64 even if present, if the cpu # doesn't fit. # TODO: Determine the prefixes (i386, x86_64, ...) for # other cpus. The path after the generic one is utterly # specific to intel right now. Ok, on Ubuntu, possibly # other Debian systems we may apparently be able to query # the necessary CPU code. If we can't we simply use the # hardwired fallback. switch -exact -- $tcl_platform(wordSize) { 4 { lappend bases /lib if {[catch { exec dpkg-architecture -qDEB_HOST_MULTIARCH } res]} { lappend bases /lib/i386-linux-gnu } else { # dpkg-arch returns the full tripled, not just cpu. lappend bases /lib/$res } } 8 { lappend bases /lib64 if {[catch { exec dpkg-architecture -qDEB_HOST_MULTIARCH } res]} { lappend bases /lib/x86_64-linux-gnu } else { # dpkg-arch returns the full tripled, not just cpu. lappend bases /lib/$res } } default { return -code error "Bad wordSize $tcl_platform(wordSize), expected 4 or 8" } } foreach base $bases { if {[LibcVersion $base -> v]} break } append plat -$v return "${plat}-${cpu}" } } return $id } proc ::platform::LibcVersion {base _->_ vv} { upvar 1 $vv v set libclist [lsort [glob -nocomplain -directory $base libc*]] if {![llength $libclist]} { return 0 } set libc [lindex $libclist 0] # Try executing the library first. This should suceed # for a glibc library, and return the version # information. if {![catch { set vdata [lindex [split [exec $libc] \n] 0] }]} { regexp {version ([0-9]+(\.[0-9]+)*)} $vdata -> v foreach {major minor} [split $v .] break set v glibc${major}.${minor} return 1 } else { # We had trouble executing the library. We are now # inspecting its name to determine the version # number. This code by Larry McVoy. if {[regexp -- {libc-([0-9]+)\.([0-9]+)} $libc -> major minor]} { set v glibc${major}.${minor} return 1 } } return 0 } # -- platform::patterns # # Given an exact platform identifier, i.e. _not_ the generic # identifier it assembles a list of exact platform identifier # describing platform which should be compatible with the # input. # # I.e. packages for all platforms in the result list should be # loadable on the specified platform. # << Should we add the generic identifier to the list as well ? In # general it is not compatible I believe. So better not. In many # cases the exact identifier is identical to the generic one # anyway. # >> proc ::platform::patterns {id} { set res [list $id] if {$id eq "tcl"} {return $res} switch -glob -- $id { solaris*-* { if {[regexp {solaris([^-]*)-(.*)} $id -> v cpu]} { if {$v eq ""} {return $id} foreach {major minor} [split $v .] break incr minor -1 for {set j $minor} {$j >= 6} {incr j -1} { lappend res solaris${major}.${j}-${cpu} } } } linux*-* { if {[regexp {linux-glibc([^-]*)-(.*)} $id -> v cpu]} { foreach {major minor} [split $v .] break incr minor -1 for {set j $minor} {$j >= 0} {incr j -1} { lappend res linux-glibc${major}.${j}-${cpu} } } } macosx-powerpc { lappend res macosx-universal } macosx-x86_64 { lappend res macosx-i386-x86_64 } macosx-ix86 { lappend res macosx-universal macosx-i386-x86_64 } macosx*-* { # 10.5+ if {[regexp {macosx([^-]*)-(.*)} $id -> v cpu]} { switch -exact -- $cpu { ix86 { lappend alt i386-x86_64 lappend alt universal } x86_64 { lappend alt i386-x86_64 } default { set alt {} } } if {$v ne ""} { foreach {major minor} [split $v .] break # Add 10.5 to 10.minor to patterns. set res {} for {set j $minor} {$j >= 5} {incr j -1} { lappend res macosx${major}.${j}-${cpu} foreach a $alt { lappend res macosx${major}.${j}-$a } } # Add unversioned patterns for 10.3/10.4 builds. lappend res macosx-${cpu} foreach a $alt { lappend res macosx-$a } } else { # No version, just do unversioned patterns. foreach a $alt { lappend res macosx-$a } } } else { # no v, no cpu ... nothing } } } lappend res tcl ; # Pure tcl packages are always compatible. return $res } # ### ### ### ######### ######### ######### ## Ready package provide platform 1.0.14 # ### ### ### ######### ######### ######### ## Demo application if {[info exists argv0] && ($argv0 eq [info script])} { puts ==================================== parray tcl_platform puts ==================================== puts Generic\ identification:\ [::platform::generic] puts Exact\ identification:\ \ \ [::platform::identify] puts ==================================== puts Search\ patterns: puts *\ [join [::platform::patterns [::platform::identify]] \n*\ ] puts ==================================== exit 0 } tcl8.6.5/library/platform/shell.tcl0000644000175000017500000001353112663660066016676 0ustar sergeisergei # -*- tcl -*- # ### ### ### ######### ######### ######### ## Overview # Higher-level commands which invoke the functionality of this package # for an arbitrary tcl shell (tclsh, wish, ...). This is required by a # repository as while the tcl shell executing packages uses the same # platform in general as a repository application there can be # differences in detail (i.e. 32/64 bit builds). # ### ### ### ######### ######### ######### ## Requirements package require platform namespace eval ::platform::shell {} # ### ### ### ######### ######### ######### ## Implementation # -- platform::shell::generic proc ::platform::shell::generic {shell} { # Argument is the path to a tcl shell. CHECK $shell LOCATE base out set code {} # Forget any pre-existing platform package, it might be in # conflict with this one. lappend code {package forget platform} # Inject our platform package lappend code [list source $base] # Query and print the architecture lappend code {puts [platform::generic]} # And done lappend code {exit 0} set arch [RUN $shell [join $code \n]] if {$out} {file delete -force $base} return $arch } # -- platform::shell::identify proc ::platform::shell::identify {shell} { # Argument is the path to a tcl shell. CHECK $shell LOCATE base out set code {} # Forget any pre-existing platform package, it might be in # conflict with this one. lappend code {package forget platform} # Inject our platform package lappend code [list source $base] # Query and print the architecture lappend code {puts [platform::identify]} # And done lappend code {exit 0} set arch [RUN $shell [join $code \n]] if {$out} {file delete -force $base} return $arch } # -- platform::shell::platform proc ::platform::shell::platform {shell} { # Argument is the path to a tcl shell. CHECK $shell set code {} lappend code {puts $tcl_platform(platform)} lappend code {exit 0} return [RUN $shell [join $code \n]] } # ### ### ### ######### ######### ######### ## Internal helper commands. proc ::platform::shell::CHECK {shell} { if {![file exists $shell]} { return -code error "Shell \"$shell\" does not exist" } if {![file executable $shell]} { return -code error "Shell \"$shell\" is not executable (permissions)" } return } proc ::platform::shell::LOCATE {bv ov} { upvar 1 $bv base $ov out # Locate the platform package for injection into the specified # shell. We are using package management to find it, whereever it # is, instead of using hardwired relative paths. This allows us to # install the two packages as TMs without breaking the code # here. If the found package is wrapped we copy the code somewhere # where the spawned shell will be able to read it. # This code is brittle, it needs has to adapt to whatever changes # are made to the TM code, i.e. the provide statement generated by # tm.tcl set pl [package ifneeded platform [package require platform]] set base [lindex $pl end] set out 0 if {[lindex [file system $base]] ne "native"} { set temp [TEMP] file copy -force $base $temp set base $temp set out 1 } return } proc ::platform::shell::RUN {shell code} { set c [TEMP] set cc [open $c w] puts $cc $code close $cc set e [TEMP] set code [catch { exec $shell $c 2> $e } res] file delete $c if {$code} { append res \n[read [set chan [open $e r]]][close $chan] file delete $e return -code error "Shell \"$shell\" is not executable ($res)" } file delete $e return $res } proc ::platform::shell::TEMP {} { set prefix platform # This code is copied out of Tcllib's fileutil package. # (TempFile/tempfile) set tmpdir [DIR] set chars "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" set nrand_chars 10 set maxtries 10 set access [list RDWR CREAT EXCL TRUNC] set permission 0600 set channel "" set checked_dir_writable 0 set mypid [pid] for {set i 0} {$i < $maxtries} {incr i} { set newname $prefix for {set j 0} {$j < $nrand_chars} {incr j} { append newname [string index $chars \ [expr {int(rand()*62)}]] } set newname [file join $tmpdir $newname] if {[file exists $newname]} { after 1 } else { if {[catch {open $newname $access $permission} channel]} { if {!$checked_dir_writable} { set dirname [file dirname $newname] if {![file writable $dirname]} { return -code error "Directory $dirname is not writable" } set checked_dir_writable 1 } } else { # Success close $channel return [file normalize $newname] } } } if {$channel ne ""} { return -code error "Failed to open a temporary file: $channel" } else { return -code error "Failed to find an unused temporary file name" } } proc ::platform::shell::DIR {} { # This code is copied out of Tcllib's fileutil package. # (TempDir/tempdir) global tcl_platform env set attempdirs [list] foreach tmp {TMPDIR TEMP TMP} { if { [info exists env($tmp)] } { lappend attempdirs $env($tmp) } } switch $tcl_platform(platform) { windows { lappend attempdirs "C:\\TEMP" "C:\\TMP" "\\TEMP" "\\TMP" } macintosh { set tmpdir $env(TRASH_FOLDER) ;# a better place? } default { lappend attempdirs \ [file join / tmp] \ [file join / var tmp] \ [file join / usr tmp] } } lappend attempdirs [pwd] foreach tmp $attempdirs { if { [file isdirectory $tmp] && [file writable $tmp] } { return [file normalize $tmp] } } # Fail if nothing worked. return -code error "Unable to determine a proper directory for temporary files" } # ### ### ### ######### ######### ######### ## Ready package provide platform::shell 1.1.4 tcl8.6.5/library/tzdata/0000755000175000017500000000000012665173607014525 5ustar sergeisergeitcl8.6.5/library/tzdata/GMT00000644000175000017500000000022512661614722015150 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/GMT)]} { LoadTimeZoneFile Etc/GMT } set TZData(:GMT0) $TZData(:Etc/GMT) tcl8.6.5/library/tzdata/WET0000644000175000017500000001504612661614722015107 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:WET) { {-9223372036854775808 0 0 WET} {228877200 3600 1 WEST} {243997200 0 0 WET} {260326800 3600 1 WEST} {276051600 0 0 WET} {291776400 3600 1 WEST} {307501200 0 0 WET} {323830800 3600 1 WEST} {338950800 0 0 WET} {354675600 3600 1 WEST} {370400400 0 0 WET} {386125200 3600 1 WEST} {401850000 0 0 WET} {417574800 3600 1 WEST} {433299600 0 0 WET} {449024400 3600 1 WEST} {465354000 0 0 WET} {481078800 3600 1 WEST} {496803600 0 0 WET} {512528400 3600 1 WEST} {528253200 0 0 WET} {543978000 3600 1 WEST} {559702800 0 0 WET} {575427600 3600 1 WEST} {591152400 0 0 WET} {606877200 3600 1 WEST} {622602000 0 0 WET} {638326800 3600 1 WEST} {654656400 0 0 WET} {670381200 3600 1 WEST} {686106000 0 0 WET} {701830800 3600 1 WEST} {717555600 0 0 WET} {733280400 3600 1 WEST} {749005200 0 0 WET} {764730000 3600 1 WEST} {780454800 0 0 WET} {796179600 3600 1 WEST} {811904400 0 0 WET} {828234000 3600 1 WEST} {846378000 0 0 WET} {859683600 3600 1 WEST} {877827600 0 0 WET} {891133200 3600 1 WEST} {909277200 0 0 WET} {922582800 3600 1 WEST} {941331600 0 0 WET} {954032400 3600 1 WEST} {972781200 0 0 WET} {985482000 3600 1 WEST} {1004230800 0 0 WET} {1017536400 3600 1 WEST} {1035680400 0 0 WET} {1048986000 3600 1 WEST} {1067130000 0 0 WET} {1080435600 3600 1 WEST} {1099184400 0 0 WET} {1111885200 3600 1 WEST} {1130634000 0 0 WET} {1143334800 3600 1 WEST} {1162083600 0 0 WET} {1174784400 3600 1 WEST} {1193533200 0 0 WET} {1206838800 3600 1 WEST} {1224982800 0 0 WET} {1238288400 3600 1 WEST} {1256432400 0 0 WET} {1269738000 3600 1 WEST} {1288486800 0 0 WET} {1301187600 3600 1 WEST} {1319936400 0 0 WET} {1332637200 3600 1 WEST} {1351386000 0 0 WET} {1364691600 3600 1 WEST} {1382835600 0 0 WET} {1396141200 3600 1 WEST} {1414285200 0 0 WET} {1427590800 3600 1 WEST} {1445734800 0 0 WET} {1459040400 3600 1 WEST} {1477789200 0 0 WET} {1490490000 3600 1 WEST} {1509238800 0 0 WET} {1521939600 3600 1 WEST} {1540688400 0 0 WET} {1553994000 3600 1 WEST} {1572138000 0 0 WET} {1585443600 3600 1 WEST} {1603587600 0 0 WET} {1616893200 3600 1 WEST} {1635642000 0 0 WET} {1648342800 3600 1 WEST} {1667091600 0 0 WET} {1679792400 3600 1 WEST} {1698541200 0 0 WET} {1711846800 3600 1 WEST} {1729990800 0 0 WET} {1743296400 3600 1 WEST} {1761440400 0 0 WET} {1774746000 3600 1 WEST} {1792890000 0 0 WET} {1806195600 3600 1 WEST} {1824944400 0 0 WET} {1837645200 3600 1 WEST} {1856394000 0 0 WET} {1869094800 3600 1 WEST} {1887843600 0 0 WET} {1901149200 3600 1 WEST} {1919293200 0 0 WET} {1932598800 3600 1 WEST} {1950742800 0 0 WET} {1964048400 3600 1 WEST} {1982797200 0 0 WET} {1995498000 3600 1 WEST} {2014246800 0 0 WET} {2026947600 3600 1 WEST} {2045696400 0 0 WET} {2058397200 3600 1 WEST} {2077146000 0 0 WET} {2090451600 3600 1 WEST} {2108595600 0 0 WET} {2121901200 3600 1 WEST} {2140045200 0 0 WET} {2153350800 3600 1 WEST} {2172099600 0 0 WET} {2184800400 3600 1 WEST} {2203549200 0 0 WET} {2216250000 3600 1 WEST} {2234998800 0 0 WET} {2248304400 3600 1 WEST} {2266448400 0 0 WET} {2279754000 3600 1 WEST} {2297898000 0 0 WET} {2311203600 3600 1 WEST} {2329347600 0 0 WET} {2342653200 3600 1 WEST} {2361402000 0 0 WET} {2374102800 3600 1 WEST} {2392851600 0 0 WET} {2405552400 3600 1 WEST} {2424301200 0 0 WET} {2437606800 3600 1 WEST} {2455750800 0 0 WET} {2469056400 3600 1 WEST} {2487200400 0 0 WET} {2500506000 3600 1 WEST} {2519254800 0 0 WET} {2531955600 3600 1 WEST} {2550704400 0 0 WET} {2563405200 3600 1 WEST} {2582154000 0 0 WET} {2595459600 3600 1 WEST} {2613603600 0 0 WET} {2626909200 3600 1 WEST} {2645053200 0 0 WET} {2658358800 3600 1 WEST} {2676502800 0 0 WET} {2689808400 3600 1 WEST} {2708557200 0 0 WET} {2721258000 3600 1 WEST} {2740006800 0 0 WET} {2752707600 3600 1 WEST} {2771456400 0 0 WET} {2784762000 3600 1 WEST} {2802906000 0 0 WET} {2816211600 3600 1 WEST} {2834355600 0 0 WET} {2847661200 3600 1 WEST} {2866410000 0 0 WET} {2879110800 3600 1 WEST} {2897859600 0 0 WET} {2910560400 3600 1 WEST} {2929309200 0 0 WET} {2942010000 3600 1 WEST} {2960758800 0 0 WET} {2974064400 3600 1 WEST} {2992208400 0 0 WET} {3005514000 3600 1 WEST} {3023658000 0 0 WET} {3036963600 3600 1 WEST} {3055712400 0 0 WET} {3068413200 3600 1 WEST} {3087162000 0 0 WET} {3099862800 3600 1 WEST} {3118611600 0 0 WET} {3131917200 3600 1 WEST} {3150061200 0 0 WET} {3163366800 3600 1 WEST} {3181510800 0 0 WET} {3194816400 3600 1 WEST} {3212960400 0 0 WET} {3226266000 3600 1 WEST} {3245014800 0 0 WET} {3257715600 3600 1 WEST} {3276464400 0 0 WET} {3289165200 3600 1 WEST} {3307914000 0 0 WET} {3321219600 3600 1 WEST} {3339363600 0 0 WET} {3352669200 3600 1 WEST} {3370813200 0 0 WET} {3384118800 3600 1 WEST} {3402867600 0 0 WET} {3415568400 3600 1 WEST} {3434317200 0 0 WET} {3447018000 3600 1 WEST} {3465766800 0 0 WET} {3479072400 3600 1 WEST} {3497216400 0 0 WET} {3510522000 3600 1 WEST} {3528666000 0 0 WET} {3541971600 3600 1 WEST} {3560115600 0 0 WET} {3573421200 3600 1 WEST} {3592170000 0 0 WET} {3604870800 3600 1 WEST} {3623619600 0 0 WET} {3636320400 3600 1 WEST} {3655069200 0 0 WET} {3668374800 3600 1 WEST} {3686518800 0 0 WET} {3699824400 3600 1 WEST} {3717968400 0 0 WET} {3731274000 3600 1 WEST} {3750022800 0 0 WET} {3762723600 3600 1 WEST} {3781472400 0 0 WET} {3794173200 3600 1 WEST} {3812922000 0 0 WET} {3825622800 3600 1 WEST} {3844371600 0 0 WET} {3857677200 3600 1 WEST} {3875821200 0 0 WET} {3889126800 3600 1 WEST} {3907270800 0 0 WET} {3920576400 3600 1 WEST} {3939325200 0 0 WET} {3952026000 3600 1 WEST} {3970774800 0 0 WET} {3983475600 3600 1 WEST} {4002224400 0 0 WET} {4015530000 3600 1 WEST} {4033674000 0 0 WET} {4046979600 3600 1 WEST} {4065123600 0 0 WET} {4078429200 3600 1 WEST} {4096573200 0 0 WET} } tcl8.6.5/library/tzdata/Europe/0000755000175000017500000000000012665173607015764 5ustar sergeisergeitcl8.6.5/library/tzdata/Europe/Zagreb0000644000175000017500000000026612661614722017117 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Belgrade)]} { LoadTimeZoneFile Europe/Belgrade } set TZData(:Europe/Zagreb) $TZData(:Europe/Belgrade) tcl8.6.5/library/tzdata/Europe/Moscow0000644000175000017500000000445312663660066017162 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Moscow) { {-9223372036854775808 9017 0 LMT} {-2840149817 9017 0 MMT} {-1688265017 9079 0 MMT} {-1656819079 12679 1 MST} {-1641353479 9079 0 MMT} {-1627965079 16279 1 MDST} {-1618716679 12679 1 MST} {-1596429079 16279 1 MDST} {-1593822679 14400 0 MSD} {-1589860800 10800 0 MSK} {-1542427200 14400 1 MSD} {-1539493200 18000 1 MSM} {-1525323600 14400 1 MSD} {-1491188400 7200 0 EET} {-1247536800 10800 0 MSD} {354920400 14400 1 MSD} {370728000 10800 0 MSK} {386456400 14400 1 MSD} {402264000 10800 0 MSK} {417992400 14400 1 MSD} {433800000 10800 0 MSK} {449614800 14400 1 MSD} {465346800 10800 0 MSK} {481071600 14400 1 MSD} {496796400 10800 0 MSK} {512521200 14400 1 MSD} {528246000 10800 0 MSK} {543970800 14400 1 MSD} {559695600 10800 0 MSK} {575420400 14400 1 MSD} {591145200 10800 0 MSK} {606870000 14400 1 MSD} {622594800 10800 0 MSK} {638319600 14400 1 MSD} {654649200 10800 0 MSK} {670374000 7200 0 EEMMTT} {670377600 10800 1 EEST} {686102400 7200 0 EET} {695779200 10800 0 MSD} {701812800 14400 1 MSD} {717534000 10800 0 MSK} {733273200 14400 1 MSD} {748998000 10800 0 MSK} {764722800 14400 1 MSD} {780447600 10800 0 MSK} {796172400 14400 1 MSD} {811897200 10800 0 MSK} {828226800 14400 1 MSD} {846370800 10800 0 MSK} {859676400 14400 1 MSD} {877820400 10800 0 MSK} {891126000 14400 1 MSD} {909270000 10800 0 MSK} {922575600 14400 1 MSD} {941324400 10800 0 MSK} {954025200 14400 1 MSD} {972774000 10800 0 MSK} {985474800 14400 1 MSD} {1004223600 10800 0 MSK} {1017529200 14400 1 MSD} {1035673200 10800 0 MSK} {1048978800 14400 1 MSD} {1067122800 10800 0 MSK} {1080428400 14400 1 MSD} {1099177200 10800 0 MSK} {1111878000 14400 1 MSD} {1130626800 10800 0 MSK} {1143327600 14400 1 MSD} {1162076400 10800 0 MSK} {1174777200 14400 1 MSD} {1193526000 10800 0 MSK} {1206831600 14400 1 MSD} {1224975600 10800 0 MSK} {1238281200 14400 1 MSD} {1256425200 10800 0 MSK} {1269730800 14400 1 MSD} {1288479600 10800 0 MSK} {1301180400 14400 0 MSK} {1414274400 10800 0 MSK} } tcl8.6.5/library/tzdata/Europe/Lisbon0000644000175000017500000002237712663660066017146 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Lisbon) { {-9223372036854775808 -2205 0 LMT} {-2713908195 -2205 0 LMT} {-1830381795 0 0 WET} {-1689555600 3600 1 WEST} {-1677801600 0 0 WET} {-1667437200 3600 1 WEST} {-1647738000 0 0 WET} {-1635814800 3600 1 WEST} {-1616202000 0 0 WET} {-1604365200 3600 1 WEST} {-1584666000 0 0 WET} {-1572742800 3600 1 WEST} {-1553043600 0 0 WET} {-1541206800 3600 1 WEST} {-1521507600 0 0 WET} {-1442451600 3600 1 WEST} {-1426813200 0 0 WET} {-1379293200 3600 1 WEST} {-1364778000 0 0 WET} {-1348448400 3600 1 WEST} {-1333328400 0 0 WET} {-1316394000 3600 1 WEST} {-1301274000 0 0 WET} {-1284339600 3600 1 WEST} {-1269824400 0 0 WET} {-1221440400 3600 1 WEST} {-1206925200 0 0 WET} {-1191200400 3600 1 WEST} {-1175475600 0 0 WET} {-1127696400 3600 1 WEST} {-1111971600 0 0 WET} {-1096851600 3600 1 WEST} {-1080522000 0 0 WET} {-1063587600 3600 1 WEST} {-1049072400 0 0 WET} {-1033347600 3600 1 WEST} {-1017622800 0 0 WET} {-1002502800 3600 1 WEST} {-986173200 0 0 WET} {-969238800 3600 1 WEST} {-950490000 0 0 WET} {-942022800 3600 1 WEST} {-922669200 0 0 WET} {-906944400 3600 1 WEST} {-891133200 0 0 WET} {-877309200 3600 1 WEST} {-873684000 7200 1 WEMT} {-864007200 3600 1 WEST} {-857955600 0 0 WET} {-845859600 3600 1 WEST} {-842839200 7200 1 WEMT} {-831348000 3600 1 WEST} {-825901200 0 0 WET} {-814410000 3600 1 WEST} {-810784800 7200 1 WEMT} {-799898400 3600 1 WEST} {-794451600 0 0 WET} {-782960400 3600 1 WEST} {-779335200 7200 1 WEMT} {-768448800 3600 1 WEST} {-763002000 0 0 WET} {-749091600 3600 1 WEST} {-733366800 0 0 WET} {-717631200 3600 1 WEST} {-701906400 0 0 WET} {-686181600 3600 1 WEST} {-670456800 0 0 WET} {-654732000 3600 1 WEST} {-639007200 0 0 WET} {-591832800 3600 1 WEST} {-575503200 0 0 WET} {-559778400 3600 1 WEST} {-544053600 0 0 WET} {-528328800 3600 1 WEST} {-512604000 0 0 WET} {-496879200 3600 1 WEST} {-481154400 0 0 WET} {-465429600 3600 1 WEST} {-449704800 0 0 WET} {-433980000 3600 1 WEST} {-417650400 0 0 WET} {-401925600 3600 1 WEST} {-386200800 0 0 WET} {-370476000 3600 1 WEST} {-354751200 0 0 WET} {-339026400 3600 1 WEST} {-323301600 0 0 WET} {-307576800 3600 1 WEST} {-291852000 0 0 WET} {-276127200 3600 1 WEST} {-260402400 0 0 WET} {-244677600 3600 1 WEST} {-228348000 0 0 WET} {-212623200 3600 1 WEST} {-196898400 0 0 WET} {-181173600 3600 1 WEST} {-165448800 0 0 WET} {-149724000 3600 1 WEST} {-133999200 0 0 WET} {-118274400 3600 0 CET} {212544000 0 0 WET} {228268800 3600 1 WEST} {243993600 0 0 WET} {260323200 3600 1 WEST} {276048000 0 0 WET} {291772800 3600 1 WEST} {307501200 0 0 WET} {323222400 3600 1 WEST} {338950800 0 0 WET} {354675600 3600 1 WEST} {370400400 0 0 WET} {386125200 3600 1 WEST} {401850000 0 0 WET} {417578400 3600 1 WEST} {433299600 0 0 WET} {449024400 3600 1 WEST} {465354000 0 0 WET} {481078800 3600 1 WEST} {496803600 0 0 WET} {512528400 3600 1 WEST} {528253200 0 0 WET} {543978000 3600 1 WEST} {559702800 0 0 WET} {575427600 3600 1 WEST} {591152400 0 0 WET} {606877200 3600 1 WEST} {622602000 0 0 WET} {638326800 3600 1 WEST} {654656400 0 0 WET} {670381200 3600 1 WEST} {686106000 0 0 WET} {701830800 3600 1 WEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 3600 0 WEST} {846378000 0 0 WET} {859683600 3600 1 WEST} {877827600 0 0 WET} {891133200 3600 1 WEST} {909277200 0 0 WET} {922582800 3600 1 WEST} {941331600 0 0 WET} {954032400 3600 1 WEST} {972781200 0 0 WET} {985482000 3600 1 WEST} {1004230800 0 0 WET} {1017536400 3600 1 WEST} {1035680400 0 0 WET} {1048986000 3600 1 WEST} {1067130000 0 0 WET} {1080435600 3600 1 WEST} {1099184400 0 0 WET} {1111885200 3600 1 WEST} {1130634000 0 0 WET} {1143334800 3600 1 WEST} {1162083600 0 0 WET} {1174784400 3600 1 WEST} {1193533200 0 0 WET} {1206838800 3600 1 WEST} {1224982800 0 0 WET} {1238288400 3600 1 WEST} {1256432400 0 0 WET} {1269738000 3600 1 WEST} {1288486800 0 0 WET} {1301187600 3600 1 WEST} {1319936400 0 0 WET} {1332637200 3600 1 WEST} {1351386000 0 0 WET} {1364691600 3600 1 WEST} {1382835600 0 0 WET} {1396141200 3600 1 WEST} {1414285200 0 0 WET} {1427590800 3600 1 WEST} {1445734800 0 0 WET} {1459040400 3600 1 WEST} {1477789200 0 0 WET} {1490490000 3600 1 WEST} {1509238800 0 0 WET} {1521939600 3600 1 WEST} {1540688400 0 0 WET} {1553994000 3600 1 WEST} {1572138000 0 0 WET} {1585443600 3600 1 WEST} {1603587600 0 0 WET} {1616893200 3600 1 WEST} {1635642000 0 0 WET} {1648342800 3600 1 WEST} {1667091600 0 0 WET} {1679792400 3600 1 WEST} {1698541200 0 0 WET} {1711846800 3600 1 WEST} {1729990800 0 0 WET} {1743296400 3600 1 WEST} {1761440400 0 0 WET} {1774746000 3600 1 WEST} {1792890000 0 0 WET} {1806195600 3600 1 WEST} {1824944400 0 0 WET} {1837645200 3600 1 WEST} {1856394000 0 0 WET} {1869094800 3600 1 WEST} {1887843600 0 0 WET} {1901149200 3600 1 WEST} {1919293200 0 0 WET} {1932598800 3600 1 WEST} {1950742800 0 0 WET} {1964048400 3600 1 WEST} {1982797200 0 0 WET} {1995498000 3600 1 WEST} {2014246800 0 0 WET} {2026947600 3600 1 WEST} {2045696400 0 0 WET} {2058397200 3600 1 WEST} {2077146000 0 0 WET} {2090451600 3600 1 WEST} {2108595600 0 0 WET} {2121901200 3600 1 WEST} {2140045200 0 0 WET} {2153350800 3600 1 WEST} {2172099600 0 0 WET} {2184800400 3600 1 WEST} {2203549200 0 0 WET} {2216250000 3600 1 WEST} {2234998800 0 0 WET} {2248304400 3600 1 WEST} {2266448400 0 0 WET} {2279754000 3600 1 WEST} {2297898000 0 0 WET} {2311203600 3600 1 WEST} {2329347600 0 0 WET} {2342653200 3600 1 WEST} {2361402000 0 0 WET} {2374102800 3600 1 WEST} {2392851600 0 0 WET} {2405552400 3600 1 WEST} {2424301200 0 0 WET} {2437606800 3600 1 WEST} {2455750800 0 0 WET} {2469056400 3600 1 WEST} {2487200400 0 0 WET} {2500506000 3600 1 WEST} {2519254800 0 0 WET} {2531955600 3600 1 WEST} {2550704400 0 0 WET} {2563405200 3600 1 WEST} {2582154000 0 0 WET} {2595459600 3600 1 WEST} {2613603600 0 0 WET} {2626909200 3600 1 WEST} {2645053200 0 0 WET} {2658358800 3600 1 WEST} {2676502800 0 0 WET} {2689808400 3600 1 WEST} {2708557200 0 0 WET} {2721258000 3600 1 WEST} {2740006800 0 0 WET} {2752707600 3600 1 WEST} {2771456400 0 0 WET} {2784762000 3600 1 WEST} {2802906000 0 0 WET} {2816211600 3600 1 WEST} {2834355600 0 0 WET} {2847661200 3600 1 WEST} {2866410000 0 0 WET} {2879110800 3600 1 WEST} {2897859600 0 0 WET} {2910560400 3600 1 WEST} {2929309200 0 0 WET} {2942010000 3600 1 WEST} {2960758800 0 0 WET} {2974064400 3600 1 WEST} {2992208400 0 0 WET} {3005514000 3600 1 WEST} {3023658000 0 0 WET} {3036963600 3600 1 WEST} {3055712400 0 0 WET} {3068413200 3600 1 WEST} {3087162000 0 0 WET} {3099862800 3600 1 WEST} {3118611600 0 0 WET} {3131917200 3600 1 WEST} {3150061200 0 0 WET} {3163366800 3600 1 WEST} {3181510800 0 0 WET} {3194816400 3600 1 WEST} {3212960400 0 0 WET} {3226266000 3600 1 WEST} {3245014800 0 0 WET} {3257715600 3600 1 WEST} {3276464400 0 0 WET} {3289165200 3600 1 WEST} {3307914000 0 0 WET} {3321219600 3600 1 WEST} {3339363600 0 0 WET} {3352669200 3600 1 WEST} {3370813200 0 0 WET} {3384118800 3600 1 WEST} {3402867600 0 0 WET} {3415568400 3600 1 WEST} {3434317200 0 0 WET} {3447018000 3600 1 WEST} {3465766800 0 0 WET} {3479072400 3600 1 WEST} {3497216400 0 0 WET} {3510522000 3600 1 WEST} {3528666000 0 0 WET} {3541971600 3600 1 WEST} {3560115600 0 0 WET} {3573421200 3600 1 WEST} {3592170000 0 0 WET} {3604870800 3600 1 WEST} {3623619600 0 0 WET} {3636320400 3600 1 WEST} {3655069200 0 0 WET} {3668374800 3600 1 WEST} {3686518800 0 0 WET} {3699824400 3600 1 WEST} {3717968400 0 0 WET} {3731274000 3600 1 WEST} {3750022800 0 0 WET} {3762723600 3600 1 WEST} {3781472400 0 0 WET} {3794173200 3600 1 WEST} {3812922000 0 0 WET} {3825622800 3600 1 WEST} {3844371600 0 0 WET} {3857677200 3600 1 WEST} {3875821200 0 0 WET} {3889126800 3600 1 WEST} {3907270800 0 0 WET} {3920576400 3600 1 WEST} {3939325200 0 0 WET} {3952026000 3600 1 WEST} {3970774800 0 0 WET} {3983475600 3600 1 WEST} {4002224400 0 0 WET} {4015530000 3600 1 WEST} {4033674000 0 0 WET} {4046979600 3600 1 WEST} {4065123600 0 0 WET} {4078429200 3600 1 WEST} {4096573200 0 0 WET} } tcl8.6.5/library/tzdata/Europe/Warsaw0000644000175000017500000002025612661614721017151 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Warsaw) { {-9223372036854775808 5040 0 LMT} {-2840145840 5040 0 WMT} {-1717032240 3600 0 CET} {-1693706400 7200 1 CEST} {-1680483600 3600 0 CET} {-1663455600 7200 1 CEST} {-1650150000 3600 0 CET} {-1632006000 7200 1 CEST} {-1618696800 7200 0 EET} {-1600473600 10800 1 EEST} {-1587168000 7200 0 EET} {-931734000 7200 0 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796870800 7200 0 CEST} {-796608000 3600 0 CET} {-778726800 7200 1 CEST} {-762660000 3600 0 CET} {-748486800 7200 1 CEST} {-733273200 3600 0 CET} {-715215600 7200 1 CEST} {-701910000 3600 0 CET} {-684975600 7200 1 CEST} {-670460400 3600 0 CET} {-654130800 7200 1 CEST} {-639010800 3600 0 CET} {-397094400 7200 1 CEST} {-386812800 3600 0 CET} {-371088000 7200 1 CEST} {-355363200 3600 0 CET} {-334195200 7200 1 CEST} {-323308800 3600 0 CET} {-307584000 7200 1 CEST} {-291859200 3600 0 CET} {-271296000 7200 1 CEST} {-260409600 3600 0 CET} {-239846400 7200 1 CEST} {-228960000 3600 0 CET} {-208396800 7200 1 CEST} {-197510400 3600 0 CET} {-176342400 7200 1 CEST} {-166060800 3600 0 CET} {220921200 3600 0 CET} {228873600 7200 1 CEST} {243993600 3600 0 CET} {260323200 7200 1 CEST} {276048000 3600 0 CET} {291772800 7200 1 CEST} {307497600 3600 0 CET} {323827200 7200 1 CEST} {338947200 3600 0 CET} {354672000 7200 1 CEST} {370396800 3600 0 CET} {386121600 7200 1 CEST} {401846400 3600 0 CET} {417571200 7200 1 CEST} {433296000 3600 0 CET} {449020800 7200 1 CEST} {465350400 3600 0 CET} {481075200 7200 1 CEST} {496800000 3600 0 CET} {512524800 7200 1 CEST} {528249600 3600 0 CET} {543974400 7200 1 CEST} {559699200 3600 0 CET} {567990000 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Mariehamn0000644000175000017500000000027112661614722017602 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Helsinki)]} { LoadTimeZoneFile Europe/Helsinki } set TZData(:Europe/Mariehamn) $TZData(:Europe/Helsinki) tcl8.6.5/library/tzdata/Europe/Berlin0000644000175000017500000001710212663653132017115 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Berlin) { {-9223372036854775808 3208 0 LMT} {-2422054408 3600 0 CET} {-1693706400 7200 1 CEST} {-1680483600 3600 0 CET} {-1663455600 7200 1 CEST} {-1650150000 3600 0 CET} {-1632006000 7200 1 CEST} {-1618700400 3600 0 CET} {-938905200 7200 1 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-781052400 7200 1 CEST} {-776559600 10800 0 CEMT} {-765936000 7200 1 CEST} {-761180400 3600 0 CET} {-757386000 3600 0 CET} {-748479600 7200 1 CEST} {-733273200 3600 0 CET} {-717631200 7200 1 CEST} {-714610800 10800 1 CEMT} {-710380800 7200 1 CEST} {-701910000 3600 0 CET} {-684975600 7200 1 CEST} {-670460400 3600 0 CET} {-654130800 7200 1 CEST} {-639010800 3600 0 CET} {315529200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Luxembourg0000644000175000017500000002117212661614721020034 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Luxembourg) { {-9223372036854775808 1476 0 LMT} {-2069713476 3600 0 CET} {-1692496800 7200 1 CEST} {-1680483600 3600 0 CET} {-1662343200 7200 1 CEST} {-1650157200 3600 0 CET} {-1632006000 7200 1 CEST} {-1618700400 3600 0 CET} {-1612659600 0 0 WET} {-1604278800 3600 1 WEST} {-1585519200 0 0 WET} {-1574038800 3600 1 WEST} {-1552258800 0 0 WET} {-1539997200 3600 1 WEST} {-1520550000 0 0 WET} {-1507510800 3600 1 WEST} {-1490572800 0 0 WET} {-1473642000 3600 1 WEST} {-1459119600 0 0 WET} {-1444006800 3600 1 WEST} {-1427673600 0 0 WET} {-1411866000 3600 1 WEST} {-1396224000 0 0 WET} {-1379293200 3600 1 WEST} {-1364774400 0 0 WET} {-1348448400 3600 1 WEST} {-1333324800 0 0 WET} {-1316394000 3600 1 WEST} {-1301270400 0 0 WET} {-1284339600 3600 1 WEST} {-1269813600 0 0 WET} {-1253484000 3600 1 WEST} {-1238364000 0 0 WET} {-1221429600 3600 1 WEST} {-1206914400 0 0 WET} {-1191189600 3600 1 WEST} {-1175464800 0 0 WET} {-1160344800 3600 1 WEST} {-1143410400 0 0 WET} {-1127685600 3600 1 WEST} {-1111960800 0 0 WET} {-1096840800 3600 1 WEST} {-1080511200 0 0 WET} {-1063576800 3600 1 WEST} {-1049061600 0 0 WET} {-1033336800 3600 1 WEST} {-1017612000 0 0 WET} {-1002492000 3600 1 WEST} {-986162400 0 0 WET} {-969228000 3600 1 WEST} {-950479200 0 0 WET} {-942012000 3600 1 WEST} {-935186400 7200 0 WEST} {-857257200 3600 0 WET} {-844556400 7200 1 WEST} {-828226800 3600 0 WET} {-812502000 7200 1 WEST} {-797983200 3600 0 CET} {-781052400 7200 1 CEST} {-766623600 3600 0 CET} {-745455600 7200 1 CEST} {-733273200 3600 0 CET} {220921200 3600 0 CET} {228877200 7200 1 CEST} {243997200 3600 0 CET} {260326800 7200 1 CEST} {276051600 3600 0 CET} {291776400 7200 1 CEST} {307501200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Isle_of_Man0000644000175000017500000000026512661614722020057 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/London)]} { LoadTimeZoneFile Europe/London } set TZData(:Europe/Isle_of_Man) $TZData(:Europe/London) tcl8.6.5/library/tzdata/Europe/Busingen0000644000175000017500000000026212663660066017457 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Zurich)]} { LoadTimeZoneFile Europe/Zurich } set TZData(:Europe/Busingen) $TZData(:Europe/Zurich) tcl8.6.5/library/tzdata/Europe/Prague0000644000175000017500000001700412661614721017125 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Prague) { {-9223372036854775808 3464 0 LMT} {-3786829064 3464 0 PMT} {-2469401864 3600 0 CET} {-1693706400 7200 1 CEST} {-1680483600 3600 0 CET} {-1663455600 7200 1 CEST} {-1650150000 3600 0 CET} {-1632006000 7200 1 CEST} {-1618700400 3600 0 CET} {-938905200 7200 1 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-798073200 3600 0 CET} {-780534000 7200 1 CEST} {-761180400 3600 0 CET} {-746578800 7200 1 CEST} {-733359600 3600 0 CET} {-716425200 7200 1 CEST} {-701910000 3600 0 CET} {-684975600 7200 1 CEST} {-670460400 3600 0 CET} {-654217200 7200 1 CEST} {-639010800 3600 0 CET} {283993200 3600 0 CET} {291776400 7200 1 CEST} {307501200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Vienna0000644000175000017500000001675312663660066017141 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Vienna) { {-9223372036854775808 3921 0 LMT} {-2422055121 3600 0 CET} {-1693706400 7200 1 CEST} {-1680483600 3600 0 CET} {-1663455600 7200 1 CEST} {-1650150000 3600 0 CET} {-1632006000 7200 1 CEST} {-1618700400 3600 0 CET} {-1577926800 3600 0 CET} {-1569711600 7200 1 CEST} {-1555801200 3600 0 CET} {-938905200 7200 0 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-781052400 7200 1 CEST} {-780188400 3600 0 CET} {-757386000 3600 0 CET} {-748479600 7200 1 CEST} {-733359600 3600 0 CET} {-717634800 7200 1 CEST} {-701910000 3600 0 CET} {-684975600 7200 1 CEST} {-670460400 3600 0 CET} {323823600 7200 1 CEST} {338940000 3600 0 CET} {347151600 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Chisinau0000644000175000017500000001722112663660066017453 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Chisinau) { {-9223372036854775808 6920 0 LMT} {-2840147720 6900 0 CMT} {-1637114100 6264 0 BMT} {-1213148664 7200 0 EET} {-1187056800 10800 1 EEST} {-1175479200 7200 0 EET} {-1159754400 10800 1 EEST} {-1144029600 7200 0 EET} {-1127700000 10800 1 EEST} {-1111975200 7200 0 EET} {-1096250400 10800 1 EEST} {-1080525600 7200 0 EET} {-1064800800 10800 1 EEST} {-1049076000 7200 0 EET} {-1033351200 10800 1 EEST} {-1017626400 7200 0 EET} {-1001901600 10800 1 EEST} {-986176800 7200 0 EET} {-970452000 10800 1 EEST} {-954727200 7200 0 EET} {-927165600 10800 1 EEST} {-898138800 7200 0 CET} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-800154000 10800 0 MSD} {354920400 14400 1 MSD} {370728000 10800 0 MSK} {386456400 14400 1 MSD} {402264000 10800 0 MSK} {417992400 14400 1 MSD} {433800000 10800 0 MSK} {449614800 14400 1 MSD} {465346800 10800 0 MSK} {481071600 14400 1 MSD} {496796400 10800 0 MSK} {512521200 14400 1 MSD} {528246000 10800 0 MSK} {543970800 14400 1 MSD} {559695600 10800 0 MSK} {575420400 14400 1 MSD} {591145200 10800 0 MSK} {606870000 14400 1 MSD} {622594800 10800 0 MSK} {631141200 10800 0 MSK} {641941200 7200 0 EET} {662680800 7200 0 EEMMTT} {670377600 10800 1 EEST} {686102400 7200 0 EET} {694216800 7200 0 EET} {701820000 10800 1 EEST} {717541200 7200 0 EET} {733269600 10800 1 EEST} {748990800 7200 0 EET} {764719200 10800 1 EEST} {780440400 7200 0 EET} {796168800 10800 1 EEST} {811890000 7200 0 EET} {828223200 10800 1 EEST} {846363600 7200 0 EET} {852069600 7200 0 EET} {859680000 10800 1 EEST} {877824000 7200 0 EET} {891129600 10800 1 EEST} {909273600 7200 0 EET} {922579200 10800 1 EEST} {941328000 7200 0 EET} {954028800 10800 1 EEST} {972777600 7200 0 EET} {985478400 10800 1 EEST} {1004227200 7200 0 EET} {1017532800 10800 1 EEST} {1035676800 7200 0 EET} {1048982400 10800 1 EEST} {1067126400 7200 0 EET} {1080432000 10800 1 EEST} {1099180800 7200 0 EET} {1111881600 10800 1 EEST} {1130630400 7200 0 EET} {1143331200 10800 1 EEST} {1162080000 7200 0 EET} {1174780800 10800 1 EEST} {1193529600 7200 0 EET} {1206835200 10800 1 EEST} {1224979200 7200 0 EET} {1238284800 10800 1 EEST} {1256428800 7200 0 EET} {1269734400 10800 1 EEST} {1288483200 7200 0 EET} {1301184000 10800 1 EEST} {1319932800 7200 0 EET} {1332633600 10800 1 EEST} {1351382400 7200 0 EET} {1364688000 10800 1 EEST} {1382832000 7200 0 EET} {1396137600 10800 1 EEST} {1414281600 7200 0 EET} {1427587200 10800 1 EEST} {1445731200 7200 0 EET} {1459036800 10800 1 EEST} {1477785600 7200 0 EET} {1490486400 10800 1 EEST} {1509235200 7200 0 EET} {1521936000 10800 1 EEST} {1540684800 7200 0 EET} {1553990400 10800 1 EEST} {1572134400 7200 0 EET} {1585440000 10800 1 EEST} {1603584000 7200 0 EET} {1616889600 10800 1 EEST} {1635638400 7200 0 EET} {1648339200 10800 1 EEST} {1667088000 7200 0 EET} {1679788800 10800 1 EEST} {1698537600 7200 0 EET} {1711843200 10800 1 EEST} {1729987200 7200 0 EET} {1743292800 10800 1 EEST} {1761436800 7200 0 EET} {1774742400 10800 1 EEST} {1792886400 7200 0 EET} {1806192000 10800 1 EEST} {1824940800 7200 0 EET} {1837641600 10800 1 EEST} {1856390400 7200 0 EET} {1869091200 10800 1 EEST} {1887840000 7200 0 EET} {1901145600 10800 1 EEST} {1919289600 7200 0 EET} {1932595200 10800 1 EEST} {1950739200 7200 0 EET} {1964044800 10800 1 EEST} {1982793600 7200 0 EET} {1995494400 10800 1 EEST} {2014243200 7200 0 EET} {2026944000 10800 1 EEST} {2045692800 7200 0 EET} {2058393600 10800 1 EEST} {2077142400 7200 0 EET} {2090448000 10800 1 EEST} {2108592000 7200 0 EET} {2121897600 10800 1 EEST} {2140041600 7200 0 EET} {2153347200 10800 1 EEST} {2172096000 7200 0 EET} {2184796800 10800 1 EEST} {2203545600 7200 0 EET} {2216246400 10800 1 EEST} {2234995200 7200 0 EET} {2248300800 10800 1 EEST} {2266444800 7200 0 EET} {2279750400 10800 1 EEST} {2297894400 7200 0 EET} {2311200000 10800 1 EEST} {2329344000 7200 0 EET} {2342649600 10800 1 EEST} {2361398400 7200 0 EET} {2374099200 10800 1 EEST} {2392848000 7200 0 EET} {2405548800 10800 1 EEST} {2424297600 7200 0 EET} {2437603200 10800 1 EEST} {2455747200 7200 0 EET} {2469052800 10800 1 EEST} {2487196800 7200 0 EET} {2500502400 10800 1 EEST} {2519251200 7200 0 EET} {2531952000 10800 1 EEST} {2550700800 7200 0 EET} {2563401600 10800 1 EEST} {2582150400 7200 0 EET} {2595456000 10800 1 EEST} {2613600000 7200 0 EET} {2626905600 10800 1 EEST} {2645049600 7200 0 EET} {2658355200 10800 1 EEST} {2676499200 7200 0 EET} {2689804800 10800 1 EEST} {2708553600 7200 0 EET} {2721254400 10800 1 EEST} {2740003200 7200 0 EET} {2752704000 10800 1 EEST} {2771452800 7200 0 EET} {2784758400 10800 1 EEST} {2802902400 7200 0 EET} {2816208000 10800 1 EEST} {2834352000 7200 0 EET} {2847657600 10800 1 EEST} {2866406400 7200 0 EET} {2879107200 10800 1 EEST} {2897856000 7200 0 EET} {2910556800 10800 1 EEST} {2929305600 7200 0 EET} {2942006400 10800 1 EEST} {2960755200 7200 0 EET} {2974060800 10800 1 EEST} {2992204800 7200 0 EET} {3005510400 10800 1 EEST} {3023654400 7200 0 EET} {3036960000 10800 1 EEST} {3055708800 7200 0 EET} {3068409600 10800 1 EEST} {3087158400 7200 0 EET} {3099859200 10800 1 EEST} {3118608000 7200 0 EET} {3131913600 10800 1 EEST} {3150057600 7200 0 EET} {3163363200 10800 1 EEST} {3181507200 7200 0 EET} {3194812800 10800 1 EEST} {3212956800 7200 0 EET} {3226262400 10800 1 EEST} {3245011200 7200 0 EET} {3257712000 10800 1 EEST} {3276460800 7200 0 EET} {3289161600 10800 1 EEST} {3307910400 7200 0 EET} {3321216000 10800 1 EEST} {3339360000 7200 0 EET} {3352665600 10800 1 EEST} {3370809600 7200 0 EET} {3384115200 10800 1 EEST} {3402864000 7200 0 EET} {3415564800 10800 1 EEST} {3434313600 7200 0 EET} {3447014400 10800 1 EEST} {3465763200 7200 0 EET} {3479068800 10800 1 EEST} {3497212800 7200 0 EET} {3510518400 10800 1 EEST} {3528662400 7200 0 EET} {3541968000 10800 1 EEST} {3560112000 7200 0 EET} {3573417600 10800 1 EEST} {3592166400 7200 0 EET} {3604867200 10800 1 EEST} {3623616000 7200 0 EET} {3636316800 10800 1 EEST} {3655065600 7200 0 EET} {3668371200 10800 1 EEST} {3686515200 7200 0 EET} {3699820800 10800 1 EEST} {3717964800 7200 0 EET} {3731270400 10800 1 EEST} {3750019200 7200 0 EET} {3762720000 10800 1 EEST} {3781468800 7200 0 EET} {3794169600 10800 1 EEST} {3812918400 7200 0 EET} {3825619200 10800 1 EEST} {3844368000 7200 0 EET} {3857673600 10800 1 EEST} {3875817600 7200 0 EET} {3889123200 10800 1 EEST} {3907267200 7200 0 EET} {3920572800 10800 1 EEST} {3939321600 7200 0 EET} {3952022400 10800 1 EEST} {3970771200 7200 0 EET} {3983472000 10800 1 EEST} {4002220800 7200 0 EET} {4015526400 10800 1 EEST} {4033670400 7200 0 EET} {4046976000 10800 1 EEST} {4065120000 7200 0 EET} {4078425600 10800 1 EEST} {4096569600 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Vilnius0000644000175000017500000001604312661614721017335 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Vilnius) { {-9223372036854775808 6076 0 LMT} {-2840146876 5040 0 WMT} {-1672536240 5736 0 KMT} {-1585100136 3600 0 CET} {-1561251600 7200 0 EET} {-1553565600 3600 0 CET} {-928198800 10800 0 MSK} {-900126000 3600 0 CET} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-802141200 10800 0 MSD} {354920400 14400 1 MSD} {370728000 10800 0 MSK} {386456400 14400 1 MSD} {402264000 10800 0 MSK} {417992400 14400 1 MSD} {433800000 10800 0 MSK} {449614800 14400 1 MSD} {465346800 10800 0 MSK} {481071600 14400 1 MSD} {496796400 10800 0 MSK} {512521200 14400 1 MSD} {528246000 10800 0 MSK} {543970800 14400 1 MSD} {559695600 10800 0 MSK} {575420400 14400 1 MSD} {591145200 10800 0 MSK} {606870000 14400 1 MSD} {622594800 10800 0 MSK} {638319600 14400 1 MSD} {654649200 10800 0 MSK} {670374000 10800 1 EEST} {686102400 7200 0 EET} {701827200 10800 1 EEST} {717552000 7200 0 EET} {733276800 10800 1 EEST} {749001600 7200 0 EET} {764726400 10800 1 EEST} {780451200 7200 0 EET} {796176000 10800 1 EEST} {811900800 7200 0 EET} {828230400 10800 1 EEST} {846374400 7200 0 EET} {859680000 10800 1 EEST} {877824000 7200 0 EET} {883605600 7200 0 EET} {891133200 7200 0 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 7200 0 EET} {1041372000 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Belgrade0000644000175000017500000001562312663653132017415 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Belgrade) { {-9223372036854775808 4920 0 LMT} {-2713915320 3600 0 CET} {-905824800 3600 0 CET} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-788922000 3600 0 CET} {-777942000 7200 1 CEST} {-766623600 3600 0 CET} {407199600 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Belfast0000644000175000017500000000026112661614722017260 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/London)]} { LoadTimeZoneFile Europe/London } set TZData(:Europe/Belfast) $TZData(:Europe/London) tcl8.6.5/library/tzdata/Europe/Nicosia0000644000175000017500000000025612661614722017271 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Nicosia)]} { LoadTimeZoneFile Asia/Nicosia } set TZData(:Europe/Nicosia) $TZData(:Asia/Nicosia) tcl8.6.5/library/tzdata/Europe/Zurich0000644000175000017500000001561712663660066017163 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Zurich) { {-9223372036854775808 2048 0 LMT} {-3675198848 1786 0 BMT} {-2385246586 3600 0 CET} {-904435200 7200 1 CEST} {-891129600 3600 0 CET} {-872985600 7200 1 CEST} {-859680000 3600 0 CET} {347151600 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Vaduz0000644000175000017500000000025712663660066017002 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Zurich)]} { LoadTimeZoneFile Europe/Zurich } set TZData(:Europe/Vaduz) $TZData(:Europe/Zurich) tcl8.6.5/library/tzdata/Europe/Skopje0000644000175000017500000000026612661614722017140 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Belgrade)]} { LoadTimeZoneFile Europe/Belgrade } set TZData(:Europe/Skopje) $TZData(:Europe/Belgrade) tcl8.6.5/library/tzdata/Europe/Sarajevo0000644000175000017500000000027012661614722017452 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Belgrade)]} { LoadTimeZoneFile Europe/Belgrade } set TZData(:Europe/Sarajevo) $TZData(:Europe/Belgrade) tcl8.6.5/library/tzdata/Europe/Copenhagen0000644000175000017500000001644212661614721017756 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Copenhagen) { {-9223372036854775808 3020 0 LMT} {-2524524620 3020 0 CMT} {-2398294220 3600 0 CET} {-1692496800 7200 1 CEST} {-1680490800 3600 0 CET} {-935110800 7200 1 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-781052400 7200 0 CEST} {-769388400 3600 0 CET} {-747010800 7200 1 CEST} {-736383600 3600 0 CET} {-715215600 7200 1 CEST} {-706748400 3600 0 CET} {-683161200 7200 1 CEST} {-675298800 3600 0 CET} {315529200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Kiev0000644000175000017500000001604212663660066016606 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Kiev) { {-9223372036854775808 7324 0 LMT} {-2840148124 7324 0 KMT} {-1441159324 7200 0 EET} {-1247536800 10800 0 MSK} {-892522800 3600 0 CET} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-825382800 10800 0 MSD} {354920400 14400 1 MSD} {370728000 10800 0 MSK} {386456400 14400 1 MSD} {402264000 10800 0 MSK} {417992400 14400 1 MSD} {433800000 10800 0 MSK} {449614800 14400 1 MSD} {465346800 10800 0 MSK} {481071600 14400 1 MSD} {496796400 10800 0 MSK} {512521200 14400 1 MSD} {528246000 10800 0 MSK} {543970800 14400 1 MSD} {559695600 10800 0 MSK} {575420400 14400 1 MSD} {591145200 10800 0 MSK} {606870000 14400 1 MSD} {622594800 10800 0 MSK} {638319600 14400 1 MSD} {646786800 10800 1 EEST} {686102400 7200 0 EET} {701820000 10800 1 EEST} {717541200 7200 0 EET} {733269600 10800 1 EEST} {748990800 7200 0 EET} {764719200 10800 1 EEST} {780440400 7200 0 EET} {788911200 7200 0 EET} {796179600 10800 1 EEST} {811904400 7200 0 EET} {828234000 10800 1 EEST} {846378000 7200 0 EET} {859683600 10800 1 EEST} {877827600 7200 0 EET} {891133200 10800 1 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941331600 7200 0 EET} {954032400 10800 1 EEST} {972781200 7200 0 EET} {985482000 10800 1 EEST} {1004230800 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Samara0000644000175000017500000000413712663660066017116 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Samara) { {-9223372036854775808 12020 0 LMT} {-1593825620 10800 0 SAMT} {-1247540400 14400 0 SAMT} {-1102305600 14400 0 KUYMMTT} {354916800 18000 1 KUYST} {370724400 14400 0 KUYT} {386452800 18000 1 KUYST} {402260400 14400 0 KUYT} {417988800 18000 1 KUYST} {433796400 14400 0 KUYT} {449611200 18000 1 KUYST} {465343200 14400 0 KUYT} {481068000 18000 1 KUYST} {496792800 14400 0 KUYT} {512517600 18000 1 KUYST} {528242400 14400 0 KUYT} {543967200 18000 1 KUYST} {559692000 14400 0 KUYT} {575416800 18000 1 KUYST} {591141600 14400 0 KUYT} {606866400 10800 0 MSD} {606870000 14400 1 MSD} {622594800 10800 0 MSK} {638319600 14400 1 MSD} {654649200 10800 0 MSK} {670374000 7200 0 EEMMTT} {670377600 10800 1 EEST} {686102400 10800 0 KUYT} {687916800 14400 0 SAMT} {701809200 18000 1 SAMST} {717530400 14400 0 SAMT} {733269600 18000 1 SAMST} {748994400 14400 0 SAMT} {764719200 18000 1 SAMST} {780444000 14400 0 SAMT} {796168800 18000 1 SAMST} {811893600 14400 0 SAMT} {828223200 18000 1 SAMST} {846367200 14400 0 SAMT} {859672800 18000 1 SAMST} {877816800 14400 0 SAMT} {891122400 18000 1 SAMST} {909266400 14400 0 SAMT} {922572000 18000 1 SAMST} {941320800 14400 0 SAMT} {954021600 18000 1 SAMST} {972770400 14400 0 SAMT} {985471200 18000 1 SAMST} {1004220000 14400 0 SAMT} {1017525600 18000 1 SAMST} {1035669600 14400 0 SAMT} {1048975200 18000 1 SAMST} {1067119200 14400 0 SAMT} {1080424800 18000 1 SAMST} {1099173600 14400 0 SAMT} {1111874400 18000 1 SAMST} {1130623200 14400 0 SAMT} {1143324000 18000 1 SAMST} {1162072800 14400 0 SAMT} {1174773600 18000 1 SAMST} {1193522400 14400 0 SAMT} {1206828000 18000 1 SAMST} {1224972000 14400 0 SAMT} {1238277600 18000 1 SAMST} {1256421600 14400 0 SAMT} {1269727200 10800 0 SAMMMTT} {1269730800 14400 1 SAMST} {1288479600 10800 0 SAMT} {1301180400 14400 0 SAMT} } tcl8.6.5/library/tzdata/Europe/Monaco0000644000175000017500000002124712661614721017122 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Monaco) { {-9223372036854775808 1772 0 LMT} {-2486680172 561 0 PMT} {-1855958961 0 0 WET} {-1689814800 3600 1 WEST} {-1680397200 0 0 WET} {-1665363600 3600 1 WEST} {-1648342800 0 0 WET} {-1635123600 3600 1 WEST} {-1616893200 0 0 WET} {-1604278800 3600 1 WEST} {-1585443600 0 0 WET} {-1574038800 3600 1 WEST} {-1552266000 0 0 WET} {-1539997200 3600 1 WEST} {-1520557200 0 0 WET} {-1507510800 3600 1 WEST} {-1490576400 0 0 WET} {-1470618000 3600 1 WEST} {-1459126800 0 0 WET} {-1444006800 3600 1 WEST} {-1427677200 0 0 WET} {-1411952400 3600 1 WEST} {-1396227600 0 0 WET} {-1379293200 3600 1 WEST} {-1364778000 0 0 WET} {-1348448400 3600 1 WEST} {-1333328400 0 0 WET} {-1316394000 3600 1 WEST} {-1301274000 0 0 WET} {-1284339600 3600 1 WEST} {-1269824400 0 0 WET} {-1253494800 3600 1 WEST} {-1238374800 0 0 WET} {-1221440400 3600 1 WEST} {-1206925200 0 0 WET} {-1191200400 3600 1 WEST} {-1175475600 0 0 WET} {-1160355600 3600 1 WEST} {-1143421200 0 0 WET} {-1127696400 3600 1 WEST} {-1111971600 0 0 WET} {-1096851600 3600 1 WEST} {-1080522000 0 0 WET} {-1063587600 3600 1 WEST} {-1049072400 0 0 WET} {-1033347600 3600 1 WEST} {-1017622800 0 0 WET} {-1002502800 3600 1 WEST} {-986173200 0 0 WET} {-969238800 3600 1 WEST} {-950490000 0 0 WET} {-942012000 3600 1 WEST} {-904438800 7200 1 WEMT} {-891136800 3600 1 WEST} {-877827600 7200 1 WEMT} {-857257200 3600 1 WEST} {-844556400 7200 1 WEMT} {-828226800 3600 1 WEST} {-812502000 7200 1 WEMT} {-796266000 3600 1 WEST} {-781052400 7200 1 WEMT} {-766616400 3600 0 CET} {196819200 7200 1 CEST} {212540400 3600 0 CET} {220921200 3600 0 CET} {228877200 7200 1 CEST} {243997200 3600 0 CET} {260326800 7200 1 CEST} {276051600 3600 0 CET} {291776400 7200 1 CEST} {307501200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Simferopol0000644000175000017500000000440312663660066020025 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Simferopol) { {-9223372036854775808 8184 0 LMT} {-2840148984 8160 0 SMT} {-1441160160 7200 0 EET} {-1247536800 10800 0 MSK} {-888894000 3600 0 CET} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-811645200 10800 0 MSD} {354920400 14400 1 MSD} {370728000 10800 0 MSK} {386456400 14400 1 MSD} {402264000 10800 0 MSK} {417992400 14400 1 MSD} {433800000 10800 0 MSK} {449614800 14400 1 MSD} {465346800 10800 0 MSK} {481071600 14400 1 MSD} {496796400 10800 0 MSK} {512521200 14400 1 MSD} {528246000 10800 0 MSK} {543970800 14400 1 MSD} {559695600 10800 0 MSK} {575420400 14400 1 MSD} {591145200 10800 0 MSK} {606870000 14400 1 MSD} {622594800 10800 0 MSK} {631141200 10800 0 MSK} {646786800 7200 0 EET} {694216800 7200 0 EET} {701820000 10800 1 EEST} {717541200 7200 0 EET} {733269600 10800 1 EEST} {748990800 7200 0 EET} {764719200 10800 1 EEST} {767743200 14400 0 MSD} {780436800 10800 0 MSK} {796165200 14400 1 MSD} {811886400 10800 0 MSK} {828219600 14400 1 MSD} {852066000 10800 0 MSK} {859683600 10800 0 EEST} {877827600 7200 0 EET} {891133200 10800 1 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941331600 7200 0 EET} {954032400 10800 1 EEST} {972781200 7200 0 EET} {985482000 10800 1 EEST} {1004230800 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396137600 14400 0 MSK} {1414274400 10800 0 MSK} } tcl8.6.5/library/tzdata/Europe/Helsinki0000644000175000017500000001572012663660066017460 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Helsinki) { {-9223372036854775808 5989 0 LMT} {-2890258789 5989 0 HMT} {-1535938789 7200 0 EET} {-875671200 10800 1 EEST} {-859773600 7200 0 EET} {354672000 10800 1 EEST} {370396800 7200 0 EET} {386121600 10800 1 EEST} {401846400 7200 0 EET} {410220000 7200 0 EET} {417574800 10800 1 EEST} {433299600 7200 0 EET} {449024400 10800 1 EEST} {465354000 7200 0 EET} {481078800 10800 1 EEST} {496803600 7200 0 EET} {512528400 10800 1 EEST} {528253200 7200 0 EET} {543978000 10800 1 EEST} {559702800 7200 0 EET} {575427600 10800 1 EEST} {591152400 7200 0 EET} {606877200 10800 1 EEST} {622602000 7200 0 EET} {638326800 10800 1 EEST} {654656400 7200 0 EET} {670381200 10800 1 EEST} {686106000 7200 0 EET} {701830800 10800 1 EEST} {717555600 7200 0 EET} {733280400 10800 1 EEST} {749005200 7200 0 EET} {764730000 10800 1 EEST} {780454800 7200 0 EET} {796179600 10800 1 EEST} {811904400 7200 0 EET} {828234000 10800 1 EEST} {846378000 7200 0 EET} {859683600 10800 1 EEST} {877827600 7200 0 EET} {891133200 10800 1 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941331600 7200 0 EET} {954032400 10800 1 EEST} {972781200 7200 0 EET} {985482000 10800 1 EEST} {1004230800 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Brussels0000644000175000017500000002131312661614721017502 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Brussels) { {-9223372036854775808 1050 0 LMT} {-2840141850 1050 0 BMT} {-2450953050 0 0 WET} {-1740355200 3600 0 CET} {-1693702800 7200 0 CEST} {-1680483600 3600 0 CET} {-1663455600 7200 1 CEST} {-1650150000 3600 0 CET} {-1632006000 7200 1 CEST} {-1618700400 3600 0 CET} {-1613826000 0 0 WET} {-1604278800 3600 1 WEST} {-1585530000 0 0 WET} {-1574038800 3600 1 WEST} {-1552266000 0 0 WET} {-1539997200 3600 1 WEST} {-1520557200 0 0 WET} {-1507510800 3600 1 WEST} {-1490576400 0 0 WET} {-1473642000 3600 1 WEST} {-1459126800 0 0 WET} {-1444006800 3600 1 WEST} {-1427677200 0 0 WET} {-1411952400 3600 1 WEST} {-1396227600 0 0 WET} {-1379293200 3600 1 WEST} {-1364778000 0 0 WET} {-1348448400 3600 1 WEST} {-1333328400 0 0 WET} {-1316394000 3600 1 WEST} {-1301263200 0 0 WET} {-1284328800 3600 1 WEST} {-1269813600 0 0 WET} {-1253484000 3600 1 WEST} {-1238364000 0 0 WET} {-1221429600 3600 1 WEST} {-1206914400 0 0 WET} {-1191189600 3600 1 WEST} {-1175464800 0 0 WET} {-1160344800 3600 1 WEST} {-1143410400 0 0 WET} {-1127685600 3600 1 WEST} {-1111960800 0 0 WET} {-1096840800 3600 1 WEST} {-1080511200 0 0 WET} {-1063576800 3600 1 WEST} {-1049061600 0 0 WET} {-1033336800 3600 1 WEST} {-1017612000 0 0 WET} {-1002492000 3600 1 WEST} {-986162400 0 0 WET} {-969228000 3600 1 WEST} {-950479200 0 0 WET} {-942012000 3600 1 WEST} {-934668000 7200 0 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-799290000 3600 0 CET} {-798073200 3600 0 CET} {-781052400 7200 1 CEST} {-766623600 3600 0 CET} {-745455600 7200 1 CEST} {-733273200 3600 0 CET} {220921200 3600 0 CET} {228877200 7200 1 CEST} {243997200 3600 0 CET} {260326800 7200 1 CEST} {276051600 3600 0 CET} {291776400 7200 1 CEST} {307501200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Jersey0000644000175000017500000000026012661614722017140 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/London)]} { LoadTimeZoneFile Europe/London } set TZData(:Europe/Jersey) $TZData(:Europe/London) tcl8.6.5/library/tzdata/Europe/Bratislava0000644000175000017500000000026412661614722017773 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Prague)]} { LoadTimeZoneFile Europe/Prague } set TZData(:Europe/Bratislava) $TZData(:Europe/Prague) tcl8.6.5/library/tzdata/Europe/Rome0000644000175000017500000002044112661614721016603 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Rome) { {-9223372036854775808 2996 0 LMT} {-3259097396 2996 0 RMT} {-2403564596 3600 0 CET} {-1690851600 7200 1 CEST} {-1680483600 3600 0 CET} {-1664758800 7200 1 CEST} {-1649034000 3600 0 CET} {-1635123600 7200 1 CEST} {-1616979600 3600 0 CET} {-1604278800 7200 1 CEST} {-1585530000 3600 0 CET} {-1571014800 7200 1 CEST} {-1555290000 3600 0 CET} {-932432400 7200 1 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-804819600 3600 0 CET} {-798080400 3600 0 CET} {-781052400 7200 1 CEST} {-766717200 3600 0 CET} {-750898800 7200 1 CEST} {-733359600 3600 0 CET} {-719456400 7200 1 CEST} {-701917200 3600 0 CET} {-689209200 7200 1 CEST} {-670460400 3600 0 CET} {-114051600 7200 1 CEST} {-103168800 3600 0 CET} {-81997200 7200 1 CEST} {-71719200 3600 0 CET} {-50547600 7200 1 CEST} {-40269600 3600 0 CET} {-18493200 7200 1 CEST} {-8215200 3600 0 CET} {12956400 7200 1 CEST} {23234400 3600 0 CET} {43801200 7200 1 CEST} {54687600 3600 0 CET} {75855600 7200 1 CEST} {86738400 3600 0 CET} {107910000 7200 1 CEST} {118188000 3600 0 CET} {138754800 7200 1 CEST} {149637600 3600 0 CET} {170809200 7200 1 CEST} {181090800 3600 0 CET} {202258800 7200 1 CEST} {212540400 3600 0 CET} {233103600 7200 1 CEST} {243990000 3600 0 CET} {265158000 7200 1 CEST} {276044400 3600 0 CET} {296607600 7200 1 CEST} {307494000 3600 0 CET} {315529200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Bucharest0000644000175000017500000001703212661614721017623 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Bucharest) { {-9223372036854775808 6264 0 LMT} {-2469404664 6264 0 BMT} {-1213148664 7200 0 EET} {-1187056800 10800 1 EEST} {-1175479200 7200 0 EET} {-1159754400 10800 1 EEST} {-1144029600 7200 0 EET} {-1127700000 10800 1 EEST} {-1111975200 7200 0 EET} {-1096250400 10800 1 EEST} {-1080525600 7200 0 EET} {-1064800800 10800 1 EEST} {-1049076000 7200 0 EET} {-1033351200 10800 1 EEST} {-1017626400 7200 0 EET} {-1001901600 10800 1 EEST} {-986176800 7200 0 EET} {-970452000 10800 1 EEST} {-954727200 7200 0 EET} {296604000 10800 1 EEST} {307486800 7200 0 EET} {323816400 10800 1 EEST} {338940000 7200 0 EET} {354672000 10800 0 EEST} {370396800 7200 0 EET} {386121600 10800 1 EEST} {401846400 7200 0 EET} {417571200 10800 1 EEST} {433296000 7200 0 EET} {449020800 10800 1 EEST} {465350400 7200 0 EET} {481075200 10800 1 EEST} {496800000 7200 0 EET} {512524800 10800 1 EEST} {528249600 7200 0 EET} {543974400 10800 1 EEST} {559699200 7200 0 EET} {575424000 10800 1 EEST} {591148800 7200 0 EET} {606873600 10800 1 EEST} {622598400 7200 0 EET} {638323200 10800 1 EEST} {654652800 7200 0 EET} {662680800 7200 0 EET} {670370400 10800 1 EEST} {686095200 7200 0 EET} {701820000 10800 1 EEST} {717544800 7200 0 EET} {733269600 10800 1 EEST} {748994400 7200 0 EET} {757375200 7200 0 EET} {764719200 10800 1 EEST} {780440400 7200 0 EET} {796168800 10800 1 EEST} {811890000 7200 0 EET} {828223200 10800 1 EEST} {846363600 7200 0 EET} {852069600 7200 0 EET} {859683600 10800 1 EEST} {877827600 7200 0 EET} {891133200 10800 1 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941331600 7200 0 EET} {954032400 10800 1 EEST} {972781200 7200 0 EET} {985482000 10800 1 EEST} {1004230800 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Athens0000644000175000017500000001700612661614721017126 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Athens) { {-9223372036854775808 5692 0 LMT} {-2344642492 5692 0 AMT} {-1686101632 7200 0 EET} {-1182996000 10800 1 EEST} {-1178161200 7200 0 EET} {-906861600 10800 1 EEST} {-904878000 7200 0 CEST} {-857257200 3600 0 CET} {-844477200 7200 1 CEST} {-828237600 3600 0 CET} {-812422800 7200 0 EET} {-552362400 10800 1 EEST} {-541652400 7200 0 EET} {166485600 10800 1 EEST} {186184800 7200 0 EET} {198028800 10800 1 EEST} {213753600 7200 0 EET} {228873600 10800 1 EEST} {244080000 7200 0 EET} {260323200 10800 1 EEST} {275446800 7200 0 EET} {291798000 10800 1 EEST} {307407600 7200 0 EET} {323388000 10800 1 EEST} {338936400 7200 0 EET} {347148000 7200 0 EET} {354675600 10800 1 EEST} {370400400 7200 0 EET} {386125200 10800 1 EEST} {401850000 7200 0 EET} {417574800 10800 1 EEST} {433299600 7200 0 EET} {449024400 10800 1 EEST} {465354000 7200 0 EET} {481078800 10800 1 EEST} {496803600 7200 0 EET} {512528400 10800 1 EEST} {528253200 7200 0 EET} {543978000 10800 1 EEST} {559702800 7200 0 EET} {575427600 10800 1 EEST} {591152400 7200 0 EET} {606877200 10800 1 EEST} {622602000 7200 0 EET} {638326800 10800 1 EEST} {654656400 7200 0 EET} {670381200 10800 1 EEST} {686106000 7200 0 EET} {701830800 10800 1 EEST} {717555600 7200 0 EET} {733280400 10800 1 EEST} {749005200 7200 0 EET} {764730000 10800 1 EEST} {780454800 7200 0 EET} {796179600 10800 1 EEST} {811904400 7200 0 EET} {828234000 10800 1 EEST} {846378000 7200 0 EET} {859683600 10800 1 EEST} {877827600 7200 0 EET} {891133200 10800 1 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941331600 7200 0 EET} {954032400 10800 1 EEST} {972781200 7200 0 EET} {985482000 10800 1 EEST} {1004230800 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Zaporozhye0000644000175000017500000001610412661614721020054 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Zaporozhye) { {-9223372036854775808 8440 0 LMT} {-2840149240 8400 0 CUT} {-1441160400 7200 0 EET} {-1247536800 10800 0 MSK} {-894769200 3600 0 CET} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-826419600 10800 0 MSD} {354920400 14400 1 MSD} {370728000 10800 0 MSK} {386456400 14400 1 MSD} {402264000 10800 0 MSK} {417992400 14400 1 MSD} {433800000 10800 0 MSK} {449614800 14400 1 MSD} {465346800 10800 0 MSK} {481071600 14400 1 MSD} {496796400 10800 0 MSK} {512521200 14400 1 MSD} {528246000 10800 0 MSK} {543970800 14400 1 MSD} {559695600 10800 0 MSK} {575420400 14400 1 MSD} {591145200 10800 0 MSK} {606870000 14400 1 MSD} {622594800 10800 0 MSK} {638319600 14400 1 MSD} {654649200 10800 0 MSK} {670374000 10800 0 EEST} {686091600 7200 0 EET} {701820000 10800 1 EEST} {717541200 7200 0 EET} {733269600 10800 1 EEST} {748990800 7200 0 EET} {764719200 10800 1 EEST} {780440400 7200 0 EET} {788911200 7200 0 EET} {796179600 10800 1 EEST} {811904400 7200 0 EET} {828234000 10800 1 EEST} {846378000 7200 0 EET} {859683600 10800 1 EEST} {877827600 7200 0 EET} {891133200 10800 1 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941331600 7200 0 EET} {954032400 10800 1 EEST} {972781200 7200 0 EET} {985482000 10800 1 EEST} {1004230800 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Tiraspol0000644000175000017500000000027012661614722017475 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Chisinau)]} { LoadTimeZoneFile Europe/Chisinau } set TZData(:Europe/Tiraspol) $TZData(:Europe/Chisinau) tcl8.6.5/library/tzdata/Europe/Gibraltar0000644000175000017500000002173512661614721017617 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Gibraltar) { {-9223372036854775808 -1284 0 LMT} {-2821649916 0 0 GMT} {-1691964000 3600 1 BST} {-1680472800 0 0 GMT} {-1664143200 3600 1 BST} {-1650146400 0 0 GMT} {-1633903200 3600 1 BST} {-1617487200 0 0 GMT} {-1601848800 3600 1 BST} {-1586037600 0 0 GMT} {-1570399200 3600 1 BST} {-1552168800 0 0 GMT} {-1538344800 3600 1 BST} {-1522533600 0 0 GMT} {-1507500000 3600 1 BST} {-1490565600 0 0 GMT} {-1473631200 3600 1 BST} {-1460930400 0 0 GMT} {-1442786400 3600 1 BST} {-1428876000 0 0 GMT} {-1410732000 3600 1 BST} {-1396216800 0 0 GMT} {-1379282400 3600 1 BST} {-1364767200 0 0 GMT} {-1348437600 3600 1 BST} {-1333317600 0 0 GMT} {-1315778400 3600 1 BST} {-1301263200 0 0 GMT} {-1284328800 3600 1 BST} {-1269813600 0 0 GMT} {-1253484000 3600 1 BST} {-1238364000 0 0 GMT} {-1221429600 3600 1 BST} {-1206914400 0 0 GMT} {-1189980000 3600 1 BST} {-1175464800 0 0 GMT} {-1159135200 3600 1 BST} {-1143410400 0 0 GMT} {-1126476000 3600 1 BST} {-1111960800 0 0 GMT} {-1095631200 3600 1 BST} {-1080511200 0 0 GMT} {-1063576800 3600 1 BST} {-1049061600 0 0 GMT} {-1032127200 3600 1 BST} {-1017612000 0 0 GMT} {-1001282400 3600 1 BST} {-986162400 0 0 GMT} {-969228000 3600 1 BST} {-950479200 0 0 GMT} {-942012000 3600 1 BST} {-904518000 7200 1 BDST} {-896050800 3600 1 BST} {-875487600 7200 1 BDST} {-864601200 3600 1 BST} {-844038000 7200 1 BDST} {-832546800 3600 1 BST} {-812588400 7200 1 BDST} {-798073200 3600 1 BST} {-781052400 7200 1 BDST} {-772066800 3600 1 BST} {-764805600 0 0 GMT} {-748476000 3600 1 BST} {-733356000 0 0 GMT} {-719445600 3600 1 BST} {-717030000 7200 1 BDST} {-706748400 3600 1 BST} {-699487200 0 0 GMT} {-687996000 3600 1 BST} {-668037600 0 0 GMT} {-654732000 3600 1 BST} {-636588000 0 0 GMT} {-622072800 3600 1 BST} {-605743200 0 0 GMT} {-590623200 3600 1 BST} {-574293600 0 0 GMT} {-558568800 3600 1 BST} {-542239200 0 0 GMT} {-527119200 3600 1 BST} {-512604000 0 0 GMT} {-496274400 3600 1 BST} {-481154400 0 0 GMT} {-464220000 3600 1 BST} {-449704800 0 0 GMT} {-432165600 3600 1 BST} {-417650400 0 0 GMT} {-401320800 3600 0 CET} {378687600 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Riga0000644000175000017500000001635012663660066016574 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Riga) { {-9223372036854775808 5794 0 LMT} {-2840146594 5794 0 RMT} {-1632008194 9394 1 LST} {-1618702594 5794 0 RMT} {-1601681794 9394 1 LST} {-1597275394 5794 0 RMT} {-1377308194 7200 0 EET} {-928029600 10800 0 MSK} {-899521200 3600 0 CET} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-795834000 10800 0 MSD} {354920400 14400 1 MSD} {370728000 10800 0 MSK} {386456400 14400 1 MSD} {402264000 10800 0 MSK} {417992400 14400 1 MSD} {433800000 10800 0 MSK} {449614800 14400 1 MSD} {465346800 10800 0 MSK} {481071600 14400 1 MSD} {496796400 10800 0 MSK} {512521200 14400 1 MSD} {528246000 10800 0 MSK} {543970800 14400 1 MSD} {559695600 10800 0 MSK} {575420400 14400 1 MSD} {591145200 10800 0 MSK} {606870000 10800 1 EEST} {622598400 7200 0 EET} {638323200 10800 1 EEST} {654652800 7200 0 EET} {670377600 10800 1 EEST} {686102400 7200 0 EET} {701827200 10800 1 EEST} {717552000 7200 0 EET} {733276800 10800 1 EEST} {749001600 7200 0 EET} {764726400 10800 1 EEST} {780451200 7200 0 EET} {796176000 10800 1 EEST} {811900800 7200 0 EET} {828230400 10800 1 EEST} {843955200 7200 0 EET} {853797600 7200 0 EET} {859683600 10800 1 EEST} {877827600 7200 0 EET} {891133200 10800 1 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941331600 7200 0 EET} {951775200 7200 0 EET} {978386400 7200 0 EET} {985482000 10800 1 EEST} {1004230800 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Dublin0000644000175000017500000002240412661614721017117 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Dublin) { {-9223372036854775808 -1500 0 LMT} {-2821649700 -1521 0 DMT} {-1691962479 2079 1 IST} {-1680471279 0 0 GMT} {-1664143200 3600 1 BST} {-1650146400 0 0 GMT} {-1633903200 3600 1 BST} {-1617487200 0 0 GMT} {-1601848800 3600 1 BST} {-1586037600 0 0 GMT} {-1570399200 3600 1 BST} {-1552168800 0 0 GMT} {-1538344800 3600 1 BST} {-1522533600 0 0 GMT} {-1517011200 0 0 IST} {-1507500000 3600 1 IST} {-1490565600 0 0 IST} {-1473631200 3600 1 IST} {-1460930400 0 0 IST} {-1442786400 3600 1 IST} {-1428876000 0 0 IST} {-1410732000 3600 1 IST} {-1396216800 0 0 IST} {-1379282400 3600 1 IST} {-1364767200 0 0 IST} {-1348437600 3600 1 IST} {-1333317600 0 0 IST} {-1315778400 3600 1 IST} {-1301263200 0 0 IST} {-1284328800 3600 1 IST} {-1269813600 0 0 IST} {-1253484000 3600 1 IST} {-1238364000 0 0 IST} {-1221429600 3600 1 IST} {-1206914400 0 0 IST} {-1189980000 3600 1 IST} {-1175464800 0 0 IST} {-1159135200 3600 1 IST} {-1143410400 0 0 IST} {-1126476000 3600 1 IST} {-1111960800 0 0 IST} {-1095631200 3600 1 IST} {-1080511200 0 0 IST} {-1063576800 3600 1 IST} {-1049061600 0 0 IST} {-1032127200 3600 1 IST} {-1017612000 0 0 IST} {-1001282400 3600 1 IST} {-986162400 0 0 IST} {-969228000 3600 1 IST} {-950479200 0 0 IST} {-942015600 3600 1 IST} {-733359600 0 0 GMT} {-719445600 3600 1 IST} {-699490800 0 0 GMT} {-684972000 3600 0 IST} {-668037600 0 0 IST} {-654732000 3600 1 IST} {-636588000 0 0 IST} {-622072800 3600 1 IST} {-605743200 0 0 IST} {-590623200 3600 1 IST} {-574293600 0 0 IST} {-558568800 3600 1 IST} {-542239200 0 0 IST} {-527119200 3600 1 IST} {-512604000 0 0 IST} {-496274400 3600 1 IST} {-481154400 0 0 IST} {-464220000 3600 1 IST} {-449704800 0 0 IST} {-432165600 3600 1 IST} {-417650400 0 0 IST} {-401320800 3600 1 IST} {-386200800 0 0 IST} {-369266400 3600 1 IST} {-354751200 0 0 IST} {-337816800 3600 1 IST} {-323301600 0 0 IST} {-306972000 3600 1 IST} {-291852000 0 0 IST} {-276732000 3600 1 IST} {-257983200 0 0 IST} {-245282400 3600 1 IST} {-226533600 0 0 IST} {-213228000 3600 1 IST} {-195084000 0 0 IST} {-182383200 3600 1 IST} {-163634400 0 0 IST} {-150933600 3600 1 IST} {-132184800 0 0 IST} {-119484000 3600 1 IST} {-100735200 0 0 IST} {-88034400 3600 1 IST} {-68680800 0 0 IST} {-59004000 3600 1 IST} {-37238400 3600 0 IST} {57722400 0 0 IST} {69818400 3600 1 IST} {89172000 0 0 IST} {101268000 3600 1 IST} {120621600 0 0 IST} {132717600 3600 1 IST} {152071200 0 0 IST} {164167200 3600 1 IST} {183520800 0 0 IST} {196221600 3600 1 IST} {214970400 0 0 IST} {227671200 3600 1 IST} {246420000 0 0 IST} {259120800 3600 1 IST} {278474400 0 0 IST} {290570400 3600 1 IST} {309924000 0 0 IST} {322020000 3600 1 IST} {341373600 0 0 IST} {354675600 3600 1 IST} {372819600 0 0 IST} {386125200 3600 1 IST} {404269200 0 0 IST} {417574800 3600 1 IST} {435718800 0 0 IST} {449024400 3600 1 IST} {467773200 0 0 IST} {481078800 3600 1 IST} {499222800 0 0 IST} {512528400 3600 1 IST} {530672400 0 0 IST} {543978000 3600 1 IST} {562122000 0 0 IST} {575427600 3600 1 IST} {593571600 0 0 IST} {606877200 3600 1 IST} {625626000 0 0 IST} {638326800 3600 1 IST} {657075600 0 0 IST} {670381200 3600 1 IST} {688525200 0 0 IST} {701830800 3600 1 IST} {719974800 0 0 IST} {733280400 3600 1 IST} {751424400 0 0 IST} {764730000 3600 1 IST} {782874000 0 0 IST} {796179600 3600 1 IST} {814323600 0 0 IST} {820454400 0 0 GMT} {828234000 3600 1 IST} {846378000 0 0 GMT} {859683600 3600 1 IST} {877827600 0 0 GMT} {891133200 3600 1 IST} {909277200 0 0 GMT} {922582800 3600 1 IST} {941331600 0 0 GMT} {954032400 3600 1 IST} {972781200 0 0 GMT} {985482000 3600 1 IST} {1004230800 0 0 GMT} {1017536400 3600 1 IST} {1035680400 0 0 GMT} {1048986000 3600 1 IST} {1067130000 0 0 GMT} {1080435600 3600 1 IST} {1099184400 0 0 GMT} {1111885200 3600 1 IST} {1130634000 0 0 GMT} {1143334800 3600 1 IST} {1162083600 0 0 GMT} {1174784400 3600 1 IST} {1193533200 0 0 GMT} {1206838800 3600 1 IST} {1224982800 0 0 GMT} {1238288400 3600 1 IST} {1256432400 0 0 GMT} {1269738000 3600 1 IST} {1288486800 0 0 GMT} {1301187600 3600 1 IST} {1319936400 0 0 GMT} {1332637200 3600 1 IST} {1351386000 0 0 GMT} {1364691600 3600 1 IST} {1382835600 0 0 GMT} {1396141200 3600 1 IST} {1414285200 0 0 GMT} {1427590800 3600 1 IST} {1445734800 0 0 GMT} {1459040400 3600 1 IST} {1477789200 0 0 GMT} {1490490000 3600 1 IST} {1509238800 0 0 GMT} {1521939600 3600 1 IST} {1540688400 0 0 GMT} {1553994000 3600 1 IST} {1572138000 0 0 GMT} {1585443600 3600 1 IST} {1603587600 0 0 GMT} {1616893200 3600 1 IST} {1635642000 0 0 GMT} {1648342800 3600 1 IST} {1667091600 0 0 GMT} {1679792400 3600 1 IST} {1698541200 0 0 GMT} {1711846800 3600 1 IST} {1729990800 0 0 GMT} {1743296400 3600 1 IST} {1761440400 0 0 GMT} {1774746000 3600 1 IST} {1792890000 0 0 GMT} {1806195600 3600 1 IST} {1824944400 0 0 GMT} {1837645200 3600 1 IST} {1856394000 0 0 GMT} {1869094800 3600 1 IST} {1887843600 0 0 GMT} {1901149200 3600 1 IST} {1919293200 0 0 GMT} {1932598800 3600 1 IST} {1950742800 0 0 GMT} {1964048400 3600 1 IST} {1982797200 0 0 GMT} {1995498000 3600 1 IST} {2014246800 0 0 GMT} {2026947600 3600 1 IST} {2045696400 0 0 GMT} {2058397200 3600 1 IST} {2077146000 0 0 GMT} {2090451600 3600 1 IST} {2108595600 0 0 GMT} {2121901200 3600 1 IST} {2140045200 0 0 GMT} {2153350800 3600 1 IST} {2172099600 0 0 GMT} {2184800400 3600 1 IST} {2203549200 0 0 GMT} {2216250000 3600 1 IST} {2234998800 0 0 GMT} {2248304400 3600 1 IST} {2266448400 0 0 GMT} {2279754000 3600 1 IST} {2297898000 0 0 GMT} {2311203600 3600 1 IST} {2329347600 0 0 GMT} {2342653200 3600 1 IST} {2361402000 0 0 GMT} {2374102800 3600 1 IST} {2392851600 0 0 GMT} {2405552400 3600 1 IST} {2424301200 0 0 GMT} {2437606800 3600 1 IST} {2455750800 0 0 GMT} {2469056400 3600 1 IST} {2487200400 0 0 GMT} {2500506000 3600 1 IST} {2519254800 0 0 GMT} {2531955600 3600 1 IST} {2550704400 0 0 GMT} {2563405200 3600 1 IST} {2582154000 0 0 GMT} {2595459600 3600 1 IST} {2613603600 0 0 GMT} {2626909200 3600 1 IST} {2645053200 0 0 GMT} {2658358800 3600 1 IST} {2676502800 0 0 GMT} {2689808400 3600 1 IST} {2708557200 0 0 GMT} {2721258000 3600 1 IST} {2740006800 0 0 GMT} {2752707600 3600 1 IST} {2771456400 0 0 GMT} {2784762000 3600 1 IST} {2802906000 0 0 GMT} {2816211600 3600 1 IST} {2834355600 0 0 GMT} {2847661200 3600 1 IST} {2866410000 0 0 GMT} {2879110800 3600 1 IST} {2897859600 0 0 GMT} {2910560400 3600 1 IST} {2929309200 0 0 GMT} {2942010000 3600 1 IST} {2960758800 0 0 GMT} {2974064400 3600 1 IST} {2992208400 0 0 GMT} {3005514000 3600 1 IST} {3023658000 0 0 GMT} {3036963600 3600 1 IST} {3055712400 0 0 GMT} {3068413200 3600 1 IST} {3087162000 0 0 GMT} {3099862800 3600 1 IST} {3118611600 0 0 GMT} {3131917200 3600 1 IST} {3150061200 0 0 GMT} {3163366800 3600 1 IST} {3181510800 0 0 GMT} {3194816400 3600 1 IST} {3212960400 0 0 GMT} {3226266000 3600 1 IST} {3245014800 0 0 GMT} {3257715600 3600 1 IST} {3276464400 0 0 GMT} {3289165200 3600 1 IST} {3307914000 0 0 GMT} {3321219600 3600 1 IST} {3339363600 0 0 GMT} {3352669200 3600 1 IST} {3370813200 0 0 GMT} {3384118800 3600 1 IST} {3402867600 0 0 GMT} {3415568400 3600 1 IST} {3434317200 0 0 GMT} {3447018000 3600 1 IST} {3465766800 0 0 GMT} {3479072400 3600 1 IST} {3497216400 0 0 GMT} {3510522000 3600 1 IST} {3528666000 0 0 GMT} {3541971600 3600 1 IST} {3560115600 0 0 GMT} {3573421200 3600 1 IST} {3592170000 0 0 GMT} {3604870800 3600 1 IST} {3623619600 0 0 GMT} {3636320400 3600 1 IST} {3655069200 0 0 GMT} {3668374800 3600 1 IST} {3686518800 0 0 GMT} {3699824400 3600 1 IST} {3717968400 0 0 GMT} {3731274000 3600 1 IST} {3750022800 0 0 GMT} {3762723600 3600 1 IST} {3781472400 0 0 GMT} {3794173200 3600 1 IST} {3812922000 0 0 GMT} {3825622800 3600 1 IST} {3844371600 0 0 GMT} {3857677200 3600 1 IST} {3875821200 0 0 GMT} {3889126800 3600 1 IST} {3907270800 0 0 GMT} {3920576400 3600 1 IST} {3939325200 0 0 GMT} {3952026000 3600 1 IST} {3970774800 0 0 GMT} {3983475600 3600 1 IST} {4002224400 0 0 GMT} {4015530000 3600 1 IST} {4033674000 0 0 GMT} {4046979600 3600 1 IST} {4065123600 0 0 GMT} {4078429200 3600 1 IST} {4096573200 0 0 GMT} } tcl8.6.5/library/tzdata/Europe/Andorra0000644000175000017500000001504212661614721017270 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Andorra) { {-9223372036854775808 364 0 LMT} {-2177453164 0 0 WET} {-733881600 3600 0 CET} {481078800 7200 0 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/London0000644000175000017500000002315712661614721017141 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/London) { {-9223372036854775808 -75 0 LMT} {-3852662325 0 0 GMT} {-1691964000 3600 1 BST} {-1680472800 0 0 GMT} {-1664143200 3600 1 BST} {-1650146400 0 0 GMT} {-1633903200 3600 1 BST} {-1617487200 0 0 GMT} {-1601848800 3600 1 BST} {-1586037600 0 0 GMT} {-1570399200 3600 1 BST} {-1552168800 0 0 GMT} {-1538344800 3600 1 BST} {-1522533600 0 0 GMT} {-1507500000 3600 1 BST} {-1490565600 0 0 GMT} {-1473631200 3600 1 BST} {-1460930400 0 0 GMT} {-1442786400 3600 1 BST} {-1428876000 0 0 GMT} {-1410732000 3600 1 BST} {-1396216800 0 0 GMT} {-1379282400 3600 1 BST} {-1364767200 0 0 GMT} {-1348437600 3600 1 BST} {-1333317600 0 0 GMT} {-1315778400 3600 1 BST} {-1301263200 0 0 GMT} {-1284328800 3600 1 BST} {-1269813600 0 0 GMT} {-1253484000 3600 1 BST} {-1238364000 0 0 GMT} {-1221429600 3600 1 BST} {-1206914400 0 0 GMT} {-1189980000 3600 1 BST} {-1175464800 0 0 GMT} {-1159135200 3600 1 BST} {-1143410400 0 0 GMT} {-1126476000 3600 1 BST} {-1111960800 0 0 GMT} {-1095631200 3600 1 BST} {-1080511200 0 0 GMT} {-1063576800 3600 1 BST} {-1049061600 0 0 GMT} {-1032127200 3600 1 BST} {-1017612000 0 0 GMT} {-1001282400 3600 1 BST} {-986162400 0 0 GMT} {-969228000 3600 1 BST} {-950479200 0 0 GMT} {-942012000 3600 1 BST} {-904518000 7200 1 BDST} {-896050800 3600 1 BST} {-875487600 7200 1 BDST} {-864601200 3600 1 BST} {-844038000 7200 1 BDST} {-832546800 3600 1 BST} {-812588400 7200 1 BDST} {-798073200 3600 1 BST} {-781052400 7200 1 BDST} {-772066800 3600 1 BST} {-764805600 0 0 GMT} {-748476000 3600 1 BST} {-733356000 0 0 GMT} {-719445600 3600 1 BST} {-717030000 7200 1 BDST} {-706748400 3600 1 BST} {-699487200 0 0 GMT} {-687996000 3600 1 BST} {-668037600 0 0 GMT} {-654732000 3600 1 BST} {-636588000 0 0 GMT} {-622072800 3600 1 BST} {-605743200 0 0 GMT} {-590623200 3600 1 BST} {-574293600 0 0 GMT} {-558568800 3600 1 BST} {-542239200 0 0 GMT} {-527119200 3600 1 BST} {-512604000 0 0 GMT} {-496274400 3600 1 BST} {-481154400 0 0 GMT} {-464220000 3600 1 BST} {-449704800 0 0 GMT} {-432165600 3600 1 BST} {-417650400 0 0 GMT} {-401320800 3600 1 BST} {-386200800 0 0 GMT} {-369266400 3600 1 BST} {-354751200 0 0 GMT} {-337816800 3600 1 BST} {-323301600 0 0 GMT} {-306972000 3600 1 BST} {-291852000 0 0 GMT} {-276732000 3600 1 BST} {-257983200 0 0 GMT} {-245282400 3600 1 BST} {-226533600 0 0 GMT} {-213228000 3600 1 BST} {-195084000 0 0 GMT} {-182383200 3600 1 BST} {-163634400 0 0 GMT} {-150933600 3600 1 BST} {-132184800 0 0 GMT} {-119484000 3600 1 BST} {-100735200 0 0 GMT} {-88034400 3600 1 BST} {-68680800 0 0 GMT} {-59004000 3600 1 BST} {-37238400 3600 0 BST} {57722400 0 0 GMT} {69818400 3600 1 BST} {89172000 0 0 GMT} {101268000 3600 1 BST} {120621600 0 0 GMT} {132717600 3600 1 BST} {152071200 0 0 GMT} {164167200 3600 1 BST} {183520800 0 0 GMT} {196221600 3600 1 BST} {214970400 0 0 GMT} {227671200 3600 1 BST} {246420000 0 0 GMT} {259120800 3600 1 BST} {278474400 0 0 GMT} {290570400 3600 1 BST} {309924000 0 0 GMT} {322020000 3600 1 BST} {341373600 0 0 GMT} {354675600 3600 1 BST} {372819600 0 0 GMT} {386125200 3600 1 BST} {404269200 0 0 GMT} {417574800 3600 1 BST} {435718800 0 0 GMT} {449024400 3600 1 BST} {467773200 0 0 GMT} {481078800 3600 1 BST} {499222800 0 0 GMT} {512528400 3600 1 BST} {530672400 0 0 GMT} {543978000 3600 1 BST} {562122000 0 0 GMT} {575427600 3600 1 BST} {593571600 0 0 GMT} {606877200 3600 1 BST} {625626000 0 0 GMT} {638326800 3600 1 BST} {657075600 0 0 GMT} {670381200 3600 1 BST} {688525200 0 0 GMT} {701830800 3600 1 BST} {719974800 0 0 GMT} {733280400 3600 1 BST} {751424400 0 0 GMT} {764730000 3600 1 BST} {782874000 0 0 GMT} {796179600 3600 1 BST} {814323600 0 0 GMT} {820454400 0 0 GMT} {828234000 3600 1 BST} {846378000 0 0 GMT} {859683600 3600 1 BST} {877827600 0 0 GMT} {891133200 3600 1 BST} {909277200 0 0 GMT} {922582800 3600 1 BST} {941331600 0 0 GMT} {954032400 3600 1 BST} {972781200 0 0 GMT} {985482000 3600 1 BST} {1004230800 0 0 GMT} {1017536400 3600 1 BST} {1035680400 0 0 GMT} {1048986000 3600 1 BST} {1067130000 0 0 GMT} {1080435600 3600 1 BST} {1099184400 0 0 GMT} {1111885200 3600 1 BST} {1130634000 0 0 GMT} {1143334800 3600 1 BST} {1162083600 0 0 GMT} {1174784400 3600 1 BST} {1193533200 0 0 GMT} {1206838800 3600 1 BST} {1224982800 0 0 GMT} {1238288400 3600 1 BST} {1256432400 0 0 GMT} {1269738000 3600 1 BST} {1288486800 0 0 GMT} {1301187600 3600 1 BST} {1319936400 0 0 GMT} {1332637200 3600 1 BST} {1351386000 0 0 GMT} {1364691600 3600 1 BST} {1382835600 0 0 GMT} {1396141200 3600 1 BST} {1414285200 0 0 GMT} {1427590800 3600 1 BST} {1445734800 0 0 GMT} {1459040400 3600 1 BST} {1477789200 0 0 GMT} {1490490000 3600 1 BST} {1509238800 0 0 GMT} {1521939600 3600 1 BST} {1540688400 0 0 GMT} {1553994000 3600 1 BST} {1572138000 0 0 GMT} {1585443600 3600 1 BST} {1603587600 0 0 GMT} {1616893200 3600 1 BST} {1635642000 0 0 GMT} {1648342800 3600 1 BST} {1667091600 0 0 GMT} {1679792400 3600 1 BST} {1698541200 0 0 GMT} {1711846800 3600 1 BST} {1729990800 0 0 GMT} {1743296400 3600 1 BST} {1761440400 0 0 GMT} {1774746000 3600 1 BST} {1792890000 0 0 GMT} {1806195600 3600 1 BST} {1824944400 0 0 GMT} {1837645200 3600 1 BST} {1856394000 0 0 GMT} {1869094800 3600 1 BST} {1887843600 0 0 GMT} {1901149200 3600 1 BST} {1919293200 0 0 GMT} {1932598800 3600 1 BST} {1950742800 0 0 GMT} {1964048400 3600 1 BST} {1982797200 0 0 GMT} {1995498000 3600 1 BST} {2014246800 0 0 GMT} {2026947600 3600 1 BST} {2045696400 0 0 GMT} {2058397200 3600 1 BST} {2077146000 0 0 GMT} {2090451600 3600 1 BST} {2108595600 0 0 GMT} {2121901200 3600 1 BST} {2140045200 0 0 GMT} {2153350800 3600 1 BST} {2172099600 0 0 GMT} {2184800400 3600 1 BST} {2203549200 0 0 GMT} {2216250000 3600 1 BST} {2234998800 0 0 GMT} {2248304400 3600 1 BST} {2266448400 0 0 GMT} {2279754000 3600 1 BST} {2297898000 0 0 GMT} {2311203600 3600 1 BST} {2329347600 0 0 GMT} {2342653200 3600 1 BST} {2361402000 0 0 GMT} {2374102800 3600 1 BST} {2392851600 0 0 GMT} {2405552400 3600 1 BST} {2424301200 0 0 GMT} {2437606800 3600 1 BST} {2455750800 0 0 GMT} {2469056400 3600 1 BST} {2487200400 0 0 GMT} {2500506000 3600 1 BST} {2519254800 0 0 GMT} {2531955600 3600 1 BST} {2550704400 0 0 GMT} {2563405200 3600 1 BST} {2582154000 0 0 GMT} {2595459600 3600 1 BST} {2613603600 0 0 GMT} {2626909200 3600 1 BST} {2645053200 0 0 GMT} {2658358800 3600 1 BST} {2676502800 0 0 GMT} {2689808400 3600 1 BST} {2708557200 0 0 GMT} {2721258000 3600 1 BST} {2740006800 0 0 GMT} {2752707600 3600 1 BST} {2771456400 0 0 GMT} {2784762000 3600 1 BST} {2802906000 0 0 GMT} {2816211600 3600 1 BST} {2834355600 0 0 GMT} {2847661200 3600 1 BST} {2866410000 0 0 GMT} {2879110800 3600 1 BST} {2897859600 0 0 GMT} {2910560400 3600 1 BST} {2929309200 0 0 GMT} {2942010000 3600 1 BST} {2960758800 0 0 GMT} {2974064400 3600 1 BST} {2992208400 0 0 GMT} {3005514000 3600 1 BST} {3023658000 0 0 GMT} {3036963600 3600 1 BST} {3055712400 0 0 GMT} {3068413200 3600 1 BST} {3087162000 0 0 GMT} {3099862800 3600 1 BST} {3118611600 0 0 GMT} {3131917200 3600 1 BST} {3150061200 0 0 GMT} {3163366800 3600 1 BST} {3181510800 0 0 GMT} {3194816400 3600 1 BST} {3212960400 0 0 GMT} {3226266000 3600 1 BST} {3245014800 0 0 GMT} {3257715600 3600 1 BST} {3276464400 0 0 GMT} {3289165200 3600 1 BST} {3307914000 0 0 GMT} {3321219600 3600 1 BST} {3339363600 0 0 GMT} {3352669200 3600 1 BST} {3370813200 0 0 GMT} {3384118800 3600 1 BST} {3402867600 0 0 GMT} {3415568400 3600 1 BST} {3434317200 0 0 GMT} {3447018000 3600 1 BST} {3465766800 0 0 GMT} {3479072400 3600 1 BST} {3497216400 0 0 GMT} {3510522000 3600 1 BST} {3528666000 0 0 GMT} {3541971600 3600 1 BST} {3560115600 0 0 GMT} {3573421200 3600 1 BST} {3592170000 0 0 GMT} {3604870800 3600 1 BST} {3623619600 0 0 GMT} {3636320400 3600 1 BST} {3655069200 0 0 GMT} {3668374800 3600 1 BST} {3686518800 0 0 GMT} {3699824400 3600 1 BST} {3717968400 0 0 GMT} {3731274000 3600 1 BST} {3750022800 0 0 GMT} {3762723600 3600 1 BST} {3781472400 0 0 GMT} {3794173200 3600 1 BST} {3812922000 0 0 GMT} {3825622800 3600 1 BST} {3844371600 0 0 GMT} {3857677200 3600 1 BST} {3875821200 0 0 GMT} {3889126800 3600 1 BST} {3907270800 0 0 GMT} {3920576400 3600 1 BST} {3939325200 0 0 GMT} {3952026000 3600 1 BST} {3970774800 0 0 GMT} {3983475600 3600 1 BST} {4002224400 0 0 GMT} {4015530000 3600 1 BST} {4033674000 0 0 GMT} {4046979600 3600 1 BST} {4065123600 0 0 GMT} {4078429200 3600 1 BST} {4096573200 0 0 GMT} } tcl8.6.5/library/tzdata/Europe/Stockholm0000644000175000017500000001562212661614721017651 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Stockholm) { {-9223372036854775808 4332 0 LMT} {-2871681132 3614 0 SET} {-2208992414 3600 0 CET} {-1692496800 7200 1 CEST} {-1680483600 3600 0 CET} {315529200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Madrid0000644000175000017500000002013212661614721017076 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Madrid) { {-9223372036854775808 -884 0 LMT} {-2177451916 0 0 WET} {-1661734800 3600 1 WEST} {-1648429200 0 0 WET} {-1631926800 3600 1 WEST} {-1616893200 0 0 WET} {-1601254800 3600 1 WEST} {-1585357200 0 0 WET} {-1442451600 3600 1 WEST} {-1427677200 0 0 WET} {-1379293200 3600 1 WEST} {-1364778000 0 0 WET} {-1348448400 3600 1 WEST} {-1333328400 0 0 WET} {-1316394000 3600 1 WEST} {-1301274000 0 0 WET} {-1284339600 3600 1 WEST} {-1269824400 0 0 WET} {-1029114000 3600 1 WEST} {-1017622800 0 0 WET} {-1002848400 3600 1 WEST} {-986173200 0 0 WET} {-969238800 3600 1 WEST} {-954118800 0 0 WET} {-940208400 3600 1 WEST} {-873079200 7200 1 WEMT} {-862538400 3600 1 WEST} {-842839200 7200 1 WEMT} {-828237600 3600 1 WEST} {-811389600 7200 1 WEMT} {-796010400 3600 1 WEST} {-779940000 7200 1 WEMT} {-765421200 3600 1 WEST} {-748490400 7200 1 WEMT} {-733881600 3600 0 CET} {-652327200 7200 1 CEST} {-639190800 3600 0 CET} {135122400 7200 1 CEST} {150246000 3600 0 CET} {167176800 7200 1 CEST} {181695600 3600 0 CET} {196812000 7200 1 CEST} {212540400 3600 0 CET} {228866400 7200 1 CEST} {243990000 3600 0 CET} {260402400 7200 1 CEST} {276044400 3600 0 CET} {283993200 3600 0 CET} {291776400 7200 1 CEST} {307501200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Tirane0000644000175000017500000001636412661614721017134 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Tirane) { {-9223372036854775808 4760 0 LMT} {-1767230360 3600 0 CET} {-932346000 7200 0 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-843519600 3600 0 CET} {136854000 7200 1 CEST} {149896800 3600 0 CET} {168130800 7200 1 CEST} {181432800 3600 0 CET} {199839600 7200 1 CEST} {213141600 3600 0 CET} {231894000 7200 1 CEST} {244591200 3600 0 CET} {263257200 7200 1 CEST} {276040800 3600 0 CET} {294706800 7200 1 CEST} {307490400 3600 0 CET} {326156400 7200 1 CEST} {339458400 3600 0 CET} {357087600 7200 1 CEST} {370389600 3600 0 CET} {389142000 7200 1 CEST} {402444000 3600 0 CET} {419468400 7200 1 CEST} {433807200 3600 0 CET} {449622000 7200 1 CEST} {457480800 7200 0 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Vatican0000644000175000017500000000025312661614722017266 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Rome)]} { LoadTimeZoneFile Europe/Rome } set TZData(:Europe/Vatican) $TZData(:Europe/Rome) tcl8.6.5/library/tzdata/Europe/Kaliningrad0000644000175000017500000000453512663660066020137 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Kaliningrad) { {-9223372036854775808 4920 0 LMT} {-2422056120 3600 0 CET} {-1693706400 7200 1 CEST} {-1680483600 3600 0 CET} {-1663455600 7200 1 CEST} {-1650150000 3600 0 CET} {-1632006000 7200 1 CEST} {-1618700400 3600 0 CET} {-938905200 7200 1 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-788922000 7200 0 CET} {-778730400 10800 1 CEST} {-762663600 7200 0 CET} {-757389600 10800 0 MSD} {354920400 14400 1 MSD} {370728000 10800 0 MSK} {386456400 14400 1 MSD} {402264000 10800 0 MSK} {417992400 14400 1 MSD} {433800000 10800 0 MSK} {449614800 14400 1 MSD} {465346800 10800 0 MSK} {481071600 14400 1 MSD} {496796400 10800 0 MSK} {512521200 14400 1 MSD} {528246000 10800 0 MSK} {543970800 14400 1 MSD} {559695600 10800 0 MSK} {575420400 14400 1 MSD} {591145200 10800 0 MSK} {606870000 14400 1 MSD} {622594800 10800 0 MSK} {638319600 14400 1 MSD} {654649200 10800 0 MSK} {670374000 7200 0 EEMMTT} {670377600 10800 1 EEST} {686102400 7200 0 EET} {701816400 10800 1 EEST} {717537600 7200 0 EET} {733276800 10800 1 EEST} {749001600 7200 0 EET} {764726400 10800 1 EEST} {780451200 7200 0 EET} {796176000 10800 1 EEST} {811900800 7200 0 EET} {828230400 10800 1 EEST} {846374400 7200 0 EET} {859680000 10800 1 EEST} {877824000 7200 0 EET} {891129600 10800 1 EEST} {909273600 7200 0 EET} {922579200 10800 1 EEST} {941328000 7200 0 EET} {954028800 10800 1 EEST} {972777600 7200 0 EET} {985478400 10800 1 EEST} {1004227200 7200 0 EET} {1017532800 10800 1 EEST} {1035676800 7200 0 EET} {1048982400 10800 1 EEST} {1067126400 7200 0 EET} {1080432000 10800 1 EEST} {1099180800 7200 0 EET} {1111881600 10800 1 EEST} {1130630400 7200 0 EET} {1143331200 10800 1 EEST} {1162080000 7200 0 EET} {1174780800 10800 1 EEST} {1193529600 7200 0 EET} {1206835200 10800 1 EEST} {1224979200 7200 0 EET} {1238284800 10800 1 EEST} {1256428800 7200 0 EET} {1269734400 10800 1 EEST} {1288483200 7200 0 EET} {1301184000 10800 0 FET} {1414278000 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Amsterdam0000644000175000017500000002111712661614721017617 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Amsterdam) { {-9223372036854775808 1172 0 LMT} {-4260212372 1172 0 AMT} {-1693700372 4772 1 NST} {-1680484772 1172 0 AMT} {-1663453172 4772 1 NST} {-1650147572 1172 0 AMT} {-1633213172 4772 1 NST} {-1617488372 1172 0 AMT} {-1601158772 4772 1 NST} {-1586038772 1172 0 AMT} {-1569709172 4772 1 NST} {-1554589172 1172 0 AMT} {-1538259572 4772 1 NST} {-1523139572 1172 0 AMT} {-1507501172 4772 1 NST} {-1490566772 1172 0 AMT} {-1470176372 4772 1 NST} {-1459117172 1172 0 AMT} {-1443997172 4772 1 NST} {-1427667572 1172 0 AMT} {-1406672372 4772 1 NST} {-1396217972 1172 0 AMT} {-1376950772 4772 1 NST} {-1364768372 1172 0 AMT} {-1345414772 4772 1 NST} {-1333318772 1172 0 AMT} {-1313792372 4772 1 NST} {-1301264372 1172 0 AMT} {-1282256372 4772 1 NST} {-1269814772 1172 0 AMT} {-1250720372 4772 1 NST} {-1238365172 1172 0 AMT} {-1219184372 4772 1 NST} {-1206915572 1172 0 AMT} {-1186957172 4772 1 NST} {-1175465972 1172 0 AMT} {-1156025972 4772 1 NST} {-1143411572 1172 0 AMT} {-1124489972 4772 1 NST} {-1111961972 1172 0 AMT} {-1092953972 4772 1 NST} {-1080512372 1172 0 AMT} {-1061331572 4772 1 NST} {-1049062772 1172 0 AMT} {-1029190772 4772 1 NST} {-1025741972 4800 0 NEST} {-1017613200 1200 0 NET} {-998259600 4800 1 NEST} {-986163600 1200 0 NET} {-966723600 4800 1 NEST} {-954109200 1200 0 NET} {-935022000 7200 0 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-781052400 7200 0 CEST} {-766623600 3600 0 CET} {220921200 3600 0 CET} {228877200 7200 1 CEST} {243997200 3600 0 CET} {260326800 7200 1 CEST} {276051600 3600 0 CET} {291776400 7200 1 CEST} {307501200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/San_Marino0000644000175000017500000000025612661614722017732 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Rome)]} { LoadTimeZoneFile Europe/Rome } set TZData(:Europe/San_Marino) $TZData(:Europe/Rome) tcl8.6.5/library/tzdata/Europe/Guernsey0000644000175000017500000000026212661614722017502 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/London)]} { LoadTimeZoneFile Europe/London } set TZData(:Europe/Guernsey) $TZData(:Europe/London) tcl8.6.5/library/tzdata/Europe/Podgorica0000644000175000017500000000027112661614722017610 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Belgrade)]} { LoadTimeZoneFile Europe/Belgrade } set TZData(:Europe/Podgorica) $TZData(:Europe/Belgrade) tcl8.6.5/library/tzdata/Europe/Tallinn0000644000175000017500000001617712663660066017322 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Tallinn) { {-9223372036854775808 5940 0 LMT} {-2840146740 5940 0 TMT} {-1638322740 3600 0 CET} {-1632006000 7200 1 CEST} {-1618700400 3600 0 CET} {-1593824400 5940 0 TMT} {-1535938740 7200 0 EET} {-927943200 10800 0 MSK} {-892954800 3600 0 CET} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-797648400 10800 0 MSD} {354920400 14400 1 MSD} {370728000 10800 0 MSK} {386456400 14400 1 MSD} {402264000 10800 0 MSK} {417992400 14400 1 MSD} {433800000 10800 0 MSK} {449614800 14400 1 MSD} {465346800 10800 0 MSK} {481071600 14400 1 MSD} {496796400 10800 0 MSK} {512521200 14400 1 MSD} {528246000 10800 0 MSK} {543970800 14400 1 MSD} {559695600 10800 0 MSK} {575420400 14400 1 MSD} {591145200 10800 0 MSK} {606870000 10800 1 EEST} {622598400 7200 0 EET} {638323200 10800 1 EEST} {654652800 7200 0 EET} {670377600 10800 1 EEST} {686102400 7200 0 EET} {701827200 10800 1 EEST} {717552000 7200 0 EET} {733276800 10800 1 EEST} {749001600 7200 0 EET} {764726400 10800 1 EEST} {780451200 7200 0 EET} {796176000 10800 1 EEST} {811900800 7200 0 EET} {828230400 10800 1 EEST} {846374400 7200 0 EET} {859680000 10800 1 EEST} {877824000 7200 0 EET} {891129600 10800 1 EEST} {906415200 10800 0 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941335200 7200 0 EET} {1014242400 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Minsk0000644000175000017500000000406512663660066016773 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Minsk) { {-9223372036854775808 6616 0 LMT} {-2840147416 6600 0 MMT} {-1441158600 7200 0 EET} {-1247536800 10800 0 MSK} {-899780400 3600 0 CET} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-804646800 10800 0 MSD} {354920400 14400 1 MSD} {370728000 10800 0 MSK} {386456400 14400 1 MSD} {402264000 10800 0 MSK} {417992400 14400 1 MSD} {433800000 10800 0 MSK} {449614800 14400 1 MSD} {465346800 10800 0 MSK} {481071600 14400 1 MSD} {496796400 10800 0 MSK} {512521200 14400 1 MSD} {528246000 10800 0 MSK} {543970800 14400 1 MSD} {559695600 10800 0 MSK} {575420400 14400 1 MSD} {591145200 10800 0 MSK} {606870000 14400 1 MSD} {622594800 10800 0 MSK} {631141200 10800 0 MSK} {670374000 10800 1 EEST} {686102400 7200 0 EET} {701820000 10800 1 EEST} {717544800 7200 0 EET} {733276800 10800 1 EEST} {749001600 7200 0 EET} {764726400 10800 1 EEST} {780451200 7200 0 EET} {796176000 10800 1 EEST} {811900800 7200 0 EET} {828230400 10800 1 EEST} {846374400 7200 0 EET} {859680000 10800 1 EEST} {877824000 7200 0 EET} {891129600 10800 1 EEST} {909273600 7200 0 EET} {922579200 10800 1 EEST} {941328000 7200 0 EET} {954028800 10800 1 EEST} {972777600 7200 0 EET} {985478400 10800 1 EEST} {1004227200 7200 0 EET} {1017532800 10800 1 EEST} {1035676800 7200 0 EET} {1048982400 10800 1 EEST} {1067126400 7200 0 EET} {1080432000 10800 1 EEST} {1099180800 7200 0 EET} {1111881600 10800 1 EEST} {1130630400 7200 0 EET} {1143331200 10800 1 EEST} {1162080000 7200 0 EET} {1174780800 10800 1 EEST} {1193529600 7200 0 EET} {1206835200 10800 1 EEST} {1224979200 7200 0 EET} {1238284800 10800 1 EEST} {1256428800 7200 0 EET} {1269734400 10800 1 EEST} {1288483200 7200 0 EET} {1301184000 10800 0 FET} {1414274400 10800 0 MSK} } tcl8.6.5/library/tzdata/Europe/Oslo0000644000175000017500000001674312661614721016627 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Oslo) { {-9223372036854775808 2580 0 LMT} {-2366757780 3600 0 CET} {-1691884800 7200 1 CEST} {-1680573600 3600 0 CET} {-927511200 7200 0 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-781052400 7200 0 CEST} {-765327600 3600 0 CET} {-340844400 7200 1 CEST} {-324514800 3600 0 CET} {-308790000 7200 1 CEST} {-293065200 3600 0 CET} {-277340400 7200 1 CEST} {-261615600 3600 0 CET} {-245890800 7200 1 CEST} {-230166000 3600 0 CET} {-214441200 7200 1 CEST} {-198716400 3600 0 CET} {-182991600 7200 1 CEST} {-166662000 3600 0 CET} {-147913200 7200 1 CEST} {-135212400 3600 0 CET} {315529200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Volgograd0000644000175000017500000000376412663660066017643 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Volgograd) { {-9223372036854775808 10660 0 LMT} {-1577761060 10800 0 TSAT} {-1411873200 10800 0 STAT} {-1247540400 14400 0 STAT} {-256881600 14400 0 VOLMMTT} {354916800 18000 1 VOLST} {370724400 14400 0 VOLT} {386452800 18000 1 VOLST} {402260400 14400 0 VOLT} {417988800 18000 1 VOLST} {433796400 14400 0 VOLT} {449611200 18000 1 VOLST} {465343200 14400 0 VOLT} {481068000 18000 1 VOLST} {496792800 14400 0 VOLT} {512517600 18000 1 VOLST} {528242400 14400 0 VOLT} {543967200 18000 1 VOLST} {559692000 14400 0 VOLT} {575416800 18000 1 VOLST} {591141600 14400 0 VOLT} {606866400 10800 0 VOLMMTT} {606870000 14400 1 VOLST} {622594800 10800 0 VOLT} {638319600 14400 1 VOLST} {654649200 10800 0 VOLT} {670374000 14400 0 VOLT} {701820000 14400 0 MSD} {717534000 10800 0 MSK} {733273200 14400 1 MSD} {748998000 10800 0 MSK} {764722800 14400 1 MSD} {780447600 10800 0 MSK} {796172400 14400 1 MSD} {811897200 10800 0 MSK} {828226800 14400 1 MSD} {846370800 10800 0 MSK} {859676400 14400 1 MSD} {877820400 10800 0 MSK} {891126000 14400 1 MSD} {909270000 10800 0 MSK} {922575600 14400 1 MSD} {941324400 10800 0 MSK} {954025200 14400 1 MSD} {972774000 10800 0 MSK} {985474800 14400 1 MSD} {1004223600 10800 0 MSK} {1017529200 14400 1 MSD} {1035673200 10800 0 MSK} {1048978800 14400 1 MSD} {1067122800 10800 0 MSK} {1080428400 14400 1 MSD} {1099177200 10800 0 MSK} {1111878000 14400 1 MSD} {1130626800 10800 0 MSK} {1143327600 14400 1 MSD} {1162076400 10800 0 MSK} {1174777200 14400 1 MSD} {1193526000 10800 0 MSK} {1206831600 14400 1 MSD} {1224975600 10800 0 MSK} {1238281200 14400 1 MSD} {1256425200 10800 0 MSK} {1269730800 14400 1 MSD} {1288479600 10800 0 MSK} {1301180400 14400 0 MSK} {1414274400 10800 0 MSK} } tcl8.6.5/library/tzdata/Europe/Sofia0000644000175000017500000001634412663660066016756 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Sofia) { {-9223372036854775808 5596 0 LMT} {-2840146396 7016 0 IMT} {-2369527016 7200 0 EET} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-788922000 3600 0 CET} {-781048800 7200 0 EET} {291762000 10800 0 EEST} {307576800 7200 0 EET} {323816400 10800 1 EEST} {339026400 7200 0 EET} {355266000 10800 1 EEST} {370393200 7200 0 EET} {386715600 10800 1 EEST} {401846400 7200 0 EET} {417571200 10800 1 EEST} {433296000 7200 0 EET} {449020800 10800 1 EEST} {465350400 7200 0 EET} {481075200 10800 1 EEST} {496800000 7200 0 EET} {512524800 10800 1 EEST} {528249600 7200 0 EET} {543974400 10800 1 EEST} {559699200 7200 0 EET} {575424000 10800 1 EEST} {591148800 7200 0 EET} {606873600 10800 1 EEST} {622598400 7200 0 EET} {638323200 10800 1 EEST} {654652800 7200 0 EET} {662680800 7200 0 EET} {670370400 10800 1 EEST} {686091600 7200 0 EET} {701820000 10800 1 EEST} {717541200 7200 0 EET} {733269600 10800 1 EEST} {748990800 7200 0 EET} {764719200 10800 1 EEST} {780440400 7200 0 EET} {796168800 10800 1 EEST} {811890000 7200 0 EET} {828223200 10800 1 EEST} {846363600 7200 0 EET} {852069600 7200 0 EET} {859683600 10800 1 EEST} {877827600 7200 0 EET} {891133200 10800 1 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941331600 7200 0 EET} {954032400 10800 1 EEST} {972781200 7200 0 EET} {985482000 10800 1 EEST} {1004230800 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Istanbul0000644000175000017500000002113112663660066017464 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Istanbul) { {-9223372036854775808 6952 0 LMT} {-2840147752 7016 0 IMT} {-1869875816 7200 0 EET} {-1693706400 10800 1 EEST} {-1680490800 7200 0 EET} {-1570413600 10800 1 EEST} {-1552186800 7200 0 EET} {-1538359200 10800 1 EEST} {-1522551600 7200 0 EET} {-1507514400 10800 1 EEST} {-1490583600 7200 0 EET} {-1440208800 10800 1 EEST} {-1428030000 7200 0 EET} {-1409709600 10800 1 EEST} {-1396494000 7200 0 EET} {-931140000 10800 1 EEST} {-922762800 7200 0 EET} {-917834400 10800 1 EEST} {-892436400 7200 0 EET} {-875844000 10800 1 EEST} {-857358000 7200 0 EET} {-781063200 10800 1 EEST} {-764737200 7200 0 EET} {-744343200 10800 1 EEST} {-733806000 7200 0 EET} {-716436000 10800 1 EEST} {-701924400 7200 0 EET} {-684986400 10800 1 EEST} {-670474800 7200 0 EET} {-654141600 10800 1 EEST} {-639025200 7200 0 EET} {-621828000 10800 1 EEST} {-606970800 7200 0 EET} {-590032800 10800 1 EEST} {-575434800 7200 0 EET} {-235620000 10800 1 EEST} {-228279600 7200 0 EET} {-177732000 10800 1 EEST} {-165726000 7200 0 EET} {10533600 10800 1 EEST} {23835600 7200 0 EET} {41983200 10800 1 EEST} {55285200 7200 0 EET} {74037600 10800 1 EEST} {87339600 7200 0 EET} {107910000 10800 1 EEST} {121219200 7200 0 EET} {133920000 10800 1 EEST} {152676000 7200 0 EET} {165362400 10800 1 EEST} {183502800 7200 0 EET} {202428000 10800 1 EEST} {215557200 7200 0 EET} {228866400 10800 1 EEST} {245797200 7200 0 EET} {260316000 10800 1 EEST} {277246800 14400 0 TRST} {291769200 14400 1 TRST} {308779200 10800 0 TRT} {323827200 14400 1 TRST} {340228800 10800 0 TRT} {354672000 14400 1 TRST} {371678400 10800 0 TRT} {386121600 14400 1 TRST} {403128000 10800 0 TRT} {428446800 14400 1 TRST} {433886400 10800 0 TRT} {482792400 7200 0 EET} {482796000 10800 1 EEST} {496702800 7200 0 EET} {512524800 10800 1 EEST} {528249600 7200 0 EET} {543974400 10800 1 EEST} {559699200 7200 0 EET} {575424000 10800 1 EEST} {591148800 7200 0 EET} {606873600 10800 1 EEST} {622598400 7200 0 EET} {638323200 10800 1 EEST} {654652800 7200 0 EET} {670374000 10800 1 EEST} {686098800 7200 0 EET} {701823600 10800 1 EEST} {717548400 7200 0 EET} {733273200 10800 1 EEST} {748998000 7200 0 EET} {764722800 10800 1 EEST} {780447600 7200 0 EET} {796172400 10800 1 EEST} {811897200 7200 0 EET} {828226800 10800 1 EEST} {846370800 7200 0 EET} {859676400 10800 1 EEST} {877820400 7200 0 EET} {891126000 10800 1 EEST} {909270000 7200 0 EET} {922575600 10800 1 EEST} {941324400 7200 0 EET} {954025200 10800 1 EEST} {972774000 7200 0 EET} {985474800 10800 1 EEST} {1004223600 7200 0 EET} {1017529200 10800 1 EEST} {1035673200 7200 0 EET} {1048978800 10800 1 EEST} {1067122800 7200 0 EET} {1080428400 10800 1 EEST} {1099177200 7200 0 EET} {1111878000 10800 1 EEST} {1130626800 7200 0 EET} {1143327600 10800 1 EEST} {1162076400 7200 0 EET} {1167602400 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 7200 0 EET} {1301274000 10800 0 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 7200 0 EET} {1396227600 10800 0 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 10800 1 EEST} {1446944400 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Ljubljana0000644000175000017500000000027112661614722017603 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Belgrade)]} { LoadTimeZoneFile Europe/Belgrade } set TZData(:Europe/Ljubljana) $TZData(:Europe/Belgrade) tcl8.6.5/library/tzdata/Europe/Uzhgorod0000644000175000017500000001616712661614721017514 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Uzhgorod) { {-9223372036854775808 5352 0 LMT} {-2500939752 3600 0 CET} {-946774800 3600 0 CET} {-938905200 7200 1 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796870800 7200 1 CEST} {-794714400 3600 0 CET} {-773456400 10800 0 MSD} {354920400 14400 1 MSD} {370728000 10800 0 MSK} {386456400 14400 1 MSD} {402264000 10800 0 MSK} {417992400 14400 1 MSD} {433800000 10800 0 MSK} {449614800 14400 1 MSD} {465346800 10800 0 MSK} {481071600 14400 1 MSD} {496796400 10800 0 MSK} {512521200 14400 1 MSD} {528246000 10800 0 MSK} {543970800 14400 1 MSD} {559695600 10800 0 MSK} {575420400 14400 1 MSD} {591145200 10800 0 MSK} {606870000 14400 1 MSD} {622594800 10800 0 MSK} {631141200 10800 0 MSK} {646786800 3600 0 CET} {670384800 7200 0 EET} {694216800 7200 0 EET} {701820000 10800 1 EEST} {717541200 7200 0 EET} {733269600 10800 1 EEST} {748990800 7200 0 EET} {764719200 10800 1 EEST} {780440400 7200 0 EET} {788911200 7200 0 EET} {796179600 10800 1 EEST} {811904400 7200 0 EET} {828234000 10800 1 EEST} {846378000 7200 0 EET} {859683600 10800 1 EEST} {877827600 7200 0 EET} {891133200 10800 1 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941331600 7200 0 EET} {954032400 10800 1 EEST} {972781200 7200 0 EET} {985482000 10800 1 EEST} {1004230800 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Europe/Paris0000644000175000017500000002120612661614721016757 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Paris) { {-9223372036854775808 561 0 LMT} {-2486678901 561 0 PMT} {-1855958901 0 0 WET} {-1689814800 3600 1 WEST} {-1680397200 0 0 WET} {-1665363600 3600 1 WEST} {-1648342800 0 0 WET} {-1635123600 3600 1 WEST} {-1616893200 0 0 WET} {-1604278800 3600 1 WEST} {-1585443600 0 0 WET} {-1574038800 3600 1 WEST} {-1552266000 0 0 WET} {-1539997200 3600 1 WEST} {-1520557200 0 0 WET} {-1507510800 3600 1 WEST} {-1490576400 0 0 WET} {-1470618000 3600 1 WEST} {-1459126800 0 0 WET} {-1444006800 3600 1 WEST} {-1427677200 0 0 WET} {-1411952400 3600 1 WEST} {-1396227600 0 0 WET} {-1379293200 3600 1 WEST} {-1364778000 0 0 WET} {-1348448400 3600 1 WEST} {-1333328400 0 0 WET} {-1316394000 3600 1 WEST} {-1301274000 0 0 WET} {-1284339600 3600 1 WEST} {-1269824400 0 0 WET} {-1253494800 3600 1 WEST} {-1238374800 0 0 WET} {-1221440400 3600 1 WEST} {-1206925200 0 0 WET} {-1191200400 3600 1 WEST} {-1175475600 0 0 WET} {-1160355600 3600 1 WEST} {-1143421200 0 0 WET} {-1127696400 3600 1 WEST} {-1111971600 0 0 WET} {-1096851600 3600 1 WEST} {-1080522000 0 0 WET} {-1063587600 3600 1 WEST} {-1049072400 0 0 WET} {-1033347600 3600 1 WEST} {-1017622800 0 0 WET} {-1002502800 3600 1 WEST} {-986173200 0 0 WET} {-969238800 3600 1 WEST} {-950490000 0 0 WET} {-942012000 3600 1 WEST} {-932436000 7200 0 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-800067600 7200 0 WEMT} {-796266000 3600 1 WEST} {-781052400 7200 1 WEMT} {-766616400 3600 0 CET} {196819200 7200 1 CEST} {212540400 3600 0 CET} {220921200 3600 0 CET} {228877200 7200 1 CEST} {243997200 3600 0 CET} {260326800 7200 1 CEST} {276051600 3600 0 CET} {291776400 7200 1 CEST} {307501200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Malta0000644000175000017500000002035112661614721016737 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Malta) { {-9223372036854775808 3484 0 LMT} {-2403478684 3600 0 CET} {-1690851600 7200 1 CEST} {-1680483600 3600 0 CET} {-1664758800 7200 1 CEST} {-1649034000 3600 0 CET} {-1635123600 7200 1 CEST} {-1616979600 3600 0 CET} {-1604278800 7200 1 CEST} {-1585530000 3600 0 CET} {-1571014800 7200 1 CEST} {-1555290000 3600 0 CET} {-932432400 7200 1 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-781052400 7200 0 CEST} {-766717200 3600 0 CET} {-750898800 7200 1 CEST} {-733359600 3600 0 CET} {-719456400 7200 1 CEST} {-701917200 3600 0 CET} {-689209200 7200 1 CEST} {-670460400 3600 0 CET} {-114051600 7200 1 CEST} {-103168800 3600 0 CET} {-81997200 7200 1 CEST} {-71719200 3600 0 CET} {-50547600 7200 1 CEST} {-40269600 3600 0 CET} {-18493200 7200 1 CEST} {-8215200 3600 0 CET} {12956400 7200 1 CEST} {23234400 3600 0 CET} {43801200 7200 1 CEST} {54687600 3600 0 CET} {75855600 7200 1 CEST} {86738400 3600 0 CET} {102380400 7200 0 CEST} {118105200 3600 0 CET} {135730800 7200 1 CEST} {148518000 3600 0 CET} {167187600 7200 1 CEST} {180489600 3600 0 CET} {198637200 7200 1 CEST} {211939200 3600 0 CET} {230086800 7200 1 CEST} {243388800 3600 0 CET} {261536400 7200 1 CEST} {274838400 3600 0 CET} {292986000 7200 1 CEST} {306288000 3600 0 CET} {323312400 7200 1 CEST} {338342400 3600 0 CET} {347151600 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Europe/Budapest0000644000175000017500000001744712663660066017471 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Europe/Budapest) { {-9223372036854775808 4580 0 LMT} {-2500938980 3600 0 CET} {-1693706400 7200 1 CEST} {-1680483600 3600 0 CET} {-1663455600 7200 1 CEST} {-1650150000 3600 0 CET} {-1640998800 3600 0 CET} {-1633212000 7200 1 CEST} {-1618700400 3600 0 CET} {-1600466400 7200 1 CEST} {-1581202800 3600 0 CET} {-906771600 3600 0 CET} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-788922000 3600 0 CET} {-778471200 7200 1 CEST} {-762660000 3600 0 CET} {-749689200 7200 1 CEST} {-733359600 3600 0 CET} {-717634800 7200 1 CEST} {-701910000 3600 0 CET} {-686185200 7200 1 CEST} {-670460400 3600 0 CET} {-654130800 7200 1 CEST} {-639010800 3600 0 CET} {-621990000 7200 1 CEST} {-605660400 3600 0 CET} {-492656400 7200 1 CEST} {-481168800 3600 0 CET} {-461120400 7200 1 CEST} {-449632800 3600 0 CET} {-428547600 7200 1 CEST} {-418269600 3600 0 CET} {-397094400 7200 1 CEST} {-386809200 3600 0 CET} {323827200 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Zulu0000644000175000017500000000022512661614722015400 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/UTC)]} { LoadTimeZoneFile Etc/UTC } set TZData(:Zulu) $TZData(:Etc/UTC) tcl8.6.5/library/tzdata/Hongkong0000644000175000017500000000025612661614722016217 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Hong_Kong)]} { LoadTimeZoneFile Asia/Hong_Kong } set TZData(:Hongkong) $TZData(:Asia/Hong_Kong) tcl8.6.5/library/tzdata/UTC0000644000175000017500000000022412661614722015073 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/UTC)]} { LoadTimeZoneFile Etc/UTC } set TZData(:UTC) $TZData(:Etc/UTC) tcl8.6.5/library/tzdata/Libya0000644000175000017500000000025312661614722015502 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Tripoli)]} { LoadTimeZoneFile Africa/Tripoli } set TZData(:Libya) $TZData(:Africa/Tripoli) tcl8.6.5/library/tzdata/Iran0000644000175000017500000000024112661614722015330 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Tehran)]} { LoadTimeZoneFile Asia/Tehran } set TZData(:Iran) $TZData(:Asia/Tehran) tcl8.6.5/library/tzdata/Portugal0000644000175000017500000000025312661614722016237 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Lisbon)]} { LoadTimeZoneFile Europe/Lisbon } set TZData(:Portugal) $TZData(:Europe/Lisbon) tcl8.6.5/library/tzdata/Asia/0000755000175000017500000000000012665173607015402 5ustar sergeisergeitcl8.6.5/library/tzdata/Asia/Tokyo0000644000175000017500000000066312663660066016435 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Tokyo) { {-9223372036854775808 33539 0 LMT} {-2587712400 32400 0 JST} {-2335251600 32400 0 JCST} {-1017824400 32400 0 JST} {-683794800 36000 1 JDT} {-672393600 32400 0 JST} {-654764400 36000 1 JDT} {-640944000 32400 0 JST} {-620290800 36000 1 JDT} {-609494400 32400 0 JST} {-588841200 36000 1 JDT} {-578044800 32400 0 JST} } tcl8.6.5/library/tzdata/Asia/Macau0000644000175000017500000000240612661614721016346 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Macau) { {-9223372036854775808 27260 0 LMT} {-1830411260 28800 0 MOT} {-277360200 32400 1 MOST} {-257405400 28800 0 MOT} {-245910600 32400 1 MOST} {-225955800 28800 0 MOT} {-214473600 32400 1 MOST} {-194506200 28800 0 MOT} {-182406600 32400 1 MOST} {-163056600 28800 0 MOT} {-150969600 32400 1 MOST} {-131619600 28800 0 MOT} {-117088200 32400 1 MOST} {-101367000 28800 0 MOT} {-85638600 32400 1 MOST} {-69312600 28800 0 MOT} {-53584200 32400 1 MOST} {-37863000 28800 0 MOT} {-22134600 32400 1 MOST} {-6413400 28800 0 MOT} {9315000 32400 1 MOST} {25036200 28800 0 MOT} {40764600 32400 1 MOST} {56485800 28800 0 MOT} {72201600 32400 1 MOST} {87922800 28800 0 MOT} {103651200 32400 1 MOST} {119977200 28800 0 MOT} {135705600 32400 1 MOST} {151439400 28800 0 MOT} {167167800 32400 1 MOST} {182889000 28800 0 MOT} {198617400 32400 1 MOST} {214338600 28800 0 MOT} {230067000 32400 1 MOST} {245788200 28800 0 MOT} {261504000 32400 1 MOST} {277225200 28800 0 MOT} {292953600 32400 1 MOST} {309279600 28800 0 MOT} {325008000 32400 1 MOST} {340729200 28800 0 MOT} } tcl8.6.5/library/tzdata/Asia/Harbin0000644000175000017500000000025612663660066016531 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Shanghai)]} { LoadTimeZoneFile Asia/Shanghai } set TZData(:Asia/Harbin) $TZData(:Asia/Shanghai) tcl8.6.5/library/tzdata/Asia/Dushanbe0000644000175000017500000000147112661614721017052 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Dushanbe) { {-9223372036854775808 16512 0 LMT} {-1441168512 18000 0 DUST} {-1247547600 21600 0 DUST} {354909600 25200 1 DUSST} {370717200 21600 0 DUST} {386445600 25200 1 DUSST} {402253200 21600 0 DUST} {417981600 25200 1 DUSST} {433789200 21600 0 DUST} {449604000 25200 1 DUSST} {465336000 21600 0 DUST} {481060800 25200 1 DUSST} {496785600 21600 0 DUST} {512510400 25200 1 DUSST} {528235200 21600 0 DUST} {543960000 25200 1 DUSST} {559684800 21600 0 DUST} {575409600 25200 1 DUSST} {591134400 21600 0 DUST} {606859200 25200 1 DUSST} {622584000 21600 0 DUST} {638308800 25200 1 DUSST} {654638400 21600 0 DUST} {670363200 21600 1 DUSST} {684363600 18000 0 TJT} } tcl8.6.5/library/tzdata/Asia/Irkutsk0000644000175000017500000000411212663660066016755 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Irkutsk) { {-9223372036854775808 25025 0 LMT} {-2840165825 25025 0 IMT} {-1575874625 25200 0 IRKT} {-1247554800 28800 0 IRKMMTT} {354902400 32400 1 IRKST} {370710000 28800 0 IRKT} {386438400 32400 1 IRKST} {402246000 28800 0 IRKT} {417974400 32400 1 IRKST} {433782000 28800 0 IRKT} {449596800 32400 1 IRKST} {465328800 28800 0 IRKT} {481053600 32400 1 IRKST} {496778400 28800 0 IRKT} {512503200 32400 1 IRKST} {528228000 28800 0 IRKT} {543952800 32400 1 IRKST} {559677600 28800 0 IRKT} {575402400 32400 1 IRKST} {591127200 28800 0 IRKT} {606852000 32400 1 IRKST} {622576800 28800 0 IRKT} {638301600 32400 1 IRKST} {654631200 28800 0 IRKT} {670356000 25200 0 IRKMMTT} {670359600 28800 1 IRKST} {686084400 25200 0 IRKT} {695761200 28800 0 IRKMMTT} {701794800 32400 1 IRKST} {717516000 28800 0 IRKT} {733255200 32400 1 IRKST} {748980000 28800 0 IRKT} {764704800 32400 1 IRKST} {780429600 28800 0 IRKT} {796154400 32400 1 IRKST} {811879200 28800 0 IRKT} {828208800 32400 1 IRKST} {846352800 28800 0 IRKT} {859658400 32400 1 IRKST} {877802400 28800 0 IRKT} {891108000 32400 1 IRKST} {909252000 28800 0 IRKT} {922557600 32400 1 IRKST} {941306400 28800 0 IRKT} {954007200 32400 1 IRKST} {972756000 28800 0 IRKT} {985456800 32400 1 IRKST} {1004205600 28800 0 IRKT} {1017511200 32400 1 IRKST} {1035655200 28800 0 IRKT} {1048960800 32400 1 IRKST} {1067104800 28800 0 IRKT} {1080410400 32400 1 IRKST} {1099159200 28800 0 IRKT} {1111860000 32400 1 IRKST} {1130608800 28800 0 IRKT} {1143309600 32400 1 IRKST} {1162058400 28800 0 IRKT} {1174759200 32400 1 IRKST} {1193508000 28800 0 IRKT} {1206813600 32400 1 IRKST} {1224957600 28800 0 IRKT} {1238263200 32400 1 IRKST} {1256407200 28800 0 IRKT} {1269712800 32400 1 IRKST} {1288461600 28800 0 IRKT} {1301162400 32400 0 IRKT} {1414256400 28800 0 IRKT} } tcl8.6.5/library/tzdata/Asia/Dili0000644000175000017500000000040012663660066016176 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Dili) { {-9223372036854775808 30140 0 LMT} {-1830414140 28800 0 TLT} {-879152400 32400 0 JST} {-766054800 32400 0 TLT} {199897200 28800 0 WITA} {969120000 32400 0 TLT} } tcl8.6.5/library/tzdata/Asia/Urumqi0000644000175000017500000000021712663660066016605 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Urumqi) { {-9223372036854775808 21020 0 LMT} {-1325483420 21600 0 XJT} } tcl8.6.5/library/tzdata/Asia/Kuala_Lumpur0000644000175000017500000000055012661614721017717 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Kuala_Lumpur) { {-9223372036854775808 24406 0 LMT} {-2177477206 24925 0 SMT} {-2038200925 25200 0 MALT} {-1167634800 26400 1 MALST} {-1073028000 26400 0 MALT} {-894180000 27000 0 MALT} {-879665400 32400 0 JST} {-767005200 27000 0 MALT} {378664200 28800 0 MYT} } tcl8.6.5/library/tzdata/Asia/Khandyga0000644000175000017500000000415412663660066017055 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Khandyga) { {-9223372036854775808 32533 0 LMT} {-1579424533 28800 0 YAKT} {-1247558400 32400 0 YAKMMTT} {354898800 36000 1 YAKST} {370706400 32400 0 YAKT} {386434800 36000 1 YAKST} {402242400 32400 0 YAKT} {417970800 36000 1 YAKST} {433778400 32400 0 YAKT} {449593200 36000 1 YAKST} {465325200 32400 0 YAKT} {481050000 36000 1 YAKST} {496774800 32400 0 YAKT} {512499600 36000 1 YAKST} {528224400 32400 0 YAKT} {543949200 36000 1 YAKST} {559674000 32400 0 YAKT} {575398800 36000 1 YAKST} {591123600 32400 0 YAKT} {606848400 36000 1 YAKST} {622573200 32400 0 YAKT} {638298000 36000 1 YAKST} {654627600 32400 0 YAKT} {670352400 28800 0 YAKMMTT} {670356000 32400 1 YAKST} {686080800 28800 0 YAKT} {695757600 32400 0 YAKMMTT} {701791200 36000 1 YAKST} {717512400 32400 0 YAKT} {733251600 36000 1 YAKST} {748976400 32400 0 YAKT} {764701200 36000 1 YAKST} {780426000 32400 0 YAKT} {796150800 36000 1 YAKST} {811875600 32400 0 YAKT} {828205200 36000 1 YAKST} {846349200 32400 0 YAKT} {859654800 36000 1 YAKST} {877798800 32400 0 YAKT} {891104400 36000 1 YAKST} {909248400 32400 0 YAKT} {922554000 36000 1 YAKST} {941302800 32400 0 YAKT} {954003600 36000 1 YAKST} {972752400 32400 0 YAKT} {985453200 36000 1 YAKST} {1004202000 32400 0 YAKT} {1017507600 36000 1 YAKST} {1035651600 32400 0 YAKT} {1048957200 36000 1 YAKST} {1067101200 32400 0 YAKT} {1072882800 36000 0 VLAMMTT} {1080403200 39600 1 VLAST} {1099152000 36000 0 VLAT} {1111852800 39600 1 VLAST} {1130601600 36000 0 VLAT} {1143302400 39600 1 VLAST} {1162051200 36000 0 VLAT} {1174752000 39600 1 VLAST} {1193500800 36000 0 VLAT} {1206806400 39600 1 VLAST} {1224950400 36000 0 VLAT} {1238256000 39600 1 VLAST} {1256400000 36000 0 VLAT} {1269705600 39600 1 VLAST} {1288454400 36000 0 VLAT} {1301155200 39600 0 VLAT} {1315832400 36000 0 YAKT} {1414252800 32400 0 YAKT} } tcl8.6.5/library/tzdata/Asia/Qyzylorda0000644000175000017500000000323012661614721017312 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Qyzylorda) { {-9223372036854775808 15712 0 LMT} {-1441167712 14400 0 KIZT} {-1247544000 18000 0 KIZT} {354913200 21600 1 KIZST} {370720800 21600 0 KIZT} {386445600 18000 0 KIZT} {386449200 21600 1 KIZST} {402256800 18000 0 KIZT} {417985200 21600 1 KIZST} {433792800 18000 0 KIZT} {449607600 21600 1 KIZST} {465339600 18000 0 KIZT} {481064400 21600 1 KIZST} {496789200 18000 0 KIZT} {512514000 21600 1 KIZST} {528238800 18000 0 KIZT} {543963600 21600 1 KIZST} {559688400 18000 0 KIZT} {575413200 21600 1 KIZST} {591138000 18000 0 KIZT} {606862800 21600 1 KIZST} {622587600 18000 0 KIZT} {638312400 21600 1 KIZST} {654642000 18000 0 KIZT} {662670000 18000 0 KIZT} {692823600 18000 0 QYZT} {695768400 21600 0 QYZT} {701802000 25200 1 QYZST} {717523200 21600 0 QYZT} {733262400 25200 1 QYZST} {748987200 21600 0 QYZT} {764712000 25200 1 QYZST} {780436800 21600 0 QYZT} {796161600 25200 1 QYZST} {811886400 21600 0 QYZT} {828216000 25200 1 QYZST} {846360000 21600 0 QYZT} {859665600 25200 1 QYZST} {877809600 21600 0 QYZT} {891115200 25200 1 QYZST} {909259200 21600 0 QYZT} {922564800 25200 1 QYZST} {941313600 21600 0 QYZT} {954014400 25200 1 QYZST} {972763200 21600 0 QYZT} {985464000 25200 1 QYZST} {1004212800 21600 0 QYZT} {1017518400 25200 1 QYZST} {1035662400 21600 0 QYZT} {1048968000 25200 1 QYZST} {1067112000 21600 0 QYZT} {1080417600 25200 1 QYZST} {1099166400 21600 0 QYZT} {1110823200 21600 0 QYZT} } tcl8.6.5/library/tzdata/Asia/Jakarta0000644000175000017500000000053612663660066016704 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Jakarta) { {-9223372036854775808 25632 0 LMT} {-3231299232 25632 0 BMT} {-1451719200 26400 0 JAVT} {-1172906400 27000 0 WIB} {-876641400 32400 0 JST} {-766054800 27000 0 WIB} {-683883000 28800 0 WIB} {-620812800 27000 0 WIB} {-189415800 25200 0 WIB} } tcl8.6.5/library/tzdata/Asia/Ust-Nera0000644000175000017500000000405112663660066016761 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Ust-Nera) { {-9223372036854775808 34374 0 LMT} {-1579426374 28800 0 YAKT} {354898800 43200 0 MAGST} {370699200 39600 0 MAGT} {386427600 43200 1 MAGST} {402235200 39600 0 MAGT} {417963600 43200 1 MAGST} {433771200 39600 0 MAGT} {449586000 43200 1 MAGST} {465318000 39600 0 MAGT} {481042800 43200 1 MAGST} {496767600 39600 0 MAGT} {512492400 43200 1 MAGST} {528217200 39600 0 MAGT} {543942000 43200 1 MAGST} {559666800 39600 0 MAGT} {575391600 43200 1 MAGST} {591116400 39600 0 MAGT} {606841200 43200 1 MAGST} {622566000 39600 0 MAGT} {638290800 43200 1 MAGST} {654620400 39600 0 MAGT} {670345200 36000 0 MAGMMTT} {670348800 39600 1 MAGST} {686073600 36000 0 MAGT} {695750400 39600 0 MAGMMTT} {701784000 43200 1 MAGST} {717505200 39600 0 MAGT} {733244400 43200 1 MAGST} {748969200 39600 0 MAGT} {764694000 43200 1 MAGST} {780418800 39600 0 MAGT} {796143600 43200 1 MAGST} {811868400 39600 0 MAGT} {828198000 43200 1 MAGST} {846342000 39600 0 MAGT} {859647600 43200 1 MAGST} {877791600 39600 0 MAGT} {891097200 43200 1 MAGST} {909241200 39600 0 MAGT} {922546800 43200 1 MAGST} {941295600 39600 0 MAGT} {953996400 43200 1 MAGST} {972745200 39600 0 MAGT} {985446000 43200 1 MAGST} {1004194800 39600 0 MAGT} {1017500400 43200 1 MAGST} {1035644400 39600 0 MAGT} {1048950000 43200 1 MAGST} {1067094000 39600 0 MAGT} {1080399600 43200 1 MAGST} {1099148400 39600 0 MAGT} {1111849200 43200 1 MAGST} {1130598000 39600 0 MAGT} {1143298800 43200 1 MAGST} {1162047600 39600 0 MAGT} {1174748400 43200 1 MAGST} {1193497200 39600 0 MAGT} {1206802800 43200 1 MAGST} {1224946800 39600 0 MAGT} {1238252400 43200 1 MAGST} {1256396400 39600 0 MAGT} {1269702000 43200 1 MAGST} {1288450800 39600 0 MAGT} {1301151600 43200 0 MAGT} {1315828800 39600 0 VLAT} {1414249200 36000 0 VLAT} } tcl8.6.5/library/tzdata/Asia/Srednekolymsk0000644000175000017500000000406212663660066020157 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Srednekolymsk) { {-9223372036854775808 36892 0 LMT} {-1441188892 36000 0 MAGT} {-1247565600 39600 0 MAGMMTT} {354891600 43200 1 MAGST} {370699200 39600 0 MAGT} {386427600 43200 1 MAGST} {402235200 39600 0 MAGT} {417963600 43200 1 MAGST} {433771200 39600 0 MAGT} {449586000 43200 1 MAGST} {465318000 39600 0 MAGT} {481042800 43200 1 MAGST} {496767600 39600 0 MAGT} {512492400 43200 1 MAGST} {528217200 39600 0 MAGT} {543942000 43200 1 MAGST} {559666800 39600 0 MAGT} {575391600 43200 1 MAGST} {591116400 39600 0 MAGT} {606841200 43200 1 MAGST} {622566000 39600 0 MAGT} {638290800 43200 1 MAGST} {654620400 39600 0 MAGT} {670345200 36000 0 MAGMMTT} {670348800 39600 1 MAGST} {686073600 36000 0 MAGT} {695750400 39600 0 MAGMMTT} {701784000 43200 1 MAGST} {717505200 39600 0 MAGT} {733244400 43200 1 MAGST} {748969200 39600 0 MAGT} {764694000 43200 1 MAGST} {780418800 39600 0 MAGT} {796143600 43200 1 MAGST} {811868400 39600 0 MAGT} {828198000 43200 1 MAGST} {846342000 39600 0 MAGT} {859647600 43200 1 MAGST} {877791600 39600 0 MAGT} {891097200 43200 1 MAGST} {909241200 39600 0 MAGT} {922546800 43200 1 MAGST} {941295600 39600 0 MAGT} {953996400 43200 1 MAGST} {972745200 39600 0 MAGT} {985446000 43200 1 MAGST} {1004194800 39600 0 MAGT} {1017500400 43200 1 MAGST} {1035644400 39600 0 MAGT} {1048950000 43200 1 MAGST} {1067094000 39600 0 MAGT} {1080399600 43200 1 MAGST} {1099148400 39600 0 MAGT} {1111849200 43200 1 MAGST} {1130598000 39600 0 MAGT} {1143298800 43200 1 MAGST} {1162047600 39600 0 MAGT} {1174748400 43200 1 MAGST} {1193497200 39600 0 MAGT} {1206802800 43200 1 MAGST} {1224946800 39600 0 MAGT} {1238252400 43200 1 MAGST} {1256396400 39600 0 MAGT} {1269702000 43200 1 MAGST} {1288450800 39600 0 MAGT} {1301151600 43200 0 MAGT} {1414245600 39600 0 SRET} } tcl8.6.5/library/tzdata/Asia/Ashkhabad0000644000175000017500000000026112661614722017164 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Ashgabat)]} { LoadTimeZoneFile Asia/Ashgabat } set TZData(:Asia/Ashkhabad) $TZData(:Asia/Ashgabat) tcl8.6.5/library/tzdata/Asia/Katmandu0000644000175000017500000000026312663653132017064 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Kathmandu)]} { LoadTimeZoneFile Asia/Kathmandu } set TZData(:Asia/Katmandu) $TZData(:Asia/Kathmandu) tcl8.6.5/library/tzdata/Asia/Baku0000644000175000017500000001565712661614721016216 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Baku) { {-9223372036854775808 11964 0 LMT} {-1441163964 10800 0 BAKT} {-405140400 14400 0 BAKT} {354916800 18000 1 BAKST} {370724400 14400 0 BAKT} {386452800 18000 1 BAKST} {402260400 14400 0 BAKT} {417988800 18000 1 BAKST} {433796400 14400 0 BAKT} {449611200 18000 1 BAKST} {465343200 14400 0 BAKT} {481068000 18000 1 BAKST} {496792800 14400 0 BAKT} {512517600 18000 1 BAKST} {528242400 14400 0 BAKT} {543967200 18000 1 BAKST} {559692000 14400 0 BAKT} {575416800 18000 1 BAKST} {591141600 14400 0 BAKT} {606866400 18000 1 BAKST} {622591200 14400 0 BAKT} {638316000 18000 1 BAKST} {654645600 14400 0 BAKT} {670370400 14400 1 BAKST} {683496000 14400 0 AZST} {686098800 10800 0 AZT} {701812800 14400 1 AZST} {717537600 14400 0 AZT} {820440000 14400 0 AZT} {828234000 18000 1 AZST} {846378000 14400 0 AZT} {852062400 14400 0 AZT} {859680000 18000 1 AZST} {877824000 14400 0 AZT} {891129600 18000 1 AZST} {909273600 14400 0 AZT} {922579200 18000 1 AZST} {941328000 14400 0 AZT} {954028800 18000 1 AZST} {972777600 14400 0 AZT} {985478400 18000 1 AZST} {1004227200 14400 0 AZT} {1017532800 18000 1 AZST} {1035676800 14400 0 AZT} {1048982400 18000 1 AZST} {1067126400 14400 0 AZT} {1080432000 18000 1 AZST} {1099180800 14400 0 AZT} {1111881600 18000 1 AZST} {1130630400 14400 0 AZT} {1143331200 18000 1 AZST} {1162080000 14400 0 AZT} {1174780800 18000 1 AZST} {1193529600 14400 0 AZT} {1206835200 18000 1 AZST} {1224979200 14400 0 AZT} {1238284800 18000 1 AZST} {1256428800 14400 0 AZT} {1269734400 18000 1 AZST} {1288483200 14400 0 AZT} {1301184000 18000 1 AZST} {1319932800 14400 0 AZT} {1332633600 18000 1 AZST} {1351382400 14400 0 AZT} {1364688000 18000 1 AZST} {1382832000 14400 0 AZT} {1396137600 18000 1 AZST} {1414281600 14400 0 AZT} {1427587200 18000 1 AZST} {1445731200 14400 0 AZT} {1459036800 18000 1 AZST} {1477785600 14400 0 AZT} {1490486400 18000 1 AZST} {1509235200 14400 0 AZT} {1521936000 18000 1 AZST} {1540684800 14400 0 AZT} {1553990400 18000 1 AZST} {1572134400 14400 0 AZT} {1585440000 18000 1 AZST} {1603584000 14400 0 AZT} {1616889600 18000 1 AZST} {1635638400 14400 0 AZT} {1648339200 18000 1 AZST} {1667088000 14400 0 AZT} {1679788800 18000 1 AZST} {1698537600 14400 0 AZT} {1711843200 18000 1 AZST} {1729987200 14400 0 AZT} {1743292800 18000 1 AZST} {1761436800 14400 0 AZT} {1774742400 18000 1 AZST} {1792886400 14400 0 AZT} {1806192000 18000 1 AZST} {1824940800 14400 0 AZT} {1837641600 18000 1 AZST} {1856390400 14400 0 AZT} {1869091200 18000 1 AZST} {1887840000 14400 0 AZT} {1901145600 18000 1 AZST} {1919289600 14400 0 AZT} {1932595200 18000 1 AZST} {1950739200 14400 0 AZT} {1964044800 18000 1 AZST} {1982793600 14400 0 AZT} {1995494400 18000 1 AZST} {2014243200 14400 0 AZT} {2026944000 18000 1 AZST} {2045692800 14400 0 AZT} {2058393600 18000 1 AZST} {2077142400 14400 0 AZT} {2090448000 18000 1 AZST} {2108592000 14400 0 AZT} {2121897600 18000 1 AZST} {2140041600 14400 0 AZT} {2153347200 18000 1 AZST} {2172096000 14400 0 AZT} {2184796800 18000 1 AZST} {2203545600 14400 0 AZT} {2216246400 18000 1 AZST} {2234995200 14400 0 AZT} {2248300800 18000 1 AZST} {2266444800 14400 0 AZT} {2279750400 18000 1 AZST} {2297894400 14400 0 AZT} {2311200000 18000 1 AZST} {2329344000 14400 0 AZT} {2342649600 18000 1 AZST} {2361398400 14400 0 AZT} {2374099200 18000 1 AZST} {2392848000 14400 0 AZT} {2405548800 18000 1 AZST} {2424297600 14400 0 AZT} {2437603200 18000 1 AZST} {2455747200 14400 0 AZT} {2469052800 18000 1 AZST} {2487196800 14400 0 AZT} {2500502400 18000 1 AZST} {2519251200 14400 0 AZT} {2531952000 18000 1 AZST} {2550700800 14400 0 AZT} {2563401600 18000 1 AZST} {2582150400 14400 0 AZT} {2595456000 18000 1 AZST} {2613600000 14400 0 AZT} {2626905600 18000 1 AZST} {2645049600 14400 0 AZT} {2658355200 18000 1 AZST} {2676499200 14400 0 AZT} {2689804800 18000 1 AZST} {2708553600 14400 0 AZT} {2721254400 18000 1 AZST} {2740003200 14400 0 AZT} {2752704000 18000 1 AZST} {2771452800 14400 0 AZT} {2784758400 18000 1 AZST} {2802902400 14400 0 AZT} {2816208000 18000 1 AZST} {2834352000 14400 0 AZT} {2847657600 18000 1 AZST} {2866406400 14400 0 AZT} {2879107200 18000 1 AZST} {2897856000 14400 0 AZT} {2910556800 18000 1 AZST} {2929305600 14400 0 AZT} {2942006400 18000 1 AZST} {2960755200 14400 0 AZT} {2974060800 18000 1 AZST} {2992204800 14400 0 AZT} {3005510400 18000 1 AZST} {3023654400 14400 0 AZT} {3036960000 18000 1 AZST} {3055708800 14400 0 AZT} {3068409600 18000 1 AZST} {3087158400 14400 0 AZT} {3099859200 18000 1 AZST} {3118608000 14400 0 AZT} {3131913600 18000 1 AZST} {3150057600 14400 0 AZT} {3163363200 18000 1 AZST} {3181507200 14400 0 AZT} {3194812800 18000 1 AZST} {3212956800 14400 0 AZT} {3226262400 18000 1 AZST} {3245011200 14400 0 AZT} {3257712000 18000 1 AZST} {3276460800 14400 0 AZT} {3289161600 18000 1 AZST} {3307910400 14400 0 AZT} {3321216000 18000 1 AZST} {3339360000 14400 0 AZT} {3352665600 18000 1 AZST} {3370809600 14400 0 AZT} {3384115200 18000 1 AZST} {3402864000 14400 0 AZT} {3415564800 18000 1 AZST} {3434313600 14400 0 AZT} {3447014400 18000 1 AZST} {3465763200 14400 0 AZT} {3479068800 18000 1 AZST} {3497212800 14400 0 AZT} {3510518400 18000 1 AZST} {3528662400 14400 0 AZT} {3541968000 18000 1 AZST} {3560112000 14400 0 AZT} {3573417600 18000 1 AZST} {3592166400 14400 0 AZT} {3604867200 18000 1 AZST} {3623616000 14400 0 AZT} {3636316800 18000 1 AZST} {3655065600 14400 0 AZT} {3668371200 18000 1 AZST} {3686515200 14400 0 AZT} {3699820800 18000 1 AZST} {3717964800 14400 0 AZT} {3731270400 18000 1 AZST} {3750019200 14400 0 AZT} {3762720000 18000 1 AZST} {3781468800 14400 0 AZT} {3794169600 18000 1 AZST} {3812918400 14400 0 AZT} {3825619200 18000 1 AZST} {3844368000 14400 0 AZT} {3857673600 18000 1 AZST} {3875817600 14400 0 AZT} {3889123200 18000 1 AZST} {3907267200 14400 0 AZT} {3920572800 18000 1 AZST} {3939321600 14400 0 AZT} {3952022400 18000 1 AZST} {3970771200 14400 0 AZT} {3983472000 18000 1 AZST} {4002220800 14400 0 AZT} {4015526400 18000 1 AZST} {4033670400 14400 0 AZT} {4046976000 18000 1 AZST} {4065120000 14400 0 AZT} {4078425600 18000 1 AZST} {4096569600 14400 0 AZT} } tcl8.6.5/library/tzdata/Asia/Anadyr0000644000175000017500000000411612663653454016546 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Anadyr) { {-9223372036854775808 42596 0 LMT} {-1441194596 43200 0 ANAT} {-1247572800 46800 0 ANAMMTT} {354884400 50400 1 ANAST} {370692000 46800 0 ANAT} {386420400 43200 0 ANAMMTT} {386424000 46800 1 ANAST} {402231600 43200 0 ANAT} {417960000 46800 1 ANAST} {433767600 43200 0 ANAT} {449582400 46800 1 ANAST} {465314400 43200 0 ANAT} {481039200 46800 1 ANAST} {496764000 43200 0 ANAT} {512488800 46800 1 ANAST} {528213600 43200 0 ANAT} {543938400 46800 1 ANAST} {559663200 43200 0 ANAT} {575388000 46800 1 ANAST} {591112800 43200 0 ANAT} {606837600 46800 1 ANAST} {622562400 43200 0 ANAT} {638287200 46800 1 ANAST} {654616800 43200 0 ANAT} {670341600 39600 0 ANAMMTT} {670345200 43200 1 ANAST} {686070000 39600 0 ANAT} {695746800 43200 0 ANAMMTT} {701780400 46800 1 ANAST} {717501600 43200 0 ANAT} {733240800 46800 1 ANAST} {748965600 43200 0 ANAT} {764690400 46800 1 ANAST} {780415200 43200 0 ANAT} {796140000 46800 1 ANAST} {811864800 43200 0 ANAT} {828194400 46800 1 ANAST} {846338400 43200 0 ANAT} {859644000 46800 1 ANAST} {877788000 43200 0 ANAT} {891093600 46800 1 ANAST} {909237600 43200 0 ANAT} {922543200 46800 1 ANAST} {941292000 43200 0 ANAT} {953992800 46800 1 ANAST} {972741600 43200 0 ANAT} {985442400 46800 1 ANAST} {1004191200 43200 0 ANAT} {1017496800 46800 1 ANAST} {1035640800 43200 0 ANAT} {1048946400 46800 1 ANAST} {1067090400 43200 0 ANAT} {1080396000 46800 1 ANAST} {1099144800 43200 0 ANAT} {1111845600 46800 1 ANAST} {1130594400 43200 0 ANAT} {1143295200 46800 1 ANAST} {1162044000 43200 0 ANAT} {1174744800 46800 1 ANAST} {1193493600 43200 0 ANAT} {1206799200 46800 1 ANAST} {1224943200 43200 0 ANAT} {1238248800 46800 1 ANAST} {1256392800 43200 0 ANAT} {1269698400 39600 0 ANAMMTT} {1269702000 43200 1 ANAST} {1288450800 39600 0 ANAT} {1301151600 43200 0 ANAT} } tcl8.6.5/library/tzdata/Asia/Colombo0000644000175000017500000000053312661614721016711 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Colombo) { {-9223372036854775808 19164 0 LMT} {-2840159964 19172 0 MMT} {-2019705572 19800 0 IST} {-883287000 21600 1 IHST} {-862639200 23400 1 IST} {-764051400 19800 0 IST} {832962600 23400 0 LKT} {846266400 21600 0 LKT} {1145039400 19800 0 IST} } tcl8.6.5/library/tzdata/Asia/Makassar0000644000175000017500000000035312663660066017066 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Makassar) { {-9223372036854775808 28656 0 LMT} {-1577951856 28656 0 MMT} {-1172908656 28800 0 WITA} {-880272000 32400 0 JST} {-766054800 28800 0 WITA} } tcl8.6.5/library/tzdata/Asia/Baghdad0000644000175000017500000000315312661614721016632 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Baghdad) { {-9223372036854775808 10660 0 LMT} {-2524532260 10656 0 BMT} {-1641005856 10800 0 AST} {389048400 14400 0 ADT} {402264000 10800 0 AST} {417906000 14400 1 ADT} {433800000 10800 0 AST} {449614800 14400 1 ADT} {465422400 10800 0 AST} {481150800 14400 1 ADT} {496792800 10800 0 AST} {512517600 14400 1 ADT} {528242400 10800 0 AST} {543967200 14400 1 ADT} {559692000 10800 0 AST} {575416800 14400 1 ADT} {591141600 10800 0 AST} {606866400 14400 1 ADT} {622591200 10800 0 AST} {638316000 14400 1 ADT} {654645600 10800 0 AST} {670464000 14400 1 ADT} {686275200 10800 0 AST} {702086400 14400 1 ADT} {717897600 10800 0 AST} {733622400 14400 1 ADT} {749433600 10800 0 AST} {765158400 14400 1 ADT} {780969600 10800 0 AST} {796694400 14400 1 ADT} {812505600 10800 0 AST} {828316800 14400 1 ADT} {844128000 10800 0 AST} {859852800 14400 1 ADT} {875664000 10800 0 AST} {891388800 14400 1 ADT} {907200000 10800 0 AST} {922924800 14400 1 ADT} {938736000 10800 0 AST} {954547200 14400 1 ADT} {970358400 10800 0 AST} {986083200 14400 1 ADT} {1001894400 10800 0 AST} {1017619200 14400 1 ADT} {1033430400 10800 0 AST} {1049155200 14400 1 ADT} {1064966400 10800 0 AST} {1080777600 14400 1 ADT} {1096588800 10800 0 AST} {1112313600 14400 1 ADT} {1128124800 10800 0 AST} {1143849600 14400 1 ADT} {1159660800 10800 0 AST} {1175385600 14400 1 ADT} {1191196800 10800 0 AST} } tcl8.6.5/library/tzdata/Asia/Thimbu0000644000175000017500000000025312661614722016547 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Thimphu)]} { LoadTimeZoneFile Asia/Thimphu } set TZData(:Asia/Thimbu) $TZData(:Asia/Thimphu) tcl8.6.5/library/tzdata/Asia/Beirut0000644000175000017500000001711212661614721016552 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Beirut) { {-9223372036854775808 8520 0 LMT} {-2840149320 7200 0 EET} {-1570413600 10800 1 EEST} {-1552186800 7200 0 EET} {-1538359200 10800 1 EEST} {-1522551600 7200 0 EET} {-1507514400 10800 1 EEST} {-1490583600 7200 0 EET} {-1473645600 10800 1 EEST} {-1460948400 7200 0 EET} {-399866400 10800 1 EEST} {-386650800 7200 0 EET} {-368330400 10800 1 EEST} {-355114800 7200 0 EET} {-336794400 10800 1 EEST} {-323578800 7200 0 EET} {-305172000 10800 1 EEST} {-291956400 7200 0 EET} {-273636000 10800 1 EEST} {-260420400 7200 0 EET} {78012000 10800 1 EEST} {86734800 7200 0 EET} {105055200 10800 1 EEST} {118270800 7200 0 EET} {136591200 10800 1 EEST} {149806800 7200 0 EET} {168127200 10800 1 EEST} {181342800 7200 0 EET} {199749600 10800 1 EEST} {212965200 7200 0 EET} {231285600 10800 1 EEST} {244501200 7200 0 EET} {262735200 10800 1 EEST} {275950800 7200 0 EET} {452210400 10800 1 EEST} {466722000 7200 0 EET} {483746400 10800 1 EEST} {498258000 7200 0 EET} {515282400 10800 1 EEST} {529794000 7200 0 EET} {546818400 10800 1 EEST} {561330000 7200 0 EET} {581119200 10800 1 EEST} {592952400 7200 0 EET} {610754400 10800 1 EEST} {624488400 7200 0 EET} {641512800 10800 1 EEST} {656024400 7200 0 EET} {673048800 10800 1 EEST} {687560400 7200 0 EET} {704671200 10800 1 EEST} {718146000 7200 0 EET} {733269600 10800 1 EEST} {748990800 7200 0 EET} {764719200 10800 1 EEST} {780440400 7200 0 EET} {796168800 10800 1 EEST} {811890000 7200 0 EET} {828223200 10800 1 EEST} {843944400 7200 0 EET} {859672800 10800 1 EEST} {875394000 7200 0 EET} {891122400 10800 1 EEST} {906843600 7200 0 EET} {922572000 10800 1 EEST} {941317200 7200 0 EET} {954021600 10800 1 EEST} {972766800 7200 0 EET} {985471200 10800 1 EEST} {1004216400 7200 0 EET} {1017525600 10800 1 EEST} {1035666000 7200 0 EET} {1048975200 10800 1 EEST} {1067115600 7200 0 EET} {1080424800 10800 1 EEST} {1099170000 7200 0 EET} {1111874400 10800 1 EEST} {1130619600 7200 0 EET} {1143324000 10800 1 EEST} {1162069200 7200 0 EET} {1174773600 10800 1 EEST} {1193518800 7200 0 EET} {1206828000 10800 1 EEST} {1224968400 7200 0 EET} {1238277600 10800 1 EEST} {1256418000 7200 0 EET} {1269727200 10800 1 EEST} {1288472400 7200 0 EET} {1301176800 10800 1 EEST} {1319922000 7200 0 EET} {1332626400 10800 1 EEST} {1351371600 7200 0 EET} {1364680800 10800 1 EEST} {1382821200 7200 0 EET} {1396130400 10800 1 EEST} {1414270800 7200 0 EET} {1427580000 10800 1 EEST} {1445720400 7200 0 EET} {1459029600 10800 1 EEST} {1477774800 7200 0 EET} {1490479200 10800 1 EEST} {1509224400 7200 0 EET} {1521928800 10800 1 EEST} {1540674000 7200 0 EET} {1553983200 10800 1 EEST} {1572123600 7200 0 EET} {1585432800 10800 1 EEST} {1603573200 7200 0 EET} {1616882400 10800 1 EEST} {1635627600 7200 0 EET} {1648332000 10800 1 EEST} {1667077200 7200 0 EET} {1679781600 10800 1 EEST} {1698526800 7200 0 EET} {1711836000 10800 1 EEST} {1729976400 7200 0 EET} {1743285600 10800 1 EEST} {1761426000 7200 0 EET} {1774735200 10800 1 EEST} {1792875600 7200 0 EET} {1806184800 10800 1 EEST} {1824930000 7200 0 EET} {1837634400 10800 1 EEST} {1856379600 7200 0 EET} {1869084000 10800 1 EEST} {1887829200 7200 0 EET} {1901138400 10800 1 EEST} {1919278800 7200 0 EET} {1932588000 10800 1 EEST} {1950728400 7200 0 EET} {1964037600 10800 1 EEST} {1982782800 7200 0 EET} {1995487200 10800 1 EEST} {2014232400 7200 0 EET} {2026936800 10800 1 EEST} {2045682000 7200 0 EET} {2058386400 10800 1 EEST} {2077131600 7200 0 EET} {2090440800 10800 1 EEST} {2108581200 7200 0 EET} {2121890400 10800 1 EEST} {2140030800 7200 0 EET} {2153340000 10800 1 EEST} {2172085200 7200 0 EET} {2184789600 10800 1 EEST} {2203534800 7200 0 EET} {2216239200 10800 1 EEST} {2234984400 7200 0 EET} {2248293600 10800 1 EEST} {2266434000 7200 0 EET} {2279743200 10800 1 EEST} {2297883600 7200 0 EET} {2311192800 10800 1 EEST} {2329333200 7200 0 EET} {2342642400 10800 1 EEST} {2361387600 7200 0 EET} {2374092000 10800 1 EEST} {2392837200 7200 0 EET} {2405541600 10800 1 EEST} {2424286800 7200 0 EET} {2437596000 10800 1 EEST} {2455736400 7200 0 EET} {2469045600 10800 1 EEST} {2487186000 7200 0 EET} {2500495200 10800 1 EEST} {2519240400 7200 0 EET} {2531944800 10800 1 EEST} {2550690000 7200 0 EET} {2563394400 10800 1 EEST} {2582139600 7200 0 EET} {2595448800 10800 1 EEST} {2613589200 7200 0 EET} {2626898400 10800 1 EEST} {2645038800 7200 0 EET} {2658348000 10800 1 EEST} {2676488400 7200 0 EET} {2689797600 10800 1 EEST} {2708542800 7200 0 EET} {2721247200 10800 1 EEST} {2739992400 7200 0 EET} {2752696800 10800 1 EEST} {2771442000 7200 0 EET} {2784751200 10800 1 EEST} {2802891600 7200 0 EET} {2816200800 10800 1 EEST} {2834341200 7200 0 EET} {2847650400 10800 1 EEST} {2866395600 7200 0 EET} {2879100000 10800 1 EEST} {2897845200 7200 0 EET} {2910549600 10800 1 EEST} {2929294800 7200 0 EET} {2941999200 10800 1 EEST} {2960744400 7200 0 EET} {2974053600 10800 1 EEST} {2992194000 7200 0 EET} {3005503200 10800 1 EEST} {3023643600 7200 0 EET} {3036952800 10800 1 EEST} {3055698000 7200 0 EET} {3068402400 10800 1 EEST} {3087147600 7200 0 EET} {3099852000 10800 1 EEST} {3118597200 7200 0 EET} {3131906400 10800 1 EEST} {3150046800 7200 0 EET} {3163356000 10800 1 EEST} {3181496400 7200 0 EET} {3194805600 10800 1 EEST} {3212946000 7200 0 EET} {3226255200 10800 1 EEST} {3245000400 7200 0 EET} {3257704800 10800 1 EEST} {3276450000 7200 0 EET} {3289154400 10800 1 EEST} {3307899600 7200 0 EET} {3321208800 10800 1 EEST} {3339349200 7200 0 EET} {3352658400 10800 1 EEST} {3370798800 7200 0 EET} {3384108000 10800 1 EEST} {3402853200 7200 0 EET} {3415557600 10800 1 EEST} {3434302800 7200 0 EET} {3447007200 10800 1 EEST} {3465752400 7200 0 EET} {3479061600 10800 1 EEST} {3497202000 7200 0 EET} {3510511200 10800 1 EEST} {3528651600 7200 0 EET} {3541960800 10800 1 EEST} {3560101200 7200 0 EET} {3573410400 10800 1 EEST} {3592155600 7200 0 EET} {3604860000 10800 1 EEST} {3623605200 7200 0 EET} {3636309600 10800 1 EEST} {3655054800 7200 0 EET} {3668364000 10800 1 EEST} {3686504400 7200 0 EET} {3699813600 10800 1 EEST} {3717954000 7200 0 EET} {3731263200 10800 1 EEST} {3750008400 7200 0 EET} {3762712800 10800 1 EEST} {3781458000 7200 0 EET} {3794162400 10800 1 EEST} {3812907600 7200 0 EET} {3825612000 10800 1 EEST} {3844357200 7200 0 EET} {3857666400 10800 1 EEST} {3875806800 7200 0 EET} {3889116000 10800 1 EEST} {3907256400 7200 0 EET} {3920565600 10800 1 EEST} {3939310800 7200 0 EET} {3952015200 10800 1 EEST} {3970760400 7200 0 EET} {3983464800 10800 1 EEST} {4002210000 7200 0 EET} {4015519200 10800 1 EEST} {4033659600 7200 0 EET} {4046968800 10800 1 EEST} {4065109200 7200 0 EET} {4078418400 10800 1 EEST} {4096558800 7200 0 EET} } tcl8.6.5/library/tzdata/Asia/Tashkent0000644000175000017500000000161712663660066017111 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Tashkent) { {-9223372036854775808 16631 0 LMT} {-1441168631 18000 0 TAST} {-1247547600 21600 0 TAST} {354909600 25200 1 TASST} {370717200 21600 0 TAST} {386445600 25200 1 TASST} {402253200 21600 0 TAST} {417981600 25200 1 TASST} {433789200 21600 0 TAST} {449604000 25200 1 TASST} {465336000 21600 0 TAST} {481060800 25200 1 TASST} {496785600 21600 0 TAST} {512510400 25200 1 TASST} {528235200 21600 0 TAST} {543960000 25200 1 TASST} {559684800 21600 0 TAST} {575409600 25200 1 TASST} {591134400 21600 0 TAST} {606859200 25200 1 TASST} {622584000 21600 0 TAST} {638308800 25200 1 TASST} {654638400 21600 0 TAST} {670363200 18000 0 TAST} {670366800 21600 1 TASST} {683665200 21600 0 UZST} {686091600 18000 0 UZT} {694206000 18000 0 UZT} } tcl8.6.5/library/tzdata/Asia/Dacca0000644000175000017500000000024412661614722016312 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Dhaka)]} { LoadTimeZoneFile Asia/Dhaka } set TZData(:Asia/Dacca) $TZData(:Asia/Dhaka) tcl8.6.5/library/tzdata/Asia/Jayapura0000644000175000017500000000031412663660066017075 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Jayapura) { {-9223372036854775808 33768 0 LMT} {-1172913768 32400 0 WIT} {-799491600 34200 0 ACST} {-189423000 32400 0 WIT} } tcl8.6.5/library/tzdata/Asia/Phnom_Penh0000644000175000017500000000025712663660066017362 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Bangkok)]} { LoadTimeZoneFile Asia/Bangkok } set TZData(:Asia/Phnom_Penh) $TZData(:Asia/Bangkok) tcl8.6.5/library/tzdata/Asia/Kuwait0000644000175000017500000000025012663660066016564 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Riyadh)]} { LoadTimeZoneFile Asia/Riyadh } set TZData(:Asia/Kuwait) $TZData(:Asia/Riyadh) tcl8.6.5/library/tzdata/Asia/Krasnoyarsk0000644000175000017500000000406012663660066017632 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Krasnoyarsk) { {-9223372036854775808 22286 0 LMT} {-1577513486 21600 0 KRAT} {-1247551200 25200 0 KRAMMTT} {354906000 28800 1 KRAST} {370713600 25200 0 KRAT} {386442000 28800 1 KRAST} {402249600 25200 0 KRAT} {417978000 28800 1 KRAST} {433785600 25200 0 KRAT} {449600400 28800 1 KRAST} {465332400 25200 0 KRAT} {481057200 28800 1 KRAST} {496782000 25200 0 KRAT} {512506800 28800 1 KRAST} {528231600 25200 0 KRAT} {543956400 28800 1 KRAST} {559681200 25200 0 KRAT} {575406000 28800 1 KRAST} {591130800 25200 0 KRAT} {606855600 28800 1 KRAST} {622580400 25200 0 KRAT} {638305200 28800 1 KRAST} {654634800 25200 0 KRAT} {670359600 21600 0 KRAMMTT} {670363200 25200 1 KRAST} {686088000 21600 0 KRAT} {695764800 25200 0 KRAMMTT} {701798400 28800 1 KRAST} {717519600 25200 0 KRAT} {733258800 28800 1 KRAST} {748983600 25200 0 KRAT} {764708400 28800 1 KRAST} {780433200 25200 0 KRAT} {796158000 28800 1 KRAST} {811882800 25200 0 KRAT} {828212400 28800 1 KRAST} {846356400 25200 0 KRAT} {859662000 28800 1 KRAST} {877806000 25200 0 KRAT} {891111600 28800 1 KRAST} {909255600 25200 0 KRAT} {922561200 28800 1 KRAST} {941310000 25200 0 KRAT} {954010800 28800 1 KRAST} {972759600 25200 0 KRAT} {985460400 28800 1 KRAST} {1004209200 25200 0 KRAT} {1017514800 28800 1 KRAST} {1035658800 25200 0 KRAT} {1048964400 28800 1 KRAST} {1067108400 25200 0 KRAT} {1080414000 28800 1 KRAST} {1099162800 25200 0 KRAT} {1111863600 28800 1 KRAST} {1130612400 25200 0 KRAT} {1143313200 28800 1 KRAST} {1162062000 25200 0 KRAT} {1174762800 28800 1 KRAST} {1193511600 25200 0 KRAT} {1206817200 28800 1 KRAST} {1224961200 25200 0 KRAT} {1238266800 28800 1 KRAST} {1256410800 25200 0 KRAT} {1269716400 28800 1 KRAST} {1288465200 25200 0 KRAT} {1301166000 28800 0 KRAT} {1414260000 25200 0 KRAT} } tcl8.6.5/library/tzdata/Asia/Yekaterinburg0000644000175000017500000000412012663660066020133 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Yekaterinburg) { {-9223372036854775808 14553 0 LMT} {-1688270553 13505 0 PMT} {-1592610305 14400 0 SVET} {-1247544000 18000 0 SVEMMTT} {354913200 21600 1 SVEST} {370720800 18000 0 SVET} {386449200 21600 1 SVEST} {402256800 18000 0 SVET} {417985200 21600 1 SVEST} {433792800 18000 0 SVET} {449607600 21600 1 SVEST} {465339600 18000 0 SVET} {481064400 21600 1 SVEST} {496789200 18000 0 SVET} {512514000 21600 1 SVEST} {528238800 18000 0 SVET} {543963600 21600 1 SVEST} {559688400 18000 0 SVET} {575413200 21600 1 SVEST} {591138000 18000 0 SVET} {606862800 21600 1 SVEST} {622587600 18000 0 SVET} {638312400 21600 1 SVEST} {654642000 18000 0 SVET} {670366800 14400 0 SVEMMTT} {670370400 18000 1 SVEST} {686095200 14400 0 SVET} {695772000 18000 0 YEKMMTT} {701805600 21600 1 YEKST} {717526800 18000 0 YEKT} {733266000 21600 1 YEKST} {748990800 18000 0 YEKT} {764715600 21600 1 YEKST} {780440400 18000 0 YEKT} {796165200 21600 1 YEKST} {811890000 18000 0 YEKT} {828219600 21600 1 YEKST} {846363600 18000 0 YEKT} {859669200 21600 1 YEKST} {877813200 18000 0 YEKT} {891118800 21600 1 YEKST} {909262800 18000 0 YEKT} {922568400 21600 1 YEKST} {941317200 18000 0 YEKT} {954018000 21600 1 YEKST} {972766800 18000 0 YEKT} {985467600 21600 1 YEKST} {1004216400 18000 0 YEKT} {1017522000 21600 1 YEKST} {1035666000 18000 0 YEKT} {1048971600 21600 1 YEKST} {1067115600 18000 0 YEKT} {1080421200 21600 1 YEKST} {1099170000 18000 0 YEKT} {1111870800 21600 1 YEKST} {1130619600 18000 0 YEKT} {1143320400 21600 1 YEKST} {1162069200 18000 0 YEKT} {1174770000 21600 1 YEKST} {1193518800 18000 0 YEKT} {1206824400 21600 1 YEKST} {1224968400 18000 0 YEKT} {1238274000 21600 1 YEKST} {1256418000 18000 0 YEKT} {1269723600 21600 1 YEKST} {1288472400 18000 0 YEKT} {1301173200 21600 0 YEKT} {1414267200 18000 0 YEKT} } tcl8.6.5/library/tzdata/Asia/Yakutsk0000644000175000017500000000405412663660066016761 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Yakutsk) { {-9223372036854775808 31138 0 LMT} {-1579423138 28800 0 YAKT} {-1247558400 32400 0 YAKMMTT} {354898800 36000 1 YAKST} {370706400 32400 0 YAKT} {386434800 36000 1 YAKST} {402242400 32400 0 YAKT} {417970800 36000 1 YAKST} {433778400 32400 0 YAKT} {449593200 36000 1 YAKST} {465325200 32400 0 YAKT} {481050000 36000 1 YAKST} {496774800 32400 0 YAKT} {512499600 36000 1 YAKST} {528224400 32400 0 YAKT} {543949200 36000 1 YAKST} {559674000 32400 0 YAKT} {575398800 36000 1 YAKST} {591123600 32400 0 YAKT} {606848400 36000 1 YAKST} {622573200 32400 0 YAKT} {638298000 36000 1 YAKST} {654627600 32400 0 YAKT} {670352400 28800 0 YAKMMTT} {670356000 32400 1 YAKST} {686080800 28800 0 YAKT} {695757600 32400 0 YAKMMTT} {701791200 36000 1 YAKST} {717512400 32400 0 YAKT} {733251600 36000 1 YAKST} {748976400 32400 0 YAKT} {764701200 36000 1 YAKST} {780426000 32400 0 YAKT} {796150800 36000 1 YAKST} {811875600 32400 0 YAKT} {828205200 36000 1 YAKST} {846349200 32400 0 YAKT} {859654800 36000 1 YAKST} {877798800 32400 0 YAKT} {891104400 36000 1 YAKST} {909248400 32400 0 YAKT} {922554000 36000 1 YAKST} {941302800 32400 0 YAKT} {954003600 36000 1 YAKST} {972752400 32400 0 YAKT} {985453200 36000 1 YAKST} {1004202000 32400 0 YAKT} {1017507600 36000 1 YAKST} {1035651600 32400 0 YAKT} {1048957200 36000 1 YAKST} {1067101200 32400 0 YAKT} {1080406800 36000 1 YAKST} {1099155600 32400 0 YAKT} {1111856400 36000 1 YAKST} {1130605200 32400 0 YAKT} {1143306000 36000 1 YAKST} {1162054800 32400 0 YAKT} {1174755600 36000 1 YAKST} {1193504400 32400 0 YAKT} {1206810000 36000 1 YAKST} {1224954000 32400 0 YAKT} {1238259600 36000 1 YAKST} {1256403600 32400 0 YAKT} {1269709200 36000 1 YAKST} {1288458000 32400 0 YAKT} {1301158800 36000 0 YAKT} {1414252800 32400 0 YAKT} } tcl8.6.5/library/tzdata/Asia/Calcutta0000644000175000017500000000025512661614722017061 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Kolkata)]} { LoadTimeZoneFile Asia/Kolkata } set TZData(:Asia/Calcutta) $TZData(:Asia/Kolkata) tcl8.6.5/library/tzdata/Asia/Nicosia0000644000175000017500000001631012661614721016704 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Nicosia) { {-9223372036854775808 8008 0 LMT} {-1518920008 7200 0 EET} {166572000 10800 1 EEST} {182293200 7200 0 EET} {200959200 10800 1 EEST} {213829200 7200 0 EET} {228866400 10800 1 EEST} {243982800 7200 0 EET} {260316000 10800 1 EEST} {276123600 7200 0 EET} {291765600 10800 1 EEST} {307486800 7200 0 EET} {323820000 10800 1 EEST} {338936400 7200 0 EET} {354664800 10800 1 EEST} {370386000 7200 0 EET} {386114400 10800 1 EEST} {401835600 7200 0 EET} {417564000 10800 1 EEST} {433285200 7200 0 EET} {449013600 10800 1 EEST} {465339600 7200 0 EET} {481068000 10800 1 EEST} {496789200 7200 0 EET} {512517600 10800 1 EEST} {528238800 7200 0 EET} {543967200 10800 1 EEST} {559688400 7200 0 EET} {575416800 10800 1 EEST} {591138000 7200 0 EET} {606866400 10800 1 EEST} {622587600 7200 0 EET} {638316000 10800 1 EEST} {654642000 7200 0 EET} {670370400 10800 1 EEST} {686091600 7200 0 EET} {701820000 10800 1 EEST} {717541200 7200 0 EET} {733269600 10800 1 EEST} {748990800 7200 0 EET} {764719200 10800 1 EEST} {780440400 7200 0 EET} {796168800 10800 1 EEST} {811890000 7200 0 EET} {828223200 10800 1 EEST} {843944400 7200 0 EET} {859672800 10800 1 EEST} {875394000 7200 0 EET} {891122400 10800 1 EEST} {904597200 10800 0 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941331600 7200 0 EET} {954032400 10800 1 EEST} {972781200 7200 0 EET} {985482000 10800 1 EEST} {1004230800 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Asia/Chongqing0000644000175000017500000000026112663660066017237 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Shanghai)]} { LoadTimeZoneFile Asia/Shanghai } set TZData(:Asia/Chongqing) $TZData(:Asia/Shanghai) tcl8.6.5/library/tzdata/Asia/Karachi0000644000175000017500000000066412665113557016673 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Karachi) { {-9223372036854775808 16092 0 LMT} {-1988166492 19800 0 IST} {-862637400 23400 1 IST} {-764145000 19800 0 IST} {-576135000 18000 0 KART} {38775600 18000 0 PKT} {1018119600 21600 1 PKST} {1033840800 18000 0 PKT} {1212260400 21600 1 PKST} {1225476000 18000 0 PKT} {1239735600 21600 1 PKST} {1257012000 18000 0 PKT} } tcl8.6.5/library/tzdata/Asia/Manila0000644000175000017500000000063112661614721016517 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Manila) { {-9223372036854775808 -57360 0 LMT} {-3944621040 29040 0 LMT} {-2229321840 28800 0 PHT} {-1046678400 32400 1 PHST} {-1038733200 28800 0 PHT} {-873273600 32400 0 JST} {-794221200 28800 0 PHT} {-496224000 32400 1 PHST} {-489315600 28800 0 PHT} {259344000 32400 1 PHST} {275151600 28800 0 PHT} } tcl8.6.5/library/tzdata/Asia/Kolkata0000644000175000017500000000040512661614721016703 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Kolkata) { {-9223372036854775808 21208 0 LMT} {-2840162008 21200 0 HMT} {-891582800 23400 0 BURT} {-872058600 19800 0 IST} {-862637400 23400 1 IST} {-764145000 19800 0 IST} } tcl8.6.5/library/tzdata/Asia/Yerevan0000644000175000017500000000373512663660066016744 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Yerevan) { {-9223372036854775808 10680 0 LMT} {-1441162680 10800 0 YERT} {-405140400 14400 0 YERT} {354916800 18000 1 YERST} {370724400 14400 0 YERT} {386452800 18000 1 YERST} {402260400 14400 0 YERT} {417988800 18000 1 YERST} {433796400 14400 0 YERT} {449611200 18000 1 YERST} {465343200 14400 0 YERT} {481068000 18000 1 YERST} {496792800 14400 0 YERT} {512517600 18000 1 YERST} {528242400 14400 0 YERT} {543967200 18000 1 YERST} {559692000 14400 0 YERT} {575416800 18000 1 YERST} {591141600 14400 0 YERT} {606866400 18000 1 YERST} {622591200 14400 0 YERT} {638316000 18000 1 YERST} {654645600 14400 0 YERT} {670370400 14400 1 YERST} {685569600 14400 0 AMST} {686098800 10800 0 AMT} {701812800 14400 1 AMST} {717534000 10800 0 AMT} {733273200 14400 1 AMST} {748998000 10800 0 AMT} {764722800 14400 1 AMST} {780447600 10800 0 AMT} {796172400 14400 1 AMST} {811897200 14400 0 AMT} {852062400 14400 0 AMT} {859672800 18000 1 AMST} {877816800 14400 0 AMT} {891122400 18000 1 AMST} {909266400 14400 0 AMT} {922572000 18000 1 AMST} {941320800 14400 0 AMT} {954021600 18000 1 AMST} {972770400 14400 0 AMT} {985471200 18000 1 AMST} {1004220000 14400 0 AMT} {1017525600 18000 1 AMST} {1035669600 14400 0 AMT} {1048975200 18000 1 AMST} {1067119200 14400 0 AMT} {1080424800 18000 1 AMST} {1099173600 14400 0 AMT} {1111874400 18000 1 AMST} {1130623200 14400 0 AMT} {1143324000 18000 1 AMST} {1162072800 14400 0 AMT} {1174773600 18000 1 AMST} {1193522400 14400 0 AMT} {1206828000 18000 1 AMST} {1224972000 14400 0 AMT} {1238277600 18000 1 AMST} {1256421600 14400 0 AMT} {1269727200 18000 1 AMST} {1288476000 14400 0 AMT} {1301176800 18000 1 AMST} {1319925600 14400 0 AMT} {1332626400 14400 0 AMT} } tcl8.6.5/library/tzdata/Asia/Oral0000644000175000017500000000322312661614721016213 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Oral) { {-9223372036854775808 12324 0 LMT} {-1441164324 14400 0 URAT} {-1247544000 18000 0 URAT} {354913200 21600 1 URAST} {370720800 21600 0 URAT} {386445600 18000 0 URAT} {386449200 21600 1 URAST} {402256800 18000 0 URAT} {417985200 21600 1 URAST} {433792800 18000 0 URAT} {449607600 21600 1 URAST} {465339600 18000 0 URAT} {481064400 21600 1 URAST} {496789200 18000 0 URAT} {512514000 21600 1 URAST} {528238800 18000 0 URAT} {543963600 21600 1 URAST} {559688400 18000 0 URAT} {575413200 21600 1 URAST} {591138000 18000 0 URAT} {606862800 14400 0 URAT} {606866400 18000 1 URAST} {622591200 14400 0 URAT} {638316000 18000 1 URAST} {654645600 14400 0 URAT} {662673600 14400 0 URAT} {692827200 14400 0 ORAT} {701809200 18000 1 ORAST} {717530400 14400 0 ORAT} {733269600 18000 1 ORAST} {748994400 14400 0 ORAT} {764719200 18000 1 ORAST} {780444000 14400 0 ORAT} {796168800 18000 1 ORAST} {811893600 14400 0 ORAT} {828223200 18000 1 ORAST} {846367200 14400 0 ORAT} {859672800 18000 1 ORAST} {877816800 14400 0 ORAT} {891122400 18000 1 ORAST} {909266400 14400 0 ORAT} {922572000 18000 1 ORAST} {941320800 14400 0 ORAT} {954021600 18000 1 ORAST} {972770400 14400 0 ORAT} {985471200 18000 1 ORAST} {1004220000 14400 0 ORAT} {1017525600 18000 1 ORAST} {1035669600 14400 0 ORAT} {1048975200 18000 1 ORAST} {1067119200 14400 0 ORAT} {1080424800 18000 1 ORAST} {1099173600 14400 0 ORAT} {1110830400 18000 0 ORAT} } tcl8.6.5/library/tzdata/Asia/Bishkek0000644000175000017500000000313712661614721016702 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Bishkek) { {-9223372036854775808 17904 0 LMT} {-1441169904 18000 0 FRUT} {-1247547600 21600 0 FRUT} {354909600 25200 1 FRUST} {370717200 21600 0 FRUT} {386445600 25200 1 FRUST} {402253200 21600 0 FRUT} {417981600 25200 1 FRUST} {433789200 21600 0 FRUT} {449604000 25200 1 FRUST} {465336000 21600 0 FRUT} {481060800 25200 1 FRUST} {496785600 21600 0 FRUT} {512510400 25200 1 FRUST} {528235200 21600 0 FRUT} {543960000 25200 1 FRUST} {559684800 21600 0 FRUT} {575409600 25200 1 FRUST} {591134400 21600 0 FRUT} {606859200 25200 1 FRUST} {622584000 21600 0 FRUT} {638308800 25200 1 FRUST} {654638400 21600 0 FRUT} {670363200 21600 1 FRUST} {683582400 21600 0 KGT} {703018800 21600 1 KGST} {717530400 18000 0 KGT} {734468400 21600 1 KGST} {748980000 18000 0 KGT} {765918000 21600 1 KGST} {780429600 18000 0 KGT} {797367600 21600 1 KGST} {811879200 18000 0 KGT} {828817200 21600 1 KGST} {843933600 18000 0 KGT} {859671000 21600 1 KGST} {877811400 18000 0 KGT} {891120600 21600 1 KGST} {909261000 18000 0 KGT} {922570200 21600 1 KGST} {941315400 18000 0 KGT} {954019800 21600 1 KGST} {972765000 18000 0 KGT} {985469400 21600 1 KGST} {1004214600 18000 0 KGT} {1017523800 21600 1 KGST} {1035664200 18000 0 KGT} {1048973400 21600 1 KGST} {1067113800 18000 0 KGT} {1080423000 21600 1 KGST} {1099168200 18000 0 KGT} {1111872600 21600 1 KGST} {1123783200 21600 0 KGT} } tcl8.6.5/library/tzdata/Asia/Ulan_Bator0000644000175000017500000000027312661614722017347 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Ulaanbaatar)]} { LoadTimeZoneFile Asia/Ulaanbaatar } set TZData(:Asia/Ulan_Bator) $TZData(:Asia/Ulaanbaatar) tcl8.6.5/library/tzdata/Asia/Rangoon0000644000175000017500000000035112663660066016725 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Rangoon) { {-9223372036854775808 23080 0 LMT} {-2840163880 23080 0 RMT} {-1577946280 23400 0 BURT} {-873268200 32400 0 JST} {-778410000 23400 0 MMT} } tcl8.6.5/library/tzdata/Asia/Chungking0000644000175000017500000000026112663660066017237 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Shanghai)]} { LoadTimeZoneFile Asia/Shanghai } set TZData(:Asia/Chungking) $TZData(:Asia/Shanghai) tcl8.6.5/library/tzdata/Asia/Almaty0000644000175000017500000000313312661614721016545 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Almaty) { {-9223372036854775808 18468 0 LMT} {-1441170468 18000 0 ALMT} {-1247547600 21600 0 ALMT} {354909600 25200 1 ALMST} {370717200 21600 0 ALMT} {386445600 25200 1 ALMST} {402253200 21600 0 ALMT} {417981600 25200 1 ALMST} {433789200 21600 0 ALMT} {449604000 25200 1 ALMST} {465336000 21600 0 ALMT} {481060800 25200 1 ALMST} {496785600 21600 0 ALMT} {512510400 25200 1 ALMST} {528235200 21600 0 ALMT} {543960000 25200 1 ALMST} {559684800 21600 0 ALMT} {575409600 25200 1 ALMST} {591134400 21600 0 ALMT} {606859200 25200 1 ALMST} {622584000 21600 0 ALMT} {638308800 25200 1 ALMST} {654638400 21600 0 ALMT} {662666400 21600 0 ALMT} {694202400 21600 0 ALMT} {701802000 25200 1 ALMST} {717523200 21600 0 ALMT} {733262400 25200 1 ALMST} {748987200 21600 0 ALMT} {764712000 25200 1 ALMST} {780436800 21600 0 ALMT} {796161600 25200 1 ALMST} {811886400 21600 0 ALMT} {828216000 25200 1 ALMST} {846360000 21600 0 ALMT} {859665600 25200 1 ALMST} {877809600 21600 0 ALMT} {891115200 25200 1 ALMST} {909259200 21600 0 ALMT} {922564800 25200 1 ALMST} {941313600 21600 0 ALMT} {954014400 25200 1 ALMST} {972763200 21600 0 ALMT} {985464000 25200 1 ALMST} {1004212800 21600 0 ALMT} {1017518400 25200 1 ALMST} {1035662400 21600 0 ALMT} {1048968000 25200 1 ALMST} {1067112000 21600 0 ALMT} {1080417600 25200 1 ALMST} {1099166400 21600 0 ALMT} {1110823200 21600 0 ALMT} } tcl8.6.5/library/tzdata/Asia/Brunei0000644000175000017500000000025512661614721016544 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Brunei) { {-9223372036854775808 27580 0 LMT} {-1383464380 27000 0 BNT} {-1167636600 28800 0 BNT} } tcl8.6.5/library/tzdata/Asia/Ho_Chi_Minh0000644000175000017500000000057512663660066017436 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Ho_Chi_Minh) { {-9223372036854775808 25600 0 LMT} {-2004073600 25590 0 PLMT} {-1851577590 25200 0 ICT} {-852105600 28800 0 IDT} {-782643600 32400 0 JST} {-767869200 25200 0 ICT} {-718095600 28800 0 IDT} {-457776000 25200 0 ICT} {-315648000 28800 0 IDT} {171820800 25200 0 ICT} } tcl8.6.5/library/tzdata/Asia/Hebron0000644000175000017500000001740312663660066016545 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Hebron) { {-9223372036854775808 8423 0 LMT} {-2185410023 7200 0 EET} {-933645600 10800 1 EET} {-857358000 7200 0 EET} {-844300800 10800 1 EET} {-825822000 7200 0 EET} {-812685600 10800 1 EET} {-794199600 7200 0 EET} {-779853600 10800 1 EET} {-762656400 7200 0 EET} {-748310400 10800 1 EET} {-731127600 7200 0 EET} {-682653600 7200 0 EET} {-399088800 10800 1 EEST} {-386650800 7200 0 EET} {-368330400 10800 1 EEST} {-355114800 7200 0 EET} {-336790800 10800 1 EEST} {-323654400 7200 0 EET} {-305168400 10800 1 EEST} {-292032000 7200 0 EET} {-273632400 10800 1 EEST} {-260496000 7200 0 EET} {-242096400 10800 1 EEST} {-228960000 7200 0 EET} {-210560400 10800 1 EEST} {-197424000 7200 0 EET} {-178938000 10800 1 EEST} {-165801600 7200 0 EET} {-147402000 10800 1 EEST} {-134265600 7200 0 EET} {-115866000 10800 1 EEST} {-102643200 7200 0 EET} {-84330000 10800 1 EEST} {-81313200 10800 0 IST} {142376400 10800 1 IDT} {150843600 7200 0 IST} {167176800 10800 1 IDT} {178664400 7200 0 IST} {482277600 10800 1 IDT} {495579600 7200 0 IST} {516751200 10800 1 IDT} {526424400 7200 0 IST} {545436000 10800 1 IDT} {558478800 7200 0 IST} {576626400 10800 1 IDT} {589323600 7200 0 IST} {609890400 10800 1 IDT} {620773200 7200 0 IST} {638316000 10800 1 IDT} {651618000 7200 0 IST} {669765600 10800 1 IDT} {683672400 7200 0 IST} {701820000 10800 1 IDT} {715726800 7200 0 IST} {733701600 10800 1 IDT} {747176400 7200 0 IST} {765151200 10800 1 IDT} {778021200 7200 0 IST} {796600800 10800 1 IDT} {810075600 7200 0 IST} {820447200 7200 0 EET} {828655200 10800 1 EEST} {843170400 7200 0 EET} {860104800 10800 1 EEST} {874620000 7200 0 EET} {891554400 10800 1 EEST} {906069600 7200 0 EET} {915141600 7200 0 EET} {924213600 10800 1 EEST} {939934800 7200 0 EET} {956268000 10800 1 EEST} {971989200 7200 0 EET} {987717600 10800 1 EEST} {1003438800 7200 0 EET} {1019167200 10800 1 EEST} {1034888400 7200 0 EET} {1050616800 10800 1 EEST} {1066338000 7200 0 EET} {1082066400 10800 1 EEST} {1096581600 7200 0 EET} {1113516000 10800 1 EEST} {1128380400 7200 0 EET} {1143842400 10800 1 EEST} {1158872400 7200 0 EET} {1175378400 10800 1 EEST} {1189638000 7200 0 EET} {1206655200 10800 1 EEST} {1220216400 7200 0 EET} {1238104800 10800 1 EEST} {1252015200 7200 0 EET} {1269554400 10800 1 EEST} {1281474000 7200 0 EET} {1301608860 10800 1 EEST} {1312146000 7200 0 EET} {1314655200 10800 1 EEST} {1317330000 7200 0 EET} {1333058400 10800 1 EEST} {1348178400 7200 0 EET} {1364508000 10800 1 EEST} {1380229200 7200 0 EET} {1395957600 10800 1 EEST} {1414098000 7200 0 EET} {1427493600 10800 1 EEST} {1445547600 7200 0 EET} {1458943200 10800 1 EEST} {1476997200 7200 0 EET} {1490997600 10800 1 EEST} {1509051600 7200 0 EET} {1522447200 10800 1 EEST} {1540501200 7200 0 EET} {1553896800 10800 1 EEST} {1571950800 7200 0 EET} {1585346400 10800 1 EEST} {1603400400 7200 0 EET} {1616796000 10800 1 EEST} {1634850000 7200 0 EET} {1648245600 10800 1 EEST} {1666299600 7200 0 EET} {1680300000 10800 1 EEST} {1698354000 7200 0 EET} {1711749600 10800 1 EEST} {1729803600 7200 0 EET} {1743199200 10800 1 EEST} {1761253200 7200 0 EET} {1774648800 10800 1 EEST} {1792702800 7200 0 EET} {1806098400 10800 1 EEST} {1824152400 7200 0 EET} {1838152800 10800 1 EEST} {1856206800 7200 0 EET} {1869602400 10800 1 EEST} {1887656400 7200 0 EET} {1901052000 10800 1 EEST} {1919106000 7200 0 EET} {1932501600 10800 1 EEST} {1950555600 7200 0 EET} {1963951200 10800 1 EEST} {1982005200 7200 0 EET} {1995400800 10800 1 EEST} {2013454800 7200 0 EET} {2027455200 10800 1 EEST} {2045509200 7200 0 EET} {2058904800 10800 1 EEST} {2076958800 7200 0 EET} {2090354400 10800 1 EEST} {2108408400 7200 0 EET} {2121804000 10800 1 EEST} {2139858000 7200 0 EET} {2153253600 10800 1 EEST} {2171307600 7200 0 EET} {2184703200 10800 1 EEST} {2202757200 7200 0 EET} {2216757600 10800 1 EEST} {2234811600 7200 0 EET} {2248207200 10800 1 EEST} {2266261200 7200 0 EET} {2279656800 10800 1 EEST} {2297710800 7200 0 EET} {2311106400 10800 1 EEST} {2329160400 7200 0 EET} {2342556000 10800 1 EEST} {2360610000 7200 0 EET} {2374610400 10800 1 EEST} {2392664400 7200 0 EET} {2406060000 10800 1 EEST} {2424114000 7200 0 EET} {2437509600 10800 1 EEST} {2455563600 7200 0 EET} {2468959200 10800 1 EEST} {2487013200 7200 0 EET} {2500408800 10800 1 EEST} {2518462800 7200 0 EET} {2531858400 10800 1 EEST} {2549912400 7200 0 EET} {2563912800 10800 1 EEST} {2581966800 7200 0 EET} {2595362400 10800 1 EEST} {2613416400 7200 0 EET} {2626812000 10800 1 EEST} {2644866000 7200 0 EET} {2658261600 10800 1 EEST} {2676315600 7200 0 EET} {2689711200 10800 1 EEST} {2707765200 7200 0 EET} {2721765600 10800 1 EEST} {2739819600 7200 0 EET} {2753215200 10800 1 EEST} {2771269200 7200 0 EET} {2784664800 10800 1 EEST} {2802718800 7200 0 EET} {2816114400 10800 1 EEST} {2834168400 7200 0 EET} {2847564000 10800 1 EEST} {2865618000 7200 0 EET} {2879013600 10800 1 EEST} {2897067600 7200 0 EET} {2911068000 10800 1 EEST} {2929122000 7200 0 EET} {2942517600 10800 1 EEST} {2960571600 7200 0 EET} {2973967200 10800 1 EEST} {2992021200 7200 0 EET} {3005416800 10800 1 EEST} {3023470800 7200 0 EET} {3036866400 10800 1 EEST} {3054920400 7200 0 EET} {3068316000 10800 1 EEST} {3086370000 7200 0 EET} {3100370400 10800 1 EEST} {3118424400 7200 0 EET} {3131820000 10800 1 EEST} {3149874000 7200 0 EET} {3163269600 10800 1 EEST} {3181323600 7200 0 EET} {3194719200 10800 1 EEST} {3212773200 7200 0 EET} {3226168800 10800 1 EEST} {3244222800 7200 0 EET} {3258223200 10800 1 EEST} {3276277200 7200 0 EET} {3289672800 10800 1 EEST} {3307726800 7200 0 EET} {3321122400 10800 1 EEST} {3339176400 7200 0 EET} {3352572000 10800 1 EEST} {3370626000 7200 0 EET} {3384021600 10800 1 EEST} {3402075600 7200 0 EET} {3415471200 10800 1 EEST} {3433525200 7200 0 EET} {3447525600 10800 1 EEST} {3465579600 7200 0 EET} {3478975200 10800 1 EEST} {3497029200 7200 0 EET} {3510424800 10800 1 EEST} {3528478800 7200 0 EET} {3541874400 10800 1 EEST} {3559928400 7200 0 EET} {3573324000 10800 1 EEST} {3591378000 7200 0 EET} {3605378400 10800 1 EEST} {3623432400 7200 0 EET} {3636828000 10800 1 EEST} {3654882000 7200 0 EET} {3668277600 10800 1 EEST} {3686331600 7200 0 EET} {3699727200 10800 1 EEST} {3717781200 7200 0 EET} {3731176800 10800 1 EEST} {3749230800 7200 0 EET} {3762626400 10800 1 EEST} {3780680400 7200 0 EET} {3794680800 10800 1 EEST} {3812734800 7200 0 EET} {3826130400 10800 1 EEST} {3844184400 7200 0 EET} {3857580000 10800 1 EEST} {3875634000 7200 0 EET} {3889029600 10800 1 EEST} {3907083600 7200 0 EET} {3920479200 10800 1 EEST} {3938533200 7200 0 EET} {3951928800 10800 1 EEST} {3969982800 7200 0 EET} {3983983200 10800 1 EEST} {4002037200 7200 0 EET} {4015432800 10800 1 EEST} {4033486800 7200 0 EET} {4046882400 10800 1 EEST} {4064936400 7200 0 EET} {4078332000 10800 1 EEST} {4096386000 7200 0 EET} } tcl8.6.5/library/tzdata/Asia/Kashgar0000644000175000017500000000025112663660066016701 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Urumqi)]} { LoadTimeZoneFile Asia/Urumqi } set TZData(:Asia/Kashgar) $TZData(:Asia/Urumqi) tcl8.6.5/library/tzdata/Asia/Damascus0000644000175000017500000001753712663660066017100 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Damascus) { {-9223372036854775808 8712 0 LMT} {-1577931912 7200 0 EET} {-1568592000 10800 1 EEST} {-1554080400 7200 0 EET} {-1537142400 10800 1 EEST} {-1522630800 7200 0 EET} {-1505692800 10800 1 EEST} {-1491181200 7200 0 EET} {-1474243200 10800 1 EEST} {-1459126800 7200 0 EET} {-242265600 10800 1 EEST} {-228877200 7200 0 EET} {-210556800 10800 1 EEST} {-197427600 7200 0 EET} {-178934400 10800 1 EEST} {-165718800 7200 0 EET} {-147398400 10800 1 EEST} {-134269200 7200 0 EET} {-116467200 10800 1 EEST} {-102646800 7200 0 EET} {-84326400 10800 1 EEST} {-71110800 7200 0 EET} {-52704000 10800 1 EEST} {-39488400 7200 0 EET} {-21168000 10800 1 EEST} {-7952400 7200 0 EET} {10368000 10800 1 EEST} {23583600 7200 0 EET} {41904000 10800 1 EEST} {55119600 7200 0 EET} {73526400 10800 1 EEST} {86742000 7200 0 EET} {105062400 10800 1 EEST} {118278000 7200 0 EET} {136598400 10800 1 EEST} {149814000 7200 0 EET} {168134400 10800 1 EEST} {181350000 7200 0 EET} {199756800 10800 1 EEST} {212972400 7200 0 EET} {231292800 10800 1 EEST} {241916400 7200 0 EET} {262828800 10800 1 EEST} {273452400 7200 0 EET} {418694400 10800 1 EEST} {433810800 7200 0 EET} {450316800 10800 1 EEST} {465433200 7200 0 EET} {508896000 10800 1 EEST} {529196400 7200 0 EET} {541555200 10800 1 EEST} {562633200 7200 0 EET} {574387200 10800 1 EEST} {594255600 7200 0 EET} {607305600 10800 1 EEST} {623199600 7200 0 EET} {638928000 10800 1 EEST} {654649200 7200 0 EET} {670456800 10800 1 EEST} {686264400 7200 0 EET} {702684000 10800 1 EEST} {717886800 7200 0 EET} {733096800 10800 1 EEST} {748904400 7200 0 EET} {765151200 10800 1 EEST} {780958800 7200 0 EET} {796687200 10800 1 EEST} {812494800 7200 0 EET} {828309600 10800 1 EEST} {844117200 7200 0 EET} {859759200 10800 1 EEST} {875653200 7200 0 EET} {891208800 10800 1 EEST} {907189200 7200 0 EET} {922917600 10800 1 EEST} {938725200 7200 0 EET} {954540000 10800 1 EEST} {970347600 7200 0 EET} {986076000 10800 1 EEST} {1001883600 7200 0 EET} {1017612000 10800 1 EEST} {1033419600 7200 0 EET} {1049148000 10800 1 EEST} {1064955600 7200 0 EET} {1080770400 10800 1 EEST} {1096578000 7200 0 EET} {1112306400 10800 1 EEST} {1128114000 7200 0 EET} {1143842400 10800 1 EEST} {1158872400 7200 0 EET} {1175205600 10800 1 EEST} {1193950800 7200 0 EET} {1207260000 10800 1 EEST} {1225486800 7200 0 EET} {1238104800 10800 1 EEST} {1256850000 7200 0 EET} {1270159200 10800 1 EEST} {1288299600 7200 0 EET} {1301608800 10800 1 EEST} {1319749200 7200 0 EET} {1333058400 10800 1 EEST} {1351198800 7200 0 EET} {1364508000 10800 1 EEST} {1382648400 7200 0 EET} {1395957600 10800 1 EEST} {1414702800 7200 0 EET} {1427407200 10800 1 EEST} {1446152400 7200 0 EET} {1458856800 10800 1 EEST} {1477602000 7200 0 EET} {1490911200 10800 1 EEST} {1509051600 7200 0 EET} {1522360800 10800 1 EEST} {1540501200 7200 0 EET} {1553810400 10800 1 EEST} {1571950800 7200 0 EET} {1585260000 10800 1 EEST} {1604005200 7200 0 EET} {1616709600 10800 1 EEST} {1635454800 7200 0 EET} {1648159200 10800 1 EEST} {1666904400 7200 0 EET} {1680213600 10800 1 EEST} {1698354000 7200 0 EET} {1711663200 10800 1 EEST} {1729803600 7200 0 EET} {1743112800 10800 1 EEST} {1761858000 7200 0 EET} {1774562400 10800 1 EEST} {1793307600 7200 0 EET} {1806012000 10800 1 EEST} {1824757200 7200 0 EET} {1838066400 10800 1 EEST} {1856206800 7200 0 EET} {1869516000 10800 1 EEST} {1887656400 7200 0 EET} {1900965600 10800 1 EEST} {1919106000 7200 0 EET} {1932415200 10800 1 EEST} {1951160400 7200 0 EET} {1963864800 10800 1 EEST} {1982610000 7200 0 EET} {1995314400 10800 1 EEST} {2014059600 7200 0 EET} {2027368800 10800 1 EEST} {2045509200 7200 0 EET} {2058818400 10800 1 EEST} {2076958800 7200 0 EET} {2090268000 10800 1 EEST} {2109013200 7200 0 EET} {2121717600 10800 1 EEST} {2140462800 7200 0 EET} {2153167200 10800 1 EEST} {2171912400 7200 0 EET} {2184616800 10800 1 EEST} {2203362000 7200 0 EET} {2216671200 10800 1 EEST} {2234811600 7200 0 EET} {2248120800 10800 1 EEST} {2266261200 7200 0 EET} {2279570400 10800 1 EEST} {2298315600 7200 0 EET} {2311020000 10800 1 EEST} {2329765200 7200 0 EET} {2342469600 10800 1 EEST} {2361214800 7200 0 EET} {2374524000 10800 1 EEST} {2392664400 7200 0 EET} {2405973600 10800 1 EEST} {2424114000 7200 0 EET} {2437423200 10800 1 EEST} {2455563600 7200 0 EET} {2468872800 10800 1 EEST} {2487618000 7200 0 EET} {2500322400 10800 1 EEST} {2519067600 7200 0 EET} {2531772000 10800 1 EEST} {2550517200 7200 0 EET} {2563826400 10800 1 EEST} {2581966800 7200 0 EET} {2595276000 10800 1 EEST} {2613416400 7200 0 EET} {2626725600 10800 1 EEST} {2645470800 7200 0 EET} {2658175200 10800 1 EEST} {2676920400 7200 0 EET} {2689624800 10800 1 EEST} {2708370000 7200 0 EET} {2721679200 10800 1 EEST} {2739819600 7200 0 EET} {2753128800 10800 1 EEST} {2771269200 7200 0 EET} {2784578400 10800 1 EEST} {2802718800 7200 0 EET} {2816028000 10800 1 EEST} {2834773200 7200 0 EET} {2847477600 10800 1 EEST} {2866222800 7200 0 EET} {2878927200 10800 1 EEST} {2897672400 7200 0 EET} {2910981600 10800 1 EEST} {2929122000 7200 0 EET} {2942431200 10800 1 EEST} {2960571600 7200 0 EET} {2973880800 10800 1 EEST} {2992626000 7200 0 EET} {3005330400 10800 1 EEST} {3024075600 7200 0 EET} {3036780000 10800 1 EEST} {3055525200 7200 0 EET} {3068229600 10800 1 EEST} {3086974800 7200 0 EET} {3100284000 10800 1 EEST} {3118424400 7200 0 EET} {3131733600 10800 1 EEST} {3149874000 7200 0 EET} {3163183200 10800 1 EEST} {3181928400 7200 0 EET} {3194632800 10800 1 EEST} {3213378000 7200 0 EET} {3226082400 10800 1 EEST} {3244827600 7200 0 EET} {3258136800 10800 1 EEST} {3276277200 7200 0 EET} {3289586400 10800 1 EEST} {3307726800 7200 0 EET} {3321036000 10800 1 EEST} {3339176400 7200 0 EET} {3352485600 10800 1 EEST} {3371230800 7200 0 EET} {3383935200 10800 1 EEST} {3402680400 7200 0 EET} {3415384800 10800 1 EEST} {3434130000 7200 0 EET} {3447439200 10800 1 EEST} {3465579600 7200 0 EET} {3478888800 10800 1 EEST} {3497029200 7200 0 EET} {3510338400 10800 1 EEST} {3529083600 7200 0 EET} {3541788000 10800 1 EEST} {3560533200 7200 0 EET} {3573237600 10800 1 EEST} {3591982800 7200 0 EET} {3605292000 10800 1 EEST} {3623432400 7200 0 EET} {3636741600 10800 1 EEST} {3654882000 7200 0 EET} {3668191200 10800 1 EEST} {3686331600 7200 0 EET} {3699640800 10800 1 EEST} {3718386000 7200 0 EET} {3731090400 10800 1 EEST} {3749835600 7200 0 EET} {3762540000 10800 1 EEST} {3781285200 7200 0 EET} {3794594400 10800 1 EEST} {3812734800 7200 0 EET} {3826044000 10800 1 EEST} {3844184400 7200 0 EET} {3857493600 10800 1 EEST} {3876238800 7200 0 EET} {3888943200 10800 1 EEST} {3907688400 7200 0 EET} {3920392800 10800 1 EEST} {3939138000 7200 0 EET} {3951842400 10800 1 EEST} {3970587600 7200 0 EET} {3983896800 10800 1 EEST} {4002037200 7200 0 EET} {4015346400 10800 1 EEST} {4033486800 7200 0 EET} {4046796000 10800 1 EEST} {4065541200 7200 0 EET} {4078245600 10800 1 EEST} {4096990800 7200 0 EET} } tcl8.6.5/library/tzdata/Asia/Singapore0000644000175000017500000000060212661614721017243 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Singapore) { {-9223372036854775808 24925 0 LMT} {-2177477725 24925 0 SMT} {-2038200925 25200 0 MALT} {-1167634800 26400 1 MALST} {-1073028000 26400 0 MALT} {-894180000 27000 0 MALT} {-879665400 32400 0 JST} {-767005200 27000 0 MALT} {-138785400 27000 0 SGT} {378664200 28800 0 SGT} } tcl8.6.5/library/tzdata/Asia/Novosibirsk0000644000175000017500000000411612663660066017635 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Novosibirsk) { {-9223372036854775808 19900 0 LMT} {-1579476700 21600 0 NOVT} {-1247551200 25200 0 NOVMMTT} {354906000 28800 1 NOVST} {370713600 25200 0 NOVT} {386442000 28800 1 NOVST} {402249600 25200 0 NOVT} {417978000 28800 1 NOVST} {433785600 25200 0 NOVT} {449600400 28800 1 NOVST} {465332400 25200 0 NOVT} {481057200 28800 1 NOVST} {496782000 25200 0 NOVT} {512506800 28800 1 NOVST} {528231600 25200 0 NOVT} {543956400 28800 1 NOVST} {559681200 25200 0 NOVT} {575406000 28800 1 NOVST} {591130800 25200 0 NOVT} {606855600 28800 1 NOVST} {622580400 25200 0 NOVT} {638305200 28800 1 NOVST} {654634800 25200 0 NOVT} {670359600 21600 0 NOVMMTT} {670363200 25200 1 NOVST} {686088000 21600 0 NOVT} {695764800 25200 0 NOVMMTT} {701798400 28800 1 NOVST} {717519600 25200 0 NOVT} {733258800 28800 1 NOVST} {738090000 25200 0 NOVST} {748987200 21600 0 NOVT} {764712000 25200 1 NOVST} {780436800 21600 0 NOVT} {796161600 25200 1 NOVST} {811886400 21600 0 NOVT} {828216000 25200 1 NOVST} {846360000 21600 0 NOVT} {859665600 25200 1 NOVST} {877809600 21600 0 NOVT} {891115200 25200 1 NOVST} {909259200 21600 0 NOVT} {922564800 25200 1 NOVST} {941313600 21600 0 NOVT} {954014400 25200 1 NOVST} {972763200 21600 0 NOVT} {985464000 25200 1 NOVST} {1004212800 21600 0 NOVT} {1017518400 25200 1 NOVST} {1035662400 21600 0 NOVT} {1048968000 25200 1 NOVST} {1067112000 21600 0 NOVT} {1080417600 25200 1 NOVST} {1099166400 21600 0 NOVT} {1111867200 25200 1 NOVST} {1130616000 21600 0 NOVT} {1143316800 25200 1 NOVST} {1162065600 21600 0 NOVT} {1174766400 25200 1 NOVST} {1193515200 21600 0 NOVT} {1206820800 25200 1 NOVST} {1224964800 21600 0 NOVT} {1238270400 25200 1 NOVST} {1256414400 21600 0 NOVT} {1269720000 25200 1 NOVST} {1288468800 21600 0 NOVT} {1301169600 25200 0 NOVT} {1414263600 21600 0 NOVT} } tcl8.6.5/library/tzdata/Asia/Macao0000644000175000017500000000024412661614722016337 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Macau)]} { LoadTimeZoneFile Asia/Macau } set TZData(:Asia/Macao) $TZData(:Asia/Macau) tcl8.6.5/library/tzdata/Asia/Omsk0000644000175000017500000000405112663660066016234 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Omsk) { {-9223372036854775808 17610 0 LMT} {-1582088010 18000 0 OMST} {-1247547600 21600 0 OMSMMTT} {354909600 25200 1 OMSST} {370717200 21600 0 OMST} {386445600 25200 1 OMSST} {402253200 21600 0 OMST} {417981600 25200 1 OMSST} {433789200 21600 0 OMST} {449604000 25200 1 OMSST} {465336000 21600 0 OMST} {481060800 25200 1 OMSST} {496785600 21600 0 OMST} {512510400 25200 1 OMSST} {528235200 21600 0 OMST} {543960000 25200 1 OMSST} {559684800 21600 0 OMST} {575409600 25200 1 OMSST} {591134400 21600 0 OMST} {606859200 25200 1 OMSST} {622584000 21600 0 OMST} {638308800 25200 1 OMSST} {654638400 21600 0 OMST} {670363200 18000 0 OMSMMTT} {670366800 21600 1 OMSST} {686091600 18000 0 OMST} {695768400 21600 0 OMSMMTT} {701802000 25200 1 OMSST} {717523200 21600 0 OMST} {733262400 25200 1 OMSST} {748987200 21600 0 OMST} {764712000 25200 1 OMSST} {780436800 21600 0 OMST} {796161600 25200 1 OMSST} {811886400 21600 0 OMST} {828216000 25200 1 OMSST} {846360000 21600 0 OMST} {859665600 25200 1 OMSST} {877809600 21600 0 OMST} {891115200 25200 1 OMSST} {909259200 21600 0 OMST} {922564800 25200 1 OMSST} {941313600 21600 0 OMST} {954014400 25200 1 OMSST} {972763200 21600 0 OMST} {985464000 25200 1 OMSST} {1004212800 21600 0 OMST} {1017518400 25200 1 OMSST} {1035662400 21600 0 OMST} {1048968000 25200 1 OMSST} {1067112000 21600 0 OMST} {1080417600 25200 1 OMSST} {1099166400 21600 0 OMST} {1111867200 25200 1 OMSST} {1130616000 21600 0 OMST} {1143316800 25200 1 OMSST} {1162065600 21600 0 OMST} {1174766400 25200 1 OMSST} {1193515200 21600 0 OMST} {1206820800 25200 1 OMSST} {1224964800 21600 0 OMST} {1238270400 25200 1 OMSST} {1256414400 21600 0 OMST} {1269720000 25200 1 OMSST} {1288468800 21600 0 OMST} {1301169600 25200 0 OMST} {1414263600 21600 0 OMST} } tcl8.6.5/library/tzdata/Asia/Dhaka0000644000175000017500000000057012663660066016335 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Dhaka) { {-9223372036854775808 21700 0 LMT} {-2524543300 21200 0 HMT} {-891582800 23400 0 BURT} {-872058600 19800 0 IST} {-862637400 23400 0 BURT} {-576138600 21600 0 DACT} {38772000 21600 0 BDT} {1230746400 21600 0 BDT} {1245430800 25200 1 BDST} {1262278800 21600 0 BDT} } tcl8.6.5/library/tzdata/Asia/Kamchatka0000644000175000017500000000406112663653454017213 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Kamchatka) { {-9223372036854775808 38076 0 LMT} {-1487759676 39600 0 PETT} {-1247569200 43200 0 PETMMTT} {354888000 46800 1 PETST} {370695600 43200 0 PETT} {386424000 46800 1 PETST} {402231600 43200 0 PETT} {417960000 46800 1 PETST} {433767600 43200 0 PETT} {449582400 46800 1 PETST} {465314400 43200 0 PETT} {481039200 46800 1 PETST} {496764000 43200 0 PETT} {512488800 46800 1 PETST} {528213600 43200 0 PETT} {543938400 46800 1 PETST} {559663200 43200 0 PETT} {575388000 46800 1 PETST} {591112800 43200 0 PETT} {606837600 46800 1 PETST} {622562400 43200 0 PETT} {638287200 46800 1 PETST} {654616800 43200 0 PETT} {670341600 39600 0 PETMMTT} {670345200 43200 1 PETST} {686070000 39600 0 PETT} {695746800 43200 0 PETMMTT} {701780400 46800 1 PETST} {717501600 43200 0 PETT} {733240800 46800 1 PETST} {748965600 43200 0 PETT} {764690400 46800 1 PETST} {780415200 43200 0 PETT} {796140000 46800 1 PETST} {811864800 43200 0 PETT} {828194400 46800 1 PETST} {846338400 43200 0 PETT} {859644000 46800 1 PETST} {877788000 43200 0 PETT} {891093600 46800 1 PETST} {909237600 43200 0 PETT} {922543200 46800 1 PETST} {941292000 43200 0 PETT} {953992800 46800 1 PETST} {972741600 43200 0 PETT} {985442400 46800 1 PETST} {1004191200 43200 0 PETT} {1017496800 46800 1 PETST} {1035640800 43200 0 PETT} {1048946400 46800 1 PETST} {1067090400 43200 0 PETT} {1080396000 46800 1 PETST} {1099144800 43200 0 PETT} {1111845600 46800 1 PETST} {1130594400 43200 0 PETT} {1143295200 46800 1 PETST} {1162044000 43200 0 PETT} {1174744800 46800 1 PETST} {1193493600 43200 0 PETT} {1206799200 46800 1 PETST} {1224943200 43200 0 PETT} {1238248800 46800 1 PETST} {1256392800 43200 0 PETT} {1269698400 39600 0 PETMMTT} {1269702000 43200 1 PETST} {1288450800 39600 0 PETT} {1301151600 43200 0 PETT} } tcl8.6.5/library/tzdata/Asia/Hong_Kong0000644000175000017500000000414612663660066017201 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Hong_Kong) { {-9223372036854775808 27402 0 LMT} {-2056693002 28800 0 HKT} {-907389000 32400 1 HKST} {-891667800 28800 0 HKT} {-884246400 32400 0 JST} {-766746000 28800 0 HKT} {-747981000 32400 1 HKST} {-728544600 28800 0 HKT} {-717049800 32400 1 HKST} {-694503000 28800 0 HKT} {-683785800 32400 1 HKST} {-668064600 28800 0 HKT} {-654755400 32400 1 HKST} {-636615000 28800 0 HKT} {-623305800 32400 1 HKST} {-605165400 28800 0 HKT} {-591856200 32400 1 HKST} {-573715800 28800 0 HKT} {-559801800 32400 1 HKST} {-542352600 28800 0 HKT} {-528352200 32400 1 HKST} {-510211800 28800 0 HKT} {-498112200 32400 1 HKST} {-478762200 28800 0 HKT} {-466662600 32400 1 HKST} {-446707800 28800 0 HKT} {-435213000 32400 1 HKST} {-415258200 28800 0 HKT} {-403158600 32400 1 HKST} {-383808600 28800 0 HKT} {-371709000 32400 1 HKST} {-352359000 28800 0 HKT} {-340259400 32400 1 HKST} {-320909400 28800 0 HKT} {-308809800 32400 1 HKST} {-288855000 28800 0 HKT} {-277360200 32400 1 HKST} {-257405400 28800 0 HKT} {-245910600 32400 1 HKST} {-225955800 28800 0 HKT} {-213856200 32400 1 HKST} {-194506200 28800 0 HKT} {-182406600 32400 1 HKST} {-163056600 28800 0 HKT} {-148537800 32400 1 HKST} {-132816600 28800 0 HKT} {-117088200 32400 1 HKST} {-101367000 28800 0 HKT} {-85638600 32400 1 HKST} {-69312600 28800 0 HKT} {-53584200 32400 1 HKST} {-37863000 28800 0 HKT} {-22134600 32400 1 HKST} {-6413400 28800 0 HKT} {9315000 32400 1 HKST} {25036200 28800 0 HKT} {40764600 32400 1 HKST} {56485800 28800 0 HKT} {72214200 32400 1 HKST} {88540200 28800 0 HKT} {104268600 32400 1 HKST} {119989800 28800 0 HKT} {126041400 32400 1 HKST} {135714600 32400 1 HKST} {151439400 28800 0 HKT} {167167800 32400 1 HKST} {182889000 28800 0 HKT} {198617400 32400 1 HKST} {214338600 28800 0 HKT} {295385400 32400 1 HKST} {309292200 28800 0 HKT} } tcl8.6.5/library/tzdata/Asia/Saigon0000644000175000017500000000026712661614722016544 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Ho_Chi_Minh)]} { LoadTimeZoneFile Asia/Ho_Chi_Minh } set TZData(:Asia/Saigon) $TZData(:Asia/Ho_Chi_Minh) tcl8.6.5/library/tzdata/Asia/Riyadh0000644000175000017500000000021612663660066016542 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Riyadh) { {-9223372036854775808 11212 0 LMT} {-719636812 10800 0 AST} } tcl8.6.5/library/tzdata/Asia/Aqtau0000644000175000017500000000322412661614721016372 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Aqtau) { {-9223372036854775808 12064 0 LMT} {-1441164064 14400 0 FORT} {-1247544000 18000 0 FORT} {-220942800 18000 0 SHET} {370724400 21600 0 SHET} {386445600 18000 0 SHET} {386449200 21600 1 SHEST} {402256800 18000 0 SHET} {417985200 21600 1 SHEST} {433792800 18000 0 SHET} {449607600 21600 1 SHEST} {465339600 18000 0 SHET} {481064400 21600 1 SHEST} {496789200 18000 0 SHET} {512514000 21600 1 SHEST} {528238800 18000 0 SHET} {543963600 21600 1 SHEST} {559688400 18000 0 SHET} {575413200 21600 1 SHEST} {591138000 18000 0 SHET} {606862800 21600 1 SHEST} {622587600 18000 0 SHET} {638312400 21600 1 SHEST} {654642000 18000 0 SHET} {662670000 18000 0 SHET} {692823600 18000 0 AQTT} {701805600 21600 1 AQTST} {717526800 18000 0 AQTT} {733266000 21600 1 AQTST} {748990800 18000 0 AQTT} {764715600 21600 1 AQTST} {780440400 18000 0 AQTT} {796165200 14400 0 AQTT} {796168800 18000 1 AQTST} {811893600 14400 0 AQTT} {828223200 18000 1 AQTST} {846367200 14400 0 AQTT} {859672800 18000 1 AQTST} {877816800 14400 0 AQTT} {891122400 18000 1 AQTST} {909266400 14400 0 AQTT} {922572000 18000 1 AQTST} {941320800 14400 0 AQTT} {954021600 18000 1 AQTST} {972770400 14400 0 AQTT} {985471200 18000 1 AQTST} {1004220000 14400 0 AQTT} {1017525600 18000 1 AQTST} {1035669600 14400 0 AQTT} {1048975200 18000 1 AQTST} {1067119200 14400 0 AQTT} {1080424800 18000 1 AQTST} {1099173600 14400 0 AQTT} {1110830400 18000 0 AQTT} } tcl8.6.5/library/tzdata/Asia/Qatar0000644000175000017500000000025112661614721016364 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Qatar) { {-9223372036854775808 12368 0 LMT} {-1577935568 14400 0 GST} {76190400 10800 0 AST} } tcl8.6.5/library/tzdata/Asia/Ashgabat0000644000175000017500000000156312661614721017035 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Ashgabat) { {-9223372036854775808 14012 0 LMT} {-1441166012 14400 0 ASHT} {-1247544000 18000 0 ASHT} {354913200 21600 1 ASHST} {370720800 18000 0 ASHT} {386449200 21600 1 ASHST} {402256800 18000 0 ASHT} {417985200 21600 1 ASHST} {433792800 18000 0 ASHT} {449607600 21600 1 ASHST} {465339600 18000 0 ASHT} {481064400 21600 1 ASHST} {496789200 18000 0 ASHT} {512514000 21600 1 ASHST} {528238800 18000 0 ASHT} {543963600 21600 1 ASHST} {559688400 18000 0 ASHT} {575413200 21600 1 ASHST} {591138000 18000 0 ASHT} {606862800 21600 1 ASHST} {622587600 18000 0 ASHT} {638312400 21600 1 ASHST} {654642000 18000 0 ASHT} {670366800 14400 0 ASHT} {670370400 18000 1 ASHST} {686095200 14400 0 ASHT} {695772000 18000 0 TMT} } tcl8.6.5/library/tzdata/Asia/Seoul0000644000175000017500000000135612663660066016417 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Seoul) { {-9223372036854775808 30472 0 LMT} {-1948782472 30600 0 KST} {-1830414600 32400 0 JCST} {-1017824400 32400 0 JST} {-767350800 32400 0 KST} {-498128400 30600 0 KST} {-462702600 34200 1 KDT} {-451733400 30600 0 KST} {-429784200 34200 1 KDT} {-418296600 30600 0 KST} {-399544200 34200 1 KDT} {-387451800 30600 0 KST} {-368094600 34200 1 KDT} {-356002200 30600 0 KST} {-336645000 34200 1 KDT} {-324552600 30600 0 KST} {-305195400 34200 1 KDT} {-293103000 30600 0 KST} {-264933000 32400 0 KST} {547578000 36000 1 KDT} {560883600 32400 0 KST} {579027600 36000 1 KDT} {592333200 32400 0 KST} } tcl8.6.5/library/tzdata/Asia/Ulaanbaatar0000644000175000017500000001502012663660066017534 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Ulaanbaatar) { {-9223372036854775808 25652 0 LMT} {-2032931252 25200 0 ULAT} {252435600 28800 0 ULAT} {417974400 32400 1 ULAST} {433782000 28800 0 ULAT} {449596800 32400 1 ULAST} {465318000 28800 0 ULAT} {481046400 32400 1 ULAST} {496767600 28800 0 ULAT} {512496000 32400 1 ULAST} {528217200 28800 0 ULAT} {543945600 32400 1 ULAST} {559666800 28800 0 ULAT} {575395200 32400 1 ULAST} {591116400 28800 0 ULAT} {606844800 32400 1 ULAST} {622566000 28800 0 ULAT} {638294400 32400 1 ULAST} {654620400 28800 0 ULAT} {670348800 32400 1 ULAST} {686070000 28800 0 ULAT} {701798400 32400 1 ULAST} {717519600 28800 0 ULAT} {733248000 32400 1 ULAST} {748969200 28800 0 ULAT} {764697600 32400 1 ULAST} {780418800 28800 0 ULAT} {796147200 32400 1 ULAST} {811868400 28800 0 ULAT} {828201600 32400 1 ULAST} {843922800 28800 0 ULAT} {859651200 32400 1 ULAST} {875372400 28800 0 ULAT} {891100800 32400 1 ULAST} {906822000 28800 0 ULAT} {988394400 32400 1 ULAST} {1001696400 28800 0 ULAT} {1017424800 32400 1 ULAST} {1033146000 28800 0 ULAT} {1048874400 32400 1 ULAST} {1064595600 28800 0 ULAT} {1080324000 32400 1 ULAST} {1096045200 28800 0 ULAT} {1111773600 32400 1 ULAST} {1127494800 28800 0 ULAT} {1143223200 32400 1 ULAST} {1159549200 28800 0 ULAT} {1427479200 32400 1 ULAST} {1443193200 28800 0 ULAT} {1458928800 32400 1 ULAST} {1474642800 28800 0 ULAT} {1490378400 32400 1 ULAST} {1506697200 28800 0 ULAT} {1522432800 32400 1 ULAST} {1538146800 28800 0 ULAT} {1553882400 32400 1 ULAST} {1569596400 28800 0 ULAT} {1585332000 32400 1 ULAST} {1601046000 28800 0 ULAT} {1616781600 32400 1 ULAST} {1632495600 28800 0 ULAT} {1648231200 32400 1 ULAST} {1663945200 28800 0 ULAT} {1679680800 32400 1 ULAST} {1695999600 28800 0 ULAT} {1711735200 32400 1 ULAST} {1727449200 28800 0 ULAT} {1743184800 32400 1 ULAST} {1758898800 28800 0 ULAT} {1774634400 32400 1 ULAST} {1790348400 28800 0 ULAT} {1806084000 32400 1 ULAST} {1821798000 28800 0 ULAT} {1837533600 32400 1 ULAST} {1853852400 28800 0 ULAT} {1869588000 32400 1 ULAST} {1885302000 28800 0 ULAT} {1901037600 32400 1 ULAST} {1916751600 28800 0 ULAT} {1932487200 32400 1 ULAST} {1948201200 28800 0 ULAT} {1963936800 32400 1 ULAST} {1979650800 28800 0 ULAT} {1995386400 32400 1 ULAST} {2011100400 28800 0 ULAT} {2026836000 32400 1 ULAST} {2043154800 28800 0 ULAT} {2058890400 32400 1 ULAST} {2074604400 28800 0 ULAT} {2090340000 32400 1 ULAST} {2106054000 28800 0 ULAT} {2121789600 32400 1 ULAST} {2137503600 28800 0 ULAT} {2153239200 32400 1 ULAST} {2168953200 28800 0 ULAT} {2184688800 32400 1 ULAST} {2200402800 28800 0 ULAT} {2216743200 32400 1 ULAST} {2232457200 28800 0 ULAT} {2248192800 32400 1 ULAST} {2263906800 28800 0 ULAT} {2279642400 32400 1 ULAST} {2295356400 28800 0 ULAT} {2311092000 32400 1 ULAST} {2326806000 28800 0 ULAT} {2342541600 32400 1 ULAST} {2358255600 28800 0 ULAT} {2373991200 32400 1 ULAST} {2390310000 28800 0 ULAT} {2406045600 32400 1 ULAST} {2421759600 28800 0 ULAT} {2437495200 32400 1 ULAST} {2453209200 28800 0 ULAT} {2468944800 32400 1 ULAST} {2484658800 28800 0 ULAT} {2500394400 32400 1 ULAST} {2516108400 28800 0 ULAT} {2531844000 32400 1 ULAST} {2547558000 28800 0 ULAT} {2563293600 32400 1 ULAST} {2579612400 28800 0 ULAT} {2595348000 32400 1 ULAST} {2611062000 28800 0 ULAT} {2626797600 32400 1 ULAST} {2642511600 28800 0 ULAT} {2658247200 32400 1 ULAST} {2673961200 28800 0 ULAT} {2689696800 32400 1 ULAST} {2705410800 28800 0 ULAT} {2721146400 32400 1 ULAST} {2737465200 28800 0 ULAT} {2753200800 32400 1 ULAST} {2768914800 28800 0 ULAT} {2784650400 32400 1 ULAST} {2800364400 28800 0 ULAT} {2816100000 32400 1 ULAST} {2831814000 28800 0 ULAT} {2847549600 32400 1 ULAST} {2863263600 28800 0 ULAT} {2878999200 32400 1 ULAST} {2894713200 28800 0 ULAT} {2910448800 32400 1 ULAST} {2926767600 28800 0 ULAT} {2942503200 32400 1 ULAST} {2958217200 28800 0 ULAT} {2973952800 32400 1 ULAST} {2989666800 28800 0 ULAT} {3005402400 32400 1 ULAST} {3021116400 28800 0 ULAT} {3036852000 32400 1 ULAST} {3052566000 28800 0 ULAT} {3068301600 32400 1 ULAST} {3084015600 28800 0 ULAT} {3100356000 32400 1 ULAST} {3116070000 28800 0 ULAT} {3131805600 32400 1 ULAST} {3147519600 28800 0 ULAT} {3163255200 32400 1 ULAST} {3178969200 28800 0 ULAT} {3194704800 32400 1 ULAST} {3210418800 28800 0 ULAT} {3226154400 32400 1 ULAST} {3241868400 28800 0 ULAT} {3257604000 32400 1 ULAST} {3273922800 28800 0 ULAT} {3289658400 32400 1 ULAST} {3305372400 28800 0 ULAT} {3321108000 32400 1 ULAST} {3336822000 28800 0 ULAT} {3352557600 32400 1 ULAST} {3368271600 28800 0 ULAT} {3384007200 32400 1 ULAST} {3399721200 28800 0 ULAT} {3415456800 32400 1 ULAST} {3431170800 28800 0 ULAT} {3446906400 32400 1 ULAST} {3463225200 28800 0 ULAT} {3478960800 32400 1 ULAST} {3494674800 28800 0 ULAT} {3510410400 32400 1 ULAST} {3526124400 28800 0 ULAT} {3541860000 32400 1 ULAST} {3557574000 28800 0 ULAT} {3573309600 32400 1 ULAST} {3589023600 28800 0 ULAT} {3604759200 32400 1 ULAST} {3621078000 28800 0 ULAT} {3636813600 32400 1 ULAST} {3652527600 28800 0 ULAT} {3668263200 32400 1 ULAST} {3683977200 28800 0 ULAT} {3699712800 32400 1 ULAST} {3715426800 28800 0 ULAT} {3731162400 32400 1 ULAST} {3746876400 28800 0 ULAT} {3762612000 32400 1 ULAST} {3778326000 28800 0 ULAT} {3794061600 32400 1 ULAST} {3810380400 28800 0 ULAT} {3826116000 32400 1 ULAST} {3841830000 28800 0 ULAT} {3857565600 32400 1 ULAST} {3873279600 28800 0 ULAT} {3889015200 32400 1 ULAST} {3904729200 28800 0 ULAT} {3920464800 32400 1 ULAST} {3936178800 28800 0 ULAT} {3951914400 32400 1 ULAST} {3967628400 28800 0 ULAT} {3983968800 32400 1 ULAST} {3999682800 28800 0 ULAT} {4015418400 32400 1 ULAST} {4031132400 28800 0 ULAT} {4046868000 32400 1 ULAST} {4062582000 28800 0 ULAT} {4078317600 32400 1 ULAST} {4094031600 28800 0 ULAT} } tcl8.6.5/library/tzdata/Asia/Choibalsan0000644000175000017500000001505512663660066017374 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Choibalsan) { {-9223372036854775808 27480 0 LMT} {-2032933080 25200 0 ULAT} {252435600 28800 0 ULAT} {417974400 36000 0 CHOST} {433778400 32400 0 CHOT} {449593200 36000 1 CHOST} {465314400 32400 0 CHOT} {481042800 36000 1 CHOST} {496764000 32400 0 CHOT} {512492400 36000 1 CHOST} {528213600 32400 0 CHOT} {543942000 36000 1 CHOST} {559663200 32400 0 CHOT} {575391600 36000 1 CHOST} {591112800 32400 0 CHOT} {606841200 36000 1 CHOST} {622562400 32400 0 CHOT} {638290800 36000 1 CHOST} {654616800 32400 0 CHOT} {670345200 36000 1 CHOST} {686066400 32400 0 CHOT} {701794800 36000 1 CHOST} {717516000 32400 0 CHOT} {733244400 36000 1 CHOST} {748965600 32400 0 CHOT} {764694000 36000 1 CHOST} {780415200 32400 0 CHOT} {796143600 36000 1 CHOST} {811864800 32400 0 CHOT} {828198000 36000 1 CHOST} {843919200 32400 0 CHOT} {859647600 36000 1 CHOST} {875368800 32400 0 CHOT} {891097200 36000 1 CHOST} {906818400 32400 0 CHOT} {988390800 36000 1 CHOST} {1001692800 32400 0 CHOT} {1017421200 36000 1 CHOST} {1033142400 32400 0 CHOT} {1048870800 36000 1 CHOST} {1064592000 32400 0 CHOT} {1080320400 36000 1 CHOST} {1096041600 32400 0 CHOT} {1111770000 36000 1 CHOST} {1127491200 32400 0 CHOT} {1143219600 36000 1 CHOST} {1159545600 32400 0 CHOT} {1206889200 28800 0 CHOT} {1427479200 32400 1 CHOST} {1443193200 28800 0 CHOT} {1458928800 32400 1 CHOST} {1474642800 28800 0 CHOT} {1490378400 32400 1 CHOST} {1506697200 28800 0 CHOT} {1522432800 32400 1 CHOST} {1538146800 28800 0 CHOT} {1553882400 32400 1 CHOST} {1569596400 28800 0 CHOT} {1585332000 32400 1 CHOST} {1601046000 28800 0 CHOT} {1616781600 32400 1 CHOST} {1632495600 28800 0 CHOT} {1648231200 32400 1 CHOST} {1663945200 28800 0 CHOT} {1679680800 32400 1 CHOST} {1695999600 28800 0 CHOT} {1711735200 32400 1 CHOST} {1727449200 28800 0 CHOT} {1743184800 32400 1 CHOST} {1758898800 28800 0 CHOT} {1774634400 32400 1 CHOST} {1790348400 28800 0 CHOT} {1806084000 32400 1 CHOST} {1821798000 28800 0 CHOT} {1837533600 32400 1 CHOST} {1853852400 28800 0 CHOT} {1869588000 32400 1 CHOST} {1885302000 28800 0 CHOT} {1901037600 32400 1 CHOST} {1916751600 28800 0 CHOT} {1932487200 32400 1 CHOST} {1948201200 28800 0 CHOT} {1963936800 32400 1 CHOST} {1979650800 28800 0 CHOT} {1995386400 32400 1 CHOST} {2011100400 28800 0 CHOT} {2026836000 32400 1 CHOST} {2043154800 28800 0 CHOT} {2058890400 32400 1 CHOST} {2074604400 28800 0 CHOT} {2090340000 32400 1 CHOST} {2106054000 28800 0 CHOT} {2121789600 32400 1 CHOST} {2137503600 28800 0 CHOT} {2153239200 32400 1 CHOST} {2168953200 28800 0 CHOT} {2184688800 32400 1 CHOST} {2200402800 28800 0 CHOT} {2216743200 32400 1 CHOST} {2232457200 28800 0 CHOT} {2248192800 32400 1 CHOST} {2263906800 28800 0 CHOT} {2279642400 32400 1 CHOST} {2295356400 28800 0 CHOT} {2311092000 32400 1 CHOST} {2326806000 28800 0 CHOT} {2342541600 32400 1 CHOST} {2358255600 28800 0 CHOT} {2373991200 32400 1 CHOST} {2390310000 28800 0 CHOT} {2406045600 32400 1 CHOST} {2421759600 28800 0 CHOT} {2437495200 32400 1 CHOST} {2453209200 28800 0 CHOT} {2468944800 32400 1 CHOST} {2484658800 28800 0 CHOT} {2500394400 32400 1 CHOST} {2516108400 28800 0 CHOT} {2531844000 32400 1 CHOST} {2547558000 28800 0 CHOT} {2563293600 32400 1 CHOST} {2579612400 28800 0 CHOT} {2595348000 32400 1 CHOST} {2611062000 28800 0 CHOT} {2626797600 32400 1 CHOST} {2642511600 28800 0 CHOT} {2658247200 32400 1 CHOST} {2673961200 28800 0 CHOT} {2689696800 32400 1 CHOST} {2705410800 28800 0 CHOT} {2721146400 32400 1 CHOST} {2737465200 28800 0 CHOT} {2753200800 32400 1 CHOST} {2768914800 28800 0 CHOT} {2784650400 32400 1 CHOST} {2800364400 28800 0 CHOT} {2816100000 32400 1 CHOST} {2831814000 28800 0 CHOT} {2847549600 32400 1 CHOST} {2863263600 28800 0 CHOT} {2878999200 32400 1 CHOST} {2894713200 28800 0 CHOT} {2910448800 32400 1 CHOST} {2926767600 28800 0 CHOT} {2942503200 32400 1 CHOST} {2958217200 28800 0 CHOT} {2973952800 32400 1 CHOST} {2989666800 28800 0 CHOT} {3005402400 32400 1 CHOST} {3021116400 28800 0 CHOT} {3036852000 32400 1 CHOST} {3052566000 28800 0 CHOT} {3068301600 32400 1 CHOST} {3084015600 28800 0 CHOT} {3100356000 32400 1 CHOST} {3116070000 28800 0 CHOT} {3131805600 32400 1 CHOST} {3147519600 28800 0 CHOT} {3163255200 32400 1 CHOST} {3178969200 28800 0 CHOT} {3194704800 32400 1 CHOST} {3210418800 28800 0 CHOT} {3226154400 32400 1 CHOST} {3241868400 28800 0 CHOT} {3257604000 32400 1 CHOST} {3273922800 28800 0 CHOT} {3289658400 32400 1 CHOST} {3305372400 28800 0 CHOT} {3321108000 32400 1 CHOST} {3336822000 28800 0 CHOT} {3352557600 32400 1 CHOST} {3368271600 28800 0 CHOT} {3384007200 32400 1 CHOST} {3399721200 28800 0 CHOT} {3415456800 32400 1 CHOST} {3431170800 28800 0 CHOT} {3446906400 32400 1 CHOST} {3463225200 28800 0 CHOT} {3478960800 32400 1 CHOST} {3494674800 28800 0 CHOT} {3510410400 32400 1 CHOST} {3526124400 28800 0 CHOT} {3541860000 32400 1 CHOST} {3557574000 28800 0 CHOT} {3573309600 32400 1 CHOST} {3589023600 28800 0 CHOT} {3604759200 32400 1 CHOST} {3621078000 28800 0 CHOT} {3636813600 32400 1 CHOST} {3652527600 28800 0 CHOT} {3668263200 32400 1 CHOST} {3683977200 28800 0 CHOT} {3699712800 32400 1 CHOST} {3715426800 28800 0 CHOT} {3731162400 32400 1 CHOST} {3746876400 28800 0 CHOT} {3762612000 32400 1 CHOST} {3778326000 28800 0 CHOT} {3794061600 32400 1 CHOST} {3810380400 28800 0 CHOT} {3826116000 32400 1 CHOST} {3841830000 28800 0 CHOT} {3857565600 32400 1 CHOST} {3873279600 28800 0 CHOT} {3889015200 32400 1 CHOST} {3904729200 28800 0 CHOT} {3920464800 32400 1 CHOST} {3936178800 28800 0 CHOT} {3951914400 32400 1 CHOST} {3967628400 28800 0 CHOT} {3983968800 32400 1 CHOST} {3999682800 28800 0 CHOT} {4015418400 32400 1 CHOST} {4031132400 28800 0 CHOT} {4046868000 32400 1 CHOST} {4062582000 28800 0 CHOT} {4078317600 32400 1 CHOST} {4094031600 28800 0 CHOT} } tcl8.6.5/library/tzdata/Asia/Samarkand0000644000175000017500000000162012663660066017223 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Samarkand) { {-9223372036854775808 16073 0 LMT} {-1441168073 14400 0 SAMT} {-1247544000 18000 0 SAMT} {354913200 21600 1 SAMST} {370720800 21600 0 TAST} {386445600 18000 0 SAMT} {386449200 21600 1 SAMST} {402256800 18000 0 SAMT} {417985200 21600 1 SAMST} {433792800 18000 0 SAMT} {449607600 21600 1 SAMST} {465339600 18000 0 SAMT} {481064400 21600 1 SAMST} {496789200 18000 0 SAMT} {512514000 21600 1 SAMST} {528238800 18000 0 SAMT} {543963600 21600 1 SAMST} {559688400 18000 0 SAMT} {575413200 21600 1 SAMST} {591138000 18000 0 SAMT} {606862800 21600 1 SAMST} {622587600 18000 0 SAMT} {638312400 21600 1 SAMST} {654642000 18000 0 SAMT} {670366800 21600 1 SAMST} {683665200 21600 0 UZST} {686091600 18000 0 UZT} {694206000 18000 0 UZT} } tcl8.6.5/library/tzdata/Asia/Pyongyang0000644000175000017500000000041112663660066017272 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Pyongyang) { {-9223372036854775808 30180 0 LMT} {-1948782180 30600 0 KST} {-1830414600 32400 0 JCST} {-1017824400 32400 0 JST} {-768646800 32400 0 KST} {1439564400 30600 0 KST} } tcl8.6.5/library/tzdata/Asia/Tbilisi0000644000175000017500000000326712663660066016732 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Tbilisi) { {-9223372036854775808 10751 0 LMT} {-2840151551 10751 0 TBMT} {-1441162751 10800 0 TBIT} {-405140400 14400 0 TBIT} {354916800 18000 1 TBIST} {370724400 14400 0 TBIT} {386452800 18000 1 TBIST} {402260400 14400 0 TBIT} {417988800 18000 1 TBIST} {433796400 14400 0 TBIT} {449611200 18000 1 TBIST} {465343200 14400 0 TBIT} {481068000 18000 1 TBIST} {496792800 14400 0 TBIT} {512517600 18000 1 TBIST} {528242400 14400 0 TBIT} {543967200 18000 1 TBIST} {559692000 14400 0 TBIT} {575416800 18000 1 TBIST} {591141600 14400 0 TBIT} {606866400 18000 1 TBIST} {622591200 14400 0 TBIT} {638316000 18000 1 TBIST} {654645600 14400 0 TBIT} {670370400 14400 1 TBIST} {671140800 14400 0 GEST} {686098800 10800 0 GET} {694213200 10800 0 GET} {701816400 14400 1 GEST} {717537600 10800 0 GET} {733266000 14400 1 GEST} {748987200 10800 0 GET} {764715600 14400 1 GEST} {780440400 14400 0 GET} {796161600 18000 1 GEST} {811882800 14400 0 GET} {828216000 18000 1 GEST} {846360000 18000 1 GEST} {859662000 18000 0 GEST} {877806000 14400 0 GET} {891115200 18000 1 GEST} {909255600 14400 0 GET} {922564800 18000 1 GEST} {941310000 14400 0 GET} {954014400 18000 1 GEST} {972759600 14400 0 GET} {985464000 18000 1 GEST} {1004209200 14400 0 GET} {1017518400 18000 1 GEST} {1035658800 14400 0 GET} {1048968000 18000 1 GEST} {1067108400 14400 0 GET} {1080417600 18000 1 GEST} {1088280000 14400 0 GEST} {1099177200 10800 0 GET} {1111878000 14400 0 GET} } tcl8.6.5/library/tzdata/Asia/Gaza0000644000175000017500000001743312663660066016215 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Gaza) { {-9223372036854775808 8272 0 LMT} {-2185409872 7200 0 EET} {-933645600 10800 1 EET} {-857358000 7200 0 EET} {-844300800 10800 1 EET} {-825822000 7200 0 EET} {-812685600 10800 1 EET} {-794199600 7200 0 EET} {-779853600 10800 1 EET} {-762656400 7200 0 EET} {-748310400 10800 1 EET} {-731127600 7200 0 EET} {-682653600 7200 0 EET} {-399088800 10800 1 EEST} {-386650800 7200 0 EET} {-368330400 10800 1 EEST} {-355114800 7200 0 EET} {-336790800 10800 1 EEST} {-323654400 7200 0 EET} {-305168400 10800 1 EEST} {-292032000 7200 0 EET} {-273632400 10800 1 EEST} {-260496000 7200 0 EET} {-242096400 10800 1 EEST} {-228960000 7200 0 EET} {-210560400 10800 1 EEST} {-197424000 7200 0 EET} {-178938000 10800 1 EEST} {-165801600 7200 0 EET} {-147402000 10800 1 EEST} {-134265600 7200 0 EET} {-115866000 10800 1 EEST} {-102643200 7200 0 EET} {-84330000 10800 1 EEST} {-81313200 10800 0 IST} {142376400 10800 1 IDT} {150843600 7200 0 IST} {167176800 10800 1 IDT} {178664400 7200 0 IST} {482277600 10800 1 IDT} {495579600 7200 0 IST} {516751200 10800 1 IDT} {526424400 7200 0 IST} {545436000 10800 1 IDT} {558478800 7200 0 IST} {576626400 10800 1 IDT} {589323600 7200 0 IST} {609890400 10800 1 IDT} {620773200 7200 0 IST} {638316000 10800 1 IDT} {651618000 7200 0 IST} {669765600 10800 1 IDT} {683672400 7200 0 IST} {701820000 10800 1 IDT} {715726800 7200 0 IST} {733701600 10800 1 IDT} {747176400 7200 0 IST} {765151200 10800 1 IDT} {778021200 7200 0 IST} {796600800 10800 1 IDT} {810075600 7200 0 IST} {820447200 7200 0 EET} {828655200 10800 1 EEST} {843170400 7200 0 EET} {860104800 10800 1 EEST} {874620000 7200 0 EET} {891554400 10800 1 EEST} {906069600 7200 0 EET} {915141600 7200 0 EET} {924213600 10800 1 EEST} {939934800 7200 0 EET} {956268000 10800 1 EEST} {971989200 7200 0 EET} {987717600 10800 1 EEST} {1003438800 7200 0 EET} {1019167200 10800 1 EEST} {1034888400 7200 0 EET} {1050616800 10800 1 EEST} {1066338000 7200 0 EET} {1082066400 10800 1 EEST} {1096581600 7200 0 EET} {1113516000 10800 1 EEST} {1128380400 7200 0 EET} {1143842400 10800 1 EEST} {1158872400 7200 0 EET} {1175378400 10800 1 EEST} {1189638000 7200 0 EET} {1206655200 10800 1 EEST} {1219960800 7200 0 EET} {1220220000 7200 0 EET} {1238104800 10800 1 EEST} {1252015200 7200 0 EET} {1262296800 7200 0 EET} {1269640860 10800 0 EEST} {1281474000 7200 0 EET} {1301608860 10800 1 EEST} {1312149600 7200 0 EET} {1325368800 7200 0 EET} {1333058400 10800 1 EEST} {1348178400 7200 0 EET} {1364508000 10800 1 EEST} {1380229200 7200 0 EET} {1395957600 10800 1 EEST} {1414098000 7200 0 EET} {1427493600 10800 1 EEST} {1445547600 7200 0 EET} {1458943200 10800 1 EEST} {1476997200 7200 0 EET} {1490997600 10800 1 EEST} {1509051600 7200 0 EET} {1522447200 10800 1 EEST} {1540501200 7200 0 EET} {1553896800 10800 1 EEST} {1571950800 7200 0 EET} {1585346400 10800 1 EEST} {1603400400 7200 0 EET} {1616796000 10800 1 EEST} {1634850000 7200 0 EET} {1648245600 10800 1 EEST} {1666299600 7200 0 EET} {1680300000 10800 1 EEST} {1698354000 7200 0 EET} {1711749600 10800 1 EEST} {1729803600 7200 0 EET} {1743199200 10800 1 EEST} {1761253200 7200 0 EET} {1774648800 10800 1 EEST} {1792702800 7200 0 EET} {1806098400 10800 1 EEST} {1824152400 7200 0 EET} {1838152800 10800 1 EEST} {1856206800 7200 0 EET} {1869602400 10800 1 EEST} {1887656400 7200 0 EET} {1901052000 10800 1 EEST} {1919106000 7200 0 EET} {1932501600 10800 1 EEST} {1950555600 7200 0 EET} {1963951200 10800 1 EEST} {1982005200 7200 0 EET} {1995400800 10800 1 EEST} {2013454800 7200 0 EET} {2027455200 10800 1 EEST} {2045509200 7200 0 EET} {2058904800 10800 1 EEST} {2076958800 7200 0 EET} {2090354400 10800 1 EEST} {2108408400 7200 0 EET} {2121804000 10800 1 EEST} {2139858000 7200 0 EET} {2153253600 10800 1 EEST} {2171307600 7200 0 EET} {2184703200 10800 1 EEST} {2202757200 7200 0 EET} {2216757600 10800 1 EEST} {2234811600 7200 0 EET} {2248207200 10800 1 EEST} {2266261200 7200 0 EET} {2279656800 10800 1 EEST} {2297710800 7200 0 EET} {2311106400 10800 1 EEST} {2329160400 7200 0 EET} {2342556000 10800 1 EEST} {2360610000 7200 0 EET} {2374610400 10800 1 EEST} {2392664400 7200 0 EET} {2406060000 10800 1 EEST} {2424114000 7200 0 EET} {2437509600 10800 1 EEST} {2455563600 7200 0 EET} {2468959200 10800 1 EEST} {2487013200 7200 0 EET} {2500408800 10800 1 EEST} {2518462800 7200 0 EET} {2531858400 10800 1 EEST} {2549912400 7200 0 EET} {2563912800 10800 1 EEST} {2581966800 7200 0 EET} {2595362400 10800 1 EEST} {2613416400 7200 0 EET} {2626812000 10800 1 EEST} {2644866000 7200 0 EET} {2658261600 10800 1 EEST} {2676315600 7200 0 EET} {2689711200 10800 1 EEST} {2707765200 7200 0 EET} {2721765600 10800 1 EEST} {2739819600 7200 0 EET} {2753215200 10800 1 EEST} {2771269200 7200 0 EET} {2784664800 10800 1 EEST} {2802718800 7200 0 EET} {2816114400 10800 1 EEST} {2834168400 7200 0 EET} {2847564000 10800 1 EEST} {2865618000 7200 0 EET} {2879013600 10800 1 EEST} {2897067600 7200 0 EET} {2911068000 10800 1 EEST} {2929122000 7200 0 EET} {2942517600 10800 1 EEST} {2960571600 7200 0 EET} {2973967200 10800 1 EEST} {2992021200 7200 0 EET} {3005416800 10800 1 EEST} {3023470800 7200 0 EET} {3036866400 10800 1 EEST} {3054920400 7200 0 EET} {3068316000 10800 1 EEST} {3086370000 7200 0 EET} {3100370400 10800 1 EEST} {3118424400 7200 0 EET} {3131820000 10800 1 EEST} {3149874000 7200 0 EET} {3163269600 10800 1 EEST} {3181323600 7200 0 EET} {3194719200 10800 1 EEST} {3212773200 7200 0 EET} {3226168800 10800 1 EEST} {3244222800 7200 0 EET} {3258223200 10800 1 EEST} {3276277200 7200 0 EET} {3289672800 10800 1 EEST} {3307726800 7200 0 EET} {3321122400 10800 1 EEST} {3339176400 7200 0 EET} {3352572000 10800 1 EEST} {3370626000 7200 0 EET} {3384021600 10800 1 EEST} {3402075600 7200 0 EET} {3415471200 10800 1 EEST} {3433525200 7200 0 EET} {3447525600 10800 1 EEST} {3465579600 7200 0 EET} {3478975200 10800 1 EEST} {3497029200 7200 0 EET} {3510424800 10800 1 EEST} {3528478800 7200 0 EET} {3541874400 10800 1 EEST} {3559928400 7200 0 EET} {3573324000 10800 1 EEST} {3591378000 7200 0 EET} {3605378400 10800 1 EEST} {3623432400 7200 0 EET} {3636828000 10800 1 EEST} {3654882000 7200 0 EET} {3668277600 10800 1 EEST} {3686331600 7200 0 EET} {3699727200 10800 1 EEST} {3717781200 7200 0 EET} {3731176800 10800 1 EEST} {3749230800 7200 0 EET} {3762626400 10800 1 EEST} {3780680400 7200 0 EET} {3794680800 10800 1 EEST} {3812734800 7200 0 EET} {3826130400 10800 1 EEST} {3844184400 7200 0 EET} {3857580000 10800 1 EEST} {3875634000 7200 0 EET} {3889029600 10800 1 EEST} {3907083600 7200 0 EET} {3920479200 10800 1 EEST} {3938533200 7200 0 EET} {3951928800 10800 1 EEST} {3969982800 7200 0 EET} {3983983200 10800 1 EEST} {4002037200 7200 0 EET} {4015432800 10800 1 EEST} {4033486800 7200 0 EET} {4046882400 10800 1 EEST} {4064936400 7200 0 EET} {4078332000 10800 1 EEST} {4096386000 7200 0 EET} } tcl8.6.5/library/tzdata/Asia/Sakhalin0000644000175000017500000000415212663660066017057 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Sakhalin) { {-9223372036854775808 34248 0 LMT} {-2031039048 32400 0 JCST} {-1017824400 32400 0 JST} {-768560400 39600 0 SAKMMTT} {354891600 43200 1 SAKST} {370699200 39600 0 SAKT} {386427600 43200 1 SAKST} {402235200 39600 0 SAKT} {417963600 43200 1 SAKST} {433771200 39600 0 SAKT} {449586000 43200 1 SAKST} {465318000 39600 0 SAKT} {481042800 43200 1 SAKST} {496767600 39600 0 SAKT} {512492400 43200 1 SAKST} {528217200 39600 0 SAKT} {543942000 43200 1 SAKST} {559666800 39600 0 SAKT} {575391600 43200 1 SAKST} {591116400 39600 0 SAKT} {606841200 43200 1 SAKST} {622566000 39600 0 SAKT} {638290800 43200 1 SAKST} {654620400 39600 0 SAKT} {670345200 36000 0 SAKMMTT} {670348800 39600 1 SAKST} {686073600 36000 0 SAKT} {695750400 39600 0 SAKMMTT} {701784000 43200 1 SAKST} {717505200 39600 0 SAKT} {733244400 43200 1 SAKST} {748969200 39600 0 SAKT} {764694000 43200 1 SAKST} {780418800 39600 0 SAKT} {796143600 43200 1 SAKST} {811868400 39600 0 SAKT} {828198000 43200 1 SAKST} {846342000 39600 0 SAKT} {859647600 36000 0 SAKMMTT} {859651200 39600 1 SAKST} {877795200 36000 0 SAKT} {891100800 39600 1 SAKST} {909244800 36000 0 SAKT} {922550400 39600 1 SAKST} {941299200 36000 0 SAKT} {954000000 39600 1 SAKST} {972748800 36000 0 SAKT} {985449600 39600 1 SAKST} {1004198400 36000 0 SAKT} {1017504000 39600 1 SAKST} {1035648000 36000 0 SAKT} {1048953600 39600 1 SAKST} {1067097600 36000 0 SAKT} {1080403200 39600 1 SAKST} {1099152000 36000 0 SAKT} {1111852800 39600 1 SAKST} {1130601600 36000 0 SAKT} {1143302400 39600 1 SAKST} {1162051200 36000 0 SAKT} {1174752000 39600 1 SAKST} {1193500800 36000 0 SAKT} {1206806400 39600 1 SAKST} {1224950400 36000 0 SAKT} {1238256000 39600 1 SAKST} {1256400000 36000 0 SAKT} {1269705600 39600 1 SAKST} {1288454400 36000 0 SAKT} {1301155200 39600 0 SAKT} {1414249200 36000 0 SAKT} } tcl8.6.5/library/tzdata/Asia/Magadan0000644000175000017500000000405412663660066016656 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Magadan) { {-9223372036854775808 36192 0 LMT} {-1441188192 36000 0 MAGT} {-1247565600 39600 0 MAGMMTT} {354891600 43200 1 MAGST} {370699200 39600 0 MAGT} {386427600 43200 1 MAGST} {402235200 39600 0 MAGT} {417963600 43200 1 MAGST} {433771200 39600 0 MAGT} {449586000 43200 1 MAGST} {465318000 39600 0 MAGT} {481042800 43200 1 MAGST} {496767600 39600 0 MAGT} {512492400 43200 1 MAGST} {528217200 39600 0 MAGT} {543942000 43200 1 MAGST} {559666800 39600 0 MAGT} {575391600 43200 1 MAGST} {591116400 39600 0 MAGT} {606841200 43200 1 MAGST} {622566000 39600 0 MAGT} {638290800 43200 1 MAGST} {654620400 39600 0 MAGT} {670345200 36000 0 MAGMMTT} {670348800 39600 1 MAGST} {686073600 36000 0 MAGT} {695750400 39600 0 MAGMMTT} {701784000 43200 1 MAGST} {717505200 39600 0 MAGT} {733244400 43200 1 MAGST} {748969200 39600 0 MAGT} {764694000 43200 1 MAGST} {780418800 39600 0 MAGT} {796143600 43200 1 MAGST} {811868400 39600 0 MAGT} {828198000 43200 1 MAGST} {846342000 39600 0 MAGT} {859647600 43200 1 MAGST} {877791600 39600 0 MAGT} {891097200 43200 1 MAGST} {909241200 39600 0 MAGT} {922546800 43200 1 MAGST} {941295600 39600 0 MAGT} {953996400 43200 1 MAGST} {972745200 39600 0 MAGT} {985446000 43200 1 MAGST} {1004194800 39600 0 MAGT} {1017500400 43200 1 MAGST} {1035644400 39600 0 MAGT} {1048950000 43200 1 MAGST} {1067094000 39600 0 MAGT} {1080399600 43200 1 MAGST} {1099148400 39600 0 MAGT} {1111849200 43200 1 MAGST} {1130598000 39600 0 MAGT} {1143298800 43200 1 MAGST} {1162047600 39600 0 MAGT} {1174748400 43200 1 MAGST} {1193497200 39600 0 MAGT} {1206802800 43200 1 MAGST} {1224946800 39600 0 MAGT} {1238252400 43200 1 MAGST} {1256396400 39600 0 MAGT} {1269702000 43200 1 MAGST} {1288450800 39600 0 MAGT} {1301151600 43200 0 MAGT} {1414245600 36000 0 MAGT} } tcl8.6.5/library/tzdata/Asia/Dubai0000644000175000017500000000021612661614721016341 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Dubai) { {-9223372036854775808 13272 0 LMT} {-1577936472 14400 0 GST} } tcl8.6.5/library/tzdata/Asia/Muscat0000644000175000017500000000024512663660066016560 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Dubai)]} { LoadTimeZoneFile Asia/Dubai } set TZData(:Asia/Muscat) $TZData(:Asia/Dubai) tcl8.6.5/library/tzdata/Asia/Tehran0000644000175000017500000001522412665113557016550 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Tehran) { {-9223372036854775808 12344 0 LMT} {-1704165944 12344 0 TMT} {-757394744 12600 0 IRST} {247177800 14400 0 IRST} {259272000 18000 1 IRDT} {277758000 14400 0 IRST} {283982400 12600 0 IRST} {290809800 16200 1 IRDT} {306531000 12600 0 IRST} {322432200 16200 1 IRDT} {338499000 12600 0 IRST} {673216200 16200 1 IRDT} {685481400 12600 0 IRST} {701209800 16200 1 IRDT} {717103800 12600 0 IRST} {732745800 16200 1 IRDT} {748639800 12600 0 IRST} {764281800 16200 1 IRDT} {780175800 12600 0 IRST} {795817800 16200 1 IRDT} {811711800 12600 0 IRST} {827353800 16200 1 IRDT} {843247800 12600 0 IRST} {858976200 16200 1 IRDT} {874870200 12600 0 IRST} {890512200 16200 1 IRDT} {906406200 12600 0 IRST} {922048200 16200 1 IRDT} {937942200 12600 0 IRST} {953584200 16200 1 IRDT} {969478200 12600 0 IRST} {985206600 16200 1 IRDT} {1001100600 12600 0 IRST} {1016742600 16200 1 IRDT} {1032636600 12600 0 IRST} {1048278600 16200 1 IRDT} {1064172600 12600 0 IRST} {1079814600 16200 1 IRDT} {1095708600 12600 0 IRST} {1111437000 16200 1 IRDT} {1127331000 12600 0 IRST} {1206045000 16200 1 IRDT} {1221939000 12600 0 IRST} {1237667400 16200 1 IRDT} {1253561400 12600 0 IRST} {1269203400 16200 1 IRDT} {1285097400 12600 0 IRST} {1300739400 16200 1 IRDT} {1316633400 12600 0 IRST} {1332275400 16200 1 IRDT} {1348169400 12600 0 IRST} {1363897800 16200 1 IRDT} {1379791800 12600 0 IRST} {1395433800 16200 1 IRDT} {1411327800 12600 0 IRST} {1426969800 16200 1 IRDT} {1442863800 12600 0 IRST} {1458505800 16200 1 IRDT} {1474399800 12600 0 IRST} {1490128200 16200 1 IRDT} {1506022200 12600 0 IRST} {1521664200 16200 1 IRDT} {1537558200 12600 0 IRST} {1553200200 16200 1 IRDT} {1569094200 12600 0 IRST} {1584736200 16200 1 IRDT} {1600630200 12600 0 IRST} {1616358600 16200 1 IRDT} {1632252600 12600 0 IRST} {1647894600 16200 1 IRDT} {1663788600 12600 0 IRST} {1679430600 16200 1 IRDT} {1695324600 12600 0 IRST} {1710966600 16200 1 IRDT} {1726860600 12600 0 IRST} {1742589000 16200 1 IRDT} {1758483000 12600 0 IRST} {1774125000 16200 1 IRDT} {1790019000 12600 0 IRST} {1805661000 16200 1 IRDT} {1821555000 12600 0 IRST} {1837197000 16200 1 IRDT} {1853091000 12600 0 IRST} {1868733000 16200 1 IRDT} {1884627000 12600 0 IRST} {1900355400 16200 1 IRDT} {1916249400 12600 0 IRST} {1931891400 16200 1 IRDT} {1947785400 12600 0 IRST} {1963427400 16200 1 IRDT} {1979321400 12600 0 IRST} {1994963400 16200 1 IRDT} {2010857400 12600 0 IRST} {2026585800 16200 1 IRDT} {2042479800 12600 0 IRST} {2058121800 16200 1 IRDT} {2074015800 12600 0 IRST} {2089657800 16200 1 IRDT} {2105551800 12600 0 IRST} {2121193800 16200 1 IRDT} {2137087800 12600 0 IRST} {2152729800 16200 1 IRDT} {2168623800 12600 0 IRST} {2184265800 16200 1 IRDT} {2200159800 12600 0 IRST} {2215888200 16200 1 IRDT} {2231782200 12600 0 IRST} {2247424200 16200 1 IRDT} {2263318200 12600 0 IRST} {2278960200 16200 1 IRDT} {2294854200 12600 0 IRST} {2310496200 16200 1 IRDT} {2326390200 12600 0 IRST} {2342118600 16200 1 IRDT} {2358012600 12600 0 IRST} {2373654600 16200 1 IRDT} {2389548600 12600 0 IRST} {2405190600 16200 1 IRDT} {2421084600 12600 0 IRST} {2436726600 16200 1 IRDT} {2452620600 12600 0 IRST} {2468349000 16200 1 IRDT} {2484243000 12600 0 IRST} {2499885000 16200 1 IRDT} {2515779000 12600 0 IRST} {2531421000 16200 1 IRDT} {2547315000 12600 0 IRST} {2562957000 16200 1 IRDT} {2578851000 12600 0 IRST} {2594579400 16200 1 IRDT} {2610473400 12600 0 IRST} {2626115400 16200 1 IRDT} {2642009400 12600 0 IRST} {2657651400 16200 1 IRDT} {2673545400 12600 0 IRST} {2689187400 16200 1 IRDT} {2705081400 12600 0 IRST} {2720809800 16200 1 IRDT} {2736703800 12600 0 IRST} {2752345800 16200 1 IRDT} {2768239800 12600 0 IRST} {2783881800 16200 1 IRDT} {2799775800 12600 0 IRST} {2815417800 16200 1 IRDT} {2831311800 12600 0 IRST} {2847040200 16200 1 IRDT} {2862934200 12600 0 IRST} {2878576200 16200 1 IRDT} {2894470200 12600 0 IRST} {2910112200 16200 1 IRDT} {2926006200 12600 0 IRST} {2941648200 16200 1 IRDT} {2957542200 12600 0 IRST} {2973270600 16200 1 IRDT} {2989164600 12600 0 IRST} {3004806600 16200 1 IRDT} {3020700600 12600 0 IRST} {3036342600 16200 1 IRDT} {3052236600 12600 0 IRST} {3067878600 16200 1 IRDT} {3083772600 12600 0 IRST} {3099501000 16200 1 IRDT} {3115395000 12600 0 IRST} {3131037000 16200 1 IRDT} {3146931000 12600 0 IRST} {3162573000 16200 1 IRDT} {3178467000 12600 0 IRST} {3194109000 16200 1 IRDT} {3210003000 12600 0 IRST} {3225731400 16200 1 IRDT} {3241625400 12600 0 IRST} {3257267400 16200 1 IRDT} {3273161400 12600 0 IRST} {3288803400 16200 1 IRDT} {3304697400 12600 0 IRST} {3320339400 16200 1 IRDT} {3336233400 12600 0 IRST} {3351961800 16200 1 IRDT} {3367855800 12600 0 IRST} {3383497800 16200 1 IRDT} {3399391800 12600 0 IRST} {3415033800 16200 1 IRDT} {3430927800 12600 0 IRST} {3446569800 16200 1 IRDT} {3462463800 12600 0 IRST} {3478192200 16200 1 IRDT} {3494086200 12600 0 IRST} {3509728200 16200 1 IRDT} {3525622200 12600 0 IRST} {3541264200 16200 1 IRDT} {3557158200 12600 0 IRST} {3572800200 16200 1 IRDT} {3588694200 12600 0 IRST} {3604422600 16200 1 IRDT} {3620316600 12600 0 IRST} {3635958600 16200 1 IRDT} {3651852600 12600 0 IRST} {3667494600 16200 1 IRDT} {3683388600 12600 0 IRST} {3699030600 16200 1 IRDT} {3714924600 12600 0 IRST} {3730653000 16200 1 IRDT} {3746547000 12600 0 IRST} {3762189000 16200 1 IRDT} {3778083000 12600 0 IRST} {3793725000 16200 1 IRDT} {3809619000 12600 0 IRST} {3825261000 16200 1 IRDT} {3841155000 12600 0 IRST} {3856883400 16200 1 IRDT} {3872777400 12600 0 IRST} {3888419400 16200 1 IRDT} {3904313400 12600 0 IRST} {3919955400 16200 1 IRDT} {3935849400 12600 0 IRST} {3951491400 16200 1 IRDT} {3967385400 12600 0 IRST} {3983113800 16200 1 IRDT} {3999007800 12600 0 IRST} {4014649800 16200 1 IRDT} {4030543800 12600 0 IRST} {4046185800 16200 1 IRDT} {4062079800 12600 0 IRST} {4077721800 16200 1 IRDT} {4093615800 12600 0 IRST} } tcl8.6.5/library/tzdata/Asia/Kuching0000644000175000017500000000127712661614721016715 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Kuching) { {-9223372036854775808 26480 0 LMT} {-1383463280 27000 0 BORT} {-1167636600 28800 0 BORT} {-1082448000 30000 1 BORTST} {-1074586800 28800 0 BORT} {-1050825600 30000 1 BORTST} {-1042964400 28800 0 BORT} {-1019289600 30000 1 BORTST} {-1011428400 28800 0 BORT} {-987753600 30000 1 BORTST} {-979892400 28800 0 BORT} {-956217600 30000 1 BORTST} {-948356400 28800 0 BORT} {-924595200 30000 1 BORTST} {-916734000 28800 0 BORT} {-893059200 30000 1 BORTST} {-885198000 28800 0 BORT} {-879667200 32400 0 JST} {-767005200 28800 0 BORT} {378662400 28800 0 MYT} } tcl8.6.5/library/tzdata/Asia/Hovd0000644000175000017500000001501112663660066016221 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Hovd) { {-9223372036854775808 21996 0 LMT} {-2032927596 21600 0 HOVT} {252439200 25200 0 HOVT} {417978000 28800 1 HOVST} {433785600 25200 0 HOVT} {449600400 28800 1 HOVST} {465321600 25200 0 HOVT} {481050000 28800 1 HOVST} {496771200 25200 0 HOVT} {512499600 28800 1 HOVST} {528220800 25200 0 HOVT} {543949200 28800 1 HOVST} {559670400 25200 0 HOVT} {575398800 28800 1 HOVST} {591120000 25200 0 HOVT} {606848400 28800 1 HOVST} {622569600 25200 0 HOVT} {638298000 28800 1 HOVST} {654624000 25200 0 HOVT} {670352400 28800 1 HOVST} {686073600 25200 0 HOVT} {701802000 28800 1 HOVST} {717523200 25200 0 HOVT} {733251600 28800 1 HOVST} {748972800 25200 0 HOVT} {764701200 28800 1 HOVST} {780422400 25200 0 HOVT} {796150800 28800 1 HOVST} {811872000 25200 0 HOVT} {828205200 28800 1 HOVST} {843926400 25200 0 HOVT} {859654800 28800 1 HOVST} {875376000 25200 0 HOVT} {891104400 28800 1 HOVST} {906825600 25200 0 HOVT} {988398000 28800 1 HOVST} {1001700000 25200 0 HOVT} {1017428400 28800 1 HOVST} {1033149600 25200 0 HOVT} {1048878000 28800 1 HOVST} {1064599200 25200 0 HOVT} {1080327600 28800 1 HOVST} {1096048800 25200 0 HOVT} {1111777200 28800 1 HOVST} {1127498400 25200 0 HOVT} {1143226800 28800 1 HOVST} {1159552800 25200 0 HOVT} {1427482800 28800 1 HOVST} {1443196800 25200 0 HOVT} {1458932400 28800 1 HOVST} {1474646400 25200 0 HOVT} {1490382000 28800 1 HOVST} {1506700800 25200 0 HOVT} {1522436400 28800 1 HOVST} {1538150400 25200 0 HOVT} {1553886000 28800 1 HOVST} {1569600000 25200 0 HOVT} {1585335600 28800 1 HOVST} {1601049600 25200 0 HOVT} {1616785200 28800 1 HOVST} {1632499200 25200 0 HOVT} {1648234800 28800 1 HOVST} {1663948800 25200 0 HOVT} {1679684400 28800 1 HOVST} {1696003200 25200 0 HOVT} {1711738800 28800 1 HOVST} {1727452800 25200 0 HOVT} {1743188400 28800 1 HOVST} {1758902400 25200 0 HOVT} {1774638000 28800 1 HOVST} {1790352000 25200 0 HOVT} {1806087600 28800 1 HOVST} {1821801600 25200 0 HOVT} {1837537200 28800 1 HOVST} {1853856000 25200 0 HOVT} {1869591600 28800 1 HOVST} {1885305600 25200 0 HOVT} {1901041200 28800 1 HOVST} {1916755200 25200 0 HOVT} {1932490800 28800 1 HOVST} {1948204800 25200 0 HOVT} {1963940400 28800 1 HOVST} {1979654400 25200 0 HOVT} {1995390000 28800 1 HOVST} {2011104000 25200 0 HOVT} {2026839600 28800 1 HOVST} {2043158400 25200 0 HOVT} {2058894000 28800 1 HOVST} {2074608000 25200 0 HOVT} {2090343600 28800 1 HOVST} {2106057600 25200 0 HOVT} {2121793200 28800 1 HOVST} {2137507200 25200 0 HOVT} {2153242800 28800 1 HOVST} {2168956800 25200 0 HOVT} {2184692400 28800 1 HOVST} {2200406400 25200 0 HOVT} {2216746800 28800 1 HOVST} {2232460800 25200 0 HOVT} {2248196400 28800 1 HOVST} {2263910400 25200 0 HOVT} {2279646000 28800 1 HOVST} {2295360000 25200 0 HOVT} {2311095600 28800 1 HOVST} {2326809600 25200 0 HOVT} {2342545200 28800 1 HOVST} {2358259200 25200 0 HOVT} {2373994800 28800 1 HOVST} {2390313600 25200 0 HOVT} {2406049200 28800 1 HOVST} {2421763200 25200 0 HOVT} {2437498800 28800 1 HOVST} {2453212800 25200 0 HOVT} {2468948400 28800 1 HOVST} {2484662400 25200 0 HOVT} {2500398000 28800 1 HOVST} {2516112000 25200 0 HOVT} {2531847600 28800 1 HOVST} {2547561600 25200 0 HOVT} {2563297200 28800 1 HOVST} {2579616000 25200 0 HOVT} {2595351600 28800 1 HOVST} {2611065600 25200 0 HOVT} {2626801200 28800 1 HOVST} {2642515200 25200 0 HOVT} {2658250800 28800 1 HOVST} {2673964800 25200 0 HOVT} {2689700400 28800 1 HOVST} {2705414400 25200 0 HOVT} {2721150000 28800 1 HOVST} {2737468800 25200 0 HOVT} {2753204400 28800 1 HOVST} {2768918400 25200 0 HOVT} {2784654000 28800 1 HOVST} {2800368000 25200 0 HOVT} {2816103600 28800 1 HOVST} {2831817600 25200 0 HOVT} {2847553200 28800 1 HOVST} {2863267200 25200 0 HOVT} {2879002800 28800 1 HOVST} {2894716800 25200 0 HOVT} {2910452400 28800 1 HOVST} {2926771200 25200 0 HOVT} {2942506800 28800 1 HOVST} {2958220800 25200 0 HOVT} {2973956400 28800 1 HOVST} {2989670400 25200 0 HOVT} {3005406000 28800 1 HOVST} {3021120000 25200 0 HOVT} {3036855600 28800 1 HOVST} {3052569600 25200 0 HOVT} {3068305200 28800 1 HOVST} {3084019200 25200 0 HOVT} {3100359600 28800 1 HOVST} {3116073600 25200 0 HOVT} {3131809200 28800 1 HOVST} {3147523200 25200 0 HOVT} {3163258800 28800 1 HOVST} {3178972800 25200 0 HOVT} {3194708400 28800 1 HOVST} {3210422400 25200 0 HOVT} {3226158000 28800 1 HOVST} {3241872000 25200 0 HOVT} {3257607600 28800 1 HOVST} {3273926400 25200 0 HOVT} {3289662000 28800 1 HOVST} {3305376000 25200 0 HOVT} {3321111600 28800 1 HOVST} {3336825600 25200 0 HOVT} {3352561200 28800 1 HOVST} {3368275200 25200 0 HOVT} {3384010800 28800 1 HOVST} {3399724800 25200 0 HOVT} {3415460400 28800 1 HOVST} {3431174400 25200 0 HOVT} {3446910000 28800 1 HOVST} {3463228800 25200 0 HOVT} {3478964400 28800 1 HOVST} {3494678400 25200 0 HOVT} {3510414000 28800 1 HOVST} {3526128000 25200 0 HOVT} {3541863600 28800 1 HOVST} {3557577600 25200 0 HOVT} {3573313200 28800 1 HOVST} {3589027200 25200 0 HOVT} {3604762800 28800 1 HOVST} {3621081600 25200 0 HOVT} {3636817200 28800 1 HOVST} {3652531200 25200 0 HOVT} {3668266800 28800 1 HOVST} {3683980800 25200 0 HOVT} {3699716400 28800 1 HOVST} {3715430400 25200 0 HOVT} {3731166000 28800 1 HOVST} {3746880000 25200 0 HOVT} {3762615600 28800 1 HOVST} {3778329600 25200 0 HOVT} {3794065200 28800 1 HOVST} {3810384000 25200 0 HOVT} {3826119600 28800 1 HOVST} {3841833600 25200 0 HOVT} {3857569200 28800 1 HOVST} {3873283200 25200 0 HOVT} {3889018800 28800 1 HOVST} {3904732800 25200 0 HOVT} {3920468400 28800 1 HOVST} {3936182400 25200 0 HOVT} {3951918000 28800 1 HOVST} {3967632000 25200 0 HOVT} {3983972400 28800 1 HOVST} {3999686400 25200 0 HOVT} {4015422000 28800 1 HOVST} {4031136000 25200 0 HOVT} {4046871600 28800 1 HOVST} {4062585600 25200 0 HOVT} {4078321200 28800 1 HOVST} {4094035200 25200 0 HOVT} } tcl8.6.5/library/tzdata/Asia/Tel_Aviv0000644000175000017500000000026312661614722017031 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Jerusalem)]} { LoadTimeZoneFile Asia/Jerusalem } set TZData(:Asia/Tel_Aviv) $TZData(:Asia/Jerusalem) tcl8.6.5/library/tzdata/Asia/Taipei0000644000175000017500000000242312663660066016537 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Taipei) { {-9223372036854775808 29160 0 LMT} {-2335248360 28800 0 JWST} {-1017820800 32400 0 JST} {-766224000 28800 0 CST} {-745833600 32400 1 CDT} {-733827600 28800 0 CST} {-716889600 32400 1 CDT} {-699613200 28800 0 CST} {-683884800 32400 1 CDT} {-670669200 28800 0 CST} {-652348800 32400 1 CDT} {-639133200 28800 0 CST} {-620812800 32400 1 CDT} {-607597200 28800 0 CST} {-589276800 32400 1 CDT} {-576061200 28800 0 CST} {-562924800 32400 1 CDT} {-541760400 28800 0 CST} {-528710400 32400 1 CDT} {-510224400 28800 0 CST} {-497174400 32400 1 CDT} {-478688400 28800 0 CST} {-465638400 32400 1 CDT} {-449830800 28800 0 CST} {-434016000 32400 1 CDT} {-418208400 28800 0 CST} {-402480000 32400 1 CDT} {-386672400 28800 0 CST} {-370944000 32400 1 CDT} {-355136400 28800 0 CST} {-339408000 32400 1 CDT} {-323600400 28800 0 CST} {-302515200 32400 1 CDT} {-291978000 28800 0 CST} {-270979200 32400 1 CDT} {-260442000 28800 0 CST} {133977600 32400 1 CDT} {149785200 28800 0 CST} {165513600 32400 1 CDT} {181321200 28800 0 CST} {299606400 32400 1 CDT} {307551600 28800 0 CST} } tcl8.6.5/library/tzdata/Asia/Pontianak0000644000175000017500000000053612663660066017253 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Pontianak) { {-9223372036854775808 26240 0 LMT} {-1946186240 26240 0 PMT} {-1172906240 27000 0 WIB} {-881220600 32400 0 JST} {-766054800 27000 0 WIB} {-683883000 28800 0 WIB} {-620812800 27000 0 WIB} {-189415800 28800 0 WITA} {567964800 25200 0 WIB} } tcl8.6.5/library/tzdata/Asia/Ujung_Pandang0000644000175000017500000000026512661614722020042 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Makassar)]} { LoadTimeZoneFile Asia/Makassar } set TZData(:Asia/Ujung_Pandang) $TZData(:Asia/Makassar) tcl8.6.5/library/tzdata/Asia/Istanbul0000644000175000017500000000026612661614722017104 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Istanbul)]} { LoadTimeZoneFile Europe/Istanbul } set TZData(:Asia/Istanbul) $TZData(:Europe/Istanbul) tcl8.6.5/library/tzdata/Asia/Chita0000644000175000017500000000411012665113557016347 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Chita) { {-9223372036854775808 27232 0 LMT} {-1579419232 28800 0 YAKT} {-1247558400 32400 0 YAKMMTT} {354898800 36000 1 YAKST} {370706400 32400 0 YAKT} {386434800 36000 1 YAKST} {402242400 32400 0 YAKT} {417970800 36000 1 YAKST} {433778400 32400 0 YAKT} {449593200 36000 1 YAKST} {465325200 32400 0 YAKT} {481050000 36000 1 YAKST} {496774800 32400 0 YAKT} {512499600 36000 1 YAKST} {528224400 32400 0 YAKT} {543949200 36000 1 YAKST} {559674000 32400 0 YAKT} {575398800 36000 1 YAKST} {591123600 32400 0 YAKT} {606848400 36000 1 YAKST} {622573200 32400 0 YAKT} {638298000 36000 1 YAKST} {654627600 32400 0 YAKT} {670352400 28800 0 YAKMMTT} {670356000 32400 1 YAKST} {686080800 28800 0 YAKT} {695757600 32400 0 YAKMMTT} {701791200 36000 1 YAKST} {717512400 32400 0 YAKT} {733251600 36000 1 YAKST} {748976400 32400 0 YAKT} {764701200 36000 1 YAKST} {780426000 32400 0 YAKT} {796150800 36000 1 YAKST} {811875600 32400 0 YAKT} {828205200 36000 1 YAKST} {846349200 32400 0 YAKT} {859654800 36000 1 YAKST} {877798800 32400 0 YAKT} {891104400 36000 1 YAKST} {909248400 32400 0 YAKT} {922554000 36000 1 YAKST} {941302800 32400 0 YAKT} {954003600 36000 1 YAKST} {972752400 32400 0 YAKT} {985453200 36000 1 YAKST} {1004202000 32400 0 YAKT} {1017507600 36000 1 YAKST} {1035651600 32400 0 YAKT} {1048957200 36000 1 YAKST} {1067101200 32400 0 YAKT} {1080406800 36000 1 YAKST} {1099155600 32400 0 YAKT} {1111856400 36000 1 YAKST} {1130605200 32400 0 YAKT} {1143306000 36000 1 YAKST} {1162054800 32400 0 YAKT} {1174755600 36000 1 YAKST} {1193504400 32400 0 YAKT} {1206810000 36000 1 YAKST} {1224954000 32400 0 YAKT} {1238259600 36000 1 YAKST} {1256403600 32400 0 YAKT} {1269709200 36000 1 YAKST} {1288458000 32400 0 YAKT} {1301158800 36000 0 YAKT} {1414252800 28800 0 IRKT} {1459015200 32400 0 YAKT} } tcl8.6.5/library/tzdata/Asia/Shanghai0000644000175000017500000000116212663660066017045 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Shanghai) { {-9223372036854775808 29143 0 LMT} {-2177481943 28800 0 CST} {-933494400 32400 1 CDT} {-923130000 28800 0 CST} {-908784000 32400 1 CDT} {-891594000 28800 0 CST} {-662716800 28800 0 CST} {515520000 32400 1 CDT} {527007600 28800 0 CST} {545155200 32400 1 CDT} {558457200 28800 0 CST} {576604800 32400 1 CDT} {589906800 28800 0 CST} {608659200 32400 1 CDT} {621961200 28800 0 CST} {640108800 32400 1 CDT} {653410800 28800 0 CST} {671558400 32400 1 CDT} {684860400 28800 0 CST} } tcl8.6.5/library/tzdata/Asia/Aqtobe0000644000175000017500000000317012661614721016532 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Aqtobe) { {-9223372036854775808 13720 0 LMT} {-1441165720 14400 0 AKTT} {-1247544000 18000 0 AKTT} {354913200 21600 1 AKTST} {370720800 21600 0 AKTT} {386445600 18000 0 AKTT} {386449200 21600 1 AKTST} {402256800 18000 0 AKTT} {417985200 21600 1 AKTST} {433792800 18000 0 AKTT} {449607600 21600 1 AKTST} {465339600 18000 0 AKTT} {481064400 21600 1 AKTST} {496789200 18000 0 AKTT} {512514000 21600 1 AKTST} {528238800 18000 0 AKTT} {543963600 21600 1 AKTST} {559688400 18000 0 AKTT} {575413200 21600 1 AKTST} {591138000 18000 0 AKTT} {606862800 21600 1 AKTST} {622587600 18000 0 AKTT} {638312400 21600 1 AKTST} {654642000 18000 0 AKTT} {662670000 18000 0 AKTT} {692823600 18000 0 AQTT} {701805600 21600 1 AQTST} {717526800 18000 0 AQTT} {733266000 21600 1 AQTST} {748990800 18000 0 AQTT} {764715600 21600 1 AQTST} {780440400 18000 0 AQTT} {796165200 21600 1 AQTST} {811890000 18000 0 AQTT} {828219600 21600 1 AQTST} {846363600 18000 0 AQTT} {859669200 21600 1 AQTST} {877813200 18000 0 AQTT} {891118800 21600 1 AQTST} {909262800 18000 0 AQTT} {922568400 21600 1 AQTST} {941317200 18000 0 AQTT} {954018000 21600 1 AQTST} {972766800 18000 0 AQTT} {985467600 21600 1 AQTST} {1004216400 18000 0 AQTT} {1017522000 21600 1 AQTST} {1035666000 18000 0 AQTT} {1048971600 21600 1 AQTST} {1067115600 18000 0 AQTT} {1080421200 21600 1 AQTST} {1099170000 18000 0 AQTT} {1110826800 18000 0 AQTT} } tcl8.6.5/library/tzdata/Asia/Kabul0000644000175000017500000000025312661614721016354 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Kabul) { {-9223372036854775808 16608 0 LMT} {-2524538208 14400 0 AFT} {-788932800 16200 0 AFT} } tcl8.6.5/library/tzdata/Asia/Kathmandu0000644000175000017500000000025612663653132017236 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Kathmandu) { {-9223372036854775808 20476 0 LMT} {-1577943676 19800 0 IST} {504901800 20700 0 NPT} } tcl8.6.5/library/tzdata/Asia/Amman0000644000175000017500000001561712663660066016366 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Amman) { {-9223372036854775808 8624 0 LMT} {-1230776624 7200 0 EET} {108165600 10800 1 EEST} {118270800 7200 0 EET} {136591200 10800 1 EEST} {149806800 7200 0 EET} {168127200 10800 1 EEST} {181342800 7200 0 EET} {199749600 10800 1 EEST} {215643600 7200 0 EET} {231285600 10800 1 EEST} {244501200 7200 0 EET} {262735200 10800 1 EEST} {275950800 7200 0 EET} {481154400 10800 1 EEST} {496962000 7200 0 EET} {512949600 10800 1 EEST} {528670800 7200 0 EET} {544399200 10800 1 EEST} {560120400 7200 0 EET} {575848800 10800 1 EEST} {592174800 7200 0 EET} {610581600 10800 1 EEST} {623624400 7200 0 EET} {641167200 10800 1 EEST} {655074000 7200 0 EET} {671839200 10800 1 EEST} {685918800 7200 0 EET} {702856800 10800 1 EEST} {717973200 7200 0 EET} {733701600 10800 1 EEST} {749422800 7200 0 EET} {765151200 10800 1 EEST} {779662800 7200 0 EET} {797205600 10800 1 EEST} {811116000 7200 0 EET} {828655200 10800 1 EEST} {843170400 7200 0 EET} {860104800 10800 1 EEST} {874620000 7200 0 EET} {891554400 10800 1 EEST} {906069600 7200 0 EET} {930780000 10800 1 EEST} {938124000 7200 0 EET} {954367200 10800 1 EEST} {970178400 7200 0 EET} {985816800 10800 1 EEST} {1001628000 7200 0 EET} {1017352800 10800 1 EEST} {1033077600 7200 0 EET} {1048802400 10800 1 EEST} {1066946400 7200 0 EET} {1080252000 10800 1 EEST} {1097791200 7200 0 EET} {1112306400 10800 1 EEST} {1128031200 7200 0 EET} {1143756000 10800 1 EEST} {1161900000 7200 0 EET} {1175205600 10800 1 EEST} {1193349600 7200 0 EET} {1206655200 10800 1 EEST} {1225404000 7200 0 EET} {1238104800 10800 1 EEST} {1256853600 7200 0 EET} {1269554400 10800 1 EEST} {1288303200 7200 0 EET} {1301608800 10800 1 EEST} {1319752800 7200 0 EET} {1333058400 10800 1 EEST} {1387486800 7200 0 EET} {1395957600 10800 1 EEST} {1414706400 7200 0 EET} {1427407200 10800 1 EEST} {1446156000 7200 0 EET} {1459461600 10800 1 EEST} {1477605600 7200 0 EET} {1490911200 10800 1 EEST} {1509055200 7200 0 EET} {1522360800 10800 1 EEST} {1540504800 7200 0 EET} {1553810400 10800 1 EEST} {1571954400 7200 0 EET} {1585260000 10800 1 EEST} {1604008800 7200 0 EET} {1616709600 10800 1 EEST} {1635458400 7200 0 EET} {1648764000 10800 1 EEST} {1666908000 7200 0 EET} {1680213600 10800 1 EEST} {1698357600 7200 0 EET} {1711663200 10800 1 EEST} {1729807200 7200 0 EET} {1743112800 10800 1 EEST} {1761861600 7200 0 EET} {1774562400 10800 1 EEST} {1793311200 7200 0 EET} {1806012000 10800 1 EEST} {1824760800 7200 0 EET} {1838066400 10800 1 EEST} {1856210400 7200 0 EET} {1869516000 10800 1 EEST} {1887660000 7200 0 EET} {1900965600 10800 1 EEST} {1919109600 7200 0 EET} {1932415200 10800 1 EEST} {1951164000 7200 0 EET} {1963864800 10800 1 EEST} {1982613600 7200 0 EET} {1995919200 10800 1 EEST} {2014063200 7200 0 EET} {2027368800 10800 1 EEST} {2045512800 7200 0 EET} {2058818400 10800 1 EEST} {2076962400 7200 0 EET} {2090268000 10800 1 EEST} {2109016800 7200 0 EET} {2121717600 10800 1 EEST} {2140466400 7200 0 EET} {2153167200 10800 1 EEST} {2171916000 7200 0 EET} {2185221600 10800 1 EEST} {2203365600 7200 0 EET} {2216671200 10800 1 EEST} {2234815200 7200 0 EET} {2248120800 10800 1 EEST} {2266264800 7200 0 EET} {2279570400 10800 1 EEST} {2298319200 7200 0 EET} {2311020000 10800 1 EEST} {2329768800 7200 0 EET} {2343074400 10800 1 EEST} {2361218400 7200 0 EET} {2374524000 10800 1 EEST} {2392668000 7200 0 EET} {2405973600 10800 1 EEST} {2424117600 7200 0 EET} {2437423200 10800 1 EEST} {2455567200 7200 0 EET} {2468872800 10800 1 EEST} {2487621600 7200 0 EET} {2500322400 10800 1 EEST} {2519071200 7200 0 EET} {2532376800 10800 1 EEST} {2550520800 7200 0 EET} {2563826400 10800 1 EEST} {2581970400 7200 0 EET} {2595276000 10800 1 EEST} {2613420000 7200 0 EET} {2626725600 10800 1 EEST} {2645474400 7200 0 EET} {2658175200 10800 1 EEST} {2676924000 7200 0 EET} {2689624800 10800 1 EEST} {2708373600 7200 0 EET} {2721679200 10800 1 EEST} {2739823200 7200 0 EET} {2753128800 10800 1 EEST} {2771272800 7200 0 EET} {2784578400 10800 1 EEST} {2802722400 7200 0 EET} {2816028000 10800 1 EEST} {2834776800 7200 0 EET} {2847477600 10800 1 EEST} {2866226400 7200 0 EET} {2879532000 10800 1 EEST} {2897676000 7200 0 EET} {2910981600 10800 1 EEST} {2929125600 7200 0 EET} {2942431200 10800 1 EEST} {2960575200 7200 0 EET} {2973880800 10800 1 EEST} {2992629600 7200 0 EET} {3005330400 10800 1 EEST} {3024079200 7200 0 EET} {3036780000 10800 1 EEST} {3055528800 7200 0 EET} {3068834400 10800 1 EEST} {3086978400 7200 0 EET} {3100284000 10800 1 EEST} {3118428000 7200 0 EET} {3131733600 10800 1 EEST} {3149877600 7200 0 EET} {3163183200 10800 1 EEST} {3181932000 7200 0 EET} {3194632800 10800 1 EEST} {3213381600 7200 0 EET} {3226687200 10800 1 EEST} {3244831200 7200 0 EET} {3258136800 10800 1 EEST} {3276280800 7200 0 EET} {3289586400 10800 1 EEST} {3307730400 7200 0 EET} {3321036000 10800 1 EEST} {3339180000 7200 0 EET} {3352485600 10800 1 EEST} {3371234400 7200 0 EET} {3383935200 10800 1 EEST} {3402684000 7200 0 EET} {3415989600 10800 1 EEST} {3434133600 7200 0 EET} {3447439200 10800 1 EEST} {3465583200 7200 0 EET} {3478888800 10800 1 EEST} {3497032800 7200 0 EET} {3510338400 10800 1 EEST} {3529087200 7200 0 EET} {3541788000 10800 1 EEST} {3560536800 7200 0 EET} {3573237600 10800 1 EEST} {3591986400 7200 0 EET} {3605292000 10800 1 EEST} {3623436000 7200 0 EET} {3636741600 10800 1 EEST} {3654885600 7200 0 EET} {3668191200 10800 1 EEST} {3686335200 7200 0 EET} {3699640800 10800 1 EEST} {3718389600 7200 0 EET} {3731090400 10800 1 EEST} {3749839200 7200 0 EET} {3763144800 10800 1 EEST} {3781288800 7200 0 EET} {3794594400 10800 1 EEST} {3812738400 7200 0 EET} {3826044000 10800 1 EEST} {3844188000 7200 0 EET} {3857493600 10800 1 EEST} {3876242400 7200 0 EET} {3888943200 10800 1 EEST} {3907692000 7200 0 EET} {3920392800 10800 1 EEST} {3939141600 7200 0 EET} {3952447200 10800 1 EEST} {3970591200 7200 0 EET} {3983896800 10800 1 EEST} {4002040800 7200 0 EET} {4015346400 10800 1 EEST} {4033490400 7200 0 EET} {4046796000 10800 1 EEST} {4065544800 7200 0 EET} {4078245600 10800 1 EEST} {4096994400 7200 0 EET} } tcl8.6.5/library/tzdata/Asia/Jerusalem0000644000175000017500000001701212663660066017253 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Jerusalem) { {-9223372036854775808 8454 0 LMT} {-2840149254 8440 0 JMT} {-1641003640 7200 0 IST} {-933645600 10800 1 IDT} {-857358000 7200 0 IST} {-844300800 10800 1 IDT} {-825822000 7200 0 IST} {-812685600 10800 1 IDT} {-794199600 7200 0 IST} {-779853600 10800 1 IDT} {-762656400 7200 0 IST} {-748310400 10800 1 IDT} {-731127600 7200 0 IST} {-681962400 14400 1 IDDT} {-673243200 10800 1 IDT} {-667962000 7200 0 IST} {-652327200 10800 1 IDT} {-636426000 7200 0 IST} {-622087200 10800 1 IDT} {-608947200 7200 0 IST} {-591847200 10800 1 IDT} {-572486400 7200 0 IST} {-558576000 10800 1 IDT} {-542851200 7200 0 IST} {-527731200 10800 1 IDT} {-514425600 7200 0 IST} {-490845600 10800 1 IDT} {-482986800 7200 0 IST} {-459475200 10800 1 IDT} {-451537200 7200 0 IST} {-428551200 10800 1 IDT} {-418262400 7200 0 IST} {-400032000 10800 1 IDT} {-387428400 7200 0 IST} {142380000 10800 1 IDT} {150843600 7200 0 IST} {167176800 10800 1 IDT} {178664400 7200 0 IST} {482277600 10800 1 IDT} {495579600 7200 0 IST} {516751200 10800 1 IDT} {526424400 7200 0 IST} {545436000 10800 1 IDT} {558478800 7200 0 IST} {576626400 10800 1 IDT} {589323600 7200 0 IST} {609890400 10800 1 IDT} {620773200 7200 0 IST} {638316000 10800 1 IDT} {651618000 7200 0 IST} {669765600 10800 1 IDT} {683672400 7200 0 IST} {701820000 10800 1 IDT} {715726800 7200 0 IST} {733701600 10800 1 IDT} {747176400 7200 0 IST} {765151200 10800 1 IDT} {778021200 7200 0 IST} {796600800 10800 1 IDT} {810075600 7200 0 IST} {826840800 10800 1 IDT} {842821200 7200 0 IST} {858895200 10800 1 IDT} {874184400 7200 0 IST} {890344800 10800 1 IDT} {905029200 7200 0 IST} {923011200 10800 1 IDT} {936313200 7200 0 IST} {955670400 10800 1 IDT} {970783200 7200 0 IST} {986770800 10800 1 IDT} {1001282400 7200 0 IST} {1017356400 10800 1 IDT} {1033941600 7200 0 IST} {1048806000 10800 1 IDT} {1065132000 7200 0 IST} {1081292400 10800 1 IDT} {1095804000 7200 0 IST} {1112313600 10800 1 IDT} {1128812400 7200 0 IST} {1143763200 10800 1 IDT} {1159657200 7200 0 IST} {1175212800 10800 1 IDT} {1189897200 7200 0 IST} {1206662400 10800 1 IDT} {1223161200 7200 0 IST} {1238112000 10800 1 IDT} {1254006000 7200 0 IST} {1269561600 10800 1 IDT} {1284246000 7200 0 IST} {1301616000 10800 1 IDT} {1317510000 7200 0 IST} {1333065600 10800 1 IDT} {1348354800 7200 0 IST} {1364515200 10800 1 IDT} {1382828400 7200 0 IST} {1395964800 10800 1 IDT} {1414278000 7200 0 IST} {1427414400 10800 1 IDT} {1445727600 7200 0 IST} {1458864000 10800 1 IDT} {1477782000 7200 0 IST} {1490313600 10800 1 IDT} {1509231600 7200 0 IST} {1521763200 10800 1 IDT} {1540681200 7200 0 IST} {1553817600 10800 1 IDT} {1572130800 7200 0 IST} {1585267200 10800 1 IDT} {1603580400 7200 0 IST} {1616716800 10800 1 IDT} {1635634800 7200 0 IST} {1648166400 10800 1 IDT} {1667084400 7200 0 IST} {1679616000 10800 1 IDT} {1698534000 7200 0 IST} {1711670400 10800 1 IDT} {1729983600 7200 0 IST} {1743120000 10800 1 IDT} {1761433200 7200 0 IST} {1774569600 10800 1 IDT} {1792882800 7200 0 IST} {1806019200 10800 1 IDT} {1824937200 7200 0 IST} {1837468800 10800 1 IDT} {1856386800 7200 0 IST} {1868918400 10800 1 IDT} {1887836400 7200 0 IST} {1900972800 10800 1 IDT} {1919286000 7200 0 IST} {1932422400 10800 1 IDT} {1950735600 7200 0 IST} {1963872000 10800 1 IDT} {1982790000 7200 0 IST} {1995321600 10800 1 IDT} {2014239600 7200 0 IST} {2026771200 10800 1 IDT} {2045689200 7200 0 IST} {2058220800 10800 1 IDT} {2077138800 7200 0 IST} {2090275200 10800 1 IDT} {2108588400 7200 0 IST} {2121724800 10800 1 IDT} {2140038000 7200 0 IST} {2153174400 10800 1 IDT} {2172092400 7200 0 IST} {2184624000 10800 1 IDT} {2203542000 7200 0 IST} {2216073600 10800 1 IDT} {2234991600 7200 0 IST} {2248128000 10800 1 IDT} {2266441200 7200 0 IST} {2279577600 10800 1 IDT} {2297890800 7200 0 IST} {2311027200 10800 1 IDT} {2329340400 7200 0 IST} {2342476800 10800 1 IDT} {2361394800 7200 0 IST} {2373926400 10800 1 IDT} {2392844400 7200 0 IST} {2405376000 10800 1 IDT} {2424294000 7200 0 IST} {2437430400 10800 1 IDT} {2455743600 7200 0 IST} {2468880000 10800 1 IDT} {2487193200 7200 0 IST} {2500329600 10800 1 IDT} {2519247600 7200 0 IST} {2531779200 10800 1 IDT} {2550697200 7200 0 IST} {2563228800 10800 1 IDT} {2582146800 7200 0 IST} {2595283200 10800 1 IDT} {2613596400 7200 0 IST} {2626732800 10800 1 IDT} {2645046000 7200 0 IST} {2658182400 10800 1 IDT} {2676495600 7200 0 IST} {2689632000 10800 1 IDT} {2708550000 7200 0 IST} {2721081600 10800 1 IDT} {2739999600 7200 0 IST} {2752531200 10800 1 IDT} {2771449200 7200 0 IST} {2784585600 10800 1 IDT} {2802898800 7200 0 IST} {2816035200 10800 1 IDT} {2834348400 7200 0 IST} {2847484800 10800 1 IDT} {2866402800 7200 0 IST} {2878934400 10800 1 IDT} {2897852400 7200 0 IST} {2910384000 10800 1 IDT} {2929302000 7200 0 IST} {2941833600 10800 1 IDT} {2960751600 7200 0 IST} {2973888000 10800 1 IDT} {2992201200 7200 0 IST} {3005337600 10800 1 IDT} {3023650800 7200 0 IST} {3036787200 10800 1 IDT} {3055705200 7200 0 IST} {3068236800 10800 1 IDT} {3087154800 7200 0 IST} {3099686400 10800 1 IDT} {3118604400 7200 0 IST} {3131740800 10800 1 IDT} {3150054000 7200 0 IST} {3163190400 10800 1 IDT} {3181503600 7200 0 IST} {3194640000 10800 1 IDT} {3212953200 7200 0 IST} {3226089600 10800 1 IDT} {3245007600 7200 0 IST} {3257539200 10800 1 IDT} {3276457200 7200 0 IST} {3288988800 10800 1 IDT} {3307906800 7200 0 IST} {3321043200 10800 1 IDT} {3339356400 7200 0 IST} {3352492800 10800 1 IDT} {3370806000 7200 0 IST} {3383942400 10800 1 IDT} {3402860400 7200 0 IST} {3415392000 10800 1 IDT} {3434310000 7200 0 IST} {3446841600 10800 1 IDT} {3465759600 7200 0 IST} {3478896000 10800 1 IDT} {3497209200 7200 0 IST} {3510345600 10800 1 IDT} {3528658800 7200 0 IST} {3541795200 10800 1 IDT} {3560108400 7200 0 IST} {3573244800 10800 1 IDT} {3592162800 7200 0 IST} {3604694400 10800 1 IDT} {3623612400 7200 0 IST} {3636144000 10800 1 IDT} {3655062000 7200 0 IST} {3668198400 10800 1 IDT} {3686511600 7200 0 IST} {3699648000 10800 1 IDT} {3717961200 7200 0 IST} {3731097600 10800 1 IDT} {3750015600 7200 0 IST} {3762547200 10800 1 IDT} {3781465200 7200 0 IST} {3793996800 10800 1 IDT} {3812914800 7200 0 IST} {3825446400 10800 1 IDT} {3844364400 7200 0 IST} {3857500800 10800 1 IDT} {3875814000 7200 0 IST} {3888950400 10800 1 IDT} {3907263600 7200 0 IST} {3920400000 10800 1 IDT} {3939318000 7200 0 IST} {3951849600 10800 1 IDT} {3970767600 7200 0 IST} {3983299200 10800 1 IDT} {4002217200 7200 0 IST} {4015353600 10800 1 IDT} {4033666800 7200 0 IST} {4046803200 10800 1 IDT} {4065116400 7200 0 IST} {4078252800 10800 1 IDT} {4096566000 7200 0 IST} } tcl8.6.5/library/tzdata/Asia/Novokuznetsk0000644000175000017500000000412212663660066020042 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Novokuznetsk) { {-9223372036854775808 20928 0 LMT} {-1441259328 21600 0 KRAT} {-1247551200 25200 0 KRAMMTT} {354906000 28800 1 KRAST} {370713600 25200 0 KRAT} {386442000 28800 1 KRAST} {402249600 25200 0 KRAT} {417978000 28800 1 KRAST} {433785600 25200 0 KRAT} {449600400 28800 1 KRAST} {465332400 25200 0 KRAT} {481057200 28800 1 KRAST} {496782000 25200 0 KRAT} {512506800 28800 1 KRAST} {528231600 25200 0 KRAT} {543956400 28800 1 KRAST} {559681200 25200 0 KRAT} {575406000 28800 1 KRAST} {591130800 25200 0 KRAT} {606855600 28800 1 KRAST} {622580400 25200 0 KRAT} {638305200 28800 1 KRAST} {654634800 25200 0 KRAT} {670359600 21600 0 KRAMMTT} {670363200 25200 1 KRAST} {686088000 21600 0 KRAT} {695764800 25200 0 KRAMMTT} {701798400 28800 1 KRAST} {717519600 25200 0 KRAT} {733258800 28800 1 KRAST} {748983600 25200 0 KRAT} {764708400 28800 1 KRAST} {780433200 25200 0 KRAT} {796158000 28800 1 KRAST} {811882800 25200 0 KRAT} {828212400 28800 1 KRAST} {846356400 25200 0 KRAT} {859662000 28800 1 KRAST} {877806000 25200 0 KRAT} {891111600 28800 1 KRAST} {909255600 25200 0 KRAT} {922561200 28800 1 KRAST} {941310000 25200 0 KRAT} {954010800 28800 1 KRAST} {972759600 25200 0 KRAT} {985460400 28800 1 KRAST} {1004209200 25200 0 KRAT} {1017514800 28800 1 KRAST} {1035658800 25200 0 KRAT} {1048964400 28800 1 KRAST} {1067108400 25200 0 KRAT} {1080414000 28800 1 KRAST} {1099162800 25200 0 KRAT} {1111863600 28800 1 KRAST} {1130612400 25200 0 KRAT} {1143313200 28800 1 KRAST} {1162062000 25200 0 KRAT} {1174762800 28800 1 KRAST} {1193511600 25200 0 KRAT} {1206817200 28800 1 KRAST} {1224961200 25200 0 KRAT} {1238266800 28800 1 KRAST} {1256410800 25200 0 KRAT} {1269716400 21600 0 NOVMMTT} {1269720000 25200 1 NOVST} {1288468800 21600 0 NOVT} {1301169600 25200 0 NOVT} {1414263600 25200 0 KRAT} } tcl8.6.5/library/tzdata/Asia/Thimphu0000644000175000017500000000025312661614721016734 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Thimphu) { {-9223372036854775808 21516 0 LMT} {-706341516 19800 0 IST} {560025000 21600 0 BTT} } tcl8.6.5/library/tzdata/Asia/Aden0000644000175000017500000000024612663660066016174 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Riyadh)]} { LoadTimeZoneFile Asia/Riyadh } set TZData(:Asia/Aden) $TZData(:Asia/Riyadh) tcl8.6.5/library/tzdata/Asia/Vientiane0000644000175000017500000000025612663660066017250 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Bangkok)]} { LoadTimeZoneFile Asia/Bangkok } set TZData(:Asia/Vientiane) $TZData(:Asia/Bangkok) tcl8.6.5/library/tzdata/Asia/Bahrain0000644000175000017500000000024612663660066016671 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Qatar)]} { LoadTimeZoneFile Asia/Qatar } set TZData(:Asia/Bahrain) $TZData(:Asia/Qatar) tcl8.6.5/library/tzdata/Asia/Vladivostok0000644000175000017500000000406012663660066017630 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Vladivostok) { {-9223372036854775808 31651 0 LMT} {-1487321251 32400 0 VLAT} {-1247562000 36000 0 VLAMMTT} {354895200 39600 1 VLAST} {370702800 36000 0 VLAT} {386431200 39600 1 VLAST} {402238800 36000 0 VLAT} {417967200 39600 1 VLAST} {433774800 36000 0 VLAT} {449589600 39600 1 VLAST} {465321600 36000 0 VLAT} {481046400 39600 1 VLAST} {496771200 36000 0 VLAT} {512496000 39600 1 VLAST} {528220800 36000 0 VLAT} {543945600 39600 1 VLAST} {559670400 36000 0 VLAT} {575395200 39600 1 VLAST} {591120000 36000 0 VLAT} {606844800 39600 1 VLAST} {622569600 36000 0 VLAT} {638294400 39600 1 VLAST} {654624000 36000 0 VLAT} {670348800 32400 0 VLAMMTT} {670352400 36000 1 VLAST} {686077200 32400 0 VLAT} {695754000 36000 0 VLAMMTT} {701787600 39600 1 VLAST} {717508800 36000 0 VLAT} {733248000 39600 1 VLAST} {748972800 36000 0 VLAT} {764697600 39600 1 VLAST} {780422400 36000 0 VLAT} {796147200 39600 1 VLAST} {811872000 36000 0 VLAT} {828201600 39600 1 VLAST} {846345600 36000 0 VLAT} {859651200 39600 1 VLAST} {877795200 36000 0 VLAT} {891100800 39600 1 VLAST} {909244800 36000 0 VLAT} {922550400 39600 1 VLAST} {941299200 36000 0 VLAT} {954000000 39600 1 VLAST} {972748800 36000 0 VLAT} {985449600 39600 1 VLAST} {1004198400 36000 0 VLAT} {1017504000 39600 1 VLAST} {1035648000 36000 0 VLAT} {1048953600 39600 1 VLAST} {1067097600 36000 0 VLAT} {1080403200 39600 1 VLAST} {1099152000 36000 0 VLAT} {1111852800 39600 1 VLAST} {1130601600 36000 0 VLAT} {1143302400 39600 1 VLAST} {1162051200 36000 0 VLAT} {1174752000 39600 1 VLAST} {1193500800 36000 0 VLAT} {1206806400 39600 1 VLAST} {1224950400 36000 0 VLAT} {1238256000 39600 1 VLAST} {1256400000 36000 0 VLAT} {1269705600 39600 1 VLAST} {1288454400 36000 0 VLAT} {1301155200 39600 0 VLAT} {1414249200 36000 0 VLAT} } tcl8.6.5/library/tzdata/Asia/Bangkok0000644000175000017500000000025612661614721016675 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Asia/Bangkok) { {-9223372036854775808 24124 0 LMT} {-2840164924 24124 0 BMT} {-1570084924 25200 0 ICT} } tcl8.6.5/library/tzdata/GB-Eire0000644000175000017500000000025212661614722015613 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/London)]} { LoadTimeZoneFile Europe/London } set TZData(:GB-Eire) $TZData(:Europe/London) tcl8.6.5/library/tzdata/Greenwich0000644000175000017500000000023212661614722016352 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/GMT)]} { LoadTimeZoneFile Etc/GMT } set TZData(:Greenwich) $TZData(:Etc/GMT) tcl8.6.5/library/tzdata/MST7MDT0000644000175000017500000002004312661614721015537 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:MST7MDT) { {-9223372036854775808 -25200 0 MST} {-1633273200 -21600 1 MDT} {-1615132800 -25200 0 MST} {-1601823600 -21600 1 MDT} {-1583683200 -25200 0 MST} {-880210800 -21600 1 MWT} {-769395600 -21600 1 MPT} {-765388800 -25200 0 MST} {-84380400 -21600 1 MDT} {-68659200 -25200 0 MST} {-52930800 -21600 1 MDT} {-37209600 -25200 0 MST} {-21481200 -21600 1 MDT} {-5760000 -25200 0 MST} {9968400 -21600 1 MDT} {25689600 -25200 0 MST} {41418000 -21600 1 MDT} {57744000 -25200 0 MST} {73472400 -21600 1 MDT} {89193600 -25200 0 MST} {104922000 -21600 1 MDT} {120643200 -25200 0 MST} {126694800 -21600 1 MDT} {152092800 -25200 0 MST} {162378000 -21600 1 MDT} {183542400 -25200 0 MST} {199270800 -21600 1 MDT} {215596800 -25200 0 MST} {230720400 -21600 1 MDT} {247046400 -25200 0 MST} {262774800 -21600 1 MDT} {278496000 -25200 0 MST} {294224400 -21600 1 MDT} {309945600 -25200 0 MST} {325674000 -21600 1 MDT} {341395200 -25200 0 MST} {357123600 -21600 1 MDT} {372844800 -25200 0 MST} {388573200 -21600 1 MDT} {404899200 -25200 0 MST} {420022800 -21600 1 MDT} {436348800 -25200 0 MST} {452077200 -21600 1 MDT} {467798400 -25200 0 MST} {483526800 -21600 1 MDT} {499248000 -25200 0 MST} {514976400 -21600 1 MDT} {530697600 -25200 0 MST} {544611600 -21600 1 MDT} {562147200 -25200 0 MST} {576061200 -21600 1 MDT} {594201600 -25200 0 MST} {607510800 -21600 1 MDT} {625651200 -25200 0 MST} {638960400 -21600 1 MDT} {657100800 -25200 0 MST} {671014800 -21600 1 MDT} {688550400 -25200 0 MST} {702464400 -21600 1 MDT} {720000000 -25200 0 MST} {733914000 -21600 1 MDT} {752054400 -25200 0 MST} {765363600 -21600 1 MDT} {783504000 -25200 0 MST} {796813200 -21600 1 MDT} {814953600 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {986115600 -21600 1 MDT} {1004256000 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1173603600 -21600 1 MDT} {1194163200 -25200 0 MST} {1205053200 -21600 1 MDT} {1225612800 -25200 0 MST} {1236502800 -21600 1 MDT} {1257062400 -25200 0 MST} {1268557200 -21600 1 MDT} {1289116800 -25200 0 MST} {1300006800 -21600 1 MDT} {1320566400 -25200 0 MST} {1331456400 -21600 1 MDT} {1352016000 -25200 0 MST} {1362906000 -21600 1 MDT} {1383465600 -25200 0 MST} {1394355600 -21600 1 MDT} {1414915200 -25200 0 MST} {1425805200 -21600 1 MDT} {1446364800 -25200 0 MST} {1457859600 -21600 1 MDT} {1478419200 -25200 0 MST} {1489309200 -21600 1 MDT} {1509868800 -25200 0 MST} {1520758800 -21600 1 MDT} {1541318400 -25200 0 MST} {1552208400 -21600 1 MDT} {1572768000 -25200 0 MST} {1583658000 -21600 1 MDT} {1604217600 -25200 0 MST} {1615712400 -21600 1 MDT} {1636272000 -25200 0 MST} {1647162000 -21600 1 MDT} {1667721600 -25200 0 MST} {1678611600 -21600 1 MDT} {1699171200 -25200 0 MST} {1710061200 -21600 1 MDT} {1730620800 -25200 0 MST} {1741510800 -21600 1 MDT} {1762070400 -25200 0 MST} {1772960400 -21600 1 MDT} {1793520000 -25200 0 MST} {1805014800 -21600 1 MDT} {1825574400 -25200 0 MST} {1836464400 -21600 1 MDT} {1857024000 -25200 0 MST} {1867914000 -21600 1 MDT} {1888473600 -25200 0 MST} {1899363600 -21600 1 MDT} {1919923200 -25200 0 MST} {1930813200 -21600 1 MDT} {1951372800 -25200 0 MST} {1962867600 -21600 1 MDT} {1983427200 -25200 0 MST} {1994317200 -21600 1 MDT} {2014876800 -25200 0 MST} {2025766800 -21600 1 MDT} {2046326400 -25200 0 MST} {2057216400 -21600 1 MDT} {2077776000 -25200 0 MST} {2088666000 -21600 1 MDT} {2109225600 -25200 0 MST} {2120115600 -21600 1 MDT} {2140675200 -25200 0 MST} {2152170000 -21600 1 MDT} {2172729600 -25200 0 MST} {2183619600 -21600 1 MDT} {2204179200 -25200 0 MST} {2215069200 -21600 1 MDT} {2235628800 -25200 0 MST} {2246518800 -21600 1 MDT} {2267078400 -25200 0 MST} {2277968400 -21600 1 MDT} {2298528000 -25200 0 MST} {2309418000 -21600 1 MDT} {2329977600 -25200 0 MST} {2341472400 -21600 1 MDT} {2362032000 -25200 0 MST} {2372922000 -21600 1 MDT} {2393481600 -25200 0 MST} {2404371600 -21600 1 MDT} {2424931200 -25200 0 MST} {2435821200 -21600 1 MDT} {2456380800 -25200 0 MST} {2467270800 -21600 1 MDT} {2487830400 -25200 0 MST} {2499325200 -21600 1 MDT} {2519884800 -25200 0 MST} {2530774800 -21600 1 MDT} {2551334400 -25200 0 MST} {2562224400 -21600 1 MDT} {2582784000 -25200 0 MST} {2593674000 -21600 1 MDT} {2614233600 -25200 0 MST} {2625123600 -21600 1 MDT} {2645683200 -25200 0 MST} {2656573200 -21600 1 MDT} {2677132800 -25200 0 MST} {2688627600 -21600 1 MDT} {2709187200 -25200 0 MST} {2720077200 -21600 1 MDT} {2740636800 -25200 0 MST} {2751526800 -21600 1 MDT} {2772086400 -25200 0 MST} {2782976400 -21600 1 MDT} {2803536000 -25200 0 MST} {2814426000 -21600 1 MDT} {2834985600 -25200 0 MST} {2846480400 -21600 1 MDT} {2867040000 -25200 0 MST} {2877930000 -21600 1 MDT} {2898489600 -25200 0 MST} {2909379600 -21600 1 MDT} {2929939200 -25200 0 MST} {2940829200 -21600 1 MDT} {2961388800 -25200 0 MST} {2972278800 -21600 1 MDT} {2992838400 -25200 0 MST} {3003728400 -21600 1 MDT} {3024288000 -25200 0 MST} {3035782800 -21600 1 MDT} {3056342400 -25200 0 MST} {3067232400 -21600 1 MDT} {3087792000 -25200 0 MST} {3098682000 -21600 1 MDT} {3119241600 -25200 0 MST} {3130131600 -21600 1 MDT} {3150691200 -25200 0 MST} {3161581200 -21600 1 MDT} {3182140800 -25200 0 MST} {3193030800 -21600 1 MDT} {3213590400 -25200 0 MST} {3225085200 -21600 1 MDT} {3245644800 -25200 0 MST} {3256534800 -21600 1 MDT} {3277094400 -25200 0 MST} {3287984400 -21600 1 MDT} {3308544000 -25200 0 MST} {3319434000 -21600 1 MDT} {3339993600 -25200 0 MST} {3350883600 -21600 1 MDT} {3371443200 -25200 0 MST} {3382938000 -21600 1 MDT} {3403497600 -25200 0 MST} {3414387600 -21600 1 MDT} {3434947200 -25200 0 MST} {3445837200 -21600 1 MDT} {3466396800 -25200 0 MST} {3477286800 -21600 1 MDT} {3497846400 -25200 0 MST} {3508736400 -21600 1 MDT} {3529296000 -25200 0 MST} {3540186000 -21600 1 MDT} {3560745600 -25200 0 MST} {3572240400 -21600 1 MDT} {3592800000 -25200 0 MST} {3603690000 -21600 1 MDT} {3624249600 -25200 0 MST} {3635139600 -21600 1 MDT} {3655699200 -25200 0 MST} {3666589200 -21600 1 MDT} {3687148800 -25200 0 MST} {3698038800 -21600 1 MDT} {3718598400 -25200 0 MST} {3730093200 -21600 1 MDT} {3750652800 -25200 0 MST} {3761542800 -21600 1 MDT} {3782102400 -25200 0 MST} {3792992400 -21600 1 MDT} {3813552000 -25200 0 MST} {3824442000 -21600 1 MDT} {3845001600 -25200 0 MST} {3855891600 -21600 1 MDT} {3876451200 -25200 0 MST} {3887341200 -21600 1 MDT} {3907900800 -25200 0 MST} {3919395600 -21600 1 MDT} {3939955200 -25200 0 MST} {3950845200 -21600 1 MDT} {3971404800 -25200 0 MST} {3982294800 -21600 1 MDT} {4002854400 -25200 0 MST} {4013744400 -21600 1 MDT} {4034304000 -25200 0 MST} {4045194000 -21600 1 MDT} {4065753600 -25200 0 MST} {4076643600 -21600 1 MDT} {4097203200 -25200 0 MST} } tcl8.6.5/library/tzdata/Antarctica/0000755000175000017500000000000012665173607016576 5ustar sergeisergeitcl8.6.5/library/tzdata/Antarctica/Troll0000644000175000017500000001222512663660066017615 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Antarctica/Troll) { {-9223372036854775808 0 0 zzz} {1108166400 0 0 UTC} {1111885200 7200 1 CEST} {1130634000 0 0 UTC} {1143334800 7200 1 CEST} {1162083600 0 0 UTC} {1174784400 7200 1 CEST} {1193533200 0 0 UTC} {1206838800 7200 1 CEST} {1224982800 0 0 UTC} {1238288400 7200 1 CEST} {1256432400 0 0 UTC} {1269738000 7200 1 CEST} {1288486800 0 0 UTC} {1301187600 7200 1 CEST} {1319936400 0 0 UTC} {1332637200 7200 1 CEST} {1351386000 0 0 UTC} {1364691600 7200 1 CEST} {1382835600 0 0 UTC} {1396141200 7200 1 CEST} {1414285200 0 0 UTC} {1427590800 7200 1 CEST} {1445734800 0 0 UTC} {1459040400 7200 1 CEST} {1477789200 0 0 UTC} {1490490000 7200 1 CEST} {1509238800 0 0 UTC} {1521939600 7200 1 CEST} {1540688400 0 0 UTC} {1553994000 7200 1 CEST} {1572138000 0 0 UTC} {1585443600 7200 1 CEST} {1603587600 0 0 UTC} {1616893200 7200 1 CEST} {1635642000 0 0 UTC} {1648342800 7200 1 CEST} {1667091600 0 0 UTC} {1679792400 7200 1 CEST} {1698541200 0 0 UTC} {1711846800 7200 1 CEST} {1729990800 0 0 UTC} {1743296400 7200 1 CEST} {1761440400 0 0 UTC} {1774746000 7200 1 CEST} {1792890000 0 0 UTC} {1806195600 7200 1 CEST} {1824944400 0 0 UTC} {1837645200 7200 1 CEST} {1856394000 0 0 UTC} {1869094800 7200 1 CEST} {1887843600 0 0 UTC} {1901149200 7200 1 CEST} {1919293200 0 0 UTC} {1932598800 7200 1 CEST} {1950742800 0 0 UTC} {1964048400 7200 1 CEST} {1982797200 0 0 UTC} {1995498000 7200 1 CEST} {2014246800 0 0 UTC} {2026947600 7200 1 CEST} {2045696400 0 0 UTC} {2058397200 7200 1 CEST} {2077146000 0 0 UTC} {2090451600 7200 1 CEST} {2108595600 0 0 UTC} {2121901200 7200 1 CEST} {2140045200 0 0 UTC} {2153350800 7200 1 CEST} {2172099600 0 0 UTC} {2184800400 7200 1 CEST} {2203549200 0 0 UTC} {2216250000 7200 1 CEST} {2234998800 0 0 UTC} {2248304400 7200 1 CEST} {2266448400 0 0 UTC} {2279754000 7200 1 CEST} {2297898000 0 0 UTC} {2311203600 7200 1 CEST} {2329347600 0 0 UTC} {2342653200 7200 1 CEST} {2361402000 0 0 UTC} {2374102800 7200 1 CEST} {2392851600 0 0 UTC} {2405552400 7200 1 CEST} {2424301200 0 0 UTC} {2437606800 7200 1 CEST} {2455750800 0 0 UTC} {2469056400 7200 1 CEST} {2487200400 0 0 UTC} {2500506000 7200 1 CEST} {2519254800 0 0 UTC} {2531955600 7200 1 CEST} {2550704400 0 0 UTC} {2563405200 7200 1 CEST} {2582154000 0 0 UTC} {2595459600 7200 1 CEST} {2613603600 0 0 UTC} {2626909200 7200 1 CEST} {2645053200 0 0 UTC} {2658358800 7200 1 CEST} {2676502800 0 0 UTC} {2689808400 7200 1 CEST} {2708557200 0 0 UTC} {2721258000 7200 1 CEST} {2740006800 0 0 UTC} {2752707600 7200 1 CEST} {2771456400 0 0 UTC} {2784762000 7200 1 CEST} {2802906000 0 0 UTC} {2816211600 7200 1 CEST} {2834355600 0 0 UTC} {2847661200 7200 1 CEST} {2866410000 0 0 UTC} {2879110800 7200 1 CEST} {2897859600 0 0 UTC} {2910560400 7200 1 CEST} {2929309200 0 0 UTC} {2942010000 7200 1 CEST} {2960758800 0 0 UTC} {2974064400 7200 1 CEST} {2992208400 0 0 UTC} {3005514000 7200 1 CEST} {3023658000 0 0 UTC} {3036963600 7200 1 CEST} {3055712400 0 0 UTC} {3068413200 7200 1 CEST} {3087162000 0 0 UTC} {3099862800 7200 1 CEST} {3118611600 0 0 UTC} {3131917200 7200 1 CEST} {3150061200 0 0 UTC} {3163366800 7200 1 CEST} {3181510800 0 0 UTC} {3194816400 7200 1 CEST} {3212960400 0 0 UTC} {3226266000 7200 1 CEST} {3245014800 0 0 UTC} {3257715600 7200 1 CEST} {3276464400 0 0 UTC} {3289165200 7200 1 CEST} {3307914000 0 0 UTC} {3321219600 7200 1 CEST} {3339363600 0 0 UTC} {3352669200 7200 1 CEST} {3370813200 0 0 UTC} {3384118800 7200 1 CEST} {3402867600 0 0 UTC} {3415568400 7200 1 CEST} {3434317200 0 0 UTC} {3447018000 7200 1 CEST} {3465766800 0 0 UTC} {3479072400 7200 1 CEST} {3497216400 0 0 UTC} {3510522000 7200 1 CEST} {3528666000 0 0 UTC} {3541971600 7200 1 CEST} {3560115600 0 0 UTC} {3573421200 7200 1 CEST} {3592170000 0 0 UTC} {3604870800 7200 1 CEST} {3623619600 0 0 UTC} {3636320400 7200 1 CEST} {3655069200 0 0 UTC} {3668374800 7200 1 CEST} {3686518800 0 0 UTC} {3699824400 7200 1 CEST} {3717968400 0 0 UTC} {3731274000 7200 1 CEST} {3750022800 0 0 UTC} {3762723600 7200 1 CEST} {3781472400 0 0 UTC} {3794173200 7200 1 CEST} {3812922000 0 0 UTC} {3825622800 7200 1 CEST} {3844371600 0 0 UTC} {3857677200 7200 1 CEST} {3875821200 0 0 UTC} {3889126800 7200 1 CEST} {3907270800 0 0 UTC} {3920576400 7200 1 CEST} {3939325200 0 0 UTC} {3952026000 7200 1 CEST} {3970774800 0 0 UTC} {3983475600 7200 1 CEST} {4002224400 0 0 UTC} {4015530000 7200 1 CEST} {4033674000 0 0 UTC} {4046979600 7200 1 CEST} {4065123600 0 0 UTC} {4078429200 7200 1 CEST} {4096573200 0 0 UTC} } tcl8.6.5/library/tzdata/Antarctica/Syowa0000644000175000017500000000022012661614721017606 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Antarctica/Syowa) { {-9223372036854775808 0 0 zzz} {-407808000 10800 0 SYOT} } tcl8.6.5/library/tzdata/Antarctica/McMurdo0000644000175000017500000000027612663660066020072 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Auckland)]} { LoadTimeZoneFile Pacific/Auckland } set TZData(:Antarctica/McMurdo) $TZData(:Pacific/Auckland) tcl8.6.5/library/tzdata/Antarctica/DumontDUrville0000644000175000017500000000031712661614721021430 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Antarctica/DumontDUrville) { {-9223372036854775808 0 0 zzz} {-725846400 36000 0 PMT} {-566992800 0 0 zzz} {-415497600 36000 0 DDUT} } tcl8.6.5/library/tzdata/Antarctica/Vostok0000644000175000017500000000022112661614721017772 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Antarctica/Vostok) { {-9223372036854775808 0 0 zzz} {-380073600 21600 0 VOST} } tcl8.6.5/library/tzdata/Antarctica/Mawson0000644000175000017500000000025712663653207017766 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Antarctica/Mawson) { {-9223372036854775808 0 0 zzz} {-501206400 21600 0 MAWT} {1255809600 18000 0 MAWT} } tcl8.6.5/library/tzdata/Antarctica/Palmer0000644000175000017500000000471012663660066017741 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Antarctica/Palmer) { {-9223372036854775808 0 0 zzz} {-157766400 -14400 0 ART} {-152654400 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {389070000 -14400 0 CLT} {403070400 -10800 1 CLST} {416372400 -14400 0 CLT} {434520000 -10800 1 CLST} {447822000 -14400 0 CLT} {466574400 -10800 1 CLST} {479271600 -14400 0 CLT} {498024000 -10800 1 CLST} {510721200 -14400 0 CLT} {529473600 -10800 1 CLST} {545194800 -14400 0 CLT} {560923200 -10800 1 CLST} {574225200 -14400 0 CLT} {592372800 -10800 1 CLST} {605674800 -14400 0 CLT} {624427200 -10800 1 CLST} {637124400 -14400 0 CLT} {653457600 -10800 1 CLST} {668574000 -14400 0 CLT} {687326400 -10800 1 CLST} {700628400 -14400 0 CLT} {718776000 -10800 1 CLST} {732078000 -14400 0 CLT} {750225600 -10800 1 CLST} {763527600 -14400 0 CLT} {781675200 -10800 1 CLST} {794977200 -14400 0 CLT} {813729600 -10800 1 CLST} {826426800 -14400 0 CLT} {845179200 -10800 1 CLST} {859690800 -14400 0 CLT} {876628800 -10800 1 CLST} {889930800 -14400 0 CLT} {906868800 -10800 1 CLST} {923194800 -14400 0 CLT} {939528000 -10800 1 CLST} {952830000 -14400 0 CLT} {971582400 -10800 1 CLST} {984279600 -14400 0 CLT} {1003032000 -10800 1 CLST} {1015729200 -14400 0 CLT} {1034481600 -10800 1 CLST} {1047178800 -14400 0 CLT} {1065931200 -10800 1 CLST} {1079233200 -14400 0 CLT} {1097380800 -10800 1 CLST} {1110682800 -14400 0 CLT} {1128830400 -10800 1 CLST} {1142132400 -14400 0 CLT} {1160884800 -10800 1 CLST} {1173582000 -14400 0 CLT} {1192334400 -10800 1 CLST} {1206846000 -14400 0 CLT} {1223784000 -10800 1 CLST} {1237086000 -14400 0 CLT} {1255233600 -10800 1 CLST} {1270350000 -14400 0 CLT} {1286683200 -10800 1 CLST} {1304823600 -14400 0 CLT} {1313899200 -10800 1 CLST} {1335668400 -14400 0 CLT} {1346558400 -10800 1 CLST} {1367118000 -14400 0 CLT} {1378612800 -10800 1 CLST} {1398567600 -14400 0 CLT} {1410062400 -10800 1 CLST} {1430017200 -10800 0 CLT} } tcl8.6.5/library/tzdata/Antarctica/Casey0000644000175000017500000000040712663660066017564 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Antarctica/Casey) { {-9223372036854775808 0 0 zzz} {-31536000 28800 0 AWST} {1255802400 39600 0 CAST} {1267714800 28800 0 AWST} {1319738400 39600 0 CAST} {1329843600 28800 0 AWST} } tcl8.6.5/library/tzdata/Antarctica/Macquarie0000644000175000017500000000536112663660066020433 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Antarctica/Macquarie) { {-9223372036854775808 0 0 zzz} {-2214259200 36000 0 AEST} {-1680508800 39600 1 AEDT} {-1669892400 39600 0 AEDT} {-1665392400 36000 0 AEST} {-1601719200 0 0 zzz} {-94730400 36000 0 AEST} {-71136000 39600 1 AEDT} {-55411200 36000 0 AEST} {-37267200 39600 1 AEDT} {-25776000 36000 0 AEST} {-5817600 39600 1 AEDT} {5673600 36000 0 AEST} {25632000 39600 1 AEDT} {37728000 36000 0 AEST} {57686400 39600 1 AEDT} {67968000 36000 0 AEST} {89136000 39600 1 AEDT} {100022400 36000 0 AEST} {120585600 39600 1 AEDT} {131472000 36000 0 AEST} {152035200 39600 1 AEDT} {162921600 36000 0 AEST} {183484800 39600 1 AEDT} {194976000 36000 0 AEST} {215539200 39600 1 AEDT} {226425600 36000 0 AEST} {246988800 39600 1 AEDT} {257875200 36000 0 AEST} {278438400 39600 1 AEDT} {289324800 36000 0 AEST} {309888000 39600 1 AEDT} {320774400 36000 0 AEST} {341337600 39600 1 AEDT} {352224000 36000 0 AEST} {372787200 39600 1 AEDT} {386092800 36000 0 AEST} {404841600 39600 1 AEDT} {417542400 36000 0 AEST} {436291200 39600 1 AEDT} {447177600 36000 0 AEST} {467740800 39600 1 AEDT} {478627200 36000 0 AEST} {499190400 39600 1 AEDT} {510076800 36000 0 AEST} {530035200 39600 1 AEDT} {542736000 36000 0 AEST} {562089600 39600 1 AEDT} {574790400 36000 0 AEST} {594144000 39600 1 AEDT} {606240000 36000 0 AEST} {625593600 39600 1 AEDT} {637689600 36000 0 AEST} {657043200 39600 1 AEDT} {670348800 36000 0 AEST} {686678400 39600 1 AEDT} {701798400 36000 0 AEST} {718128000 39600 1 AEDT} {733248000 36000 0 AEST} {749577600 39600 1 AEDT} {764697600 36000 0 AEST} {781027200 39600 1 AEDT} {796147200 36000 0 AEST} {812476800 39600 1 AEDT} {828201600 36000 0 AEST} {844531200 39600 1 AEDT} {859651200 36000 0 AEST} {875980800 39600 1 AEDT} {891100800 36000 0 AEST} {907430400 39600 1 AEDT} {922550400 36000 0 AEST} {938880000 39600 1 AEDT} {954000000 36000 0 AEST} {967305600 39600 1 AEDT} {985449600 36000 0 AEST} {1002384000 39600 1 AEDT} {1017504000 36000 0 AEST} {1033833600 39600 1 AEDT} {1048953600 36000 0 AEST} {1065283200 39600 1 AEDT} {1080403200 36000 0 AEST} {1096732800 39600 1 AEDT} {1111852800 36000 0 AEST} {1128182400 39600 1 AEDT} {1143907200 36000 0 AEST} {1159632000 39600 1 AEDT} {1174752000 36000 0 AEST} {1191686400 39600 1 AEDT} {1207411200 36000 0 AEST} {1223136000 39600 1 AEDT} {1238860800 36000 0 AEST} {1254585600 39600 1 AEDT} {1270310400 39600 0 MIST} } tcl8.6.5/library/tzdata/Antarctica/Davis0000644000175000017500000000047612663660066017574 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Antarctica/Davis) { {-9223372036854775808 0 0 zzz} {-409190400 25200 0 DAVT} {-163062000 0 0 zzz} {-28857600 25200 0 DAVT} {1255806000 18000 0 DAVT} {1268251200 25200 0 DAVT} {1319742000 18000 0 DAVT} {1329854400 25200 0 DAVT} } tcl8.6.5/library/tzdata/Antarctica/Rothera0000644000175000017500000000022212661614721020112 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Antarctica/Rothera) { {-9223372036854775808 0 0 zzz} {218246400 -10800 0 ROTT} } tcl8.6.5/library/tzdata/Antarctica/South_Pole0000644000175000017500000000030112663660066020572 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Auckland)]} { LoadTimeZoneFile Pacific/Auckland } set TZData(:Antarctica/South_Pole) $TZData(:Pacific/Auckland) tcl8.6.5/library/tzdata/Arctic/0000755000175000017500000000000012665173607015732 5ustar sergeisergeitcl8.6.5/library/tzdata/Arctic/Longyearbyen0000644000175000017500000000026012661614722020303 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Oslo)]} { LoadTimeZoneFile Europe/Oslo } set TZData(:Arctic/Longyearbyen) $TZData(:Europe/Oslo) tcl8.6.5/library/tzdata/UCT0000644000175000017500000000022412661614722015073 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/UCT)]} { LoadTimeZoneFile Etc/UCT } set TZData(:UCT) $TZData(:Etc/UCT) tcl8.6.5/library/tzdata/Egypt0000644000175000017500000000024512661614722015533 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Cairo)]} { LoadTimeZoneFile Africa/Cairo } set TZData(:Egypt) $TZData(:Africa/Cairo) tcl8.6.5/library/tzdata/Atlantic/0000755000175000017500000000000012665173607016264 5ustar sergeisergeitcl8.6.5/library/tzdata/Atlantic/Azores0000644000175000017500000002355412663660066017461 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Atlantic/Azores) { {-9223372036854775808 -6160 0 LMT} {-2713904240 -6872 0 HMT} {-1830377128 -7200 0 AZOT} {-1689548400 -3600 1 AZOST} {-1677794400 -7200 0 AZOT} {-1667430000 -3600 1 AZOST} {-1647730800 -7200 0 AZOT} {-1635807600 -3600 1 AZOST} {-1616194800 -7200 0 AZOT} {-1604358000 -3600 1 AZOST} {-1584658800 -7200 0 AZOT} {-1572735600 -3600 1 AZOST} {-1553036400 -7200 0 AZOT} {-1541199600 -3600 1 AZOST} {-1521500400 -7200 0 AZOT} {-1442444400 -3600 1 AZOST} {-1426806000 -7200 0 AZOT} {-1379286000 -3600 1 AZOST} {-1364770800 -7200 0 AZOT} {-1348441200 -3600 1 AZOST} {-1333321200 -7200 0 AZOT} {-1316386800 -3600 1 AZOST} {-1301266800 -7200 0 AZOT} {-1284332400 -3600 1 AZOST} {-1269817200 -7200 0 AZOT} {-1221433200 -3600 1 AZOST} {-1206918000 -7200 0 AZOT} {-1191193200 -3600 1 AZOST} {-1175468400 -7200 0 AZOT} {-1127689200 -3600 1 AZOST} {-1111964400 -7200 0 AZOT} {-1096844400 -3600 1 AZOST} {-1080514800 -7200 0 AZOT} {-1063580400 -3600 1 AZOST} {-1049065200 -7200 0 AZOT} {-1033340400 -3600 1 AZOST} {-1017615600 -7200 0 AZOT} {-1002495600 -3600 1 AZOST} {-986166000 -7200 0 AZOT} {-969231600 -3600 1 AZOST} {-950482800 -7200 0 AZOT} {-942015600 -3600 1 AZOST} {-922662000 -7200 0 AZOT} {-906937200 -3600 1 AZOST} {-891126000 -7200 0 AZOT} {-877302000 -3600 1 AZOST} {-873676800 0 1 AZOMT} {-864000000 -3600 1 AZOST} {-857948400 -7200 0 AZOT} {-845852400 -3600 1 AZOST} {-842832000 0 1 AZOMT} {-831340800 -3600 1 AZOST} {-825894000 -7200 0 AZOT} {-814402800 -3600 1 AZOST} {-810777600 0 1 AZOMT} {-799891200 -3600 1 AZOST} {-794444400 -7200 0 AZOT} {-782953200 -3600 1 AZOST} {-779328000 0 1 AZOMT} {-768441600 -3600 1 AZOST} {-762994800 -7200 0 AZOT} {-749084400 -3600 1 AZOST} {-733359600 -7200 0 AZOT} {-717624000 -3600 1 AZOST} {-701899200 -7200 0 AZOT} {-686174400 -3600 1 AZOST} {-670449600 -7200 0 AZOT} {-654724800 -3600 1 AZOST} {-639000000 -7200 0 AZOT} {-591825600 -3600 1 AZOST} {-575496000 -7200 0 AZOT} {-559771200 -3600 1 AZOST} {-544046400 -7200 0 AZOT} {-528321600 -3600 1 AZOST} {-512596800 -7200 0 AZOT} {-496872000 -3600 1 AZOST} {-481147200 -7200 0 AZOT} {-465422400 -3600 1 AZOST} {-449697600 -7200 0 AZOT} {-433972800 -3600 1 AZOST} {-417643200 -7200 0 AZOT} {-401918400 -3600 1 AZOST} {-386193600 -7200 0 AZOT} {-370468800 -3600 1 AZOST} {-354744000 -7200 0 AZOT} {-339019200 -3600 1 AZOST} {-323294400 -7200 0 AZOT} {-307569600 -3600 1 AZOST} {-291844800 -7200 0 AZOT} {-276120000 -3600 1 AZOST} {-260395200 -7200 0 AZOT} {-244670400 -3600 1 AZOST} {-228340800 -7200 0 AZOT} {-212616000 -3600 1 AZOST} {-196891200 -7200 0 AZOT} {-181166400 -3600 1 AZOST} {-165441600 -7200 0 AZOT} {-149716800 -3600 1 AZOST} {-133992000 -7200 0 AZOT} {-118267200 -3600 0 AZOT} {228272400 0 1 AZOST} {243997200 -3600 0 AZOT} {260326800 0 1 AZOST} {276051600 -3600 0 AZOT} {291776400 0 1 AZOST} {307504800 -3600 0 AZOT} {323226000 0 1 AZOST} {338954400 -3600 0 AZOT} {354679200 0 1 AZOST} {370404000 -3600 0 AZOT} {386128800 0 1 AZOST} {401853600 -3600 0 AZOT} {417582000 0 1 AZOST} {433303200 -3600 0 AZOT} {449028000 0 1 AZOST} {465357600 -3600 0 AZOT} {481082400 0 1 AZOST} {496807200 -3600 0 AZOT} {512532000 0 1 AZOST} {528256800 -3600 0 AZOT} {543981600 0 1 AZOST} {559706400 -3600 0 AZOT} {575431200 0 1 AZOST} {591156000 -3600 0 AZOT} {606880800 0 1 AZOST} {622605600 -3600 0 AZOT} {638330400 0 1 AZOST} {654660000 -3600 0 AZOT} {670384800 0 1 AZOST} {686109600 -3600 0 AZOT} {701834400 0 1 AZOST} {733280400 0 0 AZOST} {749005200 -3600 0 AZOT} {764730000 0 1 AZOST} {780454800 -3600 0 AZOT} {796179600 0 1 AZOST} {811904400 -3600 0 AZOT} {828234000 0 1 AZOST} {846378000 -3600 0 AZOT} {859683600 0 1 AZOST} {877827600 -3600 0 AZOT} {891133200 0 1 AZOST} {909277200 -3600 0 AZOT} {922582800 0 1 AZOST} {941331600 -3600 0 AZOT} {954032400 0 1 AZOST} {972781200 -3600 0 AZOT} {985482000 0 1 AZOST} {1004230800 -3600 0 AZOT} {1017536400 0 1 AZOST} {1035680400 -3600 0 AZOT} {1048986000 0 1 AZOST} {1067130000 -3600 0 AZOT} {1080435600 0 1 AZOST} {1099184400 -3600 0 AZOT} {1111885200 0 1 AZOST} {1130634000 -3600 0 AZOT} {1143334800 0 1 AZOST} {1162083600 -3600 0 AZOT} {1174784400 0 1 AZOST} {1193533200 -3600 0 AZOT} {1206838800 0 1 AZOST} {1224982800 -3600 0 AZOT} {1238288400 0 1 AZOST} {1256432400 -3600 0 AZOT} {1269738000 0 1 AZOST} {1288486800 -3600 0 AZOT} {1301187600 0 1 AZOST} {1319936400 -3600 0 AZOT} {1332637200 0 1 AZOST} {1351386000 -3600 0 AZOT} {1364691600 0 1 AZOST} {1382835600 -3600 0 AZOT} {1396141200 0 1 AZOST} {1414285200 -3600 0 AZOT} {1427590800 0 1 AZOST} {1445734800 -3600 0 AZOT} {1459040400 0 1 AZOST} {1477789200 -3600 0 AZOT} {1490490000 0 1 AZOST} {1509238800 -3600 0 AZOT} {1521939600 0 1 AZOST} {1540688400 -3600 0 AZOT} {1553994000 0 1 AZOST} {1572138000 -3600 0 AZOT} {1585443600 0 1 AZOST} {1603587600 -3600 0 AZOT} {1616893200 0 1 AZOST} {1635642000 -3600 0 AZOT} {1648342800 0 1 AZOST} {1667091600 -3600 0 AZOT} {1679792400 0 1 AZOST} {1698541200 -3600 0 AZOT} {1711846800 0 1 AZOST} {1729990800 -3600 0 AZOT} {1743296400 0 1 AZOST} {1761440400 -3600 0 AZOT} {1774746000 0 1 AZOST} {1792890000 -3600 0 AZOT} {1806195600 0 1 AZOST} {1824944400 -3600 0 AZOT} {1837645200 0 1 AZOST} {1856394000 -3600 0 AZOT} {1869094800 0 1 AZOST} {1887843600 -3600 0 AZOT} {1901149200 0 1 AZOST} {1919293200 -3600 0 AZOT} {1932598800 0 1 AZOST} {1950742800 -3600 0 AZOT} {1964048400 0 1 AZOST} {1982797200 -3600 0 AZOT} {1995498000 0 1 AZOST} {2014246800 -3600 0 AZOT} {2026947600 0 1 AZOST} {2045696400 -3600 0 AZOT} {2058397200 0 1 AZOST} {2077146000 -3600 0 AZOT} {2090451600 0 1 AZOST} {2108595600 -3600 0 AZOT} {2121901200 0 1 AZOST} {2140045200 -3600 0 AZOT} {2153350800 0 1 AZOST} {2172099600 -3600 0 AZOT} {2184800400 0 1 AZOST} {2203549200 -3600 0 AZOT} {2216250000 0 1 AZOST} {2234998800 -3600 0 AZOT} {2248304400 0 1 AZOST} {2266448400 -3600 0 AZOT} {2279754000 0 1 AZOST} {2297898000 -3600 0 AZOT} {2311203600 0 1 AZOST} {2329347600 -3600 0 AZOT} {2342653200 0 1 AZOST} {2361402000 -3600 0 AZOT} {2374102800 0 1 AZOST} {2392851600 -3600 0 AZOT} {2405552400 0 1 AZOST} {2424301200 -3600 0 AZOT} {2437606800 0 1 AZOST} {2455750800 -3600 0 AZOT} {2469056400 0 1 AZOST} {2487200400 -3600 0 AZOT} {2500506000 0 1 AZOST} {2519254800 -3600 0 AZOT} {2531955600 0 1 AZOST} {2550704400 -3600 0 AZOT} {2563405200 0 1 AZOST} {2582154000 -3600 0 AZOT} {2595459600 0 1 AZOST} {2613603600 -3600 0 AZOT} {2626909200 0 1 AZOST} {2645053200 -3600 0 AZOT} {2658358800 0 1 AZOST} {2676502800 -3600 0 AZOT} {2689808400 0 1 AZOST} {2708557200 -3600 0 AZOT} {2721258000 0 1 AZOST} {2740006800 -3600 0 AZOT} {2752707600 0 1 AZOST} {2771456400 -3600 0 AZOT} {2784762000 0 1 AZOST} {2802906000 -3600 0 AZOT} {2816211600 0 1 AZOST} {2834355600 -3600 0 AZOT} {2847661200 0 1 AZOST} {2866410000 -3600 0 AZOT} {2879110800 0 1 AZOST} {2897859600 -3600 0 AZOT} {2910560400 0 1 AZOST} {2929309200 -3600 0 AZOT} {2942010000 0 1 AZOST} {2960758800 -3600 0 AZOT} {2974064400 0 1 AZOST} {2992208400 -3600 0 AZOT} {3005514000 0 1 AZOST} {3023658000 -3600 0 AZOT} {3036963600 0 1 AZOST} {3055712400 -3600 0 AZOT} {3068413200 0 1 AZOST} {3087162000 -3600 0 AZOT} {3099862800 0 1 AZOST} {3118611600 -3600 0 AZOT} {3131917200 0 1 AZOST} {3150061200 -3600 0 AZOT} {3163366800 0 1 AZOST} {3181510800 -3600 0 AZOT} {3194816400 0 1 AZOST} {3212960400 -3600 0 AZOT} {3226266000 0 1 AZOST} {3245014800 -3600 0 AZOT} {3257715600 0 1 AZOST} {3276464400 -3600 0 AZOT} {3289165200 0 1 AZOST} {3307914000 -3600 0 AZOT} {3321219600 0 1 AZOST} {3339363600 -3600 0 AZOT} {3352669200 0 1 AZOST} {3370813200 -3600 0 AZOT} {3384118800 0 1 AZOST} {3402867600 -3600 0 AZOT} {3415568400 0 1 AZOST} {3434317200 -3600 0 AZOT} {3447018000 0 1 AZOST} {3465766800 -3600 0 AZOT} {3479072400 0 1 AZOST} {3497216400 -3600 0 AZOT} {3510522000 0 1 AZOST} {3528666000 -3600 0 AZOT} {3541971600 0 1 AZOST} {3560115600 -3600 0 AZOT} {3573421200 0 1 AZOST} {3592170000 -3600 0 AZOT} {3604870800 0 1 AZOST} {3623619600 -3600 0 AZOT} {3636320400 0 1 AZOST} {3655069200 -3600 0 AZOT} {3668374800 0 1 AZOST} {3686518800 -3600 0 AZOT} {3699824400 0 1 AZOST} {3717968400 -3600 0 AZOT} {3731274000 0 1 AZOST} {3750022800 -3600 0 AZOT} {3762723600 0 1 AZOST} {3781472400 -3600 0 AZOT} {3794173200 0 1 AZOST} {3812922000 -3600 0 AZOT} {3825622800 0 1 AZOST} {3844371600 -3600 0 AZOT} {3857677200 0 1 AZOST} {3875821200 -3600 0 AZOT} {3889126800 0 1 AZOST} {3907270800 -3600 0 AZOT} {3920576400 0 1 AZOST} {3939325200 -3600 0 AZOT} {3952026000 0 1 AZOST} {3970774800 -3600 0 AZOT} {3983475600 0 1 AZOST} {4002224400 -3600 0 AZOT} {4015530000 0 1 AZOST} {4033674000 -3600 0 AZOT} {4046979600 0 1 AZOST} {4065123600 -3600 0 AZOT} {4078429200 0 1 AZOST} {4096573200 -3600 0 AZOT} } tcl8.6.5/library/tzdata/Atlantic/Madeira0000644000175000017500000002254012663660066017552 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Atlantic/Madeira) { {-9223372036854775808 -4056 0 LMT} {-2713906344 -4056 0 FMT} {-1830379944 -3600 0 MADT} {-1689552000 0 1 MADST} {-1677798000 -3600 0 MADT} {-1667433600 0 1 MADST} {-1647734400 -3600 0 MADT} {-1635811200 0 1 MADST} {-1616198400 -3600 0 MADT} {-1604361600 0 1 MADST} {-1584662400 -3600 0 MADT} {-1572739200 0 1 MADST} {-1553040000 -3600 0 MADT} {-1541203200 0 1 MADST} {-1521504000 -3600 0 MADT} {-1442448000 0 1 MADST} {-1426809600 -3600 0 MADT} {-1379289600 0 1 MADST} {-1364774400 -3600 0 MADT} {-1348444800 0 1 MADST} {-1333324800 -3600 0 MADT} {-1316390400 0 1 MADST} {-1301270400 -3600 0 MADT} {-1284336000 0 1 MADST} {-1269820800 -3600 0 MADT} {-1221436800 0 1 MADST} {-1206921600 -3600 0 MADT} {-1191196800 0 1 MADST} {-1175472000 -3600 0 MADT} {-1127692800 0 1 MADST} {-1111968000 -3600 0 MADT} {-1096848000 0 1 MADST} {-1080518400 -3600 0 MADT} {-1063584000 0 1 MADST} {-1049068800 -3600 0 MADT} {-1033344000 0 1 MADST} {-1017619200 -3600 0 MADT} {-1002499200 0 1 MADST} {-986169600 -3600 0 MADT} {-969235200 0 1 MADST} {-950486400 -3600 0 MADT} {-942019200 0 1 MADST} {-922665600 -3600 0 MADT} {-906940800 0 1 MADST} {-891129600 -3600 0 MADT} {-877305600 0 1 MADST} {-873680400 3600 1 MADMT} {-864003600 0 1 MADST} {-857952000 -3600 0 MADT} {-845856000 0 1 MADST} {-842835600 3600 1 MADMT} {-831344400 0 1 MADST} {-825897600 -3600 0 MADT} {-814406400 0 1 MADST} {-810781200 3600 1 MADMT} {-799894800 0 1 MADST} {-794448000 -3600 0 MADT} {-782956800 0 1 MADST} {-779331600 3600 1 MADMT} {-768445200 0 1 MADST} {-762998400 -3600 0 MADT} {-749088000 0 1 MADST} {-733363200 -3600 0 MADT} {-717627600 0 1 MADST} {-701902800 -3600 0 MADT} {-686178000 0 1 MADST} {-670453200 -3600 0 MADT} {-654728400 0 1 MADST} {-639003600 -3600 0 MADT} {-591829200 0 1 MADST} {-575499600 -3600 0 MADT} {-559774800 0 1 MADST} {-544050000 -3600 0 MADT} {-528325200 0 1 MADST} {-512600400 -3600 0 MADT} {-496875600 0 1 MADST} {-481150800 -3600 0 MADT} {-465426000 0 1 MADST} {-449701200 -3600 0 MADT} {-433976400 0 1 MADST} {-417646800 -3600 0 MADT} {-401922000 0 1 MADST} {-386197200 -3600 0 MADT} {-370472400 0 1 MADST} {-354747600 -3600 0 MADT} {-339022800 0 1 MADST} {-323298000 -3600 0 MADT} {-307573200 0 1 MADST} {-291848400 -3600 0 MADT} {-276123600 0 1 MADST} {-260398800 -3600 0 MADT} {-244674000 0 1 MADST} {-228344400 -3600 0 MADT} {-212619600 0 1 MADST} {-196894800 -3600 0 MADT} {-181170000 0 1 MADST} {-165445200 -3600 0 MADT} {-149720400 0 1 MADST} {-133995600 -3600 0 MADT} {-118270800 0 0 WET} {228268800 3600 1 WEST} {243993600 0 0 WET} {260323200 3600 1 WEST} {276048000 0 0 WET} {291772800 3600 1 WEST} {307501200 0 0 WET} {323222400 3600 1 WEST} {338950800 0 0 WET} {354675600 3600 1 WEST} {370400400 0 0 WET} {386125200 3600 1 WEST} {401850000 0 0 WET} {417578400 3600 1 WEST} {433299600 0 0 WET} {449024400 3600 1 WEST} {465354000 0 0 WET} {481078800 3600 1 WEST} {496803600 0 0 WET} {512528400 3600 1 WEST} {528253200 0 0 WET} {543978000 3600 1 WEST} {559702800 0 0 WET} {575427600 3600 1 WEST} {591152400 0 0 WET} {606877200 3600 1 WEST} {622602000 0 0 WET} {638326800 3600 1 WEST} {654656400 0 0 WET} {670381200 3600 1 WEST} {686106000 0 0 WET} {701830800 3600 1 WEST} {717555600 0 0 WET} {733280400 3600 1 WEST} {749005200 0 0 WET} {764730000 3600 1 WEST} {780454800 0 0 WET} {796179600 3600 1 WEST} {811904400 0 0 WET} {828234000 3600 1 WEST} {846378000 0 0 WET} {859683600 3600 1 WEST} {877827600 0 0 WET} {891133200 3600 1 WEST} {909277200 0 0 WET} {922582800 3600 1 WEST} {941331600 0 0 WET} {954032400 3600 1 WEST} {972781200 0 0 WET} {985482000 3600 1 WEST} {1004230800 0 0 WET} {1017536400 3600 1 WEST} {1035680400 0 0 WET} {1048986000 3600 1 WEST} {1067130000 0 0 WET} {1080435600 3600 1 WEST} {1099184400 0 0 WET} {1111885200 3600 1 WEST} {1130634000 0 0 WET} {1143334800 3600 1 WEST} {1162083600 0 0 WET} {1174784400 3600 1 WEST} {1193533200 0 0 WET} {1206838800 3600 1 WEST} {1224982800 0 0 WET} {1238288400 3600 1 WEST} {1256432400 0 0 WET} {1269738000 3600 1 WEST} {1288486800 0 0 WET} {1301187600 3600 1 WEST} {1319936400 0 0 WET} {1332637200 3600 1 WEST} {1351386000 0 0 WET} {1364691600 3600 1 WEST} {1382835600 0 0 WET} {1396141200 3600 1 WEST} {1414285200 0 0 WET} {1427590800 3600 1 WEST} {1445734800 0 0 WET} {1459040400 3600 1 WEST} {1477789200 0 0 WET} {1490490000 3600 1 WEST} {1509238800 0 0 WET} {1521939600 3600 1 WEST} {1540688400 0 0 WET} {1553994000 3600 1 WEST} {1572138000 0 0 WET} {1585443600 3600 1 WEST} {1603587600 0 0 WET} {1616893200 3600 1 WEST} {1635642000 0 0 WET} {1648342800 3600 1 WEST} {1667091600 0 0 WET} {1679792400 3600 1 WEST} {1698541200 0 0 WET} {1711846800 3600 1 WEST} {1729990800 0 0 WET} {1743296400 3600 1 WEST} {1761440400 0 0 WET} {1774746000 3600 1 WEST} {1792890000 0 0 WET} {1806195600 3600 1 WEST} {1824944400 0 0 WET} {1837645200 3600 1 WEST} {1856394000 0 0 WET} {1869094800 3600 1 WEST} {1887843600 0 0 WET} {1901149200 3600 1 WEST} {1919293200 0 0 WET} {1932598800 3600 1 WEST} {1950742800 0 0 WET} {1964048400 3600 1 WEST} {1982797200 0 0 WET} {1995498000 3600 1 WEST} {2014246800 0 0 WET} {2026947600 3600 1 WEST} {2045696400 0 0 WET} {2058397200 3600 1 WEST} {2077146000 0 0 WET} {2090451600 3600 1 WEST} {2108595600 0 0 WET} {2121901200 3600 1 WEST} {2140045200 0 0 WET} {2153350800 3600 1 WEST} {2172099600 0 0 WET} {2184800400 3600 1 WEST} {2203549200 0 0 WET} {2216250000 3600 1 WEST} {2234998800 0 0 WET} {2248304400 3600 1 WEST} {2266448400 0 0 WET} {2279754000 3600 1 WEST} {2297898000 0 0 WET} {2311203600 3600 1 WEST} {2329347600 0 0 WET} {2342653200 3600 1 WEST} {2361402000 0 0 WET} {2374102800 3600 1 WEST} {2392851600 0 0 WET} {2405552400 3600 1 WEST} {2424301200 0 0 WET} {2437606800 3600 1 WEST} {2455750800 0 0 WET} {2469056400 3600 1 WEST} {2487200400 0 0 WET} {2500506000 3600 1 WEST} {2519254800 0 0 WET} {2531955600 3600 1 WEST} {2550704400 0 0 WET} {2563405200 3600 1 WEST} {2582154000 0 0 WET} {2595459600 3600 1 WEST} {2613603600 0 0 WET} {2626909200 3600 1 WEST} {2645053200 0 0 WET} {2658358800 3600 1 WEST} {2676502800 0 0 WET} {2689808400 3600 1 WEST} {2708557200 0 0 WET} {2721258000 3600 1 WEST} {2740006800 0 0 WET} {2752707600 3600 1 WEST} {2771456400 0 0 WET} {2784762000 3600 1 WEST} {2802906000 0 0 WET} {2816211600 3600 1 WEST} {2834355600 0 0 WET} {2847661200 3600 1 WEST} {2866410000 0 0 WET} {2879110800 3600 1 WEST} {2897859600 0 0 WET} {2910560400 3600 1 WEST} {2929309200 0 0 WET} {2942010000 3600 1 WEST} {2960758800 0 0 WET} {2974064400 3600 1 WEST} {2992208400 0 0 WET} {3005514000 3600 1 WEST} {3023658000 0 0 WET} {3036963600 3600 1 WEST} {3055712400 0 0 WET} {3068413200 3600 1 WEST} {3087162000 0 0 WET} {3099862800 3600 1 WEST} {3118611600 0 0 WET} {3131917200 3600 1 WEST} {3150061200 0 0 WET} {3163366800 3600 1 WEST} {3181510800 0 0 WET} {3194816400 3600 1 WEST} {3212960400 0 0 WET} {3226266000 3600 1 WEST} {3245014800 0 0 WET} {3257715600 3600 1 WEST} {3276464400 0 0 WET} {3289165200 3600 1 WEST} {3307914000 0 0 WET} {3321219600 3600 1 WEST} {3339363600 0 0 WET} {3352669200 3600 1 WEST} {3370813200 0 0 WET} {3384118800 3600 1 WEST} {3402867600 0 0 WET} {3415568400 3600 1 WEST} {3434317200 0 0 WET} {3447018000 3600 1 WEST} {3465766800 0 0 WET} {3479072400 3600 1 WEST} {3497216400 0 0 WET} {3510522000 3600 1 WEST} {3528666000 0 0 WET} {3541971600 3600 1 WEST} {3560115600 0 0 WET} {3573421200 3600 1 WEST} {3592170000 0 0 WET} {3604870800 3600 1 WEST} {3623619600 0 0 WET} {3636320400 3600 1 WEST} {3655069200 0 0 WET} {3668374800 3600 1 WEST} {3686518800 0 0 WET} {3699824400 3600 1 WEST} {3717968400 0 0 WET} {3731274000 3600 1 WEST} {3750022800 0 0 WET} {3762723600 3600 1 WEST} {3781472400 0 0 WET} {3794173200 3600 1 WEST} {3812922000 0 0 WET} {3825622800 3600 1 WEST} {3844371600 0 0 WET} {3857677200 3600 1 WEST} {3875821200 0 0 WET} {3889126800 3600 1 WEST} {3907270800 0 0 WET} {3920576400 3600 1 WEST} {3939325200 0 0 WET} {3952026000 3600 1 WEST} {3970774800 0 0 WET} {3983475600 3600 1 WEST} {4002224400 0 0 WET} {4015530000 3600 1 WEST} {4033674000 0 0 WET} {4046979600 3600 1 WEST} {4065123600 0 0 WET} {4078429200 3600 1 WEST} {4096573200 0 0 WET} } tcl8.6.5/library/tzdata/Atlantic/Jan_Mayen0000644000175000017500000000025712661614722020046 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Oslo)]} { LoadTimeZoneFile Europe/Oslo } set TZData(:Atlantic/Jan_Mayen) $TZData(:Europe/Oslo) tcl8.6.5/library/tzdata/Atlantic/St_Helena0000644000175000017500000000027012663660066020046 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Abidjan)]} { LoadTimeZoneFile Africa/Abidjan } set TZData(:Atlantic/St_Helena) $TZData(:Africa/Abidjan) tcl8.6.5/library/tzdata/Atlantic/South_Georgia0000644000175000017500000000023212661614721020734 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Atlantic/South_Georgia) { {-9223372036854775808 -8768 0 LMT} {-2524512832 -7200 0 GST} } tcl8.6.5/library/tzdata/Atlantic/Canary0000644000175000017500000001472212663660066017430 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Atlantic/Canary) { {-9223372036854775808 -3696 0 LMT} {-1509663504 -3600 0 CANT} {-733874400 0 0 WET} {323827200 3600 1 WEST} {338950800 0 0 WET} {354675600 3600 1 WEST} {370400400 0 0 WET} {386125200 3600 1 WEST} {401850000 0 0 WET} {417574800 3600 1 WEST} {433299600 0 0 WET} {449024400 3600 1 WEST} {465354000 0 0 WET} {481078800 3600 1 WEST} {496803600 0 0 WET} {512528400 3600 1 WEST} {528253200 0 0 WET} {543978000 3600 1 WEST} {559702800 0 0 WET} {575427600 3600 1 WEST} {591152400 0 0 WET} {606877200 3600 1 WEST} {622602000 0 0 WET} {638326800 3600 1 WEST} {654656400 0 0 WET} {670381200 3600 1 WEST} {686106000 0 0 WET} {701830800 3600 1 WEST} {717555600 0 0 WET} {733280400 3600 1 WEST} {749005200 0 0 WET} {764730000 3600 1 WEST} {780454800 0 0 WET} {796179600 3600 1 WEST} {811904400 0 0 WET} {828234000 3600 1 WEST} {846378000 0 0 WET} {859683600 3600 1 WEST} {877827600 0 0 WET} {891133200 3600 1 WEST} {909277200 0 0 WET} {922582800 3600 1 WEST} {941331600 0 0 WET} {954032400 3600 1 WEST} {972781200 0 0 WET} {985482000 3600 1 WEST} {1004230800 0 0 WET} {1017536400 3600 1 WEST} {1035680400 0 0 WET} {1048986000 3600 1 WEST} {1067130000 0 0 WET} {1080435600 3600 1 WEST} {1099184400 0 0 WET} {1111885200 3600 1 WEST} {1130634000 0 0 WET} {1143334800 3600 1 WEST} {1162083600 0 0 WET} {1174784400 3600 1 WEST} {1193533200 0 0 WET} {1206838800 3600 1 WEST} {1224982800 0 0 WET} {1238288400 3600 1 WEST} {1256432400 0 0 WET} {1269738000 3600 1 WEST} {1288486800 0 0 WET} {1301187600 3600 1 WEST} {1319936400 0 0 WET} {1332637200 3600 1 WEST} {1351386000 0 0 WET} {1364691600 3600 1 WEST} {1382835600 0 0 WET} {1396141200 3600 1 WEST} {1414285200 0 0 WET} {1427590800 3600 1 WEST} {1445734800 0 0 WET} {1459040400 3600 1 WEST} {1477789200 0 0 WET} {1490490000 3600 1 WEST} {1509238800 0 0 WET} {1521939600 3600 1 WEST} {1540688400 0 0 WET} {1553994000 3600 1 WEST} {1572138000 0 0 WET} {1585443600 3600 1 WEST} {1603587600 0 0 WET} {1616893200 3600 1 WEST} {1635642000 0 0 WET} {1648342800 3600 1 WEST} {1667091600 0 0 WET} {1679792400 3600 1 WEST} {1698541200 0 0 WET} {1711846800 3600 1 WEST} {1729990800 0 0 WET} {1743296400 3600 1 WEST} {1761440400 0 0 WET} {1774746000 3600 1 WEST} {1792890000 0 0 WET} {1806195600 3600 1 WEST} {1824944400 0 0 WET} {1837645200 3600 1 WEST} {1856394000 0 0 WET} {1869094800 3600 1 WEST} {1887843600 0 0 WET} {1901149200 3600 1 WEST} {1919293200 0 0 WET} {1932598800 3600 1 WEST} {1950742800 0 0 WET} {1964048400 3600 1 WEST} {1982797200 0 0 WET} {1995498000 3600 1 WEST} {2014246800 0 0 WET} {2026947600 3600 1 WEST} {2045696400 0 0 WET} {2058397200 3600 1 WEST} {2077146000 0 0 WET} {2090451600 3600 1 WEST} {2108595600 0 0 WET} {2121901200 3600 1 WEST} {2140045200 0 0 WET} {2153350800 3600 1 WEST} {2172099600 0 0 WET} {2184800400 3600 1 WEST} {2203549200 0 0 WET} {2216250000 3600 1 WEST} {2234998800 0 0 WET} {2248304400 3600 1 WEST} {2266448400 0 0 WET} {2279754000 3600 1 WEST} {2297898000 0 0 WET} {2311203600 3600 1 WEST} {2329347600 0 0 WET} {2342653200 3600 1 WEST} {2361402000 0 0 WET} {2374102800 3600 1 WEST} {2392851600 0 0 WET} {2405552400 3600 1 WEST} {2424301200 0 0 WET} {2437606800 3600 1 WEST} {2455750800 0 0 WET} {2469056400 3600 1 WEST} {2487200400 0 0 WET} {2500506000 3600 1 WEST} {2519254800 0 0 WET} {2531955600 3600 1 WEST} {2550704400 0 0 WET} {2563405200 3600 1 WEST} {2582154000 0 0 WET} {2595459600 3600 1 WEST} {2613603600 0 0 WET} {2626909200 3600 1 WEST} {2645053200 0 0 WET} {2658358800 3600 1 WEST} {2676502800 0 0 WET} {2689808400 3600 1 WEST} {2708557200 0 0 WET} {2721258000 3600 1 WEST} {2740006800 0 0 WET} {2752707600 3600 1 WEST} {2771456400 0 0 WET} {2784762000 3600 1 WEST} {2802906000 0 0 WET} {2816211600 3600 1 WEST} {2834355600 0 0 WET} {2847661200 3600 1 WEST} {2866410000 0 0 WET} {2879110800 3600 1 WEST} {2897859600 0 0 WET} {2910560400 3600 1 WEST} {2929309200 0 0 WET} {2942010000 3600 1 WEST} {2960758800 0 0 WET} {2974064400 3600 1 WEST} {2992208400 0 0 WET} {3005514000 3600 1 WEST} {3023658000 0 0 WET} {3036963600 3600 1 WEST} {3055712400 0 0 WET} {3068413200 3600 1 WEST} {3087162000 0 0 WET} {3099862800 3600 1 WEST} {3118611600 0 0 WET} {3131917200 3600 1 WEST} {3150061200 0 0 WET} {3163366800 3600 1 WEST} {3181510800 0 0 WET} {3194816400 3600 1 WEST} {3212960400 0 0 WET} {3226266000 3600 1 WEST} {3245014800 0 0 WET} {3257715600 3600 1 WEST} {3276464400 0 0 WET} {3289165200 3600 1 WEST} {3307914000 0 0 WET} {3321219600 3600 1 WEST} {3339363600 0 0 WET} {3352669200 3600 1 WEST} {3370813200 0 0 WET} {3384118800 3600 1 WEST} {3402867600 0 0 WET} {3415568400 3600 1 WEST} {3434317200 0 0 WET} {3447018000 3600 1 WEST} {3465766800 0 0 WET} {3479072400 3600 1 WEST} {3497216400 0 0 WET} {3510522000 3600 1 WEST} {3528666000 0 0 WET} {3541971600 3600 1 WEST} {3560115600 0 0 WET} {3573421200 3600 1 WEST} {3592170000 0 0 WET} {3604870800 3600 1 WEST} {3623619600 0 0 WET} {3636320400 3600 1 WEST} {3655069200 0 0 WET} {3668374800 3600 1 WEST} {3686518800 0 0 WET} {3699824400 3600 1 WEST} {3717968400 0 0 WET} {3731274000 3600 1 WEST} {3750022800 0 0 WET} {3762723600 3600 1 WEST} {3781472400 0 0 WET} {3794173200 3600 1 WEST} {3812922000 0 0 WET} {3825622800 3600 1 WEST} {3844371600 0 0 WET} {3857677200 3600 1 WEST} {3875821200 0 0 WET} {3889126800 3600 1 WEST} {3907270800 0 0 WET} {3920576400 3600 1 WEST} {3939325200 0 0 WET} {3952026000 3600 1 WEST} {3970774800 0 0 WET} {3983475600 3600 1 WEST} {4002224400 0 0 WET} {4015530000 3600 1 WEST} {4033674000 0 0 WET} {4046979600 3600 1 WEST} {4065123600 0 0 WET} {4078429200 3600 1 WEST} {4096573200 0 0 WET} } tcl8.6.5/library/tzdata/Atlantic/Reykjavik0000644000175000017500000000371312663660066020150 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Atlantic/Reykjavik) { {-9223372036854775808 -5280 0 LMT} {-1956609120 -3600 0 IST} {-1668211200 0 1 ISST} {-1647212400 -3600 0 IST} {-1636675200 0 1 ISST} {-1613430000 -3600 0 IST} {-1605139200 0 1 ISST} {-1581894000 -3600 0 IST} {-1539561600 0 1 ISST} {-1531350000 -3600 0 IST} {-968025600 0 1 ISST} {-952293600 -3600 0 IST} {-942008400 0 1 ISST} {-920239200 -3600 0 IST} {-909957600 0 1 ISST} {-888789600 -3600 0 IST} {-877903200 0 1 ISST} {-857944800 -3600 0 IST} {-846453600 0 1 ISST} {-826495200 -3600 0 IST} {-815004000 0 1 ISST} {-795045600 -3600 0 IST} {-783554400 0 1 ISST} {-762991200 -3600 0 IST} {-752104800 0 1 ISST} {-731541600 -3600 0 IST} {-717631200 0 1 ISST} {-700092000 -3600 0 IST} {-686181600 0 1 ISST} {-668642400 -3600 0 IST} {-654732000 0 1 ISST} {-636588000 -3600 0 IST} {-623282400 0 1 ISST} {-605743200 -3600 0 IST} {-591832800 0 1 ISST} {-573688800 -3600 0 IST} {-559778400 0 1 ISST} {-542239200 -3600 0 IST} {-528328800 0 1 ISST} {-510789600 -3600 0 IST} {-496879200 0 1 ISST} {-479340000 -3600 0 IST} {-465429600 0 1 ISST} {-447890400 -3600 0 IST} {-433980000 0 1 ISST} {-415836000 -3600 0 IST} {-401925600 0 1 ISST} {-384386400 -3600 0 IST} {-370476000 0 1 ISST} {-352936800 -3600 0 IST} {-339026400 0 1 ISST} {-321487200 -3600 0 IST} {-307576800 0 1 ISST} {-290037600 -3600 0 IST} {-276127200 0 1 ISST} {-258588000 -3600 0 IST} {-244677600 0 1 ISST} {-226533600 -3600 0 IST} {-212623200 0 1 ISST} {-195084000 -3600 0 IST} {-181173600 0 1 ISST} {-163634400 -3600 0 IST} {-149724000 0 1 ISST} {-132184800 -3600 0 IST} {-118274400 0 1 ISST} {-100735200 -3600 0 IST} {-86824800 0 1 ISST} {-68680800 -3600 0 IST} {-54770400 0 0 GMT} } tcl8.6.5/library/tzdata/Atlantic/Faroe0000644000175000017500000001462712661614721017246 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Atlantic/Faroe) { {-9223372036854775808 -1624 0 LMT} {-1955748776 0 0 WET} {347155200 0 0 WET} {354675600 3600 1 WEST} {370400400 0 0 WET} {386125200 3600 1 WEST} {401850000 0 0 WET} {417574800 3600 1 WEST} {433299600 0 0 WET} {449024400 3600 1 WEST} {465354000 0 0 WET} {481078800 3600 1 WEST} {496803600 0 0 WET} {512528400 3600 1 WEST} {528253200 0 0 WET} {543978000 3600 1 WEST} {559702800 0 0 WET} {575427600 3600 1 WEST} {591152400 0 0 WET} {606877200 3600 1 WEST} {622602000 0 0 WET} {638326800 3600 1 WEST} {654656400 0 0 WET} {670381200 3600 1 WEST} {686106000 0 0 WET} {701830800 3600 1 WEST} {717555600 0 0 WET} {733280400 3600 1 WEST} {749005200 0 0 WET} {764730000 3600 1 WEST} {780454800 0 0 WET} {796179600 3600 1 WEST} {811904400 0 0 WET} {828234000 3600 1 WEST} {846378000 0 0 WET} {859683600 3600 1 WEST} {877827600 0 0 WET} {891133200 3600 1 WEST} {909277200 0 0 WET} {922582800 3600 1 WEST} {941331600 0 0 WET} {954032400 3600 1 WEST} {972781200 0 0 WET} {985482000 3600 1 WEST} {1004230800 0 0 WET} {1017536400 3600 1 WEST} {1035680400 0 0 WET} {1048986000 3600 1 WEST} {1067130000 0 0 WET} {1080435600 3600 1 WEST} {1099184400 0 0 WET} {1111885200 3600 1 WEST} {1130634000 0 0 WET} {1143334800 3600 1 WEST} {1162083600 0 0 WET} {1174784400 3600 1 WEST} {1193533200 0 0 WET} {1206838800 3600 1 WEST} {1224982800 0 0 WET} {1238288400 3600 1 WEST} {1256432400 0 0 WET} {1269738000 3600 1 WEST} {1288486800 0 0 WET} {1301187600 3600 1 WEST} {1319936400 0 0 WET} {1332637200 3600 1 WEST} {1351386000 0 0 WET} {1364691600 3600 1 WEST} {1382835600 0 0 WET} {1396141200 3600 1 WEST} {1414285200 0 0 WET} {1427590800 3600 1 WEST} {1445734800 0 0 WET} {1459040400 3600 1 WEST} {1477789200 0 0 WET} {1490490000 3600 1 WEST} {1509238800 0 0 WET} {1521939600 3600 1 WEST} {1540688400 0 0 WET} {1553994000 3600 1 WEST} {1572138000 0 0 WET} {1585443600 3600 1 WEST} {1603587600 0 0 WET} {1616893200 3600 1 WEST} {1635642000 0 0 WET} {1648342800 3600 1 WEST} {1667091600 0 0 WET} {1679792400 3600 1 WEST} {1698541200 0 0 WET} {1711846800 3600 1 WEST} {1729990800 0 0 WET} {1743296400 3600 1 WEST} {1761440400 0 0 WET} {1774746000 3600 1 WEST} {1792890000 0 0 WET} {1806195600 3600 1 WEST} {1824944400 0 0 WET} {1837645200 3600 1 WEST} {1856394000 0 0 WET} {1869094800 3600 1 WEST} {1887843600 0 0 WET} {1901149200 3600 1 WEST} {1919293200 0 0 WET} {1932598800 3600 1 WEST} {1950742800 0 0 WET} {1964048400 3600 1 WEST} {1982797200 0 0 WET} {1995498000 3600 1 WEST} {2014246800 0 0 WET} {2026947600 3600 1 WEST} {2045696400 0 0 WET} {2058397200 3600 1 WEST} {2077146000 0 0 WET} {2090451600 3600 1 WEST} {2108595600 0 0 WET} {2121901200 3600 1 WEST} {2140045200 0 0 WET} {2153350800 3600 1 WEST} {2172099600 0 0 WET} {2184800400 3600 1 WEST} {2203549200 0 0 WET} {2216250000 3600 1 WEST} {2234998800 0 0 WET} {2248304400 3600 1 WEST} {2266448400 0 0 WET} {2279754000 3600 1 WEST} {2297898000 0 0 WET} {2311203600 3600 1 WEST} {2329347600 0 0 WET} {2342653200 3600 1 WEST} {2361402000 0 0 WET} {2374102800 3600 1 WEST} {2392851600 0 0 WET} {2405552400 3600 1 WEST} {2424301200 0 0 WET} {2437606800 3600 1 WEST} {2455750800 0 0 WET} {2469056400 3600 1 WEST} {2487200400 0 0 WET} {2500506000 3600 1 WEST} {2519254800 0 0 WET} {2531955600 3600 1 WEST} {2550704400 0 0 WET} {2563405200 3600 1 WEST} {2582154000 0 0 WET} {2595459600 3600 1 WEST} {2613603600 0 0 WET} {2626909200 3600 1 WEST} {2645053200 0 0 WET} {2658358800 3600 1 WEST} {2676502800 0 0 WET} {2689808400 3600 1 WEST} {2708557200 0 0 WET} {2721258000 3600 1 WEST} {2740006800 0 0 WET} {2752707600 3600 1 WEST} {2771456400 0 0 WET} {2784762000 3600 1 WEST} {2802906000 0 0 WET} {2816211600 3600 1 WEST} {2834355600 0 0 WET} {2847661200 3600 1 WEST} {2866410000 0 0 WET} {2879110800 3600 1 WEST} {2897859600 0 0 WET} {2910560400 3600 1 WEST} {2929309200 0 0 WET} {2942010000 3600 1 WEST} {2960758800 0 0 WET} {2974064400 3600 1 WEST} {2992208400 0 0 WET} {3005514000 3600 1 WEST} {3023658000 0 0 WET} {3036963600 3600 1 WEST} {3055712400 0 0 WET} {3068413200 3600 1 WEST} {3087162000 0 0 WET} {3099862800 3600 1 WEST} {3118611600 0 0 WET} {3131917200 3600 1 WEST} {3150061200 0 0 WET} {3163366800 3600 1 WEST} {3181510800 0 0 WET} {3194816400 3600 1 WEST} {3212960400 0 0 WET} {3226266000 3600 1 WEST} {3245014800 0 0 WET} {3257715600 3600 1 WEST} {3276464400 0 0 WET} {3289165200 3600 1 WEST} {3307914000 0 0 WET} {3321219600 3600 1 WEST} {3339363600 0 0 WET} {3352669200 3600 1 WEST} {3370813200 0 0 WET} {3384118800 3600 1 WEST} {3402867600 0 0 WET} {3415568400 3600 1 WEST} {3434317200 0 0 WET} {3447018000 3600 1 WEST} {3465766800 0 0 WET} {3479072400 3600 1 WEST} {3497216400 0 0 WET} {3510522000 3600 1 WEST} {3528666000 0 0 WET} {3541971600 3600 1 WEST} {3560115600 0 0 WET} {3573421200 3600 1 WEST} {3592170000 0 0 WET} {3604870800 3600 1 WEST} {3623619600 0 0 WET} {3636320400 3600 1 WEST} {3655069200 0 0 WET} {3668374800 3600 1 WEST} {3686518800 0 0 WET} {3699824400 3600 1 WEST} {3717968400 0 0 WET} {3731274000 3600 1 WEST} {3750022800 0 0 WET} {3762723600 3600 1 WEST} {3781472400 0 0 WET} {3794173200 3600 1 WEST} {3812922000 0 0 WET} {3825622800 3600 1 WEST} {3844371600 0 0 WET} {3857677200 3600 1 WEST} {3875821200 0 0 WET} {3889126800 3600 1 WEST} {3907270800 0 0 WET} {3920576400 3600 1 WEST} {3939325200 0 0 WET} {3952026000 3600 1 WEST} {3970774800 0 0 WET} {3983475600 3600 1 WEST} {4002224400 0 0 WET} {4015530000 3600 1 WEST} {4033674000 0 0 WET} {4046979600 3600 1 WEST} {4065123600 0 0 WET} {4078429200 3600 1 WEST} {4096573200 0 0 WET} } tcl8.6.5/library/tzdata/Atlantic/Faeroe0000644000175000017500000000026512661614722017405 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Atlantic/Faroe)]} { LoadTimeZoneFile Atlantic/Faroe } set TZData(:Atlantic/Faeroe) $TZData(:Atlantic/Faroe) tcl8.6.5/library/tzdata/Atlantic/Bermuda0000644000175000017500000001700412663660066017566 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Atlantic/Bermuda) { {-9223372036854775808 -15558 0 LMT} {-1262281242 -14400 0 AST} {136360800 -10800 0 ADT} {152082000 -14400 0 AST} {167810400 -10800 1 ADT} {183531600 -14400 0 AST} {189316800 -14400 0 AST} {199260000 -10800 1 ADT} {215586000 -14400 0 AST} {230709600 -10800 1 ADT} {247035600 -14400 0 AST} {262764000 -10800 1 ADT} {278485200 -14400 0 AST} {294213600 -10800 1 ADT} {309934800 -14400 0 AST} {325663200 -10800 1 ADT} {341384400 -14400 0 AST} {357112800 -10800 1 ADT} {372834000 -14400 0 AST} {388562400 -10800 1 ADT} {404888400 -14400 0 AST} {420012000 -10800 1 ADT} {436338000 -14400 0 AST} {452066400 -10800 1 ADT} {467787600 -14400 0 AST} {483516000 -10800 1 ADT} {499237200 -14400 0 AST} {514965600 -10800 1 ADT} {530686800 -14400 0 AST} {544600800 -10800 1 ADT} {562136400 -14400 0 AST} {576050400 -10800 1 ADT} {594190800 -14400 0 AST} {607500000 -10800 1 ADT} {625640400 -14400 0 AST} {638949600 -10800 1 ADT} {657090000 -14400 0 AST} {671004000 -10800 1 ADT} {688539600 -14400 0 AST} {702453600 -10800 1 ADT} {719989200 -14400 0 AST} {733903200 -10800 1 ADT} {752043600 -14400 0 AST} {765352800 -10800 1 ADT} {783493200 -14400 0 AST} {796802400 -10800 1 ADT} {814942800 -14400 0 AST} {828856800 -10800 1 ADT} {846392400 -14400 0 AST} {860306400 -10800 1 ADT} {877842000 -14400 0 AST} {891756000 -10800 1 ADT} {909291600 -14400 0 AST} {923205600 -10800 1 ADT} {941346000 -14400 0 AST} {954655200 -10800 1 ADT} {972795600 -14400 0 AST} {986104800 -10800 1 ADT} {1004245200 -14400 0 AST} {1018159200 -10800 1 ADT} {1035694800 -14400 0 AST} {1049608800 -10800 1 ADT} {1067144400 -14400 0 AST} {1081058400 -10800 1 ADT} {1099198800 -14400 0 AST} {1112508000 -10800 1 ADT} {1130648400 -14400 0 AST} {1143957600 -10800 1 ADT} {1162098000 -14400 0 AST} {1173592800 -10800 1 ADT} {1194152400 -14400 0 AST} {1205042400 -10800 1 ADT} {1225602000 -14400 0 AST} {1236492000 -10800 1 ADT} {1257051600 -14400 0 AST} {1268546400 -10800 1 ADT} {1289106000 -14400 0 AST} {1299996000 -10800 1 ADT} {1320555600 -14400 0 AST} {1331445600 -10800 1 ADT} {1352005200 -14400 0 AST} {1362895200 -10800 1 ADT} {1383454800 -14400 0 AST} {1394344800 -10800 1 ADT} {1414904400 -14400 0 AST} {1425794400 -10800 1 ADT} {1446354000 -14400 0 AST} {1457848800 -10800 1 ADT} {1478408400 -14400 0 AST} {1489298400 -10800 1 ADT} {1509858000 -14400 0 AST} {1520748000 -10800 1 ADT} {1541307600 -14400 0 AST} {1552197600 -10800 1 ADT} {1572757200 -14400 0 AST} {1583647200 -10800 1 ADT} {1604206800 -14400 0 AST} {1615701600 -10800 1 ADT} {1636261200 -14400 0 AST} {1647151200 -10800 1 ADT} {1667710800 -14400 0 AST} {1678600800 -10800 1 ADT} {1699160400 -14400 0 AST} {1710050400 -10800 1 ADT} {1730610000 -14400 0 AST} {1741500000 -10800 1 ADT} {1762059600 -14400 0 AST} {1772949600 -10800 1 ADT} {1793509200 -14400 0 AST} {1805004000 -10800 1 ADT} {1825563600 -14400 0 AST} {1836453600 -10800 1 ADT} {1857013200 -14400 0 AST} {1867903200 -10800 1 ADT} {1888462800 -14400 0 AST} {1899352800 -10800 1 ADT} {1919912400 -14400 0 AST} {1930802400 -10800 1 ADT} {1951362000 -14400 0 AST} {1962856800 -10800 1 ADT} {1983416400 -14400 0 AST} {1994306400 -10800 1 ADT} {2014866000 -14400 0 AST} {2025756000 -10800 1 ADT} {2046315600 -14400 0 AST} {2057205600 -10800 1 ADT} {2077765200 -14400 0 AST} {2088655200 -10800 1 ADT} {2109214800 -14400 0 AST} {2120104800 -10800 1 ADT} {2140664400 -14400 0 AST} {2152159200 -10800 1 ADT} {2172718800 -14400 0 AST} {2183608800 -10800 1 ADT} {2204168400 -14400 0 AST} {2215058400 -10800 1 ADT} {2235618000 -14400 0 AST} {2246508000 -10800 1 ADT} {2267067600 -14400 0 AST} {2277957600 -10800 1 ADT} {2298517200 -14400 0 AST} {2309407200 -10800 1 ADT} {2329966800 -14400 0 AST} {2341461600 -10800 1 ADT} {2362021200 -14400 0 AST} {2372911200 -10800 1 ADT} {2393470800 -14400 0 AST} {2404360800 -10800 1 ADT} {2424920400 -14400 0 AST} {2435810400 -10800 1 ADT} {2456370000 -14400 0 AST} {2467260000 -10800 1 ADT} {2487819600 -14400 0 AST} {2499314400 -10800 1 ADT} {2519874000 -14400 0 AST} {2530764000 -10800 1 ADT} {2551323600 -14400 0 AST} {2562213600 -10800 1 ADT} {2582773200 -14400 0 AST} {2593663200 -10800 1 ADT} {2614222800 -14400 0 AST} {2625112800 -10800 1 ADT} {2645672400 -14400 0 AST} {2656562400 -10800 1 ADT} {2677122000 -14400 0 AST} {2688616800 -10800 1 ADT} {2709176400 -14400 0 AST} {2720066400 -10800 1 ADT} {2740626000 -14400 0 AST} {2751516000 -10800 1 ADT} {2772075600 -14400 0 AST} {2782965600 -10800 1 ADT} {2803525200 -14400 0 AST} {2814415200 -10800 1 ADT} {2834974800 -14400 0 AST} {2846469600 -10800 1 ADT} {2867029200 -14400 0 AST} {2877919200 -10800 1 ADT} {2898478800 -14400 0 AST} {2909368800 -10800 1 ADT} {2929928400 -14400 0 AST} {2940818400 -10800 1 ADT} {2961378000 -14400 0 AST} {2972268000 -10800 1 ADT} {2992827600 -14400 0 AST} {3003717600 -10800 1 ADT} {3024277200 -14400 0 AST} {3035772000 -10800 1 ADT} {3056331600 -14400 0 AST} {3067221600 -10800 1 ADT} {3087781200 -14400 0 AST} {3098671200 -10800 1 ADT} {3119230800 -14400 0 AST} {3130120800 -10800 1 ADT} {3150680400 -14400 0 AST} {3161570400 -10800 1 ADT} {3182130000 -14400 0 AST} {3193020000 -10800 1 ADT} {3213579600 -14400 0 AST} {3225074400 -10800 1 ADT} {3245634000 -14400 0 AST} {3256524000 -10800 1 ADT} {3277083600 -14400 0 AST} {3287973600 -10800 1 ADT} {3308533200 -14400 0 AST} {3319423200 -10800 1 ADT} {3339982800 -14400 0 AST} {3350872800 -10800 1 ADT} {3371432400 -14400 0 AST} {3382927200 -10800 1 ADT} {3403486800 -14400 0 AST} {3414376800 -10800 1 ADT} {3434936400 -14400 0 AST} {3445826400 -10800 1 ADT} {3466386000 -14400 0 AST} {3477276000 -10800 1 ADT} {3497835600 -14400 0 AST} {3508725600 -10800 1 ADT} {3529285200 -14400 0 AST} {3540175200 -10800 1 ADT} {3560734800 -14400 0 AST} {3572229600 -10800 1 ADT} {3592789200 -14400 0 AST} {3603679200 -10800 1 ADT} {3624238800 -14400 0 AST} {3635128800 -10800 1 ADT} {3655688400 -14400 0 AST} {3666578400 -10800 1 ADT} {3687138000 -14400 0 AST} {3698028000 -10800 1 ADT} {3718587600 -14400 0 AST} {3730082400 -10800 1 ADT} {3750642000 -14400 0 AST} {3761532000 -10800 1 ADT} {3782091600 -14400 0 AST} {3792981600 -10800 1 ADT} {3813541200 -14400 0 AST} {3824431200 -10800 1 ADT} {3844990800 -14400 0 AST} {3855880800 -10800 1 ADT} {3876440400 -14400 0 AST} {3887330400 -10800 1 ADT} {3907890000 -14400 0 AST} {3919384800 -10800 1 ADT} {3939944400 -14400 0 AST} {3950834400 -10800 1 ADT} {3971394000 -14400 0 AST} {3982284000 -10800 1 ADT} {4002843600 -14400 0 AST} {4013733600 -10800 1 ADT} {4034293200 -14400 0 AST} {4045183200 -10800 1 ADT} {4065742800 -14400 0 AST} {4076632800 -10800 1 ADT} {4097192400 -14400 0 AST} } tcl8.6.5/library/tzdata/Atlantic/Cape_Verde0000644000175000017500000000035612661614721020201 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Atlantic/Cape_Verde) { {-9223372036854775808 -5644 0 LMT} {-1988144756 -7200 0 CVT} {-862610400 -3600 1 CVST} {-764118000 -7200 0 CVT} {186120000 -3600 0 CVT} } tcl8.6.5/library/tzdata/Atlantic/Stanley0000644000175000017500000000424712663660066017633 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Atlantic/Stanley) { {-9223372036854775808 -13884 0 LMT} {-2524507716 -13884 0 SMT} {-1824235716 -14400 0 FKT} {-1018209600 -10800 1 FKST} {-1003093200 -14400 0 FKT} {-986760000 -10800 1 FKST} {-971643600 -14400 0 FKT} {-954705600 -10800 1 FKST} {-939589200 -14400 0 FKT} {-923256000 -10800 1 FKST} {-908139600 -14400 0 FKT} {-891806400 -10800 1 FKST} {-876690000 -14400 0 FKT} {-860356800 -10800 1 FKST} {420606000 -7200 0 FKT} {433303200 -7200 1 FKST} {452052000 -10800 0 FKT} {464151600 -7200 1 FKST} {483501600 -10800 0 FKT} {495597600 -14400 0 FKT} {495604800 -10800 1 FKST} {514350000 -14400 0 FKT} {527054400 -10800 1 FKST} {545799600 -14400 0 FKT} {558504000 -10800 1 FKST} {577249200 -14400 0 FKT} {589953600 -10800 1 FKST} {608698800 -14400 0 FKT} {621403200 -10800 1 FKST} {640753200 -14400 0 FKT} {652852800 -10800 1 FKST} {672202800 -14400 0 FKT} {684907200 -10800 1 FKST} {703652400 -14400 0 FKT} {716356800 -10800 1 FKST} {735102000 -14400 0 FKT} {747806400 -10800 1 FKST} {766551600 -14400 0 FKT} {779256000 -10800 1 FKST} {798001200 -14400 0 FKT} {810705600 -10800 1 FKST} {830055600 -14400 0 FKT} {842760000 -10800 1 FKST} {861505200 -14400 0 FKT} {874209600 -10800 1 FKST} {892954800 -14400 0 FKT} {905659200 -10800 1 FKST} {924404400 -14400 0 FKT} {937108800 -10800 1 FKST} {955854000 -14400 0 FKT} {968558400 -10800 1 FKST} {987310800 -14400 0 FKT} {999410400 -10800 1 FKST} {1019365200 -14400 0 FKT} {1030860000 -10800 1 FKST} {1050814800 -14400 0 FKT} {1062914400 -10800 1 FKST} {1082264400 -14400 0 FKT} {1094364000 -10800 1 FKST} {1113714000 -14400 0 FKT} {1125813600 -10800 1 FKST} {1145163600 -14400 0 FKT} {1157263200 -10800 1 FKST} {1176613200 -14400 0 FKT} {1188712800 -10800 1 FKST} {1208667600 -14400 0 FKT} {1220767200 -10800 1 FKST} {1240117200 -14400 0 FKT} {1252216800 -10800 1 FKST} {1271566800 -14400 0 FKT} {1283662800 -10800 0 FKST} } tcl8.6.5/library/tzdata/NZ-CHAT0000644000175000017500000000026012661614722015504 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Chatham)]} { LoadTimeZoneFile Pacific/Chatham } set TZData(:NZ-CHAT) $TZData(:Pacific/Chatham) tcl8.6.5/library/tzdata/EET0000644000175000017500000001602512661614721015062 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:EET) { {-9223372036854775808 7200 0 EET} {228877200 10800 1 EEST} {243997200 7200 0 EET} {260326800 10800 1 EEST} {276051600 7200 0 EET} {291776400 10800 1 EEST} {307501200 7200 0 EET} {323830800 10800 1 EEST} {338950800 7200 0 EET} {354675600 10800 1 EEST} {370400400 7200 0 EET} {386125200 10800 1 EEST} {401850000 7200 0 EET} {417574800 10800 1 EEST} {433299600 7200 0 EET} {449024400 10800 1 EEST} {465354000 7200 0 EET} {481078800 10800 1 EEST} {496803600 7200 0 EET} {512528400 10800 1 EEST} {528253200 7200 0 EET} {543978000 10800 1 EEST} {559702800 7200 0 EET} {575427600 10800 1 EEST} {591152400 7200 0 EET} {606877200 10800 1 EEST} {622602000 7200 0 EET} {638326800 10800 1 EEST} {654656400 7200 0 EET} {670381200 10800 1 EEST} {686106000 7200 0 EET} {701830800 10800 1 EEST} {717555600 7200 0 EET} {733280400 10800 1 EEST} {749005200 7200 0 EET} {764730000 10800 1 EEST} {780454800 7200 0 EET} {796179600 10800 1 EEST} {811904400 7200 0 EET} {828234000 10800 1 EEST} {846378000 7200 0 EET} {859683600 10800 1 EEST} {877827600 7200 0 EET} {891133200 10800 1 EEST} {909277200 7200 0 EET} {922582800 10800 1 EEST} {941331600 7200 0 EET} {954032400 10800 1 EEST} {972781200 7200 0 EET} {985482000 10800 1 EEST} {1004230800 7200 0 EET} {1017536400 10800 1 EEST} {1035680400 7200 0 EET} {1048986000 10800 1 EEST} {1067130000 7200 0 EET} {1080435600 10800 1 EEST} {1099184400 7200 0 EET} {1111885200 10800 1 EEST} {1130634000 7200 0 EET} {1143334800 10800 1 EEST} {1162083600 7200 0 EET} {1174784400 10800 1 EEST} {1193533200 7200 0 EET} {1206838800 10800 1 EEST} {1224982800 7200 0 EET} {1238288400 10800 1 EEST} {1256432400 7200 0 EET} {1269738000 10800 1 EEST} {1288486800 7200 0 EET} {1301187600 10800 1 EEST} {1319936400 7200 0 EET} {1332637200 10800 1 EEST} {1351386000 7200 0 EET} {1364691600 10800 1 EEST} {1382835600 7200 0 EET} {1396141200 10800 1 EEST} {1414285200 7200 0 EET} {1427590800 10800 1 EEST} {1445734800 7200 0 EET} {1459040400 10800 1 EEST} {1477789200 7200 0 EET} {1490490000 10800 1 EEST} {1509238800 7200 0 EET} {1521939600 10800 1 EEST} {1540688400 7200 0 EET} {1553994000 10800 1 EEST} {1572138000 7200 0 EET} {1585443600 10800 1 EEST} {1603587600 7200 0 EET} {1616893200 10800 1 EEST} {1635642000 7200 0 EET} {1648342800 10800 1 EEST} {1667091600 7200 0 EET} {1679792400 10800 1 EEST} {1698541200 7200 0 EET} {1711846800 10800 1 EEST} {1729990800 7200 0 EET} {1743296400 10800 1 EEST} {1761440400 7200 0 EET} {1774746000 10800 1 EEST} {1792890000 7200 0 EET} {1806195600 10800 1 EEST} {1824944400 7200 0 EET} {1837645200 10800 1 EEST} {1856394000 7200 0 EET} {1869094800 10800 1 EEST} {1887843600 7200 0 EET} {1901149200 10800 1 EEST} {1919293200 7200 0 EET} {1932598800 10800 1 EEST} {1950742800 7200 0 EET} {1964048400 10800 1 EEST} {1982797200 7200 0 EET} {1995498000 10800 1 EEST} {2014246800 7200 0 EET} {2026947600 10800 1 EEST} {2045696400 7200 0 EET} {2058397200 10800 1 EEST} {2077146000 7200 0 EET} {2090451600 10800 1 EEST} {2108595600 7200 0 EET} {2121901200 10800 1 EEST} {2140045200 7200 0 EET} {2153350800 10800 1 EEST} {2172099600 7200 0 EET} {2184800400 10800 1 EEST} {2203549200 7200 0 EET} {2216250000 10800 1 EEST} {2234998800 7200 0 EET} {2248304400 10800 1 EEST} {2266448400 7200 0 EET} {2279754000 10800 1 EEST} {2297898000 7200 0 EET} {2311203600 10800 1 EEST} {2329347600 7200 0 EET} {2342653200 10800 1 EEST} {2361402000 7200 0 EET} {2374102800 10800 1 EEST} {2392851600 7200 0 EET} {2405552400 10800 1 EEST} {2424301200 7200 0 EET} {2437606800 10800 1 EEST} {2455750800 7200 0 EET} {2469056400 10800 1 EEST} {2487200400 7200 0 EET} {2500506000 10800 1 EEST} {2519254800 7200 0 EET} {2531955600 10800 1 EEST} {2550704400 7200 0 EET} {2563405200 10800 1 EEST} {2582154000 7200 0 EET} {2595459600 10800 1 EEST} {2613603600 7200 0 EET} {2626909200 10800 1 EEST} {2645053200 7200 0 EET} {2658358800 10800 1 EEST} {2676502800 7200 0 EET} {2689808400 10800 1 EEST} {2708557200 7200 0 EET} {2721258000 10800 1 EEST} {2740006800 7200 0 EET} {2752707600 10800 1 EEST} {2771456400 7200 0 EET} {2784762000 10800 1 EEST} {2802906000 7200 0 EET} {2816211600 10800 1 EEST} {2834355600 7200 0 EET} {2847661200 10800 1 EEST} {2866410000 7200 0 EET} {2879110800 10800 1 EEST} {2897859600 7200 0 EET} {2910560400 10800 1 EEST} {2929309200 7200 0 EET} {2942010000 10800 1 EEST} {2960758800 7200 0 EET} {2974064400 10800 1 EEST} {2992208400 7200 0 EET} {3005514000 10800 1 EEST} {3023658000 7200 0 EET} {3036963600 10800 1 EEST} {3055712400 7200 0 EET} {3068413200 10800 1 EEST} {3087162000 7200 0 EET} {3099862800 10800 1 EEST} {3118611600 7200 0 EET} {3131917200 10800 1 EEST} {3150061200 7200 0 EET} {3163366800 10800 1 EEST} {3181510800 7200 0 EET} {3194816400 10800 1 EEST} {3212960400 7200 0 EET} {3226266000 10800 1 EEST} {3245014800 7200 0 EET} {3257715600 10800 1 EEST} {3276464400 7200 0 EET} {3289165200 10800 1 EEST} {3307914000 7200 0 EET} {3321219600 10800 1 EEST} {3339363600 7200 0 EET} {3352669200 10800 1 EEST} {3370813200 7200 0 EET} {3384118800 10800 1 EEST} {3402867600 7200 0 EET} {3415568400 10800 1 EEST} {3434317200 7200 0 EET} {3447018000 10800 1 EEST} {3465766800 7200 0 EET} {3479072400 10800 1 EEST} {3497216400 7200 0 EET} {3510522000 10800 1 EEST} {3528666000 7200 0 EET} {3541971600 10800 1 EEST} {3560115600 7200 0 EET} {3573421200 10800 1 EEST} {3592170000 7200 0 EET} {3604870800 10800 1 EEST} {3623619600 7200 0 EET} {3636320400 10800 1 EEST} {3655069200 7200 0 EET} {3668374800 10800 1 EEST} {3686518800 7200 0 EET} {3699824400 10800 1 EEST} {3717968400 7200 0 EET} {3731274000 10800 1 EEST} {3750022800 7200 0 EET} {3762723600 10800 1 EEST} {3781472400 7200 0 EET} {3794173200 10800 1 EEST} {3812922000 7200 0 EET} {3825622800 10800 1 EEST} {3844371600 7200 0 EET} {3857677200 10800 1 EEST} {3875821200 7200 0 EET} {3889126800 10800 1 EEST} {3907270800 7200 0 EET} {3920576400 10800 1 EEST} {3939325200 7200 0 EET} {3952026000 10800 1 EEST} {3970774800 7200 0 EET} {3983475600 10800 1 EEST} {4002224400 7200 0 EET} {4015530000 10800 1 EEST} {4033674000 7200 0 EET} {4046979600 10800 1 EEST} {4065123600 7200 0 EET} {4078429200 10800 1 EEST} {4096573200 7200 0 EET} } tcl8.6.5/library/tzdata/Brazil/0000755000175000017500000000000012665173607015750 5ustar sergeisergeitcl8.6.5/library/tzdata/Brazil/Acre0000644000175000017500000000027512661614722016543 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Rio_Branco)]} { LoadTimeZoneFile America/Rio_Branco } set TZData(:Brazil/Acre) $TZData(:America/Rio_Branco) tcl8.6.5/library/tzdata/Brazil/DeNoronha0000644000175000017500000000027112661614722017542 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Noronha)]} { LoadTimeZoneFile America/Noronha } set TZData(:Brazil/DeNoronha) $TZData(:America/Noronha) tcl8.6.5/library/tzdata/Brazil/East0000644000175000017500000000027212661614722016562 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Sao_Paulo)]} { LoadTimeZoneFile America/Sao_Paulo } set TZData(:Brazil/East) $TZData(:America/Sao_Paulo) tcl8.6.5/library/tzdata/Brazil/West0000644000175000017500000000026112661614722016606 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Manaus)]} { LoadTimeZoneFile America/Manaus } set TZData(:Brazil/West) $TZData(:America/Manaus) tcl8.6.5/library/tzdata/Eire0000644000175000017500000000024712661614722015331 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Dublin)]} { LoadTimeZoneFile Europe/Dublin } set TZData(:Eire) $TZData(:Europe/Dublin) tcl8.6.5/library/tzdata/Israel0000644000175000017500000000025412661614722015662 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Jerusalem)]} { LoadTimeZoneFile Asia/Jerusalem } set TZData(:Israel) $TZData(:Asia/Jerusalem) tcl8.6.5/library/tzdata/HST0000644000175000017500000000015212661614721015075 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:HST) { {-9223372036854775808 -36000 0 HST} } tcl8.6.5/library/tzdata/ROK0000644000175000017500000000023512661614722015075 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Seoul)]} { LoadTimeZoneFile Asia/Seoul } set TZData(:ROK) $TZData(:Asia/Seoul) tcl8.6.5/library/tzdata/Japan0000644000175000017500000000023712661614722015475 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Tokyo)]} { LoadTimeZoneFile Asia/Tokyo } set TZData(:Japan) $TZData(:Asia/Tokyo) tcl8.6.5/library/tzdata/Chile/0000755000175000017500000000000012665173607015551 5ustar sergeisergeitcl8.6.5/library/tzdata/Chile/Continental0000644000175000017500000000027512661614722017750 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Santiago)]} { LoadTimeZoneFile America/Santiago } set TZData(:Chile/Continental) $TZData(:America/Santiago) tcl8.6.5/library/tzdata/Chile/EasterIsland0000644000175000017500000000027012661614722020043 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Easter)]} { LoadTimeZoneFile Pacific/Easter } set TZData(:Chile/EasterIsland) $TZData(:Pacific/Easter) tcl8.6.5/library/tzdata/America/0000755000175000017500000000000012665173607016066 5ustar sergeisergeitcl8.6.5/library/tzdata/America/St_Lucia0000644000175000017500000000031312663660066017507 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/St_Lucia) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Cordoba0000644000175000017500000000032612661614722017355 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Argentina/Cordoba)]} { LoadTimeZoneFile America/Argentina/Cordoba } set TZData(:America/Cordoba) $TZData(:America/Argentina/Cordoba) tcl8.6.5/library/tzdata/America/Anchorage0000644000175000017500000002037412661614720017676 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Anchorage) { {-9223372036854775808 50424 0 LMT} {-3225362424 -35976 0 LMT} {-2188951224 -36000 0 CAT} {-883576800 -36000 0 CAWT} {-880200000 -32400 1 CAWT} {-769395600 -32400 0 CAPT} {-765378000 -36000 0 CAPT} {-757346400 -36000 0 CAT} {-86882400 -36000 0 AHST} {-31500000 -36000 0 AHST} {-21470400 -32400 1 AHDT} {-5749200 -36000 0 AHST} {9979200 -32400 1 AHDT} {25700400 -36000 0 AHST} {41428800 -32400 1 AHDT} {57754800 -36000 0 AHST} {73483200 -32400 1 AHDT} {89204400 -36000 0 AHST} {104932800 -32400 1 AHDT} {120654000 -36000 0 AHST} {126705600 -32400 1 AHDT} {152103600 -36000 0 AHST} {162388800 -32400 1 AHDT} {183553200 -36000 0 AHST} {199281600 -32400 1 AHDT} {215607600 -36000 0 AHST} {230731200 -32400 1 AHDT} {247057200 -36000 0 AHST} {262785600 -32400 1 AHDT} {278506800 -36000 0 AHST} {294235200 -32400 1 AHDT} {309956400 -36000 0 AHST} {325684800 -32400 1 AHDT} {341406000 -36000 0 AHST} {357134400 -32400 1 AHDT} {372855600 -36000 0 AHST} {388584000 -32400 1 AHDT} {404910000 -36000 0 AHST} {420033600 -32400 1 AHDT} {439030800 -32400 0 AKST} {452084400 -28800 1 AKDT} {467805600 -32400 0 AKST} {483534000 -28800 1 AKDT} {499255200 -32400 0 AKST} {514983600 -28800 1 AKDT} {530704800 -32400 0 AKST} {544618800 -28800 1 AKDT} {562154400 -32400 0 AKST} {576068400 -28800 1 AKDT} {594208800 -32400 0 AKST} {607518000 -28800 1 AKDT} {625658400 -32400 0 AKST} {638967600 -28800 1 AKDT} {657108000 -32400 0 AKST} {671022000 -28800 1 AKDT} {688557600 -32400 0 AKST} {702471600 -28800 1 AKDT} {720007200 -32400 0 AKST} {733921200 -28800 1 AKDT} {752061600 -32400 0 AKST} {765370800 -28800 1 AKDT} {783511200 -32400 0 AKST} {796820400 -28800 1 AKDT} {814960800 -32400 0 AKST} {828874800 -28800 1 AKDT} {846410400 -32400 0 AKST} {860324400 -28800 1 AKDT} {877860000 -32400 0 AKST} {891774000 -28800 1 AKDT} {909309600 -32400 0 AKST} {923223600 -28800 1 AKDT} {941364000 -32400 0 AKST} {954673200 -28800 1 AKDT} {972813600 -32400 0 AKST} {986122800 -28800 1 AKDT} {1004263200 -32400 0 AKST} {1018177200 -28800 1 AKDT} {1035712800 -32400 0 AKST} {1049626800 -28800 1 AKDT} {1067162400 -32400 0 AKST} {1081076400 -28800 1 AKDT} {1099216800 -32400 0 AKST} {1112526000 -28800 1 AKDT} {1130666400 -32400 0 AKST} {1143975600 -28800 1 AKDT} {1162116000 -32400 0 AKST} {1173610800 -28800 1 AKDT} {1194170400 -32400 0 AKST} {1205060400 -28800 1 AKDT} {1225620000 -32400 0 AKST} {1236510000 -28800 1 AKDT} {1257069600 -32400 0 AKST} {1268564400 -28800 1 AKDT} {1289124000 -32400 0 AKST} {1300014000 -28800 1 AKDT} {1320573600 -32400 0 AKST} {1331463600 -28800 1 AKDT} {1352023200 -32400 0 AKST} {1362913200 -28800 1 AKDT} {1383472800 -32400 0 AKST} {1394362800 -28800 1 AKDT} {1414922400 -32400 0 AKST} {1425812400 -28800 1 AKDT} {1446372000 -32400 0 AKST} {1457866800 -28800 1 AKDT} {1478426400 -32400 0 AKST} {1489316400 -28800 1 AKDT} {1509876000 -32400 0 AKST} {1520766000 -28800 1 AKDT} {1541325600 -32400 0 AKST} {1552215600 -28800 1 AKDT} {1572775200 -32400 0 AKST} {1583665200 -28800 1 AKDT} {1604224800 -32400 0 AKST} {1615719600 -28800 1 AKDT} {1636279200 -32400 0 AKST} {1647169200 -28800 1 AKDT} {1667728800 -32400 0 AKST} {1678618800 -28800 1 AKDT} {1699178400 -32400 0 AKST} {1710068400 -28800 1 AKDT} {1730628000 -32400 0 AKST} {1741518000 -28800 1 AKDT} {1762077600 -32400 0 AKST} {1772967600 -28800 1 AKDT} {1793527200 -32400 0 AKST} {1805022000 -28800 1 AKDT} {1825581600 -32400 0 AKST} {1836471600 -28800 1 AKDT} {1857031200 -32400 0 AKST} {1867921200 -28800 1 AKDT} {1888480800 -32400 0 AKST} {1899370800 -28800 1 AKDT} {1919930400 -32400 0 AKST} {1930820400 -28800 1 AKDT} {1951380000 -32400 0 AKST} {1962874800 -28800 1 AKDT} {1983434400 -32400 0 AKST} {1994324400 -28800 1 AKDT} {2014884000 -32400 0 AKST} {2025774000 -28800 1 AKDT} {2046333600 -32400 0 AKST} {2057223600 -28800 1 AKDT} {2077783200 -32400 0 AKST} {2088673200 -28800 1 AKDT} {2109232800 -32400 0 AKST} {2120122800 -28800 1 AKDT} {2140682400 -32400 0 AKST} {2152177200 -28800 1 AKDT} {2172736800 -32400 0 AKST} {2183626800 -28800 1 AKDT} {2204186400 -32400 0 AKST} {2215076400 -28800 1 AKDT} {2235636000 -32400 0 AKST} {2246526000 -28800 1 AKDT} {2267085600 -32400 0 AKST} {2277975600 -28800 1 AKDT} {2298535200 -32400 0 AKST} {2309425200 -28800 1 AKDT} {2329984800 -32400 0 AKST} {2341479600 -28800 1 AKDT} {2362039200 -32400 0 AKST} {2372929200 -28800 1 AKDT} {2393488800 -32400 0 AKST} {2404378800 -28800 1 AKDT} {2424938400 -32400 0 AKST} {2435828400 -28800 1 AKDT} {2456388000 -32400 0 AKST} {2467278000 -28800 1 AKDT} {2487837600 -32400 0 AKST} {2499332400 -28800 1 AKDT} {2519892000 -32400 0 AKST} {2530782000 -28800 1 AKDT} {2551341600 -32400 0 AKST} {2562231600 -28800 1 AKDT} {2582791200 -32400 0 AKST} {2593681200 -28800 1 AKDT} {2614240800 -32400 0 AKST} {2625130800 -28800 1 AKDT} {2645690400 -32400 0 AKST} {2656580400 -28800 1 AKDT} {2677140000 -32400 0 AKST} {2688634800 -28800 1 AKDT} {2709194400 -32400 0 AKST} {2720084400 -28800 1 AKDT} {2740644000 -32400 0 AKST} {2751534000 -28800 1 AKDT} {2772093600 -32400 0 AKST} {2782983600 -28800 1 AKDT} {2803543200 -32400 0 AKST} {2814433200 -28800 1 AKDT} {2834992800 -32400 0 AKST} {2846487600 -28800 1 AKDT} {2867047200 -32400 0 AKST} {2877937200 -28800 1 AKDT} {2898496800 -32400 0 AKST} {2909386800 -28800 1 AKDT} {2929946400 -32400 0 AKST} {2940836400 -28800 1 AKDT} {2961396000 -32400 0 AKST} {2972286000 -28800 1 AKDT} {2992845600 -32400 0 AKST} {3003735600 -28800 1 AKDT} {3024295200 -32400 0 AKST} {3035790000 -28800 1 AKDT} {3056349600 -32400 0 AKST} {3067239600 -28800 1 AKDT} {3087799200 -32400 0 AKST} {3098689200 -28800 1 AKDT} {3119248800 -32400 0 AKST} {3130138800 -28800 1 AKDT} {3150698400 -32400 0 AKST} {3161588400 -28800 1 AKDT} {3182148000 -32400 0 AKST} {3193038000 -28800 1 AKDT} {3213597600 -32400 0 AKST} {3225092400 -28800 1 AKDT} {3245652000 -32400 0 AKST} {3256542000 -28800 1 AKDT} {3277101600 -32400 0 AKST} {3287991600 -28800 1 AKDT} {3308551200 -32400 0 AKST} {3319441200 -28800 1 AKDT} {3340000800 -32400 0 AKST} {3350890800 -28800 1 AKDT} {3371450400 -32400 0 AKST} {3382945200 -28800 1 AKDT} {3403504800 -32400 0 AKST} {3414394800 -28800 1 AKDT} {3434954400 -32400 0 AKST} {3445844400 -28800 1 AKDT} {3466404000 -32400 0 AKST} {3477294000 -28800 1 AKDT} {3497853600 -32400 0 AKST} {3508743600 -28800 1 AKDT} {3529303200 -32400 0 AKST} {3540193200 -28800 1 AKDT} {3560752800 -32400 0 AKST} {3572247600 -28800 1 AKDT} {3592807200 -32400 0 AKST} {3603697200 -28800 1 AKDT} {3624256800 -32400 0 AKST} {3635146800 -28800 1 AKDT} {3655706400 -32400 0 AKST} {3666596400 -28800 1 AKDT} {3687156000 -32400 0 AKST} {3698046000 -28800 1 AKDT} {3718605600 -32400 0 AKST} {3730100400 -28800 1 AKDT} {3750660000 -32400 0 AKST} {3761550000 -28800 1 AKDT} {3782109600 -32400 0 AKST} {3792999600 -28800 1 AKDT} {3813559200 -32400 0 AKST} {3824449200 -28800 1 AKDT} {3845008800 -32400 0 AKST} {3855898800 -28800 1 AKDT} {3876458400 -32400 0 AKST} {3887348400 -28800 1 AKDT} {3907908000 -32400 0 AKST} {3919402800 -28800 1 AKDT} {3939962400 -32400 0 AKST} {3950852400 -28800 1 AKDT} {3971412000 -32400 0 AKST} {3982302000 -28800 1 AKDT} {4002861600 -32400 0 AKST} {4013751600 -28800 1 AKDT} {4034311200 -32400 0 AKST} {4045201200 -28800 1 AKDT} {4065760800 -32400 0 AKST} {4076650800 -28800 1 AKDT} {4097210400 -32400 0 AKST} } tcl8.6.5/library/tzdata/America/Hermosillo0000644000175000017500000000112312661614720020113 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Hermosillo) { {-9223372036854775808 -26632 0 LMT} {-1514739600 -25200 0 MST} {-1343066400 -21600 0 CST} {-1234807200 -25200 0 MST} {-1220292000 -21600 0 CST} {-1207159200 -25200 0 MST} {-1191344400 -21600 0 CST} {-873828000 -25200 0 MST} {-661539600 -28800 0 PST} {28800 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {915174000 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Cayman0000644000175000017500000000026412665113557017221 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Panama)]} { LoadTimeZoneFile America/Panama } set TZData(:America/Cayman) $TZData(:America/Panama) tcl8.6.5/library/tzdata/America/Belize0000644000175000017500000000344512661614720017221 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Belize) { {-9223372036854775808 -21168 0 LMT} {-1822500432 -21600 0 CST} {-1616954400 -19800 1 CHDT} {-1606069800 -21600 0 CST} {-1585504800 -19800 1 CHDT} {-1574015400 -21600 0 CST} {-1554055200 -19800 1 CHDT} {-1542565800 -21600 0 CST} {-1522605600 -19800 1 CHDT} {-1511116200 -21600 0 CST} {-1490551200 -19800 1 CHDT} {-1479666600 -21600 0 CST} {-1459101600 -19800 1 CHDT} {-1448217000 -21600 0 CST} {-1427652000 -19800 1 CHDT} {-1416162600 -21600 0 CST} {-1396202400 -19800 1 CHDT} {-1384713000 -21600 0 CST} {-1364752800 -19800 1 CHDT} {-1353263400 -21600 0 CST} {-1333303200 -19800 1 CHDT} {-1321813800 -21600 0 CST} {-1301248800 -19800 1 CHDT} {-1290364200 -21600 0 CST} {-1269799200 -19800 1 CHDT} {-1258914600 -21600 0 CST} {-1238349600 -19800 1 CHDT} {-1226860200 -21600 0 CST} {-1206900000 -19800 1 CHDT} {-1195410600 -21600 0 CST} {-1175450400 -19800 1 CHDT} {-1163961000 -21600 0 CST} {-1143396000 -19800 1 CHDT} {-1132511400 -21600 0 CST} {-1111946400 -19800 1 CHDT} {-1101061800 -21600 0 CST} {-1080496800 -19800 1 CHDT} {-1069612200 -21600 0 CST} {-1049047200 -19800 1 CHDT} {-1037557800 -21600 0 CST} {-1017597600 -19800 1 CHDT} {-1006108200 -21600 0 CST} {-986148000 -19800 1 CHDT} {-974658600 -21600 0 CST} {-954093600 -19800 1 CHDT} {-943209000 -21600 0 CST} {-922644000 -19800 1 CHDT} {-911759400 -21600 0 CST} {-891194400 -19800 1 CHDT} {-879705000 -21600 0 CST} {-859744800 -19800 1 CHDT} {-848255400 -21600 0 CST} {123919200 -18000 1 CDT} {129618000 -21600 0 CST} {409039200 -18000 1 CDT} {413874000 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Vancouver0000644000175000017500000002242712663660066017766 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Vancouver) { {-9223372036854775808 -29548 0 LMT} {-2713880852 -28800 0 PST} {-1632060000 -25200 1 PDT} {-1615129200 -28800 0 PST} {-880207200 -25200 1 PWT} {-769395600 -25200 1 PPT} {-765385200 -28800 0 PST} {-747237600 -25200 1 PDT} {-732726000 -28800 0 PST} {-715788000 -25200 1 PDT} {-702486000 -28800 0 PST} {-684338400 -25200 1 PDT} {-671036400 -28800 0 PST} {-652888800 -25200 1 PDT} {-639586800 -28800 0 PST} {-620834400 -25200 1 PDT} {-608137200 -28800 0 PST} {-589384800 -25200 1 PDT} {-576082800 -28800 0 PST} {-557935200 -25200 1 PDT} {-544633200 -28800 0 PST} {-526485600 -25200 1 PDT} {-513183600 -28800 0 PST} {-495036000 -25200 1 PDT} {-481734000 -28800 0 PST} {-463586400 -25200 1 PDT} {-450284400 -28800 0 PST} {-431532000 -25200 1 PDT} {-418230000 -28800 0 PST} {-400082400 -25200 1 PDT} {-386780400 -28800 0 PST} {-368632800 -25200 1 PDT} {-355330800 -28800 0 PST} {-337183200 -25200 1 PDT} {-323881200 -28800 0 PST} {-305733600 -25200 1 PDT} {-292431600 -28800 0 PST} {-273679200 -25200 1 PDT} {-260982000 -28800 0 PST} {-242229600 -25200 1 PDT} {-226508400 -28800 0 PST} {-210780000 -25200 1 PDT} {-195058800 -28800 0 PST} {-179330400 -25200 1 PDT} {-163609200 -28800 0 PST} {-147880800 -25200 1 PDT} {-131554800 -28800 0 PST} {-116431200 -25200 1 PDT} {-100105200 -28800 0 PST} {-84376800 -25200 1 PDT} {-68655600 -28800 0 PST} {-52927200 -25200 1 PDT} {-37206000 -28800 0 PST} {-21477600 -25200 1 PDT} {-5756400 -28800 0 PST} {9972000 -25200 1 PDT} {25693200 -28800 0 PST} {41421600 -25200 1 PDT} {57747600 -28800 0 PST} {73476000 -25200 1 PDT} {89197200 -28800 0 PST} {104925600 -25200 1 PDT} {120646800 -28800 0 PST} {136375200 -25200 1 PDT} {152096400 -28800 0 PST} {167824800 -25200 1 PDT} {183546000 -28800 0 PST} {199274400 -25200 1 PDT} {215600400 -28800 0 PST} {230724000 -25200 1 PDT} {247050000 -28800 0 PST} {262778400 -25200 1 PDT} {278499600 -28800 0 PST} {294228000 -25200 1 PDT} {309949200 -28800 0 PST} {325677600 -25200 1 PDT} {341398800 -28800 0 PST} {357127200 -25200 1 PDT} {372848400 -28800 0 PST} {388576800 -25200 1 PDT} {404902800 -28800 0 PST} {420026400 -25200 1 PDT} {436352400 -28800 0 PST} {452080800 -25200 1 PDT} {467802000 -28800 0 PST} {483530400 -25200 1 PDT} {499251600 -28800 0 PST} {514980000 -25200 1 PDT} {530701200 -28800 0 PST} {536486400 -28800 0 PST} {544615200 -25200 1 PDT} {562150800 -28800 0 PST} {576064800 -25200 1 PDT} {594205200 -28800 0 PST} {607514400 -25200 1 PDT} {625654800 -28800 0 PST} {638964000 -25200 1 PDT} {657104400 -28800 0 PST} {671018400 -25200 1 PDT} {688554000 -28800 0 PST} {702468000 -25200 1 PDT} {720003600 -28800 0 PST} {733917600 -25200 1 PDT} {752058000 -28800 0 PST} {765367200 -25200 1 PDT} {783507600 -28800 0 PST} {796816800 -25200 1 PDT} {814957200 -28800 0 PST} {828871200 -25200 1 PDT} {846406800 -28800 0 PST} {860320800 -25200 1 PDT} {877856400 -28800 0 PST} {891770400 -25200 1 PDT} {909306000 -28800 0 PST} {923220000 -25200 1 PDT} {941360400 -28800 0 PST} {954669600 -25200 1 PDT} {972810000 -28800 0 PST} {986119200 -25200 1 PDT} {1004259600 -28800 0 PST} {1018173600 -25200 1 PDT} {1035709200 -28800 0 PST} {1049623200 -25200 1 PDT} {1067158800 -28800 0 PST} {1081072800 -25200 1 PDT} {1099213200 -28800 0 PST} {1112522400 -25200 1 PDT} {1130662800 -28800 0 PST} {1143972000 -25200 1 PDT} {1162112400 -28800 0 PST} {1173607200 -25200 1 PDT} {1194166800 -28800 0 PST} {1205056800 -25200 1 PDT} {1225616400 -28800 0 PST} {1236506400 -25200 1 PDT} {1257066000 -28800 0 PST} {1268560800 -25200 1 PDT} {1289120400 -28800 0 PST} {1300010400 -25200 1 PDT} {1320570000 -28800 0 PST} {1331460000 -25200 1 PDT} {1352019600 -28800 0 PST} {1362909600 -25200 1 PDT} {1383469200 -28800 0 PST} {1394359200 -25200 1 PDT} {1414918800 -28800 0 PST} {1425808800 -25200 1 PDT} {1446368400 -28800 0 PST} {1457863200 -25200 1 PDT} {1478422800 -28800 0 PST} {1489312800 -25200 1 PDT} {1509872400 -28800 0 PST} {1520762400 -25200 1 PDT} {1541322000 -28800 0 PST} {1552212000 -25200 1 PDT} {1572771600 -28800 0 PST} {1583661600 -25200 1 PDT} {1604221200 -28800 0 PST} {1615716000 -25200 1 PDT} {1636275600 -28800 0 PST} {1647165600 -25200 1 PDT} {1667725200 -28800 0 PST} {1678615200 -25200 1 PDT} {1699174800 -28800 0 PST} {1710064800 -25200 1 PDT} {1730624400 -28800 0 PST} {1741514400 -25200 1 PDT} {1762074000 -28800 0 PST} {1772964000 -25200 1 PDT} {1793523600 -28800 0 PST} {1805018400 -25200 1 PDT} {1825578000 -28800 0 PST} {1836468000 -25200 1 PDT} {1857027600 -28800 0 PST} {1867917600 -25200 1 PDT} {1888477200 -28800 0 PST} {1899367200 -25200 1 PDT} {1919926800 -28800 0 PST} {1930816800 -25200 1 PDT} {1951376400 -28800 0 PST} {1962871200 -25200 1 PDT} {1983430800 -28800 0 PST} {1994320800 -25200 1 PDT} {2014880400 -28800 0 PST} {2025770400 -25200 1 PDT} {2046330000 -28800 0 PST} {2057220000 -25200 1 PDT} {2077779600 -28800 0 PST} {2088669600 -25200 1 PDT} {2109229200 -28800 0 PST} {2120119200 -25200 1 PDT} {2140678800 -28800 0 PST} {2152173600 -25200 1 PDT} {2172733200 -28800 0 PST} {2183623200 -25200 1 PDT} {2204182800 -28800 0 PST} {2215072800 -25200 1 PDT} {2235632400 -28800 0 PST} {2246522400 -25200 1 PDT} {2267082000 -28800 0 PST} {2277972000 -25200 1 PDT} {2298531600 -28800 0 PST} {2309421600 -25200 1 PDT} {2329981200 -28800 0 PST} {2341476000 -25200 1 PDT} {2362035600 -28800 0 PST} {2372925600 -25200 1 PDT} {2393485200 -28800 0 PST} {2404375200 -25200 1 PDT} {2424934800 -28800 0 PST} {2435824800 -25200 1 PDT} {2456384400 -28800 0 PST} {2467274400 -25200 1 PDT} {2487834000 -28800 0 PST} {2499328800 -25200 1 PDT} {2519888400 -28800 0 PST} {2530778400 -25200 1 PDT} {2551338000 -28800 0 PST} {2562228000 -25200 1 PDT} {2582787600 -28800 0 PST} {2593677600 -25200 1 PDT} {2614237200 -28800 0 PST} {2625127200 -25200 1 PDT} {2645686800 -28800 0 PST} {2656576800 -25200 1 PDT} {2677136400 -28800 0 PST} {2688631200 -25200 1 PDT} {2709190800 -28800 0 PST} {2720080800 -25200 1 PDT} {2740640400 -28800 0 PST} {2751530400 -25200 1 PDT} {2772090000 -28800 0 PST} {2782980000 -25200 1 PDT} {2803539600 -28800 0 PST} {2814429600 -25200 1 PDT} {2834989200 -28800 0 PST} {2846484000 -25200 1 PDT} {2867043600 -28800 0 PST} {2877933600 -25200 1 PDT} {2898493200 -28800 0 PST} {2909383200 -25200 1 PDT} {2929942800 -28800 0 PST} {2940832800 -25200 1 PDT} {2961392400 -28800 0 PST} {2972282400 -25200 1 PDT} {2992842000 -28800 0 PST} {3003732000 -25200 1 PDT} {3024291600 -28800 0 PST} {3035786400 -25200 1 PDT} {3056346000 -28800 0 PST} {3067236000 -25200 1 PDT} {3087795600 -28800 0 PST} {3098685600 -25200 1 PDT} {3119245200 -28800 0 PST} {3130135200 -25200 1 PDT} {3150694800 -28800 0 PST} {3161584800 -25200 1 PDT} {3182144400 -28800 0 PST} {3193034400 -25200 1 PDT} {3213594000 -28800 0 PST} {3225088800 -25200 1 PDT} {3245648400 -28800 0 PST} {3256538400 -25200 1 PDT} {3277098000 -28800 0 PST} {3287988000 -25200 1 PDT} {3308547600 -28800 0 PST} {3319437600 -25200 1 PDT} {3339997200 -28800 0 PST} {3350887200 -25200 1 PDT} {3371446800 -28800 0 PST} {3382941600 -25200 1 PDT} {3403501200 -28800 0 PST} {3414391200 -25200 1 PDT} {3434950800 -28800 0 PST} {3445840800 -25200 1 PDT} {3466400400 -28800 0 PST} {3477290400 -25200 1 PDT} {3497850000 -28800 0 PST} {3508740000 -25200 1 PDT} {3529299600 -28800 0 PST} {3540189600 -25200 1 PDT} {3560749200 -28800 0 PST} {3572244000 -25200 1 PDT} {3592803600 -28800 0 PST} {3603693600 -25200 1 PDT} {3624253200 -28800 0 PST} {3635143200 -25200 1 PDT} {3655702800 -28800 0 PST} {3666592800 -25200 1 PDT} {3687152400 -28800 0 PST} {3698042400 -25200 1 PDT} {3718602000 -28800 0 PST} {3730096800 -25200 1 PDT} {3750656400 -28800 0 PST} {3761546400 -25200 1 PDT} {3782106000 -28800 0 PST} {3792996000 -25200 1 PDT} {3813555600 -28800 0 PST} {3824445600 -25200 1 PDT} {3845005200 -28800 0 PST} {3855895200 -25200 1 PDT} {3876454800 -28800 0 PST} {3887344800 -25200 1 PDT} {3907904400 -28800 0 PST} {3919399200 -25200 1 PDT} {3939958800 -28800 0 PST} {3950848800 -25200 1 PDT} {3971408400 -28800 0 PST} {3982298400 -25200 1 PDT} {4002858000 -28800 0 PST} {4013748000 -25200 1 PDT} {4034307600 -28800 0 PST} {4045197600 -25200 1 PDT} {4065757200 -28800 0 PST} {4076647200 -25200 1 PDT} {4097206800 -28800 0 PST} } tcl8.6.5/library/tzdata/America/Sao_Paulo0000644000175000017500000001677612663653132017706 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Sao_Paulo) { {-9223372036854775808 -11188 0 LMT} {-1767214412 -10800 0 BRT} {-1206957600 -7200 1 BRST} {-1191362400 -10800 0 BRT} {-1175374800 -7200 1 BRST} {-1159826400 -10800 0 BRT} {-633819600 -7200 1 BRST} {-622069200 -10800 0 BRT} {-602283600 -7200 1 BRST} {-591832800 -10800 0 BRT} {-570747600 -7200 1 BRST} {-560210400 -10800 0 BRT} {-539125200 -7200 1 BRST} {-531352800 -10800 0 BRT} {-195429600 -7200 1 BRST} {-189381600 -7200 0 BRT} {-184197600 -10800 0 BRT} {-155163600 -7200 1 BRST} {-150069600 -10800 0 BRT} {-128898000 -7200 1 BRST} {-121125600 -10800 0 BRT} {-99954000 -7200 1 BRST} {-89589600 -10800 0 BRT} {-68418000 -7200 1 BRST} {-57967200 -10800 0 BRT} {499748400 -7200 1 BRST} {511236000 -10800 0 BRT} {530593200 -7200 1 BRST} {540266400 -10800 0 BRT} {562129200 -7200 1 BRST} {571197600 -10800 0 BRT} {592974000 -7200 1 BRST} {602042400 -10800 0 BRT} {624423600 -7200 1 BRST} {634701600 -10800 0 BRT} {656478000 -7200 1 BRST} {666756000 -10800 0 BRT} {687927600 -7200 1 BRST} {697600800 -10800 0 BRT} {719982000 -7200 1 BRST} {728445600 -10800 0 BRT} {750826800 -7200 1 BRST} {761709600 -10800 0 BRT} {782276400 -7200 1 BRST} {793159200 -10800 0 BRT} {813726000 -7200 1 BRST} {824004000 -10800 0 BRT} {844570800 -7200 1 BRST} {856058400 -10800 0 BRT} {876106800 -7200 1 BRST} {888717600 -10800 0 BRT} {908074800 -7200 1 BRST} {919562400 -10800 0 BRT} {938919600 -7200 1 BRST} {951616800 -10800 0 BRT} {970974000 -7200 1 BRST} {982461600 -10800 0 BRT} {1003028400 -7200 1 BRST} {1013911200 -10800 0 BRT} {1036292400 -7200 1 BRST} {1045360800 -10800 0 BRT} {1066532400 -7200 1 BRST} {1076810400 -10800 0 BRT} {1099364400 -7200 1 BRST} {1108864800 -10800 0 BRT} {1129431600 -7200 1 BRST} {1140314400 -10800 0 BRT} {1162695600 -7200 1 BRST} {1172368800 -10800 0 BRT} {1192330800 -7200 1 BRST} {1203213600 -10800 0 BRT} {1224385200 -7200 1 BRST} {1234663200 -10800 0 BRT} {1255834800 -7200 1 BRST} {1266717600 -10800 0 BRT} {1287284400 -7200 1 BRST} {1298167200 -10800 0 BRT} {1318734000 -7200 1 BRST} {1330221600 -10800 0 BRT} {1350788400 -7200 1 BRST} {1361066400 -10800 0 BRT} {1382238000 -7200 1 BRST} {1392516000 -10800 0 BRT} {1413687600 -7200 1 BRST} {1424570400 -10800 0 BRT} {1445137200 -7200 1 BRST} {1456020000 -10800 0 BRT} {1476586800 -7200 1 BRST} {1487469600 -10800 0 BRT} {1508036400 -7200 1 BRST} {1518919200 -10800 0 BRT} {1540090800 -7200 1 BRST} {1550368800 -10800 0 BRT} {1571540400 -7200 1 BRST} {1581818400 -10800 0 BRT} {1602990000 -7200 1 BRST} {1613872800 -10800 0 BRT} {1634439600 -7200 1 BRST} {1645322400 -10800 0 BRT} {1665889200 -7200 1 BRST} {1677376800 -10800 0 BRT} {1697338800 -7200 1 BRST} {1708221600 -10800 0 BRT} {1729393200 -7200 1 BRST} {1739671200 -10800 0 BRT} {1760842800 -7200 1 BRST} {1771725600 -10800 0 BRT} {1792292400 -7200 1 BRST} {1803175200 -10800 0 BRT} {1823742000 -7200 1 BRST} {1834624800 -10800 0 BRT} {1855191600 -7200 1 BRST} {1866074400 -10800 0 BRT} {1887246000 -7200 1 BRST} {1897524000 -10800 0 BRT} {1918695600 -7200 1 BRST} {1928973600 -10800 0 BRT} {1950145200 -7200 1 BRST} {1960423200 -10800 0 BRT} {1981594800 -7200 1 BRST} {1992477600 -10800 0 BRT} {2013044400 -7200 1 BRST} {2024532000 -10800 0 BRT} {2044494000 -7200 1 BRST} {2055376800 -10800 0 BRT} {2076548400 -7200 1 BRST} {2086826400 -10800 0 BRT} {2107998000 -7200 1 BRST} {2118880800 -10800 0 BRT} {2139447600 -7200 1 BRST} {2150330400 -10800 0 BRT} {2170897200 -7200 1 BRST} {2181780000 -10800 0 BRT} {2202346800 -7200 1 BRST} {2213229600 -10800 0 BRT} {2234401200 -7200 1 BRST} {2244679200 -10800 0 BRT} {2265850800 -7200 1 BRST} {2276128800 -10800 0 BRT} {2297300400 -7200 1 BRST} {2307578400 -10800 0 BRT} {2328750000 -7200 1 BRST} {2339632800 -10800 0 BRT} {2360199600 -7200 1 BRST} {2371082400 -10800 0 BRT} {2391649200 -7200 1 BRST} {2402532000 -10800 0 BRT} {2423703600 -7200 1 BRST} {2433981600 -10800 0 BRT} {2455153200 -7200 1 BRST} {2465431200 -10800 0 BRT} {2486602800 -7200 1 BRST} {2497485600 -10800 0 BRT} {2518052400 -7200 1 BRST} {2528935200 -10800 0 BRT} {2549502000 -7200 1 BRST} {2560384800 -10800 0 BRT} {2580951600 -7200 1 BRST} {2591834400 -10800 0 BRT} {2613006000 -7200 1 BRST} {2623284000 -10800 0 BRT} {2644455600 -7200 1 BRST} {2654733600 -10800 0 BRT} {2675905200 -7200 1 BRST} {2686788000 -10800 0 BRT} {2707354800 -7200 1 BRST} {2718237600 -10800 0 BRT} {2738804400 -7200 1 BRST} {2749687200 -10800 0 BRT} {2770858800 -7200 1 BRST} {2781136800 -10800 0 BRT} {2802308400 -7200 1 BRST} {2812586400 -10800 0 BRT} {2833758000 -7200 1 BRST} {2844036000 -10800 0 BRT} {2865207600 -7200 1 BRST} {2876090400 -10800 0 BRT} {2896657200 -7200 1 BRST} {2907540000 -10800 0 BRT} {2928106800 -7200 1 BRST} {2938989600 -10800 0 BRT} {2960161200 -7200 1 BRST} {2970439200 -10800 0 BRT} {2991610800 -7200 1 BRST} {3001888800 -10800 0 BRT} {3023060400 -7200 1 BRST} {3033943200 -10800 0 BRT} {3054510000 -7200 1 BRST} {3065392800 -10800 0 BRT} {3085959600 -7200 1 BRST} {3096842400 -10800 0 BRT} {3118014000 -7200 1 BRST} {3128292000 -10800 0 BRT} {3149463600 -7200 1 BRST} {3159741600 -10800 0 BRT} {3180913200 -7200 1 BRST} {3191191200 -10800 0 BRT} {3212362800 -7200 1 BRST} {3223245600 -10800 0 BRT} {3243812400 -7200 1 BRST} {3254695200 -10800 0 BRT} {3275262000 -7200 1 BRST} {3286144800 -10800 0 BRT} {3307316400 -7200 1 BRST} {3317594400 -10800 0 BRT} {3338766000 -7200 1 BRST} {3349044000 -10800 0 BRT} {3370215600 -7200 1 BRST} {3381098400 -10800 0 BRT} {3401665200 -7200 1 BRST} {3412548000 -10800 0 BRT} {3433114800 -7200 1 BRST} {3443997600 -10800 0 BRT} {3464564400 -7200 1 BRST} {3475447200 -10800 0 BRT} {3496618800 -7200 1 BRST} {3506896800 -10800 0 BRT} {3528068400 -7200 1 BRST} {3538346400 -10800 0 BRT} {3559518000 -7200 1 BRST} {3570400800 -10800 0 BRT} {3590967600 -7200 1 BRST} {3601850400 -10800 0 BRT} {3622417200 -7200 1 BRST} {3633300000 -10800 0 BRT} {3654471600 -7200 1 BRST} {3664749600 -10800 0 BRT} {3685921200 -7200 1 BRST} {3696199200 -10800 0 BRT} {3717370800 -7200 1 BRST} {3727648800 -10800 0 BRT} {3748820400 -7200 1 BRST} {3759703200 -10800 0 BRT} {3780270000 -7200 1 BRST} {3791152800 -10800 0 BRT} {3811719600 -7200 1 BRST} {3822602400 -10800 0 BRT} {3843774000 -7200 1 BRST} {3854052000 -10800 0 BRT} {3875223600 -7200 1 BRST} {3885501600 -10800 0 BRT} {3906673200 -7200 1 BRST} {3917556000 -10800 0 BRT} {3938122800 -7200 1 BRST} {3949005600 -10800 0 BRT} {3969572400 -7200 1 BRST} {3980455200 -10800 0 BRT} {4001626800 -7200 1 BRST} {4011904800 -10800 0 BRT} {4033076400 -7200 1 BRST} {4043354400 -10800 0 BRT} {4064526000 -7200 1 BRST} {4074804000 -10800 0 BRT} {4095975600 -7200 1 BRST} } tcl8.6.5/library/tzdata/America/Chicago0000644000175000017500000002537312661614720017350 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Chicago) { {-9223372036854775808 -21036 0 LMT} {-2717647200 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-1577901600 -21600 0 CST} {-1563724800 -18000 1 CDT} {-1551632400 -21600 0 CST} {-1538928000 -18000 1 CDT} {-1520182800 -21600 0 CST} {-1504454400 -18000 1 CDT} {-1491757200 -21600 0 CST} {-1473004800 -18000 1 CDT} {-1459702800 -21600 0 CST} {-1441555200 -18000 1 CDT} {-1428253200 -21600 0 CST} {-1410105600 -18000 1 CDT} {-1396803600 -21600 0 CST} {-1378656000 -18000 1 CDT} {-1365354000 -21600 0 CST} {-1347206400 -18000 1 CDT} {-1333904400 -21600 0 CST} {-1315152000 -18000 1 CDT} {-1301850000 -21600 0 CST} {-1283702400 -18000 1 CDT} {-1270400400 -21600 0 CST} {-1252252800 -18000 1 CDT} {-1238950800 -21600 0 CST} {-1220803200 -18000 1 CDT} {-1207501200 -21600 0 CST} {-1189353600 -18000 1 CDT} {-1176051600 -21600 0 CST} {-1157299200 -18000 1 CDT} {-1144602000 -21600 0 CST} {-1125849600 -18000 1 CDT} {-1112547600 -21600 0 CST} {-1094400000 -18000 1 CDT} {-1081098000 -21600 0 CST} {-1067788800 -18000 0 EST} {-1045414800 -21600 0 CST} {-1031500800 -18000 1 CDT} {-1018198800 -21600 0 CST} {-1000051200 -18000 1 CDT} {-986749200 -21600 0 CST} {-967996800 -18000 1 CDT} {-955299600 -21600 0 CST} {-936547200 -18000 1 CDT} {-923245200 -21600 0 CST} {-905097600 -18000 1 CDT} {-891795600 -21600 0 CST} {-883591200 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-757360800 -21600 0 CST} {-747244800 -18000 1 CDT} {-733942800 -21600 0 CST} {-715795200 -18000 1 CDT} {-702493200 -21600 0 CST} {-684345600 -18000 1 CDT} {-671043600 -21600 0 CST} {-652896000 -18000 1 CDT} {-639594000 -21600 0 CST} {-620841600 -18000 1 CDT} {-608144400 -21600 0 CST} {-589392000 -18000 1 CDT} {-576090000 -21600 0 CST} {-557942400 -18000 1 CDT} {-544640400 -21600 0 CST} {-526492800 -18000 1 CDT} {-513190800 -21600 0 CST} {-495043200 -18000 1 CDT} {-481741200 -21600 0 CST} {-463593600 -18000 1 CDT} {-447267600 -21600 0 CST} {-431539200 -18000 1 CDT} {-415818000 -21600 0 CST} {-400089600 -18000 1 CDT} {-384368400 -21600 0 CST} {-368640000 -18000 1 CDT} {-352918800 -21600 0 CST} {-337190400 -18000 1 CDT} {-321469200 -21600 0 CST} {-305740800 -18000 1 CDT} {-289414800 -21600 0 CST} {-273686400 -18000 1 CDT} {-257965200 -21600 0 CST} {-242236800 -18000 1 CDT} {-226515600 -21600 0 CST} {-210787200 -18000 1 CDT} {-195066000 -21600 0 CST} {-179337600 -18000 1 CDT} {-163616400 -21600 0 CST} {-147888000 -18000 1 CDT} {-131562000 -21600 0 CST} {-116438400 -18000 1 CDT} {-100112400 -21600 0 CST} {-94672800 -21600 0 CST} {-84384000 -18000 1 CDT} {-68662800 -21600 0 CST} {-52934400 -18000 1 CDT} {-37213200 -21600 0 CST} {-21484800 -18000 1 CDT} {-5763600 -21600 0 CST} {9964800 -18000 1 CDT} {25686000 -21600 0 CST} {41414400 -18000 1 CDT} {57740400 -21600 0 CST} {73468800 -18000 1 CDT} {89190000 -21600 0 CST} {104918400 -18000 1 CDT} {120639600 -21600 0 CST} {126691200 -18000 1 CDT} {152089200 -21600 0 CST} {162374400 -18000 1 CDT} {183538800 -21600 0 CST} {199267200 -18000 1 CDT} {215593200 -21600 0 CST} {230716800 -18000 1 CDT} {247042800 -21600 0 CST} {262771200 -18000 1 CDT} {278492400 -21600 0 CST} {294220800 -18000 1 CDT} {309942000 -21600 0 CST} {325670400 -18000 1 CDT} {341391600 -21600 0 CST} {357120000 -18000 1 CDT} {372841200 -21600 0 CST} {388569600 -18000 1 CDT} {404895600 -21600 0 CST} {420019200 -18000 1 CDT} {436345200 -21600 0 CST} {452073600 -18000 1 CDT} {467794800 -21600 0 CST} {483523200 -18000 1 CDT} {499244400 -21600 0 CST} {514972800 -18000 1 CDT} {530694000 -21600 0 CST} {544608000 -18000 1 CDT} {562143600 -21600 0 CST} {576057600 -18000 1 CDT} {594198000 -21600 0 CST} {607507200 -18000 1 CDT} {625647600 -21600 0 CST} {638956800 -18000 1 CDT} {657097200 -21600 0 CST} {671011200 -18000 1 CDT} {688546800 -21600 0 CST} {702460800 -18000 1 CDT} {719996400 -21600 0 CST} {733910400 -18000 1 CDT} {752050800 -21600 0 CST} {765360000 -18000 1 CDT} {783500400 -21600 0 CST} {796809600 -18000 1 CDT} {814950000 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972802800 -21600 0 CST} {986112000 -18000 1 CDT} {1004252400 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194159600 -21600 0 CST} {1205049600 -18000 1 CDT} {1225609200 -21600 0 CST} {1236499200 -18000 1 CDT} {1257058800 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Nome0000644000175000017500000002032412661614721016701 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Nome) { {-9223372036854775808 46701 0 LMT} {-3225358701 -39698 0 LMT} {-2188947502 -39600 0 NST} {-883573200 -39600 0 NST} {-880196400 -36000 1 NWT} {-769395600 -36000 1 NPT} {-765374400 -39600 0 NST} {-757342800 -39600 0 NST} {-86878800 -39600 0 BST} {-31496400 -39600 0 BST} {-21466800 -36000 1 BDT} {-5745600 -39600 0 BST} {9982800 -36000 1 BDT} {25704000 -39600 0 BST} {41432400 -36000 1 BDT} {57758400 -39600 0 BST} {73486800 -36000 1 BDT} {89208000 -39600 0 BST} {104936400 -36000 1 BDT} {120657600 -39600 0 BST} {126709200 -36000 1 BDT} {152107200 -39600 0 BST} {162392400 -36000 1 BDT} {183556800 -39600 0 BST} {199285200 -36000 1 BDT} {215611200 -39600 0 BST} {230734800 -36000 1 BDT} {247060800 -39600 0 BST} {262789200 -36000 1 BDT} {278510400 -39600 0 BST} {294238800 -36000 1 BDT} {309960000 -39600 0 BST} {325688400 -36000 1 BDT} {341409600 -39600 0 BST} {357138000 -36000 1 BDT} {372859200 -39600 0 BST} {388587600 -36000 1 BDT} {404913600 -39600 0 BST} {420037200 -36000 1 BDT} {439030800 -32400 0 AKST} {452084400 -28800 1 AKDT} {467805600 -32400 0 AKST} {483534000 -28800 1 AKDT} {499255200 -32400 0 AKST} {514983600 -28800 1 AKDT} {530704800 -32400 0 AKST} {544618800 -28800 1 AKDT} {562154400 -32400 0 AKST} {576068400 -28800 1 AKDT} {594208800 -32400 0 AKST} {607518000 -28800 1 AKDT} {625658400 -32400 0 AKST} {638967600 -28800 1 AKDT} {657108000 -32400 0 AKST} {671022000 -28800 1 AKDT} {688557600 -32400 0 AKST} {702471600 -28800 1 AKDT} {720007200 -32400 0 AKST} {733921200 -28800 1 AKDT} {752061600 -32400 0 AKST} {765370800 -28800 1 AKDT} {783511200 -32400 0 AKST} {796820400 -28800 1 AKDT} {814960800 -32400 0 AKST} {828874800 -28800 1 AKDT} {846410400 -32400 0 AKST} {860324400 -28800 1 AKDT} {877860000 -32400 0 AKST} {891774000 -28800 1 AKDT} {909309600 -32400 0 AKST} {923223600 -28800 1 AKDT} {941364000 -32400 0 AKST} {954673200 -28800 1 AKDT} {972813600 -32400 0 AKST} {986122800 -28800 1 AKDT} {1004263200 -32400 0 AKST} {1018177200 -28800 1 AKDT} {1035712800 -32400 0 AKST} {1049626800 -28800 1 AKDT} {1067162400 -32400 0 AKST} {1081076400 -28800 1 AKDT} {1099216800 -32400 0 AKST} {1112526000 -28800 1 AKDT} {1130666400 -32400 0 AKST} {1143975600 -28800 1 AKDT} {1162116000 -32400 0 AKST} {1173610800 -28800 1 AKDT} {1194170400 -32400 0 AKST} {1205060400 -28800 1 AKDT} {1225620000 -32400 0 AKST} {1236510000 -28800 1 AKDT} {1257069600 -32400 0 AKST} {1268564400 -28800 1 AKDT} {1289124000 -32400 0 AKST} {1300014000 -28800 1 AKDT} {1320573600 -32400 0 AKST} {1331463600 -28800 1 AKDT} {1352023200 -32400 0 AKST} {1362913200 -28800 1 AKDT} {1383472800 -32400 0 AKST} {1394362800 -28800 1 AKDT} {1414922400 -32400 0 AKST} {1425812400 -28800 1 AKDT} {1446372000 -32400 0 AKST} {1457866800 -28800 1 AKDT} {1478426400 -32400 0 AKST} {1489316400 -28800 1 AKDT} {1509876000 -32400 0 AKST} {1520766000 -28800 1 AKDT} {1541325600 -32400 0 AKST} {1552215600 -28800 1 AKDT} {1572775200 -32400 0 AKST} {1583665200 -28800 1 AKDT} {1604224800 -32400 0 AKST} {1615719600 -28800 1 AKDT} {1636279200 -32400 0 AKST} {1647169200 -28800 1 AKDT} {1667728800 -32400 0 AKST} {1678618800 -28800 1 AKDT} {1699178400 -32400 0 AKST} {1710068400 -28800 1 AKDT} {1730628000 -32400 0 AKST} {1741518000 -28800 1 AKDT} {1762077600 -32400 0 AKST} {1772967600 -28800 1 AKDT} {1793527200 -32400 0 AKST} {1805022000 -28800 1 AKDT} {1825581600 -32400 0 AKST} {1836471600 -28800 1 AKDT} {1857031200 -32400 0 AKST} {1867921200 -28800 1 AKDT} {1888480800 -32400 0 AKST} {1899370800 -28800 1 AKDT} {1919930400 -32400 0 AKST} {1930820400 -28800 1 AKDT} {1951380000 -32400 0 AKST} {1962874800 -28800 1 AKDT} {1983434400 -32400 0 AKST} {1994324400 -28800 1 AKDT} {2014884000 -32400 0 AKST} {2025774000 -28800 1 AKDT} {2046333600 -32400 0 AKST} {2057223600 -28800 1 AKDT} {2077783200 -32400 0 AKST} {2088673200 -28800 1 AKDT} {2109232800 -32400 0 AKST} {2120122800 -28800 1 AKDT} {2140682400 -32400 0 AKST} {2152177200 -28800 1 AKDT} {2172736800 -32400 0 AKST} {2183626800 -28800 1 AKDT} {2204186400 -32400 0 AKST} {2215076400 -28800 1 AKDT} {2235636000 -32400 0 AKST} {2246526000 -28800 1 AKDT} {2267085600 -32400 0 AKST} {2277975600 -28800 1 AKDT} {2298535200 -32400 0 AKST} {2309425200 -28800 1 AKDT} {2329984800 -32400 0 AKST} {2341479600 -28800 1 AKDT} {2362039200 -32400 0 AKST} {2372929200 -28800 1 AKDT} {2393488800 -32400 0 AKST} {2404378800 -28800 1 AKDT} {2424938400 -32400 0 AKST} {2435828400 -28800 1 AKDT} {2456388000 -32400 0 AKST} {2467278000 -28800 1 AKDT} {2487837600 -32400 0 AKST} {2499332400 -28800 1 AKDT} {2519892000 -32400 0 AKST} {2530782000 -28800 1 AKDT} {2551341600 -32400 0 AKST} {2562231600 -28800 1 AKDT} {2582791200 -32400 0 AKST} {2593681200 -28800 1 AKDT} {2614240800 -32400 0 AKST} {2625130800 -28800 1 AKDT} {2645690400 -32400 0 AKST} {2656580400 -28800 1 AKDT} {2677140000 -32400 0 AKST} {2688634800 -28800 1 AKDT} {2709194400 -32400 0 AKST} {2720084400 -28800 1 AKDT} {2740644000 -32400 0 AKST} {2751534000 -28800 1 AKDT} {2772093600 -32400 0 AKST} {2782983600 -28800 1 AKDT} {2803543200 -32400 0 AKST} {2814433200 -28800 1 AKDT} {2834992800 -32400 0 AKST} {2846487600 -28800 1 AKDT} {2867047200 -32400 0 AKST} {2877937200 -28800 1 AKDT} {2898496800 -32400 0 AKST} {2909386800 -28800 1 AKDT} {2929946400 -32400 0 AKST} {2940836400 -28800 1 AKDT} {2961396000 -32400 0 AKST} {2972286000 -28800 1 AKDT} {2992845600 -32400 0 AKST} {3003735600 -28800 1 AKDT} {3024295200 -32400 0 AKST} {3035790000 -28800 1 AKDT} {3056349600 -32400 0 AKST} {3067239600 -28800 1 AKDT} {3087799200 -32400 0 AKST} {3098689200 -28800 1 AKDT} {3119248800 -32400 0 AKST} {3130138800 -28800 1 AKDT} {3150698400 -32400 0 AKST} {3161588400 -28800 1 AKDT} {3182148000 -32400 0 AKST} {3193038000 -28800 1 AKDT} {3213597600 -32400 0 AKST} {3225092400 -28800 1 AKDT} {3245652000 -32400 0 AKST} {3256542000 -28800 1 AKDT} {3277101600 -32400 0 AKST} {3287991600 -28800 1 AKDT} {3308551200 -32400 0 AKST} {3319441200 -28800 1 AKDT} {3340000800 -32400 0 AKST} {3350890800 -28800 1 AKDT} {3371450400 -32400 0 AKST} {3382945200 -28800 1 AKDT} {3403504800 -32400 0 AKST} {3414394800 -28800 1 AKDT} {3434954400 -32400 0 AKST} {3445844400 -28800 1 AKDT} {3466404000 -32400 0 AKST} {3477294000 -28800 1 AKDT} {3497853600 -32400 0 AKST} {3508743600 -28800 1 AKDT} {3529303200 -32400 0 AKST} {3540193200 -28800 1 AKDT} {3560752800 -32400 0 AKST} {3572247600 -28800 1 AKDT} {3592807200 -32400 0 AKST} {3603697200 -28800 1 AKDT} {3624256800 -32400 0 AKST} {3635146800 -28800 1 AKDT} {3655706400 -32400 0 AKST} {3666596400 -28800 1 AKDT} {3687156000 -32400 0 AKST} {3698046000 -28800 1 AKDT} {3718605600 -32400 0 AKST} {3730100400 -28800 1 AKDT} {3750660000 -32400 0 AKST} {3761550000 -28800 1 AKDT} {3782109600 -32400 0 AKST} {3792999600 -28800 1 AKDT} {3813559200 -32400 0 AKST} {3824449200 -28800 1 AKDT} {3845008800 -32400 0 AKST} {3855898800 -28800 1 AKDT} {3876458400 -32400 0 AKST} {3887348400 -28800 1 AKDT} {3907908000 -32400 0 AKST} {3919402800 -28800 1 AKDT} {3939962400 -32400 0 AKST} {3950852400 -28800 1 AKDT} {3971412000 -32400 0 AKST} {3982302000 -28800 1 AKDT} {4002861600 -32400 0 AKST} {4013751600 -28800 1 AKDT} {4034311200 -32400 0 AKST} {4045201200 -28800 1 AKDT} {4065760800 -32400 0 AKST} {4076650800 -28800 1 AKDT} {4097210400 -32400 0 AKST} } tcl8.6.5/library/tzdata/America/Caracas0000644000175000017500000000036012661614720017335 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Caracas) { {-9223372036854775808 -16064 0 LMT} {-2524505536 -16060 0 CMT} {-1826739140 -16200 0 VET} {-157750200 -14400 0 VET} {1197183600 -16200 0 VET} } tcl8.6.5/library/tzdata/America/Yakutat0000644000175000017500000002032712661614721017430 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Yakutat) { {-9223372036854775808 52865 0 LMT} {-3225364865 -33535 0 LMT} {-2188953665 -32400 0 YST} {-883580400 -32400 0 YST} {-880203600 -28800 1 YWT} {-769395600 -28800 1 YPT} {-765381600 -32400 0 YST} {-757350000 -32400 0 YST} {-31503600 -32400 0 YST} {-21474000 -28800 1 YDT} {-5752800 -32400 0 YST} {9975600 -28800 1 YDT} {25696800 -32400 0 YST} {41425200 -28800 1 YDT} {57751200 -32400 0 YST} {73479600 -28800 1 YDT} {89200800 -32400 0 YST} {104929200 -28800 1 YDT} {120650400 -32400 0 YST} {126702000 -28800 1 YDT} {152100000 -32400 0 YST} {162385200 -28800 1 YDT} {183549600 -32400 0 YST} {199278000 -28800 1 YDT} {215604000 -32400 0 YST} {230727600 -28800 1 YDT} {247053600 -32400 0 YST} {262782000 -28800 1 YDT} {278503200 -32400 0 YST} {294231600 -28800 1 YDT} {309952800 -32400 0 YST} {325681200 -28800 1 YDT} {341402400 -32400 0 YST} {357130800 -28800 1 YDT} {372852000 -32400 0 YST} {388580400 -28800 1 YDT} {404906400 -32400 0 YST} {420030000 -28800 1 YDT} {436356000 -32400 0 YST} {439030800 -32400 0 AKST} {452084400 -28800 1 AKDT} {467805600 -32400 0 AKST} {483534000 -28800 1 AKDT} {499255200 -32400 0 AKST} {514983600 -28800 1 AKDT} {530704800 -32400 0 AKST} {544618800 -28800 1 AKDT} {562154400 -32400 0 AKST} {576068400 -28800 1 AKDT} {594208800 -32400 0 AKST} {607518000 -28800 1 AKDT} {625658400 -32400 0 AKST} {638967600 -28800 1 AKDT} {657108000 -32400 0 AKST} {671022000 -28800 1 AKDT} {688557600 -32400 0 AKST} {702471600 -28800 1 AKDT} {720007200 -32400 0 AKST} {733921200 -28800 1 AKDT} {752061600 -32400 0 AKST} {765370800 -28800 1 AKDT} {783511200 -32400 0 AKST} {796820400 -28800 1 AKDT} {814960800 -32400 0 AKST} {828874800 -28800 1 AKDT} {846410400 -32400 0 AKST} {860324400 -28800 1 AKDT} {877860000 -32400 0 AKST} {891774000 -28800 1 AKDT} {909309600 -32400 0 AKST} {923223600 -28800 1 AKDT} {941364000 -32400 0 AKST} {954673200 -28800 1 AKDT} {972813600 -32400 0 AKST} {986122800 -28800 1 AKDT} {1004263200 -32400 0 AKST} {1018177200 -28800 1 AKDT} {1035712800 -32400 0 AKST} {1049626800 -28800 1 AKDT} {1067162400 -32400 0 AKST} {1081076400 -28800 1 AKDT} {1099216800 -32400 0 AKST} {1112526000 -28800 1 AKDT} {1130666400 -32400 0 AKST} {1143975600 -28800 1 AKDT} {1162116000 -32400 0 AKST} {1173610800 -28800 1 AKDT} {1194170400 -32400 0 AKST} {1205060400 -28800 1 AKDT} {1225620000 -32400 0 AKST} {1236510000 -28800 1 AKDT} {1257069600 -32400 0 AKST} {1268564400 -28800 1 AKDT} {1289124000 -32400 0 AKST} {1300014000 -28800 1 AKDT} {1320573600 -32400 0 AKST} {1331463600 -28800 1 AKDT} {1352023200 -32400 0 AKST} {1362913200 -28800 1 AKDT} {1383472800 -32400 0 AKST} {1394362800 -28800 1 AKDT} {1414922400 -32400 0 AKST} {1425812400 -28800 1 AKDT} {1446372000 -32400 0 AKST} {1457866800 -28800 1 AKDT} {1478426400 -32400 0 AKST} {1489316400 -28800 1 AKDT} {1509876000 -32400 0 AKST} {1520766000 -28800 1 AKDT} {1541325600 -32400 0 AKST} {1552215600 -28800 1 AKDT} {1572775200 -32400 0 AKST} {1583665200 -28800 1 AKDT} {1604224800 -32400 0 AKST} {1615719600 -28800 1 AKDT} {1636279200 -32400 0 AKST} {1647169200 -28800 1 AKDT} {1667728800 -32400 0 AKST} {1678618800 -28800 1 AKDT} {1699178400 -32400 0 AKST} {1710068400 -28800 1 AKDT} {1730628000 -32400 0 AKST} {1741518000 -28800 1 AKDT} {1762077600 -32400 0 AKST} {1772967600 -28800 1 AKDT} {1793527200 -32400 0 AKST} {1805022000 -28800 1 AKDT} {1825581600 -32400 0 AKST} {1836471600 -28800 1 AKDT} {1857031200 -32400 0 AKST} {1867921200 -28800 1 AKDT} {1888480800 -32400 0 AKST} {1899370800 -28800 1 AKDT} {1919930400 -32400 0 AKST} {1930820400 -28800 1 AKDT} {1951380000 -32400 0 AKST} {1962874800 -28800 1 AKDT} {1983434400 -32400 0 AKST} {1994324400 -28800 1 AKDT} {2014884000 -32400 0 AKST} {2025774000 -28800 1 AKDT} {2046333600 -32400 0 AKST} {2057223600 -28800 1 AKDT} {2077783200 -32400 0 AKST} {2088673200 -28800 1 AKDT} {2109232800 -32400 0 AKST} {2120122800 -28800 1 AKDT} {2140682400 -32400 0 AKST} {2152177200 -28800 1 AKDT} {2172736800 -32400 0 AKST} {2183626800 -28800 1 AKDT} {2204186400 -32400 0 AKST} {2215076400 -28800 1 AKDT} {2235636000 -32400 0 AKST} {2246526000 -28800 1 AKDT} {2267085600 -32400 0 AKST} {2277975600 -28800 1 AKDT} {2298535200 -32400 0 AKST} {2309425200 -28800 1 AKDT} {2329984800 -32400 0 AKST} {2341479600 -28800 1 AKDT} {2362039200 -32400 0 AKST} {2372929200 -28800 1 AKDT} {2393488800 -32400 0 AKST} {2404378800 -28800 1 AKDT} {2424938400 -32400 0 AKST} {2435828400 -28800 1 AKDT} {2456388000 -32400 0 AKST} {2467278000 -28800 1 AKDT} {2487837600 -32400 0 AKST} {2499332400 -28800 1 AKDT} {2519892000 -32400 0 AKST} {2530782000 -28800 1 AKDT} {2551341600 -32400 0 AKST} {2562231600 -28800 1 AKDT} {2582791200 -32400 0 AKST} {2593681200 -28800 1 AKDT} {2614240800 -32400 0 AKST} {2625130800 -28800 1 AKDT} {2645690400 -32400 0 AKST} {2656580400 -28800 1 AKDT} {2677140000 -32400 0 AKST} {2688634800 -28800 1 AKDT} {2709194400 -32400 0 AKST} {2720084400 -28800 1 AKDT} {2740644000 -32400 0 AKST} {2751534000 -28800 1 AKDT} {2772093600 -32400 0 AKST} {2782983600 -28800 1 AKDT} {2803543200 -32400 0 AKST} {2814433200 -28800 1 AKDT} {2834992800 -32400 0 AKST} {2846487600 -28800 1 AKDT} {2867047200 -32400 0 AKST} {2877937200 -28800 1 AKDT} {2898496800 -32400 0 AKST} {2909386800 -28800 1 AKDT} {2929946400 -32400 0 AKST} {2940836400 -28800 1 AKDT} {2961396000 -32400 0 AKST} {2972286000 -28800 1 AKDT} {2992845600 -32400 0 AKST} {3003735600 -28800 1 AKDT} {3024295200 -32400 0 AKST} {3035790000 -28800 1 AKDT} {3056349600 -32400 0 AKST} {3067239600 -28800 1 AKDT} {3087799200 -32400 0 AKST} {3098689200 -28800 1 AKDT} {3119248800 -32400 0 AKST} {3130138800 -28800 1 AKDT} {3150698400 -32400 0 AKST} {3161588400 -28800 1 AKDT} {3182148000 -32400 0 AKST} {3193038000 -28800 1 AKDT} {3213597600 -32400 0 AKST} {3225092400 -28800 1 AKDT} {3245652000 -32400 0 AKST} {3256542000 -28800 1 AKDT} {3277101600 -32400 0 AKST} {3287991600 -28800 1 AKDT} {3308551200 -32400 0 AKST} {3319441200 -28800 1 AKDT} {3340000800 -32400 0 AKST} {3350890800 -28800 1 AKDT} {3371450400 -32400 0 AKST} {3382945200 -28800 1 AKDT} {3403504800 -32400 0 AKST} {3414394800 -28800 1 AKDT} {3434954400 -32400 0 AKST} {3445844400 -28800 1 AKDT} {3466404000 -32400 0 AKST} {3477294000 -28800 1 AKDT} {3497853600 -32400 0 AKST} {3508743600 -28800 1 AKDT} {3529303200 -32400 0 AKST} {3540193200 -28800 1 AKDT} {3560752800 -32400 0 AKST} {3572247600 -28800 1 AKDT} {3592807200 -32400 0 AKST} {3603697200 -28800 1 AKDT} {3624256800 -32400 0 AKST} {3635146800 -28800 1 AKDT} {3655706400 -32400 0 AKST} {3666596400 -28800 1 AKDT} {3687156000 -32400 0 AKST} {3698046000 -28800 1 AKDT} {3718605600 -32400 0 AKST} {3730100400 -28800 1 AKDT} {3750660000 -32400 0 AKST} {3761550000 -28800 1 AKDT} {3782109600 -32400 0 AKST} {3792999600 -28800 1 AKDT} {3813559200 -32400 0 AKST} {3824449200 -28800 1 AKDT} {3845008800 -32400 0 AKST} {3855898800 -28800 1 AKDT} {3876458400 -32400 0 AKST} {3887348400 -28800 1 AKDT} {3907908000 -32400 0 AKST} {3919402800 -28800 1 AKDT} {3939962400 -32400 0 AKST} {3950852400 -28800 1 AKDT} {3971412000 -32400 0 AKST} {3982302000 -28800 1 AKDT} {4002861600 -32400 0 AKST} {4013751600 -28800 1 AKDT} {4034311200 -32400 0 AKST} {4045201200 -28800 1 AKDT} {4065760800 -32400 0 AKST} {4076650800 -28800 1 AKDT} {4097210400 -32400 0 AKST} } tcl8.6.5/library/tzdata/America/Mazatlan0000644000175000017500000001473312661614721017561 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Mazatlan) { {-9223372036854775808 -25540 0 LMT} {-1514739600 -25200 0 MST} {-1343066400 -21600 0 CST} {-1234807200 -25200 0 MST} {-1220292000 -21600 0 CST} {-1207159200 -25200 0 MST} {-1191344400 -21600 0 CST} {-873828000 -25200 0 MST} {-661539600 -28800 0 PST} {28800 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {989139600 -21600 1 MDT} {1001836800 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1175418000 -21600 1 MDT} {1193558400 -25200 0 MST} {1207472400 -21600 1 MDT} {1225008000 -25200 0 MST} {1238922000 -21600 1 MDT} {1256457600 -25200 0 MST} {1270371600 -21600 1 MDT} {1288512000 -25200 0 MST} {1301821200 -21600 1 MDT} {1319961600 -25200 0 MST} {1333270800 -21600 1 MDT} {1351411200 -25200 0 MST} {1365325200 -21600 1 MDT} {1382860800 -25200 0 MST} {1396774800 -21600 1 MDT} {1414310400 -25200 0 MST} {1428224400 -21600 1 MDT} {1445760000 -25200 0 MST} {1459674000 -21600 1 MDT} {1477814400 -25200 0 MST} {1491123600 -21600 1 MDT} {1509264000 -25200 0 MST} {1522573200 -21600 1 MDT} {1540713600 -25200 0 MST} {1554627600 -21600 1 MDT} {1572163200 -25200 0 MST} {1586077200 -21600 1 MDT} {1603612800 -25200 0 MST} {1617526800 -21600 1 MDT} {1635667200 -25200 0 MST} {1648976400 -21600 1 MDT} {1667116800 -25200 0 MST} {1680426000 -21600 1 MDT} {1698566400 -25200 0 MST} {1712480400 -21600 1 MDT} {1730016000 -25200 0 MST} {1743930000 -21600 1 MDT} {1761465600 -25200 0 MST} {1775379600 -21600 1 MDT} {1792915200 -25200 0 MST} {1806829200 -21600 1 MDT} {1824969600 -25200 0 MST} {1838278800 -21600 1 MDT} {1856419200 -25200 0 MST} {1869728400 -21600 1 MDT} {1887868800 -25200 0 MST} {1901782800 -21600 1 MDT} {1919318400 -25200 0 MST} {1933232400 -21600 1 MDT} {1950768000 -25200 0 MST} {1964682000 -21600 1 MDT} {1982822400 -25200 0 MST} {1996131600 -21600 1 MDT} {2014272000 -25200 0 MST} {2027581200 -21600 1 MDT} {2045721600 -25200 0 MST} {2059030800 -21600 1 MDT} {2077171200 -25200 0 MST} {2091085200 -21600 1 MDT} {2108620800 -25200 0 MST} {2122534800 -21600 1 MDT} {2140070400 -25200 0 MST} {2153984400 -21600 1 MDT} {2172124800 -25200 0 MST} {2185434000 -21600 1 MDT} {2203574400 -25200 0 MST} {2216883600 -21600 1 MDT} {2235024000 -25200 0 MST} {2248938000 -21600 1 MDT} {2266473600 -25200 0 MST} {2280387600 -21600 1 MDT} {2297923200 -25200 0 MST} {2311837200 -21600 1 MDT} {2329372800 -25200 0 MST} {2343286800 -21600 1 MDT} {2361427200 -25200 0 MST} {2374736400 -21600 1 MDT} {2392876800 -25200 0 MST} {2406186000 -21600 1 MDT} {2424326400 -25200 0 MST} {2438240400 -21600 1 MDT} {2455776000 -25200 0 MST} {2469690000 -21600 1 MDT} {2487225600 -25200 0 MST} {2501139600 -21600 1 MDT} {2519280000 -25200 0 MST} {2532589200 -21600 1 MDT} {2550729600 -25200 0 MST} {2564038800 -21600 1 MDT} {2582179200 -25200 0 MST} {2596093200 -21600 1 MDT} {2613628800 -25200 0 MST} {2627542800 -21600 1 MDT} {2645078400 -25200 0 MST} {2658992400 -21600 1 MDT} {2676528000 -25200 0 MST} {2690442000 -21600 1 MDT} {2708582400 -25200 0 MST} {2721891600 -21600 1 MDT} {2740032000 -25200 0 MST} {2753341200 -21600 1 MDT} {2771481600 -25200 0 MST} {2785395600 -21600 1 MDT} {2802931200 -25200 0 MST} {2816845200 -21600 1 MDT} {2834380800 -25200 0 MST} {2848294800 -21600 1 MDT} {2866435200 -25200 0 MST} {2879744400 -21600 1 MDT} {2897884800 -25200 0 MST} {2911194000 -21600 1 MDT} {2929334400 -25200 0 MST} {2942643600 -21600 1 MDT} {2960784000 -25200 0 MST} {2974698000 -21600 1 MDT} {2992233600 -25200 0 MST} {3006147600 -21600 1 MDT} {3023683200 -25200 0 MST} {3037597200 -21600 1 MDT} {3055737600 -25200 0 MST} {3069046800 -21600 1 MDT} {3087187200 -25200 0 MST} {3100496400 -21600 1 MDT} {3118636800 -25200 0 MST} {3132550800 -21600 1 MDT} {3150086400 -25200 0 MST} {3164000400 -21600 1 MDT} {3181536000 -25200 0 MST} {3195450000 -21600 1 MDT} {3212985600 -25200 0 MST} {3226899600 -21600 1 MDT} {3245040000 -25200 0 MST} {3258349200 -21600 1 MDT} {3276489600 -25200 0 MST} {3289798800 -21600 1 MDT} {3307939200 -25200 0 MST} {3321853200 -21600 1 MDT} {3339388800 -25200 0 MST} {3353302800 -21600 1 MDT} {3370838400 -25200 0 MST} {3384752400 -21600 1 MDT} {3402892800 -25200 0 MST} {3416202000 -21600 1 MDT} {3434342400 -25200 0 MST} {3447651600 -21600 1 MDT} {3465792000 -25200 0 MST} {3479706000 -21600 1 MDT} {3497241600 -25200 0 MST} {3511155600 -21600 1 MDT} {3528691200 -25200 0 MST} {3542605200 -21600 1 MDT} {3560140800 -25200 0 MST} {3574054800 -21600 1 MDT} {3592195200 -25200 0 MST} {3605504400 -21600 1 MDT} {3623644800 -25200 0 MST} {3636954000 -21600 1 MDT} {3655094400 -25200 0 MST} {3669008400 -21600 1 MDT} {3686544000 -25200 0 MST} {3700458000 -21600 1 MDT} {3717993600 -25200 0 MST} {3731907600 -21600 1 MDT} {3750048000 -25200 0 MST} {3763357200 -21600 1 MDT} {3781497600 -25200 0 MST} {3794806800 -21600 1 MDT} {3812947200 -25200 0 MST} {3826256400 -21600 1 MDT} {3844396800 -25200 0 MST} {3858310800 -21600 1 MDT} {3875846400 -25200 0 MST} {3889760400 -21600 1 MDT} {3907296000 -25200 0 MST} {3921210000 -21600 1 MDT} {3939350400 -25200 0 MST} {3952659600 -21600 1 MDT} {3970800000 -25200 0 MST} {3984109200 -21600 1 MDT} {4002249600 -25200 0 MST} {4016163600 -21600 1 MDT} {4033699200 -25200 0 MST} {4047613200 -21600 1 MDT} {4065148800 -25200 0 MST} {4079062800 -21600 1 MDT} {4096598400 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Montserrat0000644000175000017500000000031512663660066020144 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/Montserrat) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Havana0000644000175000017500000002037412663660066017213 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Havana) { {-9223372036854775808 -19768 0 LMT} {-2524501832 -19776 0 HMT} {-1402813824 -18000 0 CST} {-1311534000 -14400 1 CDT} {-1300996800 -18000 0 CST} {-933534000 -14400 1 CDT} {-925675200 -18000 0 CST} {-902084400 -14400 1 CDT} {-893620800 -18000 0 CST} {-870030000 -14400 1 CDT} {-862171200 -18000 0 CST} {-775681200 -14400 1 CDT} {-767822400 -18000 0 CST} {-744231600 -14400 1 CDT} {-736372800 -18000 0 CST} {-144702000 -14400 1 CDT} {-134251200 -18000 0 CST} {-113425200 -14400 1 CDT} {-102542400 -18000 0 CST} {-86295600 -14400 1 CDT} {-72907200 -18000 0 CST} {-54154800 -14400 1 CDT} {-41457600 -18000 0 CST} {-21495600 -14400 1 CDT} {-5774400 -18000 0 CST} {9954000 -14400 1 CDT} {25675200 -18000 0 CST} {41403600 -14400 1 CDT} {57729600 -18000 0 CST} {73458000 -14400 1 CDT} {87364800 -18000 0 CST} {104907600 -14400 1 CDT} {118900800 -18000 0 CST} {136357200 -14400 1 CDT} {150436800 -18000 0 CST} {167806800 -14400 1 CDT} {183528000 -18000 0 CST} {199256400 -14400 1 CDT} {215582400 -18000 0 CST} {230706000 -14400 1 CDT} {247032000 -18000 0 CST} {263365200 -14400 1 CDT} {276667200 -18000 0 CST} {290581200 -14400 1 CDT} {308721600 -18000 0 CST} {322030800 -14400 1 CDT} {340171200 -18000 0 CST} {358318800 -14400 1 CDT} {371620800 -18000 0 CST} {389768400 -14400 1 CDT} {403070400 -18000 0 CST} {421218000 -14400 1 CDT} {434520000 -18000 0 CST} {452667600 -14400 1 CDT} {466574400 -18000 0 CST} {484117200 -14400 1 CDT} {498024000 -18000 0 CST} {511333200 -14400 1 CDT} {529473600 -18000 0 CST} {542782800 -14400 1 CDT} {560923200 -18000 0 CST} {574837200 -14400 1 CDT} {592372800 -18000 0 CST} {606286800 -14400 1 CDT} {623822400 -18000 0 CST} {638946000 -14400 1 CDT} {655876800 -18000 0 CST} {671000400 -14400 1 CDT} {687330000 -18000 0 CST} {702450000 -14400 1 CDT} {718779600 -18000 0 CST} {733899600 -14400 1 CDT} {750229200 -18000 0 CST} {765349200 -14400 1 CDT} {781678800 -18000 0 CST} {796798800 -14400 1 CDT} {813128400 -18000 0 CST} {828853200 -14400 1 CDT} {844578000 -18000 0 CST} {860302800 -14400 1 CDT} {876632400 -18000 0 CST} {891147600 -14400 1 CDT} {909291600 -18000 0 CST} {922597200 -14400 1 CDT} {941346000 -18000 0 CST} {954651600 -14400 1 CDT} {972795600 -18000 0 CST} {986101200 -14400 1 CDT} {1004245200 -18000 0 CST} {1018155600 -14400 1 CDT} {1035694800 -18000 0 CST} {1049605200 -14400 1 CDT} {1067144400 -18000 0 CST} {1080450000 -14400 1 CDT} {1162098000 -18000 0 CST} {1173589200 -14400 1 CDT} {1193547600 -18000 0 CST} {1205643600 -14400 1 CDT} {1224997200 -18000 0 CST} {1236488400 -14400 1 CDT} {1256446800 -18000 0 CST} {1268542800 -14400 1 CDT} {1288501200 -18000 0 CST} {1300597200 -14400 1 CDT} {1321160400 -18000 0 CST} {1333256400 -14400 1 CDT} {1352005200 -18000 0 CST} {1362891600 -14400 1 CDT} {1383454800 -18000 0 CST} {1394341200 -14400 1 CDT} {1414904400 -18000 0 CST} {1425790800 -14400 1 CDT} {1446354000 -18000 0 CST} {1457845200 -14400 1 CDT} {1478408400 -18000 0 CST} {1489294800 -14400 1 CDT} {1509858000 -18000 0 CST} {1520744400 -14400 1 CDT} {1541307600 -18000 0 CST} {1552194000 -14400 1 CDT} {1572757200 -18000 0 CST} {1583643600 -14400 1 CDT} {1604206800 -18000 0 CST} {1615698000 -14400 1 CDT} {1636261200 -18000 0 CST} {1647147600 -14400 1 CDT} {1667710800 -18000 0 CST} {1678597200 -14400 1 CDT} {1699160400 -18000 0 CST} {1710046800 -14400 1 CDT} {1730610000 -18000 0 CST} {1741496400 -14400 1 CDT} {1762059600 -18000 0 CST} {1772946000 -14400 1 CDT} {1793509200 -18000 0 CST} {1805000400 -14400 1 CDT} {1825563600 -18000 0 CST} {1836450000 -14400 1 CDT} {1857013200 -18000 0 CST} {1867899600 -14400 1 CDT} {1888462800 -18000 0 CST} {1899349200 -14400 1 CDT} {1919912400 -18000 0 CST} {1930798800 -14400 1 CDT} {1951362000 -18000 0 CST} {1962853200 -14400 1 CDT} {1983416400 -18000 0 CST} {1994302800 -14400 1 CDT} {2014866000 -18000 0 CST} {2025752400 -14400 1 CDT} {2046315600 -18000 0 CST} {2057202000 -14400 1 CDT} {2077765200 -18000 0 CST} {2088651600 -14400 1 CDT} {2109214800 -18000 0 CST} {2120101200 -14400 1 CDT} {2140664400 -18000 0 CST} {2152155600 -14400 1 CDT} {2172718800 -18000 0 CST} {2183605200 -14400 1 CDT} {2204168400 -18000 0 CST} {2215054800 -14400 1 CDT} {2235618000 -18000 0 CST} {2246504400 -14400 1 CDT} {2267067600 -18000 0 CST} {2277954000 -14400 1 CDT} {2298517200 -18000 0 CST} {2309403600 -14400 1 CDT} {2329966800 -18000 0 CST} {2341458000 -14400 1 CDT} {2362021200 -18000 0 CST} {2372907600 -14400 1 CDT} {2393470800 -18000 0 CST} {2404357200 -14400 1 CDT} {2424920400 -18000 0 CST} {2435806800 -14400 1 CDT} {2456370000 -18000 0 CST} {2467256400 -14400 1 CDT} {2487819600 -18000 0 CST} {2499310800 -14400 1 CDT} {2519874000 -18000 0 CST} {2530760400 -14400 1 CDT} {2551323600 -18000 0 CST} {2562210000 -14400 1 CDT} {2582773200 -18000 0 CST} {2593659600 -14400 1 CDT} {2614222800 -18000 0 CST} {2625109200 -14400 1 CDT} {2645672400 -18000 0 CST} {2656558800 -14400 1 CDT} {2677122000 -18000 0 CST} {2688613200 -14400 1 CDT} {2709176400 -18000 0 CST} {2720062800 -14400 1 CDT} {2740626000 -18000 0 CST} {2751512400 -14400 1 CDT} {2772075600 -18000 0 CST} {2782962000 -14400 1 CDT} {2803525200 -18000 0 CST} {2814411600 -14400 1 CDT} {2834974800 -18000 0 CST} {2846466000 -14400 1 CDT} {2867029200 -18000 0 CST} {2877915600 -14400 1 CDT} {2898478800 -18000 0 CST} {2909365200 -14400 1 CDT} {2929928400 -18000 0 CST} {2940814800 -14400 1 CDT} {2961378000 -18000 0 CST} {2972264400 -14400 1 CDT} {2992827600 -18000 0 CST} {3003714000 -14400 1 CDT} {3024277200 -18000 0 CST} {3035768400 -14400 1 CDT} {3056331600 -18000 0 CST} {3067218000 -14400 1 CDT} {3087781200 -18000 0 CST} {3098667600 -14400 1 CDT} {3119230800 -18000 0 CST} {3130117200 -14400 1 CDT} {3150680400 -18000 0 CST} {3161566800 -14400 1 CDT} {3182130000 -18000 0 CST} {3193016400 -14400 1 CDT} {3213579600 -18000 0 CST} {3225070800 -14400 1 CDT} {3245634000 -18000 0 CST} {3256520400 -14400 1 CDT} {3277083600 -18000 0 CST} {3287970000 -14400 1 CDT} {3308533200 -18000 0 CST} {3319419600 -14400 1 CDT} {3339982800 -18000 0 CST} {3350869200 -14400 1 CDT} {3371432400 -18000 0 CST} {3382923600 -14400 1 CDT} {3403486800 -18000 0 CST} {3414373200 -14400 1 CDT} {3434936400 -18000 0 CST} {3445822800 -14400 1 CDT} {3466386000 -18000 0 CST} {3477272400 -14400 1 CDT} {3497835600 -18000 0 CST} {3508722000 -14400 1 CDT} {3529285200 -18000 0 CST} {3540171600 -14400 1 CDT} {3560734800 -18000 0 CST} {3572226000 -14400 1 CDT} {3592789200 -18000 0 CST} {3603675600 -14400 1 CDT} {3624238800 -18000 0 CST} {3635125200 -14400 1 CDT} {3655688400 -18000 0 CST} {3666574800 -14400 1 CDT} {3687138000 -18000 0 CST} {3698024400 -14400 1 CDT} {3718587600 -18000 0 CST} {3730078800 -14400 1 CDT} {3750642000 -18000 0 CST} {3761528400 -14400 1 CDT} {3782091600 -18000 0 CST} {3792978000 -14400 1 CDT} {3813541200 -18000 0 CST} {3824427600 -14400 1 CDT} {3844990800 -18000 0 CST} {3855877200 -14400 1 CDT} {3876440400 -18000 0 CST} {3887326800 -14400 1 CDT} {3907890000 -18000 0 CST} {3919381200 -14400 1 CDT} {3939944400 -18000 0 CST} {3950830800 -14400 1 CDT} {3971394000 -18000 0 CST} {3982280400 -14400 1 CDT} {4002843600 -18000 0 CST} {4013730000 -14400 1 CDT} {4034293200 -18000 0 CST} {4045179600 -14400 1 CDT} {4065742800 -18000 0 CST} {4076629200 -14400 1 CDT} {4097192400 -18000 0 CST} } tcl8.6.5/library/tzdata/America/Dominica0000644000175000017500000000031312663660066017527 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/Dominica) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Monterrey0000644000175000017500000001454012661614721017772 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Monterrey) { {-9223372036854775808 -24076 0 LMT} {-1514743200 -21600 0 CST} {568015200 -21600 0 CST} {576057600 -18000 1 CDT} {594198000 -21600 0 CST} {599637600 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972802800 -21600 0 CST} {989136000 -18000 1 CDT} {1001833200 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1175414400 -18000 1 CDT} {1193554800 -21600 0 CST} {1207468800 -18000 1 CDT} {1225004400 -21600 0 CST} {1238918400 -18000 1 CDT} {1256454000 -21600 0 CST} {1270368000 -18000 1 CDT} {1288508400 -21600 0 CST} {1301817600 -18000 1 CDT} {1319958000 -21600 0 CST} {1333267200 -18000 1 CDT} {1351407600 -21600 0 CST} {1365321600 -18000 1 CDT} {1382857200 -21600 0 CST} {1396771200 -18000 1 CDT} {1414306800 -21600 0 CST} {1428220800 -18000 1 CDT} {1445756400 -21600 0 CST} {1459670400 -18000 1 CDT} {1477810800 -21600 0 CST} {1491120000 -18000 1 CDT} {1509260400 -21600 0 CST} {1522569600 -18000 1 CDT} {1540710000 -21600 0 CST} {1554624000 -18000 1 CDT} {1572159600 -21600 0 CST} {1586073600 -18000 1 CDT} {1603609200 -21600 0 CST} {1617523200 -18000 1 CDT} {1635663600 -21600 0 CST} {1648972800 -18000 1 CDT} {1667113200 -21600 0 CST} {1680422400 -18000 1 CDT} {1698562800 -21600 0 CST} {1712476800 -18000 1 CDT} {1730012400 -21600 0 CST} {1743926400 -18000 1 CDT} {1761462000 -21600 0 CST} {1775376000 -18000 1 CDT} {1792911600 -21600 0 CST} {1806825600 -18000 1 CDT} {1824966000 -21600 0 CST} {1838275200 -18000 1 CDT} {1856415600 -21600 0 CST} {1869724800 -18000 1 CDT} {1887865200 -21600 0 CST} {1901779200 -18000 1 CDT} {1919314800 -21600 0 CST} {1933228800 -18000 1 CDT} {1950764400 -21600 0 CST} {1964678400 -18000 1 CDT} {1982818800 -21600 0 CST} {1996128000 -18000 1 CDT} {2014268400 -21600 0 CST} {2027577600 -18000 1 CDT} {2045718000 -21600 0 CST} {2059027200 -18000 1 CDT} {2077167600 -21600 0 CST} {2091081600 -18000 1 CDT} {2108617200 -21600 0 CST} {2122531200 -18000 1 CDT} {2140066800 -21600 0 CST} {2153980800 -18000 1 CDT} {2172121200 -21600 0 CST} {2185430400 -18000 1 CDT} {2203570800 -21600 0 CST} {2216880000 -18000 1 CDT} {2235020400 -21600 0 CST} {2248934400 -18000 1 CDT} {2266470000 -21600 0 CST} {2280384000 -18000 1 CDT} {2297919600 -21600 0 CST} {2311833600 -18000 1 CDT} {2329369200 -21600 0 CST} {2343283200 -18000 1 CDT} {2361423600 -21600 0 CST} {2374732800 -18000 1 CDT} {2392873200 -21600 0 CST} {2406182400 -18000 1 CDT} {2424322800 -21600 0 CST} {2438236800 -18000 1 CDT} {2455772400 -21600 0 CST} {2469686400 -18000 1 CDT} {2487222000 -21600 0 CST} {2501136000 -18000 1 CDT} {2519276400 -21600 0 CST} {2532585600 -18000 1 CDT} {2550726000 -21600 0 CST} {2564035200 -18000 1 CDT} {2582175600 -21600 0 CST} {2596089600 -18000 1 CDT} {2613625200 -21600 0 CST} {2627539200 -18000 1 CDT} {2645074800 -21600 0 CST} {2658988800 -18000 1 CDT} {2676524400 -21600 0 CST} {2690438400 -18000 1 CDT} {2708578800 -21600 0 CST} {2721888000 -18000 1 CDT} {2740028400 -21600 0 CST} {2753337600 -18000 1 CDT} {2771478000 -21600 0 CST} {2785392000 -18000 1 CDT} {2802927600 -21600 0 CST} {2816841600 -18000 1 CDT} {2834377200 -21600 0 CST} {2848291200 -18000 1 CDT} {2866431600 -21600 0 CST} {2879740800 -18000 1 CDT} {2897881200 -21600 0 CST} {2911190400 -18000 1 CDT} {2929330800 -21600 0 CST} {2942640000 -18000 1 CDT} {2960780400 -21600 0 CST} {2974694400 -18000 1 CDT} {2992230000 -21600 0 CST} {3006144000 -18000 1 CDT} {3023679600 -21600 0 CST} {3037593600 -18000 1 CDT} {3055734000 -21600 0 CST} {3069043200 -18000 1 CDT} {3087183600 -21600 0 CST} {3100492800 -18000 1 CDT} {3118633200 -21600 0 CST} {3132547200 -18000 1 CDT} {3150082800 -21600 0 CST} {3163996800 -18000 1 CDT} {3181532400 -21600 0 CST} {3195446400 -18000 1 CDT} {3212982000 -21600 0 CST} {3226896000 -18000 1 CDT} {3245036400 -21600 0 CST} {3258345600 -18000 1 CDT} {3276486000 -21600 0 CST} {3289795200 -18000 1 CDT} {3307935600 -21600 0 CST} {3321849600 -18000 1 CDT} {3339385200 -21600 0 CST} {3353299200 -18000 1 CDT} {3370834800 -21600 0 CST} {3384748800 -18000 1 CDT} {3402889200 -21600 0 CST} {3416198400 -18000 1 CDT} {3434338800 -21600 0 CST} {3447648000 -18000 1 CDT} {3465788400 -21600 0 CST} {3479702400 -18000 1 CDT} {3497238000 -21600 0 CST} {3511152000 -18000 1 CDT} {3528687600 -21600 0 CST} {3542601600 -18000 1 CDT} {3560137200 -21600 0 CST} {3574051200 -18000 1 CDT} {3592191600 -21600 0 CST} {3605500800 -18000 1 CDT} {3623641200 -21600 0 CST} {3636950400 -18000 1 CDT} {3655090800 -21600 0 CST} {3669004800 -18000 1 CDT} {3686540400 -21600 0 CST} {3700454400 -18000 1 CDT} {3717990000 -21600 0 CST} {3731904000 -18000 1 CDT} {3750044400 -21600 0 CST} {3763353600 -18000 1 CDT} {3781494000 -21600 0 CST} {3794803200 -18000 1 CDT} {3812943600 -21600 0 CST} {3826252800 -18000 1 CDT} {3844393200 -21600 0 CST} {3858307200 -18000 1 CDT} {3875842800 -21600 0 CST} {3889756800 -18000 1 CDT} {3907292400 -21600 0 CST} {3921206400 -18000 1 CDT} {3939346800 -21600 0 CST} {3952656000 -18000 1 CDT} {3970796400 -21600 0 CST} {3984105600 -18000 1 CDT} {4002246000 -21600 0 CST} {4016160000 -18000 1 CDT} {4033695600 -21600 0 CST} {4047609600 -18000 1 CDT} {4065145200 -21600 0 CST} {4079059200 -18000 1 CDT} {4096594800 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Porto_Acre0000644000175000017500000000030412661614722020035 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Rio_Branco)]} { LoadTimeZoneFile America/Rio_Branco } set TZData(:America/Porto_Acre) $TZData(:America/Rio_Branco) tcl8.6.5/library/tzdata/America/Managua0000644000175000017500000000111612661614721017352 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Managua) { {-9223372036854775808 -20708 0 LMT} {-2524500892 -20712 0 MMT} {-1121105688 -21600 0 CST} {105084000 -18000 0 EST} {161758800 -21600 0 CST} {290584800 -18000 1 CDT} {299134800 -21600 0 CST} {322034400 -18000 1 CDT} {330584400 -21600 0 CST} {694260000 -18000 0 EST} {717310800 -21600 0 CST} {725868000 -18000 0 EST} {852094800 -21600 0 CST} {1113112800 -18000 1 CDT} {1128229200 -21600 0 CST} {1146384000 -18000 1 CDT} {1159682400 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Bahia0000644000175000017500000000366612663660066017026 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Bahia) { {-9223372036854775808 -9244 0 LMT} {-1767216356 -10800 0 BRT} {-1206957600 -7200 1 BRST} {-1191362400 -10800 0 BRT} {-1175374800 -7200 1 BRST} {-1159826400 -10800 0 BRT} {-633819600 -7200 1 BRST} {-622069200 -10800 0 BRT} {-602283600 -7200 1 BRST} {-591832800 -10800 0 BRT} {-570747600 -7200 1 BRST} {-560210400 -10800 0 BRT} {-539125200 -7200 1 BRST} {-531352800 -10800 0 BRT} {-191365200 -7200 1 BRST} {-184197600 -10800 0 BRT} {-155163600 -7200 1 BRST} {-150069600 -10800 0 BRT} {-128898000 -7200 1 BRST} {-121125600 -10800 0 BRT} {-99954000 -7200 1 BRST} {-89589600 -10800 0 BRT} {-68418000 -7200 1 BRST} {-57967200 -10800 0 BRT} {499748400 -7200 1 BRST} {511236000 -10800 0 BRT} {530593200 -7200 1 BRST} {540266400 -10800 0 BRT} {562129200 -7200 1 BRST} {571197600 -10800 0 BRT} {592974000 -7200 1 BRST} {602042400 -10800 0 BRT} {624423600 -7200 1 BRST} {634701600 -10800 0 BRT} {656478000 -7200 1 BRST} {666756000 -10800 0 BRT} {687927600 -7200 1 BRST} {697600800 -10800 0 BRT} {719982000 -7200 1 BRST} {728445600 -10800 0 BRT} {750826800 -7200 1 BRST} {761709600 -10800 0 BRT} {782276400 -7200 1 BRST} {793159200 -10800 0 BRT} {813726000 -7200 1 BRST} {824004000 -10800 0 BRT} {844570800 -7200 1 BRST} {856058400 -10800 0 BRT} {876106800 -7200 1 BRST} {888717600 -10800 0 BRT} {908074800 -7200 1 BRST} {919562400 -10800 0 BRT} {938919600 -7200 1 BRST} {951616800 -10800 0 BRT} {970974000 -7200 1 BRST} {982461600 -10800 0 BRT} {1003028400 -7200 1 BRST} {1013911200 -10800 0 BRT} {1036292400 -7200 1 BRST} {1045360800 -10800 0 BRT} {1064368800 -10800 0 BRT} {1318734000 -7200 0 BRST} {1330221600 -10800 0 BRT} {1350784800 -10800 0 BRT} } tcl8.6.5/library/tzdata/America/Atka0000644000175000017500000000025412661614722016664 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Adak)]} { LoadTimeZoneFile America/Adak } set TZData(:America/Atka) $TZData(:America/Adak) tcl8.6.5/library/tzdata/America/Knox_IN0000644000175000017500000000030712661614722017310 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Indiana/Knox)]} { LoadTimeZoneFile America/Indiana/Knox } set TZData(:America/Knox_IN) $TZData(:America/Indiana/Knox) tcl8.6.5/library/tzdata/America/Grenada0000644000175000017500000000031212663660066017344 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/Grenada) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Porto_Velho0000644000175000017500000000200612661614721020240 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Porto_Velho) { {-9223372036854775808 -15336 0 LMT} {-1767210264 -14400 0 AMT} {-1206954000 -10800 1 AMST} {-1191358800 -14400 0 AMT} {-1175371200 -10800 1 AMST} {-1159822800 -14400 0 AMT} {-633816000 -10800 1 AMST} {-622065600 -14400 0 AMT} {-602280000 -10800 1 AMST} {-591829200 -14400 0 AMT} {-570744000 -10800 1 AMST} {-560206800 -14400 0 AMT} {-539121600 -10800 1 AMST} {-531349200 -14400 0 AMT} {-191361600 -10800 1 AMST} {-184194000 -14400 0 AMT} {-155160000 -10800 1 AMST} {-150066000 -14400 0 AMT} {-128894400 -10800 1 AMST} {-121122000 -14400 0 AMT} {-99950400 -10800 1 AMST} {-89586000 -14400 0 AMT} {-68414400 -10800 1 AMST} {-57963600 -14400 0 AMT} {499752000 -10800 1 AMST} {511239600 -14400 0 AMT} {530596800 -10800 1 AMST} {540270000 -14400 0 AMT} {562132800 -10800 1 AMST} {571201200 -14400 0 AMT} {590036400 -14400 0 AMT} } tcl8.6.5/library/tzdata/America/Iqaluit0000644000175000017500000001637512661614721017426 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Iqaluit) { {-9223372036854775808 0 0 zzz} {-865296000 -14400 0 EWT} {-769395600 -14400 1 EPT} {-765396000 -18000 0 EST} {-147898800 -10800 1 EDDT} {-131569200 -18000 0 EST} {325666800 -14400 1 EDT} {341388000 -18000 0 EST} {357116400 -14400 1 EDT} {372837600 -18000 0 EST} {388566000 -14400 1 EDT} {404892000 -18000 0 EST} {420015600 -14400 1 EDT} {436341600 -18000 0 EST} {452070000 -14400 1 EDT} {467791200 -18000 0 EST} {483519600 -14400 1 EDT} {499240800 -18000 0 EST} {514969200 -14400 1 EDT} {530690400 -18000 0 EST} {544604400 -14400 1 EDT} {562140000 -18000 0 EST} {576054000 -14400 1 EDT} {594194400 -18000 0 EST} {607503600 -14400 1 EDT} {625644000 -18000 0 EST} {638953200 -14400 1 EDT} {657093600 -18000 0 EST} {671007600 -14400 1 EDT} {688543200 -18000 0 EST} {702457200 -14400 1 EDT} {719992800 -18000 0 EST} {733906800 -14400 1 EDT} {752047200 -18000 0 EST} {765356400 -14400 1 EDT} {783496800 -18000 0 EST} {796806000 -14400 1 EDT} {814946400 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {909295200 -18000 0 EST} {923209200 -14400 1 EDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972806400 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Dawson0000644000175000017500000001667112661614720017247 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Dawson) { {-9223372036854775808 -33460 0 LMT} {-2188996940 -32400 0 YST} {-1632056400 -28800 1 YDT} {-1615125600 -32400 0 YST} {-1596978000 -28800 1 YDT} {-1583164800 -32400 0 YST} {-880203600 -28800 1 YWT} {-769395600 -28800 1 YPT} {-765381600 -32400 0 YST} {-147884400 -25200 1 YDDT} {-131554800 -32400 0 YST} {315561600 -28800 0 PST} {325677600 -25200 1 PDT} {341398800 -28800 0 PST} {357127200 -25200 1 PDT} {372848400 -28800 0 PST} {388576800 -25200 1 PDT} {404902800 -28800 0 PST} {420026400 -25200 1 PDT} {436352400 -28800 0 PST} {452080800 -25200 1 PDT} {467802000 -28800 0 PST} {483530400 -25200 1 PDT} {499251600 -28800 0 PST} {514980000 -25200 1 PDT} {530701200 -28800 0 PST} {544615200 -25200 1 PDT} {562150800 -28800 0 PST} {576064800 -25200 1 PDT} {594205200 -28800 0 PST} {607514400 -25200 1 PDT} {625654800 -28800 0 PST} {638964000 -25200 1 PDT} {657104400 -28800 0 PST} {671018400 -25200 1 PDT} {688554000 -28800 0 PST} {702468000 -25200 1 PDT} {720003600 -28800 0 PST} {733917600 -25200 1 PDT} {752058000 -28800 0 PST} {765367200 -25200 1 PDT} {783507600 -28800 0 PST} {796816800 -25200 1 PDT} {814957200 -28800 0 PST} {828871200 -25200 1 PDT} {846406800 -28800 0 PST} {860320800 -25200 1 PDT} {877856400 -28800 0 PST} {891770400 -25200 1 PDT} {909306000 -28800 0 PST} {923220000 -25200 1 PDT} {941360400 -28800 0 PST} {954669600 -25200 1 PDT} {972810000 -28800 0 PST} {986119200 -25200 1 PDT} {1004259600 -28800 0 PST} {1018173600 -25200 1 PDT} {1035709200 -28800 0 PST} {1049623200 -25200 1 PDT} {1067158800 -28800 0 PST} {1081072800 -25200 1 PDT} {1099213200 -28800 0 PST} {1112522400 -25200 1 PDT} {1130662800 -28800 0 PST} {1143972000 -25200 1 PDT} {1162112400 -28800 0 PST} {1173607200 -25200 1 PDT} {1194166800 -28800 0 PST} {1205056800 -25200 1 PDT} {1225616400 -28800 0 PST} {1236506400 -25200 1 PDT} {1257066000 -28800 0 PST} {1268560800 -25200 1 PDT} {1289120400 -28800 0 PST} {1300010400 -25200 1 PDT} {1320570000 -28800 0 PST} {1331460000 -25200 1 PDT} {1352019600 -28800 0 PST} {1362909600 -25200 1 PDT} {1383469200 -28800 0 PST} {1394359200 -25200 1 PDT} {1414918800 -28800 0 PST} {1425808800 -25200 1 PDT} {1446368400 -28800 0 PST} {1457863200 -25200 1 PDT} {1478422800 -28800 0 PST} {1489312800 -25200 1 PDT} {1509872400 -28800 0 PST} {1520762400 -25200 1 PDT} {1541322000 -28800 0 PST} {1552212000 -25200 1 PDT} {1572771600 -28800 0 PST} {1583661600 -25200 1 PDT} {1604221200 -28800 0 PST} {1615716000 -25200 1 PDT} {1636275600 -28800 0 PST} {1647165600 -25200 1 PDT} {1667725200 -28800 0 PST} {1678615200 -25200 1 PDT} {1699174800 -28800 0 PST} {1710064800 -25200 1 PDT} {1730624400 -28800 0 PST} {1741514400 -25200 1 PDT} {1762074000 -28800 0 PST} {1772964000 -25200 1 PDT} {1793523600 -28800 0 PST} {1805018400 -25200 1 PDT} {1825578000 -28800 0 PST} {1836468000 -25200 1 PDT} {1857027600 -28800 0 PST} {1867917600 -25200 1 PDT} {1888477200 -28800 0 PST} {1899367200 -25200 1 PDT} {1919926800 -28800 0 PST} {1930816800 -25200 1 PDT} {1951376400 -28800 0 PST} {1962871200 -25200 1 PDT} {1983430800 -28800 0 PST} {1994320800 -25200 1 PDT} {2014880400 -28800 0 PST} {2025770400 -25200 1 PDT} {2046330000 -28800 0 PST} {2057220000 -25200 1 PDT} {2077779600 -28800 0 PST} {2088669600 -25200 1 PDT} {2109229200 -28800 0 PST} {2120119200 -25200 1 PDT} {2140678800 -28800 0 PST} {2152173600 -25200 1 PDT} {2172733200 -28800 0 PST} {2183623200 -25200 1 PDT} {2204182800 -28800 0 PST} {2215072800 -25200 1 PDT} {2235632400 -28800 0 PST} {2246522400 -25200 1 PDT} {2267082000 -28800 0 PST} {2277972000 -25200 1 PDT} {2298531600 -28800 0 PST} {2309421600 -25200 1 PDT} {2329981200 -28800 0 PST} {2341476000 -25200 1 PDT} {2362035600 -28800 0 PST} {2372925600 -25200 1 PDT} {2393485200 -28800 0 PST} {2404375200 -25200 1 PDT} {2424934800 -28800 0 PST} {2435824800 -25200 1 PDT} {2456384400 -28800 0 PST} {2467274400 -25200 1 PDT} {2487834000 -28800 0 PST} {2499328800 -25200 1 PDT} {2519888400 -28800 0 PST} {2530778400 -25200 1 PDT} {2551338000 -28800 0 PST} {2562228000 -25200 1 PDT} {2582787600 -28800 0 PST} {2593677600 -25200 1 PDT} {2614237200 -28800 0 PST} {2625127200 -25200 1 PDT} {2645686800 -28800 0 PST} {2656576800 -25200 1 PDT} {2677136400 -28800 0 PST} {2688631200 -25200 1 PDT} {2709190800 -28800 0 PST} {2720080800 -25200 1 PDT} {2740640400 -28800 0 PST} {2751530400 -25200 1 PDT} {2772090000 -28800 0 PST} {2782980000 -25200 1 PDT} {2803539600 -28800 0 PST} {2814429600 -25200 1 PDT} {2834989200 -28800 0 PST} {2846484000 -25200 1 PDT} {2867043600 -28800 0 PST} {2877933600 -25200 1 PDT} {2898493200 -28800 0 PST} {2909383200 -25200 1 PDT} {2929942800 -28800 0 PST} {2940832800 -25200 1 PDT} {2961392400 -28800 0 PST} {2972282400 -25200 1 PDT} {2992842000 -28800 0 PST} {3003732000 -25200 1 PDT} {3024291600 -28800 0 PST} {3035786400 -25200 1 PDT} {3056346000 -28800 0 PST} {3067236000 -25200 1 PDT} {3087795600 -28800 0 PST} {3098685600 -25200 1 PDT} {3119245200 -28800 0 PST} {3130135200 -25200 1 PDT} {3150694800 -28800 0 PST} {3161584800 -25200 1 PDT} {3182144400 -28800 0 PST} {3193034400 -25200 1 PDT} {3213594000 -28800 0 PST} {3225088800 -25200 1 PDT} {3245648400 -28800 0 PST} {3256538400 -25200 1 PDT} {3277098000 -28800 0 PST} {3287988000 -25200 1 PDT} {3308547600 -28800 0 PST} {3319437600 -25200 1 PDT} {3339997200 -28800 0 PST} {3350887200 -25200 1 PDT} {3371446800 -28800 0 PST} {3382941600 -25200 1 PDT} {3403501200 -28800 0 PST} {3414391200 -25200 1 PDT} {3434950800 -28800 0 PST} {3445840800 -25200 1 PDT} {3466400400 -28800 0 PST} {3477290400 -25200 1 PDT} {3497850000 -28800 0 PST} {3508740000 -25200 1 PDT} {3529299600 -28800 0 PST} {3540189600 -25200 1 PDT} {3560749200 -28800 0 PST} {3572244000 -25200 1 PDT} {3592803600 -28800 0 PST} {3603693600 -25200 1 PDT} {3624253200 -28800 0 PST} {3635143200 -25200 1 PDT} {3655702800 -28800 0 PST} {3666592800 -25200 1 PDT} {3687152400 -28800 0 PST} {3698042400 -25200 1 PDT} {3718602000 -28800 0 PST} {3730096800 -25200 1 PDT} {3750656400 -28800 0 PST} {3761546400 -25200 1 PDT} {3782106000 -28800 0 PST} {3792996000 -25200 1 PDT} {3813555600 -28800 0 PST} {3824445600 -25200 1 PDT} {3845005200 -28800 0 PST} {3855895200 -25200 1 PDT} {3876454800 -28800 0 PST} {3887344800 -25200 1 PDT} {3907904400 -28800 0 PST} {3919399200 -25200 1 PDT} {3939958800 -28800 0 PST} {3950848800 -25200 1 PDT} {3971408400 -28800 0 PST} {3982298400 -25200 1 PDT} {4002858000 -28800 0 PST} {4013748000 -25200 1 PDT} {4034307600 -28800 0 PST} {4045197600 -25200 1 PDT} {4065757200 -28800 0 PST} {4076647200 -25200 1 PDT} {4097206800 -28800 0 PST} } tcl8.6.5/library/tzdata/America/Metlakatla0000644000175000017500000001447612665113557020102 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Metlakatla) { {-9223372036854775808 54822 0 LMT} {-3225366822 -31578 0 LMT} {-2188955622 -28800 0 PST} {-883584000 -28800 0 PST} {-880207200 -25200 1 PWT} {-769395600 -25200 1 PPT} {-765385200 -28800 0 PST} {-757353600 -28800 0 PST} {-31507200 -28800 0 PST} {-21477600 -25200 1 PDT} {-5756400 -28800 0 PST} {9972000 -25200 1 PDT} {25693200 -28800 0 PST} {41421600 -25200 1 PDT} {57747600 -28800 0 PST} {73476000 -25200 1 PDT} {89197200 -28800 0 PST} {104925600 -25200 1 PDT} {120646800 -28800 0 PST} {126698400 -25200 1 PDT} {152096400 -28800 0 PST} {162381600 -25200 1 PDT} {183546000 -28800 0 PST} {199274400 -25200 1 PDT} {215600400 -28800 0 PST} {230724000 -25200 1 PDT} {247050000 -28800 0 PST} {262778400 -25200 1 PDT} {278499600 -28800 0 PST} {294228000 -25200 1 PDT} {309949200 -28800 0 PST} {325677600 -25200 1 PDT} {341398800 -28800 0 PST} {357127200 -25200 1 PDT} {372848400 -28800 0 PST} {388576800 -25200 1 PDT} {404902800 -28800 0 PST} {420026400 -25200 1 PDT} {436356000 -28800 0 PST} {1446372000 -32400 0 AKST} {1457866800 -28800 1 AKDT} {1478426400 -32400 0 AKST} {1489316400 -28800 1 AKDT} {1509876000 -32400 0 AKST} {1520766000 -28800 1 AKDT} {1541325600 -32400 0 AKST} {1552215600 -28800 1 AKDT} {1572775200 -32400 0 AKST} {1583665200 -28800 1 AKDT} {1604224800 -32400 0 AKST} {1615719600 -28800 1 AKDT} {1636279200 -32400 0 AKST} {1647169200 -28800 1 AKDT} {1667728800 -32400 0 AKST} {1678618800 -28800 1 AKDT} {1699178400 -32400 0 AKST} {1710068400 -28800 1 AKDT} {1730628000 -32400 0 AKST} {1741518000 -28800 1 AKDT} {1762077600 -32400 0 AKST} {1772967600 -28800 1 AKDT} {1793527200 -32400 0 AKST} {1805022000 -28800 1 AKDT} {1825581600 -32400 0 AKST} {1836471600 -28800 1 AKDT} {1857031200 -32400 0 AKST} {1867921200 -28800 1 AKDT} {1888480800 -32400 0 AKST} {1899370800 -28800 1 AKDT} {1919930400 -32400 0 AKST} {1930820400 -28800 1 AKDT} {1951380000 -32400 0 AKST} {1962874800 -28800 1 AKDT} {1983434400 -32400 0 AKST} {1994324400 -28800 1 AKDT} {2014884000 -32400 0 AKST} {2025774000 -28800 1 AKDT} {2046333600 -32400 0 AKST} {2057223600 -28800 1 AKDT} {2077783200 -32400 0 AKST} {2088673200 -28800 1 AKDT} {2109232800 -32400 0 AKST} {2120122800 -28800 1 AKDT} {2140682400 -32400 0 AKST} {2152177200 -28800 1 AKDT} {2172736800 -32400 0 AKST} {2183626800 -28800 1 AKDT} {2204186400 -32400 0 AKST} {2215076400 -28800 1 AKDT} {2235636000 -32400 0 AKST} {2246526000 -28800 1 AKDT} {2267085600 -32400 0 AKST} {2277975600 -28800 1 AKDT} {2298535200 -32400 0 AKST} {2309425200 -28800 1 AKDT} {2329984800 -32400 0 AKST} {2341479600 -28800 1 AKDT} {2362039200 -32400 0 AKST} {2372929200 -28800 1 AKDT} {2393488800 -32400 0 AKST} {2404378800 -28800 1 AKDT} {2424938400 -32400 0 AKST} {2435828400 -28800 1 AKDT} {2456388000 -32400 0 AKST} {2467278000 -28800 1 AKDT} {2487837600 -32400 0 AKST} {2499332400 -28800 1 AKDT} {2519892000 -32400 0 AKST} {2530782000 -28800 1 AKDT} {2551341600 -32400 0 AKST} {2562231600 -28800 1 AKDT} {2582791200 -32400 0 AKST} {2593681200 -28800 1 AKDT} {2614240800 -32400 0 AKST} {2625130800 -28800 1 AKDT} {2645690400 -32400 0 AKST} {2656580400 -28800 1 AKDT} {2677140000 -32400 0 AKST} {2688634800 -28800 1 AKDT} {2709194400 -32400 0 AKST} {2720084400 -28800 1 AKDT} {2740644000 -32400 0 AKST} {2751534000 -28800 1 AKDT} {2772093600 -32400 0 AKST} {2782983600 -28800 1 AKDT} {2803543200 -32400 0 AKST} {2814433200 -28800 1 AKDT} {2834992800 -32400 0 AKST} {2846487600 -28800 1 AKDT} {2867047200 -32400 0 AKST} {2877937200 -28800 1 AKDT} {2898496800 -32400 0 AKST} {2909386800 -28800 1 AKDT} {2929946400 -32400 0 AKST} {2940836400 -28800 1 AKDT} {2961396000 -32400 0 AKST} {2972286000 -28800 1 AKDT} {2992845600 -32400 0 AKST} {3003735600 -28800 1 AKDT} {3024295200 -32400 0 AKST} {3035790000 -28800 1 AKDT} {3056349600 -32400 0 AKST} {3067239600 -28800 1 AKDT} {3087799200 -32400 0 AKST} {3098689200 -28800 1 AKDT} {3119248800 -32400 0 AKST} {3130138800 -28800 1 AKDT} {3150698400 -32400 0 AKST} {3161588400 -28800 1 AKDT} {3182148000 -32400 0 AKST} {3193038000 -28800 1 AKDT} {3213597600 -32400 0 AKST} {3225092400 -28800 1 AKDT} {3245652000 -32400 0 AKST} {3256542000 -28800 1 AKDT} {3277101600 -32400 0 AKST} {3287991600 -28800 1 AKDT} {3308551200 -32400 0 AKST} {3319441200 -28800 1 AKDT} {3340000800 -32400 0 AKST} {3350890800 -28800 1 AKDT} {3371450400 -32400 0 AKST} {3382945200 -28800 1 AKDT} {3403504800 -32400 0 AKST} {3414394800 -28800 1 AKDT} {3434954400 -32400 0 AKST} {3445844400 -28800 1 AKDT} {3466404000 -32400 0 AKST} {3477294000 -28800 1 AKDT} {3497853600 -32400 0 AKST} {3508743600 -28800 1 AKDT} {3529303200 -32400 0 AKST} {3540193200 -28800 1 AKDT} {3560752800 -32400 0 AKST} {3572247600 -28800 1 AKDT} {3592807200 -32400 0 AKST} {3603697200 -28800 1 AKDT} {3624256800 -32400 0 AKST} {3635146800 -28800 1 AKDT} {3655706400 -32400 0 AKST} {3666596400 -28800 1 AKDT} {3687156000 -32400 0 AKST} {3698046000 -28800 1 AKDT} {3718605600 -32400 0 AKST} {3730100400 -28800 1 AKDT} {3750660000 -32400 0 AKST} {3761550000 -28800 1 AKDT} {3782109600 -32400 0 AKST} {3792999600 -28800 1 AKDT} {3813559200 -32400 0 AKST} {3824449200 -28800 1 AKDT} {3845008800 -32400 0 AKST} {3855898800 -28800 1 AKDT} {3876458400 -32400 0 AKST} {3887348400 -28800 1 AKDT} {3907908000 -32400 0 AKST} {3919402800 -28800 1 AKDT} {3939962400 -32400 0 AKST} {3950852400 -28800 1 AKDT} {3971412000 -32400 0 AKST} {3982302000 -28800 1 AKDT} {4002861600 -32400 0 AKST} {4013751600 -28800 1 AKDT} {4034311200 -32400 0 AKST} {4045201200 -28800 1 AKDT} {4065760800 -32400 0 AKST} {4076650800 -28800 1 AKDT} {4097210400 -32400 0 AKST} } tcl8.6.5/library/tzdata/America/Santarem0000644000175000017500000000204112663653132017552 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Santarem) { {-9223372036854775808 -13128 0 LMT} {-1767212472 -14400 0 AMT} {-1206954000 -10800 1 AMST} {-1191358800 -14400 0 AMT} {-1175371200 -10800 1 AMST} {-1159822800 -14400 0 AMT} {-633816000 -10800 1 AMST} {-622065600 -14400 0 AMT} {-602280000 -10800 1 AMST} {-591829200 -14400 0 AMT} {-570744000 -10800 1 AMST} {-560206800 -14400 0 AMT} {-539121600 -10800 1 AMST} {-531349200 -14400 0 AMT} {-191361600 -10800 1 AMST} {-184194000 -14400 0 AMT} {-155160000 -10800 1 AMST} {-150066000 -14400 0 AMT} {-128894400 -10800 1 AMST} {-121122000 -14400 0 AMT} {-99950400 -10800 1 AMST} {-89586000 -14400 0 AMT} {-68414400 -10800 1 AMST} {-57963600 -14400 0 AMT} {499752000 -10800 1 AMST} {511239600 -14400 0 AMT} {530596800 -10800 1 AMST} {540270000 -14400 0 AMT} {562132800 -10800 1 AMST} {571201200 -14400 0 AMT} {590036400 -14400 0 AMT} {1214280000 -10800 0 BRT} } tcl8.6.5/library/tzdata/America/Cayenne0000644000175000017500000000026212661614720017363 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Cayenne) { {-9223372036854775808 -12560 0 LMT} {-1846269040 -14400 0 GFT} {-71092800 -10800 0 GFT} } tcl8.6.5/library/tzdata/America/Rainy_River0000644000175000017500000001724012663660066020244 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Rainy_River) { {-9223372036854775808 -22696 0 LMT} {-2366732504 -21600 0 CST} {-1632067200 -18000 1 CDT} {-1615136400 -21600 0 CST} {-923248800 -18000 1 CDT} {-880214400 -18000 0 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {136368000 -18000 1 CDT} {152089200 -21600 0 CST} {167817600 -18000 1 CDT} {183538800 -21600 0 CST} {199267200 -18000 1 CDT} {215593200 -21600 0 CST} {230716800 -18000 1 CDT} {247042800 -21600 0 CST} {262771200 -18000 1 CDT} {278492400 -21600 0 CST} {294220800 -18000 1 CDT} {309942000 -21600 0 CST} {325670400 -18000 1 CDT} {341391600 -21600 0 CST} {357120000 -18000 1 CDT} {372841200 -21600 0 CST} {388569600 -18000 1 CDT} {404895600 -21600 0 CST} {420019200 -18000 1 CDT} {436345200 -21600 0 CST} {452073600 -18000 1 CDT} {467794800 -21600 0 CST} {483523200 -18000 1 CDT} {499244400 -21600 0 CST} {514972800 -18000 1 CDT} {530694000 -21600 0 CST} {544608000 -18000 1 CDT} {562143600 -21600 0 CST} {576057600 -18000 1 CDT} {594198000 -21600 0 CST} {607507200 -18000 1 CDT} {625647600 -21600 0 CST} {638956800 -18000 1 CDT} {657097200 -21600 0 CST} {671011200 -18000 1 CDT} {688546800 -21600 0 CST} {702460800 -18000 1 CDT} {719996400 -21600 0 CST} {733910400 -18000 1 CDT} {752050800 -21600 0 CST} {765360000 -18000 1 CDT} {783500400 -21600 0 CST} {796809600 -18000 1 CDT} {814950000 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972802800 -21600 0 CST} {986112000 -18000 1 CDT} {1004252400 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194159600 -21600 0 CST} {1205049600 -18000 1 CDT} {1225609200 -21600 0 CST} {1236499200 -18000 1 CDT} {1257058800 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Virgin0000644000175000017500000000031112663660066017240 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/Virgin) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Winnipeg0000644000175000017500000002224312663660066017572 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Winnipeg) { {-9223372036854775808 -23316 0 LMT} {-2602258284 -21600 0 CST} {-1694368800 -18000 1 CDT} {-1681671600 -21600 0 CST} {-1632067200 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1029686400 -18000 1 CDT} {-1018198800 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-746035200 -18000 1 CDT} {-732733200 -21600 0 CST} {-715795200 -18000 1 CDT} {-702493200 -21600 0 CST} {-684345600 -18000 1 CDT} {-671043600 -21600 0 CST} {-652896000 -18000 1 CDT} {-639594000 -21600 0 CST} {-620755200 -18000 1 CDT} {-607626000 -21600 0 CST} {-589392000 -18000 1 CDT} {-576090000 -21600 0 CST} {-557942400 -18000 1 CDT} {-544640400 -21600 0 CST} {-526492800 -18000 1 CDT} {-513190800 -21600 0 CST} {-495043200 -18000 1 CDT} {-481741200 -21600 0 CST} {-463593600 -18000 1 CDT} {-450291600 -21600 0 CST} {-431539200 -18000 1 CDT} {-418237200 -21600 0 CST} {-400089600 -18000 1 CDT} {-386787600 -21600 0 CST} {-368640000 -18000 1 CDT} {-355338000 -21600 0 CST} {-337190400 -18000 1 CDT} {-321469200 -21600 0 CST} {-305740800 -18000 1 CDT} {-292438800 -21600 0 CST} {-210787200 -18000 1 CDT} {-198090000 -21600 0 CST} {-116438400 -18000 1 CDT} {-100108800 -21600 0 CST} {-84384000 -18000 1 CDT} {-68659200 -21600 0 CST} {-52934400 -18000 1 CDT} {-37209600 -21600 0 CST} {-21484800 -18000 1 CDT} {-5760000 -21600 0 CST} {9964800 -18000 1 CDT} {25689600 -21600 0 CST} {41414400 -18000 1 CDT} {57744000 -21600 0 CST} {73468800 -18000 1 CDT} {89193600 -21600 0 CST} {104918400 -18000 1 CDT} {120643200 -21600 0 CST} {136368000 -18000 1 CDT} {152092800 -21600 0 CST} {167817600 -18000 1 CDT} {183542400 -21600 0 CST} {199267200 -18000 1 CDT} {215596800 -21600 0 CST} {230716800 -18000 1 CDT} {247046400 -21600 0 CST} {262771200 -18000 1 CDT} {278496000 -21600 0 CST} {294220800 -18000 1 CDT} {309945600 -21600 0 CST} {325670400 -18000 1 CDT} {341395200 -21600 0 CST} {357120000 -18000 1 CDT} {372844800 -21600 0 CST} {388569600 -18000 1 CDT} {404899200 -21600 0 CST} {420019200 -18000 1 CDT} {436348800 -21600 0 CST} {452073600 -18000 1 CDT} {467798400 -21600 0 CST} {483523200 -18000 1 CDT} {499248000 -21600 0 CST} {514972800 -18000 1 CDT} {530697600 -21600 0 CST} {544608000 -18000 1 CDT} {562147200 -21600 0 CST} {576057600 -18000 1 CDT} {594201600 -21600 0 CST} {607507200 -18000 1 CDT} {625651200 -21600 0 CST} {638956800 -18000 1 CDT} {657100800 -21600 0 CST} {671011200 -18000 1 CDT} {688550400 -21600 0 CST} {702460800 -18000 1 CDT} {720000000 -21600 0 CST} {733910400 -18000 1 CDT} {752054400 -21600 0 CST} {765360000 -18000 1 CDT} {783504000 -21600 0 CST} {796809600 -18000 1 CDT} {814953600 -21600 0 CST} {828864000 -18000 1 CDT} {846403200 -21600 0 CST} {860313600 -18000 1 CDT} {877852800 -21600 0 CST} {891763200 -18000 1 CDT} {909302400 -21600 0 CST} {923212800 -18000 1 CDT} {941356800 -21600 0 CST} {954662400 -18000 1 CDT} {972806400 -21600 0 CST} {986112000 -18000 1 CDT} {1004256000 -21600 0 CST} {1018166400 -18000 1 CDT} {1035705600 -21600 0 CST} {1049616000 -18000 1 CDT} {1067155200 -21600 0 CST} {1081065600 -18000 1 CDT} {1099209600 -21600 0 CST} {1112515200 -18000 1 CDT} {1130659200 -21600 0 CST} {1136095200 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194159600 -21600 0 CST} {1205049600 -18000 1 CDT} {1225609200 -21600 0 CST} {1236499200 -18000 1 CDT} {1257058800 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/St_Thomas0000644000175000017500000000031412663660066017706 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/St_Thomas) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/La_Paz0000644000175000017500000000032312661614721017146 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/La_Paz) { {-9223372036854775808 -16356 0 LMT} {-2524505244 -16356 0 CMT} {-1205954844 -12756 1 BOST} {-1192307244 -14400 0 BOT} } tcl8.6.5/library/tzdata/America/Merida0000644000175000017500000001444312661614721017211 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Merida) { {-9223372036854775808 -21508 0 LMT} {-1514743200 -21600 0 CST} {377935200 -18000 0 EST} {407653200 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972802800 -21600 0 CST} {989136000 -18000 1 CDT} {1001833200 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1175414400 -18000 1 CDT} {1193554800 -21600 0 CST} {1207468800 -18000 1 CDT} {1225004400 -21600 0 CST} {1238918400 -18000 1 CDT} {1256454000 -21600 0 CST} {1270368000 -18000 1 CDT} {1288508400 -21600 0 CST} {1301817600 -18000 1 CDT} {1319958000 -21600 0 CST} {1333267200 -18000 1 CDT} {1351407600 -21600 0 CST} {1365321600 -18000 1 CDT} {1382857200 -21600 0 CST} {1396771200 -18000 1 CDT} {1414306800 -21600 0 CST} {1428220800 -18000 1 CDT} {1445756400 -21600 0 CST} {1459670400 -18000 1 CDT} {1477810800 -21600 0 CST} {1491120000 -18000 1 CDT} {1509260400 -21600 0 CST} {1522569600 -18000 1 CDT} {1540710000 -21600 0 CST} {1554624000 -18000 1 CDT} {1572159600 -21600 0 CST} {1586073600 -18000 1 CDT} {1603609200 -21600 0 CST} {1617523200 -18000 1 CDT} {1635663600 -21600 0 CST} {1648972800 -18000 1 CDT} {1667113200 -21600 0 CST} {1680422400 -18000 1 CDT} {1698562800 -21600 0 CST} {1712476800 -18000 1 CDT} {1730012400 -21600 0 CST} {1743926400 -18000 1 CDT} {1761462000 -21600 0 CST} {1775376000 -18000 1 CDT} {1792911600 -21600 0 CST} {1806825600 -18000 1 CDT} {1824966000 -21600 0 CST} {1838275200 -18000 1 CDT} {1856415600 -21600 0 CST} {1869724800 -18000 1 CDT} {1887865200 -21600 0 CST} {1901779200 -18000 1 CDT} {1919314800 -21600 0 CST} {1933228800 -18000 1 CDT} {1950764400 -21600 0 CST} {1964678400 -18000 1 CDT} {1982818800 -21600 0 CST} {1996128000 -18000 1 CDT} {2014268400 -21600 0 CST} {2027577600 -18000 1 CDT} {2045718000 -21600 0 CST} {2059027200 -18000 1 CDT} {2077167600 -21600 0 CST} {2091081600 -18000 1 CDT} {2108617200 -21600 0 CST} {2122531200 -18000 1 CDT} {2140066800 -21600 0 CST} {2153980800 -18000 1 CDT} {2172121200 -21600 0 CST} {2185430400 -18000 1 CDT} {2203570800 -21600 0 CST} {2216880000 -18000 1 CDT} {2235020400 -21600 0 CST} {2248934400 -18000 1 CDT} {2266470000 -21600 0 CST} {2280384000 -18000 1 CDT} {2297919600 -21600 0 CST} {2311833600 -18000 1 CDT} {2329369200 -21600 0 CST} {2343283200 -18000 1 CDT} {2361423600 -21600 0 CST} {2374732800 -18000 1 CDT} {2392873200 -21600 0 CST} {2406182400 -18000 1 CDT} {2424322800 -21600 0 CST} {2438236800 -18000 1 CDT} {2455772400 -21600 0 CST} {2469686400 -18000 1 CDT} {2487222000 -21600 0 CST} {2501136000 -18000 1 CDT} {2519276400 -21600 0 CST} {2532585600 -18000 1 CDT} {2550726000 -21600 0 CST} {2564035200 -18000 1 CDT} {2582175600 -21600 0 CST} {2596089600 -18000 1 CDT} {2613625200 -21600 0 CST} {2627539200 -18000 1 CDT} {2645074800 -21600 0 CST} {2658988800 -18000 1 CDT} {2676524400 -21600 0 CST} {2690438400 -18000 1 CDT} {2708578800 -21600 0 CST} {2721888000 -18000 1 CDT} {2740028400 -21600 0 CST} {2753337600 -18000 1 CDT} {2771478000 -21600 0 CST} {2785392000 -18000 1 CDT} {2802927600 -21600 0 CST} {2816841600 -18000 1 CDT} {2834377200 -21600 0 CST} {2848291200 -18000 1 CDT} {2866431600 -21600 0 CST} {2879740800 -18000 1 CDT} {2897881200 -21600 0 CST} {2911190400 -18000 1 CDT} {2929330800 -21600 0 CST} {2942640000 -18000 1 CDT} {2960780400 -21600 0 CST} {2974694400 -18000 1 CDT} {2992230000 -21600 0 CST} {3006144000 -18000 1 CDT} {3023679600 -21600 0 CST} {3037593600 -18000 1 CDT} {3055734000 -21600 0 CST} {3069043200 -18000 1 CDT} {3087183600 -21600 0 CST} {3100492800 -18000 1 CDT} {3118633200 -21600 0 CST} {3132547200 -18000 1 CDT} {3150082800 -21600 0 CST} {3163996800 -18000 1 CDT} {3181532400 -21600 0 CST} {3195446400 -18000 1 CDT} {3212982000 -21600 0 CST} {3226896000 -18000 1 CDT} {3245036400 -21600 0 CST} {3258345600 -18000 1 CDT} {3276486000 -21600 0 CST} {3289795200 -18000 1 CDT} {3307935600 -21600 0 CST} {3321849600 -18000 1 CDT} {3339385200 -21600 0 CST} {3353299200 -18000 1 CDT} {3370834800 -21600 0 CST} {3384748800 -18000 1 CDT} {3402889200 -21600 0 CST} {3416198400 -18000 1 CDT} {3434338800 -21600 0 CST} {3447648000 -18000 1 CDT} {3465788400 -21600 0 CST} {3479702400 -18000 1 CDT} {3497238000 -21600 0 CST} {3511152000 -18000 1 CDT} {3528687600 -21600 0 CST} {3542601600 -18000 1 CDT} {3560137200 -21600 0 CST} {3574051200 -18000 1 CDT} {3592191600 -21600 0 CST} {3605500800 -18000 1 CDT} {3623641200 -21600 0 CST} {3636950400 -18000 1 CDT} {3655090800 -21600 0 CST} {3669004800 -18000 1 CDT} {3686540400 -21600 0 CST} {3700454400 -18000 1 CDT} {3717990000 -21600 0 CST} {3731904000 -18000 1 CDT} {3750044400 -21600 0 CST} {3763353600 -18000 1 CDT} {3781494000 -21600 0 CST} {3794803200 -18000 1 CDT} {3812943600 -21600 0 CST} {3826252800 -18000 1 CDT} {3844393200 -21600 0 CST} {3858307200 -18000 1 CDT} {3875842800 -21600 0 CST} {3889756800 -18000 1 CDT} {3907292400 -21600 0 CST} {3921206400 -18000 1 CDT} {3939346800 -21600 0 CST} {3952656000 -18000 1 CDT} {3970796400 -21600 0 CST} {3984105600 -18000 1 CDT} {4002246000 -21600 0 CST} {4016160000 -18000 1 CDT} {4033695600 -21600 0 CST} {4047609600 -18000 1 CDT} {4065145200 -21600 0 CST} {4079059200 -18000 1 CDT} {4096594800 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Rio_Branco0000644000175000017500000000210112663660066020016 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Rio_Branco) { {-9223372036854775808 -16272 0 LMT} {-1767209328 -18000 0 ACT} {-1206950400 -14400 1 ACST} {-1191355200 -18000 0 ACT} {-1175367600 -14400 1 ACST} {-1159819200 -18000 0 ACT} {-633812400 -14400 1 ACST} {-622062000 -18000 0 ACT} {-602276400 -14400 1 ACST} {-591825600 -18000 0 ACT} {-570740400 -14400 1 ACST} {-560203200 -18000 0 ACT} {-539118000 -14400 1 ACST} {-531345600 -18000 0 ACT} {-191358000 -14400 1 ACST} {-184190400 -18000 0 ACT} {-155156400 -14400 1 ACST} {-150062400 -18000 0 ACT} {-128890800 -14400 1 ACST} {-121118400 -18000 0 ACT} {-99946800 -14400 1 ACST} {-89582400 -18000 0 ACT} {-68410800 -14400 1 ACST} {-57960000 -18000 0 ACT} {499755600 -14400 1 ACST} {511243200 -18000 0 ACT} {530600400 -14400 1 ACST} {540273600 -18000 0 ACT} {562136400 -14400 1 ACST} {571204800 -18000 0 ACT} {590040000 -18000 0 ACT} {1214283600 -14400 0 AMT} {1384056000 -18000 0 ACT} } tcl8.6.5/library/tzdata/America/Thunder_Bay0000644000175000017500000001757212661614721020222 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Thunder_Bay) { {-9223372036854775808 -21420 0 LMT} {-2366733780 -21600 0 CST} {-1893434400 -18000 0 EST} {-883594800 -18000 0 EST} {-880218000 -14400 1 EWT} {-769395600 -14400 1 EPT} {-765396000 -18000 0 EST} {18000 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {41410800 -14400 1 EDT} {57736800 -18000 0 EST} {73465200 -14400 1 EDT} {89186400 -18000 0 EST} {94712400 -18000 0 EST} {126248400 -18000 0 EST} {136364400 -14400 1 EDT} {152085600 -18000 0 EST} {167814000 -14400 1 EDT} {183535200 -18000 0 EST} {199263600 -14400 1 EDT} {215589600 -18000 0 EST} {230713200 -14400 1 EDT} {247039200 -18000 0 EST} {262767600 -14400 1 EDT} {278488800 -18000 0 EST} {294217200 -14400 1 EDT} {309938400 -18000 0 EST} {325666800 -14400 1 EDT} {341388000 -18000 0 EST} {357116400 -14400 1 EDT} {372837600 -18000 0 EST} {388566000 -14400 1 EDT} {404892000 -18000 0 EST} {420015600 -14400 1 EDT} {436341600 -18000 0 EST} {452070000 -14400 1 EDT} {467791200 -18000 0 EST} {483519600 -14400 1 EDT} {499240800 -18000 0 EST} {514969200 -14400 1 EDT} {530690400 -18000 0 EST} {544604400 -14400 1 EDT} {562140000 -18000 0 EST} {576054000 -14400 1 EDT} {594194400 -18000 0 EST} {607503600 -14400 1 EDT} {625644000 -18000 0 EST} {638953200 -14400 1 EDT} {657093600 -18000 0 EST} {671007600 -14400 1 EDT} {688543200 -18000 0 EST} {702457200 -14400 1 EDT} {719992800 -18000 0 EST} {733906800 -14400 1 EDT} {752047200 -18000 0 EST} {765356400 -14400 1 EDT} {783496800 -18000 0 EST} {796806000 -14400 1 EDT} {814946400 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {909295200 -18000 0 EST} {923209200 -14400 1 EDT} {941349600 -18000 0 EST} {954658800 -14400 1 EDT} {972799200 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Adak0000644000175000017500000001775312663660066016664 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Adak) { {-9223372036854775808 44001 0 LMT} {-3225356001 -42398 0 LMT} {-2188944802 -39600 0 NST} {-883573200 -39600 0 NST} {-880196400 -36000 1 NWT} {-769395600 -36000 1 NPT} {-765374400 -39600 0 NST} {-757342800 -39600 0 NST} {-86878800 -39600 0 BST} {-31496400 -39600 0 BST} {-21466800 -36000 1 BDT} {-5745600 -39600 0 BST} {9982800 -36000 1 BDT} {25704000 -39600 0 BST} {41432400 -36000 1 BDT} {57758400 -39600 0 BST} {73486800 -36000 1 BDT} {89208000 -39600 0 BST} {104936400 -36000 1 BDT} {120657600 -39600 0 BST} {126709200 -36000 1 BDT} {152107200 -39600 0 BST} {162392400 -36000 1 BDT} {183556800 -39600 0 BST} {199285200 -36000 1 BDT} {215611200 -39600 0 BST} {230734800 -36000 1 BDT} {247060800 -39600 0 BST} {262789200 -36000 1 BDT} {278510400 -39600 0 BST} {294238800 -36000 1 BDT} {309960000 -39600 0 BST} {325688400 -36000 1 BDT} {341409600 -39600 0 BST} {357138000 -36000 1 BDT} {372859200 -39600 0 BST} {388587600 -36000 1 BDT} {404913600 -39600 0 BST} {420037200 -36000 1 BDT} {439034400 -36000 0 HST} {452088000 -32400 1 HDT} {467809200 -36000 0 HST} {483537600 -32400 1 HDT} {499258800 -36000 0 HST} {514987200 -32400 1 HDT} {530708400 -36000 0 HST} {544622400 -32400 1 HDT} {562158000 -36000 0 HST} {576072000 -32400 1 HDT} {594212400 -36000 0 HST} {607521600 -32400 1 HDT} {625662000 -36000 0 HST} {638971200 -32400 1 HDT} {657111600 -36000 0 HST} {671025600 -32400 1 HDT} {688561200 -36000 0 HST} {702475200 -32400 1 HDT} {720010800 -36000 0 HST} {733924800 -32400 1 HDT} {752065200 -36000 0 HST} {765374400 -32400 1 HDT} {783514800 -36000 0 HST} {796824000 -32400 1 HDT} {814964400 -36000 0 HST} {828878400 -32400 1 HDT} {846414000 -36000 0 HST} {860328000 -32400 1 HDT} {877863600 -36000 0 HST} {891777600 -32400 1 HDT} {909313200 -36000 0 HST} {923227200 -32400 1 HDT} {941367600 -36000 0 HST} {954676800 -32400 1 HDT} {972817200 -36000 0 HST} {986126400 -32400 1 HDT} {1004266800 -36000 0 HST} {1018180800 -32400 1 HDT} {1035716400 -36000 0 HST} {1049630400 -32400 1 HDT} {1067166000 -36000 0 HST} {1081080000 -32400 1 HDT} {1099220400 -36000 0 HST} {1112529600 -32400 1 HDT} {1130670000 -36000 0 HST} {1143979200 -32400 1 HDT} {1162119600 -36000 0 HST} {1173614400 -32400 1 HDT} {1194174000 -36000 0 HST} {1205064000 -32400 1 HDT} {1225623600 -36000 0 HST} {1236513600 -32400 1 HDT} {1257073200 -36000 0 HST} {1268568000 -32400 1 HDT} {1289127600 -36000 0 HST} {1300017600 -32400 1 HDT} {1320577200 -36000 0 HST} {1331467200 -32400 1 HDT} {1352026800 -36000 0 HST} {1362916800 -32400 1 HDT} {1383476400 -36000 0 HST} {1394366400 -32400 1 HDT} {1414926000 -36000 0 HST} {1425816000 -32400 1 HDT} {1446375600 -36000 0 HST} {1457870400 -32400 1 HDT} {1478430000 -36000 0 HST} {1489320000 -32400 1 HDT} {1509879600 -36000 0 HST} {1520769600 -32400 1 HDT} {1541329200 -36000 0 HST} {1552219200 -32400 1 HDT} {1572778800 -36000 0 HST} {1583668800 -32400 1 HDT} {1604228400 -36000 0 HST} {1615723200 -32400 1 HDT} {1636282800 -36000 0 HST} {1647172800 -32400 1 HDT} {1667732400 -36000 0 HST} {1678622400 -32400 1 HDT} {1699182000 -36000 0 HST} {1710072000 -32400 1 HDT} {1730631600 -36000 0 HST} {1741521600 -32400 1 HDT} {1762081200 -36000 0 HST} {1772971200 -32400 1 HDT} {1793530800 -36000 0 HST} {1805025600 -32400 1 HDT} {1825585200 -36000 0 HST} {1836475200 -32400 1 HDT} {1857034800 -36000 0 HST} {1867924800 -32400 1 HDT} {1888484400 -36000 0 HST} {1899374400 -32400 1 HDT} {1919934000 -36000 0 HST} {1930824000 -32400 1 HDT} {1951383600 -36000 0 HST} {1962878400 -32400 1 HDT} {1983438000 -36000 0 HST} {1994328000 -32400 1 HDT} {2014887600 -36000 0 HST} {2025777600 -32400 1 HDT} {2046337200 -36000 0 HST} {2057227200 -32400 1 HDT} {2077786800 -36000 0 HST} {2088676800 -32400 1 HDT} {2109236400 -36000 0 HST} {2120126400 -32400 1 HDT} {2140686000 -36000 0 HST} {2152180800 -32400 1 HDT} {2172740400 -36000 0 HST} {2183630400 -32400 1 HDT} {2204190000 -36000 0 HST} {2215080000 -32400 1 HDT} {2235639600 -36000 0 HST} {2246529600 -32400 1 HDT} {2267089200 -36000 0 HST} {2277979200 -32400 1 HDT} {2298538800 -36000 0 HST} {2309428800 -32400 1 HDT} {2329988400 -36000 0 HST} {2341483200 -32400 1 HDT} {2362042800 -36000 0 HST} {2372932800 -32400 1 HDT} {2393492400 -36000 0 HST} {2404382400 -32400 1 HDT} {2424942000 -36000 0 HST} {2435832000 -32400 1 HDT} {2456391600 -36000 0 HST} {2467281600 -32400 1 HDT} {2487841200 -36000 0 HST} {2499336000 -32400 1 HDT} {2519895600 -36000 0 HST} {2530785600 -32400 1 HDT} {2551345200 -36000 0 HST} {2562235200 -32400 1 HDT} {2582794800 -36000 0 HST} {2593684800 -32400 1 HDT} {2614244400 -36000 0 HST} {2625134400 -32400 1 HDT} {2645694000 -36000 0 HST} {2656584000 -32400 1 HDT} {2677143600 -36000 0 HST} {2688638400 -32400 1 HDT} {2709198000 -36000 0 HST} {2720088000 -32400 1 HDT} {2740647600 -36000 0 HST} {2751537600 -32400 1 HDT} {2772097200 -36000 0 HST} {2782987200 -32400 1 HDT} {2803546800 -36000 0 HST} {2814436800 -32400 1 HDT} {2834996400 -36000 0 HST} {2846491200 -32400 1 HDT} {2867050800 -36000 0 HST} {2877940800 -32400 1 HDT} {2898500400 -36000 0 HST} {2909390400 -32400 1 HDT} {2929950000 -36000 0 HST} {2940840000 -32400 1 HDT} {2961399600 -36000 0 HST} {2972289600 -32400 1 HDT} {2992849200 -36000 0 HST} {3003739200 -32400 1 HDT} {3024298800 -36000 0 HST} {3035793600 -32400 1 HDT} {3056353200 -36000 0 HST} {3067243200 -32400 1 HDT} {3087802800 -36000 0 HST} {3098692800 -32400 1 HDT} {3119252400 -36000 0 HST} {3130142400 -32400 1 HDT} {3150702000 -36000 0 HST} {3161592000 -32400 1 HDT} {3182151600 -36000 0 HST} {3193041600 -32400 1 HDT} {3213601200 -36000 0 HST} {3225096000 -32400 1 HDT} {3245655600 -36000 0 HST} {3256545600 -32400 1 HDT} {3277105200 -36000 0 HST} {3287995200 -32400 1 HDT} {3308554800 -36000 0 HST} {3319444800 -32400 1 HDT} {3340004400 -36000 0 HST} {3350894400 -32400 1 HDT} {3371454000 -36000 0 HST} {3382948800 -32400 1 HDT} {3403508400 -36000 0 HST} {3414398400 -32400 1 HDT} {3434958000 -36000 0 HST} {3445848000 -32400 1 HDT} {3466407600 -36000 0 HST} {3477297600 -32400 1 HDT} {3497857200 -36000 0 HST} {3508747200 -32400 1 HDT} {3529306800 -36000 0 HST} {3540196800 -32400 1 HDT} {3560756400 -36000 0 HST} {3572251200 -32400 1 HDT} {3592810800 -36000 0 HST} {3603700800 -32400 1 HDT} {3624260400 -36000 0 HST} {3635150400 -32400 1 HDT} {3655710000 -36000 0 HST} {3666600000 -32400 1 HDT} {3687159600 -36000 0 HST} {3698049600 -32400 1 HDT} {3718609200 -36000 0 HST} {3730104000 -32400 1 HDT} {3750663600 -36000 0 HST} {3761553600 -32400 1 HDT} {3782113200 -36000 0 HST} {3793003200 -32400 1 HDT} {3813562800 -36000 0 HST} {3824452800 -32400 1 HDT} {3845012400 -36000 0 HST} {3855902400 -32400 1 HDT} {3876462000 -36000 0 HST} {3887352000 -32400 1 HDT} {3907911600 -36000 0 HST} {3919406400 -32400 1 HDT} {3939966000 -36000 0 HST} {3950856000 -32400 1 HDT} {3971415600 -36000 0 HST} {3982305600 -32400 1 HDT} {4002865200 -36000 0 HST} {4013755200 -32400 1 HDT} {4034314800 -36000 0 HST} {4045204800 -32400 1 HDT} {4065764400 -36000 0 HST} {4076654400 -32400 1 HDT} {4097214000 -36000 0 HST} } tcl8.6.5/library/tzdata/America/Whitehorse0000644000175000017500000001667512661614721020142 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Whitehorse) { {-9223372036854775808 -32412 0 LMT} {-2188997988 -32400 0 YST} {-1632056400 -28800 1 YDT} {-1615125600 -32400 0 YST} {-1596978000 -28800 1 YDT} {-1583164800 -32400 0 YST} {-880203600 -28800 1 YWT} {-769395600 -28800 1 YPT} {-765381600 -32400 0 YST} {-147884400 -25200 1 YDDT} {-131554800 -32400 0 YST} {315561600 -28800 0 PST} {325677600 -25200 1 PDT} {341398800 -28800 0 PST} {357127200 -25200 1 PDT} {372848400 -28800 0 PST} {388576800 -25200 1 PDT} {404902800 -28800 0 PST} {420026400 -25200 1 PDT} {436352400 -28800 0 PST} {452080800 -25200 1 PDT} {467802000 -28800 0 PST} {483530400 -25200 1 PDT} {499251600 -28800 0 PST} {514980000 -25200 1 PDT} {530701200 -28800 0 PST} {544615200 -25200 1 PDT} {562150800 -28800 0 PST} {576064800 -25200 1 PDT} {594205200 -28800 0 PST} {607514400 -25200 1 PDT} {625654800 -28800 0 PST} {638964000 -25200 1 PDT} {657104400 -28800 0 PST} {671018400 -25200 1 PDT} {688554000 -28800 0 PST} {702468000 -25200 1 PDT} {720003600 -28800 0 PST} {733917600 -25200 1 PDT} {752058000 -28800 0 PST} {765367200 -25200 1 PDT} {783507600 -28800 0 PST} {796816800 -25200 1 PDT} {814957200 -28800 0 PST} {828871200 -25200 1 PDT} {846406800 -28800 0 PST} {860320800 -25200 1 PDT} {877856400 -28800 0 PST} {891770400 -25200 1 PDT} {909306000 -28800 0 PST} {923220000 -25200 1 PDT} {941360400 -28800 0 PST} {954669600 -25200 1 PDT} {972810000 -28800 0 PST} {986119200 -25200 1 PDT} {1004259600 -28800 0 PST} {1018173600 -25200 1 PDT} {1035709200 -28800 0 PST} {1049623200 -25200 1 PDT} {1067158800 -28800 0 PST} {1081072800 -25200 1 PDT} {1099213200 -28800 0 PST} {1112522400 -25200 1 PDT} {1130662800 -28800 0 PST} {1143972000 -25200 1 PDT} {1162112400 -28800 0 PST} {1173607200 -25200 1 PDT} {1194166800 -28800 0 PST} {1205056800 -25200 1 PDT} {1225616400 -28800 0 PST} {1236506400 -25200 1 PDT} {1257066000 -28800 0 PST} {1268560800 -25200 1 PDT} {1289120400 -28800 0 PST} {1300010400 -25200 1 PDT} {1320570000 -28800 0 PST} {1331460000 -25200 1 PDT} {1352019600 -28800 0 PST} {1362909600 -25200 1 PDT} {1383469200 -28800 0 PST} {1394359200 -25200 1 PDT} {1414918800 -28800 0 PST} {1425808800 -25200 1 PDT} {1446368400 -28800 0 PST} {1457863200 -25200 1 PDT} {1478422800 -28800 0 PST} {1489312800 -25200 1 PDT} {1509872400 -28800 0 PST} {1520762400 -25200 1 PDT} {1541322000 -28800 0 PST} {1552212000 -25200 1 PDT} {1572771600 -28800 0 PST} {1583661600 -25200 1 PDT} {1604221200 -28800 0 PST} {1615716000 -25200 1 PDT} {1636275600 -28800 0 PST} {1647165600 -25200 1 PDT} {1667725200 -28800 0 PST} {1678615200 -25200 1 PDT} {1699174800 -28800 0 PST} {1710064800 -25200 1 PDT} {1730624400 -28800 0 PST} {1741514400 -25200 1 PDT} {1762074000 -28800 0 PST} {1772964000 -25200 1 PDT} {1793523600 -28800 0 PST} {1805018400 -25200 1 PDT} {1825578000 -28800 0 PST} {1836468000 -25200 1 PDT} {1857027600 -28800 0 PST} {1867917600 -25200 1 PDT} {1888477200 -28800 0 PST} {1899367200 -25200 1 PDT} {1919926800 -28800 0 PST} {1930816800 -25200 1 PDT} {1951376400 -28800 0 PST} {1962871200 -25200 1 PDT} {1983430800 -28800 0 PST} {1994320800 -25200 1 PDT} {2014880400 -28800 0 PST} {2025770400 -25200 1 PDT} {2046330000 -28800 0 PST} {2057220000 -25200 1 PDT} {2077779600 -28800 0 PST} {2088669600 -25200 1 PDT} {2109229200 -28800 0 PST} {2120119200 -25200 1 PDT} {2140678800 -28800 0 PST} {2152173600 -25200 1 PDT} {2172733200 -28800 0 PST} {2183623200 -25200 1 PDT} {2204182800 -28800 0 PST} {2215072800 -25200 1 PDT} {2235632400 -28800 0 PST} {2246522400 -25200 1 PDT} {2267082000 -28800 0 PST} {2277972000 -25200 1 PDT} {2298531600 -28800 0 PST} {2309421600 -25200 1 PDT} {2329981200 -28800 0 PST} {2341476000 -25200 1 PDT} {2362035600 -28800 0 PST} {2372925600 -25200 1 PDT} {2393485200 -28800 0 PST} {2404375200 -25200 1 PDT} {2424934800 -28800 0 PST} {2435824800 -25200 1 PDT} {2456384400 -28800 0 PST} {2467274400 -25200 1 PDT} {2487834000 -28800 0 PST} {2499328800 -25200 1 PDT} {2519888400 -28800 0 PST} {2530778400 -25200 1 PDT} {2551338000 -28800 0 PST} {2562228000 -25200 1 PDT} {2582787600 -28800 0 PST} {2593677600 -25200 1 PDT} {2614237200 -28800 0 PST} {2625127200 -25200 1 PDT} {2645686800 -28800 0 PST} {2656576800 -25200 1 PDT} {2677136400 -28800 0 PST} {2688631200 -25200 1 PDT} {2709190800 -28800 0 PST} {2720080800 -25200 1 PDT} {2740640400 -28800 0 PST} {2751530400 -25200 1 PDT} {2772090000 -28800 0 PST} {2782980000 -25200 1 PDT} {2803539600 -28800 0 PST} {2814429600 -25200 1 PDT} {2834989200 -28800 0 PST} {2846484000 -25200 1 PDT} {2867043600 -28800 0 PST} {2877933600 -25200 1 PDT} {2898493200 -28800 0 PST} {2909383200 -25200 1 PDT} {2929942800 -28800 0 PST} {2940832800 -25200 1 PDT} {2961392400 -28800 0 PST} {2972282400 -25200 1 PDT} {2992842000 -28800 0 PST} {3003732000 -25200 1 PDT} {3024291600 -28800 0 PST} {3035786400 -25200 1 PDT} {3056346000 -28800 0 PST} {3067236000 -25200 1 PDT} {3087795600 -28800 0 PST} {3098685600 -25200 1 PDT} {3119245200 -28800 0 PST} {3130135200 -25200 1 PDT} {3150694800 -28800 0 PST} {3161584800 -25200 1 PDT} {3182144400 -28800 0 PST} {3193034400 -25200 1 PDT} {3213594000 -28800 0 PST} {3225088800 -25200 1 PDT} {3245648400 -28800 0 PST} {3256538400 -25200 1 PDT} {3277098000 -28800 0 PST} {3287988000 -25200 1 PDT} {3308547600 -28800 0 PST} {3319437600 -25200 1 PDT} {3339997200 -28800 0 PST} {3350887200 -25200 1 PDT} {3371446800 -28800 0 PST} {3382941600 -25200 1 PDT} {3403501200 -28800 0 PST} {3414391200 -25200 1 PDT} {3434950800 -28800 0 PST} {3445840800 -25200 1 PDT} {3466400400 -28800 0 PST} {3477290400 -25200 1 PDT} {3497850000 -28800 0 PST} {3508740000 -25200 1 PDT} {3529299600 -28800 0 PST} {3540189600 -25200 1 PDT} {3560749200 -28800 0 PST} {3572244000 -25200 1 PDT} {3592803600 -28800 0 PST} {3603693600 -25200 1 PDT} {3624253200 -28800 0 PST} {3635143200 -25200 1 PDT} {3655702800 -28800 0 PST} {3666592800 -25200 1 PDT} {3687152400 -28800 0 PST} {3698042400 -25200 1 PDT} {3718602000 -28800 0 PST} {3730096800 -25200 1 PDT} {3750656400 -28800 0 PST} {3761546400 -25200 1 PDT} {3782106000 -28800 0 PST} {3792996000 -25200 1 PDT} {3813555600 -28800 0 PST} {3824445600 -25200 1 PDT} {3845005200 -28800 0 PST} {3855895200 -25200 1 PDT} {3876454800 -28800 0 PST} {3887344800 -25200 1 PDT} {3907904400 -28800 0 PST} {3919399200 -25200 1 PDT} {3939958800 -28800 0 PST} {3950848800 -25200 1 PDT} {3971408400 -28800 0 PST} {3982298400 -25200 1 PDT} {4002858000 -28800 0 PST} {4013748000 -25200 1 PDT} {4034307600 -28800 0 PST} {4045197600 -25200 1 PDT} {4065757200 -28800 0 PST} {4076647200 -25200 1 PDT} {4097206800 -28800 0 PST} } tcl8.6.5/library/tzdata/America/Santiago0000644000175000017500000000705112663660066017557 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Santiago) { {-9223372036854775808 -16966 0 LMT} {-2524504634 -16966 0 SMT} {-1892661434 -18000 0 CLT} {-1688410800 -16966 0 SMT} {-1619205434 -14400 0 CLT} {-1593806400 -16966 0 SMT} {-1335986234 -18000 0 CLT} {-1335985200 -14400 1 CLST} {-1317585600 -18000 0 CLT} {-1304362800 -14400 1 CLST} {-1286049600 -18000 0 CLT} {-1272826800 -14400 1 CLST} {-1254513600 -18000 0 CLT} {-1241290800 -14400 1 CLST} {-1222977600 -18000 0 CLT} {-1209754800 -14400 1 CLST} {-1191355200 -18000 0 CLT} {-1178132400 -14400 0 CLT} {-870552000 -18000 0 CLT} {-865278000 -14400 0 CLT} {-740520000 -10800 1 CLST} {-736376400 -14400 0 CLT} {-718056000 -18000 0 CLT} {-713649600 -14400 0 CLT} {-36619200 -10800 1 CLST} {-23922000 -14400 0 CLT} {-3355200 -10800 1 CLST} {7527600 -14400 0 CLT} {24465600 -10800 1 CLST} {37767600 -14400 0 CLT} {55915200 -10800 1 CLST} {69217200 -14400 0 CLT} {87969600 -10800 1 CLST} {100666800 -14400 0 CLT} {118209600 -10800 1 CLST} {132116400 -14400 0 CLT} {150868800 -10800 1 CLST} {163566000 -14400 0 CLT} {182318400 -10800 1 CLST} {195620400 -14400 0 CLT} {213768000 -10800 1 CLST} {227070000 -14400 0 CLT} {245217600 -10800 1 CLST} {258519600 -14400 0 CLT} {277272000 -10800 1 CLST} {289969200 -14400 0 CLT} {308721600 -10800 1 CLST} {321418800 -14400 0 CLT} {340171200 -10800 1 CLST} {353473200 -14400 0 CLT} {371620800 -10800 1 CLST} {384922800 -14400 0 CLT} {403070400 -10800 1 CLST} {416372400 -14400 0 CLT} {434520000 -10800 1 CLST} {447822000 -14400 0 CLT} {466574400 -10800 1 CLST} {479271600 -14400 0 CLT} {498024000 -10800 1 CLST} {510721200 -14400 0 CLT} {529473600 -10800 1 CLST} {545194800 -14400 0 CLT} {560923200 -10800 1 CLST} {574225200 -14400 0 CLT} {592372800 -10800 1 CLST} {605674800 -14400 0 CLT} {624427200 -10800 1 CLST} {637124400 -14400 0 CLT} {653457600 -10800 1 CLST} {668574000 -14400 0 CLT} {687326400 -10800 1 CLST} {700628400 -14400 0 CLT} {718776000 -10800 1 CLST} {732078000 -14400 0 CLT} {750225600 -10800 1 CLST} {763527600 -14400 0 CLT} {781675200 -10800 1 CLST} {794977200 -14400 0 CLT} {813729600 -10800 1 CLST} {826426800 -14400 0 CLT} {845179200 -10800 1 CLST} {859690800 -14400 0 CLT} {876628800 -10800 1 CLST} {889930800 -14400 0 CLT} {906868800 -10800 1 CLST} {923194800 -14400 0 CLT} {939528000 -10800 1 CLST} {952830000 -14400 0 CLT} {971582400 -10800 1 CLST} {984279600 -14400 0 CLT} {1003032000 -10800 1 CLST} {1015729200 -14400 0 CLT} {1034481600 -10800 1 CLST} {1047178800 -14400 0 CLT} {1065931200 -10800 1 CLST} {1079233200 -14400 0 CLT} {1097380800 -10800 1 CLST} {1110682800 -14400 0 CLT} {1128830400 -10800 1 CLST} {1142132400 -14400 0 CLT} {1160884800 -10800 1 CLST} {1173582000 -14400 0 CLT} {1192334400 -10800 1 CLST} {1206846000 -14400 0 CLT} {1223784000 -10800 1 CLST} {1237086000 -14400 0 CLT} {1255233600 -10800 1 CLST} {1270350000 -14400 0 CLT} {1286683200 -10800 1 CLST} {1304823600 -14400 0 CLT} {1313899200 -10800 1 CLST} {1335668400 -14400 0 CLT} {1346558400 -10800 1 CLST} {1367118000 -14400 0 CLT} {1378612800 -10800 1 CLST} {1398567600 -14400 0 CLT} {1410062400 -10800 1 CLST} {1430017200 -10800 0 CLT} } tcl8.6.5/library/tzdata/America/Argentina/0000755000175000017500000000000012665173607017776 5ustar sergeisergeitcl8.6.5/library/tzdata/America/Argentina/Cordoba0000644000175000017500000000372612663653132021274 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/Cordoba) { {-9223372036854775808 -15408 0 LMT} {-2372096592 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {636516000 -10800 0 ART} {656478000 -7200 1 ARST} {667965600 -14400 0 WART} {687931200 -7200 0 ARST} {699415200 -10800 0 ART} {719377200 -7200 1 ARST} {731469600 -10800 0 ART} {938916000 -10800 0 ART} {938919600 -10800 1 ARST} {952056000 -10800 0 ART} {1198983600 -7200 1 ARST} {1205632800 -10800 0 ART} {1224385200 -7200 1 ARST} {1237082400 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Argentina/La_Rioja0000644000175000017500000000402312663653132021372 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/La_Rioja) { {-9223372036854775808 -16044 0 LMT} {-2372095956 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {636516000 -10800 0 ART} {656478000 -7200 1 ARST} {667792800 -14400 0 WART} {673588800 -10800 0 ART} {687927600 -7200 1 ARST} {699415200 -10800 0 ART} {719377200 -7200 1 ARST} {731469600 -10800 0 ART} {938916000 -10800 0 ART} {938919600 -10800 1 ARST} {952056000 -10800 0 ART} {1086058800 -14400 0 WART} {1087704000 -10800 0 ART} {1198983600 -7200 1 ARST} {1205632800 -10800 0 ART} {1224295200 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Argentina/San_Luis0000644000175000017500000000400212663660066021430 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/San_Luis) { {-9223372036854775808 -15924 0 LMT} {-2372096076 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {631159200 -7200 1 ARST} {637380000 -14400 0 WART} {655963200 -10800 1 WARST} {667796400 -14400 0 WART} {675748800 -10800 0 ART} {938919600 -10800 1 WARST} {952052400 -10800 0 ART} {1085972400 -14400 0 WART} {1090728000 -10800 0 ART} {1198983600 -7200 1 ARST} {1200880800 -10800 0 WART} {1205031600 -14400 0 WART} {1223784000 -10800 1 WARST} {1236481200 -14400 0 WART} {1255233600 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Argentina/Rio_Gallegos0000644000175000017500000000377112663653132022271 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/Rio_Gallegos) { {-9223372036854775808 -16612 0 LMT} {-2372095388 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {636516000 -10800 0 ART} {656478000 -7200 1 ARST} {667965600 -10800 0 ART} {687927600 -7200 1 ARST} {699415200 -10800 0 ART} {719377200 -7200 1 ARST} {731469600 -10800 0 ART} {938916000 -10800 0 ART} {938919600 -10800 1 ARST} {952056000 -10800 0 ART} {1086058800 -14400 0 WART} {1087704000 -10800 0 ART} {1198983600 -7200 1 ARST} {1205632800 -10800 0 ART} {1224295200 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Argentina/Ushuaia0000644000175000017500000000376412663653132021324 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/Ushuaia) { {-9223372036854775808 -16392 0 LMT} {-2372095608 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {636516000 -10800 0 ART} {656478000 -7200 1 ARST} {667965600 -10800 0 ART} {687927600 -7200 1 ARST} {699415200 -10800 0 ART} {719377200 -7200 1 ARST} {731469600 -10800 0 ART} {938916000 -10800 0 ART} {938919600 -10800 1 ARST} {952056000 -10800 0 ART} {1085886000 -14400 0 WART} {1087704000 -10800 0 ART} {1198983600 -7200 1 ARST} {1205632800 -10800 0 ART} {1224295200 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Argentina/Buenos_Aires0000644000175000017500000000373212663653132022276 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/Buenos_Aires) { {-9223372036854775808 -14028 0 LMT} {-2372097972 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {636516000 -10800 0 ART} {656478000 -7200 1 ARST} {667965600 -10800 0 ART} {687927600 -7200 1 ARST} {699415200 -10800 0 ART} {719377200 -7200 1 ARST} {731469600 -10800 0 ART} {938916000 -10800 0 ART} {938919600 -10800 1 ARST} {952056000 -10800 0 ART} {1198983600 -7200 1 ARST} {1205632800 -10800 0 ART} {1224385200 -7200 1 ARST} {1237082400 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Argentina/Jujuy0000644000175000017500000000372512663653132021030 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/Jujuy) { {-9223372036854775808 -15672 0 LMT} {-2372096328 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {636516000 -14400 0 WART} {657086400 -10800 1 WARST} {669178800 -14400 0 WART} {686721600 -7200 1 ARST} {694231200 -7200 0 ART} {699415200 -10800 0 ART} {719377200 -7200 1 ARST} {731469600 -10800 0 ART} {938916000 -10800 0 ART} {938919600 -10800 1 ARST} {952056000 -10800 0 ART} {1198983600 -7200 1 ARST} {1205632800 -10800 0 ART} {1224295200 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Argentina/ComodRivadavia0000644000175000017500000000035512661614722022606 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Argentina/Catamarca)]} { LoadTimeZoneFile America/Argentina/Catamarca } set TZData(:America/Argentina/ComodRivadavia) $TZData(:America/Argentina/Catamarca) tcl8.6.5/library/tzdata/America/Argentina/Catamarca0000644000175000017500000000376712663653132021604 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/Catamarca) { {-9223372036854775808 -15788 0 LMT} {-2372096212 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {636516000 -10800 0 ART} {656478000 -7200 1 ARST} {667965600 -14400 0 WART} {687931200 -7200 0 ARST} {699415200 -10800 0 ART} {719377200 -7200 1 ARST} {731469600 -10800 0 ART} {938916000 -10800 0 ART} {938919600 -10800 1 ARST} {952056000 -10800 0 ART} {1086058800 -14400 0 WART} {1087704000 -10800 0 ART} {1198983600 -7200 1 ARST} {1205632800 -10800 0 ART} {1224295200 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Argentina/Tucuman0000644000175000017500000000402312663653132021326 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/Tucuman) { {-9223372036854775808 -15652 0 LMT} {-2372096348 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {636516000 -10800 0 ART} {656478000 -7200 1 ARST} {667965600 -14400 0 WART} {687931200 -7200 0 ARST} {699415200 -10800 0 ART} {719377200 -7200 1 ARST} {731469600 -10800 0 ART} {938916000 -10800 0 ART} {938919600 -10800 1 ARST} {952056000 -10800 0 ART} {1086058800 -14400 0 WART} {1087099200 -10800 0 ART} {1198983600 -7200 1 ARST} {1205632800 -10800 0 ART} {1224385200 -7200 1 ARST} {1237082400 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Argentina/San_Juan0000644000175000017500000000402312663653132021410 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/San_Juan) { {-9223372036854775808 -16444 0 LMT} {-2372095556 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {636516000 -10800 0 ART} {656478000 -7200 1 ARST} {667792800 -14400 0 WART} {673588800 -10800 0 ART} {687927600 -7200 1 ARST} {699415200 -10800 0 ART} {719377200 -7200 1 ARST} {731469600 -10800 0 ART} {938916000 -10800 0 ART} {938919600 -10800 1 ARST} {952056000 -10800 0 ART} {1085972400 -14400 0 WART} {1090728000 -10800 0 ART} {1198983600 -7200 1 ARST} {1205632800 -10800 0 ART} {1224295200 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Argentina/Mendoza0000644000175000017500000000377312663653132021322 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/Mendoza) { {-9223372036854775808 -16516 0 LMT} {-2372095484 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {636516000 -14400 0 WART} {655963200 -10800 1 WARST} {667796400 -14400 0 WART} {687499200 -10800 1 WARST} {699418800 -14400 0 WART} {719380800 -7200 0 ARST} {731469600 -10800 0 ART} {938916000 -10800 0 ART} {938919600 -10800 1 ARST} {952056000 -10800 0 ART} {1085281200 -14400 0 WART} {1096171200 -10800 0 ART} {1198983600 -7200 1 ARST} {1205632800 -10800 0 ART} {1224295200 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Argentina/Salta0000644000175000017500000000366612663653132020772 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Argentina/Salta) { {-9223372036854775808 -15700 0 LMT} {-2372096300 -15408 0 CMT} {-1567453392 -14400 0 ART} {-1233432000 -10800 0 ARST} {-1222981200 -14400 0 ART} {-1205956800 -10800 1 ARST} {-1194037200 -14400 0 ART} {-1172865600 -10800 1 ARST} {-1162501200 -14400 0 ART} {-1141329600 -10800 1 ARST} {-1130965200 -14400 0 ART} {-1109793600 -10800 1 ARST} {-1099429200 -14400 0 ART} {-1078257600 -10800 1 ARST} {-1067806800 -14400 0 ART} {-1046635200 -10800 1 ARST} {-1036270800 -14400 0 ART} {-1015099200 -10800 1 ARST} {-1004734800 -14400 0 ART} {-983563200 -10800 1 ARST} {-973198800 -14400 0 ART} {-952027200 -10800 1 ARST} {-941576400 -14400 0 ART} {-931032000 -10800 1 ARST} {-900882000 -14400 0 ART} {-890337600 -10800 1 ARST} {-833749200 -14400 0 ART} {-827265600 -10800 1 ARST} {-752274000 -14400 0 ART} {-733780800 -10800 1 ARST} {-197326800 -14400 0 ART} {-190843200 -10800 1 ARST} {-184194000 -14400 0 ART} {-164491200 -10800 1 ARST} {-152658000 -14400 0 ART} {-132955200 -10800 1 ARST} {-121122000 -14400 0 ART} {-101419200 -10800 1 ARST} {-86821200 -14400 0 ART} {-71092800 -10800 1 ARST} {-54766800 -14400 0 ART} {-39038400 -10800 1 ARST} {-23317200 -14400 0 ART} {-7588800 -10800 0 ART} {128142000 -7200 1 ARST} {136605600 -10800 0 ART} {596948400 -7200 1 ARST} {605066400 -10800 0 ART} {624423600 -7200 1 ARST} {636516000 -10800 0 ART} {656478000 -7200 1 ARST} {667965600 -14400 0 WART} {687931200 -7200 0 ARST} {699415200 -10800 0 ART} {719377200 -7200 1 ARST} {731469600 -10800 0 ART} {938916000 -10800 0 ART} {938919600 -10800 1 ARST} {952056000 -10800 0 ART} {1198983600 -7200 1 ARST} {1205632800 -10800 0 ART} {1224295200 -10800 0 ART} } tcl8.6.5/library/tzdata/America/Port-au-Prince0000644000175000017500000001447212663660066020564 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Port-au-Prince) { {-9223372036854775808 -17360 0 LMT} {-2524504240 -17340 0 PPMT} {-1670483460 -18000 0 EST} {421218000 -14400 1 EDT} {436334400 -18000 0 EST} {452062800 -14400 1 EDT} {467784000 -18000 0 EST} {483512400 -14400 1 EDT} {499233600 -18000 0 EST} {514962000 -14400 1 EDT} {530683200 -18000 0 EST} {546411600 -14400 1 EDT} {562132800 -18000 0 EST} {576050400 -14400 1 EDT} {594194400 -18000 0 EST} {607500000 -14400 1 EDT} {625644000 -18000 0 EST} {638949600 -14400 1 EDT} {657093600 -18000 0 EST} {671004000 -14400 1 EDT} {688543200 -18000 0 EST} {702453600 -14400 1 EDT} {719992800 -18000 0 EST} {733903200 -14400 1 EDT} {752047200 -18000 0 EST} {765352800 -14400 1 EDT} {783496800 -18000 0 EST} {796802400 -14400 1 EDT} {814946400 -18000 0 EST} {828856800 -14400 1 EDT} {846396000 -18000 0 EST} {860306400 -14400 1 EDT} {877845600 -18000 0 EST} {1112504400 -14400 1 EDT} {1130644800 -18000 0 EST} {1143954000 -14400 1 EDT} {1162094400 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Resolute0000644000175000017500000001630212663660066017613 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Resolute) { {-9223372036854775808 0 0 zzz} {-704937600 -21600 0 CST} {-147895200 -14400 1 CDDT} {-131565600 -21600 0 CST} {325670400 -18000 1 CDT} {341391600 -21600 0 CST} {357120000 -18000 1 CDT} {372841200 -21600 0 CST} {388569600 -18000 1 CDT} {404895600 -21600 0 CST} {420019200 -18000 1 CDT} {436345200 -21600 0 CST} {452073600 -18000 1 CDT} {467794800 -21600 0 CST} {483523200 -18000 1 CDT} {499244400 -21600 0 CST} {514972800 -18000 1 CDT} {530694000 -21600 0 CST} {544608000 -18000 1 CDT} {562143600 -21600 0 CST} {576057600 -18000 1 CDT} {594198000 -21600 0 CST} {607507200 -18000 1 CDT} {625647600 -21600 0 CST} {638956800 -18000 1 CDT} {657097200 -21600 0 CST} {671011200 -18000 1 CDT} {688546800 -21600 0 CST} {702460800 -18000 1 CDT} {719996400 -21600 0 CST} {733910400 -18000 1 CDT} {752050800 -21600 0 CST} {765360000 -18000 1 CDT} {783500400 -21600 0 CST} {796809600 -18000 1 CDT} {814950000 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972806400 -18000 0 EST} {986112000 -18000 0 CDT} {1004252400 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162108800 -18000 0 EST} {1173600000 -18000 0 CDT} {1194159600 -21600 0 CST} {1205049600 -18000 1 CDT} {1225609200 -21600 0 CST} {1236499200 -18000 1 CDT} {1257058800 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Rankin_Inlet0000644000175000017500000001630612661614721020365 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Rankin_Inlet) { {-9223372036854775808 0 0 zzz} {-410227200 -21600 0 CST} {-147895200 -14400 1 CDDT} {-131565600 -21600 0 CST} {325670400 -18000 1 CDT} {341391600 -21600 0 CST} {357120000 -18000 1 CDT} {372841200 -21600 0 CST} {388569600 -18000 1 CDT} {404895600 -21600 0 CST} {420019200 -18000 1 CDT} {436345200 -21600 0 CST} {452073600 -18000 1 CDT} {467794800 -21600 0 CST} {483523200 -18000 1 CDT} {499244400 -21600 0 CST} {514972800 -18000 1 CDT} {530694000 -21600 0 CST} {544608000 -18000 1 CDT} {562143600 -21600 0 CST} {576057600 -18000 1 CDT} {594198000 -21600 0 CST} {607507200 -18000 1 CDT} {625647600 -21600 0 CST} {638956800 -18000 1 CDT} {657097200 -21600 0 CST} {671011200 -18000 1 CDT} {688546800 -21600 0 CST} {702460800 -18000 1 CDT} {719996400 -21600 0 CST} {733910400 -18000 1 CDT} {752050800 -21600 0 CST} {765360000 -18000 1 CDT} {783500400 -21600 0 CST} {796809600 -18000 1 CDT} {814950000 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972806400 -18000 0 EST} {986112000 -18000 0 CDT} {1004252400 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194159600 -21600 0 CST} {1205049600 -18000 1 CDT} {1225609200 -21600 0 CST} {1236499200 -18000 1 CDT} {1257058800 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Barbados0000644000175000017500000000063512663660066017530 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Barbados) { {-9223372036854775808 -14309 0 LMT} {-1451678491 -14309 0 BMT} {-1199217691 -14400 0 AST} {234943200 -10800 1 ADT} {244616400 -14400 0 AST} {261554400 -10800 1 ADT} {276066000 -14400 0 AST} {293004000 -10800 1 ADT} {307515600 -14400 0 AST} {325058400 -10800 1 ADT} {338706000 -14400 0 AST} } tcl8.6.5/library/tzdata/America/Yellowknife0000644000175000017500000001647512661614721020307 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Yellowknife) { {-9223372036854775808 0 0 zzz} {-1104537600 -25200 0 MST} {-880210800 -21600 1 MWT} {-769395600 -21600 1 MPT} {-765388800 -25200 0 MST} {-147891600 -18000 1 MDDT} {-131562000 -25200 0 MST} {315558000 -25200 0 MST} {325674000 -21600 1 MDT} {341395200 -25200 0 MST} {357123600 -21600 1 MDT} {372844800 -25200 0 MST} {388573200 -21600 1 MDT} {404899200 -25200 0 MST} {420022800 -21600 1 MDT} {436348800 -25200 0 MST} {452077200 -21600 1 MDT} {467798400 -25200 0 MST} {483526800 -21600 1 MDT} {499248000 -25200 0 MST} {514976400 -21600 1 MDT} {530697600 -25200 0 MST} {544611600 -21600 1 MDT} {562147200 -25200 0 MST} {576061200 -21600 1 MDT} {594201600 -25200 0 MST} {607510800 -21600 1 MDT} {625651200 -25200 0 MST} {638960400 -21600 1 MDT} {657100800 -25200 0 MST} {671014800 -21600 1 MDT} {688550400 -25200 0 MST} {702464400 -21600 1 MDT} {720000000 -25200 0 MST} {733914000 -21600 1 MDT} {752054400 -25200 0 MST} {765363600 -21600 1 MDT} {783504000 -25200 0 MST} {796813200 -21600 1 MDT} {814953600 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {986115600 -21600 1 MDT} {1004256000 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1173603600 -21600 1 MDT} {1194163200 -25200 0 MST} {1205053200 -21600 1 MDT} {1225612800 -25200 0 MST} {1236502800 -21600 1 MDT} {1257062400 -25200 0 MST} {1268557200 -21600 1 MDT} {1289116800 -25200 0 MST} {1300006800 -21600 1 MDT} {1320566400 -25200 0 MST} {1331456400 -21600 1 MDT} {1352016000 -25200 0 MST} {1362906000 -21600 1 MDT} {1383465600 -25200 0 MST} {1394355600 -21600 1 MDT} {1414915200 -25200 0 MST} {1425805200 -21600 1 MDT} {1446364800 -25200 0 MST} {1457859600 -21600 1 MDT} {1478419200 -25200 0 MST} {1489309200 -21600 1 MDT} {1509868800 -25200 0 MST} {1520758800 -21600 1 MDT} {1541318400 -25200 0 MST} {1552208400 -21600 1 MDT} {1572768000 -25200 0 MST} {1583658000 -21600 1 MDT} {1604217600 -25200 0 MST} {1615712400 -21600 1 MDT} {1636272000 -25200 0 MST} {1647162000 -21600 1 MDT} {1667721600 -25200 0 MST} {1678611600 -21600 1 MDT} {1699171200 -25200 0 MST} {1710061200 -21600 1 MDT} {1730620800 -25200 0 MST} {1741510800 -21600 1 MDT} {1762070400 -25200 0 MST} {1772960400 -21600 1 MDT} {1793520000 -25200 0 MST} {1805014800 -21600 1 MDT} {1825574400 -25200 0 MST} {1836464400 -21600 1 MDT} {1857024000 -25200 0 MST} {1867914000 -21600 1 MDT} {1888473600 -25200 0 MST} {1899363600 -21600 1 MDT} {1919923200 -25200 0 MST} {1930813200 -21600 1 MDT} {1951372800 -25200 0 MST} {1962867600 -21600 1 MDT} {1983427200 -25200 0 MST} {1994317200 -21600 1 MDT} {2014876800 -25200 0 MST} {2025766800 -21600 1 MDT} {2046326400 -25200 0 MST} {2057216400 -21600 1 MDT} {2077776000 -25200 0 MST} {2088666000 -21600 1 MDT} {2109225600 -25200 0 MST} {2120115600 -21600 1 MDT} {2140675200 -25200 0 MST} {2152170000 -21600 1 MDT} {2172729600 -25200 0 MST} {2183619600 -21600 1 MDT} {2204179200 -25200 0 MST} {2215069200 -21600 1 MDT} {2235628800 -25200 0 MST} {2246518800 -21600 1 MDT} {2267078400 -25200 0 MST} {2277968400 -21600 1 MDT} {2298528000 -25200 0 MST} {2309418000 -21600 1 MDT} {2329977600 -25200 0 MST} {2341472400 -21600 1 MDT} {2362032000 -25200 0 MST} {2372922000 -21600 1 MDT} {2393481600 -25200 0 MST} {2404371600 -21600 1 MDT} {2424931200 -25200 0 MST} {2435821200 -21600 1 MDT} {2456380800 -25200 0 MST} {2467270800 -21600 1 MDT} {2487830400 -25200 0 MST} {2499325200 -21600 1 MDT} {2519884800 -25200 0 MST} {2530774800 -21600 1 MDT} {2551334400 -25200 0 MST} {2562224400 -21600 1 MDT} {2582784000 -25200 0 MST} {2593674000 -21600 1 MDT} {2614233600 -25200 0 MST} {2625123600 -21600 1 MDT} {2645683200 -25200 0 MST} {2656573200 -21600 1 MDT} {2677132800 -25200 0 MST} {2688627600 -21600 1 MDT} {2709187200 -25200 0 MST} {2720077200 -21600 1 MDT} {2740636800 -25200 0 MST} {2751526800 -21600 1 MDT} {2772086400 -25200 0 MST} {2782976400 -21600 1 MDT} {2803536000 -25200 0 MST} {2814426000 -21600 1 MDT} {2834985600 -25200 0 MST} {2846480400 -21600 1 MDT} {2867040000 -25200 0 MST} {2877930000 -21600 1 MDT} {2898489600 -25200 0 MST} {2909379600 -21600 1 MDT} {2929939200 -25200 0 MST} {2940829200 -21600 1 MDT} {2961388800 -25200 0 MST} {2972278800 -21600 1 MDT} {2992838400 -25200 0 MST} {3003728400 -21600 1 MDT} {3024288000 -25200 0 MST} {3035782800 -21600 1 MDT} {3056342400 -25200 0 MST} {3067232400 -21600 1 MDT} {3087792000 -25200 0 MST} {3098682000 -21600 1 MDT} {3119241600 -25200 0 MST} {3130131600 -21600 1 MDT} {3150691200 -25200 0 MST} {3161581200 -21600 1 MDT} {3182140800 -25200 0 MST} {3193030800 -21600 1 MDT} {3213590400 -25200 0 MST} {3225085200 -21600 1 MDT} {3245644800 -25200 0 MST} {3256534800 -21600 1 MDT} {3277094400 -25200 0 MST} {3287984400 -21600 1 MDT} {3308544000 -25200 0 MST} {3319434000 -21600 1 MDT} {3339993600 -25200 0 MST} {3350883600 -21600 1 MDT} {3371443200 -25200 0 MST} {3382938000 -21600 1 MDT} {3403497600 -25200 0 MST} {3414387600 -21600 1 MDT} {3434947200 -25200 0 MST} {3445837200 -21600 1 MDT} {3466396800 -25200 0 MST} {3477286800 -21600 1 MDT} {3497846400 -25200 0 MST} {3508736400 -21600 1 MDT} {3529296000 -25200 0 MST} {3540186000 -21600 1 MDT} {3560745600 -25200 0 MST} {3572240400 -21600 1 MDT} {3592800000 -25200 0 MST} {3603690000 -21600 1 MDT} {3624249600 -25200 0 MST} {3635139600 -21600 1 MDT} {3655699200 -25200 0 MST} {3666589200 -21600 1 MDT} {3687148800 -25200 0 MST} {3698038800 -21600 1 MDT} {3718598400 -25200 0 MST} {3730093200 -21600 1 MDT} {3750652800 -25200 0 MST} {3761542800 -21600 1 MDT} {3782102400 -25200 0 MST} {3792992400 -21600 1 MDT} {3813552000 -25200 0 MST} {3824442000 -21600 1 MDT} {3845001600 -25200 0 MST} {3855891600 -21600 1 MDT} {3876451200 -25200 0 MST} {3887341200 -21600 1 MDT} {3907900800 -25200 0 MST} {3919395600 -21600 1 MDT} {3939955200 -25200 0 MST} {3950845200 -21600 1 MDT} {3971404800 -25200 0 MST} {3982294800 -21600 1 MDT} {4002854400 -25200 0 MST} {4013744400 -21600 1 MDT} {4034304000 -25200 0 MST} {4045194000 -21600 1 MDT} {4065753600 -25200 0 MST} {4076643600 -21600 1 MDT} {4097203200 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Guyana0000644000175000017500000000035512661614720017230 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Guyana) { {-9223372036854775808 -13960 0 LMT} {-1730578040 -13500 0 GBGT} {-113688900 -13500 0 GYT} {176010300 -10800 0 GYT} {662698800 -14400 0 GYT} } tcl8.6.5/library/tzdata/America/Edmonton0000644000175000017500000002036312663660066017576 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Edmonton) { {-9223372036854775808 -27232 0 LMT} {-1998663968 -25200 0 MST} {-1632063600 -21600 1 MDT} {-1615132800 -25200 0 MST} {-1600614000 -21600 1 MDT} {-1596816000 -25200 0 MST} {-1567954800 -21600 1 MDT} {-1551628800 -25200 0 MST} {-1536505200 -21600 1 MDT} {-1523203200 -25200 0 MST} {-1504450800 -21600 1 MDT} {-1491753600 -25200 0 MST} {-1473001200 -21600 1 MDT} {-1459699200 -25200 0 MST} {-880210800 -21600 1 MWT} {-769395600 -21600 1 MPT} {-765388800 -25200 0 MST} {-715791600 -21600 1 MDT} {-702489600 -25200 0 MST} {-84380400 -21600 1 MDT} {-68659200 -25200 0 MST} {-21481200 -21600 1 MDT} {-5760000 -25200 0 MST} {73472400 -21600 1 MDT} {89193600 -25200 0 MST} {104922000 -21600 1 MDT} {120643200 -25200 0 MST} {136371600 -21600 1 MDT} {152092800 -25200 0 MST} {167821200 -21600 1 MDT} {183542400 -25200 0 MST} {199270800 -21600 1 MDT} {215596800 -25200 0 MST} {230720400 -21600 1 MDT} {247046400 -25200 0 MST} {262774800 -21600 1 MDT} {278496000 -25200 0 MST} {294224400 -21600 1 MDT} {309945600 -25200 0 MST} {325674000 -21600 1 MDT} {341395200 -25200 0 MST} {357123600 -21600 1 MDT} {372844800 -25200 0 MST} {388573200 -21600 1 MDT} {404899200 -25200 0 MST} {420022800 -21600 1 MDT} {436348800 -25200 0 MST} {452077200 -21600 1 MDT} {467798400 -25200 0 MST} {483526800 -21600 1 MDT} {499248000 -25200 0 MST} {514976400 -21600 1 MDT} {530697600 -25200 0 MST} {536482800 -25200 0 MST} {544611600 -21600 1 MDT} {562147200 -25200 0 MST} {576061200 -21600 1 MDT} {594201600 -25200 0 MST} {607510800 -21600 1 MDT} {625651200 -25200 0 MST} {638960400 -21600 1 MDT} {657100800 -25200 0 MST} {671014800 -21600 1 MDT} {688550400 -25200 0 MST} {702464400 -21600 1 MDT} {720000000 -25200 0 MST} {733914000 -21600 1 MDT} {752054400 -25200 0 MST} {765363600 -21600 1 MDT} {783504000 -25200 0 MST} {796813200 -21600 1 MDT} {814953600 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {986115600 -21600 1 MDT} {1004256000 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1173603600 -21600 1 MDT} {1194163200 -25200 0 MST} {1205053200 -21600 1 MDT} {1225612800 -25200 0 MST} {1236502800 -21600 1 MDT} {1257062400 -25200 0 MST} {1268557200 -21600 1 MDT} {1289116800 -25200 0 MST} {1300006800 -21600 1 MDT} {1320566400 -25200 0 MST} {1331456400 -21600 1 MDT} {1352016000 -25200 0 MST} {1362906000 -21600 1 MDT} {1383465600 -25200 0 MST} {1394355600 -21600 1 MDT} {1414915200 -25200 0 MST} {1425805200 -21600 1 MDT} {1446364800 -25200 0 MST} {1457859600 -21600 1 MDT} {1478419200 -25200 0 MST} {1489309200 -21600 1 MDT} {1509868800 -25200 0 MST} {1520758800 -21600 1 MDT} {1541318400 -25200 0 MST} {1552208400 -21600 1 MDT} {1572768000 -25200 0 MST} {1583658000 -21600 1 MDT} {1604217600 -25200 0 MST} {1615712400 -21600 1 MDT} {1636272000 -25200 0 MST} {1647162000 -21600 1 MDT} {1667721600 -25200 0 MST} {1678611600 -21600 1 MDT} {1699171200 -25200 0 MST} {1710061200 -21600 1 MDT} {1730620800 -25200 0 MST} {1741510800 -21600 1 MDT} {1762070400 -25200 0 MST} {1772960400 -21600 1 MDT} {1793520000 -25200 0 MST} {1805014800 -21600 1 MDT} {1825574400 -25200 0 MST} {1836464400 -21600 1 MDT} {1857024000 -25200 0 MST} {1867914000 -21600 1 MDT} {1888473600 -25200 0 MST} {1899363600 -21600 1 MDT} {1919923200 -25200 0 MST} {1930813200 -21600 1 MDT} {1951372800 -25200 0 MST} {1962867600 -21600 1 MDT} {1983427200 -25200 0 MST} {1994317200 -21600 1 MDT} {2014876800 -25200 0 MST} {2025766800 -21600 1 MDT} {2046326400 -25200 0 MST} {2057216400 -21600 1 MDT} {2077776000 -25200 0 MST} {2088666000 -21600 1 MDT} {2109225600 -25200 0 MST} {2120115600 -21600 1 MDT} {2140675200 -25200 0 MST} {2152170000 -21600 1 MDT} {2172729600 -25200 0 MST} {2183619600 -21600 1 MDT} {2204179200 -25200 0 MST} {2215069200 -21600 1 MDT} {2235628800 -25200 0 MST} {2246518800 -21600 1 MDT} {2267078400 -25200 0 MST} {2277968400 -21600 1 MDT} {2298528000 -25200 0 MST} {2309418000 -21600 1 MDT} {2329977600 -25200 0 MST} {2341472400 -21600 1 MDT} {2362032000 -25200 0 MST} {2372922000 -21600 1 MDT} {2393481600 -25200 0 MST} {2404371600 -21600 1 MDT} {2424931200 -25200 0 MST} {2435821200 -21600 1 MDT} {2456380800 -25200 0 MST} {2467270800 -21600 1 MDT} {2487830400 -25200 0 MST} {2499325200 -21600 1 MDT} {2519884800 -25200 0 MST} {2530774800 -21600 1 MDT} {2551334400 -25200 0 MST} {2562224400 -21600 1 MDT} {2582784000 -25200 0 MST} {2593674000 -21600 1 MDT} {2614233600 -25200 0 MST} {2625123600 -21600 1 MDT} {2645683200 -25200 0 MST} {2656573200 -21600 1 MDT} {2677132800 -25200 0 MST} {2688627600 -21600 1 MDT} {2709187200 -25200 0 MST} {2720077200 -21600 1 MDT} {2740636800 -25200 0 MST} {2751526800 -21600 1 MDT} {2772086400 -25200 0 MST} {2782976400 -21600 1 MDT} {2803536000 -25200 0 MST} {2814426000 -21600 1 MDT} {2834985600 -25200 0 MST} {2846480400 -21600 1 MDT} {2867040000 -25200 0 MST} {2877930000 -21600 1 MDT} {2898489600 -25200 0 MST} {2909379600 -21600 1 MDT} {2929939200 -25200 0 MST} {2940829200 -21600 1 MDT} {2961388800 -25200 0 MST} {2972278800 -21600 1 MDT} {2992838400 -25200 0 MST} {3003728400 -21600 1 MDT} {3024288000 -25200 0 MST} {3035782800 -21600 1 MDT} {3056342400 -25200 0 MST} {3067232400 -21600 1 MDT} {3087792000 -25200 0 MST} {3098682000 -21600 1 MDT} {3119241600 -25200 0 MST} {3130131600 -21600 1 MDT} {3150691200 -25200 0 MST} {3161581200 -21600 1 MDT} {3182140800 -25200 0 MST} {3193030800 -21600 1 MDT} {3213590400 -25200 0 MST} {3225085200 -21600 1 MDT} {3245644800 -25200 0 MST} {3256534800 -21600 1 MDT} {3277094400 -25200 0 MST} {3287984400 -21600 1 MDT} {3308544000 -25200 0 MST} {3319434000 -21600 1 MDT} {3339993600 -25200 0 MST} {3350883600 -21600 1 MDT} {3371443200 -25200 0 MST} {3382938000 -21600 1 MDT} {3403497600 -25200 0 MST} {3414387600 -21600 1 MDT} {3434947200 -25200 0 MST} {3445837200 -21600 1 MDT} {3466396800 -25200 0 MST} {3477286800 -21600 1 MDT} {3497846400 -25200 0 MST} {3508736400 -21600 1 MDT} {3529296000 -25200 0 MST} {3540186000 -21600 1 MDT} {3560745600 -25200 0 MST} {3572240400 -21600 1 MDT} {3592800000 -25200 0 MST} {3603690000 -21600 1 MDT} {3624249600 -25200 0 MST} {3635139600 -21600 1 MDT} {3655699200 -25200 0 MST} {3666589200 -21600 1 MDT} {3687148800 -25200 0 MST} {3698038800 -21600 1 MDT} {3718598400 -25200 0 MST} {3730093200 -21600 1 MDT} {3750652800 -25200 0 MST} {3761542800 -21600 1 MDT} {3782102400 -25200 0 MST} {3792992400 -21600 1 MDT} {3813552000 -25200 0 MST} {3824442000 -21600 1 MDT} {3845001600 -25200 0 MST} {3855891600 -21600 1 MDT} {3876451200 -25200 0 MST} {3887341200 -21600 1 MDT} {3907900800 -25200 0 MST} {3919395600 -21600 1 MDT} {3939955200 -25200 0 MST} {3950845200 -21600 1 MDT} {3971404800 -25200 0 MST} {3982294800 -21600 1 MDT} {4002854400 -25200 0 MST} {4013744400 -21600 1 MDT} {4034304000 -25200 0 MST} {4045194000 -21600 1 MDT} {4065753600 -25200 0 MST} {4076643600 -21600 1 MDT} {4097203200 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Tijuana0000644000175000017500000002042612663653207017405 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Tijuana) { {-9223372036854775808 -28084 0 LMT} {-1514736000 -25200 0 MST} {-1451667600 -28800 0 PST} {-1343062800 -25200 0 MST} {-1234803600 -28800 0 PST} {-1222963200 -25200 1 PDT} {-1207242000 -28800 0 PST} {-873820800 -25200 1 PWT} {-769395600 -25200 1 PPT} {-761677200 -28800 0 PST} {-686073600 -25200 1 PDT} {-661539600 -28800 0 PST} {-504892800 -28800 0 PST} {-495036000 -25200 1 PDT} {-481734000 -28800 0 PST} {-463586400 -25200 1 PDT} {-450284400 -28800 0 PST} {-431532000 -25200 1 PDT} {-418230000 -28800 0 PST} {-400082400 -25200 1 PDT} {-386780400 -28800 0 PST} {-368632800 -25200 1 PDT} {-355330800 -28800 0 PST} {-337183200 -25200 1 PDT} {-323881200 -28800 0 PST} {-305733600 -25200 1 PDT} {-292431600 -28800 0 PST} {-283968000 -28800 0 PST} {189331200 -28800 0 PST} {199274400 -25200 1 PDT} {215600400 -28800 0 PST} {230724000 -25200 1 PDT} {247050000 -28800 0 PST} {262778400 -25200 1 PDT} {278499600 -28800 0 PST} {294228000 -25200 1 PDT} {309949200 -28800 0 PST} {325677600 -25200 1 PDT} {341398800 -28800 0 PST} {357127200 -25200 1 PDT} {372848400 -28800 0 PST} {388576800 -25200 1 PDT} {404902800 -28800 0 PST} {420026400 -25200 1 PDT} {436352400 -28800 0 PST} {452080800 -25200 1 PDT} {467802000 -28800 0 PST} {483530400 -25200 1 PDT} {499251600 -28800 0 PST} {514980000 -25200 1 PDT} {530701200 -28800 0 PST} {544615200 -25200 1 PDT} {562150800 -28800 0 PST} {576064800 -25200 1 PDT} {594205200 -28800 0 PST} {607514400 -25200 1 PDT} {625654800 -28800 0 PST} {638964000 -25200 1 PDT} {657104400 -28800 0 PST} {671018400 -25200 1 PDT} {688554000 -28800 0 PST} {702468000 -25200 1 PDT} {720003600 -28800 0 PST} {733917600 -25200 1 PDT} {752058000 -28800 0 PST} {765367200 -25200 1 PDT} {783507600 -28800 0 PST} {796816800 -25200 1 PDT} {814957200 -28800 0 PST} {820483200 -28800 0 PST} {828871200 -25200 1 PDT} {846406800 -28800 0 PST} {860320800 -25200 1 PDT} {877856400 -28800 0 PST} {891770400 -25200 1 PDT} {909306000 -28800 0 PST} {923220000 -25200 1 PDT} {941360400 -28800 0 PST} {954669600 -25200 1 PDT} {972810000 -28800 0 PST} {978336000 -28800 0 PST} {986119200 -25200 1 PDT} {1004259600 -28800 0 PST} {1014192000 -28800 0 PST} {1018173600 -25200 1 PDT} {1035709200 -28800 0 PST} {1049623200 -25200 1 PDT} {1067158800 -28800 0 PST} {1081072800 -25200 1 PDT} {1099213200 -28800 0 PST} {1112522400 -25200 1 PDT} {1130662800 -28800 0 PST} {1143972000 -25200 1 PDT} {1162112400 -28800 0 PST} {1175421600 -25200 1 PDT} {1193562000 -28800 0 PST} {1207476000 -25200 1 PDT} {1225011600 -28800 0 PST} {1238925600 -25200 1 PDT} {1256461200 -28800 0 PST} {1262332800 -28800 0 PST} {1268560800 -25200 1 PDT} {1289120400 -28800 0 PST} {1300010400 -25200 1 PDT} {1320570000 -28800 0 PST} {1331460000 -25200 1 PDT} {1352019600 -28800 0 PST} {1362909600 -25200 1 PDT} {1383469200 -28800 0 PST} {1394359200 -25200 1 PDT} {1414918800 -28800 0 PST} {1425808800 -25200 1 PDT} {1446368400 -28800 0 PST} {1457863200 -25200 1 PDT} {1478422800 -28800 0 PST} {1489312800 -25200 1 PDT} {1509872400 -28800 0 PST} {1520762400 -25200 1 PDT} {1541322000 -28800 0 PST} {1552212000 -25200 1 PDT} {1572771600 -28800 0 PST} {1583661600 -25200 1 PDT} {1604221200 -28800 0 PST} {1615716000 -25200 1 PDT} {1636275600 -28800 0 PST} {1647165600 -25200 1 PDT} {1667725200 -28800 0 PST} {1678615200 -25200 1 PDT} {1699174800 -28800 0 PST} {1710064800 -25200 1 PDT} {1730624400 -28800 0 PST} {1741514400 -25200 1 PDT} {1762074000 -28800 0 PST} {1772964000 -25200 1 PDT} {1793523600 -28800 0 PST} {1805018400 -25200 1 PDT} {1825578000 -28800 0 PST} {1836468000 -25200 1 PDT} {1857027600 -28800 0 PST} {1867917600 -25200 1 PDT} {1888477200 -28800 0 PST} {1899367200 -25200 1 PDT} {1919926800 -28800 0 PST} {1930816800 -25200 1 PDT} {1951376400 -28800 0 PST} {1962871200 -25200 1 PDT} {1983430800 -28800 0 PST} {1994320800 -25200 1 PDT} {2014880400 -28800 0 PST} {2025770400 -25200 1 PDT} {2046330000 -28800 0 PST} {2057220000 -25200 1 PDT} {2077779600 -28800 0 PST} {2088669600 -25200 1 PDT} {2109229200 -28800 0 PST} {2120119200 -25200 1 PDT} {2140678800 -28800 0 PST} {2152173600 -25200 1 PDT} {2172733200 -28800 0 PST} {2183623200 -25200 1 PDT} {2204182800 -28800 0 PST} {2215072800 -25200 1 PDT} {2235632400 -28800 0 PST} {2246522400 -25200 1 PDT} {2267082000 -28800 0 PST} {2277972000 -25200 1 PDT} {2298531600 -28800 0 PST} {2309421600 -25200 1 PDT} {2329981200 -28800 0 PST} {2341476000 -25200 1 PDT} {2362035600 -28800 0 PST} {2372925600 -25200 1 PDT} {2393485200 -28800 0 PST} {2404375200 -25200 1 PDT} {2424934800 -28800 0 PST} {2435824800 -25200 1 PDT} {2456384400 -28800 0 PST} {2467274400 -25200 1 PDT} {2487834000 -28800 0 PST} {2499328800 -25200 1 PDT} {2519888400 -28800 0 PST} {2530778400 -25200 1 PDT} {2551338000 -28800 0 PST} {2562228000 -25200 1 PDT} {2582787600 -28800 0 PST} {2593677600 -25200 1 PDT} {2614237200 -28800 0 PST} {2625127200 -25200 1 PDT} {2645686800 -28800 0 PST} {2656576800 -25200 1 PDT} {2677136400 -28800 0 PST} {2688631200 -25200 1 PDT} {2709190800 -28800 0 PST} {2720080800 -25200 1 PDT} {2740640400 -28800 0 PST} {2751530400 -25200 1 PDT} {2772090000 -28800 0 PST} {2782980000 -25200 1 PDT} {2803539600 -28800 0 PST} {2814429600 -25200 1 PDT} {2834989200 -28800 0 PST} {2846484000 -25200 1 PDT} {2867043600 -28800 0 PST} {2877933600 -25200 1 PDT} {2898493200 -28800 0 PST} {2909383200 -25200 1 PDT} {2929942800 -28800 0 PST} {2940832800 -25200 1 PDT} {2961392400 -28800 0 PST} {2972282400 -25200 1 PDT} {2992842000 -28800 0 PST} {3003732000 -25200 1 PDT} {3024291600 -28800 0 PST} {3035786400 -25200 1 PDT} {3056346000 -28800 0 PST} {3067236000 -25200 1 PDT} {3087795600 -28800 0 PST} {3098685600 -25200 1 PDT} {3119245200 -28800 0 PST} {3130135200 -25200 1 PDT} {3150694800 -28800 0 PST} {3161584800 -25200 1 PDT} {3182144400 -28800 0 PST} {3193034400 -25200 1 PDT} {3213594000 -28800 0 PST} {3225088800 -25200 1 PDT} {3245648400 -28800 0 PST} {3256538400 -25200 1 PDT} {3277098000 -28800 0 PST} {3287988000 -25200 1 PDT} {3308547600 -28800 0 PST} {3319437600 -25200 1 PDT} {3339997200 -28800 0 PST} {3350887200 -25200 1 PDT} {3371446800 -28800 0 PST} {3382941600 -25200 1 PDT} {3403501200 -28800 0 PST} {3414391200 -25200 1 PDT} {3434950800 -28800 0 PST} {3445840800 -25200 1 PDT} {3466400400 -28800 0 PST} {3477290400 -25200 1 PDT} {3497850000 -28800 0 PST} {3508740000 -25200 1 PDT} {3529299600 -28800 0 PST} {3540189600 -25200 1 PDT} {3560749200 -28800 0 PST} {3572244000 -25200 1 PDT} {3592803600 -28800 0 PST} {3603693600 -25200 1 PDT} {3624253200 -28800 0 PST} {3635143200 -25200 1 PDT} {3655702800 -28800 0 PST} {3666592800 -25200 1 PDT} {3687152400 -28800 0 PST} {3698042400 -25200 1 PDT} {3718602000 -28800 0 PST} {3730096800 -25200 1 PDT} {3750656400 -28800 0 PST} {3761546400 -25200 1 PDT} {3782106000 -28800 0 PST} {3792996000 -25200 1 PDT} {3813555600 -28800 0 PST} {3824445600 -25200 1 PDT} {3845005200 -28800 0 PST} {3855895200 -25200 1 PDT} {3876454800 -28800 0 PST} {3887344800 -25200 1 PDT} {3907904400 -28800 0 PST} {3919399200 -25200 1 PDT} {3939958800 -28800 0 PST} {3950848800 -25200 1 PDT} {3971408400 -28800 0 PST} {3982298400 -25200 1 PDT} {4002858000 -28800 0 PST} {4013748000 -25200 1 PDT} {4034307600 -28800 0 PST} {4045197600 -25200 1 PDT} {4065757200 -28800 0 PST} {4076647200 -25200 1 PDT} {4097206800 -28800 0 PST} } tcl8.6.5/library/tzdata/America/St_Johns0000644000175000017500000002524512663660066017546 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/St_Johns) { {-9223372036854775808 -12652 0 LMT} {-2713897748 -12652 0 NST} {-1664130548 -9052 1 NDT} {-1650137348 -12652 0 NST} {-1640982548 -12652 0 NST} {-1632076148 -9052 1 NDT} {-1615145348 -12652 0 NST} {-1609446548 -12652 0 NST} {-1598650148 -9052 1 NDT} {-1590100148 -12652 0 NST} {-1567286948 -9052 1 NDT} {-1551565748 -12652 0 NST} {-1535837348 -9052 1 NDT} {-1520116148 -12652 0 NST} {-1503782948 -9052 1 NDT} {-1488666548 -12652 0 NST} {-1472333348 -9052 1 NDT} {-1457216948 -12652 0 NST} {-1440883748 -9052 1 NDT} {-1425767348 -12652 0 NST} {-1409434148 -9052 1 NDT} {-1394317748 -12652 0 NST} {-1377984548 -9052 1 NDT} {-1362263348 -12652 0 NST} {-1346534948 -9052 1 NDT} {-1330813748 -12652 0 NST} {-1314480548 -9052 1 NDT} {-1299364148 -12652 0 NST} {-1283030948 -9052 1 NDT} {-1267914548 -12652 0 NST} {-1251581348 -9052 1 NDT} {-1236464948 -12652 0 NST} {-1220131748 -9052 1 NDT} {-1205015348 -12652 0 NST} {-1188682148 -9052 1 NDT} {-1172960948 -12652 0 NST} {-1156627748 -9052 1 NDT} {-1141511348 -12652 0 NST} {-1125178148 -9052 1 NDT} {-1110061748 -12652 0 NST} {-1096921748 -12600 0 NST} {-1093728600 -9000 1 NDT} {-1078612200 -12600 0 NST} {-1061670600 -9000 1 NDT} {-1048973400 -12600 0 NST} {-1030221000 -9000 1 NDT} {-1017523800 -12600 0 NST} {-998771400 -9000 1 NDT} {-986074200 -12600 0 NST} {-966717000 -9000 1 NDT} {-954624600 -12600 0 NST} {-935267400 -9000 1 NDT} {-922570200 -12600 0 NST} {-903817800 -9000 1 NDT} {-891120600 -12600 0 NST} {-872368200 -9000 0 NWT} {-769395600 -9000 1 NPT} {-765401400 -12600 0 NST} {-757369800 -12600 0 NST} {-746044200 -9000 1 NDT} {-733347000 -12600 0 NST} {-714594600 -9000 1 NDT} {-701897400 -12600 0 NST} {-683145000 -9000 1 NDT} {-670447800 -12600 0 NST} {-651695400 -9000 1 NDT} {-638998200 -12600 0 NST} {-619641000 -9000 1 NDT} {-606943800 -12600 0 NST} {-589401000 -9000 1 NDT} {-576099000 -12600 0 NST} {-557951400 -9000 1 NDT} {-544649400 -12600 0 NST} {-526501800 -9000 1 NDT} {-513199800 -12600 0 NST} {-495052200 -9000 1 NDT} {-481750200 -12600 0 NST} {-463602600 -9000 1 NDT} {-450300600 -12600 0 NST} {-431548200 -9000 1 NDT} {-418246200 -12600 0 NST} {-400098600 -9000 1 NDT} {-386796600 -12600 0 NST} {-368649000 -9000 1 NDT} {-355347000 -12600 0 NST} {-337199400 -9000 1 NDT} {-323897400 -12600 0 NST} {-305749800 -9000 1 NDT} {-289423800 -12600 0 NST} {-273695400 -9000 1 NDT} {-257974200 -12600 0 NST} {-242245800 -9000 1 NDT} {-226524600 -12600 0 NST} {-210796200 -9000 1 NDT} {-195075000 -12600 0 NST} {-179346600 -9000 1 NDT} {-163625400 -12600 0 NST} {-147897000 -9000 1 NDT} {-131571000 -12600 0 NST} {-116447400 -9000 1 NDT} {-100121400 -12600 0 NST} {-84393000 -9000 1 NDT} {-68671800 -12600 0 NST} {-52943400 -9000 1 NDT} {-37222200 -12600 0 NST} {-21493800 -9000 1 NDT} {-5772600 -12600 0 NST} {9955800 -9000 1 NDT} {25677000 -12600 0 NST} {41405400 -9000 1 NDT} {57731400 -12600 0 NST} {73459800 -9000 1 NDT} {89181000 -12600 0 NST} {104909400 -9000 1 NDT} {120630600 -12600 0 NST} {136359000 -9000 1 NDT} {152080200 -12600 0 NST} {167808600 -9000 1 NDT} {183529800 -12600 0 NST} {199258200 -9000 1 NDT} {215584200 -12600 0 NST} {230707800 -9000 1 NDT} {247033800 -12600 0 NST} {262762200 -9000 1 NDT} {278483400 -12600 0 NST} {294211800 -9000 1 NDT} {309933000 -12600 0 NST} {325661400 -9000 1 NDT} {341382600 -12600 0 NST} {357111000 -9000 1 NDT} {372832200 -12600 0 NST} {388560600 -9000 1 NDT} {404886600 -12600 0 NST} {420010200 -9000 1 NDT} {436336200 -12600 0 NST} {452064600 -9000 1 NDT} {467785800 -12600 0 NST} {483514200 -9000 1 NDT} {499235400 -12600 0 NST} {514963800 -9000 1 NDT} {530685000 -12600 0 NST} {544591860 -9000 1 NDT} {562127460 -12600 0 NST} {576041460 -5400 1 NDDT} {594178260 -12600 0 NST} {607491060 -9000 1 NDT} {625631460 -12600 0 NST} {638940660 -9000 1 NDT} {657081060 -12600 0 NST} {670995060 -9000 1 NDT} {688530660 -12600 0 NST} {702444660 -9000 1 NDT} {719980260 -12600 0 NST} {733894260 -9000 1 NDT} {752034660 -12600 0 NST} {765343860 -9000 1 NDT} {783484260 -12600 0 NST} {796793460 -9000 1 NDT} {814933860 -12600 0 NST} {828847860 -9000 1 NDT} {846383460 -12600 0 NST} {860297460 -9000 1 NDT} {877833060 -12600 0 NST} {891747060 -9000 1 NDT} {909282660 -12600 0 NST} {923196660 -9000 1 NDT} {941337060 -12600 0 NST} {954646260 -9000 1 NDT} {972786660 -12600 0 NST} {986095860 -9000 1 NDT} {1004236260 -12600 0 NST} {1018150260 -9000 1 NDT} {1035685860 -12600 0 NST} {1049599860 -9000 1 NDT} {1067135460 -12600 0 NST} {1081049460 -9000 1 NDT} {1099189860 -12600 0 NST} {1112499060 -9000 1 NDT} {1130639460 -12600 0 NST} {1143948660 -9000 1 NDT} {1162089060 -12600 0 NST} {1173583860 -9000 1 NDT} {1194143460 -12600 0 NST} {1205033460 -9000 1 NDT} {1225593060 -12600 0 NST} {1236483060 -9000 1 NDT} {1257042660 -12600 0 NST} {1268537460 -9000 1 NDT} {1289097060 -12600 0 NST} {1299987060 -9000 1 NDT} {1320114600 -9000 0 NDT} {1320553800 -12600 0 NST} {1331443800 -9000 1 NDT} {1352003400 -12600 0 NST} {1362893400 -9000 1 NDT} {1383453000 -12600 0 NST} {1394343000 -9000 1 NDT} {1414902600 -12600 0 NST} {1425792600 -9000 1 NDT} {1446352200 -12600 0 NST} {1457847000 -9000 1 NDT} {1478406600 -12600 0 NST} {1489296600 -9000 1 NDT} {1509856200 -12600 0 NST} {1520746200 -9000 1 NDT} {1541305800 -12600 0 NST} {1552195800 -9000 1 NDT} {1572755400 -12600 0 NST} {1583645400 -9000 1 NDT} {1604205000 -12600 0 NST} {1615699800 -9000 1 NDT} {1636259400 -12600 0 NST} {1647149400 -9000 1 NDT} {1667709000 -12600 0 NST} {1678599000 -9000 1 NDT} {1699158600 -12600 0 NST} {1710048600 -9000 1 NDT} {1730608200 -12600 0 NST} {1741498200 -9000 1 NDT} {1762057800 -12600 0 NST} {1772947800 -9000 1 NDT} {1793507400 -12600 0 NST} {1805002200 -9000 1 NDT} {1825561800 -12600 0 NST} {1836451800 -9000 1 NDT} {1857011400 -12600 0 NST} {1867901400 -9000 1 NDT} {1888461000 -12600 0 NST} {1899351000 -9000 1 NDT} {1919910600 -12600 0 NST} {1930800600 -9000 1 NDT} {1951360200 -12600 0 NST} {1962855000 -9000 1 NDT} {1983414600 -12600 0 NST} {1994304600 -9000 1 NDT} {2014864200 -12600 0 NST} {2025754200 -9000 1 NDT} {2046313800 -12600 0 NST} {2057203800 -9000 1 NDT} {2077763400 -12600 0 NST} {2088653400 -9000 1 NDT} {2109213000 -12600 0 NST} {2120103000 -9000 1 NDT} {2140662600 -12600 0 NST} {2152157400 -9000 1 NDT} {2172717000 -12600 0 NST} {2183607000 -9000 1 NDT} {2204166600 -12600 0 NST} {2215056600 -9000 1 NDT} {2235616200 -12600 0 NST} {2246506200 -9000 1 NDT} {2267065800 -12600 0 NST} {2277955800 -9000 1 NDT} {2298515400 -12600 0 NST} {2309405400 -9000 1 NDT} {2329965000 -12600 0 NST} {2341459800 -9000 1 NDT} {2362019400 -12600 0 NST} {2372909400 -9000 1 NDT} {2393469000 -12600 0 NST} {2404359000 -9000 1 NDT} {2424918600 -12600 0 NST} {2435808600 -9000 1 NDT} {2456368200 -12600 0 NST} {2467258200 -9000 1 NDT} {2487817800 -12600 0 NST} {2499312600 -9000 1 NDT} {2519872200 -12600 0 NST} {2530762200 -9000 1 NDT} {2551321800 -12600 0 NST} {2562211800 -9000 1 NDT} {2582771400 -12600 0 NST} {2593661400 -9000 1 NDT} {2614221000 -12600 0 NST} {2625111000 -9000 1 NDT} {2645670600 -12600 0 NST} {2656560600 -9000 1 NDT} {2677120200 -12600 0 NST} {2688615000 -9000 1 NDT} {2709174600 -12600 0 NST} {2720064600 -9000 1 NDT} {2740624200 -12600 0 NST} {2751514200 -9000 1 NDT} {2772073800 -12600 0 NST} {2782963800 -9000 1 NDT} {2803523400 -12600 0 NST} {2814413400 -9000 1 NDT} {2834973000 -12600 0 NST} {2846467800 -9000 1 NDT} {2867027400 -12600 0 NST} {2877917400 -9000 1 NDT} {2898477000 -12600 0 NST} {2909367000 -9000 1 NDT} {2929926600 -12600 0 NST} {2940816600 -9000 1 NDT} {2961376200 -12600 0 NST} {2972266200 -9000 1 NDT} {2992825800 -12600 0 NST} {3003715800 -9000 1 NDT} {3024275400 -12600 0 NST} {3035770200 -9000 1 NDT} {3056329800 -12600 0 NST} {3067219800 -9000 1 NDT} {3087779400 -12600 0 NST} {3098669400 -9000 1 NDT} {3119229000 -12600 0 NST} {3130119000 -9000 1 NDT} {3150678600 -12600 0 NST} {3161568600 -9000 1 NDT} {3182128200 -12600 0 NST} {3193018200 -9000 1 NDT} {3213577800 -12600 0 NST} {3225072600 -9000 1 NDT} {3245632200 -12600 0 NST} {3256522200 -9000 1 NDT} {3277081800 -12600 0 NST} {3287971800 -9000 1 NDT} {3308531400 -12600 0 NST} {3319421400 -9000 1 NDT} {3339981000 -12600 0 NST} {3350871000 -9000 1 NDT} {3371430600 -12600 0 NST} {3382925400 -9000 1 NDT} {3403485000 -12600 0 NST} {3414375000 -9000 1 NDT} {3434934600 -12600 0 NST} {3445824600 -9000 1 NDT} {3466384200 -12600 0 NST} {3477274200 -9000 1 NDT} {3497833800 -12600 0 NST} {3508723800 -9000 1 NDT} {3529283400 -12600 0 NST} {3540173400 -9000 1 NDT} {3560733000 -12600 0 NST} {3572227800 -9000 1 NDT} {3592787400 -12600 0 NST} {3603677400 -9000 1 NDT} {3624237000 -12600 0 NST} {3635127000 -9000 1 NDT} {3655686600 -12600 0 NST} {3666576600 -9000 1 NDT} {3687136200 -12600 0 NST} {3698026200 -9000 1 NDT} {3718585800 -12600 0 NST} {3730080600 -9000 1 NDT} {3750640200 -12600 0 NST} {3761530200 -9000 1 NDT} {3782089800 -12600 0 NST} {3792979800 -9000 1 NDT} {3813539400 -12600 0 NST} {3824429400 -9000 1 NDT} {3844989000 -12600 0 NST} {3855879000 -9000 1 NDT} {3876438600 -12600 0 NST} {3887328600 -9000 1 NDT} {3907888200 -12600 0 NST} {3919383000 -9000 1 NDT} {3939942600 -12600 0 NST} {3950832600 -9000 1 NDT} {3971392200 -12600 0 NST} {3982282200 -9000 1 NDT} {4002841800 -12600 0 NST} {4013731800 -9000 1 NDT} {4034291400 -12600 0 NST} {4045181400 -9000 1 NDT} {4065741000 -12600 0 NST} {4076631000 -9000 1 NDT} {4097190600 -12600 0 NST} } tcl8.6.5/library/tzdata/America/Santo_Domingo0000644000175000017500000000111612661614721020541 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Santo_Domingo) { {-9223372036854775808 -16776 0 LMT} {-2524504824 -16800 0 SDMT} {-1159773600 -18000 0 EST} {-100119600 -14400 1 EDT} {-89668800 -18000 0 EST} {-5770800 -16200 1 EHDT} {4422600 -18000 0 EST} {25678800 -16200 1 EHDT} {33193800 -18000 0 EST} {57733200 -16200 1 EHDT} {64816200 -18000 0 EST} {89182800 -16200 1 EHDT} {96438600 -18000 0 EST} {120632400 -16200 1 EHDT} {127974600 -18000 0 EST} {152082000 -14400 0 AST} {975823200 -14400 0 AST} } tcl8.6.5/library/tzdata/America/Fort_Wayne0000644000175000017500000000034212661614722020057 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Indiana/Indianapolis)]} { LoadTimeZoneFile America/Indiana/Indianapolis } set TZData(:America/Fort_Wayne) $TZData(:America/Indiana/Indianapolis) tcl8.6.5/library/tzdata/America/Guatemala0000644000175000017500000000060112661614720017676 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Guatemala) { {-9223372036854775808 -21724 0 LMT} {-1617040676 -21600 0 CST} {123055200 -18000 1 CDT} {130914000 -21600 0 CST} {422344800 -18000 1 CDT} {433054800 -21600 0 CST} {669708000 -18000 1 CDT} {684219600 -21600 0 CST} {1146376800 -18000 1 CDT} {1159678800 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Swift_Current0000644000175000017500000000151512663660066020607 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Swift_Current) { {-9223372036854775808 -25880 0 LMT} {-2030201320 -25200 0 MST} {-1632063600 -21600 1 MDT} {-1615132800 -25200 0 MST} {-880210800 -21600 1 MWT} {-769395600 -21600 1 MPT} {-765388800 -25200 0 MST} {-747241200 -21600 0 MDT} {-732729600 -25200 0 MST} {-715791600 -21600 1 MDT} {-702489600 -25200 0 MST} {-684342000 -21600 1 MDT} {-671040000 -25200 0 MST} {-652892400 -21600 1 MDT} {-639590400 -25200 0 MST} {-631126800 -25200 0 MST} {-400086000 -21600 1 MDT} {-384364800 -25200 0 MST} {-337186800 -21600 1 MDT} {-321465600 -25200 0 MST} {-305737200 -21600 1 MDT} {-292435200 -25200 0 MST} {-273682800 -21600 1 MDT} {-260985600 -25200 0 MST} {73472400 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Montreal0000644000175000017500000000027112663660066017570 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Toronto)]} { LoadTimeZoneFile America/Toronto } set TZData(:America/Montreal) $TZData(:America/Toronto) tcl8.6.5/library/tzdata/America/Detroit0000644000175000017500000001760412661614720017423 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Detroit) { {-9223372036854775808 -19931 0 LMT} {-2051202469 -21600 0 CST} {-1724083200 -18000 0 EST} {-883594800 -18000 0 EST} {-880218000 -14400 1 EWT} {-769395600 -14400 1 EPT} {-765396000 -18000 0 EST} {-757364400 -18000 0 EST} {-684349200 -14400 1 EDT} {-671047200 -18000 0 EST} {-80499600 -14400 1 EDT} {-68666400 -18000 0 EST} {94712400 -18000 0 EST} {104914800 -14400 1 EDT} {120636000 -18000 0 EST} {126687600 -14400 1 EDT} {152085600 -18000 0 EST} {157784400 -18000 0 EST} {167814000 -14400 0 EDT} {183535200 -18000 0 EST} {199263600 -14400 1 EDT} {215589600 -18000 0 EST} {230713200 -14400 1 EDT} {247039200 -18000 0 EST} {262767600 -14400 1 EDT} {278488800 -18000 0 EST} {294217200 -14400 1 EDT} {309938400 -18000 0 EST} {325666800 -14400 1 EDT} {341388000 -18000 0 EST} {357116400 -14400 1 EDT} {372837600 -18000 0 EST} {388566000 -14400 1 EDT} {404892000 -18000 0 EST} {420015600 -14400 1 EDT} {436341600 -18000 0 EST} {452070000 -14400 1 EDT} {467791200 -18000 0 EST} {483519600 -14400 1 EDT} {499240800 -18000 0 EST} {514969200 -14400 1 EDT} {530690400 -18000 0 EST} {544604400 -14400 1 EDT} {562140000 -18000 0 EST} {576054000 -14400 1 EDT} {594194400 -18000 0 EST} {607503600 -14400 1 EDT} {625644000 -18000 0 EST} {638953200 -14400 1 EDT} {657093600 -18000 0 EST} {671007600 -14400 1 EDT} {688543200 -18000 0 EST} {702457200 -14400 1 EDT} {719992800 -18000 0 EST} {733906800 -14400 1 EDT} {752047200 -18000 0 EST} {765356400 -14400 1 EDT} {783496800 -18000 0 EST} {796806000 -14400 1 EDT} {814946400 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {909295200 -18000 0 EST} {923209200 -14400 1 EDT} {941349600 -18000 0 EST} {954658800 -14400 1 EDT} {972799200 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Inuvik0000644000175000017500000001633512661614721017257 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Inuvik) { {-9223372036854775808 0 0 zzz} {-536457600 -28800 0 PST} {-147888000 -21600 1 PDDT} {-131558400 -28800 0 PST} {315558000 -25200 0 MST} {325674000 -21600 1 MDT} {341395200 -25200 0 MST} {357123600 -21600 1 MDT} {372844800 -25200 0 MST} {388573200 -21600 1 MDT} {404899200 -25200 0 MST} {420022800 -21600 1 MDT} {436348800 -25200 0 MST} {452077200 -21600 1 MDT} {467798400 -25200 0 MST} {483526800 -21600 1 MDT} {499248000 -25200 0 MST} {514976400 -21600 1 MDT} {530697600 -25200 0 MST} {544611600 -21600 1 MDT} {562147200 -25200 0 MST} {576061200 -21600 1 MDT} {594201600 -25200 0 MST} {607510800 -21600 1 MDT} {625651200 -25200 0 MST} {638960400 -21600 1 MDT} {657100800 -25200 0 MST} {671014800 -21600 1 MDT} {688550400 -25200 0 MST} {702464400 -21600 1 MDT} {720000000 -25200 0 MST} {733914000 -21600 1 MDT} {752054400 -25200 0 MST} {765363600 -21600 1 MDT} {783504000 -25200 0 MST} {796813200 -21600 1 MDT} {814953600 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {986115600 -21600 1 MDT} {1004256000 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1173603600 -21600 1 MDT} {1194163200 -25200 0 MST} {1205053200 -21600 1 MDT} {1225612800 -25200 0 MST} {1236502800 -21600 1 MDT} {1257062400 -25200 0 MST} {1268557200 -21600 1 MDT} {1289116800 -25200 0 MST} {1300006800 -21600 1 MDT} {1320566400 -25200 0 MST} {1331456400 -21600 1 MDT} {1352016000 -25200 0 MST} {1362906000 -21600 1 MDT} {1383465600 -25200 0 MST} {1394355600 -21600 1 MDT} {1414915200 -25200 0 MST} {1425805200 -21600 1 MDT} {1446364800 -25200 0 MST} {1457859600 -21600 1 MDT} {1478419200 -25200 0 MST} {1489309200 -21600 1 MDT} {1509868800 -25200 0 MST} {1520758800 -21600 1 MDT} {1541318400 -25200 0 MST} {1552208400 -21600 1 MDT} {1572768000 -25200 0 MST} {1583658000 -21600 1 MDT} {1604217600 -25200 0 MST} {1615712400 -21600 1 MDT} {1636272000 -25200 0 MST} {1647162000 -21600 1 MDT} {1667721600 -25200 0 MST} {1678611600 -21600 1 MDT} {1699171200 -25200 0 MST} {1710061200 -21600 1 MDT} {1730620800 -25200 0 MST} {1741510800 -21600 1 MDT} {1762070400 -25200 0 MST} {1772960400 -21600 1 MDT} {1793520000 -25200 0 MST} {1805014800 -21600 1 MDT} {1825574400 -25200 0 MST} {1836464400 -21600 1 MDT} {1857024000 -25200 0 MST} {1867914000 -21600 1 MDT} {1888473600 -25200 0 MST} {1899363600 -21600 1 MDT} {1919923200 -25200 0 MST} {1930813200 -21600 1 MDT} {1951372800 -25200 0 MST} {1962867600 -21600 1 MDT} {1983427200 -25200 0 MST} {1994317200 -21600 1 MDT} {2014876800 -25200 0 MST} {2025766800 -21600 1 MDT} {2046326400 -25200 0 MST} {2057216400 -21600 1 MDT} {2077776000 -25200 0 MST} {2088666000 -21600 1 MDT} {2109225600 -25200 0 MST} {2120115600 -21600 1 MDT} {2140675200 -25200 0 MST} {2152170000 -21600 1 MDT} {2172729600 -25200 0 MST} {2183619600 -21600 1 MDT} {2204179200 -25200 0 MST} {2215069200 -21600 1 MDT} {2235628800 -25200 0 MST} {2246518800 -21600 1 MDT} {2267078400 -25200 0 MST} {2277968400 -21600 1 MDT} {2298528000 -25200 0 MST} {2309418000 -21600 1 MDT} {2329977600 -25200 0 MST} {2341472400 -21600 1 MDT} {2362032000 -25200 0 MST} {2372922000 -21600 1 MDT} {2393481600 -25200 0 MST} {2404371600 -21600 1 MDT} {2424931200 -25200 0 MST} {2435821200 -21600 1 MDT} {2456380800 -25200 0 MST} {2467270800 -21600 1 MDT} {2487830400 -25200 0 MST} {2499325200 -21600 1 MDT} {2519884800 -25200 0 MST} {2530774800 -21600 1 MDT} {2551334400 -25200 0 MST} {2562224400 -21600 1 MDT} {2582784000 -25200 0 MST} {2593674000 -21600 1 MDT} {2614233600 -25200 0 MST} {2625123600 -21600 1 MDT} {2645683200 -25200 0 MST} {2656573200 -21600 1 MDT} {2677132800 -25200 0 MST} {2688627600 -21600 1 MDT} {2709187200 -25200 0 MST} {2720077200 -21600 1 MDT} {2740636800 -25200 0 MST} {2751526800 -21600 1 MDT} {2772086400 -25200 0 MST} {2782976400 -21600 1 MDT} {2803536000 -25200 0 MST} {2814426000 -21600 1 MDT} {2834985600 -25200 0 MST} {2846480400 -21600 1 MDT} {2867040000 -25200 0 MST} {2877930000 -21600 1 MDT} {2898489600 -25200 0 MST} {2909379600 -21600 1 MDT} {2929939200 -25200 0 MST} {2940829200 -21600 1 MDT} {2961388800 -25200 0 MST} {2972278800 -21600 1 MDT} {2992838400 -25200 0 MST} {3003728400 -21600 1 MDT} {3024288000 -25200 0 MST} {3035782800 -21600 1 MDT} {3056342400 -25200 0 MST} {3067232400 -21600 1 MDT} {3087792000 -25200 0 MST} {3098682000 -21600 1 MDT} {3119241600 -25200 0 MST} {3130131600 -21600 1 MDT} {3150691200 -25200 0 MST} {3161581200 -21600 1 MDT} {3182140800 -25200 0 MST} {3193030800 -21600 1 MDT} {3213590400 -25200 0 MST} {3225085200 -21600 1 MDT} {3245644800 -25200 0 MST} {3256534800 -21600 1 MDT} {3277094400 -25200 0 MST} {3287984400 -21600 1 MDT} {3308544000 -25200 0 MST} {3319434000 -21600 1 MDT} {3339993600 -25200 0 MST} {3350883600 -21600 1 MDT} {3371443200 -25200 0 MST} {3382938000 -21600 1 MDT} {3403497600 -25200 0 MST} {3414387600 -21600 1 MDT} {3434947200 -25200 0 MST} {3445837200 -21600 1 MDT} {3466396800 -25200 0 MST} {3477286800 -21600 1 MDT} {3497846400 -25200 0 MST} {3508736400 -21600 1 MDT} {3529296000 -25200 0 MST} {3540186000 -21600 1 MDT} {3560745600 -25200 0 MST} {3572240400 -21600 1 MDT} {3592800000 -25200 0 MST} {3603690000 -21600 1 MDT} {3624249600 -25200 0 MST} {3635139600 -21600 1 MDT} {3655699200 -25200 0 MST} {3666589200 -21600 1 MDT} {3687148800 -25200 0 MST} {3698038800 -21600 1 MDT} {3718598400 -25200 0 MST} {3730093200 -21600 1 MDT} {3750652800 -25200 0 MST} {3761542800 -21600 1 MDT} {3782102400 -25200 0 MST} {3792992400 -21600 1 MDT} {3813552000 -25200 0 MST} {3824442000 -21600 1 MDT} {3845001600 -25200 0 MST} {3855891600 -21600 1 MDT} {3876451200 -25200 0 MST} {3887341200 -21600 1 MDT} {3907900800 -25200 0 MST} {3919395600 -21600 1 MDT} {3939955200 -25200 0 MST} {3950845200 -21600 1 MDT} {3971404800 -25200 0 MST} {3982294800 -21600 1 MDT} {4002854400 -25200 0 MST} {4013744400 -21600 1 MDT} {4034304000 -25200 0 MST} {4045194000 -21600 1 MDT} {4065753600 -25200 0 MST} {4076643600 -21600 1 MDT} {4097203200 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Indianapolis0000644000175000017500000000034412661614722020416 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Indiana/Indianapolis)]} { LoadTimeZoneFile America/Indiana/Indianapolis } set TZData(:America/Indianapolis) $TZData(:America/Indiana/Indianapolis) tcl8.6.5/library/tzdata/America/Blanc-Sablon0000644000175000017500000000051312663660066020241 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Blanc-Sablon) { {-9223372036854775808 -13708 0 LMT} {-2713896692 -14400 0 AST} {-1632074400 -10800 1 ADT} {-1615143600 -14400 0 AST} {-880221600 -10800 1 AWT} {-769395600 -10800 1 APT} {-765399600 -14400 0 AST} {14400 -14400 0 AST} } tcl8.6.5/library/tzdata/America/Paramaribo0000644000175000017500000000042012661614721020053 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Paramaribo) { {-9223372036854775808 -13240 0 LMT} {-1861906760 -13252 0 PMT} {-1104524348 -13236 0 PMT} {-765317964 -12600 0 NEGT} {185686200 -12600 0 SRT} {465449400 -10800 0 SRT} } tcl8.6.5/library/tzdata/America/North_Dakota/0000755000175000017500000000000012665173607020443 5ustar sergeisergeitcl8.6.5/library/tzdata/America/North_Dakota/Beulah0000644000175000017500000002012612663653207021564 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/North_Dakota/Beulah) { {-9223372036854775808 -24427 0 LMT} {-2717643600 -25200 0 MST} {-1633273200 -21600 1 MDT} {-1615132800 -25200 0 MST} {-1601823600 -21600 1 MDT} {-1583683200 -25200 0 MST} {-880210800 -21600 1 MWT} {-769395600 -21600 1 MPT} {-765388800 -25200 0 MST} {-84380400 -21600 1 MDT} {-68659200 -25200 0 MST} {-52930800 -21600 1 MDT} {-37209600 -25200 0 MST} {-21481200 -21600 1 MDT} {-5760000 -25200 0 MST} {9968400 -21600 1 MDT} {25689600 -25200 0 MST} {41418000 -21600 1 MDT} {57744000 -25200 0 MST} {73472400 -21600 1 MDT} {89193600 -25200 0 MST} {104922000 -21600 1 MDT} {120643200 -25200 0 MST} {126694800 -21600 1 MDT} {152092800 -25200 0 MST} {162378000 -21600 1 MDT} {183542400 -25200 0 MST} {199270800 -21600 1 MDT} {215596800 -25200 0 MST} {230720400 -21600 1 MDT} {247046400 -25200 0 MST} {262774800 -21600 1 MDT} {278496000 -25200 0 MST} {294224400 -21600 1 MDT} {309945600 -25200 0 MST} {325674000 -21600 1 MDT} {341395200 -25200 0 MST} {357123600 -21600 1 MDT} {372844800 -25200 0 MST} {388573200 -21600 1 MDT} {404899200 -25200 0 MST} {420022800 -21600 1 MDT} {436348800 -25200 0 MST} {452077200 -21600 1 MDT} {467798400 -25200 0 MST} {483526800 -21600 1 MDT} {499248000 -25200 0 MST} {514976400 -21600 1 MDT} {530697600 -25200 0 MST} {544611600 -21600 1 MDT} {562147200 -25200 0 MST} {576061200 -21600 1 MDT} {594201600 -25200 0 MST} {607510800 -21600 1 MDT} {625651200 -25200 0 MST} {638960400 -21600 1 MDT} {657100800 -25200 0 MST} {671014800 -21600 1 MDT} {688550400 -25200 0 MST} {702464400 -21600 1 MDT} {720000000 -25200 0 MST} {733914000 -21600 1 MDT} {752054400 -25200 0 MST} {765363600 -21600 1 MDT} {783504000 -25200 0 MST} {796813200 -21600 1 MDT} {814953600 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {986115600 -21600 1 MDT} {1004256000 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1173603600 -21600 1 MDT} {1194163200 -25200 0 MST} {1205053200 -21600 1 MDT} {1225612800 -25200 0 MST} {1236502800 -21600 1 MDT} {1257062400 -25200 0 MST} {1268557200 -21600 1 MDT} {1289120400 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/North_Dakota/New_Salem0000644000175000017500000002013112661614721022226 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/North_Dakota/New_Salem) { {-9223372036854775808 -24339 0 LMT} {-2717643600 -25200 0 MST} {-1633273200 -21600 1 MDT} {-1615132800 -25200 0 MST} {-1601823600 -21600 1 MDT} {-1583683200 -25200 0 MST} {-880210800 -21600 1 MWT} {-769395600 -21600 1 MPT} {-765388800 -25200 0 MST} {-84380400 -21600 1 MDT} {-68659200 -25200 0 MST} {-52930800 -21600 1 MDT} {-37209600 -25200 0 MST} {-21481200 -21600 1 MDT} {-5760000 -25200 0 MST} {9968400 -21600 1 MDT} {25689600 -25200 0 MST} {41418000 -21600 1 MDT} {57744000 -25200 0 MST} {73472400 -21600 1 MDT} {89193600 -25200 0 MST} {104922000 -21600 1 MDT} {120643200 -25200 0 MST} {126694800 -21600 1 MDT} {152092800 -25200 0 MST} {162378000 -21600 1 MDT} {183542400 -25200 0 MST} {199270800 -21600 1 MDT} {215596800 -25200 0 MST} {230720400 -21600 1 MDT} {247046400 -25200 0 MST} {262774800 -21600 1 MDT} {278496000 -25200 0 MST} {294224400 -21600 1 MDT} {309945600 -25200 0 MST} {325674000 -21600 1 MDT} {341395200 -25200 0 MST} {357123600 -21600 1 MDT} {372844800 -25200 0 MST} {388573200 -21600 1 MDT} {404899200 -25200 0 MST} {420022800 -21600 1 MDT} {436348800 -25200 0 MST} {452077200 -21600 1 MDT} {467798400 -25200 0 MST} {483526800 -21600 1 MDT} {499248000 -25200 0 MST} {514976400 -21600 1 MDT} {530697600 -25200 0 MST} {544611600 -21600 1 MDT} {562147200 -25200 0 MST} {576061200 -21600 1 MDT} {594201600 -25200 0 MST} {607510800 -21600 1 MDT} {625651200 -25200 0 MST} {638960400 -21600 1 MDT} {657100800 -25200 0 MST} {671014800 -21600 1 MDT} {688550400 -25200 0 MST} {702464400 -21600 1 MDT} {720000000 -25200 0 MST} {733914000 -21600 1 MDT} {752054400 -25200 0 MST} {765363600 -21600 1 MDT} {783504000 -25200 0 MST} {796813200 -21600 1 MDT} {814953600 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {986115600 -21600 1 MDT} {1004256000 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067158800 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194159600 -21600 0 CST} {1205049600 -18000 1 CDT} {1225609200 -21600 0 CST} {1236499200 -18000 1 CDT} {1257058800 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/North_Dakota/Center0000644000175000017500000002012612661614721021600 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/North_Dakota/Center) { {-9223372036854775808 -24312 0 LMT} {-2717643600 -25200 0 MST} {-1633273200 -21600 1 MDT} {-1615132800 -25200 0 MST} {-1601823600 -21600 1 MDT} {-1583683200 -25200 0 MST} {-880210800 -21600 1 MWT} {-769395600 -21600 1 MPT} {-765388800 -25200 0 MST} {-84380400 -21600 1 MDT} {-68659200 -25200 0 MST} {-52930800 -21600 1 MDT} {-37209600 -25200 0 MST} {-21481200 -21600 1 MDT} {-5760000 -25200 0 MST} {9968400 -21600 1 MDT} {25689600 -25200 0 MST} {41418000 -21600 1 MDT} {57744000 -25200 0 MST} {73472400 -21600 1 MDT} {89193600 -25200 0 MST} {104922000 -21600 1 MDT} {120643200 -25200 0 MST} {126694800 -21600 1 MDT} {152092800 -25200 0 MST} {162378000 -21600 1 MDT} {183542400 -25200 0 MST} {199270800 -21600 1 MDT} {215596800 -25200 0 MST} {230720400 -21600 1 MDT} {247046400 -25200 0 MST} {262774800 -21600 1 MDT} {278496000 -25200 0 MST} {294224400 -21600 1 MDT} {309945600 -25200 0 MST} {325674000 -21600 1 MDT} {341395200 -25200 0 MST} {357123600 -21600 1 MDT} {372844800 -25200 0 MST} {388573200 -21600 1 MDT} {404899200 -25200 0 MST} {420022800 -21600 1 MDT} {436348800 -25200 0 MST} {452077200 -21600 1 MDT} {467798400 -25200 0 MST} {483526800 -21600 1 MDT} {499248000 -25200 0 MST} {514976400 -21600 1 MDT} {530697600 -25200 0 MST} {544611600 -21600 1 MDT} {562147200 -25200 0 MST} {576061200 -21600 1 MDT} {594201600 -25200 0 MST} {607510800 -21600 1 MDT} {625651200 -25200 0 MST} {638960400 -21600 1 MDT} {657100800 -25200 0 MST} {671014800 -21600 1 MDT} {688550400 -25200 0 MST} {702464400 -21600 1 MDT} {720003600 -21600 0 CST} {733910400 -18000 1 CDT} {752050800 -21600 0 CST} {765360000 -18000 1 CDT} {783500400 -21600 0 CST} {796809600 -18000 1 CDT} {814950000 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972802800 -21600 0 CST} {986112000 -18000 1 CDT} {1004252400 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194159600 -21600 0 CST} {1205049600 -18000 1 CDT} {1225609200 -21600 0 CST} {1236499200 -18000 1 CDT} {1257058800 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Martinique0000644000175000017500000000036212661614721020121 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Martinique) { {-9223372036854775808 -14660 0 LMT} {-2524506940 -14660 0 FFMT} {-1851537340 -14400 0 AST} {323841600 -10800 1 ADT} {338958000 -14400 0 AST} } tcl8.6.5/library/tzdata/America/Maceio0000644000175000017500000000274312661614721017205 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Maceio) { {-9223372036854775808 -8572 0 LMT} {-1767217028 -10800 0 BRT} {-1206957600 -7200 1 BRST} {-1191362400 -10800 0 BRT} {-1175374800 -7200 1 BRST} {-1159826400 -10800 0 BRT} {-633819600 -7200 1 BRST} {-622069200 -10800 0 BRT} {-602283600 -7200 1 BRST} {-591832800 -10800 0 BRT} {-570747600 -7200 1 BRST} {-560210400 -10800 0 BRT} {-539125200 -7200 1 BRST} {-531352800 -10800 0 BRT} {-191365200 -7200 1 BRST} {-184197600 -10800 0 BRT} {-155163600 -7200 1 BRST} {-150069600 -10800 0 BRT} {-128898000 -7200 1 BRST} {-121125600 -10800 0 BRT} {-99954000 -7200 1 BRST} {-89589600 -10800 0 BRT} {-68418000 -7200 1 BRST} {-57967200 -10800 0 BRT} {499748400 -7200 1 BRST} {511236000 -10800 0 BRT} {530593200 -7200 1 BRST} {540266400 -10800 0 BRT} {562129200 -7200 1 BRST} {571197600 -10800 0 BRT} {592974000 -7200 1 BRST} {602042400 -10800 0 BRT} {624423600 -7200 1 BRST} {634701600 -10800 0 BRT} {653536800 -10800 0 BRT} {813553200 -10800 0 BRT} {813726000 -7200 1 BRST} {824004000 -10800 0 BRT} {841802400 -10800 0 BRT} {938660400 -10800 0 BRT} {938919600 -7200 1 BRST} {951616800 -10800 0 BRT} {970974000 -7200 1 BRST} {972180000 -10800 0 BRT} {1000350000 -10800 0 BRT} {1003028400 -7200 1 BRST} {1013911200 -10800 0 BRT} {1033437600 -10800 0 BRT} } tcl8.6.5/library/tzdata/America/Buenos_Aires0000644000175000017500000000035212661614722020361 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Argentina/Buenos_Aires)]} { LoadTimeZoneFile America/Argentina/Buenos_Aires } set TZData(:America/Buenos_Aires) $TZData(:America/Argentina/Buenos_Aires) tcl8.6.5/library/tzdata/America/Menominee0000644000175000017500000001771012661614721017724 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Menominee) { {-9223372036854775808 -21027 0 LMT} {-2659759773 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-757360800 -21600 0 CST} {-747244800 -18000 1 CDT} {-733942800 -21600 0 CST} {-116438400 -18000 1 CDT} {-100112400 -21600 0 CST} {-21484800 -18000 0 EST} {104914800 -21600 0 CST} {104918400 -18000 1 CDT} {120639600 -21600 0 CST} {126691200 -18000 1 CDT} {152089200 -21600 0 CST} {162374400 -18000 1 CDT} {183538800 -21600 0 CST} {199267200 -18000 1 CDT} {215593200 -21600 0 CST} {230716800 -18000 1 CDT} {247042800 -21600 0 CST} {262771200 -18000 1 CDT} {278492400 -21600 0 CST} {294220800 -18000 1 CDT} {309942000 -21600 0 CST} {325670400 -18000 1 CDT} {341391600 -21600 0 CST} {357120000 -18000 1 CDT} {372841200 -21600 0 CST} {388569600 -18000 1 CDT} {404895600 -21600 0 CST} {420019200 -18000 1 CDT} {436345200 -21600 0 CST} {452073600 -18000 1 CDT} {467794800 -21600 0 CST} {483523200 -18000 1 CDT} {499244400 -21600 0 CST} {514972800 -18000 1 CDT} {530694000 -21600 0 CST} {544608000 -18000 1 CDT} {562143600 -21600 0 CST} {576057600 -18000 1 CDT} {594198000 -21600 0 CST} {607507200 -18000 1 CDT} {625647600 -21600 0 CST} {638956800 -18000 1 CDT} {657097200 -21600 0 CST} {671011200 -18000 1 CDT} {688546800 -21600 0 CST} {702460800 -18000 1 CDT} {719996400 -21600 0 CST} {733910400 -18000 1 CDT} {752050800 -21600 0 CST} {765360000 -18000 1 CDT} {783500400 -21600 0 CST} {796809600 -18000 1 CDT} {814950000 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972802800 -21600 0 CST} {986112000 -18000 1 CDT} {1004252400 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194159600 -21600 0 CST} {1205049600 -18000 1 CDT} {1225609200 -21600 0 CST} {1236499200 -18000 1 CDT} {1257058800 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Goose_Bay0000644000175000017500000002343712663660066017667 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Goose_Bay) { {-9223372036854775808 -14500 0 LMT} {-2713895900 -12652 0 NST} {-1640982548 -12652 0 NST} {-1632076148 -9052 1 NDT} {-1615145348 -12652 0 NST} {-1609446548 -12652 0 NST} {-1096921748 -12600 0 NST} {-1072989000 -12600 0 NST} {-1061670600 -9000 1 NDT} {-1048973400 -12600 0 NST} {-1030221000 -9000 1 NDT} {-1017523800 -12600 0 NST} {-998771400 -9000 1 NDT} {-986074200 -12600 0 NST} {-966717000 -9000 1 NDT} {-954624600 -12600 0 NST} {-935267400 -9000 1 NDT} {-922570200 -12600 0 NST} {-903817800 -9000 1 NDT} {-891120600 -12600 0 NST} {-872368200 -9000 0 NWT} {-769395600 -9000 1 NPT} {-765401400 -12600 0 NST} {-757369800 -12600 0 NST} {-746044200 -9000 1 NDT} {-733347000 -12600 0 NST} {-714594600 -9000 1 NDT} {-701897400 -12600 0 NST} {-683145000 -9000 1 NDT} {-670447800 -12600 0 NST} {-651695400 -9000 1 NDT} {-638998200 -12600 0 NST} {-619641000 -9000 1 NDT} {-606943800 -12600 0 NST} {-589401000 -9000 1 NDT} {-576099000 -12600 0 NST} {-557951400 -9000 1 NDT} {-544649400 -12600 0 NST} {-526501800 -9000 1 NDT} {-513199800 -12600 0 NST} {-495052200 -9000 1 NDT} {-481750200 -12600 0 NST} {-463602600 -9000 1 NDT} {-450300600 -12600 0 NST} {-431548200 -9000 1 NDT} {-418246200 -12600 0 NST} {-400098600 -9000 1 NDT} {-386796600 -12600 0 NST} {-368649000 -9000 1 NDT} {-355347000 -12600 0 NST} {-337199400 -9000 1 NDT} {-323897400 -12600 0 NST} {-305749800 -9000 1 NDT} {-289423800 -12600 0 NST} {-273695400 -9000 1 NDT} {-257974200 -12600 0 NST} {-242245800 -9000 1 NDT} {-226524600 -12600 0 NST} {-210796200 -9000 1 NDT} {-195075000 -12600 0 NST} {-179346600 -9000 1 NDT} {-163625400 -12600 0 NST} {-147897000 -9000 1 NDT} {-131571000 -12600 0 NST} {-119903400 -14400 0 AST} {-116445600 -10800 1 ADT} {-100119600 -14400 0 AST} {-84391200 -10800 1 ADT} {-68670000 -14400 0 AST} {-52941600 -10800 1 ADT} {-37220400 -14400 0 AST} {-21492000 -10800 1 ADT} {-5770800 -14400 0 AST} {9957600 -10800 1 ADT} {25678800 -14400 0 AST} {41407200 -10800 1 ADT} {57733200 -14400 0 AST} {73461600 -10800 1 ADT} {89182800 -14400 0 AST} {104911200 -10800 1 ADT} {120632400 -14400 0 AST} {136360800 -10800 1 ADT} {152082000 -14400 0 AST} {167810400 -10800 1 ADT} {183531600 -14400 0 AST} {199260000 -10800 1 ADT} {215586000 -14400 0 AST} {230709600 -10800 1 ADT} {247035600 -14400 0 AST} {262764000 -10800 1 ADT} {278485200 -14400 0 AST} {294213600 -10800 1 ADT} {309934800 -14400 0 AST} {325663200 -10800 1 ADT} {341384400 -14400 0 AST} {357112800 -10800 1 ADT} {372834000 -14400 0 AST} {388562400 -10800 1 ADT} {404888400 -14400 0 AST} {420012000 -10800 1 ADT} {436338000 -14400 0 AST} {452066400 -10800 1 ADT} {467787600 -14400 0 AST} {483516000 -10800 1 ADT} {499237200 -14400 0 AST} {514965600 -10800 1 ADT} {530686800 -14400 0 AST} {544593660 -10800 1 ADT} {562129260 -14400 0 AST} {576043260 -7200 1 ADDT} {594180060 -14400 0 AST} {607492860 -10800 1 ADT} {625633260 -14400 0 AST} {638942460 -10800 1 ADT} {657082860 -14400 0 AST} {670996860 -10800 1 ADT} {688532460 -14400 0 AST} {702446460 -10800 1 ADT} {719982060 -14400 0 AST} {733896060 -10800 1 ADT} {752036460 -14400 0 AST} {765345660 -10800 1 ADT} {783486060 -14400 0 AST} {796795260 -10800 1 ADT} {814935660 -14400 0 AST} {828849660 -10800 1 ADT} {846385260 -14400 0 AST} {860299260 -10800 1 ADT} {877834860 -14400 0 AST} {891748860 -10800 1 ADT} {909284460 -14400 0 AST} {923198460 -10800 1 ADT} {941338860 -14400 0 AST} {954648060 -10800 1 ADT} {972788460 -14400 0 AST} {986097660 -10800 1 ADT} {1004238060 -14400 0 AST} {1018152060 -10800 1 ADT} {1035687660 -14400 0 AST} {1049601660 -10800 1 ADT} {1067137260 -14400 0 AST} {1081051260 -10800 1 ADT} {1099191660 -14400 0 AST} {1112500860 -10800 1 ADT} {1130641260 -14400 0 AST} {1143950460 -10800 1 ADT} {1162090860 -14400 0 AST} {1173585660 -10800 1 ADT} {1194145260 -14400 0 AST} {1205035260 -10800 1 ADT} {1225594860 -14400 0 AST} {1236484860 -10800 1 ADT} {1257044460 -14400 0 AST} {1268539260 -10800 1 ADT} {1289098860 -14400 0 AST} {1299988860 -10800 1 ADT} {1320116400 -10800 0 ADT} {1320555600 -14400 0 AST} {1331445600 -10800 1 ADT} {1352005200 -14400 0 AST} {1362895200 -10800 1 ADT} {1383454800 -14400 0 AST} {1394344800 -10800 1 ADT} {1414904400 -14400 0 AST} {1425794400 -10800 1 ADT} {1446354000 -14400 0 AST} {1457848800 -10800 1 ADT} {1478408400 -14400 0 AST} {1489298400 -10800 1 ADT} {1509858000 -14400 0 AST} {1520748000 -10800 1 ADT} {1541307600 -14400 0 AST} {1552197600 -10800 1 ADT} {1572757200 -14400 0 AST} {1583647200 -10800 1 ADT} {1604206800 -14400 0 AST} {1615701600 -10800 1 ADT} {1636261200 -14400 0 AST} {1647151200 -10800 1 ADT} {1667710800 -14400 0 AST} {1678600800 -10800 1 ADT} {1699160400 -14400 0 AST} {1710050400 -10800 1 ADT} {1730610000 -14400 0 AST} {1741500000 -10800 1 ADT} {1762059600 -14400 0 AST} {1772949600 -10800 1 ADT} {1793509200 -14400 0 AST} {1805004000 -10800 1 ADT} {1825563600 -14400 0 AST} {1836453600 -10800 1 ADT} {1857013200 -14400 0 AST} {1867903200 -10800 1 ADT} {1888462800 -14400 0 AST} {1899352800 -10800 1 ADT} {1919912400 -14400 0 AST} {1930802400 -10800 1 ADT} {1951362000 -14400 0 AST} {1962856800 -10800 1 ADT} {1983416400 -14400 0 AST} {1994306400 -10800 1 ADT} {2014866000 -14400 0 AST} {2025756000 -10800 1 ADT} {2046315600 -14400 0 AST} {2057205600 -10800 1 ADT} {2077765200 -14400 0 AST} {2088655200 -10800 1 ADT} {2109214800 -14400 0 AST} {2120104800 -10800 1 ADT} {2140664400 -14400 0 AST} {2152159200 -10800 1 ADT} {2172718800 -14400 0 AST} {2183608800 -10800 1 ADT} {2204168400 -14400 0 AST} {2215058400 -10800 1 ADT} {2235618000 -14400 0 AST} {2246508000 -10800 1 ADT} {2267067600 -14400 0 AST} {2277957600 -10800 1 ADT} {2298517200 -14400 0 AST} {2309407200 -10800 1 ADT} {2329966800 -14400 0 AST} {2341461600 -10800 1 ADT} {2362021200 -14400 0 AST} {2372911200 -10800 1 ADT} {2393470800 -14400 0 AST} {2404360800 -10800 1 ADT} {2424920400 -14400 0 AST} {2435810400 -10800 1 ADT} {2456370000 -14400 0 AST} {2467260000 -10800 1 ADT} {2487819600 -14400 0 AST} {2499314400 -10800 1 ADT} {2519874000 -14400 0 AST} {2530764000 -10800 1 ADT} {2551323600 -14400 0 AST} {2562213600 -10800 1 ADT} {2582773200 -14400 0 AST} {2593663200 -10800 1 ADT} {2614222800 -14400 0 AST} {2625112800 -10800 1 ADT} {2645672400 -14400 0 AST} {2656562400 -10800 1 ADT} {2677122000 -14400 0 AST} {2688616800 -10800 1 ADT} {2709176400 -14400 0 AST} {2720066400 -10800 1 ADT} {2740626000 -14400 0 AST} {2751516000 -10800 1 ADT} {2772075600 -14400 0 AST} {2782965600 -10800 1 ADT} {2803525200 -14400 0 AST} {2814415200 -10800 1 ADT} {2834974800 -14400 0 AST} {2846469600 -10800 1 ADT} {2867029200 -14400 0 AST} {2877919200 -10800 1 ADT} {2898478800 -14400 0 AST} {2909368800 -10800 1 ADT} {2929928400 -14400 0 AST} {2940818400 -10800 1 ADT} {2961378000 -14400 0 AST} {2972268000 -10800 1 ADT} {2992827600 -14400 0 AST} {3003717600 -10800 1 ADT} {3024277200 -14400 0 AST} {3035772000 -10800 1 ADT} {3056331600 -14400 0 AST} {3067221600 -10800 1 ADT} {3087781200 -14400 0 AST} {3098671200 -10800 1 ADT} {3119230800 -14400 0 AST} {3130120800 -10800 1 ADT} {3150680400 -14400 0 AST} {3161570400 -10800 1 ADT} {3182130000 -14400 0 AST} {3193020000 -10800 1 ADT} {3213579600 -14400 0 AST} {3225074400 -10800 1 ADT} {3245634000 -14400 0 AST} {3256524000 -10800 1 ADT} {3277083600 -14400 0 AST} {3287973600 -10800 1 ADT} {3308533200 -14400 0 AST} {3319423200 -10800 1 ADT} {3339982800 -14400 0 AST} {3350872800 -10800 1 ADT} {3371432400 -14400 0 AST} {3382927200 -10800 1 ADT} {3403486800 -14400 0 AST} {3414376800 -10800 1 ADT} {3434936400 -14400 0 AST} {3445826400 -10800 1 ADT} {3466386000 -14400 0 AST} {3477276000 -10800 1 ADT} {3497835600 -14400 0 AST} {3508725600 -10800 1 ADT} {3529285200 -14400 0 AST} {3540175200 -10800 1 ADT} {3560734800 -14400 0 AST} {3572229600 -10800 1 ADT} {3592789200 -14400 0 AST} {3603679200 -10800 1 ADT} {3624238800 -14400 0 AST} {3635128800 -10800 1 ADT} {3655688400 -14400 0 AST} {3666578400 -10800 1 ADT} {3687138000 -14400 0 AST} {3698028000 -10800 1 ADT} {3718587600 -14400 0 AST} {3730082400 -10800 1 ADT} {3750642000 -14400 0 AST} {3761532000 -10800 1 ADT} {3782091600 -14400 0 AST} {3792981600 -10800 1 ADT} {3813541200 -14400 0 AST} {3824431200 -10800 1 ADT} {3844990800 -14400 0 AST} {3855880800 -10800 1 ADT} {3876440400 -14400 0 AST} {3887330400 -10800 1 ADT} {3907890000 -14400 0 AST} {3919384800 -10800 1 ADT} {3939944400 -14400 0 AST} {3950834400 -10800 1 ADT} {3971394000 -14400 0 AST} {3982284000 -10800 1 ADT} {4002843600 -14400 0 AST} {4013733600 -10800 1 ADT} {4034293200 -14400 0 AST} {4045183200 -10800 1 ADT} {4065742800 -14400 0 AST} {4076632800 -10800 1 ADT} {4097192400 -14400 0 AST} } tcl8.6.5/library/tzdata/America/Cuiaba0000644000175000017500000001713312663653132017174 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Cuiaba) { {-9223372036854775808 -13460 0 LMT} {-1767212140 -14400 0 AMT} {-1206954000 -10800 1 AMST} {-1191358800 -14400 0 AMT} {-1175371200 -10800 1 AMST} {-1159822800 -14400 0 AMT} {-633816000 -10800 1 AMST} {-622065600 -14400 0 AMT} {-602280000 -10800 1 AMST} {-591829200 -14400 0 AMT} {-570744000 -10800 1 AMST} {-560206800 -14400 0 AMT} {-539121600 -10800 1 AMST} {-531349200 -14400 0 AMT} {-191361600 -10800 1 AMST} {-184194000 -14400 0 AMT} {-155160000 -10800 1 AMST} {-150066000 -14400 0 AMT} {-128894400 -10800 1 AMST} {-121122000 -14400 0 AMT} {-99950400 -10800 1 AMST} {-89586000 -14400 0 AMT} {-68414400 -10800 1 AMST} {-57963600 -14400 0 AMT} {499752000 -10800 1 AMST} {511239600 -14400 0 AMT} {530596800 -10800 1 AMST} {540270000 -14400 0 AMT} {562132800 -10800 1 AMST} {571201200 -14400 0 AMT} {592977600 -10800 1 AMST} {602046000 -14400 0 AMT} {624427200 -10800 1 AMST} {634705200 -14400 0 AMT} {656481600 -10800 1 AMST} {666759600 -14400 0 AMT} {687931200 -10800 1 AMST} {697604400 -14400 0 AMT} {719985600 -10800 1 AMST} {728449200 -14400 0 AMT} {750830400 -10800 1 AMST} {761713200 -14400 0 AMT} {782280000 -10800 1 AMST} {793162800 -14400 0 AMT} {813729600 -10800 1 AMST} {824007600 -14400 0 AMT} {844574400 -10800 1 AMST} {856062000 -14400 0 AMT} {876110400 -10800 1 AMST} {888721200 -14400 0 AMT} {908078400 -10800 1 AMST} {919566000 -14400 0 AMT} {938923200 -10800 1 AMST} {951620400 -14400 0 AMT} {970977600 -10800 1 AMST} {982465200 -14400 0 AMT} {1003032000 -10800 1 AMST} {1013914800 -14400 0 AMT} {1036296000 -10800 1 AMST} {1045364400 -14400 0 AMT} {1064372400 -14400 0 AMT} {1096603200 -14400 0 AMT} {1099368000 -10800 1 AMST} {1108868400 -14400 0 AMT} {1129435200 -10800 1 AMST} {1140318000 -14400 0 AMT} {1162699200 -10800 1 AMST} {1172372400 -14400 0 AMT} {1192334400 -10800 1 AMST} {1203217200 -14400 0 AMT} {1224388800 -10800 1 AMST} {1234666800 -14400 0 AMT} {1255838400 -10800 1 AMST} {1266721200 -14400 0 AMT} {1287288000 -10800 1 AMST} {1298170800 -14400 0 AMT} {1318737600 -10800 1 AMST} {1330225200 -14400 0 AMT} {1350792000 -10800 1 AMST} {1361070000 -14400 0 AMT} {1382241600 -10800 1 AMST} {1392519600 -14400 0 AMT} {1413691200 -10800 1 AMST} {1424574000 -14400 0 AMT} {1445140800 -10800 1 AMST} {1456023600 -14400 0 AMT} {1476590400 -10800 1 AMST} {1487473200 -14400 0 AMT} {1508040000 -10800 1 AMST} {1518922800 -14400 0 AMT} {1540094400 -10800 1 AMST} {1550372400 -14400 0 AMT} {1571544000 -10800 1 AMST} {1581822000 -14400 0 AMT} {1602993600 -10800 1 AMST} {1613876400 -14400 0 AMT} {1634443200 -10800 1 AMST} {1645326000 -14400 0 AMT} {1665892800 -10800 1 AMST} {1677380400 -14400 0 AMT} {1697342400 -10800 1 AMST} {1708225200 -14400 0 AMT} {1729396800 -10800 1 AMST} {1739674800 -14400 0 AMT} {1760846400 -10800 1 AMST} {1771729200 -14400 0 AMT} {1792296000 -10800 1 AMST} {1803178800 -14400 0 AMT} {1823745600 -10800 1 AMST} {1834628400 -14400 0 AMT} {1855195200 -10800 1 AMST} {1866078000 -14400 0 AMT} {1887249600 -10800 1 AMST} {1897527600 -14400 0 AMT} {1918699200 -10800 1 AMST} {1928977200 -14400 0 AMT} {1950148800 -10800 1 AMST} {1960426800 -14400 0 AMT} {1981598400 -10800 1 AMST} {1992481200 -14400 0 AMT} {2013048000 -10800 1 AMST} {2024535600 -14400 0 AMT} {2044497600 -10800 1 AMST} {2055380400 -14400 0 AMT} {2076552000 -10800 1 AMST} {2086830000 -14400 0 AMT} {2108001600 -10800 1 AMST} {2118884400 -14400 0 AMT} {2139451200 -10800 1 AMST} {2150334000 -14400 0 AMT} {2170900800 -10800 1 AMST} {2181783600 -14400 0 AMT} {2202350400 -10800 1 AMST} {2213233200 -14400 0 AMT} {2234404800 -10800 1 AMST} {2244682800 -14400 0 AMT} {2265854400 -10800 1 AMST} {2276132400 -14400 0 AMT} {2297304000 -10800 1 AMST} {2307582000 -14400 0 AMT} {2328753600 -10800 1 AMST} {2339636400 -14400 0 AMT} {2360203200 -10800 1 AMST} {2371086000 -14400 0 AMT} {2391652800 -10800 1 AMST} {2402535600 -14400 0 AMT} {2423707200 -10800 1 AMST} {2433985200 -14400 0 AMT} {2455156800 -10800 1 AMST} {2465434800 -14400 0 AMT} {2486606400 -10800 1 AMST} {2497489200 -14400 0 AMT} {2518056000 -10800 1 AMST} {2528938800 -14400 0 AMT} {2549505600 -10800 1 AMST} {2560388400 -14400 0 AMT} {2580955200 -10800 1 AMST} {2591838000 -14400 0 AMT} {2613009600 -10800 1 AMST} {2623287600 -14400 0 AMT} {2644459200 -10800 1 AMST} {2654737200 -14400 0 AMT} {2675908800 -10800 1 AMST} {2686791600 -14400 0 AMT} {2707358400 -10800 1 AMST} {2718241200 -14400 0 AMT} {2738808000 -10800 1 AMST} {2749690800 -14400 0 AMT} {2770862400 -10800 1 AMST} {2781140400 -14400 0 AMT} {2802312000 -10800 1 AMST} {2812590000 -14400 0 AMT} {2833761600 -10800 1 AMST} {2844039600 -14400 0 AMT} {2865211200 -10800 1 AMST} {2876094000 -14400 0 AMT} {2896660800 -10800 1 AMST} {2907543600 -14400 0 AMT} {2928110400 -10800 1 AMST} {2938993200 -14400 0 AMT} {2960164800 -10800 1 AMST} {2970442800 -14400 0 AMT} {2991614400 -10800 1 AMST} {3001892400 -14400 0 AMT} {3023064000 -10800 1 AMST} {3033946800 -14400 0 AMT} {3054513600 -10800 1 AMST} {3065396400 -14400 0 AMT} {3085963200 -10800 1 AMST} {3096846000 -14400 0 AMT} {3118017600 -10800 1 AMST} {3128295600 -14400 0 AMT} {3149467200 -10800 1 AMST} {3159745200 -14400 0 AMT} {3180916800 -10800 1 AMST} {3191194800 -14400 0 AMT} {3212366400 -10800 1 AMST} {3223249200 -14400 0 AMT} {3243816000 -10800 1 AMST} {3254698800 -14400 0 AMT} {3275265600 -10800 1 AMST} {3286148400 -14400 0 AMT} {3307320000 -10800 1 AMST} {3317598000 -14400 0 AMT} {3338769600 -10800 1 AMST} {3349047600 -14400 0 AMT} {3370219200 -10800 1 AMST} {3381102000 -14400 0 AMT} {3401668800 -10800 1 AMST} {3412551600 -14400 0 AMT} {3433118400 -10800 1 AMST} {3444001200 -14400 0 AMT} {3464568000 -10800 1 AMST} {3475450800 -14400 0 AMT} {3496622400 -10800 1 AMST} {3506900400 -14400 0 AMT} {3528072000 -10800 1 AMST} {3538350000 -14400 0 AMT} {3559521600 -10800 1 AMST} {3570404400 -14400 0 AMT} {3590971200 -10800 1 AMST} {3601854000 -14400 0 AMT} {3622420800 -10800 1 AMST} {3633303600 -14400 0 AMT} {3654475200 -10800 1 AMST} {3664753200 -14400 0 AMT} {3685924800 -10800 1 AMST} {3696202800 -14400 0 AMT} {3717374400 -10800 1 AMST} {3727652400 -14400 0 AMT} {3748824000 -10800 1 AMST} {3759706800 -14400 0 AMT} {3780273600 -10800 1 AMST} {3791156400 -14400 0 AMT} {3811723200 -10800 1 AMST} {3822606000 -14400 0 AMT} {3843777600 -10800 1 AMST} {3854055600 -14400 0 AMT} {3875227200 -10800 1 AMST} {3885505200 -14400 0 AMT} {3906676800 -10800 1 AMST} {3917559600 -14400 0 AMT} {3938126400 -10800 1 AMST} {3949009200 -14400 0 AMT} {3969576000 -10800 1 AMST} {3980458800 -14400 0 AMT} {4001630400 -10800 1 AMST} {4011908400 -14400 0 AMT} {4033080000 -10800 1 AMST} {4043358000 -14400 0 AMT} {4064529600 -10800 1 AMST} {4074807600 -14400 0 AMT} {4095979200 -10800 1 AMST} } tcl8.6.5/library/tzdata/America/Eirunepe0000644000175000017500000000226412663660066017567 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Eirunepe) { {-9223372036854775808 -16768 0 LMT} {-1767208832 -18000 0 ACT} {-1206950400 -14400 1 ACST} {-1191355200 -18000 0 ACT} {-1175367600 -14400 1 ACST} {-1159819200 -18000 0 ACT} {-633812400 -14400 1 ACST} {-622062000 -18000 0 ACT} {-602276400 -14400 1 ACST} {-591825600 -18000 0 ACT} {-570740400 -14400 1 ACST} {-560203200 -18000 0 ACT} {-539118000 -14400 1 ACST} {-531345600 -18000 0 ACT} {-191358000 -14400 1 ACST} {-184190400 -18000 0 ACT} {-155156400 -14400 1 ACST} {-150062400 -18000 0 ACT} {-128890800 -14400 1 ACST} {-121118400 -18000 0 ACT} {-99946800 -14400 1 ACST} {-89582400 -18000 0 ACT} {-68410800 -14400 1 ACST} {-57960000 -18000 0 ACT} {499755600 -14400 1 ACST} {511243200 -18000 0 ACT} {530600400 -14400 1 ACST} {540273600 -18000 0 ACT} {562136400 -14400 1 ACST} {571204800 -18000 0 ACT} {590040000 -18000 0 ACT} {749192400 -18000 0 ACT} {750834000 -14400 1 ACST} {761716800 -18000 0 ACT} {780206400 -18000 0 ACT} {1214283600 -14400 0 AMT} {1384056000 -18000 0 ACT} } tcl8.6.5/library/tzdata/America/Creston0000644000175000017500000000032312663660066017422 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Creston) { {-9223372036854775808 -27964 0 LMT} {-2713882436 -25200 0 MST} {-1680454800 -28800 0 PST} {-1627833600 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Rosario0000644000175000017500000000032612661614722017422 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Argentina/Cordoba)]} { LoadTimeZoneFile America/Argentina/Cordoba } set TZData(:America/Rosario) $TZData(:America/Argentina/Cordoba) tcl8.6.5/library/tzdata/America/Miquelon0000644000175000017500000001564212661614721017603 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Miquelon) { {-9223372036854775808 -13480 0 LMT} {-1850328920 -14400 0 AST} {326001600 -10800 0 PMST} {536468400 -10800 0 PMST} {544597200 -7200 1 PMDT} {562132800 -10800 0 PMST} {576046800 -7200 1 PMDT} {594187200 -10800 0 PMST} {607496400 -7200 1 PMDT} {625636800 -10800 0 PMST} {638946000 -7200 1 PMDT} {657086400 -10800 0 PMST} {671000400 -7200 1 PMDT} {688536000 -10800 0 PMST} {702450000 -7200 1 PMDT} {719985600 -10800 0 PMST} {733899600 -7200 1 PMDT} {752040000 -10800 0 PMST} {765349200 -7200 1 PMDT} {783489600 -10800 0 PMST} {796798800 -7200 1 PMDT} {814939200 -10800 0 PMST} {828853200 -7200 1 PMDT} {846388800 -10800 0 PMST} {860302800 -7200 1 PMDT} {877838400 -10800 0 PMST} {891752400 -7200 1 PMDT} {909288000 -10800 0 PMST} {923202000 -7200 1 PMDT} {941342400 -10800 0 PMST} {954651600 -7200 1 PMDT} {972792000 -10800 0 PMST} {986101200 -7200 1 PMDT} {1004241600 -10800 0 PMST} {1018155600 -7200 1 PMDT} {1035691200 -10800 0 PMST} {1049605200 -7200 1 PMDT} {1067140800 -10800 0 PMST} {1081054800 -7200 1 PMDT} {1099195200 -10800 0 PMST} {1112504400 -7200 1 PMDT} {1130644800 -10800 0 PMST} {1143954000 -7200 1 PMDT} {1162094400 -10800 0 PMST} {1173589200 -7200 1 PMDT} {1194148800 -10800 0 PMST} {1205038800 -7200 1 PMDT} {1225598400 -10800 0 PMST} {1236488400 -7200 1 PMDT} {1257048000 -10800 0 PMST} {1268542800 -7200 1 PMDT} {1289102400 -10800 0 PMST} {1299992400 -7200 1 PMDT} {1320552000 -10800 0 PMST} {1331442000 -7200 1 PMDT} {1352001600 -10800 0 PMST} {1362891600 -7200 1 PMDT} {1383451200 -10800 0 PMST} {1394341200 -7200 1 PMDT} {1414900800 -10800 0 PMST} {1425790800 -7200 1 PMDT} {1446350400 -10800 0 PMST} {1457845200 -7200 1 PMDT} {1478404800 -10800 0 PMST} {1489294800 -7200 1 PMDT} {1509854400 -10800 0 PMST} {1520744400 -7200 1 PMDT} {1541304000 -10800 0 PMST} {1552194000 -7200 1 PMDT} {1572753600 -10800 0 PMST} {1583643600 -7200 1 PMDT} {1604203200 -10800 0 PMST} {1615698000 -7200 1 PMDT} {1636257600 -10800 0 PMST} {1647147600 -7200 1 PMDT} {1667707200 -10800 0 PMST} {1678597200 -7200 1 PMDT} {1699156800 -10800 0 PMST} {1710046800 -7200 1 PMDT} {1730606400 -10800 0 PMST} {1741496400 -7200 1 PMDT} {1762056000 -10800 0 PMST} {1772946000 -7200 1 PMDT} {1793505600 -10800 0 PMST} {1805000400 -7200 1 PMDT} {1825560000 -10800 0 PMST} {1836450000 -7200 1 PMDT} {1857009600 -10800 0 PMST} {1867899600 -7200 1 PMDT} {1888459200 -10800 0 PMST} {1899349200 -7200 1 PMDT} {1919908800 -10800 0 PMST} {1930798800 -7200 1 PMDT} {1951358400 -10800 0 PMST} {1962853200 -7200 1 PMDT} {1983412800 -10800 0 PMST} {1994302800 -7200 1 PMDT} {2014862400 -10800 0 PMST} {2025752400 -7200 1 PMDT} {2046312000 -10800 0 PMST} {2057202000 -7200 1 PMDT} {2077761600 -10800 0 PMST} {2088651600 -7200 1 PMDT} {2109211200 -10800 0 PMST} {2120101200 -7200 1 PMDT} {2140660800 -10800 0 PMST} {2152155600 -7200 1 PMDT} {2172715200 -10800 0 PMST} {2183605200 -7200 1 PMDT} {2204164800 -10800 0 PMST} {2215054800 -7200 1 PMDT} {2235614400 -10800 0 PMST} {2246504400 -7200 1 PMDT} {2267064000 -10800 0 PMST} {2277954000 -7200 1 PMDT} {2298513600 -10800 0 PMST} {2309403600 -7200 1 PMDT} {2329963200 -10800 0 PMST} {2341458000 -7200 1 PMDT} {2362017600 -10800 0 PMST} {2372907600 -7200 1 PMDT} {2393467200 -10800 0 PMST} {2404357200 -7200 1 PMDT} {2424916800 -10800 0 PMST} {2435806800 -7200 1 PMDT} {2456366400 -10800 0 PMST} {2467256400 -7200 1 PMDT} {2487816000 -10800 0 PMST} {2499310800 -7200 1 PMDT} {2519870400 -10800 0 PMST} {2530760400 -7200 1 PMDT} {2551320000 -10800 0 PMST} {2562210000 -7200 1 PMDT} {2582769600 -10800 0 PMST} {2593659600 -7200 1 PMDT} {2614219200 -10800 0 PMST} {2625109200 -7200 1 PMDT} {2645668800 -10800 0 PMST} {2656558800 -7200 1 PMDT} {2677118400 -10800 0 PMST} {2688613200 -7200 1 PMDT} {2709172800 -10800 0 PMST} {2720062800 -7200 1 PMDT} {2740622400 -10800 0 PMST} {2751512400 -7200 1 PMDT} {2772072000 -10800 0 PMST} {2782962000 -7200 1 PMDT} {2803521600 -10800 0 PMST} {2814411600 -7200 1 PMDT} {2834971200 -10800 0 PMST} {2846466000 -7200 1 PMDT} {2867025600 -10800 0 PMST} {2877915600 -7200 1 PMDT} {2898475200 -10800 0 PMST} {2909365200 -7200 1 PMDT} {2929924800 -10800 0 PMST} {2940814800 -7200 1 PMDT} {2961374400 -10800 0 PMST} {2972264400 -7200 1 PMDT} {2992824000 -10800 0 PMST} {3003714000 -7200 1 PMDT} {3024273600 -10800 0 PMST} {3035768400 -7200 1 PMDT} {3056328000 -10800 0 PMST} {3067218000 -7200 1 PMDT} {3087777600 -10800 0 PMST} {3098667600 -7200 1 PMDT} {3119227200 -10800 0 PMST} {3130117200 -7200 1 PMDT} {3150676800 -10800 0 PMST} {3161566800 -7200 1 PMDT} {3182126400 -10800 0 PMST} {3193016400 -7200 1 PMDT} {3213576000 -10800 0 PMST} {3225070800 -7200 1 PMDT} {3245630400 -10800 0 PMST} {3256520400 -7200 1 PMDT} {3277080000 -10800 0 PMST} {3287970000 -7200 1 PMDT} {3308529600 -10800 0 PMST} {3319419600 -7200 1 PMDT} {3339979200 -10800 0 PMST} {3350869200 -7200 1 PMDT} {3371428800 -10800 0 PMST} {3382923600 -7200 1 PMDT} {3403483200 -10800 0 PMST} {3414373200 -7200 1 PMDT} {3434932800 -10800 0 PMST} {3445822800 -7200 1 PMDT} {3466382400 -10800 0 PMST} {3477272400 -7200 1 PMDT} {3497832000 -10800 0 PMST} {3508722000 -7200 1 PMDT} {3529281600 -10800 0 PMST} {3540171600 -7200 1 PMDT} {3560731200 -10800 0 PMST} {3572226000 -7200 1 PMDT} {3592785600 -10800 0 PMST} {3603675600 -7200 1 PMDT} {3624235200 -10800 0 PMST} {3635125200 -7200 1 PMDT} {3655684800 -10800 0 PMST} {3666574800 -7200 1 PMDT} {3687134400 -10800 0 PMST} {3698024400 -7200 1 PMDT} {3718584000 -10800 0 PMST} {3730078800 -7200 1 PMDT} {3750638400 -10800 0 PMST} {3761528400 -7200 1 PMDT} {3782088000 -10800 0 PMST} {3792978000 -7200 1 PMDT} {3813537600 -10800 0 PMST} {3824427600 -7200 1 PMDT} {3844987200 -10800 0 PMST} {3855877200 -7200 1 PMDT} {3876436800 -10800 0 PMST} {3887326800 -7200 1 PMDT} {3907886400 -10800 0 PMST} {3919381200 -7200 1 PMDT} {3939940800 -10800 0 PMST} {3950830800 -7200 1 PMDT} {3971390400 -10800 0 PMST} {3982280400 -7200 1 PMDT} {4002840000 -10800 0 PMST} {4013730000 -7200 1 PMDT} {4034289600 -10800 0 PMST} {4045179600 -7200 1 PMDT} {4065739200 -10800 0 PMST} {4076629200 -7200 1 PMDT} {4097188800 -10800 0 PMST} } tcl8.6.5/library/tzdata/America/Cancun0000644000175000017500000000252512663660066017222 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Cancun) { {-9223372036854775808 -20824 0 LMT} {-1514743200 -21600 0 CST} {377935200 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {902041200 -18000 0 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972802800 -21600 0 CST} {989136000 -18000 1 CDT} {1001833200 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1175414400 -18000 1 CDT} {1193554800 -21600 0 CST} {1207468800 -18000 1 CDT} {1225004400 -21600 0 CST} {1238918400 -18000 1 CDT} {1256454000 -21600 0 CST} {1270368000 -18000 1 CDT} {1288508400 -21600 0 CST} {1301817600 -18000 1 CDT} {1319958000 -21600 0 CST} {1333267200 -18000 1 CDT} {1351407600 -21600 0 CST} {1365321600 -18000 1 CDT} {1382857200 -21600 0 CST} {1396771200 -18000 1 CDT} {1414306800 -21600 0 CST} {1422777600 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Lima0000644000175000017500000000067712661614721016676 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Lima) { {-9223372036854775808 -18492 0 LMT} {-2524503108 -18516 0 LMT} {-1938538284 -14400 0 PEST} {-1002052800 -18000 0 PET} {-986756400 -14400 1 PEST} {-971035200 -18000 0 PET} {-955306800 -14400 1 PEST} {-939585600 -18000 0 PET} {512712000 -18000 0 PET} {544248000 -18000 0 PET} {638942400 -18000 0 PET} {765172800 -18000 0 PET} } tcl8.6.5/library/tzdata/America/Aruba0000644000175000017500000000026612663660066017045 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Curacao)]} { LoadTimeZoneFile America/Curacao } set TZData(:America/Aruba) $TZData(:America/Curacao) tcl8.6.5/library/tzdata/America/Atikokan0000644000175000017500000000051412663660066017550 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Atikokan) { {-9223372036854775808 -21988 0 LMT} {-2366733212 -21600 0 CST} {-1632067200 -18000 1 CDT} {-1615136400 -21600 0 CST} {-923248800 -18000 1 CDT} {-880214400 -18000 0 CWT} {-769395600 -18000 1 CPT} {-765388800 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Boa_Vista0000644000175000017500000000222712661614720017653 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Boa_Vista) { {-9223372036854775808 -14560 0 LMT} {-1767211040 -14400 0 AMT} {-1206954000 -10800 1 AMST} {-1191358800 -14400 0 AMT} {-1175371200 -10800 1 AMST} {-1159822800 -14400 0 AMT} {-633816000 -10800 1 AMST} {-622065600 -14400 0 AMT} {-602280000 -10800 1 AMST} {-591829200 -14400 0 AMT} {-570744000 -10800 1 AMST} {-560206800 -14400 0 AMT} {-539121600 -10800 1 AMST} {-531349200 -14400 0 AMT} {-191361600 -10800 1 AMST} {-184194000 -14400 0 AMT} {-155160000 -10800 1 AMST} {-150066000 -14400 0 AMT} {-128894400 -10800 1 AMST} {-121122000 -14400 0 AMT} {-99950400 -10800 1 AMST} {-89586000 -14400 0 AMT} {-68414400 -10800 1 AMST} {-57963600 -14400 0 AMT} {499752000 -10800 1 AMST} {511239600 -14400 0 AMT} {530596800 -10800 1 AMST} {540270000 -14400 0 AMT} {562132800 -10800 1 AMST} {571201200 -14400 0 AMT} {590036400 -14400 0 AMT} {938664000 -14400 0 AMT} {938923200 -10800 1 AMST} {951620400 -14400 0 AMT} {970977600 -10800 1 AMST} {971578800 -14400 0 AMT} } tcl8.6.5/library/tzdata/America/Louisville0000644000175000017500000000033712661614722020135 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Kentucky/Louisville)]} { LoadTimeZoneFile America/Kentucky/Louisville } set TZData(:America/Louisville) $TZData(:America/Kentucky/Louisville) tcl8.6.5/library/tzdata/America/Guadeloupe0000644000175000017500000000031512663660066020100 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/Guadeloupe) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Jujuy0000644000175000017500000000031612661614722017111 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Argentina/Jujuy)]} { LoadTimeZoneFile America/Argentina/Jujuy } set TZData(:America/Jujuy) $TZData(:America/Argentina/Jujuy) tcl8.6.5/library/tzdata/America/Halifax0000644000175000017500000002501312663660066017364 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Halifax) { {-9223372036854775808 -15264 0 LMT} {-2131645536 -14400 0 AST} {-1696276800 -10800 1 ADT} {-1680469200 -14400 0 AST} {-1640980800 -14400 0 AST} {-1632074400 -10800 1 ADT} {-1615143600 -14400 0 AST} {-1609444800 -14400 0 AST} {-1566763200 -10800 1 ADT} {-1557090000 -14400 0 AST} {-1535486400 -10800 1 ADT} {-1524949200 -14400 0 AST} {-1504468800 -10800 1 ADT} {-1493413200 -14400 0 AST} {-1472414400 -10800 1 ADT} {-1461963600 -14400 0 AST} {-1440964800 -10800 1 ADT} {-1429390800 -14400 0 AST} {-1409515200 -10800 1 ADT} {-1396731600 -14400 0 AST} {-1376856000 -10800 1 ADT} {-1366491600 -14400 0 AST} {-1346616000 -10800 1 ADT} {-1333832400 -14400 0 AST} {-1313956800 -10800 1 ADT} {-1303678800 -14400 0 AST} {-1282507200 -10800 1 ADT} {-1272661200 -14400 0 AST} {-1251057600 -10800 1 ADT} {-1240088400 -14400 0 AST} {-1219608000 -10800 1 ADT} {-1207429200 -14400 0 AST} {-1188763200 -10800 1 ADT} {-1175979600 -14400 0 AST} {-1157313600 -10800 1 ADT} {-1143925200 -14400 0 AST} {-1124049600 -10800 1 ADT} {-1113771600 -14400 0 AST} {-1091390400 -10800 1 ADT} {-1081026000 -14400 0 AST} {-1059854400 -10800 1 ADT} {-1050786000 -14400 0 AST} {-1030910400 -10800 1 ADT} {-1018126800 -14400 0 AST} {-999460800 -10800 1 ADT} {-986677200 -14400 0 AST} {-965592000 -10800 1 ADT} {-955227600 -14400 0 AST} {-935956800 -10800 1 ADT} {-923173200 -14400 0 AST} {-904507200 -10800 1 ADT} {-891723600 -14400 0 AST} {-880221600 -10800 0 AWT} {-769395600 -10800 1 APT} {-765399600 -14400 0 AST} {-757368000 -14400 0 AST} {-747252000 -10800 1 ADT} {-733950000 -14400 0 AST} {-715802400 -10800 1 ADT} {-702500400 -14400 0 AST} {-684352800 -10800 1 ADT} {-671050800 -14400 0 AST} {-652903200 -10800 1 ADT} {-639601200 -14400 0 AST} {-589399200 -10800 1 ADT} {-576097200 -14400 0 AST} {-557949600 -10800 1 ADT} {-544647600 -14400 0 AST} {-526500000 -10800 1 ADT} {-513198000 -14400 0 AST} {-495050400 -10800 1 ADT} {-481748400 -14400 0 AST} {-431546400 -10800 1 ADT} {-418244400 -14400 0 AST} {-400096800 -10800 1 ADT} {-386794800 -14400 0 AST} {-368647200 -10800 1 ADT} {-355345200 -14400 0 AST} {-337197600 -10800 1 ADT} {-323895600 -14400 0 AST} {-242244000 -10800 1 ADT} {-226522800 -14400 0 AST} {-210794400 -10800 1 ADT} {-195073200 -14400 0 AST} {-179344800 -10800 1 ADT} {-163623600 -14400 0 AST} {-147895200 -10800 1 ADT} {-131569200 -14400 0 AST} {-116445600 -10800 1 ADT} {-100119600 -14400 0 AST} {-84391200 -10800 1 ADT} {-68670000 -14400 0 AST} {-52941600 -10800 1 ADT} {-37220400 -14400 0 AST} {-21492000 -10800 1 ADT} {-5770800 -14400 0 AST} {9957600 -10800 1 ADT} {25678800 -14400 0 AST} {41407200 -10800 1 ADT} {57733200 -14400 0 AST} {73461600 -10800 1 ADT} {89182800 -14400 0 AST} {104911200 -10800 1 ADT} {120632400 -14400 0 AST} {126244800 -14400 0 AST} {136360800 -10800 1 ADT} {152082000 -14400 0 AST} {167810400 -10800 1 ADT} {183531600 -14400 0 AST} {199260000 -10800 1 ADT} {215586000 -14400 0 AST} {230709600 -10800 1 ADT} {247035600 -14400 0 AST} {262764000 -10800 1 ADT} {278485200 -14400 0 AST} {294213600 -10800 1 ADT} {309934800 -14400 0 AST} {325663200 -10800 1 ADT} {341384400 -14400 0 AST} {357112800 -10800 1 ADT} {372834000 -14400 0 AST} {388562400 -10800 1 ADT} {404888400 -14400 0 AST} {420012000 -10800 1 ADT} {436338000 -14400 0 AST} {452066400 -10800 1 ADT} {467787600 -14400 0 AST} {483516000 -10800 1 ADT} {499237200 -14400 0 AST} {514965600 -10800 1 ADT} {530686800 -14400 0 AST} {544600800 -10800 1 ADT} {562136400 -14400 0 AST} {576050400 -10800 1 ADT} {594190800 -14400 0 AST} {607500000 -10800 1 ADT} {625640400 -14400 0 AST} {638949600 -10800 1 ADT} {657090000 -14400 0 AST} {671004000 -10800 1 ADT} {688539600 -14400 0 AST} {702453600 -10800 1 ADT} {719989200 -14400 0 AST} {733903200 -10800 1 ADT} {752043600 -14400 0 AST} {765352800 -10800 1 ADT} {783493200 -14400 0 AST} {796802400 -10800 1 ADT} {814942800 -14400 0 AST} {828856800 -10800 1 ADT} {846392400 -14400 0 AST} {860306400 -10800 1 ADT} {877842000 -14400 0 AST} {891756000 -10800 1 ADT} {909291600 -14400 0 AST} {923205600 -10800 1 ADT} {941346000 -14400 0 AST} {954655200 -10800 1 ADT} {972795600 -14400 0 AST} {986104800 -10800 1 ADT} {1004245200 -14400 0 AST} {1018159200 -10800 1 ADT} {1035694800 -14400 0 AST} {1049608800 -10800 1 ADT} {1067144400 -14400 0 AST} {1081058400 -10800 1 ADT} {1099198800 -14400 0 AST} {1112508000 -10800 1 ADT} {1130648400 -14400 0 AST} {1143957600 -10800 1 ADT} {1162098000 -14400 0 AST} {1173592800 -10800 1 ADT} {1194152400 -14400 0 AST} {1205042400 -10800 1 ADT} {1225602000 -14400 0 AST} {1236492000 -10800 1 ADT} {1257051600 -14400 0 AST} {1268546400 -10800 1 ADT} {1289106000 -14400 0 AST} {1299996000 -10800 1 ADT} {1320555600 -14400 0 AST} {1331445600 -10800 1 ADT} {1352005200 -14400 0 AST} {1362895200 -10800 1 ADT} {1383454800 -14400 0 AST} {1394344800 -10800 1 ADT} {1414904400 -14400 0 AST} {1425794400 -10800 1 ADT} {1446354000 -14400 0 AST} {1457848800 -10800 1 ADT} {1478408400 -14400 0 AST} {1489298400 -10800 1 ADT} {1509858000 -14400 0 AST} {1520748000 -10800 1 ADT} {1541307600 -14400 0 AST} {1552197600 -10800 1 ADT} {1572757200 -14400 0 AST} {1583647200 -10800 1 ADT} {1604206800 -14400 0 AST} {1615701600 -10800 1 ADT} {1636261200 -14400 0 AST} {1647151200 -10800 1 ADT} {1667710800 -14400 0 AST} {1678600800 -10800 1 ADT} {1699160400 -14400 0 AST} {1710050400 -10800 1 ADT} {1730610000 -14400 0 AST} {1741500000 -10800 1 ADT} {1762059600 -14400 0 AST} {1772949600 -10800 1 ADT} {1793509200 -14400 0 AST} {1805004000 -10800 1 ADT} {1825563600 -14400 0 AST} {1836453600 -10800 1 ADT} {1857013200 -14400 0 AST} {1867903200 -10800 1 ADT} {1888462800 -14400 0 AST} {1899352800 -10800 1 ADT} {1919912400 -14400 0 AST} {1930802400 -10800 1 ADT} {1951362000 -14400 0 AST} {1962856800 -10800 1 ADT} {1983416400 -14400 0 AST} {1994306400 -10800 1 ADT} {2014866000 -14400 0 AST} {2025756000 -10800 1 ADT} {2046315600 -14400 0 AST} {2057205600 -10800 1 ADT} {2077765200 -14400 0 AST} {2088655200 -10800 1 ADT} {2109214800 -14400 0 AST} {2120104800 -10800 1 ADT} {2140664400 -14400 0 AST} {2152159200 -10800 1 ADT} {2172718800 -14400 0 AST} {2183608800 -10800 1 ADT} {2204168400 -14400 0 AST} {2215058400 -10800 1 ADT} {2235618000 -14400 0 AST} {2246508000 -10800 1 ADT} {2267067600 -14400 0 AST} {2277957600 -10800 1 ADT} {2298517200 -14400 0 AST} {2309407200 -10800 1 ADT} {2329966800 -14400 0 AST} {2341461600 -10800 1 ADT} {2362021200 -14400 0 AST} {2372911200 -10800 1 ADT} {2393470800 -14400 0 AST} {2404360800 -10800 1 ADT} {2424920400 -14400 0 AST} {2435810400 -10800 1 ADT} {2456370000 -14400 0 AST} {2467260000 -10800 1 ADT} {2487819600 -14400 0 AST} {2499314400 -10800 1 ADT} {2519874000 -14400 0 AST} {2530764000 -10800 1 ADT} {2551323600 -14400 0 AST} {2562213600 -10800 1 ADT} {2582773200 -14400 0 AST} {2593663200 -10800 1 ADT} {2614222800 -14400 0 AST} {2625112800 -10800 1 ADT} {2645672400 -14400 0 AST} {2656562400 -10800 1 ADT} {2677122000 -14400 0 AST} {2688616800 -10800 1 ADT} {2709176400 -14400 0 AST} {2720066400 -10800 1 ADT} {2740626000 -14400 0 AST} {2751516000 -10800 1 ADT} {2772075600 -14400 0 AST} {2782965600 -10800 1 ADT} {2803525200 -14400 0 AST} {2814415200 -10800 1 ADT} {2834974800 -14400 0 AST} {2846469600 -10800 1 ADT} {2867029200 -14400 0 AST} {2877919200 -10800 1 ADT} {2898478800 -14400 0 AST} {2909368800 -10800 1 ADT} {2929928400 -14400 0 AST} {2940818400 -10800 1 ADT} {2961378000 -14400 0 AST} {2972268000 -10800 1 ADT} {2992827600 -14400 0 AST} {3003717600 -10800 1 ADT} {3024277200 -14400 0 AST} {3035772000 -10800 1 ADT} {3056331600 -14400 0 AST} {3067221600 -10800 1 ADT} {3087781200 -14400 0 AST} {3098671200 -10800 1 ADT} {3119230800 -14400 0 AST} {3130120800 -10800 1 ADT} {3150680400 -14400 0 AST} {3161570400 -10800 1 ADT} {3182130000 -14400 0 AST} {3193020000 -10800 1 ADT} {3213579600 -14400 0 AST} {3225074400 -10800 1 ADT} {3245634000 -14400 0 AST} {3256524000 -10800 1 ADT} {3277083600 -14400 0 AST} {3287973600 -10800 1 ADT} {3308533200 -14400 0 AST} {3319423200 -10800 1 ADT} {3339982800 -14400 0 AST} {3350872800 -10800 1 ADT} {3371432400 -14400 0 AST} {3382927200 -10800 1 ADT} {3403486800 -14400 0 AST} {3414376800 -10800 1 ADT} {3434936400 -14400 0 AST} {3445826400 -10800 1 ADT} {3466386000 -14400 0 AST} {3477276000 -10800 1 ADT} {3497835600 -14400 0 AST} {3508725600 -10800 1 ADT} {3529285200 -14400 0 AST} {3540175200 -10800 1 ADT} {3560734800 -14400 0 AST} {3572229600 -10800 1 ADT} {3592789200 -14400 0 AST} {3603679200 -10800 1 ADT} {3624238800 -14400 0 AST} {3635128800 -10800 1 ADT} {3655688400 -14400 0 AST} {3666578400 -10800 1 ADT} {3687138000 -14400 0 AST} {3698028000 -10800 1 ADT} {3718587600 -14400 0 AST} {3730082400 -10800 1 ADT} {3750642000 -14400 0 AST} {3761532000 -10800 1 ADT} {3782091600 -14400 0 AST} {3792981600 -10800 1 ADT} {3813541200 -14400 0 AST} {3824431200 -10800 1 ADT} {3844990800 -14400 0 AST} {3855880800 -10800 1 ADT} {3876440400 -14400 0 AST} {3887330400 -10800 1 ADT} {3907890000 -14400 0 AST} {3919384800 -10800 1 ADT} {3939944400 -14400 0 AST} {3950834400 -10800 1 ADT} {3971394000 -14400 0 AST} {3982284000 -10800 1 ADT} {4002843600 -14400 0 AST} {4013733600 -10800 1 ADT} {4034293200 -14400 0 AST} {4045183200 -10800 1 ADT} {4065742800 -14400 0 AST} {4076632800 -10800 1 ADT} {4097192400 -14400 0 AST} } tcl8.6.5/library/tzdata/America/Antigua0000644000175000017500000000031212663660066017373 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/Antigua) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Glace_Bay0000644000175000017500000001764312663660066017630 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Glace_Bay) { {-9223372036854775808 -14388 0 LMT} {-2131646412 -14400 0 AST} {-1632074400 -10800 1 ADT} {-1615143600 -14400 0 AST} {-880221600 -10800 1 AWT} {-769395600 -10800 1 APT} {-765399600 -14400 0 AST} {-536443200 -14400 0 AST} {-526500000 -10800 1 ADT} {-513198000 -14400 0 AST} {-504907200 -14400 0 AST} {63086400 -14400 0 AST} {73461600 -10800 1 ADT} {89182800 -14400 0 AST} {104911200 -10800 1 ADT} {120632400 -14400 0 AST} {126244800 -14400 0 AST} {136360800 -10800 1 ADT} {152082000 -14400 0 AST} {167810400 -10800 1 ADT} {183531600 -14400 0 AST} {199260000 -10800 1 ADT} {215586000 -14400 0 AST} {230709600 -10800 1 ADT} {247035600 -14400 0 AST} {262764000 -10800 1 ADT} {278485200 -14400 0 AST} {294213600 -10800 1 ADT} {309934800 -14400 0 AST} {325663200 -10800 1 ADT} {341384400 -14400 0 AST} {357112800 -10800 1 ADT} {372834000 -14400 0 AST} {388562400 -10800 1 ADT} {404888400 -14400 0 AST} {420012000 -10800 1 ADT} {436338000 -14400 0 AST} {452066400 -10800 1 ADT} {467787600 -14400 0 AST} {483516000 -10800 1 ADT} {499237200 -14400 0 AST} {514965600 -10800 1 ADT} {530686800 -14400 0 AST} {544600800 -10800 1 ADT} {562136400 -14400 0 AST} {576050400 -10800 1 ADT} {594190800 -14400 0 AST} {607500000 -10800 1 ADT} {625640400 -14400 0 AST} {638949600 -10800 1 ADT} {657090000 -14400 0 AST} {671004000 -10800 1 ADT} {688539600 -14400 0 AST} {702453600 -10800 1 ADT} {719989200 -14400 0 AST} {733903200 -10800 1 ADT} {752043600 -14400 0 AST} {765352800 -10800 1 ADT} {783493200 -14400 0 AST} {796802400 -10800 1 ADT} {814942800 -14400 0 AST} {828856800 -10800 1 ADT} {846392400 -14400 0 AST} {860306400 -10800 1 ADT} {877842000 -14400 0 AST} {891756000 -10800 1 ADT} {909291600 -14400 0 AST} {923205600 -10800 1 ADT} {941346000 -14400 0 AST} {954655200 -10800 1 ADT} {972795600 -14400 0 AST} {986104800 -10800 1 ADT} {1004245200 -14400 0 AST} {1018159200 -10800 1 ADT} {1035694800 -14400 0 AST} {1049608800 -10800 1 ADT} {1067144400 -14400 0 AST} {1081058400 -10800 1 ADT} {1099198800 -14400 0 AST} {1112508000 -10800 1 ADT} {1130648400 -14400 0 AST} {1143957600 -10800 1 ADT} {1162098000 -14400 0 AST} {1173592800 -10800 1 ADT} {1194152400 -14400 0 AST} {1205042400 -10800 1 ADT} {1225602000 -14400 0 AST} {1236492000 -10800 1 ADT} {1257051600 -14400 0 AST} {1268546400 -10800 1 ADT} {1289106000 -14400 0 AST} {1299996000 -10800 1 ADT} {1320555600 -14400 0 AST} {1331445600 -10800 1 ADT} {1352005200 -14400 0 AST} {1362895200 -10800 1 ADT} {1383454800 -14400 0 AST} {1394344800 -10800 1 ADT} {1414904400 -14400 0 AST} {1425794400 -10800 1 ADT} {1446354000 -14400 0 AST} {1457848800 -10800 1 ADT} {1478408400 -14400 0 AST} {1489298400 -10800 1 ADT} {1509858000 -14400 0 AST} {1520748000 -10800 1 ADT} {1541307600 -14400 0 AST} {1552197600 -10800 1 ADT} {1572757200 -14400 0 AST} {1583647200 -10800 1 ADT} {1604206800 -14400 0 AST} {1615701600 -10800 1 ADT} {1636261200 -14400 0 AST} {1647151200 -10800 1 ADT} {1667710800 -14400 0 AST} {1678600800 -10800 1 ADT} {1699160400 -14400 0 AST} {1710050400 -10800 1 ADT} {1730610000 -14400 0 AST} {1741500000 -10800 1 ADT} {1762059600 -14400 0 AST} {1772949600 -10800 1 ADT} {1793509200 -14400 0 AST} {1805004000 -10800 1 ADT} {1825563600 -14400 0 AST} {1836453600 -10800 1 ADT} {1857013200 -14400 0 AST} {1867903200 -10800 1 ADT} {1888462800 -14400 0 AST} {1899352800 -10800 1 ADT} {1919912400 -14400 0 AST} {1930802400 -10800 1 ADT} {1951362000 -14400 0 AST} {1962856800 -10800 1 ADT} {1983416400 -14400 0 AST} {1994306400 -10800 1 ADT} {2014866000 -14400 0 AST} {2025756000 -10800 1 ADT} {2046315600 -14400 0 AST} {2057205600 -10800 1 ADT} {2077765200 -14400 0 AST} {2088655200 -10800 1 ADT} {2109214800 -14400 0 AST} {2120104800 -10800 1 ADT} {2140664400 -14400 0 AST} {2152159200 -10800 1 ADT} {2172718800 -14400 0 AST} {2183608800 -10800 1 ADT} {2204168400 -14400 0 AST} {2215058400 -10800 1 ADT} {2235618000 -14400 0 AST} {2246508000 -10800 1 ADT} {2267067600 -14400 0 AST} {2277957600 -10800 1 ADT} {2298517200 -14400 0 AST} {2309407200 -10800 1 ADT} {2329966800 -14400 0 AST} {2341461600 -10800 1 ADT} {2362021200 -14400 0 AST} {2372911200 -10800 1 ADT} {2393470800 -14400 0 AST} {2404360800 -10800 1 ADT} {2424920400 -14400 0 AST} {2435810400 -10800 1 ADT} {2456370000 -14400 0 AST} {2467260000 -10800 1 ADT} {2487819600 -14400 0 AST} {2499314400 -10800 1 ADT} {2519874000 -14400 0 AST} {2530764000 -10800 1 ADT} {2551323600 -14400 0 AST} {2562213600 -10800 1 ADT} {2582773200 -14400 0 AST} {2593663200 -10800 1 ADT} {2614222800 -14400 0 AST} {2625112800 -10800 1 ADT} {2645672400 -14400 0 AST} {2656562400 -10800 1 ADT} {2677122000 -14400 0 AST} {2688616800 -10800 1 ADT} {2709176400 -14400 0 AST} {2720066400 -10800 1 ADT} {2740626000 -14400 0 AST} {2751516000 -10800 1 ADT} {2772075600 -14400 0 AST} {2782965600 -10800 1 ADT} {2803525200 -14400 0 AST} {2814415200 -10800 1 ADT} {2834974800 -14400 0 AST} {2846469600 -10800 1 ADT} {2867029200 -14400 0 AST} {2877919200 -10800 1 ADT} {2898478800 -14400 0 AST} {2909368800 -10800 1 ADT} {2929928400 -14400 0 AST} {2940818400 -10800 1 ADT} {2961378000 -14400 0 AST} {2972268000 -10800 1 ADT} {2992827600 -14400 0 AST} {3003717600 -10800 1 ADT} {3024277200 -14400 0 AST} {3035772000 -10800 1 ADT} {3056331600 -14400 0 AST} {3067221600 -10800 1 ADT} {3087781200 -14400 0 AST} {3098671200 -10800 1 ADT} {3119230800 -14400 0 AST} {3130120800 -10800 1 ADT} {3150680400 -14400 0 AST} {3161570400 -10800 1 ADT} {3182130000 -14400 0 AST} {3193020000 -10800 1 ADT} {3213579600 -14400 0 AST} {3225074400 -10800 1 ADT} {3245634000 -14400 0 AST} {3256524000 -10800 1 ADT} {3277083600 -14400 0 AST} {3287973600 -10800 1 ADT} {3308533200 -14400 0 AST} {3319423200 -10800 1 ADT} {3339982800 -14400 0 AST} {3350872800 -10800 1 ADT} {3371432400 -14400 0 AST} {3382927200 -10800 1 ADT} {3403486800 -14400 0 AST} {3414376800 -10800 1 ADT} {3434936400 -14400 0 AST} {3445826400 -10800 1 ADT} {3466386000 -14400 0 AST} {3477276000 -10800 1 ADT} {3497835600 -14400 0 AST} {3508725600 -10800 1 ADT} {3529285200 -14400 0 AST} {3540175200 -10800 1 ADT} {3560734800 -14400 0 AST} {3572229600 -10800 1 ADT} {3592789200 -14400 0 AST} {3603679200 -10800 1 ADT} {3624238800 -14400 0 AST} {3635128800 -10800 1 ADT} {3655688400 -14400 0 AST} {3666578400 -10800 1 ADT} {3687138000 -14400 0 AST} {3698028000 -10800 1 ADT} {3718587600 -14400 0 AST} {3730082400 -10800 1 ADT} {3750642000 -14400 0 AST} {3761532000 -10800 1 ADT} {3782091600 -14400 0 AST} {3792981600 -10800 1 ADT} {3813541200 -14400 0 AST} {3824431200 -10800 1 ADT} {3844990800 -14400 0 AST} {3855880800 -10800 1 ADT} {3876440400 -14400 0 AST} {3887330400 -10800 1 ADT} {3907890000 -14400 0 AST} {3919384800 -10800 1 ADT} {3939944400 -14400 0 AST} {3950834400 -10800 1 ADT} {3971394000 -14400 0 AST} {3982284000 -10800 1 ADT} {4002843600 -14400 0 AST} {4013733600 -10800 1 ADT} {4034293200 -14400 0 AST} {4045183200 -10800 1 ADT} {4065742800 -14400 0 AST} {4076632800 -10800 1 ADT} {4097192400 -14400 0 AST} } tcl8.6.5/library/tzdata/America/Tortola0000644000175000017500000000031212663660066017427 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/Tortola) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/El_Salvador0000644000175000017500000000041512661614720020174 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/El_Salvador) { {-9223372036854775808 -21408 0 LMT} {-1546279392 -21600 0 CST} {547020000 -18000 1 CDT} {559717200 -21600 0 CST} {578469600 -18000 1 CDT} {591166800 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Chihuahua0000644000175000017500000001470112661614720017703 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Chihuahua) { {-9223372036854775808 -25460 0 LMT} {-1514739600 -25200 0 MST} {-1343066400 -21600 0 CST} {-1234807200 -25200 0 MST} {-1220292000 -21600 0 CST} {-1207159200 -25200 0 MST} {-1191344400 -21600 0 CST} {820476000 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {883634400 -21600 0 CST} {891766800 -21600 0 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {989139600 -21600 1 MDT} {1001836800 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1175418000 -21600 1 MDT} {1193558400 -25200 0 MST} {1207472400 -21600 1 MDT} {1225008000 -25200 0 MST} {1238922000 -21600 1 MDT} {1256457600 -25200 0 MST} {1270371600 -21600 1 MDT} {1288512000 -25200 0 MST} {1301821200 -21600 1 MDT} {1319961600 -25200 0 MST} {1333270800 -21600 1 MDT} {1351411200 -25200 0 MST} {1365325200 -21600 1 MDT} {1382860800 -25200 0 MST} {1396774800 -21600 1 MDT} {1414310400 -25200 0 MST} {1428224400 -21600 1 MDT} {1445760000 -25200 0 MST} {1459674000 -21600 1 MDT} {1477814400 -25200 0 MST} {1491123600 -21600 1 MDT} {1509264000 -25200 0 MST} {1522573200 -21600 1 MDT} {1540713600 -25200 0 MST} {1554627600 -21600 1 MDT} {1572163200 -25200 0 MST} {1586077200 -21600 1 MDT} {1603612800 -25200 0 MST} {1617526800 -21600 1 MDT} {1635667200 -25200 0 MST} {1648976400 -21600 1 MDT} {1667116800 -25200 0 MST} {1680426000 -21600 1 MDT} {1698566400 -25200 0 MST} {1712480400 -21600 1 MDT} {1730016000 -25200 0 MST} {1743930000 -21600 1 MDT} {1761465600 -25200 0 MST} {1775379600 -21600 1 MDT} {1792915200 -25200 0 MST} {1806829200 -21600 1 MDT} {1824969600 -25200 0 MST} {1838278800 -21600 1 MDT} {1856419200 -25200 0 MST} {1869728400 -21600 1 MDT} {1887868800 -25200 0 MST} {1901782800 -21600 1 MDT} {1919318400 -25200 0 MST} {1933232400 -21600 1 MDT} {1950768000 -25200 0 MST} {1964682000 -21600 1 MDT} {1982822400 -25200 0 MST} {1996131600 -21600 1 MDT} {2014272000 -25200 0 MST} {2027581200 -21600 1 MDT} {2045721600 -25200 0 MST} {2059030800 -21600 1 MDT} {2077171200 -25200 0 MST} {2091085200 -21600 1 MDT} {2108620800 -25200 0 MST} {2122534800 -21600 1 MDT} {2140070400 -25200 0 MST} {2153984400 -21600 1 MDT} {2172124800 -25200 0 MST} {2185434000 -21600 1 MDT} {2203574400 -25200 0 MST} {2216883600 -21600 1 MDT} {2235024000 -25200 0 MST} {2248938000 -21600 1 MDT} {2266473600 -25200 0 MST} {2280387600 -21600 1 MDT} {2297923200 -25200 0 MST} {2311837200 -21600 1 MDT} {2329372800 -25200 0 MST} {2343286800 -21600 1 MDT} {2361427200 -25200 0 MST} {2374736400 -21600 1 MDT} {2392876800 -25200 0 MST} {2406186000 -21600 1 MDT} {2424326400 -25200 0 MST} {2438240400 -21600 1 MDT} {2455776000 -25200 0 MST} {2469690000 -21600 1 MDT} {2487225600 -25200 0 MST} {2501139600 -21600 1 MDT} {2519280000 -25200 0 MST} {2532589200 -21600 1 MDT} {2550729600 -25200 0 MST} {2564038800 -21600 1 MDT} {2582179200 -25200 0 MST} {2596093200 -21600 1 MDT} {2613628800 -25200 0 MST} {2627542800 -21600 1 MDT} {2645078400 -25200 0 MST} {2658992400 -21600 1 MDT} {2676528000 -25200 0 MST} {2690442000 -21600 1 MDT} {2708582400 -25200 0 MST} {2721891600 -21600 1 MDT} {2740032000 -25200 0 MST} {2753341200 -21600 1 MDT} {2771481600 -25200 0 MST} {2785395600 -21600 1 MDT} {2802931200 -25200 0 MST} {2816845200 -21600 1 MDT} {2834380800 -25200 0 MST} {2848294800 -21600 1 MDT} {2866435200 -25200 0 MST} {2879744400 -21600 1 MDT} {2897884800 -25200 0 MST} {2911194000 -21600 1 MDT} {2929334400 -25200 0 MST} {2942643600 -21600 1 MDT} {2960784000 -25200 0 MST} {2974698000 -21600 1 MDT} {2992233600 -25200 0 MST} {3006147600 -21600 1 MDT} {3023683200 -25200 0 MST} {3037597200 -21600 1 MDT} {3055737600 -25200 0 MST} {3069046800 -21600 1 MDT} {3087187200 -25200 0 MST} {3100496400 -21600 1 MDT} {3118636800 -25200 0 MST} {3132550800 -21600 1 MDT} {3150086400 -25200 0 MST} {3164000400 -21600 1 MDT} {3181536000 -25200 0 MST} {3195450000 -21600 1 MDT} {3212985600 -25200 0 MST} {3226899600 -21600 1 MDT} {3245040000 -25200 0 MST} {3258349200 -21600 1 MDT} {3276489600 -25200 0 MST} {3289798800 -21600 1 MDT} {3307939200 -25200 0 MST} {3321853200 -21600 1 MDT} {3339388800 -25200 0 MST} {3353302800 -21600 1 MDT} {3370838400 -25200 0 MST} {3384752400 -21600 1 MDT} {3402892800 -25200 0 MST} {3416202000 -21600 1 MDT} {3434342400 -25200 0 MST} {3447651600 -21600 1 MDT} {3465792000 -25200 0 MST} {3479706000 -21600 1 MDT} {3497241600 -25200 0 MST} {3511155600 -21600 1 MDT} {3528691200 -25200 0 MST} {3542605200 -21600 1 MDT} {3560140800 -25200 0 MST} {3574054800 -21600 1 MDT} {3592195200 -25200 0 MST} {3605504400 -21600 1 MDT} {3623644800 -25200 0 MST} {3636954000 -21600 1 MDT} {3655094400 -25200 0 MST} {3669008400 -21600 1 MDT} {3686544000 -25200 0 MST} {3700458000 -21600 1 MDT} {3717993600 -25200 0 MST} {3731907600 -21600 1 MDT} {3750048000 -25200 0 MST} {3763357200 -21600 1 MDT} {3781497600 -25200 0 MST} {3794806800 -21600 1 MDT} {3812947200 -25200 0 MST} {3826256400 -21600 1 MDT} {3844396800 -25200 0 MST} {3858310800 -21600 1 MDT} {3875846400 -25200 0 MST} {3889760400 -21600 1 MDT} {3907296000 -25200 0 MST} {3921210000 -21600 1 MDT} {3939350400 -25200 0 MST} {3952659600 -21600 1 MDT} {3970800000 -25200 0 MST} {3984109200 -21600 1 MDT} {4002249600 -25200 0 MST} {4016163600 -21600 1 MDT} {4033699200 -25200 0 MST} {4047613200 -21600 1 MDT} {4065148800 -25200 0 MST} {4079062800 -21600 1 MDT} {4096598400 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Thule0000644000175000017500000001501212661614721017062 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Thule) { {-9223372036854775808 -16508 0 LMT} {-1686079492 -14400 0 AST} {670399200 -10800 1 ADT} {686120400 -14400 0 AST} {701848800 -10800 1 ADT} {717570000 -14400 0 AST} {733903200 -10800 1 ADT} {752043600 -14400 0 AST} {765352800 -10800 1 ADT} {783493200 -14400 0 AST} {796802400 -10800 1 ADT} {814942800 -14400 0 AST} {828856800 -10800 1 ADT} {846392400 -14400 0 AST} {860306400 -10800 1 ADT} {877842000 -14400 0 AST} {891756000 -10800 1 ADT} {909291600 -14400 0 AST} {923205600 -10800 1 ADT} {941346000 -14400 0 AST} {954655200 -10800 1 ADT} {972795600 -14400 0 AST} {986104800 -10800 1 ADT} {1004245200 -14400 0 AST} {1018159200 -10800 1 ADT} {1035694800 -14400 0 AST} {1049608800 -10800 1 ADT} {1067144400 -14400 0 AST} {1081058400 -10800 1 ADT} {1099198800 -14400 0 AST} {1112508000 -10800 1 ADT} {1130648400 -14400 0 AST} {1143957600 -10800 1 ADT} {1162098000 -14400 0 AST} {1173592800 -10800 1 ADT} {1194152400 -14400 0 AST} {1205042400 -10800 1 ADT} {1225602000 -14400 0 AST} {1236492000 -10800 1 ADT} {1257051600 -14400 0 AST} {1268546400 -10800 1 ADT} {1289106000 -14400 0 AST} {1299996000 -10800 1 ADT} {1320555600 -14400 0 AST} {1331445600 -10800 1 ADT} {1352005200 -14400 0 AST} {1362895200 -10800 1 ADT} {1383454800 -14400 0 AST} {1394344800 -10800 1 ADT} {1414904400 -14400 0 AST} {1425794400 -10800 1 ADT} {1446354000 -14400 0 AST} {1457848800 -10800 1 ADT} {1478408400 -14400 0 AST} {1489298400 -10800 1 ADT} {1509858000 -14400 0 AST} {1520748000 -10800 1 ADT} {1541307600 -14400 0 AST} {1552197600 -10800 1 ADT} {1572757200 -14400 0 AST} {1583647200 -10800 1 ADT} {1604206800 -14400 0 AST} {1615701600 -10800 1 ADT} {1636261200 -14400 0 AST} {1647151200 -10800 1 ADT} {1667710800 -14400 0 AST} {1678600800 -10800 1 ADT} {1699160400 -14400 0 AST} {1710050400 -10800 1 ADT} {1730610000 -14400 0 AST} {1741500000 -10800 1 ADT} {1762059600 -14400 0 AST} {1772949600 -10800 1 ADT} {1793509200 -14400 0 AST} {1805004000 -10800 1 ADT} {1825563600 -14400 0 AST} {1836453600 -10800 1 ADT} {1857013200 -14400 0 AST} {1867903200 -10800 1 ADT} {1888462800 -14400 0 AST} {1899352800 -10800 1 ADT} {1919912400 -14400 0 AST} {1930802400 -10800 1 ADT} {1951362000 -14400 0 AST} {1962856800 -10800 1 ADT} {1983416400 -14400 0 AST} {1994306400 -10800 1 ADT} {2014866000 -14400 0 AST} {2025756000 -10800 1 ADT} {2046315600 -14400 0 AST} {2057205600 -10800 1 ADT} {2077765200 -14400 0 AST} {2088655200 -10800 1 ADT} {2109214800 -14400 0 AST} {2120104800 -10800 1 ADT} {2140664400 -14400 0 AST} {2152159200 -10800 1 ADT} {2172718800 -14400 0 AST} {2183608800 -10800 1 ADT} {2204168400 -14400 0 AST} {2215058400 -10800 1 ADT} {2235618000 -14400 0 AST} {2246508000 -10800 1 ADT} {2267067600 -14400 0 AST} {2277957600 -10800 1 ADT} {2298517200 -14400 0 AST} {2309407200 -10800 1 ADT} {2329966800 -14400 0 AST} {2341461600 -10800 1 ADT} {2362021200 -14400 0 AST} {2372911200 -10800 1 ADT} {2393470800 -14400 0 AST} {2404360800 -10800 1 ADT} {2424920400 -14400 0 AST} {2435810400 -10800 1 ADT} {2456370000 -14400 0 AST} {2467260000 -10800 1 ADT} {2487819600 -14400 0 AST} {2499314400 -10800 1 ADT} {2519874000 -14400 0 AST} {2530764000 -10800 1 ADT} {2551323600 -14400 0 AST} {2562213600 -10800 1 ADT} {2582773200 -14400 0 AST} {2593663200 -10800 1 ADT} {2614222800 -14400 0 AST} {2625112800 -10800 1 ADT} {2645672400 -14400 0 AST} {2656562400 -10800 1 ADT} {2677122000 -14400 0 AST} {2688616800 -10800 1 ADT} {2709176400 -14400 0 AST} {2720066400 -10800 1 ADT} {2740626000 -14400 0 AST} {2751516000 -10800 1 ADT} {2772075600 -14400 0 AST} {2782965600 -10800 1 ADT} {2803525200 -14400 0 AST} {2814415200 -10800 1 ADT} {2834974800 -14400 0 AST} {2846469600 -10800 1 ADT} {2867029200 -14400 0 AST} {2877919200 -10800 1 ADT} {2898478800 -14400 0 AST} {2909368800 -10800 1 ADT} {2929928400 -14400 0 AST} {2940818400 -10800 1 ADT} {2961378000 -14400 0 AST} {2972268000 -10800 1 ADT} {2992827600 -14400 0 AST} {3003717600 -10800 1 ADT} {3024277200 -14400 0 AST} {3035772000 -10800 1 ADT} {3056331600 -14400 0 AST} {3067221600 -10800 1 ADT} {3087781200 -14400 0 AST} {3098671200 -10800 1 ADT} {3119230800 -14400 0 AST} {3130120800 -10800 1 ADT} {3150680400 -14400 0 AST} {3161570400 -10800 1 ADT} {3182130000 -14400 0 AST} {3193020000 -10800 1 ADT} {3213579600 -14400 0 AST} {3225074400 -10800 1 ADT} {3245634000 -14400 0 AST} {3256524000 -10800 1 ADT} {3277083600 -14400 0 AST} {3287973600 -10800 1 ADT} {3308533200 -14400 0 AST} {3319423200 -10800 1 ADT} {3339982800 -14400 0 AST} {3350872800 -10800 1 ADT} {3371432400 -14400 0 AST} {3382927200 -10800 1 ADT} {3403486800 -14400 0 AST} {3414376800 -10800 1 ADT} {3434936400 -14400 0 AST} {3445826400 -10800 1 ADT} {3466386000 -14400 0 AST} {3477276000 -10800 1 ADT} {3497835600 -14400 0 AST} {3508725600 -10800 1 ADT} {3529285200 -14400 0 AST} {3540175200 -10800 1 ADT} {3560734800 -14400 0 AST} {3572229600 -10800 1 ADT} {3592789200 -14400 0 AST} {3603679200 -10800 1 ADT} {3624238800 -14400 0 AST} {3635128800 -10800 1 ADT} {3655688400 -14400 0 AST} {3666578400 -10800 1 ADT} {3687138000 -14400 0 AST} {3698028000 -10800 1 ADT} {3718587600 -14400 0 AST} {3730082400 -10800 1 ADT} {3750642000 -14400 0 AST} {3761532000 -10800 1 ADT} {3782091600 -14400 0 AST} {3792981600 -10800 1 ADT} {3813541200 -14400 0 AST} {3824431200 -10800 1 ADT} {3844990800 -14400 0 AST} {3855880800 -10800 1 ADT} {3876440400 -14400 0 AST} {3887330400 -10800 1 ADT} {3907890000 -14400 0 AST} {3919384800 -10800 1 ADT} {3939944400 -14400 0 AST} {3950834400 -10800 1 ADT} {3971394000 -14400 0 AST} {3982284000 -10800 1 ADT} {4002843600 -14400 0 AST} {4013733600 -10800 1 ADT} {4034293200 -14400 0 AST} {4045183200 -10800 1 ADT} {4065742800 -14400 0 AST} {4076632800 -10800 1 ADT} {4097192400 -14400 0 AST} } tcl8.6.5/library/tzdata/America/New_York0000644000175000017500000002537412661614721017552 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/New_York) { {-9223372036854775808 -17762 0 LMT} {-2717650800 -18000 0 EST} {-1633280400 -14400 1 EDT} {-1615140000 -18000 0 EST} {-1601830800 -14400 1 EDT} {-1583690400 -18000 0 EST} {-1577905200 -18000 0 EST} {-1570381200 -14400 1 EDT} {-1551636000 -18000 0 EST} {-1536512400 -14400 1 EDT} {-1523210400 -18000 0 EST} {-1504458000 -14400 1 EDT} {-1491760800 -18000 0 EST} {-1473008400 -14400 1 EDT} {-1459706400 -18000 0 EST} {-1441558800 -14400 1 EDT} {-1428256800 -18000 0 EST} {-1410109200 -14400 1 EDT} {-1396807200 -18000 0 EST} {-1378659600 -14400 1 EDT} {-1365357600 -18000 0 EST} {-1347210000 -14400 1 EDT} {-1333908000 -18000 0 EST} {-1315155600 -14400 1 EDT} {-1301853600 -18000 0 EST} {-1283706000 -14400 1 EDT} {-1270404000 -18000 0 EST} {-1252256400 -14400 1 EDT} {-1238954400 -18000 0 EST} {-1220806800 -14400 1 EDT} {-1207504800 -18000 0 EST} {-1189357200 -14400 1 EDT} {-1176055200 -18000 0 EST} {-1157302800 -14400 1 EDT} {-1144605600 -18000 0 EST} {-1125853200 -14400 1 EDT} {-1112551200 -18000 0 EST} {-1094403600 -14400 1 EDT} {-1081101600 -18000 0 EST} {-1062954000 -14400 1 EDT} {-1049652000 -18000 0 EST} {-1031504400 -14400 1 EDT} {-1018202400 -18000 0 EST} {-1000054800 -14400 1 EDT} {-986752800 -18000 0 EST} {-968000400 -14400 1 EDT} {-955303200 -18000 0 EST} {-936550800 -14400 1 EDT} {-923248800 -18000 0 EST} {-905101200 -14400 1 EDT} {-891799200 -18000 0 EST} {-883594800 -18000 0 EST} {-880218000 -14400 1 EWT} {-769395600 -14400 1 EPT} {-765396000 -18000 0 EST} {-757364400 -18000 0 EST} {-747248400 -14400 1 EDT} {-733946400 -18000 0 EST} {-715798800 -14400 1 EDT} {-702496800 -18000 0 EST} {-684349200 -14400 1 EDT} {-671047200 -18000 0 EST} {-652899600 -14400 1 EDT} {-639597600 -18000 0 EST} {-620845200 -14400 1 EDT} {-608148000 -18000 0 EST} {-589395600 -14400 1 EDT} {-576093600 -18000 0 EST} {-557946000 -14400 1 EDT} {-544644000 -18000 0 EST} {-526496400 -14400 1 EDT} {-513194400 -18000 0 EST} {-495046800 -14400 1 EDT} {-481744800 -18000 0 EST} {-463597200 -14400 1 EDT} {-447271200 -18000 0 EST} {-431542800 -14400 1 EDT} {-415821600 -18000 0 EST} {-400093200 -14400 1 EDT} {-384372000 -18000 0 EST} {-368643600 -14400 1 EDT} {-352922400 -18000 0 EST} {-337194000 -14400 1 EDT} {-321472800 -18000 0 EST} {-305744400 -14400 1 EDT} {-289418400 -18000 0 EST} {-273690000 -14400 1 EDT} {-257968800 -18000 0 EST} {-242240400 -14400 1 EDT} {-226519200 -18000 0 EST} {-210790800 -14400 1 EDT} {-195069600 -18000 0 EST} {-179341200 -14400 1 EDT} {-163620000 -18000 0 EST} {-147891600 -14400 1 EDT} {-131565600 -18000 0 EST} {-116442000 -14400 1 EDT} {-100116000 -18000 0 EST} {-94676400 -18000 0 EST} {-84387600 -14400 1 EDT} {-68666400 -18000 0 EST} {-52938000 -14400 1 EDT} {-37216800 -18000 0 EST} {-21488400 -14400 1 EDT} {-5767200 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {41410800 -14400 1 EDT} {57736800 -18000 0 EST} {73465200 -14400 1 EDT} {89186400 -18000 0 EST} {104914800 -14400 1 EDT} {120636000 -18000 0 EST} {126687600 -14400 1 EDT} {152085600 -18000 0 EST} {162370800 -14400 1 EDT} {183535200 -18000 0 EST} {199263600 -14400 1 EDT} {215589600 -18000 0 EST} {230713200 -14400 1 EDT} {247039200 -18000 0 EST} {262767600 -14400 1 EDT} {278488800 -18000 0 EST} {294217200 -14400 1 EDT} {309938400 -18000 0 EST} {325666800 -14400 1 EDT} {341388000 -18000 0 EST} {357116400 -14400 1 EDT} {372837600 -18000 0 EST} {388566000 -14400 1 EDT} {404892000 -18000 0 EST} {420015600 -14400 1 EDT} {436341600 -18000 0 EST} {452070000 -14400 1 EDT} {467791200 -18000 0 EST} {483519600 -14400 1 EDT} {499240800 -18000 0 EST} {514969200 -14400 1 EDT} {530690400 -18000 0 EST} {544604400 -14400 1 EDT} {562140000 -18000 0 EST} {576054000 -14400 1 EDT} {594194400 -18000 0 EST} {607503600 -14400 1 EDT} {625644000 -18000 0 EST} {638953200 -14400 1 EDT} {657093600 -18000 0 EST} {671007600 -14400 1 EDT} {688543200 -18000 0 EST} {702457200 -14400 1 EDT} {719992800 -18000 0 EST} {733906800 -14400 1 EDT} {752047200 -18000 0 EST} {765356400 -14400 1 EDT} {783496800 -18000 0 EST} {796806000 -14400 1 EDT} {814946400 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {909295200 -18000 0 EST} {923209200 -14400 1 EDT} {941349600 -18000 0 EST} {954658800 -14400 1 EDT} {972799200 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Juneau0000644000175000017500000002032612663653207017240 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Juneau) { {-9223372036854775808 54139 0 LMT} {-3225366139 -32261 0 LMT} {-2188954939 -28800 0 PST} {-883584000 -28800 0 PST} {-880207200 -25200 1 PWT} {-769395600 -25200 1 PPT} {-765385200 -28800 0 PST} {-757353600 -28800 0 PST} {-31507200 -28800 0 PST} {-21477600 -25200 1 PDT} {-5756400 -28800 0 PST} {9972000 -25200 1 PDT} {25693200 -28800 0 PST} {41421600 -25200 1 PDT} {57747600 -28800 0 PST} {73476000 -25200 1 PDT} {89197200 -28800 0 PST} {104925600 -25200 1 PDT} {120646800 -28800 0 PST} {126698400 -25200 1 PDT} {152096400 -28800 0 PST} {162381600 -25200 1 PDT} {183546000 -28800 0 PST} {199274400 -25200 1 PDT} {215600400 -28800 0 PST} {230724000 -25200 1 PDT} {247050000 -28800 0 PST} {262778400 -25200 1 PDT} {278499600 -28800 0 PST} {294228000 -25200 1 PDT} {309949200 -28800 0 PST} {325677600 -32400 0 YST} {325681200 -28800 1 YDT} {341406000 -28800 0 PST} {357127200 -25200 1 PDT} {372848400 -28800 0 PST} {388576800 -25200 1 PDT} {404902800 -28800 0 PST} {420026400 -25200 1 PDT} {439030800 -32400 0 AKST} {452084400 -28800 1 AKDT} {467805600 -32400 0 AKST} {483534000 -28800 1 AKDT} {499255200 -32400 0 AKST} {514983600 -28800 1 AKDT} {530704800 -32400 0 AKST} {544618800 -28800 1 AKDT} {562154400 -32400 0 AKST} {576068400 -28800 1 AKDT} {594208800 -32400 0 AKST} {607518000 -28800 1 AKDT} {625658400 -32400 0 AKST} {638967600 -28800 1 AKDT} {657108000 -32400 0 AKST} {671022000 -28800 1 AKDT} {688557600 -32400 0 AKST} {702471600 -28800 1 AKDT} {720007200 -32400 0 AKST} {733921200 -28800 1 AKDT} {752061600 -32400 0 AKST} {765370800 -28800 1 AKDT} {783511200 -32400 0 AKST} {796820400 -28800 1 AKDT} {814960800 -32400 0 AKST} {828874800 -28800 1 AKDT} {846410400 -32400 0 AKST} {860324400 -28800 1 AKDT} {877860000 -32400 0 AKST} {891774000 -28800 1 AKDT} {909309600 -32400 0 AKST} {923223600 -28800 1 AKDT} {941364000 -32400 0 AKST} {954673200 -28800 1 AKDT} {972813600 -32400 0 AKST} {986122800 -28800 1 AKDT} {1004263200 -32400 0 AKST} {1018177200 -28800 1 AKDT} {1035712800 -32400 0 AKST} {1049626800 -28800 1 AKDT} {1067162400 -32400 0 AKST} {1081076400 -28800 1 AKDT} {1099216800 -32400 0 AKST} {1112526000 -28800 1 AKDT} {1130666400 -32400 0 AKST} {1143975600 -28800 1 AKDT} {1162116000 -32400 0 AKST} {1173610800 -28800 1 AKDT} {1194170400 -32400 0 AKST} {1205060400 -28800 1 AKDT} {1225620000 -32400 0 AKST} {1236510000 -28800 1 AKDT} {1257069600 -32400 0 AKST} {1268564400 -28800 1 AKDT} {1289124000 -32400 0 AKST} {1300014000 -28800 1 AKDT} {1320573600 -32400 0 AKST} {1331463600 -28800 1 AKDT} {1352023200 -32400 0 AKST} {1362913200 -28800 1 AKDT} {1383472800 -32400 0 AKST} {1394362800 -28800 1 AKDT} {1414922400 -32400 0 AKST} {1425812400 -28800 1 AKDT} {1446372000 -32400 0 AKST} {1457866800 -28800 1 AKDT} {1478426400 -32400 0 AKST} {1489316400 -28800 1 AKDT} {1509876000 -32400 0 AKST} {1520766000 -28800 1 AKDT} {1541325600 -32400 0 AKST} {1552215600 -28800 1 AKDT} {1572775200 -32400 0 AKST} {1583665200 -28800 1 AKDT} {1604224800 -32400 0 AKST} {1615719600 -28800 1 AKDT} {1636279200 -32400 0 AKST} {1647169200 -28800 1 AKDT} {1667728800 -32400 0 AKST} {1678618800 -28800 1 AKDT} {1699178400 -32400 0 AKST} {1710068400 -28800 1 AKDT} {1730628000 -32400 0 AKST} {1741518000 -28800 1 AKDT} {1762077600 -32400 0 AKST} {1772967600 -28800 1 AKDT} {1793527200 -32400 0 AKST} {1805022000 -28800 1 AKDT} {1825581600 -32400 0 AKST} {1836471600 -28800 1 AKDT} {1857031200 -32400 0 AKST} {1867921200 -28800 1 AKDT} {1888480800 -32400 0 AKST} {1899370800 -28800 1 AKDT} {1919930400 -32400 0 AKST} {1930820400 -28800 1 AKDT} {1951380000 -32400 0 AKST} {1962874800 -28800 1 AKDT} {1983434400 -32400 0 AKST} {1994324400 -28800 1 AKDT} {2014884000 -32400 0 AKST} {2025774000 -28800 1 AKDT} {2046333600 -32400 0 AKST} {2057223600 -28800 1 AKDT} {2077783200 -32400 0 AKST} {2088673200 -28800 1 AKDT} {2109232800 -32400 0 AKST} {2120122800 -28800 1 AKDT} {2140682400 -32400 0 AKST} {2152177200 -28800 1 AKDT} {2172736800 -32400 0 AKST} {2183626800 -28800 1 AKDT} {2204186400 -32400 0 AKST} {2215076400 -28800 1 AKDT} {2235636000 -32400 0 AKST} {2246526000 -28800 1 AKDT} {2267085600 -32400 0 AKST} {2277975600 -28800 1 AKDT} {2298535200 -32400 0 AKST} {2309425200 -28800 1 AKDT} {2329984800 -32400 0 AKST} {2341479600 -28800 1 AKDT} {2362039200 -32400 0 AKST} {2372929200 -28800 1 AKDT} {2393488800 -32400 0 AKST} {2404378800 -28800 1 AKDT} {2424938400 -32400 0 AKST} {2435828400 -28800 1 AKDT} {2456388000 -32400 0 AKST} {2467278000 -28800 1 AKDT} {2487837600 -32400 0 AKST} {2499332400 -28800 1 AKDT} {2519892000 -32400 0 AKST} {2530782000 -28800 1 AKDT} {2551341600 -32400 0 AKST} {2562231600 -28800 1 AKDT} {2582791200 -32400 0 AKST} {2593681200 -28800 1 AKDT} {2614240800 -32400 0 AKST} {2625130800 -28800 1 AKDT} {2645690400 -32400 0 AKST} {2656580400 -28800 1 AKDT} {2677140000 -32400 0 AKST} {2688634800 -28800 1 AKDT} {2709194400 -32400 0 AKST} {2720084400 -28800 1 AKDT} {2740644000 -32400 0 AKST} {2751534000 -28800 1 AKDT} {2772093600 -32400 0 AKST} {2782983600 -28800 1 AKDT} {2803543200 -32400 0 AKST} {2814433200 -28800 1 AKDT} {2834992800 -32400 0 AKST} {2846487600 -28800 1 AKDT} {2867047200 -32400 0 AKST} {2877937200 -28800 1 AKDT} {2898496800 -32400 0 AKST} {2909386800 -28800 1 AKDT} {2929946400 -32400 0 AKST} {2940836400 -28800 1 AKDT} {2961396000 -32400 0 AKST} {2972286000 -28800 1 AKDT} {2992845600 -32400 0 AKST} {3003735600 -28800 1 AKDT} {3024295200 -32400 0 AKST} {3035790000 -28800 1 AKDT} {3056349600 -32400 0 AKST} {3067239600 -28800 1 AKDT} {3087799200 -32400 0 AKST} {3098689200 -28800 1 AKDT} {3119248800 -32400 0 AKST} {3130138800 -28800 1 AKDT} {3150698400 -32400 0 AKST} {3161588400 -28800 1 AKDT} {3182148000 -32400 0 AKST} {3193038000 -28800 1 AKDT} {3213597600 -32400 0 AKST} {3225092400 -28800 1 AKDT} {3245652000 -32400 0 AKST} {3256542000 -28800 1 AKDT} {3277101600 -32400 0 AKST} {3287991600 -28800 1 AKDT} {3308551200 -32400 0 AKST} {3319441200 -28800 1 AKDT} {3340000800 -32400 0 AKST} {3350890800 -28800 1 AKDT} {3371450400 -32400 0 AKST} {3382945200 -28800 1 AKDT} {3403504800 -32400 0 AKST} {3414394800 -28800 1 AKDT} {3434954400 -32400 0 AKST} {3445844400 -28800 1 AKDT} {3466404000 -32400 0 AKST} {3477294000 -28800 1 AKDT} {3497853600 -32400 0 AKST} {3508743600 -28800 1 AKDT} {3529303200 -32400 0 AKST} {3540193200 -28800 1 AKDT} {3560752800 -32400 0 AKST} {3572247600 -28800 1 AKDT} {3592807200 -32400 0 AKST} {3603697200 -28800 1 AKDT} {3624256800 -32400 0 AKST} {3635146800 -28800 1 AKDT} {3655706400 -32400 0 AKST} {3666596400 -28800 1 AKDT} {3687156000 -32400 0 AKST} {3698046000 -28800 1 AKDT} {3718605600 -32400 0 AKST} {3730100400 -28800 1 AKDT} {3750660000 -32400 0 AKST} {3761550000 -28800 1 AKDT} {3782109600 -32400 0 AKST} {3792999600 -28800 1 AKDT} {3813559200 -32400 0 AKST} {3824449200 -28800 1 AKDT} {3845008800 -32400 0 AKST} {3855898800 -28800 1 AKDT} {3876458400 -32400 0 AKST} {3887348400 -28800 1 AKDT} {3907908000 -32400 0 AKST} {3919402800 -28800 1 AKDT} {3939962400 -32400 0 AKST} {3950852400 -28800 1 AKDT} {3971412000 -32400 0 AKST} {3982302000 -28800 1 AKDT} {4002861600 -32400 0 AKST} {4013751600 -28800 1 AKDT} {4034311200 -32400 0 AKST} {4045201200 -28800 1 AKDT} {4065760800 -32400 0 AKST} {4076650800 -28800 1 AKDT} {4097210400 -32400 0 AKST} } tcl8.6.5/library/tzdata/America/Nipigon0000644000175000017500000001723412663660066017421 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Nipigon) { {-9223372036854775808 -21184 0 LMT} {-2366734016 -18000 0 EST} {-1632070800 -14400 1 EDT} {-1615140000 -18000 0 EST} {-923252400 -14400 1 EDT} {-880218000 -14400 0 EWT} {-769395600 -14400 1 EPT} {-765396000 -18000 0 EST} {136364400 -14400 1 EDT} {152085600 -18000 0 EST} {167814000 -14400 1 EDT} {183535200 -18000 0 EST} {199263600 -14400 1 EDT} {215589600 -18000 0 EST} {230713200 -14400 1 EDT} {247039200 -18000 0 EST} {262767600 -14400 1 EDT} {278488800 -18000 0 EST} {294217200 -14400 1 EDT} {309938400 -18000 0 EST} {325666800 -14400 1 EDT} {341388000 -18000 0 EST} {357116400 -14400 1 EDT} {372837600 -18000 0 EST} {388566000 -14400 1 EDT} {404892000 -18000 0 EST} {420015600 -14400 1 EDT} {436341600 -18000 0 EST} {452070000 -14400 1 EDT} {467791200 -18000 0 EST} {483519600 -14400 1 EDT} {499240800 -18000 0 EST} {514969200 -14400 1 EDT} {530690400 -18000 0 EST} {544604400 -14400 1 EDT} {562140000 -18000 0 EST} {576054000 -14400 1 EDT} {594194400 -18000 0 EST} {607503600 -14400 1 EDT} {625644000 -18000 0 EST} {638953200 -14400 1 EDT} {657093600 -18000 0 EST} {671007600 -14400 1 EDT} {688543200 -18000 0 EST} {702457200 -14400 1 EDT} {719992800 -18000 0 EST} {733906800 -14400 1 EDT} {752047200 -18000 0 EST} {765356400 -14400 1 EDT} {783496800 -18000 0 EST} {796806000 -14400 1 EDT} {814946400 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {909295200 -18000 0 EST} {923209200 -14400 1 EDT} {941349600 -18000 0 EST} {954658800 -14400 1 EDT} {972799200 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Anguilla0000644000175000017500000000031312663660066017540 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/Anguilla) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Kralendijk0000644000175000017500000000027312663653454020072 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Curacao)]} { LoadTimeZoneFile America/Curacao } set TZData(:America/Kralendijk) $TZData(:America/Curacao) tcl8.6.5/library/tzdata/America/Denver0000644000175000017500000002066512661614720017235 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Denver) { {-9223372036854775808 -25196 0 LMT} {-2717643600 -25200 0 MST} {-1633273200 -21600 1 MDT} {-1615132800 -25200 0 MST} {-1601823600 -21600 1 MDT} {-1583683200 -25200 0 MST} {-1577898000 -25200 0 MST} {-1570374000 -21600 1 MDT} {-1551628800 -25200 0 MST} {-1538924400 -21600 1 MDT} {-1534089600 -25200 0 MST} {-883587600 -25200 0 MST} {-880210800 -21600 1 MWT} {-769395600 -21600 1 MPT} {-765388800 -25200 0 MST} {-757357200 -25200 0 MST} {-147884400 -21600 1 MDT} {-131558400 -25200 0 MST} {-116434800 -21600 1 MDT} {-100108800 -25200 0 MST} {-94669200 -25200 0 MST} {-84380400 -21600 1 MDT} {-68659200 -25200 0 MST} {-52930800 -21600 1 MDT} {-37209600 -25200 0 MST} {-21481200 -21600 1 MDT} {-5760000 -25200 0 MST} {9968400 -21600 1 MDT} {25689600 -25200 0 MST} {41418000 -21600 1 MDT} {57744000 -25200 0 MST} {73472400 -21600 1 MDT} {89193600 -25200 0 MST} {104922000 -21600 1 MDT} {120643200 -25200 0 MST} {126694800 -21600 1 MDT} {152092800 -25200 0 MST} {162378000 -21600 1 MDT} {183542400 -25200 0 MST} {199270800 -21600 1 MDT} {215596800 -25200 0 MST} {230720400 -21600 1 MDT} {247046400 -25200 0 MST} {262774800 -21600 1 MDT} {278496000 -25200 0 MST} {294224400 -21600 1 MDT} {309945600 -25200 0 MST} {325674000 -21600 1 MDT} {341395200 -25200 0 MST} {357123600 -21600 1 MDT} {372844800 -25200 0 MST} {388573200 -21600 1 MDT} {404899200 -25200 0 MST} {420022800 -21600 1 MDT} {436348800 -25200 0 MST} {452077200 -21600 1 MDT} {467798400 -25200 0 MST} {483526800 -21600 1 MDT} {499248000 -25200 0 MST} {514976400 -21600 1 MDT} {530697600 -25200 0 MST} {544611600 -21600 1 MDT} {562147200 -25200 0 MST} {576061200 -21600 1 MDT} {594201600 -25200 0 MST} {607510800 -21600 1 MDT} {625651200 -25200 0 MST} {638960400 -21600 1 MDT} {657100800 -25200 0 MST} {671014800 -21600 1 MDT} {688550400 -25200 0 MST} {702464400 -21600 1 MDT} {720000000 -25200 0 MST} {733914000 -21600 1 MDT} {752054400 -25200 0 MST} {765363600 -21600 1 MDT} {783504000 -25200 0 MST} {796813200 -21600 1 MDT} {814953600 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {986115600 -21600 1 MDT} {1004256000 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1173603600 -21600 1 MDT} {1194163200 -25200 0 MST} {1205053200 -21600 1 MDT} {1225612800 -25200 0 MST} {1236502800 -21600 1 MDT} {1257062400 -25200 0 MST} {1268557200 -21600 1 MDT} {1289116800 -25200 0 MST} {1300006800 -21600 1 MDT} {1320566400 -25200 0 MST} {1331456400 -21600 1 MDT} {1352016000 -25200 0 MST} {1362906000 -21600 1 MDT} {1383465600 -25200 0 MST} {1394355600 -21600 1 MDT} {1414915200 -25200 0 MST} {1425805200 -21600 1 MDT} {1446364800 -25200 0 MST} {1457859600 -21600 1 MDT} {1478419200 -25200 0 MST} {1489309200 -21600 1 MDT} {1509868800 -25200 0 MST} {1520758800 -21600 1 MDT} {1541318400 -25200 0 MST} {1552208400 -21600 1 MDT} {1572768000 -25200 0 MST} {1583658000 -21600 1 MDT} {1604217600 -25200 0 MST} {1615712400 -21600 1 MDT} {1636272000 -25200 0 MST} {1647162000 -21600 1 MDT} {1667721600 -25200 0 MST} {1678611600 -21600 1 MDT} {1699171200 -25200 0 MST} {1710061200 -21600 1 MDT} {1730620800 -25200 0 MST} {1741510800 -21600 1 MDT} {1762070400 -25200 0 MST} {1772960400 -21600 1 MDT} {1793520000 -25200 0 MST} {1805014800 -21600 1 MDT} {1825574400 -25200 0 MST} {1836464400 -21600 1 MDT} {1857024000 -25200 0 MST} {1867914000 -21600 1 MDT} {1888473600 -25200 0 MST} {1899363600 -21600 1 MDT} {1919923200 -25200 0 MST} {1930813200 -21600 1 MDT} {1951372800 -25200 0 MST} {1962867600 -21600 1 MDT} {1983427200 -25200 0 MST} {1994317200 -21600 1 MDT} {2014876800 -25200 0 MST} {2025766800 -21600 1 MDT} {2046326400 -25200 0 MST} {2057216400 -21600 1 MDT} {2077776000 -25200 0 MST} {2088666000 -21600 1 MDT} {2109225600 -25200 0 MST} {2120115600 -21600 1 MDT} {2140675200 -25200 0 MST} {2152170000 -21600 1 MDT} {2172729600 -25200 0 MST} {2183619600 -21600 1 MDT} {2204179200 -25200 0 MST} {2215069200 -21600 1 MDT} {2235628800 -25200 0 MST} {2246518800 -21600 1 MDT} {2267078400 -25200 0 MST} {2277968400 -21600 1 MDT} {2298528000 -25200 0 MST} {2309418000 -21600 1 MDT} {2329977600 -25200 0 MST} {2341472400 -21600 1 MDT} {2362032000 -25200 0 MST} {2372922000 -21600 1 MDT} {2393481600 -25200 0 MST} {2404371600 -21600 1 MDT} {2424931200 -25200 0 MST} {2435821200 -21600 1 MDT} {2456380800 -25200 0 MST} {2467270800 -21600 1 MDT} {2487830400 -25200 0 MST} {2499325200 -21600 1 MDT} {2519884800 -25200 0 MST} {2530774800 -21600 1 MDT} {2551334400 -25200 0 MST} {2562224400 -21600 1 MDT} {2582784000 -25200 0 MST} {2593674000 -21600 1 MDT} {2614233600 -25200 0 MST} {2625123600 -21600 1 MDT} {2645683200 -25200 0 MST} {2656573200 -21600 1 MDT} {2677132800 -25200 0 MST} {2688627600 -21600 1 MDT} {2709187200 -25200 0 MST} {2720077200 -21600 1 MDT} {2740636800 -25200 0 MST} {2751526800 -21600 1 MDT} {2772086400 -25200 0 MST} {2782976400 -21600 1 MDT} {2803536000 -25200 0 MST} {2814426000 -21600 1 MDT} {2834985600 -25200 0 MST} {2846480400 -21600 1 MDT} {2867040000 -25200 0 MST} {2877930000 -21600 1 MDT} {2898489600 -25200 0 MST} {2909379600 -21600 1 MDT} {2929939200 -25200 0 MST} {2940829200 -21600 1 MDT} {2961388800 -25200 0 MST} {2972278800 -21600 1 MDT} {2992838400 -25200 0 MST} {3003728400 -21600 1 MDT} {3024288000 -25200 0 MST} {3035782800 -21600 1 MDT} {3056342400 -25200 0 MST} {3067232400 -21600 1 MDT} {3087792000 -25200 0 MST} {3098682000 -21600 1 MDT} {3119241600 -25200 0 MST} {3130131600 -21600 1 MDT} {3150691200 -25200 0 MST} {3161581200 -21600 1 MDT} {3182140800 -25200 0 MST} {3193030800 -21600 1 MDT} {3213590400 -25200 0 MST} {3225085200 -21600 1 MDT} {3245644800 -25200 0 MST} {3256534800 -21600 1 MDT} {3277094400 -25200 0 MST} {3287984400 -21600 1 MDT} {3308544000 -25200 0 MST} {3319434000 -21600 1 MDT} {3339993600 -25200 0 MST} {3350883600 -21600 1 MDT} {3371443200 -25200 0 MST} {3382938000 -21600 1 MDT} {3403497600 -25200 0 MST} {3414387600 -21600 1 MDT} {3434947200 -25200 0 MST} {3445837200 -21600 1 MDT} {3466396800 -25200 0 MST} {3477286800 -21600 1 MDT} {3497846400 -25200 0 MST} {3508736400 -21600 1 MDT} {3529296000 -25200 0 MST} {3540186000 -21600 1 MDT} {3560745600 -25200 0 MST} {3572240400 -21600 1 MDT} {3592800000 -25200 0 MST} {3603690000 -21600 1 MDT} {3624249600 -25200 0 MST} {3635139600 -21600 1 MDT} {3655699200 -25200 0 MST} {3666589200 -21600 1 MDT} {3687148800 -25200 0 MST} {3698038800 -21600 1 MDT} {3718598400 -25200 0 MST} {3730093200 -21600 1 MDT} {3750652800 -25200 0 MST} {3761542800 -21600 1 MDT} {3782102400 -25200 0 MST} {3792992400 -21600 1 MDT} {3813552000 -25200 0 MST} {3824442000 -21600 1 MDT} {3845001600 -25200 0 MST} {3855891600 -21600 1 MDT} {3876451200 -25200 0 MST} {3887341200 -21600 1 MDT} {3907900800 -25200 0 MST} {3919395600 -21600 1 MDT} {3939955200 -25200 0 MST} {3950845200 -21600 1 MDT} {3971404800 -25200 0 MST} {3982294800 -21600 1 MDT} {4002854400 -25200 0 MST} {4013744400 -21600 1 MDT} {4034304000 -25200 0 MST} {4045194000 -21600 1 MDT} {4065753600 -25200 0 MST} {4076643600 -21600 1 MDT} {4097203200 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Catamarca0000644000175000017500000000033612661614722017661 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Argentina/Catamarca)]} { LoadTimeZoneFile America/Argentina/Catamarca } set TZData(:America/Catamarca) $TZData(:America/Argentina/Catamarca) tcl8.6.5/library/tzdata/America/Costa_Rica0000644000175000017500000000064012663660066020016 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Costa_Rica) { {-9223372036854775808 -20173 0 LMT} {-2524501427 -20173 0 SJMT} {-1545071027 -21600 0 CST} {288770400 -18000 1 CDT} {297234000 -21600 0 CST} {320220000 -18000 1 CDT} {328683600 -21600 0 CST} {664264800 -18000 1 CDT} {678344400 -21600 0 CST} {695714400 -18000 1 CDT} {700635600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Bogota0000644000175000017500000000035612663660066017226 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Bogota) { {-9223372036854775808 -17776 0 LMT} {-2707671824 -17776 0 BMT} {-1739041424 -18000 0 COT} {704869200 -14400 1 COST} {733896000 -18000 0 COT} } tcl8.6.5/library/tzdata/America/Noronha0000644000175000017500000000253012661614721017406 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Noronha) { {-9223372036854775808 -7780 0 LMT} {-1767217820 -7200 0 FNT} {-1206961200 -3600 1 FNST} {-1191366000 -7200 0 FNT} {-1175378400 -3600 1 FNST} {-1159830000 -7200 0 FNT} {-633823200 -3600 1 FNST} {-622072800 -7200 0 FNT} {-602287200 -3600 1 FNST} {-591836400 -7200 0 FNT} {-570751200 -3600 1 FNST} {-560214000 -7200 0 FNT} {-539128800 -3600 1 FNST} {-531356400 -7200 0 FNT} {-191368800 -3600 1 FNST} {-184201200 -7200 0 FNT} {-155167200 -3600 1 FNST} {-150073200 -7200 0 FNT} {-128901600 -3600 1 FNST} {-121129200 -7200 0 FNT} {-99957600 -3600 1 FNST} {-89593200 -7200 0 FNT} {-68421600 -3600 1 FNST} {-57970800 -7200 0 FNT} {499744800 -3600 1 FNST} {511232400 -7200 0 FNT} {530589600 -3600 1 FNST} {540262800 -7200 0 FNT} {562125600 -3600 1 FNST} {571194000 -7200 0 FNT} {592970400 -3600 1 FNST} {602038800 -7200 0 FNT} {624420000 -3600 1 FNST} {634698000 -7200 0 FNT} {653533200 -7200 0 FNT} {938656800 -7200 0 FNT} {938916000 -3600 1 FNST} {951613200 -7200 0 FNT} {970970400 -3600 1 FNST} {971571600 -7200 0 FNT} {1000346400 -7200 0 FNT} {1003024800 -3600 1 FNST} {1013907600 -7200 0 FNT} {1033434000 -7200 0 FNT} } tcl8.6.5/library/tzdata/America/Port_of_Spain0000644000175000017500000000023312661614721020542 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Port_of_Spain) { {-9223372036854775808 -14764 0 LMT} {-1825098836 -14400 0 AST} } tcl8.6.5/library/tzdata/America/Danmarkshavn0000644000175000017500000000212112661614720020412 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Danmarkshavn) { {-9223372036854775808 -4480 0 LMT} {-1686091520 -10800 0 WGT} {323845200 -7200 0 WGST} {338950800 -10800 0 WGT} {354675600 -7200 1 WGST} {370400400 -10800 0 WGT} {386125200 -7200 1 WGST} {401850000 -10800 0 WGT} {417574800 -7200 1 WGST} {433299600 -10800 0 WGT} {449024400 -7200 1 WGST} {465354000 -10800 0 WGT} {481078800 -7200 1 WGST} {496803600 -10800 0 WGT} {512528400 -7200 1 WGST} {528253200 -10800 0 WGT} {543978000 -7200 1 WGST} {559702800 -10800 0 WGT} {575427600 -7200 1 WGST} {591152400 -10800 0 WGT} {606877200 -7200 1 WGST} {622602000 -10800 0 WGT} {638326800 -7200 1 WGST} {654656400 -10800 0 WGT} {670381200 -7200 1 WGST} {686106000 -10800 0 WGT} {701830800 -7200 1 WGST} {717555600 -10800 0 WGT} {733280400 -7200 1 WGST} {749005200 -10800 0 WGT} {764730000 -7200 1 WGST} {780454800 -10800 0 WGT} {796179600 -7200 1 WGST} {811904400 -10800 0 WGT} {820465200 0 0 GMT} } tcl8.6.5/library/tzdata/America/St_Vincent0000644000175000017500000000031512663660066020062 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/St_Vincent) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Santa_Isabel0000644000175000017500000000027512665113557020340 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Tijuana)]} { LoadTimeZoneFile America/Tijuana } set TZData(:America/Santa_Isabel) $TZData(:America/Tijuana) tcl8.6.5/library/tzdata/America/Asuncion0000644000175000017500000001720212663660066017570 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Asuncion) { {-9223372036854775808 -13840 0 LMT} {-2524507760 -13840 0 AMT} {-1206389360 -14400 0 PYT} {86760000 -10800 0 PYT} {134017200 -14400 0 PYT} {162878400 -14400 0 PYT} {181368000 -10800 1 PYST} {194497200 -14400 0 PYT} {212990400 -10800 1 PYST} {226033200 -14400 0 PYT} {244526400 -10800 1 PYST} {257569200 -14400 0 PYT} {276062400 -10800 1 PYST} {291783600 -14400 0 PYT} {307598400 -10800 1 PYST} {323406000 -14400 0 PYT} {339220800 -10800 1 PYST} {354942000 -14400 0 PYT} {370756800 -10800 1 PYST} {386478000 -14400 0 PYT} {402292800 -10800 1 PYST} {418014000 -14400 0 PYT} {433828800 -10800 1 PYST} {449636400 -14400 0 PYT} {465451200 -10800 1 PYST} {481172400 -14400 0 PYT} {496987200 -10800 1 PYST} {512708400 -14400 0 PYT} {528523200 -10800 1 PYST} {544244400 -14400 0 PYT} {560059200 -10800 1 PYST} {575866800 -14400 0 PYT} {591681600 -10800 1 PYST} {607402800 -14400 0 PYT} {625032000 -10800 1 PYST} {638938800 -14400 0 PYT} {654753600 -10800 1 PYST} {670474800 -14400 0 PYT} {686721600 -10800 1 PYST} {699418800 -14400 0 PYT} {718257600 -10800 1 PYST} {733546800 -14400 0 PYT} {749448000 -10800 1 PYST} {762318000 -14400 0 PYT} {780984000 -10800 1 PYST} {793767600 -14400 0 PYT} {812520000 -10800 1 PYST} {825649200 -14400 0 PYT} {844574400 -10800 1 PYST} {856666800 -14400 0 PYT} {876024000 -10800 1 PYST} {888721200 -14400 0 PYT} {907473600 -10800 1 PYST} {920775600 -14400 0 PYT} {938923200 -10800 1 PYST} {952225200 -14400 0 PYT} {970372800 -10800 1 PYST} {983674800 -14400 0 PYT} {1002427200 -10800 1 PYST} {1018148400 -14400 0 PYT} {1030852800 -10800 1 PYST} {1049598000 -14400 0 PYT} {1062907200 -10800 1 PYST} {1081047600 -14400 0 PYT} {1097985600 -10800 1 PYST} {1110682800 -14400 0 PYT} {1129435200 -10800 1 PYST} {1142132400 -14400 0 PYT} {1160884800 -10800 1 PYST} {1173582000 -14400 0 PYT} {1192939200 -10800 1 PYST} {1205031600 -14400 0 PYT} {1224388800 -10800 1 PYST} {1236481200 -14400 0 PYT} {1255838400 -10800 1 PYST} {1270954800 -14400 0 PYT} {1286078400 -10800 1 PYST} {1302404400 -14400 0 PYT} {1317528000 -10800 1 PYST} {1333854000 -14400 0 PYT} {1349582400 -10800 1 PYST} {1364094000 -14400 0 PYT} {1381032000 -10800 1 PYST} {1395543600 -14400 0 PYT} {1412481600 -10800 1 PYST} {1426993200 -14400 0 PYT} {1443931200 -10800 1 PYST} {1459047600 -14400 0 PYT} {1475380800 -10800 1 PYST} {1490497200 -14400 0 PYT} {1506830400 -10800 1 PYST} {1521946800 -14400 0 PYT} {1538884800 -10800 1 PYST} {1553396400 -14400 0 PYT} {1570334400 -10800 1 PYST} {1584846000 -14400 0 PYT} {1601784000 -10800 1 PYST} {1616900400 -14400 0 PYT} {1633233600 -10800 1 PYST} {1648350000 -14400 0 PYT} {1664683200 -10800 1 PYST} {1679799600 -14400 0 PYT} {1696132800 -10800 1 PYST} {1711249200 -14400 0 PYT} {1728187200 -10800 1 PYST} {1742698800 -14400 0 PYT} {1759636800 -10800 1 PYST} {1774148400 -14400 0 PYT} {1791086400 -10800 1 PYST} {1806202800 -14400 0 PYT} {1822536000 -10800 1 PYST} {1837652400 -14400 0 PYT} {1853985600 -10800 1 PYST} {1869102000 -14400 0 PYT} {1886040000 -10800 1 PYST} {1900551600 -14400 0 PYT} {1917489600 -10800 1 PYST} {1932001200 -14400 0 PYT} {1948939200 -10800 1 PYST} {1964055600 -14400 0 PYT} {1980388800 -10800 1 PYST} {1995505200 -14400 0 PYT} {2011838400 -10800 1 PYST} {2026954800 -14400 0 PYT} {2043288000 -10800 1 PYST} {2058404400 -14400 0 PYT} {2075342400 -10800 1 PYST} {2089854000 -14400 0 PYT} {2106792000 -10800 1 PYST} {2121303600 -14400 0 PYT} {2138241600 -10800 1 PYST} {2153358000 -14400 0 PYT} {2169691200 -10800 1 PYST} {2184807600 -14400 0 PYT} {2201140800 -10800 1 PYST} {2216257200 -14400 0 PYT} {2233195200 -10800 1 PYST} {2247706800 -14400 0 PYT} {2264644800 -10800 1 PYST} {2279156400 -14400 0 PYT} {2296094400 -10800 1 PYST} {2310606000 -14400 0 PYT} {2327544000 -10800 1 PYST} {2342660400 -14400 0 PYT} {2358993600 -10800 1 PYST} {2374110000 -14400 0 PYT} {2390443200 -10800 1 PYST} {2405559600 -14400 0 PYT} {2422497600 -10800 1 PYST} {2437009200 -14400 0 PYT} {2453947200 -10800 1 PYST} {2468458800 -14400 0 PYT} {2485396800 -10800 1 PYST} {2500513200 -14400 0 PYT} {2516846400 -10800 1 PYST} {2531962800 -14400 0 PYT} {2548296000 -10800 1 PYST} {2563412400 -14400 0 PYT} {2579745600 -10800 1 PYST} {2594862000 -14400 0 PYT} {2611800000 -10800 1 PYST} {2626311600 -14400 0 PYT} {2643249600 -10800 1 PYST} {2657761200 -14400 0 PYT} {2674699200 -10800 1 PYST} {2689815600 -14400 0 PYT} {2706148800 -10800 1 PYST} {2721265200 -14400 0 PYT} {2737598400 -10800 1 PYST} {2752714800 -14400 0 PYT} {2769652800 -10800 1 PYST} {2784164400 -14400 0 PYT} {2801102400 -10800 1 PYST} {2815614000 -14400 0 PYT} {2832552000 -10800 1 PYST} {2847668400 -14400 0 PYT} {2864001600 -10800 1 PYST} {2879118000 -14400 0 PYT} {2895451200 -10800 1 PYST} {2910567600 -14400 0 PYT} {2926900800 -10800 1 PYST} {2942017200 -14400 0 PYT} {2958955200 -10800 1 PYST} {2973466800 -14400 0 PYT} {2990404800 -10800 1 PYST} {3004916400 -14400 0 PYT} {3021854400 -10800 1 PYST} {3036970800 -14400 0 PYT} {3053304000 -10800 1 PYST} {3068420400 -14400 0 PYT} {3084753600 -10800 1 PYST} {3099870000 -14400 0 PYT} {3116808000 -10800 1 PYST} {3131319600 -14400 0 PYT} {3148257600 -10800 1 PYST} {3162769200 -14400 0 PYT} {3179707200 -10800 1 PYST} {3194218800 -14400 0 PYT} {3211156800 -10800 1 PYST} {3226273200 -14400 0 PYT} {3242606400 -10800 1 PYST} {3257722800 -14400 0 PYT} {3274056000 -10800 1 PYST} {3289172400 -14400 0 PYT} {3306110400 -10800 1 PYST} {3320622000 -14400 0 PYT} {3337560000 -10800 1 PYST} {3352071600 -14400 0 PYT} {3369009600 -10800 1 PYST} {3384126000 -14400 0 PYT} {3400459200 -10800 1 PYST} {3415575600 -14400 0 PYT} {3431908800 -10800 1 PYST} {3447025200 -14400 0 PYT} {3463358400 -10800 1 PYST} {3478474800 -14400 0 PYT} {3495412800 -10800 1 PYST} {3509924400 -14400 0 PYT} {3526862400 -10800 1 PYST} {3541374000 -14400 0 PYT} {3558312000 -10800 1 PYST} {3573428400 -14400 0 PYT} {3589761600 -10800 1 PYST} {3604878000 -14400 0 PYT} {3621211200 -10800 1 PYST} {3636327600 -14400 0 PYT} {3653265600 -10800 1 PYST} {3667777200 -14400 0 PYT} {3684715200 -10800 1 PYST} {3699226800 -14400 0 PYT} {3716164800 -10800 1 PYST} {3731281200 -14400 0 PYT} {3747614400 -10800 1 PYST} {3762730800 -14400 0 PYT} {3779064000 -10800 1 PYST} {3794180400 -14400 0 PYT} {3810513600 -10800 1 PYST} {3825630000 -14400 0 PYT} {3842568000 -10800 1 PYST} {3857079600 -14400 0 PYT} {3874017600 -10800 1 PYST} {3888529200 -14400 0 PYT} {3905467200 -10800 1 PYST} {3920583600 -14400 0 PYT} {3936916800 -10800 1 PYST} {3952033200 -14400 0 PYT} {3968366400 -10800 1 PYST} {3983482800 -14400 0 PYT} {4000420800 -10800 1 PYST} {4014932400 -14400 0 PYT} {4031870400 -10800 1 PYST} {4046382000 -14400 0 PYT} {4063320000 -10800 1 PYST} {4077831600 -14400 0 PYT} {4094769600 -10800 1 PYST} } tcl8.6.5/library/tzdata/America/Kentucky/0000755000175000017500000000000012665173607017663 5ustar sergeisergeitcl8.6.5/library/tzdata/America/Kentucky/Monticello0000644000175000017500000002012712661614721021706 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Kentucky/Monticello) { {-9223372036854775808 -20364 0 LMT} {-2717647200 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-757360800 -21600 0 CST} {-63136800 -21600 0 CST} {-52934400 -18000 1 CDT} {-37213200 -21600 0 CST} {-21484800 -18000 1 CDT} {-5763600 -21600 0 CST} {9964800 -18000 1 CDT} {25686000 -21600 0 CST} {41414400 -18000 1 CDT} {57740400 -21600 0 CST} {73468800 -18000 1 CDT} {89190000 -21600 0 CST} {104918400 -18000 1 CDT} {120639600 -21600 0 CST} {126691200 -18000 1 CDT} {152089200 -21600 0 CST} {162374400 -18000 1 CDT} {183538800 -21600 0 CST} {199267200 -18000 1 CDT} {215593200 -21600 0 CST} {230716800 -18000 1 CDT} {247042800 -21600 0 CST} {262771200 -18000 1 CDT} {278492400 -21600 0 CST} {294220800 -18000 1 CDT} {309942000 -21600 0 CST} {325670400 -18000 1 CDT} {341391600 -21600 0 CST} {357120000 -18000 1 CDT} {372841200 -21600 0 CST} {388569600 -18000 1 CDT} {404895600 -21600 0 CST} {420019200 -18000 1 CDT} {436345200 -21600 0 CST} {452073600 -18000 1 CDT} {467794800 -21600 0 CST} {483523200 -18000 1 CDT} {499244400 -21600 0 CST} {514972800 -18000 1 CDT} {530694000 -21600 0 CST} {544608000 -18000 1 CDT} {562143600 -21600 0 CST} {576057600 -18000 1 CDT} {594198000 -21600 0 CST} {607507200 -18000 1 CDT} {625647600 -21600 0 CST} {638956800 -18000 1 CDT} {657097200 -21600 0 CST} {671011200 -18000 1 CDT} {688546800 -21600 0 CST} {702460800 -18000 1 CDT} {719996400 -21600 0 CST} {733910400 -18000 1 CDT} {752050800 -21600 0 CST} {765360000 -18000 1 CDT} {783500400 -21600 0 CST} {796809600 -18000 1 CDT} {814950000 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972806400 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Kentucky/Louisville0000644000175000017500000002216412661614721021733 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Kentucky/Louisville) { {-9223372036854775808 -20582 0 LMT} {-2717647200 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-1546279200 -21600 0 CST} {-1535904000 -18000 1 CDT} {-1525280400 -21600 0 CST} {-905097600 -18000 1 CDT} {-891795600 -21600 0 CST} {-883591200 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-757360800 -21600 0 CST} {-747244800 -18000 1 CDT} {-744224400 -21600 0 CST} {-715795200 -18000 1 CDT} {-684349200 -18000 1 CDT} {-652899600 -18000 1 CDT} {-620845200 -18000 1 CDT} {-608144400 -21600 0 CST} {-589392000 -18000 1 CDT} {-576090000 -21600 0 CST} {-557942400 -18000 1 CDT} {-544640400 -21600 0 CST} {-526492800 -18000 1 CDT} {-513190800 -21600 0 CST} {-495043200 -18000 1 CDT} {-481741200 -21600 0 CST} {-463593600 -18000 1 CDT} {-450291600 -21600 0 CST} {-431539200 -18000 1 CDT} {-415818000 -21600 0 CST} {-400089600 -18000 1 CDT} {-384368400 -21600 0 CST} {-368640000 -18000 1 CDT} {-352918800 -21600 0 CST} {-337190400 -18000 1 CDT} {-321469200 -21600 0 CST} {-305740800 -18000 1 CDT} {-289414800 -21600 0 CST} {-273686400 -18000 1 CDT} {-266432400 -18000 0 EST} {-63140400 -18000 0 EST} {-52938000 -14400 1 EDT} {-37216800 -18000 0 EST} {-21488400 -14400 1 EDT} {-5767200 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {41410800 -14400 1 EDT} {57736800 -18000 0 EST} {73465200 -14400 1 EDT} {89186400 -18000 0 EST} {104914800 -14400 1 EDT} {120636000 -18000 0 EST} {126687600 -18000 1 CDT} {152089200 -18000 0 EST} {162370800 -14400 1 EDT} {183535200 -18000 0 EST} {199263600 -14400 1 EDT} {215589600 -18000 0 EST} {230713200 -14400 1 EDT} {247039200 -18000 0 EST} {262767600 -14400 1 EDT} {278488800 -18000 0 EST} {294217200 -14400 1 EDT} {309938400 -18000 0 EST} {325666800 -14400 1 EDT} {341388000 -18000 0 EST} {357116400 -14400 1 EDT} {372837600 -18000 0 EST} {388566000 -14400 1 EDT} {404892000 -18000 0 EST} {420015600 -14400 1 EDT} {436341600 -18000 0 EST} {452070000 -14400 1 EDT} {467791200 -18000 0 EST} {483519600 -14400 1 EDT} {499240800 -18000 0 EST} {514969200 -14400 1 EDT} {530690400 -18000 0 EST} {544604400 -14400 1 EDT} {562140000 -18000 0 EST} {576054000 -14400 1 EDT} {594194400 -18000 0 EST} {607503600 -14400 1 EDT} {625644000 -18000 0 EST} {638953200 -14400 1 EDT} {657093600 -18000 0 EST} {671007600 -14400 1 EDT} {688543200 -18000 0 EST} {702457200 -14400 1 EDT} {719992800 -18000 0 EST} {733906800 -14400 1 EDT} {752047200 -18000 0 EST} {765356400 -14400 1 EDT} {783496800 -18000 0 EST} {796806000 -14400 1 EDT} {814946400 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {909295200 -18000 0 EST} {923209200 -14400 1 EDT} {941349600 -18000 0 EST} {954658800 -14400 1 EDT} {972799200 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Los_Angeles0000644000175000017500000002230112661614721020173 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Los_Angeles) { {-9223372036854775808 -28378 0 LMT} {-2717640000 -28800 0 PST} {-1633269600 -25200 1 PDT} {-1615129200 -28800 0 PST} {-1601820000 -25200 1 PDT} {-1583679600 -28800 0 PST} {-880207200 -25200 1 PWT} {-769395600 -25200 1 PPT} {-765385200 -28800 0 PST} {-757353600 -28800 0 PST} {-687967200 -25200 1 PDT} {-662655600 -28800 0 PST} {-620834400 -25200 1 PDT} {-608137200 -28800 0 PST} {-589384800 -25200 1 PDT} {-576082800 -28800 0 PST} {-557935200 -25200 1 PDT} {-544633200 -28800 0 PST} {-526485600 -25200 1 PDT} {-513183600 -28800 0 PST} {-495036000 -25200 1 PDT} {-481734000 -28800 0 PST} {-463586400 -25200 1 PDT} {-450284400 -28800 0 PST} {-431532000 -25200 1 PDT} {-418230000 -28800 0 PST} {-400082400 -25200 1 PDT} {-386780400 -28800 0 PST} {-368632800 -25200 1 PDT} {-355330800 -28800 0 PST} {-337183200 -25200 1 PDT} {-323881200 -28800 0 PST} {-305733600 -25200 1 PDT} {-292431600 -28800 0 PST} {-273679200 -25200 1 PDT} {-260982000 -28800 0 PST} {-242229600 -25200 1 PDT} {-226508400 -28800 0 PST} {-210780000 -25200 1 PDT} {-195058800 -28800 0 PST} {-179330400 -25200 1 PDT} {-163609200 -28800 0 PST} {-147880800 -25200 1 PDT} {-131554800 -28800 0 PST} {-116431200 -25200 1 PDT} {-100105200 -28800 0 PST} {-94665600 -28800 0 PST} {-84376800 -25200 1 PDT} {-68655600 -28800 0 PST} {-52927200 -25200 1 PDT} {-37206000 -28800 0 PST} {-21477600 -25200 1 PDT} {-5756400 -28800 0 PST} {9972000 -25200 1 PDT} {25693200 -28800 0 PST} {41421600 -25200 1 PDT} {57747600 -28800 0 PST} {73476000 -25200 1 PDT} {89197200 -28800 0 PST} {104925600 -25200 1 PDT} {120646800 -28800 0 PST} {126698400 -25200 1 PDT} {152096400 -28800 0 PST} {162381600 -25200 1 PDT} {183546000 -28800 0 PST} {199274400 -25200 1 PDT} {215600400 -28800 0 PST} {230724000 -25200 1 PDT} {247050000 -28800 0 PST} {262778400 -25200 1 PDT} {278499600 -28800 0 PST} {294228000 -25200 1 PDT} {309949200 -28800 0 PST} {325677600 -25200 1 PDT} {341398800 -28800 0 PST} {357127200 -25200 1 PDT} {372848400 -28800 0 PST} {388576800 -25200 1 PDT} {404902800 -28800 0 PST} {420026400 -25200 1 PDT} {436352400 -28800 0 PST} {452080800 -25200 1 PDT} {467802000 -28800 0 PST} {483530400 -25200 1 PDT} {499251600 -28800 0 PST} {514980000 -25200 1 PDT} {530701200 -28800 0 PST} {544615200 -25200 1 PDT} {562150800 -28800 0 PST} {576064800 -25200 1 PDT} {594205200 -28800 0 PST} {607514400 -25200 1 PDT} {625654800 -28800 0 PST} {638964000 -25200 1 PDT} {657104400 -28800 0 PST} {671018400 -25200 1 PDT} {688554000 -28800 0 PST} {702468000 -25200 1 PDT} {720003600 -28800 0 PST} {733917600 -25200 1 PDT} {752058000 -28800 0 PST} {765367200 -25200 1 PDT} {783507600 -28800 0 PST} {796816800 -25200 1 PDT} {814957200 -28800 0 PST} {828871200 -25200 1 PDT} {846406800 -28800 0 PST} {860320800 -25200 1 PDT} {877856400 -28800 0 PST} {891770400 -25200 1 PDT} {909306000 -28800 0 PST} {923220000 -25200 1 PDT} {941360400 -28800 0 PST} {954669600 -25200 1 PDT} {972810000 -28800 0 PST} {986119200 -25200 1 PDT} {1004259600 -28800 0 PST} {1018173600 -25200 1 PDT} {1035709200 -28800 0 PST} {1049623200 -25200 1 PDT} {1067158800 -28800 0 PST} {1081072800 -25200 1 PDT} {1099213200 -28800 0 PST} {1112522400 -25200 1 PDT} {1130662800 -28800 0 PST} {1143972000 -25200 1 PDT} {1162112400 -28800 0 PST} {1173607200 -25200 1 PDT} {1194166800 -28800 0 PST} {1205056800 -25200 1 PDT} {1225616400 -28800 0 PST} {1236506400 -25200 1 PDT} {1257066000 -28800 0 PST} {1268560800 -25200 1 PDT} {1289120400 -28800 0 PST} {1300010400 -25200 1 PDT} {1320570000 -28800 0 PST} {1331460000 -25200 1 PDT} {1352019600 -28800 0 PST} {1362909600 -25200 1 PDT} {1383469200 -28800 0 PST} {1394359200 -25200 1 PDT} {1414918800 -28800 0 PST} {1425808800 -25200 1 PDT} {1446368400 -28800 0 PST} {1457863200 -25200 1 PDT} {1478422800 -28800 0 PST} {1489312800 -25200 1 PDT} {1509872400 -28800 0 PST} {1520762400 -25200 1 PDT} {1541322000 -28800 0 PST} {1552212000 -25200 1 PDT} {1572771600 -28800 0 PST} {1583661600 -25200 1 PDT} {1604221200 -28800 0 PST} {1615716000 -25200 1 PDT} {1636275600 -28800 0 PST} {1647165600 -25200 1 PDT} {1667725200 -28800 0 PST} {1678615200 -25200 1 PDT} {1699174800 -28800 0 PST} {1710064800 -25200 1 PDT} {1730624400 -28800 0 PST} {1741514400 -25200 1 PDT} {1762074000 -28800 0 PST} {1772964000 -25200 1 PDT} {1793523600 -28800 0 PST} {1805018400 -25200 1 PDT} {1825578000 -28800 0 PST} {1836468000 -25200 1 PDT} {1857027600 -28800 0 PST} {1867917600 -25200 1 PDT} {1888477200 -28800 0 PST} {1899367200 -25200 1 PDT} {1919926800 -28800 0 PST} {1930816800 -25200 1 PDT} {1951376400 -28800 0 PST} {1962871200 -25200 1 PDT} {1983430800 -28800 0 PST} {1994320800 -25200 1 PDT} {2014880400 -28800 0 PST} {2025770400 -25200 1 PDT} {2046330000 -28800 0 PST} {2057220000 -25200 1 PDT} {2077779600 -28800 0 PST} {2088669600 -25200 1 PDT} {2109229200 -28800 0 PST} {2120119200 -25200 1 PDT} {2140678800 -28800 0 PST} {2152173600 -25200 1 PDT} {2172733200 -28800 0 PST} {2183623200 -25200 1 PDT} {2204182800 -28800 0 PST} {2215072800 -25200 1 PDT} {2235632400 -28800 0 PST} {2246522400 -25200 1 PDT} {2267082000 -28800 0 PST} {2277972000 -25200 1 PDT} {2298531600 -28800 0 PST} {2309421600 -25200 1 PDT} {2329981200 -28800 0 PST} {2341476000 -25200 1 PDT} {2362035600 -28800 0 PST} {2372925600 -25200 1 PDT} {2393485200 -28800 0 PST} {2404375200 -25200 1 PDT} {2424934800 -28800 0 PST} {2435824800 -25200 1 PDT} {2456384400 -28800 0 PST} {2467274400 -25200 1 PDT} {2487834000 -28800 0 PST} {2499328800 -25200 1 PDT} {2519888400 -28800 0 PST} {2530778400 -25200 1 PDT} {2551338000 -28800 0 PST} {2562228000 -25200 1 PDT} {2582787600 -28800 0 PST} {2593677600 -25200 1 PDT} {2614237200 -28800 0 PST} {2625127200 -25200 1 PDT} {2645686800 -28800 0 PST} {2656576800 -25200 1 PDT} {2677136400 -28800 0 PST} {2688631200 -25200 1 PDT} {2709190800 -28800 0 PST} {2720080800 -25200 1 PDT} {2740640400 -28800 0 PST} {2751530400 -25200 1 PDT} {2772090000 -28800 0 PST} {2782980000 -25200 1 PDT} {2803539600 -28800 0 PST} {2814429600 -25200 1 PDT} {2834989200 -28800 0 PST} {2846484000 -25200 1 PDT} {2867043600 -28800 0 PST} {2877933600 -25200 1 PDT} {2898493200 -28800 0 PST} {2909383200 -25200 1 PDT} {2929942800 -28800 0 PST} {2940832800 -25200 1 PDT} {2961392400 -28800 0 PST} {2972282400 -25200 1 PDT} {2992842000 -28800 0 PST} {3003732000 -25200 1 PDT} {3024291600 -28800 0 PST} {3035786400 -25200 1 PDT} {3056346000 -28800 0 PST} {3067236000 -25200 1 PDT} {3087795600 -28800 0 PST} {3098685600 -25200 1 PDT} {3119245200 -28800 0 PST} {3130135200 -25200 1 PDT} {3150694800 -28800 0 PST} {3161584800 -25200 1 PDT} {3182144400 -28800 0 PST} {3193034400 -25200 1 PDT} {3213594000 -28800 0 PST} {3225088800 -25200 1 PDT} {3245648400 -28800 0 PST} {3256538400 -25200 1 PDT} {3277098000 -28800 0 PST} {3287988000 -25200 1 PDT} {3308547600 -28800 0 PST} {3319437600 -25200 1 PDT} {3339997200 -28800 0 PST} {3350887200 -25200 1 PDT} {3371446800 -28800 0 PST} {3382941600 -25200 1 PDT} {3403501200 -28800 0 PST} {3414391200 -25200 1 PDT} {3434950800 -28800 0 PST} {3445840800 -25200 1 PDT} {3466400400 -28800 0 PST} {3477290400 -25200 1 PDT} {3497850000 -28800 0 PST} {3508740000 -25200 1 PDT} {3529299600 -28800 0 PST} {3540189600 -25200 1 PDT} {3560749200 -28800 0 PST} {3572244000 -25200 1 PDT} {3592803600 -28800 0 PST} {3603693600 -25200 1 PDT} {3624253200 -28800 0 PST} {3635143200 -25200 1 PDT} {3655702800 -28800 0 PST} {3666592800 -25200 1 PDT} {3687152400 -28800 0 PST} {3698042400 -25200 1 PDT} {3718602000 -28800 0 PST} {3730096800 -25200 1 PDT} {3750656400 -28800 0 PST} {3761546400 -25200 1 PDT} {3782106000 -28800 0 PST} {3792996000 -25200 1 PDT} {3813555600 -28800 0 PST} {3824445600 -25200 1 PDT} {3845005200 -28800 0 PST} {3855895200 -25200 1 PDT} {3876454800 -28800 0 PST} {3887344800 -25200 1 PDT} {3907904400 -28800 0 PST} {3919399200 -25200 1 PDT} {3939958800 -28800 0 PST} {3950848800 -25200 1 PDT} {3971408400 -28800 0 PST} {3982298400 -25200 1 PDT} {4002858000 -28800 0 PST} {4013748000 -25200 1 PDT} {4034307600 -28800 0 PST} {4045197600 -25200 1 PDT} {4065757200 -28800 0 PST} {4076647200 -25200 1 PDT} {4097206800 -28800 0 PST} } tcl8.6.5/library/tzdata/America/Panama0000644000175000017500000000026312661614721017200 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Panama) { {-9223372036854775808 -19088 0 LMT} {-2524502512 -19176 0 CMT} {-1946918424 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Jamaica0000644000175000017500000000146212663660066017337 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Jamaica) { {-9223372036854775808 -18431 0 LMT} {-2524503169 -18431 0 KMT} {-1827687169 -18000 0 EST} {126248400 -18000 0 EST} {126687600 -14400 1 EDT} {152085600 -18000 0 EST} {162370800 -14400 1 EDT} {183535200 -18000 0 EST} {199263600 -14400 1 EDT} {215589600 -18000 0 EST} {230713200 -14400 1 EDT} {247039200 -18000 0 EST} {262767600 -14400 1 EDT} {278488800 -18000 0 EST} {294217200 -14400 1 EDT} {309938400 -18000 0 EST} {325666800 -14400 1 EDT} {341388000 -18000 0 EST} {357116400 -14400 1 EDT} {372837600 -18000 0 EST} {388566000 -14400 1 EDT} {404892000 -18000 0 EST} {420015600 -14400 1 EDT} {436341600 -18000 0 EST} {441781200 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Boise0000644000175000017500000002020412661614720017040 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Boise) { {-9223372036854775808 -27889 0 LMT} {-2717640000 -28800 0 PST} {-1633269600 -25200 1 PDT} {-1615129200 -28800 0 PST} {-1601820000 -25200 1 PDT} {-1583679600 -28800 0 PST} {-1471788000 -25200 0 MST} {-880210800 -21600 1 MWT} {-769395600 -21600 1 MPT} {-765388800 -25200 0 MST} {-84380400 -21600 1 MDT} {-68659200 -25200 0 MST} {-52930800 -21600 1 MDT} {-37209600 -25200 0 MST} {-21481200 -21600 1 MDT} {-5760000 -25200 0 MST} {9968400 -21600 1 MDT} {25689600 -25200 0 MST} {41418000 -21600 1 MDT} {57744000 -25200 0 MST} {73472400 -21600 1 MDT} {89193600 -25200 0 MST} {104922000 -21600 1 MDT} {120643200 -25200 0 MST} {126255600 -25200 0 MST} {129114000 -21600 0 MDT} {152092800 -25200 0 MST} {162378000 -21600 1 MDT} {183542400 -25200 0 MST} {199270800 -21600 1 MDT} {215596800 -25200 0 MST} {230720400 -21600 1 MDT} {247046400 -25200 0 MST} {262774800 -21600 1 MDT} {278496000 -25200 0 MST} {294224400 -21600 1 MDT} {309945600 -25200 0 MST} {325674000 -21600 1 MDT} {341395200 -25200 0 MST} {357123600 -21600 1 MDT} {372844800 -25200 0 MST} {388573200 -21600 1 MDT} {404899200 -25200 0 MST} {420022800 -21600 1 MDT} {436348800 -25200 0 MST} {452077200 -21600 1 MDT} {467798400 -25200 0 MST} {483526800 -21600 1 MDT} {499248000 -25200 0 MST} {514976400 -21600 1 MDT} {530697600 -25200 0 MST} {544611600 -21600 1 MDT} {562147200 -25200 0 MST} {576061200 -21600 1 MDT} {594201600 -25200 0 MST} {607510800 -21600 1 MDT} {625651200 -25200 0 MST} {638960400 -21600 1 MDT} {657100800 -25200 0 MST} {671014800 -21600 1 MDT} {688550400 -25200 0 MST} {702464400 -21600 1 MDT} {720000000 -25200 0 MST} {733914000 -21600 1 MDT} {752054400 -25200 0 MST} {765363600 -21600 1 MDT} {783504000 -25200 0 MST} {796813200 -21600 1 MDT} {814953600 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {986115600 -21600 1 MDT} {1004256000 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1173603600 -21600 1 MDT} {1194163200 -25200 0 MST} {1205053200 -21600 1 MDT} {1225612800 -25200 0 MST} {1236502800 -21600 1 MDT} {1257062400 -25200 0 MST} {1268557200 -21600 1 MDT} {1289116800 -25200 0 MST} {1300006800 -21600 1 MDT} {1320566400 -25200 0 MST} {1331456400 -21600 1 MDT} {1352016000 -25200 0 MST} {1362906000 -21600 1 MDT} {1383465600 -25200 0 MST} {1394355600 -21600 1 MDT} {1414915200 -25200 0 MST} {1425805200 -21600 1 MDT} {1446364800 -25200 0 MST} {1457859600 -21600 1 MDT} {1478419200 -25200 0 MST} {1489309200 -21600 1 MDT} {1509868800 -25200 0 MST} {1520758800 -21600 1 MDT} {1541318400 -25200 0 MST} {1552208400 -21600 1 MDT} {1572768000 -25200 0 MST} {1583658000 -21600 1 MDT} {1604217600 -25200 0 MST} {1615712400 -21600 1 MDT} {1636272000 -25200 0 MST} {1647162000 -21600 1 MDT} {1667721600 -25200 0 MST} {1678611600 -21600 1 MDT} {1699171200 -25200 0 MST} {1710061200 -21600 1 MDT} {1730620800 -25200 0 MST} {1741510800 -21600 1 MDT} {1762070400 -25200 0 MST} {1772960400 -21600 1 MDT} {1793520000 -25200 0 MST} {1805014800 -21600 1 MDT} {1825574400 -25200 0 MST} {1836464400 -21600 1 MDT} {1857024000 -25200 0 MST} {1867914000 -21600 1 MDT} {1888473600 -25200 0 MST} {1899363600 -21600 1 MDT} {1919923200 -25200 0 MST} {1930813200 -21600 1 MDT} {1951372800 -25200 0 MST} {1962867600 -21600 1 MDT} {1983427200 -25200 0 MST} {1994317200 -21600 1 MDT} {2014876800 -25200 0 MST} {2025766800 -21600 1 MDT} {2046326400 -25200 0 MST} {2057216400 -21600 1 MDT} {2077776000 -25200 0 MST} {2088666000 -21600 1 MDT} {2109225600 -25200 0 MST} {2120115600 -21600 1 MDT} {2140675200 -25200 0 MST} {2152170000 -21600 1 MDT} {2172729600 -25200 0 MST} {2183619600 -21600 1 MDT} {2204179200 -25200 0 MST} {2215069200 -21600 1 MDT} {2235628800 -25200 0 MST} {2246518800 -21600 1 MDT} {2267078400 -25200 0 MST} {2277968400 -21600 1 MDT} {2298528000 -25200 0 MST} {2309418000 -21600 1 MDT} {2329977600 -25200 0 MST} {2341472400 -21600 1 MDT} {2362032000 -25200 0 MST} {2372922000 -21600 1 MDT} {2393481600 -25200 0 MST} {2404371600 -21600 1 MDT} {2424931200 -25200 0 MST} {2435821200 -21600 1 MDT} {2456380800 -25200 0 MST} {2467270800 -21600 1 MDT} {2487830400 -25200 0 MST} {2499325200 -21600 1 MDT} {2519884800 -25200 0 MST} {2530774800 -21600 1 MDT} {2551334400 -25200 0 MST} {2562224400 -21600 1 MDT} {2582784000 -25200 0 MST} {2593674000 -21600 1 MDT} {2614233600 -25200 0 MST} {2625123600 -21600 1 MDT} {2645683200 -25200 0 MST} {2656573200 -21600 1 MDT} {2677132800 -25200 0 MST} {2688627600 -21600 1 MDT} {2709187200 -25200 0 MST} {2720077200 -21600 1 MDT} {2740636800 -25200 0 MST} {2751526800 -21600 1 MDT} {2772086400 -25200 0 MST} {2782976400 -21600 1 MDT} {2803536000 -25200 0 MST} {2814426000 -21600 1 MDT} {2834985600 -25200 0 MST} {2846480400 -21600 1 MDT} {2867040000 -25200 0 MST} {2877930000 -21600 1 MDT} {2898489600 -25200 0 MST} {2909379600 -21600 1 MDT} {2929939200 -25200 0 MST} {2940829200 -21600 1 MDT} {2961388800 -25200 0 MST} {2972278800 -21600 1 MDT} {2992838400 -25200 0 MST} {3003728400 -21600 1 MDT} {3024288000 -25200 0 MST} {3035782800 -21600 1 MDT} {3056342400 -25200 0 MST} {3067232400 -21600 1 MDT} {3087792000 -25200 0 MST} {3098682000 -21600 1 MDT} {3119241600 -25200 0 MST} {3130131600 -21600 1 MDT} {3150691200 -25200 0 MST} {3161581200 -21600 1 MDT} {3182140800 -25200 0 MST} {3193030800 -21600 1 MDT} {3213590400 -25200 0 MST} {3225085200 -21600 1 MDT} {3245644800 -25200 0 MST} {3256534800 -21600 1 MDT} {3277094400 -25200 0 MST} {3287984400 -21600 1 MDT} {3308544000 -25200 0 MST} {3319434000 -21600 1 MDT} {3339993600 -25200 0 MST} {3350883600 -21600 1 MDT} {3371443200 -25200 0 MST} {3382938000 -21600 1 MDT} {3403497600 -25200 0 MST} {3414387600 -21600 1 MDT} {3434947200 -25200 0 MST} {3445837200 -21600 1 MDT} {3466396800 -25200 0 MST} {3477286800 -21600 1 MDT} {3497846400 -25200 0 MST} {3508736400 -21600 1 MDT} {3529296000 -25200 0 MST} {3540186000 -21600 1 MDT} {3560745600 -25200 0 MST} {3572240400 -21600 1 MDT} {3592800000 -25200 0 MST} {3603690000 -21600 1 MDT} {3624249600 -25200 0 MST} {3635139600 -21600 1 MDT} {3655699200 -25200 0 MST} {3666589200 -21600 1 MDT} {3687148800 -25200 0 MST} {3698038800 -21600 1 MDT} {3718598400 -25200 0 MST} {3730093200 -21600 1 MDT} {3750652800 -25200 0 MST} {3761542800 -21600 1 MDT} {3782102400 -25200 0 MST} {3792992400 -21600 1 MDT} {3813552000 -25200 0 MST} {3824442000 -21600 1 MDT} {3845001600 -25200 0 MST} {3855891600 -21600 1 MDT} {3876451200 -25200 0 MST} {3887341200 -21600 1 MDT} {3907900800 -25200 0 MST} {3919395600 -21600 1 MDT} {3939955200 -25200 0 MST} {3950845200 -21600 1 MDT} {3971404800 -25200 0 MST} {3982294800 -21600 1 MDT} {4002854400 -25200 0 MST} {4013744400 -21600 1 MDT} {4034304000 -25200 0 MST} {4045194000 -21600 1 MDT} {4065753600 -25200 0 MST} {4076643600 -21600 1 MDT} {4097203200 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Mendoza0000644000175000017500000000032612661614722017401 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Argentina/Mendoza)]} { LoadTimeZoneFile America/Argentina/Mendoza } set TZData(:America/Mendoza) $TZData(:America/Argentina/Mendoza) tcl8.6.5/library/tzdata/America/Puerto_Rico0000644000175000017500000000042112661614721020231 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Puerto_Rico) { {-9223372036854775808 -15865 0 LMT} {-2233035335 -14400 0 AST} {-873057600 -10800 0 AWT} {-769395600 -10800 1 APT} {-765399600 -14400 0 AST} {-757368000 -14400 0 AST} } tcl8.6.5/library/tzdata/America/Toronto0000644000175000017500000002520312663660066017455 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Toronto) { {-9223372036854775808 -19052 0 LMT} {-2366736148 -18000 0 EST} {-1632070800 -14400 1 EDT} {-1615140000 -18000 0 EST} {-1609441200 -18000 0 EST} {-1601753400 -14400 1 EDT} {-1583697600 -18000 0 EST} {-1567357200 -14400 1 EDT} {-1554667200 -18000 0 EST} {-1534698000 -14400 1 EDT} {-1524074400 -18000 0 EST} {-1503248400 -14400 1 EDT} {-1492365600 -18000 0 EST} {-1471798800 -14400 1 EDT} {-1460916000 -18000 0 EST} {-1440954000 -14400 1 EDT} {-1428861600 -18000 0 EST} {-1409504400 -14400 1 EDT} {-1397412000 -18000 0 EST} {-1378054800 -14400 1 EDT} {-1365962400 -18000 0 EST} {-1346605200 -14400 1 EDT} {-1333908000 -18000 0 EST} {-1315155600 -14400 1 EDT} {-1301853600 -18000 0 EST} {-1283706000 -14400 1 EDT} {-1270404000 -18000 0 EST} {-1252256400 -14400 1 EDT} {-1238954400 -18000 0 EST} {-1220806800 -14400 1 EDT} {-1207504800 -18000 0 EST} {-1188752400 -14400 1 EDT} {-1176055200 -18000 0 EST} {-1157302800 -14400 1 EDT} {-1144000800 -18000 0 EST} {-1125853200 -14400 1 EDT} {-1112551200 -18000 0 EST} {-1094403600 -14400 1 EDT} {-1081101600 -18000 0 EST} {-1062954000 -14400 1 EDT} {-1049652000 -18000 0 EST} {-1031504400 -14400 1 EDT} {-1018202400 -18000 0 EST} {-1000054800 -14400 1 EDT} {-986752800 -18000 0 EST} {-968000400 -14400 1 EDT} {-955303200 -18000 0 EST} {-936550800 -14400 1 EDT} {-880218000 -14400 0 EWT} {-769395600 -14400 1 EPT} {-765396000 -18000 0 EST} {-757364400 -18000 0 EST} {-747248400 -14400 1 EDT} {-733946400 -18000 0 EST} {-715806000 -14400 1 EDT} {-702504000 -18000 0 EST} {-684356400 -14400 1 EDT} {-671054400 -18000 0 EST} {-652906800 -14400 1 EDT} {-634161600 -18000 0 EST} {-620845200 -14400 1 EDT} {-602704800 -18000 0 EST} {-589395600 -14400 1 EDT} {-576093600 -18000 0 EST} {-557946000 -14400 1 EDT} {-544644000 -18000 0 EST} {-526496400 -14400 1 EDT} {-513194400 -18000 0 EST} {-495046800 -14400 1 EDT} {-481744800 -18000 0 EST} {-463597200 -14400 1 EDT} {-450295200 -18000 0 EST} {-431542800 -14400 1 EDT} {-418240800 -18000 0 EST} {-400093200 -14400 1 EDT} {-384372000 -18000 0 EST} {-368643600 -14400 1 EDT} {-352922400 -18000 0 EST} {-337194000 -14400 1 EDT} {-321472800 -18000 0 EST} {-305744400 -14400 1 EDT} {-289418400 -18000 0 EST} {-273690000 -14400 1 EDT} {-257968800 -18000 0 EST} {-242240400 -14400 1 EDT} {-226519200 -18000 0 EST} {-210790800 -14400 1 EDT} {-195069600 -18000 0 EST} {-179341200 -14400 1 EDT} {-163620000 -18000 0 EST} {-147891600 -14400 1 EDT} {-131565600 -18000 0 EST} {-116442000 -14400 1 EDT} {-100116000 -18000 0 EST} {-84387600 -14400 1 EDT} {-68666400 -18000 0 EST} {-52938000 -14400 1 EDT} {-37216800 -18000 0 EST} {-21488400 -14400 1 EDT} {-5767200 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {41410800 -14400 1 EDT} {57736800 -18000 0 EST} {73465200 -14400 1 EDT} {89186400 -18000 0 EST} {104914800 -14400 1 EDT} {120636000 -18000 0 EST} {126248400 -18000 0 EST} {136364400 -14400 1 EDT} {152085600 -18000 0 EST} {167814000 -14400 1 EDT} {183535200 -18000 0 EST} {199263600 -14400 1 EDT} {215589600 -18000 0 EST} {230713200 -14400 1 EDT} {247039200 -18000 0 EST} {262767600 -14400 1 EDT} {278488800 -18000 0 EST} {294217200 -14400 1 EDT} {309938400 -18000 0 EST} {325666800 -14400 1 EDT} {341388000 -18000 0 EST} {357116400 -14400 1 EDT} {372837600 -18000 0 EST} {388566000 -14400 1 EDT} {404892000 -18000 0 EST} {420015600 -14400 1 EDT} {436341600 -18000 0 EST} {452070000 -14400 1 EDT} {467791200 -18000 0 EST} {483519600 -14400 1 EDT} {499240800 -18000 0 EST} {514969200 -14400 1 EDT} {530690400 -18000 0 EST} {544604400 -14400 1 EDT} {562140000 -18000 0 EST} {576054000 -14400 1 EDT} {594194400 -18000 0 EST} {607503600 -14400 1 EDT} {625644000 -18000 0 EST} {638953200 -14400 1 EDT} {657093600 -18000 0 EST} {671007600 -14400 1 EDT} {688543200 -18000 0 EST} {702457200 -14400 1 EDT} {719992800 -18000 0 EST} {733906800 -14400 1 EDT} {752047200 -18000 0 EST} {765356400 -14400 1 EDT} {783496800 -18000 0 EST} {796806000 -14400 1 EDT} {814946400 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {909295200 -18000 0 EST} {923209200 -14400 1 EDT} {941349600 -18000 0 EST} {954658800 -14400 1 EDT} {972799200 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Matamoros0000644000175000017500000001457612663653207017765 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Matamoros) { {-9223372036854775808 -24000 0 LMT} {-1514743200 -21600 0 CST} {568015200 -21600 0 CST} {576057600 -18000 1 CDT} {594198000 -21600 0 CST} {599637600 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972802800 -21600 0 CST} {989136000 -18000 1 CDT} {1001833200 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1175414400 -18000 1 CDT} {1193554800 -21600 0 CST} {1207468800 -18000 1 CDT} {1225004400 -21600 0 CST} {1238918400 -18000 1 CDT} {1256454000 -21600 0 CST} {1262325600 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Montevideo0000644000175000017500000000526712663660066020132 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Montevideo) { {-9223372036854775808 -13484 0 LMT} {-2256668116 -13484 0 MMT} {-1567455316 -12600 0 UYT} {-1459542600 -10800 1 UYHST} {-1443819600 -12600 0 UYT} {-1428006600 -10800 1 UYHST} {-1412283600 -12600 0 UYT} {-1396470600 -10800 1 UYHST} {-1380747600 -12600 0 UYT} {-1141590600 -10800 1 UYHST} {-1128286800 -12600 0 UYT} {-1110141000 -10800 1 UYHST} {-1096837200 -12600 0 UYT} {-1078691400 -10800 1 UYHST} {-1065387600 -12600 0 UYT} {-1046637000 -10800 1 UYHST} {-1033938000 -12600 0 UYT} {-1015187400 -10800 1 UYHST} {-1002488400 -12600 0 UYT} {-983737800 -10800 1 UYHST} {-971038800 -12600 0 UYT} {-952288200 -10800 1 UYHST} {-938984400 -12600 0 UYT} {-920838600 -10800 1 UYHST} {-907534800 -12600 0 UYT} {-896819400 -10800 1 UYHST} {-853623000 -10800 0 UYT} {-853621200 -7200 1 UYST} {-845848800 -10800 0 UYT} {-334789200 -7200 1 UYST} {-319672800 -10800 0 UYT} {-314226000 -7200 1 UYST} {-309996000 -10800 0 UYT} {-149720400 -7200 1 UYST} {-134604000 -10800 0 UYT} {-118270800 -7200 1 UYST} {-100044000 -10800 0 UYT} {-86821200 -7200 1 UYST} {-68508000 -10800 0 UYT} {-50446800 -9000 1 UYHST} {-34119000 -10800 0 UYT} {-18910800 -9000 1 UYHST} {-2583000 -10800 0 UYT} {12625200 -9000 1 UYHST} {28953000 -10800 0 UYT} {72932400 -7200 1 UYST} {82692000 -10800 0 UYT} {132116400 -9000 1 UYHST} {156911400 -7200 1 UYST} {212983200 -10800 0 UYT} {250052400 -7200 1 UYST} {260244000 -10800 0 UYT} {307594800 -7200 1 UYST} {325994400 -10800 0 UYT} {566449200 -7200 1 UYST} {574308000 -10800 0 UYT} {597812400 -7200 1 UYST} {605671200 -10800 0 UYT} {625633200 -7200 1 UYST} {636516000 -10800 0 UYT} {656478000 -7200 1 UYST} {667965600 -10800 0 UYT} {688532400 -7200 1 UYST} {699415200 -10800 0 UYT} {719377200 -7200 1 UYST} {730864800 -10800 0 UYT} {1095562800 -7200 1 UYST} {1111896000 -10800 0 UYT} {1128834000 -7200 1 UYST} {1142136000 -10800 0 UYT} {1159678800 -7200 1 UYST} {1173585600 -10800 0 UYT} {1191733200 -7200 1 UYST} {1205035200 -10800 0 UYT} {1223182800 -7200 1 UYST} {1236484800 -10800 0 UYT} {1254632400 -7200 1 UYST} {1268539200 -10800 0 UYT} {1286082000 -7200 1 UYST} {1299988800 -10800 0 UYT} {1317531600 -7200 1 UYST} {1331438400 -10800 0 UYT} {1349586000 -7200 1 UYST} {1362888000 -10800 0 UYT} {1381035600 -7200 1 UYST} {1394337600 -10800 0 UYT} {1412485200 -7200 1 UYST} {1425787200 -10800 0 UYT} } tcl8.6.5/library/tzdata/America/Godthab0000644000175000017500000001621212661614720017353 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Godthab) { {-9223372036854775808 -12416 0 LMT} {-1686083584 -10800 0 WGT} {323845200 -7200 0 WGST} {338950800 -10800 0 WGT} {354675600 -7200 1 WGST} {370400400 -10800 0 WGT} {386125200 -7200 1 WGST} {401850000 -10800 0 WGT} {417574800 -7200 1 WGST} {433299600 -10800 0 WGT} {449024400 -7200 1 WGST} {465354000 -10800 0 WGT} {481078800 -7200 1 WGST} {496803600 -10800 0 WGT} {512528400 -7200 1 WGST} {528253200 -10800 0 WGT} {543978000 -7200 1 WGST} {559702800 -10800 0 WGT} {575427600 -7200 1 WGST} {591152400 -10800 0 WGT} {606877200 -7200 1 WGST} {622602000 -10800 0 WGT} {638326800 -7200 1 WGST} {654656400 -10800 0 WGT} {670381200 -7200 1 WGST} {686106000 -10800 0 WGT} {701830800 -7200 1 WGST} {717555600 -10800 0 WGT} {733280400 -7200 1 WGST} {749005200 -10800 0 WGT} {764730000 -7200 1 WGST} {780454800 -10800 0 WGT} {796179600 -7200 1 WGST} {811904400 -10800 0 WGT} {828234000 -7200 1 WGST} {846378000 -10800 0 WGT} {859683600 -7200 1 WGST} {877827600 -10800 0 WGT} {891133200 -7200 1 WGST} {909277200 -10800 0 WGT} {922582800 -7200 1 WGST} {941331600 -10800 0 WGT} {954032400 -7200 1 WGST} {972781200 -10800 0 WGT} {985482000 -7200 1 WGST} {1004230800 -10800 0 WGT} {1017536400 -7200 1 WGST} {1035680400 -10800 0 WGT} {1048986000 -7200 1 WGST} {1067130000 -10800 0 WGT} {1080435600 -7200 1 WGST} {1099184400 -10800 0 WGT} {1111885200 -7200 1 WGST} {1130634000 -10800 0 WGT} {1143334800 -7200 1 WGST} {1162083600 -10800 0 WGT} {1174784400 -7200 1 WGST} {1193533200 -10800 0 WGT} {1206838800 -7200 1 WGST} {1224982800 -10800 0 WGT} {1238288400 -7200 1 WGST} {1256432400 -10800 0 WGT} {1269738000 -7200 1 WGST} {1288486800 -10800 0 WGT} {1301187600 -7200 1 WGST} {1319936400 -10800 0 WGT} {1332637200 -7200 1 WGST} {1351386000 -10800 0 WGT} {1364691600 -7200 1 WGST} {1382835600 -10800 0 WGT} {1396141200 -7200 1 WGST} {1414285200 -10800 0 WGT} {1427590800 -7200 1 WGST} {1445734800 -10800 0 WGT} {1459040400 -7200 1 WGST} {1477789200 -10800 0 WGT} {1490490000 -7200 1 WGST} {1509238800 -10800 0 WGT} {1521939600 -7200 1 WGST} {1540688400 -10800 0 WGT} {1553994000 -7200 1 WGST} {1572138000 -10800 0 WGT} {1585443600 -7200 1 WGST} {1603587600 -10800 0 WGT} {1616893200 -7200 1 WGST} {1635642000 -10800 0 WGT} {1648342800 -7200 1 WGST} {1667091600 -10800 0 WGT} {1679792400 -7200 1 WGST} {1698541200 -10800 0 WGT} {1711846800 -7200 1 WGST} {1729990800 -10800 0 WGT} {1743296400 -7200 1 WGST} {1761440400 -10800 0 WGT} {1774746000 -7200 1 WGST} {1792890000 -10800 0 WGT} {1806195600 -7200 1 WGST} {1824944400 -10800 0 WGT} {1837645200 -7200 1 WGST} {1856394000 -10800 0 WGT} {1869094800 -7200 1 WGST} {1887843600 -10800 0 WGT} {1901149200 -7200 1 WGST} {1919293200 -10800 0 WGT} {1932598800 -7200 1 WGST} {1950742800 -10800 0 WGT} {1964048400 -7200 1 WGST} {1982797200 -10800 0 WGT} {1995498000 -7200 1 WGST} {2014246800 -10800 0 WGT} {2026947600 -7200 1 WGST} {2045696400 -10800 0 WGT} {2058397200 -7200 1 WGST} {2077146000 -10800 0 WGT} {2090451600 -7200 1 WGST} {2108595600 -10800 0 WGT} {2121901200 -7200 1 WGST} {2140045200 -10800 0 WGT} {2153350800 -7200 1 WGST} {2172099600 -10800 0 WGT} {2184800400 -7200 1 WGST} {2203549200 -10800 0 WGT} {2216250000 -7200 1 WGST} {2234998800 -10800 0 WGT} {2248304400 -7200 1 WGST} {2266448400 -10800 0 WGT} {2279754000 -7200 1 WGST} {2297898000 -10800 0 WGT} {2311203600 -7200 1 WGST} {2329347600 -10800 0 WGT} {2342653200 -7200 1 WGST} {2361402000 -10800 0 WGT} {2374102800 -7200 1 WGST} {2392851600 -10800 0 WGT} {2405552400 -7200 1 WGST} {2424301200 -10800 0 WGT} {2437606800 -7200 1 WGST} {2455750800 -10800 0 WGT} {2469056400 -7200 1 WGST} {2487200400 -10800 0 WGT} {2500506000 -7200 1 WGST} {2519254800 -10800 0 WGT} {2531955600 -7200 1 WGST} {2550704400 -10800 0 WGT} {2563405200 -7200 1 WGST} {2582154000 -10800 0 WGT} {2595459600 -7200 1 WGST} {2613603600 -10800 0 WGT} {2626909200 -7200 1 WGST} {2645053200 -10800 0 WGT} {2658358800 -7200 1 WGST} {2676502800 -10800 0 WGT} {2689808400 -7200 1 WGST} {2708557200 -10800 0 WGT} {2721258000 -7200 1 WGST} {2740006800 -10800 0 WGT} {2752707600 -7200 1 WGST} {2771456400 -10800 0 WGT} {2784762000 -7200 1 WGST} {2802906000 -10800 0 WGT} {2816211600 -7200 1 WGST} {2834355600 -10800 0 WGT} {2847661200 -7200 1 WGST} {2866410000 -10800 0 WGT} {2879110800 -7200 1 WGST} {2897859600 -10800 0 WGT} {2910560400 -7200 1 WGST} {2929309200 -10800 0 WGT} {2942010000 -7200 1 WGST} {2960758800 -10800 0 WGT} {2974064400 -7200 1 WGST} {2992208400 -10800 0 WGT} {3005514000 -7200 1 WGST} {3023658000 -10800 0 WGT} {3036963600 -7200 1 WGST} {3055712400 -10800 0 WGT} {3068413200 -7200 1 WGST} {3087162000 -10800 0 WGT} {3099862800 -7200 1 WGST} {3118611600 -10800 0 WGT} {3131917200 -7200 1 WGST} {3150061200 -10800 0 WGT} {3163366800 -7200 1 WGST} {3181510800 -10800 0 WGT} {3194816400 -7200 1 WGST} {3212960400 -10800 0 WGT} {3226266000 -7200 1 WGST} {3245014800 -10800 0 WGT} {3257715600 -7200 1 WGST} {3276464400 -10800 0 WGT} {3289165200 -7200 1 WGST} {3307914000 -10800 0 WGT} {3321219600 -7200 1 WGST} {3339363600 -10800 0 WGT} {3352669200 -7200 1 WGST} {3370813200 -10800 0 WGT} {3384118800 -7200 1 WGST} {3402867600 -10800 0 WGT} {3415568400 -7200 1 WGST} {3434317200 -10800 0 WGT} {3447018000 -7200 1 WGST} {3465766800 -10800 0 WGT} {3479072400 -7200 1 WGST} {3497216400 -10800 0 WGT} {3510522000 -7200 1 WGST} {3528666000 -10800 0 WGT} {3541971600 -7200 1 WGST} {3560115600 -10800 0 WGT} {3573421200 -7200 1 WGST} {3592170000 -10800 0 WGT} {3604870800 -7200 1 WGST} {3623619600 -10800 0 WGT} {3636320400 -7200 1 WGST} {3655069200 -10800 0 WGT} {3668374800 -7200 1 WGST} {3686518800 -10800 0 WGT} {3699824400 -7200 1 WGST} {3717968400 -10800 0 WGT} {3731274000 -7200 1 WGST} {3750022800 -10800 0 WGT} {3762723600 -7200 1 WGST} {3781472400 -10800 0 WGT} {3794173200 -7200 1 WGST} {3812922000 -10800 0 WGT} {3825622800 -7200 1 WGST} {3844371600 -10800 0 WGT} {3857677200 -7200 1 WGST} {3875821200 -10800 0 WGT} {3889126800 -7200 1 WGST} {3907270800 -10800 0 WGT} {3920576400 -7200 1 WGST} {3939325200 -10800 0 WGT} {3952026000 -7200 1 WGST} {3970774800 -10800 0 WGT} {3983475600 -7200 1 WGST} {4002224400 -10800 0 WGT} {4015530000 -7200 1 WGST} {4033674000 -10800 0 WGT} {4046979600 -7200 1 WGST} {4065123600 -10800 0 WGT} {4078429200 -7200 1 WGST} {4096573200 -10800 0 WGT} } tcl8.6.5/library/tzdata/America/Scoresbysund0000644000175000017500000001507112661614721020471 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Scoresbysund) { {-9223372036854775808 -5272 0 LMT} {-1686090728 -7200 0 CGT} {323841600 -3600 0 CGST} {338961600 -7200 0 CGT} {354679200 0 0 EGST} {370400400 -3600 0 EGT} {386125200 0 1 EGST} {401850000 -3600 0 EGT} {417574800 0 1 EGST} {433299600 -3600 0 EGT} {449024400 0 1 EGST} {465354000 -3600 0 EGT} {481078800 0 1 EGST} {496803600 -3600 0 EGT} {512528400 0 1 EGST} {528253200 -3600 0 EGT} {543978000 0 1 EGST} {559702800 -3600 0 EGT} {575427600 0 1 EGST} {591152400 -3600 0 EGT} {606877200 0 1 EGST} {622602000 -3600 0 EGT} {638326800 0 1 EGST} {654656400 -3600 0 EGT} {670381200 0 1 EGST} {686106000 -3600 0 EGT} {701830800 0 1 EGST} {717555600 -3600 0 EGT} {733280400 0 1 EGST} {749005200 -3600 0 EGT} {764730000 0 1 EGST} {780454800 -3600 0 EGT} {796179600 0 1 EGST} {811904400 -3600 0 EGT} {828234000 0 1 EGST} {846378000 -3600 0 EGT} {859683600 0 1 EGST} {877827600 -3600 0 EGT} {891133200 0 1 EGST} {909277200 -3600 0 EGT} {922582800 0 1 EGST} {941331600 -3600 0 EGT} {954032400 0 1 EGST} {972781200 -3600 0 EGT} {985482000 0 1 EGST} {1004230800 -3600 0 EGT} {1017536400 0 1 EGST} {1035680400 -3600 0 EGT} {1048986000 0 1 EGST} {1067130000 -3600 0 EGT} {1080435600 0 1 EGST} {1099184400 -3600 0 EGT} {1111885200 0 1 EGST} {1130634000 -3600 0 EGT} {1143334800 0 1 EGST} {1162083600 -3600 0 EGT} {1174784400 0 1 EGST} {1193533200 -3600 0 EGT} {1206838800 0 1 EGST} {1224982800 -3600 0 EGT} {1238288400 0 1 EGST} {1256432400 -3600 0 EGT} {1269738000 0 1 EGST} {1288486800 -3600 0 EGT} {1301187600 0 1 EGST} {1319936400 -3600 0 EGT} {1332637200 0 1 EGST} {1351386000 -3600 0 EGT} {1364691600 0 1 EGST} {1382835600 -3600 0 EGT} {1396141200 0 1 EGST} {1414285200 -3600 0 EGT} {1427590800 0 1 EGST} {1445734800 -3600 0 EGT} {1459040400 0 1 EGST} {1477789200 -3600 0 EGT} {1490490000 0 1 EGST} {1509238800 -3600 0 EGT} {1521939600 0 1 EGST} {1540688400 -3600 0 EGT} {1553994000 0 1 EGST} {1572138000 -3600 0 EGT} {1585443600 0 1 EGST} {1603587600 -3600 0 EGT} {1616893200 0 1 EGST} {1635642000 -3600 0 EGT} {1648342800 0 1 EGST} {1667091600 -3600 0 EGT} {1679792400 0 1 EGST} {1698541200 -3600 0 EGT} {1711846800 0 1 EGST} {1729990800 -3600 0 EGT} {1743296400 0 1 EGST} {1761440400 -3600 0 EGT} {1774746000 0 1 EGST} {1792890000 -3600 0 EGT} {1806195600 0 1 EGST} {1824944400 -3600 0 EGT} {1837645200 0 1 EGST} {1856394000 -3600 0 EGT} {1869094800 0 1 EGST} {1887843600 -3600 0 EGT} {1901149200 0 1 EGST} {1919293200 -3600 0 EGT} {1932598800 0 1 EGST} {1950742800 -3600 0 EGT} {1964048400 0 1 EGST} {1982797200 -3600 0 EGT} {1995498000 0 1 EGST} {2014246800 -3600 0 EGT} {2026947600 0 1 EGST} {2045696400 -3600 0 EGT} {2058397200 0 1 EGST} {2077146000 -3600 0 EGT} {2090451600 0 1 EGST} {2108595600 -3600 0 EGT} {2121901200 0 1 EGST} {2140045200 -3600 0 EGT} {2153350800 0 1 EGST} {2172099600 -3600 0 EGT} {2184800400 0 1 EGST} {2203549200 -3600 0 EGT} {2216250000 0 1 EGST} {2234998800 -3600 0 EGT} {2248304400 0 1 EGST} {2266448400 -3600 0 EGT} {2279754000 0 1 EGST} {2297898000 -3600 0 EGT} {2311203600 0 1 EGST} {2329347600 -3600 0 EGT} {2342653200 0 1 EGST} {2361402000 -3600 0 EGT} {2374102800 0 1 EGST} {2392851600 -3600 0 EGT} {2405552400 0 1 EGST} {2424301200 -3600 0 EGT} {2437606800 0 1 EGST} {2455750800 -3600 0 EGT} {2469056400 0 1 EGST} {2487200400 -3600 0 EGT} {2500506000 0 1 EGST} {2519254800 -3600 0 EGT} {2531955600 0 1 EGST} {2550704400 -3600 0 EGT} {2563405200 0 1 EGST} {2582154000 -3600 0 EGT} {2595459600 0 1 EGST} {2613603600 -3600 0 EGT} {2626909200 0 1 EGST} {2645053200 -3600 0 EGT} {2658358800 0 1 EGST} {2676502800 -3600 0 EGT} {2689808400 0 1 EGST} {2708557200 -3600 0 EGT} {2721258000 0 1 EGST} {2740006800 -3600 0 EGT} {2752707600 0 1 EGST} {2771456400 -3600 0 EGT} {2784762000 0 1 EGST} {2802906000 -3600 0 EGT} {2816211600 0 1 EGST} {2834355600 -3600 0 EGT} {2847661200 0 1 EGST} {2866410000 -3600 0 EGT} {2879110800 0 1 EGST} {2897859600 -3600 0 EGT} {2910560400 0 1 EGST} {2929309200 -3600 0 EGT} {2942010000 0 1 EGST} {2960758800 -3600 0 EGT} {2974064400 0 1 EGST} {2992208400 -3600 0 EGT} {3005514000 0 1 EGST} {3023658000 -3600 0 EGT} {3036963600 0 1 EGST} {3055712400 -3600 0 EGT} {3068413200 0 1 EGST} {3087162000 -3600 0 EGT} {3099862800 0 1 EGST} {3118611600 -3600 0 EGT} {3131917200 0 1 EGST} {3150061200 -3600 0 EGT} {3163366800 0 1 EGST} {3181510800 -3600 0 EGT} {3194816400 0 1 EGST} {3212960400 -3600 0 EGT} {3226266000 0 1 EGST} {3245014800 -3600 0 EGT} {3257715600 0 1 EGST} {3276464400 -3600 0 EGT} {3289165200 0 1 EGST} {3307914000 -3600 0 EGT} {3321219600 0 1 EGST} {3339363600 -3600 0 EGT} {3352669200 0 1 EGST} {3370813200 -3600 0 EGT} {3384118800 0 1 EGST} {3402867600 -3600 0 EGT} {3415568400 0 1 EGST} {3434317200 -3600 0 EGT} {3447018000 0 1 EGST} {3465766800 -3600 0 EGT} {3479072400 0 1 EGST} {3497216400 -3600 0 EGT} {3510522000 0 1 EGST} {3528666000 -3600 0 EGT} {3541971600 0 1 EGST} {3560115600 -3600 0 EGT} {3573421200 0 1 EGST} {3592170000 -3600 0 EGT} {3604870800 0 1 EGST} {3623619600 -3600 0 EGT} {3636320400 0 1 EGST} {3655069200 -3600 0 EGT} {3668374800 0 1 EGST} {3686518800 -3600 0 EGT} {3699824400 0 1 EGST} {3717968400 -3600 0 EGT} {3731274000 0 1 EGST} {3750022800 -3600 0 EGT} {3762723600 0 1 EGST} {3781472400 -3600 0 EGT} {3794173200 0 1 EGST} {3812922000 -3600 0 EGT} {3825622800 0 1 EGST} {3844371600 -3600 0 EGT} {3857677200 0 1 EGST} {3875821200 -3600 0 EGT} {3889126800 0 1 EGST} {3907270800 -3600 0 EGT} {3920576400 0 1 EGST} {3939325200 -3600 0 EGT} {3952026000 0 1 EGST} {3970774800 -3600 0 EGT} {3983475600 0 1 EGST} {4002224400 -3600 0 EGT} {4015530000 0 1 EGST} {4033674000 -3600 0 EGT} {4046979600 0 1 EGST} {4065123600 -3600 0 EGT} {4078429200 0 1 EGST} {4096573200 -3600 0 EGT} } tcl8.6.5/library/tzdata/America/Fortaleza0000644000175000017500000000256212661614720017735 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Fortaleza) { {-9223372036854775808 -9240 0 LMT} {-1767216360 -10800 0 BRT} {-1206957600 -7200 1 BRST} {-1191362400 -10800 0 BRT} {-1175374800 -7200 1 BRST} {-1159826400 -10800 0 BRT} {-633819600 -7200 1 BRST} {-622069200 -10800 0 BRT} {-602283600 -7200 1 BRST} {-591832800 -10800 0 BRT} {-570747600 -7200 1 BRST} {-560210400 -10800 0 BRT} {-539125200 -7200 1 BRST} {-531352800 -10800 0 BRT} {-191365200 -7200 1 BRST} {-184197600 -10800 0 BRT} {-155163600 -7200 1 BRST} {-150069600 -10800 0 BRT} {-128898000 -7200 1 BRST} {-121125600 -10800 0 BRT} {-99954000 -7200 1 BRST} {-89589600 -10800 0 BRT} {-68418000 -7200 1 BRST} {-57967200 -10800 0 BRT} {499748400 -7200 1 BRST} {511236000 -10800 0 BRT} {530593200 -7200 1 BRST} {540266400 -10800 0 BRT} {562129200 -7200 1 BRST} {571197600 -10800 0 BRT} {592974000 -7200 1 BRST} {602042400 -10800 0 BRT} {624423600 -7200 1 BRST} {634701600 -10800 0 BRT} {653536800 -10800 0 BRT} {938660400 -10800 0 BRT} {938919600 -7200 1 BRST} {951616800 -10800 0 BRT} {970974000 -7200 1 BRST} {972180000 -10800 0 BRT} {1000350000 -10800 0 BRT} {1003028400 -7200 1 BRST} {1013911200 -10800 0 BRT} {1033437600 -10800 0 BRT} } tcl8.6.5/library/tzdata/America/Tegucigalpa0000644000175000017500000000051112661614721020224 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Tegucigalpa) { {-9223372036854775808 -20932 0 LMT} {-1538503868 -21600 0 CST} {547020000 -18000 1 CDT} {559717200 -21600 0 CST} {578469600 -18000 1 CDT} {591166800 -21600 0 CST} {1146981600 -18000 1 CDT} {1154926800 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Indiana/0000755000175000017500000000000012665173607017431 5ustar sergeisergeitcl8.6.5/library/tzdata/America/Indiana/Vevay0000644000175000017500000001431612661614721020444 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Indiana/Vevay) { {-9223372036854775808 -20416 0 LMT} {-2717647200 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-495043200 -18000 0 EST} {-31518000 -18000 0 EST} {-21488400 -14400 1 EDT} {-5767200 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {41410800 -14400 1 EDT} {57736800 -18000 0 EST} {73465200 -14400 1 EDT} {89186400 -18000 0 EST} {94712400 -18000 0 EST} {1136091600 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Indiana/Winamac0000644000175000017500000001600212661614721020723 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Indiana/Winamac) { {-9223372036854775808 -20785 0 LMT} {-2717647200 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-757360800 -21600 0 CST} {-747244800 -18000 1 CDT} {-733942800 -21600 0 CST} {-715795200 -18000 1 CDT} {-702493200 -21600 0 CST} {-684345600 -18000 1 CDT} {-671043600 -21600 0 CST} {-652896000 -18000 1 CDT} {-639594000 -21600 0 CST} {-620841600 -18000 1 CDT} {-608144400 -21600 0 CST} {-589392000 -18000 1 CDT} {-576090000 -21600 0 CST} {-557942400 -18000 1 CDT} {-544640400 -21600 0 CST} {-526492800 -18000 1 CDT} {-513190800 -21600 0 CST} {-495043200 -18000 1 CDT} {-481741200 -21600 0 CST} {-463593600 -18000 1 CDT} {-447267600 -21600 0 CST} {-431539200 -18000 1 CDT} {-415818000 -21600 0 CST} {-400089600 -18000 1 CDT} {-386787600 -21600 0 CST} {-368640000 -18000 1 CDT} {-355338000 -21600 0 CST} {-337190400 -18000 1 CDT} {-323888400 -21600 0 CST} {-305740800 -18000 1 CDT} {-292438800 -21600 0 CST} {-273686400 -18000 0 EST} {-31518000 -18000 0 EST} {-21488400 -14400 1 EDT} {-5767200 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {31554000 -18000 0 EST} {1143961200 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -14400 0 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Indiana/Petersburg0000644000175000017500000001630412661614720021472 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Indiana/Petersburg) { {-9223372036854775808 -20947 0 LMT} {-2717647200 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-473364000 -21600 0 CST} {-462996000 -18000 1 CDT} {-450291600 -21600 0 CST} {-431539200 -18000 1 CDT} {-418237200 -21600 0 CST} {-400089600 -18000 1 CDT} {-386787600 -21600 0 CST} {-368640000 -18000 1 CDT} {-355338000 -21600 0 CST} {-337190400 -18000 1 CDT} {-323888400 -21600 0 CST} {-305740800 -18000 1 CDT} {-292438800 -21600 0 CST} {-273686400 -18000 1 CDT} {-257965200 -21600 0 CST} {-242236800 -18000 1 CDT} {-226515600 -21600 0 CST} {-210787200 -18000 1 CDT} {-195066000 -21600 0 CST} {-179337600 -18000 1 CDT} {-163616400 -21600 0 CST} {-147888000 -18000 0 EST} {-100112400 -21600 0 CST} {-84384000 -18000 1 CDT} {-68662800 -21600 0 CST} {-52934400 -18000 1 CDT} {-37213200 -21600 0 CST} {-21484800 -18000 1 CDT} {-5763600 -21600 0 CST} {9964800 -18000 1 CDT} {25686000 -21600 0 CST} {41414400 -18000 1 CDT} {57740400 -21600 0 CST} {73468800 -18000 1 CDT} {89190000 -21600 0 CST} {104918400 -18000 1 CDT} {120639600 -21600 0 CST} {126691200 -18000 1 CDT} {152089200 -21600 0 CST} {162374400 -18000 1 CDT} {183538800 -21600 0 CST} {199267200 -18000 1 CDT} {215593200 -21600 0 CST} {230716800 -18000 1 CDT} {247046400 -18000 0 EST} {1143961200 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194163200 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Indiana/Vincennes0000644000175000017500000001552012661614721021300 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Indiana/Vincennes) { {-9223372036854775808 -21007 0 LMT} {-2717647200 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-757360800 -21600 0 CST} {-747244800 -18000 1 CDT} {-733942800 -21600 0 CST} {-526492800 -18000 1 CDT} {-513190800 -21600 0 CST} {-495043200 -18000 1 CDT} {-481741200 -21600 0 CST} {-462996000 -18000 1 CDT} {-450291600 -21600 0 CST} {-431539200 -18000 1 CDT} {-418237200 -21600 0 CST} {-400089600 -18000 1 CDT} {-386787600 -21600 0 CST} {-368640000 -18000 1 CDT} {-355338000 -21600 0 CST} {-337190400 -18000 1 CDT} {-323888400 -21600 0 CST} {-305740800 -18000 1 CDT} {-289414800 -21600 0 CST} {-273686400 -18000 1 CDT} {-260989200 -21600 0 CST} {-242236800 -18000 1 CDT} {-226515600 -21600 0 CST} {-210787200 -18000 1 CDT} {-195066000 -21600 0 CST} {-179337600 -18000 0 EST} {-31518000 -18000 0 EST} {-21488400 -14400 1 EDT} {-5767200 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {31554000 -18000 0 EST} {1143961200 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194163200 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Indiana/Indianapolis0000644000175000017500000001552412661614720021765 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Indiana/Indianapolis) { {-9223372036854775808 -20678 0 LMT} {-2717647200 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-1577901600 -21600 0 CST} {-900259200 -18000 1 CDT} {-891795600 -21600 0 CST} {-883591200 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-757360800 -21600 0 CST} {-747244800 -18000 1 CDT} {-733942800 -21600 0 CST} {-715795200 -18000 1 CDT} {-702493200 -21600 0 CST} {-684345600 -18000 1 CDT} {-671043600 -21600 0 CST} {-652896000 -18000 1 CDT} {-639594000 -21600 0 CST} {-620841600 -18000 1 CDT} {-608144400 -21600 0 CST} {-589392000 -18000 1 CDT} {-576090000 -21600 0 CST} {-557942400 -18000 1 CDT} {-544640400 -21600 0 CST} {-526492800 -18000 1 CDT} {-513190800 -21600 0 CST} {-495043200 -18000 1 CDT} {-481741200 -21600 0 CST} {-463593600 -18000 0 EST} {-386787600 -21600 0 CST} {-368640000 -18000 0 EST} {-31518000 -18000 0 EST} {-21488400 -14400 1 EDT} {-5767200 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {31554000 -18000 0 EST} {1136091600 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Indiana/Tell_City0000644000175000017500000001552012661614721021240 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Indiana/Tell_City) { {-9223372036854775808 -20823 0 LMT} {-2717647200 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-757360800 -21600 0 CST} {-747244800 -18000 1 CDT} {-733942800 -21600 0 CST} {-526492800 -18000 1 CDT} {-513190800 -21600 0 CST} {-495043200 -18000 1 CDT} {-481741200 -21600 0 CST} {-462996000 -18000 1 CDT} {-450291600 -21600 0 CST} {-431539200 -18000 1 CDT} {-418237200 -21600 0 CST} {-400089600 -18000 1 CDT} {-386787600 -21600 0 CST} {-368640000 -18000 1 CDT} {-355338000 -21600 0 CST} {-337190400 -18000 1 CDT} {-323888400 -21600 0 CST} {-305740800 -18000 1 CDT} {-289414800 -21600 0 CST} {-273686400 -18000 1 CDT} {-260989200 -21600 0 CST} {-242236800 -18000 1 CDT} {-226515600 -21600 0 CST} {-210787200 -18000 1 CDT} {-195066000 -21600 0 CST} {-179337600 -18000 0 EST} {-31518000 -18000 0 EST} {-21488400 -14400 1 EDT} {-5767200 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {31554000 -18000 0 EST} {1143961200 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194159600 -21600 0 CST} {1205049600 -18000 1 CDT} {1225609200 -21600 0 CST} {1236499200 -18000 1 CDT} {1257058800 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Indiana/Marengo0000644000175000017500000001557512661614720020751 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Indiana/Marengo) { {-9223372036854775808 -20723 0 LMT} {-2717647200 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-599594400 -21600 0 CST} {-589392000 -18000 1 CDT} {-576090000 -21600 0 CST} {-495043200 -18000 1 CDT} {-481741200 -21600 0 CST} {-463593600 -18000 1 CDT} {-450291600 -21600 0 CST} {-431539200 -18000 1 CDT} {-418237200 -21600 0 CST} {-400089600 -18000 1 CDT} {-386787600 -21600 0 CST} {-368640000 -18000 1 CDT} {-355338000 -21600 0 CST} {-337190400 -18000 1 CDT} {-323888400 -21600 0 CST} {-305740800 -18000 1 CDT} {-292438800 -21600 0 CST} {-273686400 -18000 0 EST} {-31518000 -18000 0 EST} {-21488400 -14400 1 EDT} {-5767200 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {41410800 -14400 1 EDT} {57736800 -18000 0 EST} {73465200 -14400 1 EDT} {89186400 -18000 0 EST} {104914800 -14400 1 EDT} {120636000 -18000 0 EST} {126687600 -18000 1 CDT} {152089200 -18000 0 EST} {162370800 -14400 1 EDT} {183535200 -18000 0 EST} {189320400 -18000 0 EST} {1136091600 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Indiana/Knox0000644000175000017500000002042612661614720020267 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Indiana/Knox) { {-9223372036854775808 -20790 0 LMT} {-2717647200 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-725824800 -21600 0 CST} {-715795200 -18000 1 CDT} {-702493200 -21600 0 CST} {-684345600 -18000 1 CDT} {-671043600 -21600 0 CST} {-652896000 -18000 1 CDT} {-639594000 -21600 0 CST} {-620841600 -18000 1 CDT} {-608144400 -21600 0 CST} {-589392000 -18000 1 CDT} {-576090000 -21600 0 CST} {-557942400 -18000 1 CDT} {-544640400 -21600 0 CST} {-526492800 -18000 1 CDT} {-513190800 -21600 0 CST} {-495043200 -18000 1 CDT} {-481741200 -21600 0 CST} {-463593600 -18000 1 CDT} {-447267600 -21600 0 CST} {-431539200 -18000 1 CDT} {-415818000 -21600 0 CST} {-400089600 -18000 1 CDT} {-386787600 -21600 0 CST} {-368640000 -18000 1 CDT} {-355338000 -21600 0 CST} {-337190400 -18000 1 CDT} {-321469200 -21600 0 CST} {-305740800 -18000 1 CDT} {-289414800 -21600 0 CST} {-273686400 -18000 1 CDT} {-257965200 -21600 0 CST} {-242236800 -18000 0 EST} {-195066000 -21600 0 CST} {-84384000 -18000 1 CDT} {-68662800 -21600 0 CST} {-52934400 -18000 1 CDT} {-37213200 -21600 0 CST} {-21484800 -18000 1 CDT} {-5763600 -21600 0 CST} {9964800 -18000 1 CDT} {25686000 -21600 0 CST} {41414400 -18000 1 CDT} {57740400 -21600 0 CST} {73468800 -18000 1 CDT} {89190000 -21600 0 CST} {104918400 -18000 1 CDT} {120639600 -21600 0 CST} {126691200 -18000 1 CDT} {152089200 -21600 0 CST} {162374400 -18000 1 CDT} {183538800 -21600 0 CST} {199267200 -18000 1 CDT} {215593200 -21600 0 CST} {230716800 -18000 1 CDT} {247042800 -21600 0 CST} {262771200 -18000 1 CDT} {278492400 -21600 0 CST} {294220800 -18000 1 CDT} {309942000 -21600 0 CST} {325670400 -18000 1 CDT} {341391600 -21600 0 CST} {357120000 -18000 1 CDT} {372841200 -21600 0 CST} {388569600 -18000 1 CDT} {404895600 -21600 0 CST} {420019200 -18000 1 CDT} {436345200 -21600 0 CST} {452073600 -18000 1 CDT} {467794800 -21600 0 CST} {483523200 -18000 1 CDT} {499244400 -21600 0 CST} {514972800 -18000 1 CDT} {530694000 -21600 0 CST} {544608000 -18000 1 CDT} {562143600 -21600 0 CST} {576057600 -18000 1 CDT} {594198000 -21600 0 CST} {607507200 -18000 1 CDT} {625647600 -21600 0 CST} {638956800 -18000 1 CDT} {657097200 -21600 0 CST} {671011200 -18000 1 CDT} {688550400 -18000 0 EST} {1143961200 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194159600 -21600 0 CST} {1205049600 -18000 1 CDT} {1225609200 -21600 0 CST} {1236499200 -18000 1 CDT} {1257058800 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Regina0000644000175000017500000000327312663660066017221 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Regina) { {-9223372036854775808 -25116 0 LMT} {-2030202084 -25200 0 MST} {-1632063600 -21600 1 MDT} {-1615132800 -25200 0 MST} {-1251651600 -21600 1 MDT} {-1238349600 -25200 0 MST} {-1220202000 -21600 1 MDT} {-1206900000 -25200 0 MST} {-1188752400 -21600 1 MDT} {-1175450400 -25200 0 MST} {-1156698000 -21600 1 MDT} {-1144000800 -25200 0 MST} {-1125248400 -21600 1 MDT} {-1111946400 -25200 0 MST} {-1032714000 -21600 1 MDT} {-1016992800 -25200 0 MST} {-1001264400 -21600 1 MDT} {-986148000 -25200 0 MST} {-969814800 -21600 1 MDT} {-954093600 -25200 0 MST} {-937760400 -21600 1 MDT} {-922039200 -25200 0 MST} {-906310800 -21600 1 MDT} {-890589600 -25200 0 MST} {-880210800 -21600 1 MWT} {-769395600 -21600 1 MPT} {-765388800 -25200 0 MST} {-748450800 -21600 1 MDT} {-732729600 -25200 0 MST} {-715791600 -21600 1 MDT} {-702489600 -25200 0 MST} {-684342000 -21600 1 MDT} {-671040000 -25200 0 MST} {-652892400 -21600 1 MDT} {-639590400 -25200 0 MST} {-620838000 -21600 1 MDT} {-608140800 -25200 0 MST} {-589388400 -21600 1 MDT} {-576086400 -25200 0 MST} {-557938800 -21600 1 MDT} {-544636800 -25200 0 MST} {-526489200 -21600 1 MDT} {-513187200 -25200 0 MST} {-495039600 -21600 1 MDT} {-481737600 -25200 0 MST} {-463590000 -21600 1 MDT} {-450288000 -25200 0 MST} {-431535600 -21600 1 MDT} {-418233600 -25200 0 MST} {-400086000 -21600 1 MDT} {-386784000 -25200 0 MST} {-337186800 -21600 1 MDT} {-321465600 -25200 0 MST} {-305737200 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Mexico_City0000644000175000017500000001522712661614721020225 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Mexico_City) { {-9223372036854775808 -23796 0 LMT} {-1514739600 -25200 0 MST} {-1343066400 -21600 0 CST} {-1234807200 -25200 0 MST} {-1220292000 -21600 0 CST} {-1207159200 -25200 0 MST} {-1191344400 -21600 0 CST} {-975261600 -18000 1 CDT} {-963169200 -21600 0 CST} {-917114400 -18000 1 CDT} {-907354800 -21600 0 CST} {-821901600 -18000 1 CWT} {-810068400 -21600 0 CST} {-627501600 -18000 1 CDT} {-612990000 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972802800 -21600 0 CST} {989136000 -18000 1 CDT} {1001836800 -21600 0 CST} {1014184800 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1175414400 -18000 1 CDT} {1193554800 -21600 0 CST} {1207468800 -18000 1 CDT} {1225004400 -21600 0 CST} {1238918400 -18000 1 CDT} {1256454000 -21600 0 CST} {1270368000 -18000 1 CDT} {1288508400 -21600 0 CST} {1301817600 -18000 1 CDT} {1319958000 -21600 0 CST} {1333267200 -18000 1 CDT} {1351407600 -21600 0 CST} {1365321600 -18000 1 CDT} {1382857200 -21600 0 CST} {1396771200 -18000 1 CDT} {1414306800 -21600 0 CST} {1428220800 -18000 1 CDT} {1445756400 -21600 0 CST} {1459670400 -18000 1 CDT} {1477810800 -21600 0 CST} {1491120000 -18000 1 CDT} {1509260400 -21600 0 CST} {1522569600 -18000 1 CDT} {1540710000 -21600 0 CST} {1554624000 -18000 1 CDT} {1572159600 -21600 0 CST} {1586073600 -18000 1 CDT} {1603609200 -21600 0 CST} {1617523200 -18000 1 CDT} {1635663600 -21600 0 CST} {1648972800 -18000 1 CDT} {1667113200 -21600 0 CST} {1680422400 -18000 1 CDT} {1698562800 -21600 0 CST} {1712476800 -18000 1 CDT} {1730012400 -21600 0 CST} {1743926400 -18000 1 CDT} {1761462000 -21600 0 CST} {1775376000 -18000 1 CDT} {1792911600 -21600 0 CST} {1806825600 -18000 1 CDT} {1824966000 -21600 0 CST} {1838275200 -18000 1 CDT} {1856415600 -21600 0 CST} {1869724800 -18000 1 CDT} {1887865200 -21600 0 CST} {1901779200 -18000 1 CDT} {1919314800 -21600 0 CST} {1933228800 -18000 1 CDT} {1950764400 -21600 0 CST} {1964678400 -18000 1 CDT} {1982818800 -21600 0 CST} {1996128000 -18000 1 CDT} {2014268400 -21600 0 CST} {2027577600 -18000 1 CDT} {2045718000 -21600 0 CST} {2059027200 -18000 1 CDT} {2077167600 -21600 0 CST} {2091081600 -18000 1 CDT} {2108617200 -21600 0 CST} {2122531200 -18000 1 CDT} {2140066800 -21600 0 CST} {2153980800 -18000 1 CDT} {2172121200 -21600 0 CST} {2185430400 -18000 1 CDT} {2203570800 -21600 0 CST} {2216880000 -18000 1 CDT} {2235020400 -21600 0 CST} {2248934400 -18000 1 CDT} {2266470000 -21600 0 CST} {2280384000 -18000 1 CDT} {2297919600 -21600 0 CST} {2311833600 -18000 1 CDT} {2329369200 -21600 0 CST} {2343283200 -18000 1 CDT} {2361423600 -21600 0 CST} {2374732800 -18000 1 CDT} {2392873200 -21600 0 CST} {2406182400 -18000 1 CDT} {2424322800 -21600 0 CST} {2438236800 -18000 1 CDT} {2455772400 -21600 0 CST} {2469686400 -18000 1 CDT} {2487222000 -21600 0 CST} {2501136000 -18000 1 CDT} {2519276400 -21600 0 CST} {2532585600 -18000 1 CDT} {2550726000 -21600 0 CST} {2564035200 -18000 1 CDT} {2582175600 -21600 0 CST} {2596089600 -18000 1 CDT} {2613625200 -21600 0 CST} {2627539200 -18000 1 CDT} {2645074800 -21600 0 CST} {2658988800 -18000 1 CDT} {2676524400 -21600 0 CST} {2690438400 -18000 1 CDT} {2708578800 -21600 0 CST} {2721888000 -18000 1 CDT} {2740028400 -21600 0 CST} {2753337600 -18000 1 CDT} {2771478000 -21600 0 CST} {2785392000 -18000 1 CDT} {2802927600 -21600 0 CST} {2816841600 -18000 1 CDT} {2834377200 -21600 0 CST} {2848291200 -18000 1 CDT} {2866431600 -21600 0 CST} {2879740800 -18000 1 CDT} {2897881200 -21600 0 CST} {2911190400 -18000 1 CDT} {2929330800 -21600 0 CST} {2942640000 -18000 1 CDT} {2960780400 -21600 0 CST} {2974694400 -18000 1 CDT} {2992230000 -21600 0 CST} {3006144000 -18000 1 CDT} {3023679600 -21600 0 CST} {3037593600 -18000 1 CDT} {3055734000 -21600 0 CST} {3069043200 -18000 1 CDT} {3087183600 -21600 0 CST} {3100492800 -18000 1 CDT} {3118633200 -21600 0 CST} {3132547200 -18000 1 CDT} {3150082800 -21600 0 CST} {3163996800 -18000 1 CDT} {3181532400 -21600 0 CST} {3195446400 -18000 1 CDT} {3212982000 -21600 0 CST} {3226896000 -18000 1 CDT} {3245036400 -21600 0 CST} {3258345600 -18000 1 CDT} {3276486000 -21600 0 CST} {3289795200 -18000 1 CDT} {3307935600 -21600 0 CST} {3321849600 -18000 1 CDT} {3339385200 -21600 0 CST} {3353299200 -18000 1 CDT} {3370834800 -21600 0 CST} {3384748800 -18000 1 CDT} {3402889200 -21600 0 CST} {3416198400 -18000 1 CDT} {3434338800 -21600 0 CST} {3447648000 -18000 1 CDT} {3465788400 -21600 0 CST} {3479702400 -18000 1 CDT} {3497238000 -21600 0 CST} {3511152000 -18000 1 CDT} {3528687600 -21600 0 CST} {3542601600 -18000 1 CDT} {3560137200 -21600 0 CST} {3574051200 -18000 1 CDT} {3592191600 -21600 0 CST} {3605500800 -18000 1 CDT} {3623641200 -21600 0 CST} {3636950400 -18000 1 CDT} {3655090800 -21600 0 CST} {3669004800 -18000 1 CDT} {3686540400 -21600 0 CST} {3700454400 -18000 1 CDT} {3717990000 -21600 0 CST} {3731904000 -18000 1 CDT} {3750044400 -21600 0 CST} {3763353600 -18000 1 CDT} {3781494000 -21600 0 CST} {3794803200 -18000 1 CDT} {3812943600 -21600 0 CST} {3826252800 -18000 1 CDT} {3844393200 -21600 0 CST} {3858307200 -18000 1 CDT} {3875842800 -21600 0 CST} {3889756800 -18000 1 CDT} {3907292400 -21600 0 CST} {3921206400 -18000 1 CDT} {3939346800 -21600 0 CST} {3952656000 -18000 1 CDT} {3970796400 -21600 0 CST} {3984105600 -18000 1 CDT} {4002246000 -21600 0 CST} {4016160000 -18000 1 CDT} {4033695600 -21600 0 CST} {4047609600 -18000 1 CDT} {4065145200 -21600 0 CST} {4079059200 -18000 1 CDT} {4096594800 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Coral_Harbour0000644000175000017500000000030112661614722020517 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Atikokan)]} { LoadTimeZoneFile America/Atikokan } set TZData(:America/Coral_Harbour) $TZData(:America/Atikokan) tcl8.6.5/library/tzdata/America/Nassau0000644000175000017500000002010412663660066017236 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Nassau) { {-9223372036854775808 -18570 0 LMT} {-1825095030 -18000 0 EST} {-179341200 -14400 1 EDT} {-163620000 -18000 0 EST} {-147891600 -14400 1 EDT} {-131565600 -18000 0 EST} {-116442000 -14400 1 EDT} {-100116000 -18000 0 EST} {-84387600 -14400 1 EDT} {-68666400 -18000 0 EST} {-52938000 -14400 1 EDT} {-37216800 -18000 0 EST} {-21488400 -14400 1 EDT} {-5767200 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {41410800 -14400 1 EDT} {57736800 -18000 0 EST} {73465200 -14400 1 EDT} {89186400 -18000 0 EST} {104914800 -14400 1 EDT} {120636000 -18000 0 EST} {136364400 -14400 1 EDT} {152085600 -18000 0 EST} {167814000 -14400 1 EDT} {183535200 -18000 0 EST} {189320400 -18000 0 EST} {199263600 -14400 1 EDT} {215589600 -18000 0 EST} {230713200 -14400 1 EDT} {247039200 -18000 0 EST} {262767600 -14400 1 EDT} {278488800 -18000 0 EST} {294217200 -14400 1 EDT} {309938400 -18000 0 EST} {325666800 -14400 1 EDT} {341388000 -18000 0 EST} {357116400 -14400 1 EDT} {372837600 -18000 0 EST} {388566000 -14400 1 EDT} {404892000 -18000 0 EST} {420015600 -14400 1 EDT} {436341600 -18000 0 EST} {452070000 -14400 1 EDT} {467791200 -18000 0 EST} {483519600 -14400 1 EDT} {499240800 -18000 0 EST} {514969200 -14400 1 EDT} {530690400 -18000 0 EST} {544604400 -14400 1 EDT} {562140000 -18000 0 EST} {576054000 -14400 1 EDT} {594194400 -18000 0 EST} {607503600 -14400 1 EDT} {625644000 -18000 0 EST} {638953200 -14400 1 EDT} {657093600 -18000 0 EST} {671007600 -14400 1 EDT} {688543200 -18000 0 EST} {702457200 -14400 1 EDT} {719992800 -18000 0 EST} {733906800 -14400 1 EDT} {752047200 -18000 0 EST} {765356400 -14400 1 EDT} {783496800 -18000 0 EST} {796806000 -14400 1 EDT} {814946400 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {909295200 -18000 0 EST} {923209200 -14400 1 EDT} {941349600 -18000 0 EST} {954658800 -14400 1 EDT} {972799200 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Cambridge_Bay0000644000175000017500000001647712661614720020470 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Cambridge_Bay) { {-9223372036854775808 0 0 zzz} {-1577923200 -25200 0 MST} {-880210800 -21600 1 MWT} {-769395600 -21600 1 MPT} {-765388800 -25200 0 MST} {-147891600 -18000 1 MDDT} {-131562000 -25200 0 MST} {325674000 -21600 1 MDT} {341395200 -25200 0 MST} {357123600 -21600 1 MDT} {372844800 -25200 0 MST} {388573200 -21600 1 MDT} {404899200 -25200 0 MST} {420022800 -21600 1 MDT} {436348800 -25200 0 MST} {452077200 -21600 1 MDT} {467798400 -25200 0 MST} {483526800 -21600 1 MDT} {499248000 -25200 0 MST} {514976400 -21600 1 MDT} {530697600 -25200 0 MST} {544611600 -21600 1 MDT} {562147200 -25200 0 MST} {576061200 -21600 1 MDT} {594201600 -25200 0 MST} {607510800 -21600 1 MDT} {625651200 -25200 0 MST} {638960400 -21600 1 MDT} {657100800 -25200 0 MST} {671014800 -21600 1 MDT} {688550400 -25200 0 MST} {702464400 -21600 1 MDT} {720000000 -25200 0 MST} {733914000 -21600 1 MDT} {752054400 -25200 0 MST} {765363600 -21600 1 MDT} {783504000 -25200 0 MST} {796813200 -21600 1 MDT} {814953600 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941360400 -21600 0 CST} {954662400 -18000 1 CDT} {972806400 -18000 0 EST} {973400400 -21600 0 CST} {986115600 -21600 0 MDT} {1004256000 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1173603600 -21600 1 MDT} {1194163200 -25200 0 MST} {1205053200 -21600 1 MDT} {1225612800 -25200 0 MST} {1236502800 -21600 1 MDT} {1257062400 -25200 0 MST} {1268557200 -21600 1 MDT} {1289116800 -25200 0 MST} {1300006800 -21600 1 MDT} {1320566400 -25200 0 MST} {1331456400 -21600 1 MDT} {1352016000 -25200 0 MST} {1362906000 -21600 1 MDT} {1383465600 -25200 0 MST} {1394355600 -21600 1 MDT} {1414915200 -25200 0 MST} {1425805200 -21600 1 MDT} {1446364800 -25200 0 MST} {1457859600 -21600 1 MDT} {1478419200 -25200 0 MST} {1489309200 -21600 1 MDT} {1509868800 -25200 0 MST} {1520758800 -21600 1 MDT} {1541318400 -25200 0 MST} {1552208400 -21600 1 MDT} {1572768000 -25200 0 MST} {1583658000 -21600 1 MDT} {1604217600 -25200 0 MST} {1615712400 -21600 1 MDT} {1636272000 -25200 0 MST} {1647162000 -21600 1 MDT} {1667721600 -25200 0 MST} {1678611600 -21600 1 MDT} {1699171200 -25200 0 MST} {1710061200 -21600 1 MDT} {1730620800 -25200 0 MST} {1741510800 -21600 1 MDT} {1762070400 -25200 0 MST} {1772960400 -21600 1 MDT} {1793520000 -25200 0 MST} {1805014800 -21600 1 MDT} {1825574400 -25200 0 MST} {1836464400 -21600 1 MDT} {1857024000 -25200 0 MST} {1867914000 -21600 1 MDT} {1888473600 -25200 0 MST} {1899363600 -21600 1 MDT} {1919923200 -25200 0 MST} {1930813200 -21600 1 MDT} {1951372800 -25200 0 MST} {1962867600 -21600 1 MDT} {1983427200 -25200 0 MST} {1994317200 -21600 1 MDT} {2014876800 -25200 0 MST} {2025766800 -21600 1 MDT} {2046326400 -25200 0 MST} {2057216400 -21600 1 MDT} {2077776000 -25200 0 MST} {2088666000 -21600 1 MDT} {2109225600 -25200 0 MST} {2120115600 -21600 1 MDT} {2140675200 -25200 0 MST} {2152170000 -21600 1 MDT} {2172729600 -25200 0 MST} {2183619600 -21600 1 MDT} {2204179200 -25200 0 MST} {2215069200 -21600 1 MDT} {2235628800 -25200 0 MST} {2246518800 -21600 1 MDT} {2267078400 -25200 0 MST} {2277968400 -21600 1 MDT} {2298528000 -25200 0 MST} {2309418000 -21600 1 MDT} {2329977600 -25200 0 MST} {2341472400 -21600 1 MDT} {2362032000 -25200 0 MST} {2372922000 -21600 1 MDT} {2393481600 -25200 0 MST} {2404371600 -21600 1 MDT} {2424931200 -25200 0 MST} {2435821200 -21600 1 MDT} {2456380800 -25200 0 MST} {2467270800 -21600 1 MDT} {2487830400 -25200 0 MST} {2499325200 -21600 1 MDT} {2519884800 -25200 0 MST} {2530774800 -21600 1 MDT} {2551334400 -25200 0 MST} {2562224400 -21600 1 MDT} {2582784000 -25200 0 MST} {2593674000 -21600 1 MDT} {2614233600 -25200 0 MST} {2625123600 -21600 1 MDT} {2645683200 -25200 0 MST} {2656573200 -21600 1 MDT} {2677132800 -25200 0 MST} {2688627600 -21600 1 MDT} {2709187200 -25200 0 MST} {2720077200 -21600 1 MDT} {2740636800 -25200 0 MST} {2751526800 -21600 1 MDT} {2772086400 -25200 0 MST} {2782976400 -21600 1 MDT} {2803536000 -25200 0 MST} {2814426000 -21600 1 MDT} {2834985600 -25200 0 MST} {2846480400 -21600 1 MDT} {2867040000 -25200 0 MST} {2877930000 -21600 1 MDT} {2898489600 -25200 0 MST} {2909379600 -21600 1 MDT} {2929939200 -25200 0 MST} {2940829200 -21600 1 MDT} {2961388800 -25200 0 MST} {2972278800 -21600 1 MDT} {2992838400 -25200 0 MST} {3003728400 -21600 1 MDT} {3024288000 -25200 0 MST} {3035782800 -21600 1 MDT} {3056342400 -25200 0 MST} {3067232400 -21600 1 MDT} {3087792000 -25200 0 MST} {3098682000 -21600 1 MDT} {3119241600 -25200 0 MST} {3130131600 -21600 1 MDT} {3150691200 -25200 0 MST} {3161581200 -21600 1 MDT} {3182140800 -25200 0 MST} {3193030800 -21600 1 MDT} {3213590400 -25200 0 MST} {3225085200 -21600 1 MDT} {3245644800 -25200 0 MST} {3256534800 -21600 1 MDT} {3277094400 -25200 0 MST} {3287984400 -21600 1 MDT} {3308544000 -25200 0 MST} {3319434000 -21600 1 MDT} {3339993600 -25200 0 MST} {3350883600 -21600 1 MDT} {3371443200 -25200 0 MST} {3382938000 -21600 1 MDT} {3403497600 -25200 0 MST} {3414387600 -21600 1 MDT} {3434947200 -25200 0 MST} {3445837200 -21600 1 MDT} {3466396800 -25200 0 MST} {3477286800 -21600 1 MDT} {3497846400 -25200 0 MST} {3508736400 -21600 1 MDT} {3529296000 -25200 0 MST} {3540186000 -21600 1 MDT} {3560745600 -25200 0 MST} {3572240400 -21600 1 MDT} {3592800000 -25200 0 MST} {3603690000 -21600 1 MDT} {3624249600 -25200 0 MST} {3635139600 -21600 1 MDT} {3655699200 -25200 0 MST} {3666589200 -21600 1 MDT} {3687148800 -25200 0 MST} {3698038800 -21600 1 MDT} {3718598400 -25200 0 MST} {3730093200 -21600 1 MDT} {3750652800 -25200 0 MST} {3761542800 -21600 1 MDT} {3782102400 -25200 0 MST} {3792992400 -21600 1 MDT} {3813552000 -25200 0 MST} {3824442000 -21600 1 MDT} {3845001600 -25200 0 MST} {3855891600 -21600 1 MDT} {3876451200 -25200 0 MST} {3887341200 -21600 1 MDT} {3907900800 -25200 0 MST} {3919395600 -21600 1 MDT} {3939955200 -25200 0 MST} {3950845200 -21600 1 MDT} {3971404800 -25200 0 MST} {3982294800 -21600 1 MDT} {4002854400 -25200 0 MST} {4013744400 -21600 1 MDT} {4034304000 -25200 0 MST} {4045194000 -21600 1 MDT} {4065753600 -25200 0 MST} {4076643600 -21600 1 MDT} {4097203200 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Manaus0000644000175000017500000000216612661614721017233 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Manaus) { {-9223372036854775808 -14404 0 LMT} {-1767211196 -14400 0 AMT} {-1206954000 -10800 1 AMST} {-1191358800 -14400 0 AMT} {-1175371200 -10800 1 AMST} {-1159822800 -14400 0 AMT} {-633816000 -10800 1 AMST} {-622065600 -14400 0 AMT} {-602280000 -10800 1 AMST} {-591829200 -14400 0 AMT} {-570744000 -10800 1 AMST} {-560206800 -14400 0 AMT} {-539121600 -10800 1 AMST} {-531349200 -14400 0 AMT} {-191361600 -10800 1 AMST} {-184194000 -14400 0 AMT} {-155160000 -10800 1 AMST} {-150066000 -14400 0 AMT} {-128894400 -10800 1 AMST} {-121122000 -14400 0 AMT} {-99950400 -10800 1 AMST} {-89586000 -14400 0 AMT} {-68414400 -10800 1 AMST} {-57963600 -14400 0 AMT} {499752000 -10800 1 AMST} {511239600 -14400 0 AMT} {530596800 -10800 1 AMST} {540270000 -14400 0 AMT} {562132800 -10800 1 AMST} {571201200 -14400 0 AMT} {590036400 -14400 0 AMT} {749188800 -14400 0 AMT} {750830400 -10800 1 AMST} {761713200 -14400 0 AMT} {780202800 -14400 0 AMT} } tcl8.6.5/library/tzdata/America/St_Kitts0000644000175000017500000000031312663660066017550 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/St_Kitts) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Shiprock0000644000175000017500000000026612661614722017571 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Denver)]} { LoadTimeZoneFile America/Denver } set TZData(:America/Shiprock) $TZData(:America/Denver) tcl8.6.5/library/tzdata/America/Ojinaga0000644000175000017500000001473512663653207017370 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Ojinaga) { {-9223372036854775808 -25060 0 LMT} {-1514739600 -25200 0 MST} {-1343066400 -21600 0 CST} {-1234807200 -25200 0 MST} {-1220292000 -21600 0 CST} {-1207159200 -25200 0 MST} {-1191344400 -21600 0 CST} {820476000 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {883634400 -21600 0 CST} {891766800 -21600 0 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {989139600 -21600 1 MDT} {1001836800 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1175418000 -21600 1 MDT} {1193558400 -25200 0 MST} {1207472400 -21600 1 MDT} {1225008000 -25200 0 MST} {1238922000 -21600 1 MDT} {1256457600 -25200 0 MST} {1262329200 -25200 0 MST} {1268557200 -21600 1 MDT} {1289116800 -25200 0 MST} {1300006800 -21600 1 MDT} {1320566400 -25200 0 MST} {1331456400 -21600 1 MDT} {1352016000 -25200 0 MST} {1362906000 -21600 1 MDT} {1383465600 -25200 0 MST} {1394355600 -21600 1 MDT} {1414915200 -25200 0 MST} {1425805200 -21600 1 MDT} {1446364800 -25200 0 MST} {1457859600 -21600 1 MDT} {1478419200 -25200 0 MST} {1489309200 -21600 1 MDT} {1509868800 -25200 0 MST} {1520758800 -21600 1 MDT} {1541318400 -25200 0 MST} {1552208400 -21600 1 MDT} {1572768000 -25200 0 MST} {1583658000 -21600 1 MDT} {1604217600 -25200 0 MST} {1615712400 -21600 1 MDT} {1636272000 -25200 0 MST} {1647162000 -21600 1 MDT} {1667721600 -25200 0 MST} {1678611600 -21600 1 MDT} {1699171200 -25200 0 MST} {1710061200 -21600 1 MDT} {1730620800 -25200 0 MST} {1741510800 -21600 1 MDT} {1762070400 -25200 0 MST} {1772960400 -21600 1 MDT} {1793520000 -25200 0 MST} {1805014800 -21600 1 MDT} {1825574400 -25200 0 MST} {1836464400 -21600 1 MDT} {1857024000 -25200 0 MST} {1867914000 -21600 1 MDT} {1888473600 -25200 0 MST} {1899363600 -21600 1 MDT} {1919923200 -25200 0 MST} {1930813200 -21600 1 MDT} {1951372800 -25200 0 MST} {1962867600 -21600 1 MDT} {1983427200 -25200 0 MST} {1994317200 -21600 1 MDT} {2014876800 -25200 0 MST} {2025766800 -21600 1 MDT} {2046326400 -25200 0 MST} {2057216400 -21600 1 MDT} {2077776000 -25200 0 MST} {2088666000 -21600 1 MDT} {2109225600 -25200 0 MST} {2120115600 -21600 1 MDT} {2140675200 -25200 0 MST} {2152170000 -21600 1 MDT} {2172729600 -25200 0 MST} {2183619600 -21600 1 MDT} {2204179200 -25200 0 MST} {2215069200 -21600 1 MDT} {2235628800 -25200 0 MST} {2246518800 -21600 1 MDT} {2267078400 -25200 0 MST} {2277968400 -21600 1 MDT} {2298528000 -25200 0 MST} {2309418000 -21600 1 MDT} {2329977600 -25200 0 MST} {2341472400 -21600 1 MDT} {2362032000 -25200 0 MST} {2372922000 -21600 1 MDT} {2393481600 -25200 0 MST} {2404371600 -21600 1 MDT} {2424931200 -25200 0 MST} {2435821200 -21600 1 MDT} {2456380800 -25200 0 MST} {2467270800 -21600 1 MDT} {2487830400 -25200 0 MST} {2499325200 -21600 1 MDT} {2519884800 -25200 0 MST} {2530774800 -21600 1 MDT} {2551334400 -25200 0 MST} {2562224400 -21600 1 MDT} {2582784000 -25200 0 MST} {2593674000 -21600 1 MDT} {2614233600 -25200 0 MST} {2625123600 -21600 1 MDT} {2645683200 -25200 0 MST} {2656573200 -21600 1 MDT} {2677132800 -25200 0 MST} {2688627600 -21600 1 MDT} {2709187200 -25200 0 MST} {2720077200 -21600 1 MDT} {2740636800 -25200 0 MST} {2751526800 -21600 1 MDT} {2772086400 -25200 0 MST} {2782976400 -21600 1 MDT} {2803536000 -25200 0 MST} {2814426000 -21600 1 MDT} {2834985600 -25200 0 MST} {2846480400 -21600 1 MDT} {2867040000 -25200 0 MST} {2877930000 -21600 1 MDT} {2898489600 -25200 0 MST} {2909379600 -21600 1 MDT} {2929939200 -25200 0 MST} {2940829200 -21600 1 MDT} {2961388800 -25200 0 MST} {2972278800 -21600 1 MDT} {2992838400 -25200 0 MST} {3003728400 -21600 1 MDT} {3024288000 -25200 0 MST} {3035782800 -21600 1 MDT} {3056342400 -25200 0 MST} {3067232400 -21600 1 MDT} {3087792000 -25200 0 MST} {3098682000 -21600 1 MDT} {3119241600 -25200 0 MST} {3130131600 -21600 1 MDT} {3150691200 -25200 0 MST} {3161581200 -21600 1 MDT} {3182140800 -25200 0 MST} {3193030800 -21600 1 MDT} {3213590400 -25200 0 MST} {3225085200 -21600 1 MDT} {3245644800 -25200 0 MST} {3256534800 -21600 1 MDT} {3277094400 -25200 0 MST} {3287984400 -21600 1 MDT} {3308544000 -25200 0 MST} {3319434000 -21600 1 MDT} {3339993600 -25200 0 MST} {3350883600 -21600 1 MDT} {3371443200 -25200 0 MST} {3382938000 -21600 1 MDT} {3403497600 -25200 0 MST} {3414387600 -21600 1 MDT} {3434947200 -25200 0 MST} {3445837200 -21600 1 MDT} {3466396800 -25200 0 MST} {3477286800 -21600 1 MDT} {3497846400 -25200 0 MST} {3508736400 -21600 1 MDT} {3529296000 -25200 0 MST} {3540186000 -21600 1 MDT} {3560745600 -25200 0 MST} {3572240400 -21600 1 MDT} {3592800000 -25200 0 MST} {3603690000 -21600 1 MDT} {3624249600 -25200 0 MST} {3635139600 -21600 1 MDT} {3655699200 -25200 0 MST} {3666589200 -21600 1 MDT} {3687148800 -25200 0 MST} {3698038800 -21600 1 MDT} {3718598400 -25200 0 MST} {3730093200 -21600 1 MDT} {3750652800 -25200 0 MST} {3761542800 -21600 1 MDT} {3782102400 -25200 0 MST} {3792992400 -21600 1 MDT} {3813552000 -25200 0 MST} {3824442000 -21600 1 MDT} {3845001600 -25200 0 MST} {3855891600 -21600 1 MDT} {3876451200 -25200 0 MST} {3887341200 -21600 1 MDT} {3907900800 -25200 0 MST} {3919395600 -21600 1 MDT} {3939955200 -25200 0 MST} {3950845200 -21600 1 MDT} {3971404800 -25200 0 MST} {3982294800 -21600 1 MDT} {4002854400 -25200 0 MST} {4013744400 -21600 1 MDT} {4034304000 -25200 0 MST} {4045194000 -21600 1 MDT} {4065753600 -25200 0 MST} {4076643600 -21600 1 MDT} {4097203200 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Araguaina0000644000175000017500000000332312663660066017700 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Araguaina) { {-9223372036854775808 -11568 0 LMT} {-1767214032 -10800 0 BRT} {-1206957600 -7200 1 BRST} {-1191362400 -10800 0 BRT} {-1175374800 -7200 1 BRST} {-1159826400 -10800 0 BRT} {-633819600 -7200 1 BRST} {-622069200 -10800 0 BRT} {-602283600 -7200 1 BRST} {-591832800 -10800 0 BRT} {-570747600 -7200 1 BRST} {-560210400 -10800 0 BRT} {-539125200 -7200 1 BRST} {-531352800 -10800 0 BRT} {-191365200 -7200 1 BRST} {-184197600 -10800 0 BRT} {-155163600 -7200 1 BRST} {-150069600 -10800 0 BRT} {-128898000 -7200 1 BRST} {-121125600 -10800 0 BRT} {-99954000 -7200 1 BRST} {-89589600 -10800 0 BRT} {-68418000 -7200 1 BRST} {-57967200 -10800 0 BRT} {499748400 -7200 1 BRST} {511236000 -10800 0 BRT} {530593200 -7200 1 BRST} {540266400 -10800 0 BRT} {562129200 -7200 1 BRST} {571197600 -10800 0 BRT} {592974000 -7200 1 BRST} {602042400 -10800 0 BRT} {624423600 -7200 1 BRST} {634701600 -10800 0 BRT} {653536800 -10800 0 BRT} {811047600 -10800 0 BRT} {813726000 -7200 1 BRST} {824004000 -10800 0 BRT} {844570800 -7200 1 BRST} {856058400 -10800 0 BRT} {876106800 -7200 1 BRST} {888717600 -10800 0 BRT} {908074800 -7200 1 BRST} {919562400 -10800 0 BRT} {938919600 -7200 1 BRST} {951616800 -10800 0 BRT} {970974000 -7200 1 BRST} {982461600 -10800 0 BRT} {1003028400 -7200 1 BRST} {1013911200 -10800 0 BRT} {1036292400 -7200 1 BRST} {1045360800 -10800 0 BRT} {1064368800 -10800 0 BRT} {1350788400 -7200 0 BRST} {1361066400 -10800 0 BRT} {1378000800 -10800 0 BRT} } tcl8.6.5/library/tzdata/America/Ensenada0000644000175000017500000000027112661614722017521 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Tijuana)]} { LoadTimeZoneFile America/Tijuana } set TZData(:America/Ensenada) $TZData(:America/Tijuana) tcl8.6.5/library/tzdata/America/Phoenix0000644000175000017500000000073712661614721017423 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Phoenix) { {-9223372036854775808 -26898 0 LMT} {-2717643600 -25200 0 MST} {-1633273200 -21600 1 MDT} {-1615132800 -25200 0 MST} {-1601823600 -21600 1 MDT} {-1583683200 -25200 0 MST} {-880210800 -21600 1 MWT} {-820519140 -25200 0 MST} {-796841940 -25200 0 MST} {-94669200 -25200 0 MST} {-84380400 -21600 1 MDT} {-68659200 -25200 0 MST} {-56221200 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Bahia_Banderas0000644000175000017500000001474112663653207020620 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Bahia_Banderas) { {-9223372036854775808 -25260 0 LMT} {-1514739600 -25200 0 MST} {-1343066400 -21600 0 CST} {-1234807200 -25200 0 MST} {-1220292000 -21600 0 CST} {-1207159200 -25200 0 MST} {-1191344400 -21600 0 CST} {-873828000 -25200 0 MST} {-661539600 -28800 0 PST} {28800 -25200 0 MST} {828867600 -21600 1 MDT} {846403200 -25200 0 MST} {860317200 -21600 1 MDT} {877852800 -25200 0 MST} {891766800 -21600 1 MDT} {909302400 -25200 0 MST} {923216400 -21600 1 MDT} {941356800 -25200 0 MST} {954666000 -21600 1 MDT} {972806400 -25200 0 MST} {989139600 -21600 1 MDT} {1001836800 -25200 0 MST} {1018170000 -21600 1 MDT} {1035705600 -25200 0 MST} {1049619600 -21600 1 MDT} {1067155200 -25200 0 MST} {1081069200 -21600 1 MDT} {1099209600 -25200 0 MST} {1112518800 -21600 1 MDT} {1130659200 -25200 0 MST} {1143968400 -21600 1 MDT} {1162108800 -25200 0 MST} {1175418000 -21600 1 MDT} {1193558400 -25200 0 MST} {1207472400 -21600 1 MDT} {1225008000 -25200 0 MST} {1238922000 -21600 1 MDT} {1256457600 -25200 0 MST} {1270371600 -18000 0 CDT} {1288508400 -21600 0 CST} {1301817600 -18000 1 CDT} {1319958000 -21600 0 CST} {1333267200 -18000 1 CDT} {1351407600 -21600 0 CST} {1365321600 -18000 1 CDT} {1382857200 -21600 0 CST} {1396771200 -18000 1 CDT} {1414306800 -21600 0 CST} {1428220800 -18000 1 CDT} {1445756400 -21600 0 CST} {1459670400 -18000 1 CDT} {1477810800 -21600 0 CST} {1491120000 -18000 1 CDT} {1509260400 -21600 0 CST} {1522569600 -18000 1 CDT} {1540710000 -21600 0 CST} {1554624000 -18000 1 CDT} {1572159600 -21600 0 CST} {1586073600 -18000 1 CDT} {1603609200 -21600 0 CST} {1617523200 -18000 1 CDT} {1635663600 -21600 0 CST} {1648972800 -18000 1 CDT} {1667113200 -21600 0 CST} {1680422400 -18000 1 CDT} {1698562800 -21600 0 CST} {1712476800 -18000 1 CDT} {1730012400 -21600 0 CST} {1743926400 -18000 1 CDT} {1761462000 -21600 0 CST} {1775376000 -18000 1 CDT} {1792911600 -21600 0 CST} {1806825600 -18000 1 CDT} {1824966000 -21600 0 CST} {1838275200 -18000 1 CDT} {1856415600 -21600 0 CST} {1869724800 -18000 1 CDT} {1887865200 -21600 0 CST} {1901779200 -18000 1 CDT} {1919314800 -21600 0 CST} {1933228800 -18000 1 CDT} {1950764400 -21600 0 CST} {1964678400 -18000 1 CDT} {1982818800 -21600 0 CST} {1996128000 -18000 1 CDT} {2014268400 -21600 0 CST} {2027577600 -18000 1 CDT} {2045718000 -21600 0 CST} {2059027200 -18000 1 CDT} {2077167600 -21600 0 CST} {2091081600 -18000 1 CDT} {2108617200 -21600 0 CST} {2122531200 -18000 1 CDT} {2140066800 -21600 0 CST} {2153980800 -18000 1 CDT} {2172121200 -21600 0 CST} {2185430400 -18000 1 CDT} {2203570800 -21600 0 CST} {2216880000 -18000 1 CDT} {2235020400 -21600 0 CST} {2248934400 -18000 1 CDT} {2266470000 -21600 0 CST} {2280384000 -18000 1 CDT} {2297919600 -21600 0 CST} {2311833600 -18000 1 CDT} {2329369200 -21600 0 CST} {2343283200 -18000 1 CDT} {2361423600 -21600 0 CST} {2374732800 -18000 1 CDT} {2392873200 -21600 0 CST} {2406182400 -18000 1 CDT} {2424322800 -21600 0 CST} {2438236800 -18000 1 CDT} {2455772400 -21600 0 CST} {2469686400 -18000 1 CDT} {2487222000 -21600 0 CST} {2501136000 -18000 1 CDT} {2519276400 -21600 0 CST} {2532585600 -18000 1 CDT} {2550726000 -21600 0 CST} {2564035200 -18000 1 CDT} {2582175600 -21600 0 CST} {2596089600 -18000 1 CDT} {2613625200 -21600 0 CST} {2627539200 -18000 1 CDT} {2645074800 -21600 0 CST} {2658988800 -18000 1 CDT} {2676524400 -21600 0 CST} {2690438400 -18000 1 CDT} {2708578800 -21600 0 CST} {2721888000 -18000 1 CDT} {2740028400 -21600 0 CST} {2753337600 -18000 1 CDT} {2771478000 -21600 0 CST} {2785392000 -18000 1 CDT} {2802927600 -21600 0 CST} {2816841600 -18000 1 CDT} {2834377200 -21600 0 CST} {2848291200 -18000 1 CDT} {2866431600 -21600 0 CST} {2879740800 -18000 1 CDT} {2897881200 -21600 0 CST} {2911190400 -18000 1 CDT} {2929330800 -21600 0 CST} {2942640000 -18000 1 CDT} {2960780400 -21600 0 CST} {2974694400 -18000 1 CDT} {2992230000 -21600 0 CST} {3006144000 -18000 1 CDT} {3023679600 -21600 0 CST} {3037593600 -18000 1 CDT} {3055734000 -21600 0 CST} {3069043200 -18000 1 CDT} {3087183600 -21600 0 CST} {3100492800 -18000 1 CDT} {3118633200 -21600 0 CST} {3132547200 -18000 1 CDT} {3150082800 -21600 0 CST} {3163996800 -18000 1 CDT} {3181532400 -21600 0 CST} {3195446400 -18000 1 CDT} {3212982000 -21600 0 CST} {3226896000 -18000 1 CDT} {3245036400 -21600 0 CST} {3258345600 -18000 1 CDT} {3276486000 -21600 0 CST} {3289795200 -18000 1 CDT} {3307935600 -21600 0 CST} {3321849600 -18000 1 CDT} {3339385200 -21600 0 CST} {3353299200 -18000 1 CDT} {3370834800 -21600 0 CST} {3384748800 -18000 1 CDT} {3402889200 -21600 0 CST} {3416198400 -18000 1 CDT} {3434338800 -21600 0 CST} {3447648000 -18000 1 CDT} {3465788400 -21600 0 CST} {3479702400 -18000 1 CDT} {3497238000 -21600 0 CST} {3511152000 -18000 1 CDT} {3528687600 -21600 0 CST} {3542601600 -18000 1 CDT} {3560137200 -21600 0 CST} {3574051200 -18000 1 CDT} {3592191600 -21600 0 CST} {3605500800 -18000 1 CDT} {3623641200 -21600 0 CST} {3636950400 -18000 1 CDT} {3655090800 -21600 0 CST} {3669004800 -18000 1 CDT} {3686540400 -21600 0 CST} {3700454400 -18000 1 CDT} {3717990000 -21600 0 CST} {3731904000 -18000 1 CDT} {3750044400 -21600 0 CST} {3763353600 -18000 1 CDT} {3781494000 -21600 0 CST} {3794803200 -18000 1 CDT} {3812943600 -21600 0 CST} {3826252800 -18000 1 CDT} {3844393200 -21600 0 CST} {3858307200 -18000 1 CDT} {3875842800 -21600 0 CST} {3889756800 -18000 1 CDT} {3907292400 -21600 0 CST} {3921206400 -18000 1 CDT} {3939346800 -21600 0 CST} {3952656000 -18000 1 CDT} {3970796400 -21600 0 CST} {3984105600 -18000 1 CDT} {4002246000 -21600 0 CST} {4016160000 -18000 1 CDT} {4033695600 -21600 0 CST} {4047609600 -18000 1 CDT} {4065145200 -21600 0 CST} {4079059200 -18000 1 CDT} {4096594800 -21600 0 CST} } tcl8.6.5/library/tzdata/America/Pangnirtung0000644000175000017500000001647412661614721020312 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Pangnirtung) { {-9223372036854775808 0 0 zzz} {-1546300800 -14400 0 AST} {-880221600 -10800 1 AWT} {-769395600 -10800 1 APT} {-765399600 -14400 0 AST} {-147902400 -7200 1 ADDT} {-131572800 -14400 0 AST} {325663200 -10800 1 ADT} {341384400 -14400 0 AST} {357112800 -10800 1 ADT} {372834000 -14400 0 AST} {388562400 -10800 1 ADT} {404888400 -14400 0 AST} {420012000 -10800 1 ADT} {436338000 -14400 0 AST} {452066400 -10800 1 ADT} {467787600 -14400 0 AST} {483516000 -10800 1 ADT} {499237200 -14400 0 AST} {514965600 -10800 1 ADT} {530686800 -14400 0 AST} {544600800 -10800 1 ADT} {562136400 -14400 0 AST} {576050400 -10800 1 ADT} {594190800 -14400 0 AST} {607500000 -10800 1 ADT} {625640400 -14400 0 AST} {638949600 -10800 1 ADT} {657090000 -14400 0 AST} {671004000 -10800 1 ADT} {688539600 -14400 0 AST} {702453600 -10800 1 ADT} {719989200 -14400 0 AST} {733903200 -10800 1 ADT} {752043600 -14400 0 AST} {765352800 -10800 1 ADT} {783493200 -14400 0 AST} {796802400 -18000 0 EST} {796806000 -14400 1 EDT} {814946400 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {909295200 -18000 0 EST} {923209200 -14400 1 EDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972806400 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/America/Campo_Grande0000644000175000017500000001714212663653132020327 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Campo_Grande) { {-9223372036854775808 -13108 0 LMT} {-1767212492 -14400 0 AMT} {-1206954000 -10800 1 AMST} {-1191358800 -14400 0 AMT} {-1175371200 -10800 1 AMST} {-1159822800 -14400 0 AMT} {-633816000 -10800 1 AMST} {-622065600 -14400 0 AMT} {-602280000 -10800 1 AMST} {-591829200 -14400 0 AMT} {-570744000 -10800 1 AMST} {-560206800 -14400 0 AMT} {-539121600 -10800 1 AMST} {-531349200 -14400 0 AMT} {-191361600 -10800 1 AMST} {-184194000 -14400 0 AMT} {-155160000 -10800 1 AMST} {-150066000 -14400 0 AMT} {-128894400 -10800 1 AMST} {-121122000 -14400 0 AMT} {-99950400 -10800 1 AMST} {-89586000 -14400 0 AMT} {-68414400 -10800 1 AMST} {-57963600 -14400 0 AMT} {499752000 -10800 1 AMST} {511239600 -14400 0 AMT} {530596800 -10800 1 AMST} {540270000 -14400 0 AMT} {562132800 -10800 1 AMST} {571201200 -14400 0 AMT} {592977600 -10800 1 AMST} {602046000 -14400 0 AMT} {624427200 -10800 1 AMST} {634705200 -14400 0 AMT} {656481600 -10800 1 AMST} {666759600 -14400 0 AMT} {687931200 -10800 1 AMST} {697604400 -14400 0 AMT} {719985600 -10800 1 AMST} {728449200 -14400 0 AMT} {750830400 -10800 1 AMST} {761713200 -14400 0 AMT} {782280000 -10800 1 AMST} {793162800 -14400 0 AMT} {813729600 -10800 1 AMST} {824007600 -14400 0 AMT} {844574400 -10800 1 AMST} {856062000 -14400 0 AMT} {876110400 -10800 1 AMST} {888721200 -14400 0 AMT} {908078400 -10800 1 AMST} {919566000 -14400 0 AMT} {938923200 -10800 1 AMST} {951620400 -14400 0 AMT} {970977600 -10800 1 AMST} {982465200 -14400 0 AMT} {1003032000 -10800 1 AMST} {1013914800 -14400 0 AMT} {1036296000 -10800 1 AMST} {1045364400 -14400 0 AMT} {1066536000 -10800 1 AMST} {1076814000 -14400 0 AMT} {1099368000 -10800 1 AMST} {1108868400 -14400 0 AMT} {1129435200 -10800 1 AMST} {1140318000 -14400 0 AMT} {1162699200 -10800 1 AMST} {1172372400 -14400 0 AMT} {1192334400 -10800 1 AMST} {1203217200 -14400 0 AMT} {1224388800 -10800 1 AMST} {1234666800 -14400 0 AMT} {1255838400 -10800 1 AMST} {1266721200 -14400 0 AMT} {1287288000 -10800 1 AMST} {1298170800 -14400 0 AMT} {1318737600 -10800 1 AMST} {1330225200 -14400 0 AMT} {1350792000 -10800 1 AMST} {1361070000 -14400 0 AMT} {1382241600 -10800 1 AMST} {1392519600 -14400 0 AMT} {1413691200 -10800 1 AMST} {1424574000 -14400 0 AMT} {1445140800 -10800 1 AMST} {1456023600 -14400 0 AMT} {1476590400 -10800 1 AMST} {1487473200 -14400 0 AMT} {1508040000 -10800 1 AMST} {1518922800 -14400 0 AMT} {1540094400 -10800 1 AMST} {1550372400 -14400 0 AMT} {1571544000 -10800 1 AMST} {1581822000 -14400 0 AMT} {1602993600 -10800 1 AMST} {1613876400 -14400 0 AMT} {1634443200 -10800 1 AMST} {1645326000 -14400 0 AMT} {1665892800 -10800 1 AMST} {1677380400 -14400 0 AMT} {1697342400 -10800 1 AMST} {1708225200 -14400 0 AMT} {1729396800 -10800 1 AMST} {1739674800 -14400 0 AMT} {1760846400 -10800 1 AMST} {1771729200 -14400 0 AMT} {1792296000 -10800 1 AMST} {1803178800 -14400 0 AMT} {1823745600 -10800 1 AMST} {1834628400 -14400 0 AMT} {1855195200 -10800 1 AMST} {1866078000 -14400 0 AMT} {1887249600 -10800 1 AMST} {1897527600 -14400 0 AMT} {1918699200 -10800 1 AMST} {1928977200 -14400 0 AMT} {1950148800 -10800 1 AMST} {1960426800 -14400 0 AMT} {1981598400 -10800 1 AMST} {1992481200 -14400 0 AMT} {2013048000 -10800 1 AMST} {2024535600 -14400 0 AMT} {2044497600 -10800 1 AMST} {2055380400 -14400 0 AMT} {2076552000 -10800 1 AMST} {2086830000 -14400 0 AMT} {2108001600 -10800 1 AMST} {2118884400 -14400 0 AMT} {2139451200 -10800 1 AMST} {2150334000 -14400 0 AMT} {2170900800 -10800 1 AMST} {2181783600 -14400 0 AMT} {2202350400 -10800 1 AMST} {2213233200 -14400 0 AMT} {2234404800 -10800 1 AMST} {2244682800 -14400 0 AMT} {2265854400 -10800 1 AMST} {2276132400 -14400 0 AMT} {2297304000 -10800 1 AMST} {2307582000 -14400 0 AMT} {2328753600 -10800 1 AMST} {2339636400 -14400 0 AMT} {2360203200 -10800 1 AMST} {2371086000 -14400 0 AMT} {2391652800 -10800 1 AMST} {2402535600 -14400 0 AMT} {2423707200 -10800 1 AMST} {2433985200 -14400 0 AMT} {2455156800 -10800 1 AMST} {2465434800 -14400 0 AMT} {2486606400 -10800 1 AMST} {2497489200 -14400 0 AMT} {2518056000 -10800 1 AMST} {2528938800 -14400 0 AMT} {2549505600 -10800 1 AMST} {2560388400 -14400 0 AMT} {2580955200 -10800 1 AMST} {2591838000 -14400 0 AMT} {2613009600 -10800 1 AMST} {2623287600 -14400 0 AMT} {2644459200 -10800 1 AMST} {2654737200 -14400 0 AMT} {2675908800 -10800 1 AMST} {2686791600 -14400 0 AMT} {2707358400 -10800 1 AMST} {2718241200 -14400 0 AMT} {2738808000 -10800 1 AMST} {2749690800 -14400 0 AMT} {2770862400 -10800 1 AMST} {2781140400 -14400 0 AMT} {2802312000 -10800 1 AMST} {2812590000 -14400 0 AMT} {2833761600 -10800 1 AMST} {2844039600 -14400 0 AMT} {2865211200 -10800 1 AMST} {2876094000 -14400 0 AMT} {2896660800 -10800 1 AMST} {2907543600 -14400 0 AMT} {2928110400 -10800 1 AMST} {2938993200 -14400 0 AMT} {2960164800 -10800 1 AMST} {2970442800 -14400 0 AMT} {2991614400 -10800 1 AMST} {3001892400 -14400 0 AMT} {3023064000 -10800 1 AMST} {3033946800 -14400 0 AMT} {3054513600 -10800 1 AMST} {3065396400 -14400 0 AMT} {3085963200 -10800 1 AMST} {3096846000 -14400 0 AMT} {3118017600 -10800 1 AMST} {3128295600 -14400 0 AMT} {3149467200 -10800 1 AMST} {3159745200 -14400 0 AMT} {3180916800 -10800 1 AMST} {3191194800 -14400 0 AMT} {3212366400 -10800 1 AMST} {3223249200 -14400 0 AMT} {3243816000 -10800 1 AMST} {3254698800 -14400 0 AMT} {3275265600 -10800 1 AMST} {3286148400 -14400 0 AMT} {3307320000 -10800 1 AMST} {3317598000 -14400 0 AMT} {3338769600 -10800 1 AMST} {3349047600 -14400 0 AMT} {3370219200 -10800 1 AMST} {3381102000 -14400 0 AMT} {3401668800 -10800 1 AMST} {3412551600 -14400 0 AMT} {3433118400 -10800 1 AMST} {3444001200 -14400 0 AMT} {3464568000 -10800 1 AMST} {3475450800 -14400 0 AMT} {3496622400 -10800 1 AMST} {3506900400 -14400 0 AMT} {3528072000 -10800 1 AMST} {3538350000 -14400 0 AMT} {3559521600 -10800 1 AMST} {3570404400 -14400 0 AMT} {3590971200 -10800 1 AMST} {3601854000 -14400 0 AMT} {3622420800 -10800 1 AMST} {3633303600 -14400 0 AMT} {3654475200 -10800 1 AMST} {3664753200 -14400 0 AMT} {3685924800 -10800 1 AMST} {3696202800 -14400 0 AMT} {3717374400 -10800 1 AMST} {3727652400 -14400 0 AMT} {3748824000 -10800 1 AMST} {3759706800 -14400 0 AMT} {3780273600 -10800 1 AMST} {3791156400 -14400 0 AMT} {3811723200 -10800 1 AMST} {3822606000 -14400 0 AMT} {3843777600 -10800 1 AMST} {3854055600 -14400 0 AMT} {3875227200 -10800 1 AMST} {3885505200 -14400 0 AMT} {3906676800 -10800 1 AMST} {3917559600 -14400 0 AMT} {3938126400 -10800 1 AMST} {3949009200 -14400 0 AMT} {3969576000 -10800 1 AMST} {3980458800 -14400 0 AMT} {4001630400 -10800 1 AMST} {4011908400 -14400 0 AMT} {4033080000 -10800 1 AMST} {4043358000 -14400 0 AMT} {4064529600 -10800 1 AMST} {4074807600 -14400 0 AMT} {4095979200 -10800 1 AMST} } tcl8.6.5/library/tzdata/America/Marigot0000644000175000017500000000031212663660066017405 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/Marigot) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Fort_Nelson0000644000175000017500000001051312663660066020237 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Fort_Nelson) { {-9223372036854775808 -29447 0 LMT} {-2713880953 -28800 0 PST} {-1632060000 -25200 1 PDT} {-1615129200 -28800 0 PST} {-880207200 -25200 1 PWT} {-769395600 -25200 1 PPT} {-765385200 -28800 0 PST} {-757353600 -28800 0 PST} {-725817600 -28800 0 PST} {-715788000 -25200 1 PDT} {-702486000 -28800 0 PST} {-684338400 -25200 1 PDT} {-671036400 -28800 0 PST} {-652888800 -25200 1 PDT} {-639586800 -28800 0 PST} {-620834400 -25200 1 PDT} {-608137200 -28800 0 PST} {-589384800 -25200 1 PDT} {-576082800 -28800 0 PST} {-557935200 -25200 1 PDT} {-544633200 -28800 0 PST} {-526485600 -25200 1 PDT} {-513183600 -28800 0 PST} {-495036000 -25200 1 PDT} {-481734000 -28800 0 PST} {-463586400 -25200 1 PDT} {-450284400 -28800 0 PST} {-431532000 -25200 1 PDT} {-418230000 -28800 0 PST} {-400082400 -25200 1 PDT} {-386780400 -28800 0 PST} {-368632800 -25200 1 PDT} {-355330800 -28800 0 PST} {-337183200 -25200 1 PDT} {-323881200 -28800 0 PST} {-305733600 -25200 1 PDT} {-292431600 -28800 0 PST} {-273679200 -25200 1 PDT} {-260982000 -28800 0 PST} {-242229600 -25200 1 PDT} {-226508400 -28800 0 PST} {-210780000 -25200 1 PDT} {-195058800 -28800 0 PST} {-179330400 -25200 1 PDT} {-163609200 -28800 0 PST} {-147880800 -25200 1 PDT} {-131554800 -28800 0 PST} {-116431200 -25200 1 PDT} {-100105200 -28800 0 PST} {-84376800 -25200 1 PDT} {-68655600 -28800 0 PST} {-52927200 -25200 1 PDT} {-37206000 -28800 0 PST} {-21477600 -25200 1 PDT} {-5756400 -28800 0 PST} {9972000 -25200 1 PDT} {25693200 -28800 0 PST} {41421600 -25200 1 PDT} {57747600 -28800 0 PST} {73476000 -25200 1 PDT} {89197200 -28800 0 PST} {104925600 -25200 1 PDT} {120646800 -28800 0 PST} {136375200 -25200 1 PDT} {152096400 -28800 0 PST} {167824800 -25200 1 PDT} {183546000 -28800 0 PST} {199274400 -25200 1 PDT} {215600400 -28800 0 PST} {230724000 -25200 1 PDT} {247050000 -28800 0 PST} {262778400 -25200 1 PDT} {278499600 -28800 0 PST} {294228000 -25200 1 PDT} {309949200 -28800 0 PST} {325677600 -25200 1 PDT} {341398800 -28800 0 PST} {357127200 -25200 1 PDT} {372848400 -28800 0 PST} {388576800 -25200 1 PDT} {404902800 -28800 0 PST} {420026400 -25200 1 PDT} {436352400 -28800 0 PST} {452080800 -25200 1 PDT} {467802000 -28800 0 PST} {483530400 -25200 1 PDT} {499251600 -28800 0 PST} {514980000 -25200 1 PDT} {530701200 -28800 0 PST} {536486400 -28800 0 PST} {544615200 -25200 1 PDT} {562150800 -28800 0 PST} {576064800 -25200 1 PDT} {594205200 -28800 0 PST} {607514400 -25200 1 PDT} {625654800 -28800 0 PST} {638964000 -25200 1 PDT} {657104400 -28800 0 PST} {671018400 -25200 1 PDT} {688554000 -28800 0 PST} {702468000 -25200 1 PDT} {720003600 -28800 0 PST} {733917600 -25200 1 PDT} {752058000 -28800 0 PST} {765367200 -25200 1 PDT} {783507600 -28800 0 PST} {796816800 -25200 1 PDT} {814957200 -28800 0 PST} {828871200 -25200 1 PDT} {846406800 -28800 0 PST} {860320800 -25200 1 PDT} {877856400 -28800 0 PST} {891770400 -25200 1 PDT} {909306000 -28800 0 PST} {923220000 -25200 1 PDT} {941360400 -28800 0 PST} {954669600 -25200 1 PDT} {972810000 -28800 0 PST} {986119200 -25200 1 PDT} {1004259600 -28800 0 PST} {1018173600 -25200 1 PDT} {1035709200 -28800 0 PST} {1049623200 -25200 1 PDT} {1067158800 -28800 0 PST} {1081072800 -25200 1 PDT} {1099213200 -28800 0 PST} {1112522400 -25200 1 PDT} {1130662800 -28800 0 PST} {1143972000 -25200 1 PDT} {1162112400 -28800 0 PST} {1173607200 -25200 1 PDT} {1194166800 -28800 0 PST} {1205056800 -25200 1 PDT} {1225616400 -28800 0 PST} {1236506400 -25200 1 PDT} {1257066000 -28800 0 PST} {1268560800 -25200 1 PDT} {1289120400 -28800 0 PST} {1300010400 -25200 1 PDT} {1320570000 -28800 0 PST} {1331460000 -25200 1 PDT} {1352019600 -28800 0 PST} {1362909600 -25200 1 PDT} {1383469200 -28800 0 PST} {1394359200 -25200 1 PDT} {1414918800 -28800 0 PST} {1425808800 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Recife0000644000175000017500000000255712661614721017210 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Recife) { {-9223372036854775808 -8376 0 LMT} {-1767217224 -10800 0 BRT} {-1206957600 -7200 1 BRST} {-1191362400 -10800 0 BRT} {-1175374800 -7200 1 BRST} {-1159826400 -10800 0 BRT} {-633819600 -7200 1 BRST} {-622069200 -10800 0 BRT} {-602283600 -7200 1 BRST} {-591832800 -10800 0 BRT} {-570747600 -7200 1 BRST} {-560210400 -10800 0 BRT} {-539125200 -7200 1 BRST} {-531352800 -10800 0 BRT} {-191365200 -7200 1 BRST} {-184197600 -10800 0 BRT} {-155163600 -7200 1 BRST} {-150069600 -10800 0 BRT} {-128898000 -7200 1 BRST} {-121125600 -10800 0 BRT} {-99954000 -7200 1 BRST} {-89589600 -10800 0 BRT} {-68418000 -7200 1 BRST} {-57967200 -10800 0 BRT} {499748400 -7200 1 BRST} {511236000 -10800 0 BRT} {530593200 -7200 1 BRST} {540266400 -10800 0 BRT} {562129200 -7200 1 BRST} {571197600 -10800 0 BRT} {592974000 -7200 1 BRST} {602042400 -10800 0 BRT} {624423600 -7200 1 BRST} {634701600 -10800 0 BRT} {653536800 -10800 0 BRT} {938660400 -10800 0 BRT} {938919600 -7200 1 BRST} {951616800 -10800 0 BRT} {970974000 -7200 1 BRST} {971575200 -10800 0 BRT} {1000350000 -10800 0 BRT} {1003028400 -7200 1 BRST} {1013911200 -10800 0 BRT} {1033437600 -10800 0 BRT} } tcl8.6.5/library/tzdata/America/Moncton0000644000175000017500000002366512663660066017440 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Moncton) { {-9223372036854775808 -15548 0 LMT} {-2715882052 -18000 0 EST} {-2131642800 -14400 0 AST} {-1632074400 -10800 1 ADT} {-1615143600 -14400 0 AST} {-1167595200 -14400 0 AST} {-1153681200 -10800 1 ADT} {-1145822400 -14400 0 AST} {-1122231600 -10800 1 ADT} {-1114372800 -14400 0 AST} {-1090782000 -10800 1 ADT} {-1082923200 -14400 0 AST} {-1059332400 -10800 1 ADT} {-1051473600 -14400 0 AST} {-1027882800 -10800 1 ADT} {-1020024000 -14400 0 AST} {-996433200 -10800 1 ADT} {-988574400 -14400 0 AST} {-965674800 -10800 1 ADT} {-955396800 -14400 0 AST} {-934743600 -10800 1 ADT} {-923947200 -14400 0 AST} {-904503600 -10800 1 ADT} {-891892800 -14400 0 AST} {-883598400 -14400 0 AST} {-880221600 -10800 1 AWT} {-769395600 -10800 1 APT} {-765399600 -14400 0 AST} {-757368000 -14400 0 AST} {-747252000 -10800 1 ADT} {-733950000 -14400 0 AST} {-715802400 -10800 1 ADT} {-702500400 -14400 0 AST} {-684352800 -10800 1 ADT} {-671050800 -14400 0 AST} {-652903200 -10800 1 ADT} {-639601200 -14400 0 AST} {-620848800 -10800 1 ADT} {-608151600 -14400 0 AST} {-589399200 -10800 1 ADT} {-576097200 -14400 0 AST} {-557949600 -10800 1 ADT} {-544647600 -14400 0 AST} {-526500000 -10800 1 ADT} {-513198000 -14400 0 AST} {-495050400 -10800 1 ADT} {-481748400 -14400 0 AST} {-463600800 -10800 1 ADT} {-450298800 -14400 0 AST} {-431546400 -10800 1 ADT} {-418244400 -14400 0 AST} {-400096800 -10800 1 ADT} {-384375600 -14400 0 AST} {-368647200 -10800 1 ADT} {-352926000 -14400 0 AST} {-337197600 -10800 1 ADT} {-321476400 -14400 0 AST} {-305748000 -10800 1 ADT} {-289422000 -14400 0 AST} {-273693600 -10800 1 ADT} {-257972400 -14400 0 AST} {-242244000 -10800 1 ADT} {-226522800 -14400 0 AST} {-210794400 -10800 1 ADT} {-195073200 -14400 0 AST} {-179344800 -10800 1 ADT} {-163623600 -14400 0 AST} {-147895200 -10800 1 ADT} {-131569200 -14400 0 AST} {-116445600 -10800 1 ADT} {-100119600 -14400 0 AST} {-84391200 -10800 1 ADT} {-68670000 -14400 0 AST} {-52941600 -10800 1 ADT} {-37220400 -14400 0 AST} {-21492000 -10800 1 ADT} {-5770800 -14400 0 AST} {9957600 -10800 1 ADT} {25678800 -14400 0 AST} {41407200 -10800 1 ADT} {57733200 -14400 0 AST} {73461600 -10800 1 ADT} {89182800 -14400 0 AST} {94708800 -14400 0 AST} {136360800 -10800 1 ADT} {152082000 -14400 0 AST} {167810400 -10800 1 ADT} {183531600 -14400 0 AST} {199260000 -10800 1 ADT} {215586000 -14400 0 AST} {230709600 -10800 1 ADT} {247035600 -14400 0 AST} {262764000 -10800 1 ADT} {278485200 -14400 0 AST} {294213600 -10800 1 ADT} {309934800 -14400 0 AST} {325663200 -10800 1 ADT} {341384400 -14400 0 AST} {357112800 -10800 1 ADT} {372834000 -14400 0 AST} {388562400 -10800 1 ADT} {404888400 -14400 0 AST} {420012000 -10800 1 ADT} {436338000 -14400 0 AST} {452066400 -10800 1 ADT} {467787600 -14400 0 AST} {483516000 -10800 1 ADT} {499237200 -14400 0 AST} {514965600 -10800 1 ADT} {530686800 -14400 0 AST} {544600800 -10800 1 ADT} {562136400 -14400 0 AST} {576050400 -10800 1 ADT} {594190800 -14400 0 AST} {607500000 -10800 1 ADT} {625640400 -14400 0 AST} {638949600 -10800 1 ADT} {657090000 -14400 0 AST} {671004000 -10800 1 ADT} {688539600 -14400 0 AST} {702453600 -10800 1 ADT} {719989200 -14400 0 AST} {725860800 -14400 0 AST} {733896060 -10800 1 ADT} {752036460 -14400 0 AST} {765345660 -10800 1 ADT} {783486060 -14400 0 AST} {796795260 -10800 1 ADT} {814935660 -14400 0 AST} {828849660 -10800 1 ADT} {846385260 -14400 0 AST} {860299260 -10800 1 ADT} {877834860 -14400 0 AST} {891748860 -10800 1 ADT} {909284460 -14400 0 AST} {923198460 -10800 1 ADT} {941338860 -14400 0 AST} {954648060 -10800 1 ADT} {972788460 -14400 0 AST} {986097660 -10800 1 ADT} {1004238060 -14400 0 AST} {1018152060 -10800 1 ADT} {1035687660 -14400 0 AST} {1049601660 -10800 1 ADT} {1067137260 -14400 0 AST} {1081051260 -10800 1 ADT} {1099191660 -14400 0 AST} {1112500860 -10800 1 ADT} {1130641260 -14400 0 AST} {1143950460 -10800 1 ADT} {1162090860 -14400 0 AST} {1167624000 -14400 0 AST} {1173592800 -10800 1 ADT} {1194152400 -14400 0 AST} {1205042400 -10800 1 ADT} {1225602000 -14400 0 AST} {1236492000 -10800 1 ADT} {1257051600 -14400 0 AST} {1268546400 -10800 1 ADT} {1289106000 -14400 0 AST} {1299996000 -10800 1 ADT} {1320555600 -14400 0 AST} {1331445600 -10800 1 ADT} {1352005200 -14400 0 AST} {1362895200 -10800 1 ADT} {1383454800 -14400 0 AST} {1394344800 -10800 1 ADT} {1414904400 -14400 0 AST} {1425794400 -10800 1 ADT} {1446354000 -14400 0 AST} {1457848800 -10800 1 ADT} {1478408400 -14400 0 AST} {1489298400 -10800 1 ADT} {1509858000 -14400 0 AST} {1520748000 -10800 1 ADT} {1541307600 -14400 0 AST} {1552197600 -10800 1 ADT} {1572757200 -14400 0 AST} {1583647200 -10800 1 ADT} {1604206800 -14400 0 AST} {1615701600 -10800 1 ADT} {1636261200 -14400 0 AST} {1647151200 -10800 1 ADT} {1667710800 -14400 0 AST} {1678600800 -10800 1 ADT} {1699160400 -14400 0 AST} {1710050400 -10800 1 ADT} {1730610000 -14400 0 AST} {1741500000 -10800 1 ADT} {1762059600 -14400 0 AST} {1772949600 -10800 1 ADT} {1793509200 -14400 0 AST} {1805004000 -10800 1 ADT} {1825563600 -14400 0 AST} {1836453600 -10800 1 ADT} {1857013200 -14400 0 AST} {1867903200 -10800 1 ADT} {1888462800 -14400 0 AST} {1899352800 -10800 1 ADT} {1919912400 -14400 0 AST} {1930802400 -10800 1 ADT} {1951362000 -14400 0 AST} {1962856800 -10800 1 ADT} {1983416400 -14400 0 AST} {1994306400 -10800 1 ADT} {2014866000 -14400 0 AST} {2025756000 -10800 1 ADT} {2046315600 -14400 0 AST} {2057205600 -10800 1 ADT} {2077765200 -14400 0 AST} {2088655200 -10800 1 ADT} {2109214800 -14400 0 AST} {2120104800 -10800 1 ADT} {2140664400 -14400 0 AST} {2152159200 -10800 1 ADT} {2172718800 -14400 0 AST} {2183608800 -10800 1 ADT} {2204168400 -14400 0 AST} {2215058400 -10800 1 ADT} {2235618000 -14400 0 AST} {2246508000 -10800 1 ADT} {2267067600 -14400 0 AST} {2277957600 -10800 1 ADT} {2298517200 -14400 0 AST} {2309407200 -10800 1 ADT} {2329966800 -14400 0 AST} {2341461600 -10800 1 ADT} {2362021200 -14400 0 AST} {2372911200 -10800 1 ADT} {2393470800 -14400 0 AST} {2404360800 -10800 1 ADT} {2424920400 -14400 0 AST} {2435810400 -10800 1 ADT} {2456370000 -14400 0 AST} {2467260000 -10800 1 ADT} {2487819600 -14400 0 AST} {2499314400 -10800 1 ADT} {2519874000 -14400 0 AST} {2530764000 -10800 1 ADT} {2551323600 -14400 0 AST} {2562213600 -10800 1 ADT} {2582773200 -14400 0 AST} {2593663200 -10800 1 ADT} {2614222800 -14400 0 AST} {2625112800 -10800 1 ADT} {2645672400 -14400 0 AST} {2656562400 -10800 1 ADT} {2677122000 -14400 0 AST} {2688616800 -10800 1 ADT} {2709176400 -14400 0 AST} {2720066400 -10800 1 ADT} {2740626000 -14400 0 AST} {2751516000 -10800 1 ADT} {2772075600 -14400 0 AST} {2782965600 -10800 1 ADT} {2803525200 -14400 0 AST} {2814415200 -10800 1 ADT} {2834974800 -14400 0 AST} {2846469600 -10800 1 ADT} {2867029200 -14400 0 AST} {2877919200 -10800 1 ADT} {2898478800 -14400 0 AST} {2909368800 -10800 1 ADT} {2929928400 -14400 0 AST} {2940818400 -10800 1 ADT} {2961378000 -14400 0 AST} {2972268000 -10800 1 ADT} {2992827600 -14400 0 AST} {3003717600 -10800 1 ADT} {3024277200 -14400 0 AST} {3035772000 -10800 1 ADT} {3056331600 -14400 0 AST} {3067221600 -10800 1 ADT} {3087781200 -14400 0 AST} {3098671200 -10800 1 ADT} {3119230800 -14400 0 AST} {3130120800 -10800 1 ADT} {3150680400 -14400 0 AST} {3161570400 -10800 1 ADT} {3182130000 -14400 0 AST} {3193020000 -10800 1 ADT} {3213579600 -14400 0 AST} {3225074400 -10800 1 ADT} {3245634000 -14400 0 AST} {3256524000 -10800 1 ADT} {3277083600 -14400 0 AST} {3287973600 -10800 1 ADT} {3308533200 -14400 0 AST} {3319423200 -10800 1 ADT} {3339982800 -14400 0 AST} {3350872800 -10800 1 ADT} {3371432400 -14400 0 AST} {3382927200 -10800 1 ADT} {3403486800 -14400 0 AST} {3414376800 -10800 1 ADT} {3434936400 -14400 0 AST} {3445826400 -10800 1 ADT} {3466386000 -14400 0 AST} {3477276000 -10800 1 ADT} {3497835600 -14400 0 AST} {3508725600 -10800 1 ADT} {3529285200 -14400 0 AST} {3540175200 -10800 1 ADT} {3560734800 -14400 0 AST} {3572229600 -10800 1 ADT} {3592789200 -14400 0 AST} {3603679200 -10800 1 ADT} {3624238800 -14400 0 AST} {3635128800 -10800 1 ADT} {3655688400 -14400 0 AST} {3666578400 -10800 1 ADT} {3687138000 -14400 0 AST} {3698028000 -10800 1 ADT} {3718587600 -14400 0 AST} {3730082400 -10800 1 ADT} {3750642000 -14400 0 AST} {3761532000 -10800 1 ADT} {3782091600 -14400 0 AST} {3792981600 -10800 1 ADT} {3813541200 -14400 0 AST} {3824431200 -10800 1 ADT} {3844990800 -14400 0 AST} {3855880800 -10800 1 ADT} {3876440400 -14400 0 AST} {3887330400 -10800 1 ADT} {3907890000 -14400 0 AST} {3919384800 -10800 1 ADT} {3939944400 -14400 0 AST} {3950834400 -10800 1 ADT} {3971394000 -14400 0 AST} {3982284000 -10800 1 ADT} {4002843600 -14400 0 AST} {4013733600 -10800 1 ADT} {4034293200 -14400 0 AST} {4045183200 -10800 1 ADT} {4065742800 -14400 0 AST} {4076632800 -10800 1 ADT} {4097192400 -14400 0 AST} } tcl8.6.5/library/tzdata/America/St_Barthelemy0000644000175000017500000000032012663660066020544 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Port_of_Spain)]} { LoadTimeZoneFile America/Port_of_Spain } set TZData(:America/St_Barthelemy) $TZData(:America/Port_of_Spain) tcl8.6.5/library/tzdata/America/Dawson_Creek0000644000175000017500000000352412663660066020357 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Dawson_Creek) { {-9223372036854775808 -28856 0 LMT} {-2713881544 -28800 0 PST} {-1632060000 -25200 1 PDT} {-1615129200 -28800 0 PST} {-880207200 -25200 1 PWT} {-769395600 -25200 1 PPT} {-765385200 -28800 0 PST} {-725817600 -28800 0 PST} {-715788000 -25200 1 PDT} {-702486000 -28800 0 PST} {-684338400 -25200 1 PDT} {-671036400 -28800 0 PST} {-652888800 -25200 1 PDT} {-639586800 -28800 0 PST} {-620834400 -25200 1 PDT} {-608137200 -28800 0 PST} {-589384800 -25200 1 PDT} {-576082800 -28800 0 PST} {-557935200 -25200 1 PDT} {-544633200 -28800 0 PST} {-526485600 -25200 1 PDT} {-513183600 -28800 0 PST} {-495036000 -25200 1 PDT} {-481734000 -28800 0 PST} {-463586400 -25200 1 PDT} {-450284400 -28800 0 PST} {-431532000 -25200 1 PDT} {-418230000 -28800 0 PST} {-400082400 -25200 1 PDT} {-386780400 -28800 0 PST} {-368632800 -25200 1 PDT} {-355330800 -28800 0 PST} {-337183200 -25200 1 PDT} {-323881200 -28800 0 PST} {-305733600 -25200 1 PDT} {-292431600 -28800 0 PST} {-273679200 -25200 1 PDT} {-260982000 -28800 0 PST} {-242229600 -25200 1 PDT} {-226508400 -28800 0 PST} {-210780000 -25200 1 PDT} {-195058800 -28800 0 PST} {-179330400 -25200 1 PDT} {-163609200 -28800 0 PST} {-147880800 -25200 1 PDT} {-131554800 -28800 0 PST} {-116431200 -25200 1 PDT} {-100105200 -28800 0 PST} {-84376800 -25200 1 PDT} {-68655600 -28800 0 PST} {-52927200 -25200 1 PDT} {-37206000 -28800 0 PST} {-21477600 -25200 1 PDT} {-5756400 -28800 0 PST} {9972000 -25200 1 PDT} {25693200 -28800 0 PST} {41421600 -25200 1 PDT} {57747600 -28800 0 PST} {73476000 -25200 1 PDT} {84016800 -25200 0 MST} } tcl8.6.5/library/tzdata/America/Lower_Princes0000644000175000017500000000027612663653454020572 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Curacao)]} { LoadTimeZoneFile America/Curacao } set TZData(:America/Lower_Princes) $TZData(:America/Curacao) tcl8.6.5/library/tzdata/America/Sitka0000644000175000017500000002027012663660066017063 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Sitka) { {-9223372036854775808 53927 0 LMT} {-3225365927 -32473 0 LMT} {-2188954727 -28800 0 PST} {-883584000 -28800 0 PST} {-880207200 -25200 1 PWT} {-769395600 -25200 1 PPT} {-765385200 -28800 0 PST} {-757353600 -28800 0 PST} {-31507200 -28800 0 PST} {-21477600 -25200 1 PDT} {-5756400 -28800 0 PST} {9972000 -25200 1 PDT} {25693200 -28800 0 PST} {41421600 -25200 1 PDT} {57747600 -28800 0 PST} {73476000 -25200 1 PDT} {89197200 -28800 0 PST} {104925600 -25200 1 PDT} {120646800 -28800 0 PST} {126698400 -25200 1 PDT} {152096400 -28800 0 PST} {162381600 -25200 1 PDT} {183546000 -28800 0 PST} {199274400 -25200 1 PDT} {215600400 -28800 0 PST} {230724000 -25200 1 PDT} {247050000 -28800 0 PST} {262778400 -25200 1 PDT} {278499600 -28800 0 PST} {294228000 -25200 1 PDT} {309949200 -28800 0 PST} {325677600 -25200 1 PDT} {341398800 -28800 0 PST} {357127200 -25200 1 PDT} {372848400 -28800 0 PST} {388576800 -25200 1 PDT} {404902800 -28800 0 PST} {420026400 -25200 1 PDT} {439030800 -32400 0 AKST} {452084400 -28800 1 AKDT} {467805600 -32400 0 AKST} {483534000 -28800 1 AKDT} {499255200 -32400 0 AKST} {514983600 -28800 1 AKDT} {530704800 -32400 0 AKST} {544618800 -28800 1 AKDT} {562154400 -32400 0 AKST} {576068400 -28800 1 AKDT} {594208800 -32400 0 AKST} {607518000 -28800 1 AKDT} {625658400 -32400 0 AKST} {638967600 -28800 1 AKDT} {657108000 -32400 0 AKST} {671022000 -28800 1 AKDT} {688557600 -32400 0 AKST} {702471600 -28800 1 AKDT} {720007200 -32400 0 AKST} {733921200 -28800 1 AKDT} {752061600 -32400 0 AKST} {765370800 -28800 1 AKDT} {783511200 -32400 0 AKST} {796820400 -28800 1 AKDT} {814960800 -32400 0 AKST} {828874800 -28800 1 AKDT} {846410400 -32400 0 AKST} {860324400 -28800 1 AKDT} {877860000 -32400 0 AKST} {891774000 -28800 1 AKDT} {909309600 -32400 0 AKST} {923223600 -28800 1 AKDT} {941364000 -32400 0 AKST} {954673200 -28800 1 AKDT} {972813600 -32400 0 AKST} {986122800 -28800 1 AKDT} {1004263200 -32400 0 AKST} {1018177200 -28800 1 AKDT} {1035712800 -32400 0 AKST} {1049626800 -28800 1 AKDT} {1067162400 -32400 0 AKST} {1081076400 -28800 1 AKDT} {1099216800 -32400 0 AKST} {1112526000 -28800 1 AKDT} {1130666400 -32400 0 AKST} {1143975600 -28800 1 AKDT} {1162116000 -32400 0 AKST} {1173610800 -28800 1 AKDT} {1194170400 -32400 0 AKST} {1205060400 -28800 1 AKDT} {1225620000 -32400 0 AKST} {1236510000 -28800 1 AKDT} {1257069600 -32400 0 AKST} {1268564400 -28800 1 AKDT} {1289124000 -32400 0 AKST} {1300014000 -28800 1 AKDT} {1320573600 -32400 0 AKST} {1331463600 -28800 1 AKDT} {1352023200 -32400 0 AKST} {1362913200 -28800 1 AKDT} {1383472800 -32400 0 AKST} {1394362800 -28800 1 AKDT} {1414922400 -32400 0 AKST} {1425812400 -28800 1 AKDT} {1446372000 -32400 0 AKST} {1457866800 -28800 1 AKDT} {1478426400 -32400 0 AKST} {1489316400 -28800 1 AKDT} {1509876000 -32400 0 AKST} {1520766000 -28800 1 AKDT} {1541325600 -32400 0 AKST} {1552215600 -28800 1 AKDT} {1572775200 -32400 0 AKST} {1583665200 -28800 1 AKDT} {1604224800 -32400 0 AKST} {1615719600 -28800 1 AKDT} {1636279200 -32400 0 AKST} {1647169200 -28800 1 AKDT} {1667728800 -32400 0 AKST} {1678618800 -28800 1 AKDT} {1699178400 -32400 0 AKST} {1710068400 -28800 1 AKDT} {1730628000 -32400 0 AKST} {1741518000 -28800 1 AKDT} {1762077600 -32400 0 AKST} {1772967600 -28800 1 AKDT} {1793527200 -32400 0 AKST} {1805022000 -28800 1 AKDT} {1825581600 -32400 0 AKST} {1836471600 -28800 1 AKDT} {1857031200 -32400 0 AKST} {1867921200 -28800 1 AKDT} {1888480800 -32400 0 AKST} {1899370800 -28800 1 AKDT} {1919930400 -32400 0 AKST} {1930820400 -28800 1 AKDT} {1951380000 -32400 0 AKST} {1962874800 -28800 1 AKDT} {1983434400 -32400 0 AKST} {1994324400 -28800 1 AKDT} {2014884000 -32400 0 AKST} {2025774000 -28800 1 AKDT} {2046333600 -32400 0 AKST} {2057223600 -28800 1 AKDT} {2077783200 -32400 0 AKST} {2088673200 -28800 1 AKDT} {2109232800 -32400 0 AKST} {2120122800 -28800 1 AKDT} {2140682400 -32400 0 AKST} {2152177200 -28800 1 AKDT} {2172736800 -32400 0 AKST} {2183626800 -28800 1 AKDT} {2204186400 -32400 0 AKST} {2215076400 -28800 1 AKDT} {2235636000 -32400 0 AKST} {2246526000 -28800 1 AKDT} {2267085600 -32400 0 AKST} {2277975600 -28800 1 AKDT} {2298535200 -32400 0 AKST} {2309425200 -28800 1 AKDT} {2329984800 -32400 0 AKST} {2341479600 -28800 1 AKDT} {2362039200 -32400 0 AKST} {2372929200 -28800 1 AKDT} {2393488800 -32400 0 AKST} {2404378800 -28800 1 AKDT} {2424938400 -32400 0 AKST} {2435828400 -28800 1 AKDT} {2456388000 -32400 0 AKST} {2467278000 -28800 1 AKDT} {2487837600 -32400 0 AKST} {2499332400 -28800 1 AKDT} {2519892000 -32400 0 AKST} {2530782000 -28800 1 AKDT} {2551341600 -32400 0 AKST} {2562231600 -28800 1 AKDT} {2582791200 -32400 0 AKST} {2593681200 -28800 1 AKDT} {2614240800 -32400 0 AKST} {2625130800 -28800 1 AKDT} {2645690400 -32400 0 AKST} {2656580400 -28800 1 AKDT} {2677140000 -32400 0 AKST} {2688634800 -28800 1 AKDT} {2709194400 -32400 0 AKST} {2720084400 -28800 1 AKDT} {2740644000 -32400 0 AKST} {2751534000 -28800 1 AKDT} {2772093600 -32400 0 AKST} {2782983600 -28800 1 AKDT} {2803543200 -32400 0 AKST} {2814433200 -28800 1 AKDT} {2834992800 -32400 0 AKST} {2846487600 -28800 1 AKDT} {2867047200 -32400 0 AKST} {2877937200 -28800 1 AKDT} {2898496800 -32400 0 AKST} {2909386800 -28800 1 AKDT} {2929946400 -32400 0 AKST} {2940836400 -28800 1 AKDT} {2961396000 -32400 0 AKST} {2972286000 -28800 1 AKDT} {2992845600 -32400 0 AKST} {3003735600 -28800 1 AKDT} {3024295200 -32400 0 AKST} {3035790000 -28800 1 AKDT} {3056349600 -32400 0 AKST} {3067239600 -28800 1 AKDT} {3087799200 -32400 0 AKST} {3098689200 -28800 1 AKDT} {3119248800 -32400 0 AKST} {3130138800 -28800 1 AKDT} {3150698400 -32400 0 AKST} {3161588400 -28800 1 AKDT} {3182148000 -32400 0 AKST} {3193038000 -28800 1 AKDT} {3213597600 -32400 0 AKST} {3225092400 -28800 1 AKDT} {3245652000 -32400 0 AKST} {3256542000 -28800 1 AKDT} {3277101600 -32400 0 AKST} {3287991600 -28800 1 AKDT} {3308551200 -32400 0 AKST} {3319441200 -28800 1 AKDT} {3340000800 -32400 0 AKST} {3350890800 -28800 1 AKDT} {3371450400 -32400 0 AKST} {3382945200 -28800 1 AKDT} {3403504800 -32400 0 AKST} {3414394800 -28800 1 AKDT} {3434954400 -32400 0 AKST} {3445844400 -28800 1 AKDT} {3466404000 -32400 0 AKST} {3477294000 -28800 1 AKDT} {3497853600 -32400 0 AKST} {3508743600 -28800 1 AKDT} {3529303200 -32400 0 AKST} {3540193200 -28800 1 AKDT} {3560752800 -32400 0 AKST} {3572247600 -28800 1 AKDT} {3592807200 -32400 0 AKST} {3603697200 -28800 1 AKDT} {3624256800 -32400 0 AKST} {3635146800 -28800 1 AKDT} {3655706400 -32400 0 AKST} {3666596400 -28800 1 AKDT} {3687156000 -32400 0 AKST} {3698046000 -28800 1 AKDT} {3718605600 -32400 0 AKST} {3730100400 -28800 1 AKDT} {3750660000 -32400 0 AKST} {3761550000 -28800 1 AKDT} {3782109600 -32400 0 AKST} {3792999600 -28800 1 AKDT} {3813559200 -32400 0 AKST} {3824449200 -28800 1 AKDT} {3845008800 -32400 0 AKST} {3855898800 -28800 1 AKDT} {3876458400 -32400 0 AKST} {3887348400 -28800 1 AKDT} {3907908000 -32400 0 AKST} {3919402800 -28800 1 AKDT} {3939962400 -32400 0 AKST} {3950852400 -28800 1 AKDT} {3971412000 -32400 0 AKST} {3982302000 -28800 1 AKDT} {4002861600 -32400 0 AKST} {4013751600 -28800 1 AKDT} {4034311200 -32400 0 AKST} {4045201200 -28800 1 AKDT} {4065760800 -32400 0 AKST} {4076650800 -28800 1 AKDT} {4097210400 -32400 0 AKST} } tcl8.6.5/library/tzdata/America/Guayaquil0000644000175000017500000000026612661614720017746 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Guayaquil) { {-9223372036854775808 -19160 0 LMT} {-2524502440 -18840 0 QMT} {-1230749160 -18000 0 ECT} } tcl8.6.5/library/tzdata/America/Curacao0000644000175000017500000000026312663660066017365 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Curacao) { {-9223372036854775808 -16547 0 LMT} {-1826738653 -16200 0 ANT} {-157750200 -14400 0 AST} } tcl8.6.5/library/tzdata/America/Grand_Turk0000644000175000017500000000452312663660066020053 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Grand_Turk) { {-9223372036854775808 -17072 0 LMT} {-2524504528 -18431 0 KMT} {-1827687169 -18000 0 EST} {284014800 -18000 0 EST} {294217200 -14400 1 EDT} {309938400 -18000 0 EST} {325666800 -14400 1 EDT} {341388000 -18000 0 EST} {357116400 -14400 1 EDT} {372837600 -18000 0 EST} {388566000 -14400 1 EDT} {404892000 -18000 0 EST} {420015600 -14400 1 EDT} {436341600 -18000 0 EST} {452070000 -14400 1 EDT} {467791200 -18000 0 EST} {483519600 -14400 1 EDT} {499240800 -18000 0 EST} {514969200 -14400 1 EDT} {530690400 -18000 0 EST} {544604400 -14400 1 EDT} {562140000 -18000 0 EST} {576054000 -14400 1 EDT} {594194400 -18000 0 EST} {607503600 -14400 1 EDT} {625644000 -18000 0 EST} {638953200 -14400 1 EDT} {657093600 -18000 0 EST} {671007600 -14400 1 EDT} {688543200 -18000 0 EST} {702457200 -14400 1 EDT} {719992800 -18000 0 EST} {733906800 -14400 1 EDT} {752047200 -18000 0 EST} {765356400 -14400 1 EDT} {783496800 -18000 0 EST} {796806000 -14400 1 EDT} {814946400 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {909295200 -18000 0 EST} {923209200 -14400 1 EDT} {941349600 -18000 0 EST} {954658800 -14400 1 EDT} {972799200 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446361200 -14400 0 AST} } tcl8.6.5/library/tzdata/America/Belem0000644000175000017500000000176212661614720017033 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:America/Belem) { {-9223372036854775808 -11636 0 LMT} {-1767213964 -10800 0 BRT} {-1206957600 -7200 1 BRST} {-1191362400 -10800 0 BRT} {-1175374800 -7200 1 BRST} {-1159826400 -10800 0 BRT} {-633819600 -7200 1 BRST} {-622069200 -10800 0 BRT} {-602283600 -7200 1 BRST} {-591832800 -10800 0 BRT} {-570747600 -7200 1 BRST} {-560210400 -10800 0 BRT} {-539125200 -7200 1 BRST} {-531352800 -10800 0 BRT} {-191365200 -7200 1 BRST} {-184197600 -10800 0 BRT} {-155163600 -7200 1 BRST} {-150069600 -10800 0 BRT} {-128898000 -7200 1 BRST} {-121125600 -10800 0 BRT} {-99954000 -7200 1 BRST} {-89589600 -10800 0 BRT} {-68418000 -7200 1 BRST} {-57967200 -10800 0 BRT} {499748400 -7200 1 BRST} {511236000 -10800 0 BRT} {530593200 -7200 1 BRST} {540266400 -10800 0 BRT} {562129200 -7200 1 BRST} {571197600 -10800 0 BRT} {590032800 -10800 0 BRT} } tcl8.6.5/library/tzdata/Singapore0000644000175000017500000000025712661614722016375 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Singapore)]} { LoadTimeZoneFile Asia/Singapore } set TZData(:Singapore) $TZData(:Asia/Singapore) tcl8.6.5/library/tzdata/GMT-00000644000175000017500000000022612661614722015226 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/GMT)]} { LoadTimeZoneFile Etc/GMT } set TZData(:GMT-0) $TZData(:Etc/GMT) tcl8.6.5/library/tzdata/Australia/0000755000175000017500000000000012665173607016452 5ustar sergeisergeitcl8.6.5/library/tzdata/Australia/Queensland0000644000175000017500000000030612661614722020465 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Australia/Brisbane)]} { LoadTimeZoneFile Australia/Brisbane } set TZData(:Australia/Queensland) $TZData(:Australia/Brisbane) tcl8.6.5/library/tzdata/Australia/Brisbane0000644000175000017500000000121312663660066020115 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Brisbane) { {-9223372036854775808 36728 0 LMT} {-2366791928 36000 0 AEST} {-1672567140 39600 1 AEDT} {-1665392400 36000 0 AEST} {-883641600 39600 1 AEDT} {-876128400 36000 0 AEST} {-860400000 39600 1 AEDT} {-844678800 36000 0 AEST} {-828345600 39600 1 AEDT} {-813229200 36000 0 AEST} {31500000 36000 0 AEST} {57686400 39600 1 AEDT} {67968000 36000 0 AEST} {625593600 39600 1 AEDT} {636480000 36000 0 AEST} {657043200 39600 1 AEDT} {667929600 36000 0 AEST} {688492800 39600 1 AEDT} {699379200 36000 0 AEST} } tcl8.6.5/library/tzdata/Australia/Perth0000644000175000017500000000131212663660066017452 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Perth) { {-9223372036854775808 27804 0 LMT} {-2337925404 28800 0 AWST} {-1672559940 32400 1 AWDT} {-1665385200 28800 0 AWST} {-883634400 32400 1 AWDT} {-876121200 28800 0 AWST} {-860392800 32400 1 AWDT} {-844671600 28800 0 AWST} {-836470800 32400 0 AWST} {152042400 32400 1 AWDT} {162928800 28800 0 AWST} {436298400 32400 1 AWDT} {447184800 28800 0 AWST} {690314400 32400 1 AWDT} {699386400 28800 0 AWST} {1165082400 32400 1 AWDT} {1174759200 28800 0 AWST} {1193508000 32400 1 AWDT} {1206813600 28800 0 AWST} {1224957600 32400 1 AWDT} {1238263200 28800 0 AWST} } tcl8.6.5/library/tzdata/Australia/Lord_Howe0000644000175000017500000001612312663660066020260 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Lord_Howe) { {-9223372036854775808 38180 0 LMT} {-2364114980 36000 0 AEST} {352216800 37800 0 LHST} {372785400 41400 1 LHDT} {384273000 37800 0 LHST} {404839800 41400 1 LHDT} {415722600 37800 0 LHST} {436289400 41400 1 LHDT} {447172200 37800 0 LHST} {467739000 41400 1 LHDT} {478621800 37800 0 LHST} {499188600 39600 1 LHDT} {511282800 37800 0 LHST} {530033400 39600 1 LHDT} {542732400 37800 0 LHST} {562087800 39600 1 LHDT} {574786800 37800 0 LHST} {594142200 39600 1 LHDT} {606236400 37800 0 LHST} {625591800 39600 1 LHDT} {636476400 37800 0 LHST} {657041400 39600 1 LHDT} {667926000 37800 0 LHST} {688491000 39600 1 LHDT} {699375600 37800 0 LHST} {719940600 39600 1 LHDT} {731430000 37800 0 LHST} {751995000 39600 1 LHDT} {762879600 37800 0 LHST} {783444600 39600 1 LHDT} {794329200 37800 0 LHST} {814894200 39600 1 LHDT} {828198000 37800 0 LHST} {846343800 39600 1 LHDT} {859647600 37800 0 LHST} {877793400 39600 1 LHDT} {891097200 37800 0 LHST} {909243000 39600 1 LHDT} {922546800 37800 0 LHST} {941297400 39600 1 LHDT} {953996400 37800 0 LHST} {967303800 39600 1 LHDT} {985446000 37800 0 LHST} {1004196600 39600 1 LHDT} {1017500400 37800 0 LHST} {1035646200 39600 1 LHDT} {1048950000 37800 0 LHST} {1067095800 39600 1 LHDT} {1080399600 37800 0 LHST} {1099150200 39600 1 LHDT} {1111849200 37800 0 LHST} {1130599800 39600 1 LHDT} {1143903600 37800 0 LHST} {1162049400 39600 1 LHDT} {1174748400 37800 0 LHST} {1193499000 39600 1 LHDT} {1207407600 37800 0 LHST} {1223134200 39600 1 LHDT} {1238857200 37800 0 LHST} {1254583800 39600 1 LHDT} {1270306800 37800 0 LHST} {1286033400 39600 1 LHDT} {1301756400 37800 0 LHST} {1317483000 39600 1 LHDT} {1333206000 37800 0 LHST} {1349537400 39600 1 LHDT} {1365260400 37800 0 LHST} {1380987000 39600 1 LHDT} {1396710000 37800 0 LHST} {1412436600 39600 1 LHDT} {1428159600 37800 0 LHST} {1443886200 39600 1 LHDT} {1459609200 37800 0 LHST} {1475335800 39600 1 LHDT} {1491058800 37800 0 LHST} {1506785400 39600 1 LHDT} {1522508400 37800 0 LHST} {1538839800 39600 1 LHDT} {1554562800 37800 0 LHST} {1570289400 39600 1 LHDT} {1586012400 37800 0 LHST} {1601739000 39600 1 LHDT} {1617462000 37800 0 LHST} {1633188600 39600 1 LHDT} {1648911600 37800 0 LHST} {1664638200 39600 1 LHDT} {1680361200 37800 0 LHST} {1696087800 39600 1 LHDT} {1712415600 37800 0 LHST} {1728142200 39600 1 LHDT} {1743865200 37800 0 LHST} {1759591800 39600 1 LHDT} {1775314800 37800 0 LHST} {1791041400 39600 1 LHDT} {1806764400 37800 0 LHST} {1822491000 39600 1 LHDT} {1838214000 37800 0 LHST} {1853940600 39600 1 LHDT} {1869663600 37800 0 LHST} {1885995000 39600 1 LHDT} {1901718000 37800 0 LHST} {1917444600 39600 1 LHDT} {1933167600 37800 0 LHST} {1948894200 39600 1 LHDT} {1964617200 37800 0 LHST} {1980343800 39600 1 LHDT} {1996066800 37800 0 LHST} {2011793400 39600 1 LHDT} {2027516400 37800 0 LHST} {2043243000 39600 1 LHDT} {2058966000 37800 0 LHST} {2075297400 39600 1 LHDT} {2091020400 37800 0 LHST} {2106747000 39600 1 LHDT} {2122470000 37800 0 LHST} {2138196600 39600 1 LHDT} {2153919600 37800 0 LHST} {2169646200 39600 1 LHDT} {2185369200 37800 0 LHST} {2201095800 39600 1 LHDT} {2216818800 37800 0 LHST} {2233150200 39600 1 LHDT} {2248873200 37800 0 LHST} {2264599800 39600 1 LHDT} {2280322800 37800 0 LHST} {2296049400 39600 1 LHDT} {2311772400 37800 0 LHST} {2327499000 39600 1 LHDT} {2343222000 37800 0 LHST} {2358948600 39600 1 LHDT} {2374671600 37800 0 LHST} {2390398200 39600 1 LHDT} {2406121200 37800 0 LHST} {2422452600 39600 1 LHDT} {2438175600 37800 0 LHST} {2453902200 39600 1 LHDT} {2469625200 37800 0 LHST} {2485351800 39600 1 LHDT} {2501074800 37800 0 LHST} {2516801400 39600 1 LHDT} {2532524400 37800 0 LHST} {2548251000 39600 1 LHDT} {2563974000 37800 0 LHST} {2579700600 39600 1 LHDT} {2596028400 37800 0 LHST} {2611755000 39600 1 LHDT} {2627478000 37800 0 LHST} {2643204600 39600 1 LHDT} {2658927600 37800 0 LHST} {2674654200 39600 1 LHDT} {2690377200 37800 0 LHST} {2706103800 39600 1 LHDT} {2721826800 37800 0 LHST} {2737553400 39600 1 LHDT} {2753276400 37800 0 LHST} {2769607800 39600 1 LHDT} {2785330800 37800 0 LHST} {2801057400 39600 1 LHDT} {2816780400 37800 0 LHST} {2832507000 39600 1 LHDT} {2848230000 37800 0 LHST} {2863956600 39600 1 LHDT} {2879679600 37800 0 LHST} {2895406200 39600 1 LHDT} {2911129200 37800 0 LHST} {2926855800 39600 1 LHDT} {2942578800 37800 0 LHST} {2958910200 39600 1 LHDT} {2974633200 37800 0 LHST} {2990359800 39600 1 LHDT} {3006082800 37800 0 LHST} {3021809400 39600 1 LHDT} {3037532400 37800 0 LHST} {3053259000 39600 1 LHDT} {3068982000 37800 0 LHST} {3084708600 39600 1 LHDT} {3100431600 37800 0 LHST} {3116763000 39600 1 LHDT} {3132486000 37800 0 LHST} {3148212600 39600 1 LHDT} {3163935600 37800 0 LHST} {3179662200 39600 1 LHDT} {3195385200 37800 0 LHST} {3211111800 39600 1 LHDT} {3226834800 37800 0 LHST} {3242561400 39600 1 LHDT} {3258284400 37800 0 LHST} {3274011000 39600 1 LHDT} {3289734000 37800 0 LHST} {3306065400 39600 1 LHDT} {3321788400 37800 0 LHST} {3337515000 39600 1 LHDT} {3353238000 37800 0 LHST} {3368964600 39600 1 LHDT} {3384687600 37800 0 LHST} {3400414200 39600 1 LHDT} {3416137200 37800 0 LHST} {3431863800 39600 1 LHDT} {3447586800 37800 0 LHST} {3463313400 39600 1 LHDT} {3479641200 37800 0 LHST} {3495367800 39600 1 LHDT} {3511090800 37800 0 LHST} {3526817400 39600 1 LHDT} {3542540400 37800 0 LHST} {3558267000 39600 1 LHDT} {3573990000 37800 0 LHST} {3589716600 39600 1 LHDT} {3605439600 37800 0 LHST} {3621166200 39600 1 LHDT} {3636889200 37800 0 LHST} {3653220600 39600 1 LHDT} {3668943600 37800 0 LHST} {3684670200 39600 1 LHDT} {3700393200 37800 0 LHST} {3716119800 39600 1 LHDT} {3731842800 37800 0 LHST} {3747569400 39600 1 LHDT} {3763292400 37800 0 LHST} {3779019000 39600 1 LHDT} {3794742000 37800 0 LHST} {3810468600 39600 1 LHDT} {3826191600 37800 0 LHST} {3842523000 39600 1 LHDT} {3858246000 37800 0 LHST} {3873972600 39600 1 LHDT} {3889695600 37800 0 LHST} {3905422200 39600 1 LHDT} {3921145200 37800 0 LHST} {3936871800 39600 1 LHDT} {3952594800 37800 0 LHST} {3968321400 39600 1 LHDT} {3984044400 37800 0 LHST} {4000375800 39600 1 LHDT} {4016098800 37800 0 LHST} {4031825400 39600 1 LHDT} {4047548400 37800 0 LHST} {4063275000 39600 1 LHDT} {4078998000 37800 0 LHST} {4094724600 39600 1 LHDT} } tcl8.6.5/library/tzdata/Australia/Canberra0000644000175000017500000000027612661614722020111 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Australia/Sydney)]} { LoadTimeZoneFile Australia/Sydney } set TZData(:Australia/Canberra) $TZData(:Australia/Sydney) tcl8.6.5/library/tzdata/Australia/Sydney0000644000175000017500000001760212663660066017654 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Sydney) { {-9223372036854775808 36292 0 LMT} {-2364113092 36000 0 AEST} {-1672567140 39600 1 AEDT} {-1665392400 36000 0 AEST} {-883641600 39600 1 AEDT} {-876128400 36000 0 AEST} {-860400000 39600 1 AEDT} {-844678800 36000 0 AEST} {-828345600 39600 1 AEDT} {-813229200 36000 0 AEST} {31500000 36000 0 AEST} {57686400 39600 1 AEDT} {67968000 36000 0 AEST} {89136000 39600 1 AEDT} {100022400 36000 0 AEST} {120585600 39600 1 AEDT} {131472000 36000 0 AEST} {152035200 39600 1 AEDT} {162921600 36000 0 AEST} {183484800 39600 1 AEDT} {194976000 36000 0 AEST} {215539200 39600 1 AEDT} {226425600 36000 0 AEST} {246988800 39600 1 AEDT} {257875200 36000 0 AEST} {278438400 39600 1 AEDT} {289324800 36000 0 AEST} {309888000 39600 1 AEDT} {320774400 36000 0 AEST} {341337600 39600 1 AEDT} {352224000 36000 0 AEST} {372787200 39600 1 AEDT} {386697600 36000 0 AEST} {404841600 39600 1 AEDT} {415728000 36000 0 AEST} {436291200 39600 1 AEDT} {447177600 36000 0 AEST} {467740800 39600 1 AEDT} {478627200 36000 0 AEST} {499190400 39600 1 AEDT} {511286400 36000 0 AEST} {530035200 39600 1 AEDT} {542736000 36000 0 AEST} {562089600 39600 1 AEDT} {574790400 36000 0 AEST} {594144000 39600 1 AEDT} {606240000 36000 0 AEST} {625593600 39600 1 AEDT} {636480000 36000 0 AEST} {657043200 39600 1 AEDT} {667929600 36000 0 AEST} {688492800 39600 1 AEDT} {699379200 36000 0 AEST} {719942400 39600 1 AEDT} {731433600 36000 0 AEST} {751996800 39600 1 AEDT} {762883200 36000 0 AEST} {783446400 39600 1 AEDT} {794332800 36000 0 AEST} {814896000 39600 1 AEDT} {828201600 36000 0 AEST} {846345600 39600 1 AEDT} {859651200 36000 0 AEST} {877795200 39600 1 AEDT} {891100800 36000 0 AEST} {909244800 39600 1 AEDT} {922550400 36000 0 AEST} {941299200 39600 1 AEDT} {954000000 36000 0 AEST} {967305600 39600 1 AEDT} {985449600 36000 0 AEST} {1004198400 39600 1 AEDT} {1017504000 36000 0 AEST} {1035648000 39600 1 AEDT} {1048953600 36000 0 AEST} {1067097600 39600 1 AEDT} {1080403200 36000 0 AEST} {1099152000 39600 1 AEDT} {1111852800 36000 0 AEST} {1130601600 39600 1 AEDT} {1143907200 36000 0 AEST} {1162051200 39600 1 AEDT} {1174752000 36000 0 AEST} {1193500800 39600 1 AEDT} {1207411200 36000 0 AEST} {1223136000 39600 1 AEDT} {1238860800 36000 0 AEST} {1254585600 39600 1 AEDT} {1270310400 36000 0 AEST} {1286035200 39600 1 AEDT} {1301760000 36000 0 AEST} {1317484800 39600 1 AEDT} {1333209600 36000 0 AEST} {1349539200 39600 1 AEDT} {1365264000 36000 0 AEST} {1380988800 39600 1 AEDT} {1396713600 36000 0 AEST} {1412438400 39600 1 AEDT} {1428163200 36000 0 AEST} {1443888000 39600 1 AEDT} {1459612800 36000 0 AEST} {1475337600 39600 1 AEDT} {1491062400 36000 0 AEST} {1506787200 39600 1 AEDT} {1522512000 36000 0 AEST} {1538841600 39600 1 AEDT} {1554566400 36000 0 AEST} {1570291200 39600 1 AEDT} {1586016000 36000 0 AEST} {1601740800 39600 1 AEDT} {1617465600 36000 0 AEST} {1633190400 39600 1 AEDT} {1648915200 36000 0 AEST} {1664640000 39600 1 AEDT} {1680364800 36000 0 AEST} {1696089600 39600 1 AEDT} {1712419200 36000 0 AEST} {1728144000 39600 1 AEDT} {1743868800 36000 0 AEST} {1759593600 39600 1 AEDT} {1775318400 36000 0 AEST} {1791043200 39600 1 AEDT} {1806768000 36000 0 AEST} {1822492800 39600 1 AEDT} {1838217600 36000 0 AEST} {1853942400 39600 1 AEDT} {1869667200 36000 0 AEST} {1885996800 39600 1 AEDT} {1901721600 36000 0 AEST} {1917446400 39600 1 AEDT} {1933171200 36000 0 AEST} {1948896000 39600 1 AEDT} {1964620800 36000 0 AEST} {1980345600 39600 1 AEDT} {1996070400 36000 0 AEST} {2011795200 39600 1 AEDT} {2027520000 36000 0 AEST} {2043244800 39600 1 AEDT} {2058969600 36000 0 AEST} {2075299200 39600 1 AEDT} {2091024000 36000 0 AEST} {2106748800 39600 1 AEDT} {2122473600 36000 0 AEST} {2138198400 39600 1 AEDT} {2153923200 36000 0 AEST} {2169648000 39600 1 AEDT} {2185372800 36000 0 AEST} {2201097600 39600 1 AEDT} {2216822400 36000 0 AEST} {2233152000 39600 1 AEDT} {2248876800 36000 0 AEST} {2264601600 39600 1 AEDT} {2280326400 36000 0 AEST} {2296051200 39600 1 AEDT} {2311776000 36000 0 AEST} {2327500800 39600 1 AEDT} {2343225600 36000 0 AEST} {2358950400 39600 1 AEDT} {2374675200 36000 0 AEST} {2390400000 39600 1 AEDT} {2406124800 36000 0 AEST} {2422454400 39600 1 AEDT} {2438179200 36000 0 AEST} {2453904000 39600 1 AEDT} {2469628800 36000 0 AEST} {2485353600 39600 1 AEDT} {2501078400 36000 0 AEST} {2516803200 39600 1 AEDT} {2532528000 36000 0 AEST} {2548252800 39600 1 AEDT} {2563977600 36000 0 AEST} {2579702400 39600 1 AEDT} {2596032000 36000 0 AEST} {2611756800 39600 1 AEDT} {2627481600 36000 0 AEST} {2643206400 39600 1 AEDT} {2658931200 36000 0 AEST} {2674656000 39600 1 AEDT} {2690380800 36000 0 AEST} {2706105600 39600 1 AEDT} {2721830400 36000 0 AEST} {2737555200 39600 1 AEDT} {2753280000 36000 0 AEST} {2769609600 39600 1 AEDT} {2785334400 36000 0 AEST} {2801059200 39600 1 AEDT} {2816784000 36000 0 AEST} {2832508800 39600 1 AEDT} {2848233600 36000 0 AEST} {2863958400 39600 1 AEDT} {2879683200 36000 0 AEST} {2895408000 39600 1 AEDT} {2911132800 36000 0 AEST} {2926857600 39600 1 AEDT} {2942582400 36000 0 AEST} {2958912000 39600 1 AEDT} {2974636800 36000 0 AEST} {2990361600 39600 1 AEDT} {3006086400 36000 0 AEST} {3021811200 39600 1 AEDT} {3037536000 36000 0 AEST} {3053260800 39600 1 AEDT} {3068985600 36000 0 AEST} {3084710400 39600 1 AEDT} {3100435200 36000 0 AEST} {3116764800 39600 1 AEDT} {3132489600 36000 0 AEST} {3148214400 39600 1 AEDT} {3163939200 36000 0 AEST} {3179664000 39600 1 AEDT} {3195388800 36000 0 AEST} {3211113600 39600 1 AEDT} {3226838400 36000 0 AEST} {3242563200 39600 1 AEDT} {3258288000 36000 0 AEST} {3274012800 39600 1 AEDT} {3289737600 36000 0 AEST} {3306067200 39600 1 AEDT} {3321792000 36000 0 AEST} {3337516800 39600 1 AEDT} {3353241600 36000 0 AEST} {3368966400 39600 1 AEDT} {3384691200 36000 0 AEST} {3400416000 39600 1 AEDT} {3416140800 36000 0 AEST} {3431865600 39600 1 AEDT} {3447590400 36000 0 AEST} {3463315200 39600 1 AEDT} {3479644800 36000 0 AEST} {3495369600 39600 1 AEDT} {3511094400 36000 0 AEST} {3526819200 39600 1 AEDT} {3542544000 36000 0 AEST} {3558268800 39600 1 AEDT} {3573993600 36000 0 AEST} {3589718400 39600 1 AEDT} {3605443200 36000 0 AEST} {3621168000 39600 1 AEDT} {3636892800 36000 0 AEST} {3653222400 39600 1 AEDT} {3668947200 36000 0 AEST} {3684672000 39600 1 AEDT} {3700396800 36000 0 AEST} {3716121600 39600 1 AEDT} {3731846400 36000 0 AEST} {3747571200 39600 1 AEDT} {3763296000 36000 0 AEST} {3779020800 39600 1 AEDT} {3794745600 36000 0 AEST} {3810470400 39600 1 AEDT} {3826195200 36000 0 AEST} {3842524800 39600 1 AEDT} {3858249600 36000 0 AEST} {3873974400 39600 1 AEDT} {3889699200 36000 0 AEST} {3905424000 39600 1 AEDT} {3921148800 36000 0 AEST} {3936873600 39600 1 AEDT} {3952598400 36000 0 AEST} {3968323200 39600 1 AEDT} {3984048000 36000 0 AEST} {4000377600 39600 1 AEDT} {4016102400 36000 0 AEST} {4031827200 39600 1 AEDT} {4047552000 36000 0 AEST} {4063276800 39600 1 AEDT} {4079001600 36000 0 AEST} {4094726400 39600 1 AEDT} } tcl8.6.5/library/tzdata/Australia/Yancowinna0000644000175000017500000000031712661614722020476 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Australia/Broken_Hill)]} { LoadTimeZoneFile Australia/Broken_Hill } set TZData(:Australia/Yancowinna) $TZData(:Australia/Broken_Hill) tcl8.6.5/library/tzdata/Australia/Victoria0000644000175000017500000000030712661614722020147 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Australia/Melbourne)]} { LoadTimeZoneFile Australia/Melbourne } set TZData(:Australia/Victoria) $TZData(:Australia/Melbourne) tcl8.6.5/library/tzdata/Australia/NSW0000644000175000017500000000027112661614722017036 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Australia/Sydney)]} { LoadTimeZoneFile Australia/Sydney } set TZData(:Australia/NSW) $TZData(:Australia/Sydney) tcl8.6.5/library/tzdata/Australia/Darwin0000644000175000017500000000064612663660066017625 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Darwin) { {-9223372036854775808 31400 0 LMT} {-2364108200 32400 0 ACST} {-2230189200 34200 0 ACST} {-1672565340 37800 1 ACDT} {-1665390600 34200 0 ACST} {-883639800 37800 1 ACDT} {-876126600 34200 0 ACST} {-860398200 37800 1 ACDT} {-844677000 34200 0 ACST} {-828343800 37800 1 ACDT} {-813227400 34200 0 ACST} } tcl8.6.5/library/tzdata/Australia/Hobart0000644000175000017500000002020512663660066017611 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Hobart) { {-9223372036854775808 35356 0 LMT} {-2345795356 36000 0 AEST} {-1680508800 39600 1 AEDT} {-1669892400 39600 0 AEDT} {-1665392400 36000 0 AEST} {-883641600 39600 1 AEDT} {-876128400 36000 0 AEST} {-860400000 39600 1 AEDT} {-844678800 36000 0 AEST} {-828345600 39600 1 AEDT} {-813229200 36000 0 AEST} {-94730400 36000 0 AEST} {-71136000 39600 1 AEDT} {-55411200 36000 0 AEST} {-37267200 39600 1 AEDT} {-25776000 36000 0 AEST} {-5817600 39600 1 AEDT} {5673600 36000 0 AEST} {25632000 39600 1 AEDT} {37728000 36000 0 AEST} {57686400 39600 1 AEDT} {67968000 36000 0 AEST} {89136000 39600 1 AEDT} {100022400 36000 0 AEST} {120585600 39600 1 AEDT} {131472000 36000 0 AEST} {152035200 39600 1 AEDT} {162921600 36000 0 AEST} {183484800 39600 1 AEDT} {194976000 36000 0 AEST} {215539200 39600 1 AEDT} {226425600 36000 0 AEST} {246988800 39600 1 AEDT} {257875200 36000 0 AEST} {278438400 39600 1 AEDT} {289324800 36000 0 AEST} {309888000 39600 1 AEDT} {320774400 36000 0 AEST} {341337600 39600 1 AEDT} {352224000 36000 0 AEST} {372787200 39600 1 AEDT} {386092800 36000 0 AEST} {404841600 39600 1 AEDT} {417542400 36000 0 AEST} {436291200 39600 1 AEDT} {447177600 36000 0 AEST} {467740800 39600 1 AEDT} {478627200 36000 0 AEST} {499190400 39600 1 AEDT} {510076800 36000 0 AEST} {530035200 39600 1 AEDT} {542736000 36000 0 AEST} {562089600 39600 1 AEDT} {574790400 36000 0 AEST} {594144000 39600 1 AEDT} {606240000 36000 0 AEST} {625593600 39600 1 AEDT} {637689600 36000 0 AEST} {657043200 39600 1 AEDT} {670348800 36000 0 AEST} {686678400 39600 1 AEDT} {701798400 36000 0 AEST} {718128000 39600 1 AEDT} {733248000 36000 0 AEST} {749577600 39600 1 AEDT} {764697600 36000 0 AEST} {781027200 39600 1 AEDT} {796147200 36000 0 AEST} {812476800 39600 1 AEDT} {828201600 36000 0 AEST} {844531200 39600 1 AEDT} {859651200 36000 0 AEST} {875980800 39600 1 AEDT} {891100800 36000 0 AEST} {907430400 39600 1 AEDT} {922550400 36000 0 AEST} {938880000 39600 1 AEDT} {954000000 36000 0 AEST} {967305600 39600 1 AEDT} {985449600 36000 0 AEST} {1002384000 39600 1 AEDT} {1017504000 36000 0 AEST} {1033833600 39600 1 AEDT} {1048953600 36000 0 AEST} {1065283200 39600 1 AEDT} {1080403200 36000 0 AEST} {1096732800 39600 1 AEDT} {1111852800 36000 0 AEST} {1128182400 39600 1 AEDT} {1143907200 36000 0 AEST} {1159632000 39600 1 AEDT} {1174752000 36000 0 AEST} {1191686400 39600 1 AEDT} {1207411200 36000 0 AEST} {1223136000 39600 1 AEDT} {1238860800 36000 0 AEST} {1254585600 39600 1 AEDT} {1270310400 36000 0 AEST} {1286035200 39600 1 AEDT} {1301760000 36000 0 AEST} {1317484800 39600 1 AEDT} {1333209600 36000 0 AEST} {1349539200 39600 1 AEDT} {1365264000 36000 0 AEST} {1380988800 39600 1 AEDT} {1396713600 36000 0 AEST} {1412438400 39600 1 AEDT} {1428163200 36000 0 AEST} {1443888000 39600 1 AEDT} {1459612800 36000 0 AEST} {1475337600 39600 1 AEDT} {1491062400 36000 0 AEST} {1506787200 39600 1 AEDT} {1522512000 36000 0 AEST} {1538841600 39600 1 AEDT} {1554566400 36000 0 AEST} {1570291200 39600 1 AEDT} {1586016000 36000 0 AEST} {1601740800 39600 1 AEDT} {1617465600 36000 0 AEST} {1633190400 39600 1 AEDT} {1648915200 36000 0 AEST} {1664640000 39600 1 AEDT} {1680364800 36000 0 AEST} {1696089600 39600 1 AEDT} {1712419200 36000 0 AEST} {1728144000 39600 1 AEDT} {1743868800 36000 0 AEST} {1759593600 39600 1 AEDT} {1775318400 36000 0 AEST} {1791043200 39600 1 AEDT} {1806768000 36000 0 AEST} {1822492800 39600 1 AEDT} {1838217600 36000 0 AEST} {1853942400 39600 1 AEDT} {1869667200 36000 0 AEST} {1885996800 39600 1 AEDT} {1901721600 36000 0 AEST} {1917446400 39600 1 AEDT} {1933171200 36000 0 AEST} {1948896000 39600 1 AEDT} {1964620800 36000 0 AEST} {1980345600 39600 1 AEDT} {1996070400 36000 0 AEST} {2011795200 39600 1 AEDT} {2027520000 36000 0 AEST} {2043244800 39600 1 AEDT} {2058969600 36000 0 AEST} {2075299200 39600 1 AEDT} {2091024000 36000 0 AEST} {2106748800 39600 1 AEDT} {2122473600 36000 0 AEST} {2138198400 39600 1 AEDT} {2153923200 36000 0 AEST} {2169648000 39600 1 AEDT} {2185372800 36000 0 AEST} {2201097600 39600 1 AEDT} {2216822400 36000 0 AEST} {2233152000 39600 1 AEDT} {2248876800 36000 0 AEST} {2264601600 39600 1 AEDT} {2280326400 36000 0 AEST} {2296051200 39600 1 AEDT} {2311776000 36000 0 AEST} {2327500800 39600 1 AEDT} {2343225600 36000 0 AEST} {2358950400 39600 1 AEDT} {2374675200 36000 0 AEST} {2390400000 39600 1 AEDT} {2406124800 36000 0 AEST} {2422454400 39600 1 AEDT} {2438179200 36000 0 AEST} {2453904000 39600 1 AEDT} {2469628800 36000 0 AEST} {2485353600 39600 1 AEDT} {2501078400 36000 0 AEST} {2516803200 39600 1 AEDT} {2532528000 36000 0 AEST} {2548252800 39600 1 AEDT} {2563977600 36000 0 AEST} {2579702400 39600 1 AEDT} {2596032000 36000 0 AEST} {2611756800 39600 1 AEDT} {2627481600 36000 0 AEST} {2643206400 39600 1 AEDT} {2658931200 36000 0 AEST} {2674656000 39600 1 AEDT} {2690380800 36000 0 AEST} {2706105600 39600 1 AEDT} {2721830400 36000 0 AEST} {2737555200 39600 1 AEDT} {2753280000 36000 0 AEST} {2769609600 39600 1 AEDT} {2785334400 36000 0 AEST} {2801059200 39600 1 AEDT} {2816784000 36000 0 AEST} {2832508800 39600 1 AEDT} {2848233600 36000 0 AEST} {2863958400 39600 1 AEDT} {2879683200 36000 0 AEST} {2895408000 39600 1 AEDT} {2911132800 36000 0 AEST} {2926857600 39600 1 AEDT} {2942582400 36000 0 AEST} {2958912000 39600 1 AEDT} {2974636800 36000 0 AEST} {2990361600 39600 1 AEDT} {3006086400 36000 0 AEST} {3021811200 39600 1 AEDT} {3037536000 36000 0 AEST} {3053260800 39600 1 AEDT} {3068985600 36000 0 AEST} {3084710400 39600 1 AEDT} {3100435200 36000 0 AEST} {3116764800 39600 1 AEDT} {3132489600 36000 0 AEST} {3148214400 39600 1 AEDT} {3163939200 36000 0 AEST} {3179664000 39600 1 AEDT} {3195388800 36000 0 AEST} {3211113600 39600 1 AEDT} {3226838400 36000 0 AEST} {3242563200 39600 1 AEDT} {3258288000 36000 0 AEST} {3274012800 39600 1 AEDT} {3289737600 36000 0 AEST} {3306067200 39600 1 AEDT} {3321792000 36000 0 AEST} {3337516800 39600 1 AEDT} {3353241600 36000 0 AEST} {3368966400 39600 1 AEDT} {3384691200 36000 0 AEST} {3400416000 39600 1 AEDT} {3416140800 36000 0 AEST} {3431865600 39600 1 AEDT} {3447590400 36000 0 AEST} {3463315200 39600 1 AEDT} {3479644800 36000 0 AEST} {3495369600 39600 1 AEDT} {3511094400 36000 0 AEST} {3526819200 39600 1 AEDT} {3542544000 36000 0 AEST} {3558268800 39600 1 AEDT} {3573993600 36000 0 AEST} {3589718400 39600 1 AEDT} {3605443200 36000 0 AEST} {3621168000 39600 1 AEDT} {3636892800 36000 0 AEST} {3653222400 39600 1 AEDT} {3668947200 36000 0 AEST} {3684672000 39600 1 AEDT} {3700396800 36000 0 AEST} {3716121600 39600 1 AEDT} {3731846400 36000 0 AEST} {3747571200 39600 1 AEDT} {3763296000 36000 0 AEST} {3779020800 39600 1 AEDT} {3794745600 36000 0 AEST} {3810470400 39600 1 AEDT} {3826195200 36000 0 AEST} {3842524800 39600 1 AEDT} {3858249600 36000 0 AEST} {3873974400 39600 1 AEDT} {3889699200 36000 0 AEST} {3905424000 39600 1 AEDT} {3921148800 36000 0 AEST} {3936873600 39600 1 AEDT} {3952598400 36000 0 AEST} {3968323200 39600 1 AEDT} {3984048000 36000 0 AEST} {4000377600 39600 1 AEDT} {4016102400 36000 0 AEST} {4031827200 39600 1 AEDT} {4047552000 36000 0 AEST} {4063276800 39600 1 AEDT} {4079001600 36000 0 AEST} {4094726400 39600 1 AEDT} } tcl8.6.5/library/tzdata/Australia/Adelaide0000644000175000017500000001764312663660066020076 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Adelaide) { {-9223372036854775808 33260 0 LMT} {-2364110060 32400 0 ACST} {-2230189200 34200 0 ACST} {-1672565340 37800 1 ACDT} {-1665390600 34200 0 ACST} {-883639800 37800 1 ACDT} {-876126600 34200 0 ACST} {-860398200 37800 1 ACDT} {-844677000 34200 0 ACST} {-828343800 37800 1 ACDT} {-813227400 34200 0 ACST} {31501800 34200 0 ACST} {57688200 37800 1 ACDT} {67969800 34200 0 ACST} {89137800 37800 1 ACDT} {100024200 34200 0 ACST} {120587400 37800 1 ACDT} {131473800 34200 0 ACST} {152037000 37800 1 ACDT} {162923400 34200 0 ACST} {183486600 37800 1 ACDT} {194977800 34200 0 ACST} {215541000 37800 1 ACDT} {226427400 34200 0 ACST} {246990600 37800 1 ACDT} {257877000 34200 0 ACST} {278440200 37800 1 ACDT} {289326600 34200 0 ACST} {309889800 37800 1 ACDT} {320776200 34200 0 ACST} {341339400 37800 1 ACDT} {352225800 34200 0 ACST} {372789000 37800 1 ACDT} {384280200 34200 0 ACST} {404843400 37800 1 ACDT} {415729800 34200 0 ACST} {436293000 37800 1 ACDT} {447179400 34200 0 ACST} {467742600 37800 1 ACDT} {478629000 34200 0 ACST} {499192200 37800 1 ACDT} {511288200 34200 0 ACST} {530037000 37800 1 ACDT} {542737800 34200 0 ACST} {562091400 37800 1 ACDT} {574792200 34200 0 ACST} {594145800 37800 1 ACDT} {606241800 34200 0 ACST} {625595400 37800 1 ACDT} {637691400 34200 0 ACST} {657045000 37800 1 ACDT} {667931400 34200 0 ACST} {688494600 37800 1 ACDT} {701195400 34200 0 ACST} {719944200 37800 1 ACDT} {731435400 34200 0 ACST} {751998600 37800 1 ACDT} {764094600 34200 0 ACST} {783448200 37800 1 ACDT} {796149000 34200 0 ACST} {814897800 37800 1 ACDT} {828203400 34200 0 ACST} {846347400 37800 1 ACDT} {859653000 34200 0 ACST} {877797000 37800 1 ACDT} {891102600 34200 0 ACST} {909246600 37800 1 ACDT} {922552200 34200 0 ACST} {941301000 37800 1 ACDT} {954001800 34200 0 ACST} {972750600 37800 1 ACDT} {985451400 34200 0 ACST} {1004200200 37800 1 ACDT} {1017505800 34200 0 ACST} {1035649800 37800 1 ACDT} {1048955400 34200 0 ACST} {1067099400 37800 1 ACDT} {1080405000 34200 0 ACST} {1099153800 37800 1 ACDT} {1111854600 34200 0 ACST} {1130603400 37800 1 ACDT} {1143909000 34200 0 ACST} {1162053000 37800 1 ACDT} {1174753800 34200 0 ACST} {1193502600 37800 1 ACDT} {1207413000 34200 0 ACST} {1223137800 37800 1 ACDT} {1238862600 34200 0 ACST} {1254587400 37800 1 ACDT} {1270312200 34200 0 ACST} {1286037000 37800 1 ACDT} {1301761800 34200 0 ACST} {1317486600 37800 1 ACDT} {1333211400 34200 0 ACST} {1349541000 37800 1 ACDT} {1365265800 34200 0 ACST} {1380990600 37800 1 ACDT} {1396715400 34200 0 ACST} {1412440200 37800 1 ACDT} {1428165000 34200 0 ACST} {1443889800 37800 1 ACDT} {1459614600 34200 0 ACST} {1475339400 37800 1 ACDT} {1491064200 34200 0 ACST} {1506789000 37800 1 ACDT} {1522513800 34200 0 ACST} {1538843400 37800 1 ACDT} {1554568200 34200 0 ACST} {1570293000 37800 1 ACDT} {1586017800 34200 0 ACST} {1601742600 37800 1 ACDT} {1617467400 34200 0 ACST} {1633192200 37800 1 ACDT} {1648917000 34200 0 ACST} {1664641800 37800 1 ACDT} {1680366600 34200 0 ACST} {1696091400 37800 1 ACDT} {1712421000 34200 0 ACST} {1728145800 37800 1 ACDT} {1743870600 34200 0 ACST} {1759595400 37800 1 ACDT} {1775320200 34200 0 ACST} {1791045000 37800 1 ACDT} {1806769800 34200 0 ACST} {1822494600 37800 1 ACDT} {1838219400 34200 0 ACST} {1853944200 37800 1 ACDT} {1869669000 34200 0 ACST} {1885998600 37800 1 ACDT} {1901723400 34200 0 ACST} {1917448200 37800 1 ACDT} {1933173000 34200 0 ACST} {1948897800 37800 1 ACDT} {1964622600 34200 0 ACST} {1980347400 37800 1 ACDT} {1996072200 34200 0 ACST} {2011797000 37800 1 ACDT} {2027521800 34200 0 ACST} {2043246600 37800 1 ACDT} {2058971400 34200 0 ACST} {2075301000 37800 1 ACDT} {2091025800 34200 0 ACST} {2106750600 37800 1 ACDT} {2122475400 34200 0 ACST} {2138200200 37800 1 ACDT} {2153925000 34200 0 ACST} {2169649800 37800 1 ACDT} {2185374600 34200 0 ACST} {2201099400 37800 1 ACDT} {2216824200 34200 0 ACST} {2233153800 37800 1 ACDT} {2248878600 34200 0 ACST} {2264603400 37800 1 ACDT} {2280328200 34200 0 ACST} {2296053000 37800 1 ACDT} {2311777800 34200 0 ACST} {2327502600 37800 1 ACDT} {2343227400 34200 0 ACST} {2358952200 37800 1 ACDT} {2374677000 34200 0 ACST} {2390401800 37800 1 ACDT} {2406126600 34200 0 ACST} {2422456200 37800 1 ACDT} {2438181000 34200 0 ACST} {2453905800 37800 1 ACDT} {2469630600 34200 0 ACST} {2485355400 37800 1 ACDT} {2501080200 34200 0 ACST} {2516805000 37800 1 ACDT} {2532529800 34200 0 ACST} {2548254600 37800 1 ACDT} {2563979400 34200 0 ACST} {2579704200 37800 1 ACDT} {2596033800 34200 0 ACST} {2611758600 37800 1 ACDT} {2627483400 34200 0 ACST} {2643208200 37800 1 ACDT} {2658933000 34200 0 ACST} {2674657800 37800 1 ACDT} {2690382600 34200 0 ACST} {2706107400 37800 1 ACDT} {2721832200 34200 0 ACST} {2737557000 37800 1 ACDT} {2753281800 34200 0 ACST} {2769611400 37800 1 ACDT} {2785336200 34200 0 ACST} {2801061000 37800 1 ACDT} {2816785800 34200 0 ACST} {2832510600 37800 1 ACDT} {2848235400 34200 0 ACST} {2863960200 37800 1 ACDT} {2879685000 34200 0 ACST} {2895409800 37800 1 ACDT} {2911134600 34200 0 ACST} {2926859400 37800 1 ACDT} {2942584200 34200 0 ACST} {2958913800 37800 1 ACDT} {2974638600 34200 0 ACST} {2990363400 37800 1 ACDT} {3006088200 34200 0 ACST} {3021813000 37800 1 ACDT} {3037537800 34200 0 ACST} {3053262600 37800 1 ACDT} {3068987400 34200 0 ACST} {3084712200 37800 1 ACDT} {3100437000 34200 0 ACST} {3116766600 37800 1 ACDT} {3132491400 34200 0 ACST} {3148216200 37800 1 ACDT} {3163941000 34200 0 ACST} {3179665800 37800 1 ACDT} {3195390600 34200 0 ACST} {3211115400 37800 1 ACDT} {3226840200 34200 0 ACST} {3242565000 37800 1 ACDT} {3258289800 34200 0 ACST} {3274014600 37800 1 ACDT} {3289739400 34200 0 ACST} {3306069000 37800 1 ACDT} {3321793800 34200 0 ACST} {3337518600 37800 1 ACDT} {3353243400 34200 0 ACST} {3368968200 37800 1 ACDT} {3384693000 34200 0 ACST} {3400417800 37800 1 ACDT} {3416142600 34200 0 ACST} {3431867400 37800 1 ACDT} {3447592200 34200 0 ACST} {3463317000 37800 1 ACDT} {3479646600 34200 0 ACST} {3495371400 37800 1 ACDT} {3511096200 34200 0 ACST} {3526821000 37800 1 ACDT} {3542545800 34200 0 ACST} {3558270600 37800 1 ACDT} {3573995400 34200 0 ACST} {3589720200 37800 1 ACDT} {3605445000 34200 0 ACST} {3621169800 37800 1 ACDT} {3636894600 34200 0 ACST} {3653224200 37800 1 ACDT} {3668949000 34200 0 ACST} {3684673800 37800 1 ACDT} {3700398600 34200 0 ACST} {3716123400 37800 1 ACDT} {3731848200 34200 0 ACST} {3747573000 37800 1 ACDT} {3763297800 34200 0 ACST} {3779022600 37800 1 ACDT} {3794747400 34200 0 ACST} {3810472200 37800 1 ACDT} {3826197000 34200 0 ACST} {3842526600 37800 1 ACDT} {3858251400 34200 0 ACST} {3873976200 37800 1 ACDT} {3889701000 34200 0 ACST} {3905425800 37800 1 ACDT} {3921150600 34200 0 ACST} {3936875400 37800 1 ACDT} {3952600200 34200 0 ACST} {3968325000 37800 1 ACDT} {3984049800 34200 0 ACST} {4000379400 37800 1 ACDT} {4016104200 34200 0 ACST} {4031829000 37800 1 ACDT} {4047553800 34200 0 ACST} {4063278600 37800 1 ACDT} {4079003400 34200 0 ACST} {4094728200 37800 1 ACDT} } tcl8.6.5/library/tzdata/Australia/North0000644000175000017500000000027312661614722017463 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Australia/Darwin)]} { LoadTimeZoneFile Australia/Darwin } set TZData(:Australia/North) $TZData(:Australia/Darwin) tcl8.6.5/library/tzdata/Australia/Broken_Hill0000644000175000017500000001774212663660066020576 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Broken_Hill) { {-9223372036854775808 33948 0 LMT} {-2364110748 36000 0 AEST} {-2314951200 32400 0 ACST} {-2230189200 34200 0 ACST} {-1672565340 37800 1 ACDT} {-1665390600 34200 0 ACST} {-883639800 37800 1 ACDT} {-876126600 34200 0 ACST} {-860398200 37800 1 ACDT} {-844677000 34200 0 ACST} {-828343800 37800 1 ACDT} {-813227400 34200 0 ACST} {31501800 34200 0 ACST} {57688200 37800 1 ACDT} {67969800 34200 0 ACST} {89137800 37800 1 ACDT} {100024200 34200 0 ACST} {120587400 37800 1 ACDT} {131473800 34200 0 ACST} {152037000 37800 1 ACDT} {162923400 34200 0 ACST} {183486600 37800 1 ACDT} {194977800 34200 0 ACST} {215541000 37800 1 ACDT} {226427400 34200 0 ACST} {246990600 37800 1 ACDT} {257877000 34200 0 ACST} {278440200 37800 1 ACDT} {289326600 34200 0 ACST} {309889800 37800 1 ACDT} {320776200 34200 0 ACST} {341339400 37800 1 ACDT} {352225800 34200 0 ACST} {372789000 37800 1 ACDT} {386699400 34200 0 ACST} {404843400 37800 1 ACDT} {415729800 34200 0 ACST} {436293000 37800 1 ACDT} {447179400 34200 0 ACST} {467742600 37800 1 ACDT} {478629000 34200 0 ACST} {499192200 37800 1 ACDT} {511288200 34200 0 ACST} {530037000 37800 1 ACDT} {542737800 34200 0 ACST} {562091400 37800 1 ACDT} {574792200 34200 0 ACST} {594145800 37800 1 ACDT} {606241800 34200 0 ACST} {625595400 37800 1 ACDT} {636481800 34200 0 ACST} {657045000 37800 1 ACDT} {667931400 34200 0 ACST} {688494600 37800 1 ACDT} {699381000 34200 0 ACST} {719944200 37800 1 ACDT} {731435400 34200 0 ACST} {751998600 37800 1 ACDT} {762885000 34200 0 ACST} {783448200 37800 1 ACDT} {794334600 34200 0 ACST} {814897800 37800 1 ACDT} {828203400 34200 0 ACST} {846347400 37800 1 ACDT} {859653000 34200 0 ACST} {877797000 37800 1 ACDT} {891102600 34200 0 ACST} {909246600 37800 1 ACDT} {922552200 34200 0 ACST} {941301000 37800 1 ACDT} {946647000 37800 0 ACST} {954001800 34200 0 ACST} {972750600 37800 1 ACDT} {985451400 34200 0 ACST} {1004200200 37800 1 ACDT} {1017505800 34200 0 ACST} {1035649800 37800 1 ACDT} {1048955400 34200 0 ACST} {1067099400 37800 1 ACDT} {1080405000 34200 0 ACST} {1099153800 37800 1 ACDT} {1111854600 34200 0 ACST} {1130603400 37800 1 ACDT} {1143909000 34200 0 ACST} {1162053000 37800 1 ACDT} {1174753800 34200 0 ACST} {1193502600 37800 1 ACDT} {1207413000 34200 0 ACST} {1223137800 37800 1 ACDT} {1238862600 34200 0 ACST} {1254587400 37800 1 ACDT} {1270312200 34200 0 ACST} {1286037000 37800 1 ACDT} {1301761800 34200 0 ACST} {1317486600 37800 1 ACDT} {1333211400 34200 0 ACST} {1349541000 37800 1 ACDT} {1365265800 34200 0 ACST} {1380990600 37800 1 ACDT} {1396715400 34200 0 ACST} {1412440200 37800 1 ACDT} {1428165000 34200 0 ACST} {1443889800 37800 1 ACDT} {1459614600 34200 0 ACST} {1475339400 37800 1 ACDT} {1491064200 34200 0 ACST} {1506789000 37800 1 ACDT} {1522513800 34200 0 ACST} {1538843400 37800 1 ACDT} {1554568200 34200 0 ACST} {1570293000 37800 1 ACDT} {1586017800 34200 0 ACST} {1601742600 37800 1 ACDT} {1617467400 34200 0 ACST} {1633192200 37800 1 ACDT} {1648917000 34200 0 ACST} {1664641800 37800 1 ACDT} {1680366600 34200 0 ACST} {1696091400 37800 1 ACDT} {1712421000 34200 0 ACST} {1728145800 37800 1 ACDT} {1743870600 34200 0 ACST} {1759595400 37800 1 ACDT} {1775320200 34200 0 ACST} {1791045000 37800 1 ACDT} {1806769800 34200 0 ACST} {1822494600 37800 1 ACDT} {1838219400 34200 0 ACST} {1853944200 37800 1 ACDT} {1869669000 34200 0 ACST} {1885998600 37800 1 ACDT} {1901723400 34200 0 ACST} {1917448200 37800 1 ACDT} {1933173000 34200 0 ACST} {1948897800 37800 1 ACDT} {1964622600 34200 0 ACST} {1980347400 37800 1 ACDT} {1996072200 34200 0 ACST} {2011797000 37800 1 ACDT} {2027521800 34200 0 ACST} {2043246600 37800 1 ACDT} {2058971400 34200 0 ACST} {2075301000 37800 1 ACDT} {2091025800 34200 0 ACST} {2106750600 37800 1 ACDT} {2122475400 34200 0 ACST} {2138200200 37800 1 ACDT} {2153925000 34200 0 ACST} {2169649800 37800 1 ACDT} {2185374600 34200 0 ACST} {2201099400 37800 1 ACDT} {2216824200 34200 0 ACST} {2233153800 37800 1 ACDT} {2248878600 34200 0 ACST} {2264603400 37800 1 ACDT} {2280328200 34200 0 ACST} {2296053000 37800 1 ACDT} {2311777800 34200 0 ACST} {2327502600 37800 1 ACDT} {2343227400 34200 0 ACST} {2358952200 37800 1 ACDT} {2374677000 34200 0 ACST} {2390401800 37800 1 ACDT} {2406126600 34200 0 ACST} {2422456200 37800 1 ACDT} {2438181000 34200 0 ACST} {2453905800 37800 1 ACDT} {2469630600 34200 0 ACST} {2485355400 37800 1 ACDT} {2501080200 34200 0 ACST} {2516805000 37800 1 ACDT} {2532529800 34200 0 ACST} {2548254600 37800 1 ACDT} {2563979400 34200 0 ACST} {2579704200 37800 1 ACDT} {2596033800 34200 0 ACST} {2611758600 37800 1 ACDT} {2627483400 34200 0 ACST} {2643208200 37800 1 ACDT} {2658933000 34200 0 ACST} {2674657800 37800 1 ACDT} {2690382600 34200 0 ACST} {2706107400 37800 1 ACDT} {2721832200 34200 0 ACST} {2737557000 37800 1 ACDT} {2753281800 34200 0 ACST} {2769611400 37800 1 ACDT} {2785336200 34200 0 ACST} {2801061000 37800 1 ACDT} {2816785800 34200 0 ACST} {2832510600 37800 1 ACDT} {2848235400 34200 0 ACST} {2863960200 37800 1 ACDT} {2879685000 34200 0 ACST} {2895409800 37800 1 ACDT} {2911134600 34200 0 ACST} {2926859400 37800 1 ACDT} {2942584200 34200 0 ACST} {2958913800 37800 1 ACDT} {2974638600 34200 0 ACST} {2990363400 37800 1 ACDT} {3006088200 34200 0 ACST} {3021813000 37800 1 ACDT} {3037537800 34200 0 ACST} {3053262600 37800 1 ACDT} {3068987400 34200 0 ACST} {3084712200 37800 1 ACDT} {3100437000 34200 0 ACST} {3116766600 37800 1 ACDT} {3132491400 34200 0 ACST} {3148216200 37800 1 ACDT} {3163941000 34200 0 ACST} {3179665800 37800 1 ACDT} {3195390600 34200 0 ACST} {3211115400 37800 1 ACDT} {3226840200 34200 0 ACST} {3242565000 37800 1 ACDT} {3258289800 34200 0 ACST} {3274014600 37800 1 ACDT} {3289739400 34200 0 ACST} {3306069000 37800 1 ACDT} {3321793800 34200 0 ACST} {3337518600 37800 1 ACDT} {3353243400 34200 0 ACST} {3368968200 37800 1 ACDT} {3384693000 34200 0 ACST} {3400417800 37800 1 ACDT} {3416142600 34200 0 ACST} {3431867400 37800 1 ACDT} {3447592200 34200 0 ACST} {3463317000 37800 1 ACDT} {3479646600 34200 0 ACST} {3495371400 37800 1 ACDT} {3511096200 34200 0 ACST} {3526821000 37800 1 ACDT} {3542545800 34200 0 ACST} {3558270600 37800 1 ACDT} {3573995400 34200 0 ACST} {3589720200 37800 1 ACDT} {3605445000 34200 0 ACST} {3621169800 37800 1 ACDT} {3636894600 34200 0 ACST} {3653224200 37800 1 ACDT} {3668949000 34200 0 ACST} {3684673800 37800 1 ACDT} {3700398600 34200 0 ACST} {3716123400 37800 1 ACDT} {3731848200 34200 0 ACST} {3747573000 37800 1 ACDT} {3763297800 34200 0 ACST} {3779022600 37800 1 ACDT} {3794747400 34200 0 ACST} {3810472200 37800 1 ACDT} {3826197000 34200 0 ACST} {3842526600 37800 1 ACDT} {3858251400 34200 0 ACST} {3873976200 37800 1 ACDT} {3889701000 34200 0 ACST} {3905425800 37800 1 ACDT} {3921150600 34200 0 ACST} {3936875400 37800 1 ACDT} {3952600200 34200 0 ACST} {3968325000 37800 1 ACDT} {3984049800 34200 0 ACST} {4000379400 37800 1 ACDT} {4016104200 34200 0 ACST} {4031829000 37800 1 ACDT} {4047553800 34200 0 ACST} {4063278600 37800 1 ACDT} {4079003400 34200 0 ACST} {4094728200 37800 1 ACDT} } tcl8.6.5/library/tzdata/Australia/Melbourne0000644000175000017500000001760512663660066020334 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Melbourne) { {-9223372036854775808 34792 0 LMT} {-2364111592 36000 0 AEST} {-1672567140 39600 1 AEDT} {-1665392400 36000 0 AEST} {-883641600 39600 1 AEDT} {-876128400 36000 0 AEST} {-860400000 39600 1 AEDT} {-844678800 36000 0 AEST} {-828345600 39600 1 AEDT} {-813229200 36000 0 AEST} {31500000 36000 0 AEST} {57686400 39600 1 AEDT} {67968000 36000 0 AEST} {89136000 39600 1 AEDT} {100022400 36000 0 AEST} {120585600 39600 1 AEDT} {131472000 36000 0 AEST} {152035200 39600 1 AEDT} {162921600 36000 0 AEST} {183484800 39600 1 AEDT} {194976000 36000 0 AEST} {215539200 39600 1 AEDT} {226425600 36000 0 AEST} {246988800 39600 1 AEDT} {257875200 36000 0 AEST} {278438400 39600 1 AEDT} {289324800 36000 0 AEST} {309888000 39600 1 AEDT} {320774400 36000 0 AEST} {341337600 39600 1 AEDT} {352224000 36000 0 AEST} {372787200 39600 1 AEDT} {384278400 36000 0 AEST} {404841600 39600 1 AEDT} {415728000 36000 0 AEST} {436291200 39600 1 AEDT} {447177600 36000 0 AEST} {467740800 39600 1 AEDT} {478627200 36000 0 AEST} {499190400 39600 1 AEDT} {511286400 36000 0 AEST} {530035200 39600 1 AEDT} {542736000 36000 0 AEST} {561484800 39600 1 AEDT} {574790400 36000 0 AEST} {594144000 39600 1 AEDT} {606240000 36000 0 AEST} {625593600 39600 1 AEDT} {637689600 36000 0 AEST} {657043200 39600 1 AEDT} {667929600 36000 0 AEST} {688492800 39600 1 AEDT} {699379200 36000 0 AEST} {719942400 39600 1 AEDT} {731433600 36000 0 AEST} {751996800 39600 1 AEDT} {762883200 36000 0 AEST} {783446400 39600 1 AEDT} {796147200 36000 0 AEST} {814896000 39600 1 AEDT} {828201600 36000 0 AEST} {846345600 39600 1 AEDT} {859651200 36000 0 AEST} {877795200 39600 1 AEDT} {891100800 36000 0 AEST} {909244800 39600 1 AEDT} {922550400 36000 0 AEST} {941299200 39600 1 AEDT} {954000000 36000 0 AEST} {967305600 39600 1 AEDT} {985449600 36000 0 AEST} {1004198400 39600 1 AEDT} {1017504000 36000 0 AEST} {1035648000 39600 1 AEDT} {1048953600 36000 0 AEST} {1067097600 39600 1 AEDT} {1080403200 36000 0 AEST} {1099152000 39600 1 AEDT} {1111852800 36000 0 AEST} {1130601600 39600 1 AEDT} {1143907200 36000 0 AEST} {1162051200 39600 1 AEDT} {1174752000 36000 0 AEST} {1193500800 39600 1 AEDT} {1207411200 36000 0 AEST} {1223136000 39600 1 AEDT} {1238860800 36000 0 AEST} {1254585600 39600 1 AEDT} {1270310400 36000 0 AEST} {1286035200 39600 1 AEDT} {1301760000 36000 0 AEST} {1317484800 39600 1 AEDT} {1333209600 36000 0 AEST} {1349539200 39600 1 AEDT} {1365264000 36000 0 AEST} {1380988800 39600 1 AEDT} {1396713600 36000 0 AEST} {1412438400 39600 1 AEDT} {1428163200 36000 0 AEST} {1443888000 39600 1 AEDT} {1459612800 36000 0 AEST} {1475337600 39600 1 AEDT} {1491062400 36000 0 AEST} {1506787200 39600 1 AEDT} {1522512000 36000 0 AEST} {1538841600 39600 1 AEDT} {1554566400 36000 0 AEST} {1570291200 39600 1 AEDT} {1586016000 36000 0 AEST} {1601740800 39600 1 AEDT} {1617465600 36000 0 AEST} {1633190400 39600 1 AEDT} {1648915200 36000 0 AEST} {1664640000 39600 1 AEDT} {1680364800 36000 0 AEST} {1696089600 39600 1 AEDT} {1712419200 36000 0 AEST} {1728144000 39600 1 AEDT} {1743868800 36000 0 AEST} {1759593600 39600 1 AEDT} {1775318400 36000 0 AEST} {1791043200 39600 1 AEDT} {1806768000 36000 0 AEST} {1822492800 39600 1 AEDT} {1838217600 36000 0 AEST} {1853942400 39600 1 AEDT} {1869667200 36000 0 AEST} {1885996800 39600 1 AEDT} {1901721600 36000 0 AEST} {1917446400 39600 1 AEDT} {1933171200 36000 0 AEST} {1948896000 39600 1 AEDT} {1964620800 36000 0 AEST} {1980345600 39600 1 AEDT} {1996070400 36000 0 AEST} {2011795200 39600 1 AEDT} {2027520000 36000 0 AEST} {2043244800 39600 1 AEDT} {2058969600 36000 0 AEST} {2075299200 39600 1 AEDT} {2091024000 36000 0 AEST} {2106748800 39600 1 AEDT} {2122473600 36000 0 AEST} {2138198400 39600 1 AEDT} {2153923200 36000 0 AEST} {2169648000 39600 1 AEDT} {2185372800 36000 0 AEST} {2201097600 39600 1 AEDT} {2216822400 36000 0 AEST} {2233152000 39600 1 AEDT} {2248876800 36000 0 AEST} {2264601600 39600 1 AEDT} {2280326400 36000 0 AEST} {2296051200 39600 1 AEDT} {2311776000 36000 0 AEST} {2327500800 39600 1 AEDT} {2343225600 36000 0 AEST} {2358950400 39600 1 AEDT} {2374675200 36000 0 AEST} {2390400000 39600 1 AEDT} {2406124800 36000 0 AEST} {2422454400 39600 1 AEDT} {2438179200 36000 0 AEST} {2453904000 39600 1 AEDT} {2469628800 36000 0 AEST} {2485353600 39600 1 AEDT} {2501078400 36000 0 AEST} {2516803200 39600 1 AEDT} {2532528000 36000 0 AEST} {2548252800 39600 1 AEDT} {2563977600 36000 0 AEST} {2579702400 39600 1 AEDT} {2596032000 36000 0 AEST} {2611756800 39600 1 AEDT} {2627481600 36000 0 AEST} {2643206400 39600 1 AEDT} {2658931200 36000 0 AEST} {2674656000 39600 1 AEDT} {2690380800 36000 0 AEST} {2706105600 39600 1 AEDT} {2721830400 36000 0 AEST} {2737555200 39600 1 AEDT} {2753280000 36000 0 AEST} {2769609600 39600 1 AEDT} {2785334400 36000 0 AEST} {2801059200 39600 1 AEDT} {2816784000 36000 0 AEST} {2832508800 39600 1 AEDT} {2848233600 36000 0 AEST} {2863958400 39600 1 AEDT} {2879683200 36000 0 AEST} {2895408000 39600 1 AEDT} {2911132800 36000 0 AEST} {2926857600 39600 1 AEDT} {2942582400 36000 0 AEST} {2958912000 39600 1 AEDT} {2974636800 36000 0 AEST} {2990361600 39600 1 AEDT} {3006086400 36000 0 AEST} {3021811200 39600 1 AEDT} {3037536000 36000 0 AEST} {3053260800 39600 1 AEDT} {3068985600 36000 0 AEST} {3084710400 39600 1 AEDT} {3100435200 36000 0 AEST} {3116764800 39600 1 AEDT} {3132489600 36000 0 AEST} {3148214400 39600 1 AEDT} {3163939200 36000 0 AEST} {3179664000 39600 1 AEDT} {3195388800 36000 0 AEST} {3211113600 39600 1 AEDT} {3226838400 36000 0 AEST} {3242563200 39600 1 AEDT} {3258288000 36000 0 AEST} {3274012800 39600 1 AEDT} {3289737600 36000 0 AEST} {3306067200 39600 1 AEDT} {3321792000 36000 0 AEST} {3337516800 39600 1 AEDT} {3353241600 36000 0 AEST} {3368966400 39600 1 AEDT} {3384691200 36000 0 AEST} {3400416000 39600 1 AEDT} {3416140800 36000 0 AEST} {3431865600 39600 1 AEDT} {3447590400 36000 0 AEST} {3463315200 39600 1 AEDT} {3479644800 36000 0 AEST} {3495369600 39600 1 AEDT} {3511094400 36000 0 AEST} {3526819200 39600 1 AEDT} {3542544000 36000 0 AEST} {3558268800 39600 1 AEDT} {3573993600 36000 0 AEST} {3589718400 39600 1 AEDT} {3605443200 36000 0 AEST} {3621168000 39600 1 AEDT} {3636892800 36000 0 AEST} {3653222400 39600 1 AEDT} {3668947200 36000 0 AEST} {3684672000 39600 1 AEDT} {3700396800 36000 0 AEST} {3716121600 39600 1 AEDT} {3731846400 36000 0 AEST} {3747571200 39600 1 AEDT} {3763296000 36000 0 AEST} {3779020800 39600 1 AEDT} {3794745600 36000 0 AEST} {3810470400 39600 1 AEDT} {3826195200 36000 0 AEST} {3842524800 39600 1 AEDT} {3858249600 36000 0 AEST} {3873974400 39600 1 AEDT} {3889699200 36000 0 AEST} {3905424000 39600 1 AEDT} {3921148800 36000 0 AEST} {3936873600 39600 1 AEDT} {3952598400 36000 0 AEST} {3968323200 39600 1 AEDT} {3984048000 36000 0 AEST} {4000377600 39600 1 AEDT} {4016102400 36000 0 AEST} {4031827200 39600 1 AEDT} {4047552000 36000 0 AEST} {4063276800 39600 1 AEDT} {4079001600 36000 0 AEST} {4094726400 39600 1 AEDT} } tcl8.6.5/library/tzdata/Australia/LHI0000644000175000017500000000030212661614722016776 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Australia/Lord_Howe)]} { LoadTimeZoneFile Australia/Lord_Howe } set TZData(:Australia/LHI) $TZData(:Australia/Lord_Howe) tcl8.6.5/library/tzdata/Australia/Eucla0000644000175000017500000000133612663660066017427 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Eucla) { {-9223372036854775808 30928 0 LMT} {-2337928528 31500 0 ACWST} {-1672562640 35100 1 ACWDT} {-1665387900 31500 0 ACWST} {-883637100 35100 1 ACWDT} {-876123900 31500 0 ACWST} {-860395500 35100 1 ACWDT} {-844674300 31500 0 ACWST} {-836473500 35100 0 ACWST} {152039700 35100 1 ACWDT} {162926100 31500 0 ACWST} {436295700 35100 1 ACWDT} {447182100 31500 0 ACWST} {690311700 35100 1 ACWDT} {699383700 31500 0 ACWST} {1165079700 35100 1 ACWDT} {1174756500 31500 0 ACWST} {1193505300 35100 1 ACWDT} {1206810900 31500 0 ACWST} {1224954900 35100 1 ACWDT} {1238260500 31500 0 ACWST} } tcl8.6.5/library/tzdata/Australia/ACT0000644000175000017500000000027112661614722016776 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Australia/Sydney)]} { LoadTimeZoneFile Australia/Sydney } set TZData(:Australia/ACT) $TZData(:Australia/Sydney) tcl8.6.5/library/tzdata/Australia/West0000644000175000017500000000026712661614722017316 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Australia/Perth)]} { LoadTimeZoneFile Australia/Perth } set TZData(:Australia/West) $TZData(:Australia/Perth) tcl8.6.5/library/tzdata/Australia/Lindeman0000644000175000017500000000143412663660066020124 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Lindeman) { {-9223372036854775808 35756 0 LMT} {-2366790956 36000 0 AEST} {-1672567140 39600 1 AEDT} {-1665392400 36000 0 AEST} {-883641600 39600 1 AEDT} {-876128400 36000 0 AEST} {-860400000 39600 1 AEDT} {-844678800 36000 0 AEST} {-828345600 39600 1 AEDT} {-813229200 36000 0 AEST} {31500000 36000 0 AEST} {57686400 39600 1 AEDT} {67968000 36000 0 AEST} {625593600 39600 1 AEDT} {636480000 36000 0 AEST} {657043200 39600 1 AEDT} {667929600 36000 0 AEST} {688492800 39600 1 AEDT} {699379200 36000 0 AEST} {709912800 36000 0 AEST} {719942400 39600 1 AEDT} {731433600 36000 0 AEST} {751996800 39600 1 AEDT} {762883200 36000 0 AEST} } tcl8.6.5/library/tzdata/Australia/Tasmania0000644000175000017500000000027612661614722020131 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Australia/Hobart)]} { LoadTimeZoneFile Australia/Hobart } set TZData(:Australia/Tasmania) $TZData(:Australia/Hobart) tcl8.6.5/library/tzdata/Australia/Currie0000644000175000017500000001764112663660066017635 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Australia/Currie) { {-9223372036854775808 34528 0 LMT} {-2345794528 36000 0 AEST} {-1680508800 39600 1 AEDT} {-1669892400 39600 0 AEDT} {-1665392400 36000 0 AEST} {-883641600 39600 1 AEDT} {-876128400 36000 0 AEST} {-860400000 39600 1 AEDT} {-844678800 36000 0 AEST} {-828345600 39600 1 AEDT} {-813229200 36000 0 AEST} {47138400 36000 0 AEST} {57686400 39600 1 AEDT} {67968000 36000 0 AEST} {89136000 39600 1 AEDT} {100022400 36000 0 AEST} {120585600 39600 1 AEDT} {131472000 36000 0 AEST} {152035200 39600 1 AEDT} {162921600 36000 0 AEST} {183484800 39600 1 AEDT} {194976000 36000 0 AEST} {215539200 39600 1 AEDT} {226425600 36000 0 AEST} {246988800 39600 1 AEDT} {257875200 36000 0 AEST} {278438400 39600 1 AEDT} {289324800 36000 0 AEST} {309888000 39600 1 AEDT} {320774400 36000 0 AEST} {341337600 39600 1 AEDT} {352224000 36000 0 AEST} {372787200 39600 1 AEDT} {386092800 36000 0 AEST} {404841600 39600 1 AEDT} {417542400 36000 0 AEST} {436291200 39600 1 AEDT} {447177600 36000 0 AEST} {467740800 39600 1 AEDT} {478627200 36000 0 AEST} {499190400 39600 1 AEDT} {510076800 36000 0 AEST} {530035200 39600 1 AEDT} {542736000 36000 0 AEST} {562089600 39600 1 AEDT} {574790400 36000 0 AEST} {594144000 39600 1 AEDT} {606240000 36000 0 AEST} {625593600 39600 1 AEDT} {637689600 36000 0 AEST} {657043200 39600 1 AEDT} {670348800 36000 0 AEST} {686678400 39600 1 AEDT} {701798400 36000 0 AEST} {718128000 39600 1 AEDT} {733248000 36000 0 AEST} {749577600 39600 1 AEDT} {764697600 36000 0 AEST} {781027200 39600 1 AEDT} {796147200 36000 0 AEST} {812476800 39600 1 AEDT} {828201600 36000 0 AEST} {844531200 39600 1 AEDT} {859651200 36000 0 AEST} {875980800 39600 1 AEDT} {891100800 36000 0 AEST} {907430400 39600 1 AEDT} {922550400 36000 0 AEST} {938880000 39600 1 AEDT} {954000000 36000 0 AEST} {967305600 39600 1 AEDT} {985449600 36000 0 AEST} {1002384000 39600 1 AEDT} {1017504000 36000 0 AEST} {1033833600 39600 1 AEDT} {1048953600 36000 0 AEST} {1065283200 39600 1 AEDT} {1080403200 36000 0 AEST} {1096732800 39600 1 AEDT} {1111852800 36000 0 AEST} {1128182400 39600 1 AEDT} {1143907200 36000 0 AEST} {1159632000 39600 1 AEDT} {1174752000 36000 0 AEST} {1191686400 39600 1 AEDT} {1207411200 36000 0 AEST} {1223136000 39600 1 AEDT} {1238860800 36000 0 AEST} {1254585600 39600 1 AEDT} {1270310400 36000 0 AEST} {1286035200 39600 1 AEDT} {1301760000 36000 0 AEST} {1317484800 39600 1 AEDT} {1333209600 36000 0 AEST} {1349539200 39600 1 AEDT} {1365264000 36000 0 AEST} {1380988800 39600 1 AEDT} {1396713600 36000 0 AEST} {1412438400 39600 1 AEDT} {1428163200 36000 0 AEST} {1443888000 39600 1 AEDT} {1459612800 36000 0 AEST} {1475337600 39600 1 AEDT} {1491062400 36000 0 AEST} {1506787200 39600 1 AEDT} {1522512000 36000 0 AEST} {1538841600 39600 1 AEDT} {1554566400 36000 0 AEST} {1570291200 39600 1 AEDT} {1586016000 36000 0 AEST} {1601740800 39600 1 AEDT} {1617465600 36000 0 AEST} {1633190400 39600 1 AEDT} {1648915200 36000 0 AEST} {1664640000 39600 1 AEDT} {1680364800 36000 0 AEST} {1696089600 39600 1 AEDT} {1712419200 36000 0 AEST} {1728144000 39600 1 AEDT} {1743868800 36000 0 AEST} {1759593600 39600 1 AEDT} {1775318400 36000 0 AEST} {1791043200 39600 1 AEDT} {1806768000 36000 0 AEST} {1822492800 39600 1 AEDT} {1838217600 36000 0 AEST} {1853942400 39600 1 AEDT} {1869667200 36000 0 AEST} {1885996800 39600 1 AEDT} {1901721600 36000 0 AEST} {1917446400 39600 1 AEDT} {1933171200 36000 0 AEST} {1948896000 39600 1 AEDT} {1964620800 36000 0 AEST} {1980345600 39600 1 AEDT} {1996070400 36000 0 AEST} {2011795200 39600 1 AEDT} {2027520000 36000 0 AEST} {2043244800 39600 1 AEDT} {2058969600 36000 0 AEST} {2075299200 39600 1 AEDT} {2091024000 36000 0 AEST} {2106748800 39600 1 AEDT} {2122473600 36000 0 AEST} {2138198400 39600 1 AEDT} {2153923200 36000 0 AEST} {2169648000 39600 1 AEDT} {2185372800 36000 0 AEST} {2201097600 39600 1 AEDT} {2216822400 36000 0 AEST} {2233152000 39600 1 AEDT} {2248876800 36000 0 AEST} {2264601600 39600 1 AEDT} {2280326400 36000 0 AEST} {2296051200 39600 1 AEDT} {2311776000 36000 0 AEST} {2327500800 39600 1 AEDT} {2343225600 36000 0 AEST} {2358950400 39600 1 AEDT} {2374675200 36000 0 AEST} {2390400000 39600 1 AEDT} {2406124800 36000 0 AEST} {2422454400 39600 1 AEDT} {2438179200 36000 0 AEST} {2453904000 39600 1 AEDT} {2469628800 36000 0 AEST} {2485353600 39600 1 AEDT} {2501078400 36000 0 AEST} {2516803200 39600 1 AEDT} {2532528000 36000 0 AEST} {2548252800 39600 1 AEDT} {2563977600 36000 0 AEST} {2579702400 39600 1 AEDT} {2596032000 36000 0 AEST} {2611756800 39600 1 AEDT} {2627481600 36000 0 AEST} {2643206400 39600 1 AEDT} {2658931200 36000 0 AEST} {2674656000 39600 1 AEDT} {2690380800 36000 0 AEST} {2706105600 39600 1 AEDT} {2721830400 36000 0 AEST} {2737555200 39600 1 AEDT} {2753280000 36000 0 AEST} {2769609600 39600 1 AEDT} {2785334400 36000 0 AEST} {2801059200 39600 1 AEDT} {2816784000 36000 0 AEST} {2832508800 39600 1 AEDT} {2848233600 36000 0 AEST} {2863958400 39600 1 AEDT} {2879683200 36000 0 AEST} {2895408000 39600 1 AEDT} {2911132800 36000 0 AEST} {2926857600 39600 1 AEDT} {2942582400 36000 0 AEST} {2958912000 39600 1 AEDT} {2974636800 36000 0 AEST} {2990361600 39600 1 AEDT} {3006086400 36000 0 AEST} {3021811200 39600 1 AEDT} {3037536000 36000 0 AEST} {3053260800 39600 1 AEDT} {3068985600 36000 0 AEST} {3084710400 39600 1 AEDT} {3100435200 36000 0 AEST} {3116764800 39600 1 AEDT} {3132489600 36000 0 AEST} {3148214400 39600 1 AEDT} {3163939200 36000 0 AEST} {3179664000 39600 1 AEDT} {3195388800 36000 0 AEST} {3211113600 39600 1 AEDT} {3226838400 36000 0 AEST} {3242563200 39600 1 AEDT} {3258288000 36000 0 AEST} {3274012800 39600 1 AEDT} {3289737600 36000 0 AEST} {3306067200 39600 1 AEDT} {3321792000 36000 0 AEST} {3337516800 39600 1 AEDT} {3353241600 36000 0 AEST} {3368966400 39600 1 AEDT} {3384691200 36000 0 AEST} {3400416000 39600 1 AEDT} {3416140800 36000 0 AEST} {3431865600 39600 1 AEDT} {3447590400 36000 0 AEST} {3463315200 39600 1 AEDT} {3479644800 36000 0 AEST} {3495369600 39600 1 AEDT} {3511094400 36000 0 AEST} {3526819200 39600 1 AEDT} {3542544000 36000 0 AEST} {3558268800 39600 1 AEDT} {3573993600 36000 0 AEST} {3589718400 39600 1 AEDT} {3605443200 36000 0 AEST} {3621168000 39600 1 AEDT} {3636892800 36000 0 AEST} {3653222400 39600 1 AEDT} {3668947200 36000 0 AEST} {3684672000 39600 1 AEDT} {3700396800 36000 0 AEST} {3716121600 39600 1 AEDT} {3731846400 36000 0 AEST} {3747571200 39600 1 AEDT} {3763296000 36000 0 AEST} {3779020800 39600 1 AEDT} {3794745600 36000 0 AEST} {3810470400 39600 1 AEDT} {3826195200 36000 0 AEST} {3842524800 39600 1 AEDT} {3858249600 36000 0 AEST} {3873974400 39600 1 AEDT} {3889699200 36000 0 AEST} {3905424000 39600 1 AEDT} {3921148800 36000 0 AEST} {3936873600 39600 1 AEDT} {3952598400 36000 0 AEST} {3968323200 39600 1 AEDT} {3984048000 36000 0 AEST} {4000377600 39600 1 AEDT} {4016102400 36000 0 AEST} {4031827200 39600 1 AEDT} {4047552000 36000 0 AEST} {4063276800 39600 1 AEDT} {4079001600 36000 0 AEST} {4094726400 39600 1 AEDT} } tcl8.6.5/library/tzdata/Australia/South0000644000175000017500000000030112661614722017463 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Australia/Adelaide)]} { LoadTimeZoneFile Australia/Adelaide } set TZData(:Australia/South) $TZData(:Australia/Adelaide) tcl8.6.5/library/tzdata/Kwajalein0000644000175000017500000000027012661614722016346 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Kwajalein)]} { LoadTimeZoneFile Pacific/Kwajalein } set TZData(:Kwajalein) $TZData(:Pacific/Kwajalein) tcl8.6.5/library/tzdata/CET0000644000175000017500000001645712663653132015072 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:CET) { {-9223372036854775808 3600 0 CET} {-1693706400 7200 1 CEST} {-1680483600 3600 0 CET} {-1663455600 7200 1 CEST} {-1650150000 3600 0 CET} {-1632006000 7200 1 CEST} {-1618700400 3600 0 CET} {-938905200 7200 1 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} {-796777200 3600 0 CET} {-781052400 7200 1 CEST} {-766623600 3600 0 CET} {228877200 7200 1 CEST} {243997200 3600 0 CET} {260326800 7200 1 CEST} {276051600 3600 0 CET} {291776400 7200 1 CEST} {307501200 3600 0 CET} {323830800 7200 1 CEST} {338950800 3600 0 CET} {354675600 7200 1 CEST} {370400400 3600 0 CET} {386125200 7200 1 CEST} {401850000 3600 0 CET} {417574800 7200 1 CEST} {433299600 3600 0 CET} {449024400 7200 1 CEST} {465354000 3600 0 CET} {481078800 7200 1 CEST} {496803600 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Iceland0000644000175000017500000000027112661614722016001 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Atlantic/Reykjavik)]} { LoadTimeZoneFile Atlantic/Reykjavik } set TZData(:Iceland) $TZData(:Atlantic/Reykjavik) tcl8.6.5/library/tzdata/US/0000755000175000017500000000000012665173607015054 5ustar sergeisergeitcl8.6.5/library/tzdata/US/Central0000644000175000017500000000026312661614722016362 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Chicago)]} { LoadTimeZoneFile America/Chicago } set TZData(:US/Central) $TZData(:America/Chicago) tcl8.6.5/library/tzdata/US/Arizona0000644000175000017500000000026312661614722016375 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Phoenix)]} { LoadTimeZoneFile America/Phoenix } set TZData(:US/Arizona) $TZData(:America/Phoenix) tcl8.6.5/library/tzdata/US/Pacific-New0000644000175000017500000000030312661614722017052 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Los_Angeles)]} { LoadTimeZoneFile America/Los_Angeles } set TZData(:US/Pacific-New) $TZData(:America/Los_Angeles) tcl8.6.5/library/tzdata/US/Aleutian0000644000175000017500000000025312661614722016533 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Adak)]} { LoadTimeZoneFile America/Adak } set TZData(:US/Aleutian) $TZData(:America/Adak) tcl8.6.5/library/tzdata/US/Mountain0000644000175000017500000000026112661614722016562 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Denver)]} { LoadTimeZoneFile America/Denver } set TZData(:US/Mountain) $TZData(:America/Denver) tcl8.6.5/library/tzdata/US/Indiana-Starke0000644000175000017500000000031112661614722017556 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Indiana/Knox)]} { LoadTimeZoneFile America/Indiana/Knox } set TZData(:US/Indiana-Starke) $TZData(:America/Indiana/Knox) tcl8.6.5/library/tzdata/US/East-Indiana0000644000175000017500000000033712661614722017231 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Indiana/Indianapolis)]} { LoadTimeZoneFile America/Indiana/Indianapolis } set TZData(:US/East-Indiana) $TZData(:America/Indiana/Indianapolis) tcl8.6.5/library/tzdata/US/Michigan0000644000175000017500000000026412661614722016512 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Detroit)]} { LoadTimeZoneFile America/Detroit } set TZData(:US/Michigan) $TZData(:America/Detroit) tcl8.6.5/library/tzdata/US/Eastern0000644000175000017500000000026612661614722016376 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/New_York)]} { LoadTimeZoneFile America/New_York } set TZData(:US/Eastern) $TZData(:America/New_York) tcl8.6.5/library/tzdata/US/Pacific0000644000175000017500000000027712661614722016335 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Los_Angeles)]} { LoadTimeZoneFile America/Los_Angeles } set TZData(:US/Pacific) $TZData(:America/Los_Angeles) tcl8.6.5/library/tzdata/US/Samoa0000644000175000017500000000026712661614722016036 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Pago_Pago)]} { LoadTimeZoneFile Pacific/Pago_Pago } set TZData(:US/Samoa) $TZData(:Pacific/Pago_Pago) tcl8.6.5/library/tzdata/US/Alaska0000644000175000017500000000027012661614722016164 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Anchorage)]} { LoadTimeZoneFile America/Anchorage } set TZData(:US/Alaska) $TZData(:America/Anchorage) tcl8.6.5/library/tzdata/US/Hawaii0000644000175000017500000000026512661614722016176 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Honolulu)]} { LoadTimeZoneFile Pacific/Honolulu } set TZData(:US/Hawaii) $TZData(:Pacific/Honolulu) tcl8.6.5/library/tzdata/CST6CDT0000644000175000017500000002004312661614721015512 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:CST6CDT) { {-9223372036854775808 -21600 0 CST} {-1633276800 -18000 1 CDT} {-1615136400 -21600 0 CST} {-1601827200 -18000 1 CDT} {-1583686800 -21600 0 CST} {-880214400 -18000 1 CWT} {-769395600 -18000 1 CPT} {-765392400 -21600 0 CST} {-84384000 -18000 1 CDT} {-68662800 -21600 0 CST} {-52934400 -18000 1 CDT} {-37213200 -21600 0 CST} {-21484800 -18000 1 CDT} {-5763600 -21600 0 CST} {9964800 -18000 1 CDT} {25686000 -21600 0 CST} {41414400 -18000 1 CDT} {57740400 -21600 0 CST} {73468800 -18000 1 CDT} {89190000 -21600 0 CST} {104918400 -18000 1 CDT} {120639600 -21600 0 CST} {126691200 -18000 1 CDT} {152089200 -21600 0 CST} {162374400 -18000 1 CDT} {183538800 -21600 0 CST} {199267200 -18000 1 CDT} {215593200 -21600 0 CST} {230716800 -18000 1 CDT} {247042800 -21600 0 CST} {262771200 -18000 1 CDT} {278492400 -21600 0 CST} {294220800 -18000 1 CDT} {309942000 -21600 0 CST} {325670400 -18000 1 CDT} {341391600 -21600 0 CST} {357120000 -18000 1 CDT} {372841200 -21600 0 CST} {388569600 -18000 1 CDT} {404895600 -21600 0 CST} {420019200 -18000 1 CDT} {436345200 -21600 0 CST} {452073600 -18000 1 CDT} {467794800 -21600 0 CST} {483523200 -18000 1 CDT} {499244400 -21600 0 CST} {514972800 -18000 1 CDT} {530694000 -21600 0 CST} {544608000 -18000 1 CDT} {562143600 -21600 0 CST} {576057600 -18000 1 CDT} {594198000 -21600 0 CST} {607507200 -18000 1 CDT} {625647600 -21600 0 CST} {638956800 -18000 1 CDT} {657097200 -21600 0 CST} {671011200 -18000 1 CDT} {688546800 -21600 0 CST} {702460800 -18000 1 CDT} {719996400 -21600 0 CST} {733910400 -18000 1 CDT} {752050800 -21600 0 CST} {765360000 -18000 1 CDT} {783500400 -21600 0 CST} {796809600 -18000 1 CDT} {814950000 -21600 0 CST} {828864000 -18000 1 CDT} {846399600 -21600 0 CST} {860313600 -18000 1 CDT} {877849200 -21600 0 CST} {891763200 -18000 1 CDT} {909298800 -21600 0 CST} {923212800 -18000 1 CDT} {941353200 -21600 0 CST} {954662400 -18000 1 CDT} {972802800 -21600 0 CST} {986112000 -18000 1 CDT} {1004252400 -21600 0 CST} {1018166400 -18000 1 CDT} {1035702000 -21600 0 CST} {1049616000 -18000 1 CDT} {1067151600 -21600 0 CST} {1081065600 -18000 1 CDT} {1099206000 -21600 0 CST} {1112515200 -18000 1 CDT} {1130655600 -21600 0 CST} {1143964800 -18000 1 CDT} {1162105200 -21600 0 CST} {1173600000 -18000 1 CDT} {1194159600 -21600 0 CST} {1205049600 -18000 1 CDT} {1225609200 -21600 0 CST} {1236499200 -18000 1 CDT} {1257058800 -21600 0 CST} {1268553600 -18000 1 CDT} {1289113200 -21600 0 CST} {1300003200 -18000 1 CDT} {1320562800 -21600 0 CST} {1331452800 -18000 1 CDT} {1352012400 -21600 0 CST} {1362902400 -18000 1 CDT} {1383462000 -21600 0 CST} {1394352000 -18000 1 CDT} {1414911600 -21600 0 CST} {1425801600 -18000 1 CDT} {1446361200 -21600 0 CST} {1457856000 -18000 1 CDT} {1478415600 -21600 0 CST} {1489305600 -18000 1 CDT} {1509865200 -21600 0 CST} {1520755200 -18000 1 CDT} {1541314800 -21600 0 CST} {1552204800 -18000 1 CDT} {1572764400 -21600 0 CST} {1583654400 -18000 1 CDT} {1604214000 -21600 0 CST} {1615708800 -18000 1 CDT} {1636268400 -21600 0 CST} {1647158400 -18000 1 CDT} {1667718000 -21600 0 CST} {1678608000 -18000 1 CDT} {1699167600 -21600 0 CST} {1710057600 -18000 1 CDT} {1730617200 -21600 0 CST} {1741507200 -18000 1 CDT} {1762066800 -21600 0 CST} {1772956800 -18000 1 CDT} {1793516400 -21600 0 CST} {1805011200 -18000 1 CDT} {1825570800 -21600 0 CST} {1836460800 -18000 1 CDT} {1857020400 -21600 0 CST} {1867910400 -18000 1 CDT} {1888470000 -21600 0 CST} {1899360000 -18000 1 CDT} {1919919600 -21600 0 CST} {1930809600 -18000 1 CDT} {1951369200 -21600 0 CST} {1962864000 -18000 1 CDT} {1983423600 -21600 0 CST} {1994313600 -18000 1 CDT} {2014873200 -21600 0 CST} {2025763200 -18000 1 CDT} {2046322800 -21600 0 CST} {2057212800 -18000 1 CDT} {2077772400 -21600 0 CST} {2088662400 -18000 1 CDT} {2109222000 -21600 0 CST} {2120112000 -18000 1 CDT} {2140671600 -21600 0 CST} {2152166400 -18000 1 CDT} {2172726000 -21600 0 CST} {2183616000 -18000 1 CDT} {2204175600 -21600 0 CST} {2215065600 -18000 1 CDT} {2235625200 -21600 0 CST} {2246515200 -18000 1 CDT} {2267074800 -21600 0 CST} {2277964800 -18000 1 CDT} {2298524400 -21600 0 CST} {2309414400 -18000 1 CDT} {2329974000 -21600 0 CST} {2341468800 -18000 1 CDT} {2362028400 -21600 0 CST} {2372918400 -18000 1 CDT} {2393478000 -21600 0 CST} {2404368000 -18000 1 CDT} {2424927600 -21600 0 CST} {2435817600 -18000 1 CDT} {2456377200 -21600 0 CST} {2467267200 -18000 1 CDT} {2487826800 -21600 0 CST} {2499321600 -18000 1 CDT} {2519881200 -21600 0 CST} {2530771200 -18000 1 CDT} {2551330800 -21600 0 CST} {2562220800 -18000 1 CDT} {2582780400 -21600 0 CST} {2593670400 -18000 1 CDT} {2614230000 -21600 0 CST} {2625120000 -18000 1 CDT} {2645679600 -21600 0 CST} {2656569600 -18000 1 CDT} {2677129200 -21600 0 CST} {2688624000 -18000 1 CDT} {2709183600 -21600 0 CST} {2720073600 -18000 1 CDT} {2740633200 -21600 0 CST} {2751523200 -18000 1 CDT} {2772082800 -21600 0 CST} {2782972800 -18000 1 CDT} {2803532400 -21600 0 CST} {2814422400 -18000 1 CDT} {2834982000 -21600 0 CST} {2846476800 -18000 1 CDT} {2867036400 -21600 0 CST} {2877926400 -18000 1 CDT} {2898486000 -21600 0 CST} {2909376000 -18000 1 CDT} {2929935600 -21600 0 CST} {2940825600 -18000 1 CDT} {2961385200 -21600 0 CST} {2972275200 -18000 1 CDT} {2992834800 -21600 0 CST} {3003724800 -18000 1 CDT} {3024284400 -21600 0 CST} {3035779200 -18000 1 CDT} {3056338800 -21600 0 CST} {3067228800 -18000 1 CDT} {3087788400 -21600 0 CST} {3098678400 -18000 1 CDT} {3119238000 -21600 0 CST} {3130128000 -18000 1 CDT} {3150687600 -21600 0 CST} {3161577600 -18000 1 CDT} {3182137200 -21600 0 CST} {3193027200 -18000 1 CDT} {3213586800 -21600 0 CST} {3225081600 -18000 1 CDT} {3245641200 -21600 0 CST} {3256531200 -18000 1 CDT} {3277090800 -21600 0 CST} {3287980800 -18000 1 CDT} {3308540400 -21600 0 CST} {3319430400 -18000 1 CDT} {3339990000 -21600 0 CST} {3350880000 -18000 1 CDT} {3371439600 -21600 0 CST} {3382934400 -18000 1 CDT} {3403494000 -21600 0 CST} {3414384000 -18000 1 CDT} {3434943600 -21600 0 CST} {3445833600 -18000 1 CDT} {3466393200 -21600 0 CST} {3477283200 -18000 1 CDT} {3497842800 -21600 0 CST} {3508732800 -18000 1 CDT} {3529292400 -21600 0 CST} {3540182400 -18000 1 CDT} {3560742000 -21600 0 CST} {3572236800 -18000 1 CDT} {3592796400 -21600 0 CST} {3603686400 -18000 1 CDT} {3624246000 -21600 0 CST} {3635136000 -18000 1 CDT} {3655695600 -21600 0 CST} {3666585600 -18000 1 CDT} {3687145200 -21600 0 CST} {3698035200 -18000 1 CDT} {3718594800 -21600 0 CST} {3730089600 -18000 1 CDT} {3750649200 -21600 0 CST} {3761539200 -18000 1 CDT} {3782098800 -21600 0 CST} {3792988800 -18000 1 CDT} {3813548400 -21600 0 CST} {3824438400 -18000 1 CDT} {3844998000 -21600 0 CST} {3855888000 -18000 1 CDT} {3876447600 -21600 0 CST} {3887337600 -18000 1 CDT} {3907897200 -21600 0 CST} {3919392000 -18000 1 CDT} {3939951600 -21600 0 CST} {3950841600 -18000 1 CDT} {3971401200 -21600 0 CST} {3982291200 -18000 1 CDT} {4002850800 -21600 0 CST} {4013740800 -18000 1 CDT} {4034300400 -21600 0 CST} {4045190400 -18000 1 CDT} {4065750000 -21600 0 CST} {4076640000 -18000 1 CDT} {4097199600 -21600 0 CST} } tcl8.6.5/library/tzdata/Mexico/0000755000175000017500000000000012665173607015751 5ustar sergeisergeitcl8.6.5/library/tzdata/Mexico/General0000644000175000017500000000030312661614722017237 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Mexico_City)]} { LoadTimeZoneFile America/Mexico_City } set TZData(:Mexico/General) $TZData(:America/Mexico_City) tcl8.6.5/library/tzdata/Mexico/BajaNorte0000644000175000017500000000027112661614722017533 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Tijuana)]} { LoadTimeZoneFile America/Tijuana } set TZData(:Mexico/BajaNorte) $TZData(:America/Tijuana) tcl8.6.5/library/tzdata/Mexico/BajaSur0000644000175000017500000000027212661614722017216 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Mazatlan)]} { LoadTimeZoneFile America/Mazatlan } set TZData(:Mexico/BajaSur) $TZData(:America/Mazatlan) tcl8.6.5/library/tzdata/Etc/0000755000175000017500000000000012665173607015240 5ustar sergeisergeitcl8.6.5/library/tzdata/Etc/GMT-110000644000175000017500000000016312661614721016022 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-11) { {-9223372036854775808 39600 0 GMT-11} } tcl8.6.5/library/tzdata/Etc/GMT00000644000175000017500000000023112661614722015660 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/GMT)]} { LoadTimeZoneFile Etc/GMT } set TZData(:Etc/GMT0) $TZData(:Etc/GMT) tcl8.6.5/library/tzdata/Etc/GMT-60000644000175000017500000000016112661614721015744 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-6) { {-9223372036854775808 21600 0 GMT-6} } tcl8.6.5/library/tzdata/Etc/GMT+110000644000175000017500000000016412661614721016021 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+11) { {-9223372036854775808 -39600 0 GMT+11} } tcl8.6.5/library/tzdata/Etc/Zulu0000644000175000017500000000023112661614722016110 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/UTC)]} { LoadTimeZoneFile Etc/UTC } set TZData(:Etc/Zulu) $TZData(:Etc/UTC) tcl8.6.5/library/tzdata/Etc/GMT-100000644000175000017500000000016312661614721016021 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-10) { {-9223372036854775808 36000 0 GMT-10} } tcl8.6.5/library/tzdata/Etc/GMT+120000644000175000017500000000016412661614721016022 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+12) { {-9223372036854775808 -43200 0 GMT+12} } tcl8.6.5/library/tzdata/Etc/UTC0000644000175000017500000000015112661614721015604 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/UTC) { {-9223372036854775808 0 0 UTC} } tcl8.6.5/library/tzdata/Etc/GMT-120000644000175000017500000000016312661614721016023 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-12) { {-9223372036854775808 43200 0 GMT-12} } tcl8.6.5/library/tzdata/Etc/GMT-130000644000175000017500000000016312661614721016024 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-13) { {-9223372036854775808 46800 0 GMT-13} } tcl8.6.5/library/tzdata/Etc/GMT-80000644000175000017500000000016112661614721015746 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-8) { {-9223372036854775808 28800 0 GMT-8} } tcl8.6.5/library/tzdata/Etc/GMT+70000644000175000017500000000016212661614721015744 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+7) { {-9223372036854775808 -25200 0 GMT+7} } tcl8.6.5/library/tzdata/Etc/Greenwich0000644000175000017500000000023612661614722017071 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/GMT)]} { LoadTimeZoneFile Etc/GMT } set TZData(:Etc/Greenwich) $TZData(:Etc/GMT) tcl8.6.5/library/tzdata/Etc/GMT+80000644000175000017500000000016212661614721015745 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+8) { {-9223372036854775808 -28800 0 GMT+8} } tcl8.6.5/library/tzdata/Etc/UCT0000644000175000017500000000015112661614721015604 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/UCT) { {-9223372036854775808 0 0 UCT} } tcl8.6.5/library/tzdata/Etc/GMT-140000644000175000017500000000016312661614721016025 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-14) { {-9223372036854775808 50400 0 GMT-14} } tcl8.6.5/library/tzdata/Etc/GMT-90000644000175000017500000000016112661614721015747 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-9) { {-9223372036854775808 32400 0 GMT-9} } tcl8.6.5/library/tzdata/Etc/GMT+90000644000175000017500000000016212661614721015746 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+9) { {-9223372036854775808 -32400 0 GMT+9} } tcl8.6.5/library/tzdata/Etc/GMT+20000644000175000017500000000016112661614721015736 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+2) { {-9223372036854775808 -7200 0 GMT+2} } tcl8.6.5/library/tzdata/Etc/GMT+10000644000175000017500000000016112661614721015735 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+1) { {-9223372036854775808 -3600 0 GMT+1} } tcl8.6.5/library/tzdata/Etc/GMT-00000644000175000017500000000023212661614722015736 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/GMT)]} { LoadTimeZoneFile Etc/GMT } set TZData(:Etc/GMT-0) $TZData(:Etc/GMT) tcl8.6.5/library/tzdata/Etc/GMT-20000644000175000017500000000016012661614721015737 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-2) { {-9223372036854775808 7200 0 GMT-2} } tcl8.6.5/library/tzdata/Etc/GMT+50000644000175000017500000000016212661614721015742 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+5) { {-9223372036854775808 -18000 0 GMT+5} } tcl8.6.5/library/tzdata/Etc/GMT-50000644000175000017500000000016112661614721015743 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-5) { {-9223372036854775808 18000 0 GMT-5} } tcl8.6.5/library/tzdata/Etc/GMT-40000644000175000017500000000016112661614721015742 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-4) { {-9223372036854775808 14400 0 GMT-4} } tcl8.6.5/library/tzdata/Etc/GMT+40000644000175000017500000000016212661614721015741 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+4) { {-9223372036854775808 -14400 0 GMT+4} } tcl8.6.5/library/tzdata/Etc/GMT-30000644000175000017500000000016112661614721015741 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-3) { {-9223372036854775808 10800 0 GMT-3} } tcl8.6.5/library/tzdata/Etc/GMT+100000644000175000017500000000016412661614721016020 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+10) { {-9223372036854775808 -36000 0 GMT+10} } tcl8.6.5/library/tzdata/Etc/GMT+00000644000175000017500000000023212661614722015734 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/GMT)]} { LoadTimeZoneFile Etc/GMT } set TZData(:Etc/GMT+0) $TZData(:Etc/GMT) tcl8.6.5/library/tzdata/Etc/GMT0000644000175000017500000000015112661614721015600 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT) { {-9223372036854775808 0 0 GMT} } tcl8.6.5/library/tzdata/Etc/GMT+60000644000175000017500000000016212661614721015743 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+6) { {-9223372036854775808 -21600 0 GMT+6} } tcl8.6.5/library/tzdata/Etc/Universal0000644000175000017500000000023612661614722017126 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/UTC)]} { LoadTimeZoneFile Etc/UTC } set TZData(:Etc/Universal) $TZData(:Etc/UTC) tcl8.6.5/library/tzdata/Etc/GMT-70000644000175000017500000000016112661614721015745 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-7) { {-9223372036854775808 25200 0 GMT-7} } tcl8.6.5/library/tzdata/Etc/GMT-10000644000175000017500000000016012661614721015736 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT-1) { {-9223372036854775808 3600 0 GMT-1} } tcl8.6.5/library/tzdata/Etc/GMT+30000644000175000017500000000016212661614721015740 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Etc/GMT+3) { {-9223372036854775808 -10800 0 GMT+3} } tcl8.6.5/library/tzdata/MET0000644000175000017500000001645712663653132015104 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:MET) { {-9223372036854775808 3600 0 MET} {-1693706400 7200 1 MEST} {-1680483600 3600 0 MET} {-1663455600 7200 1 MEST} {-1650150000 3600 0 MET} {-1632006000 7200 1 MEST} {-1618700400 3600 0 MET} {-938905200 7200 1 MEST} {-857257200 3600 0 MET} {-844556400 7200 1 MEST} {-828226800 3600 0 MET} {-812502000 7200 1 MEST} {-796777200 3600 0 MET} {-781052400 7200 1 MEST} {-766623600 3600 0 MET} {228877200 7200 1 MEST} {243997200 3600 0 MET} {260326800 7200 1 MEST} {276051600 3600 0 MET} {291776400 7200 1 MEST} {307501200 3600 0 MET} {323830800 7200 1 MEST} {338950800 3600 0 MET} {354675600 7200 1 MEST} {370400400 3600 0 MET} {386125200 7200 1 MEST} {401850000 3600 0 MET} {417574800 7200 1 MEST} {433299600 3600 0 MET} {449024400 7200 1 MEST} {465354000 3600 0 MET} {481078800 7200 1 MEST} {496803600 3600 0 MET} {512528400 7200 1 MEST} {528253200 3600 0 MET} {543978000 7200 1 MEST} {559702800 3600 0 MET} {575427600 7200 1 MEST} {591152400 3600 0 MET} {606877200 7200 1 MEST} {622602000 3600 0 MET} {638326800 7200 1 MEST} {654656400 3600 0 MET} {670381200 7200 1 MEST} {686106000 3600 0 MET} {701830800 7200 1 MEST} {717555600 3600 0 MET} {733280400 7200 1 MEST} {749005200 3600 0 MET} {764730000 7200 1 MEST} {780454800 3600 0 MET} {796179600 7200 1 MEST} {811904400 3600 0 MET} {828234000 7200 1 MEST} {846378000 3600 0 MET} {859683600 7200 1 MEST} {877827600 3600 0 MET} {891133200 7200 1 MEST} {909277200 3600 0 MET} {922582800 7200 1 MEST} {941331600 3600 0 MET} {954032400 7200 1 MEST} {972781200 3600 0 MET} {985482000 7200 1 MEST} {1004230800 3600 0 MET} {1017536400 7200 1 MEST} {1035680400 3600 0 MET} {1048986000 7200 1 MEST} {1067130000 3600 0 MET} {1080435600 7200 1 MEST} {1099184400 3600 0 MET} {1111885200 7200 1 MEST} {1130634000 3600 0 MET} {1143334800 7200 1 MEST} {1162083600 3600 0 MET} {1174784400 7200 1 MEST} {1193533200 3600 0 MET} {1206838800 7200 1 MEST} {1224982800 3600 0 MET} {1238288400 7200 1 MEST} {1256432400 3600 0 MET} {1269738000 7200 1 MEST} {1288486800 3600 0 MET} {1301187600 7200 1 MEST} {1319936400 3600 0 MET} {1332637200 7200 1 MEST} {1351386000 3600 0 MET} {1364691600 7200 1 MEST} {1382835600 3600 0 MET} {1396141200 7200 1 MEST} {1414285200 3600 0 MET} {1427590800 7200 1 MEST} {1445734800 3600 0 MET} {1459040400 7200 1 MEST} {1477789200 3600 0 MET} {1490490000 7200 1 MEST} {1509238800 3600 0 MET} {1521939600 7200 1 MEST} {1540688400 3600 0 MET} {1553994000 7200 1 MEST} {1572138000 3600 0 MET} {1585443600 7200 1 MEST} {1603587600 3600 0 MET} {1616893200 7200 1 MEST} {1635642000 3600 0 MET} {1648342800 7200 1 MEST} {1667091600 3600 0 MET} {1679792400 7200 1 MEST} {1698541200 3600 0 MET} {1711846800 7200 1 MEST} {1729990800 3600 0 MET} {1743296400 7200 1 MEST} {1761440400 3600 0 MET} {1774746000 7200 1 MEST} {1792890000 3600 0 MET} {1806195600 7200 1 MEST} {1824944400 3600 0 MET} {1837645200 7200 1 MEST} {1856394000 3600 0 MET} {1869094800 7200 1 MEST} {1887843600 3600 0 MET} {1901149200 7200 1 MEST} {1919293200 3600 0 MET} {1932598800 7200 1 MEST} {1950742800 3600 0 MET} {1964048400 7200 1 MEST} {1982797200 3600 0 MET} {1995498000 7200 1 MEST} {2014246800 3600 0 MET} {2026947600 7200 1 MEST} {2045696400 3600 0 MET} {2058397200 7200 1 MEST} {2077146000 3600 0 MET} {2090451600 7200 1 MEST} {2108595600 3600 0 MET} {2121901200 7200 1 MEST} {2140045200 3600 0 MET} {2153350800 7200 1 MEST} {2172099600 3600 0 MET} {2184800400 7200 1 MEST} {2203549200 3600 0 MET} {2216250000 7200 1 MEST} {2234998800 3600 0 MET} {2248304400 7200 1 MEST} {2266448400 3600 0 MET} {2279754000 7200 1 MEST} {2297898000 3600 0 MET} {2311203600 7200 1 MEST} {2329347600 3600 0 MET} {2342653200 7200 1 MEST} {2361402000 3600 0 MET} {2374102800 7200 1 MEST} {2392851600 3600 0 MET} {2405552400 7200 1 MEST} {2424301200 3600 0 MET} {2437606800 7200 1 MEST} {2455750800 3600 0 MET} {2469056400 7200 1 MEST} {2487200400 3600 0 MET} {2500506000 7200 1 MEST} {2519254800 3600 0 MET} {2531955600 7200 1 MEST} {2550704400 3600 0 MET} {2563405200 7200 1 MEST} {2582154000 3600 0 MET} {2595459600 7200 1 MEST} {2613603600 3600 0 MET} {2626909200 7200 1 MEST} {2645053200 3600 0 MET} {2658358800 7200 1 MEST} {2676502800 3600 0 MET} {2689808400 7200 1 MEST} {2708557200 3600 0 MET} {2721258000 7200 1 MEST} {2740006800 3600 0 MET} {2752707600 7200 1 MEST} {2771456400 3600 0 MET} {2784762000 7200 1 MEST} {2802906000 3600 0 MET} {2816211600 7200 1 MEST} {2834355600 3600 0 MET} {2847661200 7200 1 MEST} {2866410000 3600 0 MET} {2879110800 7200 1 MEST} {2897859600 3600 0 MET} {2910560400 7200 1 MEST} {2929309200 3600 0 MET} {2942010000 7200 1 MEST} {2960758800 3600 0 MET} {2974064400 7200 1 MEST} {2992208400 3600 0 MET} {3005514000 7200 1 MEST} {3023658000 3600 0 MET} {3036963600 7200 1 MEST} {3055712400 3600 0 MET} {3068413200 7200 1 MEST} {3087162000 3600 0 MET} {3099862800 7200 1 MEST} {3118611600 3600 0 MET} {3131917200 7200 1 MEST} {3150061200 3600 0 MET} {3163366800 7200 1 MEST} {3181510800 3600 0 MET} {3194816400 7200 1 MEST} {3212960400 3600 0 MET} {3226266000 7200 1 MEST} {3245014800 3600 0 MET} {3257715600 7200 1 MEST} {3276464400 3600 0 MET} {3289165200 7200 1 MEST} {3307914000 3600 0 MET} {3321219600 7200 1 MEST} {3339363600 3600 0 MET} {3352669200 7200 1 MEST} {3370813200 3600 0 MET} {3384118800 7200 1 MEST} {3402867600 3600 0 MET} {3415568400 7200 1 MEST} {3434317200 3600 0 MET} {3447018000 7200 1 MEST} {3465766800 3600 0 MET} {3479072400 7200 1 MEST} {3497216400 3600 0 MET} {3510522000 7200 1 MEST} {3528666000 3600 0 MET} {3541971600 7200 1 MEST} {3560115600 3600 0 MET} {3573421200 7200 1 MEST} {3592170000 3600 0 MET} {3604870800 7200 1 MEST} {3623619600 3600 0 MET} {3636320400 7200 1 MEST} {3655069200 3600 0 MET} {3668374800 7200 1 MEST} {3686518800 3600 0 MET} {3699824400 7200 1 MEST} {3717968400 3600 0 MET} {3731274000 7200 1 MEST} {3750022800 3600 0 MET} {3762723600 7200 1 MEST} {3781472400 3600 0 MET} {3794173200 7200 1 MEST} {3812922000 3600 0 MET} {3825622800 7200 1 MEST} {3844371600 3600 0 MET} {3857677200 7200 1 MEST} {3875821200 3600 0 MET} {3889126800 7200 1 MEST} {3907270800 3600 0 MET} {3920576400 7200 1 MEST} {3939325200 3600 0 MET} {3952026000 7200 1 MEST} {3970774800 3600 0 MET} {3983475600 7200 1 MEST} {4002224400 3600 0 MET} {4015530000 7200 1 MEST} {4033674000 3600 0 MET} {4046979600 7200 1 MEST} {4065123600 3600 0 MET} {4078429200 7200 1 MEST} {4096573200 3600 0 MET} } tcl8.6.5/library/tzdata/GMT+00000644000175000017500000000022612661614722015224 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/GMT)]} { LoadTimeZoneFile Etc/GMT } set TZData(:GMT+0) $TZData(:Etc/GMT) tcl8.6.5/library/tzdata/Turkey0000644000175000017500000000025712661614722015731 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Istanbul)]} { LoadTimeZoneFile Europe/Istanbul } set TZData(:Turkey) $TZData(:Europe/Istanbul) tcl8.6.5/library/tzdata/Jamaica0000644000175000017500000000026012661614722015765 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Jamaica)]} { LoadTimeZoneFile America/Jamaica } set TZData(:Jamaica) $TZData(:America/Jamaica) tcl8.6.5/library/tzdata/ROC0000644000175000017500000000024012661614722015061 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Taipei)]} { LoadTimeZoneFile Asia/Taipei } set TZData(:ROC) $TZData(:Asia/Taipei) tcl8.6.5/library/tzdata/GMT0000644000175000017500000000022412661614722015067 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/GMT)]} { LoadTimeZoneFile Etc/GMT } set TZData(:GMT) $TZData(:Etc/GMT) tcl8.6.5/library/tzdata/MST0000644000175000017500000000015212661614721015102 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:MST) { {-9223372036854775808 -25200 0 MST} } tcl8.6.5/library/tzdata/Canada/0000755000175000017500000000000012665173607015674 5ustar sergeisergeitcl8.6.5/library/tzdata/Canada/Yukon0000644000175000017500000000027612661614722016723 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Whitehorse)]} { LoadTimeZoneFile America/Whitehorse } set TZData(:Canada/Yukon) $TZData(:America/Whitehorse) tcl8.6.5/library/tzdata/Canada/Central0000644000175000017500000000027212661614722017202 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Winnipeg)]} { LoadTimeZoneFile America/Winnipeg } set TZData(:Canada/Central) $TZData(:America/Winnipeg) tcl8.6.5/library/tzdata/Canada/Atlantic0000644000175000017500000000027012661614722017347 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Halifax)]} { LoadTimeZoneFile America/Halifax } set TZData(:Canada/Atlantic) $TZData(:America/Halifax) tcl8.6.5/library/tzdata/Canada/East-Saskatchewan0000644000175000017500000000027612661614722021124 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Regina)]} { LoadTimeZoneFile America/Regina } set TZData(:Canada/East-Saskatchewan) $TZData(:America/Regina) tcl8.6.5/library/tzdata/Canada/Newfoundland0000644000175000017500000000027712661614722020243 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/St_Johns)]} { LoadTimeZoneFile America/St_Johns } set TZData(:Canada/Newfoundland) $TZData(:America/St_Johns) tcl8.6.5/library/tzdata/Canada/Mountain0000644000175000017500000000027312661614722017405 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Edmonton)]} { LoadTimeZoneFile America/Edmonton } set TZData(:Canada/Mountain) $TZData(:America/Edmonton) tcl8.6.5/library/tzdata/Canada/Saskatchewan0000644000175000017500000000027112661614722020225 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Regina)]} { LoadTimeZoneFile America/Regina } set TZData(:Canada/Saskatchewan) $TZData(:America/Regina) tcl8.6.5/library/tzdata/Canada/Eastern0000644000175000017500000000026712661614722017217 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Toronto)]} { LoadTimeZoneFile America/Toronto } set TZData(:Canada/Eastern) $TZData(:America/Toronto) tcl8.6.5/library/tzdata/Canada/Pacific0000644000175000017500000000027512661614722017153 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Vancouver)]} { LoadTimeZoneFile America/Vancouver } set TZData(:Canada/Pacific) $TZData(:America/Vancouver) tcl8.6.5/library/tzdata/Pacific/0000755000175000017500000000000012665173607016063 5ustar sergeisergeitcl8.6.5/library/tzdata/Pacific/Pohnpei0000644000175000017500000000022412663653207017403 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Pohnpei) { {-9223372036854775808 37972 0 LMT} {-2177490772 39600 0 PONT} } tcl8.6.5/library/tzdata/Pacific/Bougainville0000644000175000017500000000041612663660066020425 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Bougainville) { {-9223372036854775808 37336 0 LMT} {-2840178136 35312 0 PMMT} {-2366790512 36000 0 PGT} {-868010400 32400 0 JST} {-768906000 36000 0 PGT} {1419696000 39600 0 BST} } tcl8.6.5/library/tzdata/Pacific/Truk0000644000175000017500000000025712663653207016734 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Chuuk)]} { LoadTimeZoneFile Pacific/Chuuk } set TZData(:Pacific/Truk) $TZData(:Pacific/Chuuk) tcl8.6.5/library/tzdata/Pacific/Kiritimati0000644000175000017500000000032412661614722020105 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Kiritimati) { {-9223372036854775808 -37760 0 LMT} {-2177415040 -38400 0 LINT} {307622400 -36000 0 LINT} {788954400 50400 0 LINT} } tcl8.6.5/library/tzdata/Pacific/Tahiti0000644000175000017500000000022512661614722017221 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Tahiti) { {-9223372036854775808 -35896 0 LMT} {-1806674504 -36000 0 TAHT} } tcl8.6.5/library/tzdata/Pacific/Efate0000644000175000017500000000131312661614722017022 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Efate) { {-9223372036854775808 40396 0 LMT} {-1829387596 39600 0 VUT} {433256400 43200 1 VUST} {448977600 39600 0 VUT} {467298000 43200 1 VUST} {480427200 39600 0 VUT} {496760400 43200 1 VUST} {511876800 39600 0 VUT} {528210000 43200 1 VUST} {543931200 39600 0 VUT} {559659600 43200 1 VUST} {575380800 39600 0 VUT} {591109200 43200 1 VUST} {606830400 39600 0 VUT} {622558800 43200 1 VUST} {638280000 39600 0 VUT} {654008400 43200 1 VUST} {669729600 39600 0 VUT} {686062800 43200 1 VUST} {696340800 39600 0 VUT} {719931600 43200 1 VUST} {727790400 39600 0 VUT} } tcl8.6.5/library/tzdata/Pacific/Ponape0000644000175000017500000000026712663653207017232 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Pohnpei)]} { LoadTimeZoneFile Pacific/Pohnpei } set TZData(:Pacific/Ponape) $TZData(:Pacific/Pohnpei) tcl8.6.5/library/tzdata/Pacific/Noumea0000644000175000017500000000047512661614722017232 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Noumea) { {-9223372036854775808 39948 0 LMT} {-1829387148 39600 0 NCT} {250002000 43200 1 NCST} {257342400 39600 0 NCT} {281451600 43200 1 NCST} {288878400 39600 0 NCT} {849366000 43200 1 NCST} {857228400 39600 0 NCT} } tcl8.6.5/library/tzdata/Pacific/Majuro0000644000175000017500000000025512661614722017237 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Majuro) { {-9223372036854775808 41088 0 LMT} {-2177493888 39600 0 MHT} {-7988400 43200 0 MHT} } tcl8.6.5/library/tzdata/Pacific/Johnston0000644000175000017500000000027412663660066017611 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Honolulu)]} { LoadTimeZoneFile Pacific/Honolulu } set TZData(:Pacific/Johnston) $TZData(:Pacific/Honolulu) tcl8.6.5/library/tzdata/Pacific/Port_Moresby0000644000175000017500000000026712661614722020431 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Port_Moresby) { {-9223372036854775808 35320 0 LMT} {-2840176120 35312 0 PMMT} {-2366790512 36000 0 PGT} } tcl8.6.5/library/tzdata/Pacific/Chatham0000644000175000017500000001734312663660066017361 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Chatham) { {-9223372036854775808 44028 0 LMT} {-3192437628 44100 0 CHAST} {-757426500 45900 0 CHAST} {152632800 49500 1 CHADT} {162309600 45900 0 CHAST} {183477600 49500 1 CHADT} {194968800 45900 0 CHAST} {215532000 49500 1 CHADT} {226418400 45900 0 CHAST} {246981600 49500 1 CHADT} {257868000 45900 0 CHAST} {278431200 49500 1 CHADT} {289317600 45900 0 CHAST} {309880800 49500 1 CHADT} {320767200 45900 0 CHAST} {341330400 49500 1 CHADT} {352216800 45900 0 CHAST} {372780000 49500 1 CHADT} {384271200 45900 0 CHAST} {404834400 49500 1 CHADT} {415720800 45900 0 CHAST} {436284000 49500 1 CHADT} {447170400 45900 0 CHAST} {467733600 49500 1 CHADT} {478620000 45900 0 CHAST} {499183200 49500 1 CHADT} {510069600 45900 0 CHAST} {530632800 49500 1 CHADT} {541519200 45900 0 CHAST} {562082400 49500 1 CHADT} {573573600 45900 0 CHAST} {594136800 49500 1 CHADT} {605023200 45900 0 CHAST} {623772000 49500 1 CHADT} {637682400 45900 0 CHAST} {655221600 49500 1 CHADT} {669132000 45900 0 CHAST} {686671200 49500 1 CHADT} {700581600 45900 0 CHAST} {718120800 49500 1 CHADT} {732636000 45900 0 CHAST} {749570400 49500 1 CHADT} {764085600 45900 0 CHAST} {781020000 49500 1 CHADT} {795535200 45900 0 CHAST} {812469600 49500 1 CHADT} {826984800 45900 0 CHAST} {844524000 49500 1 CHADT} {858434400 45900 0 CHAST} {875973600 49500 1 CHADT} {889884000 45900 0 CHAST} {907423200 49500 1 CHADT} {921938400 45900 0 CHAST} {938872800 49500 1 CHADT} {953388000 45900 0 CHAST} {970322400 49500 1 CHADT} {984837600 45900 0 CHAST} {1002376800 49500 1 CHADT} {1016287200 45900 0 CHAST} {1033826400 49500 1 CHADT} {1047736800 45900 0 CHAST} {1065276000 49500 1 CHADT} {1079791200 45900 0 CHAST} {1096725600 49500 1 CHADT} {1111240800 45900 0 CHAST} {1128175200 49500 1 CHADT} {1142690400 45900 0 CHAST} {1159624800 49500 1 CHADT} {1174140000 45900 0 CHAST} {1191074400 49500 1 CHADT} {1207404000 45900 0 CHAST} {1222524000 49500 1 CHADT} {1238853600 45900 0 CHAST} {1253973600 49500 1 CHADT} {1270303200 45900 0 CHAST} {1285423200 49500 1 CHADT} {1301752800 45900 0 CHAST} {1316872800 49500 1 CHADT} {1333202400 45900 0 CHAST} {1348927200 49500 1 CHADT} {1365256800 45900 0 CHAST} {1380376800 49500 1 CHADT} {1396706400 45900 0 CHAST} {1411826400 49500 1 CHADT} {1428156000 45900 0 CHAST} {1443276000 49500 1 CHADT} {1459605600 45900 0 CHAST} {1474725600 49500 1 CHADT} {1491055200 45900 0 CHAST} {1506175200 49500 1 CHADT} {1522504800 45900 0 CHAST} {1538229600 49500 1 CHADT} {1554559200 45900 0 CHAST} {1569679200 49500 1 CHADT} {1586008800 45900 0 CHAST} {1601128800 49500 1 CHADT} {1617458400 45900 0 CHAST} {1632578400 49500 1 CHADT} {1648908000 45900 0 CHAST} {1664028000 49500 1 CHADT} {1680357600 45900 0 CHAST} {1695477600 49500 1 CHADT} {1712412000 45900 0 CHAST} {1727532000 49500 1 CHADT} {1743861600 45900 0 CHAST} {1758981600 49500 1 CHADT} {1775311200 45900 0 CHAST} {1790431200 49500 1 CHADT} {1806760800 45900 0 CHAST} {1821880800 49500 1 CHADT} {1838210400 45900 0 CHAST} {1853330400 49500 1 CHADT} {1869660000 45900 0 CHAST} {1885384800 49500 1 CHADT} {1901714400 45900 0 CHAST} {1916834400 49500 1 CHADT} {1933164000 45900 0 CHAST} {1948284000 49500 1 CHADT} {1964613600 45900 0 CHAST} {1979733600 49500 1 CHADT} {1996063200 45900 0 CHAST} {2011183200 49500 1 CHADT} {2027512800 45900 0 CHAST} {2042632800 49500 1 CHADT} {2058962400 45900 0 CHAST} {2074687200 49500 1 CHADT} {2091016800 45900 0 CHAST} {2106136800 49500 1 CHADT} {2122466400 45900 0 CHAST} {2137586400 49500 1 CHADT} {2153916000 45900 0 CHAST} {2169036000 49500 1 CHADT} {2185365600 45900 0 CHAST} {2200485600 49500 1 CHADT} {2216815200 45900 0 CHAST} {2232540000 49500 1 CHADT} {2248869600 45900 0 CHAST} {2263989600 49500 1 CHADT} {2280319200 45900 0 CHAST} {2295439200 49500 1 CHADT} {2311768800 45900 0 CHAST} {2326888800 49500 1 CHADT} {2343218400 45900 0 CHAST} {2358338400 49500 1 CHADT} {2374668000 45900 0 CHAST} {2389788000 49500 1 CHADT} {2406117600 45900 0 CHAST} {2421842400 49500 1 CHADT} {2438172000 45900 0 CHAST} {2453292000 49500 1 CHADT} {2469621600 45900 0 CHAST} {2484741600 49500 1 CHADT} {2501071200 45900 0 CHAST} {2516191200 49500 1 CHADT} {2532520800 45900 0 CHAST} {2547640800 49500 1 CHADT} {2563970400 45900 0 CHAST} {2579090400 49500 1 CHADT} {2596024800 45900 0 CHAST} {2611144800 49500 1 CHADT} {2627474400 45900 0 CHAST} {2642594400 49500 1 CHADT} {2658924000 45900 0 CHAST} {2674044000 49500 1 CHADT} {2690373600 45900 0 CHAST} {2705493600 49500 1 CHADT} {2721823200 45900 0 CHAST} {2736943200 49500 1 CHADT} {2753272800 45900 0 CHAST} {2768997600 49500 1 CHADT} {2785327200 45900 0 CHAST} {2800447200 49500 1 CHADT} {2816776800 45900 0 CHAST} {2831896800 49500 1 CHADT} {2848226400 45900 0 CHAST} {2863346400 49500 1 CHADT} {2879676000 45900 0 CHAST} {2894796000 49500 1 CHADT} {2911125600 45900 0 CHAST} {2926245600 49500 1 CHADT} {2942575200 45900 0 CHAST} {2958300000 49500 1 CHADT} {2974629600 45900 0 CHAST} {2989749600 49500 1 CHADT} {3006079200 45900 0 CHAST} {3021199200 49500 1 CHADT} {3037528800 45900 0 CHAST} {3052648800 49500 1 CHADT} {3068978400 45900 0 CHAST} {3084098400 49500 1 CHADT} {3100428000 45900 0 CHAST} {3116152800 49500 1 CHADT} {3132482400 45900 0 CHAST} {3147602400 49500 1 CHADT} {3163932000 45900 0 CHAST} {3179052000 49500 1 CHADT} {3195381600 45900 0 CHAST} {3210501600 49500 1 CHADT} {3226831200 45900 0 CHAST} {3241951200 49500 1 CHADT} {3258280800 45900 0 CHAST} {3273400800 49500 1 CHADT} {3289730400 45900 0 CHAST} {3305455200 49500 1 CHADT} {3321784800 45900 0 CHAST} {3336904800 49500 1 CHADT} {3353234400 45900 0 CHAST} {3368354400 49500 1 CHADT} {3384684000 45900 0 CHAST} {3399804000 49500 1 CHADT} {3416133600 45900 0 CHAST} {3431253600 49500 1 CHADT} {3447583200 45900 0 CHAST} {3462703200 49500 1 CHADT} {3479637600 45900 0 CHAST} {3494757600 49500 1 CHADT} {3511087200 45900 0 CHAST} {3526207200 49500 1 CHADT} {3542536800 45900 0 CHAST} {3557656800 49500 1 CHADT} {3573986400 45900 0 CHAST} {3589106400 49500 1 CHADT} {3605436000 45900 0 CHAST} {3620556000 49500 1 CHADT} {3636885600 45900 0 CHAST} {3652610400 49500 1 CHADT} {3668940000 45900 0 CHAST} {3684060000 49500 1 CHADT} {3700389600 45900 0 CHAST} {3715509600 49500 1 CHADT} {3731839200 45900 0 CHAST} {3746959200 49500 1 CHADT} {3763288800 45900 0 CHAST} {3778408800 49500 1 CHADT} {3794738400 45900 0 CHAST} {3809858400 49500 1 CHADT} {3826188000 45900 0 CHAST} {3841912800 49500 1 CHADT} {3858242400 45900 0 CHAST} {3873362400 49500 1 CHADT} {3889692000 45900 0 CHAST} {3904812000 49500 1 CHADT} {3921141600 45900 0 CHAST} {3936261600 49500 1 CHADT} {3952591200 45900 0 CHAST} {3967711200 49500 1 CHADT} {3984040800 45900 0 CHAST} {3999765600 49500 1 CHADT} {4016095200 45900 0 CHAST} {4031215200 49500 1 CHADT} {4047544800 45900 0 CHAST} {4062664800 49500 1 CHADT} {4078994400 45900 0 CHAST} {4094114400 49500 1 CHADT} } tcl8.6.5/library/tzdata/Pacific/Marquesas0000644000175000017500000000023012661614722017734 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Marquesas) { {-9223372036854775808 -33480 0 LMT} {-1806676920 -34200 0 MART} } tcl8.6.5/library/tzdata/Pacific/Wallis0000644000175000017500000000022212661614722017227 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Wallis) { {-9223372036854775808 44120 0 LMT} {-2177496920 43200 0 WFT} } tcl8.6.5/library/tzdata/Pacific/Guam0000644000175000017500000000031412661614722016667 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Guam) { {-9223372036854775808 -51660 0 LMT} {-3944626740 34740 0 LMT} {-2177487540 36000 0 GST} {977493600 36000 0 ChST} } tcl8.6.5/library/tzdata/Pacific/Honolulu0000644000175000017500000000045612663660066017616 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Honolulu) { {-9223372036854775808 -37886 0 LMT} {-2334101314 -37800 0 HST} {-1157283000 -34200 1 HDT} {-1155436200 -37800 0 HST} {-880198200 -34200 1 HDT} {-765376200 -37800 0 HST} {-712150200 -36000 0 HST} } tcl8.6.5/library/tzdata/Pacific/Kwajalein0000644000175000017500000000031612661614722017705 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Kwajalein) { {-9223372036854775808 40160 0 LMT} {-2177492960 39600 0 MHT} {-7988400 -43200 0 KWAT} {745848000 43200 0 MHT} } tcl8.6.5/library/tzdata/Pacific/Tarawa0000644000175000017500000000022312661614722017214 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Tarawa) { {-9223372036854775808 41524 0 LMT} {-2177494324 43200 0 GILT} } tcl8.6.5/library/tzdata/Pacific/Guadalcanal0000644000175000017500000000022712661614722020175 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Guadalcanal) { {-9223372036854775808 38388 0 LMT} {-1806748788 39600 0 SBT} } tcl8.6.5/library/tzdata/Pacific/Nauru0000644000175000017500000000034712661614722017076 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Nauru) { {-9223372036854775808 40060 0 LMT} {-1545131260 41400 0 NRT} {-877347000 32400 0 JST} {-800960400 41400 0 NRT} {294323400 43200 0 NRT} } tcl8.6.5/library/tzdata/Pacific/Rarotonga0000644000175000017500000000164312661614722017740 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Rarotonga) { {-9223372036854775808 -38344 0 LMT} {-2177414456 -37800 0 CKT} {279714600 -34200 0 CKHST} {289387800 -36000 0 CKT} {309952800 -34200 1 CKHST} {320837400 -36000 0 CKT} {341402400 -34200 1 CKHST} {352287000 -36000 0 CKT} {372852000 -34200 1 CKHST} {384341400 -36000 0 CKT} {404906400 -34200 1 CKHST} {415791000 -36000 0 CKT} {436356000 -34200 1 CKHST} {447240600 -36000 0 CKT} {467805600 -34200 1 CKHST} {478690200 -36000 0 CKT} {499255200 -34200 1 CKHST} {510139800 -36000 0 CKT} {530704800 -34200 1 CKHST} {541589400 -36000 0 CKT} {562154400 -34200 1 CKHST} {573643800 -36000 0 CKT} {594208800 -34200 1 CKHST} {605093400 -36000 0 CKT} {625658400 -34200 1 CKHST} {636543000 -36000 0 CKT} {657108000 -34200 1 CKHST} {667992600 -36000 0 CKT} } tcl8.6.5/library/tzdata/Pacific/Funafuti0000644000175000017500000000022412661614722017557 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Funafuti) { {-9223372036854775808 43012 0 LMT} {-2177495812 43200 0 TVT} } tcl8.6.5/library/tzdata/Pacific/Apia0000644000175000017500000001274712663660066016671 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Apia) { {-9223372036854775808 45184 0 LMT} {-2855737984 -41216 0 LMT} {-1861878784 -41400 0 WSST} {-631110600 -39600 0 SST} {1285498800 -36000 1 SDT} {1301752800 -39600 0 SST} {1316872800 -36000 1 SDT} {1325239200 50400 0 WSDT} {1333202400 46800 0 WSST} {1348927200 50400 1 WSDT} {1365256800 46800 0 WSST} {1380376800 50400 1 WSDT} {1396706400 46800 0 WSST} {1411826400 50400 1 WSDT} {1428156000 46800 0 WSST} {1443276000 50400 1 WSDT} {1459605600 46800 0 WSST} {1474725600 50400 1 WSDT} {1491055200 46800 0 WSST} {1506175200 50400 1 WSDT} {1522504800 46800 0 WSST} {1538229600 50400 1 WSDT} {1554559200 46800 0 WSST} {1569679200 50400 1 WSDT} {1586008800 46800 0 WSST} {1601128800 50400 1 WSDT} {1617458400 46800 0 WSST} {1632578400 50400 1 WSDT} {1648908000 46800 0 WSST} {1664028000 50400 1 WSDT} {1680357600 46800 0 WSST} {1695477600 50400 1 WSDT} {1712412000 46800 0 WSST} {1727532000 50400 1 WSDT} {1743861600 46800 0 WSST} {1758981600 50400 1 WSDT} {1775311200 46800 0 WSST} {1790431200 50400 1 WSDT} {1806760800 46800 0 WSST} {1821880800 50400 1 WSDT} {1838210400 46800 0 WSST} {1853330400 50400 1 WSDT} {1869660000 46800 0 WSST} {1885384800 50400 1 WSDT} {1901714400 46800 0 WSST} {1916834400 50400 1 WSDT} {1933164000 46800 0 WSST} {1948284000 50400 1 WSDT} {1964613600 46800 0 WSST} {1979733600 50400 1 WSDT} {1996063200 46800 0 WSST} {2011183200 50400 1 WSDT} {2027512800 46800 0 WSST} {2042632800 50400 1 WSDT} {2058962400 46800 0 WSST} {2074687200 50400 1 WSDT} {2091016800 46800 0 WSST} {2106136800 50400 1 WSDT} {2122466400 46800 0 WSST} {2137586400 50400 1 WSDT} {2153916000 46800 0 WSST} {2169036000 50400 1 WSDT} {2185365600 46800 0 WSST} {2200485600 50400 1 WSDT} {2216815200 46800 0 WSST} {2232540000 50400 1 WSDT} {2248869600 46800 0 WSST} {2263989600 50400 1 WSDT} {2280319200 46800 0 WSST} {2295439200 50400 1 WSDT} {2311768800 46800 0 WSST} {2326888800 50400 1 WSDT} {2343218400 46800 0 WSST} {2358338400 50400 1 WSDT} {2374668000 46800 0 WSST} {2389788000 50400 1 WSDT} {2406117600 46800 0 WSST} {2421842400 50400 1 WSDT} {2438172000 46800 0 WSST} {2453292000 50400 1 WSDT} {2469621600 46800 0 WSST} {2484741600 50400 1 WSDT} {2501071200 46800 0 WSST} {2516191200 50400 1 WSDT} {2532520800 46800 0 WSST} {2547640800 50400 1 WSDT} {2563970400 46800 0 WSST} {2579090400 50400 1 WSDT} {2596024800 46800 0 WSST} {2611144800 50400 1 WSDT} {2627474400 46800 0 WSST} {2642594400 50400 1 WSDT} {2658924000 46800 0 WSST} {2674044000 50400 1 WSDT} {2690373600 46800 0 WSST} {2705493600 50400 1 WSDT} {2721823200 46800 0 WSST} {2736943200 50400 1 WSDT} {2753272800 46800 0 WSST} {2768997600 50400 1 WSDT} {2785327200 46800 0 WSST} {2800447200 50400 1 WSDT} {2816776800 46800 0 WSST} {2831896800 50400 1 WSDT} {2848226400 46800 0 WSST} {2863346400 50400 1 WSDT} {2879676000 46800 0 WSST} {2894796000 50400 1 WSDT} {2911125600 46800 0 WSST} {2926245600 50400 1 WSDT} {2942575200 46800 0 WSST} {2958300000 50400 1 WSDT} {2974629600 46800 0 WSST} {2989749600 50400 1 WSDT} {3006079200 46800 0 WSST} {3021199200 50400 1 WSDT} {3037528800 46800 0 WSST} {3052648800 50400 1 WSDT} {3068978400 46800 0 WSST} {3084098400 50400 1 WSDT} {3100428000 46800 0 WSST} {3116152800 50400 1 WSDT} {3132482400 46800 0 WSST} {3147602400 50400 1 WSDT} {3163932000 46800 0 WSST} {3179052000 50400 1 WSDT} {3195381600 46800 0 WSST} {3210501600 50400 1 WSDT} {3226831200 46800 0 WSST} {3241951200 50400 1 WSDT} {3258280800 46800 0 WSST} {3273400800 50400 1 WSDT} {3289730400 46800 0 WSST} {3305455200 50400 1 WSDT} {3321784800 46800 0 WSST} {3336904800 50400 1 WSDT} {3353234400 46800 0 WSST} {3368354400 50400 1 WSDT} {3384684000 46800 0 WSST} {3399804000 50400 1 WSDT} {3416133600 46800 0 WSST} {3431253600 50400 1 WSDT} {3447583200 46800 0 WSST} {3462703200 50400 1 WSDT} {3479637600 46800 0 WSST} {3494757600 50400 1 WSDT} {3511087200 46800 0 WSST} {3526207200 50400 1 WSDT} {3542536800 46800 0 WSST} {3557656800 50400 1 WSDT} {3573986400 46800 0 WSST} {3589106400 50400 1 WSDT} {3605436000 46800 0 WSST} {3620556000 50400 1 WSDT} {3636885600 46800 0 WSST} {3652610400 50400 1 WSDT} {3668940000 46800 0 WSST} {3684060000 50400 1 WSDT} {3700389600 46800 0 WSST} {3715509600 50400 1 WSDT} {3731839200 46800 0 WSST} {3746959200 50400 1 WSDT} {3763288800 46800 0 WSST} {3778408800 50400 1 WSDT} {3794738400 46800 0 WSST} {3809858400 50400 1 WSDT} {3826188000 46800 0 WSST} {3841912800 50400 1 WSDT} {3858242400 46800 0 WSST} {3873362400 50400 1 WSDT} {3889692000 46800 0 WSST} {3904812000 50400 1 WSDT} {3921141600 46800 0 WSST} {3936261600 50400 1 WSDT} {3952591200 46800 0 WSST} {3967711200 50400 1 WSDT} {3984040800 46800 0 WSST} {3999765600 50400 1 WSDT} {4016095200 46800 0 WSST} {4031215200 50400 1 WSDT} {4047544800 46800 0 WSST} {4062664800 50400 1 WSDT} {4078994400 46800 0 WSST} {4094114400 50400 1 WSDT} } tcl8.6.5/library/tzdata/Pacific/Easter0000644000175000017500000000577312663660066017243 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Easter) { {-9223372036854775808 -26248 0 LMT} {-2524495352 -26248 0 EMT} {-1178124152 -25200 0 EAST} {-36619200 -21600 1 EASST} {-23922000 -25200 0 EAST} {-3355200 -21600 1 EASST} {7527600 -25200 0 EAST} {24465600 -21600 1 EASST} {37767600 -25200 0 EAST} {55915200 -21600 1 EASST} {69217200 -25200 0 EAST} {87969600 -21600 1 EASST} {100666800 -25200 0 EAST} {118209600 -21600 1 EASST} {132116400 -25200 0 EAST} {150868800 -21600 1 EASST} {163566000 -25200 0 EAST} {182318400 -21600 1 EASST} {195620400 -25200 0 EAST} {213768000 -21600 1 EASST} {227070000 -25200 0 EAST} {245217600 -21600 1 EASST} {258519600 -25200 0 EAST} {277272000 -21600 1 EASST} {289969200 -25200 0 EAST} {308721600 -21600 1 EASST} {321418800 -25200 0 EAST} {340171200 -21600 1 EASST} {353473200 -25200 0 EAST} {371620800 -21600 1 EASST} {384922800 -21600 0 EAST} {403070400 -18000 1 EASST} {416372400 -21600 0 EAST} {434520000 -18000 1 EASST} {447822000 -21600 0 EAST} {466574400 -18000 1 EASST} {479271600 -21600 0 EAST} {498024000 -18000 1 EASST} {510721200 -21600 0 EAST} {529473600 -18000 1 EASST} {545194800 -21600 0 EAST} {560923200 -18000 1 EASST} {574225200 -21600 0 EAST} {592372800 -18000 1 EASST} {605674800 -21600 0 EAST} {624427200 -18000 1 EASST} {637124400 -21600 0 EAST} {653457600 -18000 1 EASST} {668574000 -21600 0 EAST} {687326400 -18000 1 EASST} {700628400 -21600 0 EAST} {718776000 -18000 1 EASST} {732078000 -21600 0 EAST} {750225600 -18000 1 EASST} {763527600 -21600 0 EAST} {781675200 -18000 1 EASST} {794977200 -21600 0 EAST} {813729600 -18000 1 EASST} {826426800 -21600 0 EAST} {845179200 -18000 1 EASST} {859690800 -21600 0 EAST} {876628800 -18000 1 EASST} {889930800 -21600 0 EAST} {906868800 -18000 1 EASST} {923194800 -21600 0 EAST} {939528000 -18000 1 EASST} {952830000 -21600 0 EAST} {971582400 -18000 1 EASST} {984279600 -21600 0 EAST} {1003032000 -18000 1 EASST} {1015729200 -21600 0 EAST} {1034481600 -18000 1 EASST} {1047178800 -21600 0 EAST} {1065931200 -18000 1 EASST} {1079233200 -21600 0 EAST} {1097380800 -18000 1 EASST} {1110682800 -21600 0 EAST} {1128830400 -18000 1 EASST} {1142132400 -21600 0 EAST} {1160884800 -18000 1 EASST} {1173582000 -21600 0 EAST} {1192334400 -18000 1 EASST} {1206846000 -21600 0 EAST} {1223784000 -18000 1 EASST} {1237086000 -21600 0 EAST} {1255233600 -18000 1 EASST} {1270350000 -21600 0 EAST} {1286683200 -18000 1 EASST} {1304823600 -21600 0 EAST} {1313899200 -18000 1 EASST} {1335668400 -21600 0 EAST} {1346558400 -18000 1 EASST} {1367118000 -21600 0 EAST} {1378612800 -18000 1 EASST} {1398567600 -21600 0 EAST} {1410062400 -18000 1 EASST} {1430017200 -18000 0 EAST} } tcl8.6.5/library/tzdata/Pacific/Yap0000644000175000017500000000025612663653207016537 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Chuuk)]} { LoadTimeZoneFile Pacific/Chuuk } set TZData(:Pacific/Yap) $TZData(:Pacific/Chuuk) tcl8.6.5/library/tzdata/Pacific/Midway0000644000175000017500000000027512663660066017242 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Pago_Pago)]} { LoadTimeZoneFile Pacific/Pago_Pago } set TZData(:Pacific/Midway) $TZData(:Pacific/Pago_Pago) tcl8.6.5/library/tzdata/Pacific/Fakaofo0000644000175000017500000000026212663660066017352 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Fakaofo) { {-9223372036854775808 -41096 0 LMT} {-2177411704 -39600 0 TKT} {1325242800 46800 0 TKT} } tcl8.6.5/library/tzdata/Pacific/Palau0000644000175000017500000000022112661614722017035 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Palau) { {-9223372036854775808 32276 0 LMT} {-2177485076 32400 0 PWT} } tcl8.6.5/library/tzdata/Pacific/Chuuk0000644000175000017500000000022212663653207017056 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Chuuk) { {-9223372036854775808 36428 0 LMT} {-2177489228 36000 0 CHUT} } tcl8.6.5/library/tzdata/Pacific/Galapagos0000644000175000017500000000026512661614722017701 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Galapagos) { {-9223372036854775808 -21504 0 LMT} {-1230746496 -18000 0 ECT} {504939600 -21600 0 GALT} } tcl8.6.5/library/tzdata/Pacific/Kosrae0000644000175000017500000000031412661614722017222 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Kosrae) { {-9223372036854775808 39116 0 LMT} {-2177491916 39600 0 KOST} {-7988400 43200 0 KOST} {915105600 39600 0 KOST} } tcl8.6.5/library/tzdata/Pacific/Gambier0000644000175000017500000000022612661614722017346 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Gambier) { {-9223372036854775808 -32388 0 LMT} {-1806678012 -32400 0 GAMT} } tcl8.6.5/library/tzdata/Pacific/Tongatapu0000644000175000017500000000057312661614722017747 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Tongatapu) { {-9223372036854775808 44360 0 LMT} {-2177497160 44400 0 TOT} {-915193200 46800 0 TOT} {915102000 46800 0 TOT} {939214800 50400 1 TOST} {953384400 46800 0 TOT} {973342800 50400 1 TOST} {980596800 46800 0 TOT} {1004792400 50400 1 TOST} {1012046400 46800 0 TOT} } tcl8.6.5/library/tzdata/Pacific/Pitcairn0000644000175000017500000000026312661614722017552 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Pitcairn) { {-9223372036854775808 -31220 0 LMT} {-2177421580 -30600 0 PNT} {893665800 -28800 0 PST} } tcl8.6.5/library/tzdata/Pacific/Fiji0000644000175000017500000001273612663660066016676 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Fiji) { {-9223372036854775808 42944 0 LMT} {-1709985344 43200 0 FJT} {909842400 46800 1 FJST} {920124000 43200 0 FJT} {941896800 46800 1 FJST} {951573600 43200 0 FJT} {1259416800 46800 1 FJST} {1269698400 43200 0 FJT} {1287842400 46800 1 FJST} {1299333600 43200 0 FJT} {1319292000 46800 1 FJST} {1327154400 43200 0 FJT} {1350741600 46800 1 FJST} {1358604000 43200 0 FJT} {1382796000 46800 1 FJST} {1390050000 43200 0 FJT} {1414850400 46800 1 FJST} {1421503200 43200 0 FJT} {1446300000 46800 1 FJST} {1452952800 43200 0 FJT} {1478354400 46800 1 FJST} {1484402400 43200 0 FJT} {1509804000 46800 1 FJST} {1516456800 43200 0 FJT} {1541253600 46800 1 FJST} {1547906400 43200 0 FJT} {1572703200 46800 1 FJST} {1579356000 43200 0 FJT} {1604152800 46800 1 FJST} {1610805600 43200 0 FJT} {1636207200 46800 1 FJST} {1642255200 43200 0 FJT} {1667656800 46800 1 FJST} {1673704800 43200 0 FJT} {1699106400 46800 1 FJST} {1705759200 43200 0 FJT} {1730556000 46800 1 FJST} {1737208800 43200 0 FJT} {1762005600 46800 1 FJST} {1768658400 43200 0 FJT} {1793455200 46800 1 FJST} {1800108000 43200 0 FJT} {1825509600 46800 1 FJST} {1831557600 43200 0 FJT} {1856959200 46800 1 FJST} {1863612000 43200 0 FJT} {1888408800 46800 1 FJST} {1895061600 43200 0 FJT} {1919858400 46800 1 FJST} {1926511200 43200 0 FJT} {1951308000 46800 1 FJST} {1957960800 43200 0 FJT} {1983362400 46800 1 FJST} {1989410400 43200 0 FJT} {2014812000 46800 1 FJST} {2020860000 43200 0 FJT} {2046261600 46800 1 FJST} {2052914400 43200 0 FJT} {2077711200 46800 1 FJST} {2084364000 43200 0 FJT} {2109160800 46800 1 FJST} {2115813600 43200 0 FJT} {2140610400 46800 1 FJST} {2147263200 43200 0 FJT} {2172664800 46800 1 FJST} {2178712800 43200 0 FJT} {2204114400 46800 1 FJST} {2210162400 43200 0 FJT} {2235564000 46800 1 FJST} {2242216800 43200 0 FJT} {2267013600 46800 1 FJST} {2273666400 43200 0 FJT} {2298463200 46800 1 FJST} {2305116000 43200 0 FJT} {2329912800 46800 1 FJST} {2336565600 43200 0 FJT} {2361967200 46800 1 FJST} {2368015200 43200 0 FJT} {2393416800 46800 1 FJST} {2400069600 43200 0 FJT} {2424866400 46800 1 FJST} {2431519200 43200 0 FJT} {2456316000 46800 1 FJST} {2462968800 43200 0 FJT} {2487765600 46800 1 FJST} {2494418400 43200 0 FJT} {2519820000 46800 1 FJST} {2525868000 43200 0 FJT} {2551269600 46800 1 FJST} {2557317600 43200 0 FJT} {2582719200 46800 1 FJST} {2589372000 43200 0 FJT} {2614168800 46800 1 FJST} {2620821600 43200 0 FJT} {2645618400 46800 1 FJST} {2652271200 43200 0 FJT} {2677068000 46800 1 FJST} {2683720800 43200 0 FJT} {2709122400 46800 1 FJST} {2715170400 43200 0 FJT} {2740572000 46800 1 FJST} {2747224800 43200 0 FJT} {2772021600 46800 1 FJST} {2778674400 43200 0 FJT} {2803471200 46800 1 FJST} {2810124000 43200 0 FJT} {2834920800 46800 1 FJST} {2841573600 43200 0 FJT} {2866975200 46800 1 FJST} {2873023200 43200 0 FJT} {2898424800 46800 1 FJST} {2904472800 43200 0 FJT} {2929874400 46800 1 FJST} {2936527200 43200 0 FJT} {2961324000 46800 1 FJST} {2967976800 43200 0 FJT} {2992773600 46800 1 FJST} {2999426400 43200 0 FJT} {3024223200 46800 1 FJST} {3030876000 43200 0 FJT} {3056277600 46800 1 FJST} {3062325600 43200 0 FJT} {3087727200 46800 1 FJST} {3093775200 43200 0 FJT} {3119176800 46800 1 FJST} {3125829600 43200 0 FJT} {3150626400 46800 1 FJST} {3157279200 43200 0 FJT} {3182076000 46800 1 FJST} {3188728800 43200 0 FJT} {3213525600 46800 1 FJST} {3220178400 43200 0 FJT} {3245580000 46800 1 FJST} {3251628000 43200 0 FJT} {3277029600 46800 1 FJST} {3283682400 43200 0 FJT} {3308479200 46800 1 FJST} {3315132000 43200 0 FJT} {3339928800 46800 1 FJST} {3346581600 43200 0 FJT} {3371378400 46800 1 FJST} {3378031200 43200 0 FJT} {3403432800 46800 1 FJST} {3409480800 43200 0 FJT} {3434882400 46800 1 FJST} {3440930400 43200 0 FJT} {3466332000 46800 1 FJST} {3472984800 43200 0 FJT} {3497781600 46800 1 FJST} {3504434400 43200 0 FJT} {3529231200 46800 1 FJST} {3535884000 43200 0 FJT} {3560680800 46800 1 FJST} {3567333600 43200 0 FJT} {3592735200 46800 1 FJST} {3598783200 43200 0 FJT} {3624184800 46800 1 FJST} {3630837600 43200 0 FJT} {3655634400 46800 1 FJST} {3662287200 43200 0 FJT} {3687084000 46800 1 FJST} {3693736800 43200 0 FJT} {3718533600 46800 1 FJST} {3725186400 43200 0 FJT} {3750588000 46800 1 FJST} {3756636000 43200 0 FJT} {3782037600 46800 1 FJST} {3788085600 43200 0 FJT} {3813487200 46800 1 FJST} {3820140000 43200 0 FJT} {3844936800 46800 1 FJST} {3851589600 43200 0 FJT} {3876386400 46800 1 FJST} {3883039200 43200 0 FJT} {3907836000 46800 1 FJST} {3914488800 43200 0 FJT} {3939890400 46800 1 FJST} {3945938400 43200 0 FJT} {3971340000 46800 1 FJST} {3977388000 43200 0 FJT} {4002789600 46800 1 FJST} {4009442400 43200 0 FJT} {4034239200 46800 1 FJST} {4040892000 43200 0 FJT} {4065688800 46800 1 FJST} {4072341600 43200 0 FJT} {4097138400 46800 1 FJST} } tcl8.6.5/library/tzdata/Pacific/Niue0000644000175000017500000000031512661614722016677 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Niue) { {-9223372036854775808 -40780 0 LMT} {-2177412020 -40800 0 NUT} {-599575200 -41400 0 NUT} {276089400 -39600 0 NUT} } tcl8.6.5/library/tzdata/Pacific/Samoa0000644000175000017500000000027412661614722017043 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Pago_Pago)]} { LoadTimeZoneFile Pacific/Pago_Pago } set TZData(:Pacific/Samoa) $TZData(:Pacific/Pago_Pago) tcl8.6.5/library/tzdata/Pacific/Wake0000644000175000017500000000022112661614722016662 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Wake) { {-9223372036854775808 39988 0 LMT} {-2177492788 43200 0 WAKT} } tcl8.6.5/library/tzdata/Pacific/Saipan0000644000175000017500000000025612663660066017222 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Guam)]} { LoadTimeZoneFile Pacific/Guam } set TZData(:Pacific/Saipan) $TZData(:Pacific/Guam) tcl8.6.5/library/tzdata/Pacific/Enderbury0000644000175000017500000000032312661614722017735 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Enderbury) { {-9223372036854775808 -41060 0 LMT} {-2177411740 -43200 0 PHOT} {307627200 -39600 0 PHOT} {788958000 46800 0 PHOT} } tcl8.6.5/library/tzdata/Pacific/Auckland0000644000175000017500000002044712661614721017530 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Auckland) { {-9223372036854775808 41944 0 LMT} {-3192435544 41400 0 NZMT} {-1330335000 45000 1 NZST} {-1320057000 41400 0 NZMT} {-1300699800 43200 1 NZST} {-1287396000 41400 0 NZMT} {-1269250200 43200 1 NZST} {-1255946400 41400 0 NZMT} {-1237800600 43200 1 NZST} {-1224496800 41400 0 NZMT} {-1206351000 43200 1 NZST} {-1192442400 41400 0 NZMT} {-1174901400 43200 1 NZST} {-1160992800 41400 0 NZMT} {-1143451800 43200 1 NZST} {-1125914400 41400 0 NZMT} {-1112607000 43200 1 NZST} {-1094464800 41400 0 NZMT} {-1081157400 43200 1 NZST} {-1063015200 41400 0 NZMT} {-1049707800 43200 1 NZST} {-1031565600 41400 0 NZMT} {-1018258200 43200 1 NZST} {-1000116000 41400 0 NZMT} {-986808600 43200 1 NZST} {-968061600 41400 0 NZMT} {-955359000 43200 1 NZST} {-936612000 41400 0 NZMT} {-923304600 43200 1 NZST} {-757425600 43200 0 NZST} {152632800 46800 1 NZDT} {162309600 43200 0 NZST} {183477600 46800 1 NZDT} {194968800 43200 0 NZST} {215532000 46800 1 NZDT} {226418400 43200 0 NZST} {246981600 46800 1 NZDT} {257868000 43200 0 NZST} {278431200 46800 1 NZDT} {289317600 43200 0 NZST} {309880800 46800 1 NZDT} {320767200 43200 0 NZST} {341330400 46800 1 NZDT} {352216800 43200 0 NZST} {372780000 46800 1 NZDT} {384271200 43200 0 NZST} {404834400 46800 1 NZDT} {415720800 43200 0 NZST} {436284000 46800 1 NZDT} {447170400 43200 0 NZST} {467733600 46800 1 NZDT} {478620000 43200 0 NZST} {499183200 46800 1 NZDT} {510069600 43200 0 NZST} {530632800 46800 1 NZDT} {541519200 43200 0 NZST} {562082400 46800 1 NZDT} {573573600 43200 0 NZST} {594136800 46800 1 NZDT} {605023200 43200 0 NZST} {623772000 46800 1 NZDT} {637682400 43200 0 NZST} {655221600 46800 1 NZDT} {669132000 43200 0 NZST} {686671200 46800 1 NZDT} {700581600 43200 0 NZST} {718120800 46800 1 NZDT} {732636000 43200 0 NZST} {749570400 46800 1 NZDT} {764085600 43200 0 NZST} {781020000 46800 1 NZDT} {795535200 43200 0 NZST} {812469600 46800 1 NZDT} {826984800 43200 0 NZST} {844524000 46800 1 NZDT} {858434400 43200 0 NZST} {875973600 46800 1 NZDT} {889884000 43200 0 NZST} {907423200 46800 1 NZDT} {921938400 43200 0 NZST} {938872800 46800 1 NZDT} {953388000 43200 0 NZST} {970322400 46800 1 NZDT} {984837600 43200 0 NZST} {1002376800 46800 1 NZDT} {1016287200 43200 0 NZST} {1033826400 46800 1 NZDT} {1047736800 43200 0 NZST} {1065276000 46800 1 NZDT} {1079791200 43200 0 NZST} {1096725600 46800 1 NZDT} {1111240800 43200 0 NZST} {1128175200 46800 1 NZDT} {1142690400 43200 0 NZST} {1159624800 46800 1 NZDT} {1174140000 43200 0 NZST} {1191074400 46800 1 NZDT} {1207404000 43200 0 NZST} {1222524000 46800 1 NZDT} {1238853600 43200 0 NZST} {1253973600 46800 1 NZDT} {1270303200 43200 0 NZST} {1285423200 46800 1 NZDT} {1301752800 43200 0 NZST} {1316872800 46800 1 NZDT} {1333202400 43200 0 NZST} {1348927200 46800 1 NZDT} {1365256800 43200 0 NZST} {1380376800 46800 1 NZDT} {1396706400 43200 0 NZST} {1411826400 46800 1 NZDT} {1428156000 43200 0 NZST} {1443276000 46800 1 NZDT} {1459605600 43200 0 NZST} {1474725600 46800 1 NZDT} {1491055200 43200 0 NZST} {1506175200 46800 1 NZDT} {1522504800 43200 0 NZST} {1538229600 46800 1 NZDT} {1554559200 43200 0 NZST} {1569679200 46800 1 NZDT} {1586008800 43200 0 NZST} {1601128800 46800 1 NZDT} {1617458400 43200 0 NZST} {1632578400 46800 1 NZDT} {1648908000 43200 0 NZST} {1664028000 46800 1 NZDT} {1680357600 43200 0 NZST} {1695477600 46800 1 NZDT} {1712412000 43200 0 NZST} {1727532000 46800 1 NZDT} {1743861600 43200 0 NZST} {1758981600 46800 1 NZDT} {1775311200 43200 0 NZST} {1790431200 46800 1 NZDT} {1806760800 43200 0 NZST} {1821880800 46800 1 NZDT} {1838210400 43200 0 NZST} {1853330400 46800 1 NZDT} {1869660000 43200 0 NZST} {1885384800 46800 1 NZDT} {1901714400 43200 0 NZST} {1916834400 46800 1 NZDT} {1933164000 43200 0 NZST} {1948284000 46800 1 NZDT} {1964613600 43200 0 NZST} {1979733600 46800 1 NZDT} {1996063200 43200 0 NZST} {2011183200 46800 1 NZDT} {2027512800 43200 0 NZST} {2042632800 46800 1 NZDT} {2058962400 43200 0 NZST} {2074687200 46800 1 NZDT} {2091016800 43200 0 NZST} {2106136800 46800 1 NZDT} {2122466400 43200 0 NZST} {2137586400 46800 1 NZDT} {2153916000 43200 0 NZST} {2169036000 46800 1 NZDT} {2185365600 43200 0 NZST} {2200485600 46800 1 NZDT} {2216815200 43200 0 NZST} {2232540000 46800 1 NZDT} {2248869600 43200 0 NZST} {2263989600 46800 1 NZDT} {2280319200 43200 0 NZST} {2295439200 46800 1 NZDT} {2311768800 43200 0 NZST} {2326888800 46800 1 NZDT} {2343218400 43200 0 NZST} {2358338400 46800 1 NZDT} {2374668000 43200 0 NZST} {2389788000 46800 1 NZDT} {2406117600 43200 0 NZST} {2421842400 46800 1 NZDT} {2438172000 43200 0 NZST} {2453292000 46800 1 NZDT} {2469621600 43200 0 NZST} {2484741600 46800 1 NZDT} {2501071200 43200 0 NZST} {2516191200 46800 1 NZDT} {2532520800 43200 0 NZST} {2547640800 46800 1 NZDT} {2563970400 43200 0 NZST} {2579090400 46800 1 NZDT} {2596024800 43200 0 NZST} {2611144800 46800 1 NZDT} {2627474400 43200 0 NZST} {2642594400 46800 1 NZDT} {2658924000 43200 0 NZST} {2674044000 46800 1 NZDT} {2690373600 43200 0 NZST} {2705493600 46800 1 NZDT} {2721823200 43200 0 NZST} {2736943200 46800 1 NZDT} {2753272800 43200 0 NZST} {2768997600 46800 1 NZDT} {2785327200 43200 0 NZST} {2800447200 46800 1 NZDT} {2816776800 43200 0 NZST} {2831896800 46800 1 NZDT} {2848226400 43200 0 NZST} {2863346400 46800 1 NZDT} {2879676000 43200 0 NZST} {2894796000 46800 1 NZDT} {2911125600 43200 0 NZST} {2926245600 46800 1 NZDT} {2942575200 43200 0 NZST} {2958300000 46800 1 NZDT} {2974629600 43200 0 NZST} {2989749600 46800 1 NZDT} {3006079200 43200 0 NZST} {3021199200 46800 1 NZDT} {3037528800 43200 0 NZST} {3052648800 46800 1 NZDT} {3068978400 43200 0 NZST} {3084098400 46800 1 NZDT} {3100428000 43200 0 NZST} {3116152800 46800 1 NZDT} {3132482400 43200 0 NZST} {3147602400 46800 1 NZDT} {3163932000 43200 0 NZST} {3179052000 46800 1 NZDT} {3195381600 43200 0 NZST} {3210501600 46800 1 NZDT} {3226831200 43200 0 NZST} {3241951200 46800 1 NZDT} {3258280800 43200 0 NZST} {3273400800 46800 1 NZDT} {3289730400 43200 0 NZST} {3305455200 46800 1 NZDT} {3321784800 43200 0 NZST} {3336904800 46800 1 NZDT} {3353234400 43200 0 NZST} {3368354400 46800 1 NZDT} {3384684000 43200 0 NZST} {3399804000 46800 1 NZDT} {3416133600 43200 0 NZST} {3431253600 46800 1 NZDT} {3447583200 43200 0 NZST} {3462703200 46800 1 NZDT} {3479637600 43200 0 NZST} {3494757600 46800 1 NZDT} {3511087200 43200 0 NZST} {3526207200 46800 1 NZDT} {3542536800 43200 0 NZST} {3557656800 46800 1 NZDT} {3573986400 43200 0 NZST} {3589106400 46800 1 NZDT} {3605436000 43200 0 NZST} {3620556000 46800 1 NZDT} {3636885600 43200 0 NZST} {3652610400 46800 1 NZDT} {3668940000 43200 0 NZST} {3684060000 46800 1 NZDT} {3700389600 43200 0 NZST} {3715509600 46800 1 NZDT} {3731839200 43200 0 NZST} {3746959200 46800 1 NZDT} {3763288800 43200 0 NZST} {3778408800 46800 1 NZDT} {3794738400 43200 0 NZST} {3809858400 46800 1 NZDT} {3826188000 43200 0 NZST} {3841912800 46800 1 NZDT} {3858242400 43200 0 NZST} {3873362400 46800 1 NZDT} {3889692000 43200 0 NZST} {3904812000 46800 1 NZDT} {3921141600 43200 0 NZST} {3936261600 46800 1 NZDT} {3952591200 43200 0 NZST} {3967711200 46800 1 NZDT} {3984040800 43200 0 NZST} {3999765600 46800 1 NZDT} {4016095200 43200 0 NZST} {4031215200 46800 1 NZDT} {4047544800 43200 0 NZST} {4062664800 46800 1 NZDT} {4078994400 43200 0 NZST} {4094114400 46800 1 NZDT} } tcl8.6.5/library/tzdata/Pacific/Pago_Pago0000644000175000017500000000035712663660066017645 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Pago_Pago) { {-9223372036854775808 45432 0 LMT} {-2855738232 -40968 0 LMT} {-1861879032 -39600 0 NST} {-86878800 -39600 0 BST} {439038000 -39600 0 SST} } tcl8.6.5/library/tzdata/Pacific/Norfolk0000644000175000017500000000040612663660066017416 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Pacific/Norfolk) { {-9223372036854775808 40312 0 LMT} {-2177493112 40320 0 NMT} {-599656320 41400 0 NFT} {152029800 45000 1 NFST} {162912600 41400 0 NFT} {1443882600 39600 0 NFT} } tcl8.6.5/library/tzdata/Africa/0000755000175000017500000000000012665173607015712 5ustar sergeisergeitcl8.6.5/library/tzdata/Africa/Asmara0000644000175000017500000000026312663660066017040 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Nairobi)]} { LoadTimeZoneFile Africa/Nairobi } set TZData(:Africa/Asmara) $TZData(:Africa/Nairobi) tcl8.6.5/library/tzdata/Africa/Tunis0000644000175000017500000000206012663653207016732 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Tunis) { {-9223372036854775808 2444 0 LMT} {-2797202444 561 0 PMT} {-1855958961 3600 0 CET} {-969242400 7200 1 CEST} {-950493600 3600 0 CET} {-941940000 7200 1 CEST} {-891136800 3600 0 CET} {-877827600 7200 1 CEST} {-857257200 3600 0 CET} {-844556400 7200 1 CEST} {-842918400 3600 0 CET} {-842223600 7200 1 CEST} {-828230400 3600 0 CET} {-812502000 7200 1 CEST} {-796269600 3600 0 CET} {-781052400 7200 1 CEST} {-766634400 3600 0 CET} {231202800 7200 1 CEST} {243903600 3600 0 CET} {262825200 7200 1 CEST} {276044400 3600 0 CET} {581122800 7200 1 CEST} {591145200 3600 0 CET} {606870000 7200 1 CEST} {622594800 3600 0 CET} {641516400 7200 1 CEST} {654649200 3600 0 CET} {1114902000 7200 1 CEST} {1128038400 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} } tcl8.6.5/library/tzdata/Africa/El_Aaiun0000644000175000017500000001337512663660066017321 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/El_Aaiun) { {-9223372036854775808 -3168 0 LMT} {-1136070432 -3600 0 WAT} {198291600 0 0 WET} {199756800 3600 1 WEST} {207702000 0 0 WET} {231292800 3600 1 WEST} {244249200 0 0 WET} {265507200 3600 1 WEST} {271033200 0 0 WET} {1212278400 3600 1 WEST} {1220223600 0 0 WET} {1243814400 3600 1 WEST} {1250809200 0 0 WET} {1272758400 3600 1 WEST} {1281222000 0 0 WET} {1301788800 3600 1 WEST} {1312066800 0 0 WET} {1335664800 3600 1 WEST} {1342749600 0 0 WET} {1345428000 3600 1 WEST} {1348970400 0 0 WET} {1367114400 3600 1 WEST} {1373162400 0 0 WET} {1376100000 3600 1 WEST} {1382839200 0 0 WET} {1396144800 3600 1 WEST} {1403920800 0 0 WET} {1406944800 3600 1 WEST} {1414288800 0 0 WET} {1427594400 3600 1 WEST} {1434247200 0 0 WET} {1437271200 3600 1 WEST} {1445738400 0 0 WET} {1459044000 3600 1 WEST} {1465092000 0 0 WET} {1468116000 3600 1 WEST} {1477792800 0 0 WET} {1490493600 3600 1 WEST} {1495332000 0 0 WET} {1498960800 3600 1 WEST} {1509242400 0 0 WET} {1521943200 3600 1 WEST} {1526176800 0 0 WET} {1529200800 3600 1 WEST} {1540692000 0 0 WET} {1553997600 3600 1 WEST} {1557021600 0 0 WET} {1560045600 3600 1 WEST} {1572141600 0 0 WET} {1585447200 3600 1 WEST} {1587261600 0 0 WET} {1590285600 3600 1 WEST} {1603591200 0 0 WET} {1616896800 3600 1 WEST} {1618106400 0 0 WET} {1621130400 3600 1 WEST} {1635645600 0 0 WET} {1651975200 3600 1 WEST} {1667095200 0 0 WET} {1682215200 3600 1 WEST} {1698544800 0 0 WET} {1713060000 3600 1 WEST} {1729994400 0 0 WET} {1743904800 3600 1 WEST} {1761444000 0 0 WET} {1774749600 3600 1 WEST} {1792893600 0 0 WET} {1806199200 3600 1 WEST} {1824948000 0 0 WET} {1837648800 3600 1 WEST} {1856397600 0 0 WET} {1869098400 3600 1 WEST} {1887847200 0 0 WET} {1901152800 3600 1 WEST} {1919296800 0 0 WET} {1932602400 3600 1 WEST} {1950746400 0 0 WET} {1964052000 3600 1 WEST} {1982800800 0 0 WET} {1995501600 3600 1 WEST} {2014250400 0 0 WET} {2026951200 3600 1 WEST} {2045700000 0 0 WET} {2058400800 3600 1 WEST} {2077149600 0 0 WET} {2090455200 3600 1 WEST} {2107994400 0 0 WET} {2108602800 0 0 WET} {2121904800 3600 1 WEST} {2138234400 0 0 WET} {2140052400 0 0 WET} {2153354400 3600 1 WEST} {2172103200 0 0 WET} {2184804000 3600 1 WEST} {2203552800 0 0 WET} {2216253600 3600 1 WEST} {2235002400 0 0 WET} {2248308000 3600 1 WEST} {2266452000 0 0 WET} {2279757600 3600 1 WEST} {2297901600 0 0 WET} {2311207200 3600 1 WEST} {2329351200 0 0 WET} {2342656800 3600 1 WEST} {2361405600 0 0 WET} {2374106400 3600 1 WEST} {2392855200 0 0 WET} {2405556000 3600 1 WEST} {2424304800 0 0 WET} {2437610400 3600 1 WEST} {2455754400 0 0 WET} {2469060000 3600 1 WEST} {2487204000 0 0 WET} {2500509600 3600 1 WEST} {2519258400 0 0 WET} {2531959200 3600 1 WEST} {2550708000 0 0 WET} {2563408800 3600 1 WEST} {2582157600 0 0 WET} {2595463200 3600 1 WEST} {2613607200 0 0 WET} {2626912800 3600 1 WEST} {2645056800 0 0 WET} {2658362400 3600 1 WEST} {2676506400 0 0 WET} {2689812000 3600 1 WEST} {2708560800 0 0 WET} {2721261600 3600 1 WEST} {2740010400 0 0 WET} {2752711200 3600 1 WEST} {2771460000 0 0 WET} {2784765600 3600 1 WEST} {2802909600 0 0 WET} {2816215200 3600 1 WEST} {2834359200 0 0 WET} {2847664800 3600 1 WEST} {2866413600 0 0 WET} {2879114400 3600 1 WEST} {2897863200 0 0 WET} {2910564000 3600 1 WEST} {2929312800 0 0 WET} {2942013600 3600 1 WEST} {2960762400 0 0 WET} {2974068000 3600 1 WEST} {2992212000 0 0 WET} {3005517600 3600 1 WEST} {3023661600 0 0 WET} {3036967200 3600 1 WEST} {3055716000 0 0 WET} {3068416800 3600 1 WEST} {3087165600 0 0 WET} {3099866400 3600 1 WEST} {3118615200 0 0 WET} {3131920800 3600 1 WEST} {3150064800 0 0 WET} {3163370400 3600 1 WEST} {3181514400 0 0 WET} {3194820000 3600 1 WEST} {3212964000 0 0 WET} {3226269600 3600 1 WEST} {3245018400 0 0 WET} {3257719200 3600 1 WEST} {3276468000 0 0 WET} {3289168800 3600 1 WEST} {3307917600 0 0 WET} {3321223200 3600 1 WEST} {3339367200 0 0 WET} {3352672800 3600 1 WEST} {3370816800 0 0 WET} {3384122400 3600 1 WEST} {3402871200 0 0 WET} {3415572000 3600 1 WEST} {3434320800 0 0 WET} {3447021600 3600 1 WEST} {3465770400 0 0 WET} {3479076000 3600 1 WEST} {3497220000 0 0 WET} {3510525600 3600 1 WEST} {3528669600 0 0 WET} {3541975200 3600 1 WEST} {3560119200 0 0 WET} {3573424800 3600 1 WEST} {3592173600 0 0 WET} {3604874400 3600 1 WEST} {3623623200 0 0 WET} {3636324000 3600 1 WEST} {3655072800 0 0 WET} {3668378400 3600 1 WEST} {3686522400 0 0 WET} {3699828000 3600 1 WEST} {3717972000 0 0 WET} {3731277600 3600 1 WEST} {3750026400 0 0 WET} {3762727200 3600 1 WEST} {3781476000 0 0 WET} {3794176800 3600 1 WEST} {3812925600 0 0 WET} {3825626400 3600 1 WEST} {3844375200 0 0 WET} {3857680800 3600 1 WEST} {3875824800 0 0 WET} {3889130400 3600 1 WEST} {3907274400 0 0 WET} {3920580000 3600 1 WEST} {3939328800 0 0 WET} {3952029600 3600 1 WEST} {3970778400 0 0 WET} {3983479200 3600 1 WEST} {4002228000 0 0 WET} {4015533600 3600 1 WEST} {4033677600 0 0 WET} {4046983200 3600 1 WEST} {4065127200 0 0 WET} {4078432800 3600 1 WEST} {4096576800 0 0 WET} } tcl8.6.5/library/tzdata/Africa/Conakry0000644000175000017500000000026412663660066017243 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Abidjan)]} { LoadTimeZoneFile Africa/Abidjan } set TZData(:Africa/Conakry) $TZData(:Africa/Abidjan) tcl8.6.5/library/tzdata/Africa/Freetown0000644000175000017500000000026512663660066017427 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Abidjan)]} { LoadTimeZoneFile Africa/Abidjan } set TZData(:Africa/Freetown) $TZData(:Africa/Abidjan) tcl8.6.5/library/tzdata/Africa/Lagos0000644000175000017500000000021512661614720016670 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Lagos) { {-9223372036854775808 816 0 LMT} {-1588464816 3600 0 WAT} } tcl8.6.5/library/tzdata/Africa/Asmera0000644000175000017500000000026312663660066017044 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Nairobi)]} { LoadTimeZoneFile Africa/Nairobi } set TZData(:Africa/Asmera) $TZData(:Africa/Nairobi) tcl8.6.5/library/tzdata/Africa/Kampala0000644000175000017500000000026412663660066017203 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Nairobi)]} { LoadTimeZoneFile Africa/Nairobi } set TZData(:Africa/Kampala) $TZData(:Africa/Nairobi) tcl8.6.5/library/tzdata/Africa/Monrovia0000644000175000017500000000031012661614720017411 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Monrovia) { {-9223372036854775808 -2588 0 LMT} {-2776979812 -2588 0 MMT} {-1604359012 -2670 0 LRT} {73529070 0 0 GMT} } tcl8.6.5/library/tzdata/Africa/Juba0000644000175000017500000000026412663660066016516 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Khartoum)]} { LoadTimeZoneFile Africa/Khartoum } set TZData(:Africa/Juba) $TZData(:Africa/Khartoum) tcl8.6.5/library/tzdata/Africa/Nairobi0000644000175000017500000000035212663660066017216 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Nairobi) { {-9223372036854775808 8836 0 LMT} {-1309746436 10800 0 EAT} {-1262314800 9000 0 BEAT} {-946780200 9900 0 BEAUT} {-315629100 10800 0 EAT} } tcl8.6.5/library/tzdata/Africa/Timbuktu0000644000175000017500000000026512663660066017442 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Abidjan)]} { LoadTimeZoneFile Africa/Abidjan } set TZData(:Africa/Timbuktu) $TZData(:Africa/Abidjan) tcl8.6.5/library/tzdata/Africa/Lusaka0000644000175000017500000000026012663660066017051 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Maputo)]} { LoadTimeZoneFile Africa/Maputo } set TZData(:Africa/Lusaka) $TZData(:Africa/Maputo) tcl8.6.5/library/tzdata/Africa/Banjul0000644000175000017500000000026312663660066017047 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Abidjan)]} { LoadTimeZoneFile Africa/Abidjan } set TZData(:Africa/Banjul) $TZData(:Africa/Abidjan) tcl8.6.5/library/tzdata/Africa/Blantyre0000644000175000017500000000026212663660066017413 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Maputo)]} { LoadTimeZoneFile Africa/Maputo } set TZData(:Africa/Blantyre) $TZData(:Africa/Maputo) tcl8.6.5/library/tzdata/Africa/Casablanca0000644000175000017500000001404012663660066017642 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Casablanca) { {-9223372036854775808 -1820 0 LMT} {-1773012580 0 0 WET} {-956361600 3600 1 WEST} {-950490000 0 0 WET} {-942019200 3600 1 WEST} {-761187600 0 0 WET} {-617241600 3600 1 WEST} {-605149200 0 0 WET} {-81432000 3600 1 WEST} {-71110800 0 0 WET} {141264000 3600 1 WEST} {147222000 0 0 WET} {199756800 3600 1 WEST} {207702000 0 0 WET} {231292800 3600 1 WEST} {244249200 0 0 WET} {265507200 3600 1 WEST} {271033200 0 0 WET} {448243200 3600 0 CET} {504918000 0 0 WET} {1212278400 3600 1 WEST} {1220223600 0 0 WET} {1243814400 3600 1 WEST} {1250809200 0 0 WET} {1272758400 3600 1 WEST} {1281222000 0 0 WET} {1301788800 3600 1 WEST} {1312066800 0 0 WET} {1335664800 3600 1 WEST} {1342749600 0 0 WET} {1345428000 3600 1 WEST} {1348970400 0 0 WET} {1367114400 3600 1 WEST} {1373162400 0 0 WET} {1376100000 3600 1 WEST} {1382839200 0 0 WET} {1396144800 3600 1 WEST} {1403920800 0 0 WET} {1406944800 3600 1 WEST} {1414288800 0 0 WET} {1427594400 3600 1 WEST} {1434247200 0 0 WET} {1437271200 3600 1 WEST} {1445738400 0 0 WET} {1459044000 3600 1 WEST} {1465092000 0 0 WET} {1468116000 3600 1 WEST} {1477792800 0 0 WET} {1490493600 3600 1 WEST} {1495332000 0 0 WET} {1498960800 3600 1 WEST} {1509242400 0 0 WET} {1521943200 3600 1 WEST} {1526176800 0 0 WET} {1529200800 3600 1 WEST} {1540692000 0 0 WET} {1553997600 3600 1 WEST} {1557021600 0 0 WET} {1560045600 3600 1 WEST} {1572141600 0 0 WET} {1585447200 3600 1 WEST} {1587261600 0 0 WET} {1590285600 3600 1 WEST} {1603591200 0 0 WET} {1616896800 3600 1 WEST} {1618106400 0 0 WET} {1621130400 3600 1 WEST} {1635645600 0 0 WET} {1651975200 3600 1 WEST} {1667095200 0 0 WET} {1682215200 3600 1 WEST} {1698544800 0 0 WET} {1713060000 3600 1 WEST} {1729994400 0 0 WET} {1743904800 3600 1 WEST} {1761444000 0 0 WET} {1774749600 3600 1 WEST} {1792893600 0 0 WET} {1806199200 3600 1 WEST} {1824948000 0 0 WET} {1837648800 3600 1 WEST} {1856397600 0 0 WET} {1869098400 3600 1 WEST} {1887847200 0 0 WET} {1901152800 3600 1 WEST} {1919296800 0 0 WET} {1932602400 3600 1 WEST} {1950746400 0 0 WET} {1964052000 3600 1 WEST} {1982800800 0 0 WET} {1995501600 3600 1 WEST} {2014250400 0 0 WET} {2026951200 3600 1 WEST} {2045700000 0 0 WET} {2058400800 3600 1 WEST} {2077149600 0 0 WET} {2090455200 3600 1 WEST} {2107994400 0 0 WET} {2108602800 0 0 WET} {2121904800 3600 1 WEST} {2138234400 0 0 WET} {2140052400 0 0 WET} {2153354400 3600 1 WEST} {2172103200 0 0 WET} {2184804000 3600 1 WEST} {2203552800 0 0 WET} {2216253600 3600 1 WEST} {2235002400 0 0 WET} {2248308000 3600 1 WEST} {2266452000 0 0 WET} {2279757600 3600 1 WEST} {2297901600 0 0 WET} {2311207200 3600 1 WEST} {2329351200 0 0 WET} {2342656800 3600 1 WEST} {2361405600 0 0 WET} {2374106400 3600 1 WEST} {2392855200 0 0 WET} {2405556000 3600 1 WEST} {2424304800 0 0 WET} {2437610400 3600 1 WEST} {2455754400 0 0 WET} {2469060000 3600 1 WEST} {2487204000 0 0 WET} {2500509600 3600 1 WEST} {2519258400 0 0 WET} {2531959200 3600 1 WEST} {2550708000 0 0 WET} {2563408800 3600 1 WEST} {2582157600 0 0 WET} {2595463200 3600 1 WEST} {2613607200 0 0 WET} {2626912800 3600 1 WEST} {2645056800 0 0 WET} {2658362400 3600 1 WEST} {2676506400 0 0 WET} {2689812000 3600 1 WEST} {2708560800 0 0 WET} {2721261600 3600 1 WEST} {2740010400 0 0 WET} {2752711200 3600 1 WEST} {2771460000 0 0 WET} {2784765600 3600 1 WEST} {2802909600 0 0 WET} {2816215200 3600 1 WEST} {2834359200 0 0 WET} {2847664800 3600 1 WEST} {2866413600 0 0 WET} {2879114400 3600 1 WEST} {2897863200 0 0 WET} {2910564000 3600 1 WEST} {2929312800 0 0 WET} {2942013600 3600 1 WEST} {2960762400 0 0 WET} {2974068000 3600 1 WEST} {2992212000 0 0 WET} {3005517600 3600 1 WEST} {3023661600 0 0 WET} {3036967200 3600 1 WEST} {3055716000 0 0 WET} {3068416800 3600 1 WEST} {3087165600 0 0 WET} {3099866400 3600 1 WEST} {3118615200 0 0 WET} {3131920800 3600 1 WEST} {3150064800 0 0 WET} {3163370400 3600 1 WEST} {3181514400 0 0 WET} {3194820000 3600 1 WEST} {3212964000 0 0 WET} {3226269600 3600 1 WEST} {3245018400 0 0 WET} {3257719200 3600 1 WEST} {3276468000 0 0 WET} {3289168800 3600 1 WEST} {3307917600 0 0 WET} {3321223200 3600 1 WEST} {3339367200 0 0 WET} {3352672800 3600 1 WEST} {3370816800 0 0 WET} {3384122400 3600 1 WEST} {3402871200 0 0 WET} {3415572000 3600 1 WEST} {3434320800 0 0 WET} {3447021600 3600 1 WEST} {3465770400 0 0 WET} {3479076000 3600 1 WEST} {3497220000 0 0 WET} {3510525600 3600 1 WEST} {3528669600 0 0 WET} {3541975200 3600 1 WEST} {3560119200 0 0 WET} {3573424800 3600 1 WEST} {3592173600 0 0 WET} {3604874400 3600 1 WEST} {3623623200 0 0 WET} {3636324000 3600 1 WEST} {3655072800 0 0 WET} {3668378400 3600 1 WEST} {3686522400 0 0 WET} {3699828000 3600 1 WEST} {3717972000 0 0 WET} {3731277600 3600 1 WEST} {3750026400 0 0 WET} {3762727200 3600 1 WEST} {3781476000 0 0 WET} {3794176800 3600 1 WEST} {3812925600 0 0 WET} {3825626400 3600 1 WEST} {3844375200 0 0 WET} {3857680800 3600 1 WEST} {3875824800 0 0 WET} {3889130400 3600 1 WEST} {3907274400 0 0 WET} {3920580000 3600 1 WEST} {3939328800 0 0 WET} {3952029600 3600 1 WEST} {3970778400 0 0 WET} {3983479200 3600 1 WEST} {4002228000 0 0 WET} {4015533600 3600 1 WEST} {4033677600 0 0 WET} {4046983200 3600 1 WEST} {4065127200 0 0 WET} {4078432800 3600 1 WEST} {4096576800 0 0 WET} } tcl8.6.5/library/tzdata/Africa/Lome0000644000175000017500000000026112663660066016526 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Abidjan)]} { LoadTimeZoneFile Africa/Abidjan } set TZData(:Africa/Lome) $TZData(:Africa/Abidjan) tcl8.6.5/library/tzdata/Africa/Niamey0000644000175000017500000000025512663660066017057 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Lagos)]} { LoadTimeZoneFile Africa/Lagos } set TZData(:Africa/Niamey) $TZData(:Africa/Lagos) tcl8.6.5/library/tzdata/Africa/Kigali0000644000175000017500000000026012663660066017031 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Maputo)]} { LoadTimeZoneFile Africa/Maputo } set TZData(:Africa/Kigali) $TZData(:Africa/Maputo) tcl8.6.5/library/tzdata/Africa/Mogadishu0000644000175000017500000000026612663660066017557 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Nairobi)]} { LoadTimeZoneFile Africa/Nairobi } set TZData(:Africa/Mogadishu) $TZData(:Africa/Nairobi) tcl8.6.5/library/tzdata/Africa/Abidjan0000644000175000017500000000021512661614720017153 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Abidjan) { {-9223372036854775808 -968 0 LMT} {-1830383032 0 0 GMT} } tcl8.6.5/library/tzdata/Africa/Porto-Novo0000644000175000017500000000026112663660066017654 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Lagos)]} { LoadTimeZoneFile Africa/Lagos } set TZData(:Africa/Porto-Novo) $TZData(:Africa/Lagos) tcl8.6.5/library/tzdata/Africa/Maseru0000644000175000017500000000030212663660066017062 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Johannesburg)]} { LoadTimeZoneFile Africa/Johannesburg } set TZData(:Africa/Maseru) $TZData(:Africa/Johannesburg) tcl8.6.5/library/tzdata/Africa/Harare0000644000175000017500000000026012663660066017033 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Maputo)]} { LoadTimeZoneFile Africa/Maputo } set TZData(:Africa/Harare) $TZData(:Africa/Maputo) tcl8.6.5/library/tzdata/Africa/Luanda0000644000175000017500000000025512663660066017041 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Lagos)]} { LoadTimeZoneFile Africa/Lagos } set TZData(:Africa/Luanda) $TZData(:Africa/Lagos) tcl8.6.5/library/tzdata/Africa/Algiers0000644000175000017500000000202112661614720017206 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Algiers) { {-9223372036854775808 732 0 LMT} {-2486679072 561 0 PMT} {-1855958961 0 0 WET} {-1689814800 3600 1 WEST} {-1680397200 0 0 WET} {-1665363600 3600 1 WEST} {-1648342800 0 0 WET} {-1635123600 3600 1 WEST} {-1616893200 0 0 WET} {-1604278800 3600 1 WEST} {-1585443600 0 0 WET} {-1574038800 3600 1 WEST} {-1552266000 0 0 WET} {-1539997200 3600 1 WEST} {-1531443600 0 0 WET} {-956365200 3600 1 WEST} {-950486400 0 0 WET} {-942012000 3600 0 CET} {-812502000 7200 1 CEST} {-796262400 3600 0 CET} {-781052400 7200 1 CEST} {-766630800 3600 0 CET} {-733280400 0 0 WET} {-439430400 3600 0 CET} {-212029200 0 0 WET} {41468400 3600 1 WEST} {54774000 0 0 WET} {231724800 3600 1 WEST} {246240000 3600 0 CET} {259545600 7200 1 CEST} {275274000 3600 0 CET} {309740400 0 0 WET} {325468800 3600 1 WEST} {341802000 0 0 WET} {357523200 3600 0 CET} } tcl8.6.5/library/tzdata/Africa/Malabo0000644000175000017500000000025512663660066017030 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Lagos)]} { LoadTimeZoneFile Africa/Lagos } set TZData(:Africa/Malabo) $TZData(:Africa/Lagos) tcl8.6.5/library/tzdata/Africa/Ndjamena0000644000175000017500000000031012661614720017334 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Ndjamena) { {-9223372036854775808 3612 0 LMT} {-1830387612 3600 0 WAT} {308703600 7200 1 WAST} {321314400 3600 0 WAT} } tcl8.6.5/library/tzdata/Africa/Ouagadougou0000644000175000017500000000027012663660066020111 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Abidjan)]} { LoadTimeZoneFile Africa/Abidjan } set TZData(:Africa/Ouagadougou) $TZData(:Africa/Abidjan) tcl8.6.5/library/tzdata/Africa/Khartoum0000644000175000017500000000204712661614720017422 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Khartoum) { {-9223372036854775808 7808 0 LMT} {-1230775808 7200 0 CAT} {10360800 10800 1 CAST} {24786000 7200 0 CAT} {41810400 10800 1 CAST} {56322000 7200 0 CAT} {73432800 10800 1 CAST} {87944400 7200 0 CAT} {104882400 10800 1 CAST} {119480400 7200 0 CAT} {136332000 10800 1 CAST} {151016400 7200 0 CAT} {167781600 10800 1 CAST} {182552400 7200 0 CAT} {199231200 10800 1 CAST} {214174800 7200 0 CAT} {230680800 10800 1 CAST} {245710800 7200 0 CAT} {262735200 10800 1 CAST} {277246800 7200 0 CAT} {294184800 10800 1 CAST} {308782800 7200 0 CAT} {325634400 10800 1 CAST} {340405200 7200 0 CAT} {357084000 10800 1 CAST} {371941200 7200 0 CAT} {388533600 10800 1 CAST} {403477200 7200 0 CAT} {419983200 10800 1 CAST} {435013200 7200 0 CAT} {452037600 10800 1 CAST} {466635600 7200 0 CAT} {483487200 10800 1 CAST} {498171600 7200 0 CAT} {947930400 10800 0 EAT} } tcl8.6.5/library/tzdata/Africa/Brazzaville0000644000175000017500000000026212663660066020120 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Lagos)]} { LoadTimeZoneFile Africa/Lagos } set TZData(:Africa/Brazzaville) $TZData(:Africa/Lagos) tcl8.6.5/library/tzdata/Africa/Johannesburg0000644000175000017500000000045212661614720020253 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Johannesburg) { {-9223372036854775808 6720 0 LMT} {-2458173120 5400 0 SAST} {-2109288600 7200 0 SAST} {-860976000 10800 1 SAST} {-845254800 7200 0 SAST} {-829526400 10800 1 SAST} {-813805200 7200 0 SAST} } tcl8.6.5/library/tzdata/Africa/Lubumbashi0000644000175000017500000000026412663660066017730 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Maputo)]} { LoadTimeZoneFile Africa/Maputo } set TZData(:Africa/Lubumbashi) $TZData(:Africa/Maputo) tcl8.6.5/library/tzdata/Africa/Douala0000644000175000017500000000025512663660066017042 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Lagos)]} { LoadTimeZoneFile Africa/Lagos } set TZData(:Africa/Douala) $TZData(:Africa/Lagos) tcl8.6.5/library/tzdata/Africa/Libreville0000644000175000017500000000026112663660066017723 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Lagos)]} { LoadTimeZoneFile Africa/Lagos } set TZData(:Africa/Libreville) $TZData(:Africa/Lagos) tcl8.6.5/library/tzdata/Africa/Dar_es_Salaam0000644000175000017500000000027212663660066020307 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Nairobi)]} { LoadTimeZoneFile Africa/Nairobi } set TZData(:Africa/Dar_es_Salaam) $TZData(:Africa/Nairobi) tcl8.6.5/library/tzdata/Africa/Addis_Ababa0000644000175000017500000000027012663660066017724 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Nairobi)]} { LoadTimeZoneFile Africa/Nairobi } set TZData(:Africa/Addis_Ababa) $TZData(:Africa/Nairobi) tcl8.6.5/library/tzdata/Africa/Cairo0000644000175000017500000000721012663660066016670 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Cairo) { {-9223372036854775808 7509 0 LMT} {-2185409109 7200 0 EET} {-929844000 10800 1 EEST} {-923108400 7200 0 EET} {-906170400 10800 1 EEST} {-892868400 7200 0 EET} {-875844000 10800 1 EEST} {-857790000 7200 0 EET} {-844308000 10800 1 EEST} {-825822000 7200 0 EET} {-812685600 10800 1 EEST} {-794199600 7200 0 EET} {-779853600 10800 1 EEST} {-762663600 7200 0 EET} {-399088800 10800 1 EEST} {-386650800 7200 0 EET} {-368330400 10800 1 EEST} {-355114800 7200 0 EET} {-336790800 10800 1 EEST} {-323654400 7200 0 EET} {-305168400 10800 1 EEST} {-292032000 7200 0 EET} {-273632400 10800 1 EEST} {-260496000 7200 0 EET} {-242096400 10800 1 EEST} {-228960000 7200 0 EET} {-210560400 10800 1 EEST} {-197424000 7200 0 EET} {-178938000 10800 1 EEST} {-165801600 7200 0 EET} {-147402000 10800 1 EEST} {-134265600 7200 0 EET} {-115866000 10800 1 EEST} {-102643200 7200 0 EET} {-84330000 10800 1 EEST} {-71107200 7200 0 EET} {-52707600 10800 1 EEST} {-39484800 7200 0 EET} {-21171600 10800 1 EEST} {-7948800 7200 0 EET} {10364400 10800 1 EEST} {23587200 7200 0 EET} {41900400 10800 1 EEST} {55123200 7200 0 EET} {73522800 10800 1 EEST} {86745600 7200 0 EET} {105058800 10800 1 EEST} {118281600 7200 0 EET} {136594800 10800 1 EEST} {149817600 7200 0 EET} {168130800 10800 1 EEST} {181353600 7200 0 EET} {199753200 10800 1 EEST} {212976000 7200 0 EET} {231289200 10800 1 EEST} {244512000 7200 0 EET} {262825200 10800 1 EEST} {276048000 7200 0 EET} {294361200 10800 1 EEST} {307584000 7200 0 EET} {325983600 10800 1 EEST} {339206400 7200 0 EET} {357519600 10800 1 EEST} {370742400 7200 0 EET} {396399600 10800 1 EEST} {402278400 7200 0 EET} {426812400 10800 1 EEST} {433814400 7200 0 EET} {452214000 10800 1 EEST} {465436800 7200 0 EET} {483750000 10800 1 EEST} {496972800 7200 0 EET} {515286000 10800 1 EEST} {528508800 7200 0 EET} {546822000 10800 1 EEST} {560044800 7200 0 EET} {578444400 10800 1 EEST} {591667200 7200 0 EET} {610412400 10800 1 EEST} {623203200 7200 0 EET} {641516400 10800 1 EEST} {654739200 7200 0 EET} {673052400 10800 1 EEST} {686275200 7200 0 EET} {704674800 10800 1 EEST} {717897600 7200 0 EET} {736210800 10800 1 EEST} {749433600 7200 0 EET} {767746800 10800 1 EEST} {780969600 7200 0 EET} {799020000 10800 1 EEST} {812322000 7200 0 EET} {830469600 10800 1 EEST} {843771600 7200 0 EET} {861919200 10800 1 EEST} {875221200 7200 0 EET} {893368800 10800 1 EEST} {906670800 7200 0 EET} {925423200 10800 1 EEST} {938725200 7200 0 EET} {956872800 10800 1 EEST} {970174800 7200 0 EET} {988322400 10800 1 EEST} {1001624400 7200 0 EET} {1019772000 10800 1 EEST} {1033074000 7200 0 EET} {1051221600 10800 1 EEST} {1064523600 7200 0 EET} {1083276000 10800 1 EEST} {1096578000 7200 0 EET} {1114725600 10800 1 EEST} {1128027600 7200 0 EET} {1146175200 10800 1 EEST} {1158872400 7200 0 EET} {1177624800 10800 1 EEST} {1189112400 7200 0 EET} {1209074400 10800 1 EEST} {1219957200 7200 0 EET} {1240524000 10800 1 EEST} {1250802000 7200 0 EET} {1272578400 10800 1 EEST} {1281474000 7200 0 EET} {1284069600 10800 1 EEST} {1285880400 7200 0 EET} {1400191200 10800 1 EEST} {1403816400 7200 0 EET} {1406844000 10800 1 EEST} {1411678800 7200 0 EET} } tcl8.6.5/library/tzdata/Africa/Nouakchott0000644000175000017500000000026712663660066017757 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Abidjan)]} { LoadTimeZoneFile Africa/Abidjan } set TZData(:Africa/Nouakchott) $TZData(:Africa/Abidjan) tcl8.6.5/library/tzdata/Africa/Dakar0000644000175000017500000000026212663660066016655 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Abidjan)]} { LoadTimeZoneFile Africa/Abidjan } set TZData(:Africa/Dakar) $TZData(:Africa/Abidjan) tcl8.6.5/library/tzdata/Africa/Bamako0000644000175000017500000000026312663660066017026 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Abidjan)]} { LoadTimeZoneFile Africa/Abidjan } set TZData(:Africa/Bamako) $TZData(:Africa/Abidjan) tcl8.6.5/library/tzdata/Africa/Djibouti0000644000175000017500000000026512663660066017407 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Nairobi)]} { LoadTimeZoneFile Africa/Nairobi } set TZData(:Africa/Djibouti) $TZData(:Africa/Nairobi) tcl8.6.5/library/tzdata/Africa/Accra0000644000175000017500000000261012663660066016643 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Accra) { {-9223372036854775808 -52 0 LMT} {-1640995148 0 0 GMT} {-1556841600 1200 1 GHST} {-1546388400 0 0 GMT} {-1525305600 1200 1 GHST} {-1514852400 0 0 GMT} {-1493769600 1200 1 GHST} {-1483316400 0 0 GMT} {-1462233600 1200 1 GHST} {-1451780400 0 0 GMT} {-1430611200 1200 1 GHST} {-1420158000 0 0 GMT} {-1399075200 1200 1 GHST} {-1388622000 0 0 GMT} {-1367539200 1200 1 GHST} {-1357086000 0 0 GMT} {-1336003200 1200 1 GHST} {-1325550000 0 0 GMT} {-1304380800 1200 1 GHST} {-1293927600 0 0 GMT} {-1272844800 1200 1 GHST} {-1262391600 0 0 GMT} {-1241308800 1200 1 GHST} {-1230855600 0 0 GMT} {-1209772800 1200 1 GHST} {-1199319600 0 0 GMT} {-1178150400 1200 1 GHST} {-1167697200 0 0 GMT} {-1146614400 1200 1 GHST} {-1136161200 0 0 GMT} {-1115078400 1200 1 GHST} {-1104625200 0 0 GMT} {-1083542400 1200 1 GHST} {-1073089200 0 0 GMT} {-1051920000 1200 1 GHST} {-1041466800 0 0 GMT} {-1020384000 1200 1 GHST} {-1009930800 0 0 GMT} {-988848000 1200 1 GHST} {-978394800 0 0 GMT} {-957312000 1200 1 GHST} {-946858800 0 0 GMT} {-925689600 1200 1 GHST} {-915236400 0 0 GMT} {-894153600 1200 1 GHST} {-883700400 0 0 GMT} {-862617600 1200 1 GHST} {-852164400 0 0 GMT} } tcl8.6.5/library/tzdata/Africa/Tripoli0000644000175000017500000000163012663660066017255 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Tripoli) { {-9223372036854775808 3164 0 LMT} {-1577926364 3600 0 CET} {-574902000 7200 1 CEST} {-512175600 7200 1 CEST} {-449888400 7200 1 CEST} {-347158800 7200 0 EET} {378684000 3600 0 CET} {386463600 7200 1 CEST} {402271200 3600 0 CET} {417999600 7200 1 CEST} {433807200 3600 0 CET} {449622000 7200 1 CEST} {465429600 3600 0 CET} {481590000 7200 1 CEST} {496965600 3600 0 CET} {512953200 7200 1 CEST} {528674400 3600 0 CET} {544230000 7200 1 CEST} {560037600 3600 0 CET} {575852400 7200 1 CEST} {591660000 3600 0 CET} {607388400 7200 1 CEST} {623196000 3600 0 CET} {641775600 7200 0 EET} {844034400 3600 0 CET} {860108400 7200 1 CEST} {875919600 7200 0 EET} {1352505600 3600 0 CET} {1364515200 7200 1 CEST} {1382662800 7200 0 EET} } tcl8.6.5/library/tzdata/Africa/Maputo0000644000175000017500000000021712661614720017072 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Maputo) { {-9223372036854775808 7820 0 LMT} {-2109291020 7200 0 CAT} } tcl8.6.5/library/tzdata/Africa/Mbabane0000644000175000017500000000030312663660066017154 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Johannesburg)]} { LoadTimeZoneFile Africa/Johannesburg } set TZData(:Africa/Mbabane) $TZData(:Africa/Johannesburg) tcl8.6.5/library/tzdata/Africa/Kinshasa0000644000175000017500000000025712663660066017400 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Lagos)]} { LoadTimeZoneFile Africa/Lagos } set TZData(:Africa/Kinshasa) $TZData(:Africa/Lagos) tcl8.6.5/library/tzdata/Africa/Windhoek0000644000175000017500000001422012661614720017374 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Windhoek) { {-9223372036854775808 4104 0 LMT} {-2458170504 5400 0 SWAT} {-2109288600 7200 0 SAST} {-860976000 10800 1 SAST} {-845254800 7200 0 SAST} {637970400 7200 0 CAT} {765324000 3600 0 WAT} {778640400 7200 1 WAST} {796780800 3600 0 WAT} {810090000 7200 1 WAST} {828835200 3600 0 WAT} {841539600 7200 1 WAST} {860284800 3600 0 WAT} {873594000 7200 1 WAST} {891734400 3600 0 WAT} {905043600 7200 1 WAST} {923184000 3600 0 WAT} {936493200 7200 1 WAST} {954633600 3600 0 WAT} {967942800 7200 1 WAST} {986083200 3600 0 WAT} {999392400 7200 1 WAST} {1018137600 3600 0 WAT} {1030842000 7200 1 WAST} {1049587200 3600 0 WAT} {1062896400 7200 1 WAST} {1081036800 3600 0 WAT} {1094346000 7200 1 WAST} {1112486400 3600 0 WAT} {1125795600 7200 1 WAST} {1143936000 3600 0 WAT} {1157245200 7200 1 WAST} {1175385600 3600 0 WAT} {1188694800 7200 1 WAST} {1207440000 3600 0 WAT} {1220749200 7200 1 WAST} {1238889600 3600 0 WAT} {1252198800 7200 1 WAST} {1270339200 3600 0 WAT} {1283648400 7200 1 WAST} {1301788800 3600 0 WAT} {1315098000 7200 1 WAST} {1333238400 3600 0 WAT} {1346547600 7200 1 WAST} {1365292800 3600 0 WAT} {1377997200 7200 1 WAST} {1396742400 3600 0 WAT} {1410051600 7200 1 WAST} {1428192000 3600 0 WAT} {1441501200 7200 1 WAST} {1459641600 3600 0 WAT} {1472950800 7200 1 WAST} {1491091200 3600 0 WAT} {1504400400 7200 1 WAST} {1522540800 3600 0 WAT} {1535850000 7200 1 WAST} {1554595200 3600 0 WAT} {1567299600 7200 1 WAST} {1586044800 3600 0 WAT} {1599354000 7200 1 WAST} {1617494400 3600 0 WAT} {1630803600 7200 1 WAST} {1648944000 3600 0 WAT} {1662253200 7200 1 WAST} {1680393600 3600 0 WAT} {1693702800 7200 1 WAST} {1712448000 3600 0 WAT} {1725152400 7200 1 WAST} {1743897600 3600 0 WAT} {1757206800 7200 1 WAST} {1775347200 3600 0 WAT} {1788656400 7200 1 WAST} {1806796800 3600 0 WAT} {1820106000 7200 1 WAST} {1838246400 3600 0 WAT} {1851555600 7200 1 WAST} {1869696000 3600 0 WAT} {1883005200 7200 1 WAST} {1901750400 3600 0 WAT} {1914454800 7200 1 WAST} {1933200000 3600 0 WAT} {1946509200 7200 1 WAST} {1964649600 3600 0 WAT} {1977958800 7200 1 WAST} {1996099200 3600 0 WAT} {2009408400 7200 1 WAST} {2027548800 3600 0 WAT} {2040858000 7200 1 WAST} {2058998400 3600 0 WAT} {2072307600 7200 1 WAST} {2091052800 3600 0 WAT} {2104362000 7200 1 WAST} {2122502400 3600 0 WAT} {2135811600 7200 1 WAST} {2153952000 3600 0 WAT} {2167261200 7200 1 WAST} {2185401600 3600 0 WAT} {2198710800 7200 1 WAST} {2216851200 3600 0 WAT} {2230160400 7200 1 WAST} {2248905600 3600 0 WAT} {2261610000 7200 1 WAST} {2280355200 3600 0 WAT} {2293664400 7200 1 WAST} {2311804800 3600 0 WAT} {2325114000 7200 1 WAST} {2343254400 3600 0 WAT} {2356563600 7200 1 WAST} {2374704000 3600 0 WAT} {2388013200 7200 1 WAST} {2406153600 3600 0 WAT} {2419462800 7200 1 WAST} {2438208000 3600 0 WAT} {2450912400 7200 1 WAST} {2469657600 3600 0 WAT} {2482966800 7200 1 WAST} {2501107200 3600 0 WAT} {2514416400 7200 1 WAST} {2532556800 3600 0 WAT} {2545866000 7200 1 WAST} {2564006400 3600 0 WAT} {2577315600 7200 1 WAST} {2596060800 3600 0 WAT} {2608765200 7200 1 WAST} {2627510400 3600 0 WAT} {2640819600 7200 1 WAST} {2658960000 3600 0 WAT} {2672269200 7200 1 WAST} {2690409600 3600 0 WAT} {2703718800 7200 1 WAST} {2721859200 3600 0 WAT} {2735168400 7200 1 WAST} {2753308800 3600 0 WAT} {2766618000 7200 1 WAST} {2785363200 3600 0 WAT} {2798067600 7200 1 WAST} {2816812800 3600 0 WAT} {2830122000 7200 1 WAST} {2848262400 3600 0 WAT} {2861571600 7200 1 WAST} {2879712000 3600 0 WAT} {2893021200 7200 1 WAST} {2911161600 3600 0 WAT} {2924470800 7200 1 WAST} {2942611200 3600 0 WAT} {2955920400 7200 1 WAST} {2974665600 3600 0 WAT} {2987974800 7200 1 WAST} {3006115200 3600 0 WAT} {3019424400 7200 1 WAST} {3037564800 3600 0 WAT} {3050874000 7200 1 WAST} {3069014400 3600 0 WAT} {3082323600 7200 1 WAST} {3100464000 3600 0 WAT} {3113773200 7200 1 WAST} {3132518400 3600 0 WAT} {3145222800 7200 1 WAST} {3163968000 3600 0 WAT} {3177277200 7200 1 WAST} {3195417600 3600 0 WAT} {3208726800 7200 1 WAST} {3226867200 3600 0 WAT} {3240176400 7200 1 WAST} {3258316800 3600 0 WAT} {3271626000 7200 1 WAST} {3289766400 3600 0 WAT} {3303075600 7200 1 WAST} {3321820800 3600 0 WAT} {3334525200 7200 1 WAST} {3353270400 3600 0 WAT} {3366579600 7200 1 WAST} {3384720000 3600 0 WAT} {3398029200 7200 1 WAST} {3416169600 3600 0 WAT} {3429478800 7200 1 WAST} {3447619200 3600 0 WAT} {3460928400 7200 1 WAST} {3479673600 3600 0 WAT} {3492378000 7200 1 WAST} {3511123200 3600 0 WAT} {3524432400 7200 1 WAST} {3542572800 3600 0 WAT} {3555882000 7200 1 WAST} {3574022400 3600 0 WAT} {3587331600 7200 1 WAST} {3605472000 3600 0 WAT} {3618781200 7200 1 WAST} {3636921600 3600 0 WAT} {3650230800 7200 1 WAST} {3668976000 3600 0 WAT} {3681680400 7200 1 WAST} {3700425600 3600 0 WAT} {3713734800 7200 1 WAST} {3731875200 3600 0 WAT} {3745184400 7200 1 WAST} {3763324800 3600 0 WAT} {3776634000 7200 1 WAST} {3794774400 3600 0 WAT} {3808083600 7200 1 WAST} {3826224000 3600 0 WAT} {3839533200 7200 1 WAST} {3858278400 3600 0 WAT} {3871587600 7200 1 WAST} {3889728000 3600 0 WAT} {3903037200 7200 1 WAST} {3921177600 3600 0 WAT} {3934486800 7200 1 WAST} {3952627200 3600 0 WAT} {3965936400 7200 1 WAST} {3984076800 3600 0 WAT} {3997386000 7200 1 WAST} {4016131200 3600 0 WAT} {4028835600 7200 1 WAST} {4047580800 3600 0 WAT} {4060890000 7200 1 WAST} {4079030400 3600 0 WAT} {4092339600 7200 1 WAST} } tcl8.6.5/library/tzdata/Africa/Bissau0000644000175000017500000000025112663660066017057 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Bissau) { {-9223372036854775808 -3740 0 LMT} {-1830380260 -3600 0 WAT} {157770000 0 0 GMT} } tcl8.6.5/library/tzdata/Africa/Ceuta0000644000175000017500000001612512661614720016673 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Africa/Ceuta) { {-9223372036854775808 -1276 0 LMT} {-2177451524 0 0 WET} {-1630112400 3600 1 WEST} {-1616810400 0 0 WET} {-1451692800 0 0 WET} {-1442451600 3600 1 WEST} {-1427677200 0 0 WET} {-1379293200 3600 1 WEST} {-1364778000 0 0 WET} {-1348448400 3600 1 WEST} {-1333328400 0 0 WET} {-1316394000 3600 1 WEST} {-1301274000 0 0 WET} {-1293840000 0 0 WET} {-81432000 3600 1 WEST} {-71110800 0 0 WET} {141264000 3600 1 WEST} {147222000 0 0 WET} {199756800 3600 1 WEST} {207702000 0 0 WET} {231292800 3600 1 WEST} {244249200 0 0 WET} {265507200 3600 1 WEST} {271033200 0 0 WET} {448243200 3600 0 CET} {504918000 3600 0 CET} {512528400 7200 1 CEST} {528253200 3600 0 CET} {543978000 7200 1 CEST} {559702800 3600 0 CET} {575427600 7200 1 CEST} {591152400 3600 0 CET} {606877200 7200 1 CEST} {622602000 3600 0 CET} {638326800 7200 1 CEST} {654656400 3600 0 CET} {670381200 7200 1 CEST} {686106000 3600 0 CET} {701830800 7200 1 CEST} {717555600 3600 0 CET} {733280400 7200 1 CEST} {749005200 3600 0 CET} {764730000 7200 1 CEST} {780454800 3600 0 CET} {796179600 7200 1 CEST} {811904400 3600 0 CET} {828234000 7200 1 CEST} {846378000 3600 0 CET} {859683600 7200 1 CEST} {877827600 3600 0 CET} {891133200 7200 1 CEST} {909277200 3600 0 CET} {922582800 7200 1 CEST} {941331600 3600 0 CET} {954032400 7200 1 CEST} {972781200 3600 0 CET} {985482000 7200 1 CEST} {1004230800 3600 0 CET} {1017536400 7200 1 CEST} {1035680400 3600 0 CET} {1048986000 7200 1 CEST} {1067130000 3600 0 CET} {1080435600 7200 1 CEST} {1099184400 3600 0 CET} {1111885200 7200 1 CEST} {1130634000 3600 0 CET} {1143334800 7200 1 CEST} {1162083600 3600 0 CET} {1174784400 7200 1 CEST} {1193533200 3600 0 CET} {1206838800 7200 1 CEST} {1224982800 3600 0 CET} {1238288400 7200 1 CEST} {1256432400 3600 0 CET} {1269738000 7200 1 CEST} {1288486800 3600 0 CET} {1301187600 7200 1 CEST} {1319936400 3600 0 CET} {1332637200 7200 1 CEST} {1351386000 3600 0 CET} {1364691600 7200 1 CEST} {1382835600 3600 0 CET} {1396141200 7200 1 CEST} {1414285200 3600 0 CET} {1427590800 7200 1 CEST} {1445734800 3600 0 CET} {1459040400 7200 1 CEST} {1477789200 3600 0 CET} {1490490000 7200 1 CEST} {1509238800 3600 0 CET} {1521939600 7200 1 CEST} {1540688400 3600 0 CET} {1553994000 7200 1 CEST} {1572138000 3600 0 CET} {1585443600 7200 1 CEST} {1603587600 3600 0 CET} {1616893200 7200 1 CEST} {1635642000 3600 0 CET} {1648342800 7200 1 CEST} {1667091600 3600 0 CET} {1679792400 7200 1 CEST} {1698541200 3600 0 CET} {1711846800 7200 1 CEST} {1729990800 3600 0 CET} {1743296400 7200 1 CEST} {1761440400 3600 0 CET} {1774746000 7200 1 CEST} {1792890000 3600 0 CET} {1806195600 7200 1 CEST} {1824944400 3600 0 CET} {1837645200 7200 1 CEST} {1856394000 3600 0 CET} {1869094800 7200 1 CEST} {1887843600 3600 0 CET} {1901149200 7200 1 CEST} {1919293200 3600 0 CET} {1932598800 7200 1 CEST} {1950742800 3600 0 CET} {1964048400 7200 1 CEST} {1982797200 3600 0 CET} {1995498000 7200 1 CEST} {2014246800 3600 0 CET} {2026947600 7200 1 CEST} {2045696400 3600 0 CET} {2058397200 7200 1 CEST} {2077146000 3600 0 CET} {2090451600 7200 1 CEST} {2108595600 3600 0 CET} {2121901200 7200 1 CEST} {2140045200 3600 0 CET} {2153350800 7200 1 CEST} {2172099600 3600 0 CET} {2184800400 7200 1 CEST} {2203549200 3600 0 CET} {2216250000 7200 1 CEST} {2234998800 3600 0 CET} {2248304400 7200 1 CEST} {2266448400 3600 0 CET} {2279754000 7200 1 CEST} {2297898000 3600 0 CET} {2311203600 7200 1 CEST} {2329347600 3600 0 CET} {2342653200 7200 1 CEST} {2361402000 3600 0 CET} {2374102800 7200 1 CEST} {2392851600 3600 0 CET} {2405552400 7200 1 CEST} {2424301200 3600 0 CET} {2437606800 7200 1 CEST} {2455750800 3600 0 CET} {2469056400 7200 1 CEST} {2487200400 3600 0 CET} {2500506000 7200 1 CEST} {2519254800 3600 0 CET} {2531955600 7200 1 CEST} {2550704400 3600 0 CET} {2563405200 7200 1 CEST} {2582154000 3600 0 CET} {2595459600 7200 1 CEST} {2613603600 3600 0 CET} {2626909200 7200 1 CEST} {2645053200 3600 0 CET} {2658358800 7200 1 CEST} {2676502800 3600 0 CET} {2689808400 7200 1 CEST} {2708557200 3600 0 CET} {2721258000 7200 1 CEST} {2740006800 3600 0 CET} {2752707600 7200 1 CEST} {2771456400 3600 0 CET} {2784762000 7200 1 CEST} {2802906000 3600 0 CET} {2816211600 7200 1 CEST} {2834355600 3600 0 CET} {2847661200 7200 1 CEST} {2866410000 3600 0 CET} {2879110800 7200 1 CEST} {2897859600 3600 0 CET} {2910560400 7200 1 CEST} {2929309200 3600 0 CET} {2942010000 7200 1 CEST} {2960758800 3600 0 CET} {2974064400 7200 1 CEST} {2992208400 3600 0 CET} {3005514000 7200 1 CEST} {3023658000 3600 0 CET} {3036963600 7200 1 CEST} {3055712400 3600 0 CET} {3068413200 7200 1 CEST} {3087162000 3600 0 CET} {3099862800 7200 1 CEST} {3118611600 3600 0 CET} {3131917200 7200 1 CEST} {3150061200 3600 0 CET} {3163366800 7200 1 CEST} {3181510800 3600 0 CET} {3194816400 7200 1 CEST} {3212960400 3600 0 CET} {3226266000 7200 1 CEST} {3245014800 3600 0 CET} {3257715600 7200 1 CEST} {3276464400 3600 0 CET} {3289165200 7200 1 CEST} {3307914000 3600 0 CET} {3321219600 7200 1 CEST} {3339363600 3600 0 CET} {3352669200 7200 1 CEST} {3370813200 3600 0 CET} {3384118800 7200 1 CEST} {3402867600 3600 0 CET} {3415568400 7200 1 CEST} {3434317200 3600 0 CET} {3447018000 7200 1 CEST} {3465766800 3600 0 CET} {3479072400 7200 1 CEST} {3497216400 3600 0 CET} {3510522000 7200 1 CEST} {3528666000 3600 0 CET} {3541971600 7200 1 CEST} {3560115600 3600 0 CET} {3573421200 7200 1 CEST} {3592170000 3600 0 CET} {3604870800 7200 1 CEST} {3623619600 3600 0 CET} {3636320400 7200 1 CEST} {3655069200 3600 0 CET} {3668374800 7200 1 CEST} {3686518800 3600 0 CET} {3699824400 7200 1 CEST} {3717968400 3600 0 CET} {3731274000 7200 1 CEST} {3750022800 3600 0 CET} {3762723600 7200 1 CEST} {3781472400 3600 0 CET} {3794173200 7200 1 CEST} {3812922000 3600 0 CET} {3825622800 7200 1 CEST} {3844371600 3600 0 CET} {3857677200 7200 1 CEST} {3875821200 3600 0 CET} {3889126800 7200 1 CEST} {3907270800 3600 0 CET} {3920576400 7200 1 CEST} {3939325200 3600 0 CET} {3952026000 7200 1 CEST} {3970774800 3600 0 CET} {3983475600 7200 1 CEST} {4002224400 3600 0 CET} {4015530000 7200 1 CEST} {4033674000 3600 0 CET} {4046979600 7200 1 CEST} {4065123600 3600 0 CET} {4078429200 7200 1 CEST} {4096573200 3600 0 CET} } tcl8.6.5/library/tzdata/Africa/Gaborone0000644000175000017500000000026212663660066017367 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Maputo)]} { LoadTimeZoneFile Africa/Maputo } set TZData(:Africa/Gaborone) $TZData(:Africa/Maputo) tcl8.6.5/library/tzdata/Africa/Sao_Tome0000644000175000017500000000026512663660066017344 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Abidjan)]} { LoadTimeZoneFile Africa/Abidjan } set TZData(:Africa/Sao_Tome) $TZData(:Africa/Abidjan) tcl8.6.5/library/tzdata/Africa/Bangui0000644000175000017500000000025512663660066017042 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Lagos)]} { LoadTimeZoneFile Africa/Lagos } set TZData(:Africa/Bangui) $TZData(:Africa/Lagos) tcl8.6.5/library/tzdata/Africa/Bujumbura0000644000175000017500000000026312663660066017570 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Maputo)]} { LoadTimeZoneFile Africa/Maputo } set TZData(:Africa/Bujumbura) $TZData(:Africa/Maputo) tcl8.6.5/library/tzdata/NZ0000644000175000017500000000025612661614722014774 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Auckland)]} { LoadTimeZoneFile Pacific/Auckland } set TZData(:NZ) $TZData(:Pacific/Auckland) tcl8.6.5/library/tzdata/EST0000644000175000017500000000015212661614721015072 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:EST) { {-9223372036854775808 -18000 0 EST} } tcl8.6.5/library/tzdata/Poland0000644000175000017500000000025112661614722015655 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Warsaw)]} { LoadTimeZoneFile Europe/Warsaw } set TZData(:Poland) $TZData(:Europe/Warsaw) tcl8.6.5/library/tzdata/W-SU0000644000175000017500000000024712661614722015200 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/Moscow)]} { LoadTimeZoneFile Europe/Moscow } set TZData(:W-SU) $TZData(:Europe/Moscow) tcl8.6.5/library/tzdata/Universal0000644000175000017500000000023212661614722016407 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Etc/UTC)]} { LoadTimeZoneFile Etc/UTC } set TZData(:Universal) $TZData(:Etc/UTC) tcl8.6.5/library/tzdata/Cuba0000644000175000017500000000025212661614722015313 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Havana)]} { LoadTimeZoneFile America/Havana } set TZData(:Cuba) $TZData(:America/Havana) tcl8.6.5/library/tzdata/PST8PDT0000644000175000017500000002004312661614722015547 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:PST8PDT) { {-9223372036854775808 -28800 0 PST} {-1633269600 -25200 1 PDT} {-1615129200 -28800 0 PST} {-1601820000 -25200 1 PDT} {-1583679600 -28800 0 PST} {-880207200 -25200 1 PWT} {-769395600 -25200 1 PPT} {-765385200 -28800 0 PST} {-84376800 -25200 1 PDT} {-68655600 -28800 0 PST} {-52927200 -25200 1 PDT} {-37206000 -28800 0 PST} {-21477600 -25200 1 PDT} {-5756400 -28800 0 PST} {9972000 -25200 1 PDT} {25693200 -28800 0 PST} {41421600 -25200 1 PDT} {57747600 -28800 0 PST} {73476000 -25200 1 PDT} {89197200 -28800 0 PST} {104925600 -25200 1 PDT} {120646800 -28800 0 PST} {126698400 -25200 1 PDT} {152096400 -28800 0 PST} {162381600 -25200 1 PDT} {183546000 -28800 0 PST} {199274400 -25200 1 PDT} {215600400 -28800 0 PST} {230724000 -25200 1 PDT} {247050000 -28800 0 PST} {262778400 -25200 1 PDT} {278499600 -28800 0 PST} {294228000 -25200 1 PDT} {309949200 -28800 0 PST} {325677600 -25200 1 PDT} {341398800 -28800 0 PST} {357127200 -25200 1 PDT} {372848400 -28800 0 PST} {388576800 -25200 1 PDT} {404902800 -28800 0 PST} {420026400 -25200 1 PDT} {436352400 -28800 0 PST} {452080800 -25200 1 PDT} {467802000 -28800 0 PST} {483530400 -25200 1 PDT} {499251600 -28800 0 PST} {514980000 -25200 1 PDT} {530701200 -28800 0 PST} {544615200 -25200 1 PDT} {562150800 -28800 0 PST} {576064800 -25200 1 PDT} {594205200 -28800 0 PST} {607514400 -25200 1 PDT} {625654800 -28800 0 PST} {638964000 -25200 1 PDT} {657104400 -28800 0 PST} {671018400 -25200 1 PDT} {688554000 -28800 0 PST} {702468000 -25200 1 PDT} {720003600 -28800 0 PST} {733917600 -25200 1 PDT} {752058000 -28800 0 PST} {765367200 -25200 1 PDT} {783507600 -28800 0 PST} {796816800 -25200 1 PDT} {814957200 -28800 0 PST} {828871200 -25200 1 PDT} {846406800 -28800 0 PST} {860320800 -25200 1 PDT} {877856400 -28800 0 PST} {891770400 -25200 1 PDT} {909306000 -28800 0 PST} {923220000 -25200 1 PDT} {941360400 -28800 0 PST} {954669600 -25200 1 PDT} {972810000 -28800 0 PST} {986119200 -25200 1 PDT} {1004259600 -28800 0 PST} {1018173600 -25200 1 PDT} {1035709200 -28800 0 PST} {1049623200 -25200 1 PDT} {1067158800 -28800 0 PST} {1081072800 -25200 1 PDT} {1099213200 -28800 0 PST} {1112522400 -25200 1 PDT} {1130662800 -28800 0 PST} {1143972000 -25200 1 PDT} {1162112400 -28800 0 PST} {1173607200 -25200 1 PDT} {1194166800 -28800 0 PST} {1205056800 -25200 1 PDT} {1225616400 -28800 0 PST} {1236506400 -25200 1 PDT} {1257066000 -28800 0 PST} {1268560800 -25200 1 PDT} {1289120400 -28800 0 PST} {1300010400 -25200 1 PDT} {1320570000 -28800 0 PST} {1331460000 -25200 1 PDT} {1352019600 -28800 0 PST} {1362909600 -25200 1 PDT} {1383469200 -28800 0 PST} {1394359200 -25200 1 PDT} {1414918800 -28800 0 PST} {1425808800 -25200 1 PDT} {1446368400 -28800 0 PST} {1457863200 -25200 1 PDT} {1478422800 -28800 0 PST} {1489312800 -25200 1 PDT} {1509872400 -28800 0 PST} {1520762400 -25200 1 PDT} {1541322000 -28800 0 PST} {1552212000 -25200 1 PDT} {1572771600 -28800 0 PST} {1583661600 -25200 1 PDT} {1604221200 -28800 0 PST} {1615716000 -25200 1 PDT} {1636275600 -28800 0 PST} {1647165600 -25200 1 PDT} {1667725200 -28800 0 PST} {1678615200 -25200 1 PDT} {1699174800 -28800 0 PST} {1710064800 -25200 1 PDT} {1730624400 -28800 0 PST} {1741514400 -25200 1 PDT} {1762074000 -28800 0 PST} {1772964000 -25200 1 PDT} {1793523600 -28800 0 PST} {1805018400 -25200 1 PDT} {1825578000 -28800 0 PST} {1836468000 -25200 1 PDT} {1857027600 -28800 0 PST} {1867917600 -25200 1 PDT} {1888477200 -28800 0 PST} {1899367200 -25200 1 PDT} {1919926800 -28800 0 PST} {1930816800 -25200 1 PDT} {1951376400 -28800 0 PST} {1962871200 -25200 1 PDT} {1983430800 -28800 0 PST} {1994320800 -25200 1 PDT} {2014880400 -28800 0 PST} {2025770400 -25200 1 PDT} {2046330000 -28800 0 PST} {2057220000 -25200 1 PDT} {2077779600 -28800 0 PST} {2088669600 -25200 1 PDT} {2109229200 -28800 0 PST} {2120119200 -25200 1 PDT} {2140678800 -28800 0 PST} {2152173600 -25200 1 PDT} {2172733200 -28800 0 PST} {2183623200 -25200 1 PDT} {2204182800 -28800 0 PST} {2215072800 -25200 1 PDT} {2235632400 -28800 0 PST} {2246522400 -25200 1 PDT} {2267082000 -28800 0 PST} {2277972000 -25200 1 PDT} {2298531600 -28800 0 PST} {2309421600 -25200 1 PDT} {2329981200 -28800 0 PST} {2341476000 -25200 1 PDT} {2362035600 -28800 0 PST} {2372925600 -25200 1 PDT} {2393485200 -28800 0 PST} {2404375200 -25200 1 PDT} {2424934800 -28800 0 PST} {2435824800 -25200 1 PDT} {2456384400 -28800 0 PST} {2467274400 -25200 1 PDT} {2487834000 -28800 0 PST} {2499328800 -25200 1 PDT} {2519888400 -28800 0 PST} {2530778400 -25200 1 PDT} {2551338000 -28800 0 PST} {2562228000 -25200 1 PDT} {2582787600 -28800 0 PST} {2593677600 -25200 1 PDT} {2614237200 -28800 0 PST} {2625127200 -25200 1 PDT} {2645686800 -28800 0 PST} {2656576800 -25200 1 PDT} {2677136400 -28800 0 PST} {2688631200 -25200 1 PDT} {2709190800 -28800 0 PST} {2720080800 -25200 1 PDT} {2740640400 -28800 0 PST} {2751530400 -25200 1 PDT} {2772090000 -28800 0 PST} {2782980000 -25200 1 PDT} {2803539600 -28800 0 PST} {2814429600 -25200 1 PDT} {2834989200 -28800 0 PST} {2846484000 -25200 1 PDT} {2867043600 -28800 0 PST} {2877933600 -25200 1 PDT} {2898493200 -28800 0 PST} {2909383200 -25200 1 PDT} {2929942800 -28800 0 PST} {2940832800 -25200 1 PDT} {2961392400 -28800 0 PST} {2972282400 -25200 1 PDT} {2992842000 -28800 0 PST} {3003732000 -25200 1 PDT} {3024291600 -28800 0 PST} {3035786400 -25200 1 PDT} {3056346000 -28800 0 PST} {3067236000 -25200 1 PDT} {3087795600 -28800 0 PST} {3098685600 -25200 1 PDT} {3119245200 -28800 0 PST} {3130135200 -25200 1 PDT} {3150694800 -28800 0 PST} {3161584800 -25200 1 PDT} {3182144400 -28800 0 PST} {3193034400 -25200 1 PDT} {3213594000 -28800 0 PST} {3225088800 -25200 1 PDT} {3245648400 -28800 0 PST} {3256538400 -25200 1 PDT} {3277098000 -28800 0 PST} {3287988000 -25200 1 PDT} {3308547600 -28800 0 PST} {3319437600 -25200 1 PDT} {3339997200 -28800 0 PST} {3350887200 -25200 1 PDT} {3371446800 -28800 0 PST} {3382941600 -25200 1 PDT} {3403501200 -28800 0 PST} {3414391200 -25200 1 PDT} {3434950800 -28800 0 PST} {3445840800 -25200 1 PDT} {3466400400 -28800 0 PST} {3477290400 -25200 1 PDT} {3497850000 -28800 0 PST} {3508740000 -25200 1 PDT} {3529299600 -28800 0 PST} {3540189600 -25200 1 PDT} {3560749200 -28800 0 PST} {3572244000 -25200 1 PDT} {3592803600 -28800 0 PST} {3603693600 -25200 1 PDT} {3624253200 -28800 0 PST} {3635143200 -25200 1 PDT} {3655702800 -28800 0 PST} {3666592800 -25200 1 PDT} {3687152400 -28800 0 PST} {3698042400 -25200 1 PDT} {3718602000 -28800 0 PST} {3730096800 -25200 1 PDT} {3750656400 -28800 0 PST} {3761546400 -25200 1 PDT} {3782106000 -28800 0 PST} {3792996000 -25200 1 PDT} {3813555600 -28800 0 PST} {3824445600 -25200 1 PDT} {3845005200 -28800 0 PST} {3855895200 -25200 1 PDT} {3876454800 -28800 0 PST} {3887344800 -25200 1 PDT} {3907904400 -28800 0 PST} {3919399200 -25200 1 PDT} {3939958800 -28800 0 PST} {3950848800 -25200 1 PDT} {3971408400 -28800 0 PST} {3982298400 -25200 1 PDT} {4002858000 -28800 0 PST} {4013748000 -25200 1 PDT} {4034307600 -28800 0 PST} {4045197600 -25200 1 PDT} {4065757200 -28800 0 PST} {4076647200 -25200 1 PDT} {4097206800 -28800 0 PST} } tcl8.6.5/library/tzdata/Indian/0000755000175000017500000000000012665173607015727 5ustar sergeisergeitcl8.6.5/library/tzdata/Indian/Christmas0000644000175000017500000000022412661614721017576 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Indian/Christmas) { {-9223372036854775808 25372 0 LMT} {-2364102172 25200 0 CXT} } tcl8.6.5/library/tzdata/Indian/Mahe0000644000175000017500000000021712661614721016515 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Indian/Mahe) { {-9223372036854775808 13308 0 LMT} {-2006653308 14400 0 SCT} } tcl8.6.5/library/tzdata/Indian/Reunion0000644000175000017500000000022212661614721017256 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Indian/Reunion) { {-9223372036854775808 13312 0 LMT} {-1848886912 14400 0 RET} } tcl8.6.5/library/tzdata/Indian/Mauritius0000644000175000017500000000041012663653132017621 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Indian/Mauritius) { {-9223372036854775808 13800 0 LMT} {-1988164200 14400 0 MUT} {403041600 18000 1 MUST} {417034800 14400 0 MUT} {1224972000 18000 1 MUST} {1238274000 14400 0 MUT} } tcl8.6.5/library/tzdata/Indian/Kerguelen0000644000175000017500000000021712661614721017564 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Indian/Kerguelen) { {-9223372036854775808 0 0 zzz} {-631152000 18000 0 TFT} } tcl8.6.5/library/tzdata/Indian/Chagos0000644000175000017500000000025512661614721017051 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Indian/Chagos) { {-9223372036854775808 17380 0 LMT} {-1988167780 18000 0 IOT} {820436400 21600 0 IOT} } tcl8.6.5/library/tzdata/Indian/Mayotte0000644000175000017500000000026412663660066017274 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Nairobi)]} { LoadTimeZoneFile Africa/Nairobi } set TZData(:Indian/Mayotte) $TZData(:Africa/Nairobi) tcl8.6.5/library/tzdata/Indian/Cocos0000644000175000017500000000022012661614721016703 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Indian/Cocos) { {-9223372036854775808 23260 0 LMT} {-2209012060 23400 0 CCT} } tcl8.6.5/library/tzdata/Indian/Comoro0000644000175000017500000000026312663660066017107 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Nairobi)]} { LoadTimeZoneFile Africa/Nairobi } set TZData(:Indian/Comoro) $TZData(:Africa/Nairobi) tcl8.6.5/library/tzdata/Indian/Antananarivo0000644000175000017500000000027112663660066020271 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Africa/Nairobi)]} { LoadTimeZoneFile Africa/Nairobi } set TZData(:Indian/Antananarivo) $TZData(:Africa/Nairobi) tcl8.6.5/library/tzdata/Indian/Maldives0000644000175000017500000000026012661614721017405 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:Indian/Maldives) { {-9223372036854775808 17640 0 LMT} {-2840158440 17640 0 MMT} {-315636840 18000 0 MVT} } tcl8.6.5/library/tzdata/PRC0000644000175000017500000000024612661614722015070 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Asia/Shanghai)]} { LoadTimeZoneFile Asia/Shanghai } set TZData(:PRC) $TZData(:Asia/Shanghai) tcl8.6.5/library/tzdata/EST5EDT0000644000175000017500000002004312661614721015515 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit set TZData(:EST5EDT) { {-9223372036854775808 -18000 0 EST} {-1633280400 -14400 1 EDT} {-1615140000 -18000 0 EST} {-1601830800 -14400 1 EDT} {-1583690400 -18000 0 EST} {-880218000 -14400 1 EWT} {-769395600 -14400 1 EPT} {-765396000 -18000 0 EST} {-84387600 -14400 1 EDT} {-68666400 -18000 0 EST} {-52938000 -14400 1 EDT} {-37216800 -18000 0 EST} {-21488400 -14400 1 EDT} {-5767200 -18000 0 EST} {9961200 -14400 1 EDT} {25682400 -18000 0 EST} {41410800 -14400 1 EDT} {57736800 -18000 0 EST} {73465200 -14400 1 EDT} {89186400 -18000 0 EST} {104914800 -14400 1 EDT} {120636000 -18000 0 EST} {126687600 -14400 1 EDT} {152085600 -18000 0 EST} {162370800 -14400 1 EDT} {183535200 -18000 0 EST} {199263600 -14400 1 EDT} {215589600 -18000 0 EST} {230713200 -14400 1 EDT} {247039200 -18000 0 EST} {262767600 -14400 1 EDT} {278488800 -18000 0 EST} {294217200 -14400 1 EDT} {309938400 -18000 0 EST} {325666800 -14400 1 EDT} {341388000 -18000 0 EST} {357116400 -14400 1 EDT} {372837600 -18000 0 EST} {388566000 -14400 1 EDT} {404892000 -18000 0 EST} {420015600 -14400 1 EDT} {436341600 -18000 0 EST} {452070000 -14400 1 EDT} {467791200 -18000 0 EST} {483519600 -14400 1 EDT} {499240800 -18000 0 EST} {514969200 -14400 1 EDT} {530690400 -18000 0 EST} {544604400 -14400 1 EDT} {562140000 -18000 0 EST} {576054000 -14400 1 EDT} {594194400 -18000 0 EST} {607503600 -14400 1 EDT} {625644000 -18000 0 EST} {638953200 -14400 1 EDT} {657093600 -18000 0 EST} {671007600 -14400 1 EDT} {688543200 -18000 0 EST} {702457200 -14400 1 EDT} {719992800 -18000 0 EST} {733906800 -14400 1 EDT} {752047200 -18000 0 EST} {765356400 -14400 1 EDT} {783496800 -18000 0 EST} {796806000 -14400 1 EDT} {814946400 -18000 0 EST} {828860400 -14400 1 EDT} {846396000 -18000 0 EST} {860310000 -14400 1 EDT} {877845600 -18000 0 EST} {891759600 -14400 1 EDT} {909295200 -18000 0 EST} {923209200 -14400 1 EDT} {941349600 -18000 0 EST} {954658800 -14400 1 EDT} {972799200 -18000 0 EST} {986108400 -14400 1 EDT} {1004248800 -18000 0 EST} {1018162800 -14400 1 EDT} {1035698400 -18000 0 EST} {1049612400 -14400 1 EDT} {1067148000 -18000 0 EST} {1081062000 -14400 1 EDT} {1099202400 -18000 0 EST} {1112511600 -14400 1 EDT} {1130652000 -18000 0 EST} {1143961200 -14400 1 EDT} {1162101600 -18000 0 EST} {1173596400 -14400 1 EDT} {1194156000 -18000 0 EST} {1205046000 -14400 1 EDT} {1225605600 -18000 0 EST} {1236495600 -14400 1 EDT} {1257055200 -18000 0 EST} {1268550000 -14400 1 EDT} {1289109600 -18000 0 EST} {1299999600 -14400 1 EDT} {1320559200 -18000 0 EST} {1331449200 -14400 1 EDT} {1352008800 -18000 0 EST} {1362898800 -14400 1 EDT} {1383458400 -18000 0 EST} {1394348400 -14400 1 EDT} {1414908000 -18000 0 EST} {1425798000 -14400 1 EDT} {1446357600 -18000 0 EST} {1457852400 -14400 1 EDT} {1478412000 -18000 0 EST} {1489302000 -14400 1 EDT} {1509861600 -18000 0 EST} {1520751600 -14400 1 EDT} {1541311200 -18000 0 EST} {1552201200 -14400 1 EDT} {1572760800 -18000 0 EST} {1583650800 -14400 1 EDT} {1604210400 -18000 0 EST} {1615705200 -14400 1 EDT} {1636264800 -18000 0 EST} {1647154800 -14400 1 EDT} {1667714400 -18000 0 EST} {1678604400 -14400 1 EDT} {1699164000 -18000 0 EST} {1710054000 -14400 1 EDT} {1730613600 -18000 0 EST} {1741503600 -14400 1 EDT} {1762063200 -18000 0 EST} {1772953200 -14400 1 EDT} {1793512800 -18000 0 EST} {1805007600 -14400 1 EDT} {1825567200 -18000 0 EST} {1836457200 -14400 1 EDT} {1857016800 -18000 0 EST} {1867906800 -14400 1 EDT} {1888466400 -18000 0 EST} {1899356400 -14400 1 EDT} {1919916000 -18000 0 EST} {1930806000 -14400 1 EDT} {1951365600 -18000 0 EST} {1962860400 -14400 1 EDT} {1983420000 -18000 0 EST} {1994310000 -14400 1 EDT} {2014869600 -18000 0 EST} {2025759600 -14400 1 EDT} {2046319200 -18000 0 EST} {2057209200 -14400 1 EDT} {2077768800 -18000 0 EST} {2088658800 -14400 1 EDT} {2109218400 -18000 0 EST} {2120108400 -14400 1 EDT} {2140668000 -18000 0 EST} {2152162800 -14400 1 EDT} {2172722400 -18000 0 EST} {2183612400 -14400 1 EDT} {2204172000 -18000 0 EST} {2215062000 -14400 1 EDT} {2235621600 -18000 0 EST} {2246511600 -14400 1 EDT} {2267071200 -18000 0 EST} {2277961200 -14400 1 EDT} {2298520800 -18000 0 EST} {2309410800 -14400 1 EDT} {2329970400 -18000 0 EST} {2341465200 -14400 1 EDT} {2362024800 -18000 0 EST} {2372914800 -14400 1 EDT} {2393474400 -18000 0 EST} {2404364400 -14400 1 EDT} {2424924000 -18000 0 EST} {2435814000 -14400 1 EDT} {2456373600 -18000 0 EST} {2467263600 -14400 1 EDT} {2487823200 -18000 0 EST} {2499318000 -14400 1 EDT} {2519877600 -18000 0 EST} {2530767600 -14400 1 EDT} {2551327200 -18000 0 EST} {2562217200 -14400 1 EDT} {2582776800 -18000 0 EST} {2593666800 -14400 1 EDT} {2614226400 -18000 0 EST} {2625116400 -14400 1 EDT} {2645676000 -18000 0 EST} {2656566000 -14400 1 EDT} {2677125600 -18000 0 EST} {2688620400 -14400 1 EDT} {2709180000 -18000 0 EST} {2720070000 -14400 1 EDT} {2740629600 -18000 0 EST} {2751519600 -14400 1 EDT} {2772079200 -18000 0 EST} {2782969200 -14400 1 EDT} {2803528800 -18000 0 EST} {2814418800 -14400 1 EDT} {2834978400 -18000 0 EST} {2846473200 -14400 1 EDT} {2867032800 -18000 0 EST} {2877922800 -14400 1 EDT} {2898482400 -18000 0 EST} {2909372400 -14400 1 EDT} {2929932000 -18000 0 EST} {2940822000 -14400 1 EDT} {2961381600 -18000 0 EST} {2972271600 -14400 1 EDT} {2992831200 -18000 0 EST} {3003721200 -14400 1 EDT} {3024280800 -18000 0 EST} {3035775600 -14400 1 EDT} {3056335200 -18000 0 EST} {3067225200 -14400 1 EDT} {3087784800 -18000 0 EST} {3098674800 -14400 1 EDT} {3119234400 -18000 0 EST} {3130124400 -14400 1 EDT} {3150684000 -18000 0 EST} {3161574000 -14400 1 EDT} {3182133600 -18000 0 EST} {3193023600 -14400 1 EDT} {3213583200 -18000 0 EST} {3225078000 -14400 1 EDT} {3245637600 -18000 0 EST} {3256527600 -14400 1 EDT} {3277087200 -18000 0 EST} {3287977200 -14400 1 EDT} {3308536800 -18000 0 EST} {3319426800 -14400 1 EDT} {3339986400 -18000 0 EST} {3350876400 -14400 1 EDT} {3371436000 -18000 0 EST} {3382930800 -14400 1 EDT} {3403490400 -18000 0 EST} {3414380400 -14400 1 EDT} {3434940000 -18000 0 EST} {3445830000 -14400 1 EDT} {3466389600 -18000 0 EST} {3477279600 -14400 1 EDT} {3497839200 -18000 0 EST} {3508729200 -14400 1 EDT} {3529288800 -18000 0 EST} {3540178800 -14400 1 EDT} {3560738400 -18000 0 EST} {3572233200 -14400 1 EDT} {3592792800 -18000 0 EST} {3603682800 -14400 1 EDT} {3624242400 -18000 0 EST} {3635132400 -14400 1 EDT} {3655692000 -18000 0 EST} {3666582000 -14400 1 EDT} {3687141600 -18000 0 EST} {3698031600 -14400 1 EDT} {3718591200 -18000 0 EST} {3730086000 -14400 1 EDT} {3750645600 -18000 0 EST} {3761535600 -14400 1 EDT} {3782095200 -18000 0 EST} {3792985200 -14400 1 EDT} {3813544800 -18000 0 EST} {3824434800 -14400 1 EDT} {3844994400 -18000 0 EST} {3855884400 -14400 1 EDT} {3876444000 -18000 0 EST} {3887334000 -14400 1 EDT} {3907893600 -18000 0 EST} {3919388400 -14400 1 EDT} {3939948000 -18000 0 EST} {3950838000 -14400 1 EDT} {3971397600 -18000 0 EST} {3982287600 -14400 1 EDT} {4002847200 -18000 0 EST} {4013737200 -14400 1 EDT} {4034296800 -18000 0 EST} {4045186800 -14400 1 EDT} {4065746400 -18000 0 EST} {4076636400 -14400 1 EDT} {4097196000 -18000 0 EST} } tcl8.6.5/library/tzdata/Navajo0000644000175000017500000000025412661614722015661 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Denver)]} { LoadTimeZoneFile America/Denver } set TZData(:Navajo) $TZData(:America/Denver) tcl8.6.5/library/tzdata/SystemV/0000755000175000017500000000000012665173607016137 5ustar sergeisergeitcl8.6.5/library/tzdata/SystemV/MST7MDT0000644000175000017500000000027011555560473017156 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Denver)]} { LoadTimeZoneFile America/Denver } set TZData(:SystemV/MST7MDT) $TZData(:America/Denver) tcl8.6.5/library/tzdata/SystemV/MST70000644000175000017500000000027011555560473016611 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Phoenix)]} { LoadTimeZoneFile America/Phoenix } set TZData(:SystemV/MST7) $TZData(:America/Phoenix) tcl8.6.5/library/tzdata/SystemV/AST4ADT0000644000175000017500000000027311555560473017126 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Halifax)]} { LoadTimeZoneFile America/Halifax } set TZData(:SystemV/AST4ADT) $TZData(:America/Halifax) tcl8.6.5/library/tzdata/SystemV/EST50000644000175000017500000000030711555560473016600 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Indianapolis)]} { LoadTimeZoneFile America/Indianapolis } set TZData(:SystemV/EST5) $TZData(:America/Indianapolis) tcl8.6.5/library/tzdata/SystemV/YST9YDT0000644000175000017500000000030111555560473017203 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Anchorage)]} { LoadTimeZoneFile America/Anchorage } set TZData(:SystemV/YST9YDT) $TZData(:America/Anchorage) tcl8.6.5/library/tzdata/SystemV/CST6CDT0000644000175000017500000000027311555560473017134 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Chicago)]} { LoadTimeZoneFile America/Chicago } set TZData(:SystemV/CST6CDT) $TZData(:America/Chicago) tcl8.6.5/library/tzdata/SystemV/HST100000644000175000017500000000027411555560473016662 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Honolulu)]} { LoadTimeZoneFile Pacific/Honolulu } set TZData(:SystemV/HST10) $TZData(:Pacific/Honolulu) tcl8.6.5/library/tzdata/SystemV/CST60000644000175000017500000000026511555560473016602 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Regina)]} { LoadTimeZoneFile America/Regina } set TZData(:SystemV/CST6) $TZData(:America/Regina) tcl8.6.5/library/tzdata/SystemV/PST80000644000175000017500000000027311555560473016620 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Pitcairn)]} { LoadTimeZoneFile Pacific/Pitcairn } set TZData(:SystemV/PST8) $TZData(:Pacific/Pitcairn) tcl8.6.5/library/tzdata/SystemV/YST90000644000175000017500000000027011555560473016627 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(Pacific/Gambier)]} { LoadTimeZoneFile Pacific/Gambier } set TZData(:SystemV/YST9) $TZData(:Pacific/Gambier) tcl8.6.5/library/tzdata/SystemV/PST8PDT0000644000175000017500000000030711555560473017166 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Los_Angeles)]} { LoadTimeZoneFile America/Los_Angeles } set TZData(:SystemV/PST8PDT) $TZData(:America/Los_Angeles) tcl8.6.5/library/tzdata/SystemV/EST5EDT0000644000175000017500000000027611555560473017142 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(America/New_York)]} { LoadTimeZoneFile America/New_York } set TZData(:SystemV/EST5EDT) $TZData(:America/New_York) tcl8.6.5/library/tzdata/SystemV/AST40000644000175000017500000000030411555560473016570 0ustar sergeisergei# created by ../tools/tclZIC.tcl - do not edit if {![info exists TZData(America/Puerto_Rico)]} { LoadTimeZoneFile America/Puerto_Rico } set TZData(:SystemV/AST4) $TZData(:America/Puerto_Rico) tcl8.6.5/library/tzdata/GB0000644000175000017500000000024512661614722014733 0ustar sergeisergei# created by tools/tclZIC.tcl - do not edit if {![info exists TZData(Europe/London)]} { LoadTimeZoneFile Europe/London } set TZData(:GB) $TZData(:Europe/London) tcl8.6.5/library/opt/0000755000175000017500000000000012665173607014040 5ustar sergeisergeitcl8.6.5/library/opt/optparse.tcl0000644000175000017500000007771612663660066016421 0ustar sergeisergei# optparse.tcl -- # # (private) Option parsing package # Primarily used internally by the safe:: code. # # WARNING: This code will go away in a future release # of Tcl. It is NOT supported and you should not rely # on it. If your code does rely on this package you # may directly incorporate this code into your application. package require Tcl 8.2 # When this version number changes, update the pkgIndex.tcl file # and the install directory in the Makefiles. package provide opt 0.4.6 namespace eval ::tcl { # Exported APIs namespace export OptKeyRegister OptKeyDelete OptKeyError OptKeyParse \ OptProc OptProcArgGiven OptParse \ Lempty Lget \ Lassign Lvarpop Lvarpop1 Lvarset Lvarincr \ SetMax SetMin ################# Example of use / 'user documentation' ################### proc OptCreateTestProc {} { # Defines ::tcl::OptParseTest as a test proc with parsed arguments # (can't be defined before the code below is loaded (before "OptProc")) # Every OptProc give usage information on "procname -help". # Try "tcl::OptParseTest -help" and "tcl::OptParseTest -a" and # then other arguments. # # example of 'valid' call: # ::tcl::OptParseTest save -4 -pr 23 -libsok SybTcl\ # -nostatics false ch1 OptProc OptParseTest { {subcommand -choice {save print} "sub command"} {arg1 3 "some number"} {-aflag} {-intflag 7} {-weirdflag "help string"} {-noStatics "Not ok to load static packages"} {-nestedloading1 true "OK to load into nested slaves"} {-nestedloading2 -boolean true "OK to load into nested slaves"} {-libsOK -choice {Tk SybTcl} "List of packages that can be loaded"} {-precision -int 12 "Number of digits of precision"} {-intval 7 "An integer"} {-scale -float 1.0 "Scale factor"} {-zoom 1.0 "Zoom factor"} {-arbitrary foobar "Arbitrary string"} {-random -string 12 "Random string"} {-listval -list {} "List value"} {-blahflag -blah abc "Funny type"} {arg2 -boolean "a boolean"} {arg3 -choice "ch1 ch2"} {?optarg? -list {} "optional argument"} } { foreach v [info locals] { puts stderr [format "%14s : %s" $v [set $v]] } } } ################### No User serviceable part below ! ############### # Array storing the parsed descriptions variable OptDesc array set OptDesc {} # Next potentially free key id (numeric) variable OptDescN 0 # Inside algorithm/mechanism description: # (not for the faint hearted ;-) # # The argument description is parsed into a "program tree" # It is called a "program" because it is the program used by # the state machine interpreter that use that program to # actually parse the arguments at run time. # # The general structure of a "program" is # notation (pseudo bnf like) # name :== definition defines "name" as being "definition" # { x y z } means list of x, y, and z # x* means x repeated 0 or more time # x+ means "x x*" # x? means optionally x # x | y means x or y # "cccc" means the literal string # # program :== { programCounter programStep* } # # programStep :== program | singleStep # # programCounter :== {"P" integer+ } # # singleStep :== { instruction parameters* } # # instruction :== single element list # # (the difference between singleStep and program is that \ # llength [lindex $program 0] >= 2 # while # llength [lindex $singleStep 0] == 1 # ) # # And for this application: # # singleStep :== { instruction varname {hasBeenSet currentValue} type # typeArgs help } # instruction :== "flags" | "value" # type :== knowType | anyword # knowType :== "string" | "int" | "boolean" | "boolflag" | "float" # | "choice" # # for type "choice" typeArgs is a list of possible choices, the first one # is the default value. for all other types the typeArgs is the default value # # a "boolflag" is the type for a flag whose presence or absence, without # additional arguments means respectively true or false (default flag type). # # programCounter is the index in the list of the currently processed # programStep (thus starting at 1 (0 is {"P" prgCounterValue}). # If it is a list it points toward each currently selected programStep. # (like for "flags", as they are optional, form a set and programStep). # Performance/Implementation issues # --------------------------------- # We use tcl lists instead of arrays because with tcl8.0 # they should start to be much faster. # But this code use a lot of helper procs (like Lvarset) # which are quite slow and would be helpfully optimized # for instance by being written in C. Also our struture # is complex and there is maybe some places where the # string rep might be calculated at great exense. to be checked. # # Parse a given description and saves it here under the given key # generate a unused keyid if not given # proc ::tcl::OptKeyRegister {desc {key ""}} { variable OptDesc variable OptDescN if {[string equal $key ""]} { # in case a key given to us as a parameter was a number while {[info exists OptDesc($OptDescN)]} {incr OptDescN} set key $OptDescN incr OptDescN } # program counter set program [list [list "P" 1]] # are we processing flags (which makes a single program step) set inflags 0 set state {} # flag used to detect that we just have a single (flags set) subprogram. set empty 1 foreach item $desc { if {$state == "args"} { # more items after 'args'... return -code error "'args' special argument must be the last one" } set res [OptNormalizeOne $item] set state [lindex $res 0] if {$inflags} { if {$state == "flags"} { # add to 'subprogram' lappend flagsprg $res } else { # put in the flags # structure for flag programs items is a list of # {subprgcounter {prg flag 1} {prg flag 2} {...}} lappend program $flagsprg # put the other regular stuff lappend program $res set inflags 0 set empty 0 } } else { if {$state == "flags"} { set inflags 1 # sub program counter + first sub program set flagsprg [list [list "P" 1] $res] } else { lappend program $res set empty 0 } } } if {$inflags} { if {$empty} { # We just have the subprogram, optimize and remove # unneeded level: set program $flagsprg } else { lappend program $flagsprg } } set OptDesc($key) $program return $key } # # Free the storage for that given key # proc ::tcl::OptKeyDelete {key} { variable OptDesc unset OptDesc($key) } # Get the parsed description stored under the given key. proc OptKeyGetDesc {descKey} { variable OptDesc if {![info exists OptDesc($descKey)]} { return -code error "Unknown option description key \"$descKey\"" } set OptDesc($descKey) } # Parse entry point for ppl who don't want to register with a key, # for instance because the description changes dynamically. # (otherwise one should really use OptKeyRegister once + OptKeyParse # as it is way faster or simply OptProc which does it all) # Assign a temporary key, call OptKeyParse and then free the storage proc ::tcl::OptParse {desc arglist} { set tempkey [OptKeyRegister $desc] set ret [catch {uplevel 1 [list ::tcl::OptKeyParse $tempkey $arglist]} res] OptKeyDelete $tempkey return -code $ret $res } # Helper function, replacement for proc that both # register the description under a key which is the name of the proc # (and thus unique to that code) # and add a first line to the code to call the OptKeyParse proc # Stores the list of variables that have been actually given by the user # (the other will be sets to their default value) # into local variable named "Args". proc ::tcl::OptProc {name desc body} { set namespace [uplevel 1 [list ::namespace current]] if {[string match "::*" $name] || [string equal $namespace "::"]} { # absolute name or global namespace, name is the key set key $name } else { # we are relative to some non top level namespace: set key "${namespace}::${name}" } OptKeyRegister $desc $key uplevel 1 [list ::proc $name args "set Args \[::tcl::OptKeyParse $key \$args\]\n$body"] return $key } # Check that a argument has been given # assumes that "OptProc" has been used as it will check in "Args" list proc ::tcl::OptProcArgGiven {argname} { upvar Args alist expr {[lsearch $alist $argname] >=0} } ####### # Programs/Descriptions manipulation # Return the instruction word/list of a given step/(sub)program proc OptInstr {lst} { lindex $lst 0 } # Is a (sub) program or a plain instruction ? proc OptIsPrg {lst} { expr {[llength [OptInstr $lst]]>=2} } # Is this instruction a program counter or a real instr proc OptIsCounter {item} { expr {[lindex $item 0]=="P"} } # Current program counter (2nd word of first word) proc OptGetPrgCounter {lst} { Lget $lst {0 1} } # Current program counter (2nd word of first word) proc OptSetPrgCounter {lstName newValue} { upvar $lstName lst set lst [lreplace $lst 0 0 [concat "P" $newValue]] } # returns a list of currently selected items. proc OptSelection {lst} { set res {} foreach idx [lrange [lindex $lst 0] 1 end] { lappend res [Lget $lst $idx] } return $res } # Advance to next description proc OptNextDesc {descName} { uplevel 1 [list Lvarincr $descName {0 1}] } # Get the current description, eventually descend proc OptCurDesc {descriptions} { lindex $descriptions [OptGetPrgCounter $descriptions] } # get the current description, eventually descend # through sub programs as needed. proc OptCurDescFinal {descriptions} { set item [OptCurDesc $descriptions] # Descend untill we get the actual item and not a sub program while {[OptIsPrg $item]} { set item [OptCurDesc $item] } return $item } # Current final instruction adress proc OptCurAddr {descriptions {start {}}} { set adress [OptGetPrgCounter $descriptions] lappend start $adress set item [lindex $descriptions $adress] if {[OptIsPrg $item]} { return [OptCurAddr $item $start] } else { return $start } } # Set the value field of the current instruction proc OptCurSetValue {descriptionsName value} { upvar $descriptionsName descriptions # get the current item full adress set adress [OptCurAddr $descriptions] # use the 3th field of the item (see OptValue / OptNewInst) lappend adress 2 Lvarset descriptions $adress [list 1 $value] # ^hasBeenSet flag } # empty state means done/paste the end of the program proc OptState {item} { lindex $item 0 } # current state proc OptCurState {descriptions} { OptState [OptCurDesc $descriptions] } ####### # Arguments manipulation # Returns the argument that has to be processed now proc OptCurrentArg {lst} { lindex $lst 0 } # Advance to next argument proc OptNextArg {argsName} { uplevel 1 [list Lvarpop1 $argsName] } ####### # Loop over all descriptions, calling OptDoOne which will # eventually eat all the arguments. proc OptDoAll {descriptionsName argumentsName} { upvar $descriptionsName descriptions upvar $argumentsName arguments # puts "entered DoAll" # Nb: the places where "state" can be set are tricky to figure # because DoOne sets the state to flagsValue and return -continue # when needed... set state [OptCurState $descriptions] # We'll exit the loop in "OptDoOne" or when state is empty. while 1 { set curitem [OptCurDesc $descriptions] # Do subprograms if needed, call ourselves on the sub branch while {[OptIsPrg $curitem]} { OptDoAll curitem arguments # puts "done DoAll sub" # Insert back the results in current tree Lvarset1nc descriptions [OptGetPrgCounter $descriptions]\ $curitem OptNextDesc descriptions set curitem [OptCurDesc $descriptions] set state [OptCurState $descriptions] } # puts "state = \"$state\" - arguments=($arguments)" if {[Lempty $state]} { # Nothing left to do, we are done in this branch: break } # The following statement can make us terminate/continue # as it use return -code {break, continue, return and error} # codes OptDoOne descriptions state arguments # If we are here, no special return code where issued, # we'll step to next instruction : # puts "new state = \"$state\"" OptNextDesc descriptions set state [OptCurState $descriptions] } } # Process one step for the state machine, # eventually consuming the current argument. proc OptDoOne {descriptionsName stateName argumentsName} { upvar $argumentsName arguments upvar $descriptionsName descriptions upvar $stateName state # the special state/instruction "args" eats all # the remaining args (if any) if {($state == "args")} { if {![Lempty $arguments]} { # If there is no additional arguments, leave the default value # in. OptCurSetValue descriptions $arguments set arguments {} } # puts "breaking out ('args' state: consuming every reminding args)" return -code break } if {[Lempty $arguments]} { if {$state == "flags"} { # no argument and no flags : we're done # puts "returning to previous (sub)prg (no more args)" return -code return } elseif {$state == "optValue"} { set state next; # not used, for debug only # go to next state return } else { return -code error [OptMissingValue $descriptions] } } else { set arg [OptCurrentArg $arguments] } switch $state { flags { # A non-dash argument terminates the options, as does -- # Still a flag ? if {![OptIsFlag $arg]} { # don't consume the argument, return to previous prg return -code return } # consume the flag OptNextArg arguments if {[string equal "--" $arg]} { # return from 'flags' state return -code return } set hits [OptHits descriptions $arg] if {$hits > 1} { return -code error [OptAmbigous $descriptions $arg] } elseif {$hits == 0} { return -code error [OptFlagUsage $descriptions $arg] } set item [OptCurDesc $descriptions] if {[OptNeedValue $item]} { # we need a value, next state is set state flagValue } else { OptCurSetValue descriptions 1 } # continue return -code continue } flagValue - value { set item [OptCurDesc $descriptions] # Test the values against their required type if {[catch {OptCheckType $arg\ [OptType $item] [OptTypeArgs $item]} val]} { return -code error [OptBadValue $item $arg $val] } # consume the value OptNextArg arguments # set the value OptCurSetValue descriptions $val # go to next state if {$state == "flagValue"} { set state flags return -code continue } else { set state next; # not used, for debug only return ; # will go on next step } } optValue { set item [OptCurDesc $descriptions] # Test the values against their required type if {![catch {OptCheckType $arg\ [OptType $item] [OptTypeArgs $item]} val]} { # right type, so : # consume the value OptNextArg arguments # set the value OptCurSetValue descriptions $val } # go to next state set state next; # not used, for debug only return ; # will go on next step } } # If we reach this point: an unknown # state as been entered ! return -code error "Bug! unknown state in DoOne \"$state\"\ (prg counter [OptGetPrgCounter $descriptions]:\ [OptCurDesc $descriptions])" } # Parse the options given the key to previously registered description # and arguments list proc ::tcl::OptKeyParse {descKey arglist} { set desc [OptKeyGetDesc $descKey] # make sure -help always give usage if {[string equal -nocase "-help" $arglist]} { return -code error [OptError "Usage information:" $desc 1] } OptDoAll desc arglist if {![Lempty $arglist]} { return -code error [OptTooManyArgs $desc $arglist] } # Analyse the result # Walk through the tree: OptTreeVars $desc "#[expr {[info level]-1}]" } # determine string length for nice tabulated output proc OptTreeVars {desc level {vnamesLst {}}} { foreach item $desc { if {[OptIsCounter $item]} continue if {[OptIsPrg $item]} { set vnamesLst [OptTreeVars $item $level $vnamesLst] } else { set vname [OptVarName $item] upvar $level $vname var if {[OptHasBeenSet $item]} { # puts "adding $vname" # lets use the input name for the returned list # it is more usefull, for instance you can check that # no flags at all was given with expr # {![string match "*-*" $Args]} lappend vnamesLst [OptName $item] set var [OptValue $item] } else { set var [OptDefaultValue $item] } } } return $vnamesLst } # Check the type of a value # and emit an error if arg is not of the correct type # otherwise returns the canonical value of that arg (ie 0/1 for booleans) proc ::tcl::OptCheckType {arg type {typeArgs ""}} { # puts "checking '$arg' against '$type' ($typeArgs)" # only types "any", "choice", and numbers can have leading "-" switch -exact -- $type { int { if {![string is integer -strict $arg]} { error "not an integer" } return $arg } float { return [expr {double($arg)}] } script - list { # if llength fail : malformed list if {[llength $arg]==0 && [OptIsFlag $arg]} { error "no values with leading -" } return $arg } boolean { if {![string is boolean -strict $arg]} { error "non canonic boolean" } # convert true/false because expr/if is broken with "!,... return [expr {$arg ? 1 : 0}] } choice { if {[lsearch -exact $typeArgs $arg] < 0} { error "invalid choice" } return $arg } any { return $arg } string - default { if {[OptIsFlag $arg]} { error "no values with leading -" } return $arg } } return neverReached } # internal utilities # returns the number of flags matching the given arg # sets the (local) prg counter to the list of matches proc OptHits {descName arg} { upvar $descName desc set hits 0 set hitems {} set i 1 set larg [string tolower $arg] set len [string length $larg] set last [expr {$len-1}] foreach item [lrange $desc 1 end] { set flag [OptName $item] # lets try to match case insensitively # (string length ought to be cheap) set lflag [string tolower $flag] if {$len == [string length $lflag]} { if {[string equal $larg $lflag]} { # Exact match case OptSetPrgCounter desc $i return 1 } } elseif {[string equal $larg [string range $lflag 0 $last]]} { lappend hitems $i incr hits } incr i } if {$hits} { OptSetPrgCounter desc $hitems } return $hits } # Extract fields from the list structure: proc OptName {item} { lindex $item 1 } proc OptHasBeenSet {item} { Lget $item {2 0} } proc OptValue {item} { Lget $item {2 1} } proc OptIsFlag {name} { string match "-*" $name } proc OptIsOpt {name} { string match {\?*} $name } proc OptVarName {item} { set name [OptName $item] if {[OptIsFlag $name]} { return [string range $name 1 end] } elseif {[OptIsOpt $name]} { return [string trim $name "?"] } else { return $name } } proc OptType {item} { lindex $item 3 } proc OptTypeArgs {item} { lindex $item 4 } proc OptHelp {item} { lindex $item 5 } proc OptNeedValue {item} { expr {![string equal [OptType $item] boolflag]} } proc OptDefaultValue {item} { set val [OptTypeArgs $item] switch -exact -- [OptType $item] { choice {return [lindex $val 0]} boolean - boolflag { # convert back false/true to 0/1 because expr !$bool # is broken.. if {$val} { return 1 } else { return 0 } } } return $val } # Description format error helper proc OptOptUsage {item {what ""}} { return -code error "invalid description format$what: $item\n\ should be a list of {varname|-flagname ?-type? ?defaultvalue?\ ?helpstring?}" } # Generate a canonical form single instruction proc OptNewInst {state varname type typeArgs help} { list $state $varname [list 0 {}] $type $typeArgs $help # ^ ^ # | | # hasBeenSet=+ +=currentValue } # Translate one item to canonical form proc OptNormalizeOne {item} { set lg [Lassign $item varname arg1 arg2 arg3] # puts "called optnormalizeone '$item' v=($varname), lg=$lg" set isflag [OptIsFlag $varname] set isopt [OptIsOpt $varname] if {$isflag} { set state "flags" } elseif {$isopt} { set state "optValue" } elseif {![string equal $varname "args"]} { set state "value" } else { set state "args" } # apply 'smart' 'fuzzy' logic to try to make # description writer's life easy, and our's difficult : # let's guess the missing arguments :-) switch $lg { 1 { if {$isflag} { return [OptNewInst $state $varname boolflag false ""] } else { return [OptNewInst $state $varname any "" ""] } } 2 { # varname default # varname help set type [OptGuessType $arg1] if {[string equal $type "string"]} { if {$isflag} { set type boolflag set def false } else { set type any set def "" } set help $arg1 } else { set help "" set def $arg1 } return [OptNewInst $state $varname $type $def $help] } 3 { # varname type value # varname value comment if {[regexp {^-(.+)$} $arg1 x type]} { # flags/optValue as they are optional, need a "value", # on the contrary, for a variable (non optional), # default value is pointless, 'cept for choices : if {$isflag || $isopt || ($type == "choice")} { return [OptNewInst $state $varname $type $arg2 ""] } else { return [OptNewInst $state $varname $type "" $arg2] } } else { return [OptNewInst $state $varname\ [OptGuessType $arg1] $arg1 $arg2] } } 4 { if {[regexp {^-(.+)$} $arg1 x type]} { return [OptNewInst $state $varname $type $arg2 $arg3] } else { return -code error [OptOptUsage $item] } } default { return -code error [OptOptUsage $item] } } } # Auto magic lazy type determination proc OptGuessType {arg} { if { $arg == "true" || $arg == "false" } { return boolean } if {[string is integer -strict $arg]} { return int } if {[string is double -strict $arg]} { return float } return string } # Error messages front ends proc OptAmbigous {desc arg} { OptError "ambigous option \"$arg\", choose from:" [OptSelection $desc] } proc OptFlagUsage {desc arg} { OptError "bad flag \"$arg\", must be one of" $desc } proc OptTooManyArgs {desc arguments} { OptError "too many arguments (unexpected argument(s): $arguments),\ usage:"\ $desc 1 } proc OptParamType {item} { if {[OptIsFlag $item]} { return "flag" } else { return "parameter" } } proc OptBadValue {item arg {err {}}} { # puts "bad val err = \"$err\"" OptError "bad value \"$arg\" for [OptParamType $item]"\ [list $item] } proc OptMissingValue {descriptions} { # set item [OptCurDescFinal $descriptions] set item [OptCurDesc $descriptions] OptError "no value given for [OptParamType $item] \"[OptName $item]\"\ (use -help for full usage) :"\ [list $item] } proc ::tcl::OptKeyError {prefix descKey {header 0}} { OptError $prefix [OptKeyGetDesc $descKey] $header } # determine string length for nice tabulated output proc OptLengths {desc nlName tlName dlName} { upvar $nlName nl upvar $tlName tl upvar $dlName dl foreach item $desc { if {[OptIsCounter $item]} continue if {[OptIsPrg $item]} { OptLengths $item nl tl dl } else { SetMax nl [string length [OptName $item]] SetMax tl [string length [OptType $item]] set dv [OptTypeArgs $item] if {[OptState $item] != "header"} { set dv "($dv)" } set l [string length $dv] # limit the space allocated to potentially big "choices" if {([OptType $item] != "choice") || ($l<=12)} { SetMax dl $l } else { if {![info exists dl]} { set dl 0 } } } } } # output the tree proc OptTree {desc nl tl dl} { set res "" foreach item $desc { if {[OptIsCounter $item]} continue if {[OptIsPrg $item]} { append res [OptTree $item $nl $tl $dl] } else { set dv [OptTypeArgs $item] if {[OptState $item] != "header"} { set dv "($dv)" } append res [string trimright [format "\n %-*s %-*s %-*s %s" \ $nl [OptName $item] $tl [OptType $item] \ $dl $dv [OptHelp $item]]] } } return $res } # Give nice usage string proc ::tcl::OptError {prefix desc {header 0}} { # determine length if {$header} { # add faked instruction set h [list [OptNewInst header Var/FlagName Type Value Help]] lappend h [OptNewInst header ------------ ---- ----- ----] lappend h [OptNewInst header {(-help} "" "" {gives this help)}] set desc [concat $h $desc] } OptLengths $desc nl tl dl # actually output return "$prefix[OptTree $desc $nl $tl $dl]" } ################ General Utility functions ####################### # # List utility functions # Naming convention: # "Lvarxxx" take the list VARiable name as argument # "Lxxxx" take the list value as argument # (which is not costly with Tcl8 objects system # as it's still a reference and not a copy of the values) # # Is that list empty ? proc ::tcl::Lempty {list} { expr {[llength $list]==0} } # Gets the value of one leaf of a lists tree proc ::tcl::Lget {list indexLst} { if {[llength $indexLst] <= 1} { return [lindex $list $indexLst] } Lget [lindex $list [lindex $indexLst 0]] [lrange $indexLst 1 end] } # Sets the value of one leaf of a lists tree # (we use the version that does not create the elements because # it would be even slower... needs to be written in C !) # (nb: there is a non trivial recursive problem with indexes 0, # which appear because there is no difference between a list # of 1 element and 1 element alone : [list "a"] == "a" while # it should be {a} and [listp a] should be 0 while [listp {a b}] would be 1 # and [listp "a b"] maybe 0. listp does not exist either...) proc ::tcl::Lvarset {listName indexLst newValue} { upvar $listName list if {[llength $indexLst] <= 1} { Lvarset1nc list $indexLst $newValue } else { set idx [lindex $indexLst 0] set targetList [lindex $list $idx] # reduce refcount on targetList (not really usefull now, # could be with optimizing compiler) # Lvarset1 list $idx {} # recursively replace in targetList Lvarset targetList [lrange $indexLst 1 end] $newValue # put updated sub list back in the tree Lvarset1nc list $idx $targetList } } # Set one cell to a value, eventually create all the needed elements # (on level-1 of lists) variable emptyList {} proc ::tcl::Lvarset1 {listName index newValue} { upvar $listName list if {$index < 0} {return -code error "invalid negative index"} set lg [llength $list] if {$index >= $lg} { variable emptyList for {set i $lg} {$i<$index} {incr i} { lappend list $emptyList } lappend list $newValue } else { set list [lreplace $list $index $index $newValue] } } # same as Lvarset1 but no bound checking / creation proc ::tcl::Lvarset1nc {listName index newValue} { upvar $listName list set list [lreplace $list $index $index $newValue] } # Increments the value of one leaf of a lists tree # (which must exists) proc ::tcl::Lvarincr {listName indexLst {howMuch 1}} { upvar $listName list if {[llength $indexLst] <= 1} { Lvarincr1 list $indexLst $howMuch } else { set idx [lindex $indexLst 0] set targetList [lindex $list $idx] # reduce refcount on targetList Lvarset1nc list $idx {} # recursively replace in targetList Lvarincr targetList [lrange $indexLst 1 end] $howMuch # put updated sub list back in the tree Lvarset1nc list $idx $targetList } } # Increments the value of one cell of a list proc ::tcl::Lvarincr1 {listName index {howMuch 1}} { upvar $listName list set newValue [expr {[lindex $list $index]+$howMuch}] set list [lreplace $list $index $index $newValue] return $newValue } # Removes the first element of a list # and returns the new list value proc ::tcl::Lvarpop1 {listName} { upvar $listName list set list [lrange $list 1 end] } # Same but returns the removed element # (Like the tclX version) proc ::tcl::Lvarpop {listName} { upvar $listName list set el [lindex $list 0] set list [lrange $list 1 end] return $el } # Assign list elements to variables and return the length of the list proc ::tcl::Lassign {list args} { # faster than direct blown foreach (which does not byte compile) set i 0 set lg [llength $list] foreach vname $args { if {$i>=$lg} break uplevel 1 [list ::set $vname [lindex $list $i]] incr i } return $lg } # Misc utilities # Set the varname to value if value is greater than varname's current value # or if varname is undefined proc ::tcl::SetMax {varname value} { upvar 1 $varname var if {![info exists var] || $value > $var} { set var $value } } # Set the varname to value if value is smaller than varname's current value # or if varname is undefined proc ::tcl::SetMin {varname value} { upvar 1 $varname var if {![info exists var] || $value < $var} { set var $value } } # everything loaded fine, lets create the test proc: # OptCreateTestProc # Don't need the create temp proc anymore: # rename OptCreateTestProc {} } tcl8.6.5/library/opt/pkgIndex.tcl0000644000175000017500000000113712663653207016314 0ustar sergeisergei# Tcl package index file, version 1.1 # This file is generated by the "pkg_mkIndex -direct" command # and sourced either when an application starts up or # by a "package unknown" script. It invokes the # "package ifneeded" command to set up package-related # information so that packages will be loaded automatically # in response to "package require" commands. When this # script is sourced, the variable $dir must contain the # full path name of this file's directory. if {![package vsatisfies [package provide Tcl] 8.2]} {return} package ifneeded opt 0.4.6 [list source [file join $dir optparse.tcl]] tcl8.6.5/library/history.tcl0000644000175000017500000001624012663660066015444 0ustar sergeisergei# history.tcl -- # # Implementation of the history command. # # Copyright (c) 1997 Sun Microsystems, Inc. # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. # # The tcl::history array holds the history list and some additional # bookkeeping variables. # # nextid the index used for the next history list item. # keep the max size of the history list # oldest the index of the oldest item in the history. namespace eval ::tcl { variable history if {![info exists history]} { array set history { nextid 0 keep 20 oldest -20 } } namespace ensemble create -command ::tcl::history -map { add ::tcl::HistAdd change ::tcl::HistChange clear ::tcl::HistClear event ::tcl::HistEvent info ::tcl::HistInfo keep ::tcl::HistKeep nextid ::tcl::HistNextID redo ::tcl::HistRedo } } # history -- # # This is the main history command. See the man page for its interface. # This does some argument checking and calls the helper ensemble in the # tcl namespace. proc ::history {args} { # If no command given, we're doing 'history info'. Can't be done with an # ensemble unknown handler, as those don't fire when no subcommand is # given at all. if {![llength $args]} { set args info } # Tricky stuff needed to make stack and errors come out right! tailcall apply {arglist {tailcall history {*}$arglist} ::tcl} $args } # tcl::HistAdd -- # # Add an item to the history, and optionally eval it at the global scope # # Parameters: # event the command to add # exec (optional) a substring of "exec" causes the command to # be evaled. # Results: # If executing, then the results of the command are returned # # Side Effects: # Adds to the history list proc ::tcl::HistAdd {event {exec {}}} { variable history if { [prefix longest {exec {}} $exec] eq "" && [llength [info level 0]] == 3 } then { return -code error "bad argument \"$exec\": should be \"exec\"" } # Do not add empty commands to the history if {[string trim $event] eq ""} { return "" } # Maintain the history set history([incr history(nextid)]) $event unset -nocomplain history([incr history(oldest)]) # Only execute if 'exec' (or non-empty prefix of it) given if {$exec eq ""} { return "" } tailcall eval $event } # tcl::HistKeep -- # # Set or query the limit on the length of the history list # # Parameters: # limit (optional) the length of the history list # # Results: # If no limit is specified, the current limit is returned # # Side Effects: # Updates history(keep) if a limit is specified proc ::tcl::HistKeep {{count {}}} { variable history if {[llength [info level 0]] == 1} { return $history(keep) } if {![string is integer -strict $count] || ($count < 0)} { return -code error "illegal keep count \"$count\"" } set oldold $history(oldest) set history(oldest) [expr {$history(nextid) - $count}] for {} {$oldold <= $history(oldest)} {incr oldold} { unset -nocomplain history($oldold) } set history(keep) $count } # tcl::HistClear -- # # Erase the history list # # Parameters: # none # # Results: # none # # Side Effects: # Resets the history array, except for the keep limit proc ::tcl::HistClear {} { variable history set keep $history(keep) unset history array set history [list \ nextid 0 \ keep $keep \ oldest -$keep \ ] } # tcl::HistInfo -- # # Return a pretty-printed version of the history list # # Parameters: # num (optional) the length of the history list to return # # Results: # A formatted history list proc ::tcl::HistInfo {{count {}}} { variable history if {[llength [info level 0]] == 1} { set count [expr {$history(keep) + 1}] } elseif {![string is integer -strict $count]} { return -code error "bad integer \"$count\"" } set result {} set newline "" for {set i [expr {$history(nextid) - $count + 1}]} \ {$i <= $history(nextid)} {incr i} { if {![info exists history($i)]} { continue } set cmd [string map [list \n \n\t] [string trimright $history($i) \ \n]] append result $newline[format "%6d %s" $i $cmd] set newline \n } return $result } # tcl::HistRedo -- # # Fetch the previous or specified event, execute it, and then replace # the current history item with that event. # # Parameters: # event (optional) index of history item to redo. Defaults to -1, # which means the previous event. # # Results: # Those of the command being redone. # # Side Effects: # Replaces the current history list item with the one being redone. proc ::tcl::HistRedo {{event -1}} { variable history set i [HistIndex $event] if {$i == $history(nextid)} { return -code error "cannot redo the current event" } set cmd $history($i) HistChange $cmd 0 tailcall eval $cmd } # tcl::HistIndex -- # # Map from an event specifier to an index in the history list. # # Parameters: # event index of history item to redo. # If this is a positive number, it is used directly. # If it is a negative number, then it counts back to a previous # event, where -1 is the most recent event. # A string can be matched, either by being the prefix of a # command or by matching a command with string match. # # Results: # The index into history, or an error if the index didn't match. proc ::tcl::HistIndex {event} { variable history if {![string is integer -strict $event]} { for {set i [expr {$history(nextid)-1}]} {[info exists history($i)]} \ {incr i -1} { if {[string match $event* $history($i)]} { return $i } if {[string match $event $history($i)]} { return $i } } return -code error "no event matches \"$event\"" } elseif {$event <= 0} { set i [expr {$history(nextid) + $event}] } else { set i $event } if {$i <= $history(oldest)} { return -code error "event \"$event\" is too far in the past" } if {$i > $history(nextid)} { return -code error "event \"$event\" hasn't occured yet" } return $i } # tcl::HistEvent -- # # Map from an event specifier to the value in the history list. # # Parameters: # event index of history item to redo. See index for a description of # possible event patterns. # # Results: # The value from the history list. proc ::tcl::HistEvent {{event -1}} { variable history set i [HistIndex $event] if {![info exists history($i)]} { return "" } return [string trimright $history($i) \ \n] } # tcl::HistChange -- # # Replace a value in the history list. # # Parameters: # newValue The new value to put into the history list. # event (optional) index of history item to redo. See index for a # description of possible event patterns. This defaults to 0, # which specifies the current event. # # Side Effects: # Changes the history list. proc ::tcl::HistChange {newValue {event 0}} { variable history set i [HistIndex $event] set history($i) $newValue } # tcl::HistNextID -- # # Returns the number of the next history event. # # Parameters: # None. # # Side Effects: # None. proc ::tcl::HistNextID {} { variable history return [expr {$history(nextid) + 1}] } return # Local Variables: # mode: tcl # fill-column: 78 # End: tcl8.6.5/library/msgs/0000755000175000017500000000000012665173607014207 5ustar sergeisergeitcl8.6.5/library/msgs/ta_in.msg0000644000175000017500000000037311555560473016012 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ta_IN DATE_FORMAT "%d %M %Y" ::msgcat::mcset ta_IN TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset ta_IN DATE_TIME_FORMAT "%d %M %Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/ko.msg0000644000175000017500000000303611555560473015330 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ko DAYS_OF_WEEK_ABBREV [list \ "\uc77c"\ "\uc6d4"\ "\ud654"\ "\uc218"\ "\ubaa9"\ "\uae08"\ "\ud1a0"] ::msgcat::mcset ko DAYS_OF_WEEK_FULL [list \ "\uc77c\uc694\uc77c"\ "\uc6d4\uc694\uc77c"\ "\ud654\uc694\uc77c"\ "\uc218\uc694\uc77c"\ "\ubaa9\uc694\uc77c"\ "\uae08\uc694\uc77c"\ "\ud1a0\uc694\uc77c"] ::msgcat::mcset ko MONTHS_ABBREV [list \ "1\uc6d4"\ "2\uc6d4"\ "3\uc6d4"\ "4\uc6d4"\ "5\uc6d4"\ "6\uc6d4"\ "7\uc6d4"\ "8\uc6d4"\ "9\uc6d4"\ "10\uc6d4"\ "11\uc6d4"\ "12\uc6d4"\ ""] ::msgcat::mcset ko MONTHS_FULL [list \ "1\uc6d4"\ "2\uc6d4"\ "3\uc6d4"\ "4\uc6d4"\ "5\uc6d4"\ "6\uc6d4"\ "7\uc6d4"\ "8\uc6d4"\ "9\uc6d4"\ "10\uc6d4"\ "11\uc6d4"\ "12\uc6d4"\ ""] ::msgcat::mcset ko AM "\uc624\uc804" ::msgcat::mcset ko PM "\uc624\ud6c4" ::msgcat::mcset ko DATE_FORMAT "%Y-%m-%d" ::msgcat::mcset ko TIME_FORMAT_12 "%P %l:%M:%S" ::msgcat::mcset ko DATE_TIME_FORMAT "%Y-%m-%d %P %l:%M:%S %z" ::msgcat::mcset ko LOCALE_DATE_FORMAT "%Y\ub144%B%Od\uc77c" ::msgcat::mcset ko LOCALE_TIME_FORMAT "%H\uc2dc%M\ubd84%S\ucd08" ::msgcat::mcset ko LOCALE_DATE_TIME_FORMAT "%A %Y\ub144%B%Od\uc77c%H\uc2dc%M\ubd84%S\ucd08 %z" } tcl8.6.5/library/msgs/af.msg0000644000175000017500000000173511555560473015311 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset af DAYS_OF_WEEK_ABBREV [list \ "So"\ "Ma"\ "Di"\ "Wo"\ "Do"\ "Vr"\ "Sa"] ::msgcat::mcset af DAYS_OF_WEEK_FULL [list \ "Sondag"\ "Maandag"\ "Dinsdag"\ "Woensdag"\ "Donderdag"\ "Vrydag"\ "Saterdag"] ::msgcat::mcset af MONTHS_ABBREV [list \ "Jan"\ "Feb"\ "Mar"\ "Apr"\ "Mei"\ "Jun"\ "Jul"\ "Aug"\ "Sep"\ "Okt"\ "Nov"\ "Des"\ ""] ::msgcat::mcset af MONTHS_FULL [list \ "Januarie"\ "Februarie"\ "Maart"\ "April"\ "Mei"\ "Junie"\ "Julie"\ "Augustus"\ "September"\ "Oktober"\ "November"\ "Desember"\ ""] ::msgcat::mcset af AM "VM" ::msgcat::mcset af PM "NM" } tcl8.6.5/library/msgs/et.msg0000644000175000017500000000226611555560473015333 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset et DAYS_OF_WEEK_ABBREV [list \ "P"\ "E"\ "T"\ "K"\ "N"\ "R"\ "L"] ::msgcat::mcset et DAYS_OF_WEEK_FULL [list \ "p\u00fchap\u00e4ev"\ "esmasp\u00e4ev"\ "teisip\u00e4ev"\ "kolmap\u00e4ev"\ "neljap\u00e4ev"\ "reede"\ "laup\u00e4ev"] ::msgcat::mcset et MONTHS_ABBREV [list \ "Jaan"\ "Veebr"\ "M\u00e4rts"\ "Apr"\ "Mai"\ "Juuni"\ "Juuli"\ "Aug"\ "Sept"\ "Okt"\ "Nov"\ "Dets"\ ""] ::msgcat::mcset et MONTHS_FULL [list \ "Jaanuar"\ "Veebruar"\ "M\u00e4rts"\ "Aprill"\ "Mai"\ "Juuni"\ "Juuli"\ "August"\ "September"\ "Oktoober"\ "November"\ "Detsember"\ ""] ::msgcat::mcset et BCE "e.m.a." ::msgcat::mcset et CE "m.a.j." ::msgcat::mcset et DATE_FORMAT "%e-%m-%Y" ::msgcat::mcset et TIME_FORMAT "%k:%M:%S" ::msgcat::mcset et DATE_TIME_FORMAT "%e-%m-%Y %k:%M:%S %z" } tcl8.6.5/library/msgs/es_ec.msg0000644000175000017500000000037311555560473015776 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_EC DATE_FORMAT "%d/%m/%Y" ::msgcat::mcset es_EC TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_EC DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/kl_gl.msg0000644000175000017500000000042711555560473016010 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset kl_GL DATE_FORMAT "%d %b %Y" ::msgcat::mcset kl_GL TIME_FORMAT "%T" ::msgcat::mcset kl_GL TIME_FORMAT_12 "%T" ::msgcat::mcset kl_GL DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/te.msg0000644000175000017500000000406611555560473015333 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset te DAYS_OF_WEEK_ABBREV [list \ "\u0c06\u0c26\u0c3f"\ "\u0c38\u0c4b\u0c2e"\ "\u0c2e\u0c02\u0c17\u0c33"\ "\u0c2c\u0c41\u0c27"\ "\u0c17\u0c41\u0c30\u0c41"\ "\u0c36\u0c41\u0c15\u0c4d\u0c30"\ "\u0c36\u0c28\u0c3f"] ::msgcat::mcset te DAYS_OF_WEEK_FULL [list \ "\u0c06\u0c26\u0c3f\u0c35\u0c3e\u0c30\u0c02"\ "\u0c38\u0c4b\u0c2e\u0c35\u0c3e\u0c30\u0c02"\ "\u0c2e\u0c02\u0c17\u0c33\u0c35\u0c3e\u0c30\u0c02"\ "\u0c2c\u0c41\u0c27\u0c35\u0c3e\u0c30\u0c02"\ "\u0c17\u0c41\u0c30\u0c41\u0c35\u0c3e\u0c30\u0c02"\ "\u0c36\u0c41\u0c15\u0c4d\u0c30\u0c35\u0c3e\u0c30\u0c02"\ "\u0c36\u0c28\u0c3f\u0c35\u0c3e\u0c30\u0c02"] ::msgcat::mcset te MONTHS_ABBREV [list \ "\u0c1c\u0c28\u0c35\u0c30\u0c3f"\ "\u0c2b\u0c3f\u0c2c\u0c4d\u0c30\u0c35\u0c30\u0c3f"\ "\u0c2e\u0c3e\u0c30\u0c4d\u0c1a\u0c3f"\ "\u0c0f\u0c2a\u0c4d\u0c30\u0c3f\u0c32\u0c4d"\ "\u0c2e\u0c47"\ "\u0c1c\u0c42\u0c28\u0c4d"\ "\u0c1c\u0c42\u0c32\u0c48"\ "\u0c06\u0c17\u0c38\u0c4d\u0c1f\u0c41"\ "\u0c38\u0c46\u0c2a\u0c4d\u0c1f\u0c46\u0c02\u0c2c\u0c30\u0c4d"\ "\u0c05\u0c15\u0c4d\u0c1f\u0c4b\u0c2c\u0c30\u0c4d"\ "\u0c28\u0c35\u0c02\u0c2c\u0c30\u0c4d"\ "\u0c21\u0c3f\u0c38\u0c46\u0c02\u0c2c\u0c30\u0c4d"\ ""] ::msgcat::mcset te MONTHS_FULL [list \ "\u0c1c\u0c28\u0c35\u0c30\u0c3f"\ "\u0c2b\u0c3f\u0c2c\u0c4d\u0c30\u0c35\u0c30\u0c3f"\ "\u0c2e\u0c3e\u0c30\u0c4d\u0c1a\u0c3f"\ "\u0c0f\u0c2a\u0c4d\u0c30\u0c3f\u0c32\u0c4d"\ "\u0c2e\u0c47"\ "\u0c1c\u0c42\u0c28\u0c4d"\ "\u0c1c\u0c42\u0c32\u0c48"\ "\u0c06\u0c17\u0c38\u0c4d\u0c1f\u0c41"\ "\u0c38\u0c46\u0c2a\u0c4d\u0c1f\u0c46\u0c02\u0c2c\u0c30\u0c4d"\ "\u0c05\u0c15\u0c4d\u0c1f\u0c4b\u0c2c\u0c30\u0c4d"\ "\u0c28\u0c35\u0c02\u0c2c\u0c30\u0c4d"\ "\u0c21\u0c3f\u0c38\u0c46\u0c02\u0c2c\u0c30\u0c4d"\ ""] } tcl8.6.5/library/msgs/id_id.msg0000644000175000017500000000037311555560473015770 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset id_ID DATE_FORMAT "%d %B %Y" ::msgcat::mcset id_ID TIME_FORMAT_12 "%l:%M:%S %P" ::msgcat::mcset id_ID DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z" } tcl8.6.5/library/msgs/fr.msg0000644000175000017500000000226511555560473015331 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset fr DAYS_OF_WEEK_ABBREV [list \ "dim."\ "lun."\ "mar."\ "mer."\ "jeu."\ "ven."\ "sam."] ::msgcat::mcset fr DAYS_OF_WEEK_FULL [list \ "dimanche"\ "lundi"\ "mardi"\ "mercredi"\ "jeudi"\ "vendredi"\ "samedi"] ::msgcat::mcset fr MONTHS_ABBREV [list \ "janv."\ "f\u00e9vr."\ "mars"\ "avr."\ "mai"\ "juin"\ "juil."\ "ao\u00fbt"\ "sept."\ "oct."\ "nov."\ "d\u00e9c."\ ""] ::msgcat::mcset fr MONTHS_FULL [list \ "janvier"\ "f\u00e9vrier"\ "mars"\ "avril"\ "mai"\ "juin"\ "juillet"\ "ao\u00fbt"\ "septembre"\ "octobre"\ "novembre"\ "d\u00e9cembre"\ ""] ::msgcat::mcset fr BCE "av. J.-C." ::msgcat::mcset fr CE "ap. J.-C." ::msgcat::mcset fr DATE_FORMAT "%e %B %Y" ::msgcat::mcset fr TIME_FORMAT "%H:%M:%S" ::msgcat::mcset fr DATE_TIME_FORMAT "%e %B %Y %H:%M:%S %z" } tcl8.6.5/library/msgs/ta.msg0000644000175000017500000000345311555560473015326 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ta DAYS_OF_WEEK_FULL [list \ "\u0b9e\u0bbe\u0baf\u0bbf\u0bb1\u0bc1"\ "\u0ba4\u0bbf\u0b99\u0bcd\u0b95\u0bb3\u0bcd"\ "\u0b9a\u0bc6\u0bb5\u0bcd\u0bb5\u0bbe\u0baf\u0bcd"\ "\u0baa\u0bc1\u0ba4\u0ba9\u0bcd"\ "\u0bb5\u0bbf\u0baf\u0bbe\u0bb4\u0ba9\u0bcd"\ "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf"\ "\u0b9a\u0ba9\u0bbf"] ::msgcat::mcset ta MONTHS_ABBREV [list \ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf"\ "\u0baa\u0bc6\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf"\ "\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd"\ "\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd"\ "\u0bae\u0bc7"\ "\u0b9c\u0bc2\u0ba9\u0bcd"\ "\u0b9c\u0bc2\u0bb2\u0bc8"\ "\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd"\ "\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bae\u0bcd\u0baa\u0bb0\u0bcd"\ "\u0b85\u0b95\u0bcd\u0b9f\u0bcb\u0baa\u0bb0\u0bcd"\ "\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd"\ "\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcdr"] ::msgcat::mcset ta MONTHS_FULL [list \ "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf"\ "\u0baa\u0bc6\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf"\ "\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd"\ "\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd"\ "\u0bae\u0bc7"\ "\u0b9c\u0bc2\u0ba9\u0bcd"\ "\u0b9c\u0bc2\u0bb2\u0bc8"\ "\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd"\ "\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bae\u0bcd\u0baa\u0bb0\u0bcd"\ "\u0b85\u0b95\u0bcd\u0b9f\u0bcb\u0baa\u0bb0\u0bcd"\ "\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd"\ "\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcdr"] ::msgcat::mcset ta AM "\u0b95\u0bbf\u0bae\u0bc1" ::msgcat::mcset ta PM "\u0b95\u0bbf\u0baa\u0bbf" } tcl8.6.5/library/msgs/mt.msg0000644000175000017500000000126211555560473015336 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset mt DAYS_OF_WEEK_ABBREV [list \ "\u0126ad"\ "Tne"\ "Tli"\ "Erb"\ "\u0126am"\ "\u0120im"] ::msgcat::mcset mt MONTHS_ABBREV [list \ "Jan"\ "Fra"\ "Mar"\ "Apr"\ "Mej"\ "\u0120un"\ "Lul"\ "Awi"\ "Set"\ "Ott"\ "Nov"] ::msgcat::mcset mt BCE "QK" ::msgcat::mcset mt CE "" ::msgcat::mcset mt DATE_FORMAT "%A, %e ta %B, %Y" ::msgcat::mcset mt TIME_FORMAT_12 "%l:%M:%S %P" ::msgcat::mcset mt DATE_TIME_FORMAT "%A, %e ta %B, %Y %l:%M:%S %P %z" } tcl8.6.5/library/msgs/kok_in.msg0000644000175000017500000000037611555560473016175 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset kok_IN DATE_FORMAT "%d %M %Y" ::msgcat::mcset kok_IN TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset kok_IN DATE_TIME_FORMAT "%d %M %Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/lv.msg0000644000175000017500000000230311555560473015334 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset lv DAYS_OF_WEEK_ABBREV [list \ "Sv"\ "P"\ "O"\ "T"\ "C"\ "Pk"\ "S"] ::msgcat::mcset lv DAYS_OF_WEEK_FULL [list \ "sv\u0113tdiena"\ "pirmdiena"\ "otrdiena"\ "tre\u0161diena"\ "ceturdien"\ "piektdiena"\ "sestdiena"] ::msgcat::mcset lv MONTHS_ABBREV [list \ "Jan"\ "Feb"\ "Mar"\ "Apr"\ "Maijs"\ "J\u016bn"\ "J\u016bl"\ "Aug"\ "Sep"\ "Okt"\ "Nov"\ "Dec"\ ""] ::msgcat::mcset lv MONTHS_FULL [list \ "janv\u0101ris"\ "febru\u0101ris"\ "marts"\ "apr\u012blis"\ "maijs"\ "j\u016bnijs"\ "j\u016blijs"\ "augusts"\ "septembris"\ "oktobris"\ "novembris"\ "decembris"\ ""] ::msgcat::mcset lv BCE "pm\u0113" ::msgcat::mcset lv CE "m\u0113" ::msgcat::mcset lv DATE_FORMAT "%Y.%e.%m" ::msgcat::mcset lv TIME_FORMAT "%H:%M:%S" ::msgcat::mcset lv DATE_TIME_FORMAT "%Y.%e.%m %H:%M:%S %z" } tcl8.6.5/library/msgs/fi.msg0000644000175000017500000000217111555560473015314 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset fi DAYS_OF_WEEK_ABBREV [list \ "su"\ "ma"\ "ti"\ "ke"\ "to"\ "pe"\ "la"] ::msgcat::mcset fi DAYS_OF_WEEK_FULL [list \ "sunnuntai"\ "maanantai"\ "tiistai"\ "keskiviikko"\ "torstai"\ "perjantai"\ "lauantai"] ::msgcat::mcset fi MONTHS_ABBREV [list \ "tammi"\ "helmi"\ "maalis"\ "huhti"\ "touko"\ "kes\u00e4"\ "hein\u00e4"\ "elo"\ "syys"\ "loka"\ "marras"\ "joulu"\ ""] ::msgcat::mcset fi MONTHS_FULL [list \ "tammikuu"\ "helmikuu"\ "maaliskuu"\ "huhtikuu"\ "toukokuu"\ "kes\u00e4kuu"\ "hein\u00e4kuu"\ "elokuu"\ "syyskuu"\ "lokakuu"\ "marraskuu"\ "joulukuu"\ ""] ::msgcat::mcset fi DATE_FORMAT "%e.%m.%Y" ::msgcat::mcset fi TIME_FORMAT "%k:%M:%S" ::msgcat::mcset fi DATE_TIME_FORMAT "%e.%m.%Y %k:%M:%S %z" } tcl8.6.5/library/msgs/bn.msg0000644000175000017500000000435611555560473015324 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset bn DAYS_OF_WEEK_ABBREV [list \ "\u09b0\u09ac\u09bf"\ "\u09b8\u09cb\u09ae"\ "\u09ae\u0999\u0997\u09b2"\ "\u09ac\u09c1\u09a7"\ "\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf"\ "\u09b6\u09c1\u0995\u09cd\u09b0"\ "\u09b6\u09a8\u09bf"] ::msgcat::mcset bn DAYS_OF_WEEK_FULL [list \ "\u09b0\u09ac\u09bf\u09ac\u09be\u09b0"\ "\u09b8\u09cb\u09ae\u09ac\u09be\u09b0"\ "\u09ae\u0999\u0997\u09b2\u09ac\u09be\u09b0"\ "\u09ac\u09c1\u09a7\u09ac\u09be\u09b0"\ "\u09ac\u09c3\u09b9\u09b8\u09cd\u09aa\u09a4\u09bf\u09ac\u09be\u09b0"\ "\u09b6\u09c1\u0995\u09cd\u09b0\u09ac\u09be\u09b0"\ "\u09b6\u09a8\u09bf\u09ac\u09be\u09b0"] ::msgcat::mcset bn MONTHS_ABBREV [list \ "\u099c\u09be\u09a8\u09c1\u09df\u09be\u09b0\u09c0"\ "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09df\u09be\u09b0\u09c0"\ "\u09ae\u09be\u09b0\u09cd\u099a"\ "\u098f\u09aa\u09cd\u09b0\u09bf\u09b2"\ "\u09ae\u09c7"\ "\u099c\u09c1\u09a8"\ "\u099c\u09c1\u09b2\u09be\u0987"\ "\u0986\u0997\u09b8\u09cd\u099f"\ "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0"\ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0"\ "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0"\ "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0"\ ""] ::msgcat::mcset bn MONTHS_FULL [list \ "\u099c\u09be\u09a8\u09c1\u09df\u09be\u09b0\u09c0"\ "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09df\u09be\u09b0\u09c0"\ "\u09ae\u09be\u09b0\u09cd\u099a"\ "\u098f\u09aa\u09cd\u09b0\u09bf\u09b2"\ "\u09ae\u09c7"\ "\u099c\u09c1\u09a8"\ "\u099c\u09c1\u09b2\u09be\u0987"\ "\u0986\u0997\u09b8\u09cd\u099f"\ "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0"\ "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0"\ "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0"\ "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0"\ ""] ::msgcat::mcset bn AM "\u09aa\u09c2\u09b0\u09cd\u09ac\u09be\u09b9\u09cd\u09a3" ::msgcat::mcset bn PM "\u0985\u09aa\u09b0\u09be\u09b9\u09cd\u09a3" } tcl8.6.5/library/msgs/ar_lb.msg0000644000175000017500000000342411555560473015777 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ar_LB DAYS_OF_WEEK_ABBREV [list \ "\u0627\u0644\u0623\u062d\u062f"\ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646"\ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621"\ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621"\ "\u0627\u0644\u062e\u0645\u064a\u0633"\ "\u0627\u0644\u062c\u0645\u0639\u0629"\ "\u0627\u0644\u0633\u0628\u062a"] ::msgcat::mcset ar_LB MONTHS_ABBREV [list \ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0634\u0628\u0627\u0637"\ "\u0622\u0630\u0627\u0631"\ "\u0646\u064a\u0633\u0627\u0646"\ "\u0646\u0648\u0627\u0631"\ "\u062d\u0632\u064a\u0631\u0627\u0646"\ "\u062a\u0645\u0648\u0632"\ "\u0622\u0628"\ "\u0623\u064a\u0644\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\ ""] ::msgcat::mcset ar_LB MONTHS_FULL [list \ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0634\u0628\u0627\u0637"\ "\u0622\u0630\u0627\u0631"\ "\u0646\u064a\u0633\u0627\u0646"\ "\u0646\u0648\u0627\u0631"\ "\u062d\u0632\u064a\u0631\u0627\u0646"\ "\u062a\u0645\u0648\u0632"\ "\u0622\u0628"\ "\u0623\u064a\u0644\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\ ""] } tcl8.6.5/library/msgs/pt.msg0000644000175000017500000000214711555560473015344 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset pt DAYS_OF_WEEK_ABBREV [list \ "Dom"\ "Seg"\ "Ter"\ "Qua"\ "Qui"\ "Sex"\ "S\u00e1b"] ::msgcat::mcset pt DAYS_OF_WEEK_FULL [list \ "Domingo"\ "Segunda-feira"\ "Ter\u00e7a-feira"\ "Quarta-feira"\ "Quinta-feira"\ "Sexta-feira"\ "S\u00e1bado"] ::msgcat::mcset pt MONTHS_ABBREV [list \ "Jan"\ "Fev"\ "Mar"\ "Abr"\ "Mai"\ "Jun"\ "Jul"\ "Ago"\ "Set"\ "Out"\ "Nov"\ "Dez"\ ""] ::msgcat::mcset pt MONTHS_FULL [list \ "Janeiro"\ "Fevereiro"\ "Mar\u00e7o"\ "Abril"\ "Maio"\ "Junho"\ "Julho"\ "Agosto"\ "Setembro"\ "Outubro"\ "Novembro"\ "Dezembro"\ ""] ::msgcat::mcset pt DATE_FORMAT "%d-%m-%Y" ::msgcat::mcset pt TIME_FORMAT "%k:%M:%S" ::msgcat::mcset pt DATE_TIME_FORMAT "%d-%m-%Y %k:%M:%S %z" } tcl8.6.5/library/msgs/hr.msg0000644000175000017500000000214111555560473015324 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset hr DAYS_OF_WEEK_ABBREV [list \ "ned"\ "pon"\ "uto"\ "sri"\ "\u010det"\ "pet"\ "sub"] ::msgcat::mcset hr DAYS_OF_WEEK_FULL [list \ "nedjelja"\ "ponedjeljak"\ "utorak"\ "srijeda"\ "\u010detvrtak"\ "petak"\ "subota"] ::msgcat::mcset hr MONTHS_ABBREV [list \ "sij"\ "vel"\ "o\u017eu"\ "tra"\ "svi"\ "lip"\ "srp"\ "kol"\ "ruj"\ "lis"\ "stu"\ "pro"\ ""] ::msgcat::mcset hr MONTHS_FULL [list \ "sije\u010danj"\ "velja\u010da"\ "o\u017eujak"\ "travanj"\ "svibanj"\ "lipanj"\ "srpanj"\ "kolovoz"\ "rujan"\ "listopad"\ "studeni"\ "prosinac"\ ""] ::msgcat::mcset hr DATE_FORMAT "%Y.%m.%d" ::msgcat::mcset hr TIME_FORMAT "%H:%M:%S" ::msgcat::mcset hr DATE_TIME_FORMAT "%Y.%m.%d %H:%M:%S %z" } tcl8.6.5/library/msgs/it.msg0000644000175000017500000000233011555560473015327 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset it DAYS_OF_WEEK_ABBREV [list \ "dom"\ "lun"\ "mar"\ "mer"\ "gio"\ "ven"\ "sab"] ::msgcat::mcset it DAYS_OF_WEEK_FULL [list \ "domenica"\ "luned\u00ec"\ "marted\u00ec"\ "mercoled\u00ec"\ "gioved\u00ec"\ "venerd\u00ec"\ "sabato"] ::msgcat::mcset it MONTHS_ABBREV [list \ "gen"\ "feb"\ "mar"\ "apr"\ "mag"\ "giu"\ "lug"\ "ago"\ "set"\ "ott"\ "nov"\ "dic"\ ""] ::msgcat::mcset it MONTHS_FULL [list \ "gennaio"\ "febbraio"\ "marzo"\ "aprile"\ "maggio"\ "giugno"\ "luglio"\ "agosto"\ "settembre"\ "ottobre"\ "novembre"\ "dicembre"\ ""] ::msgcat::mcset it BCE "aC" ::msgcat::mcset it CE "dC" ::msgcat::mcset it AM "m." ::msgcat::mcset it PM "p." ::msgcat::mcset it DATE_FORMAT "%d %B %Y" ::msgcat::mcset it TIME_FORMAT "%H:%M:%S" ::msgcat::mcset it DATE_TIME_FORMAT "%d %B %Y %H:%M:%S %z" } tcl8.6.5/library/msgs/en_sg.msg0000644000175000017500000000037311555560473016013 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_SG DATE_FORMAT "%d %b %Y" ::msgcat::mcset en_SG TIME_FORMAT_12 "%P %I:%M:%S" ::msgcat::mcset en_SG DATE_TIME_FORMAT "%d %b %Y %P %I:%M:%S %z" } tcl8.6.5/library/msgs/lt.msg0000644000175000017500000000234711555560473015342 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset lt DAYS_OF_WEEK_ABBREV [list \ "Sk"\ "Pr"\ "An"\ "Tr"\ "Kt"\ "Pn"\ "\u0160t"] ::msgcat::mcset lt DAYS_OF_WEEK_FULL [list \ "Sekmadienis"\ "Pirmadienis"\ "Antradienis"\ "Tre\u010diadienis"\ "Ketvirtadienis"\ "Penktadienis"\ "\u0160e\u0161tadienis"] ::msgcat::mcset lt MONTHS_ABBREV [list \ "Sau"\ "Vas"\ "Kov"\ "Bal"\ "Geg"\ "Bir"\ "Lie"\ "Rgp"\ "Rgs"\ "Spa"\ "Lap"\ "Grd"\ ""] ::msgcat::mcset lt MONTHS_FULL [list \ "Sausio"\ "Vasario"\ "Kovo"\ "Baland\u017eio"\ "Gegu\u017e\u0117s"\ "Bir\u017eelio"\ "Liepos"\ "Rugpj\u016b\u010dio"\ "Rugs\u0117jo"\ "Spalio"\ "Lapkri\u010dio"\ "Gruod\u017eio"\ ""] ::msgcat::mcset lt BCE "pr.Kr." ::msgcat::mcset lt CE "po.Kr." ::msgcat::mcset lt DATE_FORMAT "%Y.%m.%e" ::msgcat::mcset lt TIME_FORMAT "%H.%M.%S" ::msgcat::mcset lt DATE_TIME_FORMAT "%Y.%m.%e %H.%M.%S %z" } tcl8.6.5/library/msgs/tr.msg0000644000175000017500000000215511555560473015345 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset tr DAYS_OF_WEEK_ABBREV [list \ "Paz"\ "Pzt"\ "Sal"\ "\u00c7ar"\ "Per"\ "Cum"\ "Cmt"] ::msgcat::mcset tr DAYS_OF_WEEK_FULL [list \ "Pazar"\ "Pazartesi"\ "Sal\u0131"\ "\u00c7ar\u015famba"\ "Per\u015fembe"\ "Cuma"\ "Cumartesi"] ::msgcat::mcset tr MONTHS_ABBREV [list \ "Oca"\ "\u015eub"\ "Mar"\ "Nis"\ "May"\ "Haz"\ "Tem"\ "A\u011fu"\ "Eyl"\ "Eki"\ "Kas"\ "Ara"\ ""] ::msgcat::mcset tr MONTHS_FULL [list \ "Ocak"\ "\u015eubat"\ "Mart"\ "Nisan"\ "May\u0131s"\ "Haziran"\ "Temmuz"\ "A\u011fustos"\ "Eyl\u00fcl"\ "Ekim"\ "Kas\u0131m"\ "Aral\u0131k"\ ""] ::msgcat::mcset tr DATE_FORMAT "%d.%m.%Y" ::msgcat::mcset tr TIME_FORMAT "%H:%M:%S" ::msgcat::mcset tr DATE_TIME_FORMAT "%d.%m.%Y %H:%M:%S %z" } tcl8.6.5/library/msgs/fr_ch.msg0000644000175000017500000000043111555560473015774 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset fr_CH DATE_FORMAT "%d. %m. %y" ::msgcat::mcset fr_CH TIME_FORMAT "%T" ::msgcat::mcset fr_CH TIME_FORMAT_12 "%T" ::msgcat::mcset fr_CH DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/en_zw.msg0000644000175000017500000000037311555560473016042 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_ZW DATE_FORMAT "%d %B %Y" ::msgcat::mcset en_ZW TIME_FORMAT_12 "%l:%M:%S %P" ::msgcat::mcset en_ZW DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z" } tcl8.6.5/library/msgs/es_sv.msg0000644000175000017500000000037311555560473016037 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_SV DATE_FORMAT "%m-%d-%Y" ::msgcat::mcset es_SV TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_SV DATE_TIME_FORMAT "%m-%d-%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/eu.msg0000644000175000017500000000173111555560473015330 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset eu DAYS_OF_WEEK_ABBREV [list \ "igandea"\ "astelehena"\ "asteartea"\ "asteazkena"\ "osteguna"\ "ostirala"\ "larunbata"] ::msgcat::mcset eu DAYS_OF_WEEK_FULL [list \ "igandea"\ "astelehena"\ "asteartea"\ "asteazkena"\ "osteguna"\ "ostirala"\ "larunbata"] ::msgcat::mcset eu MONTHS_ABBREV [list \ "urt"\ "ots"\ "mar"\ "api"\ "mai"\ "eka"\ "uzt"\ "abu"\ "ira"\ "urr"\ "aza"\ "abe"\ ""] ::msgcat::mcset eu MONTHS_FULL [list \ "urtarrila"\ "otsaila"\ "martxoa"\ "apirila"\ "maiatza"\ "ekaina"\ "uztaila"\ "abuztua"\ "iraila"\ "urria"\ "azaroa"\ "abendua"\ ""] } tcl8.6.5/library/msgs/es_bo.msg0000644000175000017500000000037311555560473016007 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_BO DATE_FORMAT "%d-%m-%Y" ::msgcat::mcset es_BO TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_BO DATE_TIME_FORMAT "%d-%m-%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/id.msg0000644000175000017500000000162211555560473015312 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset id DAYS_OF_WEEK_ABBREV [list \ "Min"\ "Sen"\ "Sel"\ "Rab"\ "Kam"\ "Jum"\ "Sab"] ::msgcat::mcset id DAYS_OF_WEEK_FULL [list \ "Minggu"\ "Senin"\ "Selasa"\ "Rabu"\ "Kamis"\ "Jumat"\ "Sabtu"] ::msgcat::mcset id MONTHS_ABBREV [list \ "Jan"\ "Peb"\ "Mar"\ "Apr"\ "Mei"\ "Jun"\ "Jul"\ "Agu"\ "Sep"\ "Okt"\ "Nov"\ "Des"\ ""] ::msgcat::mcset id MONTHS_FULL [list \ "Januari"\ "Pebruari"\ "Maret"\ "April"\ "Mei"\ "Juni"\ "Juli"\ "Agustus"\ "September"\ "Oktober"\ "November"\ "Desember"\ ""] } tcl8.6.5/library/msgs/mk.msg0000644000175000017500000000407111555560473015326 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset mk DAYS_OF_WEEK_ABBREV [list \ "\u043d\u0435\u0434."\ "\u043f\u043e\u043d."\ "\u0432\u0442."\ "\u0441\u0440\u0435."\ "\u0447\u0435\u0442."\ "\u043f\u0435\u0442."\ "\u0441\u0430\u0431."] ::msgcat::mcset mk DAYS_OF_WEEK_FULL [list \ "\u043d\u0435\u0434\u0435\u043b\u0430"\ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a"\ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a"\ "\u0441\u0440\u0435\u0434\u0430"\ "\u0447\u0435\u0442\u0432\u0440\u0442\u043e\u043a"\ "\u043f\u0435\u0442\u043e\u043a"\ "\u0441\u0430\u0431\u043e\u0442\u0430"] ::msgcat::mcset mk MONTHS_ABBREV [list \ "\u0458\u0430\u043d."\ "\u0444\u0435\u0432."\ "\u043c\u0430\u0440."\ "\u0430\u043f\u0440."\ "\u043c\u0430\u0458."\ "\u0458\u0443\u043d."\ "\u0458\u0443\u043b."\ "\u0430\u0432\u0433."\ "\u0441\u0435\u043f\u0442."\ "\u043e\u043a\u0442."\ "\u043d\u043e\u0435\u043c."\ "\u0434\u0435\u043a\u0435\u043c."\ ""] ::msgcat::mcset mk MONTHS_FULL [list \ "\u0458\u0430\u043d\u0443\u0430\u0440\u0438"\ "\u0444\u0435\u0432\u0440\u0443\u0430\u0440\u0438"\ "\u043c\u0430\u0440\u0442"\ "\u0430\u043f\u0440\u0438\u043b"\ "\u043c\u0430\u0458"\ "\u0458\u0443\u043d\u0438"\ "\u0458\u0443\u043b\u0438"\ "\u0430\u0432\u0433\u0443\u0441\u0442"\ "\u0441\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438"\ "\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438"\ "\u043d\u043e\u0435\u043c\u0432\u0440\u0438"\ "\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438"\ ""] ::msgcat::mcset mk BCE "\u043f\u0440.\u043d.\u0435." ::msgcat::mcset mk CE "\u0430\u0435." ::msgcat::mcset mk DATE_FORMAT "%e.%m.%Y" ::msgcat::mcset mk TIME_FORMAT "%H:%M:%S %z" ::msgcat::mcset mk DATE_TIME_FORMAT "%e.%m.%Y %H:%M:%S %z %z" } tcl8.6.5/library/msgs/te_in.msg0000644000175000017500000000063311555560473016015 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset te_IN AM "\u0c2a\u0c42\u0c30\u0c4d\u0c35\u0c3e\u0c39\u0c4d\u0c28" ::msgcat::mcset te_IN PM "\u0c05\u0c2a\u0c30\u0c3e\u0c39\u0c4d\u0c28" ::msgcat::mcset te_IN DATE_FORMAT "%d/%m/%Y" ::msgcat::mcset te_IN TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset te_IN DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/zh.msg0000644000175000017500000000640211555560473015340 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset zh DAYS_OF_WEEK_ABBREV [list \ "\u661f\u671f\u65e5"\ "\u661f\u671f\u4e00"\ "\u661f\u671f\u4e8c"\ "\u661f\u671f\u4e09"\ "\u661f\u671f\u56db"\ "\u661f\u671f\u4e94"\ "\u661f\u671f\u516d"] ::msgcat::mcset zh DAYS_OF_WEEK_FULL [list \ "\u661f\u671f\u65e5"\ "\u661f\u671f\u4e00"\ "\u661f\u671f\u4e8c"\ "\u661f\u671f\u4e09"\ "\u661f\u671f\u56db"\ "\u661f\u671f\u4e94"\ "\u661f\u671f\u516d"] ::msgcat::mcset zh MONTHS_ABBREV [list \ "\u4e00\u6708"\ "\u4e8c\u6708"\ "\u4e09\u6708"\ "\u56db\u6708"\ "\u4e94\u6708"\ "\u516d\u6708"\ "\u4e03\u6708"\ "\u516b\u6708"\ "\u4e5d\u6708"\ "\u5341\u6708"\ "\u5341\u4e00\u6708"\ "\u5341\u4e8c\u6708"\ ""] ::msgcat::mcset zh MONTHS_FULL [list \ "\u4e00\u6708"\ "\u4e8c\u6708"\ "\u4e09\u6708"\ "\u56db\u6708"\ "\u4e94\u6708"\ "\u516d\u6708"\ "\u4e03\u6708"\ "\u516b\u6708"\ "\u4e5d\u6708"\ "\u5341\u6708"\ "\u5341\u4e00\u6708"\ "\u5341\u4e8c\u6708"\ ""] ::msgcat::mcset zh BCE "\u516c\u5143\u524d" ::msgcat::mcset zh CE "\u516c\u5143" ::msgcat::mcset zh AM "\u4e0a\u5348" ::msgcat::mcset zh PM "\u4e0b\u5348" ::msgcat::mcset zh LOCALE_NUMERALS "\u3007 \u4e00 \u4e8c \u4e09 \u56db \u4e94 \u516d \u4e03 \u516b \u4e5d \u5341 \u5341\u4e00 \u5341\u4e8c \u5341\u4e09 \u5341\u56db \u5341\u4e94 \u5341\u516d \u5341\u4e03 \u5341\u516b \u5341\u4e5d \u4e8c\u5341 \u5eff\u4e00 \u5eff\u4e8c \u5eff\u4e09 \u5eff\u56db \u5eff\u4e94 \u5eff\u516d \u5eff\u4e03 \u5eff\u516b \u5eff\u4e5d \u4e09\u5341 \u5345\u4e00 \u5345\u4e8c \u5345\u4e09 \u5345\u56db \u5345\u4e94 \u5345\u516d \u5345\u4e03 \u5345\u516b \u5345\u4e5d \u56db\u5341 \u56db\u5341\u4e00 \u56db\u5341\u4e8c \u56db\u5341\u4e09 \u56db\u5341\u56db \u56db\u5341\u4e94 \u56db\u5341\u516d \u56db\u5341\u4e03 \u56db\u5341\u516b \u56db\u5341\u4e5d \u4e94\u5341 \u4e94\u5341\u4e00 \u4e94\u5341\u4e8c \u4e94\u5341\u4e09 \u4e94\u5341\u56db \u4e94\u5341\u4e94 \u4e94\u5341\u516d \u4e94\u5341\u4e03 \u4e94\u5341\u516b \u4e94\u5341\u4e5d \u516d\u5341 \u516d\u5341\u4e00 \u516d\u5341\u4e8c \u516d\u5341\u4e09 \u516d\u5341\u56db \u516d\u5341\u4e94 \u516d\u5341\u516d \u516d\u5341\u4e03 \u516d\u5341\u516b \u516d\u5341\u4e5d \u4e03\u5341 \u4e03\u5341\u4e00 \u4e03\u5341\u4e8c \u4e03\u5341\u4e09 \u4e03\u5341\u56db \u4e03\u5341\u4e94 \u4e03\u5341\u516d \u4e03\u5341\u4e03 \u4e03\u5341\u516b \u4e03\u5341\u4e5d \u516b\u5341 \u516b\u5341\u4e00 \u516b\u5341\u4e8c \u516b\u5341\u4e09 \u516b\u5341\u56db \u516b\u5341\u4e94 \u516b\u5341\u516d \u516b\u5341\u4e03 \u516b\u5341\u516b \u516b\u5341\u4e5d \u4e5d\u5341 \u4e5d\u5341\u4e00 \u4e5d\u5341\u4e8c \u4e5d\u5341\u4e09 \u4e5d\u5341\u56db \u4e5d\u5341\u4e94 \u4e5d\u5341\u516d \u4e5d\u5341\u4e03 \u4e5d\u5341\u516b \u4e5d\u5341\u4e5d" ::msgcat::mcset zh LOCALE_DATE_FORMAT "\u516c\u5143%Y\u5e74%B%Od\u65e5" ::msgcat::mcset zh LOCALE_TIME_FORMAT "%OH\u65f6%OM\u5206%OS\u79d2" ::msgcat::mcset zh LOCALE_DATE_TIME_FORMAT "%A %Y\u5e74%B%Od\u65e5%OH\u65f6%OM\u5206%OS\u79d2 %z" } tcl8.6.5/library/msgs/sh.msg0000644000175000017500000000221011555560473015322 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset sh DAYS_OF_WEEK_ABBREV [list \ "Ned"\ "Pon"\ "Uto"\ "Sre"\ "\u010cet"\ "Pet"\ "Sub"] ::msgcat::mcset sh DAYS_OF_WEEK_FULL [list \ "Nedelja"\ "Ponedeljak"\ "Utorak"\ "Sreda"\ "\u010cetvrtak"\ "Petak"\ "Subota"] ::msgcat::mcset sh MONTHS_ABBREV [list \ "Jan"\ "Feb"\ "Mar"\ "Apr"\ "Maj"\ "Jun"\ "Jul"\ "Avg"\ "Sep"\ "Okt"\ "Nov"\ "Dec"\ ""] ::msgcat::mcset sh MONTHS_FULL [list \ "Januar"\ "Februar"\ "Mart"\ "April"\ "Maj"\ "Juni"\ "Juli"\ "Avgust"\ "Septembar"\ "Oktobar"\ "Novembar"\ "Decembar"\ ""] ::msgcat::mcset sh BCE "p. n. e." ::msgcat::mcset sh CE "n. e." ::msgcat::mcset sh DATE_FORMAT "%d.%m.%Y." ::msgcat::mcset sh TIME_FORMAT "%k.%M.%S" ::msgcat::mcset sh DATE_TIME_FORMAT "%d.%m.%Y. %k.%M.%S %z" } tcl8.6.5/library/msgs/gv_gb.msg0000644000175000017500000000037311555560473016004 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset gv_GB DATE_FORMAT "%d %B %Y" ::msgcat::mcset gv_GB TIME_FORMAT_12 "%l:%M:%S %P" ::msgcat::mcset gv_GB DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z" } tcl8.6.5/library/msgs/en_be.msg0000644000175000017500000000046111555560473015766 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_BE DATE_FORMAT "%d %b %Y" ::msgcat::mcset en_BE TIME_FORMAT "%k:%M:%S" ::msgcat::mcset en_BE TIME_FORMAT_12 "%k h %M min %S s %z" ::msgcat::mcset en_BE DATE_TIME_FORMAT "%d %b %Y %k:%M:%S %z" } tcl8.6.5/library/msgs/sr.msg0000644000175000017500000000376311555560473015352 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset sr DAYS_OF_WEEK_ABBREV [list \ "\u041d\u0435\u0434"\ "\u041f\u043e\u043d"\ "\u0423\u0442\u043e"\ "\u0421\u0440\u0435"\ "\u0427\u0435\u0442"\ "\u041f\u0435\u0442"\ "\u0421\u0443\u0431"] ::msgcat::mcset sr DAYS_OF_WEEK_FULL [list \ "\u041d\u0435\u0434\u0435\u0459\u0430"\ "\u041f\u043e\u043d\u0435\u0434\u0435\u0459\u0430\u043a"\ "\u0423\u0442\u043e\u0440\u0430\u043a"\ "\u0421\u0440\u0435\u0434\u0430"\ "\u0427\u0435\u0442\u0432\u0440\u0442\u0430\u043a"\ "\u041f\u0435\u0442\u0430\u043a"\ "\u0421\u0443\u0431\u043e\u0442\u0430"] ::msgcat::mcset sr MONTHS_ABBREV [list \ "\u0408\u0430\u043d"\ "\u0424\u0435\u0431"\ "\u041c\u0430\u0440"\ "\u0410\u043f\u0440"\ "\u041c\u0430\u0458"\ "\u0408\u0443\u043d"\ "\u0408\u0443\u043b"\ "\u0410\u0432\u0433"\ "\u0421\u0435\u043f"\ "\u041e\u043a\u0442"\ "\u041d\u043e\u0432"\ "\u0414\u0435\u0446"\ ""] ::msgcat::mcset sr MONTHS_FULL [list \ "\u0408\u0430\u043d\u0443\u0430\u0440"\ "\u0424\u0435\u0431\u0440\u0443\u0430\u0440"\ "\u041c\u0430\u0440\u0442"\ "\u0410\u043f\u0440\u0438\u043b"\ "\u041c\u0430\u0458"\ "\u0408\u0443\u043d\u0438"\ "\u0408\u0443\u043b\u0438"\ "\u0410\u0432\u0433\u0443\u0441\u0442"\ "\u0421\u0435\u043f\u0442\u0435\u043c\u0431\u0430\u0440"\ "\u041e\u043a\u0442\u043e\u0431\u0430\u0440"\ "\u041d\u043e\u0432\u0435\u043c\u0431\u0430\u0440"\ "\u0414\u0435\u0446\u0435\u043c\u0431\u0430\u0440"\ ""] ::msgcat::mcset sr BCE "\u043f. \u043d. \u0435." ::msgcat::mcset sr CE "\u043d. \u0435" ::msgcat::mcset sr DATE_FORMAT "%Y.%m.%e" ::msgcat::mcset sr TIME_FORMAT "%k.%M.%S" ::msgcat::mcset sr DATE_TIME_FORMAT "%Y.%m.%e %k.%M.%S %z" } tcl8.6.5/library/msgs/ja.msg0000644000175000017500000000320011555560473015302 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ja DAYS_OF_WEEK_ABBREV [list \ "\u65e5"\ "\u6708"\ "\u706b"\ "\u6c34"\ "\u6728"\ "\u91d1"\ "\u571f"] ::msgcat::mcset ja DAYS_OF_WEEK_FULL [list \ "\u65e5\u66dc\u65e5"\ "\u6708\u66dc\u65e5"\ "\u706b\u66dc\u65e5"\ "\u6c34\u66dc\u65e5"\ "\u6728\u66dc\u65e5"\ "\u91d1\u66dc\u65e5"\ "\u571f\u66dc\u65e5"] ::msgcat::mcset ja MONTHS_FULL [list \ "1\u6708"\ "2\u6708"\ "3\u6708"\ "4\u6708"\ "5\u6708"\ "6\u6708"\ "7\u6708"\ "8\u6708"\ "9\u6708"\ "10\u6708"\ "11\u6708"\ "12\u6708"] ::msgcat::mcset ja BCE "\u7d00\u5143\u524d" ::msgcat::mcset ja CE "\u897f\u66a6" ::msgcat::mcset ja AM "\u5348\u524d" ::msgcat::mcset ja PM "\u5348\u5f8c" ::msgcat::mcset ja DATE_FORMAT "%Y/%m/%d" ::msgcat::mcset ja TIME_FORMAT "%k:%M:%S" ::msgcat::mcset ja TIME_FORMAT_12 "%P %I:%M:%S" ::msgcat::mcset ja DATE_TIME_FORMAT "%Y/%m/%d %k:%M:%S %z" ::msgcat::mcset ja LOCALE_DATE_FORMAT "%EY\u5e74%m\u6708%d\u65e5" ::msgcat::mcset ja LOCALE_TIME_FORMAT "%H\u6642%M\u5206%S\u79d2" ::msgcat::mcset ja LOCALE_DATE_TIME_FORMAT "%EY\u5e74%m\u6708%d\u65e5 (%a) %H\u6642%M\u5206%S\u79d2 %z" ::msgcat::mcset ja LOCALE_ERAS "\u007b-9223372036854775808 \u897f\u66a6 0\u007d \u007b-3061011600 \u660e\u6cbb 1867\u007d \u007b-1812186000 \u5927\u6b63 1911\u007d \u007b-1357635600 \u662d\u548c 1925\u007d \u007b600220800 \u5e73\u6210 1988\u007d" } tcl8.6.5/library/msgs/mr_in.msg0000644000175000017500000000037311555560473016024 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset mr_IN DATE_FORMAT "%d %M %Y" ::msgcat::mcset mr_IN TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset mr_IN DATE_TIME_FORMAT "%d %M %Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/fa_in.msg0000644000175000017500000000364511555560473016001 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset fa_IN DAYS_OF_WEEK_ABBREV [list \ "\u06cc\u2214"\ "\u062f\u2214"\ "\u0633\u2214"\ "\u0686\u2214"\ "\u067e\u2214"\ "\u062c\u2214"\ "\u0634\u2214"] ::msgcat::mcset fa_IN DAYS_OF_WEEK_FULL [list \ "\u06cc\u06cc\u200c\u0634\u0646\u0628\u0647"\ "\u062f\u0648\u0634\u0646\u0628\u0647"\ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647"\ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647"\ "\u067e\u0646\u062c\u200c\u0634\u0646\u0628\u0647"\ "\u062c\u0645\u0639\u0647"\ "\u0634\u0646\u0628\u0647"] ::msgcat::mcset fa_IN MONTHS_ABBREV [list \ "\u0698\u0627\u0646"\ "\u0641\u0648\u0631"\ "\u0645\u0627\u0631"\ "\u0622\u0648\u0631"\ "\u0645\u0640\u0647"\ "\u0698\u0648\u0646"\ "\u0698\u0648\u06cc"\ "\u0627\u0648\u062a"\ "\u0633\u067e\u062a"\ "\u0627\u0643\u062a"\ "\u0646\u0648\u0627"\ "\u062f\u0633\u0627"\ ""] ::msgcat::mcset fa_IN MONTHS_FULL [list \ "\u0698\u0627\u0646\u0648\u06cc\u0647"\ "\u0641\u0648\u0631\u0648\u06cc\u0647"\ "\u0645\u0627\u0631\u0633"\ "\u0622\u0648\u0631\u06cc\u0644"\ "\u0645\u0647"\ "\u0698\u0648\u0626\u0646"\ "\u0698\u0648\u0626\u06cc\u0647"\ "\u0627\u0648\u062a"\ "\u0633\u067e\u062a\u0627\u0645\u0628\u0631"\ "\u0627\u0643\u062a\u0628\u0631"\ "\u0646\u0648\u0627\u0645\u0628\u0631"\ "\u062f\u0633\u0627\u0645\u0628\u0631"\ ""] ::msgcat::mcset fa_IN AM "\u0635\u0628\u062d" ::msgcat::mcset fa_IN PM "\u0639\u0635\u0631" ::msgcat::mcset fa_IN DATE_FORMAT "%A %d %B %Y" ::msgcat::mcset fa_IN TIME_FORMAT_12 "%I:%M:%S %z" ::msgcat::mcset fa_IN DATE_TIME_FORMAT "%A %d %B %Y %I:%M:%S %z %z" } tcl8.6.5/library/msgs/cs.msg0000644000175000017500000000242411555560473015324 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset cs DAYS_OF_WEEK_ABBREV [list \ "Ne"\ "Po"\ "\u00dat"\ "St"\ "\u010ct"\ "P\u00e1"\ "So"] ::msgcat::mcset cs DAYS_OF_WEEK_FULL [list \ "Ned\u011ble"\ "Pond\u011bl\u00ed"\ "\u00dater\u00fd"\ "St\u0159eda"\ "\u010ctvrtek"\ "P\u00e1tek"\ "Sobota"] ::msgcat::mcset cs MONTHS_ABBREV [list \ "I"\ "II"\ "III"\ "IV"\ "V"\ "VI"\ "VII"\ "VIII"\ "IX"\ "X"\ "XI"\ "XII"\ ""] ::msgcat::mcset cs MONTHS_FULL [list \ "leden"\ "\u00fanor"\ "b\u0159ezen"\ "duben"\ "kv\u011bten"\ "\u010derven"\ "\u010dervenec"\ "srpen"\ "z\u00e1\u0159\u00ed"\ "\u0159\u00edjen"\ "listopad"\ "prosinec"\ ""] ::msgcat::mcset cs BCE "p\u0159.Kr." ::msgcat::mcset cs CE "po Kr." ::msgcat::mcset cs AM "dop." ::msgcat::mcset cs PM "odp." ::msgcat::mcset cs DATE_FORMAT "%e.%m.%Y" ::msgcat::mcset cs TIME_FORMAT "%k:%M:%S" ::msgcat::mcset cs DATE_TIME_FORMAT "%e.%m.%Y %k:%M:%S %z" } tcl8.6.5/library/msgs/es.msg0000644000175000017500000000223411555560473015325 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es DAYS_OF_WEEK_ABBREV [list \ "dom"\ "lun"\ "mar"\ "mi\u00e9"\ "jue"\ "vie"\ "s\u00e1b"] ::msgcat::mcset es DAYS_OF_WEEK_FULL [list \ "domingo"\ "lunes"\ "martes"\ "mi\u00e9rcoles"\ "jueves"\ "viernes"\ "s\u00e1bado"] ::msgcat::mcset es MONTHS_ABBREV [list \ "ene"\ "feb"\ "mar"\ "abr"\ "may"\ "jun"\ "jul"\ "ago"\ "sep"\ "oct"\ "nov"\ "dic"\ ""] ::msgcat::mcset es MONTHS_FULL [list \ "enero"\ "febrero"\ "marzo"\ "abril"\ "mayo"\ "junio"\ "julio"\ "agosto"\ "septiembre"\ "octubre"\ "noviembre"\ "diciembre"\ ""] ::msgcat::mcset es BCE "a.C." ::msgcat::mcset es CE "d.C." ::msgcat::mcset es DATE_FORMAT "%e de %B de %Y" ::msgcat::mcset es TIME_FORMAT "%k:%M:%S" ::msgcat::mcset es DATE_TIME_FORMAT "%e de %B de %Y %k:%M:%S %z" } tcl8.6.5/library/msgs/en_ca.msg0000644000175000017500000000044011555560473015760 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_CA DATE_FORMAT "%d/%m/%y" ::msgcat::mcset en_CA TIME_FORMAT "%r" ::msgcat::mcset en_CA TIME_FORMAT_12 "%I:%M:%S %p" ::msgcat::mcset en_CA DATE_TIME_FORMAT "%a %d %b %Y %r %z" } tcl8.6.5/library/msgs/de.msg0000644000175000017500000000230611555560473015306 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset de DAYS_OF_WEEK_ABBREV [list \ "So"\ "Mo"\ "Di"\ "Mi"\ "Do"\ "Fr"\ "Sa"] ::msgcat::mcset de DAYS_OF_WEEK_FULL [list \ "Sonntag"\ "Montag"\ "Dienstag"\ "Mittwoch"\ "Donnerstag"\ "Freitag"\ "Samstag"] ::msgcat::mcset de MONTHS_ABBREV [list \ "Jan"\ "Feb"\ "Mrz"\ "Apr"\ "Mai"\ "Jun"\ "Jul"\ "Aug"\ "Sep"\ "Okt"\ "Nov"\ "Dez"\ ""] ::msgcat::mcset de MONTHS_FULL [list \ "Januar"\ "Februar"\ "M\u00e4rz"\ "April"\ "Mai"\ "Juni"\ "Juli"\ "August"\ "September"\ "Oktober"\ "November"\ "Dezember"\ ""] ::msgcat::mcset de BCE "v. Chr." ::msgcat::mcset de CE "n. Chr." ::msgcat::mcset de AM "vorm." ::msgcat::mcset de PM "nachm." ::msgcat::mcset de DATE_FORMAT "%d.%m.%Y" ::msgcat::mcset de TIME_FORMAT "%H:%M:%S" ::msgcat::mcset de DATE_TIME_FORMAT "%d.%m.%Y %H:%M:%S %z" } tcl8.6.5/library/msgs/es_pe.msg0000644000175000017500000000037311555560473016013 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_PE DATE_FORMAT "%d/%m/%Y" ::msgcat::mcset es_PE TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_PE DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/sw.msg0000644000175000017500000000173711555560473015356 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset sw DAYS_OF_WEEK_ABBREV [list \ "Jpi"\ "Jtt"\ "Jnn"\ "Jtn"\ "Alh"\ "Iju"\ "Jmo"] ::msgcat::mcset sw DAYS_OF_WEEK_FULL [list \ "Jumapili"\ "Jumatatu"\ "Jumanne"\ "Jumatano"\ "Alhamisi"\ "Ijumaa"\ "Jumamosi"] ::msgcat::mcset sw MONTHS_ABBREV [list \ "Jan"\ "Feb"\ "Mar"\ "Apr"\ "Mei"\ "Jun"\ "Jul"\ "Ago"\ "Sep"\ "Okt"\ "Nov"\ "Des"\ ""] ::msgcat::mcset sw MONTHS_FULL [list \ "Januari"\ "Februari"\ "Machi"\ "Aprili"\ "Mei"\ "Juni"\ "Julai"\ "Agosti"\ "Septemba"\ "Oktoba"\ "Novemba"\ "Desemba"\ ""] ::msgcat::mcset sw BCE "KK" ::msgcat::mcset sw CE "BK" } tcl8.6.5/library/msgs/th.msg0000644000175000017500000000440111555560473015327 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset th DAYS_OF_WEEK_ABBREV [list \ "\u0e2d\u0e32."\ "\u0e08."\ "\u0e2d."\ "\u0e1e."\ "\u0e1e\u0e24."\ "\u0e28."\ "\u0e2a."] ::msgcat::mcset th DAYS_OF_WEEK_FULL [list \ "\u0e27\u0e31\u0e19\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c"\ "\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c"\ "\u0e27\u0e31\u0e19\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23"\ "\u0e27\u0e31\u0e19\u0e1e\u0e38\u0e18"\ "\u0e27\u0e31\u0e19\u0e1e\u0e24\u0e2b\u0e31\u0e2a\u0e1a\u0e14\u0e35"\ "\u0e27\u0e31\u0e19\u0e28\u0e38\u0e01\u0e23\u0e4c"\ "\u0e27\u0e31\u0e19\u0e40\u0e2a\u0e32\u0e23\u0e4c"] ::msgcat::mcset th MONTHS_ABBREV [list \ "\u0e21.\u0e04."\ "\u0e01.\u0e1e."\ "\u0e21\u0e35.\u0e04."\ "\u0e40\u0e21.\u0e22."\ "\u0e1e.\u0e04."\ "\u0e21\u0e34.\u0e22."\ "\u0e01.\u0e04."\ "\u0e2a.\u0e04."\ "\u0e01.\u0e22."\ "\u0e15.\u0e04."\ "\u0e1e.\u0e22."\ "\u0e18.\u0e04."\ ""] ::msgcat::mcset th MONTHS_FULL [list \ "\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21"\ "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c"\ "\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21"\ "\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19"\ "\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21"\ "\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19"\ "\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21"\ "\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21"\ "\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19"\ "\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21"\ "\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19"\ "\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21"\ ""] ::msgcat::mcset th BCE "\u0e25\u0e17\u0e35\u0e48" ::msgcat::mcset th CE "\u0e04.\u0e28." ::msgcat::mcset th AM "\u0e01\u0e48\u0e2d\u0e19\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07" ::msgcat::mcset th PM "\u0e2b\u0e25\u0e31\u0e07\u0e40\u0e17\u0e35\u0e48\u0e22\u0e07" ::msgcat::mcset th DATE_FORMAT "%e/%m/%Y" ::msgcat::mcset th TIME_FORMAT "%k:%M:%S" ::msgcat::mcset th DATE_TIME_FORMAT "%e/%m/%Y %k:%M:%S %z" } tcl8.6.5/library/msgs/es_pa.msg0000644000175000017500000000037311555560473016007 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_PA DATE_FORMAT "%m/%d/%Y" ::msgcat::mcset es_PA TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_PA DATE_TIME_FORMAT "%m/%d/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/ms.msg0000644000175000017500000000161611555560473015340 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ms DAYS_OF_WEEK_ABBREV [list \ "Aha"\ "Isn"\ "Sei"\ "Rab"\ "Kha"\ "Jum"\ "Sab"] ::msgcat::mcset ms DAYS_OF_WEEK_FULL [list \ "Ahad"\ "Isnin"\ "Selasa"\ "Rahu"\ "Khamis"\ "Jumaat"\ "Sabtu"] ::msgcat::mcset ms MONTHS_ABBREV [list \ "Jan"\ "Feb"\ "Mac"\ "Apr"\ "Mei"\ "Jun"\ "Jul"\ "Ogos"\ "Sep"\ "Okt"\ "Nov"\ "Dis"\ ""] ::msgcat::mcset ms MONTHS_FULL [list \ "Januari"\ "Februari"\ "Mac"\ "April"\ "Mei"\ "Jun"\ "Julai"\ "Ogos"\ "September"\ "Oktober"\ "November"\ "Disember"\ ""] } tcl8.6.5/library/msgs/ru.msg0000644000175000017500000000376711555560473015360 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ru DAYS_OF_WEEK_ABBREV [list \ "\u0412\u0441"\ "\u041f\u043d"\ "\u0412\u0442"\ "\u0421\u0440"\ "\u0427\u0442"\ "\u041f\u0442"\ "\u0421\u0431"] ::msgcat::mcset ru DAYS_OF_WEEK_FULL [list \ "\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435"\ "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a"\ "\u0432\u0442\u043e\u0440\u043d\u0438\u043a"\ "\u0441\u0440\u0435\u0434\u0430"\ "\u0447\u0435\u0442\u0432\u0435\u0440\u0433"\ "\u043f\u044f\u0442\u043d\u0438\u0446\u0430"\ "\u0441\u0443\u0431\u0431\u043e\u0442\u0430"] ::msgcat::mcset ru MONTHS_ABBREV [list \ "\u044f\u043d\u0432"\ "\u0444\u0435\u0432"\ "\u043c\u0430\u0440"\ "\u0430\u043f\u0440"\ "\u043c\u0430\u0439"\ "\u0438\u044e\u043d"\ "\u0438\u044e\u043b"\ "\u0430\u0432\u0433"\ "\u0441\u0435\u043d"\ "\u043e\u043a\u0442"\ "\u043d\u043e\u044f"\ "\u0434\u0435\u043a"\ ""] ::msgcat::mcset ru MONTHS_FULL [list \ "\u042f\u043d\u0432\u0430\u0440\u044c"\ "\u0424\u0435\u0432\u0440\u0430\u043b\u044c"\ "\u041c\u0430\u0440\u0442"\ "\u0410\u043f\u0440\u0435\u043b\u044c"\ "\u041c\u0430\u0439"\ "\u0418\u044e\u043d\u044c"\ "\u0418\u044e\u043b\u044c"\ "\u0410\u0432\u0433\u0443\u0441\u0442"\ "\u0421\u0435\u043d\u0442\u044f\u0431\u0440\u044c"\ "\u041e\u043a\u0442\u044f\u0431\u0440\u044c"\ "\u041d\u043e\u044f\u0431\u0440\u044c"\ "\u0414\u0435\u043a\u0430\u0431\u0440\u044c"\ ""] ::msgcat::mcset ru BCE "\u0434\u043e \u043d.\u044d." ::msgcat::mcset ru CE "\u043d.\u044d." ::msgcat::mcset ru DATE_FORMAT "%d.%m.%Y" ::msgcat::mcset ru TIME_FORMAT "%k:%M:%S" ::msgcat::mcset ru DATE_TIME_FORMAT "%d.%m.%Y %k:%M:%S %z" } tcl8.6.5/library/msgs/sv.msg0000644000175000017500000000221711555560473015347 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset sv DAYS_OF_WEEK_ABBREV [list \ "s\u00f6"\ "m\u00e5"\ "ti"\ "on"\ "to"\ "fr"\ "l\u00f6"] ::msgcat::mcset sv DAYS_OF_WEEK_FULL [list \ "s\u00f6ndag"\ "m\u00e5ndag"\ "tisdag"\ "onsdag"\ "torsdag"\ "fredag"\ "l\u00f6rdag"] ::msgcat::mcset sv MONTHS_ABBREV [list \ "jan"\ "feb"\ "mar"\ "apr"\ "maj"\ "jun"\ "jul"\ "aug"\ "sep"\ "okt"\ "nov"\ "dec"\ ""] ::msgcat::mcset sv MONTHS_FULL [list \ "januari"\ "februari"\ "mars"\ "april"\ "maj"\ "juni"\ "juli"\ "augusti"\ "september"\ "oktober"\ "november"\ "december"\ ""] ::msgcat::mcset sv BCE "f.Kr." ::msgcat::mcset sv CE "e.Kr." ::msgcat::mcset sv DATE_FORMAT "%Y-%m-%d" ::msgcat::mcset sv TIME_FORMAT "%H:%M:%S" ::msgcat::mcset sv DATE_TIME_FORMAT "%Y-%m-%d %H:%M:%S %z" } tcl8.6.5/library/msgs/en_gb.msg0000644000175000017500000000042711555560473015772 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_GB DATE_FORMAT "%d/%m/%y" ::msgcat::mcset en_GB TIME_FORMAT "%T" ::msgcat::mcset en_GB TIME_FORMAT_12 "%T" ::msgcat::mcset en_GB DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/hu.msg0000644000175000017500000000245711555560473015341 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset hu DAYS_OF_WEEK_ABBREV [list \ "V"\ "H"\ "K"\ "Sze"\ "Cs"\ "P"\ "Szo"] ::msgcat::mcset hu DAYS_OF_WEEK_FULL [list \ "vas\u00e1rnap"\ "h\u00e9tf\u0151"\ "kedd"\ "szerda"\ "cs\u00fct\u00f6rt\u00f6k"\ "p\u00e9ntek"\ "szombat"] ::msgcat::mcset hu MONTHS_ABBREV [list \ "jan."\ "febr."\ "m\u00e1rc."\ "\u00e1pr."\ "m\u00e1j."\ "j\u00fan."\ "j\u00fal."\ "aug."\ "szept."\ "okt."\ "nov."\ "dec."\ ""] ::msgcat::mcset hu MONTHS_FULL [list \ "janu\u00e1r"\ "febru\u00e1r"\ "m\u00e1rcius"\ "\u00e1prilis"\ "m\u00e1jus"\ "j\u00fanius"\ "j\u00falius"\ "augusztus"\ "szeptember"\ "okt\u00f3ber"\ "november"\ "december"\ ""] ::msgcat::mcset hu BCE "i.e." ::msgcat::mcset hu CE "i.u." ::msgcat::mcset hu AM "DE" ::msgcat::mcset hu PM "DU" ::msgcat::mcset hu DATE_FORMAT "%Y.%m.%d." ::msgcat::mcset hu TIME_FORMAT "%k:%M:%S" ::msgcat::mcset hu DATE_TIME_FORMAT "%Y.%m.%d. %k:%M:%S %z" } tcl8.6.5/library/msgs/pl.msg0000644000175000017500000000227311555560473015334 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset pl DAYS_OF_WEEK_ABBREV [list \ "N"\ "Pn"\ "Wt"\ "\u015ar"\ "Cz"\ "Pt"\ "So"] ::msgcat::mcset pl DAYS_OF_WEEK_FULL [list \ "niedziela"\ "poniedzia\u0142ek"\ "wtorek"\ "\u015broda"\ "czwartek"\ "pi\u0105tek"\ "sobota"] ::msgcat::mcset pl MONTHS_ABBREV [list \ "sty"\ "lut"\ "mar"\ "kwi"\ "maj"\ "cze"\ "lip"\ "sie"\ "wrz"\ "pa\u017a"\ "lis"\ "gru"\ ""] ::msgcat::mcset pl MONTHS_FULL [list \ "stycze\u0144"\ "luty"\ "marzec"\ "kwiecie\u0144"\ "maj"\ "czerwiec"\ "lipiec"\ "sierpie\u0144"\ "wrzesie\u0144"\ "pa\u017adziernik"\ "listopad"\ "grudzie\u0144"\ ""] ::msgcat::mcset pl BCE "p.n.e." ::msgcat::mcset pl CE "n.e." ::msgcat::mcset pl DATE_FORMAT "%Y-%m-%d" ::msgcat::mcset pl TIME_FORMAT "%H:%M:%S" ::msgcat::mcset pl DATE_TIME_FORMAT "%Y-%m-%d %H:%M:%S %z" } tcl8.6.5/library/msgs/kok.msg0000644000175000017500000000364611555560473015512 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset kok DAYS_OF_WEEK_FULL [list \ "\u0906\u0926\u093f\u0924\u094d\u092f\u0935\u093e\u0930"\ "\u0938\u094b\u092e\u0935\u093e\u0930"\ "\u092e\u0902\u0917\u0933\u093e\u0930"\ "\u092c\u0941\u0927\u0935\u093e\u0930"\ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930"\ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930"\ "\u0936\u0928\u093f\u0935\u093e\u0930"] ::msgcat::mcset kok MONTHS_ABBREV [list \ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940"\ "\u092b\u0947\u092c\u0943\u0935\u093e\u0930\u0940"\ "\u092e\u093e\u0930\u094d\u091a"\ "\u090f\u092a\u094d\u0930\u093f\u0932"\ "\u092e\u0947"\ "\u091c\u0942\u0928"\ "\u091c\u0941\u0932\u0948"\ "\u0913\u0917\u0938\u094d\u091f"\ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930"\ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930"\ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930"\ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"] ::msgcat::mcset kok MONTHS_FULL [list \ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940"\ "\u092b\u0947\u092c\u094d\u0930\u0941\u0935\u093e\u0930\u0940"\ "\u092e\u093e\u0930\u094d\u091a"\ "\u090f\u092a\u094d\u0930\u093f\u0932"\ "\u092e\u0947"\ "\u091c\u0942\u0928"\ "\u091c\u0941\u0932\u0948"\ "\u0913\u0917\u0938\u094d\u091f"\ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930"\ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930"\ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930"\ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"] ::msgcat::mcset kok AM "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u092a\u0942\u0930\u094d\u0935" ::msgcat::mcset kok PM "\u0915\u094d\u0930\u093f\u0938\u094d\u0924\u0936\u0916\u093e" } tcl8.6.5/library/msgs/fr_be.msg0000644000175000017500000000042711555560473015775 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset fr_BE DATE_FORMAT "%d/%m/%y" ::msgcat::mcset fr_BE TIME_FORMAT "%T" ::msgcat::mcset fr_BE TIME_FORMAT_12 "%T" ::msgcat::mcset fr_BE DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/en_bw.msg0000644000175000017500000000037311555560473016012 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_BW DATE_FORMAT "%d %B %Y" ::msgcat::mcset en_BW TIME_FORMAT_12 "%l:%M:%S %P" ::msgcat::mcset en_BW DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z" } tcl8.6.5/library/msgs/fa.msg0000644000175000017500000000320011555560473015276 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset fa DAYS_OF_WEEK_ABBREV [list \ "\u06cc\u2214"\ "\u062f\u2214"\ "\u0633\u2214"\ "\u0686\u2214"\ "\u067e\u2214"\ "\u062c\u2214"\ "\u0634\u2214"] ::msgcat::mcset fa DAYS_OF_WEEK_FULL [list \ "\u06cc\u06cc\u200c\u0634\u0646\u0628\u0647"\ "\u062f\u0648\u0634\u0646\u0628\u0647"\ "\u0633\u0647\u200c\u0634\u0646\u0628\u0647"\ "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647"\ "\u067e\u0646\u062c\u200c\u0634\u0646\u0628\u0647"\ "\u062c\u0645\u0639\u0647"\ "\u0634\u0646\u0628\u0647"] ::msgcat::mcset fa MONTHS_ABBREV [list \ "\u0698\u0627\u0646"\ "\u0641\u0648\u0631"\ "\u0645\u0627\u0631"\ "\u0622\u0648\u0631"\ "\u0645\u0640\u0647"\ "\u0698\u0648\u0646"\ "\u0698\u0648\u06cc"\ "\u0627\u0648\u062a"\ "\u0633\u067e\u062a"\ "\u0627\u0643\u062a"\ "\u0646\u0648\u0627"\ "\u062f\u0633\u0627"\ ""] ::msgcat::mcset fa MONTHS_FULL [list \ "\u0698\u0627\u0646\u0648\u06cc\u0647"\ "\u0641\u0648\u0631\u0648\u06cc\u0647"\ "\u0645\u0627\u0631\u0633"\ "\u0622\u0648\u0631\u06cc\u0644"\ "\u0645\u0647"\ "\u0698\u0648\u0626\u0646"\ "\u0698\u0648\u0626\u06cc\u0647"\ "\u0627\u0648\u062a"\ "\u0633\u067e\u062a\u0627\u0645\u0628\u0631"\ "\u0627\u0643\u062a\u0628\u0631"\ "\u0646\u0648\u0627\u0645\u0628\u0631"\ "\u062f\u0633\u0627\u0645\u0628\u0631"\ ""] } tcl8.6.5/library/msgs/es_ve.msg0000644000175000017500000000037311555560473016021 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_VE DATE_FORMAT "%d/%m/%Y" ::msgcat::mcset es_VE TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_VE DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/ms_my.msg0000644000175000017500000000040311555560473016036 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ms_MY DATE_FORMAT "%A %d %b %Y" ::msgcat::mcset ms_MY TIME_FORMAT_12 "%I:%M:%S %z" ::msgcat::mcset ms_MY DATE_TIME_FORMAT "%A %d %b %Y %I:%M:%S %z %z" } tcl8.6.5/library/msgs/da.msg0000644000175000017500000000220411555560473015277 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset da DAYS_OF_WEEK_ABBREV [list \ "s\u00f8"\ "ma"\ "ti"\ "on"\ "to"\ "fr"\ "l\u00f8"] ::msgcat::mcset da DAYS_OF_WEEK_FULL [list \ "s\u00f8ndag"\ "mandag"\ "tirsdag"\ "onsdag"\ "torsdag"\ "fredag"\ "l\u00f8rdag"] ::msgcat::mcset da MONTHS_ABBREV [list \ "jan"\ "feb"\ "mar"\ "apr"\ "maj"\ "jun"\ "jul"\ "aug"\ "sep"\ "okt"\ "nov"\ "dec"\ ""] ::msgcat::mcset da MONTHS_FULL [list \ "januar"\ "februar"\ "marts"\ "april"\ "maj"\ "juni"\ "juli"\ "august"\ "september"\ "oktober"\ "november"\ "december"\ ""] ::msgcat::mcset da BCE "f.Kr." ::msgcat::mcset da CE "e.Kr." ::msgcat::mcset da DATE_FORMAT "%d-%m-%Y" ::msgcat::mcset da TIME_FORMAT "%H:%M:%S" ::msgcat::mcset da DATE_TIME_FORMAT "%d-%m-%Y %H:%M:%S %z" } tcl8.6.5/library/msgs/zh_hk.msg0000644000175000017500000000136011555560473016020 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset zh_HK DAYS_OF_WEEK_ABBREV [list \ "\u65e5"\ "\u4e00"\ "\u4e8c"\ "\u4e09"\ "\u56db"\ "\u4e94"\ "\u516d"] ::msgcat::mcset zh_HK MONTHS_ABBREV [list \ "1\u6708"\ "2\u6708"\ "3\u6708"\ "4\u6708"\ "5\u6708"\ "6\u6708"\ "7\u6708"\ "8\u6708"\ "9\u6708"\ "10\u6708"\ "11\u6708"\ "12\u6708"\ ""] ::msgcat::mcset zh_HK DATE_FORMAT "%Y\u5e74%m\u6708%e\u65e5" ::msgcat::mcset zh_HK TIME_FORMAT_12 "%P%I:%M:%S" ::msgcat::mcset zh_HK DATE_TIME_FORMAT "%Y\u5e74%m\u6708%e\u65e5 %P%I:%M:%S %z" } tcl8.6.5/library/msgs/zh_tw.msg0000644000175000017500000000053211555560473016050 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset zh_TW BCE "\u6c11\u570b\u524d" ::msgcat::mcset zh_TW CE "\u6c11\u570b" ::msgcat::mcset zh_TW DATE_FORMAT "%Y/%m/%e" ::msgcat::mcset zh_TW TIME_FORMAT_12 "%P %I:%M:%S" ::msgcat::mcset zh_TW DATE_TIME_FORMAT "%Y/%m/%e %P %I:%M:%S %z" } tcl8.6.5/library/msgs/kw.msg0000644000175000017500000000170611555560473015342 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset kw DAYS_OF_WEEK_ABBREV [list \ "Sul"\ "Lun"\ "Mth"\ "Mhr"\ "Yow"\ "Gwe"\ "Sad"] ::msgcat::mcset kw DAYS_OF_WEEK_FULL [list \ "De Sul"\ "De Lun"\ "De Merth"\ "De Merher"\ "De Yow"\ "De Gwener"\ "De Sadorn"] ::msgcat::mcset kw MONTHS_ABBREV [list \ "Gen"\ "Whe"\ "Mer"\ "Ebr"\ "Me"\ "Evn"\ "Gor"\ "Est"\ "Gwn"\ "Hed"\ "Du"\ "Kev"\ ""] ::msgcat::mcset kw MONTHS_FULL [list \ "Mys Genver"\ "Mys Whevrel"\ "Mys Merth"\ "Mys Ebrel"\ "Mys Me"\ "Mys Evan"\ "Mys Gortheren"\ "Mye Est"\ "Mys Gwyngala"\ "Mys Hedra"\ "Mys Du"\ "Mys Kevardhu"\ ""] } tcl8.6.5/library/msgs/ro.msg0000644000175000017500000000222411555560473015335 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ro DAYS_OF_WEEK_ABBREV [list \ "D"\ "L"\ "Ma"\ "Mi"\ "J"\ "V"\ "S"] ::msgcat::mcset ro DAYS_OF_WEEK_FULL [list \ "duminic\u0103"\ "luni"\ "mar\u0163i"\ "miercuri"\ "joi"\ "vineri"\ "s\u00eemb\u0103t\u0103"] ::msgcat::mcset ro MONTHS_ABBREV [list \ "Ian"\ "Feb"\ "Mar"\ "Apr"\ "Mai"\ "Iun"\ "Iul"\ "Aug"\ "Sep"\ "Oct"\ "Nov"\ "Dec"\ ""] ::msgcat::mcset ro MONTHS_FULL [list \ "ianuarie"\ "februarie"\ "martie"\ "aprilie"\ "mai"\ "iunie"\ "iulie"\ "august"\ "septembrie"\ "octombrie"\ "noiembrie"\ "decembrie"\ ""] ::msgcat::mcset ro BCE "d.C." ::msgcat::mcset ro CE "\u00ee.d.C." ::msgcat::mcset ro DATE_FORMAT "%d.%m.%Y" ::msgcat::mcset ro TIME_FORMAT "%H:%M:%S" ::msgcat::mcset ro DATE_TIME_FORMAT "%d.%m.%Y %H:%M:%S %z" } tcl8.6.5/library/msgs/ar_sy.msg0000644000175000017500000000342411555560473016035 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ar_SY DAYS_OF_WEEK_ABBREV [list \ "\u0627\u0644\u0623\u062d\u062f"\ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646"\ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621"\ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621"\ "\u0627\u0644\u062e\u0645\u064a\u0633"\ "\u0627\u0644\u062c\u0645\u0639\u0629"\ "\u0627\u0644\u0633\u0628\u062a"] ::msgcat::mcset ar_SY MONTHS_ABBREV [list \ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0634\u0628\u0627\u0637"\ "\u0622\u0630\u0627\u0631"\ "\u0646\u064a\u0633\u0627\u0646"\ "\u0646\u0648\u0627\u0631"\ "\u062d\u0632\u064a\u0631\u0627\u0646"\ "\u062a\u0645\u0648\u0632"\ "\u0622\u0628"\ "\u0623\u064a\u0644\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\ ""] ::msgcat::mcset ar_SY MONTHS_FULL [list \ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0634\u0628\u0627\u0637"\ "\u0622\u0630\u0627\u0631"\ "\u0646\u064a\u0633\u0627\u0646"\ "\u0646\u0648\u0627\u0631\u0627\u0646"\ "\u062d\u0632\u064a\u0631"\ "\u062a\u0645\u0648\u0632"\ "\u0622\u0628"\ "\u0623\u064a\u0644\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\ ""] } tcl8.6.5/library/msgs/bg.msg0000644000175000017500000000343311555560473015310 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset bg DAYS_OF_WEEK_ABBREV [list \ "\u041d\u0434"\ "\u041f\u043d"\ "\u0412\u0442"\ "\u0421\u0440"\ "\u0427\u0442"\ "\u041f\u0442"\ "\u0421\u0431"] ::msgcat::mcset bg DAYS_OF_WEEK_FULL [list \ "\u041d\u0435\u0434\u0435\u043b\u044f"\ "\u041f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a"\ "\u0412\u0442\u043e\u0440\u043d\u0438\u043a"\ "\u0421\u0440\u044f\u0434\u0430"\ "\u0427\u0435\u0442\u0432\u044a\u0440\u0442\u044a\u043a"\ "\u041f\u0435\u0442\u044a\u043a"\ "\u0421\u044a\u0431\u043e\u0442\u0430"] ::msgcat::mcset bg MONTHS_ABBREV [list \ "I"\ "II"\ "III"\ "IV"\ "V"\ "VI"\ "VII"\ "VIII"\ "IX"\ "X"\ "XI"\ "XII"\ ""] ::msgcat::mcset bg MONTHS_FULL [list \ "\u042f\u043d\u0443\u0430\u0440\u0438"\ "\u0424\u0435\u0432\u0440\u0443\u0430\u0440\u0438"\ "\u041c\u0430\u0440\u0442"\ "\u0410\u043f\u0440\u0438\u043b"\ "\u041c\u0430\u0439"\ "\u042e\u043d\u0438"\ "\u042e\u043b\u0438"\ "\u0410\u0432\u0433\u0443\u0441\u0442"\ "\u0421\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438"\ "\u041e\u043a\u0442\u043e\u043c\u0432\u0440\u0438"\ "\u041d\u043e\u0435\u043c\u0432\u0440\u0438"\ "\u0414\u0435\u043a\u0435\u043c\u0432\u0440\u0438"\ ""] ::msgcat::mcset bg BCE "\u043f\u0440.\u043d.\u0435." ::msgcat::mcset bg CE "\u043d.\u0435." ::msgcat::mcset bg DATE_FORMAT "%Y-%m-%e" ::msgcat::mcset bg TIME_FORMAT "%k:%M:%S" ::msgcat::mcset bg DATE_TIME_FORMAT "%Y-%m-%e %k:%M:%S %z" } tcl8.6.5/library/msgs/es_py.msg0000644000175000017500000000037311555560473016037 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_PY DATE_FORMAT "%d/%m/%Y" ::msgcat::mcset es_PY TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_PY DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/ca.msg0000644000175000017500000000211611555560473015300 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ca DAYS_OF_WEEK_ABBREV [list \ "dg."\ "dl."\ "dt."\ "dc."\ "dj."\ "dv."\ "ds."] ::msgcat::mcset ca DAYS_OF_WEEK_FULL [list \ "diumenge"\ "dilluns"\ "dimarts"\ "dimecres"\ "dijous"\ "divendres"\ "dissabte"] ::msgcat::mcset ca MONTHS_ABBREV [list \ "gen."\ "feb."\ "mar\u00e7"\ "abr."\ "maig"\ "juny"\ "jul."\ "ag."\ "set."\ "oct."\ "nov."\ "des."\ ""] ::msgcat::mcset ca MONTHS_FULL [list \ "gener"\ "febrer"\ "mar\u00e7"\ "abril"\ "maig"\ "juny"\ "juliol"\ "agost"\ "setembre"\ "octubre"\ "novembre"\ "desembre"\ ""] ::msgcat::mcset ca DATE_FORMAT "%d/%m/%Y" ::msgcat::mcset ca TIME_FORMAT "%H:%M:%S" ::msgcat::mcset ca DATE_TIME_FORMAT "%d/%m/%Y %H:%M:%S %z" } tcl8.6.5/library/msgs/en_nz.msg0000644000175000017500000000045411555560473016031 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_NZ DATE_FORMAT "%e/%m/%Y" ::msgcat::mcset en_NZ TIME_FORMAT "%H:%M:%S" ::msgcat::mcset en_NZ TIME_FORMAT_12 "%I:%M:%S %P %z" ::msgcat::mcset en_NZ DATE_TIME_FORMAT "%e/%m/%Y %H:%M:%S %z" } tcl8.6.5/library/msgs/es_ar.msg0000644000175000017500000000036211555560473016007 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_AR DATE_FORMAT "%d/%m/%Y" ::msgcat::mcset es_AR TIME_FORMAT "%H:%M:%S" ::msgcat::mcset es_AR DATE_TIME_FORMAT "%d/%m/%Y %H:%M:%S %z" } tcl8.6.5/library/msgs/es_hn.msg0000644000175000017500000000037311555560473016014 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_HN DATE_FORMAT "%m-%d-%Y" ::msgcat::mcset es_HN TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_HN DATE_TIME_FORMAT "%m-%d-%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/nn.msg0000644000175000017500000000217411555560473015334 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset nn DAYS_OF_WEEK_ABBREV [list \ "su"\ "m\u00e5"\ "ty"\ "on"\ "to"\ "fr"\ "lau"] ::msgcat::mcset nn DAYS_OF_WEEK_FULL [list \ "sundag"\ "m\u00e5ndag"\ "tysdag"\ "onsdag"\ "torsdag"\ "fredag"\ "laurdag"] ::msgcat::mcset nn MONTHS_ABBREV [list \ "jan"\ "feb"\ "mar"\ "apr"\ "mai"\ "jun"\ "jul"\ "aug"\ "sep"\ "okt"\ "nov"\ "des"\ ""] ::msgcat::mcset nn MONTHS_FULL [list \ "januar"\ "februar"\ "mars"\ "april"\ "mai"\ "juni"\ "juli"\ "august"\ "september"\ "oktober"\ "november"\ "desember"\ ""] ::msgcat::mcset nn BCE "f.Kr." ::msgcat::mcset nn CE "e.Kr." ::msgcat::mcset nn DATE_FORMAT "%e. %B %Y" ::msgcat::mcset nn TIME_FORMAT "%H:%M:%S" ::msgcat::mcset nn DATE_TIME_FORMAT "%e. %B %Y %H:%M:%S %z" } tcl8.6.5/library/msgs/en_hk.msg0000644000175000017500000000050111555560473015775 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_HK AM "AM" ::msgcat::mcset en_HK PM "PM" ::msgcat::mcset en_HK DATE_FORMAT "%B %e, %Y" ::msgcat::mcset en_HK TIME_FORMAT_12 "%l:%M:%S %P" ::msgcat::mcset en_HK DATE_TIME_FORMAT "%B %e, %Y %l:%M:%S %P %z" } tcl8.6.5/library/msgs/en_za.msg0000644000175000017500000000036511555560473016015 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_ZA DATE_FORMAT "%Y/%m/%d" ::msgcat::mcset en_ZA TIME_FORMAT_12 "%I:%M:%S" ::msgcat::mcset en_ZA DATE_TIME_FORMAT "%Y/%m/%d %I:%M:%S %z" } tcl8.6.5/library/msgs/el.msg0000644000175000017500000000431411555560473015317 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset el DAYS_OF_WEEK_ABBREV [list \ "\u039a\u03c5\u03c1"\ "\u0394\u03b5\u03c5"\ "\u03a4\u03c1\u03b9"\ "\u03a4\u03b5\u03c4"\ "\u03a0\u03b5\u03bc"\ "\u03a0\u03b1\u03c1"\ "\u03a3\u03b1\u03b2"] ::msgcat::mcset el DAYS_OF_WEEK_FULL [list \ "\u039a\u03c5\u03c1\u03b9\u03b1\u03ba\u03ae"\ "\u0394\u03b5\u03c5\u03c4\u03ad\u03c1\u03b1"\ "\u03a4\u03c1\u03af\u03c4\u03b7"\ "\u03a4\u03b5\u03c4\u03ac\u03c1\u03c4\u03b7"\ "\u03a0\u03ad\u03bc\u03c0\u03c4\u03b7"\ "\u03a0\u03b1\u03c1\u03b1\u03c3\u03ba\u03b5\u03c5\u03ae"\ "\u03a3\u03ac\u03b2\u03b2\u03b1\u03c4\u03bf"] ::msgcat::mcset el MONTHS_ABBREV [list \ "\u0399\u03b1\u03bd"\ "\u03a6\u03b5\u03b2"\ "\u039c\u03b1\u03c1"\ "\u0391\u03c0\u03c1"\ "\u039c\u03b1\u03ca"\ "\u0399\u03bf\u03c5\u03bd"\ "\u0399\u03bf\u03c5\u03bb"\ "\u0391\u03c5\u03b3"\ "\u03a3\u03b5\u03c0"\ "\u039f\u03ba\u03c4"\ "\u039d\u03bf\u03b5"\ "\u0394\u03b5\u03ba"\ ""] ::msgcat::mcset el MONTHS_FULL [list \ "\u0399\u03b1\u03bd\u03bf\u03c5\u03ac\u03c1\u03b9\u03bf\u03c2"\ "\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03ac\u03c1\u03b9\u03bf\u03c2"\ "\u039c\u03ac\u03c1\u03c4\u03b9\u03bf\u03c2"\ "\u0391\u03c0\u03c1\u03af\u03bb\u03b9\u03bf\u03c2"\ "\u039c\u03ac\u03ca\u03bf\u03c2"\ "\u0399\u03bf\u03cd\u03bd\u03b9\u03bf\u03c2"\ "\u0399\u03bf\u03cd\u03bb\u03b9\u03bf\u03c2"\ "\u0391\u03cd\u03b3\u03bf\u03c5\u03c3\u03c4\u03bf\u03c2"\ "\u03a3\u03b5\u03c0\u03c4\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2"\ "\u039f\u03ba\u03c4\u03ce\u03b2\u03c1\u03b9\u03bf\u03c2"\ "\u039d\u03bf\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2"\ "\u0394\u03b5\u03ba\u03ad\u03bc\u03b2\u03c1\u03b9\u03bf\u03c2"\ ""] ::msgcat::mcset el AM "\u03c0\u03bc" ::msgcat::mcset el PM "\u03bc\u03bc" ::msgcat::mcset el DATE_FORMAT "%e/%m/%Y" ::msgcat::mcset el TIME_FORMAT_12 "%l:%M:%S %P" ::msgcat::mcset el DATE_TIME_FORMAT "%e/%m/%Y %l:%M:%S %P %z" } tcl8.6.5/library/msgs/en_in.msg0000644000175000017500000000046611555560473016013 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_IN AM "AM" ::msgcat::mcset en_IN PM "PM" ::msgcat::mcset en_IN DATE_FORMAT "%d %B %Y" ::msgcat::mcset en_IN TIME_FORMAT "%H:%M:%S" ::msgcat::mcset en_IN DATE_TIME_FORMAT "%d %B %Y %H:%M:%S %z" } tcl8.6.5/library/msgs/nl_be.msg0000644000175000017500000000042711555560473015777 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset nl_BE DATE_FORMAT "%d-%m-%y" ::msgcat::mcset nl_BE TIME_FORMAT "%T" ::msgcat::mcset nl_BE TIME_FORMAT_12 "%T" ::msgcat::mcset nl_BE DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/ar.msg0000644000175000017500000000365411555560473015327 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ar DAYS_OF_WEEK_ABBREV [list \ "\u062d"\ "\u0646"\ "\u062b"\ "\u0631"\ "\u062e"\ "\u062c"\ "\u0633"] ::msgcat::mcset ar DAYS_OF_WEEK_FULL [list \ "\u0627\u0644\u0623\u062d\u062f"\ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646"\ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621"\ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621"\ "\u0627\u0644\u062e\u0645\u064a\u0633"\ "\u0627\u0644\u062c\u0645\u0639\u0629"\ "\u0627\u0644\u0633\u0628\u062a"] ::msgcat::mcset ar MONTHS_ABBREV [list \ "\u064a\u0646\u0627"\ "\u0641\u0628\u0631"\ "\u0645\u0627\u0631"\ "\u0623\u0628\u0631"\ "\u0645\u0627\u064a"\ "\u064a\u0648\u0646"\ "\u064a\u0648\u0644"\ "\u0623\u063a\u0633"\ "\u0633\u0628\u062a"\ "\u0623\u0643\u062a"\ "\u0646\u0648\u0641"\ "\u062f\u064a\u0633"\ ""] ::msgcat::mcset ar MONTHS_FULL [list \ "\u064a\u0646\u0627\u064a\u0631"\ "\u0641\u0628\u0631\u0627\u064a\u0631"\ "\u0645\u0627\u0631\u0633"\ "\u0623\u0628\u0631\u064a\u0644"\ "\u0645\u0627\u064a\u0648"\ "\u064a\u0648\u0646\u064a\u0648"\ "\u064a\u0648\u0644\u064a\u0648"\ "\u0623\u063a\u0633\u0637\u0633"\ "\u0633\u0628\u062a\u0645\u0628\u0631"\ "\u0623\u0643\u062a\u0648\u0628\u0631"\ "\u0646\u0648\u0641\u0645\u0628\u0631"\ "\u062f\u064a\u0633\u0645\u0628\u0631"\ ""] ::msgcat::mcset ar BCE "\u0642.\u0645" ::msgcat::mcset ar CE "\u0645" ::msgcat::mcset ar AM "\u0635" ::msgcat::mcset ar PM "\u0645" ::msgcat::mcset ar DATE_FORMAT "%d/%m/%Y" ::msgcat::mcset ar TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset ar DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/es_cr.msg0000644000175000017500000000037311555560473016013 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_CR DATE_FORMAT "%d/%m/%Y" ::msgcat::mcset es_CR TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_CR DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/es_co.msg0000644000175000017500000000037311555560473016010 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_CO DATE_FORMAT "%e/%m/%Y" ::msgcat::mcset es_CO TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_CO DATE_TIME_FORMAT "%e/%m/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/be.msg0000644000175000017500000000407111555560473015305 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset be DAYS_OF_WEEK_ABBREV [list \ "\u043d\u0434"\ "\u043f\u043d"\ "\u0430\u0442"\ "\u0441\u0440"\ "\u0447\u0446"\ "\u043f\u0442"\ "\u0441\u0431"] ::msgcat::mcset be DAYS_OF_WEEK_FULL [list \ "\u043d\u044f\u0434\u0437\u0435\u043b\u044f"\ "\u043f\u0430\u043d\u044f\u0434\u0437\u0435\u043b\u0430\u043a"\ "\u0430\u045e\u0442\u043e\u0440\u0430\u043a"\ "\u0441\u0435\u0440\u0430\u0434\u0430"\ "\u0447\u0430\u0446\u0432\u0435\u0440"\ "\u043f\u044f\u0442\u043d\u0456\u0446\u0430"\ "\u0441\u0443\u0431\u043e\u0442\u0430"] ::msgcat::mcset be MONTHS_ABBREV [list \ "\u0441\u0442\u0434"\ "\u043b\u044e\u0442"\ "\u0441\u043a\u0432"\ "\u043a\u0440\u0441"\ "\u043c\u0430\u0439"\ "\u0447\u0440\u0432"\ "\u043b\u043f\u043d"\ "\u0436\u043d\u0432"\ "\u0432\u0440\u0441"\ "\u043a\u0441\u0442"\ "\u043b\u0441\u0442"\ "\u0441\u043d\u0436"\ ""] ::msgcat::mcset be MONTHS_FULL [list \ "\u0441\u0442\u0443\u0434\u0437\u0435\u043d\u044f"\ "\u043b\u044e\u0442\u0430\u0433\u0430"\ "\u0441\u0430\u043a\u0430\u0432\u0456\u043a\u0430"\ "\u043a\u0440\u0430\u0441\u0430\u0432\u0456\u043a\u0430"\ "\u043c\u0430\u044f"\ "\u0447\u0440\u0432\u0435\u043d\u044f"\ "\u043b\u0456\u043f\u0435\u043d\u044f"\ "\u0436\u043d\u0456\u045e\u043d\u044f"\ "\u0432\u0435\u0440\u0430\u0441\u043d\u044f"\ "\u043a\u0430\u0441\u0442\u0440\u044b\u0447\u043d\u0456\u043a\u0430"\ "\u043b\u0438\u0441\u0442\u0430\u043f\u0430\u0434\u0430"\ "\u0441\u043d\u0435\u0436\u043d\u044f"\ ""] ::msgcat::mcset be BCE "\u0434\u0430 \u043d.\u0435." ::msgcat::mcset be CE "\u043d.\u0435." ::msgcat::mcset be DATE_FORMAT "%e.%m.%Y" ::msgcat::mcset be TIME_FORMAT "%k.%M.%S" ::msgcat::mcset be DATE_TIME_FORMAT "%e.%m.%Y %k.%M.%S %z" } tcl8.6.5/library/msgs/es_ni.msg0000644000175000017500000000037311555560473016015 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_NI DATE_FORMAT "%m-%d-%Y" ::msgcat::mcset es_NI TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_NI DATE_TIME_FORMAT "%m-%d-%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/is.msg0000644000175000017500000000234711555560473015336 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset is DAYS_OF_WEEK_ABBREV [list \ "sun."\ "m\u00e1n."\ "\u00feri."\ "mi\u00f0."\ "fim."\ "f\u00f6s."\ "lau."] ::msgcat::mcset is DAYS_OF_WEEK_FULL [list \ "sunnudagur"\ "m\u00e1nudagur"\ "\u00feri\u00f0judagur"\ "mi\u00f0vikudagur"\ "fimmtudagur"\ "f\u00f6studagur"\ "laugardagur"] ::msgcat::mcset is MONTHS_ABBREV [list \ "jan."\ "feb."\ "mar."\ "apr."\ "ma\u00ed"\ "j\u00fan."\ "j\u00fal."\ "\u00e1g\u00fa."\ "sep."\ "okt."\ "n\u00f3v."\ "des."\ ""] ::msgcat::mcset is MONTHS_FULL [list \ "jan\u00faar"\ "febr\u00faar"\ "mars"\ "apr\u00edl"\ "ma\u00ed"\ "j\u00fan\u00ed"\ "j\u00fal\u00ed"\ "\u00e1g\u00fast"\ "september"\ "okt\u00f3ber"\ "n\u00f3vember"\ "desember"\ ""] ::msgcat::mcset is DATE_FORMAT "%e.%m.%Y" ::msgcat::mcset is TIME_FORMAT "%H:%M:%S" ::msgcat::mcset is DATE_TIME_FORMAT "%e.%m.%Y %H:%M:%S %z" } tcl8.6.5/library/msgs/zh_sg.msg0000644000175000017500000000052311555560473016027 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset zh_SG AM "\u4e0a\u5348" ::msgcat::mcset zh_SG PM "\u4e2d\u5348" ::msgcat::mcset zh_SG DATE_FORMAT "%d %B %Y" ::msgcat::mcset zh_SG TIME_FORMAT_12 "%P %I:%M:%S" ::msgcat::mcset zh_SG DATE_TIME_FORMAT "%d %B %Y %P %I:%M:%S %z" } tcl8.6.5/library/msgs/it_ch.msg0000644000175000017500000000036411555560473016006 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset it_CH DATE_FORMAT "%e. %B %Y" ::msgcat::mcset it_CH TIME_FORMAT "%H:%M:%S" ::msgcat::mcset it_CH DATE_TIME_FORMAT "%e. %B %Y %H:%M:%S %z" } tcl8.6.5/library/msgs/en_ie.msg0000644000175000017500000000042711555560473015777 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_IE DATE_FORMAT "%d/%m/%y" ::msgcat::mcset en_IE TIME_FORMAT "%T" ::msgcat::mcset en_IE TIME_FORMAT_12 "%T" ::msgcat::mcset en_IE DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/ar_in.msg0000644000175000017500000000040311555560473016002 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ar_IN DATE_FORMAT "%A %d %B %Y" ::msgcat::mcset ar_IN TIME_FORMAT_12 "%I:%M:%S %z" ::msgcat::mcset ar_IN DATE_TIME_FORMAT "%A %d %B %Y %I:%M:%S %z %z" } tcl8.6.5/library/msgs/es_cl.msg0000644000175000017500000000037311555560473016005 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_CL DATE_FORMAT "%d-%m-%Y" ::msgcat::mcset es_CL TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_CL DATE_TIME_FORMAT "%d-%m-%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/fa_ir.msg0000644000175000017500000000064111555560473015776 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset fa_IR AM "\u0635\u0628\u062d" ::msgcat::mcset fa_IR PM "\u0639\u0635\u0631" ::msgcat::mcset fa_IR DATE_FORMAT "%d\u2044%m\u2044%Y" ::msgcat::mcset fa_IR TIME_FORMAT "%S:%M:%H" ::msgcat::mcset fa_IR TIME_FORMAT_12 "%S:%M:%l %P" ::msgcat::mcset fa_IR DATE_TIME_FORMAT "%d\u2044%m\u2044%Y %S:%M:%H %z" } tcl8.6.5/library/msgs/gl.msg0000644000175000017500000000166611555560473015330 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset gl DAYS_OF_WEEK_ABBREV [list \ "Dom"\ "Lun"\ "Mar"\ "M\u00e9r"\ "Xov"\ "Ven"\ "S\u00e1b"] ::msgcat::mcset gl DAYS_OF_WEEK_FULL [list \ "Domingo"\ "Luns"\ "Martes"\ "M\u00e9rcores"\ "Xoves"\ "Venres"\ "S\u00e1bado"] ::msgcat::mcset gl MONTHS_ABBREV [list \ "Xan"\ "Feb"\ "Mar"\ "Abr"\ "Mai"\ "Xu\u00f1"\ "Xul"\ "Ago"\ "Set"\ "Out"\ "Nov"\ "Dec"\ ""] ::msgcat::mcset gl MONTHS_FULL [list \ "Xaneiro"\ "Febreiro"\ "Marzo"\ "Abril"\ "Maio"\ "Xu\u00f1o"\ "Xullo"\ "Agosto"\ "Setembro"\ "Outubro"\ "Novembro"\ "Decembro"\ ""] } tcl8.6.5/library/msgs/hi.msg0000644000175000017500000000331211555560473015314 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset hi DAYS_OF_WEEK_FULL [list \ "\u0930\u0935\u093f\u0935\u093e\u0930"\ "\u0938\u094b\u092e\u0935\u093e\u0930"\ "\u092e\u0902\u0917\u0932\u0935\u093e\u0930"\ "\u092c\u0941\u0927\u0935\u093e\u0930"\ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930"\ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930"\ "\u0936\u0928\u093f\u0935\u093e\u0930"] ::msgcat::mcset hi MONTHS_ABBREV [list \ "\u091c\u0928\u0935\u0930\u0940"\ "\u092b\u093c\u0930\u0935\u0930\u0940"\ "\u092e\u093e\u0930\u094d\u091a"\ "\u0905\u092a\u094d\u0930\u0947\u0932"\ "\u092e\u0908"\ "\u091c\u0942\u0928"\ "\u091c\u0941\u0932\u093e\u0908"\ "\u0905\u0917\u0938\u094d\u0924"\ "\u0938\u093f\u0924\u092e\u094d\u092c\u0930"\ "\u0905\u0915\u094d\u091f\u0942\u092c\u0930"\ "\u0928\u0935\u092e\u094d\u092c\u0930"\ "\u0926\u093f\u0938\u092e\u094d\u092c\u0930"] ::msgcat::mcset hi MONTHS_FULL [list \ "\u091c\u0928\u0935\u0930\u0940"\ "\u092b\u093c\u0930\u0935\u0930\u0940"\ "\u092e\u093e\u0930\u094d\u091a"\ "\u0905\u092a\u094d\u0930\u0947\u0932"\ "\u092e\u0908"\ "\u091c\u0942\u0928"\ "\u091c\u0941\u0932\u093e\u0908"\ "\u0905\u0917\u0938\u094d\u0924"\ "\u0938\u093f\u0924\u092e\u094d\u092c\u0930"\ "\u0905\u0915\u094d\u091f\u0942\u092c\u0930"\ "\u0928\u0935\u092e\u094d\u092c\u0930"\ "\u0926\u093f\u0938\u092e\u094d\u092c\u0930"] ::msgcat::mcset hi AM "\u0908\u0938\u093e\u092a\u0942\u0930\u094d\u0935" ::msgcat::mcset hi PM "." } tcl8.6.5/library/msgs/sl.msg0000644000175000017500000000221411555560473015332 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset sl DAYS_OF_WEEK_ABBREV [list \ "Ned"\ "Pon"\ "Tor"\ "Sre"\ "\u010cet"\ "Pet"\ "Sob"] ::msgcat::mcset sl DAYS_OF_WEEK_FULL [list \ "Nedelja"\ "Ponedeljek"\ "Torek"\ "Sreda"\ "\u010cetrtek"\ "Petek"\ "Sobota"] ::msgcat::mcset sl MONTHS_ABBREV [list \ "jan"\ "feb"\ "mar"\ "apr"\ "maj"\ "jun"\ "jul"\ "avg"\ "sep"\ "okt"\ "nov"\ "dec"\ ""] ::msgcat::mcset sl MONTHS_FULL [list \ "januar"\ "februar"\ "marec"\ "april"\ "maj"\ "junij"\ "julij"\ "avgust"\ "september"\ "oktober"\ "november"\ "december"\ ""] ::msgcat::mcset sl BCE "pr.n.\u0161." ::msgcat::mcset sl CE "po Kr." ::msgcat::mcset sl DATE_FORMAT "%Y.%m.%e" ::msgcat::mcset sl TIME_FORMAT "%k:%M:%S" ::msgcat::mcset sl DATE_TIME_FORMAT "%Y.%m.%e %k:%M:%S %z" } tcl8.6.5/library/msgs/ru_ua.msg0000644000175000017500000000036211555560473016031 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ru_UA DATE_FORMAT "%d.%m.%Y" ::msgcat::mcset ru_UA TIME_FORMAT "%k:%M:%S" ::msgcat::mcset ru_UA DATE_TIME_FORMAT "%d.%m.%Y %k:%M:%S %z" } tcl8.6.5/library/msgs/bn_in.msg0000644000175000017500000000040311555560473015777 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset bn_IN DATE_FORMAT "%A %d %b %Y" ::msgcat::mcset bn_IN TIME_FORMAT_12 "%I:%M:%S %z" ::msgcat::mcset bn_IN DATE_TIME_FORMAT "%A %d %b %Y %I:%M:%S %z %z" } tcl8.6.5/library/msgs/fo.msg0000644000175000017500000000173211555560473015324 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset fo DAYS_OF_WEEK_ABBREV [list \ "sun"\ "m\u00e1n"\ "t\u00fds"\ "mik"\ "h\u00f3s"\ "fr\u00ed"\ "ley"] ::msgcat::mcset fo DAYS_OF_WEEK_FULL [list \ "sunnudagur"\ "m\u00e1nadagur"\ "t\u00fdsdagur"\ "mikudagur"\ "h\u00f3sdagur"\ "fr\u00edggjadagur"\ "leygardagur"] ::msgcat::mcset fo MONTHS_ABBREV [list \ "jan"\ "feb"\ "mar"\ "apr"\ "mai"\ "jun"\ "jul"\ "aug"\ "sep"\ "okt"\ "nov"\ "des"\ ""] ::msgcat::mcset fo MONTHS_FULL [list \ "januar"\ "februar"\ "mars"\ "apr\u00edl"\ "mai"\ "juni"\ "juli"\ "august"\ "september"\ "oktober"\ "november"\ "desember"\ ""] } tcl8.6.5/library/msgs/en_au.msg0000644000175000017500000000045411555560473016007 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_AU DATE_FORMAT "%e/%m/%Y" ::msgcat::mcset en_AU TIME_FORMAT "%H:%M:%S" ::msgcat::mcset en_AU TIME_FORMAT_12 "%I:%M:%S %P %z" ::msgcat::mcset en_AU DATE_TIME_FORMAT "%e/%m/%Y %H:%M:%S %z" } tcl8.6.5/library/msgs/sq.msg0000644000175000017500000000236311555560473015344 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset sq DAYS_OF_WEEK_ABBREV [list \ "Die"\ "H\u00ebn"\ "Mar"\ "M\u00ebr"\ "Enj"\ "Pre"\ "Sht"] ::msgcat::mcset sq DAYS_OF_WEEK_FULL [list \ "e diel"\ "e h\u00ebn\u00eb"\ "e mart\u00eb"\ "e m\u00ebrkur\u00eb"\ "e enjte"\ "e premte"\ "e shtun\u00eb"] ::msgcat::mcset sq MONTHS_ABBREV [list \ "Jan"\ "Shk"\ "Mar"\ "Pri"\ "Maj"\ "Qer"\ "Kor"\ "Gsh"\ "Sht"\ "Tet"\ "N\u00ebn"\ "Dhj"\ ""] ::msgcat::mcset sq MONTHS_FULL [list \ "janar"\ "shkurt"\ "mars"\ "prill"\ "maj"\ "qershor"\ "korrik"\ "gusht"\ "shtator"\ "tetor"\ "n\u00ebntor"\ "dhjetor"\ ""] ::msgcat::mcset sq BCE "p.e.r." ::msgcat::mcset sq CE "n.e.r." ::msgcat::mcset sq AM "PD" ::msgcat::mcset sq PM "MD" ::msgcat::mcset sq DATE_FORMAT "%Y-%m-%d" ::msgcat::mcset sq TIME_FORMAT_12 "%l:%M:%S.%P" ::msgcat::mcset sq DATE_TIME_FORMAT "%Y-%m-%d %l:%M:%S.%P %z" } tcl8.6.5/library/msgs/fr_ca.msg0000644000175000017500000000042711555560473015772 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset fr_CA DATE_FORMAT "%Y-%m-%d" ::msgcat::mcset fr_CA TIME_FORMAT "%T" ::msgcat::mcset fr_CA TIME_FORMAT_12 "%T" ::msgcat::mcset fr_CA DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/es_pr.msg0000644000175000017500000000037311555560473016030 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_PR DATE_FORMAT "%m-%d-%Y" ::msgcat::mcset es_PR TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_PR DATE_TIME_FORMAT "%m-%d-%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/nl.msg0000644000175000017500000000206711555560473015333 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset nl DAYS_OF_WEEK_ABBREV [list \ "zo"\ "ma"\ "di"\ "wo"\ "do"\ "vr"\ "za"] ::msgcat::mcset nl DAYS_OF_WEEK_FULL [list \ "zondag"\ "maandag"\ "dinsdag"\ "woensdag"\ "donderdag"\ "vrijdag"\ "zaterdag"] ::msgcat::mcset nl MONTHS_ABBREV [list \ "jan"\ "feb"\ "mrt"\ "apr"\ "mei"\ "jun"\ "jul"\ "aug"\ "sep"\ "okt"\ "nov"\ "dec"\ ""] ::msgcat::mcset nl MONTHS_FULL [list \ "januari"\ "februari"\ "maart"\ "april"\ "mei"\ "juni"\ "juli"\ "augustus"\ "september"\ "oktober"\ "november"\ "december"\ ""] ::msgcat::mcset nl DATE_FORMAT "%e %B %Y" ::msgcat::mcset nl TIME_FORMAT "%k:%M:%S" ::msgcat::mcset nl DATE_TIME_FORMAT "%e %B %Y %k:%M:%S %z" } tcl8.6.5/library/msgs/ko_kr.msg0000644000175000017500000000053211555560473016022 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ko_KR BCE "\uae30\uc6d0\uc804" ::msgcat::mcset ko_KR CE "\uc11c\uae30" ::msgcat::mcset ko_KR DATE_FORMAT "%Y.%m.%d" ::msgcat::mcset ko_KR TIME_FORMAT_12 "%P %l:%M:%S" ::msgcat::mcset ko_KR DATE_TIME_FORMAT "%Y.%m.%d %P %l:%M:%S %z" } tcl8.6.5/library/msgs/fo_fo.msg0000644000175000017500000000042711555560473016010 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset fo_FO DATE_FORMAT "%d/%m-%Y" ::msgcat::mcset fo_FO TIME_FORMAT "%T" ::msgcat::mcset fo_FO TIME_FORMAT_12 "%T" ::msgcat::mcset fo_FO DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/he.msg0000644000175000017500000000362212663653207015313 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset he DAYS_OF_WEEK_ABBREV [list \ "\u05d0"\ "\u05d1"\ "\u05d2"\ "\u05d3"\ "\u05d4"\ "\u05d5"\ "\u05e9"] ::msgcat::mcset he DAYS_OF_WEEK_FULL [list \ "\u05d9\u05d5\u05dd \u05e8\u05d0\u05e9\u05d5\u05df"\ "\u05d9\u05d5\u05dd \u05e9\u05e0\u05d9"\ "\u05d9\u05d5\u05dd \u05e9\u05dc\u05d9\u05e9\u05d9"\ "\u05d9\u05d5\u05dd \u05e8\u05d1\u05d9\u05e2\u05d9"\ "\u05d9\u05d5\u05dd \u05d7\u05de\u05d9\u05e9\u05d9"\ "\u05d9\u05d5\u05dd \u05e9\u05d9\u05e9\u05d9"\ "\u05e9\u05d1\u05ea"] ::msgcat::mcset he MONTHS_ABBREV [list \ "\u05d9\u05e0\u05d5"\ "\u05e4\u05d1\u05e8"\ "\u05de\u05e8\u05e5"\ "\u05d0\u05e4\u05e8"\ "\u05de\u05d0\u05d9"\ "\u05d9\u05d5\u05e0"\ "\u05d9\u05d5\u05dc"\ "\u05d0\u05d5\u05d2"\ "\u05e1\u05e4\u05d8"\ "\u05d0\u05d5\u05e7"\ "\u05e0\u05d5\u05d1"\ "\u05d3\u05e6\u05de"\ ""] ::msgcat::mcset he MONTHS_FULL [list \ "\u05d9\u05e0\u05d5\u05d0\u05e8"\ "\u05e4\u05d1\u05e8\u05d5\u05d0\u05e8"\ "\u05de\u05e8\u05e5"\ "\u05d0\u05e4\u05e8\u05d9\u05dc"\ "\u05de\u05d0\u05d9"\ "\u05d9\u05d5\u05e0\u05d9"\ "\u05d9\u05d5\u05dc\u05d9"\ "\u05d0\u05d5\u05d2\u05d5\u05e1\u05d8"\ "\u05e1\u05e4\u05d8\u05de\u05d1\u05e8"\ "\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8"\ "\u05e0\u05d5\u05d1\u05de\u05d1\u05e8"\ "\u05d3\u05e6\u05de\u05d1\u05e8"\ ""] ::msgcat::mcset he BCE "\u05dc\u05e1\u05d4\u0022\u05e0" ::msgcat::mcset he CE "\u05dc\u05e4\u05e1\u05d4\u0022\u05e0" ::msgcat::mcset he DATE_FORMAT "%d/%m/%Y" ::msgcat::mcset he TIME_FORMAT "%H:%M:%S" ::msgcat::mcset he DATE_TIME_FORMAT "%d/%m/%Y %H:%M:%S %z" } tcl8.6.5/library/msgs/es_do.msg0000644000175000017500000000037311555560473016011 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_DO DATE_FORMAT "%m/%d/%Y" ::msgcat::mcset es_DO TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_DO DATE_TIME_FORMAT "%m/%d/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/hi_in.msg0000644000175000017500000000037311555560473016006 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset hi_IN DATE_FORMAT "%d %M %Y" ::msgcat::mcset hi_IN TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset hi_IN DATE_TIME_FORMAT "%d %M %Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/zh_cn.msg0000644000175000017500000000047011555560473016017 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset zh_CN DATE_FORMAT "%Y-%m-%e" ::msgcat::mcset zh_CN TIME_FORMAT "%k:%M:%S" ::msgcat::mcset zh_CN TIME_FORMAT_12 "%P%I\u65f6%M\u5206%S\u79d2" ::msgcat::mcset zh_CN DATE_TIME_FORMAT "%Y-%m-%e %k:%M:%S %z" } tcl8.6.5/library/msgs/eo.msg0000644000175000017500000000231711555560473015323 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset eo DAYS_OF_WEEK_ABBREV [list \ "di"\ "lu"\ "ma"\ "me"\ "\u0135a"\ "ve"\ "sa"] ::msgcat::mcset eo DAYS_OF_WEEK_FULL [list \ "diman\u0109o"\ "lundo"\ "mardo"\ "merkredo"\ "\u0135a\u016ddo"\ "vendredo"\ "sabato"] ::msgcat::mcset eo MONTHS_ABBREV [list \ "jan"\ "feb"\ "mar"\ "apr"\ "maj"\ "jun"\ "jul"\ "a\u016dg"\ "sep"\ "okt"\ "nov"\ "dec"\ ""] ::msgcat::mcset eo MONTHS_FULL [list \ "januaro"\ "februaro"\ "marto"\ "aprilo"\ "majo"\ "junio"\ "julio"\ "a\u016dgusto"\ "septembro"\ "oktobro"\ "novembro"\ "decembro"\ ""] ::msgcat::mcset eo BCE "aK" ::msgcat::mcset eo CE "pK" ::msgcat::mcset eo AM "atm" ::msgcat::mcset eo PM "ptm" ::msgcat::mcset eo DATE_FORMAT "%Y-%b-%d" ::msgcat::mcset eo TIME_FORMAT "%H:%M:%S" ::msgcat::mcset eo DATE_TIME_FORMAT "%Y-%b-%d %H:%M:%S %z" } tcl8.6.5/library/msgs/es_gt.msg0000644000175000017500000000037311555560473016021 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_GT DATE_FORMAT "%e/%m/%Y" ::msgcat::mcset es_GT TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_GT DATE_TIME_FORMAT "%e/%m/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/de_at.msg0000644000175000017500000000145411555560473015775 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset de_AT MONTHS_ABBREV [list \ "J\u00e4n"\ "Feb"\ "M\u00e4r"\ "Apr"\ "Mai"\ "Jun"\ "Jul"\ "Aug"\ "Sep"\ "Okt"\ "Nov"\ "Dez"\ ""] ::msgcat::mcset de_AT MONTHS_FULL [list \ "J\u00e4nner"\ "Februar"\ "M\u00e4rz"\ "April"\ "Mai"\ "Juni"\ "Juli"\ "August"\ "September"\ "Oktober"\ "November"\ "Dezember"\ ""] ::msgcat::mcset de_AT DATE_FORMAT "%Y-%m-%d" ::msgcat::mcset de_AT TIME_FORMAT "%T" ::msgcat::mcset de_AT TIME_FORMAT_12 "%T" ::msgcat::mcset de_AT DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/en_ph.msg0000644000175000017500000000050111555560473016002 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset en_PH AM "AM" ::msgcat::mcset en_PH PM "PM" ::msgcat::mcset en_PH DATE_FORMAT "%B %e, %Y" ::msgcat::mcset en_PH TIME_FORMAT_12 "%l:%M:%S %P" ::msgcat::mcset en_PH DATE_TIME_FORMAT "%B %e, %Y %l:%M:%S %P %z" } tcl8.6.5/library/msgs/sk.msg0000644000175000017500000000226311555560473015335 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset sk DAYS_OF_WEEK_ABBREV [list \ "Ne"\ "Po"\ "Ut"\ "St"\ "\u0160t"\ "Pa"\ "So"] ::msgcat::mcset sk DAYS_OF_WEEK_FULL [list \ "Nede\u013ee"\ "Pondelok"\ "Utorok"\ "Streda"\ "\u0160tvrtok"\ "Piatok"\ "Sobota"] ::msgcat::mcset sk MONTHS_ABBREV [list \ "jan"\ "feb"\ "mar"\ "apr"\ "m\u00e1j"\ "j\u00fan"\ "j\u00fal"\ "aug"\ "sep"\ "okt"\ "nov"\ "dec"\ ""] ::msgcat::mcset sk MONTHS_FULL [list \ "janu\u00e1r"\ "febru\u00e1r"\ "marec"\ "apr\u00edl"\ "m\u00e1j"\ "j\u00fan"\ "j\u00fal"\ "august"\ "september"\ "okt\u00f3ber"\ "november"\ "december"\ ""] ::msgcat::mcset sk BCE "pred n.l." ::msgcat::mcset sk CE "n.l." ::msgcat::mcset sk DATE_FORMAT "%e.%m.%Y" ::msgcat::mcset sk TIME_FORMAT "%k:%M:%S" ::msgcat::mcset sk DATE_TIME_FORMAT "%e.%m.%Y %k:%M:%S %z" } tcl8.6.5/library/msgs/gv.msg0000644000175000017500000000201511555560473015327 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset gv DAYS_OF_WEEK_ABBREV [list \ "Jed"\ "Jel"\ "Jem"\ "Jerc"\ "Jerd"\ "Jeh"\ "Jes"] ::msgcat::mcset gv DAYS_OF_WEEK_FULL [list \ "Jedoonee"\ "Jelhein"\ "Jemayrt"\ "Jercean"\ "Jerdein"\ "Jeheiney"\ "Jesarn"] ::msgcat::mcset gv MONTHS_ABBREV [list \ "J-guer"\ "T-arree"\ "Mayrnt"\ "Avrril"\ "Boaldyn"\ "M-souree"\ "J-souree"\ "Luanistyn"\ "M-fouyir"\ "J-fouyir"\ "M.Houney"\ "M.Nollick"\ ""] ::msgcat::mcset gv MONTHS_FULL [list \ "Jerrey-geuree"\ "Toshiaght-arree"\ "Mayrnt"\ "Averil"\ "Boaldyn"\ "Mean-souree"\ "Jerrey-souree"\ "Luanistyn"\ "Mean-fouyir"\ "Jerrey-fouyir"\ "Mee Houney"\ "Mee ny Nollick"\ ""] } tcl8.6.5/library/msgs/vi.msg0000644000175000017500000000261511555560473015337 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset vi DAYS_OF_WEEK_ABBREV [list \ "Th 2"\ "Th 3"\ "Th 4"\ "Th 5"\ "Th 6"\ "Th 7"\ "CN"] ::msgcat::mcset vi DAYS_OF_WEEK_FULL [list \ "Th\u01b0\u0301 hai"\ "Th\u01b0\u0301 ba"\ "Th\u01b0\u0301 t\u01b0"\ "Th\u01b0\u0301 n\u0103m"\ "Th\u01b0\u0301 s\u00e1u"\ "Th\u01b0\u0301 ba\u0309y"\ "Chu\u0309 nh\u00e2\u0323t"] ::msgcat::mcset vi MONTHS_ABBREV [list \ "Thg 1"\ "Thg 2"\ "Thg 3"\ "Thg 4"\ "Thg 5"\ "Thg 6"\ "Thg 7"\ "Thg 8"\ "Thg 9"\ "Thg 10"\ "Thg 11"\ "Thg 12"\ ""] ::msgcat::mcset vi MONTHS_FULL [list \ "Th\u00e1ng m\u00f4\u0323t"\ "Th\u00e1ng hai"\ "Th\u00e1ng ba"\ "Th\u00e1ng t\u01b0"\ "Th\u00e1ng n\u0103m"\ "Th\u00e1ng s\u00e1u"\ "Th\u00e1ng ba\u0309y"\ "Th\u00e1ng t\u00e1m"\ "Th\u00e1ng ch\u00edn"\ "Th\u00e1ng m\u01b0\u01a1\u0300i"\ "Th\u00e1ng m\u01b0\u01a1\u0300i m\u00f4\u0323t"\ "Th\u00e1ng m\u01b0\u01a1\u0300i hai"\ ""] ::msgcat::mcset vi DATE_FORMAT "%d %b %Y" ::msgcat::mcset vi TIME_FORMAT "%H:%M:%S" ::msgcat::mcset vi DATE_TIME_FORMAT "%d %b %Y %H:%M:%S %z" } tcl8.6.5/library/msgs/ar_jo.msg0000644000175000017500000000342411555560473016012 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ar_JO DAYS_OF_WEEK_ABBREV [list \ "\u0627\u0644\u0623\u062d\u062f"\ "\u0627\u0644\u0627\u062b\u0646\u064a\u0646"\ "\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621"\ "\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621"\ "\u0627\u0644\u062e\u0645\u064a\u0633"\ "\u0627\u0644\u062c\u0645\u0639\u0629"\ "\u0627\u0644\u0633\u0628\u062a"] ::msgcat::mcset ar_JO MONTHS_ABBREV [list \ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0634\u0628\u0627\u0637"\ "\u0622\u0630\u0627\u0631"\ "\u0646\u064a\u0633\u0627\u0646"\ "\u0646\u0648\u0627\u0631"\ "\u062d\u0632\u064a\u0631\u0627\u0646"\ "\u062a\u0645\u0648\u0632"\ "\u0622\u0628"\ "\u0623\u064a\u0644\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\ ""] ::msgcat::mcset ar_JO MONTHS_FULL [list \ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0634\u0628\u0627\u0637"\ "\u0622\u0630\u0627\u0631"\ "\u0646\u064a\u0633\u0627\u0646"\ "\u0646\u0648\u0627\u0631"\ "\u062d\u0632\u064a\u0631\u0627\u0646"\ "\u062a\u0645\u0648\u0632"\ "\u0622\u0628"\ "\u0623\u064a\u0644\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u0623\u0648\u0644"\ "\u062a\u0634\u0631\u064a\u0646 \u0627\u0644\u062b\u0627\u0646\u064a"\ "\u0643\u0627\u0646\u0648\u0646 \u0627\u0644\u0623\u0648\u0644"\ ""] } tcl8.6.5/library/msgs/kl.msg0000644000175000017500000000172211555560473015325 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset kl DAYS_OF_WEEK_ABBREV [list \ "sab"\ "ata"\ "mar"\ "pin"\ "sis"\ "tal"\ "arf"] ::msgcat::mcset kl DAYS_OF_WEEK_FULL [list \ "sabaat"\ "ataasinngorneq"\ "marlunngorneq"\ "pingasunngorneq"\ "sisamanngorneq"\ "tallimanngorneq"\ "arfininngorneq"] ::msgcat::mcset kl MONTHS_ABBREV [list \ "jan"\ "feb"\ "mar"\ "apr"\ "maj"\ "jun"\ "jul"\ "aug"\ "sep"\ "okt"\ "nov"\ "dec"\ ""] ::msgcat::mcset kl MONTHS_FULL [list \ "januari"\ "februari"\ "martsi"\ "aprili"\ "maji"\ "juni"\ "juli"\ "augustusi"\ "septemberi"\ "oktoberi"\ "novemberi"\ "decemberi"\ ""] } tcl8.6.5/library/msgs/ga.msg0000644000175000017500000000216511555560473015310 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ga DAYS_OF_WEEK_ABBREV [list \ "Domh"\ "Luan"\ "M\u00e1irt"\ "C\u00e9ad"\ "D\u00e9ar"\ "Aoine"\ "Sath"] ::msgcat::mcset ga DAYS_OF_WEEK_FULL [list \ "D\u00e9 Domhnaigh"\ "D\u00e9 Luain"\ "D\u00e9 M\u00e1irt"\ "D\u00e9 C\u00e9adaoin"\ "D\u00e9ardaoin"\ "D\u00e9 hAoine"\ "D\u00e9 Sathairn"] ::msgcat::mcset ga MONTHS_ABBREV [list \ "Ean"\ "Feabh"\ "M\u00e1rta"\ "Aib"\ "Beal"\ "Meith"\ "I\u00fail"\ "L\u00fan"\ "MF\u00f3mh"\ "DF\u00f3mh"\ "Samh"\ "Noll"\ ""] ::msgcat::mcset ga MONTHS_FULL [list \ "Ean\u00e1ir"\ "Feabhra"\ "M\u00e1rta"\ "Aibre\u00e1n"\ "M\u00ed na Bealtaine"\ "Meith"\ "I\u00fail"\ "L\u00fanasa"\ "Me\u00e1n F\u00f3mhair"\ "Deireadh F\u00f3mhair"\ "M\u00ed na Samhna"\ "M\u00ed na Nollag"\ ""] } tcl8.6.5/library/msgs/es_mx.msg0000644000175000017500000000037311555560473016033 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_MX DATE_FORMAT "%e/%m/%Y" ::msgcat::mcset es_MX TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_MX DATE_TIME_FORMAT "%e/%m/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/eu_es.msg0000644000175000017500000000043711555560473016021 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset eu_ES DATE_FORMAT "%a, %Yeko %bren %da" ::msgcat::mcset eu_ES TIME_FORMAT "%T" ::msgcat::mcset eu_ES TIME_FORMAT_12 "%T" ::msgcat::mcset eu_ES DATE_TIME_FORMAT "%y-%m-%d %T %z" } tcl8.6.5/library/msgs/af_za.msg0000644000175000017500000000037311555560473016000 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset af_ZA DATE_FORMAT "%d %B %Y" ::msgcat::mcset af_ZA TIME_FORMAT_12 "%l:%M:%S %P" ::msgcat::mcset af_ZA DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z" } tcl8.6.5/library/msgs/uk.msg0000644000175000017500000000410112663660066015330 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset uk DAYS_OF_WEEK_ABBREV [list \ "\u043d\u0434"\ "\u043f\u043d"\ "\u0432\u0442"\ "\u0441\u0440"\ "\u0447\u0442"\ "\u043f\u0442"\ "\u0441\u0431"] ::msgcat::mcset uk DAYS_OF_WEEK_FULL [list \ "\u043d\u0435\u0434\u0456\u043b\u044f"\ "\u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043e\u043a"\ "\u0432\u0456\u0432\u0442\u043e\u0440\u043e\u043a"\ "\u0441\u0435\u0440\u0435\u0434\u0430"\ "\u0447\u0435\u0442\u0432\u0435\u0440"\ "\u043f'\u044f\u0442\u043d\u0438\u0446\u044f"\ "\u0441\u0443\u0431\u043e\u0442\u0430"] ::msgcat::mcset uk MONTHS_ABBREV [list \ "\u0441\u0456\u0447"\ "\u043b\u044e\u0442"\ "\u0431\u0435\u0440"\ "\u043a\u0432\u0456\u0442"\ "\u0442\u0440\u0430\u0432"\ "\u0447\u0435\u0440\u0432"\ "\u043b\u0438\u043f"\ "\u0441\u0435\u0440\u043f"\ "\u0432\u0435\u0440"\ "\u0436\u043e\u0432\u0442"\ "\u043b\u0438\u0441\u0442"\ "\u0433\u0440\u0443\u0434"\ ""] ::msgcat::mcset uk MONTHS_FULL [list \ "\u0441\u0456\u0447\u043d\u044f"\ "\u043b\u044e\u0442\u043e\u0433\u043e"\ "\u0431\u0435\u0440\u0435\u0437\u043d\u044f"\ "\u043a\u0432\u0456\u0442\u043d\u044f"\ "\u0442\u0440\u0430\u0432\u043d\u044f"\ "\u0447\u0435\u0440\u0432\u043d\u044f"\ "\u043b\u0438\u043f\u043d\u044f"\ "\u0441\u0435\u0440\u043f\u043d\u044f"\ "\u0432\u0435\u0440\u0435\u0441\u043d\u044f"\ "\u0436\u043e\u0432\u0442\u043d\u044f"\ "\u043b\u0438\u0441\u0442\u043e\u043f\u0430\u0434\u0430"\ "\u0433\u0440\u0443\u0434\u043d\u044f"\ ""] ::msgcat::mcset uk BCE "\u0434\u043e \u043d.\u0435." ::msgcat::mcset uk CE "\u043f\u0456\u0441\u043b\u044f \u043d.\u0435." ::msgcat::mcset uk DATE_FORMAT "%e/%m/%Y" ::msgcat::mcset uk TIME_FORMAT "%k:%M:%S" ::msgcat::mcset uk DATE_TIME_FORMAT "%e/%m/%Y %k:%M:%S %z" } tcl8.6.5/library/msgs/gl_es.msg0000644000175000017500000000037311555560473016011 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset gl_ES DATE_FORMAT "%d %B %Y" ::msgcat::mcset gl_ES TIME_FORMAT_12 "%l:%M:%S %P" ::msgcat::mcset gl_ES DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z" } tcl8.6.5/library/msgs/es_uy.msg0000644000175000017500000000037311555560473016044 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset es_UY DATE_FORMAT "%d/%m/%Y" ::msgcat::mcset es_UY TIME_FORMAT_12 "%I:%M:%S %P" ::msgcat::mcset es_UY DATE_TIME_FORMAT "%d/%m/%Y %I:%M:%S %P %z" } tcl8.6.5/library/msgs/ga_ie.msg0000644000175000017500000000042711555560473015764 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset ga_IE DATE_FORMAT "%d.%m.%y" ::msgcat::mcset ga_IE TIME_FORMAT "%T" ::msgcat::mcset ga_IE TIME_FORMAT_12 "%T" ::msgcat::mcset ga_IE DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/nb.msg0000644000175000017500000000220511555560473015313 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset nb DAYS_OF_WEEK_ABBREV [list \ "s\u00f8"\ "ma"\ "ti"\ "on"\ "to"\ "fr"\ "l\u00f8"] ::msgcat::mcset nb DAYS_OF_WEEK_FULL [list \ "s\u00f8ndag"\ "mandag"\ "tirsdag"\ "onsdag"\ "torsdag"\ "fredag"\ "l\u00f8rdag"] ::msgcat::mcset nb MONTHS_ABBREV [list \ "jan"\ "feb"\ "mar"\ "apr"\ "mai"\ "jun"\ "jul"\ "aug"\ "sep"\ "okt"\ "nov"\ "des"\ ""] ::msgcat::mcset nb MONTHS_FULL [list \ "januar"\ "februar"\ "mars"\ "april"\ "mai"\ "juni"\ "juli"\ "august"\ "september"\ "oktober"\ "november"\ "desember"\ ""] ::msgcat::mcset nb BCE "f.Kr." ::msgcat::mcset nb CE "e.Kr." ::msgcat::mcset nb DATE_FORMAT "%e. %B %Y" ::msgcat::mcset nb TIME_FORMAT "%H:%M:%S" ::msgcat::mcset nb DATE_TIME_FORMAT "%e. %B %Y %H:%M:%S %z" } tcl8.6.5/library/msgs/pt_br.msg0000644000175000017500000000042711555560473016026 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset pt_BR DATE_FORMAT "%d-%m-%Y" ::msgcat::mcset pt_BR TIME_FORMAT "%T" ::msgcat::mcset pt_BR TIME_FORMAT_12 "%T" ::msgcat::mcset pt_BR DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/mr.msg0000644000175000017500000000341711555560473015340 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset mr DAYS_OF_WEEK_FULL [list \ "\u0930\u0935\u093f\u0935\u093e\u0930"\ "\u0938\u094b\u092e\u0935\u093e\u0930"\ "\u092e\u0902\u0917\u0933\u0935\u093e\u0930"\ "\u092e\u0902\u0917\u0933\u0935\u093e\u0930"\ "\u0917\u0941\u0930\u0941\u0935\u093e\u0930"\ "\u0936\u0941\u0915\u094d\u0930\u0935\u093e\u0930"\ "\u0936\u0928\u093f\u0935\u093e\u0930"] ::msgcat::mcset mr MONTHS_ABBREV [list \ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940"\ "\u092b\u0947\u092c\u0943\u0935\u093e\u0930\u0940"\ "\u092e\u093e\u0930\u094d\u091a"\ "\u090f\u092a\u094d\u0930\u093f\u0932"\ "\u092e\u0947"\ "\u091c\u0942\u0928"\ "\u091c\u0941\u0932\u0948"\ "\u0913\u0917\u0938\u094d\u091f"\ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930"\ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930"\ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930"\ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"] ::msgcat::mcset mr MONTHS_FULL [list \ "\u091c\u093e\u0928\u0947\u0935\u093e\u0930\u0940"\ "\u092b\u0947\u092c\u0943\u0935\u093e\u0930\u0940"\ "\u092e\u093e\u0930\u094d\u091a"\ "\u090f\u092a\u094d\u0930\u093f\u0932"\ "\u092e\u0947"\ "\u091c\u0942\u0928"\ "\u091c\u0941\u0932\u0948"\ "\u0913\u0917\u0938\u094d\u091f"\ "\u0938\u0947\u092a\u094d\u091f\u0947\u0902\u092c\u0930"\ "\u0913\u0915\u094d\u091f\u094b\u092c\u0930"\ "\u0928\u094b\u0935\u094d\u0939\u0947\u0902\u092c\u0930"\ "\u0921\u093f\u0938\u0947\u0902\u092c\u0930"] ::msgcat::mcset mr AM "BC" ::msgcat::mcset mr PM "AD" } tcl8.6.5/library/msgs/de_be.msg0000644000175000017500000000230711555560473015755 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset de_BE DAYS_OF_WEEK_ABBREV [list \ "Son"\ "Mon"\ "Die"\ "Mit"\ "Don"\ "Fre"\ "Sam"] ::msgcat::mcset de_BE DAYS_OF_WEEK_FULL [list \ "Sonntag"\ "Montag"\ "Dienstag"\ "Mittwoch"\ "Donnerstag"\ "Freitag"\ "Samstag"] ::msgcat::mcset de_BE MONTHS_ABBREV [list \ "Jan"\ "Feb"\ "M\u00e4r"\ "Apr"\ "Mai"\ "Jun"\ "Jul"\ "Aug"\ "Sep"\ "Okt"\ "Nov"\ "Dez"\ ""] ::msgcat::mcset de_BE MONTHS_FULL [list \ "Januar"\ "Februar"\ "M\u00e4rz"\ "April"\ "Mai"\ "Juni"\ "Juli"\ "August"\ "September"\ "Oktober"\ "November"\ "Dezember"\ ""] ::msgcat::mcset de_BE AM "vorm" ::msgcat::mcset de_BE PM "nachm" ::msgcat::mcset de_BE DATE_FORMAT "%Y-%m-%d" ::msgcat::mcset de_BE TIME_FORMAT "%T" ::msgcat::mcset de_BE TIME_FORMAT_12 "%T" ::msgcat::mcset de_BE DATE_TIME_FORMAT "%a %d %b %Y %T %z" } tcl8.6.5/library/msgs/kw_gb.msg0000644000175000017500000000037311555560473016011 0ustar sergeisergei# created by tools/loadICU.tcl -- do not edit namespace eval ::tcl::clock { ::msgcat::mcset kw_GB DATE_FORMAT "%d %B %Y" ::msgcat::mcset kw_GB TIME_FORMAT_12 "%l:%M:%S %P" ::msgcat::mcset kw_GB DATE_TIME_FORMAT "%d %B %Y %l:%M:%S %P %z" } tcl8.6.5/library/license.terms0000644000175000017500000000431712663660066015737 0ustar sergeisergeiThis software is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. tcl8.6.5/library/msgcat/0000755000175000017500000000000012665173607014514 5ustar sergeisergeitcl8.6.5/library/msgcat/pkgIndex.tcl0000644000175000017500000000020612663660066016765 0ustar sergeisergeiif {![package vsatisfies [package provide Tcl] 8.5]} {return} package ifneeded msgcat 1.6.0 [list source [file join $dir msgcat.tcl]] tcl8.6.5/library/msgcat/msgcat.tcl0000644000175000017500000010221612663660066016476 0ustar sergeisergei# msgcat.tcl -- # # This file defines various procedures which implement a # message catalog facility for Tcl programs. It should be # loaded with the command "package require msgcat". # # Copyright (c) 2010-2015 by Harald Oehlmann. # Copyright (c) 1998-2000 by Ajuba Solutions. # Copyright (c) 1998 by Mark Harrison. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. package require Tcl 8.5 # When the version number changes, be sure to update the pkgIndex.tcl file, # and the installation directory in the Makefiles. package provide msgcat 1.6.0 namespace eval msgcat { namespace export mc mcexists mcload mclocale mcmax mcmset mcpreferences mcset\ mcunknown mcflset mcflmset mcloadedlocales mcforgetpackage\ mcpackageconfig mcpackagelocale # Records the list of locales to search variable Loclist {} # List of currently loaded locales variable LoadedLocales {} # Records the locale of the currently sourced message catalogue file variable FileLocale # Configuration values per Package (e.g. client namespace). # The dict key is of the form "